summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CREDITS23
-rw-r--r--Documentation/00-INDEX2
-rw-r--r--Documentation/Changes2
-rw-r--r--Documentation/DocBook/Makefile4
-rw-r--r--Documentation/DocBook/kernel-api.tmpl3
-rw-r--r--Documentation/DocBook/libata.tmpl156
-rw-r--r--Documentation/DocBook/scsidrivers.tmpl193
-rw-r--r--Documentation/DocBook/stylesheet.xsl1
-rw-r--r--Documentation/IPMI.txt146
-rw-r--r--Documentation/SubmittingPatches25
-rw-r--r--Documentation/basic_profiling.txt10
-rw-r--r--Documentation/cdrom/sbpcd16
-rw-r--r--Documentation/cpu-freq/cpufreq-stats.txt128
-rw-r--r--Documentation/cpu-freq/governors.txt14
-rw-r--r--Documentation/cpusets.txt19
-rw-r--r--Documentation/devices.txt1
-rw-r--r--Documentation/dontdiff1
-rw-r--r--Documentation/driver-model/device.txt8
-rw-r--r--Documentation/driver-model/driver.txt51
-rw-r--r--Documentation/dvb/README.dvb-usb (renamed from Documentation/dvb/README.dibusb)195
-rw-r--r--Documentation/dvb/README.flexcop205
-rw-r--r--Documentation/dvb/bt8xx.txt76
-rw-r--r--Documentation/dvb/ci.txt219
-rw-r--r--Documentation/dvb/get_dvb_firmware4
-rw-r--r--Documentation/fb/intelfb.txt135
-rw-r--r--Documentation/feature-removal-schedule.txt56
-rw-r--r--Documentation/filesystems/ext2.txt2
-rw-r--r--Documentation/filesystems/isofs.txt6
-rw-r--r--Documentation/filesystems/sysfs-pci.txt6
-rw-r--r--Documentation/filesystems/sysfs.txt2
-rw-r--r--Documentation/filesystems/tmpfs.txt6
-rw-r--r--Documentation/filesystems/xip.txt67
-rw-r--r--Documentation/i2c/busses/i2c-sis69x2
-rw-r--r--Documentation/i2c/chips/adm1021111
-rw-r--r--Documentation/i2c/chips/adm102551
-rw-r--r--Documentation/i2c/chips/adm102693
-rw-r--r--Documentation/i2c/chips/adm103135
-rw-r--r--Documentation/i2c/chips/adm9240177
-rw-r--r--Documentation/i2c/chips/asb10072
-rw-r--r--Documentation/i2c/chips/ds1621108
-rw-r--r--Documentation/i2c/chips/eeprom96
-rw-r--r--Documentation/i2c/chips/fscher169
-rw-r--r--Documentation/i2c/chips/gl518sm74
-rw-r--r--Documentation/i2c/chips/it8796
-rw-r--r--Documentation/i2c/chips/lm6357
-rw-r--r--Documentation/i2c/chips/lm7565
-rw-r--r--Documentation/i2c/chips/lm7722
-rw-r--r--Documentation/i2c/chips/lm7882
-rw-r--r--Documentation/i2c/chips/lm8056
-rw-r--r--Documentation/i2c/chips/lm8376
-rw-r--r--Documentation/i2c/chips/lm85221
-rw-r--r--Documentation/i2c/chips/lm8773
-rw-r--r--Documentation/i2c/chips/lm90121
-rw-r--r--Documentation/i2c/chips/lm9237
-rw-r--r--Documentation/i2c/chips/max161929
-rw-r--r--Documentation/i2c/chips/max687554
-rw-r--r--Documentation/i2c/chips/pc87360189
-rw-r--r--Documentation/i2c/chips/pca953947
-rw-r--r--Documentation/i2c/chips/pcf857469
-rw-r--r--Documentation/i2c/chips/pcf859190
-rw-r--r--Documentation/i2c/chips/sis5595106
-rw-r--r--Documentation/i2c/chips/smsc47b397 (renamed from Documentation/i2c/chips/smsc47b397.txt)46
-rw-r--r--Documentation/i2c/chips/smsc47m152
-rw-r--r--Documentation/i2c/chips/via686a65
-rw-r--r--Documentation/i2c/chips/w83627hf66
-rw-r--r--Documentation/i2c/chips/w83781d402
-rw-r--r--Documentation/i2c/chips/w83l785ts39
-rw-r--r--Documentation/i2c/porting-clients2
-rw-r--r--Documentation/i2c/userspace-tools39
-rw-r--r--Documentation/i2c/writing-clients62
-rw-r--r--Documentation/kdump/gdbmacros.txt179
-rw-r--r--Documentation/kdump/kdump.txt141
-rw-r--r--Documentation/kernel-parameters.txt11
-rw-r--r--Documentation/keys.txt319
-rw-r--r--Documentation/networking/00-INDEX4
-rw-r--r--Documentation/networking/generic-hdlc.txt51
-rw-r--r--Documentation/networking/ip-sysctl.txt56
-rw-r--r--Documentation/networking/multicast.txt1
-rw-r--r--Documentation/networking/net-modules.txt3
-rw-r--r--Documentation/networking/tcp.txt69
-rw-r--r--Documentation/networking/vortex.txt2
-rw-r--r--Documentation/networking/wanpipe.txt622
-rw-r--r--Documentation/power/devices.txt21
-rw-r--r--Documentation/power/kernel_threads.txt3
-rw-r--r--Documentation/power/pci.txt38
-rw-r--r--Documentation/power/swsusp.txt84
-rw-r--r--Documentation/power/video.txt3
-rw-r--r--Documentation/power/video_extension.txt19
-rw-r--r--Documentation/powerpc/hvcs.txt4
-rw-r--r--Documentation/s390/CommonIO16
-rw-r--r--Documentation/s390/s390dbf.txt79
-rw-r--r--Documentation/scsi/ChangeLog.megaraid66
-rw-r--r--Documentation/scsi/scsi-changer.txt180
-rw-r--r--Documentation/scsi/scsi_mid_low_api.txt12
-rw-r--r--Documentation/sgi-ioc4.txt45
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt127
-rw-r--r--Documentation/sound/alsa/CMIPCI.txt41
-rw-r--r--Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl6
-rw-r--r--Documentation/sound/alsa/emu10k1-jack.txt74
-rw-r--r--Documentation/sound/alsa/hdspm.txt362
-rw-r--r--Documentation/sysctl/kernel.txt20
-rw-r--r--Documentation/sysrq.txt5
-rw-r--r--Documentation/tty.txt2
-rw-r--r--Documentation/video4linux/CARDLIST.bttv14
-rw-r--r--Documentation/video4linux/CARDLIST.cx8829
-rw-r--r--Documentation/video4linux/CARDLIST.saa713429
-rw-r--r--Documentation/video4linux/CARDLIST.tuner15
-rw-r--r--Documentation/video4linux/hauppauge-wintv-cx88-ir.txt54
-rw-r--r--Documentation/video4linux/lifeview.txt42
-rw-r--r--Documentation/video4linux/not-in-cx2388x-datasheet.txt37
-rw-r--r--Documentation/w1/w1.generic107
-rw-r--r--Documentation/x86_64/boot-options.txt3
-rw-r--r--MAINTAINERS127
-rw-r--r--Makefile8
-rw-r--r--arch/alpha/Kconfig4
-rw-r--r--arch/alpha/defconfig2
-rw-r--r--arch/alpha/kernel/osf_sys.c7
-rw-r--r--arch/alpha/mm/numa.c16
-rw-r--r--arch/arm/Kconfig40
-rw-r--r--arch/arm/Makefile1
-rw-r--r--arch/arm/boot/compressed/head-xscale.S7
-rw-r--r--arch/arm/boot/install.sh4
-rw-r--r--arch/arm/common/amba.c2
-rw-r--r--arch/arm/common/dmabounce.c36
-rw-r--r--arch/arm/common/sa1111.c13
-rw-r--r--arch/arm/common/sharpsl_param.c2
-rw-r--r--arch/arm/configs/badge4_defconfig29
-rw-r--r--arch/arm/configs/enp2611_defconfig67
-rw-r--r--arch/arm/configs/h3600_defconfig24
-rw-r--r--arch/arm/configs/hackkit_defconfig22
-rw-r--r--arch/arm/configs/ixdp2400_defconfig67
-rw-r--r--arch/arm/configs/ixdp2401_defconfig67
-rw-r--r--arch/arm/configs/ixdp2800_defconfig67
-rw-r--r--arch/arm/configs/ixdp2801_defconfig67
-rw-r--r--arch/arm/configs/s3c2410_defconfig27
-rw-r--r--arch/arm/kernel/Makefile2
-rw-r--r--arch/arm/kernel/arch.c46
-rw-r--r--arch/arm/kernel/ecard.c12
-rw-r--r--arch/arm/kernel/entry-armv.S272
-rw-r--r--arch/arm/kernel/entry-header.S7
-rw-r--r--arch/arm/kernel/head.S44
-rw-r--r--arch/arm/kernel/irq.c14
-rw-r--r--arch/arm/kernel/setup.c77
-rw-r--r--arch/arm/kernel/signal.c31
-rw-r--r--arch/arm/kernel/signal.h12
-rw-r--r--arch/arm/kernel/smp.c110
-rw-r--r--arch/arm/kernel/time.c103
-rw-r--r--arch/arm/kernel/traps.c58
-rw-r--r--arch/arm/lib/ashldi3.c47
-rw-r--r--arch/arm/lib/ashrdi3.c48
-rw-r--r--arch/arm/lib/gcclib.h27
-rw-r--r--arch/arm/lib/io-writesw-armv4.S6
-rw-r--r--arch/arm/lib/longlong.h68
-rw-r--r--arch/arm/lib/lshrdi3.c47
-rw-r--r--arch/arm/lib/muldi3.c31
-rw-r--r--arch/arm/lib/ucmpdi2.c30
-rw-r--r--arch/arm/lib/udivdi3.c372
-rw-r--r--arch/arm/mach-aaec2000/Kconfig11
-rw-r--r--arch/arm/mach-aaec2000/Makefile9
-rw-r--r--arch/arm/mach-aaec2000/aaed2000.c48
-rw-r--r--arch/arm/mach-aaec2000/core.c157
-rw-r--r--arch/arm/mach-aaec2000/core.h16
-rw-r--r--arch/arm/mach-clps711x/Kconfig2
-rw-r--r--arch/arm/mach-clps7500/core.c2
-rw-r--r--arch/arm/mach-integrator/Makefile1
-rw-r--r--arch/arm/mach-integrator/core.c19
-rw-r--r--arch/arm/mach-integrator/headsmp.S37
-rw-r--r--arch/arm/mach-integrator/integrator_cp.c1
-rw-r--r--arch/arm/mach-integrator/leds.c4
-rw-r--r--arch/arm/mach-integrator/platsmp.c192
-rw-r--r--arch/arm/mach-ixp2000/Kconfig8
-rw-r--r--arch/arm/mach-ixp2000/core.c119
-rw-r--r--arch/arm/mach-ixp2000/enp2611.c17
-rw-r--r--arch/arm/mach-ixp2000/ixdp2x00.c3
-rw-r--r--arch/arm/mach-ixp2000/pci.c13
-rw-r--r--arch/arm/mach-ixp4xx/common.c8
-rw-r--r--arch/arm/mach-pxa/lubbock.c30
-rw-r--r--arch/arm/mach-pxa/mainstone.c40
-rw-r--r--arch/arm/mach-pxa/pm.c34
-rw-r--r--arch/arm/mach-pxa/pxa25x.c33
-rw-r--r--arch/arm/mach-pxa/pxa27x.c36
-rw-r--r--arch/arm/mach-rpc/riscpc.c7
-rw-r--r--arch/arm/mach-s3c2410/clock.c2
-rw-r--r--arch/arm/mach-s3c2410/dma.c4
-rw-r--r--arch/arm/mach-s3c2410/mach-bast.c49
-rw-r--r--arch/arm/mach-s3c2410/mach-vr1000.c77
-rw-r--r--arch/arm/mach-s3c2410/s3c2440.c6
-rw-r--r--arch/arm/mach-sa1100/Kconfig2
-rw-r--r--arch/arm/mach-sa1100/pm.c2
-rw-r--r--arch/arm/mach-versatile/Makefile1
-rw-r--r--arch/arm/mach-versatile/core.c16
-rw-r--r--arch/arm/mach-versatile/pci.c360
-rw-r--r--arch/arm/mm/Kconfig38
-rw-r--r--arch/arm/mm/Makefile2
-rw-r--r--arch/arm/mm/copypage-v4mc.S80
-rw-r--r--arch/arm/mm/copypage-v4mc.c111
-rw-r--r--arch/arm/mm/copypage-v6.c34
-rw-r--r--arch/arm/mm/copypage-xscale.S113
-rw-r--r--arch/arm/mm/copypage-xscale.c131
-rw-r--r--arch/arm/mm/fault-armv.c31
-rw-r--r--arch/arm/mm/flush.c57
-rw-r--r--arch/arm/mm/init.c19
-rw-r--r--arch/arm/mm/ioremap.c47
-rw-r--r--arch/arm/mm/minicache.c73
-rw-r--r--arch/arm/mm/mm-armv.c27
-rw-r--r--arch/arm/mm/mmap.c10
-rw-r--r--arch/arm/mm/proc-v6.S6
-rw-r--r--arch/arm/nwfpe/softfloat-macros22
-rw-r--r--arch/arm/nwfpe/softfloat.c12
-rw-r--r--arch/arm26/Kconfig2
-rw-r--r--arch/arm26/boot/install.sh4
-rw-r--r--arch/arm26/kernel/ecard.c10
-rw-r--r--arch/cris/Kconfig2
-rw-r--r--arch/frv/Kconfig2
-rw-r--r--arch/frv/kernel/setup.c2
-rw-r--r--arch/frv/kernel/signal.c4
-rw-r--r--arch/frv/mm/init.c1
-rw-r--r--arch/h8300/Kconfig.cpu3
-rw-r--r--arch/h8300/kernel/process.c2
-rw-r--r--arch/h8300/kernel/signal.c4
-rw-r--r--arch/h8300/platform/h8300h/ptrace_h8300h.c4
-rw-r--r--arch/i386/Kconfig109
-rw-r--r--arch/i386/Makefile7
-rw-r--r--arch/i386/boot/Makefile6
-rw-r--r--arch/i386/boot/compressed/head.S7
-rw-r--r--arch/i386/boot/compressed/misc.c8
-rw-r--r--arch/i386/boot/edd.S2
-rw-r--r--arch/i386/boot/install.sh4
-rw-r--r--arch/i386/boot/setup.S6
-rw-r--r--arch/i386/boot/tools/build.c5
-rw-r--r--arch/i386/crypto/aes.c2
-rw-r--r--arch/i386/defconfig1
-rw-r--r--arch/i386/kernel/Makefile3
-rw-r--r--arch/i386/kernel/acpi/boot.c220
-rw-r--r--arch/i386/kernel/acpi/sleep.c27
-rw-r--r--arch/i386/kernel/apic.c82
-rw-r--r--arch/i386/kernel/apm.c10
-rw-r--r--arch/i386/kernel/cpu/amd.c12
-rw-r--r--arch/i386/kernel/cpu/common.c51
-rw-r--r--arch/i386/kernel/cpu/cpufreq/Kconfig14
-rw-r--r--arch/i386/kernel/cpu/cpufreq/Makefile1
-rw-r--r--arch/i386/kernel/cpu/cpufreq/longhaul.c58
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k7.c15
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k8.c113
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k8.h15
-rw-r--r--arch/i386/kernel/cpu/cpufreq/sc520_freq.c186
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c6
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-lib.c6
-rw-r--r--arch/i386/kernel/cpu/cpufreq/speedstep-smi.c3
-rw-r--r--arch/i386/kernel/cpu/intel.c12
-rw-r--r--arch/i386/kernel/cpu/intel_cacheinfo.c6
-rw-r--r--arch/i386/kernel/cpu/mcheck/k7.c2
-rw-r--r--arch/i386/kernel/cpu/mcheck/mce.c4
-rw-r--r--arch/i386/kernel/cpu/mcheck/p4.c4
-rw-r--r--arch/i386/kernel/cpu/mcheck/p5.c2
-rw-r--r--arch/i386/kernel/cpu/mcheck/p6.c2
-rw-r--r--arch/i386/kernel/cpu/mcheck/winchip.c2
-rw-r--r--arch/i386/kernel/cpu/mtrr/generic.c3
-rw-r--r--arch/i386/kernel/cpu/mtrr/main.c23
-rw-r--r--arch/i386/kernel/cpu/proc.c2
-rw-r--r--arch/i386/kernel/cpuid.c22
-rw-r--r--arch/i386/kernel/crash.c223
-rw-r--r--arch/i386/kernel/dmi_scan.c391
-rw-r--r--arch/i386/kernel/efi.c4
-rw-r--r--arch/i386/kernel/head.S6
-rw-r--r--arch/i386/kernel/i386_ksyms.c160
-rw-r--r--arch/i386/kernel/i387.c3
-rw-r--r--arch/i386/kernel/i8259.c12
-rw-r--r--arch/i386/kernel/io_apic.c56
-rw-r--r--arch/i386/kernel/irq.c72
-rw-r--r--arch/i386/kernel/kprobes.c176
-rw-r--r--arch/i386/kernel/machine_kexec.c226
-rw-r--r--arch/i386/kernel/mpparse.c33
-rw-r--r--arch/i386/kernel/msr.c22
-rw-r--r--arch/i386/kernel/nmi.c24
-rw-r--r--arch/i386/kernel/pci-dma.c3
-rw-r--r--arch/i386/kernel/process.c75
-rw-r--r--arch/i386/kernel/ptrace.c2
-rw-r--r--arch/i386/kernel/reboot.c87
-rw-r--r--arch/i386/kernel/relocate_kernel.S120
-rw-r--r--arch/i386/kernel/setup.c99
-rw-r--r--arch/i386/kernel/signal.c35
-rw-r--r--arch/i386/kernel/smp.c37
-rw-r--r--arch/i386/kernel/smpboot.c354
-rw-r--r--arch/i386/kernel/syscall_table.S4
-rw-r--r--arch/i386/kernel/sysenter.c12
-rw-r--r--arch/i386/kernel/time.c6
-rw-r--r--arch/i386/kernel/time_hpet.c2
-rw-r--r--arch/i386/kernel/timers/common.c20
-rw-r--r--arch/i386/kernel/timers/timer.c9
-rw-r--r--arch/i386/kernel/timers/timer_hpet.c3
-rw-r--r--arch/i386/kernel/timers/timer_pm.c1
-rw-r--r--arch/i386/kernel/timers/timer_tsc.c28
-rw-r--r--arch/i386/kernel/traps.c74
-rw-r--r--arch/i386/kernel/vmlinux.lds.S59
-rw-r--r--arch/i386/lib/dec_and_lock.c2
-rw-r--r--arch/i386/lib/delay.c8
-rw-r--r--arch/i386/lib/mmx.c5
-rw-r--r--arch/i386/lib/usercopy.c8
-rw-r--r--arch/i386/mach-default/setup.c27
-rw-r--r--arch/i386/mach-default/topology.c15
-rw-r--r--arch/i386/mach-visws/mpparse.c5
-rw-r--r--arch/i386/mach-voyager/voyager_smp.c19
-rw-r--r--arch/i386/mm/Makefile2
-rw-r--r--arch/i386/mm/discontig.c129
-rw-r--r--arch/i386/mm/fault.c7
-rw-r--r--arch/i386/mm/highmem.c24
-rw-r--r--arch/i386/mm/hugetlbpage.c204
-rw-r--r--arch/i386/mm/init.c24
-rw-r--r--arch/i386/mm/ioremap.c15
-rw-r--r--arch/i386/mm/pgtable.c30
-rw-r--r--arch/i386/oprofile/backtrace.c2
-rw-r--r--arch/i386/pci/fixup.c2
-rw-r--r--arch/i386/pci/irq.c27
-rw-r--r--arch/i386/pci/pcbios.c4
-rw-r--r--arch/i386/power/cpu.c37
-rw-r--r--arch/ia64/Kconfig14
-rw-r--r--arch/ia64/Kconfig.debug11
-rw-r--r--arch/ia64/configs/sn2_defconfig8
-rw-r--r--arch/ia64/configs/tiger_defconfig19
-rw-r--r--arch/ia64/defconfig146
-rw-r--r--arch/ia64/ia32/ia32_ioctl.c1
-rw-r--r--arch/ia64/ia32/ia32priv.h2
-rw-r--r--arch/ia64/ia32/sys_ia32.c2
-rw-r--r--arch/ia64/kernel/Makefile2
-rw-r--r--arch/ia64/kernel/domain.c78
-rw-r--r--arch/ia64/kernel/efi.c32
-rw-r--r--arch/ia64/kernel/entry.S6
-rw-r--r--arch/ia64/kernel/entry.h2
-rw-r--r--arch/ia64/kernel/fsys.S4
-rw-r--r--arch/ia64/kernel/ivt.S13
-rw-r--r--arch/ia64/kernel/jprobes.S61
-rw-r--r--arch/ia64/kernel/kprobes.c601
-rw-r--r--arch/ia64/kernel/mca.c8
-rw-r--r--arch/ia64/kernel/minstate.h3
-rw-r--r--arch/ia64/kernel/module.c10
-rw-r--r--arch/ia64/kernel/perfmon.c175
-rw-r--r--arch/ia64/kernel/ptrace.c41
-rw-r--r--arch/ia64/kernel/setup.c3
-rw-r--r--arch/ia64/kernel/signal.c5
-rw-r--r--arch/ia64/kernel/smp.c2
-rw-r--r--arch/ia64/kernel/smpboot.c6
-rw-r--r--arch/ia64/kernel/sys_ia64.c7
-rw-r--r--arch/ia64/kernel/traps.c62
-rw-r--r--arch/ia64/kernel/uncached.c246
-rw-r--r--arch/ia64/mm/discontig.c9
-rw-r--r--arch/ia64/mm/fault.c8
-rw-r--r--arch/ia64/mm/hugetlbpage.c158
-rw-r--r--arch/ia64/mm/init.c19
-rw-r--r--arch/ia64/pci/pci.c20
-rw-r--r--arch/ia64/sn/kernel/setup.c6
-rw-r--r--arch/ia64/sn/kernel/tiocx.c25
-rw-r--r--arch/ia64/sn/kernel/xpc.h12
-rw-r--r--arch/ia64/sn/kernel/xpc_channel.c12
-rw-r--r--arch/ia64/sn/kernel/xpc_partition.c8
-rw-r--r--arch/m32r/Kconfig11
-rw-r--r--arch/m32r/boot/compressed/m32r_sio.c19
-rw-r--r--arch/m32r/defconfig52
-rw-r--r--arch/m32r/kernel/Makefile2
-rw-r--r--arch/m32r/kernel/io_m32700ut.c92
-rw-r--r--arch/m32r/kernel/io_mappi.c74
-rw-r--r--arch/m32r/kernel/io_mappi2.c92
-rw-r--r--arch/m32r/kernel/io_mappi3.c378
-rw-r--r--arch/m32r/kernel/io_oaks32r.c36
-rw-r--r--arch/m32r/kernel/io_opsput.c79
-rw-r--r--arch/m32r/kernel/io_usrv.c51
-rw-r--r--arch/m32r/kernel/setup.c2
-rw-r--r--arch/m32r/kernel/setup_m32700ut.c56
-rw-r--r--arch/m32r/kernel/setup_mappi.c14
-rw-r--r--arch/m32r/kernel/setup_mappi2.c20
-rw-r--r--arch/m32r/kernel/setup_mappi3.c208
-rw-r--r--arch/m32r/kernel/setup_oaks32r.c14
-rw-r--r--arch/m32r/kernel/setup_opsput.c28
-rw-r--r--arch/m32r/kernel/setup_usrv.c28
-rw-r--r--arch/m32r/kernel/signal.c4
-rw-r--r--arch/m32r/m32700ut/defconfig.m32700ut.smp53
-rw-r--r--arch/m32r/m32700ut/defconfig.m32700ut.up52
-rw-r--r--arch/m32r/mappi/defconfig.nommu46
-rw-r--r--arch/m32r/mappi/defconfig.smp49
-rw-r--r--arch/m32r/mappi/defconfig.up48
-rw-r--r--arch/m32r/mappi2/defconfig.vdec246
-rw-r--r--arch/m32r/mappi3/defconfig.smp751
-rw-r--r--arch/m32r/mappi3/dot.gdbinit224
-rw-r--r--arch/m32r/mm/extable.c5
-rw-r--r--arch/m32r/mm/init.c4
-rw-r--r--arch/m32r/oaks32r/defconfig.nommu50
-rw-r--r--arch/m32r/opsput/defconfig.opsput45
-rw-r--r--arch/m68k/Kconfig2
-rw-r--r--arch/m68k/configs/amiga_defconfig15
-rw-r--r--arch/m68k/configs/apollo_defconfig7
-rw-r--r--arch/m68k/configs/atari_defconfig7
-rw-r--r--arch/m68k/configs/bvme6000_defconfig7
-rw-r--r--arch/m68k/configs/hp300_defconfig7
-rw-r--r--arch/m68k/configs/mac_defconfig7
-rw-r--r--arch/m68k/configs/mvme147_defconfig7
-rw-r--r--arch/m68k/configs/mvme16x_defconfig7
-rw-r--r--arch/m68k/configs/q40_defconfig15
-rw-r--r--arch/m68k/configs/sun3_defconfig8
-rw-r--r--arch/m68k/configs/sun3x_defconfig7
-rw-r--r--arch/m68k/defconfig7
-rw-r--r--arch/m68knommu/Kconfig2
-rw-r--r--arch/m68knommu/kernel/process.c17
-rw-r--r--arch/mips/Kconfig8
-rw-r--r--arch/mips/configs/ip27_defconfig2
-rw-r--r--arch/mips/kernel/setup.c4
-rw-r--r--arch/mips/mm/init.c5
-rw-r--r--arch/mips/mm/pgtable.c2
-rw-r--r--arch/mips/sgi-ip27/ip27-memory.c5
-rw-r--r--arch/mips/vr41xx/common/pmu.c55
-rw-r--r--arch/parisc/Kconfig4
-rw-r--r--arch/parisc/kernel/drivers.c2
-rw-r--r--arch/parisc/mm/init.c2
-rw-r--r--arch/ppc/Kconfig65
-rw-r--r--arch/ppc/Kconfig.debug2
-rw-r--r--arch/ppc/Makefile3
-rw-r--r--arch/ppc/boot/images/Makefile3
-rw-r--r--arch/ppc/boot/ld.script3
-rw-r--r--arch/ppc/boot/openfirmware/Makefile5
-rw-r--r--arch/ppc/boot/openfirmware/chrpmain.c2
-rw-r--r--arch/ppc/boot/openfirmware/common.c16
-rw-r--r--arch/ppc/boot/simple/Makefile4
-rw-r--r--arch/ppc/boot/simple/misc.c2
-rw-r--r--arch/ppc/boot/simple/mpc10x_memory.c2
-rw-r--r--arch/ppc/boot/utils/addSystemMap.c186
-rw-r--r--arch/ppc/configs/mpc8548_cds_defconfig659
-rw-r--r--arch/ppc/configs/mpc8555_cds_defconfig117
-rw-r--r--arch/ppc/kernel/Makefile3
-rw-r--r--arch/ppc/kernel/cputable.c50
-rw-r--r--arch/ppc/kernel/entry.S189
-rw-r--r--arch/ppc/kernel/head_44x.S15
-rw-r--r--arch/ppc/kernel/head_4xx.S15
-rw-r--r--arch/ppc/kernel/head_booke.h158
-rw-r--r--arch/ppc/kernel/head_fsl_booke.S66
-rw-r--r--arch/ppc/kernel/machine_kexec.c118
-rw-r--r--arch/ppc/kernel/misc.S16
-rw-r--r--arch/ppc/kernel/pci.c2
-rw-r--r--arch/ppc/kernel/perfmon.c2
-rw-r--r--arch/ppc/kernel/ppc_ksyms.c2
-rw-r--r--arch/ppc/kernel/ptrace.c40
-rw-r--r--arch/ppc/kernel/relocate_kernel.S123
-rw-r--r--arch/ppc/kernel/setup.c15
-rw-r--r--arch/ppc/kernel/signal.c3
-rw-r--r--arch/ppc/kernel/traps.c37
-rw-r--r--arch/ppc/lib/locks.c4
-rw-r--r--arch/ppc/lib/string.S7
-rw-r--r--arch/ppc/mm/44x_mmu.c1
-rw-r--r--arch/ppc/mm/4xx_mmu.c1
-rw-r--r--arch/ppc/mm/fsl_booke_mmu.c5
-rw-r--r--arch/ppc/mm/init.c18
-rw-r--r--arch/ppc/mm/mmu_decl.h2
-rw-r--r--arch/ppc/mm/pgtable.c1
-rw-r--r--arch/ppc/platforms/83xx/mpc834x_sys.c50
-rw-r--r--arch/ppc/platforms/83xx/mpc834x_sys.h7
-rw-r--r--arch/ppc/platforms/85xx/Kconfig10
-rw-r--r--arch/ppc/platforms/85xx/Makefile1
-rw-r--r--arch/ppc/platforms/85xx/mpc8540_ads.c54
-rw-r--r--arch/ppc/platforms/85xx/mpc8560_ads.c29
-rw-r--r--arch/ppc/platforms/85xx/mpc85xx_ads_common.c37
-rw-r--r--arch/ppc/platforms/85xx/mpc85xx_cds_common.c238
-rw-r--r--arch/ppc/platforms/85xx/mpc85xx_cds_common.h3
-rw-r--r--arch/ppc/platforms/85xx/sbc8560.c36
-rw-r--r--arch/ppc/platforms/85xx/sbc85xx.c37
-rw-r--r--arch/ppc/platforms/85xx/stx_gp3.c63
-rw-r--r--arch/ppc/platforms/chrp_pci.c1
-rw-r--r--arch/ppc/platforms/katana.c2
-rw-r--r--arch/ppc/platforms/pmac_cpufreq.c43
-rw-r--r--arch/ppc/platforms/pmac_pci.c1
-rw-r--r--arch/ppc/platforms/pq2ads.h41
-rw-r--r--arch/ppc/platforms/sandpoint.c20
-rw-r--r--arch/ppc/syslib/Makefile7
-rw-r--r--arch/ppc/syslib/cpm2_common.c2
-rw-r--r--arch/ppc/syslib/indirect_pci.c1
-rw-r--r--arch/ppc/syslib/ipic.c16
-rw-r--r--arch/ppc/syslib/m8260_pci.c193
-rw-r--r--arch/ppc/syslib/m8260_pci.h76
-rw-r--r--arch/ppc/syslib/m8260_pci_erratum9.c10
-rw-r--r--arch/ppc/syslib/m8260_setup.c11
-rw-r--r--arch/ppc/syslib/m82xx_pci.c383
-rw-r--r--arch/ppc/syslib/m82xx_pci.h92
-rw-r--r--arch/ppc/syslib/mpc10x_common.c203
-rw-r--r--arch/ppc/syslib/mpc83xx_devices.c1
-rw-r--r--arch/ppc/syslib/mpc85xx_devices.c188
-rw-r--r--arch/ppc/syslib/mpc85xx_sys.c105
-rw-r--r--arch/ppc/syslib/mv64x60.c1
-rw-r--r--arch/ppc/syslib/mv64x60_win.c1
-rw-r--r--arch/ppc/syslib/ocp.c2
-rw-r--r--arch/ppc/syslib/of_device.c2
-rw-r--r--arch/ppc/syslib/open_pic.c7
-rw-r--r--arch/ppc/syslib/open_pic2.c1
-rw-r--r--arch/ppc/syslib/ppc4xx_kgdb.c124
-rw-r--r--arch/ppc/syslib/ppc83xx_setup.c29
-rw-r--r--arch/ppc/syslib/ppc85xx_setup.c19
-rw-r--r--arch/ppc/syslib/prom_init.c10
-rw-r--r--arch/ppc/xmon/xmon.c270
-rw-r--r--arch/ppc64/Kconfig103
-rw-r--r--arch/ppc64/Makefile8
-rw-r--r--arch/ppc64/boot/install.sh4
-rw-r--r--arch/ppc64/boot/prom.c28
-rw-r--r--arch/ppc64/configs/g5_defconfig76
-rw-r--r--arch/ppc64/configs/iSeries_defconfig62
-rw-r--r--arch/ppc64/configs/maple_defconfig70
-rw-r--r--arch/ppc64/configs/pSeries_defconfig104
-rw-r--r--arch/ppc64/defconfig106
-rw-r--r--arch/ppc64/kernel/HvLpEvent.c2
-rw-r--r--arch/ppc64/kernel/ItLpQueue.c1
-rw-r--r--arch/ppc64/kernel/Makefile19
-rw-r--r--arch/ppc64/kernel/XmPciLpEvent.c190
-rw-r--r--arch/ppc64/kernel/asm-offsets.c1
-rw-r--r--arch/ppc64/kernel/bpa_iic.c270
-rw-r--r--arch/ppc64/kernel/bpa_iic.h62
-rw-r--r--arch/ppc64/kernel/bpa_iommu.c377
-rw-r--r--arch/ppc64/kernel/bpa_iommu.h65
-rw-r--r--arch/ppc64/kernel/bpa_nvram.c118
-rw-r--r--arch/ppc64/kernel/bpa_setup.c140
-rw-r--r--arch/ppc64/kernel/cpu_setup_power4.S16
-rw-r--r--arch/ppc64/kernel/cputable.c11
-rw-r--r--arch/ppc64/kernel/dma.c4
-rw-r--r--arch/ppc64/kernel/eeh.c2
-rw-r--r--arch/ppc64/kernel/entry.S9
-rw-r--r--arch/ppc64/kernel/head.S20
-rw-r--r--arch/ppc64/kernel/iSeries_VpdInfo.c220
-rw-r--r--arch/ppc64/kernel/iSeries_iommu.c3
-rw-r--r--arch/ppc64/kernel/iSeries_irq.c312
-rw-r--r--arch/ppc64/kernel/iSeries_pci.c45
-rw-r--r--arch/ppc64/kernel/iSeries_pci_reset.c104
-rw-r--r--arch/ppc64/kernel/iSeries_proc.c3
-rw-r--r--arch/ppc64/kernel/iSeries_setup.c41
-rw-r--r--arch/ppc64/kernel/iSeries_smp.c2
-rw-r--r--arch/ppc64/kernel/idle.c15
-rw-r--r--arch/ppc64/kernel/iommu.c3
-rw-r--r--arch/ppc64/kernel/irq.c5
-rw-r--r--arch/ppc64/kernel/kprobes.c79
-rw-r--r--arch/ppc64/kernel/lparcfg.c3
-rw-r--r--arch/ppc64/kernel/machine_kexec.c302
-rw-r--r--arch/ppc64/kernel/maple_setup.c64
-rw-r--r--arch/ppc64/kernel/maple_time.c51
-rw-r--r--arch/ppc64/kernel/mf.c86
-rw-r--r--arch/ppc64/kernel/misc.S177
-rw-r--r--arch/ppc64/kernel/mpic.c29
-rw-r--r--arch/ppc64/kernel/mpic.h6
-rw-r--r--arch/ppc64/kernel/of_device.c2
-rw-r--r--arch/ppc64/kernel/pSeries_pci.c497
-rw-r--r--arch/ppc64/kernel/pSeries_reconfig.c8
-rw-r--r--arch/ppc64/kernel/pSeries_setup.c188
-rw-r--r--arch/ppc64/kernel/pSeries_smp.c83
-rw-r--r--arch/ppc64/kernel/pci.c5
-rw-r--r--arch/ppc64/kernel/pci.h6
-rw-r--r--arch/ppc64/kernel/pmac_smp.c28
-rw-r--r--arch/ppc64/kernel/pmac_time.c8
-rw-r--r--arch/ppc64/kernel/proc_ppc64.c2
-rw-r--r--arch/ppc64/kernel/process.c11
-rw-r--r--arch/ppc64/kernel/prom.c12
-rw-r--r--arch/ppc64/kernel/prom_init.c158
-rw-r--r--arch/ppc64/kernel/ptrace.c4
-rw-r--r--arch/ppc64/kernel/ras.c1
-rw-r--r--arch/ppc64/kernel/rtas-proc.c4
-rw-r--r--arch/ppc64/kernel/rtas.c121
-rw-r--r--arch/ppc64/kernel/rtas_pci.c495
-rw-r--r--arch/ppc64/kernel/rtasd.c4
-rw-r--r--arch/ppc64/kernel/rtc.c47
-rw-r--r--arch/ppc64/kernel/setup.c115
-rw-r--r--arch/ppc64/kernel/smp.c7
-rw-r--r--arch/ppc64/kernel/spider-pic.c191
-rw-r--r--arch/ppc64/kernel/sys_ppc32.c73
-rw-r--r--arch/ppc64/kernel/syscalls.c33
-rw-r--r--arch/ppc64/kernel/sysfs.c8
-rw-r--r--arch/ppc64/kernel/time.c66
-rw-r--r--arch/ppc64/kernel/traps.c4
-rw-r--r--arch/ppc64/kernel/vio.c41
-rw-r--r--arch/ppc64/kernel/viopath.c10
-rw-r--r--arch/ppc64/kernel/xics.c25
-rw-r--r--arch/ppc64/lib/Makefile2
-rw-r--r--arch/ppc64/mm/Makefile2
-rw-r--r--arch/ppc64/mm/hash_native.c47
-rw-r--r--arch/ppc64/mm/hash_utils.c6
-rw-r--r--arch/ppc64/mm/hugetlbpage.c214
-rw-r--r--arch/ppc64/mm/imalloc.c20
-rw-r--r--arch/ppc64/mm/init.c115
-rw-r--r--arch/ppc64/mm/numa.c3
-rw-r--r--arch/ppc64/xmon/xmon.c9
-rw-r--r--arch/s390/Kconfig10
-rw-r--r--arch/s390/appldata/appldata_base.c72
-rw-r--r--arch/s390/appldata/appldata_mem.c2
-rw-r--r--arch/s390/appldata/appldata_net_sum.c2
-rw-r--r--arch/s390/appldata/appldata_os.c4
-rw-r--r--arch/s390/boot/install.sh4
-rw-r--r--arch/s390/defconfig1
-rw-r--r--arch/s390/kernel/Makefile10
-rw-r--r--arch/s390/kernel/compat_ioctl.c6
-rw-r--r--arch/s390/kernel/compat_linux.h2
-rw-r--r--arch/s390/kernel/compat_wrapper.S8
-rw-r--r--arch/s390/kernel/cpcmd.c109
-rw-r--r--arch/s390/kernel/crash.c17
-rw-r--r--arch/s390/kernel/debug.c820
-rw-r--r--arch/s390/kernel/entry.S102
-rw-r--r--arch/s390/kernel/entry64.S97
-rw-r--r--arch/s390/kernel/head.S27
-rw-r--r--arch/s390/kernel/head64.S25
-rw-r--r--arch/s390/kernel/machine_kexec.c98
-rw-r--r--arch/s390/kernel/process.c46
-rw-r--r--arch/s390/kernel/ptrace.c55
-rw-r--r--arch/s390/kernel/relocate_kernel.S81
-rw-r--r--arch/s390/kernel/relocate_kernel64.S82
-rw-r--r--arch/s390/kernel/setup.c19
-rw-r--r--arch/s390/kernel/smp.c23
-rw-r--r--arch/s390/kernel/syscalls.S2
-rw-r--r--arch/s390/kernel/traps.c7
-rw-r--r--arch/s390/mm/cmm.c2
-rw-r--r--arch/s390/mm/extmem.c4
-rw-r--r--arch/s390/mm/fault.c2
-rw-r--r--arch/sh/Kconfig4
-rw-r--r--arch/sh/kernel/sys_sh.c8
-rw-r--r--arch/sh/lib/delay.c2
-rw-r--r--arch/sh/mm/hugetlbpage.c196
-rw-r--r--arch/sh64/Kconfig2
-rw-r--r--arch/sh64/mm/hugetlbpage.c18
-rw-r--r--arch/sparc/Kconfig18
-rw-r--r--arch/sparc/mm/init.c1
-rw-r--r--arch/sparc64/Kconfig2
-rw-r--r--arch/sparc64/kernel/kprobes.c83
-rw-r--r--arch/sparc64/kernel/pci_iommu.c221
-rw-r--r--arch/sparc64/kernel/pci_psycho.c2
-rw-r--r--arch/sparc64/kernel/pci_sabre.c2
-rw-r--r--arch/sparc64/kernel/pci_schizo.c2
-rw-r--r--arch/sparc64/kernel/sbus.c41
-rw-r--r--arch/sparc64/kernel/setup.c11
-rw-r--r--arch/sparc64/kernel/signal32.c2
-rw-r--r--arch/sparc64/kernel/smp.c3
-rw-r--r--arch/sparc64/kernel/sys_sparc.c8
-rw-r--r--arch/sparc64/kernel/traps.c19
-rw-r--r--arch/sparc64/lib/delay.c2
-rw-r--r--arch/sparc64/mm/hugetlbpage.c195
-rw-r--r--arch/sparc64/solaris/socket.c6
-rw-r--r--arch/um/Kconfig6
-rw-r--r--arch/um/Kconfig.debug4
-rw-r--r--arch/um/Kconfig_char6
-rw-r--r--arch/um/Kconfig_x86_644
-rw-r--r--arch/um/Makefile2
-rw-r--r--arch/um/drivers/Makefile6
-rw-r--r--arch/um/drivers/chan_kern.c22
-rw-r--r--arch/um/drivers/chan_user.c26
-rw-r--r--arch/um/drivers/daemon_user.c6
-rw-r--r--arch/um/drivers/line.c22
-rw-r--r--arch/um/drivers/mcast_kern.c4
-rw-r--r--arch/um/drivers/mcast_user.c47
-rw-r--r--arch/um/drivers/mconsole_kern.c36
-rw-r--r--arch/um/drivers/mmapper_kern.c24
-rw-r--r--arch/um/drivers/net_kern.c32
-rw-r--r--arch/um/drivers/net_user.c2
-rw-r--r--arch/um/drivers/port_kern.c1
-rw-r--r--arch/um/drivers/random.c16
-rw-r--r--arch/um/drivers/slip.h23
-rw-r--r--arch/um/drivers/slip_common.c54
-rw-r--r--arch/um/drivers/slip_common.h (renamed from arch/um/drivers/slip_proto.h)47
-rw-r--r--arch/um/drivers/slip_kern.c12
-rw-r--r--arch/um/drivers/slip_user.c152
-rw-r--r--arch/um/drivers/slirp.h26
-rw-r--r--arch/um/drivers/slirp_kern.c5
-rw-r--r--arch/um/drivers/slirp_user.c104
-rw-r--r--arch/um/drivers/ssl.c10
-rw-r--r--arch/um/drivers/stderr_console.c6
-rw-r--r--arch/um/drivers/stdio_console.c8
-rw-r--r--arch/um/drivers/ubd_kern.c340
-rw-r--r--arch/um/drivers/xterm_kern.c1
-rw-r--r--arch/um/include/2_5compat.h24
-rw-r--r--arch/um/include/line.h3
-rw-r--r--arch/um/include/mconsole.h2
-rw-r--r--arch/um/include/mconsole_kern.h3
-rw-r--r--arch/um/include/net_user.h2
-rw-r--r--arch/um/include/os.h2
-rw-r--r--arch/um/include/sysdep-i386/ptrace.h5
-rw-r--r--arch/um/include/sysdep-x86_64/checksum.h26
-rw-r--r--arch/um/include/sysdep-x86_64/ptrace.h62
-rw-r--r--arch/um/include/sysrq.h3
-rw-r--r--arch/um/include/time_user.h2
-rw-r--r--arch/um/include/user_util.h3
-rw-r--r--arch/um/kernel/Makefile2
-rw-r--r--arch/um/kernel/checksum.c0
-rw-r--r--arch/um/kernel/exec_kern.c1
-rw-r--r--arch/um/kernel/initrd.c (renamed from arch/um/kernel/initrd_kern.c)21
-rw-r--r--arch/um/kernel/initrd_user.c46
-rw-r--r--arch/um/kernel/irq.c11
-rw-r--r--arch/um/kernel/irq_user.c12
-rw-r--r--arch/um/kernel/ksyms.c1
-rw-r--r--arch/um/kernel/main.c41
-rw-r--r--arch/um/kernel/mem.c41
-rw-r--r--arch/um/kernel/process.c49
-rw-r--r--arch/um/kernel/process_kern.c50
-rw-r--r--arch/um/kernel/ptrace.c25
-rw-r--r--arch/um/kernel/reboot.c9
-rw-r--r--arch/um/kernel/skas/Makefile4
-rw-r--r--arch/um/kernel/skas/include/mode-skas.h1
-rw-r--r--arch/um/kernel/skas/process_kern.c22
-rw-r--r--arch/um/kernel/skas/time.c30
-rw-r--r--arch/um/kernel/syscall_kern.c19
-rw-r--r--arch/um/kernel/sysrq.c21
-rw-r--r--arch/um/kernel/time.c31
-rw-r--r--arch/um/kernel/time_kern.c2
-rw-r--r--arch/um/kernel/trap_kern.c37
-rw-r--r--arch/um/kernel/tt/Makefile19
-rw-r--r--arch/um/kernel/tt/gdb.c4
-rw-r--r--arch/um/kernel/tt/gdb_kern.c2
-rw-r--r--arch/um/kernel/tt/include/debug.h17
-rw-r--r--arch/um/kernel/tt/include/mode-tt.h1
-rw-r--r--arch/um/kernel/tt/ksyms.c1
-rw-r--r--arch/um/kernel/tt/process_kern.c25
-rw-r--r--arch/um/kernel/tt/time.c28
-rw-r--r--arch/um/kernel/tt/unmap.c31
-rw-r--r--arch/um/kernel/um_arch.c7
-rw-r--r--arch/um/kernel/uml.lds.S17
-rw-r--r--arch/um/os-Linux/elf_aux.c6
-rw-r--r--arch/um/os-Linux/file.c2
-rw-r--r--arch/um/scripts/Makefile.rules8
-rw-r--r--arch/um/scripts/Makefile.unmap22
-rw-r--r--arch/um/sys-i386/Makefile4
-rw-r--r--arch/um/sys-i386/delay.c16
-rw-r--r--arch/um/sys-i386/signal.c2
-rw-r--r--arch/um/sys-i386/syscalls.c23
-rw-r--r--arch/um/sys-i386/sysrq.c80
-rw-r--r--arch/um/sys-i386/unmap.c25
-rw-r--r--arch/um/sys-ppc/sysrq.c14
-rw-r--r--arch/um/sys-x86_64/Makefile8
-rw-r--r--arch/um/sys-x86_64/delay.c33
-rw-r--r--arch/um/sys-x86_64/ksyms.c3
-rw-r--r--arch/um/sys-x86_64/ptrace.c9
-rw-r--r--arch/um/sys-x86_64/syscalls.c40
-rw-r--r--arch/um/sys-x86_64/sysrq.c11
-rw-r--r--arch/um/sys-x86_64/unmap.c25
-rw-r--r--arch/um/sys-x86_64/user-offsets.c8
-rw-r--r--arch/v850/Kconfig2
-rw-r--r--arch/x86_64/Kconfig108
-rw-r--r--arch/x86_64/Makefile2
-rw-r--r--arch/x86_64/boot/compressed/head.S11
-rw-r--r--arch/x86_64/boot/compressed/misc.c12
-rw-r--r--arch/x86_64/boot/install.sh6
-rw-r--r--arch/x86_64/boot/setup.S8
-rw-r--r--arch/x86_64/boot/tools/build.c5
-rw-r--r--arch/x86_64/defconfig58
-rw-r--r--arch/x86_64/ia32/ia32_aout.c1
-rw-r--r--arch/x86_64/ia32/ia32_binfmt.c5
-rw-r--r--arch/x86_64/ia32/ia32_signal.c15
-rw-r--r--arch/x86_64/ia32/ia32entry.S2
-rw-r--r--arch/x86_64/kernel/Makefile2
-rw-r--r--arch/x86_64/kernel/acpi/wakeup.S2
-rw-r--r--arch/x86_64/kernel/aperture.c45
-rw-r--r--arch/x86_64/kernel/apic.c51
-rw-r--r--arch/x86_64/kernel/crash.c35
-rw-r--r--arch/x86_64/kernel/e820.c6
-rw-r--r--arch/x86_64/kernel/early_printk.c13
-rw-r--r--arch/x86_64/kernel/entry.S11
-rw-r--r--arch/x86_64/kernel/genapic_flat.c110
-rw-r--r--arch/x86_64/kernel/head.S18
-rw-r--r--arch/x86_64/kernel/head64.c2
-rw-r--r--arch/x86_64/kernel/i387.c2
-rw-r--r--arch/x86_64/kernel/i8259.c27
-rw-r--r--arch/x86_64/kernel/io_apic.c118
-rw-r--r--arch/x86_64/kernel/irq.c29
-rw-r--r--arch/x86_64/kernel/kprobes.c190
-rw-r--r--arch/x86_64/kernel/machine_kexec.c250
-rw-r--r--arch/x86_64/kernel/mce.c10
-rw-r--r--arch/x86_64/kernel/mce_intel.c4
-rw-r--r--arch/x86_64/kernel/mpparse.c48
-rw-r--r--arch/x86_64/kernel/nmi.c250
-rw-r--r--arch/x86_64/kernel/pmtimer.c101
-rw-r--r--arch/x86_64/kernel/process.c51
-rw-r--r--arch/x86_64/kernel/ptrace.c28
-rw-r--r--arch/x86_64/kernel/reboot.c62
-rw-r--r--arch/x86_64/kernel/relocate_kernel.S143
-rw-r--r--arch/x86_64/kernel/setup.c110
-rw-r--r--arch/x86_64/kernel/setup64.c6
-rw-r--r--arch/x86_64/kernel/signal.c37
-rw-r--r--arch/x86_64/kernel/smp.c10
-rw-r--r--arch/x86_64/kernel/smpboot.c580
-rw-r--r--arch/x86_64/kernel/suspend.c18
-rw-r--r--arch/x86_64/kernel/sys_x86_64.c23
-rw-r--r--arch/x86_64/kernel/time.c106
-rw-r--r--arch/x86_64/kernel/traps.c32
-rw-r--r--arch/x86_64/kernel/vmlinux.lds.S128
-rw-r--r--arch/x86_64/kernel/vsyscall.c5
-rw-r--r--arch/x86_64/kernel/x8664_ksyms.c3
-rw-r--r--arch/x86_64/lib/delay.c9
-rw-r--r--arch/x86_64/mm/Makefile2
-rw-r--r--arch/x86_64/mm/fault.c17
-rw-r--r--arch/x86_64/mm/init.c9
-rw-r--r--arch/x86_64/mm/ioremap.c31
-rw-r--r--arch/x86_64/mm/numa.c10
-rw-r--r--arch/x86_64/pci/k8-bus.c16
-rw-r--r--arch/xtensa/Kconfig258
-rw-r--r--arch/xtensa/Kconfig.debug7
-rw-r--r--arch/xtensa/Makefile102
-rw-r--r--arch/xtensa/boot/Makefile37
-rw-r--r--arch/xtensa/boot/boot-elf/Makefile52
-rw-r--r--arch/xtensa/boot/boot-elf/boot.ld71
-rw-r--r--arch/xtensa/boot/boot-elf/bootstrap.S37
-rw-r--r--arch/xtensa/boot/boot-redboot/Makefile35
-rw-r--r--arch/xtensa/boot/boot-redboot/boot.ld66
-rw-r--r--arch/xtensa/boot/boot-redboot/bootstrap.S246
-rw-r--r--arch/xtensa/boot/include/zlib.h433
-rw-r--r--arch/xtensa/boot/lib/Makefile6
-rw-r--r--arch/xtensa/boot/lib/memcpy.S36
-rw-r--r--arch/xtensa/boot/lib/zlib.c2150
-rw-r--r--arch/xtensa/boot/lib/zmem.c87
-rw-r--r--arch/xtensa/boot/ramdisk/Makefile23
-rw-r--r--arch/xtensa/configs/common_defconfig662
-rw-r--r--arch/xtensa/configs/iss_defconfig531
-rw-r--r--arch/xtensa/kernel/Makefile18
-rw-r--r--arch/xtensa/kernel/align.S459
-rw-r--r--arch/xtensa/kernel/asm-offsets.c94
-rw-r--r--arch/xtensa/kernel/coprocessor.S201
-rw-r--r--arch/xtensa/kernel/entry.S1996
-rw-r--r--arch/xtensa/kernel/head.S237
-rw-r--r--arch/xtensa/kernel/irq.c192
-rw-r--r--arch/xtensa/kernel/module.c78
-rw-r--r--arch/xtensa/kernel/pci-dma.c73
-rw-r--r--arch/xtensa/kernel/pci.c563
-rw-r--r--arch/xtensa/kernel/platform.c49
-rw-r--r--arch/xtensa/kernel/process.c482
-rw-r--r--arch/xtensa/kernel/ptrace.c407
-rw-r--r--arch/xtensa/kernel/semaphore.c226
-rw-r--r--arch/xtensa/kernel/setup.c520
-rw-r--r--arch/xtensa/kernel/signal.c713
-rw-r--r--arch/xtensa/kernel/syscalls.c418
-rw-r--r--arch/xtensa/kernel/syscalls.h248
-rw-r--r--arch/xtensa/kernel/time.c227
-rw-r--r--arch/xtensa/kernel/traps.c498
-rw-r--r--arch/xtensa/kernel/vectors.S464
-rw-r--r--arch/xtensa/kernel/vmlinux.lds.S341
-rw-r--r--arch/xtensa/kernel/xtensa_ksyms.c123
-rw-r--r--arch/xtensa/lib/Makefile7
-rw-r--r--arch/xtensa/lib/checksum.S410
-rw-r--r--arch/xtensa/lib/memcopy.S315
-rw-r--r--arch/xtensa/lib/memset.S160
-rw-r--r--arch/xtensa/lib/pci-auto.c352
-rw-r--r--arch/xtensa/lib/strcasecmp.c32
-rw-r--r--arch/xtensa/lib/strncpy_user.S224
-rw-r--r--arch/xtensa/lib/strnlen_user.S147
-rw-r--r--arch/xtensa/lib/usercopy.S321
-rw-r--r--arch/xtensa/mm/Makefile13
-rw-r--r--arch/xtensa/mm/fault.c241
-rw-r--r--arch/xtensa/mm/init.c551
-rw-r--r--arch/xtensa/mm/misc.S374
-rw-r--r--arch/xtensa/mm/pgtable.c76
-rw-r--r--arch/xtensa/mm/tlb.c545
-rw-r--r--arch/xtensa/platform-iss/Makefile13
-rw-r--r--arch/xtensa/platform-iss/console.c300
-rw-r--r--arch/xtensa/platform-iss/io.c32
-rw-r--r--arch/xtensa/platform-iss/network.c855
-rw-r--r--arch/xtensa/platform-iss/setup.c112
-rw-r--r--crypto/crypto_null.c28
-rw-r--r--crypto/internal.h2
-rw-r--r--crypto/tcrypt.c580
-rw-r--r--crypto/tcrypt.h449
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/acorn/char/pcf8583.c3
-rw-r--r--drivers/acpi/Kconfig7
-rw-r--r--drivers/acpi/pci_irq.c5
-rw-r--r--drivers/acpi/processor_idle.c2
-rw-r--r--drivers/acpi/scan.c4
-rw-r--r--drivers/atm/Makefile3
-rw-r--r--drivers/atm/fore200e.c6
-rw-r--r--drivers/atm/he.c6
-rw-r--r--drivers/atm/nicstar.c20
-rw-r--r--drivers/atm/zatm.c11
-rw-r--r--drivers/base/Makefile4
-rw-r--r--drivers/base/base.h2
-rw-r--r--drivers/base/bus.c297
-rw-r--r--drivers/base/class.c194
-rw-r--r--drivers/base/class_simple.c199
-rw-r--r--drivers/base/core.c69
-rw-r--r--drivers/base/cpu.c11
-rw-r--r--drivers/base/dd.c248
-rw-r--r--drivers/base/dmapool.c2
-rw-r--r--drivers/base/driver.c39
-rw-r--r--drivers/base/interface.c51
-rw-r--r--drivers/base/node.c22
-rw-r--r--drivers/base/power/power.h11
-rw-r--r--drivers/base/power/resume.c19
-rw-r--r--drivers/base/power/shutdown.c23
-rw-r--r--drivers/base/power/suspend.c33
-rw-r--r--drivers/base/power/sysfs.c4
-rw-r--r--drivers/base/sys.c4
-rw-r--r--drivers/block/aoe/aoechr.c10
-rw-r--r--drivers/block/as-iosched.c12
-rw-r--r--drivers/block/cciss.c12
-rw-r--r--drivers/block/cfq-iosched.c13
-rw-r--r--drivers/block/deadline-iosched.c12
-rw-r--r--drivers/block/elevator.c22
-rw-r--r--drivers/block/genhd.c27
-rw-r--r--drivers/block/ioctl.c76
-rw-r--r--drivers/block/ll_rw_blk.c208
-rw-r--r--drivers/block/loop.c81
-rw-r--r--drivers/block/paride/pd.c2
-rw-r--r--drivers/block/paride/pg.c14
-rw-r--r--drivers/block/paride/pt.c20
-rw-r--r--drivers/block/pktcdvd.c55
-rw-r--r--drivers/block/sx8.c4
-rw-r--r--drivers/block/ub.c600
-rw-r--r--drivers/bluetooth/hci_ldisc.c2
-rw-r--r--drivers/cdrom/cm206.c113
-rw-r--r--drivers/cdrom/sonycd535.c3
-rw-r--r--drivers/cdrom/viocd.c14
-rw-r--r--drivers/char/Kconfig8
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/agp/agp.h2
-rw-r--r--drivers/char/agp/ali-agp.c4
-rw-r--r--drivers/char/agp/amd-k7-agp.c6
-rw-r--r--drivers/char/agp/amd64-agp.c4
-rw-r--r--drivers/char/agp/ati-agp.c6
-rw-r--r--drivers/char/agp/backend.c6
-rw-r--r--drivers/char/agp/efficeon-agp.c2
-rw-r--r--drivers/char/agp/generic.c36
-rw-r--r--drivers/char/agp/hp-agp.c4
-rw-r--r--drivers/char/agp/i460-agp.c4
-rw-r--r--drivers/char/agp/intel-agp.c21
-rw-r--r--drivers/char/agp/sgi-agp.c12
-rw-r--r--drivers/char/agp/sworks-agp.c8
-rw-r--r--drivers/char/agp/uninorth-agp.c2
-rw-r--r--drivers/char/amiserial.c22
-rw-r--r--drivers/char/applicom.c2
-rw-r--r--drivers/char/drm/Kconfig2
-rw-r--r--drivers/char/drm/Makefile5
-rw-r--r--drivers/char/drm/drmP.h5
-rw-r--r--drivers/char/drm/drm_bufs.c25
-rw-r--r--drivers/char/drm/drm_context.c6
-rw-r--r--drivers/char/drm/drm_ioc32.c1069
-rw-r--r--drivers/char/drm/drm_pciids.h1
-rw-r--r--drivers/char/drm/i915_dma.c24
-rw-r--r--drivers/char/drm/i915_drm.h27
-rw-r--r--drivers/char/drm/i915_drv.c25
-rw-r--r--drivers/char/drm/i915_drv.h24
-rw-r--r--drivers/char/drm/i915_irq.c24
-rw-r--r--drivers/char/drm/i915_mem.c24
-rw-r--r--drivers/char/drm/radeon_drv.c3
-rw-r--r--drivers/char/drm/radeon_drv.h3
-rw-r--r--drivers/char/drm/radeon_ioc32.c395
-rw-r--r--drivers/char/drm/radeon_irq.c32
-rw-r--r--drivers/char/ds1620.c3
-rw-r--r--drivers/char/dsp56k.c14
-rw-r--r--drivers/char/ftape/compressor/zftape-compress.c4
-rw-r--r--drivers/char/ftape/zftape/zftape-init.c30
-rw-r--r--drivers/char/hpet.c2
-rw-r--r--drivers/char/hvcs.c14
-rw-r--r--drivers/char/i8k.c909
-rw-r--r--drivers/char/ip2/i2cmd.c6
-rw-r--r--drivers/char/ip2/i2cmd.h12
-rw-r--r--drivers/char/ip2main.c34
-rw-r--r--drivers/char/ipmi/ipmi_devintf.c216
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c48
-rw-r--r--drivers/char/ipmi/ipmi_poweroff.c137
-rw-r--r--drivers/char/isicom.c12
-rw-r--r--drivers/char/istallion.c13
-rw-r--r--drivers/char/lp.c12
-rw-r--r--drivers/char/mbcs.c4
-rw-r--r--drivers/char/mem.c68
-rw-r--r--drivers/char/misc.c24
-rw-r--r--drivers/char/mwave/3780i.c6
-rw-r--r--drivers/char/mwave/3780i.h4
-rw-r--r--drivers/char/mwave/mwavedd.c2
-rw-r--r--drivers/char/mwave/tp3780i.c14
-rw-r--r--drivers/char/mxser.c38
-rw-r--r--drivers/char/n_hdlc.c2
-rw-r--r--drivers/char/n_r3964.c2
-rw-r--r--drivers/char/nvram.c6
-rw-r--r--drivers/char/ppdev.c12
-rw-r--r--drivers/char/raw.c20
-rw-r--r--drivers/char/rio/func.h1
-rw-r--r--drivers/char/rio/rio_linux.c5
-rw-r--r--drivers/char/rio/rioinit.c7
-rw-r--r--drivers/char/rio/riotty.c15
-rw-r--r--drivers/char/rocket.c226
-rw-r--r--drivers/char/rocket_int.h40
-rw-r--r--drivers/char/snsc.c7
-rw-r--r--drivers/char/stallion.c10
-rw-r--r--drivers/char/sysrq.c24
-rw-r--r--drivers/char/tipar.c14
-rw-r--r--drivers/char/toshiba.c60
-rw-r--r--drivers/char/tpm/tpm.c360
-rw-r--r--drivers/char/tpm/tpm.h38
-rw-r--r--drivers/char/tpm/tpm_atmel.c63
-rw-r--r--drivers/char/tpm/tpm_nsc.c199
-rw-r--r--drivers/char/tty_io.c63
-rw-r--r--drivers/char/vc_screen.c16
-rw-r--r--drivers/char/viotape.c16
-rw-r--r--drivers/char/vr41xx_giu.c743
-rw-r--r--drivers/char/vt.c4
-rw-r--r--drivers/char/watchdog/Kconfig10
-rw-r--r--drivers/char/watchdog/Makefile1
-rw-r--r--drivers/char/watchdog/i8xx_tco.c1
-rw-r--r--drivers/char/watchdog/ixp2000_wdt.c7
-rw-r--r--drivers/char/watchdog/wdrtas.c696
-rw-r--r--drivers/cpufreq/Kconfig24
-rw-r--r--drivers/cpufreq/Makefile1
-rw-r--r--drivers/cpufreq/cpufreq.c12
-rw-r--r--drivers/cpufreq/cpufreq_conservative.c586
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c180
-rw-r--r--drivers/cpufreq/cpufreq_stats.c47
-rw-r--r--drivers/dio/dio-sysfs.c10
-rw-r--r--drivers/eisa/eisa-bus.c4
-rw-r--r--drivers/fc4/fc.c32
-rw-r--r--drivers/fc4/fc_syms.c1
-rw-r--r--drivers/fc4/fcp_impl.h1
-rw-r--r--drivers/firmware/edd.c2
-rw-r--r--drivers/firmware/efivars.c11
-rw-r--r--drivers/firmware/pcdp.c12
-rw-r--r--drivers/firmware/pcdp.h2
-rw-r--r--drivers/i2c/algos/i2c-algo-pca.c8
-rw-r--r--drivers/i2c/algos/i2c-algo-sibyte.c1
-rw-r--r--drivers/i2c/busses/Kconfig34
-rw-r--r--drivers/i2c/busses/i2c-ali1535.c1
-rw-r--r--drivers/i2c/busses/i2c-ali1563.c46
-rw-r--r--drivers/i2c/busses/i2c-ali15x3.c1
-rw-r--r--drivers/i2c/busses/i2c-amd756.c1
-rw-r--r--drivers/i2c/busses/i2c-amd8111.c1
-rw-r--r--drivers/i2c/busses/i2c-au1550.c1
-rw-r--r--drivers/i2c/busses/i2c-elektor.c1
-rw-r--r--drivers/i2c/busses/i2c-frodo.c1
-rw-r--r--drivers/i2c/busses/i2c-i801.c1
-rw-r--r--drivers/i2c/busses/i2c-i810.c1
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.c2
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.h1
-rw-r--r--drivers/i2c/busses/i2c-iop3xx.c2
-rw-r--r--drivers/i2c/busses/i2c-isa.c1
-rw-r--r--drivers/i2c/busses/i2c-ite.c1
-rw-r--r--drivers/i2c/busses/i2c-ixp2000.c8
-rw-r--r--drivers/i2c/busses/i2c-ixp4xx.c5
-rw-r--r--drivers/i2c/busses/i2c-keywest.c6
-rw-r--r--drivers/i2c/busses/i2c-mpc.c202
-rw-r--r--drivers/i2c/busses/i2c-nforce2.c1
-rw-r--r--drivers/i2c/busses/i2c-parport-light.c1
-rw-r--r--drivers/i2c/busses/i2c-parport.c3
-rw-r--r--drivers/i2c/busses/i2c-pca-isa.c1
-rw-r--r--drivers/i2c/busses/i2c-piix4.c1
-rw-r--r--drivers/i2c/busses/i2c-prosavage.c1
-rw-r--r--drivers/i2c/busses/i2c-rpx.c1
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c3
-rw-r--r--drivers/i2c/busses/i2c-savage4.c1
-rw-r--r--drivers/i2c/busses/i2c-sibyte.c1
-rw-r--r--drivers/i2c/busses/i2c-sis5595.c1
-rw-r--r--drivers/i2c/busses/i2c-sis630.c1
-rw-r--r--drivers/i2c/busses/i2c-sis96x.c1
-rw-r--r--drivers/i2c/busses/i2c-stub.c1
-rw-r--r--drivers/i2c/busses/i2c-via.c1
-rw-r--r--drivers/i2c/busses/i2c-viapro.c1
-rw-r--r--drivers/i2c/busses/i2c-voodoo3.c1
-rw-r--r--drivers/i2c/busses/scx200_acb.c1
-rw-r--r--drivers/i2c/chips/Kconfig117
-rw-r--r--drivers/i2c/chips/Makefile10
-rw-r--r--drivers/i2c/chips/adm1021.c15
-rw-r--r--drivers/i2c/chips/adm1025.c33
-rw-r--r--drivers/i2c/chips/adm1026.c578
-rw-r--r--drivers/i2c/chips/adm1031.c46
-rw-r--r--drivers/i2c/chips/adm9240.c791
-rw-r--r--drivers/i2c/chips/asb100.c51
-rw-r--r--drivers/i2c/chips/atxp1.c361
-rw-r--r--drivers/i2c/chips/ds1337.c97
-rw-r--r--drivers/i2c/chips/ds1374.c260
-rw-r--r--drivers/i2c/chips/ds1621.c10
-rw-r--r--drivers/i2c/chips/eeprom.c1
-rw-r--r--drivers/i2c/chips/fscher.c9
-rw-r--r--drivers/i2c/chips/fscpos.c16
-rw-r--r--drivers/i2c/chips/gl518sm.c13
-rw-r--r--drivers/i2c/chips/gl520sm.c8
-rw-r--r--drivers/i2c/chips/isp1301_omap.c1
-rw-r--r--drivers/i2c/chips/it87.c404
-rw-r--r--drivers/i2c/chips/lm63.c262
-rw-r--r--drivers/i2c/chips/lm75.c5
-rw-r--r--drivers/i2c/chips/lm77.c15
-rw-r--r--drivers/i2c/chips/lm78.c41
-rw-r--r--drivers/i2c/chips/lm80.c21
-rw-r--r--drivers/i2c/chips/lm83.c160
-rw-r--r--drivers/i2c/chips/lm85.c77
-rw-r--r--drivers/i2c/chips/lm87.c47
-rw-r--r--drivers/i2c/chips/lm90.c273
-rw-r--r--drivers/i2c/chips/lm92.c14
-rw-r--r--drivers/i2c/chips/m41t00.c3
-rw-r--r--drivers/i2c/chips/max1619.c7
-rw-r--r--drivers/i2c/chips/max6875.c473
-rw-r--r--drivers/i2c/chips/pc87360.c69
-rw-r--r--drivers/i2c/chips/pca9539.c192
-rw-r--r--drivers/i2c/chips/pcf8574.c12
-rw-r--r--drivers/i2c/chips/pcf8591.c10
-rw-r--r--drivers/i2c/chips/rtc8564.c4
-rw-r--r--drivers/i2c/chips/sis5595.c35
-rw-r--r--drivers/i2c/chips/smsc47b397.c4
-rw-r--r--drivers/i2c/chips/smsc47m1.c30
-rw-r--r--drivers/i2c/chips/tps65010.c1072
-rw-r--r--drivers/i2c/chips/via686a.c337
-rw-r--r--drivers/i2c/chips/w83627ehf.c846
-rw-r--r--drivers/i2c/chips/w83627hf.c58
-rw-r--r--drivers/i2c/chips/w83781d.c130
-rw-r--r--drivers/i2c/chips/w83l785ts.c5
-rw-r--r--drivers/i2c/i2c-core.c106
-rw-r--r--drivers/i2c/i2c-dev.c3
-rw-r--r--drivers/ide/Kconfig4
-rw-r--r--drivers/ide/ide-cd.c141
-rw-r--r--drivers/ide/ide-disk.c44
-rw-r--r--drivers/ide/ide-floppy.c48
-rw-r--r--drivers/ide/ide-probe.c59
-rw-r--r--drivers/ide/ide-proc.c54
-rw-r--r--drivers/ide/ide-tape.c51
-rw-r--r--drivers/ide/ide.c307
-rw-r--r--drivers/ide/pci/amd74xx.c3
-rw-r--r--drivers/ide/pci/sgiioc4.c30
-rw-r--r--drivers/ieee1394/Kconfig5
-rw-r--r--drivers/ieee1394/dv1394.c6
-rw-r--r--drivers/ieee1394/ieee1394_core.c15
-rw-r--r--drivers/ieee1394/ieee1394_core.h3
-rw-r--r--drivers/ieee1394/ieee1394_transactions.c3
-rw-r--r--drivers/ieee1394/ieee1394_transactions.h7
-rw-r--r--drivers/ieee1394/nodemgr.c32
-rw-r--r--drivers/ieee1394/ohci1394.c2
-rw-r--r--drivers/ieee1394/ohci1394.h3
-rw-r--r--drivers/ieee1394/pcilynx.c394
-rw-r--r--drivers/ieee1394/pcilynx.h49
-rw-r--r--drivers/ieee1394/raw1394.c10
-rw-r--r--drivers/ieee1394/sbp2.c156
-rw-r--r--drivers/ieee1394/sbp2.h4
-rw-r--r--drivers/ieee1394/video1394.c143
-rw-r--r--drivers/infiniband/core/sa_query.c35
-rw-r--r--drivers/infiniband/core/sysfs.c122
-rw-r--r--drivers/infiniband/core/user_mad.c4
-rw-r--r--drivers/infiniband/include/ib_sa.h4
-rw-r--r--drivers/input/evdev.c9
-rw-r--r--drivers/input/gameport/Kconfig20
-rw-r--r--drivers/input/gameport/gameport.c8
-rw-r--r--drivers/input/input.c10
-rw-r--r--drivers/input/joydev.c10
-rw-r--r--drivers/input/keyboard/atkbd.c18
-rw-r--r--drivers/input/mouse/alps.c6
-rw-r--r--drivers/input/mouse/psmouse-base.c7
-rw-r--r--drivers/input/mouse/psmouse.h4
-rw-r--r--drivers/input/mouse/synaptics.c39
-rw-r--r--drivers/input/mousedev.c31
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h32
-rw-r--r--drivers/input/serio/i8042.c52
-rw-r--r--drivers/input/serio/serio.c43
-rw-r--r--drivers/input/serio/serport.c100
-rw-r--r--drivers/input/touchscreen/gunze.c3
-rw-r--r--drivers/input/tsdev.c9
-rw-r--r--drivers/isdn/act2000/capi.c2
-rw-r--r--drivers/isdn/act2000/capi.h1
-rw-r--r--drivers/isdn/capi/capi.c14
-rw-r--r--drivers/isdn/hardware/avm/b1dma.c4
-rw-r--r--drivers/isdn/hardware/avm/c4.c6
-rw-r--r--drivers/isdn/hardware/avm/t1isa.c2
-rw-r--r--drivers/isdn/hisax/Makefile2
-rw-r--r--drivers/isdn/hisax/amd7930_fn.c8
-rw-r--r--drivers/isdn/hisax/asuscom.c4
-rw-r--r--drivers/isdn/hisax/avm_pci.c18
-rw-r--r--drivers/isdn/hisax/bkm_a4t.c4
-rw-r--r--drivers/isdn/hisax/bkm_a8.c6
-rw-r--r--drivers/isdn/hisax/callc.c6
-rw-r--r--drivers/isdn/hisax/config.c14
-rw-r--r--drivers/isdn/hisax/diva.c4
-rw-r--r--drivers/isdn/hisax/elsa.c8
-rw-r--r--drivers/isdn/hisax/elsa_ser.c20
-rw-r--r--drivers/isdn/hisax/enternow.h51
-rw-r--r--drivers/isdn/hisax/enternow_pci.c91
-rw-r--r--drivers/isdn/hisax/gazel.c5
-rw-r--r--drivers/isdn/hisax/hfc4s8s_l1.c2
-rw-r--r--drivers/isdn/hisax/hfc_2bds0.c12
-rw-r--r--drivers/isdn/hisax/hfc_2bs0.c12
-rw-r--r--drivers/isdn/hisax/hfc_pci.c12
-rw-r--r--drivers/isdn/hisax/hfc_pci.h1
-rw-r--r--drivers/isdn/hisax/hfc_sx.c10
-rw-r--r--drivers/isdn/hisax/hfc_sx.h1
-rw-r--r--drivers/isdn/hisax/hfc_usb.c6
-rw-r--r--drivers/isdn/hisax/hfc_usb.h4
-rw-r--r--drivers/isdn/hisax/hfcscard.c2
-rw-r--r--drivers/isdn/hisax/hisax.h5
-rw-r--r--drivers/isdn/hisax/hscx.c4
-rw-r--r--drivers/isdn/hisax/icc.c6
-rw-r--r--drivers/isdn/hisax/ipacx.c86
-rw-r--r--drivers/isdn/hisax/isac.c6
-rw-r--r--drivers/isdn/hisax/isar.c46
-rw-r--r--drivers/isdn/hisax/isdnl1.c8
-rw-r--r--drivers/isdn/hisax/isdnl2.c100
-rw-r--r--drivers/isdn/hisax/isdnl3.c2
-rw-r--r--drivers/isdn/hisax/isurf.c2
-rw-r--r--drivers/isdn/hisax/ix1_micro.c4
-rw-r--r--drivers/isdn/hisax/jade.c6
-rw-r--r--drivers/isdn/hisax/jade.h1
-rw-r--r--drivers/isdn/hisax/l3_1tr6.c2
-rw-r--r--drivers/isdn/hisax/l3dss1.c2
-rw-r--r--drivers/isdn/hisax/l3ni1.c4
-rw-r--r--drivers/isdn/hisax/mic.c4
-rw-r--r--drivers/isdn/hisax/netjet.c12
-rw-r--r--drivers/isdn/hisax/niccy.c4
-rw-r--r--drivers/isdn/hisax/nj_s.c2
-rw-r--r--drivers/isdn/hisax/nj_u.c2
-rw-r--r--drivers/isdn/hisax/q931.c4
-rw-r--r--drivers/isdn/hisax/s0box.c4
-rw-r--r--drivers/isdn/hisax/saphir.c2
-rw-r--r--drivers/isdn/hisax/sedlbauer.c6
-rw-r--r--drivers/isdn/hisax/sportster.c6
-rw-r--r--drivers/isdn/hisax/st5481.h4
-rw-r--r--drivers/isdn/hisax/st5481_hdlc.c580
-rw-r--r--drivers/isdn/hisax/st5481_hdlc.h62
-rw-r--r--drivers/isdn/hisax/st5481_usb.c10
-rw-r--r--drivers/isdn/hisax/tei.c2
-rw-r--r--drivers/isdn/hisax/teleint.c4
-rw-r--r--drivers/isdn/hisax/teles0.c4
-rw-r--r--drivers/isdn/hisax/teles3.c4
-rw-r--r--drivers/isdn/hisax/telespci.c4
-rw-r--r--drivers/isdn/hisax/w6692.c6
-rw-r--r--drivers/isdn/i4l/isdn_audio.c10
-rw-r--r--drivers/isdn/i4l/isdn_audio.h1
-rw-r--r--drivers/isdn/i4l/isdn_common.c6
-rw-r--r--drivers/isdn/i4l/isdn_common.h1
-rw-r--r--drivers/isdn/i4l/isdn_concap.c15
-rw-r--r--drivers/isdn/i4l/isdn_concap.h1
-rw-r--r--drivers/isdn/i4l/isdn_net.c10
-rw-r--r--drivers/isdn/i4l/isdn_tty.c4
-rw-r--r--drivers/isdn/i4l/isdn_tty.h1
-rw-r--r--drivers/isdn/i4l/isdn_ttyfax.c6
-rw-r--r--drivers/isdn/i4l/isdn_x25iface.c36
-rw-r--r--drivers/isdn/pcbit/callbacks.c17
-rw-r--r--drivers/isdn/pcbit/callbacks.h3
-rw-r--r--drivers/isdn/pcbit/capi.c10
-rw-r--r--drivers/isdn/pcbit/capi.h1
-rw-r--r--drivers/isdn/pcbit/drv.c16
-rw-r--r--drivers/isdn/sc/Makefile2
-rw-r--r--drivers/isdn/sc/command.c88
-rw-r--r--drivers/isdn/sc/debug.c46
-rw-r--r--drivers/isdn/sc/init.c21
-rw-r--r--drivers/isdn/sc/interrupt.c2
-rw-r--r--drivers/isdn/sc/ioctl.c5
-rw-r--r--drivers/isdn/sc/packet.c16
-rw-r--r--drivers/isdn/sc/shmem.c2
-rw-r--r--drivers/isdn/sc/timer.c18
-rw-r--r--drivers/macintosh/adb.c9
-rw-r--r--drivers/macintosh/therm_adt746x.c138
-rw-r--r--drivers/macintosh/therm_pm72.c4
-rw-r--r--drivers/macintosh/therm_windtunnel.c10
-rw-r--r--drivers/macintosh/via-pmu.c12
-rw-r--r--drivers/mca/mca-bus.c4
-rw-r--r--drivers/mca/mca-legacy.c1
-rw-r--r--drivers/md/Makefile3
-rw-r--r--drivers/md/bitmap.c1586
-rw-r--r--drivers/md/dm-crypt.c3
-rw-r--r--drivers/md/dm-ioctl.c14
-rw-r--r--drivers/md/dm-mpath.c3
-rw-r--r--drivers/md/linear.c8
-rw-r--r--drivers/md/md.c528
-rw-r--r--drivers/md/multipath.c11
-rw-r--r--drivers/md/raid0.c12
-rw-r--r--drivers/md/raid1.c249
-rw-r--r--drivers/md/raid10.c36
-rw-r--r--drivers/md/raid5.c19
-rw-r--r--drivers/md/raid6main.c18
-rw-r--r--drivers/media/common/ir-common.c72
-rw-r--r--drivers/media/common/saa7146_core.c4
-rw-r--r--drivers/media/common/saa7146_fops.c2
-rw-r--r--drivers/media/dvb/Kconfig4
-rw-r--r--drivers/media/dvb/Makefile2
-rw-r--r--drivers/media/dvb/b2c2/Kconfig51
-rw-r--r--drivers/media/dvb/b2c2/Makefile12
-rw-r--r--drivers/media/dvb/b2c2/b2c2-common.c214
-rw-r--r--drivers/media/dvb/b2c2/b2c2-usb-core.c549
-rw-r--r--drivers/media/dvb/b2c2/flexcop-common.h164
-rw-r--r--drivers/media/dvb/b2c2/flexcop-dma.c149
-rw-r--r--drivers/media/dvb/b2c2/flexcop-eeprom.c153
-rw-r--r--drivers/media/dvb/b2c2/flexcop-fe-tuner.c413
-rw-r--r--drivers/media/dvb/b2c2/flexcop-hw-filter.c204
-rw-r--r--drivers/media/dvb/b2c2/flexcop-i2c.c210
-rw-r--r--drivers/media/dvb/b2c2/flexcop-misc.c67
-rw-r--r--drivers/media/dvb/b2c2/flexcop-pci.c381
-rw-r--r--drivers/media/dvb/b2c2/flexcop-reg.h702
-rw-r--r--drivers/media/dvb/b2c2/flexcop-sram.c403
-rw-r--r--drivers/media/dvb/b2c2/flexcop-usb.c577
-rw-r--r--drivers/media/dvb/b2c2/flexcop-usb.h119
-rw-r--r--drivers/media/dvb/b2c2/flexcop.c286
-rw-r--r--drivers/media/dvb/b2c2/flexcop.h30
-rw-r--r--drivers/media/dvb/b2c2/skystar2.c20
-rw-r--r--drivers/media/dvb/bt8xx/Kconfig3
-rw-r--r--drivers/media/dvb/bt8xx/Makefile4
-rw-r--r--drivers/media/dvb/bt8xx/bt878.c54
-rw-r--r--drivers/media/dvb/bt8xx/bt878.h6
-rw-r--r--drivers/media/dvb/bt8xx/dst.c969
-rw-r--r--drivers/media/dvb/bt8xx/dst.h40
-rw-r--r--drivers/media/dvb/bt8xx/dst_ca.c861
-rw-r--r--drivers/media/dvb/bt8xx/dst_ca.h58
-rw-r--r--drivers/media/dvb/bt8xx/dst_common.h153
-rw-r--r--drivers/media/dvb/bt8xx/dst_priv.h1
-rw-r--r--drivers/media/dvb/bt8xx/dvb-bt8xx.c121
-rw-r--r--drivers/media/dvb/bt8xx/dvb-bt8xx.h4
-rw-r--r--drivers/media/dvb/cinergyT2/cinergyT2.c12
-rw-r--r--drivers/media/dvb/dibusb/Kconfig62
-rw-r--r--drivers/media/dvb/dibusb/Makefile11
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb-core.c558
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb-dvb.c185
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c582
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb-firmware.c87
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb-remote.c316
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb-usb.c303
-rw-r--r--drivers/media/dvb/dibusb/dvb-dibusb.h327
-rw-r--r--drivers/media/dvb/dvb-core/dmxdev.c32
-rw-r--r--drivers/media/dvb/dvb-core/dvb_ca_en50221.c38
-rw-r--r--drivers/media/dvb/dvb-core/dvb_frontend.c43
-rw-r--r--drivers/media/dvb/dvb-core/dvb_net.c75
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.c22
-rw-r--r--drivers/media/dvb/dvb-core/dvbdev.h2
-rw-r--r--drivers/media/dvb/dvb-usb/Kconfig99
-rw-r--r--drivers/media/dvb/dvb-usb/Makefile30
-rw-r--r--drivers/media/dvb/dvb-usb/a800.c176
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-common.c272
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-mb.c316
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb-mc.c116
-rw-r--r--drivers/media/dvb/dvb-usb/dibusb.h122
-rw-r--r--drivers/media/dvb/dvb-usb/digitv.c282
-rw-r--r--drivers/media/dvb/dvb-usb/digitv.h65
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u-fe.c (renamed from drivers/media/dvb/dibusb/dvb-fe-dtt200u.c)113
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u.c171
-rw-r--r--drivers/media/dvb/dvb-usb/dtt200u.h66
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-common.h44
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-dvb.c210
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-firmware.c100
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-i2c.c118
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-ids.h83
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-init.c211
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-remote.c175
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb-urb.c211
-rw-r--r--drivers/media/dvb/dvb-usb/dvb-usb.h315
-rw-r--r--drivers/media/dvb/dvb-usb/nova-t-usb2.c236
-rw-r--r--drivers/media/dvb/dvb-usb/umt-010.c162
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045-fe.c196
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045.c263
-rw-r--r--drivers/media/dvb/dvb-usb/vp7045.h78
-rw-r--r--drivers/media/dvb/frontends/Kconfig30
-rw-r--r--drivers/media/dvb/frontends/Makefile1
-rw-r--r--drivers/media/dvb/frontends/at76c651.c18
-rw-r--r--drivers/media/dvb/frontends/bcm3510.c853
-rw-r--r--drivers/media/dvb/frontends/bcm3510.h40
-rw-r--r--drivers/media/dvb/frontends/bcm3510_priv.h460
-rw-r--r--drivers/media/dvb/frontends/cx22700.c20
-rw-r--r--drivers/media/dvb/frontends/cx22702.c20
-rw-r--r--drivers/media/dvb/frontends/cx24110.c31
-rw-r--r--drivers/media/dvb/frontends/dib3000-common.c2
-rw-r--r--drivers/media/dvb/frontends/dib3000.h5
-rw-r--r--drivers/media/dvb/frontends/dib3000mb.c46
-rw-r--r--drivers/media/dvb/frontends/dib3000mb_priv.h2
-rw-r--r--drivers/media/dvb/frontends/dib3000mc.c53
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.c94
-rw-r--r--drivers/media/dvb/frontends/dvb-pll.h19
-rw-r--r--drivers/media/dvb/frontends/dvb_dummy_fe.c8
-rw-r--r--drivers/media/dvb/frontends/l64781.c22
-rw-r--r--drivers/media/dvb/frontends/mt312.c32
-rw-r--r--drivers/media/dvb/frontends/mt352.c40
-rw-r--r--drivers/media/dvb/frontends/mt352.h7
-rw-r--r--drivers/media/dvb/frontends/nxt2002.c22
-rw-r--r--drivers/media/dvb/frontends/nxt6000.c56
-rw-r--r--drivers/media/dvb/frontends/nxt6000_priv.h21
-rw-r--r--drivers/media/dvb/frontends/or51132.c14
-rw-r--r--drivers/media/dvb/frontends/sp8870.c20
-rw-r--r--drivers/media/dvb/frontends/sp887x.c22
-rw-r--r--drivers/media/dvb/frontends/stv0297.c24
-rw-r--r--drivers/media/dvb/frontends/stv0299.c114
-rw-r--r--drivers/media/dvb/frontends/tda10021.c22
-rw-r--r--drivers/media/dvb/frontends/tda1004x.c284
-rw-r--r--drivers/media/dvb/frontends/tda1004x.h7
-rw-r--r--drivers/media/dvb/frontends/tda8083.c26
-rw-r--r--drivers/media/dvb/frontends/tda80xx.c36
-rw-r--r--drivers/media/dvb/frontends/ves1820.c23
-rw-r--r--drivers/media/dvb/frontends/ves1x93.c24
-rw-r--r--drivers/media/dvb/ttpci/av7110.c144
-rw-r--r--drivers/media/dvb/ttpci/av7110.h3
-rw-r--r--drivers/media/dvb/ttpci/av7110_av.c12
-rw-r--r--drivers/media/dvb/ttpci/av7110_ca.c4
-rw-r--r--drivers/media/dvb/ttpci/av7110_hw.c20
-rw-r--r--drivers/media/dvb/ttpci/av7110_hw.h5
-rw-r--r--drivers/media/dvb/ttpci/av7110_ir.c2
-rw-r--r--drivers/media/dvb/ttpci/av7110_v4l.c16
-rw-r--r--drivers/media/dvb/ttpci/budget-av.c226
-rw-r--r--drivers/media/dvb/ttpci/budget-ci.c6
-rw-r--r--drivers/media/dvb/ttpci/budget-core.c12
-rw-r--r--drivers/media/dvb/ttpci/budget-patch.c4
-rw-r--r--drivers/media/dvb/ttpci/budget.c4
-rw-r--r--drivers/media/dvb/ttpci/budget.h5
-rw-r--r--drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c22
-rw-r--r--drivers/media/dvb/ttusb-dec/ttusb_dec.c28
-rw-r--r--drivers/media/video/Kconfig15
-rw-r--r--drivers/media/video/adv7170.c16
-rw-r--r--drivers/media/video/adv7175.c16
-rw-r--r--drivers/media/video/bt819.c16
-rw-r--r--drivers/media/video/bt832.c50
-rw-r--r--drivers/media/video/bt832.h36
-rw-r--r--drivers/media/video/bt856.c16
-rw-r--r--drivers/media/video/bttv-cards.c101
-rw-r--r--drivers/media/video/bttv-driver.c2
-rw-r--r--drivers/media/video/bttv-i2c.c5
-rw-r--r--drivers/media/video/bttv.h3
-rw-r--r--drivers/media/video/bttvp.h8
-rw-r--r--drivers/media/video/cx88/cx88-blackbird.c488
-rw-r--r--drivers/media/video/cx88/cx88-cards.c230
-rw-r--r--drivers/media/video/cx88/cx88-core.c28
-rw-r--r--drivers/media/video/cx88/cx88-dvb.c2
-rw-r--r--drivers/media/video/cx88/cx88-i2c.c18
-rw-r--r--drivers/media/video/cx88/cx88-input.c11
-rw-r--r--drivers/media/video/cx88/cx88-mpeg.c52
-rw-r--r--drivers/media/video/cx88/cx88-reg.h3
-rw-r--r--drivers/media/video/cx88/cx88-tvaudio.c103
-rw-r--r--drivers/media/video/cx88/cx88-vbi.c6
-rw-r--r--drivers/media/video/cx88/cx88-video.c59
-rw-r--r--drivers/media/video/cx88/cx88.h22
-rw-r--r--drivers/media/video/ir-kbd-gpio.c34
-rw-r--r--drivers/media/video/msp3400.c12
-rw-r--r--drivers/media/video/msp3400.h4
-rw-r--r--drivers/media/video/saa5246a.c1
-rw-r--r--drivers/media/video/saa5249.c1
-rw-r--r--drivers/media/video/saa7110.c16
-rw-r--r--drivers/media/video/saa7111.c16
-rw-r--r--drivers/media/video/saa7114.c16
-rw-r--r--drivers/media/video/saa7134/saa6752hs.c21
-rw-r--r--drivers/media/video/saa7134/saa7134-cards.c163
-rw-r--r--drivers/media/video/saa7134/saa7134-core.c8
-rw-r--r--drivers/media/video/saa7134/saa7134-dvb.c2
-rw-r--r--drivers/media/video/saa7134/saa7134-empress.c2
-rw-r--r--drivers/media/video/saa7134/saa7134-i2c.c2
-rw-r--r--drivers/media/video/saa7134/saa7134-input.c112
-rw-r--r--drivers/media/video/saa7134/saa7134-oss.c16
-rw-r--r--drivers/media/video/saa7134/saa7134-tvaudio.c21
-rw-r--r--drivers/media/video/saa7134/saa7134-vbi.c14
-rw-r--r--drivers/media/video/saa7134/saa7134-video.c92
-rw-r--r--drivers/media/video/saa7134/saa7134.h17
-rw-r--r--drivers/media/video/saa7185.c16
-rw-r--r--drivers/media/video/tda7432.c1
-rw-r--r--drivers/media/video/tda9840.c1
-rw-r--r--drivers/media/video/tda9875.c1
-rw-r--r--drivers/media/video/tda9887.c41
-rw-r--r--drivers/media/video/tea6415c.c1
-rw-r--r--drivers/media/video/tea6420.c1
-rw-r--r--drivers/media/video/tuner-3036.c17
-rw-r--r--drivers/media/video/tuner-core.c205
-rw-r--r--drivers/media/video/tuner-simple.c53
-rw-r--r--drivers/media/video/tvaudio.c24
-rw-r--r--drivers/media/video/tveeprom.c3
-rw-r--r--drivers/media/video/tvmixer.c4
-rw-r--r--drivers/media/video/v4l1-compat.c10
-rw-r--r--drivers/media/video/video-buf-dvb.c15
-rw-r--r--drivers/media/video/vpx3220.c16
-rw-r--r--drivers/message/fusion/Kconfig56
-rw-r--r--drivers/message/fusion/Makefile44
-rw-r--r--drivers/message/fusion/lsi/mpi.h70
-rw-r--r--drivers/message/fusion/lsi/mpi_cnfg.h1007
-rw-r--r--drivers/message/fusion/lsi/mpi_fc.h7
-rw-r--r--drivers/message/fusion/lsi/mpi_history.txt451
-rw-r--r--drivers/message/fusion/lsi/mpi_inb.h7
-rw-r--r--drivers/message/fusion/lsi/mpi_init.h88
-rw-r--r--drivers/message/fusion/lsi/mpi_ioc.h246
-rw-r--r--drivers/message/fusion/lsi/mpi_lan.h6
-rw-r--r--drivers/message/fusion/lsi/mpi_raid.h17
-rw-r--r--drivers/message/fusion/lsi/mpi_sas.h171
-rw-r--r--drivers/message/fusion/lsi/mpi_targ.h160
-rw-r--r--drivers/message/fusion/lsi/mpi_tool.h57
-rw-r--r--drivers/message/fusion/lsi/mpi_type.h11
-rw-r--r--drivers/message/fusion/mptbase.c343
-rw-r--r--drivers/message/fusion/mptbase.h52
-rw-r--r--drivers/message/fusion/mptctl.c68
-rw-r--r--drivers/message/fusion/mptctl.h15
-rw-r--r--drivers/message/fusion/mptfc.c431
-rw-r--r--drivers/message/fusion/mptlan.c37
-rw-r--r--drivers/message/fusion/mptlan.h48
-rw-r--r--drivers/message/fusion/mptscsih.c795
-rw-r--r--drivers/message/fusion/mptscsih.h43
-rw-r--r--drivers/message/fusion/mptspi.c486
-rw-r--r--drivers/message/i2o/Kconfig46
-rw-r--r--drivers/message/i2o/Makefile3
-rw-r--r--drivers/message/i2o/bus-osm.c164
-rw-r--r--drivers/message/i2o/config-osm.c579
-rw-r--r--drivers/message/i2o/core.h58
-rw-r--r--drivers/message/i2o/debug.c3
-rw-r--r--drivers/message/i2o/device.c40
-rw-r--r--drivers/message/i2o/driver.c130
-rw-r--r--drivers/message/i2o/exec-osm.c131
-rw-r--r--drivers/message/i2o/i2o_block.c454
-rw-r--r--drivers/message/i2o/i2o_block.h34
-rw-r--r--drivers/message/i2o/i2o_config.c124
-rw-r--r--drivers/message/i2o/i2o_proc.c6
-rw-r--r--drivers/message/i2o/i2o_scsi.c505
-rw-r--r--drivers/message/i2o/iop.c566
-rw-r--r--drivers/message/i2o/pci.c246
-rw-r--r--drivers/misc/ibmasm/command.c30
-rw-r--r--drivers/misc/ibmasm/dot_command.c10
-rw-r--r--drivers/misc/ibmasm/event.c18
-rw-r--r--drivers/misc/ibmasm/heartbeat.c13
-rw-r--r--drivers/misc/ibmasm/ibmasm.h76
-rw-r--r--drivers/misc/ibmasm/ibmasmfs.c125
-rw-r--r--drivers/misc/ibmasm/lowlevel.c18
-rw-r--r--drivers/misc/ibmasm/module.c69
-rw-r--r--drivers/misc/ibmasm/r_heartbeat.c2
-rw-r--r--drivers/misc/ibmasm/remote.c304
-rw-r--r--drivers/misc/ibmasm/remote.h173
-rw-r--r--drivers/mmc/Kconfig2
-rw-r--r--drivers/mmc/mmc_block.c5
-rw-r--r--drivers/mmc/mmc_sysfs.c2
-rw-r--r--drivers/mmc/wbsd.c716
-rw-r--r--drivers/mmc/wbsd.h12
-rw-r--r--drivers/net/3c59x.c5
-rw-r--r--drivers/net/8139cp.c100
-rw-r--r--drivers/net/8139too.c196
-rw-r--r--drivers/net/8390.c4
-rw-r--r--drivers/net/Kconfig57
-rw-r--r--drivers/net/Makefile7
-rw-r--r--drivers/net/Space.c6
-rwxr-xr-xdrivers/net/amd8111e.c24
-rw-r--r--drivers/net/appletalk/ltpc.c6
-rw-r--r--drivers/net/arm/etherh.c16
-rw-r--r--drivers/net/au1000_eth.c10
-rw-r--r--drivers/net/bmac.c2
-rw-r--r--drivers/net/bnx2.c5530
-rw-r--r--drivers/net/bnx2.h4352
-rw-r--r--drivers/net/bnx2_fw.h2468
-rw-r--r--drivers/net/bonding/bond_main.c2
-rw-r--r--drivers/net/dm9000.c1219
-rw-r--r--drivers/net/dm9000.h135
-rw-r--r--drivers/net/e100.c165
-rw-r--r--drivers/net/e1000/e1000.h37
-rw-r--r--drivers/net/e1000/e1000_ethtool.c105
-rw-r--r--drivers/net/e1000/e1000_hw.c1987
-rw-r--r--drivers/net/e1000/e1000_hw.h570
-rw-r--r--drivers/net/e1000/e1000_main.c1148
-rw-r--r--drivers/net/e1000/e1000_osdep.h32
-rw-r--r--drivers/net/e1000/e1000_param.c3
-rw-r--r--drivers/net/fmv18x.c689
-rw-r--r--drivers/net/forcedeth.c103
-rw-r--r--drivers/net/hamradio/6pack.c2
-rw-r--r--drivers/net/hamradio/baycom_epp.c126
-rw-r--r--drivers/net/hamradio/mkiss.c2
-rw-r--r--drivers/net/ibm_emac/ibm_emac_core.c2
-rw-r--r--drivers/net/irda/Kconfig2
-rw-r--r--drivers/net/irda/irtty-sir.c2
-rw-r--r--drivers/net/irda/sir_kthread.c3
-rw-r--r--drivers/net/irda/stir4200.c4
-rw-r--r--drivers/net/iseries_veth.c41
-rw-r--r--drivers/net/ixgb/ixgb.h2
-rw-r--r--drivers/net/ixgb/ixgb_ee.c24
-rw-r--r--drivers/net/ixgb/ixgb_ethtool.c4
-rw-r--r--drivers/net/ixgb/ixgb_main.c154
-rw-r--r--drivers/net/ixgb/ixgb_osdep.h3
-rw-r--r--drivers/net/natsemi.c6
-rw-r--r--drivers/net/ns83820.c69
-rw-r--r--drivers/net/pcmcia/3c574_cs.c3
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c17
-rw-r--r--drivers/net/pcnet32.c7
-rw-r--r--drivers/net/ppp_async.c2
-rw-r--r--drivers/net/ppp_generic.c191
-rw-r--r--drivers/net/ppp_synctty.c2
-rw-r--r--drivers/net/r8169.c345
-rw-r--r--drivers/net/shaper.c86
-rw-r--r--drivers/net/sis900.c52
-rw-r--r--drivers/net/sk98lin/skge.c8
-rw-r--r--drivers/net/sk_g16.c2066
-rw-r--r--drivers/net/sk_g16.h165
-rw-r--r--drivers/net/skge.c3386
-rw-r--r--drivers/net/skge.h3005
-rw-r--r--drivers/net/slip.c16
-rw-r--r--drivers/net/smc91x.c58
-rw-r--r--drivers/net/smc91x.h15
-rw-r--r--drivers/net/starfire.c142
-rw-r--r--drivers/net/starfire_firmware.h346
-rw-r--r--drivers/net/tg3.c1383
-rw-r--r--drivers/net/tg3.h32
-rw-r--r--drivers/net/tlan.c16
-rw-r--r--drivers/net/tokenring/ibmtr.c11
-rw-r--r--drivers/net/tulip/media.c1
-rw-r--r--drivers/net/tulip/tulip_core.c2
-rw-r--r--drivers/net/wan/Kconfig2
-rw-r--r--drivers/net/wan/cosa.c12
-rw-r--r--drivers/net/wan/hdlc_fr.c320
-rw-r--r--drivers/net/wan/hdlc_generic.c16
-rw-r--r--drivers/net/wan/lmc/lmc_main.c8
-rw-r--r--drivers/net/wan/x25_asy.c2
-rw-r--r--drivers/net/wireless/Kconfig2
-rw-r--r--drivers/net/wireless/airo.c152
-rw-r--r--drivers/net/wireless/atmel_cs.c1
-rw-r--r--drivers/net/wireless/orinoco.c332
-rw-r--r--drivers/net/wireless/orinoco.h1
-rw-r--r--drivers/net/wireless/strip.c2
-rw-r--r--drivers/oprofile/buffer_sync.c33
-rw-r--r--drivers/oprofile/event_buffer.h3
-rw-r--r--drivers/parport/parport_pc.c4
-rw-r--r--drivers/parport/parport_serial.c5
-rw-r--r--drivers/parport/probe.c18
-rw-r--r--drivers/pci/hotplug.c119
-rw-r--r--drivers/pci/hotplug/cpci_hotplug.h2
-rw-r--r--drivers/pci/hotplug/cpci_hotplug_core.c429
-rw-r--r--drivers/pci/hotplug/cpci_hotplug_pci.c483
-rw-r--r--drivers/pci/hotplug/cpqphp_sysfs.c4
-rw-r--r--drivers/pci/hotplug/pci_hotplug_core.c4
-rw-r--r--drivers/pci/hotplug/pciehp.h1
-rw-r--r--drivers/pci/hotplug/pciehp_core.c2
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c156
-rw-r--r--drivers/pci/hotplug/rpadlpar_sysfs.c2
-rw-r--r--drivers/pci/hotplug/shpchp_core.c2
-rw-r--r--drivers/pci/hotplug/shpchp_ctrl.c30
-rw-r--r--drivers/pci/hotplug/shpchp_sysfs.c4
-rw-r--r--drivers/pci/hotplug/shpchprm_acpi.c4
-rw-r--r--drivers/pci/pci-driver.c31
-rw-r--r--drivers/pci/pci-sysfs.c31
-rw-r--r--drivers/pci/pci.h27
-rw-r--r--drivers/pci/pci.ids1
-rw-r--r--drivers/pci/pcie/portdrv_bus.c3
-rw-r--r--drivers/pci/pcie/portdrv_core.c139
-rw-r--r--drivers/pci/probe.c2
-rw-r--r--drivers/pci/quirks.c59
-rw-r--r--drivers/pcmcia/Kconfig6
-rw-r--r--drivers/pcmcia/cs.c13
-rw-r--r--drivers/pcmcia/ds.c8
-rw-r--r--drivers/pcmcia/m32r_cfc.c57
-rw-r--r--drivers/pcmcia/m32r_cfc.h8
-rw-r--r--drivers/pcmcia/ti113x.h167
-rw-r--r--drivers/pcmcia/yenta_socket.c60
-rw-r--r--drivers/pnp/card.c7
-rw-r--r--drivers/pnp/driver.c12
-rw-r--r--drivers/pnp/interface.c8
-rw-r--r--drivers/pnp/manager.c1
-rw-r--r--drivers/pnp/pnpbios/core.c2
-rw-r--r--drivers/s390/Kconfig7
-rw-r--r--drivers/s390/block/dasd.c46
-rw-r--r--drivers/s390/block/dasd_devmap.c10
-rw-r--r--drivers/s390/block/dasd_proc.c3
-rw-r--r--drivers/s390/block/dcssblk.c72
-rw-r--r--drivers/s390/char/Makefile1
-rw-r--r--drivers/s390/char/con3215.c4
-rw-r--r--drivers/s390/char/con3270.c4
-rw-r--r--drivers/s390/char/raw3270.c6
-rw-r--r--drivers/s390/char/tape_34xx.c6
-rw-r--r--drivers/s390/char/tape_class.c10
-rw-r--r--drivers/s390/char/tape_core.c12
-rw-r--r--drivers/s390/char/tape_proc.c1
-rw-r--r--drivers/s390/char/vmcp.c219
-rw-r--r--drivers/s390/char/vmcp.h30
-rw-r--r--drivers/s390/char/vmlogrdr.c32
-rw-r--r--drivers/s390/cio/blacklist.c6
-rw-r--r--drivers/s390/cio/ccwgroup.c36
-rw-r--r--drivers/s390/cio/chsc.c6
-rw-r--r--drivers/s390/cio/cio.c8
-rw-r--r--drivers/s390/cio/cmf.c12
-rw-r--r--drivers/s390/cio/css.c34
-rw-r--r--drivers/s390/cio/device.c98
-rw-r--r--drivers/s390/cio/qdio.c14
-rw-r--r--drivers/s390/cio/qdio.h16
-rw-r--r--drivers/s390/net/Makefile3
-rw-r--r--drivers/s390/net/claw.c44
-rw-r--r--drivers/s390/net/ctcdbug.c10
-rw-r--r--drivers/s390/net/ctcdbug.h18
-rw-r--r--drivers/s390/net/ctcmain.c634
-rw-r--r--drivers/s390/net/ctcmain.h276
-rw-r--r--drivers/s390/net/ctctty.c5
-rw-r--r--drivers/s390/net/cu3088.c4
-rw-r--r--drivers/s390/net/cu3088.h3
-rw-r--r--drivers/s390/net/iucv.c10
-rw-r--r--drivers/s390/net/iucv.h6
-rw-r--r--drivers/s390/net/lcs.c47
-rw-r--r--drivers/s390/net/netiucv.c56
-rw-r--r--drivers/s390/net/qeth.h49
-rw-r--r--drivers/s390/net/qeth_eddp.c51
-rw-r--r--drivers/s390/net/qeth_main.c330
-rw-r--r--drivers/s390/net/qeth_sys.c126
-rw-r--r--drivers/s390/net/qeth_tso.c285
-rw-r--r--drivers/s390/net/qeth_tso.h166
-rw-r--r--drivers/s390/net/smsgiucv.c4
-rw-r--r--drivers/s390/s390mach.c321
-rw-r--r--drivers/s390/s390mach.h35
-rw-r--r--drivers/s390/scsi/zfcp_aux.c37
-rw-r--r--drivers/s390/scsi/zfcp_def.h25
-rw-r--r--drivers/s390/scsi/zfcp_erp.c121
-rw-r--r--drivers/s390/scsi/zfcp_ext.h4
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c324
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c68
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c26
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_adapter.c10
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_port.c10
-rw-r--r--drivers/s390/scsi/zfcp_sysfs_unit.c6
-rw-r--r--drivers/sbus/char/aurora.c8
-rw-r--r--drivers/scsi/3w-9xxx.c3
-rw-r--r--drivers/scsi/3w-xxxx.c3
-rw-r--r--drivers/scsi/53c700.c28
-rw-r--r--drivers/scsi/BusLogic.c8
-rw-r--r--drivers/scsi/FlashPoint.c5676
-rw-r--r--drivers/scsi/Kconfig42
-rw-r--r--drivers/scsi/Makefile3
-rw-r--r--drivers/scsi/NCR5380.c42
-rw-r--r--drivers/scsi/NCR5380.h2
-rw-r--r--drivers/scsi/NCR53C9x.c6
-rw-r--r--drivers/scsi/NCR53c406a.c23
-rw-r--r--drivers/scsi/a2091.c7
-rw-r--r--drivers/scsi/a3000.c7
-rw-r--r--drivers/scsi/aacraid/aachba.c165
-rw-r--r--drivers/scsi/aacraid/aacraid.h468
-rw-r--r--drivers/scsi/aacraid/commctrl.c228
-rw-r--r--drivers/scsi/aacraid/comminit.c92
-rw-r--r--drivers/scsi/aacraid/commsup.c100
-rw-r--r--drivers/scsi/aacraid/dpcsup.c6
-rw-r--r--drivers/scsi/aacraid/linit.c179
-rw-r--r--drivers/scsi/aacraid/rkt.c43
-rw-r--r--drivers/scsi/aacraid/rx.c46
-rw-r--r--drivers/scsi/aacraid/sa.c35
-rw-r--r--drivers/scsi/aha152x.c2
-rw-r--r--drivers/scsi/aha1542.c22
-rw-r--r--drivers/scsi/aha1542.h1
-rw-r--r--drivers/scsi/ahci.c103
-rw-r--r--drivers/scsi/aic7xxx/aic7770_osm.c241
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.c14
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.h17
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx.h2
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_core.c16
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.c1863
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.h231
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm_pci.c55
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_proc.c44
-rw-r--r--drivers/scsi/aic7xxx/aiclib.c1
-rw-r--r--drivers/scsi/aic7xxx_old.c33
-rw-r--r--drivers/scsi/arm/cumana_1.c2
-rw-r--r--drivers/scsi/arm/ecoscsi.c2
-rw-r--r--drivers/scsi/arm/eesox.c4
-rw-r--r--drivers/scsi/arm/fas216.c3
-rw-r--r--drivers/scsi/arm/oak.c2
-rw-r--r--drivers/scsi/arm/powertec.c4
-rw-r--r--drivers/scsi/ata_piix.c18
-rw-r--r--drivers/scsi/atp870u.c4
-rw-r--r--drivers/scsi/ch.c1026
-rw-r--r--drivers/scsi/dc395x.c12
-rw-r--r--drivers/scsi/dmx3191d.c2
-rw-r--r--drivers/scsi/dpt_i2o.c89
-rw-r--r--drivers/scsi/dpti.h14
-rw-r--r--drivers/scsi/dtc.c2
-rw-r--r--drivers/scsi/dtc.h4
-rw-r--r--drivers/scsi/eata.c11
-rw-r--r--drivers/scsi/eata_pio.c5
-rw-r--r--drivers/scsi/fcal.c1
-rw-r--r--drivers/scsi/fd_mcs.c17
-rw-r--r--drivers/scsi/fdomain.c6
-rw-r--r--drivers/scsi/g_NCR5380.c2
-rw-r--r--drivers/scsi/g_NCR5380.h4
-rw-r--r--drivers/scsi/gdth.c23
-rw-r--r--drivers/scsi/gvp11.c8
-rw-r--r--drivers/scsi/hosts.c2
-rw-r--r--drivers/scsi/ibmmca.c28
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c4
-rw-r--r--drivers/scsi/ide-scsi.c97
-rw-r--r--drivers/scsi/imm.c9
-rw-r--r--drivers/scsi/in2000.c31
-rw-r--r--drivers/scsi/in2000.h2
-rw-r--r--drivers/scsi/initio.c89
-rw-r--r--drivers/scsi/initio.h18
-rw-r--r--drivers/scsi/ipr.c57
-rw-r--r--drivers/scsi/ipr.h4
-rw-r--r--drivers/scsi/ips.c21
-rw-r--r--drivers/scsi/libata-core.c547
-rw-r--r--drivers/scsi/libata-scsi.c7
-rw-r--r--drivers/scsi/libata.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c36
-rw-r--r--drivers/scsi/mac53c94.c11
-rw-r--r--drivers/scsi/mac_scsi.c2
-rw-r--r--drivers/scsi/mac_scsi.h2
-rw-r--r--drivers/scsi/megaraid.c14
-rw-r--r--drivers/scsi/megaraid/mega_common.h1
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.c160
-rw-r--r--drivers/scsi/megaraid/megaraid_mbox.h64
-rw-r--r--drivers/scsi/megaraid/megaraid_mm.c9
-rw-r--r--drivers/scsi/megaraid/megaraid_mm.h4
-rw-r--r--drivers/scsi/mesh.c4
-rw-r--r--drivers/scsi/mvme147.c7
-rw-r--r--drivers/scsi/nsp32.c7
-rw-r--r--drivers/scsi/osst.c10
-rw-r--r--drivers/scsi/pas16.c2
-rw-r--r--drivers/scsi/pas16.h4
-rw-r--r--drivers/scsi/pci2000.c836
-rw-r--r--drivers/scsi/pci2220i.c2915
-rw-r--r--drivers/scsi/pci2220i.h39
-rw-r--r--drivers/scsi/pcmcia/nsp_cs.c15
-rw-r--r--drivers/scsi/pcmcia/qlogic_stub.c2
-rw-r--r--drivers/scsi/pcmcia/sym53c500_cs.c2
-rw-r--r--drivers/scsi/pluto.c1
-rw-r--r--drivers/scsi/ppa.c5
-rw-r--r--drivers/scsi/psi_dale.h564
-rw-r--r--drivers/scsi/psi_roy.h331
-rw-r--r--drivers/scsi/ql1040_fw.h4021
-rw-r--r--drivers/scsi/ql12160_fw.h3046
-rw-r--r--drivers/scsi/ql1280_fw.h3653
-rw-r--r--drivers/scsi/qla1280.c41
-rw-r--r--drivers/scsi/qla2xxx/qla_dbg.c3
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h60
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h14
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c33
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c3
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c18
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c6
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c173
-rw-r--r--drivers/scsi/qlogicfas.c2
-rw-r--r--drivers/scsi/qlogicfas408.c26
-rw-r--r--drivers/scsi/qlogicfas408.h2
-rw-r--r--drivers/scsi/sata_nv.c2
-rw-r--r--drivers/scsi/sata_promise.c29
-rw-r--r--drivers/scsi/sata_qstor.c2
-rw-r--r--drivers/scsi/sata_sil.c10
-rw-r--r--drivers/scsi/sata_sis.c1
-rw-r--r--drivers/scsi/sata_svw.c30
-rw-r--r--drivers/scsi/sata_sx4.c2
-rw-r--r--drivers/scsi/sata_uli.c1
-rw-r--r--drivers/scsi/sata_via.c1
-rw-r--r--drivers/scsi/sata_vsc.c2
-rw-r--r--drivers/scsi/scsi.c16
-rw-r--r--drivers/scsi/scsi_debug.c2
-rw-r--r--drivers/scsi/scsi_error.c42
-rw-r--r--drivers/scsi/scsi_lib.c42
-rw-r--r--drivers/scsi/scsi_priv.h4
-rw-r--r--drivers/scsi/scsi_scan.c26
-rw-r--r--drivers/scsi/scsi_sysfs.c46
-rw-r--r--drivers/scsi/scsi_transport_spi.c277
-rw-r--r--drivers/scsi/sd.c36
-rw-r--r--drivers/scsi/seagate.c15
-rw-r--r--drivers/scsi/seagate.h2
-rw-r--r--drivers/scsi/sg.c16
-rw-r--r--drivers/scsi/sgiwd93.c7
-rw-r--r--drivers/scsi/st.c47
-rw-r--r--drivers/scsi/sun3x_esp.c2
-rw-r--r--drivers/scsi/sym53c416.c23
-rw-r--r--drivers/scsi/sym53c416.h3
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_defs.h2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c152
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.h27
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.c65
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.h22
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_nvram.c7
-rw-r--r--drivers/scsi/t128.c2
-rw-r--r--drivers/scsi/t128.h4
-rw-r--r--drivers/scsi/tmscsim.c6
-rw-r--r--drivers/scsi/u14-34f.c8
-rw-r--r--drivers/scsi/ultrastor.c4
-rw-r--r--drivers/scsi/wd7000.c9
-rw-r--r--drivers/serial/21285.c14
-rw-r--r--drivers/serial/68328serial.c9
-rw-r--r--drivers/serial/68360serial.c9
-rw-r--r--drivers/serial/8250.c96
-rw-r--r--drivers/serial/8250.h3
-rw-r--r--drivers/serial/Kconfig11
-rw-r--r--drivers/serial/Makefile2
-rw-r--r--drivers/serial/amba-pl010.c14
-rw-r--r--drivers/serial/amba-pl011.c14
-rw-r--r--drivers/serial/au1x00_uart.c10
-rw-r--r--drivers/serial/clps711x.c5
-rw-r--r--drivers/serial/cpm_uart/cpm_uart_cpm2.c9
-rw-r--r--drivers/serial/icom.h2
-rw-r--r--drivers/serial/ioc4_serial.c336
-rw-r--r--drivers/serial/m32r_sio.c10
-rw-r--r--drivers/serial/mpsc.c8
-rw-r--r--drivers/serial/pxa.c26
-rw-r--r--drivers/serial/s3c2410.c19
-rw-r--r--drivers/serial/sa1100.c7
-rw-r--r--drivers/serial/serial_cs.c4
-rw-r--r--drivers/serial/serial_lh7a40x.c13
-rw-r--r--drivers/serial/serial_txx9.c15
-rw-r--r--drivers/serial/sn_console.c1
-rw-r--r--drivers/serial/sunsab.c109
-rw-r--r--drivers/serial/sunsab.h1
-rw-r--r--drivers/serial/sunzilog.c8
-rw-r--r--drivers/serial/vr41xx_siu.c72
-rw-r--r--drivers/sh/superhyway/superhyway-sysfs.c2
-rw-r--r--drivers/sn/Kconfig20
-rw-r--r--drivers/sn/Makefile2
-rw-r--r--drivers/sn/ioc4.c418
-rw-r--r--drivers/telephony/ixj.c52
-rw-r--r--drivers/usb/atm/speedtch.c2
-rw-r--r--drivers/usb/core/devices.c2
-rw-r--r--drivers/usb/core/file.c13
-rw-r--r--drivers/usb/core/hcd.c63
-rw-r--r--drivers/usb/core/hcd.h2
-rw-r--r--drivers/usb/core/hub.c2
-rw-r--r--drivers/usb/core/inode.c13
-rw-r--r--drivers/usb/core/sysfs.c56
-rw-r--r--drivers/usb/core/usb.c53
-rw-r--r--drivers/usb/gadget/dummy_hcd.c4
-rw-r--r--drivers/usb/gadget/file_storage.c11
-rw-r--r--drivers/usb/gadget/net2280.c6
-rw-r--r--drivers/usb/gadget/pxa2xx_udc.c2
-rw-r--r--drivers/usb/host/Kconfig11
-rw-r--r--drivers/usb/host/Makefile1
-rw-r--r--drivers/usb/host/ehci-dbg.c10
-rw-r--r--drivers/usb/host/ehci-hub.c6
-rw-r--r--drivers/usb/host/ohci-dbg.c10
-rw-r--r--drivers/usb/host/sl811-hcd.c146
-rw-r--r--drivers/usb/host/sl811_cs.c442
-rw-r--r--drivers/usb/input/aiptek.c78
-rw-r--r--drivers/usb/input/hid-core.c22
-rw-r--r--drivers/usb/media/pwc/ChangeLog143
-rw-r--r--drivers/usb/media/pwc/Makefile2
-rw-r--r--drivers/usb/media/pwc/pwc-ctrl.c14
-rw-r--r--drivers/usb/media/pwc/pwc-dec1.c42
-rw-r--r--drivers/usb/media/pwc/pwc-dec1.h36
-rw-r--r--drivers/usb/media/pwc/pwc-dec23.c623
-rw-r--r--drivers/usb/media/pwc/pwc-dec23.h58
-rw-r--r--drivers/usb/media/pwc/pwc-if.c13
-rw-r--r--drivers/usb/media/pwc/pwc-kiara.c573
-rw-r--r--drivers/usb/media/pwc/pwc-timon.c1130
-rw-r--r--drivers/usb/media/pwc/pwc-uncompress.c11
-rw-r--r--drivers/usb/misc/cytherm.c20
-rw-r--r--drivers/usb/misc/phidgetkit.c14
-rw-r--r--drivers/usb/misc/phidgetservo.c4
-rw-r--r--drivers/usb/misc/usbled.c4
-rw-r--r--drivers/usb/mon/Kconfig13
-rw-r--r--drivers/usb/mon/Makefile2
-rw-r--r--drivers/usb/net/Kconfig14
-rw-r--r--drivers/usb/net/kaweth.c2
-rw-r--r--drivers/usb/net/usbnet.c53
-rw-r--r--drivers/usb/serial/Kconfig11
-rw-r--r--drivers/usb/serial/Makefile1
-rw-r--r--drivers/usb/serial/cp2101.c363
-rw-r--r--drivers/usb/serial/cypress_m8.c2
-rw-r--r--drivers/usb/serial/cypress_m8.h1
-rw-r--r--drivers/usb/serial/ftdi_sio.c127
-rw-r--r--drivers/usb/serial/ftdi_sio.h2
-rw-r--r--drivers/usb/serial/option.c729
-rw-r--r--drivers/usb/serial/usb-serial.c20
-rw-r--r--drivers/usb/storage/scsiglue.c13
-rw-r--r--drivers/usb/storage/unusual_devs.h9
-rw-r--r--drivers/usb/storage/usb.c4
-rw-r--r--drivers/video/Kconfig16
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/arcfb.c684
-rw-r--r--drivers/video/aty/radeon_base.c7
-rw-r--r--drivers/video/au1100fb.c18
-rw-r--r--drivers/video/chipsfb.c3
-rw-r--r--drivers/video/console/Kconfig16
-rw-r--r--drivers/video/console/Makefile2
-rw-r--r--drivers/video/console/bitblit.c23
-rw-r--r--drivers/video/console/font_10x18.c5146
-rw-r--r--drivers/video/console/font_7x14.c4118
-rw-r--r--drivers/video/console/font_sun12x22.c1579
-rw-r--r--drivers/video/console/fonts.c8
-rw-r--r--drivers/video/console/vgacon.c17
-rw-r--r--drivers/video/fbmem.c77
-rw-r--r--drivers/video/fbsysfs.c4
-rw-r--r--drivers/video/gbefb.c4
-rw-r--r--drivers/video/i810/i810_main.c1
-rw-r--r--drivers/video/intelfb/intelfbdrv.c45
-rw-r--r--drivers/video/macmodes.c1
-rw-r--r--drivers/video/matrox/matroxfb_maven.c1
-rw-r--r--drivers/video/matrox/matroxfb_misc.c5
-rw-r--r--drivers/video/nvidia/nvidia.c18
-rw-r--r--drivers/video/pm3fb.c2
-rw-r--r--drivers/video/pxafb.c3
-rw-r--r--drivers/video/riva/fbdev.c19
-rw-r--r--drivers/video/s1d13xxxfb.c2
-rw-r--r--drivers/video/savage/savagefb_driver.c2
-rw-r--r--drivers/video/softcursor.c9
-rw-r--r--drivers/video/vesafb.c17
-rw-r--r--drivers/video/w100fb.c12
-rw-r--r--drivers/w1/Kconfig16
-rw-r--r--drivers/w1/ds_w1_bridge.c4
-rw-r--r--drivers/w1/matrox_w1.c10
-rw-r--r--drivers/w1/w1.c564
-rw-r--r--drivers/w1/w1.h113
-rw-r--r--drivers/w1/w1_family.c10
-rw-r--r--drivers/w1/w1_family.h20
-rw-r--r--drivers/w1/w1_int.c41
-rw-r--r--drivers/w1/w1_int.h6
-rw-r--r--drivers/w1/w1_io.c117
-rw-r--r--drivers/w1/w1_io.h9
-rw-r--r--drivers/w1/w1_log.h4
-rw-r--r--drivers/w1/w1_netlink.h4
-rw-r--r--drivers/w1/w1_smem.c54
-rw-r--r--drivers/w1/w1_therm.c104
-rw-r--r--drivers/zorro/zorro-sysfs.c4
-rw-r--r--fs/Kconfig110
-rw-r--r--fs/Makefile1
-rw-r--r--fs/afs/kafsasyncd.c2
-rw-r--r--fs/afs/kafstimod.c2
-rw-r--r--fs/autofs4/autofs_i.h13
-rw-r--r--fs/autofs4/expire.c5
-rw-r--r--fs/autofs4/root.c15
-rw-r--r--fs/autofs4/waitq.c7
-rw-r--r--fs/binfmt_aout.c1
-rw-r--r--fs/binfmt_elf.c7
-rw-r--r--fs/binfmt_flat.c6
-rw-r--r--fs/block_dev.c5
-rw-r--r--fs/buffer.c67
-rw-r--r--fs/char_dev.c13
-rw-r--r--fs/cifs/CHANGES3
-rw-r--r--fs/cifs/README4
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/cifsproto.h2
-rw-r--r--fs/cifs/cifssmb.c56
-rw-r--r--fs/cifs/dir.c3
-rw-r--r--fs/cifs/file.c2
-rw-r--r--fs/cifs/inode.c48
-rw-r--r--fs/cifs/misc.c1
-rw-r--r--fs/coda/psdev.c18
-rw-r--r--fs/debugfs/file.c67
-rw-r--r--fs/debugfs/inode.c12
-rw-r--r--fs/direct-io.c2
-rw-r--r--fs/dquot.c23
-rw-r--r--fs/eventpoll.c195
-rw-r--r--fs/exec.c39
-rw-r--r--fs/ext2/Makefile1
-rw-r--r--fs/ext2/acl.c12
-rw-r--r--fs/ext2/acl.h2
-rw-r--r--fs/ext2/ext2.h2
-rw-r--r--fs/ext2/file.c14
-rw-r--r--fs/ext2/inode.c31
-rw-r--r--fs/ext2/namei.c12
-rw-r--r--fs/ext2/super.c27
-rw-r--r--fs/ext2/xip.c80
-rw-r--r--fs/ext2/xip.h25
-rw-r--r--fs/ext3/acl.c17
-rw-r--r--fs/ext3/acl.h2
-rw-r--r--fs/ext3/inode.c7
-rw-r--r--fs/ext3/namei.c37
-rw-r--r--fs/ext3/super.c65
-rw-r--r--fs/ext3/xattr.c2
-rw-r--r--fs/file_table.c57
-rw-r--r--fs/fs-writeback.c64
-rw-r--r--fs/hostfs/hostfs_kern.c1
-rw-r--r--fs/hugetlbfs/inode.c3
-rw-r--r--fs/inode.c16
-rw-r--r--fs/isofs/dir.c17
-rw-r--r--fs/isofs/inode.c128
-rw-r--r--fs/isofs/isofs.h2
-rw-r--r--fs/isofs/namei.c16
-rw-r--r--fs/isofs/rock.c962
-rw-r--r--fs/isofs/rock.h183
-rw-r--r--fs/jbd/checkpoint.c5
-rw-r--r--fs/jbd/journal.c4
-rw-r--r--fs/jffs/intrep.c114
-rw-r--r--fs/jffs/intrep.h2
-rw-r--r--fs/jffs/jffs_fm.c105
-rw-r--r--fs/jffs/jffs_fm.h3
-rw-r--r--fs/jffs2/background.c2
-rw-r--r--fs/jfs/acl.c17
-rw-r--r--fs/jfs/file.c9
-rw-r--r--fs/jfs/inode.c11
-rw-r--r--fs/jfs/jfs_acl.h2
-rw-r--r--fs/jfs/jfs_debug.c10
-rw-r--r--fs/jfs/jfs_debug.h15
-rw-r--r--fs/jfs/jfs_dmap.c9
-rw-r--r--fs/jfs/jfs_dtree.c3
-rw-r--r--fs/jfs/jfs_extent.c7
-rw-r--r--fs/jfs/jfs_imap.c6
-rw-r--r--fs/jfs/jfs_inode.c1
-rw-r--r--fs/jfs/jfs_inode.h19
-rw-r--r--fs/jfs/jfs_logmgr.c18
-rw-r--r--fs/jfs/jfs_logmgr.h2
-rw-r--r--fs/jfs/jfs_metapage.c6
-rw-r--r--fs/jfs/jfs_metapage.h6
-rw-r--r--fs/jfs/jfs_superblock.h11
-rw-r--r--fs/jfs/jfs_txnmgr.c48
-rw-r--r--fs/jfs/jfs_txnmgr.h52
-rw-r--r--fs/jfs/namei.c28
-rw-r--r--fs/jfs/super.c38
-rw-r--r--fs/jfs/symlink.c3
-rw-r--r--fs/jfs/xattr.c13
-rw-r--r--fs/libfs.c101
-rw-r--r--fs/lockd/clntlock.c113
-rw-r--r--fs/lockd/clntproc.c42
-rw-r--r--fs/lockd/host.c8
-rw-r--r--fs/lockd/mon.c7
-rw-r--r--fs/lockd/svc.c4
-rw-r--r--fs/locks.c6
-rw-r--r--fs/mpage.c5
-rw-r--r--fs/namei.c174
-rw-r--r--fs/namespace.c2
-rw-r--r--fs/ncpfs/dir.c13
-rw-r--r--fs/ncpfs/ncplib_kernel.c40
-rw-r--r--fs/ncpfs/ncplib_kernel.h3
-rw-r--r--fs/nfs/Makefile1
-rw-r--r--fs/nfs/callback.c1
-rw-r--r--fs/nfs/callback_proc.c1
-rw-r--r--fs/nfs/callback_xdr.c2
-rw-r--r--fs/nfs/delegation.c1
-rw-r--r--fs/nfs/dir.c209
-rw-r--r--fs/nfs/direct.c7
-rw-r--r--fs/nfs/file.c88
-rw-r--r--fs/nfs/idmap.c1
-rw-r--r--fs/nfs/inode.c427
-rw-r--r--fs/nfs/mount_clnt.c4
-rw-r--r--fs/nfs/nfs3acl.c403
-rw-r--r--fs/nfs/nfs3proc.c43
-rw-r--r--fs/nfs/nfs3xdr.c147
-rw-r--r--fs/nfs/nfs4_fs.h253
-rw-r--r--fs/nfs/nfs4proc.c429
-rw-r--r--fs/nfs/nfs4renewd.c1
-rw-r--r--fs/nfs/nfs4state.c193
-rw-r--r--fs/nfs/nfs4xdr.c241
-rw-r--r--fs/nfs/nfsroot.c9
-rw-r--r--fs/nfs/pagelist.c142
-rw-r--r--fs/nfs/proc.c1
-rw-r--r--fs/nfs/read.c3
-rw-r--r--fs/nfs/write.c108
-rw-r--r--fs/nfs_common/Makefile7
-rw-r--r--fs/nfs_common/nfsacl.c257
-rw-r--r--fs/nfsd/Makefile4
-rw-r--r--fs/nfsd/nfs2acl.c336
-rw-r--r--fs/nfsd/nfs3acl.c267
-rw-r--r--fs/nfsd/nfs3xdr.c13
-rw-r--r--fs/nfsd/nfs4acl.c4
-rw-r--r--fs/nfsd/nfs4callback.c17
-rw-r--r--fs/nfsd/nfs4idmap.c12
-rw-r--r--fs/nfsd/nfs4proc.c26
-rw-r--r--fs/nfsd/nfs4recover.c431
-rw-r--r--fs/nfsd/nfs4state.c1028
-rw-r--r--fs/nfsd/nfs4xdr.c11
-rw-r--r--fs/nfsd/nfsctl.c28
-rw-r--r--fs/nfsd/nfsproc.c1
-rw-r--r--fs/nfsd/nfssvc.c30
-rw-r--r--fs/nfsd/nfsxdr.c11
-rw-r--r--fs/nfsd/vfs.c116
-rw-r--r--fs/open.c45
-rw-r--r--fs/partitions/Makefile1
-rw-r--r--fs/partitions/check.c3
-rw-r--r--fs/partitions/check.h4
-rw-r--r--fs/partitions/msdos.c4
-rw-r--r--fs/proc/Makefile1
-rw-r--r--fs/proc/base.c6
-rw-r--r--fs/proc/mmu.c14
-rw-r--r--fs/proc/proc_devtree.c105
-rw-r--r--fs/proc/proc_misc.c22
-rw-r--r--fs/proc/vmcore.c669
-rw-r--r--fs/qnx4/dir.c2
-rw-r--r--fs/qnx4/inode.c4
-rw-r--r--fs/quota.c60
-rw-r--r--fs/read_write.c20
-rw-r--r--fs/reiserfs/file.c4
-rw-r--r--fs/reiserfs/inode.c28
-rw-r--r--fs/reiserfs/journal.c2
-rw-r--r--fs/reiserfs/namei.c25
-rw-r--r--fs/reiserfs/stree.c3
-rw-r--r--fs/reiserfs/super.c106
-rw-r--r--fs/reiserfs/xattr_acl.c26
-rw-r--r--fs/super.c84
-rw-r--r--fs/sysfs/bin.c4
-rw-r--r--fs/sysfs/dir.c31
-rw-r--r--fs/sysfs/file.c16
-rw-r--r--fs/sysfs/group.c4
-rw-r--r--fs/sysfs/inode.c112
-rw-r--r--fs/sysfs/mount.c4
-rw-r--r--fs/sysfs/symlink.c8
-rw-r--r--fs/sysfs/sysfs.h5
-rw-r--r--fs/udf/udftime.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c4
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c157
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.h1
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c34
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl.c11
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.c29
-rw-r--r--fs/xfs/linux-2.6/xfs_ioctl32.h6
-rw-r--r--fs/xfs/linux-2.6/xfs_linux.h12
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c34
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.h2
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c17
-rw-r--r--fs/xfs/linux-2.6/xfs_vfs.h1
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.c4
-rw-r--r--fs/xfs/linux-2.6/xfs_vnode.h2
-rw-r--r--fs/xfs/quota/xfs_dquot.c105
-rw-r--r--fs/xfs/quota/xfs_dquot.h30
-rw-r--r--fs/xfs/quota/xfs_dquot_item.c6
-rw-r--r--fs/xfs/quota/xfs_qm.c202
-rw-r--r--fs/xfs/quota/xfs_qm.h16
-rw-r--r--fs/xfs/quota/xfs_qm_bhv.c43
-rw-r--r--fs/xfs/quota/xfs_qm_syscalls.c175
-rw-r--r--fs/xfs/quota/xfs_quota_priv.h15
-rw-r--r--fs/xfs/quota/xfs_trans_dquot.c60
-rw-r--r--fs/xfs/support/debug.c1
-rw-r--r--fs/xfs/support/debug.h7
-rw-r--r--fs/xfs/xfs_alloc.c4
-rw-r--r--fs/xfs/xfs_attr.c17
-rw-r--r--fs/xfs/xfs_attr.h7
-rw-r--r--fs/xfs/xfs_attr_leaf.c28
-rw-r--r--fs/xfs/xfs_attr_leaf.h12
-rw-r--r--fs/xfs/xfs_bit.c2
-rw-r--r--fs/xfs/xfs_bmap.c127
-rw-r--r--fs/xfs/xfs_bmap.h13
-rw-r--r--fs/xfs/xfs_bmap_btree.c14
-rw-r--r--fs/xfs/xfs_bmap_btree.h8
-rw-r--r--fs/xfs/xfs_btree.c12
-rw-r--r--fs/xfs/xfs_btree.h10
-rw-r--r--fs/xfs/xfs_buf_item.c24
-rw-r--r--fs/xfs/xfs_buf_item.h2
-rw-r--r--fs/xfs/xfs_da_btree.c9
-rw-r--r--fs/xfs/xfs_da_btree.h3
-rw-r--r--fs/xfs/xfs_dfrag.c7
-rw-r--r--fs/xfs/xfs_dir2_data.c2
-rw-r--r--fs/xfs/xfs_dir2_data.h4
-rw-r--r--fs/xfs/xfs_dir2_leaf.c8
-rw-r--r--fs/xfs/xfs_dir2_leaf.h7
-rw-r--r--fs/xfs/xfs_dir_leaf.c6
-rw-r--r--fs/xfs/xfs_dir_leaf.h2
-rw-r--r--fs/xfs/xfs_dmapi.h19
-rw-r--r--fs/xfs/xfs_error.c2
-rw-r--r--fs/xfs/xfs_error.h3
-rw-r--r--fs/xfs/xfs_extfree_item.c126
-rw-r--r--fs/xfs/xfs_extfree_item.h2
-rw-r--r--fs/xfs/xfs_fs.h3
-rw-r--r--fs/xfs/xfs_fsops.c26
-rw-r--r--fs/xfs/xfs_ialloc_btree.h8
-rw-r--r--fs/xfs/xfs_inode.c185
-rw-r--r--fs/xfs/xfs_inode.h9
-rw-r--r--fs/xfs/xfs_inode_item.c2
-rw-r--r--fs/xfs/xfs_iomap.c69
-rw-r--r--fs/xfs/xfs_log.c6
-rw-r--r--fs/xfs/xfs_log_priv.h2
-rw-r--r--fs/xfs/xfs_log_recover.c31
-rw-r--r--fs/xfs/xfs_macros.c5
-rw-r--r--fs/xfs/xfs_mount.c16
-rw-r--r--fs/xfs/xfs_mount.h7
-rw-r--r--fs/xfs/xfs_quota.h72
-rw-r--r--fs/xfs/xfs_rename.c18
-rw-r--r--fs/xfs/xfs_trans.c21
-rw-r--r--fs/xfs/xfs_trans.h3
-rw-r--r--fs/xfs/xfs_trans_buf.c1
-rw-r--r--fs/xfs/xfs_trans_inode.c18
-rw-r--r--fs/xfs/xfs_types.h2
-rw-r--r--fs/xfs/xfs_utils.c2
-rw-r--r--fs/xfs/xfs_vfsops.c74
-rw-r--r--fs/xfs/xfs_vnodeops.c95
-rw-r--r--include/asm-alpha/agp.h10
-rw-r--r--include/asm-alpha/mmzone.h3
-rw-r--r--include/asm-alpha/smp.h2
-rw-r--r--include/asm-arm/arch-aaec2000/aaec2000.h151
-rw-r--r--include/asm-arm/arch-aaec2000/debug-macro.S36
-rw-r--r--include/asm-arm/arch-aaec2000/dma.h17
-rw-r--r--include/asm-arm/arch-aaec2000/entry-macro.S33
-rw-r--r--include/asm-arm/arch-aaec2000/hardware.h49
-rw-r--r--include/asm-arm/arch-aaec2000/io.h19
-rw-r--r--include/asm-arm/arch-aaec2000/irqs.h46
-rw-r--r--include/asm-arm/arch-aaec2000/memory.h73
-rw-r--r--include/asm-arm/arch-aaec2000/param.h15
-rw-r--r--include/asm-arm/arch-aaec2000/system.h24
-rw-r--r--include/asm-arm/arch-aaec2000/timex.h18
-rw-r--r--include/asm-arm/arch-aaec2000/uncompress.h47
-rw-r--r--include/asm-arm/arch-aaec2000/vmalloc.h16
-rw-r--r--include/asm-arm/arch-imx/imx-regs.h24
-rw-r--r--include/asm-arm/arch-integrator/platform.h4
-rw-r--r--include/asm-arm/arch-integrator/smp.h19
-rw-r--r--include/asm-arm/arch-ixp2000/gpio.h31
-rw-r--r--include/asm-arm/arch-ixp2000/io.h112
-rw-r--r--include/asm-arm/arch-ixp2000/ixp2000-regs.h3
-rw-r--r--include/asm-arm/arch-ixp2000/platform.h22
-rw-r--r--include/asm-arm/arch-ixp4xx/debug-macro.S1
-rw-r--r--include/asm-arm/arch-ixp4xx/ixp4xx-regs.h10
-rw-r--r--include/asm-arm/arch-omap/tps65010.h76
-rw-r--r--include/asm-arm/arch-pxa/pxa-regs.h2
-rw-r--r--include/asm-arm/arch-s3c2410/regs-nand.h44
-rw-r--r--include/asm-arm/arch-versatile/hardware.h27
-rw-r--r--include/asm-arm/arch-versatile/io.h2
-rw-r--r--include/asm-arm/arch-versatile/platform.h33
-rw-r--r--include/asm-arm/cacheflush.h3
-rw-r--r--include/asm-arm/elf.h4
-rw-r--r--include/asm-arm/io.h29
-rw-r--r--include/asm-arm/mach/time.h21
-rw-r--r--include/asm-arm/page.h18
-rw-r--r--include/asm-arm/pgalloc.h24
-rw-r--r--include/asm-arm/signal.h1
-rw-r--r--include/asm-arm/smp.h16
-rw-r--r--include/asm-arm/system.h33
-rw-r--r--include/asm-arm/thread_info.h2
-rw-r--r--include/asm-arm26/elf.h2
-rw-r--r--include/asm-arm26/signal.h3
-rw-r--r--include/asm-arm26/thread_info.h2
-rw-r--r--include/asm-cris/thread_info.h2
-rw-r--r--include/asm-frv/thread_info.h2
-rw-r--r--include/asm-generic/percpu.h2
-rw-r--r--include/asm-generic/pgtable.h3
-rw-r--r--include/asm-generic/topology.h9
-rw-r--r--include/asm-generic/vmlinux.lds.h2
-rw-r--r--include/asm-h8300/kmap_types.h6
-rw-r--r--include/asm-h8300/mman.h3
-rw-r--r--include/asm-h8300/thread_info.h2
-rw-r--r--include/asm-i386/agp.h10
-rw-r--r--include/asm-i386/apic.h15
-rw-r--r--include/asm-i386/apicdef.h3
-rw-r--r--include/asm-i386/checksum.h2
-rw-r--r--include/asm-i386/cpu.h2
-rw-r--r--include/asm-i386/genapic.h1
-rw-r--r--include/asm-i386/highmem.h1
-rw-r--r--include/asm-i386/irq.h6
-rw-r--r--include/asm-i386/kdebug.h2
-rw-r--r--include/asm-i386/kexec.h33
-rw-r--r--include/asm-i386/kprobes.h3
-rw-r--r--include/asm-i386/linkage.h4
-rw-r--r--include/asm-i386/mach-bigsmp/mach_apic.h2
-rw-r--r--include/asm-i386/mach-default/mach_apic.h2
-rw-r--r--include/asm-i386/mach-default/mach_ipi.h27
-rw-r--r--include/asm-i386/mach-es7000/mach_apic.h2
-rw-r--r--include/asm-i386/mach-generic/mach_apic.h1
-rw-r--r--include/asm-i386/mach-numaq/mach_apic.h2
-rw-r--r--include/asm-i386/mach-numaq/mach_ipi.h2
-rw-r--r--include/asm-i386/mach-summit/mach_apic.h2
-rw-r--r--include/asm-i386/mach-visws/mach_apic.h2
-rw-r--r--include/asm-i386/mmzone.h93
-rw-r--r--include/asm-i386/page.h10
-rw-r--r--include/asm-i386/param.h4
-rw-r--r--include/asm-i386/pgtable.h6
-rw-r--r--include/asm-i386/processor.h16
-rw-r--r--include/asm-i386/ptrace.h3
-rw-r--r--include/asm-i386/smp.h12
-rw-r--r--include/asm-i386/sparsemem.h31
-rw-r--r--include/asm-i386/string.h32
-rw-r--r--include/asm-i386/thread_info.h2
-rw-r--r--include/asm-i386/timer.h3
-rw-r--r--include/asm-i386/timex.h5
-rw-r--r--include/asm-i386/topology.h15
-rw-r--r--include/asm-i386/unistd.h2
-rw-r--r--include/asm-ia64/agp.h10
-rw-r--r--include/asm-ia64/break.h2
-rw-r--r--include/asm-ia64/compat.h1
-rw-r--r--include/asm-ia64/fcntl.h2
-rw-r--r--include/asm-ia64/ioctl32.h1
-rw-r--r--include/asm-ia64/kdebug.h61
-rw-r--r--include/asm-ia64/kprobes.h116
-rw-r--r--include/asm-ia64/mmzone.h14
-rw-r--r--include/asm-ia64/param.h2
-rw-r--r--include/asm-ia64/percpu.h2
-rw-r--r--include/asm-ia64/perfmon.h8
-rw-r--r--include/asm-ia64/pgtable.h9
-rw-r--r--include/asm-ia64/processor.h10
-rw-r--r--include/asm-ia64/smp.h2
-rw-r--r--include/asm-ia64/sn/mspec.h59
-rw-r--r--include/asm-ia64/sn/sn_sal.h28
-rw-r--r--include/asm-ia64/system.h10
-rw-r--r--include/asm-ia64/thread_info.h2
-rw-r--r--include/asm-ia64/topology.h61
-rw-r--r--include/asm-ia64/uncached.h12
-rw-r--r--include/asm-ia64/unistd.h1
-rw-r--r--include/asm-m32r/div64.h39
-rw-r--r--include/asm-m32r/ide.h2
-rw-r--r--include/asm-m32r/m32102.h1
-rw-r--r--include/asm-m32r/m32102peri.h468
-rw-r--r--include/asm-m32r/m32r.h5
-rw-r--r--include/asm-m32r/mappi3/mappi3_pld.h143
-rw-r--r--include/asm-m32r/mmzone.h3
-rw-r--r--include/asm-m32r/smp.h2
-rw-r--r--include/asm-m32r/thread_info.h2
-rw-r--r--include/asm-m32r/topology.h44
-rw-r--r--include/asm-m68k/thread_info.h2
-rw-r--r--include/asm-m68knommu/thread_info.h2
-rw-r--r--include/asm-mips/compat.h1
-rw-r--r--include/asm-mips/mmzone.h4
-rw-r--r--include/asm-mips/page.h2
-rw-r--r--include/asm-mips/pgtable.h2
-rw-r--r--include/asm-mips/smp.h2
-rw-r--r--include/asm-mips/system.h10
-rw-r--r--include/asm-mips/thread_info.h2
-rw-r--r--include/asm-mips/vr41xx/giu.h69
-rw-r--r--include/asm-mips/vr41xx/vr41xx.h35
-rw-r--r--include/asm-parisc/compat.h2
-rw-r--r--include/asm-parisc/mmzone.h3
-rw-r--r--include/asm-parisc/smp.h2
-rw-r--r--include/asm-parisc/thread_info.h2
-rw-r--r--include/asm-ppc/agp.h10
-rw-r--r--include/asm-ppc/cpm2.h46
-rw-r--r--include/asm-ppc/fsl_ocp.h54
-rw-r--r--include/asm-ppc/irq.h34
-rw-r--r--include/asm-ppc/kexec.h38
-rw-r--r--include/asm-ppc/m8260_pci.h1
-rw-r--r--include/asm-ppc/machdep.h31
-rw-r--r--include/asm-ppc/mmu.h2
-rw-r--r--include/asm-ppc/mmu_context.h2
-rw-r--r--include/asm-ppc/mpc10x.h6
-rw-r--r--include/asm-ppc/mpc8260.h2
-rw-r--r--include/asm-ppc/mpc85xx.h60
-rw-r--r--include/asm-ppc/ocp.h6
-rw-r--r--include/asm-ppc/pgtable.h2
-rw-r--r--include/asm-ppc/ppc_asm.h2
-rw-r--r--include/asm-ppc/ppc_sys.h2
-rw-r--r--include/asm-ppc/reg.h1
-rw-r--r--include/asm-ppc/reg_booke.h18
-rw-r--r--include/asm-ppc/seccomp.h10
-rw-r--r--include/asm-ppc/sigcontext.h2
-rw-r--r--include/asm-ppc/smp.h2
-rw-r--r--include/asm-ppc/thread_info.h10
-rw-r--r--include/asm-ppc64/agp.h10
-rw-r--r--include/asm-ppc64/compat.h1
-rw-r--r--include/asm-ppc64/dma.h3
-rw-r--r--include/asm-ppc64/elf.h4
-rw-r--r--include/asm-ppc64/iSeries/HvCall.h156
-rw-r--r--include/asm-ppc64/iSeries/HvCallCfg.h213
-rw-r--r--include/asm-ppc64/iSeries/HvCallEvent.h94
-rw-r--r--include/asm-ppc64/iSeries/HvCallHpt.h112
-rw-r--r--include/asm-ppc64/iSeries/HvCallPci.h486
-rw-r--r--include/asm-ppc64/iSeries/HvCallSc.h40
-rw-r--r--include/asm-ppc64/iSeries/HvCallSm.h36
-rw-r--r--include/asm-ppc64/iSeries/HvCallXm.h113
-rw-r--r--include/asm-ppc64/iSeries/HvLpConfig.h300
-rw-r--r--include/asm-ppc64/iSeries/HvLpEvent.h116
-rw-r--r--include/asm-ppc64/iSeries/HvReleaseData.h78
-rw-r--r--include/asm-ppc64/iSeries/HvTypes.h108
-rw-r--r--include/asm-ppc64/iSeries/IoHriMainStore.h33
-rw-r--r--include/asm-ppc64/iSeries/IoHriProcessorVpd.h32
-rw-r--r--include/asm-ppc64/iSeries/ItExtVpdPanel.h54
-rw-r--r--include/asm-ppc64/iSeries/ItIplParmsReal.h99
-rw-r--r--include/asm-ppc64/iSeries/ItLpNaca.h44
-rw-r--r--include/asm-ppc64/iSeries/ItLpQueue.h84
-rw-r--r--include/asm-ppc64/iSeries/ItLpRegSave.h41
-rw-r--r--include/asm-ppc64/iSeries/ItSpCommArea.h10
-rw-r--r--include/asm-ppc64/iSeries/ItVpdAreas.h125
-rw-r--r--include/asm-ppc64/iSeries/LparData.h49
-rw-r--r--include/asm-ppc64/iSeries/LparMap.h44
-rw-r--r--include/asm-ppc64/iSeries/XmPciLpEvent.h18
-rw-r--r--include/asm-ppc64/iSeries/iSeries_io.h59
-rw-r--r--include/asm-ppc64/iSeries/iSeries_irq.h17
-rw-r--r--include/asm-ppc64/iSeries/iSeries_pci.h142
-rw-r--r--include/asm-ppc64/iSeries/iSeries_proc.h24
-rw-r--r--include/asm-ppc64/iSeries/mf.h6
-rw-r--r--include/asm-ppc64/iSeries/vio.h57
-rw-r--r--include/asm-ppc64/imalloc.h12
-rw-r--r--include/asm-ppc64/iommu.h25
-rw-r--r--include/asm-ppc64/kdebug.h2
-rw-r--r--include/asm-ppc64/kexec.h41
-rw-r--r--include/asm-ppc64/machdep.h2
-rw-r--r--include/asm-ppc64/mmu.h27
-rw-r--r--include/asm-ppc64/mmzone.h44
-rw-r--r--include/asm-ppc64/nvram.h1
-rw-r--r--include/asm-ppc64/paca.h2
-rw-r--r--include/asm-ppc64/page.h5
-rw-r--r--include/asm-ppc64/pgtable.h9
-rw-r--r--include/asm-ppc64/ppc32.h2
-rw-r--r--include/asm-ppc64/processor.h211
-rw-r--r--include/asm-ppc64/prom.h13
-rw-r--r--include/asm-ppc64/rtas.h6
-rw-r--r--include/asm-ppc64/smp.h10
-rw-r--r--include/asm-ppc64/sparsemem.h16
-rw-r--r--include/asm-ppc64/thread_info.h6
-rw-r--r--include/asm-ppc64/time.h9
-rw-r--r--include/asm-ppc64/topology.h4
-rw-r--r--include/asm-ppc64/xics.h1
-rw-r--r--include/asm-s390/cpcmd.h18
-rw-r--r--include/asm-s390/debug.h48
-rw-r--r--include/asm-s390/kexec.h42
-rw-r--r--include/asm-s390/lowcore.h7
-rw-r--r--include/asm-s390/processor.h52
-rw-r--r--include/asm-s390/ptrace.h2
-rw-r--r--include/asm-s390/smp.h2
-rw-r--r--include/asm-s390/system.h38
-rw-r--r--include/asm-s390/thread_info.h4
-rw-r--r--include/asm-s390/unistd.h2
-rw-r--r--include/asm-s390/user.h2
-rw-r--r--include/asm-sh/page.h1
-rw-r--r--include/asm-sh/pgtable.h1
-rw-r--r--include/asm-sh/smp.h2
-rw-r--r--include/asm-sh/thread_info.h4
-rw-r--r--include/asm-sh64/page.h1
-rw-r--r--include/asm-sh64/pgtable.h2
-rw-r--r--include/asm-sh64/thread_info.h4
-rw-r--r--include/asm-sparc/smp.h2
-rw-r--r--include/asm-sparc/system.h4
-rw-r--r--include/asm-sparc/thread_info.h4
-rw-r--r--include/asm-sparc/uaccess.h5
-rw-r--r--include/asm-sparc64/agp.h10
-rw-r--r--include/asm-sparc64/compat.h1
-rw-r--r--include/asm-sparc64/iommu.h2
-rw-r--r--include/asm-sparc64/kdebug.h2
-rw-r--r--include/asm-sparc64/page.h2
-rw-r--r--include/asm-sparc64/pbm.h8
-rw-r--r--include/asm-sparc64/pgtable.h1
-rw-r--r--include/asm-sparc64/processor.h34
-rw-r--r--include/asm-sparc64/smp.h2
-rw-r--r--include/asm-sparc64/spitfire.h3
-rw-r--r--include/asm-sparc64/system.h14
-rw-r--r--include/asm-sparc64/termios.h78
-rw-r--r--include/asm-sparc64/thread_info.h2
-rw-r--r--include/asm-um/arch-signal-i386.h0
-rw-r--r--include/asm-um/elf-i386.h2
-rw-r--r--include/asm-um/elf-x86_64.h24
-rw-r--r--include/asm-um/elf.h0
-rw-r--r--include/asm-um/page.h8
-rw-r--r--include/asm-um/pgtable.h8
-rw-r--r--include/asm-um/ptrace-i386.h4
-rw-r--r--include/asm-um/smp.h3
-rw-r--r--include/asm-um/thread_info.h11
-rw-r--r--include/asm-v850/thread_info.h3
-rw-r--r--include/asm-x86_64/a.out.h2
-rw-r--r--include/asm-x86_64/agp.h10
-rw-r--r--include/asm-x86_64/apic.h2
-rw-r--r--include/asm-x86_64/apicdef.h4
-rw-r--r--include/asm-x86_64/bitops.h2
-rw-r--r--include/asm-x86_64/bug.h2
-rw-r--r--include/asm-x86_64/ia32.h2
-rw-r--r--include/asm-x86_64/io.h5
-rw-r--r--include/asm-x86_64/io_apic.h1
-rw-r--r--include/asm-x86_64/ioctl32.h1
-rw-r--r--include/asm-x86_64/irq.h5
-rw-r--r--include/asm-x86_64/kdebug.h2
-rw-r--r--include/asm-x86_64/kexec.h33
-rw-r--r--include/asm-x86_64/kprobes.h3
-rw-r--r--include/asm-x86_64/mmzone.h20
-rw-r--r--include/asm-x86_64/msr.h5
-rw-r--r--include/asm-x86_64/nmi.h2
-rw-r--r--include/asm-x86_64/page.h11
-rw-r--r--include/asm-x86_64/param.h6
-rw-r--r--include/asm-x86_64/percpu.h2
-rw-r--r--include/asm-x86_64/pgtable.h3
-rw-r--r--include/asm-x86_64/processor.h22
-rw-r--r--include/asm-x86_64/proto.h5
-rw-r--r--include/asm-x86_64/ptrace.h1
-rw-r--r--include/asm-x86_64/smp.h6
-rw-r--r--include/asm-x86_64/sparsemem.h26
-rw-r--r--include/asm-x86_64/suspend.h2
-rw-r--r--include/asm-x86_64/thread_info.h2
-rw-r--r--include/asm-x86_64/timex.h3
-rw-r--r--include/asm-x86_64/topology.h28
-rw-r--r--include/asm-x86_64/unistd.h2
-rw-r--r--include/asm-x86_64/vsyscall.h3
-rw-r--r--include/asm-xtensa/a.out.h33
-rw-r--r--include/asm-xtensa/atomic.h272
-rw-r--r--include/asm-xtensa/bitops.h446
-rw-r--r--include/asm-xtensa/bootparam.h61
-rw-r--r--include/asm-xtensa/bug.h41
-rw-r--r--include/asm-xtensa/bugs.h22
-rw-r--r--include/asm-xtensa/byteorder.h82
-rw-r--r--include/asm-xtensa/cache.h32
-rw-r--r--include/asm-xtensa/cacheflush.h122
-rw-r--r--include/asm-xtensa/checksum.h264
-rw-r--r--include/asm-xtensa/coprocessor.h70
-rw-r--r--include/asm-xtensa/cpumask.h16
-rw-r--r--include/asm-xtensa/cputime.h6
-rw-r--r--include/asm-xtensa/current.h38
-rw-r--r--include/asm-xtensa/delay.h50
-rw-r--r--include/asm-xtensa/div64.h19
-rw-r--r--include/asm-xtensa/dma-mapping.h182
-rw-r--r--include/asm-xtensa/dma.h61
-rw-r--r--include/asm-xtensa/elf.h222
-rw-r--r--include/asm-xtensa/errno.h142
-rw-r--r--include/asm-xtensa/fcntl.h101
-rw-r--r--include/asm-xtensa/fixmap.h252
-rw-r--r--include/asm-xtensa/hardirq.h28
-rw-r--r--include/asm-xtensa/hdreg.h17
-rw-r--r--include/asm-xtensa/highmem.h17
-rw-r--r--include/asm-xtensa/hw_irq.h18
-rw-r--r--include/asm-xtensa/ide.h36
-rw-r--r--include/asm-xtensa/io.h197
-rw-r--r--include/asm-xtensa/ioctl.h83
-rw-r--r--include/asm-xtensa/ioctls.h112
-rw-r--r--include/asm-xtensa/ipc.h34
-rw-r--r--include/asm-xtensa/ipcbuf.h37
-rw-r--r--include/asm-xtensa/irq.h37
-rw-r--r--include/asm-xtensa/kmap_types.h31
-rw-r--r--include/asm-xtensa/linkage.h16
-rw-r--r--include/asm-xtensa/local.h16
-rw-r--r--include/asm-xtensa/mman.h80
-rw-r--r--include/asm-xtensa/mmu.h17
-rw-r--r--include/asm-xtensa/mmu_context.h330
-rw-r--r--include/asm-xtensa/module.h25
-rw-r--r--include/asm-xtensa/msgbuf.h48
-rw-r--r--include/asm-xtensa/namei.h26
-rw-r--r--include/asm-xtensa/page.h133
-rw-r--r--include/asm-xtensa/page.h.n135
-rw-r--r--include/asm-xtensa/param.h34
-rw-r--r--include/asm-xtensa/pci-bridge.h88
-rw-r--r--include/asm-xtensa/pci.h89
-rw-r--r--include/asm-xtensa/percpu.h16
-rw-r--r--include/asm-xtensa/pgalloc.h116
-rw-r--r--include/asm-xtensa/pgtable.h468
-rw-r--r--include/asm-xtensa/platform-iss/hardware.h29
-rw-r--r--include/asm-xtensa/platform.h92
-rw-r--r--include/asm-xtensa/poll.h37
-rw-r--r--include/asm-xtensa/posix_types.h123
-rw-r--r--include/asm-xtensa/processor.h205
-rw-r--r--include/asm-xtensa/ptrace.h135
-rw-r--r--include/asm-xtensa/resource.h16
-rw-r--r--include/asm-xtensa/rmap.h16
-rw-r--r--include/asm-xtensa/rwsem.h175
-rw-r--r--include/asm-xtensa/scatterlist.h34
-rw-r--r--include/asm-xtensa/sections.h16
-rw-r--r--include/asm-xtensa/segment.h16
-rw-r--r--include/asm-xtensa/semaphore.h129
-rw-r--r--include/asm-xtensa/sembuf.h44
-rw-r--r--include/asm-xtensa/serial.h18
-rw-r--r--include/asm-xtensa/setup.h16
-rw-r--r--include/asm-xtensa/shmbuf.h50
-rw-r--r--include/asm-xtensa/shmparam.h23
-rw-r--r--include/asm-xtensa/sigcontext.h44
-rw-r--r--include/asm-xtensa/siginfo.h16
-rw-r--r--include/asm-xtensa/signal.h187
-rw-r--r--include/asm-xtensa/smp.h27
-rw-r--r--include/asm-xtensa/socket.h61
-rw-r--r--include/asm-xtensa/sockios.h30
-rw-r--r--include/asm-xtensa/spinlock.h16
-rw-r--r--include/asm-xtensa/stat.h105
-rw-r--r--include/asm-xtensa/statfs.h17
-rw-r--r--include/asm-xtensa/string.h124
-rw-r--r--include/asm-xtensa/system.h252
-rw-r--r--include/asm-xtensa/termbits.h194
-rw-r--r--include/asm-xtensa/termios.h122
-rw-r--r--include/asm-xtensa/thread_info.h146
-rw-r--r--include/asm-xtensa/timex.h94
-rw-r--r--include/asm-xtensa/tlb.h25
-rw-r--r--include/asm-xtensa/tlbflush.h200
-rw-r--r--include/asm-xtensa/topology.h16
-rw-r--r--include/asm-xtensa/types.h66
-rw-r--r--include/asm-xtensa/uaccess.h532
-rw-r--r--include/asm-xtensa/ucontext.h22
-rw-r--r--include/asm-xtensa/unaligned.h28
-rw-r--r--include/asm-xtensa/unistd.h537
-rw-r--r--include/asm-xtensa/user.h20
-rw-r--r--include/asm-xtensa/vga.h19
-rw-r--r--include/asm-xtensa/xor.h16
-rw-r--r--include/asm-xtensa/xtensa/cacheasm.h708
-rw-r--r--include/asm-xtensa/xtensa/cacheattrasm.h432
-rw-r--r--include/asm-xtensa/xtensa/config-linux_be/core.h1270
-rw-r--r--include/asm-xtensa/xtensa/config-linux_be/defs.h270
-rw-r--r--include/asm-xtensa/xtensa/config-linux_be/specreg.h99
-rw-r--r--include/asm-xtensa/xtensa/config-linux_be/system.h198
-rw-r--r--include/asm-xtensa/xtensa/config-linux_be/tie.h275
-rw-r--r--include/asm-xtensa/xtensa/coreasm.h526
-rw-r--r--include/asm-xtensa/xtensa/corebits.h77
-rw-r--r--include/asm-xtensa/xtensa/hal.h822
-rw-r--r--include/asm-xtensa/xtensa/simcall.h130
-rw-r--r--include/asm-xtensa/xtensa/xt2000-uart.h155
-rw-r--r--include/asm-xtensa/xtensa/xt2000.h408
-rw-r--r--include/asm-xtensa/xtensa/xtboard.h120
-rw-r--r--include/linux/a.out.h2
-rw-r--r--include/linux/acpi.h7
-rw-r--r--include/linux/arcfb.h8
-rw-r--r--include/linux/ata.h1
-rw-r--r--include/linux/atalk.h26
-rw-r--r--include/linux/audit.h94
-rw-r--r--include/linux/auto_fs4.h2
-rw-r--r--include/linux/binfmts.h5
-rw-r--r--include/linux/blkdev.h18
-rw-r--r--include/linux/bootmem.h13
-rw-r--r--include/linux/chio.h168
-rw-r--r--include/linux/cpu.h1
-rw-r--r--include/linux/cpufreq.h2
-rw-r--r--include/linux/crash_dump.h18
-rw-r--r--include/linux/device.h67
-rw-r--r--include/linux/dm9000.h36
-rw-r--r--include/linux/dma-mapping.h5
-rw-r--r--include/linux/dmi.h1
-rw-r--r--include/linux/dqblk_v1.h6
-rw-r--r--include/linux/dqblk_v2.h6
-rw-r--r--include/linux/efi.h2
-rw-r--r--include/linux/err.h4
-rw-r--r--include/linux/etherdevice.h22
-rw-r--r--include/linux/ethtool.h1
-rw-r--r--include/linux/ext2_fs.h25
-rw-r--r--include/linux/ext3_fs.h1
-rw-r--r--include/linux/ext3_jbd.h19
-rw-r--r--include/linux/fb.h19
-rw-r--r--include/linux/fcntl.h4
-rw-r--r--include/linux/font.h26
-rw-r--r--include/linux/fs.h74
-rw-r--r--include/linux/fsl_devices.h8
-rw-r--r--include/linux/gameport.h28
-rw-r--r--include/linux/genalloc.h40
-rw-r--r--include/linux/genhd.h3
-rw-r--r--include/linux/gfp.h8
-rw-r--r--include/linux/hardirq.h6
-rw-r--r--include/linux/hdlc.h4
-rw-r--r--include/linux/highmem.h1
-rw-r--r--include/linux/hugetlb.h40
-rw-r--r--include/linux/hwmon-sysfs.h36
-rw-r--r--include/linux/i2c-id.h1
-rw-r--r--include/linux/i2c-vid.h12
-rw-r--r--include/linux/i2c.h12
-rw-r--r--include/linux/i2o-dev.h43
-rw-r--r--include/linux/i2o.h497
-rw-r--r--include/linux/ide.h22
-rw-r--r--include/linux/if.h2
-rw-r--r--include/linux/if_shaper.h3
-rw-r--r--include/linux/if_tr.h45
-rw-r--r--include/linux/inetdevice.h2
-rw-r--r--include/linux/init.h12
-rw-r--r--include/linux/init_task.h1
-rw-r--r--include/linux/input.h2
-rw-r--r--include/linux/ioc4.h179
-rw-r--r--include/linux/ioc4_common.h21
-rw-r--r--include/linux/ip.h21
-rw-r--r--include/linux/ipmi.h5
-rw-r--r--include/linux/ipv6.h13
-rw-r--r--include/linux/irq.h5
-rw-r--r--include/linux/kernel.h18
-rw-r--r--include/linux/kexec.h135
-rw-r--r--include/linux/key-ui.h47
-rw-r--r--include/linux/key.h44
-rw-r--r--include/linux/keyctl.h11
-rw-r--r--include/linux/klist.h55
-rw-r--r--include/linux/kmod.h13
-rw-r--r--include/linux/kobject.h8
-rw-r--r--include/linux/kprobes.h100
-rw-r--r--include/linux/libata.h67
-rw-r--r--include/linux/list.h2
-rw-r--r--include/linux/lockd/lockd.h7
-rw-r--r--include/linux/loop.h2
-rw-r--r--include/linux/major.h1
-rw-r--r--include/linux/mempool.h11
-rw-r--r--include/linux/mii.h8
-rw-r--r--include/linux/mm.h125
-rw-r--r--include/linux/mmc/protocol.h27
-rw-r--r--include/linux/mmzone.h192
-rw-r--r--include/linux/module.h5
-rw-r--r--include/linux/namespace.h1
-rw-r--r--include/linux/net.h1
-rw-r--r--include/linux/netdevice.h26
-rw-r--r--include/linux/netfilter_ipv4.h6
-rw-r--r--include/linux/netfilter_ipv4/ip_conntrack_core.h3
-rw-r--r--include/linux/netfilter_ipv4/ip_nat.h3
-rw-r--r--include/linux/netfilter_ipv4/ipt_CLUSTERIP.h3
-rw-r--r--include/linux/netfilter_ipv4/listhelp.h1
-rw-r--r--include/linux/netfilter_ipv4/lockhelp.h129
-rw-r--r--include/linux/netlink.h27
-rw-r--r--include/linux/netpoll.h34
-rw-r--r--include/linux/nfs4.h4
-rw-r--r--include/linux/nfs_fs.h306
-rw-r--r--include/linux/nfs_fs_i.h5
-rw-r--r--include/linux/nfs_fs_sb.h1
-rw-r--r--include/linux/nfs_mount.h1
-rw-r--r--include/linux/nfs_page.h30
-rw-r--r--include/linux/nfs_xdr.h43
-rw-r--r--include/linux/nfsacl.h58
-rw-r--r--include/linux/nfsd/nfsd.h24
-rw-r--r--include/linux/nfsd/state.h47
-rw-r--r--include/linux/nfsd/xdr.h4
-rw-r--r--include/linux/nfsd/xdr3.h26
-rw-r--r--include/linux/nfsd/xdr4.h1
-rw-r--r--include/linux/nfsd_idmap.h5
-rw-r--r--include/linux/node.h1
-rw-r--r--include/linux/notifier.h1
-rw-r--r--include/linux/numa.h2
-rw-r--r--include/linux/nvram.h2
-rw-r--r--include/linux/page-flags.h35
-rw-r--r--include/linux/pagemap.h4
-rw-r--r--include/linux/pci_ids.h14
-rw-r--r--include/linux/pfkeyv2.h1
-rw-r--r--include/linux/pkt_cls.h1
-rw-r--r--include/linux/pkt_sched.h9
-rw-r--r--include/linux/pktcdvd.h2
-rw-r--r--include/linux/pm.h33
-rw-r--r--include/linux/posix_acl_xattr.h11
-rw-r--r--include/linux/proc_fs.h7
-rw-r--r--include/linux/qnx4_fs.h18
-rw-r--r--include/linux/qnxtypes.h16
-rw-r--r--include/linux/quota.h7
-rw-r--r--include/linux/quotaops.h3
-rw-r--r--include/linux/raid/bitmap.h273
-rw-r--r--include/linux/raid/md.h17
-rw-r--r--include/linux/raid/md_k.h22
-rw-r--r--include/linux/raid/md_p.h9
-rw-r--r--include/linux/raid/md_u.h7
-rw-r--r--include/linux/raid/raid1.h16
-rw-r--r--include/linux/reboot.h4
-rw-r--r--include/linux/reiserfs_acl.h1
-rw-r--r--include/linux/reiserfs_fs.h15
-rw-r--r--include/linux/reiserfs_fs_sb.h2
-rw-r--r--include/linux/rmap.h6
-rw-r--r--include/linux/rtnetlink.h183
-rw-r--r--include/linux/sched.h132
-rw-r--r--include/linux/serial_core.h19
-rw-r--r--include/linux/signal.h2
-rw-r--r--include/linux/skbuff.h36
-rw-r--r--include/linux/slab.h1
-rw-r--r--include/linux/smp.h40
-rw-r--r--include/linux/spinlock.h8
-rw-r--r--include/linux/string.h2
-rw-r--r--include/linux/sunrpc/clnt.h6
-rw-r--r--include/linux/sunrpc/sched.h1
-rw-r--r--include/linux/sunrpc/svc.h14
-rw-r--r--include/linux/sunrpc/xdr.h21
-rw-r--r--include/linux/suspend.h2
-rw-r--r--include/linux/swap.h3
-rw-r--r--include/linux/syscalls.h5
-rw-r--r--include/linux/sysctl.h13
-rw-r--r--include/linux/sysfs.h15
-rw-r--r--include/linux/tc_ematch/tc_em_meta.h30
-rw-r--r--include/linux/tc_ematch/tc_em_text.h19
-rw-r--r--include/linux/tcp.h78
-rw-r--r--include/linux/tcp_diag.h4
-rw-r--r--include/linux/textsearch.h180
-rw-r--r--include/linux/textsearch_fsm.h48
-rw-r--r--include/linux/timer.h34
-rw-r--r--include/linux/topology.h14
-rw-r--r--include/linux/tty.h1
-rw-r--r--include/linux/usb.h13
-rw-r--r--include/linux/vmalloc.h1
-rw-r--r--include/linux/wait.h20
-rw-r--r--include/linux/wireless.h283
-rw-r--r--include/linux/x25.h12
-rw-r--r--include/linux/xfrm.h5
-rw-r--r--include/media/audiochip.h4
-rw-r--r--include/media/id.h4
-rw-r--r--include/media/ir-common.h3
-rw-r--r--include/media/tuner.h29
-rw-r--r--include/media/tveeprom.h4
-rw-r--r--include/media/video-buf-dvb.h2
-rw-r--r--include/net/act_generic.h4
-rw-r--r--include/net/ax25.h2
-rw-r--r--include/net/ip.h1
-rw-r--r--include/net/ip6_fib.h9
-rw-r--r--include/net/ip6_route.h9
-rw-r--r--include/net/ip_fib.h14
-rw-r--r--include/net/neighbour.h7
-rw-r--r--include/net/request_sock.h255
-rw-r--r--include/net/route.h5
-rw-r--r--include/net/sch_generic.h122
-rw-r--r--include/net/sctp/command.h8
-rw-r--r--include/net/sctp/constants.h7
-rw-r--r--include/net/sctp/sctp.h17
-rw-r--r--include/net/sctp/sm.h6
-rw-r--r--include/net/sctp/structs.h41
-rw-r--r--include/net/sctp/user.h3
-rw-r--r--include/net/snmp.h14
-rw-r--r--include/net/sock.h4
-rw-r--r--include/net/tcp.h399
-rw-r--r--include/net/tcp_ecn.h13
-rw-r--r--include/net/x25.h9
-rw-r--r--include/net/xfrm.h30
-rw-r--r--include/pcmcia/ss.h8
-rw-r--r--include/scsi/scsi.h4
-rw-r--r--include/scsi/scsi_device.h4
-rw-r--r--include/scsi/scsi_host.h25
-rw-r--r--include/scsi/scsi_transport.h38
-rw-r--r--include/scsi/scsi_transport_spi.h6
-rw-r--r--include/scsi/sg_request.h26
-rw-r--r--include/sound/ac97_codec.h8
-rw-r--r--include/sound/asound.h16
-rw-r--r--include/sound/control.h2
-rw-r--r--include/sound/core.h3
-rw-r--r--include/sound/emu10k1.h42
-rw-r--r--include/sound/gus.h23
-rw-r--r--include/sound/hdspm.h131
-rw-r--r--include/sound/pcm.h32
-rw-r--r--include/sound/seq_midi_event.h2
-rw-r--r--include/sound/seq_virmidi.h1
-rw-r--r--include/sound/timer.h2
-rw-r--r--include/sound/version.h4
-rw-r--r--init/Kconfig5
-rw-r--r--init/calibrate.c94
-rw-r--r--init/do_mounts_initrd.c4
-rw-r--r--init/main.c1
-rw-r--r--ipc/sem.c9
-rw-r--r--kernel/Kconfig.hz46
-rw-r--r--kernel/Kconfig.preempt65
-rw-r--r--kernel/Makefile2
-rw-r--r--kernel/audit.c587
-rw-r--r--kernel/auditsc.c259
-rw-r--r--kernel/cpu.c14
-rw-r--r--kernel/cpuset.c121
-rw-r--r--kernel/crash_dump.c52
-rw-r--r--kernel/exit.c20
-rw-r--r--kernel/fork.c28
-rw-r--r--kernel/irq/handle.c3
-rw-r--r--kernel/irq/manage.c8
-rw-r--r--kernel/irq/spurious.c2
-rw-r--r--kernel/kexec.c1063
-rw-r--r--kernel/kmod.c17
-rw-r--r--kernel/kprobes.c288
-rw-r--r--kernel/ksysfs.c13
-rw-r--r--kernel/module.c105
-rw-r--r--kernel/panic.c23
-rw-r--r--kernel/params.c4
-rw-r--r--kernel/posix-timers.c35
-rw-r--r--kernel/power/Kconfig8
-rw-r--r--kernel/power/Makefile6
-rw-r--r--kernel/power/disk.c35
-rw-r--r--kernel/power/main.c22
-rw-r--r--kernel/power/process.c26
-rw-r--r--kernel/power/smp.c89
-rw-r--r--kernel/power/swsusp.c95
-rw-r--r--kernel/printk.c87
-rw-r--r--kernel/profile.c16
-rw-r--r--kernel/resource.c2
-rw-r--r--kernel/sched.c1065
-rw-r--r--kernel/signal.c22
-rw-r--r--kernel/spinlock.c8
-rw-r--r--kernel/stop_machine.c4
-rw-r--r--kernel/sys.c133
-rw-r--r--kernel/sys_ni.c3
-rw-r--r--kernel/sysctl.c12
-rw-r--r--kernel/timer.c353
-rw-r--r--lib/Kconfig19
-rw-r--r--lib/Kconfig.debug3
-rw-r--r--lib/Makefile13
-rw-r--r--lib/bitmap.c3
-rw-r--r--lib/genalloc.c188
-rw-r--r--lib/idr.c2
-rw-r--r--lib/kernel_lock.c55
-rw-r--r--lib/klist.c265
-rw-r--r--lib/kobject.c2
-rw-r--r--lib/kobject_uevent.c6
-rw-r--r--lib/sha1.c2
-rw-r--r--lib/smp_processor_id.c55
-rw-r--r--lib/textsearch.c317
-rw-r--r--lib/ts_fsm.c338
-rw-r--r--lib/ts_kmp.c145
-rw-r--r--mm/Kconfig91
-rw-r--r--mm/Makefile2
-rw-r--r--mm/bootmem.c23
-rw-r--r--mm/fadvise.c4
-rw-r--r--mm/filemap.c101
-rw-r--r--mm/filemap.h94
-rw-r--r--mm/filemap_xip.c447
-rw-r--r--mm/hugetlb.c177
-rw-r--r--mm/madvise.c109
-rw-r--r--mm/memory.c80
-rw-r--r--mm/mempolicy.c110
-rw-r--r--mm/mempool.c20
-rw-r--r--mm/mmap.c120
-rw-r--r--mm/mremap.c7
-rw-r--r--mm/msync.c2
-rw-r--r--mm/nommu.c5
-rw-r--r--mm/oom_kill.c7
-rw-r--r--mm/page_alloc.c481
-rw-r--r--mm/page_io.c2
-rw-r--r--mm/pdflush.c2
-rw-r--r--mm/rmap.c33
-rw-r--r--mm/shmem.c143
-rw-r--r--mm/slab.c31
-rw-r--r--mm/sparse.c137
-rw-r--r--mm/swapfile.c57
-rw-r--r--mm/vmalloc.c33
-rw-r--r--mm/vmscan.c107
-rw-r--r--net/802/tr.c26
-rw-r--r--net/appletalk/aarp.c9
-rw-r--r--net/appletalk/ddp.c2
-rw-r--r--net/bridge/br_device.c15
-rw-r--r--net/bridge/br_forward.c3
-rw-r--r--net/bridge/br_if.c23
-rw-r--r--net/bridge/br_input.c12
-rw-r--r--net/bridge/br_netfilter.c38
-rw-r--r--net/bridge/br_notify.c9
-rw-r--r--net/bridge/br_private.h1
-rw-r--r--net/bridge/br_stp_bpdu.c3
-rw-r--r--net/bridge/netfilter/ebtables.c21
-rw-r--r--net/core/Makefile3
-rw-r--r--net/core/dev.c138
-rw-r--r--net/core/ethtool.c22
-rw-r--r--net/core/neighbour.c336
-rw-r--r--net/core/net-sysfs.c20
-rw-r--r--net/core/netfilter.c138
-rw-r--r--net/core/netpoll.c80
-rw-r--r--net/core/request_sock.c64
-rw-r--r--net/core/rtnetlink.c33
-rw-r--r--net/core/skbuff.c163
-rw-r--r--net/core/sock.c35
-rw-r--r--net/core/sysctl_net_core.c61
-rw-r--r--net/core/wireless.c74
-rw-r--r--net/decnet/dn_dev.c9
-rw-r--r--net/decnet/dn_neigh.c1
-rw-r--r--net/decnet/dn_route.c11
-rw-r--r--net/decnet/dn_rules.c7
-rw-r--r--net/decnet/dn_table.c8
-rw-r--r--net/ipv4/Kconfig146
-rw-r--r--net/ipv4/Makefile14
-rw-r--r--net/ipv4/af_inet.c13
-rw-r--r--net/ipv4/ah4.c2
-rw-r--r--net/ipv4/devinet.c45
-rw-r--r--net/ipv4/esp4.c4
-rw-r--r--net/ipv4/fib_frontend.c55
-rw-r--r--net/ipv4/fib_hash.c3
-rw-r--r--net/ipv4/fib_lookup.h3
-rw-r--r--net/ipv4/fib_rules.c7
-rw-r--r--net/ipv4/fib_semantics.c10
-rw-r--r--net/ipv4/fib_trie.c2454
-rw-r--r--net/ipv4/icmp.c9
-rw-r--r--net/ipv4/ip_input.c5
-rw-r--r--net/ipv4/ip_output.c19
-rw-r--r--net/ipv4/ip_sockglue.c6
-rw-r--r--net/ipv4/ipcomp.c11
-rw-r--r--net/ipv4/ipmr.c1
-rw-r--r--net/ipv4/ipvs/Makefile2
-rw-r--r--net/ipv4/ipvs/ip_vs_proto.c3
-rw-r--r--net/ipv4/ipvs/ip_vs_proto_icmp.c182
-rw-r--r--net/ipv4/ipvs/ip_vs_xmit.c2
-rw-r--r--net/ipv4/multipath_drr.c20
-rw-r--r--net/ipv4/multipath_random.c2
-rw-r--r--net/ipv4/multipath_rr.c22
-rw-r--r--net/ipv4/multipath_wrandom.c2
-rw-r--r--net/ipv4/netfilter/arp_tables.c1
-rw-r--r--net/ipv4/netfilter/ip_conntrack_amanda.c7
-rw-r--r--net/ipv4/netfilter/ip_conntrack_core.c127
-rw-r--r--net/ipv4/netfilter/ip_conntrack_ftp.c7
-rw-r--r--net/ipv4/netfilter/ip_conntrack_irc.c7
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_sctp.c23
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_tcp.c27
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_udp.c1
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c23
-rw-r--r--net/ipv4/netfilter/ip_nat_core.c32
-rw-r--r--net/ipv4/netfilter/ip_nat_helper.c13
-rw-r--r--net/ipv4/netfilter/ip_nat_rule.c4
-rw-r--r--net/ipv4/netfilter/ip_nat_standalone.c5
-rw-r--r--net/ipv4/netfilter/ip_queue.c10
-rw-r--r--net/ipv4/netfilter/ip_tables.c1
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c51
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c10
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c13
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c15
-rw-r--r--net/ipv4/netfilter/ipt_hashlimit.c17
-rw-r--r--net/ipv4/netfilter/ipt_helper.c4
-rw-r--r--net/ipv4/netfilter/ipt_recent.c10
-rw-r--r--net/ipv4/raw.c22
-rw-r--r--net/ipv4/route.c19
-rw-r--r--net/ipv4/syncookies.c49
-rw-r--r--net/ipv4/sysctl_net_ipv4.c123
-rw-r--r--net/ipv4/tcp.c119
-rw-r--r--net/ipv4/tcp_bic.c331
-rw-r--r--net/ipv4/tcp_cong.c237
-rw-r--r--net/ipv4/tcp_diag.c71
-rw-r--r--net/ipv4/tcp_highspeed.c181
-rw-r--r--net/ipv4/tcp_htcp.c289
-rw-r--r--net/ipv4/tcp_hybla.c187
-rw-r--r--net/ipv4/tcp_input.c748
-rw-r--r--net/ipv4/tcp_ipv4.c175
-rw-r--r--net/ipv4/tcp_minisocks.c72
-rw-r--r--net/ipv4/tcp_output.c50
-rw-r--r--net/ipv4/tcp_scalable.c68
-rw-r--r--net/ipv4/tcp_timer.c18
-rw-r--r--net/ipv4/tcp_vegas.c411
-rw-r--r--net/ipv4/tcp_westwood.c259
-rw-r--r--net/ipv4/udp.c12
-rw-r--r--net/ipv4/xfrm4_output.c8
-rw-r--r--net/ipv4/xfrm4_state.c9
-rw-r--r--net/ipv4/xfrm4_tunnel.c2
-rw-r--r--net/ipv6/addrconf.c75
-rw-r--r--net/ipv6/ah6.c2
-rw-r--r--net/ipv6/anycast.c4
-rw-r--r--net/ipv6/datagram.c6
-rw-r--r--net/ipv6/esp6.c2
-rw-r--r--net/ipv6/icmp.c14
-rw-r--r--net/ipv6/ip6_fib.c19
-rw-r--r--net/ipv6/ip6_flowlabel.c10
-rw-r--r--net/ipv6/ip6_output.c17
-rw-r--r--net/ipv6/ip6_tunnel.c1
-rw-r--r--net/ipv6/ipcomp6.c9
-rw-r--r--net/ipv6/ipv6_sockglue.c5
-rw-r--r--net/ipv6/ipv6_syms.c1
-rw-r--r--net/ipv6/mcast.c68
-rw-r--r--net/ipv6/ndisc.c4
-rw-r--r--net/ipv6/netfilter/ip6_tables.c1
-rw-r--r--net/ipv6/netfilter/ip6t_LOG.c54
-rw-r--r--net/ipv6/netfilter/ip6table_raw.c6
-rw-r--r--net/ipv6/raw.c8
-rw-r--r--net/ipv6/route.c79
-rw-r--r--net/ipv6/tcp_ipv6.c150
-rw-r--r--net/ipv6/udp.c4
-rw-r--r--net/ipv6/xfrm6_output.c1
-rw-r--r--net/ipv6/xfrm6_policy.c4
-rw-r--r--net/ipv6/xfrm6_tunnel.c2
-rw-r--r--net/key/af_key.c385
-rw-r--r--net/netlink/af_netlink.c21
-rw-r--r--net/rxrpc/krxiod.c2
-rw-r--r--net/rxrpc/krxsecd.c2
-rw-r--r--net/rxrpc/krxtimod.c2
-rw-r--r--net/sched/Kconfig15
-rw-r--r--net/sched/Makefile1
-rw-r--r--net/sched/act_api.c13
-rw-r--r--net/sched/cls_api.c5
-rw-r--r--net/sched/cls_basic.c3
-rw-r--r--net/sched/em_meta.c295
-rw-r--r--net/sched/em_text.c157
-rw-r--r--net/sched/sch_api.c10
-rw-r--r--net/sched/sch_dsmark.c373
-rw-r--r--net/sched/sch_fifo.c152
-rw-r--r--net/sched/sch_generic.c84
-rw-r--r--net/sched/sch_netem.c209
-rw-r--r--net/sctp/associola.c151
-rw-r--r--net/sctp/endpointola.c1
-rw-r--r--net/sctp/input.c51
-rw-r--r--net/sctp/ipv6.c36
-rw-r--r--net/sctp/outqueue.c11
-rw-r--r--net/sctp/proc.c194
-rw-r--r--net/sctp/protocol.c7
-rw-r--r--net/sctp/sm_make_chunk.c20
-rw-r--r--net/sctp/sm_sideeffect.c105
-rw-r--r--net/sctp/sm_statefuns.c162
-rw-r--r--net/sctp/sm_statetable.c6
-rw-r--r--net/sctp/socket.c425
-rw-r--r--net/sctp/transport.c4
-rw-r--r--net/socket.c12
-rw-r--r--net/sunrpc/auth.c6
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c18
-rw-r--r--net/sunrpc/clnt.c205
-rw-r--r--net/sunrpc/pmap_clnt.c9
-rw-r--r--net/sunrpc/sched.c84
-rw-r--r--net/sunrpc/sunrpc_syms.c7
-rw-r--r--net/sunrpc/svc.c36
-rw-r--r--net/sunrpc/svcauth_unix.c11
-rw-r--r--net/sunrpc/svcsock.c6
-rw-r--r--net/sunrpc/xdr.c298
-rw-r--r--net/sunrpc/xprt.c71
-rw-r--r--net/unix/af_unix.c28
-rw-r--r--net/x25/af_x25.c110
-rw-r--r--net/x25/x25_facilities.c34
-rw-r--r--net/x25/x25_subr.c41
-rw-r--r--net/xfrm/xfrm_algo.c2
-rw-r--r--net/xfrm/xfrm_policy.c13
-rw-r--r--net/xfrm/xfrm_state.c118
-rw-r--r--net/xfrm/xfrm_user.c312
-rw-r--r--scripts/Makefile.build4
-rw-r--r--scripts/basic/docproc.c14
-rw-r--r--scripts/basic/fixdep.c20
-rw-r--r--scripts/basic/split-include.c2
-rw-r--r--scripts/kconfig/conf.c6
-rw-r--r--scripts/kconfig/confdata.c4
-rw-r--r--scripts/kconfig/gconf.glade10
-rw-r--r--scripts/kconfig/mconf.c5
-rw-r--r--security/commoncap.c2
-rw-r--r--security/dummy.c2
-rw-r--r--security/keys/Makefile5
-rw-r--r--security/keys/compat.c7
-rw-r--r--security/keys/internal.h45
-rw-r--r--security/keys/key.c118
-rw-r--r--security/keys/keyctl.c199
-rw-r--r--security/keys/keyring.c312
-rw-r--r--security/keys/proc.c21
-rw-r--r--security/keys/process_keys.c213
-rw-r--r--security/keys/request_key.c221
-rw-r--r--security/keys/request_key_auth.c180
-rw-r--r--security/keys/user_defined.c87
-rw-r--r--security/seclvl.c4
-rw-r--r--security/selinux/avc.c40
-rw-r--r--security/selinux/hooks.c27
-rw-r--r--security/selinux/include/av_perm_to_string.h2
-rw-r--r--security/selinux/include/av_permissions.h2
-rw-r--r--security/selinux/nlmsgtab.c12
-rw-r--r--security/selinux/selinuxfs.c9
-rw-r--r--security/selinux/ss/conditional.c9
-rw-r--r--security/selinux/ss/policydb.c15
-rw-r--r--security/selinux/ss/services.c18
-rw-r--r--sound/Kconfig5
-rw-r--r--sound/arm/Kconfig6
-rw-r--r--sound/arm/Makefile3
-rw-r--r--sound/arm/aaci.c968
-rw-r--r--sound/arm/aaci.h246
-rw-r--r--sound/arm/devdma.c81
-rw-r--r--sound/arm/devdma.h3
-rw-r--r--sound/core/control.c4
-rw-r--r--sound/core/info.c3
-rw-r--r--sound/core/info_oss.c3
-rw-r--r--sound/core/memalloc.c201
-rw-r--r--sound/core/memory.c41
-rw-r--r--sound/core/oss/mixer_oss.c3
-rw-r--r--sound/core/oss/pcm_oss.c36
-rw-r--r--sound/core/oss/pcm_plugin.c5
-rw-r--r--sound/core/pcm.c3
-rw-r--r--sound/core/pcm_lib.c52
-rw-r--r--sound/core/pcm_memory.c1
-rw-r--r--sound/core/pcm_misc.c16
-rw-r--r--sound/core/pcm_native.c74
-rw-r--r--sound/core/seq/oss/seq_oss_synth.c24
-rw-r--r--sound/core/seq/seq_dummy.c5
-rw-r--r--sound/core/seq/seq_midi.c2
-rw-r--r--sound/core/seq/seq_midi_event.c6
-rw-r--r--sound/core/seq/seq_queue.c3
-rw-r--r--sound/core/seq/seq_queue.h1
-rw-r--r--sound/core/seq/seq_timer.c3
-rw-r--r--sound/core/seq/seq_timer.h2
-rw-r--r--sound/core/seq/seq_virmidi.c8
-rw-r--r--sound/core/sound.c9
-rw-r--r--sound/core/timer.c103
-rw-r--r--sound/core/timer_compat.c5
-rw-r--r--sound/drivers/vx/vx_pcm.c12
-rw-r--r--sound/i2c/tea6330t.c3
-rw-r--r--sound/isa/Kconfig1
-rw-r--r--sound/isa/ad1816a/ad1816a.c2
-rw-r--r--sound/isa/cs423x/cs4236.c3
-rw-r--r--sound/isa/gus/gus_io.c14
-rw-r--r--sound/isa/gus/gus_main.c3
-rw-r--r--sound/isa/gus/gus_mem.c19
-rw-r--r--sound/isa/gus/gus_pcm.c3
-rw-r--r--sound/isa/gus/gus_reset.c3
-rw-r--r--sound/isa/gus/gus_synth.c3
-rw-r--r--sound/isa/gus/gus_tables.h4
-rw-r--r--sound/isa/gus/gus_volume.c8
-rw-r--r--sound/oss/Kconfig64
-rw-r--r--sound/oss/ad1816.c2
-rw-r--r--sound/oss/ad1848.c3
-rw-r--r--sound/oss/ad1889.c3
-rw-r--r--sound/oss/cmpci.c3
-rw-r--r--sound/oss/dmasound/dmasound_awacs.c20
-rw-r--r--sound/oss/emu10k1/midi.c6
-rw-r--r--sound/oss/emu10k1/passthrough.c3
-rw-r--r--sound/oss/es1370.c3
-rw-r--r--sound/oss/es1371.c3
-rw-r--r--sound/oss/esssolo1.c3
-rw-r--r--sound/oss/maestro.c2
-rw-r--r--sound/oss/mpu401.c3
-rw-r--r--sound/oss/nm256.h5
-rw-r--r--sound/oss/nm256_audio.c9
-rw-r--r--sound/oss/nm256_coeff.h2
-rw-r--r--sound/oss/rme96xx.c6
-rw-r--r--sound/oss/sb_common.c4
-rw-r--r--sound/oss/soundcard.c19
-rw-r--r--sound/oss/sscape.c8
-rw-r--r--sound/oss/v_midi.c2
-rw-r--r--sound/oss/wavfront.c12
-rw-r--r--sound/pci/Kconfig13
-rw-r--r--sound/pci/ac97/ac97_codec.c71
-rw-r--r--sound/pci/ac97/ac97_patch.c585
-rw-r--r--sound/pci/ac97/ac97_patch.h1
-rw-r--r--sound/pci/ali5451/ali5451.c283
-rw-r--r--sound/pci/als4000.c4
-rw-r--r--sound/pci/atiixp.c6
-rw-r--r--sound/pci/atiixp_modem.c42
-rw-r--r--sound/pci/au88x0/au88x0.c2
-rw-r--r--sound/pci/azt3328.c2
-rw-r--r--sound/pci/bt87x.c2
-rw-r--r--sound/pci/ca0106/ca0106.h70
-rw-r--r--sound/pci/ca0106/ca0106_main.c211
-rw-r--r--sound/pci/ca0106/ca0106_mixer.c76
-rw-r--r--sound/pci/ca0106/ca0106_proc.c31
-rw-r--r--sound/pci/cmipci.c159
-rw-r--r--sound/pci/cs4281.c10
-rw-r--r--sound/pci/cs46xx/cs46xx.c2
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c3
-rw-r--r--sound/pci/emu10k1/emu10k1.c2
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c192
-rw-r--r--sound/pci/emu10k1/emu10k1x.c8
-rw-r--r--sound/pci/emu10k1/emufx.c56
-rw-r--r--sound/pci/emu10k1/emumixer.c14
-rw-r--r--sound/pci/emu10k1/emupcm.c6
-rw-r--r--sound/pci/emu10k1/emuproc.c89
-rw-r--r--sound/pci/emu10k1/irq.c46
-rw-r--r--sound/pci/emu10k1/p16v.c367
-rw-r--r--sound/pci/ens1370.c2
-rw-r--r--sound/pci/es1938.c2
-rw-r--r--sound/pci/es1968.c3
-rw-r--r--sound/pci/fm801.c3
-rw-r--r--sound/pci/hda/Makefile2
-rw-r--r--sound/pci/hda/hda_codec.c206
-rw-r--r--sound/pci/hda/hda_codec.h30
-rw-r--r--sound/pci/hda/hda_generic.c14
-rw-r--r--sound/pci/hda/hda_intel.c119
-rw-r--r--sound/pci/hda/hda_local.h37
-rw-r--r--sound/pci/hda/hda_patch.h3
-rw-r--r--sound/pci/hda/hda_proc.c56
-rw-r--r--sound/pci/hda/patch_analog.c693
-rw-r--r--sound/pci/hda/patch_cmedia.c216
-rw-r--r--sound/pci/hda/patch_realtek.c2503
-rw-r--r--sound/pci/hda/patch_sigmatel.c666
-rw-r--r--sound/pci/ice1712/amp.c30
-rw-r--r--sound/pci/ice1712/amp.h16
-rw-r--r--sound/pci/ice1712/ice1712.c2
-rw-r--r--sound/pci/ice1712/ice1712.h5
-rw-r--r--sound/pci/ice1712/ice1724.c2
-rw-r--r--sound/pci/ice1712/phase.c728
-rw-r--r--sound/pci/ice1712/phase.h19
-rw-r--r--sound/pci/ice1712/vt1720_mobo.c9
-rw-r--r--sound/pci/ice1712/vt1720_mobo.h4
-rw-r--r--sound/pci/intel8x0.c156
-rw-r--r--sound/pci/intel8x0m.c80
-rw-r--r--sound/pci/korg1212/korg1212.c2
-rw-r--r--sound/pci/maestro3.c222
-rw-r--r--sound/pci/mixart/mixart.c2
-rw-r--r--sound/pci/nm256/nm256.c2
-rw-r--r--sound/pci/rme32.c2
-rw-r--r--sound/pci/rme96.c2
-rw-r--r--sound/pci/rme9652/Makefile2
-rw-r--r--sound/pci/rme9652/hdsp.c30
-rw-r--r--sound/pci/rme9652/hdspm.c3671
-rw-r--r--sound/pci/rme9652/rme9652.c16
-rw-r--r--sound/pci/sonicvibes.c2
-rw-r--r--sound/pci/trident/trident.c5
-rw-r--r--sound/pci/via82xx.c145
-rw-r--r--sound/pci/via82xx_modem.c38
-rw-r--r--sound/pci/vx222/vx222.c2
-rw-r--r--sound/pci/ymfpci/ymfpci.c2
-rw-r--r--sound/pci/ymfpci/ymfpci_main.c35
-rw-r--r--sound/pcmcia/vx/vx_entry.c3
-rw-r--r--sound/ppc/pmac.c30
-rw-r--r--sound/sound_core.c10
-rw-r--r--sound/synth/emux/emux.c3
-rw-r--r--sound/synth/emux/emux_effect.c6
-rw-r--r--sound/usb/Kconfig1
-rw-r--r--sound/usb/usbaudio.c310
-rw-r--r--sound/usb/usbaudio.h11
-rw-r--r--sound/usb/usbmidi.c128
-rw-r--r--sound/usb/usbmixer.c588
-rw-r--r--sound/usb/usbmixer_maps.c126
-rw-r--r--sound/usb/usbquirks.h298
-rw-r--r--sound/usb/usx2y/usbusx2y.c13
-rw-r--r--sound/usb/usx2y/usbusx2yaudio.c6
3272 files changed, 199553 insertions, 77453 deletions
diff --git a/CREDITS b/CREDITS
index 3b9e160d6f7..3b7a1548aaf 100644
--- a/CREDITS
+++ b/CREDITS
@@ -882,13 +882,12 @@ S: Blacksburg, Virginia 24061
S: USA
N: Randy Dunlap
-E: rddunlap@osdl.org
+E: rdunlap@xenotime.net
W: http://www.xenotime.net/linux/linux.html
W: http://www.linux-usb.org
D: Linux-USB subsystem, USB core/UHCI/printer/storage drivers
D: x86 SMP, ACPI, bootflag hacking
-S: 12725 SW Millikan Way, Suite 400
-S: Beaverton, Oregon 97005
+S: (ask for current address)
S: USA
N: Bob Dunlop
@@ -1881,6 +1880,13 @@ S: Schlehenweg 9
S: D-91080 Uttenreuth
S: Germany
+N: Jaya Kumar
+E: jayalk@intworks.biz
+W: http://www.intworks.biz
+D: Arc monochrome LCD framebuffer driver, x86 reboot fixups
+S: Gurgaon, India
+S: Kuala Lumpur, Malaysia
+
N: Gabor Kuti
M: seasons@falcon.sch.bme.hu
M: seasons@makosteszta.sote.hu
@@ -2374,9 +2380,10 @@ E: tmolina@cablespeed.com
D: bug fixes, documentation, minor hackery
N: James Morris
-E: jmorris@intercode.com.au
+E: jmorris@redhat.com
W: http://www.intercode.com.au/jmorris/
-D: Netfilter, Linux Security Modules (LSM).
+D: Netfilter, Linux Security Modules (LSM), SELinux, IPSec,
+D: Crypto API, general networking, miscellaneous.
S: PO Box 707
S: Spit Junction NSW 2088
S: Australia
@@ -2476,13 +2483,9 @@ S: Potsdam, New York 13676
S: USA
N: Dave Neuer
-E: dneuer@innovation-charter.com
-E: mr_fred_smoothie@yahoo.com
+E: dave.neuer@pobox.com
D: Helped implement support for Compaq's H31xx series iPAQs
D: Other mostly minor tweaks & bugfixes
-S: 325 E. Main St., Suite 3
-S: Carnegie, PA 15105
-S: USA
N: Michael Neuffer
E: mike@i-Connect.Net
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
index 8de8a01a247..f28a24e0279 100644
--- a/Documentation/00-INDEX
+++ b/Documentation/00-INDEX
@@ -138,6 +138,8 @@ java.txt
- info on the in-kernel binary support for Java(tm).
kbuild/
- directory with info about the kernel build process.
+kdumpt.txt
+ - mini HowTo on getting the crash dump code to work.
kernel-doc-nano-HOWTO.txt
- mini HowTo on generation and location of kernel documentation files.
kernel-docs.txt
diff --git a/Documentation/Changes b/Documentation/Changes
index 57542bc25ed..b3760075476 100644
--- a/Documentation/Changes
+++ b/Documentation/Changes
@@ -63,7 +63,7 @@ o PPP 2.4.0 # pppd --version
o isdn4k-utils 3.1pre1 # isdnctrl 2>&1|grep version
o nfs-utils 1.0.5 # showmount --version
o procps 3.2.0 # ps --version
-o oprofile 0.5.3 # oprofiled --version
+o oprofile 0.9 # oprofiled --version
Kernel compilation
==================
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index e69b3d2e788..fa3e29ad8a4 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -8,7 +8,7 @@
DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \
kernel-hacking.xml kernel-locking.xml deviceiobook.xml \
- procfs-guide.xml writing_usb_driver.xml scsidrivers.xml \
+ procfs-guide.xml writing_usb_driver.xml \
sis900.xml kernel-api.xml journal-api.xml lsm.xml usb.xml \
gadget.xml libata.xml mtdnand.xml librs.xml
@@ -49,7 +49,7 @@ installmandocs: mandocs
KERNELDOC = scripts/kernel-doc
DOCPROC = scripts/basic/docproc
-XMLTOFLAGS = -m Documentation/DocBook/stylesheet.xsl
+XMLTOFLAGS = -m $(srctree)/Documentation/DocBook/stylesheet.xsl
#XMLTOFLAGS += --skip-validation
###
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 757cef8f849..d650ce36485 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -266,7 +266,7 @@ X!Ekernel/module.c
<chapter id="hardware">
<title>Hardware Interfaces</title>
<sect1><title>Interrupt Handling</title>
-!Iarch/i386/kernel/irq.c
+!Ikernel/irq/manage.c
</sect1>
<sect1><title>Resources Management</title>
@@ -338,7 +338,6 @@ X!Earch/i386/kernel/mca.c
X!Iinclude/linux/device.h
-->
!Edrivers/base/driver.c
-!Edrivers/base/class_simple.c
!Edrivers/base/core.c
!Edrivers/base/firmware_class.c
!Edrivers/base/transport_class.c
diff --git a/Documentation/DocBook/libata.tmpl b/Documentation/DocBook/libata.tmpl
index cf2fce7707d..6df1dfd18b6 100644
--- a/Documentation/DocBook/libata.tmpl
+++ b/Documentation/DocBook/libata.tmpl
@@ -14,7 +14,7 @@
</authorgroup>
<copyright>
- <year>2003</year>
+ <year>2003-2005</year>
<holder>Jeff Garzik</holder>
</copyright>
@@ -44,30 +44,38 @@
<toc></toc>
- <chapter id="libataThanks">
- <title>Thanks</title>
+ <chapter id="libataIntroduction">
+ <title>Introduction</title>
<para>
- The bulk of the ATA knowledge comes thanks to long conversations with
- Andre Hedrick (www.linux-ide.org).
+ libATA is a library used inside the Linux kernel to support ATA host
+ controllers and devices. libATA provides an ATA driver API, class
+ transports for ATA and ATAPI devices, and SCSI&lt;-&gt;ATA translation
+ for ATA devices according to the T10 SAT specification.
</para>
<para>
- Thanks to Alan Cox for pointing out similarities
- between SATA and SCSI, and in general for motivation to hack on
- libata.
- </para>
- <para>
- libata's device detection
- method, ata_pio_devchk, and in general all the early probing was
- based on extensive study of Hale Landis's probe/reset code in his
- ATADRVR driver (www.ata-atapi.com).
+ This Guide documents the libATA driver API, library functions, library
+ internals, and a couple sample ATA low-level drivers.
</para>
</chapter>
<chapter id="libataDriverApi">
<title>libata Driver API</title>
+ <para>
+ struct ata_port_operations is defined for every low-level libata
+ hardware driver, and it controls how the low-level driver
+ interfaces with the ATA and SCSI layers.
+ </para>
+ <para>
+ FIS-based drivers will hook into the system with ->qc_prep() and
+ ->qc_issue() high-level hooks. Hardware which behaves in a manner
+ similar to PCI IDE hardware may utilize several generic helpers,
+ defining at a bare minimum the bus I/O addresses of the ATA shadow
+ register blocks.
+ </para>
<sect1>
<title>struct ata_port_operations</title>
+ <sect2><title>Disable ATA port</title>
<programlisting>
void (*port_disable) (struct ata_port *);
</programlisting>
@@ -78,6 +86,9 @@ void (*port_disable) (struct ata_port *);
unplug).
</para>
+ </sect2>
+
+ <sect2><title>Post-IDENTIFY device configuration</title>
<programlisting>
void (*dev_config) (struct ata_port *, struct ata_device *);
</programlisting>
@@ -88,6 +99,9 @@ void (*dev_config) (struct ata_port *, struct ata_device *);
issue of SET FEATURES - XFER MODE, and prior to operation.
</para>
+ </sect2>
+
+ <sect2><title>Set PIO/DMA mode</title>
<programlisting>
void (*set_piomode) (struct ata_port *, struct ata_device *);
void (*set_dmamode) (struct ata_port *, struct ata_device *);
@@ -108,6 +122,9 @@ void (*post_set_mode) (struct ata_port *ap);
->set_dma_mode() is only called if DMA is possible.
</para>
+ </sect2>
+
+ <sect2><title>Taskfile read/write</title>
<programlisting>
void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf);
void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
@@ -120,6 +137,9 @@ void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
taskfile register values.
</para>
+ </sect2>
+
+ <sect2><title>ATA command execute</title>
<programlisting>
void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
</programlisting>
@@ -129,17 +149,37 @@ void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
->tf_load(), to be initiated in hardware.
</para>
+ </sect2>
+
+ <sect2><title>Per-cmd ATAPI DMA capabilities filter</title>
+ <programlisting>
+int (*check_atapi_dma) (struct ata_queued_cmd *qc);
+ </programlisting>
+
+ <para>
+Allow low-level driver to filter ATA PACKET commands, returning a status
+indicating whether or not it is OK to use DMA for the supplied PACKET
+command.
+ </para>
+
+ </sect2>
+
+ <sect2><title>Read specific ATA shadow registers</title>
<programlisting>
u8 (*check_status)(struct ata_port *ap);
-void (*dev_select)(struct ata_port *ap, unsigned int device);
+u8 (*check_altstatus)(struct ata_port *ap);
+u8 (*check_err)(struct ata_port *ap);
</programlisting>
<para>
- Reads the Status ATA shadow register from hardware. On some
- hardware, this has the side effect of clearing the interrupt
- condition.
+ Reads the Status/AltStatus/Error ATA shadow register from
+ hardware. On some hardware, reading the Status register has
+ the side effect of clearing the interrupt condition.
</para>
+ </sect2>
+
+ <sect2><title>Select ATA device on bus</title>
<programlisting>
void (*dev_select)(struct ata_port *ap, unsigned int device);
</programlisting>
@@ -147,9 +187,13 @@ void (*dev_select)(struct ata_port *ap, unsigned int device);
<para>
Issues the low-level hardware command(s) that causes one of N
hardware devices to be considered 'selected' (active and
- available for use) on the ATA bus.
+ available for use) on the ATA bus. This generally has no
+meaning on FIS-based devices.
</para>
+ </sect2>
+
+ <sect2><title>Reset ATA bus</title>
<programlisting>
void (*phy_reset) (struct ata_port *ap);
</programlisting>
@@ -162,17 +206,31 @@ void (*phy_reset) (struct ata_port *ap);
functions ata_bus_reset() or sata_phy_reset() for this hook.
</para>
+ </sect2>
+
+ <sect2><title>Control PCI IDE BMDMA engine</title>
<programlisting>
void (*bmdma_setup) (struct ata_queued_cmd *qc);
void (*bmdma_start) (struct ata_queued_cmd *qc);
+void (*bmdma_stop) (struct ata_port *ap);
+u8 (*bmdma_status) (struct ata_port *ap);
</programlisting>
<para>
- When setting up an IDE BMDMA transaction, these hooks arm
- (->bmdma_setup) and fire (->bmdma_start) the hardware's DMA
- engine.
+When setting up an IDE BMDMA transaction, these hooks arm
+(->bmdma_setup), fire (->bmdma_start), and halt (->bmdma_stop)
+the hardware's DMA engine. ->bmdma_status is used to read the standard
+PCI IDE DMA Status register.
</para>
+ <para>
+These hooks are typically either no-ops, or simply not implemented, in
+FIS-based drivers.
+ </para>
+
+ </sect2>
+
+ <sect2><title>High-level taskfile hooks</title>
<programlisting>
void (*qc_prep) (struct ata_queued_cmd *qc);
int (*qc_issue) (struct ata_queued_cmd *qc);
@@ -190,20 +248,26 @@ int (*qc_issue) (struct ata_queued_cmd *qc);
->qc_issue is used to make a command active, once the hardware
and S/G tables have been prepared. IDE BMDMA drivers use the
helper function ata_qc_issue_prot() for taskfile protocol-based
- dispatch. More advanced drivers roll their own ->qc_issue
- implementation, using this as the "issue new ATA command to
- hardware" hook.
+ dispatch. More advanced drivers implement their own ->qc_issue.
</para>
+ </sect2>
+
+ <sect2><title>Timeout (error) handling</title>
<programlisting>
void (*eng_timeout) (struct ata_port *ap);
</programlisting>
<para>
- This is a high level error handling function, called from the
- error handling thread, when a command times out.
+This is a high level error handling function, called from the
+error handling thread, when a command times out. Most newer
+hardware will implement its own error handling code here. IDE BMDMA
+drivers may use the helper function ata_eng_timeout().
</para>
+ </sect2>
+
+ <sect2><title>Hardware interrupt handling</title>
<programlisting>
irqreturn_t (*irq_handler)(int, void *, struct pt_regs *);
void (*irq_clear) (struct ata_port *);
@@ -216,6 +280,9 @@ void (*irq_clear) (struct ata_port *);
is quiet.
</para>
+ </sect2>
+
+ <sect2><title>SATA phy read/write</title>
<programlisting>
u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg);
void (*scr_write) (struct ata_port *ap, unsigned int sc_reg,
@@ -227,6 +294,9 @@ void (*scr_write) (struct ata_port *ap, unsigned int sc_reg,
if ->phy_reset hook called the sata_phy_reset() helper function.
</para>
+ </sect2>
+
+ <sect2><title>Init and shutdown</title>
<programlisting>
int (*port_start) (struct ata_port *ap);
void (*port_stop) (struct ata_port *ap);
@@ -240,15 +310,17 @@ void (*host_stop) (struct ata_host_set *host_set);
tasks.
</para>
<para>
- ->host_stop() is called when the rmmod or hot unplug process
- begins. The hook must stop all hardware interrupts, DMA
- engines, etc.
- </para>
- <para>
->port_stop() is called after ->host_stop(). It's sole function
is to release DMA/memory resources, now that they are no longer
actively being used.
</para>
+ <para>
+ ->host_stop() is called after all ->port_stop() calls
+have completed. The hook must finalize hardware shutdown, release DMA
+and other resources, etc.
+ </para>
+
+ </sect2>
</sect1>
</chapter>
@@ -279,4 +351,24 @@ void (*host_stop) (struct ata_host_set *host_set);
!Idrivers/scsi/sata_sil.c
</chapter>
+ <chapter id="libataThanks">
+ <title>Thanks</title>
+ <para>
+ The bulk of the ATA knowledge comes thanks to long conversations with
+ Andre Hedrick (www.linux-ide.org), and long hours pondering the ATA
+ and SCSI specifications.
+ </para>
+ <para>
+ Thanks to Alan Cox for pointing out similarities
+ between SATA and SCSI, and in general for motivation to hack on
+ libata.
+ </para>
+ <para>
+ libata's device detection
+ method, ata_pio_devchk, and in general all the early probing was
+ based on extensive study of Hale Landis's probe/reset code in his
+ ATADRVR driver (www.ata-atapi.com).
+ </para>
+ </chapter>
+
</book>
diff --git a/Documentation/DocBook/scsidrivers.tmpl b/Documentation/DocBook/scsidrivers.tmpl
deleted file mode 100644
index d058e65daf1..00000000000
--- a/Documentation/DocBook/scsidrivers.tmpl
+++ /dev/null
@@ -1,193 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-
-<book id="scsidrivers">
- <bookinfo>
- <title>SCSI Subsystem Interfaces</title>
-
- <authorgroup>
- <author>
- <firstname>Douglas</firstname>
- <surname>Gilbert</surname>
- <affiliation>
- <address>
- <email>dgilbert@interlog.com</email>
- </address>
- </affiliation>
- </author>
- </authorgroup>
- <pubdate>2003-08-11</pubdate>
-
- <copyright>
- <year>2002</year>
- <year>2003</year>
- <holder>Douglas Gilbert</holder>
- </copyright>
-
- <legalnotice>
- <para>
- This documentation 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.
- </para>
-
- <para>
- 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.
- </para>
-
- <para>
- 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
- </para>
-
- <para>
- For more details see the file COPYING in the source
- distribution of Linux.
- </para>
- </legalnotice>
-
- </bookinfo>
-
-<toc></toc>
-
- <chapter id="intro">
- <title>Introduction</title>
- <para>
-This document outlines the interface between the Linux scsi mid level
-and lower level drivers. Lower level drivers are variously called HBA
-(host bus adapter) drivers, host drivers (HD) or pseudo adapter drivers.
-The latter alludes to the fact that a lower level driver may be a
-bridge to another IO subsystem (and the "ide-scsi" driver is an example
-of this). There can be many lower level drivers active in a running
-system, but only one per hardware type. For example, the aic7xxx driver
-controls adaptec controllers based on the 7xxx chip series. Most lower
-level drivers can control one or more scsi hosts (a.k.a. scsi initiators).
- </para>
-<para>
-This document can been found in an ASCII text file in the linux kernel
-source: <filename>Documentation/scsi/scsi_mid_low_api.txt</filename> .
-It currently hold a little more information than this document. The
-<filename>drivers/scsi/hosts.h</filename> and <filename>
-drivers/scsi/scsi.h</filename> headers contain descriptions of members
-of important structures for the scsi subsystem.
-</para>
- </chapter>
-
- <chapter id="driver-struct">
- <title>Driver structure</title>
- <para>
-Traditionally a lower level driver for the scsi subsystem has been
-at least two files in the drivers/scsi directory. For example, a
-driver called "xyz" has a header file "xyz.h" and a source file
-"xyz.c". [Actually there is no good reason why this couldn't all
-be in one file.] Some drivers that have been ported to several operating
-systems (e.g. aic7xxx which has separate files for generic and
-OS-specific code) have more than two files. Such drivers tend to have
-their own directory under the drivers/scsi directory.
- </para>
- <para>
-scsi_module.c is normally included at the end of a lower
-level driver. For it to work a declaration like this is needed before
-it is included:
-<programlisting>
- static Scsi_Host_Template driver_template = DRIVER_TEMPLATE;
- /* DRIVER_TEMPLATE should contain pointers to supported interface
- functions. Scsi_Host_Template is defined hosts.h */
- #include "scsi_module.c"
-</programlisting>
- </para>
- <para>
-The scsi_module.c assumes the name "driver_template" is appropriately
-defined. It contains 2 functions:
-<orderedlist>
-<listitem><para>
- init_this_scsi_driver() called during builtin and module driver
- initialization: invokes mid level's scsi_register_host()
-</para></listitem>
-<listitem><para>
- exit_this_scsi_driver() called during closedown: invokes
- mid level's scsi_unregister_host()
-</para></listitem>
-</orderedlist>
- </para>
-<para>
-When a new, lower level driver is being added to Linux, the following
-files (all found in the drivers/scsi directory) will need some attention:
-Makefile, Config.help and Config.in . It is probably best to look at what
-an existing lower level driver does in this regard.
-</para>
- </chapter>
-
- <chapter id="intfunctions">
- <title>Interface Functions</title>
-!EDocumentation/scsi/scsi_mid_low_api.txt
- </chapter>
-
- <chapter id="locks">
- <title>Locks</title>
-<para>
-Each Scsi_Host instance has a spin_lock called Scsi_Host::default_lock
-which is initialized in scsi_register() [found in hosts.c]. Within the
-same function the Scsi_Host::host_lock pointer is initialized to point
-at default_lock with the scsi_assign_lock() function. Thereafter
-lock and unlock operations performed by the mid level use the
-Scsi_Host::host_lock pointer.
-</para>
-<para>
-Lower level drivers can override the use of Scsi_Host::default_lock by
-using scsi_assign_lock(). The earliest opportunity to do this would
-be in the detect() function after it has invoked scsi_register(). It
-could be replaced by a coarser grain lock (e.g. per driver) or a
-lock of equal granularity (i.e. per host). Using finer grain locks
-(e.g. per scsi device) may be possible by juggling locks in
-queuecommand().
-</para>
- </chapter>
-
- <chapter id="changes">
- <title>Changes since lk 2.4 series</title>
-<para>
-io_request_lock has been replaced by several finer grained locks. The lock
-relevant to lower level drivers is Scsi_Host::host_lock and there is one
-per scsi host.
-</para>
-<para>
-The older error handling mechanism has been removed. This means the
-lower level interface functions abort() and reset() have been removed.
-</para>
-<para>
-In the 2.4 series the scsi subsystem configuration descriptions were
-aggregated with the configuration descriptions from all other Linux
-subsystems in the Documentation/Configure.help file. In the 2.5 series,
-the scsi subsystem now has its own (much smaller) drivers/scsi/Config.help
-file.
-</para>
- </chapter>
-
- <chapter id="credits">
- <title>Credits</title>
-<para>
-The following people have contributed to this document:
-<orderedlist>
-<listitem><para>
-Mike Anderson <email>andmike@us.ibm.com</email>
-</para></listitem>
-<listitem><para>
-James Bottomley <email>James.Bottomley@steeleye.com</email>
-</para></listitem>
-<listitem><para>
-Patrick Mansfield <email>patmans@us.ibm.com</email>
-</para></listitem>
-</orderedlist>
-</para>
- </chapter>
-
-</book>
diff --git a/Documentation/DocBook/stylesheet.xsl b/Documentation/DocBook/stylesheet.xsl
index e14c21dda40..64be9f7ee3b 100644
--- a/Documentation/DocBook/stylesheet.xsl
+++ b/Documentation/DocBook/stylesheet.xsl
@@ -2,4 +2,5 @@
<stylesheet xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0">
<param name="chunk.quietly">1</param>
<param name="funcsynopsis.style">ansi</param>
+<param name="funcsynopsis.tabular.threshold">80</param>
</stylesheet>
diff --git a/Documentation/IPMI.txt b/Documentation/IPMI.txt
index 90d10e708ca..84d3d4d10c1 100644
--- a/Documentation/IPMI.txt
+++ b/Documentation/IPMI.txt
@@ -25,9 +25,10 @@ subject and I can't cover it all here!
Configuration
-------------
-The LinuxIPMI driver is modular, which means you have to pick several
+The Linux IPMI driver is modular, which means you have to pick several
things to have it work right depending on your hardware. Most of
-these are available in the 'Character Devices' menu.
+these are available in the 'Character Devices' menu then the IPMI
+menu.
No matter what, you must pick 'IPMI top-level message handler' to use
IPMI. What you do beyond that depends on your needs and hardware.
@@ -35,33 +36,30 @@ IPMI. What you do beyond that depends on your needs and hardware.
The message handler does not provide any user-level interfaces.
Kernel code (like the watchdog) can still use it. If you need access
from userland, you need to select 'Device interface for IPMI' if you
-want access through a device driver. Another interface is also
-available, you may select 'IPMI sockets' in the 'Networking Support'
-main menu. This provides a socket interface to IPMI. You may select
-both of these at the same time, they will both work together.
-
-The driver interface depends on your hardware. If you have a board
-with a standard interface (These will generally be either "KCS",
-"SMIC", or "BT", consult your hardware manual), choose the 'IPMI SI
-handler' option. A driver also exists for direct I2C access to the
-IPMI management controller. Some boards support this, but it is
-unknown if it will work on every board. For this, choose 'IPMI SMBus
-handler', but be ready to try to do some figuring to see if it will
-work.
-
-There is also a KCS-only driver interface supplied, but it is
-depracated in favor of the SI interface.
+want access through a device driver.
+
+The driver interface depends on your hardware. If your system
+properly provides the SMBIOS info for IPMI, the driver will detect it
+and just work. If you have a board with a standard interface (These
+will generally be either "KCS", "SMIC", or "BT", consult your hardware
+manual), choose the 'IPMI SI handler' option. A driver also exists
+for direct I2C access to the IPMI management controller. Some boards
+support this, but it is unknown if it will work on every board. For
+this, choose 'IPMI SMBus handler', but be ready to try to do some
+figuring to see if it will work on your system if the SMBIOS/APCI
+information is wrong or not present. It is fairly safe to have both
+these enabled and let the drivers auto-detect what is present.
You should generally enable ACPI on your system, as systems with IPMI
-should have ACPI tables describing them.
+can have ACPI tables describing them.
If you have a standard interface and the board manufacturer has done
their job correctly, the IPMI controller should be automatically
-detect (via ACPI or SMBIOS tables) and should just work. Sadly, many
-boards do not have this information. The driver attempts standard
-defaults, but they may not work. If you fall into this situation, you
-need to read the section below named 'The SI Driver' on how to
-hand-configure your system.
+detected (via ACPI or SMBIOS tables) and should just work. Sadly,
+many boards do not have this information. The driver attempts
+standard defaults, but they may not work. If you fall into this
+situation, you need to read the section below named 'The SI Driver' or
+"The SMBus Driver" on how to hand-configure your system.
IPMI defines a standard watchdog timer. You can enable this with the
'IPMI Watchdog Timer' config option. If you compile the driver into
@@ -73,6 +71,18 @@ closed (by default it is disabled on close). Go into the 'Watchdog
Cards' menu, enable 'Watchdog Timer Support', and enable the option
'Disable watchdog shutdown on close'.
+IPMI systems can often be powered off using IPMI commands. Select
+'IPMI Poweroff' to do this. The driver will auto-detect if the system
+can be powered off by IPMI. It is safe to enable this even if your
+system doesn't support this option. This works on ATCA systems, the
+Radisys CPI1 card, and any IPMI system that supports standard chassis
+management commands.
+
+If you want the driver to put an event into the event log on a panic,
+enable the 'Generate a panic event to all BMCs on a panic' option. If
+you want the whole panic string put into the event log using OEM
+events, enable the 'Generate OEM events containing the panic string'
+option.
Basic Design
------------
@@ -80,7 +90,7 @@ Basic Design
The Linux IPMI driver is designed to be very modular and flexible, you
only need to take the pieces you need and you can use it in many
different ways. Because of that, it's broken into many chunks of
-code. These chunks are:
+code. These chunks (by module name) are:
ipmi_msghandler - This is the central piece of software for the IPMI
system. It handles all messages, message timing, and responses. The
@@ -93,18 +103,26 @@ ipmi_devintf - This provides a userland IOCTL interface for the IPMI
driver, each open file for this device ties in to the message handler
as an IPMI user.
-ipmi_si - A driver for various system interfaces. This supports
-KCS, SMIC, and may support BT in the future. Unless you have your own
-custom interface, you probably need to use this.
+ipmi_si - A driver for various system interfaces. This supports KCS,
+SMIC, and BT interfaces. Unless you have an SMBus interface or your
+own custom interface, you probably need to use this.
ipmi_smb - A driver for accessing BMCs on the SMBus. It uses the
I2C kernel driver's SMBus interfaces to send and receive IPMI messages
over the SMBus.
-af_ipmi - A network socket interface to IPMI. This doesn't take up
-a character device in your system.
+ipmi_watchdog - IPMI requires systems to have a very capable watchdog
+timer. This driver implements the standard Linux watchdog timer
+interface on top of the IPMI message handler.
+
+ipmi_poweroff - Some systems support the ability to be turned off via
+IPMI commands.
-Note that the KCS-only interface ahs been removed.
+These are all individually selectable via configuration options.
+
+Note that the KCS-only interface has been removed. The af_ipmi driver
+is no longer supported and has been removed because it was impossible
+to do 32 bit emulation on 64-bit kernels with it.
Much documentation for the interface is in the include files. The
IPMI include files are:
@@ -424,7 +442,7 @@ at module load time (for a module) with:
modprobe ipmi_smb.o
addr=<adapter1>,<i2caddr1>[,<adapter2>,<i2caddr2>[,...]]
dbg=<flags1>,<flags2>...
- [defaultprobe=0] [dbg_probe=1]
+ [defaultprobe=1] [dbg_probe=1]
The addresses are specified in pairs, the first is the adapter ID and the
second is the I2C address on that adapter.
@@ -532,3 +550,67 @@ Once you open the watchdog timer, you must write a 'V' character to the
device to close it, or the timer will not stop. This is a new semantic
for the driver, but makes it consistent with the rest of the watchdog
drivers in Linux.
+
+
+Panic Timeouts
+--------------
+
+The OpenIPMI driver supports the ability to put semi-custom and custom
+events in the system event log if a panic occurs. if you enable the
+'Generate a panic event to all BMCs on a panic' option, you will get
+one event on a panic in a standard IPMI event format. If you enable
+the 'Generate OEM events containing the panic string' option, you will
+also get a bunch of OEM events holding the panic string.
+
+
+The field settings of the events are:
+* Generator ID: 0x21 (kernel)
+* EvM Rev: 0x03 (this event is formatting in IPMI 1.0 format)
+* Sensor Type: 0x20 (OS critical stop sensor)
+* Sensor #: The first byte of the panic string (0 if no panic string)
+* Event Dir | Event Type: 0x6f (Assertion, sensor-specific event info)
+* Event Data 1: 0xa1 (Runtime stop in OEM bytes 2 and 3)
+* Event data 2: second byte of panic string
+* Event data 3: third byte of panic string
+See the IPMI spec for the details of the event layout. This event is
+always sent to the local management controller. It will handle routing
+the message to the right place
+
+Other OEM events have the following format:
+Record ID (bytes 0-1): Set by the SEL.
+Record type (byte 2): 0xf0 (OEM non-timestamped)
+byte 3: The slave address of the card saving the panic
+byte 4: A sequence number (starting at zero)
+The rest of the bytes (11 bytes) are the panic string. If the panic string
+is longer than 11 bytes, multiple messages will be sent with increasing
+sequence numbers.
+
+Because you cannot send OEM events using the standard interface, this
+function will attempt to find an SEL and add the events there. It
+will first query the capabilities of the local management controller.
+If it has an SEL, then they will be stored in the SEL of the local
+management controller. If not, and the local management controller is
+an event generator, the event receiver from the local management
+controller will be queried and the events sent to the SEL on that
+device. Otherwise, the events go nowhere since there is nowhere to
+send them.
+
+
+Poweroff
+--------
+
+If the poweroff capability is selected, the IPMI driver will install
+a shutdown function into the standard poweroff function pointer. This
+is in the ipmi_poweroff module. When the system requests a powerdown,
+it will send the proper IPMI commands to do this. This is supported on
+several platforms.
+
+There is a module parameter named "poweroff_control" that may either be zero
+(do a power down) or 2 (do a power cycle, power the system off, then power
+it on in a few seconds). Setting ipmi_poweroff.poweroff_control=x will do
+the same thing on the kernel command line. The parameter is also available
+via the proc filesystem in /proc/ipmi/poweroff_control. Note that if the
+system does not support power cycling, it will always to the power off.
+
+Note that if you have ACPI enabled, the system will prefer using ACPI to
+power off.
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 9838d32b2fe..4d1f41b84eb 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -132,21 +132,6 @@ which require discussion or do not have a clear advantage should
usually be sent first to linux-kernel. Only after the patch is
discussed should the patch then be submitted to Linus.
-For small patches you may want to CC the Trivial Patch Monkey
-trivial@rustcorp.com.au set up by Rusty Russell; which collects "trivial"
-patches. Trivial patches must qualify for one of the following rules:
- Spelling fixes in documentation
- Spelling fixes which could break grep(1).
- Warning fixes (cluttering with useless warnings is bad)
- Compilation fixes (only if they are actually correct)
- Runtime fixes (only if they actually fix things)
- Removing use of deprecated functions/macros (eg. check_region).
- Contact detail and documentation fixes
- Non-portable code replaced by portable code (even in arch-specific,
- since people copy, as long as it's trivial)
- Any fix by the author/maintainer of the file. (ie. patch monkey
- in re-transmission mode)
-
5) Select your CC (e-mail carbon copy) list.
@@ -271,7 +256,7 @@ patch, which certifies that you wrote it or otherwise have the right to
pass it on as a open-source patch. The rules are pretty simple: if you
can certify the below:
- Developer's Certificate of Origin 1.0
+ Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
@@ -291,9 +276,15 @@ can certify the below:
person who certified (a), (b) or (c) and I have not modified
it.
+ (d) I understand and agree that this project and the contribution
+ are public and that a record of the contribution (including all
+ personal information I submit with it, including my sign-off) is
+ maintained indefinitely and may be redistributed consistent with
+ this project or the open source license(s) involved.
+
then you just add a line saying
- Signed-off-by: Random J Developer <random@developer.org>
+ Signed-off-by: Random J Developer <random@developer.example.org>
Some people also put extra tags at the end. They'll just be ignored for
now, but you can do this to mark internal company procedures or just
diff --git a/Documentation/basic_profiling.txt b/Documentation/basic_profiling.txt
index 65e3dc2d443..8764e9f7082 100644
--- a/Documentation/basic_profiling.txt
+++ b/Documentation/basic_profiling.txt
@@ -27,9 +27,13 @@ dump output readprofile -m /boot/System.map > captured_profile
Oprofile
--------
-Get the source (I use 0.8) from http://oprofile.sourceforge.net/
-and add "idle=poll" to the kernel command line
+
+Get the source (see Changes for required version) from
+http://oprofile.sourceforge.net/ and add "idle=poll" to the kernel command
+line.
+
Configure with CONFIG_PROFILING=y and CONFIG_OPROFILE=y & reboot on new kernel
+
./configure --with-kernel-support
make install
@@ -46,7 +50,7 @@ start opcontrol --start
stop opcontrol --stop
dump output opreport > output_file
-To only report on the kernel, run opreport /boot/vmlinux > output_file
+To only report on the kernel, run opreport -l /boot/vmlinux > output_file
A reset is needed to clear old statistics, which survive a reboot.
diff --git a/Documentation/cdrom/sbpcd b/Documentation/cdrom/sbpcd
index d1825dffca3..b3ba63f4ce3 100644
--- a/Documentation/cdrom/sbpcd
+++ b/Documentation/cdrom/sbpcd
@@ -419,6 +419,7 @@ into the file "track01":
*/
#include <stdio.h>
#include <sys/ioctl.h>
+#include <sys/types.h>
#include <linux/cdrom.h>
static struct cdrom_tochdr hdr;
@@ -429,7 +430,7 @@ static int datafile, drive;
static int i, j, limit, track, err;
static char filename[32];
-main(int argc, char *argv[])
+int main(int argc, char *argv[])
{
/*
* open /dev/cdrom
@@ -516,6 +517,7 @@ entry[track+1].cdte_addr.lba=entry[track].cdte_addr.lba+300;
}
arg.addr.lba++;
}
+ return 0;
}
/*===================== end program ========================================*/
@@ -564,15 +566,16 @@ Appendix -- the "cdtester" utility:
#include <stdio.h>
#include <malloc.h>
#include <sys/ioctl.h>
+#include <sys/types.h>
#include <linux/cdrom.h>
#ifdef AZT_PRIVATE_IOCTLS
#include <linux/../../drivers/cdrom/aztcd.h>
-#endif AZT_PRIVATE_IOCTLS
+#endif /* AZT_PRIVATE_IOCTLS */
#ifdef SBP_PRIVATE_IOCTLS
#include <linux/../../drivers/cdrom/sbpcd.h>
#include <linux/fs.h>
-#endif SBP_PRIVATE_IOCTLS
+#endif /* SBP_PRIVATE_IOCTLS */
struct cdrom_tochdr hdr;
struct cdrom_tochdr tocHdr;
@@ -590,7 +593,7 @@ union
struct cdrom_msf msf;
unsigned char buf[CD_FRAMESIZE_RAW];
} azt;
-#endif AZT_PRIVATE_IOCTLS
+#endif /* AZT_PRIVATE_IOCTLS */
int i, i1, i2, i3, j, k;
unsigned char sequence=0;
unsigned char command[80];
@@ -738,7 +741,7 @@ void display(int size,unsigned char *buffer)
}
}
-main(int argc, char *argv[])
+int main(int argc, char *argv[])
{
printf("\nTesting tool for a CDROM driver's audio functions V0.1\n");
printf("(C) 1995 Eberhard Moenkeberg <emoenke@gwdg.de>\n");
@@ -1046,12 +1049,13 @@ main(int argc, char *argv[])
rc=ioctl(drive,CDROMAUDIOBUFSIZ,j);
printf("%d frames granted.\n",rc);
break;
-#endif SBP_PRIVATE_IOCTLS
+#endif /* SBP_PRIVATE_IOCTLS */
default:
printf("unknown command: \"%s\".\n",command);
break;
}
}
+ return 0;
}
/*==========================================================================*/
diff --git a/Documentation/cpu-freq/cpufreq-stats.txt b/Documentation/cpu-freq/cpufreq-stats.txt
new file mode 100644
index 00000000000..e2d1e760b4b
--- /dev/null
+++ b/Documentation/cpu-freq/cpufreq-stats.txt
@@ -0,0 +1,128 @@
+
+ CPU frequency and voltage scaling statictics in the Linux(TM) kernel
+
+
+ L i n u x c p u f r e q - s t a t s d r i v e r
+
+ - information for users -
+
+
+ Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>
+
+Contents
+1. Introduction
+2. Statistics Provided (with example)
+3. Configuring cpufreq-stats
+
+
+1. Introduction
+
+cpufreq-stats is a driver that provices CPU frequency statistics for each CPU.
+This statistics is provided in /sysfs as a bunch of read_only interfaces. This
+interface (when configured) will appear in a seperate directory under cpufreq
+in /sysfs (<sysfs root>/devices/system/cpu/cpuX/cpufreq/stats/) for each CPU.
+Various statistics will form read_only files under this directory.
+
+This driver is designed to be independent of any particular cpufreq_driver
+that may be running on your CPU. So, it will work with any cpufreq_driver.
+
+
+2. Statistics Provided (with example)
+
+cpufreq stats provides following statistics (explained in detail below).
+- time_in_state
+- total_trans
+- trans_table
+
+All the statistics will be from the time the stats driver has been inserted
+to the time when a read of a particular statistic is done. Obviously, stats
+driver will not have any information about the the frequcny transitions before
+the stats driver insertion.
+
+--------------------------------------------------------------------------------
+<mysystem>:/sys/devices/system/cpu/cpu0/cpufreq/stats # ls -l
+total 0
+drwxr-xr-x 2 root root 0 May 14 16:06 .
+drwxr-xr-x 3 root root 0 May 14 15:58 ..
+-r--r--r-- 1 root root 4096 May 14 16:06 time_in_state
+-r--r--r-- 1 root root 4096 May 14 16:06 total_trans
+-r--r--r-- 1 root root 4096 May 14 16:06 trans_table
+--------------------------------------------------------------------------------
+
+- time_in_state
+This gives the amount of time spent in each of the frequencies supported by
+this CPU. The cat output will have "<frequency> <time>" pair in each line, which
+will mean this CPU spent <time> usertime units of time at <frequency>. Output
+will have one line for each of the supported freuencies. usertime units here
+is 10mS (similar to other time exported in /proc).
+
+--------------------------------------------------------------------------------
+<mysystem>:/sys/devices/system/cpu/cpu0/cpufreq/stats # cat time_in_state
+3600000 2089
+3400000 136
+3200000 34
+3000000 67
+2800000 172488
+--------------------------------------------------------------------------------
+
+
+- total_trans
+This gives the total number of frequency transitions on this CPU. The cat
+output will have a single count which is the total number of frequency
+transitions.
+
+--------------------------------------------------------------------------------
+<mysystem>:/sys/devices/system/cpu/cpu0/cpufreq/stats # cat total_trans
+20
+--------------------------------------------------------------------------------
+
+- trans_table
+This will give a fine grained information about all the CPU frequency
+transitions. The cat output here is a two dimensional matrix, where an entry
+<i,j> (row i, column j) represents the count of number of transitions from
+Freq_i to Freq_j. Freq_i is in descending order with increasing rows and
+Freq_j is in descending order with increasing columns. The output here also
+contains the actual freq values for each row and column for better readability.
+
+--------------------------------------------------------------------------------
+<mysystem>:/sys/devices/system/cpu/cpu0/cpufreq/stats # cat trans_table
+ From : To
+ : 3600000 3400000 3200000 3000000 2800000
+ 3600000: 0 5 0 0 0
+ 3400000: 4 0 2 0 0
+ 3200000: 0 1 0 2 0
+ 3000000: 0 0 1 0 3
+ 2800000: 0 0 0 2 0
+--------------------------------------------------------------------------------
+
+
+3. Configuring cpufreq-stats
+
+To configure cpufreq-stats in your kernel
+Config Main Menu
+ Power management options (ACPI, APM) --->
+ CPU Frequency scaling --->
+ [*] CPU Frequency scaling
+ <*> CPU frequency translation statistics
+ [*] CPU frequency translation statistics details
+
+
+"CPU Frequency scaling" (CONFIG_CPU_FREQ) should be enabled to configure
+cpufreq-stats.
+
+"CPU frequency translation statistics" (CONFIG_CPU_FREQ_STAT) provides the
+basic statistics which includes time_in_state and total_trans.
+
+"CPU frequency translation statistics details" (CONFIG_CPU_FREQ_STAT_DETAILS)
+provides fine grained cpufreq stats by trans_table. The reason for having a
+seperate config option for trans_table is:
+- trans_table goes against the traditional /sysfs rule of one value per
+ interface. It provides a whole bunch of value in a 2 dimensional matrix
+ form.
+
+Once these two options are enabled and your CPU supports cpufrequency, you
+will be able to see the CPU frequency statistics in /sysfs.
+
+
+
+
diff --git a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt
index b85481acd0c..933fae74c33 100644
--- a/Documentation/cpu-freq/governors.txt
+++ b/Documentation/cpu-freq/governors.txt
@@ -9,6 +9,7 @@
Dominik Brodowski <linux@brodo.de>
+ some additions and corrections by Nico Golde <nico@ngolde.de>
@@ -25,6 +26,7 @@ Contents:
2.1 Performance
2.2 Powersave
2.3 Userspace
+2.4 Ondemand
3. The Governor Interface in the CPUfreq Core
@@ -86,7 +88,7 @@ highest frequency within the borders of scaling_min_freq and
scaling_max_freq.
-2.1 Powersave
+2.2 Powersave
-------------
The CPUfreq governor "powersave" sets the CPU statically to the
@@ -94,7 +96,7 @@ lowest frequency within the borders of scaling_min_freq and
scaling_max_freq.
-2.2 Userspace
+2.3 Userspace
-------------
The CPUfreq governor "userspace" allows the user, or any userspace
@@ -103,6 +105,14 @@ by making a sysfs file "scaling_setspeed" available in the CPU-device
directory.
+2.4 Ondemand
+------------
+
+The CPUfreq govenor "ondemand" sets the CPU depending on the
+current usage. To do this the CPU must have the capability to
+switch the frequency very fast.
+
+
3. The Governor Interface in the CPUfreq Core
=============================================
diff --git a/Documentation/cpusets.txt b/Documentation/cpusets.txt
index 1ad26d2c20a..ad944c06031 100644
--- a/Documentation/cpusets.txt
+++ b/Documentation/cpusets.txt
@@ -51,6 +51,14 @@ mems_allowed vector.
If a cpuset is cpu or mem exclusive, no other cpuset, other than a direct
ancestor or descendent, may share any of the same CPUs or Memory Nodes.
+A cpuset that is cpu exclusive has a sched domain associated with it.
+The sched domain consists of all cpus in the current cpuset that are not
+part of any exclusive child cpusets.
+This ensures that the scheduler load balacing code only balances
+against the cpus that are in the sched domain as defined above and not
+all of the cpus in the system. This removes any overhead due to
+load balancing code trying to pull tasks outside of the cpu exclusive
+cpuset only to be prevented by the tasks' cpus_allowed mask.
User level code may create and destroy cpusets by name in the cpuset
virtual file system, manage the attributes and permissions of these
@@ -84,6 +92,9 @@ This can be especially valuable on:
and a database), or
* NUMA systems running large HPC applications with demanding
performance characteristics.
+ * Also cpu_exclusive cpusets are useful for servers running orthogonal
+ workloads such as RT applications requiring low latency and HPC
+ applications that are throughput sensitive
These subsets, or "soft partitions" must be able to be dynamically
adjusted, as the job mix changes, without impacting other concurrently
@@ -125,6 +136,8 @@ Cpusets extends these two mechanisms as follows:
- A cpuset may be marked exclusive, which ensures that no other
cpuset (except direct ancestors and descendents) may contain
any overlapping CPUs or Memory Nodes.
+ Also a cpu_exclusive cpuset would be associated with a sched
+ domain.
- You can list all the tasks (by pid) attached to any cpuset.
The implementation of cpusets requires a few, simple hooks
@@ -136,6 +149,9 @@ into the rest of the kernel, none in performance critical paths:
allowed in that tasks cpuset.
- in sched.c migrate_all_tasks(), to keep migrating tasks within
the CPUs allowed by their cpuset, if possible.
+ - in sched.c, a new API partition_sched_domains for handling
+ sched domain changes associated with cpu_exclusive cpusets
+ and related changes in both sched.c and arch/ia64/kernel/domain.c
- in the mbind and set_mempolicy system calls, to mask the requested
Memory Nodes by what's allowed in that tasks cpuset.
- in page_alloc, to restrict memory to allowed nodes.
@@ -252,8 +268,7 @@ in a tasks processor placement.
There is an exception to the above. If hotplug funtionality is used
to remove all the CPUs that are currently assigned to a cpuset,
then the kernel will automatically update the cpus_allowed of all
-tasks attached to CPUs in that cpuset with the online CPUs of the
-nearest parent cpuset that still has some CPUs online. When memory
+tasks attached to CPUs in that cpuset to allow all CPUs. When memory
hotplug functionality for removing Memory Nodes is available, a
similar exception is expected to apply there as well. In general,
the kernel prefers to violate cpuset placement, over starving a task
diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index bb67cf25010..0f515175c72 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -94,6 +94,7 @@ Your cooperation is appreciated.
9 = /dev/urandom Faster, less secure random number gen.
10 = /dev/aio Asyncronous I/O notification interface
11 = /dev/kmsg Writes to this come out as printk's
+ 12 = /dev/oldmem Access to crash dump from kexec kernel
1 block RAM disk
0 = /dev/ram0 First RAM disk
1 = /dev/ram1 Second RAM disk
diff --git a/Documentation/dontdiff b/Documentation/dontdiff
index 9a33bb94f74..d4fda25db86 100644
--- a/Documentation/dontdiff
+++ b/Documentation/dontdiff
@@ -111,6 +111,7 @@ mkdep
mktables
modpost
modversions.h*
+offset.h
offsets.h
oui.c*
parse.c*
diff --git a/Documentation/driver-model/device.txt b/Documentation/driver-model/device.txt
index 58cc5dc8fd3..a05ec50f800 100644
--- a/Documentation/driver-model/device.txt
+++ b/Documentation/driver-model/device.txt
@@ -76,6 +76,14 @@ driver_data: Driver-specific data.
platform_data: Platform data specific to the device.
+ Example: for devices on custom boards, as typical of embedded
+ and SOC based hardware, Linux often uses platform_data to point
+ to board-specific structures describing devices and how they
+ are wired. That can include what ports are available, chip
+ variants, which GPIO pins act in what additional roles, and so
+ on. This shrinks the "Board Support Packages" (BSPs) and
+ minimizes board-specific #ifdefs in drivers.
+
current_state: Current power state of the device.
saved_state: Pointer to saved state of the device. This is usable by
diff --git a/Documentation/driver-model/driver.txt b/Documentation/driver-model/driver.txt
index 6031a68dd3f..fabaca1ab1b 100644
--- a/Documentation/driver-model/driver.txt
+++ b/Documentation/driver-model/driver.txt
@@ -5,21 +5,17 @@ struct device_driver {
char * name;
struct bus_type * bus;
- rwlock_t lock;
- atomic_t refcount;
-
- list_t bus_list;
+ struct completion unloaded;
+ struct kobject kobj;
list_t devices;
- struct driver_dir_entry dir;
+ struct module *owner;
int (*probe) (struct device * dev);
int (*remove) (struct device * dev);
int (*suspend) (struct device * dev, pm_message_t state, u32 level);
int (*resume) (struct device * dev, u32 level);
-
- void (*release) (struct device_driver * drv);
};
@@ -51,7 +47,6 @@ being converted completely to the new model.
static struct device_driver eepro100_driver = {
.name = "eepro100",
.bus = &pci_bus_type,
- .devclass = &ethernet_devclass, /* when it's implemented */
.probe = eepro100_probe,
.remove = eepro100_remove,
@@ -85,7 +80,6 @@ static struct pci_driver eepro100_driver = {
.driver = {
.name = "eepro100",
.bus = &pci_bus_type,
- .devclass = &ethernet_devclass, /* when it's implemented */
.probe = eepro100_probe,
.remove = eepro100_remove,
.suspend = eepro100_suspend,
@@ -166,27 +160,32 @@ Callbacks
int (*probe) (struct device * dev);
-probe is called to verify the existence of a certain type of
-hardware. This is called during the driver binding process, after the
-bus has verified that the device ID of a device matches one of the
-device IDs supported by the driver.
-
-This callback only verifies that there actually is supported hardware
-present. It may allocate a driver-specific structure, but it should
-not do any initialization of the hardware itself. The device-specific
-structure may be stored in the device's driver_data field.
-
- int (*init) (struct device * dev);
-
-init is called during the binding stage. It is called after probe has
-successfully returned and the device has been registered with its
-class. It is responsible for initializing the hardware.
+The probe() entry is called in task context, with the bus's rwsem locked
+and the driver partially bound to the device. Drivers commonly use
+container_of() to convert "dev" to a bus-specific type, both in probe()
+and other routines. That type often provides device resource data, such
+as pci_dev.resource[] or platform_device.resources, which is used in
+addition to dev->platform_data to initialize the driver.
+
+This callback holds the driver-specific logic to bind the driver to a
+given device. That includes verifying that the device is present, that
+it's a version the driver can handle, that driver data structures can
+be allocated and initialized, and that any hardware can be initialized.
+Drivers often store a pointer to their state with dev_set_drvdata().
+When the driver has successfully bound itself to that device, then probe()
+returns zero and the driver model code will finish its part of binding
+the driver to that device.
+
+A driver's probe() may return a negative errno value to indicate that
+the driver did not bind to this device, in which case it should have
+released all reasources it allocated.
int (*remove) (struct device * dev);
-remove is called to dissociate a driver with a device. This may be
+remove is called to unbind a driver from a device. This may be
called if a device is physically removed from the system, if the
-driver module is being unloaded, or during a reboot sequence.
+driver module is being unloaded, during a reboot sequence, or
+in other cases.
It is up to the driver to determine if the device is present or
not. It should free any resources allocated specifically for the
diff --git a/Documentation/dvb/README.dibusb b/Documentation/dvb/README.dvb-usb
index 7a9e958513f..c7ed01b9f8f 100644
--- a/Documentation/dvb/README.dibusb
+++ b/Documentation/dvb/README.dvb-usb
@@ -1,16 +1,40 @@
-Documentation for dib3000* frontend drivers and dibusb device driver
-====================================================================
+Documentation for dvb-usb-framework module and its devices
-Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de),
+Idea behind the dvb-usb-framework
+=================================
-dibusb and dib3000mb/mc drivers based on GPL code, which has
+In March 2005 I got the new Twinhan USB2.0 DVB-T device. They provided specs and a firmware.
-Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr)
+Quite keen I wanted to put the driver (with some quirks of course) into dibusb.
+After reading some specs and doing some USB snooping, it realized, that the
+dibusb-driver would be a complete mess afterwards. So I decided to do it in a
+different way: With the help of a dvb-usb-framework.
-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, version 2.
+The framework provides generic functions (mostly kernel API calls), such as:
+- Transport Stream URB handling in conjunction with dvb-demux-feed-control
+ (bulk and isoc (TODO) are supported)
+- registering the device for the DVB-API
+- registering an I2C-adapter if applicable
+- remote-control/input-device handling
+- firmware requesting and loading (currently just for the Cypress USB
+ controller)
+- other functions/methods which can be shared by several drivers (such as
+ functions for bulk-control-commands)
+
+The source code of the particular DVB USB devices does just the communication
+with the device via the bus. The connection between the DVB-API-functionality
+is done via callbacks, assigned in a static device-description (struct
+dvb_usb_device) each device-driver has to have.
+
+For an example have a look in drivers/media/dvb/dvb-usb/vp7045*.
+
+Objective is to migrate all the usb-devices (dibusb, cinergyT2, maybe the
+ttusb; flexcop-usb already benefits from the generic flexcop-device) to use
+the dvb-usb-lib.
+
+TODO: dynamic enabling and disabling of the pid-filter in regard to number of
+feeds requested.
Supported devices USB1.1
========================
@@ -55,22 +79,34 @@ Others:
- Grandtec USB DVB-T
http://www.grand.com.tw/
-- Avermedia AverTV DVBT USB (2)
+- AVerMedia AverTV DVBT USB
http://www.avermedia.com/
- DiBcom USB DVB-T reference device (non-public)
-Supported devices USB2.0
-========================
-- Twinhan MagicBox II (2)
+Supported devices USB2.0-only
+=============================
+- Twinhan MagicBox II
http://www.twinhan.com/product_terrestrial_7.asp
-- Hanftek UMT-010 (1)
+- TwinhanDTV Alpha
+ http://www.twinhan.com/product_terrestrial_8.asp
+
+- DigitalNow TinyUSB 2 DVB-t Receiver
+ http://www.digitalnow.com.au/DigitalNow%20tinyUSB2%20Specifications.html
+
+- Hanftek UMT-010
http://www.globalsources.com/si/6008819757082/ProductDetail/Digital-TV/product_id-100046529
-- Typhoon/Yakumo/HAMA DVB-T mobile USB2.0 (1)
+
+Supported devices USB2.0 and USB1.1
+=============================
+- Typhoon/Yakumo/HAMA/Yuan DVB-T mobile USB2.0
http://www.yakumo.de/produkte/index.php?pid=1&ag=DVB-T
+ http://www.yuan.com.tw/en/products/vdo_ub300.html
+ http://www.hama.de/portal/articleId*114663/action*2563
+ http://www.anubisline.com/english/articlec.asp?id=50502&catid=002
- Artec T1 USB TVBOX (FX2) (2)
@@ -81,14 +117,24 @@ Supported devices USB2.0
- DiBcom USB2.0 DVB-T reference device (non-public)
-1) It is working almost.
+- AVerMedia AverTV A800 DVB-T USB2.0
+
+1) It is working almost - work-in-progress.
2) No test reports received yet.
+0. History & News:
+ 2005-04-17 - all dibusb devices ported to make use of the dvb-usb-framework
+ 2005-04-02 - re-enabled and improved remote control code.
+ 2005-03-31 - ported the Yakumo/Hama/Typhoon DVB-T USB2.0 device to dvb-usb.
+ 2005-03-30 - first commit of the dvb-usb-module based on the dibusb-source. First device is a new driver for the
+ TwinhanDTV Alpha / MagicBox II USB2.0-only DVB-T device.
-0. NEWS:
+ (change from dvb-dibusb to dvb-usb)
+ 2005-03-28 - added support for the AVerMedia AverTV DVB-T USB2.0 device (Thanks to Glen Harris and Jiun-Kuei Jung, AVerMedia)
+ 2005-03-14 - added support for the Typhoon/Yakumo/HAMA DVB-T mobile USB2.0
2005-02-11 - added support for the KWorld/ADSTech Instant DVB-T USB2.0. Thanks a lot to Joachim von Caron
2005-02-02 - added support for the Hauppauge Win-TV Nova-T USB2
- 2005-01-31 - distorted streaming is finally gone for USB1.1 devices
+ 2005-01-31 - distorted streaming is gone for USB1.1 devices
2005-01-13 - moved the mirrored pid_filter_table back to dvb-dibusb
- first almost working version for HanfTek UMT-010
- found out, that Yakumo/HAMA/Typhoon are predessors of the HanfTek UMT-010
@@ -99,7 +145,7 @@ Supported devices USB2.0
2004-12-26 - refactored the dibusb-driver, splitted into separate files
- i2c-probing enabled
2004-12-06 - possibility for demod i2c-address probing
- - new usb IDs (Compro,Artec)
+ - new usb IDs (Compro, Artec)
2004-11-23 - merged changes from DiB3000MC_ver2.1
- revised the debugging
- possibility to deliver the complete TS for USB2.0
@@ -127,8 +173,8 @@ Supported devices USB2.0
CTS Portable (Chinese Television System)
2004-07-08 - firmware-extraction-2.422-problem solved, driver is now working
properly with firmware extracted from 2.422
- - #if for 2.6.4 (dvb), compile issue
- - changed firmware handling, see vp7041.txt sec 1.1
+ - #if for 2.6.4 (dvb), compile issue
+ - changed firmware handling, see vp7041.txt sec 1.1
2004-07-02 - some tuner modifications, v0.1, cleanups, first public
2004-06-28 - now using the dvb_dmx_swfilter_packets, everything
runs fine now
@@ -139,38 +185,27 @@ Supported devices USB2.0
2004-05-11 - start writing the driver
1. How to use?
-NOTE: This driver was developed using Linux 2.6.6.,
-it is working with 2.6.7 and above.
-
-Linux 2.4.x support is not planned, but patches are very welcome.
-
-NOTE: I'm using Debian testing, so the following explaination (especially
-the hotplug-path) needn't match your system, but probably it will :).
-
-The driver is included in the kernel since Linux 2.6.10.
-
1.1. Firmware
-The USB driver needs to download a firmware to start working.
-
-You can either use "get_dvb_firmware dibusb" to download the firmware or you
-can get it directly via
+Most of the USB drivers need to download a firmware to start working.
-for USB1.1 (AN2135)
-http://www.linuxtv.org/downloads/firmware/dvb-dibusb-5.0.0.11.fw
+for USB1.1 (AN2135) you need: dvb-usb-dibusb-5.0.0.11.fw
+for USB2.0 HanfTek: dvb-usb-umt-010-02.fw
+for USB2.0 DiBcom: dvb-usb-dibusb-6.0.0.8.fw
+for USB2.0 AVerMedia AverTV DVB-T USB2: dvb-usb-avertv-a800-01.fw
+for USB2.0 TwinhanDTV Alpha/MagicBox II: dvb-usb-vp7045-01.fw
-for USB1.1 (AN2235) (a few Artec T1 devices)
-http://www.linuxtv.org/downloads/firmware/dvb-dibusb-an2235-1.fw
+The files can be found on http://www.linuxtv.org/download/firmware/ .
-for USB2.0 (FX2) Hauppauge, DiBcom
-http://www.linuxtv.org/downloads/firmware/dvb-dibusb-6.0.0.5.fw
+We do not have the permission (yet) to publish the following firmware-files.
+You'll need to extract them from the windows drivers.
-for USB2.0 ADSTech/Kworld USB2.0
-http://www.linuxtv.org/downloads/firmware/dvb-dibusb-adstech-usb2-1.fw
-
-for USB2.0 HanfTek
-http://www.linuxtv.org/downloads/firmware/dvb-dibusb-an2235-1.fw
+You should be able to use "get_dvb_firmware dvb-usb" to get the firmware:
+for USB1.1 (AN2235) (a few Artec T1 devices): dvb-usb-dibusb-an2235-01.fw
+for USB2.0 Hauppauge: dvb-usb-nova-t-usb2-01.fw
+for USB2.0 ADSTech/Kworld USB2.0: dvb-usb-adstech-usb2-01.fw
+for USB2.0 Yakumo/Typhoon/Hama: dvb-usb-dtt200u-01.fw
1.2. Compiling
@@ -178,6 +213,9 @@ Since the driver is in the linux kernel, activating the driver in
your favorite config-environment should sufficient. I recommend
to compile the driver as module. Hotplug does the rest.
+If you use dvb-kernel enter the build-2.6 directory run 'make' and 'insmod.sh
+load' afterwards.
+
1.3. Loading the drivers
Hotplug is able to load the driver, when it is needed (because you plugged
@@ -188,15 +226,13 @@ from withing the dvb-kernel cvs repository.
first have a look, which debug level are available:
-modinfo dib3000mb
-modinfo dib3000-common
-modinfo dib3000mc
-modinfo dvb-dibusb
+modinfo dvb-usb
+modinfo dvb-usb-vp7045
+etc.
-modprobe dib3000-common debug=<level>
-modprobe dib3000mb debug=<level>
-modprobe dib3000mc debug=<level>
-modprobe dvb-dibusb debug=<level>
+modprobe dvb-usb debug=<level>
+modprobe dvb-usb-vp7045 debug=<level>
+etc.
should do the trick.
@@ -204,52 +240,32 @@ When the driver is loaded successfully, the firmware file was in
the right place and the device is connected, the "Power"-LED should be
turned on.
-At this point you should be able to start a dvb-capable application. For myself
-I used mplayer, dvbscan, tzap and kaxtv, they are working. Using the device
-in vdr is working now also.
+At this point you should be able to start a dvb-capable application. I'm use
+(t|s)zap, mplayer and dvbscan to test the basics. VDR-xine provides the
+long-term test scenario.
2. Known problems and bugs
-- Don't remove the USB device while running an DVB application, your system will die.
+- Don't remove the USB device while running an DVB application, your system
+ will go crazy or die most likely.
2.1. Adding support for devices
-It is not possible to determine the range of devices based on the DiBcom
-reference designs. This is because the reference design of DiBcom can be sold
-to thirds, without telling DiBcom (so done with the Twinhan VP7041 and
-the HAMA device).
-
-When you think you have a device like this and the driver does not recognizes it,
-please send the ****load*.inf and the ****cap*.inf of the Windows driver to me.
-
-Sometimes the Vendor or Product ID is identical to the ones of Twinhan, even
-though it is not a Twinhan device (e.g. HAMA), then please send me the name
-of the device. I will add it to this list in order to make this clear to
-others.
-
-If you are familar with C you can also add the VID and PID of the device to
-the dvb-dibusb-core.c-file and create a patch and send it over to me or to
-the linux-dvb mailing list, _after_ you have tried compiling and modprobing
-it.
+TODO
2.2. USB1.1 Bandwidth limitation
-Most of the currently supported devices are USB1.1 and thus they have a
+A lot of the currently supported devices are USB1.1 and thus they have a
maximum bandwidth of about 5-6 MBit/s when connected to a USB2.0 hub.
This is not enough for receiving the complete transport stream of a
-DVB-T channel (which can be about 16 MBit/s). Normally this is not a
+DVB-T channel (which is about 16 MBit/s). Normally this is not a
problem, if you only want to watch TV (this does not apply for HDTV),
but watching a channel while recording another channel on the same
frequency simply does not work very well. This applies to all USB1.1
-DVB-T devices, not just dibusb)
-
-Update: For the USB1.1 and VDR some work has been done (patches and comments
-are still very welcome). Maybe the problem is solved in the meantime because I
-now use the dmx_sw_filter function instead of dmx_sw_filter_packet. I hope the
-linux-dvb software filter is able to get the best of the garbled TS.
+DVB-T devices, not just the dvb-usb-devices)
The bug, where the TS is distorted by a heavy usage of the device is gone
-definitely. All dibusb-devices I was using (Twinhan, Kworld, DiBcom) are
+definitely. All dvb-usb-devices I was using (Twinhan, Kworld, DiBcom) are
working like charm now with VDR. Sometimes I even was able to record a channel
and watch another one.
@@ -258,7 +274,7 @@ and watch another one.
Patches, comments and suggestions are very very welcome.
3. Acknowledgements
- Amaury Demol (ademol@dibcom.fr) and Francois Kanounnikoff from DiBcom for
+ Amaury Demol (ademol@dibcom.fr) and Francois Kanounnikoff from DiBcom for
providing specs, code and help, on which the dvb-dibusb, dib3000mb and
dib3000mc are based.
@@ -270,9 +286,16 @@ Patches, comments and suggestions are very very welcome.
Bernd Wagner for helping with huge bug reports and discussions.
- Gunnar Wittich and Joachim von Caron for their trust for giving me
+ Gunnar Wittich and Joachim von Caron for their trust for providing
root-shells on their machines to implement support for new devices.
+ Glen Harris for bringing up, that there is a new dibusb-device and Jiun-Kuei
+ Jung from AVerMedia who kindly provided a special firmware to get the device
+ up and running in Linux.
+
+ Jennifer Chen, Jeff and Jack from Twinhan for kindly supporting by
+ writing the vp7045-driver.
+
Some guys on the linux-dvb mailing list for encouraging me
Peter Schildmann >peter.schildmann-nospam-at-web.de< for his
@@ -282,4 +305,4 @@ Patches, comments and suggestions are very very welcome.
Ulf Hermenau for helping me out with traditional chinese.
André Smoktun and Christian Frömmel for supporting me with
- hardware and listening to my problems very patient
+ hardware and listening to my problems very patient.
diff --git a/Documentation/dvb/README.flexcop b/Documentation/dvb/README.flexcop
new file mode 100644
index 00000000000..a50c70f9ca7
--- /dev/null
+++ b/Documentation/dvb/README.flexcop
@@ -0,0 +1,205 @@
+This README escorted the skystar2-driver rewriting procedure. It describes the
+state of the new flexcop-driver set and some internals are written down here
+too.
+
+This document hopefully describes things about the flexcop and its
+device-offsprings. Goal was to write an easy-to-write and easy-to-read set of
+drivers based on the skystar2.c and other information.
+
+Remark: flexcop-pci.c was a copy of skystar2.c, but every line has been
+touched and rewritten.
+
+History & News
+==============
+ 2005-04-01 - correct USB ISOC transfers (thanks to Vadim Catana)
+
+
+
+
+General coding processing
+=========================
+
+We should proceed as follows (as long as no one complains):
+
+0) Think before start writing code!
+
+1) rewriting the skystar2.c with the help of the flexcop register descriptions
+and splitting up the files to a pci-bus-part and a flexcop-part.
+The new driver will be called b2c2-flexcop-pci.ko/b2c2-flexcop-usb.ko for the
+device-specific part and b2c2-flexcop.ko for the common flexcop-functions.
+
+2) Search for errors in the leftover of flexcop-pci.c (compare with pluto2.c
+and other pci drivers)
+
+3) make some beautification (see 'Improvements when rewriting (refactoring) is
+done')
+
+4) Testing the new driver and maybe substitute the skystar2.c with it, to reach
+a wider tester audience.
+
+5) creating an usb-bus-part using the already written flexcop code for the pci
+card.
+
+Idea: create a kernel-object for the flexcop and export all important
+functions. This option saves kernel-memory, but maybe a lot of functions have
+to be exported to kernel namespace.
+
+
+Current situation
+=================
+
+0) Done :)
+1) Done (some minor issues left)
+2) Done
+3) Not ready yet, more information is necessary
+4) next to be done (see the table below)
+5) USB driver is working (yes, there are some minor issues)
+
+What seems to be ready?
+-----------------------
+
+1) Rewriting
+1a) i2c is cut off from the flexcop-pci.c and seems to work
+1b) moved tuner and demod stuff from flexcop-pci.c to flexcop-tuner-fe.c
+1c) moved lnb and diseqc stuff from flexcop-pci.c to flexcop-tuner-fe.c
+1e) eeprom (reading MAC address)
+1d) sram (no dynamic sll size detection (commented out) (using default as JJ told me))
+1f) misc. register accesses for reading parameters (e.g. resetting, revision)
+1g) pid/mac filter (flexcop-hw-filter.c)
+1i) dvb-stuff initialization in flexcop.c (done)
+1h) dma stuff (now just using the size-irq, instead of all-together, to be done)
+1j) remove flexcop initialization from flexcop-pci.c completely (done)
+1l) use a well working dma IRQ method (done, see 'Known bugs and problems and TODO')
+1k) cleanup flexcop-files (remove unused EXPORT_SYMBOLs, make static from
+non-static where possible, moved code to proper places)
+
+2) Search for errors in the leftover of flexcop-pci.c (partially done)
+5a) add MAC address reading
+5c) feeding of ISOC data to the software demux (format of the isochronous data
+and speed optimization, no real error) (thanks to Vadim Catana)
+
+What to do in the near future?
+--------------------------------------
+(no special order here)
+
+5) USB driver
+5b) optimize isoc-transfer (submitting/killing isoc URBs when transfer is starting)
+
+Testing changes
+---------------
+
+O = item is working
+P = item is partially working
+X = item is not working
+N = item does not apply here
+<empty field> = item need to be examined
+
+ | PCI | USB
+item | mt352 | nxt2002 | stv0299 | mt312 | mt352 | nxt2002 | stv0299 | mt312
+-------+-------+---------+---------+-------+-------+---------+---------+-------
+1a) | O | | | | N | N | N | N
+1b) | O | | | | | | O |
+1c) | N | N | | | N | N | O |
+1d) | O | O
+1e) | O | O
+1f) | P
+1g) | O
+1h) | P |
+1i) | O | N
+1j) | O | N
+1l) | O | N
+2) | O | N
+5a) | N | O
+5b)* | N |
+5c) | N | O
+
+* - not done yet
+
+Known bugs and problems and TODO
+--------------------------------
+
+1g/h/l) when pid filtering is enabled on the pci card
+
+DMA usage currently:
+ The DMA is splitted in 2 equal-sized subbuffers. The Flexcop writes to first
+ address and triggers an IRQ when it's full and starts writing to the second
+ address. When the second address is full, the IRQ is triggered again, and
+ the flexcop writes to first address again, and so on.
+ The buffersize of each address is currently 640*188 bytes.
+
+ Problem is, when using hw-pid-filtering and doing some low-bandwidth
+ operation (like scanning) the buffers won't be filled enough to trigger
+ the IRQ. That's why:
+
+ When PID filtering is activated, the timer IRQ is used. Every 1.97 ms the IRQ
+ is triggered. Is the current write address of DMA1 different to the one
+ during the last IRQ, then the data is passed to the demuxer.
+
+ There is an additional DMA-IRQ-method: packet count IRQ. This isn't
+ implemented correctly yet.
+
+ The solution is to disable HW PID filtering, but I don't know how the DVB
+ API software demux behaves on slow systems with 45MBit/s TS.
+
+Solved bugs :)
+--------------
+1g) pid-filtering (somehow pid index 4 and 5 (EMM_PID and ECM_PID) aren't
+working)
+SOLUTION: also index 0 was affected, because net_translation is done for
+these indexes by default
+
+5b) isochronous transfer does only work in the first attempt (for the Sky2PC
+USB, Air2PC is working) SOLUTION: the flexcop was going asleep and never really
+woke up again (don't know if this need fixes, see
+flexcop-fe-tuner.c:flexcop_sleep)
+
+NEWS: when the driver is loaded and unloaded and loaded again (w/o doing
+anything in the while the driver is loaded the first time), no transfers take
+place anymore.
+
+Improvements when rewriting (refactoring) is done
+=================================================
+
+- split sleeping of the flexcop (misc_204.ACPI3_sig = 1;) from lnb_control
+ (enable sleeping for other demods than dvb-s)
+- add support for CableStar (stv0297 Microtune 203x/ALPS) (almost done, incompatibilities with the Nexus-CA)
+
+Debugging
+---------
+- add verbose debugging to skystar2.c (dump the reg_dw_data) and compare it
+ with this flexcop, this is important, because i2c is now using the
+ flexcop_ibi_value union from flexcop-reg.h (do you have a better idea for
+ that, please tell us so).
+
+Everything which is identical in the following table, can be put into a common
+flexcop-module.
+
+ PCI USB
+-------------------------------------------------------------------------------
+Different:
+Register access: accessing IO memory USB control message
+I2C bus: I2C bus of the FC USB control message
+Data transfer: DMA isochronous transfer
+EEPROM transfer: through i2c bus not clear yet
+
+Identical:
+Streaming: accessing registers
+PID Filtering: accessing registers
+Sram destinations: accessing registers
+Tuner/Demod: I2C bus
+DVB-stuff: can be written for common use
+
+Acknowledgements (just for the rewriting part)
+================
+
+Bjarne Steinsbo thought a lot in the first place of the pci part for this code
+sharing idea.
+
+Andreas Oberritter for providing a recent PCI initialization template
+(pluto2.c).
+
+Boleslaw Ciesielski for pointing out a problem with firmware loader.
+
+Vadim Catana for correcting the USB transfer.
+
+comments, critics and ideas to linux-dvb@linuxtv.org.
diff --git a/Documentation/dvb/bt8xx.txt b/Documentation/dvb/bt8xx.txt
index e3cacf4f234..3a326079475 100644
--- a/Documentation/dvb/bt8xx.txt
+++ b/Documentation/dvb/bt8xx.txt
@@ -17,74 +17,50 @@ Because of this, you need to enable
"Device drivers" => "Multimedia devices"
=> "Video For Linux" => "BT848 Video For Linux"
+Furthermore you need to enable
+"Device drivers" => "Multimedia devices" => "Digital Video Broadcasting Devices"
+ => "DVB for Linux" "DVB Core Support" "Nebula/Pinnacle PCTV/TwinHan PCI Cards"
+
2) Loading Modules
==================
In general you need to load the bttv driver, which will handle the gpio and
-i2c communication for us. Next you need the common dvb-bt8xx device driver
-and one frontend driver.
-
-The bttv driver will HANG YOUR SYSTEM IF YOU DO NOT SPECIFY THE CORRECT
-CARD ID!
-
-(If you don't get your card running and you suspect that the card id you're
-using is wrong, have a look at "bttv-cards.c" for a list of possible card
-ids.)
-
-Pay attention to failures when you load the frontend drivers
-(e.g. dmesg, /var/log/messages).
+i2c communication for us, plus the common dvb-bt8xx device driver.
+The frontends for Nebula (nxt6000), Pinnacle PCTV (cx24110) and
+TwinHan (dst) are loaded automatically by the dvb-bt8xx device driver.
3a) Nebula / Pinnacle PCTV
--------------------------
- $ modprobe bttv i2c_hw=1 card=0x68
- $ modprobe dvb-bt8xx
-
-For Nebula cards use the "nxt6000" frontend driver:
- $ modprobe nxt6000
+ $ modprobe bttv (normally bttv is being loaded automatically by kmod)
+ $ modprobe dvb-bt8xx (or just place dvb-bt8xx in /etc/modules for automatic loading)
-For Pinnacle PCTV cards use the "cx24110" frontend driver:
- $ modprobe cx24110
-3b) TwinHan
------------
+3b) TwinHan and Clones
+--------------------------
$ modprobe bttv i2c_hw=1 card=0x71
$ modprobe dvb-bt8xx
$ modprobe dst
-The value 0x71 will override the PCI type detection for dvb-bt8xx, which
-is necessary for TwinHan cards.#
-
-If you're having an older card (blue color circuit) and card=0x71 locks your
-machine, try using 0x68, too. If that does not work, ask on the DVB mailing list.
-
-The DST module takes a couple of useful parameters, in case the
-dst drivers fails to detect your type of card correctly.
-
-dst_type takes values 0 (satellite), 1 (terrestial TV), 2 (cable).
-
-dst_type_flags takes bit combined values:
-1 = new tuner type packets. You can use this if your card is detected
- and you have debug and you continually see the tuner packets not
- working (make sure not a basic problem like dish alignment etc.)
-
-2 = TS 204. If your card tunes OK, but the picture is terrible, seemingly
- breaking up in one half continually, and crc fails a lot, then
- this is worth a try (or trying to turn off)
-
-4 = has symdiv. Some cards, mostly without new tuner packets, require
- a symbol division algorithm. Doesn't apply to terrestial TV.
+The value 0x71 will override the PCI type detection for dvb-bt8xx,
+which is necessary for TwinHan cards.
-You can also specify a value to have the autodetected values turned off
-(e.g. 0). The autodected values are determined bythe cards 'response
-string' which you can see in your logs e.g.
+If you're having an older card (blue color circuit) and card=0x71 locks
+your machine, try using 0x68, too. If that does not work, ask on the
+mailing list.
-dst_check_ci: recognize DST-MOT
+The DST module takes a couple of useful parameters:
-or
+a. verbose takes values 0 to 5. These values control the verbosity level.
+b. debug takes values 0 and 1. You can either disable or enable debugging.
+c. dst_addons takes values 0 and 0x20:
+- A value of 0 means it is a FTA card.
+- A value of 0x20 means it has a Conditional Access slot.
-dst_check_ci: unable to recognize DSTXCI or STXCI
+The autodetected values are determined by the "response string"
+of the card, which you can see in your logs:
+e.g.: dst_get_device_id: Recognize [DSTMCI]
--
-Authors: Richard Walker, Jamie Honan, Michael Hunold
+Authors: Richard Walker, Jamie Honan, Michael Hunold, Manu Abraham, Uwe Bugla
diff --git a/Documentation/dvb/ci.txt b/Documentation/dvb/ci.txt
new file mode 100644
index 00000000000..62e0701b542
--- /dev/null
+++ b/Documentation/dvb/ci.txt
@@ -0,0 +1,219 @@
+* For the user
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+NOTE: This document describes the usage of the high level CI API as
+in accordance to the Linux DVB API. This is a not a documentation for the,
+existing low level CI API.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To utilize the High Level CI capabilities,
+
+(1*) This point is valid only for the Twinhan/clones
+ For the Twinhan/Twinhan clones, the dst_ca module handles the CI
+ hardware handling.This module is loaded automatically if a CI
+ (Common Interface, that holds the CAM (Conditional Access Module)
+ is detected.
+
+(2) one requires a userspace application, ca_zap. This small userland
+ application is in charge of sending the descrambling related information
+ to the CAM.
+
+This application requires the following to function properly as of now.
+
+ (a) Tune to a valid channel, with szap.
+ eg: $ szap -c channels.conf -r "TMC" -x
+
+ (b) a channels.conf containing a valid PMT PID
+
+ eg: TMC:11996:h:0:27500:278:512:650:321
+
+ here 278 is a valid PMT PID. the rest of the values are the
+ same ones that szap uses.
+
+ (c) after running a szap, you have to run ca_zap, for the
+ descrambler to function,
+
+ eg: $ ca_zap patched_channels.conf "TMC"
+
+ The patched means a patch to apply to scan, such that scan can
+ generate a channels.conf_with pmt, which has this PMT PID info
+ (NOTE: szap cannot use this channels.conf with the PMT_PID)
+
+
+ (d) Hopeflly Enjoy your favourite subscribed channel as you do with
+ a FTA card.
+
+(3) Currently ca_zap, and dst_test, both are meant for demonstration
+ purposes only, they can become full fledged applications if necessary.
+
+
+* Cards that fall in this category
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+At present the cards that fall in this category are the Twinhan and it's
+clones, these cards are available as VVMER, Tomato, Hercules, Orange and
+so on.
+
+* CI modules that are supported
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The CI module support is largely dependant upon the firmware on the cards
+Some cards do support almost all of the available CI modules. There is
+nothing much that can be done in order to make additional CI modules
+working with these cards.
+
+Modules that have been tested by this driver at present are
+
+(1) Irdeto 1 and 2 from SCM
+(2) Viaccess from SCM
+(3) Dragoncam
+
+* The High level CI API
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+* For the programmer
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+With the High Level CI approach any new card with almost any random
+architecture can be implemented with this style, the definitions
+insidethe switch statement can be easily adapted for any card, thereby
+eliminating the need for any additional ioctls.
+
+The disadvantage is that the driver/hardware has to manage the rest. For
+the application programmer it would be as simple as sending/receiving an
+array to/from the CI ioctls as defined in the Linux DVB API. No changes
+have been made in the API to accomodate this feature.
+
+
+* Why the need for another CI interface ?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+This is one of the most commonly asked question. Well a nice question.
+Strictly speaking this is not a new interface.
+
+The CI interface is defined in the DVB API in ca.h as
+
+typedef struct ca_slot_info {
+ int num; /* slot number */
+
+ int type; /* CA interface this slot supports */
+#define CA_CI 1 /* CI high level interface */
+#define CA_CI_LINK 2 /* CI link layer level interface */
+#define CA_CI_PHYS 4 /* CI physical layer level interface */
+#define CA_DESCR 8 /* built-in descrambler */
+#define CA_SC 128 /* simple smart card interface */
+
+ unsigned int flags;
+#define CA_CI_MODULE_PRESENT 1 /* module (or card) inserted */
+#define CA_CI_MODULE_READY 2
+} ca_slot_info_t;
+
+
+
+This CI interface follows the CI high level interface, which is not
+implemented by most applications. Hence this area is revisited.
+
+This CI interface is quite different in the case that it tries to
+accomodate all other CI based devices, that fall into the other categories
+
+This means that this CI interface handles the EN50221 style tags in the
+Application layer only and no session management is taken care of by the
+application. The driver/hardware will take care of all that.
+
+This interface is purely an EN50221 interface exchanging APDU's. This
+means that no session management, link layer or a transport layer do
+exist in this case in the application to driver communication. It is
+as simple as that. The driver/hardware has to take care of that.
+
+
+With this High Level CI interface, the interface can be defined with the
+regular ioctls.
+
+All these ioctls are also valid for the High level CI interface
+
+#define CA_RESET _IO('o', 128)
+#define CA_GET_CAP _IOR('o', 129, ca_caps_t)
+#define CA_GET_SLOT_INFO _IOR('o', 130, ca_slot_info_t)
+#define CA_GET_DESCR_INFO _IOR('o', 131, ca_descr_info_t)
+#define CA_GET_MSG _IOR('o', 132, ca_msg_t)
+#define CA_SEND_MSG _IOW('o', 133, ca_msg_t)
+#define CA_SET_DESCR _IOW('o', 134, ca_descr_t)
+#define CA_SET_PID _IOW('o', 135, ca_pid_t)
+
+
+On querying the device, the device yields information thus
+
+CA_GET_SLOT_INFO
+----------------------------
+Command = [info]
+APP: Number=[1]
+APP: Type=[1]
+APP: flags=[1]
+APP: CI High level interface
+APP: CA/CI Module Present
+
+CA_GET_CAP
+----------------------------
+Command = [caps]
+APP: Slots=[1]
+APP: Type=[1]
+APP: Descrambler keys=[16]
+APP: Type=[1]
+
+CA_SEND_MSG
+----------------------------
+Descriptors(Program Level)=[ 09 06 06 04 05 50 ff f1]
+Found CA descriptor @ program level
+
+(20) ES type=[2] ES pid=[201] ES length =[0 (0x0)]
+(25) ES type=[4] ES pid=[301] ES length =[0 (0x0)]
+ca_message length is 25 (0x19) bytes
+EN50221 CA MSG=[ 9f 80 32 19 03 01 2d d1 f0 08 01 09 06 06 04 05 50 ff f1 02 e0 c9 00 00 04 e1 2d 00 00]
+
+
+Not all ioctl's are implemented in the driver from the API, the other
+features of the hardware that cannot be implemented by the API are achieved
+using the CA_GET_MSG and CA_SEND_MSG ioctls. An EN50221 style wrapper is
+used to exchange the data to maintain compatibility with other hardware.
+
+
+/* a message to/from a CI-CAM */
+typedef struct ca_msg {
+ unsigned int index;
+ unsigned int type;
+ unsigned int length;
+ unsigned char msg[256];
+} ca_msg_t;
+
+
+The flow of data can be described thus,
+
+
+
+
+
+ App (User)
+ -----
+ parse
+ |
+ |
+ v
+ en50221 APDU (package)
+ --------------------------------------
+ | | | High Level CI driver
+ | | |
+ | v |
+ | en50221 APDU (unpackage) |
+ | | |
+ | | |
+ | v |
+ | sanity checks |
+ | | |
+ | | |
+ | v |
+ | do (H/W dep) |
+ --------------------------------------
+ | Hardware
+ |
+ v
+
+
+
+
+The High Level CI interface uses the EN50221 DVB standard, following a
+standard ensures futureproofness.
diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware
index 3ffdcb39429..a750f0101d9 100644
--- a/Documentation/dvb/get_dvb_firmware
+++ b/Documentation/dvb/get_dvb_firmware
@@ -107,7 +107,7 @@ sub tda10045 {
sub tda10046 {
my $sourcefile = "tt_budget_217g.zip";
my $url = "http://www.technotrend.de/new/217g/$sourcefile";
- my $hash = "a25b579e37109af60f4a36c37893957c";
+ my $hash = "6a7e1e2f2644b162ff0502367553c72d";
my $outfile = "dvb-fe-tda10046.fw";
my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
@@ -115,7 +115,7 @@ sub tda10046 {
wgetfile($sourcefile, $url);
unzip($sourcefile, $tmpdir);
- extract("$tmpdir/software/OEM/PCI/App/ttlcdacc.dll", 0x3f731, 24479, "$tmpdir/fwtmp");
+ extract("$tmpdir/software/OEM/PCI/App/ttlcdacc.dll", 0x3f731, 24478, "$tmpdir/fwtmp");
verify("$tmpdir/fwtmp", $hash);
copy("$tmpdir/fwtmp", $outfile);
diff --git a/Documentation/fb/intelfb.txt b/Documentation/fb/intelfb.txt
new file mode 100644
index 00000000000..c12d39a23c3
--- /dev/null
+++ b/Documentation/fb/intelfb.txt
@@ -0,0 +1,135 @@
+Intel 830M/845G/852GM/855GM/865G/915G Framebuffer driver
+================================================================
+
+A. Introduction
+ This is a framebuffer driver for various Intel 810/815 compatible
+graphics devices. These would include:
+
+ Intel 830M
+ Intel 810E845G
+ Intel 852GM
+ Intel 855GM
+ Intel 865G
+ Intel 915G
+
+B. List of available options
+
+ a. "video=intelfb"
+ enables the intelfb driver
+
+ Recommendation: required
+
+ b. "mode=<xres>x<yres>[-<bpp>][@<refresh>]"
+ select mode
+
+ Recommendation: user preference
+ (default = 1024x768-32@70)
+
+ c. "vram=<value>"
+ select amount of system RAM in MB to allocate for the video memory
+ if not enough RAM was already allocated by the BIOS.
+
+ Recommendation: 1 - 4 MB.
+ (default = 4 MB)
+
+ d. "voffset=<value>"
+ select at what offset in MB of the logical memory to allocate the
+ framebuffer memory. The intent is to avoid the memory blocks
+ used by standard graphics applications (XFree86). Depending on your
+ usage, adjust the value up or down, (0 for maximum usage, 63/127 MB
+ for the least amount). Note, an arbitrary setting may conflict
+ with XFree86.
+
+ Recommendation: do not set
+ (default = 48 MB)
+
+ e. "accel"
+ enable text acceleration. This can be enabled/reenabled anytime
+ by using 'fbset -accel true/false'.
+
+ Recommendation: enable
+ (default = set)
+
+ f. "hwcursor"
+ enable cursor acceleration.
+
+ Recommendation: enable
+ (default = set)
+
+ g. "mtrr"
+ enable MTRR. This allows data transfers to the framebuffer memory
+ to occur in bursts which can significantly increase performance.
+ Not very helpful with the intel chips because of 'shared memory'.
+
+ Recommendation: set
+ (default = set)
+
+ h. "fixed"
+ disable mode switching.
+
+ Recommendation: do not set
+ (default = not set)
+
+ The binary parameters can be unset with a "no" prefix, example "noaccel".
+ The default parameter (not named) is the mode.
+
+C. Kernel booting
+
+Separate each option/option-pair by commas (,) and the option from its value
+with an equals sign (=) as in the following:
+
+video=i810fb:option1,option2=value2
+
+Sample Usage
+------------
+
+In /etc/lilo.conf, add the line:
+
+append="video=intelfb:800x600-32@75,accel,hwcursor,vram=8"
+
+This will initialize the framebuffer to 800x600 at 32bpp and 75Hz. The
+framebuffer will use 8 MB of System RAM. hw acceleration of text and cursor
+will be enabled.
+
+D. Module options
+
+ The module parameters are essentially similar to the kernel
+parameters. The main difference is that you need to include a Boolean value
+(1 for TRUE, and 0 for FALSE) for those options which don't need a value.
+
+Example, to enable MTRR, include "mtrr=1".
+
+Sample Usage
+------------
+
+Using the same setup as described above, load the module like this:
+
+ modprobe intelfb mode=800x600-32@75 vram=8 accel=1 hwcursor=1
+
+Or just add the following to /etc/modprobe.conf
+
+ options intelfb mode=800x600-32@75 vram=8 accel=1 hwcursor=1
+
+and just do a
+
+ modprobe intelfb
+
+
+E. Acknowledgment:
+
+ 1. Geert Uytterhoeven - his excellent howto and the virtual
+ framebuffer driver code made this possible.
+
+ 2. Jeff Hartmann for his agpgart code.
+
+ 3. David Dawes for his original kernel 2.4 code.
+
+ 4. The X developers. Insights were provided just by reading the
+ XFree86 source code.
+
+ 5. Antonino A. Daplas for his inspiring i810fb driver.
+
+ 6. Andrew Morton for his kernel patches maintenance.
+
+###########################
+Sylvain
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index d3c52dd24a2..1d227ee3792 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -43,6 +43,14 @@ Who: Randy Dunlap <rddunlap@osdl.org>
---------------------------
+What: RAW driver (CONFIG_RAW_DRIVER)
+When: December 2005
+Why: declared obsolete since kernel 2.6.3
+ O_DIRECT can be used instead
+Who: Adrian Bunk <bunk@stusta.de>
+
+---------------------------
+
What: register_ioctl32_conversion() / unregister_ioctl32_conversion()
When: April 2005
Why: Replaced by ->compat_ioctl in file_operations and other method
@@ -63,3 +71,51 @@ Why: Outside of Linux, the only implementations of anything even
people, who might be using implementations that I am not aware
of, to adjust to this upcoming change.
Who: Paul E. McKenney <paulmck@us.ibm.com>
+
+---------------------------
+
+What: remove verify_area()
+When: July 2006
+Files: Various uaccess.h headers.
+Why: Deprecated and redundant. access_ok() should be used instead.
+Who: Jesper Juhl <juhl-lkml@dif.dk>
+
+---------------------------
+
+What: IEEE1394 Audio and Music Data Transmission Protocol driver,
+ Connection Management Procedures driver
+When: November 2005
+Files: drivers/ieee1394/{amdtp,cmp}*
+Why: These are incomplete, have never worked, and are better implemented
+ in userland via raw1394 (see http://freebob.sourceforge.net/ for
+ example.)
+Who: Jody McIntyre <scjody@steamballoon.com>
+
+---------------------------
+
+What: raw1394: requests of type RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN
+When: November 2005
+Why: Deprecated in favour of the new ioctl-based rawiso interface, which is
+ more efficient. You should really be using libraw1394 for raw1394
+ access anyway.
+Who: Jody McIntyre <scjody@steamballoon.com>
+
+---------------------------
+
+What: register_serial/unregister_serial
+When: December 2005
+Why: This interface does not allow serial ports to be registered against
+ a struct device, and as such does not allow correct power management
+ of such ports. 8250-based ports should use serial8250_register_port
+ and serial8250_unregister_port instead.
+Who: Russell King <rmk@arm.linux.org.uk>
+
+---------------------------
+
+What: i2c sysfs name change: in1_ref, vid deprecated in favour of cpu0_vid
+When: November 2005
+Files: drivers/i2c/chips/adm1025.c, drivers/i2c/chips/adm1026.c
+Why: Match the other drivers' name for the same function, duplicate names
+ will be available until removal of old names.
+Who: Grant Coady <gcoady@gmail.com>
+
diff --git a/Documentation/filesystems/ext2.txt b/Documentation/filesystems/ext2.txt
index b5cb9110cc6..d16334ec48b 100644
--- a/Documentation/filesystems/ext2.txt
+++ b/Documentation/filesystems/ext2.txt
@@ -58,6 +58,8 @@ noacl Don't support POSIX ACLs.
nobh Do not attach buffer_heads to file pagecache.
+xip Use execute in place (no caching) if possible
+
grpquota,noquota,quota,usrquota Quota options are silently ignored by ext2.
diff --git a/Documentation/filesystems/isofs.txt b/Documentation/filesystems/isofs.txt
index f64a1050668..424585ff6ea 100644
--- a/Documentation/filesystems/isofs.txt
+++ b/Documentation/filesystems/isofs.txt
@@ -26,7 +26,11 @@ Mount options unique to the isofs filesystem.
mode=xxx Sets the permissions on files to xxx
nojoliet Ignore Joliet extensions if they are present.
norock Ignore Rock Ridge extensions if they are present.
- unhide Show hidden files.
+ hide Completely strip hidden files from the file system.
+ showassoc Show files marked with the 'associated' bit
+ unhide Deprecated; showing hidden files is now default;
+ If given, it is a synonym for 'showassoc' which will
+ recreate previous unhide behavior
session=x Select number of session on multisession CD
sbsector=xxx Session begins from sector xxx
diff --git a/Documentation/filesystems/sysfs-pci.txt b/Documentation/filesystems/sysfs-pci.txt
index e97d024eae7..988a62fae11 100644
--- a/Documentation/filesystems/sysfs-pci.txt
+++ b/Documentation/filesystems/sysfs-pci.txt
@@ -7,7 +7,6 @@ that support it. For example, a given bus might look like this:
|-- 0000:17:00.0
| |-- class
| |-- config
- | |-- detach_state
| |-- device
| |-- irq
| |-- local_cpus
@@ -19,7 +18,7 @@ that support it. For example, a given bus might look like this:
| |-- subsystem_device
| |-- subsystem_vendor
| `-- vendor
- `-- detach_state
+ `-- ...
The topmost element describes the PCI domain and bus number. In this case,
the domain number is 0000 and the bus number is 17 (both values are in hex).
@@ -31,7 +30,6 @@ files, each with their own function.
---- --------
class PCI class (ascii, ro)
config PCI config space (binary, rw)
- detach_state connection status (bool, rw)
device PCI device (ascii, ro)
irq IRQ number (ascii, ro)
local_cpus nearby CPU mask (cpumask, ro)
@@ -85,4 +83,4 @@ useful return codes should be provided.
Legacy resources are protected by the HAVE_PCI_LEGACY define. Platforms
wishing to support legacy functionality should define it and provide
-pci_legacy_read, pci_legacy_write and pci_mmap_legacy_page_range functions. \ No newline at end of file
+pci_legacy_read, pci_legacy_write and pci_mmap_legacy_page_range functions.
diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt
index 60f6c2c4d47..dc276598a65 100644
--- a/Documentation/filesystems/sysfs.txt
+++ b/Documentation/filesystems/sysfs.txt
@@ -214,7 +214,7 @@ Other notes:
A very simple (and naive) implementation of a device attribute is:
-static ssize_t show_name(struct device * dev, char * buf)
+static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf,"%s\n",dev->name);
}
diff --git a/Documentation/filesystems/tmpfs.txt b/Documentation/filesystems/tmpfs.txt
index 417e3095fe3..0d783c504ea 100644
--- a/Documentation/filesystems/tmpfs.txt
+++ b/Documentation/filesystems/tmpfs.txt
@@ -71,8 +71,8 @@ can be changed on remount. The size parameter also accepts a suffix %
to limit this tmpfs instance to that percentage of your physical RAM:
the default, when neither size nor nr_blocks is specified, is size=50%
-If both nr_blocks (or size) and nr_inodes are set to 0, neither blocks
-nor inodes will be limited in that instance. It is generally unwise to
+If nr_blocks=0 (or size=0), blocks will not be limited in that instance;
+if nr_inodes=0, inodes will not be limited. It is generally unwise to
mount with such options, since it allows any user with write access to
use up all the memory on the machine; but enhances the scalability of
that instance in a system with many cpus making intensive use of it.
@@ -97,4 +97,4 @@ RAM/SWAP in 10240 inodes and it is only accessible by root.
Author:
Christoph Rohland <cr@sap.com>, 1.12.01
Updated:
- Hugh Dickins <hugh@veritas.com>, 01 September 2004
+ Hugh Dickins <hugh@veritas.com>, 13 March 2005
diff --git a/Documentation/filesystems/xip.txt b/Documentation/filesystems/xip.txt
new file mode 100644
index 00000000000..6c0cef10eb4
--- /dev/null
+++ b/Documentation/filesystems/xip.txt
@@ -0,0 +1,67 @@
+Execute-in-place for file mappings
+----------------------------------
+
+Motivation
+----------
+File mappings are performed by mapping page cache pages to userspace. In
+addition, read&write type file operations also transfer data from/to the page
+cache.
+
+For memory backed storage devices that use the block device interface, the page
+cache pages are in fact copies of the original storage. Various approaches
+exist to work around the need for an extra copy. The ramdisk driver for example
+does read the data into the page cache, keeps a reference, and discards the
+original data behind later on.
+
+Execute-in-place solves this issue the other way around: instead of keeping
+data in the page cache, the need to have a page cache copy is eliminated
+completely. With execute-in-place, read&write type operations are performed
+directly from/to the memory backed storage device. For file mappings, the
+storage device itself is mapped directly into userspace.
+
+This implementation was initialy written for shared memory segments between
+different virtual machines on s390 hardware to allow multiple machines to
+share the same binaries and libraries.
+
+Implementation
+--------------
+Execute-in-place is implemented in three steps: block device operation,
+address space operation, and file operations.
+
+A block device operation named direct_access is used to retrieve a
+reference (pointer) to a block on-disk. The reference is supposed to be
+cpu-addressable, physical address and remain valid until the release operation
+is performed. A struct block_device reference is used to address the device,
+and a sector_t argument is used to identify the individual block. As an
+alternative, memory technology devices can be used for this.
+
+The block device operation is optional, these block devices support it as of
+today:
+- dcssblk: s390 dcss block device driver
+
+An address space operation named get_xip_page is used to retrieve reference
+to a struct page. To address the target page, a reference to an address_space,
+and a sector number is provided. A 3rd argument indicates whether the
+function should allocate blocks if needed.
+
+This address space operation is mutually exclusive with readpage&writepage that
+do page cache read/write operations.
+The following filesystems support it as of today:
+- ext2: the second extended filesystem, see Documentation/filesystems/ext2.txt
+
+A set of file operations that do utilize get_xip_page can be found in
+mm/filemap_xip.c . The following file operation implementations are provided:
+- aio_read/aio_write
+- readv/writev
+- sendfile
+
+The generic file operations do_sync_read/do_sync_write can be used to implement
+classic synchronous IO calls.
+
+Shortcomings
+------------
+This implementation is limited to storage devices that are cpu addressable at
+all times (no highmem or such). It works well on rom/ram, but enhancements are
+needed to make it work with flash in read+write mode.
+Putting the Linux kernel and/or its modules on a xip filesystem does not mean
+they are not copied.
diff --git a/Documentation/i2c/busses/i2c-sis69x b/Documentation/i2c/busses/i2c-sis69x
index 5be48769f65..b88953dfd58 100644
--- a/Documentation/i2c/busses/i2c-sis69x
+++ b/Documentation/i2c/busses/i2c-sis69x
@@ -42,7 +42,7 @@ I suspect that this driver could be made to work for the following SiS
chipsets as well: 635, and 635T. If anyone owns a board with those chips
AND is willing to risk crashing & burning an otherwise well-behaved kernel
in the name of progress... please contact me at <mhoffman@lightlink.com> or
-via the project's mailing list: <sensors@stimpy.netroedge.com>. Please
+via the project's mailing list: <lm-sensors@lm-sensors.org>. Please
send bug reports and/or success stories as well.
diff --git a/Documentation/i2c/chips/adm1021 b/Documentation/i2c/chips/adm1021
new file mode 100644
index 00000000000..03d02bfb3df
--- /dev/null
+++ b/Documentation/i2c/chips/adm1021
@@ -0,0 +1,111 @@
+Kernel driver adm1021
+=====================
+
+Supported chips:
+ * Analog Devices ADM1021
+ Prefix: 'adm1021'
+ Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+ Datasheet: Publicly available at the Analog Devices website
+ * Analog Devices ADM1021A/ADM1023
+ Prefix: 'adm1023'
+ Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+ Datasheet: Publicly available at the Analog Devices website
+ * Genesys Logic GL523SM
+ Prefix: 'gl523sm'
+ Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+ Datasheet:
+ * Intel Xeon Processor
+ Prefix: - any other - may require 'force_adm1021' parameter
+ Addresses scanned: none
+ Datasheet: Publicly available at Intel website
+ * Maxim MAX1617
+ Prefix: 'max1617'
+ Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+ Datasheet: Publicly available at the Maxim website
+ * Maxim MAX1617A
+ Prefix: 'max1617a'
+ Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+ Datasheet: Publicly available at the Maxim website
+ * National Semiconductor LM84
+ Prefix: 'lm84'
+ Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+ Datasheet: Publicly available at the National Semiconductor website
+ * Philips NE1617
+ Prefix: 'max1617' (probably detected as a max1617)
+ Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+ Datasheet: Publicly available at the Philips website
+ * Philips NE1617A
+ Prefix: 'max1617' (probably detected as a max1617)
+ Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+ Datasheet: Publicly available at the Philips website
+ * TI THMC10
+ Prefix: 'thmc10'
+ Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+ Datasheet: Publicly available at the TI website
+ * Onsemi MC1066
+ Prefix: 'mc1066'
+ Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+ Datasheet: Publicly available at the Onsemi website
+
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>,
+ Philip Edelbrock <phil@netroedge.com>
+
+Module Parameters
+-----------------
+
+* read_only: int
+ Don't set any values, read only mode
+
+
+Description
+-----------
+
+The chips supported by this driver are very similar. The Maxim MAX1617 is
+the oldest; it has the problem that it is not very well detectable. The
+MAX1617A solves that. The ADM1021 is a straight clone of the MAX1617A.
+Ditto for the THMC10. From here on, we will refer to all these chips as
+ADM1021-clones.
+
+The ADM1021 and MAX1617A reports a die code, which is a sort of revision
+code. This can help us pinpoint problems; it is not very useful
+otherwise.
+
+ADM1021-clones implement two temperature sensors. One of them is internal,
+and measures the temperature of the chip itself; the other is external and
+is realised in the form of a transistor-like device. A special alarm
+indicates whether the remote sensor is connected.
+
+Each sensor has its own low and high limits. When they are crossed, the
+corresponding alarm is set and remains on as long as the temperature stays
+out of range. Temperatures are measured in degrees Celsius. Measurements
+are possible between -65 and +127 degrees, with a resolution of one degree.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may already
+have disappeared!
+
+This driver only updates its values each 1.5 seconds; reading it more often
+will do no harm, but will return 'old' values. It is possible to make
+ADM1021-clones do faster measurements, but there is really no good reason
+for that.
+
+Xeon support
+------------
+
+Some Xeon processors have real max1617, adm1021, or compatible chips
+within them, with two temperature sensors.
+
+Other Xeons have chips with only one sensor.
+
+If you have a Xeon, and the adm1021 module loads, and both temperatures
+appear valid, then things are good.
+
+If the adm1021 module doesn't load, you should try this:
+ modprobe adm1021 force_adm1021=BUS,ADDRESS
+ ADDRESS can only be 0x18, 0x1a, 0x29, 0x2b, 0x4c, or 0x4e.
+
+If you have dual Xeons you may have appear to have two separate
+adm1021-compatible chips, or two single-temperature sensors, at distinct
+addresses.
diff --git a/Documentation/i2c/chips/adm1025 b/Documentation/i2c/chips/adm1025
new file mode 100644
index 00000000000..39d2b781b5d
--- /dev/null
+++ b/Documentation/i2c/chips/adm1025
@@ -0,0 +1,51 @@
+Kernel driver adm1025
+=====================
+
+Supported chips:
+ * Analog Devices ADM1025, ADM1025A
+ Prefix: 'adm1025'
+ Addresses scanned: I2C 0x2c - 0x2e
+ Datasheet: Publicly available at the Analog Devices website
+ * Philips NE1619
+ Prefix: 'ne1619'
+ Addresses scanned: I2C 0x2c - 0x2d
+ Datasheet: Publicly available at the Philips website
+
+The NE1619 presents some differences with the original ADM1025:
+ * Only two possible addresses (0x2c - 0x2d).
+ * No temperature offset register, but we don't use it anyway.
+ * No INT mode for pin 16. We don't play with it anyway.
+
+Authors:
+ Chen-Yuan Wu <gwu@esoft.com>,
+ Jean Delvare <khali@linux-fr.org>
+
+Description
+-----------
+
+(This is from Analog Devices.) The ADM1025 is a complete system hardware
+monitor for microprocessor-based systems, providing measurement and limit
+comparison of various system parameters. Five voltage measurement inputs
+are provided, for monitoring +2.5V, +3.3V, +5V and +12V power supplies and
+the processor core voltage. The ADM1025 can monitor a sixth power-supply
+voltage by measuring its own VCC. One input (two pins) is dedicated to a
+remote temperature-sensing diode and an on-chip temperature sensor allows
+ambient temperature to be monitored.
+
+One specificity of this chip is that the pin 11 can be hardwired in two
+different manners. It can act as the +12V power-supply voltage analog
+input, or as the a fifth digital entry for the VID reading (bit 4). It's
+kind of strange since both are useful, and the reason for designing the
+chip that way is obscure at least to me. The bit 5 of the configuration
+register can be used to define how the chip is hardwired. Please note that
+it is not a choice you have to make as the user. The choice was already
+made by your motherboard's maker. If the configuration bit isn't set
+properly, you'll have a wrong +12V reading or a wrong VID reading. The way
+the driver handles that is to preserve this bit through the initialization
+process, assuming that the BIOS set it up properly beforehand. If it turns
+out not to be true in some cases, we'll provide a module parameter to force
+modes.
+
+This driver also supports the ADM1025A, which differs from the ADM1025
+only in that it has "open-drain VID inputs while the ADM1025 has on-chip
+100k pull-ups on the VID inputs". It doesn't make any difference for us.
diff --git a/Documentation/i2c/chips/adm1026 b/Documentation/i2c/chips/adm1026
new file mode 100644
index 00000000000..473c689d792
--- /dev/null
+++ b/Documentation/i2c/chips/adm1026
@@ -0,0 +1,93 @@
+Kernel driver adm1026
+=====================
+
+Supported chips:
+ * Analog Devices ADM1026
+ Prefix: 'adm1026'
+ Addresses scanned: I2C 0x2c, 0x2d, 0x2e
+ Datasheet: Publicly available at the Analog Devices website
+ http://www.analog.com/en/prod/0,,766_825_ADM1026,00.html
+
+Authors:
+ Philip Pokorny <ppokorny@penguincomputing.com> for Penguin Computing
+ Justin Thiessen <jthiessen@penguincomputing.com>
+
+Module Parameters
+-----------------
+
+* gpio_input: int array (min = 1, max = 17)
+ List of GPIO pins (0-16) to program as inputs
+* gpio_output: int array (min = 1, max = 17)
+ List of GPIO pins (0-16) to program as outputs
+* gpio_inverted: int array (min = 1, max = 17)
+ List of GPIO pins (0-16) to program as inverted
+* gpio_normal: int array (min = 1, max = 17)
+ List of GPIO pins (0-16) to program as normal/non-inverted
+* gpio_fan: int array (min = 1, max = 8)
+ List of GPIO pins (0-7) to program as fan tachs
+
+
+Description
+-----------
+
+This driver implements support for the Analog Devices ADM1026. Analog
+Devices calls it a "complete thermal system management controller."
+
+The ADM1026 implements three (3) temperature sensors, 17 voltage sensors,
+16 general purpose digital I/O lines, eight (8) fan speed sensors (8-bit),
+an analog output and a PWM output along with limit, alarm and mask bits for
+all of the above. There is even 8k bytes of EEPROM memory on chip.
+
+Temperatures are measured in degrees Celsius. There are two external
+sensor inputs and one internal sensor. Each sensor has a high and low
+limit. If the limit is exceeded, an interrupt (#SMBALERT) can be
+generated. The interrupts can be masked. In addition, there are over-temp
+limits for each sensor. If this limit is exceeded, the #THERM output will
+be asserted. The current temperature and limits have a resolution of 1
+degree.
+
+Fan rotation speeds are reported in RPM (rotations per minute) but measured
+in counts of a 22.5kHz internal clock. Each fan has a high limit which
+corresponds to a minimum fan speed. If the limit is exceeded, an interrupt
+can be generated. Each fan can be programmed to divide the reference clock
+by 1, 2, 4 or 8. Not all RPM values can accurately be represented, so some
+rounding is done. With a divider of 8, the slowest measurable speed of a
+two pulse per revolution fan is 661 RPM.
+
+There are 17 voltage sensors. An alarm is triggered if the voltage has
+crossed a programmable minimum or maximum limit. Note that minimum in this
+case always means 'closest to zero'; this is important for negative voltage
+measurements. Several inputs have integrated attenuators so they can measure
+higher voltages directly. 3.3V, 5V, 12V, -12V and battery voltage all have
+dedicated inputs. There are several inputs scaled to 0-3V full-scale range
+for SCSI terminator power. The remaining inputs are not scaled and have
+a 0-2.5V full-scale range. A 2.5V or 1.82V reference voltage is provided
+for negative voltage measurements.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may already
+have disappeared! Note that in the current implementation, all hardware
+registers are read whenever any data is read (unless it is less than 2.0
+seconds since the last update). This means that you can easily miss
+once-only alarms.
+
+The ADM1026 measures continuously. Analog inputs are measured about 4
+times a second. Fan speed measurement time depends on fan speed and
+divisor. It can take as long as 1.5 seconds to measure all fan speeds.
+
+The ADM1026 has the ability to automatically control fan speed based on the
+temperature sensor inputs. Both the PWM output and the DAC output can be
+used to control fan speed. Usually only one of these two outputs will be
+used. Write the minimum PWM or DAC value to the appropriate control
+register. Then set the low temperature limit in the tmin values for each
+temperature sensor. The range of control is fixed at 20 °C, and the
+largest difference between current and tmin of the temperature sensors sets
+the control output. See the datasheet for several example circuits for
+controlling fan speed with the PWM and DAC outputs. The fan speed sensors
+do not have PWM compensation, so it is probably best to control the fan
+voltage from the power lead rather than on the ground lead.
+
+The datasheet shows an example application with VID signals attached to
+GPIO lines. Unfortunately, the chip may not be connected to the VID lines
+in this way. The driver assumes that the chips *is* connected this way to
+get a VID voltage.
diff --git a/Documentation/i2c/chips/adm1031 b/Documentation/i2c/chips/adm1031
new file mode 100644
index 00000000000..130a38382b9
--- /dev/null
+++ b/Documentation/i2c/chips/adm1031
@@ -0,0 +1,35 @@
+Kernel driver adm1031
+=====================
+
+Supported chips:
+ * Analog Devices ADM1030
+ Prefix: 'adm1030'
+ Addresses scanned: I2C 0x2c to 0x2e
+ Datasheet: Publicly available at the Analog Devices website
+ http://products.analog.com/products/info.asp?product=ADM1030
+
+ * Analog Devices ADM1031
+ Prefix: 'adm1031'
+ Addresses scanned: I2C 0x2c to 0x2e
+ Datasheet: Publicly available at the Analog Devices website
+ http://products.analog.com/products/info.asp?product=ADM1031
+
+Authors:
+ Alexandre d'Alton <alex@alexdalton.org>
+ Jean Delvare <khali@linux-fr.org>
+
+Description
+-----------
+
+The ADM1030 and ADM1031 are digital temperature sensors and fan controllers.
+They sense their own temperature as well as the temperature of up to one
+(ADM1030) or two (ADM1031) external diodes.
+
+All temperature values are given in degrees Celsius. Resolution is 0.5
+degree for the local temperature, 0.125 degree for the remote temperatures.
+
+Each temperature channel has its own high and low limits, plus a critical
+limit.
+
+The ADM1030 monitors a single fan speed, while the ADM1031 monitors up to
+two. Each fan channel has its own low speed limit.
diff --git a/Documentation/i2c/chips/adm9240 b/Documentation/i2c/chips/adm9240
new file mode 100644
index 00000000000..35f618f3289
--- /dev/null
+++ b/Documentation/i2c/chips/adm9240
@@ -0,0 +1,177 @@
+Kernel driver adm9240
+=====================
+
+Supported chips:
+ * Analog Devices ADM9240
+ Prefix: 'adm9240'
+ Addresses scanned: I2C 0x2c - 0x2f
+ Datasheet: Publicly available at the Analog Devices website
+ http://www.analog.com/UploadedFiles/Data_Sheets/79857778ADM9240_0.pdf
+
+ * Dallas Semiconductor DS1780
+ Prefix: 'ds1780'
+ Addresses scanned: I2C 0x2c - 0x2f
+ Datasheet: Publicly available at the Dallas Semiconductor (Maxim) website
+ http://pdfserv.maxim-ic.com/en/ds/DS1780.pdf
+
+ * National Semiconductor LM81
+ Prefix: 'lm81'
+ Addresses scanned: I2C 0x2c - 0x2f
+ Datasheet: Publicly available at the National Semiconductor website
+ http://www.national.com/ds.cgi/LM/LM81.pdf
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>,
+ Philip Edelbrock <phil@netroedge.com>,
+ Michiel Rook <michiel@grendelproject.nl>,
+ Grant Coady <gcoady@gmail.com> with guidance
+ from Jean Delvare <khali@linux-fr.org>
+
+Interface
+---------
+The I2C addresses listed above assume BIOS has not changed the
+chip MSB 5-bit address. Each chip reports a unique manufacturer
+identification code as well as the chip revision/stepping level.
+
+Description
+-----------
+[From ADM9240] The ADM9240 is a complete system hardware monitor for
+microprocessor-based systems, providing measurement and limit comparison
+of up to four power supplies and two processor core voltages, plus
+temperature, two fan speeds and chassis intrusion. Measured values can
+be read out via an I2C-compatible serial System Management Bus, and values
+for limit comparisons can be programmed in over the same serial bus. The
+high speed successive approximation ADC allows frequent sampling of all
+analog channels to ensure a fast interrupt response to any out-of-limit
+measurement.
+
+The ADM9240, DS1780 and LM81 are register compatible, the following
+details are common to the three chips. Chip differences are described
+after this section.
+
+
+Measurements
+------------
+The measurement cycle
+
+The adm9240 driver will take a measurement reading no faster than once
+each two seconds. User-space may read sysfs interface faster than the
+measurement update rate and will receive cached data from the most
+recent measurement.
+
+ADM9240 has a very fast 320us temperature and voltage measurement cycle
+with independent fan speed measurement cycles counting alternating rising
+edges of the fan tacho inputs.
+
+DS1780 measurement cycle is about once per second including fan speed.
+
+LM81 measurement cycle is about once per 400ms including fan speed.
+The LM81 12-bit extended temperature measurement mode is not supported.
+
+Temperature
+-----------
+On chip temperature is reported as degrees Celsius as 9-bit signed data
+with resolution of 0.5 degrees Celsius. High and low temperature limits
+are 8-bit signed data with resolution of one degree Celsius.
+
+Temperature alarm is asserted once the temperature exceeds the high limit,
+and is cleared when the temperature falls below the temp1_max_hyst value.
+
+Fan Speed
+---------
+Two fan tacho inputs are provided, the ADM9240 gates an internal 22.5kHz
+clock via a divider to an 8-bit counter. Fan speed (rpm) is calculated by:
+
+rpm = (22500 * 60) / (count * divider)
+
+Automatic fan clock divider
+
+ * User sets 0 to fan_min limit
+ - low speed alarm is disabled
+ - fan clock divider not changed
+ - auto fan clock adjuster enabled for valid fan speed reading
+
+ * User sets fan_min limit too low
+ - low speed alarm is enabled
+ - fan clock divider set to max
+ - fan_min set to register value 254 which corresponds
+ to 664 rpm on adm9240
+ - low speed alarm will be asserted if fan speed is
+ less than minimum measurable speed
+ - auto fan clock adjuster disabled
+
+ * User sets reasonable fan speed
+ - low speed alarm is enabled
+ - fan clock divider set to suit fan_min
+ - auto fan clock adjuster enabled: adjusts fan_min
+
+ * User sets unreasonably high low fan speed limit
+ - resolution of the low speed limit may be reduced
+ - alarm will be asserted
+ - auto fan clock adjuster enabled: adjusts fan_min
+
+ * fan speed may be displayed as zero until the auto fan clock divider
+ adjuster brings fan speed clock divider back into chip measurement
+ range, this will occur within a few measurement cycles.
+
+Analog Output
+-------------
+An analog output provides a 0 to 1.25 volt signal intended for an external
+fan speed amplifier circuit. The analog output is set to maximum value on
+power up or reset. This doesn't do much on the test Intel SE440BX-2.
+
+Voltage Monitor
+
+Voltage (IN) measurement is internally scaled:
+
+ nr label nominal maximum resolution
+ mV mV mV
+ 0 +2.5V 2500 3320 13.0
+ 1 Vccp1 2700 3600 14.1
+ 2 +3.3V 3300 4380 17.2
+ 3 +5V 5000 6640 26.0
+ 4 +12V 12000 15940 62.5
+ 5 Vccp2 2700 3600 14.1
+
+The reading is an unsigned 8-bit value, nominal voltage measurement is
+represented by a reading of 192, being 3/4 of the measurement range.
+
+An alarm is asserted for any voltage going below or above the set limits.
+
+The driver reports and accepts voltage limits scaled to the above table.
+
+VID Monitor
+-----------
+The chip has five inputs to read the 5-bit VID and reports the mV value
+based on detected CPU type.
+
+Chassis Intrusion
+-----------------
+An alarm is asserted when the CI pin goes active high. The ADM9240
+Datasheet has an example of an external temperature sensor driving
+this pin. On an Intel SE440BX-2 the Chassis Intrusion header is
+connected to a normally open switch.
+
+The ADM9240 provides an internal open drain on this line, and may output
+a 20 ms active low pulse to reset an external Chassis Intrusion latch.
+
+Clear the CI latch by writing value 1 to the sysfs chassis_clear file.
+
+Alarm flags reported as 16-bit word
+
+ bit label comment
+ --- ------------- --------------------------
+ 0 +2.5 V_Error high or low limit exceeded
+ 1 VCCP_Error high or low limit exceeded
+ 2 +3.3 V_Error high or low limit exceeded
+ 3 +5 V_Error high or low limit exceeded
+ 4 Temp_Error temperature error
+ 6 FAN1_Error fan low limit exceeded
+ 7 FAN2_Error fan low limit exceeded
+ 8 +12 V_Error high or low limit exceeded
+ 9 VCCP2_Error high or low limit exceeded
+ 12 Chassis_Error CI pin went high
+
+Remaining bits are reserved and thus undefined. It is important to note
+that alarm bits may be cleared on read, user-space may latch alarms and
+provide the end-user with a method to clear alarm memory.
diff --git a/Documentation/i2c/chips/asb100 b/Documentation/i2c/chips/asb100
new file mode 100644
index 00000000000..ab7365e139b
--- /dev/null
+++ b/Documentation/i2c/chips/asb100
@@ -0,0 +1,72 @@
+Kernel driver asb100
+====================
+
+Supported Chips:
+ * Asus ASB100 and ASB100-A "Bach"
+ Prefix: 'asb100'
+ Addresses scanned: I2C 0x2d
+ Datasheet: none released
+
+Author: Mark M. Hoffman <mhoffman@lightlink.com>
+
+Description
+-----------
+
+This driver implements support for the Asus ASB100 and ASB100-A "Bach".
+These are custom ASICs available only on Asus mainboards. Asus refuses to
+supply a datasheet for these chips. Thanks go to many people who helped
+investigate their hardware, including:
+
+Vitaly V. Bursov
+Alexander van Kaam (author of MBM for Windows)
+Bertrik Sikken
+
+The ASB100 implements seven voltage sensors, three fan rotation speed
+sensors, four temperature sensors, VID lines and alarms. In addition to
+these, the ASB100-A also implements a single PWM controller for fans 2 and
+3 (i.e. one setting controls both.) If you have a plain ASB100, the PWM
+controller will simply not work (or maybe it will for you... it doesn't for
+me).
+
+Temperatures are measured and reported in degrees Celsius.
+
+Fan speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit.
+
+Voltage sensors (also known as IN sensors) report values in volts.
+
+The VID lines encode the core voltage value: the voltage level your
+processor should work with. This is hardcoded by the mainboard and/or
+processor itself. It is a value in volts.
+
+Alarms: (TODO question marks indicate may or may not work)
+
+0x0001 => in0 (?)
+0x0002 => in1 (?)
+0x0004 => in2
+0x0008 => in3
+0x0010 => temp1 (1)
+0x0020 => temp2
+0x0040 => fan1
+0x0080 => fan2
+0x0100 => in4
+0x0200 => in5 (?) (2)
+0x0400 => in6 (?) (2)
+0x0800 => fan3
+0x1000 => chassis switch
+0x2000 => temp3
+
+Alarm Notes:
+
+(1) This alarm will only trigger if the hysteresis value is 127C.
+I.e. it behaves the same as w83781d.
+
+(2) The min and max registers for these values appear to
+be read-only or otherwise stuck at 0x00.
+
+TODO:
+* Experiment with fan divisors > 8.
+* Experiment with temp. sensor types.
+* Are there really 13 voltage inputs? Probably not...
+* Cleanups, no doubt...
+
diff --git a/Documentation/i2c/chips/ds1621 b/Documentation/i2c/chips/ds1621
new file mode 100644
index 00000000000..1fee6f1e6bc
--- /dev/null
+++ b/Documentation/i2c/chips/ds1621
@@ -0,0 +1,108 @@
+Kernel driver ds1621
+====================
+
+Supported chips:
+ * Dallas Semiconductor DS1621
+ Prefix: 'ds1621'
+ Addresses scanned: I2C 0x48 - 0x4f
+ Datasheet: Publicly available at the Dallas Semiconductor website
+ http://www.dalsemi.com/
+ * Dallas Semiconductor DS1625
+ Prefix: 'ds1621'
+ Addresses scanned: I2C 0x48 - 0x4f
+ Datasheet: Publicly available at the Dallas Semiconductor website
+ http://www.dalsemi.com/
+
+Authors:
+ Christian W. Zuckschwerdt <zany@triq.net>
+ valuable contributions by Jan M. Sendler <sendler@sendler.de>
+ ported to 2.6 by Aurelien Jarno <aurelien@aurel32.net>
+ with the help of Jean Delvare <khali@linux-fr.org>
+
+Module Parameters
+------------------
+
+* polarity int
+ Output's polarity: 0 = active high, 1 = active low
+
+Description
+-----------
+
+The DS1621 is a (one instance) digital thermometer and thermostat. It has
+both high and low temperature limits which can be user defined (i.e.
+programmed into non-volatile on-chip registers). Temperature range is -55
+degree Celsius to +125 in 0.5 increments. You may convert this into a
+Fahrenheit range of -67 to +257 degrees with 0.9 steps. If polarity
+parameter is not provided, original value is used.
+
+As for the thermostat, behavior can also be programmed using the polarity
+toggle. On the one hand ("heater"), the thermostat output of the chip,
+Tout, will trigger when the low limit temperature is met or underrun and
+stays high until the high limit is met or exceeded. On the other hand
+("cooler"), vice versa. That way "heater" equals "active low", whereas
+"conditioner" equals "active high". Please note that the DS1621 data sheet
+is somewhat misleading in this point since setting the polarity bit does
+not simply invert Tout.
+
+A second thing is that, during extensive testing, Tout showed a tolerance
+of up to +/- 0.5 degrees even when compared against precise temperature
+readings. Be sure to have a high vs. low temperature limit gap of al least
+1.0 degree Celsius to avoid Tout "bouncing", though!
+
+As for alarms, you can read the alarm status of the DS1621 via the 'alarms'
+/sys file interface. The result consists mainly of bit 6 and 5 of the
+configuration register of the chip; bit 6 (0x40 or 64) is the high alarm
+bit and bit 5 (0x20 or 32) the low one. These bits are set when the high or
+low limits are met or exceeded and are reset by the module as soon as the
+respective temperature ranges are left.
+
+The alarm registers are in no way suitable to find out about the actual
+status of Tout. They will only tell you about its history, whether or not
+any of the limits have ever been met or exceeded since last power-up or
+reset. Be aware: When testing, it showed that the status of Tout can change
+with neither of the alarms set.
+
+Temperature conversion of the DS1621 takes up to 1000ms; internal access to
+non-volatile registers may last for 10ms or below.
+
+High Accuracy Temperature Reading
+---------------------------------
+
+As said before, the temperature issued via the 9-bit i2c-bus data is
+somewhat arbitrary. Internally, the temperature conversion is of a
+different kind that is explained (not so...) well in the DS1621 data sheet.
+To cut the long story short: Inside the DS1621 there are two oscillators,
+both of them biassed by a temperature coefficient.
+
+Higher resolution of the temperature reading can be achieved using the
+internal projection, which means taking account of REG_COUNT and REG_SLOPE
+(the driver manages them):
+
+Taken from Dallas Semiconductors App Note 068: 'Increasing Temperature
+Resolution on the DS1620' and App Note 105: 'High Resolution Temperature
+Measurement with Dallas Direct-to-Digital Temperature Sensors'
+
+- Read the 9-bit temperature and strip the LSB (Truncate the .5 degs)
+- The resulting value is TEMP_READ.
+- Then, read REG_COUNT.
+- And then, REG_SLOPE.
+
+ TEMP = TEMP_READ - 0.25 + ((REG_SLOPE - REG_COUNT) / REG_SLOPE)
+
+Note that this is what the DONE bit in the DS1621 configuration register is
+good for: Internally, one temperature conversion takes up to 1000ms. Before
+that conversion is complete you will not be able to read valid things out
+of REG_COUNT and REG_SLOPE. The DONE bit, as you may have guessed by now,
+tells you whether the conversion is complete ("done", in plain English) and
+thus, whether the values you read are good or not.
+
+The DS1621 has two modes of operation: "Continuous" conversion, which can
+be understood as the default stand-alone mode where the chip gets the
+temperature and controls external devices via its Tout pin or tells other
+i2c's about it if they care. The other mode is called "1SHOT", that means
+that it only figures out about the temperature when it is explicitly told
+to do so; this can be seen as power saving mode.
+
+Now if you want to read REG_COUNT and REG_SLOPE, you have to either stop
+the continuous conversions until the contents of these registers are valid,
+or, in 1SHOT mode, you have to have one conversion made.
diff --git a/Documentation/i2c/chips/eeprom b/Documentation/i2c/chips/eeprom
new file mode 100644
index 00000000000..f7e8104b576
--- /dev/null
+++ b/Documentation/i2c/chips/eeprom
@@ -0,0 +1,96 @@
+Kernel driver eeprom
+====================
+
+Supported chips:
+ * Any EEPROM chip in the designated address range
+ Prefix: 'eeprom'
+ Addresses scanned: I2C 0x50 - 0x57
+ Datasheets: Publicly available from:
+ Atmel (www.atmel.com),
+ Catalyst (www.catsemi.com),
+ Fairchild (www.fairchildsemi.com),
+ Microchip (www.microchip.com),
+ Philips (www.semiconductor.philips.com),
+ Rohm (www.rohm.com),
+ ST (www.st.com),
+ Xicor (www.xicor.com),
+ and others.
+
+ Chip Size (bits) Address
+ 24C01 1K 0x50 (shadows at 0x51 - 0x57)
+ 24C01A 1K 0x50 - 0x57 (Typical device on DIMMs)
+ 24C02 2K 0x50 - 0x57
+ 24C04 4K 0x50, 0x52, 0x54, 0x56
+ (additional data at 0x51, 0x53, 0x55, 0x57)
+ 24C08 8K 0x50, 0x54 (additional data at 0x51, 0x52,
+ 0x53, 0x55, 0x56, 0x57)
+ 24C16 16K 0x50 (additional data at 0x51 - 0x57)
+ Sony 2K 0x57
+
+ Atmel 34C02B 2K 0x50 - 0x57, SW write protect at 0x30-37
+ Catalyst 34FC02 2K 0x50 - 0x57, SW write protect at 0x30-37
+ Catalyst 34RC02 2K 0x50 - 0x57, SW write protect at 0x30-37
+ Fairchild 34W02 2K 0x50 - 0x57, SW write protect at 0x30-37
+ Microchip 24AA52 2K 0x50 - 0x57, SW write protect at 0x30-37
+ ST M34C02 2K 0x50 - 0x57, SW write protect at 0x30-37
+
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>,
+ Philip Edelbrock <phil@netroedge.com>,
+ Jean Delvare <khali@linux-fr.org>,
+ Greg Kroah-Hartman <greg@kroah.com>,
+ IBM Corp.
+
+Description
+-----------
+
+This is a simple EEPROM module meant to enable reading the first 256 bytes
+of an EEPROM (on a SDRAM DIMM for example). However, it will access serial
+EEPROMs on any I2C adapter. The supported devices are generically called
+24Cxx, and are listed above; however the numbering for these
+industry-standard devices may vary by manufacturer.
+
+This module was a programming exercise to get used to the new project
+organization laid out by Frodo, but it should be at least completely
+effective for decoding the contents of EEPROMs on DIMMs.
+
+DIMMS will typically contain a 24C01A or 24C02, or the 34C02 variants.
+The other devices will not be found on a DIMM because they respond to more
+than one address.
+
+DDC Monitors may contain any device. Often a 24C01, which responds to all 8
+addresses, is found.
+
+Recent Sony Vaio laptops have an EEPROM at 0x57. We couldn't get the
+specification, so it is guess work and far from being complete.
+
+The Microchip 24AA52/24LCS52, ST M34C02, and others support an additional
+software write protect register at 0x30 - 0x37 (0x20 less than the memory
+location). The chip responds to "write quick" detection at this address but
+does not respond to byte reads. If this register is present, the lower 128
+bytes of the memory array are not write protected. Any byte data write to
+this address will write protect the memory array permanently, and the
+device will no longer respond at the 0x30-37 address. The eeprom driver
+does not support this register.
+
+Lacking functionality:
+
+* Full support for larger devices (24C04, 24C08, 24C16). These are not
+typically found on a PC. These devices will appear as separate devices at
+multiple addresses.
+
+* Support for really large devices (24C32, 24C64, 24C128, 24C256, 24C512).
+These devices require two-byte address fields and are not supported.
+
+* Enable Writing. Again, no technical reason why not, but making it easy
+to change the contents of the EEPROMs (on DIMMs anyway) also makes it easy
+to disable the DIMMs (potentially preventing the computer from booting)
+until the values are restored somehow.
+
+Use:
+
+After inserting the module (and any other required SMBus/i2c modules), you
+should have some EEPROM directories in /sys/bus/i2c/devices/* of names such
+as "0-0050". Inside each of these is a series of files, the eeprom file
+contains the binary data from EEPROM.
diff --git a/Documentation/i2c/chips/fscher b/Documentation/i2c/chips/fscher
new file mode 100644
index 00000000000..64031659aff
--- /dev/null
+++ b/Documentation/i2c/chips/fscher
@@ -0,0 +1,169 @@
+Kernel driver fscher
+====================
+
+Supported chips:
+ * Fujitsu-Siemens Hermes chip
+ Prefix: 'fscher'
+ Addresses scanned: I2C 0x73
+
+Authors:
+ Reinhard Nissl <rnissl@gmx.de> based on work
+ from Hermann Jung <hej@odn.de>,
+ Frodo Looijaard <frodol@dds.nl>,
+ Philip Edelbrock <phil@netroedge.com>
+
+Description
+-----------
+
+This driver implements support for the Fujitsu-Siemens Hermes chip. It is
+described in the 'Register Set Specification BMC Hermes based Systemboard'
+from Fujitsu-Siemens.
+
+The Hermes chip implements a hardware-based system management, e.g. for
+controlling fan speed and core voltage. There is also a watchdog counter on
+the chip which can trigger an alarm and even shut the system down.
+
+The chip provides three temperature values (CPU, motherboard and
+auxiliary), three voltage values (+12V, +5V and battery) and three fans
+(power supply, CPU and auxiliary).
+
+Temperatures are measured in degrees Celsius. The resolution is 1 degree.
+
+Fan rotation speeds are reported in RPM (rotations per minute). The value
+can be divided by a programmable divider (1, 2 or 4) which is stored on
+the chip.
+
+Voltage sensors (also known as "in" sensors) report their values in volts.
+
+All values are reported as final values from the driver. There is no need
+for further calculations.
+
+
+Detailed description
+--------------------
+
+Below you'll find a single line description of all the bit values. With
+this information, you're able to decode e. g. alarms, wdog, etc. To make
+use of the watchdog, you'll need to set the watchdog time and enable the
+watchdog. After that it is necessary to restart the watchdog time within
+the specified period of time, or a system reset will occur.
+
+* revision
+ READING & 0xff = 0x??: HERMES revision identification
+
+* alarms
+ READING & 0x80 = 0x80: CPU throttling active
+ READING & 0x80 = 0x00: CPU running at full speed
+
+ READING & 0x10 = 0x10: software event (see control:1)
+ READING & 0x10 = 0x00: no software event
+
+ READING & 0x08 = 0x08: watchdog event (see wdog:2)
+ READING & 0x08 = 0x00: no watchdog event
+
+ READING & 0x02 = 0x02: thermal event (see temp*:1)
+ READING & 0x02 = 0x00: no thermal event
+
+ READING & 0x01 = 0x01: fan event (see fan*:1)
+ READING & 0x01 = 0x00: no fan event
+
+ READING & 0x13 ! 0x00: ALERT LED is flashing
+
+* control
+ READING & 0x01 = 0x01: software event
+ READING & 0x01 = 0x00: no software event
+
+ WRITING & 0x01 = 0x01: set software event
+ WRITING & 0x01 = 0x00: clear software event
+
+* watchdog_control
+ READING & 0x80 = 0x80: power off on watchdog event while thermal event
+ READING & 0x80 = 0x00: watchdog power off disabled (just system reset enabled)
+
+ READING & 0x40 = 0x40: watchdog timebase 60 seconds (see also wdog:1)
+ READING & 0x40 = 0x00: watchdog timebase 2 seconds
+
+ READING & 0x10 = 0x10: watchdog enabled
+ READING & 0x10 = 0x00: watchdog disabled
+
+ WRITING & 0x80 = 0x80: enable "power off on watchdog event while thermal event"
+ WRITING & 0x80 = 0x00: disable "power off on watchdog event while thermal event"
+
+ WRITING & 0x40 = 0x40: set watchdog timebase to 60 seconds
+ WRITING & 0x40 = 0x00: set watchdog timebase to 2 seconds
+
+ WRITING & 0x20 = 0x20: disable watchdog
+
+ WRITING & 0x10 = 0x10: enable watchdog / restart watchdog time
+
+* watchdog_state
+ READING & 0x02 = 0x02: watchdog system reset occurred
+ READING & 0x02 = 0x00: no watchdog system reset occurred
+
+ WRITING & 0x02 = 0x02: clear watchdog event
+
+* watchdog_preset
+ READING & 0xff = 0x??: configured watch dog time in units (see wdog:3 0x40)
+
+ WRITING & 0xff = 0x??: configure watch dog time in units
+
+* in* (0: +5V, 1: +12V, 2: onboard 3V battery)
+ READING: actual voltage value
+
+* temp*_status (1: CPU sensor, 2: onboard sensor, 3: auxiliary sensor)
+ READING & 0x02 = 0x02: thermal event (overtemperature)
+ READING & 0x02 = 0x00: no thermal event
+
+ READING & 0x01 = 0x01: sensor is working
+ READING & 0x01 = 0x00: sensor is faulty
+
+ WRITING & 0x02 = 0x02: clear thermal event
+
+* temp*_input (1: CPU sensor, 2: onboard sensor, 3: auxiliary sensor)
+ READING: actual temperature value
+
+* fan*_status (1: power supply fan, 2: CPU fan, 3: auxiliary fan)
+ READING & 0x04 = 0x04: fan event (fan fault)
+ READING & 0x04 = 0x00: no fan event
+
+ WRITING & 0x04 = 0x04: clear fan event
+
+* fan*_div (1: power supply fan, 2: CPU fan, 3: auxiliary fan)
+ Divisors 2,4 and 8 are supported, both for reading and writing
+
+* fan*_pwm (1: power supply fan, 2: CPU fan, 3: auxiliary fan)
+ READING & 0xff = 0x00: fan may be switched off
+ READING & 0xff = 0x01: fan must run at least at minimum speed (supply: 6V)
+ READING & 0xff = 0xff: fan must run at maximum speed (supply: 12V)
+ READING & 0xff = 0x??: fan must run at least at given speed (supply: 6V..12V)
+
+ WRITING & 0xff = 0x00: fan may be switched off
+ WRITING & 0xff = 0x01: fan must run at least at minimum speed (supply: 6V)
+ WRITING & 0xff = 0xff: fan must run at maximum speed (supply: 12V)
+ WRITING & 0xff = 0x??: fan must run at least at given speed (supply: 6V..12V)
+
+* fan*_input (1: power supply fan, 2: CPU fan, 3: auxiliary fan)
+ READING: actual RPM value
+
+
+Limitations
+-----------
+
+* Measuring fan speed
+It seems that the chip counts "ripples" (typical fans produce 2 ripples per
+rotation while VERAX fans produce 18) in a 9-bit register. This register is
+read out every second, then the ripple prescaler (2, 4 or 8) is applied and
+the result is stored in the 8 bit output register. Due to the limitation of
+the counting register to 9 bits, it is impossible to measure a VERAX fan
+properly (even with a prescaler of 8). At its maximum speed of 3500 RPM the
+fan produces 1080 ripples per second which causes the counting register to
+overflow twice, leading to only 186 RPM.
+
+* Measuring input voltages
+in2 ("battery") reports the voltage of the onboard lithium battery and not
++3.3V from the power supply.
+
+* Undocumented features
+Fujitsu-Siemens Computers has not documented all features of the chip so
+far. Their software, System Guard, shows that there are a still some
+features which cannot be controlled by this implementation.
diff --git a/Documentation/i2c/chips/gl518sm b/Documentation/i2c/chips/gl518sm
new file mode 100644
index 00000000000..ce0881883bc
--- /dev/null
+++ b/Documentation/i2c/chips/gl518sm
@@ -0,0 +1,74 @@
+Kernel driver gl518sm
+=====================
+
+Supported chips:
+ * Genesys Logic GL518SM release 0x00
+ Prefix: 'gl518sm'
+ Addresses scanned: I2C 0x2c and 0x2d
+ Datasheet: http://www.genesyslogic.com/pdf
+ * Genesys Logic GL518SM release 0x80
+ Prefix: 'gl518sm'
+ Addresses scanned: I2C 0x2c and 0x2d
+ Datasheet: http://www.genesyslogic.com/pdf
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>,
+ Kyösti Mälkki <kmalkki@cc.hut.fi>
+ Hong-Gunn Chew <hglinux@gunnet.org>
+ Jean Delvare <khali@linux-fr.org>
+
+Description
+-----------
+
+IMPORTANT:
+
+For the revision 0x00 chip, the in0, in1, and in2 values (+5V, +3V,
+and +12V) CANNOT be read. This is a limitation of the chip, not the driver.
+
+This driver supports the Genesys Logic GL518SM chip. There are at least
+two revision of this chip, which we call revision 0x00 and 0x80. Revision
+0x80 chips support the reading of all voltages and revision 0x00 only
+for VIN3.
+
+The GL518SM implements one temperature sensor, two fan rotation speed
+sensors, and four voltage sensors. It can report alarms through the
+computer speakers.
+
+Temperatures are measured in degrees Celsius. An alarm goes off while the
+temperature is above the over temperature limit, and has not yet dropped
+below the hysteresis limit. The alarm always reflects the current
+situation. Measurements are guaranteed between -10 degrees and +110
+degrees, with a accuracy of +/-3 degrees.
+
+Rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. In
+case when you have selected to turn fan1 off, no fan1 alarm is triggered.
+
+Fan readings can be divided by a programmable divider (1, 2, 4 or 8) to
+give the readings more range or accuracy. Not all RPM values can
+accurately be represented, so some rounding is done. With a divider
+of 2, the lowest representable value is around 1900 RPM.
+
+Voltage sensors (also known as VIN sensors) report their values in volts.
+An alarm is triggered if the voltage has crossed a programmable minimum or
+maximum limit. Note that minimum in this case always means 'closest to
+zero'; this is important for negative voltage measurements. The VDD input
+measures voltages between 0.000 and 5.865 volt, with a resolution of 0.023
+volt. The other inputs measure voltages between 0.000 and 4.845 volt, with
+a resolution of 0.019 volt. Note that revision 0x00 chips do not support
+reading the current voltage of any input except for VIN3; limit setting and
+alarms work fine, though.
+
+When an alarm is triggered, you can be warned by a beeping signal through your
+computer speaker. It is possible to enable all beeping globally, or only the
+beeping for some alarms.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once (except for temperature alarms). This means that the
+cause for the alarm may already have disappeared! Note that in the current
+implementation, all hardware registers are read whenever any data is read
+(unless it is less than 1.5 seconds since the last update). This means that
+you can easily miss once-only alarms.
+
+The GL518SM only updates its values each 1.5 seconds; reading it more often
+will do no harm, but will return 'old' values.
diff --git a/Documentation/i2c/chips/it87 b/Documentation/i2c/chips/it87
new file mode 100644
index 00000000000..0d0195040d8
--- /dev/null
+++ b/Documentation/i2c/chips/it87
@@ -0,0 +1,96 @@
+Kernel driver it87
+==================
+
+Supported chips:
+ * IT8705F
+ Prefix: 'it87'
+ Addresses scanned: from Super I/O config space, or default ISA 0x290 (8 I/O ports)
+ Datasheet: Publicly available at the ITE website
+ http://www.ite.com.tw/
+ * IT8712F
+ Prefix: 'it8712'
+ Addresses scanned: I2C 0x28 - 0x2f
+ from Super I/O config space, or default ISA 0x290 (8 I/O ports)
+ Datasheet: Publicly available at the ITE website
+ http://www.ite.com.tw/
+ * SiS950 [clone of IT8705F]
+ Prefix: 'sis950'
+ Addresses scanned: from Super I/O config space, or default ISA 0x290 (8 I/O ports)
+ Datasheet: No longer be available
+
+Author: Christophe Gauthron <chrisg@0-in.com>
+
+
+Module Parameters
+-----------------
+
+* update_vbat: int
+
+ 0 if vbat should report power on value, 1 if vbat should be updated after
+ each read. Default is 0. On some boards the battery voltage is provided
+ by either the battery or the onboard power supply. Only the first reading
+ at power on will be the actual battery voltage (which the chip does
+ automatically). On other boards the battery voltage is always fed to
+ the chip so can be read at any time. Excessive reading may decrease
+ battery life but no information is given in the datasheet.
+
+* fix_pwm_polarity int
+
+ Force PWM polarity to active high (DANGEROUS). Some chips are
+ misconfigured by BIOS - PWM values would be inverted. This option tries
+ to fix this. Please contact your BIOS manufacturer and ask him for fix.
+
+Description
+-----------
+
+This driver implements support for the IT8705F, IT8712F and SiS950 chips.
+
+This driver also supports IT8712F, which adds SMBus access, and a VID
+input, used to report the Vcore voltage of the Pentium processor.
+The IT8712F additionally features VID inputs.
+
+These chips are 'Super I/O chips', supporting floppy disks, infrared ports,
+joysticks and other miscellaneous stuff. For hardware monitoring, they
+include an 'environment controller' with 3 temperature sensors, 3 fan
+rotation speed sensors, 8 voltage sensors, and associated alarms.
+
+Temperatures are measured in degrees Celsius. An alarm is triggered once
+when the Overtemperature Shutdown limit is crossed.
+
+Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. Fan
+readings can be divided by a programmable divider (1, 2, 4 or 8) to give the
+readings more range or accuracy. Not all RPM values can accurately be
+represented, so some rounding is done. With a divider of 2, the lowest
+representable value is around 2600 RPM.
+
+Voltage sensors (also known as IN sensors) report their values in volts. An
+alarm is triggered if the voltage has crossed a programmable minimum or
+maximum limit. Note that minimum in this case always means 'closest to
+zero'; this is important for negative voltage measurements. All voltage
+inputs can measure voltages between 0 and 4.08 volts, with a resolution of
+0.016 volt. The battery voltage in8 does not have limit registers.
+
+The VID lines (IT8712F only) encode the core voltage value: the voltage
+level your processor should work with. This is hardcoded by the mainboard
+and/or processor itself. It is a value in volts.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may already
+have disappeared! Note that in the current implementation, all hardware
+registers are read whenever any data is read (unless it is less than 1.5
+seconds since the last update). This means that you can easily miss
+once-only alarms.
+
+The IT87xx only updates its values each 1.5 seconds; reading it more often
+will do no harm, but will return 'old' values.
+
+To change sensor N to a thermistor, 'echo 2 > tempN_type' where N is 1, 2,
+or 3. To change sensor N to a thermal diode, 'echo 3 > tempN_type'.
+Give 0 for unused sensor. Any other value is invalid. To configure this at
+startup, consult lm_sensors's /etc/sensors.conf. (2 = thermistor;
+3 = thermal diode)
+
+The fan speed control features are limited to manual PWM mode. Automatic
+"Smart Guardian" mode control handling is not implemented. However
+if you want to go for "manual mode" just write 1 to pwmN_enable.
diff --git a/Documentation/i2c/chips/lm63 b/Documentation/i2c/chips/lm63
new file mode 100644
index 00000000000..31660bf9797
--- /dev/null
+++ b/Documentation/i2c/chips/lm63
@@ -0,0 +1,57 @@
+Kernel driver lm63
+==================
+
+Supported chips:
+ * National Semiconductor LM63
+ Prefix: 'lm63'
+ Addresses scanned: I2C 0x4c
+ Datasheet: Publicly available at the National Semiconductor website
+ http://www.national.com/pf/LM/LM63.html
+
+Author: Jean Delvare <khali@linux-fr.org>
+
+Thanks go to Tyan and especially Alex Buckingham for setting up a remote
+access to their S4882 test platform for this driver.
+ http://www.tyan.com/
+
+Description
+-----------
+
+The LM63 is a digital temperature sensor with integrated fan monitoring
+and control.
+
+The LM63 is basically an LM86 with fan speed monitoring and control
+capabilities added. It misses some of the LM86 features though:
+ - No low limit for local temperature.
+ - No critical limit for local temperature.
+ - Critical limit for remote temperature can be changed only once. We
+ will consider that the critical limit is read-only.
+
+The datasheet isn't very clear about what the tachometer reading is.
+
+An explanation from National Semiconductor: The two lower bits of the read
+value have to be masked out. The value is still 16 bit in width.
+
+All temperature values are given in degrees Celsius. Resolution is 1.0
+degree for the local temperature, 0.125 degree for the remote temperature.
+
+The fan speed is measured using a tachometer. Contrary to most chips which
+store the value in an 8-bit register and have a selectable clock divider
+to make sure that the result will fit in the register, the LM63 uses 16-bit
+value for measuring the speed of the fan. It can measure fan speeds down to
+83 RPM, at least in theory.
+
+Note that the pin used for fan monitoring is shared with an alert out
+function. Depending on how the board designer wanted to use the chip, fan
+speed monitoring will or will not be possible. The proper chip configuration
+is left to the BIOS, and the driver will blindly trust it.
+
+A PWM output can be used to control the speed of the fan. The LM63 has two
+PWM modes: manual and automatic. Automatic mode is not fully implemented yet
+(you cannot define your custom PWM/temperature curve), and mode change isn't
+supported either.
+
+The lm63 driver will not update its values more frequently than every
+second; reading them more often will do no harm, but will return 'old'
+values.
+
diff --git a/Documentation/i2c/chips/lm75 b/Documentation/i2c/chips/lm75
new file mode 100644
index 00000000000..8e6356fe05d
--- /dev/null
+++ b/Documentation/i2c/chips/lm75
@@ -0,0 +1,65 @@
+Kernel driver lm75
+==================
+
+Supported chips:
+ * National Semiconductor LM75
+ Prefix: 'lm75'
+ Addresses scanned: I2C 0x48 - 0x4f
+ Datasheet: Publicly available at the National Semiconductor website
+ http://www.national.com/
+ * Dallas Semiconductor DS75
+ Prefix: 'lm75'
+ Addresses scanned: I2C 0x48 - 0x4f
+ Datasheet: Publicly available at the Dallas Semiconductor website
+ http://www.maxim-ic.com/
+ * Dallas Semiconductor DS1775
+ Prefix: 'lm75'
+ Addresses scanned: I2C 0x48 - 0x4f
+ Datasheet: Publicly available at the Dallas Semiconductor website
+ http://www.maxim-ic.com/
+ * Maxim MAX6625, MAX6626
+ Prefix: 'lm75'
+ Addresses scanned: I2C 0x48 - 0x4b
+ Datasheet: Publicly available at the Maxim website
+ http://www.maxim-ic.com/
+ * Microchip (TelCom) TCN75
+ Prefix: 'lm75'
+ Addresses scanned: I2C 0x48 - 0x4f
+ Datasheet: Publicly available at the Microchip website
+ http://www.microchip.com/
+
+Author: Frodo Looijaard <frodol@dds.nl>
+
+Description
+-----------
+
+The LM75 implements one temperature sensor. Limits can be set through the
+Overtemperature Shutdown register and Hysteresis register. Each value can be
+set and read to half-degree accuracy.
+An alarm is issued (usually to a connected LM78) when the temperature
+gets higher then the Overtemperature Shutdown value; it stays on until
+the temperature falls below the Hysteresis value.
+All temperatures are in degrees Celsius, and are guaranteed within a
+range of -55 to +125 degrees.
+
+The LM75 only updates its values each 1.5 seconds; reading it more often
+will do no harm, but will return 'old' values.
+
+The LM75 is usually used in combination with LM78-like chips, to measure
+the temperature of the processor(s).
+
+The DS75, DS1775, MAX6625, and MAX6626 are supported as well.
+They are not distinguished from an LM75. While most of these chips
+have three additional bits of accuracy (12 vs. 9 for the LM75),
+the additional bits are not supported. Not only that, but these chips will
+not be detected if not in 9-bit precision mode (use the force parameter if
+needed).
+
+The TCN75 is supported as well, and is not distinguished from an LM75.
+
+The LM75 is essentially an industry standard; there may be other
+LM75 clones not listed here, with or without various enhancements,
+that are supported.
+
+The LM77 is not supported, contrary to what we pretended for a long time.
+Both chips are simply not compatible, value encoding differs.
diff --git a/Documentation/i2c/chips/lm77 b/Documentation/i2c/chips/lm77
new file mode 100644
index 00000000000..57c3a46d637
--- /dev/null
+++ b/Documentation/i2c/chips/lm77
@@ -0,0 +1,22 @@
+Kernel driver lm77
+==================
+
+Supported chips:
+ * National Semiconductor LM77
+ Prefix: 'lm77'
+ Addresses scanned: I2C 0x48 - 0x4b
+ Datasheet: Publicly available at the National Semiconductor website
+ http://www.national.com/
+
+Author: Andras BALI <drewie@freemail.hu>
+
+Description
+-----------
+
+The LM77 implements one temperature sensor. The temperature
+sensor incorporates a band-gap type temperature sensor,
+10-bit ADC, and a digital comparator with user-programmable upper
+and lower limit values.
+
+Limits can be set through the Overtemperature Shutdown register and
+Hysteresis register.
diff --git a/Documentation/i2c/chips/lm78 b/Documentation/i2c/chips/lm78
new file mode 100644
index 00000000000..357086ed7f6
--- /dev/null
+++ b/Documentation/i2c/chips/lm78
@@ -0,0 +1,82 @@
+Kernel driver lm78
+==================
+
+Supported chips:
+ * National Semiconductor LM78
+ Prefix: 'lm78'
+ Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
+ Datasheet: Publicly available at the National Semiconductor website
+ http://www.national.com/
+ * National Semiconductor LM78-J
+ Prefix: 'lm78-j'
+ Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
+ Datasheet: Publicly available at the National Semiconductor website
+ http://www.national.com/
+ * National Semiconductor LM79
+ Prefix: 'lm79'
+ Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
+ Datasheet: Publicly available at the National Semiconductor website
+ http://www.national.com/
+
+Author: Frodo Looijaard <frodol@dds.nl>
+
+Description
+-----------
+
+This driver implements support for the National Semiconductor LM78, LM78-J
+and LM79. They are described as 'Microprocessor System Hardware Monitors'.
+
+There is almost no difference between the three supported chips. Functionally,
+the LM78 and LM78-J are exactly identical. The LM79 has one more VID line,
+which is used to report the lower voltages newer Pentium processors use.
+From here on, LM7* means either of these three types.
+
+The LM7* implements one temperature sensor, three fan rotation speed sensors,
+seven voltage sensors, VID lines, alarms, and some miscellaneous stuff.
+
+Temperatures are measured in degrees Celsius. An alarm is triggered once
+when the Overtemperature Shutdown limit is crossed; it is triggered again
+as soon as it drops below the Hysteresis value. A more useful behavior
+can be found by setting the Hysteresis value to +127 degrees Celsius; in
+this case, alarms are issued during all the time when the actual temperature
+is above the Overtemperature Shutdown value. Measurements are guaranteed
+between -55 and +125 degrees, with a resolution of 1 degree.
+
+Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. Fan
+readings can be divided by a programmable divider (1, 2, 4 or 8) to give
+the readings more range or accuracy. Not all RPM values can accurately be
+represented, so some rounding is done. With a divider of 2, the lowest
+representable value is around 2600 RPM.
+
+Voltage sensors (also known as IN sensors) report their values in volts.
+An alarm is triggered if the voltage has crossed a programmable minimum
+or maximum limit. Note that minimum in this case always means 'closest to
+zero'; this is important for negative voltage measurements. All voltage
+inputs can measure voltages between 0 and 4.08 volts, with a resolution
+of 0.016 volt.
+
+The VID lines encode the core voltage value: the voltage level your processor
+should work with. This is hardcoded by the mainboard and/or processor itself.
+It is a value in volts. When it is unconnected, you will often find the
+value 3.50 V here.
+
+In addition to the alarms described above, there are a couple of additional
+ones. There is a BTI alarm, which gets triggered when an external chip has
+crossed its limits. Usually, this is connected to all LM75 chips; if at
+least one crosses its limits, this bit gets set. The CHAS alarm triggers
+if your computer case is open. The FIFO alarms should never trigger; it
+indicates an internal error. The SMI_IN alarm indicates some other chip
+has triggered an SMI interrupt. As we do not use SMI interrupts at all,
+this condition usually indicates there is a problem with some other
+device.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may
+already have disappeared! Note that in the current implementation, all
+hardware registers are read whenever any data is read (unless it is less
+than 1.5 seconds since the last update). This means that you can easily
+miss once-only alarms.
+
+The LM7* only updates its values each 1.5 seconds; reading it more often
+will do no harm, but will return 'old' values.
diff --git a/Documentation/i2c/chips/lm80 b/Documentation/i2c/chips/lm80
new file mode 100644
index 00000000000..cb5b407ba3e
--- /dev/null
+++ b/Documentation/i2c/chips/lm80
@@ -0,0 +1,56 @@
+Kernel driver lm80
+==================
+
+Supported chips:
+ * National Semiconductor LM80
+ Prefix: 'lm80'
+ Addresses scanned: I2C 0x28 - 0x2f
+ Datasheet: Publicly available at the National Semiconductor website
+ http://www.national.com/
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>,
+ Philip Edelbrock <phil@netroedge.com>
+
+Description
+-----------
+
+This driver implements support for the National Semiconductor LM80.
+It is described as a 'Serial Interface ACPI-Compatible Microprocessor
+System Hardware Monitor'.
+
+The LM80 implements one temperature sensor, two fan rotation speed sensors,
+seven voltage sensors, alarms, and some miscellaneous stuff.
+
+Temperatures are measured in degrees Celsius. There are two sets of limits
+which operate independently. When the HOT Temperature Limit is crossed,
+this will cause an alarm that will be reasserted until the temperature
+drops below the HOT Hysteresis. The Overtemperature Shutdown (OS) limits
+should work in the same way (but this must be checked; the datasheet
+is unclear about this). Measurements are guaranteed between -55 and
++125 degrees. The current temperature measurement has a resolution of
+0.0625 degrees; the limits have a resolution of 1 degree.
+
+Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. Fan
+readings can be divided by a programmable divider (1, 2, 4 or 8) to give
+the readings more range or accuracy. Not all RPM values can accurately be
+represented, so some rounding is done. With a divider of 2, the lowest
+representable value is around 2600 RPM.
+
+Voltage sensors (also known as IN sensors) report their values in volts.
+An alarm is triggered if the voltage has crossed a programmable minimum
+or maximum limit. Note that minimum in this case always means 'closest to
+zero'; this is important for negative voltage measurements. All voltage
+inputs can measure voltages between 0 and 2.55 volts, with a resolution
+of 0.01 volt.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may
+already have disappeared! Note that in the current implementation, all
+hardware registers are read whenever any data is read (unless it is less
+than 2.0 seconds since the last update). This means that you can easily
+miss once-only alarms.
+
+The LM80 only updates its values each 1.5 seconds; reading it more often
+will do no harm, but will return 'old' values.
diff --git a/Documentation/i2c/chips/lm83 b/Documentation/i2c/chips/lm83
new file mode 100644
index 00000000000..061d9ed8ff4
--- /dev/null
+++ b/Documentation/i2c/chips/lm83
@@ -0,0 +1,76 @@
+Kernel driver lm83
+==================
+
+Supported chips:
+ * National Semiconductor LM83
+ Prefix: 'lm83'
+ Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+ Datasheet: Publicly available at the National Semiconductor website
+ http://www.national.com/pf/LM/LM83.html
+
+
+Author: Jean Delvare <khali@linux-fr.org>
+
+Description
+-----------
+
+The LM83 is a digital temperature sensor. It senses its own temperature as
+well as the temperature of up to three external diodes. It is compatible
+with many other devices such as the LM84 and all other ADM1021 clones.
+The main difference between the LM83 and the LM84 in that the later can
+only sense the temperature of one external diode.
+
+Using the adm1021 driver for a LM83 should work, but only two temperatures
+will be reported instead of four.
+
+The LM83 is only found on a handful of motherboards. Both a confirmed
+list and an unconfirmed list follow. If you can confirm or infirm the
+fact that any of these motherboards do actually have an LM83, please
+contact us. Note that the LM90 can easily be misdetected as a LM83.
+
+Confirmed motherboards:
+ SBS P014
+
+Unconfirmed motherboards:
+ Gigabyte GA-8IK1100
+ Iwill MPX2
+ Soltek SL-75DRV5
+
+The driver has been successfully tested by Magnus Forsström, who I'd
+like to thank here. More testers will be of course welcome.
+
+The fact that the LM83 is only scarcely used can be easily explained.
+Most motherboards come with more than just temperature sensors for
+health monitoring. They also have voltage and fan rotation speed
+sensors. This means that temperature-only chips are usually used as
+secondary chips coupled with another chip such as an IT8705F or similar
+chip, which provides more features. Since systems usually need three
+temperature sensors (motherboard, processor, power supply) and primary
+chips provide some temperature sensors, the secondary chip, if needed,
+won't have to handle more than two temperatures. Thus, ADM1021 clones
+are sufficient, and there is no need for a four temperatures sensor
+chip such as the LM83. The only case where using an LM83 would make
+sense is on SMP systems, such as the above-mentioned Iwill MPX2,
+because you want an additional temperature sensor for each additional
+CPU.
+
+On the SBS P014, this is different, since the LM83 is the only hardware
+monitoring chipset. One temperature sensor is used for the motherboard
+(actually measuring the LM83's own temperature), one is used for the
+CPU. The two other sensors must be used to measure the temperature of
+two other points of the motherboard. We suspect these points to be the
+north and south bridges, but this couldn't be confirmed.
+
+All temperature values are given in degrees Celsius. Local temperature
+is given within a range of 0 to +85 degrees. Remote temperatures are
+given within a range of 0 to +125 degrees. Resolution is 1.0 degree,
+accuracy is guaranteed to 3.0 degrees (see the datasheet for more
+details).
+
+Each sensor has its own high limit, but the critical limit is common to
+all four sensors. There is no hysteresis mechanism as found on most
+recent temperature sensors.
+
+The lm83 driver will not update its values more frequently than every
+other second; reading them more often will do no harm, but will return
+'old' values.
diff --git a/Documentation/i2c/chips/lm85 b/Documentation/i2c/chips/lm85
new file mode 100644
index 00000000000..9549237530c
--- /dev/null
+++ b/Documentation/i2c/chips/lm85
@@ -0,0 +1,221 @@
+Kernel driver lm85
+==================
+
+Supported chips:
+ * National Semiconductor LM85 (B and C versions)
+ Prefix: 'lm85'
+ Addresses scanned: I2C 0x2c, 0x2d, 0x2e
+ Datasheet: http://www.national.com/pf/LM/LM85.html
+ * Analog Devices ADM1027
+ Prefix: 'adm1027'
+ Addresses scanned: I2C 0x2c, 0x2d, 0x2e
+ Datasheet: http://www.analog.com/en/prod/0,,766_825_ADM1027,00.html
+ * Analog Devices ADT7463
+ Prefix: 'adt7463'
+ Addresses scanned: I2C 0x2c, 0x2d, 0x2e
+ Datasheet: http://www.analog.com/en/prod/0,,766_825_ADT7463,00.html
+ * SMSC EMC6D100, SMSC EMC6D101
+ Prefix: 'emc6d100'
+ Addresses scanned: I2C 0x2c, 0x2d, 0x2e
+ Datasheet: http://www.smsc.com/main/tools/discontinued/6d100.pdf
+ * SMSC EMC6D102
+ Prefix: 'emc6d102'
+ Addresses scanned: I2C 0x2c, 0x2d, 0x2e
+ Datasheet: http://www.smsc.com/main/catalog/emc6d102.html
+
+Authors:
+ Philip Pokorny <ppokorny@penguincomputing.com>,
+ Frodo Looijaard <frodol@dds.nl>,
+ Richard Barrington <rich_b_nz@clear.net.nz>,
+ Margit Schubert-While <margitsw@t-online.de>,
+ Justin Thiessen <jthiessen@penguincomputing.com>
+
+Description
+-----------
+
+This driver implements support for the National Semiconductor LM85 and
+compatible chips including the Analog Devices ADM1027, ADT7463 and
+SMSC EMC6D10x chips family.
+
+The LM85 uses the 2-wire interface compatible with the SMBUS 2.0
+specification. Using an analog to digital converter it measures three (3)
+temperatures and five (5) voltages. It has four (4) 16-bit counters for
+measuring fan speed. Five (5) digital inputs are provided for sampling the
+VID signals from the processor to the VRM. Lastly, there are three (3) PWM
+outputs that can be used to control fan speed.
+
+The voltage inputs have internal scaling resistors so that the following
+voltage can be measured without external resistors:
+
+ 2.5V, 3.3V, 5V, 12V, and CPU core voltage (2.25V)
+
+The temperatures measured are one internal diode, and two remote diodes.
+Remote 1 is generally the CPU temperature. These inputs are designed to
+measure a thermal diode like the one in a Pentium 4 processor in a socket
+423 or socket 478 package. They can also measure temperature using a
+transistor like the 2N3904.
+
+A sophisticated control system for the PWM outputs is designed into the
+LM85 that allows fan speed to be adjusted automatically based on any of the
+three temperature sensors. Each PWM output is individually adjustable and
+programmable. Once configured, the LM85 will adjust the PWM outputs in
+response to the measured temperatures without further host intervention.
+This feature can also be disabled for manual control of the PWM's.
+
+Each of the measured inputs (voltage, temperature, fan speed) has
+corresponding high/low limit values. The LM85 will signal an ALARM if any
+measured value exceeds either limit.
+
+The LM85 samples all inputs continuously. The lm85 driver will not read
+the registers more often than once a second. Further, configuration data is
+only read once each 5 minutes. There is twice as much config data as
+measurements, so this would seem to be a worthwhile optimization.
+
+Special Features
+----------------
+
+The LM85 has four fan speed monitoring modes. The ADM1027 has only two.
+Both have special circuitry to compensate for PWM interactions with the
+TACH signal from the fans. The ADM1027 can be configured to measure the
+speed of a two wire fan, but the input conditioning circuitry is different
+for 3-wire and 2-wire mode. For this reason, the 2-wire fan modes are not
+exposed to user control. The BIOS should initialize them to the correct
+mode. If you've designed your own ADM1027, you'll have to modify the
+init_client function and add an insmod parameter to set this up.
+
+To smooth the response of fans to changes in temperature, the LM85 has an
+optional filter for smoothing temperatures. The ADM1027 has the same
+config option but uses it to rate limit the changes to fan speed instead.
+
+The ADM1027 and ADT7463 have a 10-bit ADC and can therefore measure
+temperatures with 0.25 degC resolution. They also provide an offset to the
+temperature readings that is automatically applied during measurement.
+This offset can be used to zero out any errors due to traces and placement.
+The documentation says that the offset is in 0.25 degC steps, but in
+initial testing of the ADM1027 it was 1.00 degC steps. Analog Devices has
+confirmed this "bug". The ADT7463 is reported to work as described in the
+documentation. The current lm85 driver does not show the offset register.
+
+The ADT7463 has a THERM asserted counter. This counter has a 22.76ms
+resolution and a range of 5.8 seconds. The driver implements a 32-bit
+accumulator of the counter value to extend the range to over a year. The
+counter will stay at it's max value until read.
+
+See the vendor datasheets for more information. There is application note
+from National (AN-1260) with some additional information about the LM85.
+The Analog Devices datasheet is very detailed and describes a procedure for
+determining an optimal configuration for the automatic PWM control.
+
+The SMSC EMC6D100 & EMC6D101 monitor external voltages, temperatures, and
+fan speeds. They use this monitoring capability to alert the system to out
+of limit conditions and can automatically control the speeds of multiple
+fans in a PC or embedded system. The EMC6D101, available in a 24-pin SSOP
+package, and the EMC6D100, available in a 28-pin SSOP package, are designed
+to be register compatible. The EMC6D100 offers all the features of the
+EMC6D101 plus additional voltage monitoring and system control features.
+Unfortunately it is not possible to distinguish between the package
+versions on register level so these additional voltage inputs may read
+zero. The EMC6D102 features addtional ADC bits thus extending precision
+of voltage and temperature channels.
+
+
+Hardware Configurations
+-----------------------
+
+The LM85 can be jumpered for 3 different SMBus addresses. There are
+no other hardware configuration options for the LM85.
+
+The lm85 driver detects both LM85B and LM85C revisions of the chip. See the
+datasheet for a complete description of the differences. Other than
+identifying the chip, the driver behaves no differently with regard to
+these two chips. The LM85B is recommended for new designs.
+
+The ADM1027 and ADT7463 chips have an optional SMBALERT output that can be
+used to signal the chipset in case a limit is exceeded or the temperature
+sensors fail. Individual sensor interrupts can be masked so they won't
+trigger SMBALERT. The SMBALERT output if configured replaces one of the other
+functions (PWM2 or IN0). This functionality is not implemented in current
+driver.
+
+The ADT7463 also has an optional THERM output/input which can be connected
+to the processor PROC_HOT output. If available, the autofan control
+dynamic Tmin feature can be enabled to keep the system temperature within
+spec (just?!) with the least possible fan noise.
+
+Configuration Notes
+-------------------
+
+Besides standard interfaces driver adds following:
+
+* Temperatures and Zones
+
+Each temperature sensor is associated with a Zone. There are three
+sensors and therefore three zones (# 1, 2 and 3). Each zone has the following
+temperature configuration points:
+
+* temp#_auto_temp_off - temperature below which fans should be off or spinning very low.
+* temp#_auto_temp_min - temperature over which fans start to spin.
+* temp#_auto_temp_max - temperature when fans spin at full speed.
+* temp#_auto_temp_crit - temperature when all fans will run full speed.
+
+* PWM Control
+
+There are three PWM outputs. The LM85 datasheet suggests that the
+pwm3 output control both fan3 and fan4. Each PWM can be individually
+configured and assigned to a zone for it's control value. Each PWM can be
+configured individually according to the following options.
+
+* pwm#_auto_pwm_min - this specifies the PWM value for temp#_auto_temp_off
+ temperature. (PWM value from 0 to 255)
+
+* pwm#_auto_pwm_freq - select base frequency of PWM output. You can select
+ in range of 10.0 to 94.0 Hz in .1 Hz units.
+ (Values 100 to 940).
+
+The pwm#_auto_pwm_freq can be set to one of the following 8 values. Setting the
+frequency to a value not on this list, will result in the next higher frequency
+being selected. The actual device frequency may vary slightly from this
+specification as designed by the manufacturer. Consult the datasheet for more
+details. (PWM Frequency values: 100, 150, 230, 300, 380, 470, 620, 940)
+
+* pwm#_auto_pwm_minctl - this flags selects for temp#_auto_temp_off temperature
+ the bahaviour of fans. Write 1 to let fans spinning at
+ pwm#_auto_pwm_min or write 0 to let them off.
+
+NOTE: It has been reported that there is a bug in the LM85 that causes the flag
+to be associated with the zones not the PWMs. This contradicts all the
+published documentation. Setting pwm#_min_ctl in this case actually affects all
+PWMs controlled by zone '#'.
+
+* PWM Controlling Zone selection
+
+* pwm#_auto_channels - controls zone that is associated with PWM
+
+Configuration choices:
+
+ Value Meaning
+ ------ ------------------------------------------------
+ 1 Controlled by Zone 1
+ 2 Controlled by Zone 2
+ 3 Controlled by Zone 3
+ 23 Controlled by higher temp of Zone 2 or 3
+ 123 Controlled by highest temp of Zone 1, 2 or 3
+ 0 PWM always 0% (off)
+ -1 PWM always 100% (full on)
+ -2 Manual control (write to 'pwm#' to set)
+
+The National LM85's have two vendor specific configuration
+features. Tach. mode and Spinup Control. For more details on these,
+see the LM85 datasheet or Application Note AN-1260.
+
+The Analog Devices ADM1027 has several vendor specific enhancements.
+The number of pulses-per-rev of the fans can be set, Tach monitoring
+can be optimized for PWM operation, and an offset can be applied to
+the temperatures to compensate for systemic errors in the
+measurements.
+
+In addition to the ADM1027 features, the ADT7463 also has Tmin control
+and THERM asserted counts. Automatic Tmin control acts to adjust the
+Tmin value to maintain the measured temperature sensor at a specified
+temperature. There isn't much documentation on this feature in the
+ADT7463 data sheet. This is not supported by current driver.
diff --git a/Documentation/i2c/chips/lm87 b/Documentation/i2c/chips/lm87
new file mode 100644
index 00000000000..c952c57f0e1
--- /dev/null
+++ b/Documentation/i2c/chips/lm87
@@ -0,0 +1,73 @@
+Kernel driver lm87
+==================
+
+Supported chips:
+ * National Semiconductor LM87
+ Prefix: 'lm87'
+ Addresses scanned: I2C 0x2c - 0x2f
+ Datasheet: http://www.national.com/pf/LM/LM87.html
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>,
+ Philip Edelbrock <phil@netroedge.com>,
+ Mark Studebaker <mdsxyz123@yahoo.com>,
+ Stephen Rousset <stephen.rousset@rocketlogix.com>,
+ Dan Eaton <dan.eaton@rocketlogix.com>,
+ Jean Delvare <khali@linux-fr.org>,
+ Original 2.6 port Jeff Oliver
+
+Description
+-----------
+
+This driver implements support for the National Semiconductor LM87.
+
+The LM87 implements up to three temperature sensors, up to two fan
+rotation speed sensors, up to seven voltage sensors, alarms, and some
+miscellaneous stuff.
+
+Temperatures are measured in degrees Celsius. Each input has a high
+and low alarm settings. A high limit produces an alarm when the value
+goes above it, and an alarm is also produced when the value goes below
+the low limit.
+
+Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. Fan
+readings can be divided by a programmable divider (1, 2, 4 or 8) to give
+the readings more range or accuracy. Not all RPM values can accurately be
+represented, so some rounding is done. With a divider of 2, the lowest
+representable value is around 2600 RPM.
+
+Voltage sensors (also known as IN sensors) report their values in
+volts. An alarm is triggered if the voltage has crossed a programmable
+minimum or maximum limit. Note that minimum in this case always means
+'closest to zero'; this is important for negative voltage measurements.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may
+already have disappeared! Note that in the current implementation, all
+hardware registers are read whenever any data is read (unless it is less
+than 1.0 seconds since the last update). This means that you can easily
+miss once-only alarms.
+
+The lm87 driver only updates its values each 1.0 seconds; reading it more
+often will do no harm, but will return 'old' values.
+
+
+Hardware Configurations
+-----------------------
+
+The LM87 has four pins which can serve one of two possible functions,
+depending on the hardware configuration.
+
+Some functions share pins, so not all functions are available at the same
+time. Which are depends on the hardware setup. This driver assumes that
+the BIOS configured the chip correctly. In that respect, it differs from
+the original driver (from lm_sensors for Linux 2.4), which would force the
+LM87 to an arbitrary, compile-time chosen mode, regardless of the actual
+chipset wiring.
+
+For reference, here is the list of exclusive functions:
+ - in0+in5 (default) or temp3
+ - fan1 (default) or in6
+ - fan2 (default) or in7
+ - VID lines (default) or IRQ lines (not handled by this driver)
diff --git a/Documentation/i2c/chips/lm90 b/Documentation/i2c/chips/lm90
new file mode 100644
index 00000000000..2c4cf39471f
--- /dev/null
+++ b/Documentation/i2c/chips/lm90
@@ -0,0 +1,121 @@
+Kernel driver lm90
+==================
+
+Supported chips:
+ * National Semiconductor LM90
+ Prefix: 'lm90'
+ Addresses scanned: I2C 0x4c
+ Datasheet: Publicly available at the National Semiconductor website
+ http://www.national.com/pf/LM/LM90.html
+ * National Semiconductor LM89
+ Prefix: 'lm99'
+ Addresses scanned: I2C 0x4c and 0x4d
+ Datasheet: Publicly available at the National Semiconductor website
+ http://www.national.com/pf/LM/LM89.html
+ * National Semiconductor LM99
+ Prefix: 'lm99'
+ Addresses scanned: I2C 0x4c and 0x4d
+ Datasheet: Publicly available at the National Semiconductor website
+ http://www.national.com/pf/LM/LM99.html
+ * National Semiconductor LM86
+ Prefix: 'lm86'
+ Addresses scanned: I2C 0x4c
+ Datasheet: Publicly available at the National Semiconductor website
+ http://www.national.com/pf/LM/LM86.html
+ * Analog Devices ADM1032
+ Prefix: 'adm1032'
+ Addresses scanned: I2C 0x4c
+ Datasheet: Publicly available at the Analog Devices website
+ http://products.analog.com/products/info.asp?product=ADM1032
+ * Analog Devices ADT7461
+ Prefix: 'adt7461'
+ Addresses scanned: I2C 0x4c
+ Datasheet: Publicly available at the Analog Devices website
+ http://products.analog.com/products/info.asp?product=ADT7461
+ Note: Only if in ADM1032 compatibility mode
+ * Maxim MAX6657
+ Prefix: 'max6657'
+ Addresses scanned: I2C 0x4c
+ Datasheet: Publicly available at the Maxim website
+ http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2578
+ * Maxim MAX6658
+ Prefix: 'max6657'
+ Addresses scanned: I2C 0x4c
+ Datasheet: Publicly available at the Maxim website
+ http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2578
+ * Maxim MAX6659
+ Prefix: 'max6657'
+ Addresses scanned: I2C 0x4c, 0x4d (unsupported 0x4e)
+ Datasheet: Publicly available at the Maxim website
+ http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2578
+
+
+Author: Jean Delvare <khali@linux-fr.org>
+
+
+Description
+-----------
+
+The LM90 is a digital temperature sensor. It senses its own temperature as
+well as the temperature of up to one external diode. It is compatible
+with many other devices such as the LM86, the LM89, the LM99, the ADM1032,
+the MAX6657, MAX6658 and the MAX6659 all of which are supported by this driver.
+Note that there is no easy way to differentiate between the last three
+variants. The extra address and features of the MAX6659 are not supported by
+this driver. Additionally, the ADT7461 is supported if found in ADM1032
+compatibility mode.
+
+The specificity of this family of chipsets over the ADM1021/LM84
+family is that it features critical limits with hysteresis, and an
+increased resolution of the remote temperature measurement.
+
+The different chipsets of the family are not strictly identical, although
+very similar. This driver doesn't handle any specific feature for now,
+but could if there ever was a need for it. For reference, here comes a
+non-exhaustive list of specific features:
+
+LM90:
+ * Filter and alert configuration register at 0xBF.
+ * ALERT is triggered by temperatures over critical limits.
+
+LM86 and LM89:
+ * Same as LM90
+ * Better external channel accuracy
+
+LM99:
+ * Same as LM89
+ * External temperature shifted by 16 degrees down
+
+ADM1032:
+ * Consecutive alert register at 0x22.
+ * Conversion averaging.
+ * Up to 64 conversions/s.
+ * ALERT is triggered by open remote sensor.
+
+ADT7461
+ * Extended temperature range (breaks compatibility)
+ * Lower resolution for remote temperature
+
+MAX6657 and MAX6658:
+ * Remote sensor type selection
+
+MAX6659
+ * Selectable address
+ * Second critical temperature limit
+ * Remote sensor type selection
+
+All temperature values are given in degrees Celsius. Resolution
+is 1.0 degree for the local temperature, 0.125 degree for the remote
+temperature.
+
+Each sensor has its own high and low limits, plus a critical limit.
+Additionally, there is a relative hysteresis value common to both critical
+values. To make life easier to user-space applications, two absolute values
+are exported, one for each channel, but these values are of course linked.
+Only the local hysteresis can be set from user-space, and the same delta
+applies to the remote hysteresis.
+
+The lm90 driver will not update its values more frequently than every
+other second; reading them more often will do no harm, but will return
+'old' values.
+
diff --git a/Documentation/i2c/chips/lm92 b/Documentation/i2c/chips/lm92
new file mode 100644
index 00000000000..7705bfaa070
--- /dev/null
+++ b/Documentation/i2c/chips/lm92
@@ -0,0 +1,37 @@
+Kernel driver lm92
+==================
+
+Supported chips:
+ * National Semiconductor LM92
+ Prefix: 'lm92'
+ Addresses scanned: I2C 0x48 - 0x4b
+ Datasheet: http://www.national.com/pf/LM/LM92.html
+ * National Semiconductor LM76
+ Prefix: 'lm92'
+ Addresses scanned: none, force parameter needed
+ Datasheet: http://www.national.com/pf/LM/LM76.html
+ * Maxim MAX6633/MAX6634/MAX6635
+ Prefix: 'lm92'
+ Addresses scanned: I2C 0x48 - 0x4b
+ MAX6633 with address in 0x40 - 0x47, 0x4c - 0x4f needs force parameter
+ and MAX6634 with address in 0x4c - 0x4f needs force parameter
+ Datasheet: http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3074
+
+Authors:
+ Abraham van der Merwe <abraham@2d3d.co.za>
+ Jean Delvare <khali@linux-fr.org>
+
+
+Description
+-----------
+
+This driver implements support for the National Semiconductor LM92
+temperature sensor.
+
+Each LM92 temperature sensor supports a single temperature sensor. There are
+alarms for high, low, and critical thresholds. There's also an hysteresis to
+control the thresholds for resetting alarms.
+
+Support was added later for the LM76 and Maxim MAX6633/MAX6634/MAX6635,
+which are mostly compatible. They have not all been tested, so you
+may need to use the force parameter.
diff --git a/Documentation/i2c/chips/max1619 b/Documentation/i2c/chips/max1619
new file mode 100644
index 00000000000..d6f8d9cd7d7
--- /dev/null
+++ b/Documentation/i2c/chips/max1619
@@ -0,0 +1,29 @@
+Kernel driver max1619
+=====================
+
+Supported chips:
+ * Maxim MAX1619
+ Prefix: 'max1619'
+ Addresses scanned: I2C 0x18-0x1a, 0x29-0x2b, 0x4c-0x4e
+ Datasheet: Publicly available at the Maxim website
+ http://pdfserv.maxim-ic.com/en/ds/MAX1619.pdf
+
+Authors:
+ Alexey Fisher <fishor@mail.ru>,
+ Jean Delvare <khali@linux-fr.org>
+
+Description
+-----------
+
+The MAX1619 is a digital temperature sensor. It senses its own temperature as
+well as the temperature of up to one external diode.
+
+All temperature values are given in degrees Celsius. Resolution
+is 1.0 degree for the local temperature and for the remote temperature.
+
+Only the external sensor has high and low limits.
+
+The max1619 driver will not update its values more frequently than every
+other second; reading them more often will do no harm, but will return
+'old' values.
+
diff --git a/Documentation/i2c/chips/max6875 b/Documentation/i2c/chips/max6875
new file mode 100644
index 00000000000..b4fb49b4181
--- /dev/null
+++ b/Documentation/i2c/chips/max6875
@@ -0,0 +1,54 @@
+Kernel driver max6875
+=====================
+
+Supported chips:
+ * Maxim max6874, max6875
+ Prefixes: 'max6875'
+ Addresses scanned: 0x50, 0x52
+ Datasheets:
+ http://pdfserv.maxim-ic.com/en/ds/MAX6874-MAX6875.pdf
+
+Author: Ben Gardner <bgardner@wabtec.com>
+
+
+Module Parameters
+-----------------
+
+* allow_write int
+ Set to non-zero to enable write permission:
+ *0: Read only
+ 1: Read and write
+
+
+Description
+-----------
+
+The MAXIM max6875 is a EEPROM-programmable power-supply sequencer/supervisor.
+It provides timed outputs that can be used as a watchdog, if properly wired.
+It also provides 512 bytes of user EEPROM.
+
+At reset, the max6875 reads the configuration eeprom into its configuration
+registers. The chip then begins to operate according to the values in the
+registers.
+
+See the datasheet for details on how to program the EEPROM.
+
+
+Sysfs entries
+-------------
+
+eeprom_user - 512 bytes of user-defined EEPROM space. Only writable if
+ allow_write was set and register 0x43 is 0.
+
+eeprom_config - 70 bytes of config EEPROM. Note that changes will not get
+ loaded into register space until a power cycle or device reset.
+
+reg_config - 70 bytes of register space. Any changes take affect immediately.
+
+
+General Remarks
+---------------
+
+A typical application will require that the EEPROMs be programmed once and
+never altered afterwards.
+
diff --git a/Documentation/i2c/chips/pc87360 b/Documentation/i2c/chips/pc87360
new file mode 100644
index 00000000000..89a8fcfa78d
--- /dev/null
+++ b/Documentation/i2c/chips/pc87360
@@ -0,0 +1,189 @@
+Kernel driver pc87360
+=====================
+
+Supported chips:
+ * National Semiconductor PC87360, PC87363, PC87364, PC87365 and PC87366
+ Prefixes: 'pc87360', 'pc87363', 'pc87364', 'pc87365', 'pc87366'
+ Addresses scanned: none, address read from Super I/O config space
+ Datasheets:
+ http://www.national.com/pf/PC/PC87360.html
+ http://www.national.com/pf/PC/PC87363.html
+ http://www.national.com/pf/PC/PC87364.html
+ http://www.national.com/pf/PC/PC87365.html
+ http://www.national.com/pf/PC/PC87366.html
+
+Authors: Jean Delvare <khali@linux-fr.org>
+
+Thanks to Sandeep Mehta, Tonko de Rooy and Daniel Ceregatti for testing.
+Thanks to Rudolf Marek for helping me investigate conversion issues.
+
+
+Module Parameters
+-----------------
+
+* init int
+ Chip initialization level:
+ 0: None
+ *1: Forcibly enable internal voltage and temperature channels, except in9
+ 2: Forcibly enable all voltage and temperature channels, except in9
+ 3: Forcibly enable all voltage and temperature channels, including in9
+
+Note that this parameter has no effect for the PC87360, PC87363 and PC87364
+chips.
+
+Also note that for the PC87366, initialization levels 2 and 3 don't enable
+all temperature channels, because some of them share pins with each other,
+so they can't be used at the same time.
+
+
+Description
+-----------
+
+The National Semiconductor PC87360 Super I/O chip contains monitoring and
+PWM control circuitry for two fans. The PC87363 chip is similar, and the
+PC87364 chip has monitoring and PWM control for a third fan.
+
+The National Semiconductor PC87365 and PC87366 Super I/O chips are complete
+hardware monitoring chipsets, not only controlling and monitoring three fans,
+but also monitoring eleven voltage inputs and two (PC87365) or up to four
+(PC87366) temperatures.
+
+ Chip #vin #fan #pwm #temp devid
+
+ PC87360 - 2 2 - 0xE1
+ PC87363 - 2 2 - 0xE8
+ PC87364 - 3 3 - 0xE4
+ PC87365 11 3 3 2 0xE5
+ PC87366 11 3 3 3-4 0xE9
+
+The driver assumes that no more than one chip is present, and one of the
+standard Super I/O addresses is used (0x2E/0x2F or 0x4E/0x4F)
+
+Fan Monitoring
+--------------
+
+Fan rotation speeds are reported in RPM (revolutions per minute). An alarm
+is triggered if the rotation speed has dropped below a programmable limit.
+A different alarm is triggered if the fan speed is too low to be measured.
+
+Fan readings are affected by a programmable clock divider, giving the
+readings more range or accuracy. Usually, users have to learn how it works,
+but this driver implements dynamic clock divider selection, so you don't
+have to care no more.
+
+For reference, here are a few values about clock dividers:
+
+ slowest accuracy highest
+ measurable around 3000 accurate
+ divider speed (RPM) RPM (RPM) speed (RPM)
+ 1 1882 18 6928
+ 2 941 37 4898
+ 4 470 74 3464
+ 8 235 150 2449
+
+For the curious, here is how the values above were computed:
+ * slowest measurable speed: clock/(255*divider)
+ * accuracy around 3000 RPM: 3000^2/clock
+ * highest accurate speed: sqrt(clock*100)
+The clock speed for the PC87360 family is 480 kHz. I arbitrarily chose 100
+RPM as the lowest acceptable accuracy.
+
+As mentioned above, you don't have to care about this no more.
+
+Note that not all RPM values can be represented, even when the best clock
+divider is selected. This is not only true for the measured speeds, but
+also for the programmable low limits, so don't be surprised if you try to
+set, say, fan1_min to 2900 and it finally reads 2909.
+
+
+Fan Control
+-----------
+
+PWM (pulse width modulation) values range from 0 to 255, with 0 meaning
+that the fan is stopped, and 255 meaning that the fan goes at full speed.
+
+Be extremely careful when changing PWM values. Low PWM values, even
+non-zero, can stop the fan, which may cause irreversible damage to your
+hardware if temperature increases too much. When changing PWM values, go
+step by step and keep an eye on temperatures.
+
+One user reported problems with PWM. Changing PWM values would break fan
+speed readings. No explanation nor fix could be found.
+
+
+Temperature Monitoring
+----------------------
+
+Temperatures are reported in degrees Celsius. Each temperature measured has
+associated low, high and overtemperature limits, each of which triggers an
+alarm when crossed.
+
+The first two temperature channels are external. The third one (PC87366
+only) is internal.
+
+The PC87366 has three additional temperature channels, based on
+thermistors (as opposed to thermal diodes for the first three temperature
+channels). For technical reasons, these channels are held by the VLM
+(voltage level monitor) logical device, not the TMS (temperature
+measurement) one. As a consequence, these temperatures are exported as
+voltages, and converted into temperatures in user-space.
+
+Note that these three additional channels share their pins with the
+external thermal diode channels, so you (physically) can't use them all at
+the same time. Although it should be possible to mix the two sensor types,
+the documents from National Semiconductor suggest that motherboard
+manufacturers should choose one type and stick to it. So you will more
+likely have either channels 1 to 3 (thermal diodes) or 3 to 6 (internal
+thermal diode, and thermistors).
+
+
+Voltage Monitoring
+------------------
+
+Voltages are reported relatively to a reference voltage, either internal or
+external. Some of them (in7:Vsb, in8:Vdd and in10:AVdd) are divided by two
+internally, you will have to compensate in sensors.conf. Others (in0 to in6)
+are likely to be divided externally. The meaning of each of these inputs as
+well as the values of the resistors used for division is left to the
+motherboard manufacturers, so you will have to document yourself and edit
+sensors.conf accordingly. National Semiconductor has a document with
+recommended resistor values for some voltages, but this still leaves much
+room for per motherboard specificities, unfortunately. Even worse,
+motherboard manufacturers don't seem to care about National Semiconductor's
+recommendations.
+
+Each voltage measured has associated low and high limits, each of which
+triggers an alarm when crossed.
+
+When available, VID inputs are used to provide the nominal CPU Core voltage.
+The driver will default to VRM 9.0, but this can be changed from user-space.
+The chipsets can handle two sets of VID inputs (on dual-CPU systems), but
+the driver will only export one for now. This may change later if there is
+a need.
+
+
+General Remarks
+---------------
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may already
+have disappeared! Note that all hardware registers are read whenever any
+data is read (unless it is less than 2 seconds since the last update, in
+which case cached values are returned instead). As a consequence, when
+a once-only alarm triggers, it may take 2 seconds for it to show, and 2
+more seconds for it to disappear.
+
+Monitoring of in9 isn't enabled at lower init levels (<3) because that
+channel measures the battery voltage (Vbat). It is a known fact that
+repeatedly sampling the battery voltage reduces its lifetime. National
+Semiconductor smartly designed their chipset so that in9 is sampled only
+once every 1024 sampling cycles (that is every 34 minutes at the default
+sampling rate), so the effect is attenuated, but still present.
+
+
+Limitations
+-----------
+
+The datasheets suggests that some values (fan mins, fan dividers)
+shouldn't be changed once the monitoring has started, but we ignore that
+recommendation. We'll reconsider if it actually causes trouble.
diff --git a/Documentation/i2c/chips/pca9539 b/Documentation/i2c/chips/pca9539
new file mode 100644
index 00000000000..c4fce6a1353
--- /dev/null
+++ b/Documentation/i2c/chips/pca9539
@@ -0,0 +1,47 @@
+Kernel driver pca9539
+=====================
+
+Supported chips:
+ * Philips PCA9539
+ Prefix: 'pca9539'
+ Addresses scanned: 0x74 - 0x77
+ Datasheet:
+ http://www.semiconductors.philips.com/acrobat/datasheets/PCA9539_2.pdf
+
+Author: Ben Gardner <bgardner@wabtec.com>
+
+
+Description
+-----------
+
+The Philips PCA9539 is a 16 bit low power I/O device.
+All 16 lines can be individually configured as an input or output.
+The input sense can also be inverted.
+The 16 lines are split between two bytes.
+
+
+Sysfs entries
+-------------
+
+Each is a byte that maps to the 8 I/O bits.
+A '0' suffix is for bits 0-7, while '1' is for bits 8-15.
+
+input[01] - read the current value
+output[01] - sets the output value
+direction[01] - direction of each bit: 1=input, 0=output
+invert[01] - toggle the input bit sense
+
+input reads the actual state of the line and is always available.
+The direction defaults to input for all channels.
+
+
+General Remarks
+---------------
+
+Note that each output, direction, and invert entry controls 8 lines.
+You should use the read, modify, write sequence.
+For example. to set output bit 0 of 1.
+ val=$(cat output0)
+ val=$(( $val | 1 ))
+ echo $val > output0
+
diff --git a/Documentation/i2c/chips/pcf8574 b/Documentation/i2c/chips/pcf8574
new file mode 100644
index 00000000000..2752c8ce316
--- /dev/null
+++ b/Documentation/i2c/chips/pcf8574
@@ -0,0 +1,69 @@
+Kernel driver pcf8574
+=====================
+
+Supported chips:
+ * Philips PCF8574
+ Prefix: 'pcf8574'
+ Addresses scanned: I2C 0x20 - 0x27
+ Datasheet: Publicly available at the Philips Semiconductors website
+ http://www.semiconductors.philips.com/pip/PCF8574P.html
+
+ * Philips PCF8574A
+ Prefix: 'pcf8574a'
+ Addresses scanned: I2C 0x38 - 0x3f
+ Datasheet: Publicly available at the Philips Semiconductors website
+ http://www.semiconductors.philips.com/pip/PCF8574P.html
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>,
+ Philip Edelbrock <phil@netroedge.com>,
+ Dan Eaton <dan.eaton@rocketlogix.com>,
+ Aurelien Jarno <aurelien@aurel32.net>,
+ Jean Delvare <khali@linux-fr.org>,
+
+
+Description
+-----------
+The PCF8574(A) is an 8-bit I/O expander for the I2C bus produced by Philips
+Semiconductors. It is designed to provide a byte I2C interface to up to 16
+separate devices (8 x PCF8574 and 8 x PCF8574A).
+
+This device consists of a quasi-bidirectional port. Each of the eight I/Os
+can be independently used as an input or output. To setup an I/O as an
+input, you have to write a 1 to the corresponding output.
+
+For more informations see the datasheet.
+
+
+Accessing PCF8574(A) via /sys interface
+-------------------------------------
+
+! Be careful !
+The PCF8574(A) is plainly impossible to detect ! Stupid chip.
+So every chip with address in the interval [20..27] and [38..3f] are
+detected as PCF8574(A). If you have other chips in this address
+range, the workaround is to load this module after the one
+for your others chips.
+
+On detection (i.e. insmod, modprobe et al.), directories are being
+created for each detected PCF8574(A):
+
+/sys/bus/i2c/devices/<0>-<1>/
+where <0> is the bus the chip was detected on (e. g. i2c-0)
+and <1> the chip address ([20..27] or [38..3f]):
+
+(example: /sys/bus/i2c/devices/1-0020/)
+
+Inside these directories, there are two files each:
+read and write (and one file with chip name).
+
+The read file is read-only. Reading gives you the current I/O input
+if the corresponding output is set as 1, otherwise the current output
+value, that is to say 0.
+
+The write file is read/write. Writing a value outputs it on the I/O
+port. Reading returns the last written value.
+
+On module initialization the chip is configured as eight inputs (all
+outputs to 1), so you can connect any circuit to the PCF8574(A) without
+being afraid of short-circuit.
diff --git a/Documentation/i2c/chips/pcf8591 b/Documentation/i2c/chips/pcf8591
new file mode 100644
index 00000000000..5628fcf4207
--- /dev/null
+++ b/Documentation/i2c/chips/pcf8591
@@ -0,0 +1,90 @@
+Kernel driver pcf8591
+=====================
+
+Supported chips:
+ * Philips PCF8591
+ Prefix: 'pcf8591'
+ Addresses scanned: I2C 0x48 - 0x4f
+ Datasheet: Publicly available at the Philips Semiconductor website
+ http://www.semiconductors.philips.com/pip/PCF8591P.html
+
+Authors:
+ Aurelien Jarno <aurelien@aurel32.net>
+ valuable contributions by Jan M. Sendler <sendler@sendler.de>,
+ Jean Delvare <khali@linux-fr.org>
+
+
+Description
+-----------
+The PCF8591 is an 8-bit A/D and D/A converter (4 analog inputs and one
+analog output) for the I2C bus produced by Philips Semiconductors. It
+is designed to provide a byte I2C interface to up to 4 separate devices.
+
+The PCF8591 has 4 analog inputs programmable as single-ended or
+differential inputs :
+- mode 0 : four single ended inputs
+ Pins AIN0 to AIN3 are single ended inputs for channels 0 to 3
+
+- mode 1 : three differential inputs
+ Pins AIN3 is the common negative differential input
+ Pins AIN0 to AIN2 are positive differential inputs for channels 0 to 2
+
+- mode 2 : single ended and differential mixed
+ Pins AIN0 and AIN1 are single ended inputs for channels 0 and 1
+ Pins AIN2 is the positive differential input for channel 3
+ Pins AIN3 is the negative differential input for channel 3
+
+- mode 3 : two differential inputs
+ Pins AIN0 is the positive differential input for channel 0
+ Pins AIN1 is the negative differential input for channel 0
+ Pins AIN2 is the positive differential input for channel 1
+ Pins AIN3 is the negative differential input for channel 1
+
+See the datasheet for details.
+
+Module parameters
+-----------------
+
+* input_mode int
+
+ Analog input mode:
+ 0 = four single ended inputs
+ 1 = three differential inputs
+ 2 = single ended and differential mixed
+ 3 = two differential inputs
+
+
+Accessing PCF8591 via /sys interface
+-------------------------------------
+
+! Be careful !
+The PCF8591 is plainly impossible to detect ! Stupid chip.
+So every chip with address in the interval [48..4f] is
+detected as PCF8591. If you have other chips in this address
+range, the workaround is to load this module after the one
+for your others chips.
+
+On detection (i.e. insmod, modprobe et al.), directories are being
+created for each detected PCF8591:
+
+/sys/bus/devices/<0>-<1>/
+where <0> is the bus the chip was detected on (e. g. i2c-0)
+and <1> the chip address ([48..4f])
+
+Inside these directories, there are such files:
+in0, in1, in2, in3, out0_enable, out0_output, name
+
+Name contains chip name.
+
+The in0, in1, in2 and in3 files are RO. Reading gives the value of the
+corresponding channel. Depending on the current analog inputs configuration,
+files in2 and/or in3 do not exist. Values range are from 0 to 255 for single
+ended inputs and -128 to +127 for differential inputs (8-bit ADC).
+
+The out0_enable file is RW. Reading gives "1" for analog output enabled and
+"0" for analog output disabled. Writing accepts "0" and "1" accordingly.
+
+The out0_output file is RW. Writing a number between 0 and 255 (8-bit DAC), send
+the value to the digital-to-analog converter. Note that a voltage will
+only appears on AOUT pin if aout0_enable equals 1. Reading returns the last
+value written.
diff --git a/Documentation/i2c/chips/sis5595 b/Documentation/i2c/chips/sis5595
new file mode 100644
index 00000000000..b7ae36b8cdf
--- /dev/null
+++ b/Documentation/i2c/chips/sis5595
@@ -0,0 +1,106 @@
+Kernel driver sis5595
+=====================
+
+Supported chips:
+ * Silicon Integrated Systems Corp. SiS5595 Southbridge Hardware Monitor
+ Prefix: 'sis5595'
+ Addresses scanned: ISA in PCI-space encoded address
+ Datasheet: Publicly available at the Silicon Integrated Systems Corp. site.
+
+Authors:
+ Kyösti Mälkki <kmalkki@cc.hut.fi>,
+ Mark D. Studebaker <mdsxyz123@yahoo.com>,
+ Aurelien Jarno <aurelien@aurel32.net> 2.6 port
+
+ SiS southbridge has a LM78-like chip integrated on the same IC.
+ This driver is a customized copy of lm78.c
+
+ Supports following revisions:
+ Version PCI ID PCI Revision
+ 1 1039/0008 AF or less
+ 2 1039/0008 B0 or greater
+
+ Note: these chips contain a 0008 device which is incompatible with the
+ 5595. We recognize these by the presence of the listed
+ "blacklist" PCI ID and refuse to load.
+
+ NOT SUPPORTED PCI ID BLACKLIST PCI ID
+ 540 0008 0540
+ 550 0008 0550
+ 5513 0008 5511
+ 5581 0008 5597
+ 5582 0008 5597
+ 5597 0008 5597
+ 630 0008 0630
+ 645 0008 0645
+ 730 0008 0730
+ 735 0008 0735
+
+
+Module Parameters
+-----------------
+force_addr=0xaddr Set the I/O base address. Useful for boards
+ that don't set the address in the BIOS. Does not do a
+ PCI force; the device must still be present in lspci.
+ Don't use this unless the driver complains that the
+ base address is not set.
+ Example: 'modprobe sis5595 force_addr=0x290'
+
+
+Description
+-----------
+
+The SiS5595 southbridge has integrated hardware monitor functions. It also
+has an I2C bus, but this driver only supports the hardware monitor. For the
+I2C bus driver see i2c-sis5595.
+
+The SiS5595 implements zero or one temperature sensor, two fan speed
+sensors, four or five voltage sensors, and alarms.
+
+On the first version of the chip, there are four voltage sensors and one
+temperature sensor.
+
+On the second version of the chip, the temperature sensor (temp) and the
+fifth voltage sensor (in4) share a pin which is configurable, but not
+through the driver. Sorry. The driver senses the configuration of the pin,
+which was hopefully set by the BIOS.
+
+Temperatures are measured in degrees Celsius. An alarm is triggered once
+when the max is crossed; it is also triggered when it drops below the min
+value. Measurements are guaranteed between -55 and +125 degrees, with a
+resolution of 1 degree.
+
+Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. Fan
+readings can be divided by a programmable divider (1, 2, 4 or 8) to give
+the readings more range or accuracy. Not all RPM values can accurately be
+represented, so some rounding is done. With a divider of 2, the lowest
+representable value is around 2600 RPM.
+
+Voltage sensors (also known as IN sensors) report their values in volts. An
+alarm is triggered if the voltage has crossed a programmable minimum or
+maximum limit. Note that minimum in this case always means 'closest to
+zero'; this is important for negative voltage measurements. All voltage
+inputs can measure voltages between 0 and 4.08 volts, with a resolution of
+0.016 volt.
+
+In addition to the alarms described above, there is a BTI alarm, which gets
+triggered when an external chip has crossed its limits. Usually, this is
+connected to some LM75-like chip; if at least one crosses its limits, this
+bit gets set.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may already
+have disappeared! Note that in the current implementation, all hardware
+registers are read whenever any data is read (unless it is less than 1.5
+seconds since the last update). This means that you can easily miss
+once-only alarms.
+
+The SiS5595 only updates its values each 1.5 seconds; reading it more often
+will do no harm, but will return 'old' values.
+
+Problems
+--------
+Some chips refuse to be enabled. We don't know why.
+The driver will recognize this and print a message in dmesg.
+
diff --git a/Documentation/i2c/chips/smsc47b397.txt b/Documentation/i2c/chips/smsc47b397
index 389edae7f8d..da9d80c9643 100644
--- a/Documentation/i2c/chips/smsc47b397.txt
+++ b/Documentation/i2c/chips/smsc47b397
@@ -1,7 +1,19 @@
+Kernel driver smsc47b397
+========================
+
+Supported chips:
+ * SMSC LPC47B397-NC
+ Prefix: 'smsc47b397'
+ Addresses scanned: none, address read from Super I/O config space
+ Datasheet: In this file
+
+Authors: Mark M. Hoffman <mhoffman@lightlink.com>
+ Utilitek Systems, Inc.
+
November 23, 2004
The following specification describes the SMSC LPC47B397-NC sensor chip
-(for which there is no public datasheet available). This document was
+(for which there is no public datasheet available). This document was
provided by Craig Kelly (In-Store Broadcast Network) and edited/corrected
by Mark M. Hoffman <mhoffman@lightlink.com>.
@@ -10,10 +22,10 @@ by Mark M. Hoffman <mhoffman@lightlink.com>.
Methods for detecting the HP SIO and reading the thermal data on a dc7100.
The thermal information on the dc7100 is contained in the SIO Hardware Monitor
-(HWM). The information is accessed through an index/data pair. The index/data
-pair is located at the HWM Base Address + 0 and the HWM Base Address + 1. The
+(HWM). The information is accessed through an index/data pair. The index/data
+pair is located at the HWM Base Address + 0 and the HWM Base Address + 1. The
HWM Base address can be obtained from Logical Device 8, registers 0x60 (MSB)
-and 0x61 (LSB). Currently we are using 0x480 for the HWM Base Address and
+and 0x61 (LSB). Currently we are using 0x480 for the HWM Base Address and
0x480 and 0x481 for the index/data pair.
Reading temperature information.
@@ -50,7 +62,7 @@ Reading the tach LSB locks the tach MSB.
The LSB Must be read first.
How to convert the tach reading to RPM.
-The tach reading (TCount) is given by: (Tach MSB * 256) + (Tach LSB)
+The tach reading (TCount) is given by: (Tach MSB * 256) + (Tach LSB)
The SIO counts the number of 90kHz (11.111us) pulses per revolution.
RPM = 60/(TCount * 11.111us)
@@ -72,20 +84,20 @@ To program the configuration registers, the following sequence must be followed:
Enter Configuration Mode
To place the chip into the Configuration State The config key (0x55) is written
-to the CONFIG PORT (0x2E).
+to the CONFIG PORT (0x2E).
Configuration Mode
In configuration mode, the INDEX PORT is located at the CONFIG PORT address and
the DATA PORT is at INDEX PORT address + 1.
-The desired configuration registers are accessed in two steps:
+The desired configuration registers are accessed in two steps:
a. Write the index of the Logical Device Number Configuration Register
(i.e., 0x07) to the INDEX PORT and then write the number of the
desired logical device to the DATA PORT.
b. Write the address of the desired configuration register within the
logical device to the INDEX PORT and then write or read the config-
- uration register through the DATA PORT.
+ uration register through the DATA PORT.
Note: If accessing the Global Configuration Registers, step (a) is not required.
@@ -96,18 +108,18 @@ The chip returns to the RUN State. (This is important).
Programming Example
The following is an example of how to read the SIO Device ID located at 0x20
-; ENTER CONFIGURATION MODE
+; ENTER CONFIGURATION MODE
MOV DX,02EH
MOV AX,055H
OUT DX,AL
-; GLOBAL CONFIGURATION REGISTER
+; GLOBAL CONFIGURATION REGISTER
MOV DX,02EH
MOV AL,20H
-OUT DX,AL
+OUT DX,AL
; READ THE DATA
MOV DX,02FH
IN AL,DX
-; EXIT CONFIGURATION MODE
+; EXIT CONFIGURATION MODE
MOV DX,02EH
MOV AX,0AAH
OUT DX,AL
@@ -122,12 +134,12 @@ Obtaining the HWM Base Address.
The following is an example of how to read the HWM Base Address located in
Logical Device 8.
-; ENTER CONFIGURATION MODE
+; ENTER CONFIGURATION MODE
MOV DX,02EH
MOV AX,055H
OUT DX,AL
-; CONFIGURE REGISTER CRE0,
-; LOGICAL DEVICE 8
+; CONFIGURE REGISTER CRE0,
+; LOGICAL DEVICE 8
MOV DX,02EH
MOV AL,07H
OUT DX,AL ;Point to LD# Config Reg
@@ -135,12 +147,12 @@ MOV DX,02FH
MOV AL, 08H
OUT DX,AL;Point to Logical Device 8
;
-MOV DX,02EH
+MOV DX,02EH
MOV AL,60H
OUT DX,AL ; Point to HWM Base Addr MSB
MOV DX,02FH
IN AL,DX ; Get MSB of HWM Base Addr
-; EXIT CONFIGURATION MODE
+; EXIT CONFIGURATION MODE
MOV DX,02EH
MOV AX,0AAH
OUT DX,AL
diff --git a/Documentation/i2c/chips/smsc47m1 b/Documentation/i2c/chips/smsc47m1
new file mode 100644
index 00000000000..34e6478c142
--- /dev/null
+++ b/Documentation/i2c/chips/smsc47m1
@@ -0,0 +1,52 @@
+Kernel driver smsc47m1
+======================
+
+Supported chips:
+ * SMSC LPC47B27x, LPC47M10x, LPC47M13x, LPC47M14x, LPC47M15x and LPC47M192
+ Addresses scanned: none, address read from Super I/O config space
+ Prefix: 'smsc47m1'
+ Datasheets:
+ http://www.smsc.com/main/datasheets/47b27x.pdf
+ http://www.smsc.com/main/datasheets/47m10x.pdf
+ http://www.smsc.com/main/tools/discontinued/47m13x.pdf
+ http://www.smsc.com/main/datasheets/47m14x.pdf
+ http://www.smsc.com/main/tools/discontinued/47m15x.pdf
+ http://www.smsc.com/main/datasheets/47m192.pdf
+
+Authors:
+ Mark D. Studebaker <mdsxyz123@yahoo.com>,
+ With assistance from Bruce Allen <ballen@uwm.edu>, and his
+ fan.c program: http://www.lsc-group.phys.uwm.edu/%7Eballen/driver/
+ Gabriele Gorla <gorlik@yahoo.com>,
+ Jean Delvare <khali@linux-fr.org>
+
+Description
+-----------
+
+The Standard Microsystems Corporation (SMSC) 47M1xx Super I/O chips
+contain monitoring and PWM control circuitry for two fans.
+
+The 47M15x and 47M192 chips contain a full 'hardware monitoring block'
+in addition to the fan monitoring and control. The hardware monitoring
+block is not supported by the driver.
+
+Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. Fan
+readings can be divided by a programmable divider (1, 2, 4 or 8) to give
+the readings more range or accuracy. Not all RPM values can accurately be
+represented, so some rounding is done. With a divider of 2, the lowest
+representable value is around 2600 RPM.
+
+PWM values are from 0 to 255.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may
+already have disappeared! Note that in the current implementation, all
+hardware registers are read whenever any data is read (unless it is less
+than 1.5 seconds since the last update). This means that you can easily
+miss once-only alarms.
+
+
+**********************
+The lm_sensors project gratefully acknowledges the support of
+Intel in the development of this driver.
diff --git a/Documentation/i2c/chips/via686a b/Documentation/i2c/chips/via686a
new file mode 100644
index 00000000000..b82014cb7c5
--- /dev/null
+++ b/Documentation/i2c/chips/via686a
@@ -0,0 +1,65 @@
+Kernel driver via686a
+=====================
+
+Supported chips:
+ * Via VT82C686A, VT82C686B Southbridge Integrated Hardware Monitor
+ Prefix: 'via686a'
+ Addresses scanned: ISA in PCI-space encoded address
+ Datasheet: On request through web form (http://www.via.com.tw/en/support/datasheets/)
+
+Authors:
+ Kyösti Mälkki <kmalkki@cc.hut.fi>,
+ Mark D. Studebaker <mdsxyz123@yahoo.com>
+ Bob Dougherty <bobd@stanford.edu>
+ (Some conversion-factor data were contributed by
+ Jonathan Teh Soon Yew <j.teh@iname.com>
+ and Alex van Kaam <darkside@chello.nl>.)
+
+Module Parameters
+-----------------
+
+force_addr=0xaddr Set the I/O base address. Useful for Asus A7V boards
+ that don't set the address in the BIOS. Does not do a
+ PCI force; the via686a must still be present in lspci.
+ Don't use this unless the driver complains that the
+ base address is not set.
+ Example: 'modprobe via686a force_addr=0x6000'
+
+Description
+-----------
+
+The driver does not distinguish between the chips and reports
+all as a 686A.
+
+The Via 686a southbridge has integrated hardware monitor functionality.
+It also has an I2C bus, but this driver only supports the hardware monitor.
+For the I2C bus driver, see <file:Documentation/i2c/busses/i2c-viapro>
+
+The Via 686a implements three temperature sensors, two fan rotation speed
+sensors, five voltage sensors and alarms.
+
+Temperatures are measured in degrees Celsius. An alarm is triggered once
+when the Overtemperature Shutdown limit is crossed; it is triggered again
+as soon as it drops below the hysteresis value.
+
+Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. Fan
+readings can be divided by a programmable divider (1, 2, 4 or 8) to give
+the readings more range or accuracy. Not all RPM values can accurately be
+represented, so some rounding is done. With a divider of 2, the lowest
+representable value is around 2600 RPM.
+
+Voltage sensors (also known as IN sensors) report their values in volts.
+An alarm is triggered if the voltage has crossed a programmable minimum
+or maximum limit. Voltages are internally scalled, so each voltage channel
+has a different resolution and range.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may
+already have disappeared! Note that in the current implementation, all
+hardware registers are read whenever any data is read (unless it is less
+than 1.5 seconds since the last update). This means that you can easily
+miss once-only alarms.
+
+The driver only updates its values each 1.5 seconds; reading it more often
+will do no harm, but will return 'old' values.
diff --git a/Documentation/i2c/chips/w83627hf b/Documentation/i2c/chips/w83627hf
new file mode 100644
index 00000000000..78f37c2d602
--- /dev/null
+++ b/Documentation/i2c/chips/w83627hf
@@ -0,0 +1,66 @@
+Kernel driver w83627hf
+======================
+
+Supported chips:
+ * Winbond W83627HF (ISA accesses ONLY)
+ Prefix: 'w83627hf'
+ Addresses scanned: ISA address retrieved from Super I/O registers
+ Datasheet: http://www.winbond.com/PDF/sheet/w83627hf.pdf
+ * Winbond W83627THF
+ Prefix: 'w83627thf'
+ Addresses scanned: ISA address retrieved from Super I/O registers
+ Datasheet: http://www.winbond.com/PDF/sheet/w83627thf.pdf
+ * Winbond W83697HF
+ Prefix: 'w83697hf'
+ Addresses scanned: ISA address retrieved from Super I/O registers
+ Datasheet: http://www.winbond.com/PDF/sheet/697hf.pdf
+ * Winbond W83637HF
+ Prefix: 'w83637hf'
+ Addresses scanned: ISA address retrieved from Super I/O registers
+ Datasheet: http://www.winbond.com/PDF/sheet/w83637hf.pdf
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>,
+ Philip Edelbrock <phil@netroedge.com>,
+ Mark Studebaker <mdsxyz123@yahoo.com>,
+ Bernhard C. Schrenk <clemy@clemy.org>
+
+Module Parameters
+-----------------
+
+* force_addr: int
+ Initialize the ISA address of the sensors
+* force_i2c: int
+ Initialize the I2C address of the sensors
+* init: int
+ (default is 1)
+ Use 'init=0' to bypass initializing the chip.
+ Try this if your computer crashes when you load the module.
+
+Description
+-----------
+
+This driver implements support for ISA accesses *only* for
+the Winbond W83627HF, W83627THF, W83697HF and W83637HF Super I/O chips.
+We will refer to them collectively as Winbond chips.
+
+This driver supports ISA accesses, which should be more reliable
+than i2c accesses. Also, for Tyan boards which contain both a
+Super I/O chip and a second i2c-only Winbond chip (often a W83782D),
+using this driver will avoid i2c address conflicts and complex
+initialization that were required in the w83781d driver.
+
+If you really want i2c accesses for these Super I/O chips,
+use the w83781d driver. However this is not the preferred method
+now that this ISA driver has been developed.
+
+Technically, the w83627thf does not support a VID reading. However, it's
+possible or even likely that your mainboard maker has routed these signals
+to a specific set of general purpose IO pins (the Asus P4C800-E is one such
+board). The w83627thf driver now interprets these as VID. If the VID on
+your board doesn't work, first see doc/vid in the lm_sensors package. If
+that still doesn't help, email us at lm-sensors@lm-sensors.org.
+
+For further information on this driver see the w83781d driver
+documentation.
+
diff --git a/Documentation/i2c/chips/w83781d b/Documentation/i2c/chips/w83781d
new file mode 100644
index 00000000000..e5459333ba6
--- /dev/null
+++ b/Documentation/i2c/chips/w83781d
@@ -0,0 +1,402 @@
+Kernel driver w83781d
+=====================
+
+Supported chips:
+ * Winbond W83781D
+ Prefix: 'w83781d'
+ Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
+ Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/w83781d.pdf
+ * Winbond W83782D
+ Prefix: 'w83782d'
+ Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
+ Datasheet: http://www.winbond.com/PDF/sheet/w83782d.pdf
+ * Winbond W83783S
+ Prefix: 'w83783s'
+ Addresses scanned: I2C 0x2d
+ Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/w83783s.pdf
+ * Winbond W83627HF
+ Prefix: 'w83627hf'
+ Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
+ Datasheet: http://www.winbond.com/PDF/sheet/w83627hf.pdf
+ * Asus AS99127F
+ Prefix: 'as99127f'
+ Addresses scanned: I2C 0x28 - 0x2f
+ Datasheet: Unavailable from Asus
+
+Authors:
+ Frodo Looijaard <frodol@dds.nl>,
+ Philip Edelbrock <phil@netroedge.com>,
+ Mark Studebaker <mdsxyz123@yahoo.com>
+
+Module parameters
+-----------------
+
+* init int
+ (default 1)
+ Use 'init=0' to bypass initializing the chip.
+ Try this if your computer crashes when you load the module.
+
+force_subclients=bus,caddr,saddr,saddr
+ This is used to force the i2c addresses for subclients of
+ a certain chip. Typical usage is `force_subclients=0,0x2d,0x4a,0x4b'
+ to force the subclients of chip 0x2d on bus 0 to i2c addresses
+ 0x4a and 0x4b. This parameter is useful for certain Tyan boards.
+
+Description
+-----------
+
+This driver implements support for the Winbond W83781D, W83782D, W83783S,
+W83627HF chips, and the Asus AS99127F chips. We will refer to them
+collectively as W8378* chips.
+
+There is quite some difference between these chips, but they are similar
+enough that it was sensible to put them together in one driver.
+The W83627HF chip is assumed to be identical to the ISA W83782D.
+The Asus chips are similar to an I2C-only W83782D.
+
+Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA
+as99127f 7 3 0 3 0x31 0x12c3 yes no
+as99127f rev.2 (type_name = as99127f) 0x31 0x5ca3 yes no
+w83781d 7 3 0 3 0x10-1 0x5ca3 yes yes
+w83627hf 9 3 2 3 0x21 0x5ca3 yes yes(LPC)
+w83782d 9 3 2-4 3 0x30 0x5ca3 yes yes
+w83783s 5-6 3 2 1-2 0x40 0x5ca3 yes no
+
+Detection of these chips can sometimes be foiled because they can be in
+an internal state that allows no clean access. If you know the address
+of the chip, use a 'force' parameter; this will put them into a more
+well-behaved state first.
+
+The W8378* implements temperature sensors (three on the W83781D and W83782D,
+two on the W83783S), three fan rotation speed sensors, voltage sensors
+(seven on the W83781D, nine on the W83782D and six on the W83783S), VID
+lines, alarms with beep warnings, and some miscellaneous stuff.
+
+Temperatures are measured in degrees Celsius. There is always one main
+temperature sensor, and one (W83783S) or two (W83781D and W83782D) other
+sensors. An alarm is triggered for the main sensor once when the
+Overtemperature Shutdown limit is crossed; it is triggered again as soon as
+it drops below the Hysteresis value. A more useful behavior
+can be found by setting the Hysteresis value to +127 degrees Celsius; in
+this case, alarms are issued during all the time when the actual temperature
+is above the Overtemperature Shutdown value. The driver sets the
+hysteresis value for temp1 to 127 at initialization.
+
+For the other temperature sensor(s), an alarm is triggered when the
+temperature gets higher then the Overtemperature Shutdown value; it stays
+on until the temperature falls below the Hysteresis value. But on the
+W83781D, there is only one alarm that functions for both other sensors!
+Temperatures are guaranteed within a range of -55 to +125 degrees. The
+main temperature sensors has a resolution of 1 degree; the other sensor(s)
+of 0.5 degree.
+
+Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. Fan
+readings can be divided by a programmable divider (1, 2, 4 or 8 for the
+W83781D; 1, 2, 4, 8, 16, 32, 64 or 128 for the others) to give
+the readings more range or accuracy. Not all RPM values can accurately
+be represented, so some rounding is done. With a divider of 2, the lowest
+representable value is around 2600 RPM.
+
+Voltage sensors (also known as IN sensors) report their values in volts.
+An alarm is triggered if the voltage has crossed a programmable minimum
+or maximum limit. Note that minimum in this case always means 'closest to
+zero'; this is important for negative voltage measurements. All voltage
+inputs can measure voltages between 0 and 4.08 volts, with a resolution
+of 0.016 volt.
+
+The VID lines encode the core voltage value: the voltage level your processor
+should work with. This is hardcoded by the mainboard and/or processor itself.
+It is a value in volts. When it is unconnected, you will often find the
+value 3.50 V here.
+
+The W83782D and W83783S temperature conversion machine understands about
+several kinds of temperature probes. You can program the so-called
+beta value in the sensor files. '1' is the PII/Celeron diode, '2' is the
+TN3904 transistor, and 3435 the default thermistor value. Other values
+are (not yet) supported.
+
+In addition to the alarms described above, there is a CHAS alarm on the
+chips which triggers if your computer case is open.
+
+When an alarm goes off, you can be warned by a beeping signal through
+your computer speaker. It is possible to enable all beeping globally,
+or only the beeping for some alarms.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may
+already have disappeared! Note that in the current implementation, all
+hardware registers are read whenever any data is read (unless it is less
+than 1.5 seconds since the last update). This means that you can easily
+miss once-only alarms.
+
+The chips only update values each 1.5 seconds; reading them more often
+will do no harm, but will return 'old' values.
+
+AS99127F PROBLEMS
+-----------------
+The as99127f support was developed without the benefit of a datasheet.
+In most cases it is treated as a w83781d (although revision 2 of the
+AS99127F looks more like a w83782d).
+This support will be BETA until a datasheet is released.
+One user has reported problems with fans stopping
+occasionally.
+
+Note that the individual beep bits are inverted from the other chips.
+The driver now takes care of this so that user-space applications
+don't have to know about it.
+
+Known problems:
+ - Problems with diode/thermistor settings (supported?)
+ - One user reports fans stopping under high server load.
+ - Revision 2 seems to have 2 PWM registers but we don't know
+ how to handle them. More details below.
+
+These will not be fixed unless we get a datasheet.
+If you have problems, please lobby Asus to release a datasheet.
+Unfortunately several others have without success.
+Please do not send mail to us asking for better as99127f support.
+We have done the best we can without a datasheet.
+Please do not send mail to the author or the sensors group asking for
+a datasheet or ideas on how to convince Asus. We can't help.
+
+
+NOTES:
+-----
+ 783s has no in1 so that in[2-6] are compatible with the 781d/782d.
+
+ 783s pin is programmable for -5V or temp1; defaults to -5V,
+ no control in driver so temp1 doesn't work.
+
+ 782d and 783s datasheets differ on which is pwm1 and which is pwm2.
+ We chose to follow 782d.
+
+ 782d and 783s pin is programmable for fan3 input or pwm2 output;
+ defaults to fan3 input.
+ If pwm2 is enabled (with echo 255 1 > pwm2), then
+ fan3 will report 0.
+
+ 782d has pwm1-2 for ISA, pwm1-4 for i2c. (pwm3-4 share pins with
+ the ISA pins)
+
+Data sheet updates:
+------------------
+ - PWM clock registers:
+
+ 000: master / 512
+ 001: master / 1024
+ 010: master / 2048
+ 011: master / 4096
+ 100: master / 8192
+
+
+Answers from Winbond tech support
+---------------------------------
+>
+> 1) In the W83781D data sheet section 7.2 last paragraph, it talks about
+> reprogramming the R-T table if the Beta of the thermistor is not
+> 3435K. The R-T table is described briefly in section 8.20.
+> What formulas do I use to program a new R-T table for a given Beta?
+>
+ We are sorry that the calculation for R-T table value is
+confidential. If you have another Beta value of thermistor, we can help
+to calculate the R-T table for you. But you should give us real R-T
+Table which can be gotten by thermistor vendor. Therefore we will calculate
+them and obtain 32-byte data, and you can fill the 32-byte data to the
+register in Bank0.CR51 of W83781D.
+
+
+> 2) In the W83782D data sheet, it mentions that pins 38, 39, and 40 are
+> programmable to be either thermistor or Pentium II diode inputs.
+> How do I program them for diode inputs? I can't find any register
+> to program these to be diode inputs.
+ --> You may program Bank0 CR[5Dh] and CR[59h] registers.
+
+ CR[5Dh] bit 1(VTIN1) bit 2(VTIN2) bit 3(VTIN3)
+
+ thermistor 0 0 0
+ diode 1 1 1
+
+
+(error) CR[59h] bit 4(VTIN1) bit 2(VTIN2) bit 3(VTIN3)
+(right) CR[59h] bit 4(VTIN1) bit 5(VTIN2) bit 6(VTIN3)
+
+ PII thermal diode 1 1 1
+ 2N3904 diode 0 0 0
+
+
+Asus Clones
+-----------
+
+We have no datasheets for the Asus clones (AS99127F and ASB100 Bach).
+Here are some very useful information that were given to us by Alex Van
+Kaam about how to detect these chips, and how to read their values. He
+also gives advice for another Asus chipset, the Mozart-2 (which we
+don't support yet). Thanks Alex!
+I reworded some parts and added personal comments.
+
+# Detection:
+
+AS99127F rev.1, AS99127F rev.2 and ASB100:
+- I2C address range: 0x29 - 0x2F
+- If register 0x58 holds 0x31 then we have an Asus (either ASB100 or
+ AS99127F)
+- Which one depends on register 0x4F (manufacturer ID):
+ 0x06 or 0x94: ASB100
+ 0x12 or 0xC3: AS99127F rev.1
+ 0x5C or 0xA3: AS99127F rev.2
+ Note that 0x5CA3 is Winbond's ID (WEC), which let us think Asus get their
+ AS99127F rev.2 direct from Winbond. The other codes mean ATT and DVC,
+ respectively. ATT could stand for Asustek something (although it would be
+ very badly chosen IMHO), I don't know what DVC could stand for. Maybe
+ these codes simply aren't meant to be decoded that way.
+
+Mozart-2:
+- I2C address: 0x77
+- If register 0x58 holds 0x56 or 0x10 then we have a Mozart-2
+- Of the Mozart there are 3 types:
+ 0x58=0x56, 0x4E=0x94, 0x4F=0x36: Asus ASM58 Mozart-2
+ 0x58=0x56, 0x4E=0x94, 0x4F=0x06: Asus AS2K129R Mozart-2
+ 0x58=0x10, 0x4E=0x5C, 0x4F=0xA3: Asus ??? Mozart-2
+ You can handle all 3 the exact same way :)
+
+# Temperature sensors:
+
+ASB100:
+- sensor 1: register 0x27
+- sensor 2 & 3 are the 2 LM75's on the SMBus
+- sensor 4: register 0x17
+Remark: I noticed that on Intel boards sensor 2 is used for the CPU
+ and 4 is ignored/stuck, on AMD boards sensor 4 is the CPU and sensor 2 is
+ either ignored or a socket temperature.
+
+AS99127F (rev.1 and 2 alike):
+- sensor 1: register 0x27
+- sensor 2 & 3 are the 2 LM75's on the SMBus
+Remark: Register 0x5b is suspected to be temperature type selector. Bit 1
+ would control temp1, bit 3 temp2 and bit 5 temp3.
+
+Mozart-2:
+- sensor 1: register 0x27
+- sensor 2: register 0x13
+
+# Fan sensors:
+
+ASB100, AS99127F (rev.1 and 2 alike):
+- 3 fans, identical to the W83781D
+
+Mozart-2:
+- 2 fans only, 1350000/RPM/div
+- fan 1: register 0x28, divisor on register 0xA1 (bits 4-5)
+- fan 2: register 0x29, divisor on register 0xA1 (bits 6-7)
+
+# Voltages:
+
+This is where there is a difference between AS99127F rev.1 and 2.
+Remark: The difference is similar to the difference between
+ W83781D and W83782D.
+
+ASB100:
+in0=r(0x20)*0.016
+in1=r(0x21)*0.016
+in2=r(0x22)*0.016
+in3=r(0x23)*0.016*1.68
+in4=r(0x24)*0.016*3.8
+in5=r(0x25)*(-0.016)*3.97
+in6=r(0x26)*(-0.016)*1.666
+
+AS99127F rev.1:
+in0=r(0x20)*0.016
+in1=r(0x21)*0.016
+in2=r(0x22)*0.016
+in3=r(0x23)*0.016*1.68
+in4=r(0x24)*0.016*3.8
+in5=r(0x25)*(-0.016)*3.97
+in6=r(0x26)*(-0.016)*1.503
+
+AS99127F rev.2:
+in0=r(0x20)*0.016
+in1=r(0x21)*0.016
+in2=r(0x22)*0.016
+in3=r(0x23)*0.016*1.68
+in4=r(0x24)*0.016*3.8
+in5=(r(0x25)*0.016-3.6)*5.14+3.6
+in6=(r(0x26)*0.016-3.6)*3.14+3.6
+
+Mozart-2:
+in0=r(0x20)*0.016
+in1=255
+in2=r(0x22)*0.016
+in3=r(0x23)*0.016*1.68
+in4=r(0x24)*0.016*4
+in5=255
+in6=255
+
+
+# PWM
+
+Additional info about PWM on the AS99127F (may apply to other Asus
+chips as well) by Jean Delvare as of 2004-04-09:
+
+AS99127F revision 2 seems to have two PWM registers at 0x59 and 0x5A,
+and a temperature sensor type selector at 0x5B (which basically means
+that they swapped registers 0x59 and 0x5B when you compare with Winbond
+chips).
+Revision 1 of the chip also has the temperature sensor type selector at
+0x5B, but PWM registers have no effect.
+
+We don't know exactly how the temperature sensor type selection works.
+Looks like bits 1-0 are for temp1, bits 3-2 for temp2 and bits 5-4 for
+temp3, although it is possible that only the most significant bit matters
+each time. So far, values other than 0 always broke the readings.
+
+PWM registers seem to be split in two parts: bit 7 is a mode selector,
+while the other bits seem to define a value or threshold.
+
+When bit 7 is clear, bits 6-0 seem to hold a threshold value. If the value
+is below a given limit, the fan runs at low speed. If the value is above
+the limit, the fan runs at full speed. We have no clue as to what the limit
+represents. Note that there seem to be some inertia in this mode, speed
+changes may need some time to trigger. Also, an hysteresis mechanism is
+suspected since walking through all the values increasingly and then
+decreasingly led to slightly different limits.
+
+When bit 7 is set, bits 3-0 seem to hold a threshold value, while bits 6-4
+would not be significant. If the value is below a given limit, the fan runs
+at full speed, while if it is above the limit it runs at low speed (so this
+is the contrary of the other mode, in a way). Here again, we don't know
+what the limit is supposed to represent.
+
+One remarkable thing is that the fans would only have two or three
+different speeds (transitional states left apart), not a whole range as
+you usually get with PWM.
+
+As a conclusion, you can write 0x00 or 0x8F to the PWM registers to make
+fans run at low speed, and 0x7F or 0x80 to make them run at full speed.
+
+Please contact us if you can figure out how it is supposed to work. As
+long as we don't know more, the w83781d driver doesn't handle PWM on
+AS99127F chips at all.
+
+Additional info about PWM on the AS99127F rev.1 by Hector Martin:
+
+I've been fiddling around with the (in)famous 0x59 register and
+found out the following values do work as a form of coarse pwm:
+
+0x80 - seems to turn fans off after some time(1-2 minutes)... might be
+some form of auto-fan-control based on temp? hmm (Qfan? this mobo is an
+old ASUS, it isn't marketed as Qfan. Maybe some beta pre-attemp at Qfan
+that was dropped at the BIOS)
+0x81 - off
+0x82 - slightly "on-ner" than off, but my fans do not get to move. I can
+hear the high-pitched PWM sound that motors give off at too-low-pwm.
+0x83 - now they do move. Estimate about 70% speed or so.
+0x84-0x8f - full on
+
+Changing the high nibble doesn't seem to do much except the high bit
+(0x80) must be set for PWM to work, else the current pwm doesn't seem to
+change.
+
+My mobo is an ASUS A7V266-E. This behavior is similar to what I got
+with speedfan under Windows, where 0-15% would be off, 15-2x% (can't
+remember the exact value) would be 70% and higher would be full on.
diff --git a/Documentation/i2c/chips/w83l785ts b/Documentation/i2c/chips/w83l785ts
new file mode 100644
index 00000000000..1841cedc25b
--- /dev/null
+++ b/Documentation/i2c/chips/w83l785ts
@@ -0,0 +1,39 @@
+Kernel driver w83l785ts
+=======================
+
+Supported chips:
+ * Winbond W83L785TS-S
+ Prefix: 'w83l785ts'
+ Addresses scanned: I2C 0x2e
+ Datasheet: Publicly available at the Winbond USA website
+ http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83L785TS-S.pdf
+
+Authors:
+ Jean Delvare <khali@linux-fr.org>
+
+Description
+-----------
+
+The W83L785TS-S is a digital temperature sensor. It senses the
+temperature of a single external diode. The high limit is
+theoretically defined as 85 or 100 degrees C through a combination
+of external resistors, so the user cannot change it. Values seen so
+far suggest that the two possible limits are actually 95 and 110
+degrees C. The datasheet is rather poor and obviously inaccurate
+on several points including this one.
+
+All temperature values are given in degrees Celsius. Resolution
+is 1.0 degree. See the datasheet for details.
+
+The w83l785ts driver will not update its values more frequently than
+every other second; reading them more often will do no harm, but will
+return 'old' values.
+
+Known Issues
+------------
+
+On some systems (Asus), the BIOS is known to interfere with the driver
+and cause read errors. The driver will retry a given number of times
+(5 by default) and then give up, returning the old value (or 0 if
+there is no old value). It seems to work well enough so that you should
+not notice anything. Thanks to James Bolt for helping test this feature.
diff --git a/Documentation/i2c/porting-clients b/Documentation/i2c/porting-clients
index 56404918eab..a7adbdd9ea8 100644
--- a/Documentation/i2c/porting-clients
+++ b/Documentation/i2c/porting-clients
@@ -57,7 +57,7 @@ Technical changes:
Documentation/i2c/sysfs-interface for the individual files. Also
convert the units these files read and write to the specified ones.
If you need to add a new type of file, please discuss it on the
- sensors mailing list <sensors@stimpy.netroedge.com> by providing a
+ sensors mailing list <lm-sensors@lm-sensors.org> by providing a
patch to the Documentation/i2c/sysfs-interface file.
* [Attach] For I2C drivers, the attach function should make sure
diff --git a/Documentation/i2c/userspace-tools b/Documentation/i2c/userspace-tools
new file mode 100644
index 00000000000..2622aac6542
--- /dev/null
+++ b/Documentation/i2c/userspace-tools
@@ -0,0 +1,39 @@
+Introduction
+------------
+
+Most mainboards have sensor chips to monitor system health (like temperatures,
+voltages, fans speed). They are often connected through an I2C bus, but some
+are also connected directly through the ISA bus.
+
+The kernel drivers make the data from the sensor chips available in the /sys
+virtual filesystem. Userspace tools are then used to display or set or the
+data in a more friendly manner.
+
+Lm-sensors
+----------
+
+Core set of utilites that will allow you to obtain health information,
+setup monitoring limits etc. You can get them on their homepage
+http://www.lm-sensors.nu/ or as a package from your Linux distribution.
+
+If from website:
+Get lmsensors from project web site. Please note, you need only userspace
+part, so compile with "make user_install" target.
+
+General hints to get things working:
+
+0) get lm-sensors userspace utils
+1) compile all drivers in I2C section as modules in your kernel
+2) run sensors-detect script, it will tell you what modules you need to load.
+3) load them and run "sensors" command, you should see some results.
+4) fix sensors.conf, labels, limits, fan divisors
+5) if any more problems consult FAQ, or documentation
+
+Other utilites
+--------------
+
+If you want some graphical indicators of system health look for applications
+like: gkrellm, ksensors, xsensors, wmtemp, wmsensors, wmgtemp, ksysguardd,
+hardware-monitor
+
+If you are server administrator you can try snmpd or mrtgutils.
diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients
index ad27511e3c7..f482dae81de 100644
--- a/Documentation/i2c/writing-clients
+++ b/Documentation/i2c/writing-clients
@@ -171,45 +171,31 @@ The following lists are used internally:
normal_i2c: filled in by the module writer.
A list of I2C addresses which should normally be examined.
- normal_i2c_range: filled in by the module writer.
- A list of pairs of I2C addresses, each pair being an inclusive range of
- addresses which should normally be examined.
probe: insmod parameter.
A list of pairs. The first value is a bus number (-1 for any I2C bus),
the second is the address. These addresses are also probed, as if they
were in the 'normal' list.
- probe_range: insmod parameter.
- A list of triples. The first value is a bus number (-1 for any I2C bus),
- the second and third are addresses. These form an inclusive range of
- addresses that are also probed, as if they were in the 'normal' list.
ignore: insmod parameter.
A list of pairs. The first value is a bus number (-1 for any I2C bus),
the second is the I2C address. These addresses are never probed.
This parameter overrules 'normal' and 'probe', but not the 'force' lists.
- ignore_range: insmod parameter.
- A list of triples. The first value is a bus number (-1 for any I2C bus),
- the second and third are addresses. These form an inclusive range of
- I2C addresses that are never probed.
- This parameter overrules 'normal' and 'probe', but not the 'force' lists.
force: insmod parameter.
A list of pairs. The first value is a bus number (-1 for any I2C bus),
the second is the I2C address. A device is blindly assumed to be on
the given address, no probing is done.
-Fortunately, as a module writer, you just have to define the `normal'
-and/or `normal_range' parameters. The complete declaration could look
-like this:
+Fortunately, as a module writer, you just have to define the `normal_i2c'
+parameter. The complete declaration could look like this:
- /* Scan 0x20 to 0x2f, 0x37, and 0x40 to 0x4f */
- static unsigned short normal_i2c[] = { 0x37,I2C_CLIENT_END };
- static unsigned short normal_i2c_range[] = { 0x20, 0x2f, 0x40, 0x4f,
- I2C_CLIENT_END };
+ /* Scan 0x37, and 0x48 to 0x4f */
+ static unsigned short normal_i2c[] = { 0x37, 0x48, 0x49, 0x4a, 0x4b, 0x4c,
+ 0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
/* Magic definition of all other variables and things */
I2C_CLIENT_INSMOD;
-Note that you *have* to call the two defined variables `normal_i2c' and
-`normal_i2c_range', without any prefix!
+Note that you *have* to call the defined variable `normal_i2c',
+without any prefix!
Probing classes (sensors)
@@ -223,39 +209,17 @@ The following lists are used internally. They are all lists of integers.
normal_i2c: filled in by the module writer. Terminated by SENSORS_I2C_END.
A list of I2C addresses which should normally be examined.
- normal_i2c_range: filled in by the module writer. Terminated by
- SENSORS_I2C_END
- A list of pairs of I2C addresses, each pair being an inclusive range of
- addresses which should normally be examined.
normal_isa: filled in by the module writer. Terminated by SENSORS_ISA_END.
A list of ISA addresses which should normally be examined.
- normal_isa_range: filled in by the module writer. Terminated by
- SENSORS_ISA_END
- A list of triples. The first two elements are ISA addresses, being an
- range of addresses which should normally be examined. The third is the
- modulo parameter: only addresses which are 0 module this value relative
- to the first address of the range are actually considered.
probe: insmod parameter. Initialize this list with SENSORS_I2C_END values.
A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
the ISA bus, -1 for any I2C bus), the second is the address. These
addresses are also probed, as if they were in the 'normal' list.
- probe_range: insmod parameter. Initialize this list with SENSORS_I2C_END
- values.
- A list of triples. The first value is a bus number (SENSORS_ISA_BUS for
- the ISA bus, -1 for any I2C bus), the second and third are addresses.
- These form an inclusive range of addresses that are also probed, as
- if they were in the 'normal' list.
ignore: insmod parameter. Initialize this list with SENSORS_I2C_END values.
A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
the ISA bus, -1 for any I2C bus), the second is the I2C address. These
addresses are never probed. This parameter overrules 'normal' and
'probe', but not the 'force' lists.
- ignore_range: insmod parameter. Initialize this list with SENSORS_I2C_END
- values.
- A list of triples. The first value is a bus number (SENSORS_ISA_BUS for
- the ISA bus, -1 for any I2C bus), the second and third are addresses.
- These form an inclusive range of I2C addresses that are never probed.
- This parameter overrules 'normal' and 'probe', but not the 'force' lists.
Also used is a list of pointers to sensors_force_data structures:
force_data: insmod parameters. A list, ending with an element of which
@@ -269,16 +233,14 @@ Also used is a list of pointers to sensors_force_data structures:
So we have a generic insmod variabled `force', and chip-specific variables
`force_CHIPNAME'.
-Fortunately, as a module writer, you just have to define the `normal'
-and/or `normal_range' parameters, and define what chip names are used.
+Fortunately, as a module writer, you just have to define the `normal_i2c'
+and `normal_isa' parameters, and define what chip names are used.
The complete declaration could look like this:
- /* Scan i2c addresses 0x20 to 0x2f, 0x37, and 0x40 to 0x4f
- static unsigned short normal_i2c[] = {0x37,SENSORS_I2C_END};
- static unsigned short normal_i2c_range[] = {0x20,0x2f,0x40,0x4f,
- SENSORS_I2C_END};
+ /* Scan i2c addresses 0x37, and 0x48 to 0x4f */
+ static unsigned short normal_i2c[] = { 0x37, 0x48, 0x49, 0x4a, 0x4b, 0x4c,
+ 0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
/* Scan ISA address 0x290 */
static unsigned int normal_isa[] = {0x0290,SENSORS_ISA_END};
- static unsigned int normal_isa_range[] = {SENSORS_ISA_END};
/* Define chips foo and bar, as well as all module parameters and things */
SENSORS_INSMOD_2(foo,bar);
diff --git a/Documentation/kdump/gdbmacros.txt b/Documentation/kdump/gdbmacros.txt
new file mode 100644
index 00000000000..bc1b9eb92ae
--- /dev/null
+++ b/Documentation/kdump/gdbmacros.txt
@@ -0,0 +1,179 @@
+#
+# This file contains a few gdb macros (user defined commands) to extract
+# useful information from kernel crashdump (kdump) like stack traces of
+# all the processes or a particular process and trapinfo.
+#
+# These macros can be used by copying this file in .gdbinit (put in home
+# directory or current directory) or by invoking gdb command with
+# --command=<command-file-name> option
+#
+# Credits:
+# Alexander Nyberg <alexn@telia.com>
+# V Srivatsa <vatsa@in.ibm.com>
+# Maneesh Soni <maneesh@in.ibm.com>
+#
+
+define bttnobp
+ set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
+ set $pid_off=((size_t)&((struct task_struct *)0)->pids[1].pid_list.next)
+ set $init_t=&init_task
+ set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
+ while ($next_t != $init_t)
+ set $next_t=(struct task_struct *)$next_t
+ printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm
+ printf "===================\n"
+ set var $stackp = $next_t.thread.esp
+ set var $stack_top = ($stackp & ~4095) + 4096
+
+ while ($stackp < $stack_top)
+ if (*($stackp) > _stext && *($stackp) < _sinittext)
+ info symbol *($stackp)
+ end
+ set $stackp += 4
+ end
+ set $next_th=(((char *)$next_t->pids[1].pid_list.next) - $pid_off)
+ while ($next_th != $next_t)
+ set $next_th=(struct task_struct *)$next_th
+ printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm
+ printf "===================\n"
+ set var $stackp = $next_t.thread.esp
+ set var $stack_top = ($stackp & ~4095) + 4096
+
+ while ($stackp < $stack_top)
+ if (*($stackp) > _stext && *($stackp) < _sinittext)
+ info symbol *($stackp)
+ end
+ set $stackp += 4
+ end
+ set $next_th=(((char *)$next_th->pids[1].pid_list.next) - $pid_off)
+ end
+ set $next_t=(char *)($next_t->tasks.next) - $tasks_off
+ end
+end
+document bttnobp
+ dump all thread stack traces on a kernel compiled with !CONFIG_FRAME_POINTER
+end
+
+define btt
+ set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
+ set $pid_off=((size_t)&((struct task_struct *)0)->pids[1].pid_list.next)
+ set $init_t=&init_task
+ set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
+ while ($next_t != $init_t)
+ set $next_t=(struct task_struct *)$next_t
+ printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm
+ printf "===================\n"
+ set var $stackp = $next_t.thread.esp
+ set var $stack_top = ($stackp & ~4095) + 4096
+ set var $stack_bot = ($stackp & ~4095)
+
+ set $stackp = *($stackp)
+ while (($stackp < $stack_top) && ($stackp > $stack_bot))
+ set var $addr = *($stackp + 4)
+ info symbol $addr
+ set $stackp = *($stackp)
+ end
+
+ set $next_th=(((char *)$next_t->pids[1].pid_list.next) - $pid_off)
+ while ($next_th != $next_t)
+ set $next_th=(struct task_struct *)$next_th
+ printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm
+ printf "===================\n"
+ set var $stackp = $next_t.thread.esp
+ set var $stack_top = ($stackp & ~4095) + 4096
+ set var $stack_bot = ($stackp & ~4095)
+
+ set $stackp = *($stackp)
+ while (($stackp < $stack_top) && ($stackp > $stack_bot))
+ set var $addr = *($stackp + 4)
+ info symbol $addr
+ set $stackp = *($stackp)
+ end
+ set $next_th=(((char *)$next_th->pids[1].pid_list.next) - $pid_off)
+ end
+ set $next_t=(char *)($next_t->tasks.next) - $tasks_off
+ end
+end
+document btt
+ dump all thread stack traces on a kernel compiled with CONFIG_FRAME_POINTER
+end
+
+define btpid
+ set var $pid = $arg0
+ set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
+ set $pid_off=((size_t)&((struct task_struct *)0)->pids[1].pid_list.next)
+ set $init_t=&init_task
+ set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
+ set var $pid_task = 0
+
+ while ($next_t != $init_t)
+ set $next_t=(struct task_struct *)$next_t
+
+ if ($next_t.pid == $pid)
+ set $pid_task = $next_t
+ end
+
+ set $next_th=(((char *)$next_t->pids[1].pid_list.next) - $pid_off)
+ while ($next_th != $next_t)
+ set $next_th=(struct task_struct *)$next_th
+ if ($next_th.pid == $pid)
+ set $pid_task = $next_th
+ end
+ set $next_th=(((char *)$next_th->pids[1].pid_list.next) - $pid_off)
+ end
+ set $next_t=(char *)($next_t->tasks.next) - $tasks_off
+ end
+
+ printf "\npid %d; comm %s:\n", $pid_task.pid, $pid_task.comm
+ printf "===================\n"
+ set var $stackp = $pid_task.thread.esp
+ set var $stack_top = ($stackp & ~4095) + 4096
+ set var $stack_bot = ($stackp & ~4095)
+
+ set $stackp = *($stackp)
+ while (($stackp < $stack_top) && ($stackp > $stack_bot))
+ set var $addr = *($stackp + 4)
+ info symbol $addr
+ set $stackp = *($stackp)
+ end
+end
+document btpid
+ backtrace of pid
+end
+
+
+define trapinfo
+ set var $pid = $arg0
+ set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
+ set $pid_off=((size_t)&((struct task_struct *)0)->pids[1].pid_list.next)
+ set $init_t=&init_task
+ set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
+ set var $pid_task = 0
+
+ while ($next_t != $init_t)
+ set $next_t=(struct task_struct *)$next_t
+
+ if ($next_t.pid == $pid)
+ set $pid_task = $next_t
+ end
+
+ set $next_th=(((char *)$next_t->pids[1].pid_list.next) - $pid_off)
+ while ($next_th != $next_t)
+ set $next_th=(struct task_struct *)$next_th
+ if ($next_th.pid == $pid)
+ set $pid_task = $next_th
+ end
+ set $next_th=(((char *)$next_th->pids[1].pid_list.next) - $pid_off)
+ end
+ set $next_t=(char *)($next_t->tasks.next) - $tasks_off
+ end
+
+ printf "Trapno %ld, cr2 0x%lx, error_code %ld\n", $pid_task.thread.trap_no, \
+ $pid_task.thread.cr2, $pid_task.thread.error_code
+
+end
+document trapinfo
+ Run info threads and lookup pid of thread #1
+ 'trapinfo <pid>' will tell you by which trap & possibly
+ addresthe kernel paniced.
+end
diff --git a/Documentation/kdump/kdump.txt b/Documentation/kdump/kdump.txt
new file mode 100644
index 00000000000..7ff213f4bec
--- /dev/null
+++ b/Documentation/kdump/kdump.txt
@@ -0,0 +1,141 @@
+Documentation for kdump - the kexec-based crash dumping solution
+================================================================
+
+DESIGN
+======
+
+Kdump uses kexec to reboot to a second kernel whenever a dump needs to be taken.
+This second kernel is booted with very little memory. The first kernel reserves
+the section of memory that the second kernel uses. This ensures that on-going
+DMA from the first kernel does not corrupt the second kernel.
+
+All the necessary information about Core image is encoded in ELF format and
+stored in reserved area of memory before crash. Physical address of start of
+ELF header is passed to new kernel through command line parameter elfcorehdr=.
+
+On i386, the first 640 KB of physical memory is needed to boot, irrespective
+of where the kernel loads. Hence, this region is backed up by kexec just before
+rebooting into the new kernel.
+
+In the second kernel, "old memory" can be accessed in two ways.
+
+- The first one is through a /dev/oldmem device interface. A capture utility
+ can read the device file and write out the memory in raw format. This is raw
+ dump of memory and analysis/capture tool should be intelligent enough to
+ determine where to look for the right information. ELF headers (elfcorehdr=)
+ can become handy here.
+
+- The second interface is through /proc/vmcore. This exports the dump as an ELF
+ format file which can be written out using any file copy command
+ (cp, scp, etc). Further, gdb can be used to perform limited debugging on
+ the dump file. This method ensures methods ensure that there is correct
+ ordering of the dump pages (corresponding to the first 640 KB that has been
+ relocated).
+
+SETUP
+=====
+
+1) Download http://www.xmission.com/~ebiederm/files/kexec/kexec-tools-1.101.tar.gz
+ and apply http://lse.sourceforge.net/kdump/patches/kexec-tools-1.101-kdump.patch
+ and after that build the source.
+
+2) Download and build the appropriate (latest) kexec/kdump (-mm) kernel
+ patchset and apply it to the vanilla kernel tree.
+
+ Two kernels need to be built in order to get this feature working.
+
+ A) First kernel:
+ a) Enable "kexec system call" feature (in Processor type and features).
+ CONFIG_KEXEC=y
+ b) This kernel's physical load address should be the default value of
+ 0x100000 (0x100000, 1 MB) (in Processor type and features).
+ CONFIG_PHYSICAL_START=0x100000
+ c) Enable "sysfs file system support" (in Pseudo filesystems).
+ CONFIG_SYSFS=y
+ d) Boot into first kernel with the command line parameter "crashkernel=Y@X".
+ Use appropriate values for X and Y. Y denotes how much memory to reserve
+ for the second kernel, and X denotes at what physical address the reserved
+ memory section starts. For example: "crashkernel=64M@16M".
+
+ B) Second kernel:
+ a) Enable "kernel crash dumps" feature (in Processor type and features).
+ CONFIG_CRASH_DUMP=y
+ b) Specify a suitable value for "Physical address where the kernel is
+ loaded" (in Processor type and features). Typically this value
+ should be same as X (See option d) above, e.g., 16 MB or 0x1000000.
+ CONFIG_PHYSICAL_START=0x1000000
+ c) Enable "/proc/vmcore support" (Optional, in Pseudo filesystems).
+ CONFIG_PROC_VMCORE=y
+ d) Disable SMP support and build a UP kernel (Until it is fixed).
+ CONFIG_SMP=n
+ e) Enable "Local APIC support on uniprocessors".
+ CONFIG_X86_UP_APIC=y
+ f) Enable "IO-APIC support on uniprocessors"
+ CONFIG_X86_UP_IOAPIC=y
+
+ Note: i) Options a) and b) depend upon "Configure standard kernel features
+ (for small systems)" (under General setup).
+ ii) Option a) also depends on CONFIG_HIGHMEM (under Processor
+ type and features).
+ iii) Both option a) and b) are under "Processor type and features".
+
+3) Boot into the first kernel. You are now ready to try out kexec-based crash
+ dumps.
+
+4) Load the second kernel to be booted using:
+
+ kexec -p <second-kernel> --crash-dump --args-linux --append="root=<root-dev>
+ init 1 irqpoll"
+
+ Note: i) <second-kernel> has to be a vmlinux image. bzImage will not work,
+ as of now.
+ ii) By default ELF headers are stored in ELF32 format (for i386). This
+ is sufficient to represent the physical memory up to 4GB. To store
+ headers in ELF64 format, specifiy "--elf64-core-headers" on the
+ kexec command line additionally.
+ iii) Specify "irqpoll" as command line parameter. This reduces driver
+ initialization failures in second kernel due to shared interrupts.
+
+5) System reboots into the second kernel when a panic occurs. A module can be
+ written to force the panic or "ALT-SysRq-c" can be used initiate a crash
+ dump for testing purposes.
+
+6) Write out the dump file using
+
+ cp /proc/vmcore <dump-file>
+
+ Dump memory can also be accessed as a /dev/oldmem device for a linear/raw
+ view. To create the device, type:
+
+ mknod /dev/oldmem c 1 12
+
+ Use "dd" with suitable options for count, bs and skip to access specific
+ portions of the dump.
+
+ Entire memory: dd if=/dev/oldmem of=oldmem.001
+
+ANALYSIS
+========
+
+Limited analysis can be done using gdb on the dump file copied out of
+/proc/vmcore. Use vmlinux built with -g and run
+
+ gdb vmlinux <dump-file>
+
+Stack trace for the task on processor 0, register display, memory display
+work fine.
+
+Note: gdb cannot analyse core files generated in ELF64 format for i386.
+
+TODO
+====
+
+1) Provide a kernel pages filtering mechanism so that core file size is not
+ insane on systems having huge memory banks.
+2) Modify "crash" tool to make it recognize this dump.
+
+CONTACT
+=======
+
+Vivek Goyal (vgoyal@in.ibm.com)
+Maneesh Soni (maneesh@in.ibm.com)
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 4924d387a65..f44bb5567c5 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -358,6 +358,10 @@ running once the system is up.
cpia_pp= [HW,PPT]
Format: { parport<nr> | auto | none }
+ crashkernel=nn[KMG]@ss[KMG]
+ [KNL] Reserve a chunk of physical memory to
+ hold a kernel to switch to with kexec on panic.
+
cs4232= [HW,OSS]
Format: <io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>
@@ -447,6 +451,10 @@ running once the system is up.
Format: {"as"|"cfq"|"deadline"|"noop"}
See Documentation/block/as-iosched.txt
and Documentation/block/deadline-iosched.txt for details.
+ elfcorehdr= [IA-32]
+ Specifies physical address of start of kernel core image
+ elf header.
+ See Documentation/kdump.txt for details.
enforcing [SELINUX] Set initial enforcing status.
Format: {"0" | "1"}
@@ -548,6 +556,9 @@ running once the system is up.
i810= [HW,DRM]
+ i8k.ignore_dmi [HW] Continue probing hardware even if DMI data
+ indicates that the driver is running on unsupported
+ hardware.
i8k.force [HW] Activate i8k driver even if SMM BIOS signature
does not match list of supported models.
i8k.power_status
diff --git a/Documentation/keys.txt b/Documentation/keys.txt
index 36d80aeeaf2..0321ded4b9a 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -22,6 +22,7 @@ This document has the following sections:
- New procfs files
- Userspace system call interface
- Kernel services
+ - Notes on accessing payload contents
- Defining a key type
- Request-key callback service
- Key access filesystem
@@ -45,27 +46,26 @@ Each key has a number of attributes:
- State.
- (*) Each key is issued a serial number of type key_serial_t that is unique
- for the lifetime of that key. All serial numbers are positive non-zero
- 32-bit integers.
+ (*) Each key is issued a serial number of type key_serial_t that is unique for
+ the lifetime of that key. All serial numbers are positive non-zero 32-bit
+ integers.
Userspace programs can use a key's serial numbers as a way to gain access
to it, subject to permission checking.
(*) Each key is of a defined "type". Types must be registered inside the
- kernel by a kernel service (such as a filesystem) before keys of that
- type can be added or used. Userspace programs cannot define new types
- directly.
+ kernel by a kernel service (such as a filesystem) before keys of that type
+ can be added or used. Userspace programs cannot define new types directly.
- Key types are represented in the kernel by struct key_type. This defines
- a number of operations that can be performed on a key of that type.
+ Key types are represented in the kernel by struct key_type. This defines a
+ number of operations that can be performed on a key of that type.
Should a type be removed from the system, all the keys of that type will
be invalidated.
(*) Each key has a description. This should be a printable string. The key
- type provides an operation to perform a match between the description on
- a key and a criterion string.
+ type provides an operation to perform a match between the description on a
+ key and a criterion string.
(*) Each key has an owner user ID, a group ID and a permissions mask. These
are used to control what a process may do to a key from userspace, and
@@ -74,10 +74,10 @@ Each key has a number of attributes:
(*) Each key can be set to expire at a specific time by the key type's
instantiation function. Keys can also be immortal.
- (*) Each key can have a payload. This is a quantity of data that represent
- the actual "key". In the case of a keyring, this is a list of keys to
- which the keyring links; in the case of a user-defined key, it's an
- arbitrary blob of data.
+ (*) Each key can have a payload. This is a quantity of data that represent the
+ actual "key". In the case of a keyring, this is a list of keys to which
+ the keyring links; in the case of a user-defined key, it's an arbitrary
+ blob of data.
Having a payload is not required; and the payload can, in fact, just be a
value stored in the struct key itself.
@@ -92,8 +92,8 @@ Each key has a number of attributes:
(*) Each key can be in one of a number of basic states:
- (*) Uninstantiated. The key exists, but does not have any data
- attached. Keys being requested from userspace will be in this state.
+ (*) Uninstantiated. The key exists, but does not have any data attached.
+ Keys being requested from userspace will be in this state.
(*) Instantiated. This is the normal state. The key is fully formed, and
has data attached.
@@ -140,10 +140,10 @@ The key service provides a number of features besides keys:
clone, fork, vfork or execve occurs. A new keyring is created only when
required.
- The process-specific keyring is replaced with an empty one in the child
- on clone, fork, vfork unless CLONE_THREAD is supplied, in which case it
- is shared. execve also discards the process's process keyring and creates
- a new one.
+ The process-specific keyring is replaced with an empty one in the child on
+ clone, fork, vfork unless CLONE_THREAD is supplied, in which case it is
+ shared. execve also discards the process's process keyring and creates a
+ new one.
The session-specific keyring is persistent across clone, fork, vfork and
execve, even when the latter executes a set-UID or set-GID binary. A
@@ -177,11 +177,11 @@ The key service provides a number of features besides keys:
If a system call that modifies a key or keyring in some way would put the
user over quota, the operation is refused and error EDQUOT is returned.
- (*) There's a system call interface by which userspace programs can create
- and manipulate keys and keyrings.
+ (*) There's a system call interface by which userspace programs can create and
+ manipulate keys and keyrings.
- (*) There's a kernel interface by which services can register types and
- search for keys.
+ (*) There's a kernel interface by which services can register types and search
+ for keys.
(*) There's a way for the a search done from the kernel to call back to
userspace to request a key that can't be found in a process's keyrings.
@@ -194,9 +194,9 @@ The key service provides a number of features besides keys:
KEY ACCESS PERMISSIONS
======================
-Keys have an owner user ID, a group access ID, and a permissions mask. The
-mask has up to eight bits each for user, group and other access. Only five of
-each set of eight bits are defined. These permissions granted are:
+Keys have an owner user ID, a group access ID, and a permissions mask. The mask
+has up to eight bits each for user, group and other access. Only five of each
+set of eight bits are defined. These permissions granted are:
(*) View
@@ -210,8 +210,8 @@ each set of eight bits are defined. These permissions granted are:
(*) Write
- This permits a key's payload to be instantiated or updated, or it allows
- a link to be added to or removed from a keyring.
+ This permits a key's payload to be instantiated or updated, or it allows a
+ link to be added to or removed from a keyring.
(*) Search
@@ -238,8 +238,8 @@ about the status of the key service:
(*) /proc/keys
This lists all the keys on the system, giving information about their
- type, description and permissions. The payload of the key is not
- available this way:
+ type, description and permissions. The payload of the key is not available
+ this way:
SERIAL FLAGS USAGE EXPY PERM UID GID TYPE DESCRIPTION: SUMMARY
00000001 I----- 39 perm 1f0000 0 0 keyring _uid_ses.0: 1/4
@@ -318,21 +318,21 @@ The main syscalls are:
If a key of the same type and description as that proposed already exists
in the keyring, this will try to update it with the given payload, or it
will return error EEXIST if that function is not supported by the key
- type. The process must also have permission to write to the key to be
- able to update it. The new key will have all user permissions granted and
- no group or third party permissions.
+ type. The process must also have permission to write to the key to be able
+ to update it. The new key will have all user permissions granted and no
+ group or third party permissions.
- Otherwise, this will attempt to create a new key of the specified type
- and description, and to instantiate it with the supplied payload and
- attach it to the keyring. In this case, an error will be generated if the
- process does not have permission to write to the keyring.
+ Otherwise, this will attempt to create a new key of the specified type and
+ description, and to instantiate it with the supplied payload and attach it
+ to the keyring. In this case, an error will be generated if the process
+ does not have permission to write to the keyring.
The payload is optional, and the pointer can be NULL if not required by
the type. The payload is plen in size, and plen can be zero for an empty
payload.
- A new keyring can be generated by setting type "keyring", the keyring
- name as the description (or NULL) and setting the payload to NULL.
+ A new keyring can be generated by setting type "keyring", the keyring name
+ as the description (or NULL) and setting the payload to NULL.
User defined keys can be created by specifying type "user". It is
recommended that a user defined key's description by prefixed with a type
@@ -369,9 +369,9 @@ The keyctl syscall functions are:
key_serial_t keyctl(KEYCTL_GET_KEYRING_ID, key_serial_t id,
int create);
- The special key specified by "id" is looked up (with the key being
- created if necessary) and the ID of the key or keyring thus found is
- returned if it exists.
+ The special key specified by "id" is looked up (with the key being created
+ if necessary) and the ID of the key or keyring thus found is returned if
+ it exists.
If the key does not yet exist, the key will be created if "create" is
non-zero; and the error ENOKEY will be returned if "create" is zero.
@@ -402,8 +402,8 @@ The keyctl syscall functions are:
This will try to update the specified key with the given payload, or it
will return error EOPNOTSUPP if that function is not supported by the key
- type. The process must also have permission to write to the key to be
- able to update it.
+ type. The process must also have permission to write to the key to be able
+ to update it.
The payload is of length plen, and may be absent or empty as for
add_key().
@@ -422,8 +422,8 @@ The keyctl syscall functions are:
long keyctl(KEYCTL_CHOWN, key_serial_t key, uid_t uid, gid_t gid);
- This function permits a key's owner and group ID to be changed. Either
- one of uid or gid can be set to -1 to suppress that change.
+ This function permits a key's owner and group ID to be changed. Either one
+ of uid or gid can be set to -1 to suppress that change.
Only the superuser can change a key's owner to something other than the
key's current owner. Similarly, only the superuser can change a key's
@@ -484,12 +484,12 @@ The keyctl syscall functions are:
long keyctl(KEYCTL_LINK, key_serial_t keyring, key_serial_t key);
- This function creates a link from the keyring to the key. The process
- must have write permission on the keyring and must have link permission
- on the key.
+ This function creates a link from the keyring to the key. The process must
+ have write permission on the keyring and must have link permission on the
+ key.
- Should the keyring not be a keyring, error ENOTDIR will result; and if
- the keyring is full, error ENFILE will result.
+ Should the keyring not be a keyring, error ENOTDIR will result; and if the
+ keyring is full, error ENFILE will result.
The link procedure checks the nesting of the keyrings, returning ELOOP if
it appears to deep or EDEADLK if the link would introduce a cycle.
@@ -503,8 +503,8 @@ The keyctl syscall functions are:
specified key, and removes it if found. Subsequent links to that key are
ignored. The process must have write permission on the keyring.
- If the keyring is not a keyring, error ENOTDIR will result; and if the
- key is not present, error ENOENT will be the result.
+ If the keyring is not a keyring, error ENOTDIR will result; and if the key
+ is not present, error ENOENT will be the result.
(*) Search a keyring tree for a key:
@@ -513,9 +513,9 @@ The keyctl syscall functions are:
const char *type, const char *description,
key_serial_t dest_keyring);
- This searches the keyring tree headed by the specified keyring until a
- key is found that matches the type and description criteria. Each keyring
- is checked for keys before recursion into its children occurs.
+ This searches the keyring tree headed by the specified keyring until a key
+ is found that matches the type and description criteria. Each keyring is
+ checked for keys before recursion into its children occurs.
The process must have search permission on the top level keyring, or else
error EACCES will result. Only keyrings that the process has search
@@ -549,8 +549,8 @@ The keyctl syscall functions are:
As much of the data as can be fitted into the buffer will be copied to
userspace if the buffer pointer is not NULL.
- On a successful return, the function will always return the amount of
- data available rather than the amount copied.
+ On a successful return, the function will always return the amount of data
+ available rather than the amount copied.
(*) Instantiate a partially constructed key.
@@ -568,8 +568,8 @@ The keyctl syscall functions are:
it, and the key must be uninstantiated.
If a keyring is specified (non-zero), the key will also be linked into
- that keyring, however all the constraints applying in KEYCTL_LINK apply
- in this case too.
+ that keyring, however all the constraints applying in KEYCTL_LINK apply in
+ this case too.
The payload and plen arguments describe the payload data as for add_key().
@@ -587,8 +587,39 @@ The keyctl syscall functions are:
it, and the key must be uninstantiated.
If a keyring is specified (non-zero), the key will also be linked into
- that keyring, however all the constraints applying in KEYCTL_LINK apply
- in this case too.
+ that keyring, however all the constraints applying in KEYCTL_LINK apply in
+ this case too.
+
+
+ (*) Set the default request-key destination keyring.
+
+ long keyctl(KEYCTL_SET_REQKEY_KEYRING, int reqkey_defl);
+
+ This sets the default keyring to which implicitly requested keys will be
+ attached for this thread. reqkey_defl should be one of these constants:
+
+ CONSTANT VALUE NEW DEFAULT KEYRING
+ ====================================== ====== =======================
+ KEY_REQKEY_DEFL_NO_CHANGE -1 No change
+ KEY_REQKEY_DEFL_DEFAULT 0 Default[1]
+ KEY_REQKEY_DEFL_THREAD_KEYRING 1 Thread keyring
+ KEY_REQKEY_DEFL_PROCESS_KEYRING 2 Process keyring
+ KEY_REQKEY_DEFL_SESSION_KEYRING 3 Session keyring
+ KEY_REQKEY_DEFL_USER_KEYRING 4 User keyring
+ KEY_REQKEY_DEFL_USER_SESSION_KEYRING 5 User session keyring
+ KEY_REQKEY_DEFL_GROUP_KEYRING 6 Group keyring
+
+ The old default will be returned if successful and error EINVAL will be
+ returned if reqkey_defl is not one of the above values.
+
+ The default keyring can be overridden by the keyring indicated to the
+ request_key() system call.
+
+ Note that this setting is inherited across fork/exec.
+
+ [1] The default default is: the thread keyring if there is one, otherwise
+ the process keyring if there is one, otherwise the session keyring if
+ there is one, otherwise the user default session keyring.
===============
@@ -601,17 +632,14 @@ be broken down into two areas: keys and key types.
Dealing with keys is fairly straightforward. Firstly, the kernel service
registers its type, then it searches for a key of that type. It should retain
the key as long as it has need of it, and then it should release it. For a
-filesystem or device file, a search would probably be performed during the
-open call, and the key released upon close. How to deal with conflicting keys
-due to two different users opening the same file is left to the filesystem
-author to solve.
-
-When accessing a key's payload data, key->lock should be at least read locked,
-or else the data may be changed by an update being performed from userspace
-whilst the driver or filesystem is trying to access it. If no update method is
-supplied, then the key's payload may be accessed without holding a lock as
-there is no way to change it, provided it can be guaranteed that the key's
-type definition won't go away.
+filesystem or device file, a search would probably be performed during the open
+call, and the key released upon close. How to deal with conflicting keys due to
+two different users opening the same file is left to the filesystem author to
+solve.
+
+When accessing a key's payload contents, certain precautions must be taken to
+prevent access vs modification races. See the section "Notes on accessing
+payload contents" for more information.
(*) To search for a key, call:
@@ -629,6 +657,9 @@ type definition won't go away.
Should the function fail error ENOKEY, EKEYEXPIRED or EKEYREVOKED will be
returned.
+ If successful, the key will have been attached to the default keyring for
+ implicitly obtained request-key keys, as set by KEYCTL_SET_REQKEY_KEYRING.
+
(*) When it is no longer required, the key should be released using:
@@ -690,6 +721,54 @@ type definition won't go away.
void unregister_key_type(struct key_type *type);
+===================================
+NOTES ON ACCESSING PAYLOAD CONTENTS
+===================================
+
+The simplest payload is just a number in key->payload.value. In this case,
+there's no need to indulge in RCU or locking when accessing the payload.
+
+More complex payload contents must be allocated and a pointer to them set in
+key->payload.data. One of the following ways must be selected to access the
+data:
+
+ (1) Unmodifyable key type.
+
+ If the key type does not have a modify method, then the key's payload can
+ be accessed without any form of locking, provided that it's known to be
+ instantiated (uninstantiated keys cannot be "found").
+
+ (2) The key's semaphore.
+
+ The semaphore could be used to govern access to the payload and to control
+ the payload pointer. It must be write-locked for modifications and would
+ have to be read-locked for general access. The disadvantage of doing this
+ is that the accessor may be required to sleep.
+
+ (3) RCU.
+
+ RCU must be used when the semaphore isn't already held; if the semaphore
+ is held then the contents can't change under you unexpectedly as the
+ semaphore must still be used to serialise modifications to the key. The
+ key management code takes care of this for the key type.
+
+ However, this means using:
+
+ rcu_read_lock() ... rcu_dereference() ... rcu_read_unlock()
+
+ to read the pointer, and:
+
+ rcu_dereference() ... rcu_assign_pointer() ... call_rcu()
+
+ to set the pointer and dispose of the old contents after a grace period.
+ Note that only the key type should ever modify a key's payload.
+
+ Furthermore, an RCU controlled payload must hold a struct rcu_head for the
+ use of call_rcu() and, if the payload is of variable size, the length of
+ the payload. key->datalen cannot be relied upon to be consistent with the
+ payload just dereferenced if the key's semaphore is not held.
+
+
===================
DEFINING A KEY TYPE
===================
@@ -717,15 +796,15 @@ The structure has a number of fields, some of which are mandatory:
int key_payload_reserve(struct key *key, size_t datalen);
- With the revised data length. Error EDQUOT will be returned if this is
- not viable.
+ With the revised data length. Error EDQUOT will be returned if this is not
+ viable.
(*) int (*instantiate)(struct key *key, const void *data, size_t datalen);
This method is called to attach a payload to a key during construction.
- The payload attached need not bear any relation to the data passed to
- this function.
+ The payload attached need not bear any relation to the data passed to this
+ function.
If the amount of data attached to the key differs from the size in
keytype->def_datalen, then key_payload_reserve() should be called.
@@ -734,38 +813,47 @@ The structure has a number of fields, some of which are mandatory:
The fact that KEY_FLAG_INSTANTIATED is not set in key->flags prevents
anything else from gaining access to the key.
- This method may sleep if it wishes.
+ It is safe to sleep in this method.
(*) int (*duplicate)(struct key *key, const struct key *source);
If this type of key can be duplicated, then this method should be
- provided. It is called to copy the payload attached to the source into
- the new key. The data length on the new key will have been updated and
- the quota adjusted already.
+ provided. It is called to copy the payload attached to the source into the
+ new key. The data length on the new key will have been updated and the
+ quota adjusted already.
This method will be called with the source key's semaphore read-locked to
- prevent its payload from being changed. It is safe to sleep here.
+ prevent its payload from being changed, thus RCU constraints need not be
+ applied to the source key.
+
+ This method does not have to lock the destination key in order to attach a
+ payload. The fact that KEY_FLAG_INSTANTIATED is not set in key->flags
+ prevents anything else from gaining access to the key.
+
+ It is safe to sleep in this method.
(*) int (*update)(struct key *key, const void *data, size_t datalen);
- If this type of key can be updated, then this method should be
- provided. It is called to update a key's payload from the blob of data
- provided.
+ If this type of key can be updated, then this method should be provided.
+ It is called to update a key's payload from the blob of data provided.
key_payload_reserve() should be called if the data length might change
- before any changes are actually made. Note that if this succeeds, the
- type is committed to changing the key because it's already been altered,
- so all memory allocation must be done first.
+ before any changes are actually made. Note that if this succeeds, the type
+ is committed to changing the key because it's already been altered, so all
+ memory allocation must be done first.
+
+ The key will have its semaphore write-locked before this method is called,
+ but this only deters other writers; any changes to the key's payload must
+ be made under RCU conditions, and call_rcu() must be used to dispose of
+ the old payload.
- key_payload_reserve() should be called with the key->lock write locked,
- and the changes to the key's attached payload should be made before the
- key is locked.
+ key_payload_reserve() should be called before the changes are made, but
+ after all allocations and other potentially failing function calls are
+ made.
- The key will have its semaphore write-locked before this method is
- called. Any changes to the key should be made with the key's rwlock
- write-locked also. It is safe to sleep here.
+ It is safe to sleep in this method.
(*) int (*match)(const struct key *key, const void *desc);
@@ -782,12 +870,12 @@ The structure has a number of fields, some of which are mandatory:
(*) void (*destroy)(struct key *key);
- This method is optional. It is called to discard the payload data on a
- key when it is being destroyed.
+ This method is optional. It is called to discard the payload data on a key
+ when it is being destroyed.
- This method does not need to lock the key; it can consider the key as
- being inaccessible. Note that the key's type may have changed before this
- function is called.
+ This method does not need to lock the key to access the payload; it can
+ consider the key as being inaccessible at this time. Note that the key's
+ type may have been changed before this function is called.
It is not safe to sleep in this method; the caller may hold spinlocks.
@@ -797,26 +885,31 @@ The structure has a number of fields, some of which are mandatory:
This method is optional. It is called during /proc/keys reading to
summarise a key's description and payload in text form.
- This method will be called with the key's rwlock read-locked. This will
- prevent the key's payload and state changing; also the description should
- not change. This also means it is not safe to sleep in this method.
+ This method will be called with the RCU read lock held. rcu_dereference()
+ should be used to read the payload pointer if the payload is to be
+ accessed. key->datalen cannot be trusted to stay consistent with the
+ contents of the payload.
+
+ The description will not change, though the key's state may.
+
+ It is not safe to sleep in this method; the RCU read lock is held by the
+ caller.
(*) long (*read)(const struct key *key, char __user *buffer, size_t buflen);
This method is optional. It is called by KEYCTL_READ to translate the
- key's payload into something a blob of data for userspace to deal
- with. Ideally, the blob should be in the same format as that passed in to
- the instantiate and update methods.
+ key's payload into something a blob of data for userspace to deal with.
+ Ideally, the blob should be in the same format as that passed in to the
+ instantiate and update methods.
If successful, the blob size that could be produced should be returned
rather than the size copied.
- This method will be called with the key's semaphore read-locked. This
- will prevent the key's payload changing. It is not necessary to also
- read-lock key->lock when accessing the key's payload. It is safe to sleep
- in this method, such as might happen when the userspace buffer is
- accessed.
+ This method will be called with the key's semaphore read-locked. This will
+ prevent the key's payload changing. It is not necessary to use RCU locking
+ when accessing the key's payload. It is safe to sleep in this method, such
+ as might happen when the userspace buffer is accessed.
============================
@@ -853,8 +946,8 @@ If it returns with the key remaining in the unconstructed state, the key will
be marked as being negative, it will be added to the session keyring, and an
error will be returned to the key requestor.
-Supplementary information may be provided from whoever or whatever invoked
-this service. This will be passed as the <callout_info> parameter. If no such
+Supplementary information may be provided from whoever or whatever invoked this
+service. This will be passed as the <callout_info> parameter. If no such
information was made available, then "-" will be passed as this parameter
instead.
diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX
index 834993d2673..5b01d5cc4e9 100644
--- a/Documentation/networking/00-INDEX
+++ b/Documentation/networking/00-INDEX
@@ -114,9 +114,7 @@ tuntap.txt
vortex.txt
- info on using 3Com Vortex (3c590, 3c592, 3c595, 3c597) Ethernet cards.
wan-router.txt
- - Wan router documentation
-wanpipe.txt
- - WANPIPE(tm) Multiprotocol WAN Driver for Linux WAN Router
+ - WAN router documentation
wavelan.txt
- AT&T GIS (nee NCR) WaveLAN card: An Ethernet-like radio transceiver
x25.txt
diff --git a/Documentation/networking/generic-hdlc.txt b/Documentation/networking/generic-hdlc.txt
index 7d1dc6b884f..31bc8b759b7 100644
--- a/Documentation/networking/generic-hdlc.txt
+++ b/Documentation/networking/generic-hdlc.txt
@@ -1,21 +1,21 @@
Generic HDLC layer
Krzysztof Halasa <khc@pm.waw.pl>
-January, 2003
Generic HDLC layer currently supports:
-- Frame Relay (ANSI, CCITT and no LMI), with ARP support (no InARP).
- Normal (routed) and Ethernet-bridged (Ethernet device emulation)
- interfaces can share a single PVC.
-- raw HDLC - either IP (IPv4) interface or Ethernet device emulation.
-- Cisco HDLC,
-- PPP (uses syncppp.c),
-- X.25 (uses X.25 routines).
-
-There are hardware drivers for the following cards:
-- C101 by Moxa Technologies Co., Ltd.
-- RISCom/N2 by SDL Communications Inc.
-- and others, some not in the official kernel.
+1. Frame Relay (ANSI, CCITT, Cisco and no LMI).
+ - Normal (routed) and Ethernet-bridged (Ethernet device emulation)
+ interfaces can share a single PVC.
+ - ARP support (no InARP support in the kernel - there is an
+ experimental InARP user-space daemon available on:
+ http://www.kernel.org/pub/linux/utils/net/hdlc/).
+2. raw HDLC - either IP (IPv4) interface or Ethernet device emulation.
+3. Cisco HDLC.
+4. PPP (uses syncppp.c).
+5. X.25 (uses X.25 routines).
+
+Generic HDLC is a protocol driver only - it needs a low-level driver
+for your particular hardware.
Ethernet device emulation (using HDLC or Frame-Relay PVC) is compatible
with IEEE 802.1Q (VLANs) and 802.1D (Ethernet bridging).
@@ -24,7 +24,7 @@ with IEEE 802.1Q (VLANs) and 802.1D (Ethernet bridging).
Make sure the hdlc.o and the hardware driver are loaded. It should
create a number of "hdlc" (hdlc0 etc) network devices, one for each
WAN port. You'll need the "sethdlc" utility, get it from:
- http://hq.pm.waw.pl/hdlc/
+ http://www.kernel.org/pub/linux/utils/net/hdlc/
Compile sethdlc.c utility:
gcc -O2 -Wall -o sethdlc sethdlc.c
@@ -52,12 +52,12 @@ Setting interface:
* v35 | rs232 | x21 | t1 | e1 - sets physical interface for a given port
if the card has software-selectable interfaces
loopback - activate hardware loopback (for testing only)
-* clock ext - external clock (uses DTE RX and TX clock)
-* clock int - internal clock (provides clock signal on DCE clock output)
-* clock txint - TX internal, RX external (provides TX clock on DCE output)
-* clock txfromrx - TX clock derived from RX clock (TX clock on DCE output)
-* rate - sets clock rate in bps (not required for external clock or
- for txfromrx)
+* clock ext - both RX clock and TX clock external
+* clock int - both RX clock and TX clock internal
+* clock txint - RX clock external, TX clock internal
+* clock txfromrx - RX clock external, TX clock derived from RX clock
+* rate - sets clock rate in bps (for "int" or "txint" clock only)
+
Setting protocol:
@@ -79,7 +79,7 @@ Setting protocol:
* x25 - sets X.25 mode
* fr - Frame Relay mode
- lmi ansi / ccitt / none - LMI (link management) type
+ lmi ansi / ccitt / cisco / none - LMI (link management) type
dce - Frame Relay DCE (network) side LMI instead of default DTE (user).
It has nothing to do with clocks!
t391 - link integrity verification polling timer (in seconds) - user
@@ -119,13 +119,14 @@ or
-If you have a problem with N2 or C101 card, you can issue the "private"
-command to see port's packet descriptor rings (in kernel logs):
+If you have a problem with N2, C101 or PLX200SYN card, you can issue the
+"private" command to see port's packet descriptor rings (in kernel logs):
sethdlc hdlc0 private
-The hardware driver has to be build with CONFIG_HDLC_DEBUG_RINGS.
+The hardware driver has to be build with #define DEBUG_RINGS.
Attaching this info to bug reports would be helpful. Anyway, let me know
if you have problems using this.
-For patches and other info look at http://hq.pm.waw.pl/hdlc/
+For patches and other info look at:
+<http://www.kernel.org/pub/linux/utils/net/hdlc/>.
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index a2c893a7475..ab65714d95f 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -304,57 +304,6 @@ tcp_low_latency - BOOLEAN
changed would be a Beowulf compute cluster.
Default: 0
-tcp_westwood - BOOLEAN
- Enable TCP Westwood+ congestion control algorithm.
- TCP Westwood+ is a sender-side only modification of the TCP Reno
- protocol stack that optimizes the performance of TCP congestion
- control. It is based on end-to-end bandwidth estimation to set
- congestion window and slow start threshold after a congestion
- episode. Using this estimation, TCP Westwood+ adaptively sets a
- slow start threshold and a congestion window which takes into
- account the bandwidth used at the time congestion is experienced.
- TCP Westwood+ significantly increases fairness wrt TCP Reno in
- wired networks and throughput over wireless links.
- Default: 0
-
-tcp_vegas_cong_avoid - BOOLEAN
- Enable TCP Vegas congestion avoidance algorithm.
- TCP Vegas is a sender-side only change to TCP that anticipates
- the onset of congestion by estimating the bandwidth. TCP Vegas
- adjusts the sending rate by modifying the congestion
- window. TCP Vegas should provide less packet loss, but it is
- not as aggressive as TCP Reno.
- Default:0
-
-tcp_bic - BOOLEAN
- Enable BIC TCP congestion control algorithm.
- BIC-TCP is a sender-side only change that ensures a linear RTT
- fairness under large windows while offering both scalability and
- bounded TCP-friendliness. The protocol combines two schemes
- called additive increase and binary search increase. When the
- congestion window is large, additive increase with a large
- increment ensures linear RTT fairness as well as good
- scalability. Under small congestion windows, binary search
- increase provides TCP friendliness.
- Default: 0
-
-tcp_bic_low_window - INTEGER
- Sets the threshold window (in packets) where BIC TCP starts to
- adjust the congestion window. Below this threshold BIC TCP behaves
- the same as the default TCP Reno.
- Default: 14
-
-tcp_bic_fast_convergence - BOOLEAN
- Forces BIC TCP to more quickly respond to changes in congestion
- window. Allows two flows sharing the same connection to converge
- more rapidly.
- Default: 1
-
-tcp_default_win_scale - INTEGER
- Sets the minimum window scale TCP will negotiate for on all
- conections.
- Default: 7
-
tcp_tso_win_divisor - INTEGER
This allows control over what percentage of the congestion window
can be consumed by a single TSO frame.
@@ -368,6 +317,11 @@ tcp_frto - BOOLEAN
where packet loss is typically due to random radio interference
rather than intermediate router congestion.
+tcp_congestion_control - STRING
+ Set the congestion control algorithm to be used for new
+ connections. The algorithm "reno" is always available, but
+ additional choices may be available based on kernel configuration.
+
somaxconn - INTEGER
Limit of socket listen() backlog, known in userspace as SOMAXCONN.
Defaults to 128. See also tcp_max_syn_backlog for additional tuning
diff --git a/Documentation/networking/multicast.txt b/Documentation/networking/multicast.txt
index 5049a64313d..b06c8c69266 100644
--- a/Documentation/networking/multicast.txt
+++ b/Documentation/networking/multicast.txt
@@ -47,7 +47,6 @@ ni52 <------------------ Buggy ------------------>
ni65 YES YES YES Software(#)
seeq NO NO NO N/A
sgiseek <------------------ Buggy ------------------>
-sk_g16 NO NO YES N/A
smc-ultra YES YES YES Hardware
sunlance YES YES YES Hardware
tulip YES YES YES Hardware
diff --git a/Documentation/networking/net-modules.txt b/Documentation/networking/net-modules.txt
index 3830a83513d..0b27863f155 100644
--- a/Documentation/networking/net-modules.txt
+++ b/Documentation/networking/net-modules.txt
@@ -284,9 +284,6 @@ ppp.c:
seeq8005.c: *Not modularized*
(Probes ports: 0x300, 0x320, 0x340, 0x360)
-sk_g16.c: *Not modularized*
- (Probes ports: 0x100, 0x180, 0x208, 0x220m 0x288, 0x320, 0x328, 0x390)
-
skeleton.c: *Skeleton*
slhc.c:
diff --git a/Documentation/networking/tcp.txt b/Documentation/networking/tcp.txt
index 71749007091..0fa30042557 100644
--- a/Documentation/networking/tcp.txt
+++ b/Documentation/networking/tcp.txt
@@ -1,5 +1,72 @@
-How the new TCP output machine [nyi] works.
+TCP protocol
+============
+
+Last updated: 21 June 2005
+
+Contents
+========
+
+- Congestion control
+- How the new TCP output machine [nyi] works
+
+Congestion control
+==================
+
+The following variables are used in the tcp_sock for congestion control:
+snd_cwnd The size of the congestion window
+snd_ssthresh Slow start threshold. We are in slow start if
+ snd_cwnd is less than this.
+snd_cwnd_cnt A counter used to slow down the rate of increase
+ once we exceed slow start threshold.
+snd_cwnd_clamp This is the maximum size that snd_cwnd can grow to.
+snd_cwnd_stamp Timestamp for when congestion window last validated.
+snd_cwnd_used Used as a highwater mark for how much of the
+ congestion window is in use. It is used to adjust
+ snd_cwnd down when the link is limited by the
+ application rather than the network.
+
+As of 2.6.13, Linux supports pluggable congestion control algorithms.
+A congestion control mechanism can be registered through functions in
+tcp_cong.c. The functions used by the congestion control mechanism are
+registered via passing a tcp_congestion_ops struct to
+tcp_register_congestion_control. As a minimum name, ssthresh,
+cong_avoid, min_cwnd must be valid.
+Private data for a congestion control mechanism is stored in tp->ca_priv.
+tcp_ca(tp) returns a pointer to this space. This is preallocated space - it
+is important to check the size of your private data will fit this space, or
+alternatively space could be allocated elsewhere and a pointer to it could
+be stored here.
+
+There are three kinds of congestion control algorithms currently: The
+simplest ones are derived from TCP reno (highspeed, scalable) and just
+provide an alternative the congestion window calculation. More complex
+ones like BIC try to look at other events to provide better
+heuristics. There are also round trip time based algorithms like
+Vegas and Westwood+.
+
+Good TCP congestion control is a complex problem because the algorithm
+needs to maintain fairness and performance. Please review current
+research and RFC's before developing new modules.
+
+The method that is used to determine which congestion control mechanism is
+determined by the setting of the sysctl net.ipv4.tcp_congestion_control.
+The default congestion control will be the last one registered (LIFO);
+so if you built everything as modules. the default will be reno. If you
+build with the default's from Kconfig, then BIC will be builtin (not a module)
+and it will end up the default.
+
+If you really want a particular default value then you will need
+to set it with the sysctl. If you use a sysctl, the module will be autoloaded
+if needed and you will get the expected protocol. If you ask for an
+unknown congestion method, then the sysctl attempt will fail.
+
+If you remove a tcp congestion control module, then you will get the next
+available one. Since reno can not be built as a module, and can not be
+deleted, it will always be available.
+
+How the new TCP output machine [nyi] works.
+===========================================
Data is kept on a single queue. The skb->users flag tells us if the frame is
one that has been queued already. To add a frame we throw it on the end. Ack
diff --git a/Documentation/networking/vortex.txt b/Documentation/networking/vortex.txt
index fa12a9e4abd..80e1cb19609 100644
--- a/Documentation/networking/vortex.txt
+++ b/Documentation/networking/vortex.txt
@@ -12,7 +12,7 @@ Don is no longer the prime maintainer of this version of the driver.
Please report problems to one or more of:
Andrew Morton <andrewm@uow.edu.au>
- Netdev mailing list <netdev@oss.sgi.com>
+ Netdev mailing list <netdev@vger.kernel.org>
Linux kernel mailing list <linux-kernel@vger.kernel.org>
Please note the 'Reporting and Diagnosing Problems' section at the end
diff --git a/Documentation/networking/wanpipe.txt b/Documentation/networking/wanpipe.txt
deleted file mode 100644
index aea20cd2a56..00000000000
--- a/Documentation/networking/wanpipe.txt
+++ /dev/null
@@ -1,622 +0,0 @@
-------------------------------------------------------------------------------
-Linux WAN Router Utilities Package
-------------------------------------------------------------------------------
-Version 2.2.1
-Mar 28, 2001
-Author: Nenad Corbic <ncorbic@sangoma.com>
-Copyright (c) 1995-2001 Sangoma Technologies Inc.
-------------------------------------------------------------------------------
-
-INTRODUCTION
-
-Wide Area Networks (WANs) are used to interconnect Local Area Networks (LANs)
-and/or stand-alone hosts over vast distances with data transfer rates
-significantly higher than those achievable with commonly used dial-up
-connections.
-
-Usually an external device called `WAN router' sitting on your local network
-or connected to your machine's serial port provides physical connection to
-WAN. Although router's job may be as simple as taking your local network
-traffic, converting it to WAN format and piping it through the WAN link, these
-devices are notoriously expensive, with prices as much as 2 - 5 times higher
-then the price of a typical PC box.
-
-Alternatively, considering robustness and multitasking capabilities of Linux,
-an internal router can be built (most routers use some sort of stripped down
-Unix-like operating system anyway). With a number of relatively inexpensive WAN
-interface cards available on the market, a perfectly usable router can be
-built for less than half a price of an external router. Yet a Linux box
-acting as a router can still be used for other purposes, such as fire-walling,
-running FTP, WWW or DNS server, etc.
-
-This kernel module introduces the notion of a WAN Link Driver (WLD) to Linux
-operating system and provides generic hardware-independent services for such
-drivers. Why can existing Linux network device interface not be used for
-this purpose? Well, it can. However, there are a few key differences between
-a typical network interface (e.g. Ethernet) and a WAN link.
-
-Many WAN protocols, such as X.25 and frame relay, allow for multiple logical
-connections (known as `virtual circuits' in X.25 terminology) over a single
-physical link. Each such virtual circuit may (and almost always does) lead
-to a different geographical location and, therefore, different network. As a
-result, it is the virtual circuit, not the physical link, that represents a
-route and, therefore, a network interface in Linux terms.
-
-To further complicate things, virtual circuits are usually volatile in nature
-(excluding so called `permanent' virtual circuits or PVCs). With almost no
-time required to set up and tear down a virtual circuit, it is highly desirable
-to implement on-demand connections in order to minimize network charges. So
-unlike a typical network driver, the WAN driver must be able to handle multiple
-network interfaces and cope as multiple virtual circuits come into existence
-and go away dynamically.
-
-Last, but not least, WAN configuration is much more complex than that of say
-Ethernet and may well amount to several dozens of parameters. Some of them
-are "link-wide" while others are virtual circuit-specific. The same holds
-true for WAN statistics which is by far more extensive and extremely useful
-when troubleshooting WAN connections. Extending the ifconfig utility to suit
-these needs may be possible, but does not seem quite reasonable. Therefore, a
-WAN configuration utility and corresponding application programmer's interface
-is needed for this purpose.
-
-Most of these problems are taken care of by this module. Its goal is to
-provide a user with more-or-less standard look and feel for all WAN devices and
-assist a WAN device driver writer by providing common services, such as:
-
- o User-level interface via /proc file system
- o Centralized configuration
- o Device management (setup, shutdown, etc.)
- o Network interface management (dynamic creation/destruction)
- o Protocol encapsulation/decapsulation
-
-To ba able to use the Linux WAN Router you will also need a WAN Tools package
-available from
-
- ftp.sangoma.com/pub/linux/current_wanpipe/wanpipe-X.Y.Z.tgz
-
-where vX.Y.Z represent the wanpipe version number.
-
-For technical questions and/or comments please e-mail to ncorbic@sangoma.com.
-For general inquiries please contact Sangoma Technologies Inc. by
-
- Hotline: 1-800-388-2475 (USA and Canada, toll free)
- Phone: (905) 474-1990 ext: 106
- Fax: (905) 474-9223
- E-mail: dm@sangoma.com (David Mandelstam)
- WWW: http://www.sangoma.com
-
-
-INSTALLATION
-
-Please read the WanpipeForLinux.pdf manual on how to
-install the WANPIPE tools and drivers properly.
-
-
-After installing wanpipe package: /usr/local/wanrouter/doc.
-On the ftp.sangoma.com : /linux/current_wanpipe/doc
-
-
-COPYRIGHT AND LICENSING INFORMATION
-
-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; if not, write to the Free Software Foundation, Inc., 675 Mass
-Ave, Cambridge, MA 02139, USA.
-
-
-
-ACKNOWLEDGEMENTS
-
-This product is based on the WANPIPE(tm) Multiprotocol WAN Router developed
-by Sangoma Technologies Inc. for Linux 2.0.x and 2.2.x. Success of the WANPIPE
-together with the next major release of Linux kernel in summer 1996 commanded
-adequate changes to the WANPIPE code to take full advantage of new Linux
-features.
-
-Instead of continuing developing proprietary interface tied to Sangoma WAN
-cards, we decided to separate all hardware-independent code into a separate
-module and defined two levels of interfaces - one for user-level applications
-and another for kernel-level WAN drivers. WANPIPE is now implemented as a
-WAN driver compliant with the WAN Link Driver interface. Also a general
-purpose WAN configuration utility and a set of shell scripts was developed to
-support WAN router at the user level.
-
-Many useful ideas concerning hardware-independent interface implementation
-were given by Mike McLagan <mike.mclagan@linux.org> and his implementation
-of the Frame Relay router and drivers for Sangoma cards (dlci/sdla).
-
-With the new implementation of the APIs being incorporated into the WANPIPE,
-a special thank goes to Alan Cox in providing insight into BSD sockets.
-
-Special thanks to all the WANPIPE users who performed field-testing, reported
-bugs and made valuable comments and suggestions that help us to improve this
-product.
-
-
-
-NEW IN THIS RELEASE
-
- o Updated the WANCFG utility
- Calls the pppconfig to configure the PPPD
- for async connections.
-
- o Added the PPPCONFIG utility
- Used to configure the PPPD dameon for the
- WANPIPE Async PPP and standard serial port.
- The wancfg calls the pppconfig to configure
- the pppd.
-
- o Fixed the PCI autodetect feature.
- The SLOT 0 was used as an autodetect option
- however, some high end PC's slot numbers start
- from 0.
-
- o This release has been tested with the new backupd
- daemon release.
-
-
-PRODUCT COMPONENTS AND RELATED FILES
-
-/etc: (or user defined)
- wanpipe1.conf default router configuration file
-
-/lib/modules/X.Y.Z/misc:
- wanrouter.o router kernel loadable module
- af_wanpipe.o wanpipe api socket module
-
-/lib/modules/X.Y.Z/net:
- sdladrv.o Sangoma SDLA support module
- wanpipe.o Sangoma WANPIPE(tm) driver module
-
-/proc/net/wanrouter
- Config reads current router configuration
- Status reads current router status
- {name} reads WAN driver statistics
-
-/usr/sbin:
- wanrouter wanrouter start-up script
- wanconfig wanrouter configuration utility
- sdladump WANPIPE adapter memory dump utility
- fpipemon Monitor for Frame Relay
- cpipemon Monitor for Cisco HDLC
- ppipemon Monitor for PPP
- xpipemon Monitor for X25
- wpkbdmon WANPIPE keyboard led monitor/debugger
-
-/usr/local/wanrouter:
- README this file
- COPYING GNU General Public License
- Setup installation script
- Filelist distribution definition file
- wanrouter.rc meta-configuration file
- (used by the Setup and wanrouter script)
-
-/usr/local/wanrouter/doc:
- wanpipeForLinux.pdf WAN Router User's Manual
-
-/usr/local/wanrouter/patches:
- wanrouter-v2213.gz patch for Linux kernels 2.2.11 up to 2.2.13.
- wanrouter-v2214.gz patch for Linux kernel 2.2.14.
- wanrouter-v2215.gz patch for Linux kernels 2.2.15 to 2.2.17.
- wanrouter-v2218.gz patch for Linux kernels 2.2.18 and up.
- wanrouter-v240.gz patch for Linux kernel 2.4.0.
- wanrouter-v242.gz patch for Linux kernel 2.4.2 and up.
- wanrouter-v2034.gz patch for Linux kernel 2.0.34
- wanrouter-v2036.gz patch for Linux kernel 2.0.36 and up.
-
-/usr/local/wanrouter/patches/kdrivers:
- Sources of the latest WANPIPE device drivers.
- These are used to UPGRADE the linux kernel to the newest
- version if the kernel source has already been pathced with
- WANPIPE drivers.
-
-/usr/local/wanrouter/samples:
- interface sample interface configuration file
- wanpipe1.cpri CHDLC primary port
- wanpipe2.csec CHDLC secondary port
- wanpipe1.fr Frame Relay protocol
- wanpipe1.ppp PPP protocol )
- wanpipe1.asy CHDLC ASYNC protocol
- wanpipe1.x25 X25 protocol
- wanpipe1.stty Sync TTY driver (Used by Kernel PPPD daemon)
- wanpipe1.atty Async TTY driver (Used by Kernel PPPD daemon)
- wanrouter.rc sample meta-configuration file
-
-/usr/local/wanrouter/util:
- * wan-tools utilities source code
-
-/usr/local/wanrouter/api/x25:
- * x25 api sample programs.
-/usr/local/wanrouter/api/chdlc:
- * chdlc api sample programs.
-/usr/local/wanrouter/api/fr:
- * fr api sample programs.
-/usr/local/wanrouter/config/wancfg:
- wancfg WANPIPE GUI configuration program.
- Creates wanpipe#.conf files.
-/usr/local/wanrouter/config/cfgft1:
- cfgft1 GUI CSU/DSU configuration program.
-
-/usr/include/linux:
- wanrouter.h router API definitions
- wanpipe.h WANPIPE API definitions
- sdladrv.h SDLA support module API definitions
- sdlasfm.h SDLA firmware module definitions
- if_wanpipe.h WANPIPE Socket definitions
- if_wanpipe_common.h WANPIPE Socket/Driver common definitions.
- sdlapci.h WANPIPE PCI definitions
-
-
-/usr/src/linux/net/wanrouter:
- * wanrouter source code
-
-/var/log:
- wanrouter wanrouter start-up log (created by the Setup script)
-
-/var/lock: (or /var/lock/subsys for RedHat)
- wanrouter wanrouter lock file (created by the Setup script)
-
-/usr/local/wanrouter/firmware:
- fr514.sfm Frame relay firmware for Sangoma S508/S514 card
- cdual514.sfm Dual Port Cisco HDLC firmware for Sangoma S508/S514 card
- ppp514.sfm PPP Firmware for Sangoma S508 and S514 cards
- x25_508.sfm X25 Firmware for Sangoma S508 card.
-
-
-REVISION HISTORY
-
-1.0.0 December 31, 1996 Initial version
-
-1.0.1 January 30, 1997 Status and statistics can be read via /proc
- filesystem entries.
-
-1.0.2 April 30, 1997 Added UDP management via monitors.
-
-1.0.3 June 3, 1997 UDP management for multiple boards using Frame
- Relay and PPP
- Enabled continuous transmission of Configure
- Request Packet for PPP (for 508 only)
- Connection Timeout for PPP changed from 900 to 0
- Flow Control Problem fixed for Frame Relay
-
-1.0.4 July 10, 1997 S508/FT1 monitoring capability in fpipemon and
- ppipemon utilities.
- Configurable TTL for UDP packets.
- Multicast and Broadcast IP source addresses are
- silently discarded.
-
-1.0.5 July 28, 1997 Configurable T391,T392,N391,N392,N393 for Frame
- Relay in router.conf.
- Configurable Memory Address through router.conf
- for Frame Relay, PPP and X.25. (commenting this
- out enables auto-detection).
- Fixed freeing up received buffers using kfree()
- for Frame Relay and X.25.
- Protect sdla_peek() by calling save_flags(),
- cli() and restore_flags().
- Changed number of Trace elements from 32 to 20
- Added DLCI specific data monitoring in FPIPEMON.
-2.0.0 Nov 07, 1997 Implemented protection of RACE conditions by
- critical flags for FRAME RELAY and PPP.
- DLCI List interrupt mode implemented.
- IPX support in FRAME RELAY and PPP.
- IPX Server Support (MARS)
- More driver specific stats included in FPIPEMON
- and PIPEMON.
-
-2.0.1 Nov 28, 1997 Bug Fixes for version 2.0.0.
- Protection of "enable_irq()" while
- "disable_irq()" has been enabled from any other
- routine (for Frame Relay, PPP and X25).
- Added additional Stats for Fpipemon and Ppipemon
- Improved Load Sharing for multiple boards
-
-2.0.2 Dec 09, 1997 Support for PAP and CHAP for ppp has been
- implemented.
-
-2.0.3 Aug 15, 1998 New release supporting Cisco HDLC, CIR for Frame
- relay, Dynamic IP assignment for PPP and Inverse
- Arp support for Frame-relay. Man Pages are
- included for better support and a new utility
- for configuring FT1 cards.
-
-2.0.4 Dec 09, 1998 Dual Port support for Cisco HDLC.
- Support for HDLC (LAPB) API.
- Supports BiSync Streaming code for S502E
- and S503 cards.
- Support for Streaming HDLC API.
- Provides a BSD socket interface for
- creating applications using BiSync
- streaming.
-
-2.0.5 Aug 04, 1999 CHDLC initializatin bug fix.
- PPP interrupt driven driver:
- Fix to the PPP line hangup problem.
- New PPP firmware
- Added comments to the startup SYSTEM ERROR messages
- Xpipemon debugging application for the X25 protocol
- New USER_MANUAL.txt
- Fixed the odd boundary 4byte writes to the board.
- BiSync Streaming code has been taken out.
- Available as a patch.
- Streaming HDLC API has been taken out.
- Available as a patch.
-
-2.0.6 Aug 17, 1999 Increased debugging in statup scripts
- Fixed insallation bugs from 2.0.5
- Kernel patch works for both 2.2.10 and 2.2.11 kernels.
- There is no functional difference between the two packages
-
-2.0.7 Aug 26, 1999 o Merged X25API code into WANPIPE.
- o Fixed a memeory leak for X25API
- o Updated the X25API code for 2.2.X kernels.
- o Improved NEM handling.
-
-2.1.0 Oct 25, 1999 o New code for S514 PCI Card
- o New CHDLC and Frame Relay drivers
- o PPP and X25 are not supported in this release
-
-2.1.1 Nov 30, 1999 o PPP support for S514 PCI Cards
-
-2.1.3 Apr 06, 2000 o Socket based x25api
- o Socket based chdlc api
- o Socket based fr api
- o Dual Port Receive only CHDLC support.
- o Asynchronous CHDLC support (Secondary Port)
- o cfgft1 GUI csu/dsu configurator
- o wancfg GUI configuration file
- configurator.
- o Architectual directory changes.
-
-beta-2.1.4 Jul 2000 o Dynamic interface configuration:
- Network interfaces reflect the state
- of protocol layer. If the protocol becomes
- disconnected, driver will bring down
- the interface. Once the protocol reconnects
- the interface will be brought up.
-
- Note: This option is turned off by default.
-
- o Dynamic wanrouter setup using 'wanconfig':
- wanconfig utility can be used to
- shutdown,restart,start or reconfigure
- a virtual circuit dynamically.
-
- Frame Relay: Each DLCI can be:
- created,stopped,restarted and reconfigured
- dynamically using wanconfig.
-
- ex: wanconfig card wanpipe1 dev wp1_fr16 up
-
- o Wanrouter startup via command line arguments:
- wanconfig also supports wanrouter startup via command line
- arguments. Thus, there is no need to create a wanpipe#.conf
- configuration file.
-
- o Socket based x25api update/bug fixes.
- Added support for LCN numbers greater than 255.
- Option to pass up modem messages.
- Provided a PCI IRQ check, so a single S514
- card is guaranteed to have a non-sharing interrupt.
-
- o Fixes to the wancfg utility.
- o New FT1 debugging support via *pipemon utilities.
- o Frame Relay ARP support Enabled.
-
-beta3-2.1.4 Jul 2000 o X25 M_BIT Problem fix.
- o Added the Multi-Port PPP
- Updated utilites for the Multi-Port PPP.
-
-2.1.4 Aut 2000
- o In X25API:
- Maximum packet an application can send
- to the driver has been extended to 4096 bytes.
-
- Fixed the x25 startup bug. Enable
- communications only after all interfaces
- come up. HIGH SVC/PVC is used to calculate
- the number of channels.
- Enable protocol only after all interfaces
- are enabled.
-
- o Added an extra state to the FT1 config, kernel module.
- o Updated the pipemon debuggers.
-
- o Blocked the Multi-Port PPP from running on kernels
- 2.2.16 or greater, due to syncppp kernel module
- change.
-
-beta1-2.1.5 Nov 15 2000
- o Fixed the MulitPort PPP Support for kernels 2.2.16 and above.
- 2.2.X kernels only
-
- o Secured the driver UDP debugging calls
- - All illegal netowrk debugging calls are reported to
- the log.
- - Defined a set of allowed commands, all other denied.
-
- o Cpipemon
- - Added set FT1 commands to the cpipemon. Thus CSU/DSU
- configuraiton can be performed using cpipemon.
- All systems that cannot run cfgft1 GUI utility should
- use cpipemon to configure the on board CSU/DSU.
-
-
- o Keyboard Led Monitor/Debugger
- - A new utilty /usr/sbin/wpkbdmon uses keyboard leds
- to convey operatinal statistic information of the
- Sangoma WANPIPE cards.
- NUM_LOCK = Line State (On=connected, Off=disconnected)
- CAPS_LOCK = Tx data (On=transmitting, Off=no tx data)
- SCROLL_LOCK = Rx data (On=receiving, Off=no rx data
-
- o Hardware probe on module load and dynamic device allocation
- - During WANPIPE module load, all Sangoma cards are probed
- and found information is printed in the /var/log/messages.
- - If no cards are found, the module load fails.
- - Appropriate number of devices are dynamically loaded
- based on the number of Sangoma cards found.
-
- Note: The kernel configuraiton option
- CONFIG_WANPIPE_CARDS has been taken out.
-
- o Fixed the Frame Relay and Chdlc network interfaces so they are
- compatible with libpcap libraries. Meaning, tcpdump, snort,
- ethereal, and all other packet sniffers and debuggers work on
- all WANPIPE netowrk interfaces.
- - Set the network interface encoding type to ARPHRD_PPP.
- This tell the sniffers that data obtained from the
- network interface is in pure IP format.
- Fix for 2.2.X kernels only.
-
- o True interface encoding option for Frame Relay and CHDLC
- - The above fix sets the network interface encoding
- type to ARPHRD_PPP, however some customers use
- the encoding interface type to determine the
- protocol running. Therefore, the TURE ENCODING
- option will set the interface type back to the
- original value.
-
- NOTE: If this option is used with Frame Relay and CHDLC
- libpcap library support will be broken.
- i.e. tcpdump will not work.
- Fix for 2.2.x Kernels only.
-
- o Ethernet Bridgind over Frame Relay
- - The Frame Relay bridging has been developed by
- Kristian Hoffmann and Mark Wells.
- - The Linux kernel bridge is used to send ethernet
- data over the frame relay links.
- For 2.2.X Kernels only.
-
- o Added extensive 2.0.X support. Most new features of
- 2.1.5 for protocols Frame Relay, PPP and CHDLC are
- supported under 2.0.X kernels.
-
-beta1-2.2.0 Dec 30 2000
- o Updated drivers for 2.4.X kernels.
- o Updated drivers for SMP support.
- o X25API is now able to share PCI interrupts.
- o Took out a general polling routine that was used
- only by X25API.
- o Added appropriate locks to the dynamic reconfiguration
- code.
- o Fixed a bug in the keyboard debug monitor.
-
-beta2-2.2.0 Jan 8 2001
- o Patches for 2.4.0 kernel
- o Patches for 2.2.18 kernel
- o Minor updates to PPP and CHLDC drivers.
- Note: No functinal difference.
-
-beta3-2.2.9 Jan 10 2001
- o I missed the 2.2.18 kernel patches in beta2-2.2.0
- release. They are included in this release.
-
-Stable Release
-2.2.0 Feb 01 2001
- o Bug fix in wancfg GUI configurator.
- The edit function didn't work properly.
-
-
-bata1-2.2.1 Feb 09 2001
- o WANPIPE TTY Driver emulation.
- Two modes of operation Sync and Async.
- Sync: Using the PPPD daemon, kernel SyncPPP layer
- and the Wanpipe sync TTY driver: a PPP protocol
- connection can be established via Sangoma adapter, over
- a T1 leased line.
-
- The 2.4.0 kernel PPP layer supports MULTILINK
- protocol, that can be used to bundle any number of Sangoma
- adapters (T1 lines) into one, under a single IP address.
- Thus, efficiently obtaining multiple T1 throughput.
-
- NOTE: The remote side must also implement MULTILINK PPP
- protocol.
-
- Async:Using the PPPD daemon, kernel AsyncPPP layer
- and the WANPIPE async TTY driver: a PPP protocol
- connection can be established via Sangoma adapter and
- a modem, over a telephone line.
-
- Thus, the WANPIPE async TTY driver simulates a serial
- TTY driver that would normally be used to interface the
- MODEM to the linux kernel.
-
- o WANPIPE PPP Backup Utility
- This utility will monitor the state of the PPP T1 line.
- In case of failure, a dial up connection will be established
- via pppd daemon, ether via a serial tty driver (serial port),
- or a WANPIPE async TTY driver (in case serial port is unavailable).
-
- Furthermore, while in dial up mode, the primary PPP T1 link
- will be monitored for signs of life.
-
- If the PPP T1 link comes back to life, the dial up connection
- will be shutdown and T1 line re-established.
-
-
- o New Setup installation script.
- Option to UPGRADE device drivers if the kernel source has
- already been patched with WANPIPE.
-
- Option to COMPILE WANPIPE modules against the currently
- running kernel, thus no need for manual kernel and module
- re-compilatin.
-
- o Updates and Bug Fixes to wancfg utility.
-
-bata2-2.2.1 Feb 20 2001
-
- o Bug fixes to the CHDLC device drivers.
- The driver had compilation problems under kernels
- 2.2.14 or lower.
-
- o Bug fixes to the Setup installation script.
- The device drivers compilation options didn't work
- properly.
-
- o Update to the wpbackupd daemon.
- Optimized the cross-over times, between the primary
- link and the backup dialup.
-
-beta3-2.2.1 Mar 02 2001
- o Patches for 2.4.2 kernel.
-
- o Bug fixes to util/ make files.
- o Bug fixes to the Setup installation script.
-
- o Took out the backupd support and made it into
- as separate package.
-
-beta4-2.2.1 Mar 12 2001
-
- o Fix to the Frame Relay Device driver.
- IPSAC sends a packet of zero length
- header to the frame relay driver. The
- driver tries to push its own 2 byte header
- into the packet, which causes the driver to
- crash.
-
- o Fix the WANPIPE re-configuration code.
- Bug was found by trying to run the cfgft1 while the
- interface was already running.
-
- o Updates to cfgft1.
- Writes a wanpipe#.cfgft1 configuration file
- once the CSU/DSU is configured. This file can
- holds the current CSU/DSU configuration.
-
-
-
->>>>>> END OF README <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
-
-
diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt
index 5d4ae9a39f1..f987afe43e2 100644
--- a/Documentation/power/devices.txt
+++ b/Documentation/power/devices.txt
@@ -207,27 +207,6 @@ SYSTEM_SHUTDOWN, I do not understand this one too much. probably event
#READY_AFTER_RESUME
#
-Driver Detach Power Management
-
-The kernel now supports the ability to place a device in a low-power
-state when it is detached from its driver, which happens when its
-module is removed.
-
-Each device contains a 'detach_state' file in its sysfs directory
-which can be used to control this state. Reading from this file
-displays what the current detach state is set to. This is 0 (On) by
-default. A user may write a positive integer value to this file in the
-range of 1-4 inclusive.
-
-A value of 1-3 will indicate the device should be placed in that
-low-power state, which will cause ->suspend() to be called for that
-device. A value of 4 indicates that the device should be shutdown, so
-->shutdown() will be called for that device.
-
-The driver is responsible for reinitializing the device when the
-module is re-inserted during it's ->probe() (or equivalent) method.
-The driver core will not call any extra functions when binding the
-device to the driver.
pm_message_t meaning
diff --git a/Documentation/power/kernel_threads.txt b/Documentation/power/kernel_threads.txt
index 60b548105ed..fb57784986b 100644
--- a/Documentation/power/kernel_threads.txt
+++ b/Documentation/power/kernel_threads.txt
@@ -12,8 +12,7 @@ refrigerator. Code to do this looks like this:
do {
hub_events();
wait_event_interruptible(khubd_wait, !list_empty(&hub_event_list));
- if (current->flags & PF_FREEZE)
- refrigerator(PF_FREEZE);
+ try_to_freeze();
} while (!signal_pending(current));
from drivers/usb/core/hub.c::hub_thread()
diff --git a/Documentation/power/pci.txt b/Documentation/power/pci.txt
index 35b1a7dae34..6fc9d511fc3 100644
--- a/Documentation/power/pci.txt
+++ b/Documentation/power/pci.txt
@@ -291,6 +291,44 @@ a request to enable wake events from D3, two calls should be made to
pci_enable_wake (one for both D3hot and D3cold).
+A reference implementation
+-------------------------
+.suspend()
+{
+ /* driver specific operations */
+
+ /* Disable IRQ */
+ free_irq();
+ /* If using MSI */
+ pci_disable_msi();
+
+ pci_save_state();
+ pci_enable_wake();
+ /* Disable IO/bus master/irq router */
+ pci_disable_device();
+ pci_set_power_state(pci_choose_state());
+}
+
+.resume()
+{
+ pci_set_power_state(PCI_D0);
+ pci_restore_state();
+ /* device's irq possibly is changed, driver should take care */
+ pci_enable_device();
+ pci_set_master();
+
+ /* if using MSI, device's vector possibly is changed */
+ pci_enable_msi();
+
+ request_irq();
+ /* driver specific operations; */
+}
+
+This is a typical implementation. Drivers can slightly change the order
+of the operations in the implementation, ignore some operations or add
+more deriver specific operations in it, but drivers should do something like
+this on the whole.
+
5. Resources
~~~~~~~~~~~~
diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt
index c7c3459fde4..7a6b7896645 100644
--- a/Documentation/power/swsusp.txt
+++ b/Documentation/power/swsusp.txt
@@ -164,11 +164,11 @@ place where the thread is safe to be frozen (no kernel semaphores
should be held at that point and it must be safe to sleep there), and
add:
- if (current->flags & PF_FREEZE)
- refrigerator(PF_FREEZE);
+ try_to_freeze();
If the thread is needed for writing the image to storage, you should
-instead set the PF_NOFREEZE process flag when creating the thread.
+instead set the PF_NOFREEZE process flag when creating the thread (and
+be very carefull).
Q: What is the difference between between "platform", "shutdown" and
@@ -233,3 +233,81 @@ A: Try running
cat `cat /proc/[0-9]*/maps | grep / | sed 's:.* /:/:' | sort -u` > /dev/null
after resume. swapoff -a; swapon -a may also be usefull.
+
+Q: What happens to devices during swsusp? They seem to be resumed
+during system suspend?
+
+A: That's correct. We need to resume them if we want to write image to
+disk. Whole sequence goes like
+
+ Suspend part
+ ~~~~~~~~~~~~
+ running system, user asks for suspend-to-disk
+
+ user processes are stopped
+
+ suspend(PMSG_FREEZE): devices are frozen so that they don't interfere
+ with state snapshot
+
+ state snapshot: copy of whole used memory is taken with interrupts disabled
+
+ resume(): devices are woken up so that we can write image to swap
+
+ write image to swap
+
+ suspend(PMSG_SUSPEND): suspend devices so that we can power off
+
+ turn the power off
+
+ Resume part
+ ~~~~~~~~~~~
+ (is actually pretty similar)
+
+ running system, user asks for suspend-to-disk
+
+ user processes are stopped (in common case there are none, but with resume-from-initrd, noone knows)
+
+ read image from disk
+
+ suspend(PMSG_FREEZE): devices are frozen so that they don't interfere
+ with image restoration
+
+ image restoration: rewrite memory with image
+
+ resume(): devices are woken up so that system can continue
+
+ thaw all user processes
+
+Q: What is this 'Encrypt suspend image' for?
+
+A: First of all: it is not a replacement for dm-crypt encrypted swap.
+It cannot protect your computer while it is suspended. Instead it does
+protect from leaking sensitive data after resume from suspend.
+
+Think of the following: you suspend while an application is running
+that keeps sensitive data in memory. The application itself prevents
+the data from being swapped out. Suspend, however, must write these
+data to swap to be able to resume later on. Without suspend encryption
+your sensitive data are then stored in plaintext on disk. This means
+that after resume your sensitive data are accessible to all
+applications having direct access to the swap device which was used
+for suspend. If you don't need swap after resume these data can remain
+on disk virtually forever. Thus it can happen that your system gets
+broken in weeks later and sensitive data which you thought were
+encrypted and protected are retrieved and stolen from the swap device.
+To prevent this situation you should use 'Encrypt suspend image'.
+
+During suspend a temporary key is created and this key is used to
+encrypt the data written to disk. When, during resume, the data was
+read back into memory the temporary key is destroyed which simply
+means that all data written to disk during suspend are then
+inaccessible so they can't be stolen later on. The only thing that
+you must then take care of is that you call 'mkswap' for the swap
+partition used for suspend as early as possible during regular
+boot. This asserts that any temporary key from an oopsed suspend or
+from a failed or aborted resume is erased from the swap device.
+
+As a rule of thumb use encrypted swap to protect your data while your
+system is shut down or suspended. Additionally use the encrypted
+suspend image to prevent sensitive data from being stolen after
+resume.
diff --git a/Documentation/power/video.txt b/Documentation/power/video.txt
index 68734355d7c..881a37e3eeb 100644
--- a/Documentation/power/video.txt
+++ b/Documentation/power/video.txt
@@ -83,8 +83,10 @@ Compaq Armada E500 - P3-700 none (1) (S1 also works OK)
Compaq Evo N620c vga=normal, s3_bios (2)
Dell 600m, ATI R250 Lf none (1), but needs xorg-x11-6.8.1.902-1
Dell D600, ATI RV250 vga=normal and X, or try vbestate (6)
+Dell D610 vga=normal and X (possibly vbestate (6) too, but not tested)
Dell Inspiron 4000 ??? (*)
Dell Inspiron 500m ??? (*)
+Dell Inspiron 510m ???
Dell Inspiron 600m ??? (*)
Dell Inspiron 8200 ??? (*)
Dell Inspiron 8500 ??? (*)
@@ -123,6 +125,7 @@ Toshiba Satellite 4030CDT s3_mode (3)
Toshiba Satellite 4080XCDT s3_mode (3)
Toshiba Satellite 4090XCDT ??? (*)
Toshiba Satellite P10-554 s3_bios,s3_mode (4)(****)
+Toshiba M30 (2) xor X with nvidia driver using internal AGP
Uniwill 244IIO ??? (*)
diff --git a/Documentation/power/video_extension.txt b/Documentation/power/video_extension.txt
index 8e33d7c82c4..b2f9b1598ac 100644
--- a/Documentation/power/video_extension.txt
+++ b/Documentation/power/video_extension.txt
@@ -1,13 +1,16 @@
-This driver implement the ACPI Extensions For Display Adapters
-for integrated graphics devices on motherboard, as specified in
-ACPI 2.0 Specification, Appendix B, allowing to perform some basic
-control like defining the video POST device, retrieving EDID information
-or to setup a video output, etc. Note that this is an ref. implementation only.
-It may or may not work for your integrated video device.
+ACPI video extensions
+~~~~~~~~~~~~~~~~~~~~~
+
+This driver implement the ACPI Extensions For Display Adapters for
+integrated graphics devices on motherboard, as specified in ACPI 2.0
+Specification, Appendix B, allowing to perform some basic control like
+defining the video POST device, retrieving EDID information or to
+setup a video output, etc. Note that this is an ref. implementation
+only. It may or may not work for your integrated video device.
Interfaces exposed to userland through /proc/acpi/video:
-VGA/info : display the supported video bus device capability like ,Video ROM, CRT/LCD/TV.
+VGA/info : display the supported video bus device capability like Video ROM, CRT/LCD/TV.
VGA/ROM : Used to get a copy of the display devices' ROM data (up to 4k).
VGA/POST_info : Used to determine what options are implemented.
VGA/POST : Used to get/set POST device.
@@ -15,7 +18,7 @@ VGA/DOS : Used to get/set ownership of output switching:
Please refer ACPI spec B.4.1 _DOS
VGA/CRT : CRT output
VGA/LCD : LCD output
-VGA/TV : TV output
+VGA/TVO : TV output
VGA/*/brightness : Used to get/set brightness of output device
Notify event through /proc/acpi/event:
diff --git a/Documentation/powerpc/hvcs.txt b/Documentation/powerpc/hvcs.txt
index c0a62e116e6..dca75cbda6f 100644
--- a/Documentation/powerpc/hvcs.txt
+++ b/Documentation/powerpc/hvcs.txt
@@ -347,8 +347,8 @@ address that is created by firmware. An example vty-server sysfs entry
looks like the following:
Pow5:/sys/bus/vio/drivers/hvcs/30000004 # ls
- . current_vty devspec name partner_vtys
- .. detach_state index partner_clcs vterm_state
+ . current_vty devspec name partner_vtys
+ .. index partner_clcs vterm_state
Each entry is provided, by default with a "name" attribute. Reading the
"name" attribute will reveal the device type as shown in the following
diff --git a/Documentation/s390/CommonIO b/Documentation/s390/CommonIO
index a831d9ae5a5..59d1166d41e 100644
--- a/Documentation/s390/CommonIO
+++ b/Documentation/s390/CommonIO
@@ -30,7 +30,7 @@ Command line parameters
device numbers (0xabcd or abcd, for 2.4 backward compatibility).
You can use the 'all' keyword to ignore all devices.
The '!' operator will cause the I/O-layer to _not_ ignore a device.
- The order on the command line is not important.
+ The command line is parsed from left to right.
For example,
cio_ignore=0.0.0023-0.0.0042,0.0.4711
@@ -72,13 +72,14 @@ Command line parameters
/proc/cio_ignore; "add <device range>, <device range>, ..." will ignore the
specified devices.
- Note: Already known devices cannot be ignored.
+ Note: While already known devices can be added to the list of devices to be
+ ignored, there will be no effect on then. However, if such a device
+ disappears and then reappeares, it will then be ignored.
- For example, if device 0.0.abcd is already known and all other devices
- 0.0.a000-0.0.afff are not known,
+ For example,
"echo add 0.0.a000-0.0.accc, 0.0.af00-0.0.afff > /proc/cio_ignore"
- will add 0.0.a000-0.0.abcc, 0.0.abce-0.0.accc and 0.0.af00-0.0.afff to the
- list of ignored devices and skip 0.0.abcd.
+ will add 0.0.a000-0.0.accc and 0.0.af00-0.0.afff to the list of ignored
+ devices.
The devices can be specified either by bus id (0.0.abcd) or, for 2.4 backward
compatibilty, by the device number in hexadecimal (0xabcd or abcd).
@@ -98,7 +99,8 @@ Command line parameters
- /proc/s390dbf/cio_trace/hex_ascii
Logs the calling of functions in the common I/O-layer and, if applicable,
- which subchannel they were called for.
+ which subchannel they were called for, as well as dumps of some data
+ structures (like irb in an error case).
The level of logging can be changed to be more or less verbose by piping to
/proc/s390dbf/cio_*/level a number between 0 and 6; see the documentation on
diff --git a/Documentation/s390/s390dbf.txt b/Documentation/s390/s390dbf.txt
index 2d1cd939b4d..e24fdeada97 100644
--- a/Documentation/s390/s390dbf.txt
+++ b/Documentation/s390/s390dbf.txt
@@ -12,8 +12,8 @@ where log records can be stored efficiently in memory, where each component
One purpose of this is to inspect the debug logs after a production system crash
in order to analyze the reason for the crash.
If the system still runs but only a subcomponent which uses dbf failes,
-it is possible to look at the debug logs on a live system via the Linux proc
-filesystem.
+it is possible to look at the debug logs on a live system via the Linux
+debugfs filesystem.
The debug feature may also very useful for kernel and driver development.
Design:
@@ -52,16 +52,18 @@ Each debug entry contains the following data:
- Flag, if entry is an exception or not
The debug logs can be inspected in a live system through entries in
-the proc-filesystem. Under the path /proc/s390dbf there is
+the debugfs-filesystem. Under the toplevel directory "s390dbf" there is
a directory for each registered component, which is named like the
-corresponding component.
+corresponding component. The debugfs normally should be mounted to
+/sys/kernel/debug therefore the debug feature can be accessed unter
+/sys/kernel/debug/s390dbf.
The content of the directories are files which represent different views
to the debug log. Each component can decide which views should be
used through registering them with the function debug_register_view().
Predefined views for hex/ascii, sprintf and raw binary data are provided.
It is also possible to define other views. The content of
-a view can be inspected simply by reading the corresponding proc file.
+a view can be inspected simply by reading the corresponding debugfs file.
All debug logs have an an actual debug level (range from 0 to 6).
The default level is 3. Event and Exception functions have a 'level'
@@ -69,14 +71,14 @@ parameter. Only debug entries with a level that is lower or equal
than the actual level are written to the log. This means, when
writing events, high priority log entries should have a low level
value whereas low priority entries should have a high one.
-The actual debug level can be changed with the help of the proc-filesystem
-through writing a number string "x" to the 'level' proc file which is
+The actual debug level can be changed with the help of the debugfs-filesystem
+through writing a number string "x" to the 'level' debugfs file which is
provided for every debug log. Debugging can be switched off completely
-by using "-" on the 'level' proc file.
+by using "-" on the 'level' debugfs file.
Example:
-> echo "-" > /proc/s390dbf/dasd/level
+> echo "-" > /sys/kernel/debug/s390dbf/dasd/level
It is also possible to deactivate the debug feature globally for every
debug log. You can change the behavior using 2 sysctl parameters in
@@ -99,11 +101,11 @@ Kernel Interfaces:
------------------
----------------------------------------------------------------------------
-debug_info_t *debug_register(char *name, int pages_index, int nr_areas,
+debug_info_t *debug_register(char *name, int pages, int nr_areas,
int buf_size);
-Parameter: name: Name of debug log (e.g. used for proc entry)
- pages_index: 2^pages_index pages will be allocated per area
+Parameter: name: Name of debug log (e.g. used for debugfs entry)
+ pages: number of pages, which will be allocated per area
nr_areas: number of debug areas
buf_size: size of data area in each debug entry
@@ -134,7 +136,7 @@ Return Value: none
Description: Sets new actual debug level if new_level is valid.
---------------------------------------------------------------------------
-+void debug_stop_all(void);
+void debug_stop_all(void);
Parameter: none
@@ -270,7 +272,7 @@ Parameter: id: handle for debug log
Return Value: 0 : ok
< 0: Error
-Description: registers new debug view and creates proc dir entry
+Description: registers new debug view and creates debugfs dir entry
---------------------------------------------------------------------------
int debug_unregister_view (debug_info_t * id, struct debug_view *view);
@@ -281,7 +283,7 @@ Parameter: id: handle for debug log
Return Value: 0 : ok
< 0: Error
-Description: unregisters debug view and removes proc dir entry
+Description: unregisters debug view and removes debugfs dir entry
@@ -308,7 +310,7 @@ static int init(void)
{
/* register 4 debug areas with one page each and 4 byte data field */
- debug_info = debug_register ("test", 0, 4, 4 );
+ debug_info = debug_register ("test", 1, 4, 4 );
debug_register_view(debug_info,&debug_hex_ascii_view);
debug_register_view(debug_info,&debug_raw_view);
@@ -343,7 +345,7 @@ static int init(void)
/* register 4 debug areas with one page each and data field for */
/* format string pointer + 2 varargs (= 3 * sizeof(long)) */
- debug_info = debug_register ("test", 0, 4, sizeof(long) * 3);
+ debug_info = debug_register ("test", 1, 4, sizeof(long) * 3);
debug_register_view(debug_info,&debug_sprintf_view);
debug_sprintf_event(debug_info, 2 , "first event in %s:%i\n",__FILE__,__LINE__);
@@ -362,16 +364,16 @@ module_exit(cleanup);
-ProcFS Interface
+Debugfs Interface
----------------
Views to the debug logs can be investigated through reading the corresponding
-proc-files:
+debugfs-files:
Example:
-> ls /proc/s390dbf/dasd
-flush hex_ascii level raw
-> cat /proc/s390dbf/dasd/hex_ascii | sort +1
+> ls /sys/kernel/debug/s390dbf/dasd
+flush hex_ascii level pages raw
+> cat /sys/kernel/debug/s390dbf/dasd/hex_ascii | sort +1
00 00974733272:680099 2 - 02 0006ad7e 07 ea 4a 90 | ....
00 00974733272:682210 2 - 02 0006ade6 46 52 45 45 | FREE
00 00974733272:682213 2 - 02 0006adf6 07 ea 4a 90 | ....
@@ -391,25 +393,36 @@ Changing the debug level
Example:
-> cat /proc/s390dbf/dasd/level
+> cat /sys/kernel/debug/s390dbf/dasd/level
3
-> echo "5" > /proc/s390dbf/dasd/level
-> cat /proc/s390dbf/dasd/level
+> echo "5" > /sys/kernel/debug/s390dbf/dasd/level
+> cat /sys/kernel/debug/s390dbf/dasd/level
5
Flushing debug areas
--------------------
Debug areas can be flushed with piping the number of the desired
-area (0...n) to the proc file "flush". When using "-" all debug areas
+area (0...n) to the debugfs file "flush". When using "-" all debug areas
are flushed.
Examples:
1. Flush debug area 0:
-> echo "0" > /proc/s390dbf/dasd/flush
+> echo "0" > /sys/kernel/debug/s390dbf/dasd/flush
2. Flush all debug areas:
-> echo "-" > /proc/s390dbf/dasd/flush
+> echo "-" > /sys/kernel/debug/s390dbf/dasd/flush
+
+Changing the size of debug areas
+------------------------------------
+It is possible the change the size of debug areas through piping
+the number of pages to the debugfs file "pages". The resize request will
+also flush the debug areas.
+
+Example:
+
+Define 4 pages for the debug areas of debug feature "dasd":
+> echo "4" > /sys/kernel/debug/s390dbf/dasd/pages
Stooping the debug feature
--------------------------
@@ -491,7 +504,7 @@ Defining views
--------------
Views are specified with the 'debug_view' structure. There are defined
-callback functions which are used for reading and writing the proc files:
+callback functions which are used for reading and writing the debugfs files:
struct debug_view {
char name[DEBUG_MAX_PROCF_LEN];
@@ -525,7 +538,7 @@ typedef int (debug_input_proc_t) (debug_info_t* id,
The "private_data" member can be used as pointer to view specific data.
It is not used by the debug feature itself.
-The output when reading a debug-proc file is structured like this:
+The output when reading a debugfs file is structured like this:
"prolog_proc output"
@@ -534,13 +547,13 @@ The output when reading a debug-proc file is structured like this:
"header_proc output 3" "format_proc output 3"
...
-When a view is read from the proc fs, the Debug Feature calls the
+When a view is read from the debugfs, the Debug Feature calls the
'prolog_proc' once for writing the prolog.
Then 'header_proc' and 'format_proc' are called for each
existing debug entry.
The input_proc can be used to implement functionality when it is written to
-the view (e.g. like with 'echo "0" > /proc/s390dbf/dasd/level).
+the view (e.g. like with 'echo "0" > /sys/kernel/debug/s390dbf/dasd/level).
For header_proc there can be used the default function
debug_dflt_header_fn() which is defined in in debug.h.
@@ -602,7 +615,7 @@ debug_info = debug_register ("test", 0, 4, 4 ));
debug_register_view(debug_info, &debug_test_view);
for(i = 0; i < 10; i ++) debug_int_event(debug_info, 1, i);
-> cat /proc/s390dbf/test/myview
+> cat /sys/kernel/debug/s390dbf/test/myview
00 00964419734:611402 1 - 00 88042ca This error...........
00 00964419734:611405 1 - 00 88042ca That error...........
00 00964419734:611408 1 - 00 88042ca Problem..............
diff --git a/Documentation/scsi/ChangeLog.megaraid b/Documentation/scsi/ChangeLog.megaraid
index a9356c63b80..5331d91432c 100644
--- a/Documentation/scsi/ChangeLog.megaraid
+++ b/Documentation/scsi/ChangeLog.megaraid
@@ -1,3 +1,69 @@
+Release Date : Mon Mar 07 12:27:22 EST 2005 - Seokmann Ju <sju@lsil.com>
+Current Version : 2.20.4.6 (scsi module), 2.20.2.6 (cmm module)
+Older Version : 2.20.4.5 (scsi module), 2.20.2.5 (cmm module)
+
+1. Added IOCTL backward compatibility.
+ Convert megaraid_mm driver to new compat_ioctl entry points.
+ I don't have easy access to hardware, so only compile tested.
+ - Signed-off-by:Andi Kleen <ak@muc.de>
+
+2. megaraid_mbox fix: wrong order of arguments in memset()
+ That, BTW, shows why cross-builds are useful-the only indication of
+ problem had been a new warning showing up in sparse output on alpha
+ build (number of exceeding 256 got truncated).
+ - Signed-off-by: Al Viro
+ <viro@parcelfarce.linux.theplanet.co.uk>
+
+3. Convert pci_module_init to pci_register_driver
+ Convert from pci_module_init to pci_register_driver
+ (from:http://kerneljanitors.org/TODO)
+ - Signed-off-by: Domen Puncer <domen@coderock.org>
+
+4. Use the pre defined DMA mask constants from dma-mapping.h
+ Use the DMA_{64,32}BIT_MASK constants from dma-mapping.h when calling
+ pci_set_dma_mask() or pci_set_consistend_dma_mask(). See
+ http://marc.theaimsgroup.com/?t=108001993000001&r=1&w=2 for more
+ details.
+ Signed-off-by: Tobias Klauser <tklauser@nuerscht.ch>
+ Signed-off-by: Domen Puncer <domen@coderock.org>
+
+5. Remove SSID checking for Dobson, Lindsay, and Verde based products.
+ Checking the SSVID/SSID for controllers which have Dobson, Lindsay,
+ and Verde is unnecessary because device ID has been assigned by LSI
+ and it is unique value. So, all controllers with these IOPs have to be
+ supported by the driver regardless SSVID/SSID.
+
+6. Date Thu, 27 Jan 2005 04:31:09 +0100
+ From Herbert Poetzl <>
+ Subject RFC: assert_spin_locked() for 2.6
+
+ Greetings!
+
+ overcautious programming will kill your kernel ;)
+ ever thought about checking a spin_lock or even
+ asserting that it must be held (maybe just for
+ spinlock debugging?) ...
+
+ there are several checks present in the kernel
+ where somebody does a variation on the following:
+
+ BUG_ON(!spin_is_locked(&some_lock));
+
+ so what's wrong about that? nothing, unless you
+ compile the code with CONFIG_DEBUG_SPINLOCK but
+ without CONFIG_SMP ... in which case the BUG()
+ will kill your kernel ...
+
+ maybe it's not advised to make such assertions,
+ but here is a solution which works for me ...
+ (compile tested for sh, x86_64 and x86, boot/run
+ tested for x86 only)
+
+ best,
+ Herbert
+
+ - Herbert Poetzl <herbert@13thfloor.at>, Thu, 27 Jan 2005
+
Release Date : Thu Feb 03 12:27:22 EST 2005 - Seokmann Ju <sju@lsil.com>
Current Version : 2.20.4.5 (scsi module), 2.20.2.5 (cmm module)
Older Version : 2.20.4.4 (scsi module), 2.20.2.4 (cmm module)
diff --git a/Documentation/scsi/scsi-changer.txt b/Documentation/scsi/scsi-changer.txt
new file mode 100644
index 00000000000..c132687b017
--- /dev/null
+++ b/Documentation/scsi/scsi-changer.txt
@@ -0,0 +1,180 @@
+
+README for the SCSI media changer driver
+========================================
+
+This is a driver for SCSI Medium Changer devices, which are listed
+with "Type: Medium Changer" in /proc/scsi/scsi.
+
+This is for *real* Jukeboxes. It is *not* supported to work with
+common small CD-ROM changers, neither one-lun-per-slot SCSI changers
+nor IDE drives.
+
+Userland tools available from here:
+ http://linux.bytesex.org/misc/changer.html
+
+
+General Information
+-------------------
+
+First some words about how changers work: A changer has 2 (possibly
+more) SCSI ID's. One for the changer device which controls the robot,
+and one for the device which actually reads and writes the data. The
+later may be anything, a MOD, a CD-ROM, a tape or whatever. For the
+changer device this is a "don't care", he *only* shuffles around the
+media, nothing else.
+
+
+The SCSI changer model is complex, compared to - for example - IDE-CD
+changers. But it allows to handle nearly all possible cases. It knows
+4 different types of changer elements:
+
+ media transport - this one shuffles around the media, i.e. the
+ transport arm. Also known as "picker".
+ storage - a slot which can hold a media.
+ import/export - the same as above, but is accessable from outside,
+ i.e. there the operator (you !) can use this to
+ fill in and remove media from the changer.
+ Sometimes named "mailslot".
+ data transfer - this is the device which reads/writes, i.e. the
+ CD-ROM / Tape / whatever drive.
+
+None of these is limited to one: A huge Jukebox could have slots for
+123 CD-ROM's, 5 CD-ROM readers (and therefore 6 SCSI ID's: the changer
+and each CD-ROM) and 2 transport arms. No problem to handle.
+
+
+How it is implemented
+---------------------
+
+I implemented the driver as character device driver with a NetBSD-like
+ioctl interface. Just grabbed NetBSD's header file and one of the
+other linux SCSI device drivers as starting point. The interface
+should be source code compatible with NetBSD. So if there is any
+software (anybody knows ???) which supports a BSDish changer driver,
+it should work with this driver too.
+
+Over time a few more ioctls where added, volume tag support for example
+wasn't covered by the NetBSD ioctl API.
+
+
+Current State
+-------------
+
+Support for more than one transport arm is not implemented yet (and
+nobody asked for it so far...).
+
+I test and use the driver myself with a 35 slot cdrom jukebox from
+Grundig. I got some reports telling it works ok with tape autoloaders
+(Exabyte, HP and DEC). Some People use this driver with amanda. It
+works fine with small (11 slots) and a huge (4 MOs, 88 slots)
+magneto-optical Jukebox. Probably with lots of other changers too, most
+(but not all :-) people mail me only if it does *not* work...
+
+I don't have any device lists, neither black-list nor white-list. Thus
+it is quite useless to ask me whenever a specific device is supported or
+not. In theory every changer device which supports the SCSI-2 media
+changer command set should work out-of-the-box with this driver. If it
+doesn't, it is a bug. Either within the driver or within the firmware
+of the changer device.
+
+
+Using it
+--------
+
+This is a character device with major number is 86, so use
+"mknod /dev/sch0 c 86 0" to create the special file for the driver.
+
+If the module finds the changer, it prints some messages about the
+device [ try "dmesg" if you don't see anything ] and should show up in
+/proc/devices. If not.... some changers use ID ? / LUN 0 for the
+device and ID ? / LUN 1 for the robot mechanism. But Linux does *not*
+look for LUN's other than 0 as default, becauce there are to many
+broken devices. So you can try:
+
+ 1) echo "scsi add-single-device 0 0 ID 1" > /proc/scsi/scsi
+ (replace ID with the SCSI-ID of the device)
+ 2) boot the kernel with "max_scsi_luns=1" on the command line
+ (append="max_scsi_luns=1" in lilo.conf should do the trick)
+
+
+Trouble?
+--------
+
+If you insmod the driver with "insmod debug=1", it will be verbose and
+prints a lot of stuff to the syslog. Compiling the kernel with
+CONFIG_SCSI_CONSTANTS=y improves the quality of the error messages alot
+because the kernel will translate the error codes into human-readable
+strings then.
+
+You can display these messages with the dmesg command (or check the
+logfiles). If you email me some question becauce of a problem with the
+driver, please include these messages.
+
+
+Insmod options
+--------------
+
+debug=0/1
+ Enable debug messages (see above, default: 0).
+
+verbose=0/1
+ Be verbose (default: 1).
+
+init=0/1
+ Send INITIALIZE ELEMENT STATUS command to the changer
+ at insmod time (default: 1).
+
+timeout_init=<seconds>
+ timeout for the INITIALIZE ELEMENT STATUS command
+ (default: 3600).
+
+timeout_move=<seconds>
+ timeout for all other commands (default: 120).
+
+dt_id=<id1>,<id2>,...
+dt_lun=<lun1>,<lun2>,...
+ These two allow to specify the SCSI ID and LUN for the data
+ transfer elements. You likely don't need this as the jukebox
+ should provide this information. But some devices don't ...
+
+vendor_firsts=
+vendor_counts=
+vendor_labels=
+ These insmod options can be used to tell the driver that there
+ are some vendor-specific element types. Grundig for example
+ does this. Some jukeboxes have a printer to label fresh burned
+ CDs, which is addressed as element 0xc000 (type 5). To tell the
+ driver about this vendor-specific element, use this:
+ $ insmod ch \
+ vendor_firsts=0xc000 \
+ vendor_counts=1 \
+ vendor_labels=printer
+ All three insmod options accept up to four comma-separated
+ values, this way you can configure the element types 5-8.
+ You likely need the SCSI specs for the device in question to
+ find the correct values as they are not covered by the SCSI-2
+ standard.
+
+
+Credits
+-------
+
+I wrote this driver using the famous mailing-patches-around-the-world
+method. With (more or less) help from:
+
+ Daniel Moehwald <moehwald@hdg.de>
+ Dane Jasper <dane@sonic.net>
+ R. Scott Bailey <sbailey@dsddi.eds.com>
+ Jonathan Corbet <corbet@lwn.net>
+
+Special thanks go to
+ Martin Kuehne <martin.kuehne@bnbt.de>
+for a old, second-hand (but full functional) cdrom jukebox which I use
+to develop/test driver and tools now.
+
+Have fun,
+
+ Gerd
+
+--
+Gerd Knorr <kraxel@bytesex.org>
diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt
index e41703d7d24..da176c95d0f 100644
--- a/Documentation/scsi/scsi_mid_low_api.txt
+++ b/Documentation/scsi/scsi_mid_low_api.txt
@@ -936,8 +936,7 @@ Details:
*
* Returns SUCCESS if command aborted else FAILED
*
- * Locks: struct Scsi_Host::host_lock held (with irqsave) on entry
- * and assumed to be held on return.
+ * Locks: None held
*
* Calling context: kernel thread
*
@@ -955,8 +954,7 @@ Details:
*
* Returns SUCCESS if command aborted else FAILED
*
- * Locks: struct Scsi_Host::host_lock held (with irqsave) on entry
- * and assumed to be held on return.
+ * Locks: None held
*
* Calling context: kernel thread
*
@@ -974,8 +972,7 @@ Details:
*
* Returns SUCCESS if command aborted else FAILED
*
- * Locks: struct Scsi_Host::host_lock held (with irqsave) on entry
- * and assumed to be held on return.
+ * Locks: None held
*
* Calling context: kernel thread
*
@@ -993,8 +990,7 @@ Details:
*
* Returns SUCCESS if command aborted else FAILED
*
- * Locks: struct Scsi_Host::host_lock held (with irqsave) on entry
- * and assumed to be held on return.
+ * Locks: None held
*
* Calling context: kernel thread
*
diff --git a/Documentation/sgi-ioc4.txt b/Documentation/sgi-ioc4.txt
new file mode 100644
index 00000000000..876c96ae38d
--- /dev/null
+++ b/Documentation/sgi-ioc4.txt
@@ -0,0 +1,45 @@
+The SGI IOC4 PCI device is a bit of a strange beast, so some notes on
+it are in order.
+
+First, even though the IOC4 performs multiple functions, such as an
+IDE controller, a serial controller, a PS/2 keyboard/mouse controller,
+and an external interrupt mechanism, it's not implemented as a
+multifunction device. The consequence of this from a software
+standpoint is that all these functions share a single IRQ, and
+they can't all register to own the same PCI device ID. To make
+matters a bit worse, some of the register blocks (and even registers
+themselves) present in IOC4 are mixed-purpose between these several
+functions, meaning that there's no clear "owning" device driver.
+
+The solution is to organize the IOC4 driver into several independent
+drivers, "ioc4", "sgiioc4", and "ioc4_serial". Note that there is no
+PS/2 controller driver as this functionality has never been wired up
+on a shipping IO card.
+
+ioc4
+====
+This is the core (or shim) driver for IOC4. It is responsible for
+initializing the basic functionality of the chip, and allocating
+the PCI resources that are shared between the IOC4 functions.
+
+This driver also provides registration functions that the other
+IOC4 drivers can call to make their presence known. Each driver
+needs to provide a probe and remove function, which are invoked
+by the core driver at appropriate times. The interface of these
+IOC4 function probe and remove operations isn't precisely the same
+as PCI device probe and remove operations, but is logically the
+same operation.
+
+sgiioc4
+=======
+This is the IDE driver for IOC4. Its name isn't very descriptive
+simply for historical reasons (it used to be the only IOC4 driver
+component). There's not much to say about it other than it hooks
+up to the ioc4 driver via the appropriate registration, probe, and
+remove functions.
+
+ioc4_serial
+===========
+This is the serial driver for IOC4. There's not much to say about it
+other than it hooks up to the ioc4 driver via the appropriate registration,
+probe, and remove functions.
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 71ef0498d5e..104a994b828 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -615,9 +615,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Module snd-hda-intel
--------------------
- Module for Intel HD Audio (ICH6, ICH6M, ICH7)
+ Module for Intel HD Audio (ICH6, ICH6M, ICH7), ATI SB450,
+ VIA VT8251/VT8237A
model - force the model name
+ position_fix - Fix DMA pointer (0 = FIFO size, 1 = none, 2 = POSBUF)
Module supports up to 8 cards.
@@ -635,6 +637,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
5stack 5-jack in back, 2-jack in front
5stack-digout 5-jack in back, 2-jack in front, a SPDIF out
w810 3-jack
+ z71v 3-jack (HP shared SPDIF)
+ asus 3-jack
+ uniwill 3-jack
+ F1734 2-jack
CMI9880
minimal 3-jack in back
@@ -642,6 +648,15 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
full 6-jack in back, 2-jack in front
full_dig 6-jack in back, 2-jack in front, SPDIF I/O
allout 5-jack in back, 2-jack in front, SPDIF out
+ auto auto-config reading BIOS (default)
+
+ Note 2: If you get click noises on output, try the module option
+ position_fix=1 or 2. position_fix=1 will use the SD_LPIB
+ register value without FIFO size correction as the current
+ DMA pointer. position_fix=2 will make the driver to use
+ the position buffer instead of reading SD_LPIB register.
+ (Usually SD_LPLIB register is more accurate than the
+ position buffer.)
Module snd-hdsp
---------------
@@ -660,7 +675,19 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
module did formerly. It will allocate the buffers in advance
when any HDSP cards are found. To make the buffer
allocation sure, load snd-page-alloc module in the early
- stage of boot sequence.
+ stage of boot sequence. See "Early Buffer Allocation"
+ section.
+
+ Module snd-hdspm
+ ----------------
+
+ Module for RME HDSP MADI board.
+
+ precise_ptr - Enable precise pointer, or disable.
+ line_outs_monitor - Send playback streams to analog outs by default.
+ enable_monitor - Enable Analog Out on Channel 63/64 by default.
+
+ See hdspm.txt for details.
Module snd-ice1712
------------------
@@ -677,15 +704,19 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
* TerraTec EWS 88D
* TerraTec EWX 24/96
* TerraTec DMX 6Fire
+ * TerraTec Phase 88
* Hoontech SoundTrack DSP 24
* Hoontech SoundTrack DSP 24 Value
* Hoontech SoundTrack DSP 24 Media 7.1
+ * Event Electronics, EZ8
* Digigram VX442
+ * Lionstracs, Mediastaton
model - Use the given board model, one of the following:
delta1010, dio2496, delta66, delta44, audiophile, delta410,
delta1010lt, vx442, ewx2496, ews88mt, ews88mt_new, ews88d,
- dmx6fire, dsp24, dsp24_value, dsp24_71, ez8
+ dmx6fire, dsp24, dsp24_value, dsp24_71, ez8,
+ phase88, mediastation
omni - Omni I/O support for MidiMan M-Audio Delta44/66
cs8427_timeout - reset timeout for the CS8427 chip (S/PDIF transciever)
in msec resolution, default value is 500 (0.5 sec)
@@ -694,20 +725,46 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
is not used with all Envy24 based cards (for example in the MidiMan Delta
serie).
+ Note: The supported board is detected by reading EEPROM or PCI
+ SSID (if EEPROM isn't available). You can override the
+ model by passing "model" module option in case that the
+ driver isn't configured properly or you want to try another
+ type for testing.
+
Module snd-ice1724
------------------
- Module for Envy24HT (VT/ICE1724) based PCI sound cards.
+ Module for Envy24HT (VT/ICE1724), Envy24PT (VT1720) based PCI sound cards.
* MidiMan M Audio Revolution 7.1
* AMP Ltd AUDIO2000
- * TerraTec Aureon Sky-5.1, Space-7.1
+ * TerraTec Aureon 5.1 Sky
+ * TerraTec Aureon 7.1 Space
+ * TerraTec Aureon 7.1 Universe
+ * TerraTec Phase 22
+ * TerraTec Phase 28
+ * AudioTrak Prodigy 7.1
+ * AudioTrak Prodigy 192
+ * Pontis MS300
+ * Albatron K8X800 Pro II
+ * Chaintech ZNF3-150
+ * Chaintech ZNF3-250
+ * Chaintech 9CJS
+ * Chaintech AV-710
+ * Shuttle SN25P
model - Use the given board model, one of the following:
- revo71, amp2000, prodigy71, aureon51, aureon71,
- k8x800
+ revo71, amp2000, prodigy71, prodigy192, aureon51,
+ aureon71, universe, k8x800, phase22, phase28, ms300,
+ av710
Module supports up to 8 cards and autoprobe.
+ Note: The supported board is detected by reading EEPROM or PCI
+ SSID (if EEPROM isn't available). You can override the
+ model by passing "model" module option in case that the
+ driver isn't configured properly or you want to try another
+ type for testing.
+
Module snd-intel8x0
-------------------
@@ -1026,7 +1083,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
module did formerly. It will allocate the buffers in advance
when any RME9652 cards are found. To make the buffer
allocation sure, load snd-page-alloc module in the early
- stage of boot sequence.
+ stage of boot sequence. See "Early Buffer Allocation"
+ section.
Module snd-sa11xx-uda1341 (on arm only)
---------------------------------------
@@ -1211,16 +1269,18 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
------------------
Module for AC'97 motherboards based on VIA 82C686A/686B, 8233,
- 8233A, 8233C, 8235 (south) bridge.
+ 8233A, 8233C, 8235, 8237 (south) bridge.
mpu_port - 0x300,0x310,0x320,0x330, otherwise obtain BIOS setup
[VIA686A/686B only]
joystick - Enable joystick (default off) [VIA686A/686B only]
ac97_clock - AC'97 codec clock base (default 48000Hz)
dxs_support - support DXS channels,
- 0 = auto (defalut), 1 = enable, 2 = disable,
- 3 = 48k only, 4 = no VRA
- [VIA8233/C,8235 only]
+ 0 = auto (default), 1 = enable, 2 = disable,
+ 3 = 48k only, 4 = no VRA, 5 = enable any sample
+ rate and different sample rates on different
+ channels
+ [VIA8233/C, 8235, 8237 only]
ac97_quirk - AC'97 workaround for strange hardware
See the description of intel8x0 module for details.
@@ -1232,18 +1292,23 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
default value 1.4. Then the interrupt number will be
assigned under 15. You might also upgrade your BIOS.
- Note: VIA8233/5 (not VIA8233A) can support DXS (direct sound)
+ Note: VIA8233/5/7 (not VIA8233A) can support DXS (direct sound)
channels as the first PCM. On these channels, up to 4
- streams can be played at the same time.
+ streams can be played at the same time, and the controller
+ can perform sample rate conversion with separate rates for
+ each channel.
As default (dxs_support = 0), 48k fixed rate is chosen
except for the known devices since the output is often
noisy except for 48k on some mother boards due to the
bug of BIOS.
- Please try once dxs_support=1 and if it works on other
+ Please try once dxs_support=5 and if it works on other
sample rates (e.g. 44.1kHz of mp3 playback), please let us
know the PCI subsystem vendor/device id's (output of
"lspci -nv").
- If it doesn't work, try dxs_support=4. If it still doesn't
+ If dxs_support=5 does not work, try dxs_support=4; if it
+ doesn't work too, try dxs_support=1. (dxs_support=1 is
+ usually for old motherboards. The correct implementated
+ board should work with 4 or 5.) If it still doesn't
work and the default setting is ok, dxs_support=3 is the
right choice. If the default setting doesn't work at all,
try dxs_support=2 to disable the DXS channels.
@@ -1497,6 +1562,36 @@ Proc interfaces (/proc/asound)
echo "rvplayer 0 0 block" > /proc/asound/card0/pcm0p/oss
+Early Buffer Allocation
+=======================
+
+Some drivers (e.g. hdsp) require the large contiguous buffers, and
+sometimes it's too late to find such spaces when the driver module is
+actually loaded due to memory fragmentation. You can pre-allocate the
+PCM buffers by loading snd-page-alloc module and write commands to its
+proc file in prior, for example, in the early boot stage like
+/etc/init.d/*.local scripts.
+
+Reading the proc file /proc/drivers/snd-page-alloc shows the current
+usage of page allocation. In writing, you can send the following
+commands to the snd-page-alloc driver:
+
+ - add VENDOR DEVICE MASK SIZE BUFFERS
+
+ VENDOR and DEVICE are PCI vendor and device IDs. They take
+ integer numbers (0x prefix is needed for the hex).
+ MASK is the PCI DMA mask. Pass 0 if not restricted.
+ SIZE is the size of each buffer to allocate. You can pass
+ k and m suffix for KB and MB. The max number is 16MB.
+ BUFFERS is the number of buffers to allocate. It must be greater
+ than 0. The max number is 4.
+
+ - erase
+
+ This will erase the all pre-allocated buffers which are not in
+ use.
+
+
Links
=====
diff --git a/Documentation/sound/alsa/CMIPCI.txt b/Documentation/sound/alsa/CMIPCI.txt
index 4a7df771b80..1872e24442a 100644
--- a/Documentation/sound/alsa/CMIPCI.txt
+++ b/Documentation/sound/alsa/CMIPCI.txt
@@ -89,19 +89,22 @@ and use the interleaved 4 channel data.
There are some control switchs affecting to the speaker connections:
-"Line-In As Rear" - As mentioned above, the line-in jack is used
- for the rear (3th and 4th channels) output.
-"Line-In As Bass" - The line-in jack is used for the bass (5th
- and 6th channels) output.
-"Mic As Center/LFE" - The mic jack is used for the bass output.
- If this switch is on, you cannot use a microphone as a capture
- source, of course.
-
+"Line-In Mode" - an enum control to change the behavior of line-in
+ jack. Either "Line-In", "Rear Output" or "Bass Output" can
+ be selected. The last item is available only with model 039
+ or newer.
+ When "Rear Output" is chosen, the surround channels 3 and 4
+ are output to line-in jack.
+"Mic-In Mode" - an enum control to change the behavior of mic-in
+ jack. Either "Mic-In" or "Center/LFE Output" can be
+ selected.
+ When "Center/LFE Output" is chosen, the center and bass
+ channels (channels 5 and 6) are output to mic-in jack.
Digital I/O
-----------
-The CM8x38 provides the excellent SPDIF capability with very chip
+The CM8x38 provides the excellent SPDIF capability with very cheap
price (yes, that's the reason I bought the card :)
The SPDIF playback and capture are done via the third PCM device
@@ -122,8 +125,9 @@ respectively, so you cannot playback both analog and digital streams
simultaneously.
To enable SPDIF output, you need to turn on "IEC958 Output Switch"
-control via mixer or alsactl. Then you'll see the red light on from
-the card so you know that's working obviously :)
+control via mixer or alsactl ("IEC958" is the official name of
+so-called S/PDIF). Then you'll see the red light on from the card so
+you know that's working obviously :)
The SPDIF input is always enabled, so you can hear SPDIF input data
from line-out with "IEC958 In Monitor" switch at any time (see
below).
@@ -205,9 +209,10 @@ In addition to the standard SB mixer, CM8x38 provides more functions.
MIDI CONTROLLER
---------------
-The MPU401-UART interface is enabled as default only for the first
-(CMIPCI) card. You need to set module option "midi_port" properly
-for the 2nd (CMIPCI) card.
+The MPU401-UART interface is disabled as default. You need to set
+module option "mpu_port" with a valid I/O port address to enable the
+MIDI support. The valid I/O ports are 0x300, 0x310, 0x320 and 0x330.
+Choose the value which doesn't conflict with other cards.
There is _no_ hardware wavetable function on this chip (except for
OPL3 synth below).
@@ -229,9 +234,11 @@ I don't know why..
Joystick and Modem
------------------
-The joystick and modem should be available by enabling the control
-switch "Joystick" and "Modem" respectively. But I myself have never
-tested them yet.
+The legacy joystick is supported. To enable the joystick support, pass
+joystick_port=1 module option. The value 1 means the auto-detection.
+If the auto-detection fails, try to pass the exact I/O address.
+
+The modem is enabled dynamically via a card control switch "Modem".
Debugging Information
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
index e789475304b..db0b7d2dc47 100644
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
@@ -371,7 +371,7 @@
<listitem><para>create <function>probe()</function> callback.</para></listitem>
<listitem><para>create <function>remove()</function> callback.</para></listitem>
<listitem><para>create pci_driver table which contains the three pointers above.</para></listitem>
- <listitem><para>create <function>init()</function> function just calling <function>pci_module_init()</function> to register the pci_driver table defined above.</para></listitem>
+ <listitem><para>create <function>init()</function> function just calling <function>pci_register_driver()</function> to register the pci_driver table defined above.</para></listitem>
<listitem><para>create <function>exit()</function> function to call <function>pci_unregister_driver()</function> function.</para></listitem>
</itemizedlist>
</para>
@@ -1198,7 +1198,7 @@
/* initialization of the module */
static int __init alsa_card_mychip_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
/* clean up the module */
@@ -1654,7 +1654,7 @@
<![CDATA[
static int __init alsa_card_mychip_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_mychip_exit(void)
diff --git a/Documentation/sound/alsa/emu10k1-jack.txt b/Documentation/sound/alsa/emu10k1-jack.txt
new file mode 100644
index 00000000000..751d45036a0
--- /dev/null
+++ b/Documentation/sound/alsa/emu10k1-jack.txt
@@ -0,0 +1,74 @@
+This document is a guide to using the emu10k1 based devices with JACK for low
+latency, multichannel recording functionality. All of my recent work to allow
+Linux users to use the full capabilities of their hardware has been inspired
+by the kX Project. Without their work I never would have discovered the true
+power of this hardware.
+
+ http://www.kxproject.com
+ - Lee Revell, 2005.03.30
+
+Low latency, multichannel audio with JACK and the emu10k1/emu10k2
+-----------------------------------------------------------------
+
+Until recently, emu10k1 users on Linux did not have access to the same low
+latency, multichannel features offered by the "kX ASIO" feature of their
+Windows driver. As of ALSA 1.0.9 this is no more!
+
+For those unfamiliar with kX ASIO, this consists of 16 capture and 16 playback
+channels. With a post 2.6.9 Linux kernel, latencies down to 64 (1.33 ms) or
+even 32 (0.66ms) frames should work well.
+
+The configuration is slightly more involved than on Windows, as you have to
+select the correct device for JACK to use. Actually, for qjackctl users it's
+fairly self explanatory - select Duplex, then for capture and playback select
+the multichannel devices, set the in and out channels to 16, and the sample
+rate to 48000Hz. The command line looks like this:
+
+/usr/local/bin/jackd -R -dalsa -r48000 -p64 -n2 -D -Chw:0,2 -Phw:0,3 -S
+
+This will give you 16 input ports and 16 output ports.
+
+The 16 output ports map onto the 16 FX buses (or the first 16 of 64, for the
+Audigy). The mapping from FX bus to physical output is described in
+SB-Live-mixer.txt (or Audigy-mixer.txt).
+
+The 16 input ports are connected to the 16 physical inputs. Contrary to
+popular belief, all emu10k1 cards are multichannel cards. Which of these
+input channels have physical inputs connected to them depends on the card
+model. Trial and error is highly recommended; the pinout diagrams
+for the card have been reverse engineered by some enterprising kX users and are
+available on the internet. Meterbridge is helpful here, and the kX forums are
+packed with useful information.
+
+Each input port will either correspond to a digital (SPDIF) input, an analog
+input, or nothing. The one exception is the SBLive! 5.1. On these devices,
+the second and third input ports are wired to the center/LFE output. You will
+still see 16 capture channels, but only 14 are available for recording inputs.
+
+This chart, borrowed from kxfxlib/da_asio51.cpp, describes the mapping of JACK
+ports to FXBUS2 (multitrack recording input) and EXTOUT (physical output)
+channels.
+
+/*JACK (& ASIO) mappings on 10k1 5.1 SBLive cards:
+--------------------------------------------
+JACK Epilog FXBUS2(nr)
+--------------------------------------------
+capture_1 asio14 FXBUS2(0xe)
+capture_2 asio15 FXBUS2(0xf)
+capture_3 asio0 FXBUS2(0x0)
+~capture_4 Center EXTOUT(0x11) // mapped to by Center
+~capture_5 LFE EXTOUT(0x12) // mapped to by LFE
+capture_6 asio3 FXBUS2(0x3)
+capture_7 asio4 FXBUS2(0x4)
+capture_8 asio5 FXBUS2(0x5)
+capture_9 asio6 FXBUS2(0x6)
+capture_10 asio7 FXBUS2(0x7)
+capture_11 asio8 FXBUS2(0x8)
+capture_12 asio9 FXBUS2(0x9)
+capture_13 asio10 FXBUS2(0xa)
+capture_14 asio11 FXBUS2(0xb)
+capture_15 asio12 FXBUS2(0xc)
+capture_16 asio13 FXBUS2(0xd)
+*/
+
+TODO: describe use of ld10k1/qlo10k1 in conjunction with JACK
diff --git a/Documentation/sound/alsa/hdspm.txt b/Documentation/sound/alsa/hdspm.txt
new file mode 100644
index 00000000000..7a67ff71a9f
--- /dev/null
+++ b/Documentation/sound/alsa/hdspm.txt
@@ -0,0 +1,362 @@
+Software Interface ALSA-DSP MADI Driver
+
+(translated from German, so no good English ;-),
+2004 - winfried ritsch
+
+
+
+ Full functionality has been added to the driver. Since some of
+ the Controls and startup-options are ALSA-Standard and only the
+ special Controls are described and discussed below.
+
+
+ hardware functionality:
+
+
+ Audio transmission:
+
+ number of channels -- depends on transmission mode
+
+ The number of channels chosen is from 1..Nmax. The reason to
+ use for a lower number of channels is only resource allocation,
+ since unused DMA channels are disabled and less memory is
+ allocated. So also the throughput of the PCI system can be
+ scaled. (Only important for low performance boards).
+
+ Single Speed -- 1..64 channels
+
+ (Note: Choosing the 56channel mode for transmission or as
+ receiver, only 56 are transmitted/received over the MADI, but
+ all 64 channels are available for the mixer, so channel count
+ for the driver)
+
+ Double Speed -- 1..32 channels
+
+ Note: Choosing the 56-channel mode for
+ transmission/receive-mode , only 28 are transmitted/received
+ over the MADI, but all 32 channels are available for the mixer,
+ so channel count for the driver
+
+
+ Quad Speed -- 1..16 channels
+
+ Note: Choosing the 56-channel mode for
+ transmission/receive-mode , only 14 are transmitted/received
+ over the MADI, but all 16 channels are available for the mixer,
+ so channel count for the driver
+
+ Format -- signed 32 Bit Little Endian (SNDRV_PCM_FMTBIT_S32_LE)
+
+ Sample Rates --
+
+ Single Speed -- 32000, 44100, 48000
+
+ Double Speed -- 64000, 88200, 96000 (untested)
+
+ Quad Speed -- 128000, 176400, 192000 (untested)
+
+ access-mode -- MMAP (memory mapped), Not interleaved
+ (PCM_NON-INTERLEAVED)
+
+ buffer-sizes -- 64,128,256,512,1024,2048,8192 Samples
+
+ fragments -- 2
+
+ Hardware-pointer -- 2 Modi
+
+
+ The Card supports the readout of the actual Buffer-pointer,
+ where DMA reads/writes. Since of the bulk mode of PCI it is only
+ 64 Byte accurate. SO it is not really usable for the
+ ALSA-mid-level functions (here the buffer-ID gives a better
+ result), but if MMAP is used by the application. Therefore it
+ can be configured at load-time with the parameter
+ precise-pointer.
+
+
+ (Hint: Experimenting I found that the pointer is maximum 64 to
+ large never to small. So if you subtract 64 you always have a
+ safe pointer for writing, which is used on this mode inside
+ ALSA. In theory now you can get now a latency as low as 16
+ Samples, which is a quarter of the interrupt possibilities.)
+
+ Precise Pointer -- off
+ interrupt used for pointer-calculation
+
+ Precise Pointer -- on
+ hardware pointer used.
+
+ Controller:
+
+
+ Since DSP-MADI-Mixer has 8152 Fader, it does not make sense to
+ use the standard mixer-controls, since this would break most of
+ (especially graphic) ALSA-Mixer GUIs. So Mixer control has be
+ provided by a 2-dimensional controller using the
+ hwdep-interface.
+
+ Also all 128+256 Peak and RMS-Meter can be accessed via the
+ hwdep-interface. Since it could be a performance problem always
+ copying and converting Peak and RMS-Levels even if you just need
+ one, I decided to export the hardware structure, so that of
+ needed some driver-guru can implement a memory-mapping of mixer
+ or peak-meters over ioctl, or also to do only copying and no
+ conversion. A test-application shows the usage of the controller.
+
+ Latency Controls --- not implemented !!!
+
+
+ Note: Within the windows-driver the latency is accessible of a
+ control-panel, but buffer-sizes are controlled with ALSA from
+ hwparams-calls and should not be changed in run-state, I did not
+ implement it here.
+
+
+ System Clock -- suspended !!!!
+
+ Name -- "System Clock Mode"
+
+ Access -- Read Write
+
+ Values -- "Master" "Slave"
+
+
+ !!!! This is a hardware-function but is in conflict with the
+ Clock-source controller, which is a kind of ALSA-standard. I
+ makes sense to set the card to a special mode (master at some
+ frequency or slave), since even not using an Audio-application
+ a studio should have working synchronisations setup. So use
+ Clock-source-controller instead !!!!
+
+ Clock Source
+
+ Name -- "Sample Clock Source"
+
+ Access -- Read Write
+
+ Values -- "AutoSync", "Internal 32.0 kHz", "Internal 44.1 kHz",
+ "Internal 48.0 kHz", "Internal 64.0 kHz", "Internal 88.2 kHz",
+ "Internal 96.0 kHz"
+
+ Choose between Master at a specific Frequency and so also the
+ Speed-mode or Slave (Autosync). Also see "Preferred Sync Ref"
+
+
+ !!!! This is no pure hardware function but was implemented by
+ ALSA by some ALSA-drivers before, so I use it also. !!!
+
+
+ Preferred Sync Ref
+
+ Name -- "Preferred Sync Reference"
+
+ Access -- Read Write
+
+ Values -- "Word" "MADI"
+
+
+ Within the Auto-sync-Mode the preferred Sync Source can be
+ chosen. If it is not available another is used if possible.
+
+ Note: Since MADI has a much higher bit-rate than word-clock, the
+ card should synchronise better in MADI Mode. But since the
+ RME-PLL is very good, there are almost no problems with
+ word-clock too. I never found a difference.
+
+
+ TX 64 channel ---
+
+ Name -- "TX 64 channels mode"
+
+ Access -- Read Write
+
+ Values -- 0 1
+
+ Using 64-channel-modus (1) or 56-channel-modus for
+ MADI-transmission (0).
+
+
+ Note: This control is for output only. Input-mode is detected
+ automatically from hardware sending MADI.
+
+
+ Clear TMS ---
+
+ Name -- "Clear Track Marker"
+
+ Access -- Read Write
+
+ Values -- 0 1
+
+
+ Don't use to lower 5 Audio-bits on AES as additional Bits.
+
+
+ Safe Mode oder Auto Input ---
+
+ Name -- "Safe Mode"
+
+ Access -- Read Write
+
+ Values -- 0 1
+
+ (default on)
+
+ If on (1), then if either the optical or coaxial connection
+ has a failure, there is a takeover to the working one, with no
+ sample failure. Its only useful if you use the second as a
+ backup connection.
+
+ Input ---
+
+ Name -- "Input Select"
+
+ Access -- Read Write
+
+ Values -- optical coaxial
+
+
+ Choosing the Input, optical or coaxial. If Safe-mode is active,
+ this is the preferred Input.
+
+-------------- Mixer ----------------------
+
+ Mixer
+
+ Name -- "Mixer"
+
+ Access -- Read Write
+
+ Values - <channel-number 0-127> <Value 0-65535>
+
+
+ Here as a first value the channel-index is taken to get/set the
+ corresponding mixer channel, where 0-63 are the input to output
+ fader and 64-127 the playback to outputs fader. Value 0
+ is channel muted 0 and 32768 an amplification of 1.
+
+ Chn 1-64
+
+ fast mixer for the ALSA-mixer utils. The diagonal of the
+ mixer-matrix is implemented from playback to output.
+
+
+ Line Out
+
+ Name -- "Line Out"
+
+ Access -- Read Write
+
+ Values -- 0 1
+
+ Switching on and off the analog out, which has nothing to do
+ with mixing or routing. the analog outs reflects channel 63,64.
+
+
+--- information (only read access):
+
+ Sample Rate
+
+ Name -- "System Sample Rate"
+
+ Access -- Read-only
+
+ getting the sample rate.
+
+
+ External Rate measured
+
+ Name -- "External Rate"
+
+ Access -- Read only
+
+
+ Should be "Autosync Rate", but Name used is
+ ALSA-Scheme. External Sample frequency liked used on Autosync is
+ reported.
+
+
+ MADI Sync Status
+
+ Name -- "MADI Sync Lock Status"
+
+ Access -- Read
+
+ Values -- 0,1,2
+
+ MADI-Input is 0=Unlocked, 1=Locked, or 2=Synced.
+
+
+ Word Clock Sync Status
+
+ Name -- "Word Clock Lock Status"
+
+ Access -- Read
+
+ Values -- 0,1,2
+
+ Word Clock Input is 0=Unlocked, 1=Locked, or 2=Synced.
+
+ AutoSync
+
+ Name -- "AutoSync Reference"
+
+ Access -- Read
+
+ Values -- "WordClock", "MADI", "None"
+
+ Sync-Reference is either "WordClock", "MADI" or none.
+
+ RX 64ch --- noch nicht implementiert
+
+ MADI-Receiver is in 64 channel mode oder 56 channel mode.
+
+
+ AB_inp --- not tested
+
+ Used input for Auto-Input.
+
+
+ actual Buffer Position --- not implemented
+
+ !!! this is a ALSA internal function, so no control is used !!!
+
+
+
+Calling Parameter:
+
+ index int array (min = 1, max = 8),
+ "Index value for RME HDSPM interface." card-index within ALSA
+
+ note: ALSA-standard
+
+ id string array (min = 1, max = 8),
+ "ID string for RME HDSPM interface."
+
+ note: ALSA-standard
+
+ enable int array (min = 1, max = 8),
+ "Enable/disable specific HDSPM sound-cards."
+
+ note: ALSA-standard
+
+ precise_ptr int array (min = 1, max = 8),
+ "Enable precise pointer, or disable."
+
+ note: Use only when the application supports this (which is a special case).
+
+ line_outs_monitor int array (min = 1, max = 8),
+ "Send playback streams to analog outs by default."
+
+
+ note: each playback channel is mixed to the same numbered output
+ channel (routed). This is against the ALSA-convention, where all
+ channels have to be muted on after loading the driver, but was
+ used before on other cards, so i historically use it again)
+
+
+
+ enable_monitor int array (min = 1, max = 8),
+ "Enable Analog Out on Channel 63/64 by default."
+
+ note: here the analog output is enabled (but not routed). \ No newline at end of file
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index 35159176997..9f11d36a8c1 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -49,6 +49,7 @@ show up in /proc/sys/kernel:
- shmmax [ sysv ipc ]
- shmmni
- stop-a [ SPARC only ]
+- suid_dumpable
- sysrq ==> Documentation/sysrq.txt
- tainted
- threads-max
@@ -300,6 +301,25 @@ kernel. This value defaults to SHMMAX.
==============================================================
+suid_dumpable:
+
+This value can be used to query and set the core dump mode for setuid
+or otherwise protected/tainted binaries. The modes are
+
+0 - (default) - traditional behaviour. Any process which has changed
+ privilege levels or is execute only will not be dumped
+1 - (debug) - all processes dump core when possible. The core dump is
+ owned by the current user and no security is applied. This is
+ intended for system debugging situations only. Ptrace is unchecked.
+2 - (suidsafe) - any binary which normally would not be dumped is dumped
+ readable by root only. This allows the end user to remove
+ such a dump but not access it directly. For security reasons
+ core dumps in this mode will not overwrite one another or
+ other files. This mode is appropriate when adminstrators are
+ attempting to debug problems in a normal environment.
+
+==============================================================
+
tainted:
Non-zero if the kernel has been tainted. Numeric values, which
diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt
index f98c2e31c14..136d817c01b 100644
--- a/Documentation/sysrq.txt
+++ b/Documentation/sysrq.txt
@@ -72,6 +72,8 @@ On all - write a character to /proc/sysrq-trigger. eg:
'b' - Will immediately reboot the system without syncing or unmounting
your disks.
+'c' - Will perform a kexec reboot in order to take a crashdump.
+
'o' - Will shut your system off (if configured and supported).
's' - Will attempt to sync all mounted filesystems.
@@ -122,6 +124,9 @@ useful when you want to exit a program that will not let you switch consoles.
re'B'oot is good when you're unable to shut down. But you should also 'S'ync
and 'U'mount first.
+'C'rashdump can be used to manually trigger a crashdump when the system is hung.
+The kernel needs to have been built with CONFIG_KEXEC enabled.
+
'S'ync is great when your system is locked up, it allows you to sync your
disks and will certainly lessen the chance of data loss and fscking. Note
that the sync hasn't taken place until you see the "OK" and "Done" appear
diff --git a/Documentation/tty.txt b/Documentation/tty.txt
index 3958cf746dd..8ff7bc2a081 100644
--- a/Documentation/tty.txt
+++ b/Documentation/tty.txt
@@ -22,7 +22,7 @@ copy of the structure. You must not re-register over the top of the line
discipline even with the same data or your computer again will be eaten by
demons.
-In order to remove a line discipline call tty_register_ldisc passing NULL.
+In order to remove a line discipline call tty_unregister_ldisc().
In ancient times this always worked. In modern times the function will
return -EBUSY if the ldisc is currently in use. Since the ldisc referencing
code manages the module counts this should not usually be a concern.
diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv
index e46761c39e3..aeeafec0594 100644
--- a/Documentation/video4linux/CARDLIST.bttv
+++ b/Documentation/video4linux/CARDLIST.bttv
@@ -119,3 +119,17 @@ card=117 - NGS NGSTV+
card=118 - LMLBT4
card=119 - Tekram M205 PRO
card=120 - Conceptronic CONTVFMi
+card=121 - Euresys Picolo Tetra
+card=122 - Spirit TV Tuner
+card=123 - AVerMedia AVerTV DVB-T 771
+card=124 - AverMedia AverTV DVB-T 761
+card=125 - MATRIX Vision Sigma-SQ
+card=126 - MATRIX Vision Sigma-SLC
+card=127 - APAC Viewcomp 878(AMAX)
+card=128 - DVICO FusionHDTV DVB-T Lite
+card=129 - V-Gear MyVCD
+card=130 - Super TV Tuner
+card=131 - Tibet Systems 'Progress DVR' CS16
+card=132 - Kodicom 4400R (master)
+card=133 - Kodicom 4400R (slave)
+card=134 - Adlink RTV24
diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88
new file mode 100644
index 00000000000..216f705495c
--- /dev/null
+++ b/Documentation/video4linux/CARDLIST.cx88
@@ -0,0 +1,29 @@
+card=0 - UNKNOWN/GENERIC
+card=1 - Hauppauge WinTV 34xxx models
+card=2 - GDI Black Gold
+card=3 - PixelView
+card=4 - ATI TV Wonder Pro
+card=5 - Leadtek Winfast 2000XP Expert
+card=6 - AverTV Studio 303 (M126)
+card=7 - MSI TV-@nywhere Master
+card=8 - Leadtek Winfast DV2000
+card=9 - Leadtek PVR 2000
+card=10 - IODATA GV-VCP3/PCI
+card=11 - Prolink PlayTV PVR
+card=12 - ASUS PVR-416
+card=13 - MSI TV-@nywhere
+card=14 - KWorld/VStream XPert DVB-T
+card=15 - DVICO FusionHDTV DVB-T1
+card=16 - KWorld LTV883RF
+card=17 - DViCO - FusionHDTV 3 Gold
+card=18 - Hauppauge Nova-T DVB-T
+card=19 - Conexant DVB-T reference design
+card=20 - Provideo PV259
+card=21 - DVICO FusionHDTV DVB-T Plus
+card=22 - digitalnow DNTV Live! DVB-T
+card=23 - pcHDTV HD3000 HDTV
+card=24 - Hauppauge WinTV 28xxx (Roslyn) models
+card=25 - Digital-Logic MICROSPACE Entertainment Center (MEC)
+card=26 - IODATA GV/BCTV7E
+card=27 - PixelView PlayTV Ultra Pro (Stereo)
+card=28 - DViCO - FusionHDTV 3 Gold-T
diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134
index a6c82fa4de0..d5ed95d2850 100644
--- a/Documentation/video4linux/CARDLIST.saa7134
+++ b/Documentation/video4linux/CARDLIST.saa7134
@@ -20,16 +20,37 @@
19 -> Compro VideoMate TV [185b:c100]
20 -> Matrox CronosPlus [102B:48d0]
21 -> 10MOONS PCI TV CAPTURE CARD [1131:2001]
- 22 -> Medion 2819/ AverMedia M156 [1461:a70b,1461:2115]
+ 22 -> AverMedia M156 / Medion 2819 [1461:a70b]
23 -> BMK MPEX Tuner
24 -> KNC One TV-Station DVR [1894:a006]
25 -> ASUS TV-FM 7133 [1043:4843]
26 -> Pinnacle PCTV Stereo (saa7134) [11bd:002b]
- 27 -> Manli MuchTV M-TV002
- 28 -> Manli MuchTV M-TV001
+ 27 -> Manli MuchTV M-TV002/Behold TV 403 FM
+ 28 -> Manli MuchTV M-TV001/Behold TV 401
29 -> Nagase Sangyo TransGear 3000TV [1461:050c]
30 -> Elitegroup ECS TVP3XP FM1216 Tuner Card(PAL-BG,FM) [1019:4cb4]
31 -> Elitegroup ECS TVP3XP FM1236 Tuner Card (NTSC,FM) [1019:4cb5]
32 -> AVACS SmartTV
33 -> AVerMedia DVD EZMaker [1461:10ff]
- 34 -> LifeView FlyTV Platinum33 mini [5168:0212]
+ 34 -> Noval Prime TV 7133
+ 35 -> AverMedia AverTV Studio 305 [1461:2115]
+ 37 -> Items MuchTV Plus / IT-005
+ 38 -> Terratec Cinergy 200 TV [153B:1152]
+ 39 -> LifeView FlyTV Platinum Mini [5168:0212]
+ 40 -> Compro VideoMate TV PVR/FM [185b:c100]
+ 41 -> Compro VideoMate TV Gold+ [185b:c100]
+ 42 -> Sabrent SBT-TVFM (saa7130)
+ 43 -> :Zolid Xpert TV7134
+ 44 -> Empire PCI TV-Radio LE
+ 45 -> Avermedia AVerTV Studio 307 [1461:9715]
+ 46 -> AVerMedia Cardbus TV/Radio [1461:d6ee]
+ 47 -> Terratec Cinergy 400 mobile [153b:1162]
+ 48 -> Terratec Cinergy 600 TV MK3 [153B:1158]
+ 49 -> Compro VideoMate Gold+ Pal [185b:c200]
+ 50 -> Pinnacle PCTV 300i DVB-T + PAL [11bd:002d]
+ 51 -> ProVideo PV952 [1540:9524]
+ 52 -> AverMedia AverTV/305 [1461:2108]
+ 54 -> LifeView FlyTV Platinum FM [5168:0214,1489:0214]
+ 55 -> LifeView FlyDVB-T DUO [5168:0306]
+ 56 -> Avermedia AVerTV 307 [1461:a70a]
+ 57 -> Avermedia AVerTV GO 007 FM [1461:f31f]
diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner
index f7bafe862ba..aeb8df8ce89 100644
--- a/Documentation/video4linux/CARDLIST.tuner
+++ b/Documentation/video4linux/CARDLIST.tuner
@@ -44,3 +44,18 @@ tuner=42 - Philips 1236D ATSC/NTSC daul in
tuner=43 - Philips NTSC MK3 (FM1236MK3 or FM1236/F)
tuner=44 - Philips 4 in 1 (ATI TV Wonder Pro/Conexant)
tuner=45 - Microtune 4049 FM5
+tuner=46 - Panasonic VP27s/ENGE4324D
+tuner=47 - LG NTSC (TAPE series)
+tuner=48 - Tenna TNF 8831 BGFF)
+tuner=49 - Microtune 4042 FI5 ATSC/NTSC dual in
+tuner=50 - TCL 2002N
+tuner=51 - Philips PAL/SECAM_D (FM 1256 I-H3)
+tuner=52 - Thomson DDT 7610 (ATSC/NTSC)
+tuner=53 - Philips FQ1286
+tuner=54 - tda8290+75
+tuner=55 - LG PAL (TAPE series)
+tuner=56 - Philips PAL/SECAM multi (FQ1216AME MK4)
+tuner=57 - Philips FQ1236A MK4
+tuner=58 - Ymec TVision TVF-8531MF
+tuner=59 - Ymec TVision TVF-5533MF
+tuner=60 - Thomson DDT 7611 (ATSC/NTSC)
diff --git a/Documentation/video4linux/hauppauge-wintv-cx88-ir.txt b/Documentation/video4linux/hauppauge-wintv-cx88-ir.txt
new file mode 100644
index 00000000000..93fec32a118
--- /dev/null
+++ b/Documentation/video4linux/hauppauge-wintv-cx88-ir.txt
@@ -0,0 +1,54 @@
+The controls for the mux are GPIO [0,1] for source, and GPIO 2 for muting.
+
+GPIO0 GPIO1
+ 0 0 TV Audio
+ 1 0 FM radio
+ 0 1 Line-In
+ 1 1 Mono tuner bypass or CD passthru (tuner specific)
+
+GPIO 16(i believe) is tied to the IR port (if present).
+
+------------------------------------------------------------------------------------
+
+>From the data sheet:
+ Register 24'h20004 PCI Interrupt Status
+ bit [18] IR_SMP_INT Set when 32 input samples have been collected over
+ gpio[16] pin into GP_SAMPLE register.
+
+What's missing from the data sheet:
+
+Setup 4KHz sampling rate (roughly 2x oversampled; good enough for our RC5
+compat remote)
+set register 0x35C050 to 0xa80a80
+
+enable sampling
+set register 0x35C054 to 0x5
+
+Of course, enable the IRQ bit 18 in the interrupt mask register .(and
+provide for a handler)
+
+GP_SAMPLE register is at 0x35C058
+
+Bits are then right shifted into the GP_SAMPLE register at the specified
+rate; you get an interrupt when a full DWORD is recieved.
+You need to recover the actual RC5 bits out of the (oversampled) IR sensor
+bits. (Hint: look for the 0/1and 1/0 crossings of the RC5 bi-phase data) An
+actual raw RC5 code will span 2-3 DWORDS, depending on the actual alignment.
+
+I'm pretty sure when no IR signal is present the receiver is always in a
+marking state(1); but stray light, etc can cause intermittent noise values
+as well. Remember, this is a free running sample of the IR receiver state
+over time, so don't assume any sample starts at any particular place.
+
+http://www.atmel.com/dyn/resources/prod_documents/doc2817.pdf
+This data sheet (google search) seems to have a lovely description of the
+RC5 basics
+
+http://users.pandora.be/nenya/electronics/rc5/ and more data
+
+http://www.ee.washington.edu/circuit_archive/text/ir_decode.txt
+and even a reference to how to decode a bi-phase data stream.
+
+http://www.xs4all.nl/~sbp/knowledge/ir/rc5.htm
+still more info
+
diff --git a/Documentation/video4linux/lifeview.txt b/Documentation/video4linux/lifeview.txt
new file mode 100644
index 00000000000..b07ea79c2b7
--- /dev/null
+++ b/Documentation/video4linux/lifeview.txt
@@ -0,0 +1,42 @@
+collecting data about the lifeview models and the config coding on
+gpio pins 0-9 ...
+==================================================================
+
+bt878:
+ LR50 rev. Q ("PARTS: 7031505116), Tuner wurde als Nr. 5 erkannt, Eingänge
+ SVideo, TV, Composite, Audio, Remote. CP9..1=100001001 (1: 0-Ohm-Widerstand
+ gegen GND unbestückt; 0: bestückt)
+
+------------------------------------------------------------------------------
+
+saa7134:
+ /* LifeView FlyTV Platinum FM (LR214WF) */
+ /* "Peter Missel <peter.missel@onlinehome.de> */
+ .name = "LifeView FlyTV Platinum FM",
+ /* GP27 MDT2005 PB4 pin 10 */
+ /* GP26 MDT2005 PB3 pin 9 */
+ /* GP25 MDT2005 PB2 pin 8 */
+ /* GP23 MDT2005 PB1 pin 7 */
+ /* GP22 MDT2005 PB0 pin 6 */
+ /* GP21 MDT2005 PB5 pin 11 */
+ /* GP20 MDT2005 PB6 pin 12 */
+ /* GP19 MDT2005 PB7 pin 13 */
+ /* nc MDT2005 PA3 pin 2 */
+ /* Remote MDT2005 PA2 pin 1 */
+ /* GP18 MDT2005 PA1 pin 18 */
+ /* nc MDT2005 PA0 pin 17 strap low */
+
+ /* GP17 Strap "GP7"=High */
+ /* GP16 Strap "GP6"=High
+ 0=Radio 1=TV
+ Drives SA630D ENCH1 and HEF4052 A1 pins
+ to do FM radio through SIF input */
+ /* GP15 nc */
+ /* GP14 nc */
+ /* GP13 nc */
+ /* GP12 Strap "GP5" = High */
+ /* GP11 Strap "GP4" = High */
+ /* GP10 Strap "GP3" = High */
+ /* GP09 Strap "GP2" = Low */
+ /* GP08 Strap "GP1" = Low */
+ /* GP07.00 nc */
diff --git a/Documentation/video4linux/not-in-cx2388x-datasheet.txt b/Documentation/video4linux/not-in-cx2388x-datasheet.txt
new file mode 100644
index 00000000000..96b638b5ba1
--- /dev/null
+++ b/Documentation/video4linux/not-in-cx2388x-datasheet.txt
@@ -0,0 +1,37 @@
+=================================================================================
+MO_OUTPUT_FORMAT (0x310164)
+
+ Previous default from DScaler: 0x1c1f0008
+ Digit 8: 31-28
+ 28: PREVREMOD = 1
+
+ Digit 7: 27-24 (0xc = 12 = b1100 )
+ 27: COMBALT = 1
+ 26: PAL_INV_PHASE
+ (DScaler apparently set this to 1, resulted in sucky picture)
+
+ Digits 6,5: 23-16
+ 25-16: COMB_RANGE = 0x1f [default] (9 bits -> max 512)
+
+ Digit 4: 15-12
+ 15: DISIFX = 0
+ 14: INVCBF = 0
+ 13: DISADAPT = 0
+ 12: NARROWADAPT = 0
+
+ Digit 3: 11-8
+ 11: FORCE2H
+ 10: FORCEREMD
+ 9: NCHROMAEN
+ 8: NREMODEN
+
+ Digit 2: 7-4
+ 7-6: YCORE
+ 5-4: CCORE
+
+ Digit 1: 3-0
+ 3: RANGE = 1
+ 2: HACTEXT
+ 1: HSFMT
+
+=================================================================================
diff --git a/Documentation/w1/w1.generic b/Documentation/w1/w1.generic
index eace3046a85..f937fbe1cac 100644
--- a/Documentation/w1/w1.generic
+++ b/Documentation/w1/w1.generic
@@ -1,19 +1,92 @@
-Any w1 device must be connected to w1 bus master device - for example
-ds9490 usb device or w1-over-GPIO or RS232 converter.
-Driver for w1 bus master must provide several functions(you can find
-them in struct w1_bus_master definition in w1.h) which then will be
-called by w1 core to send various commands over w1 bus(by default it is
-reset and search commands). When some device is found on the bus, w1 core
-checks if driver for it's family is loaded.
-If driver is loaded w1 core creates new w1_slave object and registers it
-in the system(creates some generic sysfs files(struct w1_family_ops in
-w1_family.h), notifies any registered listener and so on...).
-It is device driver's business to provide any communication method
-upstream.
-For example w1_therm driver(ds18?20 thermal sensor family driver)
-provides temperature reading function which is bound to ->rbin() method
-of the above w1_family_ops structure.
-w1_smem - driver for simple 64bit memory cell provides ID reading
-method.
+The 1-wire (w1) subsystem
+------------------------------------------------------------------
+The 1-wire bus is a simple master-slave bus that communicates via a single
+signal wire (plus ground, so two wires).
+
+Devices communicate on the bus by pulling the signal to ground via an open
+drain output and by sampling the logic level of the signal line.
+
+The w1 subsystem provides the framework for managing w1 masters and
+communication with slaves.
+
+All w1 slave devices must be connected to a w1 bus master device.
+
+Example w1 master devices:
+ DS9490 usb device
+ W1-over-GPIO
+ DS2482 (i2c to w1 bridge)
+ Emulated devices, such as a RS232 converter, parallel port adapter, etc
+
+
+What does the w1 subsystem do?
+------------------------------------------------------------------
+When a w1 master driver registers with the w1 subsystem, the following occurs:
+
+ - sysfs entries for that w1 master are created
+ - the w1 bus is periodically searched for new slave devices
+
+When a device is found on the bus, w1 core checks if driver for it's family is
+loaded. If so, the family driver is attached to the slave.
+If there is no driver for the family, a simple sysfs entry is created
+for the slave device.
+
+
+W1 device families
+------------------------------------------------------------------
+Slave devices are handled by a driver written for a family of w1 devices.
+
+A family driver populates a struct w1_family_ops (see w1_family.h) and
+registers with the w1 subsystem.
+
+Current family drivers:
+w1_therm - (ds18?20 thermal sensor family driver)
+ provides temperature reading function which is bound to ->rbin() method
+ of the above w1_family_ops structure.
+
+w1_smem - driver for simple 64bit memory cell provides ID reading method.
You can call above methods by reading appropriate sysfs files.
+
+
+What does a w1 master driver need to implement?
+------------------------------------------------------------------
+
+The driver for w1 bus master must provide at minimum two functions.
+
+Emulated devices must provide the ability to set the output signal level
+(write_bit) and sample the signal level (read_bit).
+
+Devices that support the 1-wire natively must provide the ability to write and
+sample a bit (touch_bit) and reset the bus (reset_bus).
+
+Most hardware provides higher-level functions that offload w1 handling.
+See struct w1_bus_master definition in w1.h for details.
+
+
+w1 master sysfs interface
+------------------------------------------------------------------
+<xx-xxxxxxxxxxxxx> - a directory for a found device. The format is family-serial
+bus - (standard) symlink to the w1 bus
+driver - (standard) symlink to the w1 driver
+w1_master_attempts - the number of times a search was attempted
+w1_master_max_slave_count
+ - the maximum slaves that may be attached to a master
+w1_master_name - the name of the device (w1_bus_masterX)
+w1_master_search - the number of searches left to do, -1=continual (default)
+w1_master_slave_count
+ - the number of slaves found
+w1_master_slaves - the names of the slaves, one per line
+w1_master_timeout - the delay in seconds between searches
+
+If you have a w1 bus that never changes (you don't add or remove devices),
+you can set w1_master_search to a positive value to disable searches.
+
+
+w1 slave sysfs interface
+------------------------------------------------------------------
+bus - (standard) symlink to the w1 bus
+driver - (standard) symlink to the w1 driver
+name - the device name, usually the same as the directory name
+w1_slave - (optional) a binary file whose meaning depends on the
+ family driver
+
diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt
index 44b6eea60ec..b9e6be00cad 100644
--- a/Documentation/x86_64/boot-options.txt
+++ b/Documentation/x86_64/boot-options.txt
@@ -25,6 +25,9 @@ APICs
noapictimer Don't set up the APIC timer
+ no_timer_check Don't check the IO-APIC timer. This can work around
+ problems with incorrect timer initialization on some boards.
+
Early Console
syntax: earlyprintk=vga
diff --git a/MAINTAINERS b/MAINTAINERS
index 5b8483334de..a0b0d595d17 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -73,7 +73,7 @@ S: Status, one of the following:
3C359 NETWORK DRIVER
P: Mike Phillips
M: mikep@linuxtr.net
-L: netdev@oss.sgi.com
+L: netdev@vger.kernel.org
L: linux-tr@linuxtr.net
W: http://www.linuxtr.net
S: Maintained
@@ -81,13 +81,13 @@ S: Maintained
3C505 NETWORK DRIVER
P: Philip Blundell
M: philb@gnu.org
-L: netdev@oss.sgi.com
+L: netdev@vger.kernel.org
S: Maintained
3CR990 NETWORK DRIVER
P: David Dillow
M: dave@thedillows.org
-L: netdev@oss.sgi.com
+L: netdev@vger.kernel.org
S: Maintained
3W-XXXX ATA-RAID CONTROLLER DRIVER
@@ -130,7 +130,7 @@ S: Maintained
8169 10/100/1000 GIGABIT ETHERNET DRIVER
P: Francois Romieu
M: romieu@fr.zoreil.com
-L: netdev@oss.sgi.com
+L: netdev@vger.kernel.org
S: Maintained
8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
@@ -143,7 +143,7 @@ S: Maintained
8390 NETWORK DRIVERS [WD80x3/SMC-ELITE, SMC-ULTRA, NE2000, 3C503, etc.]
P: Paul Gortmaker
M: p_gortmaker@yahoo.com
-L: netdev@oss.sgi.com
+L: netdev@vger.kernel.org
S: Maintained
A2232 SERIAL BOARD DRIVER
@@ -194,7 +194,7 @@ S: Maintained
ADM1025 HARDWARE MONITOR DRIVER
P: Jean Delvare
M: khali@linux-fr.org
-L: sensors@stimpy.netroedge.com
+L: lm-sensors@lm-sensors.org
S: Maintained
ADT746X FAN DRIVER
@@ -239,6 +239,12 @@ L: linux-usb-devel@lists.sourceforge.net
W: http://www.linux-usb.org/SpeedTouch/
S: Maintained
+ALI1563 I2C DRIVER
+P: Rudolf Marek
+M: r.marek@sh.cvut.cz
+L: lm-sensors@lm-sensors.org
+S: Maintained
+
ALPHA PORT
P: Richard Henderson
M: rth@twiddle.net
@@ -259,6 +265,11 @@ P: Arnaldo Carvalho de Melo
M: acme@conectiva.com.br
S: Maintained
+ARC FRAMEBUFFER DRIVER
+P: Jaya Kumar
+M: jayalk@intworks.biz
+S: Maintained
+
ARM26 ARCHITECTURE
P: Ian Molton
M: spyro@f2s.com
@@ -293,7 +304,7 @@ S: Maintained
ARM/PT DIGITAL BOARD PORT
P: Stefan Eletzhofer
M: stefan.eletzhofer@eletztrick.de
-L: linux-arm-kernel@lists.arm.linux.org.uk
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
W: http://www.arm.linux.org.uk/
S: Maintained
@@ -306,27 +317,27 @@ S: Maintained
ARM/STRONGARM110 PORT
P: Russell King
M: rmk@arm.linux.org.uk
-L: linux-arm-kernel@lists.arm.linux.org.uk
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
W: http://www.arm.linux.org.uk/
S: Maintained
ARM/S3C2410 ARM ARCHITECTURE
P: Ben Dooks
M: ben-s3c2410@fluff.org
-L: linux-arm-kernel@lists.arm.linux.org.uk
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
W: http://www.fluff.org/ben/linux/
S: Maintained
ARM/S3C2440 ARM ARCHITECTURE
P: Ben Dooks
M: ben-s3c2440@fluff.org
-L: linux-arm-kernel@lists.arm.linux.org.uk
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
W: http://www.fluff.org/ben/linux/
S: Maintained
ARPD SUPPORT
P: Jonathan Layes
-L: netdev@oss.sgi.com
+L: netdev@vger.kernel.org
S: Maintained
ASUS ACPI EXTRAS DRIVER
@@ -493,6 +504,13 @@ L: bonding-devel@lists.sourceforge.net
W: http://sourceforge.net/projects/bonding/
S: Supported
+BROADBAND PROCESSOR ARCHITECTURE
+P: Arnd Bergmann
+M: arnd@arndb.de
+L: linuxppc64-dev@ozlabs.org
+W: http://linuxppc64.org
+S: Supported
+
BTTV VIDEO4LINUX DRIVER
P: Gerd Knorr
M: kraxel@bytesex.org
@@ -558,10 +576,9 @@ S: Supported
COMPUTONE INTELLIPORT MULTIPORT CARD
P: Michael H. Warfield
-M: Michael H. Warfield <mhw@wittsend.com>
+M: mhw@wittsend.com
W: http://www.wittsend.com/computone.html
-L: linux-computone@lazuli.wittsend.com
-S: Orphaned
+S: Maintained
COSA/SRP SYNC SERIAL DRIVER
P: Jan "Yenya" Kasprzak
@@ -700,7 +717,7 @@ S: Orphaned
DIGI RIGHTSWITCH NETWORK DRIVER
P: Rick Richardson
-L: netdev@oss.sgi.com
+L: netdev@vger.kernel.org
W: http://www.digi.com
S: Orphaned
@@ -730,6 +747,11 @@ M: tori@unhappy.mine.nu
L: linux-kernel@vger.kernel.org
S: Maintained
+DOCBOOK FOR DOCUMENTATION
+P: Martin Waitz
+M: tali@admingilde.org
+S: Maintained
+
DOUBLETALK DRIVER
P: James R. Van Zandt
M: jrv@vanzandt.mv.com
@@ -806,7 +828,7 @@ S: Maintained
ETHEREXPRESS-16 NETWORK DRIVER
P: Philip Blundell
M: philb@gnu.org
-L: netdev@oss.sgi.com
+L: netdev@vger.kernel.org
S: Maintained
ETHERNET BRIDGE
@@ -869,7 +891,7 @@ S: Maintained
FRAME RELAY DLCI/FRAD (Sangoma drivers too)
P: Mike McLagan
M: mike.mclagan@linux.org
-L: netdev@oss.sgi.com
+L: netdev@vger.kernel.org
S: Maintained
FREEVXFS FILESYSTEM
@@ -986,7 +1008,7 @@ P: Greg Kroah-Hartman
M: greg@kroah.com
P: Jean Delvare
M: khali@linux-fr.org
-L: sensors@stimpy.netroedge.com
+L: lm-sensors@lm-sensors.org
W: http://www.lm-sensors.nu/
S: Maintained
@@ -1023,8 +1045,8 @@ W: http://www.ia64-linux.org/
S: Maintained
SN-IA64 (Itanium) SUB-PLATFORM
-P: Jesse Barnes
-M: jbarnes@sgi.com
+P: Greg Edwards
+M: edwardsg@sgi.com
L: linux-altix@sgi.com
L: linux-ia64@vger.kernel.org
W: http://www.sgi.com/altix
@@ -1209,7 +1231,7 @@ S: Maintained
IPX NETWORK LAYER
P: Arnaldo Carvalho de Melo
M: acme@conectiva.com.br
-L: netdev@oss.sgi.com
+L: netdev@vger.kernel.org
S: Maintained
IRDA SUBSYSTEM
@@ -1307,6 +1329,16 @@ M: rml@novell.com
L: linux-kernel@vger.kernel.org
S: Maintained
+KEXEC
+P: Eric Biederman
+P: Randy Dunlap
+M: ebiederm@xmission.com
+M: rddunlap@osdl.org
+W: http://www.xmission.com/~ebiederm/files/kexec/
+L: linux-kernel@vger.kernel.org
+L: fastboot@osdl.org
+S: Maintained
+
LANMEDIA WAN CARD DRIVER
P: Andrew Stanley-Jones
M: asj@lanmedia.com
@@ -1414,13 +1446,13 @@ S: Supported
LM83 HARDWARE MONITOR DRIVER
P: Jean Delvare
M: khali@linux-fr.org
-L: sensors@stimpy.netroedge.com
+L: lm-sensors@lm-sensors.org
S: Maintained
LM90 HARDWARE MONITOR DRIVER
P: Jean Delvare
M: khali@linux-fr.org
-L: sensors@stimpy.netroedge.com
+L: lm-sensors@lm-sensors.org
S: Maintained
LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP Dynamic Disks)
@@ -1476,7 +1508,7 @@ MARVELL MV64340 ETHERNET DRIVER
P: Manish Lachwani
M: Manish_Lachwani@pmc-sierra.com
L: linux-mips@linux-mips.org
-L: netdev@oss.sgi.com
+L: netdev@vger.kernel.org
S: Supported
MATROX FRAMEBUFFER DRIVER
@@ -1586,13 +1618,13 @@ P: Andrew Morton
M: akpm@osdl.org
P: Jeff Garzik
M: jgarzik@pobox.com
-L: netdev@oss.sgi.com
+L: netdev@vger.kernel.org
S: Maintained
NETWORKING [GENERAL]
P: Networking Team
-M: netdev@oss.sgi.com
-L: netdev@oss.sgi.com
+M: netdev@vger.kernel.org
+L: netdev@vger.kernel.org
S: Maintained
NETWORKING [IPv4/IPv6]
@@ -1608,7 +1640,7 @@ P: Hideaki YOSHIFUJI
M: yoshfuji@linux-ipv6.org
P: Patrick McHardy
M: kaber@coreworks.de
-L: netdev@oss.sgi.com
+L: netdev@vger.kernel.org
S: Maintained
IPVS
@@ -1628,7 +1660,7 @@ NI5010 NETWORK DRIVER
P: Jan-Pascal van Best and Andreas Mohr
M: Jan-Pascal van Best <jvbest@qv3pluto.leidenuniv.nl>
M: Andreas Mohr <100.30936@germany.net>
-L: netdev@oss.sgi.com
+L: netdev@vger.kernel.org
S: Maintained
NINJA SCSI-3 / NINJA SCSI-32Bi (16bit/CardBus) PCMCIA SCSI HOST ADAPTER DRIVER
@@ -1670,7 +1702,7 @@ P: Peter De Shrijver
M: p2@ace.ulyssis.student.kuleuven.ac.be
P: Mike Phillips
M: mikep@linuxtr.net
-L: netdev@oss.sgi.com
+L: netdev@vger.kernel.org
L: linux-tr@linuxtr.net
W: http://www.linuxtr.net
S: Maintained
@@ -1777,7 +1809,7 @@ S: Unmaintained
PCNET32 NETWORK DRIVER
P: Thomas Bogendörfer
M: tsbogend@alpha.franken.de
-L: netdev@oss.sgi.com
+L: netdev@vger.kernel.org
S: Maintained
PHRAM MTD DRIVER
@@ -1789,7 +1821,7 @@ S: Maintained
POSIX CLOCKS and TIMERS
P: George Anzinger
M: george@mvista.com
-L: netdev@oss.sgi.com
+L: netdev@vger.kernel.org
S: Supported
PNP SUPPORT
@@ -1824,7 +1856,7 @@ S: Supported
PRISM54 WIRELESS DRIVER
P: Prism54 Development Team
M: prism54-private@prism54.org
-L: netdev@oss.sgi.com
+L: netdev@vger.kernel.org
W: http://prism54.org
S: Maintained
@@ -1837,7 +1869,7 @@ S: Maintained
PXA2xx SUPPORT
P: Nicolas Pitre
M: nico@cam.org
-L: linux-arm-kernel@lists.arm.linux.org.uk
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
S: Maintained
QLOGIC QLA2XXX FC-SCSI DRIVER
@@ -2041,7 +2073,7 @@ SIS 900/7016 FAST ETHERNET DRIVER
P: Daniele Venzano
M: venza@brownhat.org
W: http://www.brownhat.org/sis900.html
-L: netdev@oss.sgi.com
+L: netdev@vger.kernel.org
S: Maintained
SIS FRAMEBUFFER DRIVER
@@ -2059,7 +2091,7 @@ S: Maintained
SMSC47M1 HARDWARE MONITOR DRIVER
P: Jean Delvare
M: khali@linux-fr.org
-L: sensors@stimpy.netroedge.com
+L: lm-sensors@lm-sensors.org
S: Odd Fixes
SMB FILESYSTEM
@@ -2092,15 +2124,13 @@ S: Maintained
SOFTWARE SUSPEND:
P: Pavel Machek
M: pavel@suse.cz
-M: pavel@ucw.cz
-L: http://lister.fornax.hu/mailman/listinfo/swsusp
-W: http://swsusp.sf.net/
+L: linux-pm@osdl.org
S: Maintained
SONIC NETWORK DRIVER
P: Thomas Bogendoerfer
M: tsbogend@alpha.franken.de
-L: netdev@oss.sgi.com
+L: netdev@vger.kernel.org
S: Maintained
SONY VAIO CONTROL DEVICE DRIVER
@@ -2122,6 +2152,11 @@ W: http://tpmdd.sourceforge.net
L: tpmdd-devel@lists.sourceforge.net
S: Maintained
+TENSILICA XTENSA PORT (xtensa):
+P: Chris Zankel
+M: chris@zankel.net
+S: Maintained
+
UltraSPARC (sparc64):
P: David S. Miller
M: davem@davemloft.net
@@ -2139,7 +2174,7 @@ SHARP LH SUPPORT (LH7952X & LH7A40X)
P: Marc Singer
M: elf@buici.com
W: http://projects.buici.com/arm
-L: linux-arm-kernel@lists.arm.linux.org.uk
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
S: Maintained
SPARC (sparc32):
@@ -2157,7 +2192,7 @@ S: Supported
SPX NETWORK LAYER
P: Jay Schulist
M: jschlst@samba.org
-L: netdev@oss.sgi.com
+L: netdev@vger.kernel.org
S: Supported
SRM (Alpha) environment access
@@ -2236,7 +2271,7 @@ S: Maintained
TOKEN-RING NETWORK DRIVER
P: Mike Phillips
M: mikep@linuxtr.net
-L: netdev@oss.sgi.com
+L: netdev@vger.kernel.org
L: linux-tr@linuxtr.net
W: http://www.linuxtr.net
S: Maintained
@@ -2566,7 +2601,7 @@ M: davidm@snapgear.com
P: D. Jeff Dionne (created first uClinux port)
M: jeff@uclinux.org
W: http://www.uclinux.org/
-L: uclinux-dev@uclinux.org
+L: uclinux-dev@uclinux.org (subscribers-only)
S: Maintained
UCLINUX FOR NEC V850
@@ -2598,7 +2633,7 @@ S: Orphan
W1 DALLAS'S 1-WIRE BUS
P: Evgeniy Polyakov
M: johnpol@2ka.mipt.ru
-L: sensors@stimpy.netroedge.com
+L: lm-sensors@lm-sensors.org
S: Maintained
W83L51xD SD/MMC CARD INTERFACE DRIVER
@@ -2611,7 +2646,7 @@ S: Maintained
W83L785TS HARDWARE MONITOR DRIVER
P: Jean Delvare
M: khali@linux-fr.org
-L: sensors@stimpy.netroedge.com
+L: lm-sensors@lm-sensors.org
S: Odd Fixes
WAN ROUTER & SANGOMA WANPIPE DRIVERS & API (X.25, FRAME RELAY, PPP, CISCO HDLC)
diff --git a/Makefile b/Makefile
index bddcb861b49..1fdace757e1 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 12
-EXTRAVERSION =-rc4
+EXTRAVERSION =
NAME=Woozy Numbat
# *DOCUMENTATION*
@@ -281,7 +281,7 @@ export quiet Q KBUILD_VERBOSE
# See documentation in Documentation/kbuild/makefiles.txt
# cc-option
-# Usage: cflags-y += $(call gcc-option, -march=winchip-c6, -march=i586)
+# Usage: cflags-y += $(call cc-option, -march=winchip-c6, -march=i586)
cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
> /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
@@ -518,7 +518,7 @@ CFLAGS += $(call add-align,CONFIG_CC_ALIGN_LOOPS,-loops)
CFLAGS += $(call add-align,CONFIG_CC_ALIGN_JUMPS,-jumps)
ifdef CONFIG_FRAME_POINTER
-CFLAGS += -fno-omit-frame-pointer
+CFLAGS += -fno-omit-frame-pointer $(call cc-option,-fno-optimize-sibling-calls,)
else
CFLAGS += -fomit-frame-pointer
endif
@@ -530,7 +530,7 @@ endif
include $(srctree)/arch/$(ARCH)/Makefile
# arch Makefile may override CC so keep this after arch Makefile is included
-NOSTDINC_FLAGS := -nostdinc -isystem $(shell $(CC) -print-file-name=include)
+NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
CHECKFLAGS += $(NOSTDINC_FLAGS)
# warn about C99 declaration after statement
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index f7c96635d3b..c5739d6309d 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -509,7 +509,7 @@ config NR_CPUS
depends on SMP
default "64"
-config DISCONTIGMEM
+config ARCH_DISCONTIGMEM_ENABLE
bool "Discontiguous Memory Support (EXPERIMENTAL)"
depends on EXPERIMENTAL
help
@@ -518,6 +518,8 @@ config DISCONTIGMEM
or have huge holes in the physical address space for other reasons.
See <file:Documentation/vm/numa> for more.
+source "mm/Kconfig"
+
config NUMA
bool "NUMA Support (EXPERIMENTAL)"
depends on DISCONTIGMEM
diff --git a/arch/alpha/defconfig b/arch/alpha/defconfig
index 5e39b7a7c8f..6da9c3dbde4 100644
--- a/arch/alpha/defconfig
+++ b/arch/alpha/defconfig
@@ -96,7 +96,7 @@ CONFIG_ALPHA_CORE_AGP=y
CONFIG_ALPHA_BROKEN_IRQ_MASK=y
CONFIG_EISA=y
# CONFIG_SMP is not set
-# CONFIG_DISCONTIGMEM is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
CONFIG_VERBOSE_MCHECK=y
CONFIG_VERBOSE_MCHECK_ON=1
CONFIG_PCI_LEGACY_PROC=y
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 64e450dddb4..167fd89f870 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -1150,16 +1150,13 @@ osf_usleep_thread(struct timeval32 __user *sleep, struct timeval32 __user *remai
if (get_tv32(&tmp, sleep))
goto fault;
- ticks = tmp.tv_usec;
- ticks = (ticks + (1000000 / HZ) - 1) / (1000000 / HZ);
- ticks += tmp.tv_sec * HZ;
+ ticks = timeval_to_jiffies(&tmp);
current->state = TASK_INTERRUPTIBLE;
ticks = schedule_timeout(ticks);
if (remain) {
- tmp.tv_sec = ticks / HZ;
- tmp.tv_usec = ticks % HZ;
+ jiffies_to_timeval(ticks, &tmp);
if (put_tv32(remain, &tmp))
goto fault;
}
diff --git a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c
index ba81c4422aa..c7481d59b6d 100644
--- a/arch/alpha/mm/numa.c
+++ b/arch/alpha/mm/numa.c
@@ -327,8 +327,6 @@ void __init mem_init(void)
extern char _text, _etext, _data, _edata;
extern char __init_begin, __init_end;
unsigned long nid, i;
- struct page * lmem_map;
-
high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
reservedpages = 0;
@@ -338,10 +336,10 @@ void __init mem_init(void)
*/
totalram_pages += free_all_bootmem_node(NODE_DATA(nid));
- lmem_map = node_mem_map(nid);
pfn = NODE_DATA(nid)->node_start_pfn;
for (i = 0; i < node_spanned_pages(nid); i++, pfn++)
- if (page_is_ram(pfn) && PageReserved(lmem_map+i))
+ if (page_is_ram(pfn) &&
+ PageReserved(nid_page_nr(nid, i)))
reservedpages++;
}
@@ -373,18 +371,18 @@ show_mem(void)
show_free_areas();
printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
for_each_online_node(nid) {
- struct page * lmem_map = node_mem_map(nid);
i = node_spanned_pages(nid);
while (i-- > 0) {
+ struct page *page = nid_page_nr(nid, i);
total++;
- if (PageReserved(lmem_map+i))
+ if (PageReserved(page))
reserved++;
- else if (PageSwapCache(lmem_map+i))
+ else if (PageSwapCache(page))
cached++;
- else if (!page_count(lmem_map+i))
+ else if (!page_count(page))
free++;
else
- shared += page_count(lmem_map + i) - 1;
+ shared += page_count(page) - 1;
}
}
printk("%ld pages of RAM\n",total);
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index bf397a9f8ac..c8d94dcd8ef 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -67,10 +67,6 @@ config GENERIC_BUST_SPINLOCK
config GENERIC_ISA_DMA
bool
-config GENERIC_IOMAP
- bool
- default y
-
config FIQ
bool
@@ -161,7 +157,7 @@ config ARCH_RPC
config ARCH_SA1100
bool "SA1100-based"
select ISA
- select DISCONTIGMEM
+ select ARCH_DISCONTIGMEM_ENABLE
config ARCH_S3C2410
bool "Samsung S3C2410"
@@ -202,6 +198,11 @@ config ARCH_H720X
help
This enables support for systems based on the Hynix HMS720x
+config ARCH_AAEC2000
+ bool "Agilent AAEC-2000 based"
+ help
+ This enables support for systems based on the Agilent AAEC-2000
+
endchoice
source "arch/arm/mach-clps711x/Kconfig"
@@ -234,6 +235,8 @@ source "arch/arm/mach-h720x/Kconfig"
source "arch/arm/mach-versatile/Kconfig"
+source "arch/arm/mach-aaec2000/Kconfig"
+
# Definitions to make life easier
config ARCH_ACORN
bool
@@ -277,7 +280,7 @@ config ISA_DMA_API
default y
config PCI
- bool "PCI support" if ARCH_INTEGRATOR_AP
+ bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB
help
Find out whether you have a PCI motherboard. PCI is the name of a
bus system, i.e. the way the CPU talks to the other stuff inside
@@ -343,7 +346,22 @@ config PREEMPT
Say Y here if you are building a kernel for a desktop, embedded
or real-time system. Say N if you are unsure.
-config DISCONTIGMEM
+config NO_IDLE_HZ
+ bool "Dynamic tick timer"
+ help
+ Select this option if you want to disable continuous timer ticks
+ and have them programmed to occur as required. This option saves
+ power as the system can remain in idle state for longer.
+
+ By default dynamic tick is disabled during the boot, and can be
+ manually enabled with:
+
+ echo 1 > /sys/devices/system/timer/timer0/dyn_tick
+
+ Alternatively, if you want dynamic tick automatically enabled
+ during boot, pass "dyntick=enable" via the kernel command string.
+
+config ARCH_DISCONTIGMEM_ENABLE
bool
default (ARCH_LH7A40X && !LH7A40X_CONTIGMEM)
help
@@ -352,6 +370,8 @@ config DISCONTIGMEM
or have huge holes in the physical address space for other reasons.
See <file:Documentation/vm/numa> for more.
+source "mm/Kconfig"
+
config LEDS
bool "Timer and CPU usage LEDs"
depends on ARCH_CDB89712 || ARCH_CO285 || ARCH_EBSA110 || \
@@ -497,7 +517,7 @@ source "drivers/cpufreq/Kconfig"
config CPU_FREQ_SA1100
bool
- depends on CPU_FREQ && (SA1100_LART || SA1100_PLEB)
+ depends on CPU_FREQ && (SA1100_H3100 || SA1100_H3600 || SA1100_H3800 || SA1100_LART || SA1100_PLEB || SA1100_BADGE4 || SA1100_HACKKIT)
default y
config CPU_FREQ_SA1110
@@ -689,7 +709,9 @@ source "drivers/block/Kconfig"
source "drivers/acorn/block/Kconfig"
-if ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX || ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE
+if PCMCIA || ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX \
+ || ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \
+ || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE
source "drivers/ide/Kconfig"
endif
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 2277e3d179c..8330495e244 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -97,6 +97,7 @@ textaddr-$(CONFIG_ARCH_FORTUNET) := 0xc0008000
machine-$(CONFIG_ARCH_VERSATILE) := versatile
machine-$(CONFIG_ARCH_IMX) := imx
machine-$(CONFIG_ARCH_H720X) := h720x
+ machine-$(CONFIG_ARCH_AAEC2000) := aaec2000
ifeq ($(CONFIG_ARCH_EBSA110),y)
# This is what happens if you forget the IOCS16 line.
diff --git a/arch/arm/boot/compressed/head-xscale.S b/arch/arm/boot/compressed/head-xscale.S
index 665bd2c2074..d3fe2533907 100644
--- a/arch/arm/boot/compressed/head-xscale.S
+++ b/arch/arm/boot/compressed/head-xscale.S
@@ -47,3 +47,10 @@ __XScale_start:
orr r7, r7, #(MACH_TYPE_GTWX5715 & 0xff00)
#endif
+#ifdef CONFIG_ARCH_IXP2000
+ mov r1, #-1
+ mov r0, #0xd6000000
+ str r1, [r0, #0x14]
+ str r1, [r0, #0x18]
+#endif
+
diff --git a/arch/arm/boot/install.sh b/arch/arm/boot/install.sh
index 935bb27369e..9f9bed20734 100644
--- a/arch/arm/boot/install.sh
+++ b/arch/arm/boot/install.sh
@@ -21,8 +21,8 @@
#
# User may have a custom install script
-if [ -x ~/bin/installkernel ]; then exec ~/bin/installkernel "$@"; fi
-if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi
+if [ -x ~/bin/${CROSS_COMPILE}installkernel ]; then exec ~/bin/${CROSS_COMPILE}installkernel "$@"; fi
+if [ -x /sbin/${CROSS_COMPILE}installkernel ]; then exec /sbin/${CROSS_COMPILE}installkernel "$@"; fi
if [ "$(basename $2)" = "zImage" ]; then
# Compressed install
diff --git a/arch/arm/common/amba.c b/arch/arm/common/amba.c
index a0507f8c33f..c6beb751f2a 100644
--- a/arch/arm/common/amba.c
+++ b/arch/arm/common/amba.c
@@ -169,7 +169,7 @@ static void amba_device_release(struct device *dev)
}
#define amba_attr(name,fmt,arg...) \
-static ssize_t show_##name(struct device *_dev, char *buf) \
+static ssize_t show_##name(struct device *_dev, struct device_attribute *attr, char *buf) \
{ \
struct amba_device *dev = to_amba_device(_dev); \
return sprintf(buf, fmt, arg); \
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 5797b1b100a..cbf2165476b 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -30,6 +30,8 @@
#include <linux/dmapool.h>
#include <linux/list.h>
+#include <asm/cacheflush.h>
+
#undef DEBUG
#undef STATS
@@ -91,15 +93,12 @@ static void print_alloc_stats(struct dmabounce_device_info *device_info)
static inline struct dmabounce_device_info *
find_dmabounce_dev(struct device *dev)
{
- struct list_head *entry;
-
- list_for_each(entry, &dmabounce_devs) {
- struct dmabounce_device_info *d =
- list_entry(entry, struct dmabounce_device_info, node);
+ struct dmabounce_device_info *d;
+ list_for_each_entry(d, &dmabounce_devs, node)
if (d->dev == dev)
return d;
- }
+
return NULL;
}
@@ -170,15 +169,11 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr,
static inline struct safe_buffer *
find_safe_buffer(struct dmabounce_device_info *device_info, dma_addr_t safe_dma_addr)
{
- struct list_head *entry;
-
- list_for_each(entry, &device_info->safe_buffers) {
- struct safe_buffer *b =
- list_entry(entry, struct safe_buffer, node);
+ struct safe_buffer *b;
+ list_for_each_entry(b, &device_info->safe_buffers, node)
if (b->safe_dma_addr == safe_dma_addr)
return b;
- }
return NULL;
}
@@ -299,15 +294,26 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
__func__, buf->ptr, (void *) virt_to_dma(dev, buf->ptr),
buf->safe, (void *) buf->safe_dma_addr);
-
DO_STATS ( device_info->bounce_count++ );
- if ((dir == DMA_FROM_DEVICE) ||
- (dir == DMA_BIDIRECTIONAL)) {
+ if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) {
+ unsigned long ptr;
+
dev_dbg(dev,
"%s: copy back safe %p to unsafe %p size %d\n",
__func__, buf->safe, buf->ptr, size);
memcpy(buf->ptr, buf->safe, size);
+
+ /*
+ * DMA buffers must have the same cache properties
+ * as if they were really used for DMA - which means
+ * data must be written back to RAM. Note that
+ * we don't use dmac_flush_range() here for the
+ * bidirectional case because we know the cache
+ * lines will be coherent with the data written.
+ */
+ ptr = (unsigned long)buf->ptr;
+ dmac_clean_range(ptr, ptr + size);
}
free_safe_buffer(device_info, buf);
}
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 21fce3414ed..38c2eb667eb 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -721,16 +721,17 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq)
return ret;
}
+static int sa1111_remove_one(struct device *dev, void *data)
+{
+ device_unregister(dev);
+ return 0;
+}
+
static void __sa1111_remove(struct sa1111 *sachip)
{
- struct list_head *l, *n;
void __iomem *irqbase = sachip->base + SA1111_INTC;
- list_for_each_safe(l, n, &sachip->dev->children) {
- struct device *d = list_to_dev(l);
-
- device_unregister(d);
- }
+ device_for_each_child(sachip->dev, NULL, sa1111_remove_one);
/* disable all IRQs */
sa1111_writel(0, irqbase + SA1111_INTEN0);
diff --git a/arch/arm/common/sharpsl_param.c b/arch/arm/common/sharpsl_param.c
index c2c557a224c..c94864c5b1a 100644
--- a/arch/arm/common/sharpsl_param.c
+++ b/arch/arm/common/sharpsl_param.c
@@ -22,7 +22,7 @@
* them early in the boot process, then pass them to the appropriate drivers.
* Not all devices use all paramaters but the format is common to all.
*/
-#ifdef ARCH_SA1100
+#ifdef CONFIG_ARCH_SA1100
#define PARAM_BASE 0xe8ffc000
#else
#define PARAM_BASE 0xa0000a00
diff --git a/arch/arm/configs/badge4_defconfig b/arch/arm/configs/badge4_defconfig
index 2b4059d2f8e..5d92af975d8 100644
--- a/arch/arm/configs/badge4_defconfig
+++ b/arch/arm/configs/badge4_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sat Mar 26 21:32:26 2005
+# Linux kernel version: 2.6.12-rc6-git3
+# Thu Jun 9 19:00:50 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
@@ -16,6 +16,7 @@ CONFIG_GENERIC_IOMAP=y
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -34,6 +35,8 @@ CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
@@ -109,7 +112,6 @@ CONFIG_CPU_ABRT_EV4=y
CONFIG_CPU_CACHE_V4WB=y
CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_TLB_V4WB=y
-CONFIG_CPU_MINICACHE=y
#
# Processor Features
@@ -122,6 +124,7 @@ CONFIG_FORCE_MAX_ZONEORDER=9
# Bus support
#
CONFIG_ISA=y
+CONFIG_ISA_DMA_API=y
#
# PCCARD (PCMCIA/CardBus) support
@@ -131,6 +134,7 @@ CONFIG_ISA=y
#
# Kernel Features
#
+# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
CONFIG_DISCONTIGMEM=y
# CONFIG_LEDS is not set
@@ -152,12 +156,14 @@ CONFIG_CPU_FREQ_TABLE=y
# CONFIG_CPU_FREQ_DEBUG is not set
CONFIG_CPU_FREQ_STAT=y
# CONFIG_CPU_FREQ_STAT_DETAILS is not set
-CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
-# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
-# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_SA1100=y
#
# Floating point emulation
@@ -294,7 +300,6 @@ CONFIG_PARPORT_NOT_PC=y
#
# Block devices
#
-# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
# CONFIG_PARIDE is not set
# CONFIG_BLK_DEV_COW_COMMON is not set
@@ -428,7 +433,6 @@ CONFIG_NET=y
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
@@ -526,6 +530,7 @@ CONFIG_IRDA_ULTRA=y
# CONFIG_SMC_IRCC_FIR is not set
# CONFIG_ALI_FIR is not set
CONFIG_SA1100_FIR=y
+# CONFIG_VIA_FIR is not set
CONFIG_BT=m
CONFIG_BT_L2CAP=m
# CONFIG_BT_SCO is not set
@@ -618,7 +623,6 @@ CONFIG_NET_WIRELESS=y
#
# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
#
# Character devices
@@ -687,7 +691,6 @@ CONFIG_RTC=m
#
# TPM devices
#
-# CONFIG_TCG_TPM is not set
#
# I2C support
@@ -736,6 +739,7 @@ CONFIG_I2C_ELEKTOR=m
# CONFIG_SENSORS_LM85 is not set
# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
@@ -747,6 +751,7 @@ CONFIG_I2C_ELEKTOR=m
#
# Other I2C Chip support
#
+# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCF8591 is not set
@@ -871,7 +876,6 @@ CONFIG_USB_PRINTER=m
#
CONFIG_USB_STORAGE=y
CONFIG_USB_STORAGE_DEBUG=y
-# CONFIG_USB_STORAGE_RW_DETECT is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
@@ -954,9 +958,11 @@ CONFIG_USB_USS720=m
#
CONFIG_USB_SERIAL=m
CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRPRIME is not set
CONFIG_USB_SERIAL_BELKIN=m
CONFIG_USB_SERIAL_WHITEHEAT=m
CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+# CONFIG_USB_SERIAL_CP2101 is not set
# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
CONFIG_USB_SERIAL_EMPEG=m
CONFIG_USB_SERIAL_FTDI_SIO=m
@@ -985,6 +991,7 @@ CONFIG_USB_SERIAL_KEYSPAN=m
# CONFIG_USB_SERIAL_KOBIL_SCT is not set
CONFIG_USB_SERIAL_MCT_U232=m
CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_HP4X is not set
# CONFIG_USB_SERIAL_SAFE is not set
# CONFIG_USB_SERIAL_TI is not set
CONFIG_USB_SERIAL_CYBERJACK=m
diff --git a/arch/arm/configs/enp2611_defconfig b/arch/arm/configs/enp2611_defconfig
index e8f9fccffe8..b8c51ee7f1b 100644
--- a/arch/arm/configs/enp2611_defconfig
+++ b/arch/arm/configs/enp2611_defconfig
@@ -1,14 +1,13 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sun Mar 27 22:08:24 2005
+# Linux kernel version: 2.6.12-git6
+# Sat Jun 25 00:57:29 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
@@ -16,6 +15,7 @@ CONFIG_GENERIC_IOMAP=y
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -35,6 +35,8 @@ CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
@@ -50,7 +52,13 @@ CONFIG_BASE_SMALL=0
#
# Loadable module support
#
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
#
# System Type
@@ -76,6 +84,7 @@ CONFIG_ARCH_IXP2000=y
# CONFIG_ARCH_VERSATILE is not set
# CONFIG_ARCH_IMX is not set
# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
#
@@ -90,6 +99,7 @@ CONFIG_ARCH_ENP2611=y
# CONFIG_ARCH_IXDP2800 is not set
# CONFIG_ARCH_IXDP2401 is not set
# CONFIG_ARCH_IXDP2801 is not set
+# CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO is not set
#
# Processor Type
@@ -100,7 +110,6 @@ CONFIG_CPU_32v5=y
CONFIG_CPU_ABRT_EV5T=y
CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_TLB_V4WBI=y
-CONFIG_CPU_MINICACHE=y
#
# Processor Features
@@ -112,9 +121,11 @@ CONFIG_XSCALE_PMU=y
#
# Bus support
#
+CONFIG_ISA_DMA_API=y
CONFIG_PCI=y
CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
@@ -124,7 +135,15 @@ CONFIG_PCI_NAMES=y
#
# Kernel Features
#
+# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_ALIGNMENT_TRAP=y
#
@@ -263,7 +282,6 @@ CONFIG_MTD_IXP2000=y
#
# Block devices
#
-# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
@@ -302,6 +320,7 @@ CONFIG_IOSCHED_CFQ=y
#
# Fusion MPT device support
#
+# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
@@ -323,10 +342,11 @@ CONFIG_NET=y
#
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_PNP=y
@@ -343,6 +363,17 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_TUNNEL is not set
# CONFIG_IP_TCPDIAG is not set
# CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
@@ -398,6 +429,7 @@ CONFIG_MII=y
# CONFIG_SUNGEM is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
#
# Tulip family network device support
@@ -434,9 +466,11 @@ CONFIG_EEPRO100=y
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
+# CONFIG_SKGE is not set
# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
#
# Ethernet (10000 Mbit)
@@ -458,6 +492,7 @@ CONFIG_EEPRO100=y
# Wan interfaces
#
CONFIG_WAN=y
+# CONFIG_DSCC4 is not set
# CONFIG_LANMEDIA is not set
# CONFIG_SYNCLINK_SYNCPPP is not set
CONFIG_HDLC=y
@@ -520,7 +555,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
#
# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
#
# Character devices
@@ -541,6 +575,7 @@ CONFIG_SERIAL_8250_NR_UARTS=2
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -607,17 +642,18 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_ISA is not set
# CONFIG_I2C_IXP2000 is not set
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
# CONFIG_SCx200_ACB is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
@@ -631,7 +667,9 @@ CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
# CONFIG_SENSORS_FSCPOS is not set
@@ -647,6 +685,7 @@ CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_LM85 is not set
# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
@@ -656,14 +695,19 @@ CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
#
# Other I2C Chip support
#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
CONFIG_SENSORS_EEPROM=y
# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -717,6 +761,7 @@ CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
@@ -757,7 +802,6 @@ CONFIG_DNOTIFY=y
#
CONFIG_PROC_FS=y
CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
# CONFIG_TMPFS_XATTR is not set
@@ -795,12 +839,14 @@ CONFIG_JFFS2_RTIME=y
#
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -885,3 +931,4 @@ CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
+# CONFIG_TEXTSEARCH is not set
diff --git a/arch/arm/configs/h3600_defconfig b/arch/arm/configs/h3600_defconfig
index b4e297dd54b..b9de07de80f 100644
--- a/arch/arm/configs/h3600_defconfig
+++ b/arch/arm/configs/h3600_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Mon Mar 28 00:02:26 2005
+# Linux kernel version: 2.6.12-rc4
+# Thu Jun 9 01:59:03 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
@@ -16,6 +16,7 @@ CONFIG_GENERIC_IOMAP=y
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -33,6 +34,8 @@ CONFIG_KOBJECT_UEVENT=y
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
@@ -120,6 +123,7 @@ CONFIG_CPU_MINICACHE=y
# Bus support
#
CONFIG_ISA=y
+CONFIG_ISA_DMA_API=y
#
# PCCARD (PCMCIA/CardBus) support
@@ -138,6 +142,7 @@ CONFIG_PCMCIA_SA1100=y
#
# Kernel Features
#
+# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
CONFIG_DISCONTIGMEM=y
# CONFIG_LEDS is not set
@@ -159,12 +164,13 @@ CONFIG_CPU_FREQ_TABLE=y
# CONFIG_CPU_FREQ_DEBUG is not set
CONFIG_CPU_FREQ_STAT=y
# CONFIG_CPU_FREQ_STAT_DETAILS is not set
-CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
-# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
-CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+# CONFIG_CPU_FREQ_GOV_PERFORMANCE is not set
# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
-# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
+CONFIG_CPU_FREQ_SA1100=y
#
# Floating point emulation
@@ -298,7 +304,6 @@ CONFIG_MTD_SA1100=y
#
# Block devices
#
-# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=m
@@ -379,7 +384,6 @@ CONFIG_NET=y
# Networking options
#
# CONFIG_PACKET is not set
-# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
@@ -476,6 +480,7 @@ CONFIG_IRCOMM=m
# CONFIG_SMC_IRCC_FIR is not set
# CONFIG_ALI_FIR is not set
CONFIG_SA1100_FIR=m
+# CONFIG_VIA_FIR is not set
# CONFIG_BT is not set
CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
@@ -647,7 +652,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# TPM devices
#
-# CONFIG_TCG_TPM is not set
#
# I2C support
@@ -676,9 +680,11 @@ CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
CONFIG_FB_SOFT_CURSOR=y
+# CONFIG_FB_MACMODES is not set
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
CONFIG_FB_SA1100=y
+# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
#
diff --git a/arch/arm/configs/hackkit_defconfig b/arch/arm/configs/hackkit_defconfig
index 6987c8c5ddb..fb41a36a5a6 100644
--- a/arch/arm/configs/hackkit_defconfig
+++ b/arch/arm/configs/hackkit_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Mon Mar 28 00:22:34 2005
+# Linux kernel version: 2.6.12-rc6-git3
+# Thu Jun 9 20:58:58 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
@@ -16,6 +16,7 @@ CONFIG_GENERIC_IOMAP=y
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -34,6 +35,8 @@ CONFIG_KOBJECT_UEVENT=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
@@ -109,7 +112,6 @@ CONFIG_CPU_ABRT_EV4=y
CONFIG_CPU_CACHE_V4WB=y
CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_TLB_V4WB=y
-CONFIG_CPU_MINICACHE=y
#
# Processor Features
@@ -119,6 +121,7 @@ CONFIG_CPU_MINICACHE=y
# Bus support
#
CONFIG_ISA=y
+CONFIG_ISA_DMA_API=y
#
# PCCARD (PCMCIA/CardBus) support
@@ -128,6 +131,7 @@ CONFIG_ISA=y
#
# Kernel Features
#
+# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
CONFIG_DISCONTIGMEM=y
CONFIG_LEDS=y
@@ -151,12 +155,14 @@ CONFIG_CPU_FREQ_TABLE=y
# CONFIG_CPU_FREQ_DEBUG is not set
CONFIG_CPU_FREQ_STAT=y
# CONFIG_CPU_FREQ_STAT_DETAILS is not set
-CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
-# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
-# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_SA1100=y
#
# Floating point emulation
@@ -280,7 +286,6 @@ CONFIG_MTD_CFI_UTIL=y
#
# Block devices
#
-# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_XD is not set
# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
@@ -338,7 +343,6 @@ CONFIG_NET=y
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
@@ -484,7 +488,6 @@ CONFIG_SERIO=y
CONFIG_SERIO_SERPORT=y
# CONFIG_SERIO_RAW is not set
# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
#
# Character devices
@@ -533,7 +536,6 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# TPM devices
#
-# CONFIG_TCG_TPM is not set
#
# I2C support
diff --git a/arch/arm/configs/ixdp2400_defconfig b/arch/arm/configs/ixdp2400_defconfig
index 4fd663ecbe3..3cfbe2ec29c 100644
--- a/arch/arm/configs/ixdp2400_defconfig
+++ b/arch/arm/configs/ixdp2400_defconfig
@@ -1,14 +1,13 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sun Mar 27 21:13:38 2005
+# Linux kernel version: 2.6.12-git6
+# Sat Jun 25 00:58:38 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
@@ -16,6 +15,7 @@ CONFIG_GENERIC_IOMAP=y
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -35,6 +35,8 @@ CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
@@ -50,7 +52,13 @@ CONFIG_BASE_SMALL=0
#
# Loadable module support
#
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
#
# System Type
@@ -76,6 +84,7 @@ CONFIG_ARCH_IXP2000=y
# CONFIG_ARCH_VERSATILE is not set
# CONFIG_ARCH_IMX is not set
# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
#
@@ -91,6 +100,7 @@ CONFIG_ARCH_IXDP2400=y
CONFIG_ARCH_IXDP2X00=y
# CONFIG_ARCH_IXDP2401 is not set
# CONFIG_ARCH_IXDP2801 is not set
+# CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO is not set
#
# Processor Type
@@ -101,7 +111,6 @@ CONFIG_CPU_32v5=y
CONFIG_CPU_ABRT_EV5T=y
CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_TLB_V4WBI=y
-CONFIG_CPU_MINICACHE=y
#
# Processor Features
@@ -113,9 +122,11 @@ CONFIG_XSCALE_PMU=y
#
# Bus support
#
+CONFIG_ISA_DMA_API=y
CONFIG_PCI=y
CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
@@ -125,7 +136,15 @@ CONFIG_PCI_NAMES=y
#
# Kernel Features
#
+# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_ALIGNMENT_TRAP=y
#
@@ -264,7 +283,6 @@ CONFIG_MTD_IXP2000=y
#
# Block devices
#
-# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
@@ -303,6 +321,7 @@ CONFIG_IOSCHED_CFQ=y
#
# Fusion MPT device support
#
+# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
@@ -324,10 +343,11 @@ CONFIG_NET=y
#
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_PNP=y
@@ -344,6 +364,17 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_TUNNEL is not set
# CONFIG_IP_TCPDIAG is not set
# CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
@@ -399,6 +430,7 @@ CONFIG_MII=y
# CONFIG_SUNGEM is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
#
# Tulip family network device support
@@ -435,9 +467,11 @@ CONFIG_EEPRO100=y
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
+# CONFIG_SKGE is not set
# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
#
# Ethernet (10000 Mbit)
@@ -459,6 +493,7 @@ CONFIG_EEPRO100=y
# Wan interfaces
#
CONFIG_WAN=y
+# CONFIG_DSCC4 is not set
# CONFIG_LANMEDIA is not set
# CONFIG_SYNCLINK_SYNCPPP is not set
CONFIG_HDLC=y
@@ -521,7 +556,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
#
# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
#
# Character devices
@@ -542,6 +576,7 @@ CONFIG_SERIAL_8250_NR_UARTS=2
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -608,17 +643,18 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_ISA is not set
# CONFIG_I2C_IXP2000 is not set
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
# CONFIG_SCx200_ACB is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
@@ -632,7 +668,9 @@ CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
# CONFIG_SENSORS_FSCPOS is not set
@@ -648,6 +686,7 @@ CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_LM85 is not set
# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
@@ -657,14 +696,19 @@ CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
#
# Other I2C Chip support
#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
CONFIG_SENSORS_EEPROM=y
# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -718,6 +762,7 @@ CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
@@ -758,7 +803,6 @@ CONFIG_DNOTIFY=y
#
CONFIG_PROC_FS=y
CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
# CONFIG_TMPFS_XATTR is not set
@@ -796,12 +840,14 @@ CONFIG_JFFS2_RTIME=y
#
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -886,3 +932,4 @@ CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
+# CONFIG_TEXTSEARCH is not set
diff --git a/arch/arm/configs/ixdp2401_defconfig b/arch/arm/configs/ixdp2401_defconfig
index 6f51c98084a..5c87e8e6969 100644
--- a/arch/arm/configs/ixdp2401_defconfig
+++ b/arch/arm/configs/ixdp2401_defconfig
@@ -1,14 +1,13 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sun Mar 27 21:53:55 2005
+# Linux kernel version: 2.6.12-git6
+# Sat Jun 25 00:59:35 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
@@ -16,6 +15,7 @@ CONFIG_GENERIC_IOMAP=y
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -35,6 +35,8 @@ CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
@@ -50,7 +52,13 @@ CONFIG_BASE_SMALL=0
#
# Loadable module support
#
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
#
# System Type
@@ -76,6 +84,7 @@ CONFIG_ARCH_IXP2000=y
# CONFIG_ARCH_VERSATILE is not set
# CONFIG_ARCH_IMX is not set
# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
#
@@ -91,6 +100,7 @@ CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
CONFIG_ARCH_IXDP2401=y
# CONFIG_ARCH_IXDP2801 is not set
CONFIG_ARCH_IXDP2X01=y
+# CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO is not set
#
# Processor Type
@@ -101,7 +111,6 @@ CONFIG_CPU_32v5=y
CONFIG_CPU_ABRT_EV5T=y
CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_TLB_V4WBI=y
-CONFIG_CPU_MINICACHE=y
#
# Processor Features
@@ -113,9 +122,11 @@ CONFIG_XSCALE_PMU=y
#
# Bus support
#
+CONFIG_ISA_DMA_API=y
CONFIG_PCI=y
CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
@@ -125,7 +136,15 @@ CONFIG_PCI_NAMES=y
#
# Kernel Features
#
+# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_ALIGNMENT_TRAP=y
#
@@ -264,7 +283,6 @@ CONFIG_MTD_IXP2000=y
#
# Block devices
#
-# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
@@ -303,6 +321,7 @@ CONFIG_IOSCHED_CFQ=y
#
# Fusion MPT device support
#
+# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
@@ -324,10 +343,11 @@ CONFIG_NET=y
#
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_PNP=y
@@ -344,6 +364,17 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_TUNNEL is not set
CONFIG_IP_TCPDIAG=y
# CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
@@ -399,6 +430,7 @@ CONFIG_MII=y
# CONFIG_SUNGEM is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
#
# Tulip family network device support
@@ -436,9 +468,11 @@ CONFIG_EEPRO100=y
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
+# CONFIG_SKGE is not set
# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
#
# Ethernet (10000 Mbit)
@@ -460,6 +494,7 @@ CONFIG_EEPRO100=y
# Wan interfaces
#
CONFIG_WAN=y
+# CONFIG_DSCC4 is not set
# CONFIG_LANMEDIA is not set
# CONFIG_SYNCLINK_SYNCPPP is not set
CONFIG_HDLC=y
@@ -522,7 +557,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
#
# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
#
# Character devices
@@ -543,6 +577,7 @@ CONFIG_SERIAL_8250_NR_UARTS=2
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -609,17 +644,18 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_ISA is not set
# CONFIG_I2C_IXP2000 is not set
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
# CONFIG_SCx200_ACB is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
@@ -633,7 +669,9 @@ CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
# CONFIG_SENSORS_FSCPOS is not set
@@ -649,6 +687,7 @@ CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_LM85 is not set
# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
@@ -658,14 +697,19 @@ CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
#
# Other I2C Chip support
#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
CONFIG_SENSORS_EEPROM=y
# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -719,6 +763,7 @@ CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
@@ -759,7 +804,6 @@ CONFIG_DNOTIFY=y
#
CONFIG_PROC_FS=y
CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
# CONFIG_TMPFS_XATTR is not set
@@ -797,12 +841,14 @@ CONFIG_JFFS2_RTIME=y
#
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -887,3 +933,4 @@ CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
+# CONFIG_TEXTSEARCH is not set
diff --git a/arch/arm/configs/ixdp2800_defconfig b/arch/arm/configs/ixdp2800_defconfig
index 7be3521f91f..3cb561a551c 100644
--- a/arch/arm/configs/ixdp2800_defconfig
+++ b/arch/arm/configs/ixdp2800_defconfig
@@ -1,14 +1,13 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sun Mar 27 22:15:23 2005
+# Linux kernel version: 2.6.12-git6
+# Sat Jun 25 01:00:27 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
@@ -16,6 +15,7 @@ CONFIG_GENERIC_IOMAP=y
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -35,6 +35,8 @@ CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
@@ -50,7 +52,13 @@ CONFIG_BASE_SMALL=0
#
# Loadable module support
#
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
#
# System Type
@@ -76,6 +84,7 @@ CONFIG_ARCH_IXP2000=y
# CONFIG_ARCH_VERSATILE is not set
# CONFIG_ARCH_IMX is not set
# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
#
@@ -91,6 +100,7 @@ CONFIG_ARCH_IXDP2800=y
CONFIG_ARCH_IXDP2X00=y
# CONFIG_ARCH_IXDP2401 is not set
# CONFIG_ARCH_IXDP2801 is not set
+# CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO is not set
#
# Processor Type
@@ -101,7 +111,6 @@ CONFIG_CPU_32v5=y
CONFIG_CPU_ABRT_EV5T=y
CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_TLB_V4WBI=y
-CONFIG_CPU_MINICACHE=y
#
# Processor Features
@@ -113,9 +122,11 @@ CONFIG_XSCALE_PMU=y
#
# Bus support
#
+CONFIG_ISA_DMA_API=y
CONFIG_PCI=y
CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
@@ -125,7 +136,15 @@ CONFIG_PCI_NAMES=y
#
# Kernel Features
#
+# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_ALIGNMENT_TRAP=y
#
@@ -264,7 +283,6 @@ CONFIG_MTD_IXP2000=y
#
# Block devices
#
-# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
@@ -303,6 +321,7 @@ CONFIG_IOSCHED_CFQ=y
#
# Fusion MPT device support
#
+# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
@@ -324,10 +343,11 @@ CONFIG_NET=y
#
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_PNP=y
@@ -344,6 +364,17 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_TUNNEL is not set
# CONFIG_IP_TCPDIAG is not set
# CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
@@ -399,6 +430,7 @@ CONFIG_MII=y
# CONFIG_SUNGEM is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
#
# Tulip family network device support
@@ -435,9 +467,11 @@ CONFIG_EEPRO100=y
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
+# CONFIG_SKGE is not set
# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
#
# Ethernet (10000 Mbit)
@@ -459,6 +493,7 @@ CONFIG_EEPRO100=y
# Wan interfaces
#
CONFIG_WAN=y
+# CONFIG_DSCC4 is not set
# CONFIG_LANMEDIA is not set
# CONFIG_SYNCLINK_SYNCPPP is not set
CONFIG_HDLC=y
@@ -521,7 +556,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
#
# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
#
# Character devices
@@ -542,6 +576,7 @@ CONFIG_SERIAL_8250_NR_UARTS=2
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -608,17 +643,18 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_ISA is not set
# CONFIG_I2C_IXP2000 is not set
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
# CONFIG_SCx200_ACB is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
@@ -632,7 +668,9 @@ CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
# CONFIG_SENSORS_FSCPOS is not set
@@ -648,6 +686,7 @@ CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_LM85 is not set
# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
@@ -657,14 +696,19 @@ CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
#
# Other I2C Chip support
#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
CONFIG_SENSORS_EEPROM=y
# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -718,6 +762,7 @@ CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
@@ -758,7 +803,6 @@ CONFIG_DNOTIFY=y
#
CONFIG_PROC_FS=y
CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
# CONFIG_TMPFS_XATTR is not set
@@ -796,12 +840,14 @@ CONFIG_JFFS2_RTIME=y
#
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -886,3 +932,4 @@ CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
+# CONFIG_TEXTSEARCH is not set
diff --git a/arch/arm/configs/ixdp2801_defconfig b/arch/arm/configs/ixdp2801_defconfig
index cd84a20f30f..b1e162f29cb 100644
--- a/arch/arm/configs/ixdp2801_defconfig
+++ b/arch/arm/configs/ixdp2801_defconfig
@@ -1,14 +1,13 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sun Mar 27 22:39:19 2005
+# Linux kernel version: 2.6.12-git6
+# Sat Jun 25 01:01:18 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
@@ -16,6 +15,7 @@ CONFIG_GENERIC_IOMAP=y
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -35,6 +35,8 @@ CONFIG_EMBEDDED=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
@@ -50,7 +52,13 @@ CONFIG_BASE_SMALL=0
#
# Loadable module support
#
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
#
# System Type
@@ -76,6 +84,7 @@ CONFIG_ARCH_IXP2000=y
# CONFIG_ARCH_VERSATILE is not set
# CONFIG_ARCH_IMX is not set
# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
#
@@ -91,6 +100,7 @@ CONFIG_ARCH_SUPPORTS_BIG_ENDIAN=y
# CONFIG_ARCH_IXDP2401 is not set
CONFIG_ARCH_IXDP2801=y
CONFIG_ARCH_IXDP2X01=y
+# CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO is not set
#
# Processor Type
@@ -101,7 +111,6 @@ CONFIG_CPU_32v5=y
CONFIG_CPU_ABRT_EV5T=y
CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_TLB_V4WBI=y
-CONFIG_CPU_MINICACHE=y
#
# Processor Features
@@ -113,9 +122,11 @@ CONFIG_XSCALE_PMU=y
#
# Bus support
#
+CONFIG_ISA_DMA_API=y
CONFIG_PCI=y
CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
@@ -125,7 +136,15 @@ CONFIG_PCI_NAMES=y
#
# Kernel Features
#
+# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
CONFIG_ALIGNMENT_TRAP=y
#
@@ -264,7 +283,6 @@ CONFIG_MTD_IXP2000=y
#
# Block devices
#
-# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
@@ -303,6 +321,7 @@ CONFIG_IOSCHED_CFQ=y
#
# Fusion MPT device support
#
+# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
@@ -324,10 +343,11 @@ CONFIG_NET=y
#
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_PNP=y
@@ -344,6 +364,17 @@ CONFIG_SYN_COOKIES=y
# CONFIG_INET_TUNNEL is not set
# CONFIG_IP_TCPDIAG is not set
# CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
# CONFIG_IPV6 is not set
# CONFIG_NETFILTER is not set
@@ -399,6 +430,7 @@ CONFIG_MII=y
# CONFIG_SUNGEM is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
#
# Tulip family network device support
@@ -436,9 +468,11 @@ CONFIG_EEPRO100=y
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
+# CONFIG_SKGE is not set
# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
#
# Ethernet (10000 Mbit)
@@ -460,6 +494,7 @@ CONFIG_EEPRO100=y
# Wan interfaces
#
CONFIG_WAN=y
+# CONFIG_DSCC4 is not set
# CONFIG_LANMEDIA is not set
# CONFIG_SYNCLINK_SYNCPPP is not set
CONFIG_HDLC=y
@@ -522,7 +557,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
#
# CONFIG_SERIO is not set
# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
#
# Character devices
@@ -543,6 +577,7 @@ CONFIG_SERIAL_8250_NR_UARTS=2
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -609,17 +644,18 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_ISA is not set
# CONFIG_I2C_IXP2000 is not set
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
# CONFIG_SCx200_ACB is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
# CONFIG_I2C_VOODOO3 is not set
@@ -633,7 +669,9 @@ CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1026 is not set
# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
# CONFIG_SENSORS_FSCPOS is not set
@@ -649,6 +687,7 @@ CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_LM85 is not set
# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
@@ -658,14 +697,19 @@ CONFIG_I2C_SENSOR=y
# CONFIG_SENSORS_W83781D is not set
# CONFIG_SENSORS_W83L785TS is not set
# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
#
# Other I2C Chip support
#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
CONFIG_SENSORS_EEPROM=y
# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -719,6 +763,7 @@ CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT2_FS_POSIX_ACL=y
# CONFIG_EXT2_FS_SECURITY is not set
+# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
@@ -759,7 +804,6 @@ CONFIG_DNOTIFY=y
#
CONFIG_PROC_FS=y
CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
# CONFIG_DEVPTS_FS_XATTR is not set
CONFIG_TMPFS=y
# CONFIG_TMPFS_XATTR is not set
@@ -797,12 +841,14 @@ CONFIG_JFFS2_RTIME=y
#
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
# CONFIG_NFS_DIRECTIO is not set
# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -887,3 +933,4 @@ CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
+# CONFIG_TEXTSEARCH is not set
diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig
index 2a63fb27719..98b72ff3883 100644
--- a/arch/arm/configs/s3c2410_defconfig
+++ b/arch/arm/configs/s3c2410_defconfig
@@ -1,14 +1,13 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sun Mar 27 17:47:45 2005
+# Linux kernel version: 2.6.12-git4
+# Wed Jun 22 15:56:42 2005
#
CONFIG_ARM=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
@@ -17,6 +16,7 @@ CONFIG_EXPERIMENTAL=y
# CONFIG_CLEAN_COMPILE is not set
CONFIG_BROKEN=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -35,6 +35,8 @@ CONFIG_KOBJECT_UEVENT=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
@@ -81,6 +83,7 @@ CONFIG_ARCH_S3C2410=y
# CONFIG_ARCH_VERSATILE is not set
# CONFIG_ARCH_IMX is not set
# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
#
# S3C24XX Implementations
@@ -134,6 +137,7 @@ CONFIG_CPU_TLB_V4WBI=y
#
# Bus support
#
+CONFIG_ISA_DMA_API=y
#
# PCCARD (PCMCIA/CardBus) support
@@ -143,7 +147,9 @@ CONFIG_CPU_TLB_V4WBI=y
#
# Kernel Features
#
+# CONFIG_SMP is not set
# CONFIG_PREEMPT is not set
+# CONFIG_DISCONTIGMEM is not set
CONFIG_ALIGNMENT_TRAP=y
#
@@ -297,7 +303,6 @@ CONFIG_PARPORT_1284=y
#
# Block devices
#
-# CONFIG_BLK_DEV_FD is not set
# CONFIG_PARIDE is not set
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
@@ -359,6 +364,7 @@ CONFIG_BLK_DEV_IDE_BAST=y
#
# Fusion MPT device support
#
+# CONFIG_FUSION is not set
#
# IEEE 1394 (FireWire) support
@@ -378,10 +384,11 @@ CONFIG_NET=y
# Networking options
#
# CONFIG_PACKET is not set
-# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
CONFIG_IP_PNP=y
@@ -443,8 +450,9 @@ CONFIG_NETDEVICES=y
# Ethernet (10 or 100Mbit)
#
CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
+CONFIG_MII=m
# CONFIG_SMC91X is not set
+CONFIG_DM9000=m
#
# Ethernet (1000 Mbit)
@@ -521,7 +529,6 @@ CONFIG_SERIO_SERPORT=y
CONFIG_SERIO_LIBPS2=y
# CONFIG_SERIO_RAW is not set
# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
#
# Character devices
@@ -605,7 +612,6 @@ CONFIG_S3C2410_RTC=y
#
# TPM devices
#
-# CONFIG_TCG_TPM is not set
#
# I2C support
@@ -654,6 +660,7 @@ CONFIG_SENSORS_LM78=m
CONFIG_SENSORS_LM85=m
# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
@@ -665,6 +672,7 @@ CONFIG_SENSORS_LM85=m
#
# Other I2C Chip support
#
+# CONFIG_SENSORS_DS1337 is not set
CONFIG_SENSORS_EEPROM=m
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCF8591 is not set
@@ -696,8 +704,10 @@ CONFIG_FB=y
# CONFIG_FB_CFB_COPYAREA is not set
# CONFIG_FB_CFB_IMAGEBLIT is not set
# CONFIG_FB_SOFT_CURSOR is not set
+# CONFIG_FB_MACMODES is not set
CONFIG_FB_MODE_HELPERS=y
# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
#
@@ -782,7 +792,6 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
#
CONFIG_PROC_FS=y
CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
# CONFIG_DEVPTS_FS_XATTR is not set
# CONFIG_TMPFS is not set
# CONFIG_HUGETLBFS is not set
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 4a2af55e134..3e1b0327e4d 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -6,7 +6,7 @@ AFLAGS_head.o := -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
# Object file lists.
-obj-y := arch.o compat.o dma.o entry-armv.o entry-common.o irq.o \
+obj-y := compat.o dma.o entry-armv.o entry-common.o irq.o \
process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \
time.o traps.o
diff --git a/arch/arm/kernel/arch.c b/arch/arm/kernel/arch.c
deleted file mode 100644
index 4e02fbeb10a..00000000000
--- a/arch/arm/kernel/arch.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * linux/arch/arm/kernel/arch.c
- *
- * Architecture specific fixups.
- */
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/types.h>
-
-#include <asm/elf.h>
-#include <asm/page.h>
-#include <asm/setup.h>
-#include <asm/mach/arch.h>
-
-unsigned int vram_size;
-
-#ifdef CONFIG_ARCH_ACORN
-
-unsigned int memc_ctrl_reg;
-unsigned int number_mfm_drives;
-
-static int __init parse_tag_acorn(const struct tag *tag)
-{
- memc_ctrl_reg = tag->u.acorn.memc_control_reg;
- number_mfm_drives = tag->u.acorn.adfsdrives;
-
- switch (tag->u.acorn.vram_pages) {
- case 512:
- vram_size += PAGE_SIZE * 256;
- case 256:
- vram_size += PAGE_SIZE * 256;
- default:
- break;
- }
-#if 0
- if (vram_size) {
- desc->video_start = 0x02000000;
- desc->video_end = 0x02000000 + vram_size;
- }
-#endif
- return 0;
-}
-
-__tagtable(ATAG_ACORN, parse_tag_acorn);
-
-#endif
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index 3dc15b131f5..6540db69133 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -866,19 +866,19 @@ static struct expansion_card *__init ecard_alloc_card(int type, int slot)
return ec;
}
-static ssize_t ecard_show_irq(struct device *dev, char *buf)
+static ssize_t ecard_show_irq(struct device *dev, struct device_attribute *attr, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->irq);
}
-static ssize_t ecard_show_dma(struct device *dev, char *buf)
+static ssize_t ecard_show_dma(struct device *dev, struct device_attribute *attr, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->dma);
}
-static ssize_t ecard_show_resources(struct device *dev, char *buf)
+static ssize_t ecard_show_resources(struct device *dev, struct device_attribute *attr, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
char *str = buf;
@@ -893,19 +893,19 @@ static ssize_t ecard_show_resources(struct device *dev, char *buf)
return str - buf;
}
-static ssize_t ecard_show_vendor(struct device *dev, char *buf)
+static ssize_t ecard_show_vendor(struct device *dev, struct device_attribute *attr, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->cid.manufacturer);
}
-static ssize_t ecard_show_device(struct device *dev, char *buf)
+static ssize_t ecard_show_device(struct device *dev, struct device_attribute *attr, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->cid.product);
}
-static ssize_t ecard_show_type(struct device *dev, char *buf)
+static ssize_t ecard_show_type(struct device *dev, struct device_attribute *attr, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%s\n", ec->type == ECARD_EASI ? "EASI" : "IOC");
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 4eb36155dc9..39a6c1b0b9a 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -24,48 +24,91 @@
#include "entry-header.S"
/*
+ * Interrupt handling. Preserves r7, r8, r9
+ */
+ .macro irq_handler
+1: get_irqnr_and_base r0, r6, r5, lr
+ movne r1, sp
+ @
+ @ routine called with r0 = irq number, r1 = struct pt_regs *
+ @
+ adrne lr, 1b
+ bne asm_do_IRQ
+
+#ifdef CONFIG_SMP
+ /*
+ * XXX
+ *
+ * this macro assumes that irqstat (r6) and base (r5) are
+ * preserved from get_irqnr_and_base above
+ */
+ test_for_ipi r0, r6, r5, lr
+ movne r0, sp
+ adrne lr, 1b
+ bne do_IPI
+#endif
+
+ .endm
+
+/*
* Invalid mode handlers
*/
- .macro inv_entry, sym, reason
- sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
- stmia sp, {r0 - lr} @ Save XXX r0 - lr
- ldr r4, .LC\sym
+ .macro inv_entry, reason
+ sub sp, sp, #S_FRAME_SIZE
+ stmib sp, {r1 - lr}
mov r1, #\reason
.endm
__pabt_invalid:
- inv_entry abt, BAD_PREFETCH
- b 1f
+ inv_entry BAD_PREFETCH
+ b common_invalid
__dabt_invalid:
- inv_entry abt, BAD_DATA
- b 1f
+ inv_entry BAD_DATA
+ b common_invalid
__irq_invalid:
- inv_entry irq, BAD_IRQ
- b 1f
+ inv_entry BAD_IRQ
+ b common_invalid
__und_invalid:
- inv_entry und, BAD_UNDEFINSTR
+ inv_entry BAD_UNDEFINSTR
+
+ @
+ @ XXX fall through to common_invalid
+ @
+
+@
+@ common_invalid - generic code for failed exception (re-entrant version of handlers)
+@
+common_invalid:
+ zero_fp
+
+ ldmia r0, {r4 - r6}
+ add r0, sp, #S_PC @ here for interlock avoidance
+ mov r7, #-1 @ "" "" "" ""
+ str r4, [sp] @ save preserved r0
+ stmia r0, {r5 - r7} @ lr_<exception>,
+ @ cpsr_<exception>, "old_r0"
-1: zero_fp
- ldmia r4, {r5 - r7} @ Get XXX pc, cpsr, old_r0
- add r4, sp, #S_PC
- stmia r4, {r5 - r7} @ Save XXX pc, cpsr, old_r0
mov r0, sp
- and r2, r6, #31 @ int mode
+ and r2, r6, #0x1f
b bad_mode
/*
* SVC mode handlers
*/
- .macro svc_entry, sym
+ .macro svc_entry
sub sp, sp, #S_FRAME_SIZE
- stmia sp, {r0 - r12} @ save r0 - r12
- ldr r2, .LC\sym
- add r0, sp, #S_FRAME_SIZE
- ldmia r2, {r2 - r4} @ get pc, cpsr
- add r5, sp, #S_SP
+ stmib sp, {r1 - r12}
+
+ ldmia r0, {r1 - r3}
+ add r5, sp, #S_SP @ here for interlock avoidance
+ mov r4, #-1 @ "" "" "" ""
+ add r0, sp, #S_FRAME_SIZE @ "" "" "" ""
+ str r1, [sp] @ save the "real" r0 copied
+ @ from the exception stack
+
mov r1, lr
@
@@ -82,7 +125,7 @@ __und_invalid:
.align 5
__dabt_svc:
- svc_entry abt
+ svc_entry
@
@ get ready to re-enable interrupts if appropriate
@@ -129,28 +172,24 @@ __dabt_svc:
.align 5
__irq_svc:
- svc_entry irq
+ svc_entry
+
#ifdef CONFIG_PREEMPT
- get_thread_info r8
- ldr r9, [r8, #TI_PREEMPT] @ get preempt count
- add r7, r9, #1 @ increment it
- str r7, [r8, #TI_PREEMPT]
+ get_thread_info tsk
+ ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
+ add r7, r8, #1 @ increment it
+ str r7, [tsk, #TI_PREEMPT]
#endif
-1: get_irqnr_and_base r0, r6, r5, lr
- movne r1, sp
- @
- @ routine called with r0 = irq number, r1 = struct pt_regs *
- @
- adrne lr, 1b
- bne asm_do_IRQ
+
+ irq_handler
#ifdef CONFIG_PREEMPT
- ldr r0, [r8, #TI_FLAGS] @ get flags
+ ldr r0, [tsk, #TI_FLAGS] @ get flags
tst r0, #_TIF_NEED_RESCHED
blne svc_preempt
preempt_return:
- ldr r0, [r8, #TI_PREEMPT] @ read preempt value
+ ldr r0, [tsk, #TI_PREEMPT] @ read preempt value
+ str r8, [tsk, #TI_PREEMPT] @ restore preempt count
teq r0, r7
- str r9, [r8, #TI_PREEMPT] @ restore preempt count
strne r0, [r0, -r0] @ bug()
#endif
ldr r0, [sp, #S_PSR] @ irqs are already disabled
@@ -161,7 +200,7 @@ preempt_return:
#ifdef CONFIG_PREEMPT
svc_preempt:
- teq r9, #0 @ was preempt count = 0
+ teq r8, #0 @ was preempt count = 0
ldreq r6, .LCirq_stat
movne pc, lr @ no
ldr r0, [r6, #4] @ local_irq_count
@@ -169,9 +208,9 @@ svc_preempt:
adds r0, r0, r1
movne pc, lr
mov r7, #0 @ preempt_schedule_irq
- str r7, [r8, #TI_PREEMPT] @ expects preempt_count == 0
+ str r7, [tsk, #TI_PREEMPT] @ expects preempt_count == 0
1: bl preempt_schedule_irq @ irq en/disable is done inside
- ldr r0, [r8, #TI_FLAGS] @ get new tasks TI_FLAGS
+ ldr r0, [tsk, #TI_FLAGS] @ get new tasks TI_FLAGS
tst r0, #_TIF_NEED_RESCHED
beq preempt_return @ go again
b 1b
@@ -179,7 +218,7 @@ svc_preempt:
.align 5
__und_svc:
- svc_entry und
+ svc_entry
@
@ call emulation code, which returns using r9 if it has emulated
@@ -209,7 +248,7 @@ __und_svc:
.align 5
__pabt_svc:
- svc_entry abt
+ svc_entry
@
@ re-enable interrupts if appropriate
@@ -242,12 +281,8 @@ __pabt_svc:
ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
.align 5
-.LCirq:
- .word __temp_irq
-.LCund:
- .word __temp_und
-.LCabt:
- .word __temp_abt
+.LCcralign:
+ .word cr_alignment
#ifdef MULTI_ABORT
.LCprocfns:
.word processor
@@ -262,14 +297,18 @@ __pabt_svc:
/*
* User mode handlers
*/
- .macro usr_entry, sym
- sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
- stmia sp, {r0 - r12} @ save r0 - r12
- ldr r7, .LC\sym
- add r5, sp, #S_PC
- ldmia r7, {r2 - r4} @ Get USR pc, cpsr
-
-#if __LINUX_ARM_ARCH__ < 6
+ .macro usr_entry
+ sub sp, sp, #S_FRAME_SIZE
+ stmib sp, {r1 - r12}
+
+ ldmia r0, {r1 - r3}
+ add r0, sp, #S_PC @ here for interlock avoidance
+ mov r4, #-1 @ "" "" "" ""
+
+ str r1, [sp] @ save the "real" r0 copied
+ @ from the exception stack
+
+#if __LINUX_ARM_ARCH__ < 6 && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
@ make sure our user space atomic helper is aborted
cmp r2, #VIRT_OFFSET
bichs r3, r3, #PSR_Z_BIT
@@ -284,13 +323,13 @@ __pabt_svc:
@
@ Also, separately save sp_usr and lr_usr
@
- stmia r5, {r2 - r4}
- stmdb r5, {sp, lr}^
+ stmia r0, {r2 - r4}
+ stmdb r0, {sp, lr}^
@
@ Enable the alignment trap while in kernel mode
@
- alignment_trap r7, r0, __temp_\sym
+ alignment_trap r0
@
@ Clear FP to mark the first stack frame
@@ -300,7 +339,7 @@ __pabt_svc:
.align 5
__dabt_usr:
- usr_entry abt
+ usr_entry
@
@ Call the processor-specific abort handler:
@@ -329,30 +368,23 @@ __dabt_usr:
.align 5
__irq_usr:
- usr_entry irq
+ usr_entry
+ get_thread_info tsk
#ifdef CONFIG_PREEMPT
- get_thread_info r8
- ldr r9, [r8, #TI_PREEMPT] @ get preempt count
- add r7, r9, #1 @ increment it
- str r7, [r8, #TI_PREEMPT]
+ ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
+ add r7, r8, #1 @ increment it
+ str r7, [tsk, #TI_PREEMPT]
#endif
-1: get_irqnr_and_base r0, r6, r5, lr
- movne r1, sp
- adrne lr, 1b
- @
- @ routine called with r0 = irq number, r1 = struct pt_regs *
- @
- bne asm_do_IRQ
+
+ irq_handler
#ifdef CONFIG_PREEMPT
- ldr r0, [r8, #TI_PREEMPT]
+ ldr r0, [tsk, #TI_PREEMPT]
+ str r8, [tsk, #TI_PREEMPT]
teq r0, r7
- str r9, [r8, #TI_PREEMPT]
strne r0, [r0, -r0]
- mov tsk, r8
-#else
- get_thread_info tsk
#endif
+
mov why, #0
b ret_to_user
@@ -360,7 +392,7 @@ __irq_usr:
.align 5
__und_usr:
- usr_entry und
+ usr_entry
tst r3, #PSR_T_BIT @ Thumb mode?
bne fpundefinstr @ ignore FP
@@ -476,7 +508,7 @@ fpundefinstr:
.align 5
__pabt_usr:
- usr_entry abt
+ usr_entry
enable_irq @ Enable interrupts
mov r0, r2 @ address (pc)
@@ -616,11 +648,17 @@ __kuser_helper_start:
__kuser_cmpxchg: @ 0xffff0fc0
-#if __LINUX_ARM_ARCH__ < 6
+#if defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
-#ifdef CONFIG_SMP /* sanity check */
-#error "CONFIG_SMP on a machine supporting pre-ARMv6 processors?"
-#endif
+ /*
+ * Poor you. No fast solution possible...
+ * The kernel itself must perform the operation.
+ * A special ghost syscall is used for that (see traps.c).
+ */
+ swi #0x9ffff0
+ mov pc, lr
+
+#elif __LINUX_ARM_ARCH__ < 6
/*
* Theory of operation:
@@ -735,29 +773,41 @@ __kuser_helper_end:
*
* Common stub entry macro:
* Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
+ *
+ * SP points to a minimal amount of processor-private memory, the address
+ * of which is copied into r0 for the mode specific abort handler.
*/
- .macro vector_stub, name, sym, correction=0
+ .macro vector_stub, name, correction=0
.align 5
vector_\name:
- ldr r13, .LCs\sym
.if \correction
sub lr, lr, #\correction
.endif
- str lr, [r13] @ save lr_IRQ
+
+ @
+ @ Save r0, lr_<exception> (parent PC) and spsr_<exception>
+ @ (parent CPSR)
+ @
+ stmia sp, {r0, lr} @ save r0, lr
mrs lr, spsr
- str lr, [r13, #4] @ save spsr_IRQ
+ str lr, [sp, #8] @ save spsr
+
@
- @ now branch to the relevant MODE handling routine
+ @ Prepare for SVC32 mode. IRQs remain disabled.
@
- mrs r13, cpsr
- bic r13, r13, #MODE_MASK
- orr r13, r13, #SVC_MODE
- msr spsr_cxsf, r13 @ switch to SVC_32 mode
+ mrs r0, cpsr
+ bic r0, r0, #MODE_MASK
+ orr r0, r0, #SVC_MODE
+ msr spsr_cxsf, r0
- and lr, lr, #15
+ @
+ @ the branch table must immediately follow this code
+ @
+ mov r0, sp
+ and lr, lr, #0x0f
ldr lr, [pc, lr, lsl #2]
- movs pc, lr @ Changes mode and branches
+ movs pc, lr @ branch to handler in SVC mode
.endm
.globl __stubs_start
@@ -765,7 +815,7 @@ __stubs_start:
/*
* Interrupt dispatcher
*/
- vector_stub irq, irq, 4
+ vector_stub irq, 4
.long __irq_usr @ 0 (USR_26 / USR_32)
.long __irq_invalid @ 1 (FIQ_26 / FIQ_32)
@@ -788,7 +838,7 @@ __stubs_start:
* Data abort dispatcher
* Enter in ABT mode, spsr = USR CPSR, lr = USR PC
*/
- vector_stub dabt, abt, 8
+ vector_stub dabt, 8
.long __dabt_usr @ 0 (USR_26 / USR_32)
.long __dabt_invalid @ 1 (FIQ_26 / FIQ_32)
@@ -811,7 +861,7 @@ __stubs_start:
* Prefetch abort dispatcher
* Enter in ABT mode, spsr = USR CPSR, lr = USR PC
*/
- vector_stub pabt, abt, 4
+ vector_stub pabt, 4
.long __pabt_usr @ 0 (USR_26 / USR_32)
.long __pabt_invalid @ 1 (FIQ_26 / FIQ_32)
@@ -834,7 +884,7 @@ __stubs_start:
* Undef instr entry dispatcher
* Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
*/
- vector_stub und, und
+ vector_stub und
.long __und_usr @ 0 (USR_26 / USR_32)
.long __und_invalid @ 1 (FIQ_26 / FIQ_32)
@@ -888,13 +938,6 @@ vector_addrexcptn:
.LCvswi:
.word vector_swi
-.LCsirq:
- .word __temp_irq
-.LCsund:
- .word __temp_und
-.LCsabt:
- .word __temp_abt
-
.globl __stubs_end
__stubs_end:
@@ -916,23 +959,6 @@ __vectors_end:
.data
-/*
- * Do not reorder these, and do not insert extra data between...
- */
-
-__temp_irq:
- .word 0 @ saved lr_irq
- .word 0 @ saved spsr_irq
- .word -1 @ old_r0
-__temp_und:
- .word 0 @ Saved lr_und
- .word 0 @ Saved spsr_und
- .word -1 @ old_r0
-__temp_abt:
- .word 0 @ Saved lr_abt
- .word 0 @ Saved spsr_abt
- .word -1 @ old_r0
-
.globl cr_alignment
.globl cr_no_alignment
cr_alignment:
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index a3d40a0e2b0..afef2127396 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -59,11 +59,10 @@
mov \rd, \rd, lsl #13
.endm
- .macro alignment_trap, rbase, rtemp, sym
+ .macro alignment_trap, rtemp
#ifdef CONFIG_ALIGNMENT_TRAP
-#define OFF_CR_ALIGNMENT(x) cr_alignment - x
-
- ldr \rtemp, [\rbase, #OFF_CR_ALIGNMENT(\sym)]
+ ldr \rtemp, .LCcralign
+ ldr \rtemp, [\rtemp]
mcr p15, 0, \rtemp, c1, c0
#endif
.endm
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 4733877296d..bd4823c7464 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -2,6 +2,8 @@
* linux/arch/arm/kernel/head.S
*
* Copyright (C) 1994-2002 Russell King
+ * Copyright (c) 2003 ARM Limited
+ * 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 version 2 as
@@ -165,6 +167,48 @@ __mmap_switched:
stmia r6, {r0, r4} @ Save control register values
b start_kernel
+#if defined(CONFIG_SMP)
+ .type secondary_startup, #function
+ENTRY(secondary_startup)
+ /*
+ * Common entry point for secondary CPUs.
+ *
+ * Ensure that we're in SVC mode, and IRQs are disabled. Lookup
+ * the processor type - there is no need to check the machine type
+ * as it has already been validated by the primary processor.
+ */
+ msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | MODE_SVC
+ bl __lookup_processor_type
+ movs r10, r5 @ invalid processor?
+ moveq r0, #'p' @ yes, error 'p'
+ beq __error
+
+ /*
+ * Use the page tables supplied from __cpu_up.
+ */
+ adr r4, __secondary_data
+ ldmia r4, {r5, r6, r13} @ address to jump to after
+ sub r4, r4, r5 @ mmu has been enabled
+ ldr r4, [r6, r4] @ get secondary_data.pgdir
+ adr lr, __enable_mmu @ return address
+ add pc, r10, #12 @ initialise processor
+ @ (return control reg)
+
+ /*
+ * r6 = &secondary_data
+ */
+ENTRY(__secondary_switched)
+ ldr sp, [r6, #4] @ get secondary_data.stack
+ mov fp, #0
+ b secondary_start_kernel
+
+ .type __secondary_data, %object
+__secondary_data:
+ .long .
+ .long secondary_data
+ .long __secondary_switched
+#endif /* defined(CONFIG_SMP) */
+
/*
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index ff187f4308f..395137a8fad 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -4,6 +4,10 @@
* Copyright (C) 1992 Linus Torvalds
* Modifications for ARM processor Copyright (C) 1995-2000 Russell King.
*
+ * Support for Dynamic Tick Timer Copyright (C) 2004-2005 Nokia Corporation.
+ * Dynamic Tick Timer written by Tony Lindgren <tony@atomide.com> and
+ * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>.
+ *
* 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.
@@ -37,6 +41,7 @@
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
/*
* Maximum IRQ count. Currently, this is arbitary. However, it should
@@ -329,6 +334,15 @@ __do_irq(unsigned int irq, struct irqaction *action, struct pt_regs *regs)
spin_unlock(&irq_controller_lock);
+#ifdef CONFIG_NO_IDLE_HZ
+ if (!(action->flags & SA_TIMER) && system_timer->dyn_tick != NULL) {
+ write_seqlock(&xtime_lock);
+ if (system_timer->dyn_tick->state & DYN_TICK_ENABLED)
+ system_timer->dyn_tick->handler(irq, 0, regs);
+ write_sequnlock(&xtime_lock);
+ }
+#endif
+
if (!(action->flags & SA_INTERRUPT))
local_irq_enable();
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index c2a7da3ac0f..8cf733daa80 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -92,6 +92,14 @@ struct cpu_user_fns cpu_user;
struct cpu_cache_fns cpu_cache;
#endif
+struct stack {
+ u32 irq[3];
+ u32 abt[3];
+ u32 und[3];
+} ____cacheline_aligned;
+
+static struct stack stacks[NR_CPUS];
+
char elf_platform[ELF_PLATFORM_SIZE];
EXPORT_SYMBOL(elf_platform);
@@ -307,8 +315,6 @@ static void __init setup_processor(void)
cpu_name, processor_id, (int)processor_id & 15,
proc_arch[cpu_architecture()]);
- dump_cpu_info(smp_processor_id());
-
sprintf(system_utsname.machine, "%s%c", list->arch_name, ENDIANNESS);
sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
elf_hwcap = list->elf_hwcap;
@@ -316,6 +322,46 @@ static void __init setup_processor(void)
cpu_proc_init();
}
+/*
+ * cpu_init - initialise one CPU.
+ *
+ * cpu_init dumps the cache information, initialises SMP specific
+ * information, and sets up the per-CPU stacks.
+ */
+void cpu_init(void)
+{
+ unsigned int cpu = smp_processor_id();
+ struct stack *stk = &stacks[cpu];
+
+ if (cpu >= NR_CPUS) {
+ printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu);
+ BUG();
+ }
+
+ dump_cpu_info(cpu);
+
+ /*
+ * setup stacks for re-entrant exception handlers
+ */
+ __asm__ (
+ "msr cpsr_c, %1\n\t"
+ "add sp, %0, %2\n\t"
+ "msr cpsr_c, %3\n\t"
+ "add sp, %0, %4\n\t"
+ "msr cpsr_c, %5\n\t"
+ "add sp, %0, %6\n\t"
+ "msr cpsr_c, %7"
+ :
+ : "r" (stk),
+ "I" (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
+ "I" (offsetof(struct stack, irq[0])),
+ "I" (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
+ "I" (offsetof(struct stack, abt[0])),
+ "I" (PSR_F_BIT | PSR_I_BIT | UND_MODE),
+ "I" (offsetof(struct stack, und[0])),
+ "I" (PSR_F_BIT | PSR_I_BIT | SVC_MODE));
+}
+
static struct machine_desc * __init setup_machine(unsigned int nr)
{
struct machine_desc *list;
@@ -349,6 +395,20 @@ static void __init early_initrd(char **p)
}
__early_param("initrd=", early_initrd);
+static void __init add_memory(unsigned long start, unsigned long size)
+{
+ /*
+ * Ensure that start/size are aligned to a page boundary.
+ * Size is appropriately rounded down, start is rounded up.
+ */
+ size -= start & ~PAGE_MASK;
+
+ meminfo.bank[meminfo.nr_banks].start = PAGE_ALIGN(start);
+ meminfo.bank[meminfo.nr_banks].size = size & PAGE_MASK;
+ meminfo.bank[meminfo.nr_banks].node = PHYS_TO_NID(start);
+ meminfo.nr_banks += 1;
+}
+
/*
* Pick out the memory size. We look for mem=size@start,
* where start and size are "size[KkMm]"
@@ -373,10 +433,7 @@ static void __init early_mem(char **p)
if (**p == '@')
start = memparse(*p + 1, p);
- meminfo.bank[meminfo.nr_banks].start = start;
- meminfo.bank[meminfo.nr_banks].size = size;
- meminfo.bank[meminfo.nr_banks].node = PHYS_TO_NID(start);
- meminfo.nr_banks += 1;
+ add_memory(start, size);
}
__early_param("mem=", early_mem);
@@ -518,11 +575,7 @@ static int __init parse_tag_mem32(const struct tag *tag)
tag->u.mem.start, tag->u.mem.size / 1024);
return -EINVAL;
}
- meminfo.bank[meminfo.nr_banks].start = tag->u.mem.start;
- meminfo.bank[meminfo.nr_banks].size = tag->u.mem.size;
- meminfo.bank[meminfo.nr_banks].node = PHYS_TO_NID(tag->u.mem.start);
- meminfo.nr_banks += 1;
-
+ add_memory(tag->u.mem.start, tag->u.mem.size);
return 0;
}
@@ -715,6 +768,8 @@ void __init setup_arch(char **cmdline_p)
paging_init(&meminfo, mdesc);
request_standard_resources(&meminfo, mdesc);
+ cpu_init();
+
/*
* Set up various architecture-specific pointers
*/
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 931919fd512..5e435e42dac 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -19,6 +19,7 @@
#include <asm/unistd.h>
#include "ptrace.h"
+#include "signal.h"
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
@@ -35,7 +36,7 @@
#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_sigreturn - __NR_SYSCALL_BASE))
#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE))
-static const unsigned long retcodes[4] = {
+const unsigned long sigreturn_codes[4] = {
SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN
};
@@ -500,17 +501,25 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka,
if (ka->sa.sa_flags & SA_SIGINFO)
idx += 2;
- if (__put_user(retcodes[idx], rc))
+ if (__put_user(sigreturn_codes[idx], rc))
return 1;
- /*
- * Ensure that the instruction cache sees
- * the return code written onto the stack.
- */
- flush_icache_range((unsigned long)rc,
- (unsigned long)(rc + 1));
-
- retcode = ((unsigned long)rc) + thumb;
+ if (cpsr & MODE32_BIT) {
+ /*
+ * 32-bit code can use the new high-page
+ * signal return code support.
+ */
+ retcode = KERN_SIGRETURN_CODE + (idx << 2) + thumb;
+ } else {
+ /*
+ * Ensure that the instruction cache sees
+ * the return code written onto the stack.
+ */
+ flush_icache_range((unsigned long)rc,
+ (unsigned long)(rc + 1));
+
+ retcode = ((unsigned long)rc) + thumb;
+ }
}
regs->ARM_r0 = usig;
@@ -688,7 +697,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
if (!user_mode(regs))
return 0;
- if (try_to_freeze(0))
+ if (try_to_freeze())
goto no_signal;
if (current->ptrace & PT_SINGLESTEP)
diff --git a/arch/arm/kernel/signal.h b/arch/arm/kernel/signal.h
new file mode 100644
index 00000000000..91d26faca62
--- /dev/null
+++ b/arch/arm/kernel/signal.h
@@ -0,0 +1,12 @@
+/*
+ * linux/arch/arm/kernel/signal.h
+ *
+ * Copyright (C) 2005 Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#define KERN_SIGRETURN_CODE 0xffff0500
+
+extern const unsigned long sigreturn_codes[4];
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index ecc8c333240..34892758f09 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -24,6 +24,9 @@
#include <asm/atomic.h>
#include <asm/cacheflush.h>
#include <asm/cpu.h>
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
#include <asm/processor.h>
#include <asm/tlbflush.h>
#include <asm/ptrace.h>
@@ -37,6 +40,13 @@ cpumask_t cpu_present_mask;
cpumask_t cpu_online_map;
/*
+ * as from 2.5, kernels no longer have an init_tasks structure
+ * so we need some other way of telling a new secondary core
+ * where to place its SVC stack
+ */
+struct secondary_data secondary_data;
+
+/*
* structures for inter-processor calls
* - A collection of single bit ipi messages.
*/
@@ -71,6 +81,8 @@ static DEFINE_SPINLOCK(smp_call_function_lock);
int __init __cpu_up(unsigned int cpu)
{
struct task_struct *idle;
+ pgd_t *pgd;
+ pmd_t *pmd;
int ret;
/*
@@ -84,11 +96,57 @@ int __init __cpu_up(unsigned int cpu)
}
/*
+ * Allocate initial page tables to allow the new CPU to
+ * enable the MMU safely. This essentially means a set
+ * of our "standard" page tables, with the addition of
+ * a 1:1 mapping for the physical address of the kernel.
+ */
+ pgd = pgd_alloc(&init_mm);
+ pmd = pmd_offset(pgd, PHYS_OFFSET);
+ *pmd = __pmd((PHYS_OFFSET & PGDIR_MASK) |
+ PMD_TYPE_SECT | PMD_SECT_AP_WRITE);
+
+ /*
+ * We need to tell the secondary core where to find
+ * its stack and the page tables.
+ */
+ secondary_data.stack = (void *)idle->thread_info + THREAD_SIZE - 8;
+ secondary_data.pgdir = virt_to_phys(pgd);
+ wmb();
+
+ /*
* Now bring the CPU into our world.
*/
ret = boot_secondary(cpu, idle);
+ if (ret == 0) {
+ unsigned long timeout;
+
+ /*
+ * CPU was successfully started, wait for it
+ * to come online or time out.
+ */
+ timeout = jiffies + HZ;
+ while (time_before(jiffies, timeout)) {
+ if (cpu_online(cpu))
+ break;
+
+ udelay(10);
+ barrier();
+ }
+
+ if (!cpu_online(cpu))
+ ret = -EIO;
+ }
+
+ secondary_data.stack = 0;
+ secondary_data.pgdir = 0;
+
+ *pmd_offset(pgd, PHYS_OFFSET) = __pmd(0);
+ pgd_free(pgd);
+
if (ret) {
- printk(KERN_CRIT "cpu_up: processor %d failed to boot\n", cpu);
+ printk(KERN_CRIT "CPU%u: processor failed to boot\n", cpu);
+
/*
* FIXME: We need to clean up the new idle thread. --rmk
*/
@@ -98,6 +156,56 @@ int __init __cpu_up(unsigned int cpu)
}
/*
+ * This is the secondary CPU boot entry. We're using this CPUs
+ * idle thread stack, but a set of temporary page tables.
+ */
+asmlinkage void __init secondary_start_kernel(void)
+{
+ struct mm_struct *mm = &init_mm;
+ unsigned int cpu = smp_processor_id();
+
+ printk("CPU%u: Booted secondary processor\n", cpu);
+
+ /*
+ * All kernel threads share the same mm context; grab a
+ * reference and switch to it.
+ */
+ atomic_inc(&mm->mm_users);
+ atomic_inc(&mm->mm_count);
+ current->active_mm = mm;
+ cpu_set(cpu, mm->cpu_vm_mask);
+ cpu_switch_mm(mm->pgd, mm);
+ enter_lazy_tlb(mm, current);
+
+ cpu_init();
+
+ /*
+ * Give the platform a chance to do its own initialisation.
+ */
+ platform_secondary_init(cpu);
+
+ /*
+ * Enable local interrupts.
+ */
+ local_irq_enable();
+ local_fiq_enable();
+
+ calibrate_delay();
+
+ smp_store_cpu_info(cpu);
+
+ /*
+ * OK, now it's safe to let the boot CPU continue
+ */
+ cpu_set(cpu, cpu_online_map);
+
+ /*
+ * OK, it's off to the idle thread for us
+ */
+ cpu_idle();
+}
+
+/*
* Called by both boot and secondaries to move global data into
* per-processor storage.
*/
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index c232f24f4a6..06054c9ba07 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -381,6 +381,95 @@ static struct sysdev_class timer_sysclass = {
.resume = timer_resume,
};
+#ifdef CONFIG_NO_IDLE_HZ
+static int timer_dyn_tick_enable(void)
+{
+ struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick;
+ unsigned long flags;
+ int ret = -ENODEV;
+
+ if (dyn_tick) {
+ write_seqlock_irqsave(&xtime_lock, flags);
+ ret = 0;
+ if (!(dyn_tick->state & DYN_TICK_ENABLED)) {
+ ret = dyn_tick->enable();
+
+ if (ret == 0)
+ dyn_tick->state |= DYN_TICK_ENABLED;
+ }
+ write_sequnlock_irqrestore(&xtime_lock, flags);
+ }
+
+ return ret;
+}
+
+static int timer_dyn_tick_disable(void)
+{
+ struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick;
+ unsigned long flags;
+ int ret = -ENODEV;
+
+ if (dyn_tick) {
+ write_seqlock_irqsave(&xtime_lock, flags);
+ ret = 0;
+ if (dyn_tick->state & DYN_TICK_ENABLED) {
+ ret = dyn_tick->disable();
+
+ if (ret == 0)
+ dyn_tick->state &= ~DYN_TICK_ENABLED;
+ }
+ write_sequnlock_irqrestore(&xtime_lock, flags);
+ }
+
+ return ret;
+}
+
+void timer_dyn_reprogram(void)
+{
+ struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick;
+ unsigned long flags;
+
+ write_seqlock_irqsave(&xtime_lock, flags);
+ if (dyn_tick->state & DYN_TICK_ENABLED)
+ dyn_tick->reprogram(next_timer_interrupt() - jiffies);
+ write_sequnlock_irqrestore(&xtime_lock, flags);
+}
+
+static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf)
+{
+ return sprintf(buf, "%i\n",
+ (system_timer->dyn_tick->state & DYN_TICK_ENABLED) >> 1);
+}
+
+static ssize_t timer_set_dyn_tick(struct sys_device *dev, const char *buf,
+ size_t count)
+{
+ unsigned int enable = simple_strtoul(buf, NULL, 2);
+
+ if (enable)
+ timer_dyn_tick_enable();
+ else
+ timer_dyn_tick_disable();
+
+ return count;
+}
+static SYSDEV_ATTR(dyn_tick, 0644, timer_show_dyn_tick, timer_set_dyn_tick);
+
+/*
+ * dyntick=enable|disable
+ */
+static char dyntick_str[4] __initdata = "";
+
+static int __init dyntick_setup(char *str)
+{
+ if (str)
+ strlcpy(dyntick_str, str, sizeof(dyntick_str));
+ return 1;
+}
+
+__setup("dyntick=", dyntick_setup);
+#endif
+
static int __init timer_init_sysfs(void)
{
int ret = sysdev_class_register(&timer_sysclass);
@@ -388,6 +477,20 @@ static int __init timer_init_sysfs(void)
system_timer->dev.cls = &timer_sysclass;
ret = sysdev_register(&system_timer->dev);
}
+
+#ifdef CONFIG_NO_IDLE_HZ
+ if (ret == 0 && system_timer->dyn_tick) {
+ ret = sysdev_create_file(&system_timer->dev, &attr_dyn_tick);
+
+ /*
+ * Turn on dynamic tick after calibrate delay
+ * for correct bogomips
+ */
+ if (ret == 0 && dyntick_str[0] == 'e')
+ ret = timer_dyn_tick_enable();
+ }
+#endif
+
return ret;
}
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 14df16b983f..2fb0a4cfb37 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -30,6 +30,7 @@
#include <asm/traps.h>
#include "ptrace.h"
+#include "signal.h"
const char *processor_modes[]=
{ "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" ,
@@ -464,6 +465,55 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
#endif
return 0;
+#ifdef CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG
+ /*
+ * Atomically store r1 in *r2 if *r2 is equal to r0 for user space.
+ * Return zero in r0 if *MEM was changed or non-zero if no exchange
+ * happened. Also set the user C flag accordingly.
+ * If access permissions have to be fixed up then non-zero is
+ * returned and the operation has to be re-attempted.
+ *
+ * *NOTE*: This is a ghost syscall private to the kernel. Only the
+ * __kuser_cmpxchg code in entry-armv.S should be aware of its
+ * existence. Don't ever use this from user code.
+ */
+ case 0xfff0:
+ {
+ extern void do_DataAbort(unsigned long addr, unsigned int fsr,
+ struct pt_regs *regs);
+ unsigned long val;
+ unsigned long addr = regs->ARM_r2;
+ struct mm_struct *mm = current->mm;
+ pgd_t *pgd; pmd_t *pmd; pte_t *pte;
+
+ regs->ARM_cpsr &= ~PSR_C_BIT;
+ spin_lock(&mm->page_table_lock);
+ pgd = pgd_offset(mm, addr);
+ if (!pgd_present(*pgd))
+ goto bad_access;
+ pmd = pmd_offset(pgd, addr);
+ if (!pmd_present(*pmd))
+ goto bad_access;
+ pte = pte_offset_map(pmd, addr);
+ if (!pte_present(*pte) || !pte_write(*pte))
+ goto bad_access;
+ val = *(unsigned long *)addr;
+ val -= regs->ARM_r0;
+ if (val == 0) {
+ *(unsigned long *)addr = regs->ARM_r1;
+ regs->ARM_cpsr |= PSR_C_BIT;
+ }
+ spin_unlock(&mm->page_table_lock);
+ return val;
+
+ bad_access:
+ spin_unlock(&mm->page_table_lock);
+ /* simulate a read access fault */
+ do_DataAbort(addr, 15 + (1 << 11), regs);
+ return -1;
+ }
+#endif
+
default:
/* Calls 9f00xx..9f07ff are defined to return -ENOSYS
if not implemented, rather than raising SIGILL. This
@@ -634,6 +684,14 @@ void __init trap_init(void)
memcpy((void *)0xffff0000, __vectors_start, __vectors_end - __vectors_start);
memcpy((void *)0xffff0200, __stubs_start, __stubs_end - __stubs_start);
memcpy((void *)0xffff1000 - kuser_sz, __kuser_helper_start, kuser_sz);
+
+ /*
+ * Copy signal return handlers into the vector page, and
+ * set sigreturn to be a pointer to these.
+ */
+ memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes,
+ sizeof(sigreturn_codes));
+
flush_icache_range(0xffff0000, 0xffff0000 + PAGE_SIZE);
modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
}
diff --git a/arch/arm/lib/ashldi3.c b/arch/arm/lib/ashldi3.c
index 130f5a83966..b62875cfd8f 100644
--- a/arch/arm/lib/ashldi3.c
+++ b/arch/arm/lib/ashldi3.c
@@ -31,31 +31,26 @@ Boston, MA 02111-1307, USA. */
#include "gcclib.h"
-DItype
-__ashldi3 (DItype u, word_type b)
+s64 __ashldi3(s64 u, int b)
{
- DIunion w;
- word_type bm;
- DIunion uu;
-
- if (b == 0)
- return u;
-
- uu.ll = u;
-
- bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
- if (bm <= 0)
- {
- w.s.low = 0;
- w.s.high = (USItype)uu.s.low << -bm;
- }
- else
- {
- USItype carries = (USItype)uu.s.low >> bm;
- w.s.low = (USItype)uu.s.low << b;
- w.s.high = ((USItype)uu.s.high << b) | carries;
- }
-
- return w.ll;
+ DIunion w;
+ int bm;
+ DIunion uu;
+
+ if (b == 0)
+ return u;
+
+ uu.ll = u;
+
+ bm = (sizeof(s32) * BITS_PER_UNIT) - b;
+ if (bm <= 0) {
+ w.s.low = 0;
+ w.s.high = (u32) uu.s.low << -bm;
+ } else {
+ u32 carries = (u32) uu.s.low >> bm;
+ w.s.low = (u32) uu.s.low << b;
+ w.s.high = ((u32) uu.s.high << b) | carries;
+ }
+
+ return w.ll;
}
-
diff --git a/arch/arm/lib/ashrdi3.c b/arch/arm/lib/ashrdi3.c
index 71625d218f8..9a8600a7543 100644
--- a/arch/arm/lib/ashrdi3.c
+++ b/arch/arm/lib/ashrdi3.c
@@ -31,31 +31,27 @@ Boston, MA 02111-1307, USA. */
#include "gcclib.h"
-DItype
-__ashrdi3 (DItype u, word_type b)
+s64 __ashrdi3(s64 u, int b)
{
- DIunion w;
- word_type bm;
- DIunion uu;
-
- if (b == 0)
- return u;
-
- uu.ll = u;
-
- bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
- if (bm <= 0)
- {
- /* w.s.high = 1..1 or 0..0 */
- w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
- w.s.low = uu.s.high >> -bm;
- }
- else
- {
- USItype carries = (USItype)uu.s.high << bm;
- w.s.high = uu.s.high >> b;
- w.s.low = ((USItype)uu.s.low >> b) | carries;
- }
-
- return w.ll;
+ DIunion w;
+ int bm;
+ DIunion uu;
+
+ if (b == 0)
+ return u;
+
+ uu.ll = u;
+
+ bm = (sizeof(s32) * BITS_PER_UNIT) - b;
+ if (bm <= 0) {
+ /* w.s.high = 1..1 or 0..0 */
+ w.s.high = uu.s.high >> (sizeof(s32) * BITS_PER_UNIT - 1);
+ w.s.low = uu.s.high >> -bm;
+ } else {
+ u32 carries = (u32) uu.s.high << bm;
+ w.s.high = uu.s.high >> b;
+ w.s.low = ((u32) uu.s.low >> b) | carries;
+ }
+
+ return w.ll;
}
diff --git a/arch/arm/lib/gcclib.h b/arch/arm/lib/gcclib.h
index 65314a3d9e2..8b6dcc656de 100644
--- a/arch/arm/lib/gcclib.h
+++ b/arch/arm/lib/gcclib.h
@@ -1,25 +1,22 @@
/* gcclib.h -- definitions for various functions 'borrowed' from gcc-2.95.3 */
/* I Molton 29/07/01 */
-#define BITS_PER_UNIT 8
-#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
+#include <linux/types.h>
-typedef unsigned int UQItype __attribute__ ((mode (QI)));
-typedef int SItype __attribute__ ((mode (SI)));
-typedef unsigned int USItype __attribute__ ((mode (SI)));
-typedef int DItype __attribute__ ((mode (DI)));
-typedef int word_type __attribute__ ((mode (__word__)));
-typedef unsigned int UDItype __attribute__ ((mode (DI)));
+#define BITS_PER_UNIT 8
+#define SI_TYPE_SIZE (sizeof(s32) * BITS_PER_UNIT)
#ifdef __ARMEB__
- struct DIstruct {SItype high, low;};
+struct DIstruct {
+ s32 high, low;
+};
#else
- struct DIstruct {SItype low, high;};
+struct DIstruct {
+ s32 low, high;
+};
#endif
-typedef union
-{
- struct DIstruct s;
- DItype ll;
+typedef union {
+ struct DIstruct s;
+ s64 ll;
} DIunion;
-
diff --git a/arch/arm/lib/io-writesw-armv4.S b/arch/arm/lib/io-writesw-armv4.S
index 6d1d7c27806..5e240e452af 100644
--- a/arch/arm/lib/io-writesw-armv4.S
+++ b/arch/arm/lib/io-writesw-armv4.S
@@ -87,9 +87,9 @@ ENTRY(__raw_writesw)
subs r2, r2, #2
orr ip, ip, r3, push_hbyte1
strh ip, [r0]
- bpl 2b
+ bpl 1b
-3: tst r2, #1
-2: movne ip, r3, lsr #8
+ tst r2, #1
+3: movne ip, r3, lsr #8
strneh ip, [r0]
mov pc, lr
diff --git a/arch/arm/lib/longlong.h b/arch/arm/lib/longlong.h
index 179eea4edc3..90ae647e4d7 100644
--- a/arch/arm/lib/longlong.h
+++ b/arch/arm/lib/longlong.h
@@ -26,18 +26,18 @@
#define __BITS4 (SI_TYPE_SIZE / 4)
#define __ll_B (1L << (SI_TYPE_SIZE / 2))
-#define __ll_lowpart(t) ((USItype) (t) % __ll_B)
-#define __ll_highpart(t) ((USItype) (t) / __ll_B)
+#define __ll_lowpart(t) ((u32) (t) % __ll_B)
+#define __ll_highpart(t) ((u32) (t) / __ll_B)
/* Define auxiliary asm macros.
1) umul_ppmm(high_prod, low_prod, multipler, multiplicand)
- multiplies two USItype integers MULTIPLER and MULTIPLICAND,
- and generates a two-part USItype product in HIGH_PROD and
+ multiplies two u32 integers MULTIPLER and MULTIPLICAND,
+ and generates a two-part u32 product in HIGH_PROD and
LOW_PROD.
- 2) __umulsidi3(a,b) multiplies two USItype integers A and B,
- and returns a UDItype product. This is just a variant of umul_ppmm.
+ 2) __umulsidi3(a,b) multiplies two u32 integers A and B,
+ and returns a u64 product. This is just a variant of umul_ppmm.
3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
denominator) divides a two-word unsigned integer, composed by the
@@ -77,23 +77,23 @@
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
__asm__ ("adds %1, %4, %5 \n\
adc %0, %2, %3" \
- : "=r" ((USItype) (sh)), \
- "=&r" ((USItype) (sl)) \
- : "%r" ((USItype) (ah)), \
- "rI" ((USItype) (bh)), \
- "%r" ((USItype) (al)), \
- "rI" ((USItype) (bl)))
+ : "=r" ((u32) (sh)), \
+ "=&r" ((u32) (sl)) \
+ : "%r" ((u32) (ah)), \
+ "rI" ((u32) (bh)), \
+ "%r" ((u32) (al)), \
+ "rI" ((u32) (bl)))
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
__asm__ ("subs %1, %4, %5 \n\
sbc %0, %2, %3" \
- : "=r" ((USItype) (sh)), \
- "=&r" ((USItype) (sl)) \
- : "r" ((USItype) (ah)), \
- "rI" ((USItype) (bh)), \
- "r" ((USItype) (al)), \
- "rI" ((USItype) (bl)))
+ : "=r" ((u32) (sh)), \
+ "=&r" ((u32) (sl)) \
+ : "r" ((u32) (ah)), \
+ "rI" ((u32) (bh)), \
+ "r" ((u32) (al)), \
+ "rI" ((u32) (bl)))
#define umul_ppmm(xh, xl, a, b) \
-{register USItype __t0, __t1, __t2; \
+{register u32 __t0, __t1, __t2; \
__asm__ ("%@ Inlined umul_ppmm \n\
mov %2, %5, lsr #16 \n\
mov %0, %6, lsr #16 \n\
@@ -107,14 +107,14 @@
addcs %0, %0, #65536 \n\
adds %1, %1, %3, lsl #16 \n\
adc %0, %0, %3, lsr #16" \
- : "=&r" ((USItype) (xh)), \
- "=r" ((USItype) (xl)), \
+ : "=&r" ((u32) (xh)), \
+ "=r" ((u32) (xl)), \
"=&r" (__t0), "=&r" (__t1), "=r" (__t2) \
- : "r" ((USItype) (a)), \
- "r" ((USItype) (b)));}
+ : "r" ((u32) (a)), \
+ "r" ((u32) (b)));}
#define UMUL_TIME 20
#define UDIV_TIME 100
-#endif /* __arm__ */
+#endif /* __arm__ */
#define __umulsidi3(u, v) \
({DIunion __w; \
@@ -123,14 +123,14 @@
#define __udiv_qrnnd_c(q, r, n1, n0, d) \
do { \
- USItype __d1, __d0, __q1, __q0; \
- USItype __r1, __r0, __m; \
+ u32 __d1, __d0, __q1, __q0; \
+ u32 __r1, __r0, __m; \
__d1 = __ll_highpart (d); \
__d0 = __ll_lowpart (d); \
\
__r1 = (n1) % __d1; \
__q1 = (n1) / __d1; \
- __m = (USItype) __q1 * __d0; \
+ __m = (u32) __q1 * __d0; \
__r1 = __r1 * __ll_B | __ll_highpart (n0); \
if (__r1 < __m) \
{ \
@@ -143,7 +143,7 @@
\
__r0 = __r1 % __d1; \
__q0 = __r1 / __d1; \
- __m = (USItype) __q0 * __d0; \
+ __m = (u32) __q0 * __d0; \
__r0 = __r0 * __ll_B | __ll_lowpart (n0); \
if (__r0 < __m) \
{ \
@@ -154,7 +154,7 @@
} \
__r0 -= __m; \
\
- (q) = (USItype) __q1 * __ll_B | __q0; \
+ (q) = (u32) __q1 * __ll_B | __q0; \
(r) = __r0; \
} while (0)
@@ -163,14 +163,14 @@
#define count_leading_zeros(count, x) \
do { \
- USItype __xr = (x); \
- USItype __a; \
+ u32 __xr = (x); \
+ u32 __a; \
\
if (SI_TYPE_SIZE <= 32) \
{ \
- __a = __xr < ((USItype)1<<2*__BITS4) \
- ? (__xr < ((USItype)1<<__BITS4) ? 0 : __BITS4) \
- : (__xr < ((USItype)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \
+ __a = __xr < ((u32)1<<2*__BITS4) \
+ ? (__xr < ((u32)1<<__BITS4) ? 0 : __BITS4) \
+ : (__xr < ((u32)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \
} \
else \
{ \
diff --git a/arch/arm/lib/lshrdi3.c b/arch/arm/lib/lshrdi3.c
index b666f1bad45..3681f49d2b6 100644
--- a/arch/arm/lib/lshrdi3.c
+++ b/arch/arm/lib/lshrdi3.c
@@ -31,31 +31,26 @@ Boston, MA 02111-1307, USA. */
#include "gcclib.h"
-DItype
-__lshrdi3 (DItype u, word_type b)
+s64 __lshrdi3(s64 u, int b)
{
- DIunion w;
- word_type bm;
- DIunion uu;
-
- if (b == 0)
- return u;
-
- uu.ll = u;
-
- bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
- if (bm <= 0)
- {
- w.s.high = 0;
- w.s.low = (USItype)uu.s.high >> -bm;
- }
- else
- {
- USItype carries = (USItype)uu.s.high << bm;
- w.s.high = (USItype)uu.s.high >> b;
- w.s.low = ((USItype)uu.s.low >> b) | carries;
- }
-
- return w.ll;
+ DIunion w;
+ int bm;
+ DIunion uu;
+
+ if (b == 0)
+ return u;
+
+ uu.ll = u;
+
+ bm = (sizeof(s32) * BITS_PER_UNIT) - b;
+ if (bm <= 0) {
+ w.s.high = 0;
+ w.s.low = (u32) uu.s.high >> -bm;
+ } else {
+ u32 carries = (u32) uu.s.high << bm;
+ w.s.high = (u32) uu.s.high >> b;
+ w.s.low = ((u32) uu.s.low >> b) | carries;
+ }
+
+ return w.ll;
}
-
diff --git a/arch/arm/lib/muldi3.c b/arch/arm/lib/muldi3.c
index 44d611b1cfd..0a3b93313f1 100644
--- a/arch/arm/lib/muldi3.c
+++ b/arch/arm/lib/muldi3.c
@@ -32,7 +32,7 @@ Boston, MA 02111-1307, USA. */
#include "gcclib.h"
#define umul_ppmm(xh, xl, a, b) \
-{register USItype __t0, __t1, __t2; \
+{register u32 __t0, __t1, __t2; \
__asm__ ("%@ Inlined umul_ppmm \n\
mov %2, %5, lsr #16 \n\
mov %0, %6, lsr #16 \n\
@@ -46,32 +46,27 @@ Boston, MA 02111-1307, USA. */
addcs %0, %0, #65536 \n\
adds %1, %1, %3, lsl #16 \n\
adc %0, %0, %3, lsr #16" \
- : "=&r" ((USItype) (xh)), \
- "=r" ((USItype) (xl)), \
+ : "=&r" ((u32) (xh)), \
+ "=r" ((u32) (xl)), \
"=&r" (__t0), "=&r" (__t1), "=r" (__t2) \
- : "r" ((USItype) (a)), \
- "r" ((USItype) (b)));}
-
+ : "r" ((u32) (a)), \
+ "r" ((u32) (b)));}
#define __umulsidi3(u, v) \
({DIunion __w; \
umul_ppmm (__w.s.high, __w.s.low, u, v); \
__w.ll; })
-
-DItype
-__muldi3 (DItype u, DItype v)
+s64 __muldi3(s64 u, s64 v)
{
- DIunion w;
- DIunion uu, vv;
+ DIunion w;
+ DIunion uu, vv;
- uu.ll = u,
- vv.ll = v;
+ uu.ll = u, vv.ll = v;
- w.ll = __umulsidi3 (uu.s.low, vv.s.low);
- w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
- + (USItype) uu.s.high * (USItype) vv.s.low);
+ w.ll = __umulsidi3(uu.s.low, vv.s.low);
+ w.s.high += ((u32) uu.s.low * (u32) vv.s.high
+ + (u32) uu.s.high * (u32) vv.s.low);
- return w.ll;
+ return w.ll;
}
-
diff --git a/arch/arm/lib/ucmpdi2.c b/arch/arm/lib/ucmpdi2.c
index 6c6ae63efa0..57f3f2df385 100644
--- a/arch/arm/lib/ucmpdi2.c
+++ b/arch/arm/lib/ucmpdi2.c
@@ -31,21 +31,19 @@ Boston, MA 02111-1307, USA. */
#include "gcclib.h"
-word_type
-__ucmpdi2 (DItype a, DItype b)
+int __ucmpdi2(s64 a, s64 b)
{
- DIunion au, bu;
-
- au.ll = a, bu.ll = b;
-
- if ((USItype) au.s.high < (USItype) bu.s.high)
- return 0;
- else if ((USItype) au.s.high > (USItype) bu.s.high)
- return 2;
- if ((USItype) au.s.low < (USItype) bu.s.low)
- return 0;
- else if ((USItype) au.s.low > (USItype) bu.s.low)
- return 2;
- return 1;
+ DIunion au, bu;
+
+ au.ll = a, bu.ll = b;
+
+ if ((u32) au.s.high < (u32) bu.s.high)
+ return 0;
+ else if ((u32) au.s.high > (u32) bu.s.high)
+ return 2;
+ if ((u32) au.s.low < (u32) bu.s.low)
+ return 0;
+ else if ((u32) au.s.low > (u32) bu.s.low)
+ return 2;
+ return 1;
}
-
diff --git a/arch/arm/lib/udivdi3.c b/arch/arm/lib/udivdi3.c
index d25195f673f..e343be4c664 100644
--- a/arch/arm/lib/udivdi3.c
+++ b/arch/arm/lib/udivdi3.c
@@ -32,211 +32,191 @@ Boston, MA 02111-1307, USA. */
#include "gcclib.h"
#include "longlong.h"
-static const UQItype __clz_tab[] =
-{
- 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
- 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
- 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+static const u8 __clz_tab[] = {
+ 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
};
-UDItype
-__udivmoddi4 (UDItype n, UDItype d, UDItype *rp)
+u64 __udivmoddi4(u64 n, u64 d, u64 * rp)
{
- DIunion ww;
- DIunion nn, dd;
- DIunion rr;
- USItype d0, d1, n0, n1, n2;
- USItype q0, q1;
- USItype b, bm;
-
- nn.ll = n;
- dd.ll = d;
-
- d0 = dd.s.low;
- d1 = dd.s.high;
- n0 = nn.s.low;
- n1 = nn.s.high;
-
- if (d1 == 0)
- {
- if (d0 > n1)
- {
- /* 0q = nn / 0D */
-
- count_leading_zeros (bm, d0);
-
- if (bm != 0)
- {
- /* Normalize, i.e. make the most significant bit of the
- denominator set. */
-
- d0 = d0 << bm;
- n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
- n0 = n0 << bm;
- }
-
- udiv_qrnnd (q0, n0, n1, n0, d0);
- q1 = 0;
-
- /* Remainder in n0 >> bm. */
- }
- else
- {
- /* qq = NN / 0d */
-
- if (d0 == 0)
- d0 = 1 / d0; /* Divide intentionally by zero. */
-
- count_leading_zeros (bm, d0);
-
- if (bm == 0)
- {
- /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
- conclude (the most significant bit of n1 is set) /\ (the
- leading quotient digit q1 = 1).
-
- This special case is necessary, not an optimization.
- (Shifts counts of SI_TYPE_SIZE are undefined.) */
-
- n1 -= d0;
- q1 = 1;
- }
- else
- {
- /* Normalize. */
-
- b = SI_TYPE_SIZE - bm;
-
- d0 = d0 << bm;
- n2 = n1 >> b;
- n1 = (n1 << bm) | (n0 >> b);
- n0 = n0 << bm;
-
- udiv_qrnnd (q1, n1, n2, n1, d0);
- }
-
- /* n1 != d0... */
-
- udiv_qrnnd (q0, n0, n1, n0, d0);
-
- /* Remainder in n0 >> bm. */
- }
-
- if (rp != 0)
- {
- rr.s.low = n0 >> bm;
- rr.s.high = 0;
- *rp = rr.ll;
- }
- }
- else
- {
- if (d1 > n1)
- {
- /* 00 = nn / DD */
-
- q0 = 0;
- q1 = 0;
-
- /* Remainder in n1n0. */
- if (rp != 0)
- {
- rr.s.low = n0;
- rr.s.high = n1;
- *rp = rr.ll;
- }
- }
- else
- {
- /* 0q = NN / dd */
-
- count_leading_zeros (bm, d1);
- if (bm == 0)
- {
- /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
- conclude (the most significant bit of n1 is set) /\ (the
- quotient digit q0 = 0 or 1).
-
- This special case is necessary, not an optimization. */
-
- /* The condition on the next line takes advantage of that
- n1 >= d1 (true due to program flow). */
- if (n1 > d1 || n0 >= d0)
- {
- q0 = 1;
- sub_ddmmss (n1, n0, n1, n0, d1, d0);
- }
- else
- q0 = 0;
-
- q1 = 0;
-
- if (rp != 0)
- {
- rr.s.low = n0;
- rr.s.high = n1;
- *rp = rr.ll;
- }
- }
- else
- {
- USItype m1, m0;
- /* Normalize. */
-
- b = SI_TYPE_SIZE - bm;
-
- d1 = (d1 << bm) | (d0 >> b);
- d0 = d0 << bm;
- n2 = n1 >> b;
- n1 = (n1 << bm) | (n0 >> b);
- n0 = n0 << bm;
-
- udiv_qrnnd (q0, n1, n2, n1, d1);
- umul_ppmm (m1, m0, q0, d0);
-
- if (m1 > n1 || (m1 == n1 && m0 > n0))
- {
- q0--;
- sub_ddmmss (m1, m0, m1, m0, d1, d0);
- }
-
- q1 = 0;
-
- /* Remainder in (n1n0 - m1m0) >> bm. */
- if (rp != 0)
- {
- sub_ddmmss (n1, n0, n1, n0, m1, m0);
- rr.s.low = (n1 << b) | (n0 >> bm);
- rr.s.high = n1 >> bm;
- *rp = rr.ll;
- }
- }
- }
- }
-
- ww.s.low = q0;
- ww.s.high = q1;
- return ww.ll;
+ DIunion ww;
+ DIunion nn, dd;
+ DIunion rr;
+ u32 d0, d1, n0, n1, n2;
+ u32 q0, q1;
+ u32 b, bm;
+
+ nn.ll = n;
+ dd.ll = d;
+
+ d0 = dd.s.low;
+ d1 = dd.s.high;
+ n0 = nn.s.low;
+ n1 = nn.s.high;
+
+ if (d1 == 0) {
+ if (d0 > n1) {
+ /* 0q = nn / 0D */
+
+ count_leading_zeros(bm, d0);
+
+ if (bm != 0) {
+ /* Normalize, i.e. make the most significant bit of the
+ denominator set. */
+
+ d0 = d0 << bm;
+ n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
+ n0 = n0 << bm;
+ }
+
+ udiv_qrnnd(q0, n0, n1, n0, d0);
+ q1 = 0;
+
+ /* Remainder in n0 >> bm. */
+ } else {
+ /* qq = NN / 0d */
+
+ if (d0 == 0)
+ d0 = 1 / d0; /* Divide intentionally by zero. */
+
+ count_leading_zeros(bm, d0);
+
+ if (bm == 0) {
+ /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
+ conclude (the most significant bit of n1 is set) /\ (the
+ leading quotient digit q1 = 1).
+
+ This special case is necessary, not an optimization.
+ (Shifts counts of SI_TYPE_SIZE are undefined.) */
+
+ n1 -= d0;
+ q1 = 1;
+ } else {
+ /* Normalize. */
+
+ b = SI_TYPE_SIZE - bm;
+
+ d0 = d0 << bm;
+ n2 = n1 >> b;
+ n1 = (n1 << bm) | (n0 >> b);
+ n0 = n0 << bm;
+
+ udiv_qrnnd(q1, n1, n2, n1, d0);
+ }
+
+ /* n1 != d0... */
+
+ udiv_qrnnd(q0, n0, n1, n0, d0);
+
+ /* Remainder in n0 >> bm. */
+ }
+
+ if (rp != 0) {
+ rr.s.low = n0 >> bm;
+ rr.s.high = 0;
+ *rp = rr.ll;
+ }
+ } else {
+ if (d1 > n1) {
+ /* 00 = nn / DD */
+
+ q0 = 0;
+ q1 = 0;
+
+ /* Remainder in n1n0. */
+ if (rp != 0) {
+ rr.s.low = n0;
+ rr.s.high = n1;
+ *rp = rr.ll;
+ }
+ } else {
+ /* 0q = NN / dd */
+
+ count_leading_zeros(bm, d1);
+ if (bm == 0) {
+ /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
+ conclude (the most significant bit of n1 is set) /\ (the
+ quotient digit q0 = 0 or 1).
+
+ This special case is necessary, not an optimization. */
+
+ /* The condition on the next line takes advantage of that
+ n1 >= d1 (true due to program flow). */
+ if (n1 > d1 || n0 >= d0) {
+ q0 = 1;
+ sub_ddmmss(n1, n0, n1, n0, d1, d0);
+ } else
+ q0 = 0;
+
+ q1 = 0;
+
+ if (rp != 0) {
+ rr.s.low = n0;
+ rr.s.high = n1;
+ *rp = rr.ll;
+ }
+ } else {
+ u32 m1, m0;
+ /* Normalize. */
+
+ b = SI_TYPE_SIZE - bm;
+
+ d1 = (d1 << bm) | (d0 >> b);
+ d0 = d0 << bm;
+ n2 = n1 >> b;
+ n1 = (n1 << bm) | (n0 >> b);
+ n0 = n0 << bm;
+
+ udiv_qrnnd(q0, n1, n2, n1, d1);
+ umul_ppmm(m1, m0, q0, d0);
+
+ if (m1 > n1 || (m1 == n1 && m0 > n0)) {
+ q0--;
+ sub_ddmmss(m1, m0, m1, m0, d1, d0);
+ }
+
+ q1 = 0;
+
+ /* Remainder in (n1n0 - m1m0) >> bm. */
+ if (rp != 0) {
+ sub_ddmmss(n1, n0, n1, n0, m1, m0);
+ rr.s.low = (n1 << b) | (n0 >> bm);
+ rr.s.high = n1 >> bm;
+ *rp = rr.ll;
+ }
+ }
+ }
+ }
+
+ ww.s.low = q0;
+ ww.s.high = q1;
+ return ww.ll;
}
-UDItype
-__udivdi3 (UDItype n, UDItype d)
+u64 __udivdi3(u64 n, u64 d)
{
- return __udivmoddi4 (n, d, (UDItype *) 0);
+ return __udivmoddi4(n, d, (u64 *) 0);
}
-UDItype
-__umoddi3 (UDItype u, UDItype v)
+u64 __umoddi3(u64 u, u64 v)
{
- UDItype w;
+ u64 w;
- (void) __udivmoddi4 (u ,v, &w);
+ (void)__udivmoddi4(u, v, &w);
- return w;
+ return w;
}
-
diff --git a/arch/arm/mach-aaec2000/Kconfig b/arch/arm/mach-aaec2000/Kconfig
new file mode 100644
index 00000000000..5e4bef93754
--- /dev/null
+++ b/arch/arm/mach-aaec2000/Kconfig
@@ -0,0 +1,11 @@
+if ARCH_AAEC2000
+
+menu "Agilent AAEC-2000 Implementations"
+
+config MACH_AAED2000
+ bool "Agilent AAED-2000 Development Platform"
+ select CPU_ARM920T
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-aaec2000/Makefile b/arch/arm/mach-aaec2000/Makefile
new file mode 100644
index 00000000000..20ec83896c3
--- /dev/null
+++ b/arch/arm/mach-aaec2000/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Common support (must be linked before board specific support)
+obj-y += core.o
+
+# Specific board support
+obj-$(CONFIG_MACH_AAED2000) += aaed2000.o
diff --git a/arch/arm/mach-aaec2000/aaed2000.c b/arch/arm/mach-aaec2000/aaed2000.c
new file mode 100644
index 00000000000..5417ca3f462
--- /dev/null
+++ b/arch/arm/mach-aaec2000/aaed2000.c
@@ -0,0 +1,48 @@
+/*
+ * linux/arch/arm/mach-aaec2000/aaed2000.c
+ *
+ * Support for the Agilent AAED-2000 Development Platform.
+ *
+ * Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ * 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.
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/major.h>
+#include <linux/interrupt.h>
+
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include "core.h"
+
+static void __init aaed2000_init_irq(void)
+{
+ aaec2000_init_irq();
+}
+
+static void __init aaed2000_map_io(void)
+{
+ aaec2000_map_io();
+}
+
+MACHINE_START(AAED2000, "Agilent AAED-2000 Development Platform")
+ MAINTAINER("Nicolas Bellido Y Ortega")
+ BOOT_MEM(0xf0000000, PIO_BASE, VIO_BASE)
+ MAPIO(aaed2000_map_io)
+ INITIRQ(aaed2000_init_irq)
+ .timer = &aaec2000_timer,
+MACHINE_END
diff --git a/arch/arm/mach-aaec2000/core.c b/arch/arm/mach-aaec2000/core.c
new file mode 100644
index 00000000000..fc145b3768f
--- /dev/null
+++ b/arch/arm/mach-aaec2000/core.c
@@ -0,0 +1,157 @@
+/*
+ * linux/arch/arm/mach-aaec2000/core.c
+ *
+ * Code common to all AAEC-2000 machines
+ *
+ * Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ * 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.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/signal.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+
+/*
+ * Common I/O mapping:
+ *
+ * Static virtual address mappings are as follow:
+ *
+ * 0xf8000000-0xf8001ffff: Devices connected to APB bus
+ * 0xf8002000-0xf8003ffff: Devices connected to AHB bus
+ *
+ * Below 0xe8000000 is reserved for vm allocation.
+ *
+ * The machine specific code must provide the extra mapping beside the
+ * default mapping provided here.
+ */
+static struct map_desc standard_io_desc[] __initdata = {
+ /* virtual physical length type */
+ { VIO_APB_BASE, PIO_APB_BASE, IO_APB_LENGTH, MT_DEVICE },
+ { VIO_AHB_BASE, PIO_AHB_BASE, IO_AHB_LENGTH, MT_DEVICE }
+};
+
+void __init aaec2000_map_io(void)
+{
+ iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
+}
+
+/*
+ * Interrupt handling routines
+ */
+static void aaec2000_int_ack(unsigned int irq)
+{
+ IRQ_INTSR = 1 << irq;
+}
+
+static void aaec2000_int_mask(unsigned int irq)
+{
+ IRQ_INTENC |= (1 << irq);
+}
+
+static void aaec2000_int_unmask(unsigned int irq)
+{
+ IRQ_INTENS |= (1 << irq);
+}
+
+static struct irqchip aaec2000_irq_chip = {
+ .ack = aaec2000_int_ack,
+ .mask = aaec2000_int_mask,
+ .unmask = aaec2000_int_unmask,
+};
+
+void __init aaec2000_init_irq(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < NR_IRQS; i++) {
+ set_irq_handler(i, do_level_IRQ);
+ set_irq_chip(i, &aaec2000_irq_chip);
+ set_irq_flags(i, IRQF_VALID);
+ }
+
+ /* Disable all interrupts */
+ IRQ_INTENC = 0xffffffff;
+
+ /* Clear any pending interrupts */
+ IRQ_INTSR = IRQ_INTSR;
+}
+
+/*
+ * Time keeping
+ */
+/* IRQs are disabled before entering here from do_gettimeofday() */
+static unsigned long aaec2000_gettimeoffset(void)
+{
+ unsigned long ticks_to_match, elapsed, usec;
+
+ /* Get ticks before next timer match */
+ ticks_to_match = TIMER1_LOAD - TIMER1_VAL;
+
+ /* We need elapsed ticks since last match */
+ elapsed = LATCH - ticks_to_match;
+
+ /* Now, convert them to usec */
+ usec = (unsigned long)(elapsed * (tick_nsec / 1000))/LATCH;
+
+ return usec;
+}
+
+/* We enter here with IRQs enabled */
+static irqreturn_t
+aaec2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ /* TODO: Check timer accuracy */
+ write_seqlock(&xtime_lock);
+
+ timer_tick(regs);
+ TIMER1_CLEAR = 1;
+
+ write_sequnlock(&xtime_lock);
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction aaec2000_timer_irq = {
+ .name = "AAEC-2000 Timer Tick",
+ .flags = SA_INTERRUPT,
+ .handler = aaec2000_timer_interrupt
+};
+
+static void __init aaec2000_timer_init(void)
+{
+ /* Disable timer 1 */
+ TIMER1_CTRL = 0;
+
+ /* We have somehow to generate a 100Hz clock.
+ * We then use the 508KHz timer in periodic mode.
+ */
+ TIMER1_LOAD = LATCH;
+ TIMER1_CLEAR = 1; /* Clear interrupt */
+
+ setup_irq(INT_TMR1_OFL, &aaec2000_timer_irq);
+
+ TIMER1_CTRL = TIMER_CTRL_ENABLE |
+ TIMER_CTRL_PERIODIC |
+ TIMER_CTRL_CLKSEL_508K;
+}
+
+struct sys_timer aaec2000_timer = {
+ .init = aaec2000_timer_init,
+ .offset = aaec2000_gettimeoffset,
+};
+
diff --git a/arch/arm/mach-aaec2000/core.h b/arch/arm/mach-aaec2000/core.h
new file mode 100644
index 00000000000..91893d848c1
--- /dev/null
+++ b/arch/arm/mach-aaec2000/core.h
@@ -0,0 +1,16 @@
+/*
+ * linux/arch/arm/mach-aaec2000/core.h
+ *
+ * Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ * 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.
+ *
+ */
+
+struct sys_timer;
+
+extern struct sys_timer aaec2000_timer;
+extern void __init aaec2000_map_io(void);
+extern void __init aaec2000_init_irq(void);
diff --git a/arch/arm/mach-clps711x/Kconfig b/arch/arm/mach-clps711x/Kconfig
index 45c930ccd06..0793dcf54f2 100644
--- a/arch/arm/mach-clps711x/Kconfig
+++ b/arch/arm/mach-clps711x/Kconfig
@@ -28,7 +28,7 @@ config ARCH_CLEP7312
config ARCH_EDB7211
bool "EDB7211"
select ISA
- select DISCONTIGMEM
+ select ARCH_DISCONTIGMEM_ENABLE
help
Say Y here if you intend to run this kernel on a Cirrus Logic EDB-7211
evaluation board.
diff --git a/arch/arm/mach-clps7500/core.c b/arch/arm/mach-clps7500/core.c
index fdfededfd96..0bc7da48861 100644
--- a/arch/arm/mach-clps7500/core.c
+++ b/arch/arm/mach-clps7500/core.c
@@ -26,6 +26,8 @@
#include <asm/irq.h>
#include <asm/mach-types.h>
+unsigned int vram_size;
+
static void cl7500_ack_irq_a(unsigned int irq)
{
unsigned int val, mask;
diff --git a/arch/arm/mach-integrator/Makefile b/arch/arm/mach-integrator/Makefile
index 158daaf9e3b..ebb255bdce8 100644
--- a/arch/arm/mach-integrator/Makefile
+++ b/arch/arm/mach-integrator/Makefile
@@ -12,3 +12,4 @@ obj-$(CONFIG_LEDS) += leds.o
obj-$(CONFIG_PCI) += pci_v3.o pci.o
obj-$(CONFIG_CPU_FREQ_INTEGRATOR) += cpu.o
obj-$(CONFIG_INTEGRATOR_IMPD1) += impd1.o
+obj-$(CONFIG_SMP) += platsmp.o headsmp.o
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c
index bd17b515431..bd1e5e3c9d3 100644
--- a/arch/arm/mach-integrator/core.c
+++ b/arch/arm/mach-integrator/core.c
@@ -14,6 +14,7 @@
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
+#include <linux/smp.h>
#include <asm/hardware.h>
#include <asm/irq.h>
@@ -221,7 +222,23 @@ integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
*/
timer1->TimerClear = 1;
- timer_tick(regs);
+ /*
+ * the clock tick routines are only processed on the
+ * primary CPU
+ */
+ if (hard_smp_processor_id() == 0) {
+ timer_tick(regs);
+#ifdef CONFIG_SMP
+ smp_send_timer();
+#endif
+ }
+
+#ifdef CONFIG_SMP
+ /*
+ * this is the ARM equivalent of the APIC timer interrupt
+ */
+ update_process_times(user_mode(regs));
+#endif /* CONFIG_SMP */
write_sequnlock(&xtime_lock);
diff --git a/arch/arm/mach-integrator/headsmp.S b/arch/arm/mach-integrator/headsmp.S
new file mode 100644
index 00000000000..ceaa88e30d7
--- /dev/null
+++ b/arch/arm/mach-integrator/headsmp.S
@@ -0,0 +1,37 @@
+/*
+ * linux/arch/arm/mach-integrator/headsmp.S
+ *
+ * Copyright (c) 2003 ARM Limited
+ * 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+ __INIT
+
+/*
+ * Integrator specific entry point for secondary CPUs. This provides
+ * a "holding pen" into which all secondary cores are held until we're
+ * ready for them to initialise.
+ */
+ENTRY(integrator_secondary_startup)
+ adr r4, 1f
+ ldmia r4, {r5, r6}
+ sub r4, r4, r5
+ ldr r6, [r6, r4]
+pen: ldr r7, [r6]
+ cmp r7, r0
+ bne pen
+
+ /*
+ * we've been released from the holding pen: secondary_stack
+ * should now contain the SVC stack for this core
+ */
+ b secondary_startup
+
+1: .long .
+ .long phys_pen_release
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 3b948e8c275..e0a01eef099 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -83,7 +83,6 @@ static struct map_desc intcp_io_desc[] __initdata = {
{ IO_ADDRESS(INTEGRATOR_UART1_BASE), INTEGRATOR_UART1_BASE, SZ_4K, MT_DEVICE },
{ IO_ADDRESS(INTEGRATOR_DBG_BASE), INTEGRATOR_DBG_BASE, SZ_4K, MT_DEVICE },
{ IO_ADDRESS(INTEGRATOR_GPIO_BASE), INTEGRATOR_GPIO_BASE, SZ_4K, MT_DEVICE },
- { 0xfc900000, 0xc9000000, SZ_4K, MT_DEVICE },
{ 0xfca00000, 0xca000000, SZ_4K, MT_DEVICE },
{ 0xfcb00000, 0xcb000000, SZ_4K, MT_DEVICE },
};
diff --git a/arch/arm/mach-integrator/leds.c b/arch/arm/mach-integrator/leds.c
index d2c0ab21150..f1436e683b4 100644
--- a/arch/arm/mach-integrator/leds.c
+++ b/arch/arm/mach-integrator/leds.c
@@ -22,6 +22,8 @@
*/
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
#include <asm/hardware.h>
#include <asm/io.h>
@@ -85,4 +87,4 @@ static int __init leds_init(void)
return 0;
}
-__initcall(leds_init);
+core_initcall(leds_init);
diff --git a/arch/arm/mach-integrator/platsmp.c b/arch/arm/mach-integrator/platsmp.c
new file mode 100644
index 00000000000..ead15dfcb53
--- /dev/null
+++ b/arch/arm/mach-integrator/platsmp.c
@@ -0,0 +1,192 @@
+/*
+ * linux/arch/arm/mach-cintegrator/platsmp.c
+ *
+ * Copyright (C) 2002 ARM Ltd.
+ * 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+
+#include <asm/atomic.h>
+#include <asm/delay.h>
+#include <asm/mmu_context.h>
+#include <asm/procinfo.h>
+#include <asm/ptrace.h>
+#include <asm/smp.h>
+
+extern void integrator_secondary_startup(void);
+
+/*
+ * control for which core is the next to come out of the secondary
+ * boot "holding pen"
+ */
+volatile int __initdata pen_release = -1;
+unsigned long __initdata phys_pen_release = 0;
+
+static DEFINE_SPINLOCK(boot_lock);
+
+void __init platform_secondary_init(unsigned int cpu)
+{
+ /*
+ * the primary core may have used a "cross call" soft interrupt
+ * to get this processor out of WFI in the BootMonitor - make
+ * sure that we are no longer being sent this soft interrupt
+ */
+ smp_cross_call_done(cpumask_of_cpu(cpu));
+
+ /*
+ * if any interrupts are already enabled for the primary
+ * core (e.g. timer irq), then they will not have been enabled
+ * for us: do so
+ */
+ secondary_scan_irqs();
+
+ /*
+ * let the primary processor know we're out of the
+ * pen, then head off into the C entry point
+ */
+ pen_release = -1;
+
+ /*
+ * Synchronise with the boot thread.
+ */
+ spin_lock(&boot_lock);
+ spin_unlock(&boot_lock);
+}
+
+int __init boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+ unsigned long timeout;
+
+ /*
+ * set synchronisation state between this boot processor
+ * and the secondary one
+ */
+ spin_lock(&boot_lock);
+
+ /*
+ * The secondary processor is waiting to be released from
+ * the holding pen - release it, then wait for it to flag
+ * that it has been released by resetting pen_release.
+ *
+ * Note that "pen_release" is the hardware CPU ID, whereas
+ * "cpu" is Linux's internal ID.
+ */
+ pen_release = cpu;
+
+ /*
+ * XXX
+ *
+ * This is a later addition to the booting protocol: the
+ * bootMonitor now puts secondary cores into WFI, so
+ * poke_milo() no longer gets the cores moving; we need
+ * to send a soft interrupt to wake the secondary core.
+ * Use smp_cross_call() for this, since there's little
+ * point duplicating the code here
+ */
+ smp_cross_call(cpumask_of_cpu(cpu));
+
+ timeout = jiffies + (1 * HZ);
+ while (time_before(jiffies, timeout)) {
+ if (pen_release == -1)
+ break;
+
+ udelay(10);
+ }
+
+ /*
+ * now the secondary core is starting up let it run its
+ * calibrations, then wait for it to finish
+ */
+ spin_unlock(&boot_lock);
+
+ return pen_release != -1 ? -ENOSYS : 0;
+}
+
+static void __init poke_milo(void)
+{
+ extern void secondary_startup(void);
+
+ /* nobody is to be released from the pen yet */
+ pen_release = -1;
+
+ phys_pen_release = virt_to_phys(&pen_release);
+
+ /*
+ * write the address of secondary startup into the system-wide
+ * flags register, then clear the bottom two bits, which is what
+ * BootMonitor is waiting for
+ */
+#if 1
+#define CINTEGRATOR_HDR_FLAGSS_OFFSET 0x30
+ __raw_writel(virt_to_phys(integrator_secondary_startup),
+ (IO_ADDRESS(INTEGRATOR_HDR_BASE) +
+ CINTEGRATOR_HDR_FLAGSS_OFFSET));
+#define CINTEGRATOR_HDR_FLAGSC_OFFSET 0x34
+ __raw_writel(3,
+ (IO_ADDRESS(INTEGRATOR_HDR_BASE) +
+ CINTEGRATOR_HDR_FLAGSC_OFFSET));
+#endif
+
+ mb();
+}
+
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+ unsigned int ncores = get_core_count();
+ unsigned int cpu = smp_processor_id();
+ int i;
+
+ /* sanity check */
+ if (ncores == 0) {
+ printk(KERN_ERR
+ "Integrator/CP: strange CM count of 0? Default to 1\n");
+
+ ncores = 1;
+ }
+
+ if (ncores > NR_CPUS) {
+ printk(KERN_WARNING
+ "Integrator/CP: no. of cores (%d) greater than configured "
+ "maximum of %d - clipping\n",
+ ncores, NR_CPUS);
+ ncores = NR_CPUS;
+ }
+
+ /*
+ * start with some more config for the Boot CPU, now that
+ * the world is a bit more alive (which was not the case
+ * when smp_prepare_boot_cpu() was called)
+ */
+ smp_store_cpu_info(cpu);
+
+ /*
+ * are we trying to boot more cores than exist?
+ */
+ if (max_cpus > ncores)
+ max_cpus = ncores;
+
+ /*
+ * Initialise the present mask - this tells us which CPUs should
+ * be present.
+ */
+ for (i = 0; i < max_cpus; i++) {
+ cpu_set(i, cpu_present_mask);
+ }
+
+ /*
+ * Do we need any more CPUs? If so, then let them know where
+ * to start. Note that, on modern versions of MILO, the "poke"
+ * doesn't actually do anything until each individual core is
+ * sent a soft interrupt to get it out of WFI
+ */
+ if (max_cpus > 1)
+ poke_milo();
+}
diff --git a/arch/arm/mach-ixp2000/Kconfig b/arch/arm/mach-ixp2000/Kconfig
index 9361e05f6fa..ecb58d83478 100644
--- a/arch/arm/mach-ixp2000/Kconfig
+++ b/arch/arm/mach-ixp2000/Kconfig
@@ -54,6 +54,14 @@ config ARCH_IXDP2X01
depends on ARCH_IXDP2401 || ARCH_IXDP2801
default y
+config IXP2000_SUPPORT_BROKEN_PCI_IO
+ bool "Support broken PCI I/O on older IXP2000s"
+ default y
+ help
+ Say 'N' here if you only intend to run your kernel on an
+ IXP2000 B0 or later model and do not need the PCI I/O
+ byteswap workaround. Say 'Y' otherwise.
+
endmenu
endif
diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c
index 4f3c3d5c781..0ee34acb8d7 100644
--- a/arch/arm/mach-ixp2000/core.c
+++ b/arch/arm/mach-ixp2000/core.c
@@ -40,6 +40,8 @@
#include <asm/mach/time.h>
#include <asm/mach/irq.h>
+#include <asm/arch/gpio.h>
+
static DEFINE_SPINLOCK(ixp2000_slowport_lock);
static unsigned long ixp2000_slowport_irq_flags;
@@ -162,12 +164,13 @@ void __init ixp2000_map_io(void)
static unsigned ticks_per_jiffy;
static unsigned ticks_per_usec;
static unsigned next_jiffy_time;
+static volatile unsigned long *missing_jiffy_timer_csr;
unsigned long ixp2000_gettimeoffset (void)
{
unsigned long offset;
- offset = next_jiffy_time - *IXP2000_T4_CSR;
+ offset = next_jiffy_time - *missing_jiffy_timer_csr;
return offset / ticks_per_usec;
}
@@ -178,8 +181,8 @@ static int ixp2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* clear timer 1 */
ixp2000_reg_write(IXP2000_T1_CLR, 1);
-
- while ((next_jiffy_time - *IXP2000_T4_CSR) > ticks_per_jiffy) {
+
+ while ((next_jiffy_time - *missing_jiffy_timer_csr) > ticks_per_jiffy) {
timer_tick(regs);
next_jiffy_time -= ticks_per_jiffy;
}
@@ -197,20 +200,37 @@ static struct irqaction ixp2000_timer_irq = {
void __init ixp2000_init_time(unsigned long tick_rate)
{
- ixp2000_reg_write(IXP2000_T1_CLR, 0);
- ixp2000_reg_write(IXP2000_T4_CLR, 0);
-
ticks_per_jiffy = (tick_rate + HZ/2) / HZ;
ticks_per_usec = tick_rate / 1000000;
+ /*
+ * We use timer 1 as our timer interrupt.
+ */
+ ixp2000_reg_write(IXP2000_T1_CLR, 0);
ixp2000_reg_write(IXP2000_T1_CLD, ticks_per_jiffy - 1);
ixp2000_reg_write(IXP2000_T1_CTL, (1 << 7));
/*
- * We use T4 as a monotonic counter to track missed jiffies
+ * We use a second timer as a monotonic counter for tracking
+ * missed jiffies. The IXP2000 has four timers, but if we're
+ * on an A-step IXP2800, timer 2 and 3 don't work, so on those
+ * chips we use timer 4. Timer 4 is the only timer that can
+ * be used for the watchdog, so we use timer 2 if we're on a
+ * non-buggy chip.
*/
- ixp2000_reg_write(IXP2000_T4_CLD, -1);
- ixp2000_reg_write(IXP2000_T4_CTL, (1 << 7));
+ if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) {
+ printk(KERN_INFO "Enabling IXP2800 erratum #25 workaround\n");
+
+ ixp2000_reg_write(IXP2000_T4_CLR, 0);
+ ixp2000_reg_write(IXP2000_T4_CLD, -1);
+ ixp2000_reg_write(IXP2000_T4_CTL, (1 << 7));
+ missing_jiffy_timer_csr = IXP2000_T4_CSR;
+ } else {
+ ixp2000_reg_write(IXP2000_T2_CLR, 0);
+ ixp2000_reg_write(IXP2000_T2_CLD, -1);
+ ixp2000_reg_write(IXP2000_T2_CTL, (1 << 7));
+ missing_jiffy_timer_csr = IXP2000_T2_CSR;
+ }
next_jiffy_time = 0xffffffff;
/* register for interrupt */
@@ -220,35 +240,40 @@ void __init ixp2000_init_time(unsigned long tick_rate)
/*************************************************************************
* GPIO helpers
*************************************************************************/
-static unsigned long GPIO_IRQ_rising_edge;
static unsigned long GPIO_IRQ_falling_edge;
+static unsigned long GPIO_IRQ_rising_edge;
static unsigned long GPIO_IRQ_level_low;
static unsigned long GPIO_IRQ_level_high;
-void gpio_line_config(int line, int style)
+static void update_gpio_int_csrs(void)
+{
+ ixp2000_reg_write(IXP2000_GPIO_FEDR, GPIO_IRQ_falling_edge);
+ ixp2000_reg_write(IXP2000_GPIO_REDR, GPIO_IRQ_rising_edge);
+ ixp2000_reg_write(IXP2000_GPIO_LSLR, GPIO_IRQ_level_low);
+ ixp2000_reg_write(IXP2000_GPIO_LSHR, GPIO_IRQ_level_high);
+}
+
+void gpio_line_config(int line, int direction)
{
unsigned long flags;
local_irq_save(flags);
+ if (direction == GPIO_OUT) {
+ irq_desc[line + IRQ_IXP2000_GPIO0].valid = 0;
- if(style == GPIO_OUT) {
/* if it's an output, it ain't an interrupt anymore */
- ixp2000_reg_write(IXP2000_GPIO_PDSR, (1 << line));
GPIO_IRQ_falling_edge &= ~(1 << line);
GPIO_IRQ_rising_edge &= ~(1 << line);
GPIO_IRQ_level_low &= ~(1 << line);
GPIO_IRQ_level_high &= ~(1 << line);
- ixp2000_reg_write(IXP2000_GPIO_FEDR, GPIO_IRQ_falling_edge);
- ixp2000_reg_write(IXP2000_GPIO_REDR, GPIO_IRQ_rising_edge);
- ixp2000_reg_write(IXP2000_GPIO_LSHR, GPIO_IRQ_level_high);
- ixp2000_reg_write(IXP2000_GPIO_LSLR, GPIO_IRQ_level_low);
- irq_desc[line+IRQ_IXP2000_GPIO0].valid = 0;
- } else if(style == GPIO_IN) {
- ixp2000_reg_write(IXP2000_GPIO_PDCR, (1 << line));
+ update_gpio_int_csrs();
+
+ ixp2000_reg_write(IXP2000_GPIO_PDSR, 1 << line);
+ } else if (direction == GPIO_IN) {
+ ixp2000_reg_write(IXP2000_GPIO_PDCR, 1 << line);
}
-
local_irq_restore(flags);
-}
+}
/*************************************************************************
@@ -267,9 +292,50 @@ static void ixp2000_GPIO_irq_handler(unsigned int irq, struct irqdesc *desc, str
}
}
+static int ixp2000_GPIO_irq_type(unsigned int irq, unsigned int type)
+{
+ int line = irq - IRQ_IXP2000_GPIO0;
+
+ /*
+ * First, configure this GPIO line as an input.
+ */
+ ixp2000_reg_write(IXP2000_GPIO_PDCR, 1 << line);
+
+ /*
+ * Then, set the proper trigger type.
+ */
+ if (type & IRQT_FALLING)
+ GPIO_IRQ_falling_edge |= 1 << line;
+ else
+ GPIO_IRQ_falling_edge &= ~(1 << line);
+ if (type & IRQT_RISING)
+ GPIO_IRQ_rising_edge |= 1 << line;
+ else
+ GPIO_IRQ_rising_edge &= ~(1 << line);
+ if (type & IRQT_LOW)
+ GPIO_IRQ_level_low |= 1 << line;
+ else
+ GPIO_IRQ_level_low &= ~(1 << line);
+ if (type & IRQT_HIGH)
+ GPIO_IRQ_level_high |= 1 << line;
+ else
+ GPIO_IRQ_level_high &= ~(1 << line);
+ update_gpio_int_csrs();
+
+ /*
+ * Finally, mark the corresponding IRQ as valid.
+ */
+ irq_desc[irq].valid = 1;
+
+ return 0;
+}
+
static void ixp2000_GPIO_irq_mask_ack(unsigned int irq)
{
ixp2000_reg_write(IXP2000_GPIO_INCR, (1 << (irq - IRQ_IXP2000_GPIO0)));
+
+ ixp2000_reg_write(IXP2000_GPIO_EDSR, (1 << (irq - IRQ_IXP2000_GPIO0)));
+ ixp2000_reg_write(IXP2000_GPIO_LDSR, (1 << (irq - IRQ_IXP2000_GPIO0)));
ixp2000_reg_write(IXP2000_GPIO_INST, (1 << (irq - IRQ_IXP2000_GPIO0)));
}
@@ -284,6 +350,7 @@ static void ixp2000_GPIO_irq_unmask(unsigned int irq)
}
static struct irqchip ixp2000_GPIO_irq_chip = {
+ .type = ixp2000_GPIO_irq_type,
.ack = ixp2000_GPIO_irq_mask_ack,
.mask = ixp2000_GPIO_irq_mask,
.unmask = ixp2000_GPIO_irq_unmask
@@ -320,7 +387,7 @@ static void ixp2000_irq_mask(unsigned int irq)
static void ixp2000_irq_unmask(unsigned int irq)
{
- ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << irq));
+ ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << irq));
}
static struct irqchip ixp2000_irq_chip = {
@@ -357,16 +424,16 @@ void __init ixp2000_init_irq(void)
* our mask/unmask code much simpler.
*/
for (irq = IRQ_IXP2000_SOFT_INT; irq <= IRQ_IXP2000_THDB3; irq++) {
- if((1 << irq) & IXP2000_VALID_IRQ_MASK) {
+ if ((1 << irq) & IXP2000_VALID_IRQ_MASK) {
set_irq_chip(irq, &ixp2000_irq_chip);
set_irq_handler(irq, do_level_IRQ);
set_irq_flags(irq, IRQF_VALID);
} else set_irq_flags(irq, 0);
}
-
+
/*
* GPIO IRQs are invalid until someone sets the interrupt mode
- * by calling gpio_line_set();
+ * by calling set_irq_type().
*/
for (irq = IRQ_IXP2000_GPIO0; irq <= IRQ_IXP2000_GPIO7; irq++) {
set_irq_chip(irq, &ixp2000_GPIO_irq_chip);
diff --git a/arch/arm/mach-ixp2000/enp2611.c b/arch/arm/mach-ixp2000/enp2611.c
index 04b38bcf9aa..f3a291b6a9f 100644
--- a/arch/arm/mach-ixp2000/enp2611.c
+++ b/arch/arm/mach-ixp2000/enp2611.c
@@ -197,8 +197,23 @@ static struct platform_device enp2611_flash = {
.resource = &enp2611_flash_resource,
};
+static struct ixp2000_i2c_pins enp2611_i2c_gpio_pins = {
+ .sda_pin = ENP2611_GPIO_SDA,
+ .scl_pin = ENP2611_GPIO_SCL,
+};
+
+static struct platform_device enp2611_i2c_controller = {
+ .name = "IXP2000-I2C",
+ .id = 0,
+ .dev = {
+ .platform_data = &enp2611_i2c_gpio_pins
+ },
+ .num_resources = 0
+};
+
static struct platform_device *enp2611_devices[] __initdata = {
- &enp2611_flash
+ &enp2611_flash,
+ &enp2611_i2c_controller
};
static void __init enp2611_init_machine(void)
diff --git a/arch/arm/mach-ixp2000/ixdp2x00.c b/arch/arm/mach-ixp2000/ixdp2x00.c
index 21c41fe15b9..5e4380747b5 100644
--- a/arch/arm/mach-ixp2000/ixdp2x00.c
+++ b/arch/arm/mach-ixp2000/ixdp2x00.c
@@ -42,6 +42,9 @@
#include <asm/mach/flash.h>
#include <asm/mach/arch.h>
+#include <asm/arch/gpio.h>
+
+
/*************************************************************************
* IXDP2x00 IRQ Initialization
*************************************************************************/
diff --git a/arch/arm/mach-ixp2000/pci.c b/arch/arm/mach-ixp2000/pci.c
index 5ff2f2718c5..0788fb2b5c1 100644
--- a/arch/arm/mach-ixp2000/pci.c
+++ b/arch/arm/mach-ixp2000/pci.c
@@ -198,6 +198,19 @@ clear_master_aborts(void)
void __init
ixp2000_pci_preinit(void)
{
+#ifndef CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO
+ /*
+ * Configure the PCI unit to properly byteswap I/O transactions,
+ * and verify that it worked.
+ */
+ ixp2000_reg_write(IXP2000_PCI_CONTROL,
+ (*IXP2000_PCI_CONTROL | PCI_CONTROL_IEE));
+
+ if ((*IXP2000_PCI_CONTROL & PCI_CONTROL_IEE) == 0)
+ panic("IXP2000: PCI I/O is broken on this ixp model, and "
+ "the needed workaround has not been configured in");
+#endif
+
hook_fault_code(16+6, ixp2000_pci_abort_handler, SIGBUS,
"PCI config cycle to non-existent device");
}
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index 267ba02d77d..f39e8408488 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -141,7 +141,15 @@ static struct map_desc ixp4xx_io_desc[] __initdata = {
.physical = IXP4XX_PCI_CFG_BASE_PHYS,
.length = IXP4XX_PCI_CFG_REGION_SIZE,
.type = MT_DEVICE
+ },
+#ifdef CONFIG_DEBUG_LL
+ { /* Debug UART mapping */
+ .virtual = IXP4XX_DEBUG_UART_BASE_VIRT,
+ .physical = IXP4XX_DEBUG_UART_BASE_PHYS,
+ .length = IXP4XX_DEBUG_UART_REGION_SIZE,
+ .type = MT_DEVICE
}
+#endif
};
void __init ixp4xx_map_io(void)
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index dd012d6e2f5..f2c9e0d2b24 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -15,6 +15,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
+#include <linux/sysdev.h>
#include <linux/major.h>
#include <linux/fb.h>
#include <linux/interrupt.h>
@@ -106,6 +107,35 @@ static void __init lubbock_init_irq(void)
set_irq_type(IRQ_GPIO(0), IRQT_FALLING);
}
+#ifdef CONFIG_PM
+
+static int lubbock_irq_resume(struct sys_device *dev)
+{
+ LUB_IRQ_MASK_EN = lubbock_irq_enabled;
+ return 0;
+}
+
+static struct sysdev_class lubbock_irq_sysclass = {
+ set_kset_name("cpld_irq"),
+ .resume = lubbock_irq_resume,
+};
+
+static struct sys_device lubbock_irq_device = {
+ .cls = &lubbock_irq_sysclass,
+};
+
+static int __init lubbock_irq_device_init(void)
+{
+ int ret = sysdev_class_register(&lubbock_irq_sysclass);
+ if (ret == 0)
+ ret = sysdev_register(&lubbock_irq_device);
+ return ret;
+}
+
+device_initcall(lubbock_irq_device_init);
+
+#endif
+
static int lubbock_udc_is_connected(void)
{
return (LUB_MISC_RD & (1 << 9)) == 0;
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 3f952237ae3..9896afca751 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/device.h>
+#include <linux/sysdev.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/bitops.h>
@@ -62,7 +63,6 @@ static struct irqchip mainstone_irq_chip = {
.unmask = mainstone_unmask_irq,
};
-
static void mainstone_irq_handler(unsigned int irq, struct irqdesc *desc,
struct pt_regs *regs)
{
@@ -100,6 +100,35 @@ static void __init mainstone_init_irq(void)
set_irq_type(IRQ_GPIO(0), IRQT_FALLING);
}
+#ifdef CONFIG_PM
+
+static int mainstone_irq_resume(struct sys_device *dev)
+{
+ MST_INTMSKENA = mainstone_irq_enabled;
+ return 0;
+}
+
+static struct sysdev_class mainstone_irq_sysclass = {
+ set_kset_name("cpld_irq"),
+ .resume = mainstone_irq_resume,
+};
+
+static struct sys_device mainstone_irq_device = {
+ .cls = &mainstone_irq_sysclass,
+};
+
+static int __init mainstone_irq_device_init(void)
+{
+ int ret = sysdev_class_register(&mainstone_irq_sysclass);
+ if (ret == 0)
+ ret = sysdev_register(&mainstone_irq_device);
+ return ret;
+}
+
+device_initcall(mainstone_irq_device_init);
+
+#endif
+
static struct resource smc91x_resources[] = {
[0] = {
@@ -304,6 +333,15 @@ static void __init mainstone_map_io(void)
PWER = 0xC0000002;
PRER = 0x00000002;
PFER = 0x00000002;
+ /* for use I SRAM as framebuffer. */
+ PSLR |= 0xF04;
+ PCFR = 0x66;
+ /* For Keypad wakeup. */
+ KPC &=~KPC_ASACT;
+ KPC |=KPC_AS;
+ PKWR = 0x000FD000;
+ /* Need read PKWR back after set it. */
+ PKWR;
}
MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c
index 82a4bf34c25..ac4dd433616 100644
--- a/arch/arm/mach-pxa/pm.c
+++ b/arch/arm/mach-pxa/pm.c
@@ -29,9 +29,6 @@
*/
#undef DEBUG
-extern void pxa_cpu_suspend(void);
-extern void pxa_cpu_resume(void);
-
#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
#define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x]
@@ -63,6 +60,12 @@ enum { SLEEP_SAVE_START = 0,
SLEEP_SAVE_ICMR,
SLEEP_SAVE_CKEN,
+#ifdef CONFIG_PXA27x
+ SLEEP_SAVE_MDREFR,
+ SLEEP_SAVE_PWER, SLEEP_SAVE_PCFR, SLEEP_SAVE_PRER,
+ SLEEP_SAVE_PFER, SLEEP_SAVE_PKWR,
+#endif
+
SLEEP_SAVE_CKSUM,
SLEEP_SAVE_SIZE
@@ -75,9 +78,7 @@ static int pxa_pm_enter(suspend_state_t state)
unsigned long checksum = 0;
struct timespec delta, rtc;
int i;
-
- if (state != PM_SUSPEND_MEM)
- return -EINVAL;
+ extern void pxa_cpu_pm_enter(suspend_state_t state);
#ifdef CONFIG_IWMMXT
/* force any iWMMXt context to ram **/
@@ -100,16 +101,17 @@ static int pxa_pm_enter(suspend_state_t state)
SAVE(GAFR2_L); SAVE(GAFR2_U);
#ifdef CONFIG_PXA27x
+ SAVE(MDREFR);
SAVE(GPLR3); SAVE(GPDR3); SAVE(GRER3); SAVE(GFER3); SAVE(PGSR3);
SAVE(GAFR3_L); SAVE(GAFR3_U);
+ SAVE(PWER); SAVE(PCFR); SAVE(PRER);
+ SAVE(PFER); SAVE(PKWR);
#endif
SAVE(ICMR);
ICMR = 0;
SAVE(CKEN);
- CKEN = 0;
-
SAVE(PSTR);
/* Note: wake up source are set up in each machine specific files */
@@ -123,16 +125,15 @@ static int pxa_pm_enter(suspend_state_t state)
/* Clear sleep reset status */
RCSR = RCSR_SMR;
- /* set resume return address */
- PSPR = virt_to_phys(pxa_cpu_resume);
-
/* before sleeping, calculate and save a checksum */
for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++)
checksum += sleep_save[i];
sleep_save[SLEEP_SAVE_CKSUM] = checksum;
/* *** go zzz *** */
- pxa_cpu_suspend();
+ pxa_cpu_pm_enter(state);
+
+ cpu_init();
/* after sleeping, validate the checksum */
checksum = 0;
@@ -145,7 +146,7 @@ static int pxa_pm_enter(suspend_state_t state)
LUB_HEXLED = 0xbadbadc5;
#endif
while (1)
- pxa_cpu_suspend();
+ pxa_cpu_pm_enter(state);
}
/* ensure not to come back here if it wasn't intended */
@@ -162,8 +163,11 @@ static int pxa_pm_enter(suspend_state_t state)
RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2);
#ifdef CONFIG_PXA27x
+ RESTORE(MDREFR);
RESTORE(GAFR3_L); RESTORE(GAFR3_U); RESTORE_GPLEVEL(3);
RESTORE(GPDR3); RESTORE(GRER3); RESTORE(GFER3); RESTORE(PGSR3);
+ RESTORE(PWER); RESTORE(PCFR); RESTORE(PRER);
+ RESTORE(PFER); RESTORE(PKWR);
#endif
PSSR = PSSR_RDH | PSSR_PH;
@@ -197,7 +201,9 @@ unsigned long sleep_phys_sp(void *sp)
*/
static int pxa_pm_prepare(suspend_state_t state)
{
- return 0;
+ extern int pxa_cpu_pm_prepare(suspend_state_t state);
+
+ return pxa_cpu_pm_prepare(state);
}
/*
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index e887b7175ef..7869c3b4e62 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -16,6 +16,7 @@
* initialization stuff for PXA machines which can be overridden later if
* need be.
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -102,3 +103,35 @@ unsigned int get_lcdclk_frequency_10khz(void)
}
EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
+
+#ifdef CONFIG_PM
+
+int pxa_cpu_pm_prepare(suspend_state_t state)
+{
+ switch (state) {
+ case PM_SUSPEND_MEM:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+void pxa_cpu_pm_enter(suspend_state_t state)
+{
+ extern void pxa_cpu_suspend(unsigned int);
+ extern void pxa_cpu_resume(void);
+
+ CKEN = 0;
+
+ switch (state) {
+ case PM_SUSPEND_MEM:
+ /* set resume return address */
+ PSPR = virt_to_phys(pxa_cpu_resume);
+ pxa_cpu_suspend(3);
+ break;
+ }
+}
+
+#endif
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 7e863afefb5..893964fb965 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -120,6 +120,42 @@ EXPORT_SYMBOL(get_clk_frequency_khz);
EXPORT_SYMBOL(get_memclk_frequency_10khz);
EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
+#ifdef CONFIG_PM
+
+int pxa_cpu_pm_prepare(suspend_state_t state)
+{
+ switch (state) {
+ case PM_SUSPEND_MEM:
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+void pxa_cpu_pm_enter(suspend_state_t state)
+{
+ extern void pxa_cpu_standby(void);
+ extern void pxa_cpu_suspend(unsigned int);
+ extern void pxa_cpu_resume(void);
+
+ CKEN = CKEN22_MEMC | CKEN9_OSTIMER;
+
+ /* ensure voltage-change sequencer not initiated, which hangs */
+ PCFR &= ~PCFR_FVC;
+
+ /* Clear edge-detect status register. */
+ PEDR = 0xDF12FE1B;
+
+ switch (state) {
+ case PM_SUSPEND_MEM:
+ /* set resume return address */
+ PSPR = virt_to_phys(pxa_cpu_resume);
+ pxa_cpu_suspend(3);
+ break;
+ }
+}
+
+#endif
/*
* device registration specific to PXA27x.
diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c
index 815c53225cd..43710688143 100644
--- a/arch/arm/mach-rpc/riscpc.c
+++ b/arch/arm/mach-rpc/riscpc.c
@@ -32,10 +32,7 @@
extern void rpc_init_irq(void);
-extern unsigned int vram_size;
-
-#if 0
-
+unsigned int vram_size;
unsigned int memc_ctrl_reg;
unsigned int number_mfm_drives;
@@ -63,8 +60,6 @@ static int __init parse_tag_acorn(const struct tag *tag)
__tagtable(ATAG_ACORN, parse_tag_acorn);
-#endif
-
static struct map_desc rpc_io_desc[] __initdata = {
{ SCREEN_BASE, SCREEN_START, 2*1048576, MT_DEVICE }, /* VRAM */
{ (u32)IO_BASE, IO_START, IO_SIZE , MT_DEVICE }, /* IO space */
diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
index e23f534d4e1..8d986b8401c 100644
--- a/arch/arm/mach-s3c2410/clock.c
+++ b/arch/arm/mach-s3c2410/clock.c
@@ -478,7 +478,7 @@ static int s3c2440_clk_add(struct sys_device *sysdev)
{
unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
- s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal.rate) * 2;
+ s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal.rate);
printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz\n",
print_mhz(s3c2440_clk_upll.rate));
diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c
index bc229fab86d..c7c28890d40 100644
--- a/arch/arm/mach-s3c2410/dma.c
+++ b/arch/arm/mach-s3c2410/dma.c
@@ -785,6 +785,10 @@ int s3c2410_dma_free(dmach_t channel, s3c2410_dma_client_t *client)
chan->client = NULL;
chan->in_use = 0;
+ if (chan->irq_claimed)
+ free_irq(chan->irq, (void *)chan);
+ chan->irq_claimed = 0;
+
local_irq_restore(flags);
return 0;
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index 3bb97eb6e69..f3e970039b6 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -26,6 +26,7 @@
* 03-Mar-2005 BJD Ensured that bast-cpld.h is included
* 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
* 14-Mar-2006 BJD Updated for __iomem changes
+ * 22-Jun-2006 BJD Added DM9000 platform information
*/
#include <linux/kernel.h>
@@ -35,6 +36,7 @@
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/device.h>
+#include <linux/dm9000.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
@@ -53,6 +55,7 @@
#include <asm/arch/regs-serial.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-lcd.h>
#include <asm/arch/nand.h>
#include <linux/mtd/mtd.h>
@@ -112,7 +115,6 @@ static struct map_desc bast_iodesc[] __initdata = {
{ VA_C2(BAST_VA_ISAMEM), PA_CS2(BAST_PA_ISAMEM), SZ_16M, MT_DEVICE },
{ VA_C2(BAST_VA_ASIXNET), PA_CS3(BAST_PA_ASIXNET), SZ_1M, MT_DEVICE },
{ VA_C2(BAST_VA_SUPERIO), PA_CS2(BAST_PA_SUPERIO), SZ_1M, MT_DEVICE },
- { VA_C2(BAST_VA_DM9000), PA_CS2(BAST_PA_DM9000), SZ_1M, MT_DEVICE },
{ VA_C2(BAST_VA_IDEPRI), PA_CS3(BAST_PA_IDEPRI), SZ_1M, MT_DEVICE },
{ VA_C2(BAST_VA_IDESEC), PA_CS3(BAST_PA_IDESEC), SZ_1M, MT_DEVICE },
{ VA_C2(BAST_VA_IDEPRIAUX), PA_CS3(BAST_PA_IDEPRIAUX), SZ_1M, MT_DEVICE },
@@ -123,7 +125,6 @@ static struct map_desc bast_iodesc[] __initdata = {
{ VA_C3(BAST_VA_ISAMEM), PA_CS3(BAST_PA_ISAMEM), SZ_16M, MT_DEVICE },
{ VA_C3(BAST_VA_ASIXNET), PA_CS3(BAST_PA_ASIXNET), SZ_1M, MT_DEVICE },
{ VA_C3(BAST_VA_SUPERIO), PA_CS3(BAST_PA_SUPERIO), SZ_1M, MT_DEVICE },
- { VA_C3(BAST_VA_DM9000), PA_CS3(BAST_PA_DM9000), SZ_1M, MT_DEVICE },
{ VA_C3(BAST_VA_IDEPRI), PA_CS3(BAST_PA_IDEPRI), SZ_1M, MT_DEVICE },
{ VA_C3(BAST_VA_IDESEC), PA_CS3(BAST_PA_IDESEC), SZ_1M, MT_DEVICE },
{ VA_C3(BAST_VA_IDEPRIAUX), PA_CS3(BAST_PA_IDEPRIAUX), SZ_1M, MT_DEVICE },
@@ -134,7 +135,6 @@ static struct map_desc bast_iodesc[] __initdata = {
{ VA_C4(BAST_VA_ISAMEM), PA_CS4(BAST_PA_ISAMEM), SZ_16M, MT_DEVICE },
{ VA_C4(BAST_VA_ASIXNET), PA_CS5(BAST_PA_ASIXNET), SZ_1M, MT_DEVICE },
{ VA_C4(BAST_VA_SUPERIO), PA_CS4(BAST_PA_SUPERIO), SZ_1M, MT_DEVICE },
- { VA_C4(BAST_VA_DM9000), PA_CS4(BAST_PA_DM9000), SZ_1M, MT_DEVICE },
{ VA_C4(BAST_VA_IDEPRI), PA_CS5(BAST_PA_IDEPRI), SZ_1M, MT_DEVICE },
{ VA_C4(BAST_VA_IDESEC), PA_CS5(BAST_PA_IDESEC), SZ_1M, MT_DEVICE },
{ VA_C4(BAST_VA_IDEPRIAUX), PA_CS5(BAST_PA_IDEPRIAUX), SZ_1M, MT_DEVICE },
@@ -145,7 +145,6 @@ static struct map_desc bast_iodesc[] __initdata = {
{ VA_C5(BAST_VA_ISAMEM), PA_CS5(BAST_PA_ISAMEM), SZ_16M, MT_DEVICE },
{ VA_C5(BAST_VA_ASIXNET), PA_CS5(BAST_PA_ASIXNET), SZ_1M, MT_DEVICE },
{ VA_C5(BAST_VA_SUPERIO), PA_CS5(BAST_PA_SUPERIO), SZ_1M, MT_DEVICE },
- { VA_C5(BAST_VA_DM9000), PA_CS5(BAST_PA_DM9000), SZ_1M, MT_DEVICE },
{ VA_C5(BAST_VA_IDEPRI), PA_CS5(BAST_PA_IDEPRI), SZ_1M, MT_DEVICE },
{ VA_C5(BAST_VA_IDESEC), PA_CS5(BAST_PA_IDESEC), SZ_1M, MT_DEVICE },
{ VA_C5(BAST_VA_IDEPRIAUX), PA_CS5(BAST_PA_IDEPRIAUX), SZ_1M, MT_DEVICE },
@@ -313,6 +312,45 @@ static struct s3c2410_platform_nand bast_nand_info = {
.select_chip = bast_nand_select,
};
+/* DM9000 */
+
+static struct resource bast_dm9k_resource[] = {
+ [0] = {
+ .start = S3C2410_CS5 + BAST_PA_DM9000,
+ .end = S3C2410_CS5 + BAST_PA_DM9000 + 3,
+ .flags = IORESOURCE_MEM
+ },
+ [1] = {
+ .start = S3C2410_CS5 + BAST_PA_DM9000 + 0x40,
+ .end = S3C2410_CS5 + BAST_PA_DM9000 + 0x40 + 0x3f,
+ .flags = IORESOURCE_MEM
+ },
+ [2] = {
+ .start = IRQ_DM9000,
+ .end = IRQ_DM9000,
+ .flags = IORESOURCE_IRQ
+ }
+
+};
+
+/* for the moment we limit ourselves to 16bit IO until some
+ * better IO routines can be written and tested
+*/
+
+struct dm9000_plat_data bast_dm9k_platdata = {
+ .flags = DM9000_PLATF_16BITONLY
+};
+
+static struct platform_device bast_device_dm9k = {
+ .name = "dm9000",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(bast_dm9k_resource),
+ .resource = bast_dm9k_resource,
+ .dev = {
+ .platform_data = &bast_dm9k_platdata,
+ }
+};
+
/* Standard BAST devices */
@@ -324,7 +362,8 @@ static struct platform_device *bast_devices[] __initdata = {
&s3c_device_iis,
&s3c_device_rtc,
&s3c_device_nand,
- &bast_device_nor
+ &bast_device_nor,
+ &bast_device_dm9k,
};
static struct clk *bast_clocks[] = {
diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
index 5512146b1ce..76be074944a 100644
--- a/arch/arm/mach-s3c2410/mach-vr1000.c
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c
@@ -27,6 +27,7 @@
* 10-Feb-2005 BJD Added power-off capability
* 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
* 14-Mar-2006 BJD void __iomem fixes
+ * 22-Jun-2006 BJD Added DM9000 platform information
*/
#include <linux/kernel.h>
@@ -35,6 +36,7 @@
#include <linux/list.h>
#include <linux/timer.h>
#include <linux/init.h>
+#include <linux/dm9000.h>
#include <linux/serial.h>
#include <linux/tty.h>
@@ -98,28 +100,24 @@ static struct map_desc vr1000_iodesc[] __initdata = {
* are only 8bit */
/* slow, byte */
- { VA_C2(VR1000_VA_DM9000), PA_CS2(VR1000_PA_DM9000), SZ_1M, MT_DEVICE },
{ VA_C2(VR1000_VA_IDEPRI), PA_CS3(VR1000_PA_IDEPRI), SZ_1M, MT_DEVICE },
{ VA_C2(VR1000_VA_IDESEC), PA_CS3(VR1000_PA_IDESEC), SZ_1M, MT_DEVICE },
{ VA_C2(VR1000_VA_IDEPRIAUX), PA_CS3(VR1000_PA_IDEPRIAUX), SZ_1M, MT_DEVICE },
{ VA_C2(VR1000_VA_IDESECAUX), PA_CS3(VR1000_PA_IDESECAUX), SZ_1M, MT_DEVICE },
/* slow, word */
- { VA_C3(VR1000_VA_DM9000), PA_CS3(VR1000_PA_DM9000), SZ_1M, MT_DEVICE },
{ VA_C3(VR1000_VA_IDEPRI), PA_CS3(VR1000_PA_IDEPRI), SZ_1M, MT_DEVICE },
{ VA_C3(VR1000_VA_IDESEC), PA_CS3(VR1000_PA_IDESEC), SZ_1M, MT_DEVICE },
{ VA_C3(VR1000_VA_IDEPRIAUX), PA_CS3(VR1000_PA_IDEPRIAUX), SZ_1M, MT_DEVICE },
{ VA_C3(VR1000_VA_IDESECAUX), PA_CS3(VR1000_PA_IDESECAUX), SZ_1M, MT_DEVICE },
/* fast, byte */
- { VA_C4(VR1000_VA_DM9000), PA_CS4(VR1000_PA_DM9000), SZ_1M, MT_DEVICE },
{ VA_C4(VR1000_VA_IDEPRI), PA_CS5(VR1000_PA_IDEPRI), SZ_1M, MT_DEVICE },
{ VA_C4(VR1000_VA_IDESEC), PA_CS5(VR1000_PA_IDESEC), SZ_1M, MT_DEVICE },
{ VA_C4(VR1000_VA_IDEPRIAUX), PA_CS5(VR1000_PA_IDEPRIAUX), SZ_1M, MT_DEVICE },
{ VA_C4(VR1000_VA_IDESECAUX), PA_CS5(VR1000_PA_IDESECAUX), SZ_1M, MT_DEVICE },
/* fast, word */
- { VA_C5(VR1000_VA_DM9000), PA_CS5(VR1000_PA_DM9000), SZ_1M, MT_DEVICE },
{ VA_C5(VR1000_VA_IDEPRI), PA_CS5(VR1000_PA_IDEPRI), SZ_1M, MT_DEVICE },
{ VA_C5(VR1000_VA_IDESEC), PA_CS5(VR1000_PA_IDESEC), SZ_1M, MT_DEVICE },
{ VA_C5(VR1000_VA_IDEPRIAUX), PA_CS5(VR1000_PA_IDEPRIAUX), SZ_1M, MT_DEVICE },
@@ -246,6 +244,74 @@ static struct platform_device vr1000_nor = {
.resource = vr1000_nor_resource,
};
+/* DM9000 ethernet devices */
+
+static struct resource vr1000_dm9k0_resource[] = {
+ [0] = {
+ .start = S3C2410_CS5 + VR1000_PA_DM9000,
+ .end = S3C2410_CS5 + VR1000_PA_DM9000 + 3,
+ .flags = IORESOURCE_MEM
+ },
+ [1] = {
+ .start = S3C2410_CS5 + VR1000_PA_DM9000 + 0x40,
+ .end = S3C2410_CS5 + VR1000_PA_DM9000 + 0x7f,
+ .flags = IORESOURCE_MEM
+ },
+ [2] = {
+ .start = IRQ_VR1000_DM9000A,
+ .end = IRQ_VR1000_DM9000A,
+ .flags = IORESOURCE_IRQ
+ }
+
+};
+
+static struct resource vr1000_dm9k1_resource[] = {
+ [0] = {
+ .start = S3C2410_CS5 + VR1000_PA_DM9000 + 0x80,
+ .end = S3C2410_CS5 + VR1000_PA_DM9000 + 0x83,
+ .flags = IORESOURCE_MEM
+ },
+ [1] = {
+ .start = S3C2410_CS5 + VR1000_PA_DM9000 + 0xC0,
+ .end = S3C2410_CS5 + VR1000_PA_DM9000 + 0xFF,
+ .flags = IORESOURCE_MEM
+ },
+ [2] = {
+ .start = IRQ_VR1000_DM9000N,
+ .end = IRQ_VR1000_DM9000N,
+ .flags = IORESOURCE_IRQ
+ }
+};
+
+/* for the moment we limit ourselves to 16bit IO until some
+ * better IO routines can be written and tested
+*/
+
+struct dm9000_plat_data vr1000_dm9k_platdata = {
+ .flags = DM9000_PLATF_16BITONLY,
+};
+
+static struct platform_device vr1000_dm9k0 = {
+ .name = "dm9000",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(vr1000_dm9k0_resource),
+ .resource = vr1000_dm9k0_resource,
+ .dev = {
+ .platform_data = &vr1000_dm9k_platdata,
+ }
+};
+
+static struct platform_device vr1000_dm9k1 = {
+ .name = "dm9000",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(vr1000_dm9k1_resource),
+ .resource = vr1000_dm9k1_resource,
+ .dev = {
+ .platform_data = &vr1000_dm9k_platdata,
+ }
+};
+
+/* devices for this board */
static struct platform_device *vr1000_devices[] __initdata = {
&s3c_device_usb,
@@ -253,8 +319,11 @@ static struct platform_device *vr1000_devices[] __initdata = {
&s3c_device_wdt,
&s3c_device_i2c,
&s3c_device_iis,
+ &s3c_device_adc,
&serial_device,
&vr1000_nor,
+ &vr1000_dm9k0,
+ &vr1000_dm9k1
};
static struct clk *vr1000_clocks[] = {
diff --git a/arch/arm/mach-s3c2410/s3c2440.c b/arch/arm/mach-s3c2410/s3c2440.c
index 9a8cc5ae225..d4c8281b55f 100644
--- a/arch/arm/mach-s3c2410/s3c2440.c
+++ b/arch/arm/mach-s3c2410/s3c2440.c
@@ -192,9 +192,11 @@ void __init s3c2440_map_io(struct map_desc *mach_desc, int size)
iotable_init(s3c2440_iodesc, ARRAY_SIZE(s3c2440_iodesc));
iotable_init(mach_desc, size);
+
/* rename any peripherals used differing from the s3c2410 */
- s3c_device_i2c.name = "s3c2440-i2c";
+ s3c_device_i2c.name = "s3c2440-i2c";
+ s3c_device_nand.name = "s3c2440-nand";
/* change irq for watchdog */
@@ -225,7 +227,7 @@ void __init s3c2440_init_clocks(int xtal)
break;
case S3C2440_CLKDIVN_HDIVN_2:
- hdiv = 1;
+ hdiv = 2;
break;
case S3C2440_CLKDIVN_HDIVN_4_8:
diff --git a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig
index 50cde576dad..6923316b3d0 100644
--- a/arch/arm/mach-sa1100/Kconfig
+++ b/arch/arm/mach-sa1100/Kconfig
@@ -150,7 +150,7 @@ config SA1100_SSP
config H3600_SLEEVE
tristate "Compaq iPAQ Handheld sleeve support"
- depends on SA1100_H3600
+ depends on SA1100_H3100 || SA1100_H3600
help
Choose this option to enable support for extension packs (sleeves)
for the Compaq iPAQ H3XXX series of handheld computers. This option
diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c
index 379ea5e3950..59c7964cfe1 100644
--- a/arch/arm/mach-sa1100/pm.c
+++ b/arch/arm/mach-sa1100/pm.c
@@ -88,6 +88,8 @@ static int sa11x0_pm_enter(suspend_state_t state)
/* go zzz */
sa1100_cpu_suspend();
+ cpu_init();
+
/*
* Ensure not to come back here if it wasn't intended
*/
diff --git a/arch/arm/mach-versatile/Makefile b/arch/arm/mach-versatile/Makefile
index 5d608837757..ba81e70ed81 100644
--- a/arch/arm/mach-versatile/Makefile
+++ b/arch/arm/mach-versatile/Makefile
@@ -5,3 +5,4 @@
obj-y := core.o clock.o
obj-$(CONFIG_ARCH_VERSATILE_PB) += versatile_pb.o
obj-$(CONFIG_MACH_VERSATILE_AB) += versatile_ab.o
+obj-$(CONFIG_PCI) += pci.o
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index 554e1bd30d6..6a7cbea5e09 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -196,11 +196,15 @@ static struct map_desc versatile_io_desc[] __initdata = {
#ifdef CONFIG_DEBUG_LL
{ IO_ADDRESS(VERSATILE_UART0_BASE), VERSATILE_UART0_BASE, SZ_4K, MT_DEVICE },
#endif
-#ifdef FIXME
- { PCI_MEMORY_VADDR, PHYS_PCI_MEM_BASE, SZ_16M, MT_DEVICE },
- { PCI_CONFIG_VADDR, PHYS_PCI_CONFIG_BASE, SZ_16M, MT_DEVICE },
- { PCI_V3_VADDR, PHYS_PCI_V3_BASE, SZ_512K, MT_DEVICE },
- { PCI_IO_VADDR, PHYS_PCI_IO_BASE, SZ_64K, MT_DEVICE },
+#ifdef CONFIG_PCI
+ { IO_ADDRESS(VERSATILE_PCI_CORE_BASE), VERSATILE_PCI_CORE_BASE, SZ_4K, MT_DEVICE },
+ { VERSATILE_PCI_VIRT_BASE, VERSATILE_PCI_BASE, VERSATILE_PCI_BASE_SIZE, MT_DEVICE },
+ { VERSATILE_PCI_CFG_VIRT_BASE, VERSATILE_PCI_CFG_BASE, VERSATILE_PCI_CFG_BASE_SIZE, MT_DEVICE },
+#if 0
+ { VERSATILE_PCI_VIRT_MEM_BASE0, VERSATILE_PCI_MEM_BASE0, SZ_16M, MT_DEVICE },
+ { VERSATILE_PCI_VIRT_MEM_BASE1, VERSATILE_PCI_MEM_BASE1, SZ_16M, MT_DEVICE },
+ { VERSATILE_PCI_VIRT_MEM_BASE2, VERSATILE_PCI_MEM_BASE2, SZ_16M, MT_DEVICE },
+#endif
#endif
};
@@ -543,7 +547,7 @@ static void versatile_clcd_enable(struct clcd_fb *fb)
val |= SYS_CLCD_MODE_5551;
break;
case 6:
- val |= SYS_CLCD_MODE_565_BLSB;
+ val |= SYS_CLCD_MODE_565_RLSB;
break;
case 8:
val |= SYS_CLCD_MODE_888;
diff --git a/arch/arm/mach-versatile/pci.c b/arch/arm/mach-versatile/pci.c
new file mode 100644
index 00000000000..d1565e851f0
--- /dev/null
+++ b/arch/arm/mach-versatile/pci.c
@@ -0,0 +1,360 @@
+/*
+ * linux/arch/arm/mach-versatile/pci.c
+ *
+ * (C) Copyright Koninklijke Philips Electronics NV 2004. All rights reserved.
+ * You can redistribute and/or modify this software under the terms of version 2
+ * of the GNU General Public License as published by the Free Software Foundation.
+ * THIS SOFTWARE IS PROVIDED "AS IS" 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.
+ * Koninklijke Philips Electronics nor its subsidiaries is obligated to provide any support for this software.
+ *
+ * ARM Versatile PCI driver.
+ *
+ * 14/04/2005 Initial version, colin.king@philips.com
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+
+/*
+ * these spaces are mapped using the following base registers:
+ *
+ * Usage Local Bus Memory Base/Map registers used
+ *
+ * Mem 50000000 - 5FFFFFFF LB_BASE0/LB_MAP0, non prefetch
+ * Mem 60000000 - 6FFFFFFF LB_BASE1/LB_MAP1, prefetch
+ * IO 44000000 - 4FFFFFFF LB_BASE2/LB_MAP2, IO
+ * Cfg 42000000 - 42FFFFFF PCI config
+ *
+ */
+#define SYS_PCICTL IO_ADDRESS(VERSATILE_SYS_PCICTL)
+#define PCI_IMAP0 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x0)
+#define PCI_IMAP1 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x4)
+#define PCI_IMAP2 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x8)
+#define PCI_SMAP0 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x10)
+#define PCI_SMAP1 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x14)
+#define PCI_SMAP2 IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x18)
+#define PCI_SELFID IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0xc)
+
+#define DEVICE_ID_OFFSET 0x00
+#define CSR_OFFSET 0x04
+#define CLASS_ID_OFFSET 0x08
+
+#define VP_PCI_DEVICE_ID 0x030010ee
+#define VP_PCI_CLASS_ID 0x0b400000
+
+static unsigned long pci_slot_ignore = 0;
+
+static int __init versatile_pci_slot_ignore(char *str)
+{
+ int retval;
+ int slot;
+
+ while ((retval = get_option(&str,&slot))) {
+ if ((slot < 0) || (slot > 31)) {
+ printk("Illegal slot value: %d\n",slot);
+ } else {
+ pci_slot_ignore |= (1 << slot);
+ }
+ }
+ return 1;
+}
+
+__setup("pci_slot_ignore=", versatile_pci_slot_ignore);
+
+
+static unsigned long __pci_addr(struct pci_bus *bus,
+ unsigned int devfn, int offset)
+{
+ unsigned int busnr = bus->number;
+
+ /*
+ * Trap out illegal values
+ */
+ if (offset > 255)
+ BUG();
+ if (busnr > 255)
+ BUG();
+ if (devfn > 255)
+ BUG();
+
+ return (VERSATILE_PCI_CFG_VIRT_BASE | (busnr << 16) |
+ (PCI_SLOT(devfn) << 11) | (PCI_FUNC(devfn) << 8) | offset);
+}
+
+static int versatile_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+ int size, u32 *val)
+{
+ unsigned long addr = __pci_addr(bus, devfn, where);
+ u32 v;
+ int slot = PCI_SLOT(devfn);
+
+ if (pci_slot_ignore & (1 << slot)) {
+ /* Ignore this slot */
+ switch (size) {
+ case 1:
+ v = 0xff;
+ break;
+ case 2:
+ v = 0xffff;
+ break;
+ default:
+ v = 0xffffffff;
+ }
+ } else {
+ switch (size) {
+ case 1:
+ addr &= ~3;
+ v = __raw_readb(addr);
+ break;
+
+ case 2:
+ v = __raw_readl(addr & ~3);
+ if (addr & 2) v >>= 16;
+ v &= 0xffff;
+ break;
+
+ default:
+ addr &= ~3;
+ v = __raw_readl(addr);
+ break;
+ }
+ }
+
+ *val = v;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int versatile_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+ int size, u32 val)
+{
+ unsigned long addr = __pci_addr(bus, devfn, where);
+ int slot = PCI_SLOT(devfn);
+
+ if (pci_slot_ignore & (1 << slot)) {
+ return PCIBIOS_SUCCESSFUL;
+ }
+
+ switch (size) {
+ case 1:
+ __raw_writeb((u8)val, addr);
+ break;
+
+ case 2:
+ __raw_writew((u16)val, addr);
+ break;
+
+ case 4:
+ __raw_writel(val, addr);
+ break;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops pci_versatile_ops = {
+ .read = versatile_read_config,
+ .write = versatile_write_config,
+};
+
+static struct resource io_mem = {
+ .name = "PCI I/O space",
+ .start = VERSATILE_PCI_MEM_BASE0,
+ .end = VERSATILE_PCI_MEM_BASE0+VERSATILE_PCI_MEM_BASE0_SIZE-1,
+ .flags = IORESOURCE_IO,
+};
+
+static struct resource non_mem = {
+ .name = "PCI non-prefetchable",
+ .start = VERSATILE_PCI_MEM_BASE1,
+ .end = VERSATILE_PCI_MEM_BASE1+VERSATILE_PCI_MEM_BASE1_SIZE-1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct resource pre_mem = {
+ .name = "PCI prefetchable",
+ .start = VERSATILE_PCI_MEM_BASE2,
+ .end = VERSATILE_PCI_MEM_BASE2+VERSATILE_PCI_MEM_BASE2_SIZE-1,
+ .flags = IORESOURCE_MEM | IORESOURCE_PREFETCH,
+};
+
+static int __init pci_versatile_setup_resources(struct resource **resource)
+{
+ int ret = 0;
+
+ ret = request_resource(&iomem_resource, &io_mem);
+ if (ret) {
+ printk(KERN_ERR "PCI: unable to allocate I/O "
+ "memory region (%d)\n", ret);
+ goto out;
+ }
+ ret = request_resource(&iomem_resource, &non_mem);
+ if (ret) {
+ printk(KERN_ERR "PCI: unable to allocate non-prefetchable "
+ "memory region (%d)\n", ret);
+ goto release_io_mem;
+ }
+ ret = request_resource(&iomem_resource, &pre_mem);
+ if (ret) {
+ printk(KERN_ERR "PCI: unable to allocate prefetchable "
+ "memory region (%d)\n", ret);
+ goto release_non_mem;
+ }
+
+ /*
+ * bus->resource[0] is the IO resource for this bus
+ * bus->resource[1] is the mem resource for this bus
+ * bus->resource[2] is the prefetch mem resource for this bus
+ */
+ resource[0] = &io_mem;
+ resource[1] = &non_mem;
+ resource[2] = &pre_mem;
+
+ goto out;
+
+ release_non_mem:
+ release_resource(&non_mem);
+ release_io_mem:
+ release_resource(&io_mem);
+ out:
+ return ret;
+}
+
+int __init pci_versatile_setup(int nr, struct pci_sys_data *sys)
+{
+ int ret = 0;
+ int i;
+ int myslot = -1;
+ unsigned long val;
+
+ if (nr == 0) {
+ sys->mem_offset = 0;
+ ret = pci_versatile_setup_resources(sys->resource);
+ if (ret < 0) {
+ printk("pci_versatile_setup: resources... oops?\n");
+ goto out;
+ }
+ } else {
+ printk("pci_versatile_setup: resources... nr == 0??\n");
+ goto out;
+ }
+
+ __raw_writel(VERSATILE_PCI_MEM_BASE0 >> 28,PCI_IMAP0);
+ __raw_writel(VERSATILE_PCI_MEM_BASE1 >> 28,PCI_IMAP1);
+ __raw_writel(VERSATILE_PCI_MEM_BASE2 >> 28,PCI_IMAP2);
+
+ __raw_writel(1, SYS_PCICTL);
+
+ val = __raw_readl(SYS_PCICTL);
+ if (!(val & 1)) {
+ printk("Not plugged into PCI backplane!\n");
+ ret = -EIO;
+ goto out;
+ }
+
+ /*
+ * We need to discover the PCI core first to configure itself
+ * before the main PCI probing is performed
+ */
+ for (i=0; i<32; i++) {
+ if ((__raw_readl(VERSATILE_PCI_VIRT_BASE+(i<<11)+DEVICE_ID_OFFSET) == VP_PCI_DEVICE_ID) &&
+ (__raw_readl(VERSATILE_PCI_VIRT_BASE+(i<<11)+CLASS_ID_OFFSET) == VP_PCI_CLASS_ID)) {
+ myslot = i;
+
+ __raw_writel(myslot, PCI_SELFID);
+ val = __raw_readl(VERSATILE_PCI_CFG_VIRT_BASE+(myslot<<11)+CSR_OFFSET);
+ val |= (1<<2);
+ __raw_writel(val, VERSATILE_PCI_CFG_VIRT_BASE+(myslot<<11)+CSR_OFFSET);
+ break;
+ }
+ }
+
+ if (myslot == -1) {
+ printk("Cannot find PCI core!\n");
+ ret = -EIO;
+ } else {
+ printk("PCI core found (slot %d)\n",myslot);
+ /* Do not to map Versatile FPGA PCI device
+ into memory space as we are short of
+ mappable memory */
+ pci_slot_ignore |= (1 << myslot);
+ ret = 1;
+ }
+
+ out:
+ return ret;
+}
+
+
+struct pci_bus *pci_versatile_scan_bus(int nr, struct pci_sys_data *sys)
+{
+ return pci_scan_bus(sys->busnr, &pci_versatile_ops, sys);
+}
+
+/*
+ * V3_LB_BASE? - local bus address
+ * V3_LB_MAP? - pci bus address
+ */
+void __init pci_versatile_preinit(void)
+{
+}
+
+void __init pci_versatile_postinit(void)
+{
+}
+
+
+/*
+ * map the specified device/slot/pin to an IRQ. Different backplanes may need to modify this.
+ */
+static int __init versatile_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ int irq;
+ int devslot = PCI_SLOT(dev->devfn);
+
+ /* slot, pin, irq
+ 24 1 27
+ 25 1 28 untested
+ 26 1 29
+ 27 1 30 untested
+ */
+
+ irq = 27 + ((slot + pin + 2) % 3); /* Fudged */
+
+ printk("map irq: slot %d, pin %d, devslot %d, irq: %d\n",slot,pin,devslot,irq);
+
+ return irq;
+}
+
+static struct hw_pci versatile_pci __initdata = {
+ .swizzle = NULL,
+ .map_irq = versatile_map_irq,
+ .nr_controllers = 1,
+ .setup = pci_versatile_setup,
+ .scan = pci_versatile_scan_bus,
+ .preinit = pci_versatile_preinit,
+ .postinit = pci_versatile_postinit,
+};
+
+static int __init versatile_pci_init(void)
+{
+ pci_common_init(&versatile_pci);
+ return 0;
+}
+
+subsys_initcall(versatile_pci_init);
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index c4fc6be629d..95606b4a3ba 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -62,7 +62,7 @@ config CPU_ARM720T
# ARM920T
config CPU_ARM920T
bool "Support ARM920T processor" if !ARCH_S3C2410
- depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX
+ depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000
default y if ARCH_S3C2410
select CPU_32v4
select CPU_ABRT_EV4T
@@ -228,7 +228,6 @@ config CPU_SA1100
select CPU_CACHE_V4WB
select CPU_CACHE_VIVT
select CPU_TLB_V4WB
- select CPU_MINICACHE
# XScale
config CPU_XSCALE
@@ -239,7 +238,6 @@ config CPU_XSCALE
select CPU_ABRT_EV5T
select CPU_CACHE_VIVT
select CPU_TLB_V4WBI
- select CPU_MINICACHE
# ARMv6
config CPU_V6
@@ -345,11 +343,6 @@ config CPU_TLB_V4WBI
config CPU_TLB_V6
bool
-config CPU_MINICACHE
- bool
- help
- Processor has a minicache.
-
comment "Processor Features"
config ARM_THUMB
@@ -412,21 +405,28 @@ config CPU_BPREDICT_DISABLE
config TLS_REG_EMUL
bool
- default y if (SMP || CPU_32v6) && (CPU_32v5 || CPU_32v4 || CPU_32v3)
+ default y if SMP && (CPU_32v5 || CPU_32v4 || CPU_32v3)
help
- We might be running on an ARMv6+ processor which should have the TLS
- register but for some reason we can't use it, or maybe an SMP system
- using a pre-ARMv6 processor (there are apparently a few prototypes
- like that in existence) and therefore access to that register must
- be emulated.
+ An SMP system using a pre-ARMv6 processor (there are apparently
+ a few prototypes like that in existence) and therefore access to
+ that required register must be emulated.
config HAS_TLS_REG
bool
- depends on CPU_32v6
- default y if !TLS_REG_EMUL
+ depends on !TLS_REG_EMUL
+ default y if SMP || CPU_32v7
help
This selects support for the CP15 thread register.
- It is defined to be available on ARMv6 or later. If a particular
- ARMv6 or later CPU doesn't support it then it must omc;ide "select
- TLS_REG_EMUL" along with its other caracteristics.
+ It is defined to be available on some ARMv6 processors (including
+ all SMP capable ARMv6's) or later processors. User space may
+ assume directly accessing that register and always obtain the
+ expected value only on ARMv7 and above.
+
+config NEEDS_SYSCALL_FOR_CMPXCHG
+ bool
+ default y if SMP && (CPU_32v5 || CPU_32v4 || CPU_32v3)
+ help
+ SMP on a pre-ARMv6 processor? Well OK then.
+ Forget about fast user space cmpxchg support.
+ It is just not possible.
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index ccf316c11e0..59f47d4c2df 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -31,8 +31,6 @@ obj-$(CONFIG_CPU_COPY_V6) += copypage-v6.o mmu.o
obj-$(CONFIG_CPU_SA1100) += copypage-v4mc.o
obj-$(CONFIG_CPU_XSCALE) += copypage-xscale.o
-obj-$(CONFIG_CPU_MINICACHE) += minicache.o
-
obj-$(CONFIG_CPU_TLB_V3) += tlb-v3.o
obj-$(CONFIG_CPU_TLB_V4WT) += tlb-v4.o
obj-$(CONFIG_CPU_TLB_V4WB) += tlb-v4wb.o
diff --git a/arch/arm/mm/copypage-v4mc.S b/arch/arm/mm/copypage-v4mc.S
deleted file mode 100644
index 305af3dab3d..00000000000
--- a/arch/arm/mm/copypage-v4mc.S
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * linux/arch/arm/lib/copy_page-armv4mc.S
- *
- * Copyright (C) 1995-2001 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * ASM optimised string functions
- */
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <asm/constants.h>
-
- .text
- .align 5
-/*
- * ARMv4 mini-dcache optimised copy_user_page
- *
- * We flush the destination cache lines just before we write the data into the
- * corresponding address. Since the Dcache is read-allocate, this removes the
- * Dcache aliasing issue. The writes will be forwarded to the write buffer,
- * and merged as appropriate.
- *
- * Note: We rely on all ARMv4 processors implementing the "invalidate D line"
- * instruction. If your processor does not supply this, you have to write your
- * own copy_user_page that does the right thing.
- */
-ENTRY(v4_mc_copy_user_page)
- stmfd sp!, {r4, lr} @ 2
- mov r4, r0
- mov r0, r1
- bl map_page_minicache
- mov r1, #PAGE_SZ/64 @ 1
- ldmia r0!, {r2, r3, ip, lr} @ 4
-1: mcr p15, 0, r4, c7, c6, 1 @ 1 invalidate D line
- stmia r4!, {r2, r3, ip, lr} @ 4
- ldmia r0!, {r2, r3, ip, lr} @ 4+1
- stmia r4!, {r2, r3, ip, lr} @ 4
- ldmia r0!, {r2, r3, ip, lr} @ 4
- mcr p15, 0, r4, c7, c6, 1 @ 1 invalidate D line
- stmia r4!, {r2, r3, ip, lr} @ 4
- ldmia r0!, {r2, r3, ip, lr} @ 4
- subs r1, r1, #1 @ 1
- stmia r4!, {r2, r3, ip, lr} @ 4
- ldmneia r0!, {r2, r3, ip, lr} @ 4
- bne 1b @ 1
- ldmfd sp!, {r4, pc} @ 3
-
- .align 5
-/*
- * ARMv4 optimised clear_user_page
- *
- * Same story as above.
- */
-ENTRY(v4_mc_clear_user_page)
- str lr, [sp, #-4]!
- mov r1, #PAGE_SZ/64 @ 1
- mov r2, #0 @ 1
- mov r3, #0 @ 1
- mov ip, #0 @ 1
- mov lr, #0 @ 1
-1: mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line
- stmia r0!, {r2, r3, ip, lr} @ 4
- stmia r0!, {r2, r3, ip, lr} @ 4
- mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line
- stmia r0!, {r2, r3, ip, lr} @ 4
- stmia r0!, {r2, r3, ip, lr} @ 4
- subs r1, r1, #1 @ 1
- bne 1b @ 1
- ldr pc, [sp], #4
-
- __INITDATA
-
- .type v4_mc_user_fns, #object
-ENTRY(v4_mc_user_fns)
- .long v4_mc_clear_user_page
- .long v4_mc_copy_user_page
- .size v4_mc_user_fns, . - v4_mc_user_fns
diff --git a/arch/arm/mm/copypage-v4mc.c b/arch/arm/mm/copypage-v4mc.c
new file mode 100644
index 00000000000..fc69dccdace
--- /dev/null
+++ b/arch/arm/mm/copypage-v4mc.c
@@ -0,0 +1,111 @@
+/*
+ * linux/arch/arm/lib/copypage-armv4mc.S
+ *
+ * Copyright (C) 1995-2005 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This handles the mini data cache, as found on SA11x0 and XScale
+ * processors. When we copy a user page page, we map it in such a way
+ * that accesses to this page will not touch the main data cache, but
+ * will be cached in the mini data cache. This prevents us thrashing
+ * the main data cache on page faults.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+
+/*
+ * 0xffff8000 to 0xffffffff is reserved for any ARM architecture
+ * specific hacks for copying pages efficiently.
+ */
+#define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
+ L_PTE_CACHEABLE)
+
+#define TOP_PTE(x) pte_offset_kernel(top_pmd, x)
+
+static DEFINE_SPINLOCK(minicache_lock);
+
+/*
+ * ARMv4 mini-dcache optimised copy_user_page
+ *
+ * We flush the destination cache lines just before we write the data into the
+ * corresponding address. Since the Dcache is read-allocate, this removes the
+ * Dcache aliasing issue. The writes will be forwarded to the write buffer,
+ * and merged as appropriate.
+ *
+ * Note: We rely on all ARMv4 processors implementing the "invalidate D line"
+ * instruction. If your processor does not supply this, you have to write your
+ * own copy_user_page that does the right thing.
+ */
+static void __attribute__((naked))
+mc_copy_user_page(void *from, void *to)
+{
+ asm volatile(
+ "stmfd sp!, {r4, lr} @ 2\n\
+ mov r4, %2 @ 1\n\
+ ldmia %0!, {r2, r3, ip, lr} @ 4\n\
+1: mcr p15, 0, %1, c7, c6, 1 @ 1 invalidate D line\n\
+ stmia %1!, {r2, r3, ip, lr} @ 4\n\
+ ldmia %0!, {r2, r3, ip, lr} @ 4+1\n\
+ stmia %1!, {r2, r3, ip, lr} @ 4\n\
+ ldmia %0!, {r2, r3, ip, lr} @ 4\n\
+ mcr p15, 0, %1, c7, c6, 1 @ 1 invalidate D line\n\
+ stmia %1!, {r2, r3, ip, lr} @ 4\n\
+ ldmia %0!, {r2, r3, ip, lr} @ 4\n\
+ subs r4, r4, #1 @ 1\n\
+ stmia %1!, {r2, r3, ip, lr} @ 4\n\
+ ldmneia %0!, {r2, r3, ip, lr} @ 4\n\
+ bne 1b @ 1\n\
+ ldmfd sp!, {r4, pc} @ 3"
+ :
+ : "r" (from), "r" (to), "I" (PAGE_SIZE / 64));
+}
+
+void v4_mc_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr)
+{
+ spin_lock(&minicache_lock);
+
+ set_pte(TOP_PTE(0xffff8000), pfn_pte(__pa(kfrom) >> PAGE_SHIFT, minicache_pgprot));
+ flush_tlb_kernel_page(0xffff8000);
+
+ mc_copy_user_page((void *)0xffff8000, kto);
+
+ spin_unlock(&minicache_lock);
+}
+
+/*
+ * ARMv4 optimised clear_user_page
+ */
+void __attribute__((naked))
+v4_mc_clear_user_page(void *kaddr, unsigned long vaddr)
+{
+ asm volatile(
+ "str lr, [sp, #-4]!\n\
+ mov r1, %0 @ 1\n\
+ mov r2, #0 @ 1\n\
+ mov r3, #0 @ 1\n\
+ mov ip, #0 @ 1\n\
+ mov lr, #0 @ 1\n\
+1: mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line\n\
+ stmia r0!, {r2, r3, ip, lr} @ 4\n\
+ stmia r0!, {r2, r3, ip, lr} @ 4\n\
+ mcr p15, 0, r0, c7, c6, 1 @ 1 invalidate D line\n\
+ stmia r0!, {r2, r3, ip, lr} @ 4\n\
+ stmia r0!, {r2, r3, ip, lr} @ 4\n\
+ subs r1, r1, #1 @ 1\n\
+ bne 1b @ 1\n\
+ ldr pc, [sp], #4"
+ :
+ : "I" (PAGE_SIZE / 64));
+}
+
+struct cpu_user_fns v4_mc_user_fns __initdata = {
+ .cpu_clear_user_page = v4_mc_clear_user_page,
+ .cpu_copy_user_page = v4_mc_copy_user_page,
+};
diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c
index 694ac820885..27d041574ea 100644
--- a/arch/arm/mm/copypage-v6.c
+++ b/arch/arm/mm/copypage-v6.c
@@ -26,11 +26,9 @@
#define to_address (0xffffc000)
#define to_pgprot PAGE_KERNEL
-static pte_t *from_pte;
-static pte_t *to_pte;
-static DEFINE_SPINLOCK(v6_lock);
+#define TOP_PTE(x) pte_offset_kernel(top_pmd, x)
-#define DCACHE_COLOUR(vaddr) ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
+static DEFINE_SPINLOCK(v6_lock);
/*
* Copy the user page. No aliasing to deal with so we can just
@@ -55,7 +53,7 @@ void v6_clear_user_page_nonaliasing(void *kaddr, unsigned long vaddr)
*/
void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vaddr)
{
- unsigned int offset = DCACHE_COLOUR(vaddr);
+ unsigned int offset = CACHE_COLOUR(vaddr);
unsigned long from, to;
/*
@@ -74,8 +72,8 @@ void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vadd
*/
spin_lock(&v6_lock);
- set_pte(from_pte + offset, pfn_pte(__pa(kfrom) >> PAGE_SHIFT, from_pgprot));
- set_pte(to_pte + offset, pfn_pte(__pa(kto) >> PAGE_SHIFT, to_pgprot));
+ set_pte(TOP_PTE(from_address) + offset, pfn_pte(__pa(kfrom) >> PAGE_SHIFT, from_pgprot));
+ set_pte(TOP_PTE(to_address) + offset, pfn_pte(__pa(kto) >> PAGE_SHIFT, to_pgprot));
from = from_address + (offset << PAGE_SHIFT);
to = to_address + (offset << PAGE_SHIFT);
@@ -95,7 +93,7 @@ void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vadd
*/
void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr)
{
- unsigned int offset = DCACHE_COLOUR(vaddr);
+ unsigned int offset = CACHE_COLOUR(vaddr);
unsigned long to = to_address + (offset << PAGE_SHIFT);
/*
@@ -114,7 +112,7 @@ void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr)
*/
spin_lock(&v6_lock);
- set_pte(to_pte + offset, pfn_pte(__pa(kaddr) >> PAGE_SHIFT, to_pgprot));
+ set_pte(TOP_PTE(to_address) + offset, pfn_pte(__pa(kaddr) >> PAGE_SHIFT, to_pgprot));
flush_tlb_kernel_page(to);
clear_page((void *)to);
@@ -129,21 +127,6 @@ struct cpu_user_fns v6_user_fns __initdata = {
static int __init v6_userpage_init(void)
{
if (cache_is_vipt_aliasing()) {
- pgd_t *pgd;
- pmd_t *pmd;
-
- pgd = pgd_offset_k(from_address);
- pmd = pmd_alloc(&init_mm, pgd, from_address);
- if (!pmd)
- BUG();
- from_pte = pte_alloc_kernel(&init_mm, pmd, from_address);
- if (!from_pte)
- BUG();
-
- to_pte = pte_alloc_kernel(&init_mm, pmd, to_address);
- if (!to_pte)
- BUG();
-
cpu_user.cpu_clear_user_page = v6_clear_user_page_aliasing;
cpu_user.cpu_copy_user_page = v6_copy_user_page_aliasing;
}
@@ -151,5 +134,4 @@ static int __init v6_userpage_init(void)
return 0;
}
-__initcall(v6_userpage_init);
-
+core_initcall(v6_userpage_init);
diff --git a/arch/arm/mm/copypage-xscale.S b/arch/arm/mm/copypage-xscale.S
deleted file mode 100644
index bb277316ef5..00000000000
--- a/arch/arm/mm/copypage-xscale.S
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * linux/arch/arm/lib/copypage-xscale.S
- *
- * Copyright (C) 2001 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <asm/constants.h>
-
-/*
- * General note:
- * We don't really want write-allocate cache behaviour for these functions
- * since that will just eat through 8K of the cache.
- */
-
- .text
- .align 5
-/*
- * XScale optimised copy_user_page
- * r0 = destination
- * r1 = source
- * r2 = virtual user address of ultimate destination page
- *
- * The source page may have some clean entries in the cache already, but we
- * can safely ignore them - break_cow() will flush them out of the cache
- * if we eventually end up using our copied page.
- *
- * What we could do is use the mini-cache to buffer reads from the source
- * page. We rely on the mini-cache being smaller than one page, so we'll
- * cycle through the complete cache anyway.
- */
-ENTRY(xscale_mc_copy_user_page)
- stmfd sp!, {r4, r5, lr}
- mov r5, r0
- mov r0, r1
- bl map_page_minicache
- mov r1, r5
- mov lr, #PAGE_SZ/64-1
-
- /*
- * Strangely enough, best performance is achieved
- * when prefetching destination as well. (NP)
- */
- pld [r0, #0]
- pld [r0, #32]
- pld [r1, #0]
- pld [r1, #32]
-
-1: pld [r0, #64]
- pld [r0, #96]
- pld [r1, #64]
- pld [r1, #96]
-
-2: ldrd r2, [r0], #8
- ldrd r4, [r0], #8
- mov ip, r1
- strd r2, [r1], #8
- ldrd r2, [r0], #8
- strd r4, [r1], #8
- ldrd r4, [r0], #8
- strd r2, [r1], #8
- strd r4, [r1], #8
- mcr p15, 0, ip, c7, c10, 1 @ clean D line
- ldrd r2, [r0], #8
- mcr p15, 0, ip, c7, c6, 1 @ invalidate D line
- ldrd r4, [r0], #8
- mov ip, r1
- strd r2, [r1], #8
- ldrd r2, [r0], #8
- strd r4, [r1], #8
- ldrd r4, [r0], #8
- strd r2, [r1], #8
- strd r4, [r1], #8
- mcr p15, 0, ip, c7, c10, 1 @ clean D line
- subs lr, lr, #1
- mcr p15, 0, ip, c7, c6, 1 @ invalidate D line
- bgt 1b
- beq 2b
-
- ldmfd sp!, {r4, r5, pc}
-
- .align 5
-/*
- * XScale optimised clear_user_page
- * r0 = destination
- * r1 = virtual user address of ultimate destination page
- */
-ENTRY(xscale_mc_clear_user_page)
- mov r1, #PAGE_SZ/32
- mov r2, #0
- mov r3, #0
-1: mov ip, r0
- strd r2, [r0], #8
- strd r2, [r0], #8
- strd r2, [r0], #8
- strd r2, [r0], #8
- mcr p15, 0, ip, c7, c10, 1 @ clean D line
- subs r1, r1, #1
- mcr p15, 0, ip, c7, c6, 1 @ invalidate D line
- bne 1b
- mov pc, lr
-
- __INITDATA
-
- .type xscale_mc_user_fns, #object
-ENTRY(xscale_mc_user_fns)
- .long xscale_mc_clear_user_page
- .long xscale_mc_copy_user_page
- .size xscale_mc_user_fns, . - xscale_mc_user_fns
diff --git a/arch/arm/mm/copypage-xscale.c b/arch/arm/mm/copypage-xscale.c
new file mode 100644
index 00000000000..42a6ee255ce
--- /dev/null
+++ b/arch/arm/mm/copypage-xscale.c
@@ -0,0 +1,131 @@
+/*
+ * linux/arch/arm/lib/copypage-xscale.S
+ *
+ * Copyright (C) 1995-2005 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This handles the mini data cache, as found on SA11x0 and XScale
+ * processors. When we copy a user page page, we map it in such a way
+ * that accesses to this page will not touch the main data cache, but
+ * will be cached in the mini data cache. This prevents us thrashing
+ * the main data cache on page faults.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+
+/*
+ * 0xffff8000 to 0xffffffff is reserved for any ARM architecture
+ * specific hacks for copying pages efficiently.
+ */
+#define COPYPAGE_MINICACHE 0xffff8000
+
+#define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
+ L_PTE_CACHEABLE)
+
+#define TOP_PTE(x) pte_offset_kernel(top_pmd, x)
+
+static DEFINE_SPINLOCK(minicache_lock);
+
+/*
+ * XScale mini-dcache optimised copy_user_page
+ *
+ * We flush the destination cache lines just before we write the data into the
+ * corresponding address. Since the Dcache is read-allocate, this removes the
+ * Dcache aliasing issue. The writes will be forwarded to the write buffer,
+ * and merged as appropriate.
+ */
+static void __attribute__((naked))
+mc_copy_user_page(void *from, void *to)
+{
+ /*
+ * Strangely enough, best performance is achieved
+ * when prefetching destination as well. (NP)
+ */
+ asm volatile(
+ "stmfd sp!, {r4, r5, lr} \n\
+ mov lr, %2 \n\
+ pld [r0, #0] \n\
+ pld [r0, #32] \n\
+ pld [r1, #0] \n\
+ pld [r1, #32] \n\
+1: pld [r0, #64] \n\
+ pld [r0, #96] \n\
+ pld [r1, #64] \n\
+ pld [r1, #96] \n\
+2: ldrd r2, [r0], #8 \n\
+ ldrd r4, [r0], #8 \n\
+ mov ip, r1 \n\
+ strd r2, [r1], #8 \n\
+ ldrd r2, [r0], #8 \n\
+ strd r4, [r1], #8 \n\
+ ldrd r4, [r0], #8 \n\
+ strd r2, [r1], #8 \n\
+ strd r4, [r1], #8 \n\
+ mcr p15, 0, ip, c7, c10, 1 @ clean D line\n\
+ ldrd r2, [r0], #8 \n\
+ mcr p15, 0, ip, c7, c6, 1 @ invalidate D line\n\
+ ldrd r4, [r0], #8 \n\
+ mov ip, r1 \n\
+ strd r2, [r1], #8 \n\
+ ldrd r2, [r0], #8 \n\
+ strd r4, [r1], #8 \n\
+ ldrd r4, [r0], #8 \n\
+ strd r2, [r1], #8 \n\
+ strd r4, [r1], #8 \n\
+ mcr p15, 0, ip, c7, c10, 1 @ clean D line\n\
+ subs lr, lr, #1 \n\
+ mcr p15, 0, ip, c7, c6, 1 @ invalidate D line\n\
+ bgt 1b \n\
+ beq 2b \n\
+ ldmfd sp!, {r4, r5, pc} "
+ :
+ : "r" (from), "r" (to), "I" (PAGE_SIZE / 64 - 1));
+}
+
+void xscale_mc_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr)
+{
+ spin_lock(&minicache_lock);
+
+ set_pte(TOP_PTE(COPYPAGE_MINICACHE), pfn_pte(__pa(kfrom) >> PAGE_SHIFT, minicache_pgprot));
+ flush_tlb_kernel_page(COPYPAGE_MINICACHE);
+
+ mc_copy_user_page((void *)COPYPAGE_MINICACHE, kto);
+
+ spin_unlock(&minicache_lock);
+}
+
+/*
+ * XScale optimised clear_user_page
+ */
+void __attribute__((naked))
+xscale_mc_clear_user_page(void *kaddr, unsigned long vaddr)
+{
+ asm volatile(
+ "mov r1, %0 \n\
+ mov r2, #0 \n\
+ mov r3, #0 \n\
+1: mov ip, r0 \n\
+ strd r2, [r0], #8 \n\
+ strd r2, [r0], #8 \n\
+ strd r2, [r0], #8 \n\
+ strd r2, [r0], #8 \n\
+ mcr p15, 0, ip, c7, c10, 1 @ clean D line\n\
+ subs r1, r1, #1 \n\
+ mcr p15, 0, ip, c7, c6, 1 @ invalidate D line\n\
+ bne 1b \n\
+ mov pc, lr"
+ :
+ : "I" (PAGE_SIZE / 32));
+}
+
+struct cpu_user_fns xscale_mc_user_fns __initdata = {
+ .cpu_clear_user_page = xscale_mc_clear_user_page,
+ .cpu_copy_user_page = xscale_mc_copy_user_page,
+};
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index 01967ddeef5..be4ab3d73c9 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -77,9 +77,8 @@ no_pmd:
}
static void
-make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, int dirty)
+make_coherent(struct address_space *mapping, struct vm_area_struct *vma, unsigned long addr, unsigned long pfn)
{
- struct address_space *mapping = page_mapping(page);
struct mm_struct *mm = vma->vm_mm;
struct vm_area_struct *mpnt;
struct prio_tree_iter iter;
@@ -87,9 +86,6 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page,
pgoff_t pgoff;
int aliases = 0;
- if (!mapping)
- return;
-
pgoff = vma->vm_pgoff + ((addr - vma->vm_start) >> PAGE_SHIFT);
/*
@@ -115,9 +111,11 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page,
if (aliases)
adjust_pte(vma, addr);
else
- flush_cache_page(vma, addr, page_to_pfn(page));
+ flush_cache_page(vma, addr, pfn);
}
+void __flush_dcache_page(struct address_space *mapping, struct page *page);
+
/*
* Take care of architecture specific things when placing a new PTE into
* a page table, or changing an existing PTE. Basically, there are two
@@ -134,29 +132,22 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page,
void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
{
unsigned long pfn = pte_pfn(pte);
+ struct address_space *mapping;
struct page *page;
if (!pfn_valid(pfn))
return;
+
page = pfn_to_page(pfn);
- if (page_mapping(page)) {
+ mapping = page_mapping(page);
+ if (mapping) {
int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags);
- if (dirty) {
- /*
- * This is our first userspace mapping of this page.
- * Ensure that the physical page is coherent with
- * the kernel mapping.
- *
- * FIXME: only need to do this on VIVT and aliasing
- * VIPT cache architectures. We can do that
- * by choosing whether to set this bit...
- */
- __cpuc_flush_dcache_page(page_address(page));
- }
+ if (dirty)
+ __flush_dcache_page(mapping, page);
if (cache_is_vivt())
- make_coherent(vma, addr, page, dirty);
+ make_coherent(mapping, vma, addr, pfn);
}
}
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index c6de48d8950..191788fb18d 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -13,14 +13,32 @@
#include <asm/cacheflush.h>
#include <asm/system.h>
+#include <asm/tlbflush.h>
-static void __flush_dcache_page(struct address_space *mapping, struct page *page)
+#ifdef CONFIG_CPU_CACHE_VIPT
+#define ALIAS_FLUSH_START 0xffff4000
+
+#define TOP_PTE(x) pte_offset_kernel(top_pmd, x)
+
+static void flush_pfn_alias(unsigned long pfn, unsigned long vaddr)
{
- struct mm_struct *mm = current->active_mm;
- struct vm_area_struct *mpnt;
- struct prio_tree_iter iter;
- pgoff_t pgoff;
+ unsigned long to = ALIAS_FLUSH_START + (CACHE_COLOUR(vaddr) << PAGE_SHIFT);
+
+ set_pte(TOP_PTE(to), pfn_pte(pfn, PAGE_KERNEL));
+ flush_tlb_kernel_page(to);
+ asm( "mcrr p15, 0, %1, %0, c14\n"
+ " mcrr p15, 0, %1, %0, c5\n"
+ :
+ : "r" (to), "r" (to + PAGE_SIZE - L1_CACHE_BYTES)
+ : "cc");
+}
+#else
+#define flush_pfn_alias(pfn,vaddr) do { } while (0)
+#endif
+
+void __flush_dcache_page(struct address_space *mapping, struct page *page)
+{
/*
* Writeback any data associated with the kernel mapping of this
* page. This ensures that data in the physical page is mutually
@@ -29,12 +47,21 @@ static void __flush_dcache_page(struct address_space *mapping, struct page *page
__cpuc_flush_dcache_page(page_address(page));
/*
- * If there's no mapping pointer here, then this page isn't
- * visible to userspace yet, so there are no cache lines
- * associated with any other aliases.
+ * If this is a page cache page, and we have an aliasing VIPT cache,
+ * we only need to do one flush - which would be at the relevant
+ * userspace colour, which is congruent with page->index.
*/
- if (!mapping)
- return;
+ if (mapping && cache_is_vipt_aliasing())
+ flush_pfn_alias(page_to_pfn(page),
+ page->index << PAGE_CACHE_SHIFT);
+}
+
+static void __flush_dcache_aliases(struct address_space *mapping, struct page *page)
+{
+ struct mm_struct *mm = current->active_mm;
+ struct vm_area_struct *mpnt;
+ struct prio_tree_iter iter;
+ pgoff_t pgoff;
/*
* There are possible user space mappings of this page:
@@ -57,8 +84,6 @@ static void __flush_dcache_page(struct address_space *mapping, struct page *page
continue;
offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
flush_cache_page(mpnt, mpnt->vm_start + offset, page_to_pfn(page));
- if (cache_is_vipt())
- break;
}
flush_dcache_mmap_unlock(mapping);
}
@@ -83,12 +108,12 @@ void flush_dcache_page(struct page *page)
{
struct address_space *mapping = page_mapping(page);
- if (cache_is_vipt_nonaliasing())
- return;
-
if (mapping && !mapping_mapped(mapping))
set_bit(PG_dcache_dirty, &page->flags);
- else
+ else {
__flush_dcache_page(mapping, page);
+ if (mapping && cache_is_vivt())
+ __flush_dcache_aliases(mapping, page);
+ }
}
EXPORT_SYMBOL(flush_dcache_page);
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 72a2b8cee31..c08710b1ff0 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -93,14 +93,7 @@ struct node_info {
};
#define O_PFN_DOWN(x) ((x) >> PAGE_SHIFT)
-#define V_PFN_DOWN(x) O_PFN_DOWN(__pa(x))
-
#define O_PFN_UP(x) (PAGE_ALIGN(x) >> PAGE_SHIFT)
-#define V_PFN_UP(x) O_PFN_UP(__pa(x))
-
-#define PFN_SIZE(x) ((x) >> PAGE_SHIFT)
-#define PFN_RANGE(s,e) PFN_SIZE(PAGE_ALIGN((unsigned long)(e)) - \
- (((unsigned long)(s)) & PAGE_MASK))
/*
* FIXME: We really want to avoid allocating the bootmap bitmap
@@ -113,7 +106,7 @@ find_bootmap_pfn(int node, struct meminfo *mi, unsigned int bootmap_pages)
{
unsigned int start_pfn, bank, bootmap_pfn;
- start_pfn = V_PFN_UP(&_end);
+ start_pfn = O_PFN_UP(__pa(&_end));
bootmap_pfn = 0;
for (bank = 0; bank < mi->nr_banks; bank ++) {
@@ -122,9 +115,9 @@ find_bootmap_pfn(int node, struct meminfo *mi, unsigned int bootmap_pages)
if (mi->bank[bank].node != node)
continue;
- start = O_PFN_UP(mi->bank[bank].start);
- end = O_PFN_DOWN(mi->bank[bank].size +
- mi->bank[bank].start);
+ start = mi->bank[bank].start >> PAGE_SHIFT;
+ end = (mi->bank[bank].size +
+ mi->bank[bank].start) >> PAGE_SHIFT;
if (end < start_pfn)
continue;
@@ -191,8 +184,8 @@ find_memend_and_nodes(struct meminfo *mi, struct node_info *np)
/*
* Get the start and end pfns for this bank
*/
- start = O_PFN_UP(mi->bank[i].start);
- end = O_PFN_DOWN(mi->bank[i].start + mi->bank[i].size);
+ start = mi->bank[i].start >> PAGE_SHIFT;
+ end = (mi->bank[i].start + mi->bank[i].size) >> PAGE_SHIFT;
if (np[node].start > start)
np[node].start = start;
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 00bb8fd37a5..7110e54182b 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -170,3 +170,50 @@ void __iounmap(void __iomem *addr)
vfree((void *) (PAGE_MASK & (unsigned long) addr));
}
EXPORT_SYMBOL(__iounmap);
+
+#ifdef __io
+void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+ return __io(port);
+}
+EXPORT_SYMBOL(ioport_map);
+
+void ioport_unmap(void __iomem *addr)
+{
+}
+EXPORT_SYMBOL(ioport_unmap);
+#endif
+
+#ifdef CONFIG_PCI
+#include <linux/pci.h>
+#include <linux/ioport.h>
+
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+ unsigned long start = pci_resource_start(dev, bar);
+ unsigned long len = pci_resource_len(dev, bar);
+ unsigned long flags = pci_resource_flags(dev, bar);
+
+ if (!len || !start)
+ return NULL;
+ if (maxlen && len > maxlen)
+ len = maxlen;
+ if (flags & IORESOURCE_IO)
+ return ioport_map(start, len);
+ if (flags & IORESOURCE_MEM) {
+ if (flags & IORESOURCE_CACHEABLE)
+ return ioremap(start, len);
+ return ioremap_nocache(start, len);
+ }
+ return NULL;
+}
+EXPORT_SYMBOL(pci_iomap);
+
+void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
+{
+ if ((unsigned long)addr >= VMALLOC_START &&
+ (unsigned long)addr < VMALLOC_END)
+ iounmap(addr);
+}
+EXPORT_SYMBOL(pci_iounmap);
+#endif
diff --git a/arch/arm/mm/minicache.c b/arch/arm/mm/minicache.c
deleted file mode 100644
index dedf2ab01b2..00000000000
--- a/arch/arm/mm/minicache.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * linux/arch/arm/mm/minicache.c
- *
- * Copyright (C) 2001 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This handles the mini data cache, as found on SA11x0 and XScale
- * processors. When we copy a user page page, we map it in such a way
- * that accesses to this page will not touch the main data cache, but
- * will be cached in the mini data cache. This prevents us thrashing
- * the main data cache on page faults.
- */
-#include <linux/init.h>
-#include <linux/mm.h>
-
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/tlbflush.h>
-
-/*
- * 0xffff8000 to 0xffffffff is reserved for any ARM architecture
- * specific hacks for copying pages efficiently.
- */
-#define minicache_address (0xffff8000)
-#define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
- L_PTE_CACHEABLE)
-
-static pte_t *minicache_pte;
-
-/*
- * Note that this is intended to be called only from the copy_user_page
- * asm code; anything else will require special locking to prevent the
- * mini-cache space being re-used. (Note: probably preempt unsafe).
- *
- * We rely on the fact that the minicache is 2K, and we'll be pushing
- * 4K of data through it, so we don't actually have to specifically
- * flush the minicache when we change the mapping.
- *
- * Note also: assert(PAGE_OFFSET <= virt < high_memory).
- * Unsafe: preempt, kmap.
- */
-unsigned long map_page_minicache(unsigned long virt)
-{
- set_pte(minicache_pte, pfn_pte(__pa(virt) >> PAGE_SHIFT, minicache_pgprot));
- flush_tlb_kernel_page(minicache_address);
-
- return minicache_address;
-}
-
-static int __init minicache_init(void)
-{
- pgd_t *pgd;
- pmd_t *pmd;
-
- spin_lock(&init_mm.page_table_lock);
-
- pgd = pgd_offset_k(minicache_address);
- pmd = pmd_alloc(&init_mm, pgd, minicache_address);
- if (!pmd)
- BUG();
- minicache_pte = pte_alloc_kernel(&init_mm, pmd, minicache_address);
- if (!minicache_pte)
- BUG();
-
- spin_unlock(&init_mm.page_table_lock);
-
- return 0;
-}
-
-core_initcall(minicache_init);
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index 585dfb8e20b..2c2b93d77d4 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -37,6 +37,8 @@ pgprot_t pgprot_kernel;
EXPORT_SYMBOL(pgprot_kernel);
+pmd_t *top_pmd;
+
struct cachepolicy {
const char policy[16];
unsigned int cr_mask;
@@ -142,6 +144,16 @@ __setup("noalign", noalign_setup);
#define FIRST_KERNEL_PGD_NR (FIRST_USER_PGD_NR + USER_PTRS_PER_PGD)
+static inline pmd_t *pmd_off(pgd_t *pgd, unsigned long virt)
+{
+ return pmd_offset(pgd, virt);
+}
+
+static inline pmd_t *pmd_off_k(unsigned long virt)
+{
+ return pmd_off(pgd_offset_k(virt), virt);
+}
+
/*
* need to get a 16k page for level 1
*/
@@ -220,7 +232,7 @@ void free_pgd_slow(pgd_t *pgd)
return;
/* pgd is always present and good */
- pmd = (pmd_t *)pgd;
+ pmd = pmd_off(pgd, 0);
if (pmd_none(*pmd))
goto free;
if (pmd_bad(*pmd)) {
@@ -246,9 +258,8 @@ free:
static inline void
alloc_init_section(unsigned long virt, unsigned long phys, int prot)
{
- pmd_t *pmdp;
+ pmd_t *pmdp = pmd_off_k(virt);
- pmdp = pmd_offset(pgd_offset_k(virt), virt);
if (virt & (1 << 20))
pmdp++;
@@ -283,11 +294,9 @@ alloc_init_supersection(unsigned long virt, unsigned long phys, int prot)
static inline void
alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pgprot_t prot)
{
- pmd_t *pmdp;
+ pmd_t *pmdp = pmd_off_k(virt);
pte_t *ptep;
- pmdp = pmd_offset(pgd_offset_k(virt), virt);
-
if (pmd_none(*pmdp)) {
unsigned long pmdval;
ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE *
@@ -310,7 +319,7 @@ alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pg
*/
static inline void clear_mapping(unsigned long virt)
{
- pmd_clear(pmd_offset(pgd_offset_k(virt), virt));
+ pmd_clear(pmd_off_k(virt));
}
struct mem_types {
@@ -578,7 +587,7 @@ void setup_mm_for_reboot(char mode)
PMD_TYPE_SECT;
if (cpu_arch <= CPU_ARCH_ARMv5)
pmdval |= PMD_BIT4;
- pmd = pmd_offset(pgd + i, i << PGDIR_SHIFT);
+ pmd = pmd_off(pgd, i << PGDIR_SHIFT);
pmd[0] = __pmd(pmdval);
pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));
flush_pmd_entry(pmd);
@@ -675,6 +684,8 @@ void __init memtable_init(struct meminfo *mi)
flush_cache_all();
flush_tlb_all();
+
+ top_pmd = pmd_off_k(0xffff0000);
}
/*
diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c
index 32c4b0e35b3..3de7f84b53c 100644
--- a/arch/arm/mm/mmap.c
+++ b/arch/arm/mm/mmap.c
@@ -73,7 +73,12 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
(!vma || addr + len <= vma->vm_start))
return addr;
}
- start_addr = addr = mm->free_area_cache;
+ if (len > mm->cached_hole_size) {
+ start_addr = addr = mm->free_area_cache;
+ } else {
+ start_addr = addr = TASK_UNMAPPED_BASE;
+ mm->cached_hole_size = 0;
+ }
full_search:
if (do_align)
@@ -90,6 +95,7 @@ full_search:
*/
if (start_addr != TASK_UNMAPPED_BASE) {
start_addr = addr = TASK_UNMAPPED_BASE;
+ mm->cached_hole_size = 0;
goto full_search;
}
return -ENOMEM;
@@ -101,6 +107,8 @@ full_search:
mm->free_area_cache = addr + len;
return addr;
}
+ if (addr + mm->cached_hole_size < vma->vm_start)
+ mm->cached_hole_size = vma->vm_start - addr;
addr = vma->vm_end;
if (do_align)
addr = COLOUR_ALIGN(addr, pgoff);
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 0aa73d41478..e3d8510f434 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -132,8 +132,8 @@ ENTRY(cpu_v6_switch_mm)
* 100x 1 0 1 r/o no acc
* 10x0 1 0 1 r/o no acc
* 1011 0 0 1 r/w no acc
- * 110x 1 1 0 r/o r/o
- * 11x0 1 1 0 r/o r/o
+ * 110x 0 1 0 r/w r/o
+ * 11x0 0 1 0 r/w r/o
* 1111 0 1 1 r/w r/w
*/
ENTRY(cpu_v6_set_pte)
@@ -150,7 +150,7 @@ ENTRY(cpu_v6_set_pte)
tst r1, #L_PTE_USER
orrne r2, r2, #AP1 | nG
tstne r2, #APX
- eorne r2, r2, #AP0
+ bicne r2, r2, #APX | AP0
tst r1, #L_PTE_YOUNG
biceq r2, r2, #APX | AP1 | AP0
diff --git a/arch/arm/nwfpe/softfloat-macros b/arch/arm/nwfpe/softfloat-macros
index 5469989f2c5..5a060f95a58 100644
--- a/arch/arm/nwfpe/softfloat-macros
+++ b/arch/arm/nwfpe/softfloat-macros
@@ -563,8 +563,14 @@ static bits64 estimateDiv128To64( bits64 a0, bits64 a1, bits64 b )
bits64 rem0, rem1, term0, term1;
bits64 z;
if ( b <= a0 ) return LIT64( 0xFFFFFFFFFFFFFFFF );
- b0 = b>>32;
- z = ( b0<<32 <= a0 ) ? LIT64( 0xFFFFFFFF00000000 ) : ( a0 / b0 )<<32;
+ b0 = b>>32; /* hence b0 is 32 bits wide now */
+ if ( b0<<32 <= a0 ) {
+ z = LIT64( 0xFFFFFFFF00000000 );
+ } else {
+ z = a0;
+ do_div( z, b0 );
+ z <<= 32;
+ }
mul64To128( b, z, &term0, &term1 );
sub128( a0, a1, term0, term1, &rem0, &rem1 );
while ( ( (sbits64) rem0 ) < 0 ) {
@@ -573,7 +579,12 @@ static bits64 estimateDiv128To64( bits64 a0, bits64 a1, bits64 b )
add128( rem0, rem1, b0, b1, &rem0, &rem1 );
}
rem0 = ( rem0<<32 ) | ( rem1>>32 );
- z |= ( b0<<32 <= rem0 ) ? 0xFFFFFFFF : rem0 / b0;
+ if ( b0<<32 <= rem0 ) {
+ z |= 0xFFFFFFFF;
+ } else {
+ do_div( rem0, b0 );
+ z |= rem0;
+ }
return z;
}
@@ -601,6 +612,7 @@ static bits32 estimateSqrt32( int16 aExp, bits32 a )
};
int8 index;
bits32 z;
+ bits64 A;
index = ( a>>27 ) & 15;
if ( aExp & 1 ) {
@@ -614,7 +626,9 @@ static bits32 estimateSqrt32( int16 aExp, bits32 a )
z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 );
if ( z <= a ) return (bits32) ( ( (sbits32) a )>>1 );
}
- return ( (bits32) ( ( ( (bits64) a )<<31 ) / z ) ) + ( z>>1 );
+ A = ( (bits64) a )<<31;
+ do_div( A, z );
+ return ( (bits32) A ) + ( z>>1 );
}
diff --git a/arch/arm/nwfpe/softfloat.c b/arch/arm/nwfpe/softfloat.c
index 9d743ae2906..e038dd3be9b 100644
--- a/arch/arm/nwfpe/softfloat.c
+++ b/arch/arm/nwfpe/softfloat.c
@@ -28,6 +28,8 @@ this code that are retained.
===============================================================================
*/
+#include <asm/div64.h>
+
#include "fpa11.h"
//#include "milieu.h"
//#include "softfloat.h"
@@ -1331,7 +1333,11 @@ float32 float32_div( float32 a, float32 b )
aSig >>= 1;
++zExp;
}
- zSig = ( ( (bits64) aSig )<<32 ) / bSig;
+ {
+ bits64 tmp = ( (bits64) aSig )<<32;
+ do_div( tmp, bSig );
+ zSig = tmp;
+ }
if ( ( zSig & 0x3F ) == 0 ) {
zSig |= ( ( (bits64) bSig ) * zSig != ( (bits64) aSig )<<32 );
}
@@ -1397,7 +1403,9 @@ float32 float32_rem( float32 a, float32 b )
q = ( bSig <= aSig );
if ( q ) aSig -= bSig;
if ( 0 < expDiff ) {
- q = ( ( (bits64) aSig )<<32 ) / bSig;
+ bits64 tmp = ( (bits64) aSig )<<32;
+ do_div( tmp, bSig );
+ q = tmp;
q >>= 32 - expDiff;
bSig >>= 2;
aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q;
diff --git a/arch/arm26/Kconfig b/arch/arm26/Kconfig
index 6caed90661f..dc0c1936969 100644
--- a/arch/arm26/Kconfig
+++ b/arch/arm26/Kconfig
@@ -179,6 +179,8 @@ config CMDLINE
time by entering them here. As a minimum, you should specify the
memory size and the root device (e.g., mem=64M root=/dev/nfs).
+source "mm/Kconfig"
+
endmenu
source "drivers/base/Kconfig"
diff --git a/arch/arm26/boot/install.sh b/arch/arm26/boot/install.sh
index c628328dd9e..8a8399b26cf 100644
--- a/arch/arm26/boot/install.sh
+++ b/arch/arm26/boot/install.sh
@@ -23,8 +23,8 @@
# User may have a custom install script
-if [ -x /sbin/installkernel ]; then
- exec /sbin/installkernel "$@"
+if [ -x /sbin/${CROSS_COMPILE}installkernel ]; then
+ exec /sbin/${CROSS_COMPILE}installkernel "$@"
fi
if [ "$2" = "zImage" ]; then
diff --git a/arch/arm26/kernel/ecard.c b/arch/arm26/kernel/ecard.c
index 824c6b571ad..f2278aadac8 100644
--- a/arch/arm26/kernel/ecard.c
+++ b/arch/arm26/kernel/ecard.c
@@ -562,31 +562,31 @@ static void __init ecard_init_resources(struct expansion_card *ec)
}
}
-static ssize_t ecard_show_irq(struct device *dev, char *buf)
+static ssize_t ecard_show_irq(struct device *dev, struct device_attribute *attr, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->irq);
}
-static ssize_t ecard_show_vendor(struct device *dev, char *buf)
+static ssize_t ecard_show_vendor(struct device *dev, struct device_attribute *attr, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->cid.manufacturer);
}
-static ssize_t ecard_show_device(struct device *dev, char *buf)
+static ssize_t ecard_show_device(struct device *dev, struct device_attribute *attr, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->cid.product);
}
-static ssize_t ecard_show_dma(struct device *dev, char *buf)
+static ssize_t ecard_show_dma(struct device *dev, struct device_attribute *attr, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
return sprintf(buf, "%u\n", ec->dma);
}
-static ssize_t ecard_show_resources(struct device *dev, char *buf)
+static ssize_t ecard_show_resources(struct device *dev, struct device_attribute *attr, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
char *str = buf;
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index 4332ca348d5..f848e376149 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -74,6 +74,8 @@ config PREEMPT
Say Y here if you are building a kernel for a desktop, embedded
or real-time system. Say N if you are unsure.
+source mm/Kconfig
+
endmenu
menu "Hardware setup"
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index 2b19372767e..c93f95146cc 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -74,6 +74,8 @@ config HIGHPTE
with a lot of RAM, this can be wasteful of precious low memory.
Setting this option will put user-space page tables in high memory.
+source "mm/Kconfig"
+
choice
prompt "uClinux kernel load address"
depends on !MMU
diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c
index ef6865f0b97..767ebb55bd8 100644
--- a/arch/frv/kernel/setup.c
+++ b/arch/frv/kernel/setup.c
@@ -790,12 +790,10 @@ void __init setup_arch(char **cmdline_p)
#ifndef CONFIG_GDBSTUB_UART0
__reg(UART0_BASE + UART_IER * 8) = 0;
early_serial_setup(&__frv_uart0);
-// register_serial(&__frv_uart0);
#endif
#ifndef CONFIG_GDBSTUB_UART1
__reg(UART1_BASE + UART_IER * 8) = 0;
early_serial_setup(&__frv_uart1);
-// register_serial(&__frv_uart1);
#endif
#if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH)
diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c
index d8d8f3d4304..36a2dffc8eb 100644
--- a/arch/frv/kernel/signal.c
+++ b/arch/frv/kernel/signal.c
@@ -536,10 +536,8 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
if (!user_mode(regs))
return 1;
- if (current->flags & PF_FREEZE) {
- refrigerator(0);
+ if (try_to_freeze())
goto no_signal;
- }
if (!oldset)
oldset = &current->blocked;
diff --git a/arch/frv/mm/init.c b/arch/frv/mm/init.c
index 41958f57c83..79433159b5f 100644
--- a/arch/frv/mm/init.c
+++ b/arch/frv/mm/init.c
@@ -169,7 +169,6 @@ void __init mem_init(void)
struct page *page = &mem_map[pfn];
ClearPageReserved(page);
- set_bit(PG_highmem, &page->flags);
set_page_count(page, 1);
__free_page(page);
totalram_pages++;
diff --git a/arch/h8300/Kconfig.cpu b/arch/h8300/Kconfig.cpu
index d9dd62a565a..a380167a13c 100644
--- a/arch/h8300/Kconfig.cpu
+++ b/arch/h8300/Kconfig.cpu
@@ -180,4 +180,7 @@ config CPU_H8S
config PREEMPT
bool "Preemptible Kernel"
default n
+
+source "mm/Kconfig"
+
endmenu
diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c
index 134aec1c6d1..b5f83e9f04d 100644
--- a/arch/h8300/kernel/process.c
+++ b/arch/h8300/kernel/process.c
@@ -54,7 +54,7 @@ asmlinkage void ret_from_fork(void);
void default_idle(void)
{
while(1) {
- if (need_resched()) {
+ if (!need_resched()) {
local_irq_enable();
__asm__("sleep");
local_irq_disable();
diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c
index a4799d633ef..5aab87eae1f 100644
--- a/arch/h8300/kernel/signal.c
+++ b/arch/h8300/kernel/signal.c
@@ -517,10 +517,8 @@ asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset)
if ((regs->ccr & 0x10))
return 1;
- if (current->flags & PF_FREEZE) {
- refrigerator(0);
+ if (try_to_freeze())
goto no_signal;
- }
current->thread.esp0 = (unsigned long) regs;
diff --git a/arch/h8300/platform/h8300h/ptrace_h8300h.c b/arch/h8300/platform/h8300h/ptrace_h8300h.c
index 18e51a7167d..6ac93c05a1a 100644
--- a/arch/h8300/platform/h8300h/ptrace_h8300h.c
+++ b/arch/h8300/platform/h8300h/ptrace_h8300h.c
@@ -245,12 +245,12 @@ static unsigned short *getnextpc(struct task_struct *child, unsigned short *pc)
addr = h8300_get_reg(child, regno-1+PT_ER1);
return (unsigned short *)addr;
case relb:
- if ((inst = 0x55) || isbranch(child,inst & 0x0f))
+ if (inst == 0x55 || isbranch(child,inst & 0x0f))
pc = (unsigned short *)((unsigned long)pc +
((signed char)(*fetch_p)));
return pc+1; /* skip myself */
case relw:
- if ((inst = 0x5c) || isbranch(child,(*fetch_p & 0xf0) >> 4))
+ if (inst == 0x5c || isbranch(child,(*fetch_p & 0xf0) >> 4))
pc = (unsigned short *)((unsigned long)pc +
((signed short)(*(pc+1))));
return pc+2; /* skip myself */
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index e382f32d435..6c02336fe2e 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -68,7 +68,6 @@ config X86_VOYAGER
config X86_NUMAQ
bool "NUMAQ (IBM/Sequent)"
- select DISCONTIGMEM
select NUMA
help
This option is used for getting Linux to run on a (IBM/Sequent) NUMA
@@ -511,28 +510,7 @@ config SCHED_SMT
cost of slightly increased overhead in some places. If unsure say
N here.
-config PREEMPT
- bool "Preemptible Kernel"
- help
- This option reduces the latency of the kernel when reacting to
- real-time or interactive events by allowing a low priority process to
- be preempted even if it is in kernel mode executing a system call.
- This allows applications to run more reliably even when the system is
- under load.
-
- Say Y here if you are building a kernel for a desktop, embedded
- or real-time system. Say N if you are unsure.
-
-config PREEMPT_BKL
- bool "Preempt The Big Kernel Lock"
- depends on PREEMPT
- default y
- help
- This option reduces the latency of the kernel by making the
- big kernel lock preemptible.
-
- Say Y here if you are building a kernel for a desktop system.
- Say N if you are unsure.
+source "kernel/Kconfig.preempt"
config X86_UP_APIC
bool "Local APIC support on uniprocessors"
@@ -783,25 +761,48 @@ comment "NUMA (NUMA-Q) requires SMP, 64GB highmem support"
comment "NUMA (Summit) requires SMP, 64GB highmem support, ACPI"
depends on X86_SUMMIT && (!HIGHMEM64G || !ACPI)
-config DISCONTIGMEM
- bool
- depends on NUMA
- default y
-
config HAVE_ARCH_BOOTMEM_NODE
bool
depends on NUMA
default y
-config HAVE_MEMORY_PRESENT
+config ARCH_HAVE_MEMORY_PRESENT
bool
depends on DISCONTIGMEM
default y
config NEED_NODE_MEMMAP_SIZE
bool
- depends on DISCONTIGMEM
+ depends on DISCONTIGMEM || SPARSEMEM
+ default y
+
+config HAVE_ARCH_ALLOC_REMAP
+ bool
+ depends on NUMA
+ default y
+
+config ARCH_DISCONTIGMEM_ENABLE
+ def_bool y
+ depends on NUMA
+
+config ARCH_DISCONTIGMEM_DEFAULT
+ def_bool y
+ depends on NUMA
+
+config ARCH_SPARSEMEM_ENABLE
+ def_bool y
+ depends on NUMA
+
+config ARCH_SELECT_MEMORY_MODEL
+ def_bool y
+ depends on ARCH_SPARSEMEM_ENABLE
+
+source "mm/Kconfig"
+
+config HAVE_ARCH_EARLY_PFN_TO_NID
+ bool
default y
+ depends on NUMA
config HIGHPTE
bool "Allocate 3rd-level pagetables from highmem"
@@ -939,6 +940,43 @@ config SECCOMP
If unsure, say Y. Only embedded should say N here.
+source kernel/Kconfig.hz
+
+config PHYSICAL_START
+ hex "Physical address where the kernel is loaded" if EMBEDDED
+ default "0x100000"
+ help
+ This gives the physical address where the kernel is loaded.
+ Primarily used in the case of kexec on panic where the
+ fail safe kernel needs to run at a different address than
+ the panic-ed kernel.
+
+ Don't change this unless you know what you are doing.
+
+config KEXEC
+ bool "kexec system call (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ help
+ kexec is a system call that implements the ability to shutdown your
+ current kernel, and to start another kernel. It is like a reboot
+ but it is indepedent of the system firmware. And like a reboot
+ you can start any kernel with it, not just Linux.
+
+ The name comes from the similiarity to the exec system call.
+
+ It is an ongoing process to be certain the hardware in a machine
+ is properly shutdown, so do not be surprised if this code does not
+ initially work for you. It may help to enable device hotplugging
+ support. As of this writing the exact hardware interface is
+ strongly in flux, so no good recommendation can be made.
+
+config CRASH_DUMP
+ bool "kernel crash dumps (EXPERIMENTAL)"
+ depends on EMBEDDED
+ depends on EXPERIMENTAL
+ depends on HIGHMEM
+ help
+ Generate crash dump after being started by kexec.
endmenu
@@ -1163,7 +1201,7 @@ config PCI_DIRECT
config PCI_MMCONFIG
bool
- depends on PCI && (PCI_GOMMCONFIG || (PCI_GOANY && ACPI))
+ depends on PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY)
select ACPI_BOOT
default y
@@ -1226,6 +1264,15 @@ config SCx200
This support is also available as a module. If compiled as a
module, it will be called scx200.
+config HOTPLUG_CPU
+ bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
+ depends on SMP && HOTPLUG && EXPERIMENTAL
+ ---help---
+ Say Y here to experiment with turning CPUs off and on. CPUs
+ can be controlled through /sys/devices/system/cpu.
+
+ Say N.
+
source "drivers/pcmcia/Kconfig"
source "drivers/pci/hotplug/Kconfig"
diff --git a/arch/i386/Makefile b/arch/i386/Makefile
index 1c36ca332a9..bf7c9ba709f 100644
--- a/arch/i386/Makefile
+++ b/arch/i386/Makefile
@@ -17,6 +17,13 @@
# 20050320 Kianusch Sayah Karadji <kianusch@sk-tech.net>
# Added support for GEODE CPU
+HAS_BIARCH := $(call cc-option-yn, -m32)
+ifeq ($(HAS_BIARCH),y)
+AS := $(AS) --32
+LD := $(LD) -m elf_i386
+CC := $(CC) -m32
+endif
+
LDFLAGS := -m elf_i386
OBJCOPYFLAGS := -O binary -R .note -R .comment -S
LDFLAGS_vmlinux :=
diff --git a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile
index aa7064a75ee..1e71382d413 100644
--- a/arch/i386/boot/Makefile
+++ b/arch/i386/boot/Makefile
@@ -25,8 +25,8 @@ SVGA_MODE := -DSVGA_MODE=NORMAL_VGA
#RAMDISK := -DRAMDISK=512
-targets := vmlinux.bin bootsect bootsect.o setup setup.o \
- zImage bzImage
+targets := vmlinux.bin bootsect bootsect.o \
+ setup setup.o zImage bzImage
subdir- := compressed
hostprogs-y := tools/build
@@ -48,7 +48,7 @@ cmd_image = $(obj)/tools/build $(BUILDFLAGS) $(obj)/bootsect $(obj)/setup \
$(obj)/zImage $(obj)/bzImage: $(obj)/bootsect $(obj)/setup \
$(obj)/vmlinux.bin $(obj)/tools/build FORCE
$(call if_changed,image)
- @echo 'Kernel: $@ is ready'
+ @echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
$(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
$(call if_changed,objcopy)
diff --git a/arch/i386/boot/compressed/head.S b/arch/i386/boot/compressed/head.S
index c5e80b69e7d..b5893e4ecd3 100644
--- a/arch/i386/boot/compressed/head.S
+++ b/arch/i386/boot/compressed/head.S
@@ -25,6 +25,7 @@
#include <linux/linkage.h>
#include <asm/segment.h>
+#include <asm/page.h>
.globl startup_32
@@ -74,7 +75,7 @@ startup_32:
popl %esi # discard address
popl %esi # real mode pointer
xorl %ebx,%ebx
- ljmp $(__BOOT_CS), $0x100000
+ ljmp $(__BOOT_CS), $__PHYSICAL_START
/*
* We come here, if we were loaded high.
@@ -99,7 +100,7 @@ startup_32:
popl %ecx # lcount
popl %edx # high_buffer_start
popl %eax # hcount
- movl $0x100000,%edi
+ movl $__PHYSICAL_START,%edi
cli # make sure we don't get interrupted
ljmp $(__BOOT_CS), $0x1000 # and jump to the move routine
@@ -124,5 +125,5 @@ move_routine_start:
movsl
movl %ebx,%esi # Restore setup pointer
xorl %ebx,%ebx
- ljmp $(__BOOT_CS), $0x100000
+ ljmp $(__BOOT_CS), $__PHYSICAL_START
move_routine_end:
diff --git a/arch/i386/boot/compressed/misc.c b/arch/i386/boot/compressed/misc.c
index cedc55cc47d..82a807f9f5e 100644
--- a/arch/i386/boot/compressed/misc.c
+++ b/arch/i386/boot/compressed/misc.c
@@ -13,6 +13,7 @@
#include <linux/vmalloc.h>
#include <linux/tty.h>
#include <asm/io.h>
+#include <asm/page.h>
/*
* gzip declarations
@@ -308,7 +309,7 @@ static void setup_normal_output_buffer(void)
#else
if ((RM_ALT_MEM_K > RM_EXT_MEM_K ? RM_ALT_MEM_K : RM_EXT_MEM_K) < 1024) error("Less than 2MB of memory");
#endif
- output_data = (char *)0x100000; /* Points to 1M */
+ output_data = (char *)__PHYSICAL_START; /* Normally Points to 1M */
free_mem_end_ptr = (long)real_mode;
}
@@ -333,8 +334,8 @@ static void setup_output_buffer_if_we_run_high(struct moveparams *mv)
low_buffer_size = low_buffer_end - LOW_BUFFER_START;
high_loaded = 1;
free_mem_end_ptr = (long)high_buffer_start;
- if ( (0x100000 + low_buffer_size) > ((ulg)high_buffer_start)) {
- high_buffer_start = (uch *)(0x100000 + low_buffer_size);
+ if ( (__PHYSICAL_START + low_buffer_size) > ((ulg)high_buffer_start)) {
+ high_buffer_start = (uch *)(__PHYSICAL_START + low_buffer_size);
mv->hcount = 0; /* say: we need not to move high_buffer */
}
else mv->hcount = -1;
@@ -353,7 +354,6 @@ static void close_output_buffer_if_we_run_high(struct moveparams *mv)
}
}
-
asmlinkage int decompress_kernel(struct moveparams *mv, void *rmode)
{
real_mode = rmode;
diff --git a/arch/i386/boot/edd.S b/arch/i386/boot/edd.S
index 027d6b354ff..d8d69f2b911 100644
--- a/arch/i386/boot/edd.S
+++ b/arch/i386/boot/edd.S
@@ -6,7 +6,7 @@
* projects 1572D, 1484D, 1386D, 1226DT
* disk signature read by Matt Domsch <Matt_Domsch@dell.com>
* and Andrew Wilks <Andrew_Wilks@dell.com> September 2003, June 2004
- * legacy CHS retreival by Patrick J. LoPresti <patl@users.sourceforge.net>
+ * legacy CHS retrieval by Patrick J. LoPresti <patl@users.sourceforge.net>
* March 2004
* Command line option parsing, Matt Domsch, November 2004
*/
diff --git a/arch/i386/boot/install.sh b/arch/i386/boot/install.sh
index 90f2452b3b9..f17b40dfc0f 100644
--- a/arch/i386/boot/install.sh
+++ b/arch/i386/boot/install.sh
@@ -21,8 +21,8 @@
# User may have a custom install script
-if [ -x ~/bin/installkernel ]; then exec ~/bin/installkernel "$@"; fi
-if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi
+if [ -x ~/bin/${CROSS_COMPILE}installkernel ]; then exec ~/bin/${CROSS_COMPILE}installkernel "$@"; fi
+if [ -x /sbin/${CROSS_COMPILE}installkernel ]; then exec /sbin/${CROSS_COMPILE}installkernel "$@"; fi
# Default install - same as make zlilo
diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S
index caa1fde6904..8cb420f40c5 100644
--- a/arch/i386/boot/setup.S
+++ b/arch/i386/boot/setup.S
@@ -33,7 +33,7 @@
* Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999.
* <stiker@northlink.com>
*
- * Fix to work around buggy BIOSes which dont use carry bit correctly
+ * Fix to work around buggy BIOSes which don't use carry bit correctly
* and/or report extended memory in CX/DX for e801h memory size detection
* call. As a result the kernel got wrong figures. The int15/e801h docs
* from Ralf Brown interrupt list seem to indicate AX/BX should be used
@@ -357,7 +357,7 @@ bail820:
meme801:
stc # fix to work around buggy
- xorw %cx,%cx # BIOSes which dont clear/set
+ xorw %cx,%cx # BIOSes which don't clear/set
xorw %dx,%dx # carry on pass/error of
# e801h memory size call
# or merely pass cx,dx though
@@ -847,7 +847,7 @@ flush_instr:
#
# but we yet haven't reloaded the CS register, so the default size
# of the target offset still is 16 bit.
-# However, using an operand prefix (0x66), the CPU will properly
+# However, using an operand prefix (0x66), the CPU will properly
# take our 48 bit far pointer. (INTeL 80386 Programmer's Reference
# Manual, Mixing 16-bit and 32-bit code, page 16-6)
diff --git a/arch/i386/boot/tools/build.c b/arch/i386/boot/tools/build.c
index 26509b826ae..4a17956512e 100644
--- a/arch/i386/boot/tools/build.c
+++ b/arch/i386/boot/tools/build.c
@@ -1,6 +1,4 @@
/*
- * $Id: build.c,v 1.5 1997/05/19 12:29:58 mj Exp $
- *
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright (C) 1997 Martin Mares
*/
@@ -8,7 +6,8 @@
/*
* This file builds a disk-image from three different files:
*
- * - bootsect: exactly 512 bytes of 8086 machine code, loads the rest
+ * - bootsect: compatibility mbr which prints an error message if
+ * someone tries to boot the kernel directly.
* - setup: 8086 machine code, sets up system parm
* - system: 80386 code for actual system
*
diff --git a/arch/i386/crypto/aes.c b/arch/i386/crypto/aes.c
index 1019430fc1f..88ee85c3b43 100644
--- a/arch/i386/crypto/aes.c
+++ b/arch/i386/crypto/aes.c
@@ -59,7 +59,7 @@ struct aes_ctx {
};
#define WPOLY 0x011b
-#define u32_in(x) le32_to_cpu(*(const u32 *)(x))
+#define u32_in(x) le32_to_cpup((const __le32 *)(x))
#define bytes2word(b0, b1, b2, b3) \
(((u32)(b3) << 24) | ((u32)(b2) << 16) | ((u32)(b1) << 8) | (b0))
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index 28e62038379..ca07b95c06b 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -126,7 +126,6 @@ CONFIG_HAVE_DEC_LOCK=y
#
CONFIG_PM=y
CONFIG_SOFTWARE_SUSPEND=y
-# CONFIG_PM_DISK is not set
#
# ACPI (Advanced Configuration and Power Interface) Support
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index 0fbcfe00dd8..4cc83b322b3 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_X86_MPPARSE) += mpparse.o
obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o
obj-$(CONFIG_X86_IO_APIC) += io_apic.o
obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups.o
+obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o
obj-$(CONFIG_X86_NUMAQ) += numaq.o
obj-$(CONFIG_X86_SUMMIT_NUMA) += summit.o
obj-$(CONFIG_KPROBES) += kprobes.o
@@ -43,7 +44,7 @@ obj-$(CONFIG_SCx200) += scx200.o
# Note: kbuild does not track this dependency due to usage of .incbin
$(obj)/vsyscall.o: $(obj)/vsyscall-int80.so $(obj)/vsyscall-sysenter.so
targets += $(foreach F,int80 sysenter,vsyscall-$F.o vsyscall-$F.so)
-targets += vsyscall.lds
+targets += vsyscall-note.o vsyscall.lds
# The DSO images are built using a special linker script.
quiet_cmd_syscall = SYSCALL $@
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index 848bb97af7c..9f63ae0f404 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -29,6 +29,7 @@
#include <linux/efi.h>
#include <linux/irq.h>
#include <linux/module.h>
+#include <linux/dmi.h>
#include <asm/pgtable.h>
#include <asm/io_apic.h>
@@ -815,6 +816,219 @@ acpi_process_madt(void)
return;
}
+extern int acpi_force;
+
+#ifdef __i386__
+
+#ifdef CONFIG_ACPI_PCI
+static int __init disable_acpi_irq(struct dmi_system_id *d)
+{
+ if (!acpi_force) {
+ printk(KERN_NOTICE "%s detected: force use of acpi=noirq\n",
+ d->ident);
+ acpi_noirq_set();
+ }
+ return 0;
+}
+
+static int __init disable_acpi_pci(struct dmi_system_id *d)
+{
+ if (!acpi_force) {
+ printk(KERN_NOTICE "%s detected: force use of pci=noacpi\n",
+ d->ident);
+ acpi_disable_pci();
+ }
+ return 0;
+}
+#endif
+
+static int __init dmi_disable_acpi(struct dmi_system_id *d)
+{
+ if (!acpi_force) {
+ printk(KERN_NOTICE "%s detected: acpi off\n",d->ident);
+ disable_acpi();
+ } else {
+ printk(KERN_NOTICE
+ "Warning: DMI blacklist says broken, but acpi forced\n");
+ }
+ return 0;
+}
+
+/*
+ * Limit ACPI to CPU enumeration for HT
+ */
+static int __init force_acpi_ht(struct dmi_system_id *d)
+{
+ if (!acpi_force) {
+ printk(KERN_NOTICE "%s detected: force use of acpi=ht\n", d->ident);
+ disable_acpi();
+ acpi_ht = 1;
+ } else {
+ printk(KERN_NOTICE
+ "Warning: acpi=force overrules DMI blacklist: acpi=ht\n");
+ }
+ return 0;
+}
+
+/*
+ * If your system is blacklisted here, but you find that acpi=force
+ * works for you, please contact acpi-devel@sourceforge.net
+ */
+static struct dmi_system_id __initdata acpi_dmi_table[] = {
+ /*
+ * Boxes that need ACPI disabled
+ */
+ {
+ .callback = dmi_disable_acpi,
+ .ident = "IBM Thinkpad",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
+ DMI_MATCH(DMI_BOARD_NAME, "2629H1G"),
+ },
+ },
+
+ /*
+ * Boxes that need acpi=ht
+ */
+ {
+ .callback = force_acpi_ht,
+ .ident = "FSC Primergy T850",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "PRIMERGY T850"),
+ },
+ },
+ {
+ .callback = force_acpi_ht,
+ .ident = "DELL GX240",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Dell Computer Corporation"),
+ DMI_MATCH(DMI_BOARD_NAME, "OptiPlex GX240"),
+ },
+ },
+ {
+ .callback = force_acpi_ht,
+ .ident = "HP VISUALIZE NT Workstation",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP VISUALIZE NT Workstation"),
+ },
+ },
+ {
+ .callback = force_acpi_ht,
+ .ident = "Compaq Workstation W8000",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Workstation W8000"),
+ },
+ },
+ {
+ .callback = force_acpi_ht,
+ .ident = "ASUS P4B266",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "P4B266"),
+ },
+ },
+ {
+ .callback = force_acpi_ht,
+ .ident = "ASUS P2B-DS",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "P2B-DS"),
+ },
+ },
+ {
+ .callback = force_acpi_ht,
+ .ident = "ASUS CUR-DLS",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "CUR-DLS"),
+ },
+ },
+ {
+ .callback = force_acpi_ht,
+ .ident = "ABIT i440BX-W83977",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ABIT <http://www.abit.com>"),
+ DMI_MATCH(DMI_BOARD_NAME, "i440BX-W83977 (BP6)"),
+ },
+ },
+ {
+ .callback = force_acpi_ht,
+ .ident = "IBM Bladecenter",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
+ DMI_MATCH(DMI_BOARD_NAME, "IBM eServer BladeCenter HS20"),
+ },
+ },
+ {
+ .callback = force_acpi_ht,
+ .ident = "IBM eServer xSeries 360",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
+ DMI_MATCH(DMI_BOARD_NAME, "eServer xSeries 360"),
+ },
+ },
+ {
+ .callback = force_acpi_ht,
+ .ident = "IBM eserver xSeries 330",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
+ DMI_MATCH(DMI_BOARD_NAME, "eserver xSeries 330"),
+ },
+ },
+ {
+ .callback = force_acpi_ht,
+ .ident = "IBM eserver xSeries 440",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "eserver xSeries 440"),
+ },
+ },
+
+#ifdef CONFIG_ACPI_PCI
+ /*
+ * Boxes that need ACPI PCI IRQ routing disabled
+ */
+ {
+ .callback = disable_acpi_irq,
+ .ident = "ASUS A7V",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC"),
+ DMI_MATCH(DMI_BOARD_NAME, "<A7V>"),
+ /* newer BIOS, Revision 1011, does work */
+ DMI_MATCH(DMI_BIOS_VERSION, "ASUS A7V ACPI BIOS Revision 1007"),
+ },
+ },
+
+ /*
+ * Boxes that need ACPI PCI IRQ routing and PCI scan disabled
+ */
+ { /* _BBN 0 bug */
+ .callback = disable_acpi_pci,
+ .ident = "ASUS PR-DLS",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "PR-DLS"),
+ DMI_MATCH(DMI_BIOS_VERSION, "ASUS PR-DLS ACPI BIOS Revision 1010"),
+ DMI_MATCH(DMI_BIOS_DATE, "03/21/2003")
+ },
+ },
+ {
+ .callback = disable_acpi_pci,
+ .ident = "Acer TravelMate 36x Laptop",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
+ },
+ },
+#endif
+ { }
+};
+
+#endif /* __i386__ */
+
/*
* acpi_boot_table_init() and acpi_boot_init()
* called from setup_arch(), always.
@@ -843,6 +1057,10 @@ acpi_boot_table_init(void)
{
int error;
+#ifdef __i386__
+ dmi_check_system(acpi_dmi_table);
+#endif
+
/*
* If acpi_disabled, bail out
* One exception: acpi=ht continues far enough to enumerate LAPICs
@@ -870,8 +1088,6 @@ acpi_boot_table_init(void)
*/
error = acpi_blacklisted();
if (error) {
- extern int acpi_force;
-
if (acpi_force) {
printk(KERN_WARNING PREFIX "acpi=force override\n");
} else {
diff --git a/arch/i386/kernel/acpi/sleep.c b/arch/i386/kernel/acpi/sleep.c
index 28bb0514bb6..c1af93032ff 100644
--- a/arch/i386/kernel/acpi/sleep.c
+++ b/arch/i386/kernel/acpi/sleep.c
@@ -7,6 +7,7 @@
#include <linux/acpi.h>
#include <linux/bootmem.h>
+#include <linux/dmi.h>
#include <asm/smp.h>
#include <asm/tlbflush.h>
@@ -91,3 +92,29 @@ static int __init acpi_sleep_setup(char *str)
__setup("acpi_sleep=", acpi_sleep_setup);
+
+
+static __init int reset_videomode_after_s3(struct dmi_system_id *d)
+{
+ acpi_video_flags |= 2;
+ return 0;
+}
+
+static __initdata struct dmi_system_id acpisleep_dmi_table[] = {
+ { /* Reset video mode after returning from ACPI S3 sleep */
+ .callback = reset_videomode_after_s3,
+ .ident = "Toshiba Satellite 4030cdt",
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
+ },
+ },
+ { }
+};
+
+static int __init acpisleep_dmi_init(void)
+{
+ dmi_check_system(acpisleep_dmi_table);
+ return 0;
+}
+
+core_initcall(acpisleep_dmi_init);
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index d509836b70c..93df90bbb87 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -26,6 +26,7 @@
#include <linux/mc146818rtc.h>
#include <linux/kernel_stat.h>
#include <linux/sysdev.h>
+#include <linux/cpu.h>
#include <asm/atomic.h>
#include <asm/smp.h>
@@ -40,6 +41,11 @@
#include "io_ports.h"
/*
+ * Knob to control our willingness to enable the local APIC.
+ */
+int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */
+
+/*
* Debug level
*/
int apic_verbosity;
@@ -205,7 +211,7 @@ void __init connect_bsp_APIC(void)
enable_apic_mode();
}
-void disconnect_bsp_APIC(void)
+void disconnect_bsp_APIC(int virt_wire_setup)
{
if (pic_mode) {
/*
@@ -219,6 +225,42 @@ void disconnect_bsp_APIC(void)
outb(0x70, 0x22);
outb(0x00, 0x23);
}
+ else {
+ /* Go back to Virtual Wire compatibility mode */
+ unsigned long value;
+
+ /* For the spurious interrupt use vector F, and enable it */
+ value = apic_read(APIC_SPIV);
+ value &= ~APIC_VECTOR_MASK;
+ value |= APIC_SPIV_APIC_ENABLED;
+ value |= 0xf;
+ apic_write_around(APIC_SPIV, value);
+
+ if (!virt_wire_setup) {
+ /* For LVT0 make it edge triggered, active high, external and enabled */
+ value = apic_read(APIC_LVT0);
+ value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING |
+ APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
+ APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED );
+ value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
+ value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT);
+ apic_write_around(APIC_LVT0, value);
+ }
+ else {
+ /* Disable LVT0 */
+ apic_write_around(APIC_LVT0, APIC_LVT_MASKED);
+ }
+
+ /* For LVT1 make it edge triggered, active high, nmi and enabled */
+ value = apic_read(APIC_LVT1);
+ value &= ~(
+ APIC_MODE_MASK | APIC_SEND_PENDING |
+ APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
+ APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED);
+ value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
+ value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI);
+ apic_write_around(APIC_LVT1, value);
+ }
}
void disable_local_APIC(void)
@@ -363,7 +405,7 @@ void __init init_bsp_APIC(void)
apic_write_around(APIC_LVT1, value);
}
-void __init setup_local_APIC (void)
+void __devinit setup_local_APIC(void)
{
unsigned long oldvalue, value, ver, maxlvt;
@@ -634,7 +676,7 @@ static struct sys_device device_lapic = {
.cls = &lapic_sysclass,
};
-static void __init apic_pm_activate(void)
+static void __devinit apic_pm_activate(void)
{
apic_pm_state.active = 1;
}
@@ -665,26 +707,6 @@ static void apic_pm_activate(void) { }
* Original code written by Keir Fraser.
*/
-/*
- * Knob to control our willingness to enable the local APIC.
- */
-int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */
-
-static int __init lapic_disable(char *str)
-{
- enable_local_apic = -1;
- clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
- return 0;
-}
-__setup("nolapic", lapic_disable);
-
-static int __init lapic_enable(char *str)
-{
- enable_local_apic = 1;
- return 0;
-}
-__setup("lapic", lapic_enable);
-
static int __init apic_set_verbosity(char *str)
{
if (strcmp("debug", str) == 0)
@@ -855,7 +877,7 @@ fake_ioapic_page:
* but we do not accept timer interrupts yet. We only allow the BP
* to calibrate.
*/
-static unsigned int __init get_8254_timer_count(void)
+static unsigned int __devinit get_8254_timer_count(void)
{
extern spinlock_t i8253_lock;
unsigned long flags;
@@ -874,7 +896,7 @@ static unsigned int __init get_8254_timer_count(void)
}
/* next tick in 8254 can be caught by catching timer wraparound */
-static void __init wait_8254_wraparound(void)
+static void __devinit wait_8254_wraparound(void)
{
unsigned int curr_count, prev_count;
@@ -894,7 +916,7 @@ static void __init wait_8254_wraparound(void)
* Default initialization for 8254 timers. If we use other timers like HPET,
* we override this later
*/
-void (*wait_timer_tick)(void) __initdata = wait_8254_wraparound;
+void (*wait_timer_tick)(void) __devinitdata = wait_8254_wraparound;
/*
* This function sets up the local APIC timer, with a timeout of
@@ -930,7 +952,7 @@ static void __setup_APIC_LVTT(unsigned int clocks)
apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR);
}
-static void __init setup_APIC_timer(unsigned int clocks)
+static void __devinit setup_APIC_timer(unsigned int clocks)
{
unsigned long flags;
@@ -1043,12 +1065,12 @@ void __init setup_boot_APIC_clock(void)
local_irq_enable();
}
-void __init setup_secondary_APIC_clock(void)
+void __devinit setup_secondary_APIC_clock(void)
{
setup_APIC_timer(calibration_result);
}
-void __init disable_APIC_timer(void)
+void __devinit disable_APIC_timer(void)
{
if (using_apic_timer) {
unsigned long v;
@@ -1133,7 +1155,7 @@ inline void smp_local_timer_interrupt(struct pt_regs * regs)
}
#ifdef CONFIG_SMP
- update_process_times(user_mode(regs));
+ update_process_times(user_mode_vm(regs));
#endif
}
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index 45641a87255..d48ce929096 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -346,10 +346,10 @@ extern int (*console_blank_hook)(int);
struct apm_user {
int magic;
struct apm_user * next;
- int suser: 1;
- int writer: 1;
- int reader: 1;
- int suspend_wait: 1;
+ unsigned int suser: 1;
+ unsigned int writer: 1;
+ unsigned int reader: 1;
+ unsigned int suspend_wait: 1;
int suspend_result;
int suspends_pending;
int standbys_pending;
@@ -1222,6 +1222,7 @@ static int suspend(int vetoable)
save_processor_state();
err = set_system_power_state(APM_STATE_SUSPEND);
+ ignore_normal_resume = 1;
restore_processor_state();
local_irq_disable();
@@ -1229,7 +1230,6 @@ static int suspend(int vetoable)
spin_lock(&i8253_lock);
reinit_timer();
set_time();
- ignore_normal_resume = 1;
spin_unlock(&i8253_lock);
write_sequnlock(&xtime_lock);
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c
index 16dbc4151be..73aeaf5a9d4 100644
--- a/arch/i386/kernel/cpu/amd.c
+++ b/arch/i386/kernel/cpu/amd.c
@@ -24,9 +24,6 @@ __asm__(".align 4\nvide: ret");
static void __init init_amd(struct cpuinfo_x86 *c)
{
-#ifdef CONFIG_X86_SMP
- int cpu = c == &boot_cpu_data ? 0 : c - cpu_data;
-#endif
u32 l, h;
int mbytes = num_physpages >> (20-PAGE_SHIFT);
int r;
@@ -198,14 +195,19 @@ static void __init init_amd(struct cpuinfo_x86 *c)
c->x86_num_cores = 1;
}
-#ifdef CONFIG_X86_SMP
+#ifdef CONFIG_X86_HT
/*
* On a AMD dual core setup the lower bits of the APIC id
* distingush the cores. Assumes number of cores is a power
* of two.
*/
if (c->x86_num_cores > 1) {
- cpu_core_id[cpu] = cpu >> hweight32(c->x86_num_cores - 1);
+ int cpu = smp_processor_id();
+ unsigned bits = 0;
+ while ((1 << bits) < c->x86_num_cores)
+ bits++;
+ cpu_core_id[cpu] = phys_proc_id[cpu] & ((1<<bits)-1);
+ phys_proc_id[cpu] >>= bits;
printk(KERN_INFO "CPU %d(%d) -> Core %d\n",
cpu, c->x86_num_cores, cpu_core_id[cpu]);
}
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index 6be0310e3cd..2203a9d2021 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -24,9 +24,9 @@ EXPORT_PER_CPU_SYMBOL(cpu_gdt_table);
DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack);
-static int cachesize_override __initdata = -1;
-static int disable_x86_fxsr __initdata = 0;
-static int disable_x86_serial_nr __initdata = 1;
+static int cachesize_override __devinitdata = -1;
+static int disable_x86_fxsr __devinitdata = 0;
+static int disable_x86_serial_nr __devinitdata = 1;
struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {};
@@ -59,7 +59,7 @@ static int __init cachesize_setup(char *str)
}
__setup("cachesize=", cachesize_setup);
-int __init get_model_name(struct cpuinfo_x86 *c)
+int __devinit get_model_name(struct cpuinfo_x86 *c)
{
unsigned int *v;
char *p, *q;
@@ -89,7 +89,7 @@ int __init get_model_name(struct cpuinfo_x86 *c)
}
-void __init display_cacheinfo(struct cpuinfo_x86 *c)
+void __devinit display_cacheinfo(struct cpuinfo_x86 *c)
{
unsigned int n, dummy, ecx, edx, l2size;
@@ -130,7 +130,7 @@ void __init display_cacheinfo(struct cpuinfo_x86 *c)
/* in particular, if CPUID levels 0x80000002..4 are supported, this isn't used */
/* Look up CPU names by table lookup. */
-static char __init *table_lookup_model(struct cpuinfo_x86 *c)
+static char __devinit *table_lookup_model(struct cpuinfo_x86 *c)
{
struct cpu_model_info *info;
@@ -151,7 +151,7 @@ static char __init *table_lookup_model(struct cpuinfo_x86 *c)
}
-void __init get_cpu_vendor(struct cpuinfo_x86 *c, int early)
+void __devinit get_cpu_vendor(struct cpuinfo_x86 *c, int early)
{
char *v = c->x86_vendor_id;
int i;
@@ -202,7 +202,7 @@ static inline int flag_is_changeable_p(u32 flag)
/* Probe for the CPUID instruction */
-static int __init have_cpuid_p(void)
+static int __devinit have_cpuid_p(void)
{
return flag_is_changeable_p(X86_EFLAGS_ID);
}
@@ -243,9 +243,13 @@ static void __init early_cpu_detect(void)
}
early_intel_workaround(c);
+
+#ifdef CONFIG_X86_HT
+ phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff;
+#endif
}
-void __init generic_identify(struct cpuinfo_x86 * c)
+void __devinit generic_identify(struct cpuinfo_x86 * c)
{
u32 tfms, xlvl;
int junk;
@@ -292,7 +296,7 @@ void __init generic_identify(struct cpuinfo_x86 * c)
}
}
-static void __init squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
+static void __devinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
{
if (cpu_has(c, X86_FEATURE_PN) && disable_x86_serial_nr ) {
/* Disable processor serial number */
@@ -320,7 +324,7 @@ __setup("serialnumber", x86_serial_nr_setup);
/*
* This does the hard work of actually picking apart the CPU stuff...
*/
-void __init identify_cpu(struct cpuinfo_x86 *c)
+void __devinit identify_cpu(struct cpuinfo_x86 *c)
{
int i;
@@ -428,10 +432,13 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
#ifdef CONFIG_X86_MCE
mcheck_init(c);
#endif
+ if (c == &boot_cpu_data)
+ sysenter_setup();
+ enable_sep_cpu();
}
#ifdef CONFIG_X86_HT
-void __init detect_ht(struct cpuinfo_x86 *c)
+void __devinit detect_ht(struct cpuinfo_x86 *c)
{
u32 eax, ebx, ecx, edx;
int index_msb, tmp;
@@ -486,7 +493,7 @@ void __init detect_ht(struct cpuinfo_x86 *c)
}
#endif
-void __init print_cpu_info(struct cpuinfo_x86 *c)
+void __devinit print_cpu_info(struct cpuinfo_x86 *c)
{
char *vendor = NULL;
@@ -509,7 +516,7 @@ void __init print_cpu_info(struct cpuinfo_x86 *c)
printk("\n");
}
-cpumask_t cpu_initialized __initdata = CPU_MASK_NONE;
+cpumask_t cpu_initialized __devinitdata = CPU_MASK_NONE;
/* This is hacky. :)
* We're emulating future behavior.
@@ -556,7 +563,7 @@ void __init early_cpu_init(void)
* and IDT. We reload them nevertheless, this function acts as a
* 'CPU state barrier', nothing should get across.
*/
-void __init cpu_init (void)
+void __devinit cpu_init(void)
{
int cpu = smp_processor_id();
struct tss_struct * t = &per_cpu(init_tss, cpu);
@@ -631,7 +638,7 @@ void __init cpu_init (void)
/* Clear all 6 debug registers: */
-#define CD(register) __asm__("movl %0,%%db" #register ::"r"(0) );
+#define CD(register) set_debugreg(0, register)
CD(0); CD(1); CD(2); CD(3); /* no db4 and db5 */; CD(6); CD(7);
@@ -644,3 +651,15 @@ void __init cpu_init (void)
clear_used_math();
mxcsr_feature_mask_init();
}
+
+#ifdef CONFIG_HOTPLUG_CPU
+void __devinit cpu_uninit(void)
+{
+ int cpu = raw_smp_processor_id();
+ cpu_clear(cpu, cpu_initialized);
+
+ /* lazy TLB state */
+ per_cpu(cpu_tlbstate, cpu).state = 0;
+ per_cpu(cpu_tlbstate, cpu).active_mm = &init_mm;
+}
+#endif
diff --git a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig
index f25ffd74235..0f1eb507233 100644
--- a/arch/i386/kernel/cpu/cpufreq/Kconfig
+++ b/arch/i386/kernel/cpu/cpufreq/Kconfig
@@ -23,7 +23,7 @@ config X86_ACPI_CPUFREQ
If in doubt, say N.
config ELAN_CPUFREQ
- tristate "AMD Elan"
+ tristate "AMD Elan SC400 and SC410"
select CPU_FREQ_TABLE
depends on X86_ELAN
---help---
@@ -38,6 +38,18 @@ config ELAN_CPUFREQ
If in doubt, say N.
+config SC520_CPUFREQ
+ tristate "AMD Elan SC520"
+ select CPU_FREQ_TABLE
+ depends on X86_ELAN
+ ---help---
+ This adds the CPUFreq driver for AMD Elan SC520 processor.
+
+ For details, take a look at <file:Documentation/cpu-freq/>.
+
+ If in doubt, say N.
+
+
config X86_POWERNOW_K6
tristate "AMD Mobile K6-2/K6-3 PowerNow!"
select CPU_FREQ_TABLE
diff --git a/arch/i386/kernel/cpu/cpufreq/Makefile b/arch/i386/kernel/cpu/cpufreq/Makefile
index a922e97aeed..2e894f1c891 100644
--- a/arch/i386/kernel/cpu/cpufreq/Makefile
+++ b/arch/i386/kernel/cpu/cpufreq/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o
obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o
obj-$(CONFIG_X86_LONGHAUL) += longhaul.o
obj-$(CONFIG_ELAN_CPUFREQ) += elanfreq.o
+obj-$(CONFIG_SC520_CPUFREQ) += sc520_freq.o
obj-$(CONFIG_X86_LONGRUN) += longrun.o
obj-$(CONFIG_X86_GX_SUSPMOD) += gx-suspmod.o
obj-$(CONFIG_X86_SPEEDSTEP_ICH) += speedstep-ich.o
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index ab0f9f5aac1..04e3563da4f 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -29,6 +29,7 @@
#include <linux/cpufreq.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/pci.h>
#include <asm/msr.h>
#include <asm/timex.h>
@@ -119,7 +120,13 @@ static int longhaul_get_cpu_mult(void)
static void do_powersaver(union msr_longhaul *longhaul,
unsigned int clock_ratio_index)
{
+ struct pci_dev *dev;
+ unsigned long flags;
+ unsigned int tmp_mask;
int version;
+ int i;
+ u16 pci_cmd;
+ u16 cmd_state[64];
switch (cpu_model) {
case CPU_EZRA_T:
@@ -137,17 +144,58 @@ static void do_powersaver(union msr_longhaul *longhaul,
longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
longhaul->bits.EnableSoftBusRatio = 1;
longhaul->bits.RevisionKey = 0;
- local_irq_disable();
- wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
+
+ preempt_disable();
+ local_irq_save(flags);
+
+ /*
+ * get current pci bus master state for all devices
+ * and clear bus master bit
+ */
+ dev = NULL;
+ i = 0;
+ do {
+ dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
+ if (dev != NULL) {
+ pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);
+ cmd_state[i++] = pci_cmd;
+ pci_cmd &= ~PCI_COMMAND_MASTER;
+ pci_write_config_word(dev, PCI_COMMAND, pci_cmd);
+ }
+ } while (dev != NULL);
+
+ tmp_mask=inb(0x21); /* works on C3. save mask. */
+ outb(0xFE,0x21); /* TMR0 only */
+ outb(0xFF,0x80); /* delay */
+
local_irq_enable();
+
+ __hlt();
+ wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
__hlt();
+ local_irq_disable();
+
+ outb(tmp_mask,0x21); /* restore mask */
+
+ /* restore pci bus master state for all devices */
+ dev = NULL;
+ i = 0;
+ do {
+ dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
+ if (dev != NULL) {
+ pci_cmd = cmd_state[i++];
+ pci_write_config_byte(dev, PCI_COMMAND, pci_cmd);
+ }
+ } while (dev != NULL);
+ local_irq_restore(flags);
+ preempt_enable();
+
+ /* disable bus ratio bit */
rdmsrl(MSR_VIA_LONGHAUL, longhaul->val);
longhaul->bits.EnableSoftBusRatio = 0;
longhaul->bits.RevisionKey = version;
- local_irq_disable();
wrmsrl(MSR_VIA_LONGHAUL, longhaul->val);
- local_irq_enable();
}
/**
@@ -578,7 +626,7 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
longhaul_setup_voltagescaling();
policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
- policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+ policy->cpuinfo.transition_latency = 200000; /* nsec */
policy->cur = calc_speed(longhaul_get_cpu_mult());
ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table);
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
index 913f652623d..73a5dc5b26b 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
@@ -23,6 +23,7 @@
#include <linux/dmi.h>
#include <asm/msr.h>
+#include <asm/timer.h>
#include <asm/timex.h>
#include <asm/io.h>
#include <asm/system.h>
@@ -586,13 +587,17 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy)
rdmsrl (MSR_K7_FID_VID_STATUS, fidvidstatus.val);
- /* A K7 with powernow technology is set to max frequency by BIOS */
- fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.MFID];
+ /* recalibrate cpu_khz */
+ result = recalibrate_cpu_khz();
+ if (result)
+ return result;
+
+ fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID];
if (!fsb) {
printk(KERN_WARNING PFX "can not determine bus frequency\n");
return -EINVAL;
}
- dprintk("FSB: %3d.%03d MHz\n", fsb/1000, fsb%1000);
+ dprintk("FSB: %3dMHz\n", fsb/1000);
if (dmi_check_system(powernow_dmi_table) || acpi_force) {
printk (KERN_INFO PFX "PSB/PST known to be broken. Trying ACPI instead\n");
@@ -643,9 +648,7 @@ static int powernow_cpu_exit (struct cpufreq_policy *policy) {
}
#endif
- if (powernow_table)
- kfree(powernow_table);
-
+ kfree(powernow_table);
return 0;
}
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
index a65ff7e32e5..10cc096c0ad 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
@@ -4,7 +4,7 @@
* GNU general public license version 2. See "COPYING" or
* http://www.gnu.org/licenses/gpl.html
*
- * Support : paul.devriendt@amd.com
+ * Support : mark.langsdorf@amd.com
*
* Based on the powernow-k7.c module written by Dave Jones.
* (C) 2003 Dave Jones <davej@codemonkey.org.uk> on behalf of SuSE Labs
@@ -15,12 +15,13 @@
*
* Valuable input gratefully received from Dave Jones, Pavel Machek,
* Dominik Brodowski, and others.
+ * Originally developed by Paul Devriendt.
* Processor information obtained from Chapter 9 (Power and Thermal Management)
* of the "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD
* Opteron Processors" available for download from www.amd.com
*
* Tables for specific CPUs can be infrerred from
- * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/30430.pdf
+ * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/30430.pdf
*/
#include <linux/kernel.h>
@@ -30,6 +31,7 @@
#include <linux/cpufreq.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/cpumask.h>
#include <asm/msr.h>
#include <asm/io.h>
@@ -42,7 +44,7 @@
#define PFX "powernow-k8: "
#define BFX PFX "BIOS error: "
-#define VERSION "version 1.00.09e"
+#define VERSION "version 1.40.2"
#include "powernow-k8.h"
/* serialize freq changes */
@@ -50,6 +52,10 @@ static DECLARE_MUTEX(fidvid_sem);
static struct powernow_k8_data *powernow_data[NR_CPUS];
+#ifndef CONFIG_SMP
+static cpumask_t cpu_core_map[1];
+#endif
+
/* Return a frequency in MHz, given an input fid */
static u32 find_freq_from_fid(u32 fid)
{
@@ -274,11 +280,18 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid
{
u32 rvosteps = data->rvo;
u32 savefid = data->currfid;
+ u32 maxvid, lo;
dprintk("ph1 (cpu%d): start, currfid 0x%x, currvid 0x%x, reqvid 0x%x, rvo 0x%x\n",
smp_processor_id(),
data->currfid, data->currvid, reqvid, data->rvo);
+ rdmsr(MSR_FIDVID_STATUS, lo, maxvid);
+ maxvid = 0x1f & (maxvid >> 16);
+ dprintk("ph1 maxvid=0x%x\n", maxvid);
+ if (reqvid < maxvid) /* lower numbers are higher voltages */
+ reqvid = maxvid;
+
while (data->currvid > reqvid) {
dprintk("ph1: curr 0x%x, req vid 0x%x\n",
data->currvid, reqvid);
@@ -286,8 +299,8 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid
return 1;
}
- while ((rvosteps > 0) && ((data->rvo + data->currvid) > reqvid)) {
- if (data->currvid == 0) {
+ while ((rvosteps > 0) && ((data->rvo + data->currvid) > reqvid)) {
+ if (data->currvid == maxvid) {
rvosteps = 0;
} else {
dprintk("ph1: changing vid for rvo, req 0x%x\n",
@@ -671,7 +684,7 @@ static int find_psb_table(struct powernow_k8_data *data)
* BIOS and Kernel Developer's Guide, which is available on
* www.amd.com
*/
- printk(KERN_ERR PFX "BIOS error - no PSB\n");
+ printk(KERN_INFO PFX "BIOS error - no PSB or ACPI _PSS objects\n");
return -ENODEV;
}
@@ -695,7 +708,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
struct cpufreq_frequency_table *powernow_table;
if (acpi_processor_register_performance(&data->acpi_data, data->cpu)) {
- dprintk("register performance failed\n");
+ dprintk("register performance failed: bad ACPI data\n");
return -EIO;
}
@@ -746,22 +759,23 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
continue;
}
- if (fid < HI_FID_TABLE_BOTTOM) {
- if (cntlofreq) {
- /* if both entries are the same, ignore this
- * one...
- */
- if ((powernow_table[i].frequency != powernow_table[cntlofreq].frequency) ||
- (powernow_table[i].index != powernow_table[cntlofreq].index)) {
- printk(KERN_ERR PFX "Too many lo freq table entries\n");
- goto err_out_mem;
- }
-
- dprintk("double low frequency table entry, ignoring it.\n");
- powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
- continue;
- } else
- cntlofreq = i;
+ /* verify only 1 entry from the lo frequency table */
+ if (fid < HI_FID_TABLE_BOTTOM) {
+ if (cntlofreq) {
+ /* if both entries are the same, ignore this
+ * one...
+ */
+ if ((powernow_table[i].frequency != powernow_table[cntlofreq].frequency) ||
+ (powernow_table[i].index != powernow_table[cntlofreq].index)) {
+ printk(KERN_ERR PFX "Too many lo freq table entries\n");
+ goto err_out_mem;
+ }
+
+ dprintk("double low frequency table entry, ignoring it.\n");
+ powernow_table[i].frequency = CPUFREQ_ENTRY_INVALID;
+ continue;
+ } else
+ cntlofreq = i;
}
if (powernow_table[i].frequency != (data->acpi_data.states[i].core_frequency * 1000)) {
@@ -816,7 +830,7 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde
{
u32 fid;
u32 vid;
- int res;
+ int res, i;
struct cpufreq_freqs freqs;
dprintk("cpu %d transition to index %u\n", smp_processor_id(), index);
@@ -841,7 +855,8 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde
}
if ((fid < HI_FID_TABLE_BOTTOM) && (data->currfid < HI_FID_TABLE_BOTTOM)) {
- printk("ignoring illegal change in lo freq table-%x to 0x%x\n",
+ printk(KERN_ERR PFX
+ "ignoring illegal change in lo freq table-%x to 0x%x\n",
data->currfid, fid);
return 1;
}
@@ -850,18 +865,20 @@ static int transition_frequency(struct powernow_k8_data *data, unsigned int inde
smp_processor_id(), fid, vid);
freqs.cpu = data->cpu;
-
freqs.old = find_khz_freq_from_fid(data->currfid);
freqs.new = find_khz_freq_from_fid(fid);
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ for_each_cpu_mask(i, cpu_core_map[data->cpu]) {
+ freqs.cpu = i;
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ }
- down(&fidvid_sem);
res = transition_fid_vid(data, fid, vid);
- up(&fidvid_sem);
freqs.new = find_khz_freq_from_fid(data->currfid);
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
+ for_each_cpu_mask(i, cpu_core_map[data->cpu]) {
+ freqs.cpu = i;
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ }
return res;
}
@@ -874,6 +891,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
u32 checkvid = data->currvid;
unsigned int newstate;
int ret = -EIO;
+ int i;
/* only run on specific CPU from here on */
oldmask = current->cpus_allowed;
@@ -902,22 +920,41 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
data->currfid, data->currvid);
if ((checkvid != data->currvid) || (checkfid != data->currfid)) {
- printk(KERN_ERR PFX
- "error - out of sync, fid 0x%x 0x%x, vid 0x%x 0x%x\n",
- checkfid, data->currfid, checkvid, data->currvid);
+ printk(KERN_INFO PFX
+ "error - out of sync, fix 0x%x 0x%x, vid 0x%x 0x%x\n",
+ checkfid, data->currfid, checkvid, data->currvid);
}
if (cpufreq_frequency_table_target(pol, data->powernow_table, targfreq, relation, &newstate))
goto err_out;
+ down(&fidvid_sem);
+
+ for_each_cpu_mask(i, cpu_core_map[pol->cpu]) {
+ /* make sure the sibling is initialized */
+ if (!powernow_data[i]) {
+ ret = 0;
+ up(&fidvid_sem);
+ goto err_out;
+ }
+ }
+
powernow_k8_acpi_pst_values(data, newstate);
if (transition_frequency(data, newstate)) {
printk(KERN_ERR PFX "transition frequency failed\n");
ret = 1;
+ up(&fidvid_sem);
goto err_out;
}
+ /* Update all the fid/vids of our siblings */
+ for_each_cpu_mask(i, cpu_core_map[pol->cpu]) {
+ powernow_data[i]->currvid = data->currvid;
+ powernow_data[i]->currfid = data->currfid;
+ }
+ up(&fidvid_sem);
+
pol->cur = find_khz_freq_from_fid(data->currfid);
ret = 0;
@@ -962,7 +999,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
*/
if ((num_online_cpus() != 1) || (num_possible_cpus() != 1)) {
- printk(KERN_INFO PFX "MP systems not supported by PSB BIOS structure\n");
+ printk(KERN_ERR PFX "MP systems not supported by PSB BIOS structure\n");
kfree(data);
return -ENODEV;
}
@@ -1003,6 +1040,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol)
schedule();
pol->governor = CPUFREQ_DEFAULT_GOVERNOR;
+ pol->cpus = cpu_core_map[pol->cpu];
/* Take a crude guess here.
* That guess was in microseconds, so multiply with 1000 */
@@ -1069,7 +1107,7 @@ static unsigned int powernowk8_get (unsigned int cpu)
return 0;
}
preempt_disable();
-
+
if (query_current_values_with_pending_wait(data))
goto out;
@@ -1127,9 +1165,10 @@ static void __exit powernowk8_exit(void)
cpufreq_unregister_driver(&cpufreq_amd64_driver);
}
-MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com>");
+MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com> and Mark Langsdorf <mark.langsdorf@amd.com.");
MODULE_DESCRIPTION("AMD Athlon 64 and Opteron processor frequency driver.");
MODULE_LICENSE("GPL");
late_initcall(powernowk8_init);
module_exit(powernowk8_exit);
+
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
index 63ebc8470f5..9ed5bf221cb 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h
@@ -174,3 +174,18 @@ static int core_voltage_post_transition(struct powernow_k8_data *data, u32 reqvi
static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid);
static void powernow_k8_acpi_pst_values(struct powernow_k8_data *data, unsigned int index);
+
+#ifndef for_each_cpu_mask
+#define for_each_cpu_mask(i,mask) for (i=0;i<1;i++)
+#endif
+
+#ifdef CONFIG_SMP
+static inline void define_siblings(int cpu, cpumask_t cpu_sharedcore_mask[])
+{
+}
+#else
+static inline void define_siblings(int cpu, cpumask_t cpu_sharedcore_mask[])
+{
+ cpu_set(0, cpu_sharedcore_mask[0]);
+}
+#endif
diff --git a/arch/i386/kernel/cpu/cpufreq/sc520_freq.c b/arch/i386/kernel/cpu/cpufreq/sc520_freq.c
new file mode 100644
index 00000000000..ef457d50f4a
--- /dev/null
+++ b/arch/i386/kernel/cpu/cpufreq/sc520_freq.c
@@ -0,0 +1,186 @@
+/*
+ * sc520_freq.c: cpufreq driver for the AMD Elan sc520
+ *
+ * Copyright (C) 2005 Sean Young <sean@mess.org>
+ *
+ * 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.
+ *
+ * Based on elanfreq.c
+ *
+ * 2005-03-30: - initial revision
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/delay.h>
+#include <linux/cpufreq.h>
+
+#include <asm/msr.h>
+#include <asm/timex.h>
+#include <asm/io.h>
+
+#define MMCR_BASE 0xfffef000 /* The default base address */
+#define OFFS_CPUCTL 0x2 /* CPU Control Register */
+
+static __u8 __iomem *cpuctl;
+
+#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "sc520_freq", msg)
+
+static struct cpufreq_frequency_table sc520_freq_table[] = {
+ {0x01, 100000},
+ {0x02, 133000},
+ {0, CPUFREQ_TABLE_END},
+};
+
+static unsigned int sc520_freq_get_cpu_frequency(unsigned int cpu)
+{
+ u8 clockspeed_reg = *cpuctl;
+
+ switch (clockspeed_reg & 0x03) {
+ default:
+ printk(KERN_ERR "sc520_freq: error: cpuctl register has unexpected value %02x\n", clockspeed_reg);
+ case 0x01:
+ return 100000;
+ case 0x02:
+ return 133000;
+ }
+}
+
+static void sc520_freq_set_cpu_state (unsigned int state)
+{
+
+ struct cpufreq_freqs freqs;
+ u8 clockspeed_reg;
+
+ freqs.old = sc520_freq_get_cpu_frequency(0);
+ freqs.new = sc520_freq_table[state].frequency;
+ freqs.cpu = 0; /* AMD Elan is UP */
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+ dprintk("attempting to set frequency to %i kHz\n",
+ sc520_freq_table[state].frequency);
+
+ local_irq_disable();
+
+ clockspeed_reg = *cpuctl & ~0x03;
+ *cpuctl = clockspeed_reg | sc520_freq_table[state].index;
+
+ local_irq_enable();
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+};
+
+static int sc520_freq_verify (struct cpufreq_policy *policy)
+{
+ return cpufreq_frequency_table_verify(policy, &sc520_freq_table[0]);
+}
+
+static int sc520_freq_target (struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ unsigned int newstate = 0;
+
+ if (cpufreq_frequency_table_target(policy, sc520_freq_table, target_freq, relation, &newstate))
+ return -EINVAL;
+
+ sc520_freq_set_cpu_state(newstate);
+
+ return 0;
+}
+
+
+/*
+ * Module init and exit code
+ */
+
+static int sc520_freq_cpu_init(struct cpufreq_policy *policy)
+{
+ struct cpuinfo_x86 *c = cpu_data;
+ int result;
+
+ /* capability check */
+ if (c->x86_vendor != X86_VENDOR_AMD ||
+ c->x86 != 4 || c->x86_model != 9)
+ return -ENODEV;
+
+ /* cpuinfo and default policy values */
+ policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
+ policy->cpuinfo.transition_latency = 1000000; /* 1ms */
+ policy->cur = sc520_freq_get_cpu_frequency(0);
+
+ result = cpufreq_frequency_table_cpuinfo(policy, sc520_freq_table);
+ if (result)
+ return (result);
+
+ cpufreq_frequency_table_get_attr(sc520_freq_table, policy->cpu);
+
+ return 0;
+}
+
+
+static int sc520_freq_cpu_exit(struct cpufreq_policy *policy)
+{
+ cpufreq_frequency_table_put_attr(policy->cpu);
+ return 0;
+}
+
+
+static struct freq_attr* sc520_freq_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ NULL,
+};
+
+
+static struct cpufreq_driver sc520_freq_driver = {
+ .get = sc520_freq_get_cpu_frequency,
+ .verify = sc520_freq_verify,
+ .target = sc520_freq_target,
+ .init = sc520_freq_cpu_init,
+ .exit = sc520_freq_cpu_exit,
+ .name = "sc520_freq",
+ .owner = THIS_MODULE,
+ .attr = sc520_freq_attr,
+};
+
+
+static int __init sc520_freq_init(void)
+{
+ struct cpuinfo_x86 *c = cpu_data;
+
+ /* Test if we have the right hardware */
+ if(c->x86_vendor != X86_VENDOR_AMD ||
+ c->x86 != 4 || c->x86_model != 9) {
+ dprintk("no Elan SC520 processor found!\n");
+ return -ENODEV;
+ }
+ cpuctl = ioremap((unsigned long)(MMCR_BASE + OFFS_CPUCTL), 1);
+ if(!cpuctl) {
+ printk(KERN_ERR "sc520_freq: error: failed to remap memory\n");
+ return -ENOMEM;
+ }
+
+ return cpufreq_register_driver(&sc520_freq_driver);
+}
+
+
+static void __exit sc520_freq_exit(void)
+{
+ cpufreq_unregister_driver(&sc520_freq_driver);
+ iounmap(cpuctl);
+}
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sean Young <sean@mess.org>");
+MODULE_DESCRIPTION("cpufreq driver for AMD's Elan sc520 CPU");
+
+module_init(sc520_freq_init);
+module_exit(sc520_freq_exit);
+
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
index 07d5612dc00..7dcbf70fc16 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -54,6 +54,8 @@ enum {
CPU_DOTHAN_A1,
CPU_DOTHAN_A2,
CPU_DOTHAN_B0,
+ CPU_MP4HT_D0,
+ CPU_MP4HT_E0,
};
static const struct cpu_id cpu_ids[] = {
@@ -61,6 +63,8 @@ static const struct cpu_id cpu_ids[] = {
[CPU_DOTHAN_A1] = { 6, 13, 1 },
[CPU_DOTHAN_A2] = { 6, 13, 2 },
[CPU_DOTHAN_B0] = { 6, 13, 6 },
+ [CPU_MP4HT_D0] = {15, 3, 4 },
+ [CPU_MP4HT_E0] = {15, 4, 1 },
};
#define N_IDS (sizeof(cpu_ids)/sizeof(cpu_ids[0]))
@@ -226,6 +230,8 @@ static struct cpu_model models[] =
{ &cpu_ids[CPU_DOTHAN_A1], NULL, 0, NULL },
{ &cpu_ids[CPU_DOTHAN_A2], NULL, 0, NULL },
{ &cpu_ids[CPU_DOTHAN_B0], NULL, 0, NULL },
+ { &cpu_ids[CPU_MP4HT_D0], NULL, 0, NULL },
+ { &cpu_ids[CPU_MP4HT_E0], NULL, 0, NULL },
{ NULL, }
};
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
index 8ba430a9c3a..d368b3f5fce 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c
@@ -336,7 +336,7 @@ unsigned int speedstep_get_freqs(unsigned int processor,
if (!prev_speed)
return -EIO;
- dprintk("previous seped is %u\n", prev_speed);
+ dprintk("previous speed is %u\n", prev_speed);
local_irq_save(flags);
@@ -348,7 +348,7 @@ unsigned int speedstep_get_freqs(unsigned int processor,
goto out;
}
- dprintk("low seped is %u\n", *low_speed);
+ dprintk("low speed is %u\n", *low_speed);
/* switch to high state */
set_state(SPEEDSTEP_HIGH);
@@ -358,7 +358,7 @@ unsigned int speedstep_get_freqs(unsigned int processor,
goto out;
}
- dprintk("high seped is %u\n", *high_speed);
+ dprintk("high speed is %u\n", *high_speed);
if (*low_speed == *high_speed) {
ret = -ENODEV;
diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
index 79440b3f087..b25fb6b635a 100644
--- a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
+++ b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c
@@ -357,6 +357,9 @@ static int __init speedstep_init(void)
case SPEEDSTEP_PROCESSOR_PIII_C:
case SPEEDSTEP_PROCESSOR_PIII_C_EARLY:
break;
+ case SPEEDSTEP_PROCESSOR_P4M:
+ printk(KERN_INFO "speedstep-smi: you're trying to use this cpufreq driver on a Pentium 4-based CPU. Most likely it will not work.\n");
+ break;
default:
speedstep_processor = 0;
}
diff --git a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c
index 121aa2176e6..96a75d04583 100644
--- a/arch/i386/kernel/cpu/intel.c
+++ b/arch/i386/kernel/cpu/intel.c
@@ -28,7 +28,7 @@ extern int trap_init_f00f_bug(void);
struct movsl_mask movsl_mask;
#endif
-void __init early_intel_workaround(struct cpuinfo_x86 *c)
+void __devinit early_intel_workaround(struct cpuinfo_x86 *c)
{
if (c->x86_vendor != X86_VENDOR_INTEL)
return;
@@ -43,7 +43,7 @@ void __init early_intel_workaround(struct cpuinfo_x86 *c)
* This is called before we do cpu ident work
*/
-int __init ppro_with_ram_bug(void)
+int __devinit ppro_with_ram_bug(void)
{
/* Uses data from early_cpu_detect now */
if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
@@ -61,7 +61,7 @@ int __init ppro_with_ram_bug(void)
* P4 Xeon errata 037 workaround.
* Hardware prefetcher may cause stale data to be loaded into the cache.
*/
-static void __init Intel_errata_workarounds(struct cpuinfo_x86 *c)
+static void __devinit Intel_errata_workarounds(struct cpuinfo_x86 *c)
{
unsigned long lo, hi;
@@ -80,7 +80,7 @@ static void __init Intel_errata_workarounds(struct cpuinfo_x86 *c)
/*
* find out the number of processor cores on the die
*/
-static int __init num_cpu_cores(struct cpuinfo_x86 *c)
+static int __devinit num_cpu_cores(struct cpuinfo_x86 *c)
{
unsigned int eax;
@@ -98,7 +98,7 @@ static int __init num_cpu_cores(struct cpuinfo_x86 *c)
return 1;
}
-static void __init init_intel(struct cpuinfo_x86 *c)
+static void __devinit init_intel(struct cpuinfo_x86 *c)
{
unsigned int l2 = 0;
char *p = NULL;
@@ -204,7 +204,7 @@ static unsigned int intel_size_cache(struct cpuinfo_x86 * c, unsigned int size)
return size;
}
-static struct cpu_dev intel_cpu_dev __initdata = {
+static struct cpu_dev intel_cpu_dev __devinitdata = {
.c_vendor = "Intel",
.c_ident = { "GenuineIntel" },
.c_models = {
diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c
index aeb5b4ef8c8..1d768b26326 100644
--- a/arch/i386/kernel/cpu/intel_cacheinfo.c
+++ b/arch/i386/kernel/cpu/intel_cacheinfo.c
@@ -28,7 +28,7 @@ struct _cache_table
};
/* all the cache descriptor types we care about (no TLB or trace cache entries) */
-static struct _cache_table cache_table[] __initdata =
+static struct _cache_table cache_table[] __devinitdata =
{
{ 0x06, LVL_1_INST, 8 }, /* 4-way set assoc, 32 byte line size */
{ 0x08, LVL_1_INST, 16 }, /* 4-way set assoc, 32 byte line size */
@@ -118,7 +118,7 @@ struct _cpuid4_info {
};
#define MAX_CACHE_LEAVES 4
-static unsigned short __devinitdata num_cache_leaves;
+static unsigned short num_cache_leaves;
static int __devinit cpuid4_cache_lookup(int index, struct _cpuid4_info *this_leaf)
{
@@ -160,7 +160,7 @@ static int __init find_num_cache_leaves(void)
return retval;
}
-unsigned int __init init_intel_cacheinfo(struct cpuinfo_x86 *c)
+unsigned int __devinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
{
unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */
unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */
diff --git a/arch/i386/kernel/cpu/mcheck/k7.c b/arch/i386/kernel/cpu/mcheck/k7.c
index 8df52e86c4d..c4abe765739 100644
--- a/arch/i386/kernel/cpu/mcheck/k7.c
+++ b/arch/i386/kernel/cpu/mcheck/k7.c
@@ -69,7 +69,7 @@ static fastcall void k7_machine_check(struct pt_regs * regs, long error_code)
/* AMD K7 machine check is Intel like */
-void __init amd_mcheck_init(struct cpuinfo_x86 *c)
+void __devinit amd_mcheck_init(struct cpuinfo_x86 *c)
{
u32 l, h;
int i;
diff --git a/arch/i386/kernel/cpu/mcheck/mce.c b/arch/i386/kernel/cpu/mcheck/mce.c
index bf6d1aefafc..2cf25d2ba0f 100644
--- a/arch/i386/kernel/cpu/mcheck/mce.c
+++ b/arch/i386/kernel/cpu/mcheck/mce.c
@@ -16,7 +16,7 @@
#include "mce.h"
-int mce_disabled __initdata = 0;
+int mce_disabled __devinitdata = 0;
int nr_mce_banks;
EXPORT_SYMBOL_GPL(nr_mce_banks); /* non-fatal.o */
@@ -31,7 +31,7 @@ static fastcall void unexpected_machine_check(struct pt_regs * regs, long error_
void fastcall (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check;
/* This has to be run for each processor */
-void __init mcheck_init(struct cpuinfo_x86 *c)
+void __devinit mcheck_init(struct cpuinfo_x86 *c)
{
if (mce_disabled==1)
return;
diff --git a/arch/i386/kernel/cpu/mcheck/p4.c b/arch/i386/kernel/cpu/mcheck/p4.c
index 8b16ceb929b..0abccb6fdf9 100644
--- a/arch/i386/kernel/cpu/mcheck/p4.c
+++ b/arch/i386/kernel/cpu/mcheck/p4.c
@@ -78,7 +78,7 @@ fastcall void smp_thermal_interrupt(struct pt_regs *regs)
}
/* P4/Xeon Thermal regulation detect and init */
-static void __init intel_init_thermal(struct cpuinfo_x86 *c)
+static void __devinit intel_init_thermal(struct cpuinfo_x86 *c)
{
u32 l, h;
unsigned int cpu = smp_processor_id();
@@ -232,7 +232,7 @@ static fastcall void intel_machine_check(struct pt_regs * regs, long error_code)
}
-void __init intel_p4_mcheck_init(struct cpuinfo_x86 *c)
+void __devinit intel_p4_mcheck_init(struct cpuinfo_x86 *c)
{
u32 l, h;
int i;
diff --git a/arch/i386/kernel/cpu/mcheck/p5.c b/arch/i386/kernel/cpu/mcheck/p5.c
index c45a1b485c8..ec0614cd292 100644
--- a/arch/i386/kernel/cpu/mcheck/p5.c
+++ b/arch/i386/kernel/cpu/mcheck/p5.c
@@ -29,7 +29,7 @@ static fastcall void pentium_machine_check(struct pt_regs * regs, long error_cod
}
/* Set up machine check reporting for processors with Intel style MCE */
-void __init intel_p5_mcheck_init(struct cpuinfo_x86 *c)
+void __devinit intel_p5_mcheck_init(struct cpuinfo_x86 *c)
{
u32 l, h;
diff --git a/arch/i386/kernel/cpu/mcheck/p6.c b/arch/i386/kernel/cpu/mcheck/p6.c
index 46640f8c249..f01b73f947e 100644
--- a/arch/i386/kernel/cpu/mcheck/p6.c
+++ b/arch/i386/kernel/cpu/mcheck/p6.c
@@ -80,7 +80,7 @@ static fastcall void intel_machine_check(struct pt_regs * regs, long error_code)
}
/* Set up machine check reporting for processors with Intel style MCE */
-void __init intel_p6_mcheck_init(struct cpuinfo_x86 *c)
+void __devinit intel_p6_mcheck_init(struct cpuinfo_x86 *c)
{
u32 l, h;
int i;
diff --git a/arch/i386/kernel/cpu/mcheck/winchip.c b/arch/i386/kernel/cpu/mcheck/winchip.c
index 753fa7acb98..7bae68fa168 100644
--- a/arch/i386/kernel/cpu/mcheck/winchip.c
+++ b/arch/i386/kernel/cpu/mcheck/winchip.c
@@ -23,7 +23,7 @@ static fastcall void winchip_machine_check(struct pt_regs * regs, long error_cod
}
/* Set up machine check reporting on the Winchip C6 series */
-void __init winchip_mcheck_init(struct cpuinfo_x86 *c)
+void __devinit winchip_mcheck_init(struct cpuinfo_x86 *c)
{
u32 lo, hi;
machine_check_vector = winchip_machine_check;
diff --git a/arch/i386/kernel/cpu/mtrr/generic.c b/arch/i386/kernel/cpu/mtrr/generic.c
index f468a979e9a..64d91f73a0a 100644
--- a/arch/i386/kernel/cpu/mtrr/generic.c
+++ b/arch/i386/kernel/cpu/mtrr/generic.c
@@ -70,8 +70,7 @@ void __init get_mtrr_state(void)
/* Free resources associated with a struct mtrr_state */
void __init finalize_mtrr_state(void)
{
- if (mtrr_state.var_ranges)
- kfree(mtrr_state.var_ranges);
+ kfree(mtrr_state.var_ranges);
mtrr_state.var_ranges = NULL;
}
diff --git a/arch/i386/kernel/cpu/mtrr/main.c b/arch/i386/kernel/cpu/mtrr/main.c
index e1c2042b9b7..d66b09e0c82 100644
--- a/arch/i386/kernel/cpu/mtrr/main.c
+++ b/arch/i386/kernel/cpu/mtrr/main.c
@@ -375,6 +375,19 @@ int mtrr_add_page(unsigned long base, unsigned long size,
return error;
}
+static int mtrr_check(unsigned long base, unsigned long size)
+{
+ if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
+ printk(KERN_WARNING
+ "mtrr: size and base must be multiples of 4 kiB\n");
+ printk(KERN_DEBUG
+ "mtrr: size: 0x%lx base: 0x%lx\n", size, base);
+ dump_stack();
+ return -1;
+ }
+ return 0;
+}
+
/**
* mtrr_add - Add a memory type region
* @base: Physical base address of region
@@ -415,11 +428,8 @@ int
mtrr_add(unsigned long base, unsigned long size, unsigned int type,
char increment)
{
- if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
- printk(KERN_WARNING "mtrr: size and base must be multiples of 4 kiB\n");
- printk(KERN_DEBUG "mtrr: size: 0x%lx base: 0x%lx\n", size, base);
+ if (mtrr_check(base, size))
return -EINVAL;
- }
return mtrr_add_page(base >> PAGE_SHIFT, size >> PAGE_SHIFT, type,
increment);
}
@@ -511,11 +521,8 @@ int mtrr_del_page(int reg, unsigned long base, unsigned long size)
int
mtrr_del(int reg, unsigned long base, unsigned long size)
{
- if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
- printk(KERN_INFO "mtrr: size and base must be multiples of 4 kiB\n");
- printk(KERN_DEBUG "mtrr: size: 0x%lx base: 0x%lx\n", size, base);
+ if (mtrr_check(base, size))
return -EINVAL;
- }
return mtrr_del_page(reg, base >> PAGE_SHIFT, size >> PAGE_SHIFT);
}
diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c
index 7323c19f354..8bd77d948a8 100644
--- a/arch/i386/kernel/cpu/proc.c
+++ b/arch/i386/kernel/cpu/proc.c
@@ -86,7 +86,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "stepping\t: unknown\n");
if ( cpu_has(c, X86_FEATURE_TSC) ) {
- seq_printf(m, "cpu MHz\t\t: %lu.%03lu\n",
+ seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
cpu_khz / 1000, (cpu_khz % 1000));
}
diff --git a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c
index 2e2756345bb..4647db4ad6d 100644
--- a/arch/i386/kernel/cpuid.c
+++ b/arch/i386/kernel/cpuid.c
@@ -45,7 +45,7 @@
#include <asm/uaccess.h>
#include <asm/system.h>
-static struct class_simple *cpuid_class;
+static struct class *cpuid_class;
#ifdef CONFIG_SMP
@@ -158,12 +158,12 @@ static struct file_operations cpuid_fops = {
.open = cpuid_open,
};
-static int cpuid_class_simple_device_add(int i)
+static int cpuid_class_device_create(int i)
{
int err = 0;
struct class_device *class_err;
- class_err = class_simple_device_add(cpuid_class, MKDEV(CPUID_MAJOR, i), NULL, "cpu%d",i);
+ class_err = class_device_create(cpuid_class, MKDEV(CPUID_MAJOR, i), NULL, "cpu%d",i);
if (IS_ERR(class_err))
err = PTR_ERR(class_err);
return err;
@@ -175,10 +175,10 @@ static int __devinit cpuid_class_cpu_callback(struct notifier_block *nfb, unsign
switch (action) {
case CPU_ONLINE:
- cpuid_class_simple_device_add(cpu);
+ cpuid_class_device_create(cpu);
break;
case CPU_DEAD:
- class_simple_device_remove(MKDEV(CPUID_MAJOR, cpu));
+ class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
break;
}
return NOTIFY_OK;
@@ -200,13 +200,13 @@ static int __init cpuid_init(void)
err = -EBUSY;
goto out;
}
- cpuid_class = class_simple_create(THIS_MODULE, "cpuid");
+ cpuid_class = class_create(THIS_MODULE, "cpuid");
if (IS_ERR(cpuid_class)) {
err = PTR_ERR(cpuid_class);
goto out_chrdev;
}
for_each_online_cpu(i) {
- err = cpuid_class_simple_device_add(i);
+ err = cpuid_class_device_create(i);
if (err != 0)
goto out_class;
}
@@ -218,9 +218,9 @@ static int __init cpuid_init(void)
out_class:
i = 0;
for_each_online_cpu(i) {
- class_simple_device_remove(MKDEV(CPUID_MAJOR, i));
+ class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, i));
}
- class_simple_destroy(cpuid_class);
+ class_destroy(cpuid_class);
out_chrdev:
unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");
out:
@@ -232,8 +232,8 @@ static void __exit cpuid_exit(void)
int cpu = 0;
for_each_online_cpu(cpu)
- class_simple_device_remove(MKDEV(CPUID_MAJOR, cpu));
- class_simple_destroy(cpuid_class);
+ class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
+ class_destroy(cpuid_class);
unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");
unregister_cpu_notifier(&cpuid_class_cpu_notifier);
}
diff --git a/arch/i386/kernel/crash.c b/arch/i386/kernel/crash.c
new file mode 100644
index 00000000000..e5fab12f792
--- /dev/null
+++ b/arch/i386/kernel/crash.c
@@ -0,0 +1,223 @@
+/*
+ * Architecture specific (i386) functions for kexec based crash dumps.
+ *
+ * Created by: Hariprasad Nellitheertha (hari@in.ibm.com)
+ *
+ * Copyright (C) IBM Corporation, 2004. All rights reserved.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/irq.h>
+#include <linux/reboot.h>
+#include <linux/kexec.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/elf.h>
+#include <linux/elfcore.h>
+
+#include <asm/processor.h>
+#include <asm/hardirq.h>
+#include <asm/nmi.h>
+#include <asm/hw_irq.h>
+#include <asm/apic.h>
+#include <mach_ipi.h>
+
+
+note_buf_t crash_notes[NR_CPUS];
+/* This keeps a track of which one is crashing cpu. */
+static int crashing_cpu;
+
+static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data,
+ size_t data_len)
+{
+ struct elf_note note;
+
+ note.n_namesz = strlen(name) + 1;
+ note.n_descsz = data_len;
+ note.n_type = type;
+ memcpy(buf, &note, sizeof(note));
+ buf += (sizeof(note) +3)/4;
+ memcpy(buf, name, note.n_namesz);
+ buf += (note.n_namesz + 3)/4;
+ memcpy(buf, data, note.n_descsz);
+ buf += (note.n_descsz + 3)/4;
+
+ return buf;
+}
+
+static void final_note(u32 *buf)
+{
+ struct elf_note note;
+
+ note.n_namesz = 0;
+ note.n_descsz = 0;
+ note.n_type = 0;
+ memcpy(buf, &note, sizeof(note));
+}
+
+static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
+{
+ struct elf_prstatus prstatus;
+ u32 *buf;
+
+ if ((cpu < 0) || (cpu >= NR_CPUS))
+ return;
+
+ /* Using ELF notes here is opportunistic.
+ * I need a well defined structure format
+ * for the data I pass, and I need tags
+ * on the data to indicate what information I have
+ * squirrelled away. ELF notes happen to provide
+ * all of that that no need to invent something new.
+ */
+ buf = &crash_notes[cpu][0];
+ memset(&prstatus, 0, sizeof(prstatus));
+ prstatus.pr_pid = current->pid;
+ elf_core_copy_regs(&prstatus.pr_reg, regs);
+ buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus,
+ sizeof(prstatus));
+ final_note(buf);
+}
+
+static void crash_get_current_regs(struct pt_regs *regs)
+{
+ __asm__ __volatile__("movl %%ebx,%0" : "=m"(regs->ebx));
+ __asm__ __volatile__("movl %%ecx,%0" : "=m"(regs->ecx));
+ __asm__ __volatile__("movl %%edx,%0" : "=m"(regs->edx));
+ __asm__ __volatile__("movl %%esi,%0" : "=m"(regs->esi));
+ __asm__ __volatile__("movl %%edi,%0" : "=m"(regs->edi));
+ __asm__ __volatile__("movl %%ebp,%0" : "=m"(regs->ebp));
+ __asm__ __volatile__("movl %%eax,%0" : "=m"(regs->eax));
+ __asm__ __volatile__("movl %%esp,%0" : "=m"(regs->esp));
+ __asm__ __volatile__("movw %%ss, %%ax;" :"=a"(regs->xss));
+ __asm__ __volatile__("movw %%cs, %%ax;" :"=a"(regs->xcs));
+ __asm__ __volatile__("movw %%ds, %%ax;" :"=a"(regs->xds));
+ __asm__ __volatile__("movw %%es, %%ax;" :"=a"(regs->xes));
+ __asm__ __volatile__("pushfl; popl %0" :"=m"(regs->eflags));
+
+ regs->eip = (unsigned long)current_text_addr();
+}
+
+/* CPU does not save ss and esp on stack if execution is already
+ * running in kernel mode at the time of NMI occurrence. This code
+ * fixes it.
+ */
+static void crash_setup_regs(struct pt_regs *newregs, struct pt_regs *oldregs)
+{
+ memcpy(newregs, oldregs, sizeof(*newregs));
+ newregs->esp = (unsigned long)&(oldregs->esp);
+ __asm__ __volatile__("xorl %eax, %eax;");
+ __asm__ __volatile__ ("movw %%ss, %%ax;" :"=a"(newregs->xss));
+}
+
+/* We may have saved_regs from where the error came from
+ * or it is NULL if via a direct panic().
+ */
+static void crash_save_self(struct pt_regs *saved_regs)
+{
+ struct pt_regs regs;
+ int cpu;
+
+ cpu = smp_processor_id();
+ if (saved_regs)
+ crash_setup_regs(&regs, saved_regs);
+ else
+ crash_get_current_regs(&regs);
+ crash_save_this_cpu(&regs, cpu);
+}
+
+#ifdef CONFIG_SMP
+static atomic_t waiting_for_crash_ipi;
+
+static int crash_nmi_callback(struct pt_regs *regs, int cpu)
+{
+ struct pt_regs fixed_regs;
+
+ /* Don't do anything if this handler is invoked on crashing cpu.
+ * Otherwise, system will completely hang. Crashing cpu can get
+ * an NMI if system was initially booted with nmi_watchdog parameter.
+ */
+ if (cpu == crashing_cpu)
+ return 1;
+ local_irq_disable();
+
+ if (!user_mode(regs)) {
+ crash_setup_regs(&fixed_regs, regs);
+ regs = &fixed_regs;
+ }
+ crash_save_this_cpu(regs, cpu);
+ disable_local_APIC();
+ atomic_dec(&waiting_for_crash_ipi);
+ /* Assume hlt works */
+ __asm__("hlt");
+ for(;;);
+
+ return 1;
+}
+
+/*
+ * By using the NMI code instead of a vector we just sneak thru the
+ * word generator coming out with just what we want. AND it does
+ * not matter if clustered_apic_mode is set or not.
+ */
+static void smp_send_nmi_allbutself(void)
+{
+ send_IPI_allbutself(APIC_DM_NMI);
+}
+
+static void nmi_shootdown_cpus(void)
+{
+ unsigned long msecs;
+
+ atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
+ /* Would it be better to replace the trap vector here? */
+ set_nmi_callback(crash_nmi_callback);
+ /* Ensure the new callback function is set before sending
+ * out the NMI
+ */
+ wmb();
+
+ smp_send_nmi_allbutself();
+
+ msecs = 1000; /* Wait at most a second for the other cpus to stop */
+ while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
+ mdelay(1);
+ msecs--;
+ }
+
+ /* Leave the nmi callback set */
+ disable_local_APIC();
+}
+#else
+static void nmi_shootdown_cpus(void)
+{
+ /* There are no cpus to shootdown */
+}
+#endif
+
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+ /* This function is only called after the system
+ * has paniced or is otherwise in a critical state.
+ * The minimum amount of code to allow a kexec'd kernel
+ * to run successfully needs to happen here.
+ *
+ * In practice this means shooting down the other cpus in
+ * an SMP system.
+ */
+ /* The kernel is broken so disable interrupts */
+ local_irq_disable();
+
+ /* Make a note of crashing cpu. Will be used in NMI callback.*/
+ crashing_cpu = smp_processor_id();
+ nmi_shootdown_cpus();
+ lapic_shutdown();
+#if defined(CONFIG_X86_IO_APIC)
+ disable_IO_APIC();
+#endif
+ crash_save_self(regs);
+}
diff --git a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c
index 6ed7e28f306..a3cdf894302 100644
--- a/arch/i386/kernel/dmi_scan.c
+++ b/arch/i386/kernel/dmi_scan.c
@@ -1,22 +1,15 @@
#include <linux/types.h>
-#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/acpi.h>
-#include <asm/io.h>
-#include <linux/pm.h>
-#include <asm/system.h>
#include <linux/dmi.h>
#include <linux/bootmem.h>
-struct dmi_header
-{
- u8 type;
- u8 length;
- u16 handle;
+struct dmi_header {
+ u8 type;
+ u8 length;
+ u16 handle;
};
#undef DMI_DEBUG
@@ -29,15 +22,13 @@ struct dmi_header
static char * __init dmi_string(struct dmi_header *dm, u8 s)
{
- u8 *bp=(u8 *)dm;
- bp+=dm->length;
- if(!s)
+ u8 *bp = ((u8 *) dm) + dm->length;
+
+ if (!s)
return "";
s--;
- while(s>0 && *bp)
- {
- bp+=strlen(bp);
- bp++;
+ while (s > 0 && *bp) {
+ bp += strlen(bp) + 1;
s--;
}
return bp;
@@ -47,16 +38,14 @@ static char * __init dmi_string(struct dmi_header *dm, u8 s)
* We have to be cautious here. We have seen BIOSes with DMI pointers
* pointing to completely the wrong place for example
*/
-
-static int __init dmi_table(u32 base, int len, int num, void (*decode)(struct dmi_header *))
+static int __init dmi_table(u32 base, int len, int num,
+ void (*decode)(struct dmi_header *))
{
- u8 *buf;
- struct dmi_header *dm;
- u8 *data;
- int i=0;
+ u8 *buf, *data;
+ int i = 0;
buf = bt_ioremap(base, len);
- if(buf==NULL)
+ if (buf == NULL)
return -1;
data = buf;
@@ -65,36 +54,34 @@ static int __init dmi_table(u32 base, int len, int num, void (*decode)(struct dm
* Stop when we see all the items the table claimed to have
* OR we run off the end of the table (also happens)
*/
-
- while(i<num && data-buf+sizeof(struct dmi_header)<=len)
- {
- dm=(struct dmi_header *)data;
+ while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) {
+ struct dmi_header *dm = (struct dmi_header *)data;
/*
* We want to know the total length (formated area and strings)
* before decoding to make sure we won't run off the table in
* dmi_decode or dmi_string
*/
- data+=dm->length;
- while(data-buf<len-1 && (data[0] || data[1]))
+ data += dm->length;
+ while ((data - buf < len - 1) && (data[0] || data[1]))
data++;
- if(data-buf<len-1)
+ if (data - buf < len - 1)
decode(dm);
- data+=2;
+ data += 2;
i++;
}
bt_iounmap(buf, len);
return 0;
}
-
-inline static int __init dmi_checksum(u8 *buf)
+static int __init dmi_checksum(u8 *buf)
{
- u8 sum=0;
+ u8 sum = 0;
int a;
- for(a=0; a<15; a++)
- sum+=buf[a];
- return (sum==0);
+ for (a = 0; a < 15; a++)
+ sum += buf[a];
+
+ return sum == 0;
}
static int __init dmi_iterate(void (*decode)(struct dmi_header *))
@@ -110,28 +97,30 @@ static int __init dmi_iterate(void (*decode)(struct dmi_header *))
p = ioremap(0xF0000, 0x10000);
if (p == NULL)
return -1;
+
for (q = p; q < p + 0x10000; q += 16) {
memcpy_fromio(buf, q, 15);
- if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf))
- {
- u16 num=buf[13]<<8|buf[12];
- u16 len=buf[7]<<8|buf[6];
- u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
+ if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) {
+ u16 num = (buf[13] << 8) | buf[12];
+ u16 len = (buf[7] << 8) | buf[6];
+ u32 base = (buf[11] << 24) | (buf[10] << 16) |
+ (buf[9] << 8) | buf[8];
/*
* DMI version 0.0 means that the real version is taken from
* the SMBIOS version, which we don't know at this point.
*/
- if(buf[14]!=0)
+ if (buf[14] != 0)
printk(KERN_INFO "DMI %d.%d present.\n",
- buf[14]>>4, buf[14]&0x0F);
+ buf[14] >> 4, buf[14] & 0xF);
else
printk(KERN_INFO "DMI present.\n");
+
dmi_printk((KERN_INFO "%d structures occupying %d bytes.\n",
num, len));
- dmi_printk((KERN_INFO "DMI table at 0x%08X.\n",
- base));
- if(dmi_table(base,len, num, decode)==0)
+ dmi_printk((KERN_INFO "DMI table at 0x%08X.\n", base));
+
+ if (dmi_table(base,len, num, decode) == 0)
return 0;
}
}
@@ -143,16 +132,17 @@ static char *dmi_ident[DMI_STRING_MAX];
/*
* Save a DMI string
*/
-
static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
{
char *d = (char*)dm;
char *p = dmi_string(dm, d[string]);
- if(p==NULL || *p == 0)
+
+ if (p == NULL || *p == 0)
return;
if (dmi_ident[slot])
return;
- dmi_ident[slot] = alloc_bootmem(strlen(p)+1);
+
+ dmi_ident[slot] = alloc_bootmem(strlen(p) + 1);
if(dmi_ident[slot])
strcpy(dmi_ident[slot], p);
else
@@ -160,281 +150,47 @@ static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
}
/*
- * Ugly compatibility crap.
- */
-#define dmi_blacklist dmi_system_id
-#define NO_MATCH { DMI_NONE, NULL}
-#define MATCH DMI_MATCH
-
-/*
- * Toshiba keyboard likes to repeat keys when they are not repeated.
- */
-
-static __init int broken_toshiba_keyboard(struct dmi_blacklist *d)
-{
- printk(KERN_WARNING "Toshiba with broken keyboard detected. If your keyboard sometimes generates 3 keypresses instead of one, see http://davyd.ucc.asn.au/projects/toshiba/README\n");
- return 0;
-}
-
-
-#ifdef CONFIG_ACPI_SLEEP
-static __init int reset_videomode_after_s3(struct dmi_blacklist *d)
-{
- /* See acpi_wakeup.S */
- extern long acpi_video_flags;
- acpi_video_flags |= 2;
- return 0;
-}
-#endif
-
-
-#ifdef CONFIG_ACPI_BOOT
-extern int acpi_force;
-
-static __init __attribute__((unused)) int dmi_disable_acpi(struct dmi_blacklist *d)
-{
- if (!acpi_force) {
- printk(KERN_NOTICE "%s detected: acpi off\n",d->ident);
- disable_acpi();
- } else {
- printk(KERN_NOTICE
- "Warning: DMI blacklist says broken, but acpi forced\n");
- }
- return 0;
-}
-
-/*
- * Limit ACPI to CPU enumeration for HT
- */
-static __init __attribute__((unused)) int force_acpi_ht(struct dmi_blacklist *d)
-{
- if (!acpi_force) {
- printk(KERN_NOTICE "%s detected: force use of acpi=ht\n", d->ident);
- disable_acpi();
- acpi_ht = 1;
- } else {
- printk(KERN_NOTICE
- "Warning: acpi=force overrules DMI blacklist: acpi=ht\n");
- }
- return 0;
-}
-#endif
-
-#ifdef CONFIG_ACPI_PCI
-static __init int disable_acpi_irq(struct dmi_blacklist *d)
-{
- if (!acpi_force) {
- printk(KERN_NOTICE "%s detected: force use of acpi=noirq\n",
- d->ident);
- acpi_noirq_set();
- }
- return 0;
-}
-static __init int disable_acpi_pci(struct dmi_blacklist *d)
-{
- if (!acpi_force) {
- printk(KERN_NOTICE "%s detected: force use of pci=noacpi\n",
- d->ident);
- acpi_disable_pci();
- }
- return 0;
-}
-#endif
-
-/*
- * Process the DMI blacklists
- */
-
-
-/*
- * This will be expanded over time to force things like the APM
- * interrupt mask settings according to the laptop
- */
-
-static __initdata struct dmi_blacklist dmi_blacklist[]={
-
- { broken_toshiba_keyboard, "Toshiba Satellite 4030cdt", { /* Keyboard generates spurious repeats */
- MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
- NO_MATCH, NO_MATCH, NO_MATCH
- } },
-#ifdef CONFIG_ACPI_SLEEP
- { reset_videomode_after_s3, "Toshiba Satellite 4030cdt", { /* Reset video mode after returning from ACPI S3 sleep */
- MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
- NO_MATCH, NO_MATCH, NO_MATCH
- } },
-#endif
-
-#ifdef CONFIG_ACPI_BOOT
- /*
- * If your system is blacklisted here, but you find that acpi=force
- * works for you, please contact acpi-devel@sourceforge.net
- */
-
- /*
- * Boxes that need ACPI disabled
- */
-
- { dmi_disable_acpi, "IBM Thinkpad", {
- MATCH(DMI_BOARD_VENDOR, "IBM"),
- MATCH(DMI_BOARD_NAME, "2629H1G"),
- NO_MATCH, NO_MATCH }},
-
- /*
- * Boxes that need acpi=ht
- */
-
- { force_acpi_ht, "FSC Primergy T850", {
- MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
- MATCH(DMI_PRODUCT_NAME, "PRIMERGY T850"),
- NO_MATCH, NO_MATCH }},
-
- { force_acpi_ht, "DELL GX240", {
- MATCH(DMI_BOARD_VENDOR, "Dell Computer Corporation"),
- MATCH(DMI_BOARD_NAME, "OptiPlex GX240"),
- NO_MATCH, NO_MATCH }},
-
- { force_acpi_ht, "HP VISUALIZE NT Workstation", {
- MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
- MATCH(DMI_PRODUCT_NAME, "HP VISUALIZE NT Workstation"),
- NO_MATCH, NO_MATCH }},
-
- { force_acpi_ht, "Compaq Workstation W8000", {
- MATCH(DMI_SYS_VENDOR, "Compaq"),
- MATCH(DMI_PRODUCT_NAME, "Workstation W8000"),
- NO_MATCH, NO_MATCH }},
-
- { force_acpi_ht, "ASUS P4B266", {
- MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
- MATCH(DMI_BOARD_NAME, "P4B266"),
- NO_MATCH, NO_MATCH }},
-
- { force_acpi_ht, "ASUS P2B-DS", {
- MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
- MATCH(DMI_BOARD_NAME, "P2B-DS"),
- NO_MATCH, NO_MATCH }},
-
- { force_acpi_ht, "ASUS CUR-DLS", {
- MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
- MATCH(DMI_BOARD_NAME, "CUR-DLS"),
- NO_MATCH, NO_MATCH }},
-
- { force_acpi_ht, "ABIT i440BX-W83977", {
- MATCH(DMI_BOARD_VENDOR, "ABIT <http://www.abit.com>"),
- MATCH(DMI_BOARD_NAME, "i440BX-W83977 (BP6)"),
- NO_MATCH, NO_MATCH }},
-
- { force_acpi_ht, "IBM Bladecenter", {
- MATCH(DMI_BOARD_VENDOR, "IBM"),
- MATCH(DMI_BOARD_NAME, "IBM eServer BladeCenter HS20"),
- NO_MATCH, NO_MATCH }},
-
- { force_acpi_ht, "IBM eServer xSeries 360", {
- MATCH(DMI_BOARD_VENDOR, "IBM"),
- MATCH(DMI_BOARD_NAME, "eServer xSeries 360"),
- NO_MATCH, NO_MATCH }},
-
- { force_acpi_ht, "IBM eserver xSeries 330", {
- MATCH(DMI_BOARD_VENDOR, "IBM"),
- MATCH(DMI_BOARD_NAME, "eserver xSeries 330"),
- NO_MATCH, NO_MATCH }},
-
- { force_acpi_ht, "IBM eserver xSeries 440", {
- MATCH(DMI_BOARD_VENDOR, "IBM"),
- MATCH(DMI_PRODUCT_NAME, "eserver xSeries 440"),
- NO_MATCH, NO_MATCH }},
-
-#endif // CONFIG_ACPI_BOOT
-
-#ifdef CONFIG_ACPI_PCI
- /*
- * Boxes that need ACPI PCI IRQ routing disabled
- */
-
- { disable_acpi_irq, "ASUS A7V", {
- MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC"),
- MATCH(DMI_BOARD_NAME, "<A7V>"),
- /* newer BIOS, Revision 1011, does work */
- MATCH(DMI_BIOS_VERSION, "ASUS A7V ACPI BIOS Revision 1007"),
- NO_MATCH }},
-
- /*
- * Boxes that need ACPI PCI IRQ routing and PCI scan disabled
- */
- { disable_acpi_pci, "ASUS PR-DLS", { /* _BBN 0 bug */
- MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
- MATCH(DMI_BOARD_NAME, "PR-DLS"),
- MATCH(DMI_BIOS_VERSION, "ASUS PR-DLS ACPI BIOS Revision 1010"),
- MATCH(DMI_BIOS_DATE, "03/21/2003") }},
-
- { disable_acpi_pci, "Acer TravelMate 36x Laptop", {
- MATCH(DMI_SYS_VENDOR, "Acer"),
- MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
- NO_MATCH, NO_MATCH
- } },
-
-#endif
-
- { NULL, }
-};
-
-/*
* Process a DMI table entry. Right now all we care about are the BIOS
* and machine entries. For 2.5 we should pull the smbus controller info
* out of here.
*/
-
static void __init dmi_decode(struct dmi_header *dm)
{
-#ifdef DMI_DEBUG
- u8 *data = (u8 *)dm;
-#endif
+ u8 *data __attribute__((__unused__)) = (u8 *)dm;
- switch(dm->type)
- {
- case 0:
- dmi_printk(("BIOS Vendor: %s\n",
- dmi_string(dm, data[4])));
- dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
- dmi_printk(("BIOS Version: %s\n",
- dmi_string(dm, data[5])));
- dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
- dmi_printk(("BIOS Release: %s\n",
- dmi_string(dm, data[8])));
- dmi_save_ident(dm, DMI_BIOS_DATE, 8);
- break;
- case 1:
- dmi_printk(("System Vendor: %s\n",
- dmi_string(dm, data[4])));
- dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
- dmi_printk(("Product Name: %s\n",
- dmi_string(dm, data[5])));
- dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
- dmi_printk(("Version: %s\n",
- dmi_string(dm, data[6])));
- dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
- dmi_printk(("Serial Number: %s\n",
- dmi_string(dm, data[7])));
- break;
- case 2:
- dmi_printk(("Board Vendor: %s\n",
- dmi_string(dm, data[4])));
- dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
- dmi_printk(("Board Name: %s\n",
- dmi_string(dm, data[5])));
- dmi_save_ident(dm, DMI_BOARD_NAME, 5);
- dmi_printk(("Board Version: %s\n",
- dmi_string(dm, data[6])));
- dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
- break;
+ switch(dm->type) {
+ case 0:
+ dmi_printk(("BIOS Vendor: %s\n", dmi_string(dm, data[4])));
+ dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
+ dmi_printk(("BIOS Version: %s\n", dmi_string(dm, data[5])));
+ dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
+ dmi_printk(("BIOS Release: %s\n", dmi_string(dm, data[8])));
+ dmi_save_ident(dm, DMI_BIOS_DATE, 8);
+ break;
+ case 1:
+ dmi_printk(("System Vendor: %s\n", dmi_string(dm, data[4])));
+ dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
+ dmi_printk(("Product Name: %s\n", dmi_string(dm, data[5])));
+ dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
+ dmi_printk(("Version: %s\n", dmi_string(dm, data[6])));
+ dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
+ dmi_printk(("Serial Number: %s\n", dmi_string(dm, data[7])));
+ dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7);
+ break;
+ case 2:
+ dmi_printk(("Board Vendor: %s\n", dmi_string(dm, data[4])));
+ dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
+ dmi_printk(("Board Name: %s\n", dmi_string(dm, data[5])));
+ dmi_save_ident(dm, DMI_BOARD_NAME, 5);
+ dmi_printk(("Board Version: %s\n", dmi_string(dm, data[6])));
+ dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
+ break;
}
}
void __init dmi_scan_machine(void)
{
- int err = dmi_iterate(dmi_decode);
- if(err == 0)
- dmi_check_system(dmi_blacklist);
- else
+ if (dmi_iterate(dmi_decode))
printk(KERN_INFO "DMI not present.\n");
}
@@ -470,7 +226,6 @@ fail: d++;
return count;
}
-
EXPORT_SYMBOL(dmi_check_system);
/**
@@ -480,8 +235,8 @@ EXPORT_SYMBOL(dmi_check_system);
* Returns one DMI data value, can be used to perform
* complex DMI data checks.
*/
-char * dmi_get_system_info(int field)
+char *dmi_get_system_info(int field)
{
return dmi_ident[field];
}
-
+EXPORT_SYMBOL(dmi_get_system_info);
diff --git a/arch/i386/kernel/efi.c b/arch/i386/kernel/efi.c
index f732f427b41..385883ea8c1 100644
--- a/arch/i386/kernel/efi.c
+++ b/arch/i386/kernel/efi.c
@@ -30,6 +30,7 @@
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/efi.h>
+#include <linux/kexec.h>
#include <asm/setup.h>
#include <asm/io.h>
@@ -598,6 +599,9 @@ efi_initialize_iomem_resources(struct resource *code_resource,
if (md->type == EFI_CONVENTIONAL_MEMORY) {
request_resource(res, code_resource);
request_resource(res, data_resource);
+#ifdef CONFIG_KEXEC
+ request_resource(res, &crashk_res);
+#endif
}
}
}
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index e966fc8c44c..4477bb10709 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -299,7 +299,6 @@ is386: movl $2,%ecx # set MP
movl %eax,%cr0
call check_x87
- incb ready
lgdt cpu_gdt_descr
lidt idt_descr
ljmp $(__KERNEL_CS),$1f
@@ -316,8 +315,9 @@ is386: movl $2,%ecx # set MP
lldt %ax
cld # gcc2 wants the direction flag cleared at all times
#ifdef CONFIG_SMP
- movb ready, %cl
- cmpb $1,%cl
+ 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
diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
index 903190a4b3f..180f070d03c 100644
--- a/arch/i386/kernel/i386_ksyms.c
+++ b/arch/i386/kernel/i386_ksyms.c
@@ -1,97 +1,17 @@
#include <linux/config.h>
#include <linux/module.h>
-#include <linux/smp.h>
-#include <linux/user.h>
-#include <linux/elfcore.h>
-#include <linux/mca.h>
-#include <linux/sched.h>
-#include <linux/in6.h>
-#include <linux/interrupt.h>
-#include <linux/smp_lock.h>
-#include <linux/pm.h>
-#include <linux/pci.h>
-#include <linux/apm_bios.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/tty.h>
-#include <linux/highmem.h>
-#include <linux/time.h>
-
-#include <asm/semaphore.h>
-#include <asm/processor.h>
-#include <asm/i387.h>
-#include <asm/uaccess.h>
#include <asm/checksum.h>
-#include <asm/io.h>
-#include <asm/delay.h>
-#include <asm/irq.h>
-#include <asm/mmx.h>
#include <asm/desc.h>
-#include <asm/pgtable.h>
-#include <asm/tlbflush.h>
-#include <asm/nmi.h>
-#include <asm/ist.h>
-#include <asm/kdebug.h>
-
-extern void dump_thread(struct pt_regs *, struct user *);
-extern spinlock_t rtc_lock;
/* This is definitely a GPL-only symbol */
EXPORT_SYMBOL_GPL(cpu_gdt_table);
-#if defined(CONFIG_APM_MODULE)
-extern void machine_real_restart(unsigned char *, int);
-EXPORT_SYMBOL(machine_real_restart);
-extern void default_idle(void);
-EXPORT_SYMBOL(default_idle);
-#endif
-
-#ifdef CONFIG_SMP
-extern void FASTCALL( __write_lock_failed(rwlock_t *rw));
-extern void FASTCALL( __read_lock_failed(rwlock_t *rw));
-#endif
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE)
-extern struct drive_info_struct drive_info;
-EXPORT_SYMBOL(drive_info);
-#endif
-
-extern unsigned long cpu_khz;
-extern unsigned long get_cmos_time(void);
-
-/* platform dependent support */
-EXPORT_SYMBOL(boot_cpu_data);
-#ifdef CONFIG_DISCONTIGMEM
-EXPORT_SYMBOL(node_data);
-EXPORT_SYMBOL(physnode_map);
-#endif
-#ifdef CONFIG_X86_NUMAQ
-EXPORT_SYMBOL(xquad_portio);
-#endif
-EXPORT_SYMBOL(dump_thread);
-EXPORT_SYMBOL(dump_fpu);
-EXPORT_SYMBOL_GPL(kernel_fpu_begin);
-EXPORT_SYMBOL(__ioremap);
-EXPORT_SYMBOL(ioremap_nocache);
-EXPORT_SYMBOL(iounmap);
-EXPORT_SYMBOL(kernel_thread);
-EXPORT_SYMBOL(pm_idle);
-EXPORT_SYMBOL(pm_power_off);
-EXPORT_SYMBOL(get_cmos_time);
-EXPORT_SYMBOL(cpu_khz);
-EXPORT_SYMBOL(apm_info);
-
EXPORT_SYMBOL(__down_failed);
EXPORT_SYMBOL(__down_failed_interruptible);
EXPORT_SYMBOL(__down_failed_trylock);
EXPORT_SYMBOL(__up_wakeup);
/* Networking helper routines. */
EXPORT_SYMBOL(csum_partial_copy_generic);
-/* Delay loops */
-EXPORT_SYMBOL(__ndelay);
-EXPORT_SYMBOL(__udelay);
-EXPORT_SYMBOL(__delay);
-EXPORT_SYMBOL(__const_udelay);
EXPORT_SYMBOL(__get_user_1);
EXPORT_SYMBOL(__get_user_2);
@@ -105,87 +25,11 @@ EXPORT_SYMBOL(__put_user_8);
EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strncpy_from_user);
-EXPORT_SYMBOL(__strncpy_from_user);
-EXPORT_SYMBOL(clear_user);
-EXPORT_SYMBOL(__clear_user);
-EXPORT_SYMBOL(__copy_from_user_ll);
-EXPORT_SYMBOL(__copy_to_user_ll);
-EXPORT_SYMBOL(strnlen_user);
-
-EXPORT_SYMBOL(dma_alloc_coherent);
-EXPORT_SYMBOL(dma_free_coherent);
-
-#ifdef CONFIG_PCI
-EXPORT_SYMBOL(pci_mem_start);
-#endif
-
-#ifdef CONFIG_PCI_BIOS
-EXPORT_SYMBOL(pcibios_set_irq_routing);
-EXPORT_SYMBOL(pcibios_get_irq_routing_table);
-#endif
-
-#ifdef CONFIG_X86_USE_3DNOW
-EXPORT_SYMBOL(_mmx_memcpy);
-EXPORT_SYMBOL(mmx_clear_page);
-EXPORT_SYMBOL(mmx_copy_page);
-#endif
-
-#ifdef CONFIG_X86_HT
-EXPORT_SYMBOL(smp_num_siblings);
-EXPORT_SYMBOL(cpu_sibling_map);
-#endif
-
#ifdef CONFIG_SMP
-EXPORT_SYMBOL(cpu_data);
-EXPORT_SYMBOL(cpu_online_map);
-EXPORT_SYMBOL(cpu_callout_map);
+extern void FASTCALL( __write_lock_failed(rwlock_t *rw));
+extern void FASTCALL( __read_lock_failed(rwlock_t *rw));
EXPORT_SYMBOL(__write_lock_failed);
EXPORT_SYMBOL(__read_lock_failed);
-
-/* Global SMP stuff */
-EXPORT_SYMBOL(smp_call_function);
-
-/* TLB flushing */
-EXPORT_SYMBOL(flush_tlb_page);
-#endif
-
-#ifdef CONFIG_X86_IO_APIC
-EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
-#endif
-
-#ifdef CONFIG_MCA
-EXPORT_SYMBOL(machine_id);
-#endif
-
-#ifdef CONFIG_VT
-EXPORT_SYMBOL(screen_info);
-#endif
-
-EXPORT_SYMBOL(get_wchan);
-
-EXPORT_SYMBOL(rtc_lock);
-
-EXPORT_SYMBOL_GPL(set_nmi_callback);
-EXPORT_SYMBOL_GPL(unset_nmi_callback);
-
-EXPORT_SYMBOL(register_die_notifier);
-#ifdef CONFIG_HAVE_DEC_LOCK
-EXPORT_SYMBOL(_atomic_dec_and_lock);
-#endif
-
-EXPORT_SYMBOL(__PAGE_KERNEL);
-
-#ifdef CONFIG_HIGHMEM
-EXPORT_SYMBOL(kmap);
-EXPORT_SYMBOL(kunmap);
-EXPORT_SYMBOL(kmap_atomic);
-EXPORT_SYMBOL(kunmap_atomic);
-EXPORT_SYMBOL(kmap_atomic_to_page);
-#endif
-
-#if defined(CONFIG_X86_SPEEDSTEP_SMI) || defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE)
-EXPORT_SYMBOL(ist_info);
#endif
EXPORT_SYMBOL(csum_partial);
diff --git a/arch/i386/kernel/i387.c b/arch/i386/kernel/i387.c
index c55e037f08f..b817168d9c6 100644
--- a/arch/i386/kernel/i387.c
+++ b/arch/i386/kernel/i387.c
@@ -10,6 +10,7 @@
#include <linux/config.h>
#include <linux/sched.h>
+#include <linux/module.h>
#include <asm/processor.h>
#include <asm/i387.h>
#include <asm/math_emu.h>
@@ -79,6 +80,7 @@ void kernel_fpu_begin(void)
}
clts();
}
+EXPORT_SYMBOL_GPL(kernel_fpu_begin);
void restore_fpu( struct task_struct *tsk )
{
@@ -526,6 +528,7 @@ int dump_fpu( struct pt_regs *regs, struct user_i387_struct *fpu )
return fpvalid;
}
+EXPORT_SYMBOL(dump_fpu);
int dump_task_fpu(struct task_struct *tsk, struct user_i387_struct *fpu)
{
diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c
index 2c4813b47e5..178f4e9bac9 100644
--- a/arch/i386/kernel/i8259.c
+++ b/arch/i386/kernel/i8259.c
@@ -268,10 +268,22 @@ static int i8259A_suspend(struct sys_device *dev, pm_message_t state)
return 0;
}
+static int i8259A_shutdown(struct sys_device *dev)
+{
+ /* Put the i8259A into a quiescent state that
+ * the kernel initialization code can get it
+ * out of.
+ */
+ outb(0xff, 0x21); /* mask all of 8259A-1 */
+ outb(0xff, 0xA1); /* mask all of 8259A-1 */
+ return 0;
+}
+
static struct sysdev_class i8259_sysdev_class = {
set_kset_name("i8259"),
.suspend = i8259A_suspend,
.resume = i8259A_resume,
+ .shutdown = i8259A_shutdown,
};
static struct sys_device device_i8259A = {
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 7a324e8b86f..35eb8e29c48 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -31,7 +31,7 @@
#include <linux/mc146818rtc.h>
#include <linux/compiler.h>
#include <linux/acpi.h>
-
+#include <linux/module.h>
#include <linux/sysdev.h>
#include <asm/io.h>
#include <asm/smp.h>
@@ -573,12 +573,14 @@ static int balanced_irq(void *unused)
for ( ; ; ) {
set_current_state(TASK_INTERRUPTIBLE);
time_remaining = schedule_timeout(time_remaining);
- try_to_freeze(PF_FREEZE);
+ try_to_freeze();
if (time_after(jiffies,
prev_balance_time+balanced_irq_interval)) {
+ preempt_disable();
do_irq_balance();
prev_balance_time = jiffies;
time_remaining = balanced_irq_interval;
+ preempt_enable();
}
}
return 0;
@@ -630,10 +632,8 @@ static int __init balanced_irq_init(void)
printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq");
failed:
for (i = 0; i < NR_CPUS; i++) {
- if(irq_cpu_data[i].irq_delta)
- kfree(irq_cpu_data[i].irq_delta);
- if(irq_cpu_data[i].last_irq)
- kfree(irq_cpu_data[i].last_irq);
+ kfree(irq_cpu_data[i].irq_delta);
+ kfree(irq_cpu_data[i].last_irq);
}
return 0;
}
@@ -812,6 +812,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
}
return best_guess;
}
+EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
/*
* This function currently is only a helper for the i386 smp boot process where
@@ -1633,12 +1634,43 @@ static void __init enable_IO_APIC(void)
*/
void disable_IO_APIC(void)
{
+ int pin;
/*
* Clear the IO-APIC before rebooting:
*/
clear_IO_APIC();
- disconnect_bsp_APIC();
+ /*
+ * If the i82559 is routed through an IOAPIC
+ * Put that IOAPIC in virtual wire mode
+ * so legacy interrups can be delivered.
+ */
+ pin = find_isa_irq_pin(0, mp_ExtINT);
+ if (pin != -1) {
+ struct IO_APIC_route_entry entry;
+ unsigned long flags;
+
+ memset(&entry, 0, sizeof(entry));
+ entry.mask = 0; /* Enabled */
+ entry.trigger = 0; /* Edge */
+ entry.irr = 0;
+ entry.polarity = 0; /* High */
+ entry.delivery_status = 0;
+ entry.dest_mode = 0; /* Physical */
+ entry.delivery_mode = 7; /* ExtInt */
+ entry.vector = 0;
+ entry.dest.physical.physical_dest = 0;
+
+
+ /*
+ * Add it to the IO-APIC irq-routing table:
+ */
+ spin_lock_irqsave(&ioapic_lock, flags);
+ io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1));
+ io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0));
+ spin_unlock_irqrestore(&ioapic_lock, flags);
+ }
+ disconnect_bsp_APIC(pin != -1);
}
/*
@@ -1659,6 +1691,12 @@ static void __init setup_ioapic_ids_from_mpc(void)
unsigned long flags;
/*
+ * Don't check I/O APIC IDs for xAPIC systems. They have
+ * no meaning without the serial APIC bus.
+ */
+ if (!(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && boot_cpu_data.x86 < 15))
+ return;
+ /*
* This is broken; anything with a real cpu count has to
* circumvent this idiocy regardless.
*/
@@ -1684,10 +1722,6 @@ static void __init setup_ioapic_ids_from_mpc(void)
mp_ioapics[apic].mpc_apicid = reg_00.bits.ID;
}
- /* Don't check I/O APIC IDs for some xAPIC systems. They have
- * no meaning without the serial APIC bus. */
- if (NO_IOAPIC_CHECK)
- continue;
/*
* Sanity check, is the ID really free? Every APIC in a
* system must have a unique ID or we get lots of nice
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
index 73945a3c53c..ce66dcc26d9 100644
--- a/arch/i386/kernel/irq.c
+++ b/arch/i386/kernel/irq.c
@@ -15,6 +15,9 @@
#include <linux/seq_file.h>
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
+#include <linux/delay.h>
DEFINE_PER_CPU(irq_cpustat_t, irq_stat) ____cacheline_maxaligned_in_smp;
EXPORT_PER_CPU_SYMBOL(irq_stat);
@@ -153,6 +156,11 @@ void irq_ctx_init(int cpu)
cpu,hardirq_ctx[cpu],softirq_ctx[cpu]);
}
+void irq_ctx_exit(int cpu)
+{
+ hardirq_ctx[cpu] = NULL;
+}
+
extern asmlinkage void __do_softirq(void);
asmlinkage void do_softirq(void)
@@ -210,9 +218,8 @@ int show_interrupts(struct seq_file *p, void *v)
if (i == 0) {
seq_printf(p, " ");
- for (j=0; j<NR_CPUS; j++)
- if (cpu_online(j))
- seq_printf(p, "CPU%d ",j);
+ for_each_cpu(j)
+ seq_printf(p, "CPU%d ",j);
seq_putc(p, '\n');
}
@@ -225,9 +232,8 @@ int show_interrupts(struct seq_file *p, void *v)
#ifndef CONFIG_SMP
seq_printf(p, "%10u ", kstat_irqs(i));
#else
- for (j = 0; j < NR_CPUS; j++)
- if (cpu_online(j))
- seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+ for_each_cpu(j)
+ seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
#endif
seq_printf(p, " %14s", irq_desc[i].handler->typename);
seq_printf(p, " %s", action->name);
@@ -240,16 +246,14 @@ skip:
spin_unlock_irqrestore(&irq_desc[i].lock, flags);
} else if (i == NR_IRQS) {
seq_printf(p, "NMI: ");
- for (j = 0; j < NR_CPUS; j++)
- if (cpu_online(j))
- seq_printf(p, "%10u ", nmi_count(j));
+ for_each_cpu(j)
+ seq_printf(p, "%10u ", nmi_count(j));
seq_putc(p, '\n');
#ifdef CONFIG_X86_LOCAL_APIC
seq_printf(p, "LOC: ");
- for (j = 0; j < NR_CPUS; j++)
- if (cpu_online(j))
- seq_printf(p, "%10u ",
- per_cpu(irq_stat,j).apic_timer_irqs);
+ for_each_cpu(j)
+ seq_printf(p, "%10u ",
+ per_cpu(irq_stat,j).apic_timer_irqs);
seq_putc(p, '\n');
#endif
seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
@@ -259,3 +263,45 @@ skip:
}
return 0;
}
+
+#ifdef CONFIG_HOTPLUG_CPU
+#include <mach_apic.h>
+
+void fixup_irqs(cpumask_t map)
+{
+ unsigned int irq;
+ static int warned;
+
+ for (irq = 0; irq < NR_IRQS; irq++) {
+ cpumask_t mask;
+ if (irq == 2)
+ continue;
+
+ cpus_and(mask, irq_affinity[irq], map);
+ if (any_online_cpu(mask) == NR_CPUS) {
+ printk("Breaking affinity for irq %i\n", irq);
+ mask = map;
+ }
+ if (irq_desc[irq].handler->set_affinity)
+ irq_desc[irq].handler->set_affinity(irq, mask);
+ else if (irq_desc[irq].action && !(warned++))
+ printk("Cannot set affinity for irq %i\n", irq);
+ }
+
+#if 0
+ barrier();
+ /* Ingo Molnar says: "after the IO-APIC masks have been redirected
+ [note the nop - the interrupt-enable boundary on x86 is two
+ instructions from sti] - to flush out pending hardirqs and
+ IPIs. After this point nothing is supposed to reach this CPU." */
+ __asm__ __volatile__("sti; nop; cli");
+ barrier();
+#else
+ /* That doesn't seem sufficient. Give it 1ms. */
+ local_irq_enable();
+ mdelay(1);
+ local_irq_disable();
+#endif
+}
+#endif
+
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index 59ff9b45506..3762f6b35ab 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -23,6 +23,9 @@
* Rusty Russell).
* 2004-July Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes
* interface to access function arguments.
+ * 2005-May Hien Nguyen <hien@us.ibm.com>, Jim Keniston
+ * <jkenisto@us.ibm.com> and Prasanna S Panchamukhi
+ * <prasanna@in.ibm.com> added function-return probes.
*/
#include <linux/config.h>
@@ -30,15 +33,14 @@
#include <linux/ptrace.h>
#include <linux/spinlock.h>
#include <linux/preempt.h>
+#include <asm/cacheflush.h>
#include <asm/kdebug.h>
#include <asm/desc.h>
-/* kprobe_status settings */
-#define KPROBE_HIT_ACTIVE 0x00000001
-#define KPROBE_HIT_SS 0x00000002
-
static struct kprobe *current_kprobe;
static unsigned long kprobe_status, kprobe_old_eflags, kprobe_saved_eflags;
+static struct kprobe *kprobe_prev;
+static unsigned long kprobe_status_prev, kprobe_old_eflags_prev, kprobe_saved_eflags_prev;
static struct pt_regs jprobe_saved_regs;
static long *jprobe_saved_esp;
/* copy of the kernel stack at the probe fire time */
@@ -68,16 +70,50 @@ int arch_prepare_kprobe(struct kprobe *p)
void arch_copy_kprobe(struct kprobe *p)
{
memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
+ p->opcode = *p->addr;
}
-void arch_remove_kprobe(struct kprobe *p)
+void arch_arm_kprobe(struct kprobe *p)
{
+ *p->addr = BREAKPOINT_INSTRUCTION;
+ flush_icache_range((unsigned long) p->addr,
+ (unsigned long) p->addr + sizeof(kprobe_opcode_t));
}
-static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs)
+void arch_disarm_kprobe(struct kprobe *p)
{
*p->addr = p->opcode;
- regs->eip = (unsigned long)p->addr;
+ flush_icache_range((unsigned long) p->addr,
+ (unsigned long) p->addr + sizeof(kprobe_opcode_t));
+}
+
+void arch_remove_kprobe(struct kprobe *p)
+{
+}
+
+static inline void save_previous_kprobe(void)
+{
+ kprobe_prev = current_kprobe;
+ kprobe_status_prev = kprobe_status;
+ kprobe_old_eflags_prev = kprobe_old_eflags;
+ kprobe_saved_eflags_prev = kprobe_saved_eflags;
+}
+
+static inline void restore_previous_kprobe(void)
+{
+ current_kprobe = kprobe_prev;
+ kprobe_status = kprobe_status_prev;
+ kprobe_old_eflags = kprobe_old_eflags_prev;
+ kprobe_saved_eflags = kprobe_saved_eflags_prev;
+}
+
+static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs)
+{
+ current_kprobe = p;
+ kprobe_saved_eflags = kprobe_old_eflags
+ = (regs->eflags & (TF_MASK | IF_MASK));
+ if (is_IF_modifier(p->opcode))
+ kprobe_saved_eflags &= ~IF_MASK;
}
static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
@@ -91,6 +127,50 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
regs->eip = (unsigned long)&p->ainsn.insn;
}
+struct task_struct *arch_get_kprobe_task(void *ptr)
+{
+ return ((struct thread_info *) (((unsigned long) ptr) &
+ (~(THREAD_SIZE -1))))->task;
+}
+
+void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
+{
+ unsigned long *sara = (unsigned long *)&regs->esp;
+ struct kretprobe_instance *ri;
+ static void *orig_ret_addr;
+
+ /*
+ * Save the return address when the return probe hits
+ * the first time, and use it to populate the (krprobe
+ * instance)->ret_addr for subsequent return probes at
+ * the same addrress since stack address would have
+ * the kretprobe_trampoline by then.
+ */
+ if (((void*) *sara) != kretprobe_trampoline)
+ orig_ret_addr = (void*) *sara;
+
+ if ((ri = get_free_rp_inst(rp)) != NULL) {
+ ri->rp = rp;
+ ri->stack_addr = sara;
+ ri->ret_addr = orig_ret_addr;
+ add_rp_inst(ri);
+ /* Replace the return addr with trampoline addr */
+ *sara = (unsigned long) &kretprobe_trampoline;
+ } else {
+ rp->nmissed++;
+ }
+}
+
+void arch_kprobe_flush_task(struct task_struct *tk)
+{
+ struct kretprobe_instance *ri;
+ while ((ri = get_rp_inst_tsk(tk)) != NULL) {
+ *((unsigned long *)(ri->stack_addr)) =
+ (unsigned long) ri->ret_addr;
+ recycle_rp_inst(ri);
+ }
+}
+
/*
* Interrupts are disabled on entry as trap3 is an interrupt gate and they
* remain disabled thorough out this function.
@@ -127,8 +207,18 @@ static int kprobe_handler(struct pt_regs *regs)
unlock_kprobes();
goto no_kprobe;
}
- disarm_kprobe(p, regs);
- ret = 1;
+ /* We have reentered the kprobe_handler(), since
+ * another probe was hit while within the handler.
+ * We here save the original kprobes variables and
+ * just single step on the instruction of the new probe
+ * without calling any user handlers.
+ */
+ save_previous_kprobe();
+ set_current_kprobe(p, regs);
+ p->nmissed++;
+ prepare_singlestep(p, regs);
+ kprobe_status = KPROBE_REENTER;
+ return 1;
} else {
p = current_kprobe;
if (p->break_handler && p->break_handler(p, regs)) {
@@ -163,11 +253,7 @@ static int kprobe_handler(struct pt_regs *regs)
}
kprobe_status = KPROBE_HIT_ACTIVE;
- current_kprobe = p;
- kprobe_saved_eflags = kprobe_old_eflags
- = (regs->eflags & (TF_MASK | IF_MASK));
- if (is_IF_modifier(p->opcode))
- kprobe_saved_eflags &= ~IF_MASK;
+ set_current_kprobe(p, regs);
if (p->pre_handler && p->pre_handler(p, regs))
/* handler has already set things up, so skip ss setup */
@@ -184,6 +270,55 @@ no_kprobe:
}
/*
+ * For function-return probes, init_kprobes() establishes a probepoint
+ * here. When a retprobed function returns, this probe is hit and
+ * trampoline_probe_handler() runs, calling the kretprobe's handler.
+ */
+ void kretprobe_trampoline_holder(void)
+ {
+ asm volatile ( ".global kretprobe_trampoline\n"
+ "kretprobe_trampoline: \n"
+ "nop\n");
+ }
+
+/*
+ * Called when we hit the probe point at kretprobe_trampoline
+ */
+int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ struct task_struct *tsk;
+ struct kretprobe_instance *ri;
+ struct hlist_head *head;
+ struct hlist_node *node;
+ unsigned long *sara = ((unsigned long *) &regs->esp) - 1;
+
+ tsk = arch_get_kprobe_task(sara);
+ head = kretprobe_inst_table_head(tsk);
+
+ hlist_for_each_entry(ri, node, head, hlist) {
+ if (ri->stack_addr == sara && ri->rp) {
+ if (ri->rp->handler)
+ ri->rp->handler(ri, regs);
+ }
+ }
+ return 0;
+}
+
+void trampoline_post_handler(struct kprobe *p, struct pt_regs *regs,
+ unsigned long flags)
+{
+ struct kretprobe_instance *ri;
+ /* RA already popped */
+ unsigned long *sara = ((unsigned long *)&regs->esp) - 1;
+
+ while ((ri = get_rp_inst(sara))) {
+ regs->eip = (unsigned long)ri->ret_addr;
+ recycle_rp_inst(ri);
+ }
+ regs->eflags &= ~TF_MASK;
+}
+
+/*
* Called after single-stepping. p->addr is the address of the
* instruction whose first byte has been replaced by the "int 3"
* instruction. To avoid the SMP problems that can occur when we
@@ -263,13 +398,22 @@ static inline int post_kprobe_handler(struct pt_regs *regs)
if (!kprobe_running())
return 0;
- if (current_kprobe->post_handler)
+ if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) {
+ kprobe_status = KPROBE_HIT_SSDONE;
current_kprobe->post_handler(current_kprobe, regs, 0);
+ }
- resume_execution(current_kprobe, regs);
+ if (current_kprobe->post_handler != trampoline_post_handler)
+ resume_execution(current_kprobe, regs);
regs->eflags |= kprobe_saved_eflags;
+ /*Restore back the original saved kprobes variables and continue. */
+ if (kprobe_status == KPROBE_REENTER) {
+ restore_previous_kprobe();
+ goto out;
+ }
unlock_kprobes();
+out:
preempt_enable_no_resched();
/*
diff --git a/arch/i386/kernel/machine_kexec.c b/arch/i386/kernel/machine_kexec.c
new file mode 100644
index 00000000000..52ed18d8b51
--- /dev/null
+++ b/arch/i386/kernel/machine_kexec.c
@@ -0,0 +1,226 @@
+/*
+ * machine_kexec.c - handle transition of Linux booting another kernel
+ * Copyright (C) 2002-2005 Eric Biederman <ebiederm@xmission.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/mm.h>
+#include <linux/kexec.h>
+#include <linux/delay.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/apic.h>
+#include <asm/cpufeature.h>
+
+static inline unsigned long read_cr3(void)
+{
+ unsigned long cr3;
+ asm volatile("movl %%cr3,%0": "=r"(cr3));
+ return cr3;
+}
+
+#define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE)))
+
+#define L0_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define L1_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define L2_ATTR (_PAGE_PRESENT)
+
+#define LEVEL0_SIZE (1UL << 12UL)
+
+#ifndef CONFIG_X86_PAE
+#define LEVEL1_SIZE (1UL << 22UL)
+static u32 pgtable_level1[1024] PAGE_ALIGNED;
+
+static void identity_map_page(unsigned long address)
+{
+ unsigned long level1_index, level2_index;
+ u32 *pgtable_level2;
+
+ /* Find the current page table */
+ pgtable_level2 = __va(read_cr3());
+
+ /* Find the indexes of the physical address to identity map */
+ level1_index = (address % LEVEL1_SIZE)/LEVEL0_SIZE;
+ level2_index = address / LEVEL1_SIZE;
+
+ /* Identity map the page table entry */
+ pgtable_level1[level1_index] = address | L0_ATTR;
+ pgtable_level2[level2_index] = __pa(pgtable_level1) | L1_ATTR;
+
+ /* Flush the tlb so the new mapping takes effect.
+ * Global tlb entries are not flushed but that is not an issue.
+ */
+ load_cr3(pgtable_level2);
+}
+
+#else
+#define LEVEL1_SIZE (1UL << 21UL)
+#define LEVEL2_SIZE (1UL << 30UL)
+static u64 pgtable_level1[512] PAGE_ALIGNED;
+static u64 pgtable_level2[512] PAGE_ALIGNED;
+
+static void identity_map_page(unsigned long address)
+{
+ unsigned long level1_index, level2_index, level3_index;
+ u64 *pgtable_level3;
+
+ /* Find the current page table */
+ pgtable_level3 = __va(read_cr3());
+
+ /* Find the indexes of the physical address to identity map */
+ level1_index = (address % LEVEL1_SIZE)/LEVEL0_SIZE;
+ level2_index = (address % LEVEL2_SIZE)/LEVEL1_SIZE;
+ level3_index = address / LEVEL2_SIZE;
+
+ /* Identity map the page table entry */
+ pgtable_level1[level1_index] = address | L0_ATTR;
+ pgtable_level2[level2_index] = __pa(pgtable_level1) | L1_ATTR;
+ set_64bit(&pgtable_level3[level3_index],
+ __pa(pgtable_level2) | L2_ATTR);
+
+ /* Flush the tlb so the new mapping takes effect.
+ * Global tlb entries are not flushed but that is not an issue.
+ */
+ load_cr3(pgtable_level3);
+}
+#endif
+
+
+static void set_idt(void *newidt, __u16 limit)
+{
+ unsigned char curidt[6];
+
+ /* ia32 supports unaliged loads & stores */
+ (*(__u16 *)(curidt)) = limit;
+ (*(__u32 *)(curidt +2)) = (unsigned long)(newidt);
+
+ __asm__ __volatile__ (
+ "lidt %0\n"
+ : "=m" (curidt)
+ );
+};
+
+
+static void set_gdt(void *newgdt, __u16 limit)
+{
+ unsigned char curgdt[6];
+
+ /* ia32 supports unaligned loads & stores */
+ (*(__u16 *)(curgdt)) = limit;
+ (*(__u32 *)(curgdt +2)) = (unsigned long)(newgdt);
+
+ __asm__ __volatile__ (
+ "lgdt %0\n"
+ : "=m" (curgdt)
+ );
+};
+
+static void load_segments(void)
+{
+#define __STR(X) #X
+#define STR(X) __STR(X)
+
+ __asm__ __volatile__ (
+ "\tljmp $"STR(__KERNEL_CS)",$1f\n"
+ "\t1:\n"
+ "\tmovl $"STR(__KERNEL_DS)",%eax\n"
+ "\tmovl %eax,%ds\n"
+ "\tmovl %eax,%es\n"
+ "\tmovl %eax,%fs\n"
+ "\tmovl %eax,%gs\n"
+ "\tmovl %eax,%ss\n"
+ );
+#undef STR
+#undef __STR
+}
+
+typedef asmlinkage NORET_TYPE void (*relocate_new_kernel_t)(
+ unsigned long indirection_page,
+ unsigned long reboot_code_buffer,
+ unsigned long start_address,
+ unsigned int has_pae) ATTRIB_NORET;
+
+const extern unsigned char relocate_new_kernel[];
+extern void relocate_new_kernel_end(void);
+const extern unsigned int relocate_new_kernel_size;
+
+/*
+ * A architecture hook called to validate the
+ * proposed image and prepare the control pages
+ * as needed. The pages for KEXEC_CONTROL_CODE_SIZE
+ * have been allocated, but the segments have yet
+ * been copied into the kernel.
+ *
+ * Do what every setup is needed on image and the
+ * reboot code buffer to allow us to avoid allocations
+ * later.
+ *
+ * Currently nothing.
+ */
+int machine_kexec_prepare(struct kimage *image)
+{
+ return 0;
+}
+
+/*
+ * Undo anything leftover by machine_kexec_prepare
+ * when an image is freed.
+ */
+void machine_kexec_cleanup(struct kimage *image)
+{
+}
+
+/*
+ * Do not allocate memory (or fail in any way) in machine_kexec().
+ * We are past the point of no return, committed to rebooting now.
+ */
+NORET_TYPE void machine_kexec(struct kimage *image)
+{
+ unsigned long page_list;
+ unsigned long reboot_code_buffer;
+
+ relocate_new_kernel_t rnk;
+
+ /* Interrupts aren't acceptable while we reboot */
+ local_irq_disable();
+
+ /* Compute some offsets */
+ reboot_code_buffer = page_to_pfn(image->control_code_page)
+ << PAGE_SHIFT;
+ page_list = image->head;
+
+ /* Set up an identity mapping for the reboot_code_buffer */
+ identity_map_page(reboot_code_buffer);
+
+ /* copy it out */
+ memcpy((void *)reboot_code_buffer, relocate_new_kernel,
+ relocate_new_kernel_size);
+
+ /* The segment registers are funny things, they are
+ * automatically loaded from a table, in memory wherever you
+ * set them to a specific selector, but this table is never
+ * accessed again you set the segment to a different selector.
+ *
+ * The more common model is are caches where the behide
+ * the scenes work is done, but is also dropped at arbitrary
+ * times.
+ *
+ * I take advantage of this here by force loading the
+ * segments, before I zap the gdt with an invalid value.
+ */
+ load_segments();
+ /* The gdt & idt are now invalid.
+ * If you want to load them you must set up your own idt & gdt.
+ */
+ set_gdt(phys_to_virt(0),0);
+ set_idt(phys_to_virt(0),0);
+
+ /* now call it */
+ rnk = (relocate_new_kernel_t) reboot_code_buffer;
+ (*rnk)(page_list, reboot_code_buffer, image->start, cpu_has_pae);
+}
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
index 1347ab4939e..af917f609c7 100644
--- a/arch/i386/kernel/mpparse.c
+++ b/arch/i386/kernel/mpparse.c
@@ -67,7 +67,6 @@ unsigned long mp_lapic_addr;
/* Processor that is doing the boot up */
unsigned int boot_cpu_physical_apicid = -1U;
-unsigned int boot_cpu_logical_apicid = -1U;
/* Internal processor count */
static unsigned int __initdata num_processors;
@@ -180,7 +179,6 @@ static void __init MP_processor_info (struct mpc_config_processor *m)
if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
Dprintk(" Bootup CPU\n");
boot_cpu_physical_apicid = m->mpc_apicid;
- boot_cpu_logical_apicid = apicid;
}
if (num_processors >= NR_CPUS) {
@@ -914,7 +912,10 @@ void __init mp_register_ioapic (
mp_ioapics[idx].mpc_apicaddr = address;
set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
- mp_ioapics[idx].mpc_apicid = io_apic_get_unique_id(idx, id);
+ if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 < 15))
+ mp_ioapics[idx].mpc_apicid = io_apic_get_unique_id(idx, id);
+ else
+ mp_ioapics[idx].mpc_apicid = id;
mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
/*
@@ -1055,11 +1056,20 @@ void __init mp_config_acpi_legacy_irqs (void)
}
}
+#define MAX_GSI_NUM 4096
+
int mp_register_gsi (u32 gsi, int edge_level, int active_high_low)
{
int ioapic = -1;
int ioapic_pin = 0;
int idx, bit = 0;
+ static int pci_irq = 16;
+ /*
+ * Mapping between Global System Interrups, which
+ * represent all possible interrupts, and IRQs
+ * assigned to actual devices.
+ */
+ static int gsi_to_irq[MAX_GSI_NUM];
#ifdef CONFIG_ACPI_BUS
/* Don't set up the ACPI SCI because it's already set up */
@@ -1094,11 +1104,26 @@ int mp_register_gsi (u32 gsi, int edge_level, int active_high_low)
if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
- return gsi;
+ return gsi_to_irq[gsi];
}
mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
+ if (edge_level) {
+ /*
+ * For PCI devices assign IRQs in order, avoiding gaps
+ * due to unused I/O APIC pins.
+ */
+ int irq = gsi;
+ if (gsi < MAX_GSI_NUM) {
+ gsi = pci_irq++;
+ gsi_to_irq[irq] = gsi;
+ } else {
+ printk(KERN_ERR "GSI %u is too high\n", gsi);
+ return gsi;
+ }
+ }
+
io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
edge_level == ACPI_EDGE_SENSITIVE ? 0 : 1,
active_high_low == ACPI_ACTIVE_HIGH ? 0 : 1);
diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c
index 05d9f8f363a..b2f03c39a6f 100644
--- a/arch/i386/kernel/msr.c
+++ b/arch/i386/kernel/msr.c
@@ -44,7 +44,7 @@
#include <asm/uaccess.h>
#include <asm/system.h>
-static struct class_simple *msr_class;
+static struct class *msr_class;
/* Note: "err" is handled in a funny way below. Otherwise one version
of gcc or another breaks. */
@@ -260,12 +260,12 @@ static struct file_operations msr_fops = {
.open = msr_open,
};
-static int msr_class_simple_device_add(int i)
+static int msr_class_device_create(int i)
{
int err = 0;
struct class_device *class_err;
- class_err = class_simple_device_add(msr_class, MKDEV(MSR_MAJOR, i), NULL, "msr%d",i);
+ class_err = class_device_create(msr_class, MKDEV(MSR_MAJOR, i), NULL, "msr%d",i);
if (IS_ERR(class_err))
err = PTR_ERR(class_err);
return err;
@@ -277,10 +277,10 @@ static int __devinit msr_class_cpu_callback(struct notifier_block *nfb, unsigned
switch (action) {
case CPU_ONLINE:
- msr_class_simple_device_add(cpu);
+ msr_class_device_create(cpu);
break;
case CPU_DEAD:
- class_simple_device_remove(MKDEV(MSR_MAJOR, cpu));
+ class_device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
break;
}
return NOTIFY_OK;
@@ -302,13 +302,13 @@ static int __init msr_init(void)
err = -EBUSY;
goto out;
}
- msr_class = class_simple_create(THIS_MODULE, "msr");
+ msr_class = class_create(THIS_MODULE, "msr");
if (IS_ERR(msr_class)) {
err = PTR_ERR(msr_class);
goto out_chrdev;
}
for_each_online_cpu(i) {
- err = msr_class_simple_device_add(i);
+ err = msr_class_device_create(i);
if (err != 0)
goto out_class;
}
@@ -320,8 +320,8 @@ static int __init msr_init(void)
out_class:
i = 0;
for_each_online_cpu(i)
- class_simple_device_remove(MKDEV(MSR_MAJOR, i));
- class_simple_destroy(msr_class);
+ class_device_destroy(msr_class, MKDEV(MSR_MAJOR, i));
+ class_destroy(msr_class);
out_chrdev:
unregister_chrdev(MSR_MAJOR, "cpu/msr");
out:
@@ -332,8 +332,8 @@ static void __exit msr_exit(void)
{
int cpu = 0;
for_each_online_cpu(cpu)
- class_simple_device_remove(MKDEV(MSR_MAJOR, cpu));
- class_simple_destroy(msr_class);
+ class_device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
+ class_destroy(msr_class);
unregister_chrdev(MSR_MAJOR, "cpu/msr");
unregister_cpu_notifier(&msr_class_cpu_notifier);
}
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index 2c0ee9c2d02..da6c46d667c 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -28,8 +28,7 @@
#include <linux/sysctl.h>
#include <asm/smp.h>
-#include <asm/mtrr.h>
-#include <asm/mpspec.h>
+#include <asm/div64.h>
#include <asm/nmi.h>
#include "mach_traps.h"
@@ -324,6 +323,16 @@ static void clear_msr_range(unsigned int base, unsigned int n)
wrmsr(base+i, 0, 0);
}
+static inline void write_watchdog_counter(const char *descr)
+{
+ u64 count = (u64)cpu_khz * 1000;
+
+ do_div(count, nmi_hz);
+ if(descr)
+ Dprintk("setting %s to -0x%08Lx\n", descr, count);
+ wrmsrl(nmi_perfctr_msr, 0 - count);
+}
+
static void setup_k7_watchdog(void)
{
unsigned int evntsel;
@@ -339,8 +348,7 @@ static void setup_k7_watchdog(void)
| K7_NMI_EVENT;
wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
- Dprintk("setting K7_PERFCTR0 to %08lx\n", -(cpu_khz/nmi_hz*1000));
- wrmsr(MSR_K7_PERFCTR0, -(cpu_khz/nmi_hz*1000), -1);
+ write_watchdog_counter("K7_PERFCTR0");
apic_write(APIC_LVTPC, APIC_DM_NMI);
evntsel |= K7_EVNTSEL_ENABLE;
wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
@@ -361,8 +369,7 @@ static void setup_p6_watchdog(void)
| P6_NMI_EVENT;
wrmsr(MSR_P6_EVNTSEL0, evntsel, 0);
- Dprintk("setting P6_PERFCTR0 to %08lx\n", -(cpu_khz/nmi_hz*1000));
- wrmsr(MSR_P6_PERFCTR0, -(cpu_khz/nmi_hz*1000), 0);
+ write_watchdog_counter("P6_PERFCTR0");
apic_write(APIC_LVTPC, APIC_DM_NMI);
evntsel |= P6_EVNTSEL0_ENABLE;
wrmsr(MSR_P6_EVNTSEL0, evntsel, 0);
@@ -402,8 +409,7 @@ static int setup_p4_watchdog(void)
wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0);
wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0);
- Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz/nmi_hz*1000));
- wrmsr(MSR_P4_IQ_COUNTER0, -(cpu_khz/nmi_hz*1000), -1);
+ write_watchdog_counter("P4_IQ_COUNTER0");
apic_write(APIC_LVTPC, APIC_DM_NMI);
wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
return 1;
@@ -518,7 +524,7 @@ void nmi_watchdog_tick (struct pt_regs * regs)
* other P6 variant */
apic_write(APIC_LVTPC, APIC_DM_NMI);
}
- wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1);
+ write_watchdog_counter(NULL);
}
}
diff --git a/arch/i386/kernel/pci-dma.c b/arch/i386/kernel/pci-dma.c
index 4de2e03c7b4..1e51427cc9e 100644
--- a/arch/i386/kernel/pci-dma.c
+++ b/arch/i386/kernel/pci-dma.c
@@ -11,6 +11,7 @@
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/pci.h>
+#include <linux/module.h>
#include <asm/io.h>
struct dma_coherent_mem {
@@ -54,6 +55,7 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
}
return ret;
}
+EXPORT_SYMBOL(dma_alloc_coherent);
void dma_free_coherent(struct device *dev, size_t size,
void *vaddr, dma_addr_t dma_handle)
@@ -68,6 +70,7 @@ void dma_free_coherent(struct device *dev, size_t size,
} else
free_pages((unsigned long)vaddr, order);
}
+EXPORT_SYMBOL(dma_free_coherent);
int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
dma_addr_t device_addr, size_t size, int flags)
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 96e3ea6b17c..5f8cfa6b794 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -13,6 +13,7 @@
#include <stdarg.h>
+#include <linux/cpu.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/fs.h>
@@ -37,6 +38,7 @@
#include <linux/kallsyms.h>
#include <linux/ptrace.h>
#include <linux/random.h>
+#include <linux/kprobes.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
@@ -54,6 +56,9 @@
#include <linux/irq.h>
#include <linux/err.h>
+#include <asm/tlbflush.h>
+#include <asm/cpu.h>
+
asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
static int hlt_counter;
@@ -73,6 +78,7 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
* Powermanagement idle function, if any..
*/
void (*pm_idle)(void);
+EXPORT_SYMBOL(pm_idle);
static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
void disable_hlt(void)
@@ -105,6 +111,9 @@ void default_idle(void)
cpu_relax();
}
}
+#ifdef CONFIG_APM_MODULE
+EXPORT_SYMBOL(default_idle);
+#endif
/*
* On SMP it's slightly faster (but much more power-consuming!)
@@ -138,14 +147,42 @@ static void poll_idle (void)
}
}
+#ifdef CONFIG_HOTPLUG_CPU
+#include <asm/nmi.h>
+/* We don't actually take CPU down, just spin without interrupts. */
+static inline void play_dead(void)
+{
+ /* This must be done before dead CPU ack */
+ cpu_exit_clear();
+ wbinvd();
+ mb();
+ /* Ack it */
+ __get_cpu_var(cpu_state) = CPU_DEAD;
+
+ /*
+ * With physical CPU hotplug, we should halt the cpu
+ */
+ local_irq_disable();
+ while (1)
+ __asm__ __volatile__("hlt":::"memory");
+}
+#else
+static inline void play_dead(void)
+{
+ BUG();
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
/*
* The idle thread. There's no useful work to be
* done, so just try to conserve power and have a
* low exit latency (ie sit in a loop waiting for
* somebody to say that they'd like to reschedule)
*/
-void cpu_idle (void)
+void cpu_idle(void)
{
+ int cpu = raw_smp_processor_id();
+
/* endless idle loop with no priority at all */
while (1) {
while (!need_resched()) {
@@ -160,6 +197,9 @@ void cpu_idle (void)
if (!idle)
idle = default_idle;
+ if (cpu_is_offline(cpu))
+ play_dead();
+
__get_cpu_var(irq_stat).idle_timestamp = jiffies;
idle();
}
@@ -218,7 +258,7 @@ static void mwait_idle(void)
}
}
-void __init select_idle_routine(const struct cpuinfo_x86 *c)
+void __devinit select_idle_routine(const struct cpuinfo_x86 *c)
{
if (cpu_has(c, X86_FEATURE_MWAIT)) {
printk("monitor/mwait feature present.\n");
@@ -262,7 +302,7 @@ void show_regs(struct pt_regs * regs)
printk("EIP: %04x:[<%08lx>] CPU: %d\n",0xffff & regs->xcs,regs->eip, smp_processor_id());
print_symbol("EIP is at %s\n", regs->eip);
- if (regs->xcs & 3)
+ if (user_mode(regs))
printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp);
printk(" EFLAGS: %08lx %s (%s)\n",
regs->eflags, print_tainted(), system_utsname.release);
@@ -325,6 +365,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
/* Ok, create the new process.. */
return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
}
+EXPORT_SYMBOL(kernel_thread);
/*
* Free current thread data structures etc..
@@ -334,6 +375,13 @@ void exit_thread(void)
struct task_struct *tsk = current;
struct thread_struct *t = &tsk->thread;
+ /*
+ * Remove function-return probe instances associated with this task
+ * and put them back on the free list. Do not insert an exit probe for
+ * this function, it will be disabled by kprobe_flush_task if you do.
+ */
+ kprobe_flush_task(tsk);
+
/* The process may have allocated an io port bitmap... nuke it. */
if (unlikely(NULL != t->io_bitmap_ptr)) {
int cpu = get_cpu();
@@ -357,6 +405,13 @@ void flush_thread(void)
{
struct task_struct *tsk = current;
+ /*
+ * Remove function-return probe instances associated with this task
+ * and put them back on the free list. Do not insert an exit probe for
+ * this function, it will be disabled by kprobe_flush_task if you do.
+ */
+ kprobe_flush_task(tsk);
+
memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8);
memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
/*
@@ -508,6 +563,7 @@ void dump_thread(struct pt_regs * regs, struct user * dump)
dump->u_fpvalid = dump_fpu (regs, &dump->i387);
}
+EXPORT_SYMBOL(dump_thread);
/*
* Capture the user space registers if the task is not running (in user space)
@@ -627,13 +683,13 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
* Now maybe reload the debug registers
*/
if (unlikely(next->debugreg[7])) {
- loaddebug(next, 0);
- loaddebug(next, 1);
- loaddebug(next, 2);
- loaddebug(next, 3);
+ set_debugreg(current->thread.debugreg[0], 0);
+ set_debugreg(current->thread.debugreg[1], 1);
+ set_debugreg(current->thread.debugreg[2], 2);
+ set_debugreg(current->thread.debugreg[3], 3);
/* no 4 and 5 */
- loaddebug(next, 6);
- loaddebug(next, 7);
+ set_debugreg(current->thread.debugreg[6], 6);
+ set_debugreg(current->thread.debugreg[7], 7);
}
if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr))
@@ -731,6 +787,7 @@ unsigned long get_wchan(struct task_struct *p)
} while (count++ < 16);
return 0;
}
+EXPORT_SYMBOL(get_wchan);
/*
* sys_alloc_thread_area: get a yet unused TLS descriptor index.
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index e34f651fa13..0da59b42843 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -668,7 +668,7 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code)
info.si_code = TRAP_BRKPT;
/* User-mode eip? */
- info.si_addr = user_mode(regs) ? (void __user *) regs->eip : NULL;
+ info.si_addr = user_mode_vm(regs) ? (void __user *) regs->eip : NULL;
/* Send us the fakey SIGTRAP */
force_sig_info(SIGTRAP, &info, tsk);
diff --git a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c
index 6dc27eb70ee..b3e58484996 100644
--- a/arch/i386/kernel/reboot.c
+++ b/arch/i386/kernel/reboot.c
@@ -2,6 +2,7 @@
* linux/arch/i386/kernel/reboot.c
*/
+#include <linux/config.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/delay.h>
@@ -19,12 +20,12 @@
* Power off function, if any
*/
void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
static int reboot_mode;
static int reboot_thru_bios;
#ifdef CONFIG_SMP
-int reboot_smp = 0;
static int reboot_cpu = -1;
/* shamelessly grabbed from lib/vsprintf.c for readability */
#define is_digit(c) ((c) >= '0' && (c) <= '9')
@@ -47,7 +48,6 @@ static int __init reboot_setup(char *str)
break;
#ifdef CONFIG_SMP
case 's': /* "smp" reboot by executing reset on BSP or other CPU*/
- reboot_smp = 1;
if (is_digit(*(str+1))) {
reboot_cpu = (int) (*(str+1) - '0');
if (is_digit(*(str+2)))
@@ -86,33 +86,9 @@ static int __init set_bios_reboot(struct dmi_system_id *d)
return 0;
}
-/*
- * Some machines require the "reboot=s" commandline option, this quirk makes that automatic.
- */
-static int __init set_smp_reboot(struct dmi_system_id *d)
-{
-#ifdef CONFIG_SMP
- if (!reboot_smp) {
- reboot_smp = 1;
- printk(KERN_INFO "%s series board detected. Selecting SMP-method for reboots.\n", d->ident);
- }
-#endif
- return 0;
-}
-
-/*
- * Some machines require the "reboot=b,s" commandline option, this quirk makes that automatic.
- */
-static int __init set_smp_bios_reboot(struct dmi_system_id *d)
-{
- set_smp_reboot(d);
- set_bios_reboot(d);
- return 0;
-}
-
static struct dmi_system_id __initdata reboot_dmi_table[] = {
{ /* Handle problems with rebooting on Dell 1300's */
- .callback = set_smp_bios_reboot,
+ .callback = set_bios_reboot,
.ident = "Dell PowerEdge 1300",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
@@ -295,42 +271,36 @@ void machine_real_restart(unsigned char *code, int length)
:
: "i" ((void *) (0x1000 - sizeof (real_mode_switch) - 100)));
}
+#ifdef CONFIG_APM_MODULE
+EXPORT_SYMBOL(machine_real_restart);
+#endif
-void machine_restart(char * __unused)
+void machine_shutdown(void)
{
#ifdef CONFIG_SMP
- int cpuid;
-
- cpuid = GET_APIC_ID(apic_read(APIC_ID));
-
- if (reboot_smp) {
-
- /* check to see if reboot_cpu is valid
- if its not, default to the BSP */
- if ((reboot_cpu == -1) ||
- (reboot_cpu > (NR_CPUS -1)) ||
- !physid_isset(cpuid, phys_cpu_present_map))
- reboot_cpu = boot_cpu_physical_apicid;
-
- reboot_smp = 0; /* use this as a flag to only go through this once*/
- /* re-run this function on the other CPUs
- it will fall though this section since we have
- cleared reboot_smp, and do the reboot if it is the
- correct CPU, otherwise it halts. */
- if (reboot_cpu != cpuid)
- smp_call_function((void *)machine_restart , NULL, 1, 0);
+ int reboot_cpu_id;
+
+ /* The boot cpu is always logical cpu 0 */
+ reboot_cpu_id = 0;
+
+ /* See if there has been given a command line override */
+ if ((reboot_cpu_id != -1) && (reboot_cpu < NR_CPUS) &&
+ cpu_isset(reboot_cpu, cpu_online_map)) {
+ reboot_cpu_id = reboot_cpu;
}
- /* if reboot_cpu is still -1, then we want a tradional reboot,
- and if we are not running on the reboot_cpu,, halt */
- if ((reboot_cpu != -1) && (cpuid != reboot_cpu)) {
- for (;;)
- __asm__ __volatile__ ("hlt");
+ /* Make certain the cpu I'm rebooting on is online */
+ if (!cpu_isset(reboot_cpu_id, cpu_online_map)) {
+ reboot_cpu_id = smp_processor_id();
}
- /*
- * Stop all CPUs and turn off local APICs and the IO-APIC, so
- * other OSs see a clean IRQ state.
+
+ /* Make certain I only run on the appropriate processor */
+ set_cpus_allowed(current, cpumask_of_cpu(reboot_cpu_id));
+
+ /* O.K. Now that I'm on the appropriate processor, stop
+ * all of the others, and disable their local APICs.
*/
+
smp_send_stop();
#endif /* CONFIG_SMP */
@@ -339,6 +309,11 @@ void machine_restart(char * __unused)
#ifdef CONFIG_X86_IO_APIC
disable_IO_APIC();
#endif
+}
+
+void machine_restart(char * __unused)
+{
+ machine_shutdown();
if (!reboot_thru_bios) {
if (efi_enabled) {
diff --git a/arch/i386/kernel/relocate_kernel.S b/arch/i386/kernel/relocate_kernel.S
new file mode 100644
index 00000000000..d312616effa
--- /dev/null
+++ b/arch/i386/kernel/relocate_kernel.S
@@ -0,0 +1,120 @@
+/*
+ * relocate_kernel.S - put the kernel image in place to boot
+ * Copyright (C) 2002-2004 Eric Biederman <ebiederm@xmission.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/linkage.h>
+
+ /*
+ * Must be relocatable PIC code callable as a C function, that once
+ * it starts can not use the previous processes stack.
+ */
+ .globl relocate_new_kernel
+relocate_new_kernel:
+ /* read the arguments and say goodbye to the stack */
+ movl 4(%esp), %ebx /* page_list */
+ movl 8(%esp), %ebp /* reboot_code_buffer */
+ movl 12(%esp), %edx /* start address */
+ movl 16(%esp), %ecx /* cpu_has_pae */
+
+ /* zero out flags, and disable interrupts */
+ pushl $0
+ popfl
+
+ /* set a new stack at the bottom of our page... */
+ lea 4096(%ebp), %esp
+
+ /* store the parameters back on the stack */
+ pushl %edx /* store the start address */
+
+ /* Set cr0 to a known state:
+ * 31 0 == Paging disabled
+ * 18 0 == Alignment check disabled
+ * 16 0 == Write protect disabled
+ * 3 0 == No task switch
+ * 2 0 == Don't do FP software emulation.
+ * 0 1 == Proctected mode enabled
+ */
+ movl %cr0, %eax
+ andl $~((1<<31)|(1<<18)|(1<<16)|(1<<3)|(1<<2)), %eax
+ orl $(1<<0), %eax
+ movl %eax, %cr0
+
+ /* clear cr4 if applicable */
+ testl %ecx, %ecx
+ jz 1f
+ /* Set cr4 to a known state:
+ * Setting everything to zero seems safe.
+ */
+ movl %cr4, %eax
+ andl $0, %eax
+ movl %eax, %cr4
+
+ jmp 1f
+1:
+
+ /* Flush the TLB (needed?) */
+ xorl %eax, %eax
+ movl %eax, %cr3
+
+ /* Do the copies */
+ movl %ebx, %ecx
+ jmp 1f
+
+0: /* top, read another word from the indirection page */
+ movl (%ebx), %ecx
+ addl $4, %ebx
+1:
+ testl $0x1, %ecx /* is it a destination page */
+ jz 2f
+ movl %ecx, %edi
+ andl $0xfffff000, %edi
+ jmp 0b
+2:
+ testl $0x2, %ecx /* is it an indirection page */
+ jz 2f
+ movl %ecx, %ebx
+ andl $0xfffff000, %ebx
+ jmp 0b
+2:
+ testl $0x4, %ecx /* is it the done indicator */
+ jz 2f
+ jmp 3f
+2:
+ testl $0x8, %ecx /* is it the source indicator */
+ jz 0b /* Ignore it otherwise */
+ movl %ecx, %esi /* For every source page do a copy */
+ andl $0xfffff000, %esi
+
+ movl $1024, %ecx
+ rep ; movsl
+ jmp 0b
+
+3:
+
+ /* To be certain of avoiding problems with self-modifying code
+ * I need to execute a serializing instruction here.
+ * So I flush the TLB, it's handy, and not processor dependent.
+ */
+ xorl %eax, %eax
+ movl %eax, %cr3
+
+ /* set all of the registers to known values */
+ /* leave %esp alone */
+
+ xorl %eax, %eax
+ xorl %ebx, %ebx
+ xorl %ecx, %ecx
+ xorl %edx, %edx
+ xorl %esi, %esi
+ xorl %edi, %edi
+ xorl %ebp, %ebp
+ ret
+relocate_new_kernel_end:
+
+ .globl relocate_new_kernel_size
+relocate_new_kernel_size:
+ .long relocate_new_kernel_end - relocate_new_kernel
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 945ec73163c..7306353c520 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -23,8 +23,10 @@
* This file handles the architecture-dependent parts of initialization
*/
+#include <linux/config.h>
#include <linux/sched.h>
#include <linux/mm.h>
+#include <linux/mmzone.h>
#include <linux/tty.h>
#include <linux/ioport.h>
#include <linux/acpi.h>
@@ -41,7 +43,12 @@
#include <linux/init.h>
#include <linux/edd.h>
#include <linux/nodemask.h>
+#include <linux/kexec.h>
+#include <linux/crash_dump.h>
+
#include <video/edid.h>
+
+#include <asm/apic.h>
#include <asm/e820.h>
#include <asm/mpspec.h>
#include <asm/setup.h>
@@ -53,12 +60,15 @@
#include "setup_arch_pre.h"
#include <bios_ebda.h>
+/* Forward Declaration. */
+void __init find_max_pfn(void);
+
/* This value is set up by the early boot code to point to the value
immediately after the boot time page tables. It contains a *physical*
address, and must not be in the .bss segment! */
unsigned long init_pg_tables_end __initdata = ~0UL;
-int disable_pse __initdata = 0;
+int disable_pse __devinitdata = 0;
/*
* Machine setup..
@@ -73,6 +83,7 @@ EXPORT_SYMBOL(efi_enabled);
struct cpuinfo_x86 new_cpu_data __initdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
/* common cpu data for all cpus */
struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
+EXPORT_SYMBOL(boot_cpu_data);
unsigned long mmu_cr4_features;
@@ -90,12 +101,18 @@ extern acpi_interrupt_flags acpi_sci_flags;
/* for MCA, but anyone else can use it if they want */
unsigned int machine_id;
+#ifdef CONFIG_MCA
+EXPORT_SYMBOL(machine_id);
+#endif
unsigned int machine_submodel_id;
unsigned int BIOS_revision;
unsigned int mca_pentium_flag;
/* For PCI or other memory-mapped resources */
unsigned long pci_mem_start = 0x10000000;
+#ifdef CONFIG_PCI
+EXPORT_SYMBOL(pci_mem_start);
+#endif
/* Boot loader ID as an integer, for the benefit of proc_dointvec */
int bootloader_type;
@@ -107,14 +124,26 @@ static unsigned int highmem_pages = -1;
* Setup options
*/
struct drive_info_struct { char dummy[32]; } drive_info;
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || \
+ defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE)
+EXPORT_SYMBOL(drive_info);
+#endif
struct screen_info screen_info;
+#ifdef CONFIG_VT
+EXPORT_SYMBOL(screen_info);
+#endif
struct apm_info apm_info;
+EXPORT_SYMBOL(apm_info);
struct sys_desc_table_struct {
unsigned short length;
unsigned char table[0];
};
struct edid_info edid_info;
struct ist_info ist_info;
+#if defined(CONFIG_X86_SPEEDSTEP_SMI) || \
+ defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE)
+EXPORT_SYMBOL(ist_info);
+#endif
struct e820map e820;
extern void early_cpu_init(void);
@@ -711,6 +740,15 @@ static void __init parse_cmdline_early (char ** cmdline_p)
if (to != command_line)
to--;
if (!memcmp(from+7, "exactmap", 8)) {
+#ifdef CONFIG_CRASH_DUMP
+ /* If we are doing a crash dump, we
+ * still need to know the real mem
+ * size before original memory map is
+ * reset.
+ */
+ find_max_pfn();
+ saved_max_pfn = max_pfn;
+#endif
from += 8+7;
e820.nr_map = 0;
userdef = 1;
@@ -814,6 +852,44 @@ static void __init parse_cmdline_early (char ** cmdline_p)
#endif /* CONFIG_X86_LOCAL_APIC */
#endif /* CONFIG_ACPI_BOOT */
+#ifdef CONFIG_X86_LOCAL_APIC
+ /* enable local APIC */
+ else if (!memcmp(from, "lapic", 5))
+ lapic_enable();
+
+ /* disable local APIC */
+ else if (!memcmp(from, "nolapic", 6))
+ lapic_disable();
+#endif /* CONFIG_X86_LOCAL_APIC */
+
+#ifdef CONFIG_KEXEC
+ /* crashkernel=size@addr specifies the location to reserve for
+ * a crash kernel. By reserving this memory we guarantee
+ * that linux never set's it up as a DMA target.
+ * Useful for holding code to do something appropriate
+ * after a kernel panic.
+ */
+ else if (!memcmp(from, "crashkernel=", 12)) {
+ unsigned long size, base;
+ size = memparse(from+12, &from);
+ if (*from == '@') {
+ base = memparse(from+1, &from);
+ /* FIXME: Do I want a sanity check
+ * to validate the memory range?
+ */
+ crashk_res.start = base;
+ crashk_res.end = base + size - 1;
+ }
+ }
+#endif
+#ifdef CONFIG_CRASH_DUMP
+ /* elfcorehdr= specifies the location of elf core header
+ * stored by the crashed kernel.
+ */
+ else if (!memcmp(from, "elfcorehdr=", 11))
+ elfcorehdr_addr = memparse(from+11, &from);
+#endif
+
/*
* highmem=size forces highmem to be exactly 'size' bytes.
* This works even on boxes that have no highmem otherwise.
@@ -1022,7 +1098,7 @@ static void __init reserve_ebda_region(void)
reserve_bootmem(addr, PAGE_SIZE);
}
-#ifndef CONFIG_DISCONTIGMEM
+#ifndef CONFIG_NEED_MULTIPLE_NODES
void __init setup_bootmem_allocator(void);
static unsigned long __init setup_memory(void)
{
@@ -1072,9 +1148,9 @@ void __init zone_sizes_init(void)
free_area_init(zones_size);
}
#else
-extern unsigned long setup_memory(void);
+extern unsigned long __init setup_memory(void);
extern void zone_sizes_init(void);
-#endif /* !CONFIG_DISCONTIGMEM */
+#endif /* !CONFIG_NEED_MULTIPLE_NODES */
void __init setup_bootmem_allocator(void)
{
@@ -1092,8 +1168,8 @@ void __init setup_bootmem_allocator(void)
* the (very unlikely) case of us accidentally initializing the
* bootmem allocator with an invalid RAM area.
*/
- reserve_bootmem(HIGH_MEMORY, (PFN_PHYS(min_low_pfn) +
- bootmap_size + PAGE_SIZE-1) - (HIGH_MEMORY));
+ reserve_bootmem(__PHYSICAL_START, (PFN_PHYS(min_low_pfn) +
+ bootmap_size + PAGE_SIZE-1) - (__PHYSICAL_START));
/*
* reserve physical page 0 - it's a special BIOS page on many boxes,
@@ -1149,6 +1225,11 @@ void __init setup_bootmem_allocator(void)
}
}
#endif
+#ifdef CONFIG_KEXEC
+ if (crashk_res.start != crashk_res.end)
+ reserve_bootmem(crashk_res.start,
+ crashk_res.end - crashk_res.start + 1);
+#endif
}
/*
@@ -1202,6 +1283,9 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat
*/
request_resource(res, code_resource);
request_resource(res, data_resource);
+#ifdef CONFIG_KEXEC
+ request_resource(res, &crashk_res);
+#endif
}
}
}
@@ -1475,6 +1559,7 @@ void __init setup_arch(char **cmdline_p)
#endif
paging_init();
remapped_pgdat_init();
+ sparse_init();
zone_sizes_init();
/*
@@ -1502,11 +1587,13 @@ void __init setup_arch(char **cmdline_p)
if (efi_enabled)
efi_map_memmap();
+#ifdef CONFIG_ACPI_BOOT
/*
* Parse the ACPI tables for possible boot-time SMP configuration.
*/
acpi_boot_table_init();
acpi_boot_init();
+#endif
#ifdef CONFIG_X86_LOCAL_APIC
if (smp_found_config)
diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
index ea46d028af0..89ef7adc63a 100644
--- a/arch/i386/kernel/signal.c
+++ b/arch/i386/kernel/signal.c
@@ -346,8 +346,8 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
extern void __user __kernel_sigreturn;
extern void __user __kernel_rt_sigreturn;
-static void setup_frame(int sig, struct k_sigaction *ka,
- sigset_t *set, struct pt_regs * regs)
+static int setup_frame(int sig, struct k_sigaction *ka,
+ sigset_t *set, struct pt_regs * regs)
{
void __user *restorer;
struct sigframe __user *frame;
@@ -429,13 +429,14 @@ static void setup_frame(int sig, struct k_sigaction *ka,
current->comm, current->pid, frame, regs->eip, frame->pretcode);
#endif
- return;
+ return 1;
give_sigsegv:
force_sigsegv(sig, current);
+ return 0;
}
-static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs * regs)
{
void __user *restorer;
@@ -522,20 +523,23 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
current->comm, current->pid, frame, regs->eip, frame->pretcode);
#endif
- return;
+ return 1;
give_sigsegv:
force_sigsegv(sig, current);
+ return 0;
}
/*
* OK, we're invoking a handler
*/
-static void
+static int
handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
sigset_t *oldset, struct pt_regs * regs)
{
+ int ret;
+
/* Are we from a system call? */
if (regs->orig_eax >= 0) {
/* If so, check system call restarting.. */
@@ -569,17 +573,19 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
/* Set up the stack frame */
if (ka->sa.sa_flags & SA_SIGINFO)
- setup_rt_frame(sig, ka, info, oldset, regs);
+ ret = setup_rt_frame(sig, ka, info, oldset, regs);
else
- setup_frame(sig, ka, oldset, regs);
+ ret = setup_frame(sig, ka, oldset, regs);
- if (!(ka->sa.sa_flags & SA_NODEFER)) {
+ if (ret && !(ka->sa.sa_flags & SA_NODEFER)) {
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
sigaddset(&current->blocked,sig);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
}
+
+ return ret;
}
/*
@@ -599,13 +605,11 @@ int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset)
* kernel mode. Just return without doing anything
* if so.
*/
- if ((regs->xcs & 3) != 3)
+ if (!user_mode(regs))
return 1;
- if (current->flags & PF_FREEZE) {
- refrigerator(0);
+ if (try_to_freeze())
goto no_signal;
- }
if (!oldset)
oldset = &current->blocked;
@@ -618,12 +622,11 @@ int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset)
* inside the kernel.
*/
if (unlikely(current->thread.debugreg[7])) {
- loaddebug(&current->thread, 7);
+ set_debugreg(current->thread.debugreg[7], 7);
}
/* Whee! Actually deliver the signal. */
- handle_signal(signr, &info, &ka, oldset, regs);
- return 1;
+ return handle_signal(signr, &info, &ka, oldset, regs);
}
no_signal:
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
index 6223c33ac91..cec4bde6716 100644
--- a/arch/i386/kernel/smp.c
+++ b/arch/i386/kernel/smp.c
@@ -19,6 +19,8 @@
#include <linux/mc146818rtc.h>
#include <linux/cache.h>
#include <linux/interrupt.h>
+#include <linux/cpu.h>
+#include <linux/module.h>
#include <asm/mtrr.h>
#include <asm/tlbflush.h>
@@ -163,7 +165,7 @@ void send_IPI_mask_bitmask(cpumask_t cpumask, int vector)
unsigned long flags;
local_irq_save(flags);
-
+ WARN_ON(mask & ~cpus_addr(cpu_online_map)[0]);
/*
* Wait for idle.
*/
@@ -345,21 +347,21 @@ out:
static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
unsigned long va)
{
- cpumask_t tmp;
/*
* A couple of (to be removed) sanity checks:
*
- * - we do not send IPIs to not-yet booted CPUs.
* - current CPU must not be in mask
* - mask must exist :)
*/
BUG_ON(cpus_empty(cpumask));
-
- cpus_and(tmp, cpumask, cpu_online_map);
- BUG_ON(!cpus_equal(cpumask, tmp));
BUG_ON(cpu_isset(smp_processor_id(), cpumask));
BUG_ON(!mm);
+ /* If a CPU which we ran on has gone down, OK. */
+ cpus_and(cpumask, cpumask, cpu_online_map);
+ if (cpus_empty(cpumask))
+ return;
+
/*
* i'm not happy about this global shared spinlock in the
* MM hot path, but we'll see how contended it is.
@@ -452,6 +454,7 @@ void flush_tlb_page(struct vm_area_struct * vma, unsigned long va)
preempt_enable();
}
+EXPORT_SYMBOL(flush_tlb_page);
static void do_flush_tlb_all(void* info)
{
@@ -474,6 +477,7 @@ void flush_tlb_all(void)
*/
void smp_send_reschedule(int cpu)
{
+ WARN_ON(cpu_is_offline(cpu));
send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR);
}
@@ -491,6 +495,16 @@ struct call_data_struct {
int wait;
};
+void lock_ipi_call_lock(void)
+{
+ spin_lock_irq(&call_lock);
+}
+
+void unlock_ipi_call_lock(void)
+{
+ spin_unlock_irq(&call_lock);
+}
+
static struct call_data_struct * call_data;
/*
@@ -514,10 +528,15 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
*/
{
struct call_data_struct data;
- int cpus = num_online_cpus()-1;
+ int cpus;
- if (!cpus)
+ /* Holding any lock stops cpus from going down. */
+ spin_lock(&call_lock);
+ cpus = num_online_cpus() - 1;
+ if (!cpus) {
+ spin_unlock(&call_lock);
return 0;
+ }
/* Can deadlock when called with interrupts disabled */
WARN_ON(irqs_disabled());
@@ -529,7 +548,6 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
if (wait)
atomic_set(&data.finished, 0);
- spin_lock(&call_lock);
call_data = &data;
mb();
@@ -547,6 +565,7 @@ int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
return 0;
}
+EXPORT_SYMBOL(smp_call_function);
static void stop_this_cpu (void * dummy)
{
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index cbea7ac582e..d66bf489a2e 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -44,6 +44,9 @@
#include <linux/smp_lock.h>
#include <linux/irq.h>
#include <linux/bootmem.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
+#include <linux/percpu.h>
#include <linux/delay.h>
#include <linux/mc146818rtc.h>
@@ -56,24 +59,46 @@
#include <smpboot_hooks.h>
/* Set if we find a B stepping CPU */
-static int __initdata smp_b_stepping;
+static int __devinitdata smp_b_stepping;
/* Number of siblings per CPU package */
int smp_num_siblings = 1;
-int phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */
+#ifdef CONFIG_X86_HT
+EXPORT_SYMBOL(smp_num_siblings);
+#endif
+
+/* Package ID of each logical CPU */
+int phys_proc_id[NR_CPUS] = {[0 ... NR_CPUS-1] = BAD_APICID};
EXPORT_SYMBOL(phys_proc_id);
-int cpu_core_id[NR_CPUS]; /* Core ID of each logical CPU */
+
+/* Core ID of each logical CPU */
+int cpu_core_id[NR_CPUS] = {[0 ... NR_CPUS-1] = BAD_APICID};
EXPORT_SYMBOL(cpu_core_id);
+cpumask_t cpu_sibling_map[NR_CPUS];
+EXPORT_SYMBOL(cpu_sibling_map);
+
+cpumask_t cpu_core_map[NR_CPUS];
+EXPORT_SYMBOL(cpu_core_map);
+
/* bitmap of online cpus */
cpumask_t cpu_online_map;
+EXPORT_SYMBOL(cpu_online_map);
cpumask_t cpu_callin_map;
cpumask_t cpu_callout_map;
+EXPORT_SYMBOL(cpu_callout_map);
static cpumask_t smp_commenced_mask;
+/* TSC's upper 32 bits can't be written in eariler CPU (before prescott), there
+ * is no way to resync one AP against BP. TBD: for prescott and above, we
+ * should use IA64's algorithm
+ */
+static int __devinitdata tsc_sync_disabled;
+
/* Per CPU bogomips and other parameters */
struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
+EXPORT_SYMBOL(cpu_data);
u8 x86_cpu_to_apicid[NR_CPUS] =
{ [0 ... NR_CPUS-1] = 0xff };
@@ -90,13 +115,16 @@ static int trampoline_exec;
static void map_cpu_to_logical_apicid(void);
+/* State of each CPU. */
+DEFINE_PER_CPU(int, cpu_state) = { 0 };
+
/*
* Currently trivial. Write the real->protected mode
* bootstrap into the page concerned. The caller
* has made sure it's suitably aligned.
*/
-static unsigned long __init setup_trampoline(void)
+static unsigned long __devinit setup_trampoline(void)
{
memcpy(trampoline_base, trampoline_data, trampoline_end - trampoline_data);
return virt_to_phys(trampoline_base);
@@ -126,7 +154,7 @@ void __init smp_alloc_memory(void)
* a given CPU
*/
-static void __init smp_store_cpu_info(int id)
+static void __devinit smp_store_cpu_info(int id)
{
struct cpuinfo_x86 *c = cpu_data + id;
@@ -199,7 +227,7 @@ static void __init synchronize_tsc_bp (void)
unsigned long long t0;
unsigned long long sum, avg;
long long delta;
- unsigned long one_usec;
+ unsigned int one_usec;
int buggy = 0;
printk(KERN_INFO "checking TSC synchronization across %u CPUs: ", num_booting_cpus());
@@ -320,7 +348,7 @@ extern void calibrate_delay(void);
static atomic_t init_deasserted;
-static void __init smp_callin(void)
+static void __devinit smp_callin(void)
{
int cpuid, phys_id;
unsigned long timeout;
@@ -405,16 +433,48 @@ static void __init smp_callin(void)
/*
* Synchronize the TSC with the BP
*/
- if (cpu_has_tsc && cpu_khz)
+ if (cpu_has_tsc && cpu_khz && !tsc_sync_disabled)
synchronize_tsc_ap();
}
static int cpucount;
+static inline void
+set_cpu_sibling_map(int cpu)
+{
+ int i;
+
+ if (smp_num_siblings > 1) {
+ for (i = 0; i < NR_CPUS; i++) {
+ if (!cpu_isset(i, cpu_callout_map))
+ continue;
+ if (cpu_core_id[cpu] == cpu_core_id[i]) {
+ cpu_set(i, cpu_sibling_map[cpu]);
+ cpu_set(cpu, cpu_sibling_map[i]);
+ }
+ }
+ } else {
+ cpu_set(cpu, cpu_sibling_map[cpu]);
+ }
+
+ if (current_cpu_data.x86_num_cores > 1) {
+ for (i = 0; i < NR_CPUS; i++) {
+ if (!cpu_isset(i, cpu_callout_map))
+ continue;
+ if (phys_proc_id[cpu] == phys_proc_id[i]) {
+ cpu_set(i, cpu_core_map[cpu]);
+ cpu_set(cpu, cpu_core_map[i]);
+ }
+ }
+ } else {
+ cpu_core_map[cpu] = cpu_sibling_map[cpu];
+ }
+}
+
/*
* Activate a secondary processor.
*/
-static void __init start_secondary(void *unused)
+static void __devinit start_secondary(void *unused)
{
/*
* Dont put anything before smp_callin(), SMP
@@ -437,7 +497,23 @@ static void __init start_secondary(void *unused)
* the local TLBs too.
*/
local_flush_tlb();
+
+ /* This must be done before setting cpu_online_map */
+ set_cpu_sibling_map(raw_smp_processor_id());
+ wmb();
+
+ /*
+ * We need to hold call_lock, so there is no inconsistency
+ * between the time smp_call_function() determines number of
+ * IPI receipients, and the time when the determination is made
+ * for which cpus receive the IPI. Holding this
+ * lock helps us to not include this cpu in a currently in progress
+ * smp_call_function().
+ */
+ lock_ipi_call_lock();
cpu_set(smp_processor_id(), cpu_online_map);
+ unlock_ipi_call_lock();
+ per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
/* We can take interrupts now: we're officially "up". */
local_irq_enable();
@@ -452,7 +528,7 @@ static void __init start_secondary(void *unused)
* from the task structure
* This function must not return.
*/
-void __init initialize_secondary(void)
+void __devinit initialize_secondary(void)
{
/*
* We don't actually need to load the full TSS,
@@ -566,7 +642,7 @@ static inline void __inquire_remote_apic(int apicid)
* INIT, INIT, STARTUP sequence will reset the chip hard for us, and this
* won't ... remember to clear down the APIC, etc later.
*/
-static int __init
+static int __devinit
wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
{
unsigned long send_status = 0, accept_status = 0;
@@ -612,7 +688,7 @@ wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
#endif /* WAKE_SECONDARY_VIA_NMI */
#ifdef WAKE_SECONDARY_VIA_INIT
-static int __init
+static int __devinit
wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
{
unsigned long send_status = 0, accept_status = 0;
@@ -747,8 +823,43 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
#endif /* WAKE_SECONDARY_VIA_INIT */
extern cpumask_t cpu_initialized;
+static inline int alloc_cpu_id(void)
+{
+ cpumask_t tmp_map;
+ int cpu;
+ cpus_complement(tmp_map, cpu_present_map);
+ cpu = first_cpu(tmp_map);
+ if (cpu >= NR_CPUS)
+ return -ENODEV;
+ return cpu;
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+static struct task_struct * __devinitdata cpu_idle_tasks[NR_CPUS];
+static inline struct task_struct * alloc_idle_task(int cpu)
+{
+ struct task_struct *idle;
+
+ if ((idle = cpu_idle_tasks[cpu]) != NULL) {
+ /* initialize thread_struct. we really want to avoid destroy
+ * idle tread
+ */
+ idle->thread.esp = (unsigned long)(((struct pt_regs *)
+ (THREAD_SIZE + (unsigned long) idle->thread_info)) - 1);
+ init_idle(idle, cpu);
+ return idle;
+ }
+ idle = fork_idle(cpu);
-static int __init do_boot_cpu(int apicid)
+ if (!IS_ERR(idle))
+ cpu_idle_tasks[cpu] = idle;
+ return idle;
+}
+#else
+#define alloc_idle_task(cpu) fork_idle(cpu)
+#endif
+
+static int __devinit do_boot_cpu(int apicid, int cpu)
/*
* NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
* (ie clustered apic addressing mode), this is a LOGICAL apic ID.
@@ -757,16 +868,17 @@ static int __init do_boot_cpu(int apicid)
{
struct task_struct *idle;
unsigned long boot_error;
- int timeout, cpu;
+ int timeout;
unsigned long start_eip;
unsigned short nmi_high = 0, nmi_low = 0;
- cpu = ++cpucount;
+ ++cpucount;
+
/*
* We can't use kernel_thread since we must avoid to
* reschedule the child.
*/
- idle = fork_idle(cpu);
+ idle = alloc_idle_task(cpu);
if (IS_ERR(idle))
panic("failed fork for CPU %d", cpu);
idle->thread.eip = (unsigned long) start_secondary;
@@ -833,13 +945,16 @@ static int __init do_boot_cpu(int apicid)
inquire_remote_apic(apicid);
}
}
- x86_cpu_to_apicid[cpu] = apicid;
+
if (boot_error) {
/* Try to put things back the way they were before ... */
unmap_cpu_to_logical_apicid(cpu);
cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */
cpu_clear(cpu, cpu_initialized); /* was set by cpu_init() */
cpucount--;
+ } else {
+ x86_cpu_to_apicid[cpu] = apicid;
+ cpu_set(cpu, cpu_present_map);
}
/* mark "stuck" area as not stuck */
@@ -848,6 +963,75 @@ static int __init do_boot_cpu(int apicid)
return boot_error;
}
+#ifdef CONFIG_HOTPLUG_CPU
+void cpu_exit_clear(void)
+{
+ int cpu = raw_smp_processor_id();
+
+ idle_task_exit();
+
+ cpucount --;
+ cpu_uninit();
+ irq_ctx_exit(cpu);
+
+ cpu_clear(cpu, cpu_callout_map);
+ cpu_clear(cpu, cpu_callin_map);
+ cpu_clear(cpu, cpu_present_map);
+
+ cpu_clear(cpu, smp_commenced_mask);
+ unmap_cpu_to_logical_apicid(cpu);
+}
+
+struct warm_boot_cpu_info {
+ struct completion *complete;
+ int apicid;
+ int cpu;
+};
+
+static void __devinit do_warm_boot_cpu(void *p)
+{
+ struct warm_boot_cpu_info *info = p;
+ do_boot_cpu(info->apicid, info->cpu);
+ complete(info->complete);
+}
+
+int __devinit smp_prepare_cpu(int cpu)
+{
+ DECLARE_COMPLETION(done);
+ struct warm_boot_cpu_info info;
+ struct work_struct task;
+ int apicid, ret;
+
+ lock_cpu_hotplug();
+ apicid = x86_cpu_to_apicid[cpu];
+ if (apicid == BAD_APICID) {
+ ret = -ENODEV;
+ goto exit;
+ }
+
+ info.complete = &done;
+ info.apicid = apicid;
+ info.cpu = cpu;
+ INIT_WORK(&task, do_warm_boot_cpu, &info);
+
+ tsc_sync_disabled = 1;
+
+ /* init low mem mapping */
+ memcpy(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
+ sizeof(swapper_pg_dir[0]) * KERNEL_PGD_PTRS);
+ flush_tlb_all();
+ schedule_work(&task);
+ wait_for_completion(&done);
+
+ tsc_sync_disabled = 0;
+ zap_low_mappings();
+ ret = 0;
+exit:
+ unlock_cpu_hotplug();
+ return ret;
+}
+#endif
+
static void smp_tune_scheduling (void)
{
unsigned long cachesize; /* kB */
@@ -885,9 +1069,9 @@ static void smp_tune_scheduling (void)
static int boot_cpu_logical_apicid;
/* Where the IO area was mapped on multiquad, always 0 otherwise */
void *xquad_portio;
-
-cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
-cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
+#ifdef CONFIG_X86_NUMAQ
+EXPORT_SYMBOL(xquad_portio);
+#endif
static void __init smp_boot_cpus(unsigned int max_cpus)
{
@@ -1000,7 +1184,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
if (max_cpus <= cpucount+1)
continue;
- if (do_boot_cpu(apicid))
+ if (((cpu = alloc_cpu_id()) <= 0) || do_boot_cpu(apicid, cpu))
printk("CPU #%d not responding - cannot use it.\n",
apicid);
else
@@ -1052,42 +1236,8 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
cpus_clear(cpu_core_map[cpu]);
}
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
- struct cpuinfo_x86 *c = cpu_data + cpu;
- int siblings = 0;
- int i;
- if (!cpu_isset(cpu, cpu_callout_map))
- continue;
-
- if (smp_num_siblings > 1) {
- for (i = 0; i < NR_CPUS; i++) {
- if (!cpu_isset(i, cpu_callout_map))
- continue;
- if (cpu_core_id[cpu] == cpu_core_id[i]) {
- siblings++;
- cpu_set(i, cpu_sibling_map[cpu]);
- }
- }
- } else {
- siblings++;
- cpu_set(cpu, cpu_sibling_map[cpu]);
- }
-
- if (siblings != smp_num_siblings)
- printk(KERN_WARNING "WARNING: %d siblings found for CPU%d, should be %d\n", siblings, cpu, smp_num_siblings);
-
- if (c->x86_num_cores > 1) {
- for (i = 0; i < NR_CPUS; i++) {
- if (!cpu_isset(i, cpu_callout_map))
- continue;
- if (phys_proc_id[cpu] == phys_proc_id[i]) {
- cpu_set(i, cpu_core_map[cpu]);
- }
- }
- } else {
- cpu_core_map[cpu] = cpu_sibling_map[cpu];
- }
- }
+ cpu_set(0, cpu_sibling_map[0]);
+ cpu_set(0, cpu_core_map[0]);
smpboot_setup_io_apic();
@@ -1104,6 +1254,9 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
who understands all this stuff should rewrite it properly. --RR 15/Jul/02 */
void __init smp_prepare_cpus(unsigned int max_cpus)
{
+ smp_commenced_mask = cpumask_of_cpu(0);
+ cpu_callin_map = cpumask_of_cpu(0);
+ mb();
smp_boot_cpus(max_cpus);
}
@@ -1111,23 +1264,98 @@ void __devinit smp_prepare_boot_cpu(void)
{
cpu_set(smp_processor_id(), cpu_online_map);
cpu_set(smp_processor_id(), cpu_callout_map);
+ cpu_set(smp_processor_id(), cpu_present_map);
+ per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
}
-int __devinit __cpu_up(unsigned int cpu)
+#ifdef CONFIG_HOTPLUG_CPU
+static void
+remove_siblinginfo(int cpu)
{
- /* This only works at boot for x86. See "rewrite" above. */
- if (cpu_isset(cpu, smp_commenced_mask)) {
- local_irq_enable();
- return -ENOSYS;
+ int sibling;
+
+ for_each_cpu_mask(sibling, cpu_sibling_map[cpu])
+ cpu_clear(cpu, cpu_sibling_map[sibling]);
+ for_each_cpu_mask(sibling, cpu_core_map[cpu])
+ cpu_clear(cpu, cpu_core_map[sibling]);
+ cpus_clear(cpu_sibling_map[cpu]);
+ cpus_clear(cpu_core_map[cpu]);
+ phys_proc_id[cpu] = BAD_APICID;
+ cpu_core_id[cpu] = BAD_APICID;
+}
+
+int __cpu_disable(void)
+{
+ cpumask_t map = cpu_online_map;
+ int cpu = smp_processor_id();
+
+ /*
+ * Perhaps use cpufreq to drop frequency, but that could go
+ * into generic code.
+ *
+ * We won't take down the boot processor on i386 due to some
+ * interrupts only being able to be serviced by the BSP.
+ * Especially so if we're not using an IOAPIC -zwane
+ */
+ if (cpu == 0)
+ return -EBUSY;
+
+ /* We enable the timer again on the exit path of the death loop */
+ disable_APIC_timer();
+ /* Allow any queued timer interrupts to get serviced */
+ local_irq_enable();
+ mdelay(1);
+ local_irq_disable();
+
+ remove_siblinginfo(cpu);
+
+ cpu_clear(cpu, map);
+ fixup_irqs(map);
+ /* It's now safe to remove this processor from the online map */
+ cpu_clear(cpu, cpu_online_map);
+ return 0;
+}
+
+void __cpu_die(unsigned int cpu)
+{
+ /* We don't do anything here: idle task is faking death itself. */
+ unsigned int i;
+
+ for (i = 0; i < 10; i++) {
+ /* They ack this in play_dead by setting CPU_DEAD */
+ if (per_cpu(cpu_state, cpu) == CPU_DEAD) {
+ printk ("CPU %d is now offline\n", cpu);
+ return;
+ }
+ current->state = TASK_UNINTERRUPTIBLE;
+ schedule_timeout(HZ/10);
}
+ printk(KERN_ERR "CPU %u didn't die...\n", cpu);
+}
+#else /* ... !CONFIG_HOTPLUG_CPU */
+int __cpu_disable(void)
+{
+ return -ENOSYS;
+}
+void __cpu_die(unsigned int cpu)
+{
+ /* We said "no" in __cpu_disable */
+ BUG();
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
+int __devinit __cpu_up(unsigned int cpu)
+{
/* In case one didn't come up */
if (!cpu_isset(cpu, cpu_callin_map)) {
+ printk(KERN_DEBUG "skipping cpu%d, didn't come online\n", cpu);
local_irq_enable();
return -EIO;
}
local_irq_enable();
+ per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
/* Unleash the CPU! */
cpu_set(cpu, smp_commenced_mask);
while (!cpu_isset(cpu, cpu_online_map))
@@ -1141,10 +1369,12 @@ void __init smp_cpus_done(unsigned int max_cpus)
setup_ioapic_dest();
#endif
zap_low_mappings();
+#ifndef CONFIG_HOTPLUG_CPU
/*
* Disable executability of the SMP trampoline:
*/
set_kernel_exec((unsigned long)trampoline_base, trampoline_exec);
+#endif
}
void __init smp_intr_init(void)
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S
index 6cd1ed311f0..442a6e937b1 100644
--- a/arch/i386/kernel/syscall_table.S
+++ b/arch/i386/kernel/syscall_table.S
@@ -251,7 +251,7 @@ ENTRY(sys_call_table)
.long sys_io_submit
.long sys_io_cancel
.long sys_fadvise64 /* 250 */
- .long sys_ni_syscall
+ .long sys_set_zone_reclaim
.long sys_exit_group
.long sys_lookup_dcookie
.long sys_epoll_create
@@ -283,7 +283,7 @@ ENTRY(sys_call_table)
.long sys_mq_timedreceive /* 280 */
.long sys_mq_notify
.long sys_mq_getsetattr
- .long sys_ni_syscall /* reserved for kexec */
+ .long sys_kexec_load
.long sys_waitid
.long sys_ni_syscall /* 285 */ /* available */
.long sys_add_key
diff --git a/arch/i386/kernel/sysenter.c b/arch/i386/kernel/sysenter.c
index 960d8bd137d..0bada1870bd 100644
--- a/arch/i386/kernel/sysenter.c
+++ b/arch/i386/kernel/sysenter.c
@@ -21,11 +21,16 @@
extern asmlinkage void sysenter_entry(void);
-void enable_sep_cpu(void *info)
+void enable_sep_cpu(void)
{
int cpu = get_cpu();
struct tss_struct *tss = &per_cpu(init_tss, cpu);
+ if (!boot_cpu_has(X86_FEATURE_SEP)) {
+ put_cpu();
+ return;
+ }
+
tss->ss1 = __KERNEL_CS;
tss->esp1 = sizeof(struct tss_struct) + (unsigned long) tss;
wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
@@ -41,7 +46,7 @@ void enable_sep_cpu(void *info)
extern const char vsyscall_int80_start, vsyscall_int80_end;
extern const char vsyscall_sysenter_start, vsyscall_sysenter_end;
-static int __init sysenter_setup(void)
+int __init sysenter_setup(void)
{
void *page = (void *)get_zeroed_page(GFP_ATOMIC);
@@ -58,8 +63,5 @@ static int __init sysenter_setup(void)
&vsyscall_sysenter_start,
&vsyscall_sysenter_end - &vsyscall_sysenter_start);
- on_each_cpu(enable_sep_cpu, NULL, 1, 1);
return 0;
}
-
-__initcall(sysenter_setup);
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index a0dcb7c87c3..e68d9fdb075 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -77,11 +77,13 @@ u64 jiffies_64 = INITIAL_JIFFIES;
EXPORT_SYMBOL(jiffies_64);
-unsigned long cpu_khz; /* Detected as we calibrate the TSC */
+unsigned int cpu_khz; /* Detected as we calibrate the TSC */
+EXPORT_SYMBOL(cpu_khz);
extern unsigned long wall_jiffies;
DEFINE_SPINLOCK(rtc_lock);
+EXPORT_SYMBOL(rtc_lock);
DEFINE_SPINLOCK(i8253_lock);
EXPORT_SYMBOL(i8253_lock);
@@ -324,6 +326,8 @@ unsigned long get_cmos_time(void)
return retval;
}
+EXPORT_SYMBOL(get_cmos_time);
+
static void sync_cmos_clock(unsigned long dummy);
static struct timer_list sync_cmos_timer =
diff --git a/arch/i386/kernel/time_hpet.c b/arch/i386/kernel/time_hpet.c
index 10a0cbb88e7..658c0629ba6 100644
--- a/arch/i386/kernel/time_hpet.c
+++ b/arch/i386/kernel/time_hpet.c
@@ -50,7 +50,7 @@ static void hpet_writel(unsigned long d, unsigned long a)
* comparator value and continue. Next tick can be caught by checking
* for a change in the comparator value. Used in apic.c.
*/
-static void __init wait_hpet_tick(void)
+static void __devinit wait_hpet_tick(void)
{
unsigned int start_cmp_val, end_cmp_val;
diff --git a/arch/i386/kernel/timers/common.c b/arch/i386/kernel/timers/common.c
index f7f90005e22..8163fe0cf1f 100644
--- a/arch/i386/kernel/timers/common.c
+++ b/arch/i386/kernel/timers/common.c
@@ -6,6 +6,7 @@
#include <linux/timex.h>
#include <linux/errno.h>
#include <linux/jiffies.h>
+#include <linux/module.h>
#include <asm/io.h>
#include <asm/timer.h>
@@ -24,7 +25,7 @@
#define CALIBRATE_TIME (5 * 1000020/HZ)
-unsigned long __init calibrate_tsc(void)
+unsigned long calibrate_tsc(void)
{
mach_prepare_counter();
@@ -85,7 +86,7 @@ bad_ctc:
#define CALIBRATE_CNT_HPET (5 * hpet_tick)
#define CALIBRATE_TIME_HPET (5 * KERNEL_TICK_USEC)
-unsigned long __init calibrate_tsc_hpet(unsigned long *tsc_hpet_quotient_ptr)
+unsigned long __devinit calibrate_tsc_hpet(unsigned long *tsc_hpet_quotient_ptr)
{
unsigned long tsc_startlow, tsc_starthigh;
unsigned long tsc_endlow, tsc_endhigh;
@@ -138,8 +139,17 @@ bad_calibration:
}
#endif
+
+unsigned long read_timer_tsc(void)
+{
+ unsigned long retval;
+ rdtscl(retval);
+ return retval;
+}
+
+
/* calculate cpu_khz */
-void __init init_cpu_khz(void)
+void init_cpu_khz(void)
{
if (cpu_has_tsc) {
unsigned long tsc_quotient = calibrate_tsc();
@@ -153,8 +163,10 @@ void __init init_cpu_khz(void)
:"=a" (cpu_khz), "=d" (edx)
:"r" (tsc_quotient),
"0" (eax), "1" (edx));
- printk("Detected %lu.%03lu MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000);
+ printk("Detected %u.%03u MHz processor.\n",
+ cpu_khz / 1000, cpu_khz % 1000);
}
}
}
}
+
diff --git a/arch/i386/kernel/timers/timer.c b/arch/i386/kernel/timers/timer.c
index a3d6a288088..7e39ed8e33f 100644
--- a/arch/i386/kernel/timers/timer.c
+++ b/arch/i386/kernel/timers/timer.c
@@ -64,3 +64,12 @@ struct timer_opts* __init select_timer(void)
panic("select_timer: Cannot find a suitable timer\n");
return NULL;
}
+
+int read_current_timer(unsigned long *timer_val)
+{
+ if (cur_timer->read_timer) {
+ *timer_val = cur_timer->read_timer();
+ return 0;
+ }
+ return -1;
+}
diff --git a/arch/i386/kernel/timers/timer_hpet.c b/arch/i386/kernel/timers/timer_hpet.c
index f778f471a09..d766e0963ac 100644
--- a/arch/i386/kernel/timers/timer_hpet.c
+++ b/arch/i386/kernel/timers/timer_hpet.c
@@ -158,7 +158,7 @@ static int __init init_hpet(char* override)
{ unsigned long eax=0, edx=1000;
ASM_DIV64_REG(cpu_khz, edx, tsc_quotient,
eax, edx);
- printk("Detected %lu.%03lu MHz processor.\n",
+ printk("Detected %u.%03u MHz processor.\n",
cpu_khz / 1000, cpu_khz % 1000);
}
set_cyc2ns_scale(cpu_khz/1000);
@@ -186,6 +186,7 @@ static struct timer_opts timer_hpet = {
.get_offset = get_offset_hpet,
.monotonic_clock = monotonic_clock_hpet,
.delay = delay_hpet,
+ .read_timer = read_timer_tsc,
};
struct init_timer_opts __initdata timer_hpet_init = {
diff --git a/arch/i386/kernel/timers/timer_pm.c b/arch/i386/kernel/timers/timer_pm.c
index d77f22030fe..4ef20e66349 100644
--- a/arch/i386/kernel/timers/timer_pm.c
+++ b/arch/i386/kernel/timers/timer_pm.c
@@ -246,6 +246,7 @@ static struct timer_opts timer_pmtmr = {
.get_offset = get_offset_pmtmr,
.monotonic_clock = monotonic_clock_pmtmr,
.delay = delay_pmtmr,
+ .read_timer = read_timer_tsc,
};
struct init_timer_opts __initdata timer_pmtmr_init = {
diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c
index 7926d967be0..f46e625bab6 100644
--- a/arch/i386/kernel/timers/timer_tsc.c
+++ b/arch/i386/kernel/timers/timer_tsc.c
@@ -33,7 +33,7 @@ static struct timer_opts timer_tsc;
static inline void cpufreq_delayed_get(void);
-int tsc_disable __initdata = 0;
+int tsc_disable __devinitdata = 0;
extern spinlock_t i8253_lock;
@@ -256,7 +256,7 @@ static unsigned long loops_per_jiffy_ref = 0;
#ifndef CONFIG_SMP
static unsigned long fast_gettimeoffset_ref = 0;
-static unsigned long cpu_khz_ref = 0;
+static unsigned int cpu_khz_ref = 0;
#endif
static int
@@ -320,6 +320,26 @@ core_initcall(cpufreq_tsc);
static inline void cpufreq_delayed_get(void) { return; }
#endif
+int recalibrate_cpu_khz(void)
+{
+#ifndef CONFIG_SMP
+ unsigned int cpu_khz_old = cpu_khz;
+
+ if (cpu_has_tsc) {
+ init_cpu_khz();
+ cpu_data[0].loops_per_jiffy =
+ cpufreq_scale(cpu_data[0].loops_per_jiffy,
+ cpu_khz_old,
+ cpu_khz);
+ return 0;
+ } else
+ return -ENODEV;
+#else
+ return -ENODEV;
+#endif
+}
+EXPORT_SYMBOL(recalibrate_cpu_khz);
+
static void mark_offset_tsc(void)
{
unsigned long lost,delay;
@@ -514,7 +534,8 @@ static int __init init_tsc(char* override)
:"=a" (cpu_khz), "=d" (edx)
:"r" (tsc_quotient),
"0" (eax), "1" (edx));
- printk("Detected %lu.%03lu MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000);
+ printk("Detected %u.%03u MHz processor.\n",
+ cpu_khz / 1000, cpu_khz % 1000);
}
set_cyc2ns_scale(cpu_khz/1000);
return 0;
@@ -552,6 +573,7 @@ static struct timer_opts timer_tsc = {
.get_offset = get_offset_tsc,
.monotonic_clock = monotonic_clock_tsc,
.delay = delay_tsc,
+ .read_timer = read_timer_tsc,
};
struct init_timer_opts __initdata timer_tsc_init = {
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 00c63419c06..a61f33d06ea 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -27,6 +27,7 @@
#include <linux/ptrace.h>
#include <linux/utsname.h>
#include <linux/kprobes.h>
+#include <linux/kexec.h>
#ifdef CONFIG_EISA
#include <linux/ioport.h>
@@ -104,6 +105,7 @@ int register_die_notifier(struct notifier_block *nb)
spin_unlock_irqrestore(&die_notifier_lock, flags);
return err;
}
+EXPORT_SYMBOL(register_die_notifier);
static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
{
@@ -209,7 +211,7 @@ void show_registers(struct pt_regs *regs)
esp = (unsigned long) (&regs->esp);
ss = __KERNEL_DS;
- if (regs->xcs & 3) {
+ if (user_mode(regs)) {
in_kernel = 0;
esp = regs->esp;
ss = regs->xss & 0xffff;
@@ -233,22 +235,22 @@ void show_registers(struct pt_regs *regs)
* time of the fault..
*/
if (in_kernel) {
- u8 *eip;
+ u8 __user *eip;
printk("\nStack: ");
show_stack(NULL, (unsigned long*)esp);
printk("Code: ");
- eip = (u8 *)regs->eip - 43;
+ eip = (u8 __user *)regs->eip - 43;
for (i = 0; i < 64; i++, eip++) {
unsigned char c;
- if (eip < (u8 *)PAGE_OFFSET || __get_user(c, eip)) {
+ if (eip < (u8 __user *)PAGE_OFFSET || __get_user(c, eip)) {
printk(" Bad EIP value.");
break;
}
- if (eip == (u8 *)regs->eip)
+ if (eip == (u8 __user *)regs->eip)
printk("<%02x> ", c);
else
printk("%02x ", c);
@@ -265,20 +267,20 @@ static void handle_BUG(struct pt_regs *regs)
char c;
unsigned long eip;
- if (regs->xcs & 3)
+ if (user_mode(regs))
goto no_bug; /* Not in kernel */
eip = regs->eip;
if (eip < PAGE_OFFSET)
goto no_bug;
- if (__get_user(ud2, (unsigned short *)eip))
+ if (__get_user(ud2, (unsigned short __user *)eip))
goto no_bug;
if (ud2 != 0x0b0f)
goto no_bug;
- if (__get_user(line, (unsigned short *)(eip + 2)))
+ if (__get_user(line, (unsigned short __user *)(eip + 2)))
goto bug;
- if (__get_user(file, (char **)(eip + 4)) ||
+ if (__get_user(file, (char * __user *)(eip + 4)) ||
(unsigned long)file < PAGE_OFFSET || __get_user(c, file))
file = "<bad filename>";
@@ -293,6 +295,9 @@ bug:
printk("Kernel BUG\n");
}
+/* This is gone through when something in the kernel
+ * has done something bad and is about to be terminated.
+*/
void die(const char * str, struct pt_regs * regs, long err)
{
static struct {
@@ -306,7 +311,7 @@ void die(const char * str, struct pt_regs * regs, long err)
};
static int die_counter;
- if (die.lock_owner != _smp_processor_id()) {
+ if (die.lock_owner != raw_smp_processor_id()) {
console_verbose();
spin_lock_irq(&die.lock);
die.lock_owner = smp_processor_id();
@@ -340,6 +345,10 @@ void die(const char * str, struct pt_regs * regs, long err)
bust_spinlocks(0);
die.lock_owner = -1;
spin_unlock_irq(&die.lock);
+
+ if (kexec_should_crash(current))
+ crash_kexec(regs);
+
if (in_interrupt())
panic("Fatal exception in interrupt");
@@ -353,26 +362,27 @@ void die(const char * str, struct pt_regs * regs, long err)
static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
{
- if (!(regs->eflags & VM_MASK) && !(3 & regs->xcs))
+ if (!user_mode_vm(regs))
die(str, regs, err);
}
static void do_trap(int trapnr, int signr, char *str, int vm86,
struct pt_regs * regs, long error_code, siginfo_t *info)
{
+ struct task_struct *tsk = current;
+ tsk->thread.error_code = error_code;
+ tsk->thread.trap_no = trapnr;
+
if (regs->eflags & VM_MASK) {
if (vm86)
goto vm86_trap;
goto trap_signal;
}
- if (!(regs->xcs & 3))
+ if (!user_mode(regs))
goto kernel_trap;
trap_signal: {
- struct task_struct *tsk = current;
- tsk->thread.error_code = error_code;
- tsk->thread.trap_no = trapnr;
if (info)
force_sig_info(signr, info, tsk);
else
@@ -485,10 +495,13 @@ fastcall void do_general_protection(struct pt_regs * regs, long error_code)
}
put_cpu();
+ current->thread.error_code = error_code;
+ current->thread.trap_no = 13;
+
if (regs->eflags & VM_MASK)
goto gp_in_vm86;
- if (!(regs->xcs & 3))
+ if (!user_mode(regs))
goto gp_in_kernel;
current->thread.error_code = error_code;
@@ -569,6 +582,15 @@ void die_nmi (struct pt_regs *regs, const char *msg)
console_silent();
spin_unlock(&nmi_print_lock);
bust_spinlocks(0);
+
+ /* If we are in kernel we are probably nested up pretty bad
+ * and might aswell get out now while we still can.
+ */
+ if (!user_mode(regs)) {
+ current->thread.trap_no = 2;
+ crash_kexec(regs);
+ }
+
do_exit(SIGSEGV);
}
@@ -624,6 +646,14 @@ fastcall void do_nmi(struct pt_regs * regs, long error_code)
nmi_enter();
cpu = smp_processor_id();
+
+#ifdef CONFIG_HOTPLUG_CPU
+ if (!cpu_online(cpu)) {
+ nmi_exit();
+ return;
+ }
+#endif
+
++nmi_count(cpu);
if (!nmi_callback(regs, cpu))
@@ -636,11 +666,13 @@ void set_nmi_callback(nmi_callback_t callback)
{
nmi_callback = callback;
}
+EXPORT_SYMBOL_GPL(set_nmi_callback);
void unset_nmi_callback(void)
{
nmi_callback = dummy_nmi_callback;
}
+EXPORT_SYMBOL_GPL(unset_nmi_callback);
#ifdef CONFIG_KPROBES
fastcall void do_int3(struct pt_regs *regs, long error_code)
@@ -682,7 +714,7 @@ fastcall void do_debug(struct pt_regs * regs, long error_code)
unsigned int condition;
struct task_struct *tsk = current;
- __asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
+ get_debugreg(condition, 6);
if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
SIGTRAP) == NOTIFY_STOP)
@@ -713,7 +745,7 @@ fastcall void do_debug(struct pt_regs * regs, long error_code)
* check for kernel mode by just checking the CPL
* of CS.
*/
- if ((regs->xcs & 3) == 0)
+ if (!user_mode(regs))
goto clear_TF_reenable;
}
@@ -724,9 +756,7 @@ fastcall void do_debug(struct pt_regs * regs, long error_code)
* the signal is delivered.
*/
clear_dr7:
- __asm__("movl %0,%%db7"
- : /* no output */
- : "r" (0));
+ set_debugreg(0, 7);
return;
debug_vm86:
@@ -871,9 +901,9 @@ fastcall void do_simd_coprocessor_error(struct pt_regs * regs,
error_code);
return;
}
- die_if_kernel("cache flush denied", regs, error_code);
current->thread.trap_no = 19;
current->thread.error_code = error_code;
+ die_if_kernel("cache flush denied", regs, error_code);
force_sig(SIGSEGV, current);
}
}
diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S
index e0512cc8bea..7e01a528a83 100644
--- a/arch/i386/kernel/vmlinux.lds.S
+++ b/arch/i386/kernel/vmlinux.lds.S
@@ -2,20 +2,23 @@
* Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
*/
+#define LOAD_OFFSET __PAGE_OFFSET
+
#include <asm-generic/vmlinux.lds.h>
#include <asm/thread_info.h>
#include <asm/page.h>
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
-ENTRY(startup_32)
+ENTRY(phys_startup_32)
jiffies = jiffies_64;
SECTIONS
{
- . = __PAGE_OFFSET + 0x100000;
+ . = __KERNEL_START;
+ phys_startup_32 = startup_32 - LOAD_OFFSET;
/* read-only */
_text = .; /* Text and read-only data */
- .text : {
+ .text : AT(ADDR(.text) - LOAD_OFFSET) {
*(.text)
SCHED_TEXT
LOCK_TEXT
@@ -27,49 +30,55 @@ SECTIONS
. = ALIGN(16); /* Exception table */
__start___ex_table = .;
- __ex_table : { *(__ex_table) }
+ __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { *(__ex_table) }
__stop___ex_table = .;
RODATA
/* writeable */
- .data : { /* Data */
+ .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */
*(.data)
CONSTRUCTORS
}
. = ALIGN(4096);
__nosave_begin = .;
- .data_nosave : { *(.data.nosave) }
+ .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { *(.data.nosave) }
. = ALIGN(4096);
__nosave_end = .;
. = ALIGN(4096);
- .data.page_aligned : { *(.data.idt) }
+ .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
+ *(.data.idt)
+ }
. = ALIGN(32);
- .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+ .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
+ *(.data.cacheline_aligned)
+ }
_edata = .; /* End of data section */
. = ALIGN(THREAD_SIZE); /* init_task */
- .data.init_task : { *(.data.init_task) }
+ .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
+ *(.data.init_task)
+ }
/* will be freed after init */
. = ALIGN(4096); /* Init code and data */
__init_begin = .;
- .init.text : {
+ .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
_sinittext = .;
*(.init.text)
_einittext = .;
}
- .init.data : { *(.init.data) }
+ .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { *(.init.data) }
. = ALIGN(16);
__setup_start = .;
- .init.setup : { *(.init.setup) }
+ .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) { *(.init.setup) }
__setup_end = .;
__initcall_start = .;
- .initcall.init : {
+ .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
*(.initcall1.init)
*(.initcall2.init)
*(.initcall3.init)
@@ -80,33 +89,41 @@ SECTIONS
}
__initcall_end = .;
__con_initcall_start = .;
- .con_initcall.init : { *(.con_initcall.init) }
+ .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) {
+ *(.con_initcall.init)
+ }
__con_initcall_end = .;
SECURITY_INIT
. = ALIGN(4);
__alt_instructions = .;
- .altinstructions : { *(.altinstructions) }
+ .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) {
+ *(.altinstructions)
+ }
__alt_instructions_end = .;
- .altinstr_replacement : { *(.altinstr_replacement) }
+ .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) {
+ *(.altinstr_replacement)
+ }
/* .exit.text is discard at runtime, not link time, to deal with references
from .altinstructions and .eh_frame */
- .exit.text : { *(.exit.text) }
- .exit.data : { *(.exit.data) }
+ .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { *(.exit.text) }
+ .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { *(.exit.data) }
. = ALIGN(4096);
__initramfs_start = .;
- .init.ramfs : { *(.init.ramfs) }
+ .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { *(.init.ramfs) }
__initramfs_end = .;
. = ALIGN(32);
__per_cpu_start = .;
- .data.percpu : { *(.data.percpu) }
+ .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { *(.data.percpu) }
__per_cpu_end = .;
. = ALIGN(4096);
__init_end = .;
/* freed after init ends here */
__bss_start = .; /* BSS */
- .bss : {
+ .bss.page_aligned : AT(ADDR(.bss.page_aligned) - LOAD_OFFSET) {
*(.bss.page_aligned)
+ }
+ .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
*(.bss)
}
. = ALIGN(4);
diff --git a/arch/i386/lib/dec_and_lock.c b/arch/i386/lib/dec_and_lock.c
index ab43394dc77..8b81b2524fa 100644
--- a/arch/i386/lib/dec_and_lock.c
+++ b/arch/i386/lib/dec_and_lock.c
@@ -8,6 +8,7 @@
*/
#include <linux/spinlock.h>
+#include <linux/module.h>
#include <asm/atomic.h>
int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
@@ -38,3 +39,4 @@ slow_path:
spin_unlock(lock);
return 0;
}
+EXPORT_SYMBOL(_atomic_dec_and_lock);
diff --git a/arch/i386/lib/delay.c b/arch/i386/lib/delay.c
index 080639f262b..c49a6acbee5 100644
--- a/arch/i386/lib/delay.c
+++ b/arch/i386/lib/delay.c
@@ -13,6 +13,7 @@
#include <linux/config.h>
#include <linux/sched.h>
#include <linux/delay.h>
+#include <linux/module.h>
#include <asm/processor.h>
#include <asm/delay.h>
#include <asm/timer.h>
@@ -34,7 +35,7 @@ inline void __const_udelay(unsigned long xloops)
xloops *= 4;
__asm__("mull %0"
:"=d" (xloops), "=&a" (d0)
- :"1" (xloops),"0" (cpu_data[_smp_processor_id()].loops_per_jiffy * (HZ/4)));
+ :"1" (xloops),"0" (cpu_data[raw_smp_processor_id()].loops_per_jiffy * (HZ/4)));
__delay(++xloops);
}
@@ -47,3 +48,8 @@ void __ndelay(unsigned long nsecs)
{
__const_udelay(nsecs * 0x00005); /* 2**32 / 1000000000 (rounded up) */
}
+
+EXPORT_SYMBOL(__delay);
+EXPORT_SYMBOL(__const_udelay);
+EXPORT_SYMBOL(__udelay);
+EXPORT_SYMBOL(__ndelay);
diff --git a/arch/i386/lib/mmx.c b/arch/i386/lib/mmx.c
index 01f8b1a2cc8..2afda94dffd 100644
--- a/arch/i386/lib/mmx.c
+++ b/arch/i386/lib/mmx.c
@@ -3,6 +3,7 @@
#include <linux/string.h>
#include <linux/sched.h>
#include <linux/hardirq.h>
+#include <linux/module.h>
#include <asm/i387.h>
@@ -397,3 +398,7 @@ void mmx_copy_page(void *to, void *from)
else
fast_copy_page(to, from);
}
+
+EXPORT_SYMBOL(_mmx_memcpy);
+EXPORT_SYMBOL(mmx_clear_page);
+EXPORT_SYMBOL(mmx_copy_page);
diff --git a/arch/i386/lib/usercopy.c b/arch/i386/lib/usercopy.c
index 51aa2bbb026..4cf981d70f4 100644
--- a/arch/i386/lib/usercopy.c
+++ b/arch/i386/lib/usercopy.c
@@ -84,6 +84,7 @@ __strncpy_from_user(char *dst, const char __user *src, long count)
__do_strncpy_from_user(dst, src, count, res);
return res;
}
+EXPORT_SYMBOL(__strncpy_from_user);
/**
* strncpy_from_user: - Copy a NUL terminated string from userspace.
@@ -111,7 +112,7 @@ strncpy_from_user(char *dst, const char __user *src, long count)
__do_strncpy_from_user(dst, src, count, res);
return res;
}
-
+EXPORT_SYMBOL(strncpy_from_user);
/*
* Zero Userspace
@@ -157,6 +158,7 @@ clear_user(void __user *to, unsigned long n)
__do_clear_user(to, n);
return n;
}
+EXPORT_SYMBOL(clear_user);
/**
* __clear_user: - Zero a block of memory in user space, with less checking.
@@ -175,6 +177,7 @@ __clear_user(void __user *to, unsigned long n)
__do_clear_user(to, n);
return n;
}
+EXPORT_SYMBOL(__clear_user);
/**
* strlen_user: - Get the size of a string in user space.
@@ -218,6 +221,7 @@ long strnlen_user(const char __user *s, long n)
:"cc");
return res & mask;
}
+EXPORT_SYMBOL(strnlen_user);
#ifdef CONFIG_X86_INTEL_USERCOPY
static unsigned long
@@ -570,6 +574,7 @@ survive:
n = __copy_user_intel(to, from, n);
return n;
}
+EXPORT_SYMBOL(__copy_to_user_ll);
unsigned long
__copy_from_user_ll(void *to, const void __user *from, unsigned long n)
@@ -581,6 +586,7 @@ __copy_from_user_ll(void *to, const void __user *from, unsigned long n)
n = __copy_user_zeroing_intel(to, from, n);
return n;
}
+EXPORT_SYMBOL(__copy_from_user_ll);
/**
* copy_to_user: - Copy a block of data into user space.
diff --git a/arch/i386/mach-default/setup.c b/arch/i386/mach-default/setup.c
index 0aa08eaa893..e5a1a83d09e 100644
--- a/arch/i386/mach-default/setup.c
+++ b/arch/i386/mach-default/setup.c
@@ -10,6 +10,14 @@
#include <asm/acpi.h>
#include <asm/arch_hooks.h>
+#ifdef CONFIG_HOTPLUG_CPU
+#define DEFAULT_SEND_IPI (1)
+#else
+#define DEFAULT_SEND_IPI (0)
+#endif
+
+int no_broadcast=DEFAULT_SEND_IPI;
+
/**
* pre_intr_init_hook - initialisation prior to setting up interrupt vectors
*
@@ -104,3 +112,22 @@ void __init mca_nmi_hook(void)
printk("NMI generated from unknown source!\n");
}
#endif
+
+static __init int no_ipi_broadcast(char *str)
+{
+ get_option(&str, &no_broadcast);
+ printk ("Using %s mode\n", no_broadcast ? "No IPI Broadcast" :
+ "IPI Broadcast");
+ return 1;
+}
+
+__setup("no_ipi_broadcast", no_ipi_broadcast);
+
+static int __init print_ipi_mode(void)
+{
+ printk ("Using IPI %s mode\n", no_broadcast ? "No-Shortcut" :
+ "Shortcut");
+ return 0;
+}
+
+late_initcall(print_ipi_mode);
diff --git a/arch/i386/mach-default/topology.c b/arch/i386/mach-default/topology.c
index 5b3e8817dae..23395fff35d 100644
--- a/arch/i386/mach-default/topology.c
+++ b/arch/i386/mach-default/topology.c
@@ -73,12 +73,11 @@ static int __init topology_init(void)
{
int i;
- for (i = 0; i < MAX_NUMNODES; i++) {
- if (node_online(i))
- arch_register_node(i);
- }
- for (i = 0; i < NR_CPUS; i++)
- if (cpu_possible(i)) arch_register_cpu(i);
+ for_each_online_node(i)
+ arch_register_node(i);
+
+ for_each_cpu(i)
+ arch_register_cpu(i);
return 0;
}
@@ -88,8 +87,8 @@ static int __init topology_init(void)
{
int i;
- for (i = 0; i < NR_CPUS; i++)
- if (cpu_possible(i)) arch_register_cpu(i);
+ for_each_cpu(i)
+ arch_register_cpu(i);
return 0;
}
diff --git a/arch/i386/mach-visws/mpparse.c b/arch/i386/mach-visws/mpparse.c
index 5a22082147f..5f3d7e6de37 100644
--- a/arch/i386/mach-visws/mpparse.c
+++ b/arch/i386/mach-visws/mpparse.c
@@ -23,7 +23,6 @@ unsigned long mp_lapic_addr;
/* Processor that is doing the boot up */
unsigned int boot_cpu_physical_apicid = -1U;
-unsigned int boot_cpu_logical_apicid = -1U;
/* Bitmask of physically existing CPUs */
physid_mask_t phys_cpu_present_map;
@@ -52,10 +51,8 @@ static void __init MP_processor_info (struct mpc_config_processor *m)
(m->mpc_cpufeature & CPU_MODEL_MASK) >> 4,
m->mpc_apicver);
- if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
+ if (m->mpc_cpuflag & CPU_BOOTPROCESSOR)
boot_cpu_physical_apicid = m->mpc_apicid;
- boot_cpu_logical_apicid = logical_apicid;
- }
ver = m->mpc_apicver;
if ((ver >= 0x14 && m->mpc_apicid >= 0xff) || m->mpc_apicid >= 0xf) {
diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c
index 903d739ca74..8c8527593da 100644
--- a/arch/i386/mach-voyager/voyager_smp.c
+++ b/arch/i386/mach-voyager/voyager_smp.c
@@ -97,7 +97,6 @@ static void ack_vic_irq(unsigned int irq);
static void vic_enable_cpi(void);
static void do_boot_cpu(__u8 cpuid);
static void do_quad_bootstrap(void);
-static inline void wrapper_smp_local_timer_interrupt(struct pt_regs *);
int hard_smp_processor_id(void);
@@ -126,6 +125,14 @@ send_QIC_CPI(__u32 cpuset, __u8 cpi)
}
static inline void
+wrapper_smp_local_timer_interrupt(struct pt_regs *regs)
+{
+ irq_enter();
+ smp_local_timer_interrupt(regs);
+ irq_exit();
+}
+
+static inline void
send_one_CPI(__u8 cpu, __u8 cpi)
{
if(voyager_quad_processors & (1<<cpu))
@@ -1249,14 +1256,6 @@ smp_vic_timer_interrupt(struct pt_regs *regs)
smp_local_timer_interrupt(regs);
}
-static inline void
-wrapper_smp_local_timer_interrupt(struct pt_regs *regs)
-{
- irq_enter();
- smp_local_timer_interrupt(regs);
- irq_exit();
-}
-
/* local (per CPU) timer interrupt. It does both profiling and
* process statistics/rescheduling.
*
@@ -1289,7 +1288,7 @@ smp_local_timer_interrupt(struct pt_regs * regs)
per_cpu(prof_counter, cpu);
}
- update_process_times(user_mode(regs));
+ update_process_times(user_mode_vm(regs));
}
if( ((1<<cpu) & voyager_extended_vic_processors) == 0)
diff --git a/arch/i386/mm/Makefile b/arch/i386/mm/Makefile
index fc327250684..80908b5aa60 100644
--- a/arch/i386/mm/Makefile
+++ b/arch/i386/mm/Makefile
@@ -4,7 +4,7 @@
obj-y := init.o pgtable.o fault.o ioremap.o extable.o pageattr.o mmap.o
-obj-$(CONFIG_DISCONTIGMEM) += discontig.o
+obj-$(CONFIG_NUMA) += discontig.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
obj-$(CONFIG_HIGHMEM) += highmem.o
obj-$(CONFIG_BOOT_IOREMAP) += boot_ioremap.o
diff --git a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c
index 1726b4096b1..b358f0702a4 100644
--- a/arch/i386/mm/discontig.c
+++ b/arch/i386/mm/discontig.c
@@ -29,12 +29,16 @@
#include <linux/highmem.h>
#include <linux/initrd.h>
#include <linux/nodemask.h>
+#include <linux/module.h>
+#include <linux/kexec.h>
+
#include <asm/e820.h>
#include <asm/setup.h>
#include <asm/mmzone.h>
#include <bios_ebda.h>
struct pglist_data *node_data[MAX_NUMNODES];
+EXPORT_SYMBOL(node_data);
bootmem_data_t node0_bdata;
/*
@@ -42,12 +46,16 @@ bootmem_data_t node0_bdata;
* populated the following initialisation.
*
* 1) node_online_map - the map of all nodes configured (online) in the system
- * 2) physnode_map - the mapping between a pfn and owning node
- * 3) node_start_pfn - the starting page frame number for a node
+ * 2) node_start_pfn - the starting page frame number for a node
* 3) node_end_pfn - the ending page fram number for a node
*/
+unsigned long node_start_pfn[MAX_NUMNODES];
+unsigned long node_end_pfn[MAX_NUMNODES];
+
+#ifdef CONFIG_DISCONTIGMEM
/*
+ * 4) physnode_map - the mapping between a pfn and owning node
* physnode_map keeps track of the physical memory layout of a generic
* numa node on a 256Mb break (each element of the array will
* represent 256Mb of memory and will be marked by the node id. so,
@@ -59,6 +67,7 @@ bootmem_data_t node0_bdata;
* physnode_map[8- ] = -1;
*/
s8 physnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1};
+EXPORT_SYMBOL(physnode_map);
void memory_present(int nid, unsigned long start, unsigned long end)
{
@@ -85,9 +94,7 @@ unsigned long node_memmap_size_bytes(int nid, unsigned long start_pfn,
return (nr_pages + 1) * sizeof(struct page);
}
-
-unsigned long node_start_pfn[MAX_NUMNODES];
-unsigned long node_end_pfn[MAX_NUMNODES];
+#endif
extern unsigned long find_max_low_pfn(void);
extern void find_max_pfn(void);
@@ -108,6 +115,9 @@ unsigned long node_remap_offset[MAX_NUMNODES];
void *node_remap_start_vaddr[MAX_NUMNODES];
void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags);
+void *node_remap_end_vaddr[MAX_NUMNODES];
+void *node_remap_alloc_vaddr[MAX_NUMNODES];
+
/*
* FLAT - support for basic PC memory model with discontig enabled, essentially
* a single node with all available processors in it with a flat
@@ -146,6 +156,21 @@ static void __init find_max_pfn_node(int nid)
BUG();
}
+/* Find the owning node for a pfn. */
+int early_pfn_to_nid(unsigned long pfn)
+{
+ int nid;
+
+ for_each_node(nid) {
+ if (node_end_pfn[nid] == 0)
+ break;
+ if (node_start_pfn[nid] <= pfn && node_end_pfn[nid] >= pfn)
+ return nid;
+ }
+
+ return 0;
+}
+
/*
* Allocate memory for the pg_data_t for this node via a crude pre-bootmem
* method. For node zero take this from the bottom of memory, for
@@ -163,6 +188,21 @@ static void __init allocate_pgdat(int nid)
}
}
+void *alloc_remap(int nid, unsigned long size)
+{
+ void *allocation = node_remap_alloc_vaddr[nid];
+
+ size = ALIGN(size, L1_CACHE_BYTES);
+
+ if (!allocation || (allocation + size) >= node_remap_end_vaddr[nid])
+ return 0;
+
+ node_remap_alloc_vaddr[nid] += size;
+ memset(allocation, 0, size);
+
+ return allocation;
+}
+
void __init remap_numa_kva(void)
{
void *vaddr;
@@ -170,8 +210,6 @@ void __init remap_numa_kva(void)
int node;
for_each_online_node(node) {
- if (node == 0)
- continue;
for (pfn=0; pfn < node_remap_size[node]; pfn += PTRS_PER_PTE) {
vaddr = node_remap_start_vaddr[node]+(pfn<<PAGE_SHIFT);
set_pmd_pfn((ulong) vaddr,
@@ -185,13 +223,9 @@ static unsigned long calculate_numa_remap_pages(void)
{
int nid;
unsigned long size, reserve_pages = 0;
+ unsigned long pfn;
for_each_online_node(nid) {
- if (nid == 0)
- continue;
- if (!node_remap_size[nid])
- continue;
-
/*
* The acpi/srat node info can show hot-add memroy zones
* where memory could be added but not currently present.
@@ -208,11 +242,24 @@ static unsigned long calculate_numa_remap_pages(void)
size = (size + LARGE_PAGE_BYTES - 1) / LARGE_PAGE_BYTES;
/* now the roundup is correct, convert to PAGE_SIZE pages */
size = size * PTRS_PER_PTE;
+
+ /*
+ * Validate the region we are allocating only contains valid
+ * pages.
+ */
+ for (pfn = node_end_pfn[nid] - size;
+ pfn < node_end_pfn[nid]; pfn++)
+ if (!page_is_ram(pfn))
+ break;
+
+ if (pfn != node_end_pfn[nid])
+ size = 0;
+
printk("Reserving %ld pages of KVA for lmem_map of node %d\n",
size, nid);
node_remap_size[nid] = size;
- reserve_pages += size;
node_remap_offset[nid] = reserve_pages;
+ reserve_pages += size;
printk("Shrinking node %d from %ld pages to %ld pages\n",
nid, node_end_pfn[nid], node_end_pfn[nid] - size);
node_end_pfn[nid] -= size;
@@ -265,12 +312,18 @@ unsigned long __init setup_memory(void)
(ulong) pfn_to_kaddr(max_low_pfn));
for_each_online_node(nid) {
node_remap_start_vaddr[nid] = pfn_to_kaddr(
- (highstart_pfn + reserve_pages) - node_remap_offset[nid]);
+ highstart_pfn + node_remap_offset[nid]);
+ /* Init the node remap allocator */
+ node_remap_end_vaddr[nid] = node_remap_start_vaddr[nid] +
+ (node_remap_size[nid] * PAGE_SIZE);
+ node_remap_alloc_vaddr[nid] = node_remap_start_vaddr[nid] +
+ ALIGN(sizeof(pg_data_t), PAGE_SIZE);
+
allocate_pgdat(nid);
printk ("node %d will remap to vaddr %08lx - %08lx\n", nid,
(ulong) node_remap_start_vaddr[nid],
- (ulong) pfn_to_kaddr(highstart_pfn + reserve_pages
- - node_remap_offset[nid] + node_remap_size[nid]));
+ (ulong) pfn_to_kaddr(highstart_pfn
+ + node_remap_offset[nid] + node_remap_size[nid]));
}
printk("High memory starts at vaddr %08lx\n",
(ulong) pfn_to_kaddr(highstart_pfn));
@@ -333,23 +386,9 @@ void __init zone_sizes_init(void)
}
zholes_size = get_zholes_size(nid);
- /*
- * We let the lmem_map for node 0 be allocated from the
- * normal bootmem allocator, but other nodes come from the
- * remapped KVA area - mbligh
- */
- if (!nid)
- free_area_init_node(nid, NODE_DATA(nid),
- zones_size, start, zholes_size);
- else {
- unsigned long lmem_map;
- lmem_map = (unsigned long)node_remap_start_vaddr[nid];
- lmem_map += sizeof(pg_data_t) + PAGE_SIZE - 1;
- lmem_map &= PAGE_MASK;
- NODE_DATA(nid)->node_mem_map = (struct page *)lmem_map;
- free_area_init_node(nid, NODE_DATA(nid), zones_size,
- start, zholes_size);
- }
+
+ free_area_init_node(nid, NODE_DATA(nid), zones_size, start,
+ zholes_size);
}
return;
}
@@ -358,24 +397,26 @@ void __init set_highmem_pages_init(int bad_ppro)
{
#ifdef CONFIG_HIGHMEM
struct zone *zone;
+ struct page *page;
for_each_zone(zone) {
- unsigned long node_pfn, node_high_size, zone_start_pfn;
- struct page * zone_mem_map;
-
+ unsigned long node_pfn, zone_start_pfn, zone_end_pfn;
+
if (!is_highmem(zone))
continue;
- printk("Initializing %s for node %d\n", zone->name,
- zone->zone_pgdat->node_id);
-
- node_high_size = zone->spanned_pages;
- zone_mem_map = zone->zone_mem_map;
zone_start_pfn = zone->zone_start_pfn;
+ zone_end_pfn = zone_start_pfn + zone->spanned_pages;
+
+ printk("Initializing %s for node %d (%08lx:%08lx)\n",
+ zone->name, zone->zone_pgdat->node_id,
+ zone_start_pfn, zone_end_pfn);
- for (node_pfn = 0; node_pfn < node_high_size; node_pfn++) {
- one_highpage_init((struct page *)(zone_mem_map + node_pfn),
- zone_start_pfn + node_pfn, bad_ppro);
+ for (node_pfn = zone_start_pfn; node_pfn < zone_end_pfn; node_pfn++) {
+ if (!pfn_valid(node_pfn))
+ continue;
+ page = pfn_to_page(node_pfn);
+ one_highpage_init(page, node_pfn, bad_ppro);
}
}
totalram_pages += totalhigh_pages;
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
index a509237c481..8e90339d6ea 100644
--- a/arch/i386/mm/fault.c
+++ b/arch/i386/mm/fault.c
@@ -146,7 +146,7 @@ static int __is_prefetch(struct pt_regs *regs, unsigned long addr)
if (instr > limit)
break;
- if (__get_user(opcode, (unsigned char *) instr))
+ if (__get_user(opcode, (unsigned char __user *) instr))
break;
instr_hi = opcode & 0xf0;
@@ -173,7 +173,7 @@ static int __is_prefetch(struct pt_regs *regs, unsigned long addr)
scan_more = 0;
if (instr > limit)
break;
- if (__get_user(opcode, (unsigned char *) instr))
+ if (__get_user(opcode, (unsigned char __user *) instr))
break;
prefetch = (instr_lo == 0xF) &&
(opcode == 0x0D || opcode == 0x18);
@@ -463,6 +463,9 @@ no_context:
printk(KERN_ALERT "*pte = %08lx\n", page);
}
#endif
+ tsk->thread.cr2 = address;
+ tsk->thread.trap_no = 14;
+ tsk->thread.error_code = error_code;
die("Oops", regs, error_code);
bust_spinlocks(0);
do_exit(SIGKILL);
diff --git a/arch/i386/mm/highmem.c b/arch/i386/mm/highmem.c
index fc4c4cad4e9..b6eb4dcb877 100644
--- a/arch/i386/mm/highmem.c
+++ b/arch/i386/mm/highmem.c
@@ -1,4 +1,5 @@
#include <linux/highmem.h>
+#include <linux/module.h>
void *kmap(struct page *page)
{
@@ -74,6 +75,24 @@ void kunmap_atomic(void *kvaddr, enum km_type type)
preempt_check_resched();
}
+/* This is the same as kmap_atomic() but can map memory that doesn't
+ * have a struct page associated with it.
+ */
+void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
+{
+ enum fixed_addresses idx;
+ unsigned long vaddr;
+
+ inc_preempt_count();
+
+ idx = type + KM_TYPE_NR*smp_processor_id();
+ vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+ set_pte(kmap_pte-idx, pfn_pte(pfn, kmap_prot));
+ __flush_tlb_one(vaddr);
+
+ return (void*) vaddr;
+}
+
struct page *kmap_atomic_to_page(void *ptr)
{
unsigned long idx, vaddr = (unsigned long)ptr;
@@ -87,3 +106,8 @@ struct page *kmap_atomic_to_page(void *ptr)
return pte_page(*pte);
}
+EXPORT_SYMBOL(kmap);
+EXPORT_SYMBOL(kunmap);
+EXPORT_SYMBOL(kmap_atomic);
+EXPORT_SYMBOL(kunmap_atomic);
+EXPORT_SYMBOL(kmap_atomic_to_page);
diff --git a/arch/i386/mm/hugetlbpage.c b/arch/i386/mm/hugetlbpage.c
index 171fc925e1e..3b099f32b94 100644
--- a/arch/i386/mm/hugetlbpage.c
+++ b/arch/i386/mm/hugetlbpage.c
@@ -18,7 +18,7 @@
#include <asm/tlb.h>
#include <asm/tlbflush.h>
-static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
{
pgd_t *pgd;
pud_t *pud;
@@ -30,7 +30,7 @@ static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
return (pte_t *) pmd;
}
-static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
{
pgd_t *pgd;
pud_t *pud;
@@ -42,21 +42,6 @@ static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
return (pte_t *) pmd;
}
-static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma, struct page *page, pte_t * page_table, int write_access)
-{
- pte_t entry;
-
- add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE);
- if (write_access) {
- entry =
- pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
- } else
- entry = pte_wrprotect(mk_pte(page, vma->vm_page_prot));
- entry = pte_mkyoung(entry);
- mk_pte_huge(entry);
- set_pte(page_table, entry);
-}
-
/*
* This function checks for proper alignment of input addr and len parameters.
*/
@@ -69,77 +54,6 @@ int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
return 0;
}
-int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
- struct vm_area_struct *vma)
-{
- pte_t *src_pte, *dst_pte, entry;
- struct page *ptepage;
- unsigned long addr = vma->vm_start;
- unsigned long end = vma->vm_end;
-
- while (addr < end) {
- dst_pte = huge_pte_alloc(dst, addr);
- if (!dst_pte)
- goto nomem;
- src_pte = huge_pte_offset(src, addr);
- entry = *src_pte;
- ptepage = pte_page(entry);
- get_page(ptepage);
- set_pte(dst_pte, entry);
- add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
- addr += HPAGE_SIZE;
- }
- return 0;
-
-nomem:
- return -ENOMEM;
-}
-
-int
-follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
- struct page **pages, struct vm_area_struct **vmas,
- unsigned long *position, int *length, int i)
-{
- unsigned long vpfn, vaddr = *position;
- int remainder = *length;
-
- WARN_ON(!is_vm_hugetlb_page(vma));
-
- vpfn = vaddr/PAGE_SIZE;
- while (vaddr < vma->vm_end && remainder) {
-
- if (pages) {
- pte_t *pte;
- struct page *page;
-
- pte = huge_pte_offset(mm, vaddr);
-
- /* hugetlb should be locked, and hence, prefaulted */
- WARN_ON(!pte || pte_none(*pte));
-
- page = &pte_page(*pte)[vpfn % (HPAGE_SIZE/PAGE_SIZE)];
-
- WARN_ON(!PageCompound(page));
-
- get_page(page);
- pages[i] = page;
- }
-
- if (vmas)
- vmas[i] = vma;
-
- vaddr += PAGE_SIZE;
- ++vpfn;
- --remainder;
- ++i;
- }
-
- *length = remainder;
- *position = vaddr;
-
- return i;
-}
-
#if 0 /* This is just for testing */
struct page *
follow_huge_addr(struct mm_struct *mm, unsigned long address, int write)
@@ -204,83 +118,15 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address,
}
#endif
-void unmap_hugepage_range(struct vm_area_struct *vma,
- unsigned long start, unsigned long end)
+void hugetlb_clean_stale_pgtable(pte_t *pte)
{
- struct mm_struct *mm = vma->vm_mm;
- unsigned long address;
- pte_t pte, *ptep;
+ pmd_t *pmd = (pmd_t *) pte;
struct page *page;
- BUG_ON(start & (HPAGE_SIZE - 1));
- BUG_ON(end & (HPAGE_SIZE - 1));
-
- for (address = start; address < end; address += HPAGE_SIZE) {
- ptep = huge_pte_offset(mm, address);
- if (!ptep)
- continue;
- pte = ptep_get_and_clear(mm, address, ptep);
- if (pte_none(pte))
- continue;
- page = pte_page(pte);
- put_page(page);
- }
- add_mm_counter(mm ,rss, -((end - start) >> PAGE_SHIFT));
- flush_tlb_range(vma, start, end);
-}
-
-int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
-{
- struct mm_struct *mm = current->mm;
- unsigned long addr;
- int ret = 0;
-
- BUG_ON(vma->vm_start & ~HPAGE_MASK);
- BUG_ON(vma->vm_end & ~HPAGE_MASK);
-
- spin_lock(&mm->page_table_lock);
- for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
- unsigned long idx;
- pte_t *pte = huge_pte_alloc(mm, addr);
- struct page *page;
-
- if (!pte) {
- ret = -ENOMEM;
- goto out;
- }
-
- if (!pte_none(*pte))
- continue;
-
- idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
- + (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
- page = find_get_page(mapping, idx);
- if (!page) {
- /* charge the fs quota first */
- if (hugetlb_get_quota(mapping)) {
- ret = -ENOMEM;
- goto out;
- }
- page = alloc_huge_page();
- if (!page) {
- hugetlb_put_quota(mapping);
- ret = -ENOMEM;
- goto out;
- }
- ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
- if (! ret) {
- unlock_page(page);
- } else {
- hugetlb_put_quota(mapping);
- free_huge_page(page);
- goto out;
- }
- }
- set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE);
- }
-out:
- spin_unlock(&mm->page_table_lock);
- return ret;
+ page = pmd_page(*pmd);
+ pmd_clear(pmd);
+ dec_page_state(nr_page_table_pages);
+ page_cache_release(page);
}
/* x86_64 also uses this file */
@@ -294,7 +140,12 @@ static unsigned long hugetlb_get_unmapped_area_bottomup(struct file *file,
struct vm_area_struct *vma;
unsigned long start_addr;
- start_addr = mm->free_area_cache;
+ if (len > mm->cached_hole_size) {
+ start_addr = mm->free_area_cache;
+ } else {
+ start_addr = TASK_UNMAPPED_BASE;
+ mm->cached_hole_size = 0;
+ }
full_search:
addr = ALIGN(start_addr, HPAGE_SIZE);
@@ -308,6 +159,7 @@ full_search:
*/
if (start_addr != TASK_UNMAPPED_BASE) {
start_addr = TASK_UNMAPPED_BASE;
+ mm->cached_hole_size = 0;
goto full_search;
}
return -ENOMEM;
@@ -316,6 +168,8 @@ full_search:
mm->free_area_cache = addr + len;
return addr;
}
+ if (addr + mm->cached_hole_size < vma->vm_start)
+ mm->cached_hole_size = vma->vm_start - addr;
addr = ALIGN(vma->vm_end, HPAGE_SIZE);
}
}
@@ -327,12 +181,17 @@ static unsigned long hugetlb_get_unmapped_area_topdown(struct file *file,
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma, *prev_vma;
unsigned long base = mm->mmap_base, addr = addr0;
+ unsigned long largest_hole = mm->cached_hole_size;
int first_time = 1;
/* don't allow allocations above current base */
if (mm->free_area_cache > base)
mm->free_area_cache = base;
+ if (len <= largest_hole) {
+ largest_hole = 0;
+ mm->free_area_cache = base;
+ }
try_again:
/* make sure it can fit in the remaining address space */
if (mm->free_area_cache < len)
@@ -353,13 +212,21 @@ try_again:
* vma->vm_start, use it:
*/
if (addr + len <= vma->vm_start &&
- (!prev_vma || (addr >= prev_vma->vm_end)))
+ (!prev_vma || (addr >= prev_vma->vm_end))) {
/* remember the address as a hint for next time */
- return (mm->free_area_cache = addr);
- else
+ mm->cached_hole_size = largest_hole;
+ return (mm->free_area_cache = addr);
+ } else {
/* pull free_area_cache down to the first hole */
- if (mm->free_area_cache == vma->vm_end)
+ if (mm->free_area_cache == vma->vm_end) {
mm->free_area_cache = vma->vm_start;
+ mm->cached_hole_size = largest_hole;
+ }
+ }
+
+ /* remember the largest hole we saw so far */
+ if (addr + largest_hole < vma->vm_start)
+ largest_hole = vma->vm_start - addr;
/* try just below the current vma->vm_start */
addr = (vma->vm_start - len) & HPAGE_MASK;
@@ -372,6 +239,7 @@ fail:
*/
if (first_time) {
mm->free_area_cache = base;
+ largest_hole = 0;
first_time = 0;
goto try_again;
}
@@ -382,6 +250,7 @@ fail:
* allocations.
*/
mm->free_area_cache = TASK_UNMAPPED_BASE;
+ mm->cached_hole_size = ~0UL;
addr = hugetlb_get_unmapped_area_bottomup(file, addr0,
len, pgoff, flags);
@@ -389,6 +258,7 @@ fail:
* Restore the topdown base:
*/
mm->free_area_cache = base;
+ mm->cached_hole_size = ~0UL;
return addr;
}
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index 7a7ea373726..12216b52e28 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -191,7 +191,7 @@ static inline int page_kills_ppro(unsigned long pagenr)
extern int is_available_memory(efi_memory_desc_t *);
-static inline int page_is_ram(unsigned long pagenr)
+int page_is_ram(unsigned long pagenr)
{
int i;
unsigned long addr, end;
@@ -269,7 +269,6 @@ void __init one_highpage_init(struct page *page, int pfn, int bad_ppro)
{
if (page_is_ram(pfn) && !(bad_ppro && page_kills_ppro(pfn))) {
ClearPageReserved(page);
- set_bit(PG_highmem, &page->flags);
set_page_count(page, 1);
__free_page(page);
totalhigh_pages++;
@@ -277,7 +276,9 @@ void __init one_highpage_init(struct page *page, int pfn, int bad_ppro)
SetPageReserved(page);
}
-#ifndef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NUMA
+extern void set_highmem_pages_init(int);
+#else
static void __init set_highmem_pages_init(int bad_ppro)
{
int pfn;
@@ -285,9 +286,7 @@ static void __init set_highmem_pages_init(int bad_ppro)
one_highpage_init(pfn_to_page(pfn), pfn, bad_ppro);
totalram_pages += totalhigh_pages;
}
-#else
-extern void set_highmem_pages_init(int);
-#endif /* !CONFIG_DISCONTIGMEM */
+#endif /* CONFIG_FLATMEM */
#else
#define kmap_init() do { } while (0)
@@ -296,12 +295,13 @@ extern void set_highmem_pages_init(int);
#endif /* CONFIG_HIGHMEM */
unsigned long long __PAGE_KERNEL = _PAGE_KERNEL;
+EXPORT_SYMBOL(__PAGE_KERNEL);
unsigned long long __PAGE_KERNEL_EXEC = _PAGE_KERNEL_EXEC;
-#ifndef CONFIG_DISCONTIGMEM
-#define remap_numa_kva() do {} while (0)
-#else
+#ifdef CONFIG_NUMA
extern void __init remap_numa_kva(void);
+#else
+#define remap_numa_kva() do {} while (0)
#endif
static void __init pagetable_init (void)
@@ -352,7 +352,7 @@ static void __init pagetable_init (void)
#endif
}
-#if defined(CONFIG_PM_DISK) || defined(CONFIG_SOFTWARE_SUSPEND)
+#ifdef CONFIG_SOFTWARE_SUSPEND
/*
* Swap suspend & friends need this for resume because things like the intel-agp
* driver might have split up a kernel 4MB mapping.
@@ -526,7 +526,7 @@ static void __init set_max_mapnr_init(void)
#else
num_physpages = max_low_pfn;
#endif
-#ifndef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_FLATMEM
max_mapnr = num_physpages;
#endif
}
@@ -540,7 +540,7 @@ void __init mem_init(void)
int tmp;
int bad_ppro;
-#ifndef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_FLATMEM
if (!mem_map)
BUG();
#endif
diff --git a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c
index db06f739991..6b25afc933b 100644
--- a/arch/i386/mm/ioremap.c
+++ b/arch/i386/mm/ioremap.c
@@ -11,6 +11,7 @@
#include <linux/vmalloc.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <asm/io.h>
#include <asm/fixmap.h>
#include <asm/cacheflush.h>
@@ -165,7 +166,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
}
return (void __iomem *) (offset + (char __iomem *)addr);
}
-
+EXPORT_SYMBOL(__ioremap);
/**
* ioremap_nocache - map bus memory into CPU space
@@ -222,6 +223,7 @@ void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size)
return p;
}
+EXPORT_SYMBOL(ioremap_nocache);
void iounmap(volatile void __iomem *addr)
{
@@ -238,21 +240,24 @@ void iounmap(volatile void __iomem *addr)
addr < phys_to_virt(ISA_END_ADDRESS))
return;
- p = remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr));
+ write_lock(&vmlist_lock);
+ p = __remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr));
if (!p) {
- printk("__iounmap: bad address %p\n", addr);
- return;
+ printk(KERN_WARNING "iounmap: bad address %p\n", addr);
+ goto out_unlock;
}
if ((p->flags >> 20) && p->phys_addr < virt_to_phys(high_memory) - 1) {
- /* p->size includes the guard page, but cpa doesn't like that */
change_page_attr(virt_to_page(__va(p->phys_addr)),
p->size >> PAGE_SHIFT,
PAGE_KERNEL);
global_flush_tlb();
}
+out_unlock:
+ write_unlock(&vmlist_lock);
kfree(p);
}
+EXPORT_SYMBOL(iounmap);
void __init *bt_ioremap(unsigned long phys_addr, unsigned long size)
{
diff --git a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c
index dd81479ff88..bd2f7afc7a2 100644
--- a/arch/i386/mm/pgtable.c
+++ b/arch/i386/mm/pgtable.c
@@ -30,13 +30,14 @@ void show_mem(void)
struct page *page;
pg_data_t *pgdat;
unsigned long i;
+ struct page_state ps;
- printk("Mem-info:\n");
+ printk(KERN_INFO "Mem-info:\n");
show_free_areas();
- printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+ printk(KERN_INFO "Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
for_each_pgdat(pgdat) {
for (i = 0; i < pgdat->node_spanned_pages; ++i) {
- page = pgdat->node_mem_map + i;
+ page = pgdat_page_nr(pgdat, i);
total++;
if (PageHighMem(page))
highmem++;
@@ -48,11 +49,18 @@ void show_mem(void)
shared += page_count(page) - 1;
}
}
- printk("%d pages of RAM\n", total);
- printk("%d pages of HIGHMEM\n",highmem);
- printk("%d reserved pages\n",reserved);
- printk("%d pages shared\n",shared);
- printk("%d pages swap cached\n",cached);
+ printk(KERN_INFO "%d pages of RAM\n", total);
+ printk(KERN_INFO "%d pages of HIGHMEM\n", highmem);
+ printk(KERN_INFO "%d reserved pages\n", reserved);
+ printk(KERN_INFO "%d pages shared\n", shared);
+ printk(KERN_INFO "%d pages swap cached\n", cached);
+
+ get_page_state(&ps);
+ printk(KERN_INFO "%lu pages dirty\n", ps.nr_dirty);
+ printk(KERN_INFO "%lu pages writeback\n", ps.nr_writeback);
+ printk(KERN_INFO "%lu pages mapped\n", ps.nr_mapped);
+ printk(KERN_INFO "%lu pages slab\n", ps.nr_slab);
+ printk(KERN_INFO "%lu pages pagetables\n", ps.nr_page_table_pages);
}
/*
@@ -105,16 +113,16 @@ void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
pmd_t *pmd;
if (vaddr & (PMD_SIZE-1)) { /* vaddr is misaligned */
- printk ("set_pmd_pfn: vaddr misaligned\n");
+ printk(KERN_WARNING "set_pmd_pfn: vaddr misaligned\n");
return; /* BUG(); */
}
if (pfn & (PTRS_PER_PTE-1)) { /* pfn is misaligned */
- printk ("set_pmd_pfn: pfn misaligned\n");
+ printk(KERN_WARNING "set_pmd_pfn: pfn misaligned\n");
return; /* BUG(); */
}
pgd = swapper_pg_dir + pgd_index(vaddr);
if (pgd_none(*pgd)) {
- printk ("set_pmd_pfn: pgd_none\n");
+ printk(KERN_WARNING "set_pmd_pfn: pgd_none\n");
return; /* BUG(); */
}
pud = pud_offset(pgd, vaddr);
diff --git a/arch/i386/oprofile/backtrace.c b/arch/i386/oprofile/backtrace.c
index 52d72e074f7..65dfd2edb67 100644
--- a/arch/i386/oprofile/backtrace.c
+++ b/arch/i386/oprofile/backtrace.c
@@ -91,7 +91,7 @@ x86_backtrace(struct pt_regs * const regs, unsigned int depth)
head = (struct frame_head *)regs->ebp;
#endif
- if (!user_mode(regs)) {
+ if (!user_mode_vm(regs)) {
while (depth-- && valid_kernel_stack(head, regs))
head = dump_backtrace(head);
return;
diff --git a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c
index be52c5ac4e0..8e8e895e1b5 100644
--- a/arch/i386/pci/fixup.c
+++ b/arch/i386/pci/fixup.c
@@ -253,7 +253,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci
#define MAX_PCIEROOT 6
static int quirk_aspm_offset[MAX_PCIEROOT << 3];
-#define GET_INDEX(a, b) (((a - PCI_DEVICE_ID_INTEL_MCH_PA) << 3) + b)
+#define GET_INDEX(a, b) ((((a) - PCI_DEVICE_ID_INTEL_MCH_PA) << 3) + ((b) & 7))
static int quirk_pcie_aspm_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
{
diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
index d6598da4b67..83458f81e66 100644
--- a/arch/i386/pci/irq.c
+++ b/arch/i386/pci/irq.c
@@ -227,6 +227,24 @@ static int pirq_via_set(struct pci_dev *router, struct pci_dev *dev, int pirq, i
}
/*
+ * The VIA pirq rules are nibble-based, like ALI,
+ * but without the ugly irq number munging.
+ * However, for 82C586, nibble map is different .
+ */
+static int pirq_via586_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+ static unsigned int pirqmap[4] = { 3, 2, 5, 1 };
+ return read_config_nybble(router, 0x55, pirqmap[pirq-1]);
+}
+
+static int pirq_via586_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq)
+{
+ static unsigned int pirqmap[4] = { 3, 2, 5, 1 };
+ write_config_nybble(router, 0x55, pirqmap[pirq-1], irq);
+ return 1;
+}
+
+/*
* ITE 8330G pirq rules are nibble-based
* FIXME: pirqmap may be { 1, 0, 3, 2 },
* 2+3 are both mapped to irq 9 on my system
@@ -512,6 +530,10 @@ static __init int via_router_probe(struct irq_router *r, struct pci_dev *router,
switch(device)
{
case PCI_DEVICE_ID_VIA_82C586_0:
+ r->name = "VIA";
+ r->get = pirq_via586_get;
+ r->set = pirq_via586_set;
+ return 1;
case PCI_DEVICE_ID_VIA_82C596:
case PCI_DEVICE_ID_VIA_82C686:
case PCI_DEVICE_ID_VIA_8231:
@@ -1029,7 +1051,6 @@ void pcibios_penalize_isa_irq(int irq)
static int pirq_enable_irq(struct pci_dev *dev)
{
u8 pin;
- extern int via_interrupt_line_quirk;
struct pci_dev *temp_dev;
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
@@ -1084,10 +1105,6 @@ static int pirq_enable_irq(struct pci_dev *dev)
printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n",
'A' + pin, pci_name(dev), msg);
}
- /* VIA bridges use interrupt line for apic/pci steering across
- the V-Link */
- else if (via_interrupt_line_quirk)
- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq & 15);
return 0;
}
diff --git a/arch/i386/pci/pcbios.c b/arch/i386/pci/pcbios.c
index 141421b673b..b9d65f0bc2d 100644
--- a/arch/i386/pci/pcbios.c
+++ b/arch/i386/pci/pcbios.c
@@ -4,6 +4,7 @@
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/module.h>
#include "pci.h"
#include "pci-functions.h"
@@ -456,7 +457,7 @@ struct irq_routing_table * __devinit pcibios_get_irq_routing_table(void)
free_page(page);
return rt;
}
-
+EXPORT_SYMBOL(pcibios_get_irq_routing_table);
int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq)
{
@@ -473,6 +474,7 @@ int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq)
"S" (&pci_indirect));
return !(ret & 0xff00);
}
+EXPORT_SYMBOL(pcibios_set_irq_routing);
static int __init pci_pcbios_init(void)
{
diff --git a/arch/i386/power/cpu.c b/arch/i386/power/cpu.c
index cf337c673d9..0e6b45b6125 100644
--- a/arch/i386/power/cpu.c
+++ b/arch/i386/power/cpu.c
@@ -22,9 +22,11 @@
#include <linux/device.h>
#include <linux/suspend.h>
#include <linux/acpi.h>
+
#include <asm/uaccess.h>
#include <asm/acpi.h>
#include <asm/tlbflush.h>
+#include <asm/processor.h>
static struct saved_context saved_context;
@@ -33,8 +35,6 @@ unsigned long saved_context_esp, saved_context_ebp;
unsigned long saved_context_esi, saved_context_edi;
unsigned long saved_context_eflags;
-extern void enable_sep_cpu(void *);
-
void __save_processor_state(struct saved_context *ctxt)
{
kernel_fpu_begin();
@@ -44,7 +44,6 @@ void __save_processor_state(struct saved_context *ctxt)
*/
asm volatile ("sgdt %0" : "=m" (ctxt->gdt_limit));
asm volatile ("sidt %0" : "=m" (ctxt->idt_limit));
- asm volatile ("sldt %0" : "=m" (ctxt->ldt));
asm volatile ("str %0" : "=m" (ctxt->tr));
/*
@@ -94,20 +93,19 @@ static void fix_processor_context(void)
* Now maybe reload the debug registers
*/
if (current->thread.debugreg[7]){
- loaddebug(&current->thread, 0);
- loaddebug(&current->thread, 1);
- loaddebug(&current->thread, 2);
- loaddebug(&current->thread, 3);
- /* no 4 and 5 */
- loaddebug(&current->thread, 6);
- loaddebug(&current->thread, 7);
+ set_debugreg(current->thread.debugreg[0], 0);
+ set_debugreg(current->thread.debugreg[1], 1);
+ set_debugreg(current->thread.debugreg[2], 2);
+ set_debugreg(current->thread.debugreg[3], 3);
+ /* no 4 and 5 */
+ set_debugreg(current->thread.debugreg[6], 6);
+ set_debugreg(current->thread.debugreg[7], 7);
}
}
void __restore_processor_state(struct saved_context *ctxt)
{
-
/*
* control registers
*/
@@ -117,6 +115,13 @@ void __restore_processor_state(struct saved_context *ctxt)
asm volatile ("movl %0, %%cr0" :: "r" (ctxt->cr0));
/*
+ * now restore the descriptor tables to their proper values
+ * ltr is done i fix_processor_context().
+ */
+ asm volatile ("lgdt %0" :: "m" (ctxt->gdt_limit));
+ asm volatile ("lidt %0" :: "m" (ctxt->idt_limit));
+
+ /*
* segment registers
*/
asm volatile ("movw %0, %%es" :: "r" (ctxt->es));
@@ -125,18 +130,10 @@ void __restore_processor_state(struct saved_context *ctxt)
asm volatile ("movw %0, %%ss" :: "r" (ctxt->ss));
/*
- * now restore the descriptor tables to their proper values
- * ltr is done i fix_processor_context().
- */
- asm volatile ("lgdt %0" :: "m" (ctxt->gdt_limit));
- asm volatile ("lidt %0" :: "m" (ctxt->idt_limit));
- asm volatile ("lldt %0" :: "m" (ctxt->ldt));
-
- /*
* sysenter MSRs
*/
if (boot_cpu_has(X86_FEATURE_SEP))
- enable_sep_cpu(NULL);
+ enable_sep_cpu();
fix_processor_context();
do_fpu_end();
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 3ad2c4af099..01b78e7f992 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -50,6 +50,10 @@ config SCHED_NO_NO_OMIT_FRAME_POINTER
bool
default y
+config IA64_UNCACHED_ALLOCATOR
+ bool
+ select GENERIC_ALLOCATOR
+
choice
prompt "System type"
default IA64_GENERIC
@@ -157,6 +161,8 @@ config IA64_PAGE_SIZE_64KB
endchoice
+source kernel/Kconfig.hz
+
config IA64_BRL_EMU
bool
depends on ITANIUM
@@ -193,7 +199,7 @@ config HOLES_IN_ZONE
bool
default y if VIRTUAL_MEM_MAP
-config DISCONTIGMEM
+config ARCH_DISCONTIGMEM_ENABLE
bool "Discontiguous memory support"
depends on (IA64_DIG || IA64_SGI_SN2 || IA64_GENERIC || IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB) && NUMA && VIRTUAL_MEM_MAP
default y if (IA64_SGI_SN2 || IA64_GENERIC) && NUMA
@@ -216,14 +222,14 @@ config IOSAPIC
config IA64_SGI_SN_SIM
bool "SGI Medusa Simulator Support"
- depends on IA64_SGI_SN2
+ depends on IA64_SGI_SN2 || IA64_GENERIC
help
If you are compiling a kernel that will run under SGI's IA-64
simulator (Medusa) then say Y, otherwise say N.
config IA64_SGI_SN_XP
tristate "Support communication between SGI SSIs"
- depends on MSPEC
+ select IA64_UNCACHED_ALLOCATOR
help
An SGI machine can be divided into multiple Single System
Images which act independently of each other and have
@@ -296,6 +302,8 @@ config PREEMPT
Say Y here if you are building a kernel for a desktop, embedded
or real-time system. Say N if you are unsure.
+source "mm/Kconfig"
+
config HAVE_DEC_LOCK
bool
depends on (SMP || PREEMPT)
diff --git a/arch/ia64/Kconfig.debug b/arch/ia64/Kconfig.debug
index de9d507ba0f..fda67ac993d 100644
--- a/arch/ia64/Kconfig.debug
+++ b/arch/ia64/Kconfig.debug
@@ -2,6 +2,17 @@ menu "Kernel hacking"
source "lib/Kconfig.debug"
+config KPROBES
+ bool "Kprobes"
+ depends on DEBUG_KERNEL
+ help
+ Kprobes allows you to trap at almost any kernel address and
+ execute a callback function. register_kprobe() establishes
+ a probepoint and specifies the callback. Kprobes is useful
+ for kernel debugging, non-intrusive instrumentation and testing.
+ If in doubt, say "N".
+
+
choice
prompt "Physical memory granularity"
default IA64_GRANULE_64MB
diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig
index 6ff7107fee4..487d2e36b0a 100644
--- a/arch/ia64/configs/sn2_defconfig
+++ b/arch/ia64/configs/sn2_defconfig
@@ -78,7 +78,7 @@ CONFIG_IA64_L1_CACHE_SHIFT=7
CONFIG_NUMA=y
CONFIG_VIRTUAL_MEM_MAP=y
CONFIG_HOLES_IN_ZONE=y
-CONFIG_DISCONTIGMEM=y
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
# CONFIG_IA64_CYCLONE is not set
CONFIG_IOSAPIC=y
CONFIG_IA64_SGI_SN_SIM=y
@@ -588,6 +588,7 @@ CONFIG_SGI_MBCS=m
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_SGI_L1_CONSOLE=y
+CONFIG_SERIAL_SGI_IOC4=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -788,6 +789,11 @@ CONFIG_INFINIBAND_IPOIB=m
# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
#
+# SN Devices
+#
+CONFIG_SGI_IOC4=y
+
+#
# File systems
#
CONFIG_EXT2_FS=y
diff --git a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig
index 9086b789f6a..47f45341ac6 100644
--- a/arch/ia64/configs/tiger_defconfig
+++ b/arch/ia64/configs/tiger_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Tue May 3 15:55:04 2005
+# Linux kernel version: 2.6.12-20050621
+# Tue Jun 21 14:03:24 2005
#
#
@@ -67,6 +67,7 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_TIME_INTERPOLATION=y
CONFIG_EFI=y
CONFIG_GENERIC_IOMAP=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
# CONFIG_IA64_GENERIC is not set
CONFIG_IA64_DIG=y
# CONFIG_IA64_HP_ZX1 is not set
@@ -285,6 +286,7 @@ CONFIG_CHR_DEV_ST=m
CONFIG_BLK_DEV_SR=m
# CONFIG_BLK_DEV_SR_VENDOR is not set
CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -313,11 +315,8 @@ CONFIG_SCSI_FC_ATTRS=y
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
@@ -366,8 +365,10 @@ CONFIG_DM_ZERO=m
# Fusion MPT device support
#
CONFIG_FUSION=y
-CONFIG_FUSION_MAX_SGE=40
-# CONFIG_FUSION_CTL is not set
+CONFIG_FUSION_SPI=y
+CONFIG_FUSION_FC=y
+CONFIG_FUSION_MAX_SGE=128
+CONFIG_FUSION_CTL=y
#
# IEEE 1394 (FireWire) support
@@ -506,9 +507,11 @@ CONFIG_E1000=y
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
+# CONFIG_SKGE is not set
# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
CONFIG_TIGON3=y
+# CONFIG_BNX2 is not set
#
# Ethernet (10000 Mbit)
@@ -598,7 +601,6 @@ CONFIG_GAMEPORT=m
# CONFIG_GAMEPORT_VORTEX is not set
# CONFIG_GAMEPORT_FM801 is not set
# CONFIG_GAMEPORT_CS461X is not set
-CONFIG_SOUND_GAMEPORT=m
#
# Character devices
@@ -611,7 +613,6 @@ CONFIG_SERIAL_NONSTANDARD=y
# CONFIG_CYCLADES is not set
# CONFIG_MOXA_SMARTIO is not set
# CONFIG_ISI is not set
-# CONFIG_SYNCLINK is not set
# CONFIG_SYNCLINKMP is not set
# CONFIG_N_HDLC is not set
# CONFIG_SPECIALIX is not set
diff --git a/arch/ia64/defconfig b/arch/ia64/defconfig
index 7539e83bf05..8444add7638 100644
--- a/arch/ia64/defconfig
+++ b/arch/ia64/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10
-# Thu Jan 6 11:13:13 2005
+# Linux kernel version: 2.6.12
+# Tue Jun 21 11:30:42 2005
#
#
@@ -10,6 +10,7 @@
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -21,24 +22,27 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=20
CONFIG_HOTPLUG=y
CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SHMEM=y
CONFIG_CC_ALIGN_FUNCTIONS=0
CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -63,9 +67,11 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_TIME_INTERPOLATION=y
CONFIG_EFI=y
CONFIG_GENERIC_IOMAP=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
CONFIG_IA64_GENERIC=y
# CONFIG_IA64_DIG is not set
# CONFIG_IA64_HP_ZX1 is not set
+# CONFIG_IA64_HP_ZX1_SWIOTLB is not set
# CONFIG_IA64_SGI_SN2 is not set
# CONFIG_IA64_HP_SIM is not set
# CONFIG_ITANIUM is not set
@@ -77,13 +83,15 @@ CONFIG_IA64_PAGE_SIZE_16KB=y
CONFIG_IA64_L1_CACHE_SHIFT=7
CONFIG_NUMA=y
CONFIG_VIRTUAL_MEM_MAP=y
-CONFIG_DISCONTIGMEM=y
+CONFIG_HOLES_IN_ZONE=y
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
CONFIG_IA64_CYCLONE=y
CONFIG_IOSAPIC=y
CONFIG_FORCE_MAX_ZONEORDER=18
CONFIG_SMP=y
CONFIG_NR_CPUS=512
CONFIG_HOTPLUG_CPU=y
+# CONFIG_SCHED_SMT is not set
# CONFIG_PREEMPT is not set
CONFIG_HAVE_DEC_LOCK=y
CONFIG_IA32_SUPPORT=y
@@ -135,6 +143,7 @@ CONFIG_PCI_DOMAINS=y
# CONFIG_PCI_MSI is not set
CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
#
# PCI Hotplug Support
@@ -144,7 +153,6 @@ CONFIG_HOTPLUG_PCI=m
CONFIG_HOTPLUG_PCI_ACPI=m
# CONFIG_HOTPLUG_PCI_ACPI_IBM is not set
# CONFIG_HOTPLUG_PCI_CPCI is not set
-# CONFIG_HOTPLUG_PCI_PCIE is not set
# CONFIG_HOTPLUG_PCI_SHPC is not set
#
@@ -153,10 +161,6 @@ CONFIG_HOTPLUG_PCI_ACPI=m
# CONFIG_PCCARD is not set
#
-# PC-card bridges
-#
-
-#
# Device Drivers
#
@@ -190,6 +194,7 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=m
CONFIG_BLK_DEV_CRYPTOLOOP=m
CONFIG_BLK_DEV_NBD=m
@@ -209,6 +214,7 @@ CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_AS=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
#
# ATA/ATAPI/MFM/RLL support
@@ -283,6 +289,7 @@ CONFIG_CHR_DEV_ST=m
CONFIG_BLK_DEV_SR=m
# CONFIG_BLK_DEV_SR_VENDOR is not set
CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
@@ -310,13 +317,21 @@ CONFIG_SCSI_FC_ATTRS=y
# CONFIG_SCSI_AIC79XX is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
+CONFIG_SCSI_SATA=y
+# CONFIG_SCSI_SATA_AHCI is not set
+# CONFIG_SCSI_SATA_SVW is not set
+# CONFIG_SCSI_ATA_PIIX is not set
+# CONFIG_SCSI_SATA_NV is not set
+# CONFIG_SCSI_SATA_PROMISE is not set
+# CONFIG_SCSI_SATA_QSTOR is not set
+# CONFIG_SCSI_SATA_SX4 is not set
+# CONFIG_SCSI_SATA_SIL is not set
+# CONFIG_SCSI_SATA_SIS is not set
+# CONFIG_SCSI_SATA_ULI is not set
+# CONFIG_SCSI_SATA_VIA is not set
+CONFIG_SCSI_SATA_VITESSE=y
# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
@@ -326,7 +341,6 @@ CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
CONFIG_SCSI_QLOGIC_FC=y
# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set
CONFIG_SCSI_QLOGIC_1280=y
@@ -337,6 +351,7 @@ CONFIG_SCSI_QLA22XX=m
CONFIG_SCSI_QLA2300=m
CONFIG_SCSI_QLA2322=m
# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_DEBUG is not set
@@ -359,12 +374,16 @@ CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_MIRROR=m
CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+# CONFIG_DM_MULTIPATH_EMC is not set
#
# Fusion MPT device support
#
CONFIG_FUSION=y
-CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_SPI=y
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_MAX_SGE=128
# CONFIG_FUSION_CTL is not set
#
@@ -387,7 +406,6 @@ CONFIG_NET=y
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
@@ -447,7 +465,6 @@ CONFIG_DUMMY=m
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
#
# ARCnet devices
@@ -484,9 +501,7 @@ CONFIG_NET_PCI=y
# CONFIG_FORCEDETH is not set
# CONFIG_DGRS is not set
CONFIG_EEPRO100=m
-# CONFIG_EEPRO100_PIO is not set
CONFIG_E100=m
-# CONFIG_E100_NAPI is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
# CONFIG_NE2K_PCI is not set
@@ -508,9 +523,11 @@ CONFIG_E1000=y
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
+# CONFIG_SKGE is not set
# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
CONFIG_TIGON3=y
+# CONFIG_BNX2 is not set
#
# Ethernet (10000 Mbit)
@@ -568,25 +585,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-CONFIG_GAMEPORT=m
-CONFIG_SOUND_GAMEPORT=m
-# CONFIG_GAMEPORT_NS558 is not set
-# CONFIG_GAMEPORT_L4 is not set
-# CONFIG_GAMEPORT_EMU10K1 is not set
-# CONFIG_GAMEPORT_VORTEX is not set
-# CONFIG_GAMEPORT_FM801 is not set
-# CONFIG_GAMEPORT_CS461x is not set
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-CONFIG_SERIO_LIBPS2=y
-# CONFIG_SERIO_RAW is not set
-
-#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
@@ -604,6 +602,23 @@ CONFIG_MOUSE_PS2=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+CONFIG_GAMEPORT=m
+# CONFIG_GAMEPORT_NS558 is not set
+# CONFIG_GAMEPORT_L4 is not set
+# CONFIG_GAMEPORT_EMU10K1 is not set
+# CONFIG_GAMEPORT_VORTEX is not set
+# CONFIG_GAMEPORT_FM801 is not set
+# CONFIG_GAMEPORT_CS461X is not set
+
+#
# Character devices
#
CONFIG_VT=y
@@ -613,11 +628,15 @@ CONFIG_SERIAL_NONSTANDARD=y
# CONFIG_ROCKETPORT is not set
# CONFIG_CYCLADES is not set
# CONFIG_MOXA_SMARTIO is not set
-# CONFIG_SYNCLINK is not set
+# CONFIG_ISI is not set
# CONFIG_SYNCLINKMP is not set
# CONFIG_N_HDLC is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
# CONFIG_STALDRV is not set
CONFIG_SGI_SNSC=y
+CONFIG_SGI_TIOCX=y
+CONFIG_SGI_MBCS=m
#
# Serial drivers
@@ -638,6 +657,8 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_SGI_L1_CONSOLE=y
+CONFIG_SERIAL_SGI_IOC4=y
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -663,6 +684,7 @@ CONFIG_EFI_RTC=y
CONFIG_AGP=m
CONFIG_AGP_I460=m
CONFIG_AGP_HP_ZX1=m
+CONFIG_AGP_SGI_TIOCA=m
CONFIG_DRM=m
CONFIG_DRM_TDFX=m
CONFIG_DRM_R128=m
@@ -674,9 +696,15 @@ CONFIG_HPET=y
# CONFIG_HPET_RTC_IRQ is not set
CONFIG_HPET_MMAP=y
CONFIG_MAX_RAW_DEVS=256
+# CONFIG_HANGCHECK_TIMER is not set
CONFIG_MMTIMER=y
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
# CONFIG_I2C is not set
@@ -760,6 +788,8 @@ CONFIG_SND_CS46XX=m
CONFIG_SND_CS46XX_NEW_DSP=y
CONFIG_SND_CS4281=m
CONFIG_SND_EMU10K1=m
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_CA0106 is not set
# CONFIG_SND_KORG1212 is not set
# CONFIG_SND_MIXART is not set
# CONFIG_SND_NM256 is not set
@@ -784,13 +814,14 @@ CONFIG_SND_FM801=m
# CONFIG_SND_INTEL8X0M is not set
# CONFIG_SND_SONICVIBES is not set
# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
# CONFIG_SND_VX222 is not set
+# CONFIG_SND_HDA_INTEL is not set
#
# USB devices
#
# CONFIG_SND_USB_AUDIO is not set
-# CONFIG_SND_USB_USX2Y is not set
#
# Open Sound System
@@ -800,6 +831,8 @@ CONFIG_SND_FM801=m
#
# USB support
#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB=m
# CONFIG_USB_DEBUG is not set
@@ -811,8 +844,6 @@ CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
# CONFIG_USB_SUSPEND is not set
# CONFIG_USB_OTG is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
#
# USB Host Controller Drivers
@@ -821,6 +852,8 @@ CONFIG_USB_EHCI_HCD=m
# CONFIG_USB_EHCI_SPLIT_ISO is not set
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
CONFIG_USB_UHCI_HCD=m
# CONFIG_USB_SL811_HCD is not set
@@ -838,12 +871,11 @@ CONFIG_USB_UHCI_HCD=m
#
CONFIG_USB_STORAGE=m
# CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_RW_DETECT is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
# CONFIG_USB_STORAGE_DPCM is not set
-# CONFIG_USB_STORAGE_HP8200e is not set
+# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
# CONFIG_USB_STORAGE_JUMPSHOT is not set
@@ -893,6 +925,7 @@ CONFIG_USB_HIDINPUT=y
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RTL8150 is not set
# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=m
#
# USB port drivers
@@ -908,7 +941,6 @@ CONFIG_USB_HIDINPUT=y
#
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_TIGL is not set
# CONFIG_USB_AUERSWALD is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
@@ -917,6 +949,8 @@ CONFIG_USB_HIDINPUT=y
# CONFIG_USB_CYTHERM is not set
# CONFIG_USB_PHIDGETKIT is not set
# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_TEST is not set
#
@@ -943,6 +977,11 @@ CONFIG_INFINIBAND_IPOIB=m
# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
#
+# SN Devices
+#
+CONFIG_SGI_IOC4=y
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -964,7 +1003,12 @@ CONFIG_REISERFS_FS_POSIX_ACL=y
CONFIG_REISERFS_FS_SECURITY=y
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
+
+#
+# XFS support
+#
CONFIG_XFS_FS=y
+CONFIG_XFS_EXPORT=y
# CONFIG_XFS_RT is not set
# CONFIG_XFS_QUOTA is not set
# CONFIG_XFS_SECURITY is not set
@@ -1042,7 +1086,7 @@ CONFIG_NFSD_V4=y
CONFIG_NFSD_TCP=y
CONFIG_LOCKD=m
CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=m
+CONFIG_EXPORTFS=y
CONFIG_SUNRPC=m
CONFIG_SUNRPC_GSS=m
CONFIG_RPCSEC_GSS_KRB5=m
@@ -1128,6 +1172,8 @@ CONFIG_NLS_UTF8=m
# CONFIG_CRC_CCITT is not set
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
#
# HP Simulator drivers
@@ -1144,14 +1190,17 @@ CONFIG_CRC32=y
#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=20
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
CONFIG_IA64_GRANULE_16MB=y
# CONFIG_IA64_GRANULE_64MB is not set
# CONFIG_IA64_PRINT_HAZARDS is not set
@@ -1178,6 +1227,7 @@ CONFIG_CRYPTO_MD5=m
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
CONFIG_CRYPTO_DES=m
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
diff --git a/arch/ia64/ia32/ia32_ioctl.c b/arch/ia64/ia32/ia32_ioctl.c
index 9845dabe261..164b211f417 100644
--- a/arch/ia64/ia32/ia32_ioctl.c
+++ b/arch/ia64/ia32/ia32_ioctl.c
@@ -13,7 +13,6 @@
#define INCLUDES
#include "compat_ioctl.c"
-#include <asm/ioctl32.h>
#define IOCTL_NR(a) ((a) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
diff --git a/arch/ia64/ia32/ia32priv.h b/arch/ia64/ia32/ia32priv.h
index b2de948bdae..e3e9290e3ff 100644
--- a/arch/ia64/ia32/ia32priv.h
+++ b/arch/ia64/ia32/ia32priv.h
@@ -241,7 +241,7 @@ typedef struct compat_siginfo {
/* POSIX.1b timers */
struct {
- timer_t _tid; /* timer id */
+ compat_timer_t _tid; /* timer id */
int _overrun; /* overrun count */
char _pad[sizeof(unsigned int) - sizeof(int)];
compat_sigval_t _sigval; /* same as below */
diff --git a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
index 247a21c64ae..c1e20d65dd6 100644
--- a/arch/ia64/ia32/sys_ia32.c
+++ b/arch/ia64/ia32/sys_ia32.c
@@ -2427,7 +2427,7 @@ sys32_epoll_wait(int epfd, struct epoll_event32 __user * events, int maxevents,
{
struct epoll_event *events64 = NULL;
mm_segment_t old_fs = get_fs();
- int error, numevents, size;
+ int numevents, size;
int evt_idx;
int do_free_pages = 0;
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index c1a02bbc252..b2e2f6509eb 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -20,6 +20,8 @@ obj-$(CONFIG_SMP) += smp.o smpboot.o domain.o
obj-$(CONFIG_PERFMON) += perfmon_default_smpl.o
obj-$(CONFIG_IA64_CYCLONE) += cyclone.o
obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o
+obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o
+obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o
mca_recovery-y += mca_drv.o mca_drv_asm.o
# The gate DSO image is built using a special linker script.
diff --git a/arch/ia64/kernel/domain.c b/arch/ia64/kernel/domain.c
index fe532c97043..d65e87b6394 100644
--- a/arch/ia64/kernel/domain.c
+++ b/arch/ia64/kernel/domain.c
@@ -14,7 +14,7 @@
#include <linux/topology.h>
#include <linux/nodemask.h>
-#define SD_NODES_PER_DOMAIN 6
+#define SD_NODES_PER_DOMAIN 16
#ifdef CONFIG_NUMA
/**
@@ -27,7 +27,7 @@
*
* Should use nodemask_t.
*/
-static int __devinit find_next_best_node(int node, unsigned long *used_nodes)
+static int find_next_best_node(int node, unsigned long *used_nodes)
{
int i, n, val, min_val, best_node = 0;
@@ -66,7 +66,7 @@ static int __devinit find_next_best_node(int node, unsigned long *used_nodes)
* should be one that prevents unnecessary balancing, but also spreads tasks
* out optimally.
*/
-static cpumask_t __devinit sched_domain_node_span(int node)
+static cpumask_t sched_domain_node_span(int node)
{
int i;
cpumask_t span, nodemask;
@@ -96,7 +96,7 @@ static cpumask_t __devinit sched_domain_node_span(int node)
#ifdef CONFIG_SCHED_SMT
static DEFINE_PER_CPU(struct sched_domain, cpu_domains);
static struct sched_group sched_group_cpus[NR_CPUS];
-static int __devinit cpu_to_cpu_group(int cpu)
+static int cpu_to_cpu_group(int cpu)
{
return cpu;
}
@@ -104,7 +104,7 @@ static int __devinit cpu_to_cpu_group(int cpu)
static DEFINE_PER_CPU(struct sched_domain, phys_domains);
static struct sched_group sched_group_phys[NR_CPUS];
-static int __devinit cpu_to_phys_group(int cpu)
+static int cpu_to_phys_group(int cpu)
{
#ifdef CONFIG_SCHED_SMT
return first_cpu(cpu_sibling_map[cpu]);
@@ -125,44 +125,36 @@ static struct sched_group *sched_group_nodes[MAX_NUMNODES];
static DEFINE_PER_CPU(struct sched_domain, allnodes_domains);
static struct sched_group sched_group_allnodes[MAX_NUMNODES];
-static int __devinit cpu_to_allnodes_group(int cpu)
+static int cpu_to_allnodes_group(int cpu)
{
return cpu_to_node(cpu);
}
#endif
/*
- * Set up scheduler domains and groups. Callers must hold the hotplug lock.
+ * Build sched domains for a given set of cpus and attach the sched domains
+ * to the individual cpus
*/
-void __devinit arch_init_sched_domains(void)
+void build_sched_domains(const cpumask_t *cpu_map)
{
int i;
- cpumask_t cpu_default_map;
/*
- * Setup mask for cpus without special case scheduling requirements.
- * For now this just excludes isolated cpus, but could be used to
- * exclude other special cases in the future.
+ * Set up domains for cpus specified by the cpu_map.
*/
- cpus_complement(cpu_default_map, cpu_isolated_map);
- cpus_and(cpu_default_map, cpu_default_map, cpu_online_map);
-
- /*
- * Set up domains. Isolated domains just stay on the dummy domain.
- */
- for_each_cpu_mask(i, cpu_default_map) {
+ for_each_cpu_mask(i, *cpu_map) {
int group;
struct sched_domain *sd = NULL, *p;
cpumask_t nodemask = node_to_cpumask(cpu_to_node(i));
- cpus_and(nodemask, nodemask, cpu_default_map);
+ cpus_and(nodemask, nodemask, *cpu_map);
#ifdef CONFIG_NUMA
if (num_online_cpus()
> SD_NODES_PER_DOMAIN*cpus_weight(nodemask)) {
sd = &per_cpu(allnodes_domains, i);
*sd = SD_ALLNODES_INIT;
- sd->span = cpu_default_map;
+ sd->span = *cpu_map;
group = cpu_to_allnodes_group(i);
sd->groups = &sched_group_allnodes[group];
p = sd;
@@ -173,7 +165,7 @@ void __devinit arch_init_sched_domains(void)
*sd = SD_NODE_INIT;
sd->span = sched_domain_node_span(cpu_to_node(i));
sd->parent = p;
- cpus_and(sd->span, sd->span, cpu_default_map);
+ cpus_and(sd->span, sd->span, *cpu_map);
#endif
p = sd;
@@ -190,7 +182,7 @@ void __devinit arch_init_sched_domains(void)
group = cpu_to_cpu_group(i);
*sd = SD_SIBLING_INIT;
sd->span = cpu_sibling_map[i];
- cpus_and(sd->span, sd->span, cpu_default_map);
+ cpus_and(sd->span, sd->span, *cpu_map);
sd->parent = p;
sd->groups = &sched_group_cpus[group];
#endif
@@ -198,9 +190,9 @@ void __devinit arch_init_sched_domains(void)
#ifdef CONFIG_SCHED_SMT
/* Set up CPU (sibling) groups */
- for_each_cpu_mask(i, cpu_default_map) {
+ for_each_cpu_mask(i, *cpu_map) {
cpumask_t this_sibling_map = cpu_sibling_map[i];
- cpus_and(this_sibling_map, this_sibling_map, cpu_default_map);
+ cpus_and(this_sibling_map, this_sibling_map, *cpu_map);
if (i != first_cpu(this_sibling_map))
continue;
@@ -213,7 +205,7 @@ void __devinit arch_init_sched_domains(void)
for (i = 0; i < MAX_NUMNODES; i++) {
cpumask_t nodemask = node_to_cpumask(i);
- cpus_and(nodemask, nodemask, cpu_default_map);
+ cpus_and(nodemask, nodemask, *cpu_map);
if (cpus_empty(nodemask))
continue;
@@ -222,7 +214,7 @@ void __devinit arch_init_sched_domains(void)
}
#ifdef CONFIG_NUMA
- init_sched_build_groups(sched_group_allnodes, cpu_default_map,
+ init_sched_build_groups(sched_group_allnodes, *cpu_map,
&cpu_to_allnodes_group);
for (i = 0; i < MAX_NUMNODES; i++) {
@@ -233,12 +225,12 @@ void __devinit arch_init_sched_domains(void)
cpumask_t covered = CPU_MASK_NONE;
int j;
- cpus_and(nodemask, nodemask, cpu_default_map);
+ cpus_and(nodemask, nodemask, *cpu_map);
if (cpus_empty(nodemask))
continue;
domainspan = sched_domain_node_span(i);
- cpus_and(domainspan, domainspan, cpu_default_map);
+ cpus_and(domainspan, domainspan, *cpu_map);
sg = kmalloc(sizeof(struct sched_group), GFP_KERNEL);
sched_group_nodes[i] = sg;
@@ -266,7 +258,7 @@ void __devinit arch_init_sched_domains(void)
int n = (i + j) % MAX_NUMNODES;
cpus_complement(notcovered, covered);
- cpus_and(tmp, notcovered, cpu_default_map);
+ cpus_and(tmp, notcovered, *cpu_map);
cpus_and(tmp, tmp, domainspan);
if (cpus_empty(tmp))
break;
@@ -293,7 +285,7 @@ void __devinit arch_init_sched_domains(void)
#endif
/* Calculate CPU power for physical packages and nodes */
- for_each_cpu_mask(i, cpu_default_map) {
+ for_each_cpu_mask(i, *cpu_map) {
int power;
struct sched_domain *sd;
#ifdef CONFIG_SCHED_SMT
@@ -359,13 +351,35 @@ next_sg:
cpu_attach_domain(sd, i);
}
}
+/*
+ * Set up scheduler domains and groups. Callers must hold the hotplug lock.
+ */
+void arch_init_sched_domains(const cpumask_t *cpu_map)
+{
+ cpumask_t cpu_default_map;
+
+ /*
+ * Setup mask for cpus without special case scheduling requirements.
+ * For now this just excludes isolated cpus, but could be used to
+ * exclude other special cases in the future.
+ */
+ cpus_andnot(cpu_default_map, *cpu_map, cpu_isolated_map);
+
+ build_sched_domains(&cpu_default_map);
+}
-void __devinit arch_destroy_sched_domains(void)
+void arch_destroy_sched_domains(const cpumask_t *cpu_map)
{
#ifdef CONFIG_NUMA
int i;
for (i = 0; i < MAX_NUMNODES; i++) {
+ cpumask_t nodemask = node_to_cpumask(i);
struct sched_group *oldsg, *sg = sched_group_nodes[i];
+
+ cpus_and(nodemask, nodemask, *cpu_map);
+ if (cpus_empty(nodemask))
+ continue;
+
if (sg == NULL)
continue;
sg = sg->next;
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index 4a3b1aac43e..179f230816e 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -410,6 +410,38 @@ efi_memmap_walk (efi_freemem_callback_t callback, void *arg)
}
/*
+ * Walk the EFI memory map to pull out leftover pages in the lower
+ * memory regions which do not end up in the regular memory map and
+ * stick them into the uncached allocator
+ *
+ * The regular walk function is significantly more complex than the
+ * uncached walk which means it really doesn't make sense to try and
+ * marge the two.
+ */
+void __init
+efi_memmap_walk_uc (efi_freemem_callback_t callback)
+{
+ void *efi_map_start, *efi_map_end, *p;
+ efi_memory_desc_t *md;
+ u64 efi_desc_size, start, end;
+
+ efi_map_start = __va(ia64_boot_param->efi_memmap);
+ efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
+ efi_desc_size = ia64_boot_param->efi_memdesc_size;
+
+ for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+ md = p;
+ if (md->attribute == EFI_MEMORY_UC) {
+ start = PAGE_ALIGN(md->phys_addr);
+ end = PAGE_ALIGN((md->phys_addr+(md->num_pages << EFI_PAGE_SHIFT)) & PAGE_MASK);
+ if ((*callback)(start, end, NULL) < 0)
+ return;
+ }
+ }
+}
+
+
+/*
* Look for the PAL_CODE region reported by EFI and maps it using an
* ITR to enable safe PAL calls in virtual mode. See IA-64 Processor
* Abstraction Layer chapter 11 in ADAG
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 81c45d44739..b1d5d3d5276 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1182,7 +1182,7 @@ ENTRY(notify_resume_user)
;;
(pNonSys) mov out2=0 // out2==0 => not a syscall
.fframe 16
- .spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!)
+ .spillsp ar.unat, 16
st8 [sp]=r9,-16 // allocate space for ar.unat and save it
st8 [out1]=loc1,-8 // save ar.pfs, out1=&sigscratch
.body
@@ -1208,7 +1208,7 @@ GLOBAL_ENTRY(sys_rt_sigsuspend)
adds out2=8,sp // out2=&sigscratch->ar_pfs
;;
.fframe 16
- .spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!)
+ .spillsp ar.unat, 16
st8 [sp]=r9,-16 // allocate space for ar.unat and save it
st8 [out2]=loc1,-8 // save ar.pfs, out2=&sigscratch
.body
@@ -1579,7 +1579,7 @@ sys_call_table:
data8 sys_keyctl
data8 sys_ni_syscall
data8 sys_ni_syscall // 1275
- data8 sys_ni_syscall
+ data8 sys_set_zone_reclaim
data8 sys_ni_syscall
data8 sys_ni_syscall
data8 sys_ni_syscall
diff --git a/arch/ia64/kernel/entry.h b/arch/ia64/kernel/entry.h
index 6d4ecec989b..78eeb079341 100644
--- a/arch/ia64/kernel/entry.h
+++ b/arch/ia64/kernel/entry.h
@@ -60,7 +60,7 @@
.spillsp @priunat,SW(AR_UNAT)+16+(off); \
.spillsp ar.rnat,SW(AR_RNAT)+16+(off); \
.spillsp ar.bspstore,SW(AR_BSPSTORE)+16+(off); \
- .spillsp pr,SW(PR)+16+(off))
+ .spillsp pr,SW(PR)+16+(off)
#define DO_SAVE_SWITCH_STACK \
movl r28=1f; \
diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S
index 4f3cdef7579..962b6c4e32b 100644
--- a/arch/ia64/kernel/fsys.S
+++ b/arch/ia64/kernel/fsys.S
@@ -460,9 +460,9 @@ EX(.fail_efault, ld8 r14=[r33]) // r14 <- *set
;;
st8 [r2]=r14 // update current->blocked with new mask
- cmpxchg4.acq r14=[r9],r18,ar.ccv // current->thread_info->flags <- r18
+ cmpxchg4.acq r8=[r9],r18,ar.ccv // current->thread_info->flags <- r18
;;
- cmp.ne p6,p0=r17,r14 // update failed?
+ cmp.ne p6,p0=r17,r8 // update failed?
(p6) br.cond.spnt.few 1b // yes -> retry
#ifdef CONFIG_SMP
diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S
index d9c05d53435..2bc085a73e3 100644
--- a/arch/ia64/kernel/ivt.S
+++ b/arch/ia64/kernel/ivt.S
@@ -405,17 +405,22 @@ ENTRY(nested_dtlb_miss)
* r30: continuation address
* r31: saved pr
*
- * Clobbered: b0, r18, r19, r21, psr.dt (cleared)
+ * Clobbered: b0, r18, r19, r21, r22, psr.dt (cleared)
*/
rsm psr.dt // switch to using physical data addressing
mov r19=IA64_KR(PT_BASE) // get the page table base address
shl r21=r16,3 // shift bit 60 into sign bit
+ mov r18=cr.itir
;;
shr.u r17=r16,61 // get the region number into r17
+ extr.u r18=r18,2,6 // get the faulting page size
;;
cmp.eq p6,p7=5,r17 // is faulting address in region 5?
- shr.u r18=r16,PGDIR_SHIFT // get bits 33-63 of faulting address
+ add r22=-PAGE_SHIFT,r18 // adjustment for hugetlb address
+ add r18=PGDIR_SHIFT-PAGE_SHIFT,r18
;;
+ shr.u r22=r16,r22
+ shr.u r18=r16,r18
(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place
srlz.d
@@ -428,7 +433,7 @@ ENTRY(nested_dtlb_miss)
(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=PTA + IFA(33,42)*8
(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=PTA + (((IFA(61,63) << 7) | IFA(33,39))*8)
cmp.eq p7,p6=0,r21 // unused address bits all zeroes?
- shr.u r18=r16,PMD_SHIFT // shift L2 index into position
+ shr.u r18=r22,PMD_SHIFT // shift L2 index into position
;;
ld8 r17=[r17] // fetch the L1 entry (may be 0)
;;
@@ -436,7 +441,7 @@ ENTRY(nested_dtlb_miss)
dep r17=r18,r17,3,(PAGE_SHIFT-3) // compute address of L2 page table entry
;;
(p7) ld8 r17=[r17] // fetch the L2 entry (may be 0)
- shr.u r19=r16,PAGE_SHIFT // shift L3 index into position
+ shr.u r19=r22,PAGE_SHIFT // shift L3 index into position
;;
(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was L2 entry NULL?
dep r17=r19,r17,3,(PAGE_SHIFT-3) // compute address of L3 page table entry
diff --git a/arch/ia64/kernel/jprobes.S b/arch/ia64/kernel/jprobes.S
new file mode 100644
index 00000000000..b7fa3ccd2b0
--- /dev/null
+++ b/arch/ia64/kernel/jprobes.S
@@ -0,0 +1,61 @@
+/*
+ * Jprobe specific operations
+ *
+ * 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 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.
+ *
+ * Copyright (C) Intel Corporation, 2005
+ *
+ * 2005-May Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
+ * <anil.s.keshavamurthy@intel.com> initial implementation
+ *
+ * Jprobes (a.k.a. "jump probes" which is built on-top of kprobes) allow a
+ * probe to be inserted into the beginning of a function call. The fundamental
+ * difference between a jprobe and a kprobe is the jprobe handler is executed
+ * in the same context as the target function, while the kprobe handlers
+ * are executed in interrupt context.
+ *
+ * For jprobes we initially gain control by placing a break point in the
+ * first instruction of the targeted function. When we catch that specific
+ * break, we:
+ * * set the return address to our jprobe_inst_return() function
+ * * jump to the jprobe handler function
+ *
+ * Since we fixed up the return address, the jprobe handler will return to our
+ * jprobe_inst_return() function, giving us control again. At this point we
+ * are back in the parents frame marker, so we do yet another call to our
+ * jprobe_break() function to fix up the frame marker as it would normally
+ * exist in the target function.
+ *
+ * Our jprobe_return function then transfers control back to kprobes.c by
+ * executing a break instruction using one of our reserved numbers. When we
+ * catch that break in kprobes.c, we continue like we do for a normal kprobe
+ * by single stepping the emulated instruction, and then returning execution
+ * to the correct location.
+ */
+#include <asm/asmmacro.h>
+
+ /*
+ * void jprobe_break(void)
+ */
+ENTRY(jprobe_break)
+ break.m 0x80300
+END(jprobe_break)
+
+ /*
+ * void jprobe_inst_return(void)
+ */
+GLOBAL_ENTRY(jprobe_inst_return)
+ br.call.sptk.many b0=jprobe_break
+END(jprobe_inst_return)
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
new file mode 100644
index 00000000000..5978823d5c6
--- /dev/null
+++ b/arch/ia64/kernel/kprobes.c
@@ -0,0 +1,601 @@
+/*
+ * Kernel Probes (KProbes)
+ * arch/ia64/kernel/kprobes.c
+ *
+ * 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 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.
+ *
+ * Copyright (C) IBM Corporation, 2002, 2004
+ * Copyright (C) Intel Corporation, 2005
+ *
+ * 2005-Apr Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
+ * <anil.s.keshavamurthy@intel.com> adapted from i386
+ */
+
+#include <linux/config.h>
+#include <linux/kprobes.h>
+#include <linux/ptrace.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/preempt.h>
+#include <linux/moduleloader.h>
+
+#include <asm/pgtable.h>
+#include <asm/kdebug.h>
+
+extern void jprobe_inst_return(void);
+
+/* kprobe_status settings */
+#define KPROBE_HIT_ACTIVE 0x00000001
+#define KPROBE_HIT_SS 0x00000002
+
+static struct kprobe *current_kprobe, *kprobe_prev;
+static unsigned long kprobe_status, kprobe_status_prev;
+static struct pt_regs jprobe_saved_regs;
+
+enum instruction_type {A, I, M, F, B, L, X, u};
+static enum instruction_type bundle_encoding[32][3] = {
+ { M, I, I }, /* 00 */
+ { M, I, I }, /* 01 */
+ { M, I, I }, /* 02 */
+ { M, I, I }, /* 03 */
+ { M, L, X }, /* 04 */
+ { M, L, X }, /* 05 */
+ { u, u, u }, /* 06 */
+ { u, u, u }, /* 07 */
+ { M, M, I }, /* 08 */
+ { M, M, I }, /* 09 */
+ { M, M, I }, /* 0A */
+ { M, M, I }, /* 0B */
+ { M, F, I }, /* 0C */
+ { M, F, I }, /* 0D */
+ { M, M, F }, /* 0E */
+ { M, M, F }, /* 0F */
+ { M, I, B }, /* 10 */
+ { M, I, B }, /* 11 */
+ { M, B, B }, /* 12 */
+ { M, B, B }, /* 13 */
+ { u, u, u }, /* 14 */
+ { u, u, u }, /* 15 */
+ { B, B, B }, /* 16 */
+ { B, B, B }, /* 17 */
+ { M, M, B }, /* 18 */
+ { M, M, B }, /* 19 */
+ { u, u, u }, /* 1A */
+ { u, u, u }, /* 1B */
+ { M, F, B }, /* 1C */
+ { M, F, B }, /* 1D */
+ { u, u, u }, /* 1E */
+ { u, u, u }, /* 1F */
+};
+
+/*
+ * In this function we check to see if the instruction
+ * is IP relative instruction and update the kprobe
+ * inst flag accordingly
+ */
+static void update_kprobe_inst_flag(uint template, uint slot, uint major_opcode,
+ unsigned long kprobe_inst, struct kprobe *p)
+{
+ p->ainsn.inst_flag = 0;
+ p->ainsn.target_br_reg = 0;
+
+ if (bundle_encoding[template][slot] == B) {
+ switch (major_opcode) {
+ case INDIRECT_CALL_OPCODE:
+ p->ainsn.inst_flag |= INST_FLAG_FIX_BRANCH_REG;
+ p->ainsn.target_br_reg = ((kprobe_inst >> 6) & 0x7);
+ break;
+ case IP_RELATIVE_PREDICT_OPCODE:
+ case IP_RELATIVE_BRANCH_OPCODE:
+ p->ainsn.inst_flag |= INST_FLAG_FIX_RELATIVE_IP_ADDR;
+ break;
+ case IP_RELATIVE_CALL_OPCODE:
+ p->ainsn.inst_flag |= INST_FLAG_FIX_RELATIVE_IP_ADDR;
+ p->ainsn.inst_flag |= INST_FLAG_FIX_BRANCH_REG;
+ p->ainsn.target_br_reg = ((kprobe_inst >> 6) & 0x7);
+ break;
+ }
+ } else if (bundle_encoding[template][slot] == X) {
+ switch (major_opcode) {
+ case LONG_CALL_OPCODE:
+ p->ainsn.inst_flag |= INST_FLAG_FIX_BRANCH_REG;
+ p->ainsn.target_br_reg = ((kprobe_inst >> 6) & 0x7);
+ break;
+ }
+ }
+ return;
+}
+
+/*
+ * In this function we check to see if the instruction
+ * on which we are inserting kprobe is supported.
+ * Returns 0 if supported
+ * Returns -EINVAL if unsupported
+ */
+static int unsupported_inst(uint template, uint slot, uint major_opcode,
+ unsigned long kprobe_inst, struct kprobe *p)
+{
+ unsigned long addr = (unsigned long)p->addr;
+
+ if (bundle_encoding[template][slot] == I) {
+ switch (major_opcode) {
+ case 0x0: //I_UNIT_MISC_OPCODE:
+ /*
+ * Check for Integer speculation instruction
+ * - Bit 33-35 to be equal to 0x1
+ */
+ if (((kprobe_inst >> 33) & 0x7) == 1) {
+ printk(KERN_WARNING
+ "Kprobes on speculation inst at <0x%lx> not supported\n",
+ addr);
+ return -EINVAL;
+ }
+
+ /*
+ * IP relative mov instruction
+ * - Bit 27-35 to be equal to 0x30
+ */
+ if (((kprobe_inst >> 27) & 0x1FF) == 0x30) {
+ printk(KERN_WARNING
+ "Kprobes on \"mov r1=ip\" at <0x%lx> not supported\n",
+ addr);
+ return -EINVAL;
+
+ }
+ }
+ }
+ return 0;
+}
+
+
+/*
+ * In this function we check to see if the instruction
+ * (qp) cmpx.crel.ctype p1,p2=r2,r3
+ * on which we are inserting kprobe is cmp instruction
+ * with ctype as unc.
+ */
+static uint is_cmp_ctype_unc_inst(uint template, uint slot, uint major_opcode,
+unsigned long kprobe_inst)
+{
+ cmp_inst_t cmp_inst;
+ uint ctype_unc = 0;
+
+ if (!((bundle_encoding[template][slot] == I) ||
+ (bundle_encoding[template][slot] == M)))
+ goto out;
+
+ if (!((major_opcode == 0xC) || (major_opcode == 0xD) ||
+ (major_opcode == 0xE)))
+ goto out;
+
+ cmp_inst.l = kprobe_inst;
+ if ((cmp_inst.f.x2 == 0) || (cmp_inst.f.x2 == 1)) {
+ /* Integere compare - Register Register (A6 type)*/
+ if ((cmp_inst.f.tb == 0) && (cmp_inst.f.ta == 0)
+ &&(cmp_inst.f.c == 1))
+ ctype_unc = 1;
+ } else if ((cmp_inst.f.x2 == 2)||(cmp_inst.f.x2 == 3)) {
+ /* Integere compare - Immediate Register (A8 type)*/
+ if ((cmp_inst.f.ta == 0) &&(cmp_inst.f.c == 1))
+ ctype_unc = 1;
+ }
+out:
+ return ctype_unc;
+}
+
+/*
+ * In this function we override the bundle with
+ * the break instruction at the given slot.
+ */
+static void prepare_break_inst(uint template, uint slot, uint major_opcode,
+ unsigned long kprobe_inst, struct kprobe *p)
+{
+ unsigned long break_inst = BREAK_INST;
+ bundle_t *bundle = &p->ainsn.insn.bundle;
+
+ /*
+ * Copy the original kprobe_inst qualifying predicate(qp)
+ * to the break instruction iff !is_cmp_ctype_unc_inst
+ * because for cmp instruction with ctype equal to unc,
+ * which is a special instruction always needs to be
+ * executed regradless of qp
+ */
+ if (!is_cmp_ctype_unc_inst(template, slot, major_opcode, kprobe_inst))
+ break_inst |= (0x3f & kprobe_inst);
+
+ switch (slot) {
+ case 0:
+ bundle->quad0.slot0 = break_inst;
+ break;
+ case 1:
+ bundle->quad0.slot1_p0 = break_inst;
+ bundle->quad1.slot1_p1 = break_inst >> (64-46);
+ break;
+ case 2:
+ bundle->quad1.slot2 = break_inst;
+ break;
+ }
+
+ /*
+ * Update the instruction flag, so that we can
+ * emulate the instruction properly after we
+ * single step on original instruction
+ */
+ update_kprobe_inst_flag(template, slot, major_opcode, kprobe_inst, p);
+}
+
+static inline void get_kprobe_inst(bundle_t *bundle, uint slot,
+ unsigned long *kprobe_inst, uint *major_opcode)
+{
+ unsigned long kprobe_inst_p0, kprobe_inst_p1;
+ unsigned int template;
+
+ template = bundle->quad0.template;
+
+ switch (slot) {
+ case 0:
+ *major_opcode = (bundle->quad0.slot0 >> SLOT0_OPCODE_SHIFT);
+ *kprobe_inst = bundle->quad0.slot0;
+ break;
+ case 1:
+ *major_opcode = (bundle->quad1.slot1_p1 >> SLOT1_p1_OPCODE_SHIFT);
+ kprobe_inst_p0 = bundle->quad0.slot1_p0;
+ kprobe_inst_p1 = bundle->quad1.slot1_p1;
+ *kprobe_inst = kprobe_inst_p0 | (kprobe_inst_p1 << (64-46));
+ break;
+ case 2:
+ *major_opcode = (bundle->quad1.slot2 >> SLOT2_OPCODE_SHIFT);
+ *kprobe_inst = bundle->quad1.slot2;
+ break;
+ }
+}
+
+static int valid_kprobe_addr(int template, int slot, unsigned long addr)
+{
+ if ((slot > 2) || ((bundle_encoding[template][1] == L) && slot > 1)) {
+ printk(KERN_WARNING "Attempting to insert unaligned kprobe at 0x%lx\n",
+ addr);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static inline void save_previous_kprobe(void)
+{
+ kprobe_prev = current_kprobe;
+ kprobe_status_prev = kprobe_status;
+}
+
+static inline void restore_previous_kprobe(void)
+{
+ current_kprobe = kprobe_prev;
+ kprobe_status = kprobe_status_prev;
+}
+
+static inline void set_current_kprobe(struct kprobe *p)
+{
+ current_kprobe = p;
+}
+
+int arch_prepare_kprobe(struct kprobe *p)
+{
+ unsigned long addr = (unsigned long) p->addr;
+ unsigned long *kprobe_addr = (unsigned long *)(addr & ~0xFULL);
+ unsigned long kprobe_inst=0;
+ unsigned int slot = addr & 0xf, template, major_opcode = 0;
+ bundle_t *bundle = &p->ainsn.insn.bundle;
+
+ memcpy(&p->opcode.bundle, kprobe_addr, sizeof(bundle_t));
+ memcpy(&p->ainsn.insn.bundle, kprobe_addr, sizeof(bundle_t));
+
+ template = bundle->quad0.template;
+
+ if(valid_kprobe_addr(template, slot, addr))
+ return -EINVAL;
+
+ /* Move to slot 2, if bundle is MLX type and kprobe slot is 1 */
+ if (slot == 1 && bundle_encoding[template][1] == L)
+ slot++;
+
+ /* Get kprobe_inst and major_opcode from the bundle */
+ get_kprobe_inst(bundle, slot, &kprobe_inst, &major_opcode);
+
+ if (unsupported_inst(template, slot, major_opcode, kprobe_inst, p))
+ return -EINVAL;
+
+ prepare_break_inst(template, slot, major_opcode, kprobe_inst, p);
+
+ return 0;
+}
+
+void arch_arm_kprobe(struct kprobe *p)
+{
+ unsigned long addr = (unsigned long)p->addr;
+ unsigned long arm_addr = addr & ~0xFULL;
+
+ memcpy((char *)arm_addr, &p->ainsn.insn.bundle, sizeof(bundle_t));
+ flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
+}
+
+void arch_disarm_kprobe(struct kprobe *p)
+{
+ unsigned long addr = (unsigned long)p->addr;
+ unsigned long arm_addr = addr & ~0xFULL;
+
+ /* p->opcode contains the original unaltered bundle */
+ memcpy((char *) arm_addr, (char *) &p->opcode.bundle, sizeof(bundle_t));
+ flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
+}
+
+void arch_remove_kprobe(struct kprobe *p)
+{
+}
+
+/*
+ * We are resuming execution after a single step fault, so the pt_regs
+ * structure reflects the register state after we executed the instruction
+ * located in the kprobe (p->ainsn.insn.bundle). We still need to adjust
+ * the ip to point back to the original stack address. To set the IP address
+ * to original stack address, handle the case where we need to fixup the
+ * relative IP address and/or fixup branch register.
+ */
+static void resume_execution(struct kprobe *p, struct pt_regs *regs)
+{
+ unsigned long bundle_addr = ((unsigned long) (&p->opcode.bundle)) & ~0xFULL;
+ unsigned long resume_addr = (unsigned long)p->addr & ~0xFULL;
+ unsigned long template;
+ int slot = ((unsigned long)p->addr & 0xf);
+
+ template = p->opcode.bundle.quad0.template;
+
+ if (slot == 1 && bundle_encoding[template][1] == L)
+ slot = 2;
+
+ if (p->ainsn.inst_flag) {
+
+ if (p->ainsn.inst_flag & INST_FLAG_FIX_RELATIVE_IP_ADDR) {
+ /* Fix relative IP address */
+ regs->cr_iip = (regs->cr_iip - bundle_addr) + resume_addr;
+ }
+
+ if (p->ainsn.inst_flag & INST_FLAG_FIX_BRANCH_REG) {
+ /*
+ * Fix target branch register, software convention is
+ * to use either b0 or b6 or b7, so just checking
+ * only those registers
+ */
+ switch (p->ainsn.target_br_reg) {
+ case 0:
+ if ((regs->b0 == bundle_addr) ||
+ (regs->b0 == bundle_addr + 0x10)) {
+ regs->b0 = (regs->b0 - bundle_addr) +
+ resume_addr;
+ }
+ break;
+ case 6:
+ if ((regs->b6 == bundle_addr) ||
+ (regs->b6 == bundle_addr + 0x10)) {
+ regs->b6 = (regs->b6 - bundle_addr) +
+ resume_addr;
+ }
+ break;
+ case 7:
+ if ((regs->b7 == bundle_addr) ||
+ (regs->b7 == bundle_addr + 0x10)) {
+ regs->b7 = (regs->b7 - bundle_addr) +
+ resume_addr;
+ }
+ break;
+ } /* end switch */
+ }
+ goto turn_ss_off;
+ }
+
+ if (slot == 2) {
+ if (regs->cr_iip == bundle_addr + 0x10) {
+ regs->cr_iip = resume_addr + 0x10;
+ }
+ } else {
+ if (regs->cr_iip == bundle_addr) {
+ regs->cr_iip = resume_addr;
+ }
+ }
+
+turn_ss_off:
+ /* Turn off Single Step bit */
+ ia64_psr(regs)->ss = 0;
+}
+
+static void prepare_ss(struct kprobe *p, struct pt_regs *regs)
+{
+ unsigned long bundle_addr = (unsigned long) &p->opcode.bundle;
+ unsigned long slot = (unsigned long)p->addr & 0xf;
+
+ /* Update instruction pointer (IIP) and slot number (IPSR.ri) */
+ regs->cr_iip = bundle_addr & ~0xFULL;
+
+ if (slot > 2)
+ slot = 0;
+
+ ia64_psr(regs)->ri = slot;
+
+ /* turn on single stepping */
+ ia64_psr(regs)->ss = 1;
+}
+
+static int pre_kprobes_handler(struct die_args *args)
+{
+ struct kprobe *p;
+ int ret = 0;
+ struct pt_regs *regs = args->regs;
+ kprobe_opcode_t *addr = (kprobe_opcode_t *)instruction_pointer(regs);
+
+ preempt_disable();
+
+ /* Handle recursion cases */
+ if (kprobe_running()) {
+ p = get_kprobe(addr);
+ if (p) {
+ if (kprobe_status == KPROBE_HIT_SS) {
+ unlock_kprobes();
+ goto no_kprobe;
+ }
+ /* We have reentered the pre_kprobe_handler(), since
+ * another probe was hit while within the handler.
+ * We here save the original kprobes variables and
+ * just single step on the instruction of the new probe
+ * without calling any user handlers.
+ */
+ save_previous_kprobe();
+ set_current_kprobe(p);
+ p->nmissed++;
+ prepare_ss(p, regs);
+ kprobe_status = KPROBE_REENTER;
+ return 1;
+ } else if (args->err == __IA64_BREAK_JPROBE) {
+ /*
+ * jprobe instrumented function just completed
+ */
+ p = current_kprobe;
+ if (p->break_handler && p->break_handler(p, regs)) {
+ goto ss_probe;
+ }
+ } else {
+ /* Not our break */
+ goto no_kprobe;
+ }
+ }
+
+ lock_kprobes();
+ p = get_kprobe(addr);
+ if (!p) {
+ unlock_kprobes();
+ goto no_kprobe;
+ }
+
+ kprobe_status = KPROBE_HIT_ACTIVE;
+ set_current_kprobe(p);
+
+ if (p->pre_handler && p->pre_handler(p, regs))
+ /*
+ * Our pre-handler is specifically requesting that we just
+ * do a return. This is handling the case where the
+ * pre-handler is really our special jprobe pre-handler.
+ */
+ return 1;
+
+ss_probe:
+ prepare_ss(p, regs);
+ kprobe_status = KPROBE_HIT_SS;
+ return 1;
+
+no_kprobe:
+ preempt_enable_no_resched();
+ return ret;
+}
+
+static int post_kprobes_handler(struct pt_regs *regs)
+{
+ if (!kprobe_running())
+ return 0;
+
+ if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) {
+ kprobe_status = KPROBE_HIT_SSDONE;
+ current_kprobe->post_handler(current_kprobe, regs, 0);
+ }
+
+ resume_execution(current_kprobe, regs);
+
+ /*Restore back the original saved kprobes variables and continue. */
+ if (kprobe_status == KPROBE_REENTER) {
+ restore_previous_kprobe();
+ goto out;
+ }
+
+ unlock_kprobes();
+
+out:
+ preempt_enable_no_resched();
+ return 1;
+}
+
+static int kprobes_fault_handler(struct pt_regs *regs, int trapnr)
+{
+ if (!kprobe_running())
+ return 0;
+
+ if (current_kprobe->fault_handler &&
+ current_kprobe->fault_handler(current_kprobe, regs, trapnr))
+ return 1;
+
+ if (kprobe_status & KPROBE_HIT_SS) {
+ resume_execution(current_kprobe, regs);
+ unlock_kprobes();
+ preempt_enable_no_resched();
+ }
+
+ return 0;
+}
+
+int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
+ void *data)
+{
+ struct die_args *args = (struct die_args *)data;
+ switch(val) {
+ case DIE_BREAK:
+ if (pre_kprobes_handler(args))
+ return NOTIFY_STOP;
+ break;
+ case DIE_SS:
+ if (post_kprobes_handler(args->regs))
+ return NOTIFY_STOP;
+ break;
+ case DIE_PAGE_FAULT:
+ if (kprobes_fault_handler(args->regs, args->trapnr))
+ return NOTIFY_STOP;
+ default:
+ break;
+ }
+ return NOTIFY_DONE;
+}
+
+int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ struct jprobe *jp = container_of(p, struct jprobe, kp);
+ unsigned long addr = ((struct fnptr *)(jp->entry))->ip;
+
+ /* save architectural state */
+ jprobe_saved_regs = *regs;
+
+ /* after rfi, execute the jprobe instrumented function */
+ regs->cr_iip = addr & ~0xFULL;
+ ia64_psr(regs)->ri = addr & 0xf;
+ regs->r1 = ((struct fnptr *)(jp->entry))->gp;
+
+ /*
+ * fix the return address to our jprobe_inst_return() function
+ * in the jprobes.S file
+ */
+ regs->b0 = ((struct fnptr *)(jprobe_inst_return))->ip;
+
+ return 1;
+}
+
+int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ *regs = jprobe_saved_regs;
+ return 1;
+}
diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c
index 4d6c7b8f667..736e328b5e6 100644
--- a/arch/ia64/kernel/mca.c
+++ b/arch/ia64/kernel/mca.c
@@ -1103,8 +1103,6 @@ ia64_mca_cpe_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs)
return IRQ_HANDLED;
}
-#endif /* CONFIG_ACPI */
-
/*
* ia64_mca_cpe_poll
*
@@ -1122,6 +1120,8 @@ ia64_mca_cpe_poll (unsigned long dummy)
platform_send_ipi(first_cpu(cpu_online_map), IA64_CPEP_VECTOR, IA64_IPI_DM_INT, 0);
}
+#endif /* CONFIG_ACPI */
+
/*
* C portion of the OS INIT handler
*
@@ -1390,8 +1390,7 @@ ia64_mca_init(void)
register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction);
#ifdef CONFIG_ACPI
- /* Setup the CPEI/P vector and handler */
- cpe_vector = acpi_request_vector(ACPI_INTERRUPT_CPEI);
+ /* Setup the CPEI/P handler */
register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction);
#endif
@@ -1436,6 +1435,7 @@ ia64_mca_late_init(void)
#ifdef CONFIG_ACPI
/* Setup the CPEI/P vector and handler */
+ cpe_vector = acpi_request_vector(ACPI_INTERRUPT_CPEI);
init_timer(&cpe_poll_timer);
cpe_poll_timer.function = ia64_mca_cpe_poll;
diff --git a/arch/ia64/kernel/minstate.h b/arch/ia64/kernel/minstate.h
index 1dbc7b2497c..f6d8a010d99 100644
--- a/arch/ia64/kernel/minstate.h
+++ b/arch/ia64/kernel/minstate.h
@@ -41,7 +41,7 @@
(pKStk) addl r3=THIS_CPU(ia64_mca_data),r3;; \
(pKStk) ld8 r3 = [r3];; \
(pKStk) addl r3=IA64_MCA_CPU_INIT_STACK_OFFSET,r3;; \
-(pKStk) addl sp=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r3; \
+(pKStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r3; \
(pUStk) mov ar.rsc=0; /* set enforced lazy mode, pl 0, little-endian, loadrs=0 */ \
(pUStk) addl r22=IA64_RBS_OFFSET,r1; /* compute base of register backing store */ \
;; \
@@ -50,7 +50,6 @@
(pUStk) mov r23=ar.bspstore; /* save ar.bspstore */ \
(pUStk) dep r22=-1,r22,61,3; /* compute kernel virtual addr of RBS */ \
;; \
-(pKStk) addl r1=-IA64_PT_REGS_SIZE,r1; /* if in kernel mode, use sp (r12) */ \
(pUStk) mov ar.bspstore=r22; /* switch to kernel RBS */ \
;; \
(pUStk) mov r18=ar.bsp; \
diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c
index febc091c2f0..f1aca7cffd1 100644
--- a/arch/ia64/kernel/module.c
+++ b/arch/ia64/kernel/module.c
@@ -825,14 +825,16 @@ apply_relocate_add (Elf64_Shdr *sechdrs, const char *strtab, unsigned int symind
* XXX Should have an arch-hook for running this after final section
* addresses have been selected...
*/
- /* See if gp can cover the entire core module: */
- uint64_t gp = (uint64_t) mod->module_core + MAX_LTOFF / 2;
- if (mod->core_size >= MAX_LTOFF)
+ uint64_t gp;
+ if (mod->core_size > MAX_LTOFF)
/*
* This takes advantage of fact that SHF_ARCH_SMALL gets allocated
* at the end of the module.
*/
- gp = (uint64_t) mod->module_core + mod->core_size - MAX_LTOFF / 2;
+ gp = mod->core_size - MAX_LTOFF / 2;
+ else
+ gp = mod->core_size / 2;
+ gp = (uint64_t) mod->module_core + ((gp + 7) & -8);
mod->arch.gp = gp;
DEBUGP("%s: placing gp at 0x%lx\n", __FUNCTION__, gp);
}
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index 71c101601e3..6407bff6bfd 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -11,7 +11,7 @@
* Version Perfmon-2.x is a rewrite of perfmon-1.x
* by Stephane Eranian, Hewlett Packard Co.
*
- * Copyright (C) 1999-2003, 2005 Hewlett Packard Co
+ * Copyright (C) 1999-2005 Hewlett Packard Co
* Stephane Eranian <eranian@hpl.hp.com>
* David Mosberger-Tang <davidm@hpl.hp.com>
*
@@ -497,6 +497,9 @@ typedef struct {
static pfm_stats_t pfm_stats[NR_CPUS];
static pfm_session_t pfm_sessions; /* global sessions information */
+static spinlock_t pfm_alt_install_check = SPIN_LOCK_UNLOCKED;
+static pfm_intr_handler_desc_t *pfm_alt_intr_handler;
+
static struct proc_dir_entry *perfmon_dir;
static pfm_uuid_t pfm_null_uuid = {0,};
@@ -606,6 +609,7 @@ DEFINE_PER_CPU(unsigned long, pfm_syst_info);
DEFINE_PER_CPU(struct task_struct *, pmu_owner);
DEFINE_PER_CPU(pfm_context_t *, pmu_ctx);
DEFINE_PER_CPU(unsigned long, pmu_activation_number);
+EXPORT_PER_CPU_SYMBOL_GPL(pfm_syst_info);
/* forward declaration */
@@ -1325,7 +1329,7 @@ pfm_reserve_session(struct task_struct *task, int is_syswide, unsigned int cpu)
error_conflict:
DPRINT(("system wide not possible, conflicting session [%d] on CPU%d\n",
pfm_sessions.pfs_sys_session[cpu]->pid,
- smp_processor_id()));
+ cpu));
abort:
UNLOCK_PFS(flags);
@@ -5555,26 +5559,32 @@ pfm_interrupt_handler(int irq, void *arg, struct pt_regs *regs)
int ret;
this_cpu = get_cpu();
- min = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min;
- max = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max;
+ if (likely(!pfm_alt_intr_handler)) {
+ min = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min;
+ max = pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max;
- start_cycles = ia64_get_itc();
+ start_cycles = ia64_get_itc();
- ret = pfm_do_interrupt_handler(irq, arg, regs);
+ ret = pfm_do_interrupt_handler(irq, arg, regs);
- total_cycles = ia64_get_itc();
+ total_cycles = ia64_get_itc();
- /*
- * don't measure spurious interrupts
- */
- if (likely(ret == 0)) {
- total_cycles -= start_cycles;
+ /*
+ * don't measure spurious interrupts
+ */
+ if (likely(ret == 0)) {
+ total_cycles -= start_cycles;
- if (total_cycles < min) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min = total_cycles;
- if (total_cycles > max) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max = total_cycles;
+ if (total_cycles < min) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_min = total_cycles;
+ if (total_cycles > max) pfm_stats[this_cpu].pfm_ovfl_intr_cycles_max = total_cycles;
- pfm_stats[this_cpu].pfm_ovfl_intr_cycles += total_cycles;
+ pfm_stats[this_cpu].pfm_ovfl_intr_cycles += total_cycles;
+ }
+ }
+ else {
+ (*pfm_alt_intr_handler->handler)(irq, arg, regs);
}
+
put_cpu_no_resched();
return IRQ_HANDLED;
}
@@ -6425,6 +6435,141 @@ static struct irqaction perfmon_irqaction = {
.name = "perfmon"
};
+static void
+pfm_alt_save_pmu_state(void *data)
+{
+ struct pt_regs *regs;
+
+ regs = ia64_task_regs(current);
+
+ DPRINT(("called\n"));
+
+ /*
+ * should not be necessary but
+ * let's take not risk
+ */
+ pfm_clear_psr_up();
+ pfm_clear_psr_pp();
+ ia64_psr(regs)->pp = 0;
+
+ /*
+ * This call is required
+ * May cause a spurious interrupt on some processors
+ */
+ pfm_freeze_pmu();
+
+ ia64_srlz_d();
+}
+
+void
+pfm_alt_restore_pmu_state(void *data)
+{
+ struct pt_regs *regs;
+
+ regs = ia64_task_regs(current);
+
+ DPRINT(("called\n"));
+
+ /*
+ * put PMU back in state expected
+ * by perfmon
+ */
+ pfm_clear_psr_up();
+ pfm_clear_psr_pp();
+ ia64_psr(regs)->pp = 0;
+
+ /*
+ * perfmon runs with PMU unfrozen at all times
+ */
+ pfm_unfreeze_pmu();
+
+ ia64_srlz_d();
+}
+
+int
+pfm_install_alt_pmu_interrupt(pfm_intr_handler_desc_t *hdl)
+{
+ int ret, i;
+ int reserve_cpu;
+
+ /* some sanity checks */
+ if (hdl == NULL || hdl->handler == NULL) return -EINVAL;
+
+ /* do the easy test first */
+ if (pfm_alt_intr_handler) return -EBUSY;
+
+ /* one at a time in the install or remove, just fail the others */
+ if (!spin_trylock(&pfm_alt_install_check)) {
+ return -EBUSY;
+ }
+
+ /* reserve our session */
+ for_each_online_cpu(reserve_cpu) {
+ ret = pfm_reserve_session(NULL, 1, reserve_cpu);
+ if (ret) goto cleanup_reserve;
+ }
+
+ /* save the current system wide pmu states */
+ ret = on_each_cpu(pfm_alt_save_pmu_state, NULL, 0, 1);
+ if (ret) {
+ DPRINT(("on_each_cpu() failed: %d\n", ret));
+ goto cleanup_reserve;
+ }
+
+ /* officially change to the alternate interrupt handler */
+ pfm_alt_intr_handler = hdl;
+
+ spin_unlock(&pfm_alt_install_check);
+
+ return 0;
+
+cleanup_reserve:
+ for_each_online_cpu(i) {
+ /* don't unreserve more than we reserved */
+ if (i >= reserve_cpu) break;
+
+ pfm_unreserve_session(NULL, 1, i);
+ }
+
+ spin_unlock(&pfm_alt_install_check);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pfm_install_alt_pmu_interrupt);
+
+int
+pfm_remove_alt_pmu_interrupt(pfm_intr_handler_desc_t *hdl)
+{
+ int i;
+ int ret;
+
+ if (hdl == NULL) return -EINVAL;
+
+ /* cannot remove someone else's handler! */
+ if (pfm_alt_intr_handler != hdl) return -EINVAL;
+
+ /* one at a time in the install or remove, just fail the others */
+ if (!spin_trylock(&pfm_alt_install_check)) {
+ return -EBUSY;
+ }
+
+ pfm_alt_intr_handler = NULL;
+
+ ret = on_each_cpu(pfm_alt_restore_pmu_state, NULL, 0, 1);
+ if (ret) {
+ DPRINT(("on_each_cpu() failed: %d\n", ret));
+ }
+
+ for_each_online_cpu(i) {
+ pfm_unreserve_session(NULL, 1, i);
+ }
+
+ spin_unlock(&pfm_alt_install_check);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pfm_remove_alt_pmu_interrupt);
+
/*
* perfmon initialization routine, called from the initcall() table
*/
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index 907464ee727..6d57aebad48 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -635,11 +635,17 @@ ia64_flush_fph (struct task_struct *task)
{
struct ia64_psr *psr = ia64_psr(ia64_task_regs(task));
+ /*
+ * Prevent migrating this task while
+ * we're fiddling with the FPU state
+ */
+ preempt_disable();
if (ia64_is_local_fpu_owner(task) && psr->mfh) {
psr->mfh = 0;
task->thread.flags |= IA64_THREAD_FPH_VALID;
ia64_save_fpu(&task->thread.fph[0]);
}
+ preempt_enable();
}
/*
@@ -692,16 +698,30 @@ convert_to_non_syscall (struct task_struct *child, struct pt_regs *pt,
unsigned long cfm)
{
struct unw_frame_info info, prev_info;
- unsigned long ip, pr;
+ unsigned long ip, sp, pr;
unw_init_from_blocked_task(&info, child);
while (1) {
prev_info = info;
if (unw_unwind(&info) < 0)
return;
- if (unw_get_rp(&info, &ip) < 0)
+
+ unw_get_sp(&info, &sp);
+ if ((long)((unsigned long)child + IA64_STK_OFFSET - sp)
+ < IA64_PT_REGS_SIZE) {
+ dprintk("ptrace.%s: ran off the top of the kernel "
+ "stack\n", __FUNCTION__);
return;
- if (ip < FIXADDR_USER_END)
+ }
+ if (unw_get_pr (&prev_info, &pr) < 0) {
+ unw_get_rp(&prev_info, &ip);
+ dprintk("ptrace.%s: failed to read "
+ "predicate register (ip=0x%lx)\n",
+ __FUNCTION__, ip);
+ return;
+ }
+ if (unw_is_intr_frame(&info)
+ && (pr & (1UL << PRED_USER_STACK)))
break;
}
@@ -925,6 +945,13 @@ access_uarea (struct task_struct *child, unsigned long addr,
*data = (pt->cr_ipsr & IPSR_MASK);
return 0;
+ case PT_AR_RSC:
+ if (write_access)
+ pt->ar_rsc = *data | (3 << 2); /* force PL3 */
+ else
+ *data = pt->ar_rsc;
+ return 0;
+
case PT_AR_RNAT:
urbs_end = ia64_get_user_rbs_end(child, pt, NULL);
rnat_addr = (long) ia64_rse_rnat_addr((long *)
@@ -976,9 +1003,6 @@ access_uarea (struct task_struct *child, unsigned long addr,
case PT_AR_BSPSTORE:
ptr = pt_reg_addr(pt, ar_bspstore);
break;
- case PT_AR_RSC:
- ptr = pt_reg_addr(pt, ar_rsc);
- break;
case PT_AR_UNAT:
ptr = pt_reg_addr(pt, ar_unat);
break;
@@ -1214,7 +1238,7 @@ ptrace_getregs (struct task_struct *child, struct pt_all_user_regs __user *ppr)
static long
ptrace_setregs (struct task_struct *child, struct pt_all_user_regs __user *ppr)
{
- unsigned long psr, ec, lc, rnat, bsp, cfm, nat_bits, val = 0;
+ unsigned long psr, rsc, ec, lc, rnat, bsp, cfm, nat_bits, val = 0;
struct unw_frame_info info;
struct switch_stack *sw;
struct ia64_fpreg fpval;
@@ -1247,7 +1271,7 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs __user *ppr)
/* app regs */
retval |= __get_user(pt->ar_pfs, &ppr->ar[PT_AUR_PFS]);
- retval |= __get_user(pt->ar_rsc, &ppr->ar[PT_AUR_RSC]);
+ retval |= __get_user(rsc, &ppr->ar[PT_AUR_RSC]);
retval |= __get_user(pt->ar_bspstore, &ppr->ar[PT_AUR_BSPSTORE]);
retval |= __get_user(pt->ar_unat, &ppr->ar[PT_AUR_UNAT]);
retval |= __get_user(pt->ar_ccv, &ppr->ar[PT_AUR_CCV]);
@@ -1345,6 +1369,7 @@ ptrace_setregs (struct task_struct *child, struct pt_all_user_regs __user *ppr)
retval |= __get_user(nat_bits, &ppr->nat);
retval |= access_uarea(child, PT_CR_IPSR, &psr, 1);
+ retval |= access_uarea(child, PT_AR_RSC, &rsc, 1);
retval |= access_uarea(child, PT_AR_EC, &ec, 1);
retval |= access_uarea(child, PT_AR_LC, &lc, 1);
retval |= access_uarea(child, PT_AR_RNAT, &rnat, 1);
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index b7e6b4cb374..d14692e0920 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -720,7 +720,8 @@ cpu_init (void)
ia64_set_kr(IA64_KR_PT_BASE, __pa(ia64_imva(empty_zero_page)));
/*
- * Initialize default control register to defer all speculative faults. The
+ * Initialize default control register to defer speculative faults except
+ * for those arising from TLB misses, which are not deferred. The
* kernel MUST NOT depend on a particular setting of these bits (in other words,
* the kernel must have recovery code for all speculative accesses). Turn on
* dcr.lc as per recommendation by the architecture team. Most IA-32 apps
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
index 499b7e5317c..edd9f07860b 100644
--- a/arch/ia64/kernel/signal.c
+++ b/arch/ia64/kernel/signal.c
@@ -94,7 +94,7 @@ sys_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, long arg2,
static long
restore_sigcontext (struct sigcontext __user *sc, struct sigscratch *scr)
{
- unsigned long ip, flags, nat, um, cfm;
+ unsigned long ip, flags, nat, um, cfm, rsc;
long err;
/* Always make any pending restarted system calls return -EINTR */
@@ -106,7 +106,7 @@ restore_sigcontext (struct sigcontext __user *sc, struct sigscratch *scr)
err |= __get_user(ip, &sc->sc_ip); /* instruction pointer */
err |= __get_user(cfm, &sc->sc_cfm);
err |= __get_user(um, &sc->sc_um); /* user mask */
- err |= __get_user(scr->pt.ar_rsc, &sc->sc_ar_rsc);
+ err |= __get_user(rsc, &sc->sc_ar_rsc);
err |= __get_user(scr->pt.ar_unat, &sc->sc_ar_unat);
err |= __get_user(scr->pt.ar_fpsr, &sc->sc_ar_fpsr);
err |= __get_user(scr->pt.ar_pfs, &sc->sc_ar_pfs);
@@ -119,6 +119,7 @@ restore_sigcontext (struct sigcontext __user *sc, struct sigscratch *scr)
err |= __copy_from_user(&scr->pt.r15, &sc->sc_gr[15], 8); /* r15 */
scr->pt.cr_ifs = cfm | (1UL << 63);
+ scr->pt.ar_rsc = rsc | (3 << 2); /* force PL3 */
/* establish new instruction pointer: */
scr->pt.cr_iip = ip & ~0x3UL;
diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
index 953095e2ce1..b49d4ddaab9 100644
--- a/arch/ia64/kernel/smp.c
+++ b/arch/ia64/kernel/smp.c
@@ -269,7 +269,7 @@ smp_call_function_single (int cpuid, void (*func) (void *info), void *info, int
int me = get_cpu(); /* prevent preemption and reschedule on another processor */
if (cpuid == me) {
- printk("%s: trying to call self\n", __FUNCTION__);
+ printk(KERN_INFO "%s: trying to call self\n", __FUNCTION__);
put_cpu();
return -EBUSY;
}
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index 0d5ee57c986..623b0a54670 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -346,6 +346,7 @@ smp_callin (void)
lock_ipi_calllock();
cpu_set(cpuid, cpu_online_map);
unlock_ipi_calllock();
+ per_cpu(cpu_state, cpuid) = CPU_ONLINE;
smp_setup_percpu_timer();
@@ -611,6 +612,7 @@ void __devinit smp_prepare_boot_cpu(void)
{
cpu_set(smp_processor_id(), cpu_online_map);
cpu_set(smp_processor_id(), cpu_callin_map);
+ per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
}
/*
@@ -624,7 +626,7 @@ static struct {
__u16 thread_id;
__u16 proc_fixed_addr;
__u8 valid;
-}mt_info[NR_CPUS] __devinit;
+} mt_info[NR_CPUS] __devinitdata;
#ifdef CONFIG_HOTPLUG_CPU
static inline void
@@ -688,6 +690,7 @@ int __cpu_disable(void)
return -EBUSY;
remove_siblinginfo(cpu);
+ cpu_clear(cpu, cpu_online_map);
fixup_irqs();
local_flush_tlb_all();
cpu_clear(cpu, cpu_callin_map);
@@ -774,6 +777,7 @@ __cpu_up (unsigned int cpu)
if (cpu_isset(cpu, cpu_callin_map))
return -EINVAL;
+ per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
/* Processor goes to start_secondary(), sets online flag */
ret = do_boot_cpu(sapicid, cpu);
if (ret < 0)
diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c
index a8cf6d8a509..770fab37928 100644
--- a/arch/ia64/kernel/sys_ia64.c
+++ b/arch/ia64/kernel/sys_ia64.c
@@ -182,13 +182,6 @@ do_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, un
}
}
- /*
- * A zero mmap always succeeds in Linux, independent of whether or not the
- * remaining arguments are valid.
- */
- if (len == 0)
- goto out;
-
/* Careful about overflows.. */
len = PAGE_ALIGN(len);
if (!len || len > TASK_SIZE) {
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
index e82ad78081b..e7e520d90f0 100644
--- a/arch/ia64/kernel/traps.c
+++ b/arch/ia64/kernel/traps.c
@@ -21,12 +21,26 @@
#include <asm/intrinsics.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
+#include <asm/kdebug.h>
extern spinlock_t timerlist_lock;
fpswa_interface_t *fpswa_interface;
EXPORT_SYMBOL(fpswa_interface);
+struct notifier_block *ia64die_chain;
+static DEFINE_SPINLOCK(die_notifier_lock);
+
+int register_die_notifier(struct notifier_block *nb)
+{
+ int err = 0;
+ unsigned long flags;
+ spin_lock_irqsave(&die_notifier_lock, flags);
+ err = notifier_chain_register(&ia64die_chain, nb);
+ spin_unlock_irqrestore(&die_notifier_lock, flags);
+ return err;
+}
+
void __init
trap_init (void)
{
@@ -111,6 +125,24 @@ ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
siginfo_t siginfo;
int sig, code;
+ /* break.b always sets cr.iim to 0, which causes problems for
+ * debuggers. Get the real break number from the original instruction,
+ * but only for kernel code. User space break.b is left alone, to
+ * preserve the existing behaviour. All break codings have the same
+ * format, so there is no need to check the slot type.
+ */
+ if (break_num == 0 && !user_mode(regs)) {
+ struct ia64_psr *ipsr = ia64_psr(regs);
+ unsigned long *bundle = (unsigned long *)regs->cr_iip;
+ unsigned long slot;
+ switch (ipsr->ri) {
+ case 0: slot = (bundle[0] >> 5); break;
+ case 1: slot = (bundle[0] >> 46) | (bundle[1] << 18); break;
+ default: slot = (bundle[1] >> 23); break;
+ }
+ break_num = ((slot >> 36 & 1) << 20) | (slot >> 6 & 0xfffff);
+ }
+
/* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */
siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
siginfo.si_imm = break_num;
@@ -119,6 +151,10 @@ ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
switch (break_num) {
case 0: /* unknown error (used by GCC for __builtin_abort()) */
+ if (notify_die(DIE_BREAK, "break 0", regs, break_num, TRAP_BRKPT, SIGTRAP)
+ == NOTIFY_STOP) {
+ return;
+ }
die_if_kernel("bugcheck!", regs, break_num);
sig = SIGILL; code = ILL_ILLOPC;
break;
@@ -171,6 +207,15 @@ ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
sig = SIGILL; code = __ILL_BNDMOD;
break;
+ case 0x80200:
+ case 0x80300:
+ if (notify_die(DIE_BREAK, "kprobe", regs, break_num, TRAP_BRKPT, SIGTRAP)
+ == NOTIFY_STOP) {
+ return;
+ }
+ sig = SIGTRAP; code = TRAP_BRKPT;
+ break;
+
default:
if (break_num < 0x40000 || break_num > 0x100000)
die_if_kernel("Bad break", regs, break_num);
@@ -202,13 +247,21 @@ disabled_fph_fault (struct pt_regs *regs)
/* first, grant user-level access to fph partition: */
psr->dfh = 0;
+
+ /*
+ * Make sure that no other task gets in on this processor
+ * while we're claiming the FPU
+ */
+ preempt_disable();
#ifndef CONFIG_SMP
{
struct task_struct *fpu_owner
= (struct task_struct *)ia64_get_kr(IA64_KR_FPU_OWNER);
- if (ia64_is_local_fpu_owner(current))
+ if (ia64_is_local_fpu_owner(current)) {
+ preempt_enable_no_resched();
return;
+ }
if (fpu_owner)
ia64_flush_fph(fpu_owner);
@@ -226,6 +279,7 @@ disabled_fph_fault (struct pt_regs *regs)
*/
psr->mfh = 1;
}
+ preempt_enable_no_resched();
}
static inline int
@@ -521,7 +575,11 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
#endif
break;
case 35: siginfo.si_code = TRAP_BRANCH; ifa = 0; break;
- case 36: siginfo.si_code = TRAP_TRACE; ifa = 0; break;
+ case 36:
+ if (notify_die(DIE_SS, "ss", &regs, vector,
+ vector, SIGTRAP) == NOTIFY_STOP)
+ return;
+ siginfo.si_code = TRAP_TRACE; ifa = 0; break;
}
siginfo.si_signo = SIGTRAP;
siginfo.si_errno = 0;
diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c
new file mode 100644
index 00000000000..490dfc9ab47
--- /dev/null
+++ b/arch/ia64/kernel/uncached.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2001-2005 Silicon Graphics, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * A simple uncached page allocator using the generic allocator. This
+ * allocator first utilizes the spare (spill) pages found in the EFI
+ * memmap and will then start converting cached pages to uncached ones
+ * at a granule at a time. Node awareness is implemented by having a
+ * pool of pages per node.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/efi.h>
+#include <linux/genalloc.h>
+#include <asm/page.h>
+#include <asm/pal.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/atomic.h>
+#include <asm/tlbflush.h>
+#include <asm/sn/arch.h>
+
+#define DEBUG 0
+
+#if DEBUG
+#define dprintk printk
+#else
+#define dprintk(x...) do { } while (0)
+#endif
+
+void __init efi_memmap_walk_uc (efi_freemem_callback_t callback);
+
+#define MAX_UNCACHED_GRANULES 5
+static int allocated_granules;
+
+struct gen_pool *uncached_pool[MAX_NUMNODES];
+
+
+static void uncached_ipi_visibility(void *data)
+{
+ int status;
+
+ status = ia64_pal_prefetch_visibility(PAL_VISIBILITY_PHYSICAL);
+ if ((status != PAL_VISIBILITY_OK) &&
+ (status != PAL_VISIBILITY_OK_REMOTE_NEEDED))
+ printk(KERN_DEBUG "pal_prefetch_visibility() returns %i on "
+ "CPU %i\n", status, get_cpu());
+}
+
+
+static void uncached_ipi_mc_drain(void *data)
+{
+ int status;
+ status = ia64_pal_mc_drain();
+ if (status)
+ printk(KERN_WARNING "ia64_pal_mc_drain() failed with %i on "
+ "CPU %i\n", status, get_cpu());
+}
+
+
+static unsigned long
+uncached_get_new_chunk(struct gen_pool *poolp)
+{
+ struct page *page;
+ void *tmp;
+ int status, i;
+ unsigned long addr, node;
+
+ if (allocated_granules >= MAX_UNCACHED_GRANULES)
+ return 0;
+
+ node = poolp->private;
+ page = alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO,
+ IA64_GRANULE_SHIFT-PAGE_SHIFT);
+
+ dprintk(KERN_INFO "get_new_chunk page %p, addr %lx\n",
+ page, (unsigned long)(page-vmem_map) << PAGE_SHIFT);
+
+ /*
+ * Do magic if no mem on local node! XXX
+ */
+ if (!page)
+ return 0;
+ tmp = page_address(page);
+
+ /*
+ * There's a small race here where it's possible for someone to
+ * access the page through /dev/mem halfway through the conversion
+ * to uncached - not sure it's really worth bothering about
+ */
+ for (i = 0; i < (IA64_GRANULE_SIZE / PAGE_SIZE); i++)
+ SetPageUncached(&page[i]);
+
+ flush_tlb_kernel_range(tmp, tmp + IA64_GRANULE_SIZE);
+
+ status = ia64_pal_prefetch_visibility(PAL_VISIBILITY_PHYSICAL);
+
+ dprintk(KERN_INFO "pal_prefetch_visibility() returns %i on cpu %i\n",
+ status, get_cpu());
+
+ if (!status) {
+ status = smp_call_function(uncached_ipi_visibility, NULL, 0, 1);
+ if (status)
+ printk(KERN_WARNING "smp_call_function failed for "
+ "uncached_ipi_visibility! (%i)\n", status);
+ }
+
+ if (ia64_platform_is("sn2"))
+ sn_flush_all_caches((unsigned long)tmp, IA64_GRANULE_SIZE);
+ else
+ flush_icache_range((unsigned long)tmp,
+ (unsigned long)tmp+IA64_GRANULE_SIZE);
+
+ ia64_pal_mc_drain();
+ status = smp_call_function(uncached_ipi_mc_drain, NULL, 0, 1);
+ if (status)
+ printk(KERN_WARNING "smp_call_function failed for "
+ "uncached_ipi_mc_drain! (%i)\n", status);
+
+ addr = (unsigned long)tmp - PAGE_OFFSET + __IA64_UNCACHED_OFFSET;
+
+ allocated_granules++;
+ return addr;
+}
+
+
+/*
+ * uncached_alloc_page
+ *
+ * Allocate 1 uncached page. Allocates on the requested node. If no
+ * uncached pages are available on the requested node, roundrobin starting
+ * with higher nodes.
+ */
+unsigned long
+uncached_alloc_page(int nid)
+{
+ unsigned long maddr;
+
+ maddr = gen_pool_alloc(uncached_pool[nid], PAGE_SIZE);
+
+ dprintk(KERN_DEBUG "uncached_alloc_page returns %lx on node %i\n",
+ maddr, nid);
+
+ /*
+ * If no memory is availble on our local node, try the
+ * remaining nodes in the system.
+ */
+ if (!maddr) {
+ int i;
+
+ for (i = MAX_NUMNODES - 1; i >= 0; i--) {
+ if (i == nid || !node_online(i))
+ continue;
+ maddr = gen_pool_alloc(uncached_pool[i], PAGE_SIZE);
+ dprintk(KERN_DEBUG "uncached_alloc_page alternate search "
+ "returns %lx on node %i\n", maddr, i);
+ if (maddr) {
+ break;
+ }
+ }
+ }
+
+ return maddr;
+}
+EXPORT_SYMBOL(uncached_alloc_page);
+
+
+/*
+ * uncached_free_page
+ *
+ * Free a single uncached page.
+ */
+void
+uncached_free_page(unsigned long maddr)
+{
+ int node;
+
+ node = nasid_to_cnodeid(NASID_GET(maddr));
+
+ dprintk(KERN_DEBUG "uncached_free_page(%lx) on node %i\n", maddr, node);
+
+ if ((maddr & (0XFUL << 60)) != __IA64_UNCACHED_OFFSET)
+ panic("uncached_free_page invalid address %lx\n", maddr);
+
+ gen_pool_free(uncached_pool[node], maddr, PAGE_SIZE);
+}
+EXPORT_SYMBOL(uncached_free_page);
+
+
+/*
+ * uncached_build_memmap,
+ *
+ * Called at boot time to build a map of pages that can be used for
+ * memory special operations.
+ */
+static int __init
+uncached_build_memmap(unsigned long start, unsigned long end, void *arg)
+{
+ long length;
+ unsigned long vstart, vend;
+ int node;
+
+ length = end - start;
+ vstart = start + __IA64_UNCACHED_OFFSET;
+ vend = end + __IA64_UNCACHED_OFFSET;
+
+ dprintk(KERN_ERR "uncached_build_memmap(%lx %lx)\n", start, end);
+
+ memset((char *)vstart, 0, length);
+
+ node = nasid_to_cnodeid(NASID_GET(start));
+
+ for (; vstart < vend ; vstart += PAGE_SIZE) {
+ dprintk(KERN_INFO "sticking %lx into the pool!\n", vstart);
+ gen_pool_free(uncached_pool[node], vstart, PAGE_SIZE);
+ }
+
+ return 0;
+}
+
+
+static int __init uncached_init(void) {
+ int i;
+
+ for (i = 0; i < MAX_NUMNODES; i++) {
+ if (!node_online(i))
+ continue;
+ uncached_pool[i] = gen_pool_create(0, IA64_GRANULE_SHIFT,
+ &uncached_get_new_chunk, i);
+ }
+
+ efi_memmap_walk_uc(uncached_build_memmap);
+
+ return 0;
+}
+
+__initcall(uncached_init);
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index c0071092939..f3fd528ead3 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -560,14 +560,15 @@ void show_mem(void)
int shared = 0, cached = 0, reserved = 0;
printk("Node ID: %d\n", pgdat->node_id);
for(i = 0; i < pgdat->node_spanned_pages; i++) {
+ struct page *page = pgdat_page_nr(pgdat, i);
if (!ia64_pfn_valid(pgdat->node_start_pfn+i))
continue;
- if (PageReserved(pgdat->node_mem_map+i))
+ if (PageReserved(page))
reserved++;
- else if (PageSwapCache(pgdat->node_mem_map+i))
+ else if (PageSwapCache(page))
cached++;
- else if (page_count(pgdat->node_mem_map+i))
- shared += page_count(pgdat->node_mem_map+i)-1;
+ else if (page_count(page))
+ shared += page_count(page)-1;
}
total_present += present;
total_reserved += reserved;
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
index 4174ec999dd..ff62551eb3a 100644
--- a/arch/ia64/mm/fault.c
+++ b/arch/ia64/mm/fault.c
@@ -14,6 +14,7 @@
#include <asm/processor.h>
#include <asm/system.h>
#include <asm/uaccess.h>
+#include <asm/kdebug.h>
extern void die (char *, struct pt_regs *, long);
@@ -102,6 +103,13 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
goto bad_area_no_up;
#endif
+ /*
+ * This is to handle the kprobes on user space access instructions
+ */
+ if (notify_die(DIE_PAGE_FAULT, "page fault", regs, code, TRAP_BRKPT,
+ SIGSEGV) == NOTIFY_STOP)
+ return;
+
down_read(&mm->mmap_sem);
vma = find_vma_prev(mm, address, &prev_vma);
diff --git a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c
index df08ae7634b..e0a776a3044 100644
--- a/arch/ia64/mm/hugetlbpage.c
+++ b/arch/ia64/mm/hugetlbpage.c
@@ -24,7 +24,7 @@
unsigned int hpage_shift=HPAGE_SHIFT_DEFAULT;
-static pte_t *
+pte_t *
huge_pte_alloc (struct mm_struct *mm, unsigned long addr)
{
unsigned long taddr = htlbpage_to_page(addr);
@@ -43,7 +43,7 @@ huge_pte_alloc (struct mm_struct *mm, unsigned long addr)
return pte;
}
-static pte_t *
+pte_t *
huge_pte_offset (struct mm_struct *mm, unsigned long addr)
{
unsigned long taddr = htlbpage_to_page(addr);
@@ -67,23 +67,6 @@ huge_pte_offset (struct mm_struct *mm, unsigned long addr)
#define mk_pte_huge(entry) { pte_val(entry) |= _PAGE_P; }
-static void
-set_huge_pte (struct mm_struct *mm, struct vm_area_struct *vma,
- struct page *page, pte_t * page_table, int write_access)
-{
- pte_t entry;
-
- add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE);
- if (write_access) {
- entry =
- pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
- } else
- entry = pte_wrprotect(mk_pte(page, vma->vm_page_prot));
- entry = pte_mkyoung(entry);
- mk_pte_huge(entry);
- set_pte(page_table, entry);
- return;
-}
/*
* This function checks for proper alignment of input addr and len parameters.
*/
@@ -99,68 +82,6 @@ int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
return 0;
}
-int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
- struct vm_area_struct *vma)
-{
- pte_t *src_pte, *dst_pte, entry;
- struct page *ptepage;
- unsigned long addr = vma->vm_start;
- unsigned long end = vma->vm_end;
-
- while (addr < end) {
- dst_pte = huge_pte_alloc(dst, addr);
- if (!dst_pte)
- goto nomem;
- src_pte = huge_pte_offset(src, addr);
- entry = *src_pte;
- ptepage = pte_page(entry);
- get_page(ptepage);
- set_pte(dst_pte, entry);
- add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
- addr += HPAGE_SIZE;
- }
- return 0;
-nomem:
- return -ENOMEM;
-}
-
-int
-follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
- struct page **pages, struct vm_area_struct **vmas,
- unsigned long *st, int *length, int i)
-{
- pte_t *ptep, pte;
- unsigned long start = *st;
- unsigned long pstart;
- int len = *length;
- struct page *page;
-
- do {
- pstart = start & HPAGE_MASK;
- ptep = huge_pte_offset(mm, start);
- pte = *ptep;
-
-back1:
- page = pte_page(pte);
- if (pages) {
- page += ((start & ~HPAGE_MASK) >> PAGE_SHIFT);
- get_page(page);
- pages[i] = page;
- }
- if (vmas)
- vmas[i] = vma;
- i++;
- len--;
- start += PAGE_SIZE;
- if (((start & HPAGE_MASK) == pstart) && len &&
- (start < vma->vm_end))
- goto back1;
- } while (len && start < vma->vm_end);
- *length = len;
- *st = start;
- return i;
-}
-
struct page *follow_huge_addr(struct mm_struct *mm, unsigned long addr, int write)
{
struct page *page;
@@ -212,81 +133,6 @@ void hugetlb_free_pgd_range(struct mmu_gather **tlb,
free_pgd_range(tlb, addr, end, floor, ceiling);
}
-void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
-{
- struct mm_struct *mm = vma->vm_mm;
- unsigned long address;
- pte_t *pte;
- struct page *page;
-
- BUG_ON(start & (HPAGE_SIZE - 1));
- BUG_ON(end & (HPAGE_SIZE - 1));
-
- for (address = start; address < end; address += HPAGE_SIZE) {
- pte = huge_pte_offset(mm, address);
- if (pte_none(*pte))
- continue;
- page = pte_page(*pte);
- put_page(page);
- pte_clear(mm, address, pte);
- }
- add_mm_counter(mm, rss, - ((end - start) >> PAGE_SHIFT));
- flush_tlb_range(vma, start, end);
-}
-
-int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
-{
- struct mm_struct *mm = current->mm;
- unsigned long addr;
- int ret = 0;
-
- BUG_ON(vma->vm_start & ~HPAGE_MASK);
- BUG_ON(vma->vm_end & ~HPAGE_MASK);
-
- spin_lock(&mm->page_table_lock);
- for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
- unsigned long idx;
- pte_t *pte = huge_pte_alloc(mm, addr);
- struct page *page;
-
- if (!pte) {
- ret = -ENOMEM;
- goto out;
- }
- if (!pte_none(*pte))
- continue;
-
- idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
- + (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
- page = find_get_page(mapping, idx);
- if (!page) {
- /* charge the fs quota first */
- if (hugetlb_get_quota(mapping)) {
- ret = -ENOMEM;
- goto out;
- }
- page = alloc_huge_page();
- if (!page) {
- hugetlb_put_quota(mapping);
- ret = -ENOMEM;
- goto out;
- }
- ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
- if (! ret) {
- unlock_page(page);
- } else {
- hugetlb_put_quota(mapping);
- page_cache_release(page);
- goto out;
- }
- }
- set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE);
- }
-out:
- spin_unlock(&mm->page_table_lock);
- return ret;
-}
-
unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
unsigned long pgoff, unsigned long flags)
{
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index 547785e3cba..4eb2f52b87a 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -305,8 +305,9 @@ setup_gate (void)
struct page *page;
/*
- * Map the gate page twice: once read-only to export the ELF headers etc. and once
- * execute-only page to enable privilege-promotion via "epc":
+ * Map the gate page twice: once read-only to export the ELF
+ * headers etc. and once execute-only page to enable
+ * privilege-promotion via "epc":
*/
page = virt_to_page(ia64_imva(__start_gate_section));
put_kernel_page(page, GATE_ADDR, PAGE_READONLY);
@@ -315,6 +316,20 @@ setup_gate (void)
put_kernel_page(page, GATE_ADDR + PAGE_SIZE, PAGE_GATE);
#else
put_kernel_page(page, GATE_ADDR + PERCPU_PAGE_SIZE, PAGE_GATE);
+ /* Fill in the holes (if any) with read-only zero pages: */
+ {
+ unsigned long addr;
+
+ for (addr = GATE_ADDR + PAGE_SIZE;
+ addr < GATE_ADDR + PERCPU_PAGE_SIZE;
+ addr += PAGE_SIZE)
+ {
+ put_kernel_page(ZERO_PAGE(0), addr,
+ PAGE_READONLY);
+ put_kernel_page(ZERO_PAGE(0), addr + PERCPU_PAGE_SIZE,
+ PAGE_READONLY);
+ }
+ }
#endif
ia64_patch_gate();
}
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 88641e5095b..e3fc4edea11 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -33,8 +33,6 @@
#include <asm/hw_irq.h>
-static int pci_routeirq;
-
/*
* Low-level SAL-based PCI configuration access functions. Note that SAL
* calls are already serialized (via sal_lock), so we don't need another
@@ -139,24 +137,8 @@ static void acpi_map_iosapics(void)
static int __init
pci_acpi_init (void)
{
- struct pci_dev *dev = NULL;
-
- printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
-
acpi_map_iosapics();
- if (pci_routeirq) {
- /*
- * PCI IRQ routing is set up by pci_enable_device(), but we
- * also do it here in case there are still broken drivers that
- * don't use pci_enable_device().
- */
- printk(KERN_INFO "PCI: Routing interrupts for all devices because \"pci=routeirq\" specified\n");
- for_each_pci_dev(dev)
- acpi_pci_irq_enable(dev);
- } else
- printk(KERN_INFO "PCI: If a device doesn't work, try \"pci=routeirq\". If it helps, post a report\n");
-
return 0;
}
@@ -500,8 +482,6 @@ pcibios_align_resource (void *data, struct resource *res,
char * __init
pcibios_setup (char *str)
{
- if (!strcmp(str, "routeirq"))
- pci_routeirq = 1;
return NULL;
}
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index 4fb44984afe..44bfc7f318c 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -222,7 +222,7 @@ void __init early_sn_setup(void)
extern int platform_intr_list[];
extern nasid_t master_nasid;
-static int shub_1_1_found __initdata;
+static int __initdata shub_1_1_found = 0;
/*
* sn_check_for_wars
@@ -251,7 +251,7 @@ static void __init sn_check_for_wars(void)
} else {
for_each_online_node(cnode) {
if (is_shub_1_1(cnodeid_to_nasid(cnode)))
- sn_hub_info->shub_1_1_found = 1;
+ shub_1_1_found = 1;
}
}
}
@@ -271,6 +271,8 @@ void __init sn_setup(char **cmdline_p)
int major = sn_sal_rev_major(), minor = sn_sal_rev_minor();
extern void sn_cpu_init(void);
+ ia64_sn_plat_set_error_handling_features();
+
/*
* If the generic code has enabled vga console support - lets
* get rid of it again. This is a kludge for the fact that ACPI
diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c
index ab9b5f35c2a..a087b274847 100644
--- a/arch/ia64/sn/kernel/tiocx.c
+++ b/arch/ia64/sn/kernel/tiocx.c
@@ -432,7 +432,7 @@ static int tiocx_reload(struct cx_dev *cx_dev)
return cx_device_reload(cx_dev);
}
-static ssize_t show_cxdev_control(struct device *dev, char *buf)
+static ssize_t show_cxdev_control(struct device *dev, struct device_attribute *attr, char *buf)
{
struct cx_dev *cx_dev = to_cx_dev(dev);
@@ -442,7 +442,7 @@ static ssize_t show_cxdev_control(struct device *dev, char *buf)
tiocx_btchar_get(cx_dev->cx_id.nasid));
}
-static ssize_t store_cxdev_control(struct device *dev, const char *buf,
+static ssize_t store_cxdev_control(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
int n;
@@ -518,25 +518,22 @@ static int __init tiocx_init(void)
return 0;
}
-static void __exit tiocx_exit(void)
+static int cx_remove_device(struct device * dev, void * data)
{
- struct device *dev;
- struct device *tdev;
+ struct cx_dev *cx_dev = to_cx_dev(dev);
+ device_remove_file(dev, &dev_attr_cxdev_control);
+ cx_device_unregister(cx_dev);
+ return 0;
+}
+static void __exit tiocx_exit(void)
+{
DBG("tiocx_exit\n");
/*
* Unregister devices.
*/
- list_for_each_entry_safe(dev, tdev, &tiocx_bus_type.devices.list,
- bus_list) {
- if (dev) {
- struct cx_dev *cx_dev = to_cx_dev(dev);
- device_remove_file(dev, &dev_attr_cxdev_control);
- cx_device_unregister(cx_dev);
- }
- }
-
+ bus_for_each_dev(&tiocx_bus_type, NULL, NULL, cx_remove_device);
bus_unregister(&tiocx_bus_type);
}
diff --git a/arch/ia64/sn/kernel/xpc.h b/arch/ia64/sn/kernel/xpc.h
index 1a0aed8490d..d0ee635daf2 100644
--- a/arch/ia64/sn/kernel/xpc.h
+++ b/arch/ia64/sn/kernel/xpc.h
@@ -87,7 +87,7 @@ struct xpc_rsvd_page {
u8 partid; /* partition ID from SAL */
u8 version;
u8 pad[6]; /* pad to u64 align */
- u64 vars_pa;
+ volatile u64 vars_pa;
u64 part_nasids[XP_NASID_MASK_WORDS] ____cacheline_aligned;
u64 mach_nasids[XP_NASID_MASK_WORDS] ____cacheline_aligned;
};
@@ -138,7 +138,7 @@ struct xpc_vars {
* occupies half a cacheline.
*/
struct xpc_vars_part {
- u64 magic;
+ volatile u64 magic;
u64 openclose_args_pa; /* physical address of open and close args */
u64 GPs_pa; /* physical address of Get/Put values */
@@ -185,8 +185,8 @@ struct xpc_vars_part {
* Define a Get/Put value pair (pointers) used with a message queue.
*/
struct xpc_gp {
- s64 get; /* Get value */
- s64 put; /* Put value */
+ volatile s64 get; /* Get value */
+ volatile s64 put; /* Put value */
};
#define XPC_GP_SIZE \
@@ -231,7 +231,7 @@ struct xpc_openclose_args {
*/
struct xpc_notify {
struct semaphore sema; /* notify semaphore */
- u8 type; /* type of notification */
+ volatile u8 type; /* type of notification */
/* the following two fields are only used if type == XPC_N_CALL */
xpc_notify_func func; /* user's notify function */
@@ -439,7 +439,7 @@ struct xpc_partition {
/* XPC infrastructure referencing and teardown control */
- u8 setup_state; /* infrastructure setup state */
+ volatile u8 setup_state; /* infrastructure setup state */
wait_queue_head_t teardown_wq; /* kthread waiting to teardown infra */
atomic_t references; /* #of references to infrastructure */
diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c
index 0bf6fbcc46d..6d02dac8056 100644
--- a/arch/ia64/sn/kernel/xpc_channel.c
+++ b/arch/ia64/sn/kernel/xpc_channel.c
@@ -209,7 +209,7 @@ xpc_setup_infrastructure(struct xpc_partition *part)
* With the setting of the partition setup_state to XPC_P_SETUP, we're
* declaring that this partition is ready to go.
*/
- (volatile u8) part->setup_state = XPC_P_SETUP;
+ part->setup_state = XPC_P_SETUP;
/*
@@ -227,7 +227,7 @@ xpc_setup_infrastructure(struct xpc_partition *part)
xpc_vars_part[partid].IPI_phys_cpuid =
cpu_physical_id(smp_processor_id());
xpc_vars_part[partid].nchannels = part->nchannels;
- (volatile u64) xpc_vars_part[partid].magic = XPC_VP_MAGIC1;
+ xpc_vars_part[partid].magic = XPC_VP_MAGIC1;
return xpcSuccess;
}
@@ -355,7 +355,7 @@ xpc_pull_remote_vars_part(struct xpc_partition *part)
/* let the other side know that we've pulled their variables */
- (volatile u64) xpc_vars_part[partid].magic = XPC_VP_MAGIC2;
+ xpc_vars_part[partid].magic = XPC_VP_MAGIC2;
}
if (pulled_entry->magic == XPC_VP_MAGIC1) {
@@ -1183,7 +1183,7 @@ xpc_process_msg_IPI(struct xpc_partition *part, int ch_number)
*/
xpc_clear_local_msgqueue_flags(ch);
- (volatile s64) ch->w_remote_GP.get = ch->remote_GP.get;
+ ch->w_remote_GP.get = ch->remote_GP.get;
dev_dbg(xpc_chan, "w_remote_GP.get changed to %ld, partid=%d, "
"channel=%d\n", ch->w_remote_GP.get, ch->partid,
@@ -1211,7 +1211,7 @@ xpc_process_msg_IPI(struct xpc_partition *part, int ch_number)
*/
xpc_clear_remote_msgqueue_flags(ch);
- (volatile s64) ch->w_remote_GP.put = ch->remote_GP.put;
+ ch->w_remote_GP.put = ch->remote_GP.put;
dev_dbg(xpc_chan, "w_remote_GP.put changed to %ld, partid=%d, "
"channel=%d\n", ch->w_remote_GP.put, ch->partid,
@@ -1875,7 +1875,7 @@ xpc_send_msg(struct xpc_channel *ch, struct xpc_msg *msg, u8 notify_type,
notify = &ch->notify_queue[msg_number % ch->local_nentries];
notify->func = func;
notify->key = key;
- (volatile u8) notify->type = notify_type;
+ notify->type = notify_type;
// >>> is a mb() needed here?
diff --git a/arch/ia64/sn/kernel/xpc_partition.c b/arch/ia64/sn/kernel/xpc_partition.c
index 2c3c4a8af55..578265ea9e6 100644
--- a/arch/ia64/sn/kernel/xpc_partition.c
+++ b/arch/ia64/sn/kernel/xpc_partition.c
@@ -22,6 +22,7 @@
#include <linux/cache.h>
#include <linux/mmzone.h>
#include <linux/nodemask.h>
+#include <asm/uncached.h>
#include <asm/sn/bte.h>
#include <asm/sn/intr.h>
#include <asm/sn/sn_sal.h>
@@ -183,7 +184,7 @@ xpc_rsvd_page_init(void)
* memory protections are never restricted.
*/
if ((amos_page = xpc_vars->amos_page) == NULL) {
- amos_page = (AMO_t *) mspec_kalloc_page(0);
+ amos_page = (AMO_t *) TO_AMO(uncached_alloc_page(0));
if (amos_page == NULL) {
dev_err(xpc_part, "can't allocate page of AMOs\n");
return NULL;
@@ -200,7 +201,8 @@ xpc_rsvd_page_init(void)
if (ret != 0) {
dev_err(xpc_part, "can't change memory "
"protections\n");
- mspec_kfree_page((unsigned long) amos_page);
+ uncached_free_page(__IA64_UNCACHED_OFFSET |
+ TO_PHYS((u64) amos_page));
return NULL;
}
}
@@ -251,7 +253,7 @@ xpc_rsvd_page_init(void)
* This signifies to the remote partition that our reserved
* page is initialized.
*/
- (volatile u64) rp->vars_pa = __pa(xpc_vars);
+ rp->vars_pa = __pa(xpc_vars);
return rp;
}
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index 0d90ea58a0c..42ca8a39798 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -78,6 +78,9 @@ config PLAT_OAKS32R
config PLAT_MAPPI2
bool "Mappi-II(M3A-ZA36/M3A-ZA52)"
+config PLAT_MAPPI3
+ bool "Mappi-III(M3A-2170)"
+
endchoice
choice
@@ -134,6 +137,7 @@ config BUS_CLOCK
int "Bus Clock [Hz] (integer)"
default "70000000" if PLAT_MAPPI
default "25000000" if PLAT_USRV
+ default "50000000" if PLAT_MAPPI3
default "50000000" if PLAT_M32700UT
default "50000000" if PLAT_OPSPUT
default "33333333" if PLAT_OAKS32R
@@ -149,7 +153,7 @@ config CPU_LITTLE_ENDIAN
config MEMORY_START
hex "Physical memory start address (hex)"
- default "08000000" if PLAT_MAPPI || PLAT_MAPPI2
+ default "08000000" if PLAT_MAPPI || PLAT_MAPPI2 || PLAT_MAPPI3
default "08000000" if PLAT_USRV
default "08000000" if PLAT_M32700UT
default "08000000" if PLAT_OPSPUT
@@ -157,6 +161,7 @@ config MEMORY_START
config MEMORY_SIZE
hex "Physical memory size (hex)"
+ default "08000000" if PLAT_MAPPI3
default "04000000" if PLAT_MAPPI || PLAT_MAPPI2
default "02000000" if PLAT_USRV
default "01000000" if PLAT_M32700UT
@@ -167,11 +172,13 @@ config NOHIGHMEM
bool
default y
-config DISCONTIGMEM
+config ARCH_DISCONTIGMEM_ENABLE
bool "Internal RAM Support"
depends on CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP
default y
+source "mm/Kconfig"
+
config IRAM_START
hex "Internal memory start address (hex)"
default "00f00000"
diff --git a/arch/m32r/boot/compressed/m32r_sio.c b/arch/m32r/boot/compressed/m32r_sio.c
index bad5475eff9..8f9a57271f8 100644
--- a/arch/m32r/boot/compressed/m32r_sio.c
+++ b/arch/m32r/boot/compressed/m32r_sio.c
@@ -6,6 +6,7 @@
*/
#include <linux/config.h>
+#include <asm/processor.h>
static void putc(char c);
@@ -38,16 +39,17 @@ static int puts(const char *s)
static void putc(char c)
{
-
- while ((*BOOT_SIO0STS & 0x3) != 0x3) ;
+ while ((*BOOT_SIO0STS & 0x3) != 0x3)
+ cpu_relax();
if (c == '\n') {
*BOOT_SIO0TXB = '\r';
- while ((*BOOT_SIO0STS & 0x3) != 0x3) ;
+ while ((*BOOT_SIO0STS & 0x3) != 0x3)
+ cpu_relax();
}
*BOOT_SIO0TXB = c;
}
-#else /* defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_M32700UT) */
-#ifdef CONFIG_MMU
+#else /* !(CONFIG_PLAT_M32700UT_Alpha) && !(CONFIG_PLAT_M32700UT) */
+#if defined(CONFIG_PLAT_MAPPI2)
#define SIO0STS (volatile unsigned short *)(0xa0efd000 + 14)
#define SIO0TXB (volatile unsigned short *)(0xa0efd000 + 30)
#else
@@ -57,11 +59,12 @@ static void putc(char c)
static void putc(char c)
{
-
- while ((*SIO0STS & 0x1) == 0) ;
+ while ((*SIO0STS & 0x1) == 0)
+ cpu_relax();
if (c == '\n') {
*SIO0TXB = '\r';
- while ((*SIO0STS & 0x1) == 0) ;
+ while ((*SIO0STS & 0x1) == 0)
+ cpu_relax();
}
*SIO0TXB = c;
}
diff --git a/arch/m32r/defconfig b/arch/m32r/defconfig
index 417c95ba87e..85309309316 100644
--- a/arch/m32r/defconfig
+++ b/arch/m32r/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:10:44 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun 3 16:20:11 2005
#
CONFIG_M32R=y
# CONFIG_UID16 is not set
@@ -16,6 +16,7 @@ CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -28,13 +29,15 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
CONFIG_HOTPLUG=y
CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
# CONFIG_IKCONFIG_PROC is not set
CONFIG_EMBEDDED=y
# CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -44,6 +47,7 @@ CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -65,6 +69,7 @@ CONFIG_PLAT_M32700UT=y
# CONFIG_PLAT_OPSPUT is not set
# CONFIG_PLAT_OAKS32R is not set
# CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_PLAT_MAPPI3 is not set
CONFIG_CHIP_M32700=y
# CONFIG_CHIP_M32102 is not set
# CONFIG_CHIP_VDEC2 is not set
@@ -268,7 +273,6 @@ CONFIG_NET=y
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
@@ -393,18 +397,6 @@ CONFIG_INPUT=y
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -414,6 +406,17 @@ CONFIG_SERIO_SERPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -465,6 +468,10 @@ CONFIG_DS1302=y
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+
+#
# I2C support
#
# CONFIG_I2C is not set
@@ -508,8 +515,14 @@ CONFIG_VIDEO_M32R_AR_M64278=y
# Graphics support
#
CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SOFT_CURSOR is not set
+# CONFIG_FB_MACMODES is not set
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
#
@@ -543,10 +556,6 @@ CONFIG_LOGO_LINUX_CLUT224=y
# CONFIG_USB_ARCH_HAS_OHCI is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
@@ -719,8 +728,9 @@ CONFIG_NLS_DEFAULT="iso8859-1"
#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_FRAME_POINTER is not set
diff --git a/arch/m32r/kernel/Makefile b/arch/m32r/kernel/Makefile
index cfd690bf6d8..6c6b6c37663 100644
--- a/arch/m32r/kernel/Makefile
+++ b/arch/m32r/kernel/Makefile
@@ -10,6 +10,7 @@ obj-y := process.o entry.o traps.o align.o irq.o setup.o time.o \
obj-$(CONFIG_SMP) += smp.o smpboot.o
obj-$(CONFIG_PLAT_MAPPI) += setup_mappi.o io_mappi.o
obj-$(CONFIG_PLAT_MAPPI2) += setup_mappi2.o io_mappi2.o
+obj-$(CONFIG_PLAT_MAPPI3) += setup_mappi3.o io_mappi3.o
obj-$(CONFIG_PLAT_USRV) += setup_usrv.o io_usrv.o
obj-$(CONFIG_PLAT_M32700UT) += setup_m32700ut.o io_m32700ut.o
obj-$(CONFIG_PLAT_OPSPUT) += setup_opsput.o io_opsput.o
@@ -17,4 +18,3 @@ obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_PLAT_OAKS32R) += setup_oaks32r.o io_oaks32r.o
EXTRA_AFLAGS := -traditional
-
diff --git a/arch/m32r/kernel/io_m32700ut.c b/arch/m32r/kernel/io_m32700ut.c
index 371ba904e96..e545b065f7e 100644
--- a/arch/m32r/kernel/io_m32700ut.c
+++ b/arch/m32r/kernel/io_m32700ut.c
@@ -3,8 +3,8 @@
*
* Typical I/O routines for M32700UT board.
*
- * Copyright (c) 2001, 2002 Hiroyuki Kondo, Hirokazu Takata,
- * Hitoshi Yamamoto, Takeo Takahashi
+ * Copyright (c) 2001-2005 Hiroyuki Kondo, Hirokazu Takata,
+ * Hitoshi Yamamoto, Takeo Takahashi
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file "COPYING" in the main directory of this
@@ -172,64 +172,21 @@ unsigned long _inl(unsigned long port)
unsigned char _inb_p(unsigned long port)
{
- unsigned char v;
-
- if (port >= LAN_IOSTART && port < LAN_IOEND)
- v = _ne_inb(PORT2ADDR_NE(port));
- else
-#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
- if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
- return *(volatile unsigned char *)__port2addr_ata(port);
- } else
-#endif
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
- if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
- unsigned char b;
- pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
- return b;
- } else
-#endif
- v = *(volatile unsigned char *)PORT2ADDR(port);
-
+ unsigned char v = _inb(port);
delay();
return (v);
}
unsigned short _inw_p(unsigned long port)
{
- unsigned short v;
-
- if (port >= LAN_IOSTART && port < LAN_IOEND)
- v = _ne_inw(PORT2ADDR_NE(port));
- else
-#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
- if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
- return *(volatile unsigned short *)__port2addr_ata(port);
- } else
-#endif
-#if defined(CONFIG_USB)
- if(port >= 0x340 && port < 0x3a0)
- return *(volatile unsigned short *)PORT2ADDR_USB(port);
- else
-#endif
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
- if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
- unsigned short w;
- pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
- return w;
- } else
-#endif
- v = *(volatile unsigned short *)PORT2ADDR(port);
-
+ unsigned short v = _inw(port);
delay();
return (v);
}
unsigned long _inl_p(unsigned long port)
{
- unsigned long v;
-
- v = *(volatile unsigned long *)PORT2ADDR(port);
+ unsigned long v = _inl(port);
delay();
return (v);
}
@@ -287,52 +244,19 @@ void _outl(unsigned long l, unsigned long port)
void _outb_p(unsigned char b, unsigned long port)
{
- if (port >= LAN_IOSTART && port < LAN_IOEND)
- _ne_outb(b, PORT2ADDR_NE(port));
- else
-#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
- if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
- *(volatile unsigned char *)__port2addr_ata(port) = b;
- } else
-#endif
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
- if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
- pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
- } else
-#endif
- *(volatile unsigned char *)PORT2ADDR(port) = b;
-
+ _outb(b, port);
delay();
}
void _outw_p(unsigned short w, unsigned long port)
{
- if (port >= LAN_IOSTART && port < LAN_IOEND)
- _ne_outw(w, PORT2ADDR_NE(port));
- else
-#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
- if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
- *(volatile unsigned short *)__port2addr_ata(port) = w;
- } else
-#endif
-#if defined(CONFIG_USB)
- if(port >= 0x340 && port < 0x3a0)
- *(volatile unsigned short *)PORT2ADDR_USB(port) = w;
- else
-#endif
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
- if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
- pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
- } else
-#endif
- *(volatile unsigned short *)PORT2ADDR(port) = w;
-
+ _outw(w, port);
delay();
}
void _outl_p(unsigned long l, unsigned long port)
{
- *(volatile unsigned long *)PORT2ADDR(port) = l;
+ _outl(l, port);
delay();
}
diff --git a/arch/m32r/kernel/io_mappi.c b/arch/m32r/kernel/io_mappi.c
index 85688ffb52f..78033165fb5 100644
--- a/arch/m32r/kernel/io_mappi.c
+++ b/arch/m32r/kernel/io_mappi.c
@@ -3,8 +3,8 @@
*
* Typical I/O routines for Mappi board.
*
- * Copyright (c) 2001, 2002 Hiroyuki Kondo, Hirokazu Takata,
- * Hitoshi Yamamoto
+ * Copyright (c) 2001-2005 Hiroyuki Kondo, Hirokazu Takata,
+ * Hitoshi Yamamoto
*/
#include <linux/config.h>
@@ -130,57 +130,21 @@ unsigned long _inl(unsigned long port)
unsigned char _inb_p(unsigned long port)
{
- unsigned char v;
-
- if (port >= 0x300 && port < 0x320)
- v = _ne_inb(PORT2ADDR_NE(port));
- else
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
- if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
- unsigned char b;
- pcc_ioread(0, port, &b, sizeof(b), 1, 0);
- return b;
- } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
- unsigned char b;
- pcc_ioread(1, port, &b, sizeof(b), 1, 0);
- return b;
- } else
-#endif
- v = *(volatile unsigned char *)PORT2ADDR(port);
-
+ unsigned char v = _inb(port);
delay();
return (v);
}
unsigned short _inw_p(unsigned long port)
{
- unsigned short v;
-
- if (port >= 0x300 && port < 0x320)
- v = _ne_inw(PORT2ADDR_NE(port));
- else
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
- if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
- unsigned short w;
- pcc_ioread(0, port, &w, sizeof(w), 1, 0);
- return w;
- } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
- unsigned short w;
- pcc_ioread(1, port, &w, sizeof(w), 1, 0);
- return w;
- } else
-#endif
- v = *(volatile unsigned short *)PORT2ADDR(port);
-
+ unsigned short v = _inw(port);
delay();
return (v);
}
unsigned long _inl_p(unsigned long port)
{
- unsigned long v;
-
- v = *(volatile unsigned long *)PORT2ADDR(port);
+ unsigned long v = _inl(port);
delay();
return (v);
}
@@ -229,41 +193,19 @@ void _outl(unsigned long l, unsigned long port)
void _outb_p(unsigned char b, unsigned long port)
{
- if (port >= 0x300 && port < 0x320)
- _ne_outb(b, PORT2ADDR_NE(port));
- else
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
- if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
- pcc_iowrite(0, port, &b, sizeof(b), 1, 0);
- } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
- pcc_iowrite(1, port, &b, sizeof(b), 1, 0);
- } else
-#endif
- *(volatile unsigned char *)PORT2ADDR(port) = b;
-
+ _outb(b, port);
delay();
}
void _outw_p(unsigned short w, unsigned long port)
{
- if (port >= 0x300 && port < 0x320)
- _ne_outw(w, PORT2ADDR_NE(port));
- else
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
- if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
- pcc_iowrite(0, port, &w, sizeof(w), 1, 0);
- } else if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
- pcc_iowrite(1, port, &w, sizeof(w), 1, 0);
- } else
-#endif
- *(volatile unsigned short *)PORT2ADDR(port) = w;
-
+ _outw(w, port);
delay();
}
void _outl_p(unsigned long l, unsigned long port)
{
- *(volatile unsigned long *)PORT2ADDR(port) = l;
+ _outl(l, port);
delay();
}
diff --git a/arch/m32r/kernel/io_mappi2.c b/arch/m32r/kernel/io_mappi2.c
index 4182cd4f97c..5c03504bf65 100644
--- a/arch/m32r/kernel/io_mappi2.c
+++ b/arch/m32r/kernel/io_mappi2.c
@@ -3,7 +3,7 @@
*
* Typical I/O routines for Mappi2 board.
*
- * Copyright (c) 2001-2003 Hiroyuki Kondo, Hirokazu Takata,
+ * Copyright (c) 2001-2005 Hiroyuki Kondo, Hirokazu Takata,
* Hitoshi Yamamoto, Mamoru Sakugawa
*/
@@ -25,7 +25,7 @@ extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int);
extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int);
extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int);
extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
-#endif /* CONFIG_PCMCIA && CONFIG_MAPPI2_CFC */
+#endif /* CONFIG_PCMCIA && CONFIG_M32R_CFC */
#define PORT2ADDR(port) _port2addr(port)
#define PORT2ADDR_NE(port) _port2addr_ne(port)
@@ -169,64 +169,21 @@ unsigned long _inl(unsigned long port)
unsigned char _inb_p(unsigned long port)
{
- unsigned char v;
-
- if (port >= LAN_IOSTART && port < LAN_IOEND)
- v = _ne_inb(PORT2ADDR_NE(port));
- else
-#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
- if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
- return *(volatile unsigned char *)__port2addr_ata(port);
- } else
-#endif
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
- if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
- unsigned char b;
- pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
- return b;
- } else
-#endif
- v = *(volatile unsigned char *)PORT2ADDR(port);
-
+ unsigned char v = _inb(port);
delay();
return (v);
}
unsigned short _inw_p(unsigned long port)
{
- unsigned short v;
-
- if (port >= LAN_IOSTART && port < LAN_IOEND)
- v = _ne_inw(PORT2ADDR_NE(port));
- else
-#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
- if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
- return *(volatile unsigned short *)__port2addr_ata(port);
- } else
-#endif
-#if defined(CONFIG_USB)
- if (port >= 0x340 && port < 0x3a0)
- v = *(volatile unsigned short *)PORT2ADDR_USB(port);
- else
-#endif
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
- if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
- unsigned short w;
- pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
- return w;
- } else
-#endif
- v = *(volatile unsigned short *)PORT2ADDR(port);
-
+ unsigned short v = _inw(port);
delay();
return (v);
}
unsigned long _inl_p(unsigned long port)
{
- unsigned long v;
-
- v = *(volatile unsigned long *)PORT2ADDR(port);
+ unsigned long v = _inl(port);
delay();
return (v);
}
@@ -284,52 +241,19 @@ void _outl(unsigned long l, unsigned long port)
void _outb_p(unsigned char b, unsigned long port)
{
- if (port >= LAN_IOSTART && port < LAN_IOEND)
- _ne_outb(b, PORT2ADDR_NE(port));
- else
-#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
- if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
- *(volatile unsigned char *)__port2addr_ata(port) = b;
- } else
-#endif
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
- if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
- pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
- } else
-#endif
- *(volatile unsigned char *)PORT2ADDR(port) = b;
-
+ _outb(b, port);
delay();
}
void _outw_p(unsigned short w, unsigned long port)
{
- if (port >= LAN_IOSTART && port < LAN_IOEND)
- _ne_outw(w, PORT2ADDR_NE(port));
- else
-#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
- if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
- *(volatile unsigned short *)__port2addr_ata(port) = w;
- } else
-#endif
-#if defined(CONFIG_USB)
- if (port >= 0x340 && port < 0x3a0)
- *(volatile unsigned short *)PORT2ADDR_USB(port) = w;
- else
-#endif
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
- if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
- pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
- } else
-#endif
- *(volatile unsigned short *)PORT2ADDR(port) = w;
-
+ _outw(w, port);
delay();
}
void _outl_p(unsigned long l, unsigned long port)
{
- *(volatile unsigned long *)PORT2ADDR(port) = l;
+ _outl(l, port);
delay();
}
diff --git a/arch/m32r/kernel/io_mappi3.c b/arch/m32r/kernel/io_mappi3.c
new file mode 100644
index 00000000000..c80bde65785
--- /dev/null
+++ b/arch/m32r/kernel/io_mappi3.c
@@ -0,0 +1,378 @@
+/*
+ * linux/arch/m32r/kernel/io_mappi3.c
+ *
+ * Typical I/O routines for Mappi3 board.
+ *
+ * Copyright (c) 2001-2005 Hiroyuki Kondo, Hirokazu Takata,
+ * Hitoshi Yamamoto, Mamoru Sakugawa
+ */
+
+#include <linux/config.h>
+#include <asm/m32r.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+#include <linux/types.h>
+
+#define M32R_PCC_IOMAP_SIZE 0x1000
+
+#define M32R_PCC_IOSTART0 0x1000
+#define M32R_PCC_IOEND0 (M32R_PCC_IOSTART0 + M32R_PCC_IOMAP_SIZE - 1)
+
+extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
+#endif /* CONFIG_PCMCIA && CONFIG_M32R_CFC */
+
+#define PORT2ADDR(port) _port2addr(port)
+#define PORT2ADDR_NE(port) _port2addr_ne(port)
+#define PORT2ADDR_USB(port) _port2addr_usb(port)
+
+static inline void *_port2addr(unsigned long port)
+{
+ return (void *)(port + NONCACHE_OFFSET);
+}
+
+#define LAN_IOSTART 0x300
+#define LAN_IOEND 0x320
+
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+static inline void *__port2addr_ata(unsigned long port)
+{
+ static int dummy_reg;
+
+ switch (port) {
+ case 0x1f0: return (void *)0xb4002000;
+ case 0x1f1: return (void *)0xb4012800;
+ case 0x1f2: return (void *)0xb4012002;
+ case 0x1f3: return (void *)0xb4012802;
+ case 0x1f4: return (void *)0xb4012004;
+ case 0x1f5: return (void *)0xb4012804;
+ case 0x1f6: return (void *)0xb4012006;
+ case 0x1f7: return (void *)0xb4012806;
+ case 0x3f6: return (void *)0xb401200e;
+ default: return (void *)&dummy_reg;
+ }
+}
+#endif
+
+static inline void *_port2addr_ne(unsigned long port)
+{
+ return (void *)(port + NONCACHE_OFFSET + 0x10000000);
+}
+
+static inline void *_port2addr_usb(unsigned long port)
+{
+ return (void *)(port + NONCACHE_OFFSET + 0x12000000);
+}
+static inline void delay(void)
+{
+ __asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
+}
+
+/*
+ * NIC I/O function
+ */
+
+static inline unsigned char _ne_inb(void *portp)
+{
+ return (unsigned char) *(volatile unsigned char *)portp;
+}
+
+static inline unsigned short _ne_inw(void *portp)
+{
+ return (unsigned short)le16_to_cpu(*(volatile unsigned short *)portp);
+}
+
+static inline void _ne_insb(void *portp, void * addr, unsigned long count)
+{
+ unsigned char *buf = addr;
+
+ while (count--)
+ *buf++ = *(volatile unsigned char *)portp;
+}
+
+static inline void _ne_outb(unsigned char b, void *portp)
+{
+ *(volatile unsigned char *)portp = (unsigned char)b;
+}
+
+static inline void _ne_outw(unsigned short w, void *portp)
+{
+ *(volatile unsigned short *)portp = cpu_to_le16(w);
+}
+
+unsigned char _inb(unsigned long port)
+{
+ if (port >= LAN_IOSTART && port < LAN_IOEND)
+ return _ne_inb(PORT2ADDR_NE(port));
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+ else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+ return *(volatile unsigned char *)__port2addr_ata(port);
+ }
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+ else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+ unsigned char b;
+ pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
+ return b;
+ } else
+#endif
+ return *(volatile unsigned char *)PORT2ADDR(port);
+}
+
+unsigned short _inw(unsigned long port)
+{
+ if (port >= LAN_IOSTART && port < LAN_IOEND)
+ return _ne_inw(PORT2ADDR_NE(port));
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+ else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+ return *(volatile unsigned short *)__port2addr_ata(port);
+ }
+#endif
+#if defined(CONFIG_USB)
+ else if (port >= 0x340 && port < 0x3a0)
+ return *(volatile unsigned short *)PORT2ADDR_USB(port);
+#endif
+
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+ else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+ unsigned short w;
+ pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
+ return w;
+ } else
+#endif
+ return *(volatile unsigned short *)PORT2ADDR(port);
+}
+
+unsigned long _inl(unsigned long port)
+{
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+ if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+ unsigned long l;
+ pcc_ioread_word(0, port, &l, sizeof(l), 1, 0);
+ return l;
+ } else
+#endif
+ return *(volatile unsigned long *)PORT2ADDR(port);
+}
+
+unsigned char _inb_p(unsigned long port)
+{
+ unsigned char v = _inb(port);
+ delay();
+ return (v);
+}
+
+unsigned short _inw_p(unsigned long port)
+{
+ unsigned short v = _inw(port);
+ delay();
+ return (v);
+}
+
+unsigned long _inl_p(unsigned long port)
+{
+ unsigned long v = _inl(port);
+ delay();
+ return (v);
+}
+
+void _outb(unsigned char b, unsigned long port)
+{
+ if (port >= LAN_IOSTART && port < LAN_IOEND)
+ _ne_outb(b, PORT2ADDR_NE(port));
+ else
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+ if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+ *(volatile unsigned char *)__port2addr_ata(port) = b;
+ } else
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+ if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+ pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
+ } else
+#endif
+ *(volatile unsigned char *)PORT2ADDR(port) = b;
+}
+
+void _outw(unsigned short w, unsigned long port)
+{
+ if (port >= LAN_IOSTART && port < LAN_IOEND)
+ _ne_outw(w, PORT2ADDR_NE(port));
+ else
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+ if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+ *(volatile unsigned short *)__port2addr_ata(port) = w;
+ } else
+#endif
+#if defined(CONFIG_USB)
+ if (port >= 0x340 && port < 0x3a0)
+ *(volatile unsigned short *)PORT2ADDR_USB(port) = w;
+ else
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+ if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+ pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
+ } else
+#endif
+ *(volatile unsigned short *)PORT2ADDR(port) = w;
+}
+
+void _outl(unsigned long l, unsigned long port)
+{
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+ if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+ pcc_iowrite_word(0, port, &l, sizeof(l), 1, 0);
+ } else
+#endif
+ *(volatile unsigned long *)PORT2ADDR(port) = l;
+}
+
+void _outb_p(unsigned char b, unsigned long port)
+{
+ _outb(b, port);
+ delay();
+}
+
+void _outw_p(unsigned short w, unsigned long port)
+{
+ _outw(w, port);
+ delay();
+}
+
+void _outl_p(unsigned long l, unsigned long port)
+{
+ _outl(l, port);
+ delay();
+}
+
+void _insb(unsigned int port, void * addr, unsigned long count)
+{
+ if (port >= LAN_IOSTART && port < LAN_IOEND)
+ _ne_insb(PORT2ADDR_NE(port), addr, count);
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+ else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+ unsigned char *buf = addr;
+ unsigned char *portp = __port2addr_ata(port);
+ while (count--)
+ *buf++ = *(volatile unsigned char *)portp;
+ }
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+ else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+ pcc_ioread_byte(0, port, (void *)addr, sizeof(unsigned char),
+ count, 1);
+ }
+#endif
+ else {
+ unsigned char *buf = addr;
+ unsigned char *portp = PORT2ADDR(port);
+ while (count--)
+ *buf++ = *(volatile unsigned char *)portp;
+ }
+}
+
+void _insw(unsigned int port, void * addr, unsigned long count)
+{
+ unsigned short *buf = addr;
+ unsigned short *portp;
+
+ if (port >= LAN_IOSTART && port < LAN_IOEND) {
+ portp = PORT2ADDR_NE(port);
+ while (count--)
+ *buf++ = *(volatile unsigned short *)portp;
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+ } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+ pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short),
+ count, 1);
+#endif
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+ } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+ portp = __port2addr_ata(port);
+ while (count--)
+ *buf++ = *(volatile unsigned short *)portp;
+#endif
+ } else {
+ portp = PORT2ADDR(port);
+ while (count--)
+ *buf++ = *(volatile unsigned short *)portp;
+ }
+}
+
+void _insl(unsigned int port, void * addr, unsigned long count)
+{
+ unsigned long *buf = addr;
+ unsigned long *portp;
+
+ portp = PORT2ADDR(port);
+ while (count--)
+ *buf++ = *(volatile unsigned long *)portp;
+}
+
+void _outsb(unsigned int port, const void * addr, unsigned long count)
+{
+ const unsigned char *buf = addr;
+ unsigned char *portp;
+
+ if (port >= LAN_IOSTART && port < LAN_IOEND) {
+ portp = PORT2ADDR_NE(port);
+ while (count--)
+ _ne_outb(*buf++, portp);
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+ } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+ portp = __port2addr_ata(port);
+ while (count--)
+ *(volatile unsigned char *)portp = *buf++;
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+ } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+ pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char),
+ count, 1);
+#endif
+ } else {
+ portp = PORT2ADDR(port);
+ while (count--)
+ *(volatile unsigned char *)portp = *buf++;
+ }
+}
+
+void _outsw(unsigned int port, const void * addr, unsigned long count)
+{
+ const unsigned short *buf = addr;
+ unsigned short *portp;
+
+ if (port >= LAN_IOSTART && port < LAN_IOEND) {
+ portp = PORT2ADDR_NE(port);
+ while (count--)
+ *(volatile unsigned short *)portp = *buf++;
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+ } else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+ portp = __port2addr_ata(port);
+ while (count--)
+ *(volatile unsigned short *)portp = *buf++;
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+ } else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+ pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short),
+ count, 1);
+#endif
+ } else {
+ portp = PORT2ADDR(port);
+ while (count--)
+ *(volatile unsigned short *)portp = *buf++;
+ }
+}
+
+void _outsl(unsigned int port, const void * addr, unsigned long count)
+{
+ const unsigned long *buf = addr;
+ unsigned char *portp;
+
+ portp = PORT2ADDR(port);
+ while (count--)
+ *(volatile unsigned long *)portp = *buf++;
+}
diff --git a/arch/m32r/kernel/io_oaks32r.c b/arch/m32r/kernel/io_oaks32r.c
index 286964794d5..9997dddd24d 100644
--- a/arch/m32r/kernel/io_oaks32r.c
+++ b/arch/m32r/kernel/io_oaks32r.c
@@ -3,7 +3,7 @@
*
* Typical I/O routines for OAKS32R board.
*
- * Copyright (c) 2001-2004 Hiroyuki Kondo, Hirokazu Takata,
+ * Copyright (c) 2001-2005 Hiroyuki Kondo, Hirokazu Takata,
* Hitoshi Yamamoto, Mamoru Sakugawa
*/
@@ -90,35 +90,21 @@ unsigned long _inl(unsigned long port)
unsigned char _inb_p(unsigned long port)
{
- unsigned char v;
-
- if (port >= 0x300 && port < 0x320)
- v = _ne_inb(PORT2ADDR_NE(port));
- else
- v = *(volatile unsigned char *)PORT2ADDR(port);
-
+ unsigned char v = _inb(port);
delay();
return (v);
}
unsigned short _inw_p(unsigned long port)
{
- unsigned short v;
-
- if (port >= 0x300 && port < 0x320)
- v = _ne_inw(PORT2ADDR_NE(port));
- else
- v = *(volatile unsigned short *)PORT2ADDR(port);
-
+ unsigned short v = _inw(port);
delay();
return (v);
}
unsigned long _inl_p(unsigned long port)
{
- unsigned long v;
-
- v = *(volatile unsigned long *)PORT2ADDR(port);
+ unsigned long v = _inl(port);
delay();
return (v);
}
@@ -146,27 +132,19 @@ void _outl(unsigned long l, unsigned long port)
void _outb_p(unsigned char b, unsigned long port)
{
- if (port >= 0x300 && port < 0x320)
- _ne_outb(b, PORT2ADDR_NE(port));
- else
- *(volatile unsigned char *)PORT2ADDR(port) = b;
-
+ _outb(b, port);
delay();
}
void _outw_p(unsigned short w, unsigned long port)
{
- if (port >= 0x300 && port < 0x320)
- _ne_outw(w, PORT2ADDR_NE(port));
- else
- *(volatile unsigned short *)PORT2ADDR(port) = w;
-
+ _outw(w, port);
delay();
}
void _outl_p(unsigned long l, unsigned long port)
{
- *(volatile unsigned long *)PORT2ADDR(port) = l;
+ _outl(l, port);
delay();
}
diff --git a/arch/m32r/kernel/io_opsput.c b/arch/m32r/kernel/io_opsput.c
index aaf42f9f76d..e34951e8156 100644
--- a/arch/m32r/kernel/io_opsput.c
+++ b/arch/m32r/kernel/io_opsput.c
@@ -1,10 +1,10 @@
/*
- * linux/arch/m32r/kernel/io_mappi.c
+ * linux/arch/m32r/kernel/io_opsput.c
*
* Typical I/O routines for OPSPUT board.
*
- * Copyright (c) 2001, 2002 Hiroyuki Kondo, Hirokazu Takata,
- * Hitoshi Yamamoto, Takeo Takahashi
+ * Copyright (c) 2001-2005 Hiroyuki Kondo, Hirokazu Takata,
+ * Hitoshi Yamamoto, Takeo Takahashi
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file "COPYING" in the main directory of this
@@ -98,7 +98,6 @@ unsigned char _inb(unsigned long port)
{
if (port >= LAN_IOSTART && port < LAN_IOEND)
return _ne_inb(PORT2ADDR_NE(port));
-
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
unsigned char b;
@@ -118,7 +117,6 @@ unsigned short _inw(unsigned long port)
else if(port >= 0x340 && port < 0x3a0)
return *(volatile unsigned short *)PORT2ADDR_USB(port);
#endif
-
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
unsigned short w;
@@ -143,55 +141,21 @@ unsigned long _inl(unsigned long port)
unsigned char _inb_p(unsigned long port)
{
- unsigned char v;
-
- if (port >= LAN_IOSTART && port < LAN_IOEND)
- v = _ne_inb(PORT2ADDR_NE(port));
- else
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
- if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
- unsigned char b;
- pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
- return b;
- } else
-#endif
- v = *(volatile unsigned char *)PORT2ADDR(port);
-
+ unsigned char v = _inb(port);
delay();
return (v);
}
unsigned short _inw_p(unsigned long port)
{
- unsigned short v;
-
- if (port >= LAN_IOSTART && port < LAN_IOEND)
- v = _ne_inw(PORT2ADDR_NE(port));
- else
-#if defined(CONFIG_USB)
- if(port >= 0x340 && port < 0x3a0)
- return *(volatile unsigned short *)PORT2ADDR_USB(port);
- else
-#endif
-
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
- if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
- unsigned short w;
- pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
- return w;
- } else
-#endif
- v = *(volatile unsigned short *)PORT2ADDR(port);
-
+ unsigned short v = _inw(port);
delay();
return (v);
}
unsigned long _inl_p(unsigned long port)
{
- unsigned long v;
-
- v = *(volatile unsigned long *)PORT2ADDR(port);
+ unsigned long v = _inl(port);
delay();
return (v);
}
@@ -219,7 +183,6 @@ void _outw(unsigned short w, unsigned long port)
*(volatile unsigned short *)PORT2ADDR_USB(port) = w;
else
#endif
-
#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
@@ -240,43 +203,19 @@ void _outl(unsigned long l, unsigned long port)
void _outb_p(unsigned char b, unsigned long port)
{
- if (port >= LAN_IOSTART && port < LAN_IOEND)
- _ne_outb(b, PORT2ADDR_NE(port));
- else
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
- if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
- pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
- } else
-#endif
- *(volatile unsigned char *)PORT2ADDR(port) = b;
-
+ _outb(b, port);
delay();
}
void _outw_p(unsigned short w, unsigned long port)
{
- if (port >= LAN_IOSTART && port < LAN_IOEND)
- _ne_outw(w, PORT2ADDR_NE(port));
- else
-#if defined(CONFIG_USB)
- if(port >= 0x340 && port < 0x3a0)
- *(volatile unsigned short *)PORT2ADDR_USB(port) = w;
- else
-#endif
-
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
- if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
- pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
- } else
-#endif
- *(volatile unsigned short *)PORT2ADDR(port) = w;
-
+ _outw(w, port);
delay();
}
void _outl_p(unsigned long l, unsigned long port)
{
- *(volatile unsigned long *)PORT2ADDR(port) = l;
+ _outl(l, port);
delay();
}
diff --git a/arch/m32r/kernel/io_usrv.c b/arch/m32r/kernel/io_usrv.c
index 27928a0b99e..9eb161dcc10 100644
--- a/arch/m32r/kernel/io_usrv.c
+++ b/arch/m32r/kernel/io_usrv.c
@@ -3,8 +3,8 @@
*
* Typical I/O routines for uServer board.
*
- * Copyright (c) 2001 - 2003 Hiroyuki Kondo, Hirokazu Takata,
- * Hitoshi Yamamoto, Takeo Takahashi
+ * Copyright (c) 2001-2005 Hiroyuki Kondo, Hirokazu Takata,
+ * Hitoshi Yamamoto, Takeo Takahashi
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file "COPYING" in the main directory of this
@@ -39,7 +39,7 @@ extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
#define PORT2ADDR(port) _port2addr(port)
-static __inline__ void *_port2addr(unsigned long port)
+static inline void *_port2addr(unsigned long port)
{
#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
if (port >= UART0_IOSTART && port <= UART0_IOEND)
@@ -50,7 +50,7 @@ static __inline__ void *_port2addr(unsigned long port)
return (void *)(port + NONCACHE_OFFSET);
}
-static __inline__ void delay(void)
+static inline void delay(void)
{
__asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
}
@@ -87,39 +87,22 @@ unsigned long _inl(unsigned long port)
unsigned char _inb_p(unsigned long port)
{
- unsigned char b;
-
- if (port >= CFC_IOSTART && port <= CFC_IOEND) {
- pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
- return b;
- } else {
- b = *(volatile unsigned char *)PORT2ADDR(port);
- delay();
- return b;
- }
+ unsigned char v = _inb(port);
+ delay();
+ return v;
}
unsigned short _inw_p(unsigned long port)
{
- unsigned short w;
-
- if (port >= CFC_IOSTART && port <= CFC_IOEND) {
- pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
- return w;
- } else {
- w = *(volatile unsigned short *)PORT2ADDR(port);
- delay();
- return w;
- }
+ unsigned short v = _inw(port);
+ delay();
+ return v;
}
unsigned long _inl_p(unsigned long port)
{
- unsigned long v;
-
- v = *(volatile unsigned long *)PORT2ADDR(port);
+ unsigned long v = _inl(port);
delay();
-
return v;
}
@@ -149,25 +132,19 @@ void _outl(unsigned long l, unsigned long port)
void _outb_p(unsigned char b, unsigned long port)
{
- if (port >= CFC_IOSTART && port <= CFC_IOEND)
- pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
- else
- *(volatile unsigned char *)PORT2ADDR(port) = b;
+ _outb(b, port);
delay();
}
void _outw_p(unsigned short w, unsigned long port)
{
- if (port >= CFC_IOSTART && port <= CFC_IOEND)
- pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
- else
- *(volatile unsigned short *)PORT2ADDR(port) = w;
+ _outw(w, port);
delay();
}
void _outl_p(unsigned long l, unsigned long port)
{
- *(volatile unsigned long *)PORT2ADDR(port) = l;
+ _outl(l, port);
delay();
}
diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c
index 4826cd6e40e..ec5674727e7 100644
--- a/arch/m32r/kernel/setup.c
+++ b/arch/m32r/kernel/setup.c
@@ -330,6 +330,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "Machine\t\t: Mappi Evaluation board\n");
#elif CONFIG_PLAT_MAPPI2
seq_printf(m, "Machine\t\t: Mappi-II Evaluation board\n");
+#elif CONFIG_PLAT_MAPPI3
+ seq_printf(m, "Machine\t\t: Mappi-III Evaluation board\n");
#elif CONFIG_PLAT_M32700UT
seq_printf(m, "Machine\t\t: M32700UT Evaluation board\n");
#elif CONFIG_PLAT_OPSPUT
diff --git a/arch/m32r/kernel/setup_m32700ut.c b/arch/m32r/kernel/setup_m32700ut.c
index 488aa87bab7..b014e2c1e52 100644
--- a/arch/m32r/kernel/setup_m32700ut.c
+++ b/arch/m32r/kernel/setup_m32700ut.c
@@ -78,13 +78,13 @@ static void shutdown_m32700ut_irq(unsigned int irq)
static struct hw_interrupt_type m32700ut_irq_type =
{
- "M32700UT-IRQ",
- startup_m32700ut_irq,
- shutdown_m32700ut_irq,
- enable_m32700ut_irq,
- disable_m32700ut_irq,
- mask_and_ack_m32700ut,
- end_m32700ut_irq
+ .typename = "M32700UT-IRQ",
+ .startup = startup_m32700ut_irq,
+ .shutdown = shutdown_m32700ut_irq,
+ .enable = enable_m32700ut_irq,
+ .disable = disable_m32700ut_irq,
+ .ack = mask_and_ack_m32700ut,
+ .end = end_m32700ut_irq
};
/*
@@ -155,13 +155,13 @@ static void shutdown_m32700ut_pld_irq(unsigned int irq)
static struct hw_interrupt_type m32700ut_pld_irq_type =
{
- "M32700UT-PLD-IRQ",
- startup_m32700ut_pld_irq,
- shutdown_m32700ut_pld_irq,
- enable_m32700ut_pld_irq,
- disable_m32700ut_pld_irq,
- mask_and_ack_m32700ut_pld,
- end_m32700ut_pld_irq
+ .typename = "M32700UT-PLD-IRQ",
+ .startup = startup_m32700ut_pld_irq,
+ .shutdown = shutdown_m32700ut_pld_irq,
+ .enable = enable_m32700ut_pld_irq,
+ .disable = disable_m32700ut_pld_irq,
+ .ack = mask_and_ack_m32700ut_pld,
+ .end = end_m32700ut_pld_irq
};
/*
@@ -224,13 +224,13 @@ static void shutdown_m32700ut_lanpld_irq(unsigned int irq)
static struct hw_interrupt_type m32700ut_lanpld_irq_type =
{
- "M32700UT-PLD-LAN-IRQ",
- startup_m32700ut_lanpld_irq,
- shutdown_m32700ut_lanpld_irq,
- enable_m32700ut_lanpld_irq,
- disable_m32700ut_lanpld_irq,
- mask_and_ack_m32700ut_lanpld,
- end_m32700ut_lanpld_irq
+ .typename = "M32700UT-PLD-LAN-IRQ",
+ .startup = startup_m32700ut_lanpld_irq,
+ .shutdown = shutdown_m32700ut_lanpld_irq,
+ .enable = enable_m32700ut_lanpld_irq,
+ .disable = disable_m32700ut_lanpld_irq,
+ .ack = mask_and_ack_m32700ut_lanpld,
+ .end = end_m32700ut_lanpld_irq
};
/*
@@ -293,13 +293,13 @@ static void shutdown_m32700ut_lcdpld_irq(unsigned int irq)
static struct hw_interrupt_type m32700ut_lcdpld_irq_type =
{
- "M32700UT-PLD-LCD-IRQ",
- startup_m32700ut_lcdpld_irq,
- shutdown_m32700ut_lcdpld_irq,
- enable_m32700ut_lcdpld_irq,
- disable_m32700ut_lcdpld_irq,
- mask_and_ack_m32700ut_lcdpld,
- end_m32700ut_lcdpld_irq
+ .typename = "M32700UT-PLD-LCD-IRQ",
+ .startup = startup_m32700ut_lcdpld_irq,
+ .shutdown = shutdown_m32700ut_lcdpld_irq,
+ .enable = enable_m32700ut_lcdpld_irq,
+ .disable = disable_m32700ut_lcdpld_irq,
+ .ack = mask_and_ack_m32700ut_lcdpld,
+ .end = end_m32700ut_lcdpld_irq
};
void __init init_IRQ(void)
diff --git a/arch/m32r/kernel/setup_mappi.c b/arch/m32r/kernel/setup_mappi.c
index 1e74110f067..aaf8e569b93 100644
--- a/arch/m32r/kernel/setup_mappi.c
+++ b/arch/m32r/kernel/setup_mappi.c
@@ -70,13 +70,13 @@ static void shutdown_mappi_irq(unsigned int irq)
static struct hw_interrupt_type mappi_irq_type =
{
- "MAPPI-IRQ",
- startup_mappi_irq,
- shutdown_mappi_irq,
- enable_mappi_irq,
- disable_mappi_irq,
- mask_and_ack_mappi,
- end_mappi_irq
+ .typename = "MAPPI-IRQ",
+ .startup = startup_mappi_irq,
+ .shutdown = shutdown_mappi_irq,
+ .enable = enable_mappi_irq,
+ .disable = disable_mappi_irq,
+ .ack = mask_and_ack_mappi,
+ .end = end_mappi_irq
};
void __init init_IRQ(void)
diff --git a/arch/m32r/kernel/setup_mappi2.c b/arch/m32r/kernel/setup_mappi2.c
index 1904d465a50..38d5e9a4142 100644
--- a/arch/m32r/kernel/setup_mappi2.c
+++ b/arch/m32r/kernel/setup_mappi2.c
@@ -1,5 +1,5 @@
/*
- * linux/arch/m32r/kernel/setup_mappi.c
+ * linux/arch/m32r/kernel/setup_mappi2.c
*
* Setup routines for Renesas MAPPI-II(M3A-ZA36) Board
*
@@ -79,13 +79,13 @@ static void shutdown_mappi2_irq(unsigned int irq)
static struct hw_interrupt_type mappi2_irq_type =
{
- "MAPPI2-IRQ",
- startup_mappi2_irq,
- shutdown_mappi2_irq,
- enable_mappi2_irq,
- disable_mappi2_irq,
- mask_and_ack_mappi2,
- end_mappi2_irq
+ .typename = "MAPPI2-IRQ",
+ .startup = startup_mappi2_irq,
+ .shutdown = shutdown_mappi2_irq,
+ .enable = enable_mappi2_irq,
+ .disable = disable_mappi2_irq,
+ .ack = mask_and_ack_mappi2,
+ .end = end_mappi2_irq
};
void __init init_IRQ(void)
@@ -156,7 +156,6 @@ void __init init_IRQ(void)
irq_desc[PLD_IRQ_CFIREQ].handler = &mappi2_irq_type;
irq_desc[PLD_IRQ_CFIREQ].action = 0;
irq_desc[PLD_IRQ_CFIREQ].depth = 1; /* disable nested irq */
-// icu_data[PLD_IRQ_CFIREQ].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD00;
icu_data[PLD_IRQ_CFIREQ].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01;
disable_mappi2_irq(PLD_IRQ_CFIREQ);
@@ -167,7 +166,6 @@ void __init init_IRQ(void)
irq_desc[PLD_IRQ_CFC_INSERT].action = 0;
irq_desc[PLD_IRQ_CFC_INSERT].depth = 1; /* disable nested irq */
icu_data[PLD_IRQ_CFC_INSERT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD00;
-// icu_data[PLD_IRQ_CFC_INSERT].icucr = 0;
disable_mappi2_irq(PLD_IRQ_CFC_INSERT);
/* ICUCR42: CFC Eject */
@@ -176,9 +174,7 @@ void __init init_IRQ(void)
irq_desc[PLD_IRQ_CFC_EJECT].action = 0;
irq_desc[PLD_IRQ_CFC_EJECT].depth = 1; /* disable nested irq */
icu_data[PLD_IRQ_CFC_EJECT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
-// icu_data[PLD_IRQ_CFC_EJECT].icucr = 0;
disable_mappi2_irq(PLD_IRQ_CFC_EJECT);
-
#endif /* CONFIG_MAPPI2_CFC */
}
diff --git a/arch/m32r/kernel/setup_mappi3.c b/arch/m32r/kernel/setup_mappi3.c
new file mode 100644
index 00000000000..3d60a85aaec
--- /dev/null
+++ b/arch/m32r/kernel/setup_mappi3.c
@@ -0,0 +1,208 @@
+/*
+ * linux/arch/m32r/kernel/setup_mappi3.c
+ *
+ * Setup routines for Renesas MAPPI-III(M3A-2170) Board
+ *
+ * Copyright (c) 2001-2005 Hiroyuki Kondo, Hirokazu Takata,
+ * Hitoshi Yamamoto, Mamoru Sakugawa
+ */
+
+#include <linux/config.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <asm/system.h>
+#include <asm/m32r.h>
+#include <asm/io.h>
+
+#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
+
+#ifndef CONFIG_SMP
+typedef struct {
+ unsigned long icucr; /* ICU Control Register */
+} icu_data_t;
+#endif /* CONFIG_SMP */
+
+icu_data_t icu_data[NR_IRQS];
+
+static void disable_mappi3_irq(unsigned int irq)
+{
+ unsigned long port, data;
+
+ if ((irq == 0) ||(irq >= NR_IRQS)) {
+ printk("bad irq 0x%08x\n", irq);
+ return;
+ }
+ port = irq2port(irq);
+ data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7;
+ outl(data, port);
+}
+
+static void enable_mappi3_irq(unsigned int irq)
+{
+ unsigned long port, data;
+
+ if ((irq == 0) ||(irq >= NR_IRQS)) {
+ printk("bad irq 0x%08x\n", irq);
+ return;
+ }
+ port = irq2port(irq);
+ data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6;
+ outl(data, port);
+}
+
+static void mask_and_ack_mappi3(unsigned int irq)
+{
+ disable_mappi3_irq(irq);
+}
+
+static void end_mappi3_irq(unsigned int irq)
+{
+ enable_mappi3_irq(irq);
+}
+
+static unsigned int startup_mappi3_irq(unsigned int irq)
+{
+ enable_mappi3_irq(irq);
+ return (0);
+}
+
+static void shutdown_mappi3_irq(unsigned int irq)
+{
+ unsigned long port;
+
+ port = irq2port(irq);
+ outl(M32R_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type mappi3_irq_type =
+{
+ .typename = "MAPPI3-IRQ",
+ .startup = startup_mappi3_irq,
+ .shutdown = shutdown_mappi3_irq,
+ .enable = enable_mappi3_irq,
+ .disable = disable_mappi3_irq,
+ .ack = mask_and_ack_mappi3,
+ .end = end_mappi3_irq
+};
+
+void __init init_IRQ(void)
+{
+#if defined(CONFIG_SMC91X)
+ /* INT0 : LAN controller (SMC91111) */
+ irq_desc[M32R_IRQ_INT0].status = IRQ_DISABLED;
+ irq_desc[M32R_IRQ_INT0].handler = &mappi3_irq_type;
+ irq_desc[M32R_IRQ_INT0].action = 0;
+ irq_desc[M32R_IRQ_INT0].depth = 1;
+ icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
+ disable_mappi3_irq(M32R_IRQ_INT0);
+#endif /* CONFIG_SMC91X */
+
+ /* MFT2 : system timer */
+ irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
+ irq_desc[M32R_IRQ_MFT2].handler = &mappi3_irq_type;
+ irq_desc[M32R_IRQ_MFT2].action = 0;
+ irq_desc[M32R_IRQ_MFT2].depth = 1;
+ icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
+ disable_mappi3_irq(M32R_IRQ_MFT2);
+
+#ifdef CONFIG_SERIAL_M32R_SIO
+ /* SIO0_R : uart receive data */
+ irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
+ irq_desc[M32R_IRQ_SIO0_R].handler = &mappi3_irq_type;
+ irq_desc[M32R_IRQ_SIO0_R].action = 0;
+ irq_desc[M32R_IRQ_SIO0_R].depth = 1;
+ icu_data[M32R_IRQ_SIO0_R].icucr = 0;
+ disable_mappi3_irq(M32R_IRQ_SIO0_R);
+
+ /* SIO0_S : uart send data */
+ irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
+ irq_desc[M32R_IRQ_SIO0_S].handler = &mappi3_irq_type;
+ irq_desc[M32R_IRQ_SIO0_S].action = 0;
+ irq_desc[M32R_IRQ_SIO0_S].depth = 1;
+ icu_data[M32R_IRQ_SIO0_S].icucr = 0;
+ disable_mappi3_irq(M32R_IRQ_SIO0_S);
+ /* SIO1_R : uart receive data */
+ irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
+ irq_desc[M32R_IRQ_SIO1_R].handler = &mappi3_irq_type;
+ irq_desc[M32R_IRQ_SIO1_R].action = 0;
+ irq_desc[M32R_IRQ_SIO1_R].depth = 1;
+ icu_data[M32R_IRQ_SIO1_R].icucr = 0;
+ disable_mappi3_irq(M32R_IRQ_SIO1_R);
+
+ /* SIO1_S : uart send data */
+ irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
+ irq_desc[M32R_IRQ_SIO1_S].handler = &mappi3_irq_type;
+ irq_desc[M32R_IRQ_SIO1_S].action = 0;
+ irq_desc[M32R_IRQ_SIO1_S].depth = 1;
+ icu_data[M32R_IRQ_SIO1_S].icucr = 0;
+ disable_mappi3_irq(M32R_IRQ_SIO1_S);
+#endif /* CONFIG_M32R_USE_DBG_CONSOLE */
+
+#if defined(CONFIG_USB)
+ /* INT1 : USB Host controller interrupt */
+ irq_desc[M32R_IRQ_INT1].status = IRQ_DISABLED;
+ irq_desc[M32R_IRQ_INT1].handler = &mappi3_irq_type;
+ irq_desc[M32R_IRQ_INT1].action = 0;
+ irq_desc[M32R_IRQ_INT1].depth = 1;
+ icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_ISMOD01;
+ disable_mappi3_irq(M32R_IRQ_INT1);
+#endif /* CONFIG_USB */
+
+ /* ICUCR40: CFC IREQ */
+ irq_desc[PLD_IRQ_CFIREQ].status = IRQ_DISABLED;
+ irq_desc[PLD_IRQ_CFIREQ].handler = &mappi3_irq_type;
+ irq_desc[PLD_IRQ_CFIREQ].action = 0;
+ irq_desc[PLD_IRQ_CFIREQ].depth = 1; /* disable nested irq */
+ icu_data[PLD_IRQ_CFIREQ].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01;
+ disable_mappi3_irq(PLD_IRQ_CFIREQ);
+
+#if defined(CONFIG_M32R_CFC)
+ /* ICUCR41: CFC Insert */
+ irq_desc[PLD_IRQ_CFC_INSERT].status = IRQ_DISABLED;
+ irq_desc[PLD_IRQ_CFC_INSERT].handler = &mappi3_irq_type;
+ irq_desc[PLD_IRQ_CFC_INSERT].action = 0;
+ irq_desc[PLD_IRQ_CFC_INSERT].depth = 1; /* disable nested irq */
+ icu_data[PLD_IRQ_CFC_INSERT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD00;
+ disable_mappi3_irq(PLD_IRQ_CFC_INSERT);
+
+ /* ICUCR42: CFC Eject */
+ irq_desc[PLD_IRQ_CFC_EJECT].status = IRQ_DISABLED;
+ irq_desc[PLD_IRQ_CFC_EJECT].handler = &mappi3_irq_type;
+ irq_desc[PLD_IRQ_CFC_EJECT].action = 0;
+ irq_desc[PLD_IRQ_CFC_EJECT].depth = 1; /* disable nested irq */
+ icu_data[PLD_IRQ_CFC_EJECT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
+ disable_mappi3_irq(PLD_IRQ_CFC_EJECT);
+#endif /* CONFIG_M32R_CFC */
+}
+
+#define LAN_IOSTART 0x300
+#define LAN_IOEND 0x320
+static struct resource smc91x_resources[] = {
+ [0] = {
+ .start = (LAN_IOSTART),
+ .end = (LAN_IOEND),
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = M32R_IRQ_INT0,
+ .end = M32R_IRQ_INT0,
+ .flags = IORESOURCE_IRQ,
+ }
+};
+
+static struct platform_device smc91x_device = {
+ .name = "smc91x",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(smc91x_resources),
+ .resource = smc91x_resources,
+};
+
+static int __init platform_init(void)
+{
+ platform_device_register(&smc91x_device);
+ return 0;
+}
+arch_initcall(platform_init);
diff --git a/arch/m32r/kernel/setup_oaks32r.c b/arch/m32r/kernel/setup_oaks32r.c
index b04834526c9..d656640badc 100644
--- a/arch/m32r/kernel/setup_oaks32r.c
+++ b/arch/m32r/kernel/setup_oaks32r.c
@@ -70,13 +70,13 @@ static void shutdown_oaks32r_irq(unsigned int irq)
static struct hw_interrupt_type oaks32r_irq_type =
{
- "OAKS32R-IRQ",
- startup_oaks32r_irq,
- shutdown_oaks32r_irq,
- enable_oaks32r_irq,
- disable_oaks32r_irq,
- mask_and_ack_mappi,
- end_oaks32r_irq
+ .typename = "OAKS32R-IRQ",
+ .startup = startup_oaks32r_irq,
+ .shutdown = shutdown_oaks32r_irq,
+ .enable = enable_oaks32r_irq,
+ .disable = disable_oaks32r_irq,
+ .ack = mask_and_ack_mappi,
+ .end = end_oaks32r_irq
};
void __init init_IRQ(void)
diff --git a/arch/m32r/kernel/setup_opsput.c b/arch/m32r/kernel/setup_opsput.c
index 84315e344c5..86f4cf2a86c 100644
--- a/arch/m32r/kernel/setup_opsput.c
+++ b/arch/m32r/kernel/setup_opsput.c
@@ -79,13 +79,13 @@ static void shutdown_opsput_irq(unsigned int irq)
static struct hw_interrupt_type opsput_irq_type =
{
- "OPSPUT-IRQ",
- startup_opsput_irq,
- shutdown_opsput_irq,
- enable_opsput_irq,
- disable_opsput_irq,
- mask_and_ack_opsput,
- end_opsput_irq
+ .typename = "OPSPUT-IRQ",
+ .startup = startup_opsput_irq,
+ .shutdown = shutdown_opsput_irq,
+ .enable = enable_opsput_irq,
+ .disable = disable_opsput_irq,
+ .ack = mask_and_ack_opsput,
+ .end = end_opsput_irq
};
/*
@@ -156,13 +156,13 @@ static void shutdown_opsput_pld_irq(unsigned int irq)
static struct hw_interrupt_type opsput_pld_irq_type =
{
- "OPSPUT-PLD-IRQ",
- startup_opsput_pld_irq,
- shutdown_opsput_pld_irq,
- enable_opsput_pld_irq,
- disable_opsput_pld_irq,
- mask_and_ack_opsput_pld,
- end_opsput_pld_irq
+ .typename = "OPSPUT-PLD-IRQ",
+ .startup = startup_opsput_pld_irq,
+ .shutdown = shutdown_opsput_pld_irq,
+ .enable = enable_opsput_pld_irq,
+ .disable = disable_opsput_pld_irq,
+ .ack = mask_and_ack_opsput_pld,
+ .end = end_opsput_pld_irq
};
/*
diff --git a/arch/m32r/kernel/setup_usrv.c b/arch/m32r/kernel/setup_usrv.c
index fe417be5e3e..634741bf9d3 100644
--- a/arch/m32r/kernel/setup_usrv.c
+++ b/arch/m32r/kernel/setup_usrv.c
@@ -70,13 +70,13 @@ static void shutdown_mappi_irq(unsigned int irq)
static struct hw_interrupt_type mappi_irq_type =
{
- "M32700-IRQ",
- startup_mappi_irq,
- shutdown_mappi_irq,
- enable_mappi_irq,
- disable_mappi_irq,
- mask_and_ack_mappi,
- end_mappi_irq
+ .typename = "M32700-IRQ",
+ .startup = startup_mappi_irq,
+ .shutdown = shutdown_mappi_irq,
+ .enable = enable_mappi_irq,
+ .disable = disable_mappi_irq,
+ .ack = mask_and_ack_mappi,
+ .end = end_mappi_irq
};
/*
@@ -143,13 +143,13 @@ static void shutdown_m32700ut_pld_irq(unsigned int irq)
static struct hw_interrupt_type m32700ut_pld_irq_type =
{
- "USRV-PLD-IRQ",
- startup_m32700ut_pld_irq,
- shutdown_m32700ut_pld_irq,
- enable_m32700ut_pld_irq,
- disable_m32700ut_pld_irq,
- mask_and_ack_m32700ut_pld,
- end_m32700ut_pld_irq
+ .typename = "USRV-PLD-IRQ",
+ .startup = startup_m32700ut_pld_irq,
+ .shutdown = shutdown_m32700ut_pld_irq,
+ .enable = enable_m32700ut_pld_irq,
+ .disable = disable_m32700ut_pld_irq,
+ .ack = mask_and_ack_m32700ut_pld,
+ .end = end_m32700ut_pld_irq
};
void __init init_IRQ(void)
diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c
index 50311eb07a2..5aef7e406ef 100644
--- a/arch/m32r/kernel/signal.c
+++ b/arch/m32r/kernel/signal.c
@@ -371,10 +371,8 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
if (!user_mode(regs))
return 1;
- if (current->flags & PF_FREEZE) {
- refrigerator(0);
+ if (try_to_freeze())
goto no_signal;
- }
if (!oldset)
oldset = &current->blocked;
diff --git a/arch/m32r/m32700ut/defconfig.m32700ut.smp b/arch/m32r/m32700ut/defconfig.m32700ut.smp
index 1c002181df7..3e607d90b5f 100644
--- a/arch/m32r/m32700ut/defconfig.m32700ut.smp
+++ b/arch/m32r/m32700ut/defconfig.m32700ut.smp
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:10:50 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun 3 16:20:58 2005
#
CONFIG_M32R=y
# CONFIG_UID16 is not set
@@ -15,6 +15,7 @@ CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -27,13 +28,16 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=15
CONFIG_HOTPLUG=y
CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
# CONFIG_IKCONFIG_PROC is not set
+# CONFIG_CPUSETS is not set
CONFIG_EMBEDDED=y
# CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -43,6 +47,7 @@ CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -65,6 +70,7 @@ CONFIG_PLAT_M32700UT=y
# CONFIG_PLAT_OPSPUT is not set
# CONFIG_PLAT_OAKS32R is not set
# CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_PLAT_MAPPI3 is not set
CONFIG_CHIP_M32700=y
# CONFIG_CHIP_M32102 is not set
# CONFIG_CHIP_VDEC2 is not set
@@ -271,7 +277,6 @@ CONFIG_NET=y
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
@@ -396,18 +401,6 @@ CONFIG_INPUT=y
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -417,6 +410,17 @@ CONFIG_SERIO_SERPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -468,6 +472,10 @@ CONFIG_DS1302=y
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+
+#
# I2C support
#
# CONFIG_I2C is not set
@@ -511,8 +519,14 @@ CONFIG_VIDEO_M32R_AR_M64278=y
# Graphics support
#
CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SOFT_CURSOR is not set
+# CONFIG_FB_MACMODES is not set
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
#
@@ -546,10 +560,6 @@ CONFIG_LOGO_LINUX_CLUT224=y
# CONFIG_USB_ARCH_HAS_OHCI is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
@@ -722,8 +732,9 @@ CONFIG_NLS_DEFAULT="iso8859-1"
#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOG_BUF_SHIFT=15
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_FRAME_POINTER is not set
diff --git a/arch/m32r/m32700ut/defconfig.m32700ut.up b/arch/m32r/m32700ut/defconfig.m32700ut.up
index 805357f7bda..2d3e7cda8f4 100644
--- a/arch/m32r/m32700ut/defconfig.m32700ut.up
+++ b/arch/m32r/m32700ut/defconfig.m32700ut.up
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:10:54 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun 3 16:21:34 2005
#
CONFIG_M32R=y
# CONFIG_UID16 is not set
@@ -16,6 +16,7 @@ CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -28,13 +29,15 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
CONFIG_HOTPLUG=y
CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
# CONFIG_IKCONFIG_PROC is not set
CONFIG_EMBEDDED=y
# CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -44,6 +47,7 @@ CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -65,6 +69,7 @@ CONFIG_PLAT_M32700UT=y
# CONFIG_PLAT_OPSPUT is not set
# CONFIG_PLAT_OAKS32R is not set
# CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_PLAT_MAPPI3 is not set
CONFIG_CHIP_M32700=y
# CONFIG_CHIP_M32102 is not set
# CONFIG_CHIP_VDEC2 is not set
@@ -268,7 +273,6 @@ CONFIG_NET=y
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
@@ -393,18 +397,6 @@ CONFIG_INPUT=y
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -414,6 +406,17 @@ CONFIG_SERIO_SERPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -465,6 +468,10 @@ CONFIG_DS1302=y
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+
+#
# I2C support
#
# CONFIG_I2C is not set
@@ -508,8 +515,14 @@ CONFIG_VIDEO_M32R_AR_M64278=y
# Graphics support
#
CONFIG_FB=y
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_SOFT_CURSOR is not set
+# CONFIG_FB_MACMODES is not set
# CONFIG_FB_MODE_HELPERS is not set
# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
#
@@ -543,10 +556,6 @@ CONFIG_LOGO_LINUX_CLUT224=y
# CONFIG_USB_ARCH_HAS_OHCI is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
@@ -719,8 +728,9 @@ CONFIG_NLS_DEFAULT="iso8859-1"
#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_FRAME_POINTER is not set
diff --git a/arch/m32r/mappi/defconfig.nommu b/arch/m32r/mappi/defconfig.nommu
index 714aa6e7034..a8425fba340 100644
--- a/arch/m32r/mappi/defconfig.nommu
+++ b/arch/m32r/mappi/defconfig.nommu
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:10:57 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun 3 16:21:46 2005
#
CONFIG_M32R=y
# CONFIG_UID16 is not set
@@ -16,6 +16,7 @@ CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -26,13 +27,15 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
CONFIG_HOTPLUG=y
CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
# CONFIG_IKCONFIG_PROC is not set
CONFIG_EMBEDDED=y
# CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +44,7 @@ CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -62,6 +66,7 @@ CONFIG_PLAT_MAPPI=y
# CONFIG_PLAT_OPSPUT is not set
# CONFIG_PLAT_OAKS32R is not set
# CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_PLAT_MAPPI3 is not set
CONFIG_CHIP_M32700=y
# CONFIG_CHIP_M32102 is not set
# CONFIG_CHIP_VDEC2 is not set
@@ -202,7 +207,6 @@ CONFIG_NET=y
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
@@ -325,18 +329,6 @@ CONFIG_INPUT=y
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -346,6 +338,17 @@ CONFIG_SERIO_SERPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
# CONFIG_VT is not set
@@ -394,6 +397,10 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+
+#
# I2C support
#
# CONFIG_I2C is not set
@@ -434,10 +441,6 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_USB_ARCH_HAS_OHCI is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
@@ -595,8 +598,9 @@ CONFIG_NLS_DEFAULT="iso8859-1"
#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_FRAME_POINTER is not set
diff --git a/arch/m32r/mappi/defconfig.smp b/arch/m32r/mappi/defconfig.smp
index 956a8e2f98d..1a7f3cd4224 100644
--- a/arch/m32r/mappi/defconfig.smp
+++ b/arch/m32r/mappi/defconfig.smp
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:11:02 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun 3 16:21:52 2005
#
CONFIG_M32R=y
# CONFIG_UID16 is not set
@@ -17,6 +17,7 @@ CONFIG_EXPERIMENTAL=y
CONFIG_BROKEN=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -28,13 +29,16 @@ CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=15
CONFIG_HOTPLUG=y
CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
CONFIG_EMBEDDED=y
# CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -44,6 +48,7 @@ CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -66,6 +71,7 @@ CONFIG_PLAT_MAPPI=y
# CONFIG_PLAT_OPSPUT is not set
# CONFIG_PLAT_OAKS32R is not set
# CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_PLAT_MAPPI3 is not set
CONFIG_CHIP_M32700=y
# CONFIG_CHIP_M32102 is not set
# CONFIG_CHIP_VDEC2 is not set
@@ -139,8 +145,8 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_REDBOOT_PARTS=y
CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
@@ -294,7 +300,6 @@ CONFIG_NET=y
# Networking options
#
# CONFIG_PACKET is not set
-# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
@@ -420,18 +425,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -441,6 +434,17 @@ CONFIG_SERIO=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
# CONFIG_VT is not set
@@ -489,6 +493,10 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+
+#
# I2C support
#
# CONFIG_I2C is not set
@@ -529,10 +537,6 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_USB_ARCH_HAS_OHCI is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
@@ -708,8 +712,9 @@ CONFIG_NLS_DEFAULT="iso8859-1"
#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOG_BUF_SHIFT=15
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_FRAME_POINTER is not set
diff --git a/arch/m32r/mappi/defconfig.up b/arch/m32r/mappi/defconfig.up
index c9253e94efb..38910fb7669 100644
--- a/arch/m32r/mappi/defconfig.up
+++ b/arch/m32r/mappi/defconfig.up
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:11:07 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun 3 16:21:59 2005
#
CONFIG_M32R=y
# CONFIG_UID16 is not set
@@ -17,6 +17,7 @@ CONFIG_EXPERIMENTAL=y
CONFIG_BROKEN=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -28,13 +29,15 @@ CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
CONFIG_HOTPLUG=y
CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_EMBEDDED=y
# CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -44,6 +47,7 @@ CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -65,6 +69,7 @@ CONFIG_PLAT_MAPPI=y
# CONFIG_PLAT_OPSPUT is not set
# CONFIG_PLAT_OAKS32R is not set
# CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_PLAT_MAPPI3 is not set
CONFIG_CHIP_M32700=y
# CONFIG_CHIP_M32102 is not set
# CONFIG_CHIP_VDEC2 is not set
@@ -135,8 +140,8 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
#
CONFIG_MTD=y
# CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_REDBOOT_PARTS=y
CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
@@ -290,7 +295,6 @@ CONFIG_NET=y
# Networking options
#
# CONFIG_PACKET is not set
-# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
@@ -416,18 +420,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -437,6 +429,17 @@ CONFIG_SERIO=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
# CONFIG_VT is not set
@@ -485,6 +488,10 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+
+#
# I2C support
#
# CONFIG_I2C is not set
@@ -525,10 +532,6 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_USB_ARCH_HAS_OHCI is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
@@ -704,8 +707,9 @@ CONFIG_NLS_DEFAULT="iso8859-1"
#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_FRAME_POINTER is not set
diff --git a/arch/m32r/mappi2/defconfig.vdec2 b/arch/m32r/mappi2/defconfig.vdec2
index c14791d2730..56f287b6589 100644
--- a/arch/m32r/mappi2/defconfig.vdec2
+++ b/arch/m32r/mappi2/defconfig.vdec2
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:11:10 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun 3 16:22:02 2005
#
CONFIG_M32R=y
# CONFIG_UID16 is not set
@@ -16,6 +16,7 @@ CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -28,13 +29,15 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
CONFIG_HOTPLUG=y
CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
# CONFIG_IKCONFIG_PROC is not set
CONFIG_EMBEDDED=y
# CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -44,6 +47,7 @@ CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -65,6 +69,7 @@ CONFIG_KMOD=y
# CONFIG_PLAT_OPSPUT is not set
# CONFIG_PLAT_OAKS32R is not set
CONFIG_PLAT_MAPPI2=y
+# CONFIG_PLAT_MAPPI3 is not set
# CONFIG_CHIP_M32700 is not set
# CONFIG_CHIP_M32102 is not set
CONFIG_CHIP_VDEC2=y
@@ -264,7 +269,6 @@ CONFIG_NET=y
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
@@ -389,18 +393,6 @@ CONFIG_INPUT=y
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -410,6 +402,17 @@ CONFIG_SERIO_SERPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
CONFIG_VT=y
@@ -460,6 +463,10 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+
+#
# I2C support
#
# CONFIG_I2C is not set
@@ -521,10 +528,6 @@ CONFIG_DUMMY_CONSOLE=y
# CONFIG_USB_ARCH_HAS_OHCI is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
@@ -697,8 +700,9 @@ CONFIG_NLS_DEFAULT="iso8859-1"
#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_FRAME_POINTER is not set
diff --git a/arch/m32r/mappi3/defconfig.smp b/arch/m32r/mappi3/defconfig.smp
new file mode 100644
index 00000000000..2eebe75fc07
--- /dev/null
+++ b/arch/m32r/mappi3/defconfig.smp
@@ -0,0 +1,751 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc5
+# Tue May 31 17:55:34 2005
+#
+CONFIG_M32R=y
+# CONFIG_UID16 is not set
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_CLEAN_COMPILE is not set
+CONFIG_BROKEN=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
+
+#
+# Processor type and features
+#
+# CONFIG_PLAT_MAPPI is not set
+# CONFIG_PLAT_USRV is not set
+# CONFIG_PLAT_M32700UT is not set
+# CONFIG_PLAT_OPSPUT is not set
+# CONFIG_PLAT_OAKS32R is not set
+# CONFIG_PLAT_MAPPI2 is not set
+CONFIG_PLAT_MAPPI3=y
+CONFIG_CHIP_M32700=y
+# CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_VDEC2 is not set
+# CONFIG_CHIP_OPSP is not set
+CONFIG_MMU=y
+CONFIG_TLB_ENTRIES=32
+CONFIG_ISA_M32R2=y
+CONFIG_ISA_DSP_LEVEL2=y
+CONFIG_ISA_DUAL_ISSUE=y
+CONFIG_BUS_CLOCK=10000000
+CONFIG_TIMER_DIVIDE=128
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x08000000
+CONFIG_NOHIGHMEM=y
+CONFIG_DISCONTIGMEM=y
+CONFIG_IRAM_START=0x00f00000
+CONFIG_IRAM_SIZE=0x00080000
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_PREEMPT=y
+# CONFIG_HAVE_DEC_LOCK is not set
+CONFIG_SMP=y
+# CONFIG_CHIP_M32700_TS1 is not set
+CONFIG_NR_CPUS=2
+# CONFIG_NUMA is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+
+#
+# PC-card bridges
+#
+# CONFIG_TCIC is not set
+# CONFIG_M32R_PCC is not set
+# CONFIG_M32R_CFC is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_BLK_DEV_IDECS=y
+CONFIG_BLK_DEV_IDECD=m
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SMC91X=y
+# CONFIG_NE2000 is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_M32R_SIO=y
+CONFIG_SERIAL_M32R_SIO_CONSOLE=y
+# CONFIG_SERIAL_M32R_PLDSIO is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS_FS=y
+CONFIG_JFFS_FS_VERBOSE=0
+CONFIG_JFFS_PROC_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=15
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_FRAME_POINTER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/m32r/mappi3/dot.gdbinit b/arch/m32r/mappi3/dot.gdbinit
new file mode 100644
index 00000000000..89c22184e13
--- /dev/null
+++ b/arch/m32r/mappi3/dot.gdbinit
@@ -0,0 +1,224 @@
+# .gdbinit file
+# $Id: dot.gdbinit,v 1.1 2005/04/11 02:21:08 sakugawa Exp $
+
+# setting
+set width 0d70
+set radix 0d16
+use_debug_dma
+
+# Initialize SDRAM controller for Mappi
+define sdram_init
+ # SDIR0
+ set *(unsigned long *)0x00ef6008 = 0x00000182
+ # SDIR1
+ set *(unsigned long *)0x00ef600c = 0x00000001
+ # Initialize wait
+ shell sleep 0.1
+ # MOD
+ set *(unsigned long *)0x00ef602c = 0x00000020
+ set *(unsigned long *)0x00ef604c = 0x00000020
+ # TR
+ set *(unsigned long *)0x00ef6028 = 0x00051502
+ set *(unsigned long *)0x00ef6048 = 0x00051502
+ # ADR
+ set *(unsigned long *)0x00ef6020 = 0x08000004
+ set *(unsigned long *)0x00ef6040 = 0x0c000004
+ # AutoRef On
+ set *(unsigned long *)0x00ef6004 = 0x00010517
+ # Access enable
+ set *(unsigned long *)0x00ef6024 = 0x00000001
+ set *(unsigned long *)0x00ef6044 = 0x00000001
+end
+
+# Initialize LAN controller for Mappi
+define lanc_init
+ # Set BSEL4
+ #set *(unsigned long *)0x00ef5004 = 0x0fff330f
+ #set *(unsigned long *)0x00ef5004 = 0x01113301
+
+# set *(unsigned long *)0x00ef5004 = 0x02011101
+# set *(unsigned long *)0x00ef5004 = 0x04441104
+end
+
+define clock_init
+ set *(unsigned long *)0x00ef4010 = 2
+ set *(unsigned long *)0x00ef4014 = 2
+ set *(unsigned long *)0x00ef4020 = 3
+ set *(unsigned long *)0x00ef4024 = 3
+ set *(unsigned long *)0x00ef4004 = 0x7
+# shell sleep 0.1
+# set *(unsigned long *)0x00ef4004 = 0x5
+ shell sleep 0.1
+ set *(unsigned long *)0x00ef4008 = 0x0200
+end
+
+define port_init
+ set $sfrbase = 0x00ef0000
+ set *(unsigned short *)0x00ef1060 = 0x5555
+ set *(unsigned short *)0x00ef1062 = 0x5555
+ set *(unsigned short *)0x00ef1064 = 0x5555
+ set *(unsigned short *)0x00ef1066 = 0x5555
+ set *(unsigned short *)0x00ef1068 = 0x5555
+ set *(unsigned short *)0x00ef106a = 0x0000
+ set *(unsigned short *)0x00ef106e = 0x5555
+ set *(unsigned short *)0x00ef1070 = 0x5555
+end
+
+# MMU enable
+define mmu_enable
+ set $evb=0x88000000
+ set *(unsigned long *)0xffff0024=1
+end
+
+# MMU disable
+define mmu_disable
+ set $evb=0
+ set *(unsigned long *)0xffff0024=0
+end
+
+# Show TLB entries
+define show_tlb_entries
+ set $i = 0
+ set $addr = $arg0
+ while ($i < 0d16 )
+ set $tlb_tag = *(unsigned long*)$addr
+ set $tlb_data = *(unsigned long*)($addr + 4)
+ printf " [%2d] 0x%08lx : 0x%08lx - 0x%08lx\n", $i, $addr, $tlb_tag, $tlb_data
+ set $i = $i + 1
+ set $addr = $addr + 8
+ end
+end
+define itlb
+ set $itlb=0xfe000000
+ show_tlb_entries $itlb
+end
+define dtlb
+ set $dtlb=0xfe000800
+ show_tlb_entries $dtlb
+end
+
+# Cache ON
+define set_cache_type
+ set $mctype = (void*)0xfffffff8
+# chaos
+# set *(unsigned long *)($mctype) = 0x0000c000
+# m32102 i-cache only
+ set *(unsigned long *)($mctype) = 0x00008000
+# m32102 d-cache only
+# set *(unsigned long *)($mctype) = 0x00004000
+end
+define cache_on
+ set $param = (void*)0x08001000
+ set *(unsigned long *)($param) = 0x60ff6102
+end
+
+
+# Show current task structure
+define show_current
+ set $current = $spi & 0xffffe000
+ printf "$current=0x%08lX\n",$current
+ print *(struct task_struct *)$current
+end
+
+# Show user assigned task structure
+define show_task
+ set $task = $arg0 & 0xffffe000
+ printf "$task=0x%08lX\n",$task
+ print *(struct task_struct *)$task
+end
+document show_task
+ Show user assigned task structure
+ arg0 : task structure address
+end
+
+# Show M32R registers
+define show_regs
+ printf " R0[0x%08lX] R1[0x%08lX] R2[0x%08lX] R3[0x%08lX]\n",$r0,$r1,$r2,$r3
+ printf " R4[0x%08lX] R5[0x%08lX] R6[0x%08lX] R7[0x%08lX]\n",$r4,$r5,$r6,$r7
+ printf " R8[0x%08lX] R9[0x%08lX] R10[0x%08lX] R11[0x%08lX]\n",$r8,$r9,$r10,$r11
+ printf "R12[0x%08lX] FP[0x%08lX] LR[0x%08lX] SP[0x%08lX]\n",$r12,$fp,$lr,$sp
+ printf "PSW[0x%08lX] CBR[0x%08lX] SPI[0x%08lX] SPU[0x%08lX]\n",$psw,$cbr,$spi,$spu
+ printf "BPC[0x%08lX] PC[0x%08lX] ACCL[0x%08lX] ACCH[0x%08lX]\n",$bpc,$pc,$accl,$acch
+ printf "EVB[0x%08lX]\n",$evb
+
+ set $mests = *(unsigned long *)0xffff000c
+ set $mdeva = *(unsigned long *)0xffff0010
+ printf "MESTS[0x%08lX] MDEVA[0x%08lX]\n",$mests,$mdeva
+end
+
+
+# Setup all
+define setup
+ clock_init
+ shell sleep 0.1
+ port_init
+ sdram_init
+# lanc_init
+# dispc_init
+# set $evb=0x08000000
+end
+
+# Load modules
+define load_modules
+ use_debug_dma
+ load
+# load busybox.mot
+end
+
+# Set kernel parameters
+define set_kernel_parameters
+ set $param = (void*)0x08001000
+
+ ## MOUNT_ROOT_RDONLY
+ set {long}($param+0x00)=0
+ ## RAMDISK_FLAGS
+ #set {long}($param+0x04)=0
+ ## ORIG_ROOT_DEV
+ #set {long}($param+0x08)=0x00000100
+ ## LOADER_TYPE
+ #set {long}($param+0x0C)=0
+ ## INITRD_START
+ set {long}($param+0x10)=0x082a0000
+ ## INITRD_SIZE
+ set {long}($param+0x14)=0d6200000
+
+ # M32R_CPUCLK
+ set *(unsigned long *)($param + 0x0018) = 0d100000000
+ # M32R_BUSCLK
+ set *(unsigned long *)($param + 0x001c) = 0d50000000
+ # M32R_TIMER_DIVIDE
+ set *(unsigned long *)($param + 0x0020) = 0d128
+
+
+ set {char[0x200]}($param + 0x100) = "console=ttyS0,115200n8x root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/root.2.6_04 nfsaddrs=192.168.0.102:192.168.0.1:192.168.0.1:255.255.255.0:mappi: \0"
+
+
+end
+
+# Boot
+define boot
+ set_kernel_parameters
+ debug_chaos
+ set *(unsigned long *)0x00f00000=0x08002000
+ set $pc=0x08002000
+ set $fp=0
+ del b
+ si
+end
+
+# Restart
+define restart
+ sdireset
+ sdireset
+ setup
+ load_modules
+ boot
+end
+
+sdireset
+sdireset
+file vmlinux
+target m32rsdi
+
+restart
+boot
diff --git a/arch/m32r/mm/extable.c b/arch/m32r/mm/extable.c
index 9a97363b652..1743f23d49a 100644
--- a/arch/m32r/mm/extable.c
+++ b/arch/m32r/mm/extable.c
@@ -1,10 +1,8 @@
/*
- * linux/arch/i386/mm/extable.c
+ * linux/arch/m32r/mm/extable.c
*/
-#include <linux/config.h>
#include <linux/module.h>
-#include <linux/spinlock.h>
#include <asm/uaccess.h>
int fixup_exception(struct pt_regs *regs)
@@ -19,4 +17,3 @@ int fixup_exception(struct pt_regs *regs)
return 0;
}
-
diff --git a/arch/m32r/mm/init.c b/arch/m32r/mm/init.c
index bc423d838fb..d9a40b1fe8b 100644
--- a/arch/m32r/mm/init.c
+++ b/arch/m32r/mm/init.c
@@ -49,7 +49,7 @@ void show_mem(void)
printk("Free swap: %6ldkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
for_each_pgdat(pgdat) {
for (i = 0; i < pgdat->node_spanned_pages; ++i) {
- page = pgdat->node_mem_map + i;
+ page = pgdat_page_nr(pgdat, i);
total++;
if (PageHighMem(page))
highmem++;
@@ -152,7 +152,7 @@ int __init reservedpages_count(void)
reservedpages = 0;
for_each_online_node(nid)
for (i = 0 ; i < MAX_LOW_PFN(nid) - START_PFN(nid) ; i++)
- if (PageReserved(NODE_DATA(nid)->node_mem_map + i))
+ if (PageReserved(nid_page_nr(nid, i)))
reservedpages++;
return reservedpages;
diff --git a/arch/m32r/oaks32r/defconfig.nommu b/arch/m32r/oaks32r/defconfig.nommu
index f2da9be726e..3f9fe519acb 100644
--- a/arch/m32r/oaks32r/defconfig.nommu
+++ b/arch/m32r/oaks32r/defconfig.nommu
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:11:13 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun 3 16:22:04 2005
#
CONFIG_M32R=y
# CONFIG_UID16 is not set
@@ -16,6 +16,7 @@ CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -26,12 +27,14 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
CONFIG_HOTPLUG=y
CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
CONFIG_EMBEDDED=y
# CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -40,6 +43,7 @@ CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -61,6 +65,7 @@ CONFIG_KMOD=y
# CONFIG_PLAT_OPSPUT is not set
CONFIG_PLAT_OAKS32R=y
# CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_PLAT_MAPPI3 is not set
# CONFIG_CHIP_M32700 is not set
CONFIG_CHIP_M32102=y
# CONFIG_CHIP_VDEC2 is not set
@@ -92,10 +97,6 @@ CONFIG_PREEMPT=y
# CONFIG_PCCARD is not set
#
-# PC-card bridges
-#
-
-#
# PCI Hotplug Support
#
@@ -193,7 +194,6 @@ CONFIG_NET=y
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
@@ -311,18 +311,6 @@ CONFIG_INPUT=y
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -332,6 +320,17 @@ CONFIG_SERIO_SERPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
# CONFIG_VT is not set
@@ -375,6 +374,10 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+
+#
# I2C support
#
# CONFIG_I2C is not set
@@ -415,10 +418,6 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_USB_ARCH_HAS_OHCI is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
@@ -574,8 +573,9 @@ CONFIG_NLS_DEFAULT="iso8859-1"
#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOG_BUF_SHIFT=14
# CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_FRAME_POINTER is not set
diff --git a/arch/m32r/opsput/defconfig.opsput b/arch/m32r/opsput/defconfig.opsput
index a87e1ea4c30..66adec6a701 100644
--- a/arch/m32r/opsput/defconfig.opsput
+++ b/arch/m32r/opsput/defconfig.opsput
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:11:41 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun 3 16:22:06 2005
#
CONFIG_M32R=y
# CONFIG_UID16 is not set
@@ -15,6 +15,7 @@ CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -27,13 +28,15 @@ CONFIG_BSD_PROCESS_ACCT=y
# CONFIG_BSD_PROCESS_ACCT_V3 is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
CONFIG_HOTPLUG=y
CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
# CONFIG_IKCONFIG_PROC is not set
CONFIG_EMBEDDED=y
# CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -43,6 +46,7 @@ CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -64,6 +68,7 @@ CONFIG_KMOD=y
CONFIG_PLAT_OPSPUT=y
# CONFIG_PLAT_OAKS32R is not set
# CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_PLAT_MAPPI3 is not set
# CONFIG_CHIP_M32700 is not set
# CONFIG_CHIP_M32102 is not set
# CONFIG_CHIP_VDEC2 is not set
@@ -243,7 +248,6 @@ CONFIG_NET=y
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
@@ -368,18 +372,6 @@ CONFIG_INPUT=y
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -389,6 +381,17 @@ CONFIG_SERIO_SERPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
# CONFIG_VT is not set
@@ -438,6 +441,10 @@ CONFIG_DS1302=y
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+
+#
# I2C support
#
# CONFIG_I2C is not set
@@ -478,10 +485,6 @@ CONFIG_DS1302=y
# CONFIG_USB_ARCH_HAS_OHCI is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
# USB Gadget Support
#
# CONFIG_USB_GADGET is not set
@@ -654,8 +657,10 @@ CONFIG_NLS_DEFAULT="iso8859-1"
#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_LOG_BUF_SHIFT=14
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index d0713c7d9f0..691a2469ff3 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -357,6 +357,8 @@ config 060_WRITETHROUGH
is hardwired on. The 53c710 SCSI driver is known to suffer from
this problem.
+source "mm/Kconfig"
+
endmenu
menu "General setup"
diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig
index 7dbf997ff20..5649fbae430 100644
--- a/arch/m68k/configs/amiga_defconfig
+++ b/arch/m68k/configs/amiga_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc2-m68k
-# Tue Apr 5 14:05:59 2005
+# Linux kernel version: 2.6.12-rc6-m68k
+# Tue Jun 7 20:34:23 2005
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -35,6 +35,8 @@ CONFIG_KOBJECT_UEVENT=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
@@ -135,7 +137,6 @@ CONFIG_PARPORT_1284=y
#
CONFIG_AMIGA_FLOPPY=y
CONFIG_AMIGA_Z2RAM=y
-# CONFIG_BLK_DEV_XD is not set
# CONFIG_PARIDE is not set
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
@@ -223,17 +224,12 @@ CONFIG_SCSI_CONSTANTS=y
#
# SCSI low-level drivers
#
-# CONFIG_SCSI_7000FASST is not set
# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_IN2000 is not set
# CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_GENERIC_NCR5380 is not set
# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
# CONFIG_SCSI_PPA is not set
@@ -244,7 +240,6 @@ CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_QLOGIC_FAS is not set
# CONFIG_SCSI_SYM53C416 is not set
# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
# CONFIG_SCSI_DEBUG is not set
CONFIG_A3000_SCSI=y
CONFIG_A2091_SCSI=y
@@ -492,7 +487,6 @@ CONFIG_HYDRA=m
CONFIG_ZORRO8390=m
CONFIG_APNE=m
# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
# CONFIG_NET_VENDOR_SMC is not set
# CONFIG_NET_VENDOR_RACAL is not set
# CONFIG_AT1700 is not set
@@ -620,7 +614,6 @@ CONFIG_SERIO_SERPORT=m
# CONFIG_SERIO_PARKBD is not set
# CONFIG_SERIO_RAW is not set
# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
#
# Character devices
diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig
index 505a2968e60..63024b0b7ac 100644
--- a/arch/m68k/configs/apollo_defconfig
+++ b/arch/m68k/configs/apollo_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc2-m68k
-# Tue Apr 5 14:06:00 2005
+# Linux kernel version: 2.6.12-rc6-m68k
+# Tue Jun 7 20:34:27 2005
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -35,6 +35,8 @@ CONFIG_KOBJECT_UEVENT=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
@@ -497,7 +499,6 @@ CONFIG_SERIO_SERPORT=m
CONFIG_SERIO_LIBPS2=m
# CONFIG_SERIO_RAW is not set
# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
#
# Character devices
diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig
index 617aa73c325..6433da2d2ce 100644
--- a/arch/m68k/configs/atari_defconfig
+++ b/arch/m68k/configs/atari_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc2-m68k
-# Tue Apr 5 14:06:18 2005
+# Linux kernel version: 2.6.12-rc6-m68k
+# Tue Jun 7 20:34:32 2005
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -35,6 +35,8 @@ CONFIG_KOBJECT_UEVENT=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
@@ -531,7 +533,6 @@ CONFIG_SERIO_SERPORT=y
CONFIG_SERIO_LIBPS2=y
# CONFIG_SERIO_RAW is not set
# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
#
# Character devices
diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig
index b501db51d9e..da2a23a2146 100644
--- a/arch/m68k/configs/bvme6000_defconfig
+++ b/arch/m68k/configs/bvme6000_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc2-m68k
-# Tue Apr 5 14:06:19 2005
+# Linux kernel version: 2.6.12-rc6-m68k
+# Tue Jun 7 20:34:37 2005
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -35,6 +35,8 @@ CONFIG_KOBJECT_UEVENT=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
@@ -496,7 +498,6 @@ CONFIG_SERIO_SERPORT=m
CONFIG_SERIO_LIBPS2=m
# CONFIG_SERIO_RAW is not set
# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
#
# Character devices
diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig
index 2bf6cef4f2b..51251883adf 100644
--- a/arch/m68k/configs/hp300_defconfig
+++ b/arch/m68k/configs/hp300_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc2-m68k
-# Tue Apr 5 14:06:21 2005
+# Linux kernel version: 2.6.12-rc6-m68k
+# Tue Jun 7 20:34:41 2005
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -35,6 +35,8 @@ CONFIG_KOBJECT_UEVENT=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
@@ -498,7 +500,6 @@ CONFIG_SERIO_SERPORT=m
CONFIG_SERIO_LIBPS2=m
# CONFIG_SERIO_RAW is not set
# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
#
# Character devices
diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig
index 7074f856820..15b80abfe94 100644
--- a/arch/m68k/configs/mac_defconfig
+++ b/arch/m68k/configs/mac_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc2-m68k
-# Tue Apr 5 14:06:24 2005
+# Linux kernel version: 2.6.12-rc6-m68k
+# Tue Jun 7 20:34:45 2005
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -35,6 +35,8 @@ CONFIG_KOBJECT_UEVENT=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
@@ -540,7 +542,6 @@ CONFIG_SERIO_SERPORT=m
CONFIG_SERIO_LIBPS2=m
# CONFIG_SERIO_RAW is not set
# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
#
# Character devices
diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig
index 61f09bc4846..f0d5534f683 100644
--- a/arch/m68k/configs/mvme147_defconfig
+++ b/arch/m68k/configs/mvme147_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc2-m68k
-# Tue Apr 5 14:06:28 2005
+# Linux kernel version: 2.6.12-rc6-m68k
+# Tue Jun 7 20:34:50 2005
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -35,6 +35,8 @@ CONFIG_KOBJECT_UEVENT=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
@@ -498,7 +500,6 @@ CONFIG_SERIO_SERPORT=m
CONFIG_SERIO_LIBPS2=m
# CONFIG_SERIO_RAW is not set
# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
#
# Character devices
diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig
index 69c01004ec4..1d5c46ff3c8 100644
--- a/arch/m68k/configs/mvme16x_defconfig
+++ b/arch/m68k/configs/mvme16x_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc2-m68k
-# Tue Apr 5 14:06:31 2005
+# Linux kernel version: 2.6.12-rc6-m68k
+# Tue Jun 7 20:34:53 2005
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -35,6 +35,8 @@ CONFIG_KOBJECT_UEVENT=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
@@ -497,7 +499,6 @@ CONFIG_SERIO_SERPORT=m
CONFIG_SERIO_LIBPS2=m
# CONFIG_SERIO_RAW is not set
# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
#
# Character devices
diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig
index 550ec26006c..856238634d4 100644
--- a/arch/m68k/configs/q40_defconfig
+++ b/arch/m68k/configs/q40_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc2-m68k
-# Tue Apr 5 14:06:34 2005
+# Linux kernel version: 2.6.12-rc6-m68k
+# Tue Jun 7 20:34:58 2005
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -35,6 +35,8 @@ CONFIG_KOBJECT_UEVENT=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
@@ -125,7 +127,6 @@ CONFIG_FW_LOADER=m
# Block devices
#
# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
# CONFIG_BLK_DEV_COW_COMMON is not set
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_CRYPTOLOOP=m
@@ -210,17 +211,12 @@ CONFIG_SCSI_CONSTANTS=y
#
# SCSI low-level drivers
#
-# CONFIG_SCSI_7000FASST is not set
# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_IN2000 is not set
# CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_GENERIC_NCR5380 is not set
# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
# CONFIG_SCSI_NCR53C406A is not set
@@ -229,7 +225,6 @@ CONFIG_SCSI_CONSTANTS=y
# CONFIG_SCSI_QLOGIC_FAS is not set
# CONFIG_SCSI_SYM53C416 is not set
# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
# CONFIG_SCSI_DEBUG is not set
#
@@ -466,7 +461,6 @@ CONFIG_EQUALIZER=m
CONFIG_NET_ETHERNET=y
CONFIG_MII=m
# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
# CONFIG_NET_VENDOR_SMC is not set
# CONFIG_NET_VENDOR_RACAL is not set
# CONFIG_AT1700 is not set
@@ -570,7 +564,6 @@ CONFIG_SERIO_Q40KBD=m
CONFIG_SERIO_LIBPS2=m
# CONFIG_SERIO_RAW is not set
# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
#
# Character devices
diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig
index 5b5a619645a..af903b5c570 100644
--- a/arch/m68k/configs/sun3_defconfig
+++ b/arch/m68k/configs/sun3_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc2-m68k
-# Tue Apr 5 14:06:37 2005
+# Linux kernel version: 2.6.12-rc6-m68k
+# Tue Jun 7 20:35:02 2005
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -35,6 +35,8 @@ CONFIG_KOBJECT_UEVENT=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
@@ -171,7 +173,6 @@ CONFIG_SCSI_CONSTANTS=y
#
# CONFIG_SCSI_SATA is not set
# CONFIG_SCSI_DEBUG is not set
-CONFIG_SUN3_SCSI=y
#
# Multi-device support (RAID and LVM)
@@ -487,7 +488,6 @@ CONFIG_SERIO_SERPORT=m
CONFIG_SERIO_LIBPS2=m
# CONFIG_SERIO_RAW is not set
# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
#
# Character devices
diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig
index 704e42344cb..997143b7928 100644
--- a/arch/m68k/configs/sun3x_defconfig
+++ b/arch/m68k/configs/sun3x_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc2-m68k
-# Tue Apr 5 14:06:40 2005
+# Linux kernel version: 2.6.12-rc6-m68k
+# Tue Jun 7 20:35:06 2005
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -35,6 +35,8 @@ CONFIG_KOBJECT_UEVENT=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
@@ -497,7 +499,6 @@ CONFIG_SERIO_SERPORT=m
CONFIG_SERIO_LIBPS2=m
# CONFIG_SERIO_RAW is not set
# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
#
# Character devices
diff --git a/arch/m68k/defconfig b/arch/m68k/defconfig
index 5b2296ecba8..7d935e48a9a 100644
--- a/arch/m68k/defconfig
+++ b/arch/m68k/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc2-m68k
-# Tue Apr 5 14:05:31 2005
+# Linux kernel version: 2.6.12-rc6-m68k
+# Tue Jun 7 20:34:17 2005
#
CONFIG_M68K=y
CONFIG_MMU=y
@@ -33,6 +33,8 @@ CONFIG_KOBJECT_UEVENT=y
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
@@ -355,7 +357,6 @@ CONFIG_SERIO_SERPORT=y
CONFIG_SERIO_LIBPS2=y
# CONFIG_SERIO_RAW is not set
# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
#
# Character devices
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
index e729bd28062..dbfcdc8e608 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -532,6 +532,8 @@ config ROMKERNEL
endchoice
+source "mm/Kconfig"
+
endmenu
config ISA_DMA_API
diff --git a/arch/m68knommu/kernel/process.c b/arch/m68knommu/kernel/process.c
index 2b6c9d32b7a..c4a33f265dc 100644
--- a/arch/m68knommu/kernel/process.c
+++ b/arch/m68knommu/kernel/process.c
@@ -45,11 +45,13 @@ asmlinkage void ret_from_fork(void);
*/
void default_idle(void)
{
- while(1) {
- if (need_resched())
- __asm__("stop #0x2000" : : : "cc");
- schedule();
+ local_irq_disable();
+ while (!need_resched()) {
+ /* This stop will re-enable interrupts */
+ __asm__("stop #0x2000" : : : "cc");
+ local_irq_disable();
}
+ local_irq_enable();
}
void (*idle)(void) = default_idle;
@@ -63,7 +65,12 @@ void (*idle)(void) = default_idle;
void cpu_idle(void)
{
/* endless idle loop with no priority at all */
- idle();
+ while (1) {
+ idle();
+ preempt_enable_no_resched();
+ schedule();
+ preempt_disable();
+ }
}
void machine_restart(char * __unused)
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index ab9944693f1..bd9de7b00c0 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -492,7 +492,7 @@ config SGI_SN0_N_MODE
which allows for more memory. Your system is most probably
running in M-Mode, so you should say N here.
-config DISCONTIGMEM
+config ARCH_DISCONTIGMEM_ENABLE
bool
default y if SGI_IP27
help
@@ -1416,6 +1416,12 @@ config HIGHMEM
bool "High Memory Support"
depends on MIPS32 && (CPU_R3000 || CPU_SB1 || CPU_R7000 || CPU_RM9000 || CPU_R10000) && !(MACH_DECSTATION || MOMENCO_JAGUAR_ATX)
+config ARCH_FLATMEM_ENABLE
+ def_bool y
+ depends on !NUMA
+
+source "mm/Kconfig"
+
config SMP
bool "Multi-Processing support"
depends on CPU_RM9000 || (SIBYTE_SB1250 && !SIBYTE_STANDALONE) || SGI_IP27
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig
index 13472292d0e..b5bab3a42fc 100644
--- a/arch/mips/configs/ip27_defconfig
+++ b/arch/mips/configs/ip27_defconfig
@@ -82,7 +82,7 @@ CONFIG_STOP_MACHINE=y
# CONFIG_SGI_IP22 is not set
CONFIG_SGI_IP27=y
# CONFIG_SGI_SN0_N_MODE is not set
-CONFIG_DISCONTIGMEM=y
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
CONFIG_NUMA=y
# CONFIG_MAPPED_KERNEL is not set
# CONFIG_REPLICATE_KTEXT is not set
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 6018ca25ace..3a240e3e004 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -33,6 +33,7 @@
#include <linux/root_dev.h>
#include <linux/highmem.h>
#include <linux/console.h>
+#include <linux/mmzone.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
@@ -356,6 +357,8 @@ static inline void bootmem_init(void)
}
#endif
+ memory_present(0, first_usable_pfn, max_low_pfn);
+
/* Initialize the boot-time allocator with low memory only. */
bootmap_size = init_bootmem(first_usable_pfn, max_low_pfn);
@@ -557,6 +560,7 @@ void __init setup_arch(char **cmdline_p)
parse_cmdline_early();
bootmem_init();
+ sparse_init();
paging_init();
resource_init();
}
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index b027ce7efbc..9c9a271c8a3 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -128,7 +128,7 @@ static void __init fixrange_init(unsigned long start, unsigned long end,
#endif /* CONFIG_MIPS64 */
#endif /* CONFIG_HIGHMEM */
-#ifndef CONFIG_DISCONTIGMEM
+#ifndef CONFIG_NEED_MULTIPLE_NODES
extern void pagetable_init(void);
void __init paging_init(void)
@@ -232,7 +232,6 @@ void __init mem_init(void)
#ifdef CONFIG_LIMITED_DMA
set_page_address(page, lowmem_page_address(page));
#endif
- set_bit(PG_highmem, &page->flags);
set_page_count(page, 1);
__free_page(page);
totalhigh_pages++;
@@ -254,7 +253,7 @@ void __init mem_init(void)
initsize >> 10,
(unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));
}
-#endif /* !CONFIG_DISCONTIGMEM */
+#endif /* !CONFIG_NEED_MULTIPLE_NODES */
#ifdef CONFIG_BLK_DEV_INITRD
void free_initrd_mem(unsigned long start, unsigned long end)
diff --git a/arch/mips/mm/pgtable.c b/arch/mips/mm/pgtable.c
index 3b88fdeef32..3fe94202da8 100644
--- a/arch/mips/mm/pgtable.c
+++ b/arch/mips/mm/pgtable.c
@@ -5,7 +5,7 @@
void show_mem(void)
{
-#ifndef CONFIG_DISCONTIGMEM /* XXX(hch): later.. */
+#ifndef CONFIG_NEED_MULTIPLE_NODES /* XXX(hch): later.. */
int pfn, total = 0, reserved = 0;
int shared = 0, cached = 0;
int highmem = 0;
diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c
index 0a44a98d7ad..a160d04f7db 100644
--- a/arch/mips/sgi-ip27/ip27-memory.c
+++ b/arch/mips/sgi-ip27/ip27-memory.c
@@ -549,9 +549,8 @@ void __init mem_init(void)
*/
numslots = node_getlastslot(node);
for (slot = 1; slot <= numslots; slot++) {
- p = NODE_DATA(node)->node_mem_map +
- (slot_getbasepfn(node, slot) -
- slot_getbasepfn(node, 0));
+ p = nid_page_nr(node, slot_getbasepfn(node, slot) -
+ slot_getbasepfn(node, 0));
/*
* Free valid memory in current slot.
diff --git a/arch/mips/vr41xx/common/pmu.c b/arch/mips/vr41xx/common/pmu.c
index c5f1043de93..53166f3598b 100644
--- a/arch/mips/vr41xx/common/pmu.c
+++ b/arch/mips/vr41xx/common/pmu.c
@@ -1,7 +1,7 @@
/*
* pmu.c, Power Management Unit routines for NEC VR4100 series.
*
- * Copyright (C) 2003-2004 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
*
* 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
@@ -17,7 +17,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/errno.h>
#include <linux/init.h>
+#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/smp.h>
#include <linux/types.h>
@@ -27,20 +29,31 @@
#include <asm/reboot.h>
#include <asm/system.h>
-#define PMUCNT2REG KSEG1ADDR(0x0f0000c6)
+#define PMU_TYPE1_BASE 0x0b0000a0UL
+#define PMU_TYPE1_SIZE 0x0eUL
+
+#define PMU_TYPE2_BASE 0x0f0000c0UL
+#define PMU_TYPE2_SIZE 0x10UL
+
+#define PMUCNT2REG 0x06
#define SOFTRST 0x0010
+static void __iomem *pmu_base;
+
+#define pmu_read(offset) readw(pmu_base + (offset))
+#define pmu_write(offset, value) writew((value), pmu_base + (offset))
+
static inline void software_reset(void)
{
- uint16_t val;
+ uint16_t pmucnt2;
switch (current_cpu_data.cputype) {
case CPU_VR4122:
case CPU_VR4131:
case CPU_VR4133:
- val = readw(PMUCNT2REG);
- val |= SOFTRST;
- writew(val, PMUCNT2REG);
+ pmucnt2 = pmu_read(PMUCNT2REG);
+ pmucnt2 |= SOFTRST;
+ pmu_write(PMUCNT2REG, pmucnt2);
break;
default:
break;
@@ -71,6 +84,34 @@ static void vr41xx_power_off(void)
static int __init vr41xx_pmu_init(void)
{
+ unsigned long start, size;
+
+ switch (current_cpu_data.cputype) {
+ case CPU_VR4111:
+ case CPU_VR4121:
+ start = PMU_TYPE1_BASE;
+ size = PMU_TYPE1_SIZE;
+ break;
+ case CPU_VR4122:
+ case CPU_VR4131:
+ case CPU_VR4133:
+ start = PMU_TYPE2_BASE;
+ size = PMU_TYPE2_SIZE;
+ break;
+ default:
+ printk("Unexpected CPU of NEC VR4100 series\n");
+ return -ENODEV;
+ }
+
+ if (request_mem_region(start, size, "PMU") == NULL)
+ return -EBUSY;
+
+ pmu_base = ioremap(start, size);
+ if (pmu_base == NULL) {
+ release_mem_region(start, size);
+ return -EBUSY;
+ }
+
_machine_restart = vr41xx_restart;
_machine_halt = vr41xx_halt;
_machine_power_off = vr41xx_power_off;
@@ -78,4 +119,4 @@ static int __init vr41xx_pmu_init(void)
return 0;
}
-early_initcall(vr41xx_pmu_init);
+core_initcall(vr41xx_pmu_init);
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index e7e7c56fc21..ce327c799b4 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -148,7 +148,7 @@ config HOTPLUG_CPU
default y if SMP
select HOTPLUG
-config DISCONTIGMEM
+config ARCH_DISCONTIGMEM_ENABLE
bool "Discontiguous memory support (EXPERIMENTAL)"
depends on EXPERIMENTAL
help
@@ -157,6 +157,8 @@ config DISCONTIGMEM
or have huge holes in the physical address space for other reasons.
See <file:Documentation/vm/numa> for more.
+source "mm/Kconfig"
+
config PREEMPT
bool
# bool "Preemptible Kernel"
diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c
index ebf186656af..d34bbe7ae0e 100644
--- a/arch/parisc/kernel/drivers.c
+++ b/arch/parisc/kernel/drivers.c
@@ -466,7 +466,7 @@ static int parisc_generic_match(struct device *dev, struct device_driver *drv)
}
#define pa_dev_attr(name, field, format_string) \
-static ssize_t name##_show(struct device *dev, char *buf) \
+static ssize_t name##_show(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct parisc_device *padev = to_parisc_device(dev); \
return sprintf(buf, format_string, padev->field); \
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index cac37589e35..2886ad70db4 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -506,7 +506,7 @@ void show_mem(void)
for (j = node_start_pfn(i); j < node_end_pfn(i); j++) {
struct page *p;
- p = node_mem_map(i) + j - node_start_pfn(i);
+ p = nid_page_nr(i, j) - node_start_pfn(i);
total++;
if (PageReserved(p))
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index 600f23d7fd3..a7835cd3f51 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -88,6 +88,9 @@ config 8xx
depends on BROKEN
bool "8xx"
+config E200
+ bool "e200"
+
config E500
bool "e500"
@@ -98,12 +101,12 @@ config PPC_FPU
config BOOKE
bool
- depends on E500
+ depends on E200 || E500
default y
config FSL_BOOKE
bool
- depends on E500
+ depends on E200 || E500
default y
config PTE_64BIT
@@ -141,16 +144,16 @@ config ALTIVEC
config SPE
bool "SPE Support"
- depends on E500
+ depends on E200 || E500
---help---
This option enables kernel support for the Signal Processing
Extensions (SPE) to the PowerPC processor. The kernel currently
supports saving and restoring SPE registers, and turning on the
'spe enable' bit so user processes can execute SPE instructions.
- This option is only usefully if you have a processor that supports
+ This option is only useful if you have a processor that supports
SPE (e500, otherwise known as 85xx series), but does not have any
- affect on a non-spe cpu (it does, however add code to the kernel).
+ effect on a non-spe cpu (it does, however add code to the kernel).
If in doubt, say Y here.
@@ -200,7 +203,7 @@ config TAU_AVERAGE
config MATH_EMULATION
bool "Math emulation"
- depends on 4xx || 8xx || E500
+ depends on 4xx || 8xx || E200 || E500
---help---
Some PowerPC chips designed for embedded applications do not have
a floating-point unit and therefore do not implement the
@@ -214,6 +217,26 @@ config MATH_EMULATION
here. Saying Y here will not hurt performance (on any machine) but
will increase the size of the kernel.
+config KEXEC
+ bool "kexec system call (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ help
+ kexec is a system call that implements the ability to shutdown your
+ current kernel, and to start another kernel. It is like a reboot
+ but it is indepedent of the system firmware. And like a reboot
+ you can start any kernel with it, not just Linux.
+
+ The name comes from the similiarity to the exec system call.
+
+ It is an ongoing process to be certain the hardware in a machine
+ is properly shutdown, so do not be surprised if this code does not
+ initially work for you. It may help to enable device hotplugging
+ support. As of this writing the exact hardware interface is
+ strongly in flux, so no good recommendation can be made.
+
+ In the GameCube implementation, kexec allows you to load and
+ run DOL files, including kernel and homebrew DOLs.
+
source "drivers/cpufreq/Kconfig"
config CPU_FREQ_PMAC
@@ -254,7 +277,7 @@ config PPC_STD_MMU
config NOT_COHERENT_CACHE
bool
- depends on 4xx || 8xx
+ depends on 4xx || 8xx || E200
default y
endmenu
@@ -826,11 +849,6 @@ config MPC10X_BRIDGE
depends on PCORE || POWERPMC250 || LOPEC || SANDPOINT
default y
-config FSL_OCP
- bool
- depends on MPC10X_BRIDGE
- default y
-
config MPC10X_OPENPIC
bool
depends on POWERPMC250 || LOPEC || SANDPOINT
@@ -910,6 +928,8 @@ config PREEMPT
config HIGHMEM
bool "High memory support"
+source "mm/Kconfig"
+
source "fs/Kconfig.binfmt"
config PROC_DEVICETREE
@@ -1083,6 +1103,23 @@ source "drivers/zorro/Kconfig"
source kernel/power/Kconfig
+config SECCOMP
+ bool "Enable seccomp to safely compute untrusted bytecode"
+ depends on PROC_FS
+ default y
+ help
+ This kernel feature is useful for number crunching applications
+ that may need to compute untrusted bytecode during their
+ execution. By using pipes or other transports made available to
+ the process as file descriptors supporting the read/write
+ syscalls, it's possible to isolate those applications in
+ their own address space using seccomp. Once seccomp is
+ enabled via /proc/<pid>/seccomp, it cannot be disabled
+ and the task is only allowed to execute a few safe syscalls
+ defined by each seccomp mode.
+
+ If unsure, say Y. Only embedded should say N here.
+
endmenu
config ISA_DMA_API
@@ -1143,12 +1180,12 @@ config PCI_QSPAN
config PCI_8260
bool
- depends on PCI && 8260 && !8272
+ depends on PCI && 8260
default y
config 8260_PCI9
bool " Enable workaround for MPC826x erratum PCI 9"
- depends on PCI_8260
+ depends on PCI_8260 && !ADS8272
default y
choice
diff --git a/arch/ppc/Kconfig.debug b/arch/ppc/Kconfig.debug
index d2e1eea8e8e..e16c7710d4b 100644
--- a/arch/ppc/Kconfig.debug
+++ b/arch/ppc/Kconfig.debug
@@ -66,7 +66,7 @@ config SERIAL_TEXT_DEBUG
config PPC_OCP
bool
- depends on IBM_OCP || FSL_OCP || XILINX_OCP
+ depends on IBM_OCP || XILINX_OCP
default y
endmenu
diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile
index 0432a25b473..f9b0d778dd8 100644
--- a/arch/ppc/Makefile
+++ b/arch/ppc/Makefile
@@ -29,7 +29,7 @@ CPP = $(CC) -E $(CFLAGS)
CHECKFLAGS += -D__powerpc__
-ifndef CONFIG_E500
+ifndef CONFIG_FSL_BOOKE
CFLAGS += -mstring
endif
@@ -38,6 +38,7 @@ cpu-as-$(CONFIG_4xx) += -Wa,-m405
cpu-as-$(CONFIG_6xx) += -Wa,-maltivec
cpu-as-$(CONFIG_POWER4) += -Wa,-maltivec
cpu-as-$(CONFIG_E500) += -Wa,-me500
+cpu-as-$(CONFIG_E200) += -Wa,-me200
AFLAGS += $(cpu-as-y)
CFLAGS += $(cpu-as-y)
diff --git a/arch/ppc/boot/images/Makefile b/arch/ppc/boot/images/Makefile
index f850fb0fb51..c9ac5f5fa9e 100644
--- a/arch/ppc/boot/images/Makefile
+++ b/arch/ppc/boot/images/Makefile
@@ -22,7 +22,8 @@ targets += uImage
$(obj)/uImage: $(obj)/vmlinux.gz
$(Q)rm -f $@
$(call if_changed,uimage)
- @echo ' Image: $@' $(if $(wildcard $@),'is ready','not made')
+ @echo -n ' Image: $@ '
+ @if [ -f $@ ]; then echo 'is ready' ; else echo 'not made'; fi
# Files generated that shall be removed upon make clean
clean-files := sImage vmapus vmlinux* miboot* zImage* uImage
diff --git a/arch/ppc/boot/ld.script b/arch/ppc/boot/ld.script
index 6ee602d8b6a..9362193742a 100644
--- a/arch/ppc/boot/ld.script
+++ b/arch/ppc/boot/ld.script
@@ -58,9 +58,6 @@ SECTIONS
*(.ramdisk)
__ramdisk_end = .;
. = ALIGN(4096);
- __sysmap_begin = .;
- *(.sysmap)
- __sysmap_end = .;
CONSTRUCTORS
}
_edata = .;
diff --git a/arch/ppc/boot/openfirmware/Makefile b/arch/ppc/boot/openfirmware/Makefile
index 4eacbd8c772..03415238fab 100644
--- a/arch/ppc/boot/openfirmware/Makefile
+++ b/arch/ppc/boot/openfirmware/Makefile
@@ -54,13 +54,10 @@ $(images)/ramdisk.image.gz:
@echo ' RAM disk image must be provided separately'
@/bin/false
-objcpxmon-$(CONFIG_XMON) := --add-section=.sysmap=System.map \
- --set-section-flags=.sysmap=contents,alloc,load,readonly,data
quiet_cmd_genimage = GEN $@
cmd_genimage = $(OBJCOPY) -R .comment \
--add-section=.image=$(images)/vmlinux.gz \
- --set-section-flags=.image=contents,alloc,load,readonly,data \
- $(objcpxmon-y) $< $@
+ --set-section-flags=.image=contents,alloc,load,readonly,data $< $@
targets += image.o
$(obj)/image.o: $(obj)/dummy.o $(images)/vmlinux.gz FORCE
diff --git a/arch/ppc/boot/openfirmware/chrpmain.c b/arch/ppc/boot/openfirmware/chrpmain.c
index 6fb4f738728..effe4a0624b 100644
--- a/arch/ppc/boot/openfirmware/chrpmain.c
+++ b/arch/ppc/boot/openfirmware/chrpmain.c
@@ -39,7 +39,7 @@ char *avail_high;
#define SCRATCH_SIZE (128 << 10)
-static char scratch[SCRATCH_SIZE]; /* 1MB of scratch space for gunzip */
+static char scratch[SCRATCH_SIZE]; /* 128k of scratch space for gunzip */
typedef void (*kernel_start_t)(int, int, void *, unsigned int, unsigned int);
diff --git a/arch/ppc/boot/openfirmware/common.c b/arch/ppc/boot/openfirmware/common.c
index 9e6952781f1..0f46756a903 100644
--- a/arch/ppc/boot/openfirmware/common.c
+++ b/arch/ppc/boot/openfirmware/common.c
@@ -15,7 +15,6 @@
#include <asm/page.h>
/* Information from the linker */
-extern char __sysmap_begin, __sysmap_end;
extern int strcmp(const char *s1, const char *s2);
extern char *avail_ram, *avail_high;
@@ -116,14 +115,8 @@ void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp)
void make_bi_recs(unsigned long addr, char *name, unsigned int mach,
unsigned long progend)
{
- unsigned long sysmap_size;
struct bi_record *rec;
- /* Figure out the size of a possible System.map we're going to
- * pass along.
- * */
- sysmap_size = (unsigned long)(&__sysmap_end) -
- (unsigned long)(&__sysmap_begin);
/* leave a 1MB gap then align to the next 1MB boundary */
addr = _ALIGN(addr+ (1<<20) - 1, (1<<20));
@@ -147,15 +140,6 @@ void make_bi_recs(unsigned long addr, char *name, unsigned int mach,
rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long);
rec = (struct bi_record *)((unsigned long)rec + rec->size);
- if (sysmap_size) {
- rec->tag = BI_SYSMAP;
- rec->data[0] = (unsigned long)(&__sysmap_begin);
- rec->data[1] = sysmap_size;
- rec->size = sizeof(struct bi_record) + 2 *
- sizeof(unsigned long);
- rec = (struct bi_record *)((unsigned long)rec + rec->size);
- }
-
rec->tag = BI_LAST;
rec->size = sizeof(struct bi_record);
rec = (struct bi_record *)((unsigned long)rec + rec->size);
diff --git a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile
index c28061ad598..991b4cbb83c 100644
--- a/arch/ppc/boot/simple/Makefile
+++ b/arch/ppc/boot/simple/Makefile
@@ -203,7 +203,7 @@ $(obj)/zvmlinux: $(OBJS) $(LIBS) $(srctree)/$(boot)/ld.script \
$(obj)/dummy.o $(obj)/image.o
$(LD) $(LD_ARGS) -o $@ $(OBJS) $(obj)/image.o $(LIBS)
$(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab \
- -R .stabstr -R .ramdisk -R .sysmap
+ -R .stabstr -R .ramdisk
$(obj)/zvmlinux.initrd: $(OBJS) $(LIBS) $(srctree)/$(boot)/ld.script \
$(images)/vmlinux.gz $(obj)/dummy.o
@@ -215,7 +215,7 @@ $(obj)/zvmlinux.initrd: $(OBJS) $(LIBS) $(srctree)/$(boot)/ld.script \
$(obj)/dummy.o $(obj)/image.o
$(LD) $(LD_ARGS) -o $@ $(OBJS) $(obj)/image.o $(LIBS)
$(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab \
- -R .stabstr -R .sysmap
+ -R .stabstr
# Sort-of dummy rules, that let us format the image we want.
zImage: $(images)/$(zimage-y) $(obj)/zvmlinux
diff --git a/arch/ppc/boot/simple/misc.c b/arch/ppc/boot/simple/misc.c
index ab0f9902cb6..e02de5b467a 100644
--- a/arch/ppc/boot/simple/misc.c
+++ b/arch/ppc/boot/simple/misc.c
@@ -222,7 +222,7 @@ decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum)
puts("\n");
puts("Uncompressing Linux...");
- gunzip(0x0, 0x400000, zimage_start, &zimage_size);
+ gunzip(NULL, 0x400000, zimage_start, &zimage_size);
puts("done.\n");
/* get the bi_rec address */
diff --git a/arch/ppc/boot/simple/mpc10x_memory.c b/arch/ppc/boot/simple/mpc10x_memory.c
index 977daedc14c..20d92a34ceb 100644
--- a/arch/ppc/boot/simple/mpc10x_memory.c
+++ b/arch/ppc/boot/simple/mpc10x_memory.c
@@ -33,7 +33,7 @@
#define MPC10X_PCI_OP(rw, size, type, op, mask) \
static void \
-mpc10x_##rw##_config_##size(unsigned int *cfg_addr, \
+mpc10x_##rw##_config_##size(unsigned int __iomem *cfg_addr, \
unsigned int *cfg_data, int devfn, int offset, \
type val) \
{ \
diff --git a/arch/ppc/boot/utils/addSystemMap.c b/arch/ppc/boot/utils/addSystemMap.c
deleted file mode 100644
index 4654f891b27..00000000000
--- a/arch/ppc/boot/utils/addSystemMap.c
+++ /dev/null
@@ -1,186 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <byteswap.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-void xlate( char * inb, char * trb, unsigned len )
-{
- unsigned i;
- for ( i=0; i<len; ++i ) {
- char c = *inb++;
- char c1 = c >> 4;
- char c2 = c & 0xf;
- if ( c1 > 9 )
- c1 = c1 + 'A' - 10;
- else
- c1 = c1 + '0';
- if ( c2 > 9 )
- c2 = c2 + 'A' - 10;
- else
- c2 = c2 + '0';
- *trb++ = c1;
- *trb++ = c2;
- }
- *trb = 0;
-}
-
-#define ElfHeaderSize (64 * 1024)
-#define ElfPages (ElfHeaderSize / 4096)
-#define KERNELBASE (0xc0000000)
-
-void get4k( /*istream *inf*/FILE *file, char *buf )
-{
- unsigned j;
- unsigned num = fread(buf, 1, 4096, file);
- for ( j=num; j<4096; ++j )
- buf[j] = 0;
-}
-
-void put4k( /*ostream *outf*/FILE *file, char *buf )
-{
- fwrite(buf, 1, 4096, file);
-}
-
-int main(int argc, char **argv)
-{
- char inbuf[4096];
- FILE *ramDisk = NULL;
- FILE *inputVmlinux = NULL;
- FILE *outputVmlinux = NULL;
- unsigned i = 0;
- unsigned long ramFileLen = 0;
- unsigned long ramLen = 0;
- unsigned long roundR = 0;
- unsigned long kernelLen = 0;
- unsigned long actualKernelLen = 0;
- unsigned long round = 0;
- unsigned long roundedKernelLen = 0;
- unsigned long ramStartOffs = 0;
- unsigned long ramPages = 0;
- unsigned long roundedKernelPages = 0;
- if ( argc < 2 ) {
- printf("Name of System Map file missing.\n");
- exit(1);
- }
-
- if ( argc < 3 ) {
- printf("Name of vmlinux file missing.\n");
- exit(1);
- }
-
- if ( argc < 4 ) {
- printf("Name of vmlinux output file missing.\n");
- exit(1);
- }
-
- ramDisk = fopen(argv[1], "r");
- if ( ! ramDisk ) {
- printf("System Map file \"%s\" failed to open.\n", argv[1]);
- exit(1);
- }
- inputVmlinux = fopen(argv[2], "r");
- if ( ! inputVmlinux ) {
- printf("vmlinux file \"%s\" failed to open.\n", argv[2]);
- exit(1);
- }
- outputVmlinux = fopen(argv[3], "w");
- if ( ! outputVmlinux ) {
- printf("output vmlinux file \"%s\" failed to open.\n", argv[3]);
- exit(1);
- }
- fseek(ramDisk, 0, SEEK_END);
- ramFileLen = ftell(ramDisk);
- fseek(ramDisk, 0, SEEK_SET);
- printf("%s file size = %ld\n", argv[1], ramFileLen);
-
- ramLen = ramFileLen;
-
- roundR = 4096 - (ramLen % 4096);
- if ( roundR ) {
- printf("Rounding System Map file up to a multiple of 4096, adding %ld\n", roundR);
- ramLen += roundR;
- }
-
- printf("Rounded System Map size is %ld\n", ramLen);
- fseek(inputVmlinux, 0, SEEK_END);
- kernelLen = ftell(inputVmlinux);
- fseek(inputVmlinux, 0, SEEK_SET);
- printf("kernel file size = %ld\n", kernelLen);
- if ( kernelLen == 0 ) {
- printf("You must have a linux kernel specified as argv[2]\n");
- exit(1);
- }
-
- actualKernelLen = kernelLen - ElfHeaderSize;
-
- printf("actual kernel length (minus ELF header) = %ld\n", actualKernelLen);
-
- round = actualKernelLen % 4096;
- roundedKernelLen = actualKernelLen;
- if ( round )
- roundedKernelLen += (4096 - round);
-
- printf("actual kernel length rounded up to a 4k multiple = %ld\n", roundedKernelLen);
-
- ramStartOffs = roundedKernelLen;
- ramPages = ramLen / 4096;
-
- printf("System map pages to copy = %ld\n", ramPages);
-
- // Copy 64K ELF header
- for (i=0; i<(ElfPages); ++i) {
- get4k( inputVmlinux, inbuf );
- put4k( outputVmlinux, inbuf );
- }
-
-
-
- roundedKernelPages = roundedKernelLen / 4096;
-
- fseek(inputVmlinux, ElfHeaderSize, SEEK_SET);
-
- {
- for ( i=0; i<roundedKernelPages; ++i ) {
- get4k( inputVmlinux, inbuf );
- if ( i == 0 ) {
- unsigned long * p;
- printf("Storing embedded_sysmap_start at 0x3c\n");
- p = (unsigned long *)(inbuf + 0x3c);
-
-#if (BYTE_ORDER == __BIG_ENDIAN)
- *p = ramStartOffs;
-#else
- *p = bswap_32(ramStartOffs);
-#endif
-
- printf("Storing embedded_sysmap_end at 0x44\n");
- p = (unsigned long *)(inbuf + 0x44);
-#if (BYTE_ORDER == __BIG_ENDIAN)
- *p = ramStartOffs + ramFileLen;
-#else
- *p = bswap_32(ramStartOffs + ramFileLen);
-#endif
- }
- put4k( outputVmlinux, inbuf );
- }
- }
-
- {
- for ( i=0; i<ramPages; ++i ) {
- get4k( ramDisk, inbuf );
- put4k( outputVmlinux, inbuf );
- }
- }
-
-
- fclose(ramDisk);
- fclose(inputVmlinux);
- fclose(outputVmlinux);
- /* Set permission to executable */
- chmod(argv[3], S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
-
- return 0;
-
-}
-
diff --git a/arch/ppc/configs/mpc8548_cds_defconfig b/arch/ppc/configs/mpc8548_cds_defconfig
new file mode 100644
index 00000000000..abe034f24b8
--- /dev/null
+++ b/arch/ppc/configs/mpc8548_cds_defconfig
@@ -0,0 +1,659 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc4
+# Tue May 24 22:36:27 2005
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+CONFIG_E500=y
+CONFIG_BOOKE=y
+CONFIG_FSL_BOOKE=y
+# CONFIG_PHYS_64BIT is not set
+CONFIG_SPE=y
+CONFIG_MATH_EMULATION=y
+# CONFIG_CPU_FREQ is not set
+# CONFIG_PM is not set
+CONFIG_85xx=y
+CONFIG_PPC_INDIRECT_PCI_BE=y
+
+#
+# Freescale 85xx options
+#
+# CONFIG_MPC8540_ADS is not set
+CONFIG_MPC8548_CDS=y
+# CONFIG_MPC8555_CDS is not set
+# CONFIG_MPC8560_ADS is not set
+# CONFIG_SBC8560 is not set
+# CONFIG_STX_GP3 is not set
+CONFIG_MPC8548=y
+
+#
+# Platform options
+#
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_GIANFAR=y
+CONFIG_GFAR_NAPI=y
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ISA is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_M41T00 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff --git a/arch/ppc/configs/mpc8555_cds_defconfig b/arch/ppc/configs/mpc8555_cds_defconfig
index 728bd9e1a8f..15abebf46b9 100644
--- a/arch/ppc/configs/mpc8555_cds_defconfig
+++ b/arch/ppc/configs/mpc8555_cds_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc1
-# Thu Jan 20 01:25:35 2005
+# Linux kernel version: 2.6.12-rc4
+# Tue May 17 11:56:01 2005
#
CONFIG_MMU=y
CONFIG_GENERIC_HARDIRQS=y
@@ -11,6 +11,7 @@ CONFIG_HAVE_DEC_LOCK=y
CONFIG_PPC=y
CONFIG_PPC32=y
CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
#
# Code maturity level options
@@ -18,6 +19,7 @@ CONFIG_GENERIC_NVRAM=y
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -29,12 +31,14 @@ CONFIG_SYSVIPC=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
# CONFIG_HOTPLUG is not set
CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
CONFIG_EMBEDDED=y
# CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
# CONFIG_EPOLL is not set
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -44,6 +48,7 @@ CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -62,10 +67,12 @@ CONFIG_CC_ALIGN_JUMPS=0
CONFIG_E500=y
CONFIG_BOOKE=y
CONFIG_FSL_BOOKE=y
+# CONFIG_PHYS_64BIT is not set
CONFIG_SPE=y
CONFIG_MATH_EMULATION=y
# CONFIG_CPU_FREQ is not set
CONFIG_PPC_GEN550=y
+# CONFIG_PM is not set
CONFIG_85xx=y
CONFIG_PPC_INDIRECT_PCI_BE=y
@@ -76,6 +83,7 @@ CONFIG_PPC_INDIRECT_PCI_BE=y
CONFIG_MPC8555_CDS=y
# CONFIG_MPC8560_ADS is not set
# CONFIG_SBC8560 is not set
+# CONFIG_STX_GP3 is not set
CONFIG_MPC8555=y
CONFIG_85xx_PCI2=y
@@ -90,6 +98,7 @@ CONFIG_CPM2=y
CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
# CONFIG_CMDLINE_BOOL is not set
+CONFIG_ISA_DMA_API=y
#
# Bus options
@@ -105,10 +114,6 @@ CONFIG_PCI_NAMES=y
# CONFIG_PCCARD is not set
#
-# PC-card bridges
-#
-
-#
# Advanced setup
#
# CONFIG_ADVANCED_OPTIONS is not set
@@ -180,7 +185,59 @@ CONFIG_IOSCHED_CFQ=y
#
# ATA/ATAPI/MFM/RLL support
#
-# CONFIG_IDE is not set
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_SHARE_IRQ=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+CONFIG_BLK_DEV_VIA82CXXX=y
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_HD is not set
#
# SCSI device support
@@ -220,7 +277,6 @@ CONFIG_NET=y
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
@@ -370,14 +426,6 @@ CONFIG_INPUT=y
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -387,6 +435,13 @@ CONFIG_SOUND_GAMEPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
# Character devices
#
# CONFIG_VT is not set
@@ -406,6 +461,7 @@ CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_CPM is not set
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -434,6 +490,11 @@ CONFIG_GEN_RTC=y
# CONFIG_RAW_DRIVER is not set
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
CONFIG_I2C=y
@@ -456,11 +517,11 @@ CONFIG_I2C_CHARDEV=y
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_ISA is not set
CONFIG_I2C_MPC=y
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
# CONFIG_SCx200_ACB is not set
@@ -483,7 +544,9 @@ CONFIG_I2C_MPC=y
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
# CONFIG_SENSORS_LM63 is not set
# CONFIG_SENSORS_LM75 is not set
@@ -494,9 +557,11 @@ CONFIG_I2C_MPC=y
# CONFIG_SENSORS_LM85 is not set
# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_W83781D is not set
@@ -506,10 +571,12 @@ CONFIG_I2C_MPC=y
#
# Other I2C Chip support
#
+# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_M41T00 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_I2C_DEBUG_ALGO is not set
# CONFIG_I2C_DEBUG_BUS is not set
@@ -538,7 +605,6 @@ CONFIG_I2C_MPC=y
# Graphics support
#
# CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
#
# Sound
@@ -548,13 +614,9 @@ CONFIG_I2C_MPC=y
#
# USB support
#
-# CONFIG_USB is not set
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
#
# USB Gadget Support
@@ -585,6 +647,10 @@ CONFIG_JBD=y
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
# CONFIG_XFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_ROMFS_FS is not set
@@ -646,7 +712,6 @@ CONFIG_NFS_FS=y
# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
CONFIG_SUNRPC=y
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -698,7 +763,9 @@ CONFIG_CRC32=y
#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
# CONFIG_DEBUG_KERNEL is not set
+CONFIG_LOG_BUF_SHIFT=14
# CONFIG_KGDB_CONSOLE is not set
# CONFIG_SERIAL_TEXT_DEBUG is not set
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
index b284451802c..b1457a8a9c0 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -26,7 +26,10 @@ obj-$(CONFIG_KGDB) += ppc-stub.o
obj-$(CONFIG_SMP) += smp.o smp-tbsync.o
obj-$(CONFIG_TAU) += temp.o
obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
+ifndef CONFIG_E200
obj-$(CONFIG_FSL_BOOKE) += perfmon_fsl_booke.o
+endif
+obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
ifndef CONFIG_MATH_EMULATION
obj-$(CONFIG_8xx) += softemu8xx.o
diff --git a/arch/ppc/kernel/cputable.c b/arch/ppc/kernel/cputable.c
index 8aa5e8c6900..50936cda0af 100644
--- a/arch/ppc/kernel/cputable.c
+++ b/arch/ppc/kernel/cputable.c
@@ -838,6 +838,17 @@ struct cpu_spec cpu_specs[] = {
.icache_bsize = 32,
.dcache_bsize = 32,
},
+ { /* 405EP */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x51210000,
+ .cpu_name = "405EP",
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB,
+ .cpu_user_features = PPC_FEATURE_32 |
+ PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ },
#endif /* CONFIG_40x */
#ifdef CONFIG_44x
@@ -892,7 +903,30 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 32,
},
#endif /* CONFIG_44x */
-#ifdef CONFIG_E500
+#ifdef CONFIG_FSL_BOOKE
+ { /* e200z5 */
+ .pvr_mask = 0xfff00000,
+ .pvr_value = 0x81000000,
+ .cpu_name = "e200z5",
+ /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
+ .cpu_features = CPU_FTR_USE_TB,
+ .cpu_user_features = PPC_FEATURE_32 |
+ PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_EFP_SINGLE |
+ PPC_FEATURE_UNIFIED_CACHE,
+ .dcache_bsize = 32,
+ },
+ { /* e200z6 */
+ .pvr_mask = 0xfff00000,
+ .pvr_value = 0x81100000,
+ .cpu_name = "e200z6",
+ /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
+ .cpu_features = CPU_FTR_USE_TB,
+ .cpu_user_features = PPC_FEATURE_32 |
+ PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP |
+ PPC_FEATURE_HAS_EFP_SINGLE |
+ PPC_FEATURE_UNIFIED_CACHE,
+ .dcache_bsize = 32,
+ },
{ /* e500 */
.pvr_mask = 0xffff0000,
.pvr_value = 0x80200000,
@@ -907,6 +941,20 @@ struct cpu_spec cpu_specs[] = {
.dcache_bsize = 32,
.num_pmcs = 4,
},
+ { /* e500v2 */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x80210000,
+ .cpu_name = "e500v2",
+ /* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
+ .cpu_features = CPU_FTR_SPLIT_ID_CACHE |
+ CPU_FTR_USE_TB | CPU_FTR_BIG_PHYS,
+ .cpu_user_features = PPC_FEATURE_32 |
+ PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP |
+ PPC_FEATURE_HAS_EFP_SINGLE | PPC_FEATURE_HAS_EFP_DOUBLE,
+ .icache_bsize = 32,
+ .dcache_bsize = 32,
+ .num_pmcs = 4,
+ },
#endif
#if !CLASSIC_PPC
{ /* default match */
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index 5f075dbc4ee..d4df68629cc 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -46,26 +46,28 @@
#ifdef CONFIG_BOOKE
#include "head_booke.h"
+#define TRANSFER_TO_HANDLER_EXC_LEVEL(exc_level) \
+ mtspr exc_level##_SPRG,r8; \
+ BOOKE_LOAD_EXC_LEVEL_STACK(exc_level); \
+ lwz r0,GPR10-INT_FRAME_SIZE(r8); \
+ stw r0,GPR10(r11); \
+ lwz r0,GPR11-INT_FRAME_SIZE(r8); \
+ stw r0,GPR11(r11); \
+ mfspr r8,exc_level##_SPRG
+
.globl mcheck_transfer_to_handler
mcheck_transfer_to_handler:
- mtspr MCHECK_SPRG,r8
- BOOKE_LOAD_MCHECK_STACK
- lwz r0,GPR10-INT_FRAME_SIZE(r8)
- stw r0,GPR10(r11)
- lwz r0,GPR11-INT_FRAME_SIZE(r8)
- stw r0,GPR11(r11)
- mfspr r8,MCHECK_SPRG
+ TRANSFER_TO_HANDLER_EXC_LEVEL(MCHECK)
+ b transfer_to_handler_full
+
+ .globl debug_transfer_to_handler
+debug_transfer_to_handler:
+ TRANSFER_TO_HANDLER_EXC_LEVEL(DEBUG)
b transfer_to_handler_full
.globl crit_transfer_to_handler
crit_transfer_to_handler:
- mtspr CRIT_SPRG,r8
- BOOKE_LOAD_CRIT_STACK
- lwz r0,GPR10-INT_FRAME_SIZE(r8)
- stw r0,GPR10(r11)
- lwz r0,GPR11-INT_FRAME_SIZE(r8)
- stw r0,GPR11(r11)
- mfspr r8,CRIT_SPRG
+ TRANSFER_TO_HANDLER_EXC_LEVEL(CRIT)
/* fall through */
#endif
@@ -202,7 +204,7 @@ _GLOBAL(DoSyscall)
rlwinm r11,r11,0,~_TIFL_FORCE_NOERROR
stw r11,TI_LOCAL_FLAGS(r10)
lwz r11,TI_FLAGS(r10)
- andi. r11,r11,_TIF_SYSCALL_TRACE
+ andi. r11,r11,_TIF_SYSCALL_T_OR_A
bne- syscall_dotrace
syscall_dotrace_cont:
cmplwi 0,r0,NR_syscalls
@@ -237,7 +239,7 @@ ret_from_syscall:
SYNC
MTMSRD(r10)
lwz r9,TI_FLAGS(r12)
- andi. r0,r9,(_TIF_SYSCALL_TRACE|_TIF_SIGPENDING|_TIF_NEED_RESCHED)
+ andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED)
bne- syscall_exit_work
syscall_exit_cont:
#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
@@ -277,7 +279,8 @@ syscall_dotrace:
SAVE_NVGPRS(r1)
li r0,0xc00
stw r0,TRAP(r1)
- bl do_syscall_trace
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ bl do_syscall_trace_enter
lwz r0,GPR0(r1) /* Restore original registers */
lwz r3,GPR3(r1)
lwz r4,GPR4(r1)
@@ -291,7 +294,7 @@ syscall_dotrace:
syscall_exit_work:
stw r6,RESULT(r1) /* Save result */
stw r3,GPR3(r1) /* Update return value */
- andi. r0,r9,_TIF_SYSCALL_TRACE
+ andi. r0,r9,_TIF_SYSCALL_T_OR_A
beq 5f
ori r10,r10,MSR_EE
SYNC
@@ -303,7 +306,8 @@ syscall_exit_work:
li r4,0xc00
stw r4,TRAP(r1)
4:
- bl do_syscall_trace
+ addi r3,r1,STACK_FRAME_OVERHEAD
+ bl do_syscall_trace_leave
REST_NVGPRS(r1)
2:
lwz r3,GPR3(r1)
@@ -627,8 +631,8 @@ sigreturn_exit:
subi r1,r3,STACK_FRAME_OVERHEAD
rlwinm r12,r1,0,0,18 /* current_thread_info() */
lwz r9,TI_FLAGS(r12)
- andi. r0,r9,_TIF_SYSCALL_TRACE
- bnel- do_syscall_trace
+ andi. r0,r9,_TIF_SYSCALL_T_OR_A
+ bnel- do_syscall_trace_leave
/* fall through */
.globl ret_from_except_full
@@ -781,99 +785,68 @@ exc_exit_restart_end:
* time of the critical interrupt.
*
*/
- .globl ret_from_crit_exc
-ret_from_crit_exc:
- REST_NVGPRS(r1)
- lwz r3,_MSR(r1)
- andi. r3,r3,MSR_PR
- LOAD_MSR_KERNEL(r10,MSR_KERNEL)
- bne user_exc_return
-
- lwz r0,GPR0(r1)
- lwz r2,GPR2(r1)
- REST_4GPRS(3, r1)
- REST_2GPRS(7, r1)
-
- lwz r10,_XER(r1)
- lwz r11,_CTR(r1)
- mtspr SPRN_XER,r10
- mtctr r11
-
- PPC405_ERR77(0,r1)
- stwcx. r0,0,r1 /* to clear the reservation */
-
- lwz r11,_LINK(r1)
- mtlr r11
- lwz r10,_CCR(r1)
- mtcrf 0xff,r10
#ifdef CONFIG_40x
- /* avoid any possible TLB misses here by turning off MSR.DR, we
- * assume the instructions here are mapped by a pinned TLB entry */
- li r10,MSR_IR
- mtmsr r10
- isync
- tophys(r1, r1)
+#define PPC_40x_TURN_OFF_MSR_DR \
+ /* avoid any possible TLB misses here by turning off MSR.DR, we \
+ * assume the instructions here are mapped by a pinned TLB entry */ \
+ li r10,MSR_IR; \
+ mtmsr r10; \
+ isync; \
+ tophys(r1, r1);
+#else
+#define PPC_40x_TURN_OFF_MSR_DR
#endif
- lwz r9,_DEAR(r1)
- lwz r10,_ESR(r1)
- mtspr SPRN_DEAR,r9
- mtspr SPRN_ESR,r10
- lwz r11,_NIP(r1)
- lwz r12,_MSR(r1)
- mtspr SPRN_CSRR0,r11
- mtspr SPRN_CSRR1,r12
- lwz r9,GPR9(r1)
- lwz r12,GPR12(r1)
- lwz r10,GPR10(r1)
- lwz r11,GPR11(r1)
- lwz r1,GPR1(r1)
- PPC405_ERR77_SYNC
- rfci
- b . /* prevent prefetch past rfci */
-#ifdef CONFIG_BOOKE
-/*
- * Return from a machine check interrupt, similar to a critical
- * interrupt.
- */
- .globl ret_from_mcheck_exc
-ret_from_mcheck_exc:
- REST_NVGPRS(r1)
- lwz r3,_MSR(r1)
- andi. r3,r3,MSR_PR
- LOAD_MSR_KERNEL(r10,MSR_KERNEL)
- bne user_exc_return
-
- lwz r0,GPR0(r1)
- lwz r2,GPR2(r1)
- REST_4GPRS(3, r1)
- REST_2GPRS(7, r1)
+#define RET_FROM_EXC_LEVEL(exc_lvl_srr0, exc_lvl_srr1, exc_lvl_rfi) \
+ REST_NVGPRS(r1); \
+ lwz r3,_MSR(r1); \
+ andi. r3,r3,MSR_PR; \
+ LOAD_MSR_KERNEL(r10,MSR_KERNEL); \
+ bne user_exc_return; \
+ lwz r0,GPR0(r1); \
+ lwz r2,GPR2(r1); \
+ REST_4GPRS(3, r1); \
+ REST_2GPRS(7, r1); \
+ lwz r10,_XER(r1); \
+ lwz r11,_CTR(r1); \
+ mtspr SPRN_XER,r10; \
+ mtctr r11; \
+ PPC405_ERR77(0,r1); \
+ stwcx. r0,0,r1; /* to clear the reservation */ \
+ lwz r11,_LINK(r1); \
+ mtlr r11; \
+ lwz r10,_CCR(r1); \
+ mtcrf 0xff,r10; \
+ PPC_40x_TURN_OFF_MSR_DR; \
+ lwz r9,_DEAR(r1); \
+ lwz r10,_ESR(r1); \
+ mtspr SPRN_DEAR,r9; \
+ mtspr SPRN_ESR,r10; \
+ lwz r11,_NIP(r1); \
+ lwz r12,_MSR(r1); \
+ mtspr exc_lvl_srr0,r11; \
+ mtspr exc_lvl_srr1,r12; \
+ lwz r9,GPR9(r1); \
+ lwz r12,GPR12(r1); \
+ lwz r10,GPR10(r1); \
+ lwz r11,GPR11(r1); \
+ lwz r1,GPR1(r1); \
+ PPC405_ERR77_SYNC; \
+ exc_lvl_rfi; \
+ b .; /* prevent prefetch past exc_lvl_rfi */
- lwz r10,_XER(r1)
- lwz r11,_CTR(r1)
- mtspr SPRN_XER,r10
- mtctr r11
+ .globl ret_from_crit_exc
+ret_from_crit_exc:
+ RET_FROM_EXC_LEVEL(SPRN_CSRR0, SPRN_CSRR1, RFCI)
- stwcx. r0,0,r1 /* to clear the reservation */
+#ifdef CONFIG_BOOKE
+ .globl ret_from_debug_exc
+ret_from_debug_exc:
+ RET_FROM_EXC_LEVEL(SPRN_DSRR0, SPRN_DSRR1, RFDI)
- lwz r11,_LINK(r1)
- mtlr r11
- lwz r10,_CCR(r1)
- mtcrf 0xff,r10
- lwz r9,_DEAR(r1)
- lwz r10,_ESR(r1)
- mtspr SPRN_DEAR,r9
- mtspr SPRN_ESR,r10
- lwz r11,_NIP(r1)
- lwz r12,_MSR(r1)
- mtspr SPRN_MCSRR0,r11
- mtspr SPRN_MCSRR1,r12
- lwz r9,GPR9(r1)
- lwz r12,GPR12(r1)
- lwz r10,GPR10(r1)
- lwz r11,GPR11(r1)
- lwz r1,GPR1(r1)
- RFMCI
+ .globl ret_from_mcheck_exc
+ret_from_mcheck_exc:
+ RET_FROM_EXC_LEVEL(SPRN_MCSRR0, SPRN_MCSRR1, RFMCI)
#endif /* CONFIG_BOOKE */
/*
diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S
index 9b6a8e51365..6c7ae605246 100644
--- a/arch/ppc/kernel/head_44x.S
+++ b/arch/ppc/kernel/head_44x.S
@@ -330,8 +330,9 @@ interrupt_base:
/* If we are faulting a kernel address, we have to use the
* kernel page tables.
*/
- andis. r11, r10, 0x8000
- beq 3f
+ lis r11, TASK_SIZE@h
+ cmplw r10, r11
+ blt+ 3f
lis r11, swapper_pg_dir@h
ori r11, r11, swapper_pg_dir@l
@@ -464,8 +465,9 @@ interrupt_base:
/* If we are faulting a kernel address, we have to use the
* kernel page tables.
*/
- andis. r11, r10, 0x8000
- beq 3f
+ lis r11, TASK_SIZE@h
+ cmplw r10, r11
+ blt+ 3f
lis r11, swapper_pg_dir@h
ori r11, r11, swapper_pg_dir@l
@@ -533,8 +535,9 @@ interrupt_base:
/* If we are faulting a kernel address, we have to use the
* kernel page tables.
*/
- andis. r11, r10, 0x8000
- beq 3f
+ lis r11, TASK_SIZE@h
+ cmplw r10, r11
+ blt+ 3f
lis r11, swapper_pg_dir@h
ori r11, r11, swapper_pg_dir@l
diff --git a/arch/ppc/kernel/head_4xx.S b/arch/ppc/kernel/head_4xx.S
index 6f5d380e234..23fb51819ba 100644
--- a/arch/ppc/kernel/head_4xx.S
+++ b/arch/ppc/kernel/head_4xx.S
@@ -291,8 +291,9 @@ label:
/* If we are faulting a kernel address, we have to use the
* kernel page tables.
*/
- andis. r11, r10, 0x8000
- beq 3f
+ lis r11, TASK_SIZE@h
+ cmplw r10, r11
+ blt+ 3f
lis r11, swapper_pg_dir@h
ori r11, r11, swapper_pg_dir@l
li r9, 0
@@ -479,8 +480,9 @@ label:
/* If we are faulting a kernel address, we have to use the
* kernel page tables.
*/
- andis. r11, r10, 0x8000
- beq 3f
+ lis r11, TASK_SIZE@h
+ cmplw r10, r11
+ blt+ 3f
lis r11, swapper_pg_dir@h
ori r11, r11, swapper_pg_dir@l
li r9, 0
@@ -578,8 +580,9 @@ label:
/* If we are faulting a kernel address, we have to use the
* kernel page tables.
*/
- andis. r11, r10, 0x8000
- beq 3f
+ lis r11, TASK_SIZE@h
+ cmplw r10, r11
+ blt+ 3f
lis r11, swapper_pg_dir@h
ori r11, r11, swapper_pg_dir@l
li r9, 0
diff --git a/arch/ppc/kernel/head_booke.h b/arch/ppc/kernel/head_booke.h
index f213d12eec0..9342acf12e7 100644
--- a/arch/ppc/kernel/head_booke.h
+++ b/arch/ppc/kernel/head_booke.h
@@ -49,6 +49,7 @@
*
* On 40x critical is the only additional level
* On 44x/e500 we have critical and machine check
+ * On e200 we have critical and debug (machine check occurs via critical)
*
* Additionally we reserve a SPRG for each priority level so we can free up a
* GPR to use as the base for indirect access to the exception stacks. This
@@ -60,53 +61,47 @@
/* CRIT_SPRG only used in critical exception handling */
#define CRIT_SPRG SPRN_SPRG2
-/* MCHECK_SPRG only used in critical exception handling */
+/* MCHECK_SPRG only used in machine check exception handling */
#define MCHECK_SPRG SPRN_SPRG6W
#define MCHECK_STACK_TOP (exception_stack_top - 4096)
#define CRIT_STACK_TOP (exception_stack_top)
+/* only on e200 for now */
+#define DEBUG_STACK_TOP (exception_stack_top - 4096)
+#define DEBUG_SPRG SPRN_SPRG6W
+
#ifdef CONFIG_SMP
-#define BOOKE_LOAD_CRIT_STACK \
+#define BOOKE_LOAD_EXC_LEVEL_STACK(level) \
mfspr r8,SPRN_PIR; \
mulli r8,r8,BOOKE_EXCEPTION_STACK_SIZE; \
neg r8,r8; \
- addis r8,r8,CRIT_STACK_TOP@ha; \
- addi r8,r8,CRIT_STACK_TOP@l
-#define BOOKE_LOAD_MCHECK_STACK \
- mfspr r8,SPRN_PIR; \
- mulli r8,r8,BOOKE_EXCEPTION_STACK_SIZE; \
- neg r8,r8; \
- addis r8,r8,MCHECK_STACK_TOP@ha; \
- addi r8,r8,MCHECK_STACK_TOP@l
+ addis r8,r8,level##_STACK_TOP@ha; \
+ addi r8,r8,level##_STACK_TOP@l
#else
-#define BOOKE_LOAD_CRIT_STACK \
- lis r8,CRIT_STACK_TOP@h; \
- ori r8,r8,CRIT_STACK_TOP@l
-#define BOOKE_LOAD_MCHECK_STACK \
- lis r8,MCHECK_STACK_TOP@h; \
- ori r8,r8,MCHECK_STACK_TOP@l
+#define BOOKE_LOAD_EXC_LEVEL_STACK(level) \
+ lis r8,level##_STACK_TOP@h; \
+ ori r8,r8,level##_STACK_TOP@l
#endif
/*
- * Exception prolog for critical exceptions. This is a little different
- * from the normal exception prolog above since a critical exception
- * can potentially occur at any point during normal exception processing.
- * Thus we cannot use the same SPRG registers as the normal prolog above.
- * Instead we use a portion of the critical exception stack at low physical
- * addresses.
+ * Exception prolog for critical/machine check exceptions. This is a
+ * little different from the normal exception prolog above since a
+ * critical/machine check exception can potentially occur at any point
+ * during normal exception processing. Thus we cannot use the same SPRG
+ * registers as the normal prolog above. Instead we use a portion of the
+ * critical/machine check exception stack at low physical addresses.
*/
-
-#define CRITICAL_EXCEPTION_PROLOG \
- mtspr CRIT_SPRG,r8; \
- BOOKE_LOAD_CRIT_STACK; /* r8 points to the crit stack */ \
+#define EXC_LEVEL_EXCEPTION_PROLOG(exc_level, exc_level_srr0, exc_level_srr1) \
+ mtspr exc_level##_SPRG,r8; \
+ BOOKE_LOAD_EXC_LEVEL_STACK(exc_level);/* r8 points to the exc_level stack*/ \
stw r10,GPR10-INT_FRAME_SIZE(r8); \
stw r11,GPR11-INT_FRAME_SIZE(r8); \
mfcr r10; /* save CR in r10 for now */\
- mfspr r11,SPRN_CSRR1; /* check whether user or kernel */\
+ mfspr r11,exc_level_srr1; /* check whether user or kernel */\
andi. r11,r11,MSR_PR; \
mr r11,r8; \
- mfspr r8,CRIT_SPRG; \
+ mfspr r8,exc_level##_SPRG; \
beq 1f; \
/* COMING FROM USER MODE */ \
mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\
@@ -122,9 +117,9 @@
stw r12,_DEAR(r11); /* since they may have had stuff */\
mfspr r9,SPRN_ESR; /* in them at the point where the */\
stw r9,_ESR(r11); /* exception was taken */\
- mfspr r12,SPRN_CSRR0; \
+ mfspr r12,exc_level_srr0; \
stw r1,GPR1(r11); \
- mfspr r9,SPRN_CSRR1; \
+ mfspr r9,exc_level_srr1; \
stw r1,0(r11); \
mr r1,r11; \
rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
@@ -132,45 +127,12 @@
SAVE_4GPRS(3, r11); \
SAVE_2GPRS(7, r11)
-/*
- * Exception prolog for machine check exceptions. This is similar to
- * the critical exception prolog, except that machine check exceptions
- * have their stack.
- */
-#define MCHECK_EXCEPTION_PROLOG \
- mtspr MCHECK_SPRG,r8; \
- BOOKE_LOAD_MCHECK_STACK; /* r8 points to the mcheck stack */\
- stw r10,GPR10-INT_FRAME_SIZE(r8); \
- stw r11,GPR11-INT_FRAME_SIZE(r8); \
- mfcr r10; /* save CR in r10 for now */\
- mfspr r11,SPRN_MCSRR1; /* check whether user or kernel */\
- andi. r11,r11,MSR_PR; \
- mr r11,r8; \
- mfspr r8,MCHECK_SPRG; \
- beq 1f; \
- /* COMING FROM USER MODE */ \
- mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\
- lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
- addi r11,r11,THREAD_SIZE; \
-1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\
- stw r10,_CCR(r11); /* save various registers */\
- stw r12,GPR12(r11); \
- stw r9,GPR9(r11); \
- mflr r10; \
- stw r10,_LINK(r11); \
- mfspr r12,SPRN_DEAR; /* save DEAR and ESR in the frame */\
- stw r12,_DEAR(r11); /* since they may have had stuff */\
- mfspr r9,SPRN_ESR; /* in them at the point where the */\
- stw r9,_ESR(r11); /* exception was taken */\
- mfspr r12,SPRN_MCSRR0; \
- stw r1,GPR1(r11); \
- mfspr r9,SPRN_MCSRR1; \
- stw r1,0(r11); \
- mr r1,r11; \
- rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\
- stw r0,GPR0(r11); \
- SAVE_4GPRS(3, r11); \
- SAVE_2GPRS(7, r11)
+#define CRITICAL_EXCEPTION_PROLOG \
+ EXC_LEVEL_EXCEPTION_PROLOG(CRIT, SPRN_CSRR0, SPRN_CSRR1)
+#define DEBUG_EXCEPTION_PROLOG \
+ EXC_LEVEL_EXCEPTION_PROLOG(DEBUG, SPRN_DSRR0, SPRN_DSRR1)
+#define MCHECK_EXCEPTION_PROLOG \
+ EXC_LEVEL_EXCEPTION_PROLOG(MCHECK, SPRN_MCSRR0, SPRN_MCSRR1)
/*
* Exception vectors.
@@ -237,7 +199,6 @@ label:
EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \
ret_from_except)
-
/* Check for a single step debug exception while in an exception
* handler before state has been saved. This is to catch the case
* where an instruction that we are trying to single step causes
@@ -251,6 +212,60 @@ label:
* save (and later restore) the MSR via SPRN_CSRR1, which will still have
* the MSR_DE bit set.
*/
+#ifdef CONFIG_E200
+#define DEBUG_EXCEPTION \
+ START_EXCEPTION(Debug); \
+ DEBUG_EXCEPTION_PROLOG; \
+ \
+ /* \
+ * If there is a single step or branch-taken exception in an \
+ * exception entry sequence, it was probably meant to apply to \
+ * the code where the exception occurred (since exception entry \
+ * doesn't turn off DE automatically). We simulate the effect \
+ * of turning off DE on entry to an exception handler by turning \
+ * off DE in the CSRR1 value and clearing the debug status. \
+ */ \
+ mfspr r10,SPRN_DBSR; /* check single-step/branch taken */ \
+ andis. r10,r10,DBSR_IC@h; \
+ beq+ 2f; \
+ \
+ lis r10,KERNELBASE@h; /* check if exception in vectors */ \
+ ori r10,r10,KERNELBASE@l; \
+ cmplw r12,r10; \
+ blt+ 2f; /* addr below exception vectors */ \
+ \
+ lis r10,Debug@h; \
+ ori r10,r10,Debug@l; \
+ cmplw r12,r10; \
+ bgt+ 2f; /* addr above exception vectors */ \
+ \
+ /* here it looks like we got an inappropriate debug exception. */ \
+1: rlwinm r9,r9,0,~MSR_DE; /* clear DE in the CDRR1 value */ \
+ lis r10,DBSR_IC@h; /* clear the IC event */ \
+ mtspr SPRN_DBSR,r10; \
+ /* restore state and get out */ \
+ lwz r10,_CCR(r11); \
+ lwz r0,GPR0(r11); \
+ lwz r1,GPR1(r11); \
+ mtcrf 0x80,r10; \
+ mtspr SPRN_DSRR0,r12; \
+ mtspr SPRN_DSRR1,r9; \
+ lwz r9,GPR9(r11); \
+ lwz r12,GPR12(r11); \
+ mtspr DEBUG_SPRG,r8; \
+ BOOKE_LOAD_EXC_LEVEL_STACK(DEBUG); /* r8 points to the debug stack */ \
+ lwz r10,GPR10-INT_FRAME_SIZE(r8); \
+ lwz r11,GPR11-INT_FRAME_SIZE(r8); \
+ mfspr r8,DEBUG_SPRG; \
+ \
+ RFDI; \
+ b .; \
+ \
+ /* continue normal handling for a critical exception... */ \
+2: mfspr r4,SPRN_DBSR; \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, debug_transfer_to_handler, ret_from_debug_exc)
+#else
#define DEBUG_EXCEPTION \
START_EXCEPTION(Debug); \
CRITICAL_EXCEPTION_PROLOG; \
@@ -291,7 +306,7 @@ label:
lwz r9,GPR9(r11); \
lwz r12,GPR12(r11); \
mtspr CRIT_SPRG,r8; \
- BOOKE_LOAD_CRIT_STACK; /* r8 points to the crit stack */ \
+ BOOKE_LOAD_EXC_LEVEL_STACK(CRIT); /* r8 points to the debug stack */ \
lwz r10,GPR10-INT_FRAME_SIZE(r8); \
lwz r11,GPR11-INT_FRAME_SIZE(r8); \
mfspr r8,CRIT_SPRG; \
@@ -303,6 +318,7 @@ label:
2: mfspr r4,SPRN_DBSR; \
addi r3,r1,STACK_FRAME_OVERHEAD; \
EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, crit_transfer_to_handler, ret_from_crit_exc)
+#endif
#define INSTRUCTION_STORAGE_EXCEPTION \
START_EXCEPTION(InstructionStorage) \
diff --git a/arch/ppc/kernel/head_fsl_booke.S b/arch/ppc/kernel/head_fsl_booke.S
index f22ddce3613..eb804b7a3cb 100644
--- a/arch/ppc/kernel/head_fsl_booke.S
+++ b/arch/ppc/kernel/head_fsl_booke.S
@@ -102,6 +102,7 @@ invstr: mflr r6 /* Make it accessible */
or r7,r7,r4
mtspr SPRN_MAS6,r7
tlbsx 0,r6 /* search MSR[IS], SPID=PID0 */
+#ifndef CONFIG_E200
mfspr r7,SPRN_MAS1
andis. r7,r7,MAS1_VALID@h
bne match_TLB
@@ -118,6 +119,7 @@ invstr: mflr r6 /* Make it accessible */
or r7,r7,r4
mtspr SPRN_MAS6,r7
tlbsx 0,r6 /* Fall through, we had to match */
+#endif
match_TLB:
mfspr r7,SPRN_MAS0
rlwinm r3,r7,16,20,31 /* Extract MAS0(Entry) */
@@ -196,8 +198,10 @@ skpinv: addi r6,r6,1 /* Increment */
/* 4. Clear out PIDs & Search info */
li r6,0
mtspr SPRN_PID0,r6
+#ifndef CONFIG_E200
mtspr SPRN_PID1,r6
mtspr SPRN_PID2,r6
+#endif
mtspr SPRN_MAS6,r6
/* 5. Invalidate mapping we started in */
@@ -232,7 +236,8 @@ skpinv: addi r6,r6,1 /* Increment */
tlbwe
/* 7. Jump to KERNELBASE mapping */
- li r7,0
+ lis r7,MSR_KERNEL@h
+ ori r7,r7,MSR_KERNEL@l
bl 1f /* Find our address */
1: mflr r9
rlwimi r6,r9,0,20,31
@@ -276,7 +281,9 @@ skpinv: addi r6,r6,1 /* Increment */
SET_IVOR(32, SPEUnavailable);
SET_IVOR(33, SPEFloatingPointData);
SET_IVOR(34, SPEFloatingPointRound);
+#ifndef CONFIG_E200
SET_IVOR(35, PerformanceMonitor);
+#endif
/* Establish the interrupt vector base */
lis r4,interrupt_base@h /* IVPR only uses the high 16-bits */
@@ -284,6 +291,9 @@ skpinv: addi r6,r6,1 /* Increment */
/* Setup the defaults for TLB entries */
li r2,(MAS4_TSIZED(BOOKE_PAGESZ_4K))@l
+#ifdef CONFIG_E200
+ oris r2,r2,MAS4_TLBSELD(1)@h
+#endif
mtspr SPRN_MAS4, r2
#if 0
@@ -292,6 +302,24 @@ skpinv: addi r6,r6,1 /* Increment */
oris r2,r2,HID0_DOZE@h
mtspr SPRN_HID0, r2
#endif
+#ifdef CONFIG_E200
+ /* enable dedicated debug exception handling resources (Debug APU) */
+ mfspr r2,SPRN_HID0
+ ori r2,r2,HID0_DAPUEN@l
+ mtspr SPRN_HID0,r2
+#endif
+
+#if !defined(CONFIG_BDI_SWITCH)
+ /*
+ * The Abatron BDI JTAG debugger does not tolerate others
+ * mucking with the debug registers.
+ */
+ lis r2,DBCR0_IDM@h
+ mtspr SPRN_DBCR0,r2
+ /* clear any residual debug events */
+ li r2,-1
+ mtspr SPRN_DBSR,r2
+#endif
/*
* This is where the main kernel code starts.
@@ -401,7 +429,12 @@ interrupt_base:
CRITICAL_EXCEPTION(0x0100, CriticalInput, UnknownException)
/* Machine Check Interrupt */
+#ifdef CONFIG_E200
+ /* no RFMCI, MCSRRs on E200 */
+ CRITICAL_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
+#else
MCHECK_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
+#endif
/* Data Storage Interrupt */
START_EXCEPTION(DataStorage)
@@ -507,8 +540,13 @@ interrupt_base:
#ifdef CONFIG_PPC_FPU
FP_UNAVAILABLE_EXCEPTION
#else
+#ifdef CONFIG_E200
+ /* E200 treats 'normal' floating point instructions as FP Unavail exception */
+ EXCEPTION(0x0800, FloatingPointUnavailable, ProgramCheckException, EXC_XFER_EE)
+#else
EXCEPTION(0x0800, FloatingPointUnavailable, UnknownException, EXC_XFER_EE)
#endif
+#endif
/* System Call Interrupt */
START_EXCEPTION(SystemCall)
@@ -678,6 +716,7 @@ interrupt_base:
/*
* Local functions
*/
+
/*
* Data TLB exceptions will bail out to this point
* if they can't resolve the lightweight TLB fault.
@@ -748,6 +787,31 @@ END_FTR_SECTION_IFSET(CPU_FTR_BIG_PHYS)
2: rlwimi r11, r12, 0, 20, 31 /* Extract RPN from PTE and merge with perms */
mtspr SPRN_MAS3, r11
#endif
+#ifdef CONFIG_E200
+ /* Round robin TLB1 entries assignment */
+ mfspr r12, SPRN_MAS0
+
+ /* Extract TLB1CFG(NENTRY) */
+ mfspr r11, SPRN_TLB1CFG
+ andi. r11, r11, 0xfff
+
+ /* Extract MAS0(NV) */
+ andi. r13, r12, 0xfff
+ addi r13, r13, 1
+ cmpw 0, r13, r11
+ addi r12, r12, 1
+
+ /* check if we need to wrap */
+ blt 7f
+
+ /* wrap back to first free tlbcam entry */
+ lis r13, tlbcam_index@ha
+ lwz r13, tlbcam_index@l(r13)
+ rlwimi r12, r13, 0, 20, 31
+7:
+ mtspr SPRN_MAS0,r12
+#endif /* CONFIG_E200 */
+
tlbwe
/* Done...restore registers and get out of here. */
diff --git a/arch/ppc/kernel/machine_kexec.c b/arch/ppc/kernel/machine_kexec.c
new file mode 100644
index 00000000000..84d65a87191
--- /dev/null
+++ b/arch/ppc/kernel/machine_kexec.c
@@ -0,0 +1,118 @@
+/*
+ * machine_kexec.c - handle transition of Linux booting another kernel
+ * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
+ *
+ * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/mm.h>
+#include <linux/kexec.h>
+#include <linux/delay.h>
+#include <linux/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/hw_irq.h>
+#include <asm/cacheflush.h>
+#include <asm/machdep.h>
+
+typedef NORET_TYPE void (*relocate_new_kernel_t)(
+ unsigned long indirection_page,
+ unsigned long reboot_code_buffer,
+ unsigned long start_address) ATTRIB_NORET;
+
+const extern unsigned char relocate_new_kernel[];
+const extern unsigned int relocate_new_kernel_size;
+
+void machine_shutdown(void)
+{
+ if (ppc_md.machine_shutdown)
+ ppc_md.machine_shutdown();
+}
+
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+ if (ppc_md.machine_crash_shutdown)
+ ppc_md.machine_crash_shutdown();
+}
+
+/*
+ * Do what every setup is needed on image and the
+ * reboot code buffer to allow us to avoid allocations
+ * later.
+ */
+int machine_kexec_prepare(struct kimage *image)
+{
+ if (ppc_md.machine_kexec_prepare)
+ return ppc_md.machine_kexec_prepare(image);
+ /*
+ * Fail if platform doesn't provide its own machine_kexec_prepare
+ * implementation.
+ */
+ return -ENOSYS;
+}
+
+void machine_kexec_cleanup(struct kimage *image)
+{
+ if (ppc_md.machine_kexec_cleanup)
+ ppc_md.machine_kexec_cleanup(image);
+}
+
+/*
+ * Do not allocate memory (or fail in any way) in machine_kexec().
+ * We are past the point of no return, committed to rebooting now.
+ */
+NORET_TYPE void machine_kexec(struct kimage *image)
+{
+ if (ppc_md.machine_kexec)
+ ppc_md.machine_kexec(image);
+ else {
+ /*
+ * Fall back to normal restart if platform doesn't provide
+ * its own kexec function, and user insist to kexec...
+ */
+ machine_restart(NULL);
+ }
+ for(;;);
+}
+
+/*
+ * This is a generic machine_kexec function suitable at least for
+ * non-OpenFirmware embedded platforms.
+ * It merely copies the image relocation code to the control page and
+ * jumps to it.
+ * A platform specific function may just call this one.
+ */
+void machine_kexec_simple(struct kimage *image)
+{
+ unsigned long page_list;
+ unsigned long reboot_code_buffer, reboot_code_buffer_phys;
+ relocate_new_kernel_t rnk;
+
+ /* Interrupts aren't acceptable while we reboot */
+ local_irq_disable();
+
+ page_list = image->head;
+
+ /* we need both effective and real address here */
+ reboot_code_buffer =
+ (unsigned long)page_address(image->control_code_page);
+ reboot_code_buffer_phys = virt_to_phys((void *)reboot_code_buffer);
+
+ /* copy our kernel relocation code to the control code page */
+ memcpy((void *)reboot_code_buffer, relocate_new_kernel,
+ relocate_new_kernel_size);
+
+ flush_icache_range(reboot_code_buffer,
+ reboot_code_buffer + KEXEC_CONTROL_CODE_SIZE);
+ printk(KERN_INFO "Bye!\n");
+
+ /* now call it */
+ rnk = (relocate_new_kernel_t) reboot_code_buffer;
+ (*rnk)(page_list, reboot_code_buffer_phys, image->start);
+}
+
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index e4f1615ec13..b6a63a49a23 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -593,6 +593,14 @@ _GLOBAL(flush_instruction_cache)
iccci 0,r3
#endif
#elif CONFIG_FSL_BOOKE
+BEGIN_FTR_SECTION
+ mfspr r3,SPRN_L1CSR0
+ ori r3,r3,L1CSR0_CFI|L1CSR0_CLFC
+ /* msync; isync recommended here */
+ mtspr SPRN_L1CSR0,r3
+ isync
+ blr
+END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
mfspr r3,SPRN_L1CSR1
ori r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR
mtspr SPRN_L1CSR1,r3
@@ -619,7 +627,7 @@ _GLOBAL(flush_instruction_cache)
_GLOBAL(flush_icache_range)
BEGIN_FTR_SECTION
blr /* for 601, do nothing */
-END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE)
+END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
li r5,L1_CACHE_LINE_SIZE-1
andc r3,r3,r5
subf r4,r3,r4
@@ -736,7 +744,7 @@ _GLOBAL(flush_dcache_all)
_GLOBAL(__flush_dcache_icache)
BEGIN_FTR_SECTION
blr /* for 601, do nothing */
-END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE)
+END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
rlwinm r3,r3,0,0,19 /* Get page base address */
li r4,4096/L1_CACHE_LINE_SIZE /* Number of lines in a page */
mtctr r4
@@ -764,7 +772,7 @@ END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE)
_GLOBAL(__flush_dcache_icache_phys)
BEGIN_FTR_SECTION
blr /* for 601, do nothing */
-END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE)
+END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
mfmsr r10
rlwinm r0,r10,0,28,26 /* clear DR */
mtmsr r0
@@ -1436,7 +1444,7 @@ _GLOBAL(sys_call_table)
.long sys_mq_timedreceive /* 265 */
.long sys_mq_notify
.long sys_mq_getsetattr
- .long sys_ni_syscall /* 268 reserved for sys_kexec_load */
+ .long sys_kexec_load
.long sys_add_key
.long sys_request_key /* 270 */
.long sys_keyctl
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index 47a15306823..6d7b92d7245 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -1003,7 +1003,7 @@ pci_create_OF_bus_map(void)
}
}
-static ssize_t pci_show_devspec(struct device *dev, char *buf)
+static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pci_dev *pdev;
struct device_node *np;
diff --git a/arch/ppc/kernel/perfmon.c b/arch/ppc/kernel/perfmon.c
index 918f6b252e4..fa1dad96b83 100644
--- a/arch/ppc/kernel/perfmon.c
+++ b/arch/ppc/kernel/perfmon.c
@@ -36,7 +36,7 @@
/* A lock to regulate grabbing the interrupt */
DEFINE_SPINLOCK(perfmon_lock);
-#ifdef CONFIG_FSL_BOOKE
+#if defined (CONFIG_FSL_BOOKE) && !defined (CONFIG_E200)
static void dummy_perf(struct pt_regs *regs)
{
unsigned int pmgc0 = mfpmr(PMRN_PMGC0);
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 2ccb58fe4fc..d59ad07de8e 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -55,7 +55,6 @@
#define EXPORT_SYMTAB_STROPS
extern void transfer_to_handler(void);
-extern void do_syscall_trace(void);
extern void do_IRQ(struct pt_regs *regs);
extern void MachineCheckException(struct pt_regs *regs);
extern void AlignmentException(struct pt_regs *regs);
@@ -74,7 +73,6 @@ extern unsigned long mm_ptov (unsigned long paddr);
EXPORT_SYMBOL(clear_pages);
EXPORT_SYMBOL(clear_user_page);
EXPORT_SYMBOL(do_signal);
-EXPORT_SYMBOL(do_syscall_trace);
EXPORT_SYMBOL(transfer_to_handler);
EXPORT_SYMBOL(do_IRQ);
EXPORT_SYMBOL(MachineCheckException);
diff --git a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c
index 59d59a8dc24..e7aee4108de 100644
--- a/arch/ppc/kernel/ptrace.c
+++ b/arch/ppc/kernel/ptrace.c
@@ -27,6 +27,9 @@
#include <linux/user.h>
#include <linux/security.h>
#include <linux/signal.h>
+#include <linux/seccomp.h>
+#include <linux/audit.h>
+#include <linux/module.h>
#include <asm/uaccess.h>
#include <asm/page.h>
@@ -455,11 +458,10 @@ out:
return ret;
}
-void do_syscall_trace(void)
+static void do_syscall_trace(void)
{
- if (!test_thread_flag(TIF_SYSCALL_TRACE)
- || !(current->ptrace & PT_PTRACED))
- return;
+ /* the 0x80 provides a way for the tracing parent to distinguish
+ between a syscall stop and SIGTRAP delivery */
ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
? 0x80 : 0));
@@ -473,3 +475,33 @@ void do_syscall_trace(void)
current->exit_code = 0;
}
}
+
+void do_syscall_trace_enter(struct pt_regs *regs)
+{
+ if (test_thread_flag(TIF_SYSCALL_TRACE)
+ && (current->ptrace & PT_PTRACED))
+ do_syscall_trace();
+
+ if (unlikely(current->audit_context))
+ audit_syscall_entry(current, AUDIT_ARCH_PPC,
+ regs->gpr[0],
+ regs->gpr[3], regs->gpr[4],
+ regs->gpr[5], regs->gpr[6]);
+}
+
+void do_syscall_trace_leave(struct pt_regs *regs)
+{
+ secure_computing(regs->gpr[0]);
+
+ if (unlikely(current->audit_context))
+ audit_syscall_exit(current,
+ (regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
+ regs->result);
+
+ if ((test_thread_flag(TIF_SYSCALL_TRACE))
+ && (current->ptrace & PT_PTRACED))
+ do_syscall_trace();
+}
+
+EXPORT_SYMBOL(do_syscall_trace_enter);
+EXPORT_SYMBOL(do_syscall_trace_leave);
diff --git a/arch/ppc/kernel/relocate_kernel.S b/arch/ppc/kernel/relocate_kernel.S
new file mode 100644
index 00000000000..7ff69c4af92
--- /dev/null
+++ b/arch/ppc/kernel/relocate_kernel.S
@@ -0,0 +1,123 @@
+/*
+ * relocate_kernel.S - put the kernel image in place to boot
+ * Copyright (C) 2002-2003 Eric Biederman <ebiederm@xmission.com>
+ *
+ * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <asm/reg.h>
+#include <asm/ppc_asm.h>
+#include <asm/processor.h>
+
+#include <asm/kexec.h>
+
+#define PAGE_SIZE 4096 /* must be same value as in <asm/page.h> */
+
+ /*
+ * Must be relocatable PIC code callable as a C function.
+ */
+ .globl relocate_new_kernel
+relocate_new_kernel:
+ /* r3 = page_list */
+ /* r4 = reboot_code_buffer */
+ /* r5 = start_address */
+
+ li r0, 0
+
+ /*
+ * Set Machine Status Register to a known status,
+ * switch the MMU off and jump to 1: in a single step.
+ */
+
+ mr r8, r0
+ ori r8, r8, MSR_RI|MSR_ME
+ mtspr SRR1, r8
+ addi r8, r4, 1f - relocate_new_kernel
+ mtspr SRR0, r8
+ sync
+ rfi
+
+1:
+ /* from this point address translation is turned off */
+ /* and interrupts are disabled */
+
+ /* set a new stack at the bottom of our page... */
+ /* (not really needed now) */
+ addi r1, r4, KEXEC_CONTROL_CODE_SIZE - 8 /* for LR Save+Back Chain */
+ stw r0, 0(r1)
+
+ /* Do the copies */
+ li r6, 0 /* checksum */
+ mr r0, r3
+ b 1f
+
+0: /* top, read another word for the indirection page */
+ lwzu r0, 4(r3)
+
+1:
+ /* is it a destination page? (r8) */
+ rlwinm. r7, r0, 0, 31, 31 /* IND_DESTINATION (1<<0) */
+ beq 2f
+
+ rlwinm r8, r0, 0, 0, 19 /* clear kexec flags, page align */
+ b 0b
+
+2: /* is it an indirection page? (r3) */
+ rlwinm. r7, r0, 0, 30, 30 /* IND_INDIRECTION (1<<1) */
+ beq 2f
+
+ rlwinm r3, r0, 0, 0, 19 /* clear kexec flags, page align */
+ subi r3, r3, 4
+ b 0b
+
+2: /* are we done? */
+ rlwinm. r7, r0, 0, 29, 29 /* IND_DONE (1<<2) */
+ beq 2f
+ b 3f
+
+2: /* is it a source page? (r9) */
+ rlwinm. r7, r0, 0, 28, 28 /* IND_SOURCE (1<<3) */
+ beq 0b
+
+ rlwinm r9, r0, 0, 0, 19 /* clear kexec flags, page align */
+
+ li r7, PAGE_SIZE / 4
+ mtctr r7
+ subi r9, r9, 4
+ subi r8, r8, 4
+9:
+ lwzu r0, 4(r9) /* do the copy */
+ xor r6, r6, r0
+ stwu r0, 4(r8)
+ dcbst 0, r8
+ sync
+ icbi 0, r8
+ bdnz 9b
+
+ addi r9, r9, 4
+ addi r8, r8, 4
+ b 0b
+
+3:
+
+ /* To be certain of avoiding problems with self-modifying code
+ * execute a serializing instruction here.
+ */
+ isync
+ sync
+
+ /* jump to the entry point, usually the setup routine */
+ mtlr r5
+ blrl
+
+1: b 1b
+
+relocate_new_kernel_end:
+
+ .globl relocate_new_kernel_size
+relocate_new_kernel_size:
+ .long relocate_new_kernel_end - relocate_new_kernel
+
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 5dfb42f1a15..c42f7532693 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -41,7 +41,7 @@
#include <asm/xmon.h>
#include <asm/ocp.h>
-#if defined(CONFIG_85xx) || defined(CONFIG_83xx)
+#if defined(CONFIG_85xx) || defined(CONFIG_83xx) || defined(CONFIG_MPC10X_BRIDGE)
#include <asm/ppc_sys.h>
#endif
@@ -61,8 +61,6 @@ extern void power4_idle(void);
extern boot_infos_t *boot_infos;
struct ide_machdep_calls ppc_ide_md;
-char *sysmap;
-unsigned long sysmap_size;
/* Used with the BI_MEMSIZE bootinfo parameter to store the memory
size value reported by the boot loader. */
@@ -249,7 +247,7 @@ int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "bogomips\t: %lu.%02lu\n",
lpj / (500000/HZ), (lpj / (5000/HZ)) % 100);
-#if defined(CONFIG_85xx) || defined(CONFIG_83xx)
+#if defined(CONFIG_85xx) || defined(CONFIG_83xx) || defined(CONFIG_MPC10X_BRIDGE)
if (cur_ppc_sys_spec->ppc_sys_name)
seq_printf(m, "chipset\t\t: %s\n",
cur_ppc_sys_spec->ppc_sys_name);
@@ -499,7 +497,7 @@ static int __init set_preferred_console(void)
{
struct device_node *prom_stdout;
char *name;
- int offset;
+ int offset = 0;
if (of_stdout_device == NULL)
return -ENODEV;
@@ -578,11 +576,6 @@ void parse_bootinfo(struct bi_record *rec)
case BI_CMD_LINE:
strlcpy(cmd_line, (void *)data, sizeof(cmd_line));
break;
- case BI_SYSMAP:
- sysmap = (char *)((data[0] >= (KERNELBASE)) ? data[0] :
- (data[0]+KERNELBASE));
- sysmap_size = data[1];
- break;
#ifdef CONFIG_BLK_DEV_INITRD
case BI_INITRD:
initrd_start = data[0] + KERNELBASE;
@@ -753,6 +746,8 @@ void __init setup_arch(char **cmdline_p)
strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
*cmdline_p = cmd_line;
+ parse_early_param();
+
/* set up the bootmem stuff with available memory */
do_init_bootmem();
if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab);
diff --git a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c
index 7c8437da09d..8aaeb6f4e75 100644
--- a/arch/ppc/kernel/signal.c
+++ b/arch/ppc/kernel/signal.c
@@ -705,8 +705,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
unsigned long frame, newsp;
int signr, ret;
- if (current->flags & PF_FREEZE) {
- refrigerator(PF_FREEZE);
+ if (try_to_freeze()) {
signr = 0;
if (!signal_pending(current))
goto no_signal;
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
index f8e7e324a17..9e6ae569665 100644
--- a/arch/ppc/kernel/traps.c
+++ b/arch/ppc/kernel/traps.c
@@ -81,8 +81,10 @@ void die(const char * str, struct pt_regs * fp, long err)
console_verbose();
spin_lock_irq(&die_lock);
#ifdef CONFIG_PMAC_BACKLIGHT
- set_backlight_enable(1);
- set_backlight_level(BACKLIGHT_MAX);
+ if (_machine == _MACH_Pmac) {
+ set_backlight_enable(1);
+ set_backlight_level(BACKLIGHT_MAX);
+ }
#endif
printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter);
#ifdef CONFIG_PREEMPT
@@ -171,13 +173,13 @@ static inline int check_io_access(struct pt_regs *regs)
/* On 4xx, the reason for the machine check or program exception
is in the ESR. */
#define get_reason(regs) ((regs)->dsisr)
-#ifndef CONFIG_E500
+#ifndef CONFIG_FSL_BOOKE
#define get_mc_reason(regs) ((regs)->dsisr)
#else
#define get_mc_reason(regs) (mfspr(SPRN_MCSR))
#endif
#define REASON_FP ESR_FP
-#define REASON_ILLEGAL ESR_PIL
+#define REASON_ILLEGAL (ESR_PIL | ESR_PUO)
#define REASON_PRIVILEGED ESR_PPR
#define REASON_TRAP ESR_PTR
@@ -300,7 +302,25 @@ void MachineCheckException(struct pt_regs *regs)
printk("Bus - Instruction Parity Error\n");
if (reason & MCSR_BUS_RPERR)
printk("Bus - Read Parity Error\n");
-#else /* !CONFIG_4xx && !CONFIG_E500 */
+#elif defined (CONFIG_E200)
+ printk("Machine check in kernel mode.\n");
+ printk("Caused by (from MCSR=%lx): ", reason);
+
+ if (reason & MCSR_MCP)
+ printk("Machine Check Signal\n");
+ if (reason & MCSR_CP_PERR)
+ printk("Cache Push Parity Error\n");
+ if (reason & MCSR_CPERR)
+ printk("Cache Parity Error\n");
+ if (reason & MCSR_EXCP_ERR)
+ printk("ISI, ITLB, or Bus Error on first instruction fetch for an exception handler\n");
+ if (reason & MCSR_BUS_IRERR)
+ printk("Bus - Read Bus Error on instruction fetch\n");
+ if (reason & MCSR_BUS_DRERR)
+ printk("Bus - Read Bus Error on data load\n");
+ if (reason & MCSR_BUS_WRERR)
+ printk("Bus - Write Bus Error on buffered store or cache line push\n");
+#else /* !CONFIG_4xx && !CONFIG_E500 && !CONFIG_E200 */
printk("Machine check in kernel mode.\n");
printk("Caused by (from SRR1=%lx): ", reason);
switch (reason & 0x601F0000) {
@@ -408,12 +428,7 @@ static int emulate_string_inst(struct pt_regs *regs, u32 instword)
/* Early out if we are an invalid form of lswx */
if ((instword & INST_STRING_MASK) == INST_LSWX)
- if ((rA >= rT) || (NB_RB >= rT) || (rT == rA) || (rT == NB_RB))
- return -EINVAL;
-
- /* Early out if we are an invalid form of lswi */
- if ((instword & INST_STRING_MASK) == INST_LSWI)
- if ((rA >= rT) || (rT == rA))
+ if ((rT == rA) || (rT == NB_RB))
return -EINVAL;
EA = (rA == 0) ? 0 : regs->gpr[rA];
diff --git a/arch/ppc/lib/locks.c b/arch/ppc/lib/locks.c
index 694163d696d..c450dc4b766 100644
--- a/arch/ppc/lib/locks.c
+++ b/arch/ppc/lib/locks.c
@@ -130,7 +130,7 @@ void _raw_read_lock(rwlock_t *rw)
while (!read_can_lock(rw)) {
if (--stuck == 0) {
printk("_read_lock(%p) CPU#%d lock %d\n",
- rw, _smp_processor_id(), rw->lock);
+ rw, raw_smp_processor_id(), rw->lock);
stuck = INIT_STUCK;
}
}
@@ -158,7 +158,7 @@ void _raw_write_lock(rwlock_t *rw)
while (!write_can_lock(rw)) {
if (--stuck == 0) {
printk("write_lock(%p) CPU#%d lock %d)\n",
- rw, _smp_processor_id(), rw->lock);
+ rw, raw_smp_processor_id(), rw->lock);
stuck = INIT_STUCK;
}
}
diff --git a/arch/ppc/lib/string.S b/arch/ppc/lib/string.S
index 8d08a2eb225..36c9b97fd92 100644
--- a/arch/ppc/lib/string.S
+++ b/arch/ppc/lib/string.S
@@ -446,6 +446,7 @@ _GLOBAL(__copy_tofrom_user)
#ifdef CONFIG_8xx
/* Don't use prefetch on 8xx */
mtctr r0
+ li r0,0
53: COPY_16_BYTES_WITHEX(0)
bdnz 53b
@@ -564,7 +565,9 @@ _GLOBAL(__copy_tofrom_user)
/* or write fault in cacheline loop */
105: li r9,1
92: li r3,LG_CACHELINE_BYTES
- b 99f
+ mfctr r8
+ add r0,r0,r8
+ b 106f
/* read fault in final word loop */
108: li r9,0
b 93f
@@ -585,7 +588,7 @@ _GLOBAL(__copy_tofrom_user)
* r5 + (ctr << r3), and r9 is 0 for read or 1 for write.
*/
99: mfctr r0
- slw r3,r0,r3
+106: slw r3,r0,r3
add. r3,r3,r5
beq 120f /* shouldn't happen */
cmpwi 0,r9,0
diff --git a/arch/ppc/mm/44x_mmu.c b/arch/ppc/mm/44x_mmu.c
index 72f7c0d1c0e..3d79ce281b6 100644
--- a/arch/ppc/mm/44x_mmu.c
+++ b/arch/ppc/mm/44x_mmu.c
@@ -39,7 +39,6 @@
#include <linux/vmalloc.h>
#include <linux/init.h>
#include <linux/delay.h>
-#include <linux/bootmem.h>
#include <linux/highmem.h>
#include <asm/pgalloc.h>
diff --git a/arch/ppc/mm/4xx_mmu.c b/arch/ppc/mm/4xx_mmu.c
index a7f61614038..b7bcbc232f3 100644
--- a/arch/ppc/mm/4xx_mmu.c
+++ b/arch/ppc/mm/4xx_mmu.c
@@ -36,7 +36,6 @@
#include <linux/vmalloc.h>
#include <linux/init.h>
#include <linux/delay.h>
-#include <linux/bootmem.h>
#include <linux/highmem.h>
#include <asm/pgalloc.h>
diff --git a/arch/ppc/mm/fsl_booke_mmu.c b/arch/ppc/mm/fsl_booke_mmu.c
index 36233bdcdf8..af9ca0eb6d5 100644
--- a/arch/ppc/mm/fsl_booke_mmu.c
+++ b/arch/ppc/mm/fsl_booke_mmu.c
@@ -41,7 +41,6 @@
#include <linux/vmalloc.h>
#include <linux/init.h>
#include <linux/delay.h>
-#include <linux/bootmem.h>
#include <linux/highmem.h>
#include <asm/pgalloc.h>
@@ -64,6 +63,8 @@ extern unsigned long total_lowmem;
extern unsigned long __max_low_memory;
#define MAX_LOW_MEM CONFIG_LOWMEM_SIZE
+#define NUM_TLBCAMS (16)
+
struct tlbcam {
u32 MAS0;
u32 MAS1;
@@ -124,7 +125,7 @@ void settlbcam(int index, unsigned long virt, phys_addr_t phys,
flags |= _PAGE_COHERENT;
#endif
- TLBCAM[index].MAS0 = MAS0_TLBSEL(1) | MAS0_ESEL(index);
+ TLBCAM[index].MAS0 = MAS0_TLBSEL(1) | MAS0_ESEL(index) | MAS0_NV(index+1);
TLBCAM[index].MAS1 = MAS1_VALID | MAS1_IPROT | MAS1_TSIZE(tsize) | MAS1_TID(pid);
TLBCAM[index].MAS2 = virt & PAGE_MASK;
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index be02a7fec2b..334ef4150d9 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -96,9 +96,6 @@ extern struct task_struct *current_set[NR_CPUS];
char *klimit = _end;
struct mem_pieces phys_avail;
-extern char *sysmap;
-extern unsigned long sysmap_size;
-
/*
* this tells the system to map all of ram with the segregs
* (i.e. page tables) instead of the bats.
@@ -179,6 +176,7 @@ void free_initmem(void)
if (!have_of)
FREESEC(openfirmware);
printk("\n");
+ ppc_md.progress = NULL;
#undef FREESEC
}
@@ -441,12 +439,6 @@ void __init mem_init(void)
if (agp_special_page)
SetPageReserved(virt_to_page(agp_special_page));
#endif
- if ( sysmap )
- for (addr = (unsigned long)sysmap;
- addr < PAGE_ALIGN((unsigned long)sysmap+sysmap_size) ;
- addr += PAGE_SIZE)
- SetPageReserved(virt_to_page(addr));
-
for (addr = PAGE_OFFSET; addr < (unsigned long)high_memory;
addr += PAGE_SIZE) {
if (!PageReserved(virt_to_page(addr)))
@@ -468,7 +460,6 @@ void __init mem_init(void)
struct page *page = mem_map + pfn;
ClearPageReserved(page);
- set_bit(PG_highmem, &page->flags);
set_page_count(page, 1);
__free_page(page);
totalhigh_pages++;
@@ -482,9 +473,7 @@ void __init mem_init(void)
codepages<< (PAGE_SHIFT-10), datapages<< (PAGE_SHIFT-10),
initpages<< (PAGE_SHIFT-10),
(unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));
- if (sysmap)
- printk("System.map loaded at 0x%08x for debugger, size: %ld bytes\n",
- (unsigned int)sysmap, sysmap_size);
+
#ifdef CONFIG_PPC_PMAC
if (agp_special_page)
printk(KERN_INFO "AGP special page: 0x%08lx\n", agp_special_page);
@@ -534,9 +523,6 @@ set_phys_avail(unsigned long total_memory)
if (rtas_data)
mem_pieces_remove(&phys_avail, rtas_data, rtas_size, 1);
#endif
- /* remove the sysmap pages from the available memory */
- if (sysmap)
- mem_pieces_remove(&phys_avail, __pa(sysmap), sysmap_size, 1);
#ifdef CONFIG_PPC_PMAC
/* Because of some uninorth weirdness, we need a page of
* memory as high as possible (it must be outside of the
diff --git a/arch/ppc/mm/mmu_decl.h b/arch/ppc/mm/mmu_decl.h
index ffcdb46997d..540f3292b22 100644
--- a/arch/ppc/mm/mmu_decl.h
+++ b/arch/ppc/mm/mmu_decl.h
@@ -43,6 +43,8 @@ extern int mem_init_done;
extern PTE *Hash, *Hash_end;
extern unsigned long Hash_size, Hash_mask;
+extern unsigned int num_tlbcam_entries;
+
/* ...and now those things that may be slightly different between processor
* architectures. -- Dan
*/
diff --git a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
index 5d2f3f66aef..81a3d7446d3 100644
--- a/arch/ppc/mm/pgtable.c
+++ b/arch/ppc/mm/pgtable.c
@@ -66,7 +66,6 @@ void setbat(int index, unsigned long virt, unsigned long phys,
#ifdef HAVE_TLBCAM
extern unsigned int tlbcam_index;
-extern unsigned int num_tlbcam_entries;
extern unsigned long v_mapped_by_tlbcam(unsigned long va);
extern unsigned long p_mapped_by_tlbcam(unsigned long pa);
#else /* !HAVE_TLBCAM */
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c
index b3b0f51979d..ddd04d4c1ea 100644
--- a/arch/ppc/platforms/83xx/mpc834x_sys.c
+++ b/arch/ppc/platforms/83xx/mpc834x_sys.c
@@ -41,7 +41,6 @@
#include <asm/time.h>
#include <asm/io.h>
#include <asm/machdep.h>
-#include <asm/prom.h>
#include <asm/ipic.h>
#include <asm/bootinfo.h>
#include <asm/pci-bridge.h>
@@ -95,20 +94,24 @@ mpc834x_sys_setup_arch(void)
/* setup the board related information for the enet controllers */
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC1);
- pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
- pdata->interruptPHY = MPC83xx_IRQ_EXT1;
- pdata->phyid = 0;
- /* fixup phy address */
- pdata->phy_reg_addr += binfo->bi_immr_base;
- memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+ if (pdata) {
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->interruptPHY = MPC83xx_IRQ_EXT1;
+ pdata->phyid = 0;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+ }
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC2);
- pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
- pdata->interruptPHY = MPC83xx_IRQ_EXT2;
- pdata->phyid = 1;
- /* fixup phy address */
- pdata->phy_reg_addr += binfo->bi_immr_base;
- memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+ if (pdata) {
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->interruptPHY = MPC83xx_IRQ_EXT2;
+ pdata->phyid = 1;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+ }
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start)
@@ -127,7 +130,6 @@ mpc834x_sys_map_io(void)
{
/* we steal the lowest ioremap addr for virt space */
io_block_mapping(VIRT_IMMRBAR, immrbar, 1024*1024, _PAGE_IO);
- io_block_mapping(BCSR_VIRT_ADDR, BCSR_PHYS_ADDR, BCSR_SIZE, _PAGE_IO);
}
int
@@ -187,6 +189,26 @@ mpc834x_sys_init_IRQ(void)
ipic_set_default_priority();
}
+#if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374)
+extern ulong ds1374_get_rtc_time(void);
+extern int ds1374_set_rtc_time(ulong);
+
+static int __init
+mpc834x_rtc_hookup(void)
+{
+ struct timespec tv;
+
+ ppc_md.get_rtc_time = ds1374_get_rtc_time;
+ ppc_md.set_rtc_time = ds1374_set_rtc_time;
+
+ tv.tv_nsec = 0;
+ tv.tv_sec = (ppc_md.get_rtc_time)();
+ do_settimeofday(&tv);
+
+ return 0;
+}
+late_initcall(mpc834x_rtc_hookup);
+#endif
static __inline__ void
mpc834x_sys_set_bat(void)
{
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.h b/arch/ppc/platforms/83xx/mpc834x_sys.h
index f4d055ae19c..a2f6e49d715 100644
--- a/arch/ppc/platforms/83xx/mpc834x_sys.h
+++ b/arch/ppc/platforms/83xx/mpc834x_sys.h
@@ -26,9 +26,14 @@
#define VIRT_IMMRBAR ((uint)0xfe000000)
#define BCSR_PHYS_ADDR ((uint)0xf8000000)
-#define BCSR_VIRT_ADDR ((uint)0xfe100000)
#define BCSR_SIZE ((uint)(32 * 1024))
+#define BCSR_MISC_REG2_OFF 0x07
+#define BCSR_MISC_REG2_PORESET 0x01
+
+#define BCSR_MISC_REG3_OFF 0x08
+#define BCSR_MISC_REG3_CNFLOCK 0x80
+
#ifdef CONFIG_PCI
/* PCI interrupt controller */
#define PIRQA MPC83xx_IRQ_IRQ4
diff --git a/arch/ppc/platforms/85xx/Kconfig b/arch/ppc/platforms/85xx/Kconfig
index ff92e38e7da..c5bc2821d99 100644
--- a/arch/ppc/platforms/85xx/Kconfig
+++ b/arch/ppc/platforms/85xx/Kconfig
@@ -21,6 +21,11 @@ config MPC8540_ADS
help
This option enables support for the MPC 8540 ADS evaluation board.
+config MPC8548_CDS
+ bool "Freescale MPC8548 CDS"
+ help
+ This option enablese support for the MPC8548 CDS evaluation board.
+
config MPC8555_CDS
bool "Freescale MPC8555 CDS"
help
@@ -53,6 +58,11 @@ config MPC8540
depends on MPC8540_ADS
default y
+config MPC8548
+ bool
+ depends on MPC8548_CDS
+ default y
+
config MPC8555
bool
depends on MPC8555_CDS
diff --git a/arch/ppc/platforms/85xx/Makefile b/arch/ppc/platforms/85xx/Makefile
index 854fbd298ba..efdf813108f 100644
--- a/arch/ppc/platforms/85xx/Makefile
+++ b/arch/ppc/platforms/85xx/Makefile
@@ -2,6 +2,7 @@
# Makefile for the PowerPC 85xx linux kernel.
#
obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads_common.o mpc8540_ads.o
+obj-$(CONFIG_MPC8548_CDS) += mpc85xx_cds_common.o
obj-$(CONFIG_MPC8555_CDS) += mpc85xx_cds_common.o
obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads_common.o mpc8560_ads.o
obj-$(CONFIG_SBC8560) += sbc85xx.o sbc8560.o
diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c
index 4d857d6d633..ddd2e9a5bb1 100644
--- a/arch/ppc/platforms/85xx/mpc8540_ads.c
+++ b/arch/ppc/platforms/85xx/mpc8540_ads.c
@@ -41,7 +41,6 @@
#include <asm/time.h>
#include <asm/io.h>
#include <asm/machdep.h>
-#include <asm/prom.h>
#include <asm/open_pic.h>
#include <asm/bootinfo.h>
#include <asm/pci-bridge.h>
@@ -88,33 +87,39 @@ mpc8540ads_setup_arch(void)
#ifdef CONFIG_SERIAL_TEXT_DEBUG
/* Invalidate the entry we stole earlier the serial ports
* should be properly mapped */
- invalidate_tlbcam_entry(NUM_TLBCAMS - 1);
+ invalidate_tlbcam_entry(num_tlbcam_entries - 1);
#endif
/* setup the board related information for the enet controllers */
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
- pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
- pdata->interruptPHY = MPC85xx_IRQ_EXT5;
- pdata->phyid = 0;
- /* fixup phy address */
- pdata->phy_reg_addr += binfo->bi_immr_base;
- memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+ if (pdata) {
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+ pdata->phyid = 0;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+ }
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
- pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
- pdata->interruptPHY = MPC85xx_IRQ_EXT5;
- pdata->phyid = 1;
- /* fixup phy address */
- pdata->phy_reg_addr += binfo->bi_immr_base;
- memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
-
- pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_FEC);
- pdata->board_flags = 0;
- pdata->interruptPHY = MPC85xx_IRQ_EXT5;
- pdata->phyid = 3;
- /* fixup phy address */
- pdata->phy_reg_addr += binfo->bi_immr_base;
- memcpy(pdata->mac_addr, binfo->bi_enet2addr, 6);
+ if (pdata) {
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+ pdata->phyid = 1;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+ }
+
+ if (pdata) {
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_FEC);
+ pdata->board_flags = 0;
+ pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+ pdata->phyid = 3;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enet2addr, 6);
+ }
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start)
@@ -150,7 +155,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
struct uart_port p;
/* Use the last TLB entry to map CCSRBAR to allow access to DUART regs */
- settlbcam(NUM_TLBCAMS - 1, binfo->bi_immr_base,
+ settlbcam(num_tlbcam_entries - 1, binfo->bi_immr_base,
binfo->bi_immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0);
memset(&p, 0, sizeof (p));
@@ -210,6 +215,9 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
ppc_md.progress = gen550_progress;
#endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
+#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_KGDB)
+ ppc_md.early_serial_map = mpc85xx_early_serial_map;
+#endif /* CONFIG_SERIAL_8250 && CONFIG_KGDB */
if (ppc_md.progress)
ppc_md.progress("mpc8540ads_init(): exit", 0);
diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c
index 761b8c7b25d..e18380258b6 100644
--- a/arch/ppc/platforms/85xx/mpc8560_ads.c
+++ b/arch/ppc/platforms/85xx/mpc8560_ads.c
@@ -41,7 +41,6 @@
#include <asm/time.h>
#include <asm/io.h>
#include <asm/machdep.h>
-#include <asm/prom.h>
#include <asm/open_pic.h>
#include <asm/bootinfo.h>
#include <asm/pci-bridge.h>
@@ -91,20 +90,24 @@ mpc8560ads_setup_arch(void)
/* setup the board related information for the enet controllers */
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
- pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
- pdata->interruptPHY = MPC85xx_IRQ_EXT5;
- pdata->phyid = 0;
- /* fixup phy address */
- pdata->phy_reg_addr += binfo->bi_immr_base;
- memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+ if (pdata) {
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+ pdata->phyid = 0;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+ }
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
- pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
- pdata->interruptPHY = MPC85xx_IRQ_EXT5;
- pdata->phyid = 1;
- /* fixup phy address */
- pdata->phy_reg_addr += binfo->bi_immr_base;
- memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+ if (pdata) {
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+ pdata->phyid = 1;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+ }
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start)
diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c
index ba9f9f562c4..18e952d1767 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c
+++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c
@@ -36,7 +36,6 @@
#include <asm/time.h>
#include <asm/io.h>
#include <asm/machdep.h>
-#include <asm/prom.h>
#include <asm/open_pic.h>
#include <asm/bootinfo.h>
#include <asm/pci-bridge.h>
@@ -59,40 +58,8 @@ extern unsigned long total_memory; /* in mm/init */
unsigned char __res[sizeof (bd_t)];
/* Internal interrupts are all Level Sensitive, and Positive Polarity */
-
static u_char mpc85xx_ads_openpic_initsenses[] __initdata = {
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 0: L2 Cache */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 1: ECM */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 2: DDR DRAM */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 3: LBIU */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 4: DMA 0 */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 5: DMA 1 */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 6: DMA 2 */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 7: DMA 3 */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 8: PCI/PCI-X */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 9: RIO Inbound Port Write Error */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 10: RIO Doorbell Inbound */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 11: RIO Outbound Message */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 12: RIO Inbound Message */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 13: TSEC 0 Transmit */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 14: TSEC 0 Receive */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 15: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 16: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 17: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 18: TSEC 0 Receive/Transmit Error */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 19: TSEC 1 Transmit */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 20: TSEC 1 Receive */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 21: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 22: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 23: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 24: TSEC 1 Receive/Transmit Error */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 25: Fast Ethernet */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 26: DUART */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 27: I2C */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 28: Performance Monitor */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 29: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 30: CPM */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 31: Unused */
+ MPC85XX_INTERNAL_IRQ_SENSES,
0x0, /* External 0: */
#if defined(CONFIG_PCI)
(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 1: PCI slot 0 */
@@ -159,7 +126,7 @@ mpc85xx_ads_init_IRQ(void)
/* Skip reserved space and internal sources */
openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200);
/* Map PIC IRQs 0-11 */
- openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000);
+ openpic_set_sources(48, 12, OpenPIC_Addr + 0x10000);
/* we let openpic interrupts starting from an offset, to
* leave space for cascading interrupts underneath.
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
index 6c020d67ad7..b52c4317fef 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
@@ -42,8 +42,8 @@
#include <asm/todc.h>
#include <asm/io.h>
#include <asm/machdep.h>
-#include <asm/prom.h>
#include <asm/open_pic.h>
+#include <asm/i8259.h>
#include <asm/bootinfo.h>
#include <asm/pci-bridge.h>
#include <asm/mpc85xx.h>
@@ -72,40 +72,8 @@ static int cds_pci_slot = 2;
static volatile u8 * cadmus;
/* Internal interrupts are all Level Sensitive, and Positive Polarity */
-
static u_char mpc85xx_cds_openpic_initsenses[] __initdata = {
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 0: L2 Cache */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 1: ECM */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 2: DDR DRAM */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 3: LBIU */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 4: DMA 0 */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 5: DMA 1 */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 6: DMA 2 */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 7: DMA 3 */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 8: PCI/PCI-X */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 9: RIO Inbound Port Write Error */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 10: RIO Doorbell Inbound */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 11: RIO Outbound Message */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 12: RIO Inbound Message */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 13: TSEC 0 Transmit */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 14: TSEC 0 Receive */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 15: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 16: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 17: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 18: TSEC 0 Receive/Transmit Error */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 19: TSEC 1 Transmit */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 20: TSEC 1 Receive */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 21: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 22: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 23: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 24: TSEC 1 Receive/Transmit Error */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 25: Fast Ethernet */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 26: DUART */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 27: I2C */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 28: Performance Monitor */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 29: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 30: CPM */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 31: Unused */
+ MPC85XX_INTERNAL_IRQ_SENSES,
#if defined(CONFIG_PCI)
(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 0: PCI1 slot */
(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 1: PCI1 slot */
@@ -181,6 +149,7 @@ void __init
mpc85xx_cds_init_IRQ(void)
{
bd_t *binfo = (bd_t *) __res;
+ int i;
/* Determine the Physical Address of the OpenPIC regs */
phys_addr_t OpenPIC_PAddr = binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET;
@@ -189,15 +158,28 @@ mpc85xx_cds_init_IRQ(void)
OpenPIC_NumInitSenses = sizeof (mpc85xx_cds_openpic_initsenses);
/* Skip reserved space and internal sources */
+#ifdef CONFIG_MPC8548
+ openpic_set_sources(0, 48, OpenPIC_Addr + 0x10200);
+#else
openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200);
+#endif
/* Map PIC IRQs 0-11 */
- openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000);
+ openpic_set_sources(48, 12, OpenPIC_Addr + 0x10000);
/* we let openpic interrupts starting from an offset, to
* leave space for cascading interrupts underneath.
*/
openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET);
+#ifdef CONFIG_PCI
+ openpic_hookup_cascade(PIRQ0A, "82c59 cascade", i8259_irq);
+
+ for (i = 0; i < NUM_8259_INTERRUPTS; i++)
+ irq_desc[i].handler = &i8259_pic;
+
+ i8259_init(0);
+#endif
+
#ifdef CONFIG_CPM2
/* Setup CPM2 PIC */
cpm2_init_IRQ();
@@ -231,7 +213,7 @@ mpc85xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin)
* interrupt on slot */
{
{ 0, 1, 2, 3 }, /* 16 - PMC */
- { 3, 0, 0, 0 }, /* 17 P2P (Tsi320) */
+ { 0, 1, 2, 3 }, /* 17 P2P (Tsi320) */
{ 0, 1, 2, 3 }, /* 18 - Slot 1 */
{ 1, 2, 3, 0 }, /* 19 - Slot 2 */
{ 2, 3, 0, 1 }, /* 20 - Slot 3 */
@@ -280,13 +262,135 @@ mpc85xx_exclude_device(u_char bus, u_char devfn)
return PCIBIOS_DEVICE_NOT_FOUND;
#endif
/* We explicitly do not go past the Tundra 320 Bridge */
- if (bus == 1)
+ if ((bus == 1) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))
return PCIBIOS_DEVICE_NOT_FOUND;
if ((bus == 0) && (PCI_SLOT(devfn) == ARCADIA_2ND_BRIDGE_IDSEL))
return PCIBIOS_DEVICE_NOT_FOUND;
else
return PCIBIOS_SUCCESSFUL;
}
+
+void __init
+mpc85xx_cds_enable_via(struct pci_controller *hose)
+{
+ u32 pci_class;
+ u16 vid, did;
+
+ early_read_config_dword(hose, 0, 0x88, PCI_CLASS_REVISION, &pci_class);
+ if ((pci_class >> 16) != PCI_CLASS_BRIDGE_PCI)
+ return;
+
+ /* Configure P2P so that we can reach bus 1 */
+ early_write_config_byte(hose, 0, 0x88, PCI_PRIMARY_BUS, 0);
+ early_write_config_byte(hose, 0, 0x88, PCI_SECONDARY_BUS, 1);
+ early_write_config_byte(hose, 0, 0x88, PCI_SUBORDINATE_BUS, 0xff);
+
+ early_read_config_word(hose, 1, 0x10, PCI_VENDOR_ID, &vid);
+ early_read_config_word(hose, 1, 0x10, PCI_DEVICE_ID, &did);
+
+ if ((vid != PCI_VENDOR_ID_VIA) ||
+ (did != PCI_DEVICE_ID_VIA_82C686))
+ return;
+
+ /* Enable USB and IDE functions */
+ early_write_config_byte(hose, 1, 0x10, 0x48, 0x08);
+}
+
+void __init
+mpc85xx_cds_fixup_via(struct pci_controller *hose)
+{
+ u32 pci_class;
+ u16 vid, did;
+
+ early_read_config_dword(hose, 0, 0x88, PCI_CLASS_REVISION, &pci_class);
+ if ((pci_class >> 16) != PCI_CLASS_BRIDGE_PCI)
+ return;
+
+ /*
+ * Force the backplane P2P bridge to have a window
+ * open from 0x00000000-0x00001fff in PCI I/O space.
+ * This allows legacy I/O (i8259, etc) on the VIA
+ * southbridge to be accessed.
+ */
+ early_write_config_byte(hose, 0, 0x88, PCI_IO_BASE, 0x00);
+ early_write_config_word(hose, 0, 0x88, PCI_IO_BASE_UPPER16, 0x0000);
+ early_write_config_byte(hose, 0, 0x88, PCI_IO_LIMIT, 0x10);
+ early_write_config_word(hose, 0, 0x88, PCI_IO_LIMIT_UPPER16, 0x0000);
+
+ early_read_config_word(hose, 1, 0x10, PCI_VENDOR_ID, &vid);
+ early_read_config_word(hose, 1, 0x10, PCI_DEVICE_ID, &did);
+ if ((vid != PCI_VENDOR_ID_VIA) ||
+ (did != PCI_DEVICE_ID_VIA_82C686))
+ return;
+
+ /*
+ * Since the P2P window was forced to cover the fixed
+ * legacy I/O addresses, it is necessary to manually
+ * place the base addresses for the IDE and USB functions
+ * within this window.
+ */
+ /* Function 1, IDE */
+ early_write_config_dword(hose, 1, 0x11, PCI_BASE_ADDRESS_0, 0x1ff8);
+ early_write_config_dword(hose, 1, 0x11, PCI_BASE_ADDRESS_1, 0x1ff4);
+ early_write_config_dword(hose, 1, 0x11, PCI_BASE_ADDRESS_2, 0x1fe8);
+ early_write_config_dword(hose, 1, 0x11, PCI_BASE_ADDRESS_3, 0x1fe4);
+ early_write_config_dword(hose, 1, 0x11, PCI_BASE_ADDRESS_4, 0x1fd0);
+
+ /* Function 2, USB ports 0-1 */
+ early_write_config_dword(hose, 1, 0x12, PCI_BASE_ADDRESS_4, 0x1fa0);
+
+ /* Function 3, USB ports 2-3 */
+ early_write_config_dword(hose, 1, 0x13, PCI_BASE_ADDRESS_4, 0x1f80);
+
+ /* Function 5, Power Management */
+ early_write_config_dword(hose, 1, 0x15, PCI_BASE_ADDRESS_0, 0x1e00);
+ early_write_config_dword(hose, 1, 0x15, PCI_BASE_ADDRESS_1, 0x1dfc);
+ early_write_config_dword(hose, 1, 0x15, PCI_BASE_ADDRESS_2, 0x1df8);
+
+ /* Function 6, AC97 Interface */
+ early_write_config_dword(hose, 1, 0x16, PCI_BASE_ADDRESS_0, 0x1c00);
+}
+
+void __init
+mpc85xx_cds_pcibios_fixup(void)
+{
+ struct pci_dev *dev = NULL;
+ u_char c;
+
+ if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_82C586_1, NULL))) {
+ /*
+ * U-Boot does not set the enable bits
+ * for the IDE device. Force them on here.
+ */
+ pci_read_config_byte(dev, 0x40, &c);
+ c |= 0x03; /* IDE: Chip Enable Bits */
+ pci_write_config_byte(dev, 0x40, c);
+
+ /*
+ * Since only primary interface works, force the
+ * IDE function to standard primary IDE interrupt
+ * w/ 8259 offset
+ */
+ dev->irq = 14;
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+ }
+
+ /*
+ * Force legacy USB interrupt routing
+ */
+ if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_82C586_2, NULL))) {
+ dev->irq = 10;
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 10);
+ }
+
+ if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_82C586_2, dev))) {
+ dev->irq = 11;
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 11);
+ }
+}
#endif /* CONFIG_PCI */
TODC_ALLOC();
@@ -328,6 +432,9 @@ mpc85xx_cds_setup_arch(void)
loops_per_jiffy = freq / HZ;
#ifdef CONFIG_PCI
+ /* VIA IDE configuration */
+ ppc_md.pcibios_fixup = mpc85xx_cds_pcibios_fixup;
+
/* setup PCI host bridges */
mpc85xx_setup_hose();
#endif
@@ -339,26 +446,52 @@ mpc85xx_cds_setup_arch(void)
#ifdef CONFIG_SERIAL_TEXT_DEBUG
/* Invalidate the entry we stole earlier the serial ports
* should be properly mapped */
- invalidate_tlbcam_entry(NUM_TLBCAMS - 1);
+ invalidate_tlbcam_entry(num_tlbcam_entries - 1);
#endif
/* setup the board related information for the enet controllers */
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
- pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
- pdata->interruptPHY = MPC85xx_IRQ_EXT5;
- pdata->phyid = 0;
- /* fixup phy address */
- pdata->phy_reg_addr += binfo->bi_immr_base;
- memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+ if (pdata) {
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+ pdata->phyid = 0;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+ }
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
- pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
- pdata->interruptPHY = MPC85xx_IRQ_EXT5;
- pdata->phyid = 1;
- /* fixup phy address */
- pdata->phy_reg_addr += binfo->bi_immr_base;
- memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+ if (pdata) {
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+ pdata->phyid = 1;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+ }
+
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_eTSEC1);
+ if (pdata) {
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+ pdata->phyid = 0;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+ }
+
+ pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_eTSEC2);
+ if (pdata) {
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+ pdata->phyid = 1;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+ }
+ ppc_sys_device_remove(MPC85xx_eTSEC3);
+ ppc_sys_device_remove(MPC85xx_eTSEC4);
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start)
@@ -395,7 +528,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
struct uart_port p;
/* Use the last TLB entry to map CCSRBAR to allow access to DUART regs */
- settlbcam(NUM_TLBCAMS - 1, binfo->bi_immr_base,
+ settlbcam(num_tlbcam_entries - 1, binfo->bi_immr_base,
binfo->bi_immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0);
memset(&p, 0, sizeof (p));
@@ -459,6 +592,9 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
ppc_md.progress = gen550_progress;
#endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
+#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_KGDB)
+ ppc_md.early_serial_map = mpc85xx_early_serial_map;
+#endif /* CONFIG_SERIAL_8250 && CONFIG_KGDB */
if (ppc_md.progress)
ppc_md.progress("mpc85xx_cds_init(): exit", 0);
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.h b/arch/ppc/platforms/85xx/mpc85xx_cds_common.h
index 7627d77504b..12b292c6ae3 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.h
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.h
@@ -77,4 +77,7 @@
#define MPC85XX_PCI2_IO_SIZE 0x01000000
+#define NR_8259_INTS 16
+#define CPM_IRQ_OFFSET NR_8259_INTS
+
#endif /* __MACH_MPC85XX_CDS_H__ */
diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c
index 9ab05e590c3..165df94d4aa 100644
--- a/arch/ppc/platforms/85xx/sbc8560.c
+++ b/arch/ppc/platforms/85xx/sbc8560.c
@@ -41,7 +41,6 @@
#include <asm/time.h>
#include <asm/io.h>
#include <asm/machdep.h>
-#include <asm/prom.h>
#include <asm/open_pic.h>
#include <asm/bootinfo.h>
#include <asm/pci-bridge.h>
@@ -125,25 +124,29 @@ sbc8560_setup_arch(void)
#ifdef CONFIG_SERIAL_TEXT_DEBUG
/* Invalidate the entry we stole earlier the serial ports
* should be properly mapped */
- invalidate_tlbcam_entry(NUM_TLBCAMS - 1);
+ invalidate_tlbcam_entry(num_tlbcam_entries - 1);
#endif
/* setup the board related information for the enet controllers */
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
- pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
- pdata->interruptPHY = MPC85xx_IRQ_EXT6;
- pdata->phyid = 25;
- /* fixup phy address */
- pdata->phy_reg_addr += binfo->bi_immr_base;
- memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+ if (pdata) {
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->interruptPHY = MPC85xx_IRQ_EXT6;
+ pdata->phyid = 25;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+ }
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
- pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
- pdata->interruptPHY = MPC85xx_IRQ_EXT7;
- pdata->phyid = 26;
- /* fixup phy address */
- pdata->phy_reg_addr += binfo->bi_immr_base;
- memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+ if (pdata) {
+ pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+ pdata->interruptPHY = MPC85xx_IRQ_EXT7;
+ pdata->phyid = 26;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+ }
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start)
@@ -176,7 +179,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
#ifdef CONFIG_SERIAL_TEXT_DEBUG
/* Use the last TLB entry to map CCSRBAR to allow access to DUART regs */
- settlbcam(NUM_TLBCAMS - 1, UARTA_ADDR,
+ settlbcam(num_tlbcam_entries - 1, UARTA_ADDR,
UARTA_ADDR, 0x1000, _PAGE_IO, 0);
#endif
@@ -221,6 +224,9 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
ppc_md.progress = gen550_progress;
#endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
+#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_KGDB)
+ ppc_md.early_serial_map = sbc8560_early_serial_map;
+#endif /* CONFIG_SERIAL_8250 && CONFIG_KGDB */
if (ppc_md.progress)
ppc_md.progress("sbc8560_init(): exit", 0);
diff --git a/arch/ppc/platforms/85xx/sbc85xx.c b/arch/ppc/platforms/85xx/sbc85xx.c
index 2d638c1c1bd..4f6d1ddd6fb 100644
--- a/arch/ppc/platforms/85xx/sbc85xx.c
+++ b/arch/ppc/platforms/85xx/sbc85xx.c
@@ -35,7 +35,6 @@
#include <asm/time.h>
#include <asm/io.h>
#include <asm/machdep.h>
-#include <asm/prom.h>
#include <asm/open_pic.h>
#include <asm/bootinfo.h>
#include <asm/pci-bridge.h>
@@ -59,40 +58,8 @@ unsigned long pci_dram_offset = 0;
extern unsigned long total_memory; /* in mm/init */
/* Internal interrupts are all Level Sensitive, and Positive Polarity */
-
static u_char sbc8560_openpic_initsenses[] __initdata = {
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 0: L2 Cache */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 1: ECM */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 2: DDR DRAM */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 3: LBIU */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 4: DMA 0 */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 5: DMA 1 */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 6: DMA 2 */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 7: DMA 3 */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 8: PCI/PCI-X */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 9: RIO Inbound Port Write Error */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 10: RIO Doorbell Inbound */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 11: RIO Outbound Message */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 12: RIO Inbound Message */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 13: TSEC 0 Transmit */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 14: TSEC 0 Receive */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 15: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 16: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 17: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 18: TSEC 0 Receive/Transmit Error */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 19: TSEC 1 Transmit */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 20: TSEC 1 Receive */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 21: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 22: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 23: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 24: TSEC 1 Receive/Transmit Error */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 25: Fast Ethernet */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 26: DUART */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 27: I2C */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 28: Performance Monitor */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 29: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 30: CPM */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 31: Unused */
+ MPC85XX_INTERNAL_IRQ_SENSES,
0x0, /* External 0: */
0x0, /* External 1: */
#if defined(CONFIG_PCI)
@@ -159,7 +126,7 @@ sbc8560_init_IRQ(void)
/* Skip reserved space and internal sources */
openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200);
/* Map PIC IRQs 0-11 */
- openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000);
+ openpic_set_sources(48, 12, OpenPIC_Addr + 0x10000);
/* we let openpic interrupts starting from an offset, to
* leave space for cascading interrupts underneath.
diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c
index bc95836e417..bb41265cfc8 100644
--- a/arch/ppc/platforms/85xx/stx_gp3.c
+++ b/arch/ppc/platforms/85xx/stx_gp3.c
@@ -46,7 +46,6 @@
#include <asm/time.h>
#include <asm/io.h>
#include <asm/machdep.h>
-#include <asm/prom.h>
#include <asm/open_pic.h>
#include <asm/bootinfo.h>
#include <asm/pci-bridge.h>
@@ -72,38 +71,7 @@ unsigned long pci_dram_offset = 0;
/* Internal interrupts are all Level Sensitive, and Positive Polarity */
static u8 gp3_openpic_initsenses[] __initdata = {
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 0: L2 Cache */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 1: ECM */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 2: DDR DRAM */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 3: LBIU */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 4: DMA 0 */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 5: DMA 1 */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 6: DMA 2 */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 7: DMA 3 */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 8: PCI/PCI-X */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 9: RIO Inbound Port Write Error */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 10: RIO Doorbell Inbound */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 11: RIO Outbound Message */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 12: RIO Inbound Message */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 13: TSEC 0 Transmit */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 14: TSEC 0 Receive */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 15: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 16: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 17: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 18: TSEC 0 Receive/Transmit Error */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 19: TSEC 1 Transmit */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 20: TSEC 1 Receive */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 21: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 22: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 23: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 24: TSEC 1 Receive/Transmit Error */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 25: Fast Ethernet */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 26: DUART */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 27: I2C */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 28: Performance Monitor */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 29: Unused */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 30: CPM */
- (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 31: Unused */
+ MPC85XX_INTERNAL_IRQ_SENSES,
0x0, /* External 0: */
#if defined(CONFIG_PCI)
(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* External 1: PCI slot 0 */
@@ -154,19 +122,23 @@ gp3_setup_arch(void)
/* setup the board related information for the enet controllers */
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
-/* pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */
- pdata->interruptPHY = MPC85xx_IRQ_EXT5;
- pdata->phyid = 2;
- pdata->phy_reg_addr += binfo->bi_immr_base;
- memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+ if (pdata) {
+ /* pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */
+ pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+ pdata->phyid = 2;
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+ }
pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
-/* pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */
- pdata->interruptPHY = MPC85xx_IRQ_EXT5;
- pdata->phyid = 4;
- /* fixup phy address */
- pdata->phy_reg_addr += binfo->bi_immr_base;
- memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+ if (pdata) {
+ /* pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */
+ pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+ pdata->phyid = 4;
+ /* fixup phy address */
+ pdata->phy_reg_addr += binfo->bi_immr_base;
+ memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+ }
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start)
@@ -200,7 +172,6 @@ static struct irqaction cpm2_irqaction = {
static void __init
gp3_init_IRQ(void)
{
- int i;
bd_t *binfo = (bd_t *) __res;
/*
@@ -218,7 +189,7 @@ gp3_init_IRQ(void)
openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200);
/* Map PIC IRQs 0-11 */
- openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000);
+ openpic_set_sources(48, 12, OpenPIC_Addr + 0x10000);
/*
* Let openpic interrupts starting from an offset, to
diff --git a/arch/ppc/platforms/chrp_pci.c b/arch/ppc/platforms/chrp_pci.c
index 7d0ee308f66..7d3fbb5c5db 100644
--- a/arch/ppc/platforms/chrp_pci.c
+++ b/arch/ppc/platforms/chrp_pci.c
@@ -9,7 +9,6 @@
#include <linux/string.h>
#include <linux/init.h>
#include <linux/ide.h>
-#include <linux/bootmem.h>
#include <asm/io.h>
#include <asm/pgtable.h>
diff --git a/arch/ppc/platforms/katana.c b/arch/ppc/platforms/katana.c
index eda922ac316..169dbf6534b 100644
--- a/arch/ppc/platforms/katana.c
+++ b/arch/ppc/platforms/katana.c
@@ -27,12 +27,12 @@
#include <linux/root_dev.h>
#include <linux/delay.h>
#include <linux/seq_file.h>
-#include <linux/bootmem.h>
#include <linux/mtd/physmap.h>
#include <linux/mv643xx.h>
#ifdef CONFIG_BOOTIMG
#include <linux/bootimg.h>
#endif
+#include <asm/io.h>
#include <asm/page.h>
#include <asm/time.h>
#include <asm/smp.h>
diff --git a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c
index f7fb2786cd5..5fdd4f607a4 100644
--- a/arch/ppc/platforms/pmac_cpufreq.c
+++ b/arch/ppc/platforms/pmac_cpufreq.c
@@ -83,16 +83,13 @@ static u32 frequency_gpio;
static u32 slew_done_gpio;
static int no_schedule;
static int has_cpu_l2lve;
-
-
-#define PMAC_CPU_LOW_SPEED 1
-#define PMAC_CPU_HIGH_SPEED 0
+static int is_pmu_based;
/* There are only two frequency states for each processor. Values
* are in kHz for the time being.
*/
-#define CPUFREQ_HIGH PMAC_CPU_HIGH_SPEED
-#define CPUFREQ_LOW PMAC_CPU_LOW_SPEED
+#define CPUFREQ_HIGH 0
+#define CPUFREQ_LOW 1
static struct cpufreq_frequency_table pmac_cpu_freqs[] = {
{CPUFREQ_HIGH, 0},
@@ -100,6 +97,11 @@ static struct cpufreq_frequency_table pmac_cpu_freqs[] = {
{0, CPUFREQ_TABLE_END},
};
+static struct freq_attr* pmac_cpu_freqs_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ NULL,
+};
+
static inline void local_delay(unsigned long ms)
{
if (no_schedule)
@@ -269,6 +271,8 @@ static int __pmac pmu_set_cpu_speed(int low_speed)
#ifdef DEBUG_FREQ
printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1));
#endif
+ pmu_suspend();
+
/* Disable all interrupt sources on openpic */
pic_prio = openpic_get_priority();
openpic_set_priority(0xf);
@@ -343,6 +347,8 @@ static int __pmac pmu_set_cpu_speed(int low_speed)
debug_calc_bogomips();
#endif
+ pmu_resume();
+
preempt_enable();
return 0;
@@ -355,7 +361,7 @@ static int __pmac do_set_cpu_speed(int speed_mode, int notify)
static unsigned long prev_l3cr;
freqs.old = cur_freq;
- freqs.new = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq;
+ freqs.new = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq;
freqs.cpu = smp_processor_id();
if (freqs.old == freqs.new)
@@ -363,7 +369,7 @@ static int __pmac do_set_cpu_speed(int speed_mode, int notify)
if (notify)
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
- if (speed_mode == PMAC_CPU_LOW_SPEED &&
+ if (speed_mode == CPUFREQ_LOW &&
cpu_has_feature(CPU_FTR_L3CR)) {
l3cr = _get_L3CR();
if (l3cr & L3CR_L3E) {
@@ -371,8 +377,8 @@ static int __pmac do_set_cpu_speed(int speed_mode, int notify)
_set_L3CR(0);
}
}
- set_speed_proc(speed_mode == PMAC_CPU_LOW_SPEED);
- if (speed_mode == PMAC_CPU_HIGH_SPEED &&
+ set_speed_proc(speed_mode == CPUFREQ_LOW);
+ if (speed_mode == CPUFREQ_HIGH &&
cpu_has_feature(CPU_FTR_L3CR)) {
l3cr = _get_L3CR();
if ((prev_l3cr & L3CR_L3E) && l3cr != prev_l3cr)
@@ -380,7 +386,7 @@ static int __pmac do_set_cpu_speed(int speed_mode, int notify)
}
if (notify)
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
- cur_freq = (speed_mode == PMAC_CPU_HIGH_SPEED) ? hi_freq : low_freq;
+ cur_freq = (speed_mode == CPUFREQ_HIGH) ? hi_freq : low_freq;
return 0;
}
@@ -423,7 +429,8 @@ static int __pmac pmac_cpufreq_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
policy->cur = cur_freq;
- return cpufreq_frequency_table_cpuinfo(policy, &pmac_cpu_freqs[0]);
+ cpufreq_frequency_table_get_attr(pmac_cpu_freqs, policy->cpu);
+ return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs);
}
static u32 __pmac read_gpio(struct device_node *np)
@@ -456,8 +463,8 @@ static int __pmac pmac_cpufreq_suspend(struct cpufreq_policy *policy, u32 state)
*/
no_schedule = 1;
sleep_freq = cur_freq;
- if (cur_freq == low_freq)
- do_set_cpu_speed(PMAC_CPU_HIGH_SPEED, 0);
+ if (cur_freq == low_freq && !is_pmu_based)
+ do_set_cpu_speed(CPUFREQ_HIGH, 0);
return 0;
}
@@ -473,8 +480,8 @@ static int __pmac pmac_cpufreq_resume(struct cpufreq_policy *policy)
* is that we force a switch to whatever it was, which is
* probably high speed due to our suspend() routine
*/
- do_set_cpu_speed(sleep_freq == low_freq ? PMAC_CPU_LOW_SPEED
- : PMAC_CPU_HIGH_SPEED, 0);
+ do_set_cpu_speed(sleep_freq == low_freq ?
+ CPUFREQ_LOW : CPUFREQ_HIGH, 0);
no_schedule = 0;
return 0;
@@ -488,6 +495,7 @@ static struct cpufreq_driver pmac_cpufreq_driver = {
.suspend = pmac_cpufreq_suspend,
.resume = pmac_cpufreq_resume,
.flags = CPUFREQ_PM_NO_WARN,
+ .attr = pmac_cpu_freqs_attr,
.name = "powermac",
.owner = THIS_MODULE,
};
@@ -580,6 +588,7 @@ static int __pmac pmac_cpufreq_init_MacRISC3(struct device_node *cpunode)
return 1;
hi_freq = (*value) / 1000;
set_speed_proc = pmu_set_cpu_speed;
+ is_pmu_based = 1;
return 0;
}
@@ -684,6 +693,7 @@ static int __init pmac_cpufreq_setup(void)
hi_freq = cur_freq;
low_freq = 400000;
set_speed_proc = pmu_set_cpu_speed;
+ is_pmu_based = 1;
}
/* Else check for TiPb 400 & 500 */
else if (machine_is_compatible("PowerBook3,2")) {
@@ -695,6 +705,7 @@ static int __init pmac_cpufreq_setup(void)
hi_freq = cur_freq;
low_freq = 300000;
set_speed_proc = pmu_set_cpu_speed;
+ is_pmu_based = 1;
}
/* Else check for 750FX */
else if (PVR_VER(mfspr(SPRN_PVR)) == 0x7000)
diff --git a/arch/ppc/platforms/pmac_pci.c b/arch/ppc/platforms/pmac_pci.c
index f6ff5192406..719fb49fe2b 100644
--- a/arch/ppc/platforms/pmac_pci.c
+++ b/arch/ppc/platforms/pmac_pci.c
@@ -17,7 +17,6 @@
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/init.h>
-#include <linux/bootmem.h>
#include <asm/sections.h>
#include <asm/io.h>
diff --git a/arch/ppc/platforms/pq2ads.h b/arch/ppc/platforms/pq2ads.h
index cf5e5dd06d6..067d9a5aebc 100644
--- a/arch/ppc/platforms/pq2ads.h
+++ b/arch/ppc/platforms/pq2ads.h
@@ -49,10 +49,10 @@
/* PCI interrupt controller */
#define PCI_INT_STAT_REG 0xF8200000
#define PCI_INT_MASK_REG 0xF8200004
-#define PIRQA (NR_SIU_INTS + 0)
-#define PIRQB (NR_SIU_INTS + 1)
-#define PIRQC (NR_SIU_INTS + 2)
-#define PIRQD (NR_SIU_INTS + 3)
+#define PIRQA (NR_CPM_INTS + 0)
+#define PIRQB (NR_CPM_INTS + 1)
+#define PIRQC (NR_CPM_INTS + 2)
+#define PIRQD (NR_CPM_INTS + 3)
/*
* PCI memory map definitions for MPC8266ADS-PCI.
@@ -68,28 +68,23 @@
* 0x00000000-0x1FFFFFFF 0x00000000-0x1FFFFFFF MPC8266 local memory
*/
-/* window for a PCI master to access MPC8266 memory */
-#define PCI_SLV_MEM_LOCAL 0x00000000 /* Local base */
-#define PCI_SLV_MEM_BUS 0x00000000 /* PCI base */
+/* All the other PCI memory map definitions reside at syslib/m82xx_pci.h
+ Here we should redefine what is unique for this board */
+#define M82xx_PCI_SLAVE_MEM_LOCAL 0x00000000 /* Local base */
+#define M82xx_PCI_SLAVE_MEM_BUS 0x00000000 /* PCI base */
+#define M82xx_PCI_SLAVE_MEM_SIZE 0x10000000 /* 256 Mb */
-/* window for the processor to access PCI memory with prefetching */
-#define PCI_MSTR_MEM_LOCAL 0x80000000 /* Local base */
-#define PCI_MSTR_MEM_BUS 0x80000000 /* PCI base */
-#define PCI_MSTR_MEM_SIZE 0x20000000 /* 512MB */
+#define M82xx_PCI_SLAVE_SEC_WND_SIZE ~(0x40000000 - 1U) /* 2 x 512Mb */
+#define M82xx_PCI_SLAVE_SEC_WND_BASE 0x80000000 /* PCI Memory base */
-/* window for the processor to access PCI memory without prefetching */
-#define PCI_MSTR_MEMIO_LOCAL 0xA0000000 /* Local base */
-#define PCI_MSTR_MEMIO_BUS 0xA0000000 /* PCI base */
-#define PCI_MSTR_MEMIO_SIZE 0x20000000 /* 512MB */
+#if defined(CONFIG_ADS8272)
+#define PCI_INT_TO_SIU SIU_INT_IRQ2
+#elif defined(CONFIG_PQ2FADS)
+#define PCI_INT_TO_SIU SIU_INT_IRQ6
+#else
+#warning PCI Bridge will be without interrupts support
+#endif
-/* window for the processor to access PCI I/O */
-#define PCI_MSTR_IO_LOCAL 0xF4000000 /* Local base */
-#define PCI_MSTR_IO_BUS 0x00000000 /* PCI base */
-#define PCI_MSTR_IO_SIZE 0x04000000 /* 64MB */
-
-#define _IO_BASE PCI_MSTR_IO_LOCAL
-#define _ISA_MEM_BASE PCI_MSTR_MEMIO_LOCAL
-#define PCI_DRAM_OFFSET PCI_SLV_MEM_BUS
#endif /* CONFIG_PCI */
#endif /* __MACH_ADS8260_DEFS */
diff --git a/arch/ppc/platforms/sandpoint.c b/arch/ppc/platforms/sandpoint.c
index 531bfa0e451..70e58f43f2b 100644
--- a/arch/ppc/platforms/sandpoint.c
+++ b/arch/ppc/platforms/sandpoint.c
@@ -81,6 +81,7 @@
#include <linux/serial.h>
#include <linux/tty.h> /* for linux/serial_core.h */
#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
#include <asm/system.h>
#include <asm/pgtable.h>
@@ -99,6 +100,7 @@
#include <asm/mpc10x.h>
#include <asm/pci-bridge.h>
#include <asm/kgdb.h>
+#include <asm/ppc_sys.h>
#include "sandpoint.h"
@@ -305,6 +307,24 @@ sandpoint_setup_arch(void)
/* Lookup PCI host bridges */
sandpoint_find_bridges();
+ if (strncmp (cur_ppc_sys_spec->ppc_sys_name, "8245", 4) == 0)
+ {
+ bd_t *bp = (bd_t *)__res;
+ struct plat_serial8250_port *pdata;
+ pdata = (struct plat_serial8250_port *) ppc_sys_get_pdata(MPC10X_DUART);
+
+ if (pdata)
+ {
+ pdata[0].uartclk = bp->bi_busfreq;
+ pdata[0].membase = ioremap(pdata[0].mapbase, 0x100);
+
+ /* this disables the 2nd serial port on the DUART
+ * since the sandpoint does not have it connected */
+ pdata[1].uartclk = 0;
+ pdata[1].irq = 0;
+ pdata[1].mapbase = 0;
+ }
+
printk(KERN_INFO "Motorola SPS Sandpoint Test Platform\n");
printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n");
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index dd418ea3426..dec5bf4f687 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -81,7 +81,7 @@ obj-$(CONFIG_SBC82xx) += todc_time.o
obj-$(CONFIG_SPRUCE) += cpc700_pic.o indirect_pci.o pci_auto.o \
todc_time.o
obj-$(CONFIG_8260) += m8260_setup.o
-obj-$(CONFIG_PCI_8260) += m8260_pci.o indirect_pci.o
+obj-$(CONFIG_PCI_8260) += m82xx_pci.o indirect_pci.o pci_auto.o
obj-$(CONFIG_8260_PCI9) += m8260_pci_erratum9.o
obj-$(CONFIG_CPM2) += cpm2_common.o cpm2_pic.o
ifeq ($(CONFIG_PPC_GEN550),y)
@@ -92,12 +92,12 @@ ifeq ($(CONFIG_SERIAL_MPSC_CONSOLE),y)
obj-$(CONFIG_SERIAL_TEXT_DEBUG) += mv64x60_dbg.o
endif
obj-$(CONFIG_BOOTX_TEXT) += btext.o
-obj-$(CONFIG_MPC10X_BRIDGE) += mpc10x_common.o indirect_pci.o
+obj-$(CONFIG_MPC10X_BRIDGE) += mpc10x_common.o indirect_pci.o ppc_sys.o
obj-$(CONFIG_MPC10X_OPENPIC) += open_pic.o
obj-$(CONFIG_40x) += dcr.o
obj-$(CONFIG_BOOKE) += dcr.o
obj-$(CONFIG_85xx) += open_pic.o ppc85xx_common.o ppc85xx_setup.o \
- ppc_sys.o mpc85xx_sys.o \
+ ppc_sys.o i8259.o mpc85xx_sys.o \
mpc85xx_devices.o
ifeq ($(CONFIG_85xx),y)
obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o
@@ -107,6 +107,7 @@ obj-$(CONFIG_83xx) += ipic.o ppc83xx_setup.o ppc_sys.o \
ifeq ($(CONFIG_83xx),y)
obj-$(CONFIG_PCI) += indirect_pci.o pci_auto.o
endif
+obj-$(CONFIG_MPC8548_CDS) += todc_time.o
obj-$(CONFIG_MPC8555_CDS) += todc_time.o
obj-$(CONFIG_PPC_MPC52xx) += mpc52xx_setup.o mpc52xx_pic.o \
mpc52xx_sys.o mpc52xx_devices.o ppc_sys.o
diff --git a/arch/ppc/syslib/cpm2_common.c b/arch/ppc/syslib/cpm2_common.c
index ea5e77080e8..4c19a4ac716 100644
--- a/arch/ppc/syslib/cpm2_common.c
+++ b/arch/ppc/syslib/cpm2_common.c
@@ -21,8 +21,8 @@
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/interrupt.h>
-#include <linux/bootmem.h>
#include <linux/module.h>
+#include <asm/io.h>
#include <asm/irq.h>
#include <asm/mpc8260.h>
#include <asm/page.h>
diff --git a/arch/ppc/syslib/indirect_pci.c b/arch/ppc/syslib/indirect_pci.c
index a5a752609e2..e7148846970 100644
--- a/arch/ppc/syslib/indirect_pci.c
+++ b/arch/ppc/syslib/indirect_pci.c
@@ -14,7 +14,6 @@
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/init.h>
-#include <linux/bootmem.h>
#include <asm/io.h>
#include <asm/prom.h>
diff --git a/arch/ppc/syslib/ipic.c b/arch/ppc/syslib/ipic.c
index acb2cde3171..8f01e0f1d84 100644
--- a/arch/ppc/syslib/ipic.c
+++ b/arch/ppc/syslib/ipic.c
@@ -79,7 +79,7 @@ static struct ipic_info ipic_info[] = {
.prio_mask = 7,
},
[17] = {
- .pend = IPIC_SIPNR_H,
+ .pend = IPIC_SEPNR,
.mask = IPIC_SEMSR,
.prio = IPIC_SMPRR_A,
.force = IPIC_SEFCR,
@@ -87,7 +87,7 @@ static struct ipic_info ipic_info[] = {
.prio_mask = 5,
},
[18] = {
- .pend = IPIC_SIPNR_H,
+ .pend = IPIC_SEPNR,
.mask = IPIC_SEMSR,
.prio = IPIC_SMPRR_A,
.force = IPIC_SEFCR,
@@ -95,7 +95,7 @@ static struct ipic_info ipic_info[] = {
.prio_mask = 6,
},
[19] = {
- .pend = IPIC_SIPNR_H,
+ .pend = IPIC_SEPNR,
.mask = IPIC_SEMSR,
.prio = IPIC_SMPRR_A,
.force = IPIC_SEFCR,
@@ -103,7 +103,7 @@ static struct ipic_info ipic_info[] = {
.prio_mask = 7,
},
[20] = {
- .pend = IPIC_SIPNR_H,
+ .pend = IPIC_SEPNR,
.mask = IPIC_SEMSR,
.prio = IPIC_SMPRR_B,
.force = IPIC_SEFCR,
@@ -111,7 +111,7 @@ static struct ipic_info ipic_info[] = {
.prio_mask = 4,
},
[21] = {
- .pend = IPIC_SIPNR_H,
+ .pend = IPIC_SEPNR,
.mask = IPIC_SEMSR,
.prio = IPIC_SMPRR_B,
.force = IPIC_SEFCR,
@@ -119,7 +119,7 @@ static struct ipic_info ipic_info[] = {
.prio_mask = 5,
},
[22] = {
- .pend = IPIC_SIPNR_H,
+ .pend = IPIC_SEPNR,
.mask = IPIC_SEMSR,
.prio = IPIC_SMPRR_B,
.force = IPIC_SEFCR,
@@ -127,7 +127,7 @@ static struct ipic_info ipic_info[] = {
.prio_mask = 6,
},
[23] = {
- .pend = IPIC_SIPNR_H,
+ .pend = IPIC_SEPNR,
.mask = IPIC_SEMSR,
.prio = IPIC_SMPRR_B,
.force = IPIC_SEFCR,
@@ -479,7 +479,7 @@ void __init ipic_init(phys_addr_t phys_addr,
temp = 0;
for (i = 0 ; i < senses_count ; i++) {
if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) {
- temp |= 1 << (16 - i);
+ temp |= 1 << (15 - i);
if (i != 0)
irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0;
else
diff --git a/arch/ppc/syslib/m8260_pci.c b/arch/ppc/syslib/m8260_pci.c
deleted file mode 100644
index 057cc3f8ff3..00000000000
--- a/arch/ppc/syslib/m8260_pci.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * (C) Copyright 2003
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- *
- * (C) Copyright 2004 Red Hat, Inc.
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * 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 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 <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/machdep.h>
-#include <asm/pci-bridge.h>
-#include <asm/immap_cpm2.h>
-#include <asm/mpc8260.h>
-
-#include "m8260_pci.h"
-
-
-/* PCI bus configuration registers.
- */
-
-static void __init m8260_setup_pci(struct pci_controller *hose)
-{
- volatile cpm2_map_t *immap = cpm2_immr;
- unsigned long pocmr;
- u16 tempShort;
-
-#ifndef CONFIG_ATC /* already done in U-Boot */
- /*
- * Setting required to enable IRQ1-IRQ7 (SIUMCR [DPPC]),
- * and local bus for PCI (SIUMCR [LBPC]).
- */
- immap->im_siu_conf.siu_82xx.sc_siumcr = 0x00640000;
-#endif
-
- /* Make PCI lowest priority */
- /* Each 4 bits is a device bus request and the MS 4bits
- is highest priority */
- /* Bus 4bit value
- --- ----------
- CPM high 0b0000
- CPM middle 0b0001
- CPM low 0b0010
- PCI reguest 0b0011
- Reserved 0b0100
- Reserved 0b0101
- Internal Core 0b0110
- External Master 1 0b0111
- External Master 2 0b1000
- External Master 3 0b1001
- The rest are reserved */
- immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x61207893;
-
- /* Park bus on core while modifying PCI Bus accesses */
- immap->im_siu_conf.siu_82xx.sc_ppc_acr = 0x6;
-
- /*
- * Set up master window that allows the CPU to access PCI space. This
- * window is set up using the first SIU PCIBR registers.
- */
- immap->im_memctl.memc_pcimsk0 = MPC826x_PCI_MASK;
- immap->im_memctl.memc_pcibr0 = MPC826x_PCI_BASE | PCIBR_ENABLE;
-
- /* Disable machine check on no response or target abort */
- immap->im_pci.pci_emr = cpu_to_le32(0x1fe7);
- /* Release PCI RST (by default the PCI RST signal is held low) */
- immap->im_pci.pci_gcr = cpu_to_le32(PCIGCR_PCI_BUS_EN);
-
- /* give it some time */
- mdelay(1);
-
- /*
- * Set up master window that allows the CPU to access PCI Memory (prefetch)
- * space. This window is set up using the first set of Outbound ATU registers.
- */
- immap->im_pci.pci_potar0 = cpu_to_le32(MPC826x_PCI_LOWER_MEM >> 12);
- immap->im_pci.pci_pobar0 = cpu_to_le32((MPC826x_PCI_LOWER_MEM - MPC826x_PCI_MEM_OFFSET) >> 12);
- pocmr = ((MPC826x_PCI_UPPER_MEM - MPC826x_PCI_LOWER_MEM) >> 12) ^ 0xfffff;
- immap->im_pci.pci_pocmr0 = cpu_to_le32(pocmr | POCMR_ENABLE | POCMR_PREFETCH_EN);
-
- /*
- * Set up master window that allows the CPU to access PCI Memory (non-prefetch)
- * space. This window is set up using the second set of Outbound ATU registers.
- */
- immap->im_pci.pci_potar1 = cpu_to_le32(MPC826x_PCI_LOWER_MMIO >> 12);
- immap->im_pci.pci_pobar1 = cpu_to_le32((MPC826x_PCI_LOWER_MMIO - MPC826x_PCI_MMIO_OFFSET) >> 12);
- pocmr = ((MPC826x_PCI_UPPER_MMIO - MPC826x_PCI_LOWER_MMIO) >> 12) ^ 0xfffff;
- immap->im_pci.pci_pocmr1 = cpu_to_le32(pocmr | POCMR_ENABLE);
-
- /*
- * Set up master window that allows the CPU to access PCI IO space. This window
- * is set up using the third set of Outbound ATU registers.
- */
- immap->im_pci.pci_potar2 = cpu_to_le32(MPC826x_PCI_IO_BASE >> 12);
- immap->im_pci.pci_pobar2 = cpu_to_le32(MPC826x_PCI_LOWER_IO >> 12);
- pocmr = ((MPC826x_PCI_UPPER_IO - MPC826x_PCI_LOWER_IO) >> 12) ^ 0xfffff;
- immap->im_pci.pci_pocmr2 = cpu_to_le32(pocmr | POCMR_ENABLE | POCMR_PCI_IO);
-
- /*
- * Set up slave window that allows PCI masters to access MPC826x local memory.
- * This window is set up using the first set of Inbound ATU registers
- */
-
- immap->im_pci.pci_pitar0 = cpu_to_le32(MPC826x_PCI_SLAVE_MEM_LOCAL >> 12);
- immap->im_pci.pci_pibar0 = cpu_to_le32(MPC826x_PCI_SLAVE_MEM_BUS >> 12);
- pocmr = ((MPC826x_PCI_SLAVE_MEM_SIZE-1) >> 12) ^ 0xfffff;
- immap->im_pci.pci_picmr0 = cpu_to_le32(pocmr | PICMR_ENABLE | PICMR_PREFETCH_EN);
-
- /* See above for description - puts PCI request as highest priority */
- immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x03124567;
-
- /* Park the bus on the PCI */
- immap->im_siu_conf.siu_82xx.sc_ppc_acr = PPC_ACR_BUS_PARK_PCI;
-
- /* Host mode - specify the bridge as a host-PCI bridge */
- early_write_config_word(hose, 0, 0, PCI_CLASS_DEVICE, PCI_CLASS_BRIDGE_HOST);
-
- /* Enable the host bridge to be a master on the PCI bus, and to act as a PCI memory target */
- early_read_config_word(hose, 0, 0, PCI_COMMAND, &tempShort);
- early_write_config_word(hose, 0, 0, PCI_COMMAND,
- tempShort | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
-}
-
-void __init m8260_find_bridges(void)
-{
- extern int pci_assign_all_busses;
- struct pci_controller * hose;
-
- pci_assign_all_busses = 1;
-
- hose = pcibios_alloc_controller();
-
- if (!hose)
- return;
-
- ppc_md.pci_swizzle = common_swizzle;
-
- hose->first_busno = 0;
- hose->bus_offset = 0;
- hose->last_busno = 0xff;
-
- setup_m8260_indirect_pci(hose,
- (unsigned long)&cpm2_immr->im_pci.pci_cfg_addr,
- (unsigned long)&cpm2_immr->im_pci.pci_cfg_data);
-
- m8260_setup_pci(hose);
- hose->pci_mem_offset = MPC826x_PCI_MEM_OFFSET;
-
- hose->io_base_virt = ioremap(MPC826x_PCI_IO_BASE,
- MPC826x_PCI_IO_SIZE);
- isa_io_base = (unsigned long) hose->io_base_virt;
-
- /* setup resources */
- pci_init_resource(&hose->mem_resources[0],
- MPC826x_PCI_LOWER_MEM,
- MPC826x_PCI_UPPER_MEM,
- IORESOURCE_MEM|IORESOURCE_PREFETCH, "PCI prefetchable memory");
-
- pci_init_resource(&hose->mem_resources[1],
- MPC826x_PCI_LOWER_MMIO,
- MPC826x_PCI_UPPER_MMIO,
- IORESOURCE_MEM, "PCI memory");
-
- pci_init_resource(&hose->io_resource,
- MPC826x_PCI_LOWER_IO,
- MPC826x_PCI_UPPER_IO,
- IORESOURCE_IO, "PCI I/O");
-}
diff --git a/arch/ppc/syslib/m8260_pci.h b/arch/ppc/syslib/m8260_pci.h
deleted file mode 100644
index d1352120acd..00000000000
--- a/arch/ppc/syslib/m8260_pci.h
+++ /dev/null
@@ -1,76 +0,0 @@
-
-#ifndef _PPC_KERNEL_M8260_PCI_H
-#define _PPC_KERNEL_M8260_PCI_H
-
-#include <asm/m8260_pci.h>
-
-/*
- * Local->PCI map (from CPU) controlled by
- * MPC826x master window
- *
- * 0x80000000 - 0xBFFFFFFF Total CPU2PCI space PCIBR0
- *
- * 0x80000000 - 0x9FFFFFFF PCI Mem with prefetch (Outbound ATU #1)
- * 0xA0000000 - 0xAFFFFFFF PCI Mem w/o prefetch (Outbound ATU #2)
- * 0xB0000000 - 0xB0FFFFFF 32-bit PCI IO (Outbound ATU #3)
- *
- * PCI->Local map (from PCI)
- * MPC826x slave window controlled by
- *
- * 0x00000000 - 0x07FFFFFF MPC826x local memory (Inbound ATU #1)
- */
-
-/*
- * Slave window that allows PCI masters to access MPC826x local memory.
- * This window is set up using the first set of Inbound ATU registers
- */
-
-#ifndef MPC826x_PCI_SLAVE_MEM_LOCAL
-#define MPC826x_PCI_SLAVE_MEM_LOCAL (((struct bd_info *)__res)->bi_memstart)
-#define MPC826x_PCI_SLAVE_MEM_BUS (((struct bd_info *)__res)->bi_memstart)
-#define MPC826x_PCI_SLAVE_MEM_SIZE (((struct bd_info *)__res)->bi_memsize)
-#endif
-
-/*
- * This is the window that allows the CPU to access PCI address space.
- * It will be setup with the SIU PCIBR0 register. All three PCI master
- * windows, which allow the CPU to access PCI prefetch, non prefetch,
- * and IO space (see below), must all fit within this window.
- */
-#ifndef MPC826x_PCI_BASE
-#define MPC826x_PCI_BASE 0x80000000
-#define MPC826x_PCI_MASK 0xc0000000
-#endif
-
-#ifndef MPC826x_PCI_LOWER_MEM
-#define MPC826x_PCI_LOWER_MEM 0x80000000
-#define MPC826x_PCI_UPPER_MEM 0x9fffffff
-#define MPC826x_PCI_MEM_OFFSET 0x00000000
-#endif
-
-#ifndef MPC826x_PCI_LOWER_MMIO
-#define MPC826x_PCI_LOWER_MMIO 0xa0000000
-#define MPC826x_PCI_UPPER_MMIO 0xafffffff
-#define MPC826x_PCI_MMIO_OFFSET 0x00000000
-#endif
-
-#ifndef MPC826x_PCI_LOWER_IO
-#define MPC826x_PCI_LOWER_IO 0x00000000
-#define MPC826x_PCI_UPPER_IO 0x00ffffff
-#define MPC826x_PCI_IO_BASE 0xb0000000
-#define MPC826x_PCI_IO_SIZE 0x01000000
-#endif
-
-#ifndef _IO_BASE
-#define _IO_BASE isa_io_base
-#endif
-
-#ifdef CONFIG_8260_PCI9
-struct pci_controller;
-extern void setup_m8260_indirect_pci(struct pci_controller* hose,
- u32 cfg_addr, u32 cfg_data);
-#else
-#define setup_m8260_indirect_pci setup_indirect_pci
-#endif
-
-#endif /* _PPC_KERNEL_M8260_PCI_H */
diff --git a/arch/ppc/syslib/m8260_pci_erratum9.c b/arch/ppc/syslib/m8260_pci_erratum9.c
index 9c0582d639e..1dc7e4e1d49 100644
--- a/arch/ppc/syslib/m8260_pci_erratum9.c
+++ b/arch/ppc/syslib/m8260_pci_erratum9.c
@@ -31,7 +31,7 @@
#include <asm/immap_cpm2.h>
#include <asm/cpm2.h>
-#include "m8260_pci.h"
+#include "m82xx_pci.h"
#ifdef CONFIG_8260_PCI9
/*#include <asm/mpc8260_pci9.h>*/ /* included in asm/io.h */
@@ -248,11 +248,11 @@ EXPORT_SYMBOL(idma_pci9_read_le);
static inline int is_pci_mem(unsigned long addr)
{
- if (addr >= MPC826x_PCI_LOWER_MMIO &&
- addr <= MPC826x_PCI_UPPER_MMIO)
+ if (addr >= M82xx_PCI_LOWER_MMIO &&
+ addr <= M82xx_PCI_UPPER_MMIO)
return 1;
- if (addr >= MPC826x_PCI_LOWER_MEM &&
- addr <= MPC826x_PCI_UPPER_MEM)
+ if (addr >= M82xx_PCI_LOWER_MEM &&
+ addr <= M82xx_PCI_UPPER_MEM)
return 1;
return 0;
}
diff --git a/arch/ppc/syslib/m8260_setup.c b/arch/ppc/syslib/m8260_setup.c
index 23ea3f694de..fda75d79050 100644
--- a/arch/ppc/syslib/m8260_setup.c
+++ b/arch/ppc/syslib/m8260_setup.c
@@ -34,7 +34,8 @@
unsigned char __res[sizeof(bd_t)];
extern void cpm2_reset(void);
-extern void m8260_find_bridges(void);
+extern void pq2_find_bridges(void);
+extern void pq2pci_init_irq(void);
extern void idma_pci9_init(void);
/* Place-holder for board-specific init */
@@ -56,7 +57,7 @@ m8260_setup_arch(void)
idma_pci9_init();
#endif
#ifdef CONFIG_PCI_8260
- m8260_find_bridges();
+ pq2_find_bridges();
#endif
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start)
@@ -173,6 +174,12 @@ m8260_init_IRQ(void)
* in case the boot rom changed something on us.
*/
cpm2_immr->im_intctl.ic_siprr = 0x05309770;
+
+#if defined(CONFIG_PCI) && (defined(CONFIG_ADS8272) || defined(CONFIG_PQ2FADS))
+ /* Initialize stuff for the 82xx CPLD IC and install demux */
+ pq2pci_init_irq();
+#endif
+
}
/*
diff --git a/arch/ppc/syslib/m82xx_pci.c b/arch/ppc/syslib/m82xx_pci.c
new file mode 100644
index 00000000000..5e7a7edcea7
--- /dev/null
+++ b/arch/ppc/syslib/m82xx_pci.c
@@ -0,0 +1,383 @@
+/*
+ *
+ * (C) Copyright 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * (C) Copyright 2004 Red Hat, Inc.
+ *
+ * 2005 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 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 <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/immap_cpm2.h>
+#include <asm/mpc8260.h>
+#include <asm/cpm2.h>
+
+#include "m82xx_pci.h"
+
+/*
+ * Interrupt routing
+ */
+
+static inline int
+pq2pci_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 22 - PCI slot 0 */
+ { PIRQD, PIRQA, PIRQB, PIRQC }, /* IDSEL 23 - PCI slot 1 */
+ { PIRQC, PIRQD, PIRQA, PIRQB }, /* IDSEL 24 - PCI slot 2 */
+ };
+
+ const long min_idsel = 22, max_idsel = 24, irqs_per_slot = 4;
+ return PCI_IRQ_TABLE_LOOKUP;
+}
+
+static void
+pq2pci_mask_irq(unsigned int irq)
+{
+ int bit = irq - NR_CPM_INTS;
+
+ *(volatile unsigned long *) PCI_INT_MASK_REG |= (1 << (31 - bit));
+ return;
+}
+
+static void
+pq2pci_unmask_irq(unsigned int irq)
+{
+ int bit = irq - NR_CPM_INTS;
+
+ *(volatile unsigned long *) PCI_INT_MASK_REG &= ~(1 << (31 - bit));
+ return;
+}
+
+static void
+pq2pci_mask_and_ack(unsigned int irq)
+{
+ int bit = irq - NR_CPM_INTS;
+
+ *(volatile unsigned long *) PCI_INT_MASK_REG |= (1 << (31 - bit));
+ return;
+}
+
+static void
+pq2pci_end_irq(unsigned int irq)
+{
+ int bit = irq - NR_CPM_INTS;
+
+ *(volatile unsigned long *) PCI_INT_MASK_REG &= ~(1 << (31 - bit));
+ return;
+}
+
+struct hw_interrupt_type pq2pci_ic = {
+ "PQ2 PCI",
+ NULL,
+ NULL,
+ pq2pci_unmask_irq,
+ pq2pci_mask_irq,
+ pq2pci_mask_and_ack,
+ pq2pci_end_irq,
+ 0
+};
+
+static irqreturn_t
+pq2pci_irq_demux(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned long stat, mask, pend;
+ int bit;
+
+ for(;;) {
+ stat = *(volatile unsigned long *) PCI_INT_STAT_REG;
+ mask = *(volatile unsigned long *) PCI_INT_MASK_REG;
+ pend = stat & ~mask & 0xf0000000;
+ if (!pend)
+ break;
+ for (bit = 0; pend != 0; ++bit, pend <<= 1) {
+ if (pend & 0x80000000)
+ __do_IRQ(NR_CPM_INTS + bit, regs);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static struct irqaction pq2pci_irqaction = {
+ .handler = pq2pci_irq_demux,
+ .flags = SA_INTERRUPT,
+ .mask = CPU_MASK_NONE,
+ .name = "PQ2 PCI cascade",
+};
+
+
+void
+pq2pci_init_irq(void)
+{
+ int irq;
+ volatile cpm2_map_t *immap = cpm2_immr;
+#if defined CONFIG_ADS8272
+ /* configure chip select for PCI interrupt controller */
+ immap->im_memctl.memc_br3 = PCI_INT_STAT_REG | 0x00001801;
+ immap->im_memctl.memc_or3 = 0xffff8010;
+#elif defined CONFIG_PQ2FADS
+ immap->im_memctl.memc_br8 = PCI_INT_STAT_REG | 0x00001801;
+ immap->im_memctl.memc_or8 = 0xffff8010;
+#endif
+ for (irq = NR_CPM_INTS; irq < NR_CPM_INTS + 4; irq++)
+ irq_desc[irq].handler = &pq2pci_ic;
+
+ /* make PCI IRQ level sensitive */
+ immap->im_intctl.ic_siexr &=
+ ~(1 << (14 - (PCI_INT_TO_SIU - SIU_INT_IRQ1)));
+
+ /* mask all PCI interrupts */
+ *(volatile unsigned long *) PCI_INT_MASK_REG |= 0xfff00000;
+
+ /* install the demultiplexer for the PCI cascade interrupt */
+ setup_irq(PCI_INT_TO_SIU, &pq2pci_irqaction);
+ return;
+}
+
+static int
+pq2pci_exclude_device(u_char bus, u_char devfn)
+{
+ return PCIBIOS_SUCCESSFUL;
+}
+
+/* PCI bus configuration registers.
+ */
+static void
+pq2ads_setup_pci(struct pci_controller *hose)
+{
+ __u32 val;
+ volatile cpm2_map_t *immap = cpm2_immr;
+ bd_t* binfo = (bd_t*) __res;
+ u32 sccr = immap->im_clkrst.car_sccr;
+ uint pci_div,freq,time;
+ /* PCI int lowest prio */
+ /* Each 4 bits is a device bus request and the MS 4bits
+ is highest priority */
+ /* Bus 4bit value
+ --- ----------
+ CPM high 0b0000
+ CPM middle 0b0001
+ CPM low 0b0010
+ PCI reguest 0b0011
+ Reserved 0b0100
+ Reserved 0b0101
+ Internal Core 0b0110
+ External Master 1 0b0111
+ External Master 2 0b1000
+ External Master 3 0b1001
+ The rest are reserved
+ */
+ immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x61207893;
+ /* park bus on core */
+ immap->im_siu_conf.siu_82xx.sc_ppc_acr = PPC_ACR_BUS_PARK_CORE;
+ /*
+ * Set up master windows that allow the CPU to access PCI space. These
+ * windows are set up using the two SIU PCIBR registers.
+ */
+
+ immap->im_memctl.memc_pcimsk0 = M82xx_PCI_PRIM_WND_SIZE;
+ immap->im_memctl.memc_pcibr0 = M82xx_PCI_PRIM_WND_BASE | PCIBR_ENABLE;
+
+#ifdef M82xx_PCI_SEC_WND_SIZE
+ immap->im_memctl.memc_pcimsk1 = M82xx_PCI_SEC_WND_SIZE;
+ immap->im_memctl.memc_pcibr1 = M82xx_PCI_SEC_WND_BASE | PCIBR_ENABLE;
+#endif
+
+#if defined CONFIG_ADS8272
+ immap->im_siu_conf.siu_82xx.sc_siumcr =
+ (immap->im_siu_conf.siu_82xx.sc_siumcr &
+ ~(SIUMCR_BBD | SIUMCR_ESE | SIUMCR_PBSE |
+ SIUMCR_CDIS | SIUMCR_DPPC11 | SIUMCR_L2CPC11 |
+ SIUMCR_LBPC11 | SIUMCR_APPC11 |
+ SIUMCR_CS10PC11 | SIUMCR_BCTLC11 | SIUMCR_MMR11)) |
+ SIUMCR_DPPC11 | SIUMCR_L2CPC01 | SIUMCR_LBPC00 |
+ SIUMCR_APPC10 | SIUMCR_CS10PC00 |
+ SIUMCR_BCTLC00 | SIUMCR_MMR11 ;
+
+#elif defined CONFIG_PQ2FADS
+ /*
+ * Setting required to enable IRQ1-IRQ7 (SIUMCR [DPPC]),
+ * and local bus for PCI (SIUMCR [LBPC]).
+ */
+ immap->im_siu_conf.siu_82xx.sc_siumcr = (immap->im_siu_conf.sc_siumcr &
+ ~(SIUMCR_L2PC11 | SIUMCR_LBPC11 | SIUMCR_CS10PC11 | SIUMCR_APPC11) |
+ SIUMCR_BBD | SIUMCR_LBPC01 | SIUMCR_DPPC11 | SIUMCR_APPC10;
+#endif
+ /* Enable PCI */
+ immap->im_pci.pci_gcr = cpu_to_le32(PCIGCR_PCI_BUS_EN);
+
+ pci_div = ( (sccr & SCCR_PCI_MODCK) ? 2 : 1) *
+ ( ( (sccr & SCCR_PCIDF_MSK) >> SCCR_PCIDF_SHIFT) + 1);
+ freq = (uint)((2*binfo->bi_cpmfreq)/(pci_div));
+ time = (int)666666/freq;
+ /* due to PCI Local Bus spec, some devices needs to wait such a long
+ time after RST deassertion. More specifically, 0.508s for 66MHz & twice more for 33 */
+ printk("%s: The PCI bus is %d Mhz.\nWaiting %s after deasserting RST...\n",__FILE__,freq,
+ (time==1) ? "0.5 seconds":"1 second" );
+
+ {
+ int i;
+ for(i=0;i<(500*time);i++)
+ udelay(1000);
+ }
+
+ /* setup ATU registers */
+ immap->im_pci.pci_pocmr0 = cpu_to_le32(POCMR_ENABLE | POCMR_PCI_IO |
+ ((~(M82xx_PCI_IO_SIZE - 1U)) >> POTA_ADDR_SHIFT));
+ immap->im_pci.pci_potar0 = cpu_to_le32(M82xx_PCI_LOWER_IO >> POTA_ADDR_SHIFT);
+ immap->im_pci.pci_pobar0 = cpu_to_le32(M82xx_PCI_IO_BASE >> POTA_ADDR_SHIFT);
+
+ /* Set-up non-prefetchable window */
+ immap->im_pci.pci_pocmr1 = cpu_to_le32(POCMR_ENABLE | ((~(M82xx_PCI_MMIO_SIZE-1U)) >> POTA_ADDR_SHIFT));
+ immap->im_pci.pci_potar1 = cpu_to_le32(M82xx_PCI_LOWER_MMIO >> POTA_ADDR_SHIFT);
+ immap->im_pci.pci_pobar1 = cpu_to_le32((M82xx_PCI_LOWER_MMIO - M82xx_PCI_MMIO_OFFSET) >> POTA_ADDR_SHIFT);
+
+ /* Set-up prefetchable window */
+ immap->im_pci.pci_pocmr2 = cpu_to_le32(POCMR_ENABLE |POCMR_PREFETCH_EN |
+ (~(M82xx_PCI_MEM_SIZE-1U) >> POTA_ADDR_SHIFT));
+ immap->im_pci.pci_potar2 = cpu_to_le32(M82xx_PCI_LOWER_MEM >> POTA_ADDR_SHIFT);
+ immap->im_pci.pci_pobar2 = cpu_to_le32((M82xx_PCI_LOWER_MEM - M82xx_PCI_MEM_OFFSET) >> POTA_ADDR_SHIFT);
+
+ /* Inbound transactions from PCI memory space */
+ immap->im_pci.pci_picmr0 = cpu_to_le32(PICMR_ENABLE | PICMR_PREFETCH_EN |
+ ((~(M82xx_PCI_SLAVE_MEM_SIZE-1U)) >> PITA_ADDR_SHIFT));
+ immap->im_pci.pci_pibar0 = cpu_to_le32(M82xx_PCI_SLAVE_MEM_BUS >> PITA_ADDR_SHIFT);
+ immap->im_pci.pci_pitar0 = cpu_to_le32(M82xx_PCI_SLAVE_MEM_LOCAL>> PITA_ADDR_SHIFT);
+
+#if defined CONFIG_ADS8272
+ /* PCI int highest prio */
+ immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x01236745;
+#elif defined CONFIG_PQ2FADS
+ immap->im_siu_conf.siu_82xx.sc_ppc_alrh = 0x03124567;
+#endif
+ /* park bus on PCI */
+ immap->im_siu_conf.siu_82xx.sc_ppc_acr = PPC_ACR_BUS_PARK_PCI;
+
+ /* Enable bus mastering and inbound memory transactions */
+ early_read_config_dword(hose, hose->first_busno, 0, PCI_COMMAND, &val);
+ val &= 0xffff0000;
+ val |= PCI_COMMAND_MEMORY|PCI_COMMAND_MASTER;
+ early_write_config_dword(hose, hose->first_busno, 0, PCI_COMMAND, val);
+
+}
+
+void __init pq2_find_bridges(void)
+{
+ extern int pci_assign_all_busses;
+ struct pci_controller * hose;
+ int host_bridge;
+
+ pci_assign_all_busses = 1;
+
+ hose = pcibios_alloc_controller();
+
+ if (!hose)
+ return;
+
+ ppc_md.pci_swizzle = common_swizzle;
+
+ hose->first_busno = 0;
+ hose->bus_offset = 0;
+ hose->last_busno = 0xff;
+
+#ifdef CONFIG_ADS8272
+ hose->set_cfg_type = 1;
+#endif
+
+ setup_m8260_indirect_pci(hose,
+ (unsigned long)&cpm2_immr->im_pci.pci_cfg_addr,
+ (unsigned long)&cpm2_immr->im_pci.pci_cfg_data);
+
+ /* Make sure it is a supported bridge */
+ early_read_config_dword(hose,
+ 0,
+ PCI_DEVFN(0,0),
+ PCI_VENDOR_ID,
+ &host_bridge);
+ switch (host_bridge) {
+ case PCI_DEVICE_ID_MPC8265:
+ break;
+ case PCI_DEVICE_ID_MPC8272:
+ break;
+ default:
+ printk("Attempting to use unrecognized host bridge ID"
+ " 0x%08x.\n", host_bridge);
+ break;
+ }
+
+ pq2ads_setup_pci(hose);
+
+ hose->io_space.start = M82xx_PCI_LOWER_IO;
+ hose->io_space.end = M82xx_PCI_UPPER_IO;
+ hose->mem_space.start = M82xx_PCI_LOWER_MEM;
+ hose->mem_space.end = M82xx_PCI_UPPER_MMIO;
+ hose->pci_mem_offset = M82xx_PCI_MEM_OFFSET;
+
+ isa_io_base =
+ (unsigned long) ioremap(M82xx_PCI_IO_BASE,
+ M82xx_PCI_IO_SIZE);
+ hose->io_base_virt = (void *) isa_io_base;
+
+ /* setup resources */
+ pci_init_resource(&hose->mem_resources[0],
+ M82xx_PCI_LOWER_MEM,
+ M82xx_PCI_UPPER_MEM,
+ IORESOURCE_MEM|IORESOURCE_PREFETCH, "PCI prefetchable memory");
+
+ pci_init_resource(&hose->mem_resources[1],
+ M82xx_PCI_LOWER_MMIO,
+ M82xx_PCI_UPPER_MMIO,
+ IORESOURCE_MEM, "PCI memory");
+
+ pci_init_resource(&hose->io_resource,
+ M82xx_PCI_LOWER_IO,
+ M82xx_PCI_UPPER_IO,
+ IORESOURCE_IO | 1, "PCI I/O");
+
+ ppc_md.pci_exclude_device = pq2pci_exclude_device;
+ hose->last_busno = pciauto_bus_scan(hose, hose->first_busno);
+
+ ppc_md.pci_map_irq = pq2pci_map_irq;
+ ppc_md.pcibios_fixup = NULL;
+ ppc_md.pcibios_fixup_bus = NULL;
+
+}
diff --git a/arch/ppc/syslib/m82xx_pci.h b/arch/ppc/syslib/m82xx_pci.h
new file mode 100644
index 00000000000..924f73f8e59
--- /dev/null
+++ b/arch/ppc/syslib/m82xx_pci.h
@@ -0,0 +1,92 @@
+
+#ifndef _PPC_KERNEL_M82XX_PCI_H
+#define _PPC_KERNEL_M82XX_PCI_H
+
+#include <asm/m8260_pci.h>
+/*
+ * Local->PCI map (from CPU) controlled by
+ * MPC826x master window
+ *
+ * 0xF6000000 - 0xF7FFFFFF IO space
+ * 0x80000000 - 0xBFFFFFFF CPU2PCI memory space PCIBR0
+ *
+ * 0x80000000 - 0x9FFFFFFF PCI Mem with prefetch (Outbound ATU #1)
+ * 0xA0000000 - 0xBFFFFFFF PCI Mem w/o prefetch (Outbound ATU #2)
+ * 0xF6000000 - 0xF7FFFFFF 32-bit PCI IO (Outbound ATU #3)
+ *
+ * PCI->Local map (from PCI)
+ * MPC826x slave window controlled by
+ *
+ * 0x00000000 - 0x07FFFFFF MPC826x local memory (Inbound ATU #1)
+ */
+
+/*
+ * Slave window that allows PCI masters to access MPC826x local memory.
+ * This window is set up using the first set of Inbound ATU registers
+ */
+
+#ifndef M82xx_PCI_SLAVE_MEM_LOCAL
+#define M82xx_PCI_SLAVE_MEM_LOCAL (((struct bd_info *)__res)->bi_memstart)
+#define M82xx_PCI_SLAVE_MEM_BUS (((struct bd_info *)__res)->bi_memstart)
+#define M82xx_PCI_SLAVE_MEM_SIZE (((struct bd_info *)__res)->bi_memsize)
+#endif
+
+/*
+ * This is the window that allows the CPU to access PCI address space.
+ * It will be setup with the SIU PCIBR0 register. All three PCI master
+ * windows, which allow the CPU to access PCI prefetch, non prefetch,
+ * and IO space (see below), must all fit within this window.
+ */
+
+#ifndef M82xx_PCI_LOWER_MEM
+#define M82xx_PCI_LOWER_MEM 0x80000000
+#define M82xx_PCI_UPPER_MEM 0x9fffffff
+#define M82xx_PCI_MEM_OFFSET 0x00000000
+#define M82xx_PCI_MEM_SIZE 0x20000000
+#endif
+
+#ifndef M82xx_PCI_LOWER_MMIO
+#define M82xx_PCI_LOWER_MMIO 0xa0000000
+#define M82xx_PCI_UPPER_MMIO 0xafffffff
+#define M82xx_PCI_MMIO_OFFSET 0x00000000
+#define M82xx_PCI_MMIO_SIZE 0x20000000
+#endif
+
+#ifndef M82xx_PCI_LOWER_IO
+#define M82xx_PCI_LOWER_IO 0x00000000
+#define M82xx_PCI_UPPER_IO 0x01ffffff
+#define M82xx_PCI_IO_BASE 0xf6000000
+#define M82xx_PCI_IO_SIZE 0x02000000
+#endif
+
+#ifndef M82xx_PCI_PRIM_WND_SIZE
+#define M82xx_PCI_PRIM_WND_SIZE ~(M82xx_PCI_IO_SIZE - 1U)
+#define M82xx_PCI_PRIM_WND_BASE (M82xx_PCI_IO_BASE)
+#endif
+
+#ifndef M82xx_PCI_SEC_WND_SIZE
+#define M82xx_PCI_SEC_WND_SIZE ~(M82xx_PCI_MEM_SIZE + M82xx_PCI_MMIO_SIZE - 1U)
+#define M82xx_PCI_SEC_WND_BASE (M82xx_PCI_LOWER_MEM)
+#endif
+
+#ifndef POTA_ADDR_SHIFT
+#define POTA_ADDR_SHIFT 12
+#endif
+
+#ifndef PITA_ADDR_SHIFT
+#define PITA_ADDR_SHIFT 12
+#endif
+
+#ifndef _IO_BASE
+#define _IO_BASE isa_io_base
+#endif
+
+#ifdef CONFIG_8260_PCI9
+struct pci_controller;
+extern void setup_m8260_indirect_pci(struct pci_controller* hose,
+ u32 cfg_addr, u32 cfg_data);
+#else
+#define setup_m8260_indirect_pci setup_indirect_pci
+#endif
+
+#endif /* _PPC_KERNEL_M8260_PCI_H */
diff --git a/arch/ppc/syslib/mpc10x_common.c b/arch/ppc/syslib/mpc10x_common.c
index fd93adfd464..8fc5f415452 100644
--- a/arch/ppc/syslib/mpc10x_common.c
+++ b/arch/ppc/syslib/mpc10x_common.c
@@ -21,6 +21,9 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/slab.h>
+#include <linux/serial_8250.h>
+#include <linux/fsl_devices.h>
+#include <linux/device.h>
#include <asm/byteorder.h>
#include <asm/io.h>
@@ -30,16 +33,7 @@
#include <asm/pci-bridge.h>
#include <asm/open_pic.h>
#include <asm/mpc10x.h>
-#include <asm/ocp.h>
-
-/* The OCP structure is fixed by code below, before OCP initialises.
- paddr depends on where the board places the EUMB.
- - fixed in mpc10x_bridge_init().
- irq depends on two things:
- > does the board use the EPIC at all? (PCORE does not).
- > is the EPIC in serial or parallel mode?
- - fixed in mpc10x_set_openpic().
-*/
+#include <asm/ppc_sys.h>
#ifdef CONFIG_MPC10X_OPENPIC
#ifdef CONFIG_EPIC_SERIAL_MODE
@@ -50,35 +44,140 @@
#define MPC10X_I2C_IRQ (EPIC_IRQ_BASE + NUM_8259_INTERRUPTS)
#define MPC10X_DMA0_IRQ (EPIC_IRQ_BASE + 1 + NUM_8259_INTERRUPTS)
#define MPC10X_DMA1_IRQ (EPIC_IRQ_BASE + 2 + NUM_8259_INTERRUPTS)
+#define MPC10X_UART0_IRQ (EPIC_IRQ_BASE + 4 + NUM_8259_INTERRUPTS)
#else
-#define MPC10X_I2C_IRQ OCP_IRQ_NA
-#define MPC10X_DMA0_IRQ OCP_IRQ_NA
-#define MPC10X_DMA1_IRQ OCP_IRQ_NA
+#define MPC10X_I2C_IRQ -1
+#define MPC10X_DMA0_IRQ -1
+#define MPC10X_DMA1_IRQ -1
+#define MPC10X_UART0_IRQ -1
#endif
-
-struct ocp_def core_ocp[] = {
- { .vendor = OCP_VENDOR_INVALID
- }
+static struct fsl_i2c_platform_data mpc10x_i2c_pdata = {
+ .device_flags = 0,
};
-static struct ocp_fs_i2c_data mpc10x_i2c_data = {
- .flags = 0
+static struct plat_serial8250_port serial_platform_data[] = {
+ [0] = {
+ .mapbase = 0x4500,
+ .iotype = UPIO_MEM,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+ },
+ [1] = {
+ .mapbase = 0x4600,
+ .iotype = UPIO_MEM,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+ },
+ { },
};
-static struct ocp_def mpc10x_i2c_ocp = {
- .vendor = OCP_VENDOR_MOTOROLA,
- .function = OCP_FUNC_IIC,
- .index = 0,
- .additions = &mpc10x_i2c_data
+
+struct platform_device ppc_sys_platform_devices[] = {
+ [MPC10X_IIC1] = {
+ .name = "fsl-i2c",
+ .id = 1,
+ .dev.platform_data = &mpc10x_i2c_pdata,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = MPC10X_EUMB_I2C_OFFSET,
+ .end = MPC10X_EUMB_I2C_OFFSET +
+ MPC10X_EUMB_I2C_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .flags = IORESOURCE_IRQ
+ },
+ },
+ },
+ [MPC10X_DMA0] = {
+ .name = "fsl-dma",
+ .id = 0,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = MPC10X_EUMB_DMA_OFFSET + 0x10,
+ .end = MPC10X_EUMB_DMA_OFFSET + 0x1f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC10X_DMA1] = {
+ .name = "fsl-dma",
+ .id = 1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = MPC10X_EUMB_DMA_OFFSET + 0x20,
+ .end = MPC10X_EUMB_DMA_OFFSET + 0x2f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC10X_DMA1] = {
+ .name = "fsl-dma",
+ .id = 1,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = MPC10X_EUMB_DMA_OFFSET + 0x20,
+ .end = MPC10X_EUMB_DMA_OFFSET + 0x2f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC10X_DUART] = {
+ .name = "serial8250",
+ .id = 0,
+ .dev.platform_data = serial_platform_data,
+ },
};
-static struct ocp_def mpc10x_dma_ocp[2] = {
-{ .vendor = OCP_VENDOR_MOTOROLA,
- .function = OCP_FUNC_DMA,
- .index = 0 },
-{ .vendor = OCP_VENDOR_MOTOROLA,
- .function = OCP_FUNC_DMA,
- .index = 1 }
+/* We use the PCI ID to match on */
+struct ppc_sys_spec *cur_ppc_sys_spec;
+struct ppc_sys_spec ppc_sys_specs[] = {
+ {
+ .ppc_sys_name = "8245",
+ .mask = 0xFFFFFFFF,
+ .value = MPC10X_BRIDGE_8245,
+ .num_devices = 4,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC10X_IIC1, MPC10X_DMA0, MPC10X_DMA1, MPC10X_DUART,
+ },
+ },
+ {
+ .ppc_sys_name = "8240",
+ .mask = 0xFFFFFFFF,
+ .value = MPC10X_BRIDGE_8240,
+ .num_devices = 3,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC10X_IIC1, MPC10X_DMA0, MPC10X_DMA1,
+ },
+ },
+ {
+ .ppc_sys_name = "107",
+ .mask = 0xFFFFFFFF,
+ .value = MPC10X_BRIDGE_107,
+ .num_devices = 3,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC10X_IIC1, MPC10X_DMA0, MPC10X_DMA1,
+ },
+ },
+ { /* default match */
+ .ppc_sys_name = "",
+ .mask = 0x00000000,
+ .value = 0x00000000,
+ },
};
/* Set resources to match bridge memory map */
@@ -132,7 +231,7 @@ mpc10x_bridge_init(struct pci_controller *hose,
uint new_map,
uint phys_eumb_base)
{
- int host_bridge, picr1, picr1_bit;
+ int host_bridge, picr1, picr1_bit, i;
ulong pci_config_addr, pci_config_data;
u_char pir, byte;
@@ -273,7 +372,7 @@ mpc10x_bridge_init(struct pci_controller *hose,
printk("Host bridge in Agent mode\n");
/* Read or Set LMBAR & PCSRBAR? */
}
-
+
/* Set base addr of the 8240/107 EUMB. */
early_write_config_dword(hose,
0,
@@ -287,17 +386,6 @@ mpc10x_bridge_init(struct pci_controller *hose,
ioremap(phys_eumb_base + MPC10X_EUMB_EPIC_OFFSET,
MPC10X_EUMB_EPIC_SIZE);
#endif
- mpc10x_i2c_ocp.paddr = phys_eumb_base + MPC10X_EUMB_I2C_OFFSET;
- mpc10x_i2c_ocp.irq = MPC10X_I2C_IRQ;
- ocp_add_one_device(&mpc10x_i2c_ocp);
- mpc10x_dma_ocp[0].paddr = phys_eumb_base +
- MPC10X_EUMB_DMA_OFFSET + 0x100;
- mpc10x_dma_ocp[0].irq = MPC10X_DMA0_IRQ;
- ocp_add_one_device(&mpc10x_dma_ocp[0]);
- mpc10x_dma_ocp[1].paddr = phys_eumb_base +
- MPC10X_EUMB_DMA_OFFSET + 0x200;
- mpc10x_dma_ocp[1].irq = MPC10X_DMA1_IRQ;
- ocp_add_one_device(&mpc10x_dma_ocp[1]);
}
#ifdef CONFIG_MPC10X_STORE_GATHERING
@@ -306,6 +394,29 @@ mpc10x_bridge_init(struct pci_controller *hose,
mpc10x_disable_store_gathering(hose);
#endif
+ /* setup platform devices for MPC10x bridges */
+ identify_ppc_sys_by_id (host_bridge);
+
+ for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) {
+ unsigned int dev_id = cur_ppc_sys_spec->device_list[i];
+ ppc_sys_fixup_mem_resource(&ppc_sys_platform_devices[dev_id],
+ phys_eumb_base);
+ }
+
+ /* IRQ's are determined at runtime */
+ ppc_sys_platform_devices[MPC10X_IIC1].resource[1].start = MPC10X_I2C_IRQ;
+ ppc_sys_platform_devices[MPC10X_IIC1].resource[1].end = MPC10X_I2C_IRQ;
+ ppc_sys_platform_devices[MPC10X_DMA0].resource[1].start = MPC10X_DMA0_IRQ;
+ ppc_sys_platform_devices[MPC10X_DMA0].resource[1].end = MPC10X_DMA0_IRQ;
+ ppc_sys_platform_devices[MPC10X_DMA1].resource[1].start = MPC10X_DMA1_IRQ;
+ ppc_sys_platform_devices[MPC10X_DMA1].resource[1].end = MPC10X_DMA1_IRQ;
+
+ serial_platform_data[0].mapbase += phys_eumb_base;
+ serial_platform_data[0].irq = MPC10X_UART0_IRQ;
+
+ serial_platform_data[1].mapbase += phys_eumb_base;
+ serial_platform_data[1].irq = MPC10X_UART0_IRQ + 1;
+
/*
* 8240 erratum 26, 8241/8245 erratum 29, 107 erratum 23: speculative
* PCI reads may return stale data so turn off.
@@ -330,7 +441,7 @@ mpc10x_bridge_init(struct pci_controller *hose,
* 8245 (Rev 2., dated 10/2003) says PICR2[0] is reserverd.
*/
if (host_bridge == MPC10X_BRIDGE_8245) {
- ulong picr2;
+ u32 picr2;
early_read_config_dword(hose, 0, PCI_DEVFN(0,0),
MPC10X_CFG_PICR2_REG, &picr2);
@@ -504,6 +615,8 @@ void __init mpc10x_set_openpic(void)
openpic_set_sources(EPIC_IRQ_BASE, 3, OpenPIC_Addr + 0x11020);
/* Skip reserved space and map Message Unit Interrupt (I2O) */
openpic_set_sources(EPIC_IRQ_BASE + 3, 1, OpenPIC_Addr + 0x110C0);
+ /* Skip reserved space and map Serial Interupts */
+ openpic_set_sources(EPIC_IRQ_BASE + 4, 2, OpenPIC_Addr + 0x11120);
openpic_init(NUM_8259_INTERRUPTS);
}
diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c
index 5c1a919eaab..75c8e9834ae 100644
--- a/arch/ppc/syslib/mpc83xx_devices.c
+++ b/arch/ppc/syslib/mpc83xx_devices.c
@@ -61,6 +61,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
.iotype = UPIO_MEM,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
},
+ { },
};
struct platform_device ppc_sys_platform_devices[] = {
diff --git a/arch/ppc/syslib/mpc85xx_devices.c b/arch/ppc/syslib/mpc85xx_devices.c
index a231795ee26..8af322dd476 100644
--- a/arch/ppc/syslib/mpc85xx_devices.c
+++ b/arch/ppc/syslib/mpc85xx_devices.c
@@ -40,6 +40,42 @@ static struct gianfar_platform_data mpc85xx_tsec2_pdata = {
.phy_reg_addr = MPC85xx_ENET1_OFFSET,
};
+static struct gianfar_platform_data mpc85xx_etsec1_pdata = {
+ .device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
+ FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_RMON |
+ FSL_GIANFAR_DEV_HAS_MULTI_INTR |
+ FSL_GIANFAR_DEV_HAS_CSUM | FSL_GIANFAR_DEV_HAS_VLAN |
+ FSL_GIANFAR_DEV_HAS_EXTENDED_HASH,
+ .phy_reg_addr = MPC85xx_ENET1_OFFSET,
+};
+
+static struct gianfar_platform_data mpc85xx_etsec2_pdata = {
+ .device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
+ FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_RMON |
+ FSL_GIANFAR_DEV_HAS_MULTI_INTR |
+ FSL_GIANFAR_DEV_HAS_CSUM | FSL_GIANFAR_DEV_HAS_VLAN |
+ FSL_GIANFAR_DEV_HAS_EXTENDED_HASH,
+ .phy_reg_addr = MPC85xx_ENET1_OFFSET,
+};
+
+static struct gianfar_platform_data mpc85xx_etsec3_pdata = {
+ .device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
+ FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_RMON |
+ FSL_GIANFAR_DEV_HAS_MULTI_INTR |
+ FSL_GIANFAR_DEV_HAS_CSUM | FSL_GIANFAR_DEV_HAS_VLAN |
+ FSL_GIANFAR_DEV_HAS_EXTENDED_HASH,
+ .phy_reg_addr = MPC85xx_ENET1_OFFSET,
+};
+
+static struct gianfar_platform_data mpc85xx_etsec4_pdata = {
+ .device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
+ FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_RMON |
+ FSL_GIANFAR_DEV_HAS_MULTI_INTR |
+ FSL_GIANFAR_DEV_HAS_CSUM | FSL_GIANFAR_DEV_HAS_VLAN |
+ FSL_GIANFAR_DEV_HAS_EXTENDED_HASH,
+ .phy_reg_addr = MPC85xx_ENET1_OFFSET,
+};
+
static struct gianfar_platform_data mpc85xx_fec_pdata = {
.phy_reg_addr = MPC85xx_ENET1_OFFSET,
};
@@ -48,6 +84,10 @@ static struct fsl_i2c_platform_data mpc85xx_fsl_i2c_pdata = {
.device_flags = FSL_I2C_DEV_SEPARATE_DFSRR,
};
+static struct fsl_i2c_platform_data mpc85xx_fsl_i2c2_pdata = {
+ .device_flags = FSL_I2C_DEV_SEPARATE_DFSRR,
+};
+
static struct plat_serial8250_port serial_platform_data[] = {
[0] = {
.mapbase = 0x4500,
@@ -61,6 +101,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
.iotype = UPIO_MEM,
.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_SHARE_IRQ,
},
+ { },
};
struct platform_device ppc_sys_platform_devices[] = {
@@ -280,7 +321,6 @@ struct platform_device ppc_sys_platform_devices[] = {
},
},
},
-#ifdef CONFIG_CPM2
[MPC85xx_CPM_FCC1] = {
.name = "fsl-cpm-fcc",
.id = 1,
@@ -534,7 +574,151 @@ struct platform_device ppc_sys_platform_devices[] = {
},
},
},
-#endif /* CONFIG_CPM2 */
+ [MPC85xx_eTSEC1] = {
+ .name = "fsl-gianfar",
+ .id = 1,
+ .dev.platform_data = &mpc85xx_etsec1_pdata,
+ .num_resources = 4,
+ .resource = (struct resource[]) {
+ {
+ .start = MPC85xx_ENET1_OFFSET,
+ .end = MPC85xx_ENET1_OFFSET +
+ MPC85xx_ENET1_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "tx",
+ .start = MPC85xx_IRQ_TSEC1_TX,
+ .end = MPC85xx_IRQ_TSEC1_TX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "rx",
+ .start = MPC85xx_IRQ_TSEC1_RX,
+ .end = MPC85xx_IRQ_TSEC1_RX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "error",
+ .start = MPC85xx_IRQ_TSEC1_ERROR,
+ .end = MPC85xx_IRQ_TSEC1_ERROR,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC85xx_eTSEC2] = {
+ .name = "fsl-gianfar",
+ .id = 2,
+ .dev.platform_data = &mpc85xx_etsec2_pdata,
+ .num_resources = 4,
+ .resource = (struct resource[]) {
+ {
+ .start = MPC85xx_ENET2_OFFSET,
+ .end = MPC85xx_ENET2_OFFSET +
+ MPC85xx_ENET2_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "tx",
+ .start = MPC85xx_IRQ_TSEC2_TX,
+ .end = MPC85xx_IRQ_TSEC2_TX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "rx",
+ .start = MPC85xx_IRQ_TSEC2_RX,
+ .end = MPC85xx_IRQ_TSEC2_RX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "error",
+ .start = MPC85xx_IRQ_TSEC2_ERROR,
+ .end = MPC85xx_IRQ_TSEC2_ERROR,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC85xx_eTSEC3] = {
+ .name = "fsl-gianfar",
+ .id = 3,
+ .dev.platform_data = &mpc85xx_etsec3_pdata,
+ .num_resources = 4,
+ .resource = (struct resource[]) {
+ {
+ .start = MPC85xx_ENET3_OFFSET,
+ .end = MPC85xx_ENET3_OFFSET +
+ MPC85xx_ENET3_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "tx",
+ .start = MPC85xx_IRQ_TSEC3_TX,
+ .end = MPC85xx_IRQ_TSEC3_TX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "rx",
+ .start = MPC85xx_IRQ_TSEC3_RX,
+ .end = MPC85xx_IRQ_TSEC3_RX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "error",
+ .start = MPC85xx_IRQ_TSEC3_ERROR,
+ .end = MPC85xx_IRQ_TSEC3_ERROR,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC85xx_eTSEC4] = {
+ .name = "fsl-gianfar",
+ .id = 4,
+ .dev.platform_data = &mpc85xx_etsec4_pdata,
+ .num_resources = 4,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x27000,
+ .end = 0x27fff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "tx",
+ .start = MPC85xx_IRQ_TSEC4_TX,
+ .end = MPC85xx_IRQ_TSEC4_TX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "rx",
+ .start = MPC85xx_IRQ_TSEC4_RX,
+ .end = MPC85xx_IRQ_TSEC4_RX,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "error",
+ .start = MPC85xx_IRQ_TSEC4_ERROR,
+ .end = MPC85xx_IRQ_TSEC4_ERROR,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
+ [MPC85xx_IIC2] = {
+ .name = "fsl-i2c",
+ .id = 2,
+ .dev.platform_data = &mpc85xx_fsl_i2c2_pdata,
+ .num_resources = 2,
+ .resource = (struct resource[]) {
+ {
+ .start = 0x03100,
+ .end = 0x031ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MPC85xx_IRQ_IIC1,
+ .end = MPC85xx_IRQ_IIC1,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ },
};
static int __init mach_mpc85xx_fixup(struct platform_device *pdev)
diff --git a/arch/ppc/syslib/mpc85xx_sys.c b/arch/ppc/syslib/mpc85xx_sys.c
index d806a92a940..6e3184ab354 100644
--- a/arch/ppc/syslib/mpc85xx_sys.c
+++ b/arch/ppc/syslib/mpc85xx_sys.c
@@ -110,6 +110,111 @@ struct ppc_sys_spec ppc_sys_specs[] = {
MPC85xx_CPM_USB,
},
},
+ /* SVRs on 8548 rev1.0 matches for 8548/8547/8545 */
+ {
+ .ppc_sys_name = "8548E",
+ .mask = 0xFFFF00F0,
+ .value = 0x80390010,
+ .num_devices = 13,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_eTSEC1, MPC85xx_eTSEC2, MPC85xx_eTSEC3,
+ MPC85xx_eTSEC4, MPC85xx_IIC1, MPC85xx_IIC2,
+ MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+ MPC85xx_PERFMON, MPC85xx_DUART, MPC85xx_SEC2,
+ },
+ },
+ {
+ .ppc_sys_name = "8548",
+ .mask = 0xFFFF00F0,
+ .value = 0x80310010,
+ .num_devices = 12,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_eTSEC1, MPC85xx_eTSEC2, MPC85xx_eTSEC3,
+ MPC85xx_eTSEC4, MPC85xx_IIC1, MPC85xx_IIC2,
+ MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+ MPC85xx_PERFMON, MPC85xx_DUART,
+ },
+ },
+ {
+ .ppc_sys_name = "8547E",
+ .mask = 0xFFFF00F0,
+ .value = 0x80390010,
+ .num_devices = 13,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_eTSEC1, MPC85xx_eTSEC2, MPC85xx_eTSEC3,
+ MPC85xx_eTSEC4, MPC85xx_IIC1, MPC85xx_IIC2,
+ MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+ MPC85xx_PERFMON, MPC85xx_DUART, MPC85xx_SEC2,
+ },
+ },
+ {
+ .ppc_sys_name = "8547",
+ .mask = 0xFFFF00F0,
+ .value = 0x80310010,
+ .num_devices = 12,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_eTSEC1, MPC85xx_eTSEC2, MPC85xx_eTSEC3,
+ MPC85xx_eTSEC4, MPC85xx_IIC1, MPC85xx_IIC2,
+ MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+ MPC85xx_PERFMON, MPC85xx_DUART,
+ },
+ },
+ {
+ .ppc_sys_name = "8545E",
+ .mask = 0xFFFF00F0,
+ .value = 0x80390010,
+ .num_devices = 11,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_eTSEC1, MPC85xx_eTSEC2,
+ MPC85xx_IIC1, MPC85xx_IIC2,
+ MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+ MPC85xx_PERFMON, MPC85xx_DUART, MPC85xx_SEC2,
+ },
+ },
+ {
+ .ppc_sys_name = "8545",
+ .mask = 0xFFFF00F0,
+ .value = 0x80310010,
+ .num_devices = 10,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_eTSEC1, MPC85xx_eTSEC2,
+ MPC85xx_IIC1, MPC85xx_IIC2,
+ MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+ MPC85xx_PERFMON, MPC85xx_DUART,
+ },
+ },
+ {
+ .ppc_sys_name = "8543E",
+ .mask = 0xFFFF00F0,
+ .value = 0x803A0010,
+ .num_devices = 11,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_eTSEC1, MPC85xx_eTSEC2,
+ MPC85xx_IIC1, MPC85xx_IIC2,
+ MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+ MPC85xx_PERFMON, MPC85xx_DUART, MPC85xx_SEC2,
+ },
+ },
+ {
+ .ppc_sys_name = "8543",
+ .mask = 0xFFFF00F0,
+ .value = 0x80320010,
+ .num_devices = 10,
+ .device_list = (enum ppc_sys_devices[])
+ {
+ MPC85xx_eTSEC1, MPC85xx_eTSEC2,
+ MPC85xx_IIC1, MPC85xx_IIC2,
+ MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+ MPC85xx_PERFMON, MPC85xx_DUART,
+ },
+ },
{ /* default match */
.ppc_sys_name = "",
.mask = 0x00000000,
diff --git a/arch/ppc/syslib/mv64x60.c b/arch/ppc/syslib/mv64x60.c
index 7b241e7876b..cc77177fa1c 100644
--- a/arch/ppc/syslib/mv64x60.c
+++ b/arch/ppc/syslib/mv64x60.c
@@ -17,7 +17,6 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/string.h>
-#include <linux/bootmem.h>
#include <linux/spinlock.h>
#include <linux/mv643xx.h>
diff --git a/arch/ppc/syslib/mv64x60_win.c b/arch/ppc/syslib/mv64x60_win.c
index b6f0f5dcf6e..5b827e2bbe2 100644
--- a/arch/ppc/syslib/mv64x60_win.c
+++ b/arch/ppc/syslib/mv64x60_win.c
@@ -17,7 +17,6 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/string.h>
-#include <linux/bootmem.h>
#include <linux/mv643xx.h>
#include <asm/byteorder.h>
diff --git a/arch/ppc/syslib/ocp.c b/arch/ppc/syslib/ocp.c
index a5156c5179a..e5fd2ae503e 100644
--- a/arch/ppc/syslib/ocp.c
+++ b/arch/ppc/syslib/ocp.c
@@ -68,7 +68,7 @@ static int ocp_inited;
/* Sysfs support */
#define OCP_DEF_ATTR(field, format_string) \
static ssize_t \
-show_##field(struct device *dev, char *buf) \
+show_##field(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct ocp_device *odev = to_ocp_dev(dev); \
\
diff --git a/arch/ppc/syslib/of_device.c b/arch/ppc/syslib/of_device.c
index 46269ed21ae..49c0e34e2d6 100644
--- a/arch/ppc/syslib/of_device.c
+++ b/arch/ppc/syslib/of_device.c
@@ -161,7 +161,7 @@ void of_unregister_driver(struct of_platform_driver *drv)
}
-static ssize_t dev_show_devspec(struct device *dev, char *buf)
+static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
{
struct of_device *ofdev;
diff --git a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c
index 7619e16fcca..b45d8268bf9 100644
--- a/arch/ppc/syslib/open_pic.c
+++ b/arch/ppc/syslib/open_pic.c
@@ -21,7 +21,6 @@
#include <asm/signal.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/prom.h>
#include <asm/sections.h>
#include <asm/open_pic.h>
#include <asm/i8259.h>
@@ -275,7 +274,7 @@ static void __init openpic_enable_sie(void)
}
#endif
-#if defined(CONFIG_EPIC_SERIAL_MODE) || defined(CONFIG_PM)
+#if defined(CONFIG_EPIC_SERIAL_MODE)
static void openpic_reset(void)
{
openpic_setfield(&OpenPIC->Global.Global_Configuration0,
@@ -557,12 +556,10 @@ static void __init openpic_initipi(u_int ipi, u_int pri, u_int vec)
*/
void openpic_cause_IPI(u_int ipi, cpumask_t cpumask)
{
- cpumask_t phys;
DECL_THIS_CPU;
CHECK_THIS_CPU;
check_arg_ipi(ipi);
- phys = physmask(cpumask);
openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi),
cpus_addr(physmask(cpumask))[0]);
}
@@ -995,8 +992,6 @@ int openpic_resume(struct sys_device *sysdev)
return 0;
}
- openpic_reset();
-
/* OpenPIC sometimes seem to need some time to be fully back up... */
do {
openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
diff --git a/arch/ppc/syslib/open_pic2.c b/arch/ppc/syslib/open_pic2.c
index ea26da0d8b6..7e272c51a49 100644
--- a/arch/ppc/syslib/open_pic2.c
+++ b/arch/ppc/syslib/open_pic2.c
@@ -25,7 +25,6 @@
#include <asm/signal.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/prom.h>
#include <asm/sections.h>
#include <asm/open_pic.h>
#include <asm/i8259.h>
diff --git a/arch/ppc/syslib/ppc4xx_kgdb.c b/arch/ppc/syslib/ppc4xx_kgdb.c
deleted file mode 100644
index fe8668bf813..00000000000
--- a/arch/ppc/syslib/ppc4xx_kgdb.c
+++ /dev/null
@@ -1,124 +0,0 @@
-#include <linux/config.h>
-#include <linux/types.h>
-#include <asm/ibm4xx.h>
-#include <linux/kernel.h>
-
-
-
-#define LSR_DR 0x01 /* Data ready */
-#define LSR_OE 0x02 /* Overrun */
-#define LSR_PE 0x04 /* Parity error */
-#define LSR_FE 0x08 /* Framing error */
-#define LSR_BI 0x10 /* Break */
-#define LSR_THRE 0x20 /* Xmit holding register empty */
-#define LSR_TEMT 0x40 /* Xmitter empty */
-#define LSR_ERR 0x80 /* Error */
-
-#include <platforms/4xx/ibm_ocp.h>
-
-extern struct NS16550* COM_PORTS[];
-#ifndef NULL
-#define NULL 0x00
-#endif
-
-static volatile struct NS16550 *kgdb_debugport = NULL;
-
-volatile struct NS16550 *
-NS16550_init(int chan)
-{
- volatile struct NS16550 *com_port;
- int quot;
-#ifdef BASE_BAUD
- quot = BASE_BAUD / 9600;
-#else
- quot = 0x000c; /* 0xc = 9600 baud (on a pc) */
-#endif
-
- com_port = (struct NS16550 *) COM_PORTS[chan];
-
- com_port->lcr = 0x00;
- com_port->ier = 0xFF;
- com_port->ier = 0x00;
- com_port->lcr = com_port->lcr | 0x80; /* Access baud rate */
- com_port->dll = ( quot & 0x00ff ); /* 0xc = 9600 baud */
- com_port->dlm = ( quot & 0xff00 ) >> 8;
- com_port->lcr = 0x03; /* 8 data, 1 stop, no parity */
- com_port->mcr = 0x00; /* RTS/DTR */
- com_port->fcr = 0x07; /* Clear & enable FIFOs */
-
- return( com_port );
-}
-
-
-void
-NS16550_putc(volatile struct NS16550 *com_port, unsigned char c)
-{
- while ((com_port->lsr & LSR_THRE) == 0)
- ;
- com_port->thr = c;
- return;
-}
-
-unsigned char
-NS16550_getc(volatile struct NS16550 *com_port)
-{
- while ((com_port->lsr & LSR_DR) == 0)
- ;
- return (com_port->rbr);
-}
-
-unsigned char
-NS16550_tstc(volatile struct NS16550 *com_port)
-{
- return ((com_port->lsr & LSR_DR) != 0);
-}
-
-
-#if defined(CONFIG_KGDB_TTYS0)
-#define KGDB_PORT 0
-#elif defined(CONFIG_KGDB_TTYS1)
-#define KGDB_PORT 1
-#elif defined(CONFIG_KGDB_TTYS2)
-#define KGDB_PORT 2
-#elif defined(CONFIG_KGDB_TTYS3)
-#define KGDB_PORT 3
-#else
-#error "invalid kgdb_tty port"
-#endif
-
-void putDebugChar( unsigned char c )
-{
- if ( kgdb_debugport == NULL )
- kgdb_debugport = NS16550_init(KGDB_PORT);
- NS16550_putc( kgdb_debugport, c );
-}
-
-int getDebugChar( void )
-{
- if (kgdb_debugport == NULL)
- kgdb_debugport = NS16550_init(KGDB_PORT);
-
- return(NS16550_getc(kgdb_debugport));
-}
-
-void kgdb_interruptible(int enable)
-{
- return;
-}
-
-void putDebugString(char* str)
-{
- while (*str != '\0') {
- putDebugChar(*str);
- str++;
- }
- putDebugChar('\r');
- return;
-}
-
-void
-kgdb_map_scc(void)
-{
- printk("kgdb init \n");
- kgdb_debugport = NS16550_init(KGDB_PORT);
-}
diff --git a/arch/ppc/syslib/ppc83xx_setup.c b/arch/ppc/syslib/ppc83xx_setup.c
index c28f9d67948..602a86891f7 100644
--- a/arch/ppc/syslib/ppc83xx_setup.c
+++ b/arch/ppc/syslib/ppc83xx_setup.c
@@ -23,12 +23,12 @@
#include <linux/serial_core.h>
#include <linux/serial_8250.h>
-#include <asm/prom.h>
#include <asm/time.h>
#include <asm/mpc83xx.h>
#include <asm/mmu.h>
#include <asm/ppc_sys.h>
#include <asm/kgdb.h>
+#include <asm/delay.h>
#include <syslib/ppc83xx_setup.h>
@@ -117,7 +117,34 @@ mpc83xx_early_serial_map(void)
void
mpc83xx_restart(char *cmd)
{
+ volatile unsigned char __iomem *reg;
+ unsigned char tmp;
+
+ reg = ioremap(BCSR_PHYS_ADDR, BCSR_SIZE);
+
local_irq_disable();
+
+ /*
+ * Unlock the BCSR bits so a PRST will update the contents.
+ * Otherwise the reset asserts but doesn't clear.
+ */
+ tmp = in_8(reg + BCSR_MISC_REG3_OFF);
+ tmp |= BCSR_MISC_REG3_CNFLOCK; /* low true, high false */
+ out_8(reg + BCSR_MISC_REG3_OFF, tmp);
+
+ /*
+ * Trigger a reset via a low->high transition of the
+ * PORESET bit.
+ */
+ tmp = in_8(reg + BCSR_MISC_REG2_OFF);
+ tmp &= ~BCSR_MISC_REG2_PORESET;
+ out_8(reg + BCSR_MISC_REG2_OFF, tmp);
+
+ udelay(1);
+
+ tmp |= BCSR_MISC_REG2_PORESET;
+ out_8(reg + BCSR_MISC_REG2_OFF, tmp);
+
for(;;);
}
diff --git a/arch/ppc/syslib/ppc85xx_setup.c b/arch/ppc/syslib/ppc85xx_setup.c
index 152c3ef1312..ca95d79a704 100644
--- a/arch/ppc/syslib/ppc85xx_setup.c
+++ b/arch/ppc/syslib/ppc85xx_setup.c
@@ -23,7 +23,6 @@
#include <linux/serial_core.h>
#include <linux/serial_8250.h>
-#include <asm/prom.h>
#include <asm/time.h>
#include <asm/mpc85xx.h>
#include <asm/immap_85xx.h>
@@ -33,6 +32,8 @@
#include <syslib/ppc85xx_setup.h>
+extern void abort(void);
+
/* Return the amount of memory */
unsigned long __init
mpc85xx_find_end_of_memory(void)
@@ -132,6 +133,12 @@ mpc85xx_halt(void)
}
#ifdef CONFIG_PCI
+
+#if defined(CONFIG_MPC8555_CDS) || defined(CONFIG_MPC8548_CDS)
+extern void mpc85xx_cds_enable_via(struct pci_controller *hose);
+extern void mpc85xx_cds_fixup_via(struct pci_controller *hose);
+#endif
+
static void __init
mpc85xx_setup_pci1(struct pci_controller *hose)
{
@@ -302,8 +309,18 @@ mpc85xx_setup_hose(void)
ppc_md.pci_exclude_device = mpc85xx_exclude_device;
+#if defined(CONFIG_MPC8555_CDS) || defined(CONFIG_MPC8548_CDS)
+ /* Pre pciauto_bus_scan VIA init */
+ mpc85xx_cds_enable_via(hose_a);
+#endif
+
hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno);
+#if defined(CONFIG_MPC8555_CDS) || defined(CONFIG_MPC8548_CDS)
+ /* Post pciauto_bus_scan VIA fixup */
+ mpc85xx_cds_fixup_via(hose_a);
+#endif
+
#ifdef CONFIG_85xx_PCI2
hose_b = pcibios_alloc_controller();
diff --git a/arch/ppc/syslib/prom_init.c b/arch/ppc/syslib/prom_init.c
index 2cee87137f2..7f15136830f 100644
--- a/arch/ppc/syslib/prom_init.c
+++ b/arch/ppc/syslib/prom_init.c
@@ -626,8 +626,18 @@ inspect_node(phandle node, struct device_node *dad,
l = call_prom("package-to-path", 3, 1, node,
mem_start, mem_end - mem_start);
if (l >= 0) {
+ char *p, *ep;
+
np->full_name = PTRUNRELOC((char *) mem_start);
*(char *)(mem_start + l) = 0;
+ /* Fixup an Apple bug where they have bogus \0 chars in the
+ * middle of the path in some properties
+ */
+ for (p = (char *)mem_start, ep = p + l; p < ep; p++)
+ if ((*p) == '\0') {
+ memmove(p, p+1, ep - p);
+ ep--;
+ }
mem_start = ALIGNUL(mem_start + l + 1);
}
diff --git a/arch/ppc/xmon/xmon.c b/arch/ppc/xmon/xmon.c
index 8565f49b8b0..be7869e3946 100644
--- a/arch/ppc/xmon/xmon.c
+++ b/arch/ppc/xmon/xmon.c
@@ -9,6 +9,7 @@
#include <linux/smp.h>
#include <linux/interrupt.h>
#include <linux/bitops.h>
+#include <linux/kallsyms.h>
#include <asm/ptrace.h>
#include <asm/string.h>
#include <asm/prom.h>
@@ -93,8 +94,7 @@ static void take_input(char *);
static unsigned read_spr(int);
static void write_spr(int, unsigned);
static void super_regs(void);
-static void print_sysmap(void);
-static void sysmap_lookup(void);
+static void symbol_lookup(void);
static void remove_bpts(void);
static void insert_bpts(void);
static struct bpt *at_breakpoint(unsigned pc);
@@ -103,7 +103,6 @@ static void cacheflush(void);
#ifdef CONFIG_SMP
static void cpu_cmd(void);
#endif /* CONFIG_SMP */
-static int pretty_print_addr(unsigned long addr);
static void csum(void);
#ifdef CONFIG_BOOTX_TEXT
static void vidcmds(void);
@@ -120,8 +119,6 @@ extern void longjmp(u_int *, int);
extern void xmon_enter(void);
extern void xmon_leave(void);
-extern char* xmon_find_symbol(unsigned long addr, unsigned long* saddr);
-extern unsigned long xmon_symbol_to_addr(char* symbol);
static unsigned start_tb[NR_CPUS][2];
static unsigned stop_tb[NR_CPUS][2];
@@ -148,7 +145,6 @@ Commands:\n\
mm move a block of memory\n\
ms set a block of memory\n\
md compare two blocks of memory\n\
- M print System.map\n\
r print registers\n\
S print special registers\n\
t print backtrace\n\
@@ -175,6 +171,35 @@ extern inline void __delay(unsigned int loops)
"r" (loops) : "ctr");
}
+/* Print an address in numeric and symbolic form (if possible) */
+static void xmon_print_symbol(unsigned long address, const char *mid,
+ const char *after)
+{
+ char *modname;
+ const char *name = NULL;
+ unsigned long offset, size;
+ static char tmpstr[128];
+
+ printf("%.8lx", address);
+ if (setjmp(bus_error_jmp) == 0) {
+ debugger_fault_handler = handle_fault;
+ sync();
+ name = kallsyms_lookup(address, &size, &offset, &modname,
+ tmpstr);
+ sync();
+ /* wait a little while to see if we get a machine check */
+ __delay(200);
+ }
+ debugger_fault_handler = NULL;
+
+ if (name) {
+ printf("%s%s+%#lx/%#lx", mid, name, offset, size);
+ if (modname)
+ printf(" [%s]", modname);
+ }
+ printf("%s", after);
+}
+
static void get_tb(unsigned *p)
{
unsigned hi, lo, hiagain;
@@ -454,7 +479,7 @@ cmds(struct pt_regs *excp)
dump();
break;
case 'l':
- sysmap_lookup();
+ symbol_lookup();
break;
case 'r':
if (excp != NULL)
@@ -466,9 +491,6 @@ cmds(struct pt_regs *excp)
else
excprint(excp);
break;
- case 'M':
- print_sysmap();
- break;
case 'S':
super_regs();
break;
@@ -825,20 +847,19 @@ backtrace(struct pt_regs *excp)
for (; sp != 0; sp = stack[0]) {
if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
break;
- pretty_print_addr(stack[1]);
- printf(" ");
+ printf("[%.8lx] ", stack);
+ xmon_print_symbol(stack[1], " ", "\n");
if (stack[1] == (unsigned) &ret_from_except
|| stack[1] == (unsigned) &ret_from_except_full
|| stack[1] == (unsigned) &ret_from_syscall) {
if (mread(sp+16, &regs, sizeof(regs)) != sizeof(regs))
break;
- printf("\nexception:%x [%x] %x ", regs.trap, sp+16,
+ printf("exception:%x [%x] %x\n", regs.trap, sp+16,
regs.nip);
sp = regs.gpr[1];
if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
break;
}
- printf("\n");
}
}
@@ -859,11 +880,10 @@ excprint(struct pt_regs *fp)
#ifdef CONFIG_SMP
printf("cpu %d: ", smp_processor_id());
#endif /* CONFIG_SMP */
- printf("vector: %x at pc = ", fp->trap);
- pretty_print_addr(fp->nip);
- printf(", lr = ");
- pretty_print_addr(fp->link);
- printf("\nmsr = %x, sp = %x [%x]\n", fp->msr, fp->gpr[1], fp);
+ printf("vector: %x at pc=", fp->trap);
+ xmon_print_symbol(fp->nip, ": ", ", lr=");
+ xmon_print_symbol(fp->link, ": ", "\n");
+ printf("msr = %x, sp = %x [%x]\n", fp->msr, fp->gpr[1], fp);
trap = TRAP(fp);
if (trap == 0x300 || trap == 0x600)
printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr);
@@ -951,24 +971,6 @@ extern char exc_prolog;
extern char dec_exc;
void
-print_sysmap(void)
-{
- extern char *sysmap;
- if ( sysmap ) {
- printf("System.map: \n");
- if( setjmp(bus_error_jmp) == 0 ) {
- debugger_fault_handler = handle_fault;
- sync();
- xmon_puts(sysmap);
- sync();
- }
- debugger_fault_handler = NULL;
- }
- else
- printf("No System.map\n");
-}
-
-void
super_regs(void)
{
int i, cmd;
@@ -1738,7 +1740,7 @@ scanhex(unsigned *vp)
printf("invalid register name '%%%s'\n", regname);
return 0;
} else if (c == '$') {
- static char symname[64];
+ static char symname[128];
int i;
for (i=0; i<63; i++) {
c = inchar();
@@ -1749,7 +1751,14 @@ scanhex(unsigned *vp)
symname[i] = c;
}
symname[i++] = 0;
- *vp = xmon_symbol_to_addr(symname);
+ *vp = 0;
+ if (setjmp(bus_error_jmp) == 0) {
+ debugger_fault_handler = handle_fault;
+ sync();
+ *vp = kallsyms_lookup_name(symname);
+ sync();
+ }
+ debugger_fault_handler = NULL;
if (!(*vp)) {
printf("unknown symbol\n");
return 0;
@@ -1840,169 +1849,34 @@ take_input(char *str)
lineptr = str;
}
-void
-sysmap_lookup(void)
+static void
+symbol_lookup(void)
{
int type = inchar();
unsigned addr;
- static char tmp[64];
- char* cur;
-
- extern char *sysmap;
- extern unsigned long sysmap_size;
- if ( !sysmap || !sysmap_size )
- return;
-
- switch(type) {
- case 'a':
- if (scanhex(&addr)) {
- pretty_print_addr(addr);
- printf("\n");
- }
- termch = 0;
- break;
- case 's':
- getstring(tmp, 64);
- if( setjmp(bus_error_jmp) == 0 ) {
- debugger_fault_handler = handle_fault;
- sync();
- cur = sysmap;
- do {
- cur = strstr(cur, tmp);
- if (cur) {
- static char res[64];
- char *p, *d;
- p = cur;
- while(p > sysmap && *p != 10)
- p--;
- if (*p == 10) p++;
- d = res;
- while(*p && p < (sysmap + sysmap_size) && *p != 10)
- *(d++) = *(p++);
- *(d++) = 0;
- printf("%s\n", res);
- cur++;
- }
- } while (cur);
- sync();
- }
- debugger_fault_handler = NULL;
- termch = 0;
- break;
- }
-}
+ static char tmp[128];
-static int
-pretty_print_addr(unsigned long addr)
-{
- char *sym;
- unsigned long saddr;
-
- printf("%08x", addr);
- sym = xmon_find_symbol(addr, &saddr);
- if (sym)
- printf(" (%s+0x%x)", sym, addr-saddr);
- return (sym != 0);
-}
-
-char*
-xmon_find_symbol(unsigned long addr, unsigned long* saddr)
-{
- static char rbuffer[64];
- char *p, *ep, *limit;
- unsigned long prev, next;
- char* psym;
-
- extern char *sysmap;
- extern unsigned long sysmap_size;
- if ( !sysmap || !sysmap_size )
- return NULL;
-
- prev = 0;
- psym = NULL;
- p = sysmap;
- limit = p + sysmap_size;
- if( setjmp(bus_error_jmp) == 0 ) {
- debugger_fault_handler = handle_fault;
- sync();
- do {
- next = simple_strtoul(p, &p, 16);
- if (next > addr && prev <= addr) {
- if (!psym)
- goto bail;
- ep = rbuffer;
- p = psym;
- while(*p && p < limit && *p == 32)
- p++;
- while(*p && p < limit && *p != 10 && (ep - rbuffer) < 63)
- *(ep++) = *(p++);
- *(ep++) = 0;
- if (saddr)
- *saddr = prev;
- debugger_fault_handler = NULL;
- return rbuffer;
- }
- prev = next;
- psym = p;
- while(*p && p < limit && *p != 10)
- p++;
- if (*p) p++;
- } while(*p && p < limit && next);
-bail:
- sync();
+ switch (type) {
+ case 'a':
+ if (scanhex(&addr))
+ xmon_print_symbol(addr, ": ", "\n");
+ termch = 0;
+ break;
+ case 's':
+ getstring(tmp, 64);
+ if (setjmp(bus_error_jmp) == 0) {
+ debugger_fault_handler = handle_fault;
+ sync();
+ addr = kallsyms_lookup_name(tmp);
+ if (addr)
+ printf("%s: %lx\n", tmp, addr);
+ else
+ printf("Symbol '%s' not found.\n", tmp);
+ sync();
+ }
+ debugger_fault_handler = NULL;
+ termch = 0;
+ break;
}
- debugger_fault_handler = NULL;
- return NULL;
}
-unsigned long
-xmon_symbol_to_addr(char* symbol)
-{
- char *p, *cur;
- char *match = NULL;
- int goodness = 0;
- int result = 0;
-
- extern char *sysmap;
- extern unsigned long sysmap_size;
- if ( !sysmap || !sysmap_size )
- return 0;
-
- if( setjmp(bus_error_jmp) == 0 ) {
- debugger_fault_handler = handle_fault;
- sync();
- cur = sysmap;
- while(cur) {
- cur = strstr(cur, symbol);
- if (cur) {
- int gd = 1;
-
- /* best match if equal, better match if
- * begins with
- */
- if (cur == sysmap || *(cur-1) == ' ') {
- gd++;
- if (cur[strlen(symbol)] == 10)
- gd++;
- }
- if (gd > goodness) {
- match = cur;
- goodness = gd;
- if (gd == 3)
- break;
- }
- cur++;
- }
- }
- if (goodness) {
- p = match;
- while(p > sysmap && *p != 10)
- p--;
- if (*p == 10) p++;
- result = simple_strtoul(p, &p, 16);
- }
- sync();
- }
- debugger_fault_handler = NULL;
- return result;
-}
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
index 5cb343883e4..f804f25232a 100644
--- a/arch/ppc64/Kconfig
+++ b/arch/ppc64/Kconfig
@@ -77,6 +77,10 @@ config PPC_PSERIES
bool " IBM pSeries & new iSeries"
default y
+config PPC_BPA
+ bool " Broadband Processor Architecture"
+ depends on PPC_MULTIPLATFORM
+
config PPC_PMAC
depends on PPC_MULTIPLATFORM
bool " Apple G5 based machines"
@@ -106,6 +110,21 @@ config PPC_OF
bool
default y
+config XICS
+ depends on PPC_PSERIES
+ bool
+ default y
+
+config MPIC
+ depends on PPC_PSERIES || PPC_PMAC || PPC_MAPLE
+ bool
+ default y
+
+config BPA_IIC
+ depends on PPC_BPA
+ bool
+ default y
+
# VMX is pSeries only for now until somebody writes the iSeries
# exception vectors for it
config ALTIVEC
@@ -123,6 +142,23 @@ config PPC_SPLPAR
processors, that is, which share physical processors between
two or more partitions.
+config KEXEC
+ bool "kexec system call (EXPERIMENTAL)"
+ depends on PPC_MULTIPLATFORM && EXPERIMENTAL
+ help
+ kexec is a system call that implements the ability to shutdown your
+ current kernel, and to start another kernel. It is like a reboot
+ but it is indepedent of the system firmware. And like a reboot
+ you can start any kernel with it, not just Linux.
+
+ The name comes from the similiarity to the exec system call.
+
+ It is an ongoing process to be certain the hardware in a machine
+ is properly shutdown, so do not be surprised if this code does not
+ initially work for you. It may help to enable device hotplugging
+ support. As of this writing the exact hardware interface is
+ strongly in flux, so no good recommendation can be made.
+
config IBMVIO
depends on PPC_PSERIES || PPC_ISERIES
bool
@@ -198,13 +234,49 @@ config HMT
This option enables hardware multithreading on RS64 cpus.
pSeries systems p620 and p660 have such a cpu type.
-config DISCONTIGMEM
- bool "Discontiguous Memory Support"
+config ARCH_SELECT_MEMORY_MODEL
+ def_bool y
+
+config ARCH_FLATMEM_ENABLE
+ def_bool y
+ depends on !NUMA
+
+config ARCH_DISCONTIGMEM_ENABLE
+ def_bool y
depends on SMP && PPC_PSERIES
+config ARCH_DISCONTIGMEM_DEFAULT
+ def_bool y
+ depends on ARCH_DISCONTIGMEM_ENABLE
+
+config ARCH_FLATMEM_ENABLE
+ def_bool y
+
+config ARCH_SPARSEMEM_ENABLE
+ def_bool y
+ depends on ARCH_DISCONTIGMEM_ENABLE
+
+source "mm/Kconfig"
+
+config HAVE_ARCH_EARLY_PFN_TO_NID
+ def_bool y
+ depends on NEED_MULTIPLE_NODES
+
+# Some NUMA nodes have memory ranges that span
+# other nodes. Even though a pfn is valid and
+# between a node's start and end pfns, it may not
+# reside on that node.
+#
+# This is a relatively temporary hack that should
+# be able to go away when sparsemem is fully in
+# place
+config NODES_SPAN_OTHER_NODES
+ def_bool y
+ depends on NEED_MULTIPLE_NODES
+
config NUMA
bool "NUMA support"
- depends on DISCONTIGMEM
+ default y if DISCONTIGMEM || SPARSEMEM
config SCHED_SMT
bool "SMT (Hyperthreading) scheduler support"
@@ -215,26 +287,7 @@ config SCHED_SMT
when dealing with POWER5 cpus at a cost of slightly increased
overhead in some places. If unsure say N here.
-config PREEMPT
- bool "Preemptible Kernel"
- help
- This option reduces the latency of the kernel when reacting to
- real-time or interactive events by allowing a low priority process to
- be preempted even if it is in kernel mode executing a system call.
-
- Say Y here if you are building a kernel for a desktop, embedded
- or real-time system. Say N if you are unsure.
-
-config PREEMPT_BKL
- bool "Preempt The Big Kernel Lock"
- depends on PREEMPT
- default y
- help
- This option reduces the latency of the kernel by making the
- big kernel lock preemptible.
-
- Say Y here if you are building a kernel for a desktop system.
- Say N if you are unsure.
+source "kernel/Kconfig.preempt"
config EEH
bool "PCI Extended Error Handling (EEH)" if EMBEDDED
@@ -256,7 +309,7 @@ config MSCHUNKS
config PPC_RTAS
bool
- depends on PPC_PSERIES
+ depends on PPC_PSERIES || PPC_BPA
default y
config RTAS_PROC
@@ -323,7 +376,7 @@ config EISA
bool
config PCI
- bool
+ bool "support for PCI devices" if (EMBEDDED && PPC_ISERIES)
default y
help
Find out whether your system includes a PCI bus. PCI is the name of
diff --git a/arch/ppc64/Makefile b/arch/ppc64/Makefile
index 691f3008e69..731b8475833 100644
--- a/arch/ppc64/Makefile
+++ b/arch/ppc64/Makefile
@@ -35,9 +35,9 @@ CROSS32AS := $(AS) -a32
CROSS32LD := $(LD) -m elf32ppc
CROSS32OBJCOPY := $(OBJCOPY)
endif
-AS := $(AS) -a64
-LD := $(LD) -m elf64ppc
-CC := $(CC) -m64
+override AS += -a64
+override LD += -m elf64ppc
+override CC += -m64
endif
export CROSS32CC CROSS32AS CROSS32LD CROSS32OBJCOPY
@@ -90,12 +90,14 @@ boot := arch/ppc64/boot
boottarget-$(CONFIG_PPC_PSERIES) := zImage zImage.initrd
boottarget-$(CONFIG_PPC_MAPLE) := zImage zImage.initrd
boottarget-$(CONFIG_PPC_ISERIES) := vmlinux.sminitrd vmlinux.initrd vmlinux.sm
+boottarget-$(CONFIG_PPC_BPA) := zImage zImage.initrd
$(boottarget-y): vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
bootimage-$(CONFIG_PPC_PSERIES) := $(boot)/zImage
bootimage-$(CONFIG_PPC_PMAC) := vmlinux
bootimage-$(CONFIG_PPC_MAPLE) := $(boot)/zImage
+bootimage-$(CONFIG_PPC_BPA) := zImage
bootimage-$(CONFIG_PPC_ISERIES) := vmlinux
BOOTIMAGE := $(bootimage-y)
install: vmlinux
diff --git a/arch/ppc64/boot/install.sh b/arch/ppc64/boot/install.sh
index 955c5681db6..cb2d6626b55 100644
--- a/arch/ppc64/boot/install.sh
+++ b/arch/ppc64/boot/install.sh
@@ -22,8 +22,8 @@
# User may have a custom install script
-if [ -x ~/bin/installkernel ]; then exec ~/bin/installkernel "$@"; fi
-if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi
+if [ -x ~/bin/${CROSS_COMPILE}installkernel ]; then exec ~/bin/${CROSS_COMPILE}installkernel "$@"; fi
+if [ -x /sbin/${CROSS_COMPILE}installkernel ]; then exec /sbin/${CROSS_COMPILE}installkernel "$@"; fi
# Default install
diff --git a/arch/ppc64/boot/prom.c b/arch/ppc64/boot/prom.c
index 7b607d1862c..d5218b15824 100644
--- a/arch/ppc64/boot/prom.c
+++ b/arch/ppc64/boot/prom.c
@@ -11,6 +11,23 @@
#include <linux/string.h>
#include <linux/ctype.h>
+extern __u32 __div64_32(unsigned long long *dividend, __u32 divisor);
+
+/* The unnecessary pointer compare is there
+ * to check for type safety (n must be 64bit)
+ */
+# define do_div(n,base) ({ \
+ __u32 __base = (base); \
+ __u32 __rem; \
+ (void)(((typeof((n)) *)0) == ((unsigned long long *)0)); \
+ if (((n) >> 32) == 0) { \
+ __rem = (__u32)(n) % __base; \
+ (n) = (__u32)(n) / __base; \
+ } else \
+ __rem = __div64_32(&(n), __base); \
+ __rem; \
+ })
+
int (*prom)(void *);
void *chosen_handle;
@@ -352,7 +369,7 @@ static int skip_atoi(const char **s)
#define SPECIAL 32 /* 0x */
#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
-static char * number(char * str, long num, int base, int size, int precision, int type)
+static char * number(char * str, unsigned long long num, int base, int size, int precision, int type)
{
char c,sign,tmp[66];
const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
@@ -367,9 +384,9 @@ static char * number(char * str, long num, int base, int size, int precision, in
c = (type & ZEROPAD) ? '0' : ' ';
sign = 0;
if (type & SIGN) {
- if (num < 0) {
+ if ((signed long long)num < 0) {
sign = '-';
- num = -num;
+ num = - (signed long long)num;
size--;
} else if (type & PLUS) {
sign = '+';
@@ -389,8 +406,7 @@ static char * number(char * str, long num, int base, int size, int precision, in
if (num == 0)
tmp[i++]='0';
else while (num != 0) {
- tmp[i++] = digits[num % base];
- num /= base;
+ tmp[i++] = digits[do_div(num, base)];
}
if (i > precision)
precision = i;
@@ -426,7 +442,7 @@ int sprintf(char * buf, const char *fmt, ...);
int vsprintf(char *buf, const char *fmt, va_list args)
{
int len;
- unsigned long num;
+ unsigned long long num;
int i, base;
char * str;
const char *s;
diff --git a/arch/ppc64/configs/g5_defconfig b/arch/ppc64/configs/g5_defconfig
index 0f90df0b3f9..1eb33398648 100644
--- a/arch/ppc64/configs/g5_defconfig
+++ b/arch/ppc64/configs/g5_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11
-# Thu Mar 10 16:47:04 2005
+# Linux kernel version: 2.6.12-rc6
+# Tue Jun 14 16:59:20 2005
#
CONFIG_64BIT=y
CONFIG_MMU=y
@@ -11,7 +11,7 @@ CONFIG_GENERIC_ISA_DMA=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_EARLY_PRINTK=y
CONFIG_COMPAT=y
-CONFIG_FRAME_POINTER=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
CONFIG_FORCE_MAX_ZONEORDER=13
#
@@ -20,6 +20,7 @@ CONFIG_FORCE_MAX_ZONEORDER=13
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -31,19 +32,20 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=17
CONFIG_HOTPLUG=y
CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SHMEM=y
CONFIG_CC_ALIGN_FUNCTIONS=0
CONFIG_CC_ALIGN_LABELS=0
@@ -87,6 +89,8 @@ CONFIG_NR_CPUS=2
# CONFIG_SCHED_SMT is not set
# CONFIG_PREEMPT is not set
CONFIG_GENERIC_HARDIRQS=y
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
#
# General setup
@@ -97,6 +101,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
# CONFIG_HOTPLUG_CPU is not set
#
@@ -105,10 +110,6 @@ CONFIG_PCI_NAMES=y
# CONFIG_PCCARD is not set
#
-# PC-card bridges
-#
-
-#
# PCI Hotplug Support
#
# CONFIG_HOTPLUG_PCI is not set
@@ -293,7 +294,6 @@ CONFIG_SCSI_SATA_SVW=y
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_IPS is not set
@@ -301,7 +301,6 @@ CONFIG_SCSI_SATA_SVW=y
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
CONFIG_SCSI_QLA2XXX=y
@@ -310,6 +309,7 @@ CONFIG_SCSI_QLA2XXX=y
# CONFIG_SCSI_QLA2300 is not set
# CONFIG_SCSI_QLA2322 is not set
# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_DEBUG is not set
@@ -332,6 +332,7 @@ CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_MIRROR=m
CONFIG_DM_ZERO=m
+# CONFIG_DM_MULTIPATH is not set
#
# Fusion MPT device support
@@ -394,7 +395,6 @@ CONFIG_NET=y
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
CONFIG_NET_KEY=m
CONFIG_INET=y
@@ -564,6 +564,8 @@ CONFIG_E1000=y
# CONFIG_R8169 is not set
# CONFIG_SK98LIN is not set
CONFIG_TIGON3=m
+# CONFIG_BNX2 is not set
+# CONFIG_MV643XX_ETH is not set
#
# Ethernet (10000 Mbit)
@@ -631,18 +633,6 @@ CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
@@ -660,6 +650,16 @@ CONFIG_INPUT_MOUSE=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
# Character devices
#
CONFIG_VT=y
@@ -676,6 +676,7 @@ CONFIG_HW_CONSOLE=y
# Non-8250 serial port support
#
# CONFIG_SERIAL_PMACZILOG is not set
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -698,9 +699,12 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# Ftape, the floppy tape device driver
#
+CONFIG_AGP=m
+CONFIG_AGP_UNINORTH=m
# CONFIG_DRM is not set
CONFIG_RAW_DRIVER=y
CONFIG_MAX_RAW_DEVS=256
+# CONFIG_HANGCHECK_TIMER is not set
#
# TPM devices
@@ -730,12 +734,11 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_ISA is not set
CONFIG_I2C_KEYWEST=y
-# CONFIG_I2C_MPC is not set
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_PROSAVAGE is not set
# CONFIG_I2C_SAVAGE4 is not set
# CONFIG_SCx200_ACB is not set
@@ -772,6 +775,7 @@ CONFIG_I2C_KEYWEST=y
# CONFIG_SENSORS_LM85 is not set
# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
@@ -785,6 +789,7 @@ CONFIG_I2C_KEYWEST=y
#
# Other I2C Chip support
#
+# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCF8591 is not set
@@ -817,6 +822,11 @@ CONFIG_I2C_KEYWEST=y
# Graphics support
#
CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+CONFIG_FB_MACMODES=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_TILEBLITTING=y
# CONFIG_FB_CIRRUS is not set
@@ -830,6 +840,7 @@ CONFIG_FB_OF=y
# CONFIG_FB_ASILIANT is not set
# CONFIG_FB_IMSTT is not set
# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_NVIDIA is not set
CONFIG_FB_RIVA=y
# CONFIG_FB_RIVA_I2C is not set
# CONFIG_FB_RIVA_DEBUG is not set
@@ -847,6 +858,7 @@ CONFIG_FB_RADEON_I2C=y
# CONFIG_FB_3DFX is not set
# CONFIG_FB_VOODOO1 is not set
# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
#
@@ -880,6 +892,8 @@ CONFIG_LCD_DEVICE=y
#
# USB support
#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
@@ -890,8 +904,6 @@ CONFIG_USB_DEVICEFS=y
# CONFIG_USB_BANDWIDTH is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
# CONFIG_USB_OTG is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
#
# USB Host Controller Drivers
@@ -917,7 +929,6 @@ CONFIG_USB_PRINTER=y
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
-CONFIG_USB_STORAGE_RW_DETECT=y
CONFIG_USB_STORAGE_DATAFAB=y
CONFIG_USB_STORAGE_FREECOM=y
CONFIG_USB_STORAGE_ISD200=y
@@ -1004,8 +1015,10 @@ CONFIG_USB_MON=y
#
CONFIG_USB_SERIAL=m
CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRPRIME is not set
CONFIG_USB_SERIAL_BELKIN=m
CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+# CONFIG_USB_SERIAL_CP2101 is not set
CONFIG_USB_SERIAL_CYPRESS_M8=m
CONFIG_USB_SERIAL_EMPEG=m
CONFIG_USB_SERIAL_FTDI_SIO=m
@@ -1034,6 +1047,7 @@ CONFIG_USB_SERIAL_KLSI=m
CONFIG_USB_SERIAL_KOBIL_SCT=m
CONFIG_USB_SERIAL_MCT_U232=m
CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_HP4X is not set
CONFIG_USB_SERIAL_SAFE=m
CONFIG_USB_SERIAL_SAFE_PADDED=y
CONFIG_USB_SERIAL_TI=m
@@ -1270,11 +1284,13 @@ CONFIG_OPROFILE=y
#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_MAGIC_SYSRQ=y
-# CONFIG_PRINTK_TIME is not set
+CONFIG_LOG_BUF_SHIFT=17
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_INFO is not set
diff --git a/arch/ppc64/configs/iSeries_defconfig b/arch/ppc64/configs/iSeries_defconfig
index a39e9d2e25d..f6a2b99afd6 100644
--- a/arch/ppc64/configs/iSeries_defconfig
+++ b/arch/ppc64/configs/iSeries_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc3-bk6
-# Wed Feb 9 23:34:52 2005
+# Linux kernel version: 2.6.12-rc6
+# Tue Jun 14 17:01:28 2005
#
CONFIG_64BIT=y
CONFIG_MMU=y
@@ -11,7 +11,7 @@ CONFIG_GENERIC_ISA_DMA=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_EARLY_PRINTK=y
CONFIG_COMPAT=y
-CONFIG_FRAME_POINTER=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
CONFIG_FORCE_MAX_ZONEORDER=13
#
@@ -20,6 +20,7 @@ CONFIG_FORCE_MAX_ZONEORDER=13
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -30,24 +31,29 @@ CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=17
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
CONFIG_HOTPLUG=y
CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SHMEM=y
CONFIG_CC_ALIGN_FUNCTIONS=0
CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -79,6 +85,8 @@ CONFIG_NR_CPUS=32
CONFIG_GENERIC_HARDIRQS=y
CONFIG_MSCHUNKS=y
CONFIG_LPARCFG=y
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
#
# General setup
@@ -89,6 +97,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
@@ -96,10 +105,6 @@ CONFIG_PCI_NAMES=y
# CONFIG_PCCARD is not set
#
-# PC-card bridges
-#
-
-#
# PCI Hotplug Support
#
# CONFIG_HOTPLUG_PCI is not set
@@ -210,7 +215,6 @@ CONFIG_SCSI_FC_ATTRS=y
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_IPS is not set
@@ -219,7 +223,6 @@ CONFIG_SCSI_IBMVSCSI=m
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
CONFIG_SCSI_QLA2XXX=y
@@ -228,6 +231,7 @@ CONFIG_SCSI_QLA2XXX=y
# CONFIG_SCSI_QLA2300 is not set
# CONFIG_SCSI_QLA2322 is not set
# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_DEBUG is not set
@@ -250,6 +254,7 @@ CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_MIRROR=m
CONFIG_DM_ZERO=m
+# CONFIG_DM_MULTIPATH is not set
#
# Fusion MPT device support
@@ -280,7 +285,6 @@ CONFIG_NET=y
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
CONFIG_NET_KEY=m
CONFIG_INET=y
@@ -445,7 +449,6 @@ CONFIG_PCNET32=y
# CONFIG_DGRS is not set
# CONFIG_EEPRO100 is not set
CONFIG_E100=y
-# CONFIG_E100_NAPI is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
# CONFIG_NE2K_PCI is not set
@@ -471,6 +474,7 @@ CONFIG_E1000=m
# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
#
# Ethernet (10000 Mbit)
@@ -539,14 +543,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -556,6 +552,12 @@ CONFIG_SOUND_GAMEPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
# Character devices
#
# CONFIG_SERIAL_NONSTANDARD is not set
@@ -570,6 +572,7 @@ CONFIG_SOUND_GAMEPORT=y
#
CONFIG_SERIAL_CORE=m
CONFIG_SERIAL_ICOM=m
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -592,9 +595,16 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# Ftape, the floppy tape device driver
#
+# CONFIG_AGP is not set
# CONFIG_DRM is not set
CONFIG_RAW_DRIVER=y
CONFIG_MAX_RAW_DEVS=256
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
#
# I2C support
@@ -633,13 +643,9 @@ CONFIG_MAX_RAW_DEVS=256
#
# USB support
#
-# CONFIG_USB is not set
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
#
# USB Gadget Support
@@ -848,10 +854,13 @@ CONFIG_OPROFILE=y
#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=17
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_INFO is not set
@@ -881,6 +890,7 @@ CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_TWOFISH=m
diff --git a/arch/ppc64/configs/maple_defconfig b/arch/ppc64/configs/maple_defconfig
index cf527501915..8051b0f47b6 100644
--- a/arch/ppc64/configs/maple_defconfig
+++ b/arch/ppc64/configs/maple_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc3-bk6
-# Wed Feb 9 23:34:53 2005
+# Linux kernel version: 2.6.12-rc6
+# Tue Jun 14 17:12:48 2005
#
CONFIG_64BIT=y
CONFIG_MMU=y
@@ -11,7 +11,7 @@ CONFIG_GENERIC_ISA_DMA=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_EARLY_PRINTK=y
CONFIG_COMPAT=y
-CONFIG_FRAME_POINTER=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
CONFIG_FORCE_MAX_ZONEORDER=13
#
@@ -20,6 +20,7 @@ CONFIG_FORCE_MAX_ZONEORDER=13
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -30,24 +31,28 @@ CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_AUDIT is not set
# CONFIG_HOTPLUG is not set
CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SHMEM=y
CONFIG_CC_ALIGN_FUNCTIONS=0
CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -84,6 +89,8 @@ CONFIG_NR_CPUS=2
# CONFIG_SCHED_SMT is not set
# CONFIG_PREEMPT is not set
CONFIG_GENERIC_HARDIRQS=y
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
#
# General setup
@@ -94,6 +101,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
@@ -101,10 +109,6 @@ CONFIG_PCI_NAMES=y
# CONFIG_PCCARD is not set
#
-# PC-card bridges
-#
-
-#
# PCI Hotplug Support
#
# CONFIG_HOTPLUG_PCI is not set
@@ -261,7 +265,6 @@ CONFIG_NET=y
#
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
@@ -376,6 +379,8 @@ CONFIG_E1000=y
# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_MV643XX_ETH is not set
#
# Ethernet (10000 Mbit)
@@ -432,14 +437,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=1200
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
-#
# Input Device Drivers
#
# CONFIG_INPUT_KEYBOARD is not set
@@ -449,6 +446,12 @@ CONFIG_SOUND_GAMEPORT=y
# CONFIG_INPUT_MISC is not set
#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
# Character devices
#
CONFIG_VT=y
@@ -469,7 +472,7 @@ CONFIG_SERIAL_8250_NR_UARTS=4
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_PMACZILOG is not set
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -492,8 +495,15 @@ CONFIG_LEGACY_PTY_COUNT=256
#
# Ftape, the floppy tape device driver
#
+# CONFIG_AGP is not set
# CONFIG_DRM is not set
# CONFIG_RAW_DRIVER is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
#
# I2C support
@@ -518,8 +528,8 @@ CONFIG_I2C_ALGOBIT=y
CONFIG_I2C_AMD8111=y
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_ISA is not set
-# CONFIG_I2C_MPC is not set
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
# CONFIG_I2C_PROSAVAGE is not set
@@ -545,7 +555,9 @@ CONFIG_I2C_AMD8111=y
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
# CONFIG_SENSORS_LM63 is not set
# CONFIG_SENSORS_LM75 is not set
@@ -556,9 +568,11 @@ CONFIG_I2C_AMD8111=y
# CONFIG_SENSORS_LM85 is not set
# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_W83781D is not set
@@ -568,6 +582,7 @@ CONFIG_I2C_AMD8111=y
#
# Other I2C Chip support
#
+# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCF8591 is not set
@@ -615,6 +630,8 @@ CONFIG_DUMMY_CONSOLE=y
#
# USB support
#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
@@ -625,8 +642,6 @@ CONFIG_USB_DEVICEFS=y
# CONFIG_USB_BANDWIDTH is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
# CONFIG_USB_OTG is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
#
# USB Host Controller Drivers
@@ -635,6 +650,8 @@ CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_SPLIT_ISO=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
CONFIG_USB_UHCI_HCD=y
# CONFIG_USB_SL811_HCD is not set
@@ -688,6 +705,7 @@ CONFIG_USB_HIDINPUT=y
CONFIG_USB_PEGASUS=y
# CONFIG_USB_RTL8150 is not set
# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
#
# USB port drivers
@@ -699,8 +717,10 @@ CONFIG_USB_PEGASUS=y
CONFIG_USB_SERIAL=y
# CONFIG_USB_SERIAL_CONSOLE is not set
CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRPRIME is not set
# CONFIG_USB_SERIAL_BELKIN is not set
# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP2101 is not set
CONFIG_USB_SERIAL_CYPRESS_M8=m
# CONFIG_USB_SERIAL_EMPEG is not set
# CONFIG_USB_SERIAL_FTDI_SIO is not set
@@ -729,6 +749,7 @@ CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
# CONFIG_USB_SERIAL_KOBIL_SCT is not set
# CONFIG_USB_SERIAL_MCT_U232 is not set
# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_HP4X is not set
# CONFIG_USB_SERIAL_SAFE is not set
CONFIG_USB_SERIAL_TI=m
# CONFIG_USB_SERIAL_CYBERJACK is not set
@@ -750,6 +771,7 @@ CONFIG_USB_EZUSB=y
# CONFIG_USB_PHIDGETKIT is not set
# CONFIG_USB_PHIDGETSERVO is not set
# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_TEST is not set
#
@@ -936,10 +958,13 @@ CONFIG_NLS_UTF8=y
#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=17
# CONFIG_SCHEDSTATS is not set
CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SPINLOCK is not set
CONFIG_DEBUG_SPINLOCK_SLEEP=y
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_INFO is not set
@@ -971,6 +996,7 @@ CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
# CONFIG_CRYPTO_WP512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_TWOFISH is not set
diff --git a/arch/ppc64/configs/pSeries_defconfig b/arch/ppc64/configs/pSeries_defconfig
index 4fecf237d5c..d0db8b5966c 100644
--- a/arch/ppc64/configs/pSeries_defconfig
+++ b/arch/ppc64/configs/pSeries_defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc3-bk6
-# Wed Feb 9 23:34:54 2005
+# Linux kernel version: 2.6.12-rc6
+# Tue Jun 14 17:13:47 2005
#
CONFIG_64BIT=y
CONFIG_MMU=y
@@ -11,7 +11,7 @@ CONFIG_GENERIC_ISA_DMA=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_EARLY_PRINTK=y
CONFIG_COMPAT=y
-CONFIG_FRAME_POINTER=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
CONFIG_FORCE_MAX_ZONEORDER=13
#
@@ -20,6 +20,7 @@ CONFIG_FORCE_MAX_ZONEORDER=13
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -30,24 +31,29 @@ CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=17
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
CONFIG_HOTPLUG=y
CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_CPUSETS=y
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SHMEM=y
CONFIG_CC_ALIGN_FUNCTIONS=0
CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -82,16 +88,19 @@ CONFIG_IBMVIO=y
CONFIG_IOMMU_VMERGE=y
CONFIG_SMP=y
CONFIG_NR_CPUS=128
-CONFIG_DISCONTIGMEM=y
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
CONFIG_NUMA=y
CONFIG_SCHED_SMT=y
# CONFIG_PREEMPT is not set
CONFIG_EEH=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_PPC_RTAS=y
+CONFIG_RTAS_PROC=y
CONFIG_RTAS_FLASH=m
CONFIG_SCANLOG=m
CONFIG_LPARCFG=y
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
#
# General setup
@@ -102,6 +111,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_BINFMT_MISC is not set
CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
CONFIG_HOTPLUG_CPU=y
#
@@ -110,10 +120,6 @@ CONFIG_HOTPLUG_CPU=y
# CONFIG_PCCARD is not set
#
-# PC-card bridges
-#
-
-#
# PCI Hotplug Support
#
CONFIG_HOTPLUG_PCI=m
@@ -147,11 +153,10 @@ CONFIG_FW_LOADER=y
#
CONFIG_PARPORT=m
CONFIG_PARPORT_PC=m
-CONFIG_PARPORT_PC_CML1=m
# CONFIG_PARPORT_SERIAL is not set
# CONFIG_PARPORT_PC_FIFO is not set
# CONFIG_PARPORT_PC_SUPERIO is not set
-# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_GSC is not set
# CONFIG_PARPORT_1284 is not set
#
@@ -293,7 +298,6 @@ CONFIG_SCSI_ISCSI_ATTRS=m
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_IPS is not set
@@ -310,7 +314,6 @@ CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
CONFIG_SCSI_IPR=y
CONFIG_SCSI_IPR_TRACE=y
CONFIG_SCSI_IPR_DUMP=y
-# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
CONFIG_SCSI_QLA2XXX=y
@@ -319,6 +322,7 @@ CONFIG_SCSI_QLA22XX=m
CONFIG_SCSI_QLA2300=m
CONFIG_SCSI_QLA2322=m
CONFIG_SCSI_QLA6312=m
+CONFIG_SCSI_LPFC=m
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_DEBUG is not set
@@ -341,6 +345,8 @@ CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_MIRROR=m
CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
#
# Fusion MPT device support
@@ -371,7 +377,6 @@ CONFIG_NET=y
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
CONFIG_NET_KEY=m
CONFIG_INET=y
@@ -539,7 +544,6 @@ CONFIG_PCNET32=y
# CONFIG_DGRS is not set
# CONFIG_EEPRO100 is not set
CONFIG_E100=y
-# CONFIG_E100_NAPI is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
# CONFIG_NE2K_PCI is not set
@@ -565,6 +569,8 @@ CONFIG_E1000=y
# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
CONFIG_TIGON3=y
+# CONFIG_BNX2 is not set
+# CONFIG_MV643XX_ETH is not set
#
# Ethernet (10000 Mbit)
@@ -636,20 +642,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PARKBD is not set
-# CONFIG_SERIO_PCIPS2 is not set
-CONFIG_SERIO_LIBPS2=y
-# CONFIG_SERIO_RAW is not set
-
-#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
@@ -669,6 +661,18 @@ CONFIG_INPUT_PCSPKR=m
# CONFIG_INPUT_UINPUT is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
# Character devices
#
CONFIG_VT=y
@@ -689,8 +693,8 @@ CONFIG_SERIAL_8250_NR_UARTS=4
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_PMACZILOG is not set
CONFIG_SERIAL_ICOM=m
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -718,9 +722,16 @@ CONFIG_HVCS=m
#
# Ftape, the floppy tape device driver
#
+# CONFIG_AGP is not set
# CONFIG_DRM is not set
CONFIG_RAW_DRIVER=y
CONFIG_MAX_RAW_DEVS=1024
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
#
# I2C support
@@ -745,8 +756,8 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_ISA is not set
-# CONFIG_I2C_MPC is not set
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_PARPORT is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
@@ -773,7 +784,9 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
# CONFIG_SENSORS_LM63 is not set
# CONFIG_SENSORS_LM75 is not set
@@ -784,9 +797,11 @@ CONFIG_I2C_ALGOBIT=y
# CONFIG_SENSORS_LM85 is not set
# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_W83781D is not set
@@ -796,6 +811,7 @@ CONFIG_I2C_ALGOBIT=y
#
# Other I2C Chip support
#
+# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCF8591 is not set
@@ -828,8 +844,13 @@ CONFIG_I2C_ALGOBIT=y
# Graphics support
#
CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+CONFIG_FB_MACMODES=y
CONFIG_FB_MODE_HELPERS=y
-# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_TILEBLITTING=y
# CONFIG_FB_CIRRUS is not set
# CONFIG_FB_PM2 is not set
# CONFIG_FB_CYBER2000 is not set
@@ -838,6 +859,7 @@ CONFIG_FB_OF=y
# CONFIG_FB_ASILIANT is not set
# CONFIG_FB_IMSTT is not set
# CONFIG_FB_VGA16 is not set
+# CONFIG_FB_NVIDIA is not set
# CONFIG_FB_RIVA is not set
CONFIG_FB_MATROX=y
CONFIG_FB_MATROX_MILLENIUM=y
@@ -858,6 +880,7 @@ CONFIG_FB_RADEON_I2C=y
# CONFIG_FB_3DFX is not set
# CONFIG_FB_VOODOO1 is not set
# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
#
@@ -891,6 +914,8 @@ CONFIG_LCD_DEVICE=y
#
# USB support
#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
@@ -901,8 +926,6 @@ CONFIG_USB_DEVICEFS=y
# CONFIG_USB_BANDWIDTH is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
# CONFIG_USB_OTG is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
#
# USB Host Controller Drivers
@@ -911,6 +934,8 @@ CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_SPLIT_ISO is not set
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_UHCI_HCD is not set
# CONFIG_USB_SL811_HCD is not set
@@ -926,12 +951,11 @@ CONFIG_USB_OHCI_HCD=y
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_RW_DETECT is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
# CONFIG_USB_STORAGE_DPCM is not set
-# CONFIG_USB_STORAGE_HP8200e is not set
+# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
# CONFIG_USB_STORAGE_JUMPSHOT is not set
@@ -975,6 +999,7 @@ CONFIG_USB_HIDDEV=y
# CONFIG_USB_PEGASUS is not set
# CONFIG_USB_RTL8150 is not set
# CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
#
# USB port drivers
@@ -1000,6 +1025,7 @@ CONFIG_USB_HIDDEV=y
# CONFIG_USB_PHIDGETKIT is not set
# CONFIG_USB_PHIDGETSERVO is not set
# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_TEST is not set
#
@@ -1208,10 +1234,13 @@ CONFIG_OPROFILE=y
#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=17
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_INFO is not set
@@ -1243,6 +1272,7 @@ CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_TWOFISH=m
diff --git a/arch/ppc64/defconfig b/arch/ppc64/defconfig
index 537b1cc82ea..b8e2066dde7 100644
--- a/arch/ppc64/defconfig
+++ b/arch/ppc64/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc3-bk6
-# Wed Feb 9 23:34:51 2005
+# Linux kernel version: 2.6.12-rc5-git9
+# Sun Jun 5 09:26:47 2005
#
CONFIG_64BIT=y
CONFIG_MMU=y
@@ -11,7 +11,7 @@ CONFIG_GENERIC_ISA_DMA=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_EARLY_PRINTK=y
CONFIG_COMPAT=y
-CONFIG_FRAME_POINTER=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
CONFIG_FORCE_MAX_ZONEORDER=13
#
@@ -20,6 +20,7 @@ CONFIG_FORCE_MAX_ZONEORDER=13
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -30,24 +31,28 @@ CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_AUDIT is not set
CONFIG_HOTPLUG=y
CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
+CONFIG_CPUSETS=y
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SHMEM=y
CONFIG_CC_ALIGN_FUNCTIONS=0
CONFIG_CC_ALIGN_LABELS=0
CONFIG_CC_ALIGN_LOOPS=0
CONFIG_CC_ALIGN_JUMPS=0
# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
#
# Loadable module support
@@ -84,16 +89,19 @@ CONFIG_BOOTX_TEXT=y
CONFIG_IOMMU_VMERGE=y
CONFIG_SMP=y
CONFIG_NR_CPUS=32
-CONFIG_DISCONTIGMEM=y
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
# CONFIG_NUMA is not set
# CONFIG_SCHED_SMT is not set
# CONFIG_PREEMPT is not set
CONFIG_EEH=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_PPC_RTAS=y
+CONFIG_RTAS_PROC=y
CONFIG_RTAS_FLASH=m
CONFIG_SCANLOG=m
CONFIG_LPARCFG=y
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
#
# General setup
@@ -104,6 +112,7 @@ CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_MISC=m
# CONFIG_PCI_LEGACY_PROC is not set
# CONFIG_PCI_NAMES is not set
+# CONFIG_PCI_DEBUG is not set
CONFIG_HOTPLUG_CPU=y
#
@@ -112,10 +121,6 @@ CONFIG_HOTPLUG_CPU=y
# CONFIG_PCCARD is not set
#
-# PC-card bridges
-#
-
-#
# PCI Hotplug Support
#
CONFIG_HOTPLUG_PCI=m
@@ -149,11 +154,10 @@ CONFIG_FW_LOADER=y
#
CONFIG_PARPORT=m
CONFIG_PARPORT_PC=m
-CONFIG_PARPORT_PC_CML1=m
# CONFIG_PARPORT_SERIAL is not set
# CONFIG_PARPORT_PC_FIFO is not set
# CONFIG_PARPORT_PC_SUPERIO is not set
-# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_GSC is not set
# CONFIG_PARPORT_1284 is not set
#
@@ -301,6 +305,7 @@ CONFIG_SCSI_SATA_SVW=y
# CONFIG_SCSI_ATA_PIIX is not set
# CONFIG_SCSI_SATA_NV is not set
# CONFIG_SCSI_SATA_PROMISE is not set
+# CONFIG_SCSI_SATA_QSTOR is not set
# CONFIG_SCSI_SATA_SX4 is not set
# CONFIG_SCSI_SATA_SIL is not set
# CONFIG_SCSI_SATA_SIS is not set
@@ -310,7 +315,6 @@ CONFIG_SCSI_SATA_SVW=y
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_IPS is not set
@@ -327,7 +331,6 @@ CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
CONFIG_SCSI_IPR=y
CONFIG_SCSI_IPR_TRACE=y
CONFIG_SCSI_IPR_DUMP=y
-# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
CONFIG_SCSI_QLA2XXX=y
@@ -336,6 +339,7 @@ CONFIG_SCSI_QLA22XX=m
CONFIG_SCSI_QLA2300=m
CONFIG_SCSI_QLA2322=m
CONFIG_SCSI_QLA6312=m
+CONFIG_SCSI_LPFC=m
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
CONFIG_SCSI_DEBUG=m
@@ -358,6 +362,8 @@ CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_MIRROR=m
CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
#
# Fusion MPT device support
@@ -405,6 +411,7 @@ CONFIG_IEEE1394_AMDTP=m
#
CONFIG_ADB=y
CONFIG_ADB_PMU=y
+CONFIG_PMAC_SMU=y
# CONFIG_PMAC_PBOOK is not set
# CONFIG_PMAC_BACKLIGHT is not set
# CONFIG_INPUT_ADBHID is not set
@@ -420,7 +427,6 @@ CONFIG_NET=y
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
CONFIG_NET_KEY=m
CONFIG_INET=y
@@ -588,7 +594,6 @@ CONFIG_PCNET32=y
# CONFIG_DGRS is not set
# CONFIG_EEPRO100 is not set
CONFIG_E100=y
-# CONFIG_E100_NAPI is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
# CONFIG_NE2K_PCI is not set
@@ -614,6 +619,8 @@ CONFIG_E1000=y
# CONFIG_SK98LIN is not set
# CONFIG_VIA_VELOCITY is not set
CONFIG_TIGON3=y
+# CONFIG_BNX2 is not set
+# CONFIG_MV643XX_ETH is not set
#
# Ethernet (10000 Mbit)
@@ -683,20 +690,6 @@ CONFIG_INPUT_EVDEV=m
# CONFIG_INPUT_EVBUG is not set
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PARKBD is not set
-# CONFIG_SERIO_PCIPS2 is not set
-CONFIG_SERIO_LIBPS2=y
-# CONFIG_SERIO_RAW is not set
-
-#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
@@ -716,6 +709,18 @@ CONFIG_INPUT_PCSPKR=m
# CONFIG_INPUT_UINPUT is not set
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
# Character devices
#
CONFIG_VT=y
@@ -738,6 +743,7 @@ CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_PMACZILOG is not set
CONFIG_SERIAL_ICOM=m
+CONFIG_SERIAL_JSM=m
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -766,9 +772,16 @@ CONFIG_HVCS=m
#
# Ftape, the floppy tape device driver
#
+# CONFIG_AGP is not set
# CONFIG_DRM is not set
CONFIG_RAW_DRIVER=y
CONFIG_MAX_RAW_DEVS=256
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
#
# I2C support
@@ -793,9 +806,9 @@ CONFIG_I2C_ALGOBIT=y
CONFIG_I2C_AMD8111=y
# CONFIG_I2C_I801 is not set
# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_ISA is not set
CONFIG_I2C_KEYWEST=y
-# CONFIG_I2C_MPC is not set
# CONFIG_I2C_NFORCE2 is not set
# CONFIG_I2C_PARPORT is not set
# CONFIG_I2C_PARPORT_LIGHT is not set
@@ -822,7 +835,9 @@ CONFIG_I2C_KEYWEST=y
# CONFIG_SENSORS_ASB100 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
# CONFIG_SENSORS_LM63 is not set
# CONFIG_SENSORS_LM75 is not set
@@ -833,9 +848,11 @@ CONFIG_I2C_KEYWEST=y
# CONFIG_SENSORS_LM85 is not set
# CONFIG_SENSORS_LM87 is not set
# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_VIA686A is not set
# CONFIG_SENSORS_W83781D is not set
@@ -845,6 +862,7 @@ CONFIG_I2C_KEYWEST=y
#
# Other I2C Chip support
#
+# CONFIG_SENSORS_DS1337 is not set
# CONFIG_SENSORS_EEPROM is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_SENSORS_PCF8591 is not set
@@ -877,6 +895,11 @@ CONFIG_I2C_KEYWEST=y
# Graphics support
#
CONFIG_FB=y
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+CONFIG_FB_SOFT_CURSOR=y
+CONFIG_FB_MACMODES=y
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_TILEBLITTING=y
# CONFIG_FB_CIRRUS is not set
@@ -890,9 +913,8 @@ CONFIG_FB_OF=y
# CONFIG_FB_ASILIANT is not set
# CONFIG_FB_IMSTT is not set
# CONFIG_FB_VGA16 is not set
-CONFIG_FB_RIVA=y
-CONFIG_FB_RIVA_I2C=y
-# CONFIG_FB_RIVA_DEBUG is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
CONFIG_FB_MATROX=y
CONFIG_FB_MATROX_MILLENIUM=y
CONFIG_FB_MATROX_MYSTIQUE=y
@@ -913,6 +935,7 @@ CONFIG_FB_RADEON_I2C=y
# CONFIG_FB_3DFX is not set
# CONFIG_FB_VOODOO1 is not set
# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
#
@@ -946,6 +969,8 @@ CONFIG_LCD_DEVICE=y
#
# USB support
#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
@@ -956,8 +981,6 @@ CONFIG_USB_DEVICEFS=y
# CONFIG_USB_BANDWIDTH is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
# CONFIG_USB_OTG is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
#
# USB Host Controller Drivers
@@ -966,6 +989,8 @@ CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_SPLIT_ISO is not set
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
# CONFIG_USB_UHCI_HCD is not set
# CONFIG_USB_SL811_HCD is not set
@@ -981,12 +1006,11 @@ CONFIG_USB_OHCI_HCD=y
#
CONFIG_USB_STORAGE=m
# CONFIG_USB_STORAGE_DEBUG is not set
-CONFIG_USB_STORAGE_RW_DETECT=y
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
# CONFIG_USB_STORAGE_DPCM is not set
-# CONFIG_USB_STORAGE_HP8200e is not set
+# CONFIG_USB_STORAGE_USBAT is not set
# CONFIG_USB_STORAGE_SDDR09 is not set
# CONFIG_USB_STORAGE_SDDR55 is not set
# CONFIG_USB_STORAGE_JUMPSHOT is not set
@@ -1030,6 +1054,7 @@ CONFIG_USB_HIDDEV=y
CONFIG_USB_PEGASUS=y
# CONFIG_USB_RTL8150 is not set
# CONFIG_USB_USBNET is not set
+# CONFIG_USB_MON is not set
#
# USB port drivers
@@ -1055,6 +1080,7 @@ CONFIG_USB_PEGASUS=y
# CONFIG_USB_PHIDGETKIT is not set
# CONFIG_USB_PHIDGETSERVO is not set
# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_SISUSBVGA is not set
# CONFIG_USB_TEST is not set
#
@@ -1276,10 +1302,13 @@ CONFIG_OPROFILE=y
#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=17
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_KOBJECT is not set
# CONFIG_DEBUG_INFO is not set
@@ -1311,6 +1340,7 @@ CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=m
CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_TWOFISH=m
diff --git a/arch/ppc64/kernel/HvLpEvent.c b/arch/ppc64/kernel/HvLpEvent.c
index f8f19637f73..90032b13890 100644
--- a/arch/ppc64/kernel/HvLpEvent.c
+++ b/arch/ppc64/kernel/HvLpEvent.c
@@ -12,7 +12,7 @@
#include <asm/system.h>
#include <asm/iSeries/HvLpEvent.h>
#include <asm/iSeries/HvCallEvent.h>
-#include <asm/iSeries/LparData.h>
+#include <asm/iSeries/ItLpNaca.h>
/* Array of LpEvent handler functions */
LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes];
diff --git a/arch/ppc64/kernel/ItLpQueue.c b/arch/ppc64/kernel/ItLpQueue.c
index c923a815760..cdea00d7707 100644
--- a/arch/ppc64/kernel/ItLpQueue.c
+++ b/arch/ppc64/kernel/ItLpQueue.c
@@ -16,7 +16,6 @@
#include <asm/iSeries/ItLpQueue.h>
#include <asm/iSeries/HvLpEvent.h>
#include <asm/iSeries/HvCallEvent.h>
-#include <asm/iSeries/LparData.h>
static __inline__ int set_inUse( struct ItLpQueue * lpQueue )
{
diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
index 96d90b0c511..d9b2660ef22 100644
--- a/arch/ppc64/kernel/Makefile
+++ b/arch/ppc64/kernel/Makefile
@@ -16,29 +16,33 @@ obj-y += vdso32/ vdso64/
obj-$(CONFIG_PPC_OF) += of_device.o
-pci-obj-$(CONFIG_PPC_ISERIES) += iSeries_pci.o iSeries_pci_reset.o
+pci-obj-$(CONFIG_PPC_ISERIES) += iSeries_pci.o iSeries_irq.o \
+ iSeries_VpdInfo.o
pci-obj-$(CONFIG_PPC_MULTIPLATFORM) += pci_dn.o pci_direct_iommu.o
obj-$(CONFIG_PCI) += pci.o pci_iommu.o iomap.o $(pci-obj-y)
-obj-$(CONFIG_PPC_ISERIES) += iSeries_irq.o \
- iSeries_VpdInfo.o XmPciLpEvent.o \
- HvCall.o HvLpConfig.o LparData.o \
+obj-$(CONFIG_PPC_ISERIES) += HvCall.o HvLpConfig.o LparData.o \
iSeries_setup.o ItLpQueue.o hvCall.o \
mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \
iSeries_iommu.o
-obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o prom_init.o prom.o mpic.o
+obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o prom_init.o prom.o
obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \
pSeries_nvram.o rtasd.o ras.o pSeries_reconfig.o \
- xics.o rtas.o pSeries_setup.o pSeries_iommu.o
+ pSeries_setup.o pSeries_iommu.o
+obj-$(CONFIG_PPC_BPA) += bpa_setup.o bpa_iommu.o bpa_nvram.o \
+ bpa_iic.o spider-pic.o
+
+obj-$(CONFIG_KEXEC) += machine_kexec.o
obj-$(CONFIG_EEH) += eeh.o
obj-$(CONFIG_PROC_FS) += proc_ppc64.o
obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o
+obj-$(CONFIG_PPC_RTAS) += rtas.o rtas_pci.o
obj-$(CONFIG_RTAS_PROC) += rtas-proc.o
obj-$(CONFIG_SCANLOG) += scanlog.o
obj-$(CONFIG_VIOPATH) += viopath.o
@@ -47,6 +51,8 @@ obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o
obj-$(CONFIG_BOOTX_TEXT) += btext.o
obj-$(CONFIG_HVCS) += hvcserver.o
obj-$(CONFIG_IBMVIO) += vio.o
+obj-$(CONFIG_XICS) += xics.o
+obj-$(CONFIG_MPIC) += mpic.o
obj-$(CONFIG_PPC_PMAC) += pmac_setup.o pmac_feature.o pmac_pci.o \
pmac_time.o pmac_nvram.o pmac_low_i2c.o
@@ -59,6 +65,7 @@ ifdef CONFIG_SMP
obj-$(CONFIG_PPC_PMAC) += pmac_smp.o smp-tbsync.o
obj-$(CONFIG_PPC_ISERIES) += iSeries_smp.o
obj-$(CONFIG_PPC_PSERIES) += pSeries_smp.o
+obj-$(CONFIG_PPC_BPA) += pSeries_smp.o
obj-$(CONFIG_PPC_MAPLE) += smp-tbsync.o
endif
diff --git a/arch/ppc64/kernel/XmPciLpEvent.c b/arch/ppc64/kernel/XmPciLpEvent.c
deleted file mode 100644
index 809c9bc6678..00000000000
--- a/arch/ppc64/kernel/XmPciLpEvent.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * File XmPciLpEvent.h created by Wayne Holm on Mon Jan 15 2001.
- *
- * This module handles PCI interrupt events sent by the iSeries Hypervisor.
-*/
-
-#include <linux/config.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/threads.h>
-#include <linux/smp.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/bootmem.h>
-#include <linux/ide.h>
-
-#include <asm/iSeries/HvTypes.h>
-#include <asm/iSeries/HvLpEvent.h>
-#include <asm/iSeries/HvCallPci.h>
-#include <asm/iSeries/XmPciLpEvent.h>
-#include <asm/ppcdebug.h>
-
-static long Pci_Interrupt_Count;
-static long Pci_Event_Count;
-
-enum XmPciLpEvent_Subtype {
- XmPciLpEvent_BusCreated = 0, // PHB has been created
- XmPciLpEvent_BusError = 1, // PHB has failed
- XmPciLpEvent_BusFailed = 2, // Msg to Secondary, Primary failed bus
- XmPciLpEvent_NodeFailed = 4, // Multi-adapter bridge has failed
- XmPciLpEvent_NodeRecovered = 5, // Multi-adapter bridge has recovered
- XmPciLpEvent_BusRecovered = 12, // PHB has been recovered
- XmPciLpEvent_UnQuiesceBus = 18, // Secondary bus unqiescing
- XmPciLpEvent_BridgeError = 21, // Bridge Error
- XmPciLpEvent_SlotInterrupt = 22 // Slot interrupt
-};
-
-struct XmPciLpEvent_BusInterrupt {
- HvBusNumber busNumber;
- HvSubBusNumber subBusNumber;
-};
-
-struct XmPciLpEvent_NodeInterrupt {
- HvBusNumber busNumber;
- HvSubBusNumber subBusNumber;
- HvAgentId deviceId;
-};
-
-struct XmPciLpEvent {
- struct HvLpEvent hvLpEvent;
-
- union {
- u64 alignData; // Align on an 8-byte boundary
-
- struct {
- u32 fisr;
- HvBusNumber busNumber;
- HvSubBusNumber subBusNumber;
- HvAgentId deviceId;
- } slotInterrupt;
-
- struct XmPciLpEvent_BusInterrupt busFailed;
- struct XmPciLpEvent_BusInterrupt busRecovered;
- struct XmPciLpEvent_BusInterrupt busCreated;
-
- struct XmPciLpEvent_NodeInterrupt nodeFailed;
- struct XmPciLpEvent_NodeInterrupt nodeRecovered;
-
- } eventData;
-
-};
-
-static void intReceived(struct XmPciLpEvent *eventParm,
- struct pt_regs *regsParm);
-
-static void XmPciLpEvent_handler(struct HvLpEvent *eventParm,
- struct pt_regs *regsParm)
-{
-#ifdef CONFIG_PCI
-#if 0
- PPCDBG(PPCDBG_BUSWALK, "XmPciLpEvent_handler, type 0x%x\n",
- eventParm->xType);
-#endif
- ++Pci_Event_Count;
-
- if (eventParm && (eventParm->xType == HvLpEvent_Type_PciIo)) {
- switch (eventParm->xFlags.xFunction) {
- case HvLpEvent_Function_Int:
- intReceived((struct XmPciLpEvent *)eventParm, regsParm);
- break;
- case HvLpEvent_Function_Ack:
- printk(KERN_ERR
- "XmPciLpEvent.c: unexpected ack received\n");
- break;
- default:
- printk(KERN_ERR
- "XmPciLpEvent.c: unexpected event function %d\n",
- (int)eventParm->xFlags.xFunction);
- break;
- }
- } else if (eventParm)
- printk(KERN_ERR
- "XmPciLpEvent.c: Unrecognized PCI event type 0x%x\n",
- (int)eventParm->xType);
- else
- printk(KERN_ERR "XmPciLpEvent.c: NULL event received\n");
-#endif
-}
-
-static void intReceived(struct XmPciLpEvent *eventParm,
- struct pt_regs *regsParm)
-{
- int irq;
-
- ++Pci_Interrupt_Count;
-#if 0
- PPCDBG(PPCDBG_BUSWALK, "PCI: XmPciLpEvent.c: intReceived\n");
-#endif
-
- switch (eventParm->hvLpEvent.xSubtype) {
- case XmPciLpEvent_SlotInterrupt:
- irq = eventParm->hvLpEvent.xCorrelationToken;
- /* Dispatch the interrupt handlers for this irq */
- ppc_irq_dispatch_handler(regsParm, irq);
- HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber,
- eventParm->eventData.slotInterrupt.subBusNumber,
- eventParm->eventData.slotInterrupt.deviceId);
- break;
- /* Ignore error recovery events for now */
- case XmPciLpEvent_BusCreated:
- printk(KERN_INFO "XmPciLpEvent.c: system bus %d created\n",
- eventParm->eventData.busCreated.busNumber);
- break;
- case XmPciLpEvent_BusError:
- case XmPciLpEvent_BusFailed:
- printk(KERN_INFO "XmPciLpEvent.c: system bus %d failed\n",
- eventParm->eventData.busFailed.busNumber);
- break;
- case XmPciLpEvent_BusRecovered:
- case XmPciLpEvent_UnQuiesceBus:
- printk(KERN_INFO "XmPciLpEvent.c: system bus %d recovered\n",
- eventParm->eventData.busRecovered.busNumber);
- break;
- case XmPciLpEvent_NodeFailed:
- case XmPciLpEvent_BridgeError:
- printk(KERN_INFO
- "XmPciLpEvent.c: multi-adapter bridge %d/%d/%d failed\n",
- eventParm->eventData.nodeFailed.busNumber,
- eventParm->eventData.nodeFailed.subBusNumber,
- eventParm->eventData.nodeFailed.deviceId);
- break;
- case XmPciLpEvent_NodeRecovered:
- printk(KERN_INFO
- "XmPciLpEvent.c: multi-adapter bridge %d/%d/%d recovered\n",
- eventParm->eventData.nodeRecovered.busNumber,
- eventParm->eventData.nodeRecovered.subBusNumber,
- eventParm->eventData.nodeRecovered.deviceId);
- break;
- default:
- printk(KERN_ERR
- "XmPciLpEvent.c: unrecognized event subtype 0x%x\n",
- eventParm->hvLpEvent.xSubtype);
- break;
- }
-}
-
-
-/* This should be called sometime prior to buswalk (init_IRQ would be good) */
-int XmPciLpEvent_init()
-{
- int xRc;
-
- PPCDBG(PPCDBG_BUSWALK,
- "XmPciLpEvent_init, Register Event type 0x%04X\n",
- HvLpEvent_Type_PciIo);
-
- xRc = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo,
- &XmPciLpEvent_handler);
- if (xRc == 0) {
- xRc = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
- if (xRc != 0)
- printk(KERN_ERR
- "XmPciLpEvent.c: open event path failed with rc 0x%x\n",
- xRc);
- } else
- printk(KERN_ERR
- "XmPciLpEvent.c: register handler failed with rc 0x%x\n",
- xRc);
- return xRc;
-}
diff --git a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c
index 0094ac79a18..abb9e5b5da0 100644
--- a/arch/ppc64/kernel/asm-offsets.c
+++ b/arch/ppc64/kernel/asm-offsets.c
@@ -31,7 +31,6 @@
#include <asm/paca.h>
#include <asm/lppaca.h>
-#include <asm/iSeries/ItLpQueue.h>
#include <asm/iSeries/HvLpEvent.h>
#include <asm/rtas.h>
#include <asm/cputable.h>
diff --git a/arch/ppc64/kernel/bpa_iic.c b/arch/ppc64/kernel/bpa_iic.c
new file mode 100644
index 00000000000..c8f3dc3fad7
--- /dev/null
+++ b/arch/ppc64/kernel/bpa_iic.c
@@ -0,0 +1,270 @@
+/*
+ * BPA Internal Interrupt Controller
+ *
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ *
+ * Author: Arnd Bergmann <arndb@de.ibm.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, 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; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/percpu.h>
+#include <linux/types.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/prom.h>
+#include <asm/ptrace.h>
+
+#include "bpa_iic.h"
+
+struct iic_pending_bits {
+ u32 data;
+ u8 flags;
+ u8 class;
+ u8 source;
+ u8 prio;
+};
+
+enum iic_pending_flags {
+ IIC_VALID = 0x80,
+ IIC_IPI = 0x40,
+};
+
+struct iic_regs {
+ struct iic_pending_bits pending;
+ struct iic_pending_bits pending_destr;
+ u64 generate;
+ u64 prio;
+};
+
+struct iic {
+ struct iic_regs __iomem *regs;
+};
+
+static DEFINE_PER_CPU(struct iic, iic);
+
+void iic_local_enable(void)
+{
+ out_be64(&__get_cpu_var(iic).regs->prio, 0xff);
+}
+
+void iic_local_disable(void)
+{
+ out_be64(&__get_cpu_var(iic).regs->prio, 0x0);
+}
+
+static unsigned int iic_startup(unsigned int irq)
+{
+ return 0;
+}
+
+static void iic_enable(unsigned int irq)
+{
+ iic_local_enable();
+}
+
+static void iic_disable(unsigned int irq)
+{
+}
+
+static void iic_end(unsigned int irq)
+{
+ iic_local_enable();
+}
+
+static struct hw_interrupt_type iic_pic = {
+ .typename = " BPA-IIC ",
+ .startup = iic_startup,
+ .enable = iic_enable,
+ .disable = iic_disable,
+ .end = iic_end,
+};
+
+static int iic_external_get_irq(struct iic_pending_bits pending)
+{
+ int irq;
+ unsigned char node, unit;
+
+ node = pending.source >> 4;
+ unit = pending.source & 0xf;
+ irq = -1;
+
+ /*
+ * This mapping is specific to the Broadband
+ * Engine. We might need to get the numbers
+ * from the device tree to support future CPUs.
+ */
+ switch (unit) {
+ case 0x00:
+ case 0x0b:
+ /*
+ * One of these units can be connected
+ * to an external interrupt controller.
+ */
+ if (pending.prio > 0x3f ||
+ pending.class != 2)
+ break;
+ irq = IIC_EXT_OFFSET
+ + spider_get_irq(pending.prio + node * IIC_NODE_STRIDE)
+ + node * IIC_NODE_STRIDE;
+ break;
+ case 0x01 ... 0x04:
+ case 0x07 ... 0x0a:
+ /*
+ * These units are connected to the SPEs
+ */
+ if (pending.class > 2)
+ break;
+ irq = IIC_SPE_OFFSET
+ + pending.class * IIC_CLASS_STRIDE
+ + node * IIC_NODE_STRIDE
+ + unit;
+ break;
+ }
+ if (irq == -1)
+ printk(KERN_WARNING "Unexpected interrupt class %02x, "
+ "source %02x, prio %02x, cpu %02x\n", pending.class,
+ pending.source, pending.prio, smp_processor_id());
+ return irq;
+}
+
+/* Get an IRQ number from the pending state register of the IIC */
+int iic_get_irq(struct pt_regs *regs)
+{
+ struct iic *iic;
+ int irq;
+ struct iic_pending_bits pending;
+
+ iic = &__get_cpu_var(iic);
+ *(unsigned long *) &pending =
+ in_be64((unsigned long __iomem *) &iic->regs->pending_destr);
+
+ irq = -1;
+ if (pending.flags & IIC_VALID) {
+ if (pending.flags & IIC_IPI) {
+ irq = IIC_IPI_OFFSET + (pending.prio >> 4);
+/*
+ if (irq > 0x80)
+ printk(KERN_WARNING "Unexpected IPI prio %02x"
+ "on CPU %02x\n", pending.prio,
+ smp_processor_id());
+*/
+ } else {
+ irq = iic_external_get_irq(pending);
+ }
+ }
+ return irq;
+}
+
+static struct iic_regs __iomem *find_iic(int cpu)
+{
+ struct device_node *np;
+ int nodeid = cpu / 2;
+ unsigned long regs;
+ struct iic_regs __iomem *iic_regs;
+
+ for (np = of_find_node_by_type(NULL, "cpu");
+ np;
+ np = of_find_node_by_type(np, "cpu")) {
+ if (nodeid == *(int *)get_property(np, "node-id", NULL))
+ break;
+ }
+
+ if (!np) {
+ printk(KERN_WARNING "IIC: CPU %d not found\n", cpu);
+ iic_regs = NULL;
+ } else {
+ regs = *(long *)get_property(np, "iic", NULL);
+
+ /* hack until we have decided on the devtree info */
+ regs += 0x400;
+ if (cpu & 1)
+ regs += 0x20;
+
+ printk(KERN_DEBUG "IIC for CPU %d at %lx\n", cpu, regs);
+ iic_regs = __ioremap(regs, sizeof(struct iic_regs),
+ _PAGE_NO_CACHE);
+ }
+ return iic_regs;
+}
+
+#ifdef CONFIG_SMP
+void iic_setup_cpu(void)
+{
+ out_be64(&__get_cpu_var(iic).regs->prio, 0xff);
+}
+
+void iic_cause_IPI(int cpu, int mesg)
+{
+ out_be64(&per_cpu(iic, cpu).regs->generate, mesg);
+}
+
+static irqreturn_t iic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
+{
+
+ smp_message_recv(irq - IIC_IPI_OFFSET, regs);
+ return IRQ_HANDLED;
+}
+
+static void iic_request_ipi(int irq, const char *name)
+{
+ /* IPIs are marked SA_INTERRUPT as they must run with irqs
+ * disabled */
+ get_irq_desc(irq)->handler = &iic_pic;
+ get_irq_desc(irq)->status |= IRQ_PER_CPU;
+ request_irq(irq, iic_ipi_action, SA_INTERRUPT, name, NULL);
+}
+
+void iic_request_IPIs(void)
+{
+ iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_CALL_FUNCTION, "IPI-call");
+ iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_RESCHEDULE, "IPI-resched");
+#ifdef CONFIG_DEBUGGER
+ iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_DEBUGGER_BREAK, "IPI-debug");
+#endif /* CONFIG_DEBUGGER */
+}
+#endif /* CONFIG_SMP */
+
+static void iic_setup_spe_handlers(void)
+{
+ int be, isrc;
+
+ /* Assume two threads per BE are present */
+ for (be=0; be < num_present_cpus() / 2; be++) {
+ for (isrc = 0; isrc < IIC_CLASS_STRIDE * 3; isrc++) {
+ int irq = IIC_NODE_STRIDE * be + IIC_SPE_OFFSET + isrc;
+ get_irq_desc(irq)->handler = &iic_pic;
+ }
+ }
+}
+
+void iic_init_IRQ(void)
+{
+ int cpu, irq_offset;
+ struct iic *iic;
+
+ irq_offset = 0;
+ for_each_cpu(cpu) {
+ iic = &per_cpu(iic, cpu);
+ iic->regs = find_iic(cpu);
+ if (iic->regs)
+ out_be64(&iic->regs->prio, 0xff);
+ }
+ iic_setup_spe_handlers();
+}
diff --git a/arch/ppc64/kernel/bpa_iic.h b/arch/ppc64/kernel/bpa_iic.h
new file mode 100644
index 00000000000..6833c302216
--- /dev/null
+++ b/arch/ppc64/kernel/bpa_iic.h
@@ -0,0 +1,62 @@
+#ifndef ASM_BPA_IIC_H
+#define ASM_BPA_IIC_H
+#ifdef __KERNEL__
+/*
+ * Mapping of IIC pending bits into per-node
+ * interrupt numbers.
+ *
+ * IRQ FF CC SS PP FF CC SS PP Description
+ *
+ * 00-3f 80 02 +0 00 - 80 02 +0 3f South Bridge
+ * 00-3f 80 02 +b 00 - 80 02 +b 3f South Bridge
+ * 41-4a 80 00 +1 ** - 80 00 +a ** SPU Class 0
+ * 51-5a 80 01 +1 ** - 80 01 +a ** SPU Class 1
+ * 61-6a 80 02 +1 ** - 80 02 +a ** SPU Class 2
+ * 70-7f C0 ** ** 00 - C0 ** ** 0f IPI
+ *
+ * F flags
+ * C class
+ * S source
+ * P Priority
+ * + node number
+ * * don't care
+ *
+ * A node consists of a Broadband Engine and an optional
+ * south bridge device providing a maximum of 64 IRQs.
+ * The south bridge may be connected to either IOIF0
+ * or IOIF1.
+ * Each SPE is represented as three IRQ lines, one per
+ * interrupt class.
+ * 16 IRQ numbers are reserved for inter processor
+ * interruptions, although these are only used in the
+ * range of the first node.
+ *
+ * This scheme needs 128 IRQ numbers per BIF node ID,
+ * which means that with the total of 512 lines
+ * available, we can have a maximum of four nodes.
+ */
+
+enum {
+ IIC_EXT_OFFSET = 0x00, /* Start of south bridge IRQs */
+ IIC_NUM_EXT = 0x40, /* Number of south bridge IRQs */
+ IIC_SPE_OFFSET = 0x40, /* Start of SPE interrupts */
+ IIC_CLASS_STRIDE = 0x10, /* SPE IRQs per class */
+ IIC_IPI_OFFSET = 0x70, /* Start of IPI IRQs */
+ IIC_NUM_IPIS = 0x10, /* IRQs reserved for IPI */
+ IIC_NODE_STRIDE = 0x80, /* Total IRQs per node */
+};
+
+extern void iic_init_IRQ(void);
+extern int iic_get_irq(struct pt_regs *regs);
+extern void iic_cause_IPI(int cpu, int mesg);
+extern void iic_request_IPIs(void);
+extern void iic_setup_cpu(void);
+extern void iic_local_enable(void);
+extern void iic_local_disable(void);
+
+
+extern void spider_init_IRQ(void);
+extern int spider_get_irq(unsigned long int_pending);
+
+#endif
+#endif /* ASM_BPA_IIC_H */
diff --git a/arch/ppc64/kernel/bpa_iommu.c b/arch/ppc64/kernel/bpa_iommu.c
new file mode 100644
index 00000000000..f33a7bccb0d
--- /dev/null
+++ b/arch/ppc64/kernel/bpa_iommu.c
@@ -0,0 +1,377 @@
+/*
+ * IOMMU implementation for Broadband Processor Architecture
+ * We just establish a linear mapping at boot by setting all the
+ * IOPT cache entries in the CPU.
+ * The mapping functions should be identical to pci_direct_iommu,
+ * except for the handling of the high order bit that is required
+ * by the Spider bridge. These should be split into a separate
+ * file at the point where we get a different bridge chip.
+ *
+ * Copyright (C) 2005 IBM Deutschland Entwicklung GmbH,
+ * Arnd Bergmann <arndb@de.ibm.com>
+ *
+ * Based on linear mapping
+ * Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org)
+ *
+ * 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.
+ */
+
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/sections.h>
+#include <asm/iommu.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
+#include <asm/abs_addr.h>
+#include <asm/system.h>
+
+#include "pci.h"
+#include "bpa_iommu.h"
+
+static inline unsigned long
+get_iopt_entry(unsigned long real_address, unsigned long ioid,
+ unsigned long prot)
+{
+ return (prot & IOPT_PROT_MASK)
+ | (IOPT_COHERENT)
+ | (IOPT_ORDER_VC)
+ | (real_address & IOPT_RPN_MASK)
+ | (ioid & IOPT_IOID_MASK);
+}
+
+typedef struct {
+ unsigned long val;
+} ioste;
+
+static inline ioste
+mk_ioste(unsigned long val)
+{
+ ioste ioste = { .val = val, };
+ return ioste;
+}
+
+static inline ioste
+get_iost_entry(unsigned long iopt_base, unsigned long io_address, unsigned page_size)
+{
+ unsigned long ps;
+ unsigned long iostep;
+ unsigned long nnpt;
+ unsigned long shift;
+
+ switch (page_size) {
+ case 0x1000000:
+ ps = IOST_PS_16M;
+ nnpt = 0; /* one page per segment */
+ shift = 5; /* segment has 16 iopt entries */
+ break;
+
+ case 0x100000:
+ ps = IOST_PS_1M;
+ nnpt = 0; /* one page per segment */
+ shift = 1; /* segment has 256 iopt entries */
+ break;
+
+ case 0x10000:
+ ps = IOST_PS_64K;
+ nnpt = 0x07; /* 8 pages per io page table */
+ shift = 0; /* all entries are used */
+ break;
+
+ case 0x1000:
+ ps = IOST_PS_4K;
+ nnpt = 0x7f; /* 128 pages per io page table */
+ shift = 0; /* all entries are used */
+ break;
+
+ default: /* not a known compile time constant */
+ BUILD_BUG_ON(1);
+ break;
+ }
+
+ iostep = iopt_base +
+ /* need 8 bytes per iopte */
+ (((io_address / page_size * 8)
+ /* align io page tables on 4k page boundaries */
+ << shift)
+ /* nnpt+1 pages go into each iopt */
+ & ~(nnpt << 12));
+
+ nnpt++; /* this seems to work, but the documentation is not clear
+ about wether we put nnpt or nnpt-1 into the ioste bits.
+ In theory, this can't work for 4k pages. */
+ return mk_ioste(IOST_VALID_MASK
+ | (iostep & IOST_PT_BASE_MASK)
+ | ((nnpt << 5) & IOST_NNPT_MASK)
+ | (ps & IOST_PS_MASK));
+}
+
+/* compute the address of an io pte */
+static inline unsigned long
+get_ioptep(ioste iost_entry, unsigned long io_address)
+{
+ unsigned long iopt_base;
+ unsigned long page_size;
+ unsigned long page_number;
+ unsigned long iopt_offset;
+
+ iopt_base = iost_entry.val & IOST_PT_BASE_MASK;
+ page_size = iost_entry.val & IOST_PS_MASK;
+
+ /* decode page size to compute page number */
+ page_number = (io_address & 0x0fffffff) >> (10 + 2 * page_size);
+ /* page number is an offset into the io page table */
+ iopt_offset = (page_number << 3) & 0x7fff8ul;
+ return iopt_base + iopt_offset;
+}
+
+/* compute the tag field of the iopt cache entry */
+static inline unsigned long
+get_ioc_tag(ioste iost_entry, unsigned long io_address)
+{
+ unsigned long iopte = get_ioptep(iost_entry, io_address);
+
+ return IOPT_VALID_MASK
+ | ((iopte & 0x00000000000000ff8ul) >> 3)
+ | ((iopte & 0x0000003fffffc0000ul) >> 9);
+}
+
+/* compute the hashed 6 bit index for the 4-way associative pte cache */
+static inline unsigned long
+get_ioc_hash(ioste iost_entry, unsigned long io_address)
+{
+ unsigned long iopte = get_ioptep(iost_entry, io_address);
+
+ return ((iopte & 0x000000000000001f8ul) >> 3)
+ ^ ((iopte & 0x00000000000020000ul) >> 17)
+ ^ ((iopte & 0x00000000000010000ul) >> 15)
+ ^ ((iopte & 0x00000000000008000ul) >> 13)
+ ^ ((iopte & 0x00000000000004000ul) >> 11)
+ ^ ((iopte & 0x00000000000002000ul) >> 9)
+ ^ ((iopte & 0x00000000000001000ul) >> 7);
+}
+
+/* same as above, but pretend that we have a simpler 1-way associative
+ pte cache with an 8 bit index */
+static inline unsigned long
+get_ioc_hash_1way(ioste iost_entry, unsigned long io_address)
+{
+ unsigned long iopte = get_ioptep(iost_entry, io_address);
+
+ return ((iopte & 0x000000000000001f8ul) >> 3)
+ ^ ((iopte & 0x00000000000020000ul) >> 17)
+ ^ ((iopte & 0x00000000000010000ul) >> 15)
+ ^ ((iopte & 0x00000000000008000ul) >> 13)
+ ^ ((iopte & 0x00000000000004000ul) >> 11)
+ ^ ((iopte & 0x00000000000002000ul) >> 9)
+ ^ ((iopte & 0x00000000000001000ul) >> 7)
+ ^ ((iopte & 0x0000000000000c000ul) >> 8);
+}
+
+static inline ioste
+get_iost_cache(void __iomem *base, unsigned long index)
+{
+ unsigned long __iomem *p = (base + IOC_ST_CACHE_DIR);
+ return mk_ioste(in_be64(&p[index]));
+}
+
+static inline void
+set_iost_cache(void __iomem *base, unsigned long index, ioste ste)
+{
+ unsigned long __iomem *p = (base + IOC_ST_CACHE_DIR);
+ pr_debug("ioste %02lx was %016lx, store %016lx", index,
+ get_iost_cache(base, index).val, ste.val);
+ out_be64(&p[index], ste.val);
+ pr_debug(" now %016lx\n", get_iost_cache(base, index).val);
+}
+
+static inline unsigned long
+get_iopt_cache(void __iomem *base, unsigned long index, unsigned long *tag)
+{
+ unsigned long __iomem *tags = (void *)(base + IOC_PT_CACHE_DIR);
+ unsigned long __iomem *p = (void *)(base + IOC_PT_CACHE_REG);
+
+ *tag = tags[index];
+ rmb();
+ return *p;
+}
+
+static inline void
+set_iopt_cache(void __iomem *base, unsigned long index,
+ unsigned long tag, unsigned long val)
+{
+ unsigned long __iomem *tags = base + IOC_PT_CACHE_DIR;
+ unsigned long __iomem *p = base + IOC_PT_CACHE_REG;
+ pr_debug("iopt %02lx was v%016lx/t%016lx, store v%016lx/t%016lx\n",
+ index, get_iopt_cache(base, index, &oldtag), oldtag, val, tag);
+
+ out_be64(p, val);
+ out_be64(&tags[index], tag);
+}
+
+static inline void
+set_iost_origin(void __iomem *base)
+{
+ unsigned long __iomem *p = base + IOC_ST_ORIGIN;
+ unsigned long origin = IOSTO_ENABLE | IOSTO_SW;
+
+ pr_debug("iost_origin %016lx, now %016lx\n", in_be64(p), origin);
+ out_be64(p, origin);
+}
+
+static inline void
+set_iocmd_config(void __iomem *base)
+{
+ unsigned long __iomem *p = base + 0xc00;
+ unsigned long conf;
+
+ conf = in_be64(p);
+ pr_debug("iost_conf %016lx, now %016lx\n", conf, conf | IOCMD_CONF_TE);
+ out_be64(p, conf | IOCMD_CONF_TE);
+}
+
+/* FIXME: get these from the device tree */
+#define ioc_base 0x20000511000ull
+#define ioc_mmio_base 0x20000510000ull
+#define ioid 0x48a
+#define iopt_phys_offset (- 0x20000000) /* We have a 512MB offset from the SB */
+#define io_page_size 0x1000000
+
+static unsigned long map_iopt_entry(unsigned long address)
+{
+ switch (address >> 20) {
+ case 0x600:
+ address = 0x24020000000ull; /* spider i/o */
+ break;
+ default:
+ address += iopt_phys_offset;
+ break;
+ }
+
+ return get_iopt_entry(address, ioid, IOPT_PROT_RW);
+}
+
+static void iommu_bus_setup_null(struct pci_bus *b) { }
+static void iommu_dev_setup_null(struct pci_dev *d) { }
+
+/* initialize the iommu to support a simple linear mapping
+ * for each DMA window used by any device. For now, we
+ * happen to know that there is only one DMA window in use,
+ * starting at iopt_phys_offset. */
+static void bpa_map_iommu(void)
+{
+ unsigned long address;
+ void __iomem *base;
+ ioste ioste;
+ unsigned long index;
+
+ base = __ioremap(ioc_base, 0x1000, _PAGE_NO_CACHE);
+ pr_debug("%lx mapped to %p\n", ioc_base, base);
+ set_iocmd_config(base);
+ iounmap(base);
+
+ base = __ioremap(ioc_mmio_base, 0x1000, _PAGE_NO_CACHE);
+ pr_debug("%lx mapped to %p\n", ioc_mmio_base, base);
+
+ set_iost_origin(base);
+
+ for (address = 0; address < 0x100000000ul; address += io_page_size) {
+ ioste = get_iost_entry(0x10000000000ul, address, io_page_size);
+ if ((address & 0xfffffff) == 0) /* segment start */
+ set_iost_cache(base, address >> 28, ioste);
+ index = get_ioc_hash_1way(ioste, address);
+ pr_debug("addr %08lx, index %02lx, ioste %016lx\n",
+ address, index, ioste.val);
+ set_iopt_cache(base,
+ get_ioc_hash_1way(ioste, address),
+ get_ioc_tag(ioste, address),
+ map_iopt_entry(address));
+ }
+ iounmap(base);
+}
+
+
+static void *bpa_alloc_coherent(struct device *hwdev, size_t size,
+ dma_addr_t *dma_handle, unsigned int __nocast flag)
+{
+ void *ret;
+
+ ret = (void *)__get_free_pages(flag, get_order(size));
+ if (ret != NULL) {
+ memset(ret, 0, size);
+ *dma_handle = virt_to_abs(ret) | BPA_DMA_VALID;
+ }
+ return ret;
+}
+
+static void bpa_free_coherent(struct device *hwdev, size_t size,
+ void *vaddr, dma_addr_t dma_handle)
+{
+ free_pages((unsigned long)vaddr, get_order(size));
+}
+
+static dma_addr_t bpa_map_single(struct device *hwdev, void *ptr,
+ size_t size, enum dma_data_direction direction)
+{
+ return virt_to_abs(ptr) | BPA_DMA_VALID;
+}
+
+static void bpa_unmap_single(struct device *hwdev, dma_addr_t dma_addr,
+ size_t size, enum dma_data_direction direction)
+{
+}
+
+static int bpa_map_sg(struct device *hwdev, struct scatterlist *sg,
+ int nents, enum dma_data_direction direction)
+{
+ int i;
+
+ for (i = 0; i < nents; i++, sg++) {
+ sg->dma_address = (page_to_phys(sg->page) + sg->offset)
+ | BPA_DMA_VALID;
+ sg->dma_length = sg->length;
+ }
+
+ return nents;
+}
+
+static void bpa_unmap_sg(struct device *hwdev, struct scatterlist *sg,
+ int nents, enum dma_data_direction direction)
+{
+}
+
+static int bpa_dma_supported(struct device *dev, u64 mask)
+{
+ return mask < 0x100000000ull;
+}
+
+void bpa_init_iommu(void)
+{
+ bpa_map_iommu();
+
+ /* Direct I/O, IOMMU off */
+ ppc_md.iommu_dev_setup = iommu_dev_setup_null;
+ ppc_md.iommu_bus_setup = iommu_bus_setup_null;
+
+ pci_dma_ops.alloc_coherent = bpa_alloc_coherent;
+ pci_dma_ops.free_coherent = bpa_free_coherent;
+ pci_dma_ops.map_single = bpa_map_single;
+ pci_dma_ops.unmap_single = bpa_unmap_single;
+ pci_dma_ops.map_sg = bpa_map_sg;
+ pci_dma_ops.unmap_sg = bpa_unmap_sg;
+ pci_dma_ops.dma_supported = bpa_dma_supported;
+}
diff --git a/arch/ppc64/kernel/bpa_iommu.h b/arch/ppc64/kernel/bpa_iommu.h
new file mode 100644
index 00000000000..e547d77dfa0
--- /dev/null
+++ b/arch/ppc64/kernel/bpa_iommu.h
@@ -0,0 +1,65 @@
+#ifndef BPA_IOMMU_H
+#define BPA_IOMMU_H
+
+/* some constants */
+enum {
+ /* segment table entries */
+ IOST_VALID_MASK = 0x8000000000000000ul,
+ IOST_TAG_MASK = 0x3000000000000000ul,
+ IOST_PT_BASE_MASK = 0x000003fffffff000ul,
+ IOST_NNPT_MASK = 0x0000000000000fe0ul,
+ IOST_PS_MASK = 0x000000000000000ful,
+
+ IOST_PS_4K = 0x1,
+ IOST_PS_64K = 0x3,
+ IOST_PS_1M = 0x5,
+ IOST_PS_16M = 0x7,
+
+ /* iopt tag register */
+ IOPT_VALID_MASK = 0x0000000200000000ul,
+ IOPT_TAG_MASK = 0x00000001fffffffful,
+
+ /* iopt cache register */
+ IOPT_PROT_MASK = 0xc000000000000000ul,
+ IOPT_PROT_NONE = 0x0000000000000000ul,
+ IOPT_PROT_READ = 0x4000000000000000ul,
+ IOPT_PROT_WRITE = 0x8000000000000000ul,
+ IOPT_PROT_RW = 0xc000000000000000ul,
+ IOPT_COHERENT = 0x2000000000000000ul,
+
+ IOPT_ORDER_MASK = 0x1800000000000000ul,
+ /* order access to same IOID/VC on same address */
+ IOPT_ORDER_ADDR = 0x0800000000000000ul,
+ /* similar, but only after a write access */
+ IOPT_ORDER_WRITES = 0x1000000000000000ul,
+ /* Order all accesses to same IOID/VC */
+ IOPT_ORDER_VC = 0x1800000000000000ul,
+
+ IOPT_RPN_MASK = 0x000003fffffff000ul,
+ IOPT_HINT_MASK = 0x0000000000000800ul,
+ IOPT_IOID_MASK = 0x00000000000007fful,
+
+ IOSTO_ENABLE = 0x8000000000000000ul,
+ IOSTO_ORIGIN = 0x000003fffffff000ul,
+ IOSTO_HW = 0x0000000000000800ul,
+ IOSTO_SW = 0x0000000000000400ul,
+
+ IOCMD_CONF_TE = 0x0000800000000000ul,
+
+ /* memory mapped registers */
+ IOC_PT_CACHE_DIR = 0x000,
+ IOC_ST_CACHE_DIR = 0x800,
+ IOC_PT_CACHE_REG = 0x910,
+ IOC_ST_ORIGIN = 0x918,
+ IOC_CONF = 0x930,
+
+ /* The high bit needs to be set on every DMA address,
+ only 2GB are addressable */
+ BPA_DMA_VALID = 0x80000000,
+ BPA_DMA_MASK = 0x7fffffff,
+};
+
+
+void bpa_init_iommu(void);
+
+#endif
diff --git a/arch/ppc64/kernel/bpa_nvram.c b/arch/ppc64/kernel/bpa_nvram.c
new file mode 100644
index 00000000000..06a119cfceb
--- /dev/null
+++ b/arch/ppc64/kernel/bpa_nvram.c
@@ -0,0 +1,118 @@
+/*
+ * NVRAM for CPBW
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Authors : Utz Bacher <utz.bacher@de.ibm.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, 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; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <asm/machdep.h>
+#include <asm/nvram.h>
+#include <asm/prom.h>
+
+static void __iomem *bpa_nvram_start;
+static long bpa_nvram_len;
+static spinlock_t bpa_nvram_lock = SPIN_LOCK_UNLOCKED;
+
+static ssize_t bpa_nvram_read(char *buf, size_t count, loff_t *index)
+{
+ unsigned long flags;
+
+ if (*index >= bpa_nvram_len)
+ return 0;
+ if (*index + count > bpa_nvram_len)
+ count = bpa_nvram_len - *index;
+
+ spin_lock_irqsave(&bpa_nvram_lock, flags);
+
+ memcpy_fromio(buf, bpa_nvram_start + *index, count);
+
+ spin_unlock_irqrestore(&bpa_nvram_lock, flags);
+
+ *index += count;
+ return count;
+}
+
+static ssize_t bpa_nvram_write(char *buf, size_t count, loff_t *index)
+{
+ unsigned long flags;
+
+ if (*index >= bpa_nvram_len)
+ return 0;
+ if (*index + count > bpa_nvram_len)
+ count = bpa_nvram_len - *index;
+
+ spin_lock_irqsave(&bpa_nvram_lock, flags);
+
+ memcpy_toio(bpa_nvram_start + *index, buf, count);
+
+ spin_unlock_irqrestore(&bpa_nvram_lock, flags);
+
+ *index += count;
+ return count;
+}
+
+static ssize_t bpa_nvram_get_size(void)
+{
+ return bpa_nvram_len;
+}
+
+int __init bpa_nvram_init(void)
+{
+ struct device_node *nvram_node;
+ unsigned long *buffer;
+ int proplen;
+ unsigned long nvram_addr;
+ int ret;
+
+ ret = -ENODEV;
+ nvram_node = of_find_node_by_type(NULL, "nvram");
+ if (!nvram_node)
+ goto out;
+
+ ret = -EIO;
+ buffer = (unsigned long *)get_property(nvram_node, "reg", &proplen);
+ if (proplen != 2*sizeof(unsigned long))
+ goto out;
+
+ ret = -ENODEV;
+ nvram_addr = buffer[0];
+ bpa_nvram_len = buffer[1];
+ if ( (!bpa_nvram_len) || (!nvram_addr) )
+ goto out;
+
+ bpa_nvram_start = ioremap(nvram_addr, bpa_nvram_len);
+ if (!bpa_nvram_start)
+ goto out;
+
+ printk(KERN_INFO "BPA NVRAM, %luk mapped to %p\n",
+ bpa_nvram_len >> 10, bpa_nvram_start);
+
+ ppc_md.nvram_read = bpa_nvram_read;
+ ppc_md.nvram_write = bpa_nvram_write;
+ ppc_md.nvram_size = bpa_nvram_get_size;
+
+out:
+ of_node_put(nvram_node);
+ return ret;
+}
diff --git a/arch/ppc64/kernel/bpa_setup.c b/arch/ppc64/kernel/bpa_setup.c
new file mode 100644
index 00000000000..57b3db66f45
--- /dev/null
+++ b/arch/ppc64/kernel/bpa_setup.c
@@ -0,0 +1,140 @@
+/*
+ * linux/arch/ppc/kernel/bpa_setup.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ * Adapted from 'alpha' version by Gary Thomas
+ * Modified by Cort Dougan (cort@cs.nmt.edu)
+ * Modified by PPC64 Team, IBM Corp
+ * Modified by BPA Team, IBM Deutschland Entwicklung GmbH
+ *
+ * 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.
+ */
+#undef DEBUG
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/console.h>
+
+#include <asm/mmu.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/prom.h>
+#include <asm/rtas.h>
+#include <asm/pci-bridge.h>
+#include <asm/iommu.h>
+#include <asm/dma.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <asm/nvram.h>
+#include <asm/cputable.h>
+
+#include "pci.h"
+#include "bpa_iic.h"
+#include "bpa_iommu.h"
+
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+void bpa_get_cpuinfo(struct seq_file *m)
+{
+ struct device_node *root;
+ const char *model = "";
+
+ root = of_find_node_by_path("/");
+ if (root)
+ model = get_property(root, "model", NULL);
+ seq_printf(m, "machine\t\t: BPA %s\n", model);
+ of_node_put(root);
+}
+
+static void bpa_progress(char *s, unsigned short hex)
+{
+ printk("*** %04x : %s\n", hex, s ? s : "");
+}
+
+static void __init bpa_setup_arch(void)
+{
+ ppc_md.init_IRQ = iic_init_IRQ;
+ ppc_md.get_irq = iic_get_irq;
+
+#ifdef CONFIG_SMP
+ smp_init_pSeries();
+#endif
+
+ /* init to some ~sane value until calibrate_delay() runs */
+ loops_per_jiffy = 50000000;
+
+ if (ROOT_DEV == 0) {
+ printk("No ramdisk, default root is /dev/hda2\n");
+ ROOT_DEV = Root_HDA2;
+ }
+
+ /* Find and initialize PCI host bridges */
+ init_pci_config_tokens();
+ find_and_init_phbs();
+ spider_init_IRQ();
+#ifdef CONFIG_DUMMY_CONSOLE
+ conswitchp = &dummy_con;
+#endif
+
+ bpa_nvram_init();
+}
+
+/*
+ * Early initialization. Relocation is on but do not reference unbolted pages
+ */
+static void __init bpa_init_early(void)
+{
+ DBG(" -> bpa_init_early()\n");
+
+ hpte_init_native();
+
+ bpa_init_iommu();
+
+ ppc64_interrupt_controller = IC_BPA_IIC;
+
+ DBG(" <- bpa_init_early()\n");
+}
+
+
+static int __init bpa_probe(int platform)
+{
+ if (platform != PLATFORM_BPA)
+ return 0;
+
+ return 1;
+}
+
+struct machdep_calls __initdata bpa_md = {
+ .probe = bpa_probe,
+ .setup_arch = bpa_setup_arch,
+ .init_early = bpa_init_early,
+ .get_cpuinfo = bpa_get_cpuinfo,
+ .restart = rtas_restart,
+ .power_off = rtas_power_off,
+ .halt = rtas_halt,
+ .get_boot_time = rtas_get_boot_time,
+ .get_rtc_time = rtas_get_rtc_time,
+ .set_rtc_time = rtas_set_rtc_time,
+ .calibrate_decr = generic_calibrate_decr,
+ .progress = bpa_progress,
+};
diff --git a/arch/ppc64/kernel/cpu_setup_power4.S b/arch/ppc64/kernel/cpu_setup_power4.S
index 3bd95182085..42fc08cf87a 100644
--- a/arch/ppc64/kernel/cpu_setup_power4.S
+++ b/arch/ppc64/kernel/cpu_setup_power4.S
@@ -73,7 +73,21 @@ _GLOBAL(__970_cpu_preinit)
_GLOBAL(__setup_cpu_power4)
blr
-
+
+_GLOBAL(__setup_cpu_be)
+ /* Set large page sizes LP=0: 16MB, LP=1: 64KB */
+ addi r3, 0, 0
+ ori r3, r3, HID6_LB
+ sldi r3, r3, 32
+ nor r3, r3, r3
+ mfspr r4, SPRN_HID6
+ and r4, r4, r3
+ addi r3, 0, 0x02000
+ sldi r3, r3, 32
+ or r4, r4, r3
+ mtspr SPRN_HID6, r4
+ blr
+
_GLOBAL(__setup_cpu_ppc970)
mfspr r0,SPRN_HID0
li r11,5 /* clear DOZE and SLEEP */
diff --git a/arch/ppc64/kernel/cputable.c b/arch/ppc64/kernel/cputable.c
index 8644a864805..1d162c7c59d 100644
--- a/arch/ppc64/kernel/cputable.c
+++ b/arch/ppc64/kernel/cputable.c
@@ -34,6 +34,7 @@ EXPORT_SYMBOL(cur_cpu_spec);
extern void __setup_cpu_power3(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_power4(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec);
+extern void __setup_cpu_be(unsigned long offset, struct cpu_spec* spec);
/* We only set the altivec features if the kernel was compiled with altivec
@@ -162,6 +163,16 @@ struct cpu_spec cpu_specs[] = {
__setup_cpu_power4,
COMMON_PPC64_FW
},
+ { /* BE DD1.x */
+ 0xffff0000, 0x00700000, "Broadband Engine",
+ CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+ CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |
+ CPU_FTR_SMT,
+ COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP,
+ 128, 128,
+ __setup_cpu_be,
+ COMMON_PPC64_FW
+ },
{ /* default match */
0x00000000, 0x00000000, "POWER4 (compatible)",
CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
diff --git a/arch/ppc64/kernel/dma.c b/arch/ppc64/kernel/dma.c
index ce714c92713..4da8e31b2b6 100644
--- a/arch/ppc64/kernel/dma.c
+++ b/arch/ppc64/kernel/dma.c
@@ -15,8 +15,10 @@
static struct dma_mapping_ops *get_dma_ops(struct device *dev)
{
+#ifdef CONFIG_PCI
if (dev->bus == &pci_bus_type)
return &pci_dma_ops;
+#endif
#ifdef CONFIG_IBMVIO
if (dev->bus == &vio_bus_type)
return &vio_dma_ops;
@@ -37,8 +39,10 @@ EXPORT_SYMBOL(dma_supported);
int dma_set_mask(struct device *dev, u64 dma_mask)
{
+#ifdef CONFIG_PCI
if (dev->bus == &pci_bus_type)
return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
+#endif
#ifdef CONFIG_IBMVIO
if (dev->bus == &vio_bus_type)
return -EIO;
diff --git a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c
index d63d41f3eec..af5272fedad 100644
--- a/arch/ppc64/kernel/eeh.c
+++ b/arch/ppc64/kernel/eeh.c
@@ -505,7 +505,7 @@ static inline unsigned long eeh_token_to_phys(unsigned long token)
pte_t *ptep;
unsigned long pa;
- ptep = find_linux_pte(ioremap_mm.pgd, token);
+ ptep = find_linux_pte(init_mm.pgd, token);
if (!ptep)
return token;
pa = pte_pfn(*ptep) << PAGE_SHIFT;
diff --git a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S
index d3604056e1a..b61572eb2a7 100644
--- a/arch/ppc64/kernel/entry.S
+++ b/arch/ppc64/kernel/entry.S
@@ -436,15 +436,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
REST_8GPRS(14, r1)
REST_10GPRS(22, r1)
-#ifdef CONFIG_PPC_ISERIES
- clrrdi r7,r1,THREAD_SHIFT /* get current_thread_info() */
- ld r7,TI_FLAGS(r7) /* Get run light flag */
- mfspr r9,CTRLF
- srdi r7,r7,TIF_RUN_LIGHT
- insrdi r9,r7,1,63 /* Insert run light into CTRL */
- mtspr CTRLT,r9
-#endif
-
/* convert old thread to its task_struct for return value */
addi r3,r3,-THREAD
ld r7,_NIP(r1) /* Return to _switch caller in new task */
diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S
index 92a744c31ab..675c2708588 100644
--- a/arch/ppc64/kernel/head.S
+++ b/arch/ppc64/kernel/head.S
@@ -626,10 +626,10 @@ system_reset_iSeries:
lhz r24,PACAPACAINDEX(r13) /* Get processor # */
cmpwi 0,r24,0 /* Are we processor 0? */
beq .__start_initialization_iSeries /* Start up the first processor */
- mfspr r4,CTRLF
- li r5,RUNLATCH /* Turn off the run light */
+ mfspr r4,SPRN_CTRLF
+ li r5,CTRL_RUNLATCH /* Turn off the run light */
andc r4,r4,r5
- mtspr CTRLT,r4
+ mtspr SPRN_CTRLT,r4
1:
HMT_LOW
@@ -1194,7 +1194,7 @@ _GLOBAL(pSeries_secondary_smp_init)
bl .__restore_cpu_setup
/* Set up a paca value for this processor. Since we have the
- * physical cpu id in r3, we need to search the pacas to find
+ * physical cpu id in r24, we need to search the pacas to find
* which logical id maps to our physical one.
*/
LOADADDR(r13, paca) /* Get base vaddr of paca array */
@@ -1207,8 +1207,8 @@ _GLOBAL(pSeries_secondary_smp_init)
cmpwi r5,NR_CPUS
blt 1b
-99: HMT_LOW /* Couldn't find our CPU id */
- b 99b
+ mr r3,r24 /* not found, copy phys to r3 */
+ b .kexec_wait /* next kernel might do better */
2: mtspr SPRG3,r13 /* Save vaddr of paca in SPRG3 */
/* From now on, r24 is expected to be logica cpuid */
@@ -2082,9 +2082,9 @@ _GLOBAL(hmt_start_secondary)
mfspr r4, HID0
ori r4, r4, 0x1
mtspr HID0, r4
- mfspr r4, CTRLF
+ mfspr r4, SPRN_CTRLF
oris r4, r4, 0x40
- mtspr CTRLT, r4
+ mtspr SPRN_CTRLT, r4
blr
#endif
@@ -2121,10 +2121,6 @@ empty_zero_page:
swapper_pg_dir:
.space 4096
- .globl ioremap_dir
-ioremap_dir:
- .space 4096
-
#ifdef CONFIG_SMP
/* 1 page segment table per cpu (max 48, cpu0 allocated at STAB0_PHYS_ADDR) */
.globl stab_array
diff --git a/arch/ppc64/kernel/iSeries_VpdInfo.c b/arch/ppc64/kernel/iSeries_VpdInfo.c
index a6f0ff2d023..d11c732daf8 100644
--- a/arch/ppc64/kernel/iSeries_VpdInfo.c
+++ b/arch/ppc64/kernel/iSeries_VpdInfo.c
@@ -1,31 +1,31 @@
-/************************************************************************/
-/* File iSeries_vpdInfo.c created by Allan Trautman on Fri Feb 2 2001. */
-/************************************************************************/
-/* This code gets the card location of the hardware */
-/* Copyright (C) 20yy <Allan H Trautman> <IBM Corp> */
-/* */
-/* 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 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 */
-/************************************************************************/
-/* Change Activity: */
-/* Created, Feb 2, 2001 */
-/* Ported to ppc64, August 20, 2001 */
-/* End Change Activity */
-/************************************************************************/
-#include <linux/config.h>
+/*
+ * File iSeries_vpdInfo.c created by Allan Trautman on Fri Feb 2 2001.
+ *
+ * This code gets the card location of the hardware
+ * Copyright (C) 2001 <Allan H Trautman> <IBM Corp>
+ * Copyright (C) 2005 Stephen Rothwel, IBM Corp
+ *
+ * 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 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
+ *
+ * Change Activity:
+ * Created, Feb 2, 2001
+ * Ported to ppc64, August 20, 2001
+ * End Change Activity
+ */
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pci.h>
@@ -34,30 +34,25 @@
#include <asm/iSeries/HvCallPci.h>
#include <asm/iSeries/HvTypes.h>
-#include <asm/iSeries/mf.h>
-#include <asm/iSeries/LparData.h>
#include <asm/iSeries/iSeries_pci.h>
-#include "pci.h"
/*
* Size of Bus VPD data
*/
#define BUS_VPDSIZE 1024
+
/*
* Bus Vpd Tags
*/
-#define VpdEndOfDataTag 0x78
#define VpdEndOfAreaTag 0x79
#define VpdIdStringTag 0x82
#define VpdVendorAreaTag 0x84
+
/*
* Mfg Area Tags
*/
-#define VpdFruFlag 0x4647 // "FG"
#define VpdFruFrameId 0x4649 // "FI"
#define VpdSlotMapFormat 0x4D46 // "MF"
-#define VpdAsmPartNumber 0x504E // "PN"
-#define VpdFruSerial 0x534E // "SN"
#define VpdSlotMap 0x534D // "SM"
/*
@@ -79,74 +74,33 @@ struct SlotMapStruct {
char CardLocation[3];
char Parms[8];
char Reserved[2];
-};
+};
typedef struct SlotMapStruct SlotMap;
#define SLOT_ENTRY_SIZE 16
/*
- * Formats the device information.
- * - Pass in pci_dev* pointer to the device.
- * - Pass in buffer to place the data. Danger here is the buffer must
- * be as big as the client says it is. Should be at least 128 bytes.
- * Return will the length of the string data put in the buffer.
- * Format:
- * PCI: Bus 0, Device 26, Vendor 0x12AE Frame 1, Card C10 Ethernet
- * controller
- */
-int iSeries_Device_Information(struct pci_dev *PciDev, char *buffer,
- int BufferSize)
-{
- struct iSeries_Device_Node *DevNode =
- (struct iSeries_Device_Node *)PciDev->sysdata;
- int len;
-
- if (DevNode == NULL)
- return sprintf(buffer,
- "PCI: iSeries_Device_Information DevNode is NULL");
-
- if (BufferSize < 128)
- return 0;
-
- len = sprintf(buffer, "PCI: Bus%3d, Device%3d, Vendor %04X ",
- ISERIES_BUS(DevNode), PCI_SLOT(PciDev->devfn),
- PciDev->vendor);
- len += sprintf(buffer + len, "Frame%3d, Card %4s ",
- DevNode->FrameId, DevNode->CardLocation);
-#ifdef CONFIG_PCI
- if (pci_class_name(PciDev->class >> 8) == 0)
- len += sprintf(buffer + len, "0x%04X ",
- (int)(PciDev->class >> 8));
- else
- len += sprintf(buffer + len, "%s",
- pci_class_name(PciDev->class >> 8));
-#endif
- return len;
-}
-
-/*
* Parse the Slot Area
*/
-void iSeries_Parse_SlotArea(SlotMap *MapPtr, int MapLen,
- struct iSeries_Device_Node *DevNode)
+static void __init iSeries_Parse_SlotArea(SlotMap *MapPtr, int MapLen,
+ HvAgentId agent, u8 *PhbId, char card[4])
{
int SlotMapLen = MapLen;
SlotMap *SlotMapPtr = MapPtr;
/*
- * Parse Slot label until we find the one requrested
+ * Parse Slot label until we find the one requested
*/
while (SlotMapLen > 0) {
- if (SlotMapPtr->AgentId == DevNode->AgentId ) {
+ if (SlotMapPtr->AgentId == agent) {
/*
* If Phb wasn't found, grab the entry first one found.
*/
- if (DevNode->PhbId == 0xff)
- DevNode->PhbId = SlotMapPtr->PhbId;
+ if (*PhbId == 0xff)
+ *PhbId = SlotMapPtr->PhbId;
/* Found it, extract the data. */
- if (SlotMapPtr->PhbId == DevNode->PhbId ) {
- memcpy(&DevNode->CardLocation,
- &SlotMapPtr->CardLocation, 3);
- DevNode->CardLocation[3] = 0;
+ if (SlotMapPtr->PhbId == *PhbId) {
+ memcpy(card, &SlotMapPtr->CardLocation, 3);
+ card[3] = 0;
break;
}
}
@@ -159,8 +113,9 @@ void iSeries_Parse_SlotArea(SlotMap *MapPtr, int MapLen,
/*
* Parse the Mfg Area
*/
-static void iSeries_Parse_MfgArea(u8 *AreaData, int AreaLen,
- struct iSeries_Device_Node *DevNode)
+static void __init iSeries_Parse_MfgArea(u8 *AreaData, int AreaLen,
+ HvAgentId agent, u8 *PhbId,
+ u8 *frame, char card[4])
{
MfgArea *MfgAreaPtr = (MfgArea *)AreaData;
int MfgAreaLen = AreaLen;
@@ -171,7 +126,7 @@ static void iSeries_Parse_MfgArea(u8 *AreaData, int AreaLen,
int MfgTagLen = MfgAreaPtr->TagLength;
/* Frame ID (FI 4649020310 ) */
if (MfgAreaPtr->Tag == VpdFruFrameId) /* FI */
- DevNode->FrameId = MfgAreaPtr->AreaData1;
+ *frame = MfgAreaPtr->AreaData1;
/* Slot Map Format (MF 4D46020004 ) */
else if (MfgAreaPtr->Tag == VpdSlotMapFormat) /* MF */
SlotMapFmt = (MfgAreaPtr->AreaData1 * 256)
@@ -183,10 +138,11 @@ static void iSeries_Parse_MfgArea(u8 *AreaData, int AreaLen,
if (SlotMapFmt == 0x1004)
SlotMapPtr = (SlotMap *)((char *)MfgAreaPtr
+ MFG_ENTRY_SIZE + 1);
- else
+ else
SlotMapPtr = (SlotMap *)((char *)MfgAreaPtr
+ MFG_ENTRY_SIZE);
- iSeries_Parse_SlotArea(SlotMapPtr, MfgTagLen, DevNode);
+ iSeries_Parse_SlotArea(SlotMapPtr, MfgTagLen,
+ agent, PhbId, card);
}
/*
* Point to the next Mfg Area
@@ -194,19 +150,19 @@ static void iSeries_Parse_MfgArea(u8 *AreaData, int AreaLen,
*/
MfgAreaPtr = (MfgArea *)((char *)MfgAreaPtr + MfgTagLen
+ MFG_ENTRY_SIZE);
- MfgAreaLen -= (MfgTagLen + MFG_ENTRY_SIZE);
- }
+ MfgAreaLen -= (MfgTagLen + MFG_ENTRY_SIZE);
+ }
}
/*
* Look for "BUS".. Data is not Null terminated.
* PHBID of 0xFF indicates PHB was not found in VPD Data.
*/
-static int iSeries_Parse_PhbId(u8 *AreaPtr, int AreaLength)
+static int __init iSeries_Parse_PhbId(u8 *AreaPtr, int AreaLength)
{
u8 *PhbPtr = AreaPtr;
int DataLen = AreaLength;
- char PhbId = 0xFF;
+ char PhbId = 0xFF;
while (DataLen > 0) {
if ((*PhbPtr == 'B') && (*(PhbPtr + 1) == 'U')
@@ -216,7 +172,7 @@ static int iSeries_Parse_PhbId(u8 *AreaPtr, int AreaLength)
++PhbPtr;
PhbId = (*PhbPtr & 0x0F);
break;
- }
+ }
++PhbPtr;
--DataLen;
}
@@ -226,52 +182,90 @@ static int iSeries_Parse_PhbId(u8 *AreaPtr, int AreaLength)
/*
* Parse out the VPD Areas
*/
-static void iSeries_Parse_Vpd(u8 *VpdData, int VpdDataLen,
- struct iSeries_Device_Node *DevNode)
+static void __init iSeries_Parse_Vpd(u8 *VpdData, int VpdDataLen,
+ HvAgentId agent, u8 *frame, char card[4])
{
u8 *TagPtr = VpdData;
int DataLen = VpdDataLen - 3;
+ u8 PhbId;
while ((*TagPtr != VpdEndOfAreaTag) && (DataLen > 0)) {
- int AreaLen = *(TagPtr + 1) + (*(TagPtr + 2) * 256);
+ int AreaLen = *(TagPtr + 1) + (*(TagPtr + 2) * 256);
u8 *AreaData = TagPtr + 3;
if (*TagPtr == VpdIdStringTag)
- DevNode->PhbId = iSeries_Parse_PhbId(AreaData, AreaLen);
+ PhbId = iSeries_Parse_PhbId(AreaData, AreaLen);
else if (*TagPtr == VpdVendorAreaTag)
- iSeries_Parse_MfgArea(AreaData, AreaLen, DevNode);
+ iSeries_Parse_MfgArea(AreaData, AreaLen,
+ agent, &PhbId, frame, card);
/* Point to next Area. */
TagPtr = AreaData + AreaLen;
DataLen -= AreaLen;
}
-}
+}
-void iSeries_Get_Location_Code(struct iSeries_Device_Node *DevNode)
+static void __init iSeries_Get_Location_Code(u16 bus, HvAgentId agent,
+ u8 *frame, char card[4])
{
int BusVpdLen = 0;
- u8 *BusVpdPtr = (u8 *)kmalloc(BUS_VPDSIZE, GFP_KERNEL);
+ u8 *BusVpdPtr = kmalloc(BUS_VPDSIZE, GFP_KERNEL);
if (BusVpdPtr == NULL) {
printk("PCI: Bus VPD Buffer allocation failure.\n");
return;
}
- BusVpdLen = HvCallPci_getBusVpd(ISERIES_BUS(DevNode),
- ISERIES_HV_ADDR(BusVpdPtr),
+ BusVpdLen = HvCallPci_getBusVpd(bus, ISERIES_HV_ADDR(BusVpdPtr),
BUS_VPDSIZE);
if (BusVpdLen == 0) {
- kfree(BusVpdPtr);
printk("PCI: Bus VPD Buffer zero length.\n");
- return;
+ goto out_free;
}
/* printk("PCI: BusVpdPtr: %p, %d\n",BusVpdPtr, BusVpdLen); */
/* Make sure this is what I think it is */
if (*BusVpdPtr != VpdIdStringTag) { /* 0x82 */
printk("PCI: Bus VPD Buffer missing starting tag.\n");
- kfree(BusVpdPtr);
- return;
+ goto out_free;
}
- iSeries_Parse_Vpd(BusVpdPtr,BusVpdLen, DevNode);
- sprintf(DevNode->Location, "Frame%3d, Card %-4s", DevNode->FrameId,
- DevNode->CardLocation);
+ iSeries_Parse_Vpd(BusVpdPtr, BusVpdLen, agent, frame, card);
+out_free:
kfree(BusVpdPtr);
}
+
+/*
+ * Prints the device information.
+ * - Pass in pci_dev* pointer to the device.
+ * - Pass in the device count
+ *
+ * Format:
+ * PCI: Bus 0, Device 26, Vendor 0x12AE Frame 1, Card C10 Ethernet
+ * controller
+ */
+void __init iSeries_Device_Information(struct pci_dev *PciDev, int count)
+{
+ struct iSeries_Device_Node *DevNode = PciDev->sysdata;
+ u16 bus;
+ u8 frame;
+ char card[4];
+ HvSubBusNumber subbus;
+ HvAgentId agent;
+
+ if (DevNode == NULL) {
+ printk("%d. PCI: iSeries_Device_Information DevNode is NULL\n",
+ count);
+ return;
+ }
+
+ bus = ISERIES_BUS(DevNode);
+ subbus = ISERIES_SUBBUS(DevNode);
+ agent = ISERIES_PCI_AGENTID(ISERIES_GET_DEVICE_FROM_SUBBUS(subbus),
+ ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus));
+ iSeries_Get_Location_Code(bus, agent, &frame, card);
+
+ printk("%d. PCI: Bus%3d, Device%3d, Vendor %04X Frame%3d, Card %4s ",
+ count, bus, PCI_SLOT(PciDev->devfn), PciDev->vendor,
+ frame, card);
+ if (pci_class_name(PciDev->class >> 8) == 0)
+ printk("0x%04X\n", (int)(PciDev->class >> 8));
+ else
+ printk("%s\n", pci_class_name(PciDev->class >> 8));
+}
diff --git a/arch/ppc64/kernel/iSeries_iommu.c b/arch/ppc64/kernel/iSeries_iommu.c
index 4e1a47c8a80..f8ff1bb054d 100644
--- a/arch/ppc64/kernel/iSeries_iommu.c
+++ b/arch/ppc64/kernel/iSeries_iommu.c
@@ -83,7 +83,7 @@ static void tce_free_iSeries(struct iommu_table *tbl, long index, long npages)
}
}
-
+#ifdef CONFIG_PCI
/*
* This function compares the known tables to find an iommu_table
* that has already been built for hardware TCEs.
@@ -159,6 +159,7 @@ void iommu_devnode_init_iSeries(struct iSeries_Device_Node *dn)
else
kfree(tbl);
}
+#endif
static void iommu_dev_setup_iSeries(struct pci_dev *dev) { }
static void iommu_bus_setup_iSeries(struct pci_bus *bus) { }
diff --git a/arch/ppc64/kernel/iSeries_irq.c b/arch/ppc64/kernel/iSeries_irq.c
index f831d259dbb..77376c1bd61 100644
--- a/arch/ppc64/kernel/iSeries_irq.c
+++ b/arch/ppc64/kernel/iSeries_irq.c
@@ -1,27 +1,29 @@
-/************************************************************************/
-/* This module supports the iSeries PCI bus interrupt handling */
-/* Copyright (C) 20yy <Robert L Holtorf> <IBM Corp> */
-/* */
-/* 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 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 */
-/************************************************************************/
-/* Change Activity: */
-/* Created, December 13, 2000 by Wayne Holm */
-/* End Change Activity */
-/************************************************************************/
+/*
+ * This module supports the iSeries PCI bus interrupt handling
+ * Copyright (C) 20yy <Robert L Holtorf> <IBM Corp>
+ * Copyright (C) 2004-2005 IBM Corporation
+ *
+ * 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 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
+ *
+ * Change Activity:
+ * Created, December 13, 2000 by Wayne Holm
+ * End Change Activity
+ */
+#include <linux/config.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/threads.h>
@@ -30,30 +32,15 @@
#include <linux/string.h>
#include <linux/bootmem.h>
#include <linux/ide.h>
-
#include <linux/irq.h>
#include <linux/spinlock.h>
-#include <asm/ppcdebug.h>
+#include <asm/ppcdebug.h>
+#include <asm/iSeries/HvTypes.h>
+#include <asm/iSeries/HvLpEvent.h>
#include <asm/iSeries/HvCallPci.h>
#include <asm/iSeries/HvCallXm.h>
#include <asm/iSeries/iSeries_irq.h>
-#include <asm/iSeries/XmPciLpEvent.h>
-
-static unsigned int iSeries_startup_IRQ(unsigned int irq);
-static void iSeries_shutdown_IRQ(unsigned int irq);
-static void iSeries_enable_IRQ(unsigned int irq);
-static void iSeries_disable_IRQ(unsigned int irq);
-static void iSeries_end_IRQ(unsigned int irq);
-
-static hw_irq_controller iSeries_IRQ_handler = {
- .typename = "iSeries irq controller",
- .startup = iSeries_startup_IRQ,
- .shutdown = iSeries_shutdown_IRQ,
- .enable = iSeries_enable_IRQ,
- .disable = iSeries_disable_IRQ,
- .end = iSeries_end_IRQ
-};
/* This maps virtual irq numbers to real irqs */
unsigned int virt_irq_to_real_map[NR_IRQS];
@@ -62,37 +49,187 @@ unsigned int virt_irq_to_real_map[NR_IRQS];
/* Note: the pcnet32 driver assumes irq numbers < 2 aren't valid. :( */
static int next_virtual_irq = 2;
-/* This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c */
-void __init iSeries_init_IRQ(void)
+static long Pci_Interrupt_Count;
+static long Pci_Event_Count;
+
+enum XmPciLpEvent_Subtype {
+ XmPciLpEvent_BusCreated = 0, // PHB has been created
+ XmPciLpEvent_BusError = 1, // PHB has failed
+ XmPciLpEvent_BusFailed = 2, // Msg to Secondary, Primary failed bus
+ XmPciLpEvent_NodeFailed = 4, // Multi-adapter bridge has failed
+ XmPciLpEvent_NodeRecovered = 5, // Multi-adapter bridge has recovered
+ XmPciLpEvent_BusRecovered = 12, // PHB has been recovered
+ XmPciLpEvent_UnQuiesceBus = 18, // Secondary bus unqiescing
+ XmPciLpEvent_BridgeError = 21, // Bridge Error
+ XmPciLpEvent_SlotInterrupt = 22 // Slot interrupt
+};
+
+struct XmPciLpEvent_BusInterrupt {
+ HvBusNumber busNumber;
+ HvSubBusNumber subBusNumber;
+};
+
+struct XmPciLpEvent_NodeInterrupt {
+ HvBusNumber busNumber;
+ HvSubBusNumber subBusNumber;
+ HvAgentId deviceId;
+};
+
+struct XmPciLpEvent {
+ struct HvLpEvent hvLpEvent;
+
+ union {
+ u64 alignData; // Align on an 8-byte boundary
+
+ struct {
+ u32 fisr;
+ HvBusNumber busNumber;
+ HvSubBusNumber subBusNumber;
+ HvAgentId deviceId;
+ } slotInterrupt;
+
+ struct XmPciLpEvent_BusInterrupt busFailed;
+ struct XmPciLpEvent_BusInterrupt busRecovered;
+ struct XmPciLpEvent_BusInterrupt busCreated;
+
+ struct XmPciLpEvent_NodeInterrupt nodeFailed;
+ struct XmPciLpEvent_NodeInterrupt nodeRecovered;
+
+ } eventData;
+
+};
+
+static void intReceived(struct XmPciLpEvent *eventParm,
+ struct pt_regs *regsParm)
{
- /* Register PCI event handler and open an event path */
- XmPciLpEvent_init();
+ int irq;
+
+ ++Pci_Interrupt_Count;
+
+ switch (eventParm->hvLpEvent.xSubtype) {
+ case XmPciLpEvent_SlotInterrupt:
+ irq = eventParm->hvLpEvent.xCorrelationToken;
+ /* Dispatch the interrupt handlers for this irq */
+ ppc_irq_dispatch_handler(regsParm, irq);
+ HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber,
+ eventParm->eventData.slotInterrupt.subBusNumber,
+ eventParm->eventData.slotInterrupt.deviceId);
+ break;
+ /* Ignore error recovery events for now */
+ case XmPciLpEvent_BusCreated:
+ printk(KERN_INFO "intReceived: system bus %d created\n",
+ eventParm->eventData.busCreated.busNumber);
+ break;
+ case XmPciLpEvent_BusError:
+ case XmPciLpEvent_BusFailed:
+ printk(KERN_INFO "intReceived: system bus %d failed\n",
+ eventParm->eventData.busFailed.busNumber);
+ break;
+ case XmPciLpEvent_BusRecovered:
+ case XmPciLpEvent_UnQuiesceBus:
+ printk(KERN_INFO "intReceived: system bus %d recovered\n",
+ eventParm->eventData.busRecovered.busNumber);
+ break;
+ case XmPciLpEvent_NodeFailed:
+ case XmPciLpEvent_BridgeError:
+ printk(KERN_INFO
+ "intReceived: multi-adapter bridge %d/%d/%d failed\n",
+ eventParm->eventData.nodeFailed.busNumber,
+ eventParm->eventData.nodeFailed.subBusNumber,
+ eventParm->eventData.nodeFailed.deviceId);
+ break;
+ case XmPciLpEvent_NodeRecovered:
+ printk(KERN_INFO
+ "intReceived: multi-adapter bridge %d/%d/%d recovered\n",
+ eventParm->eventData.nodeRecovered.busNumber,
+ eventParm->eventData.nodeRecovered.subBusNumber,
+ eventParm->eventData.nodeRecovered.deviceId);
+ break;
+ default:
+ printk(KERN_ERR
+ "intReceived: unrecognized event subtype 0x%x\n",
+ eventParm->hvLpEvent.xSubtype);
+ break;
+ }
+}
+
+static void XmPciLpEvent_handler(struct HvLpEvent *eventParm,
+ struct pt_regs *regsParm)
+{
+#ifdef CONFIG_PCI
+ ++Pci_Event_Count;
+
+ if (eventParm && (eventParm->xType == HvLpEvent_Type_PciIo)) {
+ switch (eventParm->xFlags.xFunction) {
+ case HvLpEvent_Function_Int:
+ intReceived((struct XmPciLpEvent *)eventParm, regsParm);
+ break;
+ case HvLpEvent_Function_Ack:
+ printk(KERN_ERR
+ "XmPciLpEvent_handler: unexpected ack received\n");
+ break;
+ default:
+ printk(KERN_ERR
+ "XmPciLpEvent_handler: unexpected event function %d\n",
+ (int)eventParm->xFlags.xFunction);
+ break;
+ }
+ } else if (eventParm)
+ printk(KERN_ERR
+ "XmPciLpEvent_handler: Unrecognized PCI event type 0x%x\n",
+ (int)eventParm->xType);
+ else
+ printk(KERN_ERR "XmPciLpEvent_handler: NULL event received\n");
+#endif
}
/*
- * This is called out of iSeries_scan_slot to allocate an IRQ for an EADS slot
- * It calculates the irq value for the slot.
- * Note that subBusNumber is always 0 (at the moment at least).
+ * This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c
+ * It must be called before the bus walk.
*/
-int __init iSeries_allocate_IRQ(HvBusNumber busNumber,
- HvSubBusNumber subBusNumber, HvAgentId deviceId)
+void __init iSeries_init_IRQ(void)
{
- unsigned int realirq, virtirq;
- u8 idsel = (deviceId >> 4);
- u8 function = deviceId & 7;
-
- virtirq = next_virtual_irq++;
- realirq = ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function;
- virt_irq_to_real_map[virtirq] = realirq;
+ /* Register PCI event handler and open an event path */
+ int xRc;
- irq_desc[virtirq].handler = &iSeries_IRQ_handler;
- return virtirq;
+ xRc = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo,
+ &XmPciLpEvent_handler);
+ if (xRc == 0) {
+ xRc = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
+ if (xRc != 0)
+ printk(KERN_ERR "iSeries_init_IRQ: open event path "
+ "failed with rc 0x%x\n", xRc);
+ } else
+ printk(KERN_ERR "iSeries_init_IRQ: register handler "
+ "failed with rc 0x%x\n", xRc);
}
#define REAL_IRQ_TO_BUS(irq) ((((irq) >> 6) & 0xff) + 1)
#define REAL_IRQ_TO_IDSEL(irq) ((((irq) >> 3) & 7) + 1)
#define REAL_IRQ_TO_FUNC(irq) ((irq) & 7)
+/*
+ * This will be called by device drivers (via enable_IRQ)
+ * to enable INTA in the bridge interrupt status register.
+ */
+static void iSeries_enable_IRQ(unsigned int irq)
+{
+ u32 bus, deviceId, function, mask;
+ const u32 subBus = 0;
+ unsigned int rirq = virt_irq_to_real_map[irq];
+
+ /* The IRQ has already been locked by the caller */
+ bus = REAL_IRQ_TO_BUS(rirq);
+ function = REAL_IRQ_TO_FUNC(rirq);
+ deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
+
+ /* Unmask secondary INTA */
+ mask = 0x80000000;
+ HvCallPci_unmaskInterrupts(bus, subBus, deviceId, mask);
+ PPCDBG(PPCDBG_BUSWALK, "iSeries_enable_IRQ 0x%02X.%02X.%02X 0x%04X\n",
+ bus, subBus, deviceId, irq);
+}
+
/* This is called by iSeries_activate_IRQs */
static unsigned int iSeries_startup_IRQ(unsigned int irq)
{
@@ -131,7 +268,7 @@ void __init iSeries_activate_IRQs()
desc->handler->startup(irq);
spin_unlock_irqrestore(&desc->lock, flags);
}
- }
+ }
}
/* this is not called anywhere currently */
@@ -173,29 +310,7 @@ static void iSeries_disable_IRQ(unsigned int irq)
mask = 0x80000000;
HvCallPci_maskInterrupts(bus, subBus, deviceId, mask);
PPCDBG(PPCDBG_BUSWALK, "iSeries_disable_IRQ 0x%02X.%02X.%02X 0x%04X\n",
- bus, subBus, deviceId, irq);
-}
-
-/*
- * This will be called by device drivers (via enable_IRQ)
- * to enable INTA in the bridge interrupt status register.
- */
-static void iSeries_enable_IRQ(unsigned int irq)
-{
- u32 bus, deviceId, function, mask;
- const u32 subBus = 0;
- unsigned int rirq = virt_irq_to_real_map[irq];
-
- /* The IRQ has already been locked by the caller */
- bus = REAL_IRQ_TO_BUS(rirq);
- function = REAL_IRQ_TO_FUNC(rirq);
- deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
-
- /* Unmask secondary INTA */
- mask = 0x80000000;
- HvCallPci_unmaskInterrupts(bus, subBus, deviceId, mask);
- PPCDBG(PPCDBG_BUSWALK, "iSeries_enable_IRQ 0x%02X.%02X.%02X 0x%04X\n",
- bus, subBus, deviceId, irq);
+ bus, subBus, deviceId, irq);
}
/*
@@ -207,3 +322,32 @@ static void iSeries_enable_IRQ(unsigned int irq)
static void iSeries_end_IRQ(unsigned int irq)
{
}
+
+static hw_irq_controller iSeries_IRQ_handler = {
+ .typename = "iSeries irq controller",
+ .startup = iSeries_startup_IRQ,
+ .shutdown = iSeries_shutdown_IRQ,
+ .enable = iSeries_enable_IRQ,
+ .disable = iSeries_disable_IRQ,
+ .end = iSeries_end_IRQ
+};
+
+/*
+ * This is called out of iSeries_scan_slot to allocate an IRQ for an EADS slot
+ * It calculates the irq value for the slot.
+ * Note that subBusNumber is always 0 (at the moment at least).
+ */
+int __init iSeries_allocate_IRQ(HvBusNumber busNumber,
+ HvSubBusNumber subBusNumber, HvAgentId deviceId)
+{
+ unsigned int realirq, virtirq;
+ u8 idsel = (deviceId >> 4);
+ u8 function = deviceId & 7;
+
+ virtirq = next_virtual_irq++;
+ realirq = ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function;
+ virt_irq_to_real_map[virtirq] = realirq;
+
+ irq_desc[virtirq].handler = &iSeries_IRQ_handler;
+ return virtirq;
+}
diff --git a/arch/ppc64/kernel/iSeries_pci.c b/arch/ppc64/kernel/iSeries_pci.c
index bd4c2554f1a..356e4fd9a94 100644
--- a/arch/ppc64/kernel/iSeries_pci.c
+++ b/arch/ppc64/kernel/iSeries_pci.c
@@ -38,9 +38,7 @@
#include <asm/iommu.h>
#include <asm/iSeries/HvCallPci.h>
-#include <asm/iSeries/HvCallSm.h>
#include <asm/iSeries/HvCallXm.h>
-#include <asm/iSeries/LparData.h>
#include <asm/iSeries/iSeries_irq.h>
#include <asm/iSeries/iSeries_pci.h>
#include <asm/iSeries/mf.h>
@@ -225,10 +223,7 @@ static struct iSeries_Device_Node *build_device_node(HvBusNumber Bus,
node->DsaAddr.Dsa.busNumber = Bus;
node->DsaAddr.Dsa.subBusNumber = SubBus;
node->DsaAddr.Dsa.deviceId = 0x10;
- node->AgentId = AgentId;
node->DevFn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function);
- node->IoRetry = 0;
- iSeries_Get_Location_Code(node);
return node;
}
@@ -302,7 +297,6 @@ void __init iSeries_pci_final_fixup(void)
{
struct pci_dev *pdev = NULL;
struct iSeries_Device_Node *node;
- char Buffer[256];
int DeviceCount = 0;
PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_fixup Entry.\n");
@@ -324,9 +318,7 @@ void __init iSeries_pci_final_fixup(void)
"pdev 0x%p <==> DevNode 0x%p\n",
pdev, node);
allocate_device_bars(pdev);
- iSeries_Device_Information(pdev, Buffer,
- sizeof(Buffer));
- printk("%d. %s\n", DeviceCount, Buffer);
+ iSeries_Device_Information(pdev, DeviceCount);
iommu_devnode_init_iSeries(node);
} else
printk("PCI: Device Tree not found for 0x%016lX\n",
@@ -499,7 +491,6 @@ static int scan_bridge_slot(HvBusNumber Bus,
++DeviceCount;
node = build_device_node(Bus, SubBus, EADsIdSel, Function);
- node->Vendor = VendorId;
node->Irq = Irq;
node->LogicalSlot = BridgeInfo->logicalSlotNumber;
@@ -661,38 +652,34 @@ static struct pci_ops iSeries_pci_ops = {
* Check Return Code
* -> On Failure, print and log information.
* Increment Retry Count, if exceeds max, panic partition.
- * -> If in retry, print and log success
*
* PCI: Device 23.90 ReadL I/O Error( 0): 0x1234
* PCI: Device 23.90 ReadL Retry( 1)
* PCI: Device 23.90 ReadL Retry Successful(1)
*/
static int CheckReturnCode(char *TextHdr, struct iSeries_Device_Node *DevNode,
- u64 ret)
+ int *retry, u64 ret)
{
if (ret != 0) {
++Pci_Error_Count;
- ++DevNode->IoRetry;
+ (*retry)++;
printk("PCI: %s: Device 0x%04X:%02X I/O Error(%2d): 0x%04X\n",
TextHdr, DevNode->DsaAddr.Dsa.busNumber, DevNode->DevFn,
- DevNode->IoRetry, (int)ret);
+ *retry, (int)ret);
/*
* Bump the retry and check for retry count exceeded.
* If, Exceeded, panic the system.
*/
- if ((DevNode->IoRetry > Pci_Retry_Max) &&
+ if (((*retry) > Pci_Retry_Max) &&
(Pci_Error_Flag > 0)) {
mf_display_src(0xB6000103);
- panic_timeout = 0;
+ panic_timeout = 0;
panic("PCI: Hardware I/O Error, SRC B6000103, "
"Automatic Reboot Disabled.\n");
}
return -1; /* Retry Try */
}
- /* If retry was in progress, log success and rest retry count */
- if (DevNode->IoRetry > 0)
- DevNode->IoRetry = 0;
- return 0;
+ return 0;
}
/*
@@ -738,6 +725,7 @@ u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress)
{
u64 BarOffset;
u64 dsa;
+ int retry = 0;
struct HvCallPci_LoadReturn ret;
struct iSeries_Device_Node *DevNode =
xlate_iomm_address(IoAddress, &dsa, &BarOffset);
@@ -757,7 +745,7 @@ u8 iSeries_Read_Byte(const volatile void __iomem *IoAddress)
do {
++Pci_Io_Read_Count;
HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0);
- } while (CheckReturnCode("RDB", DevNode, ret.rc) != 0);
+ } while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0);
return (u8)ret.value;
}
@@ -767,6 +755,7 @@ u16 iSeries_Read_Word(const volatile void __iomem *IoAddress)
{
u64 BarOffset;
u64 dsa;
+ int retry = 0;
struct HvCallPci_LoadReturn ret;
struct iSeries_Device_Node *DevNode =
xlate_iomm_address(IoAddress, &dsa, &BarOffset);
@@ -787,7 +776,7 @@ u16 iSeries_Read_Word(const volatile void __iomem *IoAddress)
++Pci_Io_Read_Count;
HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa,
BarOffset, 0);
- } while (CheckReturnCode("RDW", DevNode, ret.rc) != 0);
+ } while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0);
return swab16((u16)ret.value);
}
@@ -797,6 +786,7 @@ u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
{
u64 BarOffset;
u64 dsa;
+ int retry = 0;
struct HvCallPci_LoadReturn ret;
struct iSeries_Device_Node *DevNode =
xlate_iomm_address(IoAddress, &dsa, &BarOffset);
@@ -817,7 +807,7 @@ u32 iSeries_Read_Long(const volatile void __iomem *IoAddress)
++Pci_Io_Read_Count;
HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa,
BarOffset, 0);
- } while (CheckReturnCode("RDL", DevNode, ret.rc) != 0);
+ } while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0);
return swab32((u32)ret.value);
}
@@ -834,6 +824,7 @@ void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress)
{
u64 BarOffset;
u64 dsa;
+ int retry = 0;
u64 rc;
struct iSeries_Device_Node *DevNode =
xlate_iomm_address(IoAddress, &dsa, &BarOffset);
@@ -853,7 +844,7 @@ void iSeries_Write_Byte(u8 data, volatile void __iomem *IoAddress)
do {
++Pci_Io_Write_Count;
rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0);
- } while (CheckReturnCode("WWB", DevNode, rc) != 0);
+ } while (CheckReturnCode("WWB", DevNode, &retry, rc) != 0);
}
EXPORT_SYMBOL(iSeries_Write_Byte);
@@ -861,6 +852,7 @@ void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress)
{
u64 BarOffset;
u64 dsa;
+ int retry = 0;
u64 rc;
struct iSeries_Device_Node *DevNode =
xlate_iomm_address(IoAddress, &dsa, &BarOffset);
@@ -880,7 +872,7 @@ void iSeries_Write_Word(u16 data, volatile void __iomem *IoAddress)
do {
++Pci_Io_Write_Count;
rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0);
- } while (CheckReturnCode("WWW", DevNode, rc) != 0);
+ } while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0);
}
EXPORT_SYMBOL(iSeries_Write_Word);
@@ -888,6 +880,7 @@ void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress)
{
u64 BarOffset;
u64 dsa;
+ int retry = 0;
u64 rc;
struct iSeries_Device_Node *DevNode =
xlate_iomm_address(IoAddress, &dsa, &BarOffset);
@@ -907,6 +900,6 @@ void iSeries_Write_Long(u32 data, volatile void __iomem *IoAddress)
do {
++Pci_Io_Write_Count;
rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0);
- } while (CheckReturnCode("WWL", DevNode, rc) != 0);
+ } while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0);
}
EXPORT_SYMBOL(iSeries_Write_Long);
diff --git a/arch/ppc64/kernel/iSeries_pci_reset.c b/arch/ppc64/kernel/iSeries_pci_reset.c
deleted file mode 100644
index 0f785e4584f..00000000000
--- a/arch/ppc64/kernel/iSeries_pci_reset.c
+++ /dev/null
@@ -1,104 +0,0 @@
-#define PCIFR(...)
-/************************************************************************/
-/* File iSeries_pci_reset.c created by Allan Trautman on Mar 21 2001. */
-/************************************************************************/
-/* This code supports the pci interface on the IBM iSeries systems. */
-/* Copyright (C) 20yy <Allan H Trautman> <IBM Corp> */
-/* */
-/* 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 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 */
-/************************************************************************/
-/* Change Activity: */
-/* Created, March 20, 2001 */
-/* April 30, 2001, Added return codes on functions. */
-/* September 10, 2001, Ported to ppc64. */
-/* End Change Activity */
-/************************************************************************/
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/irq.h>
-#include <linux/delay.h>
-
-#include <asm/io.h>
-#include <asm/iSeries/HvCallPci.h>
-#include <asm/iSeries/HvTypes.h>
-#include <asm/iSeries/mf.h>
-#include <asm/pci.h>
-
-#include <asm/iSeries/iSeries_pci.h>
-#include "pci.h"
-
-/*
- * Interface to toggle the reset line
- * Time is in .1 seconds, need for seconds.
- */
-int iSeries_Device_ToggleReset(struct pci_dev *PciDev, int AssertTime,
- int DelayTime)
-{
- unsigned int AssertDelay, WaitDelay;
- struct iSeries_Device_Node *DeviceNode =
- (struct iSeries_Device_Node *)PciDev->sysdata;
-
- if (DeviceNode == NULL) {
- printk("PCI: Pci Reset Failed, Device Node not found for pci_dev %p\n",
- PciDev);
- return -1;
- }
- /*
- * Set defaults, Assert is .5 second, Wait is 3 seconds.
- */
- if (AssertTime == 0)
- AssertDelay = 500;
- else
- AssertDelay = AssertTime * 100;
-
- if (DelayTime == 0)
- WaitDelay = 3000;
- else
- WaitDelay = DelayTime * 100;
-
- /*
- * Assert reset
- */
- DeviceNode->ReturnCode = HvCallPci_setSlotReset(ISERIES_BUS(DeviceNode),
- 0x00, DeviceNode->AgentId, 1);
- if (DeviceNode->ReturnCode == 0) {
- msleep(AssertDelay); /* Sleep for the time */
- DeviceNode->ReturnCode =
- HvCallPci_setSlotReset(ISERIES_BUS(DeviceNode),
- 0x00, DeviceNode->AgentId, 0);
-
- /*
- * Wait for device to reset
- */
- msleep(WaitDelay);
- }
- if (DeviceNode->ReturnCode == 0)
- PCIFR("Slot 0x%04X.%02 Reset\n", ISERIES_BUS(DeviceNode),
- DeviceNode->AgentId);
- else {
- printk("PCI: Slot 0x%04X.%02X Reset Failed, RCode: %04X\n",
- ISERIES_BUS(DeviceNode), DeviceNode->AgentId,
- DeviceNode->ReturnCode);
- PCIFR("Slot 0x%04X.%02X Reset Failed, RCode: %04X\n",
- ISERIES_BUS(DeviceNode), DeviceNode->AgentId,
- DeviceNode->ReturnCode);
- }
- return DeviceNode->ReturnCode;
-}
-EXPORT_SYMBOL(iSeries_Device_ToggleReset);
diff --git a/arch/ppc64/kernel/iSeries_proc.c b/arch/ppc64/kernel/iSeries_proc.c
index 0cc58ddf48d..356bd9931fc 100644
--- a/arch/ppc64/kernel/iSeries_proc.c
+++ b/arch/ppc64/kernel/iSeries_proc.c
@@ -28,8 +28,7 @@
#include <asm/iSeries/ItLpQueue.h>
#include <asm/iSeries/HvCallXm.h>
#include <asm/iSeries/IoHriMainStore.h>
-#include <asm/iSeries/LparData.h>
-#include <asm/iSeries/iSeries_proc.h>
+#include <asm/iSeries/IoHriProcessorVpd.h>
static int __init iseries_proc_create(void)
{
diff --git a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c
index da20120f226..86966ce76b5 100644
--- a/arch/ppc64/kernel/iSeries_setup.c
+++ b/arch/ppc64/kernel/iSeries_setup.c
@@ -47,7 +47,7 @@
#include <asm/paca.h>
#include <asm/cache.h>
#include <asm/sections.h>
-#include <asm/iSeries/LparData.h>
+#include <asm/abs_addr.h>
#include <asm/iSeries/HvCallHpt.h>
#include <asm/iSeries/HvLpConfig.h>
#include <asm/iSeries/HvCallEvent.h>
@@ -55,10 +55,12 @@
#include <asm/iSeries/HvCallXm.h>
#include <asm/iSeries/ItLpQueue.h>
#include <asm/iSeries/IoHriMainStore.h>
-#include <asm/iSeries/iSeries_proc.h>
#include <asm/iSeries/mf.h>
#include <asm/iSeries/HvLpEvent.h>
#include <asm/iSeries/iSeries_irq.h>
+#include <asm/iSeries/IoHriProcessorVpd.h>
+#include <asm/iSeries/ItVpdAreas.h>
+#include <asm/iSeries/LparMap.h>
extern void hvlog(char *fmt, ...);
@@ -74,7 +76,11 @@ extern void ppcdbg_initialize(void);
static void build_iSeries_Memory_Map(void);
static void setup_iSeries_cache_sizes(void);
static void iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr);
+#ifdef CONFIG_PCI
extern void iSeries_pci_final_fixup(void);
+#else
+static void iSeries_pci_final_fixup(void) { }
+#endif
/* Global Variables */
static unsigned long procFreqHz;
@@ -665,9 +671,6 @@ static void __init iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr)
}
}
-extern unsigned long ppc_proc_freq;
-extern unsigned long ppc_tb_freq;
-
/*
* Document me.
*/
@@ -766,8 +769,6 @@ static void iSeries_halt(void)
mf_power_off();
}
-extern void setup_default_decr(void);
-
/*
* void __init iSeries_calibrate_decr()
*
@@ -852,6 +853,32 @@ static int __init iSeries_src_init(void)
late_initcall(iSeries_src_init);
+static int set_spread_lpevents(char *str)
+{
+ unsigned long i;
+ unsigned long val = simple_strtoul(str, NULL, 0);
+
+ /*
+ * The parameter is the number of processors to share in processing
+ * lp events.
+ */
+ if (( val > 0) && (val <= NR_CPUS)) {
+ for (i = 1; i < val; ++i)
+ paca[i].lpqueue_ptr = paca[0].lpqueue_ptr;
+
+ printk("lpevent processing spread over %ld processors\n", val);
+ } else {
+ printk("invalid spread_lpevents %ld\n", val);
+ }
+
+ return 1;
+}
+__setup("spread_lpevents=", set_spread_lpevents);
+
+#ifndef CONFIG_PCI
+void __init iSeries_init_IRQ(void) { }
+#endif
+
void __init iSeries_early_setup(void)
{
iSeries_fixup_klimit();
diff --git a/arch/ppc64/kernel/iSeries_smp.c b/arch/ppc64/kernel/iSeries_smp.c
index ba1f084d546..f74386e3163 100644
--- a/arch/ppc64/kernel/iSeries_smp.c
+++ b/arch/ppc64/kernel/iSeries_smp.c
@@ -38,9 +38,7 @@
#include <asm/io.h>
#include <asm/smp.h>
#include <asm/paca.h>
-#include <asm/iSeries/LparData.h>
#include <asm/iSeries/HvCall.h>
-#include <asm/iSeries/HvCallCfg.h>
#include <asm/time.h>
#include <asm/ppcdebug.h>
#include <asm/machdep.h>
diff --git a/arch/ppc64/kernel/idle.c b/arch/ppc64/kernel/idle.c
index 6abc621d3ba..bdf13b4dc1c 100644
--- a/arch/ppc64/kernel/idle.c
+++ b/arch/ppc64/kernel/idle.c
@@ -42,6 +42,11 @@ static int (*idle_loop)(void);
static unsigned long maxYieldTime = 0;
static unsigned long minYieldTime = 0xffffffffffffffffUL;
+static inline void process_iSeries_events(void)
+{
+ asm volatile ("li 0,0x5555; sc" : : : "r0", "r3");
+}
+
static void yield_shared_processor(void)
{
unsigned long tb;
@@ -75,13 +80,9 @@ static int iSeries_idle(void)
{
struct paca_struct *lpaca;
long oldval;
- unsigned long CTRL;
/* ensure iSeries run light will be out when idle */
- clear_thread_flag(TIF_RUN_LIGHT);
- CTRL = mfspr(CTRLF);
- CTRL &= ~RUNLATCH;
- mtspr(CTRLT, CTRL);
+ ppc64_runlatch_off();
lpaca = get_paca();
@@ -111,7 +112,9 @@ static int iSeries_idle(void)
}
}
+ ppc64_runlatch_on();
schedule();
+ ppc64_runlatch_off();
}
return 0;
@@ -294,7 +297,7 @@ static int native_idle(void)
if (need_resched())
schedule();
- if (cpu_is_offline(_smp_processor_id()) &&
+ if (cpu_is_offline(raw_smp_processor_id()) &&
system_state == SYSTEM_RUNNING)
cpu_die();
}
diff --git a/arch/ppc64/kernel/iommu.c b/arch/ppc64/kernel/iommu.c
index 344164681d2..8316426ccaf 100644
--- a/arch/ppc64/kernel/iommu.c
+++ b/arch/ppc64/kernel/iommu.c
@@ -423,6 +423,9 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl)
tbl->it_largehint = tbl->it_halfpoint;
spin_lock_init(&tbl->it_lock);
+ /* Clear the hardware table in case firmware left allocations in it */
+ ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size);
+
if (!welcomed) {
printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n",
novmerge ? "disabled" : "enabled");
diff --git a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c
index 4fd7f203c1e..3defc8c33ad 100644
--- a/arch/ppc64/kernel/irq.c
+++ b/arch/ppc64/kernel/irq.c
@@ -52,7 +52,7 @@
#include <asm/cache.h>
#include <asm/prom.h>
#include <asm/ptrace.h>
-#include <asm/iSeries/LparData.h>
+#include <asm/iSeries/ItLpQueue.h>
#include <asm/machdep.h>
#include <asm/paca.h>
@@ -395,6 +395,9 @@ int virt_irq_create_mapping(unsigned int real_irq)
if (ppc64_interrupt_controller == IC_OPEN_PIC)
return real_irq; /* no mapping for openpic (for now) */
+ if (ppc64_interrupt_controller == IC_BPA_IIC)
+ return real_irq; /* no mapping for iic either */
+
/* don't map interrupts < MIN_VIRT_IRQ */
if (real_irq < MIN_VIRT_IRQ) {
virt_irq_to_real_map[real_irq] = real_irq;
diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c
index 103daaf7357..782ce3efa2c 100644
--- a/arch/ppc64/kernel/kprobes.c
+++ b/arch/ppc64/kernel/kprobes.c
@@ -32,40 +32,53 @@
#include <linux/ptrace.h>
#include <linux/spinlock.h>
#include <linux/preempt.h>
+#include <asm/cacheflush.h>
#include <asm/kdebug.h>
#include <asm/sstep.h>
-/* kprobe_status settings */
-#define KPROBE_HIT_ACTIVE 0x00000001
-#define KPROBE_HIT_SS 0x00000002
-
static struct kprobe *current_kprobe;
static unsigned long kprobe_status, kprobe_saved_msr;
+static struct kprobe *kprobe_prev;
+static unsigned long kprobe_status_prev, kprobe_saved_msr_prev;
static struct pt_regs jprobe_saved_regs;
int arch_prepare_kprobe(struct kprobe *p)
{
+ int ret = 0;
kprobe_opcode_t insn = *p->addr;
- if (IS_MTMSRD(insn) || IS_RFID(insn))
- /* cannot put bp on RFID/MTMSRD */
- return 1;
- return 0;
+ if ((unsigned long)p->addr & 0x03) {
+ printk("Attempt to register kprobe at an unaligned address\n");
+ ret = -EINVAL;
+ } else if (IS_MTMSRD(insn) || IS_RFID(insn)) {
+ printk("Cannot register a kprobe on rfid or mtmsrd\n");
+ ret = -EINVAL;
+ }
+ return ret;
}
void arch_copy_kprobe(struct kprobe *p)
{
memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
+ p->opcode = *p->addr;
}
-void arch_remove_kprobe(struct kprobe *p)
+void arch_arm_kprobe(struct kprobe *p)
{
+ *p->addr = BREAKPOINT_INSTRUCTION;
+ flush_icache_range((unsigned long) p->addr,
+ (unsigned long) p->addr + sizeof(kprobe_opcode_t));
}
-static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs)
+void arch_disarm_kprobe(struct kprobe *p)
{
*p->addr = p->opcode;
- regs->nip = (unsigned long)p->addr;
+ flush_icache_range((unsigned long) p->addr,
+ (unsigned long) p->addr + sizeof(kprobe_opcode_t));
+}
+
+void arch_remove_kprobe(struct kprobe *p)
+{
}
static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
@@ -78,6 +91,20 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
regs->nip = (unsigned long)&p->ainsn.insn;
}
+static inline void save_previous_kprobe(void)
+{
+ kprobe_prev = current_kprobe;
+ kprobe_status_prev = kprobe_status;
+ kprobe_saved_msr_prev = kprobe_saved_msr;
+}
+
+static inline void restore_previous_kprobe(void)
+{
+ current_kprobe = kprobe_prev;
+ kprobe_status = kprobe_status_prev;
+ kprobe_saved_msr = kprobe_saved_msr_prev;
+}
+
static inline int kprobe_handler(struct pt_regs *regs)
{
struct kprobe *p;
@@ -96,8 +123,19 @@ static inline int kprobe_handler(struct pt_regs *regs)
unlock_kprobes();
goto no_kprobe;
}
- disarm_kprobe(p, regs);
- ret = 1;
+ /* We have reentered the kprobe_handler(), since
+ * another probe was hit while within the handler.
+ * We here save the original kprobes variables and
+ * just single step on the instruction of the new probe
+ * without calling any user handlers.
+ */
+ save_previous_kprobe();
+ current_kprobe = p;
+ kprobe_saved_msr = regs->msr;
+ p->nmissed++;
+ prepare_singlestep(p, regs);
+ kprobe_status = KPROBE_REENTER;
+ return 1;
} else {
p = current_kprobe;
if (p->break_handler && p->break_handler(p, regs)) {
@@ -172,8 +210,6 @@ static void resume_execution(struct kprobe *p, struct pt_regs *regs)
ret = emulate_step(regs, p->ainsn.insn[0]);
if (ret == 0)
regs->nip = (unsigned long)p->addr + 4;
-
- regs->msr &= ~MSR_SE;
}
static inline int post_kprobe_handler(struct pt_regs *regs)
@@ -181,13 +217,21 @@ static inline int post_kprobe_handler(struct pt_regs *regs)
if (!kprobe_running())
return 0;
- if (current_kprobe->post_handler)
+ if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) {
+ kprobe_status = KPROBE_HIT_SSDONE;
current_kprobe->post_handler(current_kprobe, regs, 0);
+ }
resume_execution(current_kprobe, regs);
regs->msr |= kprobe_saved_msr;
+ /*Restore back the original saved kprobes variables and continue. */
+ if (kprobe_status == KPROBE_REENTER) {
+ restore_previous_kprobe();
+ goto out;
+ }
unlock_kprobes();
+out:
preempt_enable_no_resched();
/*
@@ -210,6 +254,7 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
if (kprobe_status & KPROBE_HIT_SS) {
resume_execution(current_kprobe, regs);
+ regs->msr &= ~MSR_SE;
regs->msr |= kprobe_saved_msr;
unlock_kprobes();
@@ -233,8 +278,6 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
*/
preempt_disable();
switch (val) {
- case DIE_IABR_MATCH:
- case DIE_DABR_MATCH:
case DIE_BPT:
if (kprobe_handler(args->regs))
ret = NOTIFY_STOP;
diff --git a/arch/ppc64/kernel/lparcfg.c b/arch/ppc64/kernel/lparcfg.c
index a8fd32df848..02e96627fa6 100644
--- a/arch/ppc64/kernel/lparcfg.c
+++ b/arch/ppc64/kernel/lparcfg.c
@@ -28,12 +28,13 @@
#include <asm/uaccess.h>
#include <asm/iSeries/HvLpConfig.h>
#include <asm/lppaca.h>
-#include <asm/iSeries/LparData.h>
#include <asm/hvcall.h>
#include <asm/cputable.h>
#include <asm/rtas.h>
#include <asm/system.h>
#include <asm/time.h>
+#include <asm/iSeries/ItExtVpdPanel.h>
+#include <asm/prom.h>
#define MODULE_VERS "1.6"
#define MODULE_NAME "lparcfg"
diff --git a/arch/ppc64/kernel/machine_kexec.c b/arch/ppc64/kernel/machine_kexec.c
new file mode 100644
index 00000000000..fdb2fc649d7
--- /dev/null
+++ b/arch/ppc64/kernel/machine_kexec.c
@@ -0,0 +1,302 @@
+/*
+ * machine_kexec.c - handle transition of Linux booting another kernel
+ *
+ * Copyright (C) 2004-2005, IBM Corp.
+ *
+ * Created by: Milton D Miller II
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+
+#include <linux/cpumask.h>
+#include <linux/kexec.h>
+#include <linux/smp.h>
+#include <linux/thread_info.h>
+#include <linux/errno.h>
+
+#include <asm/page.h>
+#include <asm/current.h>
+#include <asm/machdep.h>
+#include <asm/cacheflush.h>
+#include <asm/paca.h>
+#include <asm/mmu.h>
+#include <asm/sections.h> /* _end */
+#include <asm/prom.h>
+
+#define HASH_GROUP_SIZE 0x80 /* size of each hash group, asm/mmu.h */
+
+/* Have this around till we move it into crash specific file */
+note_buf_t crash_notes[NR_CPUS];
+
+/* Dummy for now. Not sure if we need to have a crash shutdown in here
+ * and if what it will achieve. Letting it be now to compile the code
+ * in generic kexec environment
+ */
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+ /* do nothing right now */
+ /* smp_relase_cpus() if we want smp on panic kernel */
+ /* cpu_irq_down to isolate us until we are ready */
+}
+
+int machine_kexec_prepare(struct kimage *image)
+{
+ int i;
+ unsigned long begin, end; /* limits of segment */
+ unsigned long low, high; /* limits of blocked memory range */
+ struct device_node *node;
+ unsigned long *basep;
+ unsigned int *sizep;
+
+ if (!ppc_md.hpte_clear_all)
+ return -ENOENT;
+
+ /*
+ * Since we use the kernel fault handlers and paging code to
+ * handle the virtual mode, we must make sure no destination
+ * overlaps kernel static data or bss.
+ */
+ for (i = 0; i < image->nr_segments; i++)
+ if (image->segment[i].mem < __pa(_end))
+ return -ETXTBSY;
+
+ /*
+ * For non-LPAR, we absolutely can not overwrite the mmu hash
+ * table, since we are still using the bolted entries in it to
+ * do the copy. Check that here.
+ *
+ * It is safe if the end is below the start of the blocked
+ * region (end <= low), or if the beginning is after the
+ * end of the blocked region (begin >= high). Use the
+ * boolean identity !(a || b) === (!a && !b).
+ */
+ if (htab_address) {
+ low = __pa(htab_address);
+ high = low + (htab_hash_mask + 1) * HASH_GROUP_SIZE;
+
+ for (i = 0; i < image->nr_segments; i++) {
+ begin = image->segment[i].mem;
+ end = begin + image->segment[i].memsz;
+
+ if ((begin < high) && (end > low))
+ return -ETXTBSY;
+ }
+ }
+
+ /* We also should not overwrite the tce tables */
+ for (node = of_find_node_by_type(NULL, "pci"); node != NULL;
+ node = of_find_node_by_type(node, "pci")) {
+ basep = (unsigned long *)get_property(node, "linux,tce-base",
+ NULL);
+ sizep = (unsigned int *)get_property(node, "linux,tce-size",
+ NULL);
+ if (basep == NULL || sizep == NULL)
+ continue;
+
+ low = *basep;
+ high = low + (*sizep);
+
+ for (i = 0; i < image->nr_segments; i++) {
+ begin = image->segment[i].mem;
+ end = begin + image->segment[i].memsz;
+
+ if ((begin < high) && (end > low))
+ return -ETXTBSY;
+ }
+ }
+
+ return 0;
+}
+
+void machine_kexec_cleanup(struct kimage *image)
+{
+ /* we do nothing in prepare that needs to be undone */
+}
+
+#define IND_FLAGS (IND_DESTINATION | IND_INDIRECTION | IND_DONE | IND_SOURCE)
+
+static void copy_segments(unsigned long ind)
+{
+ unsigned long entry;
+ unsigned long *ptr;
+ void *dest;
+ void *addr;
+
+ /*
+ * We rely on kexec_load to create a lists that properly
+ * initializes these pointers before they are used.
+ * We will still crash if the list is wrong, but at least
+ * the compiler will be quiet.
+ */
+ ptr = NULL;
+ dest = NULL;
+
+ for (entry = ind; !(entry & IND_DONE); entry = *ptr++) {
+ addr = __va(entry & PAGE_MASK);
+
+ switch (entry & IND_FLAGS) {
+ case IND_DESTINATION:
+ dest = addr;
+ break;
+ case IND_INDIRECTION:
+ ptr = addr;
+ break;
+ case IND_SOURCE:
+ copy_page(dest, addr);
+ dest += PAGE_SIZE;
+ }
+ }
+}
+
+void kexec_copy_flush(struct kimage *image)
+{
+ long i, nr_segments = image->nr_segments;
+ struct kexec_segment ranges[KEXEC_SEGMENT_MAX];
+
+ /* save the ranges on the stack to efficiently flush the icache */
+ memcpy(ranges, image->segment, sizeof(ranges));
+
+ /*
+ * After this call we may not use anything allocated in dynamic
+ * memory, including *image.
+ *
+ * Only globals and the stack are allowed.
+ */
+ copy_segments(image->head);
+
+ /*
+ * we need to clear the icache for all dest pages sometime,
+ * including ones that were in place on the original copy
+ */
+ for (i = 0; i < nr_segments; i++)
+ flush_icache_range(ranges[i].mem + KERNELBASE,
+ ranges[i].mem + KERNELBASE +
+ ranges[i].memsz);
+}
+
+#ifdef CONFIG_SMP
+
+/* FIXME: we should schedule this function to be called on all cpus based
+ * on calling the interrupts, but we would like to call it off irq level
+ * so that the interrupt controller is clean.
+ */
+void kexec_smp_down(void *arg)
+{
+ if (ppc_md.cpu_irq_down)
+ ppc_md.cpu_irq_down();
+
+ local_irq_disable();
+ kexec_smp_wait();
+ /* NOTREACHED */
+}
+
+static void kexec_prepare_cpus(void)
+{
+ int my_cpu, i, notified=-1;
+
+ smp_call_function(kexec_smp_down, NULL, 0, /* wait */0);
+ my_cpu = get_cpu();
+
+ /* check the others cpus are now down (via paca hw cpu id == -1) */
+ for (i=0; i < NR_CPUS; i++) {
+ if (i == my_cpu)
+ continue;
+
+ while (paca[i].hw_cpu_id != -1) {
+ if (!cpu_possible(i)) {
+ printk("kexec: cpu %d hw_cpu_id %d is not"
+ " possible, ignoring\n",
+ i, paca[i].hw_cpu_id);
+ break;
+ }
+ if (!cpu_online(i)) {
+ /* Fixme: this can be spinning in
+ * pSeries_secondary_wait with a paca
+ * waiting for it to go online.
+ */
+ printk("kexec: cpu %d hw_cpu_id %d is not"
+ " online, ignoring\n",
+ i, paca[i].hw_cpu_id);
+ break;
+ }
+ if (i != notified) {
+ printk( "kexec: waiting for cpu %d (physical"
+ " %d) to go down\n",
+ i, paca[i].hw_cpu_id);
+ notified = i;
+ }
+ }
+ }
+
+ /* after we tell the others to go down */
+ if (ppc_md.cpu_irq_down)
+ ppc_md.cpu_irq_down();
+
+ put_cpu();
+
+ local_irq_disable();
+}
+
+#else /* ! SMP */
+
+static void kexec_prepare_cpus(void)
+{
+ /*
+ * move the secondarys to us so that we can copy
+ * the new kernel 0-0x100 safely
+ *
+ * do this if kexec in setup.c ?
+ */
+ smp_relase_cpus();
+ if (ppc_md.cpu_irq_down)
+ ppc_md.cpu_irq_down();
+ local_irq_disable();
+}
+
+#endif /* SMP */
+
+/*
+ * kexec thread structure and stack.
+ *
+ * We need to make sure that this is 16384-byte aligned due to the
+ * way process stacks are handled. It also must be statically allocated
+ * or allocated as part of the kimage, because everything else may be
+ * overwritten when we copy the kexec image. We piggyback on the
+ * "init_task" linker section here to statically allocate a stack.
+ *
+ * We could use a smaller stack if we don't care about anything using
+ * current, but that audit has not been performed.
+ */
+union thread_union kexec_stack
+ __attribute__((__section__(".data.init_task"))) = { };
+
+/* Our assembly helper, in kexec_stub.S */
+extern NORET_TYPE void kexec_sequence(void *newstack, unsigned long start,
+ void *image, void *control,
+ void (*clear_all)(void)) ATTRIB_NORET;
+
+/* too late to fail here */
+void machine_kexec(struct kimage *image)
+{
+
+ /* prepare control code if any */
+
+ /* shutdown other cpus into our wait loop and quiesce interrupts */
+ kexec_prepare_cpus();
+
+ /* switch to a staticly allocated stack. Based on irq stack code.
+ * XXX: the task struct will likely be invalid once we do the copy!
+ */
+ kexec_stack.thread_info.task = current_thread_info()->task;
+ kexec_stack.thread_info.flags = 0;
+
+ /* Some things are best done in assembly. Finding globals with
+ * a toc is easier in C, so pass in what we can.
+ */
+ kexec_sequence(&kexec_stack, image->start, image,
+ page_address(image->control_code_page),
+ ppc_md.hpte_clear_all);
+ /* NOTREACHED */
+}
diff --git a/arch/ppc64/kernel/maple_setup.c b/arch/ppc64/kernel/maple_setup.c
index 8cf95a27178..da8900b51f4 100644
--- a/arch/ppc64/kernel/maple_setup.c
+++ b/arch/ppc64/kernel/maple_setup.c
@@ -78,17 +78,77 @@ extern int maple_pci_get_legacy_ide_irq(struct pci_dev *dev, int channel);
extern void generic_find_legacy_serial_ports(u64 *physport,
unsigned int *default_speed);
-
static void maple_restart(char *cmd)
{
+ unsigned int maple_nvram_base;
+ unsigned int maple_nvram_offset;
+ unsigned int maple_nvram_command;
+ struct device_node *rtcs;
+
+ /* find NVRAM device */
+ rtcs = find_compatible_devices("nvram", "AMD8111");
+ if (rtcs && rtcs->addrs) {
+ maple_nvram_base = rtcs->addrs[0].address;
+ } else {
+ printk(KERN_EMERG "Maple: Unable to find NVRAM\n");
+ printk(KERN_EMERG "Maple: Manual Restart Required\n");
+ return;
+ }
+
+ /* find service processor device */
+ rtcs = find_devices("service-processor");
+ if (!rtcs) {
+ printk(KERN_EMERG "Maple: Unable to find Service Processor\n");
+ printk(KERN_EMERG "Maple: Manual Restart Required\n");
+ return;
+ }
+ maple_nvram_offset = *(unsigned int*) get_property(rtcs,
+ "restart-addr", NULL);
+ maple_nvram_command = *(unsigned int*) get_property(rtcs,
+ "restart-value", NULL);
+
+ /* send command */
+ outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset);
+ for (;;) ;
}
static void maple_power_off(void)
{
+ unsigned int maple_nvram_base;
+ unsigned int maple_nvram_offset;
+ unsigned int maple_nvram_command;
+ struct device_node *rtcs;
+
+ /* find NVRAM device */
+ rtcs = find_compatible_devices("nvram", "AMD8111");
+ if (rtcs && rtcs->addrs) {
+ maple_nvram_base = rtcs->addrs[0].address;
+ } else {
+ printk(KERN_EMERG "Maple: Unable to find NVRAM\n");
+ printk(KERN_EMERG "Maple: Manual Power-Down Required\n");
+ return;
+ }
+
+ /* find service processor device */
+ rtcs = find_devices("service-processor");
+ if (!rtcs) {
+ printk(KERN_EMERG "Maple: Unable to find Service Processor\n");
+ printk(KERN_EMERG "Maple: Manual Power-Down Required\n");
+ return;
+ }
+ maple_nvram_offset = *(unsigned int*) get_property(rtcs,
+ "power-off-addr", NULL);
+ maple_nvram_command = *(unsigned int*) get_property(rtcs,
+ "power-off-value", NULL);
+
+ /* send command */
+ outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset);
+ for (;;) ;
}
static void maple_halt(void)
{
+ maple_power_off();
}
#ifdef CONFIG_SMP
@@ -235,6 +295,6 @@ struct machdep_calls __initdata maple_md = {
.get_boot_time = maple_get_boot_time,
.set_rtc_time = maple_set_rtc_time,
.get_rtc_time = maple_get_rtc_time,
- .calibrate_decr = maple_calibrate_decr,
+ .calibrate_decr = generic_calibrate_decr,
.progress = maple_progress,
};
diff --git a/arch/ppc64/kernel/maple_time.c b/arch/ppc64/kernel/maple_time.c
index 07ce7895b43..d65210abcd0 100644
--- a/arch/ppc64/kernel/maple_time.c
+++ b/arch/ppc64/kernel/maple_time.c
@@ -42,11 +42,8 @@
#define DBG(x...)
#endif
-extern void setup_default_decr(void);
extern void GregorianDay(struct rtc_time * tm);
-extern unsigned long ppc_tb_freq;
-extern unsigned long ppc_proc_freq;
static int maple_rtc_addr;
static int maple_clock_read(int addr)
@@ -176,51 +173,3 @@ void __init maple_get_boot_time(struct rtc_time *tm)
maple_get_rtc_time(tm);
}
-/* XXX FIXME: Some sane defaults: 125 MHz timebase, 1GHz processor */
-#define DEFAULT_TB_FREQ 125000000UL
-#define DEFAULT_PROC_FREQ (DEFAULT_TB_FREQ * 8)
-
-void __init maple_calibrate_decr(void)
-{
- struct device_node *cpu;
- struct div_result divres;
- unsigned int *fp = NULL;
-
- /*
- * The cpu node should have a timebase-frequency property
- * to tell us the rate at which the decrementer counts.
- */
- cpu = of_find_node_by_type(NULL, "cpu");
-
- ppc_tb_freq = DEFAULT_TB_FREQ;
- if (cpu != 0)
- fp = (unsigned int *)get_property(cpu, "timebase-frequency", NULL);
- if (fp != NULL)
- ppc_tb_freq = *fp;
- else
- printk(KERN_ERR "WARNING: Estimating decrementer frequency (not found)\n");
- fp = NULL;
- ppc_proc_freq = DEFAULT_PROC_FREQ;
- if (cpu != 0)
- fp = (unsigned int *)get_property(cpu, "clock-frequency", NULL);
- if (fp != NULL)
- ppc_proc_freq = *fp;
- else
- printk(KERN_ERR "WARNING: Estimating processor frequency (not found)\n");
-
- of_node_put(cpu);
-
- printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
- ppc_tb_freq/1000000, ppc_tb_freq%1000000);
- printk(KERN_INFO "time_init: processor frequency = %lu.%.6lu MHz\n",
- ppc_proc_freq/1000000, ppc_proc_freq%1000000);
-
- tb_ticks_per_jiffy = ppc_tb_freq / HZ;
- tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
- tb_ticks_per_usec = ppc_tb_freq / 1000000;
- tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
- div128_by_32(1024*1024, 0, tb_ticks_per_sec, &divres);
- tb_to_xs = divres.result_low;
-
- setup_default_decr();
-}
diff --git a/arch/ppc64/kernel/mf.c b/arch/ppc64/kernel/mf.c
index 1bd52ece497..d98bebf7042 100644
--- a/arch/ppc64/kernel/mf.c
+++ b/arch/ppc64/kernel/mf.c
@@ -1,7 +1,7 @@
/*
* mf.c
* Copyright (C) 2001 Troy D. Armstrong IBM Corporation
- * Copyright (C) 2004 Stephen Rothwell IBM Corporation
+ * Copyright (C) 2004-2005 Stephen Rothwell IBM Corporation
*
* This modules exists as an interface between a Linux secondary partition
* running on an iSeries and the primary partition's Virtual Service
@@ -36,10 +36,11 @@
#include <asm/time.h>
#include <asm/uaccess.h>
+#include <asm/paca.h>
#include <asm/iSeries/vio.h>
#include <asm/iSeries/mf.h>
#include <asm/iSeries/HvLpConfig.h>
-#include <asm/iSeries/ItSpCommArea.h>
+#include <asm/iSeries/ItLpQueue.h>
/*
* This is the structure layout for the Machine Facilites LPAR event
@@ -696,36 +697,23 @@ static void get_rtc_time_complete(void *token, struct ce_msg_data *ce_msg)
complete(&rtc->com);
}
-int mf_get_rtc(struct rtc_time *tm)
+static int rtc_set_tm(int rc, u8 *ce_msg, struct rtc_time *tm)
{
- struct ce_msg_comp_data ce_complete;
- struct rtc_time_data rtc_data;
- int rc;
-
- memset(&ce_complete, 0, sizeof(ce_complete));
- memset(&rtc_data, 0, sizeof(rtc_data));
- init_completion(&rtc_data.com);
- ce_complete.handler = &get_rtc_time_complete;
- ce_complete.token = &rtc_data;
- rc = signal_ce_msg_simple(0x40, &ce_complete);
- if (rc)
- return rc;
- wait_for_completion(&rtc_data.com);
tm->tm_wday = 0;
tm->tm_yday = 0;
tm->tm_isdst = 0;
- if (rtc_data.rc) {
+ if (rc) {
tm->tm_sec = 0;
tm->tm_min = 0;
tm->tm_hour = 0;
tm->tm_mday = 15;
tm->tm_mon = 5;
tm->tm_year = 52;
- return rtc_data.rc;
+ return rc;
}
- if ((rtc_data.ce_msg.ce_msg[2] == 0xa9) ||
- (rtc_data.ce_msg.ce_msg[2] == 0xaf)) {
+ if ((ce_msg[2] == 0xa9) ||
+ (ce_msg[2] == 0xaf)) {
/* TOD clock is not set */
tm->tm_sec = 1;
tm->tm_min = 1;
@@ -736,7 +724,6 @@ int mf_get_rtc(struct rtc_time *tm)
mf_set_rtc(tm);
}
{
- u8 *ce_msg = rtc_data.ce_msg.ce_msg;
u8 year = ce_msg[5];
u8 sec = ce_msg[6];
u8 min = ce_msg[7];
@@ -765,6 +752,63 @@ int mf_get_rtc(struct rtc_time *tm)
return 0;
}
+int mf_get_rtc(struct rtc_time *tm)
+{
+ struct ce_msg_comp_data ce_complete;
+ struct rtc_time_data rtc_data;
+ int rc;
+
+ memset(&ce_complete, 0, sizeof(ce_complete));
+ memset(&rtc_data, 0, sizeof(rtc_data));
+ init_completion(&rtc_data.com);
+ ce_complete.handler = &get_rtc_time_complete;
+ ce_complete.token = &rtc_data;
+ rc = signal_ce_msg_simple(0x40, &ce_complete);
+ if (rc)
+ return rc;
+ wait_for_completion(&rtc_data.com);
+ return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm);
+}
+
+struct boot_rtc_time_data {
+ int busy;
+ struct ce_msg_data ce_msg;
+ int rc;
+};
+
+static void get_boot_rtc_time_complete(void *token, struct ce_msg_data *ce_msg)
+{
+ struct boot_rtc_time_data *rtc = token;
+
+ memcpy(&rtc->ce_msg, ce_msg, sizeof(rtc->ce_msg));
+ rtc->rc = 0;
+ rtc->busy = 0;
+}
+
+int mf_get_boot_rtc(struct rtc_time *tm)
+{
+ struct ce_msg_comp_data ce_complete;
+ struct boot_rtc_time_data rtc_data;
+ int rc;
+
+ memset(&ce_complete, 0, sizeof(ce_complete));
+ memset(&rtc_data, 0, sizeof(rtc_data));
+ rtc_data.busy = 1;
+ ce_complete.handler = &get_boot_rtc_time_complete;
+ ce_complete.token = &rtc_data;
+ rc = signal_ce_msg_simple(0x40, &ce_complete);
+ if (rc)
+ return rc;
+ /* We need to poll here as we are not yet taking interrupts */
+ while (rtc_data.busy) {
+ extern unsigned long lpevent_count;
+ struct ItLpQueue *lpq = get_paca()->lpqueue_ptr;
+ if (lpq && ItLpQueue_isLpIntPending(lpq))
+ lpevent_count += ItLpQueue_process(lpq, NULL);
+ }
+ return rtc_set_tm(rtc_data.rc, rtc_data.ce_msg.ce_msg, tm);
+}
+
int mf_set_rtc(struct rtc_time *tm)
{
char ce_time[12];
diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
index b944717c1db..f3dea0c5a88 100644
--- a/arch/ppc64/kernel/misc.S
+++ b/arch/ppc64/kernel/misc.S
@@ -680,6 +680,177 @@ _GLOBAL(kernel_thread)
ld r30,-16(r1)
blr
+/* kexec_wait(phys_cpu)
+ *
+ * wait for the flag to change, indicating this kernel is going away but
+ * the slave code for the next one is at addresses 0 to 100.
+ *
+ * This is used by all slaves.
+ *
+ * Physical (hardware) cpu id should be in r3.
+ */
+_GLOBAL(kexec_wait)
+ bl 1f
+1: mflr r5
+ addi r5,r5,kexec_flag-1b
+
+99: HMT_LOW
+#ifdef CONFIG_KEXEC /* use no memory without kexec */
+ lwz r4,0(r5)
+ cmpwi 0,r4,0
+ bnea 0x60
+#endif
+ b 99b
+
+/* this can be in text because we won't change it until we are
+ * running in real anyways
+ */
+kexec_flag:
+ .long 0
+
+
+#ifdef CONFIG_KEXEC
+
+/* kexec_smp_wait(void)
+ *
+ * call with interrupts off
+ * note: this is a terminal routine, it does not save lr
+ *
+ * get phys id from paca
+ * set paca id to -1 to say we got here
+ * switch to real mode
+ * join other cpus in kexec_wait(phys_id)
+ */
+_GLOBAL(kexec_smp_wait)
+ lhz r3,PACAHWCPUID(r13)
+ li r4,-1
+ sth r4,PACAHWCPUID(r13) /* let others know we left */
+ bl real_mode
+ b .kexec_wait
+
+/*
+ * switch to real mode (turn mmu off)
+ * we use the early kernel trick that the hardware ignores bits
+ * 0 and 1 (big endian) of the effective address in real mode
+ *
+ * don't overwrite r3 here, it is live for kexec_wait above.
+ */
+real_mode: /* assume normal blr return */
+1: li r9,MSR_RI
+ li r10,MSR_DR|MSR_IR
+ mflr r11 /* return address to SRR0 */
+ mfmsr r12
+ andc r9,r12,r9
+ andc r10,r12,r10
+
+ mtmsrd r9,1
+ mtspr SPRN_SRR1,r10
+ mtspr SPRN_SRR0,r11
+ rfid
+
+
+/*
+ * kexec_sequence(newstack, start, image, control, clear_all())
+ *
+ * does the grungy work with stack switching and real mode switches
+ * also does simple calls to other code
+ */
+
+_GLOBAL(kexec_sequence)
+ mflr r0
+ std r0,16(r1)
+
+ /* switch stacks to newstack -- &kexec_stack.stack */
+ stdu r1,THREAD_SIZE-112(r3)
+ mr r1,r3
+
+ li r0,0
+ std r0,16(r1)
+
+ /* save regs for local vars on new stack.
+ * yes, we won't go back, but ...
+ */
+ std r31,-8(r1)
+ std r30,-16(r1)
+ std r29,-24(r1)
+ std r28,-32(r1)
+ std r27,-40(r1)
+ std r26,-48(r1)
+ std r25,-56(r1)
+
+ stdu r1,-112-64(r1)
+
+ /* save args into preserved regs */
+ mr r31,r3 /* newstack (both) */
+ mr r30,r4 /* start (real) */
+ mr r29,r5 /* image (virt) */
+ mr r28,r6 /* control, unused */
+ mr r27,r7 /* clear_all() fn desc */
+ mr r26,r8 /* spare */
+ lhz r25,PACAHWCPUID(r13) /* get our phys cpu from paca */
+
+ /* disable interrupts, we are overwriting kernel data next */
+ mfmsr r3
+ rlwinm r3,r3,0,17,15
+ mtmsrd r3,1
+
+ /* copy dest pages, flush whole dest image */
+ mr r3,r29
+ bl .kexec_copy_flush /* (image) */
+
+ /* turn off mmu */
+ bl real_mode
+
+ /* clear out hardware hash page table and tlb */
+ ld r5,0(r27) /* deref function descriptor */
+ mtctr r5
+ bctrl /* ppc_md.hash_clear_all(void); */
+
+/*
+ * kexec image calling is:
+ * the first 0x100 bytes of the entry point are copied to 0
+ *
+ * all slaves branch to slave = 0x60 (absolute)
+ * slave(phys_cpu_id);
+ *
+ * master goes to start = entry point
+ * start(phys_cpu_id, start, 0);
+ *
+ *
+ * a wrapper is needed to call existing kernels, here is an approximate
+ * description of one method:
+ *
+ * v2: (2.6.10)
+ * start will be near the boot_block (maybe 0x100 bytes before it?)
+ * it will have a 0x60, which will b to boot_block, where it will wait
+ * and 0 will store phys into struct boot-block and load r3 from there,
+ * copy kernel 0-0x100 and tell slaves to back down to 0x60 again
+ *
+ * v1: (2.6.9)
+ * boot block will have all cpus scanning device tree to see if they
+ * are the boot cpu ?????
+ * other device tree differences (prop sizes, va vs pa, etc)...
+ */
+
+ /* copy 0x100 bytes starting at start to 0 */
+ li r3,0
+ mr r4,r30
+ li r5,0x100
+ li r6,0
+ bl .copy_and_flush /* (dest, src, copy limit, start offset) */
+1: /* assume normal blr return */
+
+ /* release other cpus to the new kernel secondary start at 0x60 */
+ mflr r5
+ li r6,1
+ stw r6,kexec_flag-1b(5)
+ mr r3,r25 # my phys cpu
+ mr r4,r30 # start, aka phys mem offset
+ mtlr 4
+ li r5,0
+ blr /* image->start(physid, image->start, 0); */
+#endif /* CONFIG_KEXEC */
+
/* Why isn't this a) automatic, b) written in 'C'? */
.balign 8
_GLOBAL(sys_call_table32)
@@ -792,7 +963,7 @@ _GLOBAL(sys_call_table32)
.llong .compat_sys_newstat
.llong .compat_sys_newlstat
.llong .compat_sys_newfstat
- .llong .sys_uname
+ .llong .sys32_uname
.llong .sys_ni_syscall /* 110 old iopl syscall */
.llong .sys_vhangup
.llong .sys_ni_syscall /* old idle syscall */
@@ -951,7 +1122,7 @@ _GLOBAL(sys_call_table32)
.llong .compat_sys_mq_timedreceive /* 265 */
.llong .compat_sys_mq_notify
.llong .compat_sys_mq_getsetattr
- .llong .sys_ni_syscall /* 268 reserved for sys_kexec_load */
+ .llong .compat_sys_kexec_load
.llong .sys32_add_key
.llong .sys32_request_key
.llong .compat_sys_keyctl
@@ -1227,7 +1398,7 @@ _GLOBAL(sys_call_table)
.llong .sys_mq_timedreceive /* 265 */
.llong .sys_mq_notify
.llong .sys_mq_getsetattr
- .llong .sys_ni_syscall /* 268 reserved for sys_kexec_load */
+ .llong .sys_kexec_load
.llong .sys_add_key
.llong .sys_request_key /* 270 */
.llong .sys_keyctl
diff --git a/arch/ppc64/kernel/mpic.c b/arch/ppc64/kernel/mpic.c
index 593ea5b82af..e8fbab1df37 100644
--- a/arch/ppc64/kernel/mpic.c
+++ b/arch/ppc64/kernel/mpic.c
@@ -792,6 +792,35 @@ void mpic_setup_this_cpu(void)
#endif /* CONFIG_SMP */
}
+/*
+ * XXX: someone who knows mpic should check this.
+ * do we need to eoi the ipi here (see xics comments)?
+ * or can we reset the mpic in the new kernel?
+ */
+void mpic_teardown_this_cpu(void)
+{
+ struct mpic *mpic = mpic_primary;
+ unsigned long flags;
+ u32 msk = 1 << hard_smp_processor_id();
+ unsigned int i;
+
+ BUG_ON(mpic == NULL);
+
+ DBG("%s: teardown_this_cpu(%d)\n", mpic->name, hard_smp_processor_id());
+ spin_lock_irqsave(&mpic_lock, flags);
+
+ /* 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);
+
+ /* Set current processor priority to max */
+ mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf);
+
+ spin_unlock_irqrestore(&mpic_lock, flags);
+}
+
+
void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask)
{
struct mpic *mpic = mpic_primary;
diff --git a/arch/ppc64/kernel/mpic.h b/arch/ppc64/kernel/mpic.h
index 571b3c99e06..99fbbc9a084 100644
--- a/arch/ppc64/kernel/mpic.h
+++ b/arch/ppc64/kernel/mpic.h
@@ -255,6 +255,9 @@ extern unsigned int mpic_irq_get_priority(unsigned int irq);
/* Setup a non-boot CPU */
extern void mpic_setup_this_cpu(void);
+/* Clean up for kexec (or cpu offline or ...) */
+extern void mpic_teardown_this_cpu(void);
+
/* Request IPIs on primary mpic */
extern void mpic_request_ipis(void);
@@ -265,3 +268,6 @@ extern void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask);
extern int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs);
/* This one gets to the primary mpic */
extern int mpic_get_irq(struct pt_regs *regs);
+
+/* global mpic for pSeries */
+extern struct mpic *pSeries_mpic;
diff --git a/arch/ppc64/kernel/of_device.c b/arch/ppc64/kernel/of_device.c
index f4c825a69fa..66bd5ab7c25 100644
--- a/arch/ppc64/kernel/of_device.c
+++ b/arch/ppc64/kernel/of_device.c
@@ -161,7 +161,7 @@ void of_unregister_driver(struct of_platform_driver *drv)
}
-static ssize_t dev_show_devspec(struct device *dev, char *buf)
+static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
{
struct of_device *ofdev;
diff --git a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c
index 0b1cca28140..1f5f141fb7a 100644
--- a/arch/ppc64/kernel/pSeries_pci.c
+++ b/arch/ppc64/kernel/pSeries_pci.c
@@ -1,13 +1,11 @@
/*
- * pSeries_pci.c
+ * arch/ppc64/kernel/pSeries_pci.c
*
* Copyright (C) 2001 Dave Engebretsen, IBM Corporation
* Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM
*
* pSeries specific routines for PCI.
*
- * Based on code from pci.c and chrp_pci.c
- *
* 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
@@ -23,430 +21,18 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/init.h>
+#include <linux/ioport.h>
#include <linux/kernel.h>
-#include <linux/threads.h>
#include <linux/pci.h>
#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
#include <asm/pci-bridge.h>
-#include <asm/iommu.h>
-#include <asm/rtas.h>
+#include <asm/prom.h>
-#include "mpic.h"
#include "pci.h"
-/* RTAS tokens */
-static int read_pci_config;
-static int write_pci_config;
-static int ibm_read_pci_config;
-static int ibm_write_pci_config;
-
-static int s7a_workaround;
-
-extern struct mpic *pSeries_mpic;
-
-static int config_access_valid(struct device_node *dn, int where)
-{
- if (where < 256)
- return 1;
- if (where < 4096 && dn->pci_ext_config_space)
- return 1;
-
- return 0;
-}
-
-static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val)
-{
- int returnval = -1;
- unsigned long buid, addr;
- int ret;
-
- if (!dn)
- return PCIBIOS_DEVICE_NOT_FOUND;
- if (!config_access_valid(dn, where))
- return PCIBIOS_BAD_REGISTER_NUMBER;
-
- addr = ((where & 0xf00) << 20) | (dn->busno << 16) |
- (dn->devfn << 8) | (where & 0xff);
- buid = dn->phb->buid;
- if (buid) {
- ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval,
- addr, buid >> 32, buid & 0xffffffff, size);
- } else {
- ret = rtas_call(read_pci_config, 2, 2, &returnval, addr, size);
- }
- *val = returnval;
-
- if (ret)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- if (returnval == EEH_IO_ERROR_VALUE(size)
- && eeh_dn_check_failure (dn, NULL))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int rtas_pci_read_config(struct pci_bus *bus,
- unsigned int devfn,
- int where, int size, u32 *val)
-{
- struct device_node *busdn, *dn;
-
- if (bus->self)
- busdn = pci_device_to_OF_node(bus->self);
- else
- busdn = bus->sysdata; /* must be a phb */
-
- /* Search only direct children of the bus */
- for (dn = busdn->child; dn; dn = dn->sibling)
- if (dn->devfn == devfn)
- return rtas_read_config(dn, where, size, val);
- return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-static int rtas_write_config(struct device_node *dn, int where, int size, u32 val)
-{
- unsigned long buid, addr;
- int ret;
-
- if (!dn)
- return PCIBIOS_DEVICE_NOT_FOUND;
- if (!config_access_valid(dn, where))
- return PCIBIOS_BAD_REGISTER_NUMBER;
-
- addr = ((where & 0xf00) << 20) | (dn->busno << 16) |
- (dn->devfn << 8) | (where & 0xff);
- buid = dn->phb->buid;
- if (buid) {
- ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr, buid >> 32, buid & 0xffffffff, size, (ulong) val);
- } else {
- ret = rtas_call(write_pci_config, 3, 1, NULL, addr, size, (ulong)val);
- }
-
- if (ret)
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int rtas_pci_write_config(struct pci_bus *bus,
- unsigned int devfn,
- int where, int size, u32 val)
-{
- struct device_node *busdn, *dn;
-
- if (bus->self)
- busdn = pci_device_to_OF_node(bus->self);
- else
- busdn = bus->sysdata; /* must be a phb */
-
- /* Search only direct children of the bus */
- for (dn = busdn->child; dn; dn = dn->sibling)
- if (dn->devfn == devfn)
- return rtas_write_config(dn, where, size, val);
- return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-struct pci_ops rtas_pci_ops = {
- rtas_pci_read_config,
- rtas_pci_write_config
-};
-
-int is_python(struct device_node *dev)
-{
- char *model = (char *)get_property(dev, "model", NULL);
-
- if (model && strstr(model, "Python"))
- return 1;
-
- return 0;
-}
-
-static int get_phb_reg_prop(struct device_node *dev,
- unsigned int addr_size_words,
- struct reg_property64 *reg)
-{
- unsigned int *ui_ptr = NULL, len;
-
- /* Found a PHB, now figure out where his registers are mapped. */
- ui_ptr = (unsigned int *)get_property(dev, "reg", &len);
- if (ui_ptr == NULL)
- return 1;
-
- if (addr_size_words == 1) {
- reg->address = ((struct reg_property32 *)ui_ptr)->address;
- reg->size = ((struct reg_property32 *)ui_ptr)->size;
- } else {
- *reg = *((struct reg_property64 *)ui_ptr);
- }
-
- return 0;
-}
-
-static void python_countermeasures(struct device_node *dev,
- unsigned int addr_size_words)
-{
- struct reg_property64 reg_struct;
- void __iomem *chip_regs;
- volatile u32 val;
-
- if (get_phb_reg_prop(dev, addr_size_words, &reg_struct))
- return;
-
- /* Python's register file is 1 MB in size. */
- chip_regs = ioremap(reg_struct.address & ~(0xfffffUL), 0x100000);
-
- /*
- * Firmware doesn't always clear this bit which is critical
- * for good performance - Anton
- */
-
-#define PRG_CL_RESET_VALID 0x00010000
-
- val = in_be32(chip_regs + 0xf6030);
- if (val & PRG_CL_RESET_VALID) {
- printk(KERN_INFO "Python workaround: ");
- val &= ~PRG_CL_RESET_VALID;
- out_be32(chip_regs + 0xf6030, val);
- /*
- * We must read it back for changes to
- * take effect
- */
- val = in_be32(chip_regs + 0xf6030);
- printk("reg0: %x\n", val);
- }
-
- iounmap(chip_regs);
-}
-
-void __init init_pci_config_tokens (void)
-{
- read_pci_config = rtas_token("read-pci-config");
- write_pci_config = rtas_token("write-pci-config");
- ibm_read_pci_config = rtas_token("ibm,read-pci-config");
- ibm_write_pci_config = rtas_token("ibm,write-pci-config");
-}
-
-unsigned long __devinit get_phb_buid (struct device_node *phb)
-{
- int addr_cells;
- unsigned int *buid_vals;
- unsigned int len;
- unsigned long buid;
-
- if (ibm_read_pci_config == -1) return 0;
-
- /* PHB's will always be children of the root node,
- * or so it is promised by the current firmware. */
- if (phb->parent == NULL)
- return 0;
- if (phb->parent->parent)
- return 0;
-
- buid_vals = (unsigned int *) get_property(phb, "reg", &len);
- if (buid_vals == NULL)
- return 0;
-
- addr_cells = prom_n_addr_cells(phb);
- if (addr_cells == 1) {
- buid = (unsigned long) buid_vals[0];
- } else {
- buid = (((unsigned long)buid_vals[0]) << 32UL) |
- (((unsigned long)buid_vals[1]) & 0xffffffff);
- }
- return buid;
-}
-
-static int phb_set_bus_ranges(struct device_node *dev,
- struct pci_controller *phb)
-{
- int *bus_range;
- unsigned int len;
-
- bus_range = (int *) get_property(dev, "bus-range", &len);
- if (bus_range == NULL || len < 2 * sizeof(int)) {
- return 1;
- }
-
- phb->first_busno = bus_range[0];
- phb->last_busno = bus_range[1];
-
- return 0;
-}
-
-static int __devinit setup_phb(struct device_node *dev,
- struct pci_controller *phb,
- unsigned int addr_size_words)
-{
- pci_setup_pci_controller(phb);
-
- if (is_python(dev))
- python_countermeasures(dev, addr_size_words);
-
- if (phb_set_bus_ranges(dev, phb))
- return 1;
-
- phb->arch_data = dev;
- phb->ops = &rtas_pci_ops;
- phb->buid = get_phb_buid(dev);
-
- return 0;
-}
-
-static void __devinit add_linux_pci_domain(struct device_node *dev,
- struct pci_controller *phb,
- struct property *of_prop)
-{
- memset(of_prop, 0, sizeof(struct property));
- of_prop->name = "linux,pci-domain";
- of_prop->length = sizeof(phb->global_number);
- of_prop->value = (unsigned char *)&of_prop[1];
- memcpy(of_prop->value, &phb->global_number, sizeof(phb->global_number));
- prom_add_property(dev, of_prop);
-}
-
-static struct pci_controller * __init alloc_phb(struct device_node *dev,
- unsigned int addr_size_words)
-{
- struct pci_controller *phb;
- struct property *of_prop;
-
- phb = alloc_bootmem(sizeof(struct pci_controller));
- if (phb == NULL)
- return NULL;
-
- of_prop = alloc_bootmem(sizeof(struct property) +
- sizeof(phb->global_number));
- if (!of_prop)
- return NULL;
-
- if (setup_phb(dev, phb, addr_size_words))
- return NULL;
-
- add_linux_pci_domain(dev, phb, of_prop);
-
- return phb;
-}
-
-static struct pci_controller * __devinit alloc_phb_dynamic(struct device_node *dev, unsigned int addr_size_words)
-{
- struct pci_controller *phb;
-
- phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller),
- GFP_KERNEL);
- if (phb == NULL)
- return NULL;
-
- if (setup_phb(dev, phb, addr_size_words))
- return NULL;
-
- phb->is_dynamic = 1;
-
- /* TODO: linux,pci-domain? */
-
- return phb;
-}
-
-unsigned long __init find_and_init_phbs(void)
-{
- struct device_node *node;
- struct pci_controller *phb;
- unsigned int root_size_cells = 0;
- unsigned int index;
- unsigned int *opprop = NULL;
- struct device_node *root = of_find_node_by_path("/");
-
- if (ppc64_interrupt_controller == IC_OPEN_PIC) {
- opprop = (unsigned int *)get_property(root,
- "platform-open-pic", NULL);
- }
-
- root_size_cells = prom_n_size_cells(root);
-
- index = 0;
-
- for (node = of_get_next_child(root, NULL);
- node != NULL;
- node = of_get_next_child(root, node)) {
- if (node->type == NULL || strcmp(node->type, "pci") != 0)
- continue;
-
- phb = alloc_phb(node, root_size_cells);
- if (!phb)
- continue;
-
- pci_process_bridge_OF_ranges(phb, node);
- pci_setup_phb_io(phb, index == 0);
-
- if (ppc64_interrupt_controller == IC_OPEN_PIC && pSeries_mpic) {
- int addr = root_size_cells * (index + 2) - 1;
- mpic_assign_isu(pSeries_mpic, index, opprop[addr]);
- }
-
- index++;
- }
-
- of_node_put(root);
- pci_devs_phb_init();
-
- /*
- * pci_probe_only and pci_assign_all_buses can be set via properties
- * in chosen.
- */
- if (of_chosen) {
- int *prop;
-
- prop = (int *)get_property(of_chosen, "linux,pci-probe-only",
- NULL);
- if (prop)
- pci_probe_only = *prop;
-
- prop = (int *)get_property(of_chosen,
- "linux,pci-assign-all-buses", NULL);
- if (prop)
- pci_assign_all_buses = *prop;
- }
-
- return 0;
-}
-
-struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
-{
- struct device_node *root = of_find_node_by_path("/");
- unsigned int root_size_cells = 0;
- struct pci_controller *phb;
- struct pci_bus *bus;
- int primary;
-
- root_size_cells = prom_n_size_cells(root);
-
- primary = list_empty(&hose_list);
- phb = alloc_phb_dynamic(dn, root_size_cells);
- if (!phb)
- return NULL;
-
- pci_process_bridge_OF_ranges(phb, dn);
-
- pci_setup_phb_io_dynamic(phb, primary);
- of_node_put(root);
-
- pci_devs_phb_init_dynamic(phb);
- phb->last_busno = 0xff;
- bus = pci_scan_bus(phb->first_busno, phb->ops, phb->arch_data);
- phb->bus = bus;
- phb->last_busno = bus->subordinate;
-
- return phb;
-}
-EXPORT_SYMBOL(init_phb_dynamic);
+static int __initdata s7a_workaround = -1;
#if 0
void pcibios_name_device(struct pci_dev *dev)
@@ -474,11 +60,12 @@ void pcibios_name_device(struct pci_dev *dev)
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device);
#endif
-static void check_s7a(void)
+static void __init check_s7a(void)
{
struct device_node *root;
char *model;
+ s7a_workaround = 0;
root = of_find_node_by_path("/");
if (root) {
model = get_property(root, "model", NULL);
@@ -488,55 +75,23 @@ static void check_s7a(void)
}
}
-/* RPA-specific bits for removing PHBs */
-int pcibios_remove_root_bus(struct pci_controller *phb)
+void __devinit pSeries_irq_bus_setup(struct pci_bus *bus)
{
- struct pci_bus *b = phb->bus;
- struct resource *res;
- int rc, i;
-
- res = b->resource[0];
- if (!res->flags) {
- printk(KERN_ERR "%s: no IO resource for PHB %s\n", __FUNCTION__,
- b->name);
- return 1;
- }
-
- rc = unmap_bus_range(b);
- if (rc) {
- printk(KERN_ERR "%s: failed to unmap IO on bus %s\n",
- __FUNCTION__, b->name);
- return 1;
- }
+ struct pci_dev *dev;
- if (release_resource(res)) {
- printk(KERN_ERR "%s: failed to release IO on bus %s\n",
- __FUNCTION__, b->name);
- return 1;
- }
-
- for (i = 1; i < 3; ++i) {
- res = b->resource[i];
- if (!res->flags && i == 0) {
- printk(KERN_ERR "%s: no MEM resource for PHB %s\n",
- __FUNCTION__, b->name);
- return 1;
- }
- if (res->flags && release_resource(res)) {
- printk(KERN_ERR
- "%s: failed to release IO %d on bus %s\n",
- __FUNCTION__, i, b->name);
- return 1;
+ if (s7a_workaround < 0)
+ check_s7a();
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ pci_read_irq_line(dev);
+ if (s7a_workaround) {
+ if (dev->irq > 16) {
+ dev->irq -= 3;
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
+ dev->irq);
+ }
}
}
-
- list_del(&phb->list_node);
- if (phb->is_dynamic)
- kfree(phb);
-
- return 0;
}
-EXPORT_SYMBOL(pcibios_remove_root_bus);
static void __init pSeries_request_regions(void)
{
@@ -553,20 +108,6 @@ static void __init pSeries_request_regions(void)
void __init pSeries_final_fixup(void)
{
- struct pci_dev *dev = NULL;
-
- check_s7a();
-
- for_each_pci_dev(dev) {
- pci_read_irq_line(dev);
- if (s7a_workaround) {
- if (dev->irq > 16) {
- dev->irq -= 3;
- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
- }
- }
- }
-
phbs_remap_io();
pSeries_request_regions();
diff --git a/arch/ppc64/kernel/pSeries_reconfig.c b/arch/ppc64/kernel/pSeries_reconfig.c
index cb5443f2e49..dc2a69d412a 100644
--- a/arch/ppc64/kernel/pSeries_reconfig.c
+++ b/arch/ppc64/kernel/pSeries_reconfig.c
@@ -47,14 +47,6 @@ static void remove_node_proc_entries(struct device_node *np)
remove_proc_entry(pp->name, np->pde);
pp = pp->next;
}
-
- /* Assuming that symlinks have the same parent directory as
- * np->pde.
- */
- if (np->name_link)
- remove_proc_entry(np->name_link->name, parent->pde);
- if (np->addr_link)
- remove_proc_entry(np->addr_link->name, parent->pde);
if (np->pde)
remove_proc_entry(np->pde->name, parent->pde);
}
diff --git a/arch/ppc64/kernel/pSeries_setup.c b/arch/ppc64/kernel/pSeries_setup.c
index 6c0d1d58a55..44d9af72d22 100644
--- a/arch/ppc64/kernel/pSeries_setup.c
+++ b/arch/ppc64/kernel/pSeries_setup.c
@@ -71,11 +71,6 @@
#define DBG(fmt...)
#endif
-extern void pSeries_final_fixup(void);
-
-extern void pSeries_get_boot_time(struct rtc_time *rtc_time);
-extern void pSeries_get_rtc_time(struct rtc_time *rtc_time);
-extern int pSeries_set_rtc_time(struct rtc_time *rtc_time);
extern void find_udbg_vterm(void);
extern void system_reset_fwnmi(void); /* from head.S */
extern void machine_check_fwnmi(void); /* from head.S */
@@ -84,9 +79,6 @@ extern void generic_find_legacy_serial_ports(u64 *physport,
int fwnmi_active; /* TRUE if an FWNMI handler is present */
-extern unsigned long ppc_proc_freq;
-extern unsigned long ppc_tb_freq;
-
extern void pSeries_system_reset_exception(struct pt_regs *regs);
extern int pSeries_machine_check_exception(struct pt_regs *regs);
@@ -195,14 +187,16 @@ static void __init pSeries_setup_arch(void)
{
/* Fixup ppc_md depending on the type of interrupt controller */
if (ppc64_interrupt_controller == IC_OPEN_PIC) {
- ppc_md.init_IRQ = pSeries_init_mpic;
+ ppc_md.init_IRQ = pSeries_init_mpic;
ppc_md.get_irq = mpic_get_irq;
+ ppc_md.cpu_irq_down = mpic_teardown_this_cpu;
/* Allocate the mpic now, so that find_and_init_phbs() can
* fill the ISUs */
pSeries_setup_mpic();
} else {
ppc_md.init_IRQ = xics_init_IRQ;
ppc_md.get_irq = xics_get_irq;
+ ppc_md.cpu_irq_down = xics_teardown_cpu;
}
#ifdef CONFIG_SMP
@@ -381,171 +375,6 @@ static void __init pSeries_init_early(void)
}
-static void pSeries_progress(char *s, unsigned short hex)
-{
- struct device_node *root;
- int width, *p;
- char *os;
- static int display_character, set_indicator;
- static int max_width;
- static DEFINE_SPINLOCK(progress_lock);
- static int pending_newline = 0; /* did last write end with unprinted newline? */
-
- if (!rtas.base)
- return;
-
- if (max_width == 0) {
- if ((root = find_path_device("/rtas")) &&
- (p = (unsigned int *)get_property(root,
- "ibm,display-line-length",
- NULL)))
- max_width = *p;
- else
- max_width = 0x10;
- display_character = rtas_token("display-character");
- set_indicator = rtas_token("set-indicator");
- }
-
- if (display_character == RTAS_UNKNOWN_SERVICE) {
- /* use hex display if available */
- if (set_indicator != RTAS_UNKNOWN_SERVICE)
- rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex);
- return;
- }
-
- spin_lock(&progress_lock);
-
- /*
- * Last write ended with newline, but we didn't print it since
- * it would just clear the bottom line of output. Print it now
- * instead.
- *
- * If no newline is pending, print a CR to start output at the
- * beginning of the line.
- */
- if (pending_newline) {
- rtas_call(display_character, 1, 1, NULL, '\r');
- rtas_call(display_character, 1, 1, NULL, '\n');
- pending_newline = 0;
- } else {
- rtas_call(display_character, 1, 1, NULL, '\r');
- }
-
- width = max_width;
- os = s;
- while (*os) {
- if (*os == '\n' || *os == '\r') {
- /* Blank to end of line. */
- while (width-- > 0)
- rtas_call(display_character, 1, 1, NULL, ' ');
-
- /* If newline is the last character, save it
- * until next call to avoid bumping up the
- * display output.
- */
- if (*os == '\n' && !os[1]) {
- pending_newline = 1;
- spin_unlock(&progress_lock);
- return;
- }
-
- /* RTAS wants CR-LF, not just LF */
-
- if (*os == '\n') {
- rtas_call(display_character, 1, 1, NULL, '\r');
- rtas_call(display_character, 1, 1, NULL, '\n');
- } else {
- /* CR might be used to re-draw a line, so we'll
- * leave it alone and not add LF.
- */
- rtas_call(display_character, 1, 1, NULL, *os);
- }
-
- width = max_width;
- } else {
- width--;
- rtas_call(display_character, 1, 1, NULL, *os);
- }
-
- os++;
-
- /* if we overwrite the screen length */
- if (width <= 0)
- while ((*os != 0) && (*os != '\n') && (*os != '\r'))
- os++;
- }
-
- /* Blank to end of line. */
- while (width-- > 0)
- rtas_call(display_character, 1, 1, NULL, ' ');
-
- spin_unlock(&progress_lock);
-}
-
-extern void setup_default_decr(void);
-
-/* Some sane defaults: 125 MHz timebase, 1GHz processor */
-#define DEFAULT_TB_FREQ 125000000UL
-#define DEFAULT_PROC_FREQ (DEFAULT_TB_FREQ * 8)
-
-static void __init pSeries_calibrate_decr(void)
-{
- struct device_node *cpu;
- struct div_result divres;
- unsigned int *fp;
- int node_found;
-
- /*
- * The cpu node should have a timebase-frequency property
- * to tell us the rate at which the decrementer counts.
- */
- cpu = of_find_node_by_type(NULL, "cpu");
-
- ppc_tb_freq = DEFAULT_TB_FREQ; /* hardcoded default */
- node_found = 0;
- if (cpu != 0) {
- fp = (unsigned int *)get_property(cpu, "timebase-frequency",
- NULL);
- if (fp != 0) {
- node_found = 1;
- ppc_tb_freq = *fp;
- }
- }
- if (!node_found)
- printk(KERN_ERR "WARNING: Estimating decrementer frequency "
- "(not found)\n");
-
- ppc_proc_freq = DEFAULT_PROC_FREQ;
- node_found = 0;
- if (cpu != 0) {
- fp = (unsigned int *)get_property(cpu, "clock-frequency",
- NULL);
- if (fp != 0) {
- node_found = 1;
- ppc_proc_freq = *fp;
- }
- }
- if (!node_found)
- printk(KERN_ERR "WARNING: Estimating processor frequency "
- "(not found)\n");
-
- of_node_put(cpu);
-
- printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
- ppc_tb_freq/1000000, ppc_tb_freq%1000000);
- printk(KERN_INFO "time_init: processor frequency = %lu.%.6lu MHz\n",
- ppc_proc_freq/1000000, ppc_proc_freq%1000000);
-
- tb_ticks_per_jiffy = ppc_tb_freq / HZ;
- tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
- tb_ticks_per_usec = ppc_tb_freq / 1000000;
- tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
- div128_by_32(1024*1024, 0, tb_ticks_per_sec, &divres);
- tb_to_xs = divres.result_low;
-
- setup_default_decr();
-}
-
static int pSeries_check_legacy_ioport(unsigned int baseport)
{
struct device_node *np;
@@ -596,16 +425,17 @@ struct machdep_calls __initdata pSeries_md = {
.get_cpuinfo = pSeries_get_cpuinfo,
.log_error = pSeries_log_error,
.pcibios_fixup = pSeries_final_fixup,
+ .irq_bus_setup = pSeries_irq_bus_setup,
.restart = rtas_restart,
.power_off = rtas_power_off,
.halt = rtas_halt,
.panic = rtas_os_term,
.cpu_die = pSeries_mach_cpu_die,
- .get_boot_time = pSeries_get_boot_time,
- .get_rtc_time = pSeries_get_rtc_time,
- .set_rtc_time = pSeries_set_rtc_time,
- .calibrate_decr = pSeries_calibrate_decr,
- .progress = pSeries_progress,
+ .get_boot_time = rtas_get_boot_time,
+ .get_rtc_time = rtas_get_rtc_time,
+ .set_rtc_time = rtas_set_rtc_time,
+ .calibrate_decr = generic_calibrate_decr,
+ .progress = rtas_progress,
.check_legacy_ioport = pSeries_check_legacy_ioport,
.system_reset_exception = pSeries_system_reset_exception,
.machine_check_exception = pSeries_machine_check_exception,
diff --git a/arch/ppc64/kernel/pSeries_smp.c b/arch/ppc64/kernel/pSeries_smp.c
index fbad349ec58..62c55a12356 100644
--- a/arch/ppc64/kernel/pSeries_smp.c
+++ b/arch/ppc64/kernel/pSeries_smp.c
@@ -1,5 +1,5 @@
/*
- * SMP support for pSeries machines.
+ * SMP support for pSeries and BPA machines.
*
* Dave Engebretsen, Peter Bergner, and
* Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
@@ -47,6 +47,7 @@
#include <asm/pSeries_reconfig.h>
#include "mpic.h"
+#include "bpa_iic.h"
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
@@ -92,10 +93,13 @@ static int query_cpu_stopped(unsigned int pcpu)
int pSeries_cpu_disable(void)
{
+ int cpu = smp_processor_id();
+
+ cpu_clear(cpu, cpu_online_map);
systemcfg->processorCount--;
/*fix boot_cpuid here*/
- if (smp_processor_id() == boot_cpuid)
+ if (cpu == boot_cpuid)
boot_cpuid = any_online_cpu(cpu_online_map);
/* FIXME: abstract this to not be platform specific later on */
@@ -286,6 +290,7 @@ static inline int __devinit smp_startup_cpu(unsigned int lcpu)
return 1;
}
+#ifdef CONFIG_XICS
static inline void smp_xics_do_message(int cpu, int msg)
{
set_bit(msg, &xics_ipi_message[cpu].value);
@@ -327,6 +332,37 @@ static void __devinit smp_xics_setup_cpu(int cpu)
cpu_clear(cpu, of_spin_map);
}
+#endif /* CONFIG_XICS */
+#ifdef CONFIG_BPA_IIC
+static void smp_iic_message_pass(int target, int msg)
+{
+ unsigned int i;
+
+ if (target < NR_CPUS) {
+ iic_cause_IPI(target, msg);
+ } else {
+ for_each_online_cpu(i) {
+ if (target == MSG_ALL_BUT_SELF
+ && i == smp_processor_id())
+ continue;
+ iic_cause_IPI(i, msg);
+ }
+ }
+}
+
+static int __init smp_iic_probe(void)
+{
+ iic_request_IPIs();
+
+ return cpus_weight(cpu_possible_map);
+}
+
+static void __devinit smp_iic_setup_cpu(int cpu)
+{
+ if (cpu != boot_cpuid)
+ iic_setup_cpu();
+}
+#endif /* CONFIG_BPA_IIC */
static DEFINE_SPINLOCK(timebase_lock);
static unsigned long timebase = 0;
@@ -375,20 +411,21 @@ static int smp_pSeries_cpu_bootable(unsigned int nr)
* cpus are assumed to be secondary threads.
*/
if (system_state < SYSTEM_RUNNING &&
- cur_cpu_spec->cpu_features & CPU_FTR_SMT &&
+ cpu_has_feature(CPU_FTR_SMT) &&
!smt_enabled_at_boot && nr % 2 != 0)
return 0;
return 1;
}
-
+#ifdef CONFIG_MPIC
static struct smp_ops_t pSeries_mpic_smp_ops = {
.message_pass = smp_mpic_message_pass,
.probe = smp_mpic_probe,
.kick_cpu = smp_pSeries_kick_cpu,
.setup_cpu = smp_mpic_setup_cpu,
};
-
+#endif
+#ifdef CONFIG_XICS
static struct smp_ops_t pSeries_xics_smp_ops = {
.message_pass = smp_xics_message_pass,
.probe = smp_xics_probe,
@@ -396,6 +433,16 @@ static struct smp_ops_t pSeries_xics_smp_ops = {
.setup_cpu = smp_xics_setup_cpu,
.cpu_bootable = smp_pSeries_cpu_bootable,
};
+#endif
+#ifdef CONFIG_BPA_IIC
+static struct smp_ops_t bpa_iic_smp_ops = {
+ .message_pass = smp_iic_message_pass,
+ .probe = smp_iic_probe,
+ .kick_cpu = smp_pSeries_kick_cpu,
+ .setup_cpu = smp_iic_setup_cpu,
+ .cpu_bootable = smp_pSeries_cpu_bootable,
+};
+#endif
/* This is called very early */
void __init smp_init_pSeries(void)
@@ -404,10 +451,25 @@ void __init smp_init_pSeries(void)
DBG(" -> smp_init_pSeries()\n");
- if (ppc64_interrupt_controller == IC_OPEN_PIC)
+ switch (ppc64_interrupt_controller) {
+#ifdef CONFIG_MPIC
+ case IC_OPEN_PIC:
smp_ops = &pSeries_mpic_smp_ops;
- else
+ break;
+#endif
+#ifdef CONFIG_XICS
+ case IC_PPC_XIC:
smp_ops = &pSeries_xics_smp_ops;
+ break;
+#endif
+#ifdef CONFIG_BPA_IIC
+ case IC_BPA_IIC:
+ smp_ops = &bpa_iic_smp_ops;
+ break;
+#endif
+ default:
+ panic("Invalid interrupt controller");
+ }
#ifdef CONFIG_HOTPLUG_CPU
smp_ops->cpu_disable = pSeries_cpu_disable;
@@ -419,8 +481,8 @@ void __init smp_init_pSeries(void)
#endif
/* Mark threads which are still spinning in hold loops. */
- if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
- for_each_present_cpu(i) {
+ if (cpu_has_feature(CPU_FTR_SMT)) {
+ for_each_present_cpu(i) {
if (i % 2 == 0)
/*
* Even-numbered logical cpus correspond to
@@ -428,8 +490,9 @@ void __init smp_init_pSeries(void)
*/
cpu_set(i, of_spin_map);
}
- else
+ } else {
of_spin_map = cpu_present_map;
+ }
cpu_clear(boot_cpuid, of_spin_map);
diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c
index d786d4b6af0..580676f87d2 100644
--- a/arch/ppc64/kernel/pci.c
+++ b/arch/ppc64/kernel/pci.c
@@ -507,7 +507,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
}
#ifdef CONFIG_PPC_MULTIPLATFORM
-static ssize_t pci_show_devspec(struct device *dev, char *buf)
+static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pci_dev *pdev;
struct device_node *np;
@@ -902,6 +902,9 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
list_for_each_entry(dev, &bus->devices, bus_list)
ppc_md.iommu_dev_setup(dev);
+ if (ppc_md.irq_bus_setup)
+ ppc_md.irq_bus_setup(bus);
+
if (!pci_probe_only)
return;
diff --git a/arch/ppc64/kernel/pci.h b/arch/ppc64/kernel/pci.h
index 0fd7d849aa7..26be78b13af 100644
--- a/arch/ppc64/kernel/pci.h
+++ b/arch/ppc64/kernel/pci.h
@@ -40,10 +40,14 @@ struct device_node *fetch_dev_dn(struct pci_dev *dev);
void pci_addr_cache_insert_device(struct pci_dev *dev);
void pci_addr_cache_remove_device(struct pci_dev *dev);
-/* From pSeries_pci.h */
+/* From rtas_pci.h */
void init_pci_config_tokens (void);
unsigned long get_phb_buid (struct device_node *);
+/* From pSeries_pci.h */
+extern void pSeries_final_fixup(void);
+extern void pSeries_irq_bus_setup(struct pci_bus *bus);
+
extern unsigned long pci_probe_only;
extern unsigned long pci_assign_all_buses;
extern int pci_read_irq_line(struct pci_dev *pci_dev);
diff --git a/arch/ppc64/kernel/pmac_smp.c b/arch/ppc64/kernel/pmac_smp.c
index c27588ede2f..a23de37227b 100644
--- a/arch/ppc64/kernel/pmac_smp.c
+++ b/arch/ppc64/kernel/pmac_smp.c
@@ -68,6 +68,7 @@ extern struct smp_ops_t *smp_ops;
static void (*pmac_tb_freeze)(int freeze);
static struct device_node *pmac_tb_clock_chip_host;
+static u8 pmac_tb_pulsar_addr;
static DEFINE_SPINLOCK(timebase_lock);
static unsigned long timebase;
@@ -106,12 +107,9 @@ static void smp_core99_pulsar_tb_freeze(int freeze)
u8 data;
int rc;
- /* Strangely, the device-tree says address is 0xd2, but darwin
- * accesses 0xd0 ...
- */
pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_combined);
rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
- 0xd4 | pmac_low_i2c_read,
+ pmac_tb_pulsar_addr | pmac_low_i2c_read,
0x2e, &data, 1);
if (rc != 0)
goto bail;
@@ -120,7 +118,7 @@ static void smp_core99_pulsar_tb_freeze(int freeze)
pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_stdsub);
rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
- 0xd4 | pmac_low_i2c_write,
+ pmac_tb_pulsar_addr | pmac_low_i2c_write,
0x2e, &data, 1);
bail:
if (rc != 0) {
@@ -185,6 +183,12 @@ static int __init smp_core99_probe(void)
if (ncpus <= 1)
return 1;
+ /* HW sync only on these platforms */
+ if (!machine_is_compatible("PowerMac7,2") &&
+ !machine_is_compatible("PowerMac7,3") &&
+ !machine_is_compatible("RackMac3,1"))
+ goto nohwsync;
+
/* Look for the clock chip */
for (cc = NULL; (cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL;) {
struct device_node *p = of_get_parent(cc);
@@ -198,11 +202,18 @@ static int __init smp_core99_probe(void)
goto next;
switch (*reg) {
case 0xd2:
- pmac_tb_freeze = smp_core99_cypress_tb_freeze;
- printk(KERN_INFO "Timebase clock is Cypress chip\n");
+ if (device_is_compatible(cc, "pulsar-legacy-slewing")) {
+ pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
+ pmac_tb_pulsar_addr = 0xd2;
+ printk(KERN_INFO "Timebase clock is Pulsar chip\n");
+ } else if (device_is_compatible(cc, "cy28508")) {
+ pmac_tb_freeze = smp_core99_cypress_tb_freeze;
+ printk(KERN_INFO "Timebase clock is Cypress chip\n");
+ }
break;
case 0xd4:
pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
+ pmac_tb_pulsar_addr = 0xd4;
printk(KERN_INFO "Timebase clock is Pulsar chip\n");
break;
}
@@ -210,12 +221,15 @@ static int __init smp_core99_probe(void)
pmac_tb_clock_chip_host = p;
smp_ops->give_timebase = smp_core99_give_timebase;
smp_ops->take_timebase = smp_core99_take_timebase;
+ of_node_put(cc);
+ of_node_put(p);
break;
}
next:
of_node_put(p);
}
+ nohwsync:
mpic_request_ipis();
return ncpus;
diff --git a/arch/ppc64/kernel/pmac_time.c b/arch/ppc64/kernel/pmac_time.c
index f24827581dd..3059edb09cc 100644
--- a/arch/ppc64/kernel/pmac_time.c
+++ b/arch/ppc64/kernel/pmac_time.c
@@ -40,11 +40,6 @@
#define DBG(x...)
#endif
-extern void setup_default_decr(void);
-
-extern unsigned long ppc_tb_freq;
-extern unsigned long ppc_proc_freq;
-
/* Apparently the RTC stores seconds since 1 Jan 1904 */
#define RTC_OFFSET 2082844800
@@ -161,8 +156,7 @@ void __init pmac_get_boot_time(struct rtc_time *tm)
/*
* Query the OF and get the decr frequency.
- * This was taken from the pmac time_init() when merging the prep/pmac
- * time functions.
+ * FIXME: merge this with generic_calibrate_decr
*/
void __init pmac_calibrate_decr(void)
{
diff --git a/arch/ppc64/kernel/proc_ppc64.c b/arch/ppc64/kernel/proc_ppc64.c
index 0914b0669b0..a87c66a9652 100644
--- a/arch/ppc64/kernel/proc_ppc64.c
+++ b/arch/ppc64/kernel/proc_ppc64.c
@@ -53,7 +53,7 @@ static int __init proc_ppc64_create(void)
if (!root)
return 1;
- if (!(systemcfg->platform & PLATFORM_PSERIES))
+ if (!(systemcfg->platform & (PLATFORM_PSERIES | PLATFORM_BPA)))
return 0;
if (!proc_mkdir("rtas", root))
diff --git a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c
index 8b068612273..aba89554d89 100644
--- a/arch/ppc64/kernel/process.c
+++ b/arch/ppc64/kernel/process.c
@@ -58,14 +58,6 @@ struct task_struct *last_task_used_math = NULL;
struct task_struct *last_task_used_altivec = NULL;
#endif
-struct mm_struct ioremap_mm = {
- .pgd = ioremap_dir,
- .mm_users = ATOMIC_INIT(2),
- .mm_count = ATOMIC_INIT(1),
- .cpu_vm_mask = CPU_MASK_ALL,
- .page_table_lock = SPIN_LOCK_UNLOCKED,
-};
-
/*
* Make sure the floating-point register state in the
* the thread_struct is up to date for task tsk.
@@ -378,9 +370,6 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
childregs->gpr[1] = sp + sizeof(struct pt_regs);
p->thread.regs = NULL; /* no user register state */
clear_ti_thread_flag(p->thread_info, TIF_32BIT);
-#ifdef CONFIG_PPC_ISERIES
- set_ti_thread_flag(p->thread_info, TIF_RUN_LIGHT);
-#endif
} else {
childregs->gpr[1] = usp;
p->thread.regs = childregs;
diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
index eb6538b5800..47727a6f734 100644
--- a/arch/ppc64/kernel/prom.c
+++ b/arch/ppc64/kernel/prom.c
@@ -884,6 +884,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
{
char *type = get_flat_dt_prop(node, "device_type", NULL);
u32 *prop;
+ unsigned long size;
/* We are scanning "cpu" nodes only */
if (type == NULL || strcmp(type, "cpu") != 0)
@@ -929,6 +930,17 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC;
}
+ /*
+ * Check for an SMT capable CPU and set the CPU feature. We do
+ * this by looking at the size of the ibm,ppc-interrupt-server#s
+ * property
+ */
+ prop = (u32 *)get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s",
+ &size);
+ cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT;
+ if (prop && ((size / sizeof(u32)) > 1))
+ cur_cpu_spec->cpu_features |= CPU_FTR_SMT;
+
return 0;
}
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c
index 35ec42de962..e248a7950ae 100644
--- a/arch/ppc64/kernel/prom_init.c
+++ b/arch/ppc64/kernel/prom_init.c
@@ -211,13 +211,23 @@ struct {
*/
#define ADDR(x) (u32) ((unsigned long)(x) - offset)
+/*
+ * Error results ... some OF calls will return "-1" on error, some
+ * will return 0, some will return either. To simplify, here are
+ * macros to use with any ihandle or phandle return value to check if
+ * it is valid
+ */
+
+#define PROM_ERROR (-1u)
+#define PHANDLE_VALID(p) ((p) != 0 && (p) != PROM_ERROR)
+#define IHANDLE_VALID(i) ((i) != 0 && (i) != PROM_ERROR)
+
+
/* This is the one and *ONLY* place where we actually call open
* firmware from, since we need to make sure we're running in 32b
* mode when we do. We switch back to 64b mode upon return.
*/
-#define PROM_ERROR (-1)
-
static int __init call_prom(const char *service, int nargs, int nret, ...)
{
int i;
@@ -587,14 +597,13 @@ static void __init prom_send_capabilities(void)
{
unsigned long offset = reloc_offset();
ihandle elfloader;
- int ret;
elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader"));
if (elfloader == 0) {
prom_printf("couldn't open /packages/elf-loader\n");
return;
}
- ret = call_prom("call-method", 3, 1, ADDR("process-elf-header"),
+ call_prom("call-method", 3, 1, ADDR("process-elf-header"),
elfloader, ADDR(&fake_elf));
call_prom("close", 1, 0, elfloader);
}
@@ -646,7 +655,7 @@ static unsigned long __init alloc_up(unsigned long size, unsigned long align)
base = _ALIGN_UP(base + 0x100000, align)) {
prom_debug(" trying: 0x%x\n\r", base);
addr = (unsigned long)prom_claim(base, size, 0);
- if ((int)addr != PROM_ERROR)
+ if (addr != PROM_ERROR)
break;
addr = 0;
if (align == 0)
@@ -708,7 +717,7 @@ static unsigned long __init alloc_down(unsigned long size, unsigned long align,
for(; base > RELOC(alloc_bottom); base = _ALIGN_DOWN(base - 0x100000, align)) {
prom_debug(" trying: 0x%x\n\r", base);
addr = (unsigned long)prom_claim(base, size, 0);
- if ((int)addr != PROM_ERROR)
+ if (addr != PROM_ERROR)
break;
addr = 0;
}
@@ -902,18 +911,19 @@ static void __init prom_instantiate_rtas(void)
{
unsigned long offset = reloc_offset();
struct prom_t *_prom = PTRRELOC(&prom);
- phandle prom_rtas, rtas_node;
+ phandle rtas_node;
+ ihandle rtas_inst;
u32 base, entry = 0;
u32 size = 0;
prom_debug("prom_instantiate_rtas: start...\n");
- prom_rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
- prom_debug("prom_rtas: %x\n", prom_rtas);
- if (prom_rtas == (phandle) -1)
+ rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas"));
+ prom_debug("rtas_node: %x\n", rtas_node);
+ if (!PHANDLE_VALID(rtas_node))
return;
- prom_getprop(prom_rtas, "rtas-size", &size, sizeof(size));
+ prom_getprop(rtas_node, "rtas-size", &size, sizeof(size));
if (size == 0)
return;
@@ -922,14 +932,18 @@ static void __init prom_instantiate_rtas(void)
prom_printf("RTAS allocation failed !\n");
return;
}
- prom_printf("instantiating rtas at 0x%x", base);
- rtas_node = call_prom("open", 1, 1, ADDR("/rtas"));
- prom_printf("...");
+ rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
+ if (!IHANDLE_VALID(rtas_inst)) {
+ prom_printf("opening rtas package failed");
+ return;
+ }
+
+ prom_printf("instantiating rtas at 0x%x ...", base);
if (call_prom("call-method", 3, 2,
ADDR("instantiate-rtas"),
- rtas_node, base) != PROM_ERROR) {
+ rtas_inst, base) != PROM_ERROR) {
entry = (long)_prom->args.rets[1];
}
if (entry == 0) {
@@ -940,8 +954,8 @@ static void __init prom_instantiate_rtas(void)
reserve_mem(base, size);
- prom_setprop(prom_rtas, "linux,rtas-base", &base, sizeof(base));
- prom_setprop(prom_rtas, "linux,rtas-entry", &entry, sizeof(entry));
+ prom_setprop(rtas_node, "linux,rtas-base", &base, sizeof(base));
+ prom_setprop(rtas_node, "linux,rtas-entry", &entry, sizeof(entry));
prom_debug("rtas base = 0x%x\n", base);
prom_debug("rtas entry = 0x%x\n", entry);
@@ -1062,7 +1076,7 @@ static void __init prom_initialize_tce_table(void)
prom_printf("opening PHB %s", path);
phb_node = call_prom("open", 1, 1, path);
- if ( (long)phb_node <= 0)
+ if (phb_node == 0)
prom_printf("... failed\n");
else
prom_printf("... done\n");
@@ -1279,12 +1293,12 @@ static void __init prom_init_client_services(unsigned long pp)
/* get a handle for the stdout device */
_prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen"));
- if ((long)_prom->chosen <= 0)
+ if (!PHANDLE_VALID(_prom->chosen))
prom_panic("cannot find chosen"); /* msg won't be printed :( */
/* get device tree root */
_prom->root = call_prom("finddevice", 1, 1, ADDR("/"));
- if ((long)_prom->root <= 0)
+ if (!PHANDLE_VALID(_prom->root))
prom_panic("cannot find device tree root"); /* msg won't be printed :( */
}
@@ -1356,9 +1370,8 @@ static int __init prom_find_machine_type(void)
}
/* Default to pSeries. We need to know if we are running LPAR */
rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
- if (rtas != (phandle) -1) {
- unsigned long x;
- x = prom_getproplen(rtas, "ibm,hypertas-functions");
+ if (PHANDLE_VALID(rtas)) {
+ int x = prom_getproplen(rtas, "ibm,hypertas-functions");
if (x != PROM_ERROR) {
prom_printf("Hypertas detected, assuming LPAR !\n");
return PLATFORM_PSERIES_LPAR;
@@ -1426,12 +1439,13 @@ static void __init prom_check_displays(void)
* leave some room at the end of the path for appending extra
* arguments
*/
- if (call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-10) < 0)
+ if (call_prom("package-to-path", 3, 1, node, path,
+ PROM_SCRATCH_SIZE-10) == PROM_ERROR)
continue;
prom_printf("found display : %s, opening ... ", path);
ih = call_prom("open", 1, 1, path);
- if (ih == (ihandle)0 || ih == (ihandle)-1) {
+ if (ih == 0) {
prom_printf("failed\n");
continue;
}
@@ -1514,6 +1528,12 @@ static unsigned long __init dt_find_string(char *str)
return 0;
}
+/*
+ * The Open Firmware 1275 specification states properties must be 31 bytes or
+ * less, however not all firmwares obey this. Make it 64 bytes to be safe.
+ */
+#define MAX_PROPERTY_NAME 64
+
static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
unsigned long *mem_end)
{
@@ -1527,10 +1547,12 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
/* get and store all property names */
prev_name = RELOC("");
for (;;) {
-
- /* 32 is max len of name including nul. */
- namep = make_room(mem_start, mem_end, 32, 1);
- if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0) {
+ int rc;
+
+ /* 64 is max len of name including nul. */
+ namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
+ rc = call_prom("nextprop", 3, 1, node, prev_name, namep);
+ if (rc != 1) {
/* No more nodes: unwind alloc */
*mem_start = (unsigned long)namep;
break;
@@ -1555,18 +1577,12 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
}
}
-/*
- * The Open Firmware 1275 specification states properties must be 31 bytes or
- * less, however not all firmwares obey this. Make it 64 bytes to be safe.
- */
-#define MAX_PROPERTY_NAME 64
-
static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
unsigned long *mem_end)
{
int l, align;
phandle child;
- char *namep, *prev_name, *sstart;
+ char *namep, *prev_name, *sstart, *p, *ep;
unsigned long soff;
unsigned char *valp;
unsigned long offset = reloc_offset();
@@ -1588,6 +1604,14 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
call_prom("package-to-path", 3, 1, node, namep, l);
}
namep[l] = '\0';
+ /* Fixup an Apple bug where they have bogus \0 chars in the
+ * middle of the path in some properties
+ */
+ for (p = namep, ep = namep + l; p < ep; p++)
+ if (*p == '\0') {
+ memmove(p, p+1, ep - p);
+ ep--; l--;
+ }
*mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 1, 4);
}
@@ -1599,7 +1623,10 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
prev_name = RELOC("");
sstart = (char *)RELOC(dt_string_start);
for (;;) {
- if (call_prom("nextprop", 3, 1, node, prev_name, pname) <= 0)
+ int rc;
+
+ rc = call_prom("nextprop", 3, 1, node, prev_name, pname);
+ if (rc != 1)
break;
/* find string offset */
@@ -1615,7 +1642,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
l = call_prom("getproplen", 2, 1, node, pname);
/* sanity checks */
- if (l < 0)
+ if (l == PROM_ERROR)
continue;
if (l > MAX_PROPERTY_LENGTH) {
prom_printf("WARNING: ignoring large property ");
@@ -1750,7 +1777,45 @@ static void __init flatten_device_tree(void)
prom_printf("Device tree struct 0x%x -> 0x%x\n",
RELOC(dt_struct_start), RELOC(dt_struct_end));
- }
+}
+
+
+static void __init fixup_device_tree(void)
+{
+ unsigned long offset = reloc_offset();
+ phandle u3, i2c, mpic;
+ u32 u3_rev;
+ u32 interrupts[2];
+ u32 parent;
+
+ /* Some G5s have a missing interrupt definition, fix it up here */
+ u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000"));
+ if (!PHANDLE_VALID(u3))
+ return;
+ i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000"));
+ if (!PHANDLE_VALID(i2c))
+ return;
+ mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000"));
+ if (!PHANDLE_VALID(mpic))
+ return;
+
+ /* check if proper rev of u3 */
+ if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev))
+ == PROM_ERROR)
+ return;
+ if (u3_rev != 0x35)
+ return;
+ /* does it need fixup ? */
+ if (prom_getproplen(i2c, "interrupts") > 0)
+ return;
+ /* interrupt on this revision of u3 is number 0 and level */
+ interrupts[0] = 0;
+ interrupts[1] = 1;
+ prom_setprop(i2c, "interrupts", &interrupts, sizeof(interrupts));
+ parent = (u32)mpic;
+ prom_setprop(i2c, "interrupt-parent", &parent, sizeof(parent));
+}
+
static void __init prom_find_boot_cpu(void)
{
@@ -1844,9 +1909,15 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long
&getprop_rval, sizeof(getprop_rval));
/*
- * On pSeries, copy the CPU hold code
+ * On pSeries, inform the firmware about our capabilities
*/
- if (RELOC(of_platform) & PLATFORM_PSERIES)
+ if (RELOC(of_platform) & PLATFORM_PSERIES)
+ prom_send_capabilities();
+
+ /*
+ * On pSeries and BPA, copy the CPU hold code
+ */
+ if (RELOC(of_platform) & (PLATFORM_PSERIES | PLATFORM_BPA))
copy_and_flush(0, KERNELBASE - offset, 0x100, 0);
/*
@@ -1920,6 +1991,11 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long
}
/*
+ * Fixup any known bugs in the device-tree
+ */
+ fixup_device_tree();
+
+ /*
* Now finally create the flattened device-tree
*/
prom_printf("copying OF device tree ...\n");
diff --git a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c
index 9f8c6087ae5..2993f108d96 100644
--- a/arch/ppc64/kernel/ptrace.c
+++ b/arch/ppc64/kernel/ptrace.c
@@ -305,6 +305,8 @@ static void do_syscall_trace(void)
void do_syscall_trace_enter(struct pt_regs *regs)
{
+ secure_computing(regs->gpr[0]);
+
if (test_thread_flag(TIF_SYSCALL_TRACE)
&& (current->ptrace & PT_PTRACED))
do_syscall_trace();
@@ -320,8 +322,6 @@ void do_syscall_trace_enter(struct pt_regs *regs)
void do_syscall_trace_leave(struct pt_regs *regs)
{
- secure_computing(regs->gpr[0]);
-
if (unlikely(current->audit_context))
audit_syscall_exit(current,
(regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
diff --git a/arch/ppc64/kernel/ras.c b/arch/ppc64/kernel/ras.c
index 1c4c796b212..3c00f7bfc1b 100644
--- a/arch/ppc64/kernel/ras.c
+++ b/arch/ppc64/kernel/ras.c
@@ -47,7 +47,6 @@
#include <asm/cache.h>
#include <asm/prom.h>
#include <asm/ptrace.h>
-#include <asm/iSeries/LparData.h>
#include <asm/machdep.h>
#include <asm/rtas.h>
#include <asm/ppcdebug.h>
diff --git a/arch/ppc64/kernel/rtas-proc.c b/arch/ppc64/kernel/rtas-proc.c
index 28b1f1521f2..1f3ff860fdf 100644
--- a/arch/ppc64/kernel/rtas-proc.c
+++ b/arch/ppc64/kernel/rtas-proc.c
@@ -371,11 +371,11 @@ static ssize_t ppc_rtas_progress_write(struct file *file,
/* Lets see if the user passed hexdigits */
hex = simple_strtoul(progress_led, NULL, 10);
- ppc_md.progress ((char *)progress_led, hex);
+ rtas_progress ((char *)progress_led, hex);
return count;
/* clear the line */
- /* ppc_md.progress(" ", 0xffff);*/
+ /* rtas_progress(" ", 0xffff);*/
}
/* ****************************************************************** */
static int ppc_rtas_progress_show(struct seq_file *m, void *v)
diff --git a/arch/ppc64/kernel/rtas.c b/arch/ppc64/kernel/rtas.c
index 5575603def2..5e8eb33b8e5 100644
--- a/arch/ppc64/kernel/rtas.c
+++ b/arch/ppc64/kernel/rtas.c
@@ -91,6 +91,123 @@ call_rtas_display_status_delay(unsigned char c)
}
}
+void
+rtas_progress(char *s, unsigned short hex)
+{
+ struct device_node *root;
+ int width, *p;
+ char *os;
+ static int display_character, set_indicator;
+ static int display_width, display_lines, *row_width, form_feed;
+ static DEFINE_SPINLOCK(progress_lock);
+ static int current_line;
+ static int pending_newline = 0; /* did last write end with unprinted newline? */
+
+ if (!rtas.base)
+ return;
+
+ if (display_width == 0) {
+ display_width = 0x10;
+ if ((root = find_path_device("/rtas"))) {
+ if ((p = (unsigned int *)get_property(root,
+ "ibm,display-line-length", NULL)))
+ display_width = *p;
+ if ((p = (unsigned int *)get_property(root,
+ "ibm,form-feed", NULL)))
+ form_feed = *p;
+ if ((p = (unsigned int *)get_property(root,
+ "ibm,display-number-of-lines", NULL)))
+ display_lines = *p;
+ row_width = (unsigned int *)get_property(root,
+ "ibm,display-truncation-length", NULL);
+ }
+ display_character = rtas_token("display-character");
+ set_indicator = rtas_token("set-indicator");
+ }
+
+ if (display_character == RTAS_UNKNOWN_SERVICE) {
+ /* use hex display if available */
+ if (set_indicator != RTAS_UNKNOWN_SERVICE)
+ rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex);
+ return;
+ }
+
+ spin_lock(&progress_lock);
+
+ /*
+ * Last write ended with newline, but we didn't print it since
+ * it would just clear the bottom line of output. Print it now
+ * instead.
+ *
+ * If no newline is pending and form feed is supported, clear the
+ * display with a form feed; otherwise, print a CR to start output
+ * at the beginning of the line.
+ */
+ if (pending_newline) {
+ rtas_call(display_character, 1, 1, NULL, '\r');
+ rtas_call(display_character, 1, 1, NULL, '\n');
+ pending_newline = 0;
+ } else {
+ current_line = 0;
+ if (form_feed)
+ rtas_call(display_character, 1, 1, NULL,
+ (char)form_feed);
+ else
+ rtas_call(display_character, 1, 1, NULL, '\r');
+ }
+
+ if (row_width)
+ width = row_width[current_line];
+ else
+ width = display_width;
+ os = s;
+ while (*os) {
+ if (*os == '\n' || *os == '\r') {
+ /* If newline is the last character, save it
+ * until next call to avoid bumping up the
+ * display output.
+ */
+ if (*os == '\n' && !os[1]) {
+ pending_newline = 1;
+ current_line++;
+ if (current_line > display_lines-1)
+ current_line = display_lines-1;
+ spin_unlock(&progress_lock);
+ return;
+ }
+
+ /* RTAS wants CR-LF, not just LF */
+
+ if (*os == '\n') {
+ rtas_call(display_character, 1, 1, NULL, '\r');
+ rtas_call(display_character, 1, 1, NULL, '\n');
+ } else {
+ /* CR might be used to re-draw a line, so we'll
+ * leave it alone and not add LF.
+ */
+ rtas_call(display_character, 1, 1, NULL, *os);
+ }
+
+ if (row_width)
+ width = row_width[current_line];
+ else
+ width = display_width;
+ } else {
+ width--;
+ rtas_call(display_character, 1, 1, NULL, *os);
+ }
+
+ os++;
+
+ /* if we overwrite the screen length */
+ if (width <= 0)
+ while ((*os != 0) && (*os != '\n') && (*os != '\r'))
+ os++;
+ }
+
+ spin_unlock(&progress_lock);
+}
+
int
rtas_token(const char *service)
{
@@ -425,8 +542,8 @@ rtas_flash_firmware(void)
printk(KERN_ALERT "FLASH: flash image is %ld bytes\n", image_size);
printk(KERN_ALERT "FLASH: performing flash and reboot\n");
- ppc_md.progress("Flashing \n", 0x0);
- ppc_md.progress("Please Wait... ", 0x0);
+ rtas_progress("Flashing \n", 0x0);
+ rtas_progress("Please Wait... ", 0x0);
printk(KERN_ALERT "FLASH: this will take several minutes. Do not power off!\n");
status = rtas_call(update_token, 1, 1, NULL, rtas_block_list);
switch (status) { /* should only get "bad" status */
diff --git a/arch/ppc64/kernel/rtas_pci.c b/arch/ppc64/kernel/rtas_pci.c
new file mode 100644
index 00000000000..1048817befb
--- /dev/null
+++ b/arch/ppc64/kernel/rtas_pci.c
@@ -0,0 +1,495 @@
+/*
+ * arch/ppc64/kernel/rtas_pci.c
+ *
+ * Copyright (C) 2001 Dave Engebretsen, IBM Corporation
+ * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM
+ *
+ * RTAS specific routines for PCI.
+ *
+ * Based on code from pci.c, chrp_pci.c and pSeries_pci.c
+ *
+ * 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 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 <linux/kernel.h>
+#include <linux/threads.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/iommu.h>
+#include <asm/rtas.h>
+
+#include "mpic.h"
+#include "pci.h"
+
+/* RTAS tokens */
+static int read_pci_config;
+static int write_pci_config;
+static int ibm_read_pci_config;
+static int ibm_write_pci_config;
+
+static int config_access_valid(struct device_node *dn, int where)
+{
+ if (where < 256)
+ return 1;
+ if (where < 4096 && dn->pci_ext_config_space)
+ return 1;
+
+ return 0;
+}
+
+static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val)
+{
+ int returnval = -1;
+ unsigned long buid, addr;
+ int ret;
+
+ if (!dn)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ if (!config_access_valid(dn, where))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ addr = ((where & 0xf00) << 20) | (dn->busno << 16) |
+ (dn->devfn << 8) | (where & 0xff);
+ buid = dn->phb->buid;
+ if (buid) {
+ ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval,
+ addr, buid >> 32, buid & 0xffffffff, size);
+ } else {
+ ret = rtas_call(read_pci_config, 2, 2, &returnval, addr, size);
+ }
+ *val = returnval;
+
+ if (ret)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ if (returnval == EEH_IO_ERROR_VALUE(size)
+ && eeh_dn_check_failure (dn, NULL))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int rtas_pci_read_config(struct pci_bus *bus,
+ unsigned int devfn,
+ int where, int size, u32 *val)
+{
+ struct device_node *busdn, *dn;
+
+ if (bus->self)
+ busdn = pci_device_to_OF_node(bus->self);
+ else
+ busdn = bus->sysdata; /* must be a phb */
+
+ /* Search only direct children of the bus */
+ for (dn = busdn->child; dn; dn = dn->sibling)
+ if (dn->devfn == devfn)
+ return rtas_read_config(dn, where, size, val);
+ return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+static int rtas_write_config(struct device_node *dn, int where, int size, u32 val)
+{
+ unsigned long buid, addr;
+ int ret;
+
+ if (!dn)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ if (!config_access_valid(dn, where))
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ addr = ((where & 0xf00) << 20) | (dn->busno << 16) |
+ (dn->devfn << 8) | (where & 0xff);
+ buid = dn->phb->buid;
+ if (buid) {
+ ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr, buid >> 32, buid & 0xffffffff, size, (ulong) val);
+ } else {
+ ret = rtas_call(write_pci_config, 3, 1, NULL, addr, size, (ulong)val);
+ }
+
+ if (ret)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int rtas_pci_write_config(struct pci_bus *bus,
+ unsigned int devfn,
+ int where, int size, u32 val)
+{
+ struct device_node *busdn, *dn;
+
+ if (bus->self)
+ busdn = pci_device_to_OF_node(bus->self);
+ else
+ busdn = bus->sysdata; /* must be a phb */
+
+ /* Search only direct children of the bus */
+ for (dn = busdn->child; dn; dn = dn->sibling)
+ if (dn->devfn == devfn)
+ return rtas_write_config(dn, where, size, val);
+ return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+struct pci_ops rtas_pci_ops = {
+ rtas_pci_read_config,
+ rtas_pci_write_config
+};
+
+int is_python(struct device_node *dev)
+{
+ char *model = (char *)get_property(dev, "model", NULL);
+
+ if (model && strstr(model, "Python"))
+ return 1;
+
+ return 0;
+}
+
+static int get_phb_reg_prop(struct device_node *dev,
+ unsigned int addr_size_words,
+ struct reg_property64 *reg)
+{
+ unsigned int *ui_ptr = NULL, len;
+
+ /* Found a PHB, now figure out where his registers are mapped. */
+ ui_ptr = (unsigned int *)get_property(dev, "reg", &len);
+ if (ui_ptr == NULL)
+ return 1;
+
+ if (addr_size_words == 1) {
+ reg->address = ((struct reg_property32 *)ui_ptr)->address;
+ reg->size = ((struct reg_property32 *)ui_ptr)->size;
+ } else {
+ *reg = *((struct reg_property64 *)ui_ptr);
+ }
+
+ return 0;
+}
+
+static void python_countermeasures(struct device_node *dev,
+ unsigned int addr_size_words)
+{
+ struct reg_property64 reg_struct;
+ void __iomem *chip_regs;
+ volatile u32 val;
+
+ if (get_phb_reg_prop(dev, addr_size_words, &reg_struct))
+ return;
+
+ /* Python's register file is 1 MB in size. */
+ chip_regs = ioremap(reg_struct.address & ~(0xfffffUL), 0x100000);
+
+ /*
+ * Firmware doesn't always clear this bit which is critical
+ * for good performance - Anton
+ */
+
+#define PRG_CL_RESET_VALID 0x00010000
+
+ val = in_be32(chip_regs + 0xf6030);
+ if (val & PRG_CL_RESET_VALID) {
+ printk(KERN_INFO "Python workaround: ");
+ val &= ~PRG_CL_RESET_VALID;
+ out_be32(chip_regs + 0xf6030, val);
+ /*
+ * We must read it back for changes to
+ * take effect
+ */
+ val = in_be32(chip_regs + 0xf6030);
+ printk("reg0: %x\n", val);
+ }
+
+ iounmap(chip_regs);
+}
+
+void __init init_pci_config_tokens (void)
+{
+ read_pci_config = rtas_token("read-pci-config");
+ write_pci_config = rtas_token("write-pci-config");
+ ibm_read_pci_config = rtas_token("ibm,read-pci-config");
+ ibm_write_pci_config = rtas_token("ibm,write-pci-config");
+}
+
+unsigned long __devinit get_phb_buid (struct device_node *phb)
+{
+ int addr_cells;
+ unsigned int *buid_vals;
+ unsigned int len;
+ unsigned long buid;
+
+ if (ibm_read_pci_config == -1) return 0;
+
+ /* PHB's will always be children of the root node,
+ * or so it is promised by the current firmware. */
+ if (phb->parent == NULL)
+ return 0;
+ if (phb->parent->parent)
+ return 0;
+
+ buid_vals = (unsigned int *) get_property(phb, "reg", &len);
+ if (buid_vals == NULL)
+ return 0;
+
+ addr_cells = prom_n_addr_cells(phb);
+ if (addr_cells == 1) {
+ buid = (unsigned long) buid_vals[0];
+ } else {
+ buid = (((unsigned long)buid_vals[0]) << 32UL) |
+ (((unsigned long)buid_vals[1]) & 0xffffffff);
+ }
+ return buid;
+}
+
+static int phb_set_bus_ranges(struct device_node *dev,
+ struct pci_controller *phb)
+{
+ int *bus_range;
+ unsigned int len;
+
+ bus_range = (int *) get_property(dev, "bus-range", &len);
+ if (bus_range == NULL || len < 2 * sizeof(int)) {
+ return 1;
+ }
+
+ phb->first_busno = bus_range[0];
+ phb->last_busno = bus_range[1];
+
+ return 0;
+}
+
+static int __devinit setup_phb(struct device_node *dev,
+ struct pci_controller *phb,
+ unsigned int addr_size_words)
+{
+ pci_setup_pci_controller(phb);
+
+ if (is_python(dev))
+ python_countermeasures(dev, addr_size_words);
+
+ if (phb_set_bus_ranges(dev, phb))
+ return 1;
+
+ phb->arch_data = dev;
+ phb->ops = &rtas_pci_ops;
+ phb->buid = get_phb_buid(dev);
+
+ return 0;
+}
+
+static void __devinit add_linux_pci_domain(struct device_node *dev,
+ struct pci_controller *phb,
+ struct property *of_prop)
+{
+ memset(of_prop, 0, sizeof(struct property));
+ of_prop->name = "linux,pci-domain";
+ of_prop->length = sizeof(phb->global_number);
+ of_prop->value = (unsigned char *)&of_prop[1];
+ memcpy(of_prop->value, &phb->global_number, sizeof(phb->global_number));
+ prom_add_property(dev, of_prop);
+}
+
+static struct pci_controller * __init alloc_phb(struct device_node *dev,
+ unsigned int addr_size_words)
+{
+ struct pci_controller *phb;
+ struct property *of_prop;
+
+ phb = alloc_bootmem(sizeof(struct pci_controller));
+ if (phb == NULL)
+ return NULL;
+
+ of_prop = alloc_bootmem(sizeof(struct property) +
+ sizeof(phb->global_number));
+ if (!of_prop)
+ return NULL;
+
+ if (setup_phb(dev, phb, addr_size_words))
+ return NULL;
+
+ add_linux_pci_domain(dev, phb, of_prop);
+
+ return phb;
+}
+
+static struct pci_controller * __devinit alloc_phb_dynamic(struct device_node *dev, unsigned int addr_size_words)
+{
+ struct pci_controller *phb;
+
+ phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller),
+ GFP_KERNEL);
+ if (phb == NULL)
+ return NULL;
+
+ if (setup_phb(dev, phb, addr_size_words))
+ return NULL;
+
+ phb->is_dynamic = 1;
+
+ /* TODO: linux,pci-domain? */
+
+ return phb;
+}
+
+unsigned long __init find_and_init_phbs(void)
+{
+ struct device_node *node;
+ struct pci_controller *phb;
+ unsigned int root_size_cells = 0;
+ unsigned int index;
+ unsigned int *opprop = NULL;
+ struct device_node *root = of_find_node_by_path("/");
+
+ if (ppc64_interrupt_controller == IC_OPEN_PIC) {
+ opprop = (unsigned int *)get_property(root,
+ "platform-open-pic", NULL);
+ }
+
+ root_size_cells = prom_n_size_cells(root);
+
+ index = 0;
+
+ for (node = of_get_next_child(root, NULL);
+ node != NULL;
+ node = of_get_next_child(root, node)) {
+ if (node->type == NULL || strcmp(node->type, "pci") != 0)
+ continue;
+
+ phb = alloc_phb(node, root_size_cells);
+ if (!phb)
+ continue;
+
+ pci_process_bridge_OF_ranges(phb, node);
+ pci_setup_phb_io(phb, index == 0);
+#ifdef CONFIG_PPC_PSERIES
+ if (ppc64_interrupt_controller == IC_OPEN_PIC && pSeries_mpic) {
+ int addr = root_size_cells * (index + 2) - 1;
+ mpic_assign_isu(pSeries_mpic, index, opprop[addr]);
+ }
+#endif
+ index++;
+ }
+
+ of_node_put(root);
+ pci_devs_phb_init();
+
+ /*
+ * pci_probe_only and pci_assign_all_buses can be set via properties
+ * in chosen.
+ */
+ if (of_chosen) {
+ int *prop;
+
+ prop = (int *)get_property(of_chosen, "linux,pci-probe-only",
+ NULL);
+ if (prop)
+ pci_probe_only = *prop;
+
+ prop = (int *)get_property(of_chosen,
+ "linux,pci-assign-all-buses", NULL);
+ if (prop)
+ pci_assign_all_buses = *prop;
+ }
+
+ return 0;
+}
+
+struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
+{
+ struct device_node *root = of_find_node_by_path("/");
+ unsigned int root_size_cells = 0;
+ struct pci_controller *phb;
+ struct pci_bus *bus;
+ int primary;
+
+ root_size_cells = prom_n_size_cells(root);
+
+ primary = list_empty(&hose_list);
+ phb = alloc_phb_dynamic(dn, root_size_cells);
+ if (!phb)
+ return NULL;
+
+ pci_process_bridge_OF_ranges(phb, dn);
+
+ pci_setup_phb_io_dynamic(phb, primary);
+ of_node_put(root);
+
+ pci_devs_phb_init_dynamic(phb);
+ phb->last_busno = 0xff;
+ bus = pci_scan_bus(phb->first_busno, phb->ops, phb->arch_data);
+ phb->bus = bus;
+ phb->last_busno = bus->subordinate;
+
+ return phb;
+}
+EXPORT_SYMBOL(init_phb_dynamic);
+
+/* RPA-specific bits for removing PHBs */
+int pcibios_remove_root_bus(struct pci_controller *phb)
+{
+ struct pci_bus *b = phb->bus;
+ struct resource *res;
+ int rc, i;
+
+ res = b->resource[0];
+ if (!res->flags) {
+ printk(KERN_ERR "%s: no IO resource for PHB %s\n", __FUNCTION__,
+ b->name);
+ return 1;
+ }
+
+ rc = unmap_bus_range(b);
+ if (rc) {
+ printk(KERN_ERR "%s: failed to unmap IO on bus %s\n",
+ __FUNCTION__, b->name);
+ return 1;
+ }
+
+ if (release_resource(res)) {
+ printk(KERN_ERR "%s: failed to release IO on bus %s\n",
+ __FUNCTION__, b->name);
+ return 1;
+ }
+
+ for (i = 1; i < 3; ++i) {
+ res = b->resource[i];
+ if (!res->flags && i == 0) {
+ printk(KERN_ERR "%s: no MEM resource for PHB %s\n",
+ __FUNCTION__, b->name);
+ return 1;
+ }
+ if (res->flags && release_resource(res)) {
+ printk(KERN_ERR
+ "%s: failed to release IO %d on bus %s\n",
+ __FUNCTION__, i, b->name);
+ return 1;
+ }
+ }
+
+ list_del(&phb->list_node);
+ if (phb->is_dynamic)
+ kfree(phb);
+
+ return 0;
+}
+EXPORT_SYMBOL(pcibios_remove_root_bus);
diff --git a/arch/ppc64/kernel/rtasd.c b/arch/ppc64/kernel/rtasd.c
index ff65dc33320..b0c3b829fe4 100644
--- a/arch/ppc64/kernel/rtasd.c
+++ b/arch/ppc64/kernel/rtasd.c
@@ -440,7 +440,7 @@ static int rtasd(void *unused)
goto error;
}
- printk(KERN_ERR "RTAS daemon started\n");
+ printk(KERN_INFO "RTAS daemon started\n");
DEBUG("will sleep for %d jiffies\n", (HZ*60/rtas_event_scan_rate) / 2);
@@ -485,7 +485,7 @@ static int __init rtas_init(void)
/* No RTAS, only warn if we are on a pSeries box */
if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) {
if (systemcfg->platform & PLATFORM_PSERIES)
- printk(KERN_ERR "rtasd: no event-scan on system\n");
+ printk(KERN_INFO "rtasd: no event-scan on system\n");
return 1;
}
diff --git a/arch/ppc64/kernel/rtc.c b/arch/ppc64/kernel/rtc.c
index 3e70b91375f..d729fefa0df 100644
--- a/arch/ppc64/kernel/rtc.c
+++ b/arch/ppc64/kernel/rtc.c
@@ -42,10 +42,8 @@
#include <asm/time.h>
#include <asm/rtas.h>
-#include <asm/iSeries/LparData.h>
#include <asm/iSeries/mf.h>
#include <asm/machdep.h>
-#include <asm/iSeries/ItSpCommArea.h>
extern int piranha_simulator;
@@ -292,47 +290,10 @@ int iSeries_set_rtc_time(struct rtc_time *tm)
void iSeries_get_boot_time(struct rtc_time *tm)
{
- unsigned long time;
- static unsigned long lastsec = 1;
-
- u32 dataWord1 = *((u32 *)(&xSpCommArea.xBcdTimeAtIplStart));
- u32 dataWord2 = *(((u32 *)&(xSpCommArea.xBcdTimeAtIplStart)) + 1);
- int year = 1970;
- int year1 = ( dataWord1 >> 24 ) & 0x000000FF;
- int year2 = ( dataWord1 >> 16 ) & 0x000000FF;
- int sec = ( dataWord1 >> 8 ) & 0x000000FF;
- int min = dataWord1 & 0x000000FF;
- int hour = ( dataWord2 >> 24 ) & 0x000000FF;
- int day = ( dataWord2 >> 8 ) & 0x000000FF;
- int mon = dataWord2 & 0x000000FF;
-
if ( piranha_simulator )
return;
- BCD_TO_BIN(sec);
- BCD_TO_BIN(min);
- BCD_TO_BIN(hour);
- BCD_TO_BIN(day);
- BCD_TO_BIN(mon);
- BCD_TO_BIN(year1);
- BCD_TO_BIN(year2);
- year = year1 * 100 + year2;
-
- time = mktime(year, mon, day, hour, min, sec);
- time += ( jiffies / HZ );
-
- /* Now THIS is a nasty hack!
- * It ensures that the first two calls get different answers.
- * That way the loop in init_time (time.c) will not think
- * the clock is stuck.
- */
- if ( lastsec ) {
- time -= lastsec;
- --lastsec;
- }
-
- to_tm(time, tm);
- tm->tm_year -= 1900;
+ mf_get_boot_rtc(tm);
tm->tm_mon -= 1;
}
#endif
@@ -340,7 +301,7 @@ void iSeries_get_boot_time(struct rtc_time *tm)
#ifdef CONFIG_PPC_RTAS
#define MAX_RTC_WAIT 5000 /* 5 sec */
#define RTAS_CLOCK_BUSY (-2)
-void pSeries_get_boot_time(struct rtc_time *rtc_tm)
+void rtas_get_boot_time(struct rtc_time *rtc_tm)
{
int ret[8];
int error, wait_time;
@@ -375,7 +336,7 @@ void pSeries_get_boot_time(struct rtc_time *rtc_tm)
* and if a delay is needed to read the clock. In this case we just
* silently return without updating rtc_tm.
*/
-void pSeries_get_rtc_time(struct rtc_time *rtc_tm)
+void rtas_get_rtc_time(struct rtc_time *rtc_tm)
{
int ret[8];
int error, wait_time;
@@ -410,7 +371,7 @@ void pSeries_get_rtc_time(struct rtc_time *rtc_tm)
rtc_tm->tm_year = ret[0] - 1900;
}
-int pSeries_set_rtc_time(struct rtc_time *tm)
+int rtas_set_rtc_time(struct rtc_time *tm)
{
int error, wait_time;
unsigned long max_wait_tb;
diff --git a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c
index 21c57f539c2..d5e4866e9ac 100644
--- a/arch/ppc64/kernel/setup.c
+++ b/arch/ppc64/kernel/setup.c
@@ -41,7 +41,6 @@
#include <asm/smp.h>
#include <asm/elf.h>
#include <asm/machdep.h>
-#include <asm/iSeries/LparData.h>
#include <asm/paca.h>
#include <asm/ppcdebug.h>
#include <asm/time.h>
@@ -57,6 +56,8 @@
#include <asm/cache.h>
#include <asm/page.h>
#include <asm/mmu.h>
+#include <asm/lmb.h>
+#include <asm/iSeries/ItLpNaca.h>
#ifdef DEBUG
#define DBG(fmt...) udbg_printf(fmt)
@@ -103,11 +104,6 @@ extern void unflatten_device_tree(void);
extern void smp_release_cpus(void);
-unsigned long decr_overclock = 1;
-unsigned long decr_overclock_proc0 = 1;
-unsigned long decr_overclock_set = 0;
-unsigned long decr_overclock_proc0_set = 0;
-
int have_of = 1;
int boot_cpuid = 0;
int boot_cpuid_phys = 0;
@@ -348,6 +344,7 @@ static void __init setup_cpu_maps(void)
extern struct machdep_calls pSeries_md;
extern struct machdep_calls pmac_md;
extern struct machdep_calls maple_md;
+extern struct machdep_calls bpa_md;
/* Ultimately, stuff them in an elf section like initcalls... */
static struct machdep_calls __initdata *machines[] = {
@@ -360,6 +357,9 @@ static struct machdep_calls __initdata *machines[] = {
#ifdef CONFIG_PPC_MAPLE
&maple_md,
#endif /* CONFIG_PPC_MAPLE */
+#ifdef CONFIG_PPC_BPA
+ &bpa_md,
+#endif
NULL
};
@@ -677,37 +677,52 @@ void __init setup_system(void)
DBG(" <- setup_system()\n");
}
-
-void machine_restart(char *cmd)
+/* also used by kexec */
+void machine_shutdown(void)
{
if (ppc_md.nvram_sync)
ppc_md.nvram_sync();
- ppc_md.restart(cmd);
}
+void machine_restart(char *cmd)
+{
+ machine_shutdown();
+ ppc_md.restart(cmd);
+#ifdef CONFIG_SMP
+ smp_send_stop();
+#endif
+ printk(KERN_EMERG "System Halted, OK to turn off power\n");
+ local_irq_disable();
+ while (1) ;
+}
EXPORT_SYMBOL(machine_restart);
-
+
void machine_power_off(void)
{
- if (ppc_md.nvram_sync)
- ppc_md.nvram_sync();
+ machine_shutdown();
ppc_md.power_off();
+#ifdef CONFIG_SMP
+ smp_send_stop();
+#endif
+ printk(KERN_EMERG "System Halted, OK to turn off power\n");
+ local_irq_disable();
+ while (1) ;
}
-
EXPORT_SYMBOL(machine_power_off);
-
+
void machine_halt(void)
{
- if (ppc_md.nvram_sync)
- ppc_md.nvram_sync();
+ machine_shutdown();
ppc_md.halt();
+#ifdef CONFIG_SMP
+ smp_send_stop();
+#endif
+ printk(KERN_EMERG "System Halted, OK to turn off power\n");
+ local_irq_disable();
+ while (1) ;
}
-
EXPORT_SYMBOL(machine_halt);
-unsigned long ppc_proc_freq;
-unsigned long ppc_tb_freq;
-
static int ppc64_panic_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
@@ -1059,6 +1074,7 @@ void __init setup_arch(char **cmdline_p)
/* set up the bootmem stuff with available memory */
do_init_bootmem();
+ sparse_init();
/* initialize the syscall map in systemcfg */
setup_syscall_map();
@@ -1083,11 +1099,11 @@ void __init setup_arch(char **cmdline_p)
static void ppc64_do_msg(unsigned int src, const char *msg)
{
if (ppc_md.progress) {
- char buf[32];
+ char buf[128];
- sprintf(buf, "%08x \n", src);
+ sprintf(buf, "%08X\n", src);
ppc_md.progress(buf, 0);
- sprintf(buf, "%-16s", msg);
+ snprintf(buf, 128, "%s", msg);
ppc_md.progress(buf, 0);
}
}
@@ -1120,64 +1136,15 @@ void ppc64_dump_msg(unsigned int src, const char *msg)
printk("[dump]%04x %s\n", src, msg);
}
-int set_spread_lpevents( char * str )
-{
- /* The parameter is the number of processors to share in processing lp events */
- unsigned long i;
- unsigned long val = simple_strtoul( str, NULL, 0 );
- if ( ( val > 0 ) && ( val <= NR_CPUS ) ) {
- for ( i=1; i<val; ++i )
- paca[i].lpqueue_ptr = paca[0].lpqueue_ptr;
- printk("lpevent processing spread over %ld processors\n", val);
- }
- else
- printk("invalid spreaqd_lpevents %ld\n", val);
- return 1;
-}
-
/* This should only be called on processor 0 during calibrate decr */
-void setup_default_decr(void)
+void __init setup_default_decr(void)
{
struct paca_struct *lpaca = get_paca();
- if ( decr_overclock_set && !decr_overclock_proc0_set )
- decr_overclock_proc0 = decr_overclock;
-
- lpaca->default_decr = tb_ticks_per_jiffy / decr_overclock_proc0;
+ lpaca->default_decr = tb_ticks_per_jiffy;
lpaca->next_jiffy_update_tb = get_tb() + tb_ticks_per_jiffy;
}
-int set_decr_overclock_proc0( char * str )
-{
- unsigned long val = simple_strtoul( str, NULL, 0 );
- if ( ( val >= 1 ) && ( val <= 48 ) ) {
- decr_overclock_proc0_set = 1;
- decr_overclock_proc0 = val;
- printk("proc 0 decrementer overclock factor of %ld\n", val);
- }
- else
- printk("invalid proc 0 decrementer overclock factor of %ld\n", val);
- return 1;
-}
-
-int set_decr_overclock( char * str )
-{
- unsigned long val = simple_strtoul( str, NULL, 0 );
- if ( ( val >= 1 ) && ( val <= 48 ) ) {
- decr_overclock_set = 1;
- decr_overclock = val;
- printk("decrementer overclock factor of %ld\n", val);
- }
- else
- printk("invalid decrementer overclock factor of %ld\n", val);
- return 1;
-
-}
-
-__setup("spread_lpevents=", set_spread_lpevents );
-__setup("decr_overclock_proc0=", set_decr_overclock_proc0 );
-__setup("decr_overclock=", set_decr_overclock );
-
#ifndef CONFIG_PPC_ISERIES
/*
* This function can be used by platforms to "find" legacy serial ports.
diff --git a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c
index 3b906cd9403..2fcddfcb594 100644
--- a/arch/ppc64/kernel/smp.c
+++ b/arch/ppc64/kernel/smp.c
@@ -71,7 +71,7 @@ void smp_call_function_interrupt(void);
int smt_enabled_at_boot = 1;
-#ifdef CONFIG_PPC_MULTIPLATFORM
+#ifdef CONFIG_MPIC
void smp_mpic_message_pass(int target, int msg)
{
/* make sure we're sending something that translates to an IPI */
@@ -128,7 +128,7 @@ void __devinit smp_generic_kick_cpu(int nr)
smp_mb();
}
-#endif /* CONFIG_PPC_MULTIPLATFORM */
+#endif /* CONFIG_MPIC */
static void __init smp_space_timers(unsigned int max_cpus)
{
@@ -334,7 +334,6 @@ void smp_call_function_interrupt(void)
}
}
-extern unsigned long decr_overclock;
extern struct gettimeofday_struct do_gtod;
struct thread_info *current_set[NR_CPUS];
@@ -491,7 +490,7 @@ int __devinit __cpu_up(unsigned int cpu)
if (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu))
return -EINVAL;
- paca[cpu].default_decr = tb_ticks_per_jiffy / decr_overclock;
+ paca[cpu].default_decr = tb_ticks_per_jiffy;
if (!cpu_has_feature(CPU_FTR_SLB)) {
void *tmp;
diff --git a/arch/ppc64/kernel/spider-pic.c b/arch/ppc64/kernel/spider-pic.c
new file mode 100644
index 00000000000..d5c9a02fb11
--- /dev/null
+++ b/arch/ppc64/kernel/spider-pic.c
@@ -0,0 +1,191 @@
+/*
+ * External Interrupt Controller on Spider South Bridge
+ *
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ *
+ * Author: Arnd Bergmann <arndb@de.ibm.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, 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; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <asm/pgtable.h>
+#include <asm/prom.h>
+#include <asm/io.h>
+
+#include "bpa_iic.h"
+
+/* register layout taken from Spider spec, table 7.4-4 */
+enum {
+ TIR_DEN = 0x004, /* Detection Enable Register */
+ TIR_MSK = 0x084, /* Mask Level Register */
+ TIR_EDC = 0x0c0, /* Edge Detection Clear Register */
+ TIR_PNDA = 0x100, /* Pending Register A */
+ TIR_PNDB = 0x104, /* Pending Register B */
+ TIR_CS = 0x144, /* Current Status Register */
+ TIR_LCSA = 0x150, /* Level Current Status Register A */
+ TIR_LCSB = 0x154, /* Level Current Status Register B */
+ TIR_LCSC = 0x158, /* Level Current Status Register C */
+ TIR_LCSD = 0x15c, /* Level Current Status Register D */
+ TIR_CFGA = 0x200, /* Setting Register A0 */
+ TIR_CFGB = 0x204, /* Setting Register B0 */
+ /* 0x208 ... 0x3ff Setting Register An/Bn */
+ TIR_PPNDA = 0x400, /* Packet Pending Register A */
+ TIR_PPNDB = 0x404, /* Packet Pending Register B */
+ TIR_PIERA = 0x408, /* Packet Output Error Register A */
+ TIR_PIERB = 0x40c, /* Packet Output Error Register B */
+ TIR_PIEN = 0x444, /* Packet Output Enable Register */
+ TIR_PIPND = 0x454, /* Packet Output Pending Register */
+ TIRDID = 0x484, /* Spider Device ID Register */
+ REISTIM = 0x500, /* Reissue Command Timeout Time Setting */
+ REISTIMEN = 0x504, /* Reissue Command Timeout Setting */
+ REISWAITEN = 0x508, /* Reissue Wait Control*/
+};
+
+static void __iomem *spider_pics[4];
+
+static void __iomem *spider_get_pic(int irq)
+{
+ int node = irq / IIC_NODE_STRIDE;
+ irq %= IIC_NODE_STRIDE;
+
+ if (irq >= IIC_EXT_OFFSET &&
+ irq < IIC_EXT_OFFSET + IIC_NUM_EXT &&
+ spider_pics)
+ return spider_pics[node];
+ return NULL;
+}
+
+static int spider_get_nr(unsigned int irq)
+{
+ return (irq % IIC_NODE_STRIDE) - IIC_EXT_OFFSET;
+}
+
+static void __iomem *spider_get_irq_config(int irq)
+{
+ void __iomem *pic;
+ pic = spider_get_pic(irq);
+ return pic + TIR_CFGA + 8 * spider_get_nr(irq);
+}
+
+static void spider_enable_irq(unsigned int irq)
+{
+ void __iomem *cfg = spider_get_irq_config(irq);
+ irq = spider_get_nr(irq);
+
+ out_be32(cfg, in_be32(cfg) | 0x3107000eu);
+ out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq);
+}
+
+static void spider_disable_irq(unsigned int irq)
+{
+ void __iomem *cfg = spider_get_irq_config(irq);
+ irq = spider_get_nr(irq);
+
+ out_be32(cfg, in_be32(cfg) & ~0x30000000u);
+}
+
+static unsigned int spider_startup_irq(unsigned int irq)
+{
+ spider_enable_irq(irq);
+ return 0;
+}
+
+static void spider_shutdown_irq(unsigned int irq)
+{
+ spider_disable_irq(irq);
+}
+
+static void spider_end_irq(unsigned int irq)
+{
+ spider_enable_irq(irq);
+}
+
+static void spider_ack_irq(unsigned int irq)
+{
+ spider_disable_irq(irq);
+ iic_local_enable();
+}
+
+static struct hw_interrupt_type spider_pic = {
+ .typename = " SPIDER ",
+ .startup = spider_startup_irq,
+ .shutdown = spider_shutdown_irq,
+ .enable = spider_enable_irq,
+ .disable = spider_disable_irq,
+ .ack = spider_ack_irq,
+ .end = spider_end_irq,
+};
+
+
+int spider_get_irq(unsigned long int_pending)
+{
+ void __iomem *regs = spider_get_pic(int_pending);
+ unsigned long cs;
+ int irq;
+
+ cs = in_be32(regs + TIR_CS);
+
+ irq = cs >> 24;
+ if (irq != 63)
+ return irq;
+
+ return -1;
+}
+
+void spider_init_IRQ(void)
+{
+ int node;
+ struct device_node *dn;
+ unsigned int *property;
+ long spiderpic;
+ int n;
+
+/* FIXME: detect multiple PICs as soon as the device tree has them */
+ for (node = 0; node < 1; node++) {
+ dn = of_find_node_by_path("/");
+ n = prom_n_addr_cells(dn);
+ property = (unsigned int *) get_property(dn,
+ "platform-spider-pic", NULL);
+
+ if (!property)
+ continue;
+ for (spiderpic = 0; n > 0; --n)
+ spiderpic = (spiderpic << 32) + *property++;
+ printk(KERN_DEBUG "SPIDER addr: %lx\n", spiderpic);
+ spider_pics[node] = __ioremap(spiderpic, 0x800, _PAGE_NO_CACHE);
+ for (n = 0; n < IIC_NUM_EXT; n++) {
+ int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE;
+ get_irq_desc(irq)->handler = &spider_pic;
+
+ /* do not mask any interrupts because of level */
+ out_be32(spider_pics[node] + TIR_MSK, 0x0);
+
+ /* disable edge detection clear */
+ /* out_be32(spider_pics[node] + TIR_EDC, 0x0); */
+
+ /* enable interrupt packets to be output */
+ out_be32(spider_pics[node] + TIR_PIEN,
+ in_be32(spider_pics[node] + TIR_PIEN) | 0x1);
+
+ /* Enable the interrupt detection enable bit. Do this last! */
+ out_be32(spider_pics[node] + TIR_DEN,
+ in_be32(spider_pics[node] +TIR_DEN) | 0x1);
+
+ }
+ }
+}
diff --git a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c
index 7cf7a960002..118436e8085 100644
--- a/arch/ppc64/kernel/sys_ppc32.c
+++ b/arch/ppc64/kernel/sys_ppc32.c
@@ -741,6 +741,7 @@ asmlinkage int sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubu
asmlinkage int sys32_pciconfig_iobase(u32 which, u32 in_bus, u32 in_devfn)
{
+#ifdef CONFIG_PCI
struct pci_controller* hose;
struct list_head *ln;
struct pci_bus *bus = NULL;
@@ -786,36 +787,11 @@ asmlinkage int sys32_pciconfig_iobase(u32 which, u32 in_bus, u32 in_devfn)
case IOBASE_ISA_MEM:
return -EINVAL;
}
-
+#endif /* CONFIG_PCI */
return -EOPNOTSUPP;
}
-asmlinkage int ppc64_newuname(struct new_utsname __user * name)
-{
- int errno = sys_newuname(name);
-
- if (current->personality == PER_LINUX32 && !errno) {
- if(copy_to_user(name->machine, "ppc\0\0", 8)) {
- errno = -EFAULT;
- }
- }
- return errno;
-}
-
-asmlinkage int ppc64_personality(unsigned long personality)
-{
- int ret;
- if (current->personality == PER_LINUX32 && personality == PER_LINUX)
- personality = PER_LINUX32;
- ret = sys_personality(personality);
- if (ret == PER_LINUX32)
- ret = PER_LINUX;
- return ret;
-}
-
-
-
/* Note: it is necessary to treat mode as an unsigned int,
* with the corresponding cast to a signed int to insure that the
* proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -1158,26 +1134,47 @@ asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
}
#endif
+asmlinkage int sys32_uname(struct old_utsname __user * name)
+{
+ int err = 0;
+
+ down_read(&uts_sem);
+ if (copy_to_user(name, &system_utsname, sizeof(*name)))
+ err = -EFAULT;
+ up_read(&uts_sem);
+ if (!err && personality(current->personality) == PER_LINUX32) {
+ /* change "ppc64" to "ppc" */
+ if (__put_user(0, name->machine + 3)
+ || __put_user(0, name->machine + 4))
+ err = -EFAULT;
+ }
+ return err;
+}
+
asmlinkage int sys32_olduname(struct oldold_utsname __user * name)
{
int error;
-
- if (!name)
- return -EFAULT;
+
if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
return -EFAULT;
down_read(&uts_sem);
error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
- error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
- error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
- error -= __put_user(0,name->nodename+__OLD_UTS_LEN);
- error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
- error -= __put_user(0,name->release+__OLD_UTS_LEN);
- error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
- error -= __put_user(0,name->version+__OLD_UTS_LEN);
- error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
- error = __put_user(0,name->machine+__OLD_UTS_LEN);
+ error |= __put_user(0,name->sysname+__OLD_UTS_LEN);
+ error |= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
+ error |= __put_user(0,name->nodename+__OLD_UTS_LEN);
+ error |= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
+ error |= __put_user(0,name->release+__OLD_UTS_LEN);
+ error |= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
+ error |= __put_user(0,name->version+__OLD_UTS_LEN);
+ error |= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
+ error |= __put_user(0,name->machine+__OLD_UTS_LEN);
+ if (personality(current->personality) == PER_LINUX32) {
+ /* change "ppc64" to "ppc" */
+ error |= __put_user(0, name->machine + 3);
+ error |= __put_user(0, name->machine + 4);
+ }
+
up_read(&uts_sem);
error = error ? -EFAULT : 0;
diff --git a/arch/ppc64/kernel/syscalls.c b/arch/ppc64/kernel/syscalls.c
index f2865ff8d2f..a8cbb202b8c 100644
--- a/arch/ppc64/kernel/syscalls.c
+++ b/arch/ppc64/kernel/syscalls.c
@@ -199,24 +199,33 @@ out:
return ret;
}
-static int __init set_fakeppc(char *str)
+long ppc64_personality(unsigned long personality)
{
- if (*str)
- return 0;
- init_task.personality = PER_LINUX32;
- return 1;
+ long ret;
+
+ if (personality(current->personality) == PER_LINUX32
+ && personality == PER_LINUX)
+ personality = PER_LINUX32;
+ ret = sys_personality(personality);
+ if (ret == PER_LINUX32)
+ ret = PER_LINUX;
+ return ret;
}
-__setup("fakeppc", set_fakeppc);
-asmlinkage int sys_uname(struct old_utsname __user * name)
+long ppc64_newuname(struct new_utsname __user * name)
{
- int err = -EFAULT;
-
+ int err = 0;
+
down_read(&uts_sem);
- if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
- err = 0;
+ if (copy_to_user(name, &system_utsname, sizeof(*name)))
+ err = -EFAULT;
up_read(&uts_sem);
-
+ if (!err && personality(current->personality) == PER_LINUX32) {
+ /* change ppc64 to ppc */
+ if (__put_user(0, name->machine + 3)
+ || __put_user(0, name->machine + 4))
+ err = -EFAULT;
+ }
return err;
}
diff --git a/arch/ppc64/kernel/sysfs.c b/arch/ppc64/kernel/sysfs.c
index 0925694c3ce..c8fa6569b2f 100644
--- a/arch/ppc64/kernel/sysfs.c
+++ b/arch/ppc64/kernel/sysfs.c
@@ -113,7 +113,6 @@ void ppc64_enable_pmcs(void)
#ifdef CONFIG_PPC_PSERIES
unsigned long set, reset;
int ret;
- unsigned int ctrl;
#endif /* CONFIG_PPC_PSERIES */
/* Only need to enable them once */
@@ -167,11 +166,8 @@ void ppc64_enable_pmcs(void)
* On SMT machines we have to set the run latch in the ctrl register
* in order to make PMC6 spin.
*/
- if (cpu_has_feature(CPU_FTR_SMT)) {
- ctrl = mfspr(CTRLF);
- ctrl |= RUNLATCH;
- mtspr(CTRLT, ctrl);
- }
+ if (cpu_has_feature(CPU_FTR_SMT))
+ ppc64_runlatch_on();
#endif /* CONFIG_PPC_PSERIES */
}
diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c
index 772a465b49f..2348a75e050 100644
--- a/arch/ppc64/kernel/time.c
+++ b/arch/ppc64/kernel/time.c
@@ -107,6 +107,9 @@ void ppc_adjtimex(void);
static unsigned adjusting_time = 0;
+unsigned long ppc_proc_freq;
+unsigned long ppc_tb_freq;
+
static __inline__ void timer_check_rtc(void)
{
/*
@@ -325,9 +328,7 @@ int timer_interrupt(struct pt_regs * regs)
irq_enter();
-#ifndef CONFIG_PPC_ISERIES
profile_tick(CPU_PROFILING, regs);
-#endif
lpaca->lppaca.int_dword.fields.decr_int = 0;
@@ -474,6 +475,66 @@ int do_settimeofday(struct timespec *tv)
EXPORT_SYMBOL(do_settimeofday);
+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_MAPLE) || defined(CONFIG_PPC_BPA)
+void __init generic_calibrate_decr(void)
+{
+ struct device_node *cpu;
+ struct div_result divres;
+ unsigned int *fp;
+ int node_found;
+
+ /*
+ * The cpu node should have a timebase-frequency property
+ * to tell us the rate at which the decrementer counts.
+ */
+ cpu = of_find_node_by_type(NULL, "cpu");
+
+ ppc_tb_freq = DEFAULT_TB_FREQ; /* hardcoded default */
+ node_found = 0;
+ if (cpu != 0) {
+ fp = (unsigned int *)get_property(cpu, "timebase-frequency",
+ NULL);
+ if (fp != 0) {
+ node_found = 1;
+ ppc_tb_freq = *fp;
+ }
+ }
+ if (!node_found)
+ printk(KERN_ERR "WARNING: Estimating decrementer frequency "
+ "(not found)\n");
+
+ ppc_proc_freq = DEFAULT_PROC_FREQ;
+ node_found = 0;
+ if (cpu != 0) {
+ fp = (unsigned int *)get_property(cpu, "clock-frequency",
+ NULL);
+ if (fp != 0) {
+ node_found = 1;
+ ppc_proc_freq = *fp;
+ }
+ }
+ if (!node_found)
+ printk(KERN_ERR "WARNING: Estimating processor frequency "
+ "(not found)\n");
+
+ of_node_put(cpu);
+
+ printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
+ ppc_tb_freq/1000000, ppc_tb_freq%1000000);
+ printk(KERN_INFO "time_init: processor frequency = %lu.%.6lu MHz\n",
+ ppc_proc_freq/1000000, ppc_proc_freq%1000000);
+
+ tb_ticks_per_jiffy = ppc_tb_freq / HZ;
+ tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
+ tb_ticks_per_usec = ppc_tb_freq / 1000000;
+ tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
+ div128_by_32(1024*1024, 0, tb_ticks_per_sec, &divres);
+ tb_to_xs = divres.result_low;
+
+ setup_default_decr();
+}
+#endif
+
void __init time_init(void)
{
/* This function is only called on the boot processor */
@@ -515,6 +576,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_stamp;
+ get_paca()->next_jiffy_update_tb = tb_last_stamp + tb_ticks_per_jiffy;
do_gtod.varp->stamp_xsec = 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/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c
index 7e52cb2605e..a8d5e83ee89 100644
--- a/arch/ppc64/kernel/traps.c
+++ b/arch/ppc64/kernel/traps.c
@@ -126,6 +126,10 @@ int die(const char *str, struct pt_regs *regs, long err)
printk("POWERMAC ");
nl = 1;
break;
+ case PLATFORM_BPA:
+ printk("BPA ");
+ nl = 1;
+ break;
}
if (nl)
printk("\n");
diff --git a/arch/ppc64/kernel/vio.c b/arch/ppc64/kernel/vio.c
index cdd830cb276..0c0ba71ac0e 100644
--- a/arch/ppc64/kernel/vio.c
+++ b/arch/ppc64/kernel/vio.c
@@ -41,20 +41,25 @@ static const struct vio_device_id *vio_match_device(
static struct iommu_table *vio_build_iommu_table(struct vio_dev *);
static int vio_num_address_cells;
#endif
-static struct vio_dev *vio_bus_device; /* fake "parent" device */
-
#ifdef CONFIG_PPC_ISERIES
-static struct vio_dev *__init vio_register_device_iseries(char *type,
- uint32_t unit_num);
-
static struct iommu_table veth_iommu_table;
static struct iommu_table vio_iommu_table;
-
-static struct vio_dev _vio_dev = {
+#endif
+static struct vio_dev vio_bus_device = { /* fake "parent" device */
+ .name = vio_bus_device.dev.bus_id,
+ .type = "",
+#ifdef CONFIG_PPC_ISERIES
.iommu_table = &vio_iommu_table,
- .dev.bus = &vio_bus_type
+#endif
+ .dev.bus_id = "vio",
+ .dev.bus = &vio_bus_type,
};
-struct device *iSeries_vio_dev = &_vio_dev.dev;
+
+#ifdef CONFIG_PPC_ISERIES
+static struct vio_dev *__init vio_register_device_iseries(char *type,
+ uint32_t unit_num);
+
+struct device *iSeries_vio_dev = &vio_bus_device.dev;
EXPORT_SYMBOL(iSeries_vio_dev);
#define device_is_compatible(a, b) 1
@@ -260,18 +265,10 @@ static int __init vio_bus_init(void)
}
/* the fake parent of all vio devices, just to give us a nice directory */
- vio_bus_device = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
- if (!vio_bus_device) {
- return 1;
- }
- memset(vio_bus_device, 0, sizeof(struct vio_dev));
- strcpy(vio_bus_device->dev.bus_id, "vio");
-
- err = device_register(&vio_bus_device->dev);
+ err = device_register(&vio_bus_device.dev);
if (err) {
printk(KERN_WARNING "%s: device_register returned %i\n", __FUNCTION__,
err);
- kfree(vio_bus_device);
return err;
}
@@ -300,7 +297,7 @@ static void __devinit vio_dev_release(struct device *dev)
}
#ifdef CONFIG_PPC_PSERIES
-static ssize_t viodev_show_devspec(struct device *dev, char *buf)
+static ssize_t viodev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
{
struct device_node *of_node = dev->platform_data;
@@ -309,7 +306,7 @@ static ssize_t viodev_show_devspec(struct device *dev, char *buf)
DEVICE_ATTR(devspec, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_devspec, NULL);
#endif
-static ssize_t viodev_show_name(struct device *dev, char *buf)
+static ssize_t viodev_show_name(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%s\n", to_vio_dev(dev)->name);
}
@@ -326,7 +323,7 @@ static struct vio_dev * __devinit vio_register_device_common(
viodev->unit_address = unit_address;
viodev->iommu_table = iommu_table;
/* init generic 'struct device' fields: */
- viodev->dev.parent = &vio_bus_device->dev;
+ viodev->dev.parent = &vio_bus_device.dev;
viodev->dev.bus = &vio_bus_type;
viodev->dev.release = vio_dev_release;
@@ -636,5 +633,3 @@ struct bus_type vio_bus_type = {
.name = "vio",
.match = vio_bus_match,
};
-
-EXPORT_SYMBOL(vio_bus_type);
diff --git a/arch/ppc64/kernel/viopath.c b/arch/ppc64/kernel/viopath.c
index 2ed8ee07568..2a6c4f01c45 100644
--- a/arch/ppc64/kernel/viopath.c
+++ b/arch/ppc64/kernel/viopath.c
@@ -43,12 +43,10 @@
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/iSeries/HvTypes.h>
-#include <asm/iSeries/LparData.h>
+#include <asm/iSeries/ItExtVpdPanel.h>
#include <asm/iSeries/HvLpEvent.h>
#include <asm/iSeries/HvLpConfig.h>
-#include <asm/iSeries/HvCallCfg.h>
#include <asm/iSeries/mf.h>
-#include <asm/iSeries/iSeries_proc.h>
#include <asm/iSeries/vio.h>
/* Status of the path to each other partition in the system.
@@ -365,7 +363,7 @@ void vio_set_hostlp(void)
* while we're active
*/
viopath_ourLp = HvLpConfig_getLpIndex();
- viopath_hostLp = HvCallCfg_getHostingLpIndex(viopath_ourLp);
+ viopath_hostLp = HvLpConfig_getHostingLpIndex(viopath_ourLp);
if (viopath_hostLp != HvLpIndexInvalid)
vio_setHandler(viomajorsubtype_config, handleConfig);
@@ -487,7 +485,7 @@ int viopath_open(HvLpIndex remoteLp, int subtype, int numReq)
unsigned long flags;
int tempNumAllocated;
- if ((remoteLp >= HvMaxArchitectedLps) || (remoteLp == HvLpIndexInvalid))
+ if ((remoteLp >= HVMAXARCHITECTEDLPS) || (remoteLp == HvLpIndexInvalid))
return -EINVAL;
subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;
@@ -558,7 +556,7 @@ int viopath_close(HvLpIndex remoteLp, int subtype, int numReq)
int numOpen;
struct alloc_parms parms;
- if ((remoteLp >= HvMaxArchitectedLps) || (remoteLp == HvLpIndexInvalid))
+ if ((remoteLp >= HVMAXARCHITECTEDLPS) || (remoteLp == HvLpIndexInvalid))
return -EINVAL;
subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;
diff --git a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c
index 879f39b90a3..677c4450984 100644
--- a/arch/ppc64/kernel/xics.c
+++ b/arch/ppc64/kernel/xics.c
@@ -647,6 +647,31 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask)
}
}
+void xics_teardown_cpu(void)
+{
+ int cpu = smp_processor_id();
+ int status;
+
+ ops->cppr_info(cpu, 0x00);
+ iosync();
+
+ /*
+ * we need to EOI the IPI if we got here from kexec down IPI
+ *
+ * xics doesn't care if we duplicate an EOI as long as we
+ * don't EOI and raise priority.
+ *
+ * probably need to check all the other interrupts too
+ * should we be flagging idle loop instead?
+ * or creating some task to be scheduled?
+ */
+ ops->xirr_info_set(cpu, XICS_IPI);
+
+ status = rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
+ (1UL << interrupt_server_size) - 1 - default_distrib_server, 0);
+ WARN_ON(status != 0);
+}
+
#ifdef CONFIG_HOTPLUG_CPU
/* Interrupts are disabled. */
diff --git a/arch/ppc64/lib/Makefile b/arch/ppc64/lib/Makefile
index bf7b5bbfc04..76fbfa9f706 100644
--- a/arch/ppc64/lib/Makefile
+++ b/arch/ppc64/lib/Makefile
@@ -12,7 +12,7 @@ lib-$(CONFIG_SMP) += locks.o
# e2a provides EBCDIC to ASCII conversions.
ifdef CONFIG_PPC_ISERIES
-obj-$(CONFIG_PCI) += e2a.o
+obj-y += e2a.o
endif
lib-$(CONFIG_DEBUG_KERNEL) += sstep.o
diff --git a/arch/ppc64/mm/Makefile b/arch/ppc64/mm/Makefile
index ac522d57b2a..3695d00d347 100644
--- a/arch/ppc64/mm/Makefile
+++ b/arch/ppc64/mm/Makefile
@@ -6,6 +6,6 @@ EXTRA_CFLAGS += -mno-minimal-toc
obj-y := fault.o init.o imalloc.o hash_utils.o hash_low.o tlb.o \
slb_low.o slb.o stab.o mmap.o
-obj-$(CONFIG_DISCONTIGMEM) += numa.o
+obj-$(CONFIG_NEED_MULTIPLE_NODES) += numa.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
obj-$(CONFIG_PPC_MULTIPLATFORM) += hash_native.o
diff --git a/arch/ppc64/mm/hash_native.c b/arch/ppc64/mm/hash_native.c
index 52b6b930534..4fec05817d6 100644
--- a/arch/ppc64/mm/hash_native.c
+++ b/arch/ppc64/mm/hash_native.c
@@ -304,6 +304,50 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long va,
local_irq_restore(flags);
}
+/*
+ * clear all mappings on kexec. All cpus are in real mode (or they will
+ * be when they isi), and we are the only one left. We rely on our kernel
+ * mapping being 0xC0's and the hardware ignoring those two real bits.
+ *
+ * TODO: add batching support when enabled. remember, no dynamic memory here,
+ * athough there is the control page available...
+ */
+static void native_hpte_clear(void)
+{
+ unsigned long slot, slots, flags;
+ HPTE *hptep = htab_address;
+ Hpte_dword0 dw0;
+ unsigned long pteg_count;
+
+ pteg_count = htab_hash_mask + 1;
+
+ local_irq_save(flags);
+
+ /* we take the tlbie lock and hold it. Some hardware will
+ * deadlock if we try to tlbie from two processors at once.
+ */
+ spin_lock(&native_tlbie_lock);
+
+ slots = pteg_count * HPTES_PER_GROUP;
+
+ for (slot = 0; slot < slots; slot++, hptep++) {
+ /*
+ * we could lock the pte here, but we are the only cpu
+ * running, right? and for crash dump, we probably
+ * don't want to wait for a maybe bad cpu.
+ */
+ dw0 = hptep->dw0.dw0;
+
+ if (dw0.v) {
+ hptep->dw0.dword0 = 0;
+ tlbie(slot2va(dw0.avpn, dw0.l, dw0.h, slot), dw0.l);
+ }
+ }
+
+ spin_unlock(&native_tlbie_lock);
+ local_irq_restore(flags);
+}
+
static void native_flush_hash_range(unsigned long context,
unsigned long number, int local)
{
@@ -415,7 +459,8 @@ void hpte_init_native(void)
ppc_md.hpte_updatepp = native_hpte_updatepp;
ppc_md.hpte_updateboltedpp = native_hpte_updateboltedpp;
ppc_md.hpte_insert = native_hpte_insert;
- ppc_md.hpte_remove = native_hpte_remove;
+ ppc_md.hpte_remove = native_hpte_remove;
+ ppc_md.hpte_clear_all = native_hpte_clear;
if (tlb_batching_enabled())
ppc_md.flush_hash_range = native_flush_hash_range;
htab_finish_init();
diff --git a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c
index 0a0f97008d0..1647b1c6f28 100644
--- a/arch/ppc64/mm/hash_utils.c
+++ b/arch/ppc64/mm/hash_utils.c
@@ -195,7 +195,7 @@ void __init htab_initialize(void)
memset((void *)table, 0, htab_size_bytes);
}
- mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX;
+ mode_rw = _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX;
/* On U3 based machines, we need to reserve the DART area and
* _NOT_ map it to avoid cache paradoxes as it's remapped non
@@ -310,10 +310,6 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
vsid = get_vsid(mm->context.id, ea);
break;
- case IO_REGION_ID:
- mm = &ioremap_mm;
- vsid = get_kernel_vsid(ea);
- break;
case VMALLOC_REGION_ID:
mm = &init_mm;
vsid = get_kernel_vsid(ea);
diff --git a/arch/ppc64/mm/hugetlbpage.c b/arch/ppc64/mm/hugetlbpage.c
index d3bf86a5c1a..fdcfe97c75c 100644
--- a/arch/ppc64/mm/hugetlbpage.c
+++ b/arch/ppc64/mm/hugetlbpage.c
@@ -121,7 +121,7 @@ static pte_t *hugepte_alloc(struct mm_struct *mm, pud_t *dir, unsigned long addr
return hugepte_offset(dir, addr);
}
-static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
{
pud_t *pud;
@@ -134,7 +134,7 @@ static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
return hugepte_offset(pud, addr);
}
-static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
{
pud_t *pud;
@@ -147,25 +147,6 @@ static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
return hugepte_alloc(mm, pud, addr);
}
-static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma,
- unsigned long addr, struct page *page,
- pte_t *ptep, int write_access)
-{
- pte_t entry;
-
- add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE);
- if (write_access) {
- entry =
- pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
- } else {
- entry = pte_wrprotect(mk_pte(page, vma->vm_page_prot));
- }
- entry = pte_mkyoung(entry);
- entry = pte_mkhuge(entry);
-
- set_pte_at(mm, addr, ptep, entry);
-}
-
/*
* This function checks for proper alignment of input addr and len parameters.
*/
@@ -259,80 +240,6 @@ int prepare_hugepage_range(unsigned long addr, unsigned long len)
return -EINVAL;
}
-int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
- struct vm_area_struct *vma)
-{
- pte_t *src_pte, *dst_pte, entry;
- struct page *ptepage;
- unsigned long addr = vma->vm_start;
- unsigned long end = vma->vm_end;
- int err = -ENOMEM;
-
- while (addr < end) {
- dst_pte = huge_pte_alloc(dst, addr);
- if (!dst_pte)
- goto out;
-
- src_pte = huge_pte_offset(src, addr);
- entry = *src_pte;
-
- ptepage = pte_page(entry);
- get_page(ptepage);
- add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
- set_pte_at(dst, addr, dst_pte, entry);
-
- addr += HPAGE_SIZE;
- }
-
- err = 0;
- out:
- return err;
-}
-
-int
-follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
- struct page **pages, struct vm_area_struct **vmas,
- unsigned long *position, int *length, int i)
-{
- unsigned long vpfn, vaddr = *position;
- int remainder = *length;
-
- WARN_ON(!is_vm_hugetlb_page(vma));
-
- vpfn = vaddr/PAGE_SIZE;
- while (vaddr < vma->vm_end && remainder) {
- if (pages) {
- pte_t *pte;
- struct page *page;
-
- pte = huge_pte_offset(mm, vaddr);
-
- /* hugetlb should be locked, and hence, prefaulted */
- WARN_ON(!pte || pte_none(*pte));
-
- page = &pte_page(*pte)[vpfn % (HPAGE_SIZE/PAGE_SIZE)];
-
- WARN_ON(!PageCompound(page));
-
- get_page(page);
- pages[i] = page;
- }
-
- if (vmas)
- vmas[i] = vma;
-
- vaddr += PAGE_SIZE;
- ++vpfn;
- --remainder;
- ++i;
- }
-
- *length = remainder;
- *position = vaddr;
-
- return i;
-}
-
struct page *
follow_huge_addr(struct mm_struct *mm, unsigned long address, int write)
{
@@ -363,89 +270,6 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address,
return NULL;
}
-void unmap_hugepage_range(struct vm_area_struct *vma,
- unsigned long start, unsigned long end)
-{
- struct mm_struct *mm = vma->vm_mm;
- unsigned long addr;
- pte_t *ptep;
- struct page *page;
-
- WARN_ON(!is_vm_hugetlb_page(vma));
- BUG_ON((start % HPAGE_SIZE) != 0);
- BUG_ON((end % HPAGE_SIZE) != 0);
-
- for (addr = start; addr < end; addr += HPAGE_SIZE) {
- pte_t pte;
-
- ptep = huge_pte_offset(mm, addr);
- if (!ptep || pte_none(*ptep))
- continue;
-
- pte = *ptep;
- page = pte_page(pte);
- pte_clear(mm, addr, ptep);
-
- put_page(page);
- }
- add_mm_counter(mm, rss, -((end - start) >> PAGE_SHIFT));
- flush_tlb_pending();
-}
-
-int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
-{
- struct mm_struct *mm = current->mm;
- unsigned long addr;
- int ret = 0;
-
- WARN_ON(!is_vm_hugetlb_page(vma));
- BUG_ON((vma->vm_start % HPAGE_SIZE) != 0);
- BUG_ON((vma->vm_end % HPAGE_SIZE) != 0);
-
- spin_lock(&mm->page_table_lock);
- for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
- unsigned long idx;
- pte_t *pte = huge_pte_alloc(mm, addr);
- struct page *page;
-
- if (!pte) {
- ret = -ENOMEM;
- goto out;
- }
- if (! pte_none(*pte))
- continue;
-
- idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
- + (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
- page = find_get_page(mapping, idx);
- if (!page) {
- /* charge the fs quota first */
- if (hugetlb_get_quota(mapping)) {
- ret = -ENOMEM;
- goto out;
- }
- page = alloc_huge_page();
- if (!page) {
- hugetlb_put_quota(mapping);
- ret = -ENOMEM;
- goto out;
- }
- ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
- if (! ret) {
- unlock_page(page);
- } else {
- hugetlb_put_quota(mapping);
- free_huge_page(page);
- goto out;
- }
- }
- set_huge_pte(mm, vma, addr, page, pte, vma->vm_flags & VM_WRITE);
- }
-out:
- spin_unlock(&mm->page_table_lock);
- return ret;
-}
-
/* Because we have an exclusive hugepage region which lies within the
* normal user address space, we have to take special measures to make
* non-huge mmap()s evade the hugepage reserved regions. */
@@ -468,7 +292,12 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
&& !is_hugepage_only_range(mm, addr,len))
return addr;
}
- start_addr = addr = mm->free_area_cache;
+ if (len > mm->cached_hole_size) {
+ start_addr = addr = mm->free_area_cache;
+ } else {
+ start_addr = addr = TASK_UNMAPPED_BASE;
+ mm->cached_hole_size = 0;
+ }
full_search:
vma = find_vma(mm, addr);
@@ -492,6 +321,8 @@ full_search:
mm->free_area_cache = addr + len;
return addr;
}
+ if (addr + mm->cached_hole_size < vma->vm_start)
+ mm->cached_hole_size = vma->vm_start - addr;
addr = vma->vm_end;
vma = vma->vm_next;
}
@@ -499,6 +330,7 @@ full_search:
/* Make sure we didn't miss any holes */
if (start_addr != TASK_UNMAPPED_BASE) {
start_addr = addr = TASK_UNMAPPED_BASE;
+ mm->cached_hole_size = 0;
goto full_search;
}
return -ENOMEM;
@@ -520,6 +352,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
struct vm_area_struct *vma, *prev_vma;
struct mm_struct *mm = current->mm;
unsigned long base = mm->mmap_base, addr = addr0;
+ unsigned long largest_hole = mm->cached_hole_size;
int first_time = 1;
/* requested length too big for entire address space */
@@ -540,6 +373,10 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
return addr;
}
+ if (len <= largest_hole) {
+ largest_hole = 0;
+ mm->free_area_cache = base;
+ }
try_again:
/* make sure it can fit in the remaining address space */
if (mm->free_area_cache < len)
@@ -568,13 +405,21 @@ hugepage_recheck:
* vma->vm_start, use it:
*/
if (addr+len <= vma->vm_start &&
- (!prev_vma || (addr >= prev_vma->vm_end)))
+ (!prev_vma || (addr >= prev_vma->vm_end))) {
/* remember the address as a hint for next time */
- return (mm->free_area_cache = addr);
- else
+ mm->cached_hole_size = largest_hole;
+ return (mm->free_area_cache = addr);
+ } else {
/* pull free_area_cache down to the first hole */
- if (mm->free_area_cache == vma->vm_end)
+ if (mm->free_area_cache == vma->vm_end) {
mm->free_area_cache = vma->vm_start;
+ mm->cached_hole_size = largest_hole;
+ }
+ }
+
+ /* remember the largest hole we saw so far */
+ if (addr + largest_hole < vma->vm_start)
+ largest_hole = vma->vm_start - addr;
/* try just below the current vma->vm_start */
addr = vma->vm_start-len;
@@ -587,6 +432,7 @@ fail:
*/
if (first_time) {
mm->free_area_cache = base;
+ largest_hole = 0;
first_time = 0;
goto try_again;
}
@@ -597,11 +443,13 @@ fail:
* allocations.
*/
mm->free_area_cache = TASK_UNMAPPED_BASE;
+ mm->cached_hole_size = ~0UL;
addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
/*
* Restore the topdown base:
*/
mm->free_area_cache = base;
+ mm->cached_hole_size = ~0UL;
return addr;
}
diff --git a/arch/ppc64/mm/imalloc.c b/arch/ppc64/mm/imalloc.c
index cb8727f3267..b6e75b891ac 100644
--- a/arch/ppc64/mm/imalloc.c
+++ b/arch/ppc64/mm/imalloc.c
@@ -15,6 +15,7 @@
#include <asm/pgtable.h>
#include <asm/semaphore.h>
#include <asm/imalloc.h>
+#include <asm/cacheflush.h>
static DECLARE_MUTEX(imlist_sem);
struct vm_struct * imlist = NULL;
@@ -285,29 +286,32 @@ struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
return area;
}
-unsigned long im_free(void * addr)
+void im_free(void * addr)
{
struct vm_struct **p, *tmp;
- unsigned long ret_size = 0;
if (!addr)
- return ret_size;
- if ((PAGE_SIZE-1) & (unsigned long) addr) {
+ return;
+ if ((unsigned long) addr & ~PAGE_MASK) {
printk(KERN_ERR "Trying to %s bad address (%p)\n", __FUNCTION__, addr);
- return ret_size;
+ return;
}
down(&imlist_sem);
for (p = &imlist ; (tmp = *p) ; p = &tmp->next) {
if (tmp->addr == addr) {
- ret_size = tmp->size;
*p = tmp->next;
+
+ /* XXX: do we need the lock? */
+ spin_lock(&init_mm.page_table_lock);
+ unmap_vm_area(tmp);
+ spin_unlock(&init_mm.page_table_lock);
+
kfree(tmp);
up(&imlist_sem);
- return ret_size;
+ return;
}
}
up(&imlist_sem);
printk(KERN_ERR "Trying to %s nonexistent area (%p)\n", __FUNCTION__,
addr);
- return ret_size;
}
diff --git a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c
index 4b42aff74d7..b50b3a446db 100644
--- a/arch/ppc64/mm/init.c
+++ b/arch/ppc64/mm/init.c
@@ -73,9 +73,6 @@ static unsigned long phbs_io_bot = PHBS_IO_BASE;
extern pgd_t swapper_pg_dir[];
extern struct task_struct *current_set[NR_CPUS];
-extern pgd_t ioremap_dir[];
-pgd_t * ioremap_pgd = (pgd_t *)&ioremap_dir;
-
unsigned long klimit = (unsigned long)_end;
unsigned long _SDR1=0;
@@ -101,7 +98,7 @@ void show_mem(void)
printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
for_each_pgdat(pgdat) {
for (i = 0; i < pgdat->node_spanned_pages; i++) {
- page = pgdat->node_mem_map + i;
+ page = pgdat_page_nr(pgdat, i);
total++;
if (PageReserved(page))
reserved++;
@@ -137,69 +134,6 @@ void iounmap(volatile void __iomem *addr)
#else
-static void unmap_im_area_pte(pmd_t *pmd, unsigned long addr,
- unsigned long end)
-{
- pte_t *pte;
-
- pte = pte_offset_kernel(pmd, addr);
- do {
- pte_t ptent = ptep_get_and_clear(&ioremap_mm, addr, pte);
- WARN_ON(!pte_none(ptent) && !pte_present(ptent));
- } while (pte++, addr += PAGE_SIZE, addr != end);
-}
-
-static inline void unmap_im_area_pmd(pud_t *pud, unsigned long addr,
- unsigned long end)
-{
- pmd_t *pmd;
- unsigned long next;
-
- pmd = pmd_offset(pud, addr);
- do {
- next = pmd_addr_end(addr, end);
- if (pmd_none_or_clear_bad(pmd))
- continue;
- unmap_im_area_pte(pmd, addr, next);
- } while (pmd++, addr = next, addr != end);
-}
-
-static inline void unmap_im_area_pud(pgd_t *pgd, unsigned long addr,
- unsigned long end)
-{
- pud_t *pud;
- unsigned long next;
-
- pud = pud_offset(pgd, addr);
- do {
- next = pud_addr_end(addr, end);
- if (pud_none_or_clear_bad(pud))
- continue;
- unmap_im_area_pmd(pud, addr, next);
- } while (pud++, addr = next, addr != end);
-}
-
-static void unmap_im_area(unsigned long addr, unsigned long end)
-{
- struct mm_struct *mm = &ioremap_mm;
- unsigned long next;
- pgd_t *pgd;
-
- spin_lock(&mm->page_table_lock);
-
- pgd = pgd_offset_i(addr);
- flush_cache_vunmap(addr, end);
- do {
- next = pgd_addr_end(addr, end);
- if (pgd_none_or_clear_bad(pgd))
- continue;
- unmap_im_area_pud(pgd, addr, next);
- } while (pgd++, addr = next, addr != end);
- flush_tlb_kernel_range(start, end);
-
- spin_unlock(&mm->page_table_lock);
-}
-
/*
* map_io_page currently only called by __ioremap
* map_io_page adds an entry to the ioremap page table
@@ -214,21 +148,21 @@ static int map_io_page(unsigned long ea, unsigned long pa, int flags)
unsigned long vsid;
if (mem_init_done) {
- spin_lock(&ioremap_mm.page_table_lock);
- pgdp = pgd_offset_i(ea);
- pudp = pud_alloc(&ioremap_mm, pgdp, ea);
+ spin_lock(&init_mm.page_table_lock);
+ pgdp = pgd_offset_k(ea);
+ pudp = pud_alloc(&init_mm, pgdp, ea);
if (!pudp)
return -ENOMEM;
- pmdp = pmd_alloc(&ioremap_mm, pudp, ea);
+ pmdp = pmd_alloc(&init_mm, pudp, ea);
if (!pmdp)
return -ENOMEM;
- ptep = pte_alloc_kernel(&ioremap_mm, pmdp, ea);
+ ptep = pte_alloc_kernel(&init_mm, pmdp, ea);
if (!ptep)
return -ENOMEM;
pa = abs_to_phys(pa);
- set_pte_at(&ioremap_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT,
+ set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT,
__pgprot(flags)));
- spin_unlock(&ioremap_mm.page_table_lock);
+ spin_unlock(&init_mm.page_table_lock);
} else {
unsigned long va, vpn, hash, hpteg;
@@ -267,13 +201,9 @@ static void __iomem * __ioremap_com(unsigned long addr, unsigned long pa,
for (i = 0; i < size; i += PAGE_SIZE)
if (map_io_page(ea+i, pa+i, flags))
- goto failure;
+ return NULL;
return (void __iomem *) (ea + (addr & ~PAGE_MASK));
- failure:
- if (mem_init_done)
- unmap_im_area(ea, ea + size);
- return NULL;
}
@@ -381,19 +311,14 @@ int __ioremap_explicit(unsigned long pa, unsigned long ea,
*/
void iounmap(volatile void __iomem *token)
{
- unsigned long address, size;
void *addr;
if (!mem_init_done)
return;
addr = (void *) ((unsigned long __force) token & PAGE_MASK);
-
- if ((size = im_free(addr)) == 0)
- return;
- address = (unsigned long)addr;
- unmap_im_area(address, address + size);
+ im_free(addr);
}
static int iounmap_subset_regions(unsigned long addr, unsigned long size)
@@ -606,7 +531,7 @@ EXPORT_SYMBOL(page_is_ram);
* Initialize the bootmem system and give it all the memory we
* have available.
*/
-#ifndef CONFIG_DISCONTIGMEM
+#ifndef CONFIG_NEED_MULTIPLE_NODES
void __init do_init_bootmem(void)
{
unsigned long i;
@@ -628,12 +553,20 @@ void __init do_init_bootmem(void)
max_pfn = max_low_pfn;
- /* add all physical memory to the bootmem map. Also find the first */
+ /* Add all physical memory to the bootmem map, mark each area
+ * present.
+ */
for (i=0; i < lmb.memory.cnt; i++) {
unsigned long physbase, size;
+ unsigned long start_pfn, end_pfn;
physbase = lmb.memory.region[i].physbase;
size = lmb.memory.region[i].size;
+
+ start_pfn = physbase >> PAGE_SHIFT;
+ end_pfn = start_pfn + (size >> PAGE_SHIFT);
+ memory_present(0, start_pfn, end_pfn);
+
free_bootmem(physbase, size);
}
@@ -672,7 +605,7 @@ void __init paging_init(void)
free_area_init_node(0, NODE_DATA(0), zones_size,
__pa(PAGE_OFFSET) >> PAGE_SHIFT, zholes_size);
}
-#endif /* CONFIG_DISCONTIGMEM */
+#endif /* ! CONFIG_NEED_MULTIPLE_NODES */
static struct kcore_list kcore_vmem;
@@ -703,7 +636,7 @@ module_init(setup_kcore);
void __init mem_init(void)
{
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NEED_MULTIPLE_NODES
int nid;
#endif
pg_data_t *pgdat;
@@ -714,7 +647,7 @@ void __init mem_init(void)
num_physpages = max_low_pfn; /* RAM is assumed contiguous */
high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NEED_MULTIPLE_NODES
for_each_online_node(nid) {
if (NODE_DATA(nid)->node_spanned_pages != 0) {
printk("freeing bootmem node %x\n", nid);
@@ -729,7 +662,7 @@ void __init mem_init(void)
for_each_pgdat(pgdat) {
for (i = 0; i < pgdat->node_spanned_pages; i++) {
- page = pgdat->node_mem_map + i;
+ page = pgdat_page_nr(pgdat, i);
if (PageReserved(page))
reservedpages++;
}
diff --git a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c
index ea862ec643d..cafd91aef28 100644
--- a/arch/ppc64/mm/numa.c
+++ b/arch/ppc64/mm/numa.c
@@ -440,6 +440,8 @@ new_range:
for (i = start ; i < (start+size); i += MEMORY_INCREMENT)
numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] =
numa_domain;
+ memory_present(numa_domain, start >> PAGE_SHIFT,
+ (start + size) >> PAGE_SHIFT);
if (--ranges)
goto new_range;
@@ -481,6 +483,7 @@ static void __init setup_nonnuma(void)
for (i = 0 ; i < top_of_ram; i += MEMORY_INCREMENT)
numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] = 0;
+ memory_present(0, 0, init_node_data[0].node_end_pfn);
}
static void __init dump_numa_topology(void)
diff --git a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c
index 3c0ccb2623a..7f6e13a4b71 100644
--- a/arch/ppc64/xmon/xmon.c
+++ b/arch/ppc64/xmon/xmon.c
@@ -2247,7 +2247,14 @@ scanhex(unsigned long *vp)
tmpstr[i] = c;
}
tmpstr[i++] = 0;
- *vp = kallsyms_lookup_name(tmpstr);
+ *vp = 0;
+ if (setjmp(bus_error_jmp) == 0) {
+ catch_memory_errors = 1;
+ sync();
+ *vp = kallsyms_lookup_name(tmpstr);
+ sync();
+ }
+ catch_memory_errors = 0;
if (!(*vp)) {
printf("unknown symbol '%s'\n", tmpstr);
return 0;
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index ab79af84699..6600ee87f89 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -226,6 +226,8 @@ config WARN_STACK_SIZE
This allows you to specify the maximum frame size a function may
have without the compiler complaining about it.
+source "mm/Kconfig"
+
comment "I/O subsystem configuration"
config MACHCHK_WARNING
@@ -453,6 +455,14 @@ config NO_IDLE_HZ_INIT
The HZ timer is switched off in idle by default. That means the
HZ timer is already disabled at boot time.
+config KEXEC
+ bool "kexec system call (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ help
+ kexec is a system call that implements the ability to shutdown your
+ current kernel, and to start another kernel. It is like a reboot
+ but is independent of hardware/microcode support.
+
endmenu
config PCMCIA
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index 01ae1964c93..c067435bae4 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -28,6 +28,7 @@
//#include <linux/kernel_stat.h>
#include <linux/notifier.h>
#include <linux/cpu.h>
+#include <linux/workqueue.h>
#include "appldata.h"
@@ -133,9 +134,12 @@ static int appldata_interval = APPLDATA_CPU_INTERVAL;
static int appldata_timer_active;
/*
- * Tasklet
+ * Work queue
*/
-static struct tasklet_struct appldata_tasklet_struct;
+static struct workqueue_struct *appldata_wq;
+static void appldata_work_fn(void *data);
+static DECLARE_WORK(appldata_work, appldata_work_fn, NULL);
+
/*
* Ops list
@@ -144,11 +148,11 @@ static DEFINE_SPINLOCK(appldata_ops_lock);
static LIST_HEAD(appldata_ops_list);
-/************************* timer, tasklet, DIAG ******************************/
+/*************************** timer, work, DIAG *******************************/
/*
* appldata_timer_function()
*
- * schedule tasklet and reschedule timer
+ * schedule work and reschedule timer
*/
static void appldata_timer_function(unsigned long data, struct pt_regs *regs)
{
@@ -157,22 +161,22 @@ static void appldata_timer_function(unsigned long data, struct pt_regs *regs)
atomic_read(&appldata_expire_count));
if (atomic_dec_and_test(&appldata_expire_count)) {
atomic_set(&appldata_expire_count, num_online_cpus());
- tasklet_schedule((struct tasklet_struct *) data);
+ queue_work(appldata_wq, (struct work_struct *) data);
}
}
/*
- * appldata_tasklet_function()
+ * appldata_work_fn()
*
* call data gathering function for each (active) module
*/
-static void appldata_tasklet_function(unsigned long data)
+static void appldata_work_fn(void *data)
{
struct list_head *lh;
struct appldata_ops *ops;
int i;
- P_DEBUG(" -= Tasklet =-\n");
+ P_DEBUG(" -= Work Queue =-\n");
i = 0;
spin_lock(&appldata_ops_lock);
list_for_each(lh, &appldata_ops_list) {
@@ -231,7 +235,7 @@ static int appldata_diag(char record_nr, u16 function, unsigned long buffer,
: "=d" (ry) : "d" (&(appldata_parameter_list)) : "cc");
return (int) ry;
}
-/********************** timer, tasklet, DIAG <END> ***************************/
+/************************ timer, work, DIAG <END> ****************************/
/****************************** /proc stuff **********************************/
@@ -411,7 +415,7 @@ appldata_generic_handler(ctl_table *ctl, int write, struct file *filp,
struct list_head *lh;
found = 0;
- spin_lock_bh(&appldata_ops_lock);
+ spin_lock(&appldata_ops_lock);
list_for_each(lh, &appldata_ops_list) {
tmp_ops = list_entry(lh, struct appldata_ops, list);
if (&tmp_ops->ctl_table[2] == ctl) {
@@ -419,15 +423,15 @@ appldata_generic_handler(ctl_table *ctl, int write, struct file *filp,
}
}
if (!found) {
- spin_unlock_bh(&appldata_ops_lock);
+ spin_unlock(&appldata_ops_lock);
return -ENODEV;
}
ops = ctl->data;
if (!try_module_get(ops->owner)) { // protect this function
- spin_unlock_bh(&appldata_ops_lock);
+ spin_unlock(&appldata_ops_lock);
return -ENODEV;
}
- spin_unlock_bh(&appldata_ops_lock);
+ spin_unlock(&appldata_ops_lock);
if (!*lenp || *ppos) {
*lenp = 0;
@@ -451,10 +455,11 @@ appldata_generic_handler(ctl_table *ctl, int write, struct file *filp,
return -EFAULT;
}
- spin_lock_bh(&appldata_ops_lock);
+ spin_lock(&appldata_ops_lock);
if ((buf[0] == '1') && (ops->active == 0)) {
- if (!try_module_get(ops->owner)) { // protect tasklet
- spin_unlock_bh(&appldata_ops_lock);
+ // protect work queue callback
+ if (!try_module_get(ops->owner)) {
+ spin_unlock(&appldata_ops_lock);
module_put(ops->owner);
return -ENODEV;
}
@@ -485,7 +490,7 @@ appldata_generic_handler(ctl_table *ctl, int write, struct file *filp,
}
module_put(ops->owner);
}
- spin_unlock_bh(&appldata_ops_lock);
+ spin_unlock(&appldata_ops_lock);
out:
*lenp = len;
*ppos += len;
@@ -529,7 +534,7 @@ int appldata_register_ops(struct appldata_ops *ops)
}
memset(ops->ctl_table, 0, 4*sizeof(struct ctl_table));
- spin_lock_bh(&appldata_ops_lock);
+ spin_lock(&appldata_ops_lock);
list_for_each(lh, &appldata_ops_list) {
tmp_ops = list_entry(lh, struct appldata_ops, list);
P_DEBUG("register_ops loop: %i) name = %s, ctl = %i\n",
@@ -541,18 +546,18 @@ int appldata_register_ops(struct appldata_ops *ops)
APPLDATA_PROC_NAME_LENGTH) == 0) {
P_ERROR("Name \"%s\" already registered!\n", ops->name);
kfree(ops->ctl_table);
- spin_unlock_bh(&appldata_ops_lock);
+ spin_unlock(&appldata_ops_lock);
return -EBUSY;
}
if (tmp_ops->ctl_nr == ops->ctl_nr) {
P_ERROR("ctl_nr %i already registered!\n", ops->ctl_nr);
kfree(ops->ctl_table);
- spin_unlock_bh(&appldata_ops_lock);
+ spin_unlock(&appldata_ops_lock);
return -EBUSY;
}
}
list_add(&ops->list, &appldata_ops_list);
- spin_unlock_bh(&appldata_ops_lock);
+ spin_unlock(&appldata_ops_lock);
ops->ctl_table[0].ctl_name = CTL_APPLDATA;
ops->ctl_table[0].procname = appldata_proc_name;
@@ -583,12 +588,12 @@ int appldata_register_ops(struct appldata_ops *ops)
*/
void appldata_unregister_ops(struct appldata_ops *ops)
{
- spin_lock_bh(&appldata_ops_lock);
+ spin_lock(&appldata_ops_lock);
unregister_sysctl_table(ops->sysctl_header);
list_del(&ops->list);
kfree(ops->ctl_table);
ops->ctl_table = NULL;
- spin_unlock_bh(&appldata_ops_lock);
+ spin_unlock(&appldata_ops_lock);
P_INFO("%s-ops unregistered!\n", ops->name);
}
/********************** module-ops management <END> **************************/
@@ -602,7 +607,7 @@ appldata_online_cpu(int cpu)
init_virt_timer(&per_cpu(appldata_timer, cpu));
per_cpu(appldata_timer, cpu).function = appldata_timer_function;
per_cpu(appldata_timer, cpu).data = (unsigned long)
- &appldata_tasklet_struct;
+ &appldata_work;
atomic_inc(&appldata_expire_count);
spin_lock(&appldata_timer_lock);
__appldata_vtimer_setup(APPLDATA_MOD_TIMER);
@@ -615,7 +620,7 @@ appldata_offline_cpu(int cpu)
del_virt_timer(&per_cpu(appldata_timer, cpu));
if (atomic_dec_and_test(&appldata_expire_count)) {
atomic_set(&appldata_expire_count, num_online_cpus());
- tasklet_schedule(&appldata_tasklet_struct);
+ queue_work(appldata_wq, &appldata_work);
}
spin_lock(&appldata_timer_lock);
__appldata_vtimer_setup(APPLDATA_MOD_TIMER);
@@ -648,7 +653,7 @@ static struct notifier_block __devinitdata appldata_nb = {
/*
* appldata_init()
*
- * init timer and tasklet, register /proc entries
+ * init timer, register /proc entries
*/
static int __init appldata_init(void)
{
@@ -657,6 +662,12 @@ static int __init appldata_init(void)
P_DEBUG("sizeof(parameter_list) = %lu\n",
sizeof(struct appldata_parameter_list));
+ appldata_wq = create_singlethread_workqueue("appldata");
+ if (!appldata_wq) {
+ P_ERROR("Could not create work queue\n");
+ return -ENOMEM;
+ }
+
for_each_online_cpu(i)
appldata_online_cpu(i);
@@ -670,7 +681,6 @@ static int __init appldata_init(void)
appldata_table[1].de->owner = THIS_MODULE;
#endif
- tasklet_init(&appldata_tasklet_struct, appldata_tasklet_function, 0);
P_DEBUG("Base interface initialized.\n");
return 0;
}
@@ -678,7 +688,7 @@ static int __init appldata_init(void)
/*
* appldata_exit()
*
- * stop timer and tasklet, unregister /proc entries
+ * stop timer, unregister /proc entries
*/
static void __exit appldata_exit(void)
{
@@ -690,7 +700,7 @@ static void __exit appldata_exit(void)
/*
* ops list should be empty, but just in case something went wrong...
*/
- spin_lock_bh(&appldata_ops_lock);
+ spin_lock(&appldata_ops_lock);
list_for_each(lh, &appldata_ops_list) {
ops = list_entry(lh, struct appldata_ops, list);
rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC,
@@ -700,7 +710,7 @@ static void __exit appldata_exit(void)
"return code: %d\n", ops->name, rc);
}
}
- spin_unlock_bh(&appldata_ops_lock);
+ spin_unlock(&appldata_ops_lock);
for_each_online_cpu(i)
appldata_offline_cpu(i);
@@ -709,7 +719,7 @@ static void __exit appldata_exit(void)
unregister_sysctl_table(appldata_sysctl_header);
- tasklet_kill(&appldata_tasklet_struct);
+ destroy_workqueue(appldata_wq);
P_DEBUG("... module unloaded!\n");
}
/**************************** init / exit <END> ******************************/
diff --git a/arch/s390/appldata/appldata_mem.c b/arch/s390/appldata/appldata_mem.c
index 462ee9a84e7..f0e2fbed3d4 100644
--- a/arch/s390/appldata/appldata_mem.c
+++ b/arch/s390/appldata/appldata_mem.c
@@ -68,7 +68,7 @@ struct appldata_mem_data {
u64 pgmajfault; /* page faults (major only) */
// <-- New in 2.6
-} appldata_mem_data;
+} __attribute__((packed)) appldata_mem_data;
static inline void appldata_debug_print(struct appldata_mem_data *mem_data)
diff --git a/arch/s390/appldata/appldata_net_sum.c b/arch/s390/appldata/appldata_net_sum.c
index dd61638d302..2a4c7432db4 100644
--- a/arch/s390/appldata/appldata_net_sum.c
+++ b/arch/s390/appldata/appldata_net_sum.c
@@ -57,7 +57,7 @@ struct appldata_net_sum_data {
u64 rx_dropped; /* no space in linux buffers */
u64 tx_dropped; /* no space available in linux */
u64 collisions; /* collisions while transmitting */
-} appldata_net_sum_data;
+} __attribute__((packed)) appldata_net_sum_data;
static inline void appldata_print_debug(struct appldata_net_sum_data *net_data)
diff --git a/arch/s390/appldata/appldata_os.c b/arch/s390/appldata/appldata_os.c
index b83f0748455..e0a476bf4fd 100644
--- a/arch/s390/appldata/appldata_os.c
+++ b/arch/s390/appldata/appldata_os.c
@@ -49,7 +49,7 @@ struct appldata_os_per_cpu {
u32 per_cpu_softirq; /* ... spent in softirqs */
u32 per_cpu_iowait; /* ... spent while waiting for I/O */
// <-- New in 2.6
-};
+} __attribute__((packed));
struct appldata_os_data {
u64 timestamp;
@@ -75,7 +75,7 @@ struct appldata_os_data {
/* per cpu data */
struct appldata_os_per_cpu os_cpu[0];
-};
+} __attribute__((packed));
static struct appldata_os_data *appldata_os_data;
diff --git a/arch/s390/boot/install.sh b/arch/s390/boot/install.sh
index 278a8139cb1..d4026f62cb0 100644
--- a/arch/s390/boot/install.sh
+++ b/arch/s390/boot/install.sh
@@ -21,8 +21,8 @@
# User may have a custom install script
-if [ -x ~/bin/installkernel ]; then exec ~/bin/installkernel "$@"; fi
-if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi
+if [ -x ~/bin/${CROSS_COMPILE}installkernel ]; then exec ~/bin/${CROSS_COMPILE}installkernel "$@"; fi
+if [ -x /sbin/${CROSS_COMPILE}installkernel ]; then exec /sbin/${CROSS_COMPILE}installkernel "$@"; fi
# Default install - same as make zlilo
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 07fd0414a4b..89850b2c27e 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -245,6 +245,7 @@ CONFIG_S390_TAPE_BLOCK=y
#
CONFIG_S390_TAPE_34XX=m
# CONFIG_VMLOGRDR is not set
+# CONFIG_VMCP is not set
# CONFIG_MONREADER is not set
# CONFIG_DCSS_SHM is not set
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index b41e0e199a7..ab1e49d2e51 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -25,6 +25,16 @@ obj-$(CONFIG_ARCH_S390X) += entry64.o reipl64.o
obj-$(CONFIG_VIRT_TIMER) += vtime.o
+# Kexec part
+S390_KEXEC_OBJS := machine_kexec.o crash.o
+ifeq ($(CONFIG_ARCH_S390X),y)
+S390_KEXEC_OBJS += relocate_kernel64.o
+else
+S390_KEXEC_OBJS += relocate_kernel.o
+endif
+obj-$(CONFIG_KEXEC) += $(S390_KEXEC_OBJS)
+
+
#
# This is just to get the dependencies...
#
diff --git a/arch/s390/kernel/compat_ioctl.c b/arch/s390/kernel/compat_ioctl.c
index 03d03c6d3cb..24a1e9f069a 100644
--- a/arch/s390/kernel/compat_ioctl.c
+++ b/arch/s390/kernel/compat_ioctl.c
@@ -42,7 +42,6 @@ struct ioctl_trans ioctl_start[] = {
#include "../../../fs/compat_ioctl.c"
/* s390 only ioctls */
-#if defined(CONFIG_DASD) || defined(CONFIG_DASD_MODULE)
COMPATIBLE_IOCTL(DASDAPIVER)
COMPATIBLE_IOCTL(BIODASDDISABLE)
COMPATIBLE_IOCTL(BIODASDENABLE)
@@ -59,16 +58,11 @@ COMPATIBLE_IOCTL(BIODASDPRRD)
COMPATIBLE_IOCTL(BIODASDPSRD)
COMPATIBLE_IOCTL(BIODASDGATTR)
COMPATIBLE_IOCTL(BIODASDSATTR)
-#if defined(CONFIG_DASD_CMB) || defined(CONFIG_DASD_CMB_MODULE)
COMPATIBLE_IOCTL(BIODASDCMFENABLE)
COMPATIBLE_IOCTL(BIODASDCMFDISABLE)
COMPATIBLE_IOCTL(BIODASDREADALLCMB)
-#endif
-#endif
-#if defined(CONFIG_S390_TAPE) || defined(CONFIG_S390_TAPE_MODULE)
COMPATIBLE_IOCTL(TAPE390_DISPLAY)
-#endif
/* s390 doesn't need handlers here */
COMPATIBLE_IOCTL(TIOCGSERIAL)
diff --git a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h
index bf33dcfec7d..3898f66d0b2 100644
--- a/arch/s390/kernel/compat_linux.h
+++ b/arch/s390/kernel/compat_linux.h
@@ -45,7 +45,7 @@ typedef struct compat_siginfo {
/* POSIX.1b timers */
struct {
- timer_t _tid; /* timer id */
+ compat_timer_t _tid; /* timer id */
int _overrun; /* overrun count */
compat_sigval_t _sigval; /* same as below */
int _sys_private; /* not to be passed to user */
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 7a607b1d038..bf529739c8a 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1441,3 +1441,11 @@ compat_sys_waitid_wrapper:
lgfr %r5,%r5 # int
llgtr %r6,%r6 # struct rusage_emu31 *
jg compat_sys_waitid
+
+ .globl compat_sys_kexec_load_wrapper
+compat_sys_kexec_load_wrapper:
+ llgfr %r2,%r2 # unsigned long
+ llgfr %r3,%r3 # unsigned long
+ llgtr %r4,%r4 # struct kexec_segment *
+ llgfr %r5,%r5 # unsigned long
+ jg compat_sys_kexec_load
diff --git a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c
index 44df8dc07c5..20062145e84 100644
--- a/arch/s390/kernel/cpcmd.c
+++ b/arch/s390/kernel/cpcmd.c
@@ -2,7 +2,7 @@
* arch/s390/kernel/cpcmd.c
*
* S390 version
- * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright (C) 1999,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
* Christian Borntraeger (cborntra@de.ibm.com),
*/
@@ -18,93 +18,114 @@
#include <asm/system.h>
static DEFINE_SPINLOCK(cpcmd_lock);
-static char cpcmd_buf[240];
+static char cpcmd_buf[241];
/*
* the caller of __cpcmd has to ensure that the response buffer is below 2 GB
*/
-void __cpcmd(char *cmd, char *response, int rlen)
+int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
{
const int mask = 0x40000000L;
unsigned long flags;
+ int return_code;
+ int return_len;
int cmdlen;
spin_lock_irqsave(&cpcmd_lock, flags);
cmdlen = strlen(cmd);
BUG_ON(cmdlen > 240);
- strcpy(cpcmd_buf, cmd);
+ memcpy(cpcmd_buf, cmd, cmdlen);
ASCEBC(cpcmd_buf, cmdlen);
if (response != NULL && rlen > 0) {
memset(response, 0, rlen);
#ifndef CONFIG_ARCH_S390X
- asm volatile ("LRA 2,0(%0)\n\t"
- "LR 4,%1\n\t"
- "O 4,%4\n\t"
- "LRA 3,0(%2)\n\t"
- "LR 5,%3\n\t"
- ".long 0x83240008 # Diagnose X'08'\n\t"
- : /* no output */
- : "a" (cpcmd_buf), "d" (cmdlen),
- "a" (response), "d" (rlen), "m" (mask)
- : "cc", "2", "3", "4", "5" );
+ asm volatile ( "lra 2,0(%2)\n"
+ "lr 4,%3\n"
+ "o 4,%6\n"
+ "lra 3,0(%4)\n"
+ "lr 5,%5\n"
+ "diag 2,4,0x8\n"
+ "brc 8, .Litfits\n"
+ "ar 5, %5\n"
+ ".Litfits: \n"
+ "lr %0,4\n"
+ "lr %1,5\n"
+ : "=d" (return_code), "=d" (return_len)
+ : "a" (cpcmd_buf), "d" (cmdlen),
+ "a" (response), "d" (rlen), "m" (mask)
+ : "cc", "2", "3", "4", "5" );
#else /* CONFIG_ARCH_S390X */
- asm volatile (" lrag 2,0(%0)\n"
- " lgr 4,%1\n"
- " o 4,%4\n"
- " lrag 3,0(%2)\n"
- " lgr 5,%3\n"
- " sam31\n"
- " .long 0x83240008 # Diagnose X'08'\n"
- " sam64"
- : /* no output */
- : "a" (cpcmd_buf), "d" (cmdlen),
- "a" (response), "d" (rlen), "m" (mask)
- : "cc", "2", "3", "4", "5" );
+ asm volatile ( "lrag 2,0(%2)\n"
+ "lgr 4,%3\n"
+ "o 4,%6\n"
+ "lrag 3,0(%4)\n"
+ "lgr 5,%5\n"
+ "sam31\n"
+ "diag 2,4,0x8\n"
+ "sam64\n"
+ "brc 8, .Litfits\n"
+ "agr 5, %5\n"
+ ".Litfits: \n"
+ "lgr %0,4\n"
+ "lgr %1,5\n"
+ : "=d" (return_code), "=d" (return_len)
+ : "a" (cpcmd_buf), "d" (cmdlen),
+ "a" (response), "d" (rlen), "m" (mask)
+ : "cc", "2", "3", "4", "5" );
#endif /* CONFIG_ARCH_S390X */
EBCASC(response, rlen);
} else {
+ return_len = 0;
#ifndef CONFIG_ARCH_S390X
- asm volatile ("LRA 2,0(%0)\n\t"
- "LR 3,%1\n\t"
- ".long 0x83230008 # Diagnose X'08'\n\t"
- : /* no output */
- : "a" (cpcmd_buf), "d" (cmdlen)
- : "2", "3" );
+ asm volatile ( "lra 2,0(%1)\n"
+ "lr 3,%2\n"
+ "diag 2,3,0x8\n"
+ "lr %0,3\n"
+ : "=d" (return_code)
+ : "a" (cpcmd_buf), "d" (cmdlen)
+ : "2", "3" );
#else /* CONFIG_ARCH_S390X */
- asm volatile (" lrag 2,0(%0)\n"
- " lgr 3,%1\n"
- " sam31\n"
- " .long 0x83230008 # Diagnose X'08'\n"
- " sam64"
- : /* no output */
- : "a" (cpcmd_buf), "d" (cmdlen)
- : "2", "3" );
+ asm volatile ( "lrag 2,0(%1)\n"
+ "lgr 3,%2\n"
+ "sam31\n"
+ "diag 2,3,0x8\n"
+ "sam64\n"
+ "lgr %0,3\n"
+ : "=d" (return_code)
+ : "a" (cpcmd_buf), "d" (cmdlen)
+ : "2", "3" );
#endif /* CONFIG_ARCH_S390X */
}
spin_unlock_irqrestore(&cpcmd_lock, flags);
+ if (response_code != NULL)
+ *response_code = return_code;
+ return return_len;
}
EXPORT_SYMBOL(__cpcmd);
#ifdef CONFIG_ARCH_S390X
-void cpcmd(char *cmd, char *response, int rlen)
+int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
{
char *lowbuf;
+ int len;
+
if ((rlen == 0) || (response == NULL)
|| !((unsigned long)response >> 31))
- __cpcmd(cmd, response, rlen);
+ len = __cpcmd(cmd, response, rlen, response_code);
else {
lowbuf = kmalloc(rlen, GFP_KERNEL | GFP_DMA);
if (!lowbuf) {
printk(KERN_WARNING
"cpcmd: could not allocate response buffer\n");
- return;
+ return -ENOMEM;
}
- __cpcmd(cmd, lowbuf, rlen);
+ len = __cpcmd(cmd, lowbuf, rlen, response_code);
memcpy(response, lowbuf, rlen);
kfree(lowbuf);
}
+ return len;
}
EXPORT_SYMBOL(cpcmd);
diff --git a/arch/s390/kernel/crash.c b/arch/s390/kernel/crash.c
new file mode 100644
index 00000000000..7bd169c58b0
--- /dev/null
+++ b/arch/s390/kernel/crash.c
@@ -0,0 +1,17 @@
+/*
+ * arch/s390/kernel/crash.c
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
+ *
+ */
+
+#include <linux/threads.h>
+#include <linux/kexec.h>
+
+note_buf_t crash_notes[NR_CPUS];
+
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+}
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index 91f8ce5543d..960ba6029c3 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -19,22 +19,27 @@
#include <linux/sysctl.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
-
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/debugfs.h>
#include <asm/debug.h>
#define DEBUG_PROLOG_ENTRY -1
+#define ALL_AREAS 0 /* copy all debug areas */
+#define NO_AREAS 1 /* copy no debug areas */
+
/* typedefs */
typedef struct file_private_info {
loff_t offset; /* offset of last read in file */
int act_area; /* number of last formated area */
+ int act_page; /* act page in given area */
int act_entry; /* last formated entry (offset */
/* relative to beginning of last */
- /* formated area) */
+ /* formated page) */
size_t act_entry_offset; /* up to this offset we copied */
/* in last read the last formated */
/* entry to userland */
@@ -51,8 +56,8 @@ typedef struct
* This assumes that all args are converted into longs
* on L/390 this is the case for all types of parameter
* except of floats, and long long (32 bit)
- *
- */
+ *
+ */
long args[0];
} debug_sprintf_entry_t;
@@ -63,32 +68,38 @@ extern void tod_to_timeval(uint64_t todval, struct timeval *xtime);
static int debug_init(void);
static ssize_t debug_output(struct file *file, char __user *user_buf,
- size_t user_len, loff_t * offset);
+ size_t user_len, loff_t * offset);
static ssize_t debug_input(struct file *file, const char __user *user_buf,
- size_t user_len, loff_t * offset);
+ size_t user_len, loff_t * offset);
static int debug_open(struct inode *inode, struct file *file);
static int debug_close(struct inode *inode, struct file *file);
-static debug_info_t* debug_info_create(char *name, int page_order, int nr_areas, int buf_size);
+static debug_info_t* debug_info_create(char *name, int pages_per_area,
+ int nr_areas, int buf_size);
static void debug_info_get(debug_info_t *);
static void debug_info_put(debug_info_t *);
static int debug_prolog_level_fn(debug_info_t * id,
- struct debug_view *view, char *out_buf);
+ struct debug_view *view, char *out_buf);
static int debug_input_level_fn(debug_info_t * id, struct debug_view *view,
- struct file *file, const char __user *user_buf,
- size_t user_buf_size, loff_t * offset);
+ struct file *file, const char __user *user_buf,
+ size_t user_buf_size, loff_t * offset);
+static int debug_prolog_pages_fn(debug_info_t * id,
+ struct debug_view *view, char *out_buf);
+static int debug_input_pages_fn(debug_info_t * id, struct debug_view *view,
+ struct file *file, const char __user *user_buf,
+ size_t user_buf_size, loff_t * offset);
static int debug_input_flush_fn(debug_info_t * id, struct debug_view *view,
- struct file *file, const char __user *user_buf,
- size_t user_buf_size, loff_t * offset);
+ struct file *file, const char __user *user_buf,
+ size_t user_buf_size, loff_t * offset);
static int debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view,
- char *out_buf, const char *in_buf);
+ char *out_buf, const char *in_buf);
static int debug_raw_format_fn(debug_info_t * id,
- struct debug_view *view, char *out_buf,
- const char *in_buf);
+ struct debug_view *view, char *out_buf,
+ const char *in_buf);
static int debug_raw_header_fn(debug_info_t * id, struct debug_view *view,
- int area, debug_entry_t * entry, char *out_buf);
+ int area, debug_entry_t * entry, char *out_buf);
static int debug_sprintf_format_fn(debug_info_t * id, struct debug_view *view,
- char *out_buf, debug_sprintf_entry_t *curr_event);
+ char *out_buf, debug_sprintf_entry_t *curr_event);
/* globals */
@@ -119,6 +130,15 @@ struct debug_view debug_level_view = {
NULL
};
+struct debug_view debug_pages_view = {
+ "pages",
+ &debug_prolog_pages_fn,
+ NULL,
+ NULL,
+ &debug_input_pages_fn,
+ NULL
+};
+
struct debug_view debug_flush_view = {
"flush",
NULL,
@@ -149,98 +169,161 @@ DECLARE_MUTEX(debug_lock);
static int initialized;
static struct file_operations debug_file_ops = {
- .owner = THIS_MODULE,
+ .owner = THIS_MODULE,
.read = debug_output,
- .write = debug_input,
+ .write = debug_input,
.open = debug_open,
.release = debug_close,
};
-static struct proc_dir_entry *debug_proc_root_entry;
+static struct dentry *debug_debugfs_root_entry;
/* functions */
/*
+ * debug_areas_alloc
+ * - Debug areas are implemented as a threedimensonal array:
+ * areas[areanumber][pagenumber][pageoffset]
+ */
+
+static debug_entry_t***
+debug_areas_alloc(int pages_per_area, int nr_areas)
+{
+ debug_entry_t*** areas;
+ int i,j;
+
+ areas = (debug_entry_t ***) kmalloc(nr_areas *
+ sizeof(debug_entry_t**),
+ GFP_KERNEL);
+ if (!areas)
+ goto fail_malloc_areas;
+ for (i = 0; i < nr_areas; i++) {
+ areas[i] = (debug_entry_t**) kmalloc(pages_per_area *
+ sizeof(debug_entry_t*),GFP_KERNEL);
+ if (!areas[i]) {
+ goto fail_malloc_areas2;
+ }
+ for(j = 0; j < pages_per_area; j++) {
+ areas[i][j] = (debug_entry_t*)kmalloc(PAGE_SIZE,
+ GFP_KERNEL);
+ if(!areas[i][j]) {
+ for(j--; j >=0 ; j--) {
+ kfree(areas[i][j]);
+ }
+ kfree(areas[i]);
+ goto fail_malloc_areas2;
+ } else {
+ memset(areas[i][j],0,PAGE_SIZE);
+ }
+ }
+ }
+ return areas;
+
+fail_malloc_areas2:
+ for(i--; i >= 0; i--){
+ for(j=0; j < pages_per_area;j++){
+ kfree(areas[i][j]);
+ }
+ kfree(areas[i]);
+ }
+ kfree(areas);
+fail_malloc_areas:
+ return NULL;
+
+}
+
+
+/*
* debug_info_alloc
* - alloc new debug-info
*/
-static debug_info_t* debug_info_alloc(char *name, int page_order,
- int nr_areas, int buf_size)
+static debug_info_t*
+debug_info_alloc(char *name, int pages_per_area, int nr_areas, int buf_size,
+ int level, int mode)
{
debug_info_t* rc;
- int i;
/* alloc everything */
- rc = (debug_info_t*) kmalloc(sizeof(debug_info_t), GFP_ATOMIC);
+ rc = (debug_info_t*) kmalloc(sizeof(debug_info_t), GFP_KERNEL);
if(!rc)
goto fail_malloc_rc;
- rc->active_entry = (int*)kmalloc(nr_areas * sizeof(int), GFP_ATOMIC);
- if(!rc->active_entry)
- goto fail_malloc_active_entry;
- memset(rc->active_entry, 0, nr_areas * sizeof(int));
- rc->areas = (debug_entry_t **) kmalloc(nr_areas *
- sizeof(debug_entry_t *),
- GFP_ATOMIC);
- if (!rc->areas)
- goto fail_malloc_areas;
- for (i = 0; i < nr_areas; i++) {
- rc->areas[i] = (debug_entry_t *) __get_free_pages(GFP_ATOMIC,
- page_order);
- if (!rc->areas[i]) {
- for (i--; i >= 0; i--) {
- free_pages((unsigned long) rc->areas[i],
- page_order);
- }
- goto fail_malloc_areas2;
- } else {
- memset(rc->areas[i], 0, PAGE_SIZE << page_order);
- }
+ rc->active_entries = (int*)kmalloc(nr_areas * sizeof(int), GFP_KERNEL);
+ if(!rc->active_entries)
+ goto fail_malloc_active_entries;
+ memset(rc->active_entries, 0, nr_areas * sizeof(int));
+ rc->active_pages = (int*)kmalloc(nr_areas * sizeof(int), GFP_KERNEL);
+ if(!rc->active_pages)
+ goto fail_malloc_active_pages;
+ memset(rc->active_pages, 0, nr_areas * sizeof(int));
+ if((mode == ALL_AREAS) && (pages_per_area != 0)){
+ rc->areas = debug_areas_alloc(pages_per_area, nr_areas);
+ if(!rc->areas)
+ goto fail_malloc_areas;
+ } else {
+ rc->areas = NULL;
}
/* initialize members */
spin_lock_init(&rc->lock);
- rc->page_order = page_order;
- rc->nr_areas = nr_areas;
- rc->active_area = 0;
- rc->level = DEBUG_DEFAULT_LEVEL;
- rc->buf_size = buf_size;
- rc->entry_size = sizeof(debug_entry_t) + buf_size;
- strlcpy(rc->name, name, sizeof(rc->name));
+ rc->pages_per_area = pages_per_area;
+ rc->nr_areas = nr_areas;
+ rc->active_area = 0;
+ rc->level = level;
+ rc->buf_size = buf_size;
+ rc->entry_size = sizeof(debug_entry_t) + buf_size;
+ strlcpy(rc->name, name, sizeof(rc->name)-1);
memset(rc->views, 0, DEBUG_MAX_VIEWS * sizeof(struct debug_view *));
-#ifdef CONFIG_PROC_FS
- memset(rc->proc_entries, 0 ,DEBUG_MAX_VIEWS *
- sizeof(struct proc_dir_entry*));
-#endif /* CONFIG_PROC_FS */
+ memset(rc->debugfs_entries, 0 ,DEBUG_MAX_VIEWS *
+ sizeof(struct dentry*));
atomic_set(&(rc->ref_count), 0);
return rc;
-fail_malloc_areas2:
- kfree(rc->areas);
fail_malloc_areas:
- kfree(rc->active_entry);
-fail_malloc_active_entry:
+ kfree(rc->active_pages);
+fail_malloc_active_pages:
+ kfree(rc->active_entries);
+fail_malloc_active_entries:
kfree(rc);
fail_malloc_rc:
return NULL;
}
/*
- * debug_info_free
- * - free memory debug-info
+ * debug_areas_free
+ * - free all debug areas
*/
-static void debug_info_free(debug_info_t* db_info){
- int i;
+static void
+debug_areas_free(debug_info_t* db_info)
+{
+ int i,j;
+
+ if(!db_info->areas)
+ return;
for (i = 0; i < db_info->nr_areas; i++) {
- free_pages((unsigned long) db_info->areas[i],
- db_info->page_order);
+ for(j = 0; j < db_info->pages_per_area; j++) {
+ kfree(db_info->areas[i][j]);
+ }
+ kfree(db_info->areas[i]);
}
kfree(db_info->areas);
- kfree(db_info->active_entry);
+ db_info->areas = NULL;
+}
+
+/*
+ * debug_info_free
+ * - free memory debug-info
+ */
+
+static void
+debug_info_free(debug_info_t* db_info){
+ debug_areas_free(db_info);
+ kfree(db_info->active_entries);
+ kfree(db_info->active_pages);
kfree(db_info);
}
@@ -249,21 +332,22 @@ static void debug_info_free(debug_info_t* db_info){
* - create new debug-info
*/
-static debug_info_t* debug_info_create(char *name, int page_order,
- int nr_areas, int buf_size)
+static debug_info_t*
+debug_info_create(char *name, int pages_per_area, int nr_areas, int buf_size)
{
debug_info_t* rc;
- rc = debug_info_alloc(name, page_order, nr_areas, buf_size);
+ rc = debug_info_alloc(name, pages_per_area, nr_areas, buf_size,
+ DEBUG_DEFAULT_LEVEL, ALL_AREAS);
if(!rc)
goto out;
-
- /* create proc rood directory */
- rc->proc_root_entry = proc_mkdir(rc->name, debug_proc_root_entry);
+ /* create root directory */
+ rc->debugfs_root_entry = debugfs_create_dir(rc->name,
+ debug_debugfs_root_entry);
/* append new element to linked list */
- if (debug_area_first == NULL) {
+ if (!debug_area_first) {
/* first element in list */
debug_area_first = rc;
rc->prev = NULL;
@@ -285,17 +369,21 @@ out:
* - copy debug-info
*/
-static debug_info_t* debug_info_copy(debug_info_t* in)
+static debug_info_t*
+debug_info_copy(debug_info_t* in, int mode)
{
- int i;
+ int i,j;
debug_info_t* rc;
- rc = debug_info_alloc(in->name, in->page_order,
- in->nr_areas, in->buf_size);
- if(!rc)
+
+ rc = debug_info_alloc(in->name, in->pages_per_area, in->nr_areas,
+ in->buf_size, in->level, mode);
+ if(!rc || (mode == NO_AREAS))
goto out;
for(i = 0; i < in->nr_areas; i++){
- memcpy(rc->areas[i],in->areas[i], PAGE_SIZE << in->page_order);
+ for(j = 0; j < in->pages_per_area; j++) {
+ memcpy(rc->areas[i][j], in->areas[i][j],PAGE_SIZE);
+ }
}
out:
return rc;
@@ -306,7 +394,8 @@ out:
* - increments reference count for debug-info
*/
-static void debug_info_get(debug_info_t * db_info)
+static void
+debug_info_get(debug_info_t * db_info)
{
if (db_info)
atomic_inc(&db_info->ref_count);
@@ -317,29 +406,20 @@ static void debug_info_get(debug_info_t * db_info)
* - decreases reference count for debug-info and frees it if necessary
*/
-static void debug_info_put(debug_info_t *db_info)
+static void
+debug_info_put(debug_info_t *db_info)
{
int i;
if (!db_info)
return;
if (atomic_dec_and_test(&db_info->ref_count)) {
-#ifdef DEBUG
- printk(KERN_INFO "debug: freeing debug area %p (%s)\n",
- db_info, db_info->name);
-#endif
for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
- if (db_info->views[i] == NULL)
+ if (!db_info->views[i])
continue;
-#ifdef CONFIG_PROC_FS
- remove_proc_entry(db_info->proc_entries[i]->name,
- db_info->proc_root_entry);
-#endif
+ debugfs_remove(db_info->debugfs_entries[i]);
}
-#ifdef CONFIG_PROC_FS
- remove_proc_entry(db_info->proc_root_entry->name,
- debug_proc_root_entry);
-#endif
+ debugfs_remove(db_info->debugfs_root_entry);
if(db_info == debug_area_first)
debug_area_first = db_info->next;
if(db_info == debug_area_last)
@@ -355,9 +435,9 @@ static void debug_info_put(debug_info_t *db_info)
* - format one debug entry and return size of formated data
*/
-static int debug_format_entry(file_private_info_t *p_info)
+static int
+debug_format_entry(file_private_info_t *p_info)
{
- debug_info_t *id_org = p_info->debug_info_org;
debug_info_t *id_snap = p_info->debug_info_snap;
struct debug_view *view = p_info->view;
debug_entry_t *act_entry;
@@ -365,22 +445,23 @@ static int debug_format_entry(file_private_info_t *p_info)
if(p_info->act_entry == DEBUG_PROLOG_ENTRY){
/* print prolog */
if (view->prolog_proc)
- len += view->prolog_proc(id_org, view,p_info->temp_buf);
+ len += view->prolog_proc(id_snap,view,p_info->temp_buf);
goto out;
}
-
- act_entry = (debug_entry_t *) ((char*)id_snap->areas[p_info->act_area] +
- p_info->act_entry);
+ if (!id_snap->areas) /* this is true, if we have a prolog only view */
+ goto out; /* or if 'pages_per_area' is 0 */
+ act_entry = (debug_entry_t *) ((char*)id_snap->areas[p_info->act_area]
+ [p_info->act_page] + p_info->act_entry);
if (act_entry->id.stck == 0LL)
goto out; /* empty entry */
if (view->header_proc)
- len += view->header_proc(id_org, view, p_info->act_area,
+ len += view->header_proc(id_snap, view, p_info->act_area,
act_entry, p_info->temp_buf + len);
if (view->format_proc)
- len += view->format_proc(id_org, view, p_info->temp_buf + len,
+ len += view->format_proc(id_snap, view, p_info->temp_buf + len,
DEBUG_DATA(act_entry));
- out:
+out:
return len;
}
@@ -389,20 +470,30 @@ static int debug_format_entry(file_private_info_t *p_info)
* - goto next entry in p_info
*/
-extern inline int debug_next_entry(file_private_info_t *p_info)
+extern inline int
+debug_next_entry(file_private_info_t *p_info)
{
- debug_info_t *id = p_info->debug_info_snap;
+ debug_info_t *id;
+
+ id = p_info->debug_info_snap;
if(p_info->act_entry == DEBUG_PROLOG_ENTRY){
p_info->act_entry = 0;
+ p_info->act_page = 0;
goto out;
}
- if ((p_info->act_entry += id->entry_size)
- > ((PAGE_SIZE << (id->page_order))
- - id->entry_size)){
-
- /* next area */
+ if(!id->areas)
+ return 1;
+ p_info->act_entry += id->entry_size;
+ /* switch to next page, if we reached the end of the page */
+ if (p_info->act_entry > (PAGE_SIZE - id->entry_size)){
+ /* next page */
p_info->act_entry = 0;
- p_info->act_area++;
+ p_info->act_page += 1;
+ if((p_info->act_page % id->pages_per_area) == 0) {
+ /* next area */
+ p_info->act_area++;
+ p_info->act_page=0;
+ }
if(p_info->act_area >= id->nr_areas)
return 1;
}
@@ -416,13 +507,14 @@ out:
* - copies formated debug entries to the user buffer
*/
-static ssize_t debug_output(struct file *file, /* file descriptor */
- char __user *user_buf, /* user buffer */
- size_t len, /* length of buffer */
- loff_t *offset) /* offset in the file */
+static ssize_t
+debug_output(struct file *file, /* file descriptor */
+ char __user *user_buf, /* user buffer */
+ size_t len, /* length of buffer */
+ loff_t *offset) /* offset in the file */
{
size_t count = 0;
- size_t entry_offset, size = 0;
+ size_t entry_offset;
file_private_info_t *p_info;
p_info = ((file_private_info_t *) file->private_data);
@@ -430,27 +522,33 @@ static ssize_t debug_output(struct file *file, /* file descriptor */
return -EPIPE;
if(p_info->act_area >= p_info->debug_info_snap->nr_areas)
return 0;
-
entry_offset = p_info->act_entry_offset;
-
while(count < len){
- size = debug_format_entry(p_info);
- size = min((len - count), (size - entry_offset));
-
- if(size){
- if (copy_to_user(user_buf + count,
- p_info->temp_buf + entry_offset, size))
- return -EFAULT;
+ int formatted_line_size;
+ int formatted_line_residue;
+ int user_buf_residue;
+ size_t copy_size;
+
+ formatted_line_size = debug_format_entry(p_info);
+ formatted_line_residue = formatted_line_size - entry_offset;
+ user_buf_residue = len-count;
+ copy_size = min(user_buf_residue, formatted_line_residue);
+ if(copy_size){
+ if (copy_to_user(user_buf + count, p_info->temp_buf
+ + entry_offset, copy_size))
+ return -EFAULT;
+ count += copy_size;
+ entry_offset += copy_size;
}
- count += size;
- entry_offset = 0;
- if(count != len)
- if(debug_next_entry(p_info))
+ if(copy_size == formatted_line_residue){
+ entry_offset = 0;
+ if(debug_next_entry(p_info))
goto out;
+ }
}
out:
p_info->offset = *offset + count;
- p_info->act_entry_offset = size;
+ p_info->act_entry_offset = entry_offset;
*offset = p_info->offset;
return count;
}
@@ -461,9 +559,9 @@ out:
* - calls input function of view
*/
-static ssize_t debug_input(struct file *file,
- const char __user *user_buf, size_t length,
- loff_t *offset)
+static ssize_t
+debug_input(struct file *file, const char __user *user_buf, size_t length,
+ loff_t *offset)
{
int rc = 0;
file_private_info_t *p_info;
@@ -487,26 +585,23 @@ static ssize_t debug_input(struct file *file,
* handle
*/
-static int debug_open(struct inode *inode, struct file *file)
+static int
+debug_open(struct inode *inode, struct file *file)
{
int i = 0, rc = 0;
file_private_info_t *p_info;
debug_info_t *debug_info, *debug_info_snapshot;
-#ifdef DEBUG
- printk("debug_open\n");
-#endif
down(&debug_lock);
/* find debug log and view */
-
debug_info = debug_area_first;
while(debug_info != NULL){
for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
- if (debug_info->views[i] == NULL)
+ if (!debug_info->views[i])
continue;
- else if (debug_info->proc_entries[i] ==
- PDE(file->f_dentry->d_inode)) {
+ else if (debug_info->debugfs_entries[i] ==
+ file->f_dentry) {
goto found; /* found view ! */
}
}
@@ -516,41 +611,42 @@ static int debug_open(struct inode *inode, struct file *file)
rc = -EINVAL;
goto out;
- found:
+found:
- /* make snapshot of current debug areas to get it consistent */
+ /* Make snapshot of current debug areas to get it consistent. */
+ /* To copy all the areas is only needed, if we have a view which */
+ /* formats the debug areas. */
- debug_info_snapshot = debug_info_copy(debug_info);
+ if(!debug_info->views[i]->format_proc &&
+ !debug_info->views[i]->header_proc){
+ debug_info_snapshot = debug_info_copy(debug_info, NO_AREAS);
+ } else {
+ debug_info_snapshot = debug_info_copy(debug_info, ALL_AREAS);
+ }
if(!debug_info_snapshot){
-#ifdef DEBUG
- printk(KERN_ERR "debug_open: debug_info_copy failed (out of mem)\n");
-#endif
rc = -ENOMEM;
goto out;
}
-
- if ((file->private_data =
- kmalloc(sizeof(file_private_info_t), GFP_ATOMIC)) == 0) {
-#ifdef DEBUG
- printk(KERN_ERR "debug_open: kmalloc failed\n");
-#endif
- debug_info_free(debug_info_snapshot);
+ p_info = (file_private_info_t *) kmalloc(sizeof(file_private_info_t),
+ GFP_KERNEL);
+ if(!p_info){
+ if(debug_info_snapshot)
+ debug_info_free(debug_info_snapshot);
rc = -ENOMEM;
goto out;
}
- p_info = (file_private_info_t *) file->private_data;
p_info->offset = 0;
p_info->debug_info_snap = debug_info_snapshot;
p_info->debug_info_org = debug_info;
p_info->view = debug_info->views[i];
p_info->act_area = 0;
+ p_info->act_page = 0;
p_info->act_entry = DEBUG_PROLOG_ENTRY;
p_info->act_entry_offset = 0;
-
+ file->private_data = p_info;
debug_info_get(debug_info);
-
- out:
+out:
up(&debug_lock);
return rc;
}
@@ -561,14 +657,13 @@ static int debug_open(struct inode *inode, struct file *file)
* - deletes private_data area of the file handle
*/
-static int debug_close(struct inode *inode, struct file *file)
+static int
+debug_close(struct inode *inode, struct file *file)
{
file_private_info_t *p_info;
-#ifdef DEBUG
- printk("debug_close\n");
-#endif
p_info = (file_private_info_t *) file->private_data;
- debug_info_free(p_info->debug_info_snap);
+ if(p_info->debug_info_snap)
+ debug_info_free(p_info->debug_info_snap);
debug_info_put(p_info->debug_info_org);
kfree(file->private_data);
return 0; /* success */
@@ -580,8 +675,8 @@ static int debug_close(struct inode *inode, struct file *file)
* - returns handle for debug area
*/
-debug_info_t *debug_register
- (char *name, int page_order, int nr_areas, int buf_size)
+debug_info_t*
+debug_register (char *name, int pages_per_area, int nr_areas, int buf_size)
{
debug_info_t *rc = NULL;
@@ -591,18 +686,14 @@ debug_info_t *debug_register
/* create new debug_info */
- rc = debug_info_create(name, page_order, nr_areas, buf_size);
+ rc = debug_info_create(name, pages_per_area, nr_areas, buf_size);
if(!rc)
goto out;
debug_register_view(rc, &debug_level_view);
debug_register_view(rc, &debug_flush_view);
-#ifdef DEBUG
- printk(KERN_INFO
- "debug: reserved %d areas of %d pages for debugging %s\n",
- nr_areas, 1 << page_order, rc->name);
-#endif
- out:
- if (rc == NULL){
+ debug_register_view(rc, &debug_pages_view);
+out:
+ if (!rc){
printk(KERN_ERR "debug: debug_register failed for %s\n",name);
}
up(&debug_lock);
@@ -614,27 +705,65 @@ debug_info_t *debug_register
* - give back debug area
*/
-void debug_unregister(debug_info_t * id)
+void
+debug_unregister(debug_info_t * id)
{
if (!id)
goto out;
down(&debug_lock);
-#ifdef DEBUG
- printk(KERN_INFO "debug: unregistering %s\n", id->name);
-#endif
debug_info_put(id);
up(&debug_lock);
- out:
+out:
return;
}
/*
+ * debug_set_size:
+ * - set area size (number of pages) and number of areas
+ */
+static int
+debug_set_size(debug_info_t* id, int nr_areas, int pages_per_area)
+{
+ unsigned long flags;
+ debug_entry_t *** new_areas;
+ int rc=0;
+
+ if(!id || (nr_areas <= 0) || (pages_per_area < 0))
+ return -EINVAL;
+ if(pages_per_area > 0){
+ new_areas = debug_areas_alloc(pages_per_area, nr_areas);
+ if(!new_areas) {
+ printk(KERN_WARNING "debug: could not allocate memory "\
+ "for pagenumber: %i\n",pages_per_area);
+ rc = -ENOMEM;
+ goto out;
+ }
+ } else {
+ new_areas = NULL;
+ }
+ spin_lock_irqsave(&id->lock,flags);
+ debug_areas_free(id);
+ id->areas = new_areas;
+ id->nr_areas = nr_areas;
+ id->pages_per_area = pages_per_area;
+ id->active_area = 0;
+ memset(id->active_entries,0,sizeof(int)*id->nr_areas);
+ memset(id->active_pages, 0, sizeof(int)*id->nr_areas);
+ spin_unlock_irqrestore(&id->lock,flags);
+ printk(KERN_INFO "debug: %s: set new size (%i pages)\n"\
+ ,id->name, pages_per_area);
+out:
+ return rc;
+}
+
+/*
* debug_set_level:
* - set actual debug level
*/
-void debug_set_level(debug_info_t* id, int new_level)
+void
+debug_set_level(debug_info_t* id, int new_level)
{
unsigned long flags;
if(!id)
@@ -649,10 +778,6 @@ void debug_set_level(debug_info_t* id, int new_level)
id->name, new_level, 0, DEBUG_MAX_LEVEL);
} else {
id->level = new_level;
-#ifdef DEBUG
- printk(KERN_INFO
- "debug: %s: new level %i\n",id->name,id->level);
-#endif
}
spin_unlock_irqrestore(&id->lock,flags);
}
@@ -663,11 +788,16 @@ void debug_set_level(debug_info_t* id, int new_level)
* - set active entry to next in the ring buffer
*/
-extern inline void proceed_active_entry(debug_info_t * id)
+extern inline void
+proceed_active_entry(debug_info_t * id)
{
- if ((id->active_entry[id->active_area] += id->entry_size)
- > ((PAGE_SIZE << (id->page_order)) - id->entry_size))
- id->active_entry[id->active_area] = 0;
+ if ((id->active_entries[id->active_area] += id->entry_size)
+ > (PAGE_SIZE - id->entry_size)){
+ id->active_entries[id->active_area] = 0;
+ id->active_pages[id->active_area] =
+ (id->active_pages[id->active_area] + 1) %
+ id->pages_per_area;
+ }
}
/*
@@ -675,7 +805,8 @@ extern inline void proceed_active_entry(debug_info_t * id)
* - set active area to next in the ring buffer
*/
-extern inline void proceed_active_area(debug_info_t * id)
+extern inline void
+proceed_active_area(debug_info_t * id)
{
id->active_area++;
id->active_area = id->active_area % id->nr_areas;
@@ -685,10 +816,12 @@ extern inline void proceed_active_area(debug_info_t * id)
* get_active_entry:
*/
-extern inline debug_entry_t *get_active_entry(debug_info_t * id)
+extern inline debug_entry_t*
+get_active_entry(debug_info_t * id)
{
- return (debug_entry_t *) ((char *) id->areas[id->active_area] +
- id->active_entry[id->active_area]);
+ return (debug_entry_t *) (((char *) id->areas[id->active_area]
+ [id->active_pages[id->active_area]]) +
+ id->active_entries[id->active_area]);
}
/*
@@ -696,8 +829,9 @@ extern inline debug_entry_t *get_active_entry(debug_info_t * id)
* - set timestamp, caller address, cpu number etc.
*/
-extern inline void debug_finish_entry(debug_info_t * id, debug_entry_t* active,
- int level, int exception)
+extern inline void
+debug_finish_entry(debug_info_t * id, debug_entry_t* active, int level,
+ int exception)
{
STCK(active->id.stck);
active->id.fields.cpuid = smp_processor_id();
@@ -721,7 +855,8 @@ static int debug_active=1;
* always allow read, allow write only if debug_stoppable is set or
* if debug_active is already off
*/
-static int s390dbf_procactive(ctl_table *table, int write, struct file *filp,
+static int
+s390dbf_procactive(ctl_table *table, int write, struct file *filp,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
if (!write || debug_stoppable || !debug_active)
@@ -766,7 +901,8 @@ static struct ctl_table s390dbf_dir_table[] = {
struct ctl_table_header *s390dbf_sysctl_header;
-void debug_stop_all(void)
+void
+debug_stop_all(void)
{
if (debug_stoppable)
debug_active = 0;
@@ -778,13 +914,13 @@ void debug_stop_all(void)
* - write debug entry with given size
*/
-debug_entry_t *debug_event_common(debug_info_t * id, int level, const void *buf,
- int len)
+debug_entry_t*
+debug_event_common(debug_info_t * id, int level, const void *buf, int len)
{
unsigned long flags;
debug_entry_t *active;
- if (!debug_active)
+ if (!debug_active || !id->areas)
return NULL;
spin_lock_irqsave(&id->lock, flags);
active = get_active_entry(id);
@@ -801,13 +937,13 @@ debug_entry_t *debug_event_common(debug_info_t * id, int level, const void *buf,
* - write debug entry with given size and switch to next debug area
*/
-debug_entry_t *debug_exception_common(debug_info_t * id, int level,
- const void *buf, int len)
+debug_entry_t
+*debug_exception_common(debug_info_t * id, int level, const void *buf, int len)
{
unsigned long flags;
debug_entry_t *active;
- if (!debug_active)
+ if (!debug_active || !id->areas)
return NULL;
spin_lock_irqsave(&id->lock, flags);
active = get_active_entry(id);
@@ -823,7 +959,8 @@ debug_entry_t *debug_exception_common(debug_info_t * id, int level,
* counts arguments in format string for sprintf view
*/
-extern inline int debug_count_numargs(char *string)
+extern inline int
+debug_count_numargs(char *string)
{
int numargs=0;
@@ -838,8 +975,8 @@ extern inline int debug_count_numargs(char *string)
* debug_sprintf_event:
*/
-debug_entry_t *debug_sprintf_event(debug_info_t* id,
- int level,char *string,...)
+debug_entry_t*
+debug_sprintf_event(debug_info_t* id, int level,char *string,...)
{
va_list ap;
int numargs,idx;
@@ -849,7 +986,7 @@ debug_entry_t *debug_sprintf_event(debug_info_t* id,
if((!id) || (level > id->level))
return NULL;
- if (!debug_active)
+ if (!debug_active || !id->areas)
return NULL;
numargs=debug_count_numargs(string);
@@ -871,8 +1008,8 @@ debug_entry_t *debug_sprintf_event(debug_info_t* id,
* debug_sprintf_exception:
*/
-debug_entry_t *debug_sprintf_exception(debug_info_t* id,
- int level,char *string,...)
+debug_entry_t*
+debug_sprintf_exception(debug_info_t* id, int level,char *string,...)
{
va_list ap;
int numargs,idx;
@@ -882,7 +1019,7 @@ debug_entry_t *debug_sprintf_exception(debug_info_t* id,
if((!id) || (level > id->level))
return NULL;
- if (!debug_active)
+ if (!debug_active || !id->areas)
return NULL;
numargs=debug_count_numargs(string);
@@ -906,15 +1043,14 @@ debug_entry_t *debug_sprintf_exception(debug_info_t* id,
* - is called exactly once to initialize the debug feature
*/
-static int __init debug_init(void)
+static int
+__init debug_init(void)
{
int rc = 0;
s390dbf_sysctl_header = register_sysctl_table(s390dbf_dir_table, 1);
down(&debug_lock);
-#ifdef CONFIG_PROC_FS
- debug_proc_root_entry = proc_mkdir(DEBUG_DIR_ROOT, NULL);
-#endif /* CONFIG_PROC_FS */
+ debug_debugfs_root_entry = debugfs_create_dir(DEBUG_DIR_ROOT,NULL);
printk(KERN_INFO "debug: Initialization complete\n");
initialized = 1;
up(&debug_lock);
@@ -926,13 +1062,14 @@ static int __init debug_init(void)
* debug_register_view:
*/
-int debug_register_view(debug_info_t * id, struct debug_view *view)
+int
+debug_register_view(debug_info_t * id, struct debug_view *view)
{
int rc = 0;
int i;
unsigned long flags;
mode_t mode = S_IFREG;
- struct proc_dir_entry *pde;
+ struct dentry *pde;
if (!id)
goto out;
@@ -940,16 +1077,17 @@ int debug_register_view(debug_info_t * id, struct debug_view *view)
mode |= S_IRUSR;
if (view->input_proc)
mode |= S_IWUSR;
- pde = create_proc_entry(view->name, mode, id->proc_root_entry);
+ pde = debugfs_create_file(view->name, mode, id->debugfs_root_entry,
+ NULL, &debug_file_ops);
if (!pde){
- printk(KERN_WARNING "debug: create_proc_entry() failed! Cannot register view %s/%s\n", id->name,view->name);
+ printk(KERN_WARNING "debug: debugfs_create_file() failed!"\
+ " Cannot register view %s/%s\n", id->name,view->name);
rc = -1;
goto out;
}
-
spin_lock_irqsave(&id->lock, flags);
for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
- if (id->views[i] == NULL)
+ if (!id->views[i])
break;
}
if (i == DEBUG_MAX_VIEWS) {
@@ -957,16 +1095,14 @@ int debug_register_view(debug_info_t * id, struct debug_view *view)
id->name,view->name);
printk(KERN_WARNING
"debug: maximum number of views reached (%i)!\n", i);
- remove_proc_entry(pde->name, id->proc_root_entry);
+ debugfs_remove(pde);
rc = -1;
- }
- else {
+ } else {
id->views[i] = view;
- pde->proc_fops = &debug_file_ops;
- id->proc_entries[i] = pde;
+ id->debugfs_entries[i] = pde;
}
spin_unlock_irqrestore(&id->lock, flags);
- out:
+out:
return rc;
}
@@ -974,7 +1110,8 @@ int debug_register_view(debug_info_t * id, struct debug_view *view)
* debug_unregister_view:
*/
-int debug_unregister_view(debug_info_t * id, struct debug_view *view)
+int
+debug_unregister_view(debug_info_t * id, struct debug_view *view)
{
int rc = 0;
int i;
@@ -990,15 +1127,46 @@ int debug_unregister_view(debug_info_t * id, struct debug_view *view)
if (i == DEBUG_MAX_VIEWS)
rc = -1;
else {
-#ifdef CONFIG_PROC_FS
- remove_proc_entry(id->proc_entries[i]->name,
- id->proc_root_entry);
-#endif
+ debugfs_remove(id->debugfs_entries[i]);
id->views[i] = NULL;
rc = 0;
}
spin_unlock_irqrestore(&id->lock, flags);
- out:
+out:
+ return rc;
+}
+
+static inline char *
+debug_get_user_string(const char __user *user_buf, size_t user_len)
+{
+ char* buffer;
+
+ buffer = kmalloc(user_len + 1, GFP_KERNEL);
+ if (!buffer)
+ return ERR_PTR(-ENOMEM);
+ if (copy_from_user(buffer, user_buf, user_len) != 0) {
+ kfree(buffer);
+ return ERR_PTR(-EFAULT);
+ }
+ /* got the string, now strip linefeed. */
+ if (buffer[user_len - 1] == '\n')
+ buffer[user_len - 1] = 0;
+ else
+ buffer[user_len] = 0;
+ return buffer;
+}
+
+static inline int
+debug_get_uint(char *buf)
+{
+ int rc;
+
+ for(; isspace(*buf); buf++);
+ rc = simple_strtoul(buf, &buf, 10);
+ if(*buf){
+ printk("debug: no integer specified!\n");
+ rc = -EINVAL;
+ }
return rc;
}
@@ -1011,13 +1179,69 @@ int debug_unregister_view(debug_info_t * id, struct debug_view *view)
* prints out actual debug level
*/
-static int debug_prolog_level_fn(debug_info_t * id,
+static int
+debug_prolog_pages_fn(debug_info_t * id,
struct debug_view *view, char *out_buf)
{
+ return sprintf(out_buf, "%i\n", id->pages_per_area);
+}
+
+/*
+ * reads new size (number of pages per debug area)
+ */
+
+static int
+debug_input_pages_fn(debug_info_t * id, struct debug_view *view,
+ struct file *file, const char __user *user_buf,
+ size_t user_len, loff_t * offset)
+{
+ char *str;
+ int rc,new_pages;
+
+ if (user_len > 0x10000)
+ user_len = 0x10000;
+ if (*offset != 0){
+ rc = -EPIPE;
+ goto out;
+ }
+ str = debug_get_user_string(user_buf,user_len);
+ if(IS_ERR(str)){
+ rc = PTR_ERR(str);
+ goto out;
+ }
+ new_pages = debug_get_uint(str);
+ if(new_pages < 0){
+ rc = -EINVAL;
+ goto free_str;
+ }
+ rc = debug_set_size(id,id->nr_areas, new_pages);
+ if(rc != 0){
+ rc = -EINVAL;
+ goto free_str;
+ }
+ rc = user_len;
+free_str:
+ kfree(str);
+out:
+ *offset += user_len;
+ return rc; /* number of input characters */
+}
+
+/*
+ * prints out actual debug level
+ */
+
+static int
+debug_prolog_level_fn(debug_info_t * id, struct debug_view *view, char *out_buf)
+{
int rc = 0;
- if(id->level == -1) rc = sprintf(out_buf,"-\n");
- else rc = sprintf(out_buf, "%i\n", id->level);
+ if(id->level == DEBUG_OFF_LEVEL) {
+ rc = sprintf(out_buf,"-\n");
+ }
+ else {
+ rc = sprintf(out_buf, "%i\n", id->level);
+ }
return rc;
}
@@ -1025,30 +1249,43 @@ static int debug_prolog_level_fn(debug_info_t * id,
* reads new debug level
*/
-static int debug_input_level_fn(debug_info_t * id, struct debug_view *view,
- struct file *file, const char __user *user_buf,
- size_t in_buf_size, loff_t * offset)
+static int
+debug_input_level_fn(debug_info_t * id, struct debug_view *view,
+ struct file *file, const char __user *user_buf,
+ size_t user_len, loff_t * offset)
{
- char input_buf[1];
- int rc = in_buf_size;
+ char *str;
+ int rc,new_level;
- if (*offset != 0)
+ if (user_len > 0x10000)
+ user_len = 0x10000;
+ if (*offset != 0){
+ rc = -EPIPE;
goto out;
- if (copy_from_user(input_buf, user_buf, 1)){
- rc = -EFAULT;
+ }
+ str = debug_get_user_string(user_buf,user_len);
+ if(IS_ERR(str)){
+ rc = PTR_ERR(str);
goto out;
}
- if (isdigit(input_buf[0])) {
- int new_level = ((int) input_buf[0] - (int) '0');
- debug_set_level(id, new_level);
- } else if(input_buf[0] == '-') {
+ if(str[0] == '-'){
debug_set_level(id, DEBUG_OFF_LEVEL);
+ rc = user_len;
+ goto free_str;
} else {
- printk(KERN_INFO "debug: level `%c` is not valid\n",
- input_buf[0]);
+ new_level = debug_get_uint(str);
}
- out:
- *offset += in_buf_size;
+ if(new_level < 0) {
+ printk(KERN_INFO "debug: level `%s` is not valid\n", str);
+ rc = -EINVAL;
+ } else {
+ debug_set_level(id, new_level);
+ rc = user_len;
+ }
+free_str:
+ kfree(str);
+out:
+ *offset += user_len;
return rc; /* number of input characters */
}
@@ -1057,29 +1294,36 @@ static int debug_input_level_fn(debug_info_t * id, struct debug_view *view,
* flushes debug areas
*/
-void debug_flush(debug_info_t* id, int area)
+void
+debug_flush(debug_info_t* id, int area)
{
unsigned long flags;
- int i;
+ int i,j;
- if(!id)
+ if(!id || !id->areas)
return;
spin_lock_irqsave(&id->lock,flags);
if(area == DEBUG_FLUSH_ALL){
id->active_area = 0;
- memset(id->active_entry, 0, id->nr_areas * sizeof(int));
- for (i = 0; i < id->nr_areas; i++)
- memset(id->areas[i], 0, PAGE_SIZE << id->page_order);
+ memset(id->active_entries, 0, id->nr_areas * sizeof(int));
+ for (i = 0; i < id->nr_areas; i++) {
+ id->active_pages[i] = 0;
+ for(j = 0; j < id->pages_per_area; j++) {
+ memset(id->areas[i][j], 0, PAGE_SIZE);
+ }
+ }
printk(KERN_INFO "debug: %s: all areas flushed\n",id->name);
} else if(area >= 0 && area < id->nr_areas) {
- id->active_entry[area] = 0;
- memset(id->areas[area], 0, PAGE_SIZE << id->page_order);
- printk(KERN_INFO
- "debug: %s: area %i has been flushed\n",
+ id->active_entries[area] = 0;
+ id->active_pages[area] = 0;
+ for(i = 0; i < id->pages_per_area; i++) {
+ memset(id->areas[area][i],0,PAGE_SIZE);
+ }
+ printk(KERN_INFO "debug: %s: area %i has been flushed\n",
id->name, area);
} else {
printk(KERN_INFO
- "debug: %s: area %i cannot be flushed (range: %i - %i)\n",
+ "debug: %s: area %i cannot be flushed (range: %i - %i)\n",
id->name, area, 0, id->nr_areas-1);
}
spin_unlock_irqrestore(&id->lock,flags);
@@ -1089,15 +1333,20 @@ void debug_flush(debug_info_t* id, int area)
* view function: flushes debug areas
*/
-static int debug_input_flush_fn(debug_info_t * id, struct debug_view *view,
- struct file *file, const char __user *user_buf,
- size_t in_buf_size, loff_t * offset)
+static int
+debug_input_flush_fn(debug_info_t * id, struct debug_view *view,
+ struct file *file, const char __user *user_buf,
+ size_t user_len, loff_t * offset)
{
char input_buf[1];
- int rc = in_buf_size;
-
- if (*offset != 0)
+ int rc = user_len;
+
+ if (user_len > 0x10000)
+ user_len = 0x10000;
+ if (*offset != 0){
+ rc = -EPIPE;
goto out;
+ }
if (copy_from_user(input_buf, user_buf, 1)){
rc = -EFAULT;
goto out;
@@ -1114,8 +1363,8 @@ static int debug_input_flush_fn(debug_info_t * id, struct debug_view *view,
printk(KERN_INFO "debug: area `%c` is not valid\n", input_buf[0]);
- out:
- *offset += in_buf_size;
+out:
+ *offset += user_len;
return rc; /* number of input characters */
}
@@ -1123,8 +1372,9 @@ static int debug_input_flush_fn(debug_info_t * id, struct debug_view *view,
* prints debug header in raw format
*/
-int debug_raw_header_fn(debug_info_t * id, struct debug_view *view,
- int area, debug_entry_t * entry, char *out_buf)
+static int
+debug_raw_header_fn(debug_info_t * id, struct debug_view *view,
+ int area, debug_entry_t * entry, char *out_buf)
{
int rc;
@@ -1137,7 +1387,8 @@ int debug_raw_header_fn(debug_info_t * id, struct debug_view *view,
* prints debug data in raw format
*/
-static int debug_raw_format_fn(debug_info_t * id, struct debug_view *view,
+static int
+debug_raw_format_fn(debug_info_t * id, struct debug_view *view,
char *out_buf, const char *in_buf)
{
int rc;
@@ -1151,8 +1402,9 @@ static int debug_raw_format_fn(debug_info_t * id, struct debug_view *view,
* prints debug data in hex/ascii format
*/
-static int debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view,
- char *out_buf, const char *in_buf)
+static int
+debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view,
+ char *out_buf, const char *in_buf)
{
int i, rc = 0;
@@ -1176,7 +1428,8 @@ static int debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view,
* prints header for debug entry
*/
-int debug_dflt_header_fn(debug_info_t * id, struct debug_view *view,
+int
+debug_dflt_header_fn(debug_info_t * id, struct debug_view *view,
int area, debug_entry_t * entry, char *out_buf)
{
struct timeval time_val;
@@ -1210,8 +1463,9 @@ int debug_dflt_header_fn(debug_info_t * id, struct debug_view *view,
#define DEBUG_SPRINTF_MAX_ARGS 10
-int debug_sprintf_format_fn(debug_info_t * id, struct debug_view *view,
- char *out_buf, debug_sprintf_entry_t *curr_event)
+static int
+debug_sprintf_format_fn(debug_info_t * id, struct debug_view *view,
+ char *out_buf, debug_sprintf_entry_t *curr_event)
{
int num_longs, num_used_args = 0,i, rc = 0;
int index[DEBUG_SPRINTF_MAX_ARGS];
@@ -1251,14 +1505,10 @@ out:
/*
* clean up module
*/
-void __exit debug_exit(void)
+void
+__exit debug_exit(void)
{
-#ifdef DEBUG
- printk("debug_cleanup_module: \n");
-#endif
-#ifdef CONFIG_PROC_FS
- remove_proc_entry(debug_proc_root_entry->name, NULL);
-#endif /* CONFIG_PROC_FS */
+ debugfs_remove(debug_debugfs_root_entry);
unregister_sysctl_table(s390dbf_sysctl_header);
return;
}
@@ -1266,7 +1516,7 @@ void __exit debug_exit(void)
/*
* module definitions
*/
-core_initcall(debug_init);
+postcore_initcall(debug_init);
module_exit(debug_exit);
MODULE_LICENSE("GPL");
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index c0e09b33feb..5b262b5d869 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -7,6 +7,7 @@
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
* Hartmut Penner (hp@de.ibm.com),
* Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
+ * Heiko Carstens <heiko.carstens@de.ibm.com>
*/
#include <linux/sys.h>
@@ -49,9 +50,9 @@ SP_ILC = STACK_FRAME_OVERHEAD + __PT_ILC
SP_TRAP = STACK_FRAME_OVERHEAD + __PT_TRAP
SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
-_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
+_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING | \
_TIF_RESTART_SVC | _TIF_SINGLE_STEP )
-_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
+_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
STACK_SIZE = 1 << STACK_SHIFT
@@ -121,7 +122,11 @@ STACK_SIZE = 1 << STACK_SHIFT
bz BASED(stack_overflow)
3:
#endif
-2: s %r15,BASED(.Lc_spsize) # make room for registers & psw
+2:
+ .endm
+
+ .macro CREATE_STACK_FRAME psworg,savearea
+ s %r15,BASED(.Lc_spsize) # make room for registers & psw
mvc SP_PSW(8,%r15),0(%r12) # move user PSW to stack
la %r12,\psworg
st %r2,SP_ORIG_R2(%r15) # store original content of gpr 2
@@ -161,6 +166,13 @@ __switch_to_base:
be __switch_to_noper-__switch_to_base(%r1) # we got away w/o bashing TLB's
lctl %c9,%c11,__THREAD_per(%r3) # Nope we didn't
__switch_to_noper:
+ l %r4,__THREAD_info(%r2) # get thread_info of prev
+ tm __TI_flags+3(%r4),_TIF_MCCK_PENDING # machine check pending?
+ bz __switch_to_no_mcck-__switch_to_base(%r1)
+ ni __TI_flags+3(%r4),255-_TIF_MCCK_PENDING # clear flag in prev
+ l %r4,__THREAD_info(%r3) # get thread_info of next
+ oi __TI_flags+3(%r4),_TIF_MCCK_PENDING # set it in next
+__switch_to_no_mcck:
stm %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
st %r15,__THREAD_ksp(%r2) # store kernel stack to prev->tss.ksp
l %r15,__THREAD_ksp(%r3) # load kernel stack from next->tss.ksp
@@ -185,6 +197,7 @@ system_call:
sysc_saveall:
SAVE_ALL_BASE __LC_SAVE_AREA
SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
+ CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
lh %r7,0x8a # get svc number from lowcore
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
sysc_vtime:
@@ -234,6 +247,8 @@ sysc_work_loop:
# One of the work bits is on. Find out which one.
#
sysc_work:
+ tm __TI_flags+3(%r9),_TIF_MCCK_PENDING
+ bo BASED(sysc_mcck_pending)
tm __TI_flags+3(%r9),_TIF_NEED_RESCHED
bo BASED(sysc_reschedule)
tm __TI_flags+3(%r9),_TIF_SIGPENDING
@@ -253,6 +268,14 @@ sysc_reschedule:
br %r1 # call scheduler
#
+# _TIF_MCCK_PENDING is set, call handler
+#
+sysc_mcck_pending:
+ l %r1,BASED(.Ls390_handle_mcck)
+ la %r14,BASED(sysc_work_loop)
+ br %r1 # TIF bit will be cleared by handler
+
+#
# _TIF_SIGPENDING is set, call do_signal
#
sysc_sigpending:
@@ -430,6 +453,7 @@ pgm_check_handler:
tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
bnz BASED(pgm_per) # got per exception -> special case
SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1
+ CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
bz BASED(pgm_no_vtime)
@@ -468,6 +492,7 @@ pgm_per:
#
pgm_per_std:
SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1
+ CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
bz BASED(pgm_no_vtime2)
@@ -493,6 +518,7 @@ pgm_no_vtime2:
#
pgm_svcper:
SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
+ CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
bz BASED(pgm_no_vtime3)
@@ -521,6 +547,7 @@ io_int_handler:
stck __LC_INT_CLOCK
SAVE_ALL_BASE __LC_SAVE_AREA+16
SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+16,0
+ CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+16
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
bz BASED(io_no_vtime)
@@ -578,9 +605,11 @@ io_work:
lr %r15,%r1
#
# One of the work bits is on. Find out which one.
-# Checked are: _TIF_SIGPENDING and _TIF_NEED_RESCHED
+# Checked are: _TIF_SIGPENDING, _TIF_NEED_RESCHED and _TIF_MCCK_PENDING
#
io_work_loop:
+ tm __TI_flags+3(%r9),_TIF_MCCK_PENDING
+ bo BASED(io_mcck_pending)
tm __TI_flags+3(%r9),_TIF_NEED_RESCHED
bo BASED(io_reschedule)
tm __TI_flags+3(%r9),_TIF_SIGPENDING
@@ -588,6 +617,14 @@ io_work_loop:
b BASED(io_leave)
#
+# _TIF_MCCK_PENDING is set, call handler
+#
+io_mcck_pending:
+ l %r1,BASED(.Ls390_handle_mcck)
+ l %r14,BASED(io_work_loop)
+ br %r1 # TIF bit will be cleared by handler
+
+#
# _TIF_NEED_RESCHED is set, call schedule
#
io_reschedule:
@@ -621,6 +658,7 @@ ext_int_handler:
stck __LC_INT_CLOCK
SAVE_ALL_BASE __LC_SAVE_AREA+16
SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16,0
+ CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
bz BASED(ext_no_vtime)
@@ -642,19 +680,62 @@ ext_no_vtime:
.globl mcck_int_handler
mcck_int_handler:
- STORE_TIMER __LC_ASYNC_ENTER_TIMER
+ spt __LC_CPU_TIMER_SAVE_AREA # revalidate cpu timer
+ lm %r0,%r15,__LC_GPREGS_SAVE_AREA # revalidate gprs
SAVE_ALL_BASE __LC_SAVE_AREA+32
- SAVE_ALL __LC_MCK_OLD_PSW,__LC_SAVE_AREA+32,0
+ la %r12,__LC_MCK_OLD_PSW
+ tm __LC_MCCK_CODE,0x80 # system damage?
+ bo BASED(mcck_int_main) # yes -> rest of mcck code invalid
+ tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid?
+ bo BASED(0f)
+ spt __LC_LAST_UPDATE_TIMER # revalidate cpu timer
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
- tm SP_PSW+1(%r15),0x01 # interrupting from user ?
+ mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
+ mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
+ mvc __LC_LAST_UPDATE_TIMER(8),__LC_EXIT_TIMER
+0: tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid?
+ bno BASED(mcck_no_vtime) # no -> skip cleanup critical
+ tm __LC_MCK_OLD_PSW+1,0x01 # interrupting from user ?
bz BASED(mcck_no_vtime)
UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
mcck_no_vtime:
#endif
+0:
+ tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid?
+ bno BASED(mcck_int_main) # no -> skip cleanup critical
+ tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit
+ bnz BASED(mcck_int_main) # from user -> load async stack
+ clc __LC_MCK_OLD_PSW+4(4),BASED(.Lcritical_end)
+ bhe BASED(mcck_int_main)
+ clc __LC_MCK_OLD_PSW+4(4),BASED(.Lcritical_start)
+ bl BASED(mcck_int_main)
+ l %r14,BASED(.Lcleanup_critical)
+ basr %r14,%r14
+mcck_int_main:
+ l %r14,__LC_PANIC_STACK # are we already on the panic stack?
+ slr %r14,%r15
+ sra %r14,PAGE_SHIFT
+ be BASED(0f)
+ l %r15,__LC_PANIC_STACK # load panic stack
+0: CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+32
+ l %r9,__LC_THREAD_INFO # load pointer to thread_info struct
+ la %r2,SP_PTREGS(%r15) # load pt_regs
l %r1,BASED(.Ls390_mcck)
- basr %r14,%r1 # call machine check handler
+ basr %r14,%r1 # call machine check handler
+ tm SP_PSW+1(%r15),0x01 # returning to user ?
+ bno BASED(mcck_return)
+ l %r1,__LC_KERNEL_STACK # switch to kernel stack
+ s %r1,BASED(.Lc_spsize)
+ mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
+ xc __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
+ lr %r15,%r1
+ stosm __SF_EMPTY(%r15),0x04 # turn dat on
+ tm __TI_flags+3(%r9),_TIF_MCCK_PENDING
+ bno BASED(mcck_return)
+ l %r1,BASED(.Ls390_handle_mcck)
+ basr %r14,%r1 # call machine check handler
mcck_return:
RESTORE_ALL 0
@@ -742,7 +823,7 @@ cleanup_critical:
clc 4(4,%r12),BASED(cleanup_table_sysc_work_loop)
bl BASED(0f)
clc 4(4,%r12),BASED(cleanup_table_sysc_work_loop+4)
- bl BASED(cleanup_sysc_leave)
+ bl BASED(cleanup_sysc_return)
0:
br %r14
@@ -760,6 +841,7 @@ cleanup_system_call:
mvc __LC_SAVE_AREA(16),__LC_SAVE_AREA+16
0: st %r13,__LC_SAVE_AREA+20
SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
+ CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
st %r15,__LC_SAVE_AREA+28
lh %r7,0x8a
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
@@ -834,6 +916,8 @@ cleanup_sysc_leave_insn:
* Symbol constants
*/
.Ls390_mcck: .long s390_do_machine_check
+.Ls390_handle_mcck:
+ .long s390_handle_mcck
.Ldo_IRQ: .long do_IRQ
.Ldo_extint: .long do_extint
.Ldo_signal: .long do_signal
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 51527ab8c8f..57ca75d0ad7 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -7,6 +7,7 @@
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
* Hartmut Penner (hp@de.ibm.com),
* Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
+ * Heiko Carstens <heiko.carstens@de.ibm.com>
*/
#include <linux/sys.h>
@@ -52,9 +53,9 @@ SP_SIZE = STACK_FRAME_OVERHEAD + __PT_SIZE
STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
STACK_SIZE = 1 << STACK_SHIFT
-_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
+_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING | \
_TIF_RESTART_SVC | _TIF_SINGLE_STEP )
-_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
+_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
#define BASED(name) name-system_call(%r13)
@@ -114,7 +115,11 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
jz stack_overflow
3:
#endif
-2: aghi %r15,-SP_SIZE # make room for registers & psw
+2:
+ .endm
+
+ .macro CREATE_STACK_FRAME psworg,savearea
+ aghi %r15,-SP_SIZE # make room for registers & psw
mvc SP_PSW(16,%r15),0(%r12) # move user PSW to stack
la %r12,\psworg
stg %r2,SP_ORIG_R2(%r15) # store original content of gpr 2
@@ -152,6 +157,13 @@ __switch_to:
je __switch_to_noper # we got away without bashing TLB's
lctlg %c9,%c11,__THREAD_per(%r3) # Nope we didn't
__switch_to_noper:
+ lg %r4,__THREAD_info(%r2) # get thread_info of prev
+ tm __TI_flags+7(%r4),_TIF_MCCK_PENDING # machine check pending?
+ jz __switch_to_no_mcck
+ ni __TI_flags+7(%r4),255-_TIF_MCCK_PENDING # clear flag in prev
+ lg %r4,__THREAD_info(%r3) # get thread_info of next
+ oi __TI_flags+7(%r4),_TIF_MCCK_PENDING # set it in next
+__switch_to_no_mcck:
stmg %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
stg %r15,__THREAD_ksp(%r2) # store kernel stack to prev->tss.ksp
lg %r15,__THREAD_ksp(%r3) # load kernel stack from next->tss.ksp
@@ -176,6 +188,7 @@ system_call:
sysc_saveall:
SAVE_ALL_BASE __LC_SAVE_AREA
SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
+ CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
sysc_vtime:
@@ -232,6 +245,8 @@ sysc_work_loop:
# One of the work bits is on. Find out which one.
#
sysc_work:
+ tm __TI_flags+7(%r9),_TIF_MCCK_PENDING
+ jo sysc_mcck_pending
tm __TI_flags+7(%r9),_TIF_NEED_RESCHED
jo sysc_reschedule
tm __TI_flags+7(%r9),_TIF_SIGPENDING
@@ -250,6 +265,13 @@ sysc_reschedule:
jg schedule # return point is sysc_return
#
+# _TIF_MCCK_PENDING is set, call handler
+#
+sysc_mcck_pending:
+ larl %r14,sysc_work_loop
+ jg s390_handle_mcck # TIF bit will be cleared by handler
+
+#
# _TIF_SIGPENDING is set, call do_signal
#
sysc_sigpending:
@@ -474,6 +496,7 @@ pgm_check_handler:
tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
jnz pgm_per # got per exception -> special case
SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1
+ CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
jz pgm_no_vtime
@@ -512,6 +535,7 @@ pgm_per:
#
pgm_per_std:
SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1
+ CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
jz pgm_no_vtime2
@@ -537,6 +561,7 @@ pgm_no_vtime2:
#
pgm_svcper:
SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
+ CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
jz pgm_no_vtime3
@@ -564,6 +589,7 @@ io_int_handler:
stck __LC_INT_CLOCK
SAVE_ALL_BASE __LC_SAVE_AREA+32
SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+32,0
+ CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+32
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
jz io_no_vtime
@@ -621,9 +647,11 @@ io_work:
lgr %r15,%r1
#
# One of the work bits is on. Find out which one.
-# Checked are: _TIF_SIGPENDING and _TIF_NEED_RESCHED
+# Checked are: _TIF_SIGPENDING, _TIF_NEED_RESCHED and _TIF_MCCK_PENDING
#
io_work_loop:
+ tm __TI_flags+7(%r9),_TIF_MCCK_PENDING
+ jo io_mcck_pending
tm __TI_flags+7(%r9),_TIF_NEED_RESCHED
jo io_reschedule
tm __TI_flags+7(%r9),_TIF_SIGPENDING
@@ -631,6 +659,13 @@ io_work_loop:
j io_leave
#
+# _TIF_MCCK_PENDING is set, call handler
+#
+io_mcck_pending:
+ larl %r14,io_work_loop
+ jg s390_handle_mcck # TIF bit will be cleared by handler
+
+#
# _TIF_NEED_RESCHED is set, call schedule
#
io_reschedule:
@@ -661,6 +696,7 @@ ext_int_handler:
stck __LC_INT_CLOCK
SAVE_ALL_BASE __LC_SAVE_AREA+32
SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32,0
+ CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
tm SP_PSW+1(%r15),0x01 # interrupting from user ?
jz ext_no_vtime
@@ -680,18 +716,60 @@ ext_no_vtime:
*/
.globl mcck_int_handler
mcck_int_handler:
- STORE_TIMER __LC_ASYNC_ENTER_TIMER
+ la %r1,4095 # revalidate r1
+ spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer
+ lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs
SAVE_ALL_BASE __LC_SAVE_AREA+64
- SAVE_ALL __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64,0
+ la %r12,__LC_MCK_OLD_PSW
+ tm __LC_MCCK_CODE,0x80 # system damage?
+ jo mcck_int_main # yes -> rest of mcck code invalid
+ tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid?
+ jo 0f
+ spt __LC_LAST_UPDATE_TIMER
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
- tm SP_PSW+1(%r15),0x01 # interrupting from user ?
+ mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
+ mvc __LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
+ mvc __LC_LAST_UPDATE_TIMER(8),__LC_EXIT_TIMER
+0: tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid?
+ jno mcck_no_vtime # no -> no timer update
+ tm __LC_MCK_OLD_PSW+1,0x01 # interrupting from user ?
jz mcck_no_vtime
UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
mcck_no_vtime:
#endif
- brasl %r14,s390_do_machine_check
+0:
+ tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid?
+ jno mcck_int_main # no -> skip cleanup critical
+ tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit
+ jnz mcck_int_main # from user -> load kernel stack
+ clc __LC_MCK_OLD_PSW+8(8),BASED(.Lcritical_end)
+ jhe mcck_int_main
+ clc __LC_MCK_OLD_PSW+8(8),BASED(.Lcritical_start)
+ jl mcck_int_main
+ brasl %r14,cleanup_critical
+mcck_int_main:
+ lg %r14,__LC_PANIC_STACK # are we already on the panic stack?
+ slgr %r14,%r15
+ srag %r14,%r14,PAGE_SHIFT
+ jz 0f
+ lg %r15,__LC_PANIC_STACK # load panic stack
+0: CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64
+ lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct
+ la %r2,SP_PTREGS(%r15) # load pt_regs
+ brasl %r14,s390_do_machine_check
+ tm SP_PSW+1(%r15),0x01 # returning to user ?
+ jno mcck_return
+ lg %r1,__LC_KERNEL_STACK # switch to kernel stack
+ aghi %r1,-SP_SIZE
+ mvc SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
+ xc __SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain
+ lgr %r15,%r1
+ stosm __SF_EMPTY(%r15),0x04 # turn dat on
+ tm __TI_flags+7(%r9),_TIF_MCCK_PENDING
+ jno mcck_return
+ brasl %r14,s390_handle_mcck
mcck_return:
RESTORE_ALL 0
@@ -775,7 +853,7 @@ cleanup_critical:
clc 8(8,%r12),BASED(cleanup_table_sysc_work_loop)
jl 0f
clc 8(8,%r12),BASED(cleanup_table_sysc_work_loop+8)
- jl cleanup_sysc_leave
+ jl cleanup_sysc_return
0:
br %r14
@@ -793,6 +871,7 @@ cleanup_system_call:
mvc __LC_SAVE_AREA(32),__LC_SAVE_AREA+32
0: stg %r13,__LC_SAVE_AREA+40
SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
+ CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
stg %r15,__LC_SAVE_AREA+56
llgh %r7,__LC_SVC_INT_CODE
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index b804c55bd91..fc8bf5e285f 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -345,10 +345,25 @@ iplstart:
bno .Lnoreset
la %r2,.Lreset
lhi %r3,26
- .long 0x83230008
+ diag %r2,%r3,8
+ mvc 0x78(8),.Lrdrnewpsw # set up IO interrupt psw
+.Lwaitrdrirq:
+ lpsw .Lrdrwaitpsw
+.Lrdrint:
+ c %r1,0xb8 # compare subchannel number
+ bne .Lwaitrdrirq
+ la %r5,.Lirb
+ tsch 0(%r5)
.Lnoreset:
+ b .Lnoload
+
+ .align 8
+.Lrdrnewpsw:
+ .long 0x00080000,0x80000000+.Lrdrint
+.Lrdrwaitpsw:
+ .long 0x020a0000,0x80000000+.Lrdrint
#endif
-
+
#
# everything loaded, go for it
#
@@ -517,10 +532,10 @@ startup:basr %r13,0 # get base
l %r2, .Lrcp2-.LPG1(%r13) # try with Read SCP
b .Lservicecall-.LPG1(%r13)
.Lprocsccb:
- lh %r1,.Lscpincr1-PARMAREA(%r4) # use this one if != 0
- chi %r1,0x00
- jne .Lscnd
- l %r1,.Lscpincr2-PARMAREA(%r4) # otherwise use this one
+ lhi %r1,0
+ icm %r1,3,.Lscpincr1-PARMAREA(%r4) # use this one if != 0
+ jnz .Lscnd
+ l %r1,.Lscpincr2-PARMAREA+4(%r4) # otherwise use this one
.Lscnd:
xr %r3,%r3 # same logic
ic %r3,.Lscpa1-PARMAREA(%r4)
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index 8366793bc37..f525c0c2125 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -344,10 +344,25 @@ iplstart:
bno .Lnoreset
la %r2,.Lreset
lhi %r3,26
- .long 0x83230008
+ diag %r2,%r3,8
+ mvc 0x78(8),.Lrdrnewpsw # set up IO interrupt psw
+.Lwaitrdrirq:
+ lpsw .Lrdrwaitpsw
+.Lrdrint:
+ c %r1,0xb8 # compare subchannel number
+ bne .Lwaitrdrirq
+ la %r5,.Lirb
+ tsch 0(%r5)
.Lnoreset:
+ b .Lnoload
+
+ .align 8
+.Lrdrnewpsw:
+ .long 0x00080000,0x80000000+.Lrdrint
+.Lrdrwaitpsw:
+ .long 0x020a0000,0x80000000+.Lrdrint
#endif
-
+
#
# everything loaded, go for it
#
@@ -518,9 +533,9 @@ startup:basr %r13,0 # get base
l %r2,.Lrcp2-.LPG1(%r13) # try with Read SCP
b .Lservicecall-.LPG1(%r13)
.Lprocsccb:
- lh %r1,.Lscpincr1-PARMAREA(%r4) # use this one if != 0
- chi %r1,0x00
- jne .Lscnd
+ lghi %r1,0
+ icm %r1,3,.Lscpincr1-PARMAREA(%r4) # use this one if != 0
+ jnz .Lscnd
lg %r1,.Lscpincr2-PARMAREA(%r4) # otherwise use this one
.Lscnd:
xr %r3,%r3 # same logic
diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c
new file mode 100644
index 00000000000..2721c3a32b8
--- /dev/null
+++ b/arch/s390/kernel/machine_kexec.c
@@ -0,0 +1,98 @@
+/*
+ * arch/s390/kernel/machine_kexec.c
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com>
+ *
+ */
+
+/*
+ * s390_machine_kexec.c - handle the transition of Linux booting another kernel
+ * on the S390 architecture.
+ */
+
+#include <asm/cio.h>
+#include <asm/setup.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/kexec.h>
+#include <linux/delay.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/system.h>
+
+static void kexec_halt_all_cpus(void *);
+
+typedef void (*relocate_kernel_t) (kimage_entry_t *, unsigned long);
+
+const extern unsigned char relocate_kernel[];
+const extern unsigned long long relocate_kernel_len;
+
+int
+machine_kexec_prepare(struct kimage *image)
+{
+ unsigned long reboot_code_buffer;
+
+ /* We don't support anything but the default image type for now. */
+ if (image->type != KEXEC_TYPE_DEFAULT)
+ return -EINVAL;
+
+ /* Get the destination where the assembler code should be copied to.*/
+ reboot_code_buffer = page_to_pfn(image->control_code_page)<<PAGE_SHIFT;
+
+ /* Then copy it */
+ memcpy((void *) reboot_code_buffer, relocate_kernel,
+ relocate_kernel_len);
+ return 0;
+}
+
+void
+machine_kexec_cleanup(struct kimage *image)
+{
+}
+
+void
+machine_shutdown(void)
+{
+ printk(KERN_INFO "kexec: machine_shutdown called\n");
+}
+
+NORET_TYPE void
+machine_kexec(struct kimage *image)
+{
+ clear_all_subchannels();
+
+ /* Disable lowcore protection */
+ ctl_clear_bit(0,28);
+
+ on_each_cpu(kexec_halt_all_cpus, image, 0, 0);
+ for (;;);
+}
+
+static void
+kexec_halt_all_cpus(void *kernel_image)
+{
+ static atomic_t cpuid = ATOMIC_INIT(-1);
+ int cpu;
+ struct kimage *image;
+ relocate_kernel_t data_mover;
+
+ if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid))
+ signal_processor(smp_processor_id(), sigp_stop);
+
+ /* Wait for all other cpus to enter stopped state */
+ for_each_online_cpu(cpu) {
+ if (cpu == smp_processor_id())
+ continue;
+ while (!smp_cpu_not_running(cpu))
+ cpu_relax();
+ }
+
+ image = (struct kimage *) kernel_image;
+ data_mover = (relocate_kernel_t)
+ (page_to_pfn(image->control_code_page) << PAGE_SHIFT);
+
+ /* Call the moving routine */
+ (*data_mover) (&image->head, image->start);
+}
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 7aea25d6e30..9f3dff6c0b7 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -91,13 +91,12 @@ void do_monitor_call(struct pt_regs *regs, long interruption_code)
(void *)(long) smp_processor_id());
}
+extern void s390_handle_mcck(void);
/*
* The idle loop on a S390...
*/
void default_idle(void)
{
- psw_t wait_psw;
- unsigned long reg;
int cpu, rc;
local_irq_disable();
@@ -125,38 +124,17 @@ void default_idle(void)
cpu_die();
#endif
- /*
- * Wait for external, I/O or machine check interrupt and
- * switch off machine check bit after the wait has ended.
- */
- wait_psw.mask = PSW_KERNEL_BITS | PSW_MASK_MCHECK | PSW_MASK_WAIT |
- PSW_MASK_IO | PSW_MASK_EXT;
-#ifndef CONFIG_ARCH_S390X
- asm volatile (
- " basr %0,0\n"
- "0: la %0,1f-0b(%0)\n"
- " st %0,4(%1)\n"
- " oi 4(%1),0x80\n"
- " lpsw 0(%1)\n"
- "1: la %0,2f-1b(%0)\n"
- " st %0,4(%1)\n"
- " oi 4(%1),0x80\n"
- " ni 1(%1),0xf9\n"
- " lpsw 0(%1)\n"
- "2:"
- : "=&a" (reg) : "a" (&wait_psw) : "memory", "cc" );
-#else /* CONFIG_ARCH_S390X */
- asm volatile (
- " larl %0,0f\n"
- " stg %0,8(%1)\n"
- " lpswe 0(%1)\n"
- "0: larl %0,1f\n"
- " stg %0,8(%1)\n"
- " ni 1(%1),0xf9\n"
- " lpswe 0(%1)\n"
- "1:"
- : "=&a" (reg) : "a" (&wait_psw) : "memory", "cc" );
-#endif /* CONFIG_ARCH_S390X */
+ local_mcck_disable();
+ if (test_thread_flag(TIF_MCCK_PENDING)) {
+ local_mcck_enable();
+ local_irq_enable();
+ s390_handle_mcck();
+ return;
+ }
+
+ /* Wait for external, I/O or machine check interrupt. */
+ __load_psw_mask(PSW_KERNEL_BITS | PSW_MASK_WAIT |
+ PSW_MASK_IO | PSW_MASK_EXT);
}
void cpu_idle(void)
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 26889366929..06afa3103ac 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -40,6 +40,7 @@
#include <asm/pgalloc.h>
#include <asm/system.h>
#include <asm/uaccess.h>
+#include <asm/unistd.h>
#ifdef CONFIG_S390_SUPPORT
#include "compat_ptrace.h"
@@ -130,13 +131,19 @@ static int
peek_user(struct task_struct *child, addr_t addr, addr_t data)
{
struct user *dummy = NULL;
- addr_t offset, tmp;
+ addr_t offset, tmp, mask;
/*
* Stupid gdb peeks/pokes the access registers in 64 bit with
* an alignment of 4. Programmers from hell...
*/
- if ((addr & 3) || addr > sizeof(struct user) - __ADDR_MASK)
+ mask = __ADDR_MASK;
+#ifdef CONFIG_ARCH_S390X
+ if (addr >= (addr_t) &dummy->regs.acrs &&
+ addr < (addr_t) &dummy->regs.orig_gpr2)
+ mask = 3;
+#endif
+ if ((addr & mask) || addr > sizeof(struct user) - __ADDR_MASK)
return -EIO;
if (addr < (addr_t) &dummy->regs.acrs) {
@@ -153,6 +160,16 @@ peek_user(struct task_struct *child, addr_t addr, addr_t data)
* access registers are stored in the thread structure
*/
offset = addr - (addr_t) &dummy->regs.acrs;
+#ifdef CONFIG_ARCH_S390X
+ /*
+ * Very special case: old & broken 64 bit gdb reading
+ * from acrs[15]. Result is a 64 bit value. Read the
+ * 32 bit acrs[15] value and shift it by 32. Sick...
+ */
+ if (addr == (addr_t) &dummy->regs.acrs[15])
+ tmp = ((unsigned long) child->thread.acrs[15]) << 32;
+ else
+#endif
tmp = *(addr_t *)((addr_t) &child->thread.acrs + offset);
} else if (addr == (addr_t) &dummy->regs.orig_gpr2) {
@@ -167,6 +184,9 @@ peek_user(struct task_struct *child, addr_t addr, addr_t data)
*/
offset = addr - (addr_t) &dummy->regs.fp_regs;
tmp = *(addr_t *)((addr_t) &child->thread.fp_regs + offset);
+ if (addr == (addr_t) &dummy->regs.fp_regs.fpc)
+ tmp &= (unsigned long) FPC_VALID_MASK
+ << (BITS_PER_LONG - 32);
} else if (addr < (addr_t) (&dummy->regs.per_info + 1)) {
/*
@@ -191,13 +211,19 @@ static int
poke_user(struct task_struct *child, addr_t addr, addr_t data)
{
struct user *dummy = NULL;
- addr_t offset;
+ addr_t offset, mask;
/*
* Stupid gdb peeks/pokes the access registers in 64 bit with
* an alignment of 4. Programmers from hell indeed...
*/
- if ((addr & 3) || addr > sizeof(struct user) - __ADDR_MASK)
+ mask = __ADDR_MASK;
+#ifdef CONFIG_ARCH_S390X
+ if (addr >= (addr_t) &dummy->regs.acrs &&
+ addr < (addr_t) &dummy->regs.orig_gpr2)
+ mask = 3;
+#endif
+ if ((addr & mask) || addr > sizeof(struct user) - __ADDR_MASK)
return -EIO;
if (addr < (addr_t) &dummy->regs.acrs) {
@@ -224,6 +250,17 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data)
* access registers are stored in the thread structure
*/
offset = addr - (addr_t) &dummy->regs.acrs;
+#ifdef CONFIG_ARCH_S390X
+ /*
+ * Very special case: old & broken 64 bit gdb writing
+ * to acrs[15] with a 64 bit value. Ignore the lower
+ * half of the value and write the upper 32 bit to
+ * acrs[15]. Sick...
+ */
+ if (addr == (addr_t) &dummy->regs.acrs[15])
+ child->thread.acrs[15] = (unsigned int) (data >> 32);
+ else
+#endif
*(addr_t *)((addr_t) &child->thread.acrs + offset) = data;
} else if (addr == (addr_t) &dummy->regs.orig_gpr2) {
@@ -237,7 +274,8 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data)
* floating point regs. are stored in the thread structure
*/
if (addr == (addr_t) &dummy->regs.fp_regs.fpc &&
- (data & ~FPC_VALID_MASK) != 0)
+ (data & ~((unsigned long) FPC_VALID_MASK
+ << (BITS_PER_LONG - 32))) != 0)
return -EINVAL;
offset = addr - (addr_t) &dummy->regs.fp_regs;
*(addr_t *)((addr_t) &child->thread.fp_regs + offset) = data;
@@ -723,6 +761,13 @@ syscall_trace(struct pt_regs *regs, int entryexit)
? 0x80 : 0));
/*
+ * If the debuffer has set an invalid system call number,
+ * we prepare to skip the system call restart handling.
+ */
+ if (!entryexit && regs->gprs[2] >= NR_syscalls)
+ regs->trap = -1;
+
+ /*
* this isn't the same as continuing with a signal, but it will do
* for normal use. strace only continues with a signal if the
* stopping signal is not SIGTRAP. -brl
diff --git a/arch/s390/kernel/relocate_kernel.S b/arch/s390/kernel/relocate_kernel.S
new file mode 100644
index 00000000000..d5e4a62fbb7
--- /dev/null
+++ b/arch/s390/kernel/relocate_kernel.S
@@ -0,0 +1,81 @@
+/*
+ * arch/s390/kernel/relocate_kernel.S
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com>
+ *
+ */
+
+/*
+ * moves the new kernel to its destination...
+ * %r2 = pointer to first kimage_entry_t
+ * %r3 = start address - where to jump to after the job is done...
+ *
+ * %r5 will be used as temp. storage
+ * %r6 holds the destination address
+ * %r7 = PAGE_SIZE
+ * %r8 holds the source address
+ * %r9 = PAGE_SIZE
+ * %r10 is a page mask
+ */
+
+ .text
+ .globl relocate_kernel
+ relocate_kernel:
+ basr %r13,0 #base address
+ .base:
+ spx zero64-.base(%r13) #absolute addressing mode
+ stnsm sys_msk-.base(%r13),0xf8 #disable DAT and IRQ (external)
+ lhi %r10,-1 #preparing the mask
+ sll %r10,12 #shift it such that it becomes 0xf000
+ .top:
+ lhi %r7,4096 #load PAGE_SIZE in r7
+ lhi %r9,4096 #load PAGE_SIZE in r9
+ l %r5,0(%r2) #read another word for indirection page
+ ahi %r2,4 #increment pointer
+ tml %r5,0x1 #is it a destination page?
+ je .indir_check #NO, goto "indir_check"
+ lr %r6,%r5 #r6 = r5
+ nr %r6,%r10 #mask it out and...
+ j .top #...next iteration
+ .indir_check:
+ tml %r5,0x2 #is it a indirection page?
+ je .done_test #NO, goto "done_test"
+ nr %r5,%r10 #YES, mask out,
+ lr %r2,%r5 #move it into the right register,
+ j .top #and read next...
+ .done_test:
+ tml %r5,0x4 #is it the done indicator?
+ je .source_test #NO! Well, then it should be the source indicator...
+ j .done #ok, lets finish it here...
+ .source_test:
+ tml %r5,0x8 #it should be a source indicator...
+ je .top #NO, ignore it...
+ lr %r8,%r5 #r8 = r5
+ nr %r8,%r10 #masking
+ 0: mvcle %r6,%r8,0x0 #copy PAGE_SIZE bytes from r8 to r6 - pad with 0
+ jo 0b
+ j .top
+ .done:
+ sr %r0,%r0 #clear register r0
+ la %r4,load_psw-.base(%r13) #load psw-address into the register
+ o %r3,4(%r4) #or load address into psw
+ st %r3,4(%r4)
+ mvc 0(8,%r0),0(%r4) #copy psw to absolute address 0
+ sr %r1,%r1 #clear %r1
+ sr %r2,%r2 #clear %r2
+ sigp %r1,%r2,0x12 #set cpuid to zero
+ lpsw 0 #hopefully start new kernel...
+
+ .align 8
+ zero64:
+ .quad 0
+ load_psw:
+ .long 0x00080000,0x80000000
+ sys_msk:
+ .quad 0
+ relocate_kernel_end:
+ .globl relocate_kernel_len
+ relocate_kernel_len:
+ .quad relocate_kernel_end - relocate_kernel
diff --git a/arch/s390/kernel/relocate_kernel64.S b/arch/s390/kernel/relocate_kernel64.S
new file mode 100644
index 00000000000..96290cc4eb3
--- /dev/null
+++ b/arch/s390/kernel/relocate_kernel64.S
@@ -0,0 +1,82 @@
+/*
+ * arch/s390/kernel/relocate_kernel64.S
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com>
+ *
+ */
+
+/*
+ * moves the new kernel to its destination...
+ * %r2 = pointer to first kimage_entry_t
+ * %r3 = start address - where to jump to after the job is done...
+ *
+ * %r5 will be used as temp. storage
+ * %r6 holds the destination address
+ * %r7 = PAGE_SIZE
+ * %r8 holds the source address
+ * %r9 = PAGE_SIZE
+ *
+ * 0xf000 is a page_mask
+ */
+
+ .text
+ .globl relocate_kernel
+ relocate_kernel:
+ basr %r13,0 #base address
+ .base:
+ spx zero64-.base(%r13) #absolute addressing mode
+ stnsm sys_msk-.base(%r13),0xf8 #disable DAT and IRQ (external)
+ .top:
+ lghi %r7,4096 #load PAGE_SIZE in r7
+ lghi %r9,4096 #load PAGE_SIZE in r9
+ lg %r5,0(%r2) #read another word for indirection page
+ aghi %r2,8 #increment pointer
+ tml %r5,0x1 #is it a destination page?
+ je .indir_check #NO, goto "indir_check"
+ lgr %r6,%r5 #r6 = r5
+ nill %r6,0xf000 #mask it out and...
+ j .top #...next iteration
+ .indir_check:
+ tml %r5,0x2 #is it a indirection page?
+ je .done_test #NO, goto "done_test"
+ nill %r5,0xf000 #YES, mask out,
+ lgr %r2,%r5 #move it into the right register,
+ j .top #and read next...
+ .done_test:
+ tml %r5,0x4 #is it the done indicator?
+ je .source_test #NO! Well, then it should be the source indicator...
+ j .done #ok, lets finish it here...
+ .source_test:
+ tml %r5,0x8 #it should be a source indicator...
+ je .top #NO, ignore it...
+ lgr %r8,%r5 #r8 = r5
+ nill %r8,0xf000 #masking
+ 0: mvcle %r6,%r8,0x0 #copy PAGE_SIZE bytes from r8 to r6 - pad with 0
+ jo 0b
+ j .top
+ .done:
+ sgr %r0,%r0 #clear register r0
+ la %r4,load_psw-.base(%r13) #load psw-address into the register
+ o %r3,4(%r4) #or load address into psw
+ st %r3,4(%r4)
+ mvc 0(8,%r0),0(%r4) #copy psw to absolute address 0
+ sam31 #31 bit mode
+ sr %r1,%r1 #erase register r1
+ sr %r2,%r2 #erase register r2
+ sigp %r1,%r2,0x12 #set cpuid to zero
+ lpsw 0 #hopefully start new kernel...
+
+ .align 8
+ zero64:
+ .quad 0
+ load_psw:
+ .long 0x00080000,0x80000000
+ sys_msk:
+ .quad 0
+ relocate_kernel_end:
+ .globl relocate_kernel_len
+ relocate_kernel_len:
+ .quad relocate_kernel_end - relocate_kernel
+
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index df83215beac..b6d740ac0e6 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -198,11 +198,11 @@ static void __init conmode_default(void)
char *ptr;
if (MACHINE_IS_VM) {
- __cpcmd("QUERY CONSOLE", query_buffer, 1024);
+ __cpcmd("QUERY CONSOLE", query_buffer, 1024, NULL);
console_devno = simple_strtoul(query_buffer + 5, NULL, 16);
ptr = strstr(query_buffer, "SUBCHANNEL =");
console_irq = simple_strtoul(ptr + 13, NULL, 16);
- __cpcmd("QUERY TERM", query_buffer, 1024);
+ __cpcmd("QUERY TERM", query_buffer, 1024, NULL);
ptr = strstr(query_buffer, "CONMODE");
/*
* Set the conmode to 3215 so that the device recognition
@@ -211,7 +211,7 @@ static void __init conmode_default(void)
* 3215 and the 3270 driver will try to access the console
* device (3215 as console and 3270 as normal tty).
*/
- __cpcmd("TERM CONMODE 3215", NULL, 0);
+ __cpcmd("TERM CONMODE 3215", NULL, 0, NULL);
if (ptr == NULL) {
#if defined(CONFIG_SCLP_CONSOLE)
SET_CONSOLE_SCLP;
@@ -414,7 +414,8 @@ setup_lowcore(void)
lc->program_new_psw.mask = PSW_KERNEL_BITS;
lc->program_new_psw.addr =
PSW_ADDR_AMODE | (unsigned long)pgm_check_handler;
- lc->mcck_new_psw.mask = PSW_KERNEL_BITS;
+ lc->mcck_new_psw.mask =
+ PSW_KERNEL_BITS & ~PSW_MASK_MCHECK & ~PSW_MASK_DAT;
lc->mcck_new_psw.addr =
PSW_ADDR_AMODE | (unsigned long) mcck_int_handler;
lc->io_new_psw.mask = PSW_KERNEL_BITS;
@@ -424,12 +425,18 @@ setup_lowcore(void)
lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE;
lc->async_stack = (unsigned long)
__alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE;
-#ifdef CONFIG_CHECK_STACK
lc->panic_stack = (unsigned long)
__alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0) + PAGE_SIZE;
-#endif
lc->current_task = (unsigned long) init_thread_union.thread_info.task;
lc->thread_info = (unsigned long) &init_thread_union;
+#ifndef CONFIG_ARCH_S390X
+ if (MACHINE_HAS_IEEE) {
+ lc->extended_save_area_addr = (__u32)
+ __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0);
+ /* enable extended save area */
+ ctl_set_bit(14, 29);
+ }
+#endif
#ifdef CONFIG_ARCH_S390X
if (MACHINE_HAS_DIAG44)
lc->diag44_opcode = 0x83000044;
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index fdfcf0488b4..642572a8e33 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -284,7 +284,7 @@ static void do_machine_restart(void * __unused)
* locks are always held disabled).
*/
if (MACHINE_IS_VM)
- cpcmd ("IPL", NULL, 0);
+ cpcmd ("IPL", NULL, 0, NULL);
else
reipl (0x10000 | S390_lowcore.ipl_device);
}
@@ -313,7 +313,7 @@ static void do_machine_halt(void * __unused)
if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid) == 0) {
smp_send_stop();
if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
- cpcmd(vmhalt_cmd, NULL, 0);
+ cpcmd(vmhalt_cmd, NULL, 0, NULL);
signal_processor(smp_processor_id(),
sigp_stop_and_store_status);
}
@@ -332,7 +332,7 @@ static void do_machine_power_off(void * __unused)
if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid) == 0) {
smp_send_stop();
if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
- cpcmd(vmpoff_cmd, NULL, 0);
+ cpcmd(vmpoff_cmd, NULL, 0, NULL);
signal_processor(smp_processor_id(),
sigp_stop_and_store_status);
}
@@ -679,12 +679,14 @@ __cpu_disable(void)
{
unsigned long flags;
ec_creg_mask_parms cr_parms;
+ int cpu = smp_processor_id();
spin_lock_irqsave(&smp_reserve_lock, flags);
- if (smp_cpu_reserved[smp_processor_id()] != 0) {
+ if (smp_cpu_reserved[cpu] != 0) {
spin_unlock_irqrestore(&smp_reserve_lock, flags);
return -EBUSY;
}
+ cpu_clear(cpu, cpu_online_map);
#ifdef CONFIG_PFAULT
/* Disable pfault pseudo page faults on this cpu. */
@@ -771,13 +773,24 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
*(lowcore_ptr[i]) = S390_lowcore;
lowcore_ptr[i]->async_stack = stack + (ASYNC_SIZE);
-#ifdef CONFIG_CHECK_STACK
stack = __get_free_pages(GFP_KERNEL,0);
if (stack == 0ULL)
panic("smp_boot_cpus failed to allocate memory\n");
lowcore_ptr[i]->panic_stack = stack + (PAGE_SIZE);
+#ifndef __s390x__
+ if (MACHINE_HAS_IEEE) {
+ lowcore_ptr[i]->extended_save_area_addr =
+ (__u32) __get_free_pages(GFP_KERNEL,0);
+ if (lowcore_ptr[i]->extended_save_area_addr == 0)
+ panic("smp_boot_cpus failed to "
+ "allocate memory\n");
+ }
#endif
}
+#ifndef __s390x__
+ if (MACHINE_HAS_IEEE)
+ ctl_set_bit(14, 29); /* enable extended save area */
+#endif
set_prefix((u32)(unsigned long) lowcore_ptr[smp_processor_id()]);
for_each_cpu(cpu)
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index 515938628f8..a8668afb5f8 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -285,7 +285,7 @@ SYSCALL(sys_mq_timedsend,sys_mq_timedsend,compat_sys_mq_timedsend_wrapper)
SYSCALL(sys_mq_timedreceive,sys_mq_timedreceive,compat_sys_mq_timedreceive_wrapper)
SYSCALL(sys_mq_notify,sys_mq_notify,compat_sys_mq_notify_wrapper) /* 275 */
SYSCALL(sys_mq_getsetattr,sys_mq_getsetattr,compat_sys_mq_getsetattr_wrapper)
-NI_SYSCALL /* reserved for kexec */
+SYSCALL(sys_kexec_load,sys_kexec_load,compat_sys_kexec_load_wrapper)
SYSCALL(sys_add_key,sys_add_key,compat_sys_add_key_wrapper)
SYSCALL(sys_request_key,sys_request_key,compat_sys_request_key_wrapper)
SYSCALL(sys_keyctl,sys_keyctl,compat_sys_keyctl) /* 280 */
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 8b90e9528b9..bc7b7be7acb 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -668,7 +668,10 @@ asmlinkage void space_switch_exception(struct pt_regs * regs, long int_code)
asmlinkage void kernel_stack_overflow(struct pt_regs * regs)
{
- die("Kernel stack overflow", regs, 0);
+ bust_spinlocks(1);
+ printk("Kernel stack overflow.\n");
+ show_regs(regs);
+ bust_spinlocks(0);
panic("Corrupt kernel stack, can't continue.");
}
@@ -732,7 +735,7 @@ void __init trap_init(void)
&ext_int_pfault);
#endif
#ifndef CONFIG_ARCH_S390X
- cpcmd("SET PAGEX ON", NULL, 0);
+ cpcmd("SET PAGEX ON", NULL, 0, NULL);
#endif
}
}
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index f5a5bc09b8f..2d5cb138575 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -21,7 +21,7 @@
#include <asm/uaccess.h>
static char *sender = "VMRMSVM";
-module_param(sender, charp, 0);
+module_param(sender, charp, 0400);
MODULE_PARM_DESC(sender,
"Guest name that may send SMSG messages (default VMRMSVM)");
diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c
index 648deed17e2..c5348108ca3 100644
--- a/arch/s390/mm/extmem.c
+++ b/arch/s390/mm/extmem.c
@@ -576,8 +576,8 @@ segment_save(char *name)
segtype_string[seg->range[i].start & 0xff]);
}
sprintf(cmd2, "SAVESEG %s", name);
- cpcmd(cmd1, NULL, 0);
- cpcmd(cmd2, NULL, 0);
+ cpcmd(cmd1, NULL, 0, NULL);
+ cpcmd(cmd2, NULL, 0, NULL);
spin_unlock(&dcss_lock);
}
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 80306bc8c79..75fde949d12 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -207,7 +207,7 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection)
* we are not in an interrupt and that there is a
* user context.
*/
- if (user_address == 0 || in_interrupt() || !mm)
+ if (user_address == 0 || in_atomic() || !mm)
goto no_context;
/*
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 3468d512722..a7c8bfc1160 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -486,7 +486,7 @@ config CPU_SUBTYPE_ST40
depends on CPU_SUBTYPE_ST40STB1 || CPU_SUBTYPE_ST40GX1
default y
-config DISCONTIGMEM
+config ARCH_DISCONTIGMEM_ENABLE
bool
depends on SH_HP690
default y
@@ -496,6 +496,8 @@ config DISCONTIGMEM
or have huge holes in the physical address space for other reasons.
See <file:Documentation/vm/numa> for more.
+source "mm/Kconfig"
+
config ZERO_PAGE_OFFSET
hex "Zero page offset"
default "0x00001000" if !(SH_MPC1211 || SH_SH03)
diff --git a/arch/sh/kernel/sys_sh.c b/arch/sh/kernel/sys_sh.c
index df5ac294c37..917b2f32f26 100644
--- a/arch/sh/kernel/sys_sh.c
+++ b/arch/sh/kernel/sys_sh.c
@@ -79,6 +79,10 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
(!vma || addr + len <= vma->vm_start))
return addr;
}
+ if (len <= mm->cached_hole_size) {
+ mm->cached_hole_size = 0;
+ mm->free_area_cache = TASK_UNMAPPED_BASE;
+ }
if (flags & MAP_PRIVATE)
addr = PAGE_ALIGN(mm->free_area_cache);
else
@@ -95,6 +99,7 @@ full_search:
*/
if (start_addr != TASK_UNMAPPED_BASE) {
start_addr = addr = TASK_UNMAPPED_BASE;
+ mm->cached_hole_size = 0;
goto full_search;
}
return -ENOMEM;
@@ -106,6 +111,9 @@ full_search:
mm->free_area_cache = addr + len;
return addr;
}
+ if (addr + mm->cached_hole_size < vma->vm_start)
+ mm->cached_hole_size = vma->vm_start - addr;
+
addr = vma->vm_end;
if (!(flags & MAP_PRIVATE))
addr = COLOUR_ALIGN(addr);
diff --git a/arch/sh/lib/delay.c b/arch/sh/lib/delay.c
index 50b36037d86..351714694d6 100644
--- a/arch/sh/lib/delay.c
+++ b/arch/sh/lib/delay.c
@@ -24,7 +24,7 @@ inline void __const_udelay(unsigned long xloops)
__asm__("dmulu.l %0, %2\n\t"
"sts mach, %0"
: "=r" (xloops)
- : "0" (xloops), "r" (cpu_data[_smp_processor_id()].loops_per_jiffy)
+ : "0" (xloops), "r" (cpu_data[raw_smp_processor_id()].loops_per_jiffy)
: "macl", "mach");
__delay(xloops * HZ);
}
diff --git a/arch/sh/mm/hugetlbpage.c b/arch/sh/mm/hugetlbpage.c
index 1f897bab231..95bb1a6c606 100644
--- a/arch/sh/mm/hugetlbpage.c
+++ b/arch/sh/mm/hugetlbpage.c
@@ -24,7 +24,7 @@
#include <asm/tlbflush.h>
#include <asm/cacheflush.h>
-static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
{
pgd_t *pgd;
pmd_t *pmd;
@@ -39,7 +39,7 @@ static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
return pte;
}
-static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
{
pgd_t *pgd;
pmd_t *pmd;
@@ -56,28 +56,34 @@ static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
#define mk_pte_huge(entry) do { pte_val(entry) |= _PAGE_SZHUGE; } while (0)
-static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma,
- struct page *page, pte_t * page_table, int write_access)
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t entry)
{
- unsigned long i;
- pte_t entry;
+ int i;
- add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE);
+ for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
+ set_pte_at(mm, addr, ptep, entry);
+ ptep++;
+ addr += PAGE_SIZE;
+ pte_val(entry) += PAGE_SIZE;
+ }
+}
- if (write_access)
- entry = pte_mkwrite(pte_mkdirty(mk_pte(page,
- vma->vm_page_prot)));
- else
- entry = pte_wrprotect(mk_pte(page, vma->vm_page_prot));
- entry = pte_mkyoung(entry);
- mk_pte_huge(entry);
+pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep)
+{
+ pte_t entry;
+ int i;
- for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
- set_pte(page_table, entry);
- page_table++;
+ entry = *ptep;
- pte_val(entry) += PAGE_SIZE;
+ for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
+ pte_clear(mm, addr, ptep);
+ addr += PAGE_SIZE;
+ ptep++;
}
+
+ return entry;
}
/*
@@ -92,79 +98,6 @@ int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
return 0;
}
-int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
- struct vm_area_struct *vma)
-{
- pte_t *src_pte, *dst_pte, entry;
- struct page *ptepage;
- unsigned long addr = vma->vm_start;
- unsigned long end = vma->vm_end;
- int i;
-
- while (addr < end) {
- dst_pte = huge_pte_alloc(dst, addr);
- if (!dst_pte)
- goto nomem;
- src_pte = huge_pte_offset(src, addr);
- BUG_ON(!src_pte || pte_none(*src_pte));
- entry = *src_pte;
- ptepage = pte_page(entry);
- get_page(ptepage);
- for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
- set_pte(dst_pte, entry);
- pte_val(entry) += PAGE_SIZE;
- dst_pte++;
- }
- add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
- addr += HPAGE_SIZE;
- }
- return 0;
-
-nomem:
- return -ENOMEM;
-}
-
-int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
- struct page **pages, struct vm_area_struct **vmas,
- unsigned long *position, int *length, int i)
-{
- unsigned long vaddr = *position;
- int remainder = *length;
-
- WARN_ON(!is_vm_hugetlb_page(vma));
-
- while (vaddr < vma->vm_end && remainder) {
- if (pages) {
- pte_t *pte;
- struct page *page;
-
- pte = huge_pte_offset(mm, vaddr);
-
- /* hugetlb should be locked, and hence, prefaulted */
- BUG_ON(!pte || pte_none(*pte));
-
- page = pte_page(*pte);
-
- WARN_ON(!PageCompound(page));
-
- get_page(page);
- pages[i] = page;
- }
-
- if (vmas)
- vmas[i] = vma;
-
- vaddr += PAGE_SIZE;
- --remainder;
- ++i;
- }
-
- *length = remainder;
- *position = vaddr;
-
- return i;
-}
-
struct page *follow_huge_addr(struct mm_struct *mm,
unsigned long address, int write)
{
@@ -181,84 +114,3 @@ struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
{
return NULL;
}
-
-void unmap_hugepage_range(struct vm_area_struct *vma,
- unsigned long start, unsigned long end)
-{
- struct mm_struct *mm = vma->vm_mm;
- unsigned long address;
- pte_t *pte;
- struct page *page;
- int i;
-
- BUG_ON(start & (HPAGE_SIZE - 1));
- BUG_ON(end & (HPAGE_SIZE - 1));
-
- for (address = start; address < end; address += HPAGE_SIZE) {
- pte = huge_pte_offset(mm, address);
- BUG_ON(!pte);
- if (pte_none(*pte))
- continue;
- page = pte_page(*pte);
- put_page(page);
- for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
- pte_clear(mm, address+(i*PAGE_SIZE), pte);
- pte++;
- }
- }
- add_mm_counter(mm, rss, -((end - start) >> PAGE_SHIFT));
- flush_tlb_range(vma, start, end);
-}
-
-int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
-{
- struct mm_struct *mm = current->mm;
- unsigned long addr;
- int ret = 0;
-
- BUG_ON(vma->vm_start & ~HPAGE_MASK);
- BUG_ON(vma->vm_end & ~HPAGE_MASK);
-
- spin_lock(&mm->page_table_lock);
- for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
- unsigned long idx;
- pte_t *pte = huge_pte_alloc(mm, addr);
- struct page *page;
-
- if (!pte) {
- ret = -ENOMEM;
- goto out;
- }
- if (!pte_none(*pte))
- continue;
-
- idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
- + (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
- page = find_get_page(mapping, idx);
- if (!page) {
- /* charge the fs quota first */
- if (hugetlb_get_quota(mapping)) {
- ret = -ENOMEM;
- goto out;
- }
- page = alloc_huge_page();
- if (!page) {
- hugetlb_put_quota(mapping);
- ret = -ENOMEM;
- goto out;
- }
- ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
- if (! ret) {
- unlock_page(page);
- } else {
- hugetlb_put_quota(mapping);
- free_huge_page(page);
- goto out;
- }
- }
- set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE);
- }
-out:
- spin_unlock(&mm->page_table_lock);
- return ret;
-}
diff --git a/arch/sh64/Kconfig b/arch/sh64/Kconfig
index 76eb81fba45..708e59736a4 100644
--- a/arch/sh64/Kconfig
+++ b/arch/sh64/Kconfig
@@ -217,6 +217,8 @@ config PREEMPT
bool "Preemptible Kernel (EXPERIMENTAL)"
depends on EXPERIMENTAL
+source "mm/Kconfig"
+
endmenu
menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
diff --git a/arch/sh64/mm/hugetlbpage.c b/arch/sh64/mm/hugetlbpage.c
index bcad2aefa4e..dcd9c8a8baf 100644
--- a/arch/sh64/mm/hugetlbpage.c
+++ b/arch/sh64/mm/hugetlbpage.c
@@ -24,7 +24,7 @@
#include <asm/tlbflush.h>
#include <asm/cacheflush.h>
-static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
{
pgd_t *pgd;
pmd_t *pmd;
@@ -39,7 +39,7 @@ static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
return pte;
}
-static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
{
pgd_t *pgd;
pmd_t *pmd;
@@ -80,6 +80,20 @@ static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma,
}
}
+pte_t huge_ptep_get_and_clear(pte_t *ptep)
+{
+ pte_t entry;
+
+ entry = *ptep;
+
+ for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
+ pte_clear(pte);
+ pte++;
+ }
+
+ return entry;
+}
+
/*
* This function checks for proper alignment of input addr and len parameters.
*/
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 237f922520f..262e13d086f 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -264,7 +264,11 @@ config SUNOS_EMUL
want to run SunOS binaries on an Ultra you must also say Y to
"Kernel support for 32-bit a.out binaries" above.
-source "drivers/parport/Kconfig"
+source "mm/Kconfig"
+
+endmenu
+
+source "drivers/Kconfig"
config PRINTER
tristate "Parallel printer support"
@@ -291,6 +295,8 @@ config PRINTER
If you have more than 8 printers, you need to increase the LP_NO
macro in lp.c and the PARPORT_MAX macro in parport.h.
+source "mm/Kconfig"
+
endmenu
source "drivers/base/Kconfig"
@@ -372,18 +378,8 @@ config UNIX98_PTY_COUNT
endmenu
-source "drivers/input/Kconfig"
-
source "fs/Kconfig"
-source "sound/Kconfig"
-
-source "drivers/usb/Kconfig"
-
-source "drivers/infiniband/Kconfig"
-
-source "drivers/char/watchdog/Kconfig"
-
source "arch/sparc/Kconfig.debug"
source "security/Kconfig"
diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c
index a2dea69b2f0..ec2e05028a1 100644
--- a/arch/sparc/mm/init.c
+++ b/arch/sparc/mm/init.c
@@ -384,7 +384,6 @@ void map_high_region(unsigned long start_pfn, unsigned long end_pfn)
struct page *page = pfn_to_page(tmp);
ClearPageReserved(page);
- set_bit(PG_highmem, &page->flags);
set_page_count(page, 1);
__free_page(page);
totalhigh_pages++;
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index a72fd15d5ea..e2b050eb3b9 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -484,6 +484,8 @@ config CMDLINE
NOTE: This option WILL override the PROM bootargs setting!
+source "mm/Kconfig"
+
endmenu
source "drivers/base/Kconfig"
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index 7066d7ba667..bdac631cf01 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -6,7 +6,6 @@
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/kprobes.h>
-
#include <asm/kdebug.h>
#include <asm/signal.h>
@@ -47,25 +46,59 @@ void arch_copy_kprobe(struct kprobe *p)
{
p->ainsn.insn[0] = *p->addr;
p->ainsn.insn[1] = BREAKPOINT_INSTRUCTION_2;
+ p->opcode = *p->addr;
}
-void arch_remove_kprobe(struct kprobe *p)
+void arch_arm_kprobe(struct kprobe *p)
{
+ *p->addr = BREAKPOINT_INSTRUCTION;
+ flushi(p->addr);
}
-/* kprobe_status settings */
-#define KPROBE_HIT_ACTIVE 0x00000001
-#define KPROBE_HIT_SS 0x00000002
+void arch_disarm_kprobe(struct kprobe *p)
+{
+ *p->addr = p->opcode;
+ flushi(p->addr);
+}
+
+void arch_remove_kprobe(struct kprobe *p)
+{
+}
static struct kprobe *current_kprobe;
static unsigned long current_kprobe_orig_tnpc;
static unsigned long current_kprobe_orig_tstate_pil;
static unsigned int kprobe_status;
+static struct kprobe *kprobe_prev;
+static unsigned long kprobe_orig_tnpc_prev;
+static unsigned long kprobe_orig_tstate_pil_prev;
+static unsigned int kprobe_status_prev;
-static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+static inline void save_previous_kprobe(void)
+{
+ kprobe_status_prev = kprobe_status;
+ kprobe_orig_tnpc_prev = current_kprobe_orig_tnpc;
+ kprobe_orig_tstate_pil_prev = current_kprobe_orig_tstate_pil;
+ kprobe_prev = current_kprobe;
+}
+
+static inline void restore_previous_kprobe(void)
+{
+ kprobe_status = kprobe_status_prev;
+ current_kprobe_orig_tnpc = kprobe_orig_tnpc_prev;
+ current_kprobe_orig_tstate_pil = kprobe_orig_tstate_pil_prev;
+ current_kprobe = kprobe_prev;
+}
+
+static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs)
{
current_kprobe_orig_tnpc = regs->tnpc;
current_kprobe_orig_tstate_pil = (regs->tstate & TSTATE_PIL);
+ current_kprobe = p;
+}
+
+static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
regs->tstate |= TSTATE_PIL;
/*single step inline, if it a breakpoint instruction*/
@@ -78,17 +111,6 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
}
}
-static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs)
-{
- *p->addr = p->opcode;
- flushi(p->addr);
-
- regs->tpc = (unsigned long) p->addr;
- regs->tnpc = current_kprobe_orig_tnpc;
- regs->tstate = ((regs->tstate & ~TSTATE_PIL) |
- current_kprobe_orig_tstate_pil);
-}
-
static int kprobe_handler(struct pt_regs *regs)
{
struct kprobe *p;
@@ -109,8 +131,18 @@ static int kprobe_handler(struct pt_regs *regs)
unlock_kprobes();
goto no_kprobe;
}
- disarm_kprobe(p, regs);
- ret = 1;
+ /* We have reentered the kprobe_handler(), since
+ * another probe was hit while within the handler.
+ * We here save the original kprobes variables and
+ * just single step on the instruction of the new probe
+ * without calling any user handlers.
+ */
+ save_previous_kprobe();
+ set_current_kprobe(p, regs);
+ p->nmissed++;
+ kprobe_status = KPROBE_REENTER;
+ prepare_singlestep(p, regs);
+ return 1;
} else {
p = current_kprobe;
if (p->break_handler && p->break_handler(p, regs))
@@ -138,8 +170,8 @@ static int kprobe_handler(struct pt_regs *regs)
goto no_kprobe;
}
+ set_current_kprobe(p, regs);
kprobe_status = KPROBE_HIT_ACTIVE;
- current_kprobe = p;
if (p->pre_handler && p->pre_handler(p, regs))
return 1;
@@ -245,12 +277,20 @@ static inline int post_kprobe_handler(struct pt_regs *regs)
if (!kprobe_running())
return 0;
- if (current_kprobe->post_handler)
+ if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) {
+ kprobe_status = KPROBE_HIT_SSDONE;
current_kprobe->post_handler(current_kprobe, regs, 0);
+ }
resume_execution(current_kprobe, regs);
+ /*Restore back the original saved kprobes variables and continue. */
+ if (kprobe_status == KPROBE_REENTER) {
+ restore_previous_kprobe();
+ goto out;
+ }
unlock_kprobes();
+out:
preempt_enable_no_resched();
return 1;
@@ -392,3 +432,4 @@ int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
}
return 0;
}
+
diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c
index 292983413ae..2803bc7c2c7 100644
--- a/arch/sparc64/kernel/pci_iommu.c
+++ b/arch/sparc64/kernel/pci_iommu.c
@@ -8,6 +8,7 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mm.h>
+#include <linux/delay.h>
#include <asm/pbm.h>
@@ -195,6 +196,34 @@ static iopte_t *alloc_consistent_cluster(struct pci_iommu *iommu, unsigned long
return NULL;
}
+static int iommu_alloc_ctx(struct pci_iommu *iommu)
+{
+ int lowest = iommu->ctx_lowest_free;
+ int sz = IOMMU_NUM_CTXS - lowest;
+ int n = find_next_zero_bit(iommu->ctx_bitmap, sz, lowest);
+
+ if (unlikely(n == sz)) {
+ n = find_next_zero_bit(iommu->ctx_bitmap, lowest, 1);
+ if (unlikely(n == lowest)) {
+ printk(KERN_WARNING "IOMMU: Ran out of contexts.\n");
+ n = 0;
+ }
+ }
+ if (n)
+ __set_bit(n, iommu->ctx_bitmap);
+
+ return n;
+}
+
+static inline void iommu_free_ctx(struct pci_iommu *iommu, int ctx)
+{
+ if (likely(ctx)) {
+ __clear_bit(ctx, iommu->ctx_bitmap);
+ if (ctx < iommu->ctx_lowest_free)
+ iommu->ctx_lowest_free = ctx;
+ }
+}
+
/* Allocate and map kernel buffer of size SIZE using consistent mode
* DMA for PCI device PDEV. Return non-NULL cpu-side address if
* successful and set *DMA_ADDRP to the PCI side dma address.
@@ -235,7 +264,7 @@ void *pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_ad
npages = size >> IO_PAGE_SHIFT;
ctx = 0;
if (iommu->iommu_ctxflush)
- ctx = iommu->iommu_cur_ctx++;
+ ctx = iommu_alloc_ctx(iommu);
first_page = __pa(first_page);
while (npages--) {
iopte_val(*iopte) = (IOPTE_CONSISTENT(ctx) |
@@ -316,6 +345,8 @@ void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_
}
}
+ iommu_free_ctx(iommu, ctx);
+
spin_unlock_irqrestore(&iommu->lock, flags);
order = get_order(size);
@@ -359,7 +390,7 @@ dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direct
base_paddr = __pa(oaddr & IO_PAGE_MASK);
ctx = 0;
if (iommu->iommu_ctxflush)
- ctx = iommu->iommu_cur_ctx++;
+ ctx = iommu_alloc_ctx(iommu);
if (strbuf->strbuf_enabled)
iopte_protection = IOPTE_STREAMING(ctx);
else
@@ -379,6 +410,70 @@ bad:
return PCI_DMA_ERROR_CODE;
}
+static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages, int direction)
+{
+ int limit;
+
+ if (strbuf->strbuf_ctxflush &&
+ iommu->iommu_ctxflush) {
+ unsigned long matchreg, flushreg;
+ u64 val;
+
+ flushreg = strbuf->strbuf_ctxflush;
+ matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
+
+ pci_iommu_write(flushreg, ctx);
+ val = pci_iommu_read(matchreg);
+ val &= 0xffff;
+ if (!val)
+ goto do_flush_sync;
+
+ while (val) {
+ if (val & 0x1)
+ pci_iommu_write(flushreg, ctx);
+ val >>= 1;
+ }
+ val = pci_iommu_read(matchreg);
+ if (unlikely(val)) {
+ printk(KERN_WARNING "pci_strbuf_flush: ctx flush "
+ "timeout matchreg[%lx] ctx[%lx]\n",
+ val, ctx);
+ goto do_page_flush;
+ }
+ } else {
+ unsigned long i;
+
+ do_page_flush:
+ for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE)
+ pci_iommu_write(strbuf->strbuf_pflush, vaddr);
+ }
+
+do_flush_sync:
+ /* If the device could not have possibly put dirty data into
+ * the streaming cache, no flush-flag synchronization needs
+ * to be performed.
+ */
+ if (direction == PCI_DMA_TODEVICE)
+ return;
+
+ PCI_STC_FLUSHFLAG_INIT(strbuf);
+ pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
+ (void) pci_iommu_read(iommu->write_complete_reg);
+
+ limit = 100000;
+ while (!PCI_STC_FLUSHFLAG_SET(strbuf)) {
+ limit--;
+ if (!limit)
+ break;
+ udelay(1);
+ membar("#LoadLoad");
+ }
+ if (!limit)
+ printk(KERN_WARNING "pci_strbuf_flush: flushflag timeout "
+ "vaddr[%08x] ctx[%lx] npages[%ld]\n",
+ vaddr, ctx, npages);
+}
+
/* Unmap a single streaming mode DMA translation. */
void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction)
{
@@ -386,7 +481,7 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int
struct pci_iommu *iommu;
struct pci_strbuf *strbuf;
iopte_t *base;
- unsigned long flags, npages, i, ctx;
+ unsigned long flags, npages, ctx;
if (direction == PCI_DMA_NONE)
BUG();
@@ -414,29 +509,8 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int
ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
/* Step 1: Kick data out of streaming buffers if necessary. */
- if (strbuf->strbuf_enabled) {
- u32 vaddr = bus_addr;
-
- PCI_STC_FLUSHFLAG_INIT(strbuf);
- if (strbuf->strbuf_ctxflush &&
- iommu->iommu_ctxflush) {
- unsigned long matchreg, flushreg;
-
- flushreg = strbuf->strbuf_ctxflush;
- matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
- do {
- pci_iommu_write(flushreg, ctx);
- } while(((long)pci_iommu_read(matchreg)) < 0L);
- } else {
- for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE)
- pci_iommu_write(strbuf->strbuf_pflush, vaddr);
- }
-
- pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
- (void) pci_iommu_read(iommu->write_complete_reg);
- while (!PCI_STC_FLUSHFLAG_SET(strbuf))
- membar("#LoadLoad");
- }
+ if (strbuf->strbuf_enabled)
+ pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
/* Step 2: Clear out first TSB entry. */
iopte_make_dummy(iommu, base);
@@ -444,6 +518,8 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int
free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base,
npages, ctx);
+ iommu_free_ctx(iommu, ctx);
+
spin_unlock_irqrestore(&iommu->lock, flags);
}
@@ -583,7 +659,7 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int
/* Step 4: Choose a context if necessary. */
ctx = 0;
if (iommu->iommu_ctxflush)
- ctx = iommu->iommu_cur_ctx++;
+ ctx = iommu_alloc_ctx(iommu);
/* Step 5: Create the mappings. */
if (strbuf->strbuf_enabled)
@@ -647,29 +723,8 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems,
ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
/* Step 1: Kick data out of streaming buffers if necessary. */
- if (strbuf->strbuf_enabled) {
- u32 vaddr = (u32) bus_addr;
-
- PCI_STC_FLUSHFLAG_INIT(strbuf);
- if (strbuf->strbuf_ctxflush &&
- iommu->iommu_ctxflush) {
- unsigned long matchreg, flushreg;
-
- flushreg = strbuf->strbuf_ctxflush;
- matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
- do {
- pci_iommu_write(flushreg, ctx);
- } while(((long)pci_iommu_read(matchreg)) < 0L);
- } else {
- for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE)
- pci_iommu_write(strbuf->strbuf_pflush, vaddr);
- }
-
- pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
- (void) pci_iommu_read(iommu->write_complete_reg);
- while (!PCI_STC_FLUSHFLAG_SET(strbuf))
- membar("#LoadLoad");
- }
+ if (strbuf->strbuf_enabled)
+ pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
/* Step 2: Clear out first TSB entry. */
iopte_make_dummy(iommu, base);
@@ -677,6 +732,8 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems,
free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base,
npages, ctx);
+ iommu_free_ctx(iommu, ctx);
+
spin_unlock_irqrestore(&iommu->lock, flags);
}
@@ -715,28 +772,7 @@ void pci_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_addr, size
}
/* Step 2: Kick data out of streaming buffers. */
- PCI_STC_FLUSHFLAG_INIT(strbuf);
- if (iommu->iommu_ctxflush &&
- strbuf->strbuf_ctxflush) {
- unsigned long matchreg, flushreg;
-
- flushreg = strbuf->strbuf_ctxflush;
- matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
- do {
- pci_iommu_write(flushreg, ctx);
- } while(((long)pci_iommu_read(matchreg)) < 0L);
- } else {
- unsigned long i;
-
- for (i = 0; i < npages; i++, bus_addr += IO_PAGE_SIZE)
- pci_iommu_write(strbuf->strbuf_pflush, bus_addr);
- }
-
- /* Step 3: Perform flush synchronization sequence. */
- pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
- (void) pci_iommu_read(iommu->write_complete_reg);
- while (!PCI_STC_FLUSHFLAG_SET(strbuf))
- membar("#LoadLoad");
+ pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
spin_unlock_irqrestore(&iommu->lock, flags);
}
@@ -749,7 +785,8 @@ void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, i
struct pcidev_cookie *pcp;
struct pci_iommu *iommu;
struct pci_strbuf *strbuf;
- unsigned long flags, ctx;
+ unsigned long flags, ctx, npages, i;
+ u32 bus_addr;
pcp = pdev->sysdata;
iommu = pcp->pbm->iommu;
@@ -772,36 +809,14 @@ void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, i
}
/* Step 2: Kick data out of streaming buffers. */
- PCI_STC_FLUSHFLAG_INIT(strbuf);
- if (iommu->iommu_ctxflush &&
- strbuf->strbuf_ctxflush) {
- unsigned long matchreg, flushreg;
-
- flushreg = strbuf->strbuf_ctxflush;
- matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
- do {
- pci_iommu_write(flushreg, ctx);
- } while (((long)pci_iommu_read(matchreg)) < 0L);
- } else {
- unsigned long i, npages;
- u32 bus_addr;
-
- bus_addr = sglist[0].dma_address & IO_PAGE_MASK;
-
- for(i = 1; i < nelems; i++)
- if (!sglist[i].dma_length)
- break;
- i--;
- npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) - bus_addr) >> IO_PAGE_SHIFT;
- for (i = 0; i < npages; i++, bus_addr += IO_PAGE_SIZE)
- pci_iommu_write(strbuf->strbuf_pflush, bus_addr);
- }
-
- /* Step 3: Perform flush synchronization sequence. */
- pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
- (void) pci_iommu_read(iommu->write_complete_reg);
- while (!PCI_STC_FLUSHFLAG_SET(strbuf))
- membar("#LoadLoad");
+ bus_addr = sglist[0].dma_address & IO_PAGE_MASK;
+ for(i = 1; i < nelems; i++)
+ if (!sglist[i].dma_length)
+ break;
+ i--;
+ npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length)
+ - bus_addr) >> IO_PAGE_SHIFT;
+ pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
spin_unlock_irqrestore(&iommu->lock, flags);
}
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
index 3567fa879e1..534320ef0db 100644
--- a/arch/sparc64/kernel/pci_psycho.c
+++ b/arch/sparc64/kernel/pci_psycho.c
@@ -1212,7 +1212,7 @@ static void __init psycho_iommu_init(struct pci_controller_info *p)
/* Setup initial software IOMMU state. */
spin_lock_init(&iommu->lock);
- iommu->iommu_cur_ctx = 0;
+ iommu->ctx_lowest_free = 1;
/* Register addresses. */
iommu->iommu_control = p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL;
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
index 5525d1ec4af..53d333b4a4e 100644
--- a/arch/sparc64/kernel/pci_sabre.c
+++ b/arch/sparc64/kernel/pci_sabre.c
@@ -1265,7 +1265,7 @@ static void __init sabre_iommu_init(struct pci_controller_info *p,
/* Setup initial software IOMMU state. */
spin_lock_init(&iommu->lock);
- iommu->iommu_cur_ctx = 0;
+ iommu->ctx_lowest_free = 1;
/* Register addresses. */
iommu->iommu_control = p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL;
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c
index e93fcadc372..5753175b94e 100644
--- a/arch/sparc64/kernel/pci_schizo.c
+++ b/arch/sparc64/kernel/pci_schizo.c
@@ -1753,7 +1753,7 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
/* Setup initial software IOMMU state. */
spin_lock_init(&iommu->lock);
- iommu->iommu_cur_ctx = 0;
+ iommu->ctx_lowest_free = 1;
/* Register addresses, SCHIZO has iommu ctx flushing. */
iommu->iommu_control = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL;
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c
index 14d9c3a21b9..89f5e019f24 100644
--- a/arch/sparc64/kernel/sbus.c
+++ b/arch/sparc64/kernel/sbus.c
@@ -117,19 +117,42 @@ static void iommu_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages
#define STRBUF_TAG_VALID 0x02UL
-static void strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages)
+static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages, int direction)
{
- iommu->strbuf_flushflag = 0UL;
- while (npages--)
- upa_writeq(base + (npages << IO_PAGE_SHIFT),
+ unsigned long n;
+ int limit;
+
+ n = npages;
+ while (n--)
+ upa_writeq(base + (n << IO_PAGE_SHIFT),
iommu->strbuf_regs + STRBUF_PFLUSH);
+ /* If the device could not have possibly put dirty data into
+ * the streaming cache, no flush-flag synchronization needs
+ * to be performed.
+ */
+ if (direction == SBUS_DMA_TODEVICE)
+ return;
+
+ iommu->strbuf_flushflag = 0UL;
+
/* Whoopee cushion! */
upa_writeq(__pa(&iommu->strbuf_flushflag),
iommu->strbuf_regs + STRBUF_FSYNC);
upa_readq(iommu->sbus_control_reg);
- while (iommu->strbuf_flushflag == 0UL)
+
+ limit = 100000;
+ while (iommu->strbuf_flushflag == 0UL) {
+ limit--;
+ if (!limit)
+ break;
+ udelay(1);
membar("#LoadLoad");
+ }
+ if (!limit)
+ printk(KERN_WARNING "sbus_strbuf_flush: flushflag timeout "
+ "vaddr[%08x] npages[%ld]\n",
+ base, npages);
}
static iopte_t *alloc_streaming_cluster(struct sbus_iommu *iommu, unsigned long npages)
@@ -406,7 +429,7 @@ void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t dma_addr, size_t size,
spin_lock_irqsave(&iommu->lock, flags);
free_streaming_cluster(iommu, dma_base, size >> IO_PAGE_SHIFT);
- strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT);
+ sbus_strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT, direction);
spin_unlock_irqrestore(&iommu->lock, flags);
}
@@ -569,7 +592,7 @@ void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int
iommu = sdev->bus->iommu;
spin_lock_irqsave(&iommu->lock, flags);
free_streaming_cluster(iommu, dvma_base, size >> IO_PAGE_SHIFT);
- strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT);
+ sbus_strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT, direction);
spin_unlock_irqrestore(&iommu->lock, flags);
}
@@ -581,7 +604,7 @@ void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev, dma_addr_t base, size_t
size = (IO_PAGE_ALIGN(base + size) - (base & IO_PAGE_MASK));
spin_lock_irqsave(&iommu->lock, flags);
- strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT);
+ sbus_strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT, direction);
spin_unlock_irqrestore(&iommu->lock, flags);
}
@@ -605,7 +628,7 @@ void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev, struct scatterlist *sg, int
size = IO_PAGE_ALIGN(sg[i].dma_address + sg[i].dma_length) - base;
spin_lock_irqsave(&iommu->lock, flags);
- strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT);
+ sbus_strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT, direction);
spin_unlock_irqrestore(&iommu->lock, flags);
}
diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
index 12c3d84b746..b7e6a91952b 100644
--- a/arch/sparc64/kernel/setup.c
+++ b/arch/sparc64/kernel/setup.c
@@ -383,6 +383,17 @@ static void __init process_switch(char c)
/* Use PROM debug console. */
register_console(&prom_debug_console);
break;
+ case 'P':
+ /* Force UltraSPARC-III P-Cache on. */
+ if (tlb_type != cheetah) {
+ printk("BOOT: Ignoring P-Cache force option.\n");
+ break;
+ }
+ cheetah_pcache_forced_on = 1;
+ add_taint(TAINT_MACHINE_CHECK);
+ cheetah_enable_pcache();
+ break;
+
default:
printk("Unknown boot switch (-%c)\n", c);
break;
diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c
index 9a375e975cf..f28428f4170 100644
--- a/arch/sparc64/kernel/signal32.c
+++ b/arch/sparc64/kernel/signal32.c
@@ -102,7 +102,7 @@ typedef struct compat_siginfo{
/* POSIX.1b timers */
struct {
- timer_t _tid; /* timer id */
+ compat_timer_t _tid; /* timer id */
int _overrun; /* overrun count */
compat_sigval_t _sigval; /* same as below */
int _sys_private; /* not to be passed to user */
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 6dff06a44e7..e5b9c7a2778 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -123,6 +123,9 @@ void __init smp_callin(void)
smp_setup_percpu_timer();
+ if (cheetah_pcache_forced_on)
+ cheetah_enable_pcache();
+
local_irq_enable();
calibrate_delay();
diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
index 0077f02f4b3..5f8c822a2b4 100644
--- a/arch/sparc64/kernel/sys_sparc.c
+++ b/arch/sparc64/kernel/sys_sparc.c
@@ -84,6 +84,10 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi
return addr;
}
+ if (len <= mm->cached_hole_size) {
+ mm->cached_hole_size = 0;
+ mm->free_area_cache = TASK_UNMAPPED_BASE;
+ }
start_addr = addr = mm->free_area_cache;
task_size -= len;
@@ -103,6 +107,7 @@ full_search:
if (task_size < addr) {
if (start_addr != TASK_UNMAPPED_BASE) {
start_addr = addr = TASK_UNMAPPED_BASE;
+ mm->cached_hole_size = 0;
goto full_search;
}
return -ENOMEM;
@@ -114,6 +119,9 @@ full_search:
mm->free_area_cache = addr + len;
return addr;
}
+ if (addr + mm->cached_hole_size < vma->vm_start)
+ mm->cached_hole_size = vma->vm_start - addr;
+
addr = vma->vm_end;
if (do_color_align)
addr = COLOUR_ALIGN(addr, pgoff);
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index 56b203a2af6..a9f4596d7c2 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -421,6 +421,25 @@ asmlinkage void cee_log(unsigned long ce_status,
}
}
+int cheetah_pcache_forced_on;
+
+void cheetah_enable_pcache(void)
+{
+ unsigned long dcr;
+
+ printk("CHEETAH: Enabling P-Cache on cpu %d.\n",
+ smp_processor_id());
+
+ __asm__ __volatile__("ldxa [%%g0] %1, %0"
+ : "=r" (dcr)
+ : "i" (ASI_DCU_CONTROL_REG));
+ dcr |= (DCU_PE | DCU_HPE | DCU_SPE | DCU_SL);
+ __asm__ __volatile__("stxa %0, [%%g0] %1\n\t"
+ "membar #Sync"
+ : /* no outputs */
+ : "r" (dcr), "i" (ASI_DCU_CONTROL_REG));
+}
+
/* Cheetah error trap handling. */
static unsigned long ecache_flush_physbase;
static unsigned long ecache_flush_linesize;
diff --git a/arch/sparc64/lib/delay.c b/arch/sparc64/lib/delay.c
index f6b4c784d53..e8808727617 100644
--- a/arch/sparc64/lib/delay.c
+++ b/arch/sparc64/lib/delay.c
@@ -31,7 +31,7 @@ void __const_udelay(unsigned long n)
{
n *= 4;
- n *= (cpu_data(_smp_processor_id()).udelay_val * (HZ/4));
+ n *= (cpu_data(raw_smp_processor_id()).udelay_val * (HZ/4));
n >>= 32;
__delay(n + 1);
diff --git a/arch/sparc64/mm/hugetlbpage.c b/arch/sparc64/mm/hugetlbpage.c
index 5a1f831b2de..625cbb336a2 100644
--- a/arch/sparc64/mm/hugetlbpage.c
+++ b/arch/sparc64/mm/hugetlbpage.c
@@ -22,7 +22,7 @@
#include <asm/cacheflush.h>
#include <asm/mmu_context.h>
-static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
{
pgd_t *pgd;
pud_t *pud;
@@ -41,7 +41,7 @@ static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
return pte;
}
-static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
{
pgd_t *pgd;
pud_t *pud;
@@ -62,30 +62,34 @@ static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
#define mk_pte_huge(entry) do { pte_val(entry) |= _PAGE_SZHUGE; } while (0)
-static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma,
- unsigned long addr,
- struct page *page, pte_t * page_table, int write_access)
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t entry)
{
- unsigned long i;
- pte_t entry;
+ int i;
+
+ for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
+ set_pte_at(mm, addr, ptep, entry);
+ ptep++;
+ addr += PAGE_SIZE;
+ pte_val(entry) += PAGE_SIZE;
+ }
+}
- add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE);
+pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep)
+{
+ pte_t entry;
+ int i;
- if (write_access)
- entry = pte_mkwrite(pte_mkdirty(mk_pte(page,
- vma->vm_page_prot)));
- else
- entry = pte_wrprotect(mk_pte(page, vma->vm_page_prot));
- entry = pte_mkyoung(entry);
- mk_pte_huge(entry);
+ entry = *ptep;
for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
- set_pte_at(mm, addr, page_table, entry);
- page_table++;
+ pte_clear(mm, addr, ptep);
addr += PAGE_SIZE;
-
- pte_val(entry) += PAGE_SIZE;
+ ptep++;
}
+
+ return entry;
}
/*
@@ -100,79 +104,6 @@ int is_aligned_hugepage_range(unsigned long addr, unsigned long len)
return 0;
}
-int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
- struct vm_area_struct *vma)
-{
- pte_t *src_pte, *dst_pte, entry;
- struct page *ptepage;
- unsigned long addr = vma->vm_start;
- unsigned long end = vma->vm_end;
- int i;
-
- while (addr < end) {
- dst_pte = huge_pte_alloc(dst, addr);
- if (!dst_pte)
- goto nomem;
- src_pte = huge_pte_offset(src, addr);
- BUG_ON(!src_pte || pte_none(*src_pte));
- entry = *src_pte;
- ptepage = pte_page(entry);
- get_page(ptepage);
- for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
- set_pte_at(dst, addr, dst_pte, entry);
- pte_val(entry) += PAGE_SIZE;
- dst_pte++;
- addr += PAGE_SIZE;
- }
- add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
- }
- return 0;
-
-nomem:
- return -ENOMEM;
-}
-
-int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
- struct page **pages, struct vm_area_struct **vmas,
- unsigned long *position, int *length, int i)
-{
- unsigned long vaddr = *position;
- int remainder = *length;
-
- WARN_ON(!is_vm_hugetlb_page(vma));
-
- while (vaddr < vma->vm_end && remainder) {
- if (pages) {
- pte_t *pte;
- struct page *page;
-
- pte = huge_pte_offset(mm, vaddr);
-
- /* hugetlb should be locked, and hence, prefaulted */
- BUG_ON(!pte || pte_none(*pte));
-
- page = pte_page(*pte);
-
- WARN_ON(!PageCompound(page));
-
- get_page(page);
- pages[i] = page;
- }
-
- if (vmas)
- vmas[i] = vma;
-
- vaddr += PAGE_SIZE;
- --remainder;
- ++i;
- }
-
- *length = remainder;
- *position = vaddr;
-
- return i;
-}
-
struct page *follow_huge_addr(struct mm_struct *mm,
unsigned long address, int write)
{
@@ -190,34 +121,6 @@ struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
return NULL;
}
-void unmap_hugepage_range(struct vm_area_struct *vma,
- unsigned long start, unsigned long end)
-{
- struct mm_struct *mm = vma->vm_mm;
- unsigned long address;
- pte_t *pte;
- struct page *page;
- int i;
-
- BUG_ON(start & (HPAGE_SIZE - 1));
- BUG_ON(end & (HPAGE_SIZE - 1));
-
- for (address = start; address < end; address += HPAGE_SIZE) {
- pte = huge_pte_offset(mm, address);
- BUG_ON(!pte);
- if (pte_none(*pte))
- continue;
- page = pte_page(*pte);
- put_page(page);
- for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
- pte_clear(mm, address+(i*PAGE_SIZE), pte);
- pte++;
- }
- }
- add_mm_counter(mm, rss, -((end - start) >> PAGE_SHIFT));
- flush_tlb_range(vma, start, end);
-}
-
static void context_reload(void *__data)
{
struct mm_struct *mm = __data;
@@ -226,12 +129,8 @@ static void context_reload(void *__data)
load_secondary_context(mm);
}
-int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
+void hugetlb_prefault_arch_hook(struct mm_struct *mm)
{
- struct mm_struct *mm = current->mm;
- unsigned long addr;
- int ret = 0;
-
/* On UltraSPARC-III+ and later, configure the second half of
* the Data-TLB for huge pages.
*/
@@ -261,50 +160,4 @@ int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
}
spin_unlock(&ctx_alloc_lock);
}
-
- BUG_ON(vma->vm_start & ~HPAGE_MASK);
- BUG_ON(vma->vm_end & ~HPAGE_MASK);
-
- spin_lock(&mm->page_table_lock);
- for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
- unsigned long idx;
- pte_t *pte = huge_pte_alloc(mm, addr);
- struct page *page;
-
- if (!pte) {
- ret = -ENOMEM;
- goto out;
- }
- if (!pte_none(*pte))
- continue;
-
- idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
- + (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
- page = find_get_page(mapping, idx);
- if (!page) {
- /* charge the fs quota first */
- if (hugetlb_get_quota(mapping)) {
- ret = -ENOMEM;
- goto out;
- }
- page = alloc_huge_page();
- if (!page) {
- hugetlb_put_quota(mapping);
- ret = -ENOMEM;
- goto out;
- }
- ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
- if (! ret) {
- unlock_page(page);
- } else {
- hugetlb_put_quota(mapping);
- free_huge_page(page);
- goto out;
- }
- }
- set_huge_pte(mm, vma, addr, page, pte, vma->vm_flags & VM_WRITE);
- }
-out:
- spin_unlock(&mm->page_table_lock);
- return ret;
}
diff --git a/arch/sparc64/solaris/socket.c b/arch/sparc64/solaris/socket.c
index ec8e074c4ea..06740582717 100644
--- a/arch/sparc64/solaris/socket.c
+++ b/arch/sparc64/solaris/socket.c
@@ -317,8 +317,10 @@ asmlinkage int solaris_sendmsg(int fd, struct sol_nmsghdr __user *user_msg, unsi
unsigned long *kcmsg;
compat_size_t cmlen;
- if(kern_msg.msg_controllen > sizeof(ctl) &&
- kern_msg.msg_controllen <= 256) {
+ if (kern_msg.msg_controllen <= sizeof(compat_size_t))
+ return -EINVAL;
+
+ if(kern_msg.msg_controllen > sizeof(ctl)) {
err = -ENOBUFS;
ctl_buf = kmalloc(kern_msg.msg_controllen, GFP_KERNEL);
if(!ctl_buf)
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index c5292181a66..9469e77303e 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -35,6 +35,11 @@ config GENERIC_CALIBRATE_DELAY
bool
default y
+# Used in kernel/irq/manage.c and include/linux/irq.h
+config IRQ_RELEASE_METHOD
+ bool
+ default y
+
menu "UML-specific options"
config MODE_TT
@@ -69,6 +74,7 @@ config MODE_SKAS
option will shrink the UML binary slightly.
source "arch/um/Kconfig_arch"
+source "mm/Kconfig"
config LD_SCRIPT_STATIC
bool
diff --git a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug
index b89989de364..bd41e4286d0 100644
--- a/arch/um/Kconfig.debug
+++ b/arch/um/Kconfig.debug
@@ -2,10 +2,6 @@ menu "Kernel hacking"
source "lib/Kconfig.debug"
-config FRAME_POINTER
- bool
- default y if DEBUG_INFO
-
config PT_PROXY
bool "Enable ptrace proxy"
depends on XTERM_CHAN && DEBUG_INFO && MODE_TT
diff --git a/arch/um/Kconfig_char b/arch/um/Kconfig_char
index 3e50fdb6762..62d87b71179 100644
--- a/arch/um/Kconfig_char
+++ b/arch/um/Kconfig_char
@@ -204,5 +204,11 @@ config UML_RANDOM
http://sourceforge.net/projects/gkernel/). rngd periodically reads
/dev/hwrng and injects the entropy into /dev/random.
+config MMAPPER
+ tristate "iomem emulation driver"
+ help
+ This driver allows a host file to be used as emulated IO memory inside
+ UML.
+
endmenu
diff --git a/arch/um/Kconfig_x86_64 b/arch/um/Kconfig_x86_64
index fd8d7e8982b..f162f50f0b1 100644
--- a/arch/um/Kconfig_x86_64
+++ b/arch/um/Kconfig_x86_64
@@ -6,6 +6,10 @@ config 64BIT
bool
default y
+config TOP_ADDR
+ hex
+ default 0x80000000
+
config 3_LEVEL_PGTABLES
bool
default y
diff --git a/arch/um/Makefile b/arch/um/Makefile
index f2a0c40a920..3f073902351 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -122,7 +122,7 @@ endif
CPPFLAGS_vmlinux.lds = $(shell echo -U$(SUBARCH) \
-DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \
-DELF_FORMAT=\"$(ELF_FORMAT)\" $(CPP_MODE-y) \
- -DKERNEL_STACK_SIZE=$(STACK_SIZE))
+ -DKERNEL_STACK_SIZE=$(STACK_SIZE) -DSUBARCH=$(SUBARCH))
#The wrappers will select whether using "malloc" or the kernel allocator.
LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile
index 323f72c64cd..b2de9916c32 100644
--- a/arch/um/drivers/Makefile
+++ b/arch/um/drivers/Makefile
@@ -22,8 +22,8 @@ obj-y := stdio_console.o fd.o chan_kern.o chan_user.o line.o
obj-$(CONFIG_SSL) += ssl.o
obj-$(CONFIG_STDERR_CONSOLE) += stderr_console.o
-obj-$(CONFIG_UML_NET_SLIP) += slip.o
-obj-$(CONFIG_UML_NET_SLIRP) += slirp.o
+obj-$(CONFIG_UML_NET_SLIP) += slip.o slip_common.o
+obj-$(CONFIG_UML_NET_SLIRP) += slirp.o slip_common.o
obj-$(CONFIG_UML_NET_DAEMON) += daemon.o
obj-$(CONFIG_UML_NET_MCAST) += mcast.o
#obj-$(CONFIG_UML_NET_PCAP) += pcap.o $(PCAP)
@@ -41,6 +41,6 @@ obj-$(CONFIG_UML_WATCHDOG) += harddog.o
obj-$(CONFIG_BLK_DEV_COW_COMMON) += cow_user.o
obj-$(CONFIG_UML_RANDOM) += random.o
-USER_OBJS := fd.o null.o pty.o tty.o xterm.o
+USER_OBJS := fd.o null.o pty.o tty.o xterm.o slip_common.o
include arch/um/scripts/Makefile.rules
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 0150038af79..14a12d6b3df 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -20,9 +20,17 @@
#include "os.h"
#ifdef CONFIG_NOCONFIG_CHAN
+
+/* The printk's here are wrong because we are complaining that there is no
+ * output device, but printk is printing to that output device. The user will
+ * never see the error. printf would be better, except it can't run on a
+ * kernel stack because it will overflow it.
+ * Use printk for now since that will avoid crashing.
+ */
+
static void *not_configged_init(char *str, int device, struct chan_opts *opts)
{
- printf(KERN_ERR "Using a channel type which is configured out of "
+ printk(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
return(NULL);
}
@@ -30,27 +38,27 @@ static void *not_configged_init(char *str, int device, struct chan_opts *opts)
static int not_configged_open(int input, int output, int primary, void *data,
char **dev_out)
{
- printf(KERN_ERR "Using a channel type which is configured out of "
+ printk(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
return(-ENODEV);
}
static void not_configged_close(int fd, void *data)
{
- printf(KERN_ERR "Using a channel type which is configured out of "
+ printk(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
}
static int not_configged_read(int fd, char *c_out, void *data)
{
- printf(KERN_ERR "Using a channel type which is configured out of "
+ printk(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
return(-EIO);
}
static int not_configged_write(int fd, const char *buf, int len, void *data)
{
- printf(KERN_ERR "Using a channel type which is configured out of "
+ printk(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
return(-EIO);
}
@@ -58,7 +66,7 @@ static int not_configged_write(int fd, const char *buf, int len, void *data)
static int not_configged_console_write(int fd, const char *buf, int len,
void *data)
{
- printf(KERN_ERR "Using a channel type which is configured out of "
+ printk(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
return(-EIO);
}
@@ -66,7 +74,7 @@ static int not_configged_console_write(int fd, const char *buf, int len,
static int not_configged_window_size(int fd, void *data, unsigned short *rows,
unsigned short *cols)
{
- printf(KERN_ERR "Using a channel type which is configured out of "
+ printk(KERN_ERR "Using a channel type which is configured out of "
"UML\n");
return(-ENODEV);
}
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
index 583b8e137c3..5d3768156c9 100644
--- a/arch/um/drivers/chan_user.c
+++ b/arch/um/drivers/chan_user.c
@@ -143,22 +143,22 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out)
{
struct winch_data data;
unsigned long stack;
- int fds[2], pid, n, err;
+ int fds[2], n, err;
char c;
err = os_pipe(fds, 1, 1);
if(err < 0){
printk("winch_tramp : os_pipe failed, err = %d\n", -err);
- return(err);
+ goto out;
}
data = ((struct winch_data) { .pty_fd = fd,
.pipe_fd = fds[1],
.close_me = fds[0] } );
- pid = run_helper_thread(winch_thread, &data, 0, &stack, 0);
- if(pid < 0){
+ err = run_helper_thread(winch_thread, &data, 0, &stack, 0);
+ if(err < 0){
printk("fork of winch_thread failed - errno = %d\n", errno);
- return(pid);
+ goto out_close;
}
os_close_file(fds[1]);
@@ -168,14 +168,22 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out)
printk("winch_tramp : failed to read synchronization byte\n");
printk("read failed, err = %d\n", -n);
printk("fd %d will not support SIGWINCH\n", fd);
- *fd_out = -1;
+ err = -EINVAL;
+ goto out_close1;
}
- return(pid);
+ return err ;
+
+ out_close:
+ os_close_file(fds[1]);
+ out_close1:
+ os_close_file(fds[0]);
+ out:
+ return err;
}
void register_winch(int fd, struct tty_struct *tty)
{
- int pid, thread, thread_fd;
+ int pid, thread, thread_fd = -1;
int count;
char c = 1;
@@ -186,7 +194,7 @@ void register_winch(int fd, struct tty_struct *tty)
if(!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd,
tty) && (pid == -1)){
thread = winch_tramp(fd, tty, &thread_fd);
- if(fd != -1){
+ if(thread > 0){
register_winch_irq(thread_fd, fd, thread, tty);
count = os_write_file(thread_fd, &c, sizeof(c));
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c
index cf15b4a8b51..c1b03f7c1da 100644
--- a/arch/um/drivers/daemon_user.c
+++ b/arch/um/drivers/daemon_user.c
@@ -157,9 +157,9 @@ static void daemon_remove(void *data)
os_close_file(pri->fd);
os_close_file(pri->control);
- if(pri->data_addr != NULL) kfree(pri->data_addr);
- if(pri->ctl_addr != NULL) kfree(pri->ctl_addr);
- if(pri->local_addr != NULL) kfree(pri->local_addr);
+ kfree(pri->data_addr);
+ kfree(pri->ctl_addr);
+ kfree(pri->local_addr);
}
int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri)
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 025d3be8aca..2bb4c4f5dec 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -406,14 +406,12 @@ void line_disable(struct tty_struct *tty, int current_irq)
if(line->driver->read_irq == current_irq)
free_irq_later(line->driver->read_irq, tty);
else {
- free_irq_by_irq_and_dev(line->driver->read_irq, tty);
free_irq(line->driver->read_irq, tty);
}
if(line->driver->write_irq == current_irq)
free_irq_later(line->driver->write_irq, tty);
else {
- free_irq_by_irq_and_dev(line->driver->write_irq, tty);
free_irq(line->driver->write_irq, tty);
}
@@ -604,11 +602,26 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
return n;
}
-int line_remove(struct line *lines, unsigned int num, char *str)
+int line_id(char **str, int *start_out, int *end_out)
+{
+ char *end;
+ int n;
+
+ n = simple_strtoul(*str, &end, 0);
+ if((*end != '\0') || (end == *str))
+ return -1;
+
+ *str = end;
+ *start_out = n;
+ *end_out = n;
+ return n;
+}
+
+int line_remove(struct line *lines, unsigned int num, int n)
{
char config[sizeof("conxxxx=none\0")];
- sprintf(config, "%s=none", str);
+ sprintf(config, "%d=none", n);
return !line_setup(lines, num, config, 0);
}
@@ -758,7 +771,6 @@ static void unregister_winch(struct tty_struct *tty)
if(winch->pid != -1)
os_kill_process(winch->pid, 1);
- free_irq_by_irq_and_dev(WINCH_IRQ, winch);
free_irq(WINCH_IRQ, winch);
list_del(&winch->list);
kfree(winch);
diff --git a/arch/um/drivers/mcast_kern.c b/arch/um/drivers/mcast_kern.c
index faf714e87b5..217438cdef3 100644
--- a/arch/um/drivers/mcast_kern.c
+++ b/arch/um/drivers/mcast_kern.c
@@ -73,7 +73,6 @@ int mcast_setup(char *str, char **mac_out, void *data)
struct mcast_init *init = data;
char *port_str = NULL, *ttl_str = NULL, *remain;
char *last;
- int n;
*init = ((struct mcast_init)
{ .addr = "239.192.168.1",
@@ -89,13 +88,12 @@ int mcast_setup(char *str, char **mac_out, void *data)
}
if(port_str != NULL){
- n = simple_strtoul(port_str, &last, 10);
+ init->port = simple_strtoul(port_str, &last, 10);
if((*last != '\0') || (last == port_str)){
printk(KERN_ERR "mcast_setup - Bad port : '%s'\n",
port_str);
return(0);
}
- init->port = htons(n);
}
if(ttl_str != NULL){
diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c
index 0fe1d9fa913..7a0d115b29d 100644
--- a/arch/um/drivers/mcast_user.c
+++ b/arch/um/drivers/mcast_user.c
@@ -38,7 +38,7 @@ static struct sockaddr_in *new_addr(char *addr, unsigned short port)
}
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = in_aton(addr);
- sin->sin_port = port;
+ sin->sin_port = htons(port);
return(sin);
}
@@ -55,28 +55,25 @@ static int mcast_open(void *data)
struct mcast_data *pri = data;
struct sockaddr_in *sin = pri->mcast_addr;
struct ip_mreq mreq;
- int fd, yes = 1;
+ int fd = -EINVAL, yes = 1, err = -EINVAL;;
- if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) {
- fd = -EINVAL;
+ if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0))
goto out;
- }
fd = socket(AF_INET, SOCK_DGRAM, 0);
+
if (fd < 0){
printk("mcast_open : data socket failed, errno = %d\n",
errno);
- fd = -ENOMEM;
+ fd = -errno;
goto out;
}
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
printk("mcast_open: SO_REUSEADDR failed, errno = %d\n",
errno);
- os_close_file(fd);
- fd = -EINVAL;
- goto out;
+ goto out_close;
}
/* set ttl according to config */
@@ -84,26 +81,20 @@ static int mcast_open(void *data)
sizeof(pri->ttl)) < 0) {
printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n",
errno);
- os_close_file(fd);
- fd = -EINVAL;
- goto out;
+ goto out_close;
}
/* set LOOP, so data does get fed back to local sockets */
if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) {
printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n",
errno);
- os_close_file(fd);
- fd = -EINVAL;
- goto out;
+ goto out_close;
}
/* bind socket to mcast address */
if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) {
printk("mcast_open : data bind failed, errno = %d\n", errno);
- os_close_file(fd);
- fd = -EINVAL;
- goto out;
+ goto out_close;
}
/* subscribe to the multicast group */
@@ -117,12 +108,15 @@ static int mcast_open(void *data)
"interface on the host.\n");
printk("eth0 should be configured in order to use the "
"multicast transport.\n");
- os_close_file(fd);
- fd = -EINVAL;
+ goto out_close;
}
out:
- return(fd);
+ return fd;
+
+ out_close:
+ os_close_file(fd);
+ return err;
}
static void mcast_close(int fd, void *data)
@@ -164,14 +158,3 @@ struct net_user_info mcast_user_info = {
.delete_address = NULL,
.max_packet = MAX_PACKET - ETH_HEADER_OTHER
};
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index d7c7adcc0a6..404de41a4f6 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -419,8 +419,9 @@ void mconsole_config(struct mc_request *req)
void mconsole_remove(struct mc_request *req)
{
struct mc_device *dev;
- char *ptr = req->request.data;
- int err;
+ char *ptr = req->request.data, *err_msg = "";
+ char error[256];
+ int err, start, end, n;
ptr += strlen("remove");
while(isspace(*ptr)) ptr++;
@@ -429,8 +430,35 @@ void mconsole_remove(struct mc_request *req)
mconsole_reply(req, "Bad remove option", 1, 0);
return;
}
- err = (*dev->remove)(&ptr[strlen(dev->name)]);
- mconsole_reply(req, "", err, 0);
+
+ ptr = &ptr[strlen(dev->name)];
+
+ err = 1;
+ n = (*dev->id)(&ptr, &start, &end);
+ if(n < 0){
+ err_msg = "Couldn't parse device number";
+ goto out;
+ }
+ else if((n < start) || (n > end)){
+ sprintf(error, "Invalid device number - must be between "
+ "%d and %d", start, end);
+ err_msg = error;
+ goto out;
+ }
+
+ err = (*dev->remove)(n);
+ switch(err){
+ case -ENODEV:
+ err_msg = "Device doesn't exist";
+ break;
+ case -EBUSY:
+ err_msg = "Device is currently open";
+ break;
+ default:
+ break;
+ }
+ out:
+ mconsole_reply(req, err_msg, err, 0);
}
#ifdef CONFIG_MAGIC_SYSRQ
diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c
index a63231dffe0..a37a5ac13c2 100644
--- a/arch/um/drivers/mmapper_kern.c
+++ b/arch/um/drivers/mmapper_kern.c
@@ -18,6 +18,7 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
+#include <linux/miscdevice.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/pgtable.h>
@@ -117,24 +118,39 @@ static struct file_operations mmapper_fops = {
.release = mmapper_release,
};
+static struct miscdevice mmapper_dev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "mmapper",
+ .fops = &mmapper_fops
+};
+
static int __init mmapper_init(void)
{
+ int err;
+
printk(KERN_INFO "Mapper v0.1\n");
v_buf = (char *) find_iomem("mmapper", &mmapper_size);
if(mmapper_size == 0){
printk(KERN_ERR "mmapper_init - find_iomem failed\n");
- return(0);
+ goto out;
}
- p_buf = __pa(v_buf);
+ err = misc_register(&mmapper_dev);
+ if(err){
+ printk(KERN_ERR "mmapper - misc_register failed, err = %d\n",
+ err);
+ goto out;
+ }
- devfs_mk_cdev(MKDEV(30, 0), S_IFCHR|S_IRUGO|S_IWUGO, "mmapper");
- return(0);
+ p_buf = __pa(v_buf);
+out:
+ return 0;
}
static void mmapper_exit(void)
{
+ misc_deregister(&mmapper_dev);
}
module_init(mmapper_init);
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 4eeaf88c1e9..1495007bf6c 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -146,7 +146,6 @@ static int uml_net_close(struct net_device *dev)
netif_stop_queue(dev);
spin_lock(&lp->lock);
- free_irq_by_irq_and_dev(dev->irq, dev);
free_irq(dev->irq, dev);
if(lp->close != NULL)
(*lp->close)(lp->fd, &lp->user);
@@ -613,25 +612,35 @@ static int net_config(char *str)
return(err);
}
-static int net_remove(char *str)
+static int net_id(char **str, int *start_out, int *end_out)
+{
+ char *end;
+ int n;
+
+ n = simple_strtoul(*str, &end, 0);
+ if((*end != '\0') || (end == *str))
+ return -1;
+
+ *start_out = n;
+ *end_out = n;
+ *str = end;
+ return n;
+}
+
+static int net_remove(int n)
{
struct uml_net *device;
struct net_device *dev;
struct uml_net_private *lp;
- char *end;
- int n;
-
- n = simple_strtoul(str, &end, 0);
- if((*end != '\0') || (end == str))
- return(-1);
device = find_device(n);
if(device == NULL)
- return(0);
+ return -ENODEV;
dev = device->dev;
lp = dev->priv;
- if(lp->fd > 0) return(-1);
+ if(lp->fd > 0)
+ return -EBUSY;
if(lp->remove != NULL) (*lp->remove)(&lp->user);
unregister_netdev(dev);
platform_device_unregister(&device->pdev);
@@ -639,13 +648,14 @@ static int net_remove(char *str)
list_del(&device->list);
kfree(device);
free_netdev(dev);
- return(0);
+ return 0;
}
static struct mc_device net_mc = {
.name = "eth",
.config = net_config,
.get_config = NULL,
+ .id = net_id,
.remove = net_remove,
};
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index 47229fe4a81..3730d4f1271 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -32,7 +32,7 @@ int tap_open_common(void *dev, char *gate_addr)
return(0);
}
-void tap_check_ips(char *gate_addr, char *eth_addr)
+void tap_check_ips(char *gate_addr, unsigned char *eth_addr)
{
int tap_addr[4];
diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
index b5ee07472f7..c41efd207fc 100644
--- a/arch/um/drivers/port_kern.c
+++ b/arch/um/drivers/port_kern.c
@@ -257,7 +257,6 @@ int port_wait(void *data)
* connection. Then we loop here throwing out failed
* connections until a good one is found.
*/
- free_irq_by_irq_and_dev(TELNETD_IRQ, conn);
free_irq(TELNETD_IRQ, conn);
if(conn->fd >= 0) break;
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
index d43e9fab05a..f9e22198e01 100644
--- a/arch/um/drivers/random.c
+++ b/arch/um/drivers/random.c
@@ -1,5 +1,10 @@
-/* Much of this ripped from hw_random.c */
-
+/* Copyright (C) 2005 Jeff Dike <jdike@addtoit.com> */
+/* Much of this ripped from drivers/char/hw_random.c, see there for other
+ * copyright.
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by reference.
+ */
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
@@ -12,8 +17,6 @@
*/
#define RNG_VERSION "1.0.0"
#define RNG_MODULE_NAME "random"
-#define RNG_DRIVER_NAME RNG_MODULE_NAME " virtual driver " RNG_VERSION
-#define PFX RNG_MODULE_NAME ": "
#define RNG_MISCDEV_MINOR 183 /* official */
@@ -98,7 +101,7 @@ static int __init rng_init (void)
err = misc_register (&rng_miscdev);
if (err) {
- printk (KERN_ERR PFX "misc device register failed\n");
+ printk (KERN_ERR RNG_MODULE_NAME ": misc device register failed\n");
goto err_out_cleanup_hw;
}
@@ -120,3 +123,6 @@ static void __exit rng_cleanup (void)
module_init (rng_init);
module_exit (rng_cleanup);
+
+MODULE_DESCRIPTION("UML Host Random Number Generator (RNG) driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/um/drivers/slip.h b/arch/um/drivers/slip.h
index 495f2f1b142..bb0dab41c2e 100644
--- a/arch/um/drivers/slip.h
+++ b/arch/um/drivers/slip.h
@@ -1,10 +1,7 @@
#ifndef __UM_SLIP_H
#define __UM_SLIP_H
-#define BUF_SIZE 1500
- /* two bytes each for a (pathological) max packet of escaped chars + *
- * terminating END char + initial END char */
-#define ENC_BUF_SIZE (2 * BUF_SIZE + 2)
+#include "slip_common.h"
struct slip_data {
void *dev;
@@ -12,28 +9,12 @@ struct slip_data {
char *addr;
char *gate_addr;
int slave;
- char ibuf[ENC_BUF_SIZE];
- char obuf[ENC_BUF_SIZE];
- int more; /* more data: do not read fd until ibuf has been drained */
- int pos;
- int esc;
+ struct slip_proto slip;
};
extern struct net_user_info slip_user_info;
-extern int set_umn_addr(int fd, char *addr, char *ptp_addr);
extern int slip_user_read(int fd, void *buf, int len, struct slip_data *pri);
extern int slip_user_write(int fd, void *buf, int len, struct slip_data *pri);
#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/slip_common.c b/arch/um/drivers/slip_common.c
new file mode 100644
index 00000000000..e89cfc68fc3
--- /dev/null
+++ b/arch/um/drivers/slip_common.c
@@ -0,0 +1,54 @@
+#include <string.h>
+#include "slip_common.h"
+#include "net_user.h"
+
+int slip_proto_read(int fd, void *buf, int len, struct slip_proto *slip)
+{
+ int i, n, size, start;
+
+ if(slip->more > 0){
+ i = 0;
+ while(i < slip->more){
+ size = slip_unesc(slip->ibuf[i++], slip->ibuf,
+ &slip->pos, &slip->esc);
+ if(size){
+ memcpy(buf, slip->ibuf, size);
+ memmove(slip->ibuf, &slip->ibuf[i],
+ slip->more - i);
+ slip->more = slip->more - i;
+ return size;
+ }
+ }
+ slip->more = 0;
+ }
+
+ n = net_read(fd, &slip->ibuf[slip->pos],
+ sizeof(slip->ibuf) - slip->pos);
+ if(n <= 0)
+ return n;
+
+ start = slip->pos;
+ for(i = 0; i < n; i++){
+ size = slip_unesc(slip->ibuf[start + i], slip->ibuf,&slip->pos,
+ &slip->esc);
+ if(size){
+ memcpy(buf, slip->ibuf, size);
+ memmove(slip->ibuf, &slip->ibuf[start+i+1],
+ n - (i + 1));
+ slip->more = n - (i + 1);
+ return size;
+ }
+ }
+ return 0;
+}
+
+int slip_proto_write(int fd, void *buf, int len, struct slip_proto *slip)
+{
+ int actual, n;
+
+ actual = slip_esc(buf, slip->obuf, len);
+ n = net_write(fd, slip->obuf, actual);
+ if(n < 0)
+ return n;
+ else return len;
+}
diff --git a/arch/um/drivers/slip_proto.h b/arch/um/drivers/slip_common.h
index 7206361ace4..2ae76d8f1be 100644
--- a/arch/um/drivers/slip_proto.h
+++ b/arch/um/drivers/slip_common.h
@@ -1,10 +1,10 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
+#ifndef __UM_SLIP_COMMON_H
+#define __UM_SLIP_COMMON_H
-#ifndef __UM_SLIP_PROTO_H__
-#define __UM_SLIP_PROTO_H__
+#define BUF_SIZE 1500
+ /* two bytes each for a (pathological) max packet of escaped chars + *
+ * terminating END char + initial END char */
+#define ENC_BUF_SIZE (2 * BUF_SIZE + 2)
/* SLIP protocol characters. */
#define SLIP_END 0300 /* indicates end of frame */
@@ -12,7 +12,8 @@
#define SLIP_ESC_END 0334 /* ESC ESC_END means END 'data' */
#define SLIP_ESC_ESC 0335 /* ESC ESC_ESC means ESC 'data' */
-static inline int slip_unesc(unsigned char c,char *buf,int *pos, int *esc)
+static inline int slip_unesc(unsigned char c, unsigned char *buf, int *pos,
+ int *esc)
{
int ret;
@@ -79,15 +80,25 @@ static inline int slip_esc(unsigned char *s, unsigned char *d, int len)
return (ptr - d);
}
-#endif
+struct slip_proto {
+ unsigned char ibuf[ENC_BUF_SIZE];
+ unsigned char obuf[ENC_BUF_SIZE];
+ int more; /* more data: do not read fd until ibuf has been drained */
+ int pos;
+ int esc;
+};
+
+#define SLIP_PROTO_INIT { \
+ .ibuf = { '\0' }, \
+ .obuf = { '\0' }, \
+ .more = 0, \
+ .pos = 0, \
+ .esc = 0 \
+}
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+extern int slip_proto_read(int fd, void *buf, int len,
+ struct slip_proto *slip);
+extern int slip_proto_write(int fd, void *buf, int len,
+ struct slip_proto *slip);
+
+#endif
diff --git a/arch/um/drivers/slip_kern.c b/arch/um/drivers/slip_kern.c
index 0886eedba21..9a6f5c85f90 100644
--- a/arch/um/drivers/slip_kern.c
+++ b/arch/um/drivers/slip_kern.c
@@ -26,16 +26,16 @@ void slip_init(struct net_device *dev, void *data)
.addr = NULL,
.gate_addr = init->gate_addr,
.slave = -1,
- .ibuf = { '\0' },
- .obuf = { '\0' },
- .pos = 0,
- .esc = 0,
+ .slip = SLIP_PROTO_INIT,
.dev = dev });
dev->init = NULL;
+ dev->header_cache_update = NULL;
+ dev->hard_header_cache = NULL;
+ dev->hard_header = NULL;
dev->hard_header_len = 0;
- dev->addr_len = 4;
- dev->type = ARPHRD_ETHER;
+ dev->addr_len = 0;
+ dev->type = ARPHRD_SLIP;
dev->tx_queue_len = 256;
dev->flags = IFF_NOARP;
printk("SLIP backend - SLIP IP = %s\n", spri->gate_addr);
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index d94846b1b4c..71af444e591 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -13,7 +13,7 @@
#include "user.h"
#include "net_user.h"
#include "slip.h"
-#include "slip_proto.h"
+#include "slip_common.h"
#include "helper.h"
#include "os.h"
@@ -77,41 +77,51 @@ static int slip_tramp(char **argv, int fd)
err = os_pipe(fds, 1, 0);
if(err < 0){
printk("slip_tramp : pipe failed, err = %d\n", -err);
- return(err);
+ goto out;
}
err = 0;
pe_data.stdin = fd;
pe_data.stdout = fds[1];
pe_data.close_me = fds[0];
- pid = run_helper(slip_pre_exec, &pe_data, argv, NULL);
+ err = run_helper(slip_pre_exec, &pe_data, argv, NULL);
+ if(err < 0)
+ goto out_close;
+ pid = err;
+
+ output_len = page_size();
+ output = um_kmalloc(output_len);
+ if(output == NULL){
+ printk("slip_tramp : failed to allocate output buffer\n");
+ os_kill_process(pid, 1);
+ err = -ENOMEM;
+ goto out_free;
+ }
- if(pid < 0) err = pid;
- else {
- output_len = page_size();
- output = um_kmalloc(output_len);
- if(output == NULL)
- printk("slip_tramp : failed to allocate output "
- "buffer\n");
-
- os_close_file(fds[1]);
- read_output(fds[0], output, output_len);
- if(output != NULL){
- printk("%s", output);
- kfree(output);
- }
- CATCH_EINTR(err = waitpid(pid, &status, 0));
- if(err < 0)
- err = errno;
- else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)){
- printk("'%s' didn't exit with status 0\n", argv[0]);
- err = -EINVAL;
- }
+ os_close_file(fds[1]);
+ read_output(fds[0], output, output_len);
+ printk("%s", output);
+
+ CATCH_EINTR(err = waitpid(pid, &status, 0));
+ if(err < 0)
+ err = errno;
+ else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)){
+ printk("'%s' didn't exit with status 0\n", argv[0]);
+ err = -EINVAL;
}
+ else err = 0;
os_close_file(fds[0]);
- return(err);
+out_free:
+ kfree(output);
+ return err;
+
+out_close:
+ os_close_file(fds[0]);
+ os_close_file(fds[1]);
+out:
+ return err;
}
static int slip_open(void *data)
@@ -123,21 +133,26 @@ static int slip_open(void *data)
NULL };
int sfd, mfd, err;
- mfd = get_pty();
- if(mfd < 0){
- printk("umn : Failed to open pty, err = %d\n", -mfd);
- return(mfd);
+ err = get_pty();
+ if(err < 0){
+ printk("slip-open : Failed to open pty, err = %d\n", -err);
+ goto out;
}
- sfd = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0);
- if(sfd < 0){
- printk("Couldn't open tty for slip line, err = %d\n", -sfd);
- os_close_file(mfd);
- return(sfd);
+ mfd = err;
+
+ err = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0);
+ if(err < 0){
+ printk("Couldn't open tty for slip line, err = %d\n", -err);
+ goto out_close;
}
- if(set_up_tty(sfd)) return(-1);
+ sfd = err;
+
+ if(set_up_tty(sfd))
+ goto out_close2;
+
pri->slave = sfd;
- pri->pos = 0;
- pri->esc = 0;
+ pri->slip.pos = 0;
+ pri->slip.esc = 0;
if(pri->gate_addr != NULL){
sprintf(version_buf, "%d", UML_NET_VERSION);
strcpy(gate_buf, pri->gate_addr);
@@ -146,12 +161,12 @@ static int slip_open(void *data)
if(err < 0){
printk("slip_tramp failed - err = %d\n", -err);
- return(err);
+ goto out_close2;
}
err = os_get_ifname(pri->slave, pri->name);
if(err < 0){
printk("get_ifname failed, err = %d\n", -err);
- return(err);
+ goto out_close2;
}
iter_addresses(pri->dev, open_addr, pri->name);
}
@@ -160,10 +175,16 @@ static int slip_open(void *data)
if(err < 0){
printk("Failed to set slip discipline encapsulation - "
"err = %d\n", -err);
- return(err);
+ goto out_close2;
}
}
return(mfd);
+out_close2:
+ os_close_file(sfd);
+out_close:
+ os_close_file(mfd);
+out:
+ return err;
}
static void slip_close(int fd, void *data)
@@ -190,48 +211,12 @@ static void slip_close(int fd, void *data)
int slip_user_read(int fd, void *buf, int len, struct slip_data *pri)
{
- int i, n, size, start;
-
- if(pri->more>0) {
- i = 0;
- while(i < pri->more) {
- size = slip_unesc(pri->ibuf[i++],
- pri->ibuf, &pri->pos, &pri->esc);
- if(size){
- memcpy(buf, pri->ibuf, size);
- memmove(pri->ibuf, &pri->ibuf[i], pri->more-i);
- pri->more=pri->more-i;
- return(size);
- }
- }
- pri->more=0;
- }
-
- n = net_read(fd, &pri->ibuf[pri->pos], sizeof(pri->ibuf) - pri->pos);
- if(n <= 0) return(n);
-
- start = pri->pos;
- for(i = 0; i < n; i++){
- size = slip_unesc(pri->ibuf[start + i],
- pri->ibuf, &pri->pos, &pri->esc);
- if(size){
- memcpy(buf, pri->ibuf, size);
- memmove(pri->ibuf, &pri->ibuf[start+i+1], n-(i+1));
- pri->more=n-(i+1);
- return(size);
- }
- }
- return(0);
+ return slip_proto_read(fd, buf, len, &pri->slip);
}
int slip_user_write(int fd, void *buf, int len, struct slip_data *pri)
{
- int actual, n;
-
- actual = slip_esc(buf, pri->obuf, len);
- n = net_write(fd, pri->obuf, actual);
- if(n < 0) return(n);
- else return(len);
+ return slip_proto_write(fd, buf, len, &pri->slip);
}
static int slip_set_mtu(int mtu, void *data)
@@ -267,14 +252,3 @@ struct net_user_info slip_user_info = {
.delete_address = slip_del_addr,
.max_packet = BUF_SIZE
};
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/slirp.h b/arch/um/drivers/slirp.h
index 04e407d1e44..6cf88ab580c 100644
--- a/arch/um/drivers/slirp.h
+++ b/arch/um/drivers/slirp.h
@@ -1,10 +1,7 @@
#ifndef __UM_SLIRP_H
#define __UM_SLIRP_H
-#define BUF_SIZE 1500
- /* two bytes each for a (pathological) max packet of escaped chars + *
- * terminating END char + initial END char */
-#define ENC_BUF_SIZE (2 * BUF_SIZE + 2)
+#include "slip_common.h"
#define SLIRP_MAX_ARGS 100
/*
@@ -24,28 +21,13 @@ struct slirp_data {
struct arg_list_dummy_wrapper argw;
int pid;
int slave;
- char ibuf[ENC_BUF_SIZE];
- char obuf[ENC_BUF_SIZE];
- int more; /* more data: do not read fd until ibuf has been drained */
- int pos;
- int esc;
+ struct slip_proto slip;
};
extern struct net_user_info slirp_user_info;
-extern int set_umn_addr(int fd, char *addr, char *ptp_addr);
extern int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri);
-extern int slirp_user_write(int fd, void *buf, int len, struct slirp_data *pri);
+extern int slirp_user_write(int fd, void *buf, int len,
+ struct slirp_data *pri);
#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/slirp_kern.c b/arch/um/drivers/slirp_kern.c
index c9d6b52a831..9864d27afdb 100644
--- a/arch/um/drivers/slirp_kern.c
+++ b/arch/um/drivers/slirp_kern.c
@@ -25,10 +25,7 @@ void slirp_init(struct net_device *dev, void *data)
{ .argw = init->argw,
.pid = -1,
.slave = -1,
- .ibuf = { '\0' },
- .obuf = { '\0' },
- .pos = 0,
- .esc = 0,
+ .slip = SLIP_PROTO_INIT,
.dev = dev });
dev->init = NULL;
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c
index c322515c71c..8d91f663d82 100644
--- a/arch/um/drivers/slirp_user.c
+++ b/arch/um/drivers/slirp_user.c
@@ -12,7 +12,7 @@
#include "user.h"
#include "net_user.h"
#include "slirp.h"
-#include "slip_proto.h"
+#include "slip_common.h"
#include "helper.h"
#include "os.h"
@@ -48,47 +48,32 @@ static int slirp_tramp(char **argv, int fd)
return(pid);
}
-/* XXX This is just a trivial wrapper around os_pipe */
-static int slirp_datachan(int *mfd, int *sfd)
-{
- int fds[2], err;
-
- err = os_pipe(fds, 1, 1);
- if(err < 0){
- printk("slirp_datachan: Failed to open pipe, err = %d\n", -err);
- return(err);
- }
-
- *mfd = fds[0];
- *sfd = fds[1];
- return(0);
-}
-
static int slirp_open(void *data)
{
struct slirp_data *pri = data;
- int sfd, mfd, pid, err;
+ int fds[2], pid, err;
- err = slirp_datachan(&mfd, &sfd);
+ err = os_pipe(fds, 1, 1);
if(err)
return(err);
- pid = slirp_tramp(pri->argw.argv, sfd);
-
- if(pid < 0){
- printk("slirp_tramp failed - errno = %d\n", -pid);
- os_close_file(sfd);
- os_close_file(mfd);
- return(pid);
+ err = slirp_tramp(pri->argw.argv, fds[1]);
+ if(err < 0){
+ printk("slirp_tramp failed - errno = %d\n", -err);
+ goto out;
}
-
- pri->slave = sfd;
- pri->pos = 0;
- pri->esc = 0;
-
- pri->pid = pid;
-
- return(mfd);
+ pid = err;
+
+ pri->slave = fds[1];
+ pri->slip.pos = 0;
+ pri->slip.esc = 0;
+ pri->pid = err;
+
+ return(fds[0]);
+out:
+ os_close_file(fds[0]);
+ os_close_file(fds[1]);
+ return err;
}
static void slirp_close(int fd, void *data)
@@ -129,48 +114,12 @@ static void slirp_close(int fd, void *data)
int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri)
{
- int i, n, size, start;
-
- if(pri->more>0) {
- i = 0;
- while(i < pri->more) {
- size = slip_unesc(pri->ibuf[i++],
- pri->ibuf,&pri->pos,&pri->esc);
- if(size){
- memcpy(buf, pri->ibuf, size);
- memmove(pri->ibuf, &pri->ibuf[i], pri->more-i);
- pri->more=pri->more-i;
- return(size);
- }
- }
- pri->more=0;
- }
-
- n = net_read(fd, &pri->ibuf[pri->pos], sizeof(pri->ibuf) - pri->pos);
- if(n <= 0) return(n);
-
- start = pri->pos;
- for(i = 0; i < n; i++){
- size = slip_unesc(pri->ibuf[start + i],
- pri->ibuf,&pri->pos,&pri->esc);
- if(size){
- memcpy(buf, pri->ibuf, size);
- memmove(pri->ibuf, &pri->ibuf[start+i+1], n-(i+1));
- pri->more=n-(i+1);
- return(size);
- }
- }
- return(0);
+ return slip_proto_read(fd, buf, len, &pri->slip);
}
int slirp_user_write(int fd, void *buf, int len, struct slirp_data *pri)
{
- int actual, n;
-
- actual = slip_esc(buf, pri->obuf, len);
- n = net_write(fd, pri->obuf, actual);
- if(n < 0) return(n);
- else return(len);
+ return slip_proto_write(fd, buf, len, &pri->slip);
}
static int slirp_set_mtu(int mtu, void *data)
@@ -188,14 +137,3 @@ struct net_user_info slirp_user_info = {
.delete_address = NULL,
.max_packet = BUF_SIZE
};
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index a2bac429f3d..62e04ecfada 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -22,7 +22,6 @@
#include "init.h"
#include "irq_user.h"
#include "mconsole_kern.h"
-#include "2_5compat.h"
static int ssl_version = 1;
@@ -50,7 +49,7 @@ static struct chan_opts opts = {
static int ssl_config(char *str);
static int ssl_get_config(char *dev, char *str, int size, char **error_out);
-static int ssl_remove(char *str);
+static int ssl_remove(int n);
static struct line_driver driver = {
.name = "UML serial line",
@@ -70,6 +69,7 @@ static struct line_driver driver = {
.name = "ssl",
.config = ssl_config,
.get_config = ssl_get_config,
+ .id = line_id,
.remove = ssl_remove,
},
};
@@ -95,10 +95,10 @@ static int ssl_get_config(char *dev, char *str, int size, char **error_out)
str, size, error_out));
}
-static int ssl_remove(char *str)
+static int ssl_remove(int n)
{
- return(line_remove(serial_lines,
- sizeof(serial_lines)/sizeof(serial_lines[0]), str));
+ return line_remove(serial_lines,
+ sizeof(serial_lines)/sizeof(serial_lines[0]), n);
}
int ssl_open(struct tty_struct *tty, struct file *filp)
diff --git a/arch/um/drivers/stderr_console.c b/arch/um/drivers/stderr_console.c
index 98565b53d17..429ae8e6c7e 100644
--- a/arch/um/drivers/stderr_console.c
+++ b/arch/um/drivers/stderr_console.c
@@ -22,9 +22,9 @@ static void stderr_console_write(struct console *console, const char *string,
}
static struct console stderr_console = {
- .name "stderr",
- .write stderr_console_write,
- .flags CON_PRINTBUFFER,
+ .name = "stderr",
+ .write = stderr_console_write,
+ .flags = CON_PRINTBUFFER,
};
static int __init stderr_console_init(void)
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 361d0be342b..005aa6333b6 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -28,7 +28,6 @@
#include "irq_user.h"
#include "mconsole_kern.h"
#include "init.h"
-#include "2_5compat.h"
#define MAX_TTYS (16)
@@ -56,7 +55,7 @@ static struct chan_opts opts = {
static int con_config(char *str);
static int con_get_config(char *dev, char *str, int size, char **error_out);
-static int con_remove(char *str);
+static int con_remove(int n);
static struct line_driver driver = {
.name = "UML console",
@@ -76,6 +75,7 @@ static struct line_driver driver = {
.name = "con",
.config = con_config,
.get_config = con_get_config,
+ .id = line_id,
.remove = con_remove,
},
};
@@ -100,9 +100,9 @@ static int con_get_config(char *dev, char *str, int size, char **error_out)
size, error_out));
}
-static int con_remove(char *str)
+static int con_remove(int n)
{
- return(line_remove(vts, sizeof(vts)/sizeof(vts[0]), str));
+ return line_remove(vts, sizeof(vts)/sizeof(vts[0]), n);
}
static int con_open(struct tty_struct *tty, struct file *filp)
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 9a56ff94308..344b24d09a7 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -49,13 +49,12 @@
#include "irq_user.h"
#include "irq_kern.h"
#include "ubd_user.h"
-#include "2_5compat.h"
#include "os.h"
#include "mem.h"
#include "mem_kern.h"
#include "cow.h"
-enum ubd_req { UBD_READ, UBD_WRITE, UBD_MMAP };
+enum ubd_req { UBD_READ, UBD_WRITE };
struct io_thread_req {
enum ubd_req op;
@@ -68,8 +67,6 @@ struct io_thread_req {
unsigned long sector_mask;
unsigned long long cow_offset;
unsigned long bitmap_words[2];
- int map_fd;
- unsigned long long map_offset;
int error;
};
@@ -122,10 +119,6 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
#define MAX_DEV (8)
-/* Changed in early boot */
-static int ubd_do_mmap = 0;
-#define UBD_MMAP_BLOCK_SIZE PAGE_SIZE
-
static struct block_device_operations ubd_blops = {
.owner = THIS_MODULE,
.open = ubd_open,
@@ -175,12 +168,6 @@ struct ubd {
int no_cow;
struct cow cow;
struct platform_device pdev;
-
- int map_writes;
- int map_reads;
- int nomap_writes;
- int nomap_reads;
- int write_maps;
};
#define DEFAULT_COW { \
@@ -200,11 +187,6 @@ struct ubd {
.openflags = OPEN_FLAGS, \
.no_cow = 0, \
.cow = DEFAULT_COW, \
- .map_writes = 0, \
- .map_reads = 0, \
- .nomap_writes = 0, \
- .nomap_reads = 0, \
- .write_maps = 0, \
}
struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD };
@@ -314,13 +296,6 @@ static int ubd_setup_common(char *str, int *index_out)
int major;
str++;
- if(!strcmp(str, "mmap")){
- CHOOSE_MODE(printk("mmap not supported by the ubd "
- "driver in tt mode\n"),
- ubd_do_mmap = 1);
- return(0);
- }
-
if(!strcmp(str, "sync")){
global_openflags = of_sync(global_openflags);
return(0);
@@ -464,9 +439,9 @@ static int udb_setup(char *str)
__setup("udb", udb_setup);
__uml_help(udb_setup,
"udb\n"
-" This option is here solely to catch ubd -> udb typos, which can be\n\n"
-" to impossible to catch visually unless you specifically look for\n\n"
-" them. The only result of any option starting with 'udb' is an error\n\n"
+" This option is here solely to catch ubd -> udb typos, which can be\n"
+" to impossible to catch visually unless you specifically look for\n"
+" them. The only result of any option starting with 'udb' is an error\n"
" in the boot output.\n\n"
);
@@ -524,7 +499,7 @@ static void ubd_handler(void)
{
struct io_thread_req req;
struct request *rq = elv_next_request(ubd_queue);
- int n, err;
+ int n;
do_ubd = NULL;
intr_count++;
@@ -538,19 +513,6 @@ static void ubd_handler(void)
return;
}
- if((req.op != UBD_MMAP) &&
- ((req.offset != ((__u64) (rq->sector)) << 9) ||
- (req.length != (rq->current_nr_sectors) << 9)))
- panic("I/O op mismatch");
-
- if(req.map_fd != -1){
- err = physmem_subst_mapping(req.buffer, req.map_fd,
- req.map_offset, 1);
- if(err)
- printk("ubd_handler - physmem_subst_mapping failed, "
- "err = %d\n", -err);
- }
-
ubd_finish(rq, req.error);
reactivate_fd(thread_fd, UBD_IRQ);
do_ubd_request(ubd_queue);
@@ -583,14 +545,10 @@ static int ubd_file_size(struct ubd *dev, __u64 *size_out)
static void ubd_close(struct ubd *dev)
{
- if(ubd_do_mmap)
- physmem_forget_descriptor(dev->fd);
os_close_file(dev->fd);
if(dev->cow.file == NULL)
return;
- if(ubd_do_mmap)
- physmem_forget_descriptor(dev->cow.fd);
os_close_file(dev->cow.fd);
vfree(dev->cow.bitmap);
dev->cow.bitmap = NULL;
@@ -796,24 +754,34 @@ static int ubd_get_config(char *name, char *str, int size, char **error_out)
return(len);
}
-static int ubd_remove(char *str)
+static int ubd_id(char **str, int *start_out, int *end_out)
+{
+ int n;
+
+ n = parse_unit(str);
+ *start_out = 0;
+ *end_out = MAX_DEV - 1;
+ return n;
+}
+
+static int ubd_remove(int n)
{
struct ubd *dev;
- int n, err = -ENODEV;
+ int err = -ENODEV;
- n = parse_unit(&str);
+ spin_lock(&ubd_lock);
- if((n < 0) || (n >= MAX_DEV))
- return(err);
+ if(ubd_gendisk[n] == NULL)
+ goto out;
dev = &ubd_dev[n];
- if(dev->count > 0)
- return(-EBUSY); /* you cannot remove a open disk */
- err = 0;
- spin_lock(&ubd_lock);
+ if(dev->file == NULL)
+ goto out;
- if(ubd_gendisk[n] == NULL)
+ /* you cannot remove a open disk */
+ err = -EBUSY;
+ if(dev->count > 0)
goto out;
del_gendisk(ubd_gendisk[n]);
@@ -829,15 +797,16 @@ static int ubd_remove(char *str)
platform_device_unregister(&dev->pdev);
*dev = ((struct ubd) DEFAULT_UBD);
err = 0;
- out:
- spin_unlock(&ubd_lock);
- return(err);
+out:
+ spin_unlock(&ubd_lock);
+ return err;
}
static struct mc_device ubd_mc = {
.name = "ubd",
.config = ubd_config,
.get_config = ubd_get_config,
+ .id = ubd_id,
.remove = ubd_remove,
};
@@ -1010,94 +979,13 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap,
req->bitmap_words, bitmap_len);
}
-static int mmap_fd(struct request *req, struct ubd *dev, __u64 offset)
-{
- __u64 sector;
- unsigned char *bitmap;
- int bit, i;
-
- /* mmap must have been requested on the command line */
- if(!ubd_do_mmap)
- return(-1);
-
- /* The buffer must be page aligned */
- if(((unsigned long) req->buffer % UBD_MMAP_BLOCK_SIZE) != 0)
- return(-1);
-
- /* The request must be a page long */
- if((req->current_nr_sectors << 9) != PAGE_SIZE)
- return(-1);
-
- if(dev->cow.file == NULL)
- return(dev->fd);
-
- sector = offset >> 9;
- bitmap = (unsigned char *) dev->cow.bitmap;
- bit = ubd_test_bit(sector, bitmap);
-
- for(i = 1; i < req->current_nr_sectors; i++){
- if(ubd_test_bit(sector + i, bitmap) != bit)
- return(-1);
- }
-
- if(bit || (rq_data_dir(req) == WRITE))
- offset += dev->cow.data_offset;
-
- /* The data on disk must be page aligned */
- if((offset % UBD_MMAP_BLOCK_SIZE) != 0)
- return(-1);
-
- return(bit ? dev->fd : dev->cow.fd);
-}
-
-static int prepare_mmap_request(struct ubd *dev, int fd, __u64 offset,
- struct request *req,
- struct io_thread_req *io_req)
-{
- int err;
-
- if(rq_data_dir(req) == WRITE){
- /* Writes are almost no-ops since the new data is already in the
- * host page cache
- */
- dev->map_writes++;
- if(dev->cow.file != NULL)
- cowify_bitmap(io_req->offset, io_req->length,
- &io_req->sector_mask, &io_req->cow_offset,
- dev->cow.bitmap, dev->cow.bitmap_offset,
- io_req->bitmap_words,
- dev->cow.bitmap_len);
- }
- else {
- int w;
-
- if((dev->cow.file != NULL) && (fd == dev->cow.fd))
- w = 0;
- else w = dev->openflags.w;
-
- if((dev->cow.file != NULL) && (fd == dev->fd))
- offset += dev->cow.data_offset;
-
- err = physmem_subst_mapping(req->buffer, fd, offset, w);
- if(err){
- printk("physmem_subst_mapping failed, err = %d\n",
- -err);
- return(1);
- }
- dev->map_reads++;
- }
- io_req->op = UBD_MMAP;
- io_req->buffer = req->buffer;
- return(0);
-}
-
/* Called with ubd_io_lock held */
static int prepare_request(struct request *req, struct io_thread_req *io_req)
{
struct gendisk *disk = req->rq_disk;
struct ubd *dev = disk->private_data;
__u64 offset;
- int len, fd;
+ int len;
if(req->rq_status == RQ_INACTIVE) return(1);
@@ -1114,34 +1002,12 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req)
io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd;
io_req->fds[1] = dev->fd;
- io_req->map_fd = -1;
io_req->cow_offset = -1;
io_req->offset = offset;
io_req->length = len;
io_req->error = 0;
io_req->sector_mask = 0;
- fd = mmap_fd(req, dev, io_req->offset);
- if(fd > 0){
- /* If mmapping is otherwise OK, but the first access to the
- * page is a write, then it's not mapped in yet. So we have
- * to write the data to disk first, then we can map the disk
- * page in and continue normally from there.
- */
- if((rq_data_dir(req) == WRITE) && !is_remapped(req->buffer)){
- io_req->map_fd = dev->fd;
- io_req->map_offset = io_req->offset +
- dev->cow.data_offset;
- dev->write_maps++;
- }
- else return(prepare_mmap_request(dev, fd, io_req->offset, req,
- io_req));
- }
-
- if(rq_data_dir(req) == READ)
- dev->nomap_reads++;
- else dev->nomap_writes++;
-
io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE;
io_req->offsets[0] = 0;
io_req->offsets[1] = dev->cow.data_offset;
@@ -1229,143 +1095,6 @@ static int ubd_ioctl(struct inode * inode, struct file * file,
return(-EINVAL);
}
-static int ubd_check_remapped(int fd, unsigned long address, int is_write,
- __u64 offset)
-{
- __u64 bitmap_offset;
- unsigned long new_bitmap[2];
- int i, err, n;
-
- /* If it's not a write access, we can't do anything about it */
- if(!is_write)
- return(0);
-
- /* We have a write */
- for(i = 0; i < sizeof(ubd_dev) / sizeof(ubd_dev[0]); i++){
- struct ubd *dev = &ubd_dev[i];
-
- if((dev->fd != fd) && (dev->cow.fd != fd))
- continue;
-
- /* It's a write to a ubd device */
-
- /* This should be impossible now */
- if(!dev->openflags.w){
- /* It's a write access on a read-only device - probably
- * shouldn't happen. If the kernel is trying to change
- * something with no intention of writing it back out,
- * then this message will clue us in that this needs
- * fixing
- */
- printk("Write access to mapped page from readonly ubd "
- "device %d\n", i);
- return(0);
- }
-
- /* It's a write to a writeable ubd device - it must be COWed
- * because, otherwise, the page would have been mapped in
- * writeable
- */
-
- if(!dev->cow.file)
- panic("Write fault on writeable non-COW ubd device %d",
- i);
-
- /* It should also be an access to the backing file since the
- * COW pages should be mapped in read-write
- */
-
- if(fd == dev->fd)
- panic("Write fault on a backing page of ubd "
- "device %d\n", i);
-
- /* So, we do the write, copying the backing data to the COW
- * file...
- */
-
- err = os_seek_file(dev->fd, offset + dev->cow.data_offset);
- if(err < 0)
- panic("Couldn't seek to %lld in COW file of ubd "
- "device %d, err = %d",
- offset + dev->cow.data_offset, i, -err);
-
- n = os_write_file(dev->fd, (void *) address, PAGE_SIZE);
- if(n != PAGE_SIZE)
- panic("Couldn't copy data to COW file of ubd "
- "device %d, err = %d", i, -n);
-
- /* ... updating the COW bitmap... */
-
- cowify_bitmap(offset, PAGE_SIZE, NULL, &bitmap_offset,
- dev->cow.bitmap, dev->cow.bitmap_offset,
- new_bitmap, dev->cow.bitmap_len);
-
- err = os_seek_file(dev->fd, bitmap_offset);
- if(err < 0)
- panic("Couldn't seek to %lld in COW file of ubd "
- "device %d, err = %d", bitmap_offset, i, -err);
-
- n = os_write_file(dev->fd, new_bitmap, sizeof(new_bitmap));
- if(n != sizeof(new_bitmap))
- panic("Couldn't update bitmap of ubd device %d, "
- "err = %d", i, -n);
-
- /* Maybe we can map the COW page in, and maybe we can't. If
- * it is a pre-V3 COW file, we can't, since the alignment will
- * be wrong. If it is a V3 or later COW file which has been
- * moved to a system with a larger page size, then maybe we
- * can't, depending on the exact location of the page.
- */
-
- offset += dev->cow.data_offset;
-
- /* Remove the remapping, putting the original anonymous page
- * back. If the COW file can be mapped in, that is done.
- * Otherwise, the COW page is read in.
- */
-
- if(!physmem_remove_mapping((void *) address))
- panic("Address 0x%lx not remapped by ubd device %d",
- address, i);
- if((offset % UBD_MMAP_BLOCK_SIZE) == 0)
- physmem_subst_mapping((void *) address, dev->fd,
- offset, 1);
- else {
- err = os_seek_file(dev->fd, offset);
- if(err < 0)
- panic("Couldn't seek to %lld in COW file of "
- "ubd device %d, err = %d", offset, i,
- -err);
-
- n = os_read_file(dev->fd, (void *) address, PAGE_SIZE);
- if(n != PAGE_SIZE)
- panic("Failed to read page from offset %llx of "
- "COW file of ubd device %d, err = %d",
- offset, i, -n);
- }
-
- return(1);
- }
-
- /* It's not a write on a ubd device */
- return(0);
-}
-
-static struct remapper ubd_remapper = {
- .list = LIST_HEAD_INIT(ubd_remapper.list),
- .proc = ubd_check_remapped,
-};
-
-static int ubd_remapper_setup(void)
-{
- if(ubd_do_mmap)
- register_remapper(&ubd_remapper);
-
- return(0);
-}
-
-__initcall(ubd_remapper_setup);
-
static int same_backing_files(char *from_cmdline, char *from_cow, char *cow)
{
struct uml_stat buf1, buf2;
@@ -1568,15 +1297,6 @@ void do_io(struct io_thread_req *req)
int err;
__u64 off;
- if(req->op == UBD_MMAP){
- /* Touch the page to force the host to do any necessary IO to
- * get it into memory
- */
- n = *((volatile int *) req->buffer);
- req->error = update_bitmap(req);
- return;
- }
-
nsectors = req->length / req->sectorsize;
start = 0;
do {
diff --git a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c
index a4fdf3584ad..d269a80f4b0 100644
--- a/arch/um/drivers/xterm_kern.c
+++ b/arch/um/drivers/xterm_kern.c
@@ -69,7 +69,6 @@ int xterm_fd(int socket, int *pid_out)
* isn't set) this will hang... */
wait_for_completion(&data->ready);
- free_irq_by_irq_and_dev(XTERM_IRQ, data);
free_irq(XTERM_IRQ, data);
ret = data->new_fd;
diff --git a/arch/um/include/2_5compat.h b/arch/um/include/2_5compat.h
deleted file mode 100644
index abdb015a4d7..00000000000
--- a/arch/um/include/2_5compat.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2001 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __2_5_COMPAT_H__
-#define __2_5_COMPAT_H__
-
-#define INIT_HARDSECT(arr, maj, sizes)
-
-#define SET_PRI(task) do ; while(0)
-
-#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/line.h b/arch/um/include/line.h
index 4c5e92c04cc..5323d22a6ca 100644
--- a/arch/um/include/line.h
+++ b/arch/um/include/line.h
@@ -101,7 +101,8 @@ extern void lines_init(struct line *lines, int nlines);
extern void close_lines(struct line *lines, int nlines);
extern int line_config(struct line *lines, unsigned int sizeof_lines, char *str);
-extern int line_remove(struct line *lines, unsigned int sizeof_lines, char *str);
+extern int line_id(char **str, int *start_out, int *end_out);
+extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n);
extern int line_get_config(char *dev, struct line *lines, unsigned int sizeof_lines, char *str,
int size, char **error_out);
diff --git a/arch/um/include/mconsole.h b/arch/um/include/mconsole.h
index 9fbe3083fdd..cfa368e045a 100644
--- a/arch/um/include/mconsole.h
+++ b/arch/um/include/mconsole.h
@@ -56,7 +56,7 @@ struct mc_request
int as_interrupt;
int originating_fd;
- int originlen;
+ unsigned int originlen;
unsigned char origin[128]; /* sockaddr_un */
struct mconsole_request request;
diff --git a/arch/um/include/mconsole_kern.h b/arch/um/include/mconsole_kern.h
index 61c274fcee5..d86ee14260c 100644
--- a/arch/um/include/mconsole_kern.h
+++ b/arch/um/include/mconsole_kern.h
@@ -20,7 +20,8 @@ struct mc_device {
char *name;
int (*config)(char *);
int (*get_config)(char *, char *, int, char **);
- int (*remove)(char *);
+ int (*id)(char **, int *, int *);
+ int (*remove)(int);
};
#define CONFIG_CHUNK(str, size, current, chunk, end) \
diff --git a/arch/um/include/net_user.h b/arch/um/include/net_user.h
index 36807b796e9..89885a77a77 100644
--- a/arch/um/include/net_user.h
+++ b/arch/um/include/net_user.h
@@ -35,7 +35,7 @@ extern void *get_output_buffer(int *len_out);
extern void free_output_buffer(void *buffer);
extern int tap_open_common(void *dev, char *gate_addr);
-extern void tap_check_ips(char *gate_addr, char *eth_addr);
+extern void tap_check_ips(char *gate_addr, unsigned char *eth_addr);
extern void read_output(int fd, char *output_out, int len);
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index d246d5a2460..881d2988d2d 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -136,7 +136,7 @@ extern int os_seek_file(int fd, __u64 offset);
extern int os_open_file(char *file, struct openflags flags, int mode);
extern int os_read_file(int fd, void *buf, int len);
extern int os_write_file(int fd, const void *buf, int count);
-extern int os_file_size(char *file, long long *size_out);
+extern int os_file_size(char *file, unsigned long long *size_out);
extern int os_file_modtime(char *file, unsigned long *modtime);
extern int os_pipe(int *fd, int stream, int close_on_exec);
extern int os_set_fd_async(int fd, int owner);
diff --git a/arch/um/include/sysdep-i386/ptrace.h b/arch/um/include/sysdep-i386/ptrace.h
index 84ec7ff5cf8..c8ee9559f3a 100644
--- a/arch/um/include/sysdep-i386/ptrace.h
+++ b/arch/um/include/sysdep-i386/ptrace.h
@@ -8,6 +8,8 @@
#include "uml-config.h"
#include "user_constants.h"
+#include "sysdep/faultinfo.h"
+#include "choose-mode.h"
#define MAX_REG_NR (UM_FRAME_SIZE / sizeof(unsigned long))
#define MAX_REG_OFFSET (UM_FRAME_SIZE)
@@ -31,7 +33,6 @@ extern int sysemu_supported;
#ifdef UML_CONFIG_MODE_SKAS
#include "skas_ptregs.h"
-#include "sysdep/faultinfo.h"
#define REGS_IP(r) ((r)[HOST_IP])
#define REGS_SP(r) ((r)[HOST_SP])
@@ -59,8 +60,6 @@ extern int sysemu_supported;
#define PTRACE_SYSEMU_SINGLESTEP 32
#endif
-#include "choose-mode.h"
-
union uml_pt_regs {
#ifdef UML_CONFIG_MODE_TT
struct tt_regs {
diff --git a/arch/um/include/sysdep-x86_64/checksum.h b/arch/um/include/sysdep-x86_64/checksum.h
index 572c6c19be3..ea97005af69 100644
--- a/arch/um/include/sysdep-x86_64/checksum.h
+++ b/arch/um/include/sysdep-x86_64/checksum.h
@@ -9,8 +9,6 @@
#include "linux/in6.h"
#include "asm/uaccess.h"
-extern unsigned int csum_partial_copy_from(const unsigned char *src, unsigned char *dst, int len,
- int sum, int *err_ptr);
extern unsigned csum_partial(const unsigned char *buff, unsigned len,
unsigned sum);
@@ -31,10 +29,15 @@ unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *
}
static __inline__
-unsigned int csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst,
- int len, int sum, int *err_ptr)
+unsigned int csum_partial_copy_from_user(const unsigned char *src,
+ unsigned char *dst, int len, int sum,
+ int *err_ptr)
{
- return csum_partial_copy_from(src, dst, len, sum, err_ptr);
+ if(copy_from_user(dst, src, len)){
+ *err_ptr = -EFAULT;
+ return(-1);
+ }
+ return csum_partial(dst, len, sum);
}
/**
@@ -137,15 +140,6 @@ static inline unsigned add32_with_carry(unsigned a, unsigned b)
return a;
}
-#endif
+extern unsigned short ip_compute_csum(unsigned char * buff, int len);
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+#endif
diff --git a/arch/um/include/sysdep-x86_64/ptrace.h b/arch/um/include/sysdep-x86_64/ptrace.h
index 348e8fcd513..be8acd5efd9 100644
--- a/arch/um/include/sysdep-x86_64/ptrace.h
+++ b/arch/um/include/sysdep-x86_64/ptrace.h
@@ -135,6 +135,7 @@ extern int mode_tt;
__CHOOSE_MODE(SC_EFLAGS(UPT_SC(r)), REGS_EFLAGS((r)->skas.regs))
#define UPT_SC(r) ((r)->tt.sc)
#define UPT_SYSCALL_NR(r) __CHOOSE_MODE((r)->tt.syscall, (r)->skas.syscall)
+#define UPT_SYSCALL_RET(r) UPT_RAX(r)
extern int user_context(unsigned long sp);
@@ -196,32 +197,32 @@ struct syscall_args {
#define UPT_SET(regs, reg, val) \
- ({ unsigned long val; \
+ ({ unsigned long __upt_val = val; \
switch(reg){ \
- case R8: UPT_R8(regs) = val; break; \
- case R9: UPT_R9(regs) = val; break; \
- case R10: UPT_R10(regs) = val; break; \
- case R11: UPT_R11(regs) = val; break; \
- case R12: UPT_R12(regs) = val; break; \
- case R13: UPT_R13(regs) = val; break; \
- case R14: UPT_R14(regs) = val; break; \
- case R15: UPT_R15(regs) = val; break; \
- case RIP: UPT_IP(regs) = val; break; \
- case RSP: UPT_SP(regs) = val; break; \
- case RAX: UPT_RAX(regs) = val; break; \
- case RBX: UPT_RBX(regs) = val; break; \
- case RCX: UPT_RCX(regs) = val; break; \
- case RDX: UPT_RDX(regs) = val; break; \
- case RSI: UPT_RSI(regs) = val; break; \
- case RDI: UPT_RDI(regs) = val; break; \
- case RBP: UPT_RBP(regs) = val; break; \
- case ORIG_RAX: UPT_ORIG_RAX(regs) = val; break; \
- case CS: UPT_CS(regs) = val; break; \
- case DS: UPT_DS(regs) = val; break; \
- case ES: UPT_ES(regs) = val; break; \
- case FS: UPT_FS(regs) = val; break; \
- case GS: UPT_GS(regs) = val; break; \
- case EFLAGS: UPT_EFLAGS(regs) = val; break; \
+ case R8: UPT_R8(regs) = __upt_val; break; \
+ case R9: UPT_R9(regs) = __upt_val; break; \
+ case R10: UPT_R10(regs) = __upt_val; break; \
+ case R11: UPT_R11(regs) = __upt_val; break; \
+ case R12: UPT_R12(regs) = __upt_val; break; \
+ case R13: UPT_R13(regs) = __upt_val; break; \
+ case R14: UPT_R14(regs) = __upt_val; break; \
+ case R15: UPT_R15(regs) = __upt_val; break; \
+ case RIP: UPT_IP(regs) = __upt_val; break; \
+ case RSP: UPT_SP(regs) = __upt_val; break; \
+ case RAX: UPT_RAX(regs) = __upt_val; break; \
+ case RBX: UPT_RBX(regs) = __upt_val; break; \
+ case RCX: UPT_RCX(regs) = __upt_val; break; \
+ case RDX: UPT_RDX(regs) = __upt_val; break; \
+ case RSI: UPT_RSI(regs) = __upt_val; break; \
+ case RDI: UPT_RDI(regs) = __upt_val; break; \
+ case RBP: UPT_RBP(regs) = __upt_val; break; \
+ case ORIG_RAX: UPT_ORIG_RAX(regs) = __upt_val; break; \
+ case CS: UPT_CS(regs) = __upt_val; break; \
+ case DS: UPT_DS(regs) = __upt_val; break; \
+ case ES: UPT_ES(regs) = __upt_val; break; \
+ case FS: UPT_FS(regs) = __upt_val; break; \
+ case GS: UPT_GS(regs) = __upt_val; break; \
+ case EFLAGS: UPT_EFLAGS(regs) = __upt_val; break; \
default : \
panic("Bad register in UPT_SET : %d\n", reg); \
break; \
@@ -245,14 +246,3 @@ struct syscall_args {
CHOOSE_MODE((&(r)->tt.faultinfo), (&(r)->skas.faultinfo))
#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/include/sysrq.h b/arch/um/include/sysrq.h
index 2ce9423460b..c8d332b56b9 100644
--- a/arch/um/include/sysrq.h
+++ b/arch/um/include/sysrq.h
@@ -1,6 +1,7 @@
#ifndef __UM_SYSRQ_H
#define __UM_SYSRQ_H
-extern void show_trace(unsigned long *stack);
+struct task_struct;
+extern void show_trace(struct task_struct* task, unsigned long *stack);
#endif
diff --git a/arch/um/include/time_user.h b/arch/um/include/time_user.h
index 6793a2fcd0a..f64ef77019a 100644
--- a/arch/um/include/time_user.h
+++ b/arch/um/include/time_user.h
@@ -8,11 +8,11 @@
extern void timer(void);
extern void switch_timers(int to_real);
-extern void set_interval(int timer_type);
extern void idle_sleep(int secs);
extern void enable_timer(void);
extern void disable_timer(void);
extern unsigned long time_lock(void);
extern void time_unlock(unsigned long);
+extern void user_time_init(void);
#endif
diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h
index b8c5b8a9525..7b6a24dfd30 100644
--- a/arch/um/include/user_util.h
+++ b/arch/um/include/user_util.h
@@ -41,9 +41,6 @@ extern unsigned long highmem;
extern char host_info[];
extern char saved_command_line[];
-extern char command_line[];
-
-extern char *tempdir;
extern unsigned long _stext, _etext, _sdata, _edata, __bss_start, _end;
extern unsigned long _unprotected_end;
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
index 9736ca27c5f..a8918e80df9 100644
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -14,7 +14,7 @@ obj-y = config.o exec_kern.o exitcode.o \
tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o umid.o \
user_util.o
-obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o
+obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
obj-$(CONFIG_GPROF) += gprof_syms.o
obj-$(CONFIG_GCOV) += gmon_syms.o
obj-$(CONFIG_TTY_LOG) += tty_log.o
diff --git a/arch/um/kernel/checksum.c b/arch/um/kernel/checksum.c
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/arch/um/kernel/checksum.c
+++ /dev/null
diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c
index 49ddabe69be..efd222ffe20 100644
--- a/arch/um/kernel/exec_kern.c
+++ b/arch/um/kernel/exec_kern.c
@@ -16,7 +16,6 @@
#include "kern.h"
#include "irq_user.h"
#include "tlb.h"
-#include "2_5compat.h"
#include "os.h"
#include "time_user.h"
#include "choose-mode.h"
diff --git a/arch/um/kernel/initrd_kern.c b/arch/um/kernel/initrd.c
index fc568af468b..82ecf904b09 100644
--- a/arch/um/kernel/initrd_kern.c
+++ b/arch/um/kernel/initrd.c
@@ -41,12 +41,31 @@ static int __init uml_initrd_setup(char *line, int *add)
return 0;
}
-__uml_setup("initrd=", uml_initrd_setup,
+__uml_setup("initrd=", uml_initrd_setup,
"initrd=<initrd image>\n"
" This is used to boot UML from an initrd image. The argument is the\n"
" name of the file containing the image.\n\n"
);
+int load_initrd(char *filename, void *buf, int size)
+{
+ int fd, n;
+
+ fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
+ if(fd < 0){
+ printk("Opening '%s' failed - err = %d\n", filename, -fd);
+ return(-1);
+ }
+ n = os_read_file(fd, buf, size);
+ if(n != size){
+ printk("Read of %d bytes from '%s' failed, err = %d\n", size,
+ filename, -n);
+ return(-1);
+ }
+
+ os_close_file(fd);
+ return(0);
+}
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
diff --git a/arch/um/kernel/initrd_user.c b/arch/um/kernel/initrd_user.c
deleted file mode 100644
index cb90681e151..00000000000
--- a/arch/um/kernel/initrd_user.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-
-#include "user_util.h"
-#include "kern_util.h"
-#include "user.h"
-#include "initrd.h"
-#include "os.h"
-
-int load_initrd(char *filename, void *buf, int size)
-{
- int fd, n;
-
- fd = os_open_file(filename, of_read(OPENFLAGS()), 0);
- if(fd < 0){
- printk("Opening '%s' failed - err = %d\n", filename, -fd);
- return(-1);
- }
- n = os_read_file(fd, buf, size);
- if(n != size){
- printk("Read of %d bytes from '%s' failed, err = %d\n", size,
- filename, -n);
- return(-1);
- }
-
- os_close_file(fd);
- return(0);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index d44fb528254..9f18061ef4c 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -124,14 +124,16 @@ void irq_unlock(unsigned long flags)
spin_unlock_irqrestore(&irq_spinlock, flags);
}
-/* presently hw_interrupt_type must define (startup || enable) &&
- * disable && end */
+/* hw_interrupt_type must define (startup || enable) &&
+ * (shutdown || disable) && end */
static void dummy(unsigned int irq)
{
}
-static struct hw_interrupt_type SIGIO_irq_type = {
+/* This is used for everything else than the timer. */
+static struct hw_interrupt_type normal_irq_type = {
.typename = "SIGIO",
+ .release = free_irq_by_irq_and_dev,
.disable = dummy,
.enable = dummy,
.ack = dummy,
@@ -140,6 +142,7 @@ static struct hw_interrupt_type SIGIO_irq_type = {
static struct hw_interrupt_type SIGVTALRM_irq_type = {
.typename = "SIGVTALRM",
+ .release = free_irq_by_irq_and_dev,
.shutdown = dummy, /* never called */
.disable = dummy,
.enable = dummy,
@@ -160,7 +163,7 @@ void __init init_IRQ(void)
irq_desc[i].status = IRQ_DISABLED;
irq_desc[i].action = NULL;
irq_desc[i].depth = 1;
- irq_desc[i].handler = &SIGIO_irq_type;
+ irq_desc[i].handler = &normal_irq_type;
enable_irq(i);
}
}
diff --git a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c
index 6d6f9484b88..c3ccaf24f3e 100644
--- a/arch/um/kernel/irq_user.c
+++ b/arch/um/kernel/irq_user.c
@@ -85,8 +85,6 @@ void sigio_handler(int sig, union uml_pt_regs *regs)
next = irq_fd->next;
if(irq_fd->freed){
free_irq(irq_fd->irq, irq_fd->id);
- free_irq_by_irq_and_dev(irq_fd->irq,
- irq_fd->id);
}
}
}
@@ -236,9 +234,15 @@ static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg)
(*prev)->fd, pollfds[i].fd);
goto out;
}
- memcpy(&pollfds[i], &pollfds[i + 1],
- (pollfds_num - i - 1) * sizeof(pollfds[0]));
+
pollfds_num--;
+
+ /* This moves the *whole* array after pollfds[i] (though
+ * it doesn't spot as such)! */
+
+ memmove(&pollfds[i], &pollfds[i + 1],
+ (pollfds_num - i) * sizeof(pollfds[0]));
+
if(last_irq_ptr == &old_fd->next)
last_irq_ptr = prev;
*prev = (*prev)->next;
diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c
index 78d69dc74b2..99439fa15ef 100644
--- a/arch/um/kernel/ksyms.c
+++ b/arch/um/kernel/ksyms.c
@@ -57,6 +57,7 @@ EXPORT_SYMBOL(copy_to_user_tt);
EXPORT_SYMBOL(strncpy_from_user_skas);
EXPORT_SYMBOL(copy_to_user_skas);
EXPORT_SYMBOL(copy_from_user_skas);
+EXPORT_SYMBOL(clear_user_skas);
#endif
EXPORT_SYMBOL(uml_strdup);
diff --git a/arch/um/kernel/main.c b/arch/um/kernel/main.c
index a17c49703f9..1e1a87f1c51 100644
--- a/arch/um/kernel/main.c
+++ b/arch/um/kernel/main.c
@@ -24,8 +24,6 @@
#include "mode.h"
#include "choose-mode.h"
#include "uml-config.h"
-#include "irq_user.h"
-#include "time_user.h"
#include "os.h"
/* Set in set_stklim, which is called from main and __wrap_malloc.
@@ -71,7 +69,6 @@ static __init void do_uml_initcalls(void)
static void last_ditch_exit(int sig)
{
- CHOOSE_MODE(kmalloc_ok = 0, (void) 0);
signal(SIGINT, SIG_DFL);
signal(SIGTERM, SIG_DFL);
signal(SIGHUP, SIG_DFL);
@@ -87,7 +84,7 @@ int main(int argc, char **argv, char **envp)
{
char **new_argv;
sigset_t mask;
- int ret, i;
+ int ret, i, err;
/* Enable all signals except SIGIO - in some environments, we can
* enter with some signals blocked
@@ -160,27 +157,29 @@ int main(int argc, char **argv, char **envp)
*/
change_sig(SIGPROF, 0);
- /* Reboot */
- if(ret){
- int err;
+ /* This signal stuff used to be in the reboot case. However,
+ * sometimes a SIGVTALRM can come in when we're halting (reproducably
+ * when writing out gcov information, presumably because that takes
+ * some time) and cause a segfault.
+ */
- printf("\n");
+ /* stop timers and set SIG*ALRM to be ignored */
+ disable_timer();
- /* stop timers and set SIG*ALRM to be ignored */
- disable_timer();
+ /* disable SIGIO for the fds and set SIGIO to be ignored */
+ err = deactivate_all_fds();
+ if(err)
+ printf("deactivate_all_fds failed, errno = %d\n", -err);
- /* disable SIGIO for the fds and set SIGIO to be ignored */
- err = deactivate_all_fds();
- if(err)
- printf("deactivate_all_fds failed, errno = %d\n",
- -err);
-
- /* Let any pending signals fire now. This ensures
- * that they won't be delivered after the exec, when
- * they are definitely not expected.
- */
- unblock_signals();
+ /* Let any pending signals fire now. This ensures
+ * that they won't be delivered after the exec, when
+ * they are definitely not expected.
+ */
+ unblock_signals();
+ /* Reboot */
+ if(ret){
+ printf("\n");
execvp(new_argv[0], new_argv);
perror("Failed to exec kernel");
ret = 1;
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index f156661781c..5597bd39e6b 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -53,7 +53,6 @@ static void setup_highmem(unsigned long highmem_start,
for(i = 0; i < highmem_len >> PAGE_SHIFT; i++){
page = &mem_map[highmem_pfn + i];
ClearPageReserved(page);
- set_bit(PG_highmem, &page->flags);
set_page_count(page, 1);
__free_page(page);
}
@@ -100,12 +99,37 @@ void mem_init(void)
#endif
}
+/*
+ * Create a page table and place a pointer to it in a middle page
+ * directory entry.
+ */
+static void __init one_page_table_init(pmd_t *pmd)
+{
+ if (pmd_none(*pmd)) {
+ pte_t *pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ set_pmd(pmd, __pmd(_KERNPG_TABLE +
+ (unsigned long) __pa(pte)));
+ if (pte != pte_offset_kernel(pmd, 0))
+ BUG();
+ }
+}
+
+static void __init one_md_table_init(pud_t *pud)
+{
+#ifdef CONFIG_3_LEVEL_PGTABLES
+ pmd_t *pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ set_pud(pud, __pud(_KERNPG_TABLE + (unsigned long) __pa(pmd_table)));
+ if (pmd_table != pmd_offset(pud, 0))
+ BUG();
+#endif
+}
+
static void __init fixrange_init(unsigned long start, unsigned long end,
pgd_t *pgd_base)
{
pgd_t *pgd;
+ pud_t *pud;
pmd_t *pmd;
- pte_t *pte;
int i, j;
unsigned long vaddr;
@@ -115,15 +139,12 @@ static void __init fixrange_init(unsigned long start, unsigned long end,
pgd = pgd_base + i;
for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) {
- pmd = (pmd_t *)pgd;
+ pud = pud_offset(pgd, vaddr);
+ if (pud_none(*pud))
+ one_md_table_init(pud);
+ pmd = pmd_offset(pud, vaddr);
for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
- if (pmd_none(*pmd)) {
- pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
- set_pmd(pmd, __pmd(_KERNPG_TABLE +
- (unsigned long) __pa(pte)));
- if (pte != pte_offset_kernel(pmd, 0))
- BUG();
- }
+ one_page_table_init(pmd);
vaddr += PMD_SIZE;
}
j = 0;
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 51f8e5a8ac6..1b5ef3e96c7 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -30,7 +30,6 @@
#include "init.h"
#include "os.h"
#include "uml-config.h"
-#include "ptrace_user.h"
#include "choose-mode.h"
#include "mode.h"
#ifdef UML_CONFIG_MODE_SKAS
@@ -131,7 +130,7 @@ int start_fork_tramp(void *thread_arg, unsigned long temp_stack,
return(arg.pid);
}
-static int ptrace_child(void *arg)
+static int ptrace_child(void)
{
int ret;
int pid = os_getpid(), ppid = getppid();
@@ -160,20 +159,16 @@ static int ptrace_child(void *arg)
_exit(ret);
}
-static int start_ptraced_child(void **stack_out)
+static int start_ptraced_child(void)
{
- void *stack;
- unsigned long sp;
int pid, n, status;
- stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if(stack == MAP_FAILED)
- panic("check_ptrace : mmap failed, errno = %d", errno);
- sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
- pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL);
+ pid = fork();
+ if(pid == 0)
+ ptrace_child();
+
if(pid < 0)
- panic("check_ptrace : clone failed, errno = %d", errno);
+ panic("check_ptrace : fork failed, errno = %d", errno);
CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
if(n < 0)
panic("check_ptrace : wait failed, errno = %d", errno);
@@ -181,7 +176,6 @@ static int start_ptraced_child(void **stack_out)
panic("check_ptrace : expected SIGSTOP, got status = %d",
status);
- *stack_out = stack;
return(pid);
}
@@ -189,12 +183,12 @@ static int start_ptraced_child(void **stack_out)
* just avoid using sysemu, not panic, but only if SYSEMU features are broken.
* So only for SYSEMU features we test mustpanic, while normal host features
* must work anyway!*/
-static int stop_ptraced_child(int pid, void *stack, int exitcode, int mustpanic)
+static int stop_ptraced_child(int pid, int exitcode, int mustexit)
{
int status, n, ret = 0;
if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
- panic("check_ptrace : ptrace failed, errno = %d", errno);
+ panic("stop_ptraced_child : ptrace failed, errno = %d", errno);
CATCH_EINTR(n = waitpid(pid, &status, 0));
if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) {
int exit_with = WEXITSTATUS(status);
@@ -205,15 +199,13 @@ static int stop_ptraced_child(int pid, void *stack, int exitcode, int mustpanic)
printk("check_ptrace : child exited with exitcode %d, while "
"expecting %d; status 0x%x", exit_with,
exitcode, status);
- if (mustpanic)
+ if (mustexit)
panic("\n");
else
printk("\n");
ret = -1;
}
- if(munmap(stack, PAGE_SIZE) < 0)
- panic("check_ptrace : munmap failed, errno = %d", errno);
return ret;
}
@@ -235,12 +227,11 @@ __uml_setup("nosysemu", nosysemu_cmd_param,
static void __init check_sysemu(void)
{
- void *stack;
int pid, syscall, n, status, count=0;
printk("Checking syscall emulation patch for ptrace...");
sysemu_supported = 0;
- pid = start_ptraced_child(&stack);
+ pid = start_ptraced_child();
if(ptrace(PTRACE_SYSEMU, pid, 0, 0) < 0)
goto fail;
@@ -258,7 +249,7 @@ static void __init check_sysemu(void)
panic("check_sysemu : failed to modify system "
"call return, errno = %d", errno);
- if (stop_ptraced_child(pid, stack, 0, 0) < 0)
+ if (stop_ptraced_child(pid, 0, 0) < 0)
goto fail_stopped;
sysemu_supported = 1;
@@ -266,7 +257,7 @@ static void __init check_sysemu(void)
set_using_sysemu(!force_sysemu_disabled);
printk("Checking advanced syscall emulation patch for ptrace...");
- pid = start_ptraced_child(&stack);
+ pid = start_ptraced_child();
while(1){
count++;
if(ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, 0) < 0)
@@ -291,7 +282,7 @@ static void __init check_sysemu(void)
break;
}
}
- if (stop_ptraced_child(pid, stack, 0, 0) < 0)
+ if (stop_ptraced_child(pid, 0, 0) < 0)
goto fail_stopped;
sysemu_supported = 2;
@@ -302,18 +293,17 @@ static void __init check_sysemu(void)
return;
fail:
- stop_ptraced_child(pid, stack, 1, 0);
+ stop_ptraced_child(pid, 1, 0);
fail_stopped:
printk("missing\n");
}
void __init check_ptrace(void)
{
- void *stack;
int pid, syscall, n, status;
printk("Checking that ptrace can change system call numbers...");
- pid = start_ptraced_child(&stack);
+ pid = start_ptraced_child();
if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0)
panic("check_ptrace: PTRACE_SETOPTIONS failed, errno = %d", errno);
@@ -340,7 +330,7 @@ void __init check_ptrace(void)
break;
}
}
- stop_ptraced_child(pid, stack, 0, 1);
+ stop_ptraced_child(pid, 0, 1);
printk("OK\n");
check_sysemu();
}
@@ -372,11 +362,10 @@ void forward_pending_sigio(int target)
static inline int check_skas3_ptrace_support(void)
{
struct ptrace_faultinfo fi;
- void *stack;
int pid, n, ret = 1;
printf("Checking for the skas3 patch in the host...");
- pid = start_ptraced_child(&stack);
+ pid = start_ptraced_child();
n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi);
if (n < 0) {
@@ -391,7 +380,7 @@ static inline int check_skas3_ptrace_support(void)
}
init_registers(pid);
- stop_ptraced_child(pid, stack, 1, 1);
+ stop_ptraced_child(pid, 1, 1);
return(ret);
}
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
index c1adf7ba3fd..d4036ed680b 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process_kern.c
@@ -8,6 +8,7 @@
#include "linux/kernel.h"
#include "linux/sched.h"
#include "linux/interrupt.h"
+#include "linux/string.h"
#include "linux/mm.h"
#include "linux/slab.h"
#include "linux/utsname.h"
@@ -43,7 +44,6 @@
#include "tlb.h"
#include "frame_kern.h"
#include "sigcontext.h"
-#include "2_5compat.h"
#include "os.h"
#include "mode.h"
#include "mode_kern.h"
@@ -55,18 +55,6 @@
*/
struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
-struct task_struct *get_task(int pid, int require)
-{
- struct task_struct *ret;
-
- read_lock(&tasklist_lock);
- ret = find_task_by_pid(pid);
- read_unlock(&tasklist_lock);
-
- if(require && (ret == NULL)) panic("get_task couldn't find a task\n");
- return(ret);
-}
-
int external_pid(void *t)
{
struct task_struct *task = t ? t : current;
@@ -108,8 +96,8 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
current->thread.request.u.thread.proc = fn;
current->thread.request.u.thread.arg = arg;
- pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0, NULL, 0, NULL,
- NULL);
+ pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0,
+ &current->thread.regs, 0, NULL, NULL);
if(pid < 0)
panic("do_fork failed in kernel_thread, errno = %d", pid);
return(pid);
@@ -181,7 +169,7 @@ int current_pid(void)
void default_idle(void)
{
- uml_idle_timer();
+ CHOOSE_MODE(uml_idle_timer(), (void) 0);
atomic_inc(&init_mm.mm_count);
current->mm = &init_mm;
@@ -189,7 +177,6 @@ void default_idle(void)
while(1){
/* endless idle loop with no priority at all */
- SET_PRI(current);
/*
* although we are an idle CPU, we do not want to
@@ -212,11 +199,6 @@ int page_size(void)
return(PAGE_SIZE);
}
-unsigned long page_mask(void)
-{
- return(PAGE_MASK);
-}
-
void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
pte_t *pte_out)
{
@@ -341,17 +323,7 @@ void do_uml_exitcalls(void)
char *uml_strdup(char *string)
{
- char *new;
-
- new = kmalloc(strlen(string) + 1, GFP_KERNEL);
- if(new == NULL) return(NULL);
- strcpy(new, string);
- return(new);
-}
-
-void *get_init_task(void)
-{
- return(&init_thread_union.thread_info.task);
+ return kstrdup(string, GFP_KERNEL);
}
int copy_to_user_proc(void __user *to, void *from, int size)
@@ -480,15 +452,3 @@ unsigned long arch_align_stack(unsigned long sp)
return sp & ~0xf;
}
#endif
-
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
index 2b75d8d9ba7..71af4d50389 100644
--- a/arch/um/kernel/ptrace.c
+++ b/arch/um/kernel/ptrace.c
@@ -28,9 +28,9 @@ static inline void set_singlestepping(struct task_struct *child, int on)
child->thread.singlestep_syscall = 0;
#ifdef SUBARCH_SET_SINGLESTEPPING
- SUBARCH_SET_SINGLESTEPPING(child, on)
+ SUBARCH_SET_SINGLESTEPPING(child, on);
#endif
- }
+}
/*
* Called by kernel/ptrace.c when detaching..
@@ -83,7 +83,7 @@ long sys_ptrace(long request, long pid, long addr, long data)
}
#ifdef SUBACH_PTRACE_SPECIAL
- SUBARCH_PTRACE_SPECIAL(child,request,addr,data)
+ SUBARCH_PTRACE_SPECIAL(child,request,addr,data);
#endif
ret = ptrace_check_attach(child, request == PTRACE_KILL);
@@ -322,11 +322,9 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit)
UPT_SYSCALL_ARG2(regs),
UPT_SYSCALL_ARG3(regs),
UPT_SYSCALL_ARG4(regs));
- else {
- int res = UPT_SYSCALL_RET(regs);
- audit_syscall_exit(current, AUDITSC_RESULT(res),
- res);
- }
+ else audit_syscall_exit(current,
+ AUDITSC_RESULT(UPT_SYSCALL_RET(regs)),
+ UPT_SYSCALL_RET(regs));
}
/* Fake a debug trap */
@@ -356,14 +354,3 @@ void syscall_trace(union uml_pt_regs *regs, int entryexit)
current->exit_code = 0;
}
}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index 207f89d7490..fcec51da1d3 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -38,14 +38,14 @@ static void kill_off_processes(void)
void uml_cleanup(void)
{
- kill_off_processes();
+ kmalloc_ok = 0;
do_uml_exitcalls();
+ kill_off_processes();
}
void machine_restart(char * __unused)
{
- do_uml_exitcalls();
- kill_off_processes();
+ uml_cleanup();
CHOOSE_MODE(reboot_tt(), reboot_skas());
}
@@ -53,8 +53,7 @@ EXPORT_SYMBOL(machine_restart);
void machine_power_off(void)
{
- do_uml_exitcalls();
- kill_off_processes();
+ uml_cleanup();
CHOOSE_MODE(halt_tt(), halt_skas());
}
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index d37d1bfcd6f..ff69c4b312c 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -4,10 +4,10 @@
#
obj-y := exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \
- syscall_kern.o syscall_user.o time.o tlb.o trap_user.o uaccess.o \
+ syscall_kern.o syscall_user.o tlb.o trap_user.o uaccess.o \
subdir- := util
-USER_OBJS := process.o time.o
+USER_OBJS := process.o
include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/skas/include/mode-skas.h b/arch/um/kernel/skas/include/mode-skas.h
index c1e33bd788d..bcd26a6a388 100644
--- a/arch/um/kernel/skas/include/mode-skas.h
+++ b/arch/um/kernel/skas/include/mode-skas.h
@@ -13,7 +13,6 @@ extern unsigned long exec_fp_regs[];
extern unsigned long exec_fpx_regs[];
extern int have_fpx_regs;
-extern void user_time_init_skas(void);
extern void sig_handler_common_skas(int sig, void *sc_ptr);
extern void halt_skas(void);
extern void reboot_skas(void);
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index ab5d3271da0..0a7b8aa55db 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -68,8 +68,11 @@ void new_thread_handler(int sig)
* 0 if it just exits
*/
n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
- if(n == 1)
+ if(n == 1){
+ /* Handle any immediate reschedules or signals */
+ interrupt_end();
userspace(&current->thread.regs.regs);
+ }
else do_exit(0);
}
@@ -96,6 +99,8 @@ void fork_handler(int sig)
schedule_tail(current->thread.prev_sched);
current->thread.prev_sched = NULL;
+ /* Handle any immediate reschedules or signals */
+ interrupt_end();
userspace(&current->thread.regs.regs);
}
@@ -106,8 +111,7 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
void (*handler)(int);
if(current->thread.forking){
- memcpy(&p->thread.regs.regs.skas,
- &current->thread.regs.regs.skas,
+ memcpy(&p->thread.regs.regs.skas, &regs->regs.skas,
sizeof(p->thread.regs.regs.skas));
REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0);
if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp;
@@ -176,7 +180,6 @@ int start_uml_skas(void)
start_userspace(0);
init_new_thread_signals(1);
- uml_idle_timer();
init_task.thread.request.u.thread.proc = start_kernel_proc;
init_task.thread.request.u.thread.arg = NULL;
@@ -196,14 +199,3 @@ int thread_pid_skas(struct task_struct *task)
#warning Need to look up userspace_pid by cpu
return(userspace_pid[0]);
}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/skas/time.c b/arch/um/kernel/skas/time.c
deleted file mode 100644
index 98091494b89..00000000000
--- a/arch/um/kernel/skas/time.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <sys/signal.h>
-#include <sys/time.h>
-#include "time_user.h"
-#include "process.h"
-#include "user.h"
-
-void user_time_init_skas(void)
-{
- if(signal(SIGALRM, (__sighandler_t) alarm_handler) == SIG_ERR)
- panic("Couldn't set SIGALRM handler");
- if(signal(SIGVTALRM, (__sighandler_t) alarm_handler) == SIG_ERR)
- panic("Couldn't set SIGVTALRM handler");
- set_interval(ITIMER_VIRTUAL);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/syscall_kern.c b/arch/um/kernel/syscall_kern.c
index b7a55251e89..8e1a3501ff4 100644
--- a/arch/um/kernel/syscall_kern.c
+++ b/arch/um/kernel/syscall_kern.c
@@ -31,7 +31,8 @@ long sys_fork(void)
long ret;
current->thread.forking = 1;
- ret = do_fork(SIGCHLD, 0, NULL, 0, NULL, NULL);
+ ret = do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
+ &current->thread.regs, 0, NULL, NULL);
current->thread.forking = 0;
return(ret);
}
@@ -41,8 +42,9 @@ long sys_vfork(void)
long ret;
current->thread.forking = 1;
- ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0, NULL,
- NULL);
+ ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
+ UPT_SP(&current->thread.regs.regs),
+ &current->thread.regs, 0, NULL, NULL);
current->thread.forking = 0;
return(ret);
}
@@ -162,14 +164,3 @@ int next_syscall_index(int limit)
spin_unlock(&syscall_lock);
return(ret);
}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c
index e630438f9e7..f80850091e7 100644
--- a/arch/um/kernel/sysrq.c
+++ b/arch/um/kernel/sysrq.c
@@ -3,6 +3,7 @@
* Licensed under the GPL
*/
+#include "linux/config.h"
#include "linux/sched.h"
#include "linux/kernel.h"
#include "linux/module.h"
@@ -12,14 +13,14 @@
#include "sysrq.h"
#include "user_util.h"
-void show_trace(unsigned long * stack)
+/* Catch non-i386 SUBARCH's. */
+#if !defined(CONFIG_UML_X86) || defined(CONFIG_64BIT)
+void show_trace(struct task_struct *task, unsigned long * stack)
{
- /* XXX: Copy the CONFIG_FRAME_POINTER stack-walking backtrace from
- * arch/i386/kernel/traps.c, and then move this to sys-i386/sysrq.c.*/
unsigned long addr;
if (!stack) {
- stack = (unsigned long*) &stack;
+ stack = (unsigned long*) &stack;
WARN_ON(1);
}
@@ -35,6 +36,7 @@ void show_trace(unsigned long * stack)
}
printk("\n");
}
+#endif
/*
* stack dumps generator - this is used by arch-independent code.
@@ -44,7 +46,7 @@ void dump_stack(void)
{
unsigned long stack;
- show_trace(&stack);
+ show_trace(current, &stack);
}
EXPORT_SYMBOL(dump_stack);
@@ -59,7 +61,11 @@ void show_stack(struct task_struct *task, unsigned long *esp)
int i;
if (esp == NULL) {
- if (task != current) {
+ if (task != current && task != NULL) {
+ /* XXX: Isn't this bogus? I.e. isn't this the
+ * *userspace* stack of this task? If not so, use this
+ * even when task == current (as in i386).
+ */
esp = (unsigned long *) KSTK_ESP(task);
/* Which one? No actual difference - just coding style.*/
//esp = (unsigned long *) PT_REGS_IP(&task->thread.regs);
@@ -77,5 +83,6 @@ void show_stack(struct task_struct *task, unsigned long *esp)
printk("%08lx ", *stack++);
}
- show_trace(esp);
+ printk("Call Trace: \n");
+ show_trace(current, esp);
}
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index c40c86a3f91..f829b309b63 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -33,7 +33,7 @@ void timer(void)
timeradd(&xtime, &local_offset, &xtime);
}
-void set_interval(int timer_type)
+static void set_interval(int timer_type)
{
int usec = 1000000/hz();
struct itimerval interval = ((struct itimerval) { { 0, usec },
@@ -45,12 +45,7 @@ void set_interval(int timer_type)
void enable_timer(void)
{
- int usec = 1000000/hz();
- struct itimerval enable = ((struct itimerval) { { 0, usec },
- { 0, usec }});
- if(setitimer(ITIMER_VIRTUAL, &enable, NULL))
- printk("enable_timer - setitimer failed, errno = %d\n",
- errno);
+ set_interval(ITIMER_VIRTUAL);
}
void disable_timer(void)
@@ -155,13 +150,15 @@ void idle_sleep(int secs)
nanosleep(&ts, NULL);
}
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+/* XXX This partly duplicates init_irq_signals */
+
+void user_time_init(void)
+{
+ set_handler(SIGVTALRM, (__sighandler_t) alarm_handler,
+ SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH,
+ SIGALRM, SIGUSR2, -1);
+ set_handler(SIGALRM, (__sighandler_t) alarm_handler,
+ SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH,
+ SIGVTALRM, SIGUSR2, -1);
+ set_interval(ITIMER_VIRTUAL);
+}
diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c
index 6516fc52afe..a8b4ef601f5 100644
--- a/arch/um/kernel/time_kern.c
+++ b/arch/um/kernel/time_kern.c
@@ -162,7 +162,7 @@ int __init timer_init(void)
{
int err;
- CHOOSE_MODE(user_time_init_tt(), user_time_init_skas());
+ user_time_init();
err = request_irq(TIMER_IRQ, um_timer, SA_INTERRUPT, "timer", NULL);
if(err != 0)
printk(KERN_ERR "timer_init : request_irq failed - "
diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c
index 5fca2c61eb9..c20aef12059 100644
--- a/arch/um/kernel/trap_kern.c
+++ b/arch/um/kernel/trap_kern.c
@@ -23,7 +23,6 @@
#include "kern.h"
#include "chan_kern.h"
#include "mconsole_kern.h"
-#include "2_5compat.h"
#include "mem.h"
#include "mem_kern.h"
@@ -57,10 +56,11 @@ int handle_page_fault(unsigned long address, unsigned long ip,
*code_out = SEGV_ACCERR;
if(is_write && !(vma->vm_flags & VM_WRITE))
goto out;
+
+ if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
+ goto out;
+
page = address & PAGE_MASK;
- pgd = pgd_offset(mm, page);
- pud = pud_offset(pgd, page);
- pmd = pmd_offset(pud, page);
do {
survive:
switch (handle_mm_fault(mm, vma, address, is_write)){
@@ -106,33 +106,6 @@ out_of_memory:
goto out;
}
-LIST_HEAD(physmem_remappers);
-
-void register_remapper(struct remapper *info)
-{
- list_add(&info->list, &physmem_remappers);
-}
-
-static int check_remapped_addr(unsigned long address, int is_write)
-{
- struct remapper *remapper;
- struct list_head *ele;
- __u64 offset;
- int fd;
-
- fd = phys_mapping(__pa(address), &offset);
- if(fd == -1)
- return(0);
-
- list_for_each(ele, &physmem_remappers){
- remapper = list_entry(ele, struct remapper, list);
- if((*remapper->proc)(fd, address, is_write, offset))
- return(1);
- }
-
- return(0);
-}
-
/*
* We give a *copy* of the faultinfo in the regs to segv.
* This must be done, since nesting SEGVs could overwrite
@@ -151,8 +124,6 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc)
flush_tlb_kernel_vm();
return(0);
}
- else if(check_remapped_addr(address & PAGE_MASK, is_write))
- return(0);
else if(current->mm == NULL)
panic("Segfault with no mm");
err = handle_page_fault(address, ip, is_write, is_user, &si.si_code);
diff --git a/arch/um/kernel/tt/Makefile b/arch/um/kernel/tt/Makefile
index c3faea21a99..6939e5af847 100644
--- a/arch/um/kernel/tt/Makefile
+++ b/arch/um/kernel/tt/Makefile
@@ -3,27 +3,12 @@
# Licensed under the GPL
#
-extra-y := unmap_fin.o
-targets := unmap.o
-clean-files := unmap_tmp.o
-
obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \
- syscall_kern.o syscall_user.o time.o tlb.o tracer.o trap_user.o \
+ syscall_kern.o syscall_user.o tlb.o tracer.o trap_user.o \
uaccess.o uaccess_user.o
obj-$(CONFIG_PT_PROXY) += gdb_kern.o ptproxy/
-USER_OBJS := gdb.o time.o tracer.o
+USER_OBJS := gdb.o tracer.o
include arch/um/scripts/Makefile.rules
-
-UNMAP_CFLAGS := $(patsubst -pg -DPROFILING,,$(USER_CFLAGS))
-UNMAP_CFLAGS := $(patsubst -fprofile-arcs -ftest-coverage,,$(UNMAP_CFLAGS))
-
-#XXX: partially copied from arch/um/scripts/Makefile.rules
-$(obj)/unmap.o: c_flags = -Wp,-MD,$(depfile) $(UNMAP_CFLAGS)
-
-$(obj)/unmap_fin.o : $(obj)/unmap.o
- $(LD) -r -o $(obj)/unmap_tmp.o $< $(shell $(CC) -print-file-name=libc.a)
- $(OBJCOPY) $(obj)/unmap_tmp.o $@ -G switcheroo
-
diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c
index 19a0ad7b35b..37e22d71a0d 100644
--- a/arch/um/kernel/tt/gdb.c
+++ b/arch/um/kernel/tt/gdb.c
@@ -153,10 +153,10 @@ void remove_gdb_cb(void *unused)
exit_debugger_cb(NULL);
}
-int gdb_remove(char *unused)
+int gdb_remove(int unused)
{
initial_thread_cb(remove_gdb_cb, NULL);
- return(0);
+ return 0;
}
void signal_usr1(int sig)
diff --git a/arch/um/kernel/tt/gdb_kern.c b/arch/um/kernel/tt/gdb_kern.c
index 93fb121f86a..26506388a6a 100644
--- a/arch/um/kernel/tt/gdb_kern.c
+++ b/arch/um/kernel/tt/gdb_kern.c
@@ -10,7 +10,7 @@
#ifdef CONFIG_MCONSOLE
extern int gdb_config(char *str);
-extern int gdb_remove(char *unused);
+extern int gdb_remove(int n);
static struct mc_device gdb_mc = {
.name = "gdb",
diff --git a/arch/um/kernel/tt/include/debug.h b/arch/um/kernel/tt/include/debug.h
index 8eff674107c..738435461e1 100644
--- a/arch/um/kernel/tt/include/debug.h
+++ b/arch/um/kernel/tt/include/debug.h
@@ -4,8 +4,8 @@
* Licensed under the GPL
*/
-#ifndef __DEBUG_H
-#define __DEBUG_H
+#ifndef __UML_TT_DEBUG_H
+#define __UML_TT_DEBUG_H
extern int debugger_proxy(int status, pid_t pid);
extern void child_proxy(pid_t pid, int status);
@@ -13,17 +13,6 @@ extern void init_proxy (pid_t pid, int waiting, int status);
extern int start_debugger(char *prog, int startup, int stop, int *debugger_fd);
extern void fake_child_exit(void);
extern int gdb_config(char *str);
-extern int gdb_remove(char *unused);
+extern int gdb_remove(int unused);
#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tt/include/mode-tt.h b/arch/um/kernel/tt/include/mode-tt.h
index efe46201906..e171e15fead 100644
--- a/arch/um/kernel/tt/include/mode-tt.h
+++ b/arch/um/kernel/tt/include/mode-tt.h
@@ -13,7 +13,6 @@ enum { OP_NONE, OP_EXEC, OP_FORK, OP_TRACE_ON, OP_REBOOT, OP_HALT, OP_CB };
extern int tracing_pid;
extern int tracer(int (*init_proc)(void *), void *sp);
-extern void user_time_init_tt(void);
extern void sig_handler_common_tt(int sig, void *sc);
extern void syscall_handler_tt(int sig, union uml_pt_regs *regs);
extern void reboot_tt(void);
diff --git a/arch/um/kernel/tt/ksyms.c b/arch/um/kernel/tt/ksyms.c
index 92ec85d67c7..84a9385a8fe 100644
--- a/arch/um/kernel/tt/ksyms.c
+++ b/arch/um/kernel/tt/ksyms.c
@@ -12,6 +12,7 @@ EXPORT_SYMBOL(__do_copy_to_user);
EXPORT_SYMBOL(__do_strncpy_from_user);
EXPORT_SYMBOL(__do_strnlen_user);
EXPORT_SYMBOL(__do_clear_user);
+EXPORT_SYMBOL(clear_user_tt);
EXPORT_SYMBOL(tracing_pid);
EXPORT_SYMBOL(honeypot);
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
index df810ca8fc1..a189a2b9293 100644
--- a/arch/um/kernel/tt/process_kern.c
+++ b/arch/um/kernel/tt/process_kern.c
@@ -32,10 +32,6 @@ void *switch_to_tt(void *prev, void *next, void *last)
unsigned long flags;
int err, vtalrm, alrm, prof, cpu;
char c;
- /* jailing and SMP are incompatible, so this doesn't need to be
- * made per-cpu
- */
- static int reading;
from = prev;
to = next;
@@ -59,13 +55,11 @@ void *switch_to_tt(void *prev, void *next, void *last)
c = 0;
set_current(to);
- reading = 0;
err = os_write_file(to->thread.mode.tt.switch_pipe[1], &c, sizeof(c));
if(err != sizeof(c))
panic("write of switch_pipe failed, err = %d", -err);
- reading = 1;
- if(from->thread.mode.tt.switch_pipe[0] == -1)
+ if(from->thread.mode.tt.switch_pipe[0] == -1)
os_kill_process(os_getpid(), 0);
err = os_read_file(from->thread.mode.tt.switch_pipe[0], &c, sizeof(c));
@@ -272,10 +266,10 @@ int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp,
}
if(current->thread.forking){
- sc_to_sc(UPT_SC(&p->thread.regs.regs),
- UPT_SC(&current->thread.regs.regs));
+ sc_to_sc(UPT_SC(&p->thread.regs.regs), UPT_SC(&regs->regs));
SC_SET_SYSCALL_RETURN(UPT_SC(&p->thread.regs.regs), 0);
- if(sp != 0) SC_SP(UPT_SC(&p->thread.regs.regs)) = sp;
+ if(sp != 0)
+ SC_SP(UPT_SC(&p->thread.regs.regs)) = sp;
}
p->thread.mode.tt.extern_pid = new_pid;
@@ -465,14 +459,3 @@ int is_valid_pid(int pid)
read_unlock(&tasklist_lock);
return(0);
}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tt/time.c b/arch/um/kernel/tt/time.c
deleted file mode 100644
index 8565b71b07c..00000000000
--- a/arch/um/kernel/tt/time.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <signal.h>
-#include <sys/time.h>
-#include <time_user.h>
-#include "process.h"
-#include "user.h"
-
-void user_time_init_tt(void)
-{
- if(signal(SIGVTALRM, (__sighandler_t) alarm_handler) == SIG_ERR)
- panic("Couldn't set SIGVTALRM handler");
- set_interval(ITIMER_VIRTUAL);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tt/unmap.c b/arch/um/kernel/tt/unmap.c
deleted file mode 100644
index 3f7aecdbe53..00000000000
--- a/arch/um/kernel/tt/unmap.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <sys/mman.h>
-
-int switcheroo(int fd, int prot, void *from, void *to, int size)
-{
- if(munmap(to, size) < 0){
- return(-1);
- }
- if(mmap(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) != to){
- return(-1);
- }
- if(munmap(from, size) < 0){
- return(-1);
- }
- return(0);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 4d10ec372a6..8736d098f0e 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -26,7 +26,6 @@
#include "asm/setup.h"
#include "ubd_user.h"
#include "asm/current.h"
-#include "asm/setup.h"
#include "user_util.h"
#include "kern_util.h"
#include "kern.h"
@@ -111,12 +110,6 @@ struct seq_operations cpuinfo_op = {
.show = show_cpuinfo,
};
-pte_t * __bad_pagetable(void)
-{
- panic("Someone should implement __bad_pagetable");
- return(NULL);
-}
-
/* Set in linux_main */
unsigned long host_task_size;
unsigned long task_size;
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
index 76eadb30918..61dfd4fef75 100644
--- a/arch/um/kernel/uml.lds.S
+++ b/arch/um/kernel/uml.lds.S
@@ -14,19 +14,10 @@ SECTIONS
/* Used in arch/um/kernel/mem.c. Any memory between START and __binary_start
* is remapped.*/
__binary_start = .;
-#ifdef MODE_TT
- .thread_private : {
- __start_thread_private = .;
- errno = .;
- . += 4;
- arch/um/kernel/tt/unmap_fin.o (.data)
- __end_thread_private = .;
- }
- . = ALIGN(4096);
- .remap : { arch/um/kernel/tt/unmap_fin.o (.text) }
- /* We want it only if we are in MODE_TT. In both cases, however, when MODE_TT
- * is off the resulting binary segfaults.*/
+#ifdef MODE_TT
+ .remap_data : { arch/um/sys-SUBARCH/unmap_fin.o (.data .bss) }
+ .remap : { arch/um/sys-SUBARCH/unmap_fin.o (.text) }
. = ALIGN(4096); /* Init code and data */
#endif
@@ -73,6 +64,8 @@ SECTIONS
.got : { *(.got.plt) *(.got) }
.dynamic : { *(.dynamic) }
+ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
/* We want the small data sections together, so single-instruction offsets
can access them all, and initialized data all before uninitialized, so
we can shorten the on-disk segment size. */
diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c
index 9aee0b62ebc..f0d6060e3e5 100644
--- a/arch/um/os-Linux/elf_aux.c
+++ b/arch/um/os-Linux/elf_aux.c
@@ -45,7 +45,11 @@ __init void scan_elf_aux( char **envp)
elf_aux_hwcap = auxv->a_un.a_val;
break;
case AT_PLATFORM:
- elf_aux_platform = auxv->a_un.a_ptr;
+ /* elf.h removed the pointer elements from
+ * a_un, so we have to use a_val, which is
+ * all that's left.
+ */
+ elf_aux_platform = (char *) auxv->a_un.a_val;
break;
case AT_PAGESZ:
page_size = auxv->a_un.a_val;
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index 77d4066d1af..fd45bb26090 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -363,7 +363,7 @@ int os_write_file(int fd, const void *buf, int len)
(int (*)(int, void *, int)) write, copy_to_user_proc));
}
-int os_file_size(char *file, long long *size_out)
+int os_file_size(char *file, unsigned long long *size_out)
{
struct uml_stat buf;
int err;
diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules
index 0b2491883d9..7459d09c233 100644
--- a/arch/um/scripts/Makefile.rules
+++ b/arch/um/scripts/Makefile.rules
@@ -10,11 +10,17 @@ USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
$(USER_OBJS) : c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) \
$(CFLAGS_$(notdir $@))
+# The stubs and unmap.o can't try to call mcount or update basic block data
+define unprofile
+ $(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1)))
+endef
+
+
quiet_cmd_make_link = SYMLINK $@
cmd_make_link = ln -sf $(srctree)/arch/$(SUBARCH)/$($(notdir $@)-dir)/$(notdir $@) $@
# this needs to be before the foreach, because targets does not accept
-# complete paths like $(obj)/$(f). To make sure this works, use a := assignment,
+# complete paths like $(obj)/$(f). To make sure this works, use a := assignment
# or we will get $(obj)/$(f) in the "targets" value.
# Also, this forces you to use the := syntax when assigning to targets.
# Otherwise the line below will cause an infinite loop (if you don't know why,
diff --git a/arch/um/scripts/Makefile.unmap b/arch/um/scripts/Makefile.unmap
new file mode 100644
index 00000000000..37a8f976529
--- /dev/null
+++ b/arch/um/scripts/Makefile.unmap
@@ -0,0 +1,22 @@
+clean-files += unmap_tmp.o unmap_fin.o unmap.o
+
+ifdef CONFIG_MODE_TT
+
+#Always build unmap_fin.o
+extra-y += unmap_fin.o
+#Do dependency tracking for unmap.o (it will be always built, but won't get the tracking unless we use this).
+targets += unmap.o
+
+#XXX: partially copied from arch/um/scripts/Makefile.rules
+$(obj)/unmap.o: _c_flags = $(call unprofile,$(CFLAGS))
+
+quiet_cmd_wrapld = LD $@
+define cmd_wrapld
+ $(LD) -r -o $(obj)/unmap_tmp.o $< $(shell $(CC) -print-file-name=libc.a); \
+ $(OBJCOPY) $(obj)/unmap_tmp.o $@ -G switcheroo
+endef
+
+$(obj)/unmap_fin.o : $(obj)/unmap.o FORCE
+ $(call if_changed,wrapld)
+
+endif
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index fcd67c3414e..095bcdb0b9c 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -9,6 +9,8 @@ USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o
SYMLINKS = bitops.c semaphore.c highmem.c module.c
+include arch/um/scripts/Makefile.rules
+
bitops.c-dir = lib
semaphore.c-dir = kernel
highmem.c-dir = mm
@@ -16,4 +18,4 @@ module.c-dir = kernel
subdir- := util
-include arch/um/scripts/Makefile.rules
+include arch/um/scripts/Makefile.unmap
diff --git a/arch/um/sys-i386/delay.c b/arch/um/sys-i386/delay.c
index e9892eef51c..2c11b9770e8 100644
--- a/arch/um/sys-i386/delay.c
+++ b/arch/um/sys-i386/delay.c
@@ -1,5 +1,7 @@
-#include "linux/delay.h"
-#include "asm/param.h"
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <asm/param.h>
void __delay(unsigned long time)
{
@@ -20,13 +22,19 @@ void __udelay(unsigned long usecs)
int i, n;
n = (loops_per_jiffy * HZ * usecs) / MILLION;
- for(i=0;i<n;i++) ;
+ for(i=0;i<n;i++)
+ cpu_relax();
}
+EXPORT_SYMBOL(__udelay);
+
void __const_udelay(unsigned long usecs)
{
int i, n;
n = (loops_per_jiffy * HZ * usecs) / MILLION;
- for(i=0;i<n;i++) ;
+ for(i=0;i<n;i++)
+ cpu_relax();
}
+
+EXPORT_SYMBOL(__const_udelay);
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index 03913ca5d25..4efc69a039d 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -312,7 +312,7 @@ long sys_sigreturn(struct pt_regs regs)
unsigned long __user *extramask = frame->extramask;
int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
- if(copy_from_user(&set.sig[0], oldmask, sizeof(&set.sig[0])) ||
+ if(copy_from_user(&set.sig[0], oldmask, sizeof(set.sig[0])) ||
copy_from_user(&set.sig[1], extramask, sig_size))
goto segfault;
diff --git a/arch/um/sys-i386/syscalls.c b/arch/um/sys-i386/syscalls.c
index 335e2d89504..83e9be820a8 100644
--- a/arch/um/sys-i386/syscalls.c
+++ b/arch/um/sys-i386/syscalls.c
@@ -69,15 +69,11 @@ long sys_clone(unsigned long clone_flags, unsigned long newsp,
{
long ret;
- /* XXX: normal arch do here this pass, and also pass the regs to
- * do_fork, instead of NULL. Currently the arch-independent code
- * ignores these values, while the UML code (actually it's
- * copy_thread) does the right thing. But this should change,
- probably. */
- /*if (!newsp)
- newsp = UPT_SP(current->thread.regs);*/
+ if (!newsp)
+ newsp = UPT_SP(&current->thread.regs.regs);
current->thread.forking = 1;
- ret = do_fork(clone_flags, newsp, NULL, 0, parent_tid, child_tid);
+ ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
+ child_tid);
current->thread.forking = 0;
return(ret);
}
@@ -197,14 +193,3 @@ long sys_sigaction(int sig, const struct old_sigaction __user *act,
return ret;
}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/sys-i386/sysrq.c b/arch/um/sys-i386/sysrq.c
index 281fc7b8ca0..e3706d15c4f 100644
--- a/arch/um/sys-i386/sysrq.c
+++ b/arch/um/sys-i386/sysrq.c
@@ -3,12 +3,15 @@
* Licensed under the GPL
*/
+#include "linux/config.h"
#include "linux/kernel.h"
#include "linux/smp.h"
#include "linux/sched.h"
+#include "linux/kallsyms.h"
#include "asm/ptrace.h"
#include "sysrq.h"
+/* This is declared by <linux/sched.h> */
void show_regs(struct pt_regs *regs)
{
printk("\n");
@@ -31,5 +34,80 @@ void show_regs(struct pt_regs *regs)
0xffff & PT_REGS_DS(regs),
0xffff & PT_REGS_ES(regs));
- show_trace((unsigned long *) &regs);
+ show_trace(NULL, (unsigned long *) &regs);
}
+
+/* Copied from i386. */
+static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
+{
+ return p > (void *)tinfo &&
+ p < (void *)tinfo + THREAD_SIZE - 3;
+}
+
+/* Adapted from i386 (we also print the address we read from). */
+static inline unsigned long print_context_stack(struct thread_info *tinfo,
+ unsigned long *stack, unsigned long ebp)
+{
+ unsigned long addr;
+
+#ifdef CONFIG_FRAME_POINTER
+ while (valid_stack_ptr(tinfo, (void *)ebp)) {
+ addr = *(unsigned long *)(ebp + 4);
+ printk("%08lx: [<%08lx>]", ebp + 4, addr);
+ print_symbol(" %s", addr);
+ printk("\n");
+ ebp = *(unsigned long *)ebp;
+ }
+#else
+ while (valid_stack_ptr(tinfo, stack)) {
+ addr = *stack;
+ if (__kernel_text_address(addr)) {
+ printk("%08lx: [<%08lx>]", (unsigned long) stack, addr);
+ print_symbol(" %s", addr);
+ printk("\n");
+ }
+ stack++;
+ }
+#endif
+ return ebp;
+}
+
+void show_trace(struct task_struct* task, unsigned long * stack)
+{
+ unsigned long ebp;
+ struct thread_info *context;
+
+ /* Turn this into BUG_ON if possible. */
+ if (!stack) {
+ stack = (unsigned long*) &stack;
+ printk("show_trace: got NULL stack, implicit assumption task == current");
+ WARN_ON(1);
+ }
+
+ if (!task)
+ task = current;
+
+ if (task != current) {
+ //ebp = (unsigned long) KSTK_EBP(task);
+ /* Which one? No actual difference - just coding style.*/
+ ebp = (unsigned long) PT_REGS_EBP(&task->thread.regs);
+ } else {
+ asm ("movl %%ebp, %0" : "=r" (ebp) : );
+ }
+
+ context = (struct thread_info *)
+ ((unsigned long)stack & (~(THREAD_SIZE - 1)));
+ print_context_stack(context, stack, ebp);
+
+ /*while (((long) stack & (THREAD_SIZE-1)) != 0) {
+ addr = *stack;
+ if (__kernel_text_address(addr)) {
+ printk("%08lx: [<%08lx>]", (unsigned long) stack, addr);
+ print_symbol(" %s", addr);
+ printk("\n");
+ }
+ stack++;
+ }*/
+ printk("\n");
+}
+
diff --git a/arch/um/sys-i386/unmap.c b/arch/um/sys-i386/unmap.c
new file mode 100644
index 00000000000..136875263d2
--- /dev/null
+++ b/arch/um/sys-i386/unmap.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <linux/mman.h>
+#include <asm/unistd.h>
+
+static int errno;
+
+static inline _syscall2(int,munmap,void *,start,size_t,len)
+static inline _syscall6(void *,mmap2,void *,addr,size_t,len,int,prot,int,flags,int,fd,off_t,offset)
+int switcheroo(int fd, int prot, void *from, void *to, int size)
+{
+ if(munmap(to, size) < 0){
+ return(-1);
+ }
+ if(mmap2(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) != to){
+ return(-1);
+ }
+ if(munmap(from, size) < 0){
+ return(-1);
+ }
+ return(0);
+}
diff --git a/arch/um/sys-ppc/sysrq.c b/arch/um/sys-ppc/sysrq.c
index 82d6e9335bb..2f816f1a0ff 100644
--- a/arch/um/sys-ppc/sysrq.c
+++ b/arch/um/sys-ppc/sysrq.c
@@ -27,17 +27,5 @@ void show_regs(struct pt_regs_subarch *regs)
0xffff & regs->xds, 0xffff & regs->xes);
#endif
- show_trace(&regs->gpr[1]);
+ show_trace(current, &regs->gpr[1]);
}
-
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
index 3d7da911cc8..2bc6f684901 100644
--- a/arch/um/sys-x86_64/Makefile
+++ b/arch/um/sys-x86_64/Makefile
@@ -14,11 +14,11 @@ obj-$(CONFIG_MODULES) += module.o um_module.o
USER_OBJS := ptrace_user.o sigcontext.o
-include arch/um/scripts/Makefile.rules
-
SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c memcpy.S \
semaphore.c thunk.S module.c
+include arch/um/scripts/Makefile.rules
+
bitops.c-dir = lib
csum-copy.S-dir = lib
csum-partial.c-dir = lib
@@ -28,6 +28,6 @@ semaphore.c-dir = kernel
thunk.S-dir = lib
module.c-dir = kernel
-CFLAGS_csum-partial.o := -Dcsum_partial=arch_csum_partial
-
subdir- := util
+
+include arch/um/scripts/Makefile.unmap
diff --git a/arch/um/sys-x86_64/delay.c b/arch/um/sys-x86_64/delay.c
index 651332aeec2..137f4446b43 100644
--- a/arch/um/sys-x86_64/delay.c
+++ b/arch/um/sys-x86_64/delay.c
@@ -5,40 +5,37 @@
* Licensed under the GPL
*/
-#include "linux/delay.h"
-#include "asm/processor.h"
-#include "asm/param.h"
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <asm/processor.h>
+#include <asm/param.h>
void __delay(unsigned long loops)
{
unsigned long i;
- for(i = 0; i < loops; i++) ;
+ for(i = 0; i < loops; i++)
+ cpu_relax();
}
void __udelay(unsigned long usecs)
{
- int i, n;
+ unsigned long i, n;
n = (loops_per_jiffy * HZ * usecs) / MILLION;
- for(i=0;i<n;i++) ;
+ for(i=0;i<n;i++)
+ cpu_relax();
}
+EXPORT_SYMBOL(__udelay);
+
void __const_udelay(unsigned long usecs)
{
- int i, n;
+ unsigned long i, n;
n = (loops_per_jiffy * HZ * usecs) / MILLION;
- for(i=0;i<n;i++) ;
+ for(i=0;i<n;i++)
+ cpu_relax();
}
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+EXPORT_SYMBOL(__const_udelay);
diff --git a/arch/um/sys-x86_64/ksyms.c b/arch/um/sys-x86_64/ksyms.c
index a27f0ee6a4f..85927380820 100644
--- a/arch/um/sys-x86_64/ksyms.c
+++ b/arch/um/sys-x86_64/ksyms.c
@@ -16,5 +16,4 @@ EXPORT_SYMBOL(__up_wakeup);
EXPORT_SYMBOL(__memcpy);
/* Networking helper routines. */
-/*EXPORT_SYMBOL(csum_partial_copy_from);
-EXPORT_SYMBOL(csum_partial_copy_to);*/
+EXPORT_SYMBOL(ip_compute_csum);
diff --git a/arch/um/sys-x86_64/ptrace.c b/arch/um/sys-x86_64/ptrace.c
index b593bb256f2..74eee5c7c6d 100644
--- a/arch/um/sys-x86_64/ptrace.c
+++ b/arch/um/sys-x86_64/ptrace.c
@@ -5,10 +5,11 @@
*/
#define __FRAME_OFFSETS
-#include "asm/ptrace.h"
-#include "linux/sched.h"
-#include "linux/errno.h"
-#include "asm/elf.h"
+#include <asm/ptrace.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+#include <asm/elf.h>
/* XXX x86_64 */
unsigned long not_ss;
diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c
index dd9914642b8..3259a4db453 100644
--- a/arch/um/sys-x86_64/syscalls.c
+++ b/arch/um/sys-x86_64/syscalls.c
@@ -15,6 +15,7 @@
#include "asm/unistd.h"
#include "asm/prctl.h" /* XXX This should get the constants from libc */
#include "choose-mode.h"
+#include "kern.h"
asmlinkage long sys_uname64(struct new_utsname __user * name)
{
@@ -132,23 +133,27 @@ static long arch_prctl_tt(int code, unsigned long addr)
#ifdef CONFIG_MODE_SKAS
+/* XXX: Must also call arch_prctl in the host, beside saving the segment bases! */
static long arch_prctl_skas(int code, unsigned long addr)
{
long ret = 0;
switch(code){
- case ARCH_SET_GS:
- current->thread.regs.regs.skas.regs[GS_BASE / sizeof(unsigned long)] = addr;
- break;
case ARCH_SET_FS:
current->thread.regs.regs.skas.regs[FS_BASE / sizeof(unsigned long)] = addr;
break;
+ case ARCH_SET_GS:
+ current->thread.regs.regs.skas.regs[GS_BASE / sizeof(unsigned long)] = addr;
+ break;
case ARCH_GET_FS:
- ret = put_user(current->thread.regs.regs.skas.regs[GS / sizeof(unsigned long)], &addr);
+ ret = put_user(current->thread.regs.regs.skas.
+ regs[FS_BASE / sizeof(unsigned long)],
+ (unsigned long __user *)addr);
break;
case ARCH_GET_GS:
- ret = put_user(current->thread.regs.regs.skas.regs[FS / sizeof(unsigned \
-long)], &addr);
+ ret = put_user(current->thread.regs.regs.skas.
+ regs[GS_BASE / sizeof(unsigned long)],
+ (unsigned long __user *)addr);
break;
default:
ret = -EINVAL;
@@ -169,26 +174,11 @@ long sys_clone(unsigned long clone_flags, unsigned long newsp,
{
long ret;
- /* XXX: normal arch do here this pass, and also pass the regs to
- * do_fork, instead of NULL. Currently the arch-independent code
- * ignores these values, while the UML code (actually it's
- * copy_thread) does the right thing. But this should change,
- probably. */
- /*if (!newsp)
- newsp = UPT_SP(current->thread.regs);*/
+ if (!newsp)
+ newsp = UPT_SP(&current->thread.regs.regs);
current->thread.forking = 1;
- ret = do_fork(clone_flags, newsp, NULL, 0, parent_tid, child_tid);
+ ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
+ child_tid);
current->thread.forking = 0;
return(ret);
}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/sys-x86_64/sysrq.c b/arch/um/sys-x86_64/sysrq.c
index ddf74691a61..d0a25af19a5 100644
--- a/arch/um/sys-x86_64/sysrq.c
+++ b/arch/um/sys-x86_64/sysrq.c
@@ -36,14 +36,5 @@ void __show_regs(struct pt_regs * regs)
void show_regs(struct pt_regs *regs)
{
__show_regs(regs);
- show_trace((unsigned long *) &regs);
+ show_trace(current, (unsigned long *) &regs);
}
-
-/* Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/sys-x86_64/unmap.c b/arch/um/sys-x86_64/unmap.c
new file mode 100644
index 00000000000..bc7094cce47
--- /dev/null
+++ b/arch/um/sys-x86_64/unmap.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <linux/mman.h>
+#include <asm/unistd.h>
+
+static int errno;
+
+static inline _syscall2(int,munmap,void *,start,size_t,len)
+static inline _syscall6(void *,mmap,void *,addr,size_t,len,int,prot,int,flags,int,fd,off_t,offset)
+int switcheroo(int fd, int prot, void *from, void *to, int size)
+{
+ if(munmap(to, size) < 0){
+ return(-1);
+ }
+ if(mmap(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) != to){
+ return(-1);
+ }
+ if(munmap(from, size) < 0){
+ return(-1);
+ }
+ return(0);
+}
diff --git a/arch/um/sys-x86_64/user-offsets.c b/arch/um/sys-x86_64/user-offsets.c
index 5e14792e483..513d17ceafd 100644
--- a/arch/um/sys-x86_64/user-offsets.c
+++ b/arch/um/sys-x86_64/user-offsets.c
@@ -3,6 +3,14 @@
#include <signal.h>
#define __FRAME_OFFSETS
#include <asm/ptrace.h>
+#include <asm/types.h>
+/* For some reason, x86_64 defines u64 and u32 only in <pci/types.h>, which I
+ * refuse to include here, even though they're used throughout the headers.
+ * These are used in asm/user.h, and that include can't be avoided because of
+ * the sizeof(struct user_regs_struct) below.
+ */
+typedef __u64 u64;
+typedef __u32 u32;
#include <asm/user.h>
#define DEFINE(sym, val) \
diff --git a/arch/v850/Kconfig b/arch/v850/Kconfig
index 90cd4baa75e..27febd6ffa8 100644
--- a/arch/v850/Kconfig
+++ b/arch/v850/Kconfig
@@ -218,6 +218,8 @@ menu "Processor type and features"
a lot of RAM, and you need to able to allocate very large
contiguous chunks. If unsure, say N.
+source "mm/Kconfig"
+
endmenu
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 44ee7f6acf7..d09437b5c48 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -207,33 +207,6 @@ config SMP
If you don't know what to do here, say N.
-config PREEMPT
- bool "Preemptible Kernel"
- ---help---
- This option reduces the latency of the kernel when reacting to
- real-time or interactive events by allowing a low priority process to
- be preempted even if it is in kernel mode executing a system call.
- This allows applications to run more reliably even when the system is
- under load. On contrary it may also break your drivers and add
- priority inheritance problems to your system. Don't select it if
- you rely on a stable system or have slightly obscure hardware.
- It's also not very well tested on x86-64 currently.
- You have been warned.
-
- Say Y here if you are feeling brave and building a kernel for a
- desktop, embedded or real-time system. Say N if you are unsure.
-
-config PREEMPT_BKL
- bool "Preempt The Big Kernel Lock"
- depends on PREEMPT
- default y
- help
- This option reduces the latency of the kernel by making the
- big kernel lock preemptible.
-
- Say Y here if you are building a kernel for a desktop system.
- Say N if you are unsure.
-
config SCHED_SMT
bool "SMT (Hyperthreading) scheduler support"
depends on SMP
@@ -244,6 +217,8 @@ config SCHED_SMT
cost of slightly increased overhead in some places. If unsure say
N here.
+source "kernel/Kconfig.preempt"
+
config K8_NUMA
bool "K8 NUMA support"
select NUMA
@@ -265,7 +240,7 @@ config NUMA_EMU
into virtual nodes when booted with "numa=fake=N", where N is the
number of nodes. This is only useful for debugging.
-config DISCONTIGMEM
+config ARCH_DISCONTIGMEM_ENABLE
bool
depends on NUMA
default y
@@ -274,6 +249,27 @@ config NUMA
bool
default n
+config ARCH_DISCONTIGMEM_ENABLE
+ def_bool y
+ depends on NUMA
+
+config ARCH_DISCONTIGMEM_DEFAULT
+ def_bool y
+ depends on NUMA
+
+config ARCH_SPARSEMEM_ENABLE
+ def_bool y
+ depends on NUMA
+
+config ARCH_FLATMEM_ENABLE
+ def_bool y
+ depends on !NUMA
+
+source "mm/Kconfig"
+
+config HAVE_ARCH_EARLY_PFN_TO_NID
+ def_bool y
+
config HAVE_DEC_LOCK
bool
depends on SMP
@@ -292,6 +288,15 @@ config NR_CPUS
This is purely to save memory - each supported CPU requires
memory in the static kernel configuration.
+config HOTPLUG_CPU
+ bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
+ depends on SMP && HOTPLUG && EXPERIMENTAL
+ help
+ Say Y here to experiment with turning CPUs off and on. CPUs
+ can be controlled through /sys/devices/system/cpu/cpu#.
+ Say N if you want to disable CPU hotplug.
+
+
config HPET_TIMER
bool
default y
@@ -303,6 +308,21 @@ config HPET_TIMER
as it is off-chip. You can find the HPET spec at
<http://www.intel.com/labs/platcomp/hpet/hpetspec.htm>.
+config X86_PM_TIMER
+ bool "PM timer"
+ depends on ACPI
+ default y
+ help
+ Support the ACPI PM timer for time keeping. This is slow,
+ but is useful on some chipsets without HPET on systems with more
+ than one CPU. On a single processor or single socket multi core
+ system it is normally not required.
+ When the PM timer is active 64bit vsyscalls are disabled
+ and should not be enabled (/proc/sys/kernel/vsyscall64 should
+ not be changed).
+ The kernel selects the PM timer only as a last resort, so it is
+ useful to enable just in case.
+
config HPET_EMULATE_RTC
bool "Provide RTC interrupt"
depends on HPET_TIMER && RTC=y
@@ -349,6 +369,34 @@ config X86_MCE_INTEL
Additional support for intel specific MCE features such as
the thermal monitor.
+config PHYSICAL_START
+ hex "Physical address where the kernel is loaded" if EMBEDDED
+ default "0x100000"
+ help
+ This gives the physical address where the kernel is loaded.
+ Primarily used in the case of kexec on panic where the
+ fail safe kernel needs to run at a different address than
+ the panic-ed kernel.
+
+ Don't change this unless you know what you are doing.
+
+config KEXEC
+ bool "kexec system call (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ help
+ kexec is a system call that implements the ability to shutdown your
+ current kernel, and to start another kernel. It is like a reboot
+ but it is indepedent of the system firmware. And like a reboot
+ you can start any kernel with it, not just Linux.
+
+ The name comes from the similiarity to the exec system call.
+
+ It is an ongoing process to be certain the hardware in a machine
+ is properly shutdown, so do not be surprised if this code does not
+ initially work for you. It may help to enable device hotplugging
+ support. As of this writing the exact hardware interface is
+ strongly in flux, so no good recommendation can be made.
+
config SECCOMP
bool "Enable seccomp to safely compute untrusted bytecode"
depends on PROC_FS
@@ -366,6 +414,8 @@ config SECCOMP
If unsure, say Y. Only embedded should say N here.
+source kernel/Kconfig.hz
+
endmenu
#
@@ -407,7 +457,7 @@ config PCI_DIRECT
config PCI_MMCONFIG
bool "Support mmconfig PCI config space access"
- depends on PCI
+ depends on PCI && ACPI
select ACPI_BOOT
config UNORDERED_IO
diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile
index 6f90c246c41..8a73794f9b9 100644
--- a/arch/x86_64/Makefile
+++ b/arch/x86_64/Makefile
@@ -35,7 +35,7 @@ export IA32_CC IA32_LD IA32_AS IA32_OBJCOPY IA32_CPP
LDFLAGS := -m elf_x86_64
OBJCOPYFLAGS := -O binary -R .note -R .comment -S
-LDFLAGS_vmlinux := -e stext
+LDFLAGS_vmlinux :=
CHECKFLAGS += -D__x86_64__ -m64
diff --git a/arch/x86_64/boot/compressed/head.S b/arch/x86_64/boot/compressed/head.S
index 27264dbd575..6f55565e4d4 100644
--- a/arch/x86_64/boot/compressed/head.S
+++ b/arch/x86_64/boot/compressed/head.S
@@ -2,8 +2,6 @@
* linux/boot/head.S
*
* Copyright (C) 1991, 1992, 1993 Linus Torvalds
- *
- * $Id: head.S,v 1.3 2001/04/20 00:59:28 ak Exp $
*/
/*
@@ -21,13 +19,14 @@
*/
/*
- * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
+ * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
*/
.code32
.text
#include <linux/linkage.h>
#include <asm/segment.h>
+#include <asm/page.h>
.code32
.globl startup_32
@@ -77,7 +76,7 @@ startup_32:
jnz 3f
addl $8,%esp
xorl %ebx,%ebx
- ljmp $(__KERNEL_CS), $0x100000
+ ljmp $(__KERNEL_CS), $__PHYSICAL_START
/*
* We come here, if we were loaded high.
@@ -103,7 +102,7 @@ startup_32:
popl %ecx # lcount
popl %edx # high_buffer_start
popl %eax # hcount
- movl $0x100000,%edi
+ movl $__PHYSICAL_START,%edi
cli # make sure we don't get interrupted
ljmp $(__KERNEL_CS), $0x1000 # and jump to the move routine
@@ -128,7 +127,7 @@ move_routine_start:
movsl
movl %ebx,%esi # Restore setup pointer
xorl %ebx,%ebx
- ljmp $(__KERNEL_CS), $0x100000
+ ljmp $(__KERNEL_CS), $__PHYSICAL_START
move_routine_end:
diff --git a/arch/x86_64/boot/compressed/misc.c b/arch/x86_64/boot/compressed/misc.c
index c8b9216f9e6..b38d5b8b5fb 100644
--- a/arch/x86_64/boot/compressed/misc.c
+++ b/arch/x86_64/boot/compressed/misc.c
@@ -11,6 +11,7 @@
#include "miscsetup.h"
#include <asm/io.h>
+#include <asm/page.h>
/*
* gzip declarations
@@ -92,8 +93,11 @@ static unsigned long output_ptr = 0;
static void *malloc(int size);
static void free(void *where);
+void* memset(void* s, int c, unsigned n);
+void* memcpy(void* dest, const void* src, unsigned n);
+
static void putstr(const char *);
-
+
extern int end;
static long free_mem_ptr = (long)&end;
static long free_mem_end_ptr;
@@ -284,7 +288,7 @@ void setup_normal_output_buffer(void)
#else
if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024) error("Less than 2MB of memory");
#endif
- output_data = (char *)0x100000; /* Points to 1M */
+ output_data = (char *)__PHYSICAL_START; /* Normally Points to 1M */
free_mem_end_ptr = (long)real_mode;
}
@@ -307,8 +311,8 @@ void setup_output_buffer_if_we_run_high(struct moveparams *mv)
low_buffer_size = low_buffer_end - LOW_BUFFER_START;
high_loaded = 1;
free_mem_end_ptr = (long)high_buffer_start;
- if ( (0x100000 + low_buffer_size) > ((ulg)high_buffer_start)) {
- high_buffer_start = (uch *)(0x100000 + low_buffer_size);
+ if ( (__PHYSICAL_START + low_buffer_size) > ((ulg)high_buffer_start)) {
+ high_buffer_start = (uch *)(__PHYSICAL_START + low_buffer_size);
mv->hcount = 0; /* say: we need not to move high_buffer */
}
else mv->hcount = -1;
diff --git a/arch/x86_64/boot/install.sh b/arch/x86_64/boot/install.sh
index 90f2452b3b9..198af15a775 100644
--- a/arch/x86_64/boot/install.sh
+++ b/arch/x86_64/boot/install.sh
@@ -1,6 +1,6 @@
#!/bin/sh
#
-# arch/i386/boot/install.sh
+# arch/x86_64/boot/install.sh
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
@@ -21,8 +21,8 @@
# User may have a custom install script
-if [ -x ~/bin/installkernel ]; then exec ~/bin/installkernel "$@"; fi
-if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi
+if [ -x ~/bin/${CROSS_COMPILE}installkernel ]; then exec ~/bin/${CROSS_COMPILE}installkernel "$@"; fi
+if [ -x /sbin/${CROSS_COMPILE}installkernel ]; then exec /sbin/${CROSS_COMPILE}installkernel "$@"; fi
# Default install - same as make zlilo
diff --git a/arch/x86_64/boot/setup.S b/arch/x86_64/boot/setup.S
index 75d4d2ad93b..ff58b2832b7 100644
--- a/arch/x86_64/boot/setup.S
+++ b/arch/x86_64/boot/setup.S
@@ -33,7 +33,7 @@
* Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999.
* <stiker@northlink.com>
*
- * Fix to work around buggy BIOSes which dont use carry bit correctly
+ * Fix to work around buggy BIOSes which don't use carry bit correctly
* and/or report extended memory in CX/DX for e801h memory size detection
* call. As a result the kernel got wrong figures. The int15/e801h docs
* from Ralf Brown interrupt list seem to indicate AX/BX should be used
@@ -383,7 +383,7 @@ sse_ok:
# a whole bunch of different types, and allows memory holes and
# everything. We scan through this memory map and build a list
# of the first 32 memory areas, which we return at [E820MAP].
-# This is documented at http://www.teleport.com/~acpi/acpihtml/topic245.htm
+# This is documented at http://www.acpi.info/, in the ACPI 2.0 specification.
#define SMAP 0x534d4150
@@ -436,7 +436,7 @@ bail820:
meme801:
stc # fix to work around buggy
- xorw %cx,%cx # BIOSes which dont clear/set
+ xorw %cx,%cx # BIOSes which don't clear/set
xorw %dx,%dx # carry on pass/error of
# e801h memory size call
# or merely pass cx,dx though
@@ -733,7 +733,7 @@ flush_instr:
#
# but we yet haven't reloaded the CS register, so the default size
# of the target offset still is 16 bit.
-# However, using an operant prefix (0x66), the CPU will properly
+# However, using an operand prefix (0x66), the CPU will properly
# take our 48 bit far pointer. (INTeL 80386 Programmer's Reference
# Manual, Mixing 16-bit and 32-bit code, page 16-6)
diff --git a/arch/x86_64/boot/tools/build.c b/arch/x86_64/boot/tools/build.c
index c2fa6631317..18b5bac1c42 100644
--- a/arch/x86_64/boot/tools/build.c
+++ b/arch/x86_64/boot/tools/build.c
@@ -1,6 +1,4 @@
/*
- * $Id: build.c,v 1.3 2001/06/26 15:14:50 pavel Exp $
- *
* Copyright (C) 1991, 1992 Linus Torvalds
* Copyright (C) 1997 Martin Mares
*/
@@ -8,7 +6,8 @@
/*
* This file builds a disk-image from three different files:
*
- * - bootsect: exactly 512 bytes of 8086 machine code, loads the rest
+ * - bootsect: compatibility mbr which prints an error message if
+ * someone tries to boot the kernel directly.
* - setup: 8086 machine code, sets up system parm
* - system: 80386 code for actual system
*
diff --git a/arch/x86_64/defconfig b/arch/x86_64/defconfig
index 9ce51dee30b..569595b74c7 100644
--- a/arch/x86_64/defconfig
+++ b/arch/x86_64/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-bk7
-# Sat Mar 12 23:43:44 2005
+# Linux kernel version: 2.6.12-rc4
+# Fri May 13 06:39:11 2005
#
CONFIG_X86_64=y
CONFIG_64BIT=y
@@ -11,8 +11,6 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_X86_CMPXCHG=y
CONFIG_EARLY_PRINTK=y
-CONFIG_HPET_TIMER=y
-CONFIG_HPET_EMULATE_RTC=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_GENERIC_IOMAP=y
@@ -22,6 +20,7 @@ CONFIG_GENERIC_IOMAP=y
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
#
# General setup
@@ -33,7 +32,6 @@ CONFIG_POSIX_MQUEUE=y
# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=18
# CONFIG_HOTPLUG is not set
CONFIG_KOBJECT_UEVENT=y
CONFIG_IKCONFIG=y
@@ -43,10 +41,11 @@ CONFIG_IKCONFIG_PROC=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SHMEM=y
CONFIG_CC_ALIGN_FUNCTIONS=0
CONFIG_CC_ALIGN_LABELS=0
@@ -93,6 +92,9 @@ CONFIG_DISCONTIGMEM=y
CONFIG_NUMA=y
CONFIG_HAVE_DEC_LOCK=y
CONFIG_NR_CPUS=8
+CONFIG_HPET_TIMER=y
+CONFIG_X86_PM_TIMER=y
+CONFIG_HPET_EMULATE_RTC=y
CONFIG_GART_IOMMU=y
CONFIG_SWIOTLB=y
CONFIG_X86_MCE=y
@@ -100,6 +102,7 @@ CONFIG_X86_MCE_INTEL=y
CONFIG_SECCOMP=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_ISA_DMA_API=y
#
# Power management options
@@ -129,7 +132,7 @@ CONFIG_ACPI_NUMA=y
# CONFIG_ACPI_IBM is not set
CONFIG_ACPI_TOSHIBA=y
CONFIG_ACPI_BLACKLIST_YEAR=2001
-CONFIG_ACPI_DEBUG=y
+# CONFIG_ACPI_DEBUG is not set
CONFIG_ACPI_BUS=y
CONFIG_ACPI_EC=y
CONFIG_ACPI_POWER=y
@@ -141,6 +144,7 @@ CONFIG_ACPI_SYSTEM=y
# CPU Frequency scaling
#
CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_TABLE=y
# CONFIG_CPU_FREQ_DEBUG is not set
CONFIG_CPU_FREQ_STAT=y
# CONFIG_CPU_FREQ_STAT_DETAILS is not set
@@ -150,7 +154,6 @@ CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
-CONFIG_CPU_FREQ_TABLE=y
#
# CPUFreq processor drivers
@@ -164,6 +167,7 @@ CONFIG_X86_ACPI_CPUFREQ=y
# shared options
#
CONFIG_X86_ACPI_CPUFREQ_PROC_INTF=y
+# CONFIG_X86_SPEEDSTEP_LIB is not set
#
# Bus options (PCI etc.)
@@ -172,9 +176,11 @@ CONFIG_PCI=y
CONFIG_PCI_DIRECT=y
CONFIG_PCI_MMCONFIG=y
CONFIG_UNORDERED_IO=y
+# CONFIG_PCIEPORTBUS is not set
CONFIG_PCI_MSI=y
# CONFIG_PCI_LEGACY_PROC is not set
# CONFIG_PCI_NAMES is not set
+# CONFIG_PCI_DEBUG is not set
#
# PCCARD (PCMCIA/CardBus) support
@@ -182,10 +188,6 @@ CONFIG_PCI_MSI=y
# CONFIG_PCCARD is not set
#
-# PC-card bridges
-#
-
-#
# PCI Hotplug Support
#
# CONFIG_HOTPLUG_PCI is not set
@@ -254,7 +256,7 @@ CONFIG_LBD=y
# IO Schedulers
#
CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_AS is not set
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
# CONFIG_ATA_OVER_ETH is not set
@@ -308,7 +310,8 @@ CONFIG_BLK_DEV_AMD74XX=y
CONFIG_BLK_DEV_PIIX=y
# CONFIG_BLK_DEV_NS87415 is not set
# CONFIG_BLK_DEV_PDC202XX_OLD is not set
-# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+CONFIG_BLK_DEV_PDC202XX_NEW=y
+# CONFIG_PDC202XX_FORCE is not set
# CONFIG_BLK_DEV_SVWKS is not set
# CONFIG_BLK_DEV_SIIMAGE is not set
# CONFIG_BLK_DEV_SIS5513 is not set
@@ -353,7 +356,7 @@ CONFIG_BLK_DEV_SD=y
#
# SCSI low-level drivers
#
-CONFIG_BLK_DEV_3W_XXXX_RAID=y
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
# CONFIG_SCSI_AACRAID is not set
@@ -384,7 +387,6 @@ CONFIG_SCSI_SATA_VIA=y
# CONFIG_SCSI_BUSLOGIC is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GDTH is not set
# CONFIG_SCSI_IPS is not set
@@ -392,7 +394,6 @@ CONFIG_SCSI_SATA_VIA=y
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
CONFIG_SCSI_QLA2XXX=y
@@ -401,6 +402,7 @@ CONFIG_SCSI_QLA2XXX=y
# CONFIG_SCSI_QLA2300 is not set
# CONFIG_SCSI_QLA2322 is not set
# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_LPFC is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
# CONFIG_SCSI_DEBUG is not set
@@ -437,7 +439,6 @@ CONFIG_NET=y
#
CONFIG_PACKET=y
# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
CONFIG_UNIX=y
# CONFIG_NET_KEY is not set
CONFIG_INET=y
@@ -502,7 +503,7 @@ CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
+CONFIG_TUN=y
#
# ARCnet devices
@@ -525,8 +526,7 @@ CONFIG_MII=y
# CONFIG_HP100 is not set
CONFIG_NET_PCI=y
# CONFIG_PCNET32 is not set
-CONFIG_AMD8111_ETH=y
-# CONFIG_AMD8111E_NAPI is not set
+# CONFIG_AMD8111_ETH is not set
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
CONFIG_FORCEDETH=y
@@ -536,7 +536,7 @@ CONFIG_FORCEDETH=y
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
# CONFIG_NE2K_PCI is not set
-CONFIG_8139CP=m
+CONFIG_8139CP=y
CONFIG_8139TOO=y
# CONFIG_8139TOO_PIO is not set
# CONFIG_8139TOO_TUNE_TWISTER is not set
@@ -671,6 +671,7 @@ CONFIG_SERIAL_8250_NR_UARTS=4
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
@@ -696,6 +697,7 @@ CONFIG_RTC=y
#
CONFIG_AGP=y
CONFIG_AGP_AMD64=y
+CONFIG_AGP_INTEL=y
# CONFIG_DRM is not set
# CONFIG_MWAVE is not set
CONFIG_RAW_DRIVER=y
@@ -703,7 +705,7 @@ CONFIG_HPET=y
# CONFIG_HPET_RTC_IRQ is not set
CONFIG_HPET_MMAP=y
CONFIG_MAX_RAW_DEVS=256
-CONFIG_HANGCHECK_TIMER=y
+# CONFIG_HANGCHECK_TIMER is not set
#
# TPM devices
@@ -786,6 +788,8 @@ CONFIG_SOUND_ICH=y
#
# USB support
#
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
@@ -797,8 +801,6 @@ CONFIG_USB_DEVICEFS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
# CONFIG_USB_SUSPEND is not set
# CONFIG_USB_OTG is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
#
# USB Host Controller Drivers
@@ -826,7 +828,6 @@ CONFIG_USB_PRINTER=y
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_RW_DETECT is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
@@ -965,7 +966,7 @@ CONFIG_AUTOFS_FS=y
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
+CONFIG_JOLIET=y
# CONFIG_ZISOFS is not set
# CONFIG_UDF_FS is not set
@@ -1092,9 +1093,10 @@ CONFIG_OPROFILE=y
#
# Kernel hacking
#
+# CONFIG_PRINTK_TIME is not set
CONFIG_DEBUG_KERNEL=y
CONFIG_MAGIC_SYSRQ=y
-# CONFIG_PRINTK_TIME is not set
+CONFIG_LOG_BUF_SHIFT=18
# CONFIG_SCHEDSTATS is not set
# CONFIG_DEBUG_SLAB is not set
# CONFIG_DEBUG_SPINLOCK is not set
diff --git a/arch/x86_64/ia32/ia32_aout.c b/arch/x86_64/ia32/ia32_aout.c
index 1965efc974d..c12edf5d97f 100644
--- a/arch/x86_64/ia32/ia32_aout.c
+++ b/arch/x86_64/ia32/ia32_aout.c
@@ -312,6 +312,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
current->mm->brk = ex.a_bss +
(current->mm->start_brk = N_BSSADDR(ex));
current->mm->free_area_cache = TASK_UNMAPPED_BASE;
+ current->mm->cached_hole_size = 0;
set_mm_counter(current->mm, rss, 0);
current->mm->mmap = NULL;
diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c
index 99b522052d1..c8131f342cf 100644
--- a/arch/x86_64/ia32/ia32_binfmt.c
+++ b/arch/x86_64/ia32/ia32_binfmt.c
@@ -46,7 +46,7 @@ struct elf_phdr;
#define IA32_EMULATOR 1
-#define ELF_ET_DYN_BASE (TASK_UNMAPPED_32 + 0x1000000)
+#define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x1000000)
#undef ELF_ARCH
#define ELF_ARCH EM_386
@@ -307,9 +307,6 @@ MODULE_AUTHOR("Eric Youngdale, Andi Kleen");
#define elf_addr_t __u32
-#undef TASK_SIZE
-#define TASK_SIZE 0xffffffff
-
static void elf32_init(struct pt_regs *);
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
diff --git a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c
index fbd09b5126c..66e2821533d 100644
--- a/arch/x86_64/ia32/ia32_signal.c
+++ b/arch/x86_64/ia32/ia32_signal.c
@@ -428,8 +428,8 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
return (void __user *)((rsp - frame_size) & -8UL);
}
-void ia32_setup_frame(int sig, struct k_sigaction *ka,
- compat_sigset_t *set, struct pt_regs * regs)
+int ia32_setup_frame(int sig, struct k_sigaction *ka,
+ compat_sigset_t *set, struct pt_regs * regs)
{
struct sigframe __user *frame;
int err = 0;
@@ -514,14 +514,15 @@ void ia32_setup_frame(int sig, struct k_sigaction *ka,
current->comm, current->pid, frame, regs->rip, frame->pretcode);
#endif
- return;
+ return 1;
give_sigsegv:
force_sigsegv(sig, current);
+ return 0;
}
-void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
- compat_sigset_t *set, struct pt_regs * regs)
+int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ compat_sigset_t *set, struct pt_regs * regs)
{
struct rt_sigframe __user *frame;
int err = 0;
@@ -613,9 +614,9 @@ void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
current->comm, current->pid, frame, regs->rip, frame->pretcode);
#endif
- return;
+ return 1;
give_sigsegv:
force_sigsegv(sig, current);
+ return 0;
}
-
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index f3ca0db85b5..cc935427d53 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -589,7 +589,7 @@ ia32_sys_call_table:
.quad compat_sys_mq_timedreceive /* 280 */
.quad compat_sys_mq_notify
.quad compat_sys_mq_getsetattr
- .quad quiet_ni_syscall /* reserved for kexec */
+ .quad compat_sys_kexec_load /* reserved for kexec */
.quad compat_sys_waitid
.quad quiet_ni_syscall /* sys_altroot */
.quad sys_add_key
diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
index 0a3318e08ab..48f9e2c19cd 100644
--- a/arch/x86_64/kernel/Makefile
+++ b/arch/x86_64/kernel/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o
obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o
obj-$(CONFIG_X86_IO_APIC) += io_apic.o mpparse.o \
genapic.o genapic_cluster.o genapic_flat.o
+obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o
obj-$(CONFIG_PM) += suspend.o
obj-$(CONFIG_SOFTWARE_SUSPEND) += suspend_asm.o
obj-$(CONFIG_CPU_FREQ) += cpufreq/
@@ -28,6 +29,7 @@ obj-$(CONFIG_GART_IOMMU) += pci-gart.o aperture.o
obj-$(CONFIG_DUMMY_IOMMU) += pci-nommu.o pci-dma.o
obj-$(CONFIG_SWIOTLB) += swiotlb.o
obj-$(CONFIG_KPROBES) += kprobes.o
+obj-$(CONFIG_X86_PM_TIMER) += pmtimer.o
obj-$(CONFIG_MODULES) += module.o
diff --git a/arch/x86_64/kernel/acpi/wakeup.S b/arch/x86_64/kernel/acpi/wakeup.S
index a4c630034cd..185faa911db 100644
--- a/arch/x86_64/kernel/acpi/wakeup.S
+++ b/arch/x86_64/kernel/acpi/wakeup.S
@@ -67,7 +67,7 @@ wakeup_code:
shll $4, %eax
addl $(gdta - wakeup_code), %eax
movl %eax, gdt_48a +2 - wakeup_code
- lgdt %ds:gdt_48a - wakeup_code # load gdt with whatever is
+ lgdtl %ds:gdt_48a - wakeup_code # load gdt with whatever is
# appropriate
movl $1, %eax # protected mode (PE) bit
diff --git a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c
index a491f72cc96..c9a6b812e92 100644
--- a/arch/x86_64/kernel/aperture.c
+++ b/arch/x86_64/kernel/aperture.c
@@ -33,20 +33,14 @@ int fallback_aper_force __initdata = 0;
int fix_aperture __initdata = 1;
-#define NB_ID_3 (PCI_VENDOR_ID_AMD | (0x1103<<16))
+/* This code runs before the PCI subsystem is initialized, so just
+ access the northbridge directly. */
-static struct resource aper_res = {
- .name = "Aperture",
- .flags = IORESOURCE_MEM,
-};
+#define NB_ID_3 (PCI_VENDOR_ID_AMD | (0x1103<<16))
static u32 __init allocate_aperture(void)
{
-#ifdef CONFIG_DISCONTIGMEM
pg_data_t *nd0 = NODE_DATA(0);
-#else
- pg_data_t *nd0 = &contig_page_data;
-#endif
u32 aper_size;
void *p;
@@ -55,24 +49,11 @@ static u32 __init allocate_aperture(void)
aper_size = (32 * 1024 * 1024) << fallback_aper_order;
/*
- * Aperture has to be naturally aligned. This means an 2GB
- * aperture won't have much chances to find a place in the
- * lower 4GB of memory. Unfortunately we cannot move it up
- * because that would make the IOMMU useless.
+ * Aperture has to be naturally aligned. This means an 2GB aperture won't
+ * have much chances to find a place in the lower 4GB of memory.
+ * Unfortunately we cannot move it up because that would make the
+ * IOMMU useless.
*/
-
- /* First try to find some free unused space */
- if (!allocate_resource(&iomem_resource, &aper_res,
- aper_size,
- 0, 0xffffffff,
- aper_size,
- NULL, NULL)) {
- printk(KERN_INFO "Putting aperture at %lx-%lx\n",
- aper_res.start, aper_res.end);
- return aper_res.start;
- }
-
- /* No free space found. Go on to waste some memory... */
p = __alloc_bootmem_node(nd0, aper_size, aper_size, 0);
if (!p || __pa(p)+aper_size > 0xffffffff) {
printk("Cannot allocate aperture memory hole (%p,%uK)\n",
@@ -81,7 +62,7 @@ static u32 __init allocate_aperture(void)
free_bootmem_node(nd0, (unsigned long)p, aper_size);
return 0;
}
- printk("Mapping aperture over %d KB of precious RAM @ %lx\n",
+ printk("Mapping aperture over %d KB of RAM @ %lx\n",
aper_size >> 10, __pa(p));
return (u32)__pa(p);
}
@@ -102,16 +83,10 @@ static int __init aperture_valid(char *name, u64 aper_base, u32 aper_size)
printk("Aperture from %s pointing to e820 RAM. Ignoring.\n",name);
return 0;
}
- /* Don't check the resource here because the aperture is usually
- in an e820 reserved area, and we allocated these earlier. */
return 1;
}
-/*
- * Find a PCI capability.
- * This code runs before the PCI subsystem is initialized, so just
- * access the northbridge directly.
- */
+/* Find a PCI capability */
static __u32 __init find_cap(int num, int slot, int func, int cap)
{
u8 pos;
@@ -276,6 +251,8 @@ void __init iommu_hole_init(void)
fallback_aper_force) {
printk("Your BIOS doesn't leave a aperture memory hole\n");
printk("Please enable the IOMMU option in the BIOS setup\n");
+ printk("This costs you %d MB of RAM\n",
+ 32 << fallback_aper_order);
aper_order = fallback_aper_order;
aper_alloc = allocate_aperture();
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
index 7e13545748e..375d369570c 100644
--- a/arch/x86_64/kernel/apic.c
+++ b/arch/x86_64/kernel/apic.c
@@ -33,6 +33,7 @@
#include <asm/mpspec.h>
#include <asm/pgalloc.h>
#include <asm/mach_apic.h>
+#include <asm/nmi.h>
int apic_verbosity;
@@ -132,7 +133,7 @@ void __init connect_bsp_APIC(void)
}
}
-void disconnect_bsp_APIC(void)
+void disconnect_bsp_APIC(int virt_wire_setup)
{
if (pic_mode) {
/*
@@ -145,6 +146,42 @@ void disconnect_bsp_APIC(void)
outb(0x70, 0x22);
outb(0x00, 0x23);
}
+ else {
+ /* Go back to Virtual Wire compatibility mode */
+ unsigned long value;
+
+ /* For the spurious interrupt use vector F, and enable it */
+ value = apic_read(APIC_SPIV);
+ value &= ~APIC_VECTOR_MASK;
+ value |= APIC_SPIV_APIC_ENABLED;
+ value |= 0xf;
+ apic_write_around(APIC_SPIV, value);
+
+ if (!virt_wire_setup) {
+ /* For LVT0 make it edge triggered, active high, external and enabled */
+ value = apic_read(APIC_LVT0);
+ value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING |
+ APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
+ APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED );
+ value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
+ value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT);
+ apic_write_around(APIC_LVT0, value);
+ }
+ else {
+ /* Disable LVT0 */
+ apic_write_around(APIC_LVT0, APIC_LVT_MASKED);
+ }
+
+ /* For LVT1 make it edge triggered, active high, nmi and enabled */
+ value = apic_read(APIC_LVT1);
+ value &= ~(
+ APIC_MODE_MASK | APIC_SEND_PENDING |
+ APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
+ APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED);
+ value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
+ value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI);
+ apic_write_around(APIC_LVT1, value);
+ }
}
void disable_local_APIC(void)
@@ -284,7 +321,7 @@ void __init init_bsp_APIC(void)
apic_write_around(APIC_LVT1, value);
}
-void __init setup_local_APIC (void)
+void __cpuinit setup_local_APIC (void)
{
unsigned int value, ver, maxlvt;
@@ -533,7 +570,7 @@ static struct sys_device device_lapic = {
.cls = &lapic_sysclass,
};
-static void __init apic_pm_activate(void)
+static void __cpuinit apic_pm_activate(void)
{
apic_pm_state.active = 1;
}
@@ -773,14 +810,14 @@ void __init setup_boot_APIC_clock (void)
local_irq_enable();
}
-void __init setup_secondary_APIC_clock(void)
+void __cpuinit setup_secondary_APIC_clock(void)
{
local_irq_disable(); /* FIXME: Do we need this? --RR */
setup_APIC_timer(calibration_result);
local_irq_enable();
}
-void __init disable_APIC_timer(void)
+void __cpuinit disable_APIC_timer(void)
{
if (using_apic_timer) {
unsigned long v;
@@ -925,7 +962,7 @@ __init int oem_force_hpet_timer(void)
unsigned id;
DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS);
- bitmap_empty(clustermap, NUM_APIC_CLUSTERS);
+ bitmap_zero(clustermap, NUM_APIC_CLUSTERS);
for (i = 0; i < NR_CPUS; i++) {
id = bios_cpu_apicid[i];
@@ -1056,7 +1093,7 @@ int __init APIC_init_uniprocessor (void)
nr_ioapics = 0;
#endif
setup_boot_APIC_clock();
-
+ check_nmi_watchdog();
return 0;
}
diff --git a/arch/x86_64/kernel/crash.c b/arch/x86_64/kernel/crash.c
new file mode 100644
index 00000000000..d7fa4248501
--- /dev/null
+++ b/arch/x86_64/kernel/crash.c
@@ -0,0 +1,35 @@
+/*
+ * Architecture specific (x86_64) functions for kexec based crash dumps.
+ *
+ * Created by: Hariprasad Nellitheertha (hari@in.ibm.com)
+ *
+ * Copyright (C) IBM Corporation, 2004. All rights reserved.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/irq.h>
+#include <linux/reboot.h>
+#include <linux/kexec.h>
+
+#include <asm/processor.h>
+#include <asm/hardirq.h>
+#include <asm/nmi.h>
+#include <asm/hw_irq.h>
+
+note_buf_t crash_notes[NR_CPUS];
+
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+ /* This function is only called after the system
+ * has paniced or is otherwise in a critical state.
+ * The minimum amount of code to allow a kexec'd kernel
+ * to run successfully needs to happen here.
+ *
+ * In practice this means shooting down the other cpus in
+ * an SMP system.
+ */
+}
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
index 7c154dfff64..6ded3a50dfe 100644
--- a/arch/x86_64/kernel/e820.c
+++ b/arch/x86_64/kernel/e820.c
@@ -16,6 +16,7 @@
#include <linux/bootmem.h>
#include <linux/ioport.h>
#include <linux/string.h>
+#include <linux/kexec.h>
#include <asm/page.h>
#include <asm/e820.h>
#include <asm/proto.h>
@@ -191,8 +192,6 @@ void __init e820_reserve_resources(void)
int i;
for (i = 0; i < e820.nr_map; i++) {
struct resource *res;
- if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL)
- continue;
res = alloc_bootmem_low(sizeof(struct resource));
switch (e820.map[i].type) {
case E820_RAM: res->name = "System RAM"; break;
@@ -212,6 +211,9 @@ void __init e820_reserve_resources(void)
*/
request_resource(res, &code_resource);
request_resource(res, &data_resource);
+#ifdef CONFIG_KEXEC
+ request_resource(res, &crashk_res);
+#endif
}
}
}
diff --git a/arch/x86_64/kernel/early_printk.c b/arch/x86_64/kernel/early_printk.c
index e3a19e8ebbf..9631c747c5e 100644
--- a/arch/x86_64/kernel/early_printk.c
+++ b/arch/x86_64/kernel/early_printk.c
@@ -2,20 +2,24 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
+#include <linux/tty.h>
#include <asm/io.h>
#include <asm/processor.h>
/* Simple VGA output */
#ifdef __i386__
+#include <asm/setup.h>
#define VGABASE (__ISA_IO_base + 0xb8000)
#else
+#include <asm/bootsetup.h>
#define VGABASE ((void __iomem *)0xffffffff800b8000UL)
#endif
-#define MAX_YPOS 25
-#define MAX_XPOS 80
+#define MAX_YPOS max_ypos
+#define MAX_XPOS max_xpos
+static int max_ypos = 25, max_xpos = 80;
static int current_ypos = 1, current_xpos = 0;
static void early_vga_write(struct console *con, const char *str, unsigned n)
@@ -196,7 +200,10 @@ int __init setup_early_printk(char *opt)
} else if (!strncmp(buf, "ttyS", 4)) {
early_serial_init(buf);
early_console = &early_serial_console;
- } else if (!strncmp(buf, "vga", 3)) {
+ } else if (!strncmp(buf, "vga", 3)
+ && SCREEN_INFO.orig_video_isVGA == 1) {
+ max_xpos = SCREEN_INFO.orig_video_cols;
+ max_ypos = SCREEN_INFO.orig_video_lines;
early_console = &early_vga_console;
}
early_console_initialized = 1;
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
index 1086b5fcac2..28817490fdc 100644
--- a/arch/x86_64/kernel/entry.S
+++ b/arch/x86_64/kernel/entry.S
@@ -220,13 +220,18 @@ sysret_careful:
jmp sysret_check
/* Handle a signal */
- /* edx: work flags (arg3) */
sysret_signal:
sti
+ testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
+ jz 1f
+
+ /* Really a signal */
+ /* edx: work flags (arg3) */
leaq do_notify_resume(%rip),%rax
leaq -ARGOFFSET(%rsp),%rdi # &pt_regs -> arg1
xorl %esi,%esi # oldset -> arg2
call ptregscall_common
+1: movl $_TIF_NEED_RESCHED,%edi
jmp sysret_check
/* Do syscall tracing */
@@ -484,6 +489,8 @@ retint_careful:
jmp retint_check
retint_signal:
+ testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
+ jz retint_swapgs
sti
SAVE_REST
movq $-1,ORIG_RAX(%rsp)
@@ -492,8 +499,8 @@ retint_signal:
call do_notify_resume
RESTORE_REST
cli
+ movl $_TIF_NEED_RESCHED,%edi
GET_THREAD_INFO(%rcx)
- movl $_TIF_WORK_MASK,%edi
jmp retint_check
#ifdef CONFIG_PREEMPT
diff --git a/arch/x86_64/kernel/genapic_flat.c b/arch/x86_64/kernel/genapic_flat.c
index b4cbbad0422..28284696508 100644
--- a/arch/x86_64/kernel/genapic_flat.c
+++ b/arch/x86_64/kernel/genapic_flat.c
@@ -7,6 +7,8 @@
* Hacked for x86-64 by James Cleverdon from i386 architecture code by
* Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
* James Cleverdon.
+ * Ashok Raj <ashok.raj@intel.com>
+ * Removed IPI broadcast shortcut to support CPU hotplug
*/
#include <linux/config.h>
#include <linux/threads.h>
@@ -18,6 +20,46 @@
#include <asm/smp.h>
#include <asm/ipi.h>
+/*
+ * The following permit choosing broadcast IPI shortcut v.s sending IPI only
+ * to online cpus via the send_IPI_mask varient.
+ * The mask version is my preferred option, since it eliminates a lot of
+ * other extra code that would need to be written to cleanup intrs sent
+ * to a CPU while offline.
+ *
+ * Sending broadcast introduces lots of trouble in CPU hotplug situations.
+ * These IPI's are delivered to cpu's irrespective of their offline status
+ * and could pickup stale intr data when these CPUS are turned online.
+ *
+ * Not using broadcast is a cleaner approach IMO, but Andi Kleen disagrees with
+ * the idea of not using broadcast IPI's anymore. Hence the run time check
+ * is introduced, on his request so we can choose an alternate mechanism.
+ *
+ * Initial wacky performance tests that collect cycle counts show
+ * no increase in using mask v.s broadcast version. In fact they seem
+ * identical in terms of cycle counts.
+ *
+ * if we need to use broadcast, we need to do the following.
+ *
+ * cli;
+ * hold call_lock;
+ * clear any pending IPI, just ack and clear all pending intr
+ * set cpu_online_map;
+ * release call_lock;
+ * sti;
+ *
+ * The complicated dummy irq processing shown above is not required if
+ * we didnt sent IPI's to wrong CPU's in the first place.
+ *
+ * - Ashok Raj <ashok.raj@intel.com>
+ */
+#ifdef CONFIG_HOTPLUG_CPU
+#define DEFAULT_SEND_IPI (1)
+#else
+#define DEFAULT_SEND_IPI (0)
+#endif
+
+static int no_broadcast=DEFAULT_SEND_IPI;
static cpumask_t flat_target_cpus(void)
{
@@ -45,22 +87,6 @@ static void flat_init_apic_ldr(void)
apic_write_around(APIC_LDR, val);
}
-static void flat_send_IPI_allbutself(int vector)
-{
- /*
- * if there are no other CPUs in the system then
- * we get an APIC send error if we try to broadcast.
- * thus we have to avoid sending IPIs in this case.
- */
- if (num_online_cpus() > 1)
- __send_IPI_shortcut(APIC_DEST_ALLBUT, vector, APIC_DEST_LOGICAL);
-}
-
-static void flat_send_IPI_all(int vector)
-{
- __send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_LOGICAL);
-}
-
static void flat_send_IPI_mask(cpumask_t cpumask, int vector)
{
unsigned long mask = cpus_addr(cpumask)[0];
@@ -93,6 +119,39 @@ static void flat_send_IPI_mask(cpumask_t cpumask, int vector)
local_irq_restore(flags);
}
+static inline void __local_flat_send_IPI_allbutself(int vector)
+{
+ if (no_broadcast) {
+ cpumask_t mask = cpu_online_map;
+ int this_cpu = get_cpu();
+
+ cpu_clear(this_cpu, mask);
+ flat_send_IPI_mask(mask, vector);
+ put_cpu();
+ }
+ else
+ __send_IPI_shortcut(APIC_DEST_ALLBUT, vector, APIC_DEST_LOGICAL);
+}
+
+static inline void __local_flat_send_IPI_all(int vector)
+{
+ if (no_broadcast)
+ flat_send_IPI_mask(cpu_online_map, vector);
+ else
+ __send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_LOGICAL);
+}
+
+static void flat_send_IPI_allbutself(int vector)
+{
+ if (((num_online_cpus()) - 1) >= 1)
+ __local_flat_send_IPI_allbutself(vector);
+}
+
+static void flat_send_IPI_all(int vector)
+{
+ __local_flat_send_IPI_all(vector);
+}
+
static int flat_apic_id_registered(void)
{
return physid_isset(GET_APIC_ID(apic_read(APIC_ID)), phys_cpu_present_map);
@@ -111,6 +170,16 @@ static unsigned int phys_pkg_id(int index_msb)
return ((ebx >> 24) & 0xFF) >> index_msb;
}
+static __init int no_ipi_broadcast(char *str)
+{
+ get_option(&str, &no_broadcast);
+ printk ("Using %s mode\n", no_broadcast ? "No IPI Broadcast" :
+ "IPI Broadcast");
+ return 1;
+}
+
+__setup("no_ipi_broadcast", no_ipi_broadcast);
+
struct genapic apic_flat = {
.name = "flat",
.int_delivery_mode = dest_LowestPrio,
@@ -125,3 +194,12 @@ struct genapic apic_flat = {
.cpu_mask_to_apicid = flat_cpu_mask_to_apicid,
.phys_pkg_id = phys_pkg_id,
};
+
+static int __init print_ipi_mode(void)
+{
+ printk ("Using IPI %s mode\n", no_broadcast ? "No-Shortcut" :
+ "Shortcut");
+ return 0;
+}
+
+late_initcall(print_ipi_mode);
diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S
index 9bd2e7a4b81..8d765aa77a2 100644
--- a/arch/x86_64/kernel/head.S
+++ b/arch/x86_64/kernel/head.S
@@ -248,23 +248,23 @@ ENTRY(_stext)
*/
.org 0x1000
ENTRY(init_level4_pgt)
- .quad 0x0000000000102007 /* -> level3_ident_pgt */
+ .quad 0x0000000000002007 + __PHYSICAL_START /* -> level3_ident_pgt */
.fill 255,8,0
- .quad 0x000000000010a007
+ .quad 0x000000000000a007 + __PHYSICAL_START
.fill 254,8,0
/* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
- .quad 0x0000000000103007 /* -> level3_kernel_pgt */
+ .quad 0x0000000000003007 + __PHYSICAL_START /* -> level3_kernel_pgt */
.org 0x2000
ENTRY(level3_ident_pgt)
- .quad 0x0000000000104007
+ .quad 0x0000000000004007 + __PHYSICAL_START
.fill 511,8,0
.org 0x3000
ENTRY(level3_kernel_pgt)
.fill 510,8,0
/* (2^48-(2*1024*1024*1024)-((2^39)*511))/(2^30) = 510 */
- .quad 0x0000000000105007 /* -> level2_kernel_pgt */
+ .quad 0x0000000000005007 + __PHYSICAL_START /* -> level2_kernel_pgt */
.fill 1,8,0
.org 0x4000
@@ -337,17 +337,17 @@ ENTRY(empty_bad_pmd_table)
.org 0xa000
ENTRY(level3_physmem_pgt)
- .quad 0x0000000000105007 /* -> level2_kernel_pgt (so that __va works even before pagetable_init) */
+ .quad 0x0000000000005007 + __PHYSICAL_START /* -> level2_kernel_pgt (so that __va works even before pagetable_init) */
.org 0xb000
#ifdef CONFIG_ACPI_SLEEP
ENTRY(wakeup_level4_pgt)
- .quad 0x0000000000102007 /* -> level3_ident_pgt */
+ .quad 0x0000000000002007 + __PHYSICAL_START /* -> level3_ident_pgt */
.fill 255,8,0
- .quad 0x000000000010a007
+ .quad 0x000000000000a007 + __PHYSICAL_START
.fill 254,8,0
/* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
- .quad 0x0000000000103007 /* -> level3_kernel_pgt */
+ .quad 0x0000000000003007 + __PHYSICAL_START /* -> level3_kernel_pgt */
#endif
.data
diff --git a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c
index 0f8c78dcd38..cf6ab147a2a 100644
--- a/arch/x86_64/kernel/head64.c
+++ b/arch/x86_64/kernel/head64.c
@@ -94,7 +94,7 @@ void __init x86_64_start_kernel(char * real_mode_data)
s = strstr(saved_command_line, "earlyprintk=");
if (s != NULL)
setup_early_printk(s);
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NUMA
s = strstr(saved_command_line, "numa=");
if (s != NULL)
numa_setup(s+5);
diff --git a/arch/x86_64/kernel/i387.c b/arch/x86_64/kernel/i387.c
index ba139cac57c..d9b22b633e3 100644
--- a/arch/x86_64/kernel/i387.c
+++ b/arch/x86_64/kernel/i387.c
@@ -42,7 +42,7 @@ void mxcsr_feature_mask_init(void)
* Called at bootup to set up the initial FPU state that is later cloned
* into all processes.
*/
-void __init fpu_init(void)
+void __cpuinit fpu_init(void)
{
unsigned long oldcr0 = read_cr0();
extern void __bad_fxsave_alignment(void);
diff --git a/arch/x86_64/kernel/i8259.c b/arch/x86_64/kernel/i8259.c
index 7873d9ba881..a8916909512 100644
--- a/arch/x86_64/kernel/i8259.c
+++ b/arch/x86_64/kernel/i8259.c
@@ -157,14 +157,13 @@ static unsigned int startup_8259A_irq(unsigned int irq)
}
static struct hw_interrupt_type i8259A_irq_type = {
- "XT-PIC",
- startup_8259A_irq,
- shutdown_8259A_irq,
- enable_8259A_irq,
- disable_8259A_irq,
- mask_and_ack_8259A,
- end_8259A_irq,
- NULL
+ .typename = "XT-PIC",
+ .startup = startup_8259A_irq,
+ .shutdown = shutdown_8259A_irq,
+ .enable = enable_8259A_irq,
+ .disable = disable_8259A_irq,
+ .ack = mask_and_ack_8259A,
+ .end = end_8259A_irq,
};
/*
@@ -415,10 +414,22 @@ static int i8259A_suspend(struct sys_device *dev, pm_message_t state)
return 0;
}
+static int i8259A_shutdown(struct sys_device *dev)
+{
+ /* Put the i8259A into a quiescent state that
+ * the kernel initialization code can get it
+ * out of.
+ */
+ outb(0xff, 0x21); /* mask all of 8259A-1 */
+ outb(0xff, 0xA1); /* mask all of 8259A-1 */
+ return 0;
+}
+
static struct sysdev_class i8259_sysdev_class = {
set_kset_name("i8259"),
.suspend = i8259A_suspend,
.resume = i8259A_resume,
+ .shutdown = i8259A_shutdown,
};
static struct sys_device device_i8259A = {
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 60be58617eb..157190d986b 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -37,11 +37,14 @@
#include <asm/desc.h>
#include <asm/proto.h>
#include <asm/mach_apic.h>
+#include <asm/acpi.h>
#define __apicdebuginit __init
int sis_apic_bug; /* not actually supported, dummy for compile */
+static int no_timer_check;
+
static DEFINE_SPINLOCK(ioapic_lock);
/*
@@ -327,7 +330,7 @@ static int find_irq_entry(int apic, int pin, int type)
/*
* Find the pin to which IRQ[irq] (ISA) is connected
*/
-static int __init find_isa_irq_pin(int irq, int type)
+static int find_isa_irq_pin(int irq, int type)
{
int i;
@@ -1129,12 +1132,44 @@ static void __init enable_IO_APIC(void)
*/
void disable_IO_APIC(void)
{
+ int pin;
/*
* Clear the IO-APIC before rebooting:
*/
clear_IO_APIC();
- disconnect_bsp_APIC();
+ /*
+ * If the i82559 is routed through an IOAPIC
+ * Put that IOAPIC in virtual wire mode
+ * so legacy interrups can be delivered.
+ */
+ pin = find_isa_irq_pin(0, mp_ExtINT);
+ if (pin != -1) {
+ struct IO_APIC_route_entry entry;
+ unsigned long flags;
+
+ memset(&entry, 0, sizeof(entry));
+ entry.mask = 0; /* Enabled */
+ entry.trigger = 0; /* Edge */
+ entry.irr = 0;
+ entry.polarity = 0; /* High */
+ entry.delivery_status = 0;
+ entry.dest_mode = 0; /* Physical */
+ entry.delivery_mode = 7; /* ExtInt */
+ entry.vector = 0;
+ entry.dest.physical.physical_dest = 0;
+
+
+ /*
+ * Add it to the IO-APIC irq-routing table:
+ */
+ spin_lock_irqsave(&ioapic_lock, flags);
+ io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1));
+ io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0));
+ spin_unlock_irqrestore(&ioapic_lock, flags);
+ }
+
+ disconnect_bsp_APIC(pin != -1);
}
/*
@@ -1601,7 +1636,7 @@ static inline void check_timer(void)
* Ok, does IRQ0 through the IOAPIC work?
*/
unmask_IO_APIC_irq(0);
- if (timer_irq_works()) {
+ if (!no_timer_check && timer_irq_works()) {
nmi_watchdog_default();
if (nmi_watchdog == NMI_IO_APIC) {
disable_8259A_irq(0);
@@ -1671,6 +1706,13 @@ static inline void check_timer(void)
panic("IO-APIC + timer doesn't work! Try using the 'noapic' kernel parameter\n");
}
+static int __init notimercheck(char *s)
+{
+ no_timer_check = 1;
+ return 1;
+}
+__setup("no_timer_check", notimercheck);
+
/*
*
* IRQ's that are handled by the PIC in the MPS IOAPIC case.
@@ -1804,76 +1846,6 @@ device_initcall(ioapic_init_sysfs);
#define IO_APIC_MAX_ID 0xFE
-int __init io_apic_get_unique_id (int ioapic, int apic_id)
-{
- union IO_APIC_reg_00 reg_00;
- static physid_mask_t apic_id_map;
- unsigned long flags;
- int i = 0;
-
- /*
- * The P4 platform supports up to 256 APIC IDs on two separate APIC
- * buses (one for LAPICs, one for IOAPICs), where predecessors only
- * supports up to 16 on one shared APIC bus.
- *
- * TBD: Expand LAPIC/IOAPIC support on P4-class systems to take full
- * advantage of new APIC bus architecture.
- */
-
- if (physids_empty(apic_id_map))
- apic_id_map = phys_cpu_present_map;
-
- spin_lock_irqsave(&ioapic_lock, flags);
- reg_00.raw = io_apic_read(ioapic, 0);
- spin_unlock_irqrestore(&ioapic_lock, flags);
-
- if (apic_id >= IO_APIC_MAX_ID) {
- apic_printk(APIC_QUIET, KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying "
- "%d\n", ioapic, apic_id, reg_00.bits.ID);
- apic_id = reg_00.bits.ID;
- }
-
- /*
- * Every APIC in a system must have a unique ID or we get lots of nice
- * 'stuck on smp_invalidate_needed IPI wait' messages.
- */
- if (physid_isset(apic_id, apic_id_map)) {
-
- for (i = 0; i < IO_APIC_MAX_ID; i++) {
- if (!physid_isset(i, apic_id_map))
- break;
- }
-
- if (i == IO_APIC_MAX_ID)
- panic("Max apic_id exceeded!\n");
-
- apic_printk(APIC_VERBOSE, KERN_WARNING "IOAPIC[%d]: apic_id %d already used, "
- "trying %d\n", ioapic, apic_id, i);
-
- apic_id = i;
- }
-
- physid_set(apic_id, apic_id_map);
-
- if (reg_00.bits.ID != apic_id) {
- reg_00.bits.ID = apic_id;
-
- spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(ioapic, 0, reg_00.raw);
- reg_00.raw = io_apic_read(ioapic, 0);
- spin_unlock_irqrestore(&ioapic_lock, flags);
-
- /* Sanity check */
- if (reg_00.bits.ID != apic_id)
- panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic);
- }
-
- apic_printk(APIC_VERBOSE,KERN_INFO "IOAPIC[%d]: Assigned apic_id %d\n", ioapic, apic_id);
-
- return apic_id;
-}
-
-
int __init io_apic_get_version (int ioapic)
{
union IO_APIC_reg_01 reg_01;
diff --git a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c
index 62b112e4deb..cc3fb85f514 100644
--- a/arch/x86_64/kernel/irq.c
+++ b/arch/x86_64/kernel/irq.c
@@ -14,6 +14,7 @@
#include <linux/interrupt.h>
#include <linux/seq_file.h>
#include <linux/module.h>
+#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/io_apic.h>
@@ -106,3 +107,31 @@ asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
return 1;
}
+#ifdef CONFIG_HOTPLUG_CPU
+void fixup_irqs(cpumask_t map)
+{
+ unsigned int irq;
+ static int warned;
+
+ for (irq = 0; irq < NR_IRQS; irq++) {
+ cpumask_t mask;
+ if (irq == 2)
+ continue;
+
+ cpus_and(mask, irq_affinity[irq], map);
+ if (any_online_cpu(mask) == NR_CPUS) {
+ printk("Breaking affinity for irq %i\n", irq);
+ mask = map;
+ }
+ if (irq_desc[irq].handler->set_affinity)
+ irq_desc[irq].handler->set_affinity(irq, mask);
+ else if (irq_desc[irq].action && !(warned++))
+ printk("Cannot set affinity for irq %i\n", irq);
+ }
+
+ /* That doesn't seem sufficient. Give it 1ms. */
+ local_irq_enable();
+ mdelay(1);
+ local_irq_disable();
+}
+#endif
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c
index f77f8a0ff18..4e680f87a75 100644
--- a/arch/x86_64/kernel/kprobes.c
+++ b/arch/x86_64/kernel/kprobes.c
@@ -27,6 +27,8 @@
* <prasanna@in.ibm.com> adapted for x86_64
* 2005-Mar Roland McGrath <roland@redhat.com>
* Fixed to handle %rip-relative addressing mode correctly.
+ * 2005-May Rusty Lynch <rusty.lynch@intel.com>
+ * Added function return probes functionality
*/
#include <linux/config.h>
@@ -37,18 +39,16 @@
#include <linux/slab.h>
#include <linux/preempt.h>
#include <linux/moduleloader.h>
-
+#include <asm/cacheflush.h>
#include <asm/pgtable.h>
#include <asm/kdebug.h>
static DECLARE_MUTEX(kprobe_mutex);
-/* kprobe_status settings */
-#define KPROBE_HIT_ACTIVE 0x00000001
-#define KPROBE_HIT_SS 0x00000002
-
static struct kprobe *current_kprobe;
static unsigned long kprobe_status, kprobe_old_rflags, kprobe_saved_rflags;
+static struct kprobe *kprobe_prev;
+static unsigned long kprobe_status_prev, kprobe_old_rflags_prev, kprobe_saved_rflags_prev;
static struct pt_regs jprobe_saved_regs;
static long *jprobe_saved_rsp;
static kprobe_opcode_t *get_insn_slot(void);
@@ -214,6 +214,21 @@ void arch_copy_kprobe(struct kprobe *p)
BUG_ON((s64) (s32) disp != disp); /* Sanity check. */
*ripdisp = disp;
}
+ p->opcode = *p->addr;
+}
+
+void arch_arm_kprobe(struct kprobe *p)
+{
+ *p->addr = BREAKPOINT_INSTRUCTION;
+ flush_icache_range((unsigned long) p->addr,
+ (unsigned long) p->addr + sizeof(kprobe_opcode_t));
+}
+
+void arch_disarm_kprobe(struct kprobe *p)
+{
+ *p->addr = p->opcode;
+ flush_icache_range((unsigned long) p->addr,
+ (unsigned long) p->addr + sizeof(kprobe_opcode_t));
}
void arch_remove_kprobe(struct kprobe *p)
@@ -223,10 +238,29 @@ void arch_remove_kprobe(struct kprobe *p)
down(&kprobe_mutex);
}
-static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs)
+static inline void save_previous_kprobe(void)
{
- *p->addr = p->opcode;
- regs->rip = (unsigned long)p->addr;
+ kprobe_prev = current_kprobe;
+ kprobe_status_prev = kprobe_status;
+ kprobe_old_rflags_prev = kprobe_old_rflags;
+ kprobe_saved_rflags_prev = kprobe_saved_rflags;
+}
+
+static inline void restore_previous_kprobe(void)
+{
+ current_kprobe = kprobe_prev;
+ kprobe_status = kprobe_status_prev;
+ kprobe_old_rflags = kprobe_old_rflags_prev;
+ kprobe_saved_rflags = kprobe_saved_rflags_prev;
+}
+
+static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs)
+{
+ current_kprobe = p;
+ kprobe_saved_rflags = kprobe_old_rflags
+ = (regs->eflags & (TF_MASK | IF_MASK));
+ if (is_IF_modifier(p->ainsn.insn))
+ kprobe_saved_rflags &= ~IF_MASK;
}
static void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
@@ -240,6 +274,50 @@ static void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
regs->rip = (unsigned long)p->ainsn.insn;
}
+struct task_struct *arch_get_kprobe_task(void *ptr)
+{
+ return ((struct thread_info *) (((unsigned long) ptr) &
+ (~(THREAD_SIZE -1))))->task;
+}
+
+void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
+{
+ unsigned long *sara = (unsigned long *)regs->rsp;
+ struct kretprobe_instance *ri;
+ static void *orig_ret_addr;
+
+ /*
+ * Save the return address when the return probe hits
+ * the first time, and use it to populate the (krprobe
+ * instance)->ret_addr for subsequent return probes at
+ * the same addrress since stack address would have
+ * the kretprobe_trampoline by then.
+ */
+ if (((void*) *sara) != kretprobe_trampoline)
+ orig_ret_addr = (void*) *sara;
+
+ if ((ri = get_free_rp_inst(rp)) != NULL) {
+ ri->rp = rp;
+ ri->stack_addr = sara;
+ ri->ret_addr = orig_ret_addr;
+ add_rp_inst(ri);
+ /* Replace the return addr with trampoline addr */
+ *sara = (unsigned long) &kretprobe_trampoline;
+ } else {
+ rp->nmissed++;
+ }
+}
+
+void arch_kprobe_flush_task(struct task_struct *tk)
+{
+ struct kretprobe_instance *ri;
+ while ((ri = get_rp_inst_tsk(tk)) != NULL) {
+ *((unsigned long *)(ri->stack_addr)) =
+ (unsigned long) ri->ret_addr;
+ recycle_rp_inst(ri);
+ }
+}
+
/*
* Interrupts are disabled on entry as trap3 is an interrupt gate and they
* remain disabled thorough out this function.
@@ -264,9 +342,30 @@ int kprobe_handler(struct pt_regs *regs)
regs->eflags |= kprobe_saved_rflags;
unlock_kprobes();
goto no_kprobe;
+ } else if (kprobe_status == KPROBE_HIT_SSDONE) {
+ /* TODO: Provide re-entrancy from
+ * post_kprobes_handler() and avoid exception
+ * stack corruption while single-stepping on
+ * the instruction of the new probe.
+ */
+ arch_disarm_kprobe(p);
+ regs->rip = (unsigned long)p->addr;
+ ret = 1;
+ } else {
+ /* We have reentered the kprobe_handler(), since
+ * another probe was hit while within the
+ * handler. We here save the original kprobe
+ * variables and just single step on instruction
+ * of the new probe without calling any user
+ * handlers.
+ */
+ save_previous_kprobe();
+ set_current_kprobe(p, regs);
+ p->nmissed++;
+ prepare_singlestep(p, regs);
+ kprobe_status = KPROBE_REENTER;
+ return 1;
}
- disarm_kprobe(p, regs);
- ret = 1;
} else {
p = current_kprobe;
if (p->break_handler && p->break_handler(p, regs)) {
@@ -296,11 +395,7 @@ int kprobe_handler(struct pt_regs *regs)
}
kprobe_status = KPROBE_HIT_ACTIVE;
- current_kprobe = p;
- kprobe_saved_rflags = kprobe_old_rflags
- = (regs->eflags & (TF_MASK | IF_MASK));
- if (is_IF_modifier(p->ainsn.insn))
- kprobe_saved_rflags &= ~IF_MASK;
+ set_current_kprobe(p, regs);
if (p->pre_handler && p->pre_handler(p, regs))
/* handler has already set things up, so skip ss setup */
@@ -317,6 +412,55 @@ no_kprobe:
}
/*
+ * For function-return probes, init_kprobes() establishes a probepoint
+ * here. When a retprobed function returns, this probe is hit and
+ * trampoline_probe_handler() runs, calling the kretprobe's handler.
+ */
+ void kretprobe_trampoline_holder(void)
+ {
+ asm volatile ( ".global kretprobe_trampoline\n"
+ "kretprobe_trampoline: \n"
+ "nop\n");
+ }
+
+/*
+ * Called when we hit the probe point at kretprobe_trampoline
+ */
+int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ struct task_struct *tsk;
+ struct kretprobe_instance *ri;
+ struct hlist_head *head;
+ struct hlist_node *node;
+ unsigned long *sara = (unsigned long *)regs->rsp - 1;
+
+ tsk = arch_get_kprobe_task(sara);
+ head = kretprobe_inst_table_head(tsk);
+
+ hlist_for_each_entry(ri, node, head, hlist) {
+ if (ri->stack_addr == sara && ri->rp) {
+ if (ri->rp->handler)
+ ri->rp->handler(ri, regs);
+ }
+ }
+ return 0;
+}
+
+void trampoline_post_handler(struct kprobe *p, struct pt_regs *regs,
+ unsigned long flags)
+{
+ struct kretprobe_instance *ri;
+ /* RA already popped */
+ unsigned long *sara = ((unsigned long *)regs->rsp) - 1;
+
+ while ((ri = get_rp_inst(sara))) {
+ regs->rip = (unsigned long)ri->ret_addr;
+ recycle_rp_inst(ri);
+ }
+ regs->eflags &= ~TF_MASK;
+}
+
+/*
* Called after single-stepping. p->addr is the address of the
* instruction whose first byte has been replaced by the "int 3"
* instruction. To avoid the SMP problems that can occur when we
@@ -401,13 +545,23 @@ int post_kprobe_handler(struct pt_regs *regs)
if (!kprobe_running())
return 0;
- if (current_kprobe->post_handler)
+ if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) {
+ kprobe_status = KPROBE_HIT_SSDONE;
current_kprobe->post_handler(current_kprobe, regs, 0);
+ }
- resume_execution(current_kprobe, regs);
+ if (current_kprobe->post_handler != trampoline_post_handler)
+ resume_execution(current_kprobe, regs);
regs->eflags |= kprobe_saved_rflags;
- unlock_kprobes();
+ /* Restore the original saved kprobes variables and continue. */
+ if (kprobe_status == KPROBE_REENTER) {
+ restore_previous_kprobe();
+ goto out;
+ } else {
+ unlock_kprobes();
+ }
+out:
preempt_enable_no_resched();
/*
diff --git a/arch/x86_64/kernel/machine_kexec.c b/arch/x86_64/kernel/machine_kexec.c
new file mode 100644
index 00000000000..60d1eff4156
--- /dev/null
+++ b/arch/x86_64/kernel/machine_kexec.c
@@ -0,0 +1,250 @@
+/*
+ * machine_kexec.c - handle transition of Linux booting another kernel
+ * Copyright (C) 2002-2005 Eric Biederman <ebiederm@xmission.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/mm.h>
+#include <linux/kexec.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/reboot.h>
+#include <asm/pda.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/apic.h>
+#include <asm/cpufeature.h>
+#include <asm/hw_irq.h>
+
+#define LEVEL0_SIZE (1UL << 12UL)
+#define LEVEL1_SIZE (1UL << 21UL)
+#define LEVEL2_SIZE (1UL << 30UL)
+#define LEVEL3_SIZE (1UL << 39UL)
+#define LEVEL4_SIZE (1UL << 48UL)
+
+#define L0_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define L1_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_PSE)
+#define L2_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define L3_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
+
+static void init_level2_page(u64 *level2p, unsigned long addr)
+{
+ unsigned long end_addr;
+
+ addr &= PAGE_MASK;
+ end_addr = addr + LEVEL2_SIZE;
+ while (addr < end_addr) {
+ *(level2p++) = addr | L1_ATTR;
+ addr += LEVEL1_SIZE;
+ }
+}
+
+static int init_level3_page(struct kimage *image, u64 *level3p,
+ unsigned long addr, unsigned long last_addr)
+{
+ unsigned long end_addr;
+ int result;
+
+ result = 0;
+ addr &= PAGE_MASK;
+ end_addr = addr + LEVEL3_SIZE;
+ while ((addr < last_addr) && (addr < end_addr)) {
+ struct page *page;
+ u64 *level2p;
+
+ page = kimage_alloc_control_pages(image, 0);
+ if (!page) {
+ result = -ENOMEM;
+ goto out;
+ }
+ level2p = (u64 *)page_address(page);
+ init_level2_page(level2p, addr);
+ *(level3p++) = __pa(level2p) | L2_ATTR;
+ addr += LEVEL2_SIZE;
+ }
+ /* clear the unused entries */
+ while (addr < end_addr) {
+ *(level3p++) = 0;
+ addr += LEVEL2_SIZE;
+ }
+out:
+ return result;
+}
+
+
+static int init_level4_page(struct kimage *image, u64 *level4p,
+ unsigned long addr, unsigned long last_addr)
+{
+ unsigned long end_addr;
+ int result;
+
+ result = 0;
+ addr &= PAGE_MASK;
+ end_addr = addr + LEVEL4_SIZE;
+ while ((addr < last_addr) && (addr < end_addr)) {
+ struct page *page;
+ u64 *level3p;
+
+ page = kimage_alloc_control_pages(image, 0);
+ if (!page) {
+ result = -ENOMEM;
+ goto out;
+ }
+ level3p = (u64 *)page_address(page);
+ result = init_level3_page(image, level3p, addr, last_addr);
+ if (result) {
+ goto out;
+ }
+ *(level4p++) = __pa(level3p) | L3_ATTR;
+ addr += LEVEL3_SIZE;
+ }
+ /* clear the unused entries */
+ while (addr < end_addr) {
+ *(level4p++) = 0;
+ addr += LEVEL3_SIZE;
+ }
+out:
+ return result;
+}
+
+
+static int init_pgtable(struct kimage *image, unsigned long start_pgtable)
+{
+ u64 *level4p;
+ level4p = (u64 *)__va(start_pgtable);
+ return init_level4_page(image, level4p, 0, end_pfn << PAGE_SHIFT);
+}
+
+static void set_idt(void *newidt, u16 limit)
+{
+ unsigned char curidt[10];
+
+ /* x86-64 supports unaliged loads & stores */
+ (*(u16 *)(curidt)) = limit;
+ (*(u64 *)(curidt +2)) = (unsigned long)(newidt);
+
+ __asm__ __volatile__ (
+ "lidt %0\n"
+ : "=m" (curidt)
+ );
+};
+
+
+static void set_gdt(void *newgdt, u16 limit)
+{
+ unsigned char curgdt[10];
+
+ /* x86-64 supports unaligned loads & stores */
+ (*(u16 *)(curgdt)) = limit;
+ (*(u64 *)(curgdt +2)) = (unsigned long)(newgdt);
+
+ __asm__ __volatile__ (
+ "lgdt %0\n"
+ : "=m" (curgdt)
+ );
+};
+
+static void load_segments(void)
+{
+ __asm__ __volatile__ (
+ "\tmovl $"STR(__KERNEL_DS)",%eax\n"
+ "\tmovl %eax,%ds\n"
+ "\tmovl %eax,%es\n"
+ "\tmovl %eax,%ss\n"
+ "\tmovl %eax,%fs\n"
+ "\tmovl %eax,%gs\n"
+ );
+#undef STR
+#undef __STR
+}
+
+typedef NORET_TYPE void (*relocate_new_kernel_t)(unsigned long indirection_page,
+ unsigned long control_code_buffer,
+ unsigned long start_address,
+ unsigned long pgtable) ATTRIB_NORET;
+
+const extern unsigned char relocate_new_kernel[];
+const extern unsigned long relocate_new_kernel_size;
+
+int machine_kexec_prepare(struct kimage *image)
+{
+ unsigned long start_pgtable, control_code_buffer;
+ int result;
+
+ /* Calculate the offsets */
+ start_pgtable = page_to_pfn(image->control_code_page) << PAGE_SHIFT;
+ control_code_buffer = start_pgtable + 4096UL;
+
+ /* Setup the identity mapped 64bit page table */
+ result = init_pgtable(image, start_pgtable);
+ if (result)
+ return result;
+
+ /* Place the code in the reboot code buffer */
+ memcpy(__va(control_code_buffer), relocate_new_kernel,
+ relocate_new_kernel_size);
+
+ return 0;
+}
+
+void machine_kexec_cleanup(struct kimage *image)
+{
+ return;
+}
+
+/*
+ * Do not allocate memory (or fail in any way) in machine_kexec().
+ * We are past the point of no return, committed to rebooting now.
+ */
+NORET_TYPE void machine_kexec(struct kimage *image)
+{
+ unsigned long page_list;
+ unsigned long control_code_buffer;
+ unsigned long start_pgtable;
+ relocate_new_kernel_t rnk;
+
+ /* Interrupts aren't acceptable while we reboot */
+ local_irq_disable();
+
+ /* Calculate the offsets */
+ page_list = image->head;
+ start_pgtable = page_to_pfn(image->control_code_page) << PAGE_SHIFT;
+ control_code_buffer = start_pgtable + 4096UL;
+
+ /* Set the low half of the page table to my identity mapped
+ * page table for kexec. Leave the high half pointing at the
+ * kernel pages. Don't bother to flush the global pages
+ * as that will happen when I fully switch to my identity mapped
+ * page table anyway.
+ */
+ memcpy(__va(read_cr3()), __va(start_pgtable), PAGE_SIZE/2);
+ __flush_tlb();
+
+
+ /* The segment registers are funny things, they are
+ * automatically loaded from a table, in memory wherever you
+ * set them to a specific selector, but this table is never
+ * accessed again unless you set the segment to a different selector.
+ *
+ * The more common model are caches where the behide
+ * the scenes work is done, but is also dropped at arbitrary
+ * times.
+ *
+ * I take advantage of this here by force loading the
+ * segments, before I zap the gdt with an invalid value.
+ */
+ load_segments();
+ /* The gdt & idt are now invalid.
+ * If you want to load them you must set up your own idt & gdt.
+ */
+ set_gdt(phys_to_virt(0),0);
+ set_idt(phys_to_virt(0),0);
+ /* now call it */
+ rnk = (relocate_new_kernel_t) control_code_buffer;
+ (*rnk)(page_list, control_code_buffer, image->start, start_pgtable);
+}
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index 3a89d735a4f..21e70625a49 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -327,7 +327,7 @@ static void mce_init(void *dummy)
}
/* Add per CPU specific workarounds here */
-static void __init mce_cpu_quirks(struct cpuinfo_x86 *c)
+static void __cpuinit mce_cpu_quirks(struct cpuinfo_x86 *c)
{
/* This should be disabled by the BIOS, but isn't always */
if (c->x86_vendor == X86_VENDOR_AMD && c->x86 == 15) {
@@ -337,7 +337,7 @@ static void __init mce_cpu_quirks(struct cpuinfo_x86 *c)
}
}
-static void __init mce_cpu_features(struct cpuinfo_x86 *c)
+static void __cpuinit mce_cpu_features(struct cpuinfo_x86 *c)
{
switch (c->x86_vendor) {
case X86_VENDOR_INTEL:
@@ -352,7 +352,7 @@ static void __init mce_cpu_features(struct cpuinfo_x86 *c)
* Called for each booted CPU to set up machine checks.
* Must be called with preempt off.
*/
-void __init mcheck_init(struct cpuinfo_x86 *c)
+void __cpuinit mcheck_init(struct cpuinfo_x86 *c)
{
static cpumask_t mce_cpus __initdata = CPU_MASK_NONE;
@@ -411,7 +411,7 @@ static ssize_t mce_read(struct file *filp, char __user *ubuf, size_t usize, loff
memset(mcelog.entry, 0, next * sizeof(struct mce));
mcelog.next = 0;
- synchronize_kernel();
+ synchronize_sched();
/* Collect entries that were still getting written before the synchronize. */
@@ -542,7 +542,7 @@ ACCESSOR(bank4ctl,bank[4],mce_restart())
ACCESSOR(tolerant,tolerant,)
ACCESSOR(check_interval,check_interval,mce_restart())
-static __init int mce_init_device(void)
+static __cpuinit int mce_init_device(void)
{
int err;
if (!mce_available(&boot_cpu_data))
diff --git a/arch/x86_64/kernel/mce_intel.c b/arch/x86_64/kernel/mce_intel.c
index 4db9a640069..0be0a795981 100644
--- a/arch/x86_64/kernel/mce_intel.c
+++ b/arch/x86_64/kernel/mce_intel.c
@@ -42,7 +42,7 @@ done:
irq_exit();
}
-static void __init intel_init_thermal(struct cpuinfo_x86 *c)
+static void __cpuinit intel_init_thermal(struct cpuinfo_x86 *c)
{
u32 l, h;
int tm2 = 0;
@@ -93,7 +93,7 @@ static void __init intel_init_thermal(struct cpuinfo_x86 *c)
return;
}
-void __init mce_intel_feature_init(struct cpuinfo_x86 *c)
+void __cpuinit mce_intel_feature_init(struct cpuinfo_x86 *c)
{
intel_init_thermal(c);
}
diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c
index 7ec031c6ca1..9c5aa2a790c 100644
--- a/arch/x86_64/kernel/mpparse.c
+++ b/arch/x86_64/kernel/mpparse.c
@@ -23,6 +23,7 @@
#include <linux/kernel_stat.h>
#include <linux/mc146818rtc.h>
#include <linux/acpi.h>
+#include <linux/module.h>
#include <asm/smp.h>
#include <asm/mtrr.h>
@@ -30,6 +31,7 @@
#include <asm/pgalloc.h>
#include <asm/io_apic.h>
#include <asm/proto.h>
+#include <asm/acpi.h>
/* Have we found an MP table */
int smp_found_config;
@@ -44,7 +46,8 @@ int acpi_found_madt;
int apic_version [MAX_APICS];
unsigned char mp_bus_id_to_type [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
-cpumask_t pci_bus_to_cpumask [256] = { [0 ... 255] = CPU_MASK_ALL };
+unsigned char pci_bus_to_node [256];
+EXPORT_SYMBOL(pci_bus_to_node);
static int mp_current_pci_id = 0;
/* I/O APIC entries */
@@ -107,6 +110,7 @@ static int __init mpf_checksum(unsigned char *mp, int len)
static void __init MP_processor_info (struct mpc_config_processor *m)
{
int ver;
+ static int found_bsp=0;
if (!(m->mpc_cpuflag & CPU_ENABLED))
return;
@@ -126,11 +130,6 @@ static void __init MP_processor_info (struct mpc_config_processor *m)
" Processor ignored.\n", NR_CPUS);
return;
}
- if (num_processors >= maxcpus) {
- printk(KERN_WARNING "WARNING: maxcpus limit of %i reached."
- " Processor ignored.\n", maxcpus);
- return;
- }
num_processors++;
@@ -150,7 +149,19 @@ static void __init MP_processor_info (struct mpc_config_processor *m)
ver = 0x10;
}
apic_version[m->mpc_apicid] = ver;
- bios_cpu_apicid[num_processors - 1] = m->mpc_apicid;
+ if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
+ /*
+ * bios_cpu_apicid is required to have processors listed
+ * in same order as logical cpu numbers. Hence the first
+ * entry is BSP, and so on.
+ */
+ bios_cpu_apicid[0] = m->mpc_apicid;
+ x86_cpu_to_apicid[0] = m->mpc_apicid;
+ found_bsp = 1;
+ } else {
+ bios_cpu_apicid[num_processors - found_bsp] = m->mpc_apicid;
+ x86_cpu_to_apicid[num_processors - found_bsp] = m->mpc_apicid;
+ }
}
static void __init MP_bus_info (struct mpc_config_bus *m)
@@ -759,7 +770,7 @@ void __init mp_register_ioapic (
mp_ioapics[idx].mpc_apicaddr = address;
set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
- mp_ioapics[idx].mpc_apicid = io_apic_get_unique_id(idx, id);
+ mp_ioapics[idx].mpc_apicid = id;
mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
/*
@@ -895,11 +906,20 @@ void __init mp_config_acpi_legacy_irqs (void)
return;
}
+#define MAX_GSI_NUM 4096
+
int mp_register_gsi(u32 gsi, int edge_level, int active_high_low)
{
int ioapic = -1;
int ioapic_pin = 0;
int idx, bit = 0;
+ static int pci_irq = 16;
+ /*
+ * Mapping between Global System Interrupts, which
+ * represent all possible interrupts, to the IRQs
+ * assigned to actual devices.
+ */
+ static int gsi_to_irq[MAX_GSI_NUM];
if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
return gsi;
@@ -934,11 +954,21 @@ int mp_register_gsi(u32 gsi, int edge_level, int active_high_low)
if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
- return gsi;
+ return gsi_to_irq[gsi];
}
mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
+ if (edge_level) {
+ /*
+ * For PCI devices assign IRQs in order, avoiding gaps
+ * due to unused I/O APIC pins.
+ */
+ int irq = gsi;
+ gsi = pci_irq++;
+ gsi_to_irq[irq] = gsi;
+ }
+
io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
edge_level == ACPI_EDGE_SENSITIVE ? 0 : 1,
active_high_low == ACPI_ACTIVE_HIGH ? 0 : 1);
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index 61de0b34a01..4e44d6e6b7e 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -33,6 +33,7 @@
#include <asm/msr.h>
#include <asm/proto.h>
#include <asm/kdebug.h>
+#include <asm/local.h>
/*
* lapic_nmi_owner tracks the ownership of the lapic NMI hardware:
@@ -59,7 +60,8 @@ int panic_on_timeout;
unsigned int nmi_watchdog = NMI_DEFAULT;
static unsigned int nmi_hz = HZ;
-unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */
+static unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */
+static unsigned int nmi_p4_cccr_val;
/* Note that these events don't tick when the CPU idles. This means
the frequency varies with CPU load. */
@@ -71,61 +73,87 @@ unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */
#define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING 0x76
#define K7_NMI_EVENT K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING
-#define P6_EVNTSEL0_ENABLE (1 << 22)
-#define P6_EVNTSEL_INT (1 << 20)
-#define P6_EVNTSEL_OS (1 << 17)
-#define P6_EVNTSEL_USR (1 << 16)
-#define P6_EVENT_CPU_CLOCKS_NOT_HALTED 0x79
-#define P6_NMI_EVENT P6_EVENT_CPU_CLOCKS_NOT_HALTED
+#define MSR_P4_MISC_ENABLE 0x1A0
+#define MSR_P4_MISC_ENABLE_PERF_AVAIL (1<<7)
+#define MSR_P4_MISC_ENABLE_PEBS_UNAVAIL (1<<12)
+#define MSR_P4_PERFCTR0 0x300
+#define MSR_P4_CCCR0 0x360
+#define P4_ESCR_EVENT_SELECT(N) ((N)<<25)
+#define P4_ESCR_OS (1<<3)
+#define P4_ESCR_USR (1<<2)
+#define P4_CCCR_OVF_PMI0 (1<<26)
+#define P4_CCCR_OVF_PMI1 (1<<27)
+#define P4_CCCR_THRESHOLD(N) ((N)<<20)
+#define P4_CCCR_COMPLEMENT (1<<19)
+#define P4_CCCR_COMPARE (1<<18)
+#define P4_CCCR_REQUIRED (3<<16)
+#define P4_CCCR_ESCR_SELECT(N) ((N)<<13)
+#define P4_CCCR_ENABLE (1<<12)
+/* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter
+ CRU_ESCR0 (with any non-null event selector) through a complemented
+ max threshold. [IA32-Vol3, Section 14.9.9] */
+#define MSR_P4_IQ_COUNTER0 0x30C
+#define P4_NMI_CRU_ESCR0 (P4_ESCR_EVENT_SELECT(0x3F)|P4_ESCR_OS|P4_ESCR_USR)
+#define P4_NMI_IQ_CCCR0 \
+ (P4_CCCR_OVF_PMI0|P4_CCCR_THRESHOLD(15)|P4_CCCR_COMPLEMENT| \
+ P4_CCCR_COMPARE|P4_CCCR_REQUIRED|P4_CCCR_ESCR_SELECT(4)|P4_CCCR_ENABLE)
+
+static __cpuinit inline int nmi_known_cpu(void)
+{
+ switch (boot_cpu_data.x86_vendor) {
+ case X86_VENDOR_AMD:
+ return boot_cpu_data.x86 == 15;
+ case X86_VENDOR_INTEL:
+ return boot_cpu_data.x86 == 15;
+ }
+ return 0;
+}
/* Run after command line and cpu_init init, but before all other checks */
-void __init nmi_watchdog_default(void)
+void __cpuinit nmi_watchdog_default(void)
{
if (nmi_watchdog != NMI_DEFAULT)
return;
-
- /* For some reason the IO APIC watchdog doesn't work on the AMD
- 8111 chipset. For now switch to local APIC mode using
- perfctr0 there. On Intel CPUs we don't have code to handle
- the perfctr and the IO-APIC seems to work, so use that. */
-
- if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
- nmi_watchdog = NMI_LOCAL_APIC;
- printk(KERN_INFO
- "Using local APIC NMI watchdog using perfctr0\n");
- } else {
- printk(KERN_INFO "Using IO APIC NMI watchdog\n");
+ if (nmi_known_cpu())
+ nmi_watchdog = NMI_LOCAL_APIC;
+ else
nmi_watchdog = NMI_IO_APIC;
- }
}
-/* Why is there no CPUID flag for this? */
-static __init int cpu_has_lapic(void)
+#ifdef CONFIG_SMP
+/* The performance counters used by NMI_LOCAL_APIC don't trigger when
+ * the CPU is idle. To make sure the NMI watchdog really ticks on all
+ * CPUs during the test make them busy.
+ */
+static __init void nmi_cpu_busy(void *data)
{
- switch (boot_cpu_data.x86_vendor) {
- case X86_VENDOR_INTEL:
- case X86_VENDOR_AMD:
- return boot_cpu_data.x86 >= 6;
- /* .... add more cpus here or find a different way to figure this out. */
- default:
- return 0;
- }
+ volatile int *endflag = data;
+ local_irq_enable();
+ /* Intentionally don't use cpu_relax here. This is
+ to make sure that the performance counter really ticks,
+ even if there is a simulator or similar that catches the
+ pause instruction. On a real HT machine this is fine because
+ all other CPUs are busy with "useless" delay loops and don't
+ care if they get somewhat less cycles. */
+ while (*endflag == 0)
+ barrier();
}
+#endif
-static int __init check_nmi_watchdog (void)
+int __init check_nmi_watchdog (void)
{
- int counts[NR_CPUS];
+ volatile int endflag = 0;
+ int *counts;
int cpu;
- if (nmi_watchdog == NMI_NONE)
- return 0;
+ counts = kmalloc(NR_CPUS * sizeof(int), GFP_KERNEL);
+ if (!counts)
+ return -1;
- if (nmi_watchdog == NMI_LOCAL_APIC && !cpu_has_lapic()) {
- nmi_watchdog = NMI_NONE;
- return -1;
- }
+ printk(KERN_INFO "testing NMI watchdog ... ");
- printk(KERN_INFO "Testing NMI watchdog ... ");
+ if (nmi_watchdog == NMI_LOCAL_APIC)
+ smp_call_function(nmi_cpu_busy, (void *)&endflag, 0, 0);
for (cpu = 0; cpu < NR_CPUS; cpu++)
counts[cpu] = cpu_pda[cpu].__nmi_count;
@@ -133,15 +161,22 @@ static int __init check_nmi_watchdog (void)
mdelay((10*1000)/nmi_hz); // wait 10 ticks
for (cpu = 0; cpu < NR_CPUS; cpu++) {
+ if (!cpu_online(cpu))
+ continue;
if (cpu_pda[cpu].__nmi_count - counts[cpu] <= 5) {
- printk("CPU#%d: NMI appears to be stuck (%d)!\n",
+ endflag = 1;
+ printk("CPU#%d: NMI appears to be stuck (%d->%d)!\n",
cpu,
+ counts[cpu],
cpu_pda[cpu].__nmi_count);
nmi_active = 0;
lapic_nmi_owner &= ~LAPIC_NMI_WATCHDOG;
+ nmi_perfctr_msr = 0;
+ kfree(counts);
return -1;
}
}
+ endflag = 1;
printk("OK.\n");
/* now that we know it works we can reduce NMI frequency to
@@ -149,10 +184,9 @@ static int __init check_nmi_watchdog (void)
if (nmi_watchdog == NMI_LOCAL_APIC)
nmi_hz = 1;
+ kfree(counts);
return 0;
}
-/* Have this called later during boot so counters are updating */
-late_initcall(check_nmi_watchdog);
int __init setup_nmi_watchdog(char *str)
{
@@ -170,7 +204,7 @@ int __init setup_nmi_watchdog(char *str)
if (nmi >= NMI_INVALID)
return 0;
- nmi_watchdog = nmi;
+ nmi_watchdog = nmi;
return 1;
}
@@ -185,7 +219,10 @@ static void disable_lapic_nmi_watchdog(void)
wrmsr(MSR_K7_EVNTSEL0, 0, 0);
break;
case X86_VENDOR_INTEL:
- wrmsr(MSR_IA32_EVNTSEL0, 0, 0);
+ if (boot_cpu_data.x86 == 15) {
+ wrmsr(MSR_P4_IQ_CCCR0, 0, 0);
+ wrmsr(MSR_P4_CRU_ESCR0, 0, 0);
+ }
break;
}
nmi_active = -1;
@@ -253,7 +290,7 @@ void enable_timer_nmi_watchdog(void)
static int nmi_pm_active; /* nmi_active before suspend */
-static int lapic_nmi_suspend(struct sys_device *dev, pm_message_t state)
+static int lapic_nmi_suspend(struct sys_device *dev, u32 state)
{
nmi_pm_active = nmi_active;
disable_lapic_nmi_watchdog();
@@ -300,22 +337,27 @@ late_initcall(init_lapic_nmi_sysfs);
* Original code written by Keith Owens.
*/
+static void clear_msr_range(unsigned int base, unsigned int n)
+{
+ unsigned int i;
+
+ for(i = 0; i < n; ++i)
+ wrmsr(base+i, 0, 0);
+}
+
static void setup_k7_watchdog(void)
{
int i;
unsigned int evntsel;
- /* No check, so can start with slow frequency */
- nmi_hz = 1;
-
- /* XXX should check these in EFER */
-
nmi_perfctr_msr = MSR_K7_PERFCTR0;
for(i = 0; i < 4; ++i) {
/* Simulator may not support it */
- if (checking_wrmsrl(MSR_K7_EVNTSEL0+i, 0UL))
+ if (checking_wrmsrl(MSR_K7_EVNTSEL0+i, 0UL)) {
+ nmi_perfctr_msr = 0;
return;
+ }
wrmsrl(MSR_K7_PERFCTR0+i, 0UL);
}
@@ -325,12 +367,54 @@ static void setup_k7_watchdog(void)
| K7_NMI_EVENT;
wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
- wrmsrl(MSR_K7_PERFCTR0, -((u64)cpu_khz*1000) / nmi_hz);
+ wrmsr(MSR_K7_PERFCTR0, -(cpu_khz/nmi_hz*1000), -1);
apic_write(APIC_LVTPC, APIC_DM_NMI);
evntsel |= K7_EVNTSEL_ENABLE;
wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
}
+
+static int setup_p4_watchdog(void)
+{
+ unsigned int misc_enable, dummy;
+
+ rdmsr(MSR_P4_MISC_ENABLE, misc_enable, dummy);
+ if (!(misc_enable & MSR_P4_MISC_ENABLE_PERF_AVAIL))
+ return 0;
+
+ nmi_perfctr_msr = MSR_P4_IQ_COUNTER0;
+ nmi_p4_cccr_val = P4_NMI_IQ_CCCR0;
+#ifdef CONFIG_SMP
+ if (smp_num_siblings == 2)
+ nmi_p4_cccr_val |= P4_CCCR_OVF_PMI1;
+#endif
+
+ if (!(misc_enable & MSR_P4_MISC_ENABLE_PEBS_UNAVAIL))
+ clear_msr_range(0x3F1, 2);
+ /* MSR 0x3F0 seems to have a default value of 0xFC00, but current
+ docs doesn't fully define it, so leave it alone for now. */
+ if (boot_cpu_data.x86_model >= 0x3) {
+ /* MSR_P4_IQ_ESCR0/1 (0x3ba/0x3bb) removed */
+ clear_msr_range(0x3A0, 26);
+ clear_msr_range(0x3BC, 3);
+ } else {
+ clear_msr_range(0x3A0, 31);
+ }
+ clear_msr_range(0x3C0, 6);
+ clear_msr_range(0x3C8, 6);
+ clear_msr_range(0x3E0, 2);
+ clear_msr_range(MSR_P4_CCCR0, 18);
+ clear_msr_range(MSR_P4_PERFCTR0, 18);
+
+ wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0);
+ wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0);
+ Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz/nmi_hz*1000));
+ wrmsr(MSR_P4_IQ_COUNTER0, -(cpu_khz/nmi_hz*1000), -1);
+ apic_write(APIC_LVTPC, APIC_DM_NMI);
+ wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
+ return 1;
+}
+
void setup_apic_nmi_watchdog(void)
{
switch (boot_cpu_data.x86_vendor) {
@@ -341,6 +425,13 @@ void setup_apic_nmi_watchdog(void)
return;
setup_k7_watchdog();
break;
+ case X86_VENDOR_INTEL:
+ if (boot_cpu_data.x86 != 15)
+ return;
+ if (!setup_p4_watchdog())
+ return;
+ break;
+
default:
return;
}
@@ -355,56 +446,67 @@ void setup_apic_nmi_watchdog(void)
*
* as these watchdog NMI IRQs are generated on every CPU, we only
* have to check the current processor.
- *
- * since NMIs don't listen to _any_ locks, we have to be extremely
- * careful not to rely on unsafe variables. The printk might lock
- * up though, so we have to break up any console locks first ...
- * [when there will be more tty-related locks, break them up
- * here too!]
*/
-static unsigned int
- last_irq_sums [NR_CPUS],
- alert_counter [NR_CPUS];
+static DEFINE_PER_CPU(unsigned, last_irq_sum);
+static DEFINE_PER_CPU(local_t, alert_counter);
+static DEFINE_PER_CPU(int, nmi_touch);
void touch_nmi_watchdog (void)
{
int i;
/*
- * Just reset the alert counters, (other CPUs might be
- * spinning on locks we hold):
+ * Tell other CPUs to reset their alert counters. We cannot
+ * do it ourselves because the alert count increase is not
+ * atomic.
*/
for (i = 0; i < NR_CPUS; i++)
- alert_counter[i] = 0;
+ per_cpu(nmi_touch, i) = 1;
}
void nmi_watchdog_tick (struct pt_regs * regs, unsigned reason)
{
- int sum, cpu;
+ int sum;
+ int touched = 0;
- cpu = safe_smp_processor_id();
sum = read_pda(apic_timer_irqs);
- if (last_irq_sums[cpu] == sum) {
+ if (__get_cpu_var(nmi_touch)) {
+ __get_cpu_var(nmi_touch) = 0;
+ touched = 1;
+ }
+ if (!touched && __get_cpu_var(last_irq_sum) == sum) {
/*
* Ayiee, looks like this CPU is stuck ...
* wait a few IRQs (5 seconds) before doing the oops ...
*/
- alert_counter[cpu]++;
- if (alert_counter[cpu] == 5*nmi_hz) {
+ local_inc(&__get_cpu_var(alert_counter));
+ if (local_read(&__get_cpu_var(alert_counter)) == 5*nmi_hz) {
if (notify_die(DIE_NMI, "nmi", regs, reason, 2, SIGINT)
== NOTIFY_STOP) {
- alert_counter[cpu] = 0;
+ local_set(&__get_cpu_var(alert_counter), 0);
return;
}
die_nmi("NMI Watchdog detected LOCKUP on CPU%d", regs);
}
} else {
- last_irq_sums[cpu] = sum;
- alert_counter[cpu] = 0;
+ __get_cpu_var(last_irq_sum) = sum;
+ local_set(&__get_cpu_var(alert_counter), 0);
}
- if (nmi_perfctr_msr)
+ if (nmi_perfctr_msr) {
+ if (nmi_perfctr_msr == MSR_P4_IQ_COUNTER0) {
+ /*
+ * P4 quirks:
+ * - An overflown perfctr will assert its interrupt
+ * until the OVF flag in its CCCR is cleared.
+ * - LVTPC is masked on interrupt and must be
+ * unmasked by the LVTPC handler.
+ */
+ wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
+ apic_write(APIC_LVTPC, APIC_DM_NMI);
+ }
wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1);
+ }
}
static int dummy_nmi_callback(struct pt_regs * regs, int cpu)
diff --git a/arch/x86_64/kernel/pmtimer.c b/arch/x86_64/kernel/pmtimer.c
new file mode 100644
index 00000000000..feb5f108dd2
--- /dev/null
+++ b/arch/x86_64/kernel/pmtimer.c
@@ -0,0 +1,101 @@
+/* Ported over from i386 by AK, original copyright was:
+ *
+ * (C) Dominik Brodowski <linux@brodo.de> 2003
+ *
+ * Driver to use the Power Management Timer (PMTMR) available in some
+ * southbridges as primary timing source for the Linux kernel.
+ *
+ * Based on parts of linux/drivers/acpi/hardware/hwtimer.c, timer_pit.c,
+ * timer_hpet.c, and on Arjan van de Ven's implementation for 2.4.
+ *
+ * This file is licensed under the GPL v2.
+ *
+ * Dropped all the hardware bug workarounds for now. Hopefully they
+ * are not needed on 64bit chipsets.
+ */
+
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/cpumask.h>
+#include <asm/io.h>
+#include <asm/proto.h>
+#include <asm/msr.h>
+#include <asm/vsyscall.h>
+
+/* The I/O port the PMTMR resides at.
+ * The location is detected during setup_arch(),
+ * in arch/i386/kernel/acpi/boot.c */
+u32 pmtmr_ioport;
+
+/* value of the Power timer at last timer interrupt */
+static u32 offset_delay;
+static u32 last_pmtmr_tick;
+
+#define ACPI_PM_MASK 0xFFFFFF /* limit it to 24 bits */
+
+static inline u32 cyc2us(u32 cycles)
+{
+ /* The Power Management Timer ticks at 3.579545 ticks per microsecond.
+ * 1 / PM_TIMER_FREQUENCY == 0.27936511 =~ 286/1024 [error: 0.024%]
+ *
+ * Even with HZ = 100, delta is at maximum 35796 ticks, so it can
+ * easily be multiplied with 286 (=0x11E) without having to fear
+ * u32 overflows.
+ */
+ cycles *= 286;
+ return (cycles >> 10);
+}
+
+int pmtimer_mark_offset(void)
+{
+ static int first_run = 1;
+ unsigned long tsc;
+ u32 lost;
+
+ u32 tick = inl(pmtmr_ioport);
+ u32 delta;
+
+ delta = cyc2us((tick - last_pmtmr_tick) & ACPI_PM_MASK);
+
+ last_pmtmr_tick = tick;
+ monotonic_base += delta * NSEC_PER_USEC;
+
+ delta += offset_delay;
+
+ lost = delta / (USEC_PER_SEC / HZ);
+ offset_delay = delta % (USEC_PER_SEC / HZ);
+
+ rdtscll(tsc);
+ vxtime.last_tsc = tsc - offset_delay * cpu_khz;
+
+ /* don't calculate delay for first run,
+ or if we've got less then a tick */
+ if (first_run || (lost < 1)) {
+ first_run = 0;
+ offset_delay = 0;
+ }
+
+ return lost - 1;
+}
+
+unsigned int do_gettimeoffset_pm(void)
+{
+ u32 now, offset, delta = 0;
+
+ offset = last_pmtmr_tick;
+ now = inl(pmtmr_ioport);
+ delta = (now - offset) & ACPI_PM_MASK;
+
+ return offset_delay + cyc2us(delta);
+}
+
+
+static int __init nopmtimer_setup(char *s)
+{
+ pmtmr_ioport = 0;
+ return 0;
+}
+
+__setup("nopmtimer", nopmtimer_setup);
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index 761b6d35e33..1d91271796e 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -8,7 +8,8 @@
*
* X86-64 port
* Andi Kleen.
- *
+ *
+ * CPU hotplug support - ashok.raj@intel.com
* $Id: process.c,v 1.38 2002/01/15 10:08:03 ak Exp $
*/
@@ -18,6 +19,7 @@
#include <stdarg.h>
+#include <linux/cpu.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
@@ -34,6 +36,7 @@
#include <linux/ptrace.h>
#include <linux/utsname.h>
#include <linux/random.h>
+#include <linux/kprobes.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
@@ -153,6 +156,29 @@ void cpu_idle_wait(void)
}
EXPORT_SYMBOL_GPL(cpu_idle_wait);
+#ifdef CONFIG_HOTPLUG_CPU
+DECLARE_PER_CPU(int, cpu_state);
+
+#include <asm/nmi.h>
+/* We don't actually take CPU down, just spin without interrupts. */
+static inline void play_dead(void)
+{
+ idle_task_exit();
+ wbinvd();
+ mb();
+ /* Ack it */
+ __get_cpu_var(cpu_state) = CPU_DEAD;
+
+ while (1)
+ safe_halt();
+}
+#else
+static inline void play_dead(void)
+{
+ BUG();
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
/*
* The idle thread. There's no useful work to be
* done, so just try to conserve power and have a
@@ -173,6 +199,8 @@ void cpu_idle (void)
idle = pm_idle;
if (!idle)
idle = default_idle;
+ if (cpu_is_offline(smp_processor_id()))
+ play_dead();
idle();
}
@@ -203,7 +231,7 @@ static void mwait_idle(void)
}
}
-void __init select_idle_routine(const struct cpuinfo_x86 *c)
+void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
{
static int printed;
if (cpu_has(c, X86_FEATURE_MWAIT)) {
@@ -293,6 +321,14 @@ void exit_thread(void)
{
struct task_struct *me = current;
struct thread_struct *t = &me->thread;
+
+ /*
+ * Remove function-return probe instances associated with this task
+ * and put them back on the free list. Do not insert an exit probe for
+ * this function, it will be disabled by kprobe_flush_task if you do.
+ */
+ kprobe_flush_task(me);
+
if (me->thread.io_bitmap_ptr) {
struct tss_struct *tss = &per_cpu(init_tss, get_cpu());
@@ -312,6 +348,13 @@ void flush_thread(void)
struct task_struct *tsk = current;
struct thread_info *t = current_thread_info();
+ /*
+ * Remove function-return probe instances associated with this task
+ * and put them back on the free list. Do not insert an exit probe for
+ * this function, it will be disabled by kprobe_flush_task if you do.
+ */
+ kprobe_flush_task(tsk);
+
if (t->flags & _TIF_ABI_PENDING)
t->flags ^= (_TIF_ABI_PENDING | _TIF_IA32);
@@ -656,7 +699,7 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
switch (code) {
case ARCH_SET_GS:
- if (addr >= TASK_SIZE)
+ if (addr >= TASK_SIZE_OF(task))
return -EPERM;
cpu = get_cpu();
/* handle small bases via the GDT because that's faster to
@@ -682,7 +725,7 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
case ARCH_SET_FS:
/* Not strictly needed for fs, but do it for symmetry
with gs */
- if (addr >= TASK_SIZE)
+ if (addr >= TASK_SIZE_OF(task))
return -EPERM;
cpu = get_cpu();
/* handle small bases via the GDT because that's faster to
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
index e26e86bb56f..bbf64b59a21 100644
--- a/arch/x86_64/kernel/ptrace.c
+++ b/arch/x86_64/kernel/ptrace.c
@@ -257,13 +257,13 @@ static int putreg(struct task_struct *child,
value &= 0xffff;
return 0;
case offsetof(struct user_regs_struct,fs_base):
- if (!((value >> 48) == 0 || (value >> 48) == 0xffff))
- return -EIO;
+ if (value >= TASK_SIZE_OF(child))
+ return -EIO;
child->thread.fs = value;
return 0;
case offsetof(struct user_regs_struct,gs_base):
- if (!((value >> 48) == 0 || (value >> 48) == 0xffff))
- return -EIO;
+ if (value >= TASK_SIZE_OF(child))
+ return -EIO;
child->thread.gs = value;
return 0;
case offsetof(struct user_regs_struct, eflags):
@@ -277,6 +277,11 @@ static int putreg(struct task_struct *child,
return -EIO;
value &= 0xffff;
break;
+ case offsetof(struct user_regs_struct, rip):
+ /* Check if the new RIP address is canonical */
+ if (value >= TASK_SIZE_OF(child))
+ return -EIO;
+ break;
}
put_stack_long(child, regno - sizeof(struct pt_regs), value);
return 0;
@@ -375,7 +380,7 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data
break;
switch (addr) {
- case 0 ... sizeof(struct user_regs_struct):
+ case 0 ... sizeof(struct user_regs_struct) - sizeof(long):
tmp = getreg(child, addr);
break;
case offsetof(struct user, u_debugreg[0]):
@@ -414,33 +419,35 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data
break;
case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
+ {
+ int dsize = test_tsk_thread_flag(child, TIF_IA32) ? 3 : 7;
ret = -EIO;
if ((addr & 7) ||
addr > sizeof(struct user) - 7)
break;
switch (addr) {
- case 0 ... sizeof(struct user_regs_struct):
+ case 0 ... sizeof(struct user_regs_struct) - sizeof(long):
ret = putreg(child, addr, data);
break;
/* Disallows to set a breakpoint into the vsyscall */
case offsetof(struct user, u_debugreg[0]):
- if (data >= TASK_SIZE-7) break;
+ if (data >= TASK_SIZE_OF(child) - dsize) break;
child->thread.debugreg0 = data;
ret = 0;
break;
case offsetof(struct user, u_debugreg[1]):
- if (data >= TASK_SIZE-7) break;
+ if (data >= TASK_SIZE_OF(child) - dsize) break;
child->thread.debugreg1 = data;
ret = 0;
break;
case offsetof(struct user, u_debugreg[2]):
- if (data >= TASK_SIZE-7) break;
+ if (data >= TASK_SIZE_OF(child) - dsize) break;
child->thread.debugreg2 = data;
ret = 0;
break;
case offsetof(struct user, u_debugreg[3]):
- if (data >= TASK_SIZE-7) break;
+ if (data >= TASK_SIZE_OF(child) - dsize) break;
child->thread.debugreg3 = data;
ret = 0;
break;
@@ -464,6 +471,7 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data
break;
}
break;
+ }
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
case PTRACE_CONT: /* restart after signal. */
diff --git a/arch/x86_64/kernel/reboot.c b/arch/x86_64/kernel/reboot.c
index be4b36f762c..57e71dbdfd6 100644
--- a/arch/x86_64/kernel/reboot.c
+++ b/arch/x86_64/kernel/reboot.c
@@ -66,41 +66,47 @@ static int __init reboot_setup(char *str)
__setup("reboot=", reboot_setup);
-#ifdef CONFIG_SMP
-static void smp_halt(void)
+static inline void kb_wait(void)
{
- int cpuid = safe_smp_processor_id();
- static int first_entry = 1;
+ int i;
- if (reboot_force)
- return;
+ for (i=0; i<0x10000; i++)
+ if ((inb_p(0x64) & 0x02) == 0)
+ break;
+}
- if (first_entry) {
- first_entry = 0;
- smp_call_function((void *)machine_restart, NULL, 1, 0);
- }
-
- smp_stop_cpu();
+void machine_shutdown(void)
+{
+ /* Stop the cpus and apics */
+#ifdef CONFIG_SMP
+ int reboot_cpu_id;
- /* AP calling this. Just halt */
- if (cpuid != boot_cpu_id) {
- for (;;)
- asm("hlt");
+ /* The boot cpu is always logical cpu 0 */
+ reboot_cpu_id = 0;
+
+ /* Make certain the cpu I'm about to reboot on is online */
+ if (!cpu_isset(reboot_cpu_id, cpu_online_map)) {
+ reboot_cpu_id = smp_processor_id();
}
- /* Wait for all other CPUs to have run smp_stop_cpu */
- while (!cpus_empty(cpu_online_map))
- rep_nop();
-}
+ /* Make certain I only run on the appropriate processor */
+ set_cpus_allowed(current, cpumask_of_cpu(reboot_cpu_id));
+
+ /* O.K Now that I'm on the appropriate processor,
+ * stop all of the others.
+ */
+ smp_send_stop();
#endif
-static inline void kb_wait(void)
-{
- int i;
+ local_irq_disable();
- for (i=0; i<0x10000; i++)
- if ((inb_p(0x64) & 0x02) == 0)
- break;
+#ifndef CONFIG_SMP
+ disable_local_APIC();
+#endif
+
+ disable_IO_APIC();
+
+ local_irq_enable();
}
void machine_restart(char * __unused)
@@ -109,9 +115,7 @@ void machine_restart(char * __unused)
printk("machine restart\n");
-#ifdef CONFIG_SMP
- smp_halt();
-#endif
+ machine_shutdown();
if (!reboot_force) {
local_irq_disable();
diff --git a/arch/x86_64/kernel/relocate_kernel.S b/arch/x86_64/kernel/relocate_kernel.S
new file mode 100644
index 00000000000..d24fa9b72a2
--- /dev/null
+++ b/arch/x86_64/kernel/relocate_kernel.S
@@ -0,0 +1,143 @@
+/*
+ * relocate_kernel.S - put the kernel image in place to boot
+ * Copyright (C) 2002-2005 Eric Biederman <ebiederm@xmission.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/linkage.h>
+
+ /*
+ * Must be relocatable PIC code callable as a C function, that once
+ * it starts can not use the previous processes stack.
+ */
+ .globl relocate_new_kernel
+ .code64
+relocate_new_kernel:
+ /* %rdi page_list
+ * %rsi reboot_code_buffer
+ * %rdx start address
+ * %rcx page_table
+ * %r8 arg5
+ * %r9 arg6
+ */
+
+ /* zero out flags, and disable interrupts */
+ pushq $0
+ popfq
+
+ /* set a new stack at the bottom of our page... */
+ lea 4096(%rsi), %rsp
+
+ /* store the parameters back on the stack */
+ pushq %rdx /* store the start address */
+
+ /* Set cr0 to a known state:
+ * 31 1 == Paging enabled
+ * 18 0 == Alignment check disabled
+ * 16 0 == Write protect disabled
+ * 3 0 == No task switch
+ * 2 0 == Don't do FP software emulation.
+ * 0 1 == Proctected mode enabled
+ */
+ movq %cr0, %rax
+ andq $~((1<<18)|(1<<16)|(1<<3)|(1<<2)), %rax
+ orl $((1<<31)|(1<<0)), %eax
+ movq %rax, %cr0
+
+ /* Set cr4 to a known state:
+ * 10 0 == xmm exceptions disabled
+ * 9 0 == xmm registers instructions disabled
+ * 8 0 == performance monitoring counter disabled
+ * 7 0 == page global disabled
+ * 6 0 == machine check exceptions disabled
+ * 5 1 == physical address extension enabled
+ * 4 0 == page size extensions disabled
+ * 3 0 == Debug extensions disabled
+ * 2 0 == Time stamp disable (disabled)
+ * 1 0 == Protected mode virtual interrupts disabled
+ * 0 0 == VME disabled
+ */
+
+ movq $((1<<5)), %rax
+ movq %rax, %cr4
+
+ jmp 1f
+1:
+
+ /* Switch to the identity mapped page tables,
+ * and flush the TLB.
+ */
+ movq %rcx, %cr3
+
+ /* Do the copies */
+ movq %rdi, %rcx /* Put the page_list in %rcx */
+ xorq %rdi, %rdi
+ xorq %rsi, %rsi
+ jmp 1f
+
+0: /* top, read another word for the indirection page */
+
+ movq (%rbx), %rcx
+ addq $8, %rbx
+1:
+ testq $0x1, %rcx /* is it a destination page? */
+ jz 2f
+ movq %rcx, %rdi
+ andq $0xfffffffffffff000, %rdi
+ jmp 0b
+2:
+ testq $0x2, %rcx /* is it an indirection page? */
+ jz 2f
+ movq %rcx, %rbx
+ andq $0xfffffffffffff000, %rbx
+ jmp 0b
+2:
+ testq $0x4, %rcx /* is it the done indicator? */
+ jz 2f
+ jmp 3f
+2:
+ testq $0x8, %rcx /* is it the source indicator? */
+ jz 0b /* Ignore it otherwise */
+ movq %rcx, %rsi /* For ever source page do a copy */
+ andq $0xfffffffffffff000, %rsi
+
+ movq $512, %rcx
+ rep ; movsq
+ jmp 0b
+3:
+
+ /* To be certain of avoiding problems with self-modifying code
+ * I need to execute a serializing instruction here.
+ * So I flush the TLB by reloading %cr3 here, it's handy,
+ * and not processor dependent.
+ */
+ movq %cr3, %rax
+ movq %rax, %cr3
+
+ /* set all of the registers to known values */
+ /* leave %rsp alone */
+
+ xorq %rax, %rax
+ xorq %rbx, %rbx
+ xorq %rcx, %rcx
+ xorq %rdx, %rdx
+ xorq %rsi, %rsi
+ xorq %rdi, %rdi
+ xorq %rbp, %rbp
+ xorq %r8, %r8
+ xorq %r9, %r9
+ xorq %r10, %r9
+ xorq %r11, %r11
+ xorq %r12, %r12
+ xorq %r13, %r13
+ xorq %r14, %r14
+ xorq %r15, %r15
+
+ ret
+relocate_new_kernel_end:
+
+ .globl relocate_new_kernel_size
+relocate_new_kernel_size:
+ .quad relocate_new_kernel_end - relocate_new_kernel
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index 2129cf9ba6b..b02d921da4f 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -40,6 +40,9 @@
#include <linux/acpi.h>
#include <linux/kallsyms.h>
#include <linux/edd.h>
+#include <linux/mmzone.h>
+#include <linux/kexec.h>
+
#include <asm/mtrr.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -348,7 +351,7 @@ static __init void parse_cmdline_early (char ** cmdline_p)
if (!memcmp(from, "mem=", 4))
parse_memopt(from+4, &from);
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NUMA
if (!memcmp(from, "numa=", 5))
numa_setup(from+5);
#endif
@@ -365,6 +368,27 @@ static __init void parse_cmdline_early (char ** cmdline_p)
if (!memcmp(from, "noexec=", 7))
nonx_setup(from + 7);
+#ifdef CONFIG_KEXEC
+ /* crashkernel=size@addr specifies the location to reserve for
+ * a crash kernel. By reserving this memory we guarantee
+ * that linux never set's it up as a DMA target.
+ * Useful for holding code to do something appropriate
+ * after a kernel panic.
+ */
+ else if (!memcmp(from, "crashkernel=", 12)) {
+ unsigned long size, base;
+ size = memparse(from+12, &from);
+ if (*from == '@') {
+ base = memparse(from+1, &from);
+ /* FIXME: Do I want a sanity check
+ * to validate the memory range?
+ */
+ crashk_res.start = base;
+ crashk_res.end = base + size - 1;
+ }
+ }
+#endif
+
next_char:
c = *(from++);
if (!c)
@@ -377,17 +401,20 @@ static __init void parse_cmdline_early (char ** cmdline_p)
*cmdline_p = command_line;
}
-#ifndef CONFIG_DISCONTIGMEM
-static void __init contig_initmem_init(void)
+#ifndef CONFIG_NUMA
+static void __init
+contig_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
{
- unsigned long bootmap_size, bootmap;
- bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT;
- bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size);
- if (bootmap == -1L)
- panic("Cannot find bootmem map of size %ld\n",bootmap_size);
- bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn);
- e820_bootmem_free(&contig_page_data, 0, end_pfn << PAGE_SHIFT);
- reserve_bootmem(bootmap, bootmap_size);
+ unsigned long bootmap_size, bootmap;
+
+ memory_present(0, start_pfn, end_pfn);
+ bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT;
+ bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size);
+ if (bootmap == -1L)
+ panic("Cannot find bootmem map of size %ld\n",bootmap_size);
+ bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn);
+ e820_bootmem_free(NODE_DATA(0), 0, end_pfn << PAGE_SHIFT);
+ reserve_bootmem(bootmap, bootmap_size);
}
#endif
@@ -554,10 +581,10 @@ void __init setup_arch(char **cmdline_p)
acpi_numa_init();
#endif
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NUMA
numa_initmem_init(0, end_pfn);
#else
- contig_initmem_init();
+ contig_initmem_init(0, end_pfn);
#endif
/* Reserve direct mapping */
@@ -618,6 +645,15 @@ void __init setup_arch(char **cmdline_p)
}
}
#endif
+
+ sparse_init();
+
+#ifdef CONFIG_KEXEC
+ if (crashk_res.start != crashk_res.end) {
+ reserve_bootmem(crashk_res.start,
+ crashk_res.end - crashk_res.start + 1);
+ }
+#endif
paging_init();
check_ioapic();
@@ -669,7 +705,7 @@ void __init setup_arch(char **cmdline_p)
#endif
}
-static int __init get_model_name(struct cpuinfo_x86 *c)
+static int __cpuinit get_model_name(struct cpuinfo_x86 *c)
{
unsigned int *v;
@@ -685,7 +721,7 @@ static int __init get_model_name(struct cpuinfo_x86 *c)
}
-static void __init display_cacheinfo(struct cpuinfo_x86 *c)
+static void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
{
unsigned int n, dummy, eax, ebx, ecx, edx;
@@ -719,7 +755,6 @@ static void __init display_cacheinfo(struct cpuinfo_x86 *c)
}
}
-#ifdef CONFIG_SMP
/*
* On a AMD dual core setup the lower bits of the APIC id distingush the cores.
* Assumes number of cores is a power of two.
@@ -727,17 +762,26 @@ static void __init display_cacheinfo(struct cpuinfo_x86 *c)
static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
{
#ifdef CONFIG_SMP
- int cpu = c->x86_apicid;
+ int cpu = smp_processor_id();
int node = 0;
+ unsigned bits;
if (c->x86_num_cores == 1)
return;
- cpu_core_id[cpu] = cpu >> hweight32(c->x86_num_cores - 1);
+
+ bits = 0;
+ while ((1 << bits) < c->x86_num_cores)
+ bits++;
+
+ /* Low order bits define the core id (index of core in socket) */
+ cpu_core_id[cpu] = phys_proc_id[cpu] & ((1 << bits)-1);
+ /* Convert the APIC ID into the socket ID */
+ phys_proc_id[cpu] >>= bits;
#ifdef CONFIG_NUMA
/* When an ACPI SRAT table is available use the mappings from SRAT
instead. */
if (acpi_numa <= 0) {
- node = cpu_core_id[cpu];
+ node = phys_proc_id[cpu];
if (!node_online(node))
node = first_node(node_online_map);
cpu_to_node[cpu] = node;
@@ -745,15 +789,11 @@ static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
node = cpu_to_node[cpu];
}
#endif
+
printk(KERN_INFO "CPU %d(%d) -> Node %d -> Core %d\n",
cpu, c->x86_num_cores, node, cpu_core_id[cpu]);
#endif
}
-#else
-static void __init amd_detect_cmp(struct cpuinfo_x86 *c)
-{
-}
-#endif
static int __init init_amd(struct cpuinfo_x86 *c)
{
@@ -792,7 +832,7 @@ static int __init init_amd(struct cpuinfo_x86 *c)
return r;
}
-static void __init detect_ht(struct cpuinfo_x86 *c)
+static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
{
#ifdef CONFIG_SMP
u32 eax, ebx, ecx, edx;
@@ -853,7 +893,7 @@ static void __init detect_ht(struct cpuinfo_x86 *c)
/*
* find out the number of processor cores on the die
*/
-static int __init intel_num_cpu_cores(struct cpuinfo_x86 *c)
+static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c)
{
unsigned int eax;
@@ -871,7 +911,7 @@ static int __init intel_num_cpu_cores(struct cpuinfo_x86 *c)
return 1;
}
-static void __init init_intel(struct cpuinfo_x86 *c)
+static void __cpuinit init_intel(struct cpuinfo_x86 *c)
{
/* Cache sizes */
unsigned n;
@@ -891,7 +931,7 @@ static void __init init_intel(struct cpuinfo_x86 *c)
c->x86_num_cores = intel_num_cpu_cores(c);
}
-void __init get_cpu_vendor(struct cpuinfo_x86 *c)
+void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
{
char *v = c->x86_vendor_id;
@@ -912,7 +952,7 @@ struct cpu_model_info {
/* Do some early cpuid on the boot CPU to get some parameter that are
needed before check_bugs. Everything advanced is in identify_cpu
below. */
-void __init early_identify_cpu(struct cpuinfo_x86 *c)
+void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
{
u32 tfms;
@@ -925,7 +965,6 @@ void __init early_identify_cpu(struct cpuinfo_x86 *c)
c->x86_clflush_size = 64;
c->x86_cache_alignment = c->x86_clflush_size;
c->x86_num_cores = 1;
- c->x86_apicid = c == &boot_cpu_data ? 0 : c - cpu_data;
c->extended_cpuid_level = 0;
memset(&c->x86_capability, 0, sizeof c->x86_capability);
@@ -954,17 +993,20 @@ void __init early_identify_cpu(struct cpuinfo_x86 *c)
}
if (c->x86_capability[0] & (1<<19))
c->x86_clflush_size = ((misc >> 8) & 0xff) * 8;
- c->x86_apicid = misc >> 24;
} else {
/* Have CPUID level 0 only - unheard of */
c->x86 = 4;
}
+
+#ifdef CONFIG_SMP
+ phys_proc_id[smp_processor_id()] = (cpuid_ebx(1) >> 24) & 0xff;
+#endif
}
/*
* This does the hard work of actually picking apart the CPU stuff...
*/
-void __init identify_cpu(struct cpuinfo_x86 *c)
+void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
{
int i;
u32 xlvl;
@@ -1041,7 +1083,7 @@ void __init identify_cpu(struct cpuinfo_x86 *c)
}
-void __init print_cpu_info(struct cpuinfo_x86 *c)
+void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
{
if (c->x86_model_id[0])
printk("%s", c->x86_model_id);
@@ -1088,7 +1130,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* Other (Linux-defined) */
- "cxmmx", NULL, "cyrix_arr", "centaur_mcr", "k8c+",
+ "cxmmx", NULL, "cyrix_arr", "centaur_mcr", NULL,
"constant_tsc", NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c
index 678b7ac33b8..f2b9c6bc999 100644
--- a/arch/x86_64/kernel/setup64.c
+++ b/arch/x86_64/kernel/setup64.c
@@ -29,7 +29,7 @@
char x86_boot_params[BOOT_PARAM_SIZE] __initdata = {0,};
-cpumask_t cpu_initialized __initdata = CPU_MASK_NONE;
+cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
struct x8664_pda cpu_pda[NR_CPUS] __cacheline_aligned;
@@ -171,7 +171,7 @@ void syscall_init(void)
wrmsrl(MSR_SYSCALL_MASK, EF_TF|EF_DF|EF_IE|0x3000);
}
-void __init check_efer(void)
+void __cpuinit check_efer(void)
{
unsigned long efer;
@@ -188,7 +188,7 @@ void __init check_efer(void)
* 'CPU state barrier', nothing should get across.
* A lot of state is already set up in PDA init.
*/
-void __init cpu_init (void)
+void __cpuinit cpu_init (void)
{
#ifdef CONFIG_SMP
int cpu = stack_smp_processor_id();
diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c
index d439ced150c..98590a989f3 100644
--- a/arch/x86_64/kernel/signal.c
+++ b/arch/x86_64/kernel/signal.c
@@ -28,14 +28,15 @@
#include <asm/uaccess.h>
#include <asm/i387.h>
#include <asm/proto.h>
+#include <asm/ia32_unistd.h>
/* #define DEBUG_SIG 1 */
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs * regs);
-void ia32_setup_frame(int sig, struct k_sigaction *ka,
+int ia32_setup_frame(int sig, struct k_sigaction *ka,
sigset_t *set, struct pt_regs * regs);
asmlinkage long
@@ -237,7 +238,7 @@ get_stack(struct k_sigaction *ka, struct pt_regs *regs, unsigned long size)
return (void __user *)round_down(rsp - size, 16);
}
-static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs * regs)
{
struct rt_sigframe __user *frame;
@@ -326,20 +327,23 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
current->comm, current->pid, frame, regs->rip, frame->pretcode);
#endif
- return;
+ return 1;
give_sigsegv:
force_sigsegv(sig, current);
+ return 0;
}
/*
* OK, we're invoking a handler
*/
-static void
+static int
handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
sigset_t *oldset, struct pt_regs *regs)
{
+ int ret;
+
#ifdef DEBUG_SIG
printk("handle_signal pid:%d sig:%lu rip:%lx rsp:%lx regs=%p\n",
current->pid, sig,
@@ -383,20 +387,22 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
#ifdef CONFIG_IA32_EMULATION
if (test_thread_flag(TIF_IA32)) {
if (ka->sa.sa_flags & SA_SIGINFO)
- ia32_setup_rt_frame(sig, ka, info, oldset, regs);
+ ret = ia32_setup_rt_frame(sig, ka, info, oldset, regs);
else
- ia32_setup_frame(sig, ka, oldset, regs);
+ ret = ia32_setup_frame(sig, ka, oldset, regs);
} else
#endif
- setup_rt_frame(sig, ka, info, oldset, regs);
+ ret = setup_rt_frame(sig, ka, info, oldset, regs);
- if (!(ka->sa.sa_flags & SA_NODEFER)) {
+ if (ret && !(ka->sa.sa_flags & SA_NODEFER)) {
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
sigaddset(&current->blocked,sig);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
}
+
+ return ret;
}
/*
@@ -416,10 +422,10 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
* kernel mode. Just return without doing anything
* if so.
*/
- if ((regs->cs & 3) != 3)
+ if (!user_mode(regs))
return 1;
- if (try_to_freeze(0))
+ if (try_to_freeze())
goto no_signal;
if (!oldset)
@@ -433,11 +439,10 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
* inside the kernel.
*/
if (current->thread.debugreg7)
- asm volatile("movq %0,%%db7" : : "r" (current->thread.debugreg7));
+ set_debugreg(current->thread.debugreg7, 7);
/* Whee! Actually deliver the signal. */
- handle_signal(signr, &info, &ka, oldset, regs);
- return 1;
+ return handle_signal(signr, &info, &ka, oldset, regs);
}
no_signal:
@@ -452,7 +457,9 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
regs->rip -= 2;
}
if (regs->rax == (unsigned long)-ERESTART_RESTARTBLOCK) {
- regs->rax = __NR_restart_syscall;
+ regs->rax = test_thread_flag(TIF_IA32) ?
+ __NR_ia32_restart_syscall :
+ __NR_restart_syscall;
regs->rip -= 2;
}
}
diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c
index 1e379ed17b1..ccae392886a 100644
--- a/arch/x86_64/kernel/smp.c
+++ b/arch/x86_64/kernel/smp.c
@@ -283,6 +283,16 @@ struct call_data_struct {
static struct call_data_struct * call_data;
+void lock_ipi_call_lock(void)
+{
+ spin_lock_irq(&call_lock);
+}
+
+void unlock_ipi_call_lock(void)
+{
+ spin_unlock_irq(&call_lock);
+}
+
/*
* this function sends a 'generic call function' IPI to all other CPUs
* in the system.
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index 73f7e8b9543..b969ee12872 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -34,6 +34,7 @@
* Andi Kleen : Converted to new state machine.
* Various cleanups.
* Probably mostly hotplug CPU ready now.
+ * Ashok Raj : CPU hotplug support
*/
@@ -56,11 +57,7 @@
#include <asm/kdebug.h>
#include <asm/tlbflush.h>
#include <asm/proto.h>
-
-/* Change for real CPU hotplug. Note other files need to be fixed
- first too. */
-#define __cpuinit __init
-#define __cpuinitdata __initdata
+#include <asm/nmi.h>
/* Number of siblings per CPU package */
int smp_num_siblings = 1;
@@ -93,6 +90,7 @@ int smp_threads_ready;
cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
+EXPORT_SYMBOL(cpu_core_map);
/*
* Trampoline 80x86 program as an array.
@@ -101,6 +99,37 @@ cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
extern unsigned char trampoline_data[];
extern unsigned char trampoline_end[];
+/* State of each CPU */
+DEFINE_PER_CPU(int, cpu_state) = { 0 };
+
+/*
+ * Store all idle threads, this can be reused instead of creating
+ * a new thread. Also avoids complicated thread destroy functionality
+ * for idle threads.
+ */
+struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ;
+
+#define get_idle_for_cpu(x) (idle_thread_array[(x)])
+#define set_idle_for_cpu(x,p) (idle_thread_array[(x)] = (p))
+
+/*
+ * cpu_possible_map should be static, it cannot change as cpu's
+ * are onlined, or offlined. The reason is per-cpu data-structures
+ * are allocated by some modules at init time, and dont expect to
+ * do this dynamically on cpu arrival/departure.
+ * cpu_present_map on the other hand can change dynamically.
+ * In case when cpu_hotplug is not compiled, then we resort to current
+ * behaviour, which is cpu_possible == cpu_present.
+ * If cpu-hotplug is supported, then we need to preallocate for all
+ * those NR_CPUS, hence cpu_possible_map represents entire NR_CPUS range.
+ * - Ashok Raj
+ */
+#ifdef CONFIG_HOTPLUG_CPU
+#define fixup_cpu_possible_map(x) cpu_set((x), cpu_possible_map)
+#else
+#define fixup_cpu_possible_map(x)
+#endif
+
/*
* Currently trivial. Write the real->protected mode
* bootstrap into the page concerned. The caller
@@ -125,96 +154,210 @@ static void __cpuinit smp_store_cpu_info(int id)
*c = boot_cpu_data;
identify_cpu(c);
+ print_cpu_info(c);
}
/*
- * Synchronize TSCs of CPUs
+ * New Funky TSC sync algorithm borrowed from IA64.
+ * Main advantage is that it doesn't reset the TSCs fully and
+ * in general looks more robust and it works better than my earlier
+ * attempts. I believe it was written by David Mosberger. Some minor
+ * adjustments for x86-64 by me -AK
+ *
+ * Original comment reproduced below.
*
- * This new algorithm is less accurate than the old "zero TSCs"
- * one, but we cannot zero TSCs anymore in the new hotplug CPU
- * model.
+ * Synchronize TSC of the current (slave) CPU with the TSC of the
+ * MASTER CPU (normally the time-keeper CPU). We use a closed loop to
+ * eliminate the possibility of unaccounted-for errors (such as
+ * getting a machine check in the middle of a calibration step). The
+ * basic idea is for the slave to ask the master what itc value it has
+ * and to read its own itc before and after the master responds. Each
+ * iteration gives us three timestamps:
+ *
+ * slave master
+ *
+ * t0 ---\
+ * ---\
+ * --->
+ * tm
+ * /---
+ * /---
+ * t1 <---
+ *
+ *
+ * The goal is to adjust the slave's TSC such that tm falls exactly
+ * half-way between t0 and t1. If we achieve this, the clocks are
+ * synchronized provided the interconnect between the slave and the
+ * master is symmetric. Even if the interconnect were asymmetric, we
+ * would still know that the synchronization error is smaller than the
+ * roundtrip latency (t0 - t1).
+ *
+ * When the interconnect is quiet and symmetric, this lets us
+ * synchronize the TSC to within one or two cycles. However, we can
+ * only *guarantee* that the synchronization is accurate to within a
+ * round-trip time, which is typically in the range of several hundred
+ * cycles (e.g., ~500 cycles). In practice, this means that the TSCs
+ * are usually almost perfectly synchronized, but we shouldn't assume
+ * that the accuracy is much better than half a micro second or so.
+ *
+ * [there are other errors like the latency of RDTSC and of the
+ * WRMSR. These can also account to hundreds of cycles. So it's
+ * probably worse. It claims 153 cycles error on a dual Opteron,
+ * but I suspect the numbers are actually somewhat worse -AK]
*/
-static atomic_t __cpuinitdata tsc_flag;
+#define MASTER 0
+#define SLAVE (SMP_CACHE_BYTES/8)
+
+/* Intentionally don't use cpu_relax() while TSC synchronization
+ because we don't want to go into funky power save modi or cause
+ hypervisors to schedule us away. Going to sleep would likely affect
+ latency and low latency is the primary objective here. -AK */
+#define no_cpu_relax() barrier()
+
static __cpuinitdata DEFINE_SPINLOCK(tsc_sync_lock);
-static unsigned long long __cpuinitdata bp_tsc, ap_tsc;
+static volatile __cpuinitdata unsigned long go[SLAVE + 1];
+static int notscsync __cpuinitdata;
-#define NR_LOOPS 5
+#undef DEBUG_TSC_SYNC
-static void __cpuinit sync_tsc_bp_init(int init)
+#define NUM_ROUNDS 64 /* magic value */
+#define NUM_ITERS 5 /* likewise */
+
+/* Callback on boot CPU */
+static __cpuinit void sync_master(void *arg)
{
- if (init)
- _raw_spin_lock(&tsc_sync_lock);
- else
- _raw_spin_unlock(&tsc_sync_lock);
- atomic_set(&tsc_flag, 0);
+ unsigned long flags, i;
+
+ if (smp_processor_id() != boot_cpu_id)
+ return;
+
+ go[MASTER] = 0;
+
+ local_irq_save(flags);
+ {
+ for (i = 0; i < NUM_ROUNDS*NUM_ITERS; ++i) {
+ while (!go[MASTER])
+ no_cpu_relax();
+ go[MASTER] = 0;
+ rdtscll(go[SLAVE]);
+ }
+ }
+ local_irq_restore(flags);
}
/*
- * Synchronize TSC on AP with BP.
+ * Return the number of cycles by which our tsc differs from the tsc
+ * on the master (time-keeper) CPU. A positive number indicates our
+ * tsc is ahead of the master, negative that it is behind.
*/
-static void __cpuinit __sync_tsc_ap(void)
+static inline long
+get_delta(long *rt, long *master)
{
- if (!cpu_has_tsc)
- return;
- Dprintk("AP %d syncing TSC\n", smp_processor_id());
+ unsigned long best_t0 = 0, best_t1 = ~0UL, best_tm = 0;
+ unsigned long tcenter, t0, t1, tm;
+ int i;
- while (atomic_read(&tsc_flag) != 0)
- cpu_relax();
- atomic_inc(&tsc_flag);
- mb();
- _raw_spin_lock(&tsc_sync_lock);
- wrmsrl(MSR_IA32_TSC, bp_tsc);
- _raw_spin_unlock(&tsc_sync_lock);
- rdtscll(ap_tsc);
- mb();
- atomic_inc(&tsc_flag);
- mb();
+ for (i = 0; i < NUM_ITERS; ++i) {
+ rdtscll(t0);
+ go[MASTER] = 1;
+ while (!(tm = go[SLAVE]))
+ no_cpu_relax();
+ go[SLAVE] = 0;
+ rdtscll(t1);
+
+ if (t1 - t0 < best_t1 - best_t0)
+ best_t0 = t0, best_t1 = t1, best_tm = tm;
+ }
+
+ *rt = best_t1 - best_t0;
+ *master = best_tm - best_t0;
+
+ /* average best_t0 and best_t1 without overflow: */
+ tcenter = (best_t0/2 + best_t1/2);
+ if (best_t0 % 2 + best_t1 % 2 == 2)
+ ++tcenter;
+ return tcenter - best_tm;
}
-static void __cpuinit sync_tsc_ap(void)
+static __cpuinit void sync_tsc(void)
{
- int i;
- for (i = 0; i < NR_LOOPS; i++)
- __sync_tsc_ap();
+ int i, done = 0;
+ long delta, adj, adjust_latency = 0;
+ unsigned long flags, rt, master_time_stamp, bound;
+#if DEBUG_TSC_SYNC
+ static struct syncdebug {
+ long rt; /* roundtrip time */
+ long master; /* master's timestamp */
+ long diff; /* difference between midpoint and master's timestamp */
+ long lat; /* estimate of tsc adjustment latency */
+ } t[NUM_ROUNDS] __cpuinitdata;
+#endif
+
+ go[MASTER] = 1;
+
+ smp_call_function(sync_master, NULL, 1, 0);
+
+ while (go[MASTER]) /* wait for master to be ready */
+ no_cpu_relax();
+
+ spin_lock_irqsave(&tsc_sync_lock, flags);
+ {
+ for (i = 0; i < NUM_ROUNDS; ++i) {
+ delta = get_delta(&rt, &master_time_stamp);
+ if (delta == 0) {
+ done = 1; /* let's lock on to this... */
+ bound = rt;
+ }
+
+ if (!done) {
+ unsigned long t;
+ if (i > 0) {
+ adjust_latency += -delta;
+ adj = -delta + adjust_latency/4;
+ } else
+ adj = -delta;
+
+ rdtscll(t);
+ wrmsrl(MSR_IA32_TSC, t + adj);
+ }
+#if DEBUG_TSC_SYNC
+ t[i].rt = rt;
+ t[i].master = master_time_stamp;
+ t[i].diff = delta;
+ t[i].lat = adjust_latency/4;
+#endif
+ }
+ }
+ spin_unlock_irqrestore(&tsc_sync_lock, flags);
+
+#if DEBUG_TSC_SYNC
+ for (i = 0; i < NUM_ROUNDS; ++i)
+ printk("rt=%5ld master=%5ld diff=%5ld adjlat=%5ld\n",
+ t[i].rt, t[i].master, t[i].diff, t[i].lat);
+#endif
+
+ printk(KERN_INFO
+ "CPU %d: synchronized TSC with CPU %u (last diff %ld cycles, "
+ "maxerr %lu cycles)\n",
+ smp_processor_id(), boot_cpu_id, delta, rt);
}
-/*
- * Synchronize TSC from BP to AP.
- */
-static void __cpuinit __sync_tsc_bp(int cpu)
+static void __cpuinit tsc_sync_wait(void)
{
- if (!cpu_has_tsc)
+ if (notscsync || !cpu_has_tsc)
return;
-
- /* Wait for AP */
- while (atomic_read(&tsc_flag) == 0)
- cpu_relax();
- /* Save BPs TSC */
- sync_core();
- rdtscll(bp_tsc);
- /* Don't do the sync core here to avoid too much latency. */
- mb();
- /* Start the AP */
- _raw_spin_unlock(&tsc_sync_lock);
- /* Wait for AP again */
- while (atomic_read(&tsc_flag) < 2)
- cpu_relax();
- rdtscl(bp_tsc);
- barrier();
+ printk(KERN_INFO "CPU %d: Syncing TSC to CPU %u.\n", smp_processor_id(),
+ boot_cpu_id);
+ sync_tsc();
}
-static void __cpuinit sync_tsc_bp(int cpu)
+static __init int notscsync_setup(char *s)
{
- int i;
- for (i = 0; i < NR_LOOPS - 1; i++) {
- __sync_tsc_bp(cpu);
- sync_tsc_bp_init(1);
- }
- __sync_tsc_bp(cpu);
- printk(KERN_INFO "Synced TSC of CPU %d difference %Ld\n",
- cpu, ap_tsc - bp_tsc);
+ notscsync = 1;
+ return 0;
}
+__setup("notscsync", notscsync_setup);
static atomic_t init_deasserted __cpuinitdata;
@@ -302,6 +445,33 @@ void __cpuinit smp_callin(void)
cpu_set(cpuid, cpu_callin_map);
}
+static inline void set_cpu_sibling_map(int cpu)
+{
+ int i;
+
+ if (smp_num_siblings > 1) {
+ for_each_cpu(i) {
+ if (cpu_core_id[cpu] == cpu_core_id[i]) {
+ cpu_set(i, cpu_sibling_map[cpu]);
+ cpu_set(cpu, cpu_sibling_map[i]);
+ }
+ }
+ } else {
+ cpu_set(cpu, cpu_sibling_map[cpu]);
+ }
+
+ if (current_cpu_data.x86_num_cores > 1) {
+ for_each_cpu(i) {
+ if (phys_proc_id[cpu] == phys_proc_id[i]) {
+ cpu_set(i, cpu_core_map[cpu]);
+ cpu_set(cpu, cpu_core_map[i]);
+ }
+ }
+ } else {
+ cpu_core_map[cpu] = cpu_sibling_map[cpu];
+ }
+}
+
/*
* Setup code on secondary processor (after comming out of the trampoline)
*/
@@ -315,11 +485,6 @@ void __cpuinit start_secondary(void)
cpu_init();
smp_callin();
- /*
- * Synchronize the TSC with the BP
- */
- sync_tsc_ap();
-
/* otherwise gcc will move up the smp_processor_id before the cpu_init */
barrier();
@@ -334,15 +499,38 @@ void __cpuinit start_secondary(void)
enable_8259A_irq(0);
}
-
enable_APIC_timer();
/*
+ * The sibling maps must be set before turing the online map on for
+ * this cpu
+ */
+ set_cpu_sibling_map(smp_processor_id());
+
+ /*
+ * We need to hold call_lock, so there is no inconsistency
+ * between the time smp_call_function() determines number of
+ * IPI receipients, and the time when the determination is made
+ * for which cpus receive the IPI in genapic_flat.c. Holding this
+ * lock helps us to not include this cpu in a currently in progress
+ * smp_call_function().
+ */
+ lock_ipi_call_lock();
+
+ /*
* Allow the master to continue.
*/
cpu_set(smp_processor_id(), cpu_online_map);
+ per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
+ unlock_ipi_call_lock();
+
mb();
+ /* Wait for TSC sync to not schedule things before.
+ We still process interrupts, which could see an inconsistent
+ time in that window unfortunately. */
+ tsc_sync_wait();
+
cpu_idle();
}
@@ -513,34 +701,77 @@ static int __cpuinit wakeup_secondary_via_INIT(int phys_apicid, unsigned int sta
return (send_status | accept_status);
}
+struct create_idle {
+ struct task_struct *idle;
+ struct completion done;
+ int cpu;
+};
+
+void do_fork_idle(void *_c_idle)
+{
+ struct create_idle *c_idle = _c_idle;
+
+ c_idle->idle = fork_idle(c_idle->cpu);
+ complete(&c_idle->done);
+}
+
/*
* Boot one CPU.
*/
static int __cpuinit do_boot_cpu(int cpu, int apicid)
{
- struct task_struct *idle;
unsigned long boot_error;
int timeout;
unsigned long start_rip;
+ struct create_idle c_idle = {
+ .cpu = cpu,
+ .done = COMPLETION_INITIALIZER(c_idle.done),
+ };
+ DECLARE_WORK(work, do_fork_idle, &c_idle);
+
+ c_idle.idle = get_idle_for_cpu(cpu);
+
+ if (c_idle.idle) {
+ c_idle.idle->thread.rsp = (unsigned long) (((struct pt_regs *)
+ (THREAD_SIZE + (unsigned long) c_idle.idle->thread_info)) - 1);
+ init_idle(c_idle.idle, cpu);
+ goto do_rest;
+ }
+
/*
- * We can't use kernel_thread since we must avoid to
- * reschedule the child.
+ * During cold boot process, keventd thread is not spun up yet.
+ * When we do cpu hot-add, we create idle threads on the fly, we should
+ * not acquire any attributes from the calling context. Hence the clean
+ * way to create kernel_threads() is to do that from keventd().
+ * We do the current_is_keventd() due to the fact that ACPI notifier
+ * was also queuing to keventd() and when the caller is already running
+ * in context of keventd(), we would end up with locking up the keventd
+ * thread.
*/
- idle = fork_idle(cpu);
- if (IS_ERR(idle)) {
+ if (!keventd_up() || current_is_keventd())
+ work.func(work.data);
+ else {
+ schedule_work(&work);
+ wait_for_completion(&c_idle.done);
+ }
+
+ if (IS_ERR(c_idle.idle)) {
printk("failed fork for CPU %d\n", cpu);
- return PTR_ERR(idle);
+ return PTR_ERR(c_idle.idle);
}
- x86_cpu_to_apicid[cpu] = apicid;
- cpu_pda[cpu].pcurrent = idle;
+ set_idle_for_cpu(cpu, c_idle.idle);
+
+do_rest:
+
+ cpu_pda[cpu].pcurrent = c_idle.idle;
start_rip = setup_trampoline();
- init_rsp = idle->thread.rsp;
+ init_rsp = c_idle.idle->thread.rsp;
per_cpu(init_tss,cpu).rsp0 = init_rsp;
initial_code = start_secondary;
- clear_ti_thread_flag(idle->thread_info, TIF_FORK);
+ clear_ti_thread_flag(c_idle.idle->thread_info, TIF_FORK);
printk(KERN_INFO "Booting processor %d/%d rip %lx rsp %lx\n", cpu, apicid,
start_rip, init_rsp);
@@ -600,8 +831,6 @@ static int __cpuinit do_boot_cpu(int cpu, int apicid)
if (cpu_isset(cpu, cpu_callin_map)) {
/* number CPUs logically, starting from 1 (BSP is 0) */
- Dprintk("OK.\n");
- print_cpu_info(&cpu_data[cpu]);
Dprintk("CPU has booted.\n");
} else {
boot_error = 1;
@@ -634,51 +863,6 @@ cycles_t cacheflush_time;
unsigned long cache_decay_ticks;
/*
- * Construct cpu_sibling_map[], so that we can tell the sibling CPU
- * on SMT systems efficiently.
- */
-static __cpuinit void detect_siblings(void)
-{
- int cpu;
-
- for (cpu = 0; cpu < NR_CPUS; cpu++) {
- cpus_clear(cpu_sibling_map[cpu]);
- cpus_clear(cpu_core_map[cpu]);
- }
-
- for_each_online_cpu (cpu) {
- struct cpuinfo_x86 *c = cpu_data + cpu;
- int siblings = 0;
- int i;
- if (smp_num_siblings > 1) {
- for_each_online_cpu (i) {
- if (cpu_core_id[cpu] == cpu_core_id[i]) {
- siblings++;
- cpu_set(i, cpu_sibling_map[cpu]);
- }
- }
- } else {
- siblings++;
- cpu_set(cpu, cpu_sibling_map[cpu]);
- }
-
- if (siblings != smp_num_siblings) {
- printk(KERN_WARNING
- "WARNING: %d siblings found for CPU%d, should be %d\n",
- siblings, cpu, smp_num_siblings);
- smp_num_siblings = siblings;
- }
- if (c->x86_num_cores > 1) {
- for_each_online_cpu(i) {
- if (phys_proc_id[cpu] == phys_proc_id[i])
- cpu_set(i, cpu_core_map[cpu]);
- }
- } else
- cpu_core_map[cpu] = cpu_sibling_map[cpu];
- }
-}
-
-/*
* Cleanup possible dangling ends...
*/
static __cpuinit void smp_cleanup_boot(void)
@@ -711,7 +895,7 @@ static __cpuinit void smp_cleanup_boot(void)
*
* RED-PEN audit/test this more. I bet there is more state messed up here.
*/
-static __cpuinit void disable_smp(void)
+static __init void disable_smp(void)
{
cpu_present_map = cpumask_of_cpu(0);
cpu_possible_map = cpumask_of_cpu(0);
@@ -726,7 +910,7 @@ static __cpuinit void disable_smp(void)
/*
* Handle user cpus=... parameter.
*/
-static __cpuinit void enforce_max_cpus(unsigned max_cpus)
+static __init void enforce_max_cpus(unsigned max_cpus)
{
int i, k;
k = 0;
@@ -743,7 +927,7 @@ static __cpuinit void enforce_max_cpus(unsigned max_cpus)
/*
* Various sanity checks.
*/
-static int __cpuinit smp_sanity_check(unsigned max_cpus)
+static int __init smp_sanity_check(unsigned max_cpus)
{
if (!physid_isset(hard_smp_processor_id(), phys_cpu_present_map)) {
printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
@@ -801,7 +985,7 @@ static int __cpuinit smp_sanity_check(unsigned max_cpus)
* Prepare for SMP bootup. The MP table or ACPI has been read
* earlier. Just do some sanity checking here and enable APIC mode.
*/
-void __cpuinit smp_prepare_cpus(unsigned int max_cpus)
+void __init smp_prepare_cpus(unsigned int max_cpus)
{
int i;
@@ -818,10 +1002,9 @@ void __cpuinit smp_prepare_cpus(unsigned int max_cpus)
int apicid = cpu_present_to_apicid(i);
if (physid_isset(apicid, phys_cpu_present_map)) {
cpu_set(i, cpu_present_map);
- /* possible map would be different if we supported real
- CPU hotplug. */
cpu_set(i, cpu_possible_map);
}
+ fixup_cpu_possible_map(i);
}
if (smp_sanity_check(max_cpus) < 0) {
@@ -842,7 +1025,6 @@ void __cpuinit smp_prepare_cpus(unsigned int max_cpus)
GET_APIC_ID(apic_read(APIC_ID)), boot_cpu_id);
/* Or can we switch back to PIC here? */
}
- x86_cpu_to_apicid[0] = boot_cpu_id;
/*
* Now start the IO-APICs
@@ -867,13 +1049,13 @@ void __init smp_prepare_boot_cpu(void)
int me = smp_processor_id();
cpu_set(me, cpu_online_map);
cpu_set(me, cpu_callout_map);
+ cpu_set(0, cpu_sibling_map[0]);
+ cpu_set(0, cpu_core_map[0]);
+ per_cpu(cpu_state, me) = CPU_ONLINE;
}
/*
* Entry point to boot a CPU.
- *
- * This is all __cpuinit, not __devinit for now because we don't support
- * CPU hotplug (yet).
*/
int __cpuinit __cpu_up(unsigned int cpu)
{
@@ -889,38 +1071,140 @@ int __cpuinit __cpu_up(unsigned int cpu)
printk("__cpu_up: bad cpu %d\n", cpu);
return -EINVAL;
}
- sync_tsc_bp_init(1);
+ /*
+ * Already booted CPU?
+ */
+ if (cpu_isset(cpu, cpu_callin_map)) {
+ Dprintk("do_boot_cpu %d Already started\n", cpu);
+ return -ENOSYS;
+ }
+
+ per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
/* Boot it! */
err = do_boot_cpu(cpu, apicid);
if (err < 0) {
- sync_tsc_bp_init(0);
Dprintk("do_boot_cpu failed %d\n", err);
return err;
}
- sync_tsc_bp(cpu);
-
/* Unleash the CPU! */
Dprintk("waiting for cpu %d\n", cpu);
while (!cpu_isset(cpu, cpu_online_map))
cpu_relax();
- return 0;
+ err = 0;
+
+ return err;
}
/*
* Finish the SMP boot.
*/
-void __cpuinit smp_cpus_done(unsigned int max_cpus)
+void __init smp_cpus_done(unsigned int max_cpus)
{
+#ifndef CONFIG_HOTPLUG_CPU
zap_low_mappings();
+#endif
smp_cleanup_boot();
#ifdef CONFIG_X86_IO_APIC
setup_ioapic_dest();
#endif
- detect_siblings();
time_init_gtod();
+
+ check_nmi_watchdog();
+}
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+static void remove_siblinginfo(int cpu)
+{
+ int sibling;
+
+ for_each_cpu_mask(sibling, cpu_sibling_map[cpu])
+ cpu_clear(cpu, cpu_sibling_map[sibling]);
+ for_each_cpu_mask(sibling, cpu_core_map[cpu])
+ cpu_clear(cpu, cpu_core_map[sibling]);
+ cpus_clear(cpu_sibling_map[cpu]);
+ cpus_clear(cpu_core_map[cpu]);
+ phys_proc_id[cpu] = BAD_APICID;
+ cpu_core_id[cpu] = BAD_APICID;
+}
+
+void remove_cpu_from_maps(void)
+{
+ int cpu = smp_processor_id();
+
+ cpu_clear(cpu, cpu_callout_map);
+ cpu_clear(cpu, cpu_callin_map);
+ clear_bit(cpu, &cpu_initialized); /* was set by cpu_init() */
+}
+
+int __cpu_disable(void)
+{
+ int cpu = smp_processor_id();
+
+ /*
+ * Perhaps use cpufreq to drop frequency, but that could go
+ * into generic code.
+ *
+ * We won't take down the boot processor on i386 due to some
+ * interrupts only being able to be serviced by the BSP.
+ * Especially so if we're not using an IOAPIC -zwane
+ */
+ if (cpu == 0)
+ return -EBUSY;
+
+ disable_APIC_timer();
+
+ /*
+ * HACK:
+ * Allow any queued timer interrupts to get serviced
+ * This is only a temporary solution until we cleanup
+ * fixup_irqs as we do for IA64.
+ */
+ local_irq_enable();
+ mdelay(1);
+
+ local_irq_disable();
+ remove_siblinginfo(cpu);
+
+ /* It's now safe to remove this processor from the online map */
+ cpu_clear(cpu, cpu_online_map);
+ remove_cpu_from_maps();
+ fixup_irqs(cpu_online_map);
+ return 0;
+}
+
+void __cpu_die(unsigned int cpu)
+{
+ /* We don't do anything here: idle task is faking death itself. */
+ unsigned int i;
+
+ for (i = 0; i < 10; i++) {
+ /* They ack this in play_dead by setting CPU_DEAD */
+ if (per_cpu(cpu_state, cpu) == CPU_DEAD) {
+ printk ("CPU %d is now offline\n", cpu);
+ return;
+ }
+ current->state = TASK_UNINTERRUPTIBLE;
+ schedule_timeout(HZ/10);
+ }
+ printk(KERN_ERR "CPU %u didn't die...\n", cpu);
+}
+
+#else /* ... !CONFIG_HOTPLUG_CPU */
+
+int __cpu_disable(void)
+{
+ return -ENOSYS;
+}
+
+void __cpu_die(unsigned int cpu)
+{
+ /* We said "no" in __cpu_disable */
+ BUG();
}
+#endif /* CONFIG_HOTPLUG_CPU */
diff --git a/arch/x86_64/kernel/suspend.c b/arch/x86_64/kernel/suspend.c
index ebaa1e37d65..6c0f402e3a8 100644
--- a/arch/x86_64/kernel/suspend.c
+++ b/arch/x86_64/kernel/suspend.c
@@ -44,7 +44,6 @@ void __save_processor_state(struct saved_context *ctxt)
*/
asm volatile ("sgdt %0" : "=m" (ctxt->gdt_limit));
asm volatile ("sidt %0" : "=m" (ctxt->idt_limit));
- asm volatile ("sldt %0" : "=m" (ctxt->ldt));
asm volatile ("str %0" : "=m" (ctxt->tr));
/* XMM0..XMM15 should be handled by kernel_fpu_begin(). */
@@ -69,6 +68,7 @@ void __save_processor_state(struct saved_context *ctxt)
asm volatile ("movq %%cr2, %0" : "=r" (ctxt->cr2));
asm volatile ("movq %%cr3, %0" : "=r" (ctxt->cr3));
asm volatile ("movq %%cr4, %0" : "=r" (ctxt->cr4));
+ asm volatile ("movq %%cr8, %0" : "=r" (ctxt->cr8));
}
void save_processor_state(void)
@@ -90,12 +90,20 @@ void __restore_processor_state(struct saved_context *ctxt)
/*
* control registers
*/
+ asm volatile ("movq %0, %%cr8" :: "r" (ctxt->cr8));
asm volatile ("movq %0, %%cr4" :: "r" (ctxt->cr4));
asm volatile ("movq %0, %%cr3" :: "r" (ctxt->cr3));
asm volatile ("movq %0, %%cr2" :: "r" (ctxt->cr2));
asm volatile ("movq %0, %%cr0" :: "r" (ctxt->cr0));
/*
+ * now restore the descriptor tables to their proper values
+ * ltr is done i fix_processor_context().
+ */
+ asm volatile ("lgdt %0" :: "m" (ctxt->gdt_limit));
+ asm volatile ("lidt %0" :: "m" (ctxt->idt_limit));
+
+ /*
* segment registers
*/
asm volatile ("movw %0, %%ds" :: "r" (ctxt->ds));
@@ -108,14 +116,6 @@ void __restore_processor_state(struct saved_context *ctxt)
wrmsrl(MSR_GS_BASE, ctxt->gs_base);
wrmsrl(MSR_KERNEL_GS_BASE, ctxt->gs_kernel_base);
- /*
- * now restore the descriptor tables to their proper values
- * ltr is done i fix_processor_context().
- */
- asm volatile ("lgdt %0" :: "m" (ctxt->gdt_limit));
- asm volatile ("lidt %0" :: "m" (ctxt->idt_limit));
- asm volatile ("lldt %0" :: "m" (ctxt->ldt));
-
fix_processor_context();
do_fpu_end();
diff --git a/arch/x86_64/kernel/sys_x86_64.c b/arch/x86_64/kernel/sys_x86_64.c
index dbebd5ccba6..cc7821c6885 100644
--- a/arch/x86_64/kernel/sys_x86_64.c
+++ b/arch/x86_64/kernel/sys_x86_64.c
@@ -68,13 +68,7 @@ out:
static void find_start_end(unsigned long flags, unsigned long *begin,
unsigned long *end)
{
-#ifdef CONFIG_IA32_EMULATION
- if (test_thread_flag(TIF_IA32)) {
- *begin = TASK_UNMAPPED_32;
- *end = IA32_PAGE_OFFSET;
- } else
-#endif
- if (flags & MAP_32BIT) {
+ if (!test_thread_flag(TIF_IA32) && (flags & MAP_32BIT)) {
/* This is usually used needed to map code in small
model, so it needs to be in the first 31bit. Limit
it to that. This means we need to move the
@@ -84,10 +78,10 @@ static void find_start_end(unsigned long flags, unsigned long *begin,
of playground for now. -AK */
*begin = 0x40000000;
*end = 0x80000000;
- } else {
- *begin = TASK_UNMAPPED_64;
+ } else {
+ *begin = TASK_UNMAPPED_BASE;
*end = TASK_SIZE;
- }
+ }
}
unsigned long
@@ -111,6 +105,11 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
(!vma || addr + len <= vma->vm_start))
return addr;
}
+ if (((flags & MAP_32BIT) || test_thread_flag(TIF_IA32))
+ && len <= mm->cached_hole_size) {
+ mm->cached_hole_size = 0;
+ mm->free_area_cache = begin;
+ }
addr = mm->free_area_cache;
if (addr < begin)
addr = begin;
@@ -126,6 +125,7 @@ full_search:
*/
if (start_addr != begin) {
start_addr = addr = begin;
+ mm->cached_hole_size = 0;
goto full_search;
}
return -ENOMEM;
@@ -137,6 +137,9 @@ full_search:
mm->free_area_cache = addr + len;
return addr;
}
+ if (addr + mm->cached_hole_size < vma->vm_start)
+ mm->cached_hole_size = vma->vm_start - addr;
+
addr = vma->vm_end;
}
}
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index 0e3b60e1ac5..66bf6ddeb0c 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -26,6 +26,10 @@
#include <linux/sysdev.h>
#include <linux/bcd.h>
#include <linux/kallsyms.h>
+#include <linux/acpi.h>
+#ifdef CONFIG_ACPI
+#include <acpi/achware.h> /* for PM timer frequency */
+#endif
#include <asm/8253pit.h>
#include <asm/pgtable.h>
#include <asm/vsyscall.h>
@@ -60,6 +64,7 @@ static int notsc __initdata = 0;
unsigned int cpu_khz; /* TSC clocks / usec, not used here */
static unsigned long hpet_period; /* fsecs / HPET clock */
unsigned long hpet_tick; /* HPET clocks / interrupt */
+static int hpet_use_timer;
unsigned long vxtime_hz = PIT_TICK_RATE;
int report_lost_ticks; /* command line option */
unsigned long long monotonic_base;
@@ -101,7 +106,9 @@ static inline unsigned int do_gettimeoffset_tsc(void)
static inline unsigned int do_gettimeoffset_hpet(void)
{
- return ((hpet_readl(HPET_COUNTER) - vxtime.last) * vxtime.quot) >> 32;
+ /* cap counter read to one tick to avoid inconsistencies */
+ unsigned long counter = hpet_readl(HPET_COUNTER) - vxtime.last;
+ return (min(counter,hpet_tick) * vxtime.quot) >> 32;
}
unsigned int (*do_gettimeoffset)(void) = do_gettimeoffset_tsc;
@@ -297,7 +304,7 @@ unsigned long long monotonic_clock(void)
last_offset = vxtime.last;
base = monotonic_base;
- this_offset = hpet_readl(HPET_T0_CMP) - hpet_tick;
+ this_offset = hpet_readl(HPET_COUNTER);
} while (read_seqretry(&xtime_lock, seq));
offset = (this_offset - last_offset);
@@ -373,7 +380,14 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
write_seqlock(&xtime_lock);
- if (vxtime.hpet_address) {
+ if (vxtime.hpet_address)
+ offset = hpet_readl(HPET_COUNTER);
+
+ if (hpet_use_timer) {
+ /* if we're using the hpet timer functionality,
+ * we can more accurately know the counter value
+ * when the timer interrupt occured.
+ */
offset = hpet_readl(HPET_T0_CMP) - hpet_tick;
delay = hpet_readl(HPET_COUNTER) - offset;
} else {
@@ -396,6 +410,10 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
(offset - vxtime.last)*(NSEC_PER_SEC/HZ) / hpet_tick;
vxtime.last = offset;
+#ifdef CONFIG_X86_PM_TIMER
+ } else if (vxtime.mode == VXTIME_PMTMR) {
+ lost = pmtimer_mark_offset();
+#endif
} else {
offset = (((tsc - vxtime.last_tsc) *
vxtime.tsc_quot) >> 32) - (USEC_PER_SEC / HZ);
@@ -795,17 +813,18 @@ static int hpet_timer_stop_set_go(unsigned long tick)
* Set up timer 0, as periodic with first interrupt to happen at hpet_tick,
* and period also hpet_tick.
*/
-
- hpet_writel(HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL |
+ if (hpet_use_timer) {
+ hpet_writel(HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL |
HPET_TN_32BIT, HPET_T0_CFG);
- hpet_writel(hpet_tick, HPET_T0_CMP);
- hpet_writel(hpet_tick, HPET_T0_CMP); /* AK: why twice? */
-
+ hpet_writel(hpet_tick, HPET_T0_CMP);
+ hpet_writel(hpet_tick, HPET_T0_CMP); /* AK: why twice? */
+ cfg |= HPET_CFG_LEGACY;
+ }
/*
* Go!
*/
- cfg |= HPET_CFG_ENABLE | HPET_CFG_LEGACY;
+ cfg |= HPET_CFG_ENABLE;
hpet_writel(cfg, HPET_CFG);
return 0;
@@ -826,8 +845,7 @@ static int hpet_init(void)
id = hpet_readl(HPET_ID);
- if (!(id & HPET_ID_VENDOR) || !(id & HPET_ID_NUMBER) ||
- !(id & HPET_ID_LEGSUP))
+ if (!(id & HPET_ID_VENDOR) || !(id & HPET_ID_NUMBER))
return -1;
hpet_period = hpet_readl(HPET_PERIOD);
@@ -837,6 +855,8 @@ static int hpet_init(void)
hpet_tick = (1000000000L * (USEC_PER_SEC / HZ) + hpet_period / 2) /
hpet_period;
+ hpet_use_timer = (id & HPET_ID_LEGSUP);
+
return hpet_timer_stop_set_go(hpet_tick);
}
@@ -893,11 +913,20 @@ void __init time_init(void)
set_normalized_timespec(&wall_to_monotonic,
-xtime.tv_sec, -xtime.tv_nsec);
- if (!hpet_init()) {
+ if (!hpet_init())
vxtime_hz = (1000000000000000L + hpet_period / 2) /
hpet_period;
+
+ if (hpet_use_timer) {
cpu_khz = hpet_calibrate_tsc();
timename = "HPET";
+#ifdef CONFIG_X86_PM_TIMER
+ } else if (pmtmr_ioport) {
+ vxtime_hz = PM_TIMER_FREQUENCY;
+ timename = "PM";
+ pit_init();
+ cpu_khz = pit_calibrate_tsc();
+#endif
} else {
pit_init();
cpu_khz = pit_calibrate_tsc();
@@ -923,37 +952,52 @@ void __init time_init(void)
}
/*
+ * Make an educated guess if the TSC is trustworthy and synchronized
+ * over all CPUs.
+ */
+static __init int unsynchronized_tsc(void)
+{
+#ifdef CONFIG_SMP
+ if (oem_force_hpet_timer())
+ return 1;
+ /* Intel systems are normally all synchronized. Exceptions
+ are handled in the OEM check above. */
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
+ return 0;
+ /* All in a single socket - should be synchronized */
+ if (cpus_weight(cpu_core_map[0]) == num_online_cpus())
+ return 0;
+#endif
+ /* Assume multi socket systems are not synchronized */
+ return num_online_cpus() > 1;
+}
+
+/*
* Decide after all CPUs are booted what mode gettimeofday should use.
*/
void __init time_init_gtod(void)
{
char *timetype;
- /*
- * AMD systems with more than one CPU don't have fully synchronized
- * TSCs. Always use HPET gettimeofday for these, although it is slower.
- * Intel SMP systems usually have synchronized TSCs, so use always
- * the TSC.
- *
- * Exceptions:
- * IBM Summit2 checked by oem_force_hpet_timer().
- * AMD dual core may also not need HPET. Check me.
- *
- * Can be turned off with "notsc".
- */
- if (num_online_cpus() > 1 &&
- boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
- notsc = 1;
- /* Some systems will want to disable TSC and use HPET. */
- if (oem_force_hpet_timer())
+ if (unsynchronized_tsc())
notsc = 1;
if (vxtime.hpet_address && notsc) {
- timetype = "HPET";
+ timetype = hpet_use_timer ? "HPET" : "PIT/HPET";
vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
vxtime.mode = VXTIME_HPET;
do_gettimeoffset = do_gettimeoffset_hpet;
+#ifdef CONFIG_X86_PM_TIMER
+ /* Using PM for gettimeofday is quite slow, but we have no other
+ choice because the TSC is too unreliable on some systems. */
+ } else if (pmtmr_ioport && !vxtime.hpet_address && notsc) {
+ timetype = "PM";
+ do_gettimeoffset = do_gettimeoffset_pm;
+ vxtime.mode = VXTIME_PMTMR;
+ sysctl_vsyscall = 0;
+ printk(KERN_INFO "Disabling vsyscall due to use of PM timer\n");
+#endif
} else {
- timetype = vxtime.hpet_address ? "HPET/TSC" : "PIT/TSC";
+ timetype = hpet_use_timer ? "HPET/TSC" : "PIT/TSC";
vxtime.mode = VXTIME_TSC;
}
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index 65a37f52c56..10273663000 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -274,7 +274,7 @@ EXPORT_SYMBOL(dump_stack);
void show_registers(struct pt_regs *regs)
{
int i;
- int in_kernel = (regs->cs & 3) == 0;
+ int in_kernel = !user_mode(regs);
unsigned long rsp;
const int cpu = safe_smp_processor_id();
struct task_struct *cur = cpu_pda[cpu].pcurrent;
@@ -318,7 +318,7 @@ void handle_BUG(struct pt_regs *regs)
struct bug_frame f;
char tmp;
- if (regs->cs & 3)
+ if (user_mode(regs))
return;
if (__copy_from_user(&f, (struct bug_frame *) regs->rip,
sizeof(struct bug_frame)))
@@ -332,10 +332,12 @@ void handle_BUG(struct pt_regs *regs)
printk(KERN_ALERT "Kernel BUG at %.50s:%d\n", f.filename, f.line);
}
+#ifdef CONFIG_BUG
void out_of_line_bug(void)
{
BUG();
}
+#endif
static DEFINE_SPINLOCK(die_lock);
static int die_owner = -1;
@@ -435,7 +437,7 @@ static void do_trap(int trapnr, int signr, char *str,
}
#endif
- if ((regs->cs & 3) != 0) {
+ if (user_mode(regs)) {
struct task_struct *tsk = current;
if (exception_trace && unhandled_signal(tsk, signr))
@@ -520,7 +522,7 @@ asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
}
#endif
- if ((regs->cs & 3)!=0) {
+ if (user_mode(regs)) {
struct task_struct *tsk = current;
if (exception_trace && unhandled_signal(tsk, SIGSEGV))
@@ -584,11 +586,17 @@ static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
asmlinkage void default_do_nmi(struct pt_regs *regs)
{
unsigned char reason = 0;
+ int cpu;
+
+ cpu = smp_processor_id();
/* Only the BSP gets external NMIs from the system. */
- if (!smp_processor_id())
+ if (!cpu)
reason = get_nmi_reason();
+ if (!cpu_online(cpu))
+ return;
+
if (!(reason & 0xc0)) {
if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT)
== NOTIFY_STOP)
@@ -636,7 +644,7 @@ asmlinkage struct pt_regs *sync_regs(struct pt_regs *eregs)
if (eregs == (struct pt_regs *)eregs->rsp)
;
/* Exception from user space */
- else if (eregs->cs & 3)
+ else if (user_mode(eregs))
regs = ((struct pt_regs *)current->thread.rsp0) - 1;
/* Exception from kernel and interrupts are enabled. Move to
kernel process stack. */
@@ -667,7 +675,7 @@ asmlinkage void do_debug(struct pt_regs * regs, unsigned long error_code)
}
#endif
- asm("movq %%db6,%0" : "=r" (condition));
+ get_debugreg(condition, 6);
if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
SIGTRAP) == NOTIFY_STOP)
@@ -695,7 +703,7 @@ asmlinkage void do_debug(struct pt_regs * regs, unsigned long error_code)
* allowing programs to debug themselves without the ptrace()
* interface.
*/
- if ((regs->cs & 3) == 0)
+ if (!user_mode(regs))
goto clear_TF_reenable;
/*
* Was the TF flag set by a debugger? If so, clear it now,
@@ -713,13 +721,13 @@ asmlinkage void do_debug(struct pt_regs * regs, unsigned long error_code)
info.si_signo = SIGTRAP;
info.si_errno = 0;
info.si_code = TRAP_BRKPT;
- if ((regs->cs & 3) == 0)
+ if (!user_mode(regs))
goto clear_dr7;
info.si_addr = (void __user *)regs->rip;
force_sig_info(SIGTRAP, &info, tsk);
clear_dr7:
- asm volatile("movq %0,%%db7"::"r"(0UL));
+ set_debugreg(0UL, 7);
return;
clear_TF_reenable:
@@ -754,7 +762,7 @@ asmlinkage void do_coprocessor_error(struct pt_regs *regs)
unsigned short cwd, swd;
conditional_sti(regs);
- if ((regs->cs & 3) == 0 &&
+ if (!user_mode(regs) &&
kernel_math_error(regs, "kernel x87 math error"))
return;
@@ -820,7 +828,7 @@ asmlinkage void do_simd_coprocessor_error(struct pt_regs *regs)
unsigned short mxcsr;
conditional_sti(regs);
- if ((regs->cs & 3) == 0 &&
+ if (!user_mode(regs) &&
kernel_math_error(regs, "kernel simd math error"))
return;
diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S
index 59ebd5beda8..73389f51c4e 100644
--- a/arch/x86_64/kernel/vmlinux.lds.S
+++ b/arch/x86_64/kernel/vmlinux.lds.S
@@ -2,7 +2,10 @@
* Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
*/
+#define LOAD_OFFSET __START_KERNEL_map
+
#include <asm-generic/vmlinux.lds.h>
+#include <asm/page.h>
#include <linux/config.h>
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
@@ -11,28 +14,30 @@ ENTRY(phys_startup_64)
jiffies_64 = jiffies;
SECTIONS
{
- . = 0xffffffff80100000;
+ . = __START_KERNEL;
phys_startup_64 = startup_64 - LOAD_OFFSET;
_text = .; /* Text and read-only data */
- .text : {
+ .text : AT(ADDR(.text) - LOAD_OFFSET) {
*(.text)
SCHED_TEXT
LOCK_TEXT
*(.fixup)
*(.gnu.warning)
} = 0x9090
- .text.lock : { *(.text.lock) } /* out-of-line lock text */
+ /* out-of-line lock text */
+ .text.lock : AT(ADDR(.text.lock) - LOAD_OFFSET) { *(.text.lock) }
_etext = .; /* End of text section */
. = ALIGN(16); /* Exception table */
__start___ex_table = .;
- __ex_table : { *(__ex_table) }
+ __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { *(__ex_table) }
__stop___ex_table = .;
RODATA
- .data : { /* Data */
+ /* Data */
+ .data : AT(ADDR(.data) - LOAD_OFFSET) {
*(.data)
CONSTRUCTORS
}
@@ -40,62 +45,95 @@ SECTIONS
_edata = .; /* End of data section */
__bss_start = .; /* BSS */
- .bss : {
+ .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
*(.bss.page_aligned)
*(.bss)
}
__bss_end = .;
+ . = ALIGN(PAGE_SIZE);
. = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
- .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+ .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
+ *(.data.cacheline_aligned)
+ }
+
+#define VSYSCALL_ADDR (-10*1024*1024)
+#define VSYSCALL_PHYS_ADDR ((LOADADDR(.data.cacheline_aligned) + SIZEOF(.data.cacheline_aligned) + 4095) & ~(4095))
+#define VSYSCALL_VIRT_ADDR ((ADDR(.data.cacheline_aligned) + SIZEOF(.data.cacheline_aligned) + 4095) & ~(4095))
+
+#define VLOAD_OFFSET (VSYSCALL_ADDR - VSYSCALL_PHYS_ADDR)
+#define VLOAD(x) (ADDR(x) - VLOAD_OFFSET)
+
+#define VVIRT_OFFSET (VSYSCALL_ADDR - VSYSCALL_VIRT_ADDR)
+#define VVIRT(x) (ADDR(x) - VVIRT_OFFSET)
-#define AFTER(x) BINALIGN(LOADADDR(x) + SIZEOF(x), 16)
-#define BINALIGN(x,y) (((x) + (y) - 1) & ~((y) - 1))
-#define CACHE_ALIGN(x) BINALIGN(x, CONFIG_X86_L1_CACHE_BYTES)
+ . = VSYSCALL_ADDR;
+ .vsyscall_0 : AT(VSYSCALL_PHYS_ADDR) { *(.vsyscall_0) }
+ __vsyscall_0 = VSYSCALL_VIRT_ADDR;
- .vsyscall_0 -10*1024*1024: AT ((LOADADDR(.data.cacheline_aligned) + SIZEOF(.data.cacheline_aligned) + 4095) & ~(4095)) { *(.vsyscall_0) }
- __vsyscall_0 = LOADADDR(.vsyscall_0);
. = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
- .xtime_lock : AT CACHE_ALIGN(AFTER(.vsyscall_0)) { *(.xtime_lock) }
- xtime_lock = LOADADDR(.xtime_lock);
- .vxtime : AT AFTER(.xtime_lock) { *(.vxtime) }
- vxtime = LOADADDR(.vxtime);
- .wall_jiffies : AT AFTER(.vxtime) { *(.wall_jiffies) }
- wall_jiffies = LOADADDR(.wall_jiffies);
- .sys_tz : AT AFTER(.wall_jiffies) { *(.sys_tz) }
- sys_tz = LOADADDR(.sys_tz);
- .sysctl_vsyscall : AT AFTER(.sys_tz) { *(.sysctl_vsyscall) }
- sysctl_vsyscall = LOADADDR(.sysctl_vsyscall);
- .xtime : AT AFTER(.sysctl_vsyscall) { *(.xtime) }
- xtime = LOADADDR(.xtime);
+ .xtime_lock : AT(VLOAD(.xtime_lock)) { *(.xtime_lock) }
+ xtime_lock = VVIRT(.xtime_lock);
+
+ .vxtime : AT(VLOAD(.vxtime)) { *(.vxtime) }
+ vxtime = VVIRT(.vxtime);
+
+ .wall_jiffies : AT(VLOAD(.wall_jiffies)) { *(.wall_jiffies) }
+ wall_jiffies = VVIRT(.wall_jiffies);
+
+ .sys_tz : AT(VLOAD(.sys_tz)) { *(.sys_tz) }
+ sys_tz = VVIRT(.sys_tz);
+
+ .sysctl_vsyscall : AT(VLOAD(.sysctl_vsyscall)) { *(.sysctl_vsyscall) }
+ sysctl_vsyscall = VVIRT(.sysctl_vsyscall);
+
+ .xtime : AT(VLOAD(.xtime)) { *(.xtime) }
+ xtime = VVIRT(.xtime);
+
. = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
- .jiffies : AT CACHE_ALIGN(AFTER(.xtime)) { *(.jiffies) }
- jiffies = LOADADDR(.jiffies);
- .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT (LOADADDR(.vsyscall_0) + 1024) { *(.vsyscall_1) }
- . = LOADADDR(.vsyscall_0) + 4096;
+ .jiffies : AT(VLOAD(.jiffies)) { *(.jiffies) }
+ jiffies = VVIRT(.jiffies);
+
+ .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT(VLOAD(.vsyscall_1)) { *(.vsyscall_1) }
+ .vsyscall_2 ADDR(.vsyscall_0) + 2048: AT(VLOAD(.vsyscall_2)) { *(.vsyscall_2) }
+ .vsyscall_3 ADDR(.vsyscall_0) + 3072: AT(VLOAD(.vsyscall_3)) { *(.vsyscall_3) }
+
+ . = VSYSCALL_VIRT_ADDR + 4096;
+
+#undef VSYSCALL_ADDR
+#undef VSYSCALL_PHYS_ADDR
+#undef VSYSCALL_VIRT_ADDR
+#undef VLOAD_OFFSET
+#undef VLOAD
+#undef VVIRT_OFFSET
+#undef VVIRT
. = ALIGN(8192); /* init_task */
- .data.init_task : { *(.data.init_task) }
+ .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
+ *(.data.init_task)
+ }
. = ALIGN(4096);
- .data.page_aligned : { *(.data.page_aligned) }
+ .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
+ *(.data.page_aligned)
+ }
. = ALIGN(4096); /* Init code and data */
__init_begin = .;
- .init.text : {
+ .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
_sinittext = .;
*(.init.text)
_einittext = .;
}
__initdata_begin = .;
- .init.data : { *(.init.data) }
+ .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { *(.init.data) }
__initdata_end = .;
. = ALIGN(16);
__setup_start = .;
- .init.setup : { *(.init.setup) }
+ .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) { *(.init.setup) }
__setup_end = .;
__initcall_start = .;
- .initcall.init : {
+ .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
*(.initcall1.init)
*(.initcall2.init)
*(.initcall3.init)
@@ -106,32 +144,38 @@ SECTIONS
}
__initcall_end = .;
__con_initcall_start = .;
- .con_initcall.init : { *(.con_initcall.init) }
+ .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) {
+ *(.con_initcall.init)
+ }
__con_initcall_end = .;
SECURITY_INIT
. = ALIGN(8);
__alt_instructions = .;
- .altinstructions : { *(.altinstructions) }
+ .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) {
+ *(.altinstructions)
+ }
__alt_instructions_end = .;
- .altinstr_replacement : { *(.altinstr_replacement) }
+ .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) {
+ *(.altinstr_replacement)
+ }
/* .exit.text is discard at runtime, not link time, to deal with references
from .altinstructions and .eh_frame */
- .exit.text : { *(.exit.text) }
- .exit.data : { *(.exit.data) }
+ .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { *(.exit.text) }
+ .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { *(.exit.data) }
. = ALIGN(4096);
__initramfs_start = .;
- .init.ramfs : { *(.init.ramfs) }
+ .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { *(.init.ramfs) }
__initramfs_end = .;
. = ALIGN(32);
__per_cpu_start = .;
- .data.percpu : { *(.data.percpu) }
+ .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { *(.data.percpu) }
__per_cpu_end = .;
. = ALIGN(4096);
__init_end = .;
. = ALIGN(4096);
__nosave_begin = .;
- .data_nosave : { *(.data.nosave) }
+ .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { *(.data.nosave) }
. = ALIGN(4096);
__nosave_end = .;
diff --git a/arch/x86_64/kernel/vsyscall.c b/arch/x86_64/kernel/vsyscall.c
index b4b8dc59663..2e573442594 100644
--- a/arch/x86_64/kernel/vsyscall.c
+++ b/arch/x86_64/kernel/vsyscall.c
@@ -65,7 +65,7 @@ static force_inline void do_vgettimeofday(struct timeval * tv)
usec = (__xtime.tv_nsec / 1000) +
(__jiffies - __wall_jiffies) * (1000000 / HZ);
- if (__vxtime.mode == VXTIME_TSC) {
+ if (__vxtime.mode != VXTIME_HPET) {
sync_core();
rdtscll(t);
if (t < __vxtime.last_tsc)
@@ -217,8 +217,9 @@ static int __init vsyscall_init(void)
BUG_ON((unsigned long) &vtime != VSYSCALL_ADDR(__NR_vtime));
BUG_ON((VSYSCALL_ADDR(0) != __fix_to_virt(VSYSCALL_FIRST_PAGE)));
map_vsyscall();
- sysctl_vsyscall = 1;
+#ifdef CONFIG_SYSCTL
register_sysctl_table(kernel_root_table2, 0);
+#endif
return 0;
}
diff --git a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c
index a43dedb58fa..68ec03070e5 100644
--- a/arch/x86_64/kernel/x8664_ksyms.c
+++ b/arch/x86_64/kernel/x8664_ksyms.c
@@ -193,8 +193,9 @@ EXPORT_SYMBOL(smp_num_siblings);
extern void do_softirq_thunk(void);
EXPORT_SYMBOL(do_softirq_thunk);
-void out_of_line_bug(void);
+#ifdef CONFIG_BUG
EXPORT_SYMBOL(out_of_line_bug);
+#endif
EXPORT_SYMBOL(init_level4_pgt);
diff --git a/arch/x86_64/lib/delay.c b/arch/x86_64/lib/delay.c
index 6e2d66472eb..33a873a3c22 100644
--- a/arch/x86_64/lib/delay.c
+++ b/arch/x86_64/lib/delay.c
@@ -12,6 +12,7 @@
#include <linux/sched.h>
#include <linux/delay.h>
#include <asm/delay.h>
+#include <asm/msr.h>
#ifdef CONFIG_SMP
#include <asm/smp.h>
@@ -19,6 +20,12 @@
int x86_udelay_tsc = 0; /* Delay via TSC */
+int read_current_timer(unsigned long *timer_value)
+{
+ rdtscll(*timer_value);
+ return 0;
+}
+
void __delay(unsigned long loops)
{
unsigned bclock, now;
@@ -34,7 +41,7 @@ void __delay(unsigned long loops)
inline void __const_udelay(unsigned long xloops)
{
- __delay(((xloops * cpu_data[_smp_processor_id()].loops_per_jiffy) >> 32) * HZ);
+ __delay(((xloops * cpu_data[raw_smp_processor_id()].loops_per_jiffy) >> 32) * HZ);
}
void __udelay(unsigned long usecs)
diff --git a/arch/x86_64/mm/Makefile b/arch/x86_64/mm/Makefile
index 66c354ad80c..1d232a87f11 100644
--- a/arch/x86_64/mm/Makefile
+++ b/arch/x86_64/mm/Makefile
@@ -4,7 +4,7 @@
obj-y := init.o fault.o ioremap.o extable.o pageattr.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
-obj-$(CONFIG_DISCONTIGMEM) += numa.o
+obj-$(CONFIG_NUMA) += numa.o
obj-$(CONFIG_K8_NUMA) += k8topology.o
obj-$(CONFIG_ACPI_NUMA) += srat.o
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c
index e0330921676..2f187986f94 100644
--- a/arch/x86_64/mm/fault.c
+++ b/arch/x86_64/mm/fault.c
@@ -74,7 +74,7 @@ static noinline int is_prefetch(struct pt_regs *regs, unsigned long addr,
instr = (unsigned char *)convert_rip_to_linear(current, regs);
max_instr = instr + 15;
- if ((regs->cs & 3) != 0 && instr >= (unsigned char *)TASK_SIZE)
+ if (user_mode(regs) && instr >= (unsigned char *)TASK_SIZE)
return 0;
while (scan_more && instr < max_instr) {
@@ -106,7 +106,7 @@ static noinline int is_prefetch(struct pt_regs *regs, unsigned long addr,
/* Could check the LDT for lm, but for now it's good
enough to assume that long mode only uses well known
segments or kernel. */
- scan_more = ((regs->cs & 3) == 0) || (regs->cs == __USER_CS);
+ scan_more = (!user_mode(regs)) || (regs->cs == __USER_CS);
break;
case 0x60:
@@ -234,6 +234,8 @@ static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs,
/*
* Handle a fault on the vmalloc or module mapping area
+ *
+ * This assumes no large pages in there.
*/
static int vmalloc_fault(unsigned long address)
{
@@ -272,7 +274,10 @@ static int vmalloc_fault(unsigned long address)
if (!pte_present(*pte_ref))
return -1;
pte = pte_offset_kernel(pmd, address);
- if (!pte_present(*pte) || pte_page(*pte) != pte_page(*pte_ref))
+ /* Don't use pte_page here, because the mappings can point
+ outside mem_map, and the NUMA hash lookup cannot handle
+ that. */
+ if (!pte_present(*pte) || pte_pfn(*pte) != pte_pfn(*pte_ref))
BUG();
__flush_tlb_all();
return 0;
@@ -345,8 +350,10 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
* (error_code & 4) == 0, and that the fault was not a
* protection error (error_code & 1) == 0.
*/
- if (unlikely(address >= TASK_SIZE)) {
- if (!(error_code & 5)) {
+ if (unlikely(address >= TASK_SIZE64)) {
+ if (!(error_code & 5) &&
+ ((address >= VMALLOC_START && address < VMALLOC_END) ||
+ (address >= MODULES_VADDR && address < MODULES_END))) {
if (vmalloc_fault(address) < 0)
goto bad_area_nosemaphore;
return;
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
index dbe53b4c7e6..72e4b364ed7 100644
--- a/arch/x86_64/mm/init.c
+++ b/arch/x86_64/mm/init.c
@@ -318,7 +318,7 @@ void zap_low_mappings(void)
flush_tlb_all();
}
-#ifndef CONFIG_DISCONTIGMEM
+#ifndef CONFIG_NUMA
void __init paging_init(void)
{
{
@@ -427,13 +427,16 @@ void __init mem_init(void)
reservedpages = 0;
/* this will put all low memory onto the freelists */
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NUMA
totalram_pages += numa_free_all_bootmem();
tmp = 0;
/* should count reserved pages here for all nodes */
#else
+
+#ifdef CONFIG_FLATMEM
max_mapnr = end_pfn;
if (!mem_map) BUG();
+#endif
totalram_pages += free_all_bootmem();
@@ -515,7 +518,7 @@ void free_initrd_mem(unsigned long start, unsigned long end)
void __init reserve_bootmem_generic(unsigned long phys, unsigned len)
{
/* Should check here against the e820 map to avoid double free */
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NUMA
int nid = phys_to_nid(phys);
reserve_bootmem_node(NODE_DATA(nid), phys, len);
#else
diff --git a/arch/x86_64/mm/ioremap.c b/arch/x86_64/mm/ioremap.c
index 74ec8554b19..6972df480d2 100644
--- a/arch/x86_64/mm/ioremap.c
+++ b/arch/x86_64/mm/ioremap.c
@@ -133,7 +133,7 @@ ioremap_change_attr(unsigned long phys_addr, unsigned long size,
unsigned long flags)
{
int err = 0;
- if (flags && phys_addr + size - 1 < (end_pfn_map << PAGE_SHIFT)) {
+ if (phys_addr + size - 1 < (end_pfn_map << PAGE_SHIFT)) {
unsigned long npages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
unsigned long vaddr = (unsigned long) __va(phys_addr);
@@ -178,7 +178,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
if (phys_addr >= ISA_START_ADDRESS && last_addr < ISA_END_ADDRESS)
return (__force void __iomem *)phys_to_virt(phys_addr);
-#ifndef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_FLATMEM
/*
* Don't allow anybody to remap normal RAM that we're using..
*/
@@ -214,7 +214,7 @@ void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned l
remove_vm_area((void *)(PAGE_MASK & (unsigned long) addr));
return NULL;
}
- if (ioremap_change_attr(phys_addr, size, flags) < 0) {
+ if (flags && ioremap_change_attr(phys_addr, size, flags) < 0) {
area->flags &= 0xffffff;
vunmap(addr);
return NULL;
@@ -251,7 +251,7 @@ void __iomem *ioremap_nocache (unsigned long phys_addr, unsigned long size)
void iounmap(volatile void __iomem *addr)
{
- struct vm_struct *p, **pprev;
+ struct vm_struct *p;
if (addr <= high_memory)
return;
@@ -260,24 +260,11 @@ void iounmap(volatile void __iomem *addr)
return;
write_lock(&vmlist_lock);
- for (p = vmlist, pprev = &vmlist; p != NULL; pprev = &p->next, p = *pprev)
- if (p->addr == (void *)(PAGE_MASK & (unsigned long)addr))
- break;
- if (!p) {
- printk("__iounmap: bad address %p\n", addr);
- goto out_unlock;
- }
- *pprev = p->next;
- unmap_vm_area(p);
- if ((p->flags >> 20) &&
- p->phys_addr + p->size - 1 < virt_to_phys(high_memory)) {
- /* p->size includes the guard page, but cpa doesn't like that */
- change_page_attr(virt_to_page(__va(p->phys_addr)),
- p->size >> PAGE_SHIFT,
- PAGE_KERNEL);
- global_flush_tlb();
- }
-out_unlock:
+ p = __remove_vm_area((void *)((unsigned long)addr & PAGE_MASK));
+ if (!p)
+ printk("iounmap: bad address %p\n", addr);
+ else if (p->flags >> 20)
+ ioremap_change_attr(p->phys_addr, p->size, 0);
write_unlock(&vmlist_lock);
kfree(p);
}
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c
index fd9f25d7a6c..ac61c186eb0 100644
--- a/arch/x86_64/mm/numa.c
+++ b/arch/x86_64/mm/numa.c
@@ -66,6 +66,13 @@ int __init compute_hash_shift(struct node *nodes, int numnodes)
return -1;
}
+#ifdef CONFIG_SPARSEMEM
+int early_pfn_to_nid(unsigned long pfn)
+{
+ return phys_to_nid(pfn << PAGE_SHIFT);
+}
+#endif
+
/* Initialize bootmem allocator for a node */
void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
{
@@ -80,6 +87,7 @@ void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long en
start_pfn = start >> PAGE_SHIFT;
end_pfn = end >> PAGE_SHIFT;
+ memory_present(nodeid, start_pfn, end_pfn);
nodedata_phys = find_e820_area(start, end, pgdat_size);
if (nodedata_phys == -1L)
panic("Cannot find memory pgdat in node %d\n", nodeid);
@@ -243,7 +251,7 @@ void __init numa_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
setup_node_bootmem(0, start_pfn << PAGE_SHIFT, end_pfn << PAGE_SHIFT);
}
-__init void numa_add_cpu(int cpu)
+__cpuinit void numa_add_cpu(int cpu)
{
/* BP is initialized elsewhere */
if (cpu)
diff --git a/arch/x86_64/pci/k8-bus.c b/arch/x86_64/pci/k8-bus.c
index 62349c78db5..7e7d0c2a002 100644
--- a/arch/x86_64/pci/k8-bus.c
+++ b/arch/x86_64/pci/k8-bus.c
@@ -53,25 +53,11 @@ fill_mp_bus_to_cpumask(void)
for (j = SECONDARY_LDT_BUS_NUMBER(ldtbus);
j <= SUBORDINATE_LDT_BUS_NUMBER(ldtbus);
j++)
- pci_bus_to_cpumask[j] =
- node_to_cpumask(NODE_ID(nid));
+ pci_bus_to_node[j] = NODE_ID(nid);
}
}
}
- /* quick sanity check */
- printed = 0;
- for (i = 0; i < 256; i++) {
- if (cpus_empty(pci_bus_to_cpumask[i])) {
- pci_bus_to_cpumask[i] = CPU_MASK_ALL;
- if (printed)
- continue;
- printk(KERN_ERR
- "k8-bus.c: some busses have empty cpu mask\n");
- printed = 1;
- }
- }
-
return 0;
}
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
new file mode 100644
index 00000000000..3e89767cea7
--- /dev/null
+++ b/arch/xtensa/Kconfig
@@ -0,0 +1,258 @@
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/config-language.txt.
+
+mainmenu "Linux/Xtensa Kernel Configuration"
+
+config FRAME_POINTER
+ bool
+ default n
+
+config XTENSA
+ bool
+ default y
+ help
+ Xtensa processors are 32-bit RISC machines designed by Tensilica
+ primarily for embedded systems. These processors are both
+ configurable and extensible. The Linux port to the Xtensa
+ architecture supports all processor configurations and extensions,
+ with reasonable minimum requirements. The Xtensa Linux project has
+ a home page at <http://xtensa.sourceforge.net/>.
+
+config UID16
+ bool
+ default n
+
+config RWSEM_XCHGADD_ALGORITHM
+ bool
+ default y
+
+config HAVE_DEC_LOCK
+ bool
+ default y
+
+config GENERIC_HARDIRQS
+ bool
+ default y
+
+source "init/Kconfig"
+
+menu "Processor type and features"
+
+choice
+ prompt "Xtensa Processor Configuration"
+ default XTENSA_CPU_LINUX_BE
+
+config XTENSA_CPU_LINUX_BE
+ bool "linux_be"
+ ---help---
+ The linux_be processor configuration is the baseline Xtensa
+ configurations included in this kernel and also used by
+ binutils, gcc, and gdb. It contains no TIE, no coprocessors,
+ and the following configuration options:
+
+ Code Density Option 2 Misc Special Registers
+ NSA/NSAU Instructions 128-bit Data Bus Width
+ Processor ID 8K, 2-way I and D Caches
+ Zero-Overhead Loops 2 Inst Address Break Registers
+ Big Endian 2 Data Address Break Registers
+ 64 General-Purpose Registers JTAG Interface and Trace Port
+ 17 Interrupts MMU w/ TLBs and Autorefill
+ 3 Interrupt Levels 8 Autorefill Ways (I/D TLBs)
+ 3 Timers Unaligned Exceptions
+endchoice
+
+config MMU
+ bool
+ default y
+
+config XTENSA_UNALIGNED_USER
+ bool "Unaligned memory access in use space"
+ ---help---
+ The Xtensa architecture currently does not handle unaligned
+ memory accesses in hardware but through an exception handler.
+ Per default, unaligned memory accesses are disabled in user space.
+
+ Say Y here to enable unaligned memory access in user space.
+
+config PREEMPT
+ bool "Preemptible Kernel"
+ ---help---
+ This option reduces the latency of the kernel when reacting to
+ real-time or interactive events by allowing a low priority process to
+ be preempted even if it is in kernel mode executing a system call.
+ Unfortunately the kernel code has some race conditions if both
+ CONFIG_SMP and CONFIG_PREEMPT are enabled, so this option is
+ currently disabled if you are building an SMP kernel.
+
+ Say Y here if you are building a kernel for a desktop, embedded
+ or real-time system. Say N if you are unsure.
+
+config MATH_EMULATION
+ bool "Math emulation"
+ help
+ Can we use information of configuration file?
+
+config HIGHMEM
+ bool "High memory support"
+
+endmenu
+
+menu "Platform options"
+
+choice
+ prompt "Xtensa System Type"
+ default XTENSA_PLATFORM_ISS
+
+config XTENSA_PLATFORM_ISS
+ bool "ISS"
+ help
+ ISS is an acronym for Tensilica's Instruction Set Simulator.
+
+config XTENSA_PLATFORM_XT2000
+ bool "XT2000"
+ help
+ XT2000 is the name of Tensilica's feature-rich emulation platform.
+ This hardware is capable of running a full Linux distribution.
+
+endchoice
+
+
+config XTENSA_CALIBRATE_CCOUNT
+ bool "Auto calibration of the CPU clock rate"
+ ---help---
+ On some platforms (XT2000, for example), the CPU clock rate can
+ vary. The frequency can be determined, however, by measuring
+ against a well known, fixed frequency, such as an UART oscillator.
+
+config XTENSA_CPU_CLOCK
+ int "CPU clock rate [MHz]"
+ depends on !XTENSA_CALIBRATE_CCOUNT
+ default "16"
+
+config GENERIC_CALIBRATE_DELAY
+ bool "Auto calibration of the BogoMIPS value"
+ ---help---
+ The BogoMIPS value can easily derived from the CPU frequency.
+
+config CMDLINE_BOOL
+ bool "Default bootloader kernel arguments"
+
+config CMDLINE
+ string "Initial kernel command string"
+ depends on CMDLINE_BOOL
+ default "console=ttyS0,38400 root=/dev/ram"
+ help
+ On some architectures (EBSA110 and CATS), there is currently no way
+ for the boot loader to pass arguments to the kernel. For these
+ architectures, you should supply some command-line options at build
+ time by entering them here. As a minimum, you should specify the
+ memory size and the root device (e.g., mem=64M root=/dev/nfs).
+
+config SERIAL_CONSOLE
+ bool
+ depends on XTENSA_PLATFORM_ISS
+ default y
+
+config XTENSA_ISS_NETWORK
+ bool
+ depends on XTENSA_PLATFORM_ISS
+ default y
+
+endmenu
+
+menu "Bus options"
+
+config PCI
+ bool "PCI support" if !XTENSA_PLATFORM_ISS
+ depends on !XTENSA_PLATFORM_ISS
+ default y
+ help
+ Find out whether you have a PCI motherboard. PCI is the name of a
+ bus system, i.e. the way the CPU talks to the other stuff inside
+ your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
+ VESA. If you have PCI, say Y, otherwise N.
+
+ The PCI-HOWTO, available from
+ <http://www.linuxdoc.org/docs.html#howto>, contains valuable
+ information about which PCI hardware does work under Linux and which
+ doesn't
+
+source "drivers/pci/Kconfig"
+
+config HOTPLUG
+
+ bool "Support for hot-pluggable devices"
+ ---help---
+ Say Y here if you want to plug devices into your computer while
+ the system is running, and be able to use them quickly. In many
+ cases, the devices can likewise be unplugged at any time too.
+
+ One well known example of this is PCMCIA- or PC-cards, credit-card
+ size devices such as network cards, modems or hard drives which are
+ plugged into slots found on all modern laptop computers. Another
+ example, used on modern desktops as well as laptops, is USB.
+
+ Enable HOTPLUG and KMOD, and build a modular kernel. Get agent
+ software (at <http://linux-hotplug.sourceforge.net/>) and install it.
+ Then your kernel will automatically call out to a user mode "policy
+ agent" (/sbin/hotplug) to load modules and set up software needed
+ to use devices as you hotplug them.
+
+source "drivers/pcmcia/Kconfig"
+
+source "drivers/pci/hotplug/Kconfig"
+
+endmenu
+
+menu "Exectuable file formats"
+
+# only elf supported
+config KCORE_ELF
+ bool
+ depends on PROC_FS
+ default y
+ help
+ If you enabled support for /proc file system then the file
+ /proc/kcore will contain the kernel core image in ELF format. This
+ can be used in gdb:
+
+ $ cd /usr/src/linux ; gdb vmlinux /proc/kcore
+
+ This is especially useful if you have compiled the kernel with the
+ "-g" option to preserve debugging information. It is mainly used
+ for examining kernel data structures on the live kernel.
+
+source "fs/Kconfig.binfmt"
+
+endmenu
+
+source "drivers/Kconfig"
+
+source "fs/Kconfig"
+
+menu "Xtensa initrd options"
+ depends on BLK_DEV_INITRD
+
+ config EMBEDDED_RAMDISK
+ bool "Embed root filesystem ramdisk into the kernel"
+
+config EMBEDDED_RAMDISK_IMAGE
+ string "Filename of gziped ramdisk image"
+ depends on EMBEDDED_RAMDISK
+ default "ramdisk.gz"
+ help
+ This is the filename of the ramdisk image to be built into the
+ kernel. Relative pathnames are relative to arch/xtensa/boot/ramdisk/.
+ The ramdisk image is not part of the kernel distribution; you must
+ provide one yourself.
+endmenu
+
+source "arch/xtensa/Kconfig.debug"
+
+source "security/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
+
+
diff --git a/arch/xtensa/Kconfig.debug b/arch/xtensa/Kconfig.debug
new file mode 100644
index 00000000000..11c585295dd
--- /dev/null
+++ b/arch/xtensa/Kconfig.debug
@@ -0,0 +1,7 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+endmenu
+
+
diff --git a/arch/xtensa/Makefile b/arch/xtensa/Makefile
new file mode 100644
index 00000000000..4fa27453b1f
--- /dev/null
+++ b/arch/xtensa/Makefile
@@ -0,0 +1,102 @@
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License. See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 2001 - 2005 Tensilica Inc.
+#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies. Remember to do have actions
+# for "archclean" and "archdep" for cleaning up and making dependencies for
+# this architecture
+
+# Core configuration.
+# (Use CPU=<xtensa_config> to use another default compiler.)
+
+cpu-$(CONFIG_XTENSA_CPU_LINUX_BE) := linux_be
+cpu-$(CONFIG_XTENSA_CPU_LINUX_CUSTOM) := linux_custom
+
+CPU = $(cpu-y)
+export CPU
+
+# Platform configuration
+
+platform-y := common
+platform-$(CONFIG_XTENSA_PLATFORM_XT2000) := xt2000
+platform-$(CONFIG_XTENSA_PLATFORM_ISS) := iss
+
+PLATFORM = $(platform-y)
+export PLATFORM
+
+#LDFLAGS_vmlinux := -T$(word 1,$(LINKSCRIPT))
+AFLAGS_vmlinux.lds.o := -Uxtensa
+CPPFLAGS += -Iarch/xtensa -Iinclude/asm -mlongcalls -g
+AFLAGS += -Iarch/xtensa -Iinclude/asm
+CPP = $(CC) -E $(CFLAGS)
+
+cflags-y += -Iarch/xtensa -pipe -mlongcalls
+
+
+KBUILD_DEFCONFIG := common_defconfig
+
+# ramdisk/initrd support
+# You need a compressed ramdisk image, named ramdisk.gz in
+# arch/xtensa/boot/ramdisk
+
+core-$(CONFIG_EMBEDDED_RAMDISK) += arch/xtensa/boot/ramdisk/
+
+# Test for cross compiling
+
+ifneq ($(CPU),)
+ COMPILE_ARCH = $(shell uname -m)
+
+ ifneq ($(COMPILE_ARCH), xtensa)
+ ifndef CROSS_COMPILE
+ CROSS_COMPILE = xtensa_$(CPU)-
+ endif
+ endif
+endif
+
+#
+
+LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
+
+head-y := arch/xtensa/kernel/head.o
+core-y += arch/xtensa/kernel/ \
+ arch/xtensa/mm/ arch/xtensa/platform-$(PLATFORM)/
+libs-y += arch/xtensa/lib/ $(LIBGCC)
+
+boot := arch/xtensa/boot
+
+arch/xtensa/kernel/asm-offsets.s: \
+ arch/xtensa/kernel/asm-offsets.c \
+ include/asm-xtensa/.platform
+
+include/asm-xtensa/offsets.h: arch/xtensa/kernel/asm-offsets.s
+ $(call filechk,gen-asm-offsets)
+
+prepare: include/asm-xtensa/.platform include/asm-xtensa/offsets.h
+
+# Update machine cpu and platform symlinks if something which affects
+# them changed.
+
+include/asm-xtensa/.platform: $(wildcard include/config/arch/*.h)
+ @echo ' Setting up cpu ($(CPU)) and platform ($(PLATFORM)) symlinks'
+ $(Q)rm -f include/asm-xtensa/platform
+ $(Q)rm -f include/asm-xtensa/xtensa/config
+ $(Q)(cd include/asm-xtensa/; ln -sf platform-$(PLATFORM) platform)
+ $(Q)(cd include/asm-xtensa/xtensa; ln -sf config-$(CPU) config)
+
+all: zImage
+
+bzImage : zImage
+
+zImage zImage.initrd: vmlinux
+ $(Q)$(MAKE) $(build)=$(boot) $@
+
+CLEAN_FILES += arch/xtensa/vmlinux.lds include/asm-xtensa/offset.h
+
+define archhelp
+ @echo '* zImage - Compressed kernel image (arch/xtensa/boot/images/zImage.*)'
+endef
+
diff --git a/arch/xtensa/boot/Makefile b/arch/xtensa/boot/Makefile
new file mode 100644
index 00000000000..260f456ccf0
--- /dev/null
+++ b/arch/xtensa/boot/Makefile
@@ -0,0 +1,37 @@
+#
+# arch/xtensa/boot/Makefile
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License. See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+#
+
+
+CFLAGS += -fno-builtin -Iarch/$(ARCH)/boot/include
+HOSTFLAGS += -Iarch/$(ARCH)/boot/include
+
+BIG_ENDIAN := $(shell echo -e "\#ifdef __XTENSA_EL__\nint little;\n\#else\nint big;\n\#endif" | $(CC) -E -|grep -c big)
+
+
+export CFLAGS
+export AFLAGS
+export BIG_ENDIAN
+
+# Subdirs for the boot loader(s)
+
+bootdir-$(CONFIG_XTENSA_PLATFORM_ISS) += boot-elf
+bootdir-$(CONFIG_XTENSA_PLATFORM_XT2000) += boot-redboot boot-elf
+
+subdir-y := lib/
+
+subdir-y += boot-elf/ boot-redboot/
+
+zImage zImage.initrd Image Image.initrd: $(bootdir-y)
+
+$(bootdir-y): $(addprefix $(obj)/,$(subdir-y)) \
+ $(addprefix $(obj)/,$(host-progs))
+ $(Q)$(MAKE) $(build)=$(obj)/$@ $(MAKECMDGOALS)
+
+
+
diff --git a/arch/xtensa/boot/boot-elf/Makefile b/arch/xtensa/boot/boot-elf/Makefile
new file mode 100644
index 00000000000..f6ef6a36966
--- /dev/null
+++ b/arch/xtensa/boot/boot-elf/Makefile
@@ -0,0 +1,52 @@
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License. See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+
+GZIP = gzip
+GZIP_FLAGS = -v9fc
+
+ifeq ($(BIG_ENDIAN),1)
+OBJCOPY_ARGS := -O elf32-xtensa-be
+else
+OBJCOPY_ARGS := -O elf32-xtensa-le
+endif
+
+export OBJCOPY_ARGS
+
+boot-y := bootstrap.o
+
+OBJS := $(addprefix $(obj)/,$(boot-y))
+
+Image: vmlinux $(OBJS)
+ $(OBJCOPY) --strip-all -R .comment -R .xt.insn -O binary \
+ vmlinux vmlinux.tmp
+ $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
+ --add-section image=vmlinux.tmp \
+ --set-section-flags image=contents,alloc,load,load,data \
+ $(OBJS) $@.tmp
+ $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) \
+ -T arch/$(ARCH)/boot/boot-elf/boot.ld \
+ -o arch/$(ARCH)/boot/$@.elf $@.tmp
+ rm -f $@.tmp vmlinux.tmp
+
+Image.initrd: vmlinux $(OBJS)
+ $(OBJCOPY) --strip-all -R .comment -R .xt.insn -O binary \
+ --add-section .initrd=arch/$(ARCH)/boot/ramdisk \
+ --set-section-flags .initrd=contents,alloc,load,load,data \
+ vmlinux vmlinux.tmp
+ $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
+ --add-section image=vmlinux.tmp \
+ --set-section-flags image=contents,alloc,load,load,data \
+ $(OBJS) $@.tmp
+ $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) \
+ -T arch/$(ARCH)/boot/boot-elf/boot.ld \
+ -o arch/$(ARCH)/boot/$@.elf $@.tmp
+ rm -f $@.tmp vmlinux.tmp
+
+
+zImage: Image
+
+zImage.initrd: Image.initrd
+
diff --git a/arch/xtensa/boot/boot-elf/boot.ld b/arch/xtensa/boot/boot-elf/boot.ld
new file mode 100644
index 00000000000..4ab06a0a7a6
--- /dev/null
+++ b/arch/xtensa/boot/boot-elf/boot.ld
@@ -0,0 +1,71 @@
+OUTPUT_ARCH(xtensa)
+
+SECTIONS
+{
+ .start 0xD0000000 : { *(.start) }
+
+ .text 0xD0000000:
+ {
+ __reloc_start = . ;
+ _text_start = . ;
+ *(.literal .text.literal .text)
+ _text_end = . ;
+ }
+
+ .rodata ALIGN(0x04):
+ {
+ *(.rodata)
+ *(.rodata1)
+ }
+
+ .data ALIGN(0x04):
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.got.plt)
+ *(.got)
+ *(.dynamic)
+ }
+
+ __reloc_end = . ;
+
+ .initrd ALIGN(0x10) :
+ {
+ boot_initrd_start = . ;
+ *(.initrd)
+ boot_initrd_end = .;
+ }
+
+ . = ALIGN(0x10);
+ __image_load = . ;
+ .image 0xd0001000:
+ {
+ _image_start = .;
+ *(image)
+ . = (. + 3) & ~ 3;
+ _image_end = . ;
+ }
+
+
+ .bss ((LOADADDR(.image) + SIZEOF(.image) + 3) & ~ 3):
+ {
+ __bss_start = .;
+ *(.sbss)
+ *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ __bss_end = .;
+ }
+ _end = .;
+ _param_start = .;
+
+ .ResetVector.text 0xfe000020 :
+ {
+ *(.ResetVector.text)
+ }
+
+
+ PROVIDE (end = .);
+}
diff --git a/arch/xtensa/boot/boot-elf/bootstrap.S b/arch/xtensa/boot/boot-elf/bootstrap.S
new file mode 100644
index 00000000000..7cba94abdab
--- /dev/null
+++ b/arch/xtensa/boot/boot-elf/bootstrap.S
@@ -0,0 +1,37 @@
+
+#include <xtensa/config/specreg.h>
+#include <xtensa/config/core.h>
+
+#include <linux/config.h>
+#include <asm/bootparam.h>
+
+
+/* ResetVector
+ */
+ .section .ResetVector.text, "ax"
+ .global _ResetVector
+_ResetVector:
+ _j reset
+ .align 4
+RomInitAddr:
+ .word 0xd0001000
+RomBootParam:
+ .word _bootparam
+reset:
+ l32r a0, RomInitAddr
+ l32r a2, RomBootParam
+ movi a3, 0
+ movi a4, 0
+ jx a0
+
+ .align 4
+ .section .bootstrap.data, "aw"
+
+ .globl _bootparam
+_bootparam:
+ .short BP_TAG_FIRST
+ .short 4
+ .long BP_VERSION
+ .short BP_TAG_LAST
+ .short 0
+ .long 0
diff --git a/arch/xtensa/boot/boot-redboot/Makefile b/arch/xtensa/boot/boot-redboot/Makefile
new file mode 100644
index 00000000000..ca8a68bc847
--- /dev/null
+++ b/arch/xtensa/boot/boot-redboot/Makefile
@@ -0,0 +1,35 @@
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License. See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+
+GZIP = gzip
+GZIP_FLAGS = -v9fc
+ifeq ($(BIG_ENDIAN),1)
+OBJCOPY_ARGS := -O elf32-xtensa-be
+else
+OBJCOPY_ARGS := -O elf32-xtensa-le
+endif
+
+LD_ARGS = -T $(obj)/boot.ld
+
+boot-y := bootstrap.o
+
+OBJS := $(addprefix $(obj)/,$(boot-y))
+LIBS := arch/$(ARCH)/boot/lib/lib.a arch/$(ARCH)/lib/lib.a
+
+LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
+
+zImage: vmlinux $(OBJS) $(LIBS)
+ $(OBJCOPY) --strip-all -R .comment -R .xt.insn -O binary \
+ $(TOPDIR)/vmlinux vmlinux.tmp
+ gzip -vf9 vmlinux.tmp
+ $(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
+ --add-section image=vmlinux.tmp.gz \
+ --set-section-flags image=contents,alloc,load,load,data \
+ $(OBJS) $@.tmp
+ $(LD) $(LD_ARGS) -o $@.elf $@.tmp $(LIBS) -L/xtensa-elf/lib $(LIBGCC)
+ $(OBJCOPY) -S -O binary $@.elf arch/$(ARCH)/boot/images/$@.redboot
+# rm -f $@.tmp $@.elf vmlinux.tmp.gz
+
diff --git a/arch/xtensa/boot/boot-redboot/boot.ld b/arch/xtensa/boot/boot-redboot/boot.ld
new file mode 100644
index 00000000000..65b726410e8
--- /dev/null
+++ b/arch/xtensa/boot/boot-redboot/boot.ld
@@ -0,0 +1,66 @@
+OUTPUT_ARCH(xtensa)
+
+SECTIONS
+{
+ .start 0xD0200000 : { *(.start) }
+
+ .text :
+ {
+ __reloc_start = . ;
+ _text_start = . ;
+ *(.literal .text.literal .text)
+ _text_end = . ;
+ }
+
+ .rodata ALIGN(0x04):
+ {
+ *(.rodata)
+ *(.rodata1)
+ }
+
+ .data ALIGN(0x04):
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.got.plt)
+ *(.got)
+ *(.dynamic)
+ }
+
+ __reloc_end = . ;
+
+ .initrd ALIGN(0x10) :
+ {
+ boot_initrd_start = . ;
+ *(.initrd)
+ boot_initrd_end = .;
+ }
+
+ . = ALIGN(0x10);
+ __image_load = . ;
+ .image 0xd0001000: AT(__image_load)
+ {
+ _image_start = .;
+ *(image)
+ . = (. + 3) & ~ 3;
+ _image_end = . ;
+ }
+
+
+ .bss ((LOADADDR(.image) + SIZEOF(.image) + 3) & ~ 3):
+ {
+ __bss_start = .;
+ *(.sbss)
+ *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ __bss_end = .;
+ }
+ _end = .;
+ _param_start = .;
+
+
+ PROVIDE (end = .);
+}
diff --git a/arch/xtensa/boot/boot-redboot/bootstrap.S b/arch/xtensa/boot/boot-redboot/bootstrap.S
new file mode 100644
index 00000000000..ee636b0da81
--- /dev/null
+++ b/arch/xtensa/boot/boot-redboot/bootstrap.S
@@ -0,0 +1,246 @@
+
+#define _ASMLANGUAGE
+#include <xtensa/config/specreg.h>
+#include <xtensa/config/core.h>
+#include <xtensa/cacheasm.h>
+
+ /*
+ * RB-Data: RedBoot data/bss
+ * P: Boot-Parameters
+ * L: Kernel-Loader
+ *
+ * The Linux-Kernel image including the loader must be loaded
+ * to a position so that the kernel and the boot parameters
+ * can fit in the space before the load address.
+ * ______________________________________________________
+ * |_RB-Data_|_P_|__________|_L_|___Linux-Kernel___|______|
+ * ^
+ * ^ Load address
+ * ______________________________________________________
+ * |___Linux-Kernel___|_P_|_L_|___________________________|
+ *
+ * The loader copies the parameter to the position that will
+ * be the end of the kernel and itself to the end of the
+ * parameter list.
+ */
+
+/* Make sure we have enough space for the 'uncompressor' */
+
+#define STACK_SIZE 32768
+#define HEAP_SIZE (131072*4)
+
+ # a2: Parameter list
+ # a3: Size of parameter list
+
+ .section .start, "ax"
+
+ .globl __start
+ /* this must be the first byte of the loader! */
+__start:
+ entry sp, 32 # we do not intend to return
+ _call0 _start
+__start_a0:
+ .align 4
+
+ .section .text, "ax"
+ .begin literal_prefix .text
+
+ /* put literals in here! */
+
+ .globl _start
+_start:
+
+ /* 'reset' window registers */
+
+ movi a4, 1
+ wsr a4, PS
+ rsync
+
+ rsr a5, WINDOWBASE
+ ssl a5
+ sll a4, a4
+ wsr a4, WINDOWSTART
+ rsync
+
+ movi a4, 0x00040000
+ wsr a4, PS
+ rsync
+
+ /* copy the loader to its address
+ * Note: The loader itself is a very small piece, so we assume we
+ * don't partially overlap. We also assume (even more important)
+ * that the kernel image is out of the way. Usually, when the
+ * load address of this image is not at an arbitrary address,
+ * but aligned to some 10K's we shouldn't overlap.
+ */
+
+ /* Note: The assembler cannot relax "addi a0, a0, ..." to an
+ l32r, so we load to a4 first. */
+
+ addi a4, a0, __start - __start_a0
+ mov a0, a4
+ movi a4, __start
+ movi a5, __reloc_end
+
+ # a0: address where this code has been loaded
+ # a4: compiled address of __start
+ # a5: compiled end address
+
+ mov.n a7, a0
+ mov.n a8, a4
+
+1:
+ l32i a10, a7, 0
+ l32i a11, a7, 4
+ s32i a10, a8, 0
+ s32i a11, a8, 4
+ l32i a10, a7, 8
+ l32i a11, a7, 12
+ s32i a10, a8, 8
+ s32i a11, a8, 12
+ addi a8, a8, 16
+ addi a7, a7, 16
+ blt a8, a5, 1b
+
+
+ /* We have to flush and invalidate the caches here before we jump. */
+
+#if XCHAL_DCACHE_IS_WRITEBACK
+ dcache_writeback_all a5, a6
+#endif
+ icache_invalidate_all a5, a6
+
+ movi a11, _reloc
+ jx a11
+
+ .globl _reloc
+_reloc:
+
+ /* RedBoot is now at the end of the memory, so we don't have
+ * to copy the parameter list. Keep the code around; in case
+ * we need it again. */
+#if 0
+ # a0: load address
+ # a2: start address of parameter list
+ # a3: length of parameter list
+ # a4: __start
+
+ /* copy the parameter list out of the way */
+
+ movi a6, _param_start
+ add a3, a2, a3
+2:
+ l32i a8, a2, 0
+ s32i a8, a6, 0
+ addi a2, a2, 4
+ addi a6, a6, 4
+ blt a2, a3, 2b
+#endif
+
+ /* clear BSS section */
+ movi a6, __bss_start
+ movi a7, __bss_end
+ movi.n a5, 0
+3:
+ s32i a5, a6, 0
+ addi a6, a6, 4
+ blt a6, a7, 3b
+
+ movi a5, -16
+ movi a1, _stack + STACK_SIZE
+ and a1, a1, a5
+
+ /* Uncompress the kernel */
+
+ # a0: load address
+ # a2: boot parameter
+ # a4: __start
+
+ movi a3, __image_load
+ sub a4, a3, a4
+ add a8, a0, a4
+
+ # a1 Stack
+ # a8(a4) Load address of the image
+
+ movi a6, _image_start
+ movi a10, _image_end
+ movi a7, 0x1000000
+ sub a11, a10, a6
+ movi a9, complen
+ s32i a11, a9, 0
+
+ movi a0, 0
+
+ # a6 destination
+ # a7 maximum size of destination
+ # a8 source
+ # a9 ptr to length
+
+ .extern gunzip
+ movi a4, gunzip
+ beqz a4, 1f
+
+ callx4 a4
+
+ j 2f
+
+
+ # a6 destination start
+ # a7 maximum size of destination
+ # a8 source start
+ # a9 ptr to length
+ # a10 destination end
+
+1:
+ l32i a9, a8, 0
+ l32i a11, a8, 4
+ s32i a9, a6, 0
+ s32i a11, a6, 4
+ l32i a9, a8, 8
+ l32i a11, a8, 12
+ s32i a9, a6, 8
+ s32i a11, a6, 12
+ addi a6, a6, 16
+ addi a8, a8, 16
+ blt a6, a10, 1b
+
+
+ /* jump to the kernel */
+2:
+#if XCHAL_DCACHE_IS_WRITEBACK
+ dcache_writeback_all a5, a6
+#endif
+ icache_invalidate_all a5, a6
+
+ movi a5, __start
+ movi a3, boot_initrd_start
+ movi a4, boot_initrd_end
+ sub a3, a3, a5
+ sub a4, a4, a5
+ add a3, a0, a3
+ add a4, a0, a4
+
+ # a2 Boot parameter list
+ # a3 initrd_start (virtual load address)
+ # a4 initrd_end (virtual load address)
+
+ movi a0, _image_start
+ jx a0
+
+ .align 16
+ .data
+ .globl avail_ram
+avail_ram:
+ .long _heap
+ .globl end_avail
+end_avail:
+ .long _heap + HEAP_SIZE
+
+ .comm _stack, STACK_SIZE
+ .comm _heap, HEAP_SIZE
+
+ .globl end_avail
+ .comm complen, 4
+
+ .end literal_prefix
diff --git a/arch/xtensa/boot/include/zlib.h b/arch/xtensa/boot/include/zlib.h
new file mode 100644
index 00000000000..ea29b623785
--- /dev/null
+++ b/arch/xtensa/boot/include/zlib.h
@@ -0,0 +1,433 @@
+/*
+ * BK Id: SCCS/s.zlib.h 1.8 05/18/01 15:17:23 cort
+ */
+/*
+ * This file is derived from zlib.h and zconf.h from the zlib-0.95
+ * distribution by Jean-loup Gailly and Mark Adler, with some additions
+ * by Paul Mackerras to aid in implementing Deflate compression and
+ * decompression for PPP packets.
+ */
+
+/*
+ * ==FILEVERSION 960122==
+ *
+ * This marker is used by the Linux installation script to determine
+ * whether an up-to-date version of this file is already installed.
+ */
+
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 0.95, Aug 16th, 1995.
+
+ Copyright (C) 1995 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ gzip@prep.ai.mit.edu madler@alumni.caltech.edu
+ */
+
+#ifndef _ZLIB_H
+#define _ZLIB_H
+
+/* #include "zconf.h" */ /* included directly here */
+
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* From: zconf.h,v 1.12 1995/05/03 17:27:12 jloup Exp */
+
+/*
+ The library does not install any signal handler. It is recommended to
+ add at least a handler for SIGSEGV when decompressing; the library checks
+ the consistency of the input data whenever possible but may go nuts
+ for some forms of corrupted input.
+ */
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ * Compile with -DUNALIGNED_OK if it is OK to access shorts or ints
+ * at addresses which are not a multiple of their size.
+ * Under DOS, -DFAR=far or -DFAR=__far may be needed.
+ */
+
+#ifndef STDC
+# if defined(MSDOS) || defined(__STDC__) || defined(__cplusplus)
+# define STDC
+# endif
+#endif
+
+#ifdef __MWERKS__ /* Metrowerks CodeWarrior declares fileno() in unix.h */
+# include <unix.h>
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# ifdef MAXSEG_64K
+# define MAX_MEM_LEVEL 8
+# else
+# define MAX_MEM_LEVEL 9
+# endif
+#endif
+
+#ifndef FAR
+# define FAR
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2 */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+ 1 << (windowBits+2) + 1 << (memLevel+9)
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+ /* Type declarations */
+
+#ifndef OF /* function prototypes */
+# ifdef STDC
+# define OF(args) args
+# else
+# define OF(args) ()
+# endif
+#endif
+
+typedef unsigned char Byte; /* 8 bits */
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+
+typedef Byte FAR Bytef;
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+ typedef void FAR *voidpf;
+ typedef void *voidp;
+#else
+ typedef Byte FAR *voidpf;
+ typedef Byte *voidp;
+#endif
+
+/* end of original zconf.h */
+
+#define ZLIB_VERSION "0.95P"
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed
+ data. This version of the library supports only one compression method
+ (deflation) but other algorithms may be added later and will have the same
+ stream interface.
+
+ For compression the application must provide the output buffer and
+ may optionally provide the input buffer for optimization. For decompression,
+ the application must provide the input buffer and may optionally provide
+ the output buffer for optimization.
+
+ Compression can be done in a single step if the buffers are large
+ enough (for example if an input file is mmap'ed), or can be done by
+ repeated calls of the compression function. In the latter case, the
+ application must provide more input and/or consume the output
+ (providing more output space) before each call.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void (*free_func) OF((voidpf opaque, voidpf address, uInt nbytes));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+ Bytef *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total nb of input bytes read so far */
+
+ Bytef *next_out; /* next output byte should be put there */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total nb of bytes output so far */
+
+ char *msg; /* last error message, NULL if no error */
+ struct internal_state FAR *state; /* not visible by applications */
+
+ alloc_func zalloc; /* used to allocate the internal state */
+ free_func zfree; /* used to free the internal state */
+ voidp opaque; /* private data object passed to zalloc and zfree */
+
+ Byte data_type; /* best guess about the data type: ascii or binary */
+
+} z_stream;
+
+/*
+ The application must update next_in and avail_in when avail_in has
+ dropped to zero. It must update next_out and avail_out when avail_out
+ has dropped to zero. The application must initialize zalloc, zfree and
+ opaque before calling the init function. All other fields are set by the
+ compression library and must not be updated by the application.
+
+ The opaque value provided by the application will be passed as the first
+ parameter for calls of zalloc and zfree. This can be useful for custom
+ memory management. The compression library attaches no meaning to the
+ opaque value.
+
+ zalloc must return Z_NULL if there is not enough memory for the object.
+ On 16-bit systems, the functions zalloc and zfree must be able to allocate
+ exactly 65536 bytes, but will not be required to allocate more than this
+ if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+ pointers returned by zalloc for objects of exactly 65536 bytes *must*
+ have their offset normalized to zero. The default allocation function
+ provided by this library ensures this (see zutil.c). To reduce memory
+ requirements and avoid any allocation of 64K objects, at the expense of
+ compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+ The fields total_in and total_out can be used for statistics or
+ progress reports. After compression, total_in holds the total size of
+ the uncompressed data and may be saved for use in the decompressor
+ (particularly if the decompressor wants to decompress everything in
+ a single step).
+*/
+
+ /* constants */
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1
+#define Z_FULL_FLUSH 2
+#define Z_SYNC_FLUSH 3 /* experimental: partial_flush + byte align */
+#define Z_FINISH 4
+#define Z_PACKET_FLUSH 5
+/* See deflate() below for the usage of these constants */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+/* error codes for the compression/decompression functions */
+
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#define Z_FILTERED 1
+#define Z_HUFFMAN_ONLY 2
+#define Z_DEFAULT_STRATEGY 0
+
+#define Z_BINARY 0
+#define Z_ASCII 1
+#define Z_UNKNOWN 2
+/* Used to set the data_type field */
+
+#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */
+
+extern char *zlib_version;
+/* The application can compare zlib_version and ZLIB_VERSION for consistency.
+ If the first character differs, the library code actually used is
+ not compatible with the zlib.h header file used by the application.
+ */
+
+ /* basic functions */
+
+extern int inflateInit OF((z_stream *strm));
+/*
+ Initializes the internal stream state for decompression. The fields
+ zalloc and zfree must be initialized before by the caller. If zalloc and
+ zfree are set to Z_NULL, inflateInit updates them to use default allocation
+ functions.
+
+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory. msg is set to null if there is no error message.
+ inflateInit does not perform any decompression: this will be done by
+ inflate().
+*/
+
+
+extern int inflate OF((z_stream *strm, int flush));
+/*
+ Performs one or both of the following actions:
+
+ - Decompress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in is updated and processing
+ will resume at this point for the next call of inflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. inflate() always provides as much output as possible
+ (until there is no more input data or no more space in the output buffer).
+
+ Before the call of inflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating the next_* and avail_* values accordingly.
+ The application can consume the uncompressed output when it wants, for
+ example when the output buffer is full (avail_out == 0), or after each
+ call of inflate().
+
+ If the parameter flush is set to Z_PARTIAL_FLUSH or Z_PACKET_FLUSH,
+ inflate flushes as much output as possible to the output buffer. The
+ flushing behavior of inflate is not specified for values of the flush
+ parameter other than Z_PARTIAL_FLUSH, Z_PACKET_FLUSH or Z_FINISH, but the
+ current implementation actually flushes as much output as possible
+ anyway. For Z_PACKET_FLUSH, inflate checks that once all the input data
+ has been consumed, it is expecting to see the length field of a stored
+ block; if not, it returns Z_DATA_ERROR.
+
+ inflate() should normally be called until it returns Z_STREAM_END or an
+ error. However if all decompression is to be performed in a single step
+ (a single call of inflate), the parameter flush should be set to
+ Z_FINISH. In this case all pending input is processed and all pending
+ output is flushed; avail_out must be large enough to hold all the
+ uncompressed data. (The size of the uncompressed data may have been saved
+ by the compressor for this purpose.) The next operation on this stream must
+ be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+ is never required, but can be used to inform inflate that a faster routine
+ may be used for the single inflate() call.
+
+ inflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if the end of the
+ compressed data has been reached and all uncompressed output has been
+ produced, Z_DATA_ERROR if the input data was corrupted, Z_STREAM_ERROR if
+ the stream structure was inconsistent (for example if next_in or next_out
+ was NULL), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no
+ progress is possible or if there was not enough room in the output buffer
+ when Z_FINISH is used. In the Z_DATA_ERROR case, the application may then
+ call inflateSync to look for a good compression block. */
+
+
+extern int inflateEnd OF((z_stream *strm));
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+ was inconsistent. In the error case, msg may be set but then points to a
+ static string (which must not be deallocated).
+*/
+
+ /* advanced functions */
+
+extern int inflateInit2 OF((z_stream *strm,
+ int windowBits));
+/*
+ This is another version of inflateInit with more compression options. The
+ fields next_out, zalloc and zfree must be initialized before by the caller.
+
+ The windowBits parameter is the base two logarithm of the maximum window
+ size (the size of the history buffer). It should be in the range 8..15 for
+ this version of the library (the value 16 will be allowed soon). The
+ default value is 15 if inflateInit is used instead. If a compressed stream
+ with a larger window size is given as input, inflate() will return with
+ the error code Z_DATA_ERROR instead of trying to allocate a larger window.
+
+ If next_out is not null, the library will use this buffer for the history
+ buffer; the buffer must either be large enough to hold the entire output
+ data, or have at least 1<<windowBits bytes. If next_out is null, the
+ library will allocate its own buffer (and leave next_out null). next_in
+ need not be provided here but must be provided by the application for the
+ next call of inflate().
+
+ If the history buffer is provided by the application, next_out must
+ never be changed by the application since the decompressor maintains
+ history information inside this buffer from call to call; the application
+ can only reset next_out to the beginning of the history buffer when
+ avail_out is zero and all output has been consumed.
+
+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was
+ not enough memory, Z_STREAM_ERROR if a parameter is invalid (such as
+ windowBits < 8). msg is set to null if there is no error message.
+ inflateInit2 does not perform any decompression: this will be done by
+ inflate().
+*/
+
+extern int inflateSync OF((z_stream *strm));
+/*
+ Skips invalid compressed data until the special marker (see deflate()
+ above) can be found, or until all available input is skipped. No output
+ is provided.
+
+ inflateSync returns Z_OK if the special marker has been found, Z_BUF_ERROR
+ if no more input was provided, Z_DATA_ERROR if no marker has been found,
+ or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+ case, the application may save the current current value of total_in which
+ indicates where valid compressed data was found. In the error case, the
+ application may repeatedly call inflateSync, providing more input each time,
+ until success or end of the input data.
+*/
+
+extern int inflateReset OF((z_stream *strm));
+/*
+ This function is equivalent to inflateEnd followed by inflateInit,
+ but does not free and reallocate all the internal decompression state.
+ The stream will keep attributes that may have been set by inflateInit2.
+
+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+extern int inflateIncomp OF((z_stream *strm));
+/*
+ This function adds the data at next_in (avail_in bytes) to the output
+ history without performing any output. There must be no pending output,
+ and the decompressor must be expecting to see the start of a block.
+ Calling this function is equivalent to decompressing a stored block
+ containing the data at next_in (except that the data is not output).
+*/
+
+ /* checksum functions */
+
+/*
+ This function is not related to compression but is exported
+ anyway because it might be useful in applications using the
+ compression library.
+*/
+
+extern uLong adler32 OF((uLong adler, Bytef *buf, uInt len));
+
+/*
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+ return the updated checksum. If buf is NULL, this function returns
+ the required initial value for the checksum.
+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+ much faster. Usage example:
+
+ uLong adler = adler32(0L, Z_NULL, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ adler = adler32(adler, buffer, length);
+ }
+ if (adler != original_adler) error();
+*/
+
+#ifndef _Z_UTIL_H
+ struct internal_state {int dummy;}; /* hack for buggy compilers */
+#endif
+
+#endif /* _ZLIB_H */
diff --git a/arch/xtensa/boot/lib/Makefile b/arch/xtensa/boot/lib/Makefile
new file mode 100644
index 00000000000..c0a74dc3a0d
--- /dev/null
+++ b/arch/xtensa/boot/lib/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for some libs needed by zImage.
+#
+
+
+lib-y := zlib.o zmem.o
diff --git a/arch/xtensa/boot/lib/memcpy.S b/arch/xtensa/boot/lib/memcpy.S
new file mode 100644
index 00000000000..a029f5df2d5
--- /dev/null
+++ b/arch/xtensa/boot/lib/memcpy.S
@@ -0,0 +1,36 @@
+/*
+ * arch/xtensa/lib/memcpy.S
+ *
+ * ANSI C standard library function memcpy
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ *
+ * Copyright (C) 2002 Tensilica Inc.
+ */
+
+#define _ASMLANGUAGE
+#include <xtensa/config/core.h>
+
+.text
+.align 4
+.global bcopy
+.type bcopy,@function
+bcopy:
+ movi a14, xthal_bcopy // a14 safe to use regardless of whether caller
+ // used call4 or call8 (can't have used call12)
+ jx a14 // let the Core HAL do the work
+
+.text
+.align 4
+.global memcpy
+.type memcpy,@function
+memcpy:
+.global memmove
+.type memmove,@function
+memmove:
+ movi a14, xthal_memcpy // a14 safe to use regardless of whether caller
+ // used call4 or call8 (can't have used call12)
+ jx a14 // let the Core HAL do the work
+
diff --git a/arch/xtensa/boot/lib/zlib.c b/arch/xtensa/boot/lib/zlib.c
new file mode 100644
index 00000000000..e3859f63107
--- /dev/null
+++ b/arch/xtensa/boot/lib/zlib.c
@@ -0,0 +1,2150 @@
+/*
+ * BK Id: SCCS/s.zlib.c 1.8 05/18/01 15:17:24 cort
+ */
+/*
+ * This file is derived from various .h and .c files from the zlib-0.95
+ * distribution by Jean-loup Gailly and Mark Adler, with some additions
+ * by Paul Mackerras to aid in implementing Deflate compression and
+ * decompression for PPP packets. See zlib.h for conditions of
+ * distribution and use.
+ *
+ * Changes that have been made include:
+ * - changed functions not used outside this file to "local"
+ * - added minCompression parameter to deflateInit2
+ * - added Z_PACKET_FLUSH (see zlib.h for details)
+ * - added inflateIncomp
+ *
+ */
+
+/*+++++*/
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* From: zutil.h,v 1.9 1995/05/03 17:27:12 jloup Exp */
+
+#define _Z_UTIL_H
+
+#include "zlib.h"
+
+#ifndef local
+# define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+#define FAR
+
+typedef unsigned char uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long ulg;
+
+extern char *z_errmsg[]; /* indexed by 1-zlib_error */
+
+#define ERR_RETURN(strm,err) return (strm->msg=z_errmsg[1-err], err)
+/* To be used only when the state is known to be valid */
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+ /* common constants */
+
+#define DEFLATED 8
+
+#ifndef DEF_WBITS
+# define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES 2
+/* The three kinds of block type */
+
+#define MIN_MATCH 3
+#define MAX_MATCH 258
+/* The minimum and maximum match lengths */
+
+ /* functions */
+
+#include <linux/string.h>
+#define zmemcpy memcpy
+#define zmemzero(dest, len) memset(dest, 0, len)
+
+/* Diagnostic functions */
+#ifdef DEBUG_ZLIB
+# include <stdio.h>
+# ifndef verbose
+# define verbose 0
+# endif
+# define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+# define Trace(x) fprintf x
+# define Tracev(x) {if (verbose) fprintf x ;}
+# define Tracevv(x) {if (verbose>1) fprintf x ;}
+# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+#else
+# define Assert(cond,msg)
+# define Trace(x)
+# define Tracev(x)
+# define Tracevv(x)
+# define Tracec(c,x)
+# define Tracecv(c,x)
+#endif
+
+
+typedef uLong (*check_func) OF((uLong check, Bytef *buf, uInt len));
+
+/* voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); */
+/* void zcfree OF((voidpf opaque, voidpf ptr)); */
+
+#define ZALLOC(strm, items, size) \
+ (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr, size) \
+ (*((strm)->zfree))((strm)->opaque, (voidpf)(addr), (size))
+#define TRY_FREE(s, p, n) {if (p) ZFREE(s, p, n);}
+
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/*+++++*/
+/* infblock.h -- header to use infblock.c
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+struct inflate_blocks_state;
+typedef struct inflate_blocks_state FAR inflate_blocks_statef;
+
+local inflate_blocks_statef * inflate_blocks_new OF((
+ z_stream *z,
+ check_func c, /* check function */
+ uInt w)); /* window size */
+
+local int inflate_blocks OF((
+ inflate_blocks_statef *,
+ z_stream *,
+ int)); /* initial return code */
+
+local void inflate_blocks_reset OF((
+ inflate_blocks_statef *,
+ z_stream *,
+ uLongf *)); /* check value on output */
+
+local int inflate_blocks_free OF((
+ inflate_blocks_statef *,
+ z_stream *,
+ uLongf *)); /* check value on output */
+
+local int inflate_addhistory OF((
+ inflate_blocks_statef *,
+ z_stream *));
+
+local int inflate_packet_flush OF((
+ inflate_blocks_statef *));
+
+/*+++++*/
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+ that have 16-bit pointers (e.g. PC's in the small or medium model). */
+
+typedef struct inflate_huft_s FAR inflate_huft;
+
+struct inflate_huft_s {
+ union {
+ struct {
+ Byte Exop; /* number of extra bits or operation */
+ Byte Bits; /* number of bits in this code or subcode */
+ } what;
+ uInt Nalloc; /* number of these allocated here */
+ Bytef *pad; /* pad structure to a power of 2 (4 bytes for */
+ } word; /* 16-bit, 8 bytes for 32-bit machines) */
+ union {
+ uInt Base; /* literal, length base, or distance base */
+ inflate_huft *Next; /* pointer to next level of table */
+ } more;
+};
+
+#ifdef DEBUG_ZLIB
+ local uInt inflate_hufts;
+#endif
+
+local int inflate_trees_bits OF((
+ uIntf *, /* 19 code lengths */
+ uIntf *, /* bits tree desired/actual depth */
+ inflate_huft * FAR *, /* bits tree result */
+ z_stream *)); /* for zalloc, zfree functions */
+
+local int inflate_trees_dynamic OF((
+ uInt, /* number of literal/length codes */
+ uInt, /* number of distance codes */
+ uIntf *, /* that many (total) code lengths */
+ uIntf *, /* literal desired/actual bit depth */
+ uIntf *, /* distance desired/actual bit depth */
+ inflate_huft * FAR *, /* literal/length tree result */
+ inflate_huft * FAR *, /* distance tree result */
+ z_stream *)); /* for zalloc, zfree functions */
+
+local int inflate_trees_fixed OF((
+ uIntf *, /* literal desired/actual bit depth */
+ uIntf *, /* distance desired/actual bit depth */
+ inflate_huft * FAR *, /* literal/length tree result */
+ inflate_huft * FAR *)); /* distance tree result */
+
+local int inflate_trees_free OF((
+ inflate_huft *, /* tables to free */
+ z_stream *)); /* for zfree function */
+
+
+/*+++++*/
+/* infcodes.h -- header to use infcodes.c
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+struct inflate_codes_state;
+typedef struct inflate_codes_state FAR inflate_codes_statef;
+
+local inflate_codes_statef *inflate_codes_new OF((
+ uInt, uInt,
+ inflate_huft *, inflate_huft *,
+ z_stream *));
+
+local int inflate_codes OF((
+ inflate_blocks_statef *,
+ z_stream *,
+ int));
+
+local void inflate_codes_free OF((
+ inflate_codes_statef *,
+ z_stream *));
+
+
+/*+++++*/
+/* inflate.c -- zlib interface to inflate modules
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* inflate private state */
+struct internal_state {
+
+ /* mode */
+ enum {
+ METHOD, /* waiting for method byte */
+ FLAG, /* waiting for flag byte */
+ BLOCKS, /* decompressing blocks */
+ CHECK4, /* four check bytes to go */
+ CHECK3, /* three check bytes to go */
+ CHECK2, /* two check bytes to go */
+ CHECK1, /* one check byte to go */
+ DONE, /* finished check, done */
+ BAD} /* got an error--stay here */
+ mode; /* current inflate mode */
+
+ /* mode dependent information */
+ union {
+ uInt method; /* if FLAGS, method byte */
+ struct {
+ uLong was; /* computed check value */
+ uLong need; /* stream check value */
+ } check; /* if CHECK, check values to compare */
+ uInt marker; /* if BAD, inflateSync's marker bytes count */
+ } sub; /* submode */
+
+ /* mode independent information */
+ int nowrap; /* flag for no wrapper */
+ uInt wbits; /* log2(window size) (8..15, defaults to 15) */
+ inflate_blocks_statef
+ *blocks; /* current inflate_blocks state */
+
+};
+
+
+int inflateReset(z)
+z_stream *z;
+{
+ uLong c;
+
+ if (z == Z_NULL || z->state == Z_NULL)
+ return Z_STREAM_ERROR;
+ z->total_in = z->total_out = 0;
+ z->msg = Z_NULL;
+ z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
+ inflate_blocks_reset(z->state->blocks, z, &c);
+ Trace((stderr, "inflate: reset\n"));
+ return Z_OK;
+}
+
+
+int inflateEnd(z)
+z_stream *z;
+{
+ uLong c;
+
+ if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
+ return Z_STREAM_ERROR;
+ if (z->state->blocks != Z_NULL)
+ inflate_blocks_free(z->state->blocks, z, &c);
+ ZFREE(z, z->state, sizeof(struct internal_state));
+ z->state = Z_NULL;
+ Trace((stderr, "inflate: end\n"));
+ return Z_OK;
+}
+
+
+int inflateInit2(z, w)
+z_stream *z;
+int w;
+{
+ /* initialize state */
+ if (z == Z_NULL)
+ return Z_STREAM_ERROR;
+/* if (z->zalloc == Z_NULL) z->zalloc = zcalloc; */
+/* if (z->zfree == Z_NULL) z->zfree = zcfree; */
+ if ((z->state = (struct internal_state FAR *)
+ ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
+ return Z_MEM_ERROR;
+ z->state->blocks = Z_NULL;
+
+ /* handle undocumented nowrap option (no zlib header or check) */
+ z->state->nowrap = 0;
+ if (w < 0)
+ {
+ w = - w;
+ z->state->nowrap = 1;
+ }
+
+ /* set window size */
+ if (w < 8 || w > 15)
+ {
+ inflateEnd(z);
+ return Z_STREAM_ERROR;
+ }
+ z->state->wbits = (uInt)w;
+
+ /* create inflate_blocks state */
+ if ((z->state->blocks =
+ inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, 1 << w))
+ == Z_NULL)
+ {
+ inflateEnd(z);
+ return Z_MEM_ERROR;
+ }
+ Trace((stderr, "inflate: allocated\n"));
+
+ /* reset state */
+ inflateReset(z);
+ return Z_OK;
+}
+
+
+int inflateInit(z)
+z_stream *z;
+{
+ return inflateInit2(z, DEF_WBITS);
+}
+
+
+#define NEEDBYTE {if(z->avail_in==0)goto empty;r=Z_OK;}
+#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
+
+int inflate(z, f)
+z_stream *z;
+int f;
+{
+ int r;
+ uInt b;
+
+ if (z == Z_NULL || z->next_in == Z_NULL)
+ return Z_STREAM_ERROR;
+ r = Z_BUF_ERROR;
+ while (1) switch (z->state->mode)
+ {
+ case METHOD:
+ NEEDBYTE
+ if (((z->state->sub.method = NEXTBYTE) & 0xf) != DEFLATED)
+ {
+ z->state->mode = BAD;
+ z->msg = "unknown compression method";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
+ {
+ z->state->mode = BAD;
+ z->msg = "invalid window size";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ z->state->mode = FLAG;
+ case FLAG:
+ NEEDBYTE
+ if ((b = NEXTBYTE) & 0x20)
+ {
+ z->state->mode = BAD;
+ z->msg = "invalid reserved bit";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ if (((z->state->sub.method << 8) + b) % 31)
+ {
+ z->state->mode = BAD;
+ z->msg = "incorrect header check";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ Trace((stderr, "inflate: zlib header ok\n"));
+ z->state->mode = BLOCKS;
+ case BLOCKS:
+ r = inflate_blocks(z->state->blocks, z, r);
+ if (f == Z_PACKET_FLUSH && z->avail_in == 0 && z->avail_out != 0)
+ r = inflate_packet_flush(z->state->blocks);
+ if (r == Z_DATA_ERROR)
+ {
+ z->state->mode = BAD;
+ z->state->sub.marker = 0; /* can try inflateSync */
+ break;
+ }
+ if (r != Z_STREAM_END)
+ return r;
+ r = Z_OK;
+ inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
+ if (z->state->nowrap)
+ {
+ z->state->mode = DONE;
+ break;
+ }
+ z->state->mode = CHECK4;
+ case CHECK4:
+ NEEDBYTE
+ z->state->sub.check.need = (uLong)NEXTBYTE << 24;
+ z->state->mode = CHECK3;
+ case CHECK3:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 16;
+ z->state->mode = CHECK2;
+ case CHECK2:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE << 8;
+ z->state->mode = CHECK1;
+ case CHECK1:
+ NEEDBYTE
+ z->state->sub.check.need += (uLong)NEXTBYTE;
+
+ if (z->state->sub.check.was != z->state->sub.check.need)
+ {
+ z->state->mode = BAD;
+ z->msg = "incorrect data check";
+ z->state->sub.marker = 5; /* can't try inflateSync */
+ break;
+ }
+ Trace((stderr, "inflate: zlib check ok\n"));
+ z->state->mode = DONE;
+ case DONE:
+ return Z_STREAM_END;
+ case BAD:
+ return Z_DATA_ERROR;
+ default:
+ return Z_STREAM_ERROR;
+ }
+
+ empty:
+ if (f != Z_PACKET_FLUSH)
+ return r;
+ z->state->mode = BAD;
+ z->state->sub.marker = 0; /* can try inflateSync */
+ return Z_DATA_ERROR;
+}
+
+/*
+ * This subroutine adds the data at next_in/avail_in to the output history
+ * without performing any output. The output buffer must be "caught up";
+ * i.e. no pending output (hence s->read equals s->write), and the state must
+ * be BLOCKS (i.e. we should be willing to see the start of a series of
+ * BLOCKS). On exit, the output will also be caught up, and the checksum
+ * will have been updated if need be.
+ */
+
+int inflateIncomp(z)
+z_stream *z;
+{
+ if (z->state->mode != BLOCKS)
+ return Z_DATA_ERROR;
+ return inflate_addhistory(z->state->blocks, z);
+}
+
+
+int inflateSync(z)
+z_stream *z;
+{
+ uInt n; /* number of bytes to look at */
+ Bytef *p; /* pointer to bytes */
+ uInt m; /* number of marker bytes found in a row */
+ uLong r, w; /* temporaries to save total_in and total_out */
+
+ /* set up */
+ if (z == Z_NULL || z->state == Z_NULL)
+ return Z_STREAM_ERROR;
+ if (z->state->mode != BAD)
+ {
+ z->state->mode = BAD;
+ z->state->sub.marker = 0;
+ }
+ if ((n = z->avail_in) == 0)
+ return Z_BUF_ERROR;
+ p = z->next_in;
+ m = z->state->sub.marker;
+
+ /* search */
+ while (n && m < 4)
+ {
+ if (*p == (Byte)(m < 2 ? 0 : 0xff))
+ m++;
+ else if (*p)
+ m = 0;
+ else
+ m = 4 - m;
+ p++, n--;
+ }
+
+ /* restore */
+ z->total_in += p - z->next_in;
+ z->next_in = p;
+ z->avail_in = n;
+ z->state->sub.marker = m;
+
+ /* return no joy or set up to restart on a new block */
+ if (m != 4)
+ return Z_DATA_ERROR;
+ r = z->total_in; w = z->total_out;
+ inflateReset(z);
+ z->total_in = r; z->total_out = w;
+ z->state->mode = BLOCKS;
+ return Z_OK;
+}
+
+#undef NEEDBYTE
+#undef NEXTBYTE
+
+/*+++++*/
+/* infutil.h -- types and macros common to blocks and codes
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* inflate blocks semi-private state */
+struct inflate_blocks_state {
+
+ /* mode */
+ enum {
+ TYPE, /* get type bits (3, including end bit) */
+ LENS, /* get lengths for stored */
+ STORED, /* processing stored block */
+ TABLE, /* get table lengths */
+ BTREE, /* get bit lengths tree for a dynamic block */
+ DTREE, /* get length, distance trees for a dynamic block */
+ CODES, /* processing fixed or dynamic block */
+ DRY, /* output remaining window bytes */
+ DONEB, /* finished last block, done */
+ BADB} /* got a data error--stuck here */
+ mode; /* current inflate_block mode */
+
+ /* mode dependent information */
+ union {
+ uInt left; /* if STORED, bytes left to copy */
+ struct {
+ uInt table; /* table lengths (14 bits) */
+ uInt index; /* index into blens (or border) */
+ uIntf *blens; /* bit lengths of codes */
+ uInt bb; /* bit length tree depth */
+ inflate_huft *tb; /* bit length decoding tree */
+ int nblens; /* # elements allocated at blens */
+ } trees; /* if DTREE, decoding info for trees */
+ struct {
+ inflate_huft *tl, *td; /* trees to free */
+ inflate_codes_statef
+ *codes;
+ } decode; /* if CODES, current state */
+ } sub; /* submode */
+ uInt last; /* true if this block is the last block */
+
+ /* mode independent information */
+ uInt bitk; /* bits in bit buffer */
+ uLong bitb; /* bit buffer */
+ Bytef *window; /* sliding window */
+ Bytef *end; /* one byte after sliding window */
+ Bytef *read; /* window read pointer */
+ Bytef *write; /* window write pointer */
+ check_func checkfn; /* check function */
+ uLong check; /* check on output */
+
+};
+
+
+/* defines for inflate input/output */
+/* update pointers and return */
+#define UPDBITS {s->bitb=b;s->bitk=k;}
+#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
+#define UPDOUT {s->write=q;}
+#define UPDATE {UPDBITS UPDIN UPDOUT}
+#define LEAVE {UPDATE return inflate_flush(s,z,r);}
+/* get bytes and bits */
+#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
+#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
+#define NEXTBYTE (n--,*p++)
+#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define DUMPBITS(j) {b>>=(j);k-=(j);}
+/* output bytes */
+#define WAVAIL (q<s->read?s->read-q-1:s->end-q)
+#define LOADOUT {q=s->write;m=WAVAIL;}
+#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=WAVAIL;}}
+#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
+#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
+#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
+/* load local pointers */
+#define LOAD {LOADIN LOADOUT}
+
+/*
+ * The IBM 150 firmware munges the data right after _etext[]. This
+ * protects it. -- Cort
+ */
+local uInt protect_mask[] = {0, 0, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0};
+/* And'ing with mask[n] masks the lower n bits */
+local uInt inflate_mask[] = {
+ 0x0000,
+ 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+ 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+/* copy as much as possible from the sliding window to the output area */
+local int inflate_flush OF((
+ inflate_blocks_statef *,
+ z_stream *,
+ int));
+
+/*+++++*/
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+local int inflate_fast OF((
+ uInt,
+ uInt,
+ inflate_huft *,
+ inflate_huft *,
+ inflate_blocks_statef *,
+ z_stream *));
+
+
+/*+++++*/
+/* infblock.c -- interpret and process block types to last block
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* Table for deflate from PKZIP's appnote.txt. */
+local uInt border[] = { /* Order of the bit length code lengths */
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+/*
+ Notes beyond the 1.93a appnote.txt:
+
+ 1. Distance pointers never point before the beginning of the output
+ stream.
+ 2. Distance pointers can point back across blocks, up to 32k away.
+ 3. There is an implied maximum of 7 bits for the bit length table and
+ 15 bits for the actual data.
+ 4. If only one code exists, then it is encoded using one bit. (Zero
+ would be more efficient, but perhaps a little confusing.) If two
+ codes exist, they are coded using one bit each (0 and 1).
+ 5. There is no way of sending zero distance codes--a dummy must be
+ sent if there are none. (History: a pre 2.0 version of PKZIP would
+ store blocks with no distance codes, but this was discovered to be
+ too harsh a criterion.) Valid only for 1.93a. 2.04c does allow
+ zero distance codes, which is sent as one code of zero bits in
+ length.
+ 6. There are up to 286 literal/length codes. Code 256 represents the
+ end-of-block. Note however that the static length tree defines
+ 288 codes just to fill out the Huffman codes. Codes 286 and 287
+ cannot be used though, since there is no length base or extra bits
+ defined for them. Similarily, there are up to 30 distance codes.
+ However, static trees define 32 codes (all 5 bits) to fill out the
+ Huffman codes, but the last two had better not show up in the data.
+ 7. Unzip can check dynamic Huffman blocks for complete code sets.
+ The exception is that a single code would not be complete (see #4).
+ 8. The five bits following the block type is really the number of
+ literal codes sent minus 257.
+ 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+ (1+6+6). Therefore, to output three times the length, you output
+ three codes (1+1+1), whereas to output four times the same length,
+ you only need two codes (1+3). Hmm.
+ 10. In the tree reconstruction algorithm, Code = Code + Increment
+ only if BitLength(i) is not zero. (Pretty obvious.)
+ 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19)
+ 12. Note: length code 284 can represent 227-258, but length code 285
+ really is 258. The last length deserves its own, short code
+ since it gets used a lot in very redundant files. The length
+ 258 is special since 258 - 3 (the min match length) is 255.
+ 13. The literal/length and distance code bit lengths are read as a
+ single stream of lengths. It is possible (and advantageous) for
+ a repeat code (16, 17, or 18) to go across the boundary between
+ the two sets of lengths.
+ */
+
+
+local void inflate_blocks_reset(s, z, c)
+inflate_blocks_statef *s;
+z_stream *z;
+uLongf *c;
+{
+ if (s->checkfn != Z_NULL)
+ *c = s->check;
+ if (s->mode == BTREE || s->mode == DTREE)
+ ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt));
+ if (s->mode == CODES)
+ {
+ inflate_codes_free(s->sub.decode.codes, z);
+ inflate_trees_free(s->sub.decode.td, z);
+ inflate_trees_free(s->sub.decode.tl, z);
+ }
+ s->mode = TYPE;
+ s->bitk = 0;
+ s->bitb = 0;
+ s->read = s->write = s->window;
+ if (s->checkfn != Z_NULL)
+ s->check = (*s->checkfn)(0L, Z_NULL, 0);
+ Trace((stderr, "inflate: blocks reset\n"));
+}
+
+
+local inflate_blocks_statef *inflate_blocks_new(z, c, w)
+z_stream *z;
+check_func c;
+uInt w;
+{
+ inflate_blocks_statef *s;
+
+ if ((s = (inflate_blocks_statef *)ZALLOC
+ (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
+ return s;
+ if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
+ {
+ ZFREE(z, s, sizeof(struct inflate_blocks_state));
+ return Z_NULL;
+ }
+ s->end = s->window + w;
+ s->checkfn = c;
+ s->mode = TYPE;
+ Trace((stderr, "inflate: blocks allocated\n"));
+ inflate_blocks_reset(s, z, &s->check);
+ return s;
+}
+
+
+local int inflate_blocks(s, z, r)
+inflate_blocks_statef *s;
+z_stream *z;
+int r;
+{
+ uInt t; /* temporary storage */
+ uLong b; /* bit buffer */
+ uInt k; /* bits in bit buffer */
+ Bytef *p; /* input data pointer */
+ uInt n; /* bytes available there */
+ Bytef *q; /* output window write pointer */
+ uInt m; /* bytes to end of window or read pointer */
+
+ /* copy input/output information to locals (UPDATE macro restores) */
+ LOAD
+
+ /* process input based on current state */
+ while (1) switch (s->mode)
+ {
+ case TYPE:
+ NEEDBITS(3)
+ t = (uInt)b & 7;
+ s->last = t & 1;
+ switch (t >> 1)
+ {
+ case 0: /* stored */
+ Trace((stderr, "inflate: stored block%s\n",
+ s->last ? " (last)" : ""));
+ DUMPBITS(3)
+ t = k & 7; /* go to byte boundary */
+ DUMPBITS(t)
+ s->mode = LENS; /* get length of stored block */
+ break;
+ case 1: /* fixed */
+ Trace((stderr, "inflate: fixed codes block%s\n",
+ s->last ? " (last)" : ""));
+ {
+ uInt bl, bd;
+ inflate_huft *tl, *td;
+
+ inflate_trees_fixed(&bl, &bd, &tl, &td);
+ s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
+ if (s->sub.decode.codes == Z_NULL)
+ {
+ r = Z_MEM_ERROR;
+ LEAVE
+ }
+ s->sub.decode.tl = Z_NULL; /* don't try to free these */
+ s->sub.decode.td = Z_NULL;
+ }
+ DUMPBITS(3)
+ s->mode = CODES;
+ break;
+ case 2: /* dynamic */
+ Trace((stderr, "inflate: dynamic codes block%s\n",
+ s->last ? " (last)" : ""));
+ DUMPBITS(3)
+ s->mode = TABLE;
+ break;
+ case 3: /* illegal */
+ DUMPBITS(3)
+ s->mode = BADB;
+ z->msg = "invalid block type";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+ break;
+ case LENS:
+ NEEDBITS(32)
+ if (((~b) >> 16) != (b & 0xffff))
+ {
+ s->mode = BADB;
+ z->msg = "invalid stored block lengths";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+ s->sub.left = (uInt)b & 0xffff;
+ b = k = 0; /* dump bits */
+ Tracev((stderr, "inflate: stored length %u\n", s->sub.left));
+ s->mode = s->sub.left ? STORED : TYPE;
+ break;
+ case STORED:
+ if (n == 0)
+ LEAVE
+ NEEDOUT
+ t = s->sub.left;
+ if (t > n) t = n;
+ if (t > m) t = m;
+ zmemcpy(q, p, t);
+ p += t; n -= t;
+ q += t; m -= t;
+ if ((s->sub.left -= t) != 0)
+ break;
+ Tracev((stderr, "inflate: stored end, %lu total out\n",
+ z->total_out + (q >= s->read ? q - s->read :
+ (s->end - s->read) + (q - s->window))));
+ s->mode = s->last ? DRY : TYPE;
+ break;
+ case TABLE:
+ NEEDBITS(14)
+ s->sub.trees.table = t = (uInt)b & 0x3fff;
+#ifndef PKZIP_BUG_WORKAROUND
+ if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+ {
+ s->mode = BADB;
+ z->msg = "too many length or distance symbols";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+#endif
+ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+ if (t < 19)
+ t = 19;
+ if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
+ {
+ r = Z_MEM_ERROR;
+ LEAVE
+ }
+ s->sub.trees.nblens = t;
+ DUMPBITS(14)
+ s->sub.trees.index = 0;
+ Tracev((stderr, "inflate: table sizes ok\n"));
+ s->mode = BTREE;
+ case BTREE:
+ while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
+ {
+ NEEDBITS(3)
+ s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
+ DUMPBITS(3)
+ }
+ while (s->sub.trees.index < 19)
+ s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
+ s->sub.trees.bb = 7;
+ t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
+ &s->sub.trees.tb, z);
+ if (t != Z_OK)
+ {
+ r = t;
+ if (r == Z_DATA_ERROR)
+ s->mode = BADB;
+ LEAVE
+ }
+ s->sub.trees.index = 0;
+ Tracev((stderr, "inflate: bits tree ok\n"));
+ s->mode = DTREE;
+ case DTREE:
+ while (t = s->sub.trees.table,
+ s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
+ {
+ inflate_huft *h;
+ uInt i, j, c;
+
+ t = s->sub.trees.bb;
+ NEEDBITS(t)
+ h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
+ t = h->word.what.Bits;
+ c = h->more.Base;
+ if (c < 16)
+ {
+ DUMPBITS(t)
+ s->sub.trees.blens[s->sub.trees.index++] = c;
+ }
+ else /* c == 16..18 */
+ {
+ i = c == 18 ? 7 : c - 14;
+ j = c == 18 ? 11 : 3;
+ NEEDBITS(t + i)
+ DUMPBITS(t)
+ j += (uInt)b & inflate_mask[i];
+ DUMPBITS(i)
+ i = s->sub.trees.index;
+ t = s->sub.trees.table;
+ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+ (c == 16 && i < 1))
+ {
+ s->mode = BADB;
+ z->msg = "invalid bit length repeat";
+ r = Z_DATA_ERROR;
+ LEAVE
+ }
+ c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
+ do {
+ s->sub.trees.blens[i++] = c;
+ } while (--j);
+ s->sub.trees.index = i;
+ }
+ }
+ inflate_trees_free(s->sub.trees.tb, z);
+ s->sub.trees.tb = Z_NULL;
+ {
+ uInt bl, bd;
+ inflate_huft *tl, *td;
+ inflate_codes_statef *c;
+
+ bl = 9; /* must be <= 9 for lookahead assumptions */
+ bd = 6; /* must be <= 9 for lookahead assumptions */
+ t = s->sub.trees.table;
+ t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
+ s->sub.trees.blens, &bl, &bd, &tl, &td, z);
+ if (t != Z_OK)
+ {
+ if (t == (uInt)Z_DATA_ERROR)
+ s->mode = BADB;
+ r = t;
+ LEAVE
+ }
+ Tracev((stderr, "inflate: trees ok\n"));
+ if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
+ {
+ inflate_trees_free(td, z);
+ inflate_trees_free(tl, z);
+ r = Z_MEM_ERROR;
+ LEAVE
+ }
+ ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt));
+ s->sub.decode.codes = c;
+ s->sub.decode.tl = tl;
+ s->sub.decode.td = td;
+ }
+ s->mode = CODES;
+ case CODES:
+ UPDATE
+ if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
+ return inflate_flush(s, z, r);
+ r = Z_OK;
+ inflate_codes_free(s->sub.decode.codes, z);
+ inflate_trees_free(s->sub.decode.td, z);
+ inflate_trees_free(s->sub.decode.tl, z);
+ LOAD
+ Tracev((stderr, "inflate: codes end, %lu total out\n",
+ z->total_out + (q >= s->read ? q - s->read :
+ (s->end - s->read) + (q - s->window))));
+ if (!s->last)
+ {
+ s->mode = TYPE;
+ break;
+ }
+ if (k > 7) /* return unused byte, if any */
+ {
+ Assert(k < 16, "inflate_codes grabbed too many bytes")
+ k -= 8;
+ n++;
+ p--; /* can always return one */
+ }
+ s->mode = DRY;
+ case DRY:
+ FLUSH
+ if (s->read != s->write)
+ LEAVE
+ s->mode = DONEB;
+ case DONEB:
+ r = Z_STREAM_END;
+ LEAVE
+ case BADB:
+ r = Z_DATA_ERROR;
+ LEAVE
+ default:
+ r = Z_STREAM_ERROR;
+ LEAVE
+ }
+}
+
+
+local int inflate_blocks_free(s, z, c)
+inflate_blocks_statef *s;
+z_stream *z;
+uLongf *c;
+{
+ inflate_blocks_reset(s, z, c);
+ ZFREE(z, s->window, s->end - s->window);
+ ZFREE(z, s, sizeof(struct inflate_blocks_state));
+ Trace((stderr, "inflate: blocks freed\n"));
+ return Z_OK;
+}
+
+/*
+ * This subroutine adds the data at next_in/avail_in to the output history
+ * without performing any output. The output buffer must be "caught up";
+ * i.e. no pending output (hence s->read equals s->write), and the state must
+ * be BLOCKS (i.e. we should be willing to see the start of a series of
+ * BLOCKS). On exit, the output will also be caught up, and the checksum
+ * will have been updated if need be.
+ */
+local int inflate_addhistory(s, z)
+inflate_blocks_statef *s;
+z_stream *z;
+{
+ uLong b; /* bit buffer */ /* NOT USED HERE */
+ uInt k; /* bits in bit buffer */ /* NOT USED HERE */
+ uInt t; /* temporary storage */
+ Bytef *p; /* input data pointer */
+ uInt n; /* bytes available there */
+ Bytef *q; /* output window write pointer */
+ uInt m; /* bytes to end of window or read pointer */
+
+ if (s->read != s->write)
+ return Z_STREAM_ERROR;
+ if (s->mode != TYPE)
+ return Z_DATA_ERROR;
+
+ /* we're ready to rock */
+ LOAD
+ /* while there is input ready, copy to output buffer, moving
+ * pointers as needed.
+ */
+ while (n) {
+ t = n; /* how many to do */
+ /* is there room until end of buffer? */
+ if (t > m) t = m;
+ /* update check information */
+ if (s->checkfn != Z_NULL)
+ s->check = (*s->checkfn)(s->check, q, t);
+ zmemcpy(q, p, t);
+ q += t;
+ p += t;
+ n -= t;
+ z->total_out += t;
+ s->read = q; /* drag read pointer forward */
+/* WRAP */ /* expand WRAP macro by hand to handle s->read */
+ if (q == s->end) {
+ s->read = q = s->window;
+ m = WAVAIL;
+ }
+ }
+ UPDATE
+ return Z_OK;
+}
+
+
+/*
+ * At the end of a Deflate-compressed PPP packet, we expect to have seen
+ * a `stored' block type value but not the (zero) length bytes.
+ */
+local int inflate_packet_flush(s)
+ inflate_blocks_statef *s;
+{
+ if (s->mode != LENS)
+ return Z_DATA_ERROR;
+ s->mode = TYPE;
+ return Z_OK;
+}
+
+
+/*+++++*/
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define base more.Base
+#define next more.Next
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+
+local int huft_build OF((
+ uIntf *, /* code lengths in bits */
+ uInt, /* number of codes */
+ uInt, /* number of "simple" codes */
+ uIntf *, /* list of base values for non-simple codes */
+ uIntf *, /* list of extra bits for non-simple codes */
+ inflate_huft * FAR*,/* result: starting table */
+ uIntf *, /* maximum lookup bits (returns actual) */
+ z_stream *)); /* for zalloc function */
+
+local voidpf falloc OF((
+ voidpf, /* opaque pointer (not used) */
+ uInt, /* number of items */
+ uInt)); /* size of item */
+
+local void ffree OF((
+ voidpf q, /* opaque pointer (not used) */
+ voidpf p, /* what to free (not used) */
+ uInt n)); /* number of bytes (not used) */
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+local uInt cplens[] = { /* Copy lengths for literal codes 257..285 */
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+ /* actually lengths - 2; also see note #13 above about 258 */
+local uInt cplext[] = { /* Extra bits for literal codes 257..285 */
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 192, 192}; /* 192==invalid */
+local uInt cpdist[] = { /* Copy offsets for distance codes 0..29 */
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577};
+local uInt cpdext[] = { /* Extra bits for distance codes */
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13};
+
+/*
+ Huffman code decoding is performed using a multi-level table lookup.
+ The fastest way to decode is to simply build a lookup table whose
+ size is determined by the longest code. However, the time it takes
+ to build this table can also be a factor if the data being decoded
+ is not very long. The most common codes are necessarily the
+ shortest codes, so those codes dominate the decoding time, and hence
+ the speed. The idea is you can have a shorter table that decodes the
+ shorter, more probable codes, and then point to subsidiary tables for
+ the longer codes. The time it costs to decode the longer codes is
+ then traded against the time it takes to make longer tables.
+
+ This results of this trade are in the variables lbits and dbits
+ below. lbits is the number of bits the first level table for literal/
+ length codes can decode in one step, and dbits is the same thing for
+ the distance codes. Subsequent tables are also less than or equal to
+ those sizes. These values may be adjusted either when all of the
+ codes are shorter than that, in which case the longest code length in
+ bits is used, or when the shortest code is *longer* than the requested
+ table size, in which case the length of the shortest code in bits is
+ used.
+
+ There are two different values for the two tables, since they code a
+ different number of possibilities each. The literal/length table
+ codes 286 possible values, or in a flat code, a little over eight
+ bits. The distance table codes 30 possible values, or a little less
+ than five bits, flat. The optimum values for speed end up being
+ about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+ The optimum values may differ though from machine to machine, and
+ possibly even between compilers. Your mileage may vary.
+ */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
+#define BMAX 15 /* maximum bit length of any code */
+#define N_MAX 288 /* maximum number of codes in any set */
+
+#ifdef DEBUG_ZLIB
+ uInt inflate_hufts;
+#endif
+
+local int huft_build(b, n, s, d, e, t, m, zs)
+uIntf *b; /* code lengths in bits (all assumed <= BMAX) */
+uInt n; /* number of codes (assumed <= N_MAX) */
+uInt s; /* number of simple-valued codes (0..s-1) */
+uIntf *d; /* list of base values for non-simple codes */
+uIntf *e; /* list of extra bits for non-simple codes */
+inflate_huft * FAR *t; /* result: starting table */
+uIntf *m; /* maximum lookup bits, returns actual */
+z_stream *zs; /* for zalloc function */
+/* Given a list of code lengths and a maximum table size, make a set of
+ tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
+ if the given code set is incomplete (the tables are still built in this
+ case), Z_DATA_ERROR if the input is invalid (all zero length codes or an
+ over-subscribed set of lengths), or Z_MEM_ERROR if not enough memory. */
+{
+
+ uInt a; /* counter for codes of length k */
+ uInt c[BMAX+1]; /* bit length count table */
+ uInt f; /* i repeats in table every f entries */
+ int g; /* maximum code length */
+ int h; /* table level */
+ register uInt i; /* counter, current code */
+ register uInt j; /* counter */
+ register int k; /* number of bits in current code */
+ int l; /* bits per table (returned in m) */
+ register uIntf *p; /* pointer into c[], b[], or v[] */
+ inflate_huft *q; /* points to current table */
+ struct inflate_huft_s r; /* table entry for structure assignment */
+ inflate_huft *u[BMAX]; /* table stack */
+ uInt v[N_MAX]; /* values in order of bit length */
+ register int w; /* bits before this table == (l * h) */
+ uInt x[BMAX+1]; /* bit offsets, then code stack */
+ uIntf *xp; /* pointer into x */
+ int y; /* number of dummy codes added */
+ uInt z; /* number of entries in current table */
+
+
+ /* Generate counts for each bit length */
+ p = c;
+#define C0 *p++ = 0;
+#define C2 C0 C0 C0 C0
+#define C4 C2 C2 C2 C2
+ C4 /* clear c[]--assume BMAX+1 is 16 */
+ p = b; i = n;
+ do {
+ c[*p++]++; /* assume all entries <= BMAX */
+ } while (--i);
+ if (c[0] == n) /* null input--all zero length codes */
+ {
+ *t = (inflate_huft *)Z_NULL;
+ *m = 0;
+ return Z_OK;
+ }
+
+
+ /* Find minimum and maximum length, bound *m by those */
+ l = *m;
+ for (j = 1; j <= BMAX; j++)
+ if (c[j])
+ break;
+ k = j; /* minimum code length */
+ if ((uInt)l < j)
+ l = j;
+ for (i = BMAX; i; i--)
+ if (c[i])
+ break;
+ g = i; /* maximum code length */
+ if ((uInt)l > i)
+ l = i;
+ *m = l;
+
+
+ /* Adjust last length count to fill out codes, if needed */
+ for (y = 1 << j; j < i; j++, y <<= 1)
+ if ((y -= c[j]) < 0)
+ return Z_DATA_ERROR;
+ if ((y -= c[i]) < 0)
+ return Z_DATA_ERROR;
+ c[i] += y;
+
+
+ /* Generate starting offsets into the value table for each length */
+ x[1] = j = 0;
+ p = c + 1; xp = x + 2;
+ while (--i) { /* note that i == g from above */
+ *xp++ = (j += *p++);
+ }
+
+
+ /* Make a table of values in order of bit lengths */
+ p = b; i = 0;
+ do {
+ if ((j = *p++) != 0)
+ v[x[j]++] = i;
+ } while (++i < n);
+
+
+ /* Generate the Huffman codes and for each, make the table entries */
+ x[0] = i = 0; /* first Huffman code is zero */
+ p = v; /* grab values in bit order */
+ h = -1; /* no tables yet--level -1 */
+ w = -l; /* bits decoded == (l * h) */
+ u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */
+ q = (inflate_huft *)Z_NULL; /* ditto */
+ z = 0; /* ditto */
+
+ /* go through the bit lengths (k already is bits in shortest code) */
+ for (; k <= g; k++)
+ {
+ a = c[k];
+ while (a--)
+ {
+ /* here i is the Huffman code of length k bits for value *p */
+ /* make tables up to required level */
+ while (k > w + l)
+ {
+ h++;
+ w += l; /* previous table always l bits */
+
+ /* compute minimum size table less than or equal to l bits */
+ z = (z = g - w) > (uInt)l ? l : z; /* table size upper limit */
+ if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */
+ { /* too few codes for k-w bit table */
+ f -= a + 1; /* deduct codes from patterns left */
+ xp = c + k;
+ if (j < z)
+ while (++j < z) /* try smaller tables up to z bits */
+ {
+ if ((f <<= 1) <= *++xp)
+ break; /* enough codes to use up j bits */
+ f -= *xp; /* else deduct codes from patterns */
+ }
+ }
+ z = 1 << j; /* table entries for j-bit table */
+
+ /* allocate and link in new table */
+ if ((q = (inflate_huft *)ZALLOC
+ (zs,z + 1,sizeof(inflate_huft))) == Z_NULL)
+ {
+ if (h)
+ inflate_trees_free(u[0], zs);
+ return Z_MEM_ERROR; /* not enough memory */
+ }
+ q->word.Nalloc = z + 1;
+#ifdef DEBUG_ZLIB
+ inflate_hufts += z + 1;
+#endif
+ *t = q + 1; /* link to list for huft_free() */
+ *(t = &(q->next)) = Z_NULL;
+ u[h] = ++q; /* table starts after link */
+
+ /* connect to last table, if there is one */
+ if (h)
+ {
+ x[h] = i; /* save pattern for backing up */
+ r.bits = (Byte)l; /* bits to dump before this table */
+ r.exop = (Byte)j; /* bits in this table */
+ r.next = q; /* pointer to this table */
+ j = i >> (w - l); /* (get around Turbo C bug) */
+ u[h-1][j] = r; /* connect to last table */
+ }
+ }
+
+ /* set up table entry in r */
+ r.bits = (Byte)(k - w);
+ if (p >= v + n)
+ r.exop = 128 + 64; /* out of values--invalid code */
+ else if (*p < s)
+ {
+ r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */
+ r.base = *p++; /* simple code is just the value */
+ }
+ else
+ {
+ r.exop = (Byte)e[*p - s] + 16 + 64; /* non-simple--look up in lists */
+ r.base = d[*p++ - s];
+ }
+
+ /* fill code-like entries with r */
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f)
+ q[j] = r;
+
+ /* backwards increment the k-bit code i */
+ for (j = 1 << (k - 1); i & j; j >>= 1)
+ i ^= j;
+ i ^= j;
+
+ /* backup over finished tables */
+ while ((i & ((1 << w) - 1)) != x[h])
+ {
+ h--; /* don't need to update q */
+ w -= l;
+ }
+ }
+ }
+
+
+ /* Return Z_BUF_ERROR if we were given an incomplete table */
+ return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
+}
+
+
+local int inflate_trees_bits(c, bb, tb, z)
+uIntf *c; /* 19 code lengths */
+uIntf *bb; /* bits tree desired/actual depth */
+inflate_huft * FAR *tb; /* bits tree result */
+z_stream *z; /* for zfree function */
+{
+ int r;
+
+ r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, tb, bb, z);
+ if (r == Z_DATA_ERROR)
+ z->msg = "oversubscribed dynamic bit lengths tree";
+ else if (r == Z_BUF_ERROR)
+ {
+ inflate_trees_free(*tb, z);
+ z->msg = "incomplete dynamic bit lengths tree";
+ r = Z_DATA_ERROR;
+ }
+ return r;
+}
+
+
+local int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, z)
+uInt nl; /* number of literal/length codes */
+uInt nd; /* number of distance codes */
+uIntf *c; /* that many (total) code lengths */
+uIntf *bl; /* literal desired/actual bit depth */
+uIntf *bd; /* distance desired/actual bit depth */
+inflate_huft * FAR *tl; /* literal/length tree result */
+inflate_huft * FAR *td; /* distance tree result */
+z_stream *z; /* for zfree function */
+{
+ int r;
+
+ /* build literal/length tree */
+ if ((r = huft_build(c, nl, 257, cplens, cplext, tl, bl, z)) != Z_OK)
+ {
+ if (r == Z_DATA_ERROR)
+ z->msg = "oversubscribed literal/length tree";
+ else if (r == Z_BUF_ERROR)
+ {
+ inflate_trees_free(*tl, z);
+ z->msg = "incomplete literal/length tree";
+ r = Z_DATA_ERROR;
+ }
+ return r;
+ }
+
+ /* build distance tree */
+ if ((r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, z)) != Z_OK)
+ {
+ if (r == Z_DATA_ERROR)
+ z->msg = "oversubscribed literal/length tree";
+ else if (r == Z_BUF_ERROR) {
+#ifdef PKZIP_BUG_WORKAROUND
+ r = Z_OK;
+ }
+#else
+ inflate_trees_free(*td, z);
+ z->msg = "incomplete literal/length tree";
+ r = Z_DATA_ERROR;
+ }
+ inflate_trees_free(*tl, z);
+ return r;
+#endif
+ }
+
+ /* done */
+ return Z_OK;
+}
+
+
+/* build fixed tables only once--keep them here */
+local int fixed_lock = 0;
+local int fixed_built = 0;
+#define FIXEDH 530 /* number of hufts used by fixed tables */
+local uInt fixed_left = FIXEDH;
+local inflate_huft fixed_mem[FIXEDH];
+local uInt fixed_bl;
+local uInt fixed_bd;
+local inflate_huft *fixed_tl;
+local inflate_huft *fixed_td;
+
+
+local voidpf falloc(q, n, s)
+voidpf q; /* opaque pointer (not used) */
+uInt n; /* number of items */
+uInt s; /* size of item */
+{
+ Assert(s == sizeof(inflate_huft) && n <= fixed_left,
+ "inflate_trees falloc overflow");
+ if (q) s++; /* to make some compilers happy */
+ fixed_left -= n;
+ return (voidpf)(fixed_mem + fixed_left);
+}
+
+
+local void ffree(q, p, n)
+voidpf q;
+voidpf p;
+uInt n;
+{
+ Assert(0, "inflate_trees ffree called!");
+ if (q) q = p; /* to make some compilers happy */
+}
+
+
+local int inflate_trees_fixed(bl, bd, tl, td)
+uIntf *bl; /* literal desired/actual bit depth */
+uIntf *bd; /* distance desired/actual bit depth */
+inflate_huft * FAR *tl; /* literal/length tree result */
+inflate_huft * FAR *td; /* distance tree result */
+{
+ /* build fixed tables if not built already--lock out other instances */
+ while (++fixed_lock > 1)
+ fixed_lock--;
+ if (!fixed_built)
+ {
+ int k; /* temporary variable */
+ unsigned c[288]; /* length list for huft_build */
+ z_stream z; /* for falloc function */
+
+ /* set up fake z_stream for memory routines */
+ z.zalloc = falloc;
+ z.zfree = ffree;
+ z.opaque = Z_NULL;
+
+ /* literal table */
+ for (k = 0; k < 144; k++)
+ c[k] = 8;
+ for (; k < 256; k++)
+ c[k] = 9;
+ for (; k < 280; k++)
+ c[k] = 7;
+ for (; k < 288; k++)
+ c[k] = 8;
+ fixed_bl = 7;
+ huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, &z);
+
+ /* distance table */
+ for (k = 0; k < 30; k++)
+ c[k] = 5;
+ fixed_bd = 5;
+ huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, &z);
+
+ /* done */
+ fixed_built = 1;
+ }
+ fixed_lock--;
+ *bl = fixed_bl;
+ *bd = fixed_bd;
+ *tl = fixed_tl;
+ *td = fixed_td;
+ return Z_OK;
+}
+
+
+local int inflate_trees_free(t, z)
+inflate_huft *t; /* table to free */
+z_stream *z; /* for zfree function */
+/* Free the malloc'ed tables built by huft_build(), which makes a linked
+ list of the tables it made, with the links in a dummy first entry of
+ each table. */
+{
+ register inflate_huft *p, *q;
+
+ /* Go through linked list, freeing from the malloced (t[-1]) address. */
+ p = t;
+ while (p != Z_NULL)
+ {
+ q = (--p)->next;
+ ZFREE(z, p, p->word.Nalloc * sizeof(inflate_huft));
+ p = q;
+ }
+ return Z_OK;
+}
+
+/*+++++*/
+/* infcodes.c -- process literals and length/distance pairs
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define base more.Base
+#define next more.Next
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* inflate codes private state */
+struct inflate_codes_state {
+
+ /* mode */
+ enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+ START, /* x: set up for LEN */
+ LEN, /* i: get length/literal/eob next */
+ LENEXT, /* i: getting length extra (have base) */
+ DIST, /* i: get distance next */
+ DISTEXT, /* i: getting distance extra */
+ COPY, /* o: copying bytes in window, waiting for space */
+ LIT, /* o: got literal, waiting for output space */
+ WASH, /* o: got eob, possibly still output waiting */
+ END, /* x: got eob and all data flushed */
+ BADCODE} /* x: got error */
+ mode; /* current inflate_codes mode */
+
+ /* mode dependent information */
+ uInt len;
+ union {
+ struct {
+ inflate_huft *tree; /* pointer into tree */
+ uInt need; /* bits needed */
+ } code; /* if LEN or DIST, where in tree */
+ uInt lit; /* if LIT, literal */
+ struct {
+ uInt get; /* bits to get for extra */
+ uInt dist; /* distance back to copy from */
+ } copy; /* if EXT or COPY, where and how much */
+ } sub; /* submode */
+
+ /* mode independent information */
+ Byte lbits; /* ltree bits decoded per branch */
+ Byte dbits; /* dtree bits decoder per branch */
+ inflate_huft *ltree; /* literal/length/eob tree */
+ inflate_huft *dtree; /* distance tree */
+
+};
+
+
+local inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
+uInt bl, bd;
+inflate_huft *tl, *td;
+z_stream *z;
+{
+ inflate_codes_statef *c;
+
+ if ((c = (inflate_codes_statef *)
+ ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
+ {
+ c->mode = START;
+ c->lbits = (Byte)bl;
+ c->dbits = (Byte)bd;
+ c->ltree = tl;
+ c->dtree = td;
+ Tracev((stderr, "inflate: codes new\n"));
+ }
+ return c;
+}
+
+
+local int inflate_codes(s, z, r)
+inflate_blocks_statef *s;
+z_stream *z;
+int r;
+{
+ uInt j; /* temporary storage */
+ inflate_huft *t; /* temporary pointer */
+ uInt e; /* extra bits or operation */
+ uLong b; /* bit buffer */
+ uInt k; /* bits in bit buffer */
+ Bytef *p; /* input data pointer */
+ uInt n; /* bytes available there */
+ Bytef *q; /* output window write pointer */
+ uInt m; /* bytes to end of window or read pointer */
+ Bytef *f; /* pointer to copy strings from */
+ inflate_codes_statef *c = s->sub.decode.codes; /* codes state */
+
+ /* copy input/output information to locals (UPDATE macro restores) */
+ LOAD
+
+ /* process input and output based on current state */
+ while (1) switch (c->mode)
+ { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+ case START: /* x: set up for LEN */
+#ifndef SLOW
+ if (m >= 258 && n >= 10)
+ {
+ UPDATE
+ r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
+ LOAD
+ if (r != Z_OK)
+ {
+ c->mode = r == Z_STREAM_END ? WASH : BADCODE;
+ break;
+ }
+ }
+#endif /* !SLOW */
+ c->sub.code.need = c->lbits;
+ c->sub.code.tree = c->ltree;
+ c->mode = LEN;
+ case LEN: /* i: get length/literal/eob next */
+ j = c->sub.code.need;
+ NEEDBITS(j)
+ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+ DUMPBITS(t->bits)
+ e = (uInt)(t->exop);
+ if (e == 0) /* literal */
+ {
+ c->sub.lit = t->base;
+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+ "inflate: literal '%c'\n" :
+ "inflate: literal 0x%02x\n", t->base));
+ c->mode = LIT;
+ break;
+ }
+ if (e & 16) /* length */
+ {
+ c->sub.copy.get = e & 15;
+ c->len = t->base;
+ c->mode = LENEXT;
+ break;
+ }
+ if ((e & 64) == 0) /* next table */
+ {
+ c->sub.code.need = e;
+ c->sub.code.tree = t->next;
+ break;
+ }
+ if (e & 32) /* end of block */
+ {
+ Tracevv((stderr, "inflate: end of block\n"));
+ c->mode = WASH;
+ break;
+ }
+ c->mode = BADCODE; /* invalid code */
+ z->msg = "invalid literal/length code";
+ r = Z_DATA_ERROR;
+ LEAVE
+ case LENEXT: /* i: getting length extra (have base) */
+ j = c->sub.copy.get;
+ NEEDBITS(j)
+ c->len += (uInt)b & inflate_mask[j];
+ DUMPBITS(j)
+ c->sub.code.need = c->dbits;
+ c->sub.code.tree = c->dtree;
+ Tracevv((stderr, "inflate: length %u\n", c->len));
+ c->mode = DIST;
+ case DIST: /* i: get distance next */
+ j = c->sub.code.need;
+ NEEDBITS(j)
+ t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+ DUMPBITS(t->bits)
+ e = (uInt)(t->exop);
+ if (e & 16) /* distance */
+ {
+ c->sub.copy.get = e & 15;
+ c->sub.copy.dist = t->base;
+ c->mode = DISTEXT;
+ break;
+ }
+ if ((e & 64) == 0) /* next table */
+ {
+ c->sub.code.need = e;
+ c->sub.code.tree = t->next;
+ break;
+ }
+ c->mode = BADCODE; /* invalid code */
+ z->msg = "invalid distance code";
+ r = Z_DATA_ERROR;
+ LEAVE
+ case DISTEXT: /* i: getting distance extra */
+ j = c->sub.copy.get;
+ NEEDBITS(j)
+ c->sub.copy.dist += (uInt)b & inflate_mask[j];
+ DUMPBITS(j)
+ Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist));
+ c->mode = COPY;
+ case COPY: /* o: copying bytes in window, waiting for space */
+#ifndef __TURBOC__ /* Turbo C bug for following expression */
+ f = (uInt)(q - s->window) < c->sub.copy.dist ?
+ s->end - (c->sub.copy.dist - (q - s->window)) :
+ q - c->sub.copy.dist;
+#else
+ f = q - c->sub.copy.dist;
+ if ((uInt)(q - s->window) < c->sub.copy.dist)
+ f = s->end - (c->sub.copy.dist - (q - s->window));
+#endif
+ while (c->len)
+ {
+ NEEDOUT
+ OUTBYTE(*f++)
+ if (f == s->end)
+ f = s->window;
+ c->len--;
+ }
+ c->mode = START;
+ break;
+ case LIT: /* o: got literal, waiting for output space */
+ NEEDOUT
+ OUTBYTE(c->sub.lit)
+ c->mode = START;
+ break;
+ case WASH: /* o: got eob, possibly more output */
+ FLUSH
+ if (s->read != s->write)
+ LEAVE
+ c->mode = END;
+ case END:
+ r = Z_STREAM_END;
+ LEAVE
+ case BADCODE: /* x: got error */
+ r = Z_DATA_ERROR;
+ LEAVE
+ default:
+ r = Z_STREAM_ERROR;
+ LEAVE
+ }
+}
+
+
+local void inflate_codes_free(c, z)
+inflate_codes_statef *c;
+z_stream *z;
+{
+ ZFREE(z, c, sizeof(struct inflate_codes_state));
+ Tracev((stderr, "inflate: codes free\n"));
+}
+
+/*+++++*/
+/* inflate_util.c -- data and routines common to blocks and codes
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* copy as much as possible from the sliding window to the output area */
+local int inflate_flush(s, z, r)
+inflate_blocks_statef *s;
+z_stream *z;
+int r;
+{
+ uInt n;
+ Bytef *p, *q;
+
+ /* local copies of source and destination pointers */
+ p = z->next_out;
+ q = s->read;
+
+ /* compute number of bytes to copy as far as end of window */
+ n = (uInt)((q <= s->write ? s->write : s->end) - q);
+ if (n > z->avail_out) n = z->avail_out;
+ if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+ /* update counters */
+ z->avail_out -= n;
+ z->total_out += n;
+
+ /* update check information */
+ if (s->checkfn != Z_NULL)
+ s->check = (*s->checkfn)(s->check, q, n);
+
+ /* copy as far as end of window */
+ zmemcpy(p, q, n);
+ p += n;
+ q += n;
+
+ /* see if more to copy at beginning of window */
+ if (q == s->end)
+ {
+ /* wrap pointers */
+ q = s->window;
+ if (s->write == s->end)
+ s->write = s->window;
+
+ /* compute bytes to copy */
+ n = (uInt)(s->write - q);
+ if (n > z->avail_out) n = z->avail_out;
+ if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+ /* update counters */
+ z->avail_out -= n;
+ z->total_out += n;
+
+ /* update check information */
+ if (s->checkfn != Z_NULL)
+ s->check = (*s->checkfn)(s->check, q, n);
+
+ /* copy */
+ zmemcpy(p, q, n);
+ p += n;
+ q += n;
+ }
+
+ /* update pointers */
+ z->next_out = p;
+ s->read = q;
+
+ /* done */
+ return r;
+}
+
+
+/*+++++*/
+/* inffast.c -- process literals and length/distance pairs fast
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define base more.Base
+#define next more.Next
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* macros for bit input with no checking and for returning unused bytes */
+#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define UNGRAB {n+=(c=k>>3);p-=c;k&=7;}
+
+/* Called with number of bytes left to write in window at least 258
+ (the maximum string length) and number of input bytes available
+ at least ten. The ten bytes are six bytes for the longest length/
+ distance pair plus four bytes for overloading the bit buffer. */
+
+local int inflate_fast(bl, bd, tl, td, s, z)
+uInt bl, bd;
+inflate_huft *tl, *td;
+inflate_blocks_statef *s;
+z_stream *z;
+{
+ inflate_huft *t; /* temporary pointer */
+ uInt e; /* extra bits or operation */
+ uLong b; /* bit buffer */
+ uInt k; /* bits in bit buffer */
+ Bytef *p; /* input data pointer */
+ uInt n; /* bytes available there */
+ Bytef *q; /* output window write pointer */
+ uInt m; /* bytes to end of window or read pointer */
+ uInt ml; /* mask for literal/length tree */
+ uInt md; /* mask for distance tree */
+ uInt c; /* bytes to copy */
+ uInt d; /* distance back to copy from */
+ Bytef *r; /* copy source pointer */
+
+ /* load input, output, bit values */
+ LOAD
+
+ /* initialize masks */
+ ml = inflate_mask[bl];
+ md = inflate_mask[bd];
+
+ /* do until not enough input or output space for fast loop */
+ do { /* assume called with m >= 258 && n >= 10 */
+ /* get literal/length code */
+ GRABBITS(20) /* max bits for literal/length code */
+ if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
+ {
+ DUMPBITS(t->bits)
+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+ "inflate: * literal '%c'\n" :
+ "inflate: * literal 0x%02x\n", t->base));
+ *q++ = (Byte)t->base;
+ m--;
+ continue;
+ }
+ do {
+ DUMPBITS(t->bits)
+ if (e & 16)
+ {
+ /* get extra bits for length */
+ e &= 15;
+ c = t->base + ((uInt)b & inflate_mask[e]);
+ DUMPBITS(e)
+ Tracevv((stderr, "inflate: * length %u\n", c));
+
+ /* decode distance base of block to copy */
+ GRABBITS(15); /* max bits for distance code */
+ e = (t = td + ((uInt)b & md))->exop;
+ do {
+ DUMPBITS(t->bits)
+ if (e & 16)
+ {
+ /* get extra bits to add to distance base */
+ e &= 15;
+ GRABBITS(e) /* get extra bits (up to 13) */
+ d = t->base + ((uInt)b & inflate_mask[e]);
+ DUMPBITS(e)
+ Tracevv((stderr, "inflate: * distance %u\n", d));
+
+ /* do the copy */
+ m -= c;
+ if ((uInt)(q - s->window) >= d) /* offset before dest */
+ { /* just copy */
+ r = q - d;
+ *q++ = *r++; c--; /* minimum count is three, */
+ *q++ = *r++; c--; /* so unroll loop a little */
+ }
+ else /* else offset after destination */
+ {
+ e = d - (q - s->window); /* bytes from offset to end */
+ r = s->end - e; /* pointer to offset */
+ if (c > e) /* if source crosses, */
+ {
+ c -= e; /* copy to end of window */
+ do {
+ *q++ = *r++;
+ } while (--e);
+ r = s->window; /* copy rest from start of window */
+ }
+ }
+ do { /* copy all or what's left */
+ *q++ = *r++;
+ } while (--c);
+ break;
+ }
+ else if ((e & 64) == 0)
+ e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop;
+ else
+ {
+ z->msg = "invalid distance code";
+ UNGRAB
+ UPDATE
+ return Z_DATA_ERROR;
+ }
+ } while (1);
+ break;
+ }
+ if ((e & 64) == 0)
+ {
+ if ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) == 0)
+ {
+ DUMPBITS(t->bits)
+ Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+ "inflate: * literal '%c'\n" :
+ "inflate: * literal 0x%02x\n", t->base));
+ *q++ = (Byte)t->base;
+ m--;
+ break;
+ }
+ }
+ else if (e & 32)
+ {
+ Tracevv((stderr, "inflate: * end of block\n"));
+ UNGRAB
+ UPDATE
+ return Z_STREAM_END;
+ }
+ else
+ {
+ z->msg = "invalid literal/length code";
+ UNGRAB
+ UPDATE
+ return Z_DATA_ERROR;
+ }
+ } while (1);
+ } while (m >= 258 && n >= 10);
+
+ /* not enough input or output--restore pointers and return */
+ UNGRAB
+ UPDATE
+ return Z_OK;
+}
+
+
+/*+++++*/
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* From: zutil.c,v 1.8 1995/05/03 17:27:12 jloup Exp */
+
+char *zlib_version = ZLIB_VERSION;
+
+char *z_errmsg[] = {
+"stream end", /* Z_STREAM_END 1 */
+"", /* Z_OK 0 */
+"file error", /* Z_ERRNO (-1) */
+"stream error", /* Z_STREAM_ERROR (-2) */
+"data error", /* Z_DATA_ERROR (-3) */
+"insufficient memory", /* Z_MEM_ERROR (-4) */
+"buffer error", /* Z_BUF_ERROR (-5) */
+""};
+
+
+/*+++++*/
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* From: adler32.c,v 1.6 1995/05/03 17:27:08 jloup Exp */
+
+#define BASE 65521L /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf) {s1 += *buf++; s2 += s1;}
+#define DO2(buf) DO1(buf); DO1(buf);
+#define DO4(buf) DO2(buf); DO2(buf);
+#define DO8(buf) DO4(buf); DO4(buf);
+#define DO16(buf) DO8(buf); DO8(buf);
+
+/* ========================================================================= */
+uLong adler32(adler, buf, len)
+ uLong adler;
+ Bytef *buf;
+ uInt len;
+{
+ unsigned long s1 = adler & 0xffff;
+ unsigned long s2 = (adler >> 16) & 0xffff;
+ int k;
+
+ if (buf == Z_NULL) return 1L;
+
+ while (len > 0) {
+ k = len < NMAX ? len : NMAX;
+ len -= k;
+ while (k >= 16) {
+ DO16(buf);
+ k -= 16;
+ }
+ if (k != 0) do {
+ DO1(buf);
+ } while (--k);
+ s1 %= BASE;
+ s2 %= BASE;
+ }
+ return (s2 << 16) | s1;
+}
diff --git a/arch/xtensa/boot/lib/zmem.c b/arch/xtensa/boot/lib/zmem.c
new file mode 100644
index 00000000000..7848f126d67
--- /dev/null
+++ b/arch/xtensa/boot/lib/zmem.c
@@ -0,0 +1,87 @@
+#include "zlib.h"
+
+/* bits taken from ppc */
+
+extern void *avail_ram, *end_avail;
+
+void exit (void)
+{
+ for (;;);
+}
+
+void *zalloc(void *x, unsigned items, unsigned size)
+{
+ void *p = avail_ram;
+
+ size *= items;
+ size = (size + 7) & -8;
+ avail_ram += size;
+ if (avail_ram > end_avail) {
+ //puts("oops... out of memory\n");
+ //pause();
+ exit ();
+ }
+ return p;
+}
+
+void zfree(void *x, void *addr, unsigned nb)
+{
+}
+
+
+#define HEAD_CRC 2
+#define EXTRA_FIELD 4
+#define ORIG_NAME 8
+#define COMMENT 0x10
+#define RESERVED 0xe0
+
+#define DEFLATED 8
+
+void gunzip (void *dst, int dstlen, unsigned char *src, int *lenp)
+{
+ z_stream s;
+ int r, i, flags;
+
+ /* skip header */
+
+ i = 10;
+ flags = src[3];
+ if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
+ //puts("bad gzipped data\n");
+ exit();
+ }
+ if ((flags & EXTRA_FIELD) != 0)
+ i = 12 + src[10] + (src[11] << 8);
+ if ((flags & ORIG_NAME) != 0)
+ while (src[i++] != 0)
+ ;
+ if ((flags & COMMENT) != 0)
+ while (src[i++] != 0)
+ ;
+ if ((flags & HEAD_CRC) != 0)
+ i += 2;
+ if (i >= *lenp) {
+ //puts("gunzip: ran out of data in header\n");
+ exit();
+ }
+
+ s.zalloc = zalloc;
+ s.zfree = zfree;
+ r = inflateInit2(&s, -MAX_WBITS);
+ if (r != Z_OK) {
+ //puts("inflateInit2 returned "); puthex(r); puts("\n");
+ exit();
+ }
+ s.next_in = src + i;
+ s.avail_in = *lenp - i;
+ s.next_out = dst;
+ s.avail_out = dstlen;
+ r = inflate(&s, Z_FINISH);
+ if (r != Z_OK && r != Z_STREAM_END) {
+ //puts("inflate returned "); puthex(r); puts("\n");
+ exit();
+ }
+ *lenp = s.next_out - (unsigned char *) dst;
+ inflateEnd(&s);
+}
+
diff --git a/arch/xtensa/boot/ramdisk/Makefile b/arch/xtensa/boot/ramdisk/Makefile
new file mode 100644
index 00000000000..b12f7635243
--- /dev/null
+++ b/arch/xtensa/boot/ramdisk/Makefile
@@ -0,0 +1,23 @@
+#
+# Makefile for a ramdisk image
+#
+
+BIG_ENDIAN := $(shell echo -e "\#ifdef __XTENSA_EL__\nint little;\n\#else\nint big;\n\#endif" | $(CC) -E -|grep -c big)
+
+ifeq ($(BIG_ENDIAN),1)
+OBJCOPY_ARGS := -O elf32-xtensa-be
+else
+OBJCOPY_ARGS := -O elf32-xtensa-le
+endif
+
+obj-y = ramdisk.o
+
+RAMDISK_IMAGE = arch/$(ARCH)/boot/ramdisk/$(CONFIG_EMBEDDED_RAMDISK_IMAGE)
+
+arch/$(ARCH)/boot/ramdisk/ramdisk.o:
+ $(Q)echo -e "dummy:" | $(AS) -o $@;
+ $(Q)$(OBJCOPY) $(OBJCOPY_ARGS) \
+ --add-section .initrd=$(RAMDISK_IMAGE) \
+ --set-section-flags .initrd=contents,alloc,load,load,data \
+ arch/$(ARCH)/boot/ramdisk/ramdisk.o $@
+
diff --git a/arch/xtensa/configs/common_defconfig b/arch/xtensa/configs/common_defconfig
new file mode 100644
index 00000000000..1d230ee081b
--- /dev/null
+++ b/arch/xtensa/configs/common_defconfig
@@ -0,0 +1,662 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Tue Mar 1 16:36:53 2005
+#
+# CONFIG_FRAME_POINTER is not set
+CONFIG_XTENSA=y
+# CONFIG_UID16 is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Processor type and features
+#
+CONFIG_XTENSA_ARCH_LINUX_BE=y
+# CONFIG_XTENSA_ARCH_LINUX_LE is not set
+# CONFIG_XTENSA_ARCH_LINUX_TEST is not set
+# CONFIG_XTENSA_ARCH_S5 is not set
+# CONFIG_XTENSA_CUSTOM is not set
+CONFIG_MMU=y
+# CONFIG_XTENSA_UNALIGNED_USER is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_HIGHMEM is not set
+
+#
+# Platform options
+#
+# CONFIG_XTENSA_PLATFORM_ISS is not set
+CONFIG_XTENSA_PLATFORM_XT2000=y
+CONFIG_XTENSA_CALIBRATE_CCOUNT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,38400 ip=bootp root=nfs nfsroot=/opt/montavista/pro/devkit/xtensa/linux_be/target"
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_NAMES is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Exectuable file formats
+#
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# CONFIG_NET_SCH_CLK_CPU is not set
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+# CONFIG_NET_SCH_HFSC is not set
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+# CONFIG_NET_SCH_NETEM is not set
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_QOS=y
+CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_CLS=y
+CONFIG_NET_CLS_TCINDEX=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_ROUTE=y
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+# CONFIG_CLS_U32_PERF is not set
+# CONFIG_NET_CLS_IND is not set
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_POLICE=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_XT2000_SONIC=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+# CONFIG_NET_TULIP is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_PCI is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+CONFIG_NET_RADIO=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+CONFIG_STRIP=m
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_HERMES=m
+# CONFIG_PLX_HERMES is not set
+# CONFIG_TMD_HERMES is not set
+# CONFIG_PCI_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+# CONFIG_PRISM54 is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/xtensa/configs/iss_defconfig b/arch/xtensa/configs/iss_defconfig
new file mode 100644
index 00000000000..802621dd486
--- /dev/null
+++ b/arch/xtensa/configs/iss_defconfig
@@ -0,0 +1,531 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Fri Feb 25 19:21:24 2005
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_XTENSA=y
+# CONFIG_UID16 is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_KOBJECT_UEVENT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Processor type and features
+#
+CONFIG_XTENSA_ARCH_LINUX_BE=y
+# CONFIG_XTENSA_ARCH_LINUX_LE is not set
+# CONFIG_XTENSA_ARCH_LINUX_TEST is not set
+# CONFIG_XTENSA_ARCH_S5 is not set
+# CONFIG_XTENSA_CUSTOM is not set
+CONFIG_MMU=y
+# CONFIG_XTENSA_UNALIGNED_USER is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_HIGHMEM is not set
+
+#
+# Platform options
+#
+CONFIG_XTENSA_PLATFORM_ISS=y
+# CONFIG_XTENSA_PLATFORM_XT2000 is not set
+# CONFIG_XTENSA_PLATFORM_ARUBA is not set
+# CONFIG_XTENSA_CALIBRATE_CCOUNT is not set
+CONFIG_XTENSA_CPU_CLOCK=10
+# CONFIG_GENERIC_CALIBRATE_DELAY is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,38400 eth0=tuntap,,tap0 ip=192.168.168.5:192.168.168.1 root=nfs nfsroot=192.168.168.1:/opt/montavista/pro/devkit/xtensa/linux_be/target"
+CONFIG_SERIAL_CONSOLE=y
+CONFIG_XTENSA_ISS_NETWORK=y
+
+#
+# Bus options
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Exectuable file formats
+#
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+# CONFIG_SCTP_HMAC_MD5 is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_SCH_CLK_JIFFIES is not set
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# CONFIG_NET_SCH_CLK_CPU is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_NETDEVICES is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+CONFIG_SOFT_WATCHDOG=y
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+CONFIG_NFS_DIRECTIO=y
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
new file mode 100644
index 00000000000..d573017a5dd
--- /dev/null
+++ b/arch/xtensa/kernel/Makefile
@@ -0,0 +1,18 @@
+#
+# Makefile for the Linux/Xtensa kernel.
+#
+
+extra-y := head.o vmlinux.lds
+
+
+obj-y := align.o entry.o irq.o coprocessor.o process.o ptrace.o semaphore.o \
+ setup.o signal.o syscalls.o time.o traps.o vectors.o platform.o \
+ pci-dma.o
+
+## windowspill.o
+
+obj-$(CONFIG_KGDB) += xtensa-stub.o
+obj-$(CONFIG_PCI) += pci.o
+obj-$(CONFIG_MODULES) += xtensa_ksyms.o module.o
+
+
diff --git a/arch/xtensa/kernel/align.S b/arch/xtensa/kernel/align.S
new file mode 100644
index 00000000000..74b1e90ef08
--- /dev/null
+++ b/arch/xtensa/kernel/align.S
@@ -0,0 +1,459 @@
+/*
+ * arch/xtensa/kernel/align.S
+ *
+ * Handle unalignment exceptions in kernel space.
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica, Inc.
+ *
+ * Rewritten by Chris Zankel <chris@zankel.net>
+ *
+ * Based on work from Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
+ * and Marc Gauthier <marc@tensilica.com, marc@alimni.uwaterloo.ca>
+ */
+
+#include <linux/linkage.h>
+#include <asm/ptrace.h>
+#include <asm/ptrace.h>
+#include <asm/current.h>
+#include <asm/offsets.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/thread_info.h>
+
+#if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
+
+/* First-level exception handler for unaligned exceptions.
+ *
+ * Note: This handler works only for kernel exceptions. Unaligned user
+ * access should get a seg fault.
+ */
+
+/* Big and little endian 16-bit values are located in
+ * different halves of a register. HWORD_START helps to
+ * abstract the notion of extracting a 16-bit value from a
+ * register.
+ * We also have to define new shifting instructions because
+ * lsb and msb are on 'opposite' ends in a register for
+ * different endian machines.
+ *
+ * Assume a memory region in ascending address:
+ * 0 1 2 3|4 5 6 7
+ *
+ * When loading one word into a register, the content of that register is:
+ * LE 3 2 1 0, 7 6 5 4
+ * BE 0 1 2 3, 4 5 6 7
+ *
+ * Masking the bits of the higher/lower address means:
+ * LE X X 0 0, 0 0 X X
+ * BE 0 0 X X, X X 0 0
+ *
+ * Shifting to higher/lower addresses, means:
+ * LE shift left / shift right
+ * BE shift right / shift left
+ *
+ * Extracting 16 bits from a 32 bit reg. value to higher/lower address means:
+ * LE mask 0 0 X X / shift left
+ * BE shift left / mask 0 0 X X
+ */
+
+#define UNALIGNED_USER_EXCEPTION
+
+#if XCHAL_HAVE_BE
+
+#define HWORD_START 16
+#define INSN_OP0 28
+#define INSN_T 24
+#define INSN_OP1 16
+
+.macro __src_b r, w0, w1; src \r, \w0, \w1; .endm
+.macro __ssa8 r; ssa8b \r; .endm
+.macro __ssa8r r; ssa8l \r; .endm
+.macro __sh r, s; srl \r, \s; .endm
+.macro __sl r, s; sll \r, \s; .endm
+.macro __exth r, s; extui \r, \s, 0, 16; .endm
+.macro __extl r, s; slli \r, \s, 16; .endm
+
+#else
+
+#define HWORD_START 0
+#define INSN_OP0 0
+#define INSN_T 4
+#define INSN_OP1 12
+
+.macro __src_b r, w0, w1; src \r, \w1, \w0; .endm
+.macro __ssa8 r; ssa8l \r; .endm
+.macro __ssa8r r; ssa8b \r; .endm
+.macro __sh r, s; sll \r, \s; .endm
+.macro __sl r, s; srl \r, \s; .endm
+.macro __exth r, s; slli \r, \s, 16; .endm
+.macro __extl r, s; extui \r, \s, 0, 16; .endm
+
+#endif
+
+/*
+ * xxxx xxxx = imm8 field
+ * yyyy = imm4 field
+ * ssss = s field
+ * tttt = t field
+ *
+ * 16 0
+ * -------------------
+ * L32I.N yyyy ssss tttt 1000
+ * S32I.N yyyy ssss tttt 1001
+ *
+ * 23 0
+ * -----------------------------
+ * res 0000 0010
+ * L16UI xxxx xxxx 0001 ssss tttt 0010
+ * L32I xxxx xxxx 0010 ssss tttt 0010
+ * XXX 0011 ssss tttt 0010
+ * XXX 0100 ssss tttt 0010
+ * S16I xxxx xxxx 0101 ssss tttt 0010
+ * S32I xxxx xxxx 0110 ssss tttt 0010
+ * XXX 0111 ssss tttt 0010
+ * XXX 1000 ssss tttt 0010
+ * L16SI xxxx xxxx 1001 ssss tttt 0010
+ * XXX 1010 0010
+ * **L32AI xxxx xxxx 1011 ssss tttt 0010 unsupported
+ * XXX 1100 0010
+ * XXX 1101 0010
+ * XXX 1110 0010
+ * **S32RI xxxx xxxx 1111 ssss tttt 0010 unsupported
+ * -----------------------------
+ * ^ ^ ^
+ * sub-opcode (NIBBLE_R) -+ | |
+ * t field (NIBBLE_T) -----------+ |
+ * major opcode (NIBBLE_OP0) --------------+
+ */
+
+#define OP0_L32I_N 0x8 /* load immediate narrow */
+#define OP0_S32I_N 0x9 /* store immediate narrow */
+#define OP1_SI_MASK 0x4 /* OP1 bit set for stores */
+#define OP1_SI_BIT 2 /* OP1 bit number for stores */
+
+#define OP1_L32I 0x2
+#define OP1_L16UI 0x1
+#define OP1_L16SI 0x9
+#define OP1_L32AI 0xb
+
+#define OP1_S32I 0x6
+#define OP1_S16I 0x5
+#define OP1_S32RI 0xf
+
+/*
+ * Entry condition:
+ *
+ * a0: trashed, original value saved on stack (PT_AREG0)
+ * a1: a1
+ * a2: new stack pointer, original in DEPC
+ * a3: dispatch table
+ * depc: a2, original value saved on stack (PT_DEPC)
+ * excsave_1: a3
+ *
+ * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
+ * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
+ */
+
+
+ENTRY(fast_unaligned)
+
+ /* Note: We don't expect the address to be aligned on a word
+ * boundary. After all, the processor generated that exception
+ * and it would be a hardware fault.
+ */
+
+ /* Save some working register */
+
+ s32i a4, a2, PT_AREG4
+ s32i a5, a2, PT_AREG5
+ s32i a6, a2, PT_AREG6
+ s32i a7, a2, PT_AREG7
+ s32i a8, a2, PT_AREG8
+
+ rsr a0, DEPC
+ xsr a3, EXCSAVE_1
+ s32i a0, a2, PT_AREG2
+ s32i a3, a2, PT_AREG3
+
+ /* Keep value of SAR in a0 */
+
+ rsr a0, SAR
+ rsr a8, EXCVADDR # load unaligned memory address
+
+ /* Now, identify one of the following load/store instructions.
+ *
+ * The only possible danger of a double exception on the
+ * following l32i instructions is kernel code in vmalloc
+ * memory. The processor was just executing at the EPC_1
+ * address, and indeed, already fetched the instruction. That
+ * guarantees a TLB mapping, which hasn't been replaced by
+ * this unaligned exception handler that uses only static TLB
+ * mappings. However, high-level interrupt handlers might
+ * modify TLB entries, so for the generic case, we register a
+ * TABLE_FIXUP handler here, too.
+ */
+
+ /* a3...a6 saved on stack, a2 = SP */
+
+ /* Extract the instruction that caused the unaligned access. */
+
+ rsr a7, EPC_1 # load exception address
+ movi a3, ~3
+ and a3, a3, a7 # mask lower bits
+
+ l32i a4, a3, 0 # load 2 words
+ l32i a5, a3, 4
+
+ __ssa8 a7
+ __src_b a4, a4, a5 # a4 has the instruction
+
+ /* Analyze the instruction (load or store?). */
+
+ extui a5, a4, INSN_OP0, 4 # get insn.op0 nibble
+
+#if XCHAL_HAVE_NARROW
+ _beqi a5, OP0_L32I_N, .Lload # L32I.N, jump
+ addi a6, a5, -OP0_S32I_N
+ _beqz a6, .Lstore # S32I.N, do a store
+#endif
+ /* 'store indicator bit' not set, jump */
+ _bbci.l a4, OP1_SI_BIT + INSN_OP1, .Lload
+
+ /* Store: Jump to table entry to get the value in the source register.*/
+
+.Lstore:movi a5, .Lstore_table # table
+ extui a6, a4, INSN_T, 4 # get source register
+ addx8 a5, a6, a5
+ jx a5 # jump into table
+
+ /* Invalid instruction, CRITICAL! */
+.Linvalid_instruction_load:
+ j .Linvalid_instruction
+
+ /* Load: Load memory address. */
+
+.Lload: movi a3, ~3
+ and a3, a3, a8 # align memory address
+
+ __ssa8 a8
+#ifdef UNALIGNED_USER_EXCEPTION
+ addi a3, a3, 8
+ l32e a5, a3, -8
+ l32e a6, a3, -4
+#else
+ l32i a5, a3, 0
+ l32i a6, a3, 4
+#endif
+ __src_b a3, a5, a6 # a3 has the data word
+
+#if XCHAL_HAVE_NARROW
+ addi a7, a7, 2 # increment PC (assume 16-bit insn)
+
+ extui a5, a4, INSN_OP0, 4
+ _beqi a5, OP0_L32I_N, 1f # l32i.n: jump
+
+ addi a7, a7, 1
+#else
+ addi a7, a7, 3
+#endif
+
+ extui a5, a4, INSN_OP1, 4
+ _beqi a5, OP1_L32I, 1f # l32i: jump
+
+ extui a3, a3, 0, 16 # extract lower 16 bits
+ _beqi a5, OP1_L16UI, 1f
+ addi a5, a5, -OP1_L16SI
+ _bnez a5, .Linvalid_instruction_load
+
+ /* sign extend value */
+
+ slli a3, a3, 16
+ srai a3, a3, 16
+
+ /* Set target register. */
+
+1:
+
+#if XCHAL_HAVE_LOOP
+ rsr a3, LEND # check if we reached LEND
+ bne a7, a3, 1f
+ rsr a3, LCOUNT # and LCOUNT != 0
+ beqz a3, 1f
+ addi a3, a3, -1 # decrement LCOUNT and set
+ rsr a7, LBEG # set PC to LBEGIN
+ wsr a3, LCOUNT
+#endif
+
+1: wsr a7, EPC_1 # skip load instruction
+ extui a4, a4, INSN_T, 4 # extract target register
+ movi a5, .Lload_table
+ addx8 a4, a4, a5
+ jx a4 # jump to entry for target register
+
+ .align 8
+.Lload_table:
+ s32i a3, a2, PT_AREG0; _j .Lexit; .align 8
+ mov a1, a3; _j .Lexit; .align 8 # fishy??
+ s32i a3, a2, PT_AREG2; _j .Lexit; .align 8
+ s32i a3, a2, PT_AREG3; _j .Lexit; .align 8
+ s32i a3, a2, PT_AREG4; _j .Lexit; .align 8
+ s32i a3, a2, PT_AREG5; _j .Lexit; .align 8
+ s32i a3, a2, PT_AREG6; _j .Lexit; .align 8
+ s32i a3, a2, PT_AREG7; _j .Lexit; .align 8
+ s32i a3, a2, PT_AREG8; _j .Lexit; .align 8
+ mov a9, a3 ; _j .Lexit; .align 8
+ mov a10, a3 ; _j .Lexit; .align 8
+ mov a11, a3 ; _j .Lexit; .align 8
+ mov a12, a3 ; _j .Lexit; .align 8
+ mov a13, a3 ; _j .Lexit; .align 8
+ mov a14, a3 ; _j .Lexit; .align 8
+ mov a15, a3 ; _j .Lexit; .align 8
+
+.Lstore_table:
+ l32i a3, a2, PT_AREG0; _j 1f; .align 8
+ mov a3, a1; _j 1f; .align 8 # fishy??
+ l32i a3, a2, PT_AREG2; _j 1f; .align 8
+ l32i a3, a2, PT_AREG3; _j 1f; .align 8
+ l32i a3, a2, PT_AREG4; _j 1f; .align 8
+ l32i a3, a2, PT_AREG5; _j 1f; .align 8
+ l32i a3, a2, PT_AREG6; _j 1f; .align 8
+ l32i a3, a2, PT_AREG7; _j 1f; .align 8
+ l32i a3, a2, PT_AREG8; _j 1f; .align 8
+ mov a3, a9 ; _j 1f; .align 8
+ mov a3, a10 ; _j 1f; .align 8
+ mov a3, a11 ; _j 1f; .align 8
+ mov a3, a12 ; _j 1f; .align 8
+ mov a3, a13 ; _j 1f; .align 8
+ mov a3, a14 ; _j 1f; .align 8
+ mov a3, a15 ; _j 1f; .align 8
+
+1: # a7: instruction pointer, a4: instruction, a3: value
+
+ movi a6, 0 # mask: ffffffff:00000000
+
+#if XCHAL_HAVE_NARROW
+ addi a7, a7, 2 # incr. PC,assume 16-bit instruction
+
+ extui a5, a4, INSN_OP0, 4 # extract OP0
+ addi a5, a5, -OP0_S32I_N
+ _beqz a5, 1f # s32i.n: jump
+
+ addi a7, a7, 1 # increment PC, 32-bit instruction
+#else
+ addi a7, a7, 3 # increment PC, 32-bit instruction
+#endif
+
+ extui a5, a4, INSN_OP1, 4 # extract OP1
+ _beqi a5, OP1_S32I, 1f # jump if 32 bit store
+ _bnei a5, OP1_S16I, .Linvalid_instruction_store
+
+ movi a5, -1
+ __extl a3, a3 # get 16-bit value
+ __exth a6, a5 # get 16-bit mask ffffffff:ffff0000
+
+ /* Get memory address */
+
+1:
+#if XCHAL_HAVE_LOOP
+ rsr a3, LEND # check if we reached LEND
+ bne a7, a3, 1f
+ rsr a3, LCOUNT # and LCOUNT != 0
+ beqz a3, 1f
+ addi a3, a3, -1 # decrement LCOUNT and set
+ rsr a7, LBEG # set PC to LBEGIN
+ wsr a3, LCOUNT
+#endif
+
+1: wsr a7, EPC_1 # skip store instruction
+ movi a4, ~3
+ and a4, a4, a8 # align memory address
+
+ /* Insert value into memory */
+
+ movi a5, -1 # mask: ffffffff:XXXX0000
+#ifdef UNALIGNED_USER_EXCEPTION
+ addi a4, a4, 8
+#endif
+
+ __ssa8r a8
+ __src_b a7, a5, a6 # lo-mask F..F0..0 (BE) 0..0F..F (LE)
+ __src_b a6, a6, a5 # hi-mask 0..0F..F (BE) F..F0..0 (LE)
+#ifdef UNALIGNED_USER_EXCEPTION
+ l32e a5, a4, -8
+#else
+ l32i a5, a4, 0 # load lower address word
+#endif
+ and a5, a5, a7 # mask
+ __sh a7, a3 # shift value
+ or a5, a5, a7 # or with original value
+#ifdef UNALIGNED_USER_EXCEPTION
+ s32e a5, a4, -8
+ l32e a7, a4, -4
+#else
+ s32i a5, a4, 0 # store
+ l32i a7, a4, 4 # same for upper address word
+#endif
+ __sl a5, a3
+ and a6, a7, a6
+ or a6, a6, a5
+#ifdef UNALIGNED_USER_EXCEPTION
+ s32e a6, a4, -4
+#else
+ s32i a6, a4, 4
+#endif
+
+ /* Done. restore stack and return */
+
+.Lexit:
+ movi a4, 0
+ rsr a3, EXCSAVE_1
+ s32i a4, a3, EXC_TABLE_FIXUP
+
+ /* Restore working register */
+
+ l32i a7, a2, PT_AREG7
+ l32i a6, a2, PT_AREG6
+ l32i a5, a2, PT_AREG5
+ l32i a4, a2, PT_AREG4
+ l32i a3, a2, PT_AREG3
+
+ /* restore SAR and return */
+
+ wsr a0, SAR
+ l32i a0, a2, PT_AREG0
+ l32i a2, a2, PT_AREG2
+ rfe
+
+ /* We cannot handle this exception. */
+
+ .extern _kernel_exception
+.Linvalid_instruction_store:
+.Linvalid_instruction:
+
+ /* Restore a4...a8 and SAR, set SP, and jump to default exception. */
+
+ l32i a8, a2, PT_AREG8
+ l32i a7, a2, PT_AREG7
+ l32i a6, a2, PT_AREG6
+ l32i a5, a2, PT_AREG5
+ l32i a4, a2, PT_AREG4
+ wsr a0, SAR
+ mov a1, a2
+
+ rsr a0, PS
+ bbsi.l a2, PS_UM_SHIFT, 1f # jump if user mode
+
+ movi a0, _kernel_exception
+ jx a0
+
+1: movi a0, _user_exception
+ jx a0
+
+
+#endif /* XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION */
+
diff --git a/arch/xtensa/kernel/asm-offsets.c b/arch/xtensa/kernel/asm-offsets.c
new file mode 100644
index 00000000000..840cd9a1d3d
--- /dev/null
+++ b/arch/xtensa/kernel/asm-offsets.c
@@ -0,0 +1,94 @@
+/*
+ * arch/xtensa/kernel/asm-offsets.c
+ *
+ * Generates definitions from c-type structures used by assembly sources.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2005 Tensilica Inc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ */
+
+#include <asm/processor.h>
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/stddef.h>
+#include <linux/thread_info.h>
+#include <linux/ptrace.h>
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+
+#define DEFINE(sym, val) asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+#define BLANK() asm volatile("\n->" : : )
+
+int main(void)
+{
+ /* struct pt_regs */
+ DEFINE(PT_PC, offsetof (struct pt_regs, pc));
+ DEFINE(PT_PS, offsetof (struct pt_regs, ps));
+ DEFINE(PT_DEPC, offsetof (struct pt_regs, depc));
+ DEFINE(PT_EXCCAUSE, offsetof (struct pt_regs, exccause));
+ DEFINE(PT_EXCVADDR, offsetof (struct pt_regs, excvaddr));
+ DEFINE(PT_DEBUGCAUSE, offsetof (struct pt_regs, debugcause));
+ DEFINE(PT_WMASK, offsetof (struct pt_regs, wmask));
+ DEFINE(PT_LBEG, offsetof (struct pt_regs, lbeg));
+ DEFINE(PT_LEND, offsetof (struct pt_regs, lend));
+ DEFINE(PT_LCOUNT, offsetof (struct pt_regs, lcount));
+ DEFINE(PT_SAR, offsetof (struct pt_regs, sar));
+ DEFINE(PT_SYSCALL, offsetof (struct pt_regs, syscall));
+ DEFINE(PT_AREG, offsetof (struct pt_regs, areg[0]));
+ DEFINE(PT_AREG0, offsetof (struct pt_regs, areg[0]));
+ DEFINE(PT_AREG1, offsetof (struct pt_regs, areg[1]));
+ DEFINE(PT_AREG2, offsetof (struct pt_regs, areg[2]));
+ DEFINE(PT_AREG3, offsetof (struct pt_regs, areg[3]));
+ DEFINE(PT_AREG4, offsetof (struct pt_regs, areg[4]));
+ DEFINE(PT_AREG5, offsetof (struct pt_regs, areg[5]));
+ DEFINE(PT_AREG6, offsetof (struct pt_regs, areg[6]));
+ DEFINE(PT_AREG7, offsetof (struct pt_regs, areg[7]));
+ DEFINE(PT_AREG8, offsetof (struct pt_regs, areg[8]));
+ DEFINE(PT_AREG9, offsetof (struct pt_regs, areg[9]));
+ DEFINE(PT_AREG10, offsetof (struct pt_regs, areg[10]));
+ DEFINE(PT_AREG11, offsetof (struct pt_regs, areg[11]));
+ DEFINE(PT_AREG12, offsetof (struct pt_regs, areg[12]));
+ DEFINE(PT_AREG13, offsetof (struct pt_regs, areg[13]));
+ DEFINE(PT_AREG14, offsetof (struct pt_regs, areg[14]));
+ DEFINE(PT_AREG15, offsetof (struct pt_regs, areg[15]));
+ DEFINE(PT_WINDOWBASE, offsetof (struct pt_regs, windowbase));
+ DEFINE(PT_WINDOWSTART, offsetof(struct pt_regs, windowstart));
+ DEFINE(PT_SIZE, sizeof(struct pt_regs));
+ DEFINE(PT_AREG_END, offsetof (struct pt_regs, areg[XCHAL_NUM_AREGS]));
+ DEFINE(PT_USER_SIZE, offsetof(struct pt_regs, areg[XCHAL_NUM_AREGS]));
+ BLANK();
+
+ /* struct task_struct */
+ DEFINE(TASK_PTRACE, offsetof (struct task_struct, ptrace));
+ DEFINE(TASK_MM, offsetof (struct task_struct, mm));
+ DEFINE(TASK_ACTIVE_MM, offsetof (struct task_struct, active_mm));
+ DEFINE(TASK_PID, offsetof (struct task_struct, pid));
+ DEFINE(TASK_THREAD, offsetof (struct task_struct, thread));
+ DEFINE(TASK_THREAD_INFO, offsetof (struct task_struct, thread_info));
+ DEFINE(TASK_STRUCT_SIZE, sizeof (struct task_struct));
+ BLANK();
+
+ /* struct thread_info (offset from start_struct) */
+ DEFINE(THREAD_RA, offsetof (struct task_struct, thread.ra));
+ DEFINE(THREAD_SP, offsetof (struct task_struct, thread.sp));
+ DEFINE(THREAD_CP_SAVE, offsetof (struct task_struct, thread.cp_save));
+ DEFINE(THREAD_CURRENT_DS, offsetof (struct task_struct, thread.current_ds));
+ BLANK();
+
+ /* struct mm_struct */
+ DEFINE(MM_USERS, offsetof(struct mm_struct, mm_users));
+ DEFINE(MM_PGD, offsetof (struct mm_struct, pgd));
+ DEFINE(MM_CONTEXT, offsetof (struct mm_struct, context));
+ BLANK();
+ DEFINE(PT_SINGLESTEP_BIT, PT_SINGLESTEP_BIT);
+ return 0;
+}
+
+
diff --git a/arch/xtensa/kernel/coprocessor.S b/arch/xtensa/kernel/coprocessor.S
new file mode 100644
index 00000000000..356192a4d39
--- /dev/null
+++ b/arch/xtensa/kernel/coprocessor.S
@@ -0,0 +1,201 @@
+/*
+ * arch/xtensa/kernel/coprocessor.S
+ *
+ * Xtensa processor configuration-specific table of coprocessor and
+ * other custom register layout information.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 - 2005 Tensilica Inc.
+ *
+ * Marc Gauthier <marc@tensilica.com> <marc@alumni.uwaterloo.ca>
+ */
+
+/*
+ * This module contains a table that describes the layout of the various
+ * custom registers and states associated with each coprocessor, as well
+ * as those not associated with any coprocessor ("extra state").
+ * This table is included with core dumps and is available via the ptrace
+ * interface, allowing the layout of such register/state information to
+ * be modified in the kernel without affecting the debugger. Each
+ * register or state is identified using a 32-bit "libdb target number"
+ * assigned when the Xtensa processor is generated.
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/processor.h>
+
+#if XCHAL_HAVE_CP
+
+#define CP_LAST ((XCHAL_CP_MAX - 1) * COPROCESSOR_INFO_SIZE)
+
+ENTRY(release_coprocessors)
+
+ entry a1, 16
+ # a2: task
+ movi a3, 1 << XCHAL_CP_MAX # a3: coprocessor-bit
+ movi a4, coprocessor_info+CP_LAST # a4: owner-table
+ # a5: tmp
+ movi a6, 0 # a6: 0
+ rsil a7, LOCKLEVEL # a7: PS
+
+1: /* Check if task is coprocessor owner of coprocessor[i]. */
+
+ l32i a5, a4, COPROCESSOR_INFO_OWNER
+ srli a3, a3, 1
+ beqz a3, 1f
+ addi a4, a4, -8
+ beq a2, a5, 1b
+
+ /* Found an entry: Clear entry CPENABLE bit to disable CP. */
+
+ rsr a5, CPENABLE
+ s32i a6, a4, COPROCESSOR_INFO_OWNER
+ xor a5, a3, a5
+ wsr a5, CPENABLE
+
+ bnez a3, 1b
+
+1: wsr a7, PS
+ rsync
+ retw
+
+
+ENTRY(disable_coprocessor)
+ entry sp, 16
+ rsil a7, LOCKLEVEL
+ rsr a3, CPENABLE
+ movi a4, 1
+ ssl a2
+ sll a4, a4
+ and a4, a3, a4
+ xor a3, a3, a4
+ wsr a3, CPENABLE
+ wsr a7, PS
+ rsync
+ retw
+
+ENTRY(enable_coprocessor)
+ entry sp, 16
+ rsil a7, LOCKLEVEL
+ rsr a3, CPENABLE
+ movi a4, 1
+ ssl a2
+ sll a4, a4
+ or a3, a3, a4
+ wsr a3, CPENABLE
+ wsr a7, PS
+ rsync
+ retw
+
+#endif
+
+ENTRY(save_coprocessor_extra)
+ entry sp, 16
+ xchal_extra_store_funcbody
+ retw
+
+ENTRY(restore_coprocessor_extra)
+ entry sp, 16
+ xchal_extra_load_funcbody
+ retw
+
+ENTRY(save_coprocessor_registers)
+ entry sp, 16
+ xchal_cpi_store_funcbody
+ retw
+
+ENTRY(restore_coprocessor_registers)
+ entry sp, 16
+ xchal_cpi_load_funcbody
+ retw
+
+
+/*
+ * The Xtensa compile-time HAL (core.h) XCHAL_*_SA_CONTENTS_LIBDB macros
+ * describe the contents of coprocessor & extra save areas in terms of
+ * undefined CONTENTS_LIBDB_{SREG,UREG,REGF} macros. We define these
+ * latter macros here; they expand into a table of the format we want.
+ * The general format is:
+ *
+ * CONTENTS_LIBDB_SREG(libdbnum, offset, size, align, rsv1, name, sregnum,
+ * bitmask, rsv2, rsv3)
+ * CONTENTS_LIBDB_UREG(libdbnum, offset, size, align, rsv1, name, uregnum,
+ * bitmask, rsv2, rsv3)
+ * CONTENTS_LIBDB_REGF(libdbnum, offset, size, align, rsv1, name, index,
+ * numentries, contentsize, regname_base,
+ * regfile_name, rsv2, rsv3)
+ *
+ * For this table, we only care about the <libdbnum>, <offset> and <size>
+ * fields.
+ */
+
+/* Map all XCHAL CONTENTS macros to the reg_entry asm macro defined below: */
+
+#define CONTENTS_LIBDB_SREG(libdbnum,offset,size,align,rsv1,name,sregnum, \
+ bitmask, rsv2, rsv3) \
+ reg_entry libdbnum, offset, size ;
+#define CONTENTS_LIBDB_UREG(libdbnum,offset,size,align,rsv1,name,uregnum, \
+ bitmask, rsv2, rsv3) \
+ reg_entry libdbnum, offset, size ;
+#define CONTENTS_LIBDB_REGF(libdbnum, offset, size, align, rsv1, name, index, \
+ numentries, contentsize, regname_base, \
+ regfile_name, rsv2, rsv3) \
+ reg_entry libdbnum, offset, size ;
+
+/* A single table entry: */
+ .macro reg_entry libdbnum, offset, size
+ .ifne (__last_offset-(__last_group_offset+\offset))
+ /* padding entry */
+ .word (0xFC000000+__last_offset-(__last_group_offset+\offset))
+ .endif
+ .word \libdbnum /* actual entry */
+ .set __last_offset, __last_group_offset+\offset+\size
+ .endm /* reg_entry */
+
+
+/* Table entry that marks the beginning of a group (coprocessor or "extra"): */
+ .macro reg_group cpnum, num_entries, align
+ .set __last_group_offset, (__last_offset + \align- 1) & -\align
+ .ifne \num_entries
+ .word 0xFD000000+(\cpnum<<16)+\num_entries
+ .endif
+ .endm /* reg_group */
+
+/*
+ * Register info tables.
+ */
+
+ .section .rodata, "a"
+ .globl _xtensa_reginfo_tables
+ .globl _xtensa_reginfo_table_size
+ .align 4
+_xtensa_reginfo_table_size:
+ .word _xtensa_reginfo_table_end - _xtensa_reginfo_tables
+
+_xtensa_reginfo_tables:
+ .set __last_offset, 0
+ reg_group 0xFF, XCHAL_EXTRA_SA_CONTENTS_LIBDB_NUM, XCHAL_EXTRA_SA_ALIGN
+ XCHAL_EXTRA_SA_CONTENTS_LIBDB
+ reg_group 0, XCHAL_CP0_SA_CONTENTS_LIBDB_NUM, XCHAL_CP0_SA_ALIGN
+ XCHAL_CP0_SA_CONTENTS_LIBDB
+ reg_group 1, XCHAL_CP1_SA_CONTENTS_LIBDB_NUM, XCHAL_CP1_SA_ALIGN
+ XCHAL_CP1_SA_CONTENTS_LIBDB
+ reg_group 2, XCHAL_CP2_SA_CONTENTS_LIBDB_NUM, XCHAL_CP2_SA_ALIGN
+ XCHAL_CP2_SA_CONTENTS_LIBDB
+ reg_group 3, XCHAL_CP3_SA_CONTENTS_LIBDB_NUM, XCHAL_CP3_SA_ALIGN
+ XCHAL_CP3_SA_CONTENTS_LIBDB
+ reg_group 4, XCHAL_CP4_SA_CONTENTS_LIBDB_NUM, XCHAL_CP4_SA_ALIGN
+ XCHAL_CP4_SA_CONTENTS_LIBDB
+ reg_group 5, XCHAL_CP5_SA_CONTENTS_LIBDB_NUM, XCHAL_CP5_SA_ALIGN
+ XCHAL_CP5_SA_CONTENTS_LIBDB
+ reg_group 6, XCHAL_CP6_SA_CONTENTS_LIBDB_NUM, XCHAL_CP6_SA_ALIGN
+ XCHAL_CP6_SA_CONTENTS_LIBDB
+ reg_group 7, XCHAL_CP7_SA_CONTENTS_LIBDB_NUM, XCHAL_CP7_SA_ALIGN
+ XCHAL_CP7_SA_CONTENTS_LIBDB
+ .word 0xFC000000 /* invalid register number,marks end of table*/
+_xtensa_reginfo_table_end:
+
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
new file mode 100644
index 00000000000..c64a01f71de
--- /dev/null
+++ b/arch/xtensa/kernel/entry.S
@@ -0,0 +1,1996 @@
+/*
+ * arch/xtensa/kernel/entry.S
+ *
+ * Low-level exception handling
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2004-2005 by Tensilica Inc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ *
+ */
+
+#include <linux/linkage.h>
+#include <asm/offsets.h>
+#include <asm/processor.h>
+#include <asm/thread_info.h>
+#include <asm/uaccess.h>
+#include <asm/unistd.h>
+#include <asm/ptrace.h>
+#include <asm/current.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/signal.h>
+#include <xtensa/coreasm.h>
+
+/* Unimplemented features. */
+
+#undef SIGNAL_HANDLING_IN_DOUBLE_EXCEPTION
+#undef KERNEL_STACK_OVERFLOW_CHECK
+#undef PREEMPTIBLE_KERNEL
+#undef ALLOCA_EXCEPTION_IN_IRAM
+
+/* Not well tested.
+ *
+ * - fast_coprocessor
+ */
+
+/*
+ * Macro to find first bit set in WINDOWBASE from the left + 1
+ *
+ * 100....0 -> 1
+ * 010....0 -> 2
+ * 000....1 -> WSBITS
+ */
+
+ .macro ffs_ws bit mask
+
+#if XCHAL_HAVE_NSA
+ nsau \bit, \mask # 32-WSBITS ... 31 (32 iff 0)
+ addi \bit, \bit, WSBITS - 32 + 1 # uppest bit set -> return 1
+#else
+ movi \bit, WSBITS
+#if WSBITS > 16
+ _bltui \mask, 0x10000, 99f
+ addi \bit, \bit, -16
+ extui \mask, \mask, 16, 16
+#endif
+#if WSBITS > 8
+99: _bltui \mask, 0x100, 99f
+ addi \bit, \bit, -8
+ srli \mask, \mask, 8
+#endif
+99: _bltui \mask, 0x10, 99f
+ addi \bit, \bit, -4
+ srli \mask, \mask, 4
+99: _bltui \mask, 0x4, 99f
+ addi \bit, \bit, -2
+ srli \mask, \mask, 2
+99: _bltui \mask, 0x2, 99f
+ addi \bit, \bit, -1
+99:
+
+#endif
+ .endm
+
+/* ----------------- DEFAULT FIRST LEVEL EXCEPTION HANDLERS ----------------- */
+
+/*
+ * First-level exception handler for user exceptions.
+ * Save some special registers, extra states and all registers in the AR
+ * register file that were in use in the user task, and jump to the common
+ * exception code.
+ * We save SAR (used to calculate WMASK), and WB and WS (we don't have to
+ * save them for kernel exceptions).
+ *
+ * Entry condition for user_exception:
+ *
+ * a0: trashed, original value saved on stack (PT_AREG0)
+ * a1: a1
+ * a2: new stack pointer, original value in depc
+ * a3: dispatch table
+ * depc: a2, original value saved on stack (PT_DEPC)
+ * excsave1: a3
+ *
+ * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
+ * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
+ *
+ * Entry condition for _user_exception:
+ *
+ * a0-a3 and depc have been saved to PT_AREG0...PT_AREG3 and PT_DEPC
+ * excsave has been restored, and
+ * stack pointer (a1) has been set.
+ *
+ * Note: _user_exception might be at an odd adress. Don't use call0..call12
+ */
+
+ENTRY(user_exception)
+
+ /* Save a2, a3, and depc, restore excsave_1 and set SP. */
+
+ xsr a3, EXCSAVE_1
+ rsr a0, DEPC
+ s32i a1, a2, PT_AREG1
+ s32i a0, a2, PT_AREG2
+ s32i a3, a2, PT_AREG3
+ mov a1, a2
+
+ .globl _user_exception
+_user_exception:
+
+ /* Save SAR and turn off single stepping */
+
+ movi a2, 0
+ rsr a3, SAR
+ wsr a2, ICOUNTLEVEL
+ s32i a3, a1, PT_SAR
+
+ /* Rotate ws so that the current windowbase is at bit0. */
+ /* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */
+
+ rsr a2, WINDOWBASE
+ rsr a3, WINDOWSTART
+ ssr a2
+ s32i a2, a1, PT_WINDOWBASE
+ s32i a3, a1, PT_WINDOWSTART
+ slli a2, a3, 32-WSBITS
+ src a2, a3, a2
+ srli a2, a2, 32-WSBITS
+ s32i a2, a1, PT_WMASK # needed for restoring registers
+
+ /* Save only live registers. */
+
+ _bbsi.l a2, 1, 1f
+ s32i a4, a1, PT_AREG4
+ s32i a5, a1, PT_AREG5
+ s32i a6, a1, PT_AREG6
+ s32i a7, a1, PT_AREG7
+ _bbsi.l a2, 2, 1f
+ s32i a8, a1, PT_AREG8
+ s32i a9, a1, PT_AREG9
+ s32i a10, a1, PT_AREG10
+ s32i a11, a1, PT_AREG11
+ _bbsi.l a2, 3, 1f
+ s32i a12, a1, PT_AREG12
+ s32i a13, a1, PT_AREG13
+ s32i a14, a1, PT_AREG14
+ s32i a15, a1, PT_AREG15
+ _bnei a2, 1, 1f # only one valid frame?
+
+ /* Only one valid frame, skip saving regs. */
+
+ j 2f
+
+ /* Save the remaining registers.
+ * We have to save all registers up to the first '1' from
+ * the right, except the current frame (bit 0).
+ * Assume a2 is: 001001000110001
+ * All regiser frames starting from the top fiel to the marked '1'
+ * must be saved.
+ */
+
+1: addi a3, a2, -1 # eliminate '1' in bit 0: yyyyxxww0
+ neg a3, a3 # yyyyxxww0 -> YYYYXXWW1+1
+ and a3, a3, a2 # max. only one bit is set
+
+ /* Find number of frames to save */
+
+ ffs_ws a0, a3 # number of frames to the '1' from left
+
+ /* Store information into WMASK:
+ * bits 0..3: xxx1 masked lower 4 bits of the rotated windowstart,
+ * bits 4...: number of valid 4-register frames
+ */
+
+ slli a3, a0, 4 # number of frames to save in bits 8..4
+ extui a2, a2, 0, 4 # mask for the first 16 registers
+ or a2, a3, a2
+ s32i a2, a1, PT_WMASK # needed when we restore the reg-file
+
+ /* Save 4 registers at a time */
+
+1: rotw -1
+ s32i a0, a5, PT_AREG_END - 16
+ s32i a1, a5, PT_AREG_END - 12
+ s32i a2, a5, PT_AREG_END - 8
+ s32i a3, a5, PT_AREG_END - 4
+ addi a0, a4, -1
+ addi a1, a5, -16
+ _bnez a0, 1b
+
+ /* WINDOWBASE still in SAR! */
+
+ rsr a2, SAR # original WINDOWBASE
+ movi a3, 1
+ ssl a2
+ sll a3, a3
+ wsr a3, WINDOWSTART # set corresponding WINDOWSTART bit
+ wsr a2, WINDOWBASE # and WINDOWSTART
+ rsync
+
+ /* We are back to the original stack pointer (a1) */
+
+2:
+#if XCHAL_EXTRA_SA_SIZE
+
+ /* For user exceptions, save the extra state into the user's TCB.
+ * Note: We must assume that xchal_extra_store_funcbody destroys a2..a15
+ */
+
+ GET_CURRENT(a2,a1)
+ addi a2, a2, THREAD_CP_SAVE
+ xchal_extra_store_funcbody
+#endif
+
+ /* Now, jump to the common exception handler. */
+
+ j common_exception
+
+
+/*
+ * First-level exit handler for kernel exceptions
+ * Save special registers and the live window frame.
+ * Note: Even though we changes the stack pointer, we don't have to do a
+ * MOVSP here, as we do that when we return from the exception.
+ * (See comment in the kernel exception exit code)
+ *
+ * Entry condition for kernel_exception:
+ *
+ * a0: trashed, original value saved on stack (PT_AREG0)
+ * a1: a1
+ * a2: new stack pointer, original in DEPC
+ * a3: dispatch table
+ * depc: a2, original value saved on stack (PT_DEPC)
+ * excsave_1: a3
+ *
+ * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
+ * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
+ *
+ * Entry condition for _kernel_exception:
+ *
+ * a0-a3 and depc have been saved to PT_AREG0...PT_AREG3 and PT_DEPC
+ * excsave has been restored, and
+ * stack pointer (a1) has been set.
+ *
+ * Note: _kernel_exception might be at an odd adress. Don't use call0..call12
+ */
+
+ENTRY(kernel_exception)
+
+ /* Save a0, a2, a3, DEPC and set SP. */
+
+ xsr a3, EXCSAVE_1 # restore a3, excsave_1
+ rsr a0, DEPC # get a2
+ s32i a1, a2, PT_AREG1
+ s32i a0, a2, PT_AREG2
+ s32i a3, a2, PT_AREG3
+ mov a1, a2
+
+ .globl _kernel_exception
+_kernel_exception:
+
+ /* Save SAR and turn off single stepping */
+
+ movi a2, 0
+ rsr a3, SAR
+ wsr a2, ICOUNTLEVEL
+ s32i a3, a1, PT_SAR
+
+ /* Rotate ws so that the current windowbase is at bit0. */
+ /* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */
+
+ rsr a2, WINDOWBASE # don't need to save these, we only
+ rsr a3, WINDOWSTART # need shifted windowstart: windowmask
+ ssr a2
+ slli a2, a3, 32-WSBITS
+ src a2, a3, a2
+ srli a2, a2, 32-WSBITS
+ s32i a2, a1, PT_WMASK # needed for kernel_exception_exit
+
+ /* Save only the live window-frame */
+
+ _bbsi.l a2, 1, 1f
+ s32i a4, a1, PT_AREG4
+ s32i a5, a1, PT_AREG5
+ s32i a6, a1, PT_AREG6
+ s32i a7, a1, PT_AREG7
+ _bbsi.l a2, 2, 1f
+ s32i a8, a1, PT_AREG8
+ s32i a9, a1, PT_AREG9
+ s32i a10, a1, PT_AREG10
+ s32i a11, a1, PT_AREG11
+ _bbsi.l a2, 3, 1f
+ s32i a12, a1, PT_AREG12
+ s32i a13, a1, PT_AREG13
+ s32i a14, a1, PT_AREG14
+ s32i a15, a1, PT_AREG15
+
+1:
+
+#ifdef KERNEL_STACK_OVERFLOW_CHECK
+
+ /* Stack overflow check, for debugging */
+ extui a2, a1, TASK_SIZE_BITS,XX
+ movi a3, SIZE??
+ _bge a2, a3, out_of_stack_panic
+
+#endif
+
+/*
+ * This is the common exception handler.
+ * We get here from the user exception handler or simply by falling through
+ * from the kernel exception handler.
+ * Save the remaining special registers, switch to kernel mode, and jump
+ * to the second-level exception handler.
+ *
+ */
+
+common_exception:
+
+ /* Save EXCVADDR, DEBUGCAUSE, and PC, and clear LCOUNT */
+
+ rsr a2, DEBUGCAUSE
+ rsr a3, EPC_1
+ s32i a2, a1, PT_DEBUGCAUSE
+ s32i a3, a1, PT_PC
+
+ rsr a3, EXCVADDR
+ movi a2, 0
+ s32i a3, a1, PT_EXCVADDR
+ xsr a2, LCOUNT
+ s32i a2, a1, PT_LCOUNT
+
+ /* It is now save to restore the EXC_TABLE_FIXUP variable. */
+
+ rsr a0, EXCCAUSE
+ movi a3, 0
+ rsr a2, EXCSAVE_1
+ s32i a0, a1, PT_EXCCAUSE
+ s32i a3, a2, EXC_TABLE_FIXUP
+
+ /* All unrecoverable states are saved on stack, now, and a1 is valid,
+ * so we can allow exceptions and interrupts (*) again.
+ * Set PS(EXCM = 0, UM = 0, RING = 0, OWB = 0, WOE = 1, INTLEVEL = X)
+ *
+ * (*) We only allow interrupts if PS.INTLEVEL was not set to 1 before
+ * (interrupts disabled) and if this exception is not an interrupt.
+ */
+
+ rsr a3, PS
+ addi a0, a0, -4
+ movi a2, 1
+ extui a3, a3, 0, 1 # a3 = PS.INTLEVEL[0]
+ moveqz a3, a2, a0 # a3 = 1 iff interrupt exception
+ movi a2, PS_WOE_MASK
+ or a3, a3, a2
+ rsr a0, EXCCAUSE
+ xsr a3, PS
+
+ s32i a3, a1, PT_PS # save ps
+
+ /* Save LBEG, LEND */
+
+ rsr a2, LBEG
+ rsr a3, LEND
+ s32i a2, a1, PT_LBEG
+ s32i a3, a1, PT_LEND
+
+ /* Go to second-level dispatcher. Set up parameters to pass to the
+ * exception handler and call the exception handler.
+ */
+
+ movi a4, exc_table
+ mov a6, a1 # pass stack frame
+ mov a7, a0 # pass EXCCAUSE
+ addx4 a4, a0, a4
+ l32i a4, a4, EXC_TABLE_DEFAULT # load handler
+
+ /* Call the second-level handler */
+
+ callx4 a4
+
+ /* Jump here for exception exit */
+
+common_exception_return:
+
+ /* Jump if we are returning from kernel exceptions. */
+
+1: l32i a3, a1, PT_PS
+ _bbsi.l a3, PS_UM_SHIFT, 2f
+ j kernel_exception_exit
+
+ /* Specific to a user exception exit:
+ * We need to check some flags for signal handling and rescheduling,
+ * and have to restore WB and WS, extra states, and all registers
+ * in the register file that were in use in the user task.
+ */
+
+2: wsr a3, PS /* disable interrupts */
+
+ /* Check for signals (keep interrupts disabled while we read TI_FLAGS)
+ * Note: PS.INTLEVEL = 0, PS.EXCM = 1
+ */
+
+ GET_THREAD_INFO(a2,a1)
+ l32i a4, a2, TI_FLAGS
+
+ /* Enable interrupts again.
+ * Note: When we get here, we certainly have handled any interrupts.
+ * (Hint: There is only one user exception frame on stack)
+ */
+
+ movi a3, PS_WOE_MASK
+
+ _bbsi.l a4, TIF_NEED_RESCHED, 3f
+ _bbci.l a4, TIF_SIGPENDING, 4f
+
+#ifndef SIGNAL_HANDLING_IN_DOUBLE_EXCEPTION
+ l32i a4, a1, PT_DEPC
+ bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f
+#endif
+
+ /* Reenable interrupts and call do_signal() */
+
+ wsr a3, PS
+ movi a4, do_signal # int do_signal(struct pt_regs*, sigset_t*)
+ mov a6, a1
+ movi a7, 0
+ callx4 a4
+ j 1b
+
+3: /* Reenable interrupts and reschedule */
+
+ wsr a3, PS
+ movi a4, schedule # void schedule (void)
+ callx4 a4
+ j 1b
+
+ /* Restore the state of the task and return from the exception. */
+
+
+ /* If we are returning from a user exception, and the process
+ * to run next has PT_SINGLESTEP set, we want to setup
+ * ICOUNT and ICOUNTLEVEL to step one instruction.
+ * PT_SINGLESTEP is set by sys_ptrace (ptrace.c)
+ */
+
+4: /* a2 holds GET_CURRENT(a2,a1) */
+
+ l32i a3, a2, TI_TASK
+ l32i a3, a3, TASK_PTRACE
+ bbci.l a3, PT_SINGLESTEP_BIT, 1f # jump if single-step flag is not set
+
+ movi a3, -2 # PT_SINGLESTEP flag is set,
+ movi a4, 1 # icountlevel of 1 means it won't
+ wsr a3, ICOUNT # start counting until after rfe
+ wsr a4, ICOUNTLEVEL # so setup icount & icountlevel.
+ isync
+
+1:
+
+#if XCHAL_EXTRA_SA_SIZE
+
+ /* For user exceptions, restore the extra state from the user's TCB. */
+
+ /* Note: a2 still contains GET_CURRENT(a2,a1) */
+ addi a2, a2, THREAD_CP_SAVE
+ xchal_extra_load_funcbody
+
+ /* We must assume that xchal_extra_store_funcbody destroys
+ * registers a2..a15. FIXME, this list can eventually be
+ * reduced once real register requirements of the macro are
+ * finalized. */
+
+#endif /* XCHAL_EXTRA_SA_SIZE */
+
+
+ /* Switch to the user thread WINDOWBASE. Save SP temporarily in DEPC */
+
+ l32i a2, a1, PT_WINDOWBASE
+ l32i a3, a1, PT_WINDOWSTART
+ wsr a1, DEPC # use DEPC as temp storage
+ wsr a3, WINDOWSTART # restore WINDOWSTART
+ ssr a2 # preserve user's WB in the SAR
+ wsr a2, WINDOWBASE # switch to user's saved WB
+ rsync
+ rsr a1, DEPC # restore stack pointer
+ l32i a2, a1, PT_WMASK # register frames saved (in bits 4...9)
+ rotw -1 # we restore a4..a7
+ _bltui a6, 16, 1f # only have to restore current window?
+
+ /* The working registers are a0 and a3. We are restoring to
+ * a4..a7. Be careful not to destroy what we have just restored.
+ * Note: wmask has the format YYYYM:
+ * Y: number of registers saved in groups of 4
+ * M: 4 bit mask of first 16 registers
+ */
+
+ mov a2, a6
+ mov a3, a5
+
+2: rotw -1 # a0..a3 become a4..a7
+ addi a3, a7, -4*4 # next iteration
+ addi a2, a6, -16 # decrementing Y in WMASK
+ l32i a4, a3, PT_AREG_END + 0
+ l32i a5, a3, PT_AREG_END + 4
+ l32i a6, a3, PT_AREG_END + 8
+ l32i a7, a3, PT_AREG_END + 12
+ _bgeui a2, 16, 2b
+
+ /* Clear unrestored registers (don't leak anything to user-land */
+
+1: rsr a0, WINDOWBASE
+ rsr a3, SAR
+ sub a3, a0, a3
+ beqz a3, 2f
+ extui a3, a3, 0, WBBITS
+
+1: rotw -1
+ addi a3, a7, -1
+ movi a4, 0
+ movi a5, 0
+ movi a6, 0
+ movi a7, 0
+ bgei a3, 1, 1b
+
+ /* We are back were we were when we started.
+ * Note: a2 still contains WMASK (if we've returned to the original
+ * frame where we had loaded a2), or at least the lower 4 bits
+ * (if we have restored WSBITS-1 frames).
+ */
+
+2: j common_exception_exit
+
+ /* This is the kernel exception exit.
+ * We avoided to do a MOVSP when we entered the exception, but we
+ * have to do it here.
+ */
+
+kernel_exception_exit:
+
+ /* Disable interrupts (a3 holds PT_PS) */
+
+ wsr a3, PS
+
+#ifdef PREEMPTIBLE_KERNEL
+
+#ifdef CONFIG_PREEMPT
+
+ /*
+ * Note: We've just returned from a call4, so we have
+ * at least 4 addt'l regs.
+ */
+
+ /* Check current_thread_info->preempt_count */
+
+ GET_THREAD_INFO(a2)
+ l32i a3, a2, TI_PREEMPT
+ bnez a3, 1f
+
+ l32i a2, a2, TI_FLAGS
+
+1:
+
+#endif
+
+#endif
+
+ /* Check if we have to do a movsp.
+ *
+ * We only have to do a movsp if the previous window-frame has
+ * been spilled to the *temporary* exception stack instead of the
+ * task's stack. This is the case if the corresponding bit in
+ * WINDOWSTART for the previous window-frame was set before
+ * (not spilled) but is zero now (spilled).
+ * If this bit is zero, all other bits except the one for the
+ * current window frame are also zero. So, we can use a simple test:
+ * 'and' WINDOWSTART and WINDOWSTART-1:
+ *
+ * (XXXXXX1[0]* - 1) AND XXXXXX1[0]* = XXXXXX0[0]*
+ *
+ * The result is zero only if one bit was set.
+ *
+ * (Note: We might have gone through several task switches before
+ * we come back to the current task, so WINDOWBASE might be
+ * different from the time the exception occurred.)
+ */
+
+ /* Test WINDOWSTART before and after the exception.
+ * We actually have WMASK, so we only have to test if it is 1 or not.
+ */
+
+ l32i a2, a1, PT_WMASK
+ _beqi a2, 1, common_exception_exit # Spilled before exception,jump
+
+ /* Test WINDOWSTART now. If spilled, do the movsp */
+
+ rsr a3, WINDOWSTART
+ addi a0, a3, -1
+ and a3, a3, a0
+ _bnez a3, common_exception_exit
+
+ /* Do a movsp (we returned from a call4, so we have at least a0..a7) */
+
+ addi a0, a1, -16
+ l32i a3, a0, 0
+ l32i a4, a0, 4
+ s32i a3, a1, PT_SIZE+0
+ s32i a4, a1, PT_SIZE+4
+ l32i a3, a0, 8
+ l32i a4, a0, 12
+ s32i a3, a1, PT_SIZE+8
+ s32i a4, a1, PT_SIZE+12
+
+ /* Common exception exit.
+ * We restore the special register and the current window frame, and
+ * return from the exception.
+ *
+ * Note: We expect a2 to hold PT_WMASK
+ */
+
+common_exception_exit:
+
+ _bbsi.l a2, 1, 1f
+ l32i a4, a1, PT_AREG4
+ l32i a5, a1, PT_AREG5
+ l32i a6, a1, PT_AREG6
+ l32i a7, a1, PT_AREG7
+ _bbsi.l a2, 2, 1f
+ l32i a8, a1, PT_AREG8
+ l32i a9, a1, PT_AREG9
+ l32i a10, a1, PT_AREG10
+ l32i a11, a1, PT_AREG11
+ _bbsi.l a2, 3, 1f
+ l32i a12, a1, PT_AREG12
+ l32i a13, a1, PT_AREG13
+ l32i a14, a1, PT_AREG14
+ l32i a15, a1, PT_AREG15
+
+ /* Restore PC, SAR */
+
+1: l32i a2, a1, PT_PC
+ l32i a3, a1, PT_SAR
+ wsr a2, EPC_1
+ wsr a3, SAR
+
+ /* Restore LBEG, LEND, LCOUNT */
+
+ l32i a2, a1, PT_LBEG
+ l32i a3, a1, PT_LEND
+ wsr a2, LBEG
+ l32i a2, a1, PT_LCOUNT
+ wsr a3, LEND
+ wsr a2, LCOUNT
+
+ /* Check if it was double exception. */
+
+ l32i a0, a1, PT_DEPC
+ l32i a3, a1, PT_AREG3
+ l32i a2, a1, PT_AREG2
+ _bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
+
+ /* Restore a0...a3 and return */
+
+ l32i a0, a1, PT_AREG0
+ l32i a1, a1, PT_AREG1
+ rfe
+
+1: wsr a0, DEPC
+ l32i a0, a1, PT_AREG0
+ l32i a1, a1, PT_AREG1
+ rfde
+
+/*
+ * Debug exception handler.
+ *
+ * Currently, we don't support KGDB, so only user application can be debugged.
+ *
+ * When we get here, a0 is trashed and saved to excsave[debuglevel]
+ */
+
+ENTRY(debug_exception)
+
+ rsr a0, EPS + XCHAL_DEBUGLEVEL
+ bbsi.l a0, PS_EXCM_SHIFT, 1f # exception mode
+
+ /* Set EPC_1 and EXCCAUSE */
+
+ wsr a2, DEPC # save a2 temporarily
+ rsr a2, EPC + XCHAL_DEBUGLEVEL
+ wsr a2, EPC_1
+
+ movi a2, EXCCAUSE_MAPPED_DEBUG
+ wsr a2, EXCCAUSE
+
+ /* Restore PS to the value before the debug exc but with PS.EXCM set.*/
+
+ movi a2, 1 << PS_EXCM_SHIFT
+ or a2, a0, a2
+ movi a0, debug_exception # restore a3, debug jump vector
+ wsr a2, PS
+ xsr a0, EXCSAVE + XCHAL_DEBUGLEVEL
+
+ /* Switch to kernel/user stack, restore jump vector, and save a0 */
+
+ bbsi.l a2, PS_UM_SHIFT, 2f # jump if user mode
+
+ addi a2, a1, -16-PT_SIZE # assume kernel stack
+ s32i a0, a2, PT_AREG0
+ movi a0, 0
+ s32i a1, a2, PT_AREG1
+ s32i a0, a2, PT_DEPC # mark it as a regular exception
+ xsr a0, DEPC
+ s32i a3, a2, PT_AREG3
+ s32i a0, a2, PT_AREG2
+ mov a1, a2
+ j _kernel_exception
+
+2: rsr a2, EXCSAVE_1
+ l32i a2, a2, EXC_TABLE_KSTK # load kernel stack pointer
+ s32i a0, a2, PT_AREG0
+ movi a0, 0
+ s32i a1, a2, PT_AREG1
+ s32i a0, a2, PT_DEPC
+ xsr a0, DEPC
+ s32i a3, a2, PT_AREG3
+ s32i a0, a2, PT_AREG2
+ mov a1, a2
+ j _user_exception
+
+ /* Debug exception while in exception mode. */
+1: j 1b // FIXME!!
+
+
+/*
+ * We get here in case of an unrecoverable exception.
+ * The only thing we can do is to be nice and print a panic message.
+ * We only produce a single stack frame for panic, so ???
+ *
+ *
+ * Entry conditions:
+ *
+ * - a0 contains the caller address; original value saved in excsave1.
+ * - the original a0 contains a valid return address (backtrace) or 0.
+ * - a2 contains a valid stackpointer
+ *
+ * Notes:
+ *
+ * - If the stack pointer could be invalid, the caller has to setup a
+ * dummy stack pointer (e.g. the stack of the init_task)
+ *
+ * - If the return address could be invalid, the caller has to set it
+ * to 0, so the backtrace would stop.
+ *
+ */
+ .align 4
+unrecoverable_text:
+ .ascii "Unrecoverable error in exception handler\0"
+
+ENTRY(unrecoverable_exception)
+
+ movi a0, 1
+ movi a1, 0
+
+ wsr a0, WINDOWSTART
+ wsr a1, WINDOWBASE
+ rsync
+
+ movi a1, PS_WOE_MASK | 1
+ wsr a1, PS
+ rsync
+
+ movi a1, init_task
+ movi a0, 0
+ addi a1, a1, PT_REGS_OFFSET
+
+ movi a4, panic
+ movi a6, unrecoverable_text
+
+ callx4 a4
+
+1: j 1b
+
+
+/* -------------------------- FAST EXCEPTION HANDLERS ----------------------- */
+
+/*
+ * Fast-handler for alloca exceptions
+ *
+ * The ALLOCA handler is entered when user code executes the MOVSP
+ * instruction and the caller's frame is not in the register file.
+ * In this case, the caller frame's a0..a3 are on the stack just
+ * below sp (a1), and this handler moves them.
+ *
+ * For "MOVSP <ar>,<as>" without destination register a1, this routine
+ * simply moves the value from <as> to <ar> without moving the save area.
+ *
+ * Entry condition:
+ *
+ * a0: trashed, original value saved on stack (PT_AREG0)
+ * a1: a1
+ * a2: new stack pointer, original in DEPC
+ * a3: dispatch table
+ * depc: a2, original value saved on stack (PT_DEPC)
+ * excsave_1: a3
+ *
+ * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
+ * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
+ */
+
+#if XCHAL_HAVE_BE
+#define _EXTUI_MOVSP_SRC(ar) extui ar, ar, 4, 4
+#define _EXTUI_MOVSP_DST(ar) extui ar, ar, 0, 4
+#else
+#define _EXTUI_MOVSP_SRC(ar) extui ar, ar, 0, 4
+#define _EXTUI_MOVSP_DST(ar) extui ar, ar, 4, 4
+#endif
+
+ENTRY(fast_alloca)
+
+ /* We shouldn't be in a double exception. */
+
+ l32i a0, a2, PT_DEPC
+ _bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, .Lunhandled_double
+
+ rsr a0, DEPC # get a2
+ s32i a4, a2, PT_AREG4 # save a4 and
+ s32i a0, a2, PT_AREG2 # a2 to stack
+
+ /* Exit critical section. */
+
+ movi a0, 0
+ s32i a0, a3, EXC_TABLE_FIXUP
+
+ /* Restore a3, excsave_1 */
+
+ xsr a3, EXCSAVE_1 # make sure excsave_1 is valid for dbl.
+ rsr a4, EPC_1 # get exception address
+ s32i a3, a2, PT_AREG3 # save a3 to stack
+
+#ifdef ALLOCA_EXCEPTION_IN_IRAM
+#error iram not supported
+#else
+ /* Note: l8ui not allowed in IRAM/IROM!! */
+ l8ui a0, a4, 1 # read as(src) from MOVSP instruction
+#endif
+ movi a3, .Lmovsp_src
+ _EXTUI_MOVSP_SRC(a0) # extract source register number
+ addx8 a3, a0, a3
+ jx a3
+
+.Lunhandled_double:
+ wsr a0, EXCSAVE_1
+ movi a0, unrecoverable_exception
+ callx0 a0
+
+ .align 8
+.Lmovsp_src:
+ l32i a3, a2, PT_AREG0; _j 1f; .align 8
+ mov a3, a1; _j 1f; .align 8
+ l32i a3, a2, PT_AREG2; _j 1f; .align 8
+ l32i a3, a2, PT_AREG3; _j 1f; .align 8
+ l32i a3, a2, PT_AREG4; _j 1f; .align 8
+ mov a3, a5; _j 1f; .align 8
+ mov a3, a6; _j 1f; .align 8
+ mov a3, a7; _j 1f; .align 8
+ mov a3, a8; _j 1f; .align 8
+ mov a3, a9; _j 1f; .align 8
+ mov a3, a10; _j 1f; .align 8
+ mov a3, a11; _j 1f; .align 8
+ mov a3, a12; _j 1f; .align 8
+ mov a3, a13; _j 1f; .align 8
+ mov a3, a14; _j 1f; .align 8
+ mov a3, a15; _j 1f; .align 8
+
+1:
+
+#ifdef ALLOCA_EXCEPTION_IN_IRAM
+#error iram not supported
+#else
+ l8ui a0, a4, 0 # read ar(dst) from MOVSP instruction
+#endif
+ addi a4, a4, 3 # step over movsp
+ _EXTUI_MOVSP_DST(a0) # extract destination register
+ wsr a4, EPC_1 # save new epc_1
+
+ _bnei a0, 1, 1f # no 'movsp a1, ax': jump
+
+ /* Move the save area. This implies the use of the L32E
+ * and S32E instructions, because this move must be done with
+ * the user's PS.RING privilege levels, not with ring 0
+ * (kernel's) privileges currently active with PS.EXCM
+ * set. Note that we have stil registered a fixup routine with the
+ * double exception vector in case a double exception occurs.
+ */
+
+ /* a0,a4:avail a1:old user stack a2:exc. stack a3:new user stack. */
+
+ l32e a0, a1, -16
+ l32e a4, a1, -12
+ s32e a0, a3, -16
+ s32e a4, a3, -12
+ l32e a0, a1, -8
+ l32e a4, a1, -4
+ s32e a0, a3, -8
+ s32e a4, a3, -4
+
+ /* Restore stack-pointer and all the other saved registers. */
+
+ mov a1, a3
+
+ l32i a4, a2, PT_AREG4
+ l32i a3, a2, PT_AREG3
+ l32i a0, a2, PT_AREG0
+ l32i a2, a2, PT_AREG2
+ rfe
+
+ /* MOVSP <at>,<as> was invoked with <at> != a1.
+ * Because the stack pointer is not being modified,
+ * we should be able to just modify the pointer
+ * without moving any save area.
+ * The processor only traps these occurrences if the
+ * caller window isn't live, so unfortunately we can't
+ * use this as an alternate trap mechanism.
+ * So we just do the move. This requires that we
+ * resolve the destination register, not just the source,
+ * so there's some extra work.
+ * (PERHAPS NOT REALLY NEEDED, BUT CLEANER...)
+ */
+
+ /* a0 dst-reg, a1 user-stack, a2 stack, a3 value of src reg. */
+
+1: movi a4, .Lmovsp_dst
+ addx8 a4, a0, a4
+ jx a4
+
+ .align 8
+.Lmovsp_dst:
+ s32i a3, a2, PT_AREG0; _j 1f; .align 8
+ mov a1, a3; _j 1f; .align 8
+ s32i a3, a2, PT_AREG2; _j 1f; .align 8
+ s32i a3, a2, PT_AREG3; _j 1f; .align 8
+ s32i a3, a2, PT_AREG4; _j 1f; .align 8
+ mov a5, a3; _j 1f; .align 8
+ mov a6, a3; _j 1f; .align 8
+ mov a7, a3; _j 1f; .align 8
+ mov a8, a3; _j 1f; .align 8
+ mov a9, a3; _j 1f; .align 8
+ mov a10, a3; _j 1f; .align 8
+ mov a11, a3; _j 1f; .align 8
+ mov a12, a3; _j 1f; .align 8
+ mov a13, a3; _j 1f; .align 8
+ mov a14, a3; _j 1f; .align 8
+ mov a15, a3; _j 1f; .align 8
+
+1: l32i a4, a2, PT_AREG4
+ l32i a3, a2, PT_AREG3
+ l32i a0, a2, PT_AREG0
+ l32i a2, a2, PT_AREG2
+ rfe
+
+
+/*
+ * fast system calls.
+ *
+ * WARNING: The kernel doesn't save the entire user context before
+ * handling a fast system call. These functions are small and short,
+ * usually offering some functionality not available to user tasks.
+ *
+ * BE CAREFUL TO PRESERVE THE USER'S CONTEXT.
+ *
+ * Entry condition:
+ *
+ * a0: trashed, original value saved on stack (PT_AREG0)
+ * a1: a1
+ * a2: new stack pointer, original in DEPC
+ * a3: dispatch table
+ * depc: a2, original value saved on stack (PT_DEPC)
+ * excsave_1: a3
+ */
+
+ENTRY(fast_syscall_kernel)
+
+ /* Skip syscall. */
+
+ rsr a0, EPC_1
+ addi a0, a0, 3
+ wsr a0, EPC_1
+
+ l32i a0, a2, PT_DEPC
+ bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, fast_syscall_unrecoverable
+
+ rsr a0, DEPC # get syscall-nr
+ _beqz a0, fast_syscall_spill_registers
+
+ addi a0, a0, -__NR_sysxtensa
+ _beqz a0, fast_syscall_sysxtensa
+
+ j kernel_exception
+
+
+ENTRY(fast_syscall_user)
+
+ /* Skip syscall. */
+
+ rsr a0, EPC_1
+ addi a0, a0, 3
+ wsr a0, EPC_1
+
+ l32i a0, a2, PT_DEPC
+ bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, fast_syscall_unrecoverable
+
+ rsr a0, DEPC # get syscall-nr
+ _beqz a0, fast_syscall_spill_registers
+
+ addi a0, a0, -__NR_sysxtensa
+ _beqz a0, fast_syscall_sysxtensa
+
+ j user_exception
+
+ENTRY(fast_syscall_unrecoverable)
+
+ /* Restore all states. */
+
+ l32i a0, a2, PT_AREG0 # restore a0
+ xsr a2, DEPC # restore a2, depc
+ rsr a3, EXCSAVE_1
+
+ wsr a0, EXCSAVE_1
+ movi a0, unrecoverable_exception
+ callx0 a0
+
+
+
+/*
+ * sysxtensa syscall handler
+ *
+ * int sysxtensa (XTENSA_ATOMIC_SET, ptr, val, unused);
+ * int sysxtensa (XTENSA_ATOMIC_ADD, ptr, val, unused);
+ * int sysxtensa (XTENSA_ATOMIC_EXG_ADD, ptr, val, unused);
+ * int sysxtensa (XTENSA_ATOMIC_CMP_SWP, ptr, oldval, newval);
+ * a2 a6 a3 a4 a5
+ *
+ * Entry condition:
+ *
+ * a0: trashed, original value saved on stack (PT_AREG0)
+ * a1: a1
+ * a2: new stack pointer, original in DEPC
+ * a3: dispatch table
+ * depc: a2, original value saved on stack (PT_DEPC)
+ * excsave_1: a3
+ *
+ * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
+ * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
+ *
+ * Note: we don't have to save a2; a2 holds the return value
+ *
+ * We use the two macros TRY and CATCH:
+ *
+ * TRY adds an entry to the __ex_table fixup table for the immediately
+ * following instruction.
+ *
+ * CATCH catches any exception that occurred at one of the preceeding TRY
+ * statements and continues from there
+ *
+ * Usage TRY l32i a0, a1, 0
+ * <other code>
+ * done: rfe
+ * CATCH <set return code>
+ * j done
+ */
+
+#define TRY \
+ .section __ex_table, "a"; \
+ .word 66f, 67f; \
+ .text; \
+66:
+
+#define CATCH \
+67:
+
+ENTRY(fast_syscall_sysxtensa)
+
+ _beqz a6, 1f
+ _blti a6, SYSXTENSA_COUNT, 2f
+
+1: j user_exception
+
+2: xsr a3, EXCSAVE_1 # restore a3, excsave1
+ s32i a7, a2, PT_AREG7
+
+ movi a7, 4 # sizeof(unsigned int)
+ verify_area a3, a7, a0, a2, .Leac
+
+ _beqi a6, SYSXTENSA_ATOMIC_SET, .Lset
+ _beqi a6, SYSXTENSA_ATOMIC_EXG_ADD, .Lexg
+ _beqi a6, SYSXTENSA_ATOMIC_ADD, .Ladd
+
+ /* Fall through for SYSXTENSA_ATOMIC_CMP_SWP */
+
+.Lswp: /* Atomic compare and swap */
+
+TRY l32i a7, a3, 0 # read old value
+ bne a7, a4, 1f # same as old value? jump
+ s32i a5, a3, 0 # different, modify value
+ movi a7, 1 # and return 1
+ j .Lret
+
+1: movi a7, 0 # same values: return 0
+ j .Lret
+
+.Ladd: /* Atomic add */
+.Lexg: /* Atomic (exchange) add */
+
+TRY l32i a7, a3, 0
+ add a4, a4, a7
+ s32i a4, a3, 0
+ j .Lret
+
+.Lset: /* Atomic set */
+
+TRY l32i a7, a3, 0 # read old value as return value
+ s32i a4, a3, 0 # write new value
+
+.Lret: mov a0, a2
+ mov a2, a7
+ l32i a7, a0, PT_AREG7
+ l32i a3, a0, PT_AREG3
+ l32i a0, a0, PT_AREG0
+ rfe
+
+CATCH
+.Leac: movi a7, -EFAULT
+ j .Lret
+
+
+
+/* fast_syscall_spill_registers.
+ *
+ * Entry condition:
+ *
+ * a0: trashed, original value saved on stack (PT_AREG0)
+ * a1: a1
+ * a2: new stack pointer, original in DEPC
+ * a3: dispatch table
+ * depc: a2, original value saved on stack (PT_DEPC)
+ * excsave_1: a3
+ *
+ * Note: We assume the stack pointer is EXC_TABLE_KSTK in the fixup handler.
+ * Note: We don't need to save a2 in depc (return value)
+ */
+
+ENTRY(fast_syscall_spill_registers)
+
+ /* Register a FIXUP handler (pass current wb as a parameter) */
+
+ movi a0, fast_syscall_spill_registers_fixup
+ s32i a0, a3, EXC_TABLE_FIXUP
+ rsr a0, WINDOWBASE
+ s32i a0, a3, EXC_TABLE_PARAM
+
+ /* Save a3 and SAR on stack. */
+
+ rsr a0, SAR
+ xsr a3, EXCSAVE_1 # restore a3 and excsave_1
+ s32i a0, a2, PT_AREG4 # store SAR to PT_AREG4
+ s32i a3, a2, PT_AREG3
+
+ /* The spill routine might clobber a7, a11, and a15. */
+
+ s32i a7, a2, PT_AREG5
+ s32i a11, a2, PT_AREG6
+ s32i a15, a2, PT_AREG7
+
+ call0 _spill_registers # destroys a3, DEPC, and SAR
+
+ /* Advance PC, restore registers and SAR, and return from exception. */
+
+ l32i a3, a2, PT_AREG4
+ l32i a0, a2, PT_AREG0
+ wsr a3, SAR
+ l32i a3, a2, PT_AREG3
+
+ /* Restore clobbered registers. */
+
+ l32i a7, a2, PT_AREG5
+ l32i a11, a2, PT_AREG6
+ l32i a15, a2, PT_AREG7
+
+ movi a2, 0
+ rfe
+
+/* Fixup handler.
+ *
+ * We get here if the spill routine causes an exception, e.g. tlb miss.
+ * We basically restore WINDOWBASE and WINDOWSTART to the condition when
+ * we entered the spill routine and jump to the user exception handler.
+ *
+ * a0: value of depc, original value in depc
+ * a2: trashed, original value in EXC_TABLE_DOUBLE_SAVE
+ * a3: exctable, original value in excsave1
+ */
+
+fast_syscall_spill_registers_fixup:
+
+ rsr a2, WINDOWBASE # get current windowbase (a2 is saved)
+ xsr a0, DEPC # restore depc and a0
+ ssl a2 # set shift (32 - WB)
+
+ /* We need to make sure the current registers (a0-a3) are preserved.
+ * To do this, we simply set the bit for the current window frame
+ * in WS, so that the exception handlers save them to the task stack.
+ */
+
+ rsr a3, EXCSAVE_1 # get spill-mask
+ slli a2, a3, 1 # shift left by one
+
+ slli a3, a2, 32-WSBITS
+ src a2, a2, a3 # a1 = xxwww1yyxxxwww1yy......
+ wsr a2, WINDOWSTART # set corrected windowstart
+
+ movi a3, exc_table
+ l32i a2, a3, EXC_TABLE_DOUBLE_SAVE # restore a2
+ l32i a3, a3, EXC_TABLE_PARAM # original WB (in user task)
+
+ /* Return to the original (user task) WINDOWBASE.
+ * We leave the following frame behind:
+ * a0, a1, a2 same
+ * a3: trashed (saved in excsave_1)
+ * depc: depc (we have to return to that address)
+ * excsave_1: a3
+ */
+
+ wsr a3, WINDOWBASE
+ rsync
+
+ /* We are now in the original frame when we entered _spill_registers:
+ * a0: return address
+ * a1: used, stack pointer
+ * a2: kernel stack pointer
+ * a3: available, saved in EXCSAVE_1
+ * depc: exception address
+ * excsave: a3
+ * Note: This frame might be the same as above.
+ */
+
+#ifdef SIGNAL_HANDLING_IN_DOUBLE_EXCEPTION
+ /* Restore registers we precautiously saved.
+ * We have the value of the 'right' a3
+ */
+
+ l32i a7, a2, PT_AREG5
+ l32i a11, a2, PT_AREG6
+ l32i a15, a2, PT_AREG7
+#endif
+
+ /* Setup stack pointer. */
+
+ addi a2, a2, -PT_USER_SIZE
+ s32i a0, a2, PT_AREG0
+
+ /* Make sure we return to this fixup handler. */
+
+ movi a3, fast_syscall_spill_registers_fixup_return
+ s32i a3, a2, PT_DEPC # setup depc
+
+ /* Jump to the exception handler. */
+
+ movi a3, exc_table
+ rsr a0, EXCCAUSE
+ addx4 a0, a0, a3 # find entry in table
+ l32i a0, a0, EXC_TABLE_FAST_USER # load handler
+ jx a0
+
+fast_syscall_spill_registers_fixup_return:
+
+ /* When we return here, all registers have been restored (a2: DEPC) */
+
+ wsr a2, DEPC # exception address
+
+ /* Restore fixup handler. */
+
+ xsr a3, EXCSAVE_1
+ movi a2, fast_syscall_spill_registers_fixup
+ s32i a2, a3, EXC_TABLE_FIXUP
+ rsr a2, WINDOWBASE
+ s32i a2, a3, EXC_TABLE_PARAM
+ l32i a2, a3, EXC_TABLE_KSTK
+
+#ifdef SIGNAL_HANDLING_IN_DOUBLE_EXCEPTION
+ /* Save registers again that might be clobbered. */
+
+ s32i a7, a2, PT_AREG5
+ s32i a11, a2, PT_AREG6
+ s32i a15, a2, PT_AREG7
+#endif
+
+ /* Load WB at the time the exception occurred. */
+
+ rsr a3, SAR # WB is still in SAR
+ neg a3, a3
+ wsr a3, WINDOWBASE
+ rsync
+
+ /* Restore a3 and return. */
+
+ movi a3, exc_table
+ xsr a3, EXCSAVE_1
+
+ rfde
+
+
+/*
+ * spill all registers.
+ *
+ * This is not a real function. The following conditions must be met:
+ *
+ * - must be called with call0.
+ * - uses DEPC, a3 and SAR.
+ * - the last 'valid' register of each frame are clobbered.
+ * - the caller must have registered a fixup handler
+ * (or be inside a critical section)
+ * - PS_EXCM must be set (PS_WOE cleared?)
+ */
+
+ENTRY(_spill_registers)
+
+ /*
+ * Rotate ws so that the current windowbase is at bit 0.
+ * Assume ws = xxxwww1yy (www1 current window frame).
+ * Rotate ws right so that a2 = yyxxxwww1.
+ */
+
+ wsr a2, DEPC # preserve a2
+ rsr a2, WINDOWBASE
+ rsr a3, WINDOWSTART
+ ssr a2 # holds WB
+ slli a2, a3, WSBITS
+ or a3, a3, a2 # a2 = xxxwww1yyxxxwww1yy
+ srl a3, a3
+
+ /* We are done if there are no more than the current register frame. */
+
+ extui a3, a3, 1, WSBITS-2 # a3 = 0yyxxxwww
+ movi a2, (1 << (WSBITS-1))
+ _beqz a3, .Lnospill # only one active frame? jump
+
+ /* We want 1 at the top, so that we return to the current windowbase */
+
+ or a3, a3, a2 # 1yyxxxwww
+
+ /* Skip empty frames - get 'oldest' WINDOWSTART-bit. */
+
+ wsr a3, WINDOWSTART # save shifted windowstart
+ neg a2, a3
+ and a3, a2, a3 # first bit set from right: 000010000
+
+ ffs_ws a2, a3 # a2: shifts to skip empty frames
+ movi a3, WSBITS
+ sub a2, a3, a2 # WSBITS-a2:number of 0-bits from right
+ ssr a2 # save in SAR for later.
+
+ rsr a3, WINDOWBASE
+ add a3, a3, a2
+ rsr a2, DEPC # restore a2
+ wsr a3, WINDOWBASE
+ rsync
+
+ rsr a3, WINDOWSTART
+ srl a3, a3 # shift windowstart
+
+ /* WB is now just one frame below the oldest frame in the register
+ window. WS is shifted so the oldest frame is in bit 0, thus, WB
+ and WS differ by one 4-register frame. */
+
+ /* Save frames. Depending what call was used (call4, call8, call12),
+ * we have to save 4,8. or 12 registers.
+ */
+
+ _bbsi.l a3, 1, .Lc4
+ _bbsi.l a3, 2, .Lc8
+
+ /* Special case: we have a call12-frame starting at a4. */
+
+ _bbci.l a3, 3, .Lc12 # bit 3 shouldn't be zero! (Jump to Lc12 first)
+
+ s32e a4, a1, -16 # a1 is valid with an empty spill area
+ l32e a4, a5, -12
+ s32e a8, a4, -48
+ mov a8, a4
+ l32e a4, a1, -16
+ j .Lc12c
+
+.Lloop: _bbsi.l a3, 1, .Lc4
+ _bbci.l a3, 2, .Lc12
+
+.Lc8: s32e a4, a13, -16
+ l32e a4, a5, -12
+ s32e a8, a4, -32
+ s32e a5, a13, -12
+ s32e a6, a13, -8
+ s32e a7, a13, -4
+ s32e a9, a4, -28
+ s32e a10, a4, -24
+ s32e a11, a4, -20
+
+ srli a11, a3, 2 # shift windowbase by 2
+ rotw 2
+ _bnei a3, 1, .Lloop
+
+.Lexit: /* Done. Do the final rotation, set WS, and return. */
+
+ rotw 1
+ rsr a3, WINDOWBASE
+ ssl a3
+ movi a3, 1
+ sll a3, a3
+ wsr a3, WINDOWSTART
+
+.Lnospill:
+ jx a0
+
+.Lc4: s32e a4, a9, -16
+ s32e a5, a9, -12
+ s32e a6, a9, -8
+ s32e a7, a9, -4
+
+ srli a7, a3, 1
+ rotw 1
+ _bnei a3, 1, .Lloop
+ j .Lexit
+
+.Lc12: _bbci.l a3, 3, .Linvalid_mask # bit 2 shouldn't be zero!
+
+ /* 12-register frame (call12) */
+
+ l32e a2, a5, -12
+ s32e a8, a2, -48
+ mov a8, a2
+
+.Lc12c: s32e a9, a8, -44
+ s32e a10, a8, -40
+ s32e a11, a8, -36
+ s32e a12, a8, -32
+ s32e a13, a8, -28
+ s32e a14, a8, -24
+ s32e a15, a8, -20
+ srli a15, a3, 3
+
+ /* The stack pointer for a4..a7 is out of reach, so we rotate the
+ * window, grab the stackpointer, and rotate back.
+ * Alternatively, we could also use the following approach, but that
+ * makes the fixup routine much more complicated:
+ * rotw 1
+ * s32e a0, a13, -16
+ * ...
+ * rotw 2
+ */
+
+ rotw 1
+ mov a5, a13
+ rotw -1
+
+ s32e a4, a9, -16
+ s32e a5, a9, -12
+ s32e a6, a9, -8
+ s32e a7, a9, -4
+
+ rotw 3
+
+ _beqi a3, 1, .Lexit
+ j .Lloop
+
+.Linvalid_mask:
+
+ /* We get here because of an unrecoverable error in the window
+ * registers. If we are in user space, we kill the application,
+ * however, this condition is unrecoverable in kernel space.
+ */
+
+ rsr a0, PS
+ _bbci.l a0, PS_UM_SHIFT, 1f
+
+ /* User space: Setup a dummy frame and kill application.
+ * Note: We assume EXC_TABLE_KSTK contains a valid stack pointer.
+ */
+
+ movi a0, 1
+ movi a1, 0
+
+ wsr a0, WINDOWSTART
+ wsr a1, WINDOWBASE
+ rsync
+
+ movi a0, 0
+
+ movi a3, exc_table
+ l32i a1, a3, EXC_TABLE_KSTK
+ wsr a3, EXCSAVE_1
+
+ movi a4, PS_WOE_MASK | 1
+ wsr a4, PS
+ rsync
+
+ movi a6, SIGSEGV
+ movi a4, do_exit
+ callx4 a4
+
+1: /* Kernel space: PANIC! */
+
+ wsr a0, EXCSAVE_1
+ movi a0, unrecoverable_exception
+ callx0 a0 # should not return
+1: j 1b
+
+/*
+ * We should never get here. Bail out!
+ */
+
+ENTRY(fast_second_level_miss_double_kernel)
+
+1: movi a0, unrecoverable_exception
+ callx0 a0 # should not return
+1: j 1b
+
+/* First-level entry handler for user, kernel, and double 2nd-level
+ * TLB miss exceptions. Note that for now, user and kernel miss
+ * exceptions share the same entry point and are handled identically.
+ *
+ * An old, less-efficient C version of this function used to exist.
+ * We include it below, interleaved as comments, for reference.
+ *
+ * Entry condition:
+ *
+ * a0: trashed, original value saved on stack (PT_AREG0)
+ * a1: a1
+ * a2: new stack pointer, original in DEPC
+ * a3: dispatch table
+ * depc: a2, original value saved on stack (PT_DEPC)
+ * excsave_1: a3
+ *
+ * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
+ * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
+ */
+
+ENTRY(fast_second_level_miss)
+
+ /* Save a1. Note: we don't expect a double exception. */
+
+ s32i a1, a2, PT_AREG1
+
+ /* We need to map the page of PTEs for the user task. Find
+ * the pointer to that page. Also, it's possible for tsk->mm
+ * to be NULL while tsk->active_mm is nonzero if we faulted on
+ * a vmalloc address. In that rare case, we must use
+ * active_mm instead to avoid a fault in this handler. See
+ *
+ * http://mail.nl.linux.org/linux-mm/2002-08/msg00258.html
+ * (or search Internet on "mm vs. active_mm")
+ *
+ * if (!mm)
+ * mm = tsk->active_mm;
+ * pgd = pgd_offset (mm, regs->excvaddr);
+ * pmd = pmd_offset (pgd, regs->excvaddr);
+ * pmdval = *pmd;
+ */
+
+ GET_CURRENT(a1,a2)
+ l32i a0, a1, TASK_MM # tsk->mm
+ beqz a0, 9f
+
+8: rsr a1, EXCVADDR # fault address
+ _PGD_OFFSET(a0, a1, a1)
+ l32i a0, a0, 0 # read pmdval
+ //beqi a0, _PAGE_USER, 2f
+ beqz a0, 2f
+
+ /* Read ptevaddr and convert to top of page-table page.
+ *
+ * vpnval = read_ptevaddr_register() & PAGE_MASK;
+ * vpnval += DTLB_WAY_PGTABLE;
+ * pteval = mk_pte (virt_to_page(pmd_val(pmdval)), PAGE_KERNEL);
+ * write_dtlb_entry (pteval, vpnval);
+ *
+ * The messy computation for 'pteval' above really simplifies
+ * into the following:
+ *
+ * pteval = ((pmdval - PAGE_OFFSET) & PAGE_MASK) | PAGE_KERNEL
+ */
+
+ movi a1, -PAGE_OFFSET
+ add a0, a0, a1 # pmdval - PAGE_OFFSET
+ extui a1, a0, 0, PAGE_SHIFT # ... & PAGE_MASK
+ xor a0, a0, a1
+
+
+ movi a1, PAGE_DIRECTORY
+ or a0, a0, a1 # ... | PAGE_DIRECTORY
+
+ rsr a1, PTEVADDR
+ srli a1, a1, PAGE_SHIFT
+ slli a1, a1, PAGE_SHIFT # ptevaddr & PAGE_MASK
+ addi a1, a1, DTLB_WAY_PGTABLE # ... + way_number
+
+ wdtlb a0, a1
+ dsync
+
+ /* Exit critical section. */
+
+ movi a0, 0
+ s32i a0, a3, EXC_TABLE_FIXUP
+
+ /* Restore the working registers, and return. */
+
+ l32i a0, a2, PT_AREG0
+ l32i a1, a2, PT_AREG1
+ l32i a2, a2, PT_DEPC
+ xsr a3, EXCSAVE_1
+
+ bgeui a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
+
+ /* Restore excsave1 and return. */
+
+ rsr a2, DEPC
+ rfe
+
+ /* Return from double exception. */
+
+1: xsr a2, DEPC
+ esync
+ rfde
+
+9: l32i a0, a1, TASK_ACTIVE_MM # unlikely case mm == 0
+ j 8b
+
+2: /* Invalid PGD, default exception handling */
+
+ rsr a1, DEPC
+ xsr a3, EXCSAVE_1
+ s32i a1, a2, PT_AREG2
+ s32i a3, a2, PT_AREG3
+ mov a1, a2
+
+ rsr a2, PS
+ bbsi.l a2, PS_UM_SHIFT, 1f
+ j _kernel_exception
+1: j _user_exception
+
+
+/*
+ * StoreProhibitedException
+ *
+ * Update the pte and invalidate the itlb mapping for this pte.
+ *
+ * Entry condition:
+ *
+ * a0: trashed, original value saved on stack (PT_AREG0)
+ * a1: a1
+ * a2: new stack pointer, original in DEPC
+ * a3: dispatch table
+ * depc: a2, original value saved on stack (PT_DEPC)
+ * excsave_1: a3
+ *
+ * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
+ * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
+ */
+
+ENTRY(fast_store_prohibited)
+
+ /* Save a1 and a4. */
+
+ s32i a1, a2, PT_AREG1
+ s32i a4, a2, PT_AREG4
+
+ GET_CURRENT(a1,a2)
+ l32i a0, a1, TASK_MM # tsk->mm
+ beqz a0, 9f
+
+8: rsr a1, EXCVADDR # fault address
+ _PGD_OFFSET(a0, a1, a4)
+ l32i a0, a0, 0
+ //beqi a0, _PAGE_USER, 2f # FIXME use _PAGE_INVALID
+ beqz a0, 2f
+
+ _PTE_OFFSET(a0, a1, a4)
+ l32i a4, a0, 0 # read pteval
+ movi a1, _PAGE_VALID | _PAGE_RW
+ bnall a4, a1, 2f
+
+ movi a1, _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_WRENABLE
+ or a4, a4, a1
+ rsr a1, EXCVADDR
+ s32i a4, a0, 0
+
+ /* We need to flush the cache if we have page coloring. */
+#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
+ dhwb a0, 0
+#endif
+ pdtlb a0, a1
+ beqz a0, 1f
+ idtlb a0 // FIXME do we need this?
+ wdtlb a4, a0
+1:
+
+ /* Exit critical section. */
+
+ movi a0, 0
+ s32i a0, a3, EXC_TABLE_FIXUP
+
+ /* Restore the working registers, and return. */
+
+ l32i a4, a2, PT_AREG4
+ l32i a1, a2, PT_AREG1
+ l32i a0, a2, PT_AREG0
+ l32i a2, a2, PT_DEPC
+
+ /* Restore excsave1 and a3. */
+
+ xsr a3, EXCSAVE_1
+ bgeui a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
+
+ rsr a2, DEPC
+ rfe
+
+ /* Double exception. Restore FIXUP handler and return. */
+
+1: xsr a2, DEPC
+ esync
+ rfde
+
+9: l32i a0, a1, TASK_ACTIVE_MM # unlikely case mm == 0
+ j 8b
+
+2: /* If there was a problem, handle fault in C */
+
+ rsr a4, DEPC # still holds a2
+ xsr a3, EXCSAVE_1
+ s32i a4, a2, PT_AREG2
+ s32i a3, a2, PT_AREG3
+ l32i a4, a2, PT_AREG4
+ mov a1, a2
+
+ rsr a2, PS
+ bbsi.l a2, PS_UM_SHIFT, 1f
+ j _kernel_exception
+1: j _user_exception
+
+
+#if XCHAL_EXTRA_SA_SIZE
+
+#warning fast_coprocessor untested
+
+/*
+ * Entry condition:
+ *
+ * a0: trashed, original value saved on stack (PT_AREG0)
+ * a1: a1
+ * a2: new stack pointer, original in DEPC
+ * a3: dispatch table
+ * depc: a2, original value saved on stack (PT_DEPC)
+ * excsave_1: a3
+ *
+ * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
+ * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
+ */
+
+ENTRY(fast_coprocessor_double)
+ wsr a0, EXCSAVE_1
+ movi a0, unrecoverable_exception
+ callx0 a0
+
+ENTRY(fast_coprocessor)
+
+ /* Fatal if we are in a double exception. */
+
+ l32i a0, a2, PT_DEPC
+ _bgeui a0, VALID_DOUBLE_EXCEPTION_ADDRESS, fast_coprocessor_double
+
+ /* Save some registers a1, a3, a4, SAR */
+
+ xsr a3, EXCSAVE_1
+ s32i a3, a2, PT_AREG3
+ rsr a3, SAR
+ s32i a4, a2, PT_AREG4
+ s32i a1, a2, PT_AREG1
+ s32i a5, a1, PT_AREG5
+ s32i a3, a2, PT_SAR
+ mov a1, a2
+
+ /* Currently, the HAL macros only guarantee saving a0 and a1.
+ * These can and will be refined in the future, but for now,
+ * just save the remaining registers of a2...a15.
+ */
+ s32i a6, a1, PT_AREG6
+ s32i a7, a1, PT_AREG7
+ s32i a8, a1, PT_AREG8
+ s32i a9, a1, PT_AREG9
+ s32i a10, a1, PT_AREG10
+ s32i a11, a1, PT_AREG11
+ s32i a12, a1, PT_AREG12
+ s32i a13, a1, PT_AREG13
+ s32i a14, a1, PT_AREG14
+ s32i a15, a1, PT_AREG15
+
+ /* Find coprocessor number. Subtract first CP EXCCAUSE from EXCCAUSE */
+
+ rsr a0, EXCCAUSE
+ addi a3, a0, -XCHAL_EXCCAUSE_COPROCESSOR0_DISABLED
+
+ /* Set corresponding CPENABLE bit */
+
+ movi a4, 1
+ ssl a3 # SAR: 32 - coprocessor_number
+ rsr a5, CPENABLE
+ sll a4, a4
+ or a4, a5, a4
+ wsr a4, CPENABLE
+ rsync
+ movi a5, coprocessor_info # list of owner and offset into cp_save
+ addx8 a0, a4, a5 # entry for CP
+
+ bne a4, a5, .Lload # bit wasn't set before, cp not in use
+
+ /* Now compare the current task with the owner of the coprocessor.
+ * If they are the same, there is no reason to save or restore any
+ * coprocessor state. Having already enabled the coprocessor,
+ * branch ahead to return.
+ */
+ GET_CURRENT(a5,a1)
+ l32i a4, a0, COPROCESSOR_INFO_OWNER # a4: current owner for this CP
+ beq a4, a5, .Ldone
+
+ /* Find location to dump current coprocessor state:
+ * task_struct->task_cp_save_offset + coprocessor_offset[coprocessor]
+ *
+ * Note: a0 pointer to the entry in the coprocessor owner table,
+ * a3 coprocessor number,
+ * a4 current owner of coprocessor.
+ */
+ l32i a5, a0, COPROCESSOR_INFO_OFFSET
+ addi a2, a4, THREAD_CP_SAVE
+ add a2, a2, a5
+
+ /* Store current coprocessor states. (a5 still has CP number) */
+
+ xchal_cpi_store_funcbody
+
+ /* The macro might have destroyed a3 (coprocessor number), but
+ * SAR still has 32 - coprocessor_number!
+ */
+ movi a3, 32
+ rsr a4, SAR
+ sub a3, a3, a4
+
+.Lload: /* A new task now owns the corpocessors. Save its TCB pointer into
+ * the coprocessor owner table.
+ *
+ * Note: a0 pointer to the entry in the coprocessor owner table,
+ * a3 coprocessor number.
+ */
+ GET_CURRENT(a4,a1)
+ s32i a4, a0, 0
+
+ /* Find location from where to restore the current coprocessor state.*/
+
+ l32i a5, a0, COPROCESSOR_INFO_OFFSET
+ addi a2, a4, THREAD_CP_SAVE
+ add a2, a2, a4
+
+ xchal_cpi_load_funcbody
+
+ /* We must assume that the xchal_cpi_store_funcbody macro destroyed
+ * registers a2..a15.
+ */
+
+.Ldone: l32i a15, a1, PT_AREG15
+ l32i a14, a1, PT_AREG14
+ l32i a13, a1, PT_AREG13
+ l32i a12, a1, PT_AREG12
+ l32i a11, a1, PT_AREG11
+ l32i a10, a1, PT_AREG10
+ l32i a9, a1, PT_AREG9
+ l32i a8, a1, PT_AREG8
+ l32i a7, a1, PT_AREG7
+ l32i a6, a1, PT_AREG6
+ l32i a5, a1, PT_AREG5
+ l32i a4, a1, PT_AREG4
+ l32i a3, a1, PT_AREG3
+ l32i a2, a1, PT_AREG2
+ l32i a0, a1, PT_AREG0
+ l32i a1, a1, PT_AREG1
+
+ rfe
+
+#endif /* XCHAL_EXTRA_SA_SIZE */
+
+/*
+ * Task switch.
+ *
+ * struct task* _switch_to (struct task* prev, struct task* next)
+ * a2 a2 a3
+ */
+
+ENTRY(_switch_to)
+
+ entry a1, 16
+
+ mov a4, a3 # preserve a3
+
+ s32i a0, a2, THREAD_RA # save return address
+ s32i a1, a2, THREAD_SP # save stack pointer
+
+ /* Disable ints while we manipulate the stack pointer; spill regs. */
+
+ movi a5, PS_EXCM_MASK | LOCKLEVEL
+ xsr a5, PS
+ rsr a3, EXCSAVE_1
+ rsync
+ s32i a3, a3, EXC_TABLE_FIXUP /* enter critical section */
+
+ call0 _spill_registers
+
+ /* Set kernel stack (and leave critical section)
+ * Note: It's save to set it here. The stack will not be overwritten
+ * because the kernel stack will only be loaded again after
+ * we return from kernel space.
+ */
+
+ l32i a0, a4, TASK_THREAD_INFO
+ rsr a3, EXCSAVE_1 # exc_table
+ movi a1, 0
+ addi a0, a0, PT_REGS_OFFSET
+ s32i a1, a3, EXC_TABLE_FIXUP
+ s32i a0, a3, EXC_TABLE_KSTK
+
+ /* restore context of the task that 'next' addresses */
+
+ l32i a0, a4, THREAD_RA /* restore return address */
+ l32i a1, a4, THREAD_SP /* restore stack pointer */
+
+ wsr a5, PS
+ rsync
+
+ retw
+
+
+ENTRY(ret_from_fork)
+
+ /* void schedule_tail (struct task_struct *prev)
+ * Note: prev is still in a6 (return value from fake call4 frame)
+ */
+ movi a4, schedule_tail
+ callx4 a4
+
+ movi a4, do_syscall_trace
+ callx4 a4
+
+ j common_exception_return
+
+
+
+/*
+ * Table of syscalls
+ */
+
+.data
+.align 4
+.global sys_call_table
+sys_call_table:
+
+#define SYSCALL(call, narg) .word call
+#include "syscalls.h"
+
+/*
+ * Number of arguments of each syscall
+ */
+
+.global sys_narg_table
+sys_narg_table:
+
+#undef SYSCALL
+#define SYSCALL(call, narg) .byte narg
+#include "syscalls.h"
+
diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S
new file mode 100644
index 00000000000..6e9b5225b8f
--- /dev/null
+++ b/arch/xtensa/kernel/head.S
@@ -0,0 +1,237 @@
+/*
+ * arch/xtensa/kernel/head.S
+ *
+ * Xtensa Processor startup code.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ * Marc Gauthier <marc@tensilica.com, marc@alumni.uwaterloo.ca>
+ * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
+ * Kevin Chea
+ */
+
+#include <xtensa/cacheasm.h>
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+
+/*
+ * This module contains the entry code for kernel images. It performs the
+ * minimal setup needed to call the generic C routines.
+ *
+ * Prerequisites:
+ *
+ * - The kernel image has been loaded to the actual address where it was
+ * compiled to.
+ * - a2 contains either 0 or a pointer to a list of boot parameters.
+ * (see setup.c for more details)
+ *
+ */
+
+ .macro iterate from, to , cmd
+ .ifeq ((\to - \from) & ~0xfff)
+ \cmd \from
+ iterate "(\from+1)", \to, \cmd
+ .endif
+ .endm
+
+/*
+ * _start
+ *
+ * The bootloader passes a pointer to a list of boot parameters in a2.
+ */
+
+ /* The first bytes of the kernel image must be an instruction, so we
+ * manually allocate and define the literal constant we need for a jx
+ * instruction.
+ */
+
+ .section .head.text, "ax"
+ .globl _start
+_start: _j 2f
+ .align 4
+1: .word _startup
+2: l32r a0, 1b
+ jx a0
+
+ .text
+ .align 4
+_startup:
+
+ /* Disable interrupts and exceptions. */
+
+ movi a0, XCHAL_PS_EXCM_MASK
+ wsr a0, PS
+
+ /* Preserve the pointer to the boot parameter list in EXCSAVE_1 */
+
+ wsr a2, EXCSAVE_1
+
+ /* Start with a fresh windowbase and windowstart. */
+
+ movi a1, 1
+ movi a0, 0
+ wsr a1, WINDOWSTART
+ wsr a0, WINDOWBASE
+ rsync
+
+ /* Set a0 to 0 for the remaining initialization. */
+
+ movi a0, 0
+
+ /* Clear debugging registers. */
+
+#if XCHAL_HAVE_DEBUG
+ wsr a0, IBREAKENABLE
+ wsr a0, ICOUNT
+ movi a1, 15
+ wsr a0, ICOUNTLEVEL
+
+ .macro reset_dbreak num
+ wsr a0, DBREAKC + \num
+ .endm
+
+ iterate 0, XCHAL_NUM_IBREAK-1, reset_dbreak
+#endif
+
+ /* Clear CCOUNT (not really necessary, but nice) */
+
+ wsr a0, CCOUNT # not really necessary, but nice
+
+ /* Disable zero-loops. */
+
+#if XCHAL_HAVE_LOOPS
+ wsr a0, LCOUNT
+#endif
+
+ /* Disable all timers. */
+
+ .macro reset_timer num
+ wsr a0, CCOMPARE_0 + \num
+ .endm
+ iterate 0, XCHAL_NUM_TIMERS-1, reset_timer
+
+ /* Interrupt initialization. */
+
+ movi a2, XCHAL_INTTYPE_MASK_SOFTWARE | XCHAL_INTTYPE_MASK_EXTERN_EDGE
+ wsr a0, INTENABLE
+ wsr a2, INTCLEAR
+
+ /* Disable coprocessors. */
+
+#if XCHAL_CP_NUM > 0
+ wsr a0, CPENABLE
+#endif
+
+ /* Set PS.INTLEVEL=1, PS.WOE=0, kernel stack, PS.EXCM=0
+ *
+ * Note: PS.EXCM must be cleared before using any loop
+ * instructions; otherwise, they are silently disabled, and
+ * at most one iteration of the loop is executed.
+ */
+
+ movi a1, 1
+ wsr a1, PS
+ rsync
+
+ /* Initialize the caches.
+ * Does not include flushing writeback d-cache.
+ * a6, a7 are just working registers (clobbered).
+ */
+
+ icache_reset a2, a3
+ dcache_reset a2, a3
+
+ /* Unpack data sections
+ *
+ * The linker script used to build the Linux kernel image
+ * creates a table located at __boot_reloc_table_start
+ * that contans the information what data needs to be unpacked.
+ *
+ * Uses a2-a7.
+ */
+
+ movi a2, __boot_reloc_table_start
+ movi a3, __boot_reloc_table_end
+
+1: beq a2, a3, 3f # no more entries?
+ l32i a4, a2, 0 # start destination (in RAM)
+ l32i a5, a2, 4 # end desination (in RAM)
+ l32i a6, a2, 8 # start source (in ROM)
+ addi a2, a2, 12 # next entry
+ beq a4, a5, 1b # skip, empty entry
+ beq a4, a6, 1b # skip, source and dest. are the same
+
+2: l32i a7, a6, 0 # load word
+ addi a6, a6, 4
+ s32i a7, a4, 0 # store word
+ addi a4, a4, 4
+ bltu a4, a5, 2b
+ j 1b
+
+3:
+ /* All code and initialized data segments have been copied.
+ * Now clear the BSS segment.
+ */
+
+ movi a2, _bss_start # start of BSS
+ movi a3, _bss_end # end of BSS
+
+1: addi a2, a2, 4
+ s32i a0, a2, 0
+ blt a2, a3, 1b
+
+#if XCHAL_DCACHE_IS_WRITEBACK
+
+ /* After unpacking, flush the writeback cache to memory so the
+ * instructions/data are available.
+ */
+
+ dcache_writeback_all a2, a3
+#endif
+
+ /* Setup stack and enable window exceptions (keep irqs disabled) */
+
+ movi a1, init_thread_union
+ addi a1, a1, KERNEL_STACK_SIZE
+
+ movi a2, 0x00040001 # WOE=1, INTLEVEL=1, UM=0
+ wsr a2, PS # (enable reg-windows; progmode stack)
+ rsync
+
+ /* Set up EXCSAVE[DEBUGLEVEL] to point to the Debug Exception Handler.*/
+
+ movi a2, debug_exception
+ wsr a2, EXCSAVE + XCHAL_DEBUGLEVEL
+
+ /* Set up EXCSAVE[1] to point to the exc_table. */
+
+ movi a6, exc_table
+ xsr a6, EXCSAVE_1
+
+ /* init_arch kick-starts the linux kernel */
+
+ movi a4, init_arch
+ callx4 a4
+
+ movi a4, start_kernel
+ callx4 a4
+
+should_never_return:
+ j should_never_return
+
+ /* Define some common data structures here. We define them
+ * here in this assembly file due to their unusual alignment
+ * requirements.
+ */
+
+ .comm swapper_pg_dir,PAGE_SIZE,PAGE_SIZE
+ .comm empty_bad_page_table,PAGE_SIZE,PAGE_SIZE
+ .comm empty_bad_page,PAGE_SIZE,PAGE_SIZE
+ .comm empty_zero_page,PAGE_SIZE,PAGE_SIZE
+
diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c
new file mode 100644
index 00000000000..4cbf6d91571
--- /dev/null
+++ b/arch/xtensa/kernel/irq.c
@@ -0,0 +1,192 @@
+/*
+ * linux/arch/xtensa/kernel/irq.c
+ *
+ * Xtensa built-in interrupt controller and some generic functions copied
+ * from i386.
+ *
+ * Copyright (C) 2002 - 2005 Tensilica, Inc.
+ * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
+ *
+ *
+ * Chris Zankel <chris@zankel.net>
+ * Kevin Chea
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/uaccess.h>
+#include <asm/platform.h>
+
+static void enable_xtensa_irq(unsigned int irq);
+static void disable_xtensa_irq(unsigned int irq);
+static void mask_and_ack_xtensa(unsigned int irq);
+static void end_xtensa_irq(unsigned int irq);
+
+static unsigned int cached_irq_mask;
+
+atomic_t irq_err_count;
+
+/*
+ * 'what should we do if we get a hw irq event on an illegal vector'.
+ * each architecture has to answer this themselves.
+ */
+void ack_bad_irq(unsigned int irq)
+{
+ printk("unexpected IRQ trap at vector %02x\n", irq);
+}
+
+/*
+ * do_IRQ handles all normal device IRQ's (the special
+ * SMP cross-CPU interrupts have their own specific
+ * handlers).
+ */
+
+unsigned int do_IRQ(int irq, struct pt_regs *regs)
+{
+ irq_enter();
+
+#ifdef CONFIG_DEBUG_STACKOVERFLOW
+ /* Debugging check for stack overflow: is there less than 1KB free? */
+ {
+ unsigned long sp;
+
+ __asm__ __volatile__ ("mov %0, a1\n" : "=a" (sp));
+ sp &= THREAD_SIZE - 1;
+
+ if (unlikely(sp < (sizeof(thread_info) + 1024)))
+ printk("Stack overflow in do_IRQ: %ld\n",
+ sp - sizeof(struct thread_info));
+ }
+#endif
+
+ __do_IRQ(irq, regs);
+
+ irq_exit();
+
+ return 1;
+}
+
+/*
+ * Generic, controller-independent functions:
+ */
+
+int show_interrupts(struct seq_file *p, void *v)
+{
+ int i = *(loff_t *) v, j;
+ struct irqaction * action;
+ unsigned long flags;
+
+ if (i == 0) {
+ seq_printf(p, " ");
+ for (j=0; j<NR_CPUS; j++)
+ if (cpu_online(j))
+ seq_printf(p, "CPU%d ",j);
+ seq_putc(p, '\n');
+ }
+
+ if (i < NR_IRQS) {
+ spin_lock_irqsave(&irq_desc[i].lock, flags);
+ action = irq_desc[i].action;
+ if (!action)
+ goto skip;
+ seq_printf(p, "%3d: ",i);
+#ifndef CONFIG_SMP
+ seq_printf(p, "%10u ", kstat_irqs(i));
+#else
+ for (j = 0; j < NR_CPUS; j++)
+ if (cpu_online(j))
+ seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+#endif
+ seq_printf(p, " %14s", irq_desc[i].handler->typename);
+ seq_printf(p, " %s", action->name);
+
+ for (action=action->next; action; action = action->next)
+ seq_printf(p, ", %s", action->name);
+
+ seq_putc(p, '\n');
+skip:
+ spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+ } else if (i == NR_IRQS) {
+ seq_printf(p, "NMI: ");
+ for (j = 0; j < NR_CPUS; j++)
+ if (cpu_online(j))
+ seq_printf(p, "%10u ", nmi_count(j));
+ seq_putc(p, '\n');
+ seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
+ }
+ return 0;
+}
+/* shutdown is same as "disable" */
+#define shutdown_xtensa_irq disable_xtensa_irq
+
+static unsigned int startup_xtensa_irq(unsigned int irq)
+{
+ enable_xtensa_irq(irq);
+ return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type xtensa_irq_type = {
+ "Xtensa-IRQ",
+ startup_xtensa_irq,
+ shutdown_xtensa_irq,
+ enable_xtensa_irq,
+ disable_xtensa_irq,
+ mask_and_ack_xtensa,
+ end_xtensa_irq
+};
+
+static inline void mask_irq(unsigned int irq)
+{
+ cached_irq_mask &= ~(1 << irq);
+ set_sr (cached_irq_mask, INTENABLE);
+}
+
+static inline void unmask_irq(unsigned int irq)
+{
+ cached_irq_mask |= 1 << irq;
+ set_sr (cached_irq_mask, INTENABLE);
+}
+
+static void disable_xtensa_irq(unsigned int irq)
+{
+ unsigned long flags;
+ local_save_flags(flags);
+ mask_irq(irq);
+ local_irq_restore(flags);
+}
+
+static void enable_xtensa_irq(unsigned int irq)
+{
+ unsigned long flags;
+ local_save_flags(flags);
+ unmask_irq(irq);
+ local_irq_restore(flags);
+}
+
+static void mask_and_ack_xtensa(unsigned int irq)
+{
+ disable_xtensa_irq(irq);
+}
+
+static void end_xtensa_irq(unsigned int irq)
+{
+ enable_xtensa_irq(irq);
+}
+
+
+void __init init_IRQ(void)
+{
+ int i;
+
+ for (i=0; i < XTENSA_NR_IRQS; i++)
+ irq_desc[i].handler = &xtensa_irq_type;
+
+ cached_irq_mask = 0;
+
+ platform_init_irq();
+}
diff --git a/arch/xtensa/kernel/module.c b/arch/xtensa/kernel/module.c
new file mode 100644
index 00000000000..d1683cfa19a
--- /dev/null
+++ b/arch/xtensa/kernel/module.c
@@ -0,0 +1,78 @@
+/*
+ * arch/xtensa/kernel/platform.c
+ *
+ * Module support.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/cache.h>
+
+LIST_HEAD(module_buf_list);
+
+void *module_alloc(unsigned long size)
+{
+ panic("module_alloc not implemented");
+}
+
+void module_free(struct module *mod, void *module_region)
+{
+ panic("module_free not implemented");
+}
+
+int module_frob_arch_sections(Elf32_Ehdr *hdr,
+ Elf32_Shdr *sechdrs,
+ char *secstrings,
+ struct module *me)
+{
+ panic("module_frob_arch_sections not implemented");
+}
+
+int apply_relocate(Elf32_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *module)
+{
+ panic ("apply_relocate not implemented");
+}
+
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+ const char *strtab,
+ unsigned int symindex,
+ unsigned int relsec,
+ struct module *module)
+{
+ panic("apply_relocate_add not implemented");
+}
+
+int module_finalize(const Elf_Ehdr *hdr,
+ const Elf_Shdr *sechdrs,
+ struct module *me)
+{
+ panic ("module_finalize not implemented");
+}
+
+void module_arch_cleanup(struct module *mod)
+{
+ panic("module_arch_cleanup not implemented");
+}
+
+struct bug_entry *module_find_bug(unsigned long bugaddr)
+{
+ panic("module_find_bug not implemented");
+}
diff --git a/arch/xtensa/kernel/pci-dma.c b/arch/xtensa/kernel/pci-dma.c
new file mode 100644
index 00000000000..84fde258cf8
--- /dev/null
+++ b/arch/xtensa/kernel/pci-dma.c
@@ -0,0 +1,73 @@
+/*
+ * arch/xtensa/pci-dma.c
+ *
+ * DMA coherent memory allocation.
+ *
+ * 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.
+ *
+ * Copyright (C) 2002 - 2005 Tensilica Inc.
+ *
+ * Based on version for i386.
+ *
+ * Chris Zankel <chris@zankel.net>
+ * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/cacheflush.h>
+
+/*
+ * Note: We assume that the full memory space is always mapped to 'kseg'
+ * Otherwise we have to use page attributes (not implemented).
+ */
+
+void *
+dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, int gfp)
+{
+ void *ret;
+
+ /* ignore region speicifiers */
+ gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
+
+ if (dev == NULL || (*dev->dma_mask < 0xffffffff))
+ gfp |= GFP_DMA;
+ ret = (void *)__get_free_pages(gfp, get_order(size));
+
+ if (ret != NULL) {
+ memset(ret, 0, size);
+ *handle = virt_to_bus(ret);
+ }
+ return (void*) BYPASS_ADDR((unsigned long)ret);
+}
+
+void dma_free_coherent(struct device *hwdev, size_t size,
+ void *vaddr, dma_addr_t dma_handle)
+{
+ free_pages(CACHED_ADDR((unsigned long)vaddr), get_order(size));
+}
+
+
+void consistent_sync(void *vaddr, size_t size, int direction)
+{
+ switch (direction) {
+ case PCI_DMA_NONE:
+ BUG();
+ case PCI_DMA_FROMDEVICE: /* invalidate only */
+ __invalidate_dcache_range((unsigned long)vaddr,
+ (unsigned long)size);
+ break;
+
+ case PCI_DMA_TODEVICE: /* writeback only */
+ case PCI_DMA_BIDIRECTIONAL: /* writeback and invalidate */
+ __flush_invalidate_dcache_range((unsigned long)vaddr,
+ (unsigned long)size);
+ break;
+ }
+}
diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c
new file mode 100644
index 00000000000..d29a8164863
--- /dev/null
+++ b/arch/xtensa/kernel/pci.c
@@ -0,0 +1,563 @@
+/*
+ * arch/xtensa/pcibios.c
+ *
+ * PCI bios-type initialisation for PCI machines
+ *
+ * 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.
+ *
+ * Copyright (C) 2001-2005 Tensilica Inc.
+ *
+ * Based largely on work from Cort (ppc/kernel/pci.c)
+ * IO functions copied from sparc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/bootmem.h>
+
+#include <asm/pci-bridge.h>
+#include <asm/platform.h>
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+/* PCI Controller */
+
+
+/*
+ * pcibios_alloc_controller
+ * pcibios_enable_device
+ * pcibios_fixups
+ * pcibios_align_resource
+ * pcibios_fixup_bus
+ * pcibios_setup
+ * pci_bus_add_device
+ * pci_mmap_page_range
+ */
+
+struct pci_controller* pci_ctrl_head;
+struct pci_controller** pci_ctrl_tail = &pci_ctrl_head;
+
+static int pci_bus_count;
+
+static void pcibios_fixup_resources(struct pci_dev* dev);
+
+#if 0 // FIXME
+struct pci_fixup pcibios_fixups[] = {
+ { DECLARE_PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources },
+ { 0 }
+};
+#endif
+
+void
+pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+ struct resource *res, int resource)
+{
+ u32 new, check, mask;
+ int reg;
+ struct pci_controller* pci_ctrl = dev->sysdata;
+
+ new = res->start;
+ if (pci_ctrl && res->flags & IORESOURCE_IO) {
+ new -= pci_ctrl->io_space.base;
+ }
+ new |= (res->flags & PCI_REGION_FLAG_MASK);
+ if (resource < 6) {
+ reg = PCI_BASE_ADDRESS_0 + 4*resource;
+ } else if (resource == PCI_ROM_RESOURCE) {
+ res->flags |= PCI_ROM_ADDRESS_ENABLE;
+ reg = dev->rom_base_reg;
+ } else {
+ /* Somebody might have asked allocation of a non-standard resource */
+ return;
+ }
+
+ pci_write_config_dword(dev, reg, new);
+ pci_read_config_dword(dev, reg, &check);
+ mask = (new & PCI_BASE_ADDRESS_SPACE_IO) ?
+ PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK;
+
+ if ((new ^ check) & mask) {
+ printk(KERN_ERR "PCI: Error while updating region "
+ "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
+ new, check);
+ }
+}
+
+/*
+ * We need to avoid collisions with `mirrored' VGA ports
+ * and other strange ISA hardware, so we always want the
+ * addresses to be allocated in the 0x000-0x0ff region
+ * modulo 0x400.
+ *
+ * Why? Because some silly external IO cards only decode
+ * the low 10 bits of the IO address. The 0x00-0xff region
+ * is reserved for motherboard devices that decode all 16
+ * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
+ * but we want to try to avoid allocating at 0x2900-0x2bff
+ * which might have be mirrored at 0x0100-0x03ff..
+ */
+void
+pcibios_align_resource(void *data, struct resource *res, unsigned long size,
+ unsigned long align)
+{
+ struct pci_dev *dev = data;
+
+ if (res->flags & IORESOURCE_IO) {
+ unsigned long start = res->start;
+
+ if (size > 0x100) {
+ printk(KERN_ERR "PCI: I/O Region %s/%d too large"
+ " (%ld bytes)\n", dev->slot_name,
+ dev->resource - res, size);
+ }
+
+ if (start & 0x300) {
+ start = (start + 0x3ff) & ~0x3ff;
+ res->start = start;
+ }
+ }
+}
+
+int
+pcibios_enable_resources(struct pci_dev *dev, int mask)
+{
+ u16 cmd, old_cmd;
+ int idx;
+ struct resource *r;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ old_cmd = cmd;
+ for(idx=0; idx<6; idx++) {
+ r = &dev->resource[idx];
+ if (!r->start && r->end) {
+ printk (KERN_ERR "PCI: Device %s not available because "
+ "of resource collisions\n", dev->slot_name);
+ return -EINVAL;
+ }
+ if (r->flags & IORESOURCE_IO)
+ cmd |= PCI_COMMAND_IO;
+ if (r->flags & IORESOURCE_MEM)
+ cmd |= PCI_COMMAND_MEMORY;
+ }
+ if (dev->resource[PCI_ROM_RESOURCE].start)
+ cmd |= PCI_COMMAND_MEMORY;
+ if (cmd != old_cmd) {
+ printk("PCI: Enabling device %s (%04x -> %04x)\n",
+ dev->slot_name, old_cmd, cmd);
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ }
+ return 0;
+}
+
+struct pci_controller * __init pcibios_alloc_controller(void)
+{
+ struct pci_controller *pci_ctrl;
+
+ pci_ctrl = (struct pci_controller *)alloc_bootmem(sizeof(*pci_ctrl));
+ memset(pci_ctrl, 0, sizeof(struct pci_controller));
+
+ *pci_ctrl_tail = pci_ctrl;
+ pci_ctrl_tail = &pci_ctrl->next;
+
+ return pci_ctrl;
+}
+
+static int __init pcibios_init(void)
+{
+ struct pci_controller *pci_ctrl;
+ struct pci_bus *bus;
+ int next_busno = 0, i;
+
+ printk("PCI: Probing PCI hardware\n");
+
+ /* Scan all of the recorded PCI controllers. */
+ for (pci_ctrl = pci_ctrl_head; pci_ctrl; pci_ctrl = pci_ctrl->next) {
+ pci_ctrl->last_busno = 0xff;
+ bus = pci_scan_bus(pci_ctrl->first_busno, pci_ctrl->ops,
+ pci_ctrl);
+ if (pci_ctrl->io_resource.flags) {
+ unsigned long offs;
+
+ offs = (unsigned long)pci_ctrl->io_space.base;
+ pci_ctrl->io_resource.start += offs;
+ pci_ctrl->io_resource.end += offs;
+ bus->resource[0] = &pci_ctrl->io_resource;
+ }
+ for (i = 0; i < 3; ++i)
+ if (pci_ctrl->mem_resources[i].flags)
+ bus->resource[i+1] =&pci_ctrl->mem_resources[i];
+ pci_ctrl->bus = bus;
+ pci_ctrl->last_busno = bus->subordinate;
+ if (next_busno <= pci_ctrl->last_busno)
+ next_busno = pci_ctrl->last_busno+1;
+ }
+ pci_bus_count = next_busno;
+
+ return platform_pcibios_fixup();
+}
+
+subsys_initcall(pcibios_init);
+
+void __init pcibios_fixup_bus(struct pci_bus *bus)
+{
+ struct pci_controller *pci_ctrl = bus->sysdata;
+ struct resource *res;
+ unsigned long io_offset;
+ int i;
+
+ io_offset = (unsigned long)pci_ctrl->io_space.base;
+ if (bus->parent == NULL) {
+ /* this is a host bridge - fill in its resources */
+ pci_ctrl->bus = bus;
+
+ bus->resource[0] = res = &pci_ctrl->io_resource;
+ if (!res->flags) {
+ if (io_offset)
+ printk (KERN_ERR "I/O resource not set for host"
+ " bridge %d\n", pci_ctrl->index);
+ res->start = 0;
+ res->end = IO_SPACE_LIMIT;
+ res->flags = IORESOURCE_IO;
+ }
+ res->start += io_offset;
+ res->end += io_offset;
+
+ for (i = 0; i < 3; i++) {
+ res = &pci_ctrl->mem_resources[i];
+ if (!res->flags) {
+ if (i > 0)
+ continue;
+ printk(KERN_ERR "Memory resource not set for "
+ "host bridge %d\n", pci_ctrl->index);
+ res->start = 0;
+ res->end = ~0U;
+ res->flags = IORESOURCE_MEM;
+ }
+ bus->resource[i+1] = res;
+ }
+ } else {
+ /* This is a subordinate bridge */
+ pci_read_bridge_bases(bus);
+
+ for (i = 0; i < 4; i++) {
+ if ((res = bus->resource[i]) == NULL || !res->flags)
+ continue;
+ if (io_offset && (res->flags & IORESOURCE_IO)) {
+ res->start += io_offset;
+ res->end += io_offset;
+ }
+ }
+ }
+}
+
+char __init *pcibios_setup(char *str)
+{
+ return str;
+}
+
+/* the next one is stolen from the alpha port... */
+
+void __init
+pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+}
+
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+ u16 cmd, old_cmd;
+ int idx;
+ struct resource *r;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ old_cmd = cmd;
+ for (idx=0; idx<6; idx++) {
+ r = &dev->resource[idx];
+ if (!r->start && r->end) {
+ printk(KERN_ERR "PCI: Device %s not available because "
+ "of resource collisions\n", dev->slot_name);
+ return -EINVAL;
+ }
+ if (r->flags & IORESOURCE_IO)
+ cmd |= PCI_COMMAND_IO;
+ if (r->flags & IORESOURCE_MEM)
+ cmd |= PCI_COMMAND_MEMORY;
+ }
+ if (cmd != old_cmd) {
+ printk("PCI: Enabling device %s (%04x -> %04x)\n",
+ dev->slot_name, old_cmd, cmd);
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_PROC_FS
+
+/*
+ * Return the index of the PCI controller for device pdev.
+ */
+
+int
+pci_controller_num(struct pci_dev *dev)
+{
+ struct pci_controller *pci_ctrl = (struct pci_controller*) dev->sysdata;
+ return pci_ctrl->index;
+}
+
+#endif /* CONFIG_PROC_FS */
+
+
+static void
+pcibios_fixup_resources(struct pci_dev *dev)
+{
+ struct pci_controller* pci_ctrl = (struct pci_controller *)dev->sysdata;
+ int i;
+ unsigned long offset;
+
+ if (!pci_ctrl) {
+ printk(KERN_ERR "No pci_ctrl for PCI dev %s!\n",dev->slot_name);
+ return;
+ }
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+ struct resource *res = dev->resource + i;
+ if (!res->start || !res->flags)
+ continue;
+ if (res->end == 0xffffffff) {
+ DBG("PCI:%s Resource %d [%08lx-%08lx] is unassigned\n",
+ dev->slot_name, i, res->start, res->end);
+ res->end -= res->start;
+ res->start = 0;
+ continue;
+ }
+ offset = 0;
+ if (res->flags & IORESOURCE_IO)
+ offset = (unsigned long) pci_ctrl->io_space.base;
+ else if (res->flags & IORESOURCE_MEM)
+ offset = (unsigned long) pci_ctrl->mem_space.base;
+
+ if (offset != 0) {
+ res->start += offset;
+ res->end += offset;
+#ifdef DEBUG
+ printk("Fixup res %d (%lx) of dev %s: %lx -> %lx\n",
+ i, res->flags, dev->slot_name,
+ res->start - offset, res->start);
+#endif
+ }
+ }
+}
+
+/*
+ * Platform support for /proc/bus/pci/X/Y mmap()s,
+ * modelled on the sparc64 implementation by Dave Miller.
+ * -- paulus.
+ */
+
+/*
+ * Adjust vm_pgoff of VMA such that it is the physical page offset
+ * corresponding to the 32-bit pci bus offset for DEV requested by the user.
+ *
+ * Basically, the user finds the base address for his device which he wishes
+ * to mmap. They read the 32-bit value from the config space base register,
+ * add whatever PAGE_SIZE multiple offset they wish, and feed this into the
+ * offset parameter of mmap on /proc/bus/pci/XXX for that device.
+ *
+ * Returns negative error code on failure, zero on success.
+ */
+static __inline__ int
+__pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state)
+{
+ struct pci_controller *pci_ctrl = (struct pci_controller*) dev->sysdata;
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+ unsigned long io_offset = 0;
+ int i, res_bit;
+
+ if (pci_ctrl == 0)
+ return -EINVAL; /* should never happen */
+
+ /* If memory, add on the PCI bridge address offset */
+ if (mmap_state == pci_mmap_mem) {
+ res_bit = IORESOURCE_MEM;
+ } else {
+ io_offset = (unsigned long)pci_ctrl->io_space.base;
+ offset += io_offset;
+ res_bit = IORESOURCE_IO;
+ }
+
+ /*
+ * Check that the offset requested corresponds to one of the
+ * resources of the device.
+ */
+ for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
+ struct resource *rp = &dev->resource[i];
+ int flags = rp->flags;
+
+ /* treat ROM as memory (should be already) */
+ if (i == PCI_ROM_RESOURCE)
+ flags |= IORESOURCE_MEM;
+
+ /* Active and same type? */
+ if ((flags & res_bit) == 0)
+ continue;
+
+ /* In the range of this resource? */
+ if (offset < (rp->start & PAGE_MASK) || offset > rp->end)
+ continue;
+
+ /* found it! construct the final physical address */
+ if (mmap_state == pci_mmap_io)
+ offset += pci_ctrl->io_space.start - io_offset;
+ vma->vm_pgoff = offset >> PAGE_SHIFT;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+/*
+ * Set vm_flags of VMA, as appropriate for this architecture, for a pci device
+ * mapping.
+ */
+static __inline__ void
+__pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state)
+{
+ vma->vm_flags |= VM_SHM | VM_LOCKED | VM_IO;
+}
+
+/*
+ * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
+ * device mapping.
+ */
+static __inline__ void
+__pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state, int write_combine)
+{
+ int prot = pgprot_val(vma->vm_page_prot);
+
+ /* Set to write-through */
+ prot &= ~_PAGE_NO_CACHE;
+#if 0
+ if (!write_combine)
+ prot |= _PAGE_WRITETHRU;
+#endif
+ vma->vm_page_prot = __pgprot(prot);
+}
+
+/*
+ * Perform the actual remap of the pages for a PCI device mapping, as
+ * appropriate for this architecture. The region in the process to map
+ * is described by vm_start and vm_end members of VMA, the base physical
+ * address is found in vm_pgoff.
+ * The pci device structure is provided so that architectures may make mapping
+ * decisions on a per-device or per-bus basis.
+ *
+ * Returns a negative error code on failure, zero on success.
+ */
+int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state,
+ int write_combine)
+{
+ int ret;
+
+ ret = __pci_mmap_make_offset(dev, vma, mmap_state);
+ if (ret < 0)
+ return ret;
+
+ __pci_mmap_set_flags(dev, vma, mmap_state);
+ __pci_mmap_set_pgprot(dev, vma, mmap_state, write_combine);
+
+ ret = io_remap_page_range(vma, vma->vm_start, vma->vm_pgoff<<PAGE_SHIFT,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot);
+
+ return ret;
+}
+
+/*
+ * This probably belongs here rather than ioport.c because
+ * we do not want this crud linked into SBus kernels.
+ * Also, think for a moment about likes of floppy.c that
+ * include architecture specific parts. They may want to redefine ins/outs.
+ *
+ * We do not use horroble macroses here because we want to
+ * advance pointer by sizeof(size).
+ */
+void outsb(unsigned long addr, const void *src, unsigned long count) {
+ while (count) {
+ count -= 1;
+ writeb(*(const char *)src, addr);
+ src += 1;
+ addr += 1;
+ }
+}
+
+void outsw(unsigned long addr, const void *src, unsigned long count) {
+ while (count) {
+ count -= 2;
+ writew(*(const short *)src, addr);
+ src += 2;
+ addr += 2;
+ }
+}
+
+void outsl(unsigned long addr, const void *src, unsigned long count) {
+ while (count) {
+ count -= 4;
+ writel(*(const long *)src, addr);
+ src += 4;
+ addr += 4;
+ }
+}
+
+void insb(unsigned long addr, void *dst, unsigned long count) {
+ while (count) {
+ count -= 1;
+ *(unsigned char *)dst = readb(addr);
+ dst += 1;
+ addr += 1;
+ }
+}
+
+void insw(unsigned long addr, void *dst, unsigned long count) {
+ while (count) {
+ count -= 2;
+ *(unsigned short *)dst = readw(addr);
+ dst += 2;
+ addr += 2;
+ }
+}
+
+void insl(unsigned long addr, void *dst, unsigned long count) {
+ while (count) {
+ count -= 4;
+ /*
+ * XXX I am sure we are in for an unaligned trap here.
+ */
+ *(unsigned long *)dst = readl(addr);
+ dst += 4;
+ addr += 4;
+ }
+}
+
+
+
diff --git a/arch/xtensa/kernel/platform.c b/arch/xtensa/kernel/platform.c
new file mode 100644
index 00000000000..cf136278444
--- /dev/null
+++ b/arch/xtensa/kernel/platform.c
@@ -0,0 +1,49 @@
+/*
+ * arch/xtensa/kernel/platform.c
+ *
+ * Default platform functions.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2005 Tensilica Inc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/time.h>
+#include <asm/platform.h>
+#include <asm/timex.h>
+
+#define _F(r,f,a,b) \
+ r __platform_##f a b; \
+ r platform_##f a __attribute__((weak, alias("__platform_"#f)))
+
+/*
+ * Default functions that are used if no platform specific function is defined.
+ * (Please, refer to include/asm-xtensa/platform.h for more information)
+ */
+
+_F(void, setup, (char** cmd), { });
+_F(void, init_irq, (void), { });
+_F(void, restart, (void), { while(1); });
+_F(void, halt, (void), { while(1); });
+_F(void, power_off, (void), { while(1); });
+_F(void, idle, (void), { __asm__ __volatile__ ("waiti 0" ::: "memory"); });
+_F(void, heartbeat, (void), { });
+_F(int, pcibios_fixup, (void), { return 0; });
+_F(int, get_rtc_time, (time_t* t), { return 0; });
+_F(int, set_rtc_time, (time_t t), { return 0; });
+
+#if CONFIG_XTENSA_CALIBRATE_CCOUNT
+_F(void, calibrate_ccount, (void),
+{
+ printk ("ERROR: Cannot calibrate cpu frequency! Assuming 100MHz.\n");
+ ccount_per_jiffy = 100 * (1000000UL/HZ);
+});
+#endif
+
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c
new file mode 100644
index 00000000000..4099703b14b
--- /dev/null
+++ b/arch/xtensa/kernel/process.c
@@ -0,0 +1,482 @@
+// TODO verify coprocessor handling
+/*
+ * arch/xtensa/kernel/process.c
+ *
+ * Xtensa Processor version.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ *
+ * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
+ * Chris Zankel <chris@zankel.net>
+ * Marc Gauthier <marc@tensilica.com, marc@alumni.uwaterloo.ca>
+ * Kevin Chea
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/elf.h>
+#include <linux/init.h>
+#include <linux/prctl.h>
+#include <linux/init_task.h>
+#include <linux/module.h>
+#include <linux/mqueue.h>
+
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/platform.h>
+#include <asm/mmu.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+#include <asm/offsets.h>
+#include <asm/coprocessor.h>
+
+extern void ret_from_fork(void);
+
+static struct fs_struct init_fs = INIT_FS;
+static struct files_struct init_files = INIT_FILES;
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
+struct mm_struct init_mm = INIT_MM(init_mm);
+EXPORT_SYMBOL(init_mm);
+
+union thread_union init_thread_union
+ __attribute__((__section__(".data.init_task"))) =
+{ INIT_THREAD_INFO(init_task) };
+
+struct task_struct init_task = INIT_TASK(init_task);
+EXPORT_SYMBOL(init_task);
+
+struct task_struct *current_set[NR_CPUS] = {&init_task, };
+
+
+#if XCHAL_CP_NUM > 0
+
+/*
+ * Coprocessor ownership.
+ */
+
+coprocessor_info_t coprocessor_info[] = {
+ { 0, XTENSA_CPE_CP0_OFFSET },
+ { 0, XTENSA_CPE_CP1_OFFSET },
+ { 0, XTENSA_CPE_CP2_OFFSET },
+ { 0, XTENSA_CPE_CP3_OFFSET },
+ { 0, XTENSA_CPE_CP4_OFFSET },
+ { 0, XTENSA_CPE_CP5_OFFSET },
+ { 0, XTENSA_CPE_CP6_OFFSET },
+ { 0, XTENSA_CPE_CP7_OFFSET },
+};
+
+#endif
+
+/*
+ * Powermanagement idle function, if any is provided by the platform.
+ */
+
+void cpu_idle(void)
+{
+ local_irq_enable();
+
+ /* endless idle loop with no priority at all */
+ while (1) {
+ while (!need_resched())
+ platform_idle();
+ preempt_enable();
+ schedule();
+ }
+}
+
+/*
+ * Free current thread data structures etc..
+ */
+
+void exit_thread(void)
+{
+ release_coprocessors(current); /* Empty macro if no CPs are defined */
+}
+
+void flush_thread(void)
+{
+ release_coprocessors(current); /* Empty macro if no CPs are defined */
+}
+
+/*
+ * Copy thread.
+ *
+ * The stack layout for the new thread looks like this:
+ *
+ * +------------------------+ <- sp in childregs (= tos)
+ * | childregs |
+ * +------------------------+ <- thread.sp = sp in dummy-frame
+ * | dummy-frame | (saved in dummy-frame spill-area)
+ * +------------------------+
+ *
+ * We create a dummy frame to return to ret_from_fork:
+ * a0 points to ret_from_fork (simulating a call4)
+ * sp points to itself (thread.sp)
+ * a2, a3 are unused.
+ *
+ * Note: This is a pristine frame, so we don't need any spill region on top of
+ * childregs.
+ */
+
+int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+ unsigned long unused,
+ struct task_struct * p, struct pt_regs * regs)
+{
+ struct pt_regs *childregs;
+ unsigned long tos;
+ int user_mode = user_mode(regs);
+
+ /* Set up new TSS. */
+ tos = (unsigned long)p->thread_info + THREAD_SIZE;
+ if (user_mode)
+ childregs = (struct pt_regs*)(tos - PT_USER_SIZE);
+ else
+ childregs = (struct pt_regs*)tos - 1;
+
+ *childregs = *regs;
+
+ /* Create a call4 dummy-frame: a0 = 0, a1 = childregs. */
+ *((int*)childregs - 3) = (unsigned long)childregs;
+ *((int*)childregs - 4) = 0;
+
+ childregs->areg[1] = tos;
+ childregs->areg[2] = 0;
+ p->set_child_tid = p->clear_child_tid = NULL;
+ p->thread.ra = MAKE_RA_FOR_CALL((unsigned long)ret_from_fork, 0x1);
+ p->thread.sp = (unsigned long)childregs;
+ if (user_mode(regs)) {
+
+ int len = childregs->wmask & ~0xf;
+ childregs->areg[1] = usp;
+ memcpy(&childregs->areg[XCHAL_NUM_AREGS - len/4],
+ &regs->areg[XCHAL_NUM_AREGS - len/4], len);
+
+ if (clone_flags & CLONE_SETTLS)
+ childregs->areg[2] = childregs->areg[6];
+
+ } else {
+ /* In kernel space, we start a new thread with a new stack. */
+ childregs->wmask = 1;
+ }
+ return 0;
+}
+
+
+/*
+ * Create a kernel thread
+ */
+
+int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+{
+ long retval;
+ __asm__ __volatile__
+ ("mov a5, %4\n\t" /* preserve fn in a5 */
+ "mov a6, %3\n\t" /* preserve and setup arg in a6 */
+ "movi a2, %1\n\t" /* load __NR_clone for syscall*/
+ "mov a3, sp\n\t" /* sp check and sys_clone */
+ "mov a4, %5\n\t" /* load flags for syscall */
+ "syscall\n\t"
+ "beq a3, sp, 1f\n\t" /* branch if parent */
+ "callx4 a5\n\t" /* call fn */
+ "movi a2, %2\n\t" /* load __NR_exit for syscall */
+ "mov a3, a6\n\t" /* load fn return value */
+ "syscall\n"
+ "1:\n\t"
+ "mov %0, a2\n\t" /* parent returns zero */
+ :"=r" (retval)
+ :"i" (__NR_clone), "i" (__NR_exit),
+ "r" (arg), "r" (fn),
+ "r" (flags | CLONE_VM)
+ : "a2", "a3", "a4", "a5", "a6" );
+ return retval;
+}
+
+
+/*
+ * These bracket the sleeping functions..
+ */
+
+unsigned long get_wchan(struct task_struct *p)
+{
+ unsigned long sp, pc;
+ unsigned long stack_page = (unsigned long) p->thread_info;
+ int count = 0;
+
+ if (!p || p == current || p->state == TASK_RUNNING)
+ return 0;
+
+ sp = p->thread.sp;
+ pc = MAKE_PC_FROM_RA(p->thread.ra, p->thread.sp);
+
+ do {
+ if (sp < stack_page + sizeof(struct task_struct) ||
+ sp >= (stack_page + THREAD_SIZE) ||
+ pc == 0)
+ return 0;
+ if (!in_sched_functions(pc))
+ return pc;
+
+ /* Stack layout: sp-4: ra, sp-3: sp' */
+
+ pc = MAKE_PC_FROM_RA(*(unsigned long*)sp - 4, sp);
+ sp = *(unsigned long *)sp - 3;
+ } while (count++ < 16);
+ return 0;
+}
+
+/*
+ * do_copy_regs() gathers information from 'struct pt_regs' and
+ * 'current->thread.areg[]' to fill in the xtensa_gregset_t
+ * structure.
+ *
+ * xtensa_gregset_t and 'struct pt_regs' are vastly different formats
+ * of processor registers. Besides different ordering,
+ * xtensa_gregset_t contains non-live register information that
+ * 'struct pt_regs' does not. Exception handling (primarily) uses
+ * 'struct pt_regs'. Core files and ptrace use xtensa_gregset_t.
+ *
+ */
+
+void do_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs,
+ struct task_struct *tsk)
+{
+ int i, n, wb_offset;
+
+ elfregs->xchal_config_id0 = XCHAL_HW_CONFIGID0;
+ elfregs->xchal_config_id1 = XCHAL_HW_CONFIGID1;
+
+ __asm__ __volatile__ ("rsr %0, 176\n" : "=a" (i));
+ elfregs->cpux = i;
+ __asm__ __volatile__ ("rsr %0, 208\n" : "=a" (i));
+ elfregs->cpuy = i;
+
+ /* Note: PS.EXCM is not set while user task is running; its
+ * being set in regs->ps is for exception handling convenience.
+ */
+
+ elfregs->pc = regs->pc;
+ elfregs->ps = (regs->ps & ~XCHAL_PS_EXCM_MASK);
+ elfregs->exccause = regs->exccause;
+ elfregs->excvaddr = regs->excvaddr;
+ elfregs->windowbase = regs->windowbase;
+ elfregs->windowstart = regs->windowstart;
+ elfregs->lbeg = regs->lbeg;
+ elfregs->lend = regs->lend;
+ elfregs->lcount = regs->lcount;
+ elfregs->sar = regs->sar;
+ elfregs->syscall = regs->syscall;
+
+ /* Copy register file.
+ * The layout looks like this:
+ *
+ * | a0 ... a15 | Z ... Z | arX ... arY |
+ * current window unused saved frames
+ */
+
+ memset (elfregs->ar, 0, sizeof(elfregs->ar));
+
+ wb_offset = regs->windowbase * 4;
+ n = (regs->wmask&1)? 4 : (regs->wmask&2)? 8 : (regs->wmask&4)? 12 : 16;
+
+ for (i = 0; i < n; i++)
+ elfregs->ar[(wb_offset + i) % XCHAL_NUM_AREGS] = regs->areg[i];
+
+ n = (regs->wmask >> 4) * 4;
+
+ for (i = XCHAL_NUM_AREGS - n; n > 0; i++, n--)
+ elfregs->ar[(wb_offset + i) % XCHAL_NUM_AREGS] = regs->areg[i];
+}
+
+void xtensa_elf_core_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs)
+{
+ do_copy_regs ((xtensa_gregset_t *)elfregs, regs, current);
+}
+
+
+/* The inverse of do_copy_regs(). No error or sanity checking. */
+
+void do_restore_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs,
+ struct task_struct *tsk)
+{
+ int i, n, wb_offset;
+
+ /* Note: PS.EXCM is not set while user task is running; it
+ * needs to be set in regs->ps is for exception handling convenience.
+ */
+
+ regs->pc = elfregs->pc;
+ regs->ps = (elfregs->ps | XCHAL_PS_EXCM_MASK);
+ regs->exccause = elfregs->exccause;
+ regs->excvaddr = elfregs->excvaddr;
+ regs->windowbase = elfregs->windowbase;
+ regs->windowstart = elfregs->windowstart;
+ regs->lbeg = elfregs->lbeg;
+ regs->lend = elfregs->lend;
+ regs->lcount = elfregs->lcount;
+ regs->sar = elfregs->sar;
+ regs->syscall = elfregs->syscall;
+
+ /* Clear everything. */
+
+ memset (regs->areg, 0, sizeof(regs->areg));
+
+ /* Copy regs from live window frame. */
+
+ wb_offset = regs->windowbase * 4;
+ n = (regs->wmask&1)? 4 : (regs->wmask&2)? 8 : (regs->wmask&4)? 12 : 16;
+
+ for (i = 0; i < n; i++)
+ regs->areg[(wb_offset+i) % XCHAL_NUM_AREGS] = elfregs->ar[i];
+
+ n = (regs->wmask >> 4) * 4;
+
+ for (i = XCHAL_NUM_AREGS - n; n > 0; i++, n--)
+ regs->areg[(wb_offset+i) % XCHAL_NUM_AREGS] = elfregs->ar[i];
+}
+
+/*
+ * do_save_fpregs() gathers information from 'struct pt_regs' and
+ * 'current->thread' to fill in the elf_fpregset_t structure.
+ *
+ * Core files and ptrace use elf_fpregset_t.
+ */
+
+void do_save_fpregs (elf_fpregset_t *fpregs, struct pt_regs *regs,
+ struct task_struct *tsk)
+{
+#if XCHAL_HAVE_CP
+
+ extern unsigned char _xtensa_reginfo_tables[];
+ extern unsigned _xtensa_reginfo_table_size;
+ int i;
+ unsigned long flags;
+
+ /* Before dumping coprocessor state from memory,
+ * ensure any live coprocessor contents for this
+ * task are first saved to memory:
+ */
+ local_irq_save(flags);
+
+ for (i = 0; i < XCHAL_CP_MAX; i++) {
+ if (tsk == coprocessor_info[i].owner) {
+ enable_coprocessor(i);
+ save_coprocessor_registers(
+ tsk->thread.cp_save+coprocessor_info[i].offset,i);
+ disable_coprocessor(i);
+ }
+ }
+
+ local_irq_restore(flags);
+
+ /* Now dump coprocessor & extra state: */
+ memcpy((unsigned char*)fpregs,
+ _xtensa_reginfo_tables, _xtensa_reginfo_table_size);
+ memcpy((unsigned char*)fpregs + _xtensa_reginfo_table_size,
+ tsk->thread.cp_save, XTENSA_CP_EXTRA_SIZE);
+#endif
+}
+
+/*
+ * The inverse of do_save_fpregs().
+ * Copies coprocessor and extra state from fpregs into regs and tsk->thread.
+ * Returns 0 on success, non-zero if layout doesn't match.
+ */
+
+int do_restore_fpregs (elf_fpregset_t *fpregs, struct pt_regs *regs,
+ struct task_struct *tsk)
+{
+#if XCHAL_HAVE_CP
+
+ extern unsigned char _xtensa_reginfo_tables[];
+ extern unsigned _xtensa_reginfo_table_size;
+ int i;
+ unsigned long flags;
+
+ /* Make sure save area layouts match.
+ * FIXME: in the future we could allow restoring from
+ * a different layout of the same registers, by comparing
+ * fpregs' table with _xtensa_reginfo_tables and matching
+ * entries and copying registers one at a time.
+ * Not too sure yet whether that's very useful.
+ */
+
+ if( memcmp((unsigned char*)fpregs,
+ _xtensa_reginfo_tables, _xtensa_reginfo_table_size) ) {
+ return -1;
+ }
+
+ /* Before restoring coprocessor state from memory,
+ * ensure any live coprocessor contents for this
+ * task are first invalidated.
+ */
+
+ local_irq_save(flags);
+
+ for (i = 0; i < XCHAL_CP_MAX; i++) {
+ if (tsk == coprocessor_info[i].owner) {
+ enable_coprocessor(i);
+ save_coprocessor_registers(
+ tsk->thread.cp_save+coprocessor_info[i].offset,i);
+ coprocessor_info[i].owner = 0;
+ disable_coprocessor(i);
+ }
+ }
+
+ local_irq_restore(flags);
+
+ /* Now restore coprocessor & extra state: */
+
+ memcpy(tsk->thread.cp_save,
+ (unsigned char*)fpregs + _xtensa_reginfo_table_size,
+ XTENSA_CP_EXTRA_SIZE);
+#endif
+ return 0;
+}
+/*
+ * Fill in the CP structure for a core dump for a particular task.
+ */
+
+int
+dump_task_fpu(struct pt_regs *regs, struct task_struct *task, elf_fpregset_t *r)
+{
+/* see asm/coprocessor.h for this magic number 16 */
+#if TOTAL_CPEXTRA_SIZE > 16
+ do_save_fpregs (r, regs, task);
+
+ /* For now, bit 16 means some extra state may be present: */
+// FIXME!! need to track to return more accurate mask
+ return 0x10000 | XCHAL_CP_MASK;
+#else
+ return 0; /* no coprocessors active on this processor */
+#endif
+}
+
+/*
+ * Fill in the CP structure for a core dump.
+ * This includes any FPU coprocessor.
+ * Here, we dump all coprocessors, and other ("extra") custom state.
+ *
+ * This function is called by elf_core_dump() in fs/binfmt_elf.c
+ * (in which case 'regs' comes from calls to do_coredump, see signals.c).
+ */
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)
+{
+ return dump_task_fpu(regs, current, r);
+}
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c
new file mode 100644
index 00000000000..9ef07a4dd2a
--- /dev/null
+++ b/arch/xtensa/kernel/ptrace.c
@@ -0,0 +1,407 @@
+// TODO some minor issues
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ *
+ * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
+ * Chris Zankel <chris@zankel.net>
+ * Scott Foehner<sfoehner@yahoo.com>,
+ * Kevin Chea
+ * Marc Gauthier<marc@tensilica.com> <marc@alumni.uwaterloo.ca>
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/security.h>
+
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/ptrace.h>
+#include <asm/elf.h>
+
+#define TEST_KERNEL // verify kernel operations FIXME: remove
+
+
+/*
+ * Called by kernel/ptrace.c when detaching..
+ *
+ * Make sure single step bits etc are not set.
+ */
+
+void ptrace_disable(struct task_struct *child)
+{
+ /* Nothing to do.. */
+}
+
+int sys_ptrace(long request, long pid, long addr, long data)
+{
+ struct task_struct *child;
+ int ret = -EPERM;
+
+ lock_kernel();
+
+#if 0
+ if ((int)request != 1)
+ printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n",
+ (int) request, (int) pid, (unsigned long) addr,
+ (unsigned long) data);
+#endif
+
+ if (request == PTRACE_TRACEME) {
+
+ /* Are we already being traced? */
+
+ if (current->ptrace & PT_PTRACED)
+ goto out;
+
+ if ((ret = security_ptrace(current->parent, current)))
+ goto out;
+
+ /* Set the ptrace bit in the process flags. */
+
+ current->ptrace |= PT_PTRACED;
+ ret = 0;
+ goto out;
+ }
+
+ ret = -ESRCH;
+ read_lock(&tasklist_lock);
+ child = find_task_by_pid(pid);
+ if (child)
+ get_task_struct(child);
+ read_unlock(&tasklist_lock);
+ if (!child)
+ goto out;
+
+ ret = -EPERM;
+ if (pid == 1) /* you may not mess with init */
+ goto out;
+
+ if (request == PTRACE_ATTACH) {
+ ret = ptrace_attach(child);
+ goto out_tsk;
+ }
+
+ if ((ret = ptrace_check_attach(child, request == PTRACE_KILL)) < 0)
+ goto out_tsk;
+
+ switch (request) {
+ case PTRACE_PEEKTEXT: /* read word at location addr. */
+ case PTRACE_PEEKDATA:
+ {
+ unsigned long tmp;
+ int copied;
+
+ copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+ ret = -EIO;
+ if (copied != sizeof(tmp))
+ break;
+ ret = put_user(tmp,(unsigned long *) data);
+
+ goto out;
+ }
+
+ /* Read the word at location addr in the USER area. */
+
+ case PTRACE_PEEKUSR:
+ {
+ struct pt_regs *regs;
+ unsigned long tmp;
+
+ regs = xtensa_pt_regs(child);
+ tmp = 0; /* Default return value. */
+
+ switch(addr) {
+
+ case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1:
+ {
+ int ar = addr - REG_AR_BASE - regs->windowbase * 4;
+ ar &= (XCHAL_NUM_AREGS - 1);
+ if (ar < 16 && ar + (regs->wmask >> 4) * 4 >= 0)
+ tmp = regs->areg[ar];
+ else
+ ret = -EIO;
+ break;
+ }
+ case REG_A_BASE ... REG_A_BASE + 15:
+ tmp = regs->areg[addr - REG_A_BASE];
+ break;
+ case REG_PC:
+ tmp = regs->pc;
+ break;
+ case REG_PS:
+ /* Note: PS.EXCM is not set while user task is running;
+ * its being set in regs is for exception handling
+ * convenience. */
+ tmp = (regs->ps & ~XCHAL_PS_EXCM_MASK);
+ break;
+ case REG_WB:
+ tmp = regs->windowbase;
+ break;
+ case REG_WS:
+ tmp = regs->windowstart;
+ break;
+ case REG_LBEG:
+ tmp = regs->lbeg;
+ break;
+ case REG_LEND:
+ tmp = regs->lend;
+ break;
+ case REG_LCOUNT:
+ tmp = regs->lcount;
+ break;
+ case REG_SAR:
+ tmp = regs->sar;
+ break;
+ case REG_DEPC:
+ tmp = regs->depc;
+ break;
+ case REG_EXCCAUSE:
+ tmp = regs->exccause;
+ break;
+ case REG_EXCVADDR:
+ tmp = regs->excvaddr;
+ break;
+ case SYSCALL_NR:
+ tmp = regs->syscall;
+ break;
+ default:
+ tmp = 0;
+ ret = -EIO;
+ goto out;
+ }
+ ret = put_user(tmp, (unsigned long *) data);
+ goto out;
+ }
+
+ case PTRACE_POKETEXT: /* write the word at location addr. */
+ case PTRACE_POKEDATA:
+ if (access_process_vm(child, addr, &data, sizeof(data), 1)
+ == sizeof(data))
+ break;
+ ret = -EIO;
+ goto out;
+
+ case PTRACE_POKEUSR:
+ {
+ struct pt_regs *regs;
+ regs = xtensa_pt_regs(child);
+
+ switch (addr) {
+ case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1:
+ {
+ int ar = addr - REG_AR_BASE - regs->windowbase * 4;
+ if (ar < 16 && ar + (regs->wmask >> 4) * 4 >= 0)
+ regs->areg[ar & (XCHAL_NUM_AREGS - 1)] = data;
+ else
+ ret = -EIO;
+ break;
+ }
+ case REG_A_BASE ... REG_A_BASE + 15:
+ regs->areg[addr - REG_A_BASE] = data;
+ break;
+ case REG_PC:
+ regs->pc = data;
+ break;
+ case SYSCALL_NR:
+ regs->syscall = data;
+ break;
+#ifdef TEST_KERNEL
+ case REG_WB:
+ regs->windowbase = data;
+ break;
+ case REG_WS:
+ regs->windowstart = data;
+ break;
+#endif
+
+ default:
+ /* The rest are not allowed. */
+ ret = -EIO;
+ break;
+ }
+ break;
+ }
+
+ /* continue and stop at next (return from) syscall */
+ case PTRACE_SYSCALL:
+ case PTRACE_CONT: /* restart after signal. */
+ {
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
+ break;
+ if (request == PTRACE_SYSCALL)
+ set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ else
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ child->exit_code = data;
+ /* Make sure the single step bit is not set. */
+ child->ptrace &= ~PT_SINGLESTEP;
+ wake_up_process(child);
+ ret = 0;
+ break;
+ }
+
+ /*
+ * make the child exit. Best I can do is send it a sigkill.
+ * perhaps it should be put in the status that it wants to
+ * exit.
+ */
+ case PTRACE_KILL:
+ ret = 0;
+ if (child->state == EXIT_ZOMBIE) /* already dead */
+ break;
+ child->exit_code = SIGKILL;
+ child->ptrace &= ~PT_SINGLESTEP;
+ wake_up_process(child);
+ break;
+
+ case PTRACE_SINGLESTEP:
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
+ break;
+ clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+ child->ptrace |= PT_SINGLESTEP;
+ child->exit_code = data;
+ wake_up_process(child);
+ ret = 0;
+ break;
+
+ case PTRACE_GETREGS:
+ {
+ /* 'data' points to user memory in which to write.
+ * Mainly due to the non-live register values, we
+ * reformat the register values into something more
+ * standard. For convenience, we use the handy
+ * elf_gregset_t format. */
+
+ xtensa_gregset_t format;
+ struct pt_regs *regs = xtensa_pt_regs(child);
+
+ do_copy_regs (&format, regs, child);
+
+ /* Now, copy to user space nice and easy... */
+ ret = 0;
+ if (copy_to_user((void *)data, &format, sizeof(elf_gregset_t)))
+ ret = -EFAULT;
+ break;
+ }
+
+ case PTRACE_SETREGS:
+ {
+ /* 'data' points to user memory that contains the new
+ * values in the elf_gregset_t format. */
+
+ xtensa_gregset_t format;
+ struct pt_regs *regs = xtensa_pt_regs(child);
+
+ if (copy_from_user(&format,(void *)data,sizeof(elf_gregset_t))){
+ ret = -EFAULT;
+ break;
+ }
+
+ /* FIXME: Perhaps we want some sanity checks on
+ * these user-space values? See ARM version. Are
+ * debuggers a security concern? */
+
+ do_restore_regs (&format, regs, child);
+
+ ret = 0;
+ break;
+ }
+
+ case PTRACE_GETFPREGS:
+ {
+ /* 'data' points to user memory in which to write.
+ * For convenience, we use the handy
+ * elf_fpregset_t format. */
+
+ elf_fpregset_t fpregs;
+ struct pt_regs *regs = xtensa_pt_regs(child);
+
+ do_save_fpregs (&fpregs, regs, child);
+
+ /* Now, copy to user space nice and easy... */
+ ret = 0;
+ if (copy_to_user((void *)data, &fpregs, sizeof(elf_fpregset_t)))
+ ret = -EFAULT;
+
+ break;
+ }
+
+ case PTRACE_SETFPREGS:
+ {
+ /* 'data' points to user memory that contains the new
+ * values in the elf_fpregset_t format.
+ */
+ elf_fpregset_t fpregs;
+ struct pt_regs *regs = xtensa_pt_regs(child);
+
+ ret = 0;
+ if (copy_from_user(&fpregs, (void *)data, sizeof(elf_fpregset_t))) {
+ ret = -EFAULT;
+ break;
+ }
+
+ if (do_restore_fpregs (&fpregs, regs, child))
+ ret = -EIO;
+ break;
+ }
+
+ case PTRACE_GETFPREGSIZE:
+ /* 'data' points to 'unsigned long' set to the size
+ * of elf_fpregset_t
+ */
+ ret = put_user(sizeof(elf_fpregset_t), (unsigned long *) data);
+ break;
+
+ case PTRACE_DETACH: /* detach a process that was attached. */
+ ret = ptrace_detach(child, data);
+ break;
+
+ default:
+ ret = ptrace_request(child, request, addr, data);
+ goto out;
+ }
+out_tsk:
+ put_task_struct(child);
+out:
+ unlock_kernel();
+ return ret;
+}
+
+void do_syscall_trace(void)
+{
+ if (!test_thread_flag(TIF_SYSCALL_TRACE))
+ return;
+
+ if (!(current->ptrace & PT_PTRACED))
+ return;
+
+ /*
+ * The 0x80 provides a way for the tracing parent to distinguish
+ * between a syscall stop and SIGTRAP delivery
+ */
+ ptrace_notify(SIGTRAP|((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0));
+
+ /*
+ * this isn't the same as continuing with a signal, but it will do
+ * for normal use. strace only continues with a signal if the
+ * stopping signal is not SIGTRAP. -brl
+ */
+ if (current->exit_code) {
+ send_sig(current->exit_code, current, 1);
+ current->exit_code = 0;
+ }
+}
diff --git a/arch/xtensa/kernel/semaphore.c b/arch/xtensa/kernel/semaphore.c
new file mode 100644
index 00000000000..d40f4b1b75a
--- /dev/null
+++ b/arch/xtensa/kernel/semaphore.c
@@ -0,0 +1,226 @@
+/*
+ * arch/xtensa/kernel/semaphore.c
+ *
+ * Generic semaphore code. Buyer beware. Do your own specific changes
+ * in <asm/semaphore-helper.h>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ *
+ * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
+ * Chris Zankel <chris@zankel.net>
+ * Marc Gauthier<marc@tensilica.com, marc@alumni.uwaterloo.ca>
+ * Kevin Chea
+ */
+
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/init.h>
+#include <asm/semaphore.h>
+#include <asm/errno.h>
+
+/*
+ * These two _must_ execute atomically wrt each other.
+ */
+
+static __inline__ void wake_one_more(struct semaphore * sem)
+{
+ atomic_inc((atomic_t *)&sem->sleepers);
+}
+
+static __inline__ int waking_non_zero(struct semaphore *sem)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&semaphore_wake_lock, flags);
+ if (sem->sleepers > 0) {
+ sem->sleepers--;
+ ret = 1;
+ }
+ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+ return ret;
+}
+
+/*
+ * waking_non_zero_interruptible:
+ * 1 got the lock
+ * 0 go to sleep
+ * -EINTR interrupted
+ *
+ * We must undo the sem->count down_interruptible() increment while we are
+ * protected by the spinlock in order to make atomic this atomic_inc() with the
+ * atomic_read() in wake_one_more(), otherwise we can race. -arca
+ */
+
+static __inline__ int waking_non_zero_interruptible(struct semaphore *sem,
+ struct task_struct *tsk)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&semaphore_wake_lock, flags);
+ if (sem->sleepers > 0) {
+ sem->sleepers--;
+ ret = 1;
+ } else if (signal_pending(tsk)) {
+ atomic_inc(&sem->count);
+ ret = -EINTR;
+ }
+ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+ return ret;
+}
+
+/*
+ * waking_non_zero_trylock:
+ * 1 failed to lock
+ * 0 got the lock
+ *
+ * We must undo the sem->count down_trylock() increment while we are
+ * protected by the spinlock in order to make atomic this atomic_inc() with the
+ * atomic_read() in wake_one_more(), otherwise we can race. -arca
+ */
+
+static __inline__ int waking_non_zero_trylock(struct semaphore *sem)
+{
+ unsigned long flags;
+ int ret = 1;
+
+ spin_lock_irqsave(&semaphore_wake_lock, flags);
+ if (sem->sleepers <= 0)
+ atomic_inc(&sem->count);
+ else {
+ sem->sleepers--;
+ ret = 0;
+ }
+ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+ return ret;
+}
+
+spinlock_t semaphore_wake_lock;
+
+/*
+ * Semaphores are implemented using a two-way counter:
+ * The "count" variable is decremented for each process
+ * that tries to sleep, while the "waking" variable is
+ * incremented when the "up()" code goes to wake up waiting
+ * processes.
+ *
+ * Notably, the inline "up()" and "down()" functions can
+ * efficiently test if they need to do any extra work (up
+ * needs to do something only if count was negative before
+ * the increment operation.
+ *
+ * waking_non_zero() (from asm/semaphore.h) must execute
+ * atomically.
+ *
+ * When __up() is called, the count was negative before
+ * incrementing it, and we need to wake up somebody.
+ *
+ * This routine adds one to the count of processes that need to
+ * wake up and exit. ALL waiting processes actually wake up but
+ * only the one that gets to the "waking" field first will gate
+ * through and acquire the semaphore. The others will go back
+ * to sleep.
+ *
+ * Note that these functions are only called when there is
+ * contention on the lock, and as such all this is the
+ * "non-critical" part of the whole semaphore business. The
+ * critical part is the inline stuff in <asm/semaphore.h>
+ * where we want to avoid any extra jumps and calls.
+ */
+
+void __up(struct semaphore *sem)
+{
+ wake_one_more(sem);
+ wake_up(&sem->wait);
+}
+
+/*
+ * Perform the "down" function. Return zero for semaphore acquired,
+ * return negative for signalled out of the function.
+ *
+ * If called from __down, the return is ignored and the wait loop is
+ * not interruptible. This means that a task waiting on a semaphore
+ * using "down()" cannot be killed until someone does an "up()" on
+ * the semaphore.
+ *
+ * If called from __down_interruptible, the return value gets checked
+ * upon return. If the return value is negative then the task continues
+ * with the negative value in the return register (it can be tested by
+ * the caller).
+ *
+ * Either form may be used in conjunction with "up()".
+ *
+ */
+
+#define DOWN_VAR \
+ struct task_struct *tsk = current; \
+ wait_queue_t wait; \
+ init_waitqueue_entry(&wait, tsk);
+
+#define DOWN_HEAD(task_state) \
+ \
+ \
+ tsk->state = (task_state); \
+ add_wait_queue(&sem->wait, &wait); \
+ \
+ /* \
+ * Ok, we're set up. sem->count is known to be less than zero \
+ * so we must wait. \
+ * \
+ * We can let go the lock for purposes of waiting. \
+ * We re-acquire it after awaking so as to protect \
+ * all semaphore operations. \
+ * \
+ * If "up()" is called before we call waking_non_zero() then \
+ * we will catch it right away. If it is called later then \
+ * we will have to go through a wakeup cycle to catch it. \
+ * \
+ * Multiple waiters contend for the semaphore lock to see \
+ * who gets to gate through and who has to wait some more. \
+ */ \
+ for (;;) {
+
+#define DOWN_TAIL(task_state) \
+ tsk->state = (task_state); \
+ } \
+ tsk->state = TASK_RUNNING; \
+ remove_wait_queue(&sem->wait, &wait);
+
+void __sched __down(struct semaphore * sem)
+{
+ DOWN_VAR
+ DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+ if (waking_non_zero(sem))
+ break;
+ schedule();
+ DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+}
+
+int __sched __down_interruptible(struct semaphore * sem)
+{
+ int ret = 0;
+ DOWN_VAR
+ DOWN_HEAD(TASK_INTERRUPTIBLE)
+
+ ret = waking_non_zero_interruptible(sem, tsk);
+ if (ret)
+ {
+ if (ret == 1)
+ /* ret != 0 only if we get interrupted -arca */
+ ret = 0;
+ break;
+ }
+ schedule();
+ DOWN_TAIL(TASK_INTERRUPTIBLE)
+ return ret;
+}
+
+int __down_trylock(struct semaphore * sem)
+{
+ return waking_non_zero_trylock(sem);
+}
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
new file mode 100644
index 00000000000..1f5bf5d624e
--- /dev/null
+++ b/arch/xtensa/kernel/setup.c
@@ -0,0 +1,520 @@
+/*
+ * arch/xtensa/setup.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
+ * Kevin Chea
+ * Marc Gauthier<marc@tensilica.com> <marc@alumni.uwaterloo.ca>
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/tty.h>
+#include <linux/bootmem.h>
+#include <linux/kernel.h>
+
+#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
+# include <linux/console.h>
+#endif
+
+#ifdef CONFIG_RTC
+# include <linux/timex.h>
+#endif
+
+#ifdef CONFIG_PROC_FS
+# include <linux/seq_file.h>
+#endif
+
+#include <asm/system.h>
+#include <asm/bootparam.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/timex.h>
+#include <asm/platform.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+
+#include <xtensa/config/system.h>
+
+#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
+struct screen_info screen_info = { 0, 24, 0, 0, 0, 80, 0, 0, 0, 24, 1, 16};
+#endif
+
+#ifdef CONFIG_BLK_DEV_FD
+extern struct fd_ops no_fd_ops;
+struct fd_ops *fd_ops;
+#endif
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+extern struct ide_ops no_ide_ops;
+struct ide_ops *ide_ops;
+#endif
+
+extern struct rtc_ops no_rtc_ops;
+struct rtc_ops *rtc_ops;
+
+#ifdef CONFIG_PC_KEYB
+extern struct kbd_ops no_kbd_ops;
+struct kbd_ops *kbd_ops;
+#endif
+
+#ifdef CONFIG_BLK_DEV_INITRD
+extern void *initrd_start;
+extern void *initrd_end;
+extern void *__initrd_start;
+extern void *__initrd_end;
+int initrd_is_mapped = 0;
+extern int initrd_below_start_ok;
+#endif
+
+unsigned char aux_device_present;
+extern unsigned long loops_per_jiffy;
+
+/* Command line specified as configuration option. */
+
+static char command_line[COMMAND_LINE_SIZE];
+
+#ifdef CONFIG_CMDLINE_BOOL
+static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
+#endif
+
+sysmem_info_t __initdata sysmem;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+int initrd_is_mapped;
+#endif
+
+extern void init_mmu(void);
+
+/*
+ * Boot parameter parsing.
+ *
+ * The Xtensa port uses a list of variable-sized tags to pass data to
+ * the kernel. The first tag must be a BP_TAG_FIRST tag for the list
+ * to be recognised. The list is terminated with a zero-sized
+ * BP_TAG_LAST tag.
+ */
+
+typedef struct tagtable {
+ u32 tag;
+ int (*parse)(const bp_tag_t*);
+} tagtable_t;
+
+#define __tagtable(tag, fn) static tagtable_t __tagtable_##fn \
+ __attribute__((unused, __section__(".taglist"))) = { tag, fn }
+
+/* parse current tag */
+
+static int __init parse_tag_mem(const bp_tag_t *tag)
+{
+ meminfo_t *mi = (meminfo_t*)(tag->data);
+
+ if (mi->type != MEMORY_TYPE_CONVENTIONAL)
+ return -1;
+
+ if (sysmem.nr_banks >= SYSMEM_BANKS_MAX) {
+ printk(KERN_WARNING
+ "Ignoring memory bank 0x%08lx size %ldKB\n",
+ (unsigned long)mi->start,
+ (unsigned long)mi->end - (unsigned long)mi->start);
+ return -EINVAL;
+ }
+ sysmem.bank[sysmem.nr_banks].type = mi->type;
+ sysmem.bank[sysmem.nr_banks].start = PAGE_ALIGN(mi->start);
+ sysmem.bank[sysmem.nr_banks].end = mi->end & PAGE_SIZE;
+ sysmem.nr_banks++;
+
+ return 0;
+}
+
+__tagtable(BP_TAG_MEMORY, parse_tag_mem);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+
+static int __init parse_tag_initrd(const bp_tag_t* tag)
+{
+ meminfo_t* mi;
+ mi = (meminfo_t*)(tag->data);
+ initrd_start = (void*)(mi->start);
+ initrd_end = (void*)(mi->end);
+
+ return 0;
+}
+
+__tagtable(BP_TAG_INITRD, parse_tag_initrd);
+
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+static int __init parse_tag_cmdline(const bp_tag_t* tag)
+{
+ strncpy(command_line, (char*)(tag->data), COMMAND_LINE_SIZE);
+ command_line[COMMAND_LINE_SIZE - 1] = '\0';
+ return 0;
+}
+
+__tagtable(BP_TAG_COMMAND_LINE, parse_tag_cmdline);
+
+static int __init parse_bootparam(const bp_tag_t* tag)
+{
+ extern tagtable_t __tagtable_begin, __tagtable_end;
+ tagtable_t *t;
+
+ /* Boot parameters must start with a BP_TAG_FIRST tag. */
+
+ if (tag->id != BP_TAG_FIRST) {
+ printk(KERN_WARNING "Invalid boot parameters!\n");
+ return 0;
+ }
+
+ tag = (bp_tag_t*)((unsigned long)tag + sizeof(bp_tag_t) + tag->size);
+
+ /* Parse all tags. */
+
+ while (tag != NULL && tag->id != BP_TAG_LAST) {
+ for (t = &__tagtable_begin; t < &__tagtable_end; t++) {
+ if (tag->id == t->tag) {
+ t->parse(tag);
+ break;
+ }
+ }
+ if (t == &__tagtable_end)
+ printk(KERN_WARNING "Ignoring tag "
+ "0x%08x\n", tag->id);
+ tag = (bp_tag_t*)((unsigned long)(tag + 1) + tag->size);
+ }
+
+ return 0;
+}
+
+/*
+ * Initialize architecture. (Early stage)
+ */
+
+void __init init_arch(bp_tag_t *bp_start)
+{
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ initrd_start = &__initrd_start;
+ initrd_end = &__initrd_end;
+#endif
+
+ sysmem.nr_banks = 0;
+
+#ifdef CONFIG_CMDLINE_BOOL
+ strcpy(command_line, default_command_line);
+#endif
+
+ /* Parse boot parameters */
+
+ if (bp_start)
+ parse_bootparam(bp_start);
+
+ if (sysmem.nr_banks == 0) {
+ sysmem.nr_banks = 1;
+ sysmem.bank[0].start = PLATFORM_DEFAULT_MEM_START;
+ sysmem.bank[0].end = PLATFORM_DEFAULT_MEM_START
+ + PLATFORM_DEFAULT_MEM_SIZE;
+ }
+
+ /* Early hook for platforms */
+
+ platform_init(bp_start);
+
+ /* Initialize MMU. */
+
+ init_mmu();
+}
+
+/*
+ * Initialize system. Setup memory and reserve regions.
+ */
+
+extern char _end;
+extern char _stext;
+extern char _WindowVectors_text_start;
+extern char _WindowVectors_text_end;
+extern char _DebugInterruptVector_literal_start;
+extern char _DebugInterruptVector_text_end;
+extern char _KernelExceptionVector_literal_start;
+extern char _KernelExceptionVector_text_end;
+extern char _UserExceptionVector_literal_start;
+extern char _UserExceptionVector_text_end;
+extern char _DoubleExceptionVector_literal_start;
+extern char _DoubleExceptionVector_text_end;
+
+void __init setup_arch(char **cmdline_p)
+{
+ extern int mem_reserve(unsigned long, unsigned long, int);
+ extern void bootmem_init(void);
+
+ memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
+ saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+ *cmdline_p = command_line;
+
+ /* Reserve some memory regions */
+
+#ifdef CONFIG_BLK_DEV_INITRD
+ if (initrd_start < initrd_end) {
+ initrd_is_mapped = mem_reserve(__pa(initrd_start),
+ __pa(initrd_end), 0);
+ initrd_below_start_ok = 1;
+ } else {
+ initrd_start = 0;
+ }
+#endif
+
+ mem_reserve(__pa(&_stext),__pa(&_end), 1);
+
+ mem_reserve(__pa(&_WindowVectors_text_start),
+ __pa(&_WindowVectors_text_end), 0);
+
+ mem_reserve(__pa(&_DebugInterruptVector_literal_start),
+ __pa(&_DebugInterruptVector_text_end), 0);
+
+ mem_reserve(__pa(&_KernelExceptionVector_literal_start),
+ __pa(&_KernelExceptionVector_text_end), 0);
+
+ mem_reserve(__pa(&_UserExceptionVector_literal_start),
+ __pa(&_UserExceptionVector_text_end), 0);
+
+ mem_reserve(__pa(&_DoubleExceptionVector_literal_start),
+ __pa(&_DoubleExceptionVector_text_end), 0);
+
+ bootmem_init();
+
+ platform_setup(cmdline_p);
+
+
+ paging_init();
+
+#ifdef CONFIG_VT
+# if defined(CONFIG_VGA_CONSOLE)
+ conswitchp = &vga_con;
+# elif defined(CONFIG_DUMMY_CONSOLE)
+ conswitchp = &dummy_con;
+# endif
+#endif
+
+#if CONFIG_PCI
+ platform_pcibios_init();
+#endif
+}
+
+void machine_restart(char * cmd)
+{
+ platform_restart();
+}
+
+void machine_halt(void)
+{
+ platform_halt();
+ while (1);
+}
+
+void machine_power_off(void)
+{
+ platform_power_off();
+ while (1);
+}
+#ifdef CONFIG_PROC_FS
+
+/*
+ * Display some core information through /proc/cpuinfo.
+ */
+
+static int
+c_show(struct seq_file *f, void *slot)
+{
+ /* high-level stuff */
+ seq_printf(f,"processor\t: 0\n"
+ "vendor_id\t: Tensilica\n"
+ "model\t\t: Xtensa " XCHAL_HW_RELEASE_NAME "\n"
+ "core ID\t\t: " XCHAL_CORE_ID "\n"
+ "build ID\t: 0x%x\n"
+ "byte order\t: %s\n"
+ "cpu MHz\t\t: %lu.%02lu\n"
+ "bogomips\t: %lu.%02lu\n",
+ XCHAL_BUILD_UNIQUE_ID,
+ XCHAL_HAVE_BE ? "big" : "little",
+ CCOUNT_PER_JIFFY/(1000000/HZ),
+ (CCOUNT_PER_JIFFY/(10000/HZ)) % 100,
+ loops_per_jiffy/(500000/HZ),
+ (loops_per_jiffy/(5000/HZ)) % 100);
+
+ seq_printf(f,"flags\t\t: "
+#if XCHAL_HAVE_NMI
+ "nmi "
+#endif
+#if XCHAL_HAVE_DEBUG
+ "debug "
+# if XCHAL_HAVE_OCD
+ "ocd "
+# endif
+#endif
+#if XCHAL_HAVE_DENSITY
+ "density "
+#endif
+#if XCHAL_HAVE_BOOLEANS
+ "boolean "
+#endif
+#if XCHAL_HAVE_LOOPS
+ "loop "
+#endif
+#if XCHAL_HAVE_NSA
+ "nsa "
+#endif
+#if XCHAL_HAVE_MINMAX
+ "minmax "
+#endif
+#if XCHAL_HAVE_SEXT
+ "sext "
+#endif
+#if XCHAL_HAVE_CLAMPS
+ "clamps "
+#endif
+#if XCHAL_HAVE_MAC16
+ "mac16 "
+#endif
+#if XCHAL_HAVE_MUL16
+ "mul16 "
+#endif
+#if XCHAL_HAVE_MUL32
+ "mul32 "
+#endif
+#if XCHAL_HAVE_MUL32_HIGH
+ "mul32h "
+#endif
+#if XCHAL_HAVE_FP
+ "fpu "
+#endif
+ "\n");
+
+ /* Registers. */
+ seq_printf(f,"physical aregs\t: %d\n"
+ "misc regs\t: %d\n"
+ "ibreak\t\t: %d\n"
+ "dbreak\t\t: %d\n",
+ XCHAL_NUM_AREGS,
+ XCHAL_NUM_MISC_REGS,
+ XCHAL_NUM_IBREAK,
+ XCHAL_NUM_DBREAK);
+
+
+ /* Interrupt. */
+ seq_printf(f,"num ints\t: %d\n"
+ "ext ints\t: %d\n"
+ "int levels\t: %d\n"
+ "timers\t\t: %d\n"
+ "debug level\t: %d\n",
+ XCHAL_NUM_INTERRUPTS,
+ XCHAL_NUM_EXTINTERRUPTS,
+ XCHAL_NUM_INTLEVELS,
+ XCHAL_NUM_TIMERS,
+ XCHAL_DEBUGLEVEL);
+
+ /* Coprocessors */
+#if XCHAL_HAVE_CP
+ seq_printf(f, "coprocessors\t: %d\n", XCHAL_CP_NUM);
+#else
+ seq_printf(f, "coprocessors\t: none\n");
+#endif
+
+ /* {I,D}{RAM,ROM} and XLMI */
+ seq_printf(f,"inst ROMs\t: %d\n"
+ "inst RAMs\t: %d\n"
+ "data ROMs\t: %d\n"
+ "data RAMs\t: %d\n"
+ "XLMI ports\t: %d\n",
+ XCHAL_NUM_IROM,
+ XCHAL_NUM_IRAM,
+ XCHAL_NUM_DROM,
+ XCHAL_NUM_DRAM,
+ XCHAL_NUM_XLMI);
+
+ /* Cache */
+ seq_printf(f,"icache line size: %d\n"
+ "icache ways\t: %d\n"
+ "icache size\t: %d\n"
+ "icache flags\t: "
+#if XCHAL_ICACHE_LINE_LOCKABLE
+ "lock"
+#endif
+ "\n"
+ "dcache line size: %d\n"
+ "dcache ways\t: %d\n"
+ "dcache size\t: %d\n"
+ "dcache flags\t: "
+#if XCHAL_DCACHE_IS_WRITEBACK
+ "writeback"
+#endif
+#if XCHAL_DCACHE_LINE_LOCKABLE
+ "lock"
+#endif
+ "\n",
+ XCHAL_ICACHE_LINESIZE,
+ XCHAL_ICACHE_WAYS,
+ XCHAL_ICACHE_SIZE,
+ XCHAL_DCACHE_LINESIZE,
+ XCHAL_DCACHE_WAYS,
+ XCHAL_DCACHE_SIZE);
+
+ /* MMU */
+ seq_printf(f,"ASID bits\t: %d\n"
+ "ASID invalid\t: %d\n"
+ "ASID kernel\t: %d\n"
+ "rings\t\t: %d\n"
+ "itlb ways\t: %d\n"
+ "itlb AR ways\t: %d\n"
+ "dtlb ways\t: %d\n"
+ "dtlb AR ways\t: %d\n",
+ XCHAL_MMU_ASID_BITS,
+ XCHAL_MMU_ASID_INVALID,
+ XCHAL_MMU_ASID_KERNEL,
+ XCHAL_MMU_RINGS,
+ XCHAL_ITLB_WAYS,
+ XCHAL_ITLB_ARF_WAYS,
+ XCHAL_DTLB_WAYS,
+ XCHAL_DTLB_ARF_WAYS);
+
+ return 0;
+}
+
+/*
+ * We show only CPU #0 info.
+ */
+static void *
+c_start(struct seq_file *f, loff_t *pos)
+{
+ return (void *) ((*pos == 0) ? (void *)1 : NULL);
+}
+
+static void *
+c_next(struct seq_file *f, void *v, loff_t *pos)
+{
+ return NULL;
+}
+
+static void
+c_stop(struct seq_file *f, void *v)
+{
+}
+
+struct seq_operations cpuinfo_op =
+{
+ start: c_start,
+ next: c_next,
+ stop: c_stop,
+ show: c_show
+};
+
+#endif /* CONFIG_PROC_FS */
+
diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c
new file mode 100644
index 00000000000..df6e1e17b09
--- /dev/null
+++ b/arch/xtensa/kernel/signal.c
@@ -0,0 +1,713 @@
+// TODO coprocessor stuff
+/*
+ * linux/arch/xtensa/kernel/signal.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
+ *
+ * Joe Taylor <joe@tensilica.com>
+ * Chris Zankel <chris@zankel.net>
+ *
+ *
+ *
+ */
+
+#include <xtensa/config/core.h>
+#include <xtensa/hal.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/stddef.h>
+#include <linux/personality.h>
+#include <asm/ucontext.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/cacheflush.h>
+
+#define DEBUG_SIG 0
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, int options,
+ struct rusage * ru);
+asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
+
+extern struct task_struct *coproc_owners[];
+
+
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+
+int sys_sigsuspend(struct pt_regs *regs)
+{
+ old_sigset_t mask = (old_sigset_t) regs->areg[3];
+ sigset_t saveset;
+
+ mask &= _BLOCKABLE;
+ spin_lock_irq(&current->sighand->siglock);
+ saveset = current->blocked;
+ siginitset(&current->blocked, mask);
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+ regs->areg[2] = -EINTR;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (do_signal(regs, &saveset))
+ return -EINTR;
+ }
+}
+
+asmlinkage int
+sys_rt_sigsuspend(struct pt_regs *regs)
+{
+ sigset_t *unewset = (sigset_t *) regs->areg[4];
+ size_t sigsetsize = (size_t) regs->areg[3];
+ sigset_t saveset, newset;
+ /* XXX: Don't preclude handling different sized sigset_t's. */
+ if (sigsetsize != sizeof(sigset_t))
+ return -EINVAL;
+
+ if (copy_from_user(&newset, unewset, sizeof(newset)))
+ return -EFAULT;
+ sigdelsetmask(&newset, ~_BLOCKABLE);
+ spin_lock_irq(&current->sighand->siglock);
+ saveset = current->blocked;
+ current->blocked = newset;
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+ regs->areg[2] = -EINTR;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (do_signal(regs, &saveset))
+ return -EINTR;
+ }
+}
+
+asmlinkage int
+sys_sigaction(int sig, const struct old_sigaction *act,
+ struct old_sigaction *oact)
+{
+ struct k_sigaction new_ka, old_ka;
+ int ret;
+
+ if (act) {
+ old_sigset_t mask;
+ if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+ __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
+ __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
+ return -EFAULT;
+ __get_user(new_ka.sa.sa_flags, &act->sa_flags);
+ __get_user(mask, &act->sa_mask);
+ siginitset(&new_ka.sa.sa_mask, mask);
+ }
+
+ ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+ if (!ret && oact) {
+ if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+ __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
+ return -EFAULT;
+ __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+ __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+ }
+
+ return ret;
+}
+
+asmlinkage int
+sys_sigaltstack(struct pt_regs *regs)
+{
+ const stack_t *uss = (stack_t *) regs->areg[4];
+ stack_t *uoss = (stack_t *) regs->areg[3];
+
+ if (regs->depc > 64)
+ panic ("Double exception sys_sigreturn\n");
+
+
+ return do_sigaltstack(uss, uoss, regs->areg[1]);
+}
+
+
+/*
+ * Do a signal return; undo the signal stack.
+ */
+
+struct sigframe
+{
+ struct sigcontext sc;
+ struct _cpstate cpstate;
+ unsigned long extramask[_NSIG_WORDS-1];
+ unsigned char retcode[6];
+ unsigned int reserved[4]; /* Reserved area for chaining */
+ unsigned int window[4]; /* Window of 4 registers for initial context */
+};
+
+struct rt_sigframe
+{
+ struct siginfo info;
+ struct ucontext uc;
+ struct _cpstate cpstate;
+ unsigned char retcode[6];
+ unsigned int reserved[4]; /* Reserved area for chaining */
+ unsigned int window[4]; /* Window of 4 registers for initial context */
+};
+
+extern void release_all_cp (struct task_struct *);
+
+
+// FIXME restore_cpextra
+static inline int
+restore_cpextra (struct _cpstate *buf)
+{
+#if 0
+ /* The signal handler may have used coprocessors in which
+ * case they are still enabled. We disable them to force a
+ * reloading of the original task's CP state by the lazy
+ * context-switching mechanisms of CP exception handling.
+ * Also, we essentially discard any coprocessor state that the
+ * signal handler created. */
+
+ struct task_struct *tsk = current;
+ release_all_cp(tsk);
+ return __copy_from_user(tsk->thread.cpextra, buf, TOTAL_CPEXTRA_SIZE);
+#endif
+ return 0;
+}
+
+/* Note: We don't copy double exception 'tregs', we have to finish double exc. first before we return to signal handler! This dbl.exc.handler might cause another double exception, but I think we are fine as the situation is the same as if we had returned to the signal handerl and got an interrupt immediately...
+ */
+
+
+static int
+restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
+{
+ struct thread_struct *thread;
+ unsigned int err = 0;
+ unsigned long ps;
+ struct _cpstate *buf;
+
+#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x)
+ COPY(pc);
+ COPY(depc);
+ COPY(wmask);
+ COPY(lbeg);
+ COPY(lend);
+ COPY(lcount);
+ COPY(sar);
+ COPY(windowbase);
+ COPY(windowstart);
+#undef COPY
+
+ /* For PS, restore only PS.CALLINC.
+ * Assume that all other bits are either the same as for the signal
+ * handler, or the user mode value doesn't matter (e.g. PS.OWB).
+ */
+ err |= __get_user(ps, &sc->sc_ps);
+ regs->ps = (regs->ps & ~XCHAL_PS_CALLINC_MASK)
+ | (ps & XCHAL_PS_CALLINC_MASK);
+
+ /* Additional corruption checks */
+
+ if ((regs->windowbase >= (XCHAL_NUM_AREGS/4))
+ || ((regs->windowstart & ~((1<<(XCHAL_NUM_AREGS/4)) - 1)) != 0) )
+ err = 1;
+ if ((regs->lcount > 0)
+ && ((regs->lbeg > TASK_SIZE) || (regs->lend > TASK_SIZE)) )
+ err = 1;
+
+ /* Restore extended register state.
+ * See struct thread_struct in processor.h.
+ */
+ thread = &current->thread;
+
+ err |= __copy_from_user (regs->areg, sc->sc_areg, XCHAL_NUM_AREGS*4);
+ err |= __get_user(buf, &sc->sc_cpstate);
+ if (buf) {
+ if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
+ goto badframe;
+ err |= restore_cpextra(buf);
+ }
+
+ regs->syscall = -1; /* disable syscall checks */
+ return err;
+
+badframe:
+ return 1;
+}
+
+static inline void
+flush_my_cpstate(struct task_struct *tsk)
+{
+ unsigned long flags;
+ local_irq_save(flags);
+
+#if 0 // FIXME
+ for (i = 0; i < XCHAL_CP_NUM; i++) {
+ if (tsk == coproc_owners[i]) {
+ xthal_validate_cp(i);
+ xthal_save_cpregs(tsk->thread.cpregs_ptr[i], i);
+
+ /* Invalidate and "disown" the cp to allow
+ * callers the chance to reset cp state in the
+ * task_struct. */
+
+ xthal_invalidate_cp(i);
+ coproc_owners[i] = 0;
+ }
+ }
+#endif
+ local_irq_restore(flags);
+}
+
+/* Return codes:
+ 0: nothing saved
+ 1: stuff to save, successful
+ -1: stuff to save, error happened
+*/
+static int
+save_cpextra (struct _cpstate *buf)
+{
+#if (XCHAL_EXTRA_SA_SIZE == 0) && (XCHAL_CP_NUM == 0)
+ return 0;
+#else
+
+ /* FIXME: If a task has never used a coprocessor, there is
+ * no need to save and restore anything. Tracking this
+ * information would allow us to optimize this section.
+ * Perhaps we can use current->used_math or (current->flags &
+ * PF_USEDFPU) or define a new field in the thread
+ * structure. */
+
+ /* We flush any live, task-owned cp state to the task_struct,
+ * then copy it all to the sigframe. Then we clear all
+ * cp/extra state in the task_struct, effectively
+ * clearing/resetting all cp/extra state for the signal
+ * handler (cp-exception handling will load these new values
+ * into the cp/extra registers.) This step is important for
+ * things like a floating-point cp, where the OS must reset
+ * the FCR to the default rounding mode. */
+
+ int err = 0;
+ struct task_struct *tsk = current;
+
+ flush_my_cpstate(tsk);
+ /* Note that we just copy everything: 'extra' and 'cp' state together.*/
+ err |= __copy_to_user(buf, tsk->thread.cp_save, XTENSA_CP_EXTRA_SIZE);
+ memset(tsk->thread.cp_save, 0, XTENSA_CP_EXTRA_SIZE);
+
+#if (XTENSA_CP_EXTRA_SIZE == 0)
+#error Sanity check on memset above, cpextra_size should not be zero.
+#endif
+
+ return err ? -1 : 1;
+#endif
+}
+
+static int
+setup_sigcontext(struct sigcontext *sc, struct _cpstate *cpstate,
+ struct pt_regs *regs, unsigned long mask)
+{
+ struct thread_struct *thread;
+ int err = 0;
+
+//printk("setup_sigcontext\n");
+#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x)
+ COPY(pc);
+ COPY(ps);
+ COPY(depc);
+ COPY(wmask);
+ COPY(lbeg);
+ COPY(lend);
+ COPY(lcount);
+ COPY(sar);
+ COPY(windowbase);
+ COPY(windowstart);
+#undef COPY
+
+ /* Save extended register state.
+ * See struct thread_struct in processor.h.
+ */
+ thread = &current->thread;
+ err |= __copy_to_user (sc->sc_areg, regs->areg, XCHAL_NUM_AREGS * 4);
+ err |= save_cpextra(cpstate);
+ err |= __put_user(err ? NULL : cpstate, &sc->sc_cpstate);
+ /* non-iBCS2 extensions.. */
+ err |= __put_user(mask, &sc->oldmask);
+
+ return err;
+}
+
+asmlinkage int sys_sigreturn(struct pt_regs *regs)
+{
+ struct sigframe *frame = (struct sigframe *)regs->areg[1];
+ sigset_t set;
+ if (regs->depc > 64)
+ panic ("Double exception sys_sigreturn\n");
+
+ if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+
+ if (__get_user(set.sig[0], &frame->sc.oldmask)
+ || (_NSIG_WORDS > 1
+ && __copy_from_user(&set.sig[1], &frame->extramask,
+ sizeof(frame->extramask))))
+ goto badframe;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+
+ spin_lock_irq(&current->sighand->siglock);
+ current->blocked = set;
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+ if (restore_sigcontext(regs, &frame->sc))
+ goto badframe;
+ return regs->areg[2];
+
+badframe:
+ force_sig(SIGSEGV, current);
+ return 0;
+}
+
+asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
+{
+ struct rt_sigframe *frame = (struct rt_sigframe *)regs->areg[1];
+ sigset_t set;
+ stack_t st;
+ int ret;
+ if (regs->depc > 64)
+ {
+ printk("!!!!!!! DEPC !!!!!!!\n");
+ return 0;
+ }
+
+ if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+ goto badframe;
+
+ if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+ goto badframe;
+
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(&current->sighand->siglock);
+ current->blocked = set;
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+ if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
+ goto badframe;
+ ret = regs->areg[2];
+
+ if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
+ goto badframe;
+ /* It is more difficult to avoid calling this function than to
+ call it and ignore errors. */
+ do_sigaltstack(&st, NULL, regs->areg[1]);
+
+ return ret;
+
+badframe:
+ force_sig(SIGSEGV, current);
+ return 0;
+}
+
+/*
+ * Set up a signal frame.
+ */
+
+/*
+ * Determine which stack to use..
+ */
+static inline void *
+get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
+{
+ if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
+ sp = current->sas_ss_sp + current->sas_ss_size;
+
+ return (void *)((sp - frame_size) & -16ul);
+}
+
+#define USE_SIGRETURN 0
+#define USE_RT_SIGRETURN 1
+
+static int
+gen_return_code(unsigned char *codemem, unsigned int use_rt_sigreturn)
+{
+ unsigned int retcall;
+ int err = 0;
+
+#if 0
+ /* Ignoring SA_RESTORER for now; it's supposed to be obsolete,
+ * and the xtensa glibc doesn't use it.
+ */
+ if (ka->sa.sa_flags & SA_RESTORER) {
+ regs->pr = (unsigned long) ka->sa.sa_restorer;
+ } else
+#endif /* 0 */
+ {
+
+#if (__NR_sigreturn > 255) || (__NR_rt_sigreturn > 255)
+
+/* The 12-bit immediate is really split up within the 24-bit MOVI
+ * instruction. As long as the above system call numbers fit within
+ * 8-bits, the following code works fine. See the Xtensa ISA for
+ * details.
+ */
+
+#error Generating the MOVI instruction below breaks!
+#endif
+
+ retcall = use_rt_sigreturn ? __NR_rt_sigreturn : __NR_sigreturn;
+
+#ifdef __XTENSA_EB__ /* Big Endian version */
+ /* Generate instruction: MOVI a2, retcall */
+ err |= __put_user(0x22, &codemem[0]);
+ err |= __put_user(0x0a, &codemem[1]);
+ err |= __put_user(retcall, &codemem[2]);
+ /* Generate instruction: SYSCALL */
+ err |= __put_user(0x00, &codemem[3]);
+ err |= __put_user(0x05, &codemem[4]);
+ err |= __put_user(0x00, &codemem[5]);
+
+#elif defined __XTENSA_EL__ /* Little Endian version */
+ /* Generate instruction: MOVI a2, retcall */
+ err |= __put_user(0x22, &codemem[0]);
+ err |= __put_user(0xa0, &codemem[1]);
+ err |= __put_user(retcall, &codemem[2]);
+ /* Generate instruction: SYSCALL */
+ err |= __put_user(0x00, &codemem[3]);
+ err |= __put_user(0x50, &codemem[4]);
+ err |= __put_user(0x00, &codemem[5]);
+#else
+#error Must use compiler for Xtensa processors.
+#endif
+ }
+
+ /* Flush generated code out of the data cache */
+
+ if (err == 0)
+ __flush_invalidate_cache_range((unsigned long)codemem, 6UL);
+
+ return err;
+}
+
+static void
+set_thread_state(struct pt_regs *regs, void *stack, unsigned char *retaddr,
+ void *handler, unsigned long arg1, void *arg2, void *arg3)
+{
+ /* Set up registers for signal handler */
+ start_thread(regs, (unsigned long) handler, (unsigned long) stack);
+
+ /* Set up a stack frame for a call4
+ * Note: PS.CALLINC is set to one by start_thread
+ */
+ regs->areg[4] = (((unsigned long) retaddr) & 0x3fffffff) | 0x40000000;
+ regs->areg[6] = arg1;
+ regs->areg[7] = (unsigned long) arg2;
+ regs->areg[8] = (unsigned long) arg3;
+}
+
+static void setup_frame(int sig, struct k_sigaction *ka,
+ sigset_t *set, struct pt_regs *regs)
+{
+ struct sigframe *frame;
+ int err = 0;
+ int signal;
+
+ frame = get_sigframe(ka, regs->areg[1], sizeof(*frame));
+ if (regs->depc > 64)
+ {
+ printk("!!!!!!! DEPC !!!!!!!\n");
+ return;
+ }
+
+
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+ goto give_sigsegv;
+
+ signal = current_thread_info()->exec_domain
+ && current_thread_info()->exec_domain->signal_invmap
+ && sig < 32
+ ? current_thread_info()->exec_domain->signal_invmap[sig]
+ : sig;
+
+ err |= setup_sigcontext(&frame->sc, &frame->cpstate, regs, set->sig[0]);
+
+ if (_NSIG_WORDS > 1) {
+ err |= __copy_to_user(frame->extramask, &set->sig[1],
+ sizeof(frame->extramask));
+ }
+
+ /* Create sys_sigreturn syscall in stack frame */
+ err |= gen_return_code(frame->retcode, USE_SIGRETURN);
+
+ if (err)
+ goto give_sigsegv;
+
+ /* Create signal handler execution context.
+ * Return context not modified until this point.
+ */
+ set_thread_state(regs, frame, frame->retcode,
+ ka->sa.sa_handler, signal, &frame->sc, NULL);
+
+ /* Set access mode to USER_DS. Nomenclature is outdated, but
+ * functionality is used in uaccess.h
+ */
+ set_fs(USER_DS);
+
+
+#if DEBUG_SIG
+ printk("SIG deliver (%s:%d): signal=%d sp=%p pc=%08x\n",
+ current->comm, current->pid, signal, frame, regs->pc);
+#endif
+
+ return;
+
+give_sigsegv:
+ if (sig == SIGSEGV)
+ ka->sa.sa_handler = SIG_DFL;
+ force_sig(SIGSEGV, current);
+}
+
+static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ sigset_t *set, struct pt_regs *regs)
+{
+ struct rt_sigframe *frame;
+ int err = 0;
+ int signal;
+
+ frame = get_sigframe(ka, regs->areg[1], sizeof(*frame));
+ if (regs->depc > 64)
+ panic ("Double exception sys_sigreturn\n");
+
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+ goto give_sigsegv;
+
+ signal = current_thread_info()->exec_domain
+ && current_thread_info()->exec_domain->signal_invmap
+ && sig < 32
+ ? current_thread_info()->exec_domain->signal_invmap[sig]
+ : sig;
+
+ err |= copy_siginfo_to_user(&frame->info, info);
+
+ /* Create the ucontext. */
+ err |= __put_user(0, &frame->uc.uc_flags);
+ err |= __put_user(0, &frame->uc.uc_link);
+ err |= __put_user((void *)current->sas_ss_sp,
+ &frame->uc.uc_stack.ss_sp);
+ err |= __put_user(sas_ss_flags(regs->areg[1]),
+ &frame->uc.uc_stack.ss_flags);
+ err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+ err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->cpstate,
+ regs, set->sig[0]);
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+
+ /* Create sys_rt_sigreturn syscall in stack frame */
+ err |= gen_return_code(frame->retcode, USE_RT_SIGRETURN);
+
+ if (err)
+ goto give_sigsegv;
+
+ /* Create signal handler execution context.
+ * Return context not modified until this point.
+ */
+ set_thread_state(regs, frame, frame->retcode,
+ ka->sa.sa_handler, signal, &frame->info, &frame->uc);
+
+ /* Set access mode to USER_DS. Nomenclature is outdated, but
+ * functionality is used in uaccess.h
+ */
+ set_fs(USER_DS);
+
+#if DEBUG_SIG
+ printk("SIG rt deliver (%s:%d): signal=%d sp=%p pc=%08x\n",
+ current->comm, current->pid, signal, frame, regs->pc);
+#endif
+
+ return;
+
+give_sigsegv:
+ if (sig == SIGSEGV)
+ ka->sa.sa_handler = SIG_DFL;
+ force_sig(SIGSEGV, current);
+}
+
+
+
+/*
+ * Note that 'init' is a special process: it doesn't get signals it doesn't
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ *
+ * Note that we go through the signals twice: once to check the signals that
+ * the kernel can handle, and then we build all the user-level signal handling
+ * stack-frames in one go after that.
+ */
+int do_signal(struct pt_regs *regs, sigset_t *oldset)
+{
+ siginfo_t info;
+ int signr;
+ struct k_sigaction ka;
+
+ if (!oldset)
+ oldset = &current->blocked;
+
+ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+
+ /* Are we from a system call? */
+ if (regs->syscall >= 0) {
+ /* If so, check system call restarting.. */
+ switch (regs->areg[2]) {
+ case ERESTARTNOHAND:
+ case ERESTART_RESTARTBLOCK:
+ regs->areg[2] = -EINTR;
+ break;
+
+ case ERESTARTSYS:
+ if (!(ka.sa.sa_flags & SA_RESTART)) {
+ regs->areg[2] = -EINTR;
+ break;
+ }
+ /* fallthrough */
+ case ERESTARTNOINTR:
+ regs->areg[2] = regs->syscall;
+ regs->pc -= 3;
+ }
+ }
+
+ if (signr == 0)
+ return 0; /* no signals delivered */
+
+ /* Whee! Actually deliver the signal. */
+
+ /* Set up the stack frame */
+ if (ka.sa.sa_flags & SA_SIGINFO)
+ setup_rt_frame(signr, &ka, &info, oldset, regs);
+ else
+ setup_frame(signr, &ka, oldset, regs);
+
+ if (ka.sa.sa_flags & SA_ONESHOT)
+ ka.sa.sa_handler = SIG_DFL;
+
+ if (!(ka.sa.sa_flags & SA_NODEFER)) {
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked, &current->blocked, &ka.sa.sa_mask);
+ sigaddset(&current->blocked, signr);
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+ }
+ return 1;
+}
diff --git a/arch/xtensa/kernel/syscalls.c b/arch/xtensa/kernel/syscalls.c
new file mode 100644
index 00000000000..abc8ed6c702
--- /dev/null
+++ b/arch/xtensa/kernel/syscalls.c
@@ -0,0 +1,418 @@
+/*
+ * arch/xtensa/kernel/syscall.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ * Copyright (C) 2000 Silicon Graphics, Inc.
+ * Copyright (C) 1995 - 2000 by Ralf Baechle
+ *
+ * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
+ * Marc Gauthier <marc@tensilica.com, marc@alumni.uwaterloo.ca>
+ * Chris Zankel <chris@zankel.net>
+ * Kevin Chea
+ *
+ */
+
+#define DEBUG 0
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/mman.h>
+#include <linux/sched.h>
+#include <linux/file.h>
+#include <linux/slab.h>
+#include <linux/utsname.h>
+#include <linux/unistd.h>
+#include <linux/stringify.h>
+#include <linux/syscalls.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/errno.h>
+#include <asm/ptrace.h>
+#include <asm/signal.h>
+#include <asm/uaccess.h>
+#include <asm/hardirq.h>
+#include <asm/mman.h>
+#include <asm/shmparam.h>
+#include <asm/page.h>
+#include <asm/ipc.h>
+
+extern void do_syscall_trace(void);
+typedef int (*syscall_t)(void *a0,...);
+extern int (*do_syscalls)(struct pt_regs *regs, syscall_t fun,
+ int narg);
+extern syscall_t sys_call_table[];
+extern unsigned char sys_narg_table[];
+
+/*
+ * sys_pipe() is the normal C calling standard for creating a pipe. It's not
+ * the way unix traditional does this, though.
+ */
+
+int sys_pipe(int __user *userfds)
+{
+ int fd[2];
+ int error;
+
+ error = do_pipe(fd);
+ if (!error) {
+ if (copy_to_user(userfds, fd, 2 * sizeof(int)))
+ error = -EFAULT;
+ }
+ return error;
+}
+
+/*
+ * Common code for old and new mmaps.
+ */
+
+static inline long do_mmap2(unsigned long addr, unsigned long len,
+ unsigned long prot, unsigned long flags,
+ unsigned long fd, unsigned long pgoff)
+{
+ int error = -EBADF;
+ struct file * file = NULL;
+
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+ if (!(flags & MAP_ANONYMOUS)) {
+ file = fget(fd);
+ if (!file)
+ goto out;
+ }
+
+ down_write(&current->mm->mmap_sem);
+ error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+ up_write(&current->mm->mmap_sem);
+
+ if (file)
+ fput(file);
+out:
+ return error;
+}
+
+unsigned long old_mmap(unsigned long addr, size_t len, int prot,
+ int flags, int fd, off_t offset)
+{
+ return do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+}
+
+long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
+ unsigned long flags, unsigned long fd, unsigned long pgoff)
+{
+ return do_mmap2(addr, len, prot, flags, fd, pgoff);
+}
+
+int sys_fork(struct pt_regs *regs)
+{
+ return do_fork(SIGCHLD, regs->areg[1], regs, 0, NULL, NULL);
+}
+
+int sys_vfork(struct pt_regs *regs)
+{
+ return do_fork(CLONE_VFORK|CLONE_VM|SIGCHLD, regs->areg[1],
+ regs, 0, NULL, NULL);
+}
+
+int sys_clone(struct pt_regs *regs)
+{
+ unsigned long clone_flags;
+ unsigned long newsp;
+ int __user *parent_tidptr, *child_tidptr;
+ clone_flags = regs->areg[4];
+ newsp = regs->areg[3];
+ parent_tidptr = (int __user *)regs->areg[5];
+ child_tidptr = (int __user *)regs->areg[6];
+ if (!newsp)
+ newsp = regs->areg[1];
+ return do_fork(clone_flags,newsp,regs,0,parent_tidptr,child_tidptr);
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+
+int sys_execve(struct pt_regs *regs)
+{
+ int error;
+ char * filename;
+
+ filename = getname((char *) (long)regs->areg[5]);
+ error = PTR_ERR(filename);
+ if (IS_ERR(filename))
+ goto out;
+ error = do_execve(filename, (char **) (long)regs->areg[3],
+ (char **) (long)regs->areg[4], regs);
+ putname(filename);
+
+out:
+ return error;
+}
+
+int sys_uname(struct old_utsname * name)
+{
+ if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
+ return 0;
+ return -EFAULT;
+}
+
+int sys_olduname(struct oldold_utsname * name)
+{
+ int error;
+
+ if (!name)
+ return -EFAULT;
+ if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
+ return -EFAULT;
+
+ error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
+ error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
+ error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
+ error -= __put_user(0,name->nodename+__OLD_UTS_LEN);
+ error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
+ error -= __put_user(0,name->release+__OLD_UTS_LEN);
+ error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
+ error -= __put_user(0,name->version+__OLD_UTS_LEN);
+ error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
+ error -= __put_user(0,name->machine+__OLD_UTS_LEN);
+
+ return error ? -EFAULT : 0;
+}
+
+
+/*
+ * Build the string table for the builtin "poor man's strace".
+ */
+
+#if DEBUG
+#define SYSCALL(fun, narg) #fun,
+static char *sfnames[] = {
+#include "syscalls.h"
+};
+#undef SYS
+#endif
+
+void system_call (struct pt_regs *regs)
+{
+ syscall_t syscall;
+ unsigned long parm0, parm1, parm2, parm3, parm4, parm5;
+ int nargs, res;
+ unsigned int syscallnr;
+ int ps;
+
+#if DEBUG
+ int i;
+ unsigned long parms[6];
+ char *sysname;
+#endif
+
+ regs->syscall = regs->areg[2];
+
+ do_syscall_trace();
+
+ /* Have to load after syscall_trace because strace
+ * sometimes changes regs->syscall.
+ */
+ syscallnr = regs->syscall;
+
+ parm0 = parm1 = parm2 = parm3 = parm4 = parm5 = 0;
+
+ /* Restore interrupt level to syscall invoker's.
+ * If this were in assembly, we wouldn't disable
+ * interrupts in the first place:
+ */
+ local_save_flags (ps);
+ local_irq_restore((ps & ~XCHAL_PS_INTLEVEL_MASK) |
+ (regs->ps & XCHAL_PS_INTLEVEL_MASK) );
+
+ if (syscallnr > __NR_Linux_syscalls) {
+ regs->areg[2] = -ENOSYS;
+ return;
+ }
+
+ syscall = sys_call_table[syscallnr];
+ nargs = sys_narg_table[syscallnr];
+
+ if (syscall == NULL) {
+ regs->areg[2] = -ENOSYS;
+ return;
+ }
+
+ /* There shouldn't be more than six arguments in the table! */
+
+ if (nargs > 6)
+ panic("Internal error - too many syscall arguments (%d)!\n",
+ nargs);
+
+ /* Linux takes system-call arguments in registers. The ABI
+ * and Xtensa software conventions require the system-call
+ * number in a2. If an argument exists in a2, we move it to
+ * the next available register. Note that for improved
+ * efficiency, we do NOT shift all parameters down one
+ * register to maintain the original order.
+ *
+ * At best case (zero arguments), we just write the syscall
+ * number to a2. At worst case (1 to 6 arguments), we move
+ * the argument in a2 to the next available register, then
+ * write the syscall number to a2.
+ *
+ * For clarity, the following truth table enumerates all
+ * possibilities.
+ *
+ * arguments syscall number arg0, arg1, arg2, arg3, arg4, arg5
+ * --------- -------------- ----------------------------------
+ * 0 a2
+ * 1 a2 a3
+ * 2 a2 a4, a3
+ * 3 a2 a5, a3, a4
+ * 4 a2 a6, a3, a4, a5
+ * 5 a2 a7, a3, a4, a5, a6
+ * 6 a2 a8, a3, a4, a5, a6, a7
+ */
+ if (nargs) {
+ parm0 = regs->areg[nargs+2];
+ parm1 = regs->areg[3];
+ parm2 = regs->areg[4];
+ parm3 = regs->areg[5];
+ parm4 = regs->areg[6];
+ parm5 = regs->areg[7];
+ } else /* nargs == 0 */
+ parm0 = (unsigned long) regs;
+
+#if DEBUG
+ parms[0] = parm0;
+ parms[1] = parm1;
+ parms[2] = parm2;
+ parms[3] = parm3;
+ parms[4] = parm4;
+ parms[5] = parm5;
+
+ sysname = sfnames[syscallnr];
+ if (strncmp(sysname, "sys_", 4) == 0)
+ sysname = sysname + 4;
+
+ printk("\017SYSCALL:I:%x:%d:%s %s(", regs->pc, current->pid,
+ current->comm, sysname);
+ for (i = 0; i < nargs; i++)
+ printk((i>0) ? ", %#lx" : "%#lx", parms[i]);
+ printk(")\n");
+#endif
+
+ res = syscall((void *)parm0, parm1, parm2, parm3, parm4, parm5);
+
+#if DEBUG
+ printk("\017SYSCALL:O:%d:%s %s(",current->pid, current->comm, sysname);
+ for (i = 0; i < nargs; i++)
+ printk((i>0) ? ", %#lx" : "%#lx", parms[i]);
+ if (res < 4096)
+ printk(") = %d\n", res);
+ else
+ printk(") = %#x\n", res);
+#endif /* DEBUG */
+
+ regs->areg[2] = res;
+ do_syscall_trace();
+}
+
+/*
+ * sys_ipc() is the de-multiplexer for the SysV IPC calls..
+ *
+ * This is really horribly ugly.
+ */
+
+int sys_ipc (uint call, int first, int second,
+ int third, void __user *ptr, long fifth)
+{
+ int version, ret;
+
+ version = call >> 16; /* hack for backward compatibility */
+ call &= 0xffff;
+ ret = -ENOSYS;
+
+ switch (call) {
+ case SEMOP:
+ ret = sys_semtimedop (first, (struct sembuf __user *)ptr,
+ second, NULL);
+ break;
+
+ case SEMTIMEDOP:
+ ret = sys_semtimedop (first, (struct sembuf __user *)ptr,
+ second, (const struct timespec *) fifth);
+ break;
+
+ case SEMGET:
+ ret = sys_semget (first, second, third);
+ break;
+
+ case SEMCTL: {
+ union semun fourth;
+
+ if (ptr && !get_user(fourth.__pad, (void *__user *) ptr))
+ ret = sys_semctl (first, second, third, fourth);
+ break;
+ }
+
+ case MSGSND:
+ ret = sys_msgsnd (first, (struct msgbuf __user*) ptr,
+ second, third);
+ break;
+
+ case MSGRCV:
+ switch (version) {
+ case 0: {
+ struct ipc_kludge tmp;
+
+ if (ptr && !copy_from_user(&tmp,
+ (struct ipc_kludge *) ptr,
+ sizeof (tmp)))
+ ret = sys_msgrcv (first, tmp.msgp, second,
+ tmp.msgtyp, third);
+ break;
+ }
+
+ default:
+ ret = sys_msgrcv (first, (struct msgbuf __user *) ptr,
+ second, 0, third);
+ break;
+ }
+ break;
+
+ case MSGGET:
+ ret = sys_msgget ((key_t) first, second);
+ break;
+
+ case MSGCTL:
+ ret = sys_msgctl (first, second, (struct msqid_ds __user*) ptr);
+ break;
+
+ case SHMAT: {
+ ulong raddr;
+ ret = do_shmat (first, (char __user *) ptr, second, &raddr);
+
+ if (!ret)
+ ret = put_user (raddr, (ulong __user *) third);
+
+ break;
+ }
+
+ case SHMDT:
+ ret = sys_shmdt ((char __user *)ptr);
+ break;
+
+ case SHMGET:
+ ret = sys_shmget (first, second, third);
+ break;
+
+ case SHMCTL:
+ ret = sys_shmctl (first, second, (struct shmid_ds __user*) ptr);
+ break;
+ }
+ return ret;
+}
+
diff --git a/arch/xtensa/kernel/syscalls.h b/arch/xtensa/kernel/syscalls.h
new file mode 100644
index 00000000000..5b3f75f50fe
--- /dev/null
+++ b/arch/xtensa/kernel/syscalls.h
@@ -0,0 +1,248 @@
+/*
+ * arch/xtensa/kernel/syscalls.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ *
+ * Changes by Joe Taylor <joe@tensilica.com>
+ */
+
+/*
+ * This file is being included twice - once to build a list of all
+ * syscalls and once to build a table of how many arguments each syscall
+ * accepts. Syscalls that receive a pointer to the saved registers are
+ * marked as having zero arguments.
+ *
+ * The binary compatibility calls are in a separate list.
+ *
+ * Entry '0' used to be system_call. It's removed to disable indirect
+ * system calls for now so user tasks can't recurse. See mips'
+ * sys_syscall for a comparable example.
+ */
+
+SYSCALL(0, 0) /* 00 */
+
+SYSCALL(sys_exit, 1)
+SYSCALL(sys_fork, 0)
+SYSCALL(sys_read, 3)
+SYSCALL(sys_write, 3)
+SYSCALL(sys_open, 3) /* 05 */
+SYSCALL(sys_close, 1)
+SYSCALL(sys_waitpid, 3)
+SYSCALL(sys_creat, 2)
+SYSCALL(sys_link, 2)
+SYSCALL(sys_unlink, 1) /* 10 */
+SYSCALL(sys_execve, 0)
+SYSCALL(sys_chdir, 1)
+SYSCALL(sys_time, 1)
+SYSCALL(sys_mknod, 3)
+SYSCALL(sys_chmod, 2) /* 15 */
+SYSCALL(sys_lchown, 3)
+SYSCALL(sys_ni_syscall, 0)
+SYSCALL(sys_stat, 2)
+SYSCALL(sys_lseek, 3)
+SYSCALL(sys_getpid, 0) /* 20 */
+SYSCALL(sys_mount, 5)
+SYSCALL(sys_oldumount, 1)
+SYSCALL(sys_setuid, 1)
+SYSCALL(sys_getuid, 0)
+SYSCALL(sys_stime, 1) /* 25 */
+SYSCALL(sys_ptrace, 4)
+SYSCALL(sys_alarm, 1)
+SYSCALL(sys_fstat, 2)
+SYSCALL(sys_pause, 0)
+SYSCALL(sys_utime, 2) /* 30 */
+SYSCALL(sys_ni_syscall, 0)
+SYSCALL(sys_ni_syscall, 0)
+SYSCALL(sys_access, 2)
+SYSCALL(sys_nice, 1)
+SYSCALL(sys_ni_syscall, 0) /* 35 */
+SYSCALL(sys_sync, 0)
+SYSCALL(sys_kill, 2)
+SYSCALL(sys_rename, 2)
+SYSCALL(sys_mkdir, 2)
+SYSCALL(sys_rmdir, 1) /* 40 */
+SYSCALL(sys_dup, 1)
+SYSCALL(sys_pipe, 1)
+SYSCALL(sys_times, 1)
+SYSCALL(sys_ni_syscall, 0)
+SYSCALL(sys_brk, 1) /* 45 */
+SYSCALL(sys_setgid, 1)
+SYSCALL(sys_getgid, 0)
+SYSCALL(sys_ni_syscall, 0) /* was signal(2) */
+SYSCALL(sys_geteuid, 0)
+SYSCALL(sys_getegid, 0) /* 50 */
+SYSCALL(sys_acct, 1)
+SYSCALL(sys_umount, 2)
+SYSCALL(sys_ni_syscall, 0)
+SYSCALL(sys_ioctl, 3)
+SYSCALL(sys_fcntl, 3) /* 55 */
+SYSCALL(sys_ni_syscall, 2)
+SYSCALL(sys_setpgid, 2)
+SYSCALL(sys_ni_syscall, 0)
+SYSCALL(sys_olduname, 1)
+SYSCALL(sys_umask, 1) /* 60 */
+SYSCALL(sys_chroot, 1)
+SYSCALL(sys_ustat, 2)
+SYSCALL(sys_dup2, 2)
+SYSCALL(sys_getppid, 0)
+SYSCALL(sys_getpgrp, 0) /* 65 */
+SYSCALL(sys_setsid, 0)
+SYSCALL(sys_sigaction, 3)
+SYSCALL(sys_sgetmask, 0)
+SYSCALL(sys_ssetmask, 1)
+SYSCALL(sys_setreuid, 2) /* 70 */
+SYSCALL(sys_setregid, 2)
+SYSCALL(sys_sigsuspend, 0)
+SYSCALL(sys_sigpending, 1)
+SYSCALL(sys_sethostname, 2)
+SYSCALL(sys_setrlimit, 2) /* 75 */
+SYSCALL(sys_getrlimit, 2)
+SYSCALL(sys_getrusage, 2)
+SYSCALL(sys_gettimeofday, 2)
+SYSCALL(sys_settimeofday, 2)
+SYSCALL(sys_getgroups, 2) /* 80 */
+SYSCALL(sys_setgroups, 2)
+SYSCALL(sys_ni_syscall, 0) /* old_select */
+SYSCALL(sys_symlink, 2)
+SYSCALL(sys_lstat, 2)
+SYSCALL(sys_readlink, 3) /* 85 */
+SYSCALL(sys_uselib, 1)
+SYSCALL(sys_swapon, 2)
+SYSCALL(sys_reboot, 3)
+SYSCALL(old_readdir, 3)
+SYSCALL(old_mmap, 6) /* 90 */
+SYSCALL(sys_munmap, 2)
+SYSCALL(sys_truncate, 2)
+SYSCALL(sys_ftruncate, 2)
+SYSCALL(sys_fchmod, 2)
+SYSCALL(sys_fchown, 3) /* 95 */
+SYSCALL(sys_getpriority, 2)
+SYSCALL(sys_setpriority, 3)
+SYSCALL(sys_ni_syscall, 0)
+SYSCALL(sys_statfs, 2)
+SYSCALL(sys_fstatfs, 2) /* 100 */
+SYSCALL(sys_ni_syscall, 3)
+SYSCALL(sys_socketcall, 2)
+SYSCALL(sys_syslog, 3)
+SYSCALL(sys_setitimer, 3)
+SYSCALL(sys_getitimer, 2) /* 105 */
+SYSCALL(sys_newstat, 2)
+SYSCALL(sys_newlstat, 2)
+SYSCALL(sys_newfstat, 2)
+SYSCALL(sys_uname, 1)
+SYSCALL(sys_ni_syscall, 0) /* 110 */
+SYSCALL(sys_vhangup, 0)
+SYSCALL(sys_ni_syscall, 0) /* was sys_idle() */
+SYSCALL(sys_ni_syscall, 0)
+SYSCALL(sys_wait4, 4)
+SYSCALL(sys_swapoff, 1) /* 115 */
+SYSCALL(sys_sysinfo, 1)
+SYSCALL(sys_ipc, 5) /* 6 really, but glibc uses only 5) */
+SYSCALL(sys_fsync, 1)
+SYSCALL(sys_sigreturn, 0)
+SYSCALL(sys_clone, 0) /* 120 */
+SYSCALL(sys_setdomainname, 2)
+SYSCALL(sys_newuname, 1)
+SYSCALL(sys_ni_syscall, 0) /* sys_modify_ldt */
+SYSCALL(sys_adjtimex, 1)
+SYSCALL(sys_mprotect, 3) /* 125 */
+SYSCALL(sys_sigprocmask, 3)
+SYSCALL(sys_ni_syscall, 2) /* old sys_create_module */
+SYSCALL(sys_init_module, 2)
+SYSCALL(sys_delete_module, 1)
+SYSCALL(sys_ni_syscall, 1) /* old sys_get_kernel_sysm */ /* 130 */
+SYSCALL(sys_quotactl, 0)
+SYSCALL(sys_getpgid, 1)
+SYSCALL(sys_fchdir, 1)
+SYSCALL(sys_bdflush, 2)
+SYSCALL(sys_sysfs, 3) /* 135 */
+SYSCALL(sys_personality, 1)
+SYSCALL(sys_ni_syscall, 0) /* for afs_syscall */
+SYSCALL(sys_setfsuid, 1)
+SYSCALL(sys_setfsgid, 1)
+SYSCALL(sys_llseek, 5) /* 140 */
+SYSCALL(sys_getdents, 3)
+SYSCALL(sys_select, 5)
+SYSCALL(sys_flock, 2)
+SYSCALL(sys_msync, 3)
+SYSCALL(sys_readv, 3) /* 145 */
+SYSCALL(sys_writev, 3)
+SYSCALL(sys_ni_syscall, 3)
+SYSCALL(sys_ni_syscall, 3)
+SYSCALL(sys_ni_syscall, 4) /* handled in fast syscall handler. */
+SYSCALL(sys_ni_syscall, 0) /* 150 */
+SYSCALL(sys_getsid, 1)
+SYSCALL(sys_fdatasync, 1)
+SYSCALL(sys_sysctl, 1)
+SYSCALL(sys_mlock, 2)
+SYSCALL(sys_munlock, 2) /* 155 */
+SYSCALL(sys_mlockall, 1)
+SYSCALL(sys_munlockall, 0)
+SYSCALL(sys_sched_setparam,2)
+SYSCALL(sys_sched_getparam,2)
+SYSCALL(sys_sched_setscheduler,3) /* 160 */
+SYSCALL(sys_sched_getscheduler,1)
+SYSCALL(sys_sched_yield,0)
+SYSCALL(sys_sched_get_priority_max,1)
+SYSCALL(sys_sched_get_priority_min,1)
+SYSCALL(sys_sched_rr_get_interval,2) /* 165 */
+SYSCALL(sys_nanosleep,2)
+SYSCALL(sys_mremap,4)
+SYSCALL(sys_accept, 3)
+SYSCALL(sys_bind, 3)
+SYSCALL(sys_connect, 3) /* 170 */
+SYSCALL(sys_getpeername, 3)
+SYSCALL(sys_getsockname, 3)
+SYSCALL(sys_getsockopt, 5)
+SYSCALL(sys_listen, 2)
+SYSCALL(sys_recv, 4) /* 175 */
+SYSCALL(sys_recvfrom, 6)
+SYSCALL(sys_recvmsg, 3)
+SYSCALL(sys_send, 4)
+SYSCALL(sys_sendmsg, 3)
+SYSCALL(sys_sendto, 6) /* 180 */
+SYSCALL(sys_setsockopt, 5)
+SYSCALL(sys_shutdown, 2)
+SYSCALL(sys_socket, 3)
+SYSCALL(sys_socketpair, 4)
+SYSCALL(sys_setresuid, 3) /* 185 */
+SYSCALL(sys_getresuid, 3)
+SYSCALL(sys_ni_syscall, 5) /* old sys_query_module */
+SYSCALL(sys_poll, 3)
+SYSCALL(sys_nfsservctl, 3)
+SYSCALL(sys_setresgid, 3) /* 190 */
+SYSCALL(sys_getresgid, 3)
+SYSCALL(sys_prctl, 5)
+SYSCALL(sys_rt_sigreturn, 0)
+SYSCALL(sys_rt_sigaction, 4)
+SYSCALL(sys_rt_sigprocmask, 4) /* 195 */
+SYSCALL(sys_rt_sigpending, 2)
+SYSCALL(sys_rt_sigtimedwait, 4)
+SYSCALL(sys_rt_sigqueueinfo, 3)
+SYSCALL(sys_rt_sigsuspend, 0)
+SYSCALL(sys_pread64, 5) /* 200 */
+SYSCALL(sys_pwrite64, 5)
+SYSCALL(sys_chown, 3)
+SYSCALL(sys_getcwd, 2)
+SYSCALL(sys_capget, 2)
+SYSCALL(sys_capset, 2) /* 205 */
+SYSCALL(sys_sigaltstack, 0)
+SYSCALL(sys_sendfile, 4)
+SYSCALL(sys_ni_syscall, 0)
+SYSCALL(sys_ni_syscall, 0)
+SYSCALL(sys_mmap2, 6) /* 210 */
+SYSCALL(sys_truncate64, 2)
+SYSCALL(sys_ftruncate64, 2)
+SYSCALL(sys_stat64, 2)
+SYSCALL(sys_lstat64, 2)
+SYSCALL(sys_fstat64, 2) /* 215 */
+SYSCALL(sys_pivot_root, 2)
+SYSCALL(sys_mincore, 3)
+SYSCALL(sys_madvise, 3)
+SYSCALL(sys_getdents64, 3)
+SYSCALL(sys_vfork, 0) /* 220 */
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c
new file mode 100644
index 00000000000..e07287db5a4
--- /dev/null
+++ b/arch/xtensa/kernel/time.c
@@ -0,0 +1,227 @@
+/*
+ * arch/xtensa/kernel/time.c
+ *
+ * Timer and clock support.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2005 Tensilica Inc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/profile.h>
+#include <linux/delay.h>
+
+#include <asm/timex.h>
+#include <asm/platform.h>
+
+
+extern volatile unsigned long wall_jiffies;
+
+u64 jiffies_64 = INITIAL_JIFFIES;
+EXPORT_SYMBOL(jiffies_64);
+
+spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
+EXPORT_SYMBOL(rtc_lock);
+
+
+#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT
+unsigned long ccount_per_jiffy; /* per 1/HZ */
+unsigned long ccount_nsec; /* nsec per ccount increment */
+#endif
+
+unsigned int last_ccount_stamp;
+static long last_rtc_update = 0;
+
+/*
+ * Scheduler clock - returns current tim in nanosec units.
+ */
+
+unsigned long long sched_clock(void)
+{
+ return (unsigned long long)jiffies * (1000000000 / HZ);
+}
+
+static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static struct irqaction timer_irqaction = {
+ .handler = timer_interrupt,
+ .flags = SA_INTERRUPT,
+ .name = "timer",
+};
+
+void __init time_init(void)
+{
+ time_t sec_o, sec_n = 0;
+
+ /* The platform must provide a function to calibrate the processor
+ * speed for the CALIBRATE.
+ */
+
+#if CONFIG_XTENSA_CALIBRATE_CCOUNT
+ printk("Calibrating CPU frequency ");
+ platform_calibrate_ccount();
+ printk("%d.%02d MHz\n", (int)ccount_per_jiffy/(1000000/HZ),
+ (int)(ccount_per_jiffy/(10000/HZ))%100);
+#endif
+
+ /* Set time from RTC (if provided) */
+
+ if (platform_get_rtc_time(&sec_o) == 0)
+ while (platform_get_rtc_time(&sec_n))
+ if (sec_o != sec_n)
+ break;
+
+ xtime.tv_nsec = 0;
+ last_rtc_update = xtime.tv_sec = sec_n;
+ last_ccount_stamp = get_ccount();
+
+ set_normalized_timespec(&wall_to_monotonic,
+ -xtime.tv_sec, -xtime.tv_nsec);
+
+ /* Initialize the linux timer interrupt. */
+
+ setup_irq(LINUX_TIMER_INT, &timer_irqaction);
+ set_linux_timer(get_ccount() + CCOUNT_PER_JIFFY);
+}
+
+
+int do_settimeofday(struct timespec *tv)
+{
+ time_t wtm_sec, sec = tv->tv_sec;
+ long wtm_nsec, nsec = tv->tv_nsec;
+ unsigned long ccount;
+
+ if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+ return -EINVAL;
+
+ write_seqlock_irq(&xtime_lock);
+
+ /* This is revolting. We need to set "xtime" correctly. However, the
+ * value in this location is the value at the most recent update of
+ * wall time. Discover what correction gettimeofday() would have
+ * made, and then undo it!
+ */
+ ccount = get_ccount();
+ nsec -= (ccount - last_ccount_stamp) * CCOUNT_NSEC;
+ nsec -= (jiffies - wall_jiffies) * CCOUNT_PER_JIFFY * CCOUNT_NSEC;
+
+ wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+ wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+ set_normalized_timespec(&xtime, sec, nsec);
+ set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+
+ time_adjust = 0; /* stop active adjtime() */
+ time_status |= STA_UNSYNC;
+ time_maxerror = NTP_PHASE_LIMIT;
+ time_esterror = NTP_PHASE_LIMIT;
+ write_sequnlock_irq(&xtime_lock);
+ return 0;
+}
+
+EXPORT_SYMBOL(do_settimeofday);
+
+
+void do_gettimeofday(struct timeval *tv)
+{
+ unsigned long flags;
+ unsigned long sec, usec, delta, lost, seq;
+
+ do {
+ seq = read_seqbegin_irqsave(&xtime_lock, flags);
+
+ delta = get_ccount() - last_ccount_stamp;
+ sec = xtime.tv_sec;
+ usec = (xtime.tv_nsec / NSEC_PER_USEC);
+
+ lost = jiffies - wall_jiffies;
+
+ } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
+
+ usec += lost * (1000000UL/HZ) + (delta * CCOUNT_NSEC) / NSEC_PER_USEC;
+ for (; usec >= 1000000; sec++, usec -= 1000000)
+ ;
+
+ tv->tv_sec = sec;
+ tv->tv_usec = usec;
+}
+
+EXPORT_SYMBOL(do_gettimeofday);
+
+/*
+ * The timer interrupt is called HZ times per second.
+ */
+
+irqreturn_t timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
+{
+
+ unsigned long next;
+
+ next = get_linux_timer();
+
+again:
+ while ((signed long)(get_ccount() - next) > 0) {
+
+ profile_tick(CPU_PROFILING, regs);
+#ifndef CONFIG_SMP
+ update_process_times(user_mode(regs));
+#endif
+
+ write_seqlock(&xtime_lock);
+
+ last_ccount_stamp = next;
+ next += CCOUNT_PER_JIFFY;
+ do_timer (regs); /* Linux handler in kernel/timer.c */
+
+ if ((time_status & STA_UNSYNC) == 0 &&
+ xtime.tv_sec - last_rtc_update >= 659 &&
+ abs((xtime.tv_nsec/1000)-(1000000-1000000/HZ))<5000000/HZ &&
+ jiffies - wall_jiffies == 1) {
+
+ if (platform_set_rtc_time(xtime.tv_sec+1) == 0)
+ last_rtc_update = xtime.tv_sec+1;
+ else
+ /* Do it again in 60 s */
+ last_rtc_update += 60;
+ }
+ write_sequnlock(&xtime_lock);
+ }
+
+ /* NOTE: writing CCOMPAREn clears the interrupt. */
+
+ set_linux_timer (next);
+
+ /* Make sure we didn't miss any tick... */
+
+ if ((signed long)(get_ccount() - next) > 0)
+ goto again;
+
+ /* Allow platform to do something usefull (Wdog). */
+
+ platform_heartbeat();
+
+ return IRQ_HANDLED;
+}
+
+#ifndef CONFIG_GENERIC_CALIBRATE_DELAY
+void __devinit calibrate_delay(void)
+{
+ loops_per_jiffy = CCOUNT_PER_JIFFY;
+ printk("Calibrating delay loop (skipped)... "
+ "%lu.%02lu BogoMIPS preset\n",
+ loops_per_jiffy/(1000000/HZ),
+ (loops_per_jiffy/(10000/HZ)) % 100);
+}
+#endif
+
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
new file mode 100644
index 00000000000..804246e743b
--- /dev/null
+++ b/arch/xtensa/kernel/traps.c
@@ -0,0 +1,498 @@
+/*
+ * arch/xtensa/kernel/traps.c
+ *
+ * Exception handling.
+ *
+ * Derived from code with the following copyrights:
+ * Copyright (C) 1994 - 1999 by Ralf Baechle
+ * Modified for R3000 by Paul M. Antoine, 1995, 1996
+ * Complete output from die() by Ulf Carlsson, 1998
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ *
+ * Essentially rewritten for the Xtensa architecture port.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ *
+ * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
+ * Chris Zankel <chris@zankel.net>
+ * Marc Gauthier<marc@tensilica.com, marc@alumni.uwaterloo.ca>
+ * Kevin Chea
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/stringify.h>
+#include <linux/kallsyms.h>
+
+#include <asm/ptrace.h>
+#include <asm/timex.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+
+#ifdef CONFIG_KGDB
+extern int gdb_enter;
+extern int return_from_debug_flag;
+#endif
+
+/*
+ * Machine specific interrupt handlers
+ */
+
+extern void kernel_exception(void);
+extern void user_exception(void);
+
+extern void fast_syscall_kernel(void);
+extern void fast_syscall_user(void);
+extern void fast_alloca(void);
+extern void fast_unaligned(void);
+extern void fast_second_level_miss(void);
+extern void fast_store_prohibited(void);
+extern void fast_coprocessor(void);
+
+extern void do_illegal_instruction (struct pt_regs*);
+extern void do_interrupt (struct pt_regs*);
+extern void do_unaligned_user (struct pt_regs*);
+extern void do_multihit (struct pt_regs*, unsigned long);
+extern void do_page_fault (struct pt_regs*, unsigned long);
+extern void do_debug (struct pt_regs*);
+extern void system_call (struct pt_regs*);
+
+/*
+ * The vector table must be preceded by a save area (which
+ * implies it must be in RAM, unless one places RAM immediately
+ * before a ROM and puts the vector at the start of the ROM (!))
+ */
+
+#define KRNL 0x01
+#define USER 0x02
+
+#define COPROCESSOR(x) \
+{ XCHAL_EXCCAUSE_COPROCESSOR ## x ## _DISABLED, USER, fast_coprocessor }
+
+typedef struct {
+ int cause;
+ int fast;
+ void* handler;
+} dispatch_init_table_t;
+
+dispatch_init_table_t __init dispatch_init_table[] = {
+
+{ XCHAL_EXCCAUSE_ILLEGAL_INSTRUCTION, 0, do_illegal_instruction},
+{ XCHAL_EXCCAUSE_SYSTEM_CALL, KRNL, fast_syscall_kernel },
+{ XCHAL_EXCCAUSE_SYSTEM_CALL, USER, fast_syscall_user },
+{ XCHAL_EXCCAUSE_SYSTEM_CALL, 0, system_call },
+/* XCHAL_EXCCAUSE_INSTRUCTION_FETCH unhandled */
+/* XCHAL_EXCCAUSE_LOAD_STORE_ERROR unhandled*/
+{ XCHAL_EXCCAUSE_LEVEL1_INTERRUPT, 0, do_interrupt },
+{ XCHAL_EXCCAUSE_ALLOCA, USER|KRNL, fast_alloca },
+/* XCHAL_EXCCAUSE_INTEGER_DIVIDE_BY_ZERO unhandled */
+/* XCHAL_EXCCAUSE_PRIVILEGED unhandled */
+#if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
+#ifdef CONFIG_UNALIGNED_USER
+{ XCHAL_EXCCAUSE_UNALIGNED, USER, fast_unaligned },
+#else
+{ XCHAL_EXCCAUSE_UNALIGNED, 0, do_unaligned_user },
+#endif
+{ XCHAL_EXCCAUSE_UNALIGNED, KRNL, fast_unaligned },
+#endif
+{ XCHAL_EXCCAUSE_ITLB_MISS, 0, do_page_fault },
+{ XCHAL_EXCCAUSE_ITLB_MISS, USER|KRNL, fast_second_level_miss},
+{ XCHAL_EXCCAUSE_ITLB_MULTIHIT, 0, do_multihit },
+{ XCHAL_EXCCAUSE_ITLB_PRIVILEGE, 0, do_page_fault },
+/* XCHAL_EXCCAUSE_SIZE_RESTRICTION unhandled */
+{ XCHAL_EXCCAUSE_FETCH_CACHE_ATTRIBUTE, 0, do_page_fault },
+{ XCHAL_EXCCAUSE_DTLB_MISS, USER|KRNL, fast_second_level_miss},
+{ XCHAL_EXCCAUSE_DTLB_MISS, 0, do_page_fault },
+{ XCHAL_EXCCAUSE_DTLB_MULTIHIT, 0, do_multihit },
+{ XCHAL_EXCCAUSE_DTLB_PRIVILEGE, 0, do_page_fault },
+/* XCHAL_EXCCAUSE_DTLB_SIZE_RESTRICTION unhandled */
+{ XCHAL_EXCCAUSE_STORE_CACHE_ATTRIBUTE, USER|KRNL, fast_store_prohibited },
+{ XCHAL_EXCCAUSE_STORE_CACHE_ATTRIBUTE, 0, do_page_fault },
+{ XCHAL_EXCCAUSE_LOAD_CACHE_ATTRIBUTE, 0, do_page_fault },
+/* XCCHAL_EXCCAUSE_FLOATING_POINT unhandled */
+#if (XCHAL_CP_MASK & 1)
+COPROCESSOR(0),
+#endif
+#if (XCHAL_CP_MASK & 2)
+COPROCESSOR(1),
+#endif
+#if (XCHAL_CP_MASK & 4)
+COPROCESSOR(2),
+#endif
+#if (XCHAL_CP_MASK & 8)
+COPROCESSOR(3),
+#endif
+#if (XCHAL_CP_MASK & 16)
+COPROCESSOR(4),
+#endif
+#if (XCHAL_CP_MASK & 32)
+COPROCESSOR(5),
+#endif
+#if (XCHAL_CP_MASK & 64)
+COPROCESSOR(6),
+#endif
+#if (XCHAL_CP_MASK & 128)
+COPROCESSOR(7),
+#endif
+{ EXCCAUSE_MAPPED_DEBUG, 0, do_debug },
+{ -1, -1, 0 }
+
+};
+
+/* The exception table <exc_table> serves two functions:
+ * 1. it contains three dispatch tables (fast_user, fast_kernel, default-c)
+ * 2. it is a temporary memory buffer for the exception handlers.
+ */
+
+unsigned long exc_table[EXC_TABLE_SIZE/4];
+
+void die(const char*, struct pt_regs*, long);
+
+static inline void
+__die_if_kernel(const char *str, struct pt_regs *regs, long err)
+{
+ if (!user_mode(regs))
+ die(str, regs, err);
+}
+
+/*
+ * Unhandled Exceptions. Kill user task or panic if in kernel space.
+ */
+
+void do_unhandled(struct pt_regs *regs, unsigned long exccause)
+{
+ __die_if_kernel("Caught unhandled exception - should not happen",
+ regs, SIGKILL);
+
+ /* If in user mode, send SIGILL signal to current process */
+ printk("Caught unhandled exception in '%s' "
+ "(pid = %d, pc = %#010lx) - should not happen\n"
+ "\tEXCCAUSE is %ld\n",
+ current->comm, current->pid, regs->pc, exccause);
+ force_sig(SIGILL, current);
+}
+
+/*
+ * Multi-hit exception. This if fatal!
+ */
+
+void do_multihit(struct pt_regs *regs, unsigned long exccause)
+{
+ die("Caught multihit exception", regs, SIGKILL);
+}
+
+/*
+ * Level-1 interrupt.
+ * We currently have no priority encoding.
+ */
+
+unsigned long ignored_level1_interrupts;
+extern void do_IRQ(int, struct pt_regs *);
+
+void do_interrupt (struct pt_regs *regs)
+{
+ unsigned long intread = get_sr (INTREAD);
+ unsigned long intenable = get_sr (INTENABLE);
+ int i, mask;
+
+ /* Handle all interrupts (no priorities).
+ * (Clear the interrupt before processing, in case it's
+ * edge-triggered or software-generated)
+ */
+
+ for (i=0, mask = 1; i < XCHAL_NUM_INTERRUPTS; i++, mask <<= 1) {
+ if (mask & (intread & intenable)) {
+ set_sr (mask, INTCLEAR);
+ do_IRQ (i,regs);
+ }
+ }
+}
+
+/*
+ * Illegal instruction. Fatal if in kernel space.
+ */
+
+void
+do_illegal_instruction(struct pt_regs *regs)
+{
+ __die_if_kernel("Illegal instruction in kernel", regs, SIGKILL);
+
+ /* If in user mode, send SIGILL signal to current process. */
+
+ printk("Illegal Instruction in '%s' (pid = %d, pc = %#010lx)\n",
+ current->comm, current->pid, regs->pc);
+ force_sig(SIGILL, current);
+}
+
+
+/*
+ * Handle unaligned memory accesses from user space. Kill task.
+ *
+ * If CONFIG_UNALIGNED_USER is not set, we don't allow unaligned memory
+ * accesses causes from user space.
+ */
+
+#if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
+#ifndef CONFIG_UNALIGNED_USER
+void
+do_unaligned_user (struct pt_regs *regs)
+{
+ siginfo_t info;
+
+ __die_if_kernel("Unhandled unaligned exception in kernel",
+ regs, SIGKILL);
+
+ current->thread.bad_vaddr = regs->excvaddr;
+ current->thread.error_code = -3;
+ printk("Unaligned memory access to %08lx in '%s' "
+ "(pid = %d, pc = %#010lx)\n",
+ regs->excvaddr, current->comm, current->pid, regs->pc);
+ info.si_signo = SIGBUS;
+ info.si_errno = 0;
+ info.si_code = BUS_ADRALN;
+ info.si_addr = (void *) regs->excvaddr;
+ force_sig_info(SIGSEGV, &info, current);
+
+}
+#endif
+#endif
+
+void
+do_debug(struct pt_regs *regs)
+{
+#ifdef CONFIG_KGDB
+ /* If remote debugging is configured AND enabled, we give control to
+ * kgdb. Otherwise, we fall through, perhaps giving control to the
+ * native debugger.
+ */
+
+ if (gdb_enter) {
+ extern void gdb_handle_exception(struct pt_regs *);
+ gdb_handle_exception(regs);
+ return_from_debug_flag = 1;
+ return;
+ }
+#endif
+
+ __die_if_kernel("Breakpoint in kernel", regs, SIGKILL);
+
+ /* If in user mode, send SIGTRAP signal to current process */
+
+ force_sig(SIGTRAP, current);
+}
+
+
+/*
+ * Initialize dispatch tables.
+ *
+ * The exception vectors are stored compressed the __init section in the
+ * dispatch_init_table. This function initializes the following three tables
+ * from that compressed table:
+ * - fast user first dispatch table for user exceptions
+ * - fast kernel first dispatch table for kernel exceptions
+ * - default C-handler C-handler called by the default fast handler.
+ *
+ * See vectors.S for more details.
+ */
+
+#define set_handler(idx,handler) (exc_table[idx] = (unsigned long) (handler))
+
+void trap_init(void)
+{
+ int i;
+
+ /* Setup default vectors. */
+
+ for(i = 0; i < 64; i++) {
+ set_handler(EXC_TABLE_FAST_USER/4 + i, user_exception);
+ set_handler(EXC_TABLE_FAST_KERNEL/4 + i, kernel_exception);
+ set_handler(EXC_TABLE_DEFAULT/4 + i, do_unhandled);
+ }
+
+ /* Setup specific handlers. */
+
+ for(i = 0; dispatch_init_table[i].cause >= 0; i++) {
+
+ int fast = dispatch_init_table[i].fast;
+ int cause = dispatch_init_table[i].cause;
+ void *handler = dispatch_init_table[i].handler;
+
+ if (fast == 0)
+ set_handler (EXC_TABLE_DEFAULT/4 + cause, handler);
+ if (fast && fast & USER)
+ set_handler (EXC_TABLE_FAST_USER/4 + cause, handler);
+ if (fast && fast & KRNL)
+ set_handler (EXC_TABLE_FAST_KERNEL/4 + cause, handler);
+ }
+
+ /* Initialize EXCSAVE_1 to hold the address of the exception table. */
+
+ i = (unsigned long)exc_table;
+ __asm__ __volatile__("wsr %0, "__stringify(EXCSAVE_1)"\n" : : "a" (i));
+}
+
+/*
+ * This function dumps the current valid window frame and other base registers.
+ */
+
+void show_regs(struct pt_regs * regs)
+{
+ int i, wmask;
+
+ wmask = regs->wmask & ~1;
+
+ for (i = 0; i < 32; i++) {
+ if (wmask & (1 << (i / 4)))
+ break;
+ if ((i % 8) == 0)
+ printk ("\n" KERN_INFO "a%02d: ", i);
+ printk("%08lx ", regs->areg[i]);
+ }
+ printk("\n");
+
+ printk("pc: %08lx, ps: %08lx, depc: %08lx, excvaddr: %08lx\n",
+ regs->pc, regs->ps, regs->depc, regs->excvaddr);
+ printk("lbeg: %08lx, lend: %08lx lcount: %08lx, sar: %08lx\n",
+ regs->lbeg, regs->lend, regs->lcount, regs->sar);
+ if (user_mode(regs))
+ printk("wb: %08lx, ws: %08lx, wmask: %08lx, syscall: %ld\n",
+ regs->windowbase, regs->windowstart, regs->wmask,
+ regs->syscall);
+}
+
+void show_trace(struct task_struct *task, unsigned long *sp)
+{
+ unsigned long a0, a1, pc;
+ unsigned long sp_start, sp_end;
+
+ a1 = (unsigned long)sp;
+
+ if (a1 == 0)
+ __asm__ __volatile__ ("mov %0, a1\n" : "=a"(a1));
+
+
+ sp_start = a1 & ~(THREAD_SIZE-1);
+ sp_end = sp_start + THREAD_SIZE;
+
+ printk("Call Trace:");
+#ifdef CONFIG_KALLSYMS
+ printk("\n");
+#endif
+ spill_registers();
+
+ while (a1 > sp_start && a1 < sp_end) {
+ sp = (unsigned long*)a1;
+
+ a0 = *(sp - 4);
+ a1 = *(sp - 3);
+
+ if (a1 <= (unsigned long) sp)
+ break;
+
+ pc = MAKE_PC_FROM_RA(a0, a1);
+
+ if (kernel_text_address(pc)) {
+ printk(" [<%08lx>] ", pc);
+ print_symbol("%s\n", pc);
+ }
+ }
+ printk("\n");
+}
+
+/*
+ * This routine abuses get_user()/put_user() to reference pointers
+ * with at least a bit of error checking ...
+ */
+
+static int kstack_depth_to_print = 24;
+
+void show_stack(struct task_struct *task, unsigned long *sp)
+{
+ int i = 0;
+ unsigned long *stack;
+
+ if (sp == 0)
+ __asm__ __volatile__ ("mov %0, a1\n" : "=a"(sp));
+
+ stack = sp;
+
+ printk("\nStack: ");
+
+ for (i = 0; i < kstack_depth_to_print; i++) {
+ if (kstack_end(sp))
+ break;
+ if (i && ((i % 8) == 0))
+ printk("\n ");
+ printk("%08lx ", *sp++);
+ }
+ printk("\n");
+ show_trace(task, stack);
+}
+
+void dump_stack(void)
+{
+ show_stack(current, NULL);
+}
+
+EXPORT_SYMBOL(dump_stack);
+
+
+void show_code(unsigned int *pc)
+{
+ long i;
+
+ printk("\nCode:");
+
+ for(i = -3 ; i < 6 ; i++) {
+ unsigned long insn;
+ if (__get_user(insn, pc + i)) {
+ printk(" (Bad address in pc)\n");
+ break;
+ }
+ printk("%c%08lx%c",(i?' ':'<'),insn,(i?' ':'>'));
+ }
+}
+
+spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
+
+void die(const char * str, struct pt_regs * regs, long err)
+{
+ static int die_counter;
+ int nl = 0;
+
+ console_verbose();
+ spin_lock_irq(&die_lock);
+
+ printk("%s: sig: %ld [#%d]\n", str, err, ++die_counter);
+#ifdef CONFIG_PREEMPT
+ printk("PREEMPT ");
+ nl = 1;
+#endif
+ if (nl)
+ printk("\n");
+ show_regs(regs);
+ if (!user_mode(regs))
+ show_stack(NULL, (unsigned long*)regs->areg[1]);
+
+ spin_unlock_irq(&die_lock);
+
+ if (in_interrupt())
+ panic("Fatal exception in interrupt");
+
+ if (panic_on_oops) {
+ printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n");
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(5 * HZ);
+ panic("Fatal exception");
+ }
+ do_exit(err);
+}
+
+
diff --git a/arch/xtensa/kernel/vectors.S b/arch/xtensa/kernel/vectors.S
new file mode 100644
index 00000000000..81808f0c674
--- /dev/null
+++ b/arch/xtensa/kernel/vectors.S
@@ -0,0 +1,464 @@
+/*
+ * arch/xtensa/kernel/vectors.S
+ *
+ * This file contains all exception vectors (user, kernel, and double),
+ * as well as the window vectors (overflow and underflow), and the debug
+ * vector. These are the primary vectors executed by the processor if an
+ * exception occurs.
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ *
+ * Copyright (C) 2005 Tensilica, Inc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ *
+ */
+
+/*
+ * We use a two-level table approach. The user and kernel exception vectors
+ * use a first-level dispatch table to dispatch the exception to a registered
+ * fast handler or the default handler, if no fast handler was registered.
+ * The default handler sets up a C-stack and dispatches the exception to a
+ * registerd C handler in the second-level dispatch table.
+ *
+ * Fast handler entry condition:
+ *
+ * a0: trashed, original value saved on stack (PT_AREG0)
+ * a1: a1
+ * a2: new stack pointer, original value in depc
+ * a3: dispatch table
+ * depc: a2, original value saved on stack (PT_DEPC)
+ * excsave_1: a3
+ *
+ * The value for PT_DEPC saved to stack also functions as a boolean to
+ * indicate that the exception is either a double or a regular exception:
+ *
+ * PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception
+ * < VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
+ *
+ * Note: Neither the kernel nor the user exception handler generate literals.
+ *
+ */
+
+#include <linux/linkage.h>
+#include <asm/ptrace.h>
+#include <asm/ptrace.h>
+#include <asm/current.h>
+#include <asm/offsets.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/thread_info.h>
+#include <asm/processor.h>
+
+
+/*
+ * User exception vector. (Exceptions with PS.UM == 1, PS.EXCM == 0)
+ *
+ * We get here when an exception occurred while we were in userland.
+ * We switch to the kernel stack and jump to the first level handler
+ * associated to the exception cause.
+ *
+ * Note: the saved kernel stack pointer (EXC_TABLE_KSTK) is already
+ * decremented by PT_USER_SIZE.
+ */
+
+ .section .UserExceptionVector.text, "ax"
+
+ENTRY(_UserExceptionVector)
+
+ xsr a3, EXCSAVE_1 # save a3 and get dispatch table
+ wsr a2, DEPC # save a2
+ l32i a2, a3, EXC_TABLE_KSTK # load kernel stack to a2
+ s32i a0, a2, PT_AREG0 # save a0 to ESF
+ rsr a0, EXCCAUSE # retrieve exception cause
+ s32i a0, a2, PT_DEPC # mark it as a regular exception
+ addx4 a0, a0, a3 # find entry in table
+ l32i a0, a0, EXC_TABLE_FAST_USER # load handler
+ jx a0
+
+/*
+ * Kernel exception vector. (Exceptions with PS.UM == 0, PS.EXCM == 0)
+ *
+ * We get this exception when we were already in kernel space.
+ * We decrement the current stack pointer (kernel) by PT_SIZE and
+ * jump to the first-level handler associated with the exception cause.
+ *
+ * Note: we need to preserve space for the spill region.
+ */
+
+ .section .KernelExceptionVector.text, "ax"
+
+ENTRY(_KernelExceptionVector)
+
+ xsr a3, EXCSAVE_1 # save a3, and get dispatch table
+ wsr a2, DEPC # save a2
+ addi a2, a1, -16-PT_SIZE # adjust stack pointer
+ s32i a0, a2, PT_AREG0 # save a0 to ESF
+ rsr a0, EXCCAUSE # retrieve exception cause
+ s32i a0, a2, PT_DEPC # mark it as a regular exception
+ addx4 a0, a0, a3 # find entry in table
+ l32i a0, a0, EXC_TABLE_FAST_KERNEL # load handler address
+ jx a0
+
+
+/*
+ * Double exception vector (Exceptions with PS.EXCM == 1)
+ * We get this exception when another exception occurs while were are
+ * already in an exception, such as window overflow/underflow exception,
+ * or 'expected' exceptions, for example memory exception when we were trying
+ * to read data from an invalid address in user space.
+ *
+ * Note that this vector is never invoked for level-1 interrupts, because such
+ * interrupts are disabled (masked) when PS.EXCM is set.
+ *
+ * We decode the exception and take the appropriate action. However, the
+ * double exception vector is much more careful, because a lot more error
+ * cases go through the double exception vector than through the user and
+ * kernel exception vectors.
+ *
+ * Occasionally, the kernel expects a double exception to occur. This usually
+ * happens when accessing user-space memory with the user's permissions
+ * (l32e/s32e instructions). The kernel state, though, is not always suitable
+ * for immediate transfer of control to handle_double, where "normal" exception
+ * processing occurs. Also in kernel mode, TLB misses can occur if accessing
+ * vmalloc memory, possibly requiring repair in a double exception handler.
+ *
+ * The variable at TABLE_FIXUP offset from the pointer in EXCSAVE_1 doubles as
+ * a boolean variable and a pointer to a fixup routine. If the variable
+ * EXC_TABLE_FIXUP is non-zero, this handler jumps to that address. A value of
+ * zero indicates to use the default kernel/user exception handler.
+ * There is only one exception, when the value is identical to the exc_table
+ * label, the kernel is in trouble. This mechanism is used to protect critical
+ * sections, mainly when the handler writes to the stack to assert the stack
+ * pointer is valid. Once the fixup/default handler leaves that area, the
+ * EXC_TABLE_FIXUP variable is reset to the fixup handler or zero.
+ *
+ * Procedures wishing to use this mechanism should set EXC_TABLE_FIXUP to the
+ * nonzero address of a fixup routine before it could cause a double exception
+ * and reset it before it returns.
+ *
+ * Some other things to take care of when a fast exception handler doesn't
+ * specify a particular fixup handler but wants to use the default handlers:
+ *
+ * - The original stack pointer (in a1) must not be modified. The fast
+ * exception handler should only use a2 as the stack pointer.
+ *
+ * - If the fast handler manipulates the stack pointer (in a2), it has to
+ * register a valid fixup handler and cannot use the default handlers.
+ *
+ * - The handler can use any other generic register from a3 to a15, but it
+ * must save the content of these registers to stack (PT_AREG3...PT_AREGx)
+ *
+ * - These registers must be saved before a double exception can occur.
+ *
+ * - If we ever implement handling signals while in double exceptions, the
+ * number of registers a fast handler has saved (excluding a0 and a1) must
+ * be written to PT_AREG1. (1 if only a3 is used, 2 for a3 and a4, etc. )
+ *
+ * The fixup handlers are special handlers:
+ *
+ * - Fixup entry conditions differ from regular exceptions:
+ *
+ * a0: DEPC
+ * a1: a1
+ * a2: trashed, original value in EXC_TABLE_DOUBLE_A2
+ * a3: exctable
+ * depc: a0
+ * excsave_1: a3
+ *
+ * - When the kernel enters the fixup handler, it still assumes it is in a
+ * critical section, so EXC_TABLE_FIXUP variable is set to exc_table.
+ * The fixup handler, therefore, has to re-register itself as the fixup
+ * handler before it returns from the double exception.
+ *
+ * - Fixup handler can share the same exception frame with the fast handler.
+ * The kernel stack pointer is not changed when entering the fixup handler.
+ *
+ * - Fixup handlers can jump to the default kernel and user exception
+ * handlers. Before it jumps, though, it has to setup a exception frame
+ * on stack. Because the default handler resets the register fixup handler
+ * the fixup handler must make sure that the default handler returns to
+ * it instead of the exception address, so it can re-register itself as
+ * the fixup handler.
+ *
+ * In case of a critical condition where the kernel cannot recover, we jump
+ * to unrecoverable_exception with the following entry conditions.
+ * All registers a0...a15 are unchanged from the last exception, except:
+ *
+ * a0: last address before we jumped to the unrecoverable_exception.
+ * excsave_1: a0
+ *
+ *
+ * See the handle_alloca_user and spill_registers routines for example clients.
+ *
+ * FIXME: Note: we currently don't allow signal handling coming from a double
+ * exception, so the item markt with (*) is not required.
+ */
+
+ .section .DoubleExceptionVector.text, "ax"
+ .begin literal_prefix .DoubleExceptionVector
+
+ENTRY(_DoubleExceptionVector)
+
+ /* Deliberately destroy excsave (don't assume it's value was valid). */
+
+ wsr a3, EXCSAVE_1 # save a3
+
+ /* Check for kernel double exception (usually fatal). */
+
+ rsr a3, PS
+ _bbci.l a3, PS_UM_SHIFT, .Lksp
+
+ /* Check if we are currently handling a window exception. */
+ /* Note: We don't need to indicate that we enter a critical section. */
+
+ xsr a0, DEPC # get DEPC, save a0
+
+ movi a3, XCHAL_WINDOW_VECTORS_VADDR
+ _bltu a0, a3, .Lfixup
+ addi a3, a3, XSHAL_WINDOW_VECTORS_SIZE
+ _bgeu a0, a3, .Lfixup
+
+ /* Window overflow/underflow exception. Get stack pointer. */
+
+ mov a3, a2
+ movi a2, exc_table
+ l32i a2, a2, EXC_TABLE_KSTK
+
+ /* Check for overflow/underflow exception, jump if overflow. */
+
+ _bbci.l a0, 6, .Lovfl
+
+ /* a0: depc, a1: a1, a2: kstk, a3: a2, depc: a0, excsave: a3 */
+
+ /* Restart window underflow exception.
+ * We return to the instruction in user space that caused the window
+ * underflow exception. Therefore, we change window base to the value
+ * before we entered the window underflow exception and prepare the
+ * registers to return as if we were coming from a regular exception
+ * by changing depc (in a0).
+ * Note: We can trash the current window frame (a0...a3) and depc!
+ */
+
+ wsr a2, DEPC # save stack pointer temporarily
+ rsr a0, PS
+ extui a0, a0, XCHAL_PS_OWB_SHIFT, XCHAL_PS_OWB_BITS
+ wsr a0, WINDOWBASE
+ rsync
+
+ /* We are now in the previous window frame. Save registers again. */
+
+ xsr a2, DEPC # save a2 and get stack pointer
+ s32i a0, a2, PT_AREG0
+
+ wsr a3, EXCSAVE_1 # save a3
+ movi a3, exc_table
+
+ rsr a0, EXCCAUSE
+ s32i a0, a2, PT_DEPC # mark it as a regular exception
+ addx4 a0, a0, a3
+ l32i a0, a0, EXC_TABLE_FAST_USER
+ jx a0
+
+.Lfixup:/* Check for a fixup handler or if we were in a critical section. */
+
+ /* a0: depc, a1: a1, a2: a2, a3: trashed, depc: a0, excsave1: a3 */
+
+ movi a3, exc_table
+ s32i a2, a3, EXC_TABLE_DOUBLE_SAVE # temporary variable
+
+ /* Enter critical section. */
+
+ l32i a2, a3, EXC_TABLE_FIXUP
+ s32i a3, a3, EXC_TABLE_FIXUP
+ beq a2, a3, .Lunrecoverable_fixup # critical!
+ beqz a2, .Ldflt # no handler was registered
+
+ /* a0: depc, a1: a1, a2: trash, a3: exctable, depc: a0, excsave: a3 */
+
+ jx a2
+
+.Ldflt: /* Get stack pointer. */
+
+ l32i a3, a3, EXC_TABLE_DOUBLE_SAVE
+ addi a2, a3, -PT_USER_SIZE
+
+.Lovfl: /* Jump to default handlers. */
+
+ /* a0: depc, a1: a1, a2: kstk, a3: a2, depc: a0, excsave: a3 */
+
+ xsr a3, DEPC
+ s32i a0, a2, PT_DEPC
+ s32i a3, a2, PT_AREG0
+
+ /* a0: avail, a1: a1, a2: kstk, a3: avail, depc: a2, excsave: a3 */
+
+ movi a3, exc_table
+ rsr a0, EXCCAUSE
+ addx4 a0, a0, a3
+ l32i a0, a0, EXC_TABLE_FAST_USER
+ jx a0
+
+ /*
+ * We only allow the ITLB miss exception if we are in kernel space.
+ * All other exceptions are unexpected and thus unrecoverable!
+ */
+
+ .extern fast_second_level_miss_double_kernel
+
+.Lksp: /* a0: a0, a1: a1, a2: a2, a3: trashed, depc: depc, excsave: a3 */
+
+ rsr a3, EXCCAUSE
+ beqi a3, XCHAL_EXCCAUSE_ITLB_MISS, 1f
+ addi a3, a3, -XCHAL_EXCCAUSE_DTLB_MISS
+ bnez a3, .Lunrecoverable
+1: movi a3, fast_second_level_miss_double_kernel
+ jx a3
+
+ /* Critical! We can't handle this situation. PANIC! */
+
+ .extern unrecoverable_exception
+
+.Lunrecoverable_fixup:
+ l32i a2, a3, EXC_TABLE_DOUBLE_SAVE
+ xsr a0, DEPC
+
+.Lunrecoverable:
+ rsr a3, EXCSAVE_1
+ wsr a0, EXCSAVE_1
+ movi a0, unrecoverable_exception
+ callx0 a0
+
+ .end literal_prefix
+
+
+/*
+ * Debug interrupt vector
+ *
+ * There is not much space here, so simply jump to another handler.
+ * EXCSAVE[DEBUGLEVEL] has been set to that handler.
+ */
+
+ .section .DebugInterruptVector.text, "ax"
+
+ENTRY(_DebugInterruptVector)
+ xsr a0, EXCSAVE + XCHAL_DEBUGLEVEL
+ jx a0
+
+
+
+/* Window overflow and underflow handlers.
+ * The handlers must be 64 bytes apart, first starting with the underflow
+ * handlers underflow-4 to underflow-12, then the overflow handlers
+ * overflow-4 to overflow-12.
+ *
+ * Note: We rerun the underflow handlers if we hit an exception, so
+ * we try to access any page that would cause a page fault early.
+ */
+
+ .section .WindowVectors.text, "ax"
+
+
+/* 4-Register Window Overflow Vector (Handler) */
+
+ .align 64
+.global _WindowOverflow4
+_WindowOverflow4:
+ s32e a0, a5, -16
+ s32e a1, a5, -12
+ s32e a2, a5, -8
+ s32e a3, a5, -4
+ rfwo
+
+
+/* 4-Register Window Underflow Vector (Handler) */
+
+ .align 64
+.global _WindowUnderflow4
+_WindowUnderflow4:
+ l32e a0, a5, -16
+ l32e a1, a5, -12
+ l32e a2, a5, -8
+ l32e a3, a5, -4
+ rfwu
+
+
+/* 8-Register Window Overflow Vector (Handler) */
+
+ .align 64
+.global _WindowOverflow8
+_WindowOverflow8:
+ s32e a0, a9, -16
+ l32e a0, a1, -12
+ s32e a2, a9, -8
+ s32e a1, a9, -12
+ s32e a3, a9, -4
+ s32e a4, a0, -32
+ s32e a5, a0, -28
+ s32e a6, a0, -24
+ s32e a7, a0, -20
+ rfwo
+
+/* 8-Register Window Underflow Vector (Handler) */
+
+ .align 64
+.global _WindowUnderflow8
+_WindowUnderflow8:
+ l32e a1, a9, -12
+ l32e a0, a9, -16
+ l32e a7, a1, -12
+ l32e a2, a9, -8
+ l32e a4, a7, -32
+ l32e a3, a9, -4
+ l32e a5, a7, -28
+ l32e a6, a7, -24
+ l32e a7, a7, -20
+ rfwu
+
+
+/* 12-Register Window Overflow Vector (Handler) */
+
+ .align 64
+.global _WindowOverflow12
+_WindowOverflow12:
+ s32e a0, a13, -16
+ l32e a0, a1, -12
+ s32e a1, a13, -12
+ s32e a2, a13, -8
+ s32e a3, a13, -4
+ s32e a4, a0, -48
+ s32e a5, a0, -44
+ s32e a6, a0, -40
+ s32e a7, a0, -36
+ s32e a8, a0, -32
+ s32e a9, a0, -28
+ s32e a10, a0, -24
+ s32e a11, a0, -20
+ rfwo
+
+/* 12-Register Window Underflow Vector (Handler) */
+
+ .align 64
+.global _WindowUnderflow12
+_WindowUnderflow12:
+ l32e a1, a13, -12
+ l32e a0, a13, -16
+ l32e a11, a1, -12
+ l32e a2, a13, -8
+ l32e a4, a11, -48
+ l32e a8, a11, -32
+ l32e a3, a13, -4
+ l32e a5, a11, -44
+ l32e a6, a11, -40
+ l32e a7, a11, -36
+ l32e a9, a11, -28
+ l32e a10, a11, -24
+ l32e a11, a11, -20
+ rfwu
+
+ .text
+
+
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S
new file mode 100644
index 00000000000..476b2b53cd0
--- /dev/null
+++ b/arch/xtensa/kernel/vmlinux.lds.S
@@ -0,0 +1,341 @@
+/*
+ * arch/xtensa/kernel/vmlinux.lds.S
+ *
+ * Xtensa linker script
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ * Marc Gauthier <marc@tensilica.com, marc@alumni.uwaterloo.ca>
+ * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
+ */
+
+#include <asm-generic/vmlinux.lds.h>
+
+#include <linux/config.h>
+#define _NOCLANGUAGE
+#include <xtensa/config/core.h>
+#include <xtensa/config/system.h>
+OUTPUT_ARCH(xtensa)
+ENTRY(_start)
+
+#if XCHAL_MEMORY_ORDER == XTHAL_BIGENDIAN
+jiffies = jiffies_64 + 4;
+#else
+jiffies = jiffies_64;
+#endif
+
+#define KERNELOFFSET 0x1000
+
+/* Note: In the following macros, it would be nice to specify only the
+ vector name and section kind and construct "sym" and "section" using
+ CPP concatenation, but that does not work reliably. Concatenating a
+ string with "." produces an invalid token. CPP will not print a
+ warning because it thinks this is an assembly file, but it leaves
+ them as multiple tokens and there may or may not be whitespace
+ between them. */
+
+/* Macro for a relocation entry */
+
+#define RELOCATE_ENTRY(sym, section) \
+ LONG(sym ## _start); \
+ LONG(sym ## _end); \
+ LONG(LOADADDR(section))
+
+/* Macro to define a section for a vector.
+ *
+ * Use of the MIN function catches the types of errors illustrated in
+ * the following example:
+ *
+ * Assume the section .DoubleExceptionVector.literal is completely
+ * full. Then a programmer adds code to .DoubleExceptionVector.text
+ * that produces another literal. The final literal position will
+ * overlay onto the first word of the adjacent code section
+ * .DoubleExceptionVector.text. (In practice, the literals will
+ * overwrite the code, and the first few instructions will be
+ * garbage.)
+ */
+
+#define SECTION_VECTOR(sym, section, addr, max_prevsec_size, prevsec) \
+ section addr : AT((MIN(LOADADDR(prevsec) + max_prevsec_size, \
+ LOADADDR(prevsec) + SIZEOF(prevsec)) + 3) & ~ 3) \
+ { \
+ . = ALIGN(4); \
+ sym ## _start = ABSOLUTE(.); \
+ *(section) \
+ sym ## _end = ABSOLUTE(.); \
+ }
+
+/*
+ * Mapping of input sections to output sections when linking.
+ */
+
+SECTIONS
+{
+ . = XCHAL_KSEG_CACHED_VADDR + KERNELOFFSET;
+ /* .text section */
+
+ _text = .;
+ _stext = .;
+ _ftext = .;
+
+ .text :
+ {
+ /* The .head.text section must be the first section! */
+ *(.head.text)
+ *(.literal .text)
+ *(.srom.text)
+ VMLINUX_SYMBOL(__sched_text_start) = .;
+ *(.sched.text.literal .sched.text)
+ VMLINUX_SYMBOL(__sched_text_end) = .;
+ VMLINUX_SYMBOL(__lock_text_start) = .;
+ *(.spinlock.text.literal .spinlock.text)
+ VMLINUX_SYMBOL(__lock_text_end) = .;
+
+ }
+ _etext = .;
+
+ . = ALIGN(16);
+
+ RODATA
+
+ /* Relocation table */
+
+ . = ALIGN(16);
+ __boot_reloc_table_start = ABSOLUTE(.);
+
+ __relocate : {
+
+ RELOCATE_ENTRY(_WindowVectors_text,
+ .WindowVectors.text);
+#if 0
+ RELOCATE_ENTRY(_KernelExceptionVector_literal,
+ .KernelExceptionVector.literal);
+#endif
+ RELOCATE_ENTRY(_KernelExceptionVector_text,
+ .KernelExceptionVector.text);
+#if 0
+ RELOCATE_ENTRY(_UserExceptionVector_literal,
+ .UserExceptionVector.literal);
+#endif
+ RELOCATE_ENTRY(_UserExceptionVector_text,
+ .UserExceptionVector.text);
+ RELOCATE_ENTRY(_DoubleExceptionVector_literal,
+ .DoubleExceptionVector.literal);
+ RELOCATE_ENTRY(_DoubleExceptionVector_text,
+ .DoubleExceptionVector.text);
+ }
+ __boot_reloc_table_end = ABSOLUTE(.) ;
+
+ .fixup : { *(.fixup) }
+
+ . = ALIGN(16);
+
+ __ex_table : {
+ __start___ex_table = .;
+ *(__ex_table)
+ __stop___ex_table = .;
+ }
+
+ /* Data section */
+
+ . = ALIGN(XCHAL_ICACHE_LINESIZE);
+ _fdata = .;
+ .data :
+ {
+ *(.data) CONSTRUCTORS
+ . = ALIGN(XCHAL_ICACHE_LINESIZE);
+ *(.data.cacheline_aligned)
+ }
+
+ _edata = .;
+
+ /* The initial task */
+ . = ALIGN(8192);
+ .data.init_task : { *(.data.init_task) }
+
+ /* Initialization code and data: */
+
+ . = ALIGN(1<<XCHAL_MMU_MIN_PTE_PAGE_SIZE);
+ __init_begin = .;
+ .init.text : {
+ _sinittext = .;
+ *(.init.text.literal) *(.init.text)
+ _einittext = .;
+ }
+
+ .init.data :
+ {
+ *(.init.data)
+ . = ALIGN(0x4);
+ __tagtable_begin = .;
+ *(.taglist)
+ __tagtable_end = .;
+ }
+
+ . = ALIGN(XCHAL_ICACHE_LINESIZE);
+
+ __setup_start = .;
+ .init.setup : { *(.init.setup) }
+ __setup_end = .;
+
+ __initcall_start = .;
+ .initcall.init : {
+ *(.initcall1.init)
+ *(.initcall2.init)
+ *(.initcall3.init)
+ *(.initcall4.init)
+ *(.initcall5.init)
+ *(.initcall6.init)
+ *(.initcall7.init)
+ }
+ __initcall_end = .;
+
+ __con_initcall_start = .;
+ .con_initcall.init : { *(.con_initcall.init) }
+ __con_initcall_end = .;
+
+ SECURITY_INIT
+
+ . = ALIGN(4);
+
+ __start___ftr_fixup = .;
+ __ftr_fixup : { *(__ftr_fixup) }
+ __stop___ftr_fixup = .;
+
+ . = ALIGN(32);
+ __per_cpu_start = .;
+ .data.percpu : { *(.data.percpu) }
+ __per_cpu_end = .;
+
+ . = ALIGN(4096);
+ __initramfs_start =.;
+ .init.ramfs : { *(.init.ramfs) }
+ __initramfs_end = .;
+
+ /* We need this dummy segment here */
+
+ . = ALIGN(4);
+ .dummy : { LONG(0) }
+
+ /* The vectors are relocated to the real position at startup time */
+
+ SECTION_VECTOR (_WindowVectors_text,
+ .WindowVectors.text,
+ XCHAL_WINDOW_VECTORS_VADDR, 4,
+ .dummy)
+ SECTION_VECTOR (_DebugInterruptVector_literal,
+ .DebugInterruptVector.literal,
+ XCHAL_INTLEVEL_VECTOR_VADDR(XCHAL_DEBUGLEVEL) - 4,
+ SIZEOF(.WindowVectors.text),
+ .WindowVectors.text)
+ SECTION_VECTOR (_DebugInterruptVector_text,
+ .DebugInterruptVector.text,
+ XCHAL_INTLEVEL_VECTOR_VADDR(XCHAL_DEBUGLEVEL),
+ 4,
+ .DebugInterruptVector.literal)
+ SECTION_VECTOR (_KernelExceptionVector_literal,
+ .KernelExceptionVector.literal,
+ XCHAL_KERNELEXC_VECTOR_VADDR - 4,
+ SIZEOF(.DebugInterruptVector.text),
+ .DebugInterruptVector.text)
+ SECTION_VECTOR (_KernelExceptionVector_text,
+ .KernelExceptionVector.text,
+ XCHAL_KERNELEXC_VECTOR_VADDR,
+ 4,
+ .KernelExceptionVector.literal)
+ SECTION_VECTOR (_UserExceptionVector_literal,
+ .UserExceptionVector.literal,
+ XCHAL_USEREXC_VECTOR_VADDR - 4,
+ SIZEOF(.KernelExceptionVector.text),
+ .KernelExceptionVector.text)
+ SECTION_VECTOR (_UserExceptionVector_text,
+ .UserExceptionVector.text,
+ XCHAL_USEREXC_VECTOR_VADDR,
+ 4,
+ .UserExceptionVector.literal)
+ SECTION_VECTOR (_DoubleExceptionVector_literal,
+ .DoubleExceptionVector.literal,
+ XCHAL_DOUBLEEXC_VECTOR_VADDR - 16,
+ SIZEOF(.UserExceptionVector.text),
+ .UserExceptionVector.text)
+ SECTION_VECTOR (_DoubleExceptionVector_text,
+ .DoubleExceptionVector.text,
+ XCHAL_DOUBLEEXC_VECTOR_VADDR,
+ 32,
+ .DoubleExceptionVector.literal)
+
+ . = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3;
+ . = ALIGN(1<<XCHAL_MMU_MIN_PTE_PAGE_SIZE);
+
+ __init_end = .;
+
+ . = ALIGN(8192);
+
+ /* BSS section */
+ _bss_start = .;
+ .sbss : { *(.sbss) *(.scommon) }
+ .bss : { *(COMMON) *(.bss) }
+ _bss_end = .;
+ _end = .;
+
+ /* only used by the boot loader */
+
+ . = ALIGN(0x10);
+ .bootstrap : { *(.bootstrap.literal .bootstrap.text .bootstrap.data) }
+
+ . = ALIGN(0x1000);
+ __initrd_start = .;
+ .initrd : { *(.initrd) }
+ __initrd_end = .;
+
+ .ResetVector.text XCHAL_RESET_VECTOR_VADDR :
+ {
+ *(.ResetVector.text)
+ }
+
+
+ /* Sections to be discarded */
+ /DISCARD/ :
+ {
+ *(.text.exit)
+ *(.text.exit.literal)
+ *(.data.exit)
+ *(.exitcall.exit)
+ }
+
+
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ .debug_info 0 : { *(.debug_info) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+
+ .xt.insn 0 :
+ {
+ *(.xt.insn)
+ *(.gnu.linkonce.x*)
+ }
+
+ .xt.lit 0 :
+ {
+ *(.xt.lit)
+ *(.gnu.linkonce.p*)
+ }
+}
diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c
new file mode 100644
index 00000000000..efae56a5147
--- /dev/null
+++ b/arch/xtensa/kernel/xtensa_ksyms.c
@@ -0,0 +1,123 @@
+/*
+ * arch/xtensa/kernel/xtensa_ksyms.c
+ *
+ * Export Xtensa-specific functions for loadable modules.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ *
+ * Joe Taylor <joe@tensilica.com>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <linux/in6.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+
+#include <asm/uaccess.h>
+#include <asm/checksum.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/semaphore.h>
+#ifdef CONFIG_BLK_DEV_FD
+#include <asm/floppy.h>
+#endif
+#ifdef CONFIG_NET
+#include <net/checksum.h>
+#endif /* CONFIG_NET */
+
+
+/*
+ * String functions
+ */
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(memchr);
+EXPORT_SYMBOL(strcat);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strpbrk);
+EXPORT_SYMBOL(strncat);
+EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strrchr);
+EXPORT_SYMBOL(strstr);
+
+EXPORT_SYMBOL(enable_irq);
+EXPORT_SYMBOL(disable_irq);
+EXPORT_SYMBOL(kernel_thread);
+
+/*
+ * gcc internal math functions
+ */
+extern long long __ashrdi3(long long, int);
+extern long long __ashldi3(long long, int);
+extern long long __lshrdi3(long long, int);
+extern int __divsi3(int, int);
+extern int __modsi3(int, int);
+extern long long __muldi3(long long, long long);
+extern int __mulsi3(int, int);
+extern unsigned int __udivsi3(unsigned int, unsigned int);
+extern unsigned int __umodsi3(unsigned int, unsigned int);
+extern unsigned long long __umoddi3(unsigned long long, unsigned long long);
+extern unsigned long long __udivdi3(unsigned long long, unsigned long long);
+
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__divsi3);
+EXPORT_SYMBOL(__modsi3);
+EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__mulsi3);
+EXPORT_SYMBOL(__udivsi3);
+EXPORT_SYMBOL(__umodsi3);
+EXPORT_SYMBOL(__udivdi3);
+EXPORT_SYMBOL(__umoddi3);
+
+/*
+ * Semaphore operations
+ */
+EXPORT_SYMBOL(__down);
+EXPORT_SYMBOL(__down_interruptible);
+EXPORT_SYMBOL(__down_trylock);
+EXPORT_SYMBOL(__up);
+
+#ifdef CONFIG_NET
+/*
+ * Networking support
+ */
+EXPORT_SYMBOL(csum_partial_copy_generic);
+#endif /* CONFIG_NET */
+
+/*
+ * Architecture-specific symbols
+ */
+EXPORT_SYMBOL(__xtensa_copy_user);
+
+/*
+ * Kernel hacking ...
+ */
+
+#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
+// FIXME EXPORT_SYMBOL(screen_info);
+#endif
+
+EXPORT_SYMBOL(get_wchan);
+
+EXPORT_SYMBOL(outsb);
+EXPORT_SYMBOL(outsw);
+EXPORT_SYMBOL(outsl);
+EXPORT_SYMBOL(insb);
+EXPORT_SYMBOL(insw);
+EXPORT_SYMBOL(insl);
diff --git a/arch/xtensa/lib/Makefile b/arch/xtensa/lib/Makefile
new file mode 100644
index 00000000000..ed935b58e8a
--- /dev/null
+++ b/arch/xtensa/lib/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for Xtensa-specific library files.
+#
+
+lib-y += memcopy.o memset.o checksum.o strcasecmp.o \
+ usercopy.o strncpy_user.o strnlen_user.o
+lib-$(CONFIG_PCI) += pci-auto.o
diff --git a/arch/xtensa/lib/checksum.S b/arch/xtensa/lib/checksum.S
new file mode 100644
index 00000000000..e2d64dfd530
--- /dev/null
+++ b/arch/xtensa/lib/checksum.S
@@ -0,0 +1,410 @@
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * IP/TCP/UDP checksumming routines
+ *
+ * Xtensa version: Copyright (C) 2001 Tensilica, Inc. by Kevin Chea
+ * Optimized by Joe Taylor
+ *
+ * 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 <asm/errno.h>
+#include <linux/linkage.h>
+#define _ASMLANGUAGE
+#include <xtensa/config/core.h>
+
+/*
+ * computes a partial checksum, e.g. for TCP/UDP fragments
+ */
+
+/*
+ * unsigned int csum_partial(const unsigned char *buf, int len,
+ * unsigned int sum);
+ * a2 = buf
+ * a3 = len
+ * a4 = sum
+ *
+ * This function assumes 2- or 4-byte alignment. Other alignments will fail!
+ */
+
+/* ONES_ADD converts twos-complement math to ones-complement. */
+#define ONES_ADD(sum, val) \
+ add sum, sum, val ; \
+ bgeu sum, val, 99f ; \
+ addi sum, sum, 1 ; \
+99: ;
+
+.text
+ENTRY(csum_partial)
+ /*
+ * Experiments with Ethernet and SLIP connections show that buf
+ * is aligned on either a 2-byte or 4-byte boundary.
+ */
+ entry sp, 32
+ extui a5, a2, 0, 2
+ bnez a5, 8f /* branch if 2-byte aligned */
+ /* Fall-through on common case, 4-byte alignment */
+1:
+ srli a5, a3, 5 /* 32-byte chunks */
+#if XCHAL_HAVE_LOOPS
+ loopgtz a5, 2f
+#else
+ beqz a5, 2f
+ slli a5, a5, 5
+ add a5, a5, a2 /* a5 = end of last 32-byte chunk */
+.Loop1:
+#endif
+ l32i a6, a2, 0
+ l32i a7, a2, 4
+ ONES_ADD(a4, a6)
+ ONES_ADD(a4, a7)
+ l32i a6, a2, 8
+ l32i a7, a2, 12
+ ONES_ADD(a4, a6)
+ ONES_ADD(a4, a7)
+ l32i a6, a2, 16
+ l32i a7, a2, 20
+ ONES_ADD(a4, a6)
+ ONES_ADD(a4, a7)
+ l32i a6, a2, 24
+ l32i a7, a2, 28
+ ONES_ADD(a4, a6)
+ ONES_ADD(a4, a7)
+ addi a2, a2, 4*8
+#if !XCHAL_HAVE_LOOPS
+ blt a2, a5, .Loop1
+#endif
+2:
+ extui a5, a3, 2, 3 /* remaining 4-byte chunks */
+#if XCHAL_HAVE_LOOPS
+ loopgtz a5, 3f
+#else
+ beqz a5, 3f
+ slli a5, a5, 2
+ add a5, a5, a2 /* a5 = end of last 4-byte chunk */
+.Loop2:
+#endif
+ l32i a6, a2, 0
+ ONES_ADD(a4, a6)
+ addi a2, a2, 4
+#if !XCHAL_HAVE_LOOPS
+ blt a2, a5, .Loop2
+#endif
+3:
+ _bbci.l a3, 1, 5f /* remaining 2-byte chunk */
+ l16ui a6, a2, 0
+ ONES_ADD(a4, a6)
+ addi a2, a2, 2
+5:
+ _bbci.l a3, 0, 7f /* remaining 1-byte chunk */
+6: l8ui a6, a2, 0
+#ifdef __XTENSA_EB__
+ slli a6, a6, 8 /* load byte into bits 8..15 */
+#endif
+ ONES_ADD(a4, a6)
+7:
+ mov a2, a4
+ retw
+
+ /* uncommon case, buf is 2-byte aligned */
+8:
+ beqz a3, 7b /* branch if len == 0 */
+ beqi a3, 1, 6b /* branch if len == 1 */
+
+ extui a5, a2, 0, 1
+ bnez a5, 8f /* branch if 1-byte aligned */
+
+ l16ui a6, a2, 0 /* common case, len >= 2 */
+ ONES_ADD(a4, a6)
+ addi a2, a2, 2 /* adjust buf */
+ addi a3, a3, -2 /* adjust len */
+ j 1b /* now buf is 4-byte aligned */
+
+ /* case: odd-byte aligned, len > 1
+ * This case is dog slow, so don't give us an odd address.
+ * (I don't think this ever happens, but just in case.)
+ */
+8:
+ srli a5, a3, 2 /* 4-byte chunks */
+#if XCHAL_HAVE_LOOPS
+ loopgtz a5, 2f
+#else
+ beqz a5, 2f
+ slli a5, a5, 2
+ add a5, a5, a2 /* a5 = end of last 4-byte chunk */
+.Loop3:
+#endif
+ l8ui a6, a2, 0 /* bits 24..31 */
+ l16ui a7, a2, 1 /* bits 8..23 */
+ l8ui a8, a2, 3 /* bits 0.. 8 */
+#ifdef __XTENSA_EB__
+ slli a6, a6, 24
+#else
+ slli a8, a8, 24
+#endif
+ slli a7, a7, 8
+ or a7, a7, a6
+ or a7, a7, a8
+ ONES_ADD(a4, a7)
+ addi a2, a2, 4
+#if !XCHAL_HAVE_LOOPS
+ blt a2, a5, .Loop3
+#endif
+2:
+ _bbci.l a3, 1, 3f /* remaining 2-byte chunk, still odd addr */
+ l8ui a6, a2, 0
+ l8ui a7, a2, 1
+#ifdef __XTENSA_EB__
+ slli a6, a6, 8
+#else
+ slli a7, a7, 8
+#endif
+ or a7, a7, a6
+ ONES_ADD(a4, a7)
+ addi a2, a2, 2
+3:
+ j 5b /* branch to handle the remaining byte */
+
+
+
+/*
+ * Copy from ds while checksumming, otherwise like csum_partial
+ *
+ * The macros SRC and DST specify the type of access for the instruction.
+ * thus we can call a custom exception handler for each access type.
+ */
+
+#define SRC(y...) \
+ 9999: y; \
+ .section __ex_table, "a"; \
+ .long 9999b, 6001f ; \
+ .previous
+
+#define DST(y...) \
+ 9999: y; \
+ .section __ex_table, "a"; \
+ .long 9999b, 6002f ; \
+ .previous
+
+/*
+unsigned int csum_partial_copy_generic (const char *src, char *dst, int len,
+ int sum, int *src_err_ptr, int *dst_err_ptr)
+ a2 = src
+ a3 = dst
+ a4 = len
+ a5 = sum
+ a6 = src_err_ptr
+ a7 = dst_err_ptr
+ a8 = temp
+ a9 = temp
+ a10 = temp
+ a11 = original len for exception handling
+ a12 = original dst for exception handling
+
+ This function is optimized for 4-byte aligned addresses. Other
+ alignments work, but not nearly as efficiently.
+ */
+
+ENTRY(csum_partial_copy_generic)
+ entry sp, 32
+ mov a12, a3
+ mov a11, a4
+ or a10, a2, a3
+
+ /* We optimize the following alignment tests for the 4-byte
+ aligned case. Two bbsi.l instructions might seem more optimal
+ (commented out below). However, both labels 5: and 3: are out
+ of the imm8 range, so the assembler relaxes them into
+ equivalent bbci.l, j combinations, which is actually
+ slower. */
+
+ extui a9, a10, 0, 2
+ beqz a9, 1f /* branch if both are 4-byte aligned */
+ bbsi.l a10, 0, 5f /* branch if one address is odd */
+ j 3f /* one address is 2-byte aligned */
+
+/* _bbsi.l a10, 0, 5f */ /* branch if odd address */
+/* _bbsi.l a10, 1, 3f */ /* branch if 2-byte-aligned address */
+
+1:
+ /* src and dst are both 4-byte aligned */
+ srli a10, a4, 5 /* 32-byte chunks */
+#if XCHAL_HAVE_LOOPS
+ loopgtz a10, 2f
+#else
+ beqz a10, 2f
+ slli a10, a10, 5
+ add a10, a10, a2 /* a10 = end of last 32-byte src chunk */
+.Loop5:
+#endif
+SRC( l32i a9, a2, 0 )
+SRC( l32i a8, a2, 4 )
+DST( s32i a9, a3, 0 )
+DST( s32i a8, a3, 4 )
+ ONES_ADD(a5, a9)
+ ONES_ADD(a5, a8)
+SRC( l32i a9, a2, 8 )
+SRC( l32i a8, a2, 12 )
+DST( s32i a9, a3, 8 )
+DST( s32i a8, a3, 12 )
+ ONES_ADD(a5, a9)
+ ONES_ADD(a5, a8)
+SRC( l32i a9, a2, 16 )
+SRC( l32i a8, a2, 20 )
+DST( s32i a9, a3, 16 )
+DST( s32i a8, a3, 20 )
+ ONES_ADD(a5, a9)
+ ONES_ADD(a5, a8)
+SRC( l32i a9, a2, 24 )
+SRC( l32i a8, a2, 28 )
+DST( s32i a9, a3, 24 )
+DST( s32i a8, a3, 28 )
+ ONES_ADD(a5, a9)
+ ONES_ADD(a5, a8)
+ addi a2, a2, 32
+ addi a3, a3, 32
+#if !XCHAL_HAVE_LOOPS
+ blt a2, a10, .Loop5
+#endif
+2:
+ extui a10, a4, 2, 3 /* remaining 4-byte chunks */
+ extui a4, a4, 0, 2 /* reset len for general-case, 2-byte chunks */
+#if XCHAL_HAVE_LOOPS
+ loopgtz a10, 3f
+#else
+ beqz a10, 3f
+ slli a10, a10, 2
+ add a10, a10, a2 /* a10 = end of last 4-byte src chunk */
+.Loop6:
+#endif
+SRC( l32i a9, a2, 0 )
+DST( s32i a9, a3, 0 )
+ ONES_ADD(a5, a9)
+ addi a2, a2, 4
+ addi a3, a3, 4
+#if !XCHAL_HAVE_LOOPS
+ blt a2, a10, .Loop6
+#endif
+3:
+ /*
+ Control comes to here in two cases: (1) It may fall through
+ to here from the 4-byte alignment case to process, at most,
+ one 2-byte chunk. (2) It branches to here from above if
+ either src or dst is 2-byte aligned, and we process all bytes
+ here, except for perhaps a trailing odd byte. It's
+ inefficient, so align your addresses to 4-byte boundaries.
+
+ a2 = src
+ a3 = dst
+ a4 = len
+ a5 = sum
+ */
+ srli a10, a4, 1 /* 2-byte chunks */
+#if XCHAL_HAVE_LOOPS
+ loopgtz a10, 4f
+#else
+ beqz a10, 4f
+ slli a10, a10, 1
+ add a10, a10, a2 /* a10 = end of last 2-byte src chunk */
+.Loop7:
+#endif
+SRC( l16ui a9, a2, 0 )
+DST( s16i a9, a3, 0 )
+ ONES_ADD(a5, a9)
+ addi a2, a2, 2
+ addi a3, a3, 2
+#if !XCHAL_HAVE_LOOPS
+ blt a2, a10, .Loop7
+#endif
+4:
+ /* This section processes a possible trailing odd byte. */
+ _bbci.l a4, 0, 8f /* 1-byte chunk */
+SRC( l8ui a9, a2, 0 )
+DST( s8i a9, a3, 0 )
+#ifdef __XTENSA_EB__
+ slli a9, a9, 8 /* shift byte to bits 8..15 */
+#endif
+ ONES_ADD(a5, a9)
+8:
+ mov a2, a5
+ retw
+
+5:
+ /* Control branch to here when either src or dst is odd. We
+ process all bytes using 8-bit accesses. Grossly inefficient,
+ so don't feed us an odd address. */
+
+ srli a10, a4, 1 /* handle in pairs for 16-bit csum */
+#if XCHAL_HAVE_LOOPS
+ loopgtz a10, 6f
+#else
+ beqz a10, 6f
+ slli a10, a10, 1
+ add a10, a10, a2 /* a10 = end of last odd-aligned, 2-byte src chunk */
+.Loop8:
+#endif
+SRC( l8ui a9, a2, 0 )
+SRC( l8ui a8, a2, 1 )
+DST( s8i a9, a3, 0 )
+DST( s8i a8, a3, 1 )
+#ifdef __XTENSA_EB__
+ slli a9, a9, 8 /* combine into a single 16-bit value */
+#else /* for checksum computation */
+ slli a8, a8, 8
+#endif
+ or a9, a9, a8
+ ONES_ADD(a5, a9)
+ addi a2, a2, 2
+ addi a3, a3, 2
+#if !XCHAL_HAVE_LOOPS
+ blt a2, a10, .Loop8
+#endif
+6:
+ j 4b /* process the possible trailing odd byte */
+
+
+# Exception handler:
+.section .fixup, "ax"
+/*
+ a6 = src_err_ptr
+ a7 = dst_err_ptr
+ a11 = original len for exception handling
+ a12 = original dst for exception handling
+*/
+
+6001:
+ _movi a2, -EFAULT
+ s32i a2, a6, 0 /* src_err_ptr */
+
+ # clear the complete destination - computing the rest
+ # is too much work
+ movi a2, 0
+#if XCHAL_HAVE_LOOPS
+ loopgtz a11, 2f
+#else
+ beqz a11, 2f
+ add a11, a11, a12 /* a11 = ending address */
+.Leloop:
+#endif
+ s8i a2, a12, 0
+ addi a12, a12, 1
+#if !XCHAL_HAVE_LOOPS
+ blt a12, a11, .Leloop
+#endif
+2:
+ retw
+
+6002:
+ movi a2, -EFAULT
+ s32i a2, a7, 0 /* dst_err_ptr */
+ movi a2, 0
+ retw
+
+.previous
+
diff --git a/arch/xtensa/lib/memcopy.S b/arch/xtensa/lib/memcopy.S
new file mode 100644
index 00000000000..e8f6d7eb722
--- /dev/null
+++ b/arch/xtensa/lib/memcopy.S
@@ -0,0 +1,315 @@
+/*
+ * arch/xtensa/lib/hal/memcopy.S -- Core HAL library functions
+ * xthal_memcpy and xthal_bcopy
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2002 - 2005 Tensilica Inc.
+ */
+
+#include <xtensa/coreasm.h>
+
+ .macro src_b r, w0, w1
+#ifdef __XTENSA_EB__
+ src \r, \w0, \w1
+#else
+ src \r, \w1, \w0
+#endif
+ .endm
+
+ .macro ssa8 r
+#ifdef __XTENSA_EB__
+ ssa8b \r
+#else
+ ssa8l \r
+#endif
+ .endm
+
+
+/*
+ * void *memcpy(void *dst, const void *src, size_t len);
+ * void *memmove(void *dst, const void *src, size_t len);
+ * void *bcopy(const void *src, void *dst, size_t len);
+ *
+ * This function is intended to do the same thing as the standard
+ * library function memcpy() (or bcopy()) for most cases.
+ * However, where the source and/or destination references
+ * an instruction RAM or ROM or a data RAM or ROM, that
+ * source and/or destination will always be accessed with
+ * 32-bit load and store instructions (as required for these
+ * types of devices).
+ *
+ * !!!!!!! XTFIXME:
+ * !!!!!!! Handling of IRAM/IROM has not yet
+ * !!!!!!! been implemented.
+ *
+ * The bcopy version is provided here to avoid the overhead
+ * of an extra call, for callers that require this convention.
+ *
+ * The (general case) algorithm is as follows:
+ * If destination is unaligned, align it by conditionally
+ * copying 1 and 2 bytes.
+ * If source is aligned,
+ * do 16 bytes with a loop, and then finish up with
+ * 8, 4, 2, and 1 byte copies conditional on the length;
+ * else (if source is unaligned),
+ * do the same, but use SRC to align the source data.
+ * This code tries to use fall-through branches for the common
+ * case of aligned source and destination and multiple
+ * of 4 (or 8) length.
+ *
+ * Register use:
+ * a0/ return address
+ * a1/ stack pointer
+ * a2/ return value
+ * a3/ src
+ * a4/ length
+ * a5/ dst
+ * a6/ tmp
+ * a7/ tmp
+ * a8/ tmp
+ * a9/ tmp
+ * a10/ tmp
+ * a11/ tmp
+ */
+
+ .text
+ .align 4
+ .global bcopy
+ .type bcopy,@function
+bcopy:
+ entry sp, 16 # minimal stack frame
+ # a2=src, a3=dst, a4=len
+ mov a5, a3 # copy dst so that a2 is return value
+ mov a3, a2
+ mov a2, a5
+ j .Lcommon # go to common code for memcpy+bcopy
+
+
+/*
+ * Byte by byte copy
+ */
+ .align 4
+ .byte 0 # 1 mod 4 alignment for LOOPNEZ
+ # (0 mod 4 alignment for LBEG)
+.Lbytecopy:
+#if XCHAL_HAVE_LOOPS
+ loopnez a4, .Lbytecopydone
+#else /* !XCHAL_HAVE_LOOPS */
+ beqz a4, .Lbytecopydone
+ add a7, a3, a4 # a7 = end address for source
+#endif /* !XCHAL_HAVE_LOOPS */
+.Lnextbyte:
+ l8ui a6, a3, 0
+ addi a3, a3, 1
+ s8i a6, a5, 0
+ addi a5, a5, 1
+#if !XCHAL_HAVE_LOOPS
+ blt a3, a7, .Lnextbyte
+#endif /* !XCHAL_HAVE_LOOPS */
+.Lbytecopydone:
+ retw
+
+/*
+ * Destination is unaligned
+ */
+
+ .align 4
+.Ldst1mod2: # dst is only byte aligned
+ _bltui a4, 7, .Lbytecopy # do short copies byte by byte
+
+ # copy 1 byte
+ l8ui a6, a3, 0
+ addi a3, a3, 1
+ addi a4, a4, -1
+ s8i a6, a5, 0
+ addi a5, a5, 1
+ _bbci.l a5, 1, .Ldstaligned # if dst is now aligned, then
+ # return to main algorithm
+.Ldst2mod4: # dst 16-bit aligned
+ # copy 2 bytes
+ _bltui a4, 6, .Lbytecopy # do short copies byte by byte
+ l8ui a6, a3, 0
+ l8ui a7, a3, 1
+ addi a3, a3, 2
+ addi a4, a4, -2
+ s8i a6, a5, 0
+ s8i a7, a5, 1
+ addi a5, a5, 2
+ j .Ldstaligned # dst is now aligned, return to main algorithm
+
+ .align 4
+ .global memcpy
+ .type memcpy,@function
+memcpy:
+ .global memmove
+ .type memmove,@function
+memmove:
+
+ entry sp, 16 # minimal stack frame
+ # a2/ dst, a3/ src, a4/ len
+ mov a5, a2 # copy dst so that a2 is return value
+.Lcommon:
+ _bbsi.l a2, 0, .Ldst1mod2 # if dst is 1 mod 2
+ _bbsi.l a2, 1, .Ldst2mod4 # if dst is 2 mod 4
+.Ldstaligned: # return here from .Ldst?mod? once dst is aligned
+ srli a7, a4, 4 # number of loop iterations with 16B
+ # per iteration
+ movi a8, 3 # if source is not aligned,
+ _bany a3, a8, .Lsrcunaligned # then use shifting copy
+ /*
+ * Destination and source are word-aligned, use word copy.
+ */
+ # copy 16 bytes per iteration for word-aligned dst and word-aligned src
+#if XCHAL_HAVE_LOOPS
+ loopnez a7, .Loop1done
+#else /* !XCHAL_HAVE_LOOPS */
+ beqz a7, .Loop1done
+ slli a8, a7, 4
+ add a8, a8, a3 # a8 = end of last 16B source chunk
+#endif /* !XCHAL_HAVE_LOOPS */
+.Loop1:
+ l32i a6, a3, 0
+ l32i a7, a3, 4
+ s32i a6, a5, 0
+ l32i a6, a3, 8
+ s32i a7, a5, 4
+ l32i a7, a3, 12
+ s32i a6, a5, 8
+ addi a3, a3, 16
+ s32i a7, a5, 12
+ addi a5, a5, 16
+#if !XCHAL_HAVE_LOOPS
+ blt a3, a8, .Loop1
+#endif /* !XCHAL_HAVE_LOOPS */
+.Loop1done:
+ bbci.l a4, 3, .L2
+ # copy 8 bytes
+ l32i a6, a3, 0
+ l32i a7, a3, 4
+ addi a3, a3, 8
+ s32i a6, a5, 0
+ s32i a7, a5, 4
+ addi a5, a5, 8
+.L2:
+ bbsi.l a4, 2, .L3
+ bbsi.l a4, 1, .L4
+ bbsi.l a4, 0, .L5
+ retw
+.L3:
+ # copy 4 bytes
+ l32i a6, a3, 0
+ addi a3, a3, 4
+ s32i a6, a5, 0
+ addi a5, a5, 4
+ bbsi.l a4, 1, .L4
+ bbsi.l a4, 0, .L5
+ retw
+.L4:
+ # copy 2 bytes
+ l16ui a6, a3, 0
+ addi a3, a3, 2
+ s16i a6, a5, 0
+ addi a5, a5, 2
+ bbsi.l a4, 0, .L5
+ retw
+.L5:
+ # copy 1 byte
+ l8ui a6, a3, 0
+ s8i a6, a5, 0
+ retw
+
+/*
+ * Destination is aligned, Source is unaligned
+ */
+
+ .align 4
+.Lsrcunaligned:
+ _beqz a4, .Ldone # avoid loading anything for zero-length copies
+ # copy 16 bytes per iteration for word-aligned dst and unaligned src
+ ssa8 a3 # set shift amount from byte offset
+#define SIM_CHECKS_ALIGNMENT 1 /* set to 1 when running on ISS (simulator) with the
+ lint or ferret client, or 0 to save a few cycles */
+#if XCHAL_UNALIGNED_LOAD_EXCEPTION || SIM_CHECKS_ALIGNMENT
+ and a11, a3, a8 # save unalignment offset for below
+ sub a3, a3, a11 # align a3
+#endif
+ l32i a6, a3, 0 # load first word
+#if XCHAL_HAVE_LOOPS
+ loopnez a7, .Loop2done
+#else /* !XCHAL_HAVE_LOOPS */
+ beqz a7, .Loop2done
+ slli a10, a7, 4
+ add a10, a10, a3 # a10 = end of last 16B source chunk
+#endif /* !XCHAL_HAVE_LOOPS */
+.Loop2:
+ l32i a7, a3, 4
+ l32i a8, a3, 8
+ src_b a6, a6, a7
+ s32i a6, a5, 0
+ l32i a9, a3, 12
+ src_b a7, a7, a8
+ s32i a7, a5, 4
+ l32i a6, a3, 16
+ src_b a8, a8, a9
+ s32i a8, a5, 8
+ addi a3, a3, 16
+ src_b a9, a9, a6
+ s32i a9, a5, 12
+ addi a5, a5, 16
+#if !XCHAL_HAVE_LOOPS
+ blt a3, a10, .Loop2
+#endif /* !XCHAL_HAVE_LOOPS */
+.Loop2done:
+ bbci.l a4, 3, .L12
+ # copy 8 bytes
+ l32i a7, a3, 4
+ l32i a8, a3, 8
+ src_b a6, a6, a7
+ s32i a6, a5, 0
+ addi a3, a3, 8
+ src_b a7, a7, a8
+ s32i a7, a5, 4
+ addi a5, a5, 8
+ mov a6, a8
+.L12:
+ bbci.l a4, 2, .L13
+ # copy 4 bytes
+ l32i a7, a3, 4
+ addi a3, a3, 4
+ src_b a6, a6, a7
+ s32i a6, a5, 0
+ addi a5, a5, 4
+ mov a6, a7
+.L13:
+#if XCHAL_UNALIGNED_LOAD_EXCEPTION || SIM_CHECKS_ALIGNMENT
+ add a3, a3, a11 # readjust a3 with correct misalignment
+#endif
+ bbsi.l a4, 1, .L14
+ bbsi.l a4, 0, .L15
+.Ldone: retw
+.L14:
+ # copy 2 bytes
+ l8ui a6, a3, 0
+ l8ui a7, a3, 1
+ addi a3, a3, 2
+ s8i a6, a5, 0
+ s8i a7, a5, 1
+ addi a5, a5, 2
+ bbsi.l a4, 0, .L15
+ retw
+.L15:
+ # copy 1 byte
+ l8ui a6, a3, 0
+ s8i a6, a5, 0
+ retw
+
+/*
+ * Local Variables:
+ * mode:fundamental
+ * comment-start: "# "
+ * comment-start-skip: "# *"
+ * End:
+ */
diff --git a/arch/xtensa/lib/memset.S b/arch/xtensa/lib/memset.S
new file mode 100644
index 00000000000..4de25134bc6
--- /dev/null
+++ b/arch/xtensa/lib/memset.S
@@ -0,0 +1,160 @@
+/*
+ * arch/xtensa/lib/memset.S
+ *
+ * ANSI C standard library function memset
+ * (Well, almost. .fixup code might return zero.)
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ *
+ * Copyright (C) 2002 Tensilica Inc.
+ */
+
+#include <xtensa/coreasm.h>
+
+/*
+ * void *memset(void *dst, int c, size_t length)
+ *
+ * The algorithm is as follows:
+ * Create a word with c in all byte positions
+ * If the destination is aligned,
+ * do 16B chucks with a loop, and then finish up with
+ * 8B, 4B, 2B, and 1B stores conditional on the length.
+ * If destination is unaligned, align it by conditionally
+ * setting 1B and 2B and then go to aligned case.
+ * This code tries to use fall-through branches for the common
+ * case of an aligned destination (except for the branches to
+ * the alignment labels).
+ */
+
+/* Load or store instructions that may cause exceptions use the EX macro. */
+
+#define EX(insn,reg1,reg2,offset,handler) \
+9: insn reg1, reg2, offset; \
+ .section __ex_table, "a"; \
+ .word 9b, handler; \
+ .previous
+
+
+.text
+.align 4
+.global memset
+.type memset,@function
+memset:
+ entry sp, 16 # minimal stack frame
+ # a2/ dst, a3/ c, a4/ length
+ extui a3, a3, 0, 8 # mask to just 8 bits
+ slli a7, a3, 8 # duplicate character in all bytes of word
+ or a3, a3, a7 # ...
+ slli a7, a3, 16 # ...
+ or a3, a3, a7 # ...
+ mov a5, a2 # copy dst so that a2 is return value
+ movi a6, 3 # for alignment tests
+ bany a2, a6, .Ldstunaligned # if dst is unaligned
+.L0: # return here from .Ldstunaligned when dst is aligned
+ srli a7, a4, 4 # number of loop iterations with 16B
+ # per iteration
+ bnez a4, .Laligned
+ retw
+
+/*
+ * Destination is word-aligned.
+ */
+ # set 16 bytes per iteration for word-aligned dst
+ .align 4 # 1 mod 4 alignment for LOOPNEZ
+ .byte 0 # (0 mod 4 alignment for LBEG)
+.Laligned:
+#if XCHAL_HAVE_LOOPS
+ loopnez a7, .Loop1done
+#else /* !XCHAL_HAVE_LOOPS */
+ beqz a7, .Loop1done
+ slli a6, a7, 4
+ add a6, a6, a5 # a6 = end of last 16B chunk
+#endif /* !XCHAL_HAVE_LOOPS */
+.Loop1:
+ EX(s32i, a3, a5, 0, memset_fixup)
+ EX(s32i, a3, a5, 4, memset_fixup)
+ EX(s32i, a3, a5, 8, memset_fixup)
+ EX(s32i, a3, a5, 12, memset_fixup)
+ addi a5, a5, 16
+#if !XCHAL_HAVE_LOOPS
+ blt a5, a6, .Loop1
+#endif /* !XCHAL_HAVE_LOOPS */
+.Loop1done:
+ bbci.l a4, 3, .L2
+ # set 8 bytes
+ EX(s32i, a3, a5, 0, memset_fixup)
+ EX(s32i, a3, a5, 4, memset_fixup)
+ addi a5, a5, 8
+.L2:
+ bbci.l a4, 2, .L3
+ # set 4 bytes
+ EX(s32i, a3, a5, 0, memset_fixup)
+ addi a5, a5, 4
+.L3:
+ bbci.l a4, 1, .L4
+ # set 2 bytes
+ EX(s16i, a3, a5, 0, memset_fixup)
+ addi a5, a5, 2
+.L4:
+ bbci.l a4, 0, .L5
+ # set 1 byte
+ EX(s8i, a3, a5, 0, memset_fixup)
+.L5:
+.Lret1:
+ retw
+
+/*
+ * Destination is unaligned
+ */
+
+.Ldstunaligned:
+ bltui a4, 8, .Lbyteset # do short copies byte by byte
+ bbci.l a5, 0, .L20 # branch if dst alignment half-aligned
+ # dst is only byte aligned
+ # set 1 byte
+ EX(s8i, a3, a5, 0, memset_fixup)
+ addi a5, a5, 1
+ addi a4, a4, -1
+ # now retest if dst aligned
+ bbci.l a5, 1, .L0 # if now aligned, return to main algorithm
+.L20:
+ # dst half-aligned
+ # set 2 bytes
+ EX(s16i, a3, a5, 0, memset_fixup)
+ addi a5, a5, 2
+ addi a4, a4, -2
+ j .L0 # dst is now aligned, return to main algorithm
+
+/*
+ * Byte by byte set
+ */
+ .align 4
+ .byte 0 # 1 mod 4 alignment for LOOPNEZ
+ # (0 mod 4 alignment for LBEG)
+.Lbyteset:
+#if XCHAL_HAVE_LOOPS
+ loopnez a4, .Lbytesetdone
+#else /* !XCHAL_HAVE_LOOPS */
+ beqz a4, .Lbytesetdone
+ add a6, a5, a4 # a6 = ending address
+#endif /* !XCHAL_HAVE_LOOPS */
+.Lbyteloop:
+ EX(s8i, a3, a5, 0, memset_fixup)
+ addi a5, a5, 1
+#if !XCHAL_HAVE_LOOPS
+ blt a5, a6, .Lbyteloop
+#endif /* !XCHAL_HAVE_LOOPS */
+.Lbytesetdone:
+ retw
+
+
+ .section .fixup, "ax"
+ .align 4
+
+/* We return zero if a failure occurred. */
+
+memset_fixup:
+ movi a2, 0
+ retw
diff --git a/arch/xtensa/lib/pci-auto.c b/arch/xtensa/lib/pci-auto.c
new file mode 100644
index 00000000000..90c790f6123
--- /dev/null
+++ b/arch/xtensa/lib/pci-auto.c
@@ -0,0 +1,352 @@
+/*
+ * arch/xtensa/kernel/pci-auto.c
+ *
+ * PCI autoconfiguration library
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ *
+ * Chris Zankel <zankel@tensilica.com, cez@zankel.net>
+ *
+ * Based on work from Matt Porter <mporter@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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/pci-bridge.h>
+
+
+/*
+ *
+ * Setting up a PCI
+ *
+ * pci_ctrl->first_busno = <first bus number (0)>
+ * pci_ctrl->last_busno = <last bus number (0xff)>
+ * pci_ctrl->ops = <PCI config operations>
+ * pci_ctrl->map_irq = <function to return the interrupt number for a device>
+ *
+ * pci_ctrl->io_space.start = <IO space start address (PCI view)>
+ * pci_ctrl->io_space.end = <IO space end address (PCI view)>
+ * pci_ctrl->io_space.base = <IO space offset: address 0 from CPU space>
+ * pci_ctrl->mem_space.start = <MEM space start address (PCI view)>
+ * pci_ctrl->mem_space.end = <MEM space end address (PCI view)>
+ * pci_ctrl->mem_space.base = <MEM space offset: address 0 from CPU space>
+ *
+ * pcibios_init_resource(&pci_ctrl->io_resource, <IO space start>,
+ * <IO space end>, IORESOURCE_IO, "PCI host bridge");
+ * pcibios_init_resource(&pci_ctrl->mem_resources[0], <MEM space start>,
+ * <MEM space end>, IORESOURCE_MEM, "PCI host bridge");
+ *
+ * pci_ctrl->last_busno = pciauto_bus_scan(pci_ctrl,pci_ctrl->first_busno);
+ *
+ * int __init pciauto_bus_scan(struct pci_controller *pci_ctrl, int current_bus)
+ *
+ */
+
+
+/* define DEBUG to print some debugging messages. */
+
+#undef DEBUG
+
+#ifdef DEBUG
+# define DBG(x...) printk(x)
+#else
+# define DBG(x...)
+#endif
+
+static int pciauto_upper_iospc;
+static int pciauto_upper_memspc;
+
+static struct pci_dev pciauto_dev;
+static struct pci_bus pciauto_bus;
+
+/*
+ * Helper functions
+ */
+
+/* Initialize the bars of a PCI device. */
+
+static void __init
+pciauto_setup_bars(struct pci_dev *dev, int bar_limit)
+{
+ int bar_size;
+ int bar, bar_nr;
+ int *upper_limit;
+ int found_mem64 = 0;
+
+ for (bar = PCI_BASE_ADDRESS_0, bar_nr = 0;
+ bar <= bar_limit;
+ bar+=4, bar_nr++)
+ {
+ /* Tickle the BAR and get the size */
+ pci_write_config_dword(dev, bar, 0xffffffff);
+ pci_read_config_dword(dev, bar, &bar_size);
+
+ /* If BAR is not implemented go to the next BAR */
+ if (!bar_size)
+ continue;
+
+ /* Check the BAR type and set our address mask */
+ if (bar_size & PCI_BASE_ADDRESS_SPACE_IO)
+ {
+ bar_size &= PCI_BASE_ADDRESS_IO_MASK;
+ upper_limit = &pciauto_upper_iospc;
+ DBG("PCI Autoconfig: BAR %d, I/O, ", bar_nr);
+ }
+ else
+ {
+ if ((bar_size & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
+ PCI_BASE_ADDRESS_MEM_TYPE_64)
+ found_mem64 = 1;
+
+ bar_size &= PCI_BASE_ADDRESS_MEM_MASK;
+ upper_limit = &pciauto_upper_memspc;
+ DBG("PCI Autoconfig: BAR %d, Mem, ", bar_nr);
+ }
+
+ /* Allocate a base address (bar_size is negative!) */
+ *upper_limit = (*upper_limit + bar_size) & bar_size;
+
+ /* Write it out and update our limit */
+ pci_write_config_dword(dev, bar, *upper_limit);
+
+ /*
+ * If we are a 64-bit decoder then increment to the
+ * upper 32 bits of the bar and force it to locate
+ * in the lower 4GB of memory.
+ */
+
+ if (found_mem64)
+ pci_write_config_dword(dev, (bar+=4), 0x00000000);
+
+ DBG("size=0x%x, address=0x%x\n", ~bar_size + 1, *upper_limit);
+ }
+}
+
+/* Initialize the interrupt number. */
+
+static void __init
+pciauto_setup_irq(struct pci_controller* pci_ctrl,struct pci_dev *dev,int devfn)
+{
+ u8 pin;
+ int irq = 0;
+
+ pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+
+ /* Fix illegal pin numbers. */
+
+ if (pin == 0 || pin > 4)
+ pin = 1;
+
+ if (pci_ctrl->map_irq)
+ irq = pci_ctrl->map_irq(dev, PCI_SLOT(devfn), pin);
+
+ if (irq == -1)
+ irq = 0;
+
+ DBG("PCI Autoconfig: Interrupt %d, pin %d\n", irq, pin);
+
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+}
+
+
+static void __init
+pciauto_prescan_setup_bridge(struct pci_dev *dev, int current_bus,
+ int sub_bus, int *iosave, int *memsave)
+{
+ /* Configure bus number registers */
+ pci_write_config_byte(dev, PCI_PRIMARY_BUS, current_bus);
+ pci_write_config_byte(dev, PCI_SECONDARY_BUS, sub_bus + 1);
+ pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, 0xff);
+
+ /* Round memory allocator to 1MB boundary */
+ pciauto_upper_memspc &= ~(0x100000 - 1);
+ *memsave = pciauto_upper_memspc;
+
+ /* Round I/O allocator to 4KB boundary */
+ pciauto_upper_iospc &= ~(0x1000 - 1);
+ *iosave = pciauto_upper_iospc;
+
+ /* Set up memory and I/O filter limits, assume 32-bit I/O space */
+ pci_write_config_word(dev, PCI_MEMORY_LIMIT,
+ ((pciauto_upper_memspc - 1) & 0xfff00000) >> 16);
+ pci_write_config_byte(dev, PCI_IO_LIMIT,
+ ((pciauto_upper_iospc - 1) & 0x0000f000) >> 8);
+ pci_write_config_word(dev, PCI_IO_LIMIT_UPPER16,
+ ((pciauto_upper_iospc - 1) & 0xffff0000) >> 16);
+}
+
+static void __init
+pciauto_postscan_setup_bridge(struct pci_dev *dev, int current_bus, int sub_bus,
+ int *iosave, int *memsave)
+{
+ int cmdstat;
+
+ /* Configure bus number registers */
+ pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, sub_bus);
+
+ /*
+ * Round memory allocator to 1MB boundary.
+ * If no space used, allocate minimum.
+ */
+ pciauto_upper_memspc &= ~(0x100000 - 1);
+ if (*memsave == pciauto_upper_memspc)
+ pciauto_upper_memspc -= 0x00100000;
+
+ pci_write_config_word(dev, PCI_MEMORY_BASE, pciauto_upper_memspc >> 16);
+
+ /* Allocate 1MB for pre-fretch */
+ pci_write_config_word(dev, PCI_PREF_MEMORY_LIMIT,
+ ((pciauto_upper_memspc - 1) & 0xfff00000) >> 16);
+
+ pciauto_upper_memspc -= 0x100000;
+
+ pci_write_config_word(dev, PCI_PREF_MEMORY_BASE,
+ pciauto_upper_memspc >> 16);
+
+ /* Round I/O allocator to 4KB boundary */
+ pciauto_upper_iospc &= ~(0x1000 - 1);
+ if (*iosave == pciauto_upper_iospc)
+ pciauto_upper_iospc -= 0x1000;
+
+ pci_write_config_byte(dev, PCI_IO_BASE,
+ (pciauto_upper_iospc & 0x0000f000) >> 8);
+ pci_write_config_word(dev, PCI_IO_BASE_UPPER16,
+ pciauto_upper_iospc >> 16);
+
+ /* Enable memory and I/O accesses, enable bus master */
+ pci_read_config_dword(dev, PCI_COMMAND, &cmdstat);
+ pci_write_config_dword(dev, PCI_COMMAND,
+ cmdstat |
+ PCI_COMMAND_IO |
+ PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER);
+}
+
+/*
+ * Scan the current PCI bus.
+ */
+
+
+int __init pciauto_bus_scan(struct pci_controller *pci_ctrl, int current_bus)
+{
+ int sub_bus, pci_devfn, pci_class, cmdstat, found_multi=0;
+ unsigned short vid;
+ unsigned char header_type;
+ struct pci_dev *dev = &pciauto_dev;
+
+ pciauto_dev.bus = &pciauto_bus;
+ pciauto_dev.sysdata = pci_ctrl;
+ pciauto_bus.ops = pci_ctrl->ops;
+
+ /*
+ * Fetch our I/O and memory space upper boundaries used
+ * to allocated base addresses on this pci_controller.
+ */
+
+ if (current_bus == pci_ctrl->first_busno)
+ {
+ pciauto_upper_iospc = pci_ctrl->io_resource.end + 1;
+ pciauto_upper_memspc = pci_ctrl->mem_resources[0].end + 1;
+ }
+
+ sub_bus = current_bus;
+
+ for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++)
+ {
+ /* Skip our host bridge */
+ if ((current_bus == pci_ctrl->first_busno) && (pci_devfn == 0))
+ continue;
+
+ if (PCI_FUNC(pci_devfn) && !found_multi)
+ continue;
+
+ pciauto_bus.number = current_bus;
+ pciauto_dev.devfn = pci_devfn;
+
+ /* If config space read fails from this device, move on */
+ if (pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type))
+ continue;
+
+ if (!PCI_FUNC(pci_devfn))
+ found_multi = header_type & 0x80;
+ pci_read_config_word(dev, PCI_VENDOR_ID, &vid);
+
+ if (vid == 0xffff || vid == 0x0000) {
+ found_multi = 0;
+ continue;
+ }
+
+ pci_read_config_dword(dev, PCI_CLASS_REVISION, &pci_class);
+
+ if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) {
+
+ int iosave, memsave;
+
+ DBG("PCI Autoconfig: Found P2P bridge, device %d\n",
+ PCI_SLOT(pci_devfn));
+
+ /* Allocate PCI I/O and/or memory space */
+ pciauto_setup_bars(dev, PCI_BASE_ADDRESS_1);
+
+ pciauto_prescan_setup_bridge(dev, current_bus, sub_bus,
+ &iosave, &memsave);
+ sub_bus = pciauto_bus_scan(pci_ctrl, sub_bus+1);
+ pciauto_postscan_setup_bridge(dev, current_bus, sub_bus,
+ &iosave, &memsave);
+ pciauto_bus.number = current_bus;
+
+ continue;
+
+ }
+
+
+#if 0
+ /* Skip legacy mode IDE controller */
+
+ if ((pci_class >> 16) == PCI_CLASS_STORAGE_IDE) {
+
+ unsigned char prg_iface;
+ pci_read_config_byte(dev, PCI_CLASS_PROG, &prg_iface);
+
+ if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) {
+ DBG("PCI Autoconfig: Skipping legacy mode "
+ "IDE controller\n");
+ continue;
+ }
+ }
+#endif
+
+ /*
+ * Found a peripheral, enable some standard
+ * settings
+ */
+
+ pci_read_config_dword(dev, PCI_COMMAND, &cmdstat);
+ pci_write_config_dword(dev, PCI_COMMAND,
+ cmdstat |
+ PCI_COMMAND_IO |
+ PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER);
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80);
+
+ /* Allocate PCI I/O and/or memory space */
+ DBG("PCI Autoconfig: Found Bus %d, Device %d, Function %d\n",
+ current_bus, PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn) );
+
+ pciauto_setup_bars(dev, PCI_BASE_ADDRESS_5);
+ pciauto_setup_irq(pci_ctrl, dev, pci_devfn);
+ }
+ return sub_bus;
+}
+
+
+
+
+
diff --git a/arch/xtensa/lib/strcasecmp.c b/arch/xtensa/lib/strcasecmp.c
new file mode 100644
index 00000000000..165b2d6effa
--- /dev/null
+++ b/arch/xtensa/lib/strcasecmp.c
@@ -0,0 +1,32 @@
+/*
+ * linux/arch/xtensa/lib/strcasecmp.c
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ *
+ * Copyright (C) 2002 Tensilica Inc.
+ */
+
+#include <linux/string.h>
+
+
+/* We handle nothing here except the C locale. Since this is used in
+ only one place, on strings known to contain only 7 bit ASCII, this
+ is ok. */
+
+int strcasecmp(const char *a, const char *b)
+{
+ int ca, cb;
+
+ do {
+ ca = *a++ & 0xff;
+ cb = *b++ & 0xff;
+ if (ca >= 'A' && ca <= 'Z')
+ ca += 'a' - 'A';
+ if (cb >= 'A' && cb <= 'Z')
+ cb += 'a' - 'A';
+ } while (ca == cb && ca != '\0');
+
+ return ca - cb;
+}
diff --git a/arch/xtensa/lib/strncpy_user.S b/arch/xtensa/lib/strncpy_user.S
new file mode 100644
index 00000000000..71d55df4389
--- /dev/null
+++ b/arch/xtensa/lib/strncpy_user.S
@@ -0,0 +1,224 @@
+/*
+ * arch/xtensa/lib/strncpy_user.S
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ *
+ * Returns: -EFAULT if exception before terminator, N if the entire
+ * buffer filled, else strlen.
+ *
+ * Copyright (C) 2002 Tensilica Inc.
+ */
+
+#include <xtensa/coreasm.h>
+#include <linux/errno.h>
+
+/* Load or store instructions that may cause exceptions use the EX macro. */
+
+#define EX(insn,reg1,reg2,offset,handler) \
+9: insn reg1, reg2, offset; \
+ .section __ex_table, "a"; \
+ .word 9b, handler; \
+ .previous
+
+/*
+ * char *__strncpy_user(char *dst, const char *src, size_t len)
+ */
+.text
+.begin literal
+.align 4
+.Lmask0:
+ .byte 0xff, 0x00, 0x00, 0x00
+.Lmask1:
+ .byte 0x00, 0xff, 0x00, 0x00
+.Lmask2:
+ .byte 0x00, 0x00, 0xff, 0x00
+.Lmask3:
+ .byte 0x00, 0x00, 0x00, 0xff
+.end literal
+
+# Register use
+# a0/ return address
+# a1/ stack pointer
+# a2/ return value
+# a3/ src
+# a4/ len
+# a5/ mask0
+# a6/ mask1
+# a7/ mask2
+# a8/ mask3
+# a9/ tmp
+# a10/ tmp
+# a11/ dst
+# a12/ tmp
+
+.align 4
+.global __strncpy_user
+.type __strncpy_user,@function
+__strncpy_user:
+ entry sp, 16 # minimal stack frame
+ # a2/ dst, a3/ src, a4/ len
+ mov a11, a2 # leave dst in return value register
+ beqz a4, .Lret # if len is zero
+ l32r a5, .Lmask0 # mask for byte 0
+ l32r a6, .Lmask1 # mask for byte 1
+ l32r a7, .Lmask2 # mask for byte 2
+ l32r a8, .Lmask3 # mask for byte 3
+ bbsi.l a3, 0, .Lsrc1mod2 # if only 8-bit aligned
+ bbsi.l a3, 1, .Lsrc2mod4 # if only 16-bit aligned
+.Lsrcaligned: # return here when src is word-aligned
+ srli a12, a4, 2 # number of loop iterations with 4B per loop
+ movi a9, 3
+ bnone a11, a9, .Laligned
+ j .Ldstunaligned
+
+.Lsrc1mod2: # src address is odd
+ EX(l8ui, a9, a3, 0, fixup_l) # get byte 0
+ addi a3, a3, 1 # advance src pointer
+ EX(s8i, a9, a11, 0, fixup_s) # store byte 0
+ beqz a9, .Lret # if byte 0 is zero
+ addi a11, a11, 1 # advance dst pointer
+ addi a4, a4, -1 # decrement len
+ beqz a4, .Lret # if len is zero
+ bbci.l a3, 1, .Lsrcaligned # if src is now word-aligned
+
+.Lsrc2mod4: # src address is 2 mod 4
+ EX(l8ui, a9, a3, 0, fixup_l) # get byte 0
+ /* 1-cycle interlock */
+ EX(s8i, a9, a11, 0, fixup_s) # store byte 0
+ beqz a9, .Lret # if byte 0 is zero
+ addi a11, a11, 1 # advance dst pointer
+ addi a4, a4, -1 # decrement len
+ beqz a4, .Lret # if len is zero
+ EX(l8ui, a9, a3, 1, fixup_l) # get byte 0
+ addi a3, a3, 2 # advance src pointer
+ EX(s8i, a9, a11, 0, fixup_s) # store byte 0
+ beqz a9, .Lret # if byte 0 is zero
+ addi a11, a11, 1 # advance dst pointer
+ addi a4, a4, -1 # decrement len
+ bnez a4, .Lsrcaligned # if len is nonzero
+.Lret:
+ sub a2, a11, a2 # compute strlen
+ retw
+
+/*
+ * dst is word-aligned, src is word-aligned
+ */
+ .align 4 # 1 mod 4 alignment for LOOPNEZ
+ .byte 0 # (0 mod 4 alignment for LBEG)
+.Laligned:
+#if XCHAL_HAVE_LOOPS
+ loopnez a12, .Loop1done
+#else
+ beqz a12, .Loop1done
+ slli a12, a12, 2
+ add a12, a12, a11 # a12 = end of last 4B chunck
+#endif
+.Loop1:
+ EX(l32i, a9, a3, 0, fixup_l) # get word from src
+ addi a3, a3, 4 # advance src pointer
+ bnone a9, a5, .Lz0 # if byte 0 is zero
+ bnone a9, a6, .Lz1 # if byte 1 is zero
+ bnone a9, a7, .Lz2 # if byte 2 is zero
+ EX(s32i, a9, a11, 0, fixup_s) # store word to dst
+ bnone a9, a8, .Lz3 # if byte 3 is zero
+ addi a11, a11, 4 # advance dst pointer
+#if !XCHAL_HAVE_LOOPS
+ blt a11, a12, .Loop1
+#endif
+
+.Loop1done:
+ bbci.l a4, 1, .L100
+ # copy 2 bytes
+ EX(l16ui, a9, a3, 0, fixup_l)
+ addi a3, a3, 2 # advance src pointer
+#ifdef __XTENSA_EB__
+ bnone a9, a7, .Lz0 # if byte 2 is zero
+ bnone a9, a8, .Lz1 # if byte 3 is zero
+#else
+ bnone a9, a5, .Lz0 # if byte 0 is zero
+ bnone a9, a6, .Lz1 # if byte 1 is zero
+#endif
+ EX(s16i, a9, a11, 0, fixup_s)
+ addi a11, a11, 2 # advance dst pointer
+.L100:
+ bbci.l a4, 0, .Lret
+ EX(l8ui, a9, a3, 0, fixup_l)
+ /* slot */
+ EX(s8i, a9, a11, 0, fixup_s)
+ beqz a9, .Lret # if byte is zero
+ addi a11, a11, 1-3 # advance dst ptr 1, but also cancel
+ # the effect of adding 3 in .Lz3 code
+ /* fall thru to .Lz3 and "retw" */
+
+.Lz3: # byte 3 is zero
+ addi a11, a11, 3 # advance dst pointer
+ sub a2, a11, a2 # compute strlen
+ retw
+.Lz0: # byte 0 is zero
+#ifdef __XTENSA_EB__
+ movi a9, 0
+#endif /* __XTENSA_EB__ */
+ EX(s8i, a9, a11, 0, fixup_s)
+ sub a2, a11, a2 # compute strlen
+ retw
+.Lz1: # byte 1 is zero
+#ifdef __XTENSA_EB__
+ extui a9, a9, 16, 16
+#endif /* __XTENSA_EB__ */
+ EX(s16i, a9, a11, 0, fixup_s)
+ addi a11, a11, 1 # advance dst pointer
+ sub a2, a11, a2 # compute strlen
+ retw
+.Lz2: # byte 2 is zero
+#ifdef __XTENSA_EB__
+ extui a9, a9, 16, 16
+#endif /* __XTENSA_EB__ */
+ EX(s16i, a9, a11, 0, fixup_s)
+ movi a9, 0
+ EX(s8i, a9, a11, 2, fixup_s)
+ addi a11, a11, 2 # advance dst pointer
+ sub a2, a11, a2 # compute strlen
+ retw
+
+ .align 4 # 1 mod 4 alignment for LOOPNEZ
+ .byte 0 # (0 mod 4 alignment for LBEG)
+.Ldstunaligned:
+/*
+ * for now just use byte copy loop
+ */
+#if XCHAL_HAVE_LOOPS
+ loopnez a4, .Lunalignedend
+#else
+ beqz a4, .Lunalignedend
+ add a12, a11, a4 # a12 = ending address
+#endif /* XCHAL_HAVE_LOOPS */
+.Lnextbyte:
+ EX(l8ui, a9, a3, 0, fixup_l)
+ addi a3, a3, 1
+ EX(s8i, a9, a11, 0, fixup_s)
+ beqz a9, .Lunalignedend
+ addi a11, a11, 1
+#if !XCHAL_HAVE_LOOPS
+ blt a11, a12, .Lnextbyte
+#endif
+
+.Lunalignedend:
+ sub a2, a11, a2 # compute strlen
+ retw
+
+
+ .section .fixup, "ax"
+ .align 4
+
+ /* For now, just return -EFAULT. Future implementations might
+ * like to clear remaining kernel space, like the fixup
+ * implementation in memset(). Thus, we differentiate between
+ * load/store fixups. */
+
+fixup_s:
+fixup_l:
+ movi a2, -EFAULT
+ retw
+
diff --git a/arch/xtensa/lib/strnlen_user.S b/arch/xtensa/lib/strnlen_user.S
new file mode 100644
index 00000000000..cdff4d670f3
--- /dev/null
+++ b/arch/xtensa/lib/strnlen_user.S
@@ -0,0 +1,147 @@
+/*
+ * arch/xtensa/lib/strnlen_user.S
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ *
+ * Returns strnlen, including trailing zero terminator.
+ * Zero indicates error.
+ *
+ * Copyright (C) 2002 Tensilica Inc.
+ */
+
+#include <xtensa/coreasm.h>
+
+/* Load or store instructions that may cause exceptions use the EX macro. */
+
+#define EX(insn,reg1,reg2,offset,handler) \
+9: insn reg1, reg2, offset; \
+ .section __ex_table, "a"; \
+ .word 9b, handler; \
+ .previous
+
+/*
+ * size_t __strnlen_user(const char *s, size_t len)
+ */
+.text
+.begin literal
+.align 4
+.Lmask0:
+ .byte 0xff, 0x00, 0x00, 0x00
+.Lmask1:
+ .byte 0x00, 0xff, 0x00, 0x00
+.Lmask2:
+ .byte 0x00, 0x00, 0xff, 0x00
+.Lmask3:
+ .byte 0x00, 0x00, 0x00, 0xff
+.end literal
+
+# Register use:
+# a2/ src
+# a3/ len
+# a4/ tmp
+# a5/ mask0
+# a6/ mask1
+# a7/ mask2
+# a8/ mask3
+# a9/ tmp
+# a10/ tmp
+
+.align 4
+.global __strnlen_user
+.type __strnlen_user,@function
+__strnlen_user:
+ entry sp, 16 # minimal stack frame
+ # a2/ s, a3/ len
+ addi a4, a2, -4 # because we overincrement at the end;
+ # we compensate with load offsets of 4
+ l32r a5, .Lmask0 # mask for byte 0
+ l32r a6, .Lmask1 # mask for byte 1
+ l32r a7, .Lmask2 # mask for byte 2
+ l32r a8, .Lmask3 # mask for byte 3
+ bbsi.l a2, 0, .L1mod2 # if only 8-bit aligned
+ bbsi.l a2, 1, .L2mod4 # if only 16-bit aligned
+
+/*
+ * String is word-aligned.
+ */
+.Laligned:
+ srli a10, a3, 2 # number of loop iterations with 4B per loop
+#if XCHAL_HAVE_LOOPS
+ loopnez a10, .Ldone
+#else
+ beqz a10, .Ldone
+ slli a10, a10, 2
+ add a10, a10, a4 # a10 = end of last 4B chunk
+#endif /* XCHAL_HAVE_LOOPS */
+.Loop:
+ EX(l32i, a9, a4, 4, lenfixup) # get next word of string
+ addi a4, a4, 4 # advance string pointer
+ bnone a9, a5, .Lz0 # if byte 0 is zero
+ bnone a9, a6, .Lz1 # if byte 1 is zero
+ bnone a9, a7, .Lz2 # if byte 2 is zero
+ bnone a9, a8, .Lz3 # if byte 3 is zero
+#if !XCHAL_HAVE_LOOPS
+ blt a4, a10, .Loop
+#endif
+
+.Ldone:
+ EX(l32i, a9, a4, 4, lenfixup) # load 4 bytes for remaining checks
+
+ bbci.l a3, 1, .L100
+ # check two more bytes (bytes 0, 1 of word)
+ addi a4, a4, 2 # advance string pointer
+ bnone a9, a5, .Lz0 # if byte 0 is zero
+ bnone a9, a6, .Lz1 # if byte 1 is zero
+.L100:
+ bbci.l a3, 0, .L101
+ # check one more byte (byte 2 of word)
+ # Actually, we don't need to check. Zero or nonzero, we'll add one.
+ # Do not add an extra one for the NULL terminator since we have
+ # exhausted the original len parameter.
+ addi a4, a4, 1 # advance string pointer
+.L101:
+ sub a2, a4, a2 # compute length
+ retw
+
+# NOTE that in several places below, we point to the byte just after
+# the zero byte in order to include the NULL terminator in the count.
+
+.Lz3: # byte 3 is zero
+ addi a4, a4, 3 # point to zero byte
+.Lz0: # byte 0 is zero
+ addi a4, a4, 1 # point just beyond zero byte
+ sub a2, a4, a2 # subtract to get length
+ retw
+.Lz1: # byte 1 is zero
+ addi a4, a4, 1+1 # point just beyond zero byte
+ sub a2, a4, a2 # subtract to get length
+ retw
+.Lz2: # byte 2 is zero
+ addi a4, a4, 2+1 # point just beyond zero byte
+ sub a2, a4, a2 # subtract to get length
+ retw
+
+.L1mod2: # address is odd
+ EX(l8ui, a9, a4, 4, lenfixup) # get byte 0
+ addi a4, a4, 1 # advance string pointer
+ beqz a9, .Lz3 # if byte 0 is zero
+ bbci.l a4, 1, .Laligned # if string pointer is now word-aligned
+
+.L2mod4: # address is 2 mod 4
+ addi a4, a4, 2 # advance ptr for aligned access
+ EX(l32i, a9, a4, 0, lenfixup) # get word with first two bytes of string
+ bnone a9, a7, .Lz2 # if byte 2 (of word, not string) is zero
+ bany a9, a8, .Laligned # if byte 3 (of word, not string) is nonzero
+ # byte 3 is zero
+ addi a4, a4, 3+1 # point just beyond zero byte
+ sub a2, a4, a2 # subtract to get length
+ retw
+
+ .section .fixup, "ax"
+ .align 4
+lenfixup:
+ movi a2, 0
+ retw
+
diff --git a/arch/xtensa/lib/usercopy.S b/arch/xtensa/lib/usercopy.S
new file mode 100644
index 00000000000..265db2693cb
--- /dev/null
+++ b/arch/xtensa/lib/usercopy.S
@@ -0,0 +1,321 @@
+/*
+ * arch/xtensa/lib/usercopy.S
+ *
+ * Copy to/from user space (derived from arch/xtensa/lib/hal/memcopy.S)
+ *
+ * DO NOT COMBINE this function with <arch/xtensa/lib/hal/memcopy.S>.
+ * It needs to remain separate and distinct. The hal files are part
+ * of the the Xtensa link-time HAL, and those files may differ per
+ * processor configuration. Patching the kernel for another
+ * processor configuration includes replacing the hal files, and we
+ * could loose the special functionality for accessing user-space
+ * memory during such a patch. We sacrifice a little code space here
+ * in favor to simplify code maintenance.
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ *
+ * Copyright (C) 2002 Tensilica Inc.
+ */
+
+
+/*
+ * size_t __xtensa_copy_user (void *dst, const void *src, size_t len);
+ *
+ * The returned value is the number of bytes not copied. Implies zero
+ * is success.
+ *
+ * The general case algorithm is as follows:
+ * If the destination and source are both aligned,
+ * do 16B chunks with a loop, and then finish up with
+ * 8B, 4B, 2B, and 1B copies conditional on the length.
+ * If destination is aligned and source unaligned,
+ * do the same, but use SRC to align the source data.
+ * If destination is unaligned, align it by conditionally
+ * copying 1B and 2B and then retest.
+ * This code tries to use fall-through braches for the common
+ * case of aligned destinations (except for the branches to
+ * the alignment label).
+ *
+ * Register use:
+ * a0/ return address
+ * a1/ stack pointer
+ * a2/ return value
+ * a3/ src
+ * a4/ length
+ * a5/ dst
+ * a6/ tmp
+ * a7/ tmp
+ * a8/ tmp
+ * a9/ tmp
+ * a10/ tmp
+ * a11/ original length
+ */
+
+#include <xtensa/coreasm.h>
+
+#ifdef __XTENSA_EB__
+#define ALIGN(R, W0, W1) src R, W0, W1
+#define SSA8(R) ssa8b R
+#else
+#define ALIGN(R, W0, W1) src R, W1, W0
+#define SSA8(R) ssa8l R
+#endif
+
+/* Load or store instructions that may cause exceptions use the EX macro. */
+
+#define EX(insn,reg1,reg2,offset,handler) \
+9: insn reg1, reg2, offset; \
+ .section __ex_table, "a"; \
+ .word 9b, handler; \
+ .previous
+
+
+ .text
+ .align 4
+ .global __xtensa_copy_user
+ .type __xtensa_copy_user,@function
+__xtensa_copy_user:
+ entry sp, 16 # minimal stack frame
+ # a2/ dst, a3/ src, a4/ len
+ mov a5, a2 # copy dst so that a2 is return value
+ mov a11, a4 # preserve original len for error case
+.Lcommon:
+ bbsi.l a2, 0, .Ldst1mod2 # if dst is 1 mod 2
+ bbsi.l a2, 1, .Ldst2mod4 # if dst is 2 mod 4
+.Ldstaligned: # return here from .Ldstunaligned when dst is aligned
+ srli a7, a4, 4 # number of loop iterations with 16B
+ # per iteration
+ movi a8, 3 # if source is also aligned,
+ bnone a3, a8, .Laligned # then use word copy
+ SSA8( a3) # set shift amount from byte offset
+ bnez a4, .Lsrcunaligned
+ movi a2, 0 # return success for len==0
+ retw
+
+/*
+ * Destination is unaligned
+ */
+
+.Ldst1mod2: # dst is only byte aligned
+ bltui a4, 7, .Lbytecopy # do short copies byte by byte
+
+ # copy 1 byte
+ EX(l8ui, a6, a3, 0, l_fixup)
+ addi a3, a3, 1
+ EX(s8i, a6, a5, 0, s_fixup)
+ addi a5, a5, 1
+ addi a4, a4, -1
+ bbci.l a5, 1, .Ldstaligned # if dst is now aligned, then
+ # return to main algorithm
+.Ldst2mod4: # dst 16-bit aligned
+ # copy 2 bytes
+ bltui a4, 6, .Lbytecopy # do short copies byte by byte
+ EX(l8ui, a6, a3, 0, l_fixup)
+ EX(l8ui, a7, a3, 1, l_fixup)
+ addi a3, a3, 2
+ EX(s8i, a6, a5, 0, s_fixup)
+ EX(s8i, a7, a5, 1, s_fixup)
+ addi a5, a5, 2
+ addi a4, a4, -2
+ j .Ldstaligned # dst is now aligned, return to main algorithm
+
+/*
+ * Byte by byte copy
+ */
+ .align 4
+ .byte 0 # 1 mod 4 alignment for LOOPNEZ
+ # (0 mod 4 alignment for LBEG)
+.Lbytecopy:
+#if XCHAL_HAVE_LOOPS
+ loopnez a4, .Lbytecopydone
+#else /* !XCHAL_HAVE_LOOPS */
+ beqz a4, .Lbytecopydone
+ add a7, a3, a4 # a7 = end address for source
+#endif /* !XCHAL_HAVE_LOOPS */
+.Lnextbyte:
+ EX(l8ui, a6, a3, 0, l_fixup)
+ addi a3, a3, 1
+ EX(s8i, a6, a5, 0, s_fixup)
+ addi a5, a5, 1
+#if !XCHAL_HAVE_LOOPS
+ blt a3, a7, .Lnextbyte
+#endif /* !XCHAL_HAVE_LOOPS */
+.Lbytecopydone:
+ movi a2, 0 # return success for len bytes copied
+ retw
+
+/*
+ * Destination and source are word-aligned.
+ */
+ # copy 16 bytes per iteration for word-aligned dst and word-aligned src
+ .align 4 # 1 mod 4 alignment for LOOPNEZ
+ .byte 0 # (0 mod 4 alignment for LBEG)
+.Laligned:
+#if XCHAL_HAVE_LOOPS
+ loopnez a7, .Loop1done
+#else /* !XCHAL_HAVE_LOOPS */
+ beqz a7, .Loop1done
+ slli a8, a7, 4
+ add a8, a8, a3 # a8 = end of last 16B source chunk
+#endif /* !XCHAL_HAVE_LOOPS */
+.Loop1:
+ EX(l32i, a6, a3, 0, l_fixup)
+ EX(l32i, a7, a3, 4, l_fixup)
+ EX(s32i, a6, a5, 0, s_fixup)
+ EX(l32i, a6, a3, 8, l_fixup)
+ EX(s32i, a7, a5, 4, s_fixup)
+ EX(l32i, a7, a3, 12, l_fixup)
+ EX(s32i, a6, a5, 8, s_fixup)
+ addi a3, a3, 16
+ EX(s32i, a7, a5, 12, s_fixup)
+ addi a5, a5, 16
+#if !XCHAL_HAVE_LOOPS
+ blt a3, a8, .Loop1
+#endif /* !XCHAL_HAVE_LOOPS */
+.Loop1done:
+ bbci.l a4, 3, .L2
+ # copy 8 bytes
+ EX(l32i, a6, a3, 0, l_fixup)
+ EX(l32i, a7, a3, 4, l_fixup)
+ addi a3, a3, 8
+ EX(s32i, a6, a5, 0, s_fixup)
+ EX(s32i, a7, a5, 4, s_fixup)
+ addi a5, a5, 8
+.L2:
+ bbci.l a4, 2, .L3
+ # copy 4 bytes
+ EX(l32i, a6, a3, 0, l_fixup)
+ addi a3, a3, 4
+ EX(s32i, a6, a5, 0, s_fixup)
+ addi a5, a5, 4
+.L3:
+ bbci.l a4, 1, .L4
+ # copy 2 bytes
+ EX(l16ui, a6, a3, 0, l_fixup)
+ addi a3, a3, 2
+ EX(s16i, a6, a5, 0, s_fixup)
+ addi a5, a5, 2
+.L4:
+ bbci.l a4, 0, .L5
+ # copy 1 byte
+ EX(l8ui, a6, a3, 0, l_fixup)
+ EX(s8i, a6, a5, 0, s_fixup)
+.L5:
+ movi a2, 0 # return success for len bytes copied
+ retw
+
+/*
+ * Destination is aligned, Source is unaligned
+ */
+
+ .align 4
+ .byte 0 # 1 mod 4 alignement for LOOPNEZ
+ # (0 mod 4 alignment for LBEG)
+.Lsrcunaligned:
+ # copy 16 bytes per iteration for word-aligned dst and unaligned src
+ and a10, a3, a8 # save unalignment offset for below
+ sub a3, a3, a10 # align a3 (to avoid sim warnings only; not needed for hardware)
+ EX(l32i, a6, a3, 0, l_fixup) # load first word
+#if XCHAL_HAVE_LOOPS
+ loopnez a7, .Loop2done
+#else /* !XCHAL_HAVE_LOOPS */
+ beqz a7, .Loop2done
+ slli a10, a7, 4
+ add a10, a10, a3 # a10 = end of last 16B source chunk
+#endif /* !XCHAL_HAVE_LOOPS */
+.Loop2:
+ EX(l32i, a7, a3, 4, l_fixup)
+ EX(l32i, a8, a3, 8, l_fixup)
+ ALIGN( a6, a6, a7)
+ EX(s32i, a6, a5, 0, s_fixup)
+ EX(l32i, a9, a3, 12, l_fixup)
+ ALIGN( a7, a7, a8)
+ EX(s32i, a7, a5, 4, s_fixup)
+ EX(l32i, a6, a3, 16, l_fixup)
+ ALIGN( a8, a8, a9)
+ EX(s32i, a8, a5, 8, s_fixup)
+ addi a3, a3, 16
+ ALIGN( a9, a9, a6)
+ EX(s32i, a9, a5, 12, s_fixup)
+ addi a5, a5, 16
+#if !XCHAL_HAVE_LOOPS
+ blt a3, a10, .Loop2
+#endif /* !XCHAL_HAVE_LOOPS */
+.Loop2done:
+ bbci.l a4, 3, .L12
+ # copy 8 bytes
+ EX(l32i, a7, a3, 4, l_fixup)
+ EX(l32i, a8, a3, 8, l_fixup)
+ ALIGN( a6, a6, a7)
+ EX(s32i, a6, a5, 0, s_fixup)
+ addi a3, a3, 8
+ ALIGN( a7, a7, a8)
+ EX(s32i, a7, a5, 4, s_fixup)
+ addi a5, a5, 8
+ mov a6, a8
+.L12:
+ bbci.l a4, 2, .L13
+ # copy 4 bytes
+ EX(l32i, a7, a3, 4, l_fixup)
+ addi a3, a3, 4
+ ALIGN( a6, a6, a7)
+ EX(s32i, a6, a5, 0, s_fixup)
+ addi a5, a5, 4
+ mov a6, a7
+.L13:
+ add a3, a3, a10 # readjust a3 with correct misalignment
+ bbci.l a4, 1, .L14
+ # copy 2 bytes
+ EX(l8ui, a6, a3, 0, l_fixup)
+ EX(l8ui, a7, a3, 1, l_fixup)
+ addi a3, a3, 2
+ EX(s8i, a6, a5, 0, s_fixup)
+ EX(s8i, a7, a5, 1, s_fixup)
+ addi a5, a5, 2
+.L14:
+ bbci.l a4, 0, .L15
+ # copy 1 byte
+ EX(l8ui, a6, a3, 0, l_fixup)
+ EX(s8i, a6, a5, 0, s_fixup)
+.L15:
+ movi a2, 0 # return success for len bytes copied
+ retw
+
+
+ .section .fixup, "ax"
+ .align 4
+
+/* a2 = original dst; a5 = current dst; a11= original len
+ * bytes_copied = a5 - a2
+ * retval = bytes_not_copied = original len - bytes_copied
+ * retval = a11 - (a5 - a2)
+ *
+ * Clearing the remaining pieces of kernel memory plugs security
+ * holes. This functionality is the equivalent of the *_zeroing
+ * functions that some architectures provide.
+ */
+
+.Lmemset:
+ .word memset
+
+s_fixup:
+ sub a2, a5, a2 /* a2 <-- bytes copied */
+ sub a2, a11, a2 /* a2 <-- bytes not copied */
+ retw
+
+l_fixup:
+ sub a2, a5, a2 /* a2 <-- bytes copied */
+ sub a2, a11, a2 /* a2 <-- bytes not copied == return value */
+
+ /* void *memset(void *s, int c, size_t n); */
+ mov a6, a5 /* s */
+ movi a7, 0 /* c */
+ mov a8, a2 /* n */
+ l32r a4, .Lmemset
+ callx4 a4
+ /* Ignore memset return value in a6. */
+ /* a2 still contains bytes not copied. */
+ retw
+
diff --git a/arch/xtensa/mm/Makefile b/arch/xtensa/mm/Makefile
new file mode 100644
index 00000000000..a5aed5932d7
--- /dev/null
+++ b/arch/xtensa/mm/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for the Linux/Xtensa-specific parts of the memory manager.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+obj-y := init.o fault.o tlb.o misc.o
+obj-m :=
+obj-n :=
+obj- :=
diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c
new file mode 100644
index 00000000000..a945a33e85a
--- /dev/null
+++ b/arch/xtensa/mm/fault.c
@@ -0,0 +1,241 @@
+// TODO VM_EXEC flag work-around, cache aliasing
+/*
+ * arch/xtensa/mm/fault.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
+ */
+
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+#include <asm/hardirq.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/pgalloc.h>
+
+unsigned long asid_cache = ASID_FIRST_VERSION;
+void bad_page_fault(struct pt_regs*, unsigned long, int);
+
+/*
+ * This routine handles page faults. It determines the address,
+ * and the problem, and then passes it off to one of the appropriate
+ * routines.
+ *
+ * Note: does not handle Miss and MultiHit.
+ */
+
+void do_page_fault(struct pt_regs *regs)
+{
+ struct vm_area_struct * vma;
+ struct mm_struct *mm = current->mm;
+ unsigned int exccause = regs->exccause;
+ unsigned int address = regs->excvaddr;
+ siginfo_t info;
+
+ int is_write, is_exec;
+
+ info.si_code = SEGV_MAPERR;
+
+ /* We fault-in kernel-space virtual memory on-demand. The
+ * 'reference' page table is init_mm.pgd.
+ */
+ if (address >= TASK_SIZE && !user_mode(regs))
+ goto vmalloc_fault;
+
+ /* If we're in an interrupt or have no user
+ * context, we must not take the fault..
+ */
+ if (in_atomic() || !mm) {
+ bad_page_fault(regs, address, SIGSEGV);
+ return;
+ }
+
+ is_write = (exccause == XCHAL_EXCCAUSE_STORE_CACHE_ATTRIBUTE) ? 1 : 0;
+ is_exec = (exccause == XCHAL_EXCCAUSE_ITLB_PRIVILEGE ||
+ exccause == XCHAL_EXCCAUSE_ITLB_MISS ||
+ exccause == XCHAL_EXCCAUSE_FETCH_CACHE_ATTRIBUTE) ? 1 : 0;
+
+#if 0
+ printk("[%s:%d:%08x:%d:%08x:%s%s]\n", current->comm, current->pid,
+ address, exccause, regs->pc, is_write? "w":"", is_exec? "x":"");
+#endif
+
+ down_read(&mm->mmap_sem);
+ vma = find_vma(mm, address);
+
+ if (!vma)
+ goto bad_area;
+ if (vma->vm_start <= address)
+ goto good_area;
+ if (!(vma->vm_flags & VM_GROWSDOWN))
+ goto bad_area;
+ if (expand_stack(vma, address))
+ goto bad_area;
+
+ /* Ok, we have a good vm_area for this memory access, so
+ * we can handle it..
+ */
+
+good_area:
+ info.si_code = SEGV_ACCERR;
+
+ if (is_write) {
+ if (!(vma->vm_flags & VM_WRITE))
+ goto bad_area;
+ } else if (is_exec) {
+ if (!(vma->vm_flags & VM_EXEC))
+ goto bad_area;
+ } else /* Allow read even from write-only pages. */
+ if (!(vma->vm_flags & (VM_READ | VM_WRITE)))
+ goto bad_area;
+
+ /* If for any reason at all we couldn't handle the fault,
+ * make sure we exit gracefully rather than endlessly redo
+ * the fault.
+ */
+survive:
+ switch (handle_mm_fault(mm, vma, address, is_write)) {
+ case VM_FAULT_MINOR:
+ current->min_flt++;
+ break;
+ case VM_FAULT_MAJOR:
+ current->maj_flt++;
+ break;
+ case VM_FAULT_SIGBUS:
+ goto do_sigbus;
+ case VM_FAULT_OOM:
+ goto out_of_memory;
+ default:
+ BUG();
+ }
+
+ up_read(&mm->mmap_sem);
+ return;
+
+ /* Something tried to access memory that isn't in our memory map..
+ * Fix it, but check if it's kernel or user first..
+ */
+bad_area:
+ up_read(&mm->mmap_sem);
+ if (user_mode(regs)) {
+ current->thread.bad_vaddr = address;
+ current->thread.error_code = is_write;
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ /* info.si_code has been set above */
+ info.si_addr = (void *) address;
+ force_sig_info(SIGSEGV, &info, current);
+ return;
+ }
+ bad_page_fault(regs, address, SIGSEGV);
+ return;
+
+
+ /* We ran out of memory, or some other thing happened to us that made
+ * us unable to handle the page fault gracefully.
+ */
+out_of_memory:
+ up_read(&mm->mmap_sem);
+ if (current->pid == 1) {
+ yield();
+ down_read(&mm->mmap_sem);
+ goto survive;
+ }
+ printk("VM: killing process %s\n", current->comm);
+ if (user_mode(regs))
+ do_exit(SIGKILL);
+ bad_page_fault(regs, address, SIGKILL);
+ return;
+
+do_sigbus:
+ up_read(&mm->mmap_sem);
+
+ /* Send a sigbus, regardless of whether we were in kernel
+ * or user mode.
+ */
+ current->thread.bad_vaddr = address;
+ info.si_code = SIGBUS;
+ info.si_errno = 0;
+ info.si_code = BUS_ADRERR;
+ info.si_addr = (void *) address;
+ force_sig_info(SIGBUS, &info, current);
+
+ /* Kernel mode? Handle exceptions or die */
+ if (!user_mode(regs))
+ bad_page_fault(regs, address, SIGBUS);
+
+vmalloc_fault:
+ {
+ /* Synchronize this task's top level page-table
+ * with the 'reference' page table.
+ */
+ struct mm_struct *act_mm = current->active_mm;
+ int index = pgd_index(address);
+ pgd_t *pgd, *pgd_k;
+ pmd_t *pmd, *pmd_k;
+ pte_t *pte_k;
+
+ if (act_mm == NULL)
+ goto bad_page_fault;
+
+ pgd = act_mm->pgd + index;
+ pgd_k = init_mm.pgd + index;
+
+ if (!pgd_present(*pgd_k))
+ goto bad_page_fault;
+
+ pgd_val(*pgd) = pgd_val(*pgd_k);
+
+ pmd = pmd_offset(pgd, address);
+ pmd_k = pmd_offset(pgd_k, address);
+ if (!pmd_present(*pmd) || !pmd_present(*pmd_k))
+ goto bad_page_fault;
+
+ pmd_val(*pmd) = pmd_val(*pmd_k);
+ pte_k = pte_offset_kernel(pmd_k, address);
+
+ if (!pte_present(*pte_k))
+ goto bad_page_fault;
+ return;
+ }
+bad_page_fault:
+ bad_page_fault(regs, address, SIGKILL);
+ return;
+}
+
+
+void
+bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
+{
+ extern void die(const char*, struct pt_regs*, long);
+ const struct exception_table_entry *entry;
+
+ /* Are we prepared to handle this kernel fault? */
+ if ((entry = search_exception_tables(regs->pc)) != NULL) {
+#if 1
+ printk(KERN_DEBUG "%s: Exception at pc=%#010lx (%lx)\n",
+ current->comm, regs->pc, entry->fixup);
+#endif
+ current->thread.bad_uaddr = address;
+ regs->pc = entry->fixup;
+ return;
+ }
+
+ /* Oops. The kernel tried to access some bad page. We'll have to
+ * terminate things with extreme prejudice.
+ */
+ printk(KERN_ALERT "Unable to handle kernel paging request at virtual "
+ "address %08lx\n pc = %08lx, ra = %08lx\n",
+ address, regs->pc, regs->areg[0]);
+ die("Oops", regs, sig);
+ do_exit(sig);
+}
+
diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c
new file mode 100644
index 00000000000..56aace84aae
--- /dev/null
+++ b/arch/xtensa/mm/init.c
@@ -0,0 +1,551 @@
+/*
+ * arch/xtensa/mm/init.c
+ *
+ * Derived from MIPS, PPC.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
+ * Marc Gauthier
+ * Kevin Chea
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/bootmem.h>
+#include <linux/swap.h>
+
+#include <asm/pgtable.h>
+#include <asm/bootparam.h>
+#include <asm/mmu_context.h>
+#include <asm/tlb.h>
+#include <asm/tlbflush.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+
+
+#define DEBUG 0
+
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+//static DEFINE_SPINLOCK(tlb_lock);
+
+/*
+ * This flag is used to indicate that the page was mapped and modified in
+ * kernel space, so the cache is probably dirty at that address.
+ * If cache aliasing is enabled and the page color mismatches, update_mmu_cache
+ * synchronizes the caches if this bit is set.
+ */
+
+#define PG_cache_clean PG_arch_1
+
+/* References to section boundaries */
+
+extern char _ftext, _etext, _fdata, _edata, _rodata_end;
+extern char __init_begin, __init_end;
+
+/*
+ * mem_reserve(start, end, must_exist)
+ *
+ * Reserve some memory from the memory pool.
+ *
+ * Parameters:
+ * start Start of region,
+ * end End of region,
+ * must_exist Must exist in memory pool.
+ *
+ * Returns:
+ * 0 (memory area couldn't be mapped)
+ * -1 (success)
+ */
+
+int __init mem_reserve(unsigned long start, unsigned long end, int must_exist)
+{
+ int i;
+
+ if (start == end)
+ return 0;
+
+ start = start & PAGE_MASK;
+ end = PAGE_ALIGN(end);
+
+ for (i = 0; i < sysmem.nr_banks; i++)
+ if (start < sysmem.bank[i].end
+ && end >= sysmem.bank[i].start)
+ break;
+
+ if (i == sysmem.nr_banks) {
+ if (must_exist)
+ printk (KERN_WARNING "mem_reserve: [0x%0lx, 0x%0lx) "
+ "not in any region!\n", start, end);
+ return 0;
+ }
+
+ if (start > sysmem.bank[i].start) {
+ if (end < sysmem.bank[i].end) {
+ /* split entry */
+ if (sysmem.nr_banks >= SYSMEM_BANKS_MAX)
+ panic("meminfo overflow\n");
+ sysmem.bank[sysmem.nr_banks].start = end;
+ sysmem.bank[sysmem.nr_banks].end = sysmem.bank[i].end;
+ sysmem.nr_banks++;
+ }
+ sysmem.bank[i].end = start;
+ } else {
+ if (end < sysmem.bank[i].end)
+ sysmem.bank[i].start = end;
+ else {
+ /* remove entry */
+ sysmem.nr_banks--;
+ sysmem.bank[i].start = sysmem.bank[sysmem.nr_banks].start;
+ sysmem.bank[i].end = sysmem.bank[sysmem.nr_banks].end;
+ }
+ }
+ return -1;
+}
+
+
+/*
+ * Initialize the bootmem system and give it all the memory we have available.
+ */
+
+void __init bootmem_init(void)
+{
+ unsigned long pfn;
+ unsigned long bootmap_start, bootmap_size;
+ int i;
+
+ max_low_pfn = max_pfn = 0;
+ min_low_pfn = ~0;
+
+ for (i=0; i < sysmem.nr_banks; i++) {
+ pfn = PAGE_ALIGN(sysmem.bank[i].start) >> PAGE_SHIFT;
+ if (pfn < min_low_pfn)
+ min_low_pfn = pfn;
+ pfn = PAGE_ALIGN(sysmem.bank[i].end - 1) >> PAGE_SHIFT;
+ if (pfn > max_pfn)
+ max_pfn = pfn;
+ }
+
+ if (min_low_pfn > max_pfn)
+ panic("No memory found!\n");
+
+ max_low_pfn = max_pfn < MAX_LOW_MEMORY >> PAGE_SHIFT ?
+ max_pfn : MAX_LOW_MEMORY >> PAGE_SHIFT;
+
+ /* Find an area to use for the bootmem bitmap. */
+
+ bootmap_size = bootmem_bootmap_pages(max_low_pfn) << PAGE_SHIFT;
+ bootmap_start = ~0;
+
+ for (i=0; i<sysmem.nr_banks; i++)
+ if (sysmem.bank[i].end - sysmem.bank[i].start >= bootmap_size) {
+ bootmap_start = sysmem.bank[i].start;
+ break;
+ }
+
+ if (bootmap_start == ~0UL)
+ panic("Cannot find %ld bytes for bootmap\n", bootmap_size);
+
+ /* Reserve the bootmem bitmap area */
+
+ mem_reserve(bootmap_start, bootmap_start + bootmap_size, 1);
+ bootmap_size = init_bootmem_node(NODE_DATA(0), min_low_pfn,
+ bootmap_start >> PAGE_SHIFT,
+ max_low_pfn);
+
+ /* Add all remaining memory pieces into the bootmem map */
+
+ for (i=0; i<sysmem.nr_banks; i++)
+ free_bootmem(sysmem.bank[i].start,
+ sysmem.bank[i].end - sysmem.bank[i].start);
+
+}
+
+
+void __init paging_init(void)
+{
+ unsigned long zones_size[MAX_NR_ZONES];
+ int i;
+
+ /* All pages are DMA-able, so we put them all in the DMA zone. */
+
+ zones_size[ZONE_DMA] = max_low_pfn;
+ for (i = 1; i < MAX_NR_ZONES; i++)
+ zones_size[i] = 0;
+
+#ifdef CONFIG_HIGHMEM
+ zones_size[ZONE_HIGHMEM] = max_pfn - max_low_pfn;
+#endif
+
+ /* Initialize the kernel's page tables. */
+
+ memset(swapper_pg_dir, 0, PAGE_SIZE);
+
+ free_area_init(zones_size);
+}
+
+/*
+ * Flush the mmu and reset associated register to default values.
+ */
+
+void __init init_mmu (void)
+{
+ /* Writing zeros to the <t>TLBCFG special registers ensure
+ * that valid values exist in the register. For existing
+ * PGSZID<w> fields, zero selects the first element of the
+ * page-size array. For nonexistant PGSZID<w> fields, zero is
+ * the best value to write. Also, when changing PGSZID<w>
+ * fields, the corresponding TLB must be flushed.
+ */
+ set_itlbcfg_register (0);
+ set_dtlbcfg_register (0);
+ flush_tlb_all ();
+
+ /* Set rasid register to a known value. */
+
+ set_rasid_register (ASID_ALL_RESERVED);
+
+ /* Set PTEVADDR special register to the start of the page
+ * table, which is in kernel mappable space (ie. not
+ * statically mapped). This register's value is undefined on
+ * reset.
+ */
+ set_ptevaddr_register (PGTABLE_START);
+}
+
+/*
+ * Initialize memory pages.
+ */
+
+void __init mem_init(void)
+{
+ unsigned long codesize, reservedpages, datasize, initsize;
+ unsigned long highmemsize, tmp, ram;
+
+ max_mapnr = num_physpages = max_low_pfn;
+ high_memory = (void *) __va(max_mapnr << PAGE_SHIFT);
+ highmemsize = 0;
+
+#if CONFIG_HIGHMEM
+#error HIGHGMEM not implemented in init.c
+#endif
+
+ totalram_pages += free_all_bootmem();
+
+ reservedpages = ram = 0;
+ for (tmp = 0; tmp < max_low_pfn; tmp++) {
+ ram++;
+ if (PageReserved(mem_map+tmp))
+ reservedpages++;
+ }
+
+ codesize = (unsigned long) &_etext - (unsigned long) &_ftext;
+ datasize = (unsigned long) &_edata - (unsigned long) &_fdata;
+ initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
+
+ printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, "
+ "%ldk data, %ldk init %ldk highmem)\n",
+ (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
+ ram << (PAGE_SHIFT-10),
+ codesize >> 10,
+ reservedpages << (PAGE_SHIFT-10),
+ datasize >> 10,
+ initsize >> 10,
+ highmemsize >> 10);
+}
+
+void
+free_reserved_mem(void *start, void *end)
+{
+ for (; start < end; start += PAGE_SIZE) {
+ ClearPageReserved(virt_to_page(start));
+ set_page_count(virt_to_page(start), 1);
+ free_page((unsigned long)start);
+ totalram_pages++;
+ }
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+extern int initrd_is_mapped;
+
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+ if (initrd_is_mapped) {
+ free_reserved_mem((void*)start, (void*)end);
+ printk ("Freeing initrd memory: %ldk freed\n",(end-start)>>10);
+ }
+}
+#endif
+
+void free_initmem(void)
+{
+ free_reserved_mem(&__init_begin, &__init_end);
+ printk("Freeing unused kernel memory: %dk freed\n",
+ (&__init_end - &__init_begin) >> 10);
+}
+
+void show_mem(void)
+{
+ int i, free = 0, total = 0, reserved = 0;
+ int shared = 0, cached = 0;
+
+ printk("Mem-info:\n");
+ show_free_areas();
+ printk("Free swap: %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+ i = max_mapnr;
+ while (i-- > 0) {
+ total++;
+ if (PageReserved(mem_map+i))
+ reserved++;
+ else if (PageSwapCache(mem_map+i))
+ cached++;
+ else if (!page_count(mem_map + i))
+ free++;
+ else
+ shared += page_count(mem_map + i) - 1;
+ }
+ printk("%d pages of RAM\n", total);
+ printk("%d reserved pages\n", reserved);
+ printk("%d pages shared\n", shared);
+ printk("%d pages swap cached\n",cached);
+ printk("%d free pages\n", free);
+}
+
+/* ------------------------------------------------------------------------- */
+
+#if (DCACHE_WAY_SIZE > PAGE_SIZE)
+
+/*
+ * With cache aliasing, the page color of the page in kernel space and user
+ * space might mismatch. We temporarily map the page to a different virtual
+ * address with the same color and clear the page there.
+ */
+
+void clear_user_page(void *kaddr, unsigned long vaddr, struct page* page)
+{
+
+ /* There shouldn't be any entries for this page. */
+
+ __flush_invalidate_dcache_page_phys(__pa(page_address(page)));
+
+ if (!PAGE_COLOR_EQ(vaddr, kaddr)) {
+ unsigned long v, p;
+
+ /* Temporarily map page to DTLB_WAY_DCACHE_ALIAS0. */
+
+ spin_lock(&tlb_lock);
+
+ p = (unsigned long)pte_val((mk_pte(page,PAGE_KERNEL)));
+ kaddr = (void*)PAGE_COLOR_MAP0(vaddr);
+ v = (unsigned long)kaddr | DTLB_WAY_DCACHE_ALIAS0;
+ __asm__ __volatile__("wdtlb %0,%1; dsync" : :"a" (p), "a" (v));
+
+ clear_page(kaddr);
+
+ spin_unlock(&tlb_lock);
+ } else {
+ clear_page(kaddr);
+ }
+
+ /* We need to make sure that i$ and d$ are coherent. */
+
+ clear_bit(PG_cache_clean, &page->flags);
+}
+
+/*
+ * With cache aliasing, we have to make sure that the page color of the page
+ * in kernel space matches that of the virtual user address before we read
+ * the page. If the page color differ, we create a temporary DTLB entry with
+ * the corrent page color and use this 'temporary' address as the source.
+ * We then use the same approach as in clear_user_page and copy the data
+ * to the kernel space and clear the PG_cache_clean bit to synchronize caches
+ * later.
+ *
+ * Note:
+ * Instead of using another 'way' for the temporary DTLB entry, we could
+ * probably use the same entry that points to the kernel address (after
+ * saving the original value and restoring it when we are done).
+ */
+
+void copy_user_page(void* to, void* from, unsigned long vaddr,
+ struct page* to_page)
+{
+ /* There shouldn't be any entries for the new page. */
+
+ __flush_invalidate_dcache_page_phys(__pa(page_address(to_page)));
+
+ spin_lock(&tlb_lock);
+
+ if (!PAGE_COLOR_EQ(vaddr, from)) {
+ unsigned long v, p, t;
+
+ __asm__ __volatile__ ("pdtlb %1,%2; rdtlb1 %0,%1"
+ : "=a"(p), "=a"(t) : "a"(from));
+ from = (void*)PAGE_COLOR_MAP0(vaddr);
+ v = (unsigned long)from | DTLB_WAY_DCACHE_ALIAS0;
+ __asm__ __volatile__ ("wdtlb %0,%1; dsync" ::"a" (p), "a" (v));
+ }
+
+ if (!PAGE_COLOR_EQ(vaddr, to)) {
+ unsigned long v, p;
+
+ p = (unsigned long)pte_val((mk_pte(to_page,PAGE_KERNEL)));
+ to = (void*)PAGE_COLOR_MAP1(vaddr);
+ v = (unsigned long)to | DTLB_WAY_DCACHE_ALIAS1;
+ __asm__ __volatile__ ("wdtlb %0,%1; dsync" ::"a" (p), "a" (v));
+ }
+ copy_page(to, from);
+
+ spin_unlock(&tlb_lock);
+
+ /* We need to make sure that i$ and d$ are coherent. */
+
+ clear_bit(PG_cache_clean, &to_page->flags);
+}
+
+
+
+/*
+ * Any time the kernel writes to a user page cache page, or it is about to
+ * read from a page cache page this routine is called.
+ *
+ * Note:
+ * The kernel currently only provides one architecture bit in the page
+ * flags that we use for I$/D$ coherency. Maybe, in future, we can
+ * use a sepearte bit for deferred dcache aliasing:
+ * If the page is not mapped yet, we only need to set a flag,
+ * if mapped, we need to invalidate the page.
+ */
+// FIXME: we probably need this for WB caches not only for Page Coloring..
+
+void flush_dcache_page(struct page *page)
+{
+ unsigned long addr = __pa(page_address(page));
+ struct address_space *mapping = page_mapping(page);
+
+ __flush_invalidate_dcache_page_phys(addr);
+
+ if (!test_bit(PG_cache_clean, &page->flags))
+ return;
+
+ /* If this page hasn't been mapped, yet, handle I$/D$ coherency later.*/
+#if 0
+ if (mapping && !mapping_mapped(mapping))
+ clear_bit(PG_cache_clean, &page->flags);
+ else
+#endif
+ __invalidate_icache_page_phys(addr);
+}
+
+void flush_cache_range(struct vm_area_struct* vma, unsigned long s,
+ unsigned long e)
+{
+ __flush_invalidate_cache_all();
+}
+
+void flush_cache_page(struct vm_area_struct* vma, unsigned long address,
+ unsigned long pfn)
+{
+ struct page *page = pfn_to_page(pfn);
+
+ /* Remove any entry for the old mapping. */
+
+ if (current->active_mm == vma->vm_mm) {
+ unsigned long addr = __pa(page_address(page));
+ __flush_invalidate_dcache_page_phys(addr);
+ if ((vma->vm_flags & VM_EXEC) != 0)
+ __invalidate_icache_page_phys(addr);
+ } else {
+ BUG();
+ }
+}
+
+#endif /* (DCACHE_WAY_SIZE > PAGE_SIZE) */
+
+
+pte_t* pte_alloc_one_kernel (struct mm_struct* mm, unsigned long addr)
+{
+ pte_t* pte = (pte_t*)__get_free_pages(GFP_KERNEL|__GFP_REPEAT, 0);
+ if (likely(pte)) {
+ pte_t* ptep = (pte_t*)(pte_val(*pte) + PAGE_OFFSET);
+ int i;
+ for (i = 0; i < 1024; i++, ptep++)
+ pte_clear(mm, addr, ptep);
+ }
+ return pte;
+}
+
+struct page* pte_alloc_one(struct mm_struct *mm, unsigned long addr)
+{
+ struct page *page;
+
+ page = alloc_pages(GFP_KERNEL | __GFP_REPEAT, 0);
+
+ if (likely(page)) {
+ pte_t* ptep = kmap_atomic(page, KM_USER0);
+ int i;
+
+ for (i = 0; i < 1024; i++, ptep++)
+ pte_clear(mm, addr, ptep);
+
+ kunmap_atomic(ptep, KM_USER0);
+ }
+ return page;
+}
+
+
+/*
+ * Handle D$/I$ coherency.
+ *
+ * Note:
+ * We only have one architecture bit for the page flags, so we cannot handle
+ * cache aliasing, yet.
+ */
+
+void
+update_mmu_cache(struct vm_area_struct * vma, unsigned long addr, pte_t pte)
+{
+ unsigned long pfn = pte_pfn(pte);
+ struct page *page;
+ unsigned long vaddr = addr & PAGE_MASK;
+
+ if (!pfn_valid(pfn))
+ return;
+
+ page = pfn_to_page(pfn);
+
+ invalidate_itlb_mapping(addr);
+ invalidate_dtlb_mapping(addr);
+
+ /* We have a new mapping. Use it. */
+
+ write_dtlb_entry(pte, dtlb_probe(addr));
+
+ /* If the processor can execute from this page, synchronize D$/I$. */
+
+ if ((vma->vm_flags & VM_EXEC) != 0) {
+
+ write_itlb_entry(pte, itlb_probe(addr));
+
+ /* Synchronize caches, if not clean. */
+
+ if (!test_and_set_bit(PG_cache_clean, &page->flags)) {
+ __flush_dcache_page(vaddr);
+ __invalidate_icache_page(vaddr);
+ }
+ }
+}
+
diff --git a/arch/xtensa/mm/misc.S b/arch/xtensa/mm/misc.S
new file mode 100644
index 00000000000..327c0f17187
--- /dev/null
+++ b/arch/xtensa/mm/misc.S
@@ -0,0 +1,374 @@
+/*
+ * arch/xtensa/mm/misc.S
+ *
+ * Miscellaneous assembly functions.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ */
+
+/* Note: we might want to implement some of the loops as zero-overhead-loops,
+ * where applicable and if supported by the processor.
+ */
+
+#include <linux/linkage.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#include <xtensa/cacheasm.h>
+#include <xtensa/cacheattrasm.h>
+
+/* clear_page (page) */
+
+ENTRY(clear_page)
+ entry a1, 16
+ addi a4, a2, PAGE_SIZE
+ movi a3, 0
+
+1: s32i a3, a2, 0
+ s32i a3, a2, 4
+ s32i a3, a2, 8
+ s32i a3, a2, 12
+ s32i a3, a2, 16
+ s32i a3, a2, 20
+ s32i a3, a2, 24
+ s32i a3, a2, 28
+ addi a2, a2, 32
+ blt a2, a4, 1b
+
+ retw
+
+/*
+ * copy_page (void *to, void *from)
+ * a2 a3
+ */
+
+ENTRY(copy_page)
+ entry a1, 16
+ addi a4, a2, PAGE_SIZE
+
+1: l32i a5, a3, 0
+ l32i a6, a3, 4
+ l32i a7, a3, 8
+ s32i a5, a2, 0
+ s32i a6, a2, 4
+ s32i a7, a2, 8
+ l32i a5, a3, 12
+ l32i a6, a3, 16
+ l32i a7, a3, 20
+ s32i a5, a2, 12
+ s32i a6, a2, 16
+ s32i a7, a2, 20
+ l32i a5, a3, 24
+ l32i a6, a3, 28
+ s32i a5, a2, 24
+ s32i a6, a2, 28
+ addi a2, a2, 32
+ addi a3, a3, 32
+ blt a2, a4, 1b
+
+ retw
+
+
+/*
+ * void __flush_invalidate_cache_all(void)
+ */
+
+ENTRY(__flush_invalidate_cache_all)
+ entry sp, 16
+ dcache_writeback_inv_all a2, a3
+ icache_invalidate_all a2, a3
+ retw
+
+/*
+ * void __invalidate_icache_all(void)
+ */
+
+ENTRY(__invalidate_icache_all)
+ entry sp, 16
+ icache_invalidate_all a2, a3
+ retw
+
+/*
+ * void __flush_invalidate_dcache_all(void)
+ */
+
+ENTRY(__flush_invalidate_dcache_all)
+ entry sp, 16
+ dcache_writeback_inv_all a2, a3
+ retw
+
+
+/*
+ * void __flush_invalidate_cache_range(ulong start, ulong size)
+ */
+
+ENTRY(__flush_invalidate_cache_range)
+ entry sp, 16
+ mov a4, a2
+ mov a5, a3
+ dcache_writeback_inv_region a4, a5, a6
+ icache_invalidate_region a2, a3, a4
+ retw
+
+/*
+ * void __invalidate_icache_page(ulong start)
+ */
+
+ENTRY(__invalidate_icache_page)
+ entry sp, 16
+ movi a3, PAGE_SIZE
+ icache_invalidate_region a2, a3, a4
+ retw
+
+/*
+ * void __invalidate_dcache_page(ulong start)
+ */
+
+ENTRY(__invalidate_dcache_page)
+ entry sp, 16
+ movi a3, PAGE_SIZE
+ dcache_invalidate_region a2, a3, a4
+ retw
+
+/*
+ * void __invalidate_icache_range(ulong start, ulong size)
+ */
+
+ENTRY(__invalidate_icache_range)
+ entry sp, 16
+ icache_invalidate_region a2, a3, a4
+ retw
+
+/*
+ * void __invalidate_dcache_range(ulong start, ulong size)
+ */
+
+ENTRY(__invalidate_dcache_range)
+ entry sp, 16
+ dcache_invalidate_region a2, a3, a4
+ retw
+
+/*
+ * void __flush_dcache_page(ulong start)
+ */
+
+ENTRY(__flush_dcache_page)
+ entry sp, 16
+ movi a3, PAGE_SIZE
+ dcache_writeback_region a2, a3, a4
+ retw
+
+/*
+ * void __flush_invalidate_dcache_page(ulong start)
+ */
+
+ENTRY(__flush_invalidate_dcache_page)
+ entry sp, 16
+ movi a3, PAGE_SIZE
+ dcache_writeback_inv_region a2, a3, a4
+ retw
+
+/*
+ * void __flush_invalidate_dcache_range(ulong start, ulong size)
+ */
+
+ENTRY(__flush_invalidate_dcache_range)
+ entry sp, 16
+ dcache_writeback_inv_region a2, a3, a4
+ retw
+
+/*
+ * void __invalidate_dcache_all(void)
+ */
+
+ENTRY(__invalidate_dcache_all)
+ entry sp, 16
+ dcache_invalidate_all a2, a3
+ retw
+
+/*
+ * void __flush_invalidate_dcache_page_phys(ulong start)
+ */
+
+ENTRY(__flush_invalidate_dcache_page_phys)
+ entry sp, 16
+
+ movi a3, XCHAL_DCACHE_SIZE
+ movi a4, PAGE_MASK | 1
+ addi a2, a2, 1
+
+1: addi a3, a3, -XCHAL_DCACHE_LINESIZE
+
+ ldct a6, a3
+ dsync
+ and a6, a6, a4
+ beq a6, a2, 2f
+ bgeui a3, 2, 1b
+ retw
+
+2: diwbi a3, 0
+ bgeui a3, 2, 1b
+ retw
+
+ENTRY(check_dcache_low0)
+ entry sp, 16
+
+ movi a3, XCHAL_DCACHE_SIZE / 4
+ movi a4, PAGE_MASK | 1
+ addi a2, a2, 1
+
+1: addi a3, a3, -XCHAL_DCACHE_LINESIZE
+
+ ldct a6, a3
+ dsync
+ and a6, a6, a4
+ beq a6, a2, 2f
+ bgeui a3, 2, 1b
+ retw
+
+2: j 2b
+
+ENTRY(check_dcache_high0)
+ entry sp, 16
+
+ movi a5, XCHAL_DCACHE_SIZE / 4
+ movi a3, XCHAL_DCACHE_SIZE / 2
+ movi a4, PAGE_MASK | 1
+ addi a2, a2, 1
+
+1: addi a3, a3, -XCHAL_DCACHE_LINESIZE
+ addi a5, a5, -XCHAL_DCACHE_LINESIZE
+
+ ldct a6, a3
+ dsync
+ and a6, a6, a4
+ beq a6, a2, 2f
+ bgeui a5, 2, 1b
+ retw
+
+2: j 2b
+
+ENTRY(check_dcache_low1)
+ entry sp, 16
+
+ movi a5, XCHAL_DCACHE_SIZE / 4
+ movi a3, XCHAL_DCACHE_SIZE * 3 / 4
+ movi a4, PAGE_MASK | 1
+ addi a2, a2, 1
+
+1: addi a3, a3, -XCHAL_DCACHE_LINESIZE
+ addi a5, a5, -XCHAL_DCACHE_LINESIZE
+
+ ldct a6, a3
+ dsync
+ and a6, a6, a4
+ beq a6, a2, 2f
+ bgeui a5, 2, 1b
+ retw
+
+2: j 2b
+
+ENTRY(check_dcache_high1)
+ entry sp, 16
+
+ movi a5, XCHAL_DCACHE_SIZE / 4
+ movi a3, XCHAL_DCACHE_SIZE
+ movi a4, PAGE_MASK | 1
+ addi a2, a2, 1
+
+1: addi a3, a3, -XCHAL_DCACHE_LINESIZE
+ addi a5, a5, -XCHAL_DCACHE_LINESIZE
+
+ ldct a6, a3
+ dsync
+ and a6, a6, a4
+ beq a6, a2, 2f
+ bgeui a5, 2, 1b
+ retw
+
+2: j 2b
+
+
+/*
+ * void __invalidate_icache_page_phys(ulong start)
+ */
+
+ENTRY(__invalidate_icache_page_phys)
+ entry sp, 16
+
+ movi a3, XCHAL_ICACHE_SIZE
+ movi a4, PAGE_MASK | 1
+ addi a2, a2, 1
+
+1: addi a3, a3, -XCHAL_ICACHE_LINESIZE
+
+ lict a6, a3
+ isync
+ and a6, a6, a4
+ beq a6, a2, 2f
+ bgeui a3, 2, 1b
+ retw
+
+2: iii a3, 0
+ bgeui a3, 2, 1b
+ retw
+
+
+#if 0
+
+ movi a3, XCHAL_DCACHE_WAYS - 1
+ movi a4, PAGE_SIZE
+
+1: mov a5, a2
+ add a6, a2, a4
+
+2: diwbi a5, 0
+ diwbi a5, XCHAL_DCACHE_LINESIZE
+ diwbi a5, XCHAL_DCACHE_LINESIZE * 2
+ diwbi a5, XCHAL_DCACHE_LINESIZE * 3
+
+ addi a5, a5, XCHAL_DCACHE_LINESIZE * 4
+ blt a5, a6, 2b
+
+ addi a3, a3, -1
+ addi a2, a2, XCHAL_DCACHE_SIZE / XCHAL_DCACHE_WAYS
+ bgez a3, 1b
+
+ retw
+
+ENTRY(__invalidate_icache_page_index)
+ entry sp, 16
+
+ movi a3, XCHAL_ICACHE_WAYS - 1
+ movi a4, PAGE_SIZE
+
+1: mov a5, a2
+ add a6, a2, a4
+
+2: iii a5, 0
+ iii a5, XCHAL_ICACHE_LINESIZE
+ iii a5, XCHAL_ICACHE_LINESIZE * 2
+ iii a5, XCHAL_ICACHE_LINESIZE * 3
+
+ addi a5, a5, XCHAL_ICACHE_LINESIZE * 4
+ blt a5, a6, 2b
+
+ addi a3, a3, -1
+ addi a2, a2, XCHAL_ICACHE_SIZE / XCHAL_ICACHE_WAYS
+ bgez a3, 2b
+
+ retw
+
+#endif
+
+
+
+
+
+
diff --git a/arch/xtensa/mm/pgtable.c b/arch/xtensa/mm/pgtable.c
new file mode 100644
index 00000000000..e5e119c820e
--- /dev/null
+++ b/arch/xtensa/mm/pgtable.c
@@ -0,0 +1,76 @@
+/*
+ * arch/xtensa/mm/fault.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ */
+
+#if (DCACHE_SIZE > PAGE_SIZE)
+
+pte_t* pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+{
+ pte_t *pte, p;
+ int color = ADDR_COLOR(address);
+ int i;
+
+ p = (pte_t*) __get_free_pages(GFP_KERNEL|__GFP_REPEAT, COLOR_ORDER);
+
+ if (likely(p)) {
+ struct page *page;
+
+ for (i = 0; i < COLOR_SIZE; i++, p++) {
+ page = virt_to_page(pte);
+
+ set_page_count(page, 1);
+ ClearPageCompound(page);
+
+ if (ADDR_COLOR(p) == color)
+ pte = p;
+ else
+ free_page(p);
+ }
+ clear_page(pte);
+ }
+ return pte;
+}
+
+#ifdef PROFILING
+
+int mask;
+int hit;
+int flush;
+
+#endif
+
+struct page* pte_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+ struct page *page, p;
+ int color = ADDR_COLOR(address);
+
+ p = alloc_pages(GFP_KERNEL | __GFP_REPEAT, PTE_ORDER);
+
+ if (likely(p)) {
+ for (i = 0; i < PAGE_ORDER; i++) {
+ set_page_count(p, 1);
+ ClearPageCompound(p);
+
+ if (PADDR_COLOR(page_address(pg)) == color)
+ page = p;
+ else
+ free_page(p);
+ }
+ clear_highpage(page);
+ }
+
+ return page;
+}
+
+#endif
+
+
+
diff --git a/arch/xtensa/mm/tlb.c b/arch/xtensa/mm/tlb.c
new file mode 100644
index 00000000000..d3bd3bfc3b3
--- /dev/null
+++ b/arch/xtensa/mm/tlb.c
@@ -0,0 +1,545 @@
+/*
+ * arch/xtensa/mm/mmu.c
+ *
+ * Logic that manipulates the Xtensa MMU. Derived from MIPS.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2003 Tensilica Inc.
+ *
+ * Joe Taylor
+ * Chris Zankel <chris@zankel.net>
+ * Marc Gauthier
+ */
+
+#include <linux/mm.h>
+#include <asm/processor.h>
+#include <asm/mmu_context.h>
+#include <asm/tlbflush.h>
+#include <asm/system.h>
+#include <asm/cacheflush.h>
+
+
+static inline void __flush_itlb_all (void)
+{
+ int way, index;
+
+ for (way = 0; way < XCHAL_ITLB_ARF_WAYS; way++) {
+ for (index = 0; index < ITLB_ENTRIES_PER_ARF_WAY; index++) {
+ int entry = way + (index << PAGE_SHIFT);
+ invalidate_itlb_entry_no_isync (entry);
+ }
+ }
+ asm volatile ("isync\n");
+}
+
+static inline void __flush_dtlb_all (void)
+{
+ int way, index;
+
+ for (way = 0; way < XCHAL_DTLB_ARF_WAYS; way++) {
+ for (index = 0; index < DTLB_ENTRIES_PER_ARF_WAY; index++) {
+ int entry = way + (index << PAGE_SHIFT);
+ invalidate_dtlb_entry_no_isync (entry);
+ }
+ }
+ asm volatile ("isync\n");
+}
+
+
+void flush_tlb_all (void)
+{
+ __flush_itlb_all();
+ __flush_dtlb_all();
+}
+
+/* If mm is current, we simply assign the current task a new ASID, thus,
+ * invalidating all previous tlb entries. If mm is someone else's user mapping,
+ * wie invalidate the context, thus, when that user mapping is swapped in,
+ * a new context will be assigned to it.
+ */
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+#if 0
+ printk("[tlbmm<%lx>]\n", (unsigned long)mm->context);
+#endif
+
+ if (mm == current->active_mm) {
+ int flags;
+ local_save_flags(flags);
+ get_new_mmu_context(mm, asid_cache);
+ set_rasid_register(ASID_INSERT(mm->context));
+ local_irq_restore(flags);
+ }
+ else
+ mm->context = 0;
+}
+
+void flush_tlb_range (struct vm_area_struct *vma,
+ unsigned long start, unsigned long end)
+{
+ struct mm_struct *mm = vma->vm_mm;
+ unsigned long flags;
+
+ if (mm->context == NO_CONTEXT)
+ return;
+
+#if 0
+ printk("[tlbrange<%02lx,%08lx,%08lx>]\n",
+ (unsigned long)mm->context, start, end);
+#endif
+ local_save_flags(flags);
+
+ if (end-start + (PAGE_SIZE-1) <= SMALLEST_NTLB_ENTRIES << PAGE_SHIFT) {
+ int oldpid = get_rasid_register();
+ set_rasid_register (ASID_INSERT(mm->context));
+ start &= PAGE_MASK;
+ if (vma->vm_flags & VM_EXEC)
+ while(start < end) {
+ invalidate_itlb_mapping(start);
+ invalidate_dtlb_mapping(start);
+ start += PAGE_SIZE;
+ }
+ else
+ while(start < end) {
+ invalidate_dtlb_mapping(start);
+ start += PAGE_SIZE;
+ }
+
+ set_rasid_register(oldpid);
+ } else {
+ get_new_mmu_context(mm, asid_cache);
+ if (mm == current->active_mm)
+ set_rasid_register(ASID_INSERT(mm->context));
+ }
+ local_irq_restore(flags);
+}
+
+void flush_tlb_page (struct vm_area_struct *vma, unsigned long page)
+{
+ struct mm_struct* mm = vma->vm_mm;
+ unsigned long flags;
+ int oldpid;
+#if 0
+ printk("[tlbpage<%02lx,%08lx>]\n",
+ (unsigned long)mm->context, page);
+#endif
+
+ if(mm->context == NO_CONTEXT)
+ return;
+
+ local_save_flags(flags);
+
+ oldpid = get_rasid_register();
+
+ if (vma->vm_flags & VM_EXEC)
+ invalidate_itlb_mapping(page);
+ invalidate_dtlb_mapping(page);
+
+ set_rasid_register(oldpid);
+
+ local_irq_restore(flags);
+
+#if 0
+ flush_tlb_all();
+ return;
+#endif
+}
+
+
+#ifdef DEBUG_TLB
+
+#define USE_ITLB 0
+#define USE_DTLB 1
+
+struct way_config_t {
+ int indicies;
+ int indicies_log2;
+ int pgsz_log2;
+ int arf;
+};
+
+static struct way_config_t itlb[XCHAL_ITLB_WAYS] =
+{
+ { XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, ENTRIES),
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, ENTRIES_LOG2),
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, PAGESZ_LOG2_MIN),
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, ARF)
+ },
+ { XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, ENTRIES),
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, ENTRIES_LOG2),
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, PAGESZ_LOG2_MIN),
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, ARF)
+ },
+ { XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, ENTRIES),
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, ENTRIES_LOG2),
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, PAGESZ_LOG2_MIN),
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, ARF)
+ },
+ { XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, ENTRIES),
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, ENTRIES_LOG2),
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, PAGESZ_LOG2_MIN),
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, ARF)
+ },
+ { XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, ENTRIES),
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, ENTRIES_LOG2),
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, PAGESZ_LOG2_MIN),
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, ARF)
+ },
+ { XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, ENTRIES),
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, ENTRIES_LOG2),
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, PAGESZ_LOG2_MIN),
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, ARF)
+ },
+ { XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, ENTRIES),
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, ENTRIES_LOG2),
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, PAGESZ_LOG2_MIN),
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, ARF)
+ }
+};
+
+static struct way_config_t dtlb[XCHAL_DTLB_WAYS] =
+{
+ { XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, ENTRIES),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, ENTRIES_LOG2),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, PAGESZ_LOG2_MIN),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, ARF)
+ },
+ { XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, ENTRIES),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, ENTRIES_LOG2),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, PAGESZ_LOG2_MIN),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, ARF)
+ },
+ { XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, ENTRIES),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, ENTRIES_LOG2),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, PAGESZ_LOG2_MIN),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, ARF)
+ },
+ { XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, ENTRIES),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, ENTRIES_LOG2),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, PAGESZ_LOG2_MIN),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, ARF)
+ },
+ { XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, ENTRIES),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, ENTRIES_LOG2),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, PAGESZ_LOG2_MIN),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, ARF)
+ },
+ { XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, ENTRIES),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, ENTRIES_LOG2),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, PAGESZ_LOG2_MIN),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, ARF)
+ },
+ { XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, ENTRIES),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, ENTRIES_LOG2),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, PAGESZ_LOG2_MIN),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, ARF)
+ },
+ { XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, ENTRIES),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, ENTRIES_LOG2),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, PAGESZ_LOG2_MIN),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, ARF)
+ },
+ { XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, ENTRIES),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, ENTRIES_LOG2),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, PAGESZ_LOG2_MIN),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, ARF)
+ },
+ { XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, ENTRIES),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, ENTRIES_LOG2),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, PAGESZ_LOG2_MIN),
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, ARF)
+ }
+};
+
+/* Total number of entries: */
+#define ITLB_TOTAL_ENTRIES \
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, ENTRIES) + \
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, ENTRIES) + \
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, ENTRIES) + \
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, ENTRIES) + \
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, ENTRIES) + \
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, ENTRIES) + \
+ XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, ENTRIES)
+#define DTLB_TOTAL_ENTRIES \
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, ENTRIES) + \
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, ENTRIES) + \
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, ENTRIES) + \
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, ENTRIES) + \
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, ENTRIES) + \
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, ENTRIES) + \
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, ENTRIES) + \
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, ENTRIES) + \
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, ENTRIES) + \
+ XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, ENTRIES)
+
+
+typedef struct {
+ unsigned va;
+ unsigned pa;
+ unsigned char asid;
+ unsigned char ca;
+ unsigned char way;
+ unsigned char index;
+ unsigned char pgsz_log2; /* 0 .. 32 */
+ unsigned char type; /* 0=ITLB 1=DTLB */
+} tlb_dump_entry_t;
+
+/* Return -1 if a precedes b, +1 if a follows b, 0 if same: */
+int cmp_tlb_dump_info( tlb_dump_entry_t *a, tlb_dump_entry_t *b )
+{
+ if (a->asid < b->asid) return -1;
+ if (a->asid > b->asid) return 1;
+ if (a->va < b->va) return -1;
+ if (a->va > b->va) return 1;
+ if (a->pa < b->pa) return -1;
+ if (a->pa > b->pa) return 1;
+ if (a->ca < b->ca) return -1;
+ if (a->ca > b->ca) return 1;
+ if (a->way < b->way) return -1;
+ if (a->way > b->way) return 1;
+ if (a->index < b->index) return -1;
+ if (a->index > b->index) return 1;
+ return 0;
+}
+
+void sort_tlb_dump_info( tlb_dump_entry_t *t, int n )
+{
+ int i, j;
+ /* Simple O(n*n) sort: */
+ for (i = 0; i < n-1; i++)
+ for (j = i+1; j < n; j++)
+ if (cmp_tlb_dump_info(t+i, t+j) > 0) {
+ tlb_dump_entry_t tmp = t[i];
+ t[i] = t[j];
+ t[j] = tmp;
+ }
+}
+
+
+static tlb_dump_entry_t itlb_dump_info[ITLB_TOTAL_ENTRIES];
+static tlb_dump_entry_t dtlb_dump_info[DTLB_TOTAL_ENTRIES];
+
+
+static inline char *way_type (int type)
+{
+ return type ? "autorefill" : "non-autorefill";
+}
+
+void print_entry (struct way_config_t *way_info,
+ unsigned int way,
+ unsigned int index,
+ unsigned int virtual,
+ unsigned int translation)
+{
+ char valid_chr;
+ unsigned int va, pa, asid, ca;
+
+ va = virtual &
+ ~((1 << (way_info->pgsz_log2 + way_info->indicies_log2)) - 1);
+ asid = virtual & ((1 << XCHAL_MMU_ASID_BITS) - 1);
+ pa = translation & ~((1 << way_info->pgsz_log2) - 1);
+ ca = translation & ((1 << XCHAL_MMU_CA_BITS) - 1);
+ valid_chr = asid ? 'V' : 'I';
+
+ /* Compute and incorporate the effect of the index bits on the
+ * va. It's more useful for kernel debugging, since we always
+ * want to know the effective va anyway. */
+
+ va += index << way_info->pgsz_log2;
+
+ printk ("\t[%d,%d] (%c) vpn 0x%.8x ppn 0x%.8x asid 0x%.2x am 0x%x\n",
+ way, index, valid_chr, va, pa, asid, ca);
+}
+
+void print_itlb_entry (struct way_config_t *way_info, int way, int index)
+{
+ print_entry (way_info, way, index,
+ read_itlb_virtual (way + (index << way_info->pgsz_log2)),
+ read_itlb_translation (way + (index << way_info->pgsz_log2)));
+}
+
+void print_dtlb_entry (struct way_config_t *way_info, int way, int index)
+{
+ print_entry (way_info, way, index,
+ read_dtlb_virtual (way + (index << way_info->pgsz_log2)),
+ read_dtlb_translation (way + (index << way_info->pgsz_log2)));
+}
+
+void dump_itlb (void)
+{
+ int way, index;
+
+ printk ("\nITLB: ways = %d\n", XCHAL_ITLB_WAYS);
+
+ for (way = 0; way < XCHAL_ITLB_WAYS; way++) {
+ printk ("\nWay: %d, Entries: %d, MinPageSize: %d, Type: %s\n",
+ way, itlb[way].indicies,
+ itlb[way].pgsz_log2, way_type(itlb[way].arf));
+ for (index = 0; index < itlb[way].indicies; index++) {
+ print_itlb_entry(&itlb[way], way, index);
+ }
+ }
+}
+
+void dump_dtlb (void)
+{
+ int way, index;
+
+ printk ("\nDTLB: ways = %d\n", XCHAL_DTLB_WAYS);
+
+ for (way = 0; way < XCHAL_DTLB_WAYS; way++) {
+ printk ("\nWay: %d, Entries: %d, MinPageSize: %d, Type: %s\n",
+ way, dtlb[way].indicies,
+ dtlb[way].pgsz_log2, way_type(dtlb[way].arf));
+ for (index = 0; index < dtlb[way].indicies; index++) {
+ print_dtlb_entry(&dtlb[way], way, index);
+ }
+ }
+}
+
+void dump_tlb (tlb_dump_entry_t *tinfo, struct way_config_t *config,
+ int entries, int ways, int type, int show_invalid)
+{
+ tlb_dump_entry_t *e = tinfo;
+ int way, i;
+
+ /* Gather all info: */
+ for (way = 0; way < ways; way++) {
+ struct way_config_t *cfg = config + way;
+ for (i = 0; i < cfg->indicies; i++) {
+ unsigned wayindex = way + (i << cfg->pgsz_log2);
+ unsigned vv = (type ? read_dtlb_virtual (wayindex)
+ : read_itlb_virtual (wayindex));
+ unsigned pp = (type ? read_dtlb_translation (wayindex)
+ : read_itlb_translation (wayindex));
+
+ /* Compute and incorporate the effect of the index bits on the
+ * va. It's more useful for kernel debugging, since we always
+ * want to know the effective va anyway. */
+
+ e->va = (vv & ~((1 << (cfg->pgsz_log2 + cfg->indicies_log2)) - 1));
+ e->va += (i << cfg->pgsz_log2);
+ e->pa = (pp & ~((1 << cfg->pgsz_log2) - 1));
+ e->asid = (vv & ((1 << XCHAL_MMU_ASID_BITS) - 1));
+ e->ca = (pp & ((1 << XCHAL_MMU_CA_BITS) - 1));
+ e->way = way;
+ e->index = i;
+ e->pgsz_log2 = cfg->pgsz_log2;
+ e->type = type;
+ e++;
+ }
+ }
+#if 1
+ /* Sort by ASID and VADDR: */
+ sort_tlb_dump_info (tinfo, entries);
+#endif
+
+ /* Display all sorted info: */
+ printk ("\n%cTLB dump:\n", (type ? 'D' : 'I'));
+ for (e = tinfo, i = 0; i < entries; i++, e++) {
+#if 0
+ if (e->asid == 0 && !show_invalid)
+ continue;
+#endif
+ printk ("%c way=%d i=%d ASID=%02X V=%08X -> P=%08X CA=%X (%d %cB)\n",
+ (e->type ? 'D' : 'I'), e->way, e->index,
+ e->asid, e->va, e->pa, e->ca,
+ (1 << (e->pgsz_log2 % 10)),
+ " kMG"[e->pgsz_log2 / 10]
+ );
+ }
+}
+
+void dump_tlbs2 (int showinv)
+{
+ dump_tlb (itlb_dump_info, itlb, ITLB_TOTAL_ENTRIES, XCHAL_ITLB_WAYS, 0, showinv);
+ dump_tlb (dtlb_dump_info, dtlb, DTLB_TOTAL_ENTRIES, XCHAL_DTLB_WAYS, 1, showinv);
+}
+
+void dump_all_tlbs (void)
+{
+ dump_tlbs2 (1);
+}
+
+void dump_valid_tlbs (void)
+{
+ dump_tlbs2 (0);
+}
+
+
+void dump_tlbs (void)
+{
+ dump_itlb();
+ dump_dtlb();
+}
+
+void dump_cache_tag(int dcache, int idx)
+{
+ int w, i, s, e;
+ unsigned long tag, index;
+ unsigned long num_lines, num_ways, cache_size, line_size;
+
+ num_ways = dcache ? XCHAL_DCACHE_WAYS : XCHAL_ICACHE_WAYS;
+ cache_size = dcache ? XCHAL_DCACHE_SIZE : XCHAL_ICACHE_SIZE;
+ line_size = dcache ? XCHAL_DCACHE_LINESIZE : XCHAL_ICACHE_LINESIZE;
+
+ num_lines = cache_size / num_ways;
+
+ s = 0; e = num_lines;
+
+ if (idx >= 0)
+ e = (s = idx * line_size) + 1;
+
+ for (i = s; i < e; i+= line_size) {
+ printk("\nline %#08x:", i);
+ for (w = 0; w < num_ways; w++) {
+ index = w * num_lines + i;
+ if (dcache)
+ __asm__ __volatile__("ldct %0, %1\n\t"
+ : "=a"(tag) : "a"(index));
+ else
+ __asm__ __volatile__("lict %0, %1\n\t"
+ : "=a"(tag) : "a"(index));
+
+ printk(" %#010lx", tag);
+ }
+ }
+ printk ("\n");
+}
+
+void dump_icache(int index)
+{
+ unsigned long data, addr;
+ int w, i;
+
+ const unsigned long num_ways = XCHAL_ICACHE_WAYS;
+ const unsigned long cache_size = XCHAL_ICACHE_SIZE;
+ const unsigned long line_size = XCHAL_ICACHE_LINESIZE;
+ const unsigned long num_lines = cache_size / num_ways / line_size;
+
+ for (w = 0; w < num_ways; w++) {
+ printk ("\nWay %d", w);
+
+ for (i = 0; i < line_size; i+= 4) {
+ addr = w * num_lines + index * line_size + i;
+ __asm__ __volatile__("licw %0, %1\n\t"
+ : "=a"(data) : "a"(addr));
+ printk(" %#010lx", data);
+ }
+ }
+ printk ("\n");
+}
+
+void dump_cache_tags(void)
+{
+ printk("Instruction cache\n");
+ dump_cache_tag(0, -1);
+ printk("Data cache\n");
+ dump_cache_tag(1, -1);
+}
+
+#endif
diff --git a/arch/xtensa/platform-iss/Makefile b/arch/xtensa/platform-iss/Makefile
new file mode 100644
index 00000000000..5b394e9620e
--- /dev/null
+++ b/arch/xtensa/platform-iss/Makefile
@@ -0,0 +1,13 @@
+# $Id: Makefile,v 1.1.1.1 2002/08/28 16:10:14 aroll Exp $
+#
+# Makefile for the Xtensa Instruction Set Simulator (ISS)
+# "prom monitor" library routines under Linux.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are in the main makefile...
+
+obj-y = io.o console.o setup.o network.o
+
diff --git a/arch/xtensa/platform-iss/console.c b/arch/xtensa/platform-iss/console.c
new file mode 100644
index 00000000000..4fbddf92a92
--- /dev/null
+++ b/arch/xtensa/platform-iss/console.c
@@ -0,0 +1,300 @@
+/*
+ * arch/xtensa/platform-iss/console.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001-2005 Tensilica Inc.
+ * Authors Christian Zankel, Joe Taylor
+ */
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/major.h>
+#include <linux/param.h>
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/console.h>
+
+#include <asm/uaccess.h>
+#include <asm/irq.h>
+
+#include <xtensa/simcall.h>
+
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+
+#ifdef SERIAL_INLINE
+#define _INLINE_ inline
+#endif
+
+#define SERIAL_MAX_NUM_LINES 1
+#define SERIAL_TIMER_VALUE (20 * HZ)
+
+static struct tty_driver *serial_driver;
+static struct timer_list serial_timer;
+
+static DEFINE_SPINLOCK(timer_lock);
+
+int errno;
+
+static int __simc (int a, int b, int c, int d, int e, int f)
+{
+ int ret;
+ __asm__ __volatile__ ("simcall\n"
+ "mov %0, a2\n"
+ "mov %1, a3\n" : "=a" (ret), "=a" (errno)
+ : : "a2", "a3");
+ return ret;
+}
+
+static char *serial_version = "0.1";
+static char *serial_name = "ISS serial driver";
+
+/*
+ * This routine is called whenever a serial port is opened. It
+ * enables interrupts for a serial port, linking in its async structure into
+ * the IRQ chain. It also performs the serial-specific
+ * initialization for the tty structure.
+ */
+
+static void rs_poll(unsigned long);
+
+static int rs_open(struct tty_struct *tty, struct file * filp)
+{
+ int line = tty->index;
+
+ if ((line < 0) || (line >= SERIAL_MAX_NUM_LINES))
+ return -ENODEV;
+
+ spin_lock(&timer_lock);
+
+ if (tty->count == 1) {
+ init_timer(&serial_timer);
+ serial_timer.data = (unsigned long) tty;
+ serial_timer.function = rs_poll;
+ mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE);
+ }
+ spin_unlock(&timer_lock);
+
+ return 0;
+}
+
+
+/*
+ * ------------------------------------------------------------
+ * iss_serial_close()
+ *
+ * This routine is called when the serial port gets closed. First, we
+ * wait for the last remaining data to be sent. Then, we unlink its
+ * async structure from the interrupt chain if necessary, and we free
+ * that IRQ if nothing is left in the chain.
+ * ------------------------------------------------------------
+ */
+static void rs_close(struct tty_struct *tty, struct file * filp)
+{
+ spin_lock(&timer_lock);
+ if (tty->count == 1)
+ del_timer_sync(&serial_timer);
+ spin_unlock(&timer_lock);
+}
+
+
+static int rs_write(struct tty_struct * tty,
+ const unsigned char *buf, int count)
+{
+ /* see drivers/char/serialX.c to reference original version */
+
+ __simc (SYS_write, 1, (unsigned long)buf, count, 0, 0);
+ return count;
+}
+
+static void rs_poll(unsigned long priv)
+{
+ struct tty_struct* tty = (struct tty_struct*) priv;
+
+ struct timeval tv = { .tv_sec = 0, .tv_usec = 0 };
+ int i = 0;
+ unsigned char c;
+
+ spin_lock(&timer_lock);
+
+ while (__simc(SYS_select_one, 0, XTISS_SELECT_ONE_READ, (int)&tv,0,0)){
+ __simc (SYS_read, 0, (unsigned long)&c, 1, 0, 0);
+ tty->flip.count++;
+ *tty->flip.char_buf_ptr++ = c;
+ *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
+ i++;
+ }
+
+ if (i)
+ tty_flip_buffer_push(tty);
+
+
+ mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE);
+ spin_unlock(&timer_lock);
+}
+
+
+static void rs_put_char(struct tty_struct *tty, unsigned char ch)
+{
+ char buf[2];
+
+ if (!tty)
+ return;
+
+ buf[0] = ch;
+ buf[1] = '\0'; /* Is this NULL necessary? */
+ __simc (SYS_write, 1, (unsigned long) buf, 1, 0, 0);
+}
+
+static void rs_flush_chars(struct tty_struct *tty)
+{
+}
+
+static int rs_write_room(struct tty_struct *tty)
+{
+ /* Let's say iss can always accept 2K characters.. */
+ return 2 * 1024;
+}
+
+static int rs_chars_in_buffer(struct tty_struct *tty)
+{
+ /* the iss doesn't buffer characters */
+ return 0;
+}
+
+static void rs_hangup(struct tty_struct *tty)
+{
+ /* Stub, once again.. */
+}
+
+static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+ /* Stub, once again.. */
+}
+
+static int rs_read_proc(char *page, char **start, off_t off, int count,
+ int *eof, void *data)
+{
+ int len = 0;
+ off_t begin = 0;
+
+ len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version);
+ *eof = 1;
+
+ if (off >= len + begin)
+ return 0;
+
+ *start = page + (off - begin);
+ return ((count < begin + len - off) ? count : begin + len - off);
+}
+
+
+static struct tty_operations serial_ops = {
+ .open = rs_open,
+ .close = rs_close,
+ .write = rs_write,
+ .put_char = rs_put_char,
+ .flush_chars = rs_flush_chars,
+ .write_room = rs_write_room,
+ .chars_in_buffer = rs_chars_in_buffer,
+ .hangup = rs_hangup,
+ .wait_until_sent = rs_wait_until_sent,
+ .read_proc = rs_read_proc
+};
+
+int __init rs_init(void)
+{
+ serial_driver = alloc_tty_driver(1);
+
+ printk ("%s %s\n", serial_name, serial_version);
+
+ /* Initialize the tty_driver structure */
+
+ serial_driver->owner = THIS_MODULE;
+ serial_driver->driver_name = "iss_serial";
+ serial_driver->name = "ttyS";
+ serial_driver->major = TTY_MAJOR;
+ serial_driver->minor_start = 64;
+ serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+ serial_driver->subtype = SERIAL_TYPE_NORMAL;
+ serial_driver->init_termios = tty_std_termios;
+ serial_driver->init_termios.c_cflag =
+ B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ serial_driver->flags = TTY_DRIVER_REAL_RAW;
+
+ tty_set_operations(serial_driver, &serial_ops);
+
+ if (tty_register_driver(serial_driver))
+ panic("Couldn't register serial driver\n");
+ return 0;
+}
+
+
+static __exit void rs_exit(void)
+{
+ int error;
+
+ if ((error = tty_unregister_driver(serial_driver)))
+ printk("ISS_SERIAL: failed to unregister serial driver (%d)\n",
+ error);
+ put_tty_driver(serial_driver);
+}
+
+
+/* We use `late_initcall' instead of just `__initcall' as a workaround for
+ * the fact that (1) simcons_tty_init can't be called before tty_init,
+ * (2) tty_init is called via `module_init', (3) if statically linked,
+ * module_init == device_init, and (4) there's no ordering of init lists.
+ * We can do this easily because simcons is always statically linked, but
+ * other tty drivers that depend on tty_init and which must use
+ * `module_init' to declare their init routines are likely to be broken.
+ */
+
+late_initcall(rs_init);
+
+
+#ifdef CONFIG_SERIAL_CONSOLE
+
+static void iss_console_write(struct console *co, const char *s, unsigned count)
+{
+ int len = strlen(s);
+
+ if (s != 0 && *s != 0)
+ __simc (SYS_write, 1, (unsigned long)s,
+ count < len ? count : len,0,0);
+}
+
+static struct tty_driver* iss_console_device(struct console *c, int *index)
+{
+ *index = c->index;
+ return serial_driver;
+}
+
+
+static struct console sercons = {
+ .name = "ttyS",
+ .write = iss_console_write,
+ .device = iss_console_device,
+ .flags = CON_PRINTBUFFER,
+ .index = -1
+};
+
+static int __init iss_console_init(void)
+{
+ register_console(&sercons);
+ return 0;
+}
+
+console_initcall(iss_console_init);
+
+#endif /* CONFIG_SERIAL_CONSOLE */
+
diff --git a/arch/xtensa/platform-iss/io.c b/arch/xtensa/platform-iss/io.c
new file mode 100644
index 00000000000..5b161a5cb65
--- /dev/null
+++ b/arch/xtensa/platform-iss/io.c
@@ -0,0 +1,32 @@
+/* This file isn't really needed right now. */
+
+#if 0
+
+#include <asm/io.h>
+#include <xtensa/simcall.h>
+
+extern int __simc ();
+
+
+char iss_serial_getc()
+{
+ char c;
+ __simc( SYS_read, 0, &c, 1 );
+ return c;
+}
+
+void iss_serial_putc( char c )
+{
+ __simc( SYS_write, 1, &c, 1 );
+}
+
+void iss_serial_puts( char *s )
+{
+ if( s != 0 && *s != 0 )
+ __simc( SYS_write, 1, s, strlen(s) );
+}
+
+/*#error Need I/O ports to specific hardware!*/
+
+#endif
+
diff --git a/arch/xtensa/platform-iss/network.c b/arch/xtensa/platform-iss/network.c
new file mode 100644
index 00000000000..498d7dced1f
--- /dev/null
+++ b/arch/xtensa/platform-iss/network.c
@@ -0,0 +1,855 @@
+/*
+ *
+ * arch/xtensa/platform-iss/network.c
+ *
+ * Platform specific initialization.
+ *
+ * Authors: Chris Zankel <chris@zankel.net>
+ * Based on work form the UML team.
+ *
+ * Copyright 2005 Tensilica 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 <linux/config.h>
+#include <linux/list.h>
+#include <linux/irq.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/if_ether.h>
+#include <linux/inetdevice.h>
+#include <linux/init.h>
+#include <linux/if_tun.h>
+#include <linux/etherdevice.h>
+#include <linux/interrupt.h>
+#include <linux/ioctl.h>
+#include <linux/bootmem.h>
+#include <linux/ethtool.h>
+#include <linux/rtnetlink.h>
+#include <linux/timer.h>
+
+#include <xtensa/simcall.h>
+
+#define DRIVER_NAME "iss-netdev"
+#define ETH_MAX_PACKET 1500
+#define ETH_HEADER_OTHER 14
+#define ISS_NET_TIMER_VALUE (2 * HZ)
+
+
+static DEFINE_SPINLOCK(opened_lock);
+static LIST_HEAD(opened);
+
+static DEFINE_SPINLOCK(devices_lock);
+static LIST_HEAD(devices);
+
+/* ------------------------------------------------------------------------- */
+
+/* We currently only support the TUNTAP transport protocol. */
+
+#define TRANSPORT_TUNTAP_NAME "tuntap"
+#define TRANSPORT_TUNTAP_MTU ETH_MAX_PACKET
+
+struct tuntap_info {
+ char dev_name[IFNAMSIZ];
+ int fixed_config;
+ unsigned char gw[ETH_ALEN];
+ int fd;
+};
+
+/* ------------------------------------------------------------------------- */
+
+
+/* This structure contains out private information for the driver. */
+
+struct iss_net_private {
+
+ struct list_head device_list;
+ struct list_head opened_list;
+
+ spinlock_t lock;
+ struct net_device *dev;
+ struct platform_device pdev;
+ struct timer_list tl;
+ struct net_device_stats stats;
+
+ struct timer_list timer;
+ unsigned int timer_val;
+
+ int index;
+ int mtu;
+
+ unsigned char mac[ETH_ALEN];
+ int have_mac;
+
+ struct {
+ union {
+ struct tuntap_info tuntap;
+ } info;
+
+ int (*open)(struct iss_net_private *lp);
+ void (*close)(struct iss_net_private *lp);
+ int (*read)(struct iss_net_private *lp, struct sk_buff **skb);
+ int (*write)(struct iss_net_private *lp, struct sk_buff **skb);
+ unsigned short (*protocol)(struct sk_buff *skb);
+ int (*poll)(struct iss_net_private *lp);
+ } tp;
+
+};
+
+/* ======================= ISS SIMCALL INTERFACE =========================== */
+
+/* Note: __simc must _not_ be declared inline! */
+
+static int errno;
+
+static int __simc (int a, int b, int c, int d, int e, int f)
+{
+ int ret;
+ __asm__ __volatile__ ("simcall\n"
+ "mov %0, a2\n"
+ "mov %1, a3\n" : "=a" (ret), "=a" (errno)
+ : : "a2", "a3");
+ return ret;
+}
+
+static int inline simc_open(char *file, int flags, int mode)
+{
+ return __simc(SYS_open, (int) file, flags, mode, 0, 0);
+}
+
+static int inline simc_close(int fd)
+{
+ return __simc(SYS_close, fd, 0, 0, 0, 0);
+}
+
+static int inline simc_ioctl(int fd, int request, void *arg)
+{
+ return __simc(SYS_ioctl, fd, request, (int) arg, 0, 0);
+}
+
+static int inline simc_read(int fd, void *buf, size_t count)
+{
+ return __simc(SYS_read, fd, (int) buf, count, 0, 0);
+}
+
+static int inline simc_write(int fd, void *buf, size_t count)
+{
+ return __simc(SYS_write, fd, (int) buf, count, 0, 0);
+}
+
+static int inline simc_poll(int fd)
+{
+ struct timeval tv = { .tv_sec = 0, .tv_usec = 0 };
+
+ return __simc(SYS_select_one, fd, XTISS_SELECT_ONE_READ, (int)&tv,0,0);
+}
+
+/* ================================ HELPERS ================================ */
+
+
+static char *split_if_spec(char *str, ...)
+{
+ char **arg, *end;
+ va_list ap;
+
+ va_start(ap, str);
+ while ((arg = va_arg(ap, char**)) != NULL) {
+ if (*str == '\0')
+ return NULL;
+ end = strchr(str, ',');
+ if (end != str)
+ *arg = str;
+ if (end == NULL)
+ return NULL;
+ *end ++ = '\0';
+ str = end;
+ }
+ va_end(ap);
+ return str;
+}
+
+
+#if 0
+/* Adjust SKB. */
+
+struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra)
+{
+ if ((skb != NULL) && (skb_tailroom(skb) < extra)) {
+ struct sk_buff *skb2;
+
+ skb2 = skb_copy_expand(skb, 0, extra, GFP_ATOMIC);
+ dev_kfree_skb(skb);
+ skb = skb2;
+ }
+ if (skb != NULL)
+ skb_put(skb, extra);
+
+ return skb;
+}
+#endif
+
+/* Return the IP address as a string for a given device. */
+
+static void dev_ip_addr(void *d, char *buf, char *bin_buf)
+{
+ struct net_device *dev = d;
+ struct in_device *ip = dev->ip_ptr;
+ struct in_ifaddr *in;
+ u32 addr;
+
+ if ((ip == NULL) || ((in = ip->ifa_list) == NULL)) {
+ printk(KERN_WARNING "Device not assigned an IP address!\n");
+ return;
+ }
+
+ addr = in->ifa_address;
+ sprintf(buf, "%d.%d.%d.%d", addr & 0xff, (addr >> 8) & 0xff,
+ (addr >> 16) & 0xff, addr >> 24);
+
+ if (bin_buf) {
+ bin_buf[0] = addr & 0xff;
+ bin_buf[1] = (addr >> 8) & 0xff;
+ bin_buf[2] = (addr >> 16) & 0xff;
+ bin_buf[3] = addr >> 24;
+ }
+}
+
+/* Set Ethernet address of the specified device. */
+
+static void inline set_ether_mac(void *d, unsigned char *addr)
+{
+ struct net_device *dev = d;
+ memcpy(dev->dev_addr, addr, ETH_ALEN);
+}
+
+
+/* ======================= TUNTAP TRANSPORT INTERFACE ====================== */
+
+static int tuntap_open(struct iss_net_private *lp)
+{
+ struct ifreq ifr;
+ char *dev_name = lp->tp.info.tuntap.dev_name;
+ int err = -EINVAL;
+ int fd;
+
+ /* We currently only support a fixed configuration. */
+
+ if (!lp->tp.info.tuntap.fixed_config)
+ return -EINVAL;
+
+ if ((fd = simc_open("/dev/net/tun", 02, 0)) < 0) { /* O_RDWR */
+ printk("Failed to open /dev/net/tun, returned %d "
+ "(errno = %d)\n", fd, errno);
+ return fd;
+ }
+
+ memset(&ifr, 0, sizeof ifr);
+ ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+ strlcpy(ifr.ifr_name, dev_name, sizeof ifr.ifr_name - 1);
+
+ if ((err = simc_ioctl(fd, TUNSETIFF, (void*) &ifr)) < 0) {
+ printk("Failed to set interface, returned %d "
+ "(errno = %d)\n", err, errno);
+ simc_close(fd);
+ return err;
+ }
+
+ lp->tp.info.tuntap.fd = fd;
+ return err;
+}
+
+static void tuntap_close(struct iss_net_private *lp)
+{
+#if 0
+ if (lp->tp.info.tuntap.fixed_config)
+ iter_addresses(lp->tp.info.tuntap.dev, close_addr, lp->host.dev_name);
+#endif
+ simc_close(lp->tp.info.tuntap.fd);
+ lp->tp.info.tuntap.fd = -1;
+}
+
+static int tuntap_read (struct iss_net_private *lp, struct sk_buff **skb)
+{
+#if 0
+ *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER);
+ if (*skb == NULL)
+ return -ENOMEM;
+#endif
+
+ return simc_read(lp->tp.info.tuntap.fd,
+ (*skb)->data, (*skb)->dev->mtu + ETH_HEADER_OTHER);
+}
+
+static int tuntap_write (struct iss_net_private *lp, struct sk_buff **skb)
+{
+ return simc_write(lp->tp.info.tuntap.fd, (*skb)->data, (*skb)->len);
+}
+
+unsigned short tuntap_protocol(struct sk_buff *skb)
+{
+ return eth_type_trans(skb, skb->dev);
+}
+
+static int tuntap_poll(struct iss_net_private *lp)
+{
+ return simc_poll(lp->tp.info.tuntap.fd);
+}
+
+/*
+ * Currently only a device name is supported.
+ * ethX=tuntap[,[mac address][,[device name]]]
+ */
+
+static int tuntap_probe(struct iss_net_private *lp, int index, char *init)
+{
+ const int len = strlen(TRANSPORT_TUNTAP_NAME);
+ char *dev_name = NULL, *mac_str = NULL, *rem = NULL;
+
+ /* Transport should be 'tuntap': ethX=tuntap,mac,dev_name */
+
+ if (strncmp(init, TRANSPORT_TUNTAP_NAME, len))
+ return 0;
+
+ if (*(init += strlen(TRANSPORT_TUNTAP_NAME)) == ',') {
+ if ((rem=split_if_spec(init+1, &mac_str, &dev_name)) != NULL) {
+ printk("Extra garbage on specification : '%s'\n", rem);
+ return 0;
+ }
+ } else if (*init != '\0') {
+ printk("Invalid argument: %s. Skipping device!\n", init);
+ return 0;
+ }
+
+ if (dev_name) {
+ strncpy(lp->tp.info.tuntap.dev_name, dev_name,
+ sizeof lp->tp.info.tuntap.dev_name);
+ lp->tp.info.tuntap.fixed_config = 1;
+ } else
+ strcpy(lp->tp.info.tuntap.dev_name, TRANSPORT_TUNTAP_NAME);
+
+
+#if 0
+ if (setup_etheraddr(mac_str, lp->mac))
+ lp->have_mac = 1;
+#endif
+ lp->mtu = TRANSPORT_TUNTAP_MTU;
+
+ //lp->info.tuntap.gate_addr = gate_addr;
+
+ lp->tp.info.tuntap.fd = -1;
+
+ lp->tp.open = tuntap_open;
+ lp->tp.close = tuntap_close;
+ lp->tp.read = tuntap_read;
+ lp->tp.write = tuntap_write;
+ lp->tp.protocol = tuntap_protocol;
+ lp->tp.poll = tuntap_poll;
+
+ printk("TUN/TAP backend - ");
+#if 0
+ if (lp->host.gate_addr != NULL)
+ printk("IP = %s", lp->host.gate_addr);
+#endif
+ printk("\n");
+
+ return 1;
+}
+
+/* ================================ ISS NET ================================ */
+
+static int iss_net_rx(struct net_device *dev)
+{
+ struct iss_net_private *lp = dev->priv;
+ int pkt_len;
+ struct sk_buff *skb;
+
+ /* Check if there is any new data. */
+
+ if (lp->tp.poll(lp) == 0)
+ return 0;
+
+ /* Try to allocate memory, if it fails, try again next round. */
+
+ if ((skb = dev_alloc_skb(dev->mtu + 2 + ETH_HEADER_OTHER)) == NULL) {
+ lp->stats.rx_dropped++;
+ return 0;
+ }
+
+ skb_reserve(skb, 2);
+
+ /* Setup skb */
+
+ skb->dev = dev;
+ skb->mac.raw = skb->data;
+ pkt_len = lp->tp.read(lp, &skb);
+ skb_put(skb, pkt_len);
+
+ if (pkt_len > 0) {
+ skb_trim(skb, pkt_len);
+ skb->protocol = lp->tp.protocol(skb);
+ // netif_rx(skb);
+ netif_rx_ni(skb);
+
+ lp->stats.rx_bytes += skb->len;
+ lp->stats.rx_packets++;
+ return pkt_len;
+ }
+ kfree_skb(skb);
+ return pkt_len;
+}
+
+static int iss_net_poll(void)
+{
+ struct list_head *ele;
+ int err, ret = 0;
+
+ spin_lock(&opened_lock);
+
+ list_for_each(ele, &opened) {
+ struct iss_net_private *lp;
+
+ lp = list_entry(ele, struct iss_net_private, opened_list);
+
+ if (!netif_running(lp->dev))
+ break;
+
+ spin_lock(&lp->lock);
+
+ while ((err = iss_net_rx(lp->dev)) > 0)
+ ret++;
+
+ spin_unlock(&lp->lock);
+
+ if (err < 0) {
+ printk(KERN_ERR "Device '%s' read returned %d, "
+ "shutting it down\n", lp->dev->name, err);
+ dev_close(lp->dev);
+ } else {
+ // FIXME reactivate_fd(lp->fd, ISS_ETH_IRQ);
+ }
+ }
+
+ spin_unlock(&opened_lock);
+ return ret;
+}
+
+
+static void iss_net_timer(unsigned long priv)
+{
+ struct iss_net_private* lp = (struct iss_net_private*) priv;
+
+ spin_lock(&lp->lock);
+
+ iss_net_poll();
+
+ mod_timer(&lp->timer, jiffies + lp->timer_val);
+
+ spin_unlock(&lp->lock);
+}
+
+
+static int iss_net_open(struct net_device *dev)
+{
+ struct iss_net_private *lp = dev->priv;
+ char addr[sizeof "255.255.255.255\0"];
+ int err;
+
+ spin_lock(&lp->lock);
+
+ if ((err = lp->tp.open(lp)) < 0)
+ goto out;
+
+ if (!lp->have_mac) {
+ dev_ip_addr(dev, addr, &lp->mac[2]);
+ set_ether_mac(dev, lp->mac);
+ }
+
+ netif_start_queue(dev);
+
+ /* clear buffer - it can happen that the host side of the interface
+ * is full when we gethere. In this case, new data is never queued,
+ * SIGIOs never arrive, and the net never works.
+ */
+ while ((err = iss_net_rx(dev)) > 0)
+ ;
+
+ spin_lock(&opened_lock);
+ list_add(&lp->opened_list, &opened);
+ spin_unlock(&opened_lock);
+
+ init_timer(&lp->timer);
+ lp->timer_val = ISS_NET_TIMER_VALUE;
+ lp->timer.data = (unsigned long) lp;
+ lp->timer.function = iss_net_timer;
+ mod_timer(&lp->timer, jiffies + lp->timer_val);
+
+out:
+ spin_unlock(&lp->lock);
+ return err;
+}
+
+static int iss_net_close(struct net_device *dev)
+{
+ struct iss_net_private *lp = dev->priv;
+printk("iss_net_close!\n");
+ netif_stop_queue(dev);
+ spin_lock(&lp->lock);
+
+ spin_lock(&opened_lock);
+ list_del(&opened);
+ spin_unlock(&opened_lock);
+
+ del_timer_sync(&lp->timer);
+
+ lp->tp.close(lp);
+
+ spin_unlock(&lp->lock);
+ return 0;
+}
+
+static int iss_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct iss_net_private *lp = dev->priv;
+ unsigned long flags;
+ int len;
+
+ netif_stop_queue(dev);
+ spin_lock_irqsave(&lp->lock, flags);
+
+ len = lp->tp.write(lp, &skb);
+
+ if (len == skb->len) {
+ lp->stats.tx_packets++;
+ lp->stats.tx_bytes += skb->len;
+ dev->trans_start = jiffies;
+ netif_start_queue(dev);
+
+ /* this is normally done in the interrupt when tx finishes */
+ netif_wake_queue(dev);
+
+ } else if (len == 0) {
+ netif_start_queue(dev);
+ lp->stats.tx_dropped++;
+
+ } else {
+ netif_start_queue(dev);
+ printk(KERN_ERR "iss_net_start_xmit: failed(%d)\n", len);
+ }
+
+ spin_unlock_irqrestore(&lp->lock, flags);
+
+ dev_kfree_skb(skb);
+ return 0;
+}
+
+
+static struct net_device_stats *iss_net_get_stats(struct net_device *dev)
+{
+ struct iss_net_private *lp = dev->priv;
+ return &lp->stats;
+}
+
+static void iss_net_set_multicast_list(struct net_device *dev)
+{
+#if 0
+ if (dev->flags & IFF_PROMISC)
+ return;
+ else if (dev->mc_count)
+ dev->flags |= IFF_ALLMULTI;
+ else
+ dev->flags &= ~IFF_ALLMULTI;
+#endif
+}
+
+static void iss_net_tx_timeout(struct net_device *dev)
+{
+#if 0
+ dev->trans_start = jiffies;
+ netif_wake_queue(dev);
+#endif
+}
+
+static int iss_net_set_mac(struct net_device *dev, void *addr)
+{
+#if 0
+ struct iss_net_private *lp = dev->priv;
+ struct sockaddr *hwaddr = addr;
+
+ spin_lock(&lp->lock);
+ memcpy(dev->dev_addr, hwaddr->sa_data, ETH_ALEN);
+ spin_unlock(&lp->lock);
+#endif
+
+ return 0;
+}
+
+static int iss_net_change_mtu(struct net_device *dev, int new_mtu)
+{
+#if 0
+ struct iss_net_private *lp = dev->priv;
+ int err = 0;
+
+ spin_lock(&lp->lock);
+
+ // FIXME not needed new_mtu = transport_set_mtu(new_mtu, &lp->user);
+
+ if (new_mtu < 0)
+ err = new_mtu;
+ else
+ dev->mtu = new_mtu;
+
+ spin_unlock(&lp->lock);
+ return err;
+#endif
+ return -EINVAL;
+}
+
+static int iss_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+#if 0
+ static const struct ethtool_drvinfo info = {
+ .cmd = ETHTOOL_GDRVINFO,
+ .driver = DRIVER_NAME,
+ .version = "42",
+ };
+ void *useraddr;
+ u32 ethcmd;
+
+ switch (cmd) {
+ case SIOCETHTOOL:
+ useraddr = ifr->ifr_data;
+ if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
+ return -EFAULT;
+
+ switch (ethcmd) {
+ case ETHTOOL_GDRVINFO:
+ if (copy_to_user(useraddr, &info, sizeof(info)))
+ return -EFAULT;
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+ default:
+ return -EINVAL;
+ }
+#endif
+ return -EINVAL;
+}
+
+void iss_net_user_timer_expire(unsigned long _conn)
+{
+}
+
+
+static struct device_driver iss_net_driver = {
+ .name = DRIVER_NAME,
+ .bus = &platform_bus_type,
+};
+
+static int driver_registered;
+
+static int iss_net_configure(int index, char *init)
+{
+ struct net_device *dev;
+ struct iss_net_private *lp;
+ int err;
+
+ if ((dev = alloc_etherdev(sizeof *lp)) == NULL) {
+ printk(KERN_ERR "eth_configure: failed to allocate device\n");
+ return 1;
+ }
+
+ /* Initialize private element. */
+
+ lp = dev->priv;
+ *lp = ((struct iss_net_private) {
+ .device_list = LIST_HEAD_INIT(lp->device_list),
+ .opened_list = LIST_HEAD_INIT(lp->opened_list),
+ .lock = SPIN_LOCK_UNLOCKED,
+ .dev = dev,
+ .index = index,
+ //.fd = -1,
+ .mac = { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0 },
+ .have_mac = 0,
+ });
+
+ /*
+ * Try all transport protocols.
+ * Note: more protocols can be added by adding '&& !X_init(lp, eth)'.
+ */
+
+ if (!tuntap_probe(lp, index, init)) {
+ printk("Invalid arguments. Skipping device!\n");
+ goto errout;
+ }
+
+ printk(KERN_INFO "Netdevice %d ", index);
+ if (lp->have_mac)
+ printk("(%02x:%02x:%02x:%02x:%02x:%02x) ",
+ lp->mac[0], lp->mac[1],
+ lp->mac[2], lp->mac[3],
+ lp->mac[4], lp->mac[5]);
+ printk(": ");
+
+ /* sysfs register */
+
+ if (!driver_registered) {
+ driver_register(&iss_net_driver);
+ driver_registered = 1;
+ }
+
+ spin_lock(&devices_lock);
+ list_add(&lp->device_list, &devices);
+ spin_unlock(&devices_lock);
+
+ lp->pdev.id = index;
+ lp->pdev.name = DRIVER_NAME;
+ platform_device_register(&lp->pdev);
+ SET_NETDEV_DEV(dev,&lp->pdev.dev);
+
+ /*
+ * If this name ends up conflicting with an existing registered
+ * netdevice, that is OK, register_netdev{,ice}() will notice this
+ * and fail.
+ */
+ snprintf(dev->name, sizeof dev->name, "eth%d", index);
+
+ dev->mtu = lp->mtu;
+ dev->open = iss_net_open;
+ dev->hard_start_xmit = iss_net_start_xmit;
+ dev->stop = iss_net_close;
+ dev->get_stats = iss_net_get_stats;
+ dev->set_multicast_list = iss_net_set_multicast_list;
+ dev->tx_timeout = iss_net_tx_timeout;
+ dev->set_mac_address = iss_net_set_mac;
+ dev->change_mtu = iss_net_change_mtu;
+ dev->do_ioctl = iss_net_ioctl;
+ dev->watchdog_timeo = (HZ >> 1);
+ dev->irq = -1;
+
+ rtnl_lock();
+ err = register_netdevice(dev);
+ rtnl_unlock();
+
+ if (err) {
+ printk("Error registering net device!\n");
+ /* XXX: should we call ->remove() here? */
+ free_netdev(dev);
+ return 1;
+ }
+
+ init_timer(&lp->tl);
+ lp->tl.function = iss_net_user_timer_expire;
+
+#if 0
+ if (lp->have_mac)
+ set_ether_mac(dev, lp->mac);
+#endif
+ return 0;
+
+errout:
+ // FIXME: unregister; free, etc..
+ return -EIO;
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Filled in during early boot */
+
+struct list_head eth_cmd_line = LIST_HEAD_INIT(eth_cmd_line);
+
+struct iss_net_init {
+ struct list_head list;
+ char *init; /* init string */
+ int index;
+};
+
+/*
+ * Parse the command line and look for 'ethX=...' fields, and register all
+ * those fields. They will be later initialized in iss_net_init.
+ */
+
+#define ERR KERN_ERR "iss_net_setup: "
+
+static int iss_net_setup(char *str)
+{
+ struct iss_net_private *device = NULL;
+ struct iss_net_init *new;
+ struct list_head *ele;
+ char *end;
+ int n;
+
+ n = simple_strtoul(str, &end, 0);
+ if (end == str) {
+ printk(ERR "Failed to parse '%s'\n", str);
+ return 1;
+ }
+ if (n < 0) {
+ printk(ERR "Device %d is negative\n", n);
+ return 1;
+ }
+ if (*(str = end) != '=') {
+ printk(ERR "Expected '=' after device number\n");
+ return 1;
+ }
+
+ spin_lock(&devices_lock);
+
+ list_for_each(ele, &devices) {
+ device = list_entry(ele, struct iss_net_private, device_list);
+ if (device->index == n)
+ break;
+ }
+
+ spin_unlock(&devices_lock);
+
+ if (device && device->index == n) {
+ printk(ERR "Device %d already configured\n", n);
+ return 1;
+ }
+
+ if ((new = alloc_bootmem(sizeof new)) == NULL) {
+ printk("Alloc_bootmem failed\n");
+ return 1;
+ }
+
+ INIT_LIST_HEAD(&new->list);
+ new->index = n;
+ new->init = str + 1;
+
+ list_add_tail(&new->list, &eth_cmd_line);
+ return 1;
+}
+
+#undef ERR
+
+__setup("eth", iss_net_setup);
+
+/*
+ * Initialize all ISS Ethernet devices previously registered in iss_net_setup.
+ */
+
+static int iss_net_init(void)
+{
+ struct list_head *ele, *next;
+
+ /* Walk through all Ethernet devices specified in the command line. */
+
+ list_for_each_safe(ele, next, &eth_cmd_line) {
+ struct iss_net_init *eth;
+ eth = list_entry(ele, struct iss_net_init, list);
+ iss_net_configure(eth->index, eth->init);
+ }
+
+ return 1;
+}
+
+module_init(iss_net_init);
+
diff --git a/arch/xtensa/platform-iss/setup.c b/arch/xtensa/platform-iss/setup.c
new file mode 100644
index 00000000000..2e6dcbf0cc0
--- /dev/null
+++ b/arch/xtensa/platform-iss/setup.c
@@ -0,0 +1,112 @@
+/*
+ *
+ * arch/xtensa/platform-iss/setup.c
+ *
+ * Platform specific initialization.
+ *
+ * Authors: Chris Zankel <chris@zankel.net>
+ * Joe Taylor <joe@tensilica.com>
+ *
+ * Copyright 2001 - 2005 Tensilica 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 <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/blkdev.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/stringify.h>
+#include <linux/notifier.h>
+
+#include <asm/platform.h>
+#include <asm/bootparam.h>
+
+
+void __init platform_init(bp_tag_t* bootparam)
+{
+
+}
+
+void platform_halt(void)
+{
+ printk (" ** Called platform_halt(), looping forever! **\n");
+ while (1);
+}
+
+void platform_power_off(void)
+{
+ printk (" ** Called platform_power_off(), looping forever! **\n");
+ while (1);
+}
+void platform_restart(void)
+{
+ /* Flush and reset the mmu, simulate a processor reset, and
+ * jump to the reset vector. */
+
+ __asm__ __volatile__("movi a2, 15\n\t"
+ "wsr a2, " __stringify(ICOUNTLEVEL) "\n\t"
+ "movi a2, 0\n\t"
+ "wsr a2, " __stringify(ICOUNT) "\n\t"
+ "wsr a2, " __stringify(IBREAKENABLE) "\n\t"
+ "wsr a2, " __stringify(LCOUNT) "\n\t"
+ "movi a2, 0x1f\n\t"
+ "wsr a2, " __stringify(PS) "\n\t"
+ "isync\n\t"
+ "jx %0\n\t"
+ :
+ : "a" (XCHAL_RESET_VECTOR_VADDR)
+ : "a2");
+
+ /* control never gets here */
+}
+
+extern void iss_net_poll(void);
+
+const char twirl[]="|/-\\|/-\\";
+
+void platform_heartbeat(void)
+{
+#if 0
+ static int i = 0, j = 0;
+
+ if (--i < 0) {
+ i = 99;
+ printk("\r%c\r", twirl[j++]);
+ if (j == 8)
+ j = 0;
+ }
+#endif
+}
+
+
+
+static int
+iss_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+ __asm__ __volatile__("movi a2, -1; simcall\n");
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block iss_panic_block = {
+ iss_panic_event,
+ NULL,
+ 0
+};
+
+void __init platform_setup(char **p_cmdline)
+{
+ notifier_chain_register(&panic_notifier_list, &iss_panic_block);
+}
diff --git a/crypto/crypto_null.c b/crypto/crypto_null.c
index f691d31fa9e..3fcf6e887e8 100644
--- a/crypto/crypto_null.c
+++ b/crypto/crypto_null.c
@@ -21,6 +21,7 @@
#include <linux/mm.h>
#include <asm/scatterlist.h>
#include <linux/crypto.h>
+#include <linux/string.h>
#define NULL_KEY_SIZE 0
#define NULL_BLOCK_SIZE 1
@@ -28,11 +29,13 @@
static int null_compress(void *ctx, const u8 *src, unsigned int slen,
u8 *dst, unsigned int *dlen)
-{ return 0; }
-
-static int null_decompress(void *ctx, const u8 *src, unsigned int slen,
- u8 *dst, unsigned int *dlen)
-{ return 0; }
+{
+ if (slen > *dlen)
+ return -EINVAL;
+ memcpy(dst, src, slen);
+ *dlen = slen;
+ return 0;
+}
static void null_init(void *ctx)
{ }
@@ -47,11 +50,10 @@ static int null_setkey(void *ctx, const u8 *key,
unsigned int keylen, u32 *flags)
{ return 0; }
-static void null_encrypt(void *ctx, u8 *dst, const u8 *src)
-{ }
-
-static void null_decrypt(void *ctx, u8 *dst, const u8 *src)
-{ }
+static void null_crypt(void *ctx, u8 *dst, const u8 *src)
+{
+ memcpy(dst, src, NULL_BLOCK_SIZE);
+}
static struct crypto_alg compress_null = {
.cra_name = "compress_null",
@@ -62,7 +64,7 @@ static struct crypto_alg compress_null = {
.cra_list = LIST_HEAD_INIT(compress_null.cra_list),
.cra_u = { .compress = {
.coa_compress = null_compress,
- .coa_decompress = null_decompress } }
+ .coa_decompress = null_compress } }
};
static struct crypto_alg digest_null = {
@@ -90,8 +92,8 @@ static struct crypto_alg cipher_null = {
.cia_min_keysize = NULL_KEY_SIZE,
.cia_max_keysize = NULL_KEY_SIZE,
.cia_setkey = null_setkey,
- .cia_encrypt = null_encrypt,
- .cia_decrypt = null_decrypt } }
+ .cia_encrypt = null_crypt,
+ .cia_decrypt = null_crypt } }
};
MODULE_ALIAS("compress_null");
diff --git a/crypto/internal.h b/crypto/internal.h
index e68e43886d3..964b9a60ca2 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -38,7 +38,7 @@ static inline void crypto_kunmap(void *vaddr, int out)
static inline void crypto_yield(struct crypto_tfm *tfm)
{
- if (!in_softirq())
+ if (!in_atomic())
cond_resched();
}
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 92b0352c8e9..bd7524cfff3 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -1,4 +1,4 @@
-/*
+/*
* Quick & dirty crypto testing module.
*
* This will only exist until we have a better testing mechanism
@@ -9,11 +9,12 @@
*
* 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)
+ * Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
- * 14 - 09 - 2003
- * Rewritten by Kartikey Mahendra Bhatt
+ * 2004-08-09 Added cipher speed tests (Reyk Floeter <reyk@vantronix.net>)
+ * 2003-09-14 Rewritten by Kartikey Mahendra Bhatt
+ *
*/
#include <linux/init.h>
@@ -25,12 +26,15 @@
#include <linux/crypto.h>
#include <linux/highmem.h>
#include <linux/moduleparam.h>
+#include <linux/jiffies.h>
+#include <linux/timex.h>
+#include <linux/interrupt.h>
#include "tcrypt.h"
/*
* Need to kmalloc() memory for testing kmap().
*/
-#define TVMEMSIZE 4096
+#define TVMEMSIZE 16384
#define XBUFSIZE 32768
/*
@@ -55,19 +59,23 @@
static unsigned int IDX[8] = { IDX1, IDX2, IDX3, IDX4, IDX5, IDX6, IDX7, IDX8 };
+/*
+ * Used by test_cipher_speed()
+ */
+static unsigned int sec;
+
static int mode;
static char *xbuf;
static char *tvmem;
static char *check[] = {
"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
- "twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6",
- "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
+ "twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6",
+ "arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
"khazad", "wp512", "wp384", "wp256", "tnepres", NULL
};
-static void
-hexdump(unsigned char *buf, unsigned int len)
+static void hexdump(unsigned char *buf, unsigned int len)
{
while (len--)
printk("%02x", *buf++);
@@ -75,29 +83,29 @@ hexdump(unsigned char *buf, unsigned int len)
printk("\n");
}
-static void
-test_hash (char * algo, struct hash_testvec * template, unsigned int tcount)
+static void test_hash(char *algo, struct hash_testvec *template,
+ unsigned int tcount)
{
- char *p;
- unsigned int i, j, k, temp;
- struct scatterlist sg[8];
- char result[64];
- struct crypto_tfm *tfm;
- struct hash_testvec *hash_tv;
- unsigned int tsize;
-
- printk("\ntesting %s\n", algo);
-
- tsize = sizeof (struct hash_testvec);
+ char *p;
+ unsigned int i, j, k, temp;
+ struct scatterlist sg[8];
+ char result[64];
+ struct crypto_tfm *tfm;
+ struct hash_testvec *hash_tv;
+ unsigned int tsize;
+
+ printk("\ntesting %s\n", algo);
+
+ tsize = sizeof(struct hash_testvec);
tsize *= tcount;
-
+
if (tsize > TVMEMSIZE) {
printk("template (%u) too big for tvmem (%u)\n", tsize, TVMEMSIZE);
return;
}
memcpy(tvmem, template, tsize);
- hash_tv = (void *) tvmem;
+ hash_tv = (void *)tvmem;
tfm = crypto_alloc_tfm(algo, 0);
if (tfm == NULL) {
printk("failed to load transform for %s\n", algo);
@@ -105,70 +113,71 @@ test_hash (char * algo, struct hash_testvec * template, unsigned int tcount)
}
for (i = 0; i < tcount; i++) {
- printk ("test %u:\n", i + 1);
- memset (result, 0, 64);
+ printk("test %u:\n", i + 1);
+ memset(result, 0, 64);
p = hash_tv[i].plaintext;
- sg[0].page = virt_to_page (p);
- sg[0].offset = offset_in_page (p);
+ sg[0].page = virt_to_page(p);
+ sg[0].offset = offset_in_page(p);
sg[0].length = hash_tv[i].psize;
- crypto_digest_init (tfm);
+ crypto_digest_init(tfm);
if (tfm->crt_u.digest.dit_setkey) {
- crypto_digest_setkey (tfm, hash_tv[i].key,
- hash_tv[i].ksize);
+ crypto_digest_setkey(tfm, hash_tv[i].key,
+ hash_tv[i].ksize);
}
- crypto_digest_update (tfm, sg, 1);
- crypto_digest_final (tfm, result);
+ crypto_digest_update(tfm, sg, 1);
+ crypto_digest_final(tfm, result);
- hexdump (result, crypto_tfm_alg_digestsize (tfm));
+ hexdump(result, crypto_tfm_alg_digestsize(tfm));
printk("%s\n",
- memcmp(result, hash_tv[i].digest,
- crypto_tfm_alg_digestsize(tfm)) ? "fail" :
- "pass");
+ memcmp(result, hash_tv[i].digest,
+ crypto_tfm_alg_digestsize(tfm)) ?
+ "fail" : "pass");
}
- printk ("testing %s across pages\n", algo);
+ printk("testing %s across pages\n", algo);
/* setup the dummy buffer first */
- memset(xbuf, 0, XBUFSIZE);
+ memset(xbuf, 0, XBUFSIZE);
j = 0;
for (i = 0; i < tcount; i++) {
if (hash_tv[i].np) {
j++;
- printk ("test %u:\n", j);
- memset (result, 0, 64);
+ printk("test %u:\n", j);
+ memset(result, 0, 64);
temp = 0;
for (k = 0; k < hash_tv[i].np; k++) {
- memcpy (&xbuf[IDX[k]], hash_tv[i].plaintext + temp,
- hash_tv[i].tap[k]);
+ memcpy(&xbuf[IDX[k]],
+ hash_tv[i].plaintext + temp,
+ hash_tv[i].tap[k]);
temp += hash_tv[i].tap[k];
p = &xbuf[IDX[k]];
- sg[k].page = virt_to_page (p);
- sg[k].offset = offset_in_page (p);
+ sg[k].page = virt_to_page(p);
+ sg[k].offset = offset_in_page(p);
sg[k].length = hash_tv[i].tap[k];
}
- crypto_digest_digest (tfm, sg, hash_tv[i].np, result);
-
- hexdump (result, crypto_tfm_alg_digestsize (tfm));
+ crypto_digest_digest(tfm, sg, hash_tv[i].np, result);
+
+ hexdump(result, crypto_tfm_alg_digestsize(tfm));
printk("%s\n",
- memcmp(result, hash_tv[i].digest,
- crypto_tfm_alg_digestsize(tfm)) ? "fail" :
- "pass");
+ memcmp(result, hash_tv[i].digest,
+ crypto_tfm_alg_digestsize(tfm)) ?
+ "fail" : "pass");
}
}
-
- crypto_free_tfm (tfm);
+
+ crypto_free_tfm(tfm);
}
#ifdef CONFIG_CRYPTO_HMAC
-static void
-test_hmac(char *algo, struct hmac_testvec * template, unsigned int tcount)
+static void test_hmac(char *algo, struct hmac_testvec *template,
+ unsigned int tcount)
{
char *p;
unsigned int i, j, k, temp;
@@ -185,8 +194,8 @@ test_hmac(char *algo, struct hmac_testvec * template, unsigned int tcount)
}
printk("\ntesting hmac_%s\n", algo);
-
- tsize = sizeof (struct hmac_testvec);
+
+ tsize = sizeof(struct hmac_testvec);
tsize *= tcount;
if (tsize > TVMEMSIZE) {
printk("template (%u) too big for tvmem (%u)\n", tsize,
@@ -195,7 +204,7 @@ test_hmac(char *algo, struct hmac_testvec * template, unsigned int tcount)
}
memcpy(tvmem, template, tsize);
- hmac_tv = (void *) tvmem;
+ hmac_tv = (void *)tvmem;
for (i = 0; i < tcount; i++) {
printk("test %u:\n", i + 1);
@@ -219,34 +228,35 @@ test_hmac(char *algo, struct hmac_testvec * template, unsigned int tcount)
printk("\ntesting hmac_%s across pages\n", algo);
memset(xbuf, 0, XBUFSIZE);
-
+
j = 0;
for (i = 0; i < tcount; i++) {
if (hmac_tv[i].np) {
j++;
- printk ("test %u:\n",j);
- memset (result, 0, 64);
+ printk("test %u:\n",j);
+ memset(result, 0, 64);
temp = 0;
klen = hmac_tv[i].ksize;
for (k = 0; k < hmac_tv[i].np; k++) {
- memcpy (&xbuf[IDX[k]], hmac_tv[i].plaintext + temp,
- hmac_tv[i].tap[k]);
+ memcpy(&xbuf[IDX[k]],
+ hmac_tv[i].plaintext + temp,
+ hmac_tv[i].tap[k]);
temp += hmac_tv[i].tap[k];
p = &xbuf[IDX[k]];
- sg[k].page = virt_to_page (p);
- sg[k].offset = offset_in_page (p);
+ sg[k].page = virt_to_page(p);
+ sg[k].offset = offset_in_page(p);
sg[k].length = hmac_tv[i].tap[k];
}
- crypto_hmac(tfm, hmac_tv[i].key, &klen, sg, hmac_tv[i].np,
- result);
+ crypto_hmac(tfm, hmac_tv[i].key, &klen, sg,
+ hmac_tv[i].np, result);
hexdump(result, crypto_tfm_alg_digestsize(tfm));
-
+
printk("%s\n",
- memcmp(result, hmac_tv[i].digest,
- crypto_tfm_alg_digestsize(tfm)) ? "fail" :
- "pass");
+ memcmp(result, hmac_tv[i].digest,
+ crypto_tfm_alg_digestsize(tfm)) ?
+ "fail" : "pass");
}
}
out:
@@ -255,8 +265,8 @@ out:
#endif /* CONFIG_CRYPTO_HMAC */
-static void
-test_cipher(char * algo, int mode, int enc, struct cipher_testvec * template, unsigned int tcount)
+static void test_cipher(char *algo, int mode, int enc,
+ struct cipher_testvec *template, unsigned int tcount)
{
unsigned int ret, i, j, k, temp;
unsigned int tsize;
@@ -265,22 +275,22 @@ test_cipher(char * algo, int mode, int enc, struct cipher_testvec * template, un
char *key;
struct cipher_testvec *cipher_tv;
struct scatterlist sg[8];
- char e[11], m[4];
+ const char *e, *m;
if (enc == ENCRYPT)
- strncpy(e, "encryption", 11);
+ e = "encryption";
else
- strncpy(e, "decryption", 11);
+ e = "decryption";
if (mode == MODE_ECB)
- strncpy(m, "ECB", 4);
+ m = "ECB";
else
- strncpy(m, "CBC", 4);
+ m = "CBC";
- printk("\ntesting %s %s %s \n", algo, m, e);
+ printk("\ntesting %s %s %s\n", algo, m, e);
- tsize = sizeof (struct cipher_testvec);
+ tsize = sizeof (struct cipher_testvec);
tsize *= tcount;
-
+
if (tsize > TVMEMSIZE) {
printk("template (%u) too big for tvmem (%u)\n", tsize,
TVMEMSIZE);
@@ -288,112 +298,113 @@ test_cipher(char * algo, int mode, int enc, struct cipher_testvec * template, un
}
memcpy(tvmem, template, tsize);
- cipher_tv = (void *) tvmem;
+ cipher_tv = (void *)tvmem;
+
+ if (mode)
+ tfm = crypto_alloc_tfm(algo, 0);
+ else
+ tfm = crypto_alloc_tfm(algo, CRYPTO_TFM_MODE_CBC);
- if (mode)
- tfm = crypto_alloc_tfm (algo, 0);
- else
- tfm = crypto_alloc_tfm (algo, CRYPTO_TFM_MODE_CBC);
-
if (tfm == NULL) {
printk("failed to load transform for %s %s\n", algo, m);
return;
}
-
+
j = 0;
for (i = 0; i < tcount; i++) {
if (!(cipher_tv[i].np)) {
- j++;
+ j++;
printk("test %u (%d bit key):\n",
j, cipher_tv[i].klen * 8);
tfm->crt_flags = 0;
- if (cipher_tv[i].wk)
+ if (cipher_tv[i].wk)
tfm->crt_flags |= CRYPTO_TFM_REQ_WEAK_KEY;
key = cipher_tv[i].key;
-
+
ret = crypto_cipher_setkey(tfm, key, cipher_tv[i].klen);
if (ret) {
printk("setkey() failed flags=%x\n", tfm->crt_flags);
-
+
if (!cipher_tv[i].fail)
goto out;
- }
+ }
p = cipher_tv[i].input;
sg[0].page = virt_to_page(p);
sg[0].offset = offset_in_page(p);
sg[0].length = cipher_tv[i].ilen;
-
+
if (!mode) {
crypto_cipher_set_iv(tfm, cipher_tv[i].iv,
- crypto_tfm_alg_ivsize (tfm));
+ crypto_tfm_alg_ivsize(tfm));
}
-
+
if (enc)
ret = crypto_cipher_encrypt(tfm, sg, sg, cipher_tv[i].ilen);
else
ret = crypto_cipher_decrypt(tfm, sg, sg, cipher_tv[i].ilen);
-
-
+
+
if (ret) {
printk("%s () failed flags=%x\n", e, tfm->crt_flags);
goto out;
- }
-
+ }
+
q = kmap(sg[0].page) + sg[0].offset;
hexdump(q, cipher_tv[i].rlen);
-
- printk("%s\n",
- memcmp(q, cipher_tv[i].result, cipher_tv[i].rlen) ? "fail" :
- "pass");
+
+ printk("%s\n",
+ memcmp(q, cipher_tv[i].result,
+ cipher_tv[i].rlen) ? "fail" : "pass");
}
}
-
- printk("\ntesting %s %s %s across pages (chunking) \n", algo, m, e);
+
+ printk("\ntesting %s %s %s across pages (chunking)\n", algo, m, e);
memset(xbuf, 0, XBUFSIZE);
-
+
j = 0;
for (i = 0; i < tcount; i++) {
if (cipher_tv[i].np) {
- j++;
+ j++;
printk("test %u (%d bit key):\n",
j, cipher_tv[i].klen * 8);
- tfm->crt_flags = 0;
- if (cipher_tv[i].wk)
+ tfm->crt_flags = 0;
+ if (cipher_tv[i].wk)
tfm->crt_flags |= CRYPTO_TFM_REQ_WEAK_KEY;
key = cipher_tv[i].key;
-
- ret = crypto_cipher_setkey(tfm, key, cipher_tv[i].klen);
+
+ ret = crypto_cipher_setkey(tfm, key, cipher_tv[i].klen);
if (ret) {
printk("setkey() failed flags=%x\n", tfm->crt_flags);
-
+
if (!cipher_tv[i].fail)
goto out;
}
temp = 0;
for (k = 0; k < cipher_tv[i].np; k++) {
- memcpy (&xbuf[IDX[k]], cipher_tv[i].input + temp,
- cipher_tv[i].tap[k]);
+ memcpy(&xbuf[IDX[k]],
+ cipher_tv[i].input + temp,
+ cipher_tv[i].tap[k]);
temp += cipher_tv[i].tap[k];
p = &xbuf[IDX[k]];
- sg[k].page = virt_to_page (p);
- sg[k].offset = offset_in_page (p);
+ sg[k].page = virt_to_page(p);
+ sg[k].offset = offset_in_page(p);
sg[k].length = cipher_tv[i].tap[k];
}
-
+
if (!mode) {
crypto_cipher_set_iv(tfm, cipher_tv[i].iv,
- crypto_tfm_alg_ivsize (tfm));
+ crypto_tfm_alg_ivsize(tfm));
}
-
+
if (enc)
ret = crypto_cipher_encrypt(tfm, sg, sg, cipher_tv[i].ilen);
else
ret = crypto_cipher_decrypt(tfm, sg, sg, cipher_tv[i].ilen);
-
+
if (ret) {
printk("%s () failed flags=%x\n", e, tfm->crt_flags);
goto out;
@@ -404,9 +415,9 @@ test_cipher(char * algo, int mode, int enc, struct cipher_testvec * template, un
printk("page %u\n", k);
q = kmap(sg[k].page) + sg[k].offset;
hexdump(q, cipher_tv[i].tap[k]);
- printk("%s\n",
- memcmp(q, cipher_tv[i].result + temp,
- cipher_tv[i].tap[k]) ? "fail" :
+ printk("%s\n",
+ memcmp(q, cipher_tv[i].result + temp,
+ cipher_tv[i].tap[k]) ? "fail" :
"pass");
temp += cipher_tv[i].tap[k];
}
@@ -417,8 +428,169 @@ out:
crypto_free_tfm(tfm);
}
-static void
-test_deflate(void)
+static int test_cipher_jiffies(struct crypto_tfm *tfm, int enc, char *p,
+ int blen, int sec)
+{
+ struct scatterlist sg[8];
+ unsigned long start, end;
+ int bcount;
+ int ret;
+
+ sg[0].page = virt_to_page(p);
+ sg[0].offset = offset_in_page(p);
+ sg[0].length = blen;
+
+ for (start = jiffies, end = start + sec * HZ, bcount = 0;
+ time_before(jiffies, end); bcount++) {
+ if (enc)
+ ret = crypto_cipher_encrypt(tfm, sg, sg, blen);
+ else
+ ret = crypto_cipher_decrypt(tfm, sg, sg, blen);
+
+ if (ret)
+ return ret;
+ }
+
+ printk("%d operations in %d seconds (%ld bytes)\n",
+ bcount, sec, (long)bcount * blen);
+ return 0;
+}
+
+static int test_cipher_cycles(struct crypto_tfm *tfm, int enc, char *p,
+ int blen)
+{
+ struct scatterlist sg[8];
+ unsigned long cycles = 0;
+ int ret = 0;
+ int i;
+
+ sg[0].page = virt_to_page(p);
+ sg[0].offset = offset_in_page(p);
+ sg[0].length = blen;
+
+ local_bh_disable();
+ local_irq_disable();
+
+ /* Warm-up run. */
+ for (i = 0; i < 4; i++) {
+ if (enc)
+ ret = crypto_cipher_encrypt(tfm, sg, sg, blen);
+ else
+ ret = crypto_cipher_decrypt(tfm, sg, sg, blen);
+
+ if (ret)
+ goto out;
+ }
+
+ /* The real thing. */
+ for (i = 0; i < 8; i++) {
+ cycles_t start, end;
+
+ start = get_cycles();
+ if (enc)
+ ret = crypto_cipher_encrypt(tfm, sg, sg, blen);
+ else
+ ret = crypto_cipher_decrypt(tfm, sg, sg, blen);
+ end = get_cycles();
+
+ if (ret)
+ goto out;
+
+ cycles += end - start;
+ }
+
+out:
+ local_irq_enable();
+ local_bh_enable();
+
+ if (ret == 0)
+ printk("1 operation in %lu cycles (%d bytes)\n",
+ (cycles + 4) / 8, blen);
+
+ return ret;
+}
+
+static void test_cipher_speed(char *algo, int mode, int enc, unsigned int sec,
+ struct cipher_testvec *template,
+ unsigned int tcount, struct cipher_speed *speed)
+{
+ unsigned int ret, i, j, iv_len;
+ unsigned char *key, *p, iv[128];
+ struct crypto_tfm *tfm;
+ const char *e, *m;
+
+ if (enc == ENCRYPT)
+ e = "encryption";
+ else
+ e = "decryption";
+ if (mode == MODE_ECB)
+ m = "ECB";
+ else
+ m = "CBC";
+
+ printk("\ntesting speed of %s %s %s\n", algo, m, e);
+
+ if (mode)
+ tfm = crypto_alloc_tfm(algo, 0);
+ else
+ tfm = crypto_alloc_tfm(algo, CRYPTO_TFM_MODE_CBC);
+
+ if (tfm == NULL) {
+ printk("failed to load transform for %s %s\n", algo, m);
+ return;
+ }
+
+ for (i = 0; speed[i].klen != 0; i++) {
+ if ((speed[i].blen + speed[i].klen) > TVMEMSIZE) {
+ printk("template (%u) too big for tvmem (%u)\n",
+ speed[i].blen + speed[i].klen, TVMEMSIZE);
+ goto out;
+ }
+
+ printk("test %u (%d bit key, %d byte blocks): ", i,
+ speed[i].klen * 8, speed[i].blen);
+
+ memset(tvmem, 0xff, speed[i].klen + speed[i].blen);
+
+ /* set key, plain text and IV */
+ key = (unsigned char *)tvmem;
+ for (j = 0; j < tcount; j++) {
+ if (template[j].klen == speed[i].klen) {
+ key = template[j].key;
+ break;
+ }
+ }
+ p = (unsigned char *)tvmem + speed[i].klen;
+
+ ret = crypto_cipher_setkey(tfm, key, speed[i].klen);
+ if (ret) {
+ printk("setkey() failed flags=%x\n", tfm->crt_flags);
+ goto out;
+ }
+
+ if (!mode) {
+ iv_len = crypto_tfm_alg_ivsize(tfm);
+ memset(&iv, 0xff, iv_len);
+ crypto_cipher_set_iv(tfm, iv, iv_len);
+ }
+
+ if (sec)
+ ret = test_cipher_jiffies(tfm, enc, p, speed[i].blen,
+ sec);
+ else
+ ret = test_cipher_cycles(tfm, enc, p, speed[i].blen);
+
+ if (ret) {
+ printk("%s() failed flags=%x\n", e, tfm->crt_flags);
+ break;
+ }
+ }
+
+out:
+ crypto_free_tfm(tfm);
+}
+
+static void test_deflate(void)
{
unsigned int i;
char result[COMP_BUF_SIZE];
@@ -436,7 +608,7 @@ test_deflate(void)
}
memcpy(tvmem, deflate_comp_tv_template, tsize);
- tv = (void *) tvmem;
+ tv = (void *)tvmem;
tfm = crypto_alloc_tfm("deflate", 0);
if (tfm == NULL) {
@@ -446,7 +618,7 @@ test_deflate(void)
for (i = 0; i < DEFLATE_COMP_TEST_VECTORS; i++) {
int ilen, ret, dlen = COMP_BUF_SIZE;
-
+
printk("test %u:\n", i + 1);
memset(result, 0, sizeof (result));
@@ -473,11 +645,11 @@ test_deflate(void)
}
memcpy(tvmem, deflate_decomp_tv_template, tsize);
- tv = (void *) tvmem;
+ tv = (void *)tvmem;
for (i = 0; i < DEFLATE_DECOMP_TEST_VECTORS; i++) {
int ilen, ret, dlen = COMP_BUF_SIZE;
-
+
printk("test %u:\n", i + 1);
memset(result, 0, sizeof (result));
@@ -497,8 +669,7 @@ out:
crypto_free_tfm(tfm);
}
-static void
-test_crc32c(void)
+static void test_crc32c(void)
{
#define NUMVEC 6
#define VECSIZE 40
@@ -511,7 +682,7 @@ test_crc32c(void)
0xd579c862, 0xba979ad0, 0x2b29d913
};
static u32 tot_vec_results = 0x24c5d375;
-
+
struct scatterlist sg[NUMVEC];
struct crypto_tfm *tfm;
char *fmtdata = "testing crc32c initialized to %08x: %s\n";
@@ -525,18 +696,18 @@ test_crc32c(void)
printk("failed to load transform for crc32c\n");
return;
}
-
+
crypto_digest_init(tfm);
crypto_digest_final(tfm, (u8*)&crc);
printk(fmtdata, crc, (crc == 0) ? "pass" : "ERROR");
-
+
/*
* stuff test_vec with known values, simple incrementing
* byte values.
*/
b = 0;
for (i = 0; i < NUMVEC; i++) {
- for (j = 0; j < VECSIZE; j++)
+ for (j = 0; j < VECSIZE; j++)
test_vec[i][j] = ++b;
sg[i].page = virt_to_page(test_vec[i]);
sg[i].offset = offset_in_page(test_vec[i]);
@@ -548,11 +719,11 @@ test_crc32c(void)
crypto_digest_final(tfm, (u8*)&crc);
printk("testing crc32c setkey returns %08x : %s\n", crc, (crc == (SEEDTESTVAL ^ ~(u32)0)) ?
"pass" : "ERROR");
-
+
printk("testing crc32c using update/final:\n");
pass = 1; /* assume all is well */
-
+
for (i = 0; i < NUMVEC; i++) {
seed = ~(u32)0;
(void)crypto_digest_setkey(tfm, (const u8*)&seed, sizeof(u32));
@@ -591,66 +762,64 @@ test_crc32c(void)
printk(" %08x:BAD, wanted %08x\n", crc, tot_vec_results);
pass = 0;
}
-
+
printk("\n%s\n", pass ? "pass" : "ERROR");
crypto_free_tfm(tfm);
printk("crc32c test complete\n");
}
-static void
-test_available(void)
+static void test_available(void)
{
char **name = check;
-
+
while (*name) {
printk("alg %s ", *name);
printk((crypto_alg_available(*name, 0)) ?
"found\n" : "not found\n");
name++;
- }
+ }
}
-static void
-do_test(void)
+static void do_test(void)
{
switch (mode) {
case 0:
test_hash("md5", md5_tv_template, MD5_TEST_VECTORS);
-
+
test_hash("sha1", sha1_tv_template, SHA1_TEST_VECTORS);
-
+
//DES
test_cipher ("des", MODE_ECB, ENCRYPT, des_enc_tv_template, DES_ENC_TEST_VECTORS);
- test_cipher ("des", MODE_ECB, DECRYPT, des_dec_tv_template, DES_DEC_TEST_VECTORS);
- test_cipher ("des", MODE_CBC, ENCRYPT, des_cbc_enc_tv_template, DES_CBC_ENC_TEST_VECTORS);
- test_cipher ("des", MODE_CBC, DECRYPT, des_cbc_dec_tv_template, DES_CBC_DEC_TEST_VECTORS);
-
+ test_cipher ("des", MODE_ECB, DECRYPT, des_dec_tv_template, DES_DEC_TEST_VECTORS);
+ test_cipher ("des", MODE_CBC, ENCRYPT, des_cbc_enc_tv_template, DES_CBC_ENC_TEST_VECTORS);
+ test_cipher ("des", MODE_CBC, DECRYPT, des_cbc_dec_tv_template, DES_CBC_DEC_TEST_VECTORS);
+
//DES3_EDE
test_cipher ("des3_ede", MODE_ECB, ENCRYPT, des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS);
- test_cipher ("des3_ede", MODE_ECB, DECRYPT, des3_ede_dec_tv_template, DES3_EDE_DEC_TEST_VECTORS);
-
+ test_cipher ("des3_ede", MODE_ECB, DECRYPT, des3_ede_dec_tv_template, DES3_EDE_DEC_TEST_VECTORS);
+
test_hash("md4", md4_tv_template, MD4_TEST_VECTORS);
-
+
test_hash("sha256", sha256_tv_template, SHA256_TEST_VECTORS);
-
+
//BLOWFISH
test_cipher ("blowfish", MODE_ECB, ENCRYPT, bf_enc_tv_template, BF_ENC_TEST_VECTORS);
test_cipher ("blowfish", MODE_ECB, DECRYPT, bf_dec_tv_template, BF_DEC_TEST_VECTORS);
test_cipher ("blowfish", MODE_CBC, ENCRYPT, bf_cbc_enc_tv_template, BF_CBC_ENC_TEST_VECTORS);
test_cipher ("blowfish", MODE_CBC, DECRYPT, bf_cbc_dec_tv_template, BF_CBC_DEC_TEST_VECTORS);
-
+
//TWOFISH
test_cipher ("twofish", MODE_ECB, ENCRYPT, tf_enc_tv_template, TF_ENC_TEST_VECTORS);
test_cipher ("twofish", MODE_ECB, DECRYPT, tf_dec_tv_template, TF_DEC_TEST_VECTORS);
test_cipher ("twofish", MODE_CBC, ENCRYPT, tf_cbc_enc_tv_template, TF_CBC_ENC_TEST_VECTORS);
test_cipher ("twofish", MODE_CBC, DECRYPT, tf_cbc_dec_tv_template, TF_CBC_DEC_TEST_VECTORS);
-
+
//SERPENT
test_cipher ("serpent", MODE_ECB, ENCRYPT, serpent_enc_tv_template, SERPENT_ENC_TEST_VECTORS);
test_cipher ("serpent", MODE_ECB, DECRYPT, serpent_dec_tv_template, SERPENT_DEC_TEST_VECTORS);
-
+
//TNEPRES
test_cipher ("tnepres", MODE_ECB, ENCRYPT, tnepres_enc_tv_template, TNEPRES_ENC_TEST_VECTORS);
test_cipher ("tnepres", MODE_ECB, DECRYPT, tnepres_dec_tv_template, TNEPRES_DEC_TEST_VECTORS);
@@ -662,7 +831,7 @@ do_test(void)
//CAST5
test_cipher ("cast5", MODE_ECB, ENCRYPT, cast5_enc_tv_template, CAST5_ENC_TEST_VECTORS);
test_cipher ("cast5", MODE_ECB, DECRYPT, cast5_dec_tv_template, CAST5_DEC_TEST_VECTORS);
-
+
//CAST6
test_cipher ("cast6", MODE_ECB, ENCRYPT, cast6_enc_tv_template, CAST6_ENC_TEST_VECTORS);
test_cipher ("cast6", MODE_ECB, DECRYPT, cast6_dec_tv_template, CAST6_DEC_TEST_VECTORS);
@@ -702,9 +871,9 @@ do_test(void)
test_crc32c();
#ifdef CONFIG_CRYPTO_HMAC
test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);
- test_hmac("sha1", hmac_sha1_tv_template, HMAC_SHA1_TEST_VECTORS);
+ test_hmac("sha1", hmac_sha1_tv_template, HMAC_SHA1_TEST_VECTORS);
test_hmac("sha256", hmac_sha256_tv_template, HMAC_SHA256_TEST_VECTORS);
-#endif
+#endif
test_hash("michael_mic", michael_mic_tv_template, MICHAEL_MIC_TEST_VECTORS);
break;
@@ -726,17 +895,17 @@ do_test(void)
case 4:
test_cipher ("des3_ede", MODE_ECB, ENCRYPT, des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS);
- test_cipher ("des3_ede", MODE_ECB, DECRYPT, des3_ede_dec_tv_template, DES3_EDE_DEC_TEST_VECTORS);
+ test_cipher ("des3_ede", MODE_ECB, DECRYPT, des3_ede_dec_tv_template, DES3_EDE_DEC_TEST_VECTORS);
break;
case 5:
test_hash("md4", md4_tv_template, MD4_TEST_VECTORS);
break;
-
+
case 6:
test_hash("sha256", sha256_tv_template, SHA256_TEST_VECTORS);
break;
-
+
case 7:
test_cipher ("blowfish", MODE_ECB, ENCRYPT, bf_enc_tv_template, BF_ENC_TEST_VECTORS);
test_cipher ("blowfish", MODE_ECB, DECRYPT, bf_dec_tv_template, BF_DEC_TEST_VECTORS);
@@ -750,7 +919,7 @@ do_test(void)
test_cipher ("twofish", MODE_CBC, ENCRYPT, tf_cbc_enc_tv_template, TF_CBC_ENC_TEST_VECTORS);
test_cipher ("twofish", MODE_CBC, DECRYPT, tf_cbc_dec_tv_template, TF_CBC_DEC_TEST_VECTORS);
break;
-
+
case 9:
test_cipher ("serpent", MODE_ECB, ENCRYPT, serpent_enc_tv_template, SERPENT_ENC_TEST_VECTORS);
test_cipher ("serpent", MODE_ECB, DECRYPT, serpent_dec_tv_template, SERPENT_DEC_TEST_VECTORS);
@@ -758,13 +927,13 @@ do_test(void)
case 10:
test_cipher ("aes", MODE_ECB, ENCRYPT, aes_enc_tv_template, AES_ENC_TEST_VECTORS);
- test_cipher ("aes", MODE_ECB, DECRYPT, aes_dec_tv_template, AES_DEC_TEST_VECTORS);
+ test_cipher ("aes", MODE_ECB, DECRYPT, aes_dec_tv_template, AES_DEC_TEST_VECTORS);
break;
case 11:
test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
break;
-
+
case 12:
test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
break;
@@ -852,21 +1021,84 @@ do_test(void)
case 100:
test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);
break;
-
+
case 101:
- test_hmac("sha1", hmac_sha1_tv_template, HMAC_SHA1_TEST_VECTORS);
+ test_hmac("sha1", hmac_sha1_tv_template, HMAC_SHA1_TEST_VECTORS);
break;
-
+
case 102:
test_hmac("sha256", hmac_sha256_tv_template, HMAC_SHA256_TEST_VECTORS);
break;
#endif
+ case 200:
+ test_cipher_speed("aes", MODE_ECB, ENCRYPT, sec, NULL, 0,
+ aes_speed_template);
+ test_cipher_speed("aes", MODE_ECB, DECRYPT, sec, NULL, 0,
+ aes_speed_template);
+ test_cipher_speed("aes", MODE_CBC, ENCRYPT, sec, NULL, 0,
+ aes_speed_template);
+ test_cipher_speed("aes", MODE_CBC, DECRYPT, sec, NULL, 0,
+ aes_speed_template);
+ break;
+
+ case 201:
+ test_cipher_speed("des3_ede", MODE_ECB, ENCRYPT, sec,
+ des3_ede_enc_tv_template,
+ DES3_EDE_ENC_TEST_VECTORS,
+ des3_ede_speed_template);
+ test_cipher_speed("des3_ede", MODE_ECB, DECRYPT, sec,
+ des3_ede_dec_tv_template,
+ DES3_EDE_DEC_TEST_VECTORS,
+ des3_ede_speed_template);
+ test_cipher_speed("des3_ede", MODE_CBC, ENCRYPT, sec,
+ des3_ede_enc_tv_template,
+ DES3_EDE_ENC_TEST_VECTORS,
+ des3_ede_speed_template);
+ test_cipher_speed("des3_ede", MODE_CBC, DECRYPT, sec,
+ des3_ede_dec_tv_template,
+ DES3_EDE_DEC_TEST_VECTORS,
+ des3_ede_speed_template);
+ break;
+
+ case 202:
+ test_cipher_speed("twofish", MODE_ECB, ENCRYPT, sec, NULL, 0,
+ twofish_speed_template);
+ test_cipher_speed("twofish", MODE_ECB, DECRYPT, sec, NULL, 0,
+ twofish_speed_template);
+ test_cipher_speed("twofish", MODE_CBC, ENCRYPT, sec, NULL, 0,
+ twofish_speed_template);
+ test_cipher_speed("twofish", MODE_CBC, DECRYPT, sec, NULL, 0,
+ twofish_speed_template);
+ break;
+
+ case 203:
+ test_cipher_speed("blowfish", MODE_ECB, ENCRYPT, sec, NULL, 0,
+ blowfish_speed_template);
+ test_cipher_speed("blowfish", MODE_ECB, DECRYPT, sec, NULL, 0,
+ blowfish_speed_template);
+ test_cipher_speed("blowfish", MODE_CBC, ENCRYPT, sec, NULL, 0,
+ blowfish_speed_template);
+ test_cipher_speed("blowfish", MODE_CBC, DECRYPT, sec, NULL, 0,
+ blowfish_speed_template);
+ break;
+
+ case 204:
+ test_cipher_speed("des", MODE_ECB, ENCRYPT, sec, NULL, 0,
+ des_speed_template);
+ test_cipher_speed("des", MODE_ECB, DECRYPT, sec, NULL, 0,
+ des_speed_template);
+ test_cipher_speed("des", MODE_CBC, ENCRYPT, sec, NULL, 0,
+ des_speed_template);
+ test_cipher_speed("des", MODE_CBC, DECRYPT, sec, NULL, 0,
+ des_speed_template);
+ break;
+
case 1000:
test_available();
break;
-
+
default:
/* useful for debugging */
printk("not testing anything\n");
@@ -874,8 +1106,7 @@ do_test(void)
}
}
-static int __init
-init(void)
+static int __init init(void)
{
tvmem = kmalloc(TVMEMSIZE, GFP_KERNEL);
if (tvmem == NULL)
@@ -904,6 +1135,9 @@ module_init(init);
module_exit(fini);
module_param(mode, int, 0);
+module_param(sec, uint, 0);
+MODULE_PARM_DESC(sec, "Length in seconds of speed tests "
+ "(defaults to zero which uses CPU cycles instead)");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Quick & dirty crypto testing module");
diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h
index a3097afae59..c01a0ce9b40 100644
--- a/crypto/tcrypt.h
+++ b/crypto/tcrypt.h
@@ -9,10 +9,11 @@
*
* 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)
+ * Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
- * 14 - 09 - 2003 Changes by Kartikey Mahendra Bhatt
+ * 2004-08-09 Cipher speed tests by Reyk Floeter <reyk@vantronix.net>
+ * 2003-09-14 Changes by Kartikey Mahendra Bhatt
*
*/
#ifndef _CRYPTO_TCRYPT_H
@@ -29,19 +30,19 @@ struct hash_testvec {
unsigned char psize;
char digest[MAX_DIGEST_SIZE];
unsigned char np;
- unsigned char tap[MAX_TAP];
+ unsigned char tap[MAX_TAP];
char key[128]; /* only used with keyed hash algorithms */
unsigned char ksize;
};
-struct hmac_testvec {
+struct hmac_testvec {
char key[128];
unsigned char ksize;
char plaintext[128];
unsigned char psize;
char digest[MAX_DIGEST_SIZE];
unsigned char np;
- unsigned char tap[MAX_TAP];
+ unsigned char tap[MAX_TAP];
};
struct cipher_testvec {
@@ -55,7 +56,12 @@ struct cipher_testvec {
char result[48];
unsigned char rlen;
int np;
- unsigned char tap[MAX_TAP];
+ unsigned char tap[MAX_TAP];
+};
+
+struct cipher_speed {
+ unsigned char klen;
+ unsigned int blen;
};
/*
@@ -155,7 +161,7 @@ static struct hash_testvec md5_tv_template[] = {
#define SHA1_TEST_VECTORS 2
static struct hash_testvec sha1_tv_template[] = {
- {
+ {
.plaintext = "abc",
.psize = 3,
.digest = { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e,
@@ -175,8 +181,8 @@ static struct hash_testvec sha1_tv_template[] = {
*/
#define SHA256_TEST_VECTORS 2
-static struct hash_testvec sha256_tv_template[] = {
- {
+static struct hash_testvec sha256_tv_template[] = {
+ {
.plaintext = "abc",
.psize = 3,
.digest = { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
@@ -201,7 +207,7 @@ static struct hash_testvec sha256_tv_template[] = {
#define SHA384_TEST_VECTORS 4
static struct hash_testvec sha384_tv_template[] = {
- {
+ {
.plaintext= "abc",
.psize = 3,
.digest = { 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b,
@@ -221,7 +227,7 @@ static struct hash_testvec sha384_tv_template[] = {
0x5f, 0xe9, 0x5b, 0x1f, 0xe3, 0xc8, 0x45, 0x2b},
}, {
.plaintext = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
- "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+ "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
.psize = 112,
.digest = { 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8,
0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47,
@@ -250,7 +256,7 @@ static struct hash_testvec sha384_tv_template[] = {
#define SHA512_TEST_VECTORS 4
static struct hash_testvec sha512_tv_template[] = {
- {
+ {
.plaintext = "abc",
.psize = 3,
.digest = { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
@@ -303,14 +309,14 @@ static struct hash_testvec sha512_tv_template[] = {
/*
- * WHIRLPOOL test vectors from Whirlpool package
+ * WHIRLPOOL test vectors from Whirlpool package
* by Vincent Rijmen and Paulo S. L. M. Barreto as part of the NESSIE
* submission
*/
#define WP512_TEST_VECTORS 8
static struct hash_testvec wp512_tv_template[] = {
- {
+ {
.plaintext = "",
.psize = 0,
.digest = { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66,
@@ -348,13 +354,13 @@ static struct hash_testvec wp512_tv_template[] = {
}, {
.plaintext = "message digest",
.psize = 14,
- .digest = { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6,
- 0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC,
- 0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C,
- 0xE1, 0xF5, 0x70, 0x0C, 0x0F, 0xFB, 0x4D, 0x3B,
- 0x84, 0x21, 0x55, 0x76, 0x59, 0xEF, 0x55, 0xC1,
- 0x06, 0xB4, 0xB5, 0x2A, 0xC5, 0xA4, 0xAA, 0xA6,
- 0x92, 0xED, 0x92, 0x00, 0x52, 0x83, 0x8F, 0x33,
+ .digest = { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6,
+ 0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC,
+ 0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C,
+ 0xE1, 0xF5, 0x70, 0x0C, 0x0F, 0xFB, 0x4D, 0x3B,
+ 0x84, 0x21, 0x55, 0x76, 0x59, 0xEF, 0x55, 0xC1,
+ 0x06, 0xB4, 0xB5, 0x2A, 0xC5, 0xA4, 0xAA, 0xA6,
+ 0x92, 0xED, 0x92, 0x00, 0x52, 0x83, 0x8F, 0x33,
0x62, 0xE8, 0x6D, 0xBD, 0x37, 0xA8, 0x90, 0x3E },
}, {
.plaintext = "abcdefghijklmnopqrstuvwxyz",
@@ -394,7 +400,7 @@ static struct hash_testvec wp512_tv_template[] = {
}, {
.plaintext = "abcdbcdecdefdefgefghfghighijhijk",
.psize = 32,
- .digest = { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61,
+ .digest = { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61,
0xF5, 0xD6, 0xF0, 0xA0, 0xE4, 0x64, 0x4F, 0x48,
0x8A, 0x7A, 0x5A, 0x52, 0xDE, 0xEE, 0x65, 0x62,
0x07, 0xC5, 0x62, 0xF9, 0x88, 0xE9, 0x5C, 0x69,
@@ -408,7 +414,7 @@ static struct hash_testvec wp512_tv_template[] = {
#define WP384_TEST_VECTORS 8
static struct hash_testvec wp384_tv_template[] = {
- {
+ {
.plaintext = "",
.psize = 0,
.digest = { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66,
@@ -440,11 +446,11 @@ static struct hash_testvec wp384_tv_template[] = {
}, {
.plaintext = "message digest",
.psize = 14,
- .digest = { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6,
- 0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC,
- 0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C,
- 0xE1, 0xF5, 0x70, 0x0C, 0x0F, 0xFB, 0x4D, 0x3B,
- 0x84, 0x21, 0x55, 0x76, 0x59, 0xEF, 0x55, 0xC1,
+ .digest = { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6,
+ 0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC,
+ 0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C,
+ 0xE1, 0xF5, 0x70, 0x0C, 0x0F, 0xFB, 0x4D, 0x3B,
+ 0x84, 0x21, 0x55, 0x76, 0x59, 0xEF, 0x55, 0xC1,
0x06, 0xB4, 0xB5, 0x2A, 0xC5, 0xA4, 0xAA, 0xA6 },
}, {
.plaintext = "abcdefghijklmnopqrstuvwxyz",
@@ -478,7 +484,7 @@ static struct hash_testvec wp384_tv_template[] = {
}, {
.plaintext = "abcdbcdecdefdefgefghfghighijhijk",
.psize = 32,
- .digest = { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61,
+ .digest = { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61,
0xF5, 0xD6, 0xF0, 0xA0, 0xE4, 0x64, 0x4F, 0x48,
0x8A, 0x7A, 0x5A, 0x52, 0xDE, 0xEE, 0x65, 0x62,
0x07, 0xC5, 0x62, 0xF9, 0x88, 0xE9, 0x5C, 0x69,
@@ -490,7 +496,7 @@ static struct hash_testvec wp384_tv_template[] = {
#define WP256_TEST_VECTORS 8
static struct hash_testvec wp256_tv_template[] = {
- {
+ {
.plaintext = "",
.psize = 0,
.digest = { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66,
@@ -516,9 +522,9 @@ static struct hash_testvec wp256_tv_template[] = {
}, {
.plaintext = "message digest",
.psize = 14,
- .digest = { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6,
- 0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC,
- 0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C,
+ .digest = { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6,
+ 0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC,
+ 0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C,
0xE1, 0xF5, 0x70, 0x0C, 0x0F, 0xFB, 0x4D, 0x3B },
}, {
.plaintext = "abcdefghijklmnopqrstuvwxyz",
@@ -546,7 +552,7 @@ static struct hash_testvec wp256_tv_template[] = {
}, {
.plaintext = "abcdbcdecdefdefgefghfghighijhijk",
.psize = 32,
- .digest = { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61,
+ .digest = { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61,
0xF5, 0xD6, 0xF0, 0xA0, 0xE4, 0x64, 0x4F, 0x48,
0x8A, 0x7A, 0x5A, 0x52, 0xDE, 0xEE, 0x65, 0x62,
0x07, 0xC5, 0x62, 0xF9, 0x88, 0xE9, 0x5C, 0x69 },
@@ -554,7 +560,7 @@ static struct hash_testvec wp256_tv_template[] = {
};
/*
- * TIGER test vectors from Tiger website
+ * TIGER test vectors from Tiger website
*/
#define TGR192_TEST_VECTORS 6
@@ -693,7 +699,7 @@ static struct hash_testvec tgr128_tv_template[] = {
#define HMAC_MD5_TEST_VECTORS 7
static struct hmac_testvec hmac_md5_tv_template[] =
-{
+{
{
.key = { [0 ... 15] = 0x0b },
.ksize = 16,
@@ -756,7 +762,7 @@ static struct hmac_testvec hmac_md5_tv_template[] =
*/
#define HMAC_SHA1_TEST_VECTORS 7
-static struct hmac_testvec hmac_sha1_tv_template[] = {
+static struct hmac_testvec hmac_sha1_tv_template[] = {
{
.key = { [0 ... 19] = 0x0b },
.ksize = 20,
@@ -766,11 +772,11 @@ static struct hmac_testvec hmac_sha1_tv_template[] = {
0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e, 0xf1,
0x46, 0xbe },
}, {
- .key = { 'J', 'e', 'f', 'e' },
+ .key = { 'J', 'e', 'f', 'e' },
.ksize = 4,
.plaintext = "what do ya want for nothing?",
.psize = 28,
- .digest = { 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, 0xd2, 0x74,
+ .digest = { 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, 0xd2, 0x74,
0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c, 0x25, 0x9a, 0x7c, 0x79 },
.np = 2,
.tap = { 14, 14 }
@@ -779,30 +785,30 @@ static struct hmac_testvec hmac_sha1_tv_template[] = {
.ksize = 20,
.plaintext = { [0 ... 49] = 0xdd },
.psize = 50,
- .digest = { 0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd, 0x91, 0xa3,
+ .digest = { 0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd, 0x91, 0xa3,
0x9a, 0xf4, 0x8a, 0xa1, 0x7b, 0x4f, 0x63, 0xf1, 0x75, 0xd3 },
}, {
.key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
+ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19 },
.ksize = 25,
.plaintext = { [0 ... 49] = 0xcd },
.psize = 50,
- .digest = { 0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62, 0x50, 0xc6, 0xbc, 0x84,
+ .digest = { 0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62, 0x50, 0xc6, 0xbc, 0x84,
0x14, 0xf9, 0xbf, 0x50, 0xc8, 0x6c, 0x2d, 0x72, 0x35, 0xda },
}, {
.key = { [0 ... 19] = 0x0c },
.ksize = 20,
.plaintext = "Test With Truncation",
.psize = 20,
- .digest = { 0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2,
+ .digest = { 0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2,
0x7b, 0xe1, 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a, 0x5a, 0x04 },
}, {
.key = { [0 ... 79] = 0xaa },
.ksize = 80,
.plaintext = "Test Using Larger Than Block-Size Key - Hash Key First",
.psize = 54,
- .digest = { 0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e, 0x95, 0x70,
+ .digest = { 0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e, 0x95, 0x70,
0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55, 0xed, 0x40, 0x21, 0x12 },
}, {
.key = { [0 ... 79] = 0xaa },
@@ -810,7 +816,7 @@ static struct hmac_testvec hmac_sha1_tv_template[] = {
.plaintext = "Test Using Larger Than Block-Size Key and Larger Than One "
"Block-Size Data",
.psize = 73,
- .digest = { 0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d, 0x6b,
+ .digest = { 0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d, 0x6b,
0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91 },
},
};
@@ -1011,7 +1017,7 @@ static struct cipher_testvec des_enc_tv_template[] = {
0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b },
.rlen = 32,
.np = 3,
- .tap = { 14, 10, 8 }
+ .tap = { 14, 10, 8 }
}, {
.key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
.klen = 8,
@@ -1024,7 +1030,7 @@ static struct cipher_testvec des_enc_tv_template[] = {
0xb4, 0x99, 0x26, 0xf7, 0x1f, 0xe1, 0xd4, 0x90 },
.rlen = 24,
.np = 4,
- .tap = { 2, 1, 3, 18 }
+ .tap = { 2, 1, 3, 18 }
}, {
.key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
.klen = 8,
@@ -1035,7 +1041,7 @@ static struct cipher_testvec des_enc_tv_template[] = {
0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b },
.rlen = 16,
.np = 5,
- .tap = { 2, 2, 2, 2, 8 }
+ .tap = { 2, 2, 2, 2, 8 }
}, {
.key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
.klen = 8,
@@ -1044,7 +1050,7 @@ static struct cipher_testvec des_enc_tv_template[] = {
.result = { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d },
.rlen = 8,
.np = 8,
- .tap = { 1, 1, 1, 1, 1, 1, 1, 1 }
+ .tap = { 1, 1, 1, 1, 1, 1, 1, 1 }
},
};
@@ -1057,7 +1063,7 @@ static struct cipher_testvec des_dec_tv_template[] = {
.result = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 },
.rlen = 8,
}, { /* Sbox test from NBS */
- .key = { 0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57 },
+ .key = { 0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57 },
.klen = 8,
.input = { 0x69, 0x0f, 0x5b, 0x0d, 0x9a, 0x26, 0x93, 0x9b },
.ilen = 8,
@@ -1092,19 +1098,19 @@ static struct cipher_testvec des_cbc_enc_tv_template[] = {
{ /* From OpenSSL */
.key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
.klen = 8,
- .iv = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
- .input = { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20,
- 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74,
- 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 },
+ .iv = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+ .input = { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20,
+ 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 },
.ilen = 24,
- .result = { 0xcc, 0xd1, 0x73, 0xff, 0xab, 0x20, 0x39, 0xf4,
- 0xac, 0xd8, 0xae, 0xfd, 0xdf, 0xd8, 0xa1, 0xeb,
- 0x46, 0x8e, 0x91, 0x15, 0x78, 0x88, 0xba, 0x68 },
+ .result = { 0xcc, 0xd1, 0x73, 0xff, 0xab, 0x20, 0x39, 0xf4,
+ 0xac, 0xd8, 0xae, 0xfd, 0xdf, 0xd8, 0xa1, 0xeb,
+ 0x46, 0x8e, 0x91, 0x15, 0x78, 0x88, 0xba, 0x68 },
.rlen = 24,
}, { /* FIPS Pub 81 */
.key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
.klen = 8,
- .iv = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef },
+ .iv = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef },
.input = { 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 },
.ilen = 8,
.result = { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c },
@@ -1117,7 +1123,7 @@ static struct cipher_testvec des_cbc_enc_tv_template[] = {
.ilen = 8,
.result = { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
.rlen = 8,
- }, {
+ }, {
.key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
.klen = 8,
.iv = { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
@@ -1125,18 +1131,18 @@ static struct cipher_testvec des_cbc_enc_tv_template[] = {
.ilen = 8,
.result = { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 },
.rlen = 8,
- }, { /* Copy of openssl vector for chunk testing */
+ }, { /* Copy of openssl vector for chunk testing */
/* From OpenSSL */
.key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
.klen = 8,
- .iv = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
- .input = { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20,
- 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74,
- 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 },
+ .iv = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+ .input = { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20,
+ 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 },
.ilen = 24,
- .result = { 0xcc, 0xd1, 0x73, 0xff, 0xab, 0x20, 0x39, 0xf4,
- 0xac, 0xd8, 0xae, 0xfd, 0xdf, 0xd8, 0xa1, 0xeb,
- 0x46, 0x8e, 0x91, 0x15, 0x78, 0x88, 0xba, 0x68 },
+ .result = { 0xcc, 0xd1, 0x73, 0xff, 0xab, 0x20, 0x39, 0xf4,
+ 0xac, 0xd8, 0xae, 0xfd, 0xdf, 0xd8, 0xa1, 0xeb,
+ 0x46, 0x8e, 0x91, 0x15, 0x78, 0x88, 0xba, 0x68 },
.rlen = 24,
.np = 2,
.tap = { 13, 11 }
@@ -1155,24 +1161,24 @@ static struct cipher_testvec des_cbc_dec_tv_template[] = {
}, {
.key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
.klen = 8,
- .iv = { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c },
+ .iv = { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c },
.input = { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
.ilen = 8,
- .result = { 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 },
+ .result = { 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 },
.rlen = 8,
}, {
.key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
.klen = 8,
.iv = { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
- .input = { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 },
+ .input = { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 },
.ilen = 8,
.result = { 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20 },
.rlen = 8,
- }, { /* Copy of above, for chunk testing */
+ }, { /* Copy of above, for chunk testing */
.key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
.klen = 8,
.iv = { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
- .input = { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 },
+ .input = { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 },
.ilen = 8,
.result = { 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20 },
.rlen = 8,
@@ -1276,7 +1282,7 @@ static struct cipher_testvec bf_enc_tv_template[] = {
.ilen = 8,
.result = { 0xe8, 0x7a, 0x24, 0x4e, 0x2c, 0xc8, 0x5e, 0x82 },
.rlen = 8,
- }, { /* Vary the keylength... */
+ }, { /* Vary the keylength... */
.key = { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f },
.klen = 16,
@@ -1297,9 +1303,9 @@ static struct cipher_testvec bf_enc_tv_template[] = {
.key = { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f,
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
- 0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f,
- 0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76,
- 0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e,
+ 0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f,
+ 0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76,
+ 0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
.klen = 56,
.input = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
@@ -1331,7 +1337,7 @@ static struct cipher_testvec bf_dec_tv_template[] = {
.ilen = 8,
.result = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
.rlen = 8,
- }, { /* Vary the keylength... */
+ }, { /* Vary the keylength... */
.key = { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f },
.klen = 16,
@@ -1352,9 +1358,9 @@ static struct cipher_testvec bf_dec_tv_template[] = {
.key = { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f,
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
- 0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f,
- 0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76,
- 0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e,
+ 0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f,
+ 0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76,
+ 0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
.klen = 56,
.input = { 0xc0, 0x45, 0x04, 0x01, 0x2e, 0x4e, 0x1f, 0x53 },
@@ -1369,7 +1375,7 @@ static struct cipher_testvec bf_cbc_enc_tv_template[] = {
.key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
.klen = 16,
- .iv = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+ .iv = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
.input = { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20,
0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74,
0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20,
@@ -1388,7 +1394,7 @@ static struct cipher_testvec bf_cbc_dec_tv_template[] = {
.key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
.klen = 16,
- .iv = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
+ .iv = { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
.input = { 0x6b, 0x77, 0xb4, 0xd6, 0x30, 0x06, 0xde, 0xe6,
0x05, 0xb1, 0x56, 0xe2, 0x74, 0x03, 0x97, 0x93,
0x58, 0xde, 0xb9, 0xe7, 0x15, 0x46, 0x16, 0xd9,
@@ -1490,7 +1496,7 @@ static struct cipher_testvec tf_cbc_enc_tv_template[] = {
.key = { [0 ... 15] = 0x00 },
.klen = 16,
.iv = { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
- 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
+ 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
.input = { [0 ... 15] = 0x00 },
.ilen = 16,
.result = { 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
@@ -1528,7 +1534,7 @@ static struct cipher_testvec tf_cbc_dec_tv_template[] = {
.klen = 16,
.iv = { [0 ... 15] = 0x00 },
.input = { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
- 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
+ 0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
.ilen = 16,
.result = { [0 ... 15] = 0x00 },
.rlen = 16,
@@ -1578,8 +1584,7 @@ static struct cipher_testvec tf_cbc_dec_tv_template[] = {
#define TNEPRES_ENC_TEST_VECTORS 4
#define TNEPRES_DEC_TEST_VECTORS 4
-static struct cipher_testvec serpent_enc_tv_template[] =
-{
+static struct cipher_testvec serpent_enc_tv_template[] = {
{
.input = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
@@ -1620,8 +1625,7 @@ static struct cipher_testvec serpent_enc_tv_template[] =
},
};
-static struct cipher_testvec tnepres_enc_tv_template[] =
-{
+static struct cipher_testvec tnepres_enc_tv_template[] = {
{ /* KeySize=128, PT=0, I=1 */
.input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
@@ -1629,7 +1633,7 @@ static struct cipher_testvec tnepres_enc_tv_template[] =
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
.klen = 16,
.ilen = 16,
- .result = { 0x49, 0xaf, 0xbf, 0xad, 0x9d, 0x5a, 0x34, 0x05,
+ .result = { 0x49, 0xaf, 0xbf, 0xad, 0x9d, 0x5a, 0x34, 0x05,
0x2c, 0xd8, 0xff, 0xa5, 0x98, 0x6b, 0xd2, 0xdd },
.rlen = 16,
}, { /* KeySize=192, PT=0, I=1 */
@@ -1640,7 +1644,7 @@ static struct cipher_testvec tnepres_enc_tv_template[] =
.input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
.ilen = 16,
- .result = { 0xe7, 0x8e, 0x54, 0x02, 0xc7, 0x19, 0x55, 0x68,
+ .result = { 0xe7, 0x8e, 0x54, 0x02, 0xc7, 0x19, 0x55, 0x68,
0xac, 0x36, 0x78, 0xf7, 0xa3, 0xf6, 0x0c, 0x66 },
.rlen = 16,
}, { /* KeySize=256, PT=0, I=1 */
@@ -1652,7 +1656,7 @@ static struct cipher_testvec tnepres_enc_tv_template[] =
.input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
.ilen = 16,
- .result = { 0xab, 0xed, 0x96, 0xe7, 0x66, 0xbf, 0x28, 0xcb,
+ .result = { 0xab, 0xed, 0x96, 0xe7, 0x66, 0xbf, 0x28, 0xcb,
0xc0, 0xeb, 0xd2, 0x1a, 0x82, 0xef, 0x08, 0x19 },
.rlen = 16,
}, { /* KeySize=256, I=257 */
@@ -1664,15 +1668,14 @@ static struct cipher_testvec tnepres_enc_tv_template[] =
.input = { 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 },
.ilen = 16,
- .result = { 0x5c, 0xe7, 0x1c, 0x70, 0xd2, 0x88, 0x2e, 0x5b,
+ .result = { 0x5c, 0xe7, 0x1c, 0x70, 0xd2, 0x88, 0x2e, 0x5b,
0xb8, 0x32, 0xe4, 0x33, 0xf8, 0x9f, 0x26, 0xde },
.rlen = 16,
},
};
-static struct cipher_testvec serpent_dec_tv_template[] =
-{
+static struct cipher_testvec serpent_dec_tv_template[] = {
{
.input = { 0x12, 0x07, 0xfc, 0xce, 0x9b, 0xd0, 0xd6, 0x47,
0x6a, 0xe9, 0x8f, 0xbe, 0xd1, 0x43, 0xa0, 0xe2 },
@@ -1713,8 +1716,7 @@ static struct cipher_testvec serpent_dec_tv_template[] =
},
};
-static struct cipher_testvec tnepres_dec_tv_template[] =
-{
+static struct cipher_testvec tnepres_dec_tv_template[] = {
{
.input = { 0x41, 0xcc, 0x6b, 0x31, 0x59, 0x31, 0x45, 0x97,
0x6d, 0x6f, 0xbb, 0x38, 0x4b, 0x37, 0x21, 0x28 },
@@ -1726,7 +1728,7 @@ static struct cipher_testvec tnepres_dec_tv_template[] =
.key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
.klen = 16,
- .input = { 0xea, 0xf4, 0xd7, 0xfc, 0xd8, 0x01, 0x34, 0x47,
+ .input = { 0xea, 0xf4, 0xd7, 0xfc, 0xd8, 0x01, 0x34, 0x47,
0x81, 0x45, 0x0b, 0xfa, 0x0c, 0xd6, 0xad, 0x6e },
.ilen = 16,
.result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
@@ -1738,7 +1740,7 @@ static struct cipher_testvec tnepres_dec_tv_template[] =
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
.klen = 32,
- .input = { 0x64, 0xa9, 0x1a, 0x37, 0xed, 0x9f, 0xe7, 0x49,
+ .input = { 0x64, 0xa9, 0x1a, 0x37, 0xed, 0x9f, 0xe7, 0x49,
0xa8, 0x4e, 0x76, 0xd6, 0xf5, 0x0d, 0x78, 0xee },
.ilen = 16,
.result = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
@@ -1747,7 +1749,7 @@ static struct cipher_testvec tnepres_dec_tv_template[] =
}, { /* KeySize=128, I=121 */
.key = { [15] = 0x80 },
.klen = 16,
- .input = { 0x3d, 0xda, 0xbf, 0xc0, 0x06, 0xda, 0xab, 0x06,
+ .input = { 0x3d, 0xda, 0xbf, 0xc0, 0x06, 0xda, 0xab, 0x06,
0x46, 0x2a, 0xf4, 0xef, 0x81, 0x54, 0x4e, 0x26 },
.ilen = 16,
.result = { [0 ... 15] = 0x00 },
@@ -1760,58 +1762,56 @@ static struct cipher_testvec tnepres_dec_tv_template[] =
#define CAST6_ENC_TEST_VECTORS 3
#define CAST6_DEC_TEST_VECTORS 3
-static struct cipher_testvec cast6_enc_tv_template[] =
-{
+static struct cipher_testvec cast6_enc_tv_template[] = {
{
- .key = { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
+ .key = { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
0x0a, 0xf7, 0x56, 0x47, 0xf2, 0x9f, 0x61, 0x5d },
.klen = 16,
.input = { [0 ... 15] = 0x00 },
.ilen = 16,
- .result = { 0xc8, 0x42, 0xa0, 0x89, 0x72, 0xb4, 0x3d, 0x20,
+ .result = { 0xc8, 0x42, 0xa0, 0x89, 0x72, 0xb4, 0x3d, 0x20,
0x83, 0x6c, 0x91, 0xd1, 0xb7, 0x53, 0x0f, 0x6b },
.rlen = 16,
}, {
- .key = { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
- 0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98,
+ .key = { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
+ 0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98,
0xba, 0xc7, 0x7a, 0x77, 0x17, 0x94, 0x28, 0x63 },
.klen = 24,
.input = { [0 ... 15] = 0x00 },
.ilen = 16,
- .result = { 0x1b, 0x38, 0x6c, 0x02, 0x10, 0xdc, 0xad, 0xcb,
+ .result = { 0x1b, 0x38, 0x6c, 0x02, 0x10, 0xdc, 0xad, 0xcb,
0xdd, 0x0e, 0x41, 0xaa, 0x08, 0xa7, 0xa7, 0xe8 },
.rlen = 16,
}, {
.key = { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98,
0x8d, 0x7c, 0x47, 0xce, 0x26, 0x49, 0x08, 0x46,
- 0x1c, 0xc1, 0xb5, 0x13, 0x7a, 0xe6, 0xb6, 0x04 },
+ 0x1c, 0xc1, 0xb5, 0x13, 0x7a, 0xe6, 0xb6, 0x04 },
.klen = 32,
.input = { [0 ... 15] = 0x00 },
.ilen = 16,
- .result = { 0x4f, 0x6a, 0x20, 0x38, 0x28, 0x68, 0x97, 0xb9,
+ .result = { 0x4f, 0x6a, 0x20, 0x38, 0x28, 0x68, 0x97, 0xb9,
0xc9, 0x87, 0x01, 0x36, 0x55, 0x33, 0x17, 0xfa },
.rlen = 16,
},
};
-static struct cipher_testvec cast6_dec_tv_template[] =
-{
+static struct cipher_testvec cast6_dec_tv_template[] = {
{
- .key = { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
+ .key = { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
0x0a, 0xf7, 0x56, 0x47, 0xf2, 0x9f, 0x61, 0x5d },
.klen = 16,
- .input = { 0xc8, 0x42, 0xa0, 0x89, 0x72, 0xb4, 0x3d, 0x20,
+ .input = { 0xc8, 0x42, 0xa0, 0x89, 0x72, 0xb4, 0x3d, 0x20,
0x83, 0x6c, 0x91, 0xd1, 0xb7, 0x53, 0x0f, 0x6b },
.ilen = 16,
.result = { [0 ... 15] = 0x00 },
.rlen = 16,
}, {
- .key = { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
- 0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98,
+ .key = { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
+ 0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98,
0xba, 0xc7, 0x7a, 0x77, 0x17, 0x94, 0x28, 0x63 },
.klen = 24,
- .input = { 0x1b, 0x38, 0x6c, 0x02, 0x10, 0xdc, 0xad, 0xcb,
+ .input = { 0x1b, 0x38, 0x6c, 0x02, 0x10, 0xdc, 0xad, 0xcb,
0xdd, 0x0e, 0x41, 0xaa, 0x08, 0xa7, 0xa7, 0xe8 },
.ilen = 16,
.result = { [0 ... 15] = 0x00 },
@@ -1820,9 +1820,9 @@ static struct cipher_testvec cast6_dec_tv_template[] =
.key = { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98,
0x8d, 0x7c, 0x47, 0xce, 0x26, 0x49, 0x08, 0x46,
- 0x1c, 0xc1, 0xb5, 0x13, 0x7a, 0xe6, 0xb6, 0x04 },
+ 0x1c, 0xc1, 0xb5, 0x13, 0x7a, 0xe6, 0xb6, 0x04 },
.klen = 32,
- .input = { 0x4f, 0x6a, 0x20, 0x38, 0x28, 0x68, 0x97, 0xb9,
+ .input = { 0x4f, 0x6a, 0x20, 0x38, 0x28, 0x68, 0x97, 0xb9,
0xc9, 0x87, 0x01, 0x36, 0x55, 0x33, 0x17, 0xfa },
.ilen = 16,
.result = { [0 ... 15] = 0x00 },
@@ -1837,9 +1837,9 @@ static struct cipher_testvec cast6_dec_tv_template[] =
#define AES_ENC_TEST_VECTORS 3
#define AES_DEC_TEST_VECTORS 3
-static struct cipher_testvec aes_enc_tv_template[] = {
+static struct cipher_testvec aes_enc_tv_template[] = {
{ /* From FIPS-197 */
- .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
.klen = 16,
.input = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
@@ -1853,7 +1853,7 @@ static struct cipher_testvec aes_enc_tv_template[] = {
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
.klen = 24,
- .input = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ .input = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
.ilen = 16,
.result = { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
@@ -1865,7 +1865,7 @@ static struct cipher_testvec aes_enc_tv_template[] = {
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
.klen = 32,
- .input = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ .input = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
.ilen = 16,
.result = { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
@@ -1874,9 +1874,9 @@ static struct cipher_testvec aes_enc_tv_template[] = {
},
};
-static struct cipher_testvec aes_dec_tv_template[] = {
+static struct cipher_testvec aes_dec_tv_template[] = {
{ /* From FIPS-197 */
- .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ .key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
.klen = 16,
.input = { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
@@ -1893,8 +1893,8 @@ static struct cipher_testvec aes_dec_tv_template[] = {
.input = { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 },
.ilen = 16,
- .result = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
- 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+ .result = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
.rlen = 16,
}, {
.key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
@@ -1905,7 +1905,7 @@ static struct cipher_testvec aes_dec_tv_template[] = {
.input = { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 },
.ilen = 16,
- .result = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ .result = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
.rlen = 16,
},
@@ -1915,8 +1915,7 @@ static struct cipher_testvec aes_dec_tv_template[] = {
#define CAST5_ENC_TEST_VECTORS 3
#define CAST5_DEC_TEST_VECTORS 3
-static struct cipher_testvec cast5_enc_tv_template[] =
-{
+static struct cipher_testvec cast5_enc_tv_template[] = {
{
.key = { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9a },
@@ -1943,8 +1942,7 @@ static struct cipher_testvec cast5_enc_tv_template[] =
},
};
-static struct cipher_testvec cast5_dec_tv_template[] =
-{
+static struct cipher_testvec cast5_dec_tv_template[] = {
{
.key = { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9a },
@@ -1971,14 +1969,13 @@ static struct cipher_testvec cast5_dec_tv_template[] =
},
};
-/*
- * ARC4 test vectors from OpenSSL
+/*
+ * ARC4 test vectors from OpenSSL
*/
#define ARC4_ENC_TEST_VECTORS 7
#define ARC4_DEC_TEST_VECTORS 7
-static struct cipher_testvec arc4_enc_tv_template[] =
-{
+static struct cipher_testvec arc4_enc_tv_template[] = {
{
.key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
.klen = 8,
@@ -2044,8 +2041,7 @@ static struct cipher_testvec arc4_enc_tv_template[] =
},
};
-static struct cipher_testvec arc4_dec_tv_template[] =
-{
+static struct cipher_testvec arc4_dec_tv_template[] = {
{
.key = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
.klen = 8,
@@ -2111,14 +2107,13 @@ static struct cipher_testvec arc4_dec_tv_template[] =
},
};
-/*
+/*
* TEA test vectors
*/
#define TEA_ENC_TEST_VECTORS 4
#define TEA_DEC_TEST_VECTORS 4
-static struct cipher_testvec tea_enc_tv_template[] =
-{
+static struct cipher_testvec tea_enc_tv_template[] = {
{
.key = { [0 ... 15] = 0x00 },
.klen = 16,
@@ -2138,31 +2133,30 @@ static struct cipher_testvec tea_enc_tv_template[] =
.key = { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
.klen = 16,
- .input = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
+ .input = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
.ilen = 16,
- .result = { 0xbe, 0x7a, 0xbb, 0x81, 0x95, 0x2d, 0x1f, 0x1e,
+ .result = { 0xbe, 0x7a, 0xbb, 0x81, 0x95, 0x2d, 0x1f, 0x1e,
0xdd, 0x89, 0xa1, 0x25, 0x04, 0x21, 0xdf, 0x95 },
.rlen = 16,
}, {
.key = { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
.klen = 16,
- .input = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
- 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
- 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
+ .input = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
+ 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
.ilen = 32,
- .result = { 0xe0, 0x4d, 0x5d, 0x3c, 0xb7, 0x8c, 0x36, 0x47,
- 0x94, 0x18, 0x95, 0x91, 0xa9, 0xfc, 0x49, 0xf8,
- 0x44, 0xd1, 0x2d, 0xc2, 0x99, 0xb8, 0x08, 0x2a,
+ .result = { 0xe0, 0x4d, 0x5d, 0x3c, 0xb7, 0x8c, 0x36, 0x47,
+ 0x94, 0x18, 0x95, 0x91, 0xa9, 0xfc, 0x49, 0xf8,
+ 0x44, 0xd1, 0x2d, 0xc2, 0x99, 0xb8, 0x08, 0x2a,
0x07, 0x89, 0x73, 0xc2, 0x45, 0x92, 0xc6, 0x90 },
.rlen = 32,
}
};
-static struct cipher_testvec tea_dec_tv_template[] =
-{
+static struct cipher_testvec tea_dec_tv_template[] = {
{
.key = { [0 ... 15] = 0x00 },
.klen = 16,
@@ -2183,9 +2177,9 @@ static struct cipher_testvec tea_dec_tv_template[] =
0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
.klen = 16,
.input = { 0xbe, 0x7a, 0xbb, 0x81, 0x95, 0x2d, 0x1f, 0x1e,
- 0xdd, 0x89, 0xa1, 0x25, 0x04, 0x21, 0xdf, 0x95 },
- .ilen = 16,
- .result = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
+ 0xdd, 0x89, 0xa1, 0x25, 0x04, 0x21, 0xdf, 0x95 },
+ .ilen = 16,
+ .result = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
.rlen = 16,
}, {
@@ -2193,26 +2187,25 @@ static struct cipher_testvec tea_dec_tv_template[] =
0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
.klen = 16,
.input = { 0xe0, 0x4d, 0x5d, 0x3c, 0xb7, 0x8c, 0x36, 0x47,
- 0x94, 0x18, 0x95, 0x91, 0xa9, 0xfc, 0x49, 0xf8,
- 0x44, 0xd1, 0x2d, 0xc2, 0x99, 0xb8, 0x08, 0x2a,
- 0x07, 0x89, 0x73, 0xc2, 0x45, 0x92, 0xc6, 0x90 },
+ 0x94, 0x18, 0x95, 0x91, 0xa9, 0xfc, 0x49, 0xf8,
+ 0x44, 0xd1, 0x2d, 0xc2, 0x99, 0xb8, 0x08, 0x2a,
+ 0x07, 0x89, 0x73, 0xc2, 0x45, 0x92, 0xc6, 0x90 },
.ilen = 32,
- .result = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
- 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
- 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
+ .result = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
+ 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
.rlen = 32,
}
};
-/*
- * XTEA test vectors
+/*
+ * XTEA test vectors
*/
#define XTEA_ENC_TEST_VECTORS 4
#define XTEA_DEC_TEST_VECTORS 4
-static struct cipher_testvec xtea_enc_tv_template[] =
-{
+static struct cipher_testvec xtea_enc_tv_template[] = {
{
.key = { [0 ... 15] = 0x00 },
.klen = 16,
@@ -2232,31 +2225,30 @@ static struct cipher_testvec xtea_enc_tv_template[] =
.key = { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
.klen = 16,
- .input = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
+ .input = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
.ilen = 16,
- .result = { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea,
+ .result = { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea,
0x61, 0x35, 0xaa, 0xed, 0xb5, 0xcb, 0x71, 0x2c },
.rlen = 16,
}, {
.key = { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
.klen = 16,
- .input = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
- 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
- 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
+ .input = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
+ 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
.ilen = 32,
- .result = { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1,
- 0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4,
- 0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f,
+ .result = { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1,
+ 0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4,
+ 0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f,
0xea, 0xa5, 0x6a, 0x85, 0xd1, 0xf4, 0xa8, 0xa5 },
.rlen = 32,
}
};
-static struct cipher_testvec xtea_dec_tv_template[] =
-{
+static struct cipher_testvec xtea_dec_tv_template[] = {
{
.key = { [0 ... 15] = 0x00 },
.klen = 16,
@@ -2276,24 +2268,24 @@ static struct cipher_testvec xtea_dec_tv_template[] =
.key = { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
.klen = 16,
- .input = { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea,
+ .input = { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea,
0x61, 0x35, 0xaa, 0xed, 0xb5, 0xcb, 0x71, 0x2c },
.ilen = 16,
- .result = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
+ .result = { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
.rlen = 16,
}, {
.key = { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
.klen = 16,
- .input = { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1,
- 0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4,
- 0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f,
+ .input = { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1,
+ 0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4,
+ 0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f,
0xea, 0xa5, 0x6a, 0x85, 0xd1, 0xf4, 0xa8, 0xa5 },
.ilen = 32,
- .result = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
- 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
- 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
+ .result = { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
+ 0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+ 0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
.rlen = 32,
}
@@ -2305,9 +2297,9 @@ static struct cipher_testvec xtea_dec_tv_template[] =
#define KHAZAD_ENC_TEST_VECTORS 5
#define KHAZAD_DEC_TEST_VECTORS 5
-static struct cipher_testvec khazad_enc_tv_template[] = {
- {
- .key = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+static struct cipher_testvec khazad_enc_tv_template[] = {
+ {
+ .key = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
.klen = 16,
.input = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
@@ -2351,9 +2343,9 @@ static struct cipher_testvec khazad_enc_tv_template[] = {
},
};
-static struct cipher_testvec khazad_dec_tv_template[] = {
+static struct cipher_testvec khazad_dec_tv_template[] = {
{
- .key = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ .key = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
.klen = 16,
.input = { 0X49, 0Xa4, 0Xce, 0X32, 0Xac, 0X19, 0X0e, 0X3f },
@@ -2697,8 +2689,7 @@ static struct comp_testvec deflate_decomp_tv_template[] = {
*/
#define MICHAEL_MIC_TEST_VECTORS 6
-static struct hash_testvec michael_mic_tv_template[] =
-{
+static struct hash_testvec michael_mic_tv_template[] = {
{
.key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
.ksize = 8,
@@ -2743,4 +2734,88 @@ static struct hash_testvec michael_mic_tv_template[] =
}
};
+/*
+ * Cipher speed tests
+ */
+static struct cipher_speed aes_speed_template[] = {
+ { .klen = 16, .blen = 16, },
+ { .klen = 16, .blen = 64, },
+ { .klen = 16, .blen = 256, },
+ { .klen = 16, .blen = 1024, },
+ { .klen = 16, .blen = 8192, },
+ { .klen = 24, .blen = 16, },
+ { .klen = 24, .blen = 64, },
+ { .klen = 24, .blen = 256, },
+ { .klen = 24, .blen = 1024, },
+ { .klen = 24, .blen = 8192, },
+ { .klen = 32, .blen = 16, },
+ { .klen = 32, .blen = 64, },
+ { .klen = 32, .blen = 256, },
+ { .klen = 32, .blen = 1024, },
+ { .klen = 32, .blen = 8192, },
+
+ /* End marker */
+ { .klen = 0, .blen = 0, }
+};
+
+static struct cipher_speed des3_ede_speed_template[] = {
+ { .klen = 24, .blen = 16, },
+ { .klen = 24, .blen = 64, },
+ { .klen = 24, .blen = 256, },
+ { .klen = 24, .blen = 1024, },
+ { .klen = 24, .blen = 8192, },
+
+ /* End marker */
+ { .klen = 0, .blen = 0, }
+};
+
+static struct cipher_speed twofish_speed_template[] = {
+ { .klen = 16, .blen = 16, },
+ { .klen = 16, .blen = 64, },
+ { .klen = 16, .blen = 256, },
+ { .klen = 16, .blen = 1024, },
+ { .klen = 16, .blen = 8192, },
+ { .klen = 24, .blen = 16, },
+ { .klen = 24, .blen = 64, },
+ { .klen = 24, .blen = 256, },
+ { .klen = 24, .blen = 1024, },
+ { .klen = 24, .blen = 8192, },
+ { .klen = 32, .blen = 16, },
+ { .klen = 32, .blen = 64, },
+ { .klen = 32, .blen = 256, },
+ { .klen = 32, .blen = 1024, },
+ { .klen = 32, .blen = 8192, },
+
+ /* End marker */
+ { .klen = 0, .blen = 0, }
+};
+
+static struct cipher_speed blowfish_speed_template[] = {
+ /* Don't support blowfish keys > 256 bit in this test */
+ { .klen = 8, .blen = 16, },
+ { .klen = 8, .blen = 64, },
+ { .klen = 8, .blen = 256, },
+ { .klen = 8, .blen = 1024, },
+ { .klen = 8, .blen = 8192, },
+ { .klen = 32, .blen = 16, },
+ { .klen = 32, .blen = 64, },
+ { .klen = 32, .blen = 256, },
+ { .klen = 32, .blen = 1024, },
+ { .klen = 32, .blen = 8192, },
+
+ /* End marker */
+ { .klen = 0, .blen = 0, }
+};
+
+static struct cipher_speed des_speed_template[] = {
+ { .klen = 8, .blen = 16, },
+ { .klen = 8, .blen = 64, },
+ { .klen = 8, .blen = 256, },
+ { .klen = 8, .blen = 1024, },
+ { .klen = 8, .blen = 8192, },
+
+ /* End marker */
+ { .klen = 0, .blen = 0, }
+};
+
#endif /* _CRYPTO_TCRYPT_H */
diff --git a/drivers/Kconfig b/drivers/Kconfig
index ed41d9036bf..aed4a9b97c1 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -58,4 +58,6 @@ source "drivers/mmc/Kconfig"
source "drivers/infiniband/Kconfig"
+source "drivers/sn/Kconfig"
+
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 15681de688f..3167be54fed 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -61,6 +61,6 @@ obj-$(CONFIG_EISA) += eisa/
obj-$(CONFIG_CPU_FREQ) += cpufreq/
obj-$(CONFIG_MMC) += mmc/
obj-$(CONFIG_INFINIBAND) += infiniband/
-obj-$(CONFIG_BLK_DEV_SGIIOC4) += sn/
+obj-$(CONFIG_SGI_IOC4) += sn/
obj-y += firmware/
obj-$(CONFIG_CRYPTO) += crypto/
diff --git a/drivers/acorn/char/pcf8583.c b/drivers/acorn/char/pcf8583.c
index ad7ae7ab892..141b4c237a5 100644
--- a/drivers/acorn/char/pcf8583.c
+++ b/drivers/acorn/char/pcf8583.c
@@ -26,11 +26,8 @@ static unsigned short normal_addr[] = { 0x50, I2C_CLIENT_END };
static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_addr,
- .normal_i2c_range = ignore,
.probe = ignore,
- .probe_range = ignore,
.ignore = ignore,
- .ignore_range = ignore,
.force = ignore,
};
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 0400a52d508..86c52520ed3 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -40,13 +40,12 @@ config ACPI
available at:
<http://www.acpi.info>
+if ACPI
+
config ACPI_BOOT
bool
- depends on ACPI || X86_HT
default y
-if ACPI
-
config ACPI_INTERPRETER
bool
depends on !IA64_SGI_SN
@@ -56,7 +55,7 @@ if ACPI_INTERPRETER
config ACPI_SLEEP
bool "Sleep States (EXPERIMENTAL)"
- depends on X86
+ depends on X86 && (!SMP || SUSPEND_SMP)
depends on EXPERIMENTAL && PM
default y
---help---
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 12b0eea6340..8dbf802ee7f 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -391,7 +391,6 @@ acpi_pci_irq_enable (
u8 pin = 0;
int edge_level = ACPI_LEVEL_SENSITIVE;
int active_high_low = ACPI_ACTIVE_LOW;
- extern int via_interrupt_line_quirk;
char *link = NULL;
ACPI_FUNCTION_TRACE("acpi_pci_irq_enable");
@@ -436,6 +435,7 @@ acpi_pci_irq_enable (
/* Interrupt Line values above 0xF are forbidden */
if (dev->irq >= 0 && (dev->irq <= 0xF)) {
printk(" - using IRQ %d\n", dev->irq);
+ acpi_register_gsi(dev->irq, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW);
return_VALUE(0);
}
else {
@@ -444,9 +444,6 @@ acpi_pci_irq_enable (
}
}
- if (via_interrupt_line_quirk)
- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq & 15);
-
dev->irq = acpi_register_gsi(irq, edge_level, active_high_low);
printk(KERN_INFO PREFIX "PCI Interrupt %s[%c] -> ",
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index ff64d333e95..c9d671cf785 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -171,7 +171,7 @@ static void acpi_processor_idle (void)
int sleep_ticks = 0;
u32 t1, t2 = 0;
- pr = processors[_smp_processor_id()];
+ pr = processors[raw_smp_processor_id()];
if (!pr)
return;
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 119c94093a1..e8588559328 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -65,14 +65,14 @@ static ssize_t acpi_device_attr_show(struct kobject *kobj,
{
struct acpi_device *device = to_acpi_device(kobj);
struct acpi_device_attribute *attribute = to_handle_attr(attr);
- return attribute->show ? attribute->show(device, buf) : 0;
+ return attribute->show ? attribute->show(device, buf) : -EIO;
}
static ssize_t acpi_device_attr_store(struct kobject *kobj,
struct attribute *attr, const char *buf, size_t len)
{
struct acpi_device *device = to_acpi_device(kobj);
struct acpi_device_attribute *attribute = to_handle_attr(attr);
- return attribute->store ? attribute->store(device, buf, len) : len;
+ return attribute->store ? attribute->store(device, buf, len) : -EIO;
}
static struct sysfs_ops acpi_device_sysfs_ops = {
diff --git a/drivers/atm/Makefile b/drivers/atm/Makefile
index d1dcd8eae3c..5b77188527a 100644
--- a/drivers/atm/Makefile
+++ b/drivers/atm/Makefile
@@ -39,7 +39,8 @@ ifeq ($(CONFIG_ATM_FORE200E_PCA),y)
fore_200e-objs += fore200e_pca_fw.o
# guess the target endianess to choose the right PCA-200E firmware image
ifeq ($(CONFIG_ATM_FORE200E_PCA_DEFAULT_FW),y)
- CONFIG_ATM_FORE200E_PCA_FW = $(shell if test -n "`$(CC) -E -dM $(src)/../../include/asm/byteorder.h | grep ' __LITTLE_ENDIAN '`"; then echo $(obj)/pca200e.bin; else echo $(obj)/pca200e_ecd.bin2; fi)
+ byteorder.h := include$(if $(patsubst $(srctree),,$(objtree)),2)/asm/byteorder.h
+ CONFIG_ATM_FORE200E_PCA_FW := $(obj)/pca200e$(if $(shell $(CC) -E -dM $(byteorder.h) | grep ' __LITTLE_ENDIAN '),.bin,_ecd.bin2)
endif
endif
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index 9e65bfb85ba..5f702199543 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -383,8 +383,7 @@ fore200e_shutdown(struct fore200e* fore200e)
switch(fore200e->state) {
case FORE200E_STATE_COMPLETE:
- if (fore200e->stats)
- kfree(fore200e->stats);
+ kfree(fore200e->stats);
case FORE200E_STATE_IRQ:
free_irq(fore200e->irq, fore200e->atm_dev);
@@ -963,8 +962,7 @@ fore200e_tx_irq(struct fore200e* fore200e)
entry, txq->tail, entry->vc_map, entry->skb);
/* free copy of misaligned data */
- if (entry->data)
- kfree(entry->data);
+ kfree(entry->data);
/* remove DMA mapping */
fore200e->bus->dma_unmap(fore200e, entry->tpd->tsd[ 0 ].buffer, entry->tpd->tsd[ 0 ].length,
diff --git a/drivers/atm/he.c b/drivers/atm/he.c
index 3022c548a13..df2c83fd549 100644
--- a/drivers/atm/he.c
+++ b/drivers/atm/he.c
@@ -412,8 +412,7 @@ he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
init_one_failure:
if (atm_dev)
atm_dev_deregister(atm_dev);
- if (he_dev)
- kfree(he_dev);
+ kfree(he_dev);
pci_disable_device(pci_dev);
return err;
}
@@ -2534,8 +2533,7 @@ he_open(struct atm_vcc *vcc)
open_failed:
if (err) {
- if (he_vcc)
- kfree(he_vcc);
+ kfree(he_vcc);
clear_bit(ATM_VF_ADDR, &vcc->flags);
}
else
diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c
index 85bf5c8442b..b2a7b754fd1 100644
--- a/drivers/atm/nicstar.c
+++ b/drivers/atm/nicstar.c
@@ -676,10 +676,10 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
PRINTK("nicstar%d: RSQ base at 0x%x.\n", i, (u32) card->rsq.base);
/* Initialize SCQ0, the only VBR SCQ used */
- card->scq1 = (scq_info *) NULL;
- card->scq2 = (scq_info *) NULL;
+ card->scq1 = NULL;
+ card->scq2 = NULL;
card->scq0 = get_scq(VBR_SCQSIZE, NS_VRSCD0);
- if (card->scq0 == (scq_info *) NULL)
+ if (card->scq0 == NULL)
{
printk("nicstar%d: can't get SCQ0.\n", i);
error = 12;
@@ -993,24 +993,24 @@ static scq_info *get_scq(int size, u32 scd)
int i;
if (size != VBR_SCQSIZE && size != CBR_SCQSIZE)
- return (scq_info *) NULL;
+ return NULL;
scq = (scq_info *) kmalloc(sizeof(scq_info), GFP_KERNEL);
- if (scq == (scq_info *) NULL)
- return (scq_info *) NULL;
+ if (scq == NULL)
+ return NULL;
scq->org = kmalloc(2 * size, GFP_KERNEL);
if (scq->org == NULL)
{
kfree(scq);
- return (scq_info *) NULL;
+ return NULL;
}
scq->skb = (struct sk_buff **) kmalloc(sizeof(struct sk_buff *) *
(size / NS_SCQE_SIZE), GFP_KERNEL);
- if (scq->skb == (struct sk_buff **) NULL)
+ if (scq->skb == NULL)
{
kfree(scq->org);
kfree(scq);
- return (scq_info *) NULL;
+ return NULL;
}
scq->num_entries = size / NS_SCQE_SIZE;
scq->base = (ns_scqe *) ALIGN_ADDRESS(scq->org, size);
@@ -1498,7 +1498,7 @@ static int ns_open(struct atm_vcc *vcc)
vc->cbr_scd = NS_FRSCD + frscdi * NS_FRSCD_SIZE;
scq = get_scq(CBR_SCQSIZE, vc->cbr_scd);
- if (scq == (scq_info *) NULL)
+ if (scq == NULL)
{
PRINTK("nicstar%d: can't get fixed rate SCQ.\n", card->index);
card->scd2vc[frscdi] = NULL;
diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c
index 47a800519ad..8d5e65cb975 100644
--- a/drivers/atm/zatm.c
+++ b/drivers/atm/zatm.c
@@ -902,7 +902,7 @@ static void close_tx(struct atm_vcc *vcc)
zatm_dev->tx_bw += vcc->qos.txtp.min_pcr;
dealloc_shaper(vcc->dev,zatm_vcc->shaper);
}
- if (zatm_vcc->ring) kfree(zatm_vcc->ring);
+ kfree(zatm_vcc->ring);
}
@@ -1339,12 +1339,9 @@ static int __init zatm_start(struct atm_dev *dev)
return 0;
out:
for (i = 0; i < NR_MBX; i++)
- if (zatm_dev->mbx_start[i] != 0)
- kfree((void *) zatm_dev->mbx_start[i]);
- if (zatm_dev->rx_map != NULL)
- kfree(zatm_dev->rx_map);
- if (zatm_dev->tx_map != NULL)
- kfree(zatm_dev->tx_map);
+ kfree(zatm_dev->mbx_start[i]);
+ kfree(zatm_dev->rx_map);
+ kfree(zatm_dev->tx_map);
free_irq(zatm_dev->irq, dev);
return error;
}
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 6662b545e0a..66d9c4643fc 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -1,7 +1,7 @@
# Makefile for the Linux device tree
-obj-y := core.o sys.o interface.o bus.o \
- driver.o class.o class_simple.o platform.o \
+obj-y := core.o sys.o bus.o dd.o \
+ driver.o class.o platform.o \
cpu.o firmware.o init.o map.o dmapool.o \
attribute_container.o transport_class.o
obj-y += power/
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 8d1e8bd4863..645f6269292 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -4,6 +4,8 @@ extern void bus_remove_device(struct device * dev);
extern int bus_add_driver(struct device_driver *);
extern void bus_remove_driver(struct device_driver *);
+extern void driver_detach(struct device_driver * drv);
+
static inline struct class_device *to_class_dev(struct kobject *obj)
{
return container_of(obj, struct class_device, kobj);
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 2b3902c867d..c3fac7fd555 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -17,9 +17,6 @@
#include "base.h"
#include "power/power.h"
-#define to_dev(node) container_of(node, struct device, bus_list)
-#define to_drv(node) container_of(node, struct device_driver, kobj.entry)
-
#define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr)
#define to_bus(obj) container_of(obj, struct bus_type, subsys.kset.kobj)
@@ -36,7 +33,7 @@ drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
{
struct driver_attribute * drv_attr = to_drv_attr(attr);
struct device_driver * drv = to_driver(kobj);
- ssize_t ret = 0;
+ ssize_t ret = -EIO;
if (drv_attr->show)
ret = drv_attr->show(drv, buf);
@@ -49,7 +46,7 @@ drv_attr_store(struct kobject * kobj, struct attribute * attr,
{
struct driver_attribute * drv_attr = to_drv_attr(attr);
struct device_driver * drv = to_driver(kobj);
- ssize_t ret = 0;
+ ssize_t ret = -EIO;
if (drv_attr->store)
ret = drv_attr->store(drv, buf, count);
@@ -135,50 +132,11 @@ static struct kobj_type ktype_bus = {
decl_subsys(bus, &ktype_bus, NULL);
-static int __bus_for_each_dev(struct bus_type *bus, struct device *start,
- void *data, int (*fn)(struct device *, void *))
-{
- struct list_head *head;
- struct device *dev;
- int error = 0;
-
- if (!(bus = get_bus(bus)))
- return -EINVAL;
-
- head = &bus->devices.list;
- dev = list_prepare_entry(start, head, bus_list);
- list_for_each_entry_continue(dev, head, bus_list) {
- get_device(dev);
- error = fn(dev, data);
- put_device(dev);
- if (error)
- break;
- }
- put_bus(bus);
- return error;
-}
-static int __bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
- void * data, int (*fn)(struct device_driver *, void *))
+static struct device * next_device(struct klist_iter * i)
{
- struct list_head *head;
- struct device_driver *drv;
- int error = 0;
-
- if (!(bus = get_bus(bus)))
- return -EINVAL;
-
- head = &bus->drivers.list;
- drv = list_prepare_entry(start, head, kobj.entry);
- list_for_each_entry_continue(drv, head, kobj.entry) {
- get_driver(drv);
- error = fn(drv, data);
- put_driver(drv);
- if (error)
- break;
- }
- put_bus(bus);
- return error;
+ struct klist_node * n = klist_next(i);
+ return n ? container_of(n, struct device, knode_bus) : NULL;
}
/**
@@ -204,12 +162,27 @@ static int __bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
int bus_for_each_dev(struct bus_type * bus, struct device * start,
void * data, int (*fn)(struct device *, void *))
{
- int ret;
+ struct klist_iter i;
+ struct device * dev;
+ int error = 0;
- down_read(&bus->subsys.rwsem);
- ret = __bus_for_each_dev(bus, start, data, fn);
- up_read(&bus->subsys.rwsem);
- return ret;
+ if (!bus)
+ return -EINVAL;
+
+ klist_iter_init_node(&bus->klist_devices, &i,
+ (start ? &start->knode_bus : NULL));
+ while ((dev = next_device(&i)) && !error)
+ error = fn(dev, data);
+ klist_iter_exit(&i);
+ return error;
+}
+
+
+
+static struct device_driver * next_driver(struct klist_iter * i)
+{
+ struct klist_node * n = klist_next(i);
+ return n ? container_of(n, struct device_driver, knode_bus) : NULL;
}
/**
@@ -235,180 +208,19 @@ int bus_for_each_dev(struct bus_type * bus, struct device * start,
int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
void * data, int (*fn)(struct device_driver *, void *))
{
- int ret;
-
- down_read(&bus->subsys.rwsem);
- ret = __bus_for_each_drv(bus, start, data, fn);
- up_read(&bus->subsys.rwsem);
- return ret;
-}
-
-/**
- * device_bind_driver - bind a driver to one device.
- * @dev: device.
- *
- * Allow manual attachment of a driver to a device.
- * Caller must have already set @dev->driver.
- *
- * Note that this does not modify the bus reference count
- * nor take the bus's rwsem. Please verify those are accounted
- * for before calling this. (It is ok to call with no other effort
- * from a driver's probe() method.)
- */
-
-void device_bind_driver(struct device * dev)
-{
- pr_debug("bound device '%s' to driver '%s'\n",
- dev->bus_id, dev->driver->name);
- list_add_tail(&dev->driver_list, &dev->driver->devices);
- sysfs_create_link(&dev->driver->kobj, &dev->kobj,
- kobject_name(&dev->kobj));
- sysfs_create_link(&dev->kobj, &dev->driver->kobj, "driver");
-}
-
-
-/**
- * driver_probe_device - attempt to bind device & driver.
- * @drv: driver.
- * @dev: device.
- *
- * First, we call the bus's match function, if one present, which
- * should compare the device IDs the driver supports with the
- * device IDs of the device. Note we don't do this ourselves
- * because we don't know the format of the ID structures, nor what
- * is to be considered a match and what is not.
- *
- * If we find a match, we call @drv->probe(@dev) if it exists, and
- * call device_bind_driver() above.
- */
-int driver_probe_device(struct device_driver * drv, struct device * dev)
-{
- if (drv->bus->match && !drv->bus->match(dev, drv))
- return -ENODEV;
-
- dev->driver = drv;
- if (drv->probe) {
- int error = drv->probe(dev);
- if (error) {
- dev->driver = NULL;
- return error;
- }
- }
-
- device_bind_driver(dev);
- return 0;
-}
-
-
-/**
- * device_attach - try to attach device to a driver.
- * @dev: device.
- *
- * Walk the list of drivers that the bus has and call
- * driver_probe_device() for each pair. If a compatible
- * pair is found, break out and return.
- */
-int device_attach(struct device * dev)
-{
- struct bus_type * bus = dev->bus;
- struct list_head * entry;
- int error;
-
- if (dev->driver) {
- device_bind_driver(dev);
- return 1;
- }
-
- if (bus->match) {
- list_for_each(entry, &bus->drivers.list) {
- struct device_driver * drv = to_drv(entry);
- error = driver_probe_device(drv, dev);
- if (!error)
- /* success, driver matched */
- return 1;
- if (error != -ENODEV && error != -ENXIO)
- /* driver matched but the probe failed */
- printk(KERN_WARNING
- "%s: probe of %s failed with error %d\n",
- drv->name, dev->bus_id, error);
- }
- }
-
- return 0;
-}
-
-
-/**
- * driver_attach - try to bind driver to devices.
- * @drv: driver.
- *
- * Walk the list of devices that the bus has on it and try to
- * match the driver with each one. If driver_probe_device()
- * returns 0 and the @dev->driver is set, we've found a
- * compatible pair.
- *
- * Note that we ignore the -ENODEV error from driver_probe_device(),
- * since it's perfectly valid for a driver not to bind to any devices.
- */
-void driver_attach(struct device_driver * drv)
-{
- struct bus_type * bus = drv->bus;
- struct list_head * entry;
- int error;
-
- if (!bus->match)
- return;
-
- list_for_each(entry, &bus->devices.list) {
- struct device * dev = container_of(entry, struct device, bus_list);
- if (!dev->driver) {
- error = driver_probe_device(drv, dev);
- if (error && (error != -ENODEV))
- /* driver matched but the probe failed */
- printk(KERN_WARNING
- "%s: probe of %s failed with error %d\n",
- drv->name, dev->bus_id, error);
- }
- }
-}
-
-
-/**
- * device_release_driver - manually detach device from driver.
- * @dev: device.
- *
- * Manually detach device from driver.
- * Note that this is called without incrementing the bus
- * reference count nor taking the bus's rwsem. Be sure that
- * those are accounted for before calling this function.
- */
-
-void device_release_driver(struct device * dev)
-{
- struct device_driver * drv = dev->driver;
- if (drv) {
- sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
- sysfs_remove_link(&dev->kobj, "driver");
- list_del_init(&dev->driver_list);
- device_detach_shutdown(dev);
- if (drv->remove)
- drv->remove(dev);
- dev->driver = NULL;
- }
-}
-
+ struct klist_iter i;
+ struct device_driver * drv;
+ int error = 0;
-/**
- * driver_detach - detach driver from all devices it controls.
- * @drv: driver.
- */
+ if (!bus)
+ return -EINVAL;
-static void driver_detach(struct device_driver * drv)
-{
- while (!list_empty(&drv->devices)) {
- struct device * dev = container_of(drv->devices.next, struct device, driver_list);
- device_release_driver(dev);
- }
+ klist_iter_init_node(&bus->klist_drivers, &i,
+ start ? &start->knode_bus : NULL);
+ while ((drv = next_driver(&i)) && !error)
+ error = fn(drv, data);
+ klist_iter_exit(&i);
+ return error;
}
static int device_add_attrs(struct bus_type * bus, struct device * dev)
@@ -457,14 +269,14 @@ int bus_add_device(struct device * dev)
int error = 0;
if (bus) {
- down_write(&dev->bus->subsys.rwsem);
pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id);
- list_add_tail(&dev->bus_list, &dev->bus->devices.list);
device_attach(dev);
- up_write(&dev->bus->subsys.rwsem);
- device_add_attrs(bus, dev);
- sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
- sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus");
+ klist_add_tail(&bus->klist_devices, &dev->knode_bus);
+ error = device_add_attrs(bus, dev);
+ if (!error) {
+ sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
+ sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus");
+ }
}
return error;
}
@@ -484,11 +296,9 @@ void bus_remove_device(struct device * dev)
sysfs_remove_link(&dev->kobj, "bus");
sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id);
device_remove_attrs(dev->bus, dev);
- down_write(&dev->bus->subsys.rwsem);
+ klist_remove(&dev->knode_bus);
pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id);
device_release_driver(dev);
- list_del_init(&dev->bus_list);
- up_write(&dev->bus->subsys.rwsem);
put_bus(dev->bus);
}
}
@@ -548,9 +358,8 @@ int bus_add_driver(struct device_driver * drv)
return error;
}
- down_write(&bus->subsys.rwsem);
driver_attach(drv);
- up_write(&bus->subsys.rwsem);
+ klist_add_tail(&bus->klist_drivers, &drv->knode_bus);
module_add_driver(drv->owner, drv);
driver_add_attrs(bus, drv);
@@ -572,10 +381,9 @@ void bus_remove_driver(struct device_driver * drv)
{
if (drv->bus) {
driver_remove_attrs(drv->bus, drv);
- down_write(&drv->bus->subsys.rwsem);
+ klist_remove(&drv->knode_bus);
pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
driver_detach(drv);
- up_write(&drv->bus->subsys.rwsem);
module_remove_driver(drv);
kobject_unregister(&drv->kobj);
put_bus(drv->bus);
@@ -588,7 +396,7 @@ static int bus_rescan_devices_helper(struct device *dev, void *data)
{
int *count = data;
- if (!dev->driver && device_attach(dev))
+ if (!dev->driver && (device_attach(dev) > 0))
(*count)++;
return 0;
@@ -608,9 +416,7 @@ int bus_rescan_devices(struct bus_type * bus)
{
int count = 0;
- down_write(&bus->subsys.rwsem);
- __bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper);
- up_write(&bus->subsys.rwsem);
+ bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper);
return count;
}
@@ -711,6 +517,9 @@ int bus_register(struct bus_type * bus)
retval = kset_register(&bus->drivers);
if (retval)
goto bus_drivers_fail;
+
+ klist_init(&bus->klist_devices);
+ klist_init(&bus->klist_drivers);
bus_add_attrs(bus);
pr_debug("bus type '%s' registered\n", bus->name);
@@ -750,12 +559,6 @@ int __init buses_init(void)
EXPORT_SYMBOL_GPL(bus_for_each_dev);
EXPORT_SYMBOL_GPL(bus_for_each_drv);
-EXPORT_SYMBOL_GPL(driver_probe_device);
-EXPORT_SYMBOL_GPL(device_bind_driver);
-EXPORT_SYMBOL_GPL(device_release_driver);
-EXPORT_SYMBOL_GPL(device_attach);
-EXPORT_SYMBOL_GPL(driver_attach);
-
EXPORT_SYMBOL_GPL(bus_add_device);
EXPORT_SYMBOL_GPL(bus_remove_device);
EXPORT_SYMBOL_GPL(bus_register);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index d2a2f8f2b4e..479c1257088 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -16,6 +16,7 @@
#include <linux/init.h>
#include <linux/string.h>
#include <linux/kdev_t.h>
+#include <linux/err.h>
#include "base.h"
#define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
@@ -26,7 +27,7 @@ class_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
{
struct class_attribute * class_attr = to_class_attr(attr);
struct class * dc = to_class(kobj);
- ssize_t ret = 0;
+ ssize_t ret = -EIO;
if (class_attr->show)
ret = class_attr->show(dc, buf);
@@ -39,7 +40,7 @@ class_attr_store(struct kobject * kobj, struct attribute * attr,
{
struct class_attribute * class_attr = to_class_attr(attr);
struct class * dc = to_class(kobj);
- ssize_t ret = 0;
+ ssize_t ret = -EIO;
if (class_attr->store)
ret = class_attr->store(dc, buf, count);
@@ -162,6 +163,69 @@ void class_unregister(struct class * cls)
subsystem_unregister(&cls->subsys);
}
+static void class_create_release(struct class *cls)
+{
+ kfree(cls);
+}
+
+static void class_device_create_release(struct class_device *class_dev)
+{
+ kfree(class_dev);
+}
+
+/**
+ * class_create - create a struct class structure
+ * @owner: pointer to the module that is to "own" this struct class
+ * @name: pointer to a string for the name of this class.
+ *
+ * This is used to create a struct class pointer that can then be used
+ * in calls to class_device_create().
+ *
+ * Note, the pointer created here is to be destroyed when finished by
+ * making a call to class_destroy().
+ */
+struct class *class_create(struct module *owner, char *name)
+{
+ struct class *cls;
+ int retval;
+
+ cls = kmalloc(sizeof(struct class), GFP_KERNEL);
+ if (!cls) {
+ retval = -ENOMEM;
+ goto error;
+ }
+ memset(cls, 0x00, sizeof(struct class));
+
+ cls->name = name;
+ cls->owner = owner;
+ cls->class_release = class_create_release;
+ cls->release = class_device_create_release;
+
+ retval = class_register(cls);
+ if (retval)
+ goto error;
+
+ return cls;
+
+error:
+ kfree(cls);
+ return ERR_PTR(retval);
+}
+
+/**
+ * class_destroy - destroys a struct class structure
+ * @cs: pointer to the struct class that is to be destroyed
+ *
+ * Note, the pointer to be destroyed must have been created with a call
+ * to class_create().
+ */
+void class_destroy(struct class *cls)
+{
+ if ((cls == NULL) || (IS_ERR(cls)))
+ return;
+
+ class_unregister(cls);
+}
/* Class Device Stuff */
@@ -262,7 +326,7 @@ static int class_hotplug_filter(struct kset *kset, struct kobject *kobj)
return 0;
}
-static char *class_hotplug_name(struct kset *kset, struct kobject *kobj)
+static const char *class_hotplug_name(struct kset *kset, struct kobject *kobj)
{
struct class_device *class_dev = to_class_dev(kobj);
@@ -375,7 +439,6 @@ static ssize_t show_dev(struct class_device *class_dev, char *buf)
{
return print_dev_t(buf, class_dev->devt);
}
-static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
void class_device_initialize(struct class_device *class_dev)
{
@@ -412,7 +475,31 @@ int class_device_add(struct class_device *class_dev)
if ((error = kobject_add(&class_dev->kobj)))
goto register_done;
- /* now take care of our own registration */
+ /* add the needed attributes to this device */
+ if (MAJOR(class_dev->devt)) {
+ struct class_device_attribute *attr;
+ attr = kmalloc(sizeof(*attr), GFP_KERNEL);
+ if (!attr) {
+ error = -ENOMEM;
+ kobject_del(&class_dev->kobj);
+ goto register_done;
+ }
+ memset(attr, sizeof(*attr), 0x00);
+ attr->attr.name = "dev";
+ attr->attr.mode = S_IRUGO;
+ attr->attr.owner = parent->owner;
+ attr->show = show_dev;
+ attr->store = NULL;
+ class_device_create_file(class_dev, attr);
+ class_dev->devt_attr = attr;
+ }
+
+ class_device_add_attrs(class_dev);
+ if (class_dev->dev)
+ sysfs_create_link(&class_dev->kobj,
+ &class_dev->dev->kobj, "device");
+
+ /* notify any interfaces this device is now here */
if (parent) {
down(&parent->sem);
list_add_tail(&class_dev->node, &parent->children);
@@ -421,16 +508,8 @@ int class_device_add(struct class_device *class_dev)
class_intf->add(class_dev);
up(&parent->sem);
}
-
- if (MAJOR(class_dev->devt))
- class_device_create_file(class_dev, &class_device_attr_dev);
-
- class_device_add_attrs(class_dev);
- if (class_dev->dev)
- sysfs_create_link(&class_dev->kobj,
- &class_dev->dev->kobj, "device");
-
kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
+
register_done:
if (error && parent)
class_put(parent);
@@ -444,6 +523,58 @@ int class_device_register(struct class_device *class_dev)
return class_device_add(class_dev);
}
+/**
+ * class_device_create - creates a class device and registers it with sysfs
+ * @cs: pointer to the struct class that this device should be registered to.
+ * @dev: the dev_t for the char device to be added.
+ * @device: a pointer to a struct device that is assiociated with this class device.
+ * @fmt: string for the class device's name
+ *
+ * This function can be used by char device classes. A struct
+ * class_device will be created in sysfs, registered to the specified
+ * class. A "dev" file will be created, showing the dev_t for the
+ * device. The pointer to the struct class_device will be returned from
+ * the call. Any further sysfs files that might be required can be
+ * created using this pointer.
+ *
+ * Note: the struct class passed to this function must have previously
+ * been created with a call to class_create().
+ */
+struct class_device *class_device_create(struct class *cls, dev_t devt,
+ struct device *device, char *fmt, ...)
+{
+ va_list args;
+ struct class_device *class_dev = NULL;
+ int retval = -ENODEV;
+
+ if (cls == NULL || IS_ERR(cls))
+ goto error;
+
+ class_dev = kmalloc(sizeof(struct class_device), GFP_KERNEL);
+ if (!class_dev) {
+ retval = -ENOMEM;
+ goto error;
+ }
+ memset(class_dev, 0x00, sizeof(struct class_device));
+
+ class_dev->devt = devt;
+ class_dev->dev = device;
+ class_dev->class = cls;
+
+ va_start(args, fmt);
+ vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args);
+ va_end(args);
+ retval = class_device_register(class_dev);
+ if (retval)
+ goto error;
+
+ return class_dev;
+
+error:
+ kfree(class_dev);
+ return ERR_PTR(retval);
+}
+
void class_device_del(struct class_device *class_dev)
{
struct class * parent = class_dev->class;
@@ -460,6 +591,11 @@ void class_device_del(struct class_device *class_dev)
if (class_dev->dev)
sysfs_remove_link(&class_dev->kobj, "device");
+ if (class_dev->devt_attr) {
+ class_device_remove_file(class_dev, class_dev->devt_attr);
+ kfree(class_dev->devt_attr);
+ class_dev->devt_attr = NULL;
+ }
class_device_remove_attrs(class_dev);
kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE);
@@ -477,6 +613,32 @@ void class_device_unregister(struct class_device *class_dev)
class_device_put(class_dev);
}
+/**
+ * class_device_destroy - removes a class device that was created with class_device_create()
+ * @cls: the pointer to the struct class that this device was registered * with.
+ * @dev: the dev_t of the device that was previously registered.
+ *
+ * This call unregisters and cleans up a class device that was created with a
+ * call to class_device_create()
+ */
+void class_device_destroy(struct class *cls, dev_t devt)
+{
+ struct class_device *class_dev = NULL;
+ struct class_device *class_dev_tmp;
+
+ down(&cls->sem);
+ list_for_each_entry(class_dev_tmp, &cls->children, node) {
+ if (class_dev_tmp->devt == devt) {
+ class_dev = class_dev_tmp;
+ break;
+ }
+ }
+ up(&cls->sem);
+
+ if (class_dev)
+ class_device_unregister(class_dev);
+}
+
int class_device_rename(struct class_device *class_dev, char *new_name)
{
int error = 0;
@@ -576,6 +738,8 @@ EXPORT_SYMBOL_GPL(class_register);
EXPORT_SYMBOL_GPL(class_unregister);
EXPORT_SYMBOL_GPL(class_get);
EXPORT_SYMBOL_GPL(class_put);
+EXPORT_SYMBOL_GPL(class_create);
+EXPORT_SYMBOL_GPL(class_destroy);
EXPORT_SYMBOL_GPL(class_device_register);
EXPORT_SYMBOL_GPL(class_device_unregister);
@@ -584,6 +748,8 @@ EXPORT_SYMBOL_GPL(class_device_add);
EXPORT_SYMBOL_GPL(class_device_del);
EXPORT_SYMBOL_GPL(class_device_get);
EXPORT_SYMBOL_GPL(class_device_put);
+EXPORT_SYMBOL_GPL(class_device_create);
+EXPORT_SYMBOL_GPL(class_device_destroy);
EXPORT_SYMBOL_GPL(class_device_create_file);
EXPORT_SYMBOL_GPL(class_device_remove_file);
EXPORT_SYMBOL_GPL(class_device_create_bin_file);
diff --git a/drivers/base/class_simple.c b/drivers/base/class_simple.c
deleted file mode 100644
index 27699eb20a3..00000000000
--- a/drivers/base/class_simple.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * class_simple.c - a "simple" interface for classes for simple char devices.
- *
- * Copyright (c) 2003-2004 Greg Kroah-Hartman <greg@kroah.com>
- * Copyright (c) 2003-2004 IBM Corp.
- *
- * This file is released under the GPLv2
- *
- */
-
-#include <linux/config.h>
-#include <linux/device.h>
-#include <linux/err.h>
-
-struct class_simple {
- struct class class;
-};
-#define to_class_simple(d) container_of(d, struct class_simple, class)
-
-struct simple_dev {
- struct list_head node;
- struct class_device class_dev;
-};
-#define to_simple_dev(d) container_of(d, struct simple_dev, class_dev)
-
-static LIST_HEAD(simple_dev_list);
-static DEFINE_SPINLOCK(simple_dev_list_lock);
-
-static void release_simple_dev(struct class_device *class_dev)
-{
- struct simple_dev *s_dev = to_simple_dev(class_dev);
- kfree(s_dev);
-}
-
-static void class_simple_release(struct class *class)
-{
- struct class_simple *cs = to_class_simple(class);
- kfree(cs);
-}
-
-/**
- * class_simple_create - create a struct class_simple structure
- * @owner: pointer to the module that is to "own" this struct class_simple
- * @name: pointer to a string for the name of this class.
- *
- * This is used to create a struct class_simple pointer that can then be used
- * in calls to class_simple_device_add(). This is used when you do not wish to
- * create a full blown class support for a type of char devices.
- *
- * Note, the pointer created here is to be destroyed when finished by making a
- * call to class_simple_destroy().
- */
-struct class_simple *class_simple_create(struct module *owner, char *name)
-{
- struct class_simple *cs;
- int retval;
-
- cs = kmalloc(sizeof(*cs), GFP_KERNEL);
- if (!cs) {
- retval = -ENOMEM;
- goto error;
- }
- memset(cs, 0x00, sizeof(*cs));
-
- cs->class.name = name;
- cs->class.class_release = class_simple_release;
- cs->class.release = release_simple_dev;
-
- retval = class_register(&cs->class);
- if (retval)
- goto error;
-
- return cs;
-
-error:
- kfree(cs);
- return ERR_PTR(retval);
-}
-EXPORT_SYMBOL(class_simple_create);
-
-/**
- * class_simple_destroy - destroys a struct class_simple structure
- * @cs: pointer to the struct class_simple that is to be destroyed
- *
- * Note, the pointer to be destroyed must have been created with a call to
- * class_simple_create().
- */
-void class_simple_destroy(struct class_simple *cs)
-{
- if ((cs == NULL) || (IS_ERR(cs)))
- return;
-
- class_unregister(&cs->class);
-}
-EXPORT_SYMBOL(class_simple_destroy);
-
-/**
- * class_simple_device_add - adds a class device to sysfs for a character driver
- * @cs: pointer to the struct class_simple that this device should be registered to.
- * @dev: the dev_t for the device to be added.
- * @device: a pointer to a struct device that is assiociated with this class device.
- * @fmt: string for the class device's name
- *
- * This function can be used by simple char device classes that do not
- * implement their own class device registration. A struct class_device will
- * be created in sysfs, registered to the specified class. A "dev" file will
- * be created, showing the dev_t for the device. The pointer to the struct
- * class_device will be returned from the call. Any further sysfs files that
- * might be required can be created using this pointer.
- * Note: the struct class_simple passed to this function must have previously been
- * created with a call to class_simple_create().
- */
-struct class_device *class_simple_device_add(struct class_simple *cs, dev_t dev, struct device *device, const char *fmt, ...)
-{
- va_list args;
- struct simple_dev *s_dev = NULL;
- int retval;
-
- if ((cs == NULL) || (IS_ERR(cs))) {
- retval = -ENODEV;
- goto error;
- }
-
- s_dev = kmalloc(sizeof(*s_dev), GFP_KERNEL);
- if (!s_dev) {
- retval = -ENOMEM;
- goto error;
- }
- memset(s_dev, 0x00, sizeof(*s_dev));
-
- s_dev->class_dev.devt = dev;
- s_dev->class_dev.dev = device;
- s_dev->class_dev.class = &cs->class;
-
- va_start(args, fmt);
- vsnprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, fmt, args);
- va_end(args);
- retval = class_device_register(&s_dev->class_dev);
- if (retval)
- goto error;
-
- spin_lock(&simple_dev_list_lock);
- list_add(&s_dev->node, &simple_dev_list);
- spin_unlock(&simple_dev_list_lock);
-
- return &s_dev->class_dev;
-
-error:
- kfree(s_dev);
- return ERR_PTR(retval);
-}
-EXPORT_SYMBOL(class_simple_device_add);
-
-/**
- * class_simple_set_hotplug - set the hotplug callback in the embedded struct class
- * @cs: pointer to the struct class_simple to hold the pointer
- * @hotplug: function pointer to the hotplug function
- *
- * Implement and set a hotplug function to add environment variables specific to this
- * class on the hotplug event.
- */
-int class_simple_set_hotplug(struct class_simple *cs,
- int (*hotplug)(struct class_device *dev, char **envp, int num_envp, char *buffer, int buffer_size))
-{
- if ((cs == NULL) || (IS_ERR(cs)))
- return -ENODEV;
- cs->class.hotplug = hotplug;
- return 0;
-}
-EXPORT_SYMBOL(class_simple_set_hotplug);
-
-/**
- * class_simple_device_remove - removes a class device that was created with class_simple_device_add()
- * @dev: the dev_t of the device that was previously registered.
- *
- * This call unregisters and cleans up a class device that was created with a
- * call to class_device_simple_add()
- */
-void class_simple_device_remove(dev_t dev)
-{
- struct simple_dev *s_dev = NULL;
- int found = 0;
-
- spin_lock(&simple_dev_list_lock);
- list_for_each_entry(s_dev, &simple_dev_list, node) {
- if (s_dev->class_dev.devt == dev) {
- found = 1;
- break;
- }
- }
- if (found) {
- list_del(&s_dev->node);
- spin_unlock(&simple_dev_list_lock);
- class_device_unregister(&s_dev->class_dev);
- } else {
- spin_unlock(&simple_dev_list_lock);
- }
-}
-EXPORT_SYMBOL(class_simple_device_remove);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 268a9c8d168..86d79755fbf 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -31,17 +31,15 @@ int (*platform_notify_remove)(struct device * dev) = NULL;
#define to_dev(obj) container_of(obj, struct device, kobj)
#define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr)
-extern struct attribute * dev_default_attrs[];
-
static ssize_t
dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
{
struct device_attribute * dev_attr = to_dev_attr(attr);
struct device * dev = to_dev(kobj);
- ssize_t ret = 0;
+ ssize_t ret = -EIO;
if (dev_attr->show)
- ret = dev_attr->show(dev, buf);
+ ret = dev_attr->show(dev, dev_attr, buf);
return ret;
}
@@ -51,10 +49,10 @@ dev_attr_store(struct kobject * kobj, struct attribute * attr,
{
struct device_attribute * dev_attr = to_dev_attr(attr);
struct device * dev = to_dev(kobj);
- ssize_t ret = 0;
+ ssize_t ret = -EIO;
if (dev_attr->store)
- ret = dev_attr->store(dev, buf, count);
+ ret = dev_attr->store(dev, dev_attr, buf, count);
return ret;
}
@@ -89,7 +87,6 @@ static void device_release(struct kobject * kobj)
static struct kobj_type ktype_device = {
.release = device_release,
.sysfs_ops = &dev_sysfs_ops,
- .default_attrs = dev_default_attrs,
};
@@ -105,7 +102,7 @@ static int dev_hotplug_filter(struct kset *kset, struct kobject *kobj)
return 0;
}
-static char *dev_hotplug_name(struct kset *kset, struct kobject *kobj)
+static const char *dev_hotplug_name(struct kset *kset, struct kobject *kobj)
{
struct device *dev = to_dev(kobj);
@@ -210,11 +207,9 @@ void device_initialize(struct device *dev)
{
kobj_set_kset_s(dev, devices_subsys);
kobject_init(&dev->kobj);
- INIT_LIST_HEAD(&dev->node);
- INIT_LIST_HEAD(&dev->children);
- INIT_LIST_HEAD(&dev->driver_list);
- INIT_LIST_HEAD(&dev->bus_list);
+ klist_init(&dev->klist_children);
INIT_LIST_HEAD(&dev->dma_pools);
+ init_MUTEX(&dev->sem);
}
/**
@@ -248,26 +243,24 @@ int device_add(struct device *dev)
if ((error = kobject_add(&dev->kobj)))
goto Error;
+ kobject_hotplug(&dev->kobj, KOBJ_ADD);
if ((error = device_pm_add(dev)))
goto PMError;
if ((error = bus_add_device(dev)))
goto BusError;
- down_write(&devices_subsys.rwsem);
if (parent)
- list_add_tail(&dev->node, &parent->children);
- up_write(&devices_subsys.rwsem);
+ klist_add_tail(&parent->klist_children, &dev->knode_parent);
/* notify platform of device entry */
if (platform_notify)
platform_notify(dev);
-
- kobject_hotplug(&dev->kobj, KOBJ_ADD);
Done:
put_device(dev);
return error;
BusError:
device_pm_remove(dev);
PMError:
+ kobject_hotplug(&dev->kobj, KOBJ_REMOVE);
kobject_del(&dev->kobj);
Error:
if (parent)
@@ -339,10 +332,8 @@ void device_del(struct device * dev)
{
struct device * parent = dev->parent;
- down_write(&devices_subsys.rwsem);
if (parent)
- list_del_init(&dev->node);
- up_write(&devices_subsys.rwsem);
+ klist_remove(&dev->knode_parent);
/* Notify the platform of the removal, in case they
* need to do anything...
@@ -376,6 +367,12 @@ void device_unregister(struct device * dev)
}
+static struct device * next_device(struct klist_iter * i)
+{
+ struct klist_node * n = klist_next(i);
+ return n ? container_of(n, struct device, knode_parent) : NULL;
+}
+
/**
* device_for_each_child - device child iterator.
* @dev: parent struct device.
@@ -388,39 +385,20 @@ void device_unregister(struct device * dev)
* We check the return of @fn each time. If it returns anything
* other than 0, we break out and return that value.
*/
-int device_for_each_child(struct device * dev, void * data,
+int device_for_each_child(struct device * parent, void * data,
int (*fn)(struct device *, void *))
{
+ struct klist_iter i;
struct device * child;
int error = 0;
- down_read(&devices_subsys.rwsem);
- list_for_each_entry(child, &dev->children, node) {
- if((error = fn(child, data)))
- break;
- }
- up_read(&devices_subsys.rwsem);
+ klist_iter_init(&parent->klist_children, &i);
+ while ((child = next_device(&i)) && !error)
+ error = fn(child, data);
+ klist_iter_exit(&i);
return error;
}
-/**
- * device_find - locate device on a bus by name.
- * @name: name of the device.
- * @bus: bus to scan for the device.
- *
- * Call kset_find_obj() to iterate over list of devices on
- * a bus to find device by name. Return device if found.
- *
- * Note that kset_find_obj increments device's reference count.
- */
-struct device *device_find(const char *name, struct bus_type *bus)
-{
- struct kobject *k = kset_find_obj(&bus->devices, name);
- if (k)
- return to_dev(k);
- return NULL;
-}
-
int __init devices_init(void)
{
return subsystem_register(&devices_subsys);
@@ -436,7 +414,6 @@ EXPORT_SYMBOL_GPL(device_del);
EXPORT_SYMBOL_GPL(device_unregister);
EXPORT_SYMBOL_GPL(get_device);
EXPORT_SYMBOL_GPL(put_device);
-EXPORT_SYMBOL_GPL(device_find);
EXPORT_SYMBOL_GPL(device_create_file);
EXPORT_SYMBOL_GPL(device_remove_file);
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 6ef3069b571..b79badd0f15 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -16,6 +16,11 @@ struct sysdev_class cpu_sysdev_class = {
EXPORT_SYMBOL(cpu_sysdev_class);
#ifdef CONFIG_HOTPLUG_CPU
+int __attribute__((weak)) smp_prepare_cpu (int cpu)
+{
+ return 0;
+}
+
static ssize_t show_online(struct sys_device *dev, char *buf)
{
struct cpu *cpu = container_of(dev, struct cpu, sysdev);
@@ -36,7 +41,11 @@ static ssize_t store_online(struct sys_device *dev, const char *buf,
kobject_hotplug(&dev->kobj, KOBJ_OFFLINE);
break;
case '1':
- ret = cpu_up(cpu->sysdev.id);
+ ret = smp_prepare_cpu(cpu->sysdev.id);
+ if (!ret)
+ ret = cpu_up(cpu->sysdev.id);
+ if (!ret)
+ kobject_hotplug(&dev->kobj, KOBJ_ONLINE);
break;
default:
ret = -EINVAL;
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
new file mode 100644
index 00000000000..6db3a789c54
--- /dev/null
+++ b/drivers/base/dd.c
@@ -0,0 +1,248 @@
+/*
+ * drivers/base/dd.c - The core device/driver interactions.
+ *
+ * This file contains the (sometimes tricky) code that controls the
+ * interactions between devices and drivers, which primarily includes
+ * driver binding and unbinding.
+ *
+ * All of this code used to exist in drivers/base/bus.c, but was
+ * relocated to here in the name of compartmentalization (since it wasn't
+ * strictly code just for the 'struct bus_type'.
+ *
+ * Copyright (c) 2002-5 Patrick Mochel
+ * Copyright (c) 2002-3 Open Source Development Labs
+ *
+ * This file is released under the GPLv2
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+
+#include "base.h"
+#include "power/power.h"
+
+#define to_drv(node) container_of(node, struct device_driver, kobj.entry)
+
+
+/**
+ * device_bind_driver - bind a driver to one device.
+ * @dev: device.
+ *
+ * Allow manual attachment of a driver to a device.
+ * Caller must have already set @dev->driver.
+ *
+ * Note that this does not modify the bus reference count
+ * nor take the bus's rwsem. Please verify those are accounted
+ * for before calling this. (It is ok to call with no other effort
+ * from a driver's probe() method.)
+ *
+ * This function must be called with @dev->sem held.
+ */
+void device_bind_driver(struct device * dev)
+{
+ pr_debug("bound device '%s' to driver '%s'\n",
+ dev->bus_id, dev->driver->name);
+ klist_add_tail(&dev->driver->klist_devices, &dev->knode_driver);
+ sysfs_create_link(&dev->driver->kobj, &dev->kobj,
+ kobject_name(&dev->kobj));
+ sysfs_create_link(&dev->kobj, &dev->driver->kobj, "driver");
+}
+
+/**
+ * driver_probe_device - attempt to bind device & driver.
+ * @drv: driver.
+ * @dev: device.
+ *
+ * First, we call the bus's match function, if one present, which
+ * should compare the device IDs the driver supports with the
+ * device IDs of the device. Note we don't do this ourselves
+ * because we don't know the format of the ID structures, nor what
+ * is to be considered a match and what is not.
+ *
+ *
+ * This function returns 1 if a match is found, an error if one
+ * occurs (that is not -ENODEV or -ENXIO), and 0 otherwise.
+ *
+ * This function must be called with @dev->sem held.
+ */
+static int driver_probe_device(struct device_driver * drv, struct device * dev)
+{
+ int ret = 0;
+
+ if (drv->bus->match && !drv->bus->match(dev, drv))
+ goto Done;
+
+ pr_debug("%s: Matched Device %s with Driver %s\n",
+ drv->bus->name, dev->bus_id, drv->name);
+ dev->driver = drv;
+ if (drv->probe) {
+ ret = drv->probe(dev);
+ if (ret) {
+ dev->driver = NULL;
+ goto ProbeFailed;
+ }
+ }
+ device_bind_driver(dev);
+ ret = 1;
+ pr_debug("%s: Bound Device %s to Driver %s\n",
+ drv->bus->name, dev->bus_id, drv->name);
+ goto Done;
+
+ ProbeFailed:
+ if (ret == -ENODEV || ret == -ENXIO) {
+ /* Driver matched, but didn't support device
+ * or device not found.
+ * Not an error; keep going.
+ */
+ ret = 0;
+ } else {
+ /* driver matched but the probe failed */
+ printk(KERN_WARNING
+ "%s: probe of %s failed with error %d\n",
+ drv->name, dev->bus_id, ret);
+ }
+ Done:
+ return ret;
+}
+
+static int __device_attach(struct device_driver * drv, void * data)
+{
+ struct device * dev = data;
+ return driver_probe_device(drv, dev);
+}
+
+/**
+ * device_attach - try to attach device to a driver.
+ * @dev: device.
+ *
+ * Walk the list of drivers that the bus has and call
+ * driver_probe_device() for each pair. If a compatible
+ * pair is found, break out and return.
+ *
+ * Returns 1 if the device was bound to a driver;
+ * 0 if no matching device was found; error code otherwise.
+ */
+int device_attach(struct device * dev)
+{
+ int ret = 0;
+
+ down(&dev->sem);
+ if (dev->driver) {
+ device_bind_driver(dev);
+ ret = 1;
+ } else
+ ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
+ up(&dev->sem);
+ return ret;
+}
+
+static int __driver_attach(struct device * dev, void * data)
+{
+ struct device_driver * drv = data;
+
+ /*
+ * Lock device and try to bind to it. We drop the error
+ * here and always return 0, because we need to keep trying
+ * to bind to devices and some drivers will return an error
+ * simply if it didn't support the device.
+ *
+ * driver_probe_device() will spit a warning if there
+ * is an error.
+ */
+
+ down(&dev->sem);
+ if (!dev->driver)
+ driver_probe_device(drv, dev);
+ up(&dev->sem);
+
+
+ return 0;
+}
+
+/**
+ * driver_attach - try to bind driver to devices.
+ * @drv: driver.
+ *
+ * Walk the list of devices that the bus has on it and try to
+ * match the driver with each one. If driver_probe_device()
+ * returns 0 and the @dev->driver is set, we've found a
+ * compatible pair.
+ */
+void driver_attach(struct device_driver * drv)
+{
+ bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
+}
+
+/**
+ * device_release_driver - manually detach device from driver.
+ * @dev: device.
+ *
+ * Manually detach device from driver.
+ *
+ * __device_release_driver() must be called with @dev->sem held.
+ */
+
+static void __device_release_driver(struct device * dev)
+{
+ struct device_driver * drv;
+
+ drv = dev->driver;
+ if (drv) {
+ get_driver(drv);
+ sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
+ sysfs_remove_link(&dev->kobj, "driver");
+ klist_remove(&dev->knode_driver);
+
+ if (drv->remove)
+ drv->remove(dev);
+ dev->driver = NULL;
+ put_driver(drv);
+ }
+}
+
+void device_release_driver(struct device * dev)
+{
+ /*
+ * If anyone calls device_release_driver() recursively from
+ * within their ->remove callback for the same device, they
+ * will deadlock right here.
+ */
+ down(&dev->sem);
+ __device_release_driver(dev);
+ up(&dev->sem);
+}
+
+
+/**
+ * driver_detach - detach driver from all devices it controls.
+ * @drv: driver.
+ */
+void driver_detach(struct device_driver * drv)
+{
+ struct device * dev;
+
+ for (;;) {
+ spin_lock_irq(&drv->klist_devices.k_lock);
+ if (list_empty(&drv->klist_devices.k_list)) {
+ spin_unlock_irq(&drv->klist_devices.k_lock);
+ break;
+ }
+ dev = list_entry(drv->klist_devices.k_list.prev,
+ struct device, knode_driver.n_node);
+ get_device(dev);
+ spin_unlock_irq(&drv->klist_devices.k_lock);
+
+ down(&dev->sem);
+ if (dev->driver == drv)
+ __device_release_driver(dev);
+ up(&dev->sem);
+ put_device(dev);
+ }
+}
+
+
+EXPORT_SYMBOL_GPL(device_bind_driver);
+EXPORT_SYMBOL_GPL(device_release_driver);
+EXPORT_SYMBOL_GPL(device_attach);
+EXPORT_SYMBOL_GPL(driver_attach);
+
diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c
index f48833df61a..c4aebf2f522 100644
--- a/drivers/base/dmapool.c
+++ b/drivers/base/dmapool.c
@@ -41,7 +41,7 @@ struct dma_page { /* cacheable header for 'allocation' bytes */
static DECLARE_MUTEX (pools_lock);
static ssize_t
-show_pools (struct device *dev, char *buf)
+show_pools (struct device *dev, struct device_attribute *attr, char *buf)
{
unsigned temp;
unsigned size;
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 3b269f7e521..1b645886e9e 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -18,6 +18,43 @@
#define to_dev(node) container_of(node, struct device, driver_list)
#define to_drv(obj) container_of(obj, struct device_driver, kobj)
+
+static struct device * next_device(struct klist_iter * i)
+{
+ struct klist_node * n = klist_next(i);
+ return n ? container_of(n, struct device, knode_driver) : NULL;
+}
+
+/**
+ * driver_for_each_device - Iterator for devices bound to a driver.
+ * @drv: Driver we're iterating.
+ * @data: Data to pass to the callback.
+ * @fn: Function to call for each device.
+ *
+ * Iterate over the @drv's list of devices calling @fn for each one.
+ */
+
+int driver_for_each_device(struct device_driver * drv, struct device * start,
+ void * data, int (*fn)(struct device *, void *))
+{
+ struct klist_iter i;
+ struct device * dev;
+ int error = 0;
+
+ if (!drv)
+ return -EINVAL;
+
+ klist_iter_init_node(&drv->klist_devices, &i,
+ start ? &start->knode_driver : NULL);
+ while ((dev = next_device(&i)) && !error)
+ error = fn(dev, data);
+ klist_iter_exit(&i);
+ return error;
+}
+
+EXPORT_SYMBOL_GPL(driver_for_each_device);
+
+
/**
* driver_create_file - create sysfs file for driver.
* @drv: driver.
@@ -85,7 +122,7 @@ void put_driver(struct device_driver * drv)
*/
int driver_register(struct device_driver * drv)
{
- INIT_LIST_HEAD(&drv->devices);
+ klist_init(&drv->klist_devices);
init_completion(&drv->unloaded);
return bus_add_driver(drv);
}
diff --git a/drivers/base/interface.c b/drivers/base/interface.c
deleted file mode 100644
index bd515843a0c..00000000000
--- a/drivers/base/interface.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * drivers/base/interface.c - common driverfs interface that's exported to
- * the world for all devices.
- *
- * Copyright (c) 2002-3 Patrick Mochel
- * Copyright (c) 2002-3 Open Source Development Labs
- *
- * This file is released under the GPLv2
- *
- */
-
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/stat.h>
-#include <linux/string.h>
-
-/**
- * detach_state - control the default power state for the device.
- *
- * This is the state the device enters when it's driver module is
- * unloaded. The value is an unsigned integer, in the range of 0-4.
- * '0' indicates 'On', so no action will be taken when the driver is
- * unloaded. This is the default behavior.
- * '4' indicates 'Off', meaning the driver core will call the driver's
- * shutdown method to quiesce the device.
- * 1-3 indicate a low-power state for the device to enter via the
- * driver's suspend method.
- */
-
-static ssize_t detach_show(struct device * dev, char * buf)
-{
- return sprintf(buf, "%u\n", dev->detach_state);
-}
-
-static ssize_t detach_store(struct device * dev, const char * buf, size_t n)
-{
- u32 state;
- state = simple_strtoul(buf, NULL, 10);
- if (state > 4)
- return -EINVAL;
- dev->detach_state = state;
- return n;
-}
-
-static DEVICE_ATTR(detach_state, 0644, detach_show, detach_store);
-
-
-struct attribute * dev_default_attrs[] = {
- &dev_attr_detach_state.attr,
- NULL,
-};
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 583d57ec49a..904b27caf69 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -87,7 +87,7 @@ static ssize_t node_read_numastat(struct sys_device * dev, char * buf)
for (i = 0; i < MAX_NR_ZONES; i++) {
struct zone *z = &pg->node_zones[i];
for (cpu = 0; cpu < NR_CPUS; cpu++) {
- struct per_cpu_pageset *ps = &z->pageset[cpu];
+ struct per_cpu_pageset *ps = zone_pcp(z,cpu);
numa_hit += ps->numa_hit;
numa_miss += ps->numa_miss;
numa_foreign += ps->numa_foreign;
@@ -136,7 +136,7 @@ static SYSDEV_ATTR(distance, S_IRUGO, node_read_distance, NULL);
*
* Initialize and register the node device.
*/
-int __init register_node(struct node *node, int num, struct node *parent)
+int register_node(struct node *node, int num, struct node *parent)
{
int error;
@@ -153,8 +153,24 @@ int __init register_node(struct node *node, int num, struct node *parent)
return error;
}
+/**
+ * unregister_node - unregister a node device
+ * @node: node going away
+ *
+ * Unregisters a node device @node. All the devices on the node must be
+ * unregistered before calling this function.
+ */
+void unregister_node(struct node *node)
+{
+ sysdev_remove_file(&node->sysdev, &attr_cpumap);
+ sysdev_remove_file(&node->sysdev, &attr_meminfo);
+ sysdev_remove_file(&node->sysdev, &attr_numastat);
+ sysdev_remove_file(&node->sysdev, &attr_distance);
+
+ sysdev_unregister(&node->sysdev);
+}
-int __init register_node_type(void)
+static int __init register_node_type(void)
{
return sysdev_class_register(&node_class);
}
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index e5eda746f2a..2e700d795cf 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -1,18 +1,7 @@
-
-
-enum {
- DEVICE_PM_ON,
- DEVICE_PM1,
- DEVICE_PM2,
- DEVICE_PM3,
- DEVICE_PM_OFF,
-};
-
/*
* shutdown.c
*/
-extern int device_detach_shutdown(struct device *);
extern void device_shutdown(void);
diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c
index f8f5055754d..bdd96b03b88 100644
--- a/drivers/base/power/resume.c
+++ b/drivers/base/power/resume.c
@@ -22,9 +22,22 @@ extern int sysdev_resume(void);
int resume_device(struct device * dev)
{
- if (dev->bus && dev->bus->resume)
- return dev->bus->resume(dev);
- return 0;
+ int error = 0;
+
+ down(&dev->sem);
+ if (dev->power.pm_parent
+ && dev->power.pm_parent->power.power_state) {
+ dev_err(dev, "PM: resume from %d, parent %s still %d\n",
+ dev->power.power_state,
+ dev->power.pm_parent->bus_id,
+ dev->power.pm_parent->power.power_state);
+ }
+ if (dev->bus && dev->bus->resume) {
+ dev_dbg(dev,"resuming\n");
+ error = dev->bus->resume(dev);
+ }
+ up(&dev->sem);
+ return error;
}
diff --git a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c
index d1e023fbe16..f50a08be424 100644
--- a/drivers/base/power/shutdown.c
+++ b/drivers/base/power/shutdown.c
@@ -19,20 +19,6 @@
extern struct subsystem devices_subsys;
-int device_detach_shutdown(struct device * dev)
-{
- if (!dev->detach_state)
- return 0;
-
- if (dev->detach_state == DEVICE_PM_OFF) {
- if (dev->driver && dev->driver->shutdown)
- dev->driver->shutdown(dev);
- return 0;
- }
- return dpm_runtime_suspend(dev, dev->detach_state);
-}
-
-
/**
* We handle system devices differently - we suspend and shut them
* down last and resume them first. That way, we don't do anything stupid like
@@ -52,13 +38,12 @@ void device_shutdown(void)
struct device * dev;
down_write(&devices_subsys.rwsem);
- list_for_each_entry_reverse(dev, &devices_subsys.kset.list, kobj.entry) {
- pr_debug("shutting down %s: ", dev->bus_id);
+ list_for_each_entry_reverse(dev, &devices_subsys.kset.list,
+ kobj.entry) {
if (dev->driver && dev->driver->shutdown) {
- pr_debug("Ok\n");
+ dev_dbg(dev, "shutdown\n");
dev->driver->shutdown(dev);
- } else
- pr_debug("Ignored.\n");
+ }
}
up_write(&devices_subsys.rwsem);
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c
index a0b5cf689e6..2ccee3763ac 100644
--- a/drivers/base/power/suspend.c
+++ b/drivers/base/power/suspend.c
@@ -39,13 +39,27 @@ int suspend_device(struct device * dev, pm_message_t state)
{
int error = 0;
- dev_dbg(dev, "suspending\n");
+ down(&dev->sem);
+ if (dev->power.power_state) {
+ dev_dbg(dev, "PM: suspend %d-->%d\n",
+ dev->power.power_state, state);
+ }
+ if (dev->power.pm_parent
+ && dev->power.pm_parent->power.power_state) {
+ dev_err(dev,
+ "PM: suspend %d->%d, parent %s already %d\n",
+ dev->power.power_state, state,
+ dev->power.pm_parent->bus_id,
+ dev->power.pm_parent->power.power_state);
+ }
dev->power.prev_state = dev->power.power_state;
- if (dev->bus && dev->bus->suspend && !dev->power.power_state)
+ if (dev->bus && dev->bus->suspend && !dev->power.power_state) {
+ dev_dbg(dev, "suspending\n");
error = dev->bus->suspend(dev, state);
-
+ }
+ up(&dev->sem);
return error;
}
@@ -100,8 +114,19 @@ int device_suspend(pm_message_t state)
put_device(dev);
}
up(&dpm_list_sem);
- if (error)
+ if (error) {
+ /* we failed... before resuming, bring back devices from
+ * dpm_off_irq list back to main dpm_off list, we do want
+ * to call resume() on them, in case they partially suspended
+ * despite returning -EAGAIN
+ */
+ while (!list_empty(&dpm_off_irq)) {
+ struct list_head * entry = dpm_off_irq.next;
+ list_del(entry);
+ list_add(entry, &dpm_off);
+ }
dpm_resume();
+ }
up(&dpm_sem);
return error;
}
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index 6ac96349a8e..f82b3df9545 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -24,12 +24,12 @@
* low-power state.
*/
-static ssize_t state_show(struct device * dev, char * buf)
+static ssize_t state_show(struct device * dev, struct device_attribute *attr, char * buf)
{
return sprintf(buf, "%u\n", dev->power.power_state);
}
-static ssize_t state_store(struct device * dev, const char * buf, size_t n)
+static ssize_t state_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t n)
{
u32 state;
char * rest;
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 9102e3756f9..f37a13de804 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -37,7 +37,7 @@ sysdev_show(struct kobject * kobj, struct attribute * attr, char * buffer)
if (sysdev_attr->show)
return sysdev_attr->show(sysdev, buffer);
- return 0;
+ return -EIO;
}
@@ -50,7 +50,7 @@ sysdev_store(struct kobject * kobj, struct attribute * attr,
if (sysdev_attr->store)
return sysdev_attr->store(sysdev, buffer, count);
- return 0;
+ return -EIO;
}
static struct sysfs_ops sysfs_ops = {
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index 14aeca3e2e8..45a24309618 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -36,7 +36,7 @@ static int emsgs_head_idx, emsgs_tail_idx;
static struct semaphore emsgs_sema;
static spinlock_t emsgs_lock;
static int nblocked_emsgs_readers;
-static struct class_simple *aoe_class;
+static struct class *aoe_class;
static struct aoe_chardev chardevs[] = {
{ MINOR_ERR, "err" },
{ MINOR_DISCOVER, "discover" },
@@ -218,13 +218,13 @@ aoechr_init(void)
}
sema_init(&emsgs_sema, 0);
spin_lock_init(&emsgs_lock);
- aoe_class = class_simple_create(THIS_MODULE, "aoe");
+ aoe_class = class_create(THIS_MODULE, "aoe");
if (IS_ERR(aoe_class)) {
unregister_chrdev(AOE_MAJOR, "aoechr");
return PTR_ERR(aoe_class);
}
for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
- class_simple_device_add(aoe_class,
+ class_device_create(aoe_class,
MKDEV(AOE_MAJOR, chardevs[i].minor),
NULL, chardevs[i].name);
@@ -237,8 +237,8 @@ aoechr_exit(void)
int i;
for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
- class_simple_device_remove(MKDEV(AOE_MAJOR, chardevs[i].minor));
- class_simple_destroy(aoe_class);
+ class_device_destroy(aoe_class, MKDEV(AOE_MAJOR, chardevs[i].minor));
+ class_destroy(aoe_class);
unregister_chrdev(AOE_MAJOR, "aoechr");
}
diff --git a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c
index a9575bb58a5..3410b4d294b 100644
--- a/drivers/block/as-iosched.c
+++ b/drivers/block/as-iosched.c
@@ -1871,20 +1871,22 @@ static int as_init_queue(request_queue_t *q, elevator_t *e)
if (!arq_pool)
return -ENOMEM;
- ad = kmalloc(sizeof(*ad), GFP_KERNEL);
+ ad = kmalloc_node(sizeof(*ad), GFP_KERNEL, q->node);
if (!ad)
return -ENOMEM;
memset(ad, 0, sizeof(*ad));
ad->q = q; /* Identify what queue the data belongs to */
- ad->hash = kmalloc(sizeof(struct list_head)*AS_HASH_ENTRIES,GFP_KERNEL);
+ ad->hash = kmalloc_node(sizeof(struct list_head)*AS_HASH_ENTRIES,
+ GFP_KERNEL, q->node);
if (!ad->hash) {
kfree(ad);
return -ENOMEM;
}
- ad->arq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, arq_pool);
+ ad->arq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
+ mempool_free_slab, arq_pool, q->node);
if (!ad->arq_pool) {
kfree(ad->hash);
kfree(ad);
@@ -2044,7 +2046,7 @@ as_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
struct as_fs_entry *entry = to_as(attr);
if (!entry->show)
- return 0;
+ return -EIO;
return entry->show(e->elevator_data, page);
}
@@ -2057,7 +2059,7 @@ as_attr_store(struct kobject *kobj, struct attribute *attr,
struct as_fs_entry *entry = to_as(attr);
if (!entry->store)
- return -EINVAL;
+ return -EIO;
return entry->store(e->elevator_data, page, length);
}
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 8f7c1a1ed7f..abde27027c0 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -41,6 +41,7 @@
#include <asm/uaccess.h>
#include <asm/io.h>
+#include <linux/dma-mapping.h>
#include <linux/blkdev.h>
#include <linux/genhd.h>
#include <linux/completion.h>
@@ -126,8 +127,6 @@ static struct board_type products[] = {
#define MAX_CTLR_ORIG 8
-#define CCISS_DMA_MASK 0xFFFFFFFF /* 32 bit DMA */
-
static ctlr_info_t *hba[MAX_CTLR];
static void do_cciss_request(request_queue_t *q);
@@ -2393,11 +2392,6 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
printk(KERN_ERR "cciss: Unable to Enable PCI device\n");
return( -1);
}
- if (pci_set_dma_mask(pdev, CCISS_DMA_MASK ) != 0)
- {
- printk(KERN_ERR "cciss: Unable to set DMA mask\n");
- return(-1);
- }
subsystem_vendor_id = pdev->subsystem_vendor;
subsystem_device_id = pdev->subsystem_device;
@@ -2747,9 +2741,9 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
hba[i]->pdev = pdev;
/* configure PCI DMA stuff */
- if (!pci_set_dma_mask(pdev, 0xffffffffffffffffULL))
+ if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK))
printk("cciss: using DAC cycles\n");
- else if (!pci_set_dma_mask(pdev, 0xffffffff))
+ else if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK))
printk("cciss: not using DAC cycles\n");
else {
printk("cciss: no suitable DMA available\n");
diff --git a/drivers/block/cfq-iosched.c b/drivers/block/cfq-iosched.c
index 0ef7a0065ec..3ac47dde64d 100644
--- a/drivers/block/cfq-iosched.c
+++ b/drivers/block/cfq-iosched.c
@@ -1202,13 +1202,16 @@ retry:
if (new_cfqq) {
cfqq = new_cfqq;
new_cfqq = NULL;
- } else if (gfp_mask & __GFP_WAIT) {
+ } else {
spin_unlock_irq(cfqd->queue->queue_lock);
new_cfqq = kmem_cache_alloc(cfq_pool, gfp_mask);
spin_lock_irq(cfqd->queue->queue_lock);
+
+ if (!new_cfqq && !(gfp_mask & __GFP_WAIT))
+ goto out;
+
goto retry;
- } else
- goto out;
+ }
memset(cfqq, 0, sizeof(*cfqq));
@@ -1772,7 +1775,7 @@ cfq_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
struct cfq_fs_entry *entry = to_cfq(attr);
if (!entry->show)
- return 0;
+ return -EIO;
return entry->show(e->elevator_data, page);
}
@@ -1785,7 +1788,7 @@ cfq_attr_store(struct kobject *kobj, struct attribute *attr,
struct cfq_fs_entry *entry = to_cfq(attr);
if (!entry->store)
- return -EINVAL;
+ return -EIO;
return entry->store(e->elevator_data, page, length);
}
diff --git a/drivers/block/deadline-iosched.c b/drivers/block/deadline-iosched.c
index d63d34c671f..4bc2fea7327 100644
--- a/drivers/block/deadline-iosched.c
+++ b/drivers/block/deadline-iosched.c
@@ -711,18 +711,20 @@ static int deadline_init_queue(request_queue_t *q, elevator_t *e)
if (!drq_pool)
return -ENOMEM;
- dd = kmalloc(sizeof(*dd), GFP_KERNEL);
+ dd = kmalloc_node(sizeof(*dd), GFP_KERNEL, q->node);
if (!dd)
return -ENOMEM;
memset(dd, 0, sizeof(*dd));
- dd->hash = kmalloc(sizeof(struct list_head)*DL_HASH_ENTRIES,GFP_KERNEL);
+ dd->hash = kmalloc_node(sizeof(struct list_head)*DL_HASH_ENTRIES,
+ GFP_KERNEL, q->node);
if (!dd->hash) {
kfree(dd);
return -ENOMEM;
}
- dd->drq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, drq_pool);
+ dd->drq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
+ mempool_free_slab, drq_pool, q->node);
if (!dd->drq_pool) {
kfree(dd->hash);
kfree(dd);
@@ -886,7 +888,7 @@ deadline_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
struct deadline_fs_entry *entry = to_deadline(attr);
if (!entry->show)
- return 0;
+ return -EIO;
return entry->show(e->elevator_data, page);
}
@@ -899,7 +901,7 @@ deadline_attr_store(struct kobject *kobj, struct attribute *attr,
struct deadline_fs_entry *entry = to_deadline(attr);
if (!entry->store)
- return -EINVAL;
+ return -EIO;
return entry->store(e->elevator_data, page, length);
}
diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c
index 6b79b431462..f831f08f839 100644
--- a/drivers/block/elevator.c
+++ b/drivers/block/elevator.c
@@ -220,11 +220,6 @@ void elevator_exit(elevator_t *e)
kfree(e);
}
-static int elevator_global_init(void)
-{
- return 0;
-}
-
int elv_merge(request_queue_t *q, struct request **req, struct bio *bio)
{
elevator_t *e = q->elevator;
@@ -291,6 +286,13 @@ void elv_requeue_request(request_queue_t *q, struct request *rq)
}
/*
+ * the request is prepped and may have some resources allocated.
+ * allowing unprepped requests to pass this one may cause resource
+ * deadlock. turn on softbarrier.
+ */
+ rq->flags |= REQ_SOFTBARRIER;
+
+ /*
* if iosched has an explicit requeue hook, then use that. otherwise
* just put the request at the front of the queue
*/
@@ -322,7 +324,7 @@ void __elv_add_request(request_queue_t *q, struct request *rq, int where,
int nrq = q->rq.count[READ] + q->rq.count[WRITE]
- q->in_flight;
- if (nrq == q->unplug_thresh)
+ if (nrq >= q->unplug_thresh)
__generic_unplug_device(q);
}
} else
@@ -386,6 +388,12 @@ struct request *elv_next_request(request_queue_t *q)
if (ret == BLKPREP_OK) {
break;
} else if (ret == BLKPREP_DEFER) {
+ /*
+ * the request may have been (partially) prepped.
+ * we need to keep this request in the front to
+ * avoid resource deadlock. turn on softbarrier.
+ */
+ rq->flags |= REQ_SOFTBARRIER;
rq = NULL;
break;
} else if (ret == BLKPREP_KILL) {
@@ -692,8 +700,6 @@ ssize_t elv_iosched_show(request_queue_t *q, char *name)
return len;
}
-module_init(elevator_global_init);
-
EXPORT_SYMBOL(elv_add_request);
EXPORT_SYMBOL(__elv_add_request);
EXPORT_SYMBOL(elv_requeue_request);
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index 8bbe01d4b48..47fd3659a06 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -40,7 +40,7 @@ static inline int major_to_index(int major)
#ifdef CONFIG_PROC_FS
/* get block device names in somewhat random order */
-int get_blkdev_list(char *p)
+int get_blkdev_list(char *p, int used)
{
struct blk_major_name *n;
int i, len;
@@ -49,10 +49,18 @@ int get_blkdev_list(char *p)
down(&block_subsys_sem);
for (i = 0; i < ARRAY_SIZE(major_names); i++) {
- for (n = major_names[i]; n; n = n->next)
+ for (n = major_names[i]; n; n = n->next) {
+ /*
+ * If the curent string plus the 5 extra characters
+ * in the line would run us off the page, then we're done
+ */
+ if ((len + used + strlen(n->name) + 5) >= PAGE_SIZE)
+ goto page_full;
len += sprintf(p+len, "%3d %s\n",
n->major, n->name);
+ }
}
+page_full:
up(&block_subsys_sem);
return len;
@@ -322,7 +330,7 @@ static ssize_t disk_attr_show(struct kobject *kobj, struct attribute *attr,
struct gendisk *disk = to_disk(kobj);
struct disk_attribute *disk_attr =
container_of(attr,struct disk_attribute,attr);
- ssize_t ret = 0;
+ ssize_t ret = -EIO;
if (disk_attr->show)
ret = disk_attr->show(disk,page);
@@ -582,10 +590,16 @@ struct seq_operations diskstats_op = {
.show = diskstats_show
};
-
struct gendisk *alloc_disk(int minors)
{
- struct gendisk *disk = kmalloc(sizeof(struct gendisk), GFP_KERNEL);
+ return alloc_disk_node(minors, -1);
+}
+
+struct gendisk *alloc_disk_node(int minors, int node_id)
+{
+ struct gendisk *disk;
+
+ disk = kmalloc_node(sizeof(struct gendisk), GFP_KERNEL, node_id);
if (disk) {
memset(disk, 0, sizeof(struct gendisk));
if (!init_disk_stats(disk)) {
@@ -594,7 +608,7 @@ struct gendisk *alloc_disk(int minors)
}
if (minors > 1) {
int size = (minors - 1) * sizeof(struct hd_struct *);
- disk->part = kmalloc(size, GFP_KERNEL);
+ disk->part = kmalloc_node(size, GFP_KERNEL, node_id);
if (!disk->part) {
kfree(disk);
return NULL;
@@ -610,6 +624,7 @@ struct gendisk *alloc_disk(int minors)
}
EXPORT_SYMBOL(alloc_disk);
+EXPORT_SYMBOL(alloc_disk_node);
struct kobject *get_disk(struct gendisk *disk)
{
diff --git a/drivers/block/ioctl.c b/drivers/block/ioctl.c
index 5e03f5157ef..6e278474f9a 100644
--- a/drivers/block/ioctl.c
+++ b/drivers/block/ioctl.c
@@ -133,11 +133,9 @@ static int put_u64(unsigned long arg, u64 val)
return put_user(val, (u64 __user *)arg);
}
-int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
- unsigned long arg)
+static int blkdev_locked_ioctl(struct file *file, struct block_device *bdev,
+ unsigned cmd, unsigned long arg)
{
- struct block_device *bdev = inode->i_bdev;
- struct gendisk *disk = bdev->bd_disk;
struct backing_dev_info *bdi;
int ret, n;
@@ -190,36 +188,72 @@ int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
return put_ulong(arg, bdev->bd_inode->i_size >> 9);
case BLKGETSIZE64:
return put_u64(arg, bdev->bd_inode->i_size);
+ }
+ return -ENOIOCTLCMD;
+}
+
+static int blkdev_driver_ioctl(struct inode *inode, struct file *file,
+ struct gendisk *disk, unsigned cmd, unsigned long arg)
+{
+ int ret;
+ if (disk->fops->unlocked_ioctl)
+ return disk->fops->unlocked_ioctl(file, cmd, arg);
+
+ if (disk->fops->ioctl) {
+ lock_kernel();
+ ret = disk->fops->ioctl(inode, file, cmd, arg);
+ unlock_kernel();
+ return ret;
+ }
+
+ return -ENOTTY;
+}
+
+int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
+ unsigned long arg)
+{
+ struct block_device *bdev = inode->i_bdev;
+ struct gendisk *disk = bdev->bd_disk;
+ int ret, n;
+
+ switch(cmd) {
case BLKFLSBUF:
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
- if (disk->fops->ioctl) {
- ret = disk->fops->ioctl(inode, file, cmd, arg);
- /* -EINVAL to handle old uncorrected drivers */
- if (ret != -EINVAL && ret != -ENOTTY)
- return ret;
- }
+
+ ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg);
+ /* -EINVAL to handle old uncorrected drivers */
+ if (ret != -EINVAL && ret != -ENOTTY)
+ return ret;
+
+ lock_kernel();
fsync_bdev(bdev);
invalidate_bdev(bdev, 0);
+ unlock_kernel();
return 0;
+
case BLKROSET:
- if (disk->fops->ioctl) {
- ret = disk->fops->ioctl(inode, file, cmd, arg);
- /* -EINVAL to handle old uncorrected drivers */
- if (ret != -EINVAL && ret != -ENOTTY)
- return ret;
- }
+ ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg);
+ /* -EINVAL to handle old uncorrected drivers */
+ if (ret != -EINVAL && ret != -ENOTTY)
+ return ret;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
if (get_user(n, (int __user *)(arg)))
return -EFAULT;
+ lock_kernel();
set_device_ro(bdev, n);
+ unlock_kernel();
return 0;
- default:
- if (disk->fops->ioctl)
- return disk->fops->ioctl(inode, file, cmd, arg);
}
- return -ENOTTY;
+
+ lock_kernel();
+ ret = blkdev_locked_ioctl(file, bdev, cmd, arg);
+ unlock_kernel();
+ if (ret != -ENOIOCTLCMD)
+ return ret;
+
+ return blkdev_driver_ioctl(inode, file, disk, cmd, arg);
}
/* Most of the generic ioctls are handled in the normal fallback path.
@@ -237,3 +271,5 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
}
return ret;
}
+
+EXPORT_SYMBOL_GPL(blkdev_ioctl);
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 11ef9d9ea13..60e64091de1 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -28,6 +28,7 @@
#include <linux/slab.h>
#include <linux/swap.h>
#include <linux/writeback.h>
+#include <linux/blkdev.h>
/*
* for max sense size
@@ -36,6 +37,7 @@
static void blk_unplug_work(void *data);
static void blk_unplug_timeout(unsigned long data);
+static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io);
/*
* For the allocated request tables
@@ -716,7 +718,7 @@ struct request *blk_queue_find_tag(request_queue_t *q, int tag)
{
struct blk_queue_tag *bqt = q->queue_tags;
- if (unlikely(bqt == NULL || tag >= bqt->real_max_depth))
+ if (unlikely(bqt == NULL || tag >= bqt->max_depth))
return NULL;
return bqt->tag_index[tag];
@@ -774,9 +776,9 @@ EXPORT_SYMBOL(blk_queue_free_tags);
static int
init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth)
{
- int bits, i;
struct request **tag_index;
unsigned long *tag_map;
+ int nr_ulongs;
if (depth > q->nr_requests * 2) {
depth = q->nr_requests * 2;
@@ -788,24 +790,17 @@ init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth)
if (!tag_index)
goto fail;
- bits = (depth / BLK_TAGS_PER_LONG) + 1;
- tag_map = kmalloc(bits * sizeof(unsigned long), GFP_ATOMIC);
+ nr_ulongs = ALIGN(depth, BITS_PER_LONG) / BITS_PER_LONG;
+ tag_map = kmalloc(nr_ulongs * sizeof(unsigned long), GFP_ATOMIC);
if (!tag_map)
goto fail;
memset(tag_index, 0, depth * sizeof(struct request *));
- memset(tag_map, 0, bits * sizeof(unsigned long));
+ memset(tag_map, 0, nr_ulongs * sizeof(unsigned long));
tags->max_depth = depth;
- tags->real_max_depth = bits * BITS_PER_LONG;
tags->tag_index = tag_index;
tags->tag_map = tag_map;
- /*
- * set the upper bits if the depth isn't a multiple of the word size
- */
- for (i = depth; i < bits * BLK_TAGS_PER_LONG; i++)
- __set_bit(i, tag_map);
-
return 0;
fail:
kfree(tag_index);
@@ -870,32 +865,24 @@ int blk_queue_resize_tags(request_queue_t *q, int new_depth)
struct blk_queue_tag *bqt = q->queue_tags;
struct request **tag_index;
unsigned long *tag_map;
- int bits, max_depth;
+ int max_depth, nr_ulongs;
if (!bqt)
return -ENXIO;
/*
- * don't bother sizing down
- */
- if (new_depth <= bqt->real_max_depth) {
- bqt->max_depth = new_depth;
- return 0;
- }
-
- /*
* save the old state info, so we can copy it back
*/
tag_index = bqt->tag_index;
tag_map = bqt->tag_map;
- max_depth = bqt->real_max_depth;
+ max_depth = bqt->max_depth;
if (init_tag_map(q, bqt, new_depth))
return -ENOMEM;
memcpy(bqt->tag_index, tag_index, max_depth * sizeof(struct request *));
- bits = max_depth / BLK_TAGS_PER_LONG;
- memcpy(bqt->tag_map, tag_map, bits * sizeof(unsigned long));
+ nr_ulongs = ALIGN(max_depth, BITS_PER_LONG) / BITS_PER_LONG;
+ memcpy(bqt->tag_map, tag_map, nr_ulongs * sizeof(unsigned long));
kfree(tag_index);
kfree(tag_map);
@@ -925,11 +912,16 @@ void blk_queue_end_tag(request_queue_t *q, struct request *rq)
BUG_ON(tag == -1);
- if (unlikely(tag >= bqt->real_max_depth))
+ if (unlikely(tag >= bqt->max_depth))
+ /*
+ * This can happen after tag depth has been reduced.
+ * FIXME: how about a warning or info message here?
+ */
return;
if (unlikely(!__test_and_clear_bit(tag, bqt->tag_map))) {
- printk("attempt to clear non-busy tag (%d)\n", tag);
+ printk(KERN_ERR "%s: attempt to clear non-busy tag (%d)\n",
+ __FUNCTION__, tag);
return;
}
@@ -938,7 +930,8 @@ void blk_queue_end_tag(request_queue_t *q, struct request *rq)
rq->tag = -1;
if (unlikely(bqt->tag_index[tag] == NULL))
- printk("tag %d is missing\n", tag);
+ printk(KERN_ERR "%s: tag %d is missing\n",
+ __FUNCTION__, tag);
bqt->tag_index[tag] = NULL;
bqt->busy--;
@@ -967,24 +960,20 @@ EXPORT_SYMBOL(blk_queue_end_tag);
int blk_queue_start_tag(request_queue_t *q, struct request *rq)
{
struct blk_queue_tag *bqt = q->queue_tags;
- unsigned long *map = bqt->tag_map;
- int tag = 0;
+ int tag;
if (unlikely((rq->flags & REQ_QUEUED))) {
printk(KERN_ERR
- "request %p for device [%s] already tagged %d",
- rq, rq->rq_disk ? rq->rq_disk->disk_name : "?", rq->tag);
+ "%s: request %p for device [%s] already tagged %d",
+ __FUNCTION__, rq,
+ rq->rq_disk ? rq->rq_disk->disk_name : "?", rq->tag);
BUG();
}
- for (map = bqt->tag_map; *map == -1UL; map++) {
- tag += BLK_TAGS_PER_LONG;
-
- if (tag >= bqt->max_depth)
- return 1;
- }
+ tag = find_first_zero_bit(bqt->tag_map, bqt->max_depth);
+ if (tag >= bqt->max_depth)
+ return 1;
- tag += ffz(*map);
__set_bit(tag, bqt->tag_map);
rq->flags |= REQ_QUEUED;
@@ -1020,7 +1009,8 @@ void blk_queue_invalidate_tags(request_queue_t *q)
rq = list_entry_rq(tmp);
if (rq->tag == -1) {
- printk("bad tag found on list\n");
+ printk(KERN_ERR
+ "%s: bad tag found on list\n", __FUNCTION__);
list_del_init(&rq->queuelist);
rq->flags &= ~REQ_QUEUED;
} else
@@ -1148,7 +1138,7 @@ new_hw_segment:
}
-int blk_phys_contig_segment(request_queue_t *q, struct bio *bio,
+static int blk_phys_contig_segment(request_queue_t *q, struct bio *bio,
struct bio *nxt)
{
if (!(q->queue_flags & (1 << QUEUE_FLAG_CLUSTER)))
@@ -1169,9 +1159,7 @@ int blk_phys_contig_segment(request_queue_t *q, struct bio *bio,
return 0;
}
-EXPORT_SYMBOL(blk_phys_contig_segment);
-
-int blk_hw_contig_segment(request_queue_t *q, struct bio *bio,
+static int blk_hw_contig_segment(request_queue_t *q, struct bio *bio,
struct bio *nxt)
{
if (unlikely(!bio_flagged(bio, BIO_SEG_VALID)))
@@ -1187,8 +1175,6 @@ int blk_hw_contig_segment(request_queue_t *q, struct bio *bio,
return 1;
}
-EXPORT_SYMBOL(blk_hw_contig_segment);
-
/*
* map a request to scatterlist, return number of sg entries setup. Caller
* must make sure sg can hold rq->nr_phys_segments entries
@@ -1358,8 +1344,8 @@ static int ll_front_merge_fn(request_queue_t *q, struct request *req,
static int ll_merge_requests_fn(request_queue_t *q, struct request *req,
struct request *next)
{
- int total_phys_segments = req->nr_phys_segments +next->nr_phys_segments;
- int total_hw_segments = req->nr_hw_segments + next->nr_hw_segments;
+ int total_phys_segments;
+ int total_hw_segments;
/*
* First check if the either of the requests are re-queued
@@ -1369,7 +1355,7 @@ static int ll_merge_requests_fn(request_queue_t *q, struct request *req,
return 0;
/*
- * Will it become to large?
+ * Will it become too large?
*/
if ((req->nr_sectors + next->nr_sectors) > q->max_sectors)
return 0;
@@ -1450,7 +1436,7 @@ EXPORT_SYMBOL(blk_remove_plug);
*/
void __generic_unplug_device(request_queue_t *q)
{
- if (test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags))
+ if (unlikely(test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags)))
return;
if (!blk_remove_plug(q))
@@ -1645,7 +1631,8 @@ static int blk_init_free_list(request_queue_t *q)
init_waitqueue_head(&rl->wait[WRITE]);
init_waitqueue_head(&rl->drain);
- rl->rq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, request_cachep);
+ rl->rq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
+ mempool_free_slab, request_cachep, q->node);
if (!rl->rq_pool)
return -ENOMEM;
@@ -1657,8 +1644,15 @@ static int __make_request(request_queue_t *, struct bio *);
request_queue_t *blk_alloc_queue(int gfp_mask)
{
- request_queue_t *q = kmem_cache_alloc(requestq_cachep, gfp_mask);
+ return blk_alloc_queue_node(gfp_mask, -1);
+}
+EXPORT_SYMBOL(blk_alloc_queue);
+request_queue_t *blk_alloc_queue_node(int gfp_mask, int node_id)
+{
+ request_queue_t *q;
+
+ q = kmem_cache_alloc_node(requestq_cachep, gfp_mask, node_id);
if (!q)
return NULL;
@@ -1671,8 +1665,7 @@ request_queue_t *blk_alloc_queue(int gfp_mask)
return q;
}
-
-EXPORT_SYMBOL(blk_alloc_queue);
+EXPORT_SYMBOL(blk_alloc_queue_node);
/**
* blk_init_queue - prepare a request queue for use with a block device
@@ -1705,13 +1698,22 @@ EXPORT_SYMBOL(blk_alloc_queue);
* blk_init_queue() must be paired with a blk_cleanup_queue() call
* when the block device is deactivated (such as at module unload).
**/
+
request_queue_t *blk_init_queue(request_fn_proc *rfn, spinlock_t *lock)
{
- request_queue_t *q = blk_alloc_queue(GFP_KERNEL);
+ return blk_init_queue_node(rfn, lock, -1);
+}
+EXPORT_SYMBOL(blk_init_queue);
+
+request_queue_t *
+blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
+{
+ request_queue_t *q = blk_alloc_queue_node(GFP_KERNEL, node_id);
if (!q)
return NULL;
+ q->node = node_id;
if (blk_init_free_list(q))
goto out_init;
@@ -1754,12 +1756,11 @@ out_init:
kmem_cache_free(requestq_cachep, q);
return NULL;
}
-
-EXPORT_SYMBOL(blk_init_queue);
+EXPORT_SYMBOL(blk_init_queue_node);
int blk_get_queue(request_queue_t *q)
{
- if (!test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)) {
+ if (likely(!test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) {
atomic_inc(&q->refcnt);
return 0;
}
@@ -1821,7 +1822,7 @@ static inline int ioc_batching(request_queue_t *q, struct io_context *ioc)
* is the behaviour we want though - once it gets a wakeup it should be given
* a nice run.
*/
-void ioc_set_batching(request_queue_t *q, struct io_context *ioc)
+static void ioc_set_batching(request_queue_t *q, struct io_context *ioc)
{
if (!ioc || ioc_batching(q, ioc))
return;
@@ -1838,7 +1839,6 @@ static void __freed_request(request_queue_t *q, int rw)
clear_queue_congested(q, rw);
if (rl->count[rw] + 1 <= q->nr_requests) {
- smp_mb();
if (waitqueue_active(&rl->wait[rw]))
wake_up(&rl->wait[rw]);
@@ -1966,7 +1966,6 @@ static struct request *get_request_wait(request_queue_t *q, int rw)
DEFINE_WAIT(wait);
struct request *rq;
- generic_unplug_device(q);
do {
struct request_list *rl = &q->rq;
@@ -1978,6 +1977,7 @@ static struct request *get_request_wait(request_queue_t *q, int rw)
if (!rq) {
struct io_context *ioc;
+ generic_unplug_device(q);
io_schedule();
/*
@@ -2038,7 +2038,6 @@ EXPORT_SYMBOL(blk_requeue_request);
* @rq: request to be inserted
* @at_head: insert request at head or tail of queue
* @data: private data
- * @reinsert: true if request it a reinsertion of previously processed one
*
* Description:
* Many block devices need to execute commands asynchronously, so they don't
@@ -2053,8 +2052,9 @@ EXPORT_SYMBOL(blk_requeue_request);
* host that is unable to accept a particular command.
*/
void blk_insert_request(request_queue_t *q, struct request *rq,
- int at_head, void *data, int reinsert)
+ int at_head, void *data)
{
+ int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
unsigned long flags;
/*
@@ -2071,20 +2071,12 @@ void blk_insert_request(request_queue_t *q, struct request *rq,
/*
* If command is tagged, release the tag
*/
- if (reinsert)
- blk_requeue_request(q, rq);
- else {
- int where = ELEVATOR_INSERT_BACK;
-
- if (at_head)
- where = ELEVATOR_INSERT_FRONT;
+ if (blk_rq_tagged(rq))
+ blk_queue_end_tag(q, rq);
- if (blk_rq_tagged(rq))
- blk_queue_end_tag(q, rq);
+ drive_stat_acct(rq, rq->nr_sectors, 1);
+ __elv_add_request(q, rq, where, 0);
- drive_stat_acct(rq, rq->nr_sectors, 1);
- __elv_add_request(q, rq, where, 0);
- }
if (blk_queue_plugged(q))
__generic_unplug_device(q);
else
@@ -2259,45 +2251,7 @@ int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector)
EXPORT_SYMBOL(blkdev_issue_flush);
-/**
- * blkdev_scsi_issue_flush_fn - issue flush for SCSI devices
- * @q: device queue
- * @disk: gendisk
- * @error_sector: error offset
- *
- * Description:
- * Devices understanding the SCSI command set, can use this function as
- * a helper for issuing a cache flush. Note: driver is required to store
- * the error offset (in case of error flushing) in ->sector of struct
- * request.
- */
-int blkdev_scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
- sector_t *error_sector)
-{
- struct request *rq = blk_get_request(q, WRITE, __GFP_WAIT);
- int ret;
-
- rq->flags |= REQ_BLOCK_PC | REQ_SOFTBARRIER;
- rq->sector = 0;
- memset(rq->cmd, 0, sizeof(rq->cmd));
- rq->cmd[0] = 0x35;
- rq->cmd_len = 12;
- rq->data = NULL;
- rq->data_len = 0;
- rq->timeout = 60 * HZ;
-
- ret = blk_execute_rq(q, disk, rq);
-
- if (ret && error_sector)
- *error_sector = rq->sector;
-
- blk_put_request(rq);
- return ret;
-}
-
-EXPORT_SYMBOL(blkdev_scsi_issue_flush_fn);
-
-void drive_stat_acct(struct request *rq, int nr_sectors, int new_io)
+static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io)
{
int rw = rq_data_dir(rq);
@@ -2556,16 +2510,6 @@ void blk_attempt_remerge(request_queue_t *q, struct request *rq)
EXPORT_SYMBOL(blk_attempt_remerge);
-/*
- * Non-locking blk_attempt_remerge variant.
- */
-void __blk_attempt_remerge(request_queue_t *q, struct request *rq)
-{
- attempt_back_merge(q, rq);
-}
-
-EXPORT_SYMBOL(__blk_attempt_remerge);
-
static int __make_request(request_queue_t *q, struct bio *bio)
{
struct request *req, *freereq = NULL;
@@ -2589,7 +2533,7 @@ static int __make_request(request_queue_t *q, struct bio *bio)
spin_lock_prefetch(q->queue_lock);
barrier = bio_barrier(bio);
- if (barrier && (q->ordered == QUEUE_ORDERED_NONE)) {
+ if (unlikely(barrier) && (q->ordered == QUEUE_ORDERED_NONE)) {
err = -EOPNOTSUPP;
goto end_io;
}
@@ -2690,7 +2634,7 @@ get_rq:
/*
* REQ_BARRIER implies no merging, but lets make it explicit
*/
- if (barrier)
+ if (unlikely(barrier))
req->flags |= (REQ_HARDBARRIER | REQ_NOMERGE);
req->errors = 0;
@@ -2814,7 +2758,7 @@ static inline void block_wait_queue_running(request_queue_t *q)
{
DEFINE_WAIT(wait);
- while (test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags)) {
+ while (unlikely(test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags))) {
struct request_list *rl = &q->rq;
prepare_to_wait_exclusive(&rl->drain, &wait,
@@ -2923,7 +2867,7 @@ end_io:
goto end_io;
}
- if (test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))
+ if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
goto end_io;
block_wait_queue_running(q);
@@ -2976,7 +2920,7 @@ void submit_bio(int rw, struct bio *bio)
EXPORT_SYMBOL(submit_bio);
-void blk_recalc_rq_segments(struct request *rq)
+static void blk_recalc_rq_segments(struct request *rq)
{
struct bio *bio, *prevbio = NULL;
int nr_phys_segs, nr_hw_segs;
@@ -3018,7 +2962,7 @@ void blk_recalc_rq_segments(struct request *rq)
rq->nr_hw_segments = nr_hw_segs;
}
-void blk_recalc_rq_sectors(struct request *rq, int nsect)
+static void blk_recalc_rq_sectors(struct request *rq, int nsect)
{
if (blk_fs_request(rq)) {
rq->hard_sector += nsect;
@@ -3582,7 +3526,7 @@ queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
q = container_of(kobj, struct request_queue, kobj);
if (!entry->show)
- return 0;
+ return -EIO;
return entry->show(q, page);
}
@@ -3596,7 +3540,7 @@ queue_attr_store(struct kobject *kobj, struct attribute *attr,
q = container_of(kobj, struct request_queue, kobj);
if (!entry->store)
- return -EINVAL;
+ return -EIO;
return entry->store(q, page, length);
}
@@ -3606,7 +3550,7 @@ static struct sysfs_ops queue_sysfs_ops = {
.store = queue_attr_store,
};
-struct kobj_type queue_ktype = {
+static struct kobj_type queue_ktype = {
.sysfs_ops = &queue_sysfs_ops,
.default_attrs = default_attrs,
};
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 6f011d0d8e9..b35e08876dd 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -472,17 +472,11 @@ static int do_bio_filebacked(struct loop_device *lo, struct bio *bio)
*/
static void loop_add_bio(struct loop_device *lo, struct bio *bio)
{
- unsigned long flags;
-
- spin_lock_irqsave(&lo->lo_lock, flags);
if (lo->lo_biotail) {
lo->lo_biotail->bi_next = bio;
lo->lo_biotail = bio;
} else
lo->lo_bio = lo->lo_biotail = bio;
- spin_unlock_irqrestore(&lo->lo_lock, flags);
-
- up(&lo->lo_bh_mutex);
}
/*
@@ -492,14 +486,12 @@ static struct bio *loop_get_bio(struct loop_device *lo)
{
struct bio *bio;
- spin_lock_irq(&lo->lo_lock);
if ((bio = lo->lo_bio)) {
if (bio == lo->lo_biotail)
lo->lo_biotail = NULL;
lo->lo_bio = bio->bi_next;
bio->bi_next = NULL;
}
- spin_unlock_irq(&lo->lo_lock);
return bio;
}
@@ -509,35 +501,28 @@ static int loop_make_request(request_queue_t *q, struct bio *old_bio)
struct loop_device *lo = q->queuedata;
int rw = bio_rw(old_bio);
- if (!lo)
- goto out;
+ if (rw == READA)
+ rw = READ;
+
+ BUG_ON(!lo || (rw != READ && rw != WRITE));
spin_lock_irq(&lo->lo_lock);
if (lo->lo_state != Lo_bound)
- goto inactive;
- atomic_inc(&lo->lo_pending);
- spin_unlock_irq(&lo->lo_lock);
-
- if (rw == WRITE) {
- if (lo->lo_flags & LO_FLAGS_READ_ONLY)
- goto err;
- } else if (rw == READA) {
- rw = READ;
- } else if (rw != READ) {
- printk(KERN_ERR "loop: unknown command (%x)\n", rw);
- goto err;
- }
+ goto out;
+ if (unlikely(rw == WRITE && (lo->lo_flags & LO_FLAGS_READ_ONLY)))
+ goto out;
+ lo->lo_pending++;
loop_add_bio(lo, old_bio);
+ spin_unlock_irq(&lo->lo_lock);
+ up(&lo->lo_bh_mutex);
return 0;
-err:
- if (atomic_dec_and_test(&lo->lo_pending))
- up(&lo->lo_bh_mutex);
+
out:
+ if (lo->lo_pending == 0)
+ up(&lo->lo_bh_mutex);
+ spin_unlock_irq(&lo->lo_lock);
bio_io_error(old_bio, old_bio->bi_size);
return 0;
-inactive:
- spin_unlock_irq(&lo->lo_lock);
- goto out;
}
/*
@@ -560,13 +545,11 @@ static void do_loop_switch(struct loop_device *, struct switch_request *);
static inline void loop_handle_bio(struct loop_device *lo, struct bio *bio)
{
- int ret;
-
if (unlikely(!bio->bi_bdev)) {
do_loop_switch(lo, bio->bi_private);
bio_put(bio);
} else {
- ret = do_bio_filebacked(lo, bio);
+ int ret = do_bio_filebacked(lo, bio);
bio_endio(bio, bio->bi_size, ret);
}
}
@@ -594,7 +577,7 @@ static int loop_thread(void *data)
set_user_nice(current, -20);
lo->lo_state = Lo_bound;
- atomic_inc(&lo->lo_pending);
+ lo->lo_pending = 1;
/*
* up sem, we are running
@@ -602,26 +585,37 @@ static int loop_thread(void *data)
up(&lo->lo_sem);
for (;;) {
- down_interruptible(&lo->lo_bh_mutex);
+ int pending;
+
/*
- * could be upped because of tear-down, not because of
- * pending work
+ * interruptible just to not contribute to load avg
*/
- if (!atomic_read(&lo->lo_pending))
+ if (down_interruptible(&lo->lo_bh_mutex))
+ continue;
+
+ spin_lock_irq(&lo->lo_lock);
+
+ /*
+ * could be upped because of tear-down, not pending work
+ */
+ if (unlikely(!lo->lo_pending)) {
+ spin_unlock_irq(&lo->lo_lock);
break;
+ }
bio = loop_get_bio(lo);
- if (!bio) {
- printk("loop: missing bio\n");
- continue;
- }
+ lo->lo_pending--;
+ pending = lo->lo_pending;
+ spin_unlock_irq(&lo->lo_lock);
+
+ BUG_ON(!bio);
loop_handle_bio(lo, bio);
/*
* upped both for pending work and tear-down, lo_pending
* will hit zero then
*/
- if (atomic_dec_and_test(&lo->lo_pending))
+ if (unlikely(!pending))
break;
}
@@ -900,7 +894,8 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
spin_lock_irq(&lo->lo_lock);
lo->lo_state = Lo_rundown;
- if (atomic_dec_and_test(&lo->lo_pending))
+ lo->lo_pending--;
+ if (!lo->lo_pending)
up(&lo->lo_bh_mutex);
spin_unlock_irq(&lo->lo_lock);
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 202a5a74ad3..fa49d62626b 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -723,7 +723,7 @@ static int pd_special_command(struct pd_unit *disk,
rq.ref_count = 1;
rq.waiting = &wait;
rq.end_io = blk_end_sync_rq;
- blk_insert_request(disk->gd->queue, &rq, 0, func, 0);
+ blk_insert_request(disk->gd->queue, &rq, 0, func);
wait_for_completion(&wait);
rq.waiting = NULL;
if (rq.errors)
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index dbeb107bb97..84d8e291ed9 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -222,7 +222,7 @@ static int pg_identify(struct pg *dev, int log);
static char pg_scratch[512]; /* scratch block buffer */
-static struct class_simple *pg_class;
+static struct class *pg_class;
/* kernel glue structures */
@@ -666,7 +666,7 @@ static int __init pg_init(void)
err = -1;
goto out;
}
- pg_class = class_simple_create(THIS_MODULE, "pg");
+ pg_class = class_create(THIS_MODULE, "pg");
if (IS_ERR(pg_class)) {
err = PTR_ERR(pg_class);
goto out_chrdev;
@@ -675,7 +675,7 @@ static int __init pg_init(void)
for (unit = 0; unit < PG_UNITS; unit++) {
struct pg *dev = &devices[unit];
if (dev->present) {
- class_simple_device_add(pg_class, MKDEV(major, unit),
+ class_device_create(pg_class, MKDEV(major, unit),
NULL, "pg%u", unit);
err = devfs_mk_cdev(MKDEV(major, unit),
S_IFCHR | S_IRUSR | S_IWUSR, "pg/%u",
@@ -688,8 +688,8 @@ static int __init pg_init(void)
goto out;
out_class:
- class_simple_device_remove(MKDEV(major, unit));
- class_simple_destroy(pg_class);
+ class_device_destroy(pg_class, MKDEV(major, unit));
+ class_destroy(pg_class);
out_chrdev:
unregister_chrdev(major, "pg");
out:
@@ -703,11 +703,11 @@ static void __exit pg_exit(void)
for (unit = 0; unit < PG_UNITS; unit++) {
struct pg *dev = &devices[unit];
if (dev->present) {
- class_simple_device_remove(MKDEV(major, unit));
+ class_device_destroy(pg_class, MKDEV(major, unit));
devfs_remove("pg/%u", unit);
}
}
- class_simple_destroy(pg_class);
+ class_destroy(pg_class);
devfs_remove("pg");
unregister_chrdev(major, name);
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index 8fbd6922fe0..5fe8ee86f09 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -242,7 +242,7 @@ static struct file_operations pt_fops = {
};
/* sysfs class support */
-static struct class_simple *pt_class;
+static struct class *pt_class;
static inline int status_reg(struct pi_adapter *pi)
{
@@ -963,7 +963,7 @@ static int __init pt_init(void)
err = -1;
goto out;
}
- pt_class = class_simple_create(THIS_MODULE, "pt");
+ pt_class = class_create(THIS_MODULE, "pt");
if (IS_ERR(pt_class)) {
err = PTR_ERR(pt_class);
goto out_chrdev;
@@ -972,29 +972,29 @@ static int __init pt_init(void)
devfs_mk_dir("pt");
for (unit = 0; unit < PT_UNITS; unit++)
if (pt[unit].present) {
- class_simple_device_add(pt_class, MKDEV(major, unit),
+ class_device_create(pt_class, MKDEV(major, unit),
NULL, "pt%d", unit);
err = devfs_mk_cdev(MKDEV(major, unit),
S_IFCHR | S_IRUSR | S_IWUSR,
"pt/%d", unit);
if (err) {
- class_simple_device_remove(MKDEV(major, unit));
+ class_device_destroy(pt_class, MKDEV(major, unit));
goto out_class;
}
- class_simple_device_add(pt_class, MKDEV(major, unit + 128),
+ class_device_create(pt_class, MKDEV(major, unit + 128),
NULL, "pt%dn", unit);
err = devfs_mk_cdev(MKDEV(major, unit + 128),
S_IFCHR | S_IRUSR | S_IWUSR,
"pt/%dn", unit);
if (err) {
- class_simple_device_remove(MKDEV(major, unit + 128));
+ class_device_destroy(pt_class, MKDEV(major, unit + 128));
goto out_class;
}
}
goto out;
out_class:
- class_simple_destroy(pt_class);
+ class_destroy(pt_class);
out_chrdev:
unregister_chrdev(major, "pt");
out:
@@ -1006,12 +1006,12 @@ static void __exit pt_exit(void)
int unit;
for (unit = 0; unit < PT_UNITS; unit++)
if (pt[unit].present) {
- class_simple_device_remove(MKDEV(major, unit));
+ class_device_destroy(pt_class, MKDEV(major, unit));
devfs_remove("pt/%d", unit);
- class_simple_device_remove(MKDEV(major, unit + 128));
+ class_device_destroy(pt_class, MKDEV(major, unit + 128));
devfs_remove("pt/%dn", unit);
}
- class_simple_destroy(pt_class);
+ class_destroy(pt_class);
devfs_remove("pt");
unregister_chrdev(major, name);
for (unit = 0; unit < PT_UNITS; unit++)
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 1a1fa3ccb91..7b838342f0a 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -467,14 +467,12 @@ static int pkt_set_speed(struct pktcdvd_device *pd, unsigned write_speed, unsign
* Queue a bio for processing by the low-level CD device. Must be called
* from process context.
*/
-static void pkt_queue_bio(struct pktcdvd_device *pd, struct bio *bio, int high_prio_read)
+static void pkt_queue_bio(struct pktcdvd_device *pd, struct bio *bio)
{
spin_lock(&pd->iosched.lock);
if (bio_data_dir(bio) == READ) {
pkt_add_list_last(bio, &pd->iosched.read_queue,
&pd->iosched.read_queue_tail);
- if (high_prio_read)
- pd->iosched.high_prio_read = 1;
} else {
pkt_add_list_last(bio, &pd->iosched.write_queue,
&pd->iosched.write_queue_tail);
@@ -490,15 +488,16 @@ static void pkt_queue_bio(struct pktcdvd_device *pd, struct bio *bio, int high_p
* requirements for CDRW drives:
* - A cache flush command must be inserted before a read request if the
* previous request was a write.
- * - Switching between reading and writing is slow, so don't it more often
+ * - Switching between reading and writing is slow, so don't do it more often
* than necessary.
+ * - Optimize for throughput at the expense of latency. This means that streaming
+ * writes will never be interrupted by a read, but if the drive has to seek
+ * before the next write, switch to reading instead if there are any pending
+ * read requests.
* - Set the read speed according to current usage pattern. When only reading
* from the device, it's best to use the highest possible read speed, but
* when switching often between reading and writing, it's better to have the
* same read and write speeds.
- * - Reads originating from user space should have higher priority than reads
- * originating from pkt_gather_data, because some process is usually waiting
- * on reads of the first kind.
*/
static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
{
@@ -512,21 +511,24 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
for (;;) {
struct bio *bio;
- int reads_queued, writes_queued, high_prio_read;
+ int reads_queued, writes_queued;
spin_lock(&pd->iosched.lock);
reads_queued = (pd->iosched.read_queue != NULL);
writes_queued = (pd->iosched.write_queue != NULL);
- if (!reads_queued)
- pd->iosched.high_prio_read = 0;
- high_prio_read = pd->iosched.high_prio_read;
spin_unlock(&pd->iosched.lock);
if (!reads_queued && !writes_queued)
break;
if (pd->iosched.writing) {
- if (high_prio_read || (!writes_queued && reads_queued)) {
+ int need_write_seek = 1;
+ spin_lock(&pd->iosched.lock);
+ bio = pd->iosched.write_queue;
+ spin_unlock(&pd->iosched.lock);
+ if (bio && (bio->bi_sector == pd->iosched.last_write))
+ need_write_seek = 0;
+ if (need_write_seek && reads_queued) {
if (atomic_read(&pd->cdrw.pending_bios) > 0) {
VPRINTK("pktcdvd: write, waiting\n");
break;
@@ -559,8 +561,10 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
if (bio_data_dir(bio) == READ)
pd->iosched.successive_reads += bio->bi_size >> 10;
- else
+ else {
pd->iosched.successive_reads = 0;
+ pd->iosched.last_write = bio->bi_sector + bio_sectors(bio);
+ }
if (pd->iosched.successive_reads >= HI_SPEED_SWITCH) {
if (pd->read_speed == pd->write_speed) {
pd->read_speed = MAX_SPEED;
@@ -765,7 +769,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
atomic_inc(&pkt->io_wait);
bio->bi_rw = READ;
- pkt_queue_bio(pd, bio, 0);
+ pkt_queue_bio(pd, bio);
frames_read++;
}
@@ -914,8 +918,10 @@ static int pkt_handle_queue(struct pktcdvd_device *pd)
bio = node->bio;
zone = ZONE(bio->bi_sector, pd);
list_for_each_entry(p, &pd->cdrw.pkt_active_list, list) {
- if (p->sector == zone)
+ if (p->sector == zone) {
+ bio = NULL;
goto try_next_bio;
+ }
}
break;
try_next_bio:
@@ -1060,7 +1066,7 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
atomic_set(&pkt->io_wait, 1);
pkt->w_bio->bi_rw = WRITE;
- pkt_queue_bio(pd, pkt->w_bio, 0);
+ pkt_queue_bio(pd, pkt->w_bio);
}
static void pkt_finish_packet(struct packet_data *pkt, int uptodate)
@@ -1245,8 +1251,7 @@ static int kcdrwd(void *foobar)
VPRINTK("kcdrwd: wake up\n");
/* make swsusp happy with our thread */
- if (current->flags & PF_FREEZE)
- refrigerator(PF_FREEZE);
+ try_to_freeze();
list_for_each_entry(pkt, &pd->cdrw.pkt_active_list, list) {
if (!pkt->sleep_time)
@@ -2019,7 +2024,13 @@ static int pkt_open(struct inode *inode, struct file *file)
BUG_ON(pd->refcnt < 0);
pd->refcnt++;
- if (pd->refcnt == 1) {
+ if (pd->refcnt > 1) {
+ if ((file->f_mode & FMODE_WRITE) &&
+ !test_bit(PACKET_WRITABLE, &pd->flags)) {
+ ret = -EBUSY;
+ goto out_dec;
+ }
+ } else {
if (pkt_open_dev(pd, file->f_mode & FMODE_WRITE)) {
ret = -EIO;
goto out_dec;
@@ -2112,7 +2123,7 @@ static int pkt_make_request(request_queue_t *q, struct bio *bio)
cloned_bio->bi_private = psd;
cloned_bio->bi_end_io = pkt_end_io_read_cloned;
pd->stats.secs_r += bio->bi_size >> 9;
- pkt_queue_bio(pd, cloned_bio, 1);
+ pkt_queue_bio(pd, cloned_bio);
return 0;
}
@@ -2406,7 +2417,7 @@ static int pkt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u
case CDROM_LAST_WRITTEN:
case CDROM_SEND_PACKET:
case SCSI_IOCTL_SEND_COMMAND:
- return ioctl_by_bdev(pd->bdev, cmd, arg);
+ return blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg);
case CDROMEJECT:
/*
@@ -2414,7 +2425,7 @@ static int pkt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u
* have to unlock it or else the eject command fails.
*/
pkt_lock_door(pd, 0);
- return ioctl_by_bdev(pd->bdev, cmd, arg);
+ return blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg);
default:
printk("pktcdvd: Unknown ioctl for %s (%x)\n", pd->name, cmd);
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
index 797f5988c2b..5ed3a637945 100644
--- a/drivers/block/sx8.c
+++ b/drivers/block/sx8.c
@@ -614,7 +614,7 @@ static int carm_array_info (struct carm_host *host, unsigned int array_idx)
spin_unlock_irq(&host->lock);
DPRINTK("blk_insert_request, tag == %u\n", idx);
- blk_insert_request(host->oob_q, crq->rq, 1, crq, 0);
+ blk_insert_request(host->oob_q, crq->rq, 1, crq);
return 0;
@@ -653,7 +653,7 @@ static int carm_send_special (struct carm_host *host, carm_sspc_t func)
crq->msg_bucket = (u32) rc;
DPRINTK("blk_insert_request, tag == %u\n", idx);
- blk_insert_request(host->oob_q, crq->rq, 1, crq, 0);
+ blk_insert_request(host->oob_q, crq->rq, 1, crq);
return 0;
}
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index ce42889f98f..685f061e69b 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -8,13 +8,12 @@
* and is not licensed separately. See file COPYING for details.
*
* TODO (sorted by decreasing priority)
+ * -- Kill first_open (Al Viro fixed the block layer now)
* -- Do resets with usb_device_reset (needs a thread context, use khubd)
* -- set readonly flag for CDs, set removable flag for CF readers
* -- do inquiry and verify we got a disk and not a tape (for LUN mismatch)
- * -- support pphaneuf's SDDR-75 with two LUNs (also broken capacity...)
* -- special case some senses, e.g. 3a/0 -> no media present, reduce retries
* -- verify the 13 conditions and do bulk resets
- * -- normal pool of commands instead of cmdv[]?
* -- kill last_pipe and simply do two-state clearing on both pipes
* -- verify protocol (bulk) from USB descriptors (maybe...)
* -- highmem and sg
@@ -49,7 +48,14 @@
#define US_SC_SCSI 0x06 /* Transparent */
/*
+ * This many LUNs per USB device.
+ * Every one of them takes a host, see UB_MAX_HOSTS.
*/
+#define UB_MAX_LUNS 9
+
+/*
+ */
+
#define UB_MINORS_PER_MAJOR 8
#define UB_MAX_CDB_SIZE 16 /* Corresponds to Bulk */
@@ -65,7 +71,7 @@ struct bulk_cb_wrap {
u32 Tag; /* unique per command id */
__le32 DataTransferLength; /* size of data */
u8 Flags; /* direction in bit 0 */
- u8 Lun; /* LUN normally 0 */
+ u8 Lun; /* LUN */
u8 Length; /* of of the CDB */
u8 CDB[UB_MAX_CDB_SIZE]; /* max command */
};
@@ -168,6 +174,7 @@ struct ub_scsi_cmd {
unsigned int len; /* Requested length */
// struct scatterlist sgv[UB_MAX_REQ_SG];
+ struct ub_lun *lun;
void (*done)(struct ub_dev *, struct ub_scsi_cmd *);
void *back;
};
@@ -252,25 +259,47 @@ struct ub_scsi_cmd_queue {
};
/*
- * The UB device instance.
+ * The block device instance (one per LUN).
+ */
+struct ub_lun {
+ struct ub_dev *udev;
+ struct list_head link;
+ struct gendisk *disk;
+ int id; /* Host index */
+ int num; /* LUN number */
+ char name[16];
+
+ int changed; /* Media was changed */
+ int removable;
+ int readonly;
+ int first_open; /* Kludge. See ub_bd_open. */
+
+ /* Use Ingo's mempool if or when we have more than one command. */
+ /*
+ * Currently we never need more than one command for the whole device.
+ * However, giving every LUN a command is a cheap and automatic way
+ * to enforce fairness between them.
+ */
+ int cmda[1];
+ struct ub_scsi_cmd cmdv[1];
+
+ struct ub_capacity capacity;
+};
+
+/*
+ * The USB device instance.
*/
struct ub_dev {
spinlock_t lock;
- int id; /* Number among ub's */
atomic_t poison; /* The USB device is disconnected */
int openc; /* protected by ub_lock! */
/* kref is too implicit for our taste */
unsigned int tagcnt;
- int changed; /* Media was changed */
- int removable;
- int readonly;
- int first_open; /* Kludge. See ub_bd_open. */
- char name[8];
+ char name[12];
struct usb_device *dev;
struct usb_interface *intf;
- struct ub_capacity capacity;
- struct gendisk *disk;
+ struct list_head luns;
unsigned int send_bulk_pipe; /* cached pipe values */
unsigned int recv_bulk_pipe;
@@ -279,10 +308,6 @@ struct ub_dev {
struct tasklet_struct tasklet;
- /* XXX Use Ingo's mempool (once we have more than one) */
- int cmda[1];
- struct ub_scsi_cmd cmdv[1];
-
struct ub_scsi_cmd_queue cmd_queue;
struct ub_scsi_cmd top_rqs_cmd; /* REQUEST SENSE */
unsigned char top_sense[UB_SENSE_SIZE];
@@ -301,9 +326,9 @@ struct ub_dev {
/*
*/
static void ub_cleanup(struct ub_dev *sc);
-static int ub_bd_rq_fn_1(struct ub_dev *sc, struct request *rq);
-static int ub_cmd_build_block(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
- struct request *rq);
+static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq);
+static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
+ struct ub_scsi_cmd *cmd, struct request *rq);
static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
struct request *rq);
static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
@@ -320,8 +345,10 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
int stalled_pipe);
static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd);
-static int ub_sync_tur(struct ub_dev *sc);
-static int ub_sync_read_cap(struct ub_dev *sc, struct ub_capacity *ret);
+static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun);
+static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
+ struct ub_capacity *ret);
+static int ub_probe_lun(struct ub_dev *sc, int lnum);
/*
*/
@@ -342,6 +369,7 @@ MODULE_DEVICE_TABLE(usb, ub_usb_ids);
*/
#define UB_MAX_HOSTS 26
static char ub_hostv[UB_MAX_HOSTS];
+
static DEFINE_SPINLOCK(ub_lock); /* Locks globals and ->openc */
/*
@@ -402,10 +430,12 @@ static void ub_cmdtr_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
}
}
-static ssize_t ub_diag_show(struct device *dev, char *page)
+static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr, char *page)
{
struct usb_interface *intf;
struct ub_dev *sc;
+ struct list_head *p;
+ struct ub_lun *lun;
int cnt;
unsigned long flags;
int nc, nh;
@@ -421,9 +451,15 @@ static ssize_t ub_diag_show(struct device *dev, char *page)
spin_lock_irqsave(&sc->lock, flags);
cnt += sprintf(page + cnt,
- "qlen %d qmax %d changed %d removable %d readonly %d\n",
- sc->cmd_queue.qlen, sc->cmd_queue.qmax,
- sc->changed, sc->removable, sc->readonly);
+ "qlen %d qmax %d\n",
+ sc->cmd_queue.qlen, sc->cmd_queue.qmax);
+
+ list_for_each (p, &sc->luns) {
+ lun = list_entry(p, struct ub_lun, link);
+ cnt += sprintf(page + cnt,
+ "lun %u changed %d removable %d readonly %d\n",
+ lun->num, lun->changed, lun->removable, lun->readonly);
+ }
if ((nc = sc->tr.cur + 1) == SCMD_TRACE_SZ) nc = 0;
for (j = 0; j < SCMD_TRACE_SZ; j++) {
@@ -523,53 +559,63 @@ static void ub_put(struct ub_dev *sc)
*/
static void ub_cleanup(struct ub_dev *sc)
{
+ struct list_head *p;
+ struct ub_lun *lun;
request_queue_t *q;
- /* I don't think queue can be NULL. But... Stolen from sx8.c */
- if ((q = sc->disk->queue) != NULL)
- blk_cleanup_queue(q);
+ while (!list_empty(&sc->luns)) {
+ p = sc->luns.next;
+ lun = list_entry(p, struct ub_lun, link);
+ list_del(p);
- /*
- * If we zero disk->private_data BEFORE put_disk, we have to check
- * for NULL all over the place in open, release, check_media and
- * revalidate, because the block level semaphore is well inside the
- * put_disk. But we cannot zero after the call, because *disk is gone.
- * The sd.c is blatantly racy in this area.
- */
- /* disk->private_data = NULL; */
- put_disk(sc->disk);
- sc->disk = NULL;
+ /* I don't think queue can be NULL. But... Stolen from sx8.c */
+ if ((q = lun->disk->queue) != NULL)
+ blk_cleanup_queue(q);
+ /*
+ * If we zero disk->private_data BEFORE put_disk, we have
+ * to check for NULL all over the place in open, release,
+ * check_media and revalidate, because the block level
+ * semaphore is well inside the put_disk.
+ * But we cannot zero after the call, because *disk is gone.
+ * The sd.c is blatantly racy in this area.
+ */
+ /* disk->private_data = NULL; */
+ put_disk(lun->disk);
+ lun->disk = NULL;
+
+ ub_id_put(lun->id);
+ kfree(lun);
+ }
- ub_id_put(sc->id);
kfree(sc);
}
/*
* The "command allocator".
*/
-static struct ub_scsi_cmd *ub_get_cmd(struct ub_dev *sc)
+static struct ub_scsi_cmd *ub_get_cmd(struct ub_lun *lun)
{
struct ub_scsi_cmd *ret;
- if (sc->cmda[0])
+ if (lun->cmda[0])
return NULL;
- ret = &sc->cmdv[0];
- sc->cmda[0] = 1;
+ ret = &lun->cmdv[0];
+ lun->cmda[0] = 1;
return ret;
}
-static void ub_put_cmd(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+static void ub_put_cmd(struct ub_lun *lun, struct ub_scsi_cmd *cmd)
{
- if (cmd != &sc->cmdv[0]) {
+ if (cmd != &lun->cmdv[0]) {
printk(KERN_WARNING "%s: releasing a foreign cmd %p\n",
- sc->name, cmd);
+ lun->name, cmd);
return;
}
- if (!sc->cmda[0]) {
- printk(KERN_WARNING "%s: releasing a free cmd\n", sc->name);
+ if (!lun->cmda[0]) {
+ printk(KERN_WARNING "%s: releasing a free cmd\n", lun->name);
return;
}
- sc->cmda[0] = 0;
+ lun->cmda[0] = 0;
}
/*
@@ -630,29 +676,30 @@ static struct ub_scsi_cmd *ub_cmdq_pop(struct ub_dev *sc)
static void ub_bd_rq_fn(request_queue_t *q)
{
- struct ub_dev *sc = q->queuedata;
+ struct ub_lun *lun = q->queuedata;
struct request *rq;
while ((rq = elv_next_request(q)) != NULL) {
- if (ub_bd_rq_fn_1(sc, rq) != 0) {
+ if (ub_bd_rq_fn_1(lun, rq) != 0) {
blk_stop_queue(q);
break;
}
}
}
-static int ub_bd_rq_fn_1(struct ub_dev *sc, struct request *rq)
+static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq)
{
+ struct ub_dev *sc = lun->udev;
struct ub_scsi_cmd *cmd;
int rc;
- if (atomic_read(&sc->poison) || sc->changed) {
+ if (atomic_read(&sc->poison) || lun->changed) {
blkdev_dequeue_request(rq);
ub_end_rq(rq, 0);
return 0;
}
- if ((cmd = ub_get_cmd(sc)) == NULL)
+ if ((cmd = ub_get_cmd(lun)) == NULL)
return -1;
memset(cmd, 0, sizeof(struct ub_scsi_cmd));
@@ -661,32 +708,30 @@ static int ub_bd_rq_fn_1(struct ub_dev *sc, struct request *rq)
if (blk_pc_request(rq)) {
rc = ub_cmd_build_packet(sc, cmd, rq);
} else {
- rc = ub_cmd_build_block(sc, cmd, rq);
+ rc = ub_cmd_build_block(sc, lun, cmd, rq);
}
if (rc != 0) {
- ub_put_cmd(sc, cmd);
+ ub_put_cmd(lun, cmd);
ub_end_rq(rq, 0);
- blk_start_queue(sc->disk->queue);
return 0;
}
-
cmd->state = UB_CMDST_INIT;
+ cmd->lun = lun;
cmd->done = ub_rw_cmd_done;
cmd->back = rq;
cmd->tag = sc->tagcnt++;
if ((rc = ub_submit_scsi(sc, cmd)) != 0) {
- ub_put_cmd(sc, cmd);
+ ub_put_cmd(lun, cmd);
ub_end_rq(rq, 0);
- blk_start_queue(sc->disk->queue);
return 0;
}
return 0;
}
-static int ub_cmd_build_block(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
- struct request *rq)
+static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
+ struct ub_scsi_cmd *cmd, struct request *rq)
{
int ub_dir;
#if 0 /* We use rq->buffer for now */
@@ -707,7 +752,7 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
sg = &cmd->sgv[0];
n_elem = blk_rq_map_sg(q, rq, sg);
if (n_elem <= 0) {
- ub_put_cmd(sc, cmd);
+ ub_put_cmd(lun, cmd);
ub_end_rq(rq, 0);
blk_start_queue(q);
return 0; /* request with no s/g entries? */
@@ -716,7 +761,7 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
if (n_elem != 1) { /* Paranoia */
printk(KERN_WARNING "%s: request with %d segments\n",
sc->name, n_elem);
- ub_put_cmd(sc, cmd);
+ ub_put_cmd(lun, cmd);
ub_end_rq(rq, 0);
blk_start_queue(q);
return 0;
@@ -748,8 +793,8 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
* The call to blk_queue_hardsect_size() guarantees that request
* is aligned, but it is given in terms of 512 byte units, always.
*/
- block = rq->sector >> sc->capacity.bshift;
- nblks = rq->nr_sectors >> sc->capacity.bshift;
+ block = rq->sector >> lun->capacity.bshift;
+ nblks = rq->nr_sectors >> lun->capacity.bshift;
cmd->cdb[0] = (ub_dir == UB_DIR_READ)? READ_10: WRITE_10;
/* 10-byte uses 4 bytes of LBA: 2147483648KB, 2097152MB, 2048GB */
@@ -803,7 +848,8 @@ static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
{
struct request *rq = cmd->back;
- struct gendisk *disk = sc->disk;
+ struct ub_lun *lun = cmd->lun;
+ struct gendisk *disk = lun->disk;
request_queue_t *q = disk->queue;
int uptodate;
@@ -818,7 +864,7 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
else
uptodate = 0;
- ub_put_cmd(sc, cmd);
+ ub_put_cmd(lun, cmd);
ub_end_rq(rq, uptodate);
blk_start_queue(q);
}
@@ -887,7 +933,7 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
bcb->Tag = cmd->tag; /* Endianness is not important */
bcb->DataTransferLength = cpu_to_le32(cmd->len);
bcb->Flags = (cmd->dir == UB_DIR_READ) ? 0x80 : 0;
- bcb->Lun = 0; /* No multi-LUN yet */
+ bcb->Lun = (cmd->lun != NULL) ? cmd->lun->num : 0;
bcb->Length = cmd->cdb_len;
/* copy the command payload */
@@ -1002,9 +1048,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
* The control pipe clears itself - nothing to do.
* XXX Might try to reset the device here and retry.
*/
- printk(KERN_NOTICE "%s: "
- "stall on control pipe for device %u\n",
- sc->name, sc->dev->devnum);
+ printk(KERN_NOTICE "%s: stall on control pipe\n",
+ sc->name);
goto Bad_End;
}
@@ -1025,9 +1070,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
* The control pipe clears itself - nothing to do.
* XXX Might try to reset the device here and retry.
*/
- printk(KERN_NOTICE "%s: "
- "stall on control pipe for device %u\n",
- sc->name, sc->dev->devnum);
+ printk(KERN_NOTICE "%s: stall on control pipe\n",
+ sc->name);
goto Bad_End;
}
@@ -1046,9 +1090,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe);
if (rc != 0) {
printk(KERN_NOTICE "%s: "
- "unable to submit clear for device %u"
- " (code %d)\n",
- sc->name, sc->dev->devnum, rc);
+ "unable to submit clear (%d)\n",
+ sc->name, rc);
/*
* This is typically ENOMEM or some other such shit.
* Retrying is pointless. Just do Bad End on it...
@@ -1107,9 +1150,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe);
if (rc != 0) {
printk(KERN_NOTICE "%s: "
- "unable to submit clear for device %u"
- " (code %d)\n",
- sc->name, sc->dev->devnum, rc);
+ "unable to submit clear (%d)\n",
+ sc->name, rc);
/*
* This is typically ENOMEM or some other such shit.
* Retrying is pointless. Just do Bad End on it...
@@ -1140,9 +1182,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe);
if (rc != 0) {
printk(KERN_NOTICE "%s: "
- "unable to submit clear for device %u"
- " (code %d)\n",
- sc->name, sc->dev->devnum, rc);
+ "unable to submit clear (%d)\n",
+ sc->name, rc);
/*
* This is typically ENOMEM or some other such shit.
* Retrying is pointless. Just do Bad End on it...
@@ -1164,9 +1205,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
* encounter such a thing, try to read the CSW again.
*/
if (++cmd->stat_count >= 4) {
- printk(KERN_NOTICE "%s: "
- "unable to get CSW on device %u\n",
- sc->name, sc->dev->devnum);
+ printk(KERN_NOTICE "%s: unable to get CSW\n",
+ sc->name);
goto Bad_End;
}
__ub_state_stat(sc, cmd);
@@ -1207,10 +1247,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
*/
if (++cmd->stat_count >= 4) {
printk(KERN_NOTICE "%s: "
- "tag mismatch orig 0x%x reply 0x%x "
- "on device %u\n",
- sc->name, cmd->tag, bcs->Tag,
- sc->dev->devnum);
+ "tag mismatch orig 0x%x reply 0x%x\n",
+ sc->name, cmd->tag, bcs->Tag);
goto Bad_End;
}
__ub_state_stat(sc, cmd);
@@ -1244,8 +1282,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
} else {
printk(KERN_WARNING "%s: "
- "wrong command state %d on device %u\n",
- sc->name, cmd->state, sc->dev->devnum);
+ "wrong command state %d\n",
+ sc->name, cmd->state);
goto Bad_End;
}
return;
@@ -1288,7 +1326,6 @@ static void __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
/* XXX Clear stalls */
- printk("%s: CSW #%d submit failed (%d)\n", sc->name, cmd->tag, rc); /* P3 */
ub_complete(&sc->work_done);
ub_state_done(sc, cmd, rc);
return;
@@ -1333,6 +1370,7 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
scmd->state = UB_CMDST_INIT;
scmd->data = sc->top_sense;
scmd->len = UB_SENSE_SIZE;
+ scmd->lun = cmd->lun;
scmd->done = ub_top_sense_done;
scmd->back = cmd;
@@ -1411,14 +1449,14 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd)
}
if (cmd != scmd->back) {
printk(KERN_WARNING "%s: "
- "sense done for wrong command 0x%x on device %u\n",
- sc->name, cmd->tag, sc->dev->devnum);
+ "sense done for wrong command 0x%x\n",
+ sc->name, cmd->tag);
return;
}
if (cmd->state != UB_CMDST_SENSE) {
printk(KERN_WARNING "%s: "
- "sense done with bad cmd state %d on device %u\n",
- sc->name, cmd->state, sc->dev->devnum);
+ "sense done with bad cmd state %d\n",
+ sc->name, cmd->state);
return;
}
@@ -1429,68 +1467,32 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd)
ub_scsi_urb_compl(sc, cmd);
}
-#if 0
-/* Determine what the maximum LUN supported is */
-int usb_stor_Bulk_max_lun(struct us_data *us)
-{
- int result;
-
- /* issue the command */
- result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
- US_BULK_GET_MAX_LUN,
- USB_DIR_IN | USB_TYPE_CLASS |
- USB_RECIP_INTERFACE,
- 0, us->ifnum, us->iobuf, 1, HZ);
-
- /*
- * Some devices (i.e. Iomega Zip100) need this -- apparently
- * the bulk pipes get STALLed when the GetMaxLUN request is
- * processed. This is, in theory, harmless to all other devices
- * (regardless of if they stall or not).
- */
- if (result < 0) {
- usb_stor_clear_halt(us, us->recv_bulk_pipe);
- usb_stor_clear_halt(us, us->send_bulk_pipe);
- }
-
- US_DEBUGP("GetMaxLUN command result is %d, data is %d\n",
- result, us->iobuf[0]);
-
- /* if we have a successful request, return the result */
- if (result == 1)
- return us->iobuf[0];
-
- /* return the default -- no LUNs */
- return 0;
-}
-#endif
-
/*
* This is called from a process context.
*/
-static void ub_revalidate(struct ub_dev *sc)
+static void ub_revalidate(struct ub_dev *sc, struct ub_lun *lun)
{
- sc->readonly = 0; /* XXX Query this from the device */
+ lun->readonly = 0; /* XXX Query this from the device */
- sc->capacity.nsec = 0;
- sc->capacity.bsize = 512;
- sc->capacity.bshift = 0;
+ lun->capacity.nsec = 0;
+ lun->capacity.bsize = 512;
+ lun->capacity.bshift = 0;
- if (ub_sync_tur(sc) != 0)
+ if (ub_sync_tur(sc, lun) != 0)
return; /* Not ready */
- sc->changed = 0;
+ lun->changed = 0;
- if (ub_sync_read_cap(sc, &sc->capacity) != 0) {
+ if (ub_sync_read_cap(sc, lun, &lun->capacity) != 0) {
/*
* The retry here means something is wrong, either with the
* device, with the transport, or with our code.
* We keep this because sd.c has retries for capacity.
*/
- if (ub_sync_read_cap(sc, &sc->capacity) != 0) {
- sc->capacity.nsec = 0;
- sc->capacity.bsize = 512;
- sc->capacity.bshift = 0;
+ if (ub_sync_read_cap(sc, lun, &lun->capacity) != 0) {
+ lun->capacity.nsec = 0;
+ lun->capacity.bsize = 512;
+ lun->capacity.bshift = 0;
}
}
}
@@ -1503,12 +1505,15 @@ static void ub_revalidate(struct ub_dev *sc)
static int ub_bd_open(struct inode *inode, struct file *filp)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
+ struct ub_lun *lun;
struct ub_dev *sc;
unsigned long flags;
int rc;
- if ((sc = disk->private_data) == NULL)
+ if ((lun = disk->private_data) == NULL)
return -ENXIO;
+ sc = lun->udev;
+
spin_lock_irqsave(&ub_lock, flags);
if (atomic_read(&sc->poison)) {
spin_unlock_irqrestore(&ub_lock, flags);
@@ -1529,15 +1534,15 @@ static int ub_bd_open(struct inode *inode, struct file *filp)
* The bottom line is, Al Viro says that we should not allow
* bdev->bd_invalidated to be set when doing add_disk no matter what.
*/
- if (sc->first_open) {
- if (sc->changed) {
- sc->first_open = 0;
+ if (lun->first_open) {
+ lun->first_open = 0;
+ if (lun->changed) {
rc = -ENOMEDIUM;
goto err_open;
}
}
- if (sc->removable || sc->readonly)
+ if (lun->removable || lun->readonly)
check_disk_change(inode->i_bdev);
/*
@@ -1545,12 +1550,12 @@ static int ub_bd_open(struct inode *inode, struct file *filp)
* under some pretty murky conditions (a failure of READ CAPACITY).
* We may need it one day.
*/
- if (sc->removable && sc->changed && !(filp->f_flags & O_NDELAY)) {
+ if (lun->removable && lun->changed && !(filp->f_flags & O_NDELAY)) {
rc = -ENOMEDIUM;
goto err_open;
}
- if (sc->readonly && (filp->f_mode & FMODE_WRITE)) {
+ if (lun->readonly && (filp->f_mode & FMODE_WRITE)) {
rc = -EROFS;
goto err_open;
}
@@ -1567,7 +1572,8 @@ err_open:
static int ub_bd_release(struct inode *inode, struct file *filp)
{
struct gendisk *disk = inode->i_bdev->bd_disk;
- struct ub_dev *sc = disk->private_data;
+ struct ub_lun *lun = disk->private_data;
+ struct ub_dev *sc = lun->udev;
ub_put(sc);
return 0;
@@ -1597,20 +1603,14 @@ static int ub_bd_ioctl(struct inode *inode, struct file *filp,
*/
static int ub_bd_revalidate(struct gendisk *disk)
{
- struct ub_dev *sc = disk->private_data;
-
- ub_revalidate(sc);
- /* This is pretty much a long term P3 */
- if (!atomic_read(&sc->poison)) { /* Cover sc->dev */
- printk(KERN_INFO "%s: device %u capacity nsec %ld bsize %u\n",
- sc->name, sc->dev->devnum,
- sc->capacity.nsec, sc->capacity.bsize);
- }
+ struct ub_lun *lun = disk->private_data;
+
+ ub_revalidate(lun->udev, lun);
/* XXX Support sector size switching like in sr.c */
- blk_queue_hardsect_size(disk->queue, sc->capacity.bsize);
- set_capacity(disk, sc->capacity.nsec);
- // set_disk_ro(sdkp->disk, sc->readonly);
+ blk_queue_hardsect_size(disk->queue, lun->capacity.bsize);
+ set_capacity(disk, lun->capacity.nsec);
+ // set_disk_ro(sdkp->disk, lun->readonly);
return 0;
}
@@ -1626,9 +1626,9 @@ static int ub_bd_revalidate(struct gendisk *disk)
*/
static int ub_bd_media_changed(struct gendisk *disk)
{
- struct ub_dev *sc = disk->private_data;
+ struct ub_lun *lun = disk->private_data;
- if (!sc->removable)
+ if (!lun->removable)
return 0;
/*
@@ -1640,12 +1640,12 @@ static int ub_bd_media_changed(struct gendisk *disk)
* will fail, then block layer discards the data. Since we never
* spin drives up, such devices simply cannot be used with ub anyway.
*/
- if (ub_sync_tur(sc) != 0) {
- sc->changed = 1;
+ if (ub_sync_tur(lun->udev, lun) != 0) {
+ lun->changed = 1;
return 1;
}
- return sc->changed;
+ return lun->changed;
}
static struct block_device_operations ub_bd_fops = {
@@ -1669,7 +1669,7 @@ static void ub_probe_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
/*
* Test if the device has a check condition on it, synchronously.
*/
-static int ub_sync_tur(struct ub_dev *sc)
+static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun)
{
struct ub_scsi_cmd *cmd;
enum { ALLOC_SIZE = sizeof(struct ub_scsi_cmd) };
@@ -1688,6 +1688,7 @@ static int ub_sync_tur(struct ub_dev *sc)
cmd->cdb_len = 6;
cmd->dir = UB_DIR_NONE;
cmd->state = UB_CMDST_INIT;
+ cmd->lun = lun; /* This may be NULL, but that's ok */
cmd->done = ub_probe_done;
cmd->back = &compl;
@@ -1718,7 +1719,8 @@ err_alloc:
/*
* Read the SCSI capacity synchronously (for probing).
*/
-static int ub_sync_read_cap(struct ub_dev *sc, struct ub_capacity *ret)
+static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
+ struct ub_capacity *ret)
{
struct ub_scsi_cmd *cmd;
char *p;
@@ -1743,6 +1745,7 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_capacity *ret)
cmd->state = UB_CMDST_INIT;
cmd->data = p;
cmd->len = 8;
+ cmd->lun = lun;
cmd->done = ub_probe_done;
cmd->back = &compl;
@@ -1812,6 +1815,90 @@ static void ub_probe_timeout(unsigned long arg)
}
/*
+ * Get number of LUNs by the way of Bulk GetMaxLUN command.
+ */
+static int ub_sync_getmaxlun(struct ub_dev *sc)
+{
+ int ifnum = sc->intf->cur_altsetting->desc.bInterfaceNumber;
+ unsigned char *p;
+ enum { ALLOC_SIZE = 1 };
+ struct usb_ctrlrequest *cr;
+ struct completion compl;
+ struct timer_list timer;
+ int nluns;
+ int rc;
+
+ init_completion(&compl);
+
+ rc = -ENOMEM;
+ if ((p = kmalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL)
+ goto err_alloc;
+ *p = 55;
+
+ cr = &sc->work_cr;
+ cr->bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+ cr->bRequest = US_BULK_GET_MAX_LUN;
+ cr->wValue = cpu_to_le16(0);
+ cr->wIndex = cpu_to_le16(ifnum);
+ cr->wLength = cpu_to_le16(1);
+
+ usb_fill_control_urb(&sc->work_urb, sc->dev, sc->recv_ctrl_pipe,
+ (unsigned char*) cr, p, 1, ub_probe_urb_complete, &compl);
+ sc->work_urb.transfer_flags = 0;
+ sc->work_urb.actual_length = 0;
+ sc->work_urb.error_count = 0;
+ sc->work_urb.status = 0;
+
+ if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
+ if (rc == -EPIPE) {
+ printk("%s: Stall at GetMaxLUN, using 1 LUN\n",
+ sc->name); /* P3 */
+ } else {
+ printk(KERN_WARNING
+ "%s: Unable to submit GetMaxLUN (%d)\n",
+ sc->name, rc);
+ }
+ goto err_submit;
+ }
+
+ init_timer(&timer);
+ timer.function = ub_probe_timeout;
+ timer.data = (unsigned long) &compl;
+ timer.expires = jiffies + UB_CTRL_TIMEOUT;
+ add_timer(&timer);
+
+ wait_for_completion(&compl);
+
+ del_timer_sync(&timer);
+ usb_kill_urb(&sc->work_urb);
+
+ if (sc->work_urb.actual_length != 1) {
+ printk("%s: GetMaxLUN returned %d bytes\n", sc->name,
+ sc->work_urb.actual_length); /* P3 */
+ nluns = 0;
+ } else {
+ if ((nluns = *p) == 55) {
+ nluns = 0;
+ } else {
+ /* GetMaxLUN returns the maximum LUN number */
+ nluns += 1;
+ if (nluns > UB_MAX_LUNS)
+ nluns = UB_MAX_LUNS;
+ }
+ printk("%s: GetMaxLUN returned %d, using %d LUNs\n", sc->name,
+ *p, nluns); /* P3 */
+ }
+
+ kfree(p);
+ return nluns;
+
+err_submit:
+ kfree(p);
+err_alloc:
+ return rc;
+}
+
+/*
* Clear initial stalls.
*/
static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe)
@@ -1897,8 +1984,8 @@ static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev,
}
if (ep_in == NULL || ep_out == NULL) {
- printk(KERN_NOTICE "%s: device %u failed endpoint check\n",
- sc->name, sc->dev->devnum);
+ printk(KERN_NOTICE "%s: failed endpoint check\n",
+ sc->name);
return -EIO;
}
@@ -1921,8 +2008,7 @@ static int ub_probe(struct usb_interface *intf,
const struct usb_device_id *dev_id)
{
struct ub_dev *sc;
- request_queue_t *q;
- struct gendisk *disk;
+ int nluns;
int rc;
int i;
@@ -1931,6 +2017,7 @@ static int ub_probe(struct usb_interface *intf,
goto err_core;
memset(sc, 0, sizeof(struct ub_dev));
spin_lock_init(&sc->lock);
+ INIT_LIST_HEAD(&sc->luns);
usb_init_urb(&sc->work_urb);
tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc);
atomic_set(&sc->poison, 0);
@@ -1942,19 +2029,16 @@ static int ub_probe(struct usb_interface *intf,
ub_init_completion(&sc->work_done);
sc->work_done.done = 1; /* A little yuk, but oh well... */
- rc = -ENOSR;
- if ((sc->id = ub_id_get()) == -1)
- goto err_id;
- snprintf(sc->name, 8, DRV_NAME "%c", sc->id + 'a');
-
sc->dev = interface_to_usbdev(intf);
sc->intf = intf;
// sc->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
-
usb_set_intfdata(intf, sc);
usb_get_dev(sc->dev);
// usb_get_intf(sc->intf); /* Do we need this? */
+ snprintf(sc->name, 12, DRV_NAME "(%d.%d)",
+ sc->dev->bus->busnum, sc->dev->devnum);
+
/* XXX Verify that we can handle the device (from descriptors) */
ub_get_pipes(sc, sc->dev, intf);
@@ -1992,35 +2076,88 @@ static int ub_probe(struct usb_interface *intf,
* In any case it's not our business how revaliadation is implemented.
*/
for (i = 0; i < 3; i++) { /* Retries for benh's key */
- if ((rc = ub_sync_tur(sc)) <= 0) break;
+ if ((rc = ub_sync_tur(sc, NULL)) <= 0) break;
if (rc != 0x6) break;
msleep(10);
}
- sc->removable = 1; /* XXX Query this from the device */
- sc->changed = 1; /* ub_revalidate clears only */
- sc->first_open = 1;
+ nluns = 1;
+ for (i = 0; i < 3; i++) {
+ if ((rc = ub_sync_getmaxlun(sc)) < 0) {
+ /*
+ * Some devices (i.e. Iomega Zip100) need this --
+ * apparently the bulk pipes get STALLed when the
+ * GetMaxLUN request is processed.
+ * XXX I have a ZIP-100, verify it does this.
+ */
+ if (rc == -EPIPE) {
+ ub_probe_clear_stall(sc, sc->recv_bulk_pipe);
+ ub_probe_clear_stall(sc, sc->send_bulk_pipe);
+ }
+ break;
+ }
+ if (rc != 0) {
+ nluns = rc;
+ break;
+ }
+ msleep(100);
+ }
- ub_revalidate(sc);
- /* This is pretty much a long term P3 */
- printk(KERN_INFO "%s: device %u capacity nsec %ld bsize %u\n",
- sc->name, sc->dev->devnum, sc->capacity.nsec, sc->capacity.bsize);
+ for (i = 0; i < nluns; i++) {
+ ub_probe_lun(sc, i);
+ }
+ return 0;
+
+ /* device_remove_file(&sc->intf->dev, &dev_attr_diag); */
+err_diag:
+ usb_set_intfdata(intf, NULL);
+ // usb_put_intf(sc->intf);
+ usb_put_dev(sc->dev);
+ kfree(sc);
+err_core:
+ return rc;
+}
+
+static int ub_probe_lun(struct ub_dev *sc, int lnum)
+{
+ struct ub_lun *lun;
+ request_queue_t *q;
+ struct gendisk *disk;
+ int rc;
+
+ rc = -ENOMEM;
+ if ((lun = kmalloc(sizeof(struct ub_lun), GFP_KERNEL)) == NULL)
+ goto err_alloc;
+ memset(lun, 0, sizeof(struct ub_lun));
+ lun->num = lnum;
+
+ rc = -ENOSR;
+ if ((lun->id = ub_id_get()) == -1)
+ goto err_id;
+
+ lun->udev = sc;
+ list_add(&lun->link, &sc->luns);
+
+ snprintf(lun->name, 16, DRV_NAME "%c(%d.%d.%d)",
+ lun->id + 'a', sc->dev->bus->busnum, sc->dev->devnum, lun->num);
+
+ lun->removable = 1; /* XXX Query this from the device */
+ lun->changed = 1; /* ub_revalidate clears only */
+ lun->first_open = 1;
+ ub_revalidate(sc, lun);
- /*
- * Just one disk per sc currently, but maybe more.
- */
rc = -ENOMEM;
if ((disk = alloc_disk(UB_MINORS_PER_MAJOR)) == NULL)
goto err_diskalloc;
- sc->disk = disk;
- sprintf(disk->disk_name, DRV_NAME "%c", sc->id + 'a');
- sprintf(disk->devfs_name, DEVFS_NAME "/%c", sc->id + 'a');
+ lun->disk = disk;
+ sprintf(disk->disk_name, DRV_NAME "%c", lun->id + 'a');
+ sprintf(disk->devfs_name, DEVFS_NAME "/%c", lun->id + 'a');
disk->major = UB_MAJOR;
- disk->first_minor = sc->id * UB_MINORS_PER_MAJOR;
+ disk->first_minor = lun->id * UB_MINORS_PER_MAJOR;
disk->fops = &ub_bd_fops;
- disk->private_data = sc;
- disk->driverfs_dev = &intf->dev;
+ disk->private_data = lun;
+ disk->driverfs_dev = &sc->intf->dev; /* XXX Many to one ok? */
rc = -ENOMEM;
if ((q = blk_init_queue(ub_bd_rq_fn, &sc->lock)) == NULL)
@@ -2028,28 +2165,17 @@ static int ub_probe(struct usb_interface *intf,
disk->queue = q;
- // blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask);
+ blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH);
blk_queue_max_hw_segments(q, UB_MAX_REQ_SG);
blk_queue_max_phys_segments(q, UB_MAX_REQ_SG);
- // blk_queue_segment_boundary(q, CARM_SG_BOUNDARY);
+ blk_queue_segment_boundary(q, 0xffffffff); /* Dubious. */
blk_queue_max_sectors(q, UB_MAX_SECTORS);
- blk_queue_hardsect_size(q, sc->capacity.bsize);
-
- /*
- * This is a serious infraction, caused by a deficiency in the
- * USB sg interface (usb_sg_wait()). We plan to remove this once
- * we get mileage on the driver and can justify a change to USB API.
- * See blk_queue_bounce_limit() to understand this part.
- *
- * XXX And I still need to be aware of the DMA mask in the HC.
- */
- q->bounce_pfn = blk_max_low_pfn;
- q->bounce_gfp = GFP_NOIO;
+ blk_queue_hardsect_size(q, lun->capacity.bsize);
- q->queuedata = sc;
+ q->queuedata = lun;
- set_capacity(disk, sc->capacity.nsec);
- if (sc->removable)
+ set_capacity(disk, lun->capacity.nsec);
+ if (lun->removable)
disk->flags |= GENHD_FL_REMOVABLE;
add_disk(disk);
@@ -2059,22 +2185,20 @@ static int ub_probe(struct usb_interface *intf,
err_blkqinit:
put_disk(disk);
err_diskalloc:
- device_remove_file(&sc->intf->dev, &dev_attr_diag);
-err_diag:
- usb_set_intfdata(intf, NULL);
- // usb_put_intf(sc->intf);
- usb_put_dev(sc->dev);
- ub_id_put(sc->id);
+ list_del(&lun->link);
+ ub_id_put(lun->id);
err_id:
- kfree(sc);
-err_core:
+ kfree(lun);
+err_alloc:
return rc;
}
static void ub_disconnect(struct usb_interface *intf)
{
struct ub_dev *sc = usb_get_intfdata(intf);
- struct gendisk *disk = sc->disk;
+ struct list_head *p;
+ struct ub_lun *lun;
+ struct gendisk *disk;
unsigned long flags;
/*
@@ -2124,14 +2248,18 @@ static void ub_disconnect(struct usb_interface *intf)
/*
* Unregister the upper layer.
*/
- if (disk->flags & GENHD_FL_UP)
- del_gendisk(disk);
- /*
- * I wish I could do:
- * set_bit(QUEUE_FLAG_DEAD, &q->queue_flags);
- * As it is, we rely on our internal poisoning and let
- * the upper levels to spin furiously failing all the I/O.
- */
+ list_for_each (p, &sc->luns) {
+ lun = list_entry(p, struct ub_lun, link);
+ disk = lun->disk;
+ if (disk->flags & GENHD_FL_UP)
+ del_gendisk(disk);
+ /*
+ * I wish I could do:
+ * set_bit(QUEUE_FLAG_DEAD, &q->queue_flags);
+ * As it is, we rely on our internal poisoning and let
+ * the upper levels to spin furiously failing all the I/O.
+ */
+ }
/*
* Taking a lock on a structure which is about to be freed
@@ -2182,8 +2310,8 @@ static int __init ub_init(void)
{
int rc;
- /* P3 */ printk("ub: sizeof ub_scsi_cmd %zu ub_dev %zu\n",
- sizeof(struct ub_scsi_cmd), sizeof(struct ub_dev));
+ /* P3 */ printk("ub: sizeof ub_scsi_cmd %zu ub_dev %zu ub_lun %zu\n",
+ sizeof(struct ub_scsi_cmd), sizeof(struct ub_dev), sizeof(struct ub_lun));
if ((rc = register_blkdev(UB_MAJOR, DRV_NAME)) != 0)
goto err_regblkdev;
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 9075bbb56ad..f766bc22c6b 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -576,7 +576,7 @@ static void __exit hci_uart_exit(void)
#endif
/* Release tty registration of line discipline */
- if ((err = tty_register_ldisc(N_HCI, NULL)))
+ if ((err = tty_unregister_ldisc(N_HCI)))
BT_ERR("Can't unregister HCI line discipline (%d)", err);
}
diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
index da80b14335a..01f03517332 100644
--- a/drivers/cdrom/cm206.c
+++ b/drivers/cdrom/cm206.c
@@ -307,7 +307,7 @@ static DEFINE_SPINLOCK(cm206_lock);
/* First, we define some polling functions. These are actually
only being used in the initialization. */
-void send_command_polled(int command)
+static void send_command_polled(int command)
{
int loop = POLLOOP;
while (!(inw(r_line_status) & ls_transmitter_buffer_empty)
@@ -318,7 +318,7 @@ void send_command_polled(int command)
outw(command, r_uart_transmit);
}
-uch receive_echo_polled(void)
+static uch receive_echo_polled(void)
{
int loop = POLLOOP;
while (!(inw(r_line_status) & ls_receive_buffer_full) && loop > 0) {
@@ -328,13 +328,13 @@ uch receive_echo_polled(void)
return ((uch) inw(r_uart_receive));
}
-uch send_receive_polled(int command)
+static uch send_receive_polled(int command)
{
send_command_polled(command);
return receive_echo_polled();
}
-inline void clear_ur(void)
+static inline void clear_ur(void)
{
if (cd->ur_r != cd->ur_w) {
debug(("Deleting bytes from fifo:"));
@@ -439,7 +439,7 @@ static irqreturn_t cm206_interrupt(int sig, void *dev_id, struct pt_regs *regs)
}
/* we have put the address of the wait queue in who */
-void cm206_timeout(unsigned long who)
+static void cm206_timeout(unsigned long who)
{
cd->timed_out = 1;
debug(("Timing out\n"));
@@ -448,7 +448,7 @@ void cm206_timeout(unsigned long who)
/* This function returns 1 if a timeout occurred, 0 if an interrupt
happened */
-int sleep_or_timeout(wait_queue_head_t * wait, int timeout)
+static int sleep_or_timeout(wait_queue_head_t * wait, int timeout)
{
cd->timed_out = 0;
init_timer(&cd->timer);
@@ -465,13 +465,7 @@ int sleep_or_timeout(wait_queue_head_t * wait, int timeout)
return 0;
}
-void cm206_delay(int nr_jiffies)
-{
- DECLARE_WAIT_QUEUE_HEAD(wait);
- sleep_or_timeout(&wait, nr_jiffies);
-}
-
-void send_command(int command)
+static void send_command(int command)
{
debug(("Sending 0x%x\n", command));
if (!(inw(r_line_status) & ls_transmitter_buffer_empty)) {
@@ -490,7 +484,7 @@ void send_command(int command)
outw(command, r_uart_transmit);
}
-uch receive_byte(int timeout)
+static uch receive_byte(int timeout)
{
uch ret;
cli();
@@ -521,23 +515,23 @@ uch receive_byte(int timeout)
return ret;
}
-inline uch receive_echo(void)
+static inline uch receive_echo(void)
{
return receive_byte(UART_TIMEOUT);
}
-inline uch send_receive(int command)
+static inline uch send_receive(int command)
{
send_command(command);
return receive_echo();
}
-inline uch wait_dsb(void)
+static inline uch wait_dsb(void)
{
return receive_byte(DSB_TIMEOUT);
}
-int type_0_command(int command, int expect_dsb)
+static int type_0_command(int command, int expect_dsb)
{
int e;
clear_ur();
@@ -552,7 +546,7 @@ int type_0_command(int command, int expect_dsb)
return 0;
}
-int type_1_command(int command, int bytes, uch * status)
+static int type_1_command(int command, int bytes, uch * status)
{ /* returns info */
int i;
if (type_0_command(command, 0))
@@ -564,7 +558,7 @@ int type_1_command(int command, int bytes, uch * status)
/* This function resets the adapter card. We'd better not do this too
* often, because it tends to generate `lost interrupts.' */
-void reset_cm260(void)
+static void reset_cm260(void)
{
outw(dc_normal | dc_initialize | READ_AHEAD, r_data_control);
udelay(10); /* 3.3 mu sec minimum */
@@ -572,7 +566,7 @@ void reset_cm260(void)
}
/* fsm: frame-sec-min from linear address; one of many */
-void fsm(int lba, uch * fsm)
+static void fsm(int lba, uch * fsm)
{
fsm[0] = lba % 75;
lba /= 75;
@@ -581,17 +575,17 @@ void fsm(int lba, uch * fsm)
fsm[2] = lba / 60;
}
-inline int fsm2lba(uch * fsm)
+static inline int fsm2lba(uch * fsm)
{
return fsm[0] + 75 * (fsm[1] - 2 + 60 * fsm[2]);
}
-inline int f_s_m2lba(uch f, uch s, uch m)
+static inline int f_s_m2lba(uch f, uch s, uch m)
{
return f + 75 * (s - 2 + 60 * m);
}
-int start_read(int start)
+static int start_read(int start)
{
uch read_sector[4] = { c_read_data, };
int i, e;
@@ -613,7 +607,7 @@ int start_read(int start)
return 0;
}
-int stop_read(void)
+static int stop_read(void)
{
int e;
type_0_command(c_stop, 0);
@@ -630,7 +624,7 @@ int stop_read(void)
routine takes care of this. Set a flag `background' in the cd
struct to indicate the process. */
-int read_background(int start, int reading)
+static int read_background(int start, int reading)
{
if (cd->background)
return -1; /* can't do twice */
@@ -658,7 +652,7 @@ void transport_data(int port, ush * dest, int count)
#define MAX_TRIES 100
-int read_sector(int start)
+static int read_sector(int start)
{
int tries = 0;
if (cd->background) {
@@ -753,7 +747,7 @@ static DECLARE_TASKLET(cm206_tasklet, cm206_tasklet_func, 0);
/* This command clears the dsb_possible_media_change flag, so we must
* retain it.
*/
-void get_drive_status(void)
+static void get_drive_status(void)
{
uch status[2];
type_1_command(c_drive_status, 2, status); /* this might be done faster */
@@ -764,7 +758,7 @@ void get_drive_status(void)
dsb_drive_not_ready | dsb_tray_not_closed));
}
-void get_disc_status(void)
+static void get_disc_status(void)
{
if (type_1_command(c_disc_status, 7, cd->disc_status)) {
debug(("get_disc_status: error\n"));
@@ -801,7 +795,7 @@ static void cm206_release(struct cdrom_device_info *cdi)
/* Empty buffer empties $sectors$ sectors of the adapter card buffer,
* and then reads a sector in kernel memory. */
-void empty_buffer(int sectors)
+static void empty_buffer(int sectors)
{
while (sectors >= 0) {
transport_data(r_fifo_output_buffer,
@@ -819,7 +813,7 @@ void empty_buffer(int sectors)
/* try_adapter. This function determines if the requested sector is
in adapter memory, or will appear there soon. Returns 0 upon
success */
-int try_adapter(int sector)
+static int try_adapter(int sector)
{
if (cd->adapter_first <= sector && sector < cd->adapter_last) {
/* sector is in adapter memory */
@@ -910,7 +904,7 @@ static void do_cm206_request(request_queue_t * q)
*/
/* seek seeks to address lba. It does wait to arrive there. */
-void seek(int lba)
+static void seek(int lba)
{
int i;
uch seek_command[4] = { c_seek, };
@@ -926,7 +920,7 @@ uch bcdbin(unsigned char bcd)
return (bcd >> 4) * 10 + (bcd & 0xf);
}
-inline uch normalize_track(uch track)
+static inline uch normalize_track(uch track)
{
if (track < 1)
return 1;
@@ -939,7 +933,7 @@ inline uch normalize_track(uch track)
* tracks seen in the process. Input $track$ must be between 1 and
* #-of-tracks+1. Note that the start of the disc must be in toc[1].fsm.
*/
-int get_toc_lba(uch track)
+static int get_toc_lba(uch track)
{
int max = 74 * 60 * 75 - 150, min = fsm2lba(cd->toc[1].fsm);
int i, lba, l, old_lba = 0;
@@ -991,7 +985,7 @@ int get_toc_lba(uch track)
return lba;
}
-void update_toc_entry(uch track)
+static void update_toc_entry(uch track)
{
track = normalize_track(track);
if (!cd->toc[track].track)
@@ -999,7 +993,7 @@ void update_toc_entry(uch track)
}
/* return 0 upon success */
-int read_toc_header(struct cdrom_tochdr *hp)
+static int read_toc_header(struct cdrom_tochdr *hp)
{
if (!FIRST_TRACK)
get_disc_status();
@@ -1016,7 +1010,7 @@ int read_toc_header(struct cdrom_tochdr *hp)
return -1;
}
-void play_from_to_msf(struct cdrom_msf *msfp)
+static void play_from_to_msf(struct cdrom_msf *msfp)
{
uch play_command[] = { c_play,
msfp->cdmsf_frame0, msfp->cdmsf_sec0, msfp->cdmsf_min0,
@@ -1032,7 +1026,7 @@ void play_from_to_msf(struct cdrom_msf *msfp)
cd->dsb = wait_dsb();
}
-void play_from_to_track(int from, int to)
+static void play_from_to_track(int from, int to)
{
uch play_command[8] = { c_play, };
int i;
@@ -1059,7 +1053,7 @@ void play_from_to_track(int from, int to)
cd->dsb = wait_dsb();
}
-int get_current_q(struct cdrom_subchnl *qp)
+static int get_current_q(struct cdrom_subchnl *qp)
{
int i;
uch *q = cd->q;
@@ -1093,14 +1087,14 @@ int get_current_q(struct cdrom_subchnl *qp)
return 0;
}
-void invalidate_toc(void)
+static void invalidate_toc(void)
{
memset(cd->toc, 0, sizeof(cd->toc));
memset(cd->disc_status, 0, sizeof(cd->disc_status));
}
/* cdrom.c guarantees that cdte_format == CDROM_MSF */
-void get_toc_entry(struct cdrom_tocentry *ep)
+static void get_toc_entry(struct cdrom_tocentry *ep)
{
uch track = normalize_track(ep->cdte_track);
update_toc_entry(track);
@@ -1117,8 +1111,8 @@ void get_toc_entry(struct cdrom_tocentry *ep)
* upon success. Memory checking has been done by cdrom_ioctl(), the
* calling function, as well as LBA/MSF sanitization.
*/
-int cm206_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
- void *arg)
+static int cm206_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
+ void *arg)
{
switch (cmd) {
case CDROMREADTOCHDR:
@@ -1189,7 +1183,7 @@ static int cm206_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
}
}
-int cm206_media_changed(struct cdrom_device_info *cdi, int disc_nr)
+static int cm206_media_changed(struct cdrom_device_info *cdi, int disc_nr)
{
if (cd != NULL) {
int r;
@@ -1204,16 +1198,9 @@ int cm206_media_changed(struct cdrom_device_info *cdi, int disc_nr)
/* The new generic cdrom support. Routines should be concise, most of
the logic should be in cdrom.c */
-/* returns number of times device is in use */
-int cm206_open_files(struct cdrom_device_info *cdi)
-{
- if (cd)
- return cd->openfiles;
- return -1;
-}
/* controls tray movement */
-int cm206_tray_move(struct cdrom_device_info *cdi, int position)
+static int cm206_tray_move(struct cdrom_device_info *cdi, int position)
{
if (position) { /* 1: eject */
type_0_command(c_open_tray, 1);
@@ -1224,7 +1211,7 @@ int cm206_tray_move(struct cdrom_device_info *cdi, int position)
}
/* gives current state of the drive */
-int cm206_drive_status(struct cdrom_device_info *cdi, int slot_nr)
+static int cm206_drive_status(struct cdrom_device_info *cdi, int slot_nr)
{
get_drive_status();
if (cd->dsb & dsb_tray_not_closed)
@@ -1237,7 +1224,7 @@ int cm206_drive_status(struct cdrom_device_info *cdi, int slot_nr)
}
/* locks or unlocks door lock==1: lock; return 0 upon success */
-int cm206_lock_door(struct cdrom_device_info *cdi, int lock)
+static int cm206_lock_door(struct cdrom_device_info *cdi, int lock)
{
uch command = (lock) ? c_lock_tray : c_unlock_tray;
type_0_command(command, 1); /* wait and get dsb */
@@ -1248,8 +1235,8 @@ int cm206_lock_door(struct cdrom_device_info *cdi, int lock)
/* Although a session start should be in LBA format, we return it in
MSF format because it is slightly easier, and the new generic ioctl
will take care of the necessary conversion. */
-int cm206_get_last_session(struct cdrom_device_info *cdi,
- struct cdrom_multisession *mssp)
+static int cm206_get_last_session(struct cdrom_device_info *cdi,
+ struct cdrom_multisession *mssp)
{
if (!FIRST_TRACK)
get_disc_status();
@@ -1268,7 +1255,7 @@ int cm206_get_last_session(struct cdrom_device_info *cdi,
return 0;
}
-int cm206_get_upc(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
+static int cm206_get_upc(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
{
uch upc[10];
char *ret = mcn->medium_catalog_number;
@@ -1287,7 +1274,7 @@ int cm206_get_upc(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
return 0;
}
-int cm206_reset(struct cdrom_device_info *cdi)
+static int cm206_reset(struct cdrom_device_info *cdi)
{
stop_read();
reset_cm260();
@@ -1300,7 +1287,7 @@ int cm206_reset(struct cdrom_device_info *cdi)
return 0;
}
-int cm206_select_speed(struct cdrom_device_info *cdi, int speed)
+static int cm206_select_speed(struct cdrom_device_info *cdi, int speed)
{
int r;
switch (speed) {
@@ -1392,7 +1379,7 @@ static struct gendisk *cm206_gendisk;
request_region, 15 bits of one port and 6 of another make things
likely enough to accept the region on the first hit...
*/
-int __init probe_base_port(int base)
+static int __init probe_base_port(int base)
{
int b = 0x300, e = 0x370; /* this is the range of start addresses */
volatile int fool, i;
@@ -1416,7 +1403,7 @@ int __init probe_base_port(int base)
#if !defined(MODULE) || defined(AUTO_PROBE_MODULE)
/* Probe for irq# nr. If nr==0, probe for all possible irq's. */
-int __init probe_irq(int nr)
+static int __init probe_irq(int nr)
{
int irqs, irq;
outw(dc_normal | READ_AHEAD, r_data_control); /* disable irq-generation */
@@ -1558,7 +1545,7 @@ static void __init parse_options(void)
}
}
-int __cm206_init(void)
+static int __cm206_init(void)
{
parse_options();
#if !defined(AUTO_PROBE_MODULE)
@@ -1567,7 +1554,7 @@ int __cm206_init(void)
return cm206_init();
}
-void __exit cm206_exit(void)
+static void __exit cm206_exit(void)
{
del_gendisk(cm206_gendisk);
put_disk(cm206_gendisk);
diff --git a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c
index f4be7bfd667..9f22e8f1f6c 100644
--- a/drivers/cdrom/sonycd535.c
+++ b/drivers/cdrom/sonycd535.c
@@ -1605,8 +1605,7 @@ out7:
put_disk(cdu_disk);
out6:
for (i = 0; i < sony_buffer_sectors; i++)
- if (sony_buffer[i])
- kfree(sony_buffer[i]);
+ kfree(sony_buffer[i]);
out5:
kfree(sony_buffer);
out4:
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index fcca26c89bb..38dd9ffbe8b 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -488,6 +488,20 @@ static int viocd_packet(struct cdrom_device_info *cdi,
& (CDC_DVD_RAM | CDC_RAM)) != 0;
}
break;
+ case GPCMD_GET_CONFIGURATION:
+ if (cgc->cmd[3] == CDF_RWRT) {
+ struct rwrt_feature_desc *rfd = (struct rwrt_feature_desc *)(cgc->buffer + sizeof(struct feature_header));
+
+ if ((buflen >=
+ (sizeof(struct feature_header) + sizeof(*rfd))) &&
+ (cdi->ops->capability & ~cdi->mask
+ & (CDC_DVD_RAM | CDC_RAM))) {
+ rfd->feature_code = cpu_to_be16(CDF_RWRT);
+ rfd->curr = 1;
+ ret = 0;
+ }
+ }
+ break;
default:
if (cgc->sense) {
/* indicate Unknown code */
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 5ed6515ae01..43d0cb19ef6 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -929,6 +929,10 @@ config SCx200_GPIO
If compiled as a module, it will be called scx200_gpio.
+config GPIO_VR41XX
+ tristate "NEC VR4100 series General-purpose I/O Unit support"
+ depends on CPU_VR41XX
+
config RAW_DRIVER
tristate "RAW driver (/dev/raw/rawN) (OBSOLETE)"
help
@@ -936,8 +940,8 @@ config RAW_DRIVER
Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O.
See the raw(8) manpage for more details.
- The raw driver is deprecated and may be removed from 2.7
- kernels. Applications should simply open the device (eg /dev/hda1)
+ The raw driver is deprecated and will be removed soon.
+ Applications should simply open the device (eg /dev/hda1)
with the O_DIRECT flag.
config HPET
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index e3f5c32aac5..1aff819f383 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -80,6 +80,7 @@ obj-$(CONFIG_PPDEV) += ppdev.o
obj-$(CONFIG_NWBUTTON) += nwbutton.o
obj-$(CONFIG_NWFLASH) += nwflash.o
obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
+obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
obj-$(CONFIG_TANBAC_TB0219) += tb0219.o
obj-$(CONFIG_WATCHDOG) += watchdog/
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index ad9c11391d8..c1fe013c64f 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -278,6 +278,8 @@ void agp3_generic_cleanup(void);
#define AGP_GENERIC_SIZES_ENTRIES 11
extern struct aper_size_info_16 agp3_generic_sizes[];
+#define virt_to_gart(x) (phys_to_gart(virt_to_phys(x)))
+#define gart_to_virt(x) (phys_to_virt(gart_to_phys(x)))
extern int agp_off;
extern int agp_try_unsupported_boot;
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
index 0212febda65..9c9c9c2247c 100644
--- a/drivers/char/agp/ali-agp.c
+++ b/drivers/char/agp/ali-agp.c
@@ -150,7 +150,7 @@ static void *m1541_alloc_page(struct agp_bridge_data *bridge)
pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
(((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
- virt_to_phys(addr)) | ALI_CACHE_FLUSH_EN ));
+ virt_to_gart(addr)) | ALI_CACHE_FLUSH_EN ));
return addr;
}
@@ -174,7 +174,7 @@ static void m1541_destroy_page(void * addr)
pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
(((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
- virt_to_phys(addr)) | ALI_CACHE_FLUSH_EN));
+ virt_to_gart(addr)) | ALI_CACHE_FLUSH_EN));
agp_generic_destroy_page(addr);
}
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
index e62a3c2c44a..3a41672e4d6 100644
--- a/drivers/char/agp/amd-k7-agp.c
+++ b/drivers/char/agp/amd-k7-agp.c
@@ -43,7 +43,7 @@ static int amd_create_page_map(struct amd_page_map *page_map)
SetPageReserved(virt_to_page(page_map->real));
global_cache_flush();
- page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real),
+ page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real),
PAGE_SIZE);
if (page_map->remapped == NULL) {
ClearPageReserved(virt_to_page(page_map->real));
@@ -154,7 +154,7 @@ static int amd_create_gatt_table(struct agp_bridge_data *bridge)
agp_bridge->gatt_table_real = (u32 *)page_dir.real;
agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped;
- agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
+ agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real);
/* Get the address for the gart region.
* This is a bus address even on the alpha, b/c its
@@ -167,7 +167,7 @@ static int amd_create_gatt_table(struct agp_bridge_data *bridge)
/* Calculate the agp offset */
for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
- writel(virt_to_phys(amd_irongate_private.gatt_pages[i]->real) | 1,
+ writel(virt_to_gart(amd_irongate_private.gatt_pages[i]->real) | 1,
page_dir.remapped+GET_PAGE_DIR_OFF(addr));
readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr)); /* PCI Posting. */
}
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 399c042f68f..1407945a589 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -219,7 +219,7 @@ static struct aper_size_info_32 amd_8151_sizes[7] =
static int amd_8151_configure(void)
{
- unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real);
+ unsigned long gatt_bus = virt_to_gart(agp_bridge->gatt_table_real);
/* Configure AGP regs in each x86-64 host bridge. */
for_each_nb() {
@@ -591,7 +591,7 @@ static void __devexit agp_amd64_remove(struct pci_dev *pdev)
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
- release_mem_region(virt_to_phys(bridge->gatt_table_real),
+ release_mem_region(virt_to_gart(bridge->gatt_table_real),
amd64_aperture_sizes[bridge->aperture_size_idx].size);
agp_remove_bridge(bridge);
agp_put_bridge(bridge);
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index a65f8827c28..e572ced9100 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -61,7 +61,7 @@ static int ati_create_page_map(ati_page_map *page_map)
SetPageReserved(virt_to_page(page_map->real));
err = map_page_into_agp(virt_to_page(page_map->real));
- page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real),
+ page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real),
PAGE_SIZE);
if (page_map->remapped == NULL || err) {
ClearPageReserved(virt_to_page(page_map->real));
@@ -343,7 +343,7 @@ static int ati_create_gatt_table(struct agp_bridge_data *bridge)
agp_bridge->gatt_table_real = (u32 *)page_dir.real;
agp_bridge->gatt_table = (u32 __iomem *) page_dir.remapped;
- agp_bridge->gatt_bus_addr = virt_to_bus(page_dir.real);
+ agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real);
/* Write out the size register */
current_size = A_SIZE_LVL2(agp_bridge->current_size);
@@ -373,7 +373,7 @@ static int ati_create_gatt_table(struct agp_bridge_data *bridge)
/* Calculate the agp offset */
for(i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
- writel(virt_to_bus(ati_generic_private.gatt_pages[i]->real) | 1,
+ writel(virt_to_gart(ati_generic_private.gatt_pages[i]->real) | 1,
page_dir.remapped+GET_PAGE_DIR_OFF(addr));
readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr)); /* PCI Posting. */
}
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
index 2f3dfb63bdc..4d4e602fdc7 100644
--- a/drivers/char/agp/backend.c
+++ b/drivers/char/agp/backend.c
@@ -148,7 +148,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
return -ENOMEM;
}
- bridge->scratch_page_real = virt_to_phys(addr);
+ bridge->scratch_page_real = virt_to_gart(addr);
bridge->scratch_page =
bridge->driver->mask_memory(bridge, bridge->scratch_page_real, 0);
}
@@ -189,7 +189,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
err_out:
if (bridge->driver->needs_scratch_page)
bridge->driver->agp_destroy_page(
- phys_to_virt(bridge->scratch_page_real));
+ gart_to_virt(bridge->scratch_page_real));
if (got_gatt)
bridge->driver->free_gatt_table(bridge);
if (got_keylist) {
@@ -214,7 +214,7 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge)
if (bridge->driver->agp_destroy_page &&
bridge->driver->needs_scratch_page)
bridge->driver->agp_destroy_page(
- phys_to_virt(bridge->scratch_page_real));
+ gart_to_virt(bridge->scratch_page_real));
}
/* When we remove the global variable agp_bridge from all drivers
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c
index 1383c3165ea..ac19fdcd21c 100644
--- a/drivers/char/agp/efficeon-agp.c
+++ b/drivers/char/agp/efficeon-agp.c
@@ -219,7 +219,7 @@ static int efficeon_create_gatt_table(struct agp_bridge_data *bridge)
efficeon_private.l1_table[index] = page;
- value = __pa(page) | pati | present | index;
+ value = virt_to_gart(page) | pati | present | index;
pci_write_config_dword(agp_bridge->dev,
EFFICEON_ATTPAGE, value);
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index c321a924e38..f0079e991bd 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -153,7 +153,7 @@ void agp_free_memory(struct agp_memory *curr)
}
if (curr->page_count != 0) {
for (i = 0; i < curr->page_count; i++) {
- curr->bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[i]));
+ curr->bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[i]));
}
}
agp_free_key(curr->key);
@@ -209,7 +209,7 @@ struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge,
agp_free_memory(new);
return NULL;
}
- new->memory[i] = virt_to_phys(addr);
+ new->memory[i] = virt_to_gart(addr);
new->page_count++;
}
new->bridge = bridge;
@@ -295,19 +295,6 @@ int agp_num_entries(void)
EXPORT_SYMBOL_GPL(agp_num_entries);
-static int check_bridge_mode(struct pci_dev *dev)
-{
- u32 agp3;
- u8 cap_ptr;
-
- cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP);
- pci_read_config_dword(dev, cap_ptr+AGPSTAT, &agp3);
- if (agp3 & AGPSTAT_MODE_3_0)
- return 1;
- return 0;
-}
-
-
/**
* agp_copy_info - copy bridge state information
*
@@ -328,7 +315,7 @@ int agp_copy_info(struct agp_bridge_data *bridge, struct agp_kern_info *info)
info->version.minor = bridge->version->minor;
info->chipset = SUPPORTED;
info->device = bridge->dev;
- if (check_bridge_mode(bridge->dev))
+ if (bridge->mode & AGPSTAT_MODE_3_0)
info->mode = bridge->mode & ~AGP3_RESERVED_MASK;
else
info->mode = bridge->mode & ~AGP2_RESERVED_MASK;
@@ -661,7 +648,7 @@ u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 requested_mode
bridge_agpstat &= ~AGPSTAT_FW;
/* Check to see if we are operating in 3.0 mode */
- if (check_bridge_mode(agp_bridge->dev))
+ if (agp_bridge->mode & AGPSTAT_MODE_3_0)
agp_v3_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat);
else
agp_v2_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat);
@@ -732,7 +719,7 @@ void agp_generic_enable(struct agp_bridge_data *bridge, u32 requested_mode)
/* Do AGP version specific frobbing. */
if (bridge->major_version >= 3) {
- if (check_bridge_mode(bridge->dev)) {
+ if (bridge->mode & AGPSTAT_MODE_3_0) {
/* If we have 3.5, we can do the isoch stuff. */
if (bridge->minor_version >= 5)
agp_3_5_enable(bridge);
@@ -806,8 +793,7 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
break;
}
- table = (char *) __get_free_pages(GFP_KERNEL,
- page_order);
+ table = alloc_gatt_pages(page_order);
if (table == NULL) {
i++;
@@ -838,7 +824,7 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
size = ((struct aper_size_info_fixed *) temp)->size;
page_order = ((struct aper_size_info_fixed *) temp)->page_order;
num_entries = ((struct aper_size_info_fixed *) temp)->num_entries;
- table = (char *) __get_free_pages(GFP_KERNEL, page_order);
+ table = alloc_gatt_pages(page_order);
}
if (table == NULL)
@@ -853,7 +839,7 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
agp_gatt_table = (void *)table;
bridge->driver->cache_flush();
- bridge->gatt_table = ioremap_nocache(virt_to_phys(table),
+ bridge->gatt_table = ioremap_nocache(virt_to_gart(table),
(PAGE_SIZE * (1 << page_order)));
bridge->driver->cache_flush();
@@ -861,11 +847,11 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
ClearPageReserved(page);
- free_pages((unsigned long) table, page_order);
+ free_gatt_pages(table, page_order);
return -ENOMEM;
}
- bridge->gatt_bus_addr = virt_to_phys(bridge->gatt_table_real);
+ bridge->gatt_bus_addr = virt_to_gart(bridge->gatt_table_real);
/* AK: bogus, should encode addresses > 4GB */
for (i = 0; i < num_entries; i++) {
@@ -919,7 +905,7 @@ int agp_generic_free_gatt_table(struct agp_bridge_data *bridge)
for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
ClearPageReserved(page);
- free_pages((unsigned long) bridge->gatt_table_real, page_order);
+ free_gatt_pages(bridge->gatt_table_real, page_order);
agp_gatt_table = NULL;
bridge->gatt_table = NULL;
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
index 6052bfa04c7..99762b6c19a 100644
--- a/drivers/char/agp/hp-agp.c
+++ b/drivers/char/agp/hp-agp.c
@@ -110,7 +110,7 @@ static int __init hp_zx1_ioc_shared(void)
hp->gart_size = HP_ZX1_GART_SIZE;
hp->gatt_entries = hp->gart_size / hp->io_page_size;
- hp->io_pdir = phys_to_virt(readq(hp->ioc_regs+HP_ZX1_PDIR_BASE));
+ hp->io_pdir = gart_to_virt(readq(hp->ioc_regs+HP_ZX1_PDIR_BASE));
hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)];
if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) {
@@ -248,7 +248,7 @@ hp_zx1_configure (void)
agp_bridge->mode = readl(hp->lba_regs+hp->lba_cap_offset+PCI_AGP_STATUS);
if (hp->io_pdir_owner) {
- writel(virt_to_phys(hp->io_pdir), hp->ioc_regs+HP_ZX1_PDIR_BASE);
+ writel(virt_to_gart(hp->io_pdir), hp->ioc_regs+HP_ZX1_PDIR_BASE);
readl(hp->ioc_regs+HP_ZX1_PDIR_BASE);
writel(hp->io_tlb_ps, hp->ioc_regs+HP_ZX1_TCNFG);
readl(hp->ioc_regs+HP_ZX1_TCNFG);
diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c
index adbea896c0d..94943298c03 100644
--- a/drivers/char/agp/i460-agp.c
+++ b/drivers/char/agp/i460-agp.c
@@ -372,7 +372,7 @@ static int i460_alloc_large_page (struct lp_desc *lp)
}
memset(lp->alloced_map, 0, map_size);
- lp->paddr = virt_to_phys(lpage);
+ lp->paddr = virt_to_gart(lpage);
lp->refcount = 0;
atomic_add(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp);
return 0;
@@ -383,7 +383,7 @@ static void i460_free_large_page (struct lp_desc *lp)
kfree(lp->alloced_map);
lp->alloced_map = NULL;
- free_pages((unsigned long) phys_to_virt(lp->paddr), I460_IO_PAGE_SHIFT - PAGE_SHIFT);
+ free_pages((unsigned long) gart_to_virt(lp->paddr), I460_IO_PAGE_SHIFT - PAGE_SHIFT);
atomic_sub(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp);
}
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 8c7d727432b..51266d6b4d7 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -286,7 +286,7 @@ static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type)
if (new == NULL)
return NULL;
- new->memory[0] = virt_to_phys(addr);
+ new->memory[0] = virt_to_gart(addr);
if (pg_count == 4) {
/* kludge to get 4 physical pages for ARGB cursor */
new->memory[1] = new->memory[0] + PAGE_SIZE;
@@ -329,10 +329,10 @@ static void intel_i810_free_by_type(struct agp_memory *curr)
agp_free_key(curr->key);
if(curr->type == AGP_PHYS_MEMORY) {
if (curr->page_count == 4)
- i8xx_destroy_pages(phys_to_virt(curr->memory[0]));
+ i8xx_destroy_pages(gart_to_virt(curr->memory[0]));
else
agp_bridge->driver->agp_destroy_page(
- phys_to_virt(curr->memory[0]));
+ gart_to_virt(curr->memory[0]));
vfree(curr->memory);
}
kfree(curr);
@@ -418,7 +418,8 @@ static void intel_i830_init_gtt_entries(void)
case I915_GMCH_GMS_STOLEN_48M:
/* Check it's really I915G */
if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB)
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB)
gtt_entries = MB(48) - KB(size);
else
gtt_entries = 0;
@@ -426,7 +427,8 @@ static void intel_i830_init_gtt_entries(void)
case I915_GMCH_GMS_STOLEN_64M:
/* Check it's really I915G */
if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB)
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB)
gtt_entries = MB(64) - KB(size);
else
gtt_entries = 0;
@@ -1662,6 +1664,14 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
}
name = "915GM";
break;
+ case PCI_DEVICE_ID_INTEL_82945G_HB:
+ if (find_i830(PCI_DEVICE_ID_INTEL_82945G_IG)) {
+ bridge->driver = &intel_915_driver;
+ } else {
+ bridge->driver = &intel_845_driver;
+ }
+ name = "945G";
+ break;
case PCI_DEVICE_ID_INTEL_7505_0:
bridge->driver = &intel_7505_driver;
name = "E7505";
@@ -1801,6 +1811,7 @@ static struct pci_device_id agp_intel_pci_table[] = {
ID(PCI_DEVICE_ID_INTEL_7205_0),
ID(PCI_DEVICE_ID_INTEL_82915G_HB),
ID(PCI_DEVICE_ID_INTEL_82915GM_HB),
+ ID(PCI_DEVICE_ID_INTEL_82945G_HB),
{ }
};
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c
index 4b3eda26797..d3aa159c9de 100644
--- a/drivers/char/agp/sgi-agp.c
+++ b/drivers/char/agp/sgi-agp.c
@@ -133,11 +133,14 @@ static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start,
off_t j;
void *temp;
struct agp_bridge_data *bridge;
+ u64 *table;
bridge = mem->bridge;
if (!bridge)
return -EINVAL;
+ table = (u64 *)bridge->gatt_table;
+
temp = bridge->current_size;
switch (bridge->driver->size_type) {
@@ -175,7 +178,7 @@ static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start,
j = pg_start;
while (j < (pg_start + mem->page_count)) {
- if (*(bridge->gatt_table + j))
+ if (table[j])
return -EBUSY;
j++;
}
@@ -186,7 +189,7 @@ static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start,
}
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
- *(bridge->gatt_table + j) =
+ table[j] =
bridge->driver->mask_memory(bridge, mem->memory[i],
mem->type);
}
@@ -200,6 +203,7 @@ static int sgi_tioca_remove_memory(struct agp_memory *mem, off_t pg_start,
{
size_t i;
struct agp_bridge_data *bridge;
+ u64 *table;
bridge = mem->bridge;
if (!bridge)
@@ -209,8 +213,10 @@ static int sgi_tioca_remove_memory(struct agp_memory *mem, off_t pg_start,
return -EINVAL;
}
+ table = (u64 *)bridge->gatt_table;
+
for (i = pg_start; i < (mem->page_count + pg_start); i++) {
- *(bridge->gatt_table + i) = 0;
+ table[i] = 0;
}
bridge->driver->tlb_flush(mem);
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
index 10c23302dd8..a9fb12c20eb 100644
--- a/drivers/char/agp/sworks-agp.c
+++ b/drivers/char/agp/sworks-agp.c
@@ -51,7 +51,7 @@ static int serverworks_create_page_map(struct serverworks_page_map *page_map)
}
SetPageReserved(virt_to_page(page_map->real));
global_cache_flush();
- page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real),
+ page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real),
PAGE_SIZE);
if (page_map->remapped == NULL) {
ClearPageReserved(virt_to_page(page_map->real));
@@ -162,7 +162,7 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge)
/* Create a fake scratch directory */
for(i = 0; i < 1024; i++) {
writel(agp_bridge->scratch_page, serverworks_private.scratch_dir.remapped+i);
- writel(virt_to_phys(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i);
+ writel(virt_to_gart(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i);
}
retval = serverworks_create_gatt_pages(value->num_entries / 1024);
@@ -174,7 +174,7 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge)
agp_bridge->gatt_table_real = (u32 *)page_dir.real;
agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped;
- agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
+ agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real);
/* Get the address for the gart region.
* This is a bus address even on the alpha, b/c its
@@ -187,7 +187,7 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge)
/* Calculate the agp offset */
for(i = 0; i < value->num_entries / 1024; i++)
- writel(virt_to_phys(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i);
+ writel(virt_to_gart(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i);
return 0;
}
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c
index a673971f2a9..c8255312b8c 100644
--- a/drivers/char/agp/uninorth-agp.c
+++ b/drivers/char/agp/uninorth-agp.c
@@ -407,7 +407,7 @@ static int uninorth_create_gatt_table(struct agp_bridge_data *bridge)
bridge->gatt_table_real = (u32 *) table;
bridge->gatt_table = (u32 *)table;
- bridge->gatt_bus_addr = virt_to_phys(table);
+ bridge->gatt_bus_addr = virt_to_gart(table);
for (i = 0; i < num_entries; i++)
bridge->gatt_table[i] = 0;
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 1dc4259213a..2a36561eec6 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -861,13 +861,18 @@ static void change_speed(struct async_struct *info,
static void rs_put_char(struct tty_struct *tty, unsigned char ch)
{
- struct async_struct *info = (struct async_struct *)tty->driver_data;
+ struct async_struct *info;
unsigned long flags;
+ if (!tty)
+ return;
+
+ info = tty->driver_data;
+
if (serial_paranoia_check(info, tty->name, "rs_put_char"))
return;
- if (!tty || !info->xmit.buf)
+ if (!info->xmit.buf)
return;
local_irq_save(flags);
@@ -910,13 +915,18 @@ static void rs_flush_chars(struct tty_struct *tty)
static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count)
{
int c, ret = 0;
- struct async_struct *info = (struct async_struct *)tty->driver_data;
+ struct async_struct *info;
unsigned long flags;
+ if (!tty)
+ return 0;
+
+ info = tty->driver_data;
+
if (serial_paranoia_check(info, tty->name, "rs_write"))
return 0;
- if (!tty || !info->xmit.buf || !tmp_buf)
+ if (!info->xmit.buf || !tmp_buf)
return 0;
local_save_flags(flags);
@@ -1963,10 +1973,6 @@ static _INLINE_ void show_serial_version(void)
}
-int register_serial(struct serial_struct *req);
-void unregister_serial(int line);
-
-
static struct tty_operations serial_ops = {
.open = rs_open,
.close = rs_close,
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index 6bf2e27dc23..11f9ee58112 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -599,7 +599,7 @@ static ssize_t ac_read (struct file *filp, char __user *buf, size_t count, loff_
#ifdef DEBUG
if (loopcount++ > 2) {
- printk("Looping in ac_read. loopcount %d\n", loopcount);
+ printk(KERN_DEBUG "Looping in ac_read. loopcount %d\n", loopcount);
}
#endif
}
diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig
index d9a02993467..c2b12eab67c 100644
--- a/drivers/char/drm/Kconfig
+++ b/drivers/char/drm/Kconfig
@@ -6,7 +6,7 @@
#
config DRM
tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
- depends on AGP || AGP=n
+ depends on (AGP || AGP=n) && PCI
help
Kernel-level support for the Direct Rendering Infrastructure (DRI)
introduced in XFree86 4.0. If you say Y here, you need to select
diff --git a/drivers/char/drm/Makefile b/drivers/char/drm/Makefile
index 23ab26321e9..7444dec40b9 100644
--- a/drivers/char/drm/Makefile
+++ b/drivers/char/drm/Makefile
@@ -19,6 +19,11 @@ radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o
ffb-objs := ffb_drv.o ffb_context.o
sis-objs := sis_drv.o sis_ds.o sis_mm.o
+ifeq ($(CONFIG_COMPAT),y)
+drm-objs += drm_ioc32.o
+radeon-objs += radeon_ioc32.o
+endif
+
obj-$(CONFIG_DRM) += drm.o
obj-$(CONFIG_DRM_GAMMA) += gamma.o
obj-$(CONFIG_DRM_TDFX) += tdfx.o
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 21f4c54e1a8..b04ddf12a0f 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -316,6 +316,9 @@ do { \
typedef int drm_ioctl_t( struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg );
+typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,
+ unsigned long arg);
+
typedef struct drm_ioctl_desc {
drm_ioctl_t *func;
int auth_needed;
@@ -775,6 +778,8 @@ extern int drm_version(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int drm_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
+extern long drm_compat_ioctl(struct file *filp,
+ unsigned int cmd, unsigned long arg);
extern int drm_takedown(drm_device_t * dev);
/* Device support (drm_fops.h) */
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
index 4113bcba67f..3407380b865 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -60,6 +60,15 @@ int drm_order( unsigned long size )
}
EXPORT_SYMBOL(drm_order);
+#ifdef CONFIG_COMPAT
+/*
+ * Used to allocate 32-bit handles for _DRM_SHM regions
+ * The 0x10000000 value is chosen to be out of the way of
+ * FB/register and GART physical addresses.
+ */
+static unsigned int map32_handle = 0x10000000;
+#endif
+
/**
* Ioctl to specify a range of memory that is available for mapping by a non-root process.
*
@@ -187,16 +196,18 @@ int drm_addmap( struct inode *inode, struct file *filp,
down(&dev->struct_sem);
list_add(&list->head, &dev->maplist->head);
+#ifdef CONFIG_COMPAT
+ /* Assign a 32-bit handle for _DRM_SHM mappings */
+ /* We do it here so that dev->struct_sem protects the increment */
+ if (map->type == _DRM_SHM)
+ map->offset = map32_handle += PAGE_SIZE;
+#endif
up(&dev->struct_sem);
if ( copy_to_user( argp, map, sizeof(*map) ) )
return -EFAULT;
- if ( map->type != _DRM_SHM ) {
- if ( copy_to_user( &argp->handle,
- &map->offset,
- sizeof(map->offset) ) )
- return -EFAULT;
- }
+ if (copy_to_user(&argp->handle, &map->offset, sizeof(map->offset)))
+ return -EFAULT;
return 0;
}
@@ -240,7 +251,7 @@ int drm_rmmap(struct inode *inode, struct file *filp,
r_list = list_entry(list, drm_map_list_t, head);
if(r_list->map &&
- r_list->map->handle == request.handle &&
+ r_list->map->offset == (unsigned long) request.handle &&
r_list->map->flags & _DRM_REMOVABLE) break;
}
diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c
index f15c86c5787..fdf661f234e 100644
--- a/drivers/char/drm/drm_context.c
+++ b/drivers/char/drm/drm_context.c
@@ -225,7 +225,7 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
map = dev->context_sareas[request.ctx_id];
up(&dev->struct_sem);
- request.handle = map->handle;
+ request.handle = (void *) map->offset;
if (copy_to_user(argp, &request, sizeof(request)))
return -EFAULT;
return 0;
@@ -261,8 +261,8 @@ int drm_setsareactx(struct inode *inode, struct file *filp,
down(&dev->struct_sem);
list_for_each(list, &dev->maplist->head) {
r_list = list_entry(list, drm_map_list_t, head);
- if(r_list->map &&
- r_list->map->handle == request.handle)
+ if (r_list->map
+ && r_list->map->offset == (unsigned long) request.handle)
goto found;
}
bad:
diff --git a/drivers/char/drm/drm_ioc32.c b/drivers/char/drm/drm_ioc32.c
new file mode 100644
index 00000000000..8087a963639
--- /dev/null
+++ b/drivers/char/drm/drm_ioc32.c
@@ -0,0 +1,1069 @@
+/**
+ * \file drm_ioc32.c
+ *
+ * 32-bit ioctl compatibility routines for the DRM.
+ *
+ * \author Paul Mackerras <paulus@samba.org>
+ *
+ * Copyright (C) Paul Mackerras 2005.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <linux/compat.h>
+#include <linux/ioctl32.h>
+
+#include "drmP.h"
+#include "drm_core.h"
+
+#define DRM_IOCTL_VERSION32 DRM_IOWR(0x00, drm_version32_t)
+#define DRM_IOCTL_GET_UNIQUE32 DRM_IOWR(0x01, drm_unique32_t)
+#define DRM_IOCTL_GET_MAP32 DRM_IOWR(0x04, drm_map32_t)
+#define DRM_IOCTL_GET_CLIENT32 DRM_IOWR(0x05, drm_client32_t)
+#define DRM_IOCTL_GET_STATS32 DRM_IOR( 0x06, drm_stats32_t)
+
+#define DRM_IOCTL_SET_UNIQUE32 DRM_IOW( 0x10, drm_unique32_t)
+#define DRM_IOCTL_ADD_MAP32 DRM_IOWR(0x15, drm_map32_t)
+#define DRM_IOCTL_ADD_BUFS32 DRM_IOWR(0x16, drm_buf_desc32_t)
+#define DRM_IOCTL_MARK_BUFS32 DRM_IOW( 0x17, drm_buf_desc32_t)
+#define DRM_IOCTL_INFO_BUFS32 DRM_IOWR(0x18, drm_buf_info32_t)
+#define DRM_IOCTL_MAP_BUFS32 DRM_IOWR(0x19, drm_buf_map32_t)
+#define DRM_IOCTL_FREE_BUFS32 DRM_IOW( 0x1a, drm_buf_free32_t)
+
+#define DRM_IOCTL_RM_MAP32 DRM_IOW( 0x1b, drm_map32_t)
+
+#define DRM_IOCTL_SET_SAREA_CTX32 DRM_IOW( 0x1c, drm_ctx_priv_map32_t)
+#define DRM_IOCTL_GET_SAREA_CTX32 DRM_IOWR(0x1d, drm_ctx_priv_map32_t)
+
+#define DRM_IOCTL_RES_CTX32 DRM_IOWR(0x26, drm_ctx_res32_t)
+#define DRM_IOCTL_DMA32 DRM_IOWR(0x29, drm_dma32_t)
+
+#define DRM_IOCTL_AGP_ENABLE32 DRM_IOW( 0x32, drm_agp_mode32_t)
+#define DRM_IOCTL_AGP_INFO32 DRM_IOR( 0x33, drm_agp_info32_t)
+#define DRM_IOCTL_AGP_ALLOC32 DRM_IOWR(0x34, drm_agp_buffer32_t)
+#define DRM_IOCTL_AGP_FREE32 DRM_IOW( 0x35, drm_agp_buffer32_t)
+#define DRM_IOCTL_AGP_BIND32 DRM_IOW( 0x36, drm_agp_binding32_t)
+#define DRM_IOCTL_AGP_UNBIND32 DRM_IOW( 0x37, drm_agp_binding32_t)
+
+#define DRM_IOCTL_SG_ALLOC32 DRM_IOW( 0x38, drm_scatter_gather32_t)
+#define DRM_IOCTL_SG_FREE32 DRM_IOW( 0x39, drm_scatter_gather32_t)
+
+#define DRM_IOCTL_WAIT_VBLANK32 DRM_IOWR(0x3a, drm_wait_vblank32_t)
+
+typedef struct drm_version_32 {
+ int version_major; /**< Major version */
+ int version_minor; /**< Minor version */
+ int version_patchlevel;/**< Patch level */
+ u32 name_len; /**< Length of name buffer */
+ u32 name; /**< Name of driver */
+ u32 date_len; /**< Length of date buffer */
+ u32 date; /**< User-space buffer to hold date */
+ u32 desc_len; /**< Length of desc buffer */
+ u32 desc; /**< User-space buffer to hold desc */
+} drm_version32_t;
+
+static int compat_drm_version(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_version32_t v32;
+ drm_version_t __user *version;
+ int err;
+
+ if (copy_from_user(&v32, (void __user *) arg, sizeof(v32)))
+ return -EFAULT;
+
+ version = compat_alloc_user_space(sizeof(*version));
+ if (!access_ok(VERIFY_WRITE, version, sizeof(*version)))
+ return -EFAULT;
+ if (__put_user(v32.name_len, &version->name_len)
+ || __put_user((void __user *)(unsigned long)v32.name,
+ &version->name)
+ || __put_user(v32.date_len, &version->date_len)
+ || __put_user((void __user *)(unsigned long)v32.date,
+ &version->date)
+ || __put_user(v32.desc_len, &version->desc_len)
+ || __put_user((void __user *)(unsigned long)v32.desc,
+ &version->desc))
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_VERSION, (unsigned long) version);
+ if (err)
+ return err;
+
+ if (__get_user(v32.version_major, &version->version_major)
+ || __get_user(v32.version_minor, &version->version_minor)
+ || __get_user(v32.version_patchlevel, &version->version_patchlevel)
+ || __get_user(v32.name_len, &version->name_len)
+ || __get_user(v32.date_len, &version->date_len)
+ || __get_user(v32.desc_len, &version->desc_len))
+ return -EFAULT;
+
+ if (copy_to_user((void __user *) arg, &v32, sizeof(v32)))
+ return -EFAULT;
+ return 0;
+}
+
+typedef struct drm_unique32 {
+ u32 unique_len; /**< Length of unique */
+ u32 unique; /**< Unique name for driver instantiation */
+} drm_unique32_t;
+
+static int compat_drm_getunique(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_unique32_t uq32;
+ drm_unique_t __user *u;
+ int err;
+
+ if (copy_from_user(&uq32, (void __user *) arg, sizeof(uq32)))
+ return -EFAULT;
+
+ u = compat_alloc_user_space(sizeof(*u));
+ if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
+ return -EFAULT;
+ if (__put_user(uq32.unique_len, &u->unique_len)
+ || __put_user((void __user *)(unsigned long) uq32.unique,
+ &u->unique))
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_GET_UNIQUE, (unsigned long) u);
+ if (err)
+ return err;
+
+ if (__get_user(uq32.unique_len, &u->unique_len))
+ return -EFAULT;
+ if (copy_to_user((void __user *) arg, &uq32, sizeof(uq32)))
+ return -EFAULT;
+ return 0;
+}
+
+static int compat_drm_setunique(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_unique32_t uq32;
+ drm_unique_t __user *u;
+
+ if (copy_from_user(&uq32, (void __user *) arg, sizeof(uq32)))
+ return -EFAULT;
+
+ u = compat_alloc_user_space(sizeof(*u));
+ if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
+ return -EFAULT;
+ if (__put_user(uq32.unique_len, &u->unique_len)
+ || __put_user((void __user *)(unsigned long) uq32.unique,
+ &u->unique))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_SET_UNIQUE, (unsigned long) u);
+}
+
+typedef struct drm_map32 {
+ u32 offset; /**< Requested physical address (0 for SAREA)*/
+ u32 size; /**< Requested physical size (bytes) */
+ drm_map_type_t type; /**< Type of memory to map */
+ drm_map_flags_t flags; /**< Flags */
+ u32 handle; /**< User-space: "Handle" to pass to mmap() */
+ int mtrr; /**< MTRR slot used */
+} drm_map32_t;
+
+static int compat_drm_getmap(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_map32_t __user *argp = (void __user *)arg;
+ drm_map32_t m32;
+ drm_map_t __user *map;
+ int idx, err;
+ void *handle;
+
+ if (get_user(idx, &argp->offset))
+ return -EFAULT;
+
+ map = compat_alloc_user_space(sizeof(*map));
+ if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
+ return -EFAULT;
+ if (__put_user(idx, &map->offset))
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_GET_MAP, (unsigned long) map);
+ if (err)
+ return err;
+
+ if (__get_user(m32.offset, &map->offset)
+ || __get_user(m32.size, &map->size)
+ || __get_user(m32.type, &map->type)
+ || __get_user(m32.flags, &map->flags)
+ || __get_user(handle, &map->handle)
+ || __get_user(m32.mtrr, &map->mtrr))
+ return -EFAULT;
+
+ m32.handle = (unsigned long) handle;
+ if (copy_to_user(argp, &m32, sizeof(m32)))
+ return -EFAULT;
+ return 0;
+
+}
+
+static int compat_drm_addmap(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_map32_t __user *argp = (void __user *)arg;
+ drm_map32_t m32;
+ drm_map_t __user *map;
+ int err;
+ void *handle;
+
+ if (copy_from_user(&m32, argp, sizeof(m32)))
+ return -EFAULT;
+
+ map = compat_alloc_user_space(sizeof(*map));
+ if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
+ return -EFAULT;
+ if (__put_user(m32.offset, &map->offset)
+ || __put_user(m32.size, &map->size)
+ || __put_user(m32.type, &map->type)
+ || __put_user(m32.flags, &map->flags))
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_ADD_MAP, (unsigned long) map);
+ if (err)
+ return err;
+
+ if (__get_user(m32.offset, &map->offset)
+ || __get_user(m32.mtrr, &map->mtrr)
+ || __get_user(handle, &map->handle))
+ return -EFAULT;
+
+ m32.handle = (unsigned long) handle;
+ if (m32.handle != (unsigned long) handle && printk_ratelimit())
+ printk(KERN_ERR "compat_drm_addmap truncated handle"
+ " %p for type %d offset %x\n",
+ handle, m32.type, m32.offset);
+
+ if (copy_to_user(argp, &m32, sizeof(m32)))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int compat_drm_rmmap(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_map32_t __user *argp = (void __user *)arg;
+ drm_map_t __user *map;
+ u32 handle;
+
+ if (get_user(handle, &argp->handle))
+ return -EFAULT;
+
+ map = compat_alloc_user_space(sizeof(*map));
+ if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
+ return -EFAULT;
+ if (__put_user((void *)(unsigned long) handle, &map->handle))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_RM_MAP, (unsigned long) map);
+}
+
+typedef struct drm_client32 {
+ int idx; /**< Which client desired? */
+ int auth; /**< Is client authenticated? */
+ u32 pid; /**< Process ID */
+ u32 uid; /**< User ID */
+ u32 magic; /**< Magic */
+ u32 iocs; /**< Ioctl count */
+} drm_client32_t;
+
+static int compat_drm_getclient(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_client32_t c32;
+ drm_client32_t __user *argp = (void __user *)arg;
+ drm_client_t __user *client;
+ int idx, err;
+
+ if (get_user(idx, &argp->idx))
+ return -EFAULT;
+
+ client = compat_alloc_user_space(sizeof(*client));
+ if (!access_ok(VERIFY_WRITE, client, sizeof(*client)))
+ return -EFAULT;
+ if (__put_user(idx, &client->idx))
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_GET_CLIENT, (unsigned long) client);
+ if (err)
+ return err;
+
+ if (__get_user(c32.auth, &client->auth)
+ || __get_user(c32.pid, &client->pid)
+ || __get_user(c32.uid, &client->uid)
+ || __get_user(c32.magic, &client->magic)
+ || __get_user(c32.iocs, &client->iocs))
+ return -EFAULT;
+
+ if (copy_to_user(argp, &c32, sizeof(c32)))
+ return -EFAULT;
+ return 0;
+}
+
+typedef struct drm_stats32 {
+ u32 count;
+ struct {
+ u32 value;
+ drm_stat_type_t type;
+ } data[15];
+} drm_stats32_t;
+
+static int compat_drm_getstats(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_stats32_t s32;
+ drm_stats32_t __user *argp = (void __user *)arg;
+ drm_stats_t __user *stats;
+ int i, err;
+
+ stats = compat_alloc_user_space(sizeof(*stats));
+ if (!access_ok(VERIFY_WRITE, stats, sizeof(*stats)))
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_GET_STATS, (unsigned long) stats);
+ if (err)
+ return err;
+
+ if (__get_user(s32.count, &stats->count))
+ return -EFAULT;
+ for (i = 0; i < 15; ++i)
+ if (__get_user(s32.data[i].value, &stats->data[i].value)
+ || __get_user(s32.data[i].type, &stats->data[i].type))
+ return -EFAULT;
+
+ if (copy_to_user(argp, &s32, sizeof(s32)))
+ return -EFAULT;
+ return 0;
+}
+
+typedef struct drm_buf_desc32 {
+ int count; /**< Number of buffers of this size */
+ int size; /**< Size in bytes */
+ int low_mark; /**< Low water mark */
+ int high_mark; /**< High water mark */
+ int flags;
+ u32 agp_start; /**< Start address in the AGP aperture */
+} drm_buf_desc32_t;
+
+static int compat_drm_addbufs(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_buf_desc32_t __user *argp = (void __user *)arg;
+ drm_buf_desc_t __user *buf;
+ int err;
+ unsigned long agp_start;
+
+ buf = compat_alloc_user_space(sizeof(*buf));
+ if (!access_ok(VERIFY_WRITE, buf, sizeof(*buf))
+ || !access_ok(VERIFY_WRITE, argp, sizeof(*argp)))
+ return -EFAULT;
+
+ if (__copy_in_user(buf, argp, offsetof(drm_buf_desc32_t, agp_start))
+ || __get_user(agp_start, &argp->agp_start)
+ || __put_user(agp_start, &buf->agp_start))
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_ADD_BUFS, (unsigned long) buf);
+ if (err)
+ return err;
+
+ if (__copy_in_user(argp, buf, offsetof(drm_buf_desc32_t, agp_start))
+ || __get_user(agp_start, &buf->agp_start)
+ || __put_user(agp_start, &argp->agp_start))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int compat_drm_markbufs(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_buf_desc32_t b32;
+ drm_buf_desc32_t __user *argp = (void __user *)arg;
+ drm_buf_desc_t __user *buf;
+
+ if (copy_from_user(&b32, argp, sizeof(b32)))
+ return -EFAULT;
+
+ buf = compat_alloc_user_space(sizeof(*buf));
+ if (!access_ok(VERIFY_WRITE, buf, sizeof(*buf)))
+ return -EFAULT;
+
+ if (__put_user(b32.size, &buf->size)
+ || __put_user(b32.low_mark, &buf->low_mark)
+ || __put_user(b32.high_mark, &buf->high_mark))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_MARK_BUFS, (unsigned long) buf);
+}
+
+typedef struct drm_buf_info32 {
+ int count; /**< Entries in list */
+ u32 list;
+} drm_buf_info32_t;
+
+static int compat_drm_infobufs(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_buf_info32_t req32;
+ drm_buf_info32_t __user *argp = (void __user *)arg;
+ drm_buf_desc32_t __user *to;
+ drm_buf_info_t __user *request;
+ drm_buf_desc_t __user *list;
+ size_t nbytes;
+ int i, err;
+ int count, actual;
+
+ if (copy_from_user(&req32, argp, sizeof(req32)))
+ return -EFAULT;
+
+ count = req32.count;
+ to = (drm_buf_desc32_t __user *)(unsigned long) req32.list;
+ if (count < 0)
+ count = 0;
+ if (count > 0
+ && !access_ok(VERIFY_WRITE, to, count * sizeof(drm_buf_desc32_t)))
+ return -EFAULT;
+
+ nbytes = sizeof(*request) + count * sizeof(drm_buf_desc_t);
+ request = compat_alloc_user_space(nbytes);
+ if (!access_ok(VERIFY_WRITE, request, nbytes))
+ return -EFAULT;
+ list = (drm_buf_desc_t *) (request + 1);
+
+ if (__put_user(count, &request->count)
+ || __put_user(list, &request->list))
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_INFO_BUFS, (unsigned long) request);
+ if (err)
+ return err;
+
+ if (__get_user(actual, &request->count))
+ return -EFAULT;
+ if (count >= actual)
+ for (i = 0; i < actual; ++i)
+ if (__copy_in_user(&to[i], &list[i],
+ offsetof(drm_buf_desc_t, flags)))
+ return -EFAULT;
+
+ if (__put_user(actual, &argp->count))
+ return -EFAULT;
+
+ return 0;
+}
+
+typedef struct drm_buf_pub32 {
+ int idx; /**< Index into the master buffer list */
+ int total; /**< Buffer size */
+ int used; /**< Amount of buffer in use (for DMA) */
+ u32 address; /**< Address of buffer */
+} drm_buf_pub32_t;
+
+typedef struct drm_buf_map32 {
+ int count; /**< Length of the buffer list */
+ u32 virtual; /**< Mmap'd area in user-virtual */
+ u32 list; /**< Buffer information */
+} drm_buf_map32_t;
+
+static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_buf_map32_t __user *argp = (void __user *)arg;
+ drm_buf_map32_t req32;
+ drm_buf_pub32_t __user *list32;
+ drm_buf_map_t __user *request;
+ drm_buf_pub_t __user *list;
+ int i, err;
+ int count, actual;
+ size_t nbytes;
+ void __user *addr;
+
+ if (copy_from_user(&req32, argp, sizeof(req32)))
+ return -EFAULT;
+ count = req32.count;
+ list32 = (void __user *)(unsigned long)req32.list;
+
+ if (count < 0)
+ return -EINVAL;
+ nbytes = sizeof(*request) + count * sizeof(drm_buf_pub_t);
+ request = compat_alloc_user_space(nbytes);
+ if (!access_ok(VERIFY_WRITE, request, nbytes))
+ return -EFAULT;
+ list = (drm_buf_pub_t *) (request + 1);
+
+ if (__put_user(count, &request->count)
+ || __put_user(list, &request->list))
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_MAP_BUFS, (unsigned long) request);
+ if (err)
+ return err;
+
+ if (__get_user(actual, &request->count))
+ return -EFAULT;
+ if (count >= actual)
+ for (i = 0; i < actual; ++i)
+ if (__copy_in_user(&list32[i], &list[i],
+ offsetof(drm_buf_pub_t, address))
+ || __get_user(addr, &list[i].address)
+ || __put_user((unsigned long) addr,
+ &list32[i].address))
+ return -EFAULT;
+
+ if (__put_user(actual, &argp->count)
+ || __get_user(addr, &request->virtual)
+ || __put_user((unsigned long) addr, &argp->virtual))
+ return -EFAULT;
+
+ return 0;
+}
+
+typedef struct drm_buf_free32 {
+ int count;
+ u32 list;
+} drm_buf_free32_t;
+
+static int compat_drm_freebufs(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_buf_free32_t req32;
+ drm_buf_free_t __user *request;
+ drm_buf_free32_t __user *argp = (void __user *)arg;
+
+ if (copy_from_user(&req32, argp, sizeof(req32)))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request));
+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
+ return -EFAULT;
+ if (__put_user(req32.count, &request->count)
+ || __put_user((int __user *)(unsigned long) req32.list,
+ &request->list))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_FREE_BUFS, (unsigned long) request);
+}
+
+typedef struct drm_ctx_priv_map32 {
+ unsigned int ctx_id; /**< Context requesting private mapping */
+ u32 handle; /**< Handle of map */
+} drm_ctx_priv_map32_t;
+
+static int compat_drm_setsareactx(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_ctx_priv_map32_t req32;
+ drm_ctx_priv_map_t __user *request;
+ drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
+
+ if (copy_from_user(&req32, argp, sizeof(req32)))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request));
+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
+ return -EFAULT;
+ if (__put_user(req32.ctx_id, &request->ctx_id)
+ || __put_user((void *)(unsigned long) req32.handle,
+ &request->handle))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_SET_SAREA_CTX, (unsigned long) request);
+}
+
+static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_ctx_priv_map_t __user *request;
+ drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
+ int err;
+ unsigned int ctx_id;
+ void *handle;
+
+ if (!access_ok(VERIFY_WRITE, argp, sizeof(*argp))
+ || __get_user(ctx_id, &argp->ctx_id))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request));
+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
+ return -EFAULT;
+ if (__put_user(ctx_id, &request->ctx_id))
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_GET_SAREA_CTX, (unsigned long) request);
+ if (err)
+ return err;
+
+ if (__get_user(handle, &request->handle)
+ || __put_user((unsigned long) handle, &argp->handle))
+ return -EFAULT;
+
+ return 0;
+}
+
+typedef struct drm_ctx_res32 {
+ int count;
+ u32 contexts;
+} drm_ctx_res32_t;
+
+static int compat_drm_resctx(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_ctx_res32_t __user *argp = (void __user *)arg;
+ drm_ctx_res32_t res32;
+ drm_ctx_res_t __user *res;
+ int err;
+
+ if (copy_from_user(&res32, argp, sizeof(res32)))
+ return -EFAULT;
+
+ res = compat_alloc_user_space(sizeof(*res));
+ if (!access_ok(VERIFY_WRITE, res, sizeof(*res)))
+ return -EFAULT;
+ if (__put_user(res32.count, &res->count)
+ || __put_user((drm_ctx_t __user *)(unsigned long) res32.contexts,
+ &res->contexts))
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_RES_CTX, (unsigned long) res);
+ if (err)
+ return err;
+
+ if (__get_user(res32.count, &res->count)
+ || __put_user(res32.count, &argp->count))
+ return -EFAULT;
+
+ return 0;
+}
+
+typedef struct drm_dma32 {
+ int context; /**< Context handle */
+ int send_count; /**< Number of buffers to send */
+ u32 send_indices; /**< List of handles to buffers */
+ u32 send_sizes; /**< Lengths of data to send */
+ drm_dma_flags_t flags; /**< Flags */
+ int request_count; /**< Number of buffers requested */
+ int request_size; /**< Desired size for buffers */
+ u32 request_indices; /**< Buffer information */
+ u32 request_sizes;
+ int granted_count; /**< Number of buffers granted */
+} drm_dma32_t;
+
+static int compat_drm_dma(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_dma32_t d32;
+ drm_dma32_t __user *argp = (void __user *) arg;
+ drm_dma_t __user *d;
+ int err;
+
+ if (copy_from_user(&d32, argp, sizeof(d32)))
+ return -EFAULT;
+
+ d = compat_alloc_user_space(sizeof(*d));
+ if (!access_ok(VERIFY_WRITE, d, sizeof(*d)))
+ return -EFAULT;
+
+ if (__put_user(d32.context, &d->context)
+ || __put_user(d32.send_count, &d->send_count)
+ || __put_user((int __user *)(unsigned long) d32.send_indices,
+ &d->send_indices)
+ || __put_user((int __user *)(unsigned long) d32.send_sizes,
+ &d->send_sizes)
+ || __put_user(d32.flags, &d->flags)
+ || __put_user(d32.request_count, &d->request_count)
+ || __put_user((int __user *)(unsigned long) d32.request_indices,
+ &d->request_indices)
+ || __put_user((int __user *)(unsigned long) d32.request_sizes,
+ &d->request_sizes))
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_DMA, (unsigned long) d);
+ if (err)
+ return err;
+
+ if (__get_user(d32.request_size, &d->request_size)
+ || __get_user(d32.granted_count, &d->granted_count)
+ || __put_user(d32.request_size, &argp->request_size)
+ || __put_user(d32.granted_count, &argp->granted_count))
+ return -EFAULT;
+
+ return 0;
+}
+
+#if __OS_HAS_AGP
+typedef struct drm_agp_mode32 {
+ u32 mode; /**< AGP mode */
+} drm_agp_mode32_t;
+
+static int compat_drm_agp_enable(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_agp_mode32_t __user *argp = (void __user *)arg;
+ drm_agp_mode32_t m32;
+ drm_agp_mode_t __user *mode;
+
+ if (get_user(m32.mode, &argp->mode))
+ return -EFAULT;
+
+ mode = compat_alloc_user_space(sizeof(*mode));
+ if (put_user(m32.mode, &mode->mode))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_AGP_ENABLE, (unsigned long) mode);
+}
+
+typedef struct drm_agp_info32 {
+ int agp_version_major;
+ int agp_version_minor;
+ u32 mode;
+ u32 aperture_base; /* physical address */
+ u32 aperture_size; /* bytes */
+ u32 memory_allowed; /* bytes */
+ u32 memory_used;
+
+ /* PCI information */
+ unsigned short id_vendor;
+ unsigned short id_device;
+} drm_agp_info32_t;
+
+static int compat_drm_agp_info(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_agp_info32_t __user *argp = (void __user *)arg;
+ drm_agp_info32_t i32;
+ drm_agp_info_t __user *info;
+ int err;
+
+ info = compat_alloc_user_space(sizeof(*info));
+ if (!access_ok(VERIFY_WRITE, info, sizeof(*info)))
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_AGP_INFO, (unsigned long) info);
+ if (err)
+ return err;
+
+ if (__get_user(i32.agp_version_major, &info->agp_version_major)
+ || __get_user(i32.agp_version_minor, &info->agp_version_minor)
+ || __get_user(i32.mode, &info->mode)
+ || __get_user(i32.aperture_base, &info->aperture_base)
+ || __get_user(i32.aperture_size, &info->aperture_size)
+ || __get_user(i32.memory_allowed, &info->memory_allowed)
+ || __get_user(i32.memory_used, &info->memory_used)
+ || __get_user(i32.id_vendor, &info->id_vendor)
+ || __get_user(i32.id_device, &info->id_device))
+ return -EFAULT;
+
+ if (copy_to_user(argp, &i32, sizeof(i32)))
+ return -EFAULT;
+
+ return 0;
+}
+
+typedef struct drm_agp_buffer32 {
+ u32 size; /**< In bytes -- will round to page boundary */
+ u32 handle; /**< Used for binding / unbinding */
+ u32 type; /**< Type of memory to allocate */
+ u32 physical; /**< Physical used by i810 */
+} drm_agp_buffer32_t;
+
+static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_agp_buffer32_t __user *argp = (void __user *)arg;
+ drm_agp_buffer32_t req32;
+ drm_agp_buffer_t __user *request;
+ int err;
+
+ if (copy_from_user(&req32, argp, sizeof(req32)))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request));
+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+ || __put_user(req32.size, &request->size)
+ || __put_user(req32.type, &request->type))
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_AGP_ALLOC, (unsigned long) request);
+ if (err)
+ return err;
+
+ if (__get_user(req32.handle, &request->handle)
+ || __get_user(req32.physical, &request->physical)
+ || copy_to_user(argp, &req32, sizeof(req32))) {
+ drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_AGP_FREE, (unsigned long) request);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int compat_drm_agp_free(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_agp_buffer32_t __user *argp = (void __user *)arg;
+ drm_agp_buffer_t __user *request;
+ u32 handle;
+
+ request = compat_alloc_user_space(sizeof(*request));
+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+ || get_user(handle, &argp->handle)
+ || __put_user(handle, &request->handle))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_AGP_FREE, (unsigned long) request);
+}
+
+typedef struct drm_agp_binding32 {
+ u32 handle; /**< From drm_agp_buffer */
+ u32 offset; /**< In bytes -- will round to page boundary */
+} drm_agp_binding32_t;
+
+static int compat_drm_agp_bind(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_agp_binding32_t __user *argp = (void __user *)arg;
+ drm_agp_binding32_t req32;
+ drm_agp_binding_t __user *request;
+
+ if (copy_from_user(&req32, argp, sizeof(req32)))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request));
+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+ || __put_user(req32.handle, &request->handle)
+ || __put_user(req32.offset, &request->offset))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_AGP_BIND, (unsigned long) request);
+}
+
+static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_agp_binding32_t __user *argp = (void __user *)arg;
+ drm_agp_binding_t __user *request;
+ u32 handle;
+
+ request = compat_alloc_user_space(sizeof(*request));
+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+ || get_user(handle, &argp->handle)
+ || __put_user(handle, &request->handle))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_AGP_UNBIND, (unsigned long) request);
+}
+#endif /* __OS_HAS_AGP */
+
+typedef struct drm_scatter_gather32 {
+ u32 size; /**< In bytes -- will round to page boundary */
+ u32 handle; /**< Used for mapping / unmapping */
+} drm_scatter_gather32_t;
+
+static int compat_drm_sg_alloc(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_scatter_gather32_t __user *argp = (void __user *)arg;
+ drm_scatter_gather_t __user *request;
+ int err;
+ unsigned long x;
+
+ request = compat_alloc_user_space(sizeof(*request));
+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+ || !access_ok(VERIFY_WRITE, argp, sizeof(*argp))
+ || __get_user(x, &argp->size)
+ || __put_user(x, &request->size))
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_SG_ALLOC, (unsigned long) request);
+ if (err)
+ return err;
+
+ /* XXX not sure about the handle conversion here... */
+ if (__get_user(x, &request->handle)
+ || __put_user(x >> PAGE_SHIFT, &argp->handle))
+ return -EFAULT;
+
+ return 0;
+}
+
+static int compat_drm_sg_free(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_scatter_gather32_t __user *argp = (void __user *)arg;
+ drm_scatter_gather_t __user *request;
+ unsigned long x;
+
+ request = compat_alloc_user_space(sizeof(*request));
+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+ || !access_ok(VERIFY_WRITE, argp, sizeof(*argp))
+ || __get_user(x, &argp->handle)
+ || __put_user(x << PAGE_SHIFT, &request->handle))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_SG_FREE, (unsigned long) request);
+}
+
+struct drm_wait_vblank_request32 {
+ drm_vblank_seq_type_t type;
+ unsigned int sequence;
+ u32 signal;
+};
+
+struct drm_wait_vblank_reply32 {
+ drm_vblank_seq_type_t type;
+ unsigned int sequence;
+ s32 tval_sec;
+ s32 tval_usec;
+};
+
+typedef union drm_wait_vblank32 {
+ struct drm_wait_vblank_request32 request;
+ struct drm_wait_vblank_reply32 reply;
+} drm_wait_vblank32_t;
+
+static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_wait_vblank32_t __user *argp = (void __user *)arg;
+ drm_wait_vblank32_t req32;
+ drm_wait_vblank_t __user *request;
+ int err;
+
+ if (copy_from_user(&req32, argp, sizeof(req32)))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request));
+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+ || __put_user(req32.request.type, &request->request.type)
+ || __put_user(req32.request.sequence, &request->request.sequence)
+ || __put_user(req32.request.signal, &request->request.signal))
+ return -EFAULT;
+
+ err = drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_WAIT_VBLANK, (unsigned long) request);
+ if (err)
+ return err;
+
+ if (__get_user(req32.reply.type, &request->reply.type)
+ || __get_user(req32.reply.sequence, &request->reply.sequence)
+ || __get_user(req32.reply.tval_sec, &request->reply.tval_sec)
+ || __get_user(req32.reply.tval_usec, &request->reply.tval_usec))
+ return -EFAULT;
+
+ if (copy_to_user(argp, &req32, sizeof(req32)))
+ return -EFAULT;
+
+ return 0;
+}
+
+drm_ioctl_compat_t *drm_compat_ioctls[] = {
+ [DRM_IOCTL_NR(DRM_IOCTL_VERSION32)] = compat_drm_version,
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE32)] = compat_drm_getunique,
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP32)] = compat_drm_getmap,
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT32)] = compat_drm_getclient,
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS32)] = compat_drm_getstats,
+ [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE32)] = compat_drm_setunique,
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP32)] = compat_drm_addmap,
+ [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS32)] = compat_drm_addbufs,
+ [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS32)] = compat_drm_markbufs,
+ [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS32)] = compat_drm_infobufs,
+ [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS32)] = compat_drm_mapbufs,
+ [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS32)] = compat_drm_freebufs,
+ [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP32)] = compat_drm_rmmap,
+ [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX32)] = compat_drm_setsareactx,
+ [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX32)] = compat_drm_getsareactx,
+ [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX32)] = compat_drm_resctx,
+ [DRM_IOCTL_NR(DRM_IOCTL_DMA32)] = compat_drm_dma,
+#if __OS_HAS_AGP
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE32)] = compat_drm_agp_enable,
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO32)] = compat_drm_agp_info,
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC32)] = compat_drm_agp_alloc,
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE32)] = compat_drm_agp_free,
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND32)] = compat_drm_agp_bind,
+ [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND32)] = compat_drm_agp_unbind,
+#endif
+ [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC32)] = compat_drm_sg_alloc,
+ [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE32)] = compat_drm_sg_free,
+ [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK32)] = compat_drm_wait_vblank,
+};
+
+/**
+ * Called whenever a 32-bit process running under a 64-bit kernel
+ * performs an ioctl on /dev/drm.
+ *
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or negative number on failure.
+ */
+long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ unsigned int nr = DRM_IOCTL_NR(cmd);
+ drm_ioctl_compat_t *fn;
+ int ret;
+
+ if (nr >= DRM_ARRAY_SIZE(drm_compat_ioctls))
+ return -ENOTTY;
+
+ fn = drm_compat_ioctls[nr];
+
+ lock_kernel(); /* XXX for now */
+ if (fn != NULL)
+ ret = (*fn)(filp, cmd, arg);
+ else
+ ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+ unlock_kernel();
+
+ return ret;
+}
+EXPORT_SYMBOL(drm_compat_ioctl);
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
index 54a2914e3a3..11c6950158b 100644
--- a/drivers/char/drm/drm_pciids.h
+++ b/drivers/char/drm/drm_pciids.h
@@ -220,5 +220,6 @@
{0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x8086, 0x2582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+ {0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
{0, 0, 0}
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
index 7300a09dbd5..b5903f9f142 100644
--- a/drivers/char/drm/i915_dma.c
+++ b/drivers/char/drm/i915_dma.c
@@ -1,10 +1,30 @@
/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
*/
/**************************************************************************
- *
+ *
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
- *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
**************************************************************************/
#include "drmP.h"
diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h
index 7e55edf45c4..23e027d2908 100644
--- a/drivers/char/drm/i915_drm.h
+++ b/drivers/char/drm/i915_drm.h
@@ -1,3 +1,30 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
#ifndef _I915_DRM_H_
#define _I915_DRM_H_
diff --git a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c
index 002b7082e21..e6a9e1d1d28 100644
--- a/drivers/char/drm/i915_drv.c
+++ b/drivers/char/drm/i915_drv.c
@@ -1,11 +1,30 @@
/* i915_drv.c -- i830,i845,i855,i865,i915 driver -*- linux-c -*-
*/
-
/**************************************************************************
- *
+ *
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
- *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
**************************************************************************/
#include "drmP.h"
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
index f6ca92a565d..fa940d64b85 100644
--- a/drivers/char/drm/i915_drv.h
+++ b/drivers/char/drm/i915_drv.h
@@ -1,10 +1,30 @@
/* i915_drv.h -- Private header for the I915 driver -*- linux-c -*-
*/
/**************************************************************************
- *
+ *
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
- *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
**************************************************************************/
#ifndef _I915_DRV_H_
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
index b0239262a84..a101cc9cfd7 100644
--- a/drivers/char/drm/i915_irq.c
+++ b/drivers/char/drm/i915_irq.c
@@ -1,10 +1,30 @@
/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
*/
/**************************************************************************
- *
+ *
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
- *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
**************************************************************************/
#include "drmP.h"
diff --git a/drivers/char/drm/i915_mem.c b/drivers/char/drm/i915_mem.c
index d54a3005946..9b1698f521b 100644
--- a/drivers/char/drm/i915_mem.c
+++ b/drivers/char/drm/i915_mem.c
@@ -1,10 +1,30 @@
/* i915_mem.c -- Simple agp/fb memory manager for i915 -*- linux-c -*-
*/
/**************************************************************************
- *
+ *
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
- *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
**************************************************************************/
#include "drmP.h"
diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
index 7b983d96e53..18e4e5b0952 100644
--- a/drivers/char/drm/radeon_drv.c
+++ b/drivers/char/drm/radeon_drv.c
@@ -101,6 +101,9 @@ static struct drm_driver driver = {
.mmap = drm_mmap,
.poll = drm_poll,
.fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = radeon_compat_ioctl,
+#endif
},
.pci_driver = {
.name = DRIVER_NAME,
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index 5837098afae..771aa80a5e8 100644
--- a/drivers/char/drm/radeon_drv.h
+++ b/drivers/char/drm/radeon_drv.h
@@ -317,6 +317,9 @@ extern int radeon_preinit( struct drm_device *dev, unsigned long flags );
extern int radeon_postinit( struct drm_device *dev, unsigned long flags );
extern int radeon_postcleanup( struct drm_device *dev );
+extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg);
+
/* Flags for stats.boxes
*/
#define RADEON_BOX_DMA_IDLE 0x1
diff --git a/drivers/char/drm/radeon_ioc32.c b/drivers/char/drm/radeon_ioc32.c
new file mode 100644
index 00000000000..bfe612215fb
--- /dev/null
+++ b/drivers/char/drm/radeon_ioc32.c
@@ -0,0 +1,395 @@
+/**
+ * \file radeon_ioc32.c
+ *
+ * 32-bit ioctl compatibility routines for the Radeon DRM.
+ *
+ * \author Paul Mackerras <paulus@samba.org>
+ *
+ * Copyright (C) Paul Mackerras 2005
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include <linux/compat.h>
+#include <linux/ioctl32.h>
+
+#include "drmP.h"
+#include "drm.h"
+#include "radeon_drm.h"
+#include "radeon_drv.h"
+
+typedef struct drm_radeon_init32 {
+ int func;
+ u32 sarea_priv_offset;
+ int is_pci;
+ int cp_mode;
+ int gart_size;
+ int ring_size;
+ int usec_timeout;
+
+ unsigned int fb_bpp;
+ unsigned int front_offset, front_pitch;
+ unsigned int back_offset, back_pitch;
+ unsigned int depth_bpp;
+ unsigned int depth_offset, depth_pitch;
+
+ u32 fb_offset;
+ u32 mmio_offset;
+ u32 ring_offset;
+ u32 ring_rptr_offset;
+ u32 buffers_offset;
+ u32 gart_textures_offset;
+} drm_radeon_init32_t;
+
+static int compat_radeon_cp_init(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_radeon_init32_t init32;
+ drm_radeon_init_t __user *init;
+
+ if (copy_from_user(&init32, (void __user *)arg, sizeof(init32)))
+ return -EFAULT;
+
+ init = compat_alloc_user_space(sizeof(*init));
+ if (!access_ok(VERIFY_WRITE, init, sizeof(*init))
+ || __put_user(init32.func, &init->func)
+ || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset)
+ || __put_user(init32.is_pci, &init->is_pci)
+ || __put_user(init32.cp_mode, &init->cp_mode)
+ || __put_user(init32.gart_size, &init->gart_size)
+ || __put_user(init32.ring_size, &init->ring_size)
+ || __put_user(init32.usec_timeout, &init->usec_timeout)
+ || __put_user(init32.fb_bpp, &init->fb_bpp)
+ || __put_user(init32.front_offset, &init->front_offset)
+ || __put_user(init32.front_pitch, &init->front_pitch)
+ || __put_user(init32.back_offset, &init->back_offset)
+ || __put_user(init32.back_pitch, &init->back_pitch)
+ || __put_user(init32.depth_bpp, &init->depth_bpp)
+ || __put_user(init32.depth_offset, &init->depth_offset)
+ || __put_user(init32.depth_pitch, &init->depth_pitch)
+ || __put_user(init32.fb_offset, &init->fb_offset)
+ || __put_user(init32.mmio_offset, &init->mmio_offset)
+ || __put_user(init32.ring_offset, &init->ring_offset)
+ || __put_user(init32.ring_rptr_offset, &init->ring_rptr_offset)
+ || __put_user(init32.buffers_offset, &init->buffers_offset)
+ || __put_user(init32.gart_textures_offset,
+ &init->gart_textures_offset))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_RADEON_CP_INIT, (unsigned long) init);
+}
+
+typedef struct drm_radeon_clear32 {
+ unsigned int flags;
+ unsigned int clear_color;
+ unsigned int clear_depth;
+ unsigned int color_mask;
+ unsigned int depth_mask; /* misnamed field: should be stencil */
+ u32 depth_boxes;
+} drm_radeon_clear32_t;
+
+static int compat_radeon_cp_clear(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_radeon_clear32_t clr32;
+ drm_radeon_clear_t __user *clr;
+
+ if (copy_from_user(&clr32, (void __user *)arg, sizeof(clr32)))
+ return -EFAULT;
+
+ clr = compat_alloc_user_space(sizeof(*clr));
+ if (!access_ok(VERIFY_WRITE, clr, sizeof(*clr))
+ || __put_user(clr32.flags, &clr->flags)
+ || __put_user(clr32.clear_color, &clr->clear_color)
+ || __put_user(clr32.clear_depth, &clr->clear_depth)
+ || __put_user(clr32.color_mask, &clr->color_mask)
+ || __put_user(clr32.depth_mask, &clr->depth_mask)
+ || __put_user((void __user *)(unsigned long)clr32.depth_boxes,
+ &clr->depth_boxes))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_RADEON_CLEAR, (unsigned long) clr);
+}
+
+typedef struct drm_radeon_stipple32 {
+ u32 mask;
+} drm_radeon_stipple32_t;
+
+static int compat_radeon_cp_stipple(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_radeon_stipple32_t __user *argp = (void __user *) arg;
+ drm_radeon_stipple_t __user *request;
+ u32 mask;
+
+ if (get_user(mask, &argp->mask))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request));
+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+ || __put_user((unsigned int __user *)(unsigned long) mask,
+ &request->mask))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_RADEON_STIPPLE, (unsigned long) request);
+}
+
+typedef struct drm_radeon_tex_image32 {
+ unsigned int x, y; /* Blit coordinates */
+ unsigned int width, height;
+ u32 data;
+} drm_radeon_tex_image32_t;
+
+typedef struct drm_radeon_texture32 {
+ unsigned int offset;
+ int pitch;
+ int format;
+ int width; /* Texture image coordinates */
+ int height;
+ u32 image;
+} drm_radeon_texture32_t;
+
+static int compat_radeon_cp_texture(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_radeon_texture32_t req32;
+ drm_radeon_texture_t __user *request;
+ drm_radeon_tex_image32_t img32;
+ drm_radeon_tex_image_t __user *image;
+
+ if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+ return -EFAULT;
+ if (req32.image == 0)
+ return -EINVAL;
+ if (copy_from_user(&img32, (void __user *)(unsigned long)req32.image,
+ sizeof(img32)))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request) + sizeof(*image));
+ if (!access_ok(VERIFY_WRITE, request,
+ sizeof(*request) + sizeof(*image)))
+ return -EFAULT;
+ image = (drm_radeon_tex_image_t __user *) (request + 1);
+
+ if (__put_user(req32.offset, &request->offset)
+ || __put_user(req32.pitch, &request->pitch)
+ || __put_user(req32.format, &request->format)
+ || __put_user(req32.width, &request->width)
+ || __put_user(req32.height, &request->height)
+ || __put_user(image, &request->image)
+ || __put_user(img32.x, &image->x)
+ || __put_user(img32.y, &image->y)
+ || __put_user(img32.width, &image->width)
+ || __put_user(img32.height, &image->height)
+ || __put_user((const void __user *)(unsigned long)img32.data,
+ &image->data))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_RADEON_TEXTURE, (unsigned long) request);
+}
+
+typedef struct drm_radeon_vertex2_32 {
+ int idx; /* Index of vertex buffer */
+ int discard; /* Client finished with buffer? */
+ int nr_states;
+ u32 state;
+ int nr_prims;
+ u32 prim;
+} drm_radeon_vertex2_32_t;
+
+static int compat_radeon_cp_vertex2(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_radeon_vertex2_32_t req32;
+ drm_radeon_vertex2_t __user *request;
+
+ if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request));
+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+ || __put_user(req32.idx, &request->idx)
+ || __put_user(req32.discard, &request->discard)
+ || __put_user(req32.nr_states, &request->nr_states)
+ || __put_user((void __user *)(unsigned long)req32.state,
+ &request->state)
+ || __put_user(req32.nr_prims, &request->nr_prims)
+ || __put_user((void __user *)(unsigned long)req32.prim,
+ &request->prim))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_RADEON_VERTEX2, (unsigned long) request);
+}
+
+typedef struct drm_radeon_cmd_buffer32 {
+ int bufsz;
+ u32 buf;
+ int nbox;
+ u32 boxes;
+} drm_radeon_cmd_buffer32_t;
+
+static int compat_radeon_cp_cmdbuf(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_radeon_cmd_buffer32_t req32;
+ drm_radeon_cmd_buffer_t __user *request;
+
+ if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request));
+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+ || __put_user(req32.bufsz, &request->bufsz)
+ || __put_user((void __user *)(unsigned long)req32.buf,
+ &request->buf)
+ || __put_user(req32.nbox, &request->nbox)
+ || __put_user((void __user *)(unsigned long)req32.boxes,
+ &request->boxes))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_RADEON_CMDBUF, (unsigned long) request);
+}
+
+typedef struct drm_radeon_getparam32 {
+ int param;
+ u32 value;
+} drm_radeon_getparam32_t;
+
+static int compat_radeon_cp_getparam(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_radeon_getparam32_t req32;
+ drm_radeon_getparam_t __user *request;
+
+ if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request));
+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+ || __put_user(req32.param, &request->param)
+ || __put_user((void __user *)(unsigned long)req32.value,
+ &request->value))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_RADEON_GETPARAM, (unsigned long) request);
+}
+
+typedef struct drm_radeon_mem_alloc32 {
+ int region;
+ int alignment;
+ int size;
+ u32 region_offset; /* offset from start of fb or GART */
+} drm_radeon_mem_alloc32_t;
+
+static int compat_radeon_mem_alloc(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_radeon_mem_alloc32_t req32;
+ drm_radeon_mem_alloc_t __user *request;
+
+ if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request));
+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+ || __put_user(req32.region, &request->region)
+ || __put_user(req32.alignment, &request->alignment)
+ || __put_user(req32.size, &request->size)
+ || __put_user((int __user *)(unsigned long)req32.region_offset,
+ &request->region_offset))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_RADEON_ALLOC, (unsigned long) request);
+}
+
+typedef struct drm_radeon_irq_emit32 {
+ u32 irq_seq;
+} drm_radeon_irq_emit32_t;
+
+static int compat_radeon_irq_emit(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ drm_radeon_irq_emit32_t req32;
+ drm_radeon_irq_emit_t __user *request;
+
+ if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+ return -EFAULT;
+
+ request = compat_alloc_user_space(sizeof(*request));
+ if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+ || __put_user((int __user *)(unsigned long)req32.irq_seq,
+ &request->irq_seq))
+ return -EFAULT;
+
+ return drm_ioctl(file->f_dentry->d_inode, file,
+ DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long) request);
+}
+
+drm_ioctl_compat_t *radeon_compat_ioctls[] = {
+ [DRM_RADEON_CP_INIT] = compat_radeon_cp_init,
+ [DRM_RADEON_CLEAR] = compat_radeon_cp_clear,
+ [DRM_RADEON_STIPPLE] = compat_radeon_cp_stipple,
+ [DRM_RADEON_TEXTURE] = compat_radeon_cp_texture,
+ [DRM_RADEON_VERTEX2] = compat_radeon_cp_vertex2,
+ [DRM_RADEON_CMDBUF] = compat_radeon_cp_cmdbuf,
+ [DRM_RADEON_GETPARAM] = compat_radeon_cp_getparam,
+ [DRM_RADEON_ALLOC] = compat_radeon_mem_alloc,
+ [DRM_RADEON_IRQ_EMIT] = compat_radeon_irq_emit,
+};
+
+/**
+ * Called whenever a 32-bit process running under a 64-bit kernel
+ * performs an ioctl on /dev/dri/card<n>.
+ *
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or negative number on failure.
+ */
+long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ unsigned int nr = DRM_IOCTL_NR(cmd);
+ drm_ioctl_compat_t *fn = NULL;
+ int ret;
+
+ if (nr < DRM_COMMAND_BASE)
+ return drm_compat_ioctl(filp, cmd, arg);
+
+ if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(radeon_compat_ioctls))
+ fn = radeon_compat_ioctls[nr - DRM_COMMAND_BASE];
+
+ lock_kernel(); /* XXX for now */
+ if (fn != NULL)
+ ret = (*fn)(filp, cmd, arg);
+ else
+ ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+ unlock_kernel();
+
+ return ret;
+}
diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c
index 5b18bee6492..40474a65f56 100644
--- a/drivers/char/drm/radeon_irq.c
+++ b/drivers/char/drm/radeon_irq.c
@@ -35,6 +35,14 @@
#include "radeon_drm.h"
#include "radeon_drv.h"
+static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u32 mask)
+{
+ u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask;
+ if (irqs)
+ RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
+ return irqs;
+}
+
/* Interrupts - Used for device synchronization and flushing in the
* following circumstances:
*
@@ -63,8 +71,8 @@ irqreturn_t radeon_driver_irq_handler( DRM_IRQ_ARGS )
/* Only consider the bits we're interested in - others could be used
* outside the DRM
*/
- stat = RADEON_READ(RADEON_GEN_INT_STATUS)
- & (RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT);
+ stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
+ RADEON_CRTC_VBLANK_STAT));
if (!stat)
return IRQ_NONE;
@@ -80,19 +88,9 @@ irqreturn_t radeon_driver_irq_handler( DRM_IRQ_ARGS )
drm_vbl_send_signals( dev );
}
- /* Acknowledge interrupts we handle */
- RADEON_WRITE(RADEON_GEN_INT_STATUS, stat);
return IRQ_HANDLED;
}
-static __inline__ void radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv)
-{
- u32 tmp = RADEON_READ( RADEON_GEN_INT_STATUS )
- & (RADEON_SW_INT_TEST_ACK | RADEON_CRTC_VBLANK_STAT);
- if (tmp)
- RADEON_WRITE( RADEON_GEN_INT_STATUS, tmp );
-}
-
static int radeon_emit_irq(drm_device_t *dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -123,11 +121,6 @@ static int radeon_wait_irq(drm_device_t *dev, int swi_nr)
dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
- /* This is a hack to work around mysterious freezes on certain
- * systems:
- */
- radeon_acknowledge_irqs( dev_priv );
-
DRM_WAIT_ON( ret, dev_priv->swi_queue, 3 * DRM_HZ,
RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr );
@@ -146,7 +139,7 @@ int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
return DRM_ERR(EINVAL);
}
- radeon_acknowledge_irqs( dev_priv );
+ radeon_acknowledge_irqs(dev_priv, RADEON_CRTC_VBLANK_STAT);
dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
@@ -224,7 +217,8 @@ void radeon_driver_irq_preinstall( drm_device_t *dev ) {
RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
/* Clear bits if they're already high */
- radeon_acknowledge_irqs( dev_priv );
+ radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
+ RADEON_CRTC_VBLANK_STAT));
}
void radeon_driver_irq_postinstall( drm_device_t *dev ) {
diff --git a/drivers/char/ds1620.c b/drivers/char/ds1620.c
index 7def6ad5179..62cda25724e 100644
--- a/drivers/char/ds1620.c
+++ b/drivers/char/ds1620.c
@@ -163,8 +163,7 @@ static void ds1620_out(int cmd, int bits, int value)
netwinder_ds1620_reset();
netwinder_unlock(&flags);
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(2);
+ msleep(20);
}
static unsigned int ds1620_in(int cmd, int bits)
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index 37d6649011a..26271e3ca82 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -144,7 +144,7 @@ static struct dsp56k_device {
int tx_wsize, rx_wsize;
} dsp56k;
-static struct class_simple *dsp56k_class;
+static struct class *dsp56k_class;
static int dsp56k_reset(void)
{
@@ -510,12 +510,12 @@ static int __init dsp56k_init_driver(void)
printk("DSP56k driver: Unable to register driver\n");
return -ENODEV;
}
- dsp56k_class = class_simple_create(THIS_MODULE, "dsp56k");
+ dsp56k_class = class_create(THIS_MODULE, "dsp56k");
if (IS_ERR(dsp56k_class)) {
err = PTR_ERR(dsp56k_class);
goto out_chrdev;
}
- class_simple_device_add(dsp56k_class, MKDEV(DSP56K_MAJOR, 0), NULL, "dsp56k");
+ class_device_create(dsp56k_class, MKDEV(DSP56K_MAJOR, 0), NULL, "dsp56k");
err = devfs_mk_cdev(MKDEV(DSP56K_MAJOR, 0),
S_IFCHR | S_IRUSR | S_IWUSR, "dsp56k");
@@ -526,8 +526,8 @@ static int __init dsp56k_init_driver(void)
goto out;
out_class:
- class_simple_device_remove(MKDEV(DSP56K_MAJOR, 0));
- class_simple_destroy(dsp56k_class);
+ class_device_destroy(dsp56k_class, MKDEV(DSP56K_MAJOR, 0));
+ class_destroy(dsp56k_class);
out_chrdev:
unregister_chrdev(DSP56K_MAJOR, "dsp56k");
out:
@@ -537,8 +537,8 @@ module_init(dsp56k_init_driver);
static void __exit dsp56k_cleanup_driver(void)
{
- class_simple_device_remove(MKDEV(DSP56K_MAJOR, 0));
- class_simple_destroy(dsp56k_class);
+ class_device_destroy(dsp56k_class, MKDEV(DSP56K_MAJOR, 0));
+ class_destroy(dsp56k_class);
unregister_chrdev(DSP56K_MAJOR, "dsp56k");
devfs_remove("dsp56k");
}
diff --git a/drivers/char/ftape/compressor/zftape-compress.c b/drivers/char/ftape/compressor/zftape-compress.c
index 220a227e606..65ffc0be3df 100644
--- a/drivers/char/ftape/compressor/zftape-compress.c
+++ b/drivers/char/ftape/compressor/zftape-compress.c
@@ -1176,8 +1176,8 @@ KERN_INFO "Compressor for zftape (lzrw3 algorithm)\n");
}
#else /* !MODULE */
/* print a short no-nonsense boot message */
- printk("zftape compressor v1.00a 970514\n");
- printk("For use with " FTAPE_VERSION "\n");
+ printk(KERN_INFO "zftape compressor v1.00a 970514\n");
+ printk(KERN_INFO "For use with " FTAPE_VERSION "\n");
#endif /* MODULE */
TRACE(ft_t_info, "zft_compressor_init @ 0x%p", zft_compressor_init);
TRACE(ft_t_info, "installing compressor for zftape ...");
diff --git a/drivers/char/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c
index dbac7e54e8e..5745b74044e 100644
--- a/drivers/char/ftape/zftape/zftape-init.c
+++ b/drivers/char/ftape/zftape/zftape-init.c
@@ -99,7 +99,7 @@ static struct file_operations zft_cdev =
.release = zft_close,
};
-static struct class_simple *zft_class;
+static struct class *zft_class;
/* Open floppy tape device
*/
@@ -329,29 +329,29 @@ KERN_INFO
"installing zftape VFS interface for ftape driver ...");
TRACE_CATCH(register_chrdev(QIC117_TAPE_MAJOR, "zft", &zft_cdev),);
- zft_class = class_simple_create(THIS_MODULE, "zft");
+ zft_class = class_create(THIS_MODULE, "zft");
for (i = 0; i < 4; i++) {
- class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i), NULL, "qft%i", i);
+ class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i), NULL, "qft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i),
S_IFCHR | S_IRUSR | S_IWUSR,
"qft%i", i);
- class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4), NULL, "nqft%i", i);
+ class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4), NULL, "nqft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 4),
S_IFCHR | S_IRUSR | S_IWUSR,
"nqft%i", i);
- class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16), NULL, "zqft%i", i);
+ class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16), NULL, "zqft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 16),
S_IFCHR | S_IRUSR | S_IWUSR,
"zqft%i", i);
- class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20), NULL, "nzqft%i", i);
+ class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20), NULL, "nzqft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 20),
S_IFCHR | S_IRUSR | S_IWUSR,
"nzqft%i", i);
- class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32), NULL, "rawqft%i", i);
+ class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32), NULL, "rawqft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 32),
S_IFCHR | S_IRUSR | S_IWUSR,
"rawqft%i", i);
- class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36), NULL, "nrawrawqft%i", i);
+ class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36), NULL, "nrawrawqft%i", i);
devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 36),
S_IFCHR | S_IRUSR | S_IWUSR,
"nrawqft%i", i);
@@ -381,19 +381,19 @@ static void zft_exit(void)
}
for (i = 0; i < 4; i++) {
devfs_remove("qft%i", i);
- class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i));
+ class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i));
devfs_remove("nqft%i", i);
- class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 4));
+ class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4));
devfs_remove("zqft%i", i);
- class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 16));
+ class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16));
devfs_remove("nzqft%i", i);
- class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 20));
+ class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20));
devfs_remove("rawqft%i", i);
- class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 32));
+ class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32));
devfs_remove("nrawqft%i", i);
- class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 36));
+ class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36));
}
- class_simple_destroy(zft_class);
+ class_destroy(zft_class);
zft_uninit_mem(); /* release remaining memory, if any */
printk(KERN_INFO "zftape successfully unloaded.\n");
TRACE_EXIT;
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 5ec732e6ca9..762fa430fb5 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -834,7 +834,7 @@ int hpet_alloc(struct hpet_data *hdp)
printk("\n");
ns = hpetp->hp_period; /* femptoseconds, 10^-15 */
- do_div(ns, 1000000); /* convert to nanoseconds, 10^-9 */
+ ns /= 1000000; /* convert to nanoseconds, 10^-9 */
printk(KERN_INFO "hpet%d: %ldns tick, %d %d-bit timers\n",
hpetp->hp_which, ns, hpetp->hp_ntimer,
cap & HPET_COUNTER_SIZE_MASK ? 64 : 32);
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c
index abfbdcfd4e7..3236d240490 100644
--- a/drivers/char/hvcs.c
+++ b/drivers/char/hvcs.c
@@ -1466,7 +1466,7 @@ static inline struct hvcs_struct *from_vio_dev(struct vio_dev *viod)
}
/* The sysfs interface for the driver and devices */
-static ssize_t hvcs_partner_vtys_show(struct device *dev, char *buf)
+static ssize_t hvcs_partner_vtys_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct vio_dev *viod = to_vio_dev(dev);
struct hvcs_struct *hvcsd = from_vio_dev(viod);
@@ -1480,7 +1480,7 @@ static ssize_t hvcs_partner_vtys_show(struct device *dev, char *buf)
}
static DEVICE_ATTR(partner_vtys, S_IRUGO, hvcs_partner_vtys_show, NULL);
-static ssize_t hvcs_partner_clcs_show(struct device *dev, char *buf)
+static ssize_t hvcs_partner_clcs_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct vio_dev *viod = to_vio_dev(dev);
struct hvcs_struct *hvcsd = from_vio_dev(viod);
@@ -1494,7 +1494,7 @@ static ssize_t hvcs_partner_clcs_show(struct device *dev, char *buf)
}
static DEVICE_ATTR(partner_clcs, S_IRUGO, hvcs_partner_clcs_show, NULL);
-static ssize_t hvcs_current_vty_store(struct device *dev, const char * buf,
+static ssize_t hvcs_current_vty_store(struct device *dev, struct device_attribute *attr, const char * buf,
size_t count)
{
/*
@@ -1505,7 +1505,7 @@ static ssize_t hvcs_current_vty_store(struct device *dev, const char * buf,
return -EPERM;
}
-static ssize_t hvcs_current_vty_show(struct device *dev, char *buf)
+static ssize_t hvcs_current_vty_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct vio_dev *viod = to_vio_dev(dev);
struct hvcs_struct *hvcsd = from_vio_dev(viod);
@@ -1521,7 +1521,7 @@ static ssize_t hvcs_current_vty_show(struct device *dev, char *buf)
static DEVICE_ATTR(current_vty,
S_IRUGO | S_IWUSR, hvcs_current_vty_show, hvcs_current_vty_store);
-static ssize_t hvcs_vterm_state_store(struct device *dev, const char *buf,
+static ssize_t hvcs_vterm_state_store(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
struct vio_dev *viod = to_vio_dev(dev);
@@ -1559,7 +1559,7 @@ static ssize_t hvcs_vterm_state_store(struct device *dev, const char *buf,
return count;
}
-static ssize_t hvcs_vterm_state_show(struct device *dev, char *buf)
+static ssize_t hvcs_vterm_state_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct vio_dev *viod = to_vio_dev(dev);
struct hvcs_struct *hvcsd = from_vio_dev(viod);
@@ -1574,7 +1574,7 @@ static ssize_t hvcs_vterm_state_show(struct device *dev, char *buf)
static DEVICE_ATTR(vterm_state, S_IRUGO | S_IWUSR,
hvcs_vterm_state_show, hvcs_vterm_state_store);
-static ssize_t hvcs_index_show(struct device *dev, char *buf)
+static ssize_t hvcs_index_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct vio_dev *viod = to_vio_dev(dev);
struct hvcs_struct *hvcsd = from_vio_dev(viod);
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c
index a8119764028..6c4b3f986d0 100644
--- a/drivers/char/i8k.c
+++ b/drivers/char/i8k.c
@@ -20,13 +20,14 @@
#include <linux/types.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
-#include <linux/apm_bios.h>
+#include <linux/seq_file.h>
+#include <linux/dmi.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/i8k.h>
-#define I8K_VERSION "1.13 14/05/2002"
+#define I8K_VERSION "1.14 21/02/2005"
#define I8K_SMM_FN_STATUS 0x0025
#define I8K_SMM_POWER_STATUS 0x0069
@@ -34,7 +35,8 @@
#define I8K_SMM_GET_FAN 0x00a3
#define I8K_SMM_GET_SPEED 0x02a3
#define I8K_SMM_GET_TEMP 0x10a3
-#define I8K_SMM_GET_DELL_SIG 0xffa3
+#define I8K_SMM_GET_DELL_SIG1 0xfea3
+#define I8K_SMM_GET_DELL_SIG2 0xffa3
#define I8K_SMM_BIOS_VERSION 0x00a6
#define I8K_FAN_MULT 30
@@ -52,18 +54,7 @@
#define I8K_TEMPERATURE_BUG 1
-#define DELL_SIGNATURE "Dell Computer"
-
-static char *supported_models[] = {
- "Inspiron",
- "Latitude",
- NULL
-};
-
-static char system_vendor[48] = "?";
-static char product_name [48] = "?";
-static char bios_version [4] = "?";
-static char serial_number[16] = "?";
+static char bios_version[4];
MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)");
MODULE_DESCRIPTION("Driver for accessing SMM BIOS on Dell laptops");
@@ -73,6 +64,10 @@ static int force;
module_param(force, bool, 0);
MODULE_PARM_DESC(force, "Force loading without checking for supported models");
+static int ignore_dmi;
+module_param(ignore_dmi, bool, 0);
+MODULE_PARM_DESC(ignore_dmi, "Continue probing hardware even if DMI data does not match");
+
static int restricted;
module_param(restricted, bool, 0);
MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set");
@@ -81,69 +76,69 @@ static int power_status;
module_param(power_status, bool, 0600);
MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k");
-static ssize_t i8k_read(struct file *, char __user *, size_t, loff_t *);
+static int i8k_open_fs(struct inode *inode, struct file *file);
static int i8k_ioctl(struct inode *, struct file *, unsigned int,
unsigned long);
static struct file_operations i8k_fops = {
- .read = i8k_read,
- .ioctl = i8k_ioctl,
+ .open = i8k_open_fs,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .ioctl = i8k_ioctl,
+};
+
+struct smm_regs {
+ unsigned int eax;
+ unsigned int ebx __attribute__ ((packed));
+ unsigned int ecx __attribute__ ((packed));
+ unsigned int edx __attribute__ ((packed));
+ unsigned int esi __attribute__ ((packed));
+ unsigned int edi __attribute__ ((packed));
};
-typedef struct {
- unsigned int eax;
- unsigned int ebx __attribute__ ((packed));
- unsigned int ecx __attribute__ ((packed));
- unsigned int edx __attribute__ ((packed));
- unsigned int esi __attribute__ ((packed));
- unsigned int edi __attribute__ ((packed));
-} SMMRegisters;
-
-typedef struct {
- u8 type;
- u8 length;
- u16 handle;
-} DMIHeader;
+static inline char *i8k_get_dmi_data(int field)
+{
+ return dmi_get_system_info(field) ? : "N/A";
+}
/*
* Call the System Management Mode BIOS. Code provided by Jonathan Buzzard.
*/
-static int i8k_smm(SMMRegisters *regs)
+static int i8k_smm(struct smm_regs *regs)
{
- int rc;
- int eax = regs->eax;
-
- asm("pushl %%eax\n\t" \
- "movl 0(%%eax),%%edx\n\t" \
- "push %%edx\n\t" \
- "movl 4(%%eax),%%ebx\n\t" \
- "movl 8(%%eax),%%ecx\n\t" \
- "movl 12(%%eax),%%edx\n\t" \
- "movl 16(%%eax),%%esi\n\t" \
- "movl 20(%%eax),%%edi\n\t" \
- "popl %%eax\n\t" \
- "out %%al,$0xb2\n\t" \
- "out %%al,$0x84\n\t" \
- "xchgl %%eax,(%%esp)\n\t"
- "movl %%ebx,4(%%eax)\n\t" \
- "movl %%ecx,8(%%eax)\n\t" \
- "movl %%edx,12(%%eax)\n\t" \
- "movl %%esi,16(%%eax)\n\t" \
- "movl %%edi,20(%%eax)\n\t" \
- "popl %%edx\n\t" \
- "movl %%edx,0(%%eax)\n\t" \
- "lahf\n\t" \
- "shrl $8,%%eax\n\t" \
- "andl $1,%%eax\n" \
- : "=a" (rc)
- : "a" (regs)
- : "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
-
- if ((rc != 0) || ((regs->eax & 0xffff) == 0xffff) || (regs->eax == eax)) {
- return -EINVAL;
- }
-
- return 0;
+ int rc;
+ int eax = regs->eax;
+
+ asm("pushl %%eax\n\t"
+ "movl 0(%%eax),%%edx\n\t"
+ "push %%edx\n\t"
+ "movl 4(%%eax),%%ebx\n\t"
+ "movl 8(%%eax),%%ecx\n\t"
+ "movl 12(%%eax),%%edx\n\t"
+ "movl 16(%%eax),%%esi\n\t"
+ "movl 20(%%eax),%%edi\n\t"
+ "popl %%eax\n\t"
+ "out %%al,$0xb2\n\t"
+ "out %%al,$0x84\n\t"
+ "xchgl %%eax,(%%esp)\n\t"
+ "movl %%ebx,4(%%eax)\n\t"
+ "movl %%ecx,8(%%eax)\n\t"
+ "movl %%edx,12(%%eax)\n\t"
+ "movl %%esi,16(%%eax)\n\t"
+ "movl %%edi,20(%%eax)\n\t"
+ "popl %%edx\n\t"
+ "movl %%edx,0(%%eax)\n\t"
+ "lahf\n\t"
+ "shrl $8,%%eax\n\t"
+ "andl $1,%%eax\n":"=a"(rc)
+ : "a"(regs)
+ : "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
+
+ if (rc != 0 || (regs->eax & 0xffff) == 0xffff || regs->eax == eax)
+ return -EINVAL;
+
+ return 0;
}
/*
@@ -152,24 +147,9 @@ static int i8k_smm(SMMRegisters *regs)
*/
static int i8k_get_bios_version(void)
{
- SMMRegisters regs = { 0, 0, 0, 0, 0, 0 };
- int rc;
-
- regs.eax = I8K_SMM_BIOS_VERSION;
- if ((rc=i8k_smm(&regs)) < 0) {
- return rc;
- }
-
- return regs.eax;
-}
+ struct smm_regs regs = { .eax = I8K_SMM_BIOS_VERSION, };
-/*
- * Read the machine id.
- */
-static int i8k_get_serial_number(unsigned char *buff)
-{
- strlcpy(buff, serial_number, sizeof(serial_number));
- return 0;
+ return i8k_smm(&regs) ? : regs.eax;
}
/*
@@ -177,24 +157,22 @@ static int i8k_get_serial_number(unsigned char *buff)
*/
static int i8k_get_fn_status(void)
{
- SMMRegisters regs = { 0, 0, 0, 0, 0, 0 };
- int rc;
-
- regs.eax = I8K_SMM_FN_STATUS;
- if ((rc=i8k_smm(&regs)) < 0) {
- return rc;
- }
-
- switch ((regs.eax >> I8K_FN_SHIFT) & I8K_FN_MASK) {
- case I8K_FN_UP:
- return I8K_VOL_UP;
- case I8K_FN_DOWN:
- return I8K_VOL_DOWN;
- case I8K_FN_MUTE:
- return I8K_VOL_MUTE;
- default:
- return 0;
- }
+ struct smm_regs regs = { .eax = I8K_SMM_FN_STATUS, };
+ int rc;
+
+ if ((rc = i8k_smm(&regs)) < 0)
+ return rc;
+
+ switch ((regs.eax >> I8K_FN_SHIFT) & I8K_FN_MASK) {
+ case I8K_FN_UP:
+ return I8K_VOL_UP;
+ case I8K_FN_DOWN:
+ return I8K_VOL_DOWN;
+ case I8K_FN_MUTE:
+ return I8K_VOL_MUTE;
+ default:
+ return 0;
+ }
}
/*
@@ -202,20 +180,13 @@ static int i8k_get_fn_status(void)
*/
static int i8k_get_power_status(void)
{
- SMMRegisters regs = { 0, 0, 0, 0, 0, 0 };
- int rc;
-
- regs.eax = I8K_SMM_POWER_STATUS;
- if ((rc=i8k_smm(&regs)) < 0) {
- return rc;
- }
-
- switch (regs.eax & 0xff) {
- case I8K_POWER_AC:
- return I8K_AC;
- default:
- return I8K_BATTERY;
- }
+ struct smm_regs regs = { .eax = I8K_SMM_POWER_STATUS, };
+ int rc;
+
+ if ((rc = i8k_smm(&regs)) < 0)
+ return rc;
+
+ return (regs.eax & 0xff) == I8K_POWER_AC ? I8K_AC : I8K_BATTERY;
}
/*
@@ -223,16 +194,10 @@ static int i8k_get_power_status(void)
*/
static int i8k_get_fan_status(int fan)
{
- SMMRegisters regs = { 0, 0, 0, 0, 0, 0 };
- int rc;
-
- regs.eax = I8K_SMM_GET_FAN;
- regs.ebx = fan & 0xff;
- if ((rc=i8k_smm(&regs)) < 0) {
- return rc;
- }
+ struct smm_regs regs = { .eax = I8K_SMM_GET_FAN, };
- return (regs.eax & 0xff);
+ regs.ebx = fan & 0xff;
+ return i8k_smm(&regs) ? : regs.eax & 0xff;
}
/*
@@ -240,16 +205,10 @@ static int i8k_get_fan_status(int fan)
*/
static int i8k_get_fan_speed(int fan)
{
- SMMRegisters regs = { 0, 0, 0, 0, 0, 0 };
- int rc;
+ struct smm_regs regs = { .eax = I8K_SMM_GET_SPEED, };
- regs.eax = I8K_SMM_GET_SPEED;
- regs.ebx = fan & 0xff;
- if ((rc=i8k_smm(&regs)) < 0) {
- return rc;
- }
-
- return (regs.eax & 0xffff) * I8K_FAN_MULT;
+ regs.ebx = fan & 0xff;
+ return i8k_smm(&regs) ? : (regs.eax & 0xffff) * I8K_FAN_MULT;
}
/*
@@ -257,532 +216,318 @@ static int i8k_get_fan_speed(int fan)
*/
static int i8k_set_fan(int fan, int speed)
{
- SMMRegisters regs = { 0, 0, 0, 0, 0, 0 };
- int rc;
-
- speed = (speed < 0) ? 0 : ((speed > I8K_FAN_MAX) ? I8K_FAN_MAX : speed);
+ struct smm_regs regs = { .eax = I8K_SMM_SET_FAN, };
- regs.eax = I8K_SMM_SET_FAN;
- regs.ebx = (fan & 0xff) | (speed << 8);
- if ((rc=i8k_smm(&regs)) < 0) {
- return rc;
- }
+ speed = (speed < 0) ? 0 : ((speed > I8K_FAN_MAX) ? I8K_FAN_MAX : speed);
+ regs.ebx = (fan & 0xff) | (speed << 8);
- return (i8k_get_fan_status(fan));
+ return i8k_smm(&regs) ? : i8k_get_fan_status(fan);
}
/*
* Read the cpu temperature.
*/
-static int i8k_get_cpu_temp(void)
+static int i8k_get_temp(int sensor)
{
- SMMRegisters regs = { 0, 0, 0, 0, 0, 0 };
- int rc;
- int temp;
+ struct smm_regs regs = { .eax = I8K_SMM_GET_TEMP, };
+ int rc;
+ int temp;
#ifdef I8K_TEMPERATURE_BUG
- static int prev = 0;
+ static int prev;
#endif
+ regs.ebx = sensor & 0xff;
+ if ((rc = i8k_smm(&regs)) < 0)
+ return rc;
- regs.eax = I8K_SMM_GET_TEMP;
- if ((rc=i8k_smm(&regs)) < 0) {
- return rc;
- }
- temp = regs.eax & 0xff;
+ temp = regs.eax & 0xff;
#ifdef I8K_TEMPERATURE_BUG
- /*
- * Sometimes the temperature sensor returns 0x99, which is out of range.
- * In this case we return (once) the previous cached value. For example:
- # 1003655137 00000058 00005a4b
- # 1003655138 00000099 00003a80 <--- 0x99 = 153 degrees
- # 1003655139 00000054 00005c52
- */
- if (temp > I8K_MAX_TEMP) {
- temp = prev;
- prev = I8K_MAX_TEMP;
- } else {
- prev = temp;
- }
+ /*
+ * Sometimes the temperature sensor returns 0x99, which is out of range.
+ * In this case we return (once) the previous cached value. For example:
+ # 1003655137 00000058 00005a4b
+ # 1003655138 00000099 00003a80 <--- 0x99 = 153 degrees
+ # 1003655139 00000054 00005c52
+ */
+ if (temp > I8K_MAX_TEMP) {
+ temp = prev;
+ prev = I8K_MAX_TEMP;
+ } else {
+ prev = temp;
+ }
#endif
- return temp;
+ return temp;
}
-static int i8k_get_dell_signature(void)
+static int i8k_get_dell_signature(int req_fn)
{
- SMMRegisters regs = { 0, 0, 0, 0, 0, 0 };
- int rc;
+ struct smm_regs regs = { .eax = req_fn, };
+ int rc;
- regs.eax = I8K_SMM_GET_DELL_SIG;
- if ((rc=i8k_smm(&regs)) < 0) {
- return rc;
- }
+ if ((rc = i8k_smm(&regs)) < 0)
+ return rc;
- if ((regs.eax == 1145651527) && (regs.edx == 1145392204)) {
- return 0;
- } else {
- return -1;
- }
+ return regs.eax == 1145651527 && regs.edx == 1145392204 ? 0 : -1;
}
static int i8k_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
unsigned long arg)
{
- int val;
- int speed;
- unsigned char buff[16];
- int __user *argp = (int __user *)arg;
-
- if (!argp)
- return -EINVAL;
-
- switch (cmd) {
- case I8K_BIOS_VERSION:
- val = i8k_get_bios_version();
- break;
-
- case I8K_MACHINE_ID:
- memset(buff, 0, 16);
- val = i8k_get_serial_number(buff);
- break;
-
- case I8K_FN_STATUS:
- val = i8k_get_fn_status();
- break;
-
- case I8K_POWER_STATUS:
- val = i8k_get_power_status();
- break;
-
- case I8K_GET_TEMP:
- val = i8k_get_cpu_temp();
- break;
-
- case I8K_GET_SPEED:
- if (copy_from_user(&val, argp, sizeof(int))) {
- return -EFAULT;
- }
- val = i8k_get_fan_speed(val);
- break;
-
- case I8K_GET_FAN:
- if (copy_from_user(&val, argp, sizeof(int))) {
- return -EFAULT;
- }
- val = i8k_get_fan_status(val);
- break;
+ int val = 0;
+ int speed;
+ unsigned char buff[16];
+ int __user *argp = (int __user *)arg;
- case I8K_SET_FAN:
- if (restricted && !capable(CAP_SYS_ADMIN)) {
- return -EPERM;
- }
- if (copy_from_user(&val, argp, sizeof(int))) {
- return -EFAULT;
- }
- if (copy_from_user(&speed, argp+1, sizeof(int))) {
- return -EFAULT;
- }
- val = i8k_set_fan(val, speed);
- break;
+ if (!argp)
+ return -EINVAL;
- default:
- return -EINVAL;
- }
+ switch (cmd) {
+ case I8K_BIOS_VERSION:
+ val = i8k_get_bios_version();
+ break;
- if (val < 0) {
- return val;
- }
+ case I8K_MACHINE_ID:
+ memset(buff, 0, 16);
+ strlcpy(buff, i8k_get_dmi_data(DMI_PRODUCT_SERIAL), sizeof(buff));
+ break;
- switch (cmd) {
- case I8K_BIOS_VERSION:
- if (copy_to_user(argp, &val, 4)) {
- return -EFAULT;
- }
- break;
- case I8K_MACHINE_ID:
- if (copy_to_user(argp, buff, 16)) {
- return -EFAULT;
- }
- break;
- default:
- if (copy_to_user(argp, &val, sizeof(int))) {
- return -EFAULT;
- }
- break;
- }
+ case I8K_FN_STATUS:
+ val = i8k_get_fn_status();
+ break;
- return 0;
-}
+ case I8K_POWER_STATUS:
+ val = i8k_get_power_status();
+ break;
-/*
- * Print the information for /proc/i8k.
- */
-static int i8k_get_info(char *buffer, char **start, off_t fpos, int length)
-{
- int n, fn_key, cpu_temp, ac_power;
- int left_fan, right_fan, left_speed, right_speed;
-
- cpu_temp = i8k_get_cpu_temp(); /* 11100 µs */
- left_fan = i8k_get_fan_status(I8K_FAN_LEFT); /* 580 µs */
- right_fan = i8k_get_fan_status(I8K_FAN_RIGHT); /* 580 µs */
- left_speed = i8k_get_fan_speed(I8K_FAN_LEFT); /* 580 µs */
- right_speed = i8k_get_fan_speed(I8K_FAN_RIGHT); /* 580 µs */
- fn_key = i8k_get_fn_status(); /* 750 µs */
- if (power_status) {
- ac_power = i8k_get_power_status(); /* 14700 µs */
- } else {
- ac_power = -1;
- }
-
- /*
- * Info:
- *
- * 1) Format version (this will change if format changes)
- * 2) BIOS version
- * 3) BIOS machine ID
- * 4) Cpu temperature
- * 5) Left fan status
- * 6) Right fan status
- * 7) Left fan speed
- * 8) Right fan speed
- * 9) AC power
- * 10) Fn Key status
- */
- n = sprintf(buffer, "%s %s %s %d %d %d %d %d %d %d\n",
- I8K_PROC_FMT,
- bios_version,
- serial_number,
- cpu_temp,
- left_fan,
- right_fan,
- left_speed,
- right_speed,
- ac_power,
- fn_key);
-
- return n;
-}
+ case I8K_GET_TEMP:
+ val = i8k_get_temp(0);
+ break;
-static ssize_t i8k_read(struct file *f, char __user *buffer, size_t len, loff_t *fpos)
-{
- int n;
- char info[128];
+ case I8K_GET_SPEED:
+ if (copy_from_user(&val, argp, sizeof(int)))
+ return -EFAULT;
- n = i8k_get_info(info, NULL, 0, 128);
- if (n <= 0) {
- return n;
- }
+ val = i8k_get_fan_speed(val);
+ break;
- if (*fpos >= n) {
- return 0;
- }
+ case I8K_GET_FAN:
+ if (copy_from_user(&val, argp, sizeof(int)))
+ return -EFAULT;
- if ((*fpos + len) >= n) {
- len = n - *fpos;
- }
+ val = i8k_get_fan_status(val);
+ break;
- if (copy_to_user(buffer, info, len) != 0) {
- return -EFAULT;
- }
+ case I8K_SET_FAN:
+ if (restricted && !capable(CAP_SYS_ADMIN))
+ return -EPERM;
- *fpos += len;
- return len;
-}
+ if (copy_from_user(&val, argp, sizeof(int)))
+ return -EFAULT;
-static char* __init string_trim(char *s, int size)
-{
- int len;
- char *p;
+ if (copy_from_user(&speed, argp + 1, sizeof(int)))
+ return -EFAULT;
- if ((len = strlen(s)) > size) {
- len = size;
- }
+ val = i8k_set_fan(val, speed);
+ break;
- for (p=s+len-1; len && (*p==' '); len--,p--) {
- *p = '\0';
- }
+ default:
+ return -EINVAL;
+ }
- return s;
-}
+ if (val < 0)
+ return val;
-/* DMI code, stolen from arch/i386/kernel/dmi_scan.c */
+ switch (cmd) {
+ case I8K_BIOS_VERSION:
+ if (copy_to_user(argp, &val, 4))
+ return -EFAULT;
-/*
- * |<-- dmi->length -->|
- * | |
- * |dmi header s=N | string1,\0, ..., stringN,\0, ..., \0
- * | |
- * +-----------------------+
- */
-static char* __init dmi_string(DMIHeader *dmi, u8 s)
-{
- u8 *p;
+ break;
+ case I8K_MACHINE_ID:
+ if (copy_to_user(argp, buff, 16))
+ return -EFAULT;
- if (!s) {
- return "";
- }
- s--;
+ break;
+ default:
+ if (copy_to_user(argp, &val, sizeof(int)))
+ return -EFAULT;
- p = (u8 *)dmi + dmi->length;
- while (s > 0) {
- p += strlen(p);
- p++;
- s--;
- }
+ break;
+ }
- return p;
+ return 0;
}
-static void __init dmi_decode(DMIHeader *dmi)
+/*
+ * Print the information for /proc/i8k.
+ */
+static int i8k_proc_show(struct seq_file *seq, void *offset)
{
- u8 *data = (u8 *) dmi;
- char *p;
-
-#ifdef I8K_DEBUG
- int i;
- printk("%08x ", (int)data);
- for (i=0; i<data[1] && i<64; i++) {
- printk("%02x ", data[i]);
- }
- printk("\n");
-#endif
-
- switch (dmi->type) {
- case 0: /* BIOS Information */
- p = dmi_string(dmi,data[5]);
- if (*p) {
- strlcpy(bios_version, p, sizeof(bios_version));
- string_trim(bios_version, sizeof(bios_version));
- }
- break;
- case 1: /* System Information */
- p = dmi_string(dmi,data[4]);
- if (*p) {
- strlcpy(system_vendor, p, sizeof(system_vendor));
- string_trim(system_vendor, sizeof(system_vendor));
- }
- p = dmi_string(dmi,data[5]);
- if (*p) {
- strlcpy(product_name, p, sizeof(product_name));
- string_trim(product_name, sizeof(product_name));
- }
- p = dmi_string(dmi,data[7]);
- if (*p) {
- strlcpy(serial_number, p, sizeof(serial_number));
- string_trim(serial_number, sizeof(serial_number));
- }
- break;
- }
-}
+ int fn_key, cpu_temp, ac_power;
+ int left_fan, right_fan, left_speed, right_speed;
+
+ cpu_temp = i8k_get_temp(0); /* 11100 µs */
+ left_fan = i8k_get_fan_status(I8K_FAN_LEFT); /* 580 µs */
+ right_fan = i8k_get_fan_status(I8K_FAN_RIGHT); /* 580 µs */
+ left_speed = i8k_get_fan_speed(I8K_FAN_LEFT); /* 580 µs */
+ right_speed = i8k_get_fan_speed(I8K_FAN_RIGHT); /* 580 µs */
+ fn_key = i8k_get_fn_status(); /* 750 µs */
+ if (power_status)
+ ac_power = i8k_get_power_status(); /* 14700 µs */
+ else
+ ac_power = -1;
-static int __init dmi_table(u32 base, int len, int num, void (*fn)(DMIHeader*))
-{
- u8 *buf;
- u8 *data;
- DMIHeader *dmi;
- int i = 1;
-
- buf = ioremap(base, len);
- if (buf == NULL) {
- return -1;
- }
- data = buf;
-
- /*
- * Stop when we see al the items the table claimed to have
- * or we run off the end of the table (also happens)
- */
- while ((i<num) && ((data-buf) < len)) {
- dmi = (DMIHeader *)data;
- /*
- * Avoid misparsing crud if the length of the last
- * record is crap
- */
- if ((data-buf+dmi->length) >= len) {
- break;
- }
- fn(dmi);
- data += dmi->length;
/*
- * Don't go off the end of the data if there is
- * stuff looking like string fill past the end
+ * Info:
+ *
+ * 1) Format version (this will change if format changes)
+ * 2) BIOS version
+ * 3) BIOS machine ID
+ * 4) Cpu temperature
+ * 5) Left fan status
+ * 6) Right fan status
+ * 7) Left fan speed
+ * 8) Right fan speed
+ * 9) AC power
+ * 10) Fn Key status
*/
- while (((data-buf) < len) && (*data || data[1])) {
- data++;
- }
- data += 2;
- i++;
- }
- iounmap(buf);
-
- return 0;
+ return seq_printf(seq, "%s %s %s %d %d %d %d %d %d %d\n",
+ I8K_PROC_FMT,
+ bios_version,
+ dmi_get_system_info(DMI_PRODUCT_SERIAL) ? : "N/A",
+ cpu_temp,
+ left_fan, right_fan, left_speed, right_speed,
+ ac_power, fn_key);
}
-static int __init dmi_iterate(void (*decode)(DMIHeader *))
+static int i8k_open_fs(struct inode *inode, struct file *file)
{
- unsigned char buf[20];
- void __iomem *p = ioremap(0xe0000, 0x20000), *q;
-
- if (!p)
- return -1;
-
- for (q = p; q < p + 0x20000; q += 16) {
- memcpy_fromio(buf, q, 20);
- if (memcmp(buf, "_DMI_", 5)==0) {
- u16 num = buf[13]<<8 | buf[12];
- u16 len = buf [7]<<8 | buf [6];
- u32 base = buf[11]<<24 | buf[10]<<16 | buf[9]<<8 | buf[8];
-#ifdef I8K_DEBUG
- printk(KERN_INFO "DMI %d.%d present.\n",
- buf[14]>>4, buf[14]&0x0F);
- printk(KERN_INFO "%d structures occupying %d bytes.\n",
- buf[13]<<8 | buf[12],
- buf [7]<<8 | buf[6]);
- printk(KERN_INFO "DMI table at 0x%08X.\n",
- buf[11]<<24 | buf[10]<<16 | buf[9]<<8 | buf[8]);
-#endif
- if (dmi_table(base, len, num, decode)==0) {
- iounmap(p);
- return 0;
- }
- }
- }
- iounmap(p);
- return -1;
+ return single_open(file, i8k_proc_show, NULL);
}
-/* end of DMI code */
-
-/*
- * Get DMI information.
- */
-static int __init i8k_dmi_probe(void)
-{
- char **p;
-
- if (dmi_iterate(dmi_decode) != 0) {
- printk(KERN_INFO "i8k: unable to get DMI information\n");
- return -ENODEV;
- }
-
- if (strncmp(system_vendor,DELL_SIGNATURE,strlen(DELL_SIGNATURE)) != 0) {
- printk(KERN_INFO "i8k: not running on a Dell system\n");
- return -ENODEV;
- }
-
- for (p=supported_models; ; p++) {
- if (!*p) {
- printk(KERN_INFO "i8k: unsupported model: %s\n", product_name);
- return -ENODEV;
- }
- if (strncmp(product_name,*p,strlen(*p)) == 0) {
- break;
- }
- }
- return 0;
-}
+static struct dmi_system_id __initdata i8k_dmi_table[] = {
+ {
+ .ident = "Dell Inspiron",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron"),
+ },
+ },
+ {
+ .ident = "Dell Latitude",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"),
+ },
+ },
+ {
+ .ident = "Dell Inspiron 2",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron"),
+ },
+ },
+ {
+ .ident = "Dell Latitude 2",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"),
+ },
+ },
+ { }
+};
/*
* Probe for the presence of a supported laptop.
*/
static int __init i8k_probe(void)
{
- char buff[4];
- int version;
- int smm_found = 0;
-
- /*
- * Get DMI information
- */
- if (i8k_dmi_probe() != 0) {
- printk(KERN_INFO "i8k: vendor=%s, model=%s, version=%s\n",
- system_vendor, product_name, bios_version);
- }
-
- /*
- * Get SMM Dell signature
- */
- if (i8k_get_dell_signature() != 0) {
- printk(KERN_INFO "i8k: unable to get SMM Dell signature\n");
- } else {
- smm_found = 1;
- }
-
- /*
- * Get SMM BIOS version.
- */
- version = i8k_get_bios_version();
- if (version <= 0) {
- printk(KERN_INFO "i8k: unable to get SMM BIOS version\n");
- } else {
- smm_found = 1;
- buff[0] = (version >> 16) & 0xff;
- buff[1] = (version >> 8) & 0xff;
- buff[2] = (version) & 0xff;
- buff[3] = '\0';
+ char buff[4];
+ int version;
+
/*
- * If DMI BIOS version is unknown use SMM BIOS version.
+ * Get DMI information
*/
- if (bios_version[0] == '?') {
- strcpy(bios_version, buff);
+ if (!dmi_check_system(i8k_dmi_table)) {
+ if (!ignore_dmi && !force)
+ return -ENODEV;
+
+ printk(KERN_INFO "i8k: not running on a supported Dell system.\n");
+ printk(KERN_INFO "i8k: vendor=%s, model=%s, version=%s\n",
+ i8k_get_dmi_data(DMI_SYS_VENDOR),
+ i8k_get_dmi_data(DMI_PRODUCT_NAME),
+ i8k_get_dmi_data(DMI_BIOS_VERSION));
}
+
+ strlcpy(bios_version, i8k_get_dmi_data(DMI_BIOS_VERSION), sizeof(bios_version));
+
/*
- * Check if the two versions match.
+ * Get SMM Dell signature
*/
- if (strncmp(buff,bios_version,sizeof(bios_version)) != 0) {
- printk(KERN_INFO "i8k: BIOS version mismatch: %s != %s\n",
- buff, bios_version);
+ if (i8k_get_dell_signature(I8K_SMM_GET_DELL_SIG1) &&
+ i8k_get_dell_signature(I8K_SMM_GET_DELL_SIG2)) {
+ printk(KERN_ERR "i8k: unable to get SMM Dell signature\n");
+ if (!force)
+ return -ENODEV;
}
- }
- if (!smm_found && !force) {
- return -ENODEV;
- }
+ /*
+ * Get SMM BIOS version.
+ */
+ version = i8k_get_bios_version();
+ if (version <= 0) {
+ printk(KERN_WARNING "i8k: unable to get SMM BIOS version\n");
+ } else {
+ buff[0] = (version >> 16) & 0xff;
+ buff[1] = (version >> 8) & 0xff;
+ buff[2] = (version) & 0xff;
+ buff[3] = '\0';
+ /*
+ * If DMI BIOS version is unknown use SMM BIOS version.
+ */
+ if (!dmi_get_system_info(DMI_BIOS_VERSION))
+ strlcpy(bios_version, buff, sizeof(bios_version));
+
+ /*
+ * Check if the two versions match.
+ */
+ if (strncmp(buff, bios_version, sizeof(bios_version)) != 0)
+ printk(KERN_WARNING "i8k: BIOS version mismatch: %s != %s\n",
+ buff, bios_version);
+ }
- return 0;
+ return 0;
}
-#ifdef MODULE
-static
-#endif
-int __init i8k_init(void)
+static int __init i8k_init(void)
{
- struct proc_dir_entry *proc_i8k;
-
- /* Are we running on an supported laptop? */
- if (i8k_probe() != 0) {
- return -ENODEV;
- }
-
- /* Register the proc entry */
- proc_i8k = create_proc_info_entry("i8k", 0, NULL, i8k_get_info);
- if (!proc_i8k) {
- return -ENOENT;
- }
- proc_i8k->proc_fops = &i8k_fops;
- proc_i8k->owner = THIS_MODULE;
-
- printk(KERN_INFO
- "Dell laptop SMM driver v%s Massimo Dal Zotto (dz@debian.org)\n",
- I8K_VERSION);
-
- return 0;
-}
+ struct proc_dir_entry *proc_i8k;
-#ifdef MODULE
-int init_module(void)
-{
- return i8k_init();
+ /* Are we running on an supported laptop? */
+ if (i8k_probe())
+ return -ENODEV;
+
+ /* Register the proc entry */
+ proc_i8k = create_proc_entry("i8k", 0, NULL);
+ if (!proc_i8k)
+ return -ENOENT;
+
+ proc_i8k->proc_fops = &i8k_fops;
+ proc_i8k->owner = THIS_MODULE;
+
+ printk(KERN_INFO
+ "Dell laptop SMM driver v%s Massimo Dal Zotto (dz@debian.org)\n",
+ I8K_VERSION);
+
+ return 0;
}
-void cleanup_module(void)
+static void __exit i8k_exit(void)
{
- /* Remove the proc entry */
- remove_proc_entry("i8k", NULL);
-
- printk(KERN_INFO "i8k: module unloaded\n");
+ remove_proc_entry("i8k", NULL);
}
-#endif
-/* end of file */
+module_init(i8k_init);
+module_exit(i8k_exit);
diff --git a/drivers/char/ip2/i2cmd.c b/drivers/char/ip2/i2cmd.c
index fd299d6c42a..cb8f4198e9a 100644
--- a/drivers/char/ip2/i2cmd.c
+++ b/drivers/char/ip2/i2cmd.c
@@ -97,7 +97,7 @@ static UCHAR ct41[] = { 1, BYP, 0x29 }; // RESUME
//static UCHAR ct44[]={ 2, BTH, 0x2C,0 }; // MS PING
//static UCHAR ct45[]={ 1, BTH, 0x2D }; // HOTENAB
//static UCHAR ct46[]={ 1, BTH, 0x2E }; // HOTDSAB
-static UCHAR ct47[] = { 7, BTH, 0x2F,0,0,0,0,0,0 }; // UNIX FLAGS
+//static UCHAR ct47[]={ 7, BTH, 0x2F,0,0,0,0,0,0 }; // UNIX FLAGS
//static UCHAR ct48[]={ 1, BTH, 0x30 }; // DSRFLOWENAB
//static UCHAR ct49[]={ 1, BTH, 0x31 }; // DSRFLOWDSAB
//static UCHAR ct50[]={ 1, BTH, 0x32 }; // DTRFLOWENAB
@@ -162,6 +162,7 @@ static UCHAR ct89[]={ 1, BYP, 0x59 }; // DSS_NOW
// This routine sets the parameters of command 47 and returns a pointer to the
// appropriate structure.
//******************************************************************************
+#if 0
cmdSyntaxPtr
i2cmdUnixFlags(unsigned short iflag,unsigned short cflag,unsigned short lflag)
{
@@ -175,6 +176,7 @@ i2cmdUnixFlags(unsigned short iflag,unsigned short cflag,unsigned short lflag)
pCM->cmd[6] = (unsigned char) (lflag >> 8);
return pCM;
}
+#endif /* 0 */
//******************************************************************************
// Function: i2cmdBaudDef(which, rate)
@@ -187,7 +189,7 @@ i2cmdUnixFlags(unsigned short iflag,unsigned short cflag,unsigned short lflag)
// This routine sets the parameters of commands 54 or 55 (according to the
// argument which), and returns a pointer to the appropriate structure.
//******************************************************************************
-cmdSyntaxPtr
+static cmdSyntaxPtr
i2cmdBaudDef(int which, unsigned short rate)
{
cmdSyntaxPtr pCM;
diff --git a/drivers/char/ip2/i2cmd.h b/drivers/char/ip2/i2cmd.h
index c41728a8571..baa4e721b75 100644
--- a/drivers/char/ip2/i2cmd.h
+++ b/drivers/char/ip2/i2cmd.h
@@ -64,16 +64,6 @@ typedef struct _cmdSyntax
// directly from user-level
#define VAR 0x10 // This command is of variable length!
-//-----------------------------------
-// External declarations for i2cmd.c
-//-----------------------------------
-// Routine to set up parameters for the "define hot-key sequence" command. Since
-// there is more than one parameter to assign, we must use a function rather
-// than a macro (used usually).
-//
-extern cmdSyntaxPtr i2cmdUnixFlags(USHORT iflag,USHORT cflag,USHORT lflag);
-extern cmdSyntaxPtr i2cmdBaudDef(int which, USHORT rate);
-
// Declarations for the global arrays used to bear the commands and their
// arguments.
//
@@ -433,6 +423,7 @@ static UCHAR cc02[];
#define CMD_HOT_ENAB (cmdSyntaxPtr)(ct45) // Enable Hot-key checking
#define CMD_HOT_DSAB (cmdSyntaxPtr)(ct46) // Disable Hot-key checking
+#if 0
// COMMAND 47: Send Protocol info via Unix flags:
// iflag = Unix tty t_iflag
// cflag = Unix tty t_cflag
@@ -441,6 +432,7 @@ static UCHAR cc02[];
// within these flags
//
#define CMD_UNIX_FLAGS(iflag,cflag,lflag) i2cmdUnixFlags(iflag,cflag,lflag)
+#endif /* 0 */
#define CMD_DSRFL_ENAB (cmdSyntaxPtr)(ct48) // Enable DSR receiver ctrl
#define CMD_DSRFL_DSAB (cmdSyntaxPtr)(ct49) // Disable DSR receiver ctrl
diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c
index fca9a978fb7..cf0cd58d630 100644
--- a/drivers/char/ip2main.c
+++ b/drivers/char/ip2main.c
@@ -302,7 +302,7 @@ static char rirqs[IP2_MAX_BOARDS];
static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0};
/* for sysfs class support */
-static struct class_simple *ip2_class;
+static struct class *ip2_class;
// Some functions to keep track of what irq's we have
@@ -414,9 +414,9 @@ cleanup_module(void)
iiResetDelay( i2BoardPtrTable[i] );
/* free io addresses and Tibet */
release_region( ip2config.addr[i], 8 );
- class_simple_device_remove(MKDEV(IP2_IPL_MAJOR, 4 * i));
+ class_device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i));
devfs_remove("ip2/ipl%d", i);
- class_simple_device_remove(MKDEV(IP2_IPL_MAJOR, 4 * i + 1));
+ class_device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i + 1));
devfs_remove("ip2/stat%d", i);
}
/* Disable and remove interrupt handler. */
@@ -425,7 +425,7 @@ cleanup_module(void)
clear_requested_irq( ip2config.irq[i]);
}
}
- class_simple_destroy(ip2_class);
+ class_destroy(ip2_class);
devfs_remove("ip2");
if ( ( err = tty_unregister_driver ( ip2_tty_driver ) ) ) {
printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", err);
@@ -700,7 +700,7 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", err );
} else {
/* create the sysfs class */
- ip2_class = class_simple_create(THIS_MODULE, "ip2");
+ ip2_class = class_create(THIS_MODULE, "ip2");
if (IS_ERR(ip2_class)) {
err = PTR_ERR(ip2_class);
goto out_chrdev;
@@ -722,25 +722,25 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
}
if ( NULL != ( pB = i2BoardPtrTable[i] ) ) {
- class_simple_device_add(ip2_class, MKDEV(IP2_IPL_MAJOR,
+ class_device_create(ip2_class, MKDEV(IP2_IPL_MAJOR,
4 * i), NULL, "ipl%d", i);
err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i),
S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
"ip2/ipl%d", i);
if (err) {
- class_simple_device_remove(MKDEV(IP2_IPL_MAJOR,
- 4 * i));
+ class_device_destroy(ip2_class,
+ MKDEV(IP2_IPL_MAJOR, 4 * i));
goto out_class;
}
- class_simple_device_add(ip2_class, MKDEV(IP2_IPL_MAJOR,
+ class_device_create(ip2_class, MKDEV(IP2_IPL_MAJOR,
4 * i + 1), NULL, "stat%d", i);
err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
"ip2/stat%d", i);
if (err) {
- class_simple_device_remove(MKDEV(IP2_IPL_MAJOR,
- 4 * i + 1));
+ class_device_destroy(ip2_class,
+ MKDEV(IP2_IPL_MAJOR, 4 * i + 1));
goto out_class;
}
@@ -798,7 +798,7 @@ retry:
goto out;
out_class:
- class_simple_destroy(ip2_class);
+ class_destroy(ip2_class);
out_chrdev:
unregister_chrdev(IP2_IPL_MAJOR, "ip2");
out:
@@ -2691,16 +2691,6 @@ no_xon:
pCh->flags |= ASYNC_CHECK_CD;
}
-#ifdef XXX
-do_flags_thing: // This is a test, we don't do the flags thing
-
- if ( (cflag & CRTSCTS) ) {
- cflag |= 014000000000;
- }
- i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1,
- CMD_UNIX_FLAGS(iflag,cflag,lflag));
-#endif
-
service_it:
i2DrainOutput( pCh, 100 );
}
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index 49d67f5384a..e0a53570fea 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -44,6 +44,8 @@
#include <linux/ipmi.h>
#include <asm/semaphore.h>
#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/compat.h>
#define IPMI_DEVINTF_VERSION "v33"
@@ -499,10 +501,205 @@ static int ipmi_ioctl(struct inode *inode,
return rv;
}
+#ifdef CONFIG_COMPAT
+
+/*
+ * The following code contains code for supporting 32-bit compatible
+ * ioctls on 64-bit kernels. This allows running 32-bit apps on the
+ * 64-bit kernel
+ */
+#define COMPAT_IPMICTL_SEND_COMMAND \
+ _IOR(IPMI_IOC_MAGIC, 13, struct compat_ipmi_req)
+#define COMPAT_IPMICTL_SEND_COMMAND_SETTIME \
+ _IOR(IPMI_IOC_MAGIC, 21, struct compat_ipmi_req_settime)
+#define COMPAT_IPMICTL_RECEIVE_MSG \
+ _IOWR(IPMI_IOC_MAGIC, 12, struct compat_ipmi_recv)
+#define COMPAT_IPMICTL_RECEIVE_MSG_TRUNC \
+ _IOWR(IPMI_IOC_MAGIC, 11, struct compat_ipmi_recv)
+
+struct compat_ipmi_msg {
+ u8 netfn;
+ u8 cmd;
+ u16 data_len;
+ compat_uptr_t data;
+};
+
+struct compat_ipmi_req {
+ compat_uptr_t addr;
+ compat_uint_t addr_len;
+ compat_long_t msgid;
+ struct compat_ipmi_msg msg;
+};
+
+struct compat_ipmi_recv {
+ compat_int_t recv_type;
+ compat_uptr_t addr;
+ compat_uint_t addr_len;
+ compat_long_t msgid;
+ struct compat_ipmi_msg msg;
+};
+
+struct compat_ipmi_req_settime {
+ struct compat_ipmi_req req;
+ compat_int_t retries;
+ compat_uint_t retry_time_ms;
+};
+
+/*
+ * Define some helper functions for copying IPMI data
+ */
+static long get_compat_ipmi_msg(struct ipmi_msg *p64,
+ struct compat_ipmi_msg __user *p32)
+{
+ compat_uptr_t tmp;
+
+ if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
+ __get_user(p64->netfn, &p32->netfn) ||
+ __get_user(p64->cmd, &p32->cmd) ||
+ __get_user(p64->data_len, &p32->data_len) ||
+ __get_user(tmp, &p32->data))
+ return -EFAULT;
+ p64->data = compat_ptr(tmp);
+ return 0;
+}
+
+static long put_compat_ipmi_msg(struct ipmi_msg *p64,
+ struct compat_ipmi_msg __user *p32)
+{
+ if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) ||
+ __put_user(p64->netfn, &p32->netfn) ||
+ __put_user(p64->cmd, &p32->cmd) ||
+ __put_user(p64->data_len, &p32->data_len))
+ return -EFAULT;
+ return 0;
+}
+
+static long get_compat_ipmi_req(struct ipmi_req *p64,
+ struct compat_ipmi_req __user *p32)
+{
+
+ compat_uptr_t tmp;
+
+ if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
+ __get_user(tmp, &p32->addr) ||
+ __get_user(p64->addr_len, &p32->addr_len) ||
+ __get_user(p64->msgid, &p32->msgid) ||
+ get_compat_ipmi_msg(&p64->msg, &p32->msg))
+ return -EFAULT;
+ p64->addr = compat_ptr(tmp);
+ return 0;
+}
+
+static long get_compat_ipmi_req_settime(struct ipmi_req_settime *p64,
+ struct compat_ipmi_req_settime __user *p32)
+{
+ if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
+ get_compat_ipmi_req(&p64->req, &p32->req) ||
+ __get_user(p64->retries, &p32->retries) ||
+ __get_user(p64->retry_time_ms, &p32->retry_time_ms))
+ return -EFAULT;
+ return 0;
+}
+
+static long get_compat_ipmi_recv(struct ipmi_recv *p64,
+ struct compat_ipmi_recv __user *p32)
+{
+ compat_uptr_t tmp;
+
+ if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
+ __get_user(p64->recv_type, &p32->recv_type) ||
+ __get_user(tmp, &p32->addr) ||
+ __get_user(p64->addr_len, &p32->addr_len) ||
+ __get_user(p64->msgid, &p32->msgid) ||
+ get_compat_ipmi_msg(&p64->msg, &p32->msg))
+ return -EFAULT;
+ p64->addr = compat_ptr(tmp);
+ return 0;
+}
+
+static long put_compat_ipmi_recv(struct ipmi_recv *p64,
+ struct compat_ipmi_recv __user *p32)
+{
+ if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) ||
+ __put_user(p64->recv_type, &p32->recv_type) ||
+ __put_user(p64->addr_len, &p32->addr_len) ||
+ __put_user(p64->msgid, &p32->msgid) ||
+ put_compat_ipmi_msg(&p64->msg, &p32->msg))
+ return -EFAULT;
+ return 0;
+}
+
+/*
+ * Handle compatibility ioctls
+ */
+static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
+ unsigned long arg)
+{
+ int rc;
+ struct ipmi_file_private *priv = filep->private_data;
+
+ switch(cmd) {
+ case COMPAT_IPMICTL_SEND_COMMAND:
+ {
+ struct ipmi_req rp;
+
+ if (get_compat_ipmi_req(&rp, compat_ptr(arg)))
+ return -EFAULT;
+
+ return handle_send_req(priv->user, &rp,
+ priv->default_retries,
+ priv->default_retry_time_ms);
+ }
+ case COMPAT_IPMICTL_SEND_COMMAND_SETTIME:
+ {
+ struct ipmi_req_settime sp;
+
+ if (get_compat_ipmi_req_settime(&sp, compat_ptr(arg)))
+ return -EFAULT;
+
+ return handle_send_req(priv->user, &sp.req,
+ sp.retries, sp.retry_time_ms);
+ }
+ case COMPAT_IPMICTL_RECEIVE_MSG:
+ case COMPAT_IPMICTL_RECEIVE_MSG_TRUNC:
+ {
+ struct ipmi_recv *precv64, recv64;
+
+ if (get_compat_ipmi_recv(&recv64, compat_ptr(arg)))
+ return -EFAULT;
+
+ precv64 = compat_alloc_user_space(sizeof(recv64));
+ if (copy_to_user(precv64, &recv64, sizeof(recv64)))
+ return -EFAULT;
+
+ rc = ipmi_ioctl(filep->f_dentry->d_inode, filep,
+ ((cmd == COMPAT_IPMICTL_RECEIVE_MSG)
+ ? IPMICTL_RECEIVE_MSG
+ : IPMICTL_RECEIVE_MSG_TRUNC),
+ (long) precv64);
+ if (rc != 0)
+ return rc;
+
+ if (copy_from_user(&recv64, precv64, sizeof(recv64)))
+ return -EFAULT;
+
+ if (put_compat_ipmi_recv(&recv64, compat_ptr(arg)))
+ return -EFAULT;
+
+ return rc;
+ }
+ default:
+ return ipmi_ioctl(filep->f_dentry->d_inode, filep, cmd, arg);
+ }
+}
+#endif
static struct file_operations ipmi_fops = {
.owner = THIS_MODULE,
.ioctl = ipmi_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = compat_ipmi_ioctl,
+#endif
.open = ipmi_open,
.release = ipmi_release,
.fasync = ipmi_fasync,
@@ -519,15 +716,21 @@ MODULE_PARM_DESC(ipmi_major, "Sets the major number of the IPMI device. By"
" interface. Other values will set the major device number"
" to that value.");
+static struct class *ipmi_class;
+
static void ipmi_new_smi(int if_num)
{
- devfs_mk_cdev(MKDEV(ipmi_major, if_num),
- S_IFCHR | S_IRUSR | S_IWUSR,
+ dev_t dev = MKDEV(ipmi_major, if_num);
+
+ devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR,
"ipmidev/%d", if_num);
+
+ class_device_create(ipmi_class, dev, NULL, "ipmi%d", if_num);
}
static void ipmi_smi_gone(int if_num)
{
+ class_device_destroy(ipmi_class, MKDEV(ipmi_major, if_num));
devfs_remove("ipmidev/%d", if_num);
}
@@ -548,8 +751,15 @@ static __init int init_ipmi_devintf(void)
printk(KERN_INFO "ipmi device interface version "
IPMI_DEVINTF_VERSION "\n");
+ ipmi_class = class_create(THIS_MODULE, "ipmi");
+ if (IS_ERR(ipmi_class)) {
+ printk(KERN_ERR "ipmi: can't register device class\n");
+ return PTR_ERR(ipmi_class);
+ }
+
rv = register_chrdev(ipmi_major, DEVICE_NAME, &ipmi_fops);
if (rv < 0) {
+ class_destroy(ipmi_class);
printk(KERN_ERR "ipmi: can't get major %d\n", ipmi_major);
return rv;
}
@@ -563,6 +773,7 @@ static __init int init_ipmi_devintf(void)
rv = ipmi_smi_watcher_register(&smi_watcher);
if (rv) {
unregister_chrdev(ipmi_major, DEVICE_NAME);
+ class_destroy(ipmi_class);
printk(KERN_WARNING "ipmi: can't register smi watcher\n");
return rv;
}
@@ -573,6 +784,7 @@ module_init(init_ipmi_devintf);
static __exit void cleanup_ipmi(void)
{
+ class_destroy(ipmi_class);
ipmi_smi_watcher_unregister(&smi_watcher);
devfs_remove(DEVICE_NAME);
unregister_chrdev(ipmi_major, DEVICE_NAME);
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index d7fb452af7f..1813d0d198f 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -54,7 +54,9 @@ static int ipmi_init_msghandler(void);
static int initialized = 0;
-static struct proc_dir_entry *proc_ipmi_root = NULL;
+#ifdef CONFIG_PROC_FS
+struct proc_dir_entry *proc_ipmi_root = NULL;
+#endif /* CONFIG_PROC_FS */
#define MAX_EVENTS_IN_QUEUE 25
@@ -124,11 +126,13 @@ struct ipmi_channel
unsigned char protocol;
};
+#ifdef CONFIG_PROC_FS
struct ipmi_proc_entry
{
char *name;
struct ipmi_proc_entry *next;
};
+#endif
#define IPMI_IPMB_NUM_SEQ 64
#define IPMI_MAX_CHANNELS 8
@@ -156,10 +160,13 @@ struct ipmi_smi
struct ipmi_smi_handlers *handlers;
void *send_info;
+#ifdef CONFIG_PROC_FS
/* A list of proc entries for this interface. This does not
need a lock, only one thread creates it and only one thread
destroys it. */
+ spinlock_t proc_entry_lock;
struct ipmi_proc_entry *proc_entries;
+#endif
/* A table of sequence numbers for this interface. We use the
sequence numbers for IPMB messages that go out of the
@@ -641,7 +648,7 @@ int ipmi_create_user(unsigned int if_num,
return -ENOMEM;
down_read(&interfaces_sem);
- if ((if_num > MAX_IPMI_INTERFACES) || ipmi_interfaces[if_num] == NULL)
+ if ((if_num >= MAX_IPMI_INTERFACES) || ipmi_interfaces[if_num] == NULL)
{
rv = -EINVAL;
goto out_unlock;
@@ -1470,8 +1477,9 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
read_proc_t *read_proc, write_proc_t *write_proc,
void *data, struct module *owner)
{
- struct proc_dir_entry *file;
int rv = 0;
+#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *file;
struct ipmi_proc_entry *entry;
/* Create a list element. */
@@ -1497,10 +1505,13 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
file->write_proc = write_proc;
file->owner = owner;
+ spin_lock(&smi->proc_entry_lock);
/* Stick it on the list. */
entry->next = smi->proc_entries;
smi->proc_entries = entry;
+ spin_unlock(&smi->proc_entry_lock);
}
+#endif /* CONFIG_PROC_FS */
return rv;
}
@@ -1509,6 +1520,7 @@ static int add_proc_entries(ipmi_smi_t smi, int num)
{
int rv = 0;
+#ifdef CONFIG_PROC_FS
sprintf(smi->proc_dir_name, "%d", num);
smi->proc_dir = proc_mkdir(smi->proc_dir_name, proc_ipmi_root);
if (!smi->proc_dir)
@@ -1531,14 +1543,17 @@ static int add_proc_entries(ipmi_smi_t smi, int num)
rv = ipmi_smi_add_proc_entry(smi, "version",
version_file_read_proc, NULL,
smi, THIS_MODULE);
+#endif /* CONFIG_PROC_FS */
return rv;
}
static void remove_proc_entries(ipmi_smi_t smi)
{
+#ifdef CONFIG_PROC_FS
struct ipmi_proc_entry *entry;
+ spin_lock(&smi->proc_entry_lock);
while (smi->proc_entries) {
entry = smi->proc_entries;
smi->proc_entries = entry->next;
@@ -1547,7 +1562,9 @@ static void remove_proc_entries(ipmi_smi_t smi)
kfree(entry->name);
kfree(entry);
}
+ spin_unlock(&smi->proc_entry_lock);
remove_proc_entry(smi->proc_dir_name, proc_ipmi_root);
+#endif /* CONFIG_PROC_FS */
}
static int
@@ -1694,6 +1711,9 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
new_intf->seq_table[j].seqid = 0;
}
new_intf->curr_seq = 0;
+#ifdef CONFIG_PROC_FS
+ spin_lock_init(&(new_intf->proc_entry_lock));
+#endif
spin_lock_init(&(new_intf->waiting_msgs_lock));
INIT_LIST_HEAD(&(new_intf->waiting_msgs));
spin_lock_init(&(new_intf->events_lock));
@@ -2747,16 +2767,13 @@ static struct timer_list ipmi_timer;
the queue and this silliness can go away. */
#define IPMI_REQUEST_EV_TIME (1000 / (IPMI_TIMEOUT_TIME))
-static volatile int stop_operation = 0;
-static volatile int timer_stopped = 0;
+static atomic_t stop_operation;
static unsigned int ticks_to_req_ev = IPMI_REQUEST_EV_TIME;
static void ipmi_timeout(unsigned long data)
{
- if (stop_operation) {
- timer_stopped = 1;
+ if (atomic_read(&stop_operation))
return;
- }
ticks_to_req_ev--;
if (ticks_to_req_ev == 0) {
@@ -2766,8 +2783,7 @@ static void ipmi_timeout(unsigned long data)
ipmi_timeout_handler(IPMI_TIMEOUT_TIME);
- ipmi_timer.expires += IPMI_TIMEOUT_JIFFIES;
- add_timer(&ipmi_timer);
+ mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES);
}
@@ -3089,6 +3105,7 @@ static int ipmi_init_msghandler(void)
ipmi_interfaces[i] = NULL;
}
+#ifdef CONFIG_PROC_FS
proc_ipmi_root = proc_mkdir("ipmi", NULL);
if (!proc_ipmi_root) {
printk(KERN_ERR PFX "Unable to create IPMI proc dir");
@@ -3096,6 +3113,7 @@ static int ipmi_init_msghandler(void)
}
proc_ipmi_root->owner = THIS_MODULE;
+#endif /* CONFIG_PROC_FS */
init_timer(&ipmi_timer);
ipmi_timer.data = 0;
@@ -3130,13 +3148,12 @@ static __exit void cleanup_ipmi(void)
/* Tell the timer to stop, then wait for it to stop. This avoids
problems with race conditions removing the timer here. */
- stop_operation = 1;
- while (!timer_stopped) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
- }
+ atomic_inc(&stop_operation);
+ del_timer_sync(&ipmi_timer);
+#ifdef CONFIG_PROC_FS
remove_proc_entry(proc_ipmi_root->name, &proc_root);
+#endif /* CONFIG_PROC_FS */
initialized = 0;
@@ -3177,4 +3194,5 @@ EXPORT_SYMBOL(ipmi_get_my_address);
EXPORT_SYMBOL(ipmi_set_my_LUN);
EXPORT_SYMBOL(ipmi_get_my_LUN);
EXPORT_SYMBOL(ipmi_smi_add_proc_entry);
+EXPORT_SYMBOL(proc_ipmi_root);
EXPORT_SYMBOL(ipmi_user_set_run_to_completion);
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
index cb5cdc6f14b..f951c30236c 100644
--- a/drivers/char/ipmi/ipmi_poweroff.c
+++ b/drivers/char/ipmi/ipmi_poweroff.c
@@ -31,10 +31,13 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <asm/semaphore.h>
-#include <linux/kdev_t.h>
+#include <linux/config.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/proc_fs.h>
#include <linux/string.h>
+#include <linux/completion.h>
+#include <linux/kdev_t.h>
#include <linux/ipmi.h>
#include <linux/ipmi_smi.h>
@@ -44,6 +47,18 @@
/* Where to we insert our poweroff function? */
extern void (*pm_power_off)(void);
+/* Definitions for controlling power off (if the system supports it). It
+ * conveniently matches the IPMI chassis control values. */
+#define IPMI_CHASSIS_POWER_DOWN 0 /* power down, the default. */
+#define IPMI_CHASSIS_POWER_CYCLE 0x02 /* power cycle */
+
+/* the IPMI data command */
+static int poweroff_control = IPMI_CHASSIS_POWER_DOWN;
+
+/* parameter definition to allow user to flag power cycle */
+module_param(poweroff_control, int, IPMI_CHASSIS_POWER_DOWN);
+MODULE_PARM_DESC(poweroff_control, " Set to 2 to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down.");
+
/* Stuff from the get device id command. */
static unsigned int mfg_id;
static unsigned int prod_id;
@@ -75,10 +90,10 @@ static struct ipmi_recv_msg halt_recv_msg =
static void receive_handler(struct ipmi_recv_msg *recv_msg, void *handler_data)
{
- struct semaphore *sem = recv_msg->user_msg_data;
+ struct completion *comp = recv_msg->user_msg_data;
- if (sem)
- up(sem);
+ if (comp)
+ complete(comp);
}
static struct ipmi_user_hndl ipmi_poweroff_handler =
@@ -91,27 +106,27 @@ static int ipmi_request_wait_for_response(ipmi_user_t user,
struct ipmi_addr *addr,
struct kernel_ipmi_msg *send_msg)
{
- int rv;
- struct semaphore sem;
+ int rv;
+ struct completion comp;
- sema_init (&sem, 0);
+ init_completion(&comp);
- rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, &sem,
+ rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, &comp,
&halt_smi_msg, &halt_recv_msg, 0);
if (rv)
return rv;
- down (&sem);
+ wait_for_completion(&comp);
return halt_recv_msg.msg.data[0];
}
-/* We are in run-to-completion mode, no semaphore is desired. */
+/* We are in run-to-completion mode, no completion is desired. */
static int ipmi_request_in_rc_mode(ipmi_user_t user,
struct ipmi_addr *addr,
struct kernel_ipmi_msg *send_msg)
{
- int rv;
+ int rv;
rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, NULL,
&halt_smi_msg, &halt_recv_msg, 0);
@@ -349,26 +364,38 @@ static void ipmi_poweroff_chassis (ipmi_user_t user)
smi_addr.channel = IPMI_BMC_CHANNEL;
smi_addr.lun = 0;
- printk(KERN_INFO PFX "Powering down via IPMI chassis control command\n");
+ powercyclefailed:
+ printk(KERN_INFO PFX "Powering %s via IPMI chassis control command\n",
+ ((poweroff_control != IPMI_CHASSIS_POWER_CYCLE) ? "down" : "cycle"));
/*
* Power down
*/
send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST;
send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD;
- data[0] = 0; /* Power down */
+ data[0] = poweroff_control;
send_msg.data = data;
send_msg.data_len = sizeof(data);
rv = ipmi_request_in_rc_mode(user,
(struct ipmi_addr *) &smi_addr,
&send_msg);
if (rv) {
- printk(KERN_ERR PFX "Unable to send chassis powerdown message,"
- " IPMI error 0x%x\n", rv);
- goto out;
+ switch (poweroff_control) {
+ case IPMI_CHASSIS_POWER_CYCLE:
+ /* power cycle failed, default to power down */
+ printk(KERN_ERR PFX "Unable to send chassis power " \
+ "cycle message, IPMI error 0x%x\n", rv);
+ poweroff_control = IPMI_CHASSIS_POWER_DOWN;
+ goto powercyclefailed;
+
+ case IPMI_CHASSIS_POWER_DOWN:
+ default:
+ printk(KERN_ERR PFX "Unable to send chassis power " \
+ "down message, IPMI error 0x%x\n", rv);
+ break;
+ }
}
- out:
return;
}
@@ -430,7 +457,8 @@ static void ipmi_po_new_smi(int if_num)
if (ready)
return;
- rv = ipmi_create_user(if_num, &ipmi_poweroff_handler, NULL, &ipmi_user);
+ rv = ipmi_create_user(if_num, &ipmi_poweroff_handler, NULL,
+ &ipmi_user);
if (rv) {
printk(KERN_ERR PFX "could not create IPMI user, error %d\n",
rv);
@@ -509,21 +537,84 @@ static struct ipmi_smi_watcher smi_watcher =
};
+#ifdef CONFIG_PROC_FS
+/* displays properties to proc */
+static int proc_read_chassctrl(char *page, char **start, off_t off, int count,
+ int *eof, void *data)
+{
+ return sprintf(page, "%d\t[ 0=powerdown 2=powercycle ]\n",
+ poweroff_control);
+}
+
+/* process property writes from proc */
+static int proc_write_chassctrl(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ int rv = count;
+ unsigned int newval = 0;
+
+ sscanf(buffer, "%d", &newval);
+ switch (newval) {
+ case IPMI_CHASSIS_POWER_CYCLE:
+ printk(KERN_INFO PFX "power cycle is now enabled\n");
+ poweroff_control = newval;
+ break;
+
+ case IPMI_CHASSIS_POWER_DOWN:
+ poweroff_control = IPMI_CHASSIS_POWER_DOWN;
+ break;
+
+ default:
+ rv = -EINVAL;
+ break;
+ }
+
+ return rv;
+}
+#endif /* CONFIG_PROC_FS */
+
/*
* Startup and shutdown functions.
*/
static int ipmi_poweroff_init (void)
{
- int rv;
+ int rv;
+ struct proc_dir_entry *file;
printk ("Copyright (C) 2004 MontaVista Software -"
" IPMI Powerdown via sys_reboot version "
IPMI_POWEROFF_VERSION ".\n");
+ switch (poweroff_control) {
+ case IPMI_CHASSIS_POWER_CYCLE:
+ printk(KERN_INFO PFX "Power cycle is enabled.\n");
+ break;
+
+ case IPMI_CHASSIS_POWER_DOWN:
+ default:
+ poweroff_control = IPMI_CHASSIS_POWER_DOWN;
+ break;
+ }
+
rv = ipmi_smi_watcher_register(&smi_watcher);
- if (rv)
+ if (rv) {
printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv);
+ goto out_err;
+ }
+
+#ifdef CONFIG_PROC_FS
+ file = create_proc_entry("poweroff_control", 0, proc_ipmi_root);
+ if (!file) {
+ printk(KERN_ERR PFX "Unable to create proc power control\n");
+ } else {
+ file->nlink = 1;
+ file->read_proc = proc_read_chassctrl;
+ file->write_proc = proc_write_chassctrl;
+ file->owner = THIS_MODULE;
+ }
+#endif
+ out_err:
return rv;
}
@@ -532,6 +623,10 @@ static __exit void ipmi_poweroff_cleanup(void)
{
int rv;
+#ifdef CONFIG_PROC_FS
+ remove_proc_entry("poweroff_control", proc_ipmi_root);
+#endif
+
ipmi_smi_watcher_unregister(&smi_watcher);
if (ready) {
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index 601c7fccb4c..1bbf507adda 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -1756,7 +1756,7 @@ static void isicom_flush_buffer(struct tty_struct * tty)
}
-static int __init register_ioregion(void)
+static int __devinit register_ioregion(void)
{
int count, done=0;
for (count=0; count < BOARD_COUNT; count++ ) {
@@ -1771,7 +1771,7 @@ static int __init register_ioregion(void)
return done;
}
-static void __exit unregister_ioregion(void)
+static void unregister_ioregion(void)
{
int count;
for (count=0; count < BOARD_COUNT; count++ )
@@ -1803,7 +1803,7 @@ static struct tty_operations isicom_ops = {
.tiocmset = isicom_tiocmset,
};
-static int __init register_drivers(void)
+static int __devinit register_drivers(void)
{
int error;
@@ -1834,7 +1834,7 @@ static int __init register_drivers(void)
return 0;
}
-static void __exit unregister_drivers(void)
+static void unregister_drivers(void)
{
int error = tty_unregister_driver(isicom_normal);
if (error)
@@ -1842,7 +1842,7 @@ static void __exit unregister_drivers(void)
put_tty_driver(isicom_normal);
}
-static int __init register_isr(void)
+static int __devinit register_isr(void)
{
int count, done=0;
unsigned long irqflags;
@@ -1883,7 +1883,7 @@ static void __exit unregister_isr(void)
}
}
-static int __init isicom_init(void)
+static int __devinit isicom_init(void)
{
int card, channel, base;
struct isi_port * port;
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 21aed0e8779..52a073eee20 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -407,7 +407,6 @@ static unsigned long stli_eisamemprobeaddrs[] = {
};
static int stli_eisamempsize = sizeof(stli_eisamemprobeaddrs) / sizeof(unsigned long);
-int stli_eisaprobe = STLI_EISAPROBE;
/*
* Define the Stallion PCI vendor and device IDs.
@@ -792,7 +791,7 @@ static int stli_timeron;
/*****************************************************************************/
-static struct class_simple *istallion_class;
+static struct class *istallion_class;
#ifdef MODULE
@@ -854,10 +853,10 @@ static void __exit istallion_module_exit(void)
put_tty_driver(stli_serial);
for (i = 0; i < 4; i++) {
devfs_remove("staliomem/%d", i);
- class_simple_device_remove(MKDEV(STL_SIOMEMMAJOR, i));
+ class_device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, i));
}
devfs_remove("staliomem");
- class_simple_destroy(istallion_class);
+ class_destroy(istallion_class);
if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
printk("STALLION: failed to un-register serial memory device, "
"errno=%d\n", -i);
@@ -4685,7 +4684,7 @@ static int stli_initbrds(void)
#ifdef MODULE
stli_argbrds();
#endif
- if (stli_eisaprobe)
+ if (STLI_EISAPROBE)
stli_findeisabrds();
#ifdef CONFIG_PCI
stli_findpcibrds();
@@ -5242,12 +5241,12 @@ int __init stli_init(void)
"device\n");
devfs_mk_dir("staliomem");
- istallion_class = class_simple_create(THIS_MODULE, "staliomem");
+ istallion_class = class_create(THIS_MODULE, "staliomem");
for (i = 0; i < 4; i++) {
devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i),
S_IFCHR | S_IRUSR | S_IWUSR,
"staliomem/%d", i);
- class_simple_device_add(istallion_class, MKDEV(STL_SIOMEMMAJOR, i),
+ class_device_create(istallion_class, MKDEV(STL_SIOMEMMAJOR, i),
NULL, "staliomem%d", i);
}
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 4dee945031d..59eebe5a035 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -146,7 +146,7 @@
static struct lp_struct lp_table[LP_NO];
static unsigned int lp_count = 0;
-static struct class_simple *lp_class;
+static struct class *lp_class;
#ifdef CONFIG_LP_CONSOLE
static struct parport *console_registered; // initially NULL
@@ -804,7 +804,7 @@ static int lp_register(int nr, struct parport *port)
if (reset)
lp_reset(nr);
- class_simple_device_add(lp_class, MKDEV(LP_MAJOR, nr), NULL,
+ class_device_create(lp_class, MKDEV(LP_MAJOR, nr), NULL,
"lp%d", nr);
devfs_mk_cdev(MKDEV(LP_MAJOR, nr), S_IFCHR | S_IRUGO | S_IWUGO,
"printers/%d", nr);
@@ -907,7 +907,7 @@ static int __init lp_init (void)
}
devfs_mk_dir("printers");
- lp_class = class_simple_create(THIS_MODULE, "printer");
+ lp_class = class_create(THIS_MODULE, "printer");
if (IS_ERR(lp_class)) {
err = PTR_ERR(lp_class);
goto out_devfs;
@@ -930,7 +930,7 @@ static int __init lp_init (void)
return 0;
out_class:
- class_simple_destroy(lp_class);
+ class_destroy(lp_class);
out_devfs:
devfs_remove("printers");
unregister_chrdev(LP_MAJOR, "lp");
@@ -981,10 +981,10 @@ static void lp_cleanup_module (void)
continue;
parport_unregister_device(lp_table[offset].dev);
devfs_remove("printers/%d", offset);
- class_simple_device_remove(MKDEV(LP_MAJOR, offset));
+ class_device_destroy(lp_class, MKDEV(LP_MAJOR, offset));
}
devfs_remove("printers");
- class_simple_destroy(lp_class);
+ class_destroy(lp_class);
}
__setup("lp=", lp_setup);
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c
index ac9cfa9701e..115dbb35334 100644
--- a/drivers/char/mbcs.c
+++ b/drivers/char/mbcs.c
@@ -699,7 +699,7 @@ static inline int mbcs_hw_init(struct mbcs_soft *soft)
return 0;
}
-static ssize_t show_algo(struct device *dev, char *buf)
+static ssize_t show_algo(struct device *dev, struct device_attribute *attr, char *buf)
{
struct cx_dev *cx_dev = to_cx_dev(dev);
struct mbcs_soft *soft = cx_dev->soft;
@@ -715,7 +715,7 @@ static ssize_t show_algo(struct device *dev, char *buf)
(debug0 >> 32), (debug0 & 0xffffffff));
}
-static ssize_t store_algo(struct device *dev, const char *buf, size_t count)
+static ssize_t store_algo(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int n;
struct cx_dev *cx_dev = to_cx_dev(dev);
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 947cb3cef81..42187381506 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -23,7 +23,10 @@
#include <linux/devfs_fs_kernel.h>
#include <linux/ptrace.h>
#include <linux/device.h>
+#include <linux/highmem.h>
+#include <linux/crash_dump.h>
#include <linux/backing-dev.h>
+#include <linux/bootmem.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -273,6 +276,40 @@ static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
return mmap_mem(file, vma);
}
+#ifdef CONFIG_CRASH_DUMP
+/*
+ * Read memory corresponding to the old kernel.
+ */
+static ssize_t read_oldmem(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned long pfn, offset;
+ size_t read = 0, csize;
+ int rc = 0;
+
+ while (count) {
+ pfn = *ppos / PAGE_SIZE;
+ if (pfn > saved_max_pfn)
+ return read;
+
+ offset = (unsigned long)(*ppos % PAGE_SIZE);
+ if (count > PAGE_SIZE - offset)
+ csize = PAGE_SIZE - offset;
+ else
+ csize = count;
+
+ rc = copy_oldmem_page(pfn, buf, csize, offset, 1);
+ if (rc < 0)
+ return rc;
+ buf += csize;
+ *ppos += csize;
+ read += csize;
+ count -= csize;
+ }
+ return read;
+}
+#endif
+
extern long vread(char *buf, char *addr, unsigned long count);
extern long vwrite(char *buf, char *addr, unsigned long count);
@@ -484,7 +521,7 @@ static ssize_t write_kmem(struct file * file, const char __user * buf,
return virtr + wrote;
}
-#if defined(CONFIG_ISA) || !defined(__mc68000__)
+#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
static ssize_t read_port(struct file * file, char __user * buf,
size_t count, loff_t *ppos)
{
@@ -721,6 +758,7 @@ static int open_port(struct inode * inode, struct file * filp)
#define read_full read_zero
#define open_mem open_port
#define open_kmem open_mem
+#define open_oldmem open_mem
static struct file_operations mem_fops = {
.llseek = memory_lseek,
@@ -744,7 +782,7 @@ static struct file_operations null_fops = {
.write = write_null,
};
-#if defined(CONFIG_ISA) || !defined(__mc68000__)
+#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
static struct file_operations port_fops = {
.llseek = memory_lseek,
.read = read_port,
@@ -770,6 +808,13 @@ static struct file_operations full_fops = {
.write = write_full,
};
+#ifdef CONFIG_CRASH_DUMP
+static struct file_operations oldmem_fops = {
+ .read = read_oldmem,
+ .open = open_oldmem,
+};
+#endif
+
static ssize_t kmsg_write(struct file * file, const char __user * buf,
size_t count, loff_t *ppos)
{
@@ -804,7 +849,7 @@ static int memory_open(struct inode * inode, struct file * filp)
case 3:
filp->f_op = &null_fops;
break;
-#if defined(CONFIG_ISA) || !defined(__mc68000__)
+#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
case 4:
filp->f_op = &port_fops;
break;
@@ -825,6 +870,11 @@ static int memory_open(struct inode * inode, struct file * filp)
case 11:
filp->f_op = &kmsg_fops;
break;
+#ifdef CONFIG_CRASH_DUMP
+ case 12:
+ filp->f_op = &oldmem_fops;
+ break;
+#endif
default:
return -ENXIO;
}
@@ -846,7 +896,7 @@ static const struct {
{1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops},
{2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops},
{3, "null", S_IRUGO | S_IWUGO, &null_fops},
-#if defined(CONFIG_ISA) || !defined(__mc68000__)
+#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
{4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops},
#endif
{5, "zero", S_IRUGO | S_IWUGO, &zero_fops},
@@ -854,9 +904,12 @@ static const struct {
{8, "random", S_IRUGO | S_IWUSR, &random_fops},
{9, "urandom", S_IRUGO | S_IWUSR, &urandom_fops},
{11,"kmsg", S_IRUGO | S_IWUSR, &kmsg_fops},
+#ifdef CONFIG_CRASH_DUMP
+ {12,"oldmem", S_IRUSR | S_IWUSR | S_IRGRP, &oldmem_fops},
+#endif
};
-static struct class_simple *mem_class;
+static struct class *mem_class;
static int __init chr_dev_init(void)
{
@@ -865,10 +918,9 @@ static int __init chr_dev_init(void)
if (register_chrdev(MEM_MAJOR,"mem",&memory_fops))
printk("unable to get major %d for memory devs\n", MEM_MAJOR);
- mem_class = class_simple_create(THIS_MODULE, "mem");
+ mem_class = class_create(THIS_MODULE, "mem");
for (i = 0; i < ARRAY_SIZE(devlist); i++) {
- class_simple_device_add(mem_class,
- MKDEV(MEM_MAJOR, devlist[i].minor),
+ class_device_create(mem_class, MKDEV(MEM_MAJOR, devlist[i].minor),
NULL, devlist[i].name);
devfs_mk_cdev(MKDEV(MEM_MAJOR, devlist[i].minor),
S_IFCHR | devlist[i].mode, devlist[i].name);
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 0937544762d..31cf84d6902 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -66,8 +66,6 @@ static unsigned char misc_minors[DYNAMIC_MINORS / 8];
extern int rtc_DP8570A_init(void);
extern int rtc_MK48T08_init(void);
extern int pmu_device_init(void);
-extern int tosh_init(void);
-extern int i8k_init(void);
#ifdef CONFIG_PROC_FS
static void *misc_seq_start(struct seq_file *seq, loff_t *pos)
@@ -177,10 +175,10 @@ fail:
/*
* TODO for 2.7:
- * - add a struct class_device to struct miscdevice and make all usages of
+ * - add a struct kref to struct miscdevice and make all usages of
* them dynamic.
*/
-static struct class_simple *misc_class;
+static struct class *misc_class;
static struct file_operations misc_fops = {
.owner = THIS_MODULE,
@@ -238,8 +236,8 @@ int misc_register(struct miscdevice * misc)
}
dev = MKDEV(MISC_MAJOR, misc->minor);
- misc->class = class_simple_device_add(misc_class, dev,
- misc->dev, misc->name);
+ misc->class = class_device_create(misc_class, dev, misc->dev,
+ "%s", misc->name);
if (IS_ERR(misc->class)) {
err = PTR_ERR(misc->class);
goto out;
@@ -248,7 +246,7 @@ int misc_register(struct miscdevice * misc)
err = devfs_mk_cdev(dev, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP,
misc->devfs_name);
if (err) {
- class_simple_device_remove(dev);
+ class_device_destroy(misc_class, dev);
goto out;
}
@@ -281,7 +279,7 @@ int misc_deregister(struct miscdevice * misc)
down(&misc_sem);
list_del(&misc->list);
- class_simple_device_remove(MKDEV(MISC_MAJOR, misc->minor));
+ class_device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
devfs_remove(misc->devfs_name);
if (i < DYNAMIC_MINORS && i>0) {
misc_minors[i>>3] &= ~(1 << (misc->minor & 7));
@@ -302,7 +300,7 @@ static int __init misc_init(void)
if (ent)
ent->proc_fops = &misc_proc_fops;
#endif
- misc_class = class_simple_create(THIS_MODULE, "misc");
+ misc_class = class_create(THIS_MODULE, "misc");
if (IS_ERR(misc_class))
return PTR_ERR(misc_class);
#ifdef CONFIG_MVME16x
@@ -314,16 +312,10 @@ static int __init misc_init(void)
#ifdef CONFIG_PMAC_PBOOK
pmu_device_init();
#endif
-#ifdef CONFIG_TOSHIBA
- tosh_init();
-#endif
-#ifdef CONFIG_I8K
- i8k_init();
-#endif
if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) {
printk("unable to get major %d for misc devices\n",
MISC_MAJOR);
- class_simple_destroy(misc_class);
+ class_destroy(misc_class);
return -EIO;
}
return 0;
diff --git a/drivers/char/mwave/3780i.c b/drivers/char/mwave/3780i.c
index ab00f51475d..613aed9e184 100644
--- a/drivers/char/mwave/3780i.c
+++ b/drivers/char/mwave/3780i.c
@@ -107,8 +107,8 @@ void dsp3780I_WriteMsaCfg(unsigned short usDspBaseIO,
spin_unlock_irqrestore(&dsp_lock, flags);
}
-void dsp3780I_WriteGenCfg(unsigned short usDspBaseIO, unsigned uIndex,
- unsigned char ucValue)
+static void dsp3780I_WriteGenCfg(unsigned short usDspBaseIO, unsigned uIndex,
+ unsigned char ucValue)
{
DSP_ISA_SLAVE_CONTROL rSlaveControl;
DSP_ISA_SLAVE_CONTROL rSlaveControl_Save;
@@ -141,6 +141,7 @@ void dsp3780I_WriteGenCfg(unsigned short usDspBaseIO, unsigned uIndex,
}
+#if 0
unsigned char dsp3780I_ReadGenCfg(unsigned short usDspBaseIO,
unsigned uIndex)
{
@@ -167,6 +168,7 @@ unsigned char dsp3780I_ReadGenCfg(unsigned short usDspBaseIO,
return ucValue;
}
+#endif /* 0 */
int dsp3780I_EnableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings,
unsigned short *pIrqMap,
diff --git a/drivers/char/mwave/3780i.h b/drivers/char/mwave/3780i.h
index 3e7d020d1bf..270431ca7da 100644
--- a/drivers/char/mwave/3780i.h
+++ b/drivers/char/mwave/3780i.h
@@ -338,10 +338,6 @@ unsigned short dsp3780I_ReadMsaCfg(unsigned short usDspBaseIO,
unsigned long ulMsaAddr);
void dsp3780I_WriteMsaCfg(unsigned short usDspBaseIO,
unsigned long ulMsaAddr, unsigned short usValue);
-void dsp3780I_WriteGenCfg(unsigned short usDspBaseIO, unsigned uIndex,
- unsigned char ucValue);
-unsigned char dsp3780I_ReadGenCfg(unsigned short usDspBaseIO,
- unsigned uIndex);
int dsp3780I_GetIPCSource(unsigned short usDspBaseIO,
unsigned short *pusIPCSource);
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c
index d37625d4774..d568991ac6b 100644
--- a/drivers/char/mwave/mwavedd.c
+++ b/drivers/char/mwave/mwavedd.c
@@ -472,7 +472,7 @@ struct device mwave_device;
/* Prevent code redundancy, create a macro for mwave_show_* functions. */
#define mwave_show_function(attr_name, format_string, field) \
-static ssize_t mwave_show_##attr_name(struct device *dev, char *buf) \
+static ssize_t mwave_show_##attr_name(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
DSP_3780I_CONFIG_SETTINGS *pSettings = \
&mwave_s_mdd.rBDData.rDspSettings; \
diff --git a/drivers/char/mwave/tp3780i.c b/drivers/char/mwave/tp3780i.c
index ab650cd6efc..d6c72e0934e 100644
--- a/drivers/char/mwave/tp3780i.c
+++ b/drivers/char/mwave/tp3780i.c
@@ -242,20 +242,14 @@ int tp3780I_ClaimResources(THINKPAD_BD_DATA * pBDData)
{
int retval = 0;
DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
struct resource *pres;
-#endif
PRINTK_2(TRACE_TP3780I,
"tp3780i::tp3780I_ClaimResources entry pBDData %p\n", pBDData);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
pres = request_region(pSettings->usDspBaseIO, 16, "mwave_3780i");
if ( pres == NULL ) retval = -EIO;
-#else
- retval = check_region(pSettings->usDspBaseIO, 16);
- if (!retval) request_region(pSettings->usDspBaseIO, 16, "mwave_3780i");
-#endif
+
if (retval) {
PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_ClaimResources: Error: Could not claim I/O region starting at %x\n", pSettings->usDspBaseIO);
retval = -EIO;
@@ -292,7 +286,7 @@ int tp3780I_ReleaseResources(THINKPAD_BD_DATA * pBDData)
int tp3780I_EnableDSP(THINKPAD_BD_DATA * pBDData)
{
DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
- BOOLEAN bDSPPoweredUp = FALSE, bDSPEnabled = FALSE, bInterruptAllocated = FALSE;
+ BOOLEAN bDSPPoweredUp = FALSE, bInterruptAllocated = FALSE;
PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_EnableDSP entry pBDData %p\n", pBDData);
@@ -397,8 +391,6 @@ int tp3780I_EnableDSP(THINKPAD_BD_DATA * pBDData)
if (dsp3780I_EnableDSP(pSettings, s_ausThinkpadIrqToField, s_ausThinkpadDmaToField)) {
PRINTK_ERROR("tp3780i::tp3780I_EnableDSP: Error: dsp7880I_EnableDSP() failed\n");
goto exit_cleanup;
- } else {
- bDSPEnabled = TRUE;
}
EnableSRAM(pBDData);
@@ -411,8 +403,6 @@ int tp3780I_EnableDSP(THINKPAD_BD_DATA * pBDData)
exit_cleanup:
PRINTK_ERROR("tp3780i::tp3780I_EnableDSP: Cleaning up\n");
- if (bDSPEnabled)
- dsp3780I_DisableDSP(pSettings);
if (bDSPPoweredUp)
smapi_set_DSP_power_state(FALSE);
if (bInterruptAllocated) {
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 7a245068e3e..f022f094443 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -1995,9 +1995,6 @@ static void mxser_receive_chars(struct mxser_struct *info, int *status)
unsigned char ch, gdl;
int ignored = 0;
int cnt = 0;
- unsigned char *cp;
- char *fp;
- int count;
int recv_room;
int max = 256;
unsigned long flags;
@@ -2011,10 +2008,6 @@ static void mxser_receive_chars(struct mxser_struct *info, int *status)
//return;
}
- cp = tty->flip.char_buf;
- fp = tty->flip.flag_buf;
- count = 0;
-
// following add by Victor Yu. 09-02-2002
if (info->IsMoxaMustChipFlag != MOXA_OTHER_UART) {
@@ -2041,12 +2034,10 @@ static void mxser_receive_chars(struct mxser_struct *info, int *status)
}
while (gdl--) {
ch = inb(info->base + UART_RX);
- count++;
- *cp++ = ch;
- *fp++ = 0;
+ tty_insert_flip_char(tty, ch, 0);
cnt++;
/*
- if((count>=HI_WATER) && (info->stop_rx==0)){
+ if((cnt>=HI_WATER) && (info->stop_rx==0)){
mxser_stoprx(tty);
info->stop_rx=1;
break;
@@ -2061,7 +2052,7 @@ intr_old:
if (max-- < 0)
break;
/*
- if((count>=HI_WATER) && (info->stop_rx==0)){
+ if((cnt>=HI_WATER) && (info->stop_rx==0)){
mxser_stoprx(tty);
info->stop_rx=1;
break;
@@ -2078,36 +2069,33 @@ intr_old:
if (++ignored > 100)
break;
} else {
- count++;
+ char flag = 0;
if (*status & UART_LSR_SPECIAL) {
if (*status & UART_LSR_BI) {
- *fp++ = TTY_BREAK;
+ flag = TTY_BREAK;
/* added by casper 1/11/2000 */
info->icount.brk++;
-
/* */
if (info->flags & ASYNC_SAK)
do_SAK(tty);
} else if (*status & UART_LSR_PE) {
- *fp++ = TTY_PARITY;
+ flag = TTY_PARITY;
/* added by casper 1/11/2000 */
info->icount.parity++;
/* */
} else if (*status & UART_LSR_FE) {
- *fp++ = TTY_FRAME;
+ flag = TTY_FRAME;
/* added by casper 1/11/2000 */
info->icount.frame++;
/* */
} else if (*status & UART_LSR_OE) {
- *fp++ = TTY_OVERRUN;
+ flag = TTY_OVERRUN;
/* added by casper 1/11/2000 */
info->icount.overrun++;
/* */
- } else
- *fp++ = 0;
- } else
- *fp++ = 0;
- *cp++ = ch;
+ }
+ }
+ tty_insert_flip_char(tty, ch, flag);
cnt++;
if (cnt >= recv_room) {
if (!info->ldisc_stop_rx) {
@@ -2132,13 +2120,13 @@ intr_old:
// above add by Victor Yu. 09-02-2002
} while (*status & UART_LSR_DR);
- end_intr: // add by Victor Yu. 09-02-2002
+end_intr: // add by Victor Yu. 09-02-2002
mxvar_log.rxcnt[info->port] += cnt;
info->mon_data.rxcnt += cnt;
info->mon_data.up_rxcnt += cnt;
spin_unlock_irqrestore(&info->slock, flags);
-
+
tty_flip_buffer_push(tty);
}
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c
index b3dbff1cf96..5079beda69b 100644
--- a/drivers/char/n_hdlc.c
+++ b/drivers/char/n_hdlc.c
@@ -960,7 +960,7 @@ static char hdlc_unregister_fail[] __exitdata =
static void __exit n_hdlc_exit(void)
{
/* Release tty registration of line discipline */
- int status = tty_register_ldisc(N_HDLC, NULL);
+ int status = tty_unregister_ldisc(N_HDLC);
if (status)
printk(hdlc_unregister_fail, status);
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
index 3883073ab48..2291a87e8ad 100644
--- a/drivers/char/n_r3964.c
+++ b/drivers/char/n_r3964.c
@@ -200,7 +200,7 @@ static void __exit r3964_exit(void)
TRACE_M ("cleanup_module()");
- status=tty_register_ldisc(N_R3964, NULL);
+ status=tty_unregister_ldisc(N_R3964);
if(status!=0)
{
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index f63a3fd7ca6..1af733d0732 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -211,12 +211,13 @@ nvram_check_checksum(void)
return rv;
}
-void
+static void
__nvram_set_checksum(void)
{
mach_set_checksum();
}
+#if 0
void
nvram_set_checksum(void)
{
@@ -226,6 +227,7 @@ nvram_set_checksum(void)
__nvram_set_checksum();
spin_unlock_irqrestore(&rtc_lock, flags);
}
+#endif /* 0 */
/*
* The are the file operation function for user access to /dev/nvram
@@ -921,6 +923,4 @@ EXPORT_SYMBOL(__nvram_write_byte);
EXPORT_SYMBOL(nvram_write_byte);
EXPORT_SYMBOL(__nvram_check_checksum);
EXPORT_SYMBOL(nvram_check_checksum);
-EXPORT_SYMBOL(__nvram_set_checksum);
-EXPORT_SYMBOL(nvram_set_checksum);
MODULE_ALIAS_MISCDEV(NVRAM_MINOR);
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index 5eda075c62b..0e22880432b 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -737,7 +737,7 @@ static unsigned int pp_poll (struct file * file, poll_table * wait)
return mask;
}
-static struct class_simple *ppdev_class;
+static struct class *ppdev_class;
static struct file_operations pp_fops = {
.owner = THIS_MODULE,
@@ -752,13 +752,13 @@ static struct file_operations pp_fops = {
static void pp_attach(struct parport *port)
{
- class_simple_device_add(ppdev_class, MKDEV(PP_MAJOR, port->number),
+ class_device_create(ppdev_class, MKDEV(PP_MAJOR, port->number),
NULL, "parport%d", port->number);
}
static void pp_detach(struct parport *port)
{
- class_simple_device_remove(MKDEV(PP_MAJOR, port->number));
+ class_device_destroy(ppdev_class, MKDEV(PP_MAJOR, port->number));
}
static struct parport_driver pp_driver = {
@@ -776,7 +776,7 @@ static int __init ppdev_init (void)
PP_MAJOR);
return -EIO;
}
- ppdev_class = class_simple_create(THIS_MODULE, CHRDEV);
+ ppdev_class = class_create(THIS_MODULE, CHRDEV);
if (IS_ERR(ppdev_class)) {
err = PTR_ERR(ppdev_class);
goto out_chrdev;
@@ -798,7 +798,7 @@ out_class:
for (i = 0; i < PARPORT_MAX; i++)
devfs_remove("parports/%d", i);
devfs_remove("parports");
- class_simple_destroy(ppdev_class);
+ class_destroy(ppdev_class);
out_chrdev:
unregister_chrdev(PP_MAJOR, CHRDEV);
out:
@@ -813,7 +813,7 @@ static void __exit ppdev_cleanup (void)
devfs_remove("parports/%d", i);
parport_unregister_driver(&pp_driver);
devfs_remove("parports");
- class_simple_destroy(ppdev_class);
+ class_destroy(ppdev_class);
unregister_chrdev (PP_MAJOR, CHRDEV);
}
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index a2e33ec7961..f13e5de0220 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -27,7 +27,7 @@ struct raw_device_data {
int inuse;
};
-static struct class_simple *raw_class;
+static struct class *raw_class;
static struct raw_device_data raw_devices[MAX_RAW_MINORS];
static DECLARE_MUTEX(raw_mutex);
static struct file_operations raw_ctl_fops; /* forward declaration */
@@ -122,13 +122,13 @@ raw_ioctl(struct inode *inode, struct file *filp,
{
struct block_device *bdev = filp->private_data;
- return ioctl_by_bdev(bdev, command, arg);
+ return blkdev_ioctl(bdev->bd_inode, NULL, command, arg);
}
static void bind_device(struct raw_config_request *rq)
{
- class_simple_device_remove(MKDEV(RAW_MAJOR, rq->raw_minor));
- class_simple_device_add(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor),
+ class_device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
+ class_device_create(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor),
NULL, "raw%d", rq->raw_minor);
}
@@ -200,8 +200,8 @@ static int raw_ctl_ioctl(struct inode *inode, struct file *filp,
if (rq.block_major == 0 && rq.block_minor == 0) {
/* unbind */
rawdev->binding = NULL;
- class_simple_device_remove(MKDEV(RAW_MAJOR,
- rq.raw_minor));
+ class_device_destroy(raw_class,
+ MKDEV(RAW_MAJOR, rq.raw_minor));
} else {
rawdev->binding = bdget(dev);
if (rawdev->binding == NULL)
@@ -300,14 +300,14 @@ static int __init raw_init(void)
goto error;
}
- raw_class = class_simple_create(THIS_MODULE, "raw");
+ raw_class = class_create(THIS_MODULE, "raw");
if (IS_ERR(raw_class)) {
printk(KERN_ERR "Error creating raw class.\n");
cdev_del(&raw_cdev);
unregister_chrdev_region(dev, MAX_RAW_MINORS);
goto error;
}
- class_simple_device_add(raw_class, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
+ class_device_create(raw_class, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
devfs_mk_cdev(MKDEV(RAW_MAJOR, 0),
S_IFCHR | S_IRUGO | S_IWUGO,
@@ -331,8 +331,8 @@ static void __exit raw_exit(void)
devfs_remove("raw/raw%d", i);
devfs_remove("raw/rawctl");
devfs_remove("raw");
- class_simple_device_remove(MKDEV(RAW_MAJOR, 0));
- class_simple_destroy(raw_class);
+ class_device_destroy(raw_class, MKDEV(RAW_MAJOR, 0));
+ class_destroy(raw_class);
cdev_del(&raw_cdev);
unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), MAX_RAW_MINORS);
}
diff --git a/drivers/char/rio/func.h b/drivers/char/rio/func.h
index e8f3860f472..01987c6dc39 100644
--- a/drivers/char/rio/func.h
+++ b/drivers/char/rio/func.h
@@ -147,7 +147,6 @@ struct rio_info * rio_info_store( int cmd, struct rio_info * p);
extern int rio_pcicopy(char *src, char *dst, int n);
extern int rio_minor (struct tty_struct *tty);
extern int rio_ismodem (struct tty_struct *tty);
-extern void rio_udelay (int usecs);
extern void rio_start_card_running (struct Host * HostP);
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
index 763893e289b..7db3370f497 100644
--- a/drivers/char/rio/rio_linux.c
+++ b/drivers/char/rio/rio_linux.c
@@ -354,11 +354,6 @@ int rio_ismodem(struct tty_struct *tty)
}
-void rio_udelay (int usecs)
-{
- udelay (usecs);
-}
-
static int rio_set_real_termios (void *ptr)
{
int rv, modem;
diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c
index dca941ed10c..898a126ae3e 100644
--- a/drivers/char/rio/rioinit.c
+++ b/drivers/char/rio/rioinit.c
@@ -37,6 +37,7 @@ static char *_rioinit_c_sccs_ = "@(#)rioinit.c 1.3";
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/errno.h>
+#include <linux/delay.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/string.h>
@@ -1560,14 +1561,14 @@ uint Slot;
INTERRUPT_DISABLE | BYTE_OPERATION |
SLOW_LINKS | SLOW_AT_BUS);
WBYTE(DpRamP->DpResetTpu, 0xFF);
- rio_udelay (3);
+ udelay(3);
rio_dprintk (RIO_DEBUG_INIT, "RIOHostReset: Don't know if it worked. Try reset again\n");
WBYTE(DpRamP->DpControl, BOOT_FROM_RAM | EXTERNAL_BUS_OFF |
INTERRUPT_DISABLE | BYTE_OPERATION |
SLOW_LINKS | SLOW_AT_BUS);
WBYTE(DpRamP->DpResetTpu, 0xFF);
- rio_udelay (3);
+ udelay(3);
break;
#ifdef FUTURE_RELEASE
case RIO_EISA:
@@ -1599,7 +1600,7 @@ uint Slot;
DpRamP->DpControl = RIO_PCI_BOOT_FROM_RAM;
DpRamP->DpResetInt = 0xFF;
DpRamP->DpResetTpu = 0xFF;
- rio_udelay (100);
+ udelay(100);
/* for (i=0; i<6000; i++); */
/* suspend( 3 ); */
break;
diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c
index db655002671..78a321afdf4 100644
--- a/drivers/char/rio/riotty.c
+++ b/drivers/char/rio/riotty.c
@@ -524,16 +524,16 @@ riotclose(void *ptr)
register uint SysPort = dev;
struct ttystatics *tp; /* pointer to our ttystruct */
#endif
- struct Port *PortP =ptr; /* pointer to the port structure */
+ struct Port *PortP = ptr; /* pointer to the port structure */
int deleted = 0;
int try = -1; /* Disable the timeouts by setting them to -1 */
int repeat_this = -1; /* Congrats to those having 15 years of
uptime! (You get to break the driver.) */
- long end_time;
+ unsigned long end_time;
struct tty_struct * tty;
unsigned long flags;
int Modem;
- int rv =0;
+ int rv = 0;
rio_dprintk (RIO_DEBUG_TTY, "port close SysPort %d\n",PortP->PortNum);
@@ -620,7 +620,7 @@ riotclose(void *ptr)
if (repeat_this -- <= 0) {
rv = -EINTR;
rio_dprintk (RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
- RIOPreemptiveCmd(p, PortP, FCLOSE );
+ RIOPreemptiveCmd(p, PortP, FCLOSE);
goto close_end;
}
rio_dprintk (RIO_DEBUG_TTY, "Calling timeout to flush in closing\n");
@@ -656,14 +656,12 @@ riotclose(void *ptr)
goto close_end;
}
-
-
/* Can't call RIOShortCommand with the port locked. */
rio_spin_unlock_irqrestore(&PortP->portSem, flags);
if (RIOShortCommand(p, PortP, CLOSE, 1, 0) == RIO_FAIL) {
- RIOPreemptiveCmd(p, PortP,FCLOSE);
- goto close_end;
+ RIOPreemptiveCmd(p, PortP, FCLOSE);
+ goto close_end;
}
if (!deleted)
@@ -698,7 +696,6 @@ riotclose(void *ptr)
*/
PortP->Config &= ~(RIO_CTSFLOW|RIO_RTSFLOW);
-
#ifdef STATS
PortP->Stat.CloseCnt++;
#endif
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index 5bcbeb0cb9a..f463d6baa68 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -161,6 +161,64 @@ static Word_t upci_aiop_intr_bits[AIOP_CTL_SIZE] = {
UPCI_AIOP_INTR_BIT_3
};
+static Byte_t RData[RDATASIZE] = {
+ 0x00, 0x09, 0xf6, 0x82,
+ 0x02, 0x09, 0x86, 0xfb,
+ 0x04, 0x09, 0x00, 0x0a,
+ 0x06, 0x09, 0x01, 0x0a,
+ 0x08, 0x09, 0x8a, 0x13,
+ 0x0a, 0x09, 0xc5, 0x11,
+ 0x0c, 0x09, 0x86, 0x85,
+ 0x0e, 0x09, 0x20, 0x0a,
+ 0x10, 0x09, 0x21, 0x0a,
+ 0x12, 0x09, 0x41, 0xff,
+ 0x14, 0x09, 0x82, 0x00,
+ 0x16, 0x09, 0x82, 0x7b,
+ 0x18, 0x09, 0x8a, 0x7d,
+ 0x1a, 0x09, 0x88, 0x81,
+ 0x1c, 0x09, 0x86, 0x7a,
+ 0x1e, 0x09, 0x84, 0x81,
+ 0x20, 0x09, 0x82, 0x7c,
+ 0x22, 0x09, 0x0a, 0x0a
+};
+
+static Byte_t RRegData[RREGDATASIZE] = {
+ 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */
+ 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */
+ 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */
+ 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */
+ 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */
+ 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */
+ 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */
+ 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */
+ 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */
+ 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */
+ 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */
+ 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */
+ 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */
+};
+
+static CONTROLLER_T sController[CTL_SIZE] = {
+ {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
+ {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
+ {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
+ {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
+ {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
+ {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
+ {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
+ {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}}
+};
+
+static Byte_t sBitMapClrTbl[8] = {
+ 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f
+};
+
+static Byte_t sBitMapSetTbl[8] = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
+};
+
+static int sClockPrescale = 0x14;
+
/*
* Line number is the ttySIx number (x), the Minor number. We
* assign them sequentially, starting at zero. The following
@@ -177,6 +235,26 @@ static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model);
static unsigned char GetLineNumber(int ctrl, int aiop, int ch);
static unsigned char SetLineNumber(int ctrl, int aiop, int ch);
static void rp_start(struct tty_struct *tty);
+static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
+ int ChanNum);
+static void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode);
+static void sFlushRxFIFO(CHANNEL_T * ChP);
+static void sFlushTxFIFO(CHANNEL_T * ChP);
+static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags);
+static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags);
+static void sModemReset(CONTROLLER_T * CtlP, int chan, int on);
+static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on);
+static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data);
+static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
+ ByteIO_t * AiopIOList, int AiopIOListSize,
+ WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
+ int PeriodicOnly, int altChanRingIndicator,
+ int UPCIRingInd);
+static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
+ ByteIO_t * AiopIOList, int AiopIOListSize,
+ int IRQNum, Byte_t Frequency, int PeriodicOnly);
+static int sReadAiopID(ByteIO_t io);
+static int sReadAiopNumChan(WordIO_t io);
#ifdef MODULE
MODULE_AUTHOR("Theodore Ts'o");
@@ -1798,7 +1876,7 @@ static void rp_flush_buffer(struct tty_struct *tty)
* init's aiopic and serial port hardware.
* Inputs: i is the board number (0-n)
*/
-__init int register_PCI(int i, struct pci_dev *dev)
+static __init int register_PCI(int i, struct pci_dev *dev)
{
int num_aiops, aiop, max_num_aiops, num_chan, chan;
unsigned int aiopio[MAX_AIOPS_PER_BOARD];
@@ -2453,72 +2531,6 @@ static void rp_cleanup_module(void)
}
#endif
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-static Byte_t RData[RDATASIZE] = {
- 0x00, 0x09, 0xf6, 0x82,
- 0x02, 0x09, 0x86, 0xfb,
- 0x04, 0x09, 0x00, 0x0a,
- 0x06, 0x09, 0x01, 0x0a,
- 0x08, 0x09, 0x8a, 0x13,
- 0x0a, 0x09, 0xc5, 0x11,
- 0x0c, 0x09, 0x86, 0x85,
- 0x0e, 0x09, 0x20, 0x0a,
- 0x10, 0x09, 0x21, 0x0a,
- 0x12, 0x09, 0x41, 0xff,
- 0x14, 0x09, 0x82, 0x00,
- 0x16, 0x09, 0x82, 0x7b,
- 0x18, 0x09, 0x8a, 0x7d,
- 0x1a, 0x09, 0x88, 0x81,
- 0x1c, 0x09, 0x86, 0x7a,
- 0x1e, 0x09, 0x84, 0x81,
- 0x20, 0x09, 0x82, 0x7c,
- 0x22, 0x09, 0x0a, 0x0a
-};
-
-static Byte_t RRegData[RREGDATASIZE] = {
- 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */
- 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */
- 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */
- 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */
- 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */
- 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */
- 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */
- 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */
- 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */
- 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */
- 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */
- 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */
- 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */
-};
-
-CONTROLLER_T sController[CTL_SIZE] = {
- {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
- {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
- {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
- {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
- {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
- {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
- {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
- {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}}
-};
-
-Byte_t sBitMapClrTbl[8] = {
- 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f
-};
-
-Byte_t sBitMapSetTbl[8] = {
- 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
-};
-
-int sClockPrescale = 0x14;
-
/***************************************************************************
Function: sInitController
Purpose: Initialization of controller global registers and controller
@@ -2554,22 +2566,22 @@ Call: sInitController(CtlP,CtlNum,MudbacIO,AiopIOList,AiopIOListSize,
FREQ_4HZ - 4 Hertz
If IRQNum is set to 0 the Frequency parameter is
overidden, it is forced to a value of FREQ_DIS.
- int PeriodicOnly: TRUE if all interrupts except the periodic
+ int PeriodicOnly: 1 if all interrupts except the periodic
interrupt are to be blocked.
- FALSE is both the periodic interrupt and
+ 0 is both the periodic interrupt and
other channel interrupts are allowed.
If IRQNum is set to 0 the PeriodicOnly parameter is
- overidden, it is forced to a value of FALSE.
+ overidden, it is forced to a value of 0.
Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller
initialization failed.
Comments:
If periodic interrupts are to be disabled but AIOP interrupts
- are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE.
+ are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0.
If interrupts are to be completely disabled set IRQNum to 0.
- Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an
+ Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an
invalid combination.
This function performs initialization of global interrupt modes,
@@ -2589,9 +2601,9 @@ Warnings: No range checking on any of the parameters is done.
After this function all AIOPs on the controller are disabled,
they can be enabled with sEnAiop().
*/
-int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
- ByteIO_t * AiopIOList, int AiopIOListSize, int IRQNum,
- Byte_t Frequency, int PeriodicOnly)
+static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
+ ByteIO_t * AiopIOList, int AiopIOListSize,
+ int IRQNum, Byte_t Frequency, int PeriodicOnly)
{
int i;
ByteIO_t io;
@@ -2687,22 +2699,22 @@ Call: sPCIInitController(CtlP,CtlNum,AiopIOList,AiopIOListSize,
FREQ_4HZ - 4 Hertz
If IRQNum is set to 0 the Frequency parameter is
overidden, it is forced to a value of FREQ_DIS.
- int PeriodicOnly: TRUE if all interrupts except the periodic
+ int PeriodicOnly: 1 if all interrupts except the periodic
interrupt are to be blocked.
- FALSE is both the periodic interrupt and
+ 0 is both the periodic interrupt and
other channel interrupts are allowed.
If IRQNum is set to 0 the PeriodicOnly parameter is
- overidden, it is forced to a value of FALSE.
+ overidden, it is forced to a value of 0.
Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller
initialization failed.
Comments:
If periodic interrupts are to be disabled but AIOP interrupts
- are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE.
+ are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0.
If interrupts are to be completely disabled set IRQNum to 0.
- Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an
+ Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an
invalid combination.
This function performs initialization of global interrupt modes,
@@ -2722,11 +2734,11 @@ Warnings: No range checking on any of the parameters is done.
After this function all AIOPs on the controller are disabled,
they can be enabled with sEnAiop().
*/
-int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
- ByteIO_t * AiopIOList, int AiopIOListSize,
- WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
- int PeriodicOnly, int altChanRingIndicator,
- int UPCIRingInd)
+static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
+ ByteIO_t * AiopIOList, int AiopIOListSize,
+ WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
+ int PeriodicOnly, int altChanRingIndicator,
+ int UPCIRingInd)
{
int i;
ByteIO_t io;
@@ -2784,7 +2796,7 @@ Return: int: Flag AIOPID_XXXX if a valid AIOP is found, where X
Warnings: No context switches are allowed while executing this function.
*/
-int sReadAiopID(ByteIO_t io)
+static int sReadAiopID(ByteIO_t io)
{
Byte_t AiopID; /* ID byte from AIOP */
@@ -2810,7 +2822,7 @@ Comments: The number of channels is determined by write/reads from identical
AIOP, otherwise it is an 8 channel.
Warnings: No context switches are allowed while executing this function.
*/
-int sReadAiopNumChan(WordIO_t io)
+static int sReadAiopNumChan(WordIO_t io)
{
Word_t x;
static Byte_t R[4] = { 0x00, 0x00, 0x34, 0x12 };
@@ -2834,15 +2846,15 @@ Call: sInitChan(CtlP,ChP,AiopNum,ChanNum)
CHANNEL_T *ChP; Ptr to channel structure
int AiopNum; AIOP number within controller
int ChanNum; Channel number within AIOP
-Return: int: TRUE if initialization succeeded, FALSE if it fails because channel
+Return: int: 1 if initialization succeeded, 0 if it fails because channel
number exceeds number of channels available in AIOP.
Comments: This function must be called before a channel can be used.
Warnings: No range checking on any of the parameters is done.
No context switches are allowed while executing this function.
*/
-int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
- int ChanNum)
+static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
+ int ChanNum)
{
int i;
WordIO_t AiopIO;
@@ -2853,7 +2865,7 @@ int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
int brd9600;
if (ChanNum >= CtlP->AiopNumChan[AiopNum])
- return (FALSE); /* exceeds num chans in AIOP */
+ return 0; /* exceeds num chans in AIOP */
/* Channel, AIOP, and controller identifiers */
ChP->CtlP = CtlP;
@@ -2968,7 +2980,7 @@ int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
ChP->TxPrioBuf = ChOff + _TXP_BUF;
sEnRxProcessor(ChP); /* start the Rx processor */
- return (TRUE);
+ return 1;
}
/***************************************************************************
@@ -2989,7 +3001,7 @@ Warnings: No context switches are allowed while executing this function.
After calling this function a delay of 4 uS is required to ensure
that the receive processor is no longer processing this channel.
*/
-void sStopRxProcessor(CHANNEL_T * ChP)
+static void sStopRxProcessor(CHANNEL_T * ChP)
{
Byte_t R[4];
@@ -3014,18 +3026,18 @@ Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
this function.
Warnings: No context switches are allowed while executing this function.
*/
-void sFlushRxFIFO(CHANNEL_T * ChP)
+static void sFlushRxFIFO(CHANNEL_T * ChP)
{
int i;
Byte_t Ch; /* channel number within AIOP */
- int RxFIFOEnabled; /* TRUE if Rx FIFO enabled */
+ int RxFIFOEnabled; /* 1 if Rx FIFO enabled */
if (sGetRxCnt(ChP) == 0) /* Rx FIFO empty */
return; /* don't need to flush */
- RxFIFOEnabled = FALSE;
+ RxFIFOEnabled = 0;
if (ChP->R[0x32] == 0x08) { /* Rx FIFO is enabled */
- RxFIFOEnabled = TRUE;
+ RxFIFOEnabled = 1;
sDisRxFIFO(ChP); /* disable it */
for (i = 0; i < 2000 / 200; i++) /* delay 2 uS to allow proc to disable FIFO */
sInB(ChP->IntChan); /* depends on bus i/o timing */
@@ -3056,18 +3068,18 @@ Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
this function.
Warnings: No context switches are allowed while executing this function.
*/
-void sFlushTxFIFO(CHANNEL_T * ChP)
+static void sFlushTxFIFO(CHANNEL_T * ChP)
{
int i;
Byte_t Ch; /* channel number within AIOP */
- int TxEnabled; /* TRUE if transmitter enabled */
+ int TxEnabled; /* 1 if transmitter enabled */
if (sGetTxCnt(ChP) == 0) /* Tx FIFO empty */
return; /* don't need to flush */
- TxEnabled = FALSE;
+ TxEnabled = 0;
if (ChP->TxControl[3] & TX_ENABLE) {
- TxEnabled = TRUE;
+ TxEnabled = 1;
sDisTransmit(ChP); /* disable transmitter */
}
sStopRxProcessor(ChP); /* stop Rx processor */
@@ -3096,7 +3108,7 @@ Comments: The priority byte is transmitted before any data in the Tx FIFO.
Warnings: No context switches are allowed while executing this function.
*/
-int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data)
+static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data)
{
Byte_t DWBuf[4]; /* buffer for double word writes */
Word_t *WordPtr; /* must be far because Win SS != DS */
@@ -3158,7 +3170,7 @@ Comments: If an interrupt enable flag is set in Flags, that interrupt will be
enable channel interrupts. This would allow the global interrupt
status register to be used to determine which AIOPs need service.
*/
-void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags)
+static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags)
{
Byte_t Mask; /* Interrupt Mask Register */
@@ -3202,7 +3214,7 @@ Comments: If an interrupt flag is set in Flags, that interrupt will be
this channel's bit from being set in the AIOP's Interrupt Channel
Register.
*/
-void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags)
+static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags)
{
Byte_t Mask; /* Interrupt Mask Register */
@@ -3218,7 +3230,7 @@ void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags)
}
}
-void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode)
+static void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode)
{
sOutB(ChP->CtlP->AiopIO[2], (mode & 0x18) | ChP->ChanNum);
}
@@ -3227,7 +3239,7 @@ void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode)
* Not an official SSCI function, but how to reset RocketModems.
* ISA bus version
*/
-void sModemReset(CONTROLLER_T * CtlP, int chan, int on)
+static void sModemReset(CONTROLLER_T * CtlP, int chan, int on)
{
ByteIO_t addr;
Byte_t val;
@@ -3252,7 +3264,7 @@ void sModemReset(CONTROLLER_T * CtlP, int chan, int on)
* Not an official SSCI function, but how to reset RocketModems.
* PCI bus version
*/
-void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on)
+static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on)
{
ByteIO_t addr;
diff --git a/drivers/char/rocket_int.h b/drivers/char/rocket_int.h
index 802687290ee..3a8bcc85bc1 100644
--- a/drivers/char/rocket_int.h
+++ b/drivers/char/rocket_int.h
@@ -1130,46 +1130,6 @@ Warnings: This function writes the data byte without checking to see if
*/
#define sWriteTxByte(IO,DATA) sOutB(IO,DATA)
-int sInitController(CONTROLLER_T * CtlP,
- int CtlNum,
- ByteIO_t MudbacIO,
- ByteIO_t * AiopIOList,
- int AiopIOListSize,
- int IRQNum, Byte_t Frequency, int PeriodicOnly);
-
-int sPCIInitController(CONTROLLER_T * CtlP,
- int CtlNum,
- ByteIO_t * AiopIOList,
- int AiopIOListSize,
- WordIO_t ConfigIO,
- int IRQNum,
- Byte_t Frequency,
- int PeriodicOnly,
- int altChanRingIndicator, int UPCIRingInd);
-
-int sReadAiopID(ByteIO_t io);
-int sReadAiopNumChan(WordIO_t io);
-int sInitChan(CONTROLLER_T * CtlP,
- CHANNEL_T * ChP, int AiopNum, int ChanNum);
-Byte_t sGetRxErrStatus(CHANNEL_T * ChP);
-void sStopRxProcessor(CHANNEL_T * ChP);
-void sStopSWInFlowCtl(CHANNEL_T * ChP);
-void sFlushRxFIFO(CHANNEL_T * ChP);
-void sFlushTxFIFO(CHANNEL_T * ChP);
-int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data);
-void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags);
-void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags);
-void sModemReset(CONTROLLER_T * CtlP, int chan, int on);
-void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on);
-void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode);
-
-extern Byte_t R[RDATASIZE];
-extern CONTROLLER_T sController[CTL_SIZE];
-extern Byte_t sIRQMap[16];
-extern Byte_t sBitMapClrTbl[8];
-extern Byte_t sBitMapSetTbl[8];
-extern int sClockPrescale;
-
/*
* Begin Linux specific definitions for the Rocketport driver
*
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index e3c0b52d943..261a41bf6d0 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -357,6 +357,8 @@ static struct file_operations scdrv_fops = {
.release = scdrv_release,
};
+static struct class *snsc_class;
+
/*
* scdrv_init
*
@@ -372,7 +374,6 @@ scdrv_init(void)
char *devnamep;
struct sysctl_data_s *scd;
void *salbuf;
- struct class_simple *snsc_class;
dev_t first_dev, dev;
nasid_t event_nasid = ia64_sn_get_console_nasid();
@@ -382,7 +383,7 @@ scdrv_init(void)
__FUNCTION__);
return -ENODEV;
}
- snsc_class = class_simple_create(THIS_MODULE, SYSCTL_BASENAME);
+ snsc_class = class_create(THIS_MODULE, SYSCTL_BASENAME);
for (cnode = 0; cnode < numionodes; cnode++) {
geoid = cnodeid_get_geoid(cnode);
@@ -436,7 +437,7 @@ scdrv_init(void)
continue;
}
- class_simple_device_add(snsc_class, dev, NULL,
+ class_device_create(snsc_class, dev, NULL,
"%s", devname);
ia64_sn_irtr_intr_enable(scd->scd_nasid,
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index b8899f560b5..951545a6ef2 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -719,7 +719,7 @@ static struct file_operations stl_fsiomem = {
/*****************************************************************************/
-static struct class_simple *stallion_class;
+static struct class *stallion_class;
/*
* Loadable module initialization stuff.
@@ -777,13 +777,13 @@ static void __exit stallion_module_exit(void)
}
for (i = 0; i < 4; i++) {
devfs_remove("staliomem/%d", i);
- class_simple_device_remove(MKDEV(STL_SIOMEMMAJOR, i));
+ class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
}
devfs_remove("staliomem");
if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
printk("STALLION: failed to un-register serial memory device, "
"errno=%d\n", -i);
- class_simple_destroy(stallion_class);
+ class_destroy(stallion_class);
if (stl_tmpwritebuf != (char *) NULL)
kfree(stl_tmpwritebuf);
@@ -3090,12 +3090,12 @@ static int __init stl_init(void)
printk("STALLION: failed to register serial board device\n");
devfs_mk_dir("staliomem");
- stallion_class = class_simple_create(THIS_MODULE, "staliomem");
+ stallion_class = class_create(THIS_MODULE, "staliomem");
for (i = 0; i < 4; i++) {
devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i),
S_IFCHR|S_IRUSR|S_IWUSR,
"staliomem/%d", i);
- class_simple_device_add(stallion_class, MKDEV(STL_SIOMEMMAJOR, i), NULL, "staliomem%d", i);
+ class_device_create(stallion_class, MKDEV(STL_SIOMEMMAJOR, i), NULL, "staliomem%d", i);
}
stl_serial->owner = THIS_MODULE;
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index f59f7cbd525..af79805b557 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -35,6 +35,7 @@
#include <linux/spinlock.h>
#include <linux/vt_kern.h>
#include <linux/workqueue.h>
+#include <linux/kexec.h>
#include <asm/ptrace.h>
@@ -94,6 +95,21 @@ static struct sysrq_key_op sysrq_unraw_op = {
};
#endif /* CONFIG_VT */
+#ifdef CONFIG_KEXEC
+/* crashdump sysrq handler */
+static void sysrq_handle_crashdump(int key, struct pt_regs *pt_regs,
+ struct tty_struct *tty)
+{
+ crash_kexec(pt_regs);
+}
+static struct sysrq_key_op sysrq_crashdump_op = {
+ .handler = sysrq_handle_crashdump,
+ .help_msg = "Crashdump",
+ .action_msg = "Trigger a crashdump",
+ .enable_mask = SYSRQ_ENABLE_DUMP,
+};
+#endif
+
/* reboot sysrq handler */
static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs,
struct tty_struct *tty)
@@ -273,8 +289,12 @@ static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = {
it is handled specially on the sparc
and will never arrive */
/* b */ &sysrq_reboot_op,
-/* c */ NULL,
-/* d */ NULL,
+#ifdef CONFIG_KEXEC
+/* c */ &sysrq_crashdump_op,
+#else
+/* c */ NULL,
+#endif
+/* d */ NULL,
/* e */ &sysrq_term_op,
/* f */ &sysrq_moom_op,
/* g */ NULL,
diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c
index 0c5ba9dc906..659335d80ee 100644
--- a/drivers/char/tipar.c
+++ b/drivers/char/tipar.c
@@ -90,7 +90,7 @@ static int timeout = TIMAXTIME; /* timeout in tenth of seconds */
static unsigned int tp_count; /* tipar count */
static unsigned long opened; /* opened devices */
-static struct class_simple *tipar_class;
+static struct class *tipar_class;
/* --- macros for parport access -------------------------------------- */
@@ -436,7 +436,7 @@ tipar_register(int nr, struct parport *port)
goto out;
}
- class_simple_device_add(tipar_class, MKDEV(TIPAR_MAJOR,
+ class_device_create(tipar_class, MKDEV(TIPAR_MAJOR,
TIPAR_MINOR + nr), NULL, "par%d", nr);
/* Use devfs, tree: /dev/ticables/par/[0..2] */
err = devfs_mk_cdev(MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr),
@@ -458,8 +458,8 @@ tipar_register(int nr, struct parport *port)
goto out;
out_class:
- class_simple_device_remove(MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr));
- class_simple_destroy(tipar_class);
+ class_device_destroy(tipar_class, MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr));
+ class_destroy(tipar_class);
out:
return err;
}
@@ -505,7 +505,7 @@ tipar_init_module(void)
/* Use devfs with tree: /dev/ticables/par/[0..2] */
devfs_mk_dir("ticables/par");
- tipar_class = class_simple_create(THIS_MODULE, "ticables");
+ tipar_class = class_create(THIS_MODULE, "ticables");
if (IS_ERR(tipar_class)) {
err = PTR_ERR(tipar_class);
goto out_chrdev;
@@ -539,10 +539,10 @@ tipar_cleanup_module(void)
if (table[i].dev == NULL)
continue;
parport_unregister_device(table[i].dev);
- class_simple_device_remove(MKDEV(TIPAR_MAJOR, i));
+ class_device_destroy(tipar_class, MKDEV(TIPAR_MAJOR, i));
devfs_remove("ticables/par/%d", i);
}
- class_simple_destroy(tipar_class);
+ class_destroy(tipar_class);
devfs_remove("ticables/par");
pr_info("tipar: module unloaded\n");
diff --git a/drivers/char/toshiba.c b/drivers/char/toshiba.c
index 58e21fe4426..0c6f521abd0 100644
--- a/drivers/char/toshiba.c
+++ b/drivers/char/toshiba.c
@@ -73,16 +73,20 @@
#define TOSH_MINOR_DEV 181
-static int tosh_id = 0x0000;
-static int tosh_bios = 0x0000;
-static int tosh_date = 0x0000;
-static int tosh_sci = 0x0000;
-static int tosh_fan = 0;
-
-static int tosh_fn = 0;
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jonathan Buzzard <jonathan@buzzard.org.uk>");
+MODULE_DESCRIPTION("Toshiba laptop SMM driver");
+MODULE_SUPPORTED_DEVICE("toshiba");
-module_param(tosh_fn, int, 0);
+static int tosh_fn;
+module_param_named(fn, tosh_fn, int, 0);
+MODULE_PARM_DESC(fn, "User specified Fn key detection port");
+static int tosh_id;
+static int tosh_bios;
+static int tosh_date;
+static int tosh_sci;
+static int tosh_fan;
static int tosh_ioctl(struct inode *, struct file *, unsigned int,
unsigned long);
@@ -359,7 +363,7 @@ static int tosh_get_machine_id(void)
unsigned long address;
id = (0x100*(int) isa_readb(0xffffe))+((int) isa_readb(0xffffa));
-
+
/* do we have a SCTTable machine identication number on our hands */
if (id==0xfc2f) {
@@ -424,7 +428,7 @@ static int tosh_probe(void)
}
/* call the Toshiba SCI support check routine */
-
+
regs.eax = 0xf0f0;
regs.ebx = 0x0000;
regs.ecx = 0x0000;
@@ -440,7 +444,7 @@ static int tosh_probe(void)
/* if we get this far then we are running on a Toshiba (probably)! */
tosh_sci = regs.edx & 0xffff;
-
+
/* next get the machine ID of the current laptop */
tosh_id = tosh_get_machine_id();
@@ -475,16 +479,15 @@ static int tosh_probe(void)
return 0;
}
-int __init tosh_init(void)
+static int __init toshiba_init(void)
{
int retval;
/* are we running on a Toshiba laptop */
- if (tosh_probe()!=0)
- return -EIO;
+ if (tosh_probe())
+ return -ENODEV;
- printk(KERN_INFO "Toshiba System Managment Mode driver v"
- TOSH_VERSION"\n");
+ printk(KERN_INFO "Toshiba System Managment Mode driver v" TOSH_VERSION "\n");
/* set the port to use for Fn status if not specified as a parameter */
if (tosh_fn==0x00)
@@ -492,12 +495,12 @@ int __init tosh_init(void)
/* register the device file */
retval = misc_register(&tosh_device);
- if(retval < 0)
+ if (retval < 0)
return retval;
#ifdef CONFIG_PROC_FS
/* register the proc entry */
- if(create_proc_info_entry("toshiba", 0, NULL, tosh_get_info) == NULL){
+ if (create_proc_info_entry("toshiba", 0, NULL, tosh_get_info) == NULL) {
misc_deregister(&tosh_device);
return -ENOMEM;
}
@@ -506,27 +509,12 @@ int __init tosh_init(void)
return 0;
}
-#ifdef MODULE
-int init_module(void)
-{
- return tosh_init();
-}
-
-void cleanup_module(void)
+static void __exit toshiba_exit(void)
{
- /* remove the proc entry */
-
remove_proc_entry("toshiba", NULL);
-
- /* unregister the device file */
-
misc_deregister(&tosh_device);
}
-#endif
-MODULE_LICENSE("GPL");
-MODULE_PARM_DESC(tosh_fn, "User specified Fn key detection port");
-MODULE_AUTHOR("Jonathan Buzzard <jonathan@buzzard.org.uk>");
-MODULE_DESCRIPTION("Toshiba laptop SMM driver");
-MODULE_SUPPORTED_DEVICE("toshiba");
+module_init(toshiba_init);
+module_exit(toshiba_exit);
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 87235330fdb..854475c54f0 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -19,7 +19,7 @@
*
* Note, the TPM chip is not interrupt driven (only polling)
* and can have very long timeouts (minutes!). Hence the unusual
- * calls to schedule_timeout.
+ * calls to msleep.
*
*/
@@ -28,19 +28,16 @@
#include <linux/spinlock.h>
#include "tpm.h"
-#define TPM_MINOR 224 /* officially assigned */
-
-#define TPM_BUFSIZE 2048
-
-/* PCI configuration addresses */
-#define PCI_GEN_PMCON_1 0xA0
-#define PCI_GEN1_DEC 0xE4
-#define PCI_LPC_EN 0xE6
-#define PCI_GEN2_DEC 0xEC
+enum tpm_const {
+ TPM_MINOR = 224, /* officially assigned */
+ TPM_BUFSIZE = 2048,
+ TPM_NUM_DEVICES = 256,
+ TPM_NUM_MASK_ENTRIES = TPM_NUM_DEVICES / (8 * sizeof(int))
+};
static LIST_HEAD(tpm_chip_list);
static DEFINE_SPINLOCK(driver_lock);
-static int dev_mask[32];
+static int dev_mask[TPM_NUM_MASK_ENTRIES];
static void user_reader_timeout(unsigned long ptr)
{
@@ -52,92 +49,17 @@ static void user_reader_timeout(unsigned long ptr)
up(&chip->buffer_mutex);
}
-void tpm_time_expired(unsigned long ptr)
-{
- int *exp = (int *) ptr;
- *exp = 1;
-}
-
-EXPORT_SYMBOL_GPL(tpm_time_expired);
-
-/*
- * Initialize the LPC bus and enable the TPM ports
- */
-int tpm_lpc_bus_init(struct pci_dev *pci_dev, u16 base)
-{
- u32 lpcenable, tmp;
- int is_lpcm = 0;
-
- switch (pci_dev->vendor) {
- case PCI_VENDOR_ID_INTEL:
- switch (pci_dev->device) {
- case PCI_DEVICE_ID_INTEL_82801CA_12:
- case PCI_DEVICE_ID_INTEL_82801DB_12:
- is_lpcm = 1;
- break;
- }
- /* init ICH (enable LPC) */
- pci_read_config_dword(pci_dev, PCI_GEN1_DEC, &lpcenable);
- lpcenable |= 0x20000000;
- pci_write_config_dword(pci_dev, PCI_GEN1_DEC, lpcenable);
-
- if (is_lpcm) {
- pci_read_config_dword(pci_dev, PCI_GEN1_DEC,
- &lpcenable);
- if ((lpcenable & 0x20000000) == 0) {
- dev_err(&pci_dev->dev,
- "cannot enable LPC\n");
- return -ENODEV;
- }
- }
-
- /* initialize TPM registers */
- pci_read_config_dword(pci_dev, PCI_GEN2_DEC, &tmp);
-
- if (!is_lpcm)
- tmp = (tmp & 0xFFFF0000) | (base & 0xFFF0);
- else
- tmp =
- (tmp & 0xFFFF0000) | (base & 0xFFF0) |
- 0x00000001;
-
- pci_write_config_dword(pci_dev, PCI_GEN2_DEC, tmp);
-
- if (is_lpcm) {
- pci_read_config_dword(pci_dev, PCI_GEN_PMCON_1,
- &tmp);
- tmp |= 0x00000004; /* enable CLKRUN */
- pci_write_config_dword(pci_dev, PCI_GEN_PMCON_1,
- tmp);
- }
- tpm_write_index(0x0D, 0x55); /* unlock 4F */
- tpm_write_index(0x0A, 0x00); /* int disable */
- tpm_write_index(0x08, base); /* base addr lo */
- tpm_write_index(0x09, (base & 0xFF00) >> 8); /* base addr hi */
- tpm_write_index(0x0D, 0xAA); /* lock 4F */
- break;
- case PCI_VENDOR_ID_AMD:
- /* nothing yet */
- break;
- }
-
- return 0;
-}
-
-EXPORT_SYMBOL_GPL(tpm_lpc_bus_init);
-
/*
* Internal kernel interface to transmit TPM commands
*/
static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
size_t bufsiz)
{
- ssize_t len;
+ ssize_t rc;
u32 count;
- __be32 *native_size;
+ unsigned long stop;
- native_size = (__force __be32 *) (buf + 2);
- count = be32_to_cpu(*native_size);
+ count = be32_to_cpu(*((__be32 *) (buf + 2)));
if (count == 0)
return -ENODATA;
@@ -149,53 +71,49 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
down(&chip->tpm_mutex);
- if ((len = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
+ if ((rc = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
dev_err(&chip->pci_dev->dev,
- "tpm_transmit: tpm_send: error %zd\n", len);
- return len;
+ "tpm_transmit: tpm_send: error %zd\n", rc);
+ goto out;
}
- down(&chip->timer_manipulation_mutex);
- chip->time_expired = 0;
- init_timer(&chip->device_timer);
- chip->device_timer.function = tpm_time_expired;
- chip->device_timer.expires = jiffies + 2 * 60 * HZ;
- chip->device_timer.data = (unsigned long) &chip->time_expired;
- add_timer(&chip->device_timer);
- up(&chip->timer_manipulation_mutex);
-
+ stop = jiffies + 2 * 60 * HZ;
do {
u8 status = inb(chip->vendor->base + 1);
if ((status & chip->vendor->req_complete_mask) ==
chip->vendor->req_complete_val) {
- down(&chip->timer_manipulation_mutex);
- del_singleshot_timer_sync(&chip->device_timer);
- up(&chip->timer_manipulation_mutex);
goto out_recv;
}
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(TPM_TIMEOUT);
+
+ if ((status == chip->vendor->req_canceled)) {
+ dev_err(&chip->pci_dev->dev, "Operation Canceled\n");
+ rc = -ECANCELED;
+ goto out;
+ }
+
+ msleep(TPM_TIMEOUT); /* CHECK */
rmb();
- } while (!chip->time_expired);
+ } while (time_before(jiffies, stop));
chip->vendor->cancel(chip);
- dev_err(&chip->pci_dev->dev, "Time expired\n");
- up(&chip->tpm_mutex);
- return -EIO;
+ dev_err(&chip->pci_dev->dev, "Operation Timed out\n");
+ rc = -ETIME;
+ goto out;
out_recv:
- len = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
- if (len < 0)
+ rc = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
+ if (rc < 0)
dev_err(&chip->pci_dev->dev,
- "tpm_transmit: tpm_recv: error %zd\n", len);
+ "tpm_transmit: tpm_recv: error %zd\n", rc);
+out:
up(&chip->tpm_mutex);
- return len;
+ return rc;
}
#define TPM_DIGEST_SIZE 20
#define CAP_PCR_RESULT_SIZE 18
-static u8 cap_pcr[] = {
+static const u8 cap_pcr[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
0, 0, 0, 22, /* length */
0, 0, 0, 101, /* TPM_ORD_GetCapability */
@@ -205,75 +123,94 @@ static u8 cap_pcr[] = {
};
#define READ_PCR_RESULT_SIZE 30
-static u8 pcrread[] = {
+static const u8 pcrread[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
0, 0, 0, 14, /* length */
0, 0, 0, 21, /* TPM_ORD_PcrRead */
0, 0, 0, 0 /* PCR index */
};
-static ssize_t show_pcrs(struct device *dev, char *buf)
+ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
u8 data[READ_PCR_RESULT_SIZE];
ssize_t len;
- int i, j, index, num_pcrs;
+ int i, j, num_pcrs;
+ __be32 index;
char *str = buf;
struct tpm_chip *chip =
- pci_get_drvdata(container_of(dev, struct pci_dev, dev));
+ pci_get_drvdata(to_pci_dev(dev));
if (chip == NULL)
return -ENODEV;
memcpy(data, cap_pcr, sizeof(cap_pcr));
if ((len = tpm_transmit(chip, data, sizeof(data)))
- < CAP_PCR_RESULT_SIZE)
- return len;
+ < CAP_PCR_RESULT_SIZE) {
+ dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred "
+ "attempting to determine the number of PCRS\n",
+ be32_to_cpu(*((__be32 *) (data + 6))));
+ return 0;
+ }
- num_pcrs = be32_to_cpu(*((__force __be32 *) (data + 14)));
+ num_pcrs = be32_to_cpu(*((__be32 *) (data + 14)));
for (i = 0; i < num_pcrs; i++) {
memcpy(data, pcrread, sizeof(pcrread));
index = cpu_to_be32(i);
memcpy(data + 10, &index, 4);
if ((len = tpm_transmit(chip, data, sizeof(data)))
- < READ_PCR_RESULT_SIZE)
- return len;
+ < READ_PCR_RESULT_SIZE){
+ dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred"
+ " attempting to read PCR %d of %d\n",
+ be32_to_cpu(*((__be32 *) (data + 6))), i, num_pcrs);
+ goto out;
+ }
str += sprintf(str, "PCR-%02d: ", i);
for (j = 0; j < TPM_DIGEST_SIZE; j++)
str += sprintf(str, "%02X ", *(data + 10 + j));
str += sprintf(str, "\n");
}
+out:
return str - buf;
}
-
-static DEVICE_ATTR(pcrs, S_IRUGO, show_pcrs, NULL);
+EXPORT_SYMBOL_GPL(tpm_show_pcrs);
#define READ_PUBEK_RESULT_SIZE 314
-static u8 readpubek[] = {
+static const u8 readpubek[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
0, 0, 0, 30, /* length */
0, 0, 0, 124, /* TPM_ORD_ReadPubek */
};
-static ssize_t show_pubek(struct device *dev, char *buf)
+ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
- u8 data[READ_PUBEK_RESULT_SIZE];
+ u8 *data;
ssize_t len;
- __be32 *native_val;
- int i;
+ int i, rc;
char *str = buf;
struct tpm_chip *chip =
- pci_get_drvdata(container_of(dev, struct pci_dev, dev));
+ pci_get_drvdata(to_pci_dev(dev));
if (chip == NULL)
return -ENODEV;
+ data = kmalloc(READ_PUBEK_RESULT_SIZE, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
memcpy(data, readpubek, sizeof(readpubek));
memset(data + sizeof(readpubek), 0, 20); /* zero nonce */
- if ((len = tpm_transmit(chip, data, sizeof(data))) <
- READ_PUBEK_RESULT_SIZE)
- return len;
+ if ((len = tpm_transmit(chip, data, READ_PUBEK_RESULT_SIZE)) <
+ READ_PUBEK_RESULT_SIZE) {
+ dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred "
+ "attempting to read the PUBEK\n",
+ be32_to_cpu(*((__be32 *) (data + 6))));
+ rc = 0;
+ goto out;
+ }
/*
ignore header 10 bytes
@@ -286,8 +223,6 @@ static ssize_t show_pubek(struct device *dev, char *buf)
ignore checksum 20 bytes
*/
- native_val = (__force __be32 *) (data + 34);
-
str +=
sprintf(str,
"Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n"
@@ -298,21 +233,23 @@ static ssize_t show_pubek(struct device *dev, char *buf)
data[15], data[16], data[17], data[22], data[23],
data[24], data[25], data[26], data[27], data[28],
data[29], data[30], data[31], data[32], data[33],
- be32_to_cpu(*native_val)
- );
+ be32_to_cpu(*((__be32 *) (data + 34))));
for (i = 0; i < 256; i++) {
- str += sprintf(str, "%02X ", data[i + 39]);
+ str += sprintf(str, "%02X ", data[i + 38]);
if ((i + 1) % 16 == 0)
str += sprintf(str, "\n");
}
- return str - buf;
+ rc = str - buf;
+out:
+ kfree(data);
+ return rc;
}
-static DEVICE_ATTR(pubek, S_IRUGO, show_pubek, NULL);
+EXPORT_SYMBOL_GPL(tpm_show_pubek);
#define CAP_VER_RESULT_SIZE 18
-static u8 cap_version[] = {
+static const u8 cap_version[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
0, 0, 0, 18, /* length */
0, 0, 0, 101, /* TPM_ORD_GetCapability */
@@ -321,7 +258,7 @@ static u8 cap_version[] = {
};
#define CAP_MANUFACTURER_RESULT_SIZE 18
-static u8 cap_manufacturer[] = {
+static const u8 cap_manufacturer[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
0, 0, 0, 22, /* length */
0, 0, 0, 101, /* TPM_ORD_GetCapability */
@@ -330,14 +267,15 @@ static u8 cap_manufacturer[] = {
0, 0, 1, 3
};
-static ssize_t show_caps(struct device *dev, char *buf)
+ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
- u8 data[READ_PUBEK_RESULT_SIZE];
+ u8 data[sizeof(cap_manufacturer)];
ssize_t len;
char *str = buf;
struct tpm_chip *chip =
- pci_get_drvdata(container_of(dev, struct pci_dev, dev));
+ pci_get_drvdata(to_pci_dev(dev));
if (chip == NULL)
return -ENODEV;
@@ -348,7 +286,7 @@ static ssize_t show_caps(struct device *dev, char *buf)
return len;
str += sprintf(str, "Manufacturer: 0x%x\n",
- be32_to_cpu(*(data + 14)));
+ be32_to_cpu(*((__be32 *) (data + 14))));
memcpy(data, cap_version, sizeof(cap_version));
@@ -363,8 +301,20 @@ static ssize_t show_caps(struct device *dev, char *buf)
return str - buf;
}
+EXPORT_SYMBOL_GPL(tpm_show_caps);
+
+ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return 0;
+
+ chip->vendor->cancel(chip);
+ return count;
+}
+EXPORT_SYMBOL_GPL(tpm_store_cancel);
-static DEVICE_ATTR(caps, S_IRUGO, show_caps, NULL);
/*
* Device file system interface to the TPM
@@ -422,24 +372,15 @@ EXPORT_SYMBOL_GPL(tpm_open);
int tpm_release(struct inode *inode, struct file *file)
{
struct tpm_chip *chip = file->private_data;
-
- file->private_data = NULL;
spin_lock(&driver_lock);
+ file->private_data = NULL;
chip->num_opens--;
- spin_unlock(&driver_lock);
-
- down(&chip->timer_manipulation_mutex);
- if (timer_pending(&chip->user_read_timer))
- del_singleshot_timer_sync(&chip->user_read_timer);
- else if (timer_pending(&chip->device_timer))
- del_singleshot_timer_sync(&chip->device_timer);
- up(&chip->timer_manipulation_mutex);
-
- kfree(chip->data_buffer);
+ del_singleshot_timer_sync(&chip->user_read_timer);
atomic_set(&chip->data_pending, 0);
-
pci_dev_put(chip->pci_dev);
+ kfree(chip->data_buffer);
+ spin_unlock(&driver_lock);
return 0;
}
@@ -453,10 +394,8 @@ ssize_t tpm_write(struct file * file, const char __user * buf,
/* cannot perform a write until the read has cleared
either via tpm_read or a user_read_timer timeout */
- while (atomic_read(&chip->data_pending) != 0) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(TPM_TIMEOUT);
- }
+ while (atomic_read(&chip->data_pending) != 0)
+ msleep(TPM_TIMEOUT);
down(&chip->buffer_mutex);
@@ -476,13 +415,7 @@ ssize_t tpm_write(struct file * file, const char __user * buf,
up(&chip->buffer_mutex);
/* Set a timeout by which the reader must come claim the result */
- down(&chip->timer_manipulation_mutex);
- init_timer(&chip->user_read_timer);
- chip->user_read_timer.function = user_reader_timeout;
- chip->user_read_timer.data = (unsigned long) chip;
- chip->user_read_timer.expires = jiffies + (60 * HZ);
- add_timer(&chip->user_read_timer);
- up(&chip->timer_manipulation_mutex);
+ mod_timer(&chip->user_read_timer, jiffies + (60 * HZ));
return in_size;
}
@@ -493,29 +426,19 @@ ssize_t tpm_read(struct file * file, char __user * buf,
size_t size, loff_t * off)
{
struct tpm_chip *chip = file->private_data;
- int ret_size = -ENODATA;
+ int ret_size;
- if (atomic_read(&chip->data_pending) != 0) { /* Result available */
- down(&chip->timer_manipulation_mutex);
- del_singleshot_timer_sync(&chip->user_read_timer);
- up(&chip->timer_manipulation_mutex);
+ del_singleshot_timer_sync(&chip->user_read_timer);
+ ret_size = atomic_read(&chip->data_pending);
+ atomic_set(&chip->data_pending, 0);
+ if (ret_size > 0) { /* relay data */
+ if (size < ret_size)
+ ret_size = size;
down(&chip->buffer_mutex);
-
- ret_size = atomic_read(&chip->data_pending);
- atomic_set(&chip->data_pending, 0);
-
- if (ret_size == 0) /* timeout just occurred */
- ret_size = -ETIME;
- else if (ret_size > 0) { /* relay data */
- if (size < ret_size)
- ret_size = size;
-
- if (copy_to_user((void __user *) buf,
- chip->data_buffer, ret_size)) {
- ret_size = -EFAULT;
- }
- }
+ if (copy_to_user
+ ((void __user *) buf, chip->data_buffer, ret_size))
+ ret_size = -EFAULT;
up(&chip->buffer_mutex);
}
@@ -541,14 +464,13 @@ void __devexit tpm_remove(struct pci_dev *pci_dev)
pci_set_drvdata(pci_dev, NULL);
misc_deregister(&chip->vendor->miscdev);
+ kfree(&chip->vendor->miscdev.name);
- device_remove_file(&pci_dev->dev, &dev_attr_pubek);
- device_remove_file(&pci_dev->dev, &dev_attr_pcrs);
- device_remove_file(&pci_dev->dev, &dev_attr_caps);
+ sysfs_remove_group(&pci_dev->dev.kobj, chip->vendor->attr_group);
pci_disable_device(pci_dev);
- dev_mask[chip->dev_num / 32] &= !(1 << (chip->dev_num % 32));
+ dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= !(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES));
kfree(chip);
@@ -590,10 +512,6 @@ int tpm_pm_resume(struct pci_dev *pci_dev)
if (chip == NULL)
return -ENODEV;
- spin_lock(&driver_lock);
- tpm_lpc_bus_init(pci_dev, chip->vendor->base);
- spin_unlock(&driver_lock);
-
return 0;
}
@@ -609,7 +527,9 @@ EXPORT_SYMBOL_GPL(tpm_pm_resume);
int tpm_register_hardware(struct pci_dev *pci_dev,
struct tpm_vendor_specific *entry)
{
- char devname[7];
+#define DEVNAME_SIZE 7
+
+ char *devname;
struct tpm_chip *chip;
int i, j;
@@ -622,17 +542,21 @@ int tpm_register_hardware(struct pci_dev *pci_dev,
init_MUTEX(&chip->buffer_mutex);
init_MUTEX(&chip->tpm_mutex);
- init_MUTEX(&chip->timer_manipulation_mutex);
INIT_LIST_HEAD(&chip->list);
+ init_timer(&chip->user_read_timer);
+ chip->user_read_timer.function = user_reader_timeout;
+ chip->user_read_timer.data = (unsigned long) chip;
+
chip->vendor = entry;
chip->dev_num = -1;
- for (i = 0; i < 32; i++)
- for (j = 0; j < 8; j++)
+ for (i = 0; i < TPM_NUM_MASK_ENTRIES; i++)
+ for (j = 0; j < 8 * sizeof(int); j++)
if ((dev_mask[i] & (1 << j)) == 0) {
- chip->dev_num = i * 32 + j;
+ chip->dev_num =
+ i * TPM_NUM_MASK_ENTRIES + j;
dev_mask[i] |= 1 << j;
goto dev_num_search_complete;
}
@@ -648,7 +572,8 @@ dev_num_search_complete:
else
chip->vendor->miscdev.minor = MISC_DYNAMIC_MINOR;
- snprintf(devname, sizeof(devname), "%s%d", "tpm", chip->dev_num);
+ devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL);
+ scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num);
chip->vendor->miscdev.name = devname;
chip->vendor->miscdev.dev = &(pci_dev->dev);
@@ -665,31 +590,20 @@ dev_num_search_complete:
return -ENODEV;
}
+ spin_lock(&driver_lock);
+
pci_set_drvdata(pci_dev, chip);
list_add(&chip->list, &tpm_chip_list);
- device_create_file(&pci_dev->dev, &dev_attr_pubek);
- device_create_file(&pci_dev->dev, &dev_attr_pcrs);
- device_create_file(&pci_dev->dev, &dev_attr_caps);
-
- return 0;
-}
+ spin_unlock(&driver_lock);
-EXPORT_SYMBOL_GPL(tpm_register_hardware);
+ sysfs_create_group(&pci_dev->dev.kobj, chip->vendor->attr_group);
-static int __init init_tpm(void)
-{
return 0;
}
-static void __exit cleanup_tpm(void)
-{
-
-}
-
-module_init(init_tpm);
-module_exit(cleanup_tpm);
+EXPORT_SYMBOL_GPL(tpm_register_hardware);
MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
MODULE_DESCRIPTION("TPM Driver");
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index de0c796fce8..373b41f6b46 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -25,23 +25,38 @@
#include <linux/fs.h>
#include <linux/miscdevice.h>
-#define TPM_TIMEOUT msecs_to_jiffies(5)
+enum tpm_timeout {
+ TPM_TIMEOUT = 5, /* msecs */
+};
/* TPM addresses */
-#define TPM_ADDR 0x4E
-#define TPM_DATA 0x4F
+enum tpm_addr {
+ TPM_SUPERIO_ADDR = 0x2E,
+ TPM_ADDR = 0x4E,
+};
+
+extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr,
+ const char *, size_t);
struct tpm_chip;
struct tpm_vendor_specific {
u8 req_complete_mask;
u8 req_complete_val;
+ u8 req_canceled;
u16 base; /* TPM base address */
int (*recv) (struct tpm_chip *, u8 *, size_t);
int (*send) (struct tpm_chip *, u8 *, size_t);
void (*cancel) (struct tpm_chip *);
struct miscdevice miscdev;
+ struct attribute_group *attr_group;
};
struct tpm_chip {
@@ -58,29 +73,24 @@ struct tpm_chip {
struct timer_list user_read_timer; /* user needs to claim result */
struct semaphore tpm_mutex; /* tpm is processing */
- struct timer_list device_timer; /* tpm is processing */
- struct semaphore timer_manipulation_mutex;
struct tpm_vendor_specific *vendor;
struct list_head list;
};
-static inline int tpm_read_index(int index)
+static inline int tpm_read_index(int base, int index)
{
- outb(index, TPM_ADDR);
- return inb(TPM_DATA) & 0xFF;
+ outb(index, base);
+ return inb(base+1) & 0xFF;
}
-static inline void tpm_write_index(int index, int value)
+static inline void tpm_write_index(int base, int index, int value)
{
- outb(index, TPM_ADDR);
- outb(value & 0xFF, TPM_DATA);
+ outb(index, base);
+ outb(value & 0xFF, base+1);
}
-extern void tpm_time_expired(unsigned long);
-extern int tpm_lpc_bus_init(struct pci_dev *, u16);
-
extern int tpm_register_hardware(struct pci_dev *,
struct tpm_vendor_specific *);
extern int tpm_open(struct inode *, struct file *);
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c
index f9333e729b6..cc2cc77fd17 100644
--- a/drivers/char/tpm/tpm_atmel.c
+++ b/drivers/char/tpm/tpm_atmel.c
@@ -22,17 +22,23 @@
#include "tpm.h"
/* Atmel definitions */
-#define TPM_ATML_BASE 0x400
+enum tpm_atmel_addr {
+ TPM_ATMEL_BASE_ADDR_LO = 0x08,
+ TPM_ATMEL_BASE_ADDR_HI = 0x09
+};
/* write status bits */
-#define ATML_STATUS_ABORT 0x01
-#define ATML_STATUS_LASTBYTE 0x04
-
+enum tpm_atmel_write_status {
+ ATML_STATUS_ABORT = 0x01,
+ ATML_STATUS_LASTBYTE = 0x04
+};
/* read status bits */
-#define ATML_STATUS_BUSY 0x01
-#define ATML_STATUS_DATA_AVAIL 0x02
-#define ATML_STATUS_REWRITE 0x04
-
+enum tpm_atmel_read_status {
+ ATML_STATUS_BUSY = 0x01,
+ ATML_STATUS_DATA_AVAIL = 0x02,
+ ATML_STATUS_REWRITE = 0x04,
+ ATML_STATUS_READY = 0x08
+};
static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count)
{
@@ -121,13 +127,29 @@ static struct file_operations atmel_ops = {
.release = tpm_release,
};
+static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
+static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
+static DEVICE_ATTR(cancel, S_IWUSR |S_IWGRP, NULL, tpm_store_cancel);
+
+static struct attribute* atmel_attrs[] = {
+ &dev_attr_pubek.attr,
+ &dev_attr_pcrs.attr,
+ &dev_attr_caps.attr,
+ &dev_attr_cancel.attr,
+ 0,
+};
+
+static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs };
+
static struct tpm_vendor_specific tpm_atmel = {
.recv = tpm_atml_recv,
.send = tpm_atml_send,
.cancel = tpm_atml_cancel,
.req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL,
.req_complete_val = ATML_STATUS_DATA_AVAIL,
- .base = TPM_ATML_BASE,
+ .req_canceled = ATML_STATUS_READY,
+ .attr_group = &atmel_attr_grp,
.miscdev = { .fops = &atmel_ops, },
};
@@ -136,27 +158,29 @@ static int __devinit tpm_atml_init(struct pci_dev *pci_dev,
{
u8 version[4];
int rc = 0;
+ int lo, hi;
if (pci_enable_device(pci_dev))
return -EIO;
- if (tpm_lpc_bus_init(pci_dev, TPM_ATML_BASE)) {
- rc = -ENODEV;
- goto out_err;
- }
+ lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
+ hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
+
+ tpm_atmel.base = (hi<<8)|lo;
+ dev_dbg( &pci_dev->dev, "Operating with base: 0x%x\n", tpm_atmel.base);
/* verify that it is an Atmel part */
- if (tpm_read_index(4) != 'A' || tpm_read_index(5) != 'T'
- || tpm_read_index(6) != 'M' || tpm_read_index(7) != 'L') {
+ if (tpm_read_index(TPM_ADDR, 4) != 'A' || tpm_read_index(TPM_ADDR, 5) != 'T'
+ || tpm_read_index(TPM_ADDR, 6) != 'M' || tpm_read_index(TPM_ADDR, 7) != 'L') {
rc = -ENODEV;
goto out_err;
}
/* query chip for its version number */
- if ((version[0] = tpm_read_index(0x00)) != 0xFF) {
- version[1] = tpm_read_index(0x01);
- version[2] = tpm_read_index(0x02);
- version[3] = tpm_read_index(0x03);
+ if ((version[0] = tpm_read_index(TPM_ADDR, 0x00)) != 0xFF) {
+ version[1] = tpm_read_index(TPM_ADDR, 0x01);
+ version[2] = tpm_read_index(TPM_ADDR, 0x02);
+ version[3] = tpm_read_index(TPM_ADDR, 0x03);
} else {
dev_info(&pci_dev->dev, "version query failed\n");
rc = -ENODEV;
@@ -183,6 +207,7 @@ static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
{PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
+ {PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6LPC)},
{0,}
};
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c
index 9cce833a092..b4127348c06 100644
--- a/drivers/char/tpm/tpm_nsc.c
+++ b/drivers/char/tpm/tpm_nsc.c
@@ -22,43 +22,52 @@
#include "tpm.h"
/* National definitions */
-#define TPM_NSC_BASE 0x360
-#define TPM_NSC_IRQ 0x07
+enum tpm_nsc_addr{
+ TPM_NSC_IRQ = 0x07,
+ TPM_NSC_BASE0_HI = 0x60,
+ TPM_NSC_BASE0_LO = 0x61,
+ TPM_NSC_BASE1_HI = 0x62,
+ TPM_NSC_BASE1_LO = 0x63
+};
-#define NSC_LDN_INDEX 0x07
-#define NSC_SID_INDEX 0x20
-#define NSC_LDC_INDEX 0x30
-#define NSC_DIO_INDEX 0x60
-#define NSC_CIO_INDEX 0x62
-#define NSC_IRQ_INDEX 0x70
-#define NSC_ITS_INDEX 0x71
+enum tpm_nsc_index {
+ NSC_LDN_INDEX = 0x07,
+ NSC_SID_INDEX = 0x20,
+ NSC_LDC_INDEX = 0x30,
+ NSC_DIO_INDEX = 0x60,
+ NSC_CIO_INDEX = 0x62,
+ NSC_IRQ_INDEX = 0x70,
+ NSC_ITS_INDEX = 0x71
+};
-#define NSC_STATUS 0x01
-#define NSC_COMMAND 0x01
-#define NSC_DATA 0x00
+enum tpm_nsc_status_loc {
+ NSC_STATUS = 0x01,
+ NSC_COMMAND = 0x01,
+ NSC_DATA = 0x00
+};
/* status bits */
-#define NSC_STATUS_OBF 0x01 /* output buffer full */
-#define NSC_STATUS_IBF 0x02 /* input buffer full */
-#define NSC_STATUS_F0 0x04 /* F0 */
-#define NSC_STATUS_A2 0x08 /* A2 */
-#define NSC_STATUS_RDY 0x10 /* ready to receive command */
-#define NSC_STATUS_IBR 0x20 /* ready to receive data */
+enum tpm_nsc_status {
+ NSC_STATUS_OBF = 0x01, /* output buffer full */
+ NSC_STATUS_IBF = 0x02, /* input buffer full */
+ NSC_STATUS_F0 = 0x04, /* F0 */
+ NSC_STATUS_A2 = 0x08, /* A2 */
+ NSC_STATUS_RDY = 0x10, /* ready to receive command */
+ NSC_STATUS_IBR = 0x20 /* ready to receive data */
+};
/* command bits */
-#define NSC_COMMAND_NORMAL 0x01 /* normal mode */
-#define NSC_COMMAND_EOC 0x03
-#define NSC_COMMAND_CANCEL 0x22
-
+enum tpm_nsc_cmd_mode {
+ NSC_COMMAND_NORMAL = 0x01, /* normal mode */
+ NSC_COMMAND_EOC = 0x03,
+ NSC_COMMAND_CANCEL = 0x22
+};
/*
* Wait for a certain status to appear
*/
static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
{
- int expired = 0;
- struct timer_list status_timer =
- TIMER_INITIALIZER(tpm_time_expired, jiffies + 10 * HZ,
- (unsigned long) &expired);
+ unsigned long stop;
/* status immediately available check */
*data = inb(chip->vendor->base + NSC_STATUS);
@@ -66,17 +75,14 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
return 0;
/* wait for status */
- add_timer(&status_timer);
+ stop = jiffies + 10 * HZ;
do {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(TPM_TIMEOUT);
+ msleep(TPM_TIMEOUT);
*data = inb(chip->vendor->base + 1);
- if ((*data & mask) == val) {
- del_singleshot_timer_sync(&status_timer);
+ if ((*data & mask) == val)
return 0;
- }
}
- while (!expired);
+ while (time_before(jiffies, stop));
return -EBUSY;
}
@@ -84,10 +90,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
static int nsc_wait_for_ready(struct tpm_chip *chip)
{
int status;
- int expired = 0;
- struct timer_list status_timer =
- TIMER_INITIALIZER(tpm_time_expired, jiffies + 100,
- (unsigned long) &expired);
+ unsigned long stop;
/* status immediately available check */
status = inb(chip->vendor->base + NSC_STATUS);
@@ -97,19 +100,16 @@ static int nsc_wait_for_ready(struct tpm_chip *chip)
return 0;
/* wait for status */
- add_timer(&status_timer);
+ stop = jiffies + 100;
do {
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(TPM_TIMEOUT);
+ msleep(TPM_TIMEOUT);
status = inb(chip->vendor->base + NSC_STATUS);
if (status & NSC_STATUS_OBF)
status = inb(chip->vendor->base + NSC_DATA);
- if (status & NSC_STATUS_RDY) {
- del_singleshot_timer_sync(&status_timer);
+ if (status & NSC_STATUS_RDY)
return 0;
- }
}
- while (!expired);
+ while (time_before(jiffies, stop));
dev_info(&chip->pci_dev->dev, "wait for ready failed\n");
return -EBUSY;
@@ -150,7 +150,8 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
*p = inb(chip->vendor->base + NSC_DATA);
}
- if ((data & NSC_STATUS_F0) == 0) {
+ if ((data & NSC_STATUS_F0) == 0 &&
+ (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0)) {
dev_err(&chip->pci_dev->dev, "F0 not set\n");
return -EIO;
}
@@ -228,100 +229,95 @@ static struct file_operations nsc_ops = {
.release = tpm_release,
};
+static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
+static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
+static DEVICE_ATTR(cancel, S_IWUSR|S_IWGRP, NULL, tpm_store_cancel);
+
+static struct attribute * nsc_attrs[] = {
+ &dev_attr_pubek.attr,
+ &dev_attr_pcrs.attr,
+ &dev_attr_caps.attr,
+ &dev_attr_cancel.attr,
+ 0,
+};
+
+static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs };
+
static struct tpm_vendor_specific tpm_nsc = {
.recv = tpm_nsc_recv,
.send = tpm_nsc_send,
.cancel = tpm_nsc_cancel,
.req_complete_mask = NSC_STATUS_OBF,
.req_complete_val = NSC_STATUS_OBF,
- .base = TPM_NSC_BASE,
+ .req_canceled = NSC_STATUS_RDY,
+ .attr_group = &nsc_attr_grp,
.miscdev = { .fops = &nsc_ops, },
-
};
static int __devinit tpm_nsc_init(struct pci_dev *pci_dev,
const struct pci_device_id *pci_id)
{
int rc = 0;
+ int lo, hi;
+ int nscAddrBase = TPM_ADDR;
+
if (pci_enable_device(pci_dev))
return -EIO;
- if (tpm_lpc_bus_init(pci_dev, TPM_NSC_BASE)) {
- rc = -ENODEV;
- goto out_err;
- }
+ /* select PM channel 1 */
+ tpm_write_index(nscAddrBase,NSC_LDN_INDEX, 0x12);
/* verify that it is a National part (SID) */
- if (tpm_read_index(NSC_SID_INDEX) != 0xEF) {
- rc = -ENODEV;
- goto out_err;
+ if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) {
+ nscAddrBase = (tpm_read_index(TPM_SUPERIO_ADDR, 0x2C)<<8)|
+ (tpm_read_index(TPM_SUPERIO_ADDR, 0x2B)&0xFE);
+ if (tpm_read_index(nscAddrBase, NSC_SID_INDEX) != 0xF6) {
+ rc = -ENODEV;
+ goto out_err;
+ }
}
+ hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI);
+ lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO);
+ tpm_nsc.base = (hi<<8) | lo;
+
dev_dbg(&pci_dev->dev, "NSC TPM detected\n");
dev_dbg(&pci_dev->dev,
"NSC LDN 0x%x, SID 0x%x, SRID 0x%x\n",
- tpm_read_index(0x07), tpm_read_index(0x20),
- tpm_read_index(0x27));
+ tpm_read_index(nscAddrBase,0x07), tpm_read_index(nscAddrBase,0x20),
+ tpm_read_index(nscAddrBase,0x27));
dev_dbg(&pci_dev->dev,
"NSC SIOCF1 0x%x SIOCF5 0x%x SIOCF6 0x%x SIOCF8 0x%x\n",
- tpm_read_index(0x21), tpm_read_index(0x25),
- tpm_read_index(0x26), tpm_read_index(0x28));
+ tpm_read_index(nscAddrBase,0x21), tpm_read_index(nscAddrBase,0x25),
+ tpm_read_index(nscAddrBase,0x26), tpm_read_index(nscAddrBase,0x28));
dev_dbg(&pci_dev->dev, "NSC IO Base0 0x%x\n",
- (tpm_read_index(0x60) << 8) | tpm_read_index(0x61));
+ (tpm_read_index(nscAddrBase,0x60) << 8) | tpm_read_index(nscAddrBase,0x61));
dev_dbg(&pci_dev->dev, "NSC IO Base1 0x%x\n",
- (tpm_read_index(0x62) << 8) | tpm_read_index(0x63));
+ (tpm_read_index(nscAddrBase,0x62) << 8) | tpm_read_index(nscAddrBase,0x63));
dev_dbg(&pci_dev->dev, "NSC Interrupt number and wakeup 0x%x\n",
- tpm_read_index(0x70));
+ tpm_read_index(nscAddrBase,0x70));
dev_dbg(&pci_dev->dev, "NSC IRQ type select 0x%x\n",
- tpm_read_index(0x71));
+ tpm_read_index(nscAddrBase,0x71));
dev_dbg(&pci_dev->dev,
"NSC DMA channel select0 0x%x, select1 0x%x\n",
- tpm_read_index(0x74), tpm_read_index(0x75));
+ tpm_read_index(nscAddrBase,0x74), tpm_read_index(nscAddrBase,0x75));
dev_dbg(&pci_dev->dev,
"NSC Config "
"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
- tpm_read_index(0xF0), tpm_read_index(0xF1),
- tpm_read_index(0xF2), tpm_read_index(0xF3),
- tpm_read_index(0xF4), tpm_read_index(0xF5),
- tpm_read_index(0xF6), tpm_read_index(0xF7),
- tpm_read_index(0xF8), tpm_read_index(0xF9));
+ tpm_read_index(nscAddrBase,0xF0), tpm_read_index(nscAddrBase,0xF1),
+ tpm_read_index(nscAddrBase,0xF2), tpm_read_index(nscAddrBase,0xF3),
+ tpm_read_index(nscAddrBase,0xF4), tpm_read_index(nscAddrBase,0xF5),
+ tpm_read_index(nscAddrBase,0xF6), tpm_read_index(nscAddrBase,0xF7),
+ tpm_read_index(nscAddrBase,0xF8), tpm_read_index(nscAddrBase,0xF9));
dev_info(&pci_dev->dev,
- "NSC PC21100 TPM revision %d\n",
- tpm_read_index(0x27) & 0x1F);
-
- if (tpm_read_index(NSC_LDC_INDEX) == 0)
- dev_info(&pci_dev->dev, ": NSC TPM not active\n");
-
- /* select PM channel 1 */
- tpm_write_index(NSC_LDN_INDEX, 0x12);
- tpm_read_index(NSC_LDN_INDEX);
-
- /* disable the DPM module */
- tpm_write_index(NSC_LDC_INDEX, 0);
- tpm_read_index(NSC_LDC_INDEX);
-
- /* set the data register base addresses */
- tpm_write_index(NSC_DIO_INDEX, TPM_NSC_BASE >> 8);
- tpm_write_index(NSC_DIO_INDEX + 1, TPM_NSC_BASE);
- tpm_read_index(NSC_DIO_INDEX);
- tpm_read_index(NSC_DIO_INDEX + 1);
-
- /* set the command register base addresses */
- tpm_write_index(NSC_CIO_INDEX, (TPM_NSC_BASE + 1) >> 8);
- tpm_write_index(NSC_CIO_INDEX + 1, (TPM_NSC_BASE + 1));
- tpm_read_index(NSC_DIO_INDEX);
- tpm_read_index(NSC_DIO_INDEX + 1);
-
- /* set the interrupt number to be used for the host interface */
- tpm_write_index(NSC_IRQ_INDEX, TPM_NSC_IRQ);
- tpm_write_index(NSC_ITS_INDEX, 0x00);
- tpm_read_index(NSC_IRQ_INDEX);
+ "NSC TPM revision %d\n",
+ tpm_read_index(nscAddrBase, 0x27) & 0x1F);
/* enable the DPM module */
- tpm_write_index(NSC_LDC_INDEX, 0x01);
- tpm_read_index(NSC_LDC_INDEX);
+ tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01);
if ((rc = tpm_register_hardware(pci_dev, &tpm_nsc)) < 0)
goto out_err;
@@ -339,6 +335,9 @@ static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0)},
{PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
{0,}
};
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 26e5e19ed85..6e4be3bb2d8 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -94,6 +94,7 @@
#include <linux/idr.h>
#include <linux/wait.h>
#include <linux/bitops.h>
+#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -251,7 +252,7 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
static DEFINE_SPINLOCK(tty_ldisc_lock);
static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
-static struct tty_ldisc tty_ldiscs[NR_LDISCS]; /* line disc dispatch table */
+static struct tty_ldisc tty_ldiscs[NR_LDISCS]; /* line disc dispatch table */
int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
{
@@ -262,24 +263,35 @@ int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
return -EINVAL;
spin_lock_irqsave(&tty_ldisc_lock, flags);
- if (new_ldisc) {
- tty_ldiscs[disc] = *new_ldisc;
- tty_ldiscs[disc].num = disc;
- tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
- tty_ldiscs[disc].refcount = 0;
- } else {
- if(tty_ldiscs[disc].refcount)
- ret = -EBUSY;
- else
- tty_ldiscs[disc].flags &= ~LDISC_FLAG_DEFINED;
- }
+ tty_ldiscs[disc] = *new_ldisc;
+ tty_ldiscs[disc].num = disc;
+ tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
+ tty_ldiscs[disc].refcount = 0;
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
return ret;
}
-
EXPORT_SYMBOL(tty_register_ldisc);
+int tty_unregister_ldisc(int disc)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ if (disc < N_TTY || disc >= NR_LDISCS)
+ return -EINVAL;
+
+ spin_lock_irqsave(&tty_ldisc_lock, flags);
+ if (tty_ldiscs[disc].refcount)
+ ret = -EBUSY;
+ else
+ tty_ldiscs[disc].flags &= ~LDISC_FLAG_DEFINED;
+ spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+
+ return ret;
+}
+EXPORT_SYMBOL(tty_unregister_ldisc);
+
struct tty_ldisc *tty_ldisc_get(int disc)
{
unsigned long flags;
@@ -2169,12 +2181,11 @@ static int tiocsetd(struct tty_struct *tty, int __user *p)
return tty_set_ldisc(tty, ldisc);
}
-static int send_break(struct tty_struct *tty, int duration)
+static int send_break(struct tty_struct *tty, unsigned int duration)
{
tty->driver->break_ctl(tty, -1);
if (!signal_pending(current)) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(duration);
+ msleep_interruptible(duration);
}
tty->driver->break_ctl(tty, 0);
if (signal_pending(current))
@@ -2355,10 +2366,10 @@ int tty_ioctl(struct inode * inode, struct file * file,
* all by anyone?
*/
if (!arg)
- return send_break(tty, HZ/4);
+ return send_break(tty, 250);
return 0;
case TCSBRKP: /* support for POSIX tcsendbreak() */
- return send_break(tty, arg ? arg*(HZ/10) : HZ/4);
+ return send_break(tty, arg ? arg*100 : 250);
case TIOCMGET:
return tty_tiocmget(tty, file, p);
@@ -2654,7 +2665,7 @@ static void tty_default_put_char(struct tty_struct *tty, unsigned char ch)
tty->driver->write(tty, &ch, 1);
}
-static struct class_simple *tty_class;
+static struct class *tty_class;
/**
* tty_register_device - register a tty device
@@ -2687,7 +2698,7 @@ void tty_register_device(struct tty_driver *driver, unsigned index,
pty_line_name(driver, index, name);
else
tty_line_name(driver, index, name);
- class_simple_device_add(tty_class, dev, device, name);
+ class_device_create(tty_class, dev, device, name);
}
/**
@@ -2701,7 +2712,7 @@ void tty_register_device(struct tty_driver *driver, unsigned index,
void tty_unregister_device(struct tty_driver *driver, unsigned index)
{
devfs_remove("%s%d", driver->devfs_name, index + driver->name_base);
- class_simple_device_remove(MKDEV(driver->major, driver->minor_start) + index);
+ class_device_destroy(tty_class, MKDEV(driver->major, driver->minor_start) + index);
}
EXPORT_SYMBOL(tty_register_device);
@@ -2918,7 +2929,7 @@ extern int vty_init(void);
static int __init tty_class_init(void)
{
- tty_class = class_simple_create(THIS_MODULE, "tty");
+ tty_class = class_create(THIS_MODULE, "tty");
if (IS_ERR(tty_class))
return PTR_ERR(tty_class);
return 0;
@@ -2947,14 +2958,14 @@ static int __init tty_init(void)
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
panic("Couldn't register /dev/tty driver\n");
devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 0), S_IFCHR|S_IRUGO|S_IWUGO, "tty");
- class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");
+ class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");
cdev_init(&console_cdev, &console_fops);
if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
panic("Couldn't register /dev/console driver\n");
devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console");
- class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
+ class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
#ifdef CONFIG_UNIX98_PTYS
cdev_init(&ptmx_cdev, &ptmx_fops);
@@ -2962,7 +2973,7 @@ static int __init tty_init(void)
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
panic("Couldn't register /dev/ptmx driver\n");
devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx");
- class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
+ class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
#endif
#ifdef CONFIG_VT
@@ -2971,7 +2982,7 @@ static int __init tty_init(void)
register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
panic("Couldn't register /dev/tty0 driver\n");
devfs_mk_cdev(MKDEV(TTY_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vc/0");
- class_simple_device_add(tty_class, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
+ class_device_create(tty_class, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
vty_init();
#endif
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index 7abe405b865..79c2928a881 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -474,7 +474,7 @@ static struct file_operations vcs_fops = {
.open = vcs_open,
};
-static struct class_simple *vc_class;
+static struct class *vc_class;
void vcs_make_devfs(struct tty_struct *tty)
{
@@ -484,26 +484,26 @@ void vcs_make_devfs(struct tty_struct *tty)
devfs_mk_cdev(MKDEV(VCS_MAJOR, tty->index + 129),
S_IFCHR|S_IRUSR|S_IWUSR,
"vcc/a%u", tty->index + 1);
- class_simple_device_add(vc_class, MKDEV(VCS_MAJOR, tty->index + 1), NULL, "vcs%u", tty->index + 1);
- class_simple_device_add(vc_class, MKDEV(VCS_MAJOR, tty->index + 129), NULL, "vcsa%u", tty->index + 1);
+ class_device_create(vc_class, MKDEV(VCS_MAJOR, tty->index + 1), NULL, "vcs%u", tty->index + 1);
+ class_device_create(vc_class, MKDEV(VCS_MAJOR, tty->index + 129), NULL, "vcsa%u", tty->index + 1);
}
void vcs_remove_devfs(struct tty_struct *tty)
{
devfs_remove("vcc/%u", tty->index + 1);
devfs_remove("vcc/a%u", tty->index + 1);
- class_simple_device_remove(MKDEV(VCS_MAJOR, tty->index + 1));
- class_simple_device_remove(MKDEV(VCS_MAJOR, tty->index + 129));
+ class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 1));
+ class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 129));
}
int __init vcs_init(void)
{
if (register_chrdev(VCS_MAJOR, "vcs", &vcs_fops))
panic("unable to get major %d for vcs device", VCS_MAJOR);
- vc_class = class_simple_create(THIS_MODULE, "vc");
+ vc_class = class_create(THIS_MODULE, "vc");
devfs_mk_cdev(MKDEV(VCS_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/0");
devfs_mk_cdev(MKDEV(VCS_MAJOR, 128), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/a0");
- class_simple_device_add(vc_class, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
- class_simple_device_add(vc_class, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
+ class_device_create(vc_class, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
+ class_device_create(vc_class, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
return 0;
}
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index aea3cbf5219..4764b4f9555 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -237,7 +237,7 @@ static dma_addr_t viotape_unitinfo_token;
static struct mtget viomtget[VIOTAPE_MAX_TAPE];
-static struct class_simple *tape_class;
+static struct class *tape_class;
static struct device *tape_device[VIOTAPE_MAX_TAPE];
@@ -956,9 +956,9 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id)
state[i].cur_part = 0;
for (j = 0; j < MAX_PARTITIONS; ++j)
state[i].part_stat_rwi[j] = VIOT_IDLE;
- class_simple_device_add(tape_class, MKDEV(VIOTAPE_MAJOR, i), NULL,
+ class_device_create(tape_class, MKDEV(VIOTAPE_MAJOR, i), NULL,
"iseries!vt%d", i);
- class_simple_device_add(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80),
+ class_device_create(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80),
NULL, "iseries!nvt%d", i);
devfs_mk_cdev(MKDEV(VIOTAPE_MAJOR, i), S_IFCHR | S_IRUSR | S_IWUSR,
"iseries/vt%d", i);
@@ -980,8 +980,8 @@ static int viotape_remove(struct vio_dev *vdev)
devfs_remove("iseries/nvt%d", i);
devfs_remove("iseries/vt%d", i);
devfs_unregister_tape(state[i].dev_handle);
- class_simple_device_remove(MKDEV(VIOTAPE_MAJOR, i | 0x80));
- class_simple_device_remove(MKDEV(VIOTAPE_MAJOR, i));
+ class_device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80));
+ class_device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i));
return 0;
}
@@ -1045,7 +1045,7 @@ int __init viotap_init(void)
goto clear_handler;
}
- tape_class = class_simple_create(THIS_MODULE, "tape");
+ tape_class = class_create(THIS_MODULE, "tape");
if (IS_ERR(tape_class)) {
printk(VIOTAPE_KERN_WARN "Unable to allocat class\n");
ret = PTR_ERR(tape_class);
@@ -1070,7 +1070,7 @@ int __init viotap_init(void)
return 0;
unreg_class:
- class_simple_destroy(tape_class);
+ class_destroy(tape_class);
unreg_chrdev:
unregister_chrdev(VIOTAPE_MAJOR, "viotape");
clear_handler:
@@ -1110,7 +1110,7 @@ static void __exit viotap_exit(void)
remove_proc_entry("iSeries/viotape", NULL);
vio_unregister_driver(&viotape_driver);
- class_simple_destroy(tape_class);
+ class_destroy(tape_class);
ret = unregister_chrdev(VIOTAPE_MAJOR, "viotape");
if (ret < 0)
printk(VIOTAPE_KERN_WARN "Error unregistering device: %d\n",
diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c
new file mode 100644
index 00000000000..683278bc524
--- /dev/null
+++ b/drivers/char/vr41xx_giu.c
@@ -0,0 +1,743 @@
+/*
+ * Driver for NEC VR4100 series General-purpose I/O Unit.
+ *
+ * Copyright (C) 2002 MontaVista Software Inc.
+ * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
+ * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ * 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 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 <linux/device.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <asm/cpu.h>
+#include <asm/io.h>
+#include <asm/vr41xx/giu.h>
+#include <asm/vr41xx/vr41xx.h>
+
+MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>");
+MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver");
+MODULE_LICENSE("GPL");
+
+static int major; /* default is dynamic major device number */
+module_param(major, int, 0);
+MODULE_PARM_DESC(major, "Major device number");
+
+#define GIU_TYPE1_START 0x0b000100UL
+#define GIU_TYPE1_SIZE 0x20UL
+
+#define GIU_TYPE2_START 0x0f000140UL
+#define GIU_TYPE2_SIZE 0x20UL
+
+#define GIU_TYPE3_START 0x0f000140UL
+#define GIU_TYPE3_SIZE 0x28UL
+
+#define GIU_PULLUPDOWN_START 0x0b0002e0UL
+#define GIU_PULLUPDOWN_SIZE 0x04UL
+
+#define GIUIOSELL 0x00
+#define GIUIOSELH 0x02
+#define GIUPIODL 0x04
+#define GIUPIODH 0x06
+#define GIUINTSTATL 0x08
+#define GIUINTSTATH 0x0a
+#define GIUINTENL 0x0c
+#define GIUINTENH 0x0e
+#define GIUINTTYPL 0x10
+#define GIUINTTYPH 0x12
+#define GIUINTALSELL 0x14
+#define GIUINTALSELH 0x16
+#define GIUINTHTSELL 0x18
+#define GIUINTHTSELH 0x1a
+#define GIUPODATL 0x1c
+#define GIUPODATEN 0x1c
+#define GIUPODATH 0x1e
+ #define PIOEN0 0x0100
+ #define PIOEN1 0x0200
+#define GIUPODAT 0x1e
+#define GIUFEDGEINHL 0x20
+#define GIUFEDGEINHH 0x22
+#define GIUREDGEINHL 0x24
+#define GIUREDGEINHH 0x26
+
+#define GIUUSEUPDN 0x1e0
+#define GIUTERMUPDN 0x1e2
+
+#define GPIO_HAS_PULLUPDOWN_IO 0x0001
+#define GPIO_HAS_OUTPUT_ENABLE 0x0002
+#define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100
+
+static spinlock_t giu_lock;
+static struct resource *giu_resource1;
+static struct resource *giu_resource2;
+static unsigned long giu_flags;
+static unsigned int giu_nr_pins;
+
+static void __iomem *giu_base;
+
+#define giu_read(offset) readw(giu_base + (offset))
+#define giu_write(offset, value) writew((value), giu_base + (offset))
+
+#define GPIO_PIN_OF_IRQ(irq) ((irq) - GIU_IRQ_BASE)
+#define GIUINT_HIGH_OFFSET 16
+#define GIUINT_HIGH_MAX 32
+
+static inline uint16_t giu_set(uint16_t offset, uint16_t set)
+{
+ uint16_t data;
+
+ data = giu_read(offset);
+ data |= set;
+ giu_write(offset, data);
+
+ return data;
+}
+
+static inline uint16_t giu_clear(uint16_t offset, uint16_t clear)
+{
+ uint16_t data;
+
+ data = giu_read(offset);
+ data &= ~clear;
+ giu_write(offset, data);
+
+ return data;
+}
+
+static unsigned int startup_giuint_low_irq(unsigned int irq)
+{
+ unsigned int pin;
+
+ pin = GPIO_PIN_OF_IRQ(irq);
+ giu_write(GIUINTSTATL, 1 << pin);
+ giu_set(GIUINTENL, 1 << pin);
+
+ return 0;
+}
+
+static void shutdown_giuint_low_irq(unsigned int irq)
+{
+ giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
+}
+
+static void enable_giuint_low_irq(unsigned int irq)
+{
+ giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
+}
+
+#define disable_giuint_low_irq shutdown_giuint_low_irq
+
+static void ack_giuint_low_irq(unsigned int irq)
+{
+ unsigned int pin;
+
+ pin = GPIO_PIN_OF_IRQ(irq);
+ giu_clear(GIUINTENL, 1 << pin);
+ giu_write(GIUINTSTATL, 1 << pin);
+}
+
+static void end_giuint_low_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
+}
+
+static struct hw_interrupt_type giuint_low_irq_type = {
+ .typename = "GIUINTL",
+ .startup = startup_giuint_low_irq,
+ .shutdown = shutdown_giuint_low_irq,
+ .enable = enable_giuint_low_irq,
+ .disable = disable_giuint_low_irq,
+ .ack = ack_giuint_low_irq,
+ .end = end_giuint_low_irq,
+};
+
+static unsigned int startup_giuint_high_irq(unsigned int irq)
+{
+ unsigned int pin;
+
+ pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET;
+ giu_write(GIUINTSTATH, 1 << pin);
+ giu_set(GIUINTENH, 1 << pin);
+
+ return 0;
+}
+
+static void shutdown_giuint_high_irq(unsigned int irq)
+{
+ giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
+}
+
+static void enable_giuint_high_irq(unsigned int irq)
+{
+ giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
+}
+
+#define disable_giuint_high_irq shutdown_giuint_high_irq
+
+static void ack_giuint_high_irq(unsigned int irq)
+{
+ unsigned int pin;
+
+ pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET;
+ giu_clear(GIUINTENH, 1 << pin);
+ giu_write(GIUINTSTATH, 1 << pin);
+}
+
+static void end_giuint_high_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+ giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
+}
+
+static struct hw_interrupt_type giuint_high_irq_type = {
+ .typename = "GIUINTH",
+ .startup = startup_giuint_high_irq,
+ .shutdown = shutdown_giuint_high_irq,
+ .enable = enable_giuint_high_irq,
+ .disable = disable_giuint_high_irq,
+ .ack = ack_giuint_high_irq,
+ .end = end_giuint_high_irq,
+};
+
+static int giu_get_irq(unsigned int irq, struct pt_regs *regs)
+{
+ uint16_t pendl, pendh, maskl, maskh;
+ int i;
+
+ pendl = giu_read(GIUINTSTATL);
+ pendh = giu_read(GIUINTSTATH);
+ maskl = giu_read(GIUINTENL);
+ maskh = giu_read(GIUINTENH);
+
+ maskl &= pendl;
+ maskh &= pendh;
+
+ if (maskl) {
+ for (i = 0; i < 16; i++) {
+ if (maskl & (1 << i))
+ return GIU_IRQ(i);
+ }
+ } else if (maskh) {
+ for (i = 0; i < 16; i++) {
+ if (maskh & (1 << i))
+ return GIU_IRQ(i + GIUINT_HIGH_OFFSET);
+ }
+ }
+
+ printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n",
+ maskl, pendl, maskh, pendh);
+
+ atomic_inc(&irq_err_count);
+
+ return -EINVAL;
+}
+
+void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal)
+{
+ uint16_t mask;
+
+ if (pin < GIUINT_HIGH_OFFSET) {
+ mask = 1 << pin;
+ if (trigger != IRQ_TRIGGER_LEVEL) {
+ giu_set(GIUINTTYPL, mask);
+ if (signal == IRQ_SIGNAL_HOLD)
+ giu_set(GIUINTHTSELL, mask);
+ else
+ giu_clear(GIUINTHTSELL, mask);
+ if (current_cpu_data.cputype == CPU_VR4133) {
+ switch (trigger) {
+ case IRQ_TRIGGER_EDGE_FALLING:
+ giu_set(GIUFEDGEINHL, mask);
+ giu_clear(GIUREDGEINHL, mask);
+ break;
+ case IRQ_TRIGGER_EDGE_RISING:
+ giu_clear(GIUFEDGEINHL, mask);
+ giu_set(GIUREDGEINHL, mask);
+ break;
+ default:
+ giu_set(GIUFEDGEINHL, mask);
+ giu_set(GIUREDGEINHL, mask);
+ break;
+ }
+ }
+ } else {
+ giu_clear(GIUINTTYPL, mask);
+ giu_clear(GIUINTHTSELL, mask);
+ }
+ giu_write(GIUINTSTATL, mask);
+ } else if (pin < GIUINT_HIGH_MAX) {
+ mask = 1 << (pin - GIUINT_HIGH_OFFSET);
+ if (trigger != IRQ_TRIGGER_LEVEL) {
+ giu_set(GIUINTTYPH, mask);
+ if (signal == IRQ_SIGNAL_HOLD)
+ giu_set(GIUINTHTSELH, mask);
+ else
+ giu_clear(GIUINTHTSELH, mask);
+ if (current_cpu_data.cputype == CPU_VR4133) {
+ switch (trigger) {
+ case IRQ_TRIGGER_EDGE_FALLING:
+ giu_set(GIUFEDGEINHH, mask);
+ giu_clear(GIUREDGEINHH, mask);
+ break;
+ case IRQ_TRIGGER_EDGE_RISING:
+ giu_clear(GIUFEDGEINHH, mask);
+ giu_set(GIUREDGEINHH, mask);
+ break;
+ default:
+ giu_set(GIUFEDGEINHH, mask);
+ giu_set(GIUREDGEINHH, mask);
+ break;
+ }
+ }
+ } else {
+ giu_clear(GIUINTTYPH, mask);
+ giu_clear(GIUINTHTSELH, mask);
+ }
+ giu_write(GIUINTSTATH, mask);
+ }
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);
+
+void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
+{
+ uint16_t mask;
+
+ if (pin < GIUINT_HIGH_OFFSET) {
+ mask = 1 << pin;
+ if (level == IRQ_LEVEL_HIGH)
+ giu_set(GIUINTALSELL, mask);
+ else
+ giu_clear(GIUINTALSELL, mask);
+ giu_write(GIUINTSTATL, mask);
+ } else if (pin < GIUINT_HIGH_MAX) {
+ mask = 1 << (pin - GIUINT_HIGH_OFFSET);
+ if (level == IRQ_LEVEL_HIGH)
+ giu_set(GIUINTALSELH, mask);
+ else
+ giu_clear(GIUINTALSELH, mask);
+ giu_write(GIUINTSTATH, mask);
+ }
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);
+
+gpio_data_t vr41xx_gpio_get_pin(unsigned int pin)
+{
+ uint16_t reg, mask;
+
+ if (pin >= giu_nr_pins)
+ return GPIO_DATA_INVAL;
+
+ if (pin < 16) {
+ reg = giu_read(GIUPIODL);
+ mask = (uint16_t)1 << pin;
+ } else if (pin < 32) {
+ reg = giu_read(GIUPIODH);
+ mask = (uint16_t)1 << (pin - 16);
+ } else if (pin < 48) {
+ reg = giu_read(GIUPODATL);
+ mask = (uint16_t)1 << (pin - 32);
+ } else {
+ reg = giu_read(GIUPODATH);
+ mask = (uint16_t)1 << (pin - 48);
+ }
+
+ if (reg & mask)
+ return GPIO_DATA_HIGH;
+
+ return GPIO_DATA_LOW;
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin);
+
+int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data)
+{
+ uint16_t offset, mask, reg;
+ unsigned long flags;
+
+ if (pin >= giu_nr_pins)
+ return -EINVAL;
+
+ if (pin < 16) {
+ offset = GIUPIODL;
+ mask = (uint16_t)1 << pin;
+ } else if (pin < 32) {
+ offset = GIUPIODH;
+ mask = (uint16_t)1 << (pin - 16);
+ } else if (pin < 48) {
+ offset = GIUPODATL;
+ mask = (uint16_t)1 << (pin - 32);
+ } else {
+ offset = GIUPODATH;
+ mask = (uint16_t)1 << (pin - 48);
+ }
+
+ spin_lock_irqsave(&giu_lock, flags);
+
+ reg = giu_read(offset);
+ if (data == GPIO_DATA_HIGH)
+ reg |= mask;
+ else
+ reg &= ~mask;
+ giu_write(offset, reg);
+
+ spin_unlock_irqrestore(&giu_lock, flags);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin);
+
+int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir)
+{
+ uint16_t offset, mask, reg;
+ unsigned long flags;
+
+ if (pin >= giu_nr_pins)
+ return -EINVAL;
+
+ if (pin < 16) {
+ offset = GIUIOSELL;
+ mask = (uint16_t)1 << pin;
+ } else if (pin < 32) {
+ offset = GIUIOSELH;
+ mask = (uint16_t)1 << (pin - 16);
+ } else {
+ if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) {
+ offset = GIUPODATEN;
+ mask = (uint16_t)1 << (pin - 32);
+ } else {
+ switch (pin) {
+ case 48:
+ offset = GIUPODATH;
+ mask = PIOEN0;
+ break;
+ case 49:
+ offset = GIUPODATH;
+ mask = PIOEN1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+ }
+
+ spin_lock_irqsave(&giu_lock, flags);
+
+ reg = giu_read(offset);
+ if (dir == GPIO_OUTPUT)
+ reg |= mask;
+ else
+ reg &= ~mask;
+ giu_write(offset, reg);
+
+ spin_unlock_irqrestore(&giu_lock, flags);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction);
+
+int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
+{
+ uint16_t reg, mask;
+ unsigned long flags;
+
+ if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO)
+ return -EPERM;
+
+ if (pin >= 15)
+ return -EINVAL;
+
+ mask = (uint16_t)1 << pin;
+
+ spin_lock_irqsave(&giu_lock, flags);
+
+ if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) {
+ reg = giu_read(GIUTERMUPDN);
+ if (pull == GPIO_PULL_UP)
+ reg |= mask;
+ else
+ reg &= ~mask;
+ giu_write(GIUTERMUPDN, reg);
+
+ reg = giu_read(GIUUSEUPDN);
+ reg |= mask;
+ giu_write(GIUUSEUPDN, reg);
+ } else {
+ reg = giu_read(GIUUSEUPDN);
+ reg &= ~mask;
+ giu_write(GIUUSEUPDN, reg);
+ }
+
+ spin_unlock_irqrestore(&giu_lock, flags);
+
+ return 0;
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown);
+
+static ssize_t gpio_read(struct file *file, char __user *buf, size_t len,
+ loff_t *ppos)
+{
+ unsigned int pin;
+ char value = '0';
+
+ pin = iminor(file->f_dentry->d_inode);
+ if (pin >= giu_nr_pins)
+ return -EBADF;
+
+ if (vr41xx_gpio_get_pin(pin) == GPIO_DATA_HIGH)
+ value = '1';
+
+ if (len <= 0)
+ return -EFAULT;
+
+ if (put_user(value, buf))
+ return -EFAULT;
+
+ return 1;
+}
+
+static ssize_t gpio_write(struct file *file, const char __user *data,
+ size_t len, loff_t *ppos)
+{
+ unsigned int pin;
+ size_t i;
+ char c;
+ int retval = 0;
+
+ pin = iminor(file->f_dentry->d_inode);
+ if (pin >= giu_nr_pins)
+ return -EBADF;
+
+ for (i = 0; i < len; i++) {
+ if (get_user(c, data + i))
+ return -EFAULT;
+
+ switch (c) {
+ case '0':
+ retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_LOW);
+ break;
+ case '1':
+ retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_HIGH);
+ break;
+ case 'D':
+ printk(KERN_INFO "GPIO%d: pull down\n", pin);
+ retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DOWN);
+ break;
+ case 'd':
+ printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin);
+ retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE);
+ break;
+ case 'I':
+ printk(KERN_INFO "GPIO%d: input\n", pin);
+ retval = vr41xx_gpio_set_direction(pin, GPIO_INPUT);
+ break;
+ case 'O':
+ printk(KERN_INFO "GPIO%d: output\n", pin);
+ retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT);
+ break;
+ case 'o':
+ printk(KERN_INFO "GPIO%d: output disable\n", pin);
+ retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT_DISABLE);
+ break;
+ case 'P':
+ printk(KERN_INFO "GPIO%d: pull up\n", pin);
+ retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_UP);
+ break;
+ case 'p':
+ printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin);
+ retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE);
+ break;
+ default:
+ break;
+ }
+
+ if (retval < 0)
+ break;
+ }
+
+ return i;
+}
+
+static int gpio_open(struct inode *inode, struct file *file)
+{
+ unsigned int pin;
+
+ pin = iminor(inode);
+ if (pin >= giu_nr_pins)
+ return -EBADF;
+
+ return nonseekable_open(inode, file);
+}
+
+static int gpio_release(struct inode *inode, struct file *file)
+{
+ unsigned int pin;
+
+ pin = iminor(inode);
+ if (pin >= giu_nr_pins)
+ return -EBADF;
+
+ return 0;
+}
+
+static struct file_operations gpio_fops = {
+ .owner = THIS_MODULE,
+ .read = gpio_read,
+ .write = gpio_write,
+ .open = gpio_open,
+ .release = gpio_release,
+};
+
+static int giu_probe(struct device *dev)
+{
+ unsigned long start, size, flags = 0;
+ unsigned int nr_pins = 0;
+ struct resource *res1, *res2 = NULL;
+ void *base;
+ int retval, i;
+
+ switch (current_cpu_data.cputype) {
+ case CPU_VR4111:
+ case CPU_VR4121:
+ start = GIU_TYPE1_START;
+ size = GIU_TYPE1_SIZE;
+ flags = GPIO_HAS_PULLUPDOWN_IO;
+ nr_pins = 50;
+ break;
+ case CPU_VR4122:
+ case CPU_VR4131:
+ start = GIU_TYPE2_START;
+ size = GIU_TYPE2_SIZE;
+ nr_pins = 36;
+ break;
+ case CPU_VR4133:
+ start = GIU_TYPE3_START;
+ size = GIU_TYPE3_SIZE;
+ flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
+ nr_pins = 48;
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ res1 = request_mem_region(start, size, "GIU");
+ if (res1 == NULL)
+ return -EBUSY;
+
+ base = ioremap(start, size);
+ if (base == NULL) {
+ release_resource(res1);
+ return -ENOMEM;
+ }
+
+ if (flags & GPIO_HAS_PULLUPDOWN_IO) {
+ res2 = request_mem_region(GIU_PULLUPDOWN_START, GIU_PULLUPDOWN_SIZE, "GIU");
+ if (res2 == NULL) {
+ iounmap(base);
+ release_resource(res1);
+ return -EBUSY;
+ }
+ }
+
+ retval = register_chrdev(major, "GIU", &gpio_fops);
+ if (retval < 0) {
+ iounmap(base);
+ release_resource(res1);
+ release_resource(res2);
+ return retval;
+ }
+
+ if (major == 0) {
+ major = retval;
+ printk(KERN_INFO "GIU: major number %d\n", major);
+ }
+
+ spin_lock_init(&giu_lock);
+ giu_base = base;
+ giu_resource1 = res1;
+ giu_resource2 = res2;
+ giu_flags = flags;
+ giu_nr_pins = nr_pins;
+
+ giu_write(GIUINTENL, 0);
+ giu_write(GIUINTENH, 0);
+
+ for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
+ if (i < GIU_IRQ(GIUINT_HIGH_OFFSET))
+ irq_desc[i].handler = &giuint_low_irq_type;
+ else
+ irq_desc[i].handler = &giuint_high_irq_type;
+ }
+
+ return cascade_irq(GIUINT_IRQ, giu_get_irq);
+}
+
+static int giu_remove(struct device *dev)
+{
+ iounmap(giu_base);
+
+ release_resource(giu_resource1);
+ if (giu_flags & GPIO_HAS_PULLUPDOWN_IO)
+ release_resource(giu_resource2);
+
+ return 0;
+}
+
+static struct platform_device *giu_platform_device;
+
+static struct device_driver giu_device_driver = {
+ .name = "GIU",
+ .bus = &platform_bus_type,
+ .probe = giu_probe,
+ .remove = giu_remove,
+};
+
+static int __devinit vr41xx_giu_init(void)
+{
+ int retval;
+
+ giu_platform_device = platform_device_register_simple("GIU", -1, NULL, 0);
+ if (IS_ERR(giu_platform_device))
+ return PTR_ERR(giu_platform_device);
+
+ retval = driver_register(&giu_device_driver);
+ if (retval < 0)
+ platform_device_unregister(giu_platform_device);
+
+ return retval;
+}
+
+static void __devexit vr41xx_giu_exit(void)
+{
+ driver_unregister(&giu_device_driver);
+
+ platform_device_unregister(giu_platform_device);
+}
+
+module_init(vr41xx_giu_init);
+module_exit(vr41xx_giu_exit);
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index e5ef1dfc548..d7aa7a29f67 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -2867,6 +2867,10 @@ void unblank_screen(void)
*/
static void blank_screen_t(unsigned long dummy)
{
+ if (unlikely(!keventd_up())) {
+ mod_timer(&console_timer, jiffies + blankinterval);
+ return;
+ }
blank_timer_expired = 1;
schedule_work(&console_work);
}
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index 06a31da2381..b53e2e2b5ae 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -414,6 +414,16 @@ config WATCHDOG_RIO
machines. The watchdog timeout period is normally one minute but
can be changed with a boot-time parameter.
+# ppc64 RTAS watchdog
+config WATCHDOG_RTAS
+ tristate "RTAS watchdog"
+ depends on WATCHDOG && PPC_RTAS
+ help
+ This driver adds watchdog support for the RTAS watchdog.
+
+ To compile this driver as a module, choose M here. The module
+ will be called wdrtas.
+
#
# ISA-based Watchdog Cards
#
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index 1cd27efa35c..c1838834ea7 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
+obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o
# Only one watchdog can succeed. We probe the hardware watchdog
# drivers first, then the softdog driver. This means if your hardware
diff --git a/drivers/char/watchdog/i8xx_tco.c b/drivers/char/watchdog/i8xx_tco.c
index c337978dc96..b14d642439e 100644
--- a/drivers/char/watchdog/i8xx_tco.c
+++ b/drivers/char/watchdog/i8xx_tco.c
@@ -382,6 +382,7 @@ static struct pci_device_id i8xx_tco_pci_tbl[] = {
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2, PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, PCI_ANY_ID, PCI_ANY_ID, },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, PCI_ANY_ID, PCI_ANY_ID, },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, PCI_ANY_ID, PCI_ANY_ID, },
{ 0, }, /* End of list */
};
MODULE_DEVICE_TABLE (pci, i8xx_tco_pci_tbl);
diff --git a/drivers/char/watchdog/ixp2000_wdt.c b/drivers/char/watchdog/ixp2000_wdt.c
index ab659d37b4d..4e98c215e5b 100644
--- a/drivers/char/watchdog/ixp2000_wdt.c
+++ b/drivers/char/watchdog/ixp2000_wdt.c
@@ -192,7 +192,12 @@ static struct miscdevice ixp2000_wdt_miscdev =
static int __init ixp2000_wdt_init(void)
{
- wdt_tick_rate = (*IXP2000_T1_CLD * HZ)/ 256;;
+ if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) {
+ printk(KERN_INFO "Unable to use IXP2000 watchdog due to IXP2800 erratum #25.\n");
+ return -EIO;
+ }
+
+ wdt_tick_rate = (*IXP2000_T1_CLD * HZ) / 256;
return misc_register(&ixp2000_wdt_miscdev);
}
diff --git a/drivers/char/watchdog/wdrtas.c b/drivers/char/watchdog/wdrtas.c
new file mode 100644
index 00000000000..619e2ffca33
--- /dev/null
+++ b/drivers/char/watchdog/wdrtas.c
@@ -0,0 +1,696 @@
+/*
+ * FIXME: add wdrtas_get_status and wdrtas_get_boot_status as soon as
+ * RTAS calls are available
+ */
+
+/*
+ * RTAS watchdog driver
+ *
+ * (C) Copyright IBM Corp. 2005
+ * device driver to exploit watchdog RTAS functions
+ *
+ * Authors : Utz Bacher <utz.bacher@de.ibm.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, 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; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+
+#include <asm/rtas.h>
+#include <asm/uaccess.h>
+
+#define WDRTAS_MAGIC_CHAR 42
+#define WDRTAS_SUPPORTED_MASK (WDIOF_SETTIMEOUT | \
+ WDIOF_MAGICCLOSE)
+
+MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
+MODULE_DESCRIPTION("RTAS watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+MODULE_ALIAS_MISCDEV(TEMP_MINOR);
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int wdrtas_nowayout = 1;
+#else
+static int wdrtas_nowayout = 0;
+#endif
+
+static atomic_t wdrtas_miscdev_open = ATOMIC_INIT(0);
+static char wdrtas_expect_close = 0;
+
+static int wdrtas_interval;
+
+#define WDRTAS_THERMAL_SENSOR 3
+static int wdrtas_token_get_sensor_state;
+#define WDRTAS_SURVEILLANCE_IND 9000
+static int wdrtas_token_set_indicator;
+#define WDRTAS_SP_SPI 28
+static int wdrtas_token_get_sp;
+static int wdrtas_token_event_scan;
+
+#define WDRTAS_DEFAULT_INTERVAL 300
+
+#define WDRTAS_LOGBUFFER_LEN 128
+static char wdrtas_logbuffer[WDRTAS_LOGBUFFER_LEN];
+
+
+/*** watchdog access functions */
+
+/**
+ * wdrtas_set_interval - sets the watchdog interval
+ * @interval: new interval
+ *
+ * returns 0 on success, <0 on failures
+ *
+ * wdrtas_set_interval sets the watchdog keepalive interval by calling the
+ * RTAS function set-indicator (surveillance). The unit of interval is
+ * seconds.
+ */
+static int
+wdrtas_set_interval(int interval)
+{
+ long result;
+ static int print_msg = 10;
+
+ /* rtas uses minutes */
+ interval = (interval + 59) / 60;
+
+ result = rtas_call(wdrtas_token_set_indicator, 3, 1, NULL,
+ WDRTAS_SURVEILLANCE_IND, 0, interval);
+ if ( (result < 0) && (print_msg) ) {
+ printk(KERN_ERR "wdrtas: setting the watchdog to %i "
+ "timeout failed: %li\n", interval, result);
+ print_msg--;
+ }
+
+ return result;
+}
+
+/**
+ * wdrtas_get_interval - returns the current watchdog interval
+ * @fallback_value: value (in seconds) to use, if the RTAS call fails
+ *
+ * returns the interval
+ *
+ * wdrtas_get_interval returns the current watchdog keepalive interval
+ * as reported by the RTAS function ibm,get-system-parameter. The unit
+ * of the return value is seconds.
+ */
+static int
+wdrtas_get_interval(int fallback_value)
+{
+ long result;
+ char value[4];
+
+ result = rtas_call(wdrtas_token_get_sp, 3, 1, NULL,
+ WDRTAS_SP_SPI, (void *)__pa(&value), 4);
+ if ( (value[0] != 0) || (value[1] != 2) || (value[3] != 0) ||
+ (result < 0) ) {
+ printk(KERN_WARNING "wdrtas: could not get sp_spi watchdog "
+ "timeout (%li). Continuing\n", result);
+ return fallback_value;
+ }
+
+ /* rtas uses minutes */
+ return ((int)value[2]) * 60;
+}
+
+/**
+ * wdrtas_timer_start - starts watchdog
+ *
+ * wdrtas_timer_start starts the watchdog by calling the RTAS function
+ * set-interval (surveillance)
+ */
+static void
+wdrtas_timer_start(void)
+{
+ wdrtas_set_interval(wdrtas_interval);
+}
+
+/**
+ * wdrtas_timer_stop - stops watchdog
+ *
+ * wdrtas_timer_stop stops the watchdog timer by calling the RTAS function
+ * set-interval (surveillance)
+ */
+static void
+wdrtas_timer_stop(void)
+{
+ wdrtas_set_interval(0);
+}
+
+/**
+ * wdrtas_log_scanned_event - logs an event we received during keepalive
+ *
+ * wdrtas_log_scanned_event prints a message to the log buffer dumping
+ * the results of the last event-scan call
+ */
+static void
+wdrtas_log_scanned_event(void)
+{
+ int i;
+
+ for (i = 0; i < WDRTAS_LOGBUFFER_LEN; i += 16)
+ printk(KERN_INFO "wdrtas: dumping event (line %i/%i), data = "
+ "%02x %02x %02x %02x %02x %02x %02x %02x "
+ "%02x %02x %02x %02x %02x %02x %02x %02x\n",
+ (i / 16) + 1, (WDRTAS_LOGBUFFER_LEN / 16),
+ wdrtas_logbuffer[i + 0], wdrtas_logbuffer[i + 1],
+ wdrtas_logbuffer[i + 2], wdrtas_logbuffer[i + 3],
+ wdrtas_logbuffer[i + 4], wdrtas_logbuffer[i + 5],
+ wdrtas_logbuffer[i + 6], wdrtas_logbuffer[i + 7],
+ wdrtas_logbuffer[i + 8], wdrtas_logbuffer[i + 9],
+ wdrtas_logbuffer[i + 10], wdrtas_logbuffer[i + 11],
+ wdrtas_logbuffer[i + 12], wdrtas_logbuffer[i + 13],
+ wdrtas_logbuffer[i + 14], wdrtas_logbuffer[i + 15]);
+}
+
+/**
+ * wdrtas_timer_keepalive - resets watchdog timer to keep system alive
+ *
+ * wdrtas_timer_keepalive restarts the watchdog timer by calling the
+ * RTAS function event-scan and repeats these calls as long as there are
+ * events available. All events will be dumped.
+ */
+static void
+wdrtas_timer_keepalive(void)
+{
+ long result;
+
+ do {
+ result = rtas_call(wdrtas_token_event_scan, 4, 1, NULL,
+ RTAS_EVENT_SCAN_ALL_EVENTS, 0,
+ (void *)__pa(wdrtas_logbuffer),
+ WDRTAS_LOGBUFFER_LEN);
+ if (result < 0)
+ printk(KERN_ERR "wdrtas: event-scan failed: %li\n",
+ result);
+ if (result == 0)
+ wdrtas_log_scanned_event();
+ } while (result == 0);
+}
+
+/**
+ * wdrtas_get_temperature - returns current temperature
+ *
+ * returns temperature or <0 on failures
+ *
+ * wdrtas_get_temperature returns the current temperature in Fahrenheit. It
+ * uses the RTAS call get-sensor-state, token 3 to do so
+ */
+static int
+wdrtas_get_temperature(void)
+{
+ long result;
+ int temperature = 0;
+
+ result = rtas_call(wdrtas_token_get_sensor_state, 2, 2,
+ (void *)__pa(&temperature),
+ WDRTAS_THERMAL_SENSOR, 0);
+
+ if (result < 0)
+ printk(KERN_WARNING "wdrtas: reading the thermal sensor "
+ "faild: %li\n", result);
+ else
+ temperature = ((temperature * 9) / 5) + 32; /* fahrenheit */
+
+ return temperature;
+}
+
+/**
+ * wdrtas_get_status - returns the status of the watchdog
+ *
+ * returns a bitmask of defines WDIOF_... as defined in
+ * include/linux/watchdog.h
+ */
+static int
+wdrtas_get_status(void)
+{
+ return 0; /* TODO */
+}
+
+/**
+ * wdrtas_get_boot_status - returns the reason for the last boot
+ *
+ * returns a bitmask of defines WDIOF_... as defined in
+ * include/linux/watchdog.h, indicating why the watchdog rebooted the system
+ */
+static int
+wdrtas_get_boot_status(void)
+{
+ return 0; /* TODO */
+}
+
+/*** watchdog API and operations stuff */
+
+/* wdrtas_write - called when watchdog device is written to
+ * @file: file structure
+ * @buf: user buffer with data
+ * @len: amount to data written
+ * @ppos: position in file
+ *
+ * returns the number of successfully processed characters, which is always
+ * the number of bytes passed to this function
+ *
+ * wdrtas_write processes all the data given to it and looks for the magic
+ * character 'V'. This character allows the watchdog device to be closed
+ * properly.
+ */
+static ssize_t
+wdrtas_write(struct file *file, const char __user *buf,
+ size_t len, loff_t *ppos)
+{
+ int i;
+ char c;
+
+ if (!len)
+ goto out;
+
+ if (!wdrtas_nowayout) {
+ wdrtas_expect_close = 0;
+ /* look for 'V' */
+ for (i = 0; i < len; i++) {
+ if (get_user(c, buf + i))
+ return -EFAULT;
+ /* allow to close device */
+ if (c == 'V')
+ wdrtas_expect_close = WDRTAS_MAGIC_CHAR;
+ }
+ }
+
+ wdrtas_timer_keepalive();
+
+out:
+ return len;
+}
+
+/**
+ * wdrtas_ioctl - ioctl function for the watchdog device
+ * @inode: inode structure
+ * @file: file structure
+ * @cmd: command for ioctl
+ * @arg: argument pointer
+ *
+ * returns 0 on success, <0 on failure
+ *
+ * wdrtas_ioctl implements the watchdog API ioctls
+ */
+static int
+wdrtas_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int __user *argp = (void *)arg;
+ int i;
+ static struct watchdog_info wdinfo = {
+ .options = WDRTAS_SUPPORTED_MASK,
+ .firmware_version = 0,
+ .identity = "wdrtas"
+ };
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ if (copy_to_user(argp, &wdinfo, sizeof(wdinfo)))
+ return -EFAULT;
+ return 0;
+
+ case WDIOC_GETSTATUS:
+ i = wdrtas_get_status();
+ return put_user(i, argp);
+
+ case WDIOC_GETBOOTSTATUS:
+ i = wdrtas_get_boot_status();
+ return put_user(i, argp);
+
+ case WDIOC_GETTEMP:
+ if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE)
+ return -EOPNOTSUPP;
+
+ i = wdrtas_get_temperature();
+ return put_user(i, argp);
+
+ case WDIOC_SETOPTIONS:
+ if (get_user(i, argp))
+ return -EFAULT;
+ if (i & WDIOS_DISABLECARD)
+ wdrtas_timer_stop();
+ if (i & WDIOS_ENABLECARD) {
+ wdrtas_timer_keepalive();
+ wdrtas_timer_start();
+ }
+ if (i & WDIOS_TEMPPANIC) {
+ /* not implemented. Done by H8 */
+ }
+ return 0;
+
+ case WDIOC_KEEPALIVE:
+ wdrtas_timer_keepalive();
+ return 0;
+
+ case WDIOC_SETTIMEOUT:
+ if (get_user(i, argp))
+ return -EFAULT;
+
+ if (wdrtas_set_interval(i))
+ return -EINVAL;
+
+ wdrtas_timer_keepalive();
+
+ if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE)
+ wdrtas_interval = i;
+ else
+ wdrtas_interval = wdrtas_get_interval(i);
+ /* fallthrough */
+
+ case WDIOC_GETTIMEOUT:
+ return put_user(wdrtas_interval, argp);
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+/**
+ * wdrtas_open - open function of watchdog device
+ * @inode: inode structure
+ * @file: file structure
+ *
+ * returns 0 on success, -EBUSY if the file has been opened already, <0 on
+ * other failures
+ *
+ * function called when watchdog device is opened
+ */
+static int
+wdrtas_open(struct inode *inode, struct file *file)
+{
+ /* only open once */
+ if (atomic_inc_return(&wdrtas_miscdev_open) > 1) {
+ atomic_dec(&wdrtas_miscdev_open);
+ return -EBUSY;
+ }
+
+ wdrtas_timer_start();
+ wdrtas_timer_keepalive();
+
+ return nonseekable_open(inode, file);
+}
+
+/**
+ * wdrtas_close - close function of watchdog device
+ * @inode: inode structure
+ * @file: file structure
+ *
+ * returns 0 on success
+ *
+ * close function. Always succeeds
+ */
+static int
+wdrtas_close(struct inode *inode, struct file *file)
+{
+ /* only stop watchdog, if this was announced using 'V' before */
+ if (wdrtas_expect_close == WDRTAS_MAGIC_CHAR)
+ wdrtas_timer_stop();
+ else {
+ printk(KERN_WARNING "wdrtas: got unexpected close. Watchdog "
+ "not stopped.\n");
+ wdrtas_timer_keepalive();
+ }
+
+ wdrtas_expect_close = 0;
+ atomic_dec(&wdrtas_miscdev_open);
+ return 0;
+}
+
+/**
+ * wdrtas_temp_read - gives back the temperature in fahrenheit
+ * @file: file structure
+ * @buf: user buffer
+ * @count: number of bytes to be read
+ * @ppos: position in file
+ *
+ * returns always 1 or -EFAULT in case of user space copy failures, <0 on
+ * other failures
+ *
+ * wdrtas_temp_read gives the temperature to the users by copying this
+ * value as one byte into the user space buffer. The unit is Fahrenheit...
+ */
+static ssize_t
+wdrtas_temp_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ int temperature = 0;
+
+ temperature = wdrtas_get_temperature();
+ if (temperature < 0)
+ return temperature;
+
+ if (copy_to_user(buf, &temperature, 1))
+ return -EFAULT;
+
+ return 1;
+}
+
+/**
+ * wdrtas_temp_open - open function of temperature device
+ * @inode: inode structure
+ * @file: file structure
+ *
+ * returns 0 on success, <0 on failure
+ *
+ * function called when temperature device is opened
+ */
+static int
+wdrtas_temp_open(struct inode *inode, struct file *file)
+{
+ return nonseekable_open(inode, file);
+}
+
+/**
+ * wdrtas_temp_close - close function of temperature device
+ * @inode: inode structure
+ * @file: file structure
+ *
+ * returns 0 on success
+ *
+ * close function. Always succeeds
+ */
+static int
+wdrtas_temp_close(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+/**
+ * wdrtas_reboot - reboot notifier function
+ * @nb: notifier block structure
+ * @code: reboot code
+ * @ptr: unused
+ *
+ * returns NOTIFY_DONE
+ *
+ * wdrtas_reboot stops the watchdog in case of a reboot
+ */
+static int
+wdrtas_reboot(struct notifier_block *this, unsigned long code, void *ptr)
+{
+ if ( (code==SYS_DOWN) || (code==SYS_HALT) )
+ wdrtas_timer_stop();
+
+ return NOTIFY_DONE;
+}
+
+/*** initialization stuff */
+
+static struct file_operations wdrtas_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = wdrtas_write,
+ .ioctl = wdrtas_ioctl,
+ .open = wdrtas_open,
+ .release = wdrtas_close,
+};
+
+static struct miscdevice wdrtas_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &wdrtas_fops,
+};
+
+static struct file_operations wdrtas_temp_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .read = wdrtas_temp_read,
+ .open = wdrtas_temp_open,
+ .release = wdrtas_temp_close,
+};
+
+static struct miscdevice wdrtas_tempdev = {
+ .minor = TEMP_MINOR,
+ .name = "temperature",
+ .fops = &wdrtas_temp_fops,
+};
+
+static struct notifier_block wdrtas_notifier = {
+ .notifier_call = wdrtas_reboot,
+};
+
+/**
+ * wdrtas_get_tokens - reads in RTAS tokens
+ *
+ * returns 0 on succes, <0 on failure
+ *
+ * wdrtas_get_tokens reads in the tokens for the RTAS calls used in
+ * this watchdog driver. It tolerates, if "get-sensor-state" and
+ * "ibm,get-system-parameter" are not available.
+ */
+static int
+wdrtas_get_tokens(void)
+{
+ wdrtas_token_get_sensor_state = rtas_token("get-sensor-state");
+ if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE) {
+ printk(KERN_WARNING "wdrtas: couldn't get token for "
+ "get-sensor-state. Trying to continue without "
+ "temperature support.\n");
+ }
+
+ wdrtas_token_get_sp = rtas_token("ibm,get-system-parameter");
+ if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE) {
+ printk(KERN_WARNING "wdrtas: couldn't get token for "
+ "ibm,get-system-parameter. Trying to continue with "
+ "a default timeout value of %i seconds.\n",
+ WDRTAS_DEFAULT_INTERVAL);
+ }
+
+ wdrtas_token_set_indicator = rtas_token("set-indicator");
+ if (wdrtas_token_set_indicator == RTAS_UNKNOWN_SERVICE) {
+ printk(KERN_ERR "wdrtas: couldn't get token for "
+ "set-indicator. Terminating watchdog code.\n");
+ return -EIO;
+ }
+
+ wdrtas_token_event_scan = rtas_token("event-scan");
+ if (wdrtas_token_event_scan == RTAS_UNKNOWN_SERVICE) {
+ printk(KERN_ERR "wdrtas: couldn't get token for event-scan. "
+ "Terminating watchdog code.\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/**
+ * wdrtas_unregister_devs - unregisters the misc dev handlers
+ *
+ * wdrtas_register_devs unregisters the watchdog and temperature watchdog
+ * misc devs
+ */
+static void
+wdrtas_unregister_devs(void)
+{
+ misc_deregister(&wdrtas_miscdev);
+ if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE)
+ misc_deregister(&wdrtas_tempdev);
+}
+
+/**
+ * wdrtas_register_devs - registers the misc dev handlers
+ *
+ * returns 0 on succes, <0 on failure
+ *
+ * wdrtas_register_devs registers the watchdog and temperature watchdog
+ * misc devs
+ */
+static int
+wdrtas_register_devs(void)
+{
+ int result;
+
+ result = misc_register(&wdrtas_miscdev);
+ if (result) {
+ printk(KERN_ERR "wdrtas: couldn't register watchdog misc "
+ "device. Terminating watchdog code.\n");
+ return result;
+ }
+
+ if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE) {
+ result = misc_register(&wdrtas_tempdev);
+ if (result) {
+ printk(KERN_WARNING "wdrtas: couldn't register "
+ "watchdog temperature misc device. Continuing "
+ "without temperature support.\n");
+ wdrtas_token_get_sensor_state = RTAS_UNKNOWN_SERVICE;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * wdrtas_init - init function of the watchdog driver
+ *
+ * returns 0 on succes, <0 on failure
+ *
+ * registers the file handlers and the reboot notifier
+ */
+static int __init
+wdrtas_init(void)
+{
+ if (wdrtas_get_tokens())
+ return -ENODEV;
+
+ if (wdrtas_register_devs())
+ return -ENODEV;
+
+ if (register_reboot_notifier(&wdrtas_notifier)) {
+ printk(KERN_ERR "wdrtas: could not register reboot notifier. "
+ "Terminating watchdog code.\n");
+ wdrtas_unregister_devs();
+ return -ENODEV;
+ }
+
+ if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE)
+ wdrtas_interval = WDRTAS_DEFAULT_INTERVAL;
+ else
+ wdrtas_interval = wdrtas_get_interval(WDRTAS_DEFAULT_INTERVAL);
+
+ return 0;
+}
+
+/**
+ * wdrtas_exit - exit function of the watchdog driver
+ *
+ * unregisters the file handlers and the reboot notifier
+ */
+static void __exit
+wdrtas_exit(void)
+{
+ if (!wdrtas_nowayout)
+ wdrtas_timer_stop();
+
+ wdrtas_unregister_devs();
+
+ unregister_reboot_notifier(&wdrtas_notifier);
+}
+
+module_init(wdrtas_init);
+module_exit(wdrtas_exit);
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index 95882bb1950..60c9be99c6d 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -46,6 +46,10 @@ config CPU_FREQ_STAT_DETAILS
This will show detail CPU frequency translation table in sysfs file
system
+# Note that it is not currently possible to set the other governors (such as ondemand)
+# as the default, since if they fail to initialise, cpufreq will be
+# left in an undefined state.
+
choice
prompt "Default CPUFreq governor"
default CPU_FREQ_DEFAULT_GOV_USERSPACE if CPU_FREQ_SA1100 || CPU_FREQ_SA1110
@@ -115,4 +119,24 @@ config CPU_FREQ_GOV_ONDEMAND
If in doubt, say N.
+config CPU_FREQ_GOV_CONSERVATIVE
+ tristate "'conservative' cpufreq governor"
+ depends on CPU_FREQ
+ help
+ 'conservative' - this driver is rather similar to the 'ondemand'
+ governor both in its source code and its purpose, the difference is
+ its optimisation for better suitability in a battery powered
+ environment. The frequency is gracefully increased and decreased
+ rather than jumping to 100% when speed is required.
+
+ If you have a desktop machine then you should really be considering
+ the 'ondemand' governor instead, however if you are using a laptop,
+ PDA or even an AMD64 based computer (due to the unacceptable
+ step-by-step latency issues between the minimum and maximum frequency
+ transitions in the CPU) you will probably want to use this governor.
+
+ For details, take a look at linux/Documentation/cpu-freq.
+
+ If in doubt, say N.
+
endif # CPU_FREQ
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 67b16e5a41a..71fc3b4173f 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_PERFORMANCE) += cpufreq_performance.o
obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE) += cpufreq_powersave.o
obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o
obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o
+obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o
# CPUfreq cross-arch helpers
obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 8e561313d09..bf62dfe4976 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -258,7 +258,7 @@ void cpufreq_notify_transition(struct cpufreq_freqs *freqs, unsigned int state)
(likely(cpufreq_cpu_data[freqs->cpu]->cur)) &&
(unlikely(freqs->old != cpufreq_cpu_data[freqs->cpu]->cur)))
{
- printk(KERN_WARNING "Warning: CPU frequency is %u, "
+ dprintk(KERN_WARNING "Warning: CPU frequency is %u, "
"cpufreq assumed %u kHz.\n", freqs->old, cpufreq_cpu_data[freqs->cpu]->cur);
freqs->old = cpufreq_cpu_data[freqs->cpu]->cur;
}
@@ -521,7 +521,7 @@ static ssize_t show(struct kobject * kobj, struct attribute * attr ,char * buf)
policy = cpufreq_cpu_get(policy->cpu);
if (!policy)
return -EINVAL;
- ret = fattr->show ? fattr->show(policy,buf) : 0;
+ ret = fattr->show ? fattr->show(policy,buf) : -EIO;
cpufreq_cpu_put(policy);
return ret;
}
@@ -535,7 +535,7 @@ static ssize_t store(struct kobject * kobj, struct attribute * attr,
policy = cpufreq_cpu_get(policy->cpu);
if (!policy)
return -EINVAL;
- ret = fattr->store ? fattr->store(policy,buf,count) : 0;
+ ret = fattr->store ? fattr->store(policy,buf,count) : -EIO;
cpufreq_cpu_put(policy);
return ret;
}
@@ -814,7 +814,7 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, unsigne
{
struct cpufreq_freqs freqs;
- printk(KERN_WARNING "Warning: CPU frequency out of sync: cpufreq and timing "
+ dprintk(KERN_WARNING "Warning: CPU frequency out of sync: cpufreq and timing "
"core thinks of %u, is %u kHz.\n", old_freq, new_freq);
freqs.cpu = cpu;
@@ -923,7 +923,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, u32 state)
struct cpufreq_freqs freqs;
if (!(cpufreq_driver->flags & CPUFREQ_PM_NO_WARN))
- printk(KERN_DEBUG "Warning: CPU frequency is %u, "
+ dprintk(KERN_DEBUG "Warning: CPU frequency is %u, "
"cpufreq assumed %u kHz.\n",
cur_freq, cpu_policy->cur);
@@ -1004,7 +1004,7 @@ static int cpufreq_resume(struct sys_device * sysdev)
struct cpufreq_freqs freqs;
if (!(cpufreq_driver->flags & CPUFREQ_PM_NO_WARN))
- printk(KERN_WARNING "Warning: CPU frequency"
+ dprintk(KERN_WARNING "Warning: CPU frequency"
"is %u, cpufreq assumed %u kHz.\n",
cur_freq, cpu_policy->cur);
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
new file mode 100644
index 00000000000..e1df376e709
--- /dev/null
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -0,0 +1,586 @@
+/*
+ * drivers/cpufreq/cpufreq_conservative.c
+ *
+ * Copyright (C) 2001 Russell King
+ * (C) 2003 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>.
+ * Jun Nakajima <jun.nakajima@intel.com>
+ * (C) 2004 Alexander Clouter <alex-kernel@digriz.org.uk>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ctype.h>
+#include <linux/cpufreq.h>
+#include <linux/sysctl.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/sysfs.h>
+#include <linux/sched.h>
+#include <linux/kmod.h>
+#include <linux/workqueue.h>
+#include <linux/jiffies.h>
+#include <linux/kernel_stat.h>
+#include <linux/percpu.h>
+
+/*
+ * dbs is used in this file as a shortform for demandbased switching
+ * It helps to keep variable names smaller, simpler
+ */
+
+#define DEF_FREQUENCY_UP_THRESHOLD (80)
+#define MIN_FREQUENCY_UP_THRESHOLD (0)
+#define MAX_FREQUENCY_UP_THRESHOLD (100)
+
+#define DEF_FREQUENCY_DOWN_THRESHOLD (20)
+#define MIN_FREQUENCY_DOWN_THRESHOLD (0)
+#define MAX_FREQUENCY_DOWN_THRESHOLD (100)
+
+/*
+ * The polling frequency of this governor depends on the capability of
+ * the processor. Default polling frequency is 1000 times the transition
+ * latency of the processor. The governor will work on any processor with
+ * transition latency <= 10mS, using appropriate sampling
+ * rate.
+ * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL)
+ * this governor will not work.
+ * All times here are in uS.
+ */
+static unsigned int def_sampling_rate;
+#define MIN_SAMPLING_RATE (def_sampling_rate / 2)
+#define MAX_SAMPLING_RATE (500 * def_sampling_rate)
+#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (100000)
+#define DEF_SAMPLING_DOWN_FACTOR (5)
+#define TRANSITION_LATENCY_LIMIT (10 * 1000)
+
+static void do_dbs_timer(void *data);
+
+struct cpu_dbs_info_s {
+ struct cpufreq_policy *cur_policy;
+ unsigned int prev_cpu_idle_up;
+ unsigned int prev_cpu_idle_down;
+ unsigned int enable;
+};
+static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info);
+
+static unsigned int dbs_enable; /* number of CPUs using this policy */
+
+static DECLARE_MUTEX (dbs_sem);
+static DECLARE_WORK (dbs_work, do_dbs_timer, NULL);
+
+struct dbs_tuners {
+ unsigned int sampling_rate;
+ unsigned int sampling_down_factor;
+ unsigned int up_threshold;
+ unsigned int down_threshold;
+ unsigned int ignore_nice;
+ unsigned int freq_step;
+};
+
+static struct dbs_tuners dbs_tuners_ins = {
+ .up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
+ .down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD,
+ .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
+};
+
+static inline unsigned int get_cpu_idle_time(unsigned int cpu)
+{
+ return kstat_cpu(cpu).cpustat.idle +
+ kstat_cpu(cpu).cpustat.iowait +
+ ( !dbs_tuners_ins.ignore_nice ?
+ kstat_cpu(cpu).cpustat.nice :
+ 0);
+}
+
+/************************** sysfs interface ************************/
+static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf)
+{
+ return sprintf (buf, "%u\n", MAX_SAMPLING_RATE);
+}
+
+static ssize_t show_sampling_rate_min(struct cpufreq_policy *policy, char *buf)
+{
+ return sprintf (buf, "%u\n", MIN_SAMPLING_RATE);
+}
+
+#define define_one_ro(_name) \
+static struct freq_attr _name = \
+__ATTR(_name, 0444, show_##_name, NULL)
+
+define_one_ro(sampling_rate_max);
+define_one_ro(sampling_rate_min);
+
+/* cpufreq_conservative Governor Tunables */
+#define show_one(file_name, object) \
+static ssize_t show_##file_name \
+(struct cpufreq_policy *unused, char *buf) \
+{ \
+ return sprintf(buf, "%u\n", dbs_tuners_ins.object); \
+}
+show_one(sampling_rate, sampling_rate);
+show_one(sampling_down_factor, sampling_down_factor);
+show_one(up_threshold, up_threshold);
+show_one(down_threshold, down_threshold);
+show_one(ignore_nice, ignore_nice);
+show_one(freq_step, freq_step);
+
+static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused,
+ const char *buf, size_t count)
+{
+ unsigned int input;
+ int ret;
+ ret = sscanf (buf, "%u", &input);
+ if (ret != 1 )
+ return -EINVAL;
+
+ down(&dbs_sem);
+ dbs_tuners_ins.sampling_down_factor = input;
+ up(&dbs_sem);
+
+ return count;
+}
+
+static ssize_t store_sampling_rate(struct cpufreq_policy *unused,
+ const char *buf, size_t count)
+{
+ unsigned int input;
+ int ret;
+ ret = sscanf (buf, "%u", &input);
+
+ down(&dbs_sem);
+ if (ret != 1 || input > MAX_SAMPLING_RATE || input < MIN_SAMPLING_RATE) {
+ up(&dbs_sem);
+ return -EINVAL;
+ }
+
+ dbs_tuners_ins.sampling_rate = input;
+ up(&dbs_sem);
+
+ return count;
+}
+
+static ssize_t store_up_threshold(struct cpufreq_policy *unused,
+ const char *buf, size_t count)
+{
+ unsigned int input;
+ int ret;
+ ret = sscanf (buf, "%u", &input);
+
+ down(&dbs_sem);
+ if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD ||
+ input < MIN_FREQUENCY_UP_THRESHOLD ||
+ input <= dbs_tuners_ins.down_threshold) {
+ up(&dbs_sem);
+ return -EINVAL;
+ }
+
+ dbs_tuners_ins.up_threshold = input;
+ up(&dbs_sem);
+
+ return count;
+}
+
+static ssize_t store_down_threshold(struct cpufreq_policy *unused,
+ const char *buf, size_t count)
+{
+ unsigned int input;
+ int ret;
+ ret = sscanf (buf, "%u", &input);
+
+ down(&dbs_sem);
+ if (ret != 1 || input > MAX_FREQUENCY_DOWN_THRESHOLD ||
+ input < MIN_FREQUENCY_DOWN_THRESHOLD ||
+ input >= dbs_tuners_ins.up_threshold) {
+ up(&dbs_sem);
+ return -EINVAL;
+ }
+
+ dbs_tuners_ins.down_threshold = input;
+ up(&dbs_sem);
+
+ return count;
+}
+
+static ssize_t store_ignore_nice(struct cpufreq_policy *policy,
+ const char *buf, size_t count)
+{
+ unsigned int input;
+ int ret;
+
+ unsigned int j;
+
+ ret = sscanf (buf, "%u", &input);
+ if ( ret != 1 )
+ return -EINVAL;
+
+ if ( input > 1 )
+ input = 1;
+
+ down(&dbs_sem);
+ if ( input == dbs_tuners_ins.ignore_nice ) { /* nothing to do */
+ up(&dbs_sem);
+ return count;
+ }
+ dbs_tuners_ins.ignore_nice = input;
+
+ /* we need to re-evaluate prev_cpu_idle_up and prev_cpu_idle_down */
+ for_each_online_cpu(j) {
+ struct cpu_dbs_info_s *j_dbs_info;
+ j_dbs_info = &per_cpu(cpu_dbs_info, j);
+ j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(j);
+ j_dbs_info->prev_cpu_idle_down = j_dbs_info->prev_cpu_idle_up;
+ }
+ up(&dbs_sem);
+
+ return count;
+}
+
+static ssize_t store_freq_step(struct cpufreq_policy *policy,
+ const char *buf, size_t count)
+{
+ unsigned int input;
+ int ret;
+
+ ret = sscanf (buf, "%u", &input);
+
+ if ( ret != 1 )
+ return -EINVAL;
+
+ if ( input > 100 )
+ input = 100;
+
+ /* no need to test here if freq_step is zero as the user might actually
+ * want this, they would be crazy though :) */
+ down(&dbs_sem);
+ dbs_tuners_ins.freq_step = input;
+ up(&dbs_sem);
+
+ return count;
+}
+
+#define define_one_rw(_name) \
+static struct freq_attr _name = \
+__ATTR(_name, 0644, show_##_name, store_##_name)
+
+define_one_rw(sampling_rate);
+define_one_rw(sampling_down_factor);
+define_one_rw(up_threshold);
+define_one_rw(down_threshold);
+define_one_rw(ignore_nice);
+define_one_rw(freq_step);
+
+static struct attribute * dbs_attributes[] = {
+ &sampling_rate_max.attr,
+ &sampling_rate_min.attr,
+ &sampling_rate.attr,
+ &sampling_down_factor.attr,
+ &up_threshold.attr,
+ &down_threshold.attr,
+ &ignore_nice.attr,
+ &freq_step.attr,
+ NULL
+};
+
+static struct attribute_group dbs_attr_group = {
+ .attrs = dbs_attributes,
+ .name = "conservative",
+};
+
+/************************** sysfs end ************************/
+
+static void dbs_check_cpu(int cpu)
+{
+ unsigned int idle_ticks, up_idle_ticks, down_idle_ticks;
+ unsigned int freq_step;
+ unsigned int freq_down_sampling_rate;
+ static int down_skip[NR_CPUS];
+ static int requested_freq[NR_CPUS];
+ static unsigned short init_flag = 0;
+ struct cpu_dbs_info_s *this_dbs_info;
+ struct cpu_dbs_info_s *dbs_info;
+
+ struct cpufreq_policy *policy;
+ unsigned int j;
+
+ this_dbs_info = &per_cpu(cpu_dbs_info, cpu);
+ if (!this_dbs_info->enable)
+ return;
+
+ policy = this_dbs_info->cur_policy;
+
+ if ( init_flag == 0 ) {
+ for ( /* NULL */; init_flag < NR_CPUS; init_flag++ ) {
+ dbs_info = &per_cpu(cpu_dbs_info, init_flag);
+ requested_freq[cpu] = dbs_info->cur_policy->cur;
+ }
+ init_flag = 1;
+ }
+
+ /*
+ * The default safe range is 20% to 80%
+ * Every sampling_rate, we check
+ * - If current idle time is less than 20%, then we try to
+ * increase frequency
+ * Every sampling_rate*sampling_down_factor, we check
+ * - If current idle time is more than 80%, then we try to
+ * decrease frequency
+ *
+ * Any frequency increase takes it to the maximum frequency.
+ * Frequency reduction happens at minimum steps of
+ * 5% (default) of max_frequency
+ */
+
+ /* Check for frequency increase */
+
+ idle_ticks = UINT_MAX;
+ for_each_cpu_mask(j, policy->cpus) {
+ unsigned int tmp_idle_ticks, total_idle_ticks;
+ struct cpu_dbs_info_s *j_dbs_info;
+
+ j_dbs_info = &per_cpu(cpu_dbs_info, j);
+ /* Check for frequency increase */
+ total_idle_ticks = get_cpu_idle_time(j);
+ tmp_idle_ticks = total_idle_ticks -
+ j_dbs_info->prev_cpu_idle_up;
+ j_dbs_info->prev_cpu_idle_up = total_idle_ticks;
+
+ if (tmp_idle_ticks < idle_ticks)
+ idle_ticks = tmp_idle_ticks;
+ }
+
+ /* Scale idle ticks by 100 and compare with up and down ticks */
+ idle_ticks *= 100;
+ up_idle_ticks = (100 - dbs_tuners_ins.up_threshold) *
+ usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
+
+ if (idle_ticks < up_idle_ticks) {
+ down_skip[cpu] = 0;
+ for_each_cpu_mask(j, policy->cpus) {
+ struct cpu_dbs_info_s *j_dbs_info;
+
+ j_dbs_info = &per_cpu(cpu_dbs_info, j);
+ j_dbs_info->prev_cpu_idle_down =
+ j_dbs_info->prev_cpu_idle_up;
+ }
+ /* if we are already at full speed then break out early */
+ if (requested_freq[cpu] == policy->max)
+ return;
+
+ freq_step = (dbs_tuners_ins.freq_step * policy->max) / 100;
+
+ /* max freq cannot be less than 100. But who knows.... */
+ if (unlikely(freq_step == 0))
+ freq_step = 5;
+
+ requested_freq[cpu] += freq_step;
+ if (requested_freq[cpu] > policy->max)
+ requested_freq[cpu] = policy->max;
+
+ __cpufreq_driver_target(policy, requested_freq[cpu],
+ CPUFREQ_RELATION_H);
+ return;
+ }
+
+ /* Check for frequency decrease */
+ down_skip[cpu]++;
+ if (down_skip[cpu] < dbs_tuners_ins.sampling_down_factor)
+ return;
+
+ idle_ticks = UINT_MAX;
+ for_each_cpu_mask(j, policy->cpus) {
+ unsigned int tmp_idle_ticks, total_idle_ticks;
+ struct cpu_dbs_info_s *j_dbs_info;
+
+ j_dbs_info = &per_cpu(cpu_dbs_info, j);
+ total_idle_ticks = j_dbs_info->prev_cpu_idle_up;
+ tmp_idle_ticks = total_idle_ticks -
+ j_dbs_info->prev_cpu_idle_down;
+ j_dbs_info->prev_cpu_idle_down = total_idle_ticks;
+
+ if (tmp_idle_ticks < idle_ticks)
+ idle_ticks = tmp_idle_ticks;
+ }
+
+ /* Scale idle ticks by 100 and compare with up and down ticks */
+ idle_ticks *= 100;
+ down_skip[cpu] = 0;
+
+ freq_down_sampling_rate = dbs_tuners_ins.sampling_rate *
+ dbs_tuners_ins.sampling_down_factor;
+ down_idle_ticks = (100 - dbs_tuners_ins.down_threshold) *
+ usecs_to_jiffies(freq_down_sampling_rate);
+
+ if (idle_ticks > down_idle_ticks) {
+ /* if we are already at the lowest speed then break out early
+ * or if we 'cannot' reduce the speed as the user might want
+ * freq_step to be zero */
+ if (requested_freq[cpu] == policy->min
+ || dbs_tuners_ins.freq_step == 0)
+ return;
+
+ freq_step = (dbs_tuners_ins.freq_step * policy->max) / 100;
+
+ /* max freq cannot be less than 100. But who knows.... */
+ if (unlikely(freq_step == 0))
+ freq_step = 5;
+
+ requested_freq[cpu] -= freq_step;
+ if (requested_freq[cpu] < policy->min)
+ requested_freq[cpu] = policy->min;
+
+ __cpufreq_driver_target(policy,
+ requested_freq[cpu],
+ CPUFREQ_RELATION_H);
+ return;
+ }
+}
+
+static void do_dbs_timer(void *data)
+{
+ int i;
+ down(&dbs_sem);
+ for_each_online_cpu(i)
+ dbs_check_cpu(i);
+ schedule_delayed_work(&dbs_work,
+ usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
+ up(&dbs_sem);
+}
+
+static inline void dbs_timer_init(void)
+{
+ INIT_WORK(&dbs_work, do_dbs_timer, NULL);
+ schedule_delayed_work(&dbs_work,
+ usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
+ return;
+}
+
+static inline void dbs_timer_exit(void)
+{
+ cancel_delayed_work(&dbs_work);
+ return;
+}
+
+static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
+ unsigned int event)
+{
+ unsigned int cpu = policy->cpu;
+ struct cpu_dbs_info_s *this_dbs_info;
+ unsigned int j;
+
+ this_dbs_info = &per_cpu(cpu_dbs_info, cpu);
+
+ switch (event) {
+ case CPUFREQ_GOV_START:
+ if ((!cpu_online(cpu)) ||
+ (!policy->cur))
+ return -EINVAL;
+
+ if (policy->cpuinfo.transition_latency >
+ (TRANSITION_LATENCY_LIMIT * 1000))
+ return -EINVAL;
+ if (this_dbs_info->enable) /* Already enabled */
+ break;
+
+ down(&dbs_sem);
+ for_each_cpu_mask(j, policy->cpus) {
+ struct cpu_dbs_info_s *j_dbs_info;
+ j_dbs_info = &per_cpu(cpu_dbs_info, j);
+ j_dbs_info->cur_policy = policy;
+
+ j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(j);
+ j_dbs_info->prev_cpu_idle_down
+ = j_dbs_info->prev_cpu_idle_up;
+ }
+ this_dbs_info->enable = 1;
+ sysfs_create_group(&policy->kobj, &dbs_attr_group);
+ dbs_enable++;
+ /*
+ * Start the timerschedule work, when this governor
+ * is used for first time
+ */
+ if (dbs_enable == 1) {
+ unsigned int latency;
+ /* policy latency is in nS. Convert it to uS first */
+
+ latency = policy->cpuinfo.transition_latency;
+ if (latency < 1000)
+ latency = 1000;
+
+ def_sampling_rate = (latency / 1000) *
+ DEF_SAMPLING_RATE_LATENCY_MULTIPLIER;
+ dbs_tuners_ins.sampling_rate = def_sampling_rate;
+ dbs_tuners_ins.ignore_nice = 0;
+ dbs_tuners_ins.freq_step = 5;
+
+ dbs_timer_init();
+ }
+
+ up(&dbs_sem);
+ break;
+
+ case CPUFREQ_GOV_STOP:
+ down(&dbs_sem);
+ this_dbs_info->enable = 0;
+ sysfs_remove_group(&policy->kobj, &dbs_attr_group);
+ dbs_enable--;
+ /*
+ * Stop the timerschedule work, when this governor
+ * is used for first time
+ */
+ if (dbs_enable == 0)
+ dbs_timer_exit();
+
+ up(&dbs_sem);
+
+ break;
+
+ case CPUFREQ_GOV_LIMITS:
+ down(&dbs_sem);
+ if (policy->max < this_dbs_info->cur_policy->cur)
+ __cpufreq_driver_target(
+ this_dbs_info->cur_policy,
+ policy->max, CPUFREQ_RELATION_H);
+ else if (policy->min > this_dbs_info->cur_policy->cur)
+ __cpufreq_driver_target(
+ this_dbs_info->cur_policy,
+ policy->min, CPUFREQ_RELATION_L);
+ up(&dbs_sem);
+ break;
+ }
+ return 0;
+}
+
+static struct cpufreq_governor cpufreq_gov_dbs = {
+ .name = "conservative",
+ .governor = cpufreq_governor_dbs,
+ .owner = THIS_MODULE,
+};
+
+static int __init cpufreq_gov_dbs_init(void)
+{
+ return cpufreq_register_governor(&cpufreq_gov_dbs);
+}
+
+static void __exit cpufreq_gov_dbs_exit(void)
+{
+ /* Make sure that the scheduled work is indeed not running */
+ flush_scheduled_work();
+
+ cpufreq_unregister_governor(&cpufreq_gov_dbs);
+}
+
+
+MODULE_AUTHOR ("Alexander Clouter <alex-kernel@digriz.org.uk>");
+MODULE_DESCRIPTION ("'cpufreq_conservative' - A dynamic cpufreq governor for "
+ "Low Latency Frequency Transition capable processors "
+ "optimised for use in a battery environment");
+MODULE_LICENSE ("GPL");
+
+module_init(cpufreq_gov_dbs_init);
+module_exit(cpufreq_gov_dbs_exit);
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 8d83a21c647..c1fc9c62bb5 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -34,13 +34,9 @@
*/
#define DEF_FREQUENCY_UP_THRESHOLD (80)
-#define MIN_FREQUENCY_UP_THRESHOLD (0)
+#define MIN_FREQUENCY_UP_THRESHOLD (11)
#define MAX_FREQUENCY_UP_THRESHOLD (100)
-#define DEF_FREQUENCY_DOWN_THRESHOLD (20)
-#define MIN_FREQUENCY_DOWN_THRESHOLD (0)
-#define MAX_FREQUENCY_DOWN_THRESHOLD (100)
-
/*
* The polling frequency of this governor depends on the capability of
* the processor. Default polling frequency is 1000 times the transition
@@ -55,9 +51,9 @@ static unsigned int def_sampling_rate;
#define MIN_SAMPLING_RATE (def_sampling_rate / 2)
#define MAX_SAMPLING_RATE (500 * def_sampling_rate)
#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000)
-#define DEF_SAMPLING_DOWN_FACTOR (10)
+#define DEF_SAMPLING_DOWN_FACTOR (1)
+#define MAX_SAMPLING_DOWN_FACTOR (10)
#define TRANSITION_LATENCY_LIMIT (10 * 1000)
-#define sampling_rate_in_HZ(x) (((x * HZ) < (1000 * 1000))?1:((x * HZ) / (1000 * 1000)))
static void do_dbs_timer(void *data);
@@ -78,15 +74,23 @@ struct dbs_tuners {
unsigned int sampling_rate;
unsigned int sampling_down_factor;
unsigned int up_threshold;
- unsigned int down_threshold;
+ unsigned int ignore_nice;
};
static struct dbs_tuners dbs_tuners_ins = {
.up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
- .down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD,
.sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
};
+static inline unsigned int get_cpu_idle_time(unsigned int cpu)
+{
+ return kstat_cpu(cpu).cpustat.idle +
+ kstat_cpu(cpu).cpustat.iowait +
+ ( !dbs_tuners_ins.ignore_nice ?
+ kstat_cpu(cpu).cpustat.nice :
+ 0);
+}
+
/************************** sysfs interface ************************/
static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf)
{
@@ -115,7 +119,7 @@ static ssize_t show_##file_name \
show_one(sampling_rate, sampling_rate);
show_one(sampling_down_factor, sampling_down_factor);
show_one(up_threshold, up_threshold);
-show_one(down_threshold, down_threshold);
+show_one(ignore_nice, ignore_nice);
static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused,
const char *buf, size_t count)
@@ -126,6 +130,9 @@ static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused,
if (ret != 1 )
return -EINVAL;
+ if (input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
+ return -EINVAL;
+
down(&dbs_sem);
dbs_tuners_ins.sampling_down_factor = input;
up(&dbs_sem);
@@ -161,8 +168,7 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused,
down(&dbs_sem);
if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD ||
- input < MIN_FREQUENCY_UP_THRESHOLD ||
- input <= dbs_tuners_ins.down_threshold) {
+ input < MIN_FREQUENCY_UP_THRESHOLD) {
up(&dbs_sem);
return -EINVAL;
}
@@ -173,22 +179,35 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused,
return count;
}
-static ssize_t store_down_threshold(struct cpufreq_policy *unused,
+static ssize_t store_ignore_nice(struct cpufreq_policy *policy,
const char *buf, size_t count)
{
unsigned int input;
int ret;
+
+ unsigned int j;
+
ret = sscanf (buf, "%u", &input);
+ if ( ret != 1 )
+ return -EINVAL;
+ if ( input > 1 )
+ input = 1;
+
down(&dbs_sem);
- if (ret != 1 || input > MAX_FREQUENCY_DOWN_THRESHOLD ||
- input < MIN_FREQUENCY_DOWN_THRESHOLD ||
- input >= dbs_tuners_ins.up_threshold) {
+ if ( input == dbs_tuners_ins.ignore_nice ) { /* nothing to do */
up(&dbs_sem);
- return -EINVAL;
+ return count;
}
+ dbs_tuners_ins.ignore_nice = input;
- dbs_tuners_ins.down_threshold = input;
+ /* we need to re-evaluate prev_cpu_idle_up and prev_cpu_idle_down */
+ for_each_online_cpu(j) {
+ struct cpu_dbs_info_s *j_dbs_info;
+ j_dbs_info = &per_cpu(cpu_dbs_info, j);
+ j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(j);
+ j_dbs_info->prev_cpu_idle_down = j_dbs_info->prev_cpu_idle_up;
+ }
up(&dbs_sem);
return count;
@@ -201,7 +220,7 @@ __ATTR(_name, 0644, show_##_name, store_##_name)
define_one_rw(sampling_rate);
define_one_rw(sampling_down_factor);
define_one_rw(up_threshold);
-define_one_rw(down_threshold);
+define_one_rw(ignore_nice);
static struct attribute * dbs_attributes[] = {
&sampling_rate_max.attr,
@@ -209,7 +228,7 @@ static struct attribute * dbs_attributes[] = {
&sampling_rate.attr,
&sampling_down_factor.attr,
&up_threshold.attr,
- &down_threshold.attr,
+ &ignore_nice.attr,
NULL
};
@@ -222,9 +241,8 @@ static struct attribute_group dbs_attr_group = {
static void dbs_check_cpu(int cpu)
{
- unsigned int idle_ticks, up_idle_ticks, down_idle_ticks;
- unsigned int total_idle_ticks;
- unsigned int freq_down_step;
+ unsigned int idle_ticks, up_idle_ticks, total_ticks;
+ unsigned int freq_next;
unsigned int freq_down_sampling_rate;
static int down_skip[NR_CPUS];
struct cpu_dbs_info_s *this_dbs_info;
@@ -238,38 +256,25 @@ static void dbs_check_cpu(int cpu)
policy = this_dbs_info->cur_policy;
/*
- * The default safe range is 20% to 80%
- * Every sampling_rate, we check
- * - If current idle time is less than 20%, then we try to
- * increase frequency
- * Every sampling_rate*sampling_down_factor, we check
- * - If current idle time is more than 80%, then we try to
- * decrease frequency
+ * Every sampling_rate, we check, if current idle time is less
+ * than 20% (default), then we try to increase frequency
+ * Every sampling_rate*sampling_down_factor, we look for a the lowest
+ * frequency which can sustain the load while keeping idle time over
+ * 30%. If such a frequency exist, we try to decrease to this frequency.
*
* Any frequency increase takes it to the maximum frequency.
* Frequency reduction happens at minimum steps of
- * 5% of max_frequency
+ * 5% (default) of current frequency
*/
/* Check for frequency increase */
- total_idle_ticks = kstat_cpu(cpu).cpustat.idle +
- kstat_cpu(cpu).cpustat.iowait;
- idle_ticks = total_idle_ticks -
- this_dbs_info->prev_cpu_idle_up;
- this_dbs_info->prev_cpu_idle_up = total_idle_ticks;
-
-
+ idle_ticks = UINT_MAX;
for_each_cpu_mask(j, policy->cpus) {
- unsigned int tmp_idle_ticks;
+ unsigned int tmp_idle_ticks, total_idle_ticks;
struct cpu_dbs_info_s *j_dbs_info;
- if (j == cpu)
- continue;
-
j_dbs_info = &per_cpu(cpu_dbs_info, j);
- /* Check for frequency increase */
- total_idle_ticks = kstat_cpu(j).cpustat.idle +
- kstat_cpu(j).cpustat.iowait;
+ total_idle_ticks = get_cpu_idle_time(j);
tmp_idle_ticks = total_idle_ticks -
j_dbs_info->prev_cpu_idle_up;
j_dbs_info->prev_cpu_idle_up = total_idle_ticks;
@@ -281,13 +286,23 @@ static void dbs_check_cpu(int cpu)
/* Scale idle ticks by 100 and compare with up and down ticks */
idle_ticks *= 100;
up_idle_ticks = (100 - dbs_tuners_ins.up_threshold) *
- sampling_rate_in_HZ(dbs_tuners_ins.sampling_rate);
+ usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
if (idle_ticks < up_idle_ticks) {
+ down_skip[cpu] = 0;
+ for_each_cpu_mask(j, policy->cpus) {
+ struct cpu_dbs_info_s *j_dbs_info;
+
+ j_dbs_info = &per_cpu(cpu_dbs_info, j);
+ j_dbs_info->prev_cpu_idle_down =
+ j_dbs_info->prev_cpu_idle_up;
+ }
+ /* if we are already at full speed then break out early */
+ if (policy->cur == policy->max)
+ return;
+
__cpufreq_driver_target(policy, policy->max,
CPUFREQ_RELATION_H);
- down_skip[cpu] = 0;
- this_dbs_info->prev_cpu_idle_down = total_idle_ticks;
return;
}
@@ -296,23 +311,14 @@ static void dbs_check_cpu(int cpu)
if (down_skip[cpu] < dbs_tuners_ins.sampling_down_factor)
return;
- total_idle_ticks = kstat_cpu(cpu).cpustat.idle +
- kstat_cpu(cpu).cpustat.iowait;
- idle_ticks = total_idle_ticks -
- this_dbs_info->prev_cpu_idle_down;
- this_dbs_info->prev_cpu_idle_down = total_idle_ticks;
-
+ idle_ticks = UINT_MAX;
for_each_cpu_mask(j, policy->cpus) {
- unsigned int tmp_idle_ticks;
+ unsigned int tmp_idle_ticks, total_idle_ticks;
struct cpu_dbs_info_s *j_dbs_info;
- if (j == cpu)
- continue;
-
j_dbs_info = &per_cpu(cpu_dbs_info, j);
- /* Check for frequency increase */
- total_idle_ticks = kstat_cpu(j).cpustat.idle +
- kstat_cpu(j).cpustat.iowait;
+ /* Check for frequency decrease */
+ total_idle_ticks = j_dbs_info->prev_cpu_idle_up;
tmp_idle_ticks = total_idle_ticks -
j_dbs_info->prev_cpu_idle_down;
j_dbs_info->prev_cpu_idle_down = total_idle_ticks;
@@ -321,38 +327,37 @@ static void dbs_check_cpu(int cpu)
idle_ticks = tmp_idle_ticks;
}
- /* Scale idle ticks by 100 and compare with up and down ticks */
- idle_ticks *= 100;
down_skip[cpu] = 0;
+ /* if we cannot reduce the frequency anymore, break out early */
+ if (policy->cur == policy->min)
+ return;
+ /* Compute how many ticks there are between two measurements */
freq_down_sampling_rate = dbs_tuners_ins.sampling_rate *
dbs_tuners_ins.sampling_down_factor;
- down_idle_ticks = (100 - dbs_tuners_ins.down_threshold) *
- sampling_rate_in_HZ(freq_down_sampling_rate);
+ total_ticks = usecs_to_jiffies(freq_down_sampling_rate);
- if (idle_ticks > down_idle_ticks ) {
- freq_down_step = (5 * policy->max) / 100;
-
- /* max freq cannot be less than 100. But who knows.... */
- if (unlikely(freq_down_step == 0))
- freq_down_step = 5;
+ /*
+ * The optimal frequency is the frequency that is the lowest that
+ * can support the current CPU usage without triggering the up
+ * policy. To be safe, we focus 10 points under the threshold.
+ */
+ freq_next = ((total_ticks - idle_ticks) * 100) / total_ticks;
+ freq_next = (freq_next * policy->cur) /
+ (dbs_tuners_ins.up_threshold - 10);
- __cpufreq_driver_target(policy,
- policy->cur - freq_down_step,
- CPUFREQ_RELATION_H);
- return;
- }
+ if (freq_next <= ((policy->cur * 95) / 100))
+ __cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_L);
}
static void do_dbs_timer(void *data)
{
int i;
down(&dbs_sem);
- for (i = 0; i < NR_CPUS; i++)
- if (cpu_online(i))
- dbs_check_cpu(i);
+ for_each_online_cpu(i)
+ dbs_check_cpu(i);
schedule_delayed_work(&dbs_work,
- sampling_rate_in_HZ(dbs_tuners_ins.sampling_rate));
+ usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
up(&dbs_sem);
}
@@ -360,7 +365,7 @@ static inline void dbs_timer_init(void)
{
INIT_WORK(&dbs_work, do_dbs_timer, NULL);
schedule_delayed_work(&dbs_work,
- sampling_rate_in_HZ(dbs_tuners_ins.sampling_rate));
+ usecs_to_jiffies(dbs_tuners_ins.sampling_rate));
return;
}
@@ -397,12 +402,9 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
j_dbs_info = &per_cpu(cpu_dbs_info, j);
j_dbs_info->cur_policy = policy;
- j_dbs_info->prev_cpu_idle_up =
- kstat_cpu(j).cpustat.idle +
- kstat_cpu(j).cpustat.iowait;
- j_dbs_info->prev_cpu_idle_down =
- kstat_cpu(j).cpustat.idle +
- kstat_cpu(j).cpustat.iowait;
+ j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(j);
+ j_dbs_info->prev_cpu_idle_down
+ = j_dbs_info->prev_cpu_idle_up;
}
this_dbs_info->enable = 1;
sysfs_create_group(&policy->kobj, &dbs_attr_group);
@@ -422,6 +424,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
def_sampling_rate = (latency / 1000) *
DEF_SAMPLING_RATE_LATENCY_MULTIPLIER;
dbs_tuners_ins.sampling_rate = def_sampling_rate;
+ dbs_tuners_ins.ignore_nice = 0;
dbs_timer_init();
}
@@ -461,12 +464,11 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
return 0;
}
-struct cpufreq_governor cpufreq_gov_dbs = {
+static struct cpufreq_governor cpufreq_gov_dbs = {
.name = "ondemand",
.governor = cpufreq_governor_dbs,
.owner = THIS_MODULE,
};
-EXPORT_SYMBOL(cpufreq_gov_dbs);
static int __init cpufreq_gov_dbs_init(void)
{
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index 2084593937c..741b6b191e6 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -19,6 +19,7 @@
#include <linux/percpu.h>
#include <linux/kobject.h>
#include <linux/spinlock.h>
+#include <asm/cputime.h>
static spinlock_t cpufreq_stats_lock;
@@ -29,20 +30,14 @@ static struct freq_attr _attr_##_name = {\
.show = _show,\
};
-static unsigned long
-delta_time(unsigned long old, unsigned long new)
-{
- return (old > new) ? (old - new): (new + ~old + 1);
-}
-
struct cpufreq_stats {
unsigned int cpu;
unsigned int total_trans;
- unsigned long long last_time;
+ unsigned long long last_time;
unsigned int max_state;
unsigned int state_num;
unsigned int last_index;
- unsigned long long *time_in_state;
+ cputime64_t *time_in_state;
unsigned int *freq_table;
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
unsigned int *trans_table;
@@ -60,12 +55,16 @@ static int
cpufreq_stats_update (unsigned int cpu)
{
struct cpufreq_stats *stat;
+ unsigned long long cur_time;
+
+ cur_time = get_jiffies_64();
spin_lock(&cpufreq_stats_lock);
stat = cpufreq_stats_table[cpu];
if (stat->time_in_state)
- stat->time_in_state[stat->last_index] +=
- delta_time(stat->last_time, jiffies);
- stat->last_time = jiffies;
+ stat->time_in_state[stat->last_index] =
+ cputime64_add(stat->time_in_state[stat->last_index],
+ cputime_sub(cur_time, stat->last_time));
+ stat->last_time = cur_time;
spin_unlock(&cpufreq_stats_lock);
return 0;
}
@@ -90,8 +89,8 @@ show_time_in_state(struct cpufreq_policy *policy, char *buf)
return 0;
cpufreq_stats_update(stat->cpu);
for (i = 0; i < stat->state_num; i++) {
- len += sprintf(buf + len, "%u %llu\n",
- stat->freq_table[i], stat->time_in_state[i]);
+ len += sprintf(buf + len, "%u %llu\n", stat->freq_table[i],
+ (unsigned long long)cputime64_to_clock_t(stat->time_in_state[i]));
}
return len;
}
@@ -107,16 +106,30 @@ show_trans_table(struct cpufreq_policy *policy, char *buf)
if(!stat)
return 0;
cpufreq_stats_update(stat->cpu);
+ len += snprintf(buf + len, PAGE_SIZE - len, " From : To\n");
+ len += snprintf(buf + len, PAGE_SIZE - len, " : ");
+ for (i = 0; i < stat->state_num; i++) {
+ if (len >= PAGE_SIZE)
+ break;
+ len += snprintf(buf + len, PAGE_SIZE - len, "%9u ",
+ stat->freq_table[i]);
+ }
+ if (len >= PAGE_SIZE)
+ return len;
+
+ len += snprintf(buf + len, PAGE_SIZE - len, "\n");
+
for (i = 0; i < stat->state_num; i++) {
if (len >= PAGE_SIZE)
break;
- len += snprintf(buf + len, PAGE_SIZE - len, "%9u:\t",
+
+ len += snprintf(buf + len, PAGE_SIZE - len, "%9u: ",
stat->freq_table[i]);
for (j = 0; j < stat->state_num; j++) {
if (len >= PAGE_SIZE)
break;
- len += snprintf(buf + len, PAGE_SIZE - len, "%u\t",
+ len += snprintf(buf + len, PAGE_SIZE - len, "%9u ",
stat->trans_table[i*stat->max_state+j]);
}
len += snprintf(buf + len, PAGE_SIZE - len, "\n");
@@ -197,7 +210,7 @@ cpufreq_stats_create_table (struct cpufreq_policy *policy,
count++;
}
- alloc_size = count * sizeof(int) + count * sizeof(long long);
+ alloc_size = count * sizeof(int) + count * sizeof(cputime64_t);
#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
alloc_size += count * count * sizeof(int);
@@ -224,7 +237,7 @@ cpufreq_stats_create_table (struct cpufreq_policy *policy,
}
stat->state_num = j;
spin_lock(&cpufreq_stats_lock);
- stat->last_time = jiffies;
+ stat->last_time = get_jiffies_64();
stat->last_index = freq_table_get_index(stat, policy->cur);
spin_unlock(&cpufreq_stats_lock);
cpufreq_cpu_put(data);
diff --git a/drivers/dio/dio-sysfs.c b/drivers/dio/dio-sysfs.c
index d30591f69dd..f4646303884 100644
--- a/drivers/dio/dio-sysfs.c
+++ b/drivers/dio/dio-sysfs.c
@@ -17,7 +17,7 @@
/* show configuration fields */
-static ssize_t dio_show_id(struct device *dev, char *buf)
+static ssize_t dio_show_id(struct device *dev, struct device_attribute *attr, char *buf)
{
struct dio_dev *d;
@@ -26,7 +26,7 @@ static ssize_t dio_show_id(struct device *dev, char *buf)
}
static DEVICE_ATTR(id, S_IRUGO, dio_show_id, NULL);
-static ssize_t dio_show_ipl(struct device *dev, char *buf)
+static ssize_t dio_show_ipl(struct device *dev, struct device_attribute *attr, char *buf)
{
struct dio_dev *d;
@@ -35,7 +35,7 @@ static ssize_t dio_show_ipl(struct device *dev, char *buf)
}
static DEVICE_ATTR(ipl, S_IRUGO, dio_show_ipl, NULL);
-static ssize_t dio_show_secid(struct device *dev, char *buf)
+static ssize_t dio_show_secid(struct device *dev, struct device_attribute *attr, char *buf)
{
struct dio_dev *d;
@@ -44,7 +44,7 @@ static ssize_t dio_show_secid(struct device *dev, char *buf)
}
static DEVICE_ATTR(secid, S_IRUGO, dio_show_secid, NULL);
-static ssize_t dio_show_name(struct device *dev, char *buf)
+static ssize_t dio_show_name(struct device *dev, struct device_attribute *attr, char *buf)
{
struct dio_dev *d;
@@ -53,7 +53,7 @@ static ssize_t dio_show_name(struct device *dev, char *buf)
}
static DEVICE_ATTR(name, S_IRUGO, dio_show_name, NULL);
-static ssize_t dio_show_resource(struct device *dev, char *buf)
+static ssize_t dio_show_resource(struct device *dev, struct device_attribute *attr, char *buf)
{
struct dio_dev *d = to_dio_dev(dev);
diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c
index 6381ba53853..1937743c8e2 100644
--- a/drivers/eisa/eisa-bus.c
+++ b/drivers/eisa/eisa-bus.c
@@ -149,7 +149,7 @@ void eisa_driver_unregister (struct eisa_driver *edrv)
driver_unregister (&edrv->driver);
}
-static ssize_t eisa_show_sig (struct device *dev, char *buf)
+static ssize_t eisa_show_sig (struct device *dev, struct device_attribute *attr, char *buf)
{
struct eisa_device *edev = to_eisa_device (dev);
return sprintf (buf,"%s\n", edev->id.sig);
@@ -157,7 +157,7 @@ static ssize_t eisa_show_sig (struct device *dev, char *buf)
static DEVICE_ATTR(signature, S_IRUGO, eisa_show_sig, NULL);
-static ssize_t eisa_show_state (struct device *dev, char *buf)
+static ssize_t eisa_show_state (struct device *dev, struct device_attribute *attr, char *buf)
{
struct eisa_device *edev = to_eisa_device (dev);
return sprintf (buf,"%d\n", edev->state & EISA_CONFIG_ENABLED);
diff --git a/drivers/fc4/fc.c b/drivers/fc4/fc.c
index 1fbb219aa9b..e3c95882353 100644
--- a/drivers/fc4/fc.c
+++ b/drivers/fc4/fc.c
@@ -765,12 +765,8 @@ void fcp_release(fc_channel *fcchain, int count) /* count must > 0 */
static void fcp_scsi_done (Scsi_Cmnd *SCpnt)
{
- unsigned long flags;
-
- spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
if (FCP_CMND(SCpnt)->done)
FCP_CMND(SCpnt)->done(SCpnt);
- spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
}
static int fcp_scsi_queue_it(fc_channel *fc, Scsi_Cmnd *SCpnt, fcp_cmnd *fcmd, int prepare)
@@ -909,12 +905,8 @@ int fcp_scsi_abort(Scsi_Cmnd *SCpnt)
*/
if (++fc->abort_count < (fc->can_queue >> 1)) {
- unsigned long flags;
-
SCpnt->result = DID_ABORT;
- spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
fcmd->done(SCpnt);
- spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
printk("FC: soft abort\n");
return SUCCESS;
} else {
@@ -935,6 +927,7 @@ void fcp_scsi_reset_done(Scsi_Cmnd *SCpnt)
int fcp_scsi_dev_reset(Scsi_Cmnd *SCpnt)
{
+ unsigned long flags;
fcp_cmd *cmd;
fcp_cmnd *fcmd;
fc_channel *fc = FC_SCMND(SCpnt);
@@ -987,7 +980,10 @@ int fcp_scsi_dev_reset(Scsi_Cmnd *SCpnt)
fc->rst_pkt->request->rq_status = RQ_SCSI_BUSY;
fc->rst_pkt->done = fcp_scsi_reset_done;
+
+ spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
fcp_scsi_queue_it(fc, fc->rst_pkt, fcmd, 0);
+ spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
down(&sem);
@@ -1006,13 +1002,7 @@ int fcp_scsi_dev_reset(Scsi_Cmnd *SCpnt)
return SUCCESS;
}
-int fcp_scsi_bus_reset(Scsi_Cmnd *SCpnt)
-{
- printk ("FC: bus reset!\n");
- return FAILED;
-}
-
-int fcp_scsi_host_reset(Scsi_Cmnd *SCpnt)
+static int __fcp_scsi_host_reset(Scsi_Cmnd *SCpnt)
{
fc_channel *fc = FC_SCMND(SCpnt);
fcp_cmnd *fcmd = FCP_CMND(SCpnt);
@@ -1033,6 +1023,18 @@ int fcp_scsi_host_reset(Scsi_Cmnd *SCpnt)
else return FAILED;
}
+int fcp_scsi_host_reset(Scsi_Cmnd *SCpnt)
+{
+ unsigned long flags;
+ int rc;
+
+ spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
+ rc = __fcp_scsi_host_reset(SCpnt);
+ spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
+
+ return rc;
+}
+
static int fcp_els_queue_it(fc_channel *fc, fcp_cmnd *fcmd)
{
long i;
diff --git a/drivers/fc4/fc_syms.c b/drivers/fc4/fc_syms.c
index 8bac2c45302..ed85dfcef69 100644
--- a/drivers/fc4/fc_syms.c
+++ b/drivers/fc4/fc_syms.c
@@ -27,7 +27,6 @@ EXPORT_SYMBOL(fc_do_prli);
EXPORT_SYMBOL(fcp_scsi_queuecommand);
EXPORT_SYMBOL(fcp_scsi_abort);
EXPORT_SYMBOL(fcp_scsi_dev_reset);
-EXPORT_SYMBOL(fcp_scsi_bus_reset);
EXPORT_SYMBOL(fcp_scsi_host_reset);
#endif /* CONFIG_MODULES */
diff --git a/drivers/fc4/fcp_impl.h b/drivers/fc4/fcp_impl.h
index e44d652a83d..c397c84bef6 100644
--- a/drivers/fc4/fcp_impl.h
+++ b/drivers/fc4/fcp_impl.h
@@ -158,7 +158,6 @@ int fc_do_prli(fc_channel *, unsigned char);
int fcp_scsi_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
int fcp_scsi_abort(Scsi_Cmnd *);
int fcp_scsi_dev_reset(Scsi_Cmnd *);
-int fcp_scsi_bus_reset(Scsi_Cmnd *);
int fcp_scsi_host_reset(Scsi_Cmnd *);
#endif /* !(_FCP_SCSI_H) */
diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c
index 33b669e6f97..6996476669f 100644
--- a/drivers/firmware/edd.c
+++ b/drivers/firmware/edd.c
@@ -115,7 +115,7 @@ edd_attr_show(struct kobject * kobj, struct attribute *attr, char *buf)
{
struct edd_device *dev = to_edd_device(kobj);
struct edd_attribute *edd_attr = to_edd_attr(attr);
- ssize_t ret = 0;
+ ssize_t ret = -EIO;
if (edd_attr->show)
ret = edd_attr->show(dev, buf);
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 0287ff65963..33b17c6a46f 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -352,7 +352,7 @@ static ssize_t efivar_attr_show(struct kobject *kobj, struct attribute *attr,
{
struct efivar_entry *var = to_efivar_entry(kobj);
struct efivar_attribute *efivar_attr = to_efivar_attr(attr);
- ssize_t ret = 0;
+ ssize_t ret = -EIO;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
@@ -368,7 +368,7 @@ static ssize_t efivar_attr_store(struct kobject *kobj, struct attribute *attr,
{
struct efivar_entry *var = to_efivar_entry(kobj);
struct efivar_attribute *efivar_attr = to_efivar_attr(attr);
- ssize_t ret = 0;
+ ssize_t ret = -EIO;
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
@@ -618,8 +618,8 @@ efivar_create_sysfs_entry(unsigned long variable_name_size,
new_efivar = kmalloc(sizeof(struct efivar_entry), GFP_KERNEL);
if (!short_name || !new_efivar) {
- if (short_name) kfree(short_name);
- if (new_efivar) kfree(new_efivar);
+ kfree(short_name);
+ kfree(new_efivar);
return 1;
}
memset(short_name, 0, short_name_size+1);
@@ -644,7 +644,8 @@ efivar_create_sysfs_entry(unsigned long variable_name_size,
kobj_set_kset_s(new_efivar, vars_subsys);
kobject_register(&new_efivar->kobj);
- kfree(short_name); short_name = NULL;
+ kfree(short_name);
+ short_name = NULL;
spin_lock(&efivars_lock);
list_add(&new_efivar->list, &efivar_list);
diff --git a/drivers/firmware/pcdp.c b/drivers/firmware/pcdp.c
index 6d5df6c2efa..839b44a7e08 100644
--- a/drivers/firmware/pcdp.c
+++ b/drivers/firmware/pcdp.c
@@ -11,6 +11,7 @@
* published by the Free Software Foundation.
*/
+#include <linux/config.h>
#include <linux/acpi.h>
#include <linux/console.h>
#include <linux/efi.h>
@@ -22,12 +23,15 @@ setup_serial_console(struct pcdp_uart *uart)
{
#ifdef CONFIG_SERIAL_8250_CONSOLE
int mmio;
- static char options[64];
+ static char options[64], *p = options;
mmio = (uart->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY);
- snprintf(options, sizeof(options), "console=uart,%s,0x%lx,%lun%d",
- mmio ? "mmio" : "io", uart->addr.address, uart->baud,
- uart->bits ? uart->bits : 8);
+ p += sprintf(p, "console=uart,%s,0x%lx",
+ mmio ? "mmio" : "io", uart->addr.address);
+ if (uart->baud)
+ p += sprintf(p, ",%lu", uart->baud);
+ if (uart->bits)
+ p += sprintf(p, "n%d", uart->bits);
return early_serial_console_init(options);
#else
diff --git a/drivers/firmware/pcdp.h b/drivers/firmware/pcdp.h
index 863bb6f768c..1dc7c88b7b4 100644
--- a/drivers/firmware/pcdp.h
+++ b/drivers/firmware/pcdp.h
@@ -2,7 +2,7 @@
* Definitions for PCDP-defined console devices
*
* v1.0a: http://www.dig64.org/specifications/DIG64_HCDPv10a_01.pdf
- * v2.0: http://www.dig64.org/specifications/DIG64_HCDPv20_042804.pdf
+ * v2.0: http://www.dig64.org/specifications/DIG64_PCDPv20.pdf
*
* (c) Copyright 2002, 2004 Hewlett-Packard Development Company, L.P.
* Khalid Aziz <khalid.aziz@hp.com>
diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
index c3d912cbbbc..cc3a952401f 100644
--- a/drivers/i2c/algos/i2c-algo-pca.c
+++ b/drivers/i2c/algos/i2c-algo-pca.c
@@ -49,7 +49,7 @@ static int i2c_debug=0;
/*
* Generate a start condition on the i2c bus.
*
- * returns after the start condition has occured
+ * returns after the start condition has occurred
*/
static void pca_start(struct i2c_algo_pca_data *adap)
{
@@ -62,9 +62,9 @@ static void pca_start(struct i2c_algo_pca_data *adap)
}
/*
- * Generate a repeated start condition on the i2c bus
+ * Generate a repeated start condition on the i2c bus
*
- * return after the repeated start condition has occured
+ * return after the repeated start condition has occurred
*/
static void pca_repeated_start(struct i2c_algo_pca_data *adap)
{
@@ -82,7 +82,7 @@ static void pca_repeated_start(struct i2c_algo_pca_data *adap)
* returns after the stop condition has been generated
*
* STOPs do not generate an interrupt or set the SI flag, since the
- * part returns the the idle state (0xf8). Hence we don't need to
+ * part returns the idle state (0xf8). Hence we don't need to
* pca_wait here.
*/
static void pca_stop(struct i2c_algo_pca_data *adap)
diff --git a/drivers/i2c/algos/i2c-algo-sibyte.c b/drivers/i2c/algos/i2c-algo-sibyte.c
index 35789bb7126..f2785499237 100644
--- a/drivers/i2c/algos/i2c-algo-sibyte.c
+++ b/drivers/i2c/algos/i2c-algo-sibyte.c
@@ -24,7 +24,6 @@
/* Ported for SiByte SOCs by Broadcom Corporation. */
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index a0018de3bef..916ba5e40a9 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -7,7 +7,7 @@ menu "I2C Hardware Bus support"
config I2C_ALI1535
tristate "ALI 1535"
- depends on I2C && PCI && EXPERIMENTAL
+ depends on I2C && PCI
help
If you say yes to this option, support will be included for the SMB
Host controller on Acer Labs Inc. (ALI) M1535 South Bridges. The SMB
@@ -31,7 +31,7 @@ config I2C_ALI1563
config I2C_ALI15X3
tristate "ALI 15x3"
- depends on I2C && PCI && EXPERIMENTAL
+ depends on I2C && PCI
help
If you say yes to this option, support will be included for the
Acer Labs Inc. (ALI) M1514 and M1543 motherboard I2C interfaces.
@@ -41,7 +41,7 @@ config I2C_ALI15X3
config I2C_AMD756
tristate "AMD 756/766/768/8111 and nVidia nForce"
- depends on I2C && PCI && EXPERIMENTAL
+ depends on I2C && PCI
help
If you say yes to this option, support will be included for the AMD
756/766/768 mainboard I2C interfaces. The driver also includes
@@ -66,7 +66,7 @@ config I2C_AMD756_S4882
config I2C_AMD8111
tristate "AMD 8111"
- depends on I2C && PCI && EXPERIMENTAL
+ depends on I2C && PCI
help
If you say yes to this option, support will be included for the
second (SMBus 2.0) AMD 8111 mainboard I2C interface.
@@ -109,7 +109,7 @@ config I2C_HYDRA
config I2C_I801
tristate "Intel 82801 (ICH)"
- depends on I2C && PCI && EXPERIMENTAL
+ depends on I2C && PCI
help
If you say yes to this option, support will be included for the Intel
801 family of mainboard I2C interfaces. Specifically, the following
@@ -130,7 +130,7 @@ config I2C_I801
config I2C_I810
tristate "Intel 810/815"
- depends on I2C && PCI && EXPERIMENTAL
+ depends on I2C && PCI
select I2C_ALGOBIT
help
If you say yes to this option, support will be included for the Intel
@@ -183,7 +183,7 @@ config I2C_IOP3XX
config I2C_ISA
tristate "ISA Bus support"
- depends on I2C && EXPERIMENTAL
+ depends on I2C
help
If you say yes to this option, support will be included for i2c
interfaces that are on the ISA bus.
@@ -248,12 +248,11 @@ config I2C_MPC
will be called i2c-mpc.
config I2C_NFORCE2
- tristate "Nvidia Nforce2"
- depends on I2C && PCI && EXPERIMENTAL
+ tristate "Nvidia nForce2, nForce3 and nForce4"
+ depends on I2C && PCI
help
If you say yes to this option, support will be included for the Nvidia
- Nforce2 family of mainboard I2C interfaces.
- This driver also supports the nForce3 Pro 150 MCP.
+ nForce2, nForce3 and nForce4 families of mainboard I2C interfaces.
This driver can also be built as a module. If so, the module
will be called i2c-nforce2.
@@ -305,7 +304,7 @@ config I2C_PARPORT_LIGHT
config I2C_PROSAVAGE
tristate "S3/VIA (Pro)Savage"
- depends on I2C && PCI && EXPERIMENTAL
+ depends on I2C && PCI
select I2C_ALGOBIT
help
If you say yes to this option, support will be included for the
@@ -388,7 +387,7 @@ config SCx200_ACB
config I2C_SIS5595
tristate "SiS 5595"
- depends on I2C && PCI && EXPERIMENTAL
+ depends on I2C && PCI
help
If you say yes to this option, support will be included for the
SiS5595 SMBus (a subset of I2C) interface.
@@ -398,7 +397,7 @@ config I2C_SIS5595
config I2C_SIS630
tristate "SiS 630/730"
- depends on I2C && PCI && EXPERIMENTAL
+ depends on I2C && PCI
help
If you say yes to this option, support will be included for the
SiS630 and SiS730 SMBus (a subset of I2C) interface.
@@ -408,7 +407,7 @@ config I2C_SIS630
config I2C_SIS96X
tristate "SiS 96x"
- depends on I2C && PCI && EXPERIMENTAL
+ depends on I2C && PCI
help
If you say yes to this option, support will be included for the SiS
96x SMBus (a subset of I2C) interfaces. Specifically, the following
@@ -419,6 +418,7 @@ config I2C_SIS96X
648/961
650/961
735
+ 745
This driver can also be built as a module. If so, the module
will be called i2c-sis96x.
@@ -449,7 +449,7 @@ config I2C_VIA
config I2C_VIAPRO
tristate "VIA 82C596/82C686/823x"
- depends on I2C && PCI && EXPERIMENTAL
+ depends on I2C && PCI
help
If you say yes to this option, support will be included for the VIA
82C596/82C686/823x I2C interfaces. Specifically, the following
@@ -467,7 +467,7 @@ config I2C_VIAPRO
config I2C_VOODOO3
tristate "Voodoo 3"
- depends on I2C && PCI && EXPERIMENTAL
+ depends on I2C && PCI
select I2C_ALGOBIT
help
If you say yes to this option, support will be included for the
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
index b00cd409822..f634a0780cf 100644
--- a/drivers/i2c/busses/i2c-ali1535.c
+++ b/drivers/i2c/busses/i2c-ali1535.c
@@ -53,7 +53,6 @@
/* Note: we assume there can only be one ALI1535, with one SMBus interface */
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
index 35710818fe4..fdd881aee61 100644
--- a/drivers/i2c/busses/i2c-ali1563.c
+++ b/drivers/i2c/busses/i2c-ali1563.c
@@ -2,6 +2,7 @@
* i2c-ali1563.c - i2c driver for the ALi 1563 Southbridge
*
* Copyright (C) 2004 Patrick Mochel
+ * 2005 Rudolf Marek <r.marek@sh.cvut.cz>
*
* The 1563 southbridge is deceptively similar to the 1533, with a
* few notable exceptions. One of those happens to be the fact they
@@ -57,10 +58,11 @@
#define HST_CNTL2_BLOCK 0x05
+#define HST_CNTL2_SIZEMASK 0x38
static unsigned short ali1563_smba;
-static int ali1563_transaction(struct i2c_adapter * a)
+static int ali1563_transaction(struct i2c_adapter * a, int size)
{
u32 data;
int timeout;
@@ -73,7 +75,7 @@ static int ali1563_transaction(struct i2c_adapter * a)
data = inb_p(SMB_HST_STS);
if (data & HST_STS_BAD) {
- dev_warn(&a->dev,"ali1563: Trying to reset busy device\n");
+ dev_err(&a->dev, "ali1563: Trying to reset busy device\n");
outb_p(data | HST_STS_BAD,SMB_HST_STS);
data = inb_p(SMB_HST_STS);
if (data & HST_STS_BAD)
@@ -94,19 +96,31 @@ static int ali1563_transaction(struct i2c_adapter * a)
if (timeout && !(data & HST_STS_BAD))
return 0;
- dev_warn(&a->dev, "SMBus Error: %s%s%s%s%s\n",
- timeout ? "Timeout " : "",
- data & HST_STS_FAIL ? "Transaction Failed " : "",
- data & HST_STS_BUSERR ? "No response or Bus Collision " : "",
- data & HST_STS_DEVERR ? "Device Error " : "",
- !(data & HST_STS_DONE) ? "Transaction Never Finished " : "");
- if (!(data & HST_STS_DONE))
+ if (!timeout) {
+ dev_err(&a->dev, "Timeout - Trying to KILL transaction!\n");
/* Issue 'kill' to host controller */
outb_p(HST_CNTL2_KILL,SMB_HST_CNTL2);
- else
- /* Issue timeout to reset all devices on bus */
+ data = inb_p(SMB_HST_STS);
+ }
+
+ /* device error - no response, ignore the autodetection case */
+ if ((data & HST_STS_DEVERR) && (size != HST_CNTL2_QUICK)) {
+ dev_err(&a->dev, "Device error!\n");
+ }
+
+ /* bus collision */
+ if (data & HST_STS_BUSERR) {
+ dev_err(&a->dev, "Bus collision!\n");
+ /* Issue timeout, hoping it helps */
outb_p(HST_CNTL1_TIMEOUT,SMB_HST_CNTL1);
+ }
+
+ if (data & HST_STS_FAIL) {
+ dev_err(&a->dev, "Cleaning fail after KILL!\n");
+ outb_p(0x0,SMB_HST_CNTL2);
+ }
+
return -1;
}
@@ -149,7 +163,7 @@ static int ali1563_block_start(struct i2c_adapter * a)
if (timeout && !(data & HST_STS_BAD))
return 0;
- dev_warn(&a->dev, "SMBus Error: %s%s%s%s%s\n",
+ dev_err(&a->dev, "SMBus Error: %s%s%s%s%s\n",
timeout ? "Timeout " : "",
data & HST_STS_FAIL ? "Transaction Failed " : "",
data & HST_STS_BUSERR ? "No response or Bus Collision " : "",
@@ -242,13 +256,15 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
}
outb_p(((addr & 0x7f) << 1) | (rw & 0x01), SMB_HST_ADD);
- outb_p(inb_p(SMB_HST_CNTL2) | (size << 3), SMB_HST_CNTL2);
+ outb_p((inb_p(SMB_HST_CNTL2) & ~HST_CNTL2_SIZEMASK) | (size << 3), SMB_HST_CNTL2);
/* Write the command register */
+
switch(size) {
case HST_CNTL2_BYTE:
if (rw== I2C_SMBUS_WRITE)
- outb_p(cmd, SMB_HST_CMD);
+ /* Beware it uses DAT0 register and not CMD! */
+ outb_p(cmd, SMB_HST_DAT0);
break;
case HST_CNTL2_BYTE_DATA:
outb_p(cmd, SMB_HST_CMD);
@@ -268,7 +284,7 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
goto Done;
}
- if ((error = ali1563_transaction(a)))
+ if ((error = ali1563_transaction(a, size)))
goto Done;
if ((rw == I2C_SMBUS_WRITE) || (size == HST_CNTL2_QUICK))
diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
index 5bd6a4a77c1..0f781a1a332 100644
--- a/drivers/i2c/busses/i2c-ali15x3.c
+++ b/drivers/i2c/busses/i2c-ali15x3.c
@@ -60,7 +60,6 @@
/* Note: we assume there can only be one ALI15X3, with one SMBus interface */
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
index eca5ed3738b..6347ebc6fb5 100644
--- a/drivers/i2c/busses/i2c-amd756.c
+++ b/drivers/i2c/busses/i2c-amd756.c
@@ -37,7 +37,6 @@
Note: we assume there can only be one device, with one SMBus interface.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
index af22b401a38..d6644481d2a 100644
--- a/drivers/i2c/busses/i2c-amd8111.c
+++ b/drivers/i2c/busses/i2c-amd8111.c
@@ -8,7 +8,6 @@
* the Free Software Foundation version 2.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c
index 75831a20b0b..a7ff112e49b 100644
--- a/drivers/i2c/busses/i2c-au1550.c
+++ b/drivers/i2c/busses/i2c-au1550.c
@@ -27,7 +27,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include <linux/config.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c
index 0a7720000a0..6930b660e50 100644
--- a/drivers/i2c/busses/i2c-elektor.c
+++ b/drivers/i2c/busses/i2c-elektor.c
@@ -25,7 +25,6 @@
/* Partialy rewriten by Oleg I. Vdovikin for mmapped support of
for Alpha Processor Inc. UP-2000(+) boards */
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/module.h>
diff --git a/drivers/i2c/busses/i2c-frodo.c b/drivers/i2c/busses/i2c-frodo.c
index e093829a0bf..b6f52f5a413 100644
--- a/drivers/i2c/busses/i2c-frodo.c
+++ b/drivers/i2c/busses/i2c-frodo.c
@@ -12,7 +12,6 @@
* version 2 as published by the Free Software Foundation.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 59c238c42e8..45e6efb1dcd 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -41,7 +41,6 @@
/* Note: we assume there can only be one I801, with one SMBus interface */
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
diff --git a/drivers/i2c/busses/i2c-i810.c b/drivers/i2c/busses/i2c-i810.c
index ef358bd9c3d..0ff7016e062 100644
--- a/drivers/i2c/busses/i2c-i810.c
+++ b/drivers/i2c/busses/i2c-i810.c
@@ -34,7 +34,6 @@
i815 1132
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index bb885215c08..93ca36dc777 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -695,7 +695,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
dev->irq = iic_force_poll ? -1 : ocp->def->irq;
if (dev->irq >= 0){
- /* Disable interrupts until we finish intialization,
+ /* Disable interrupts until we finish initialization,
assumes level-sensitive IRQ setup...
*/
iic_interrupt_mode(dev, 0);
diff --git a/drivers/i2c/busses/i2c-ibm_iic.h b/drivers/i2c/busses/i2c-ibm_iic.h
index d819a955d89..2b3219d00e9 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.h
+++ b/drivers/i2c/busses/i2c-ibm_iic.h
@@ -22,7 +22,6 @@
#ifndef __I2C_IBM_IIC_H_
#define __I2C_IBM_IIC_H_
-#include <linux/config.h>
#include <linux/i2c.h>
struct iic_regs {
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index c961ba4cfb3..6b682e903f0 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -85,7 +85,7 @@ iop3xx_i2c_enable(struct i2c_algo_iop3xx_data *iop3xx_adap)
u32 cr = IOP3XX_ICR_GCD | IOP3XX_ICR_SCLEN | IOP3XX_ICR_UE;
/*
- * Everytime unit enable is asserted, GPOD needs to be cleared
+ * Every time unit enable is asserted, GPOD needs to be cleared
* on IOP321 to avoid data corruption on the bus.
*/
#ifdef CONFIG_ARCH_IOP321
diff --git a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c
index 0f54a2a0afa..00e7f7157b7 100644
--- a/drivers/i2c/busses/i2c-isa.c
+++ b/drivers/i2c/busses/i2c-isa.c
@@ -24,7 +24,6 @@
the SMBus and the ISA bus very much easier. See lm78.c for an example
of this. */
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
diff --git a/drivers/i2c/busses/i2c-ite.c b/drivers/i2c/busses/i2c-ite.c
index 702e3def1b8..5f5d2944808 100644
--- a/drivers/i2c/busses/i2c-ite.c
+++ b/drivers/i2c/busses/i2c-ite.c
@@ -33,7 +33,6 @@
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
Frodo Looijaard <frodol@dds.nl> */
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/module.h>
diff --git a/drivers/i2c/busses/i2c-ixp2000.c b/drivers/i2c/busses/i2c-ixp2000.c
index 21cd54d0230..1956af382cd 100644
--- a/drivers/i2c/busses/i2c-ixp2000.c
+++ b/drivers/i2c/busses/i2c-ixp2000.c
@@ -26,11 +26,6 @@
* 'enabled' to drive the GPIOs.
*/
-#include <linux/config.h>
-#ifdef CONFIG_I2C_DEBUG_BUS
-#define DEBUG 1
-#endif
-
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
@@ -38,7 +33,8 @@
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
-#include <asm/hardware.h> /* Pick up IXP42000-specific bits */
+#include <asm/hardware.h> /* Pick up IXP2000-specific bits */
+#include <asm/arch/gpio.h>
static inline int ixp2000_scl_pin(void *data)
{
diff --git a/drivers/i2c/busses/i2c-ixp4xx.c b/drivers/i2c/busses/i2c-ixp4xx.c
index 8c55eafc3a0..f6f5ca31fdb 100644
--- a/drivers/i2c/busses/i2c-ixp4xx.c
+++ b/drivers/i2c/busses/i2c-ixp4xx.c
@@ -26,11 +26,6 @@
* that is passed as the platform_data to this driver.
*/
-#include <linux/config.h>
-#ifdef CONFIG_I2C_DEBUG_BUS
-#define DEBUG 1
-#endif
-
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
diff --git a/drivers/i2c/busses/i2c-keywest.c b/drivers/i2c/busses/i2c-keywest.c
index dd0d4c46314..363e545fc01 100644
--- a/drivers/i2c/busses/i2c-keywest.c
+++ b/drivers/i2c/busses/i2c-keywest.c
@@ -46,7 +46,6 @@
sound driver to be happy
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
@@ -516,6 +515,11 @@ create_iface(struct device_node *np, struct device *dev)
u32 *psteps, *prate;
int rc;
+ if (np->n_intrs < 1 || np->n_addrs < 1) {
+ printk(KERN_ERR "%s: Missing interrupt or address !\n",
+ np->full_name);
+ return -ENODEV;
+ }
if (pmac_low_i2c_lock(np))
return -ENODEV;
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 6f33496d31c..03c23ce98ed 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -20,13 +20,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <asm/io.h>
-#ifdef CONFIG_FSL_OCP
-#include <asm/ocp.h>
-#define FSL_I2C_DEV_SEPARATE_DFSRR FS_I2C_SEPARATE_DFSRR
-#define FSL_I2C_DEV_CLOCK_5200 FS_I2C_CLOCK_5200
-#else
#include <linux/fsl_devices.h>
-#endif
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
@@ -294,202 +288,6 @@ static struct i2c_adapter mpc_ops = {
.retries = 1
};
-#ifdef CONFIG_FSL_OCP
-static int __devinit mpc_i2c_probe(struct ocp_device *ocp)
-{
- int result = 0;
- struct mpc_i2c *i2c;
-
- if (!(i2c = kmalloc(sizeof(*i2c), GFP_KERNEL))) {
- return -ENOMEM;
- }
- memset(i2c, 0, sizeof(*i2c));
-
- i2c->irq = ocp->def->irq;
- i2c->flags = ((struct ocp_fs_i2c_data *)ocp->def->additions)->flags;
- init_waitqueue_head(&i2c->queue);
-
- if (!request_mem_region(ocp->def->paddr, MPC_I2C_REGION, "i2c-mpc")) {
- printk(KERN_ERR "i2c-mpc - resource unavailable\n");
- return -ENODEV;
- }
-
- i2c->base = ioremap(ocp->def->paddr, MPC_I2C_REGION);
-
- if (!i2c->base) {
- printk(KERN_ERR "i2c-mpc - failed to map controller\n");
- result = -ENOMEM;
- goto fail_map;
- }
-
- if (i2c->irq != OCP_IRQ_NA)
- {
- if ((result = request_irq(ocp->def->irq, mpc_i2c_isr,
- 0, "i2c-mpc", i2c)) < 0) {
- printk(KERN_ERR
- "i2c-mpc - failed to attach interrupt\n");
- goto fail_irq;
- }
- } else
- i2c->irq = 0;
-
- i2c->adap = mpc_ops;
- i2c_set_adapdata(&i2c->adap, i2c);
-
- if ((result = i2c_add_adapter(&i2c->adap)) < 0) {
- printk(KERN_ERR "i2c-mpc - failed to add adapter\n");
- goto fail_add;
- }
-
- mpc_i2c_setclock(i2c);
- ocp_set_drvdata(ocp, i2c);
- return result;
-
- fail_add:
- if (ocp->def->irq != OCP_IRQ_NA)
- free_irq(ocp->def->irq, 0);
- fail_irq:
- iounmap(i2c->base);
- fail_map:
- release_mem_region(ocp->def->paddr, MPC_I2C_REGION);
- kfree(i2c);
- return result;
-}
-static void __devexit mpc_i2c_remove(struct ocp_device *ocp)
-{
- struct mpc_i2c *i2c = ocp_get_drvdata(ocp);
- ocp_set_drvdata(ocp, NULL);
- i2c_del_adapter(&i2c->adap);
-
- if (ocp->def->irq != OCP_IRQ_NA)
- free_irq(i2c->irq, i2c);
- iounmap(i2c->base);
- release_mem_region(ocp->def->paddr, MPC_I2C_REGION);
- kfree(i2c);
-}
-
-static struct ocp_device_id mpc_iic_ids[] __devinitdata = {
- {.vendor = OCP_VENDOR_FREESCALE,.function = OCP_FUNC_IIC},
- {.vendor = OCP_VENDOR_INVALID}
-};
-
-MODULE_DEVICE_TABLE(ocp, mpc_iic_ids);
-
-static struct ocp_driver mpc_iic_driver = {
- .name = "iic",
- .id_table = mpc_iic_ids,
- .probe = mpc_i2c_probe,
- .remove = __devexit_p(mpc_i2c_remove)
-};
-
-static int __init iic_init(void)
-{
- return ocp_register_driver(&mpc_iic_driver);
-}
-
-static void __exit iic_exit(void)
-{
- ocp_unregister_driver(&mpc_iic_driver);
-}
-
-module_init(iic_init);
-module_exit(iic_exit);
-#else
-static int fsl_i2c_probe(struct device *device)
-{
- int result = 0;
- struct mpc_i2c *i2c;
- struct platform_device *pdev = to_platform_device(device);
- struct fsl_i2c_platform_data *pdata;
- struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
- pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data;
-
- if (!(i2c = kmalloc(sizeof(*i2c), GFP_KERNEL))) {
- return -ENOMEM;
- }
- memset(i2c, 0, sizeof(*i2c));
-
- i2c->irq = platform_get_irq(pdev, 0);
- i2c->flags = pdata->device_flags;
- init_waitqueue_head(&i2c->queue);
-
- i2c->base = ioremap((phys_addr_t)r->start, MPC_I2C_REGION);
-
- if (!i2c->base) {
- printk(KERN_ERR "i2c-mpc - failed to map controller\n");
- result = -ENOMEM;
- goto fail_map;
- }
-
- if (i2c->irq != 0)
- if ((result = request_irq(i2c->irq, mpc_i2c_isr,
- 0, "fsl-i2c", i2c)) < 0) {
- printk(KERN_ERR
- "i2c-mpc - failed to attach interrupt\n");
- goto fail_irq;
- }
-
- i2c->adap = mpc_ops;
- i2c_set_adapdata(&i2c->adap, i2c);
- i2c->adap.dev.parent = &pdev->dev;
- if ((result = i2c_add_adapter(&i2c->adap)) < 0) {
- printk(KERN_ERR "i2c-mpc - failed to add adapter\n");
- goto fail_add;
- }
-
- mpc_i2c_setclock(i2c);
- dev_set_drvdata(device, i2c);
- return result;
-
- fail_add:
- if (i2c->irq != 0)
- free_irq(i2c->irq, NULL);
- fail_irq:
- iounmap(i2c->base);
- fail_map:
- kfree(i2c);
- return result;
-};
-
-static int fsl_i2c_remove(struct device *device)
-{
- struct mpc_i2c *i2c = dev_get_drvdata(device);
-
- dev_set_drvdata(device, NULL);
- i2c_del_adapter(&i2c->adap);
-
- if (i2c->irq != 0)
- free_irq(i2c->irq, i2c);
-
- iounmap(i2c->base);
- kfree(i2c);
- return 0;
-};
-
-/* Structure for a device driver */
-static struct device_driver fsl_i2c_driver = {
- .name = "fsl-i2c",
- .bus = &platform_bus_type,
- .probe = fsl_i2c_probe,
- .remove = fsl_i2c_remove,
-};
-
-static int __init fsl_i2c_init(void)
-{
- return driver_register(&fsl_i2c_driver);
-}
-
-static void __exit fsl_i2c_exit(void)
-{
- driver_unregister(&fsl_i2c_driver);
-}
-
-module_init(fsl_i2c_init);
-module_exit(fsl_i2c_exit);
-
-#endif /* CONFIG_FSL_OCP */
-
MODULE_AUTHOR("Adrian Cox <adrian@humboldt.co.uk>");
MODULE_DESCRIPTION
("I2C-Bus adapter for MPC107 bridge and MPC824x/85xx/52xx processors");
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index 6d13127c8c4..74eb89aa935 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -37,7 +37,6 @@
/* Note: we assume there can only be one nForce2, with two SMBus interfaces */
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c
index cb5e722301d..3e5eba9fcac 100644
--- a/drivers/i2c/busses/i2c-parport-light.c
+++ b/drivers/i2c/busses/i2c-parport-light.c
@@ -24,7 +24,6 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* ------------------------------------------------------------------------ */
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c
index e9560bab51c..71a2502fe06 100644
--- a/drivers/i2c/busses/i2c-parport.c
+++ b/drivers/i2c/busses/i2c-parport.c
@@ -24,7 +24,6 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
* ------------------------------------------------------------------------ */
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -131,7 +130,7 @@ static int parport_getsda(void *data)
/* Encapsulate the functions above in the correct structure.
Note that this is only a template, from which the real structures are
copied. The attaching code will set getscl to NULL for adapters that
- cannot read SCL back, and will also make the the data field point to
+ cannot read SCL back, and will also make the data field point to
the parallel port structure. */
static struct i2c_algo_bit_data parport_algo_data = {
.setsda = parport_setsda,
diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c
index 9c611134db9..d9b4ddbad7e 100644
--- a/drivers/i2c/busses/i2c-pca-isa.c
+++ b/drivers/i2c/busses/i2c-pca-isa.c
@@ -17,7 +17,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/module.h>
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 646381b6b3b..1f80ba9da6f 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -28,7 +28,6 @@
Note: we assume there can only be one device, with one SMBus interface.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/pci.h>
diff --git a/drivers/i2c/busses/i2c-prosavage.c b/drivers/i2c/busses/i2c-prosavage.c
index 13d66289933..83fd16d61ce 100644
--- a/drivers/i2c/busses/i2c-prosavage.c
+++ b/drivers/i2c/busses/i2c-prosavage.c
@@ -54,7 +54,6 @@
* (Additional documentation needed :(
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
diff --git a/drivers/i2c/busses/i2c-rpx.c b/drivers/i2c/busses/i2c-rpx.c
index 9497b1b6852..0ebec3c1a54 100644
--- a/drivers/i2c/busses/i2c-rpx.c
+++ b/drivers/i2c/busses/i2c-rpx.c
@@ -11,7 +11,6 @@
* changed to eliminate RPXLite references.
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index fcfa51c1436..a3b38257cc3 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -20,6 +20,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -533,7 +534,7 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int
/* s3c24xx_i2c_xfer
*
* first port of call from the i2c bus code when an message needs
- * transfering across the i2c bus.
+ * transferring across the i2c bus.
*/
static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
diff --git a/drivers/i2c/busses/i2c-savage4.c b/drivers/i2c/busses/i2c-savage4.c
index 092d0323c6c..0c8518298e4 100644
--- a/drivers/i2c/busses/i2c-savage4.c
+++ b/drivers/i2c/busses/i2c-savage4.c
@@ -29,7 +29,6 @@
it easier to add later.
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c
index e5dd90bdb04..1c99536b673 100644
--- a/drivers/i2c/busses/i2c-sibyte.c
+++ b/drivers/i2c/busses/i2c-sibyte.c
@@ -17,7 +17,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/i2c-algo-sibyte.h>
#include <asm/sibyte/sb1250_regs.h>
diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c
index 425733b019b..2b5911cfb7b 100644
--- a/drivers/i2c/busses/i2c-sis5595.c
+++ b/drivers/i2c/busses/i2c-sis5595.c
@@ -55,7 +55,6 @@
* Add adapter resets
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c
index 58df63df154..f58455e7689 100644
--- a/drivers/i2c/busses/i2c-sis630.c
+++ b/drivers/i2c/busses/i2c-sis630.c
@@ -48,7 +48,6 @@
Note: we assume there can only be one device, with one SMBus interface.
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
index 3cac6d43bce..6484792e23a 100644
--- a/drivers/i2c/busses/i2c-sis96x.c
+++ b/drivers/i2c/busses/i2c-sis96x.c
@@ -32,7 +32,6 @@
We assume there can only be one SiS96x with one SMBus interface.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/kernel.h>
diff --git a/drivers/i2c/busses/i2c-stub.c b/drivers/i2c/busses/i2c-stub.c
index 19c805ead4d..00d94e88695 100644
--- a/drivers/i2c/busses/i2c-stub.c
+++ b/drivers/i2c/busses/i2c-stub.c
@@ -21,7 +21,6 @@
#define DEBUG 1
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
diff --git a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c
index 2cbc4cd2236..040b8abeabb 100644
--- a/drivers/i2c/busses/i2c-via.c
+++ b/drivers/i2c/busses/i2c-via.c
@@ -21,7 +21,6 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index 0bb60a636e1..6b5008005c6 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -33,7 +33,6 @@
Note: we assume there can only be one device, with one SMBus interface.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/pci.h>
diff --git a/drivers/i2c/busses/i2c-voodoo3.c b/drivers/i2c/busses/i2c-voodoo3.c
index 3edf0e34155..b675773b0cc 100644
--- a/drivers/i2c/busses/i2c-voodoo3.c
+++ b/drivers/i2c/busses/i2c-voodoo3.c
@@ -27,7 +27,6 @@
/* This interfaces to the I2C bus of the Voodoo3 to gain access to
the BT869 and possibly other I2C devices. */
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index 1c4159a9362..a18bdd9aa7b 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -24,7 +24,6 @@
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/kernel.h>
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 74d23cfce2a..a0982da0980 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -1,5 +1,5 @@
#
-# I2C Sensor device configuration
+# I2C Sensor and "other" chip configuration
#
menu "Hardware Sensors Chip support"
@@ -11,7 +11,7 @@ config I2C_SENSOR
config SENSORS_ADM1021
tristate "Analog Devices ADM1021 and compatibles"
- depends on I2C && EXPERIMENTAL
+ depends on I2C
select I2C_SENSOR
help
If you say yes here you get support for Analog Devices ADM1021
@@ -29,6 +29,7 @@ config SENSORS_ADM1025
help
If you say yes here you get support for Analog Devices ADM1025
and Philips NE1619 sensor chips.
+
This driver can also be built as a module. If so, the module
will be called adm1025.
@@ -38,6 +39,8 @@ config SENSORS_ADM1026
select I2C_SENSOR
help
If you say yes here you get support for Analog Devices ADM1026
+ sensor chip.
+
This driver can also be built as a module. If so, the module
will be called adm1026.
@@ -48,9 +51,21 @@ config SENSORS_ADM1031
help
If you say yes here you get support for Analog Devices ADM1031
and ADM1030 sensor chips.
+
This driver can also be built as a module. If so, the module
will be called adm1031.
+config SENSORS_ADM9240
+ tristate "Analog Devices ADM9240 and compatibles"
+ depends on I2C && EXPERIMENTAL
+ select I2C_SENSOR
+ help
+ If you say yes here you get support for Analog Devices ADM9240,
+ Dallas DS1780, National Semiconductor LM81 sensor chips.
+
+ This driver can also be built as a module. If so, the module
+ will be called adm9240.
+
config SENSORS_ASB100
tristate "Asus ASB100 Bach"
depends on I2C && EXPERIMENTAL
@@ -62,6 +77,19 @@ config SENSORS_ASB100
This driver can also be built as a module. If so, the module
will be called asb100.
+config SENSORS_ATXP1
+ tristate "Attansic ATXP1 VID controller"
+ depends on I2C && EXPERIMENTAL
+ help
+ If you say yes here you get support for the Attansic ATXP1 VID
+ controller.
+
+ If your board have such a chip, you are able to control your CPU
+ core and other voltages.
+
+ This driver can also be built as a module. If so, the module
+ will be called atxp1.
+
config SENSORS_DS1621
tristate "Dallas Semiconductor DS1621 and DS1625"
depends on I2C && EXPERIMENTAL
@@ -97,7 +125,7 @@ config SENSORS_FSCPOS
config SENSORS_GL518SM
tristate "Genesys Logic GL518SM"
- depends on I2C && EXPERIMENTAL
+ depends on I2C
select I2C_SENSOR
help
If you say yes here you get support for Genesys Logic GL518SM
@@ -119,7 +147,7 @@ config SENSORS_GL520SM
config SENSORS_IT87
tristate "ITE IT87xx and compatibles"
- depends on I2C && EXPERIMENTAL
+ depends on I2C
select I2C_SENSOR
help
If you say yes here you get support for ITE IT87xx sensor chips
@@ -143,7 +171,7 @@ config SENSORS_LM63
config SENSORS_LM75
tristate "National Semiconductor LM75 and compatibles"
- depends on I2C && EXPERIMENTAL
+ depends on I2C
select I2C_SENSOR
help
If you say yes here you get support for National Semiconductor LM75
@@ -174,8 +202,7 @@ config SENSORS_LM78
select I2C_SENSOR
help
If you say yes here you get support for National Semiconductor LM78,
- LM78-J and LM79. This can also be built as a module which can be
- inserted and removed while the kernel is running.
+ LM78-J and LM79.
This driver can also be built as a module. If so, the module
will be called lm78.
@@ -208,7 +235,7 @@ config SENSORS_LM85
select I2C_SENSOR
help
If you say yes here you get support for National Semiconductor LM85
- sensor chips and clones: ADT7463 and ADM1027.
+ sensor chips and clones: ADT7463, EMC6D100, EMC6D102 and ADM1027.
This driver can also be built as a module. If so, the module
will be called lm85.
@@ -307,14 +334,14 @@ config SENSORS_SMSC47M1
help
If you say yes here you get support for the integrated fan
monitoring and control capabilities of the SMSC LPC47B27x,
- LPC47M10x, LPC47M13x and LPC47M14x chips.
+ LPC47M10x, LPC47M13x, LPC47M14x, LPC47M15x and LPC47M192 chips.
This driver can also be built as a module. If so, the module
will be called smsc47m1.
config SENSORS_VIA686A
tristate "VIA686A"
- depends on I2C && PCI && EXPERIMENTAL
+ depends on I2C && PCI
select I2C_SENSOR
select I2C_ISA
help
@@ -326,7 +353,7 @@ config SENSORS_VIA686A
config SENSORS_W83781D
tristate "Winbond W83781D, W83782D, W83783S, W83627HF, Asus AS99127F"
- depends on I2C && EXPERIMENTAL
+ depends on I2C
select I2C_SENSOR
help
If you say yes here you get support for the Winbond W8378x series
@@ -360,22 +387,47 @@ config SENSORS_W83627HF
This driver can also be built as a module. If so, the module
will be called w83627hf.
+config SENSORS_W83627EHF
+ tristate "Winbond W83627EHF"
+ depends on I2C && EXPERIMENTAL
+ select I2C_SENSOR
+ select I2C_ISA
+ help
+ If you say yes here you get preliminary support for the hardware
+ monitoring functionality of the Winbond W83627EHF Super-I/O chip.
+ Only fan and temperature inputs are supported at the moment, while
+ the chip does much more than that.
+
+ This driver can also be built as a module. If so, the module
+ will be called w83627ehf.
+
endmenu
menu "Other I2C Chip support"
depends on I2C
config SENSORS_DS1337
- tristate "Dallas Semiconductor DS1337 Real Time Clock"
+ tristate "Dallas Semiconductor DS1337 and DS1339 Real Time Clock"
depends on I2C && EXPERIMENTAL
select I2C_SENSOR
help
If you say yes here you get support for Dallas Semiconductor
- DS1337 real-time clock chips.
+ DS1337 and DS1339 real-time clock chips.
This driver can also be built as a module. If so, the module
will be called ds1337.
+config SENSORS_DS1374
+ tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock"
+ depends on I2C && EXPERIMENTAL
+ select I2C_SENSOR
+ help
+ If you say yes here you get support for Dallas Semiconductor
+ DS1374 real-time clock chips.
+
+ This driver can also be built as a module. If so, the module
+ will be called ds1374.
+
config SENSORS_EEPROM
tristate "EEPROM reader"
depends on I2C && EXPERIMENTAL
@@ -399,6 +451,16 @@ config SENSORS_PCF8574
This driver can also be built as a module. If so, the module
will be called pcf8574.
+config SENSORS_PCA9539
+ tristate "Philips PCA9539 16-bit I/O port"
+ depends on I2C && EXPERIMENTAL
+ help
+ If you say yes here you get support for the Philips PCA9539
+ 16-bit I/O port.
+
+ This driver can also be built as a module. If so, the module
+ will be called pca9539.
+
config SENSORS_PCF8591
tristate "Philips PCF8591"
depends on I2C && EXPERIMENTAL
@@ -431,6 +493,23 @@ config ISP1301_OMAP
This driver can also be built as a module. If so, the module
will be called isp1301_omap.
+# NOTE: This isn't really OMAP-specific, except for the current
+# interface location in <include/asm-arm/arch-omap/tps65010.h>
+# and having mostly OMAP-specific board support
+config TPS65010
+ tristate "TPS6501x Power Management chips"
+ depends on I2C && ARCH_OMAP
+ default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK
+ help
+ If you say yes here you get support for the TPS6501x series of
+ Power Management chips. These include voltage regulators,
+ lithium ion/polymer battery charging, and other features that
+ are often used in portable devices like cell phones and cameras.
+
+ This driver can also be built as a module. If so, the module
+ will be called tps65010.
+
+
config SENSORS_M41T00
tristate "ST M41T00 RTC chip"
depends on I2C && PPC32
@@ -440,4 +519,16 @@ config SENSORS_M41T00
This driver can also be built as a module. If so, the module
will be called m41t00.
+config SENSORS_MAX6875
+ tristate "MAXIM MAX6875 Power supply supervisor"
+ depends on I2C && EXPERIMENTAL
+ help
+ If you say yes here you get support for the MAX6875
+ EEPROM-Programmable, Hex/Quad, Power-Suppy Sequencers/Supervisors.
+
+ This provides a interface to program the EEPROM and reset the chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called max6875.
+
endmenu
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index 65599161a17..b5e6d2f84f9 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -1,5 +1,5 @@
#
-# Makefile for the kernel hardware sensors chip drivers.
+# Makefile for sensor and "other" I2C chip drivers.
#
# asb100, then w83781d go first, as they can override other drivers' addresses.
@@ -11,7 +11,10 @@ obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o
obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o
obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o
obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o
+obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o
+obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
obj-$(CONFIG_SENSORS_DS1337) += ds1337.o
+obj-$(CONFIG_SENSORS_DS1374) += ds1374.o
obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o
obj-$(CONFIG_SENSORS_FSCHER) += fscher.o
@@ -30,8 +33,10 @@ obj-$(CONFIG_SENSORS_LM87) += lm87.o
obj-$(CONFIG_SENSORS_LM90) += lm90.o
obj-$(CONFIG_SENSORS_LM92) += lm92.o
obj-$(CONFIG_SENSORS_MAX1619) += max1619.o
+obj-$(CONFIG_SENSORS_MAX6875) += max6875.o
obj-$(CONFIG_SENSORS_M41T00) += m41t00.o
obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
+obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o
obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
obj-$(CONFIG_SENSORS_RTC8564) += rtc8564.o
@@ -39,8 +44,11 @@ obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o
obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
obj-$(CONFIG_SENSORS_VIA686A) += via686a.o
+obj-$(CONFIG_SENSORS_W83627EHF) += w83627ehf.o
obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o
+
obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
+obj-$(CONFIG_TPS65010) += tps65010.o
ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
index 9c59a370b6d..d2c774c32f4 100644
--- a/drivers/i2c/chips/adm1021.c
+++ b/drivers/i2c/chips/adm1021.c
@@ -19,7 +19,6 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -103,8 +102,6 @@ struct adm1021_data {
u8 remote_temp_hyst;
u8 remote_temp_input;
u8 alarms;
- /* special values for ADM1021 only */
- u8 die_code;
/* Special values for ADM1023 only */
u8 remote_temp_prec;
u8 remote_temp_os_prec;
@@ -137,7 +134,7 @@ static struct i2c_driver adm1021_driver = {
};
#define show(value) \
-static ssize_t show_##value(struct device *dev, char *buf) \
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct adm1021_data *data = adm1021_update_device(dev); \
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->value)); \
@@ -150,16 +147,15 @@ show(remote_temp_hyst);
show(remote_temp_input);
#define show2(value) \
-static ssize_t show_##value(struct device *dev, char *buf) \
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct adm1021_data *data = adm1021_update_device(dev); \
return sprintf(buf, "%d\n", data->value); \
}
show2(alarms);
-show2(die_code);
#define set(value, reg) \
-static ssize_t set_##value(struct device *dev, const char *buf, size_t count) \
+static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct adm1021_data *data = i2c_get_clientdata(client); \
@@ -183,7 +179,6 @@ static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_remote_temp_max, set_remot
static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_remote_temp_hyst, set_remote_temp_hyst);
static DEVICE_ATTR(temp2_input, S_IRUGO, show_remote_temp_input, NULL);
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
-static DEVICE_ATTR(die_code, S_IRUGO, show_die_code, NULL);
static int adm1021_attach_adapter(struct i2c_adapter *adapter)
@@ -307,8 +302,6 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
device_create_file(&new_client->dev, &dev_attr_temp2_min);
device_create_file(&new_client->dev, &dev_attr_temp2_input);
device_create_file(&new_client->dev, &dev_attr_alarms);
- if (data->type == adm1021)
- device_create_file(&new_client->dev, &dev_attr_die_code);
return 0;
@@ -371,8 +364,6 @@ static struct adm1021_data *adm1021_update_device(struct device *dev)
data->remote_temp_max = adm1021_read_value(client, ADM1021_REG_REMOTE_TOS_R);
data->remote_temp_hyst = adm1021_read_value(client, ADM1021_REG_REMOTE_THYST_R);
data->alarms = adm1021_read_value(client, ADM1021_REG_STATUS) & 0x7c;
- if (data->type == adm1021)
- data->die_code = adm1021_read_value(client, ADM1021_REG_DIE_CODE);
if (data->type == adm1023) {
data->remote_temp_prec = adm1021_read_value(client, ADM1021_REG_REM_TEMP_PREC);
data->remote_temp_os_prec = adm1021_read_value(client, ADM1021_REG_REM_TOS_PREC);
diff --git a/drivers/i2c/chips/adm1025.c b/drivers/i2c/chips/adm1025.c
index e0771a3d05c..e452d0daf90 100644
--- a/drivers/i2c/chips/adm1025.c
+++ b/drivers/i2c/chips/adm1025.c
@@ -45,7 +45,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -153,19 +152,19 @@ struct adm1025_data {
*/
#define show_in(offset) \
-static ssize_t show_in##offset(struct device *dev, char *buf) \
+static ssize_t show_in##offset(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct adm1025_data *data = adm1025_update_device(dev); \
return sprintf(buf, "%u\n", IN_FROM_REG(data->in[offset], \
in_scale[offset])); \
} \
-static ssize_t show_in##offset##_min(struct device *dev, char *buf) \
+static ssize_t show_in##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct adm1025_data *data = adm1025_update_device(dev); \
return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[offset], \
in_scale[offset])); \
} \
-static ssize_t show_in##offset##_max(struct device *dev, char *buf) \
+static ssize_t show_in##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct adm1025_data *data = adm1025_update_device(dev); \
return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[offset], \
@@ -180,17 +179,17 @@ show_in(4);
show_in(5);
#define show_temp(offset) \
-static ssize_t show_temp##offset(struct device *dev, char *buf) \
+static ssize_t show_temp##offset(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct adm1025_data *data = adm1025_update_device(dev); \
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[offset-1])); \
} \
-static ssize_t show_temp##offset##_min(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct adm1025_data *data = adm1025_update_device(dev); \
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[offset-1])); \
} \
-static ssize_t show_temp##offset##_max(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct adm1025_data *data = adm1025_update_device(dev); \
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[offset-1])); \
@@ -200,7 +199,7 @@ show_temp(1);
show_temp(2);
#define set_in(offset) \
-static ssize_t set_in##offset##_min(struct device *dev, const char *buf, \
+static ssize_t set_in##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
@@ -214,7 +213,7 @@ static ssize_t set_in##offset##_min(struct device *dev, const char *buf, \
up(&data->update_lock); \
return count; \
} \
-static ssize_t set_in##offset##_max(struct device *dev, const char *buf, \
+static ssize_t set_in##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
@@ -240,7 +239,7 @@ set_in(4);
set_in(5);
#define set_temp(offset) \
-static ssize_t set_temp##offset##_min(struct device *dev, const char *buf, \
+static ssize_t set_temp##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
@@ -254,7 +253,7 @@ static ssize_t set_temp##offset##_min(struct device *dev, const char *buf, \
up(&data->update_lock); \
return count; \
} \
-static ssize_t set_temp##offset##_max(struct device *dev, const char *buf, \
+static ssize_t set_temp##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
@@ -275,26 +274,28 @@ static DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \
set_temp(1);
set_temp(2);
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
{
struct adm1025_data *data = adm1025_update_device(dev);
return sprintf(buf, "%u\n", data->alarms);
}
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
-static ssize_t show_vid(struct device *dev, char *buf)
+static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
{
struct adm1025_data *data = adm1025_update_device(dev);
return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm));
}
+/* in1_ref is deprecated in favour of cpu0_vid, remove after 2005-11-11 */
static DEVICE_ATTR(in1_ref, S_IRUGO, show_vid, NULL);
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
-static ssize_t show_vrm(struct device *dev, char *buf)
+static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
{
struct adm1025_data *data = adm1025_update_device(dev);
return sprintf(buf, "%u\n", data->vrm);
}
-static ssize_t set_vrm(struct device *dev, const char *buf, size_t count)
+static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct adm1025_data *data = i2c_get_clientdata(client);
@@ -437,7 +438,9 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
device_create_file(&new_client->dev, &dev_attr_temp1_max);
device_create_file(&new_client->dev, &dev_attr_temp2_max);
device_create_file(&new_client->dev, &dev_attr_alarms);
+ /* in1_ref is deprecated, remove after 2005-11-11 */
device_create_file(&new_client->dev, &dev_attr_in1_ref);
+ device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
device_create_file(&new_client->dev, &dev_attr_vrm);
/* Pin 11 is either in4 (+12V) or VID4 */
diff --git a/drivers/i2c/chips/adm1026.c b/drivers/i2c/chips/adm1026.c
index 39e2f4a900b..3c85fe150cd 100644
--- a/drivers/i2c/chips/adm1026.c
+++ b/drivers/i2c/chips/adm1026.c
@@ -23,7 +23,6 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -31,6 +30,7 @@
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
#include <linux/i2c-vid.h>
+#include <linux/hwmon-sysfs.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
@@ -711,19 +711,27 @@ static struct adm1026_data *adm1026_update_device(struct device *dev)
return data;
}
-static ssize_t show_in(struct device *dev, char *buf, int nr)
+static ssize_t show_in(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in[nr]));
}
-static ssize_t show_in_min(struct device *dev, char *buf, int nr)
+static ssize_t show_in_min(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_min[nr]));
}
-static ssize_t set_in_min(struct device *dev, const char *buf,
- size_t count, int nr)
+static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
@@ -734,14 +742,19 @@ static ssize_t set_in_min(struct device *dev, const char *buf,
up(&data->update_lock);
return count;
}
-static ssize_t show_in_max(struct device *dev, char *buf, int nr)
+static ssize_t show_in_max(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_max[nr]));
}
-static ssize_t set_in_max(struct device *dev, const char *buf,
- size_t count, int nr)
+static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
@@ -753,34 +766,13 @@ static ssize_t set_in_max(struct device *dev, const char *buf,
return count;
}
-#define in_reg(offset) \
-static ssize_t show_in##offset (struct device *dev, char *buf) \
-{ \
- return show_in(dev, buf, offset); \
-} \
-static ssize_t show_in##offset##_min (struct device *dev, char *buf) \
-{ \
- return show_in_min(dev, buf, offset); \
-} \
-static ssize_t set_in##offset##_min (struct device *dev, \
- const char *buf, size_t count) \
-{ \
- return set_in_min(dev, buf, count, offset); \
-} \
-static ssize_t show_in##offset##_max (struct device *dev, char *buf) \
-{ \
- return show_in_max(dev, buf, offset); \
-} \
-static ssize_t set_in##offset##_max (struct device *dev, \
- const char *buf, size_t count) \
-{ \
- return set_in_max(dev, buf, count, offset); \
-} \
-static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL); \
-static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
- show_in##offset##_min, set_in##offset##_min); \
-static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
- show_in##offset##_max, set_in##offset##_max);
+#define in_reg(offset) \
+static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in, \
+ NULL, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
+ show_in_min, set_in_min, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
+ show_in_max, set_in_max, offset);
in_reg(0);
@@ -800,19 +792,19 @@ in_reg(13);
in_reg(14);
in_reg(15);
-static ssize_t show_in16(struct device *dev, char *buf)
+static ssize_t show_in16(struct device *dev, struct device_attribute *attr, char *buf)
{
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", INS_FROM_REG(16, data->in[16]) -
NEG12_OFFSET);
}
-static ssize_t show_in16_min(struct device *dev, char *buf)
+static ssize_t show_in16_min(struct device *dev, struct device_attribute *attr, char *buf)
{
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", INS_FROM_REG(16, data->in_min[16])
- NEG12_OFFSET);
}
-static ssize_t set_in16_min(struct device *dev, const char *buf, size_t count)
+static ssize_t set_in16_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
@@ -824,13 +816,13 @@ static ssize_t set_in16_min(struct device *dev, const char *buf, size_t count)
up(&data->update_lock);
return count;
}
-static ssize_t show_in16_max(struct device *dev, char *buf)
+static ssize_t show_in16_max(struct device *dev, struct device_attribute *attr, char *buf)
{
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", INS_FROM_REG(16, data->in_max[16])
- NEG12_OFFSET);
}
-static ssize_t set_in16_max(struct device *dev, const char *buf, size_t count)
+static ssize_t set_in16_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
@@ -843,30 +835,38 @@ static ssize_t set_in16_max(struct device *dev, const char *buf, size_t count)
return count;
}
-static DEVICE_ATTR(in16_input, S_IRUGO, show_in16, NULL);
-static DEVICE_ATTR(in16_min, S_IRUGO | S_IWUSR, show_in16_min, set_in16_min);
-static DEVICE_ATTR(in16_max, S_IRUGO | S_IWUSR, show_in16_max, set_in16_max);
+static SENSOR_DEVICE_ATTR(in16_input, S_IRUGO, show_in16, NULL, 16);
+static SENSOR_DEVICE_ATTR(in16_min, S_IRUGO | S_IWUSR, show_in16_min, set_in16_min, 16);
+static SENSOR_DEVICE_ATTR(in16_max, S_IRUGO | S_IWUSR, show_in16_max, set_in16_max, 16);
/* Now add fan read/write functions */
-static ssize_t show_fan(struct device *dev, char *buf, int nr)
+static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr],
data->fan_div[nr]));
}
-static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
+static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr],
data->fan_div[nr]));
}
-static ssize_t set_fan_min(struct device *dev, const char *buf,
- size_t count, int nr)
+static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
@@ -879,23 +879,11 @@ static ssize_t set_fan_min(struct device *dev, const char *buf,
return count;
}
-#define fan_offset(offset) \
-static ssize_t show_fan_##offset (struct device *dev, char *buf) \
-{ \
- return show_fan(dev, buf, offset - 1); \
-} \
-static ssize_t show_fan_##offset##_min (struct device *dev, char *buf) \
-{ \
- return show_fan_min(dev, buf, offset - 1); \
-} \
-static ssize_t set_fan_##offset##_min (struct device *dev, \
- const char *buf, size_t count) \
-{ \
- return set_fan_min(dev, buf, count, offset - 1); \
-} \
-static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL); \
-static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
- show_fan_##offset##_min, set_fan_##offset##_min);
+#define fan_offset(offset) \
+static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan, NULL, \
+ offset - 1); \
+static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
+ show_fan_min, set_fan_min, offset - 1);
fan_offset(1);
fan_offset(2);
@@ -926,14 +914,19 @@ static void fixup_fan_min(struct device *dev, int fan, int old_div)
}
/* Now add fan_div read/write functions */
-static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
+static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", data->fan_div[nr]);
}
-static ssize_t set_fan_div(struct device *dev, const char *buf,
- size_t count, int nr)
+static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val,orig_div,new_div,shift;
@@ -967,17 +960,8 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
}
#define fan_offset_div(offset) \
-static ssize_t show_fan_##offset##_div (struct device *dev, char *buf) \
-{ \
- return show_fan_div(dev, buf, offset - 1); \
-} \
-static ssize_t set_fan_##offset##_div (struct device *dev, \
- const char *buf, size_t count) \
-{ \
- return set_fan_div(dev, buf, count, offset - 1); \
-} \
-static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
- show_fan_##offset##_div, set_fan_##offset##_div);
+static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
+ show_fan_div, set_fan_div, offset - 1);
fan_offset_div(1);
fan_offset_div(2);
@@ -989,19 +973,27 @@ fan_offset_div(7);
fan_offset_div(8);
/* Temps */
-static ssize_t show_temp(struct device *dev, char *buf, int nr)
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp[nr]));
}
-static ssize_t show_temp_min(struct device *dev, char *buf, int nr)
+static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_min[nr]));
}
-static ssize_t set_temp_min(struct device *dev, const char *buf,
- size_t count, int nr)
+static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
@@ -1013,14 +1005,19 @@ static ssize_t set_temp_min(struct device *dev, const char *buf,
up(&data->update_lock);
return count;
}
-static ssize_t show_temp_max(struct device *dev, char *buf, int nr)
+static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_max[nr]));
}
-static ssize_t set_temp_max(struct device *dev, const char *buf,
- size_t count, int nr)
+static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
@@ -1032,48 +1029,34 @@ static ssize_t set_temp_max(struct device *dev, const char *buf,
up(&data->update_lock);
return count;
}
-#define temp_reg(offset) \
-static ssize_t show_temp_##offset (struct device *dev, char *buf) \
-{ \
- return show_temp(dev, buf, offset - 1); \
-} \
-static ssize_t show_temp_##offset##_min (struct device *dev, char *buf) \
-{ \
- return show_temp_min(dev, buf, offset - 1); \
-} \
-static ssize_t show_temp_##offset##_max (struct device *dev, char *buf) \
-{ \
- return show_temp_max(dev, buf, offset - 1); \
-} \
-static ssize_t set_temp_##offset##_min (struct device *dev, \
- const char *buf, size_t count) \
-{ \
- return set_temp_min(dev, buf, count, offset - 1); \
-} \
-static ssize_t set_temp_##offset##_max (struct device *dev, \
- const char *buf, size_t count) \
-{ \
- return set_temp_max(dev, buf, count, offset - 1); \
-} \
-static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL); \
-static DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \
- show_temp_##offset##_min, set_temp_##offset##_min); \
-static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \
- show_temp_##offset##_max, set_temp_##offset##_max);
+
+#define temp_reg(offset) \
+static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp, \
+ NULL, offset - 1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \
+ show_temp_min, set_temp_min, offset - 1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \
+ show_temp_max, set_temp_max, offset - 1);
temp_reg(1);
temp_reg(2);
temp_reg(3);
-static ssize_t show_temp_offset(struct device *dev, char *buf, int nr)
+static ssize_t show_temp_offset(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_offset[nr]));
}
-static ssize_t set_temp_offset(struct device *dev, const char *buf,
- size_t count, int nr)
+static ssize_t set_temp_offset(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
@@ -1086,46 +1069,45 @@ static ssize_t set_temp_offset(struct device *dev, const char *buf,
return count;
}
-#define temp_offset_reg(offset) \
-static ssize_t show_temp_##offset##_offset (struct device *dev, char *buf) \
-{ \
- return show_temp_offset(dev, buf, offset - 1); \
-} \
-static ssize_t set_temp_##offset##_offset (struct device *dev, \
- const char *buf, size_t count) \
-{ \
- return set_temp_offset(dev, buf, count, offset - 1); \
-} \
-static DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR, \
- show_temp_##offset##_offset, set_temp_##offset##_offset);
+#define temp_offset_reg(offset) \
+static SENSOR_DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR, \
+ show_temp_offset, set_temp_offset, offset - 1);
temp_offset_reg(1);
temp_offset_reg(2);
temp_offset_reg(3);
-static ssize_t show_temp_auto_point1_temp_hyst(struct device *dev, char *buf,
- int nr)
+static ssize_t show_temp_auto_point1_temp_hyst(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", TEMP_FROM_REG(
ADM1026_FAN_ACTIVATION_TEMP_HYST + data->temp_tmin[nr]));
}
-static ssize_t show_temp_auto_point2_temp(struct device *dev, char *buf,
- int nr)
+static ssize_t show_temp_auto_point2_temp(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_tmin[nr] +
ADM1026_FAN_CONTROL_TEMP_RANGE));
}
-static ssize_t show_temp_auto_point1_temp(struct device *dev, char *buf,
- int nr)
+static ssize_t show_temp_auto_point1_temp(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_tmin[nr]));
}
-static ssize_t set_temp_auto_point1_temp(struct device *dev, const char *buf,
- size_t count, int nr)
+static ssize_t set_temp_auto_point1_temp(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
@@ -1138,46 +1120,27 @@ static ssize_t set_temp_auto_point1_temp(struct device *dev, const char *buf,
return count;
}
-#define temp_auto_point(offset) \
-static ssize_t show_temp##offset##_auto_point1_temp (struct device *dev, \
- char *buf) \
-{ \
- return show_temp_auto_point1_temp(dev, buf, offset - 1); \
-} \
-static ssize_t set_temp##offset##_auto_point1_temp (struct device *dev, \
- const char *buf, size_t count) \
-{ \
- return set_temp_auto_point1_temp(dev, buf, count, offset - 1); \
-} \
-static ssize_t show_temp##offset##_auto_point1_temp_hyst (struct device \
- *dev, char *buf) \
-{ \
- return show_temp_auto_point1_temp_hyst(dev, buf, offset - 1); \
-} \
-static ssize_t show_temp##offset##_auto_point2_temp (struct device *dev, \
- char *buf) \
-{ \
- return show_temp_auto_point2_temp(dev, buf, offset - 1); \
-} \
-static DEVICE_ATTR(temp##offset##_auto_point1_temp, S_IRUGO | S_IWUSR, \
- show_temp##offset##_auto_point1_temp, \
- set_temp##offset##_auto_point1_temp); \
-static DEVICE_ATTR(temp##offset##_auto_point1_temp_hyst, S_IRUGO, \
- show_temp##offset##_auto_point1_temp_hyst, NULL); \
-static DEVICE_ATTR(temp##offset##_auto_point2_temp, S_IRUGO, \
- show_temp##offset##_auto_point2_temp, NULL);
+#define temp_auto_point(offset) \
+static SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp, S_IRUGO | S_IWUSR, \
+ show_temp_auto_point1_temp, set_temp_auto_point1_temp, \
+ offset - 1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp_hyst, S_IRUGO, \
+ show_temp_auto_point1_temp_hyst, NULL, offset - 1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_auto_point2_temp, S_IRUGO, \
+ show_temp_auto_point2_temp, NULL, offset - 1);
temp_auto_point(1);
temp_auto_point(2);
temp_auto_point(3);
-static ssize_t show_temp_crit_enable(struct device *dev, char *buf)
+static ssize_t show_temp_crit_enable(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", (data->config1 & CFG1_THERM_HOT) >> 4);
}
-static ssize_t set_temp_crit_enable(struct device *dev, const char *buf,
- size_t count)
+static ssize_t set_temp_crit_enable(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
@@ -1193,24 +1156,27 @@ static ssize_t set_temp_crit_enable(struct device *dev, const char *buf,
return count;
}
-static DEVICE_ATTR(temp1_crit_enable, S_IRUGO | S_IWUSR,
- show_temp_crit_enable, set_temp_crit_enable);
-
-static DEVICE_ATTR(temp2_crit_enable, S_IRUGO | S_IWUSR,
- show_temp_crit_enable, set_temp_crit_enable);
-
-static DEVICE_ATTR(temp3_crit_enable, S_IRUGO | S_IWUSR,
+#define temp_crit_enable(offset) \
+static DEVICE_ATTR(temp##offset##_crit_enable, S_IRUGO | S_IWUSR, \
show_temp_crit_enable, set_temp_crit_enable);
+temp_crit_enable(1);
+temp_crit_enable(2);
+temp_crit_enable(3);
-static ssize_t show_temp_crit(struct device *dev, char *buf, int nr)
+static ssize_t show_temp_crit(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_crit[nr]));
}
-static ssize_t set_temp_crit(struct device *dev, const char *buf,
- size_t count, int nr)
+static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
@@ -1223,29 +1189,20 @@ static ssize_t set_temp_crit(struct device *dev, const char *buf,
return count;
}
-#define temp_crit_reg(offset) \
-static ssize_t show_temp_##offset##_crit (struct device *dev, char *buf) \
-{ \
- return show_temp_crit(dev, buf, offset - 1); \
-} \
-static ssize_t set_temp_##offset##_crit (struct device *dev, \
- const char *buf, size_t count) \
-{ \
- return set_temp_crit(dev, buf, count, offset - 1); \
-} \
-static DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR, \
- show_temp_##offset##_crit, set_temp_##offset##_crit);
+#define temp_crit_reg(offset) \
+static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR, \
+ show_temp_crit, set_temp_crit, offset - 1);
temp_crit_reg(1);
temp_crit_reg(2);
temp_crit_reg(3);
-static ssize_t show_analog_out_reg(struct device *dev, char *buf)
+static ssize_t show_analog_out_reg(struct device *dev, struct device_attribute *attr, char *buf)
{
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", DAC_FROM_REG(data->analog_out));
}
-static ssize_t set_analog_out_reg(struct device *dev, const char *buf,
+static ssize_t set_analog_out_reg(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -1262,20 +1219,21 @@ static ssize_t set_analog_out_reg(struct device *dev, const char *buf,
static DEVICE_ATTR(analog_out, S_IRUGO | S_IWUSR, show_analog_out_reg,
set_analog_out_reg);
-static ssize_t show_vid_reg(struct device *dev, char *buf)
+static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
{
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", vid_from_reg(data->vid & 0x3f, data->vrm));
}
-
+/* vid deprecated in favour of cpu0_vid, remove after 2005-11-11 */
static DEVICE_ATTR(vid, S_IRUGO, show_vid_reg, NULL);
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
-static ssize_t show_vrm_reg(struct device *dev, char *buf)
+static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
{
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", data->vrm);
}
-static ssize_t store_vrm_reg(struct device *dev, const char *buf,
+static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -1287,7 +1245,7 @@ static ssize_t store_vrm_reg(struct device *dev, const char *buf,
static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
-static ssize_t show_alarms_reg(struct device *dev, char *buf)
+static ssize_t show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
{
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf, "%ld\n", (long) (data->alarms));
@@ -1295,12 +1253,12 @@ static ssize_t show_alarms_reg(struct device *dev, char *buf)
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
-static ssize_t show_alarm_mask(struct device *dev, char *buf)
+static ssize_t show_alarm_mask(struct device *dev, struct device_attribute *attr, char *buf)
{
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%ld\n", data->alarm_mask);
}
-static ssize_t set_alarm_mask(struct device *dev, const char *buf,
+static ssize_t set_alarm_mask(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -1331,12 +1289,12 @@ static DEVICE_ATTR(alarm_mask, S_IRUGO | S_IWUSR, show_alarm_mask,
set_alarm_mask);
-static ssize_t show_gpio(struct device *dev, char *buf)
+static ssize_t show_gpio(struct device *dev, struct device_attribute *attr, char *buf)
{
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%ld\n", data->gpio);
}
-static ssize_t set_gpio(struct device *dev, const char *buf,
+static ssize_t set_gpio(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -1359,12 +1317,12 @@ static ssize_t set_gpio(struct device *dev, const char *buf,
static DEVICE_ATTR(gpio, S_IRUGO | S_IWUSR, show_gpio, set_gpio);
-static ssize_t show_gpio_mask(struct device *dev, char *buf)
+static ssize_t show_gpio_mask(struct device *dev, struct device_attribute *attr, char *buf)
{
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%ld\n", data->gpio_mask);
}
-static ssize_t set_gpio_mask(struct device *dev, const char *buf,
+static ssize_t set_gpio_mask(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -1386,12 +1344,12 @@ static ssize_t set_gpio_mask(struct device *dev, const char *buf,
static DEVICE_ATTR(gpio_mask, S_IRUGO | S_IWUSR, show_gpio_mask, set_gpio_mask);
-static ssize_t show_pwm_reg(struct device *dev, char *buf)
+static ssize_t show_pwm_reg(struct device *dev, struct device_attribute *attr, char *buf)
{
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", PWM_FROM_REG(data->pwm1.pwm));
}
-static ssize_t set_pwm_reg(struct device *dev, const char *buf,
+static ssize_t set_pwm_reg(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -1407,12 +1365,12 @@ static ssize_t set_pwm_reg(struct device *dev, const char *buf,
}
return count;
}
-static ssize_t show_auto_pwm_min(struct device *dev, char *buf)
+static ssize_t show_auto_pwm_min(struct device *dev, struct device_attribute *attr, char *buf)
{
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", data->pwm1.auto_pwm_min);
}
-static ssize_t set_auto_pwm_min(struct device *dev, const char *buf,
+static ssize_t set_auto_pwm_min(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -1429,16 +1387,16 @@ static ssize_t set_auto_pwm_min(struct device *dev, const char *buf,
up(&data->update_lock);
return count;
}
-static ssize_t show_auto_pwm_max(struct device *dev, char *buf)
+static ssize_t show_auto_pwm_max(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf,"%d\n", ADM1026_PWM_MAX);
}
-static ssize_t show_pwm_enable(struct device *dev, char *buf)
+static ssize_t show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf)
{
struct adm1026_data *data = adm1026_update_device(dev);
return sprintf(buf,"%d\n", data->pwm1.enable);
}
-static ssize_t set_pwm_enable(struct device *dev, const char *buf,
+static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -1597,118 +1555,120 @@ int adm1026_detect(struct i2c_adapter *adapter, int address,
adm1026_init_client(new_client);
/* Register sysfs hooks */
- device_create_file(&new_client->dev, &dev_attr_in0_input);
- device_create_file(&new_client->dev, &dev_attr_in0_max);
- device_create_file(&new_client->dev, &dev_attr_in0_min);
- device_create_file(&new_client->dev, &dev_attr_in1_input);
- device_create_file(&new_client->dev, &dev_attr_in1_max);
- device_create_file(&new_client->dev, &dev_attr_in1_min);
- device_create_file(&new_client->dev, &dev_attr_in2_input);
- device_create_file(&new_client->dev, &dev_attr_in2_max);
- device_create_file(&new_client->dev, &dev_attr_in2_min);
- device_create_file(&new_client->dev, &dev_attr_in3_input);
- device_create_file(&new_client->dev, &dev_attr_in3_max);
- device_create_file(&new_client->dev, &dev_attr_in3_min);
- device_create_file(&new_client->dev, &dev_attr_in4_input);
- device_create_file(&new_client->dev, &dev_attr_in4_max);
- device_create_file(&new_client->dev, &dev_attr_in4_min);
- device_create_file(&new_client->dev, &dev_attr_in5_input);
- device_create_file(&new_client->dev, &dev_attr_in5_max);
- device_create_file(&new_client->dev, &dev_attr_in5_min);
- device_create_file(&new_client->dev, &dev_attr_in6_input);
- device_create_file(&new_client->dev, &dev_attr_in6_max);
- device_create_file(&new_client->dev, &dev_attr_in6_min);
- device_create_file(&new_client->dev, &dev_attr_in7_input);
- device_create_file(&new_client->dev, &dev_attr_in7_max);
- device_create_file(&new_client->dev, &dev_attr_in7_min);
- device_create_file(&new_client->dev, &dev_attr_in8_input);
- device_create_file(&new_client->dev, &dev_attr_in8_max);
- device_create_file(&new_client->dev, &dev_attr_in8_min);
- device_create_file(&new_client->dev, &dev_attr_in9_input);
- device_create_file(&new_client->dev, &dev_attr_in9_max);
- device_create_file(&new_client->dev, &dev_attr_in9_min);
- device_create_file(&new_client->dev, &dev_attr_in10_input);
- device_create_file(&new_client->dev, &dev_attr_in10_max);
- device_create_file(&new_client->dev, &dev_attr_in10_min);
- device_create_file(&new_client->dev, &dev_attr_in11_input);
- device_create_file(&new_client->dev, &dev_attr_in11_max);
- device_create_file(&new_client->dev, &dev_attr_in11_min);
- device_create_file(&new_client->dev, &dev_attr_in12_input);
- device_create_file(&new_client->dev, &dev_attr_in12_max);
- device_create_file(&new_client->dev, &dev_attr_in12_min);
- device_create_file(&new_client->dev, &dev_attr_in13_input);
- device_create_file(&new_client->dev, &dev_attr_in13_max);
- device_create_file(&new_client->dev, &dev_attr_in13_min);
- device_create_file(&new_client->dev, &dev_attr_in14_input);
- device_create_file(&new_client->dev, &dev_attr_in14_max);
- device_create_file(&new_client->dev, &dev_attr_in14_min);
- device_create_file(&new_client->dev, &dev_attr_in15_input);
- device_create_file(&new_client->dev, &dev_attr_in15_max);
- device_create_file(&new_client->dev, &dev_attr_in15_min);
- device_create_file(&new_client->dev, &dev_attr_in16_input);
- device_create_file(&new_client->dev, &dev_attr_in16_max);
- device_create_file(&new_client->dev, &dev_attr_in16_min);
- device_create_file(&new_client->dev, &dev_attr_fan1_input);
- device_create_file(&new_client->dev, &dev_attr_fan1_div);
- device_create_file(&new_client->dev, &dev_attr_fan1_min);
- device_create_file(&new_client->dev, &dev_attr_fan2_input);
- device_create_file(&new_client->dev, &dev_attr_fan2_div);
- device_create_file(&new_client->dev, &dev_attr_fan2_min);
- device_create_file(&new_client->dev, &dev_attr_fan3_input);
- device_create_file(&new_client->dev, &dev_attr_fan3_div);
- device_create_file(&new_client->dev, &dev_attr_fan3_min);
- device_create_file(&new_client->dev, &dev_attr_fan4_input);
- device_create_file(&new_client->dev, &dev_attr_fan4_div);
- device_create_file(&new_client->dev, &dev_attr_fan4_min);
- device_create_file(&new_client->dev, &dev_attr_fan5_input);
- device_create_file(&new_client->dev, &dev_attr_fan5_div);
- device_create_file(&new_client->dev, &dev_attr_fan5_min);
- device_create_file(&new_client->dev, &dev_attr_fan6_input);
- device_create_file(&new_client->dev, &dev_attr_fan6_div);
- device_create_file(&new_client->dev, &dev_attr_fan6_min);
- device_create_file(&new_client->dev, &dev_attr_fan7_input);
- device_create_file(&new_client->dev, &dev_attr_fan7_div);
- device_create_file(&new_client->dev, &dev_attr_fan7_min);
- device_create_file(&new_client->dev, &dev_attr_fan8_input);
- device_create_file(&new_client->dev, &dev_attr_fan8_div);
- device_create_file(&new_client->dev, &dev_attr_fan8_min);
- device_create_file(&new_client->dev, &dev_attr_temp1_input);
- device_create_file(&new_client->dev, &dev_attr_temp1_max);
- device_create_file(&new_client->dev, &dev_attr_temp1_min);
- device_create_file(&new_client->dev, &dev_attr_temp2_input);
- device_create_file(&new_client->dev, &dev_attr_temp2_max);
- device_create_file(&new_client->dev, &dev_attr_temp2_min);
- device_create_file(&new_client->dev, &dev_attr_temp3_input);
- device_create_file(&new_client->dev, &dev_attr_temp3_max);
- device_create_file(&new_client->dev, &dev_attr_temp3_min);
- device_create_file(&new_client->dev, &dev_attr_temp1_offset);
- device_create_file(&new_client->dev, &dev_attr_temp2_offset);
- device_create_file(&new_client->dev, &dev_attr_temp3_offset);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in1_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in1_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in2_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in2_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in3_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in3_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in3_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in4_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in4_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in4_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in5_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in5_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in5_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in6_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in6_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in6_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in7_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in7_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in7_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in8_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in8_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in8_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in9_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in9_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in9_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in10_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in10_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in10_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in11_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in11_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in11_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in12_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in12_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in12_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in13_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in13_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in13_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in14_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in14_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in14_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in15_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in15_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in15_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in16_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in16_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in16_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan1_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan1_div.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan1_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan2_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan2_div.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan2_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan3_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan3_div.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan3_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan4_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan4_div.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan4_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan5_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan5_div.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan5_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan6_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan6_div.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan6_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan7_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan7_div.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan7_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan8_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan8_div.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan8_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp1_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp1_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp1_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp2_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp2_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp2_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp3_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp3_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp3_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp1_offset.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp2_offset.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp3_offset.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_temp1_auto_point1_temp);
+ &sensor_dev_attr_temp1_auto_point1_temp.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_temp2_auto_point1_temp);
+ &sensor_dev_attr_temp2_auto_point1_temp.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_temp3_auto_point1_temp);
+ &sensor_dev_attr_temp3_auto_point1_temp.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_temp1_auto_point1_temp_hyst);
+ &sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_temp2_auto_point1_temp_hyst);
+ &sensor_dev_attr_temp2_auto_point1_temp_hyst.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_temp3_auto_point1_temp_hyst);
+ &sensor_dev_attr_temp3_auto_point1_temp_hyst.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_temp1_auto_point2_temp);
+ &sensor_dev_attr_temp1_auto_point2_temp.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_temp2_auto_point2_temp);
+ &sensor_dev_attr_temp2_auto_point2_temp.dev_attr);
device_create_file(&new_client->dev,
- &dev_attr_temp3_auto_point2_temp);
- device_create_file(&new_client->dev, &dev_attr_temp1_crit);
- device_create_file(&new_client->dev, &dev_attr_temp2_crit);
- device_create_file(&new_client->dev, &dev_attr_temp3_crit);
+ &sensor_dev_attr_temp3_auto_point2_temp.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp1_crit.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp2_crit.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp3_crit.dev_attr);
device_create_file(&new_client->dev, &dev_attr_temp1_crit_enable);
device_create_file(&new_client->dev, &dev_attr_temp2_crit_enable);
device_create_file(&new_client->dev, &dev_attr_temp3_crit_enable);
+ /* vid deprecated in favour of cpu0_vid, remove after 2005-11-11 */
device_create_file(&new_client->dev, &dev_attr_vid);
+ device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
device_create_file(&new_client->dev, &dev_attr_vrm);
device_create_file(&new_client->dev, &dev_attr_alarms);
device_create_file(&new_client->dev, &dev_attr_alarm_mask);
diff --git a/drivers/i2c/chips/adm1031.c b/drivers/i2c/chips/adm1031.c
index d4385a23f79..9168e983ca1 100644
--- a/drivers/i2c/chips/adm1031.c
+++ b/drivers/i2c/chips/adm1031.c
@@ -292,11 +292,11 @@ set_fan_auto_channel(struct device *dev, const char *buf, size_t count, int nr)
}
#define fan_auto_channel_offset(offset) \
-static ssize_t show_fan_auto_channel_##offset (struct device *dev, char *buf) \
+static ssize_t show_fan_auto_channel_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_fan_auto_channel(dev, buf, offset - 1); \
} \
-static ssize_t set_fan_auto_channel_##offset (struct device *dev, \
+static ssize_t set_fan_auto_channel_##offset (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_fan_auto_channel(dev, buf, count, offset - 1); \
@@ -357,24 +357,24 @@ set_auto_temp_max(struct device *dev, const char *buf, size_t count, int nr)
}
#define auto_temp_reg(offset) \
-static ssize_t show_auto_temp_##offset##_off (struct device *dev, char *buf) \
+static ssize_t show_auto_temp_##offset##_off (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_auto_temp_off(dev, buf, offset - 1); \
} \
-static ssize_t show_auto_temp_##offset##_min (struct device *dev, char *buf) \
+static ssize_t show_auto_temp_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_auto_temp_min(dev, buf, offset - 1); \
} \
-static ssize_t show_auto_temp_##offset##_max (struct device *dev, char *buf) \
+static ssize_t show_auto_temp_##offset##_max (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_auto_temp_max(dev, buf, offset - 1); \
} \
-static ssize_t set_auto_temp_##offset##_min (struct device *dev, \
+static ssize_t set_auto_temp_##offset##_min (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_auto_temp_min(dev, buf, count, offset - 1); \
} \
-static ssize_t set_auto_temp_##offset##_max (struct device *dev, \
+static ssize_t set_auto_temp_##offset##_max (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_auto_temp_max(dev, buf, count, offset - 1); \
@@ -421,11 +421,11 @@ set_pwm(struct device *dev, const char *buf, size_t count, int nr)
}
#define pwm_reg(offset) \
-static ssize_t show_pwm_##offset (struct device *dev, char *buf) \
+static ssize_t show_pwm_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_pwm(dev, buf, offset - 1); \
} \
-static ssize_t set_pwm_##offset (struct device *dev, \
+static ssize_t set_pwm_##offset (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_pwm(dev, buf, count, offset - 1); \
@@ -440,7 +440,7 @@ pwm_reg(2);
/*
* That function checks the cases where the fan reading is not
- * relevent. It is used to provide 0 as fan reading when the fan is
+ * relevant. It is used to provide 0 as fan reading when the fan is
* not supposed to run
*/
static int trust_fan_readings(struct adm1031_data *data, int chan)
@@ -557,24 +557,24 @@ set_fan_div(struct device *dev, const char *buf, size_t count, int nr)
}
#define fan_offset(offset) \
-static ssize_t show_fan_##offset (struct device *dev, char *buf) \
+static ssize_t show_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_fan(dev, buf, offset - 1); \
} \
-static ssize_t show_fan_##offset##_min (struct device *dev, char *buf) \
+static ssize_t show_fan_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_fan_min(dev, buf, offset - 1); \
} \
-static ssize_t show_fan_##offset##_div (struct device *dev, char *buf) \
+static ssize_t show_fan_##offset##_div (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_fan_div(dev, buf, offset - 1); \
} \
-static ssize_t set_fan_##offset##_min (struct device *dev, \
+static ssize_t set_fan_##offset##_min (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_fan_min(dev, buf, count, offset - 1); \
} \
-static ssize_t set_fan_##offset##_div (struct device *dev, \
+static ssize_t set_fan_##offset##_div (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_fan_div(dev, buf, count, offset - 1); \
@@ -667,33 +667,33 @@ set_temp_crit(struct device *dev, const char *buf, size_t count, int nr)
}
#define temp_reg(offset) \
-static ssize_t show_temp_##offset (struct device *dev, char *buf) \
+static ssize_t show_temp_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_temp(dev, buf, offset - 1); \
} \
-static ssize_t show_temp_##offset##_min (struct device *dev, char *buf) \
+static ssize_t show_temp_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_temp_min(dev, buf, offset - 1); \
} \
-static ssize_t show_temp_##offset##_max (struct device *dev, char *buf) \
+static ssize_t show_temp_##offset##_max (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_temp_max(dev, buf, offset - 1); \
} \
-static ssize_t show_temp_##offset##_crit (struct device *dev, char *buf) \
+static ssize_t show_temp_##offset##_crit (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_temp_crit(dev, buf, offset - 1); \
} \
-static ssize_t set_temp_##offset##_min (struct device *dev, \
+static ssize_t set_temp_##offset##_min (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_temp_min(dev, buf, count, offset - 1); \
} \
-static ssize_t set_temp_##offset##_max (struct device *dev, \
+static ssize_t set_temp_##offset##_max (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_temp_max(dev, buf, count, offset - 1); \
} \
-static ssize_t set_temp_##offset##_crit (struct device *dev, \
+static ssize_t set_temp_##offset##_crit (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_temp_crit(dev, buf, count, offset - 1); \
@@ -712,7 +712,7 @@ temp_reg(2);
temp_reg(3);
/* Alarms */
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
{
struct adm1031_data *data = adm1031_update_device(dev);
return sprintf(buf, "%d\n", data->alarm);
diff --git a/drivers/i2c/chips/adm9240.c b/drivers/i2c/chips/adm9240.c
new file mode 100644
index 00000000000..5c68e9c311a
--- /dev/null
+++ b/drivers/i2c/chips/adm9240.c
@@ -0,0 +1,791 @@
+/*
+ * adm9240.c Part of lm_sensors, Linux kernel modules for hardware
+ * monitoring
+ *
+ * Copyright (C) 1999 Frodo Looijaard <frodol@dds.nl>
+ * Philip Edelbrock <phil@netroedge.com>
+ * Copyright (C) 2003 Michiel Rook <michiel@grendelproject.nl>
+ * Copyright (C) 2005 Grant Coady <gcoady@gmail.com> with valuable
+ * guidance from Jean Delvare
+ *
+ * Driver supports Analog Devices ADM9240
+ * Dallas Semiconductor DS1780
+ * National Semiconductor LM81
+ *
+ * ADM9240 is the reference, DS1780 and LM81 are register compatibles
+ *
+ * Voltage Six inputs are scaled by chip, VID also reported
+ * Temperature Chip temperature to 0.5'C, maximum and max_hysteris
+ * Fans 2 fans, low speed alarm, automatic fan clock divider
+ * Alarms 16-bit map of active alarms
+ * Analog Out 0..1250 mV output
+ *
+ * Chassis Intrusion: clear CI latch with 'echo 1 > chassis_clear'
+ *
+ * Test hardware: Intel SE440BX-2 desktop motherboard --Grant
+ *
+ * LM81 extended temp reading not implemented
+ *
+ * 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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <linux/i2c-vid.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
+ I2C_CLIENT_END };
+
+static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_3(adm9240, ds1780, lm81);
+
+/* ADM9240 registers */
+#define ADM9240_REG_MAN_ID 0x3e
+#define ADM9240_REG_DIE_REV 0x3f
+#define ADM9240_REG_CONFIG 0x40
+
+#define ADM9240_REG_IN(nr) (0x20 + (nr)) /* 0..5 */
+#define ADM9240_REG_IN_MAX(nr) (0x2b + (nr) * 2)
+#define ADM9240_REG_IN_MIN(nr) (0x2c + (nr) * 2)
+#define ADM9240_REG_FAN(nr) (0x28 + (nr)) /* 0..1 */
+#define ADM9240_REG_FAN_MIN(nr) (0x3b + (nr))
+#define ADM9240_REG_INT(nr) (0x41 + (nr))
+#define ADM9240_REG_INT_MASK(nr) (0x43 + (nr))
+#define ADM9240_REG_TEMP 0x27
+#define ADM9240_REG_TEMP_HIGH 0x39
+#define ADM9240_REG_TEMP_HYST 0x3a
+#define ADM9240_REG_ANALOG_OUT 0x19
+#define ADM9240_REG_CHASSIS_CLEAR 0x46
+#define ADM9240_REG_VID_FAN_DIV 0x47
+#define ADM9240_REG_I2C_ADDR 0x48
+#define ADM9240_REG_VID4 0x49
+#define ADM9240_REG_TEMP_CONF 0x4b
+
+/* generalised scaling with integer rounding */
+static inline int SCALE(long val, int mul, int div)
+{
+ if (val < 0)
+ return (val * mul - div / 2) / div;
+ else
+ return (val * mul + div / 2) / div;
+}
+
+/* adm9240 internally scales voltage measurements */
+static const u16 nom_mv[] = { 2500, 2700, 3300, 5000, 12000, 2700 };
+
+static inline unsigned int IN_FROM_REG(u8 reg, int n)
+{
+ return SCALE(reg, nom_mv[n], 192);
+}
+
+static inline u8 IN_TO_REG(unsigned long val, int n)
+{
+ return SENSORS_LIMIT(SCALE(val, 192, nom_mv[n]), 0, 255);
+}
+
+/* temperature range: -40..125, 127 disables temperature alarm */
+static inline s8 TEMP_TO_REG(long val)
+{
+ return SENSORS_LIMIT(SCALE(val, 1, 1000), -40, 127);
+}
+
+/* two fans, each with low fan speed limit */
+static inline unsigned int FAN_FROM_REG(u8 reg, u8 div)
+{
+ if (!reg) /* error */
+ return -1;
+
+ if (reg == 255)
+ return 0;
+
+ return SCALE(1350000, 1, reg * div);
+}
+
+/* analog out 0..1250mV */
+static inline u8 AOUT_TO_REG(unsigned long val)
+{
+ return SENSORS_LIMIT(SCALE(val, 255, 1250), 0, 255);
+}
+
+static inline unsigned int AOUT_FROM_REG(u8 reg)
+{
+ return SCALE(reg, 1250, 255);
+}
+
+static int adm9240_attach_adapter(struct i2c_adapter *adapter);
+static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind);
+static void adm9240_init_client(struct i2c_client *client);
+static int adm9240_detach_client(struct i2c_client *client);
+static struct adm9240_data *adm9240_update_device(struct device *dev);
+
+/* driver data */
+static struct i2c_driver adm9240_driver = {
+ .owner = THIS_MODULE,
+ .name = "adm9240",
+ .id = I2C_DRIVERID_ADM9240,
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = adm9240_attach_adapter,
+ .detach_client = adm9240_detach_client,
+};
+
+/* per client data */
+struct adm9240_data {
+ enum chips type;
+ struct i2c_client client;
+ struct semaphore update_lock;
+ char valid;
+ unsigned long last_updated_measure;
+ unsigned long last_updated_config;
+
+ u8 in[6]; /* ro in0_input */
+ u8 in_max[6]; /* rw in0_max */
+ u8 in_min[6]; /* rw in0_min */
+ u8 fan[2]; /* ro fan1_input */
+ u8 fan_min[2]; /* rw fan1_min */
+ u8 fan_div[2]; /* rw fan1_div, read-only accessor */
+ s16 temp; /* ro temp1_input, 9-bit sign-extended */
+ s8 temp_high; /* rw temp1_max */
+ s8 temp_hyst; /* rw temp1_max_hyst */
+ u16 alarms; /* ro alarms */
+ u8 aout; /* rw aout_output */
+ u8 vid; /* ro vid */
+ u8 vrm; /* -- vrm set on startup, no accessor */
+};
+
+/* i2c byte read/write interface */
+static int adm9240_read_value(struct i2c_client *client, u8 reg)
+{
+ return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int adm9240_write_value(struct i2c_client *client, u8 reg, u8 value)
+{
+ return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+/*** sysfs accessors ***/
+
+/* temperature */
+#define show_temp(value, scale) \
+static ssize_t show_##value(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct adm9240_data *data = adm9240_update_device(dev); \
+ return sprintf(buf, "%d\n", data->value * scale); \
+}
+show_temp(temp_high, 1000);
+show_temp(temp_hyst, 1000);
+show_temp(temp, 500); /* 0.5'C per bit */
+
+#define set_temp(value, reg) \
+static ssize_t set_##value(struct device *dev, \
+ struct device_attribute *attr, \
+ const char *buf, size_t count) \
+{ \
+ struct i2c_client *client = to_i2c_client(dev); \
+ struct adm9240_data *data = adm9240_update_device(dev); \
+ long temp = simple_strtoul(buf, NULL, 10); \
+ \
+ down(&data->update_lock); \
+ data->value = TEMP_TO_REG(temp); \
+ adm9240_write_value(client, reg, data->value); \
+ up(&data->update_lock); \
+ return count; \
+}
+
+set_temp(temp_high, ADM9240_REG_TEMP_HIGH);
+set_temp(temp_hyst, ADM9240_REG_TEMP_HYST);
+
+static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
+ show_temp_high, set_temp_high);
+static DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
+ show_temp_hyst, set_temp_hyst);
+static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL);
+
+/* voltage */
+static ssize_t show_in(struct device *dev, char *buf, int nr)
+{
+ struct adm9240_data *data = adm9240_update_device(dev);
+ return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr], nr));
+}
+
+static ssize_t show_in_min(struct device *dev, char *buf, int nr)
+{
+ struct adm9240_data *data = adm9240_update_device(dev);
+ return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr], nr));
+}
+
+static ssize_t show_in_max(struct device *dev, char *buf, int nr)
+{
+ struct adm9240_data *data = adm9240_update_device(dev);
+ return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr], nr));
+}
+
+static ssize_t set_in_min(struct device *dev, const char *buf,
+ size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adm9240_data *data = i2c_get_clientdata(client);
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_min[nr] = IN_TO_REG(val, nr);
+ adm9240_write_value(client, ADM9240_REG_IN_MIN(nr), data->in_min[nr]);
+ up(&data->update_lock);
+ return count;
+}
+
+static ssize_t set_in_max(struct device *dev, const char *buf,
+ size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adm9240_data *data = i2c_get_clientdata(client);
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->in_max[nr] = IN_TO_REG(val, nr);
+ adm9240_write_value(client, ADM9240_REG_IN_MAX(nr), data->in_max[nr]);
+ up(&data->update_lock);
+ return count;
+}
+
+#define show_in_offset(offset) \
+static ssize_t show_in##offset(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ return show_in(dev, buf, offset); \
+} \
+static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL); \
+static ssize_t show_in##offset##_min(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ return show_in_min(dev, buf, offset); \
+} \
+static ssize_t show_in##offset##_max(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+ return show_in_max(dev, buf, offset); \
+} \
+static ssize_t \
+set_in##offset##_min(struct device *dev, \
+ struct device_attribute *attr, const char *buf, \
+ size_t count) \
+{ \
+ return set_in_min(dev, buf, count, offset); \
+} \
+static ssize_t \
+set_in##offset##_max(struct device *dev, \
+ struct device_attribute *attr, const char *buf, \
+ size_t count) \
+{ \
+ return set_in_max(dev, buf, count, offset); \
+} \
+static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
+ show_in##offset##_min, set_in##offset##_min); \
+static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
+ show_in##offset##_max, set_in##offset##_max);
+
+show_in_offset(0);
+show_in_offset(1);
+show_in_offset(2);
+show_in_offset(3);
+show_in_offset(4);
+show_in_offset(5);
+
+/* fans */
+static ssize_t show_fan(struct device *dev, char *buf, int nr)
+{
+ struct adm9240_data *data = adm9240_update_device(dev);
+ return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
+ 1 << data->fan_div[nr]));
+}
+
+static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
+{
+ struct adm9240_data *data = adm9240_update_device(dev);
+ return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
+ 1 << data->fan_div[nr]));
+}
+
+static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
+{
+ struct adm9240_data *data = adm9240_update_device(dev);
+ return sprintf(buf, "%d\n", 1 << data->fan_div[nr]);
+}
+
+/* write new fan div, callers must hold data->update_lock */
+static void adm9240_write_fan_div(struct i2c_client *client, int nr,
+ u8 fan_div)
+{
+ u8 reg, old, shift = (nr + 2) * 2;
+
+ reg = adm9240_read_value(client, ADM9240_REG_VID_FAN_DIV);
+ old = (reg >> shift) & 3;
+ reg &= ~(3 << shift);
+ reg |= (fan_div << shift);
+ adm9240_write_value(client, ADM9240_REG_VID_FAN_DIV, reg);
+ dev_dbg(&client->dev, "fan%d clock divider changed from %u "
+ "to %u\n", nr + 1, 1 << old, 1 << fan_div);
+}
+
+/*
+ * set fan speed low limit:
+ *
+ * - value is zero: disable fan speed low limit alarm
+ *
+ * - value is below fan speed measurement range: enable fan speed low
+ * limit alarm to be asserted while fan speed too slow to measure
+ *
+ * - otherwise: select fan clock divider to suit fan speed low limit,
+ * measurement code may adjust registers to ensure fan speed reading
+ */
+static ssize_t set_fan_min(struct device *dev, const char *buf,
+ size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adm9240_data *data = i2c_get_clientdata(client);
+ unsigned long val = simple_strtoul(buf, NULL, 10);
+ u8 new_div;
+
+ down(&data->update_lock);
+
+ if (!val) {
+ data->fan_min[nr] = 255;
+ new_div = data->fan_div[nr];
+
+ dev_dbg(&client->dev, "fan%u low limit set disabled\n",
+ nr + 1);
+
+ } else if (val < 1350000 / (8 * 254)) {
+ new_div = 3;
+ data->fan_min[nr] = 254;
+
+ dev_dbg(&client->dev, "fan%u low limit set minimum %u\n",
+ nr + 1, FAN_FROM_REG(254, 1 << new_div));
+
+ } else {
+ unsigned int new_min = 1350000 / val;
+
+ new_div = 0;
+ while (new_min > 192 && new_div < 3) {
+ new_div++;
+ new_min /= 2;
+ }
+ if (!new_min) /* keep > 0 */
+ new_min++;
+
+ data->fan_min[nr] = new_min;
+
+ dev_dbg(&client->dev, "fan%u low limit set fan speed %u\n",
+ nr + 1, FAN_FROM_REG(new_min, 1 << new_div));
+ }
+
+ if (new_div != data->fan_div[nr]) {
+ data->fan_div[nr] = new_div;
+ adm9240_write_fan_div(client, nr, new_div);
+ }
+ adm9240_write_value(client, ADM9240_REG_FAN_MIN(nr),
+ data->fan_min[nr]);
+
+ up(&data->update_lock);
+ return count;
+}
+
+#define show_fan_offset(offset) \
+static ssize_t show_fan_##offset (struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+return show_fan(dev, buf, offset - 1); \
+} \
+static ssize_t show_fan_##offset##_div (struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+return show_fan_div(dev, buf, offset - 1); \
+} \
+static ssize_t show_fan_##offset##_min (struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+{ \
+return show_fan_min(dev, buf, offset - 1); \
+} \
+static ssize_t set_fan_##offset##_min (struct device *dev, \
+ struct device_attribute *attr, \
+ const char *buf, size_t count) \
+{ \
+return set_fan_min(dev, buf, count, offset - 1); \
+} \
+static DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
+ show_fan_##offset, NULL); \
+static DEVICE_ATTR(fan##offset##_div, S_IRUGO, \
+ show_fan_##offset##_div, NULL); \
+static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
+ show_fan_##offset##_min, set_fan_##offset##_min);
+
+show_fan_offset(1);
+show_fan_offset(2);
+
+/* alarms */
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct adm9240_data *data = adm9240_update_device(dev);
+ return sprintf(buf, "%u\n", data->alarms);
+}
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+
+/* vid */
+static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct adm9240_data *data = adm9240_update_device(dev);
+ return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
+}
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
+
+/* analog output */
+static ssize_t show_aout(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct adm9240_data *data = adm9240_update_device(dev);
+ return sprintf(buf, "%d\n", AOUT_FROM_REG(data->aout));
+}
+
+static ssize_t set_aout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adm9240_data *data = i2c_get_clientdata(client);
+ unsigned long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->aout = AOUT_TO_REG(val);
+ adm9240_write_value(client, ADM9240_REG_ANALOG_OUT, data->aout);
+ up(&data->update_lock);
+ return count;
+}
+static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout);
+
+/* chassis_clear */
+static ssize_t chassis_clear(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ unsigned long val = simple_strtol(buf, NULL, 10);
+
+ if (val == 1) {
+ adm9240_write_value(client, ADM9240_REG_CHASSIS_CLEAR, 0x80);
+ dev_dbg(&client->dev, "chassis intrusion latch cleared\n");
+ }
+ return count;
+}
+static DEVICE_ATTR(chassis_clear, S_IWUSR, NULL, chassis_clear);
+
+
+/*** sensor chip detect and driver install ***/
+
+static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+ struct i2c_client *new_client;
+ struct adm9240_data *data;
+ int err = 0;
+ const char *name = "";
+ u8 man_id, die_rev;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ goto exit;
+
+ if (!(data = kmalloc(sizeof(struct adm9240_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit;
+ }
+ memset(data, 0, sizeof(struct adm9240_data));
+
+ new_client = &data->client;
+ i2c_set_clientdata(new_client, data);
+ new_client->addr = address;
+ new_client->adapter = adapter;
+ new_client->driver = &adm9240_driver;
+ new_client->flags = 0;
+
+ if (kind == 0) {
+ kind = adm9240;
+ }
+
+ if (kind < 0) {
+
+ /* verify chip: reg address should match i2c address */
+ if (adm9240_read_value(new_client, ADM9240_REG_I2C_ADDR)
+ != address) {
+ dev_err(&adapter->dev, "detect fail: address match, "
+ "0x%02x\n", address);
+ goto exit_free;
+ }
+
+ /* check known chip manufacturer */
+ man_id = adm9240_read_value(new_client, ADM9240_REG_MAN_ID);
+
+ if (man_id == 0x23) {
+ kind = adm9240;
+ } else if (man_id == 0xda) {
+ kind = ds1780;
+ } else if (man_id == 0x01) {
+ kind = lm81;
+ } else {
+ dev_err(&adapter->dev, "detect fail: unknown manuf, "
+ "0x%02x\n", man_id);
+ goto exit_free;
+ }
+
+ /* successful detect, print chip info */
+ die_rev = adm9240_read_value(new_client, ADM9240_REG_DIE_REV);
+ dev_info(&adapter->dev, "found %s revision %u\n",
+ man_id == 0x23 ? "ADM9240" :
+ man_id == 0xda ? "DS1780" : "LM81", die_rev);
+ }
+
+ /* either forced or detected chip kind */
+ if (kind == adm9240) {
+ name = "adm9240";
+ } else if (kind == ds1780) {
+ name = "ds1780";
+ } else if (kind == lm81) {
+ name = "lm81";
+ }
+
+ /* fill in the remaining client fields and attach */
+ strlcpy(new_client->name, name, I2C_NAME_SIZE);
+ data->type = kind;
+ init_MUTEX(&data->update_lock);
+
+ if ((err = i2c_attach_client(new_client)))
+ goto exit_free;
+
+ adm9240_init_client(new_client);
+
+ /* populate sysfs filesystem */
+ device_create_file(&new_client->dev, &dev_attr_in0_input);
+ device_create_file(&new_client->dev, &dev_attr_in0_min);
+ device_create_file(&new_client->dev, &dev_attr_in0_max);
+ device_create_file(&new_client->dev, &dev_attr_in1_input);
+ device_create_file(&new_client->dev, &dev_attr_in1_min);
+ device_create_file(&new_client->dev, &dev_attr_in1_max);
+ device_create_file(&new_client->dev, &dev_attr_in2_input);
+ device_create_file(&new_client->dev, &dev_attr_in2_min);
+ device_create_file(&new_client->dev, &dev_attr_in2_max);
+ device_create_file(&new_client->dev, &dev_attr_in3_input);
+ device_create_file(&new_client->dev, &dev_attr_in3_min);
+ device_create_file(&new_client->dev, &dev_attr_in3_max);
+ device_create_file(&new_client->dev, &dev_attr_in4_input);
+ device_create_file(&new_client->dev, &dev_attr_in4_min);
+ device_create_file(&new_client->dev, &dev_attr_in4_max);
+ device_create_file(&new_client->dev, &dev_attr_in5_input);
+ device_create_file(&new_client->dev, &dev_attr_in5_min);
+ device_create_file(&new_client->dev, &dev_attr_in5_max);
+ device_create_file(&new_client->dev, &dev_attr_temp1_max);
+ device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
+ device_create_file(&new_client->dev, &dev_attr_temp1_input);
+ device_create_file(&new_client->dev, &dev_attr_fan1_input);
+ device_create_file(&new_client->dev, &dev_attr_fan1_div);
+ device_create_file(&new_client->dev, &dev_attr_fan1_min);
+ device_create_file(&new_client->dev, &dev_attr_fan2_input);
+ device_create_file(&new_client->dev, &dev_attr_fan2_div);
+ device_create_file(&new_client->dev, &dev_attr_fan2_min);
+ device_create_file(&new_client->dev, &dev_attr_alarms);
+ device_create_file(&new_client->dev, &dev_attr_aout_output);
+ device_create_file(&new_client->dev, &dev_attr_chassis_clear);
+ device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
+
+ return 0;
+exit_free:
+ kfree(new_client);
+exit:
+ return err;
+}
+
+static int adm9240_attach_adapter(struct i2c_adapter *adapter)
+{
+ if (!(adapter->class & I2C_CLASS_HWMON))
+ return 0;
+ return i2c_detect(adapter, &addr_data, adm9240_detect);
+}
+
+static int adm9240_detach_client(struct i2c_client *client)
+{
+ int err;
+
+ if ((err = i2c_detach_client(client))) {
+ dev_err(&client->dev, "Client deregistration failed, "
+ "client not detached.\n");
+ return err;
+ }
+
+ kfree(i2c_get_clientdata(client));
+ return 0;
+}
+
+static void adm9240_init_client(struct i2c_client *client)
+{
+ struct adm9240_data *data = i2c_get_clientdata(client);
+ u8 conf = adm9240_read_value(client, ADM9240_REG_CONFIG);
+ u8 mode = adm9240_read_value(client, ADM9240_REG_TEMP_CONF) & 3;
+
+ data->vrm = i2c_which_vrm(); /* need this to report vid as mV */
+
+ dev_info(&client->dev, "Using VRM: %d.%d\n", data->vrm / 10,
+ data->vrm % 10);
+
+ if (conf & 1) { /* measurement cycle running: report state */
+
+ dev_info(&client->dev, "status: config 0x%02x mode %u\n",
+ conf, mode);
+
+ } else { /* cold start: open limits before starting chip */
+ int i;
+
+ for (i = 0; i < 6; i++)
+ {
+ adm9240_write_value(client,
+ ADM9240_REG_IN_MIN(i), 0);
+ adm9240_write_value(client,
+ ADM9240_REG_IN_MAX(i), 255);
+ }
+ adm9240_write_value(client, ADM9240_REG_FAN_MIN(0), 255);
+ adm9240_write_value(client, ADM9240_REG_FAN_MIN(1), 255);
+ adm9240_write_value(client, ADM9240_REG_TEMP_HIGH, 127);
+ adm9240_write_value(client, ADM9240_REG_TEMP_HYST, 127);
+
+ /* start measurement cycle */
+ adm9240_write_value(client, ADM9240_REG_CONFIG, 1);
+
+ dev_info(&client->dev, "cold start: config was 0x%02x "
+ "mode %u\n", conf, mode);
+ }
+}
+
+static struct adm9240_data *adm9240_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adm9240_data *data = i2c_get_clientdata(client);
+ int i;
+
+ down(&data->update_lock);
+
+ /* minimum measurement cycle: 1.75 seconds */
+ if (time_after(jiffies, data->last_updated_measure + (HZ * 7 / 4))
+ || !data->valid) {
+
+ for (i = 0; i < 6; i++) /* read voltages */
+ {
+ data->in[i] = adm9240_read_value(client,
+ ADM9240_REG_IN(i));
+ }
+ data->alarms = adm9240_read_value(client,
+ ADM9240_REG_INT(0)) |
+ adm9240_read_value(client,
+ ADM9240_REG_INT(1)) << 8;
+
+ /* read temperature: assume temperature changes less than
+ * 0.5'C per two measurement cycles thus ignore possible
+ * but unlikely aliasing error on lsb reading. --Grant */
+ data->temp = ((adm9240_read_value(client,
+ ADM9240_REG_TEMP) << 8) |
+ adm9240_read_value(client,
+ ADM9240_REG_TEMP_CONF)) / 128;
+
+ for (i = 0; i < 2; i++) /* read fans */
+ {
+ data->fan[i] = adm9240_read_value(client,
+ ADM9240_REG_FAN(i));
+
+ /* adjust fan clock divider on overflow */
+ if (data->valid && data->fan[i] == 255 &&
+ data->fan_div[i] < 3) {
+
+ adm9240_write_fan_div(client, i,
+ ++data->fan_div[i]);
+
+ /* adjust fan_min if active, but not to 0 */
+ if (data->fan_min[i] < 255 &&
+ data->fan_min[i] >= 2)
+ data->fan_min[i] /= 2;
+ }
+ }
+ data->last_updated_measure = jiffies;
+ }
+
+ /* minimum config reading cycle: 300 seconds */
+ if (time_after(jiffies, data->last_updated_config + (HZ * 300))
+ || !data->valid) {
+
+ for (i = 0; i < 6; i++)
+ {
+ data->in_min[i] = adm9240_read_value(client,
+ ADM9240_REG_IN_MIN(i));
+ data->in_max[i] = adm9240_read_value(client,
+ ADM9240_REG_IN_MAX(i));
+ }
+ for (i = 0; i < 2; i++)
+ {
+ data->fan_min[i] = adm9240_read_value(client,
+ ADM9240_REG_FAN_MIN(i));
+ }
+ data->temp_high = adm9240_read_value(client,
+ ADM9240_REG_TEMP_HIGH);
+ data->temp_hyst = adm9240_read_value(client,
+ ADM9240_REG_TEMP_HYST);
+
+ /* read fan divs and 5-bit VID */
+ i = adm9240_read_value(client, ADM9240_REG_VID_FAN_DIV);
+ data->fan_div[0] = (i >> 4) & 3;
+ data->fan_div[1] = (i >> 6) & 3;
+ data->vid = i & 0x0f;
+ data->vid |= (adm9240_read_value(client,
+ ADM9240_REG_VID4) & 1) << 4;
+ /* read analog out */
+ data->aout = adm9240_read_value(client,
+ ADM9240_REG_ANALOG_OUT);
+
+ data->last_updated_config = jiffies;
+ data->valid = 1;
+ }
+ up(&data->update_lock);
+ return data;
+}
+
+static int __init sensors_adm9240_init(void)
+{
+ return i2c_add_driver(&adm9240_driver);
+}
+
+static void __exit sensors_adm9240_exit(void)
+{
+ i2c_del_driver(&adm9240_driver);
+}
+
+MODULE_AUTHOR("Michiel Rook <michiel@grendelproject.nl>, "
+ "Grant Coady <gcoady@gmail.com> and others");
+MODULE_DESCRIPTION("ADM9240/DS1780/LM81 driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_adm9240_init);
+module_exit(sensors_adm9240_exit);
+
diff --git a/drivers/i2c/chips/asb100.c b/drivers/i2c/chips/asb100.c
index 7f899002bc5..70d996d6fe0 100644
--- a/drivers/i2c/chips/asb100.c
+++ b/drivers/i2c/chips/asb100.c
@@ -42,6 +42,7 @@
#include <linux/i2c-sensor.h>
#include <linux/i2c-vid.h>
#include <linux/init.h>
+#include <linux/jiffies.h>
#include "lm75.h"
/*
@@ -168,8 +169,6 @@ static int ASB100_PWM_FROM_REG(u8 reg)
return reg * 16;
}
-#define ALARMS_FROM_REG(val) (val)
-
#define DIV_FROM_REG(val) (1 << (val))
/* FAN DIV: 1, 2, 4, or 8 (defaults to 2)
@@ -260,28 +259,28 @@ set_in_reg(MAX, max)
#define sysfs_in(offset) \
static ssize_t \
- show_in##offset (struct device *dev, char *buf) \
+ show_in##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_in(dev, buf, offset); \
} \
static DEVICE_ATTR(in##offset##_input, S_IRUGO, \
show_in##offset, NULL); \
static ssize_t \
- show_in##offset##_min (struct device *dev, char *buf) \
+ show_in##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_in_min(dev, buf, offset); \
} \
static ssize_t \
- show_in##offset##_max (struct device *dev, char *buf) \
+ show_in##offset##_max (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_in_max(dev, buf, offset); \
} \
-static ssize_t set_in##offset##_min (struct device *dev, \
+static ssize_t set_in##offset##_min (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_in_min(dev, buf, count, offset); \
} \
-static ssize_t set_in##offset##_max (struct device *dev, \
+static ssize_t set_in##offset##_max (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_in_max(dev, buf, count, offset); \
@@ -389,24 +388,24 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
}
#define sysfs_fan(offset) \
-static ssize_t show_fan##offset(struct device *dev, char *buf) \
+static ssize_t show_fan##offset(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_fan(dev, buf, offset - 1); \
} \
-static ssize_t show_fan##offset##_min(struct device *dev, char *buf) \
+static ssize_t show_fan##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_fan_min(dev, buf, offset - 1); \
} \
-static ssize_t show_fan##offset##_div(struct device *dev, char *buf) \
+static ssize_t show_fan##offset##_div(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_fan_div(dev, buf, offset - 1); \
} \
-static ssize_t set_fan##offset##_min(struct device *dev, const char *buf, \
+static ssize_t set_fan##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
return set_fan_min(dev, buf, count, offset - 1); \
} \
-static ssize_t set_fan##offset##_div(struct device *dev, const char *buf, \
+static ssize_t set_fan##offset##_div(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
return set_fan_div(dev, buf, count, offset - 1); \
@@ -482,27 +481,27 @@ set_temp_reg(MAX, temp_max);
set_temp_reg(HYST, temp_hyst);
#define sysfs_temp(num) \
-static ssize_t show_temp##num(struct device *dev, char *buf) \
+static ssize_t show_temp##num(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_temp(dev, buf, num-1); \
} \
static DEVICE_ATTR(temp##num##_input, S_IRUGO, show_temp##num, NULL); \
-static ssize_t show_temp_max##num(struct device *dev, char *buf) \
+static ssize_t show_temp_max##num(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_temp_max(dev, buf, num-1); \
} \
-static ssize_t set_temp_max##num(struct device *dev, const char *buf, \
+static ssize_t set_temp_max##num(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
return set_temp_max(dev, buf, count, num-1); \
} \
static DEVICE_ATTR(temp##num##_max, S_IRUGO | S_IWUSR, \
show_temp_max##num, set_temp_max##num); \
-static ssize_t show_temp_hyst##num(struct device *dev, char *buf) \
+static ssize_t show_temp_hyst##num(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_temp_hyst(dev, buf, num-1); \
} \
-static ssize_t set_temp_hyst##num(struct device *dev, const char *buf, \
+static ssize_t set_temp_hyst##num(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
return set_temp_hyst(dev, buf, count, num-1); \
@@ -522,7 +521,7 @@ sysfs_temp(4);
device_create_file(&client->dev, &dev_attr_temp##num##_max_hyst); \
} while (0)
-static ssize_t show_vid(struct device *dev, char *buf)
+static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
{
struct asb100_data *data = asb100_update_device(dev);
return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
@@ -533,13 +532,13 @@ static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
device_create_file(&client->dev, &dev_attr_cpu0_vid)
/* VRM */
-static ssize_t show_vrm(struct device *dev, char *buf)
+static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
{
struct asb100_data *data = asb100_update_device(dev);
return sprintf(buf, "%d\n", data->vrm);
}
-static ssize_t set_vrm(struct device *dev, const char *buf, size_t count)
+static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct asb100_data *data = i2c_get_clientdata(client);
@@ -553,10 +552,10 @@ static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
#define device_create_file_vrm(client) \
device_create_file(&client->dev, &dev_attr_vrm);
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
{
struct asb100_data *data = asb100_update_device(dev);
- return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->alarms));
+ return sprintf(buf, "%u\n", data->alarms);
}
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
@@ -564,13 +563,13 @@ static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
device_create_file(&client->dev, &dev_attr_alarms)
/* 1 PWM */
-static ssize_t show_pwm1(struct device *dev, char *buf)
+static ssize_t show_pwm1(struct device *dev, struct device_attribute *attr, char *buf)
{
struct asb100_data *data = asb100_update_device(dev);
return sprintf(buf, "%d\n", ASB100_PWM_FROM_REG(data->pwm & 0x0f));
}
-static ssize_t set_pwm1(struct device *dev, const char *buf, size_t count)
+static ssize_t set_pwm1(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct asb100_data *data = i2c_get_clientdata(client);
@@ -584,13 +583,13 @@ static ssize_t set_pwm1(struct device *dev, const char *buf, size_t count)
return count;
}
-static ssize_t show_pwm_enable1(struct device *dev, char *buf)
+static ssize_t show_pwm_enable1(struct device *dev, struct device_attribute *attr, char *buf)
{
struct asb100_data *data = asb100_update_device(dev);
return sprintf(buf, "%d\n", (data->pwm & 0x80) ? 1 : 0);
}
-static ssize_t set_pwm_enable1(struct device *dev, const char *buf,
+static ssize_t set_pwm_enable1(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
diff --git a/drivers/i2c/chips/atxp1.c b/drivers/i2c/chips/atxp1.c
new file mode 100644
index 00000000000..5c6597aa2c7
--- /dev/null
+++ b/drivers/i2c/chips/atxp1.c
@@ -0,0 +1,361 @@
+/*
+ atxp1.c - kernel module for setting CPU VID and general purpose
+ I/Os using the Attansic ATXP1 chip.
+
+ 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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <linux/i2c-vid.h>
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("System voltages control via Attansic ATXP1");
+MODULE_VERSION("0.6.2");
+MODULE_AUTHOR("Sebastian Witt <se.witt@gmx.net>");
+
+#define ATXP1_VID 0x00
+#define ATXP1_CVID 0x01
+#define ATXP1_GPIO1 0x06
+#define ATXP1_GPIO2 0x0a
+#define ATXP1_VIDENA 0x20
+#define ATXP1_VIDMASK 0x1f
+#define ATXP1_GPIO1MASK 0x0f
+
+static unsigned short normal_i2c[] = { 0x37, 0x4e, I2C_CLIENT_END };
+static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
+
+SENSORS_INSMOD_1(atxp1);
+
+static int atxp1_attach_adapter(struct i2c_adapter * adapter);
+static int atxp1_detach_client(struct i2c_client * client);
+static struct atxp1_data * atxp1_update_device(struct device *dev);
+static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind);
+
+static struct i2c_driver atxp1_driver = {
+ .owner = THIS_MODULE,
+ .name = "atxp1",
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = atxp1_attach_adapter,
+ .detach_client = atxp1_detach_client,
+};
+
+struct atxp1_data {
+ struct i2c_client client;
+ struct semaphore update_lock;
+ unsigned long last_updated;
+ u8 valid;
+ struct {
+ u8 vid; /* VID output register */
+ u8 cpu_vid; /* VID input from CPU */
+ u8 gpio1; /* General purpose I/O register 1 */
+ u8 gpio2; /* General purpose I/O register 2 */
+ } reg;
+ u8 vrm; /* Detected CPU VRM */
+};
+
+static struct atxp1_data * atxp1_update_device(struct device *dev)
+{
+ struct i2c_client *client;
+ struct atxp1_data *data;
+
+ client = to_i2c_client(dev);
+ data = i2c_get_clientdata(client);
+
+ down(&data->update_lock);
+
+ if ((jiffies - data->last_updated > HZ) ||
+ (jiffies < data->last_updated) ||
+ !data->valid) {
+
+ /* Update local register data */
+ data->reg.vid = i2c_smbus_read_byte_data(client, ATXP1_VID);
+ data->reg.cpu_vid = i2c_smbus_read_byte_data(client, ATXP1_CVID);
+ data->reg.gpio1 = i2c_smbus_read_byte_data(client, ATXP1_GPIO1);
+ data->reg.gpio2 = i2c_smbus_read_byte_data(client, ATXP1_GPIO2);
+
+ data->valid = 1;
+ }
+
+ up(&data->update_lock);
+
+ return(data);
+}
+
+/* sys file functions for cpu0_vid */
+static ssize_t atxp1_showvcore(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int size;
+ struct atxp1_data *data;
+
+ data = atxp1_update_device(dev);
+
+ size = sprintf(buf, "%d\n", vid_from_reg(data->reg.vid & ATXP1_VIDMASK, data->vrm));
+
+ return size;
+}
+
+static ssize_t atxp1_storevcore(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct atxp1_data *data;
+ struct i2c_client *client;
+ char vid;
+ char cvid;
+ unsigned int vcore;
+
+ client = to_i2c_client(dev);
+ data = atxp1_update_device(dev);
+
+ vcore = simple_strtoul(buf, NULL, 10);
+ vcore /= 25;
+ vcore *= 25;
+
+ /* Calculate VID */
+ vid = vid_to_reg(vcore, data->vrm);
+
+ if (vid < 0) {
+ dev_err(dev, "VID calculation failed.\n");
+ return -1;
+ }
+
+ /* If output enabled, use control register value. Otherwise original CPU VID */
+ if (data->reg.vid & ATXP1_VIDENA)
+ cvid = data->reg.vid & ATXP1_VIDMASK;
+ else
+ cvid = data->reg.cpu_vid;
+
+ /* Nothing changed, aborting */
+ if (vid == cvid)
+ return count;
+
+ dev_info(dev, "Setting VCore to %d mV (0x%02x)\n", vcore, vid);
+
+ /* Write every 25 mV step to increase stability */
+ if (cvid > vid) {
+ for (; cvid >= vid; cvid--) {
+ i2c_smbus_write_byte_data(client, ATXP1_VID, cvid | ATXP1_VIDENA);
+ }
+ }
+ else {
+ for (; cvid <= vid; cvid++) {
+ i2c_smbus_write_byte_data(client, ATXP1_VID, cvid | ATXP1_VIDENA);
+ }
+ }
+
+ data->valid = 0;
+
+ return count;
+}
+
+/* CPU core reference voltage
+ unit: millivolt
+*/
+static DEVICE_ATTR(cpu0_vid, S_IRUGO | S_IWUSR, atxp1_showvcore, atxp1_storevcore);
+
+/* sys file functions for GPIO1 */
+static ssize_t atxp1_showgpio1(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int size;
+ struct atxp1_data *data;
+
+ data = atxp1_update_device(dev);
+
+ size = sprintf(buf, "0x%02x\n", data->reg.gpio1 & ATXP1_GPIO1MASK);
+
+ return size;
+}
+
+static ssize_t atxp1_storegpio1(struct device *dev, struct device_attribute *attr, const char*buf, size_t count)
+{
+ struct atxp1_data *data;
+ struct i2c_client *client;
+ unsigned int value;
+
+ client = to_i2c_client(dev);
+ data = atxp1_update_device(dev);
+
+ value = simple_strtoul(buf, NULL, 16);
+
+ value &= ATXP1_GPIO1MASK;
+
+ if (value != (data->reg.gpio1 & ATXP1_GPIO1MASK)) {
+ dev_info(dev, "Writing 0x%x to GPIO1.\n", value);
+
+ i2c_smbus_write_byte_data(client, ATXP1_GPIO1, value);
+
+ data->valid = 0;
+ }
+
+ return count;
+}
+
+/* GPIO1 data register
+ unit: Four bit as hex (e.g. 0x0f)
+*/
+static DEVICE_ATTR(gpio1, S_IRUGO | S_IWUSR, atxp1_showgpio1, atxp1_storegpio1);
+
+/* sys file functions for GPIO2 */
+static ssize_t atxp1_showgpio2(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int size;
+ struct atxp1_data *data;
+
+ data = atxp1_update_device(dev);
+
+ size = sprintf(buf, "0x%02x\n", data->reg.gpio2);
+
+ return size;
+}
+
+static ssize_t atxp1_storegpio2(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct atxp1_data *data;
+ struct i2c_client *client;
+ unsigned int value;
+
+ client = to_i2c_client(dev);
+ data = atxp1_update_device(dev);
+
+ value = simple_strtoul(buf, NULL, 16) & 0xff;
+
+ if (value != data->reg.gpio2) {
+ dev_info(dev, "Writing 0x%x to GPIO1.\n", value);
+
+ i2c_smbus_write_byte_data(client, ATXP1_GPIO2, value);
+
+ data->valid = 0;
+ }
+
+ return count;
+}
+
+/* GPIO2 data register
+ unit: Eight bit as hex (e.g. 0xff)
+*/
+static DEVICE_ATTR(gpio2, S_IRUGO | S_IWUSR, atxp1_showgpio2, atxp1_storegpio2);
+
+
+static int atxp1_attach_adapter(struct i2c_adapter *adapter)
+{
+ return i2c_detect(adapter, &addr_data, &atxp1_detect);
+};
+
+static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+ struct i2c_client * new_client;
+ struct atxp1_data * data;
+ int err = 0;
+ u8 temp;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ goto exit;
+
+ if (!(data = kmalloc(sizeof(struct atxp1_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit;
+ }
+
+ memset(data, 0, sizeof(struct atxp1_data));
+ new_client = &data->client;
+ i2c_set_clientdata(new_client, data);
+
+ new_client->addr = address;
+ new_client->adapter = adapter;
+ new_client->driver = &atxp1_driver;
+ new_client->flags = 0;
+
+ /* Detect ATXP1, checking if vendor ID registers are all zero */
+ if (!((i2c_smbus_read_byte_data(new_client, 0x3e) == 0) &&
+ (i2c_smbus_read_byte_data(new_client, 0x3f) == 0) &&
+ (i2c_smbus_read_byte_data(new_client, 0xfe) == 0) &&
+ (i2c_smbus_read_byte_data(new_client, 0xff) == 0) )) {
+
+ /* No vendor ID, now checking if registers 0x10,0x11 (non-existent)
+ * showing the same as register 0x00 */
+ temp = i2c_smbus_read_byte_data(new_client, 0x00);
+
+ if (!((i2c_smbus_read_byte_data(new_client, 0x10) == temp) &&
+ (i2c_smbus_read_byte_data(new_client, 0x11) == temp) ))
+ goto exit_free;
+ }
+
+ /* Get VRM */
+ data->vrm = i2c_which_vrm();
+
+ if ((data->vrm != 90) && (data->vrm != 91)) {
+ dev_err(&new_client->dev, "Not supporting VRM %d.%d\n",
+ data->vrm / 10, data->vrm % 10);
+ goto exit_free;
+ }
+
+ strncpy(new_client->name, "atxp1", I2C_NAME_SIZE);
+
+ data->valid = 0;
+
+ init_MUTEX(&data->update_lock);
+
+ err = i2c_attach_client(new_client);
+
+ if (err)
+ {
+ dev_err(&new_client->dev, "Attach client error.\n");
+ goto exit_free;
+ }
+
+ device_create_file(&new_client->dev, &dev_attr_gpio1);
+ device_create_file(&new_client->dev, &dev_attr_gpio2);
+ device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
+
+ dev_info(&new_client->dev, "Using VRM: %d.%d\n",
+ data->vrm / 10, data->vrm % 10);
+
+ return 0;
+
+exit_free:
+ kfree(data);
+exit:
+ return err;
+};
+
+static int atxp1_detach_client(struct i2c_client * client)
+{
+ int err;
+
+ err = i2c_detach_client(client);
+
+ if (err)
+ dev_err(&client->dev, "Failed to detach client.\n");
+ else
+ kfree(i2c_get_clientdata(client));
+
+ return err;
+};
+
+static int __init atxp1_init(void)
+{
+ return i2c_add_driver(&atxp1_driver);
+};
+
+static void __exit atxp1_exit(void)
+{
+ i2c_del_driver(&atxp1_driver);
+};
+
+module_init(atxp1_init);
+module_exit(atxp1_exit);
diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c
index 07f16c3fb08..74ece8ac1c2 100644
--- a/drivers/i2c/chips/ds1337.c
+++ b/drivers/i2c/chips/ds1337.c
@@ -3,17 +3,16 @@
*
* Copyright (C) 2005 James Chapman <jchapman@katalix.com>
*
- * based on linux/drivers/acron/char/pcf8583.c
+ * based on linux/drivers/acorn/char/pcf8583.c
* Copyright (C) 2000 Russell King
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
- * Driver for Dallas Semiconductor DS1337 real time clock chip
+ * Driver for Dallas Semiconductor DS1337 and DS1339 real time clock chip
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -69,13 +68,11 @@ static struct i2c_driver ds1337_driver = {
struct ds1337_data {
struct i2c_client client;
struct list_head list;
- int id;
};
/*
* Internal variables
*/
-static int ds1337_id;
static LIST_HEAD(ds1337_clients);
static inline int ds1337_read(struct i2c_client *client, u8 reg, u8 *value)
@@ -95,7 +92,6 @@ static inline int ds1337_read(struct i2c_client *client, u8 reg, u8 *value)
*/
static int ds1337_get_datetime(struct i2c_client *client, struct rtc_time *dt)
{
- struct ds1337_data *data = i2c_get_clientdata(client);
int result;
u8 buf[7];
u8 val;
@@ -103,9 +99,7 @@ static int ds1337_get_datetime(struct i2c_client *client, struct rtc_time *dt)
u8 offs = 0;
if (!dt) {
- dev_dbg(&client->adapter->dev, "%s: EINVAL: dt=NULL\n",
- __FUNCTION__);
-
+ dev_dbg(&client->dev, "%s: EINVAL: dt=NULL\n", __FUNCTION__);
return -EINVAL;
}
@@ -119,98 +113,86 @@ static int ds1337_get_datetime(struct i2c_client *client, struct rtc_time *dt)
msg[1].len = sizeof(buf);
msg[1].buf = &buf[0];
- result = client->adapter->algo->master_xfer(client->adapter,
- &msg[0], 2);
+ result = i2c_transfer(client->adapter, msg, 2);
- dev_dbg(&client->adapter->dev,
- "%s: [%d] %02x %02x %02x %02x %02x %02x %02x\n",
+ dev_dbg(&client->dev, "%s: [%d] %02x %02x %02x %02x %02x %02x %02x\n",
__FUNCTION__, result, buf[0], buf[1], buf[2], buf[3],
buf[4], buf[5], buf[6]);
- if (result >= 0) {
- dt->tm_sec = BCD_TO_BIN(buf[0]);
- dt->tm_min = BCD_TO_BIN(buf[1]);
+ if (result == 2) {
+ dt->tm_sec = BCD2BIN(buf[0]);
+ dt->tm_min = BCD2BIN(buf[1]);
val = buf[2] & 0x3f;
- dt->tm_hour = BCD_TO_BIN(val);
- dt->tm_wday = BCD_TO_BIN(buf[3]) - 1;
- dt->tm_mday = BCD_TO_BIN(buf[4]);
+ dt->tm_hour = BCD2BIN(val);
+ dt->tm_wday = BCD2BIN(buf[3]) - 1;
+ dt->tm_mday = BCD2BIN(buf[4]);
val = buf[5] & 0x7f;
- dt->tm_mon = BCD_TO_BIN(val);
- dt->tm_year = 1900 + BCD_TO_BIN(buf[6]);
+ dt->tm_mon = BCD2BIN(val) - 1;
+ dt->tm_year = BCD2BIN(buf[6]);
if (buf[5] & 0x80)
dt->tm_year += 100;
- dev_dbg(&client->adapter->dev, "%s: secs=%d, mins=%d, "
+ dev_dbg(&client->dev, "%s: secs=%d, mins=%d, "
"hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
__FUNCTION__, dt->tm_sec, dt->tm_min,
dt->tm_hour, dt->tm_mday,
dt->tm_mon, dt->tm_year, dt->tm_wday);
- } else {
- dev_err(&client->adapter->dev, "ds1337[%d]: error reading "
- "data! %d\n", data->id, result);
- result = -EIO;
+
+ return 0;
}
- return result;
+ dev_err(&client->dev, "error reading data! %d\n", result);
+ return -EIO;
}
static int ds1337_set_datetime(struct i2c_client *client, struct rtc_time *dt)
{
- struct ds1337_data *data = i2c_get_clientdata(client);
int result;
u8 buf[8];
u8 val;
struct i2c_msg msg[1];
if (!dt) {
- dev_dbg(&client->adapter->dev, "%s: EINVAL: dt=NULL\n",
- __FUNCTION__);
-
+ dev_dbg(&client->dev, "%s: EINVAL: dt=NULL\n", __FUNCTION__);
return -EINVAL;
}
- dev_dbg(&client->adapter->dev, "%s: secs=%d, mins=%d, hours=%d, "
+ dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
"mday=%d, mon=%d, year=%d, wday=%d\n", __FUNCTION__,
dt->tm_sec, dt->tm_min, dt->tm_hour,
dt->tm_mday, dt->tm_mon, dt->tm_year, dt->tm_wday);
buf[0] = 0; /* reg offset */
- buf[1] = BIN_TO_BCD(dt->tm_sec);
- buf[2] = BIN_TO_BCD(dt->tm_min);
- buf[3] = BIN_TO_BCD(dt->tm_hour) | (1 << 6);
- buf[4] = BIN_TO_BCD(dt->tm_wday) + 1;
- buf[5] = BIN_TO_BCD(dt->tm_mday);
- buf[6] = BIN_TO_BCD(dt->tm_mon);
- if (dt->tm_year >= 2000) {
- val = dt->tm_year - 2000;
+ buf[1] = BIN2BCD(dt->tm_sec);
+ buf[2] = BIN2BCD(dt->tm_min);
+ buf[3] = BIN2BCD(dt->tm_hour) | (1 << 6);
+ buf[4] = BIN2BCD(dt->tm_wday) + 1;
+ buf[5] = BIN2BCD(dt->tm_mday);
+ buf[6] = BIN2BCD(dt->tm_mon) + 1;
+ val = dt->tm_year;
+ if (val >= 100) {
+ val -= 100;
buf[6] |= (1 << 7);
- } else {
- val = dt->tm_year - 1900;
}
- buf[7] = BIN_TO_BCD(val);
+ buf[7] = BIN2BCD(val);
msg[0].addr = client->addr;
msg[0].flags = 0;
msg[0].len = sizeof(buf);
msg[0].buf = &buf[0];
- result = client->adapter->algo->master_xfer(client->adapter,
- &msg[0], 1);
- if (result < 0) {
- dev_err(&client->adapter->dev, "ds1337[%d]: error "
- "writing data! %d\n", data->id, result);
- result = -EIO;
- } else {
- result = 0;
- }
+ result = i2c_transfer(client->adapter, msg, 1);
+ if (result == 1)
+ return 0;
- return result;
+ dev_err(&client->dev, "error writing data! %d\n", result);
+ return -EIO;
}
static int ds1337_command(struct i2c_client *client, unsigned int cmd,
void *arg)
{
- dev_dbg(&client->adapter->dev, "%s: cmd=%d\n", __FUNCTION__, cmd);
+ dev_dbg(&client->dev, "%s: cmd=%d\n", __FUNCTION__, cmd);
switch (cmd) {
case DS1337_GET_DATE:
@@ -228,7 +210,7 @@ static int ds1337_command(struct i2c_client *client, unsigned int cmd,
* Public API for access to specific device. Useful for low-level
* RTC access from kernel code.
*/
-int ds1337_do_command(int id, int cmd, void *arg)
+int ds1337_do_command(int bus, int cmd, void *arg)
{
struct list_head *walk;
struct list_head *tmp;
@@ -236,7 +218,7 @@ int ds1337_do_command(int id, int cmd, void *arg)
list_for_each_safe(walk, tmp, &ds1337_clients) {
data = list_entry(walk, struct ds1337_data, list);
- if (data->id == id)
+ if (data->client.adapter->nr == bus)
return ds1337_command(&data->client, cmd, arg);
}
@@ -346,7 +328,6 @@ static int ds1337_detect(struct i2c_adapter *adapter, int address, int kind)
ds1337_init_client(new_client);
/* Add client to local list */
- data->id = ds1337_id++;
list_add(&data->list, &ds1337_clients);
return 0;
@@ -398,5 +379,7 @@ MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
MODULE_DESCRIPTION("DS1337 RTC driver");
MODULE_LICENSE("GPL");
+EXPORT_SYMBOL_GPL(ds1337_do_command);
+
module_init(ds1337_init);
module_exit(ds1337_exit);
diff --git a/drivers/i2c/chips/ds1374.c b/drivers/i2c/chips/ds1374.c
new file mode 100644
index 00000000000..a445736d883
--- /dev/null
+++ b/drivers/i2c/chips/ds1374.c
@@ -0,0 +1,260 @@
+/*
+ * drivers/i2c/chips/ds1374.c
+ *
+ * I2C client/driver for the Maxim/Dallas DS1374 Real-Time Clock
+ *
+ * Author: Randy Vinson <rvinson@mvista.com>
+ *
+ * Based on the m41t00.c by Mark Greer <mgreer@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+/*
+ * This i2c client/driver wedges between the drivers/char/genrtc.c RTC
+ * interface and the SMBus interface of the i2c subsystem.
+ * It would be more efficient to use i2c msgs/i2c_transfer directly but, as
+ * recommened in .../Documentation/i2c/writing-clients section
+ * "Sending and receiving", using SMBus level communication is preferred.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+
+#define DS1374_REG_TOD0 0x00
+#define DS1374_REG_TOD1 0x01
+#define DS1374_REG_TOD2 0x02
+#define DS1374_REG_TOD3 0x03
+#define DS1374_REG_WDALM0 0x04
+#define DS1374_REG_WDALM1 0x05
+#define DS1374_REG_WDALM2 0x06
+#define DS1374_REG_CR 0x07
+#define DS1374_REG_SR 0x08
+#define DS1374_REG_SR_OSF 0x80
+#define DS1374_REG_TCR 0x09
+
+#define DS1374_DRV_NAME "ds1374"
+
+static DECLARE_MUTEX(ds1374_mutex);
+
+static struct i2c_driver ds1374_driver;
+static struct i2c_client *save_client;
+
+static unsigned short ignore[] = { I2C_CLIENT_END };
+static unsigned short normal_addr[] = { 0x68, I2C_CLIENT_END };
+
+static struct i2c_client_address_data addr_data = {
+ .normal_i2c = normal_addr,
+ .probe = ignore,
+ .ignore = ignore,
+ .force = ignore,
+};
+
+static ulong ds1374_read_rtc(void)
+{
+ ulong time = 0;
+ int reg = DS1374_REG_WDALM0;
+
+ while (reg--) {
+ s32 tmp;
+ if ((tmp = i2c_smbus_read_byte_data(save_client, reg)) < 0) {
+ dev_warn(&save_client->dev,
+ "can't read from rtc chip\n");
+ return 0;
+ }
+ time = (time << 8) | (tmp & 0xff);
+ }
+ return time;
+}
+
+static void ds1374_write_rtc(ulong time)
+{
+ int reg;
+
+ for (reg = DS1374_REG_TOD0; reg < DS1374_REG_WDALM0; reg++) {
+ if (i2c_smbus_write_byte_data(save_client, reg, time & 0xff)
+ < 0) {
+ dev_warn(&save_client->dev,
+ "can't write to rtc chip\n");
+ break;
+ }
+ time = time >> 8;
+ }
+}
+
+static void ds1374_check_rtc_status(void)
+{
+ s32 tmp;
+
+ tmp = i2c_smbus_read_byte_data(save_client, DS1374_REG_SR);
+ if (tmp < 0) {
+ dev_warn(&save_client->dev,
+ "can't read status from rtc chip\n");
+ return;
+ }
+ if (tmp & DS1374_REG_SR_OSF) {
+ dev_warn(&save_client->dev,
+ "oscillator discontinuity flagged, time unreliable\n");
+ tmp &= ~DS1374_REG_SR_OSF;
+ tmp = i2c_smbus_write_byte_data(save_client, DS1374_REG_SR,
+ tmp & 0xff);
+ if (tmp < 0)
+ dev_warn(&save_client->dev,
+ "can't clear discontinuity notification\n");
+ }
+}
+
+ulong ds1374_get_rtc_time(void)
+{
+ ulong t1, t2;
+ int limit = 10; /* arbitrary retry limit */
+
+ down(&ds1374_mutex);
+
+ /*
+ * Since the reads are being performed one byte at a time using
+ * the SMBus vs a 4-byte i2c transfer, there is a chance that a
+ * carry will occur during the read. To detect this, 2 reads are
+ * performed and compared.
+ */
+ do {
+ t1 = ds1374_read_rtc();
+ t2 = ds1374_read_rtc();
+ } while (t1 != t2 && limit--);
+
+ up(&ds1374_mutex);
+
+ if (t1 != t2) {
+ dev_warn(&save_client->dev,
+ "can't get consistent time from rtc chip\n");
+ t1 = 0;
+ }
+
+ return t1;
+}
+
+static void ds1374_set_tlet(ulong arg)
+{
+ ulong t1, t2;
+ int limit = 10; /* arbitrary retry limit */
+
+ t1 = *(ulong *) arg;
+
+ down(&ds1374_mutex);
+
+ /*
+ * Since the writes are being performed one byte at a time using
+ * the SMBus vs a 4-byte i2c transfer, there is a chance that a
+ * carry will occur during the write. To detect this, the write
+ * value is read back and compared.
+ */
+ do {
+ ds1374_write_rtc(t1);
+ t2 = ds1374_read_rtc();
+ } while (t1 != t2 && limit--);
+
+ up(&ds1374_mutex);
+
+ if (t1 != t2)
+ dev_warn(&save_client->dev,
+ "can't confirm time set from rtc chip\n");
+}
+
+ulong new_time;
+
+DECLARE_TASKLET_DISABLED(ds1374_tasklet, ds1374_set_tlet, (ulong) & new_time);
+
+int ds1374_set_rtc_time(ulong nowtime)
+{
+ new_time = nowtime;
+
+ if (in_interrupt())
+ tasklet_schedule(&ds1374_tasklet);
+ else
+ ds1374_set_tlet((ulong) & new_time);
+
+ return 0;
+}
+
+/*
+ *****************************************************************************
+ *
+ * Driver Interface
+ *
+ *****************************************************************************
+ */
+static int ds1374_probe(struct i2c_adapter *adap, int addr, int kind)
+{
+ struct i2c_client *client;
+ int rc;
+
+ client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+ if (!client)
+ return -ENOMEM;
+
+ memset(client, 0, sizeof(struct i2c_client));
+ strncpy(client->name, DS1374_DRV_NAME, I2C_NAME_SIZE);
+ client->flags = I2C_DF_NOTIFY;
+ client->addr = addr;
+ client->adapter = adap;
+ client->driver = &ds1374_driver;
+
+ if ((rc = i2c_attach_client(client)) != 0) {
+ kfree(client);
+ return rc;
+ }
+
+ save_client = client;
+
+ ds1374_check_rtc_status();
+
+ return 0;
+}
+
+static int ds1374_attach(struct i2c_adapter *adap)
+{
+ return i2c_probe(adap, &addr_data, ds1374_probe);
+}
+
+static int ds1374_detach(struct i2c_client *client)
+{
+ int rc;
+
+ if ((rc = i2c_detach_client(client)) == 0) {
+ kfree(i2c_get_clientdata(client));
+ tasklet_kill(&ds1374_tasklet);
+ }
+ return rc;
+}
+
+static struct i2c_driver ds1374_driver = {
+ .owner = THIS_MODULE,
+ .name = DS1374_DRV_NAME,
+ .id = I2C_DRIVERID_DS1374,
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = ds1374_attach,
+ .detach_client = ds1374_detach,
+};
+
+static int __init ds1374_init(void)
+{
+ return i2c_add_driver(&ds1374_driver);
+}
+
+static void __exit ds1374_exit(void)
+{
+ i2c_del_driver(&ds1374_driver);
+}
+
+module_init(ds1374_init);
+module_exit(ds1374_exit);
+
+MODULE_AUTHOR("Randy Vinson <rvinson@mvista.com>");
+MODULE_DESCRIPTION("Maxim/Dallas DS1374 RTC I2C Client Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/chips/ds1621.c b/drivers/i2c/chips/ds1621.c
index bb1fefb2162..5360d58804f 100644
--- a/drivers/i2c/chips/ds1621.c
+++ b/drivers/i2c/chips/ds1621.c
@@ -121,7 +121,7 @@ static int ds1621_write_value(struct i2c_client *client, u8 reg, u16 value)
static void ds1621_init_client(struct i2c_client *client)
{
int reg = ds1621_read_value(client, DS1621_REG_CONF);
- /* switch to continous conversion mode */
+ /* switch to continuous conversion mode */
reg &= ~ DS1621_REG_CONFIG_1SHOT;
/* setup output polarity */
@@ -137,7 +137,7 @@ static void ds1621_init_client(struct i2c_client *client)
}
#define show(value) \
-static ssize_t show_##value(struct device *dev, char *buf) \
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct ds1621_data *data = ds1621_update_client(dev); \
return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->value)); \
@@ -148,7 +148,7 @@ show(temp_min);
show(temp_max);
#define set_temp(suffix, value, reg) \
-static ssize_t set_temp_##suffix(struct device *dev, const char *buf, \
+static ssize_t set_temp_##suffix(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
@@ -165,7 +165,7 @@ static ssize_t set_temp_##suffix(struct device *dev, const char *buf, \
set_temp(min, temp_min, DS1621_REG_TEMP_MIN);
set_temp(max, temp_max, DS1621_REG_TEMP_MAX);
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
{
struct ds1621_data *data = ds1621_update_client(dev);
return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->conf));
@@ -303,7 +303,7 @@ static struct ds1621_data *ds1621_update_client(struct device *dev)
data->temp_max = ds1621_read_value(client,
DS1621_REG_TEMP_MAX);
- /* reset alarms if neccessary */
+ /* reset alarms if necessary */
new_conf = data->conf;
if (data->temp < data->temp_min)
new_conf &= ~DS1621_ALARM_TEMP_LOW;
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
index cbdfa2db6f7..addf0adc24d 100644
--- a/drivers/i2c/chips/eeprom.c
+++ b/drivers/i2c/chips/eeprom.c
@@ -26,7 +26,6 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
diff --git a/drivers/i2c/chips/fscher.c b/drivers/i2c/chips/fscher.c
index 18e33ac59d0..da411741c2c 100644
--- a/drivers/i2c/chips/fscher.c
+++ b/drivers/i2c/chips/fscher.c
@@ -26,7 +26,6 @@
* and Philip Edelbrock <phil@netroedge.com>
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -157,8 +156,8 @@ struct fscher_data {
#define sysfs_r(kind, sub, offset, reg) \
static ssize_t show_##kind##sub (struct fscher_data *, char *, int); \
-static ssize_t show_##kind##offset##sub (struct device *, char *); \
-static ssize_t show_##kind##offset##sub (struct device *dev, char *buf) \
+static ssize_t show_##kind##offset##sub (struct device *, struct device_attribute *attr, char *); \
+static ssize_t show_##kind##offset##sub (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct fscher_data *data = fscher_update_device(dev); \
return show_##kind##sub(data, buf, (offset)); \
@@ -166,8 +165,8 @@ static ssize_t show_##kind##offset##sub (struct device *dev, char *buf) \
#define sysfs_w(kind, sub, offset, reg) \
static ssize_t set_##kind##sub (struct i2c_client *, struct fscher_data *, const char *, size_t, int, int); \
-static ssize_t set_##kind##offset##sub (struct device *, const char *, size_t); \
-static ssize_t set_##kind##offset##sub (struct device *dev, const char *buf, size_t count) \
+static ssize_t set_##kind##offset##sub (struct device *, struct device_attribute *attr, const char *, size_t); \
+static ssize_t set_##kind##offset##sub (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct fscher_data *data = i2c_get_clientdata(client); \
diff --git a/drivers/i2c/chips/fscpos.c b/drivers/i2c/chips/fscpos.c
index 2cac79145c7..3beaa6191ef 100644
--- a/drivers/i2c/chips/fscpos.c
+++ b/drivers/i2c/chips/fscpos.c
@@ -245,19 +245,19 @@ static void reset_fan_alarm(struct i2c_client *client, int nr)
/* Volts */
#define VOLT_FROM_REG(val, mult) ((val) * (mult) / 255)
-static ssize_t show_volt_12(struct device *dev, char *buf)
+static ssize_t show_volt_12(struct device *dev, struct device_attribute *attr, char *buf)
{
struct fscpos_data *data = fscpos_update_device(dev);
return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[0], 14200));
}
-static ssize_t show_volt_5(struct device *dev, char *buf)
+static ssize_t show_volt_5(struct device *dev, struct device_attribute *attr, char *buf)
{
struct fscpos_data *data = fscpos_update_device(dev);
return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[1], 6600));
}
-static ssize_t show_volt_batt(struct device *dev, char *buf)
+static ssize_t show_volt_batt(struct device *dev, struct device_attribute *attr, char *buf)
{
struct fscpos_data *data = fscpos_update_device(dev);
return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[2], 3300));
@@ -327,7 +327,7 @@ static ssize_t set_wdog_preset(struct i2c_client *client, struct fscpos_data
}
/* Event */
-static ssize_t show_event(struct device *dev, char *buf)
+static ssize_t show_event(struct device *dev, struct device_attribute *attr, char *buf)
{
/* bits 5..7 reserved => mask with 0x1f */
struct fscpos_data *data = fscpos_update_device(dev);
@@ -338,14 +338,14 @@ static ssize_t show_event(struct device *dev, char *buf)
* Sysfs stuff
*/
#define create_getter(kind, sub) \
- static ssize_t sysfs_show_##kind##sub(struct device *dev, char *buf) \
+ static ssize_t sysfs_show_##kind##sub(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct fscpos_data *data = fscpos_update_device(dev); \
return show_##kind##sub(data, buf); \
}
#define create_getter_n(kind, offset, sub) \
- static ssize_t sysfs_show_##kind##offset##sub(struct device *dev, char\
+ static ssize_t sysfs_show_##kind##offset##sub(struct device *dev, struct device_attribute *attr, char\
*buf) \
{ \
struct fscpos_data *data = fscpos_update_device(dev); \
@@ -353,7 +353,7 @@ static ssize_t show_event(struct device *dev, char *buf)
}
#define create_setter(kind, sub, reg) \
- static ssize_t sysfs_set_##kind##sub (struct device *dev, const char \
+ static ssize_t sysfs_set_##kind##sub (struct device *dev, struct device_attribute *attr, const char \
*buf, size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
@@ -362,7 +362,7 @@ static ssize_t show_event(struct device *dev, char *buf)
}
#define create_setter_n(kind, offset, sub, reg) \
- static ssize_t sysfs_set_##kind##offset##sub (struct device *dev, \
+ static ssize_t sysfs_set_##kind##offset##sub (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
diff --git a/drivers/i2c/chips/gl518sm.c b/drivers/i2c/chips/gl518sm.c
index c82d6ce2120..6bedf729dcf 100644
--- a/drivers/i2c/chips/gl518sm.c
+++ b/drivers/i2c/chips/gl518sm.c
@@ -36,7 +36,6 @@
* 2004-01-31 Code review and approval. (Jean Delvare)
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -164,14 +163,14 @@ static struct i2c_driver gl518_driver = {
*/
#define show(type, suffix, value) \
-static ssize_t show_##suffix(struct device *dev, char *buf) \
+static ssize_t show_##suffix(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct gl518_data *data = gl518_update_device(dev); \
return sprintf(buf, "%d\n", type##_FROM_REG(data->value)); \
}
#define show_fan(suffix, value, index) \
-static ssize_t show_##suffix(struct device *dev, char *buf) \
+static ssize_t show_##suffix(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct gl518_data *data = gl518_update_device(dev); \
return sprintf(buf, "%d\n", FAN_FROM_REG(data->value[index], \
@@ -205,7 +204,7 @@ show(BOOL, beep_enable, beep_enable);
show(BEEP_MASK, beep_mask, beep_mask);
#define set(type, suffix, value, reg) \
-static ssize_t set_##suffix(struct device *dev, const char *buf, \
+static ssize_t set_##suffix(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
@@ -220,7 +219,7 @@ static ssize_t set_##suffix(struct device *dev, const char *buf, \
}
#define set_bits(type, suffix, value, reg, mask, shift) \
-static ssize_t set_##suffix(struct device *dev, const char *buf, \
+static ssize_t set_##suffix(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
@@ -258,7 +257,7 @@ set_high(IN, in_max3, voltage_max[3], GL518_REG_VIN3_LIMIT);
set_bits(BOOL, beep_enable, beep_enable, GL518_REG_CONF, 0x04, 2);
set(BEEP_MASK, beep_mask, beep_mask, GL518_REG_ALARM);
-static ssize_t set_fan_min1(struct device *dev, const char *buf, size_t count)
+static ssize_t set_fan_min1(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct gl518_data *data = i2c_get_clientdata(client);
@@ -284,7 +283,7 @@ static ssize_t set_fan_min1(struct device *dev, const char *buf, size_t count)
return count;
}
-static ssize_t set_fan_min2(struct device *dev, const char *buf, size_t count)
+static ssize_t set_fan_min2(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct gl518_data *data = i2c_get_clientdata(client);
diff --git a/drivers/i2c/chips/gl520sm.c b/drivers/i2c/chips/gl520sm.c
index 3fd17e46ffc..a13a504f5bf 100644
--- a/drivers/i2c/chips/gl520sm.c
+++ b/drivers/i2c/chips/gl520sm.c
@@ -148,8 +148,8 @@ struct gl520_data {
#define sysfs_r(type, n, item, reg) \
static ssize_t get_##type##item (struct gl520_data *, char *, int); \
-static ssize_t get_##type##n##item (struct device *, char *); \
-static ssize_t get_##type##n##item (struct device *dev, char *buf) \
+static ssize_t get_##type##n##item (struct device *, struct device_attribute *attr, char *); \
+static ssize_t get_##type##n##item (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct gl520_data *data = gl520_update_device(dev); \
return get_##type##item(data, buf, (n)); \
@@ -157,8 +157,8 @@ static ssize_t get_##type##n##item (struct device *dev, char *buf) \
#define sysfs_w(type, n, item, reg) \
static ssize_t set_##type##item (struct i2c_client *, struct gl520_data *, const char *, size_t, int, int); \
-static ssize_t set_##type##n##item (struct device *, const char *, size_t); \
-static ssize_t set_##type##n##item (struct device *dev, const char *buf, size_t count) \
+static ssize_t set_##type##n##item (struct device *, struct device_attribute *attr, const char *, size_t); \
+static ssize_t set_##type##n##item (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct gl520_data *data = i2c_get_clientdata(client); \
diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c
index 7f29a8aff16..354a2629567 100644
--- a/drivers/i2c/chips/isp1301_omap.c
+++ b/drivers/i2c/chips/isp1301_omap.c
@@ -145,7 +145,6 @@ static inline void notresponding(struct isp1301 *isp)
static unsigned short normal_i2c[] = {
ISP_BASE, ISP_BASE + 1,
I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
I2C_CLIENT_INSMOD;
diff --git a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c
index cf7e6898754..db20c9e4739 100644
--- a/drivers/i2c/chips/it87.c
+++ b/drivers/i2c/chips/it87.c
@@ -31,7 +31,6 @@
type at module load time.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -39,6 +38,7 @@
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
#include <linux/i2c-vid.h>
+#include <linux/hwmon-sysfs.h>
#include <asm/io.h>
@@ -173,8 +173,6 @@ static inline u8 FAN_TO_REG(long rpm, int div)
((val)+500)/1000),-128,127))
#define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*1000)
-#define ALARMS_FROM_REG(val) (val)
-
#define PWM_TO_REG(val) ((val) >> 1)
#define PWM_FROM_REG(val) (((val)&0x7f) << 1)
@@ -241,27 +239,42 @@ static struct i2c_driver it87_driver = {
.detach_client = it87_detach_client,
};
-static ssize_t show_in(struct device *dev, char *buf, int nr)
+static ssize_t show_in(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+
struct it87_data *data = it87_update_device(dev);
return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr]));
}
-static ssize_t show_in_min(struct device *dev, char *buf, int nr)
+static ssize_t show_in_min(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+
struct it87_data *data = it87_update_device(dev);
return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr]));
}
-static ssize_t show_in_max(struct device *dev, char *buf, int nr)
+static ssize_t show_in_max(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+
struct it87_data *data = it87_update_device(dev);
return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr]));
}
-static ssize_t set_in_min(struct device *dev, const char *buf,
- size_t count, int nr)
+static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10);
@@ -273,9 +286,12 @@ static ssize_t set_in_min(struct device *dev, const char *buf,
up(&data->update_lock);
return count;
}
-static ssize_t set_in_max(struct device *dev, const char *buf,
- size_t count, int nr)
+static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10);
@@ -289,38 +305,14 @@ static ssize_t set_in_max(struct device *dev, const char *buf,
}
#define show_in_offset(offset) \
-static ssize_t \
- show_in##offset (struct device *dev, char *buf) \
-{ \
- return show_in(dev, buf, offset); \
-} \
-static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL);
+static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \
+ show_in, NULL, offset);
#define limit_in_offset(offset) \
-static ssize_t \
- show_in##offset##_min (struct device *dev, char *buf) \
-{ \
- return show_in_min(dev, buf, offset); \
-} \
-static ssize_t \
- show_in##offset##_max (struct device *dev, char *buf) \
-{ \
- return show_in_max(dev, buf, offset); \
-} \
-static ssize_t set_in##offset##_min (struct device *dev, \
- const char *buf, size_t count) \
-{ \
- return set_in_min(dev, buf, count, offset); \
-} \
-static ssize_t set_in##offset##_max (struct device *dev, \
- const char *buf, size_t count) \
-{ \
- return set_in_max(dev, buf, count, offset); \
-} \
-static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
- show_in##offset##_min, set_in##offset##_min); \
-static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
- show_in##offset##_max, set_in##offset##_max);
+static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
+ show_in_min, set_in_min, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
+ show_in_max, set_in_max, offset);
show_in_offset(0);
limit_in_offset(0);
@@ -341,24 +333,39 @@ limit_in_offset(7);
show_in_offset(8);
/* 3 temperatures */
-static ssize_t show_temp(struct device *dev, char *buf, int nr)
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+
struct it87_data *data = it87_update_device(dev);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr]));
}
-static ssize_t show_temp_max(struct device *dev, char *buf, int nr)
+static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+
struct it87_data *data = it87_update_device(dev);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_high[nr]));
}
-static ssize_t show_temp_min(struct device *dev, char *buf, int nr)
+static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+
struct it87_data *data = it87_update_device(dev);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_low[nr]));
}
-static ssize_t set_temp_max(struct device *dev, const char *buf,
- size_t count, int nr)
+static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
@@ -369,9 +376,12 @@ static ssize_t set_temp_max(struct device *dev, const char *buf,
up(&data->update_lock);
return count;
}
-static ssize_t set_temp_min(struct device *dev, const char *buf,
- size_t count, int nr)
+static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
@@ -383,42 +393,23 @@ static ssize_t set_temp_min(struct device *dev, const char *buf,
return count;
}
#define show_temp_offset(offset) \
-static ssize_t show_temp_##offset (struct device *dev, char *buf) \
-{ \
- return show_temp(dev, buf, offset - 1); \
-} \
-static ssize_t \
-show_temp_##offset##_max (struct device *dev, char *buf) \
-{ \
- return show_temp_max(dev, buf, offset - 1); \
-} \
-static ssize_t \
-show_temp_##offset##_min (struct device *dev, char *buf) \
-{ \
- return show_temp_min(dev, buf, offset - 1); \
-} \
-static ssize_t set_temp_##offset##_max (struct device *dev, \
- const char *buf, size_t count) \
-{ \
- return set_temp_max(dev, buf, count, offset - 1); \
-} \
-static ssize_t set_temp_##offset##_min (struct device *dev, \
- const char *buf, size_t count) \
-{ \
- return set_temp_min(dev, buf, count, offset - 1); \
-} \
-static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL); \
-static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \
- show_temp_##offset##_max, set_temp_##offset##_max); \
-static DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \
- show_temp_##offset##_min, set_temp_##offset##_min);
+static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
+ show_temp, NULL, offset - 1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \
+ show_temp_max, set_temp_max, offset - 1); \
+static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \
+ show_temp_min, set_temp_min, offset - 1);
show_temp_offset(1);
show_temp_offset(2);
show_temp_offset(3);
-static ssize_t show_sensor(struct device *dev, char *buf, int nr)
+static ssize_t show_sensor(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+
struct it87_data *data = it87_update_device(dev);
u8 reg = data->sensor; /* In case the value is updated while we use it */
@@ -428,9 +419,12 @@ static ssize_t show_sensor(struct device *dev, char *buf, int nr)
return sprintf(buf, "2\n"); /* thermistor */
return sprintf(buf, "0\n"); /* disabled */
}
-static ssize_t set_sensor(struct device *dev, const char *buf,
- size_t count, int nr)
+static ssize_t set_sensor(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
@@ -453,53 +447,67 @@ static ssize_t set_sensor(struct device *dev, const char *buf,
return count;
}
#define show_sensor_offset(offset) \
-static ssize_t show_sensor_##offset (struct device *dev, char *buf) \
-{ \
- return show_sensor(dev, buf, offset - 1); \
-} \
-static ssize_t set_sensor_##offset (struct device *dev, \
- const char *buf, size_t count) \
-{ \
- return set_sensor(dev, buf, count, offset - 1); \
-} \
-static DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, \
- show_sensor_##offset, set_sensor_##offset);
+static SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, \
+ show_sensor, set_sensor, offset - 1);
show_sensor_offset(1);
show_sensor_offset(2);
show_sensor_offset(3);
/* 3 Fans */
-static ssize_t show_fan(struct device *dev, char *buf, int nr)
+static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+
struct it87_data *data = it87_update_device(dev);
return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr],
DIV_FROM_REG(data->fan_div[nr])));
}
-static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
+static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+
struct it87_data *data = it87_update_device(dev);
return sprintf(buf,"%d\n",
FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])));
}
-static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
+static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+
struct it87_data *data = it87_update_device(dev);
return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
}
-static ssize_t show_pwm_enable(struct device *dev, char *buf, int nr)
+static ssize_t show_pwm_enable(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+
struct it87_data *data = it87_update_device(dev);
return sprintf(buf,"%d\n", (data->fan_main_ctrl & (1 << nr)) ? 1 : 0);
}
-static ssize_t show_pwm(struct device *dev, char *buf, int nr)
+static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+
struct it87_data *data = it87_update_device(dev);
return sprintf(buf,"%d\n", data->manual_pwm_ctl[nr]);
}
-static ssize_t set_fan_min(struct device *dev, const char *buf,
- size_t count, int nr)
+static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
@@ -510,9 +518,12 @@ static ssize_t set_fan_min(struct device *dev, const char *buf,
up(&data->update_lock);
return count;
}
-static ssize_t set_fan_div(struct device *dev, const char *buf,
- size_t count, int nr)
+static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
@@ -550,9 +561,12 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
up(&data->update_lock);
return count;
}
-static ssize_t set_pwm_enable(struct device *dev, const char *buf,
- size_t count, int nr)
+static ssize_t set_pwm_enable(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
@@ -581,9 +595,12 @@ static ssize_t set_pwm_enable(struct device *dev, const char *buf,
up(&data->update_lock);
return count;
}
-static ssize_t set_pwm(struct device *dev, const char *buf,
- size_t count, int nr)
+static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
@@ -599,85 +616,44 @@ static ssize_t set_pwm(struct device *dev, const char *buf,
return count;
}
-#define show_fan_offset(offset) \
-static ssize_t show_fan_##offset (struct device *dev, char *buf) \
-{ \
- return show_fan(dev, buf, offset - 1); \
-} \
-static ssize_t show_fan_##offset##_min (struct device *dev, char *buf) \
-{ \
- return show_fan_min(dev, buf, offset - 1); \
-} \
-static ssize_t show_fan_##offset##_div (struct device *dev, char *buf) \
-{ \
- return show_fan_div(dev, buf, offset - 1); \
-} \
-static ssize_t set_fan_##offset##_min (struct device *dev, \
- const char *buf, size_t count) \
-{ \
- return set_fan_min(dev, buf, count, offset - 1); \
-} \
-static ssize_t set_fan_##offset##_div (struct device *dev, \
- const char *buf, size_t count) \
-{ \
- return set_fan_div(dev, buf, count, offset - 1); \
-} \
-static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL); \
-static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
- show_fan_##offset##_min, set_fan_##offset##_min); \
-static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
- show_fan_##offset##_div, set_fan_##offset##_div);
+#define show_fan_offset(offset) \
+static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
+ show_fan, NULL, offset - 1); \
+static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
+ show_fan_min, set_fan_min, offset - 1); \
+static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
+ show_fan_div, set_fan_div, offset - 1);
show_fan_offset(1);
show_fan_offset(2);
show_fan_offset(3);
#define show_pwm_offset(offset) \
-static ssize_t show_pwm##offset##_enable (struct device *dev, \
- char *buf) \
-{ \
- return show_pwm_enable(dev, buf, offset - 1); \
-} \
-static ssize_t show_pwm##offset (struct device *dev, char *buf) \
-{ \
- return show_pwm(dev, buf, offset - 1); \
-} \
-static ssize_t set_pwm##offset##_enable (struct device *dev, \
- const char *buf, size_t count) \
-{ \
- return set_pwm_enable(dev, buf, count, offset - 1); \
-} \
-static ssize_t set_pwm##offset (struct device *dev, \
- const char *buf, size_t count) \
-{ \
- return set_pwm(dev, buf, count, offset - 1); \
-} \
-static DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \
- show_pwm##offset##_enable, \
- set_pwm##offset##_enable); \
-static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \
- show_pwm##offset , set_pwm##offset );
+static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \
+ show_pwm_enable, set_pwm_enable, offset - 1); \
+static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \
+ show_pwm, set_pwm, offset - 1);
show_pwm_offset(1);
show_pwm_offset(2);
show_pwm_offset(3);
/* Alarms */
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
{
struct it87_data *data = it87_update_device(dev);
- return sprintf(buf,"%d\n", ALARMS_FROM_REG(data->alarms));
+ return sprintf(buf, "%u\n", data->alarms);
}
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
static ssize_t
-show_vrm_reg(struct device *dev, char *buf)
+show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
{
struct it87_data *data = it87_update_device(dev);
return sprintf(buf, "%ld\n", (long) data->vrm);
}
static ssize_t
-store_vrm_reg(struct device *dev, const char *buf, size_t count)
+store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct it87_data *data = i2c_get_clientdata(client);
@@ -693,7 +669,7 @@ static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
device_create_file(&client->dev, &dev_attr_vrm)
static ssize_t
-show_vid_reg(struct device *dev, char *buf)
+show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
{
struct it87_data *data = it87_update_device(dev);
return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
@@ -864,60 +840,60 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
it87_init_client(new_client, data);
/* Register sysfs hooks */
- device_create_file(&new_client->dev, &dev_attr_in0_input);
- device_create_file(&new_client->dev, &dev_attr_in1_input);
- device_create_file(&new_client->dev, &dev_attr_in2_input);
- device_create_file(&new_client->dev, &dev_attr_in3_input);
- device_create_file(&new_client->dev, &dev_attr_in4_input);
- device_create_file(&new_client->dev, &dev_attr_in5_input);
- device_create_file(&new_client->dev, &dev_attr_in6_input);
- device_create_file(&new_client->dev, &dev_attr_in7_input);
- device_create_file(&new_client->dev, &dev_attr_in8_input);
- device_create_file(&new_client->dev, &dev_attr_in0_min);
- device_create_file(&new_client->dev, &dev_attr_in1_min);
- device_create_file(&new_client->dev, &dev_attr_in2_min);
- device_create_file(&new_client->dev, &dev_attr_in3_min);
- device_create_file(&new_client->dev, &dev_attr_in4_min);
- device_create_file(&new_client->dev, &dev_attr_in5_min);
- device_create_file(&new_client->dev, &dev_attr_in6_min);
- device_create_file(&new_client->dev, &dev_attr_in7_min);
- device_create_file(&new_client->dev, &dev_attr_in0_max);
- device_create_file(&new_client->dev, &dev_attr_in1_max);
- device_create_file(&new_client->dev, &dev_attr_in2_max);
- device_create_file(&new_client->dev, &dev_attr_in3_max);
- device_create_file(&new_client->dev, &dev_attr_in4_max);
- device_create_file(&new_client->dev, &dev_attr_in5_max);
- device_create_file(&new_client->dev, &dev_attr_in6_max);
- device_create_file(&new_client->dev, &dev_attr_in7_max);
- device_create_file(&new_client->dev, &dev_attr_temp1_input);
- device_create_file(&new_client->dev, &dev_attr_temp2_input);
- device_create_file(&new_client->dev, &dev_attr_temp3_input);
- device_create_file(&new_client->dev, &dev_attr_temp1_max);
- device_create_file(&new_client->dev, &dev_attr_temp2_max);
- device_create_file(&new_client->dev, &dev_attr_temp3_max);
- device_create_file(&new_client->dev, &dev_attr_temp1_min);
- device_create_file(&new_client->dev, &dev_attr_temp2_min);
- device_create_file(&new_client->dev, &dev_attr_temp3_min);
- device_create_file(&new_client->dev, &dev_attr_temp1_type);
- device_create_file(&new_client->dev, &dev_attr_temp2_type);
- device_create_file(&new_client->dev, &dev_attr_temp3_type);
- device_create_file(&new_client->dev, &dev_attr_fan1_input);
- device_create_file(&new_client->dev, &dev_attr_fan2_input);
- device_create_file(&new_client->dev, &dev_attr_fan3_input);
- device_create_file(&new_client->dev, &dev_attr_fan1_min);
- device_create_file(&new_client->dev, &dev_attr_fan2_min);
- device_create_file(&new_client->dev, &dev_attr_fan3_min);
- device_create_file(&new_client->dev, &dev_attr_fan1_div);
- device_create_file(&new_client->dev, &dev_attr_fan2_div);
- device_create_file(&new_client->dev, &dev_attr_fan3_div);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in3_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in4_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in5_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in6_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in7_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in8_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in1_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in2_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in3_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in4_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in5_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in6_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in7_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in1_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in2_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in3_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in4_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in5_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in6_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_in7_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp1_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp2_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp3_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp1_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp2_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp3_max.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp1_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp2_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp3_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp1_type.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp2_type.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_temp3_type.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan1_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan2_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan3_input.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan1_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan2_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan3_min.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan1_div.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan2_div.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_fan3_div.dev_attr);
device_create_file(&new_client->dev, &dev_attr_alarms);
if (enable_pwm_interface) {
- device_create_file(&new_client->dev, &dev_attr_pwm1_enable);
- device_create_file(&new_client->dev, &dev_attr_pwm2_enable);
- device_create_file(&new_client->dev, &dev_attr_pwm3_enable);
- device_create_file(&new_client->dev, &dev_attr_pwm1);
- device_create_file(&new_client->dev, &dev_attr_pwm2);
- device_create_file(&new_client->dev, &dev_attr_pwm3);
+ device_create_file(&new_client->dev, &sensor_dev_attr_pwm1_enable.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_pwm2_enable.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_pwm3_enable.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_pwm1.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_pwm2.dev_attr);
+ device_create_file(&new_client->dev, &sensor_dev_attr_pwm3.dev_attr);
}
if (data->type == it8712) {
@@ -954,7 +930,7 @@ static int it87_detach_client(struct i2c_client *client)
return 0;
}
-/* The SMBus locks itself, but ISA access must be locked explicitely!
+/* The SMBus locks itself, but ISA access must be locked explicitly!
We don't want to lock the whole ISA bus, so we lock each client
separately.
We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
@@ -974,7 +950,7 @@ static int it87_read_value(struct i2c_client *client, u8 reg)
return i2c_smbus_read_byte_data(client, reg);
}
-/* The SMBus locks itself, but ISA access muse be locked explicitely!
+/* The SMBus locks itself, but ISA access muse be locked explicitly!
We don't want to lock the whole ISA bus, so we lock each client
separately.
We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
diff --git a/drivers/i2c/chips/lm63.c b/drivers/i2c/chips/lm63.c
index 14cc5af0373..7c6f9ea5a25 100644
--- a/drivers/i2c/chips/lm63.c
+++ b/drivers/i2c/chips/lm63.c
@@ -1,7 +1,7 @@
/*
* lm63.c - driver for the National Semiconductor LM63 temperature sensor
* with integrated fan control
- * Copyright (C) 2004 Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2004-2005 Jean Delvare <khali@linux-fr.org>
* Based on the lm90 driver.
*
* The LM63 is a sensor chip made by National Semiconductor. It measures
@@ -37,13 +37,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
+#include <linux/hwmon-sysfs.h>
/*
* Addresses to scan
@@ -99,9 +99,9 @@ SENSORS_INSMOD_1(lm63);
* Conversions and various macros
* For tachometer counts, the LM63 uses 16-bit values.
* For local temperature and high limit, remote critical limit and hysteresis
- * value, it uses signed 8-bit values with LSB = 1 degree Celcius.
+ * value, it uses signed 8-bit values with LSB = 1 degree Celsius.
* For remote temperature, low and high limits, it uses signed 11-bit values
- * with LSB = 0.125 degree Celcius, left-justified in 16-bit registers.
+ * with LSB = 0.125 degree Celsius, left-justified in 16-bit registers.
*/
#define FAN_FROM_REG(reg) ((reg) == 0xFFFC || (reg) == 0 ? 0 : \
@@ -158,16 +158,16 @@ struct lm63_data {
/* registers values */
u8 config, config_fan;
- u16 fan1_input;
- u16 fan1_low;
+ u16 fan[2]; /* 0: input
+ 1: low limit */
u8 pwm1_freq;
u8 pwm1_value;
- s8 temp1_input;
- s8 temp1_high;
- s16 temp2_input;
- s16 temp2_high;
- s16 temp2_low;
- s8 temp2_crit;
+ s8 temp8[3]; /* 0: local input
+ 1: local high limit
+ 2: remote critical limit */
+ s16 temp11[3]; /* 0: remote input
+ 1: remote low limit
+ 2: remote high limit */
u8 temp2_crit_hyst;
u8 alarms;
};
@@ -176,33 +176,33 @@ struct lm63_data {
* Sysfs callback functions and files
*/
-#define show_fan(value) \
-static ssize_t show_##value(struct device *dev, char *buf) \
-{ \
- struct lm63_data *data = lm63_update_device(dev); \
- return sprintf(buf, "%d\n", FAN_FROM_REG(data->value)); \
+static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct lm63_data *data = lm63_update_device(dev);
+ return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[attr->index]));
}
-show_fan(fan1_input);
-show_fan(fan1_low);
-static ssize_t set_fan1_low(struct device *dev, const char *buf,
- size_t count)
+static ssize_t set_fan(struct device *dev, struct device_attribute *dummy,
+ const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm63_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock);
- data->fan1_low = FAN_TO_REG(val);
+ data->fan[1] = FAN_TO_REG(val);
i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_LSB,
- data->fan1_low & 0xFF);
+ data->fan[1] & 0xFF);
i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_MSB,
- data->fan1_low >> 8);
+ data->fan[1] >> 8);
up(&data->update_lock);
return count;
}
-static ssize_t show_pwm1(struct device *dev, char *buf)
+static ssize_t show_pwm1(struct device *dev, struct device_attribute *dummy,
+ char *buf)
{
struct lm63_data *data = lm63_update_device(dev);
return sprintf(buf, "%d\n", data->pwm1_value >= 2 * data->pwm1_freq ?
@@ -210,7 +210,8 @@ static ssize_t show_pwm1(struct device *dev, char *buf)
(2 * data->pwm1_freq));
}
-static ssize_t set_pwm1(struct device *dev, const char *buf, size_t count)
+static ssize_t set_pwm1(struct device *dev, struct device_attribute *dummy,
+ const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm63_data *data = i2c_get_clientdata(client);
@@ -229,77 +230,83 @@ static ssize_t set_pwm1(struct device *dev, const char *buf, size_t count)
return count;
}
-static ssize_t show_pwm1_enable(struct device *dev, char *buf)
+static ssize_t show_pwm1_enable(struct device *dev, struct device_attribute *dummy,
+ char *buf)
{
struct lm63_data *data = lm63_update_device(dev);
return sprintf(buf, "%d\n", data->config_fan & 0x20 ? 1 : 2);
}
-#define show_temp8(value) \
-static ssize_t show_##value(struct device *dev, char *buf) \
-{ \
- struct lm63_data *data = lm63_update_device(dev); \
- return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->value)); \
+static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct lm63_data *data = lm63_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp8[attr->index]));
}
-#define show_temp11(value) \
-static ssize_t show_##value(struct device *dev, char *buf) \
-{ \
- struct lm63_data *data = lm63_update_device(dev); \
- return sprintf(buf, "%d\n", TEMP11_FROM_REG(data->value)); \
+
+static ssize_t set_temp8(struct device *dev, struct device_attribute *dummy,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm63_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+
+ down(&data->update_lock);
+ data->temp8[1] = TEMP8_TO_REG(val);
+ i2c_smbus_write_byte_data(client, LM63_REG_LOCAL_HIGH, data->temp8[1]);
+ up(&data->update_lock);
+ return count;
}
-show_temp8(temp1_input);
-show_temp8(temp1_high);
-show_temp11(temp2_input);
-show_temp11(temp2_high);
-show_temp11(temp2_low);
-show_temp8(temp2_crit);
-
-#define set_temp8(value, reg) \
-static ssize_t set_##value(struct device *dev, const char *buf, \
- size_t count) \
-{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct lm63_data *data = i2c_get_clientdata(client); \
- long val = simple_strtol(buf, NULL, 10); \
- \
- down(&data->update_lock); \
- data->value = TEMP8_TO_REG(val); \
- i2c_smbus_write_byte_data(client, reg, data->value); \
- up(&data->update_lock); \
- return count; \
+
+static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct lm63_data *data = lm63_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP11_FROM_REG(data->temp11[attr->index]));
}
-#define set_temp11(value, reg_msb, reg_lsb) \
-static ssize_t set_##value(struct device *dev, const char *buf, \
- size_t count) \
-{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct lm63_data *data = i2c_get_clientdata(client); \
- long val = simple_strtol(buf, NULL, 10); \
- \
- down(&data->update_lock); \
- data->value = TEMP11_TO_REG(val); \
- i2c_smbus_write_byte_data(client, reg_msb, data->value >> 8); \
- i2c_smbus_write_byte_data(client, reg_lsb, data->value & 0xff); \
- up(&data->update_lock); \
- return count; \
+
+static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ static const u8 reg[4] = {
+ LM63_REG_REMOTE_LOW_MSB,
+ LM63_REG_REMOTE_LOW_LSB,
+ LM63_REG_REMOTE_HIGH_MSB,
+ LM63_REG_REMOTE_HIGH_LSB,
+ };
+
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm63_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+ int nr = attr->index;
+
+ down(&data->update_lock);
+ data->temp11[nr] = TEMP11_TO_REG(val);
+ i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2],
+ data->temp11[nr] >> 8);
+ i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1],
+ data->temp11[nr] & 0xff);
+ up(&data->update_lock);
+ return count;
}
-set_temp8(temp1_high, LM63_REG_LOCAL_HIGH);
-set_temp11(temp2_high, LM63_REG_REMOTE_HIGH_MSB, LM63_REG_REMOTE_HIGH_LSB);
-set_temp11(temp2_low, LM63_REG_REMOTE_LOW_MSB, LM63_REG_REMOTE_LOW_LSB);
/* Hysteresis register holds a relative value, while we want to present
an absolute to user-space */
-static ssize_t show_temp2_crit_hyst(struct device *dev, char *buf)
+static ssize_t show_temp2_crit_hyst(struct device *dev, struct device_attribute *dummy,
+ char *buf)
{
struct lm63_data *data = lm63_update_device(dev);
- return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp2_crit)
+ return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp8[2])
- TEMP8_FROM_REG(data->temp2_crit_hyst));
}
/* And now the other way around, user-space provides an absolute
hysteresis value and we have to store a relative one */
-static ssize_t set_temp2_crit_hyst(struct device *dev, const char *buf,
- size_t count)
+static ssize_t set_temp2_crit_hyst(struct device *dev, struct device_attribute *dummy,
+ const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm63_data *data = i2c_get_clientdata(client);
@@ -307,36 +314,37 @@ static ssize_t set_temp2_crit_hyst(struct device *dev, const char *buf,
long hyst;
down(&data->update_lock);
- hyst = TEMP8_FROM_REG(data->temp2_crit) - val;
+ hyst = TEMP8_FROM_REG(data->temp8[2]) - val;
i2c_smbus_write_byte_data(client, LM63_REG_REMOTE_TCRIT_HYST,
HYST_TO_REG(hyst));
up(&data->update_lock);
return count;
}
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy,
+ char *buf)
{
struct lm63_data *data = lm63_update_device(dev);
return sprintf(buf, "%u\n", data->alarms);
}
-static DEVICE_ATTR(fan1_input, S_IRUGO, show_fan1_input, NULL);
-static DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan1_low,
- set_fan1_low);
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan,
+ set_fan, 1);
static DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm1, set_pwm1);
static DEVICE_ATTR(pwm1_enable, S_IRUGO, show_pwm1_enable, NULL);
-static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1_input, NULL);
-static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp1_high,
- set_temp1_high);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp8, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp8,
+ set_temp8, 1);
-static DEVICE_ATTR(temp2_input, S_IRUGO, show_temp2_input, NULL);
-static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp2_low,
- set_temp2_low);
-static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp2_high,
- set_temp2_high);
-static DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp2_crit, NULL);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11,
+ set_temp11, 1);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp11,
+ set_temp11, 2);
+static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp8, NULL, 2);
static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst,
set_temp2_crit_hyst);
@@ -430,17 +438,25 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind)
/* Register sysfs hooks */
if (data->config & 0x04) { /* tachometer enabled */
- device_create_file(&new_client->dev, &dev_attr_fan1_input);
- device_create_file(&new_client->dev, &dev_attr_fan1_min);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_fan1_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_fan1_min.dev_attr);
}
device_create_file(&new_client->dev, &dev_attr_pwm1);
device_create_file(&new_client->dev, &dev_attr_pwm1_enable);
- device_create_file(&new_client->dev, &dev_attr_temp1_input);
- device_create_file(&new_client->dev, &dev_attr_temp2_input);
- device_create_file(&new_client->dev, &dev_attr_temp2_min);
- device_create_file(&new_client->dev, &dev_attr_temp1_max);
- device_create_file(&new_client->dev, &dev_attr_temp2_max);
- device_create_file(&new_client->dev, &dev_attr_temp2_crit);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp1_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp2_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp2_min.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp1_max.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp2_max.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp2_crit.dev_attr);
device_create_file(&new_client->dev, &dev_attr_temp2_crit_hyst);
device_create_file(&new_client->dev, &dev_attr_alarms);
@@ -511,14 +527,14 @@ static struct lm63_data *lm63_update_device(struct device *dev)
if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
if (data->config & 0x04) { /* tachometer enabled */
/* order matters for fan1_input */
- data->fan1_input = i2c_smbus_read_byte_data(client,
- LM63_REG_TACH_COUNT_LSB) & 0xFC;
- data->fan1_input |= i2c_smbus_read_byte_data(client,
- LM63_REG_TACH_COUNT_MSB) << 8;
- data->fan1_low = (i2c_smbus_read_byte_data(client,
- LM63_REG_TACH_LIMIT_LSB) & 0xFC)
- | (i2c_smbus_read_byte_data(client,
- LM63_REG_TACH_LIMIT_MSB) << 8);
+ data->fan[0] = i2c_smbus_read_byte_data(client,
+ LM63_REG_TACH_COUNT_LSB) & 0xFC;
+ data->fan[0] |= i2c_smbus_read_byte_data(client,
+ LM63_REG_TACH_COUNT_MSB) << 8;
+ data->fan[1] = (i2c_smbus_read_byte_data(client,
+ LM63_REG_TACH_LIMIT_LSB) & 0xFC)
+ | (i2c_smbus_read_byte_data(client,
+ LM63_REG_TACH_LIMIT_MSB) << 8);
}
data->pwm1_freq = i2c_smbus_read_byte_data(client,
@@ -528,26 +544,26 @@ static struct lm63_data *lm63_update_device(struct device *dev)
data->pwm1_value = i2c_smbus_read_byte_data(client,
LM63_REG_PWM_VALUE);
- data->temp1_input = i2c_smbus_read_byte_data(client,
- LM63_REG_LOCAL_TEMP);
- data->temp1_high = i2c_smbus_read_byte_data(client,
- LM63_REG_LOCAL_HIGH);
+ data->temp8[0] = i2c_smbus_read_byte_data(client,
+ LM63_REG_LOCAL_TEMP);
+ data->temp8[1] = i2c_smbus_read_byte_data(client,
+ LM63_REG_LOCAL_HIGH);
/* order matters for temp2_input */
- data->temp2_input = i2c_smbus_read_byte_data(client,
- LM63_REG_REMOTE_TEMP_MSB) << 8;
- data->temp2_input |= i2c_smbus_read_byte_data(client,
- LM63_REG_REMOTE_TEMP_LSB);
- data->temp2_high = (i2c_smbus_read_byte_data(client,
- LM63_REG_REMOTE_HIGH_MSB) << 8)
- | i2c_smbus_read_byte_data(client,
- LM63_REG_REMOTE_HIGH_LSB);
- data->temp2_low = (i2c_smbus_read_byte_data(client,
+ data->temp11[0] = i2c_smbus_read_byte_data(client,
+ LM63_REG_REMOTE_TEMP_MSB) << 8;
+ data->temp11[0] |= i2c_smbus_read_byte_data(client,
+ LM63_REG_REMOTE_TEMP_LSB);
+ data->temp11[1] = (i2c_smbus_read_byte_data(client,
LM63_REG_REMOTE_LOW_MSB) << 8)
| i2c_smbus_read_byte_data(client,
LM63_REG_REMOTE_LOW_LSB);
- data->temp2_crit = i2c_smbus_read_byte_data(client,
- LM63_REG_REMOTE_TCRIT);
+ data->temp11[2] = (i2c_smbus_read_byte_data(client,
+ LM63_REG_REMOTE_HIGH_MSB) << 8)
+ | i2c_smbus_read_byte_data(client,
+ LM63_REG_REMOTE_HIGH_LSB);
+ data->temp8[2] = i2c_smbus_read_byte_data(client,
+ LM63_REG_REMOTE_TCRIT);
data->temp2_crit_hyst = i2c_smbus_read_byte_data(client,
LM63_REG_REMOTE_TCRIT_HYST);
diff --git a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c
index 0e86cc89398..5be164ed278 100644
--- a/drivers/i2c/chips/lm75.c
+++ b/drivers/i2c/chips/lm75.c
@@ -18,7 +18,6 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -75,7 +74,7 @@ static struct i2c_driver lm75_driver = {
};
#define show(value) \
-static ssize_t show_##value(struct device *dev, char *buf) \
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct lm75_data *data = lm75_update_device(dev); \
return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->value)); \
@@ -85,7 +84,7 @@ show(temp_hyst);
show(temp_input);
#define set(value, reg) \
-static ssize_t set_##value(struct device *dev, const char *buf, size_t count) \
+static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct lm75_data *data = i2c_get_clientdata(client); \
diff --git a/drivers/i2c/chips/lm77.c b/drivers/i2c/chips/lm77.c
index f56b7a37de7..b98f4495299 100644
--- a/drivers/i2c/chips/lm77.c
+++ b/drivers/i2c/chips/lm77.c
@@ -25,7 +25,6 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -103,7 +102,7 @@ static inline int LM77_TEMP_FROM_REG(u16 reg)
/* read routines for temperature limits */
#define show(value) \
-static ssize_t show_##value(struct device *dev, char *buf) \
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct lm77_data *data = lm77_update_device(dev); \
return sprintf(buf, "%d\n", data->value); \
@@ -116,17 +115,17 @@ show(temp_max);
show(alarms);
/* read routines for hysteresis values */
-static ssize_t show_temp_crit_hyst(struct device *dev, char *buf)
+static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm77_data *data = lm77_update_device(dev);
return sprintf(buf, "%d\n", data->temp_crit - data->temp_hyst);
}
-static ssize_t show_temp_min_hyst(struct device *dev, char *buf)
+static ssize_t show_temp_min_hyst(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm77_data *data = lm77_update_device(dev);
return sprintf(buf, "%d\n", data->temp_min + data->temp_hyst);
}
-static ssize_t show_temp_max_hyst(struct device *dev, char *buf)
+static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm77_data *data = lm77_update_device(dev);
return sprintf(buf, "%d\n", data->temp_max - data->temp_hyst);
@@ -134,7 +133,7 @@ static ssize_t show_temp_max_hyst(struct device *dev, char *buf)
/* write routines */
#define set(value, reg) \
-static ssize_t set_##value(struct device *dev, const char *buf, size_t count) \
+static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct lm77_data *data = i2c_get_clientdata(client); \
@@ -152,7 +151,7 @@ set(temp_max, LM77_REG_TEMP_MAX);
/* hysteresis is stored as a relative value on the chip, so it has to be
converted first */
-static ssize_t set_temp_crit_hyst(struct device *dev, const char *buf, size_t count)
+static ssize_t set_temp_crit_hyst(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm77_data *data = i2c_get_clientdata(client);
@@ -167,7 +166,7 @@ static ssize_t set_temp_crit_hyst(struct device *dev, const char *buf, size_t co
}
/* preserve hysteresis when setting T_crit */
-static ssize_t set_temp_crit(struct device *dev, const char *buf, size_t count)
+static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm77_data *data = i2c_get_clientdata(client);
diff --git a/drivers/i2c/chips/lm78.c b/drivers/i2c/chips/lm78.c
index 6d52d14eb31..29241469dcb 100644
--- a/drivers/i2c/chips/lm78.c
+++ b/drivers/i2c/chips/lm78.c
@@ -18,7 +18,6 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -224,28 +223,28 @@ static ssize_t set_in_max(struct device *dev, const char *buf,
#define show_in_offset(offset) \
static ssize_t \
- show_in##offset (struct device *dev, char *buf) \
+ show_in##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_in(dev, buf, offset); \
} \
static DEVICE_ATTR(in##offset##_input, S_IRUGO, \
show_in##offset, NULL); \
static ssize_t \
- show_in##offset##_min (struct device *dev, char *buf) \
+ show_in##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_in_min(dev, buf, offset); \
} \
static ssize_t \
- show_in##offset##_max (struct device *dev, char *buf) \
+ show_in##offset##_max (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_in_max(dev, buf, offset); \
} \
-static ssize_t set_in##offset##_min (struct device *dev, \
+static ssize_t set_in##offset##_min (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_in_min(dev, buf, count, offset); \
} \
-static ssize_t set_in##offset##_max (struct device *dev, \
+static ssize_t set_in##offset##_max (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_in_max(dev, buf, count, offset); \
@@ -264,19 +263,19 @@ show_in_offset(5);
show_in_offset(6);
/* Temperature */
-static ssize_t show_temp(struct device *dev, char *buf)
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm78_data *data = lm78_update_device(dev);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp));
}
-static ssize_t show_temp_over(struct device *dev, char *buf)
+static ssize_t show_temp_over(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm78_data *data = lm78_update_device(dev);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over));
}
-static ssize_t set_temp_over(struct device *dev, const char *buf, size_t count)
+static ssize_t set_temp_over(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm78_data *data = i2c_get_clientdata(client);
@@ -289,13 +288,13 @@ static ssize_t set_temp_over(struct device *dev, const char *buf, size_t count)
return count;
}
-static ssize_t show_temp_hyst(struct device *dev, char *buf)
+static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm78_data *data = lm78_update_device(dev);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_hyst));
}
-static ssize_t set_temp_hyst(struct device *dev, const char *buf, size_t count)
+static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm78_data *data = i2c_get_clientdata(client);
@@ -398,19 +397,19 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
}
#define show_fan_offset(offset) \
-static ssize_t show_fan_##offset (struct device *dev, char *buf) \
+static ssize_t show_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_fan(dev, buf, offset - 1); \
} \
-static ssize_t show_fan_##offset##_min (struct device *dev, char *buf) \
+static ssize_t show_fan_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_fan_min(dev, buf, offset - 1); \
} \
-static ssize_t show_fan_##offset##_div (struct device *dev, char *buf) \
+static ssize_t show_fan_##offset##_div (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_fan_div(dev, buf, offset - 1); \
} \
-static ssize_t set_fan_##offset##_min (struct device *dev, \
+static ssize_t set_fan_##offset##_min (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_fan_min(dev, buf, count, offset - 1); \
@@ -419,13 +418,13 @@ static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL);\
static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
show_fan_##offset##_min, set_fan_##offset##_min);
-static ssize_t set_fan_1_div(struct device *dev, const char *buf,
+static ssize_t set_fan_1_div(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
return set_fan_div(dev, buf, count, 0) ;
}
-static ssize_t set_fan_2_div(struct device *dev, const char *buf,
+static ssize_t set_fan_2_div(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
return set_fan_div(dev, buf, count, 1) ;
@@ -443,7 +442,7 @@ static DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR,
static DEVICE_ATTR(fan3_div, S_IRUGO, show_fan_3_div, NULL);
/* VID */
-static ssize_t show_vid(struct device *dev, char *buf)
+static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm78_data *data = lm78_update_device(dev);
return sprintf(buf, "%d\n", VID_FROM_REG(data->vid));
@@ -451,7 +450,7 @@ static ssize_t show_vid(struct device *dev, char *buf)
static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
/* Alarms */
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm78_data *data = lm78_update_device(dev);
return sprintf(buf, "%u\n", data->alarms);
@@ -671,7 +670,7 @@ static int lm78_detach_client(struct i2c_client *client)
return 0;
}
-/* The SMBus locks itself, but ISA access must be locked explicitely!
+/* The SMBus locks itself, but ISA access must be locked explicitly!
We don't want to lock the whole ISA bus, so we lock each client
separately.
We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks,
@@ -690,7 +689,7 @@ static int lm78_read_value(struct i2c_client *client, u8 reg)
return i2c_smbus_read_byte_data(client, reg);
}
-/* The SMBus locks itself, but ISA access muse be locked explicitely!
+/* The SMBus locks itself, but ISA access muse be locked explicitly!
We don't want to lock the whole ISA bus, so we lock each client
separately.
We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks,
diff --git a/drivers/i2c/chips/lm80.c b/drivers/i2c/chips/lm80.c
index a72f431971b..8100595feb4 100644
--- a/drivers/i2c/chips/lm80.c
+++ b/drivers/i2c/chips/lm80.c
@@ -21,7 +21,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -156,7 +155,7 @@ static struct i2c_driver lm80_driver = {
*/
#define show_in(suffix, value) \
-static ssize_t show_in_##suffix(struct device *dev, char *buf) \
+static ssize_t show_in_##suffix(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct lm80_data *data = lm80_update_device(dev); \
return sprintf(buf, "%d\n", IN_FROM_REG(data->value)); \
@@ -184,7 +183,7 @@ show_in(input5, in[5]);
show_in(input6, in[6]);
#define set_in(suffix, value, reg) \
-static ssize_t set_in_##suffix(struct device *dev, const char *buf, \
+static ssize_t set_in_##suffix(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
@@ -213,7 +212,7 @@ set_in(max5, in_max[5], LM80_REG_IN_MAX(5));
set_in(max6, in_max[6], LM80_REG_IN_MAX(6));
#define show_fan(suffix, value, div) \
-static ssize_t show_fan_##suffix(struct device *dev, char *buf) \
+static ssize_t show_fan_##suffix(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct lm80_data *data = lm80_update_device(dev); \
return sprintf(buf, "%d\n", FAN_FROM_REG(data->value, \
@@ -225,7 +224,7 @@ show_fan(input1, fan[0], fan_div[0]);
show_fan(input2, fan[1], fan_div[1]);
#define show_fan_div(suffix, value) \
-static ssize_t show_fan_div##suffix(struct device *dev, char *buf) \
+static ssize_t show_fan_div##suffix(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct lm80_data *data = lm80_update_device(dev); \
return sprintf(buf, "%d\n", DIV_FROM_REG(data->value)); \
@@ -234,7 +233,7 @@ show_fan_div(1, fan_div[0]);
show_fan_div(2, fan_div[1]);
#define set_fan(suffix, value, reg, div) \
-static ssize_t set_fan_##suffix(struct device *dev, const char *buf, \
+static ssize_t set_fan_##suffix(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
@@ -292,7 +291,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
}
#define set_fan_div(number) \
-static ssize_t set_fan_div##number(struct device *dev, const char *buf, \
+static ssize_t set_fan_div##number(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
return set_fan_div(dev, buf, count, number - 1); \
@@ -300,14 +299,14 @@ static ssize_t set_fan_div##number(struct device *dev, const char *buf, \
set_fan_div(1);
set_fan_div(2);
-static ssize_t show_temp_input1(struct device *dev, char *buf)
+static ssize_t show_temp_input1(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm80_data *data = lm80_update_device(dev);
return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp));
}
#define show_temp(suffix, value) \
-static ssize_t show_temp_##suffix(struct device *dev, char *buf) \
+static ssize_t show_temp_##suffix(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct lm80_data *data = lm80_update_device(dev); \
return sprintf(buf, "%d\n", TEMP_LIMIT_FROM_REG(data->value)); \
@@ -318,7 +317,7 @@ show_temp(os_max, temp_os_max);
show_temp(os_hyst, temp_os_hyst);
#define set_temp(suffix, value, reg) \
-static ssize_t set_temp_##suffix(struct device *dev, const char *buf, \
+static ssize_t set_temp_##suffix(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
@@ -336,7 +335,7 @@ set_temp(hot_hyst, temp_hot_hyst, LM80_REG_TEMP_HOT_HYST);
set_temp(os_max, temp_os_max, LM80_REG_TEMP_OS_MAX);
set_temp(os_hyst, temp_os_hyst, LM80_REG_TEMP_OS_HYST);
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm80_data *data = lm80_update_device(dev);
return sprintf(buf, "%u\n", data->alarms);
diff --git a/drivers/i2c/chips/lm83.c b/drivers/i2c/chips/lm83.c
index 3dafe60766a..a49008b444c 100644
--- a/drivers/i2c/chips/lm83.c
+++ b/drivers/i2c/chips/lm83.c
@@ -1,7 +1,7 @@
/*
* lm83.c - Part of lm_sensors, Linux kernel modules for hardware
* monitoring
- * Copyright (C) 2003 Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2003-2005 Jean Delvare <khali@linux-fr.org>
*
* Heavily inspired from the lm78, lm75 and adm1021 drivers. The LM83 is
* a sensor chip made by National Semiconductor. It reports up to four
@@ -27,13 +27,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
+#include <linux/hwmon-sysfs.h>
/*
* Addresses to scan
@@ -81,7 +81,7 @@ SENSORS_INSMOD_1(lm83);
/*
* Conversions and various macros
- * The LM83 uses signed 8-bit values with LSB = 1 degree Celcius.
+ * The LM83 uses signed 8-bit values with LSB = 1 degree Celsius.
*/
#define TEMP_FROM_REG(val) ((val) * 1000)
@@ -94,21 +94,20 @@ static const u8 LM83_REG_R_TEMP[] = {
LM83_REG_R_LOCAL_TEMP,
LM83_REG_R_REMOTE1_TEMP,
LM83_REG_R_REMOTE2_TEMP,
- LM83_REG_R_REMOTE3_TEMP
-};
-
-static const u8 LM83_REG_R_HIGH[] = {
+ LM83_REG_R_REMOTE3_TEMP,
LM83_REG_R_LOCAL_HIGH,
LM83_REG_R_REMOTE1_HIGH,
LM83_REG_R_REMOTE2_HIGH,
- LM83_REG_R_REMOTE3_HIGH
+ LM83_REG_R_REMOTE3_HIGH,
+ LM83_REG_R_TCRIT,
};
static const u8 LM83_REG_W_HIGH[] = {
LM83_REG_W_LOCAL_HIGH,
LM83_REG_W_REMOTE1_HIGH,
LM83_REG_W_REMOTE2_HIGH,
- LM83_REG_W_REMOTE3_HIGH
+ LM83_REG_W_REMOTE3_HIGH,
+ LM83_REG_W_TCRIT,
};
/*
@@ -144,9 +143,9 @@ struct lm83_data {
unsigned long last_updated; /* in jiffies */
/* registers values */
- s8 temp_input[4];
- s8 temp_high[4];
- s8 temp_crit;
+ s8 temp[9]; /* 0..3: input 1-4,
+ 4..7: high limit 1-4,
+ 8 : critical limit */
u16 alarms; /* bitvector, combined */
};
@@ -154,65 +153,55 @@ struct lm83_data {
* Sysfs stuff
*/
-#define show_temp(suffix, value) \
-static ssize_t show_temp_##suffix(struct device *dev, char *buf) \
-{ \
- struct lm83_data *data = lm83_update_device(dev); \
- return sprintf(buf, "%d\n", TEMP_FROM_REG(data->value)); \
+static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct lm83_data *data = lm83_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index]));
}
-show_temp(input1, temp_input[0]);
-show_temp(input2, temp_input[1]);
-show_temp(input3, temp_input[2]);
-show_temp(input4, temp_input[3]);
-show_temp(high1, temp_high[0]);
-show_temp(high2, temp_high[1]);
-show_temp(high3, temp_high[2]);
-show_temp(high4, temp_high[3]);
-show_temp(crit, temp_crit);
-
-#define set_temp(suffix, value, reg) \
-static ssize_t set_temp_##suffix(struct device *dev, const char *buf, \
- size_t count) \
-{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct lm83_data *data = i2c_get_clientdata(client); \
- long val = simple_strtol(buf, NULL, 10); \
- \
- down(&data->update_lock); \
- data->value = TEMP_TO_REG(val); \
- i2c_smbus_write_byte_data(client, reg, data->value); \
- up(&data->update_lock); \
- return count; \
+
+static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm83_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+ int nr = attr->index;
+
+ down(&data->update_lock);
+ data->temp[nr] = TEMP_TO_REG(val);
+ i2c_smbus_write_byte_data(client, LM83_REG_W_HIGH[nr - 4],
+ data->temp[nr]);
+ up(&data->update_lock);
+ return count;
}
-set_temp(high1, temp_high[0], LM83_REG_W_LOCAL_HIGH);
-set_temp(high2, temp_high[1], LM83_REG_W_REMOTE1_HIGH);
-set_temp(high3, temp_high[2], LM83_REG_W_REMOTE2_HIGH);
-set_temp(high4, temp_high[3], LM83_REG_W_REMOTE3_HIGH);
-set_temp(crit, temp_crit, LM83_REG_W_TCRIT);
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy,
+ char *buf)
{
struct lm83_data *data = lm83_update_device(dev);
return sprintf(buf, "%d\n", data->alarms);
}
-static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input1, NULL);
-static DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input2, NULL);
-static DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_input3, NULL);
-static DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_input4, NULL);
-static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_high1,
- set_temp_high1);
-static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_high2,
- set_temp_high2);
-static DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp_high3,
- set_temp_high3);
-static DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp_high4,
- set_temp_high4);
-static DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL);
-static DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp_crit, NULL);
-static DEVICE_ATTR(temp3_crit, S_IWUSR | S_IRUGO, show_temp_crit,
- set_temp_crit);
-static DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp_crit, NULL);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp,
+ set_temp, 4);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp,
+ set_temp, 5);
+static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp,
+ set_temp, 6);
+static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp,
+ set_temp, 7);
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp, NULL, 8);
+static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp, NULL, 8);
+static SENSOR_DEVICE_ATTR(temp3_crit, S_IWUSR | S_IRUGO, show_temp,
+ set_temp, 8);
+static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp, NULL, 8);
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
/*
@@ -323,18 +312,30 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
*/
/* Register sysfs hooks */
- device_create_file(&new_client->dev, &dev_attr_temp1_input);
- device_create_file(&new_client->dev, &dev_attr_temp2_input);
- device_create_file(&new_client->dev, &dev_attr_temp3_input);
- device_create_file(&new_client->dev, &dev_attr_temp4_input);
- device_create_file(&new_client->dev, &dev_attr_temp1_max);
- device_create_file(&new_client->dev, &dev_attr_temp2_max);
- device_create_file(&new_client->dev, &dev_attr_temp3_max);
- device_create_file(&new_client->dev, &dev_attr_temp4_max);
- device_create_file(&new_client->dev, &dev_attr_temp1_crit);
- device_create_file(&new_client->dev, &dev_attr_temp2_crit);
- device_create_file(&new_client->dev, &dev_attr_temp3_crit);
- device_create_file(&new_client->dev, &dev_attr_temp4_crit);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp1_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp2_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp3_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp4_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp1_max.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp2_max.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp3_max.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp4_max.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp1_crit.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp2_crit.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp3_crit.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp4_crit.dev_attr);
device_create_file(&new_client->dev, &dev_attr_alarms);
return 0;
@@ -370,16 +371,11 @@ static struct lm83_data *lm83_update_device(struct device *dev)
int nr;
dev_dbg(&client->dev, "Updating lm83 data.\n");
- for (nr = 0; nr < 4 ; nr++) {
- data->temp_input[nr] =
+ for (nr = 0; nr < 9; nr++) {
+ data->temp[nr] =
i2c_smbus_read_byte_data(client,
LM83_REG_R_TEMP[nr]);
- data->temp_high[nr] =
- i2c_smbus_read_byte_data(client,
- LM83_REG_R_HIGH[nr]);
}
- data->temp_crit =
- i2c_smbus_read_byte_data(client, LM83_REG_R_TCRIT);
data->alarms =
i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS1)
+ (i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS2)
diff --git a/drivers/i2c/chips/lm85.c b/drivers/i2c/chips/lm85.c
index b1a0dc5f6b3..b4d7fd41826 100644
--- a/drivers/i2c/chips/lm85.c
+++ b/drivers/i2c/chips/lm85.c
@@ -23,7 +23,6 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -285,8 +284,6 @@ static int ZONE_TO_REG( int zone )
/* i2c-vid.h defines vid_from_reg() */
#define VID_FROM_REG(val,vrm) (vid_from_reg((val),(vrm)))
-#define ALARMS_FROM_REG(val) (val)
-
/* Unlike some other drivers we DO NOT set initial limits. Use
* the config file to set limits. Some users have reported
* motherboards shutting down when we set limits in a previous
@@ -426,15 +423,15 @@ static ssize_t set_fan_min(struct device *dev, const char *buf,
}
#define show_fan_offset(offset) \
-static ssize_t show_fan_##offset (struct device *dev, char *buf) \
+static ssize_t show_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_fan(dev, buf, offset - 1); \
} \
-static ssize_t show_fan_##offset##_min (struct device *dev, char *buf) \
+static ssize_t show_fan_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_fan_min(dev, buf, offset - 1); \
} \
-static ssize_t set_fan_##offset##_min (struct device *dev, \
+static ssize_t set_fan_##offset##_min (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_fan_min(dev, buf, count, offset - 1); \
@@ -451,7 +448,7 @@ show_fan_offset(4);
/* vid, vrm, alarms */
-static ssize_t show_vid_reg(struct device *dev, char *buf)
+static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm85_data *data = lm85_update_device(dev);
return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
@@ -459,13 +456,13 @@ static ssize_t show_vid_reg(struct device *dev, char *buf)
static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
-static ssize_t show_vrm_reg(struct device *dev, char *buf)
+static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm85_data *data = lm85_update_device(dev);
return sprintf(buf, "%ld\n", (long) data->vrm);
}
-static ssize_t store_vrm_reg(struct device *dev, const char *buf, size_t count)
+static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm85_data *data = i2c_get_clientdata(client);
@@ -478,10 +475,10 @@ static ssize_t store_vrm_reg(struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
-static ssize_t show_alarms_reg(struct device *dev, char *buf)
+static ssize_t show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm85_data *data = lm85_update_device(dev);
- return sprintf(buf, "%ld\n", (long) ALARMS_FROM_REG(data->alarms));
+ return sprintf(buf, "%u\n", data->alarms);
}
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
@@ -516,16 +513,16 @@ static ssize_t show_pwm_enable(struct device *dev, char *buf, int nr)
}
#define show_pwm_reg(offset) \
-static ssize_t show_pwm_##offset (struct device *dev, char *buf) \
+static ssize_t show_pwm_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_pwm(dev, buf, offset - 1); \
} \
-static ssize_t set_pwm_##offset (struct device *dev, \
+static ssize_t set_pwm_##offset (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_pwm(dev, buf, count, offset - 1); \
} \
-static ssize_t show_pwm_enable##offset (struct device *dev, char *buf) \
+static ssize_t show_pwm_enable##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_pwm_enable(dev, buf, offset - 1); \
} \
@@ -585,24 +582,24 @@ static ssize_t set_in_max(struct device *dev, const char *buf,
return count;
}
#define show_in_reg(offset) \
-static ssize_t show_in_##offset (struct device *dev, char *buf) \
+static ssize_t show_in_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_in(dev, buf, offset); \
} \
-static ssize_t show_in_##offset##_min (struct device *dev, char *buf) \
+static ssize_t show_in_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_in_min(dev, buf, offset); \
} \
-static ssize_t show_in_##offset##_max (struct device *dev, char *buf) \
+static ssize_t show_in_##offset##_max (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_in_max(dev, buf, offset); \
} \
-static ssize_t set_in_##offset##_min (struct device *dev, \
+static ssize_t set_in_##offset##_min (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_in_min(dev, buf, count, offset); \
} \
-static ssize_t set_in_##offset##_max (struct device *dev, \
+static ssize_t set_in_##offset##_max (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_in_max(dev, buf, count, offset); \
@@ -666,24 +663,24 @@ static ssize_t set_temp_max(struct device *dev, const char *buf,
return count;
}
#define show_temp_reg(offset) \
-static ssize_t show_temp_##offset (struct device *dev, char *buf) \
+static ssize_t show_temp_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_temp(dev, buf, offset - 1); \
} \
-static ssize_t show_temp_##offset##_min (struct device *dev, char *buf) \
+static ssize_t show_temp_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_temp_min(dev, buf, offset - 1); \
} \
-static ssize_t show_temp_##offset##_max (struct device *dev, char *buf) \
+static ssize_t show_temp_##offset##_max (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_temp_max(dev, buf, offset - 1); \
} \
-static ssize_t set_temp_##offset##_min (struct device *dev, \
+static ssize_t set_temp_##offset##_min (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_temp_min(dev, buf, count, offset - 1); \
} \
-static ssize_t set_temp_##offset##_max (struct device *dev, \
+static ssize_t set_temp_##offset##_max (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_temp_max(dev, buf, count, offset - 1); \
@@ -786,42 +783,42 @@ static ssize_t set_pwm_auto_pwm_freq(struct device *dev, const char *buf,
return count;
}
#define pwm_auto(offset) \
-static ssize_t show_pwm##offset##_auto_channels (struct device *dev, \
+static ssize_t show_pwm##offset##_auto_channels (struct device *dev, struct device_attribute *attr, \
char *buf) \
{ \
return show_pwm_auto_channels(dev, buf, offset - 1); \
} \
-static ssize_t set_pwm##offset##_auto_channels (struct device *dev, \
+static ssize_t set_pwm##offset##_auto_channels (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_pwm_auto_channels(dev, buf, count, offset - 1); \
} \
-static ssize_t show_pwm##offset##_auto_pwm_min (struct device *dev, \
+static ssize_t show_pwm##offset##_auto_pwm_min (struct device *dev, struct device_attribute *attr, \
char *buf) \
{ \
return show_pwm_auto_pwm_min(dev, buf, offset - 1); \
} \
-static ssize_t set_pwm##offset##_auto_pwm_min (struct device *dev, \
+static ssize_t set_pwm##offset##_auto_pwm_min (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_pwm_auto_pwm_min(dev, buf, count, offset - 1); \
} \
-static ssize_t show_pwm##offset##_auto_pwm_minctl (struct device *dev, \
+static ssize_t show_pwm##offset##_auto_pwm_minctl (struct device *dev, struct device_attribute *attr, \
char *buf) \
{ \
return show_pwm_auto_pwm_minctl(dev, buf, offset - 1); \
} \
-static ssize_t set_pwm##offset##_auto_pwm_minctl (struct device *dev, \
+static ssize_t set_pwm##offset##_auto_pwm_minctl (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_pwm_auto_pwm_minctl(dev, buf, count, offset - 1); \
} \
-static ssize_t show_pwm##offset##_auto_pwm_freq (struct device *dev, \
+static ssize_t show_pwm##offset##_auto_pwm_freq (struct device *dev, struct device_attribute *attr, \
char *buf) \
{ \
return show_pwm_auto_pwm_freq(dev, buf, offset - 1); \
} \
-static ssize_t set_pwm##offset##_auto_pwm_freq(struct device *dev, \
+static ssize_t set_pwm##offset##_auto_pwm_freq(struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_pwm_auto_pwm_freq(dev, buf, count, offset - 1); \
@@ -962,42 +959,42 @@ static ssize_t set_temp_auto_temp_crit(struct device *dev, const char *buf,
return count;
}
#define temp_auto(offset) \
-static ssize_t show_temp##offset##_auto_temp_off (struct device *dev, \
+static ssize_t show_temp##offset##_auto_temp_off (struct device *dev, struct device_attribute *attr, \
char *buf) \
{ \
return show_temp_auto_temp_off(dev, buf, offset - 1); \
} \
-static ssize_t set_temp##offset##_auto_temp_off (struct device *dev, \
+static ssize_t set_temp##offset##_auto_temp_off (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_temp_auto_temp_off(dev, buf, count, offset - 1); \
} \
-static ssize_t show_temp##offset##_auto_temp_min (struct device *dev, \
+static ssize_t show_temp##offset##_auto_temp_min (struct device *dev, struct device_attribute *attr, \
char *buf) \
{ \
return show_temp_auto_temp_min(dev, buf, offset - 1); \
} \
-static ssize_t set_temp##offset##_auto_temp_min (struct device *dev, \
+static ssize_t set_temp##offset##_auto_temp_min (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_temp_auto_temp_min(dev, buf, count, offset - 1); \
} \
-static ssize_t show_temp##offset##_auto_temp_max (struct device *dev, \
+static ssize_t show_temp##offset##_auto_temp_max (struct device *dev, struct device_attribute *attr, \
char *buf) \
{ \
return show_temp_auto_temp_max(dev, buf, offset - 1); \
} \
-static ssize_t set_temp##offset##_auto_temp_max (struct device *dev, \
+static ssize_t set_temp##offset##_auto_temp_max (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_temp_auto_temp_max(dev, buf, count, offset - 1); \
} \
-static ssize_t show_temp##offset##_auto_temp_crit (struct device *dev, \
+static ssize_t show_temp##offset##_auto_temp_crit (struct device *dev, struct device_attribute *attr, \
char *buf) \
{ \
return show_temp_auto_temp_crit(dev, buf, offset - 1); \
} \
-static ssize_t set_temp##offset##_auto_temp_crit (struct device *dev, \
+static ssize_t set_temp##offset##_auto_temp_crit (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_temp_auto_temp_crit(dev, buf, count, offset - 1); \
diff --git a/drivers/i2c/chips/lm87.c b/drivers/i2c/chips/lm87.c
index 98cabd66506..1921ed1af18 100644
--- a/drivers/i2c/chips/lm87.c
+++ b/drivers/i2c/chips/lm87.c
@@ -52,7 +52,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -218,19 +217,19 @@ static inline int lm87_write_value(struct i2c_client *client, u8 reg, u8 value)
}
#define show_in(offset) \
-static ssize_t show_in##offset##_input(struct device *dev, char *buf) \
+static ssize_t show_in##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct lm87_data *data = lm87_update_device(dev); \
return sprintf(buf, "%u\n", IN_FROM_REG(data->in[offset], \
data->in_scale[offset])); \
} \
-static ssize_t show_in##offset##_min(struct device *dev, char *buf) \
+static ssize_t show_in##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct lm87_data *data = lm87_update_device(dev); \
return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[offset], \
data->in_scale[offset])); \
} \
-static ssize_t show_in##offset##_max(struct device *dev, char *buf) \
+static ssize_t show_in##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct lm87_data *data = lm87_update_device(dev); \
return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[offset], \
@@ -274,13 +273,13 @@ static void set_in_max(struct device *dev, const char *buf, int nr)
}
#define set_in(offset) \
-static ssize_t set_in##offset##_min(struct device *dev, \
+static ssize_t set_in##offset##_min(struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
set_in_min(dev, buf, offset); \
return count; \
} \
-static ssize_t set_in##offset##_max(struct device *dev, \
+static ssize_t set_in##offset##_max(struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
set_in_max(dev, buf, offset); \
@@ -300,17 +299,17 @@ set_in(6);
set_in(7);
#define show_temp(offset) \
-static ssize_t show_temp##offset##_input(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct lm87_data *data = lm87_update_device(dev); \
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[offset-1])); \
} \
-static ssize_t show_temp##offset##_low(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_low(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct lm87_data *data = lm87_update_device(dev); \
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_low[offset-1])); \
} \
-static ssize_t show_temp##offset##_high(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_high(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct lm87_data *data = lm87_update_device(dev); \
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_high[offset-1])); \
@@ -346,13 +345,13 @@ static void set_temp_high(struct device *dev, const char *buf, int nr)
}
#define set_temp(offset) \
-static ssize_t set_temp##offset##_low(struct device *dev, \
+static ssize_t set_temp##offset##_low(struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
set_temp_low(dev, buf, offset-1); \
return count; \
} \
-static ssize_t set_temp##offset##_high(struct device *dev, \
+static ssize_t set_temp##offset##_high(struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
set_temp_high(dev, buf, offset-1); \
@@ -366,13 +365,13 @@ set_temp(1);
set_temp(2);
set_temp(3);
-static ssize_t show_temp_crit_int(struct device *dev, char *buf)
+static ssize_t show_temp_crit_int(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm87_data *data = lm87_update_device(dev);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit_int));
}
-static ssize_t show_temp_crit_ext(struct device *dev, char *buf)
+static ssize_t show_temp_crit_ext(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm87_data *data = lm87_update_device(dev);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit_ext));
@@ -383,19 +382,19 @@ static DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp_crit_ext, NULL);
static DEVICE_ATTR(temp3_crit, S_IRUGO, show_temp_crit_ext, NULL);
#define show_fan(offset) \
-static ssize_t show_fan##offset##_input(struct device *dev, char *buf) \
+static ssize_t show_fan##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct lm87_data *data = lm87_update_device(dev); \
return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[offset-1], \
FAN_DIV_FROM_REG(data->fan_div[offset-1]))); \
} \
-static ssize_t show_fan##offset##_min(struct device *dev, char *buf) \
+static ssize_t show_fan##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct lm87_data *data = lm87_update_device(dev); \
return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[offset-1], \
FAN_DIV_FROM_REG(data->fan_div[offset-1]))); \
} \
-static ssize_t show_fan##offset##_div(struct device *dev, char *buf) \
+static ssize_t show_fan##offset##_div(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct lm87_data *data = lm87_update_device(dev); \
return sprintf(buf, "%d\n", FAN_DIV_FROM_REG(data->fan_div[offset-1])); \
@@ -465,13 +464,13 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
}
#define set_fan(offset) \
-static ssize_t set_fan##offset##_min(struct device *dev, const char *buf, \
+static ssize_t set_fan##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
set_fan_min(dev, buf, offset-1); \
return count; \
} \
-static ssize_t set_fan##offset##_div(struct device *dev, const char *buf, \
+static ssize_t set_fan##offset##_div(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
return set_fan_div(dev, buf, count, offset-1); \
@@ -483,26 +482,26 @@ static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
set_fan(1);
set_fan(2);
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm87_data *data = lm87_update_device(dev);
return sprintf(buf, "%d\n", data->alarms);
}
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
-static ssize_t show_vid(struct device *dev, char *buf)
+static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm87_data *data = lm87_update_device(dev);
return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
}
static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
-static ssize_t show_vrm(struct device *dev, char *buf)
+static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm87_data *data = lm87_update_device(dev);
return sprintf(buf, "%d\n", data->vrm);
}
-static ssize_t set_vrm(struct device *dev, const char *buf, size_t count)
+static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm87_data *data = i2c_get_clientdata(client);
@@ -511,12 +510,12 @@ static ssize_t set_vrm(struct device *dev, const char *buf, size_t count)
}
static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
-static ssize_t show_aout(struct device *dev, char *buf)
+static ssize_t show_aout(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm87_data *data = lm87_update_device(dev);
return sprintf(buf, "%d\n", AOUT_FROM_REG(data->aout));
}
-static ssize_t set_aout(struct device *dev, const char *buf, size_t count)
+static ssize_t set_aout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm87_data *data = i2c_get_clientdata(client);
diff --git a/drivers/i2c/chips/lm90.c b/drivers/i2c/chips/lm90.c
index 2c00ff83bab..a67dcadf7cb 100644
--- a/drivers/i2c/chips/lm90.c
+++ b/drivers/i2c/chips/lm90.c
@@ -1,7 +1,7 @@
/*
* lm90.c - Part of lm_sensors, Linux kernel modules for hardware
* monitoring
- * Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2003-2005 Jean Delvare <khali@linux-fr.org>
*
* Based on the lm83 driver. The LM90 is a sensor chip made by National
* Semiconductor. It reports up to two temperatures (its own plus up to
@@ -19,7 +19,7 @@
* Complete datasheets can be obtained from National's website at:
* http://www.national.com/pf/LM/LM89.html
* http://www.national.com/pf/LM/LM99.html
- * Note that there is no way to differenciate between both chips.
+ * Note that there is no way to differentiate between both chips.
*
* This driver also supports the LM86, another sensor chip made by
* National Semiconductor. It is exactly similar to the LM90 except it
@@ -39,7 +39,7 @@
* chips made by Maxim. These chips are similar to the LM86. Complete
* datasheet can be obtained at Maxim's website at:
* http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2578
- * Note that there is no easy way to differenciate between the three
+ * Note that there is no easy way to differentiate between the three
* variants. The extra address and features of the MAX6659 are not
* supported by this driver.
*
@@ -70,13 +70,13 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
+#include <linux/hwmon-sysfs.h>
/*
* Addresses to scan
@@ -139,9 +139,9 @@ SENSORS_INSMOD_6(lm90, adm1032, lm99, lm86, max6657, adt7461);
/*
* Conversions and various macros
* For local temperatures and limits, critical limits and the hysteresis
- * value, the LM90 uses signed 8-bit values with LSB = 1 degree Celcius.
+ * value, the LM90 uses signed 8-bit values with LSB = 1 degree Celsius.
* For remote temperatures and limits, it uses signed 11-bit values with
- * LSB = 0.125 degree Celcius, left-justified in 16-bit registers.
+ * LSB = 0.125 degree Celsius, left-justified in 16-bit registers.
*/
#define TEMP1_FROM_REG(val) ((val) * 1000)
@@ -206,9 +206,14 @@ struct lm90_data {
int kind;
/* registers values */
- s8 temp_input1, temp_low1, temp_high1; /* local */
- s16 temp_input2, temp_low2, temp_high2; /* remote, combined */
- s8 temp_crit1, temp_crit2;
+ s8 temp8[5]; /* 0: local input
+ 1: local low limit
+ 2: local high limit
+ 3: local critical limit
+ 4: remote critical limit */
+ s16 temp11[3]; /* 0: remote input
+ 1: remote low limit
+ 2: remote high limit */
u8 temp_hyst;
u8 alarms; /* bitvector */
};
@@ -217,75 +222,88 @@ struct lm90_data {
* Sysfs stuff
*/
-#define show_temp(value, converter) \
-static ssize_t show_##value(struct device *dev, char *buf) \
-{ \
- struct lm90_data *data = lm90_update_device(dev); \
- return sprintf(buf, "%d\n", converter(data->value)); \
+static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct lm90_data *data = lm90_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp8[attr->index]));
+}
+
+static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ static const u8 reg[4] = {
+ LM90_REG_W_LOCAL_LOW,
+ LM90_REG_W_LOCAL_HIGH,
+ LM90_REG_W_LOCAL_CRIT,
+ LM90_REG_W_REMOTE_CRIT,
+ };
+
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm90_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+ int nr = attr->index;
+
+ down(&data->update_lock);
+ if (data->kind == adt7461)
+ data->temp8[nr] = TEMP1_TO_REG_ADT7461(val);
+ else
+ data->temp8[nr] = TEMP1_TO_REG(val);
+ i2c_smbus_write_byte_data(client, reg[nr - 1], data->temp8[nr]);
+ up(&data->update_lock);
+ return count;
}
-show_temp(temp_input1, TEMP1_FROM_REG);
-show_temp(temp_input2, TEMP2_FROM_REG);
-show_temp(temp_low1, TEMP1_FROM_REG);
-show_temp(temp_low2, TEMP2_FROM_REG);
-show_temp(temp_high1, TEMP1_FROM_REG);
-show_temp(temp_high2, TEMP2_FROM_REG);
-show_temp(temp_crit1, TEMP1_FROM_REG);
-show_temp(temp_crit2, TEMP1_FROM_REG);
-
-#define set_temp1(value, reg) \
-static ssize_t set_##value(struct device *dev, const char *buf, \
- size_t count) \
-{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct lm90_data *data = i2c_get_clientdata(client); \
- long val = simple_strtol(buf, NULL, 10); \
- \
- down(&data->update_lock); \
- if (data->kind == adt7461) \
- data->value = TEMP1_TO_REG_ADT7461(val); \
- else \
- data->value = TEMP1_TO_REG(val); \
- i2c_smbus_write_byte_data(client, reg, data->value); \
- up(&data->update_lock); \
- return count; \
+
+static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct lm90_data *data = lm90_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP2_FROM_REG(data->temp11[attr->index]));
}
-#define set_temp2(value, regh, regl) \
-static ssize_t set_##value(struct device *dev, const char *buf, \
- size_t count) \
-{ \
- struct i2c_client *client = to_i2c_client(dev); \
- struct lm90_data *data = i2c_get_clientdata(client); \
- long val = simple_strtol(buf, NULL, 10); \
- \
- down(&data->update_lock); \
- if (data->kind == adt7461) \
- data->value = TEMP2_TO_REG_ADT7461(val); \
- else \
- data->value = TEMP2_TO_REG(val); \
- i2c_smbus_write_byte_data(client, regh, data->value >> 8); \
- i2c_smbus_write_byte_data(client, regl, data->value & 0xff); \
- up(&data->update_lock); \
- return count; \
+
+static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
+ const char *buf, size_t count)
+{
+ static const u8 reg[4] = {
+ LM90_REG_W_REMOTE_LOWH,
+ LM90_REG_W_REMOTE_LOWL,
+ LM90_REG_W_REMOTE_HIGHH,
+ LM90_REG_W_REMOTE_HIGHL,
+ };
+
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct lm90_data *data = i2c_get_clientdata(client);
+ long val = simple_strtol(buf, NULL, 10);
+ int nr = attr->index;
+
+ down(&data->update_lock);
+ if (data->kind == adt7461)
+ data->temp11[nr] = TEMP2_TO_REG_ADT7461(val);
+ else
+ data->temp11[nr] = TEMP2_TO_REG(val);
+ i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2],
+ data->temp11[nr] >> 8);
+ i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1],
+ data->temp11[nr] & 0xff);
+ up(&data->update_lock);
+ return count;
}
-set_temp1(temp_low1, LM90_REG_W_LOCAL_LOW);
-set_temp2(temp_low2, LM90_REG_W_REMOTE_LOWH, LM90_REG_W_REMOTE_LOWL);
-set_temp1(temp_high1, LM90_REG_W_LOCAL_HIGH);
-set_temp2(temp_high2, LM90_REG_W_REMOTE_HIGHH, LM90_REG_W_REMOTE_HIGHL);
-set_temp1(temp_crit1, LM90_REG_W_LOCAL_CRIT);
-set_temp1(temp_crit2, LM90_REG_W_REMOTE_CRIT);
-
-#define show_temp_hyst(value, basereg) \
-static ssize_t show_##value(struct device *dev, char *buf) \
-{ \
- struct lm90_data *data = lm90_update_device(dev); \
- return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->basereg) \
- - TEMP1_FROM_REG(data->temp_hyst)); \
+
+static ssize_t show_temphyst(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct lm90_data *data = lm90_update_device(dev);
+ return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp8[attr->index])
+ - TEMP1_FROM_REG(data->temp_hyst));
}
-show_temp_hyst(temp_hyst1, temp_crit1);
-show_temp_hyst(temp_hyst2, temp_crit2);
-static ssize_t set_temp_hyst1(struct device *dev, const char *buf,
- size_t count)
+static ssize_t set_temphyst(struct device *dev, struct device_attribute *dummy,
+ const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct lm90_data *data = i2c_get_clientdata(client);
@@ -293,36 +311,37 @@ static ssize_t set_temp_hyst1(struct device *dev, const char *buf,
long hyst;
down(&data->update_lock);
- hyst = TEMP1_FROM_REG(data->temp_crit1) - val;
+ hyst = TEMP1_FROM_REG(data->temp8[3]) - val;
i2c_smbus_write_byte_data(client, LM90_REG_W_TCRIT_HYST,
HYST_TO_REG(hyst));
up(&data->update_lock);
return count;
}
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy,
+ char *buf)
{
struct lm90_data *data = lm90_update_device(dev);
return sprintf(buf, "%d\n", data->alarms);
}
-static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input1, NULL);
-static DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input2, NULL);
-static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_low1,
- set_temp_low1);
-static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_low2,
- set_temp_low2);
-static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_high1,
- set_temp_high1);
-static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_high2,
- set_temp_high2);
-static DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp_crit1,
- set_temp_crit1);
-static DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp_crit2,
- set_temp_crit2);
-static DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp_hyst1,
- set_temp_hyst1);
-static DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temp_hyst2, NULL);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp8, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp8,
+ set_temp8, 1);
+static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11,
+ set_temp11, 1);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp8,
+ set_temp8, 2);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp11,
+ set_temp11, 2);
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp8,
+ set_temp8, 3);
+static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp8,
+ set_temp8, 4);
+static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temphyst,
+ set_temphyst, 3);
+static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 4);
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
/*
@@ -481,16 +500,26 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
lm90_init_client(new_client);
/* Register sysfs hooks */
- device_create_file(&new_client->dev, &dev_attr_temp1_input);
- device_create_file(&new_client->dev, &dev_attr_temp2_input);
- device_create_file(&new_client->dev, &dev_attr_temp1_min);
- device_create_file(&new_client->dev, &dev_attr_temp2_min);
- device_create_file(&new_client->dev, &dev_attr_temp1_max);
- device_create_file(&new_client->dev, &dev_attr_temp2_max);
- device_create_file(&new_client->dev, &dev_attr_temp1_crit);
- device_create_file(&new_client->dev, &dev_attr_temp2_crit);
- device_create_file(&new_client->dev, &dev_attr_temp1_crit_hyst);
- device_create_file(&new_client->dev, &dev_attr_temp2_crit_hyst);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp1_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp2_input.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp1_min.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp2_min.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp1_max.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp2_max.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp1_crit.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp2_crit.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp1_crit_hyst.dev_attr);
+ device_create_file(&new_client->dev,
+ &sensor_dev_attr_temp2_crit_hyst.dev_attr);
device_create_file(&new_client->dev, &dev_attr_alarms);
return 0;
@@ -541,16 +570,16 @@ static struct lm90_data *lm90_update_device(struct device *dev)
u8 oldh, newh;
dev_dbg(&client->dev, "Updating lm90 data.\n");
- data->temp_input1 = i2c_smbus_read_byte_data(client,
- LM90_REG_R_LOCAL_TEMP);
- data->temp_high1 = i2c_smbus_read_byte_data(client,
- LM90_REG_R_LOCAL_HIGH);
- data->temp_low1 = i2c_smbus_read_byte_data(client,
- LM90_REG_R_LOCAL_LOW);
- data->temp_crit1 = i2c_smbus_read_byte_data(client,
- LM90_REG_R_LOCAL_CRIT);
- data->temp_crit2 = i2c_smbus_read_byte_data(client,
- LM90_REG_R_REMOTE_CRIT);
+ data->temp8[0] = i2c_smbus_read_byte_data(client,
+ LM90_REG_R_LOCAL_TEMP);
+ data->temp8[1] = i2c_smbus_read_byte_data(client,
+ LM90_REG_R_LOCAL_LOW);
+ data->temp8[2] = i2c_smbus_read_byte_data(client,
+ LM90_REG_R_LOCAL_HIGH);
+ data->temp8[3] = i2c_smbus_read_byte_data(client,
+ LM90_REG_R_LOCAL_CRIT);
+ data->temp8[4] = i2c_smbus_read_byte_data(client,
+ LM90_REG_R_REMOTE_CRIT);
data->temp_hyst = i2c_smbus_read_byte_data(client,
LM90_REG_R_TCRIT_HYST);
@@ -570,13 +599,13 @@ static struct lm90_data *lm90_update_device(struct device *dev)
*/
oldh = i2c_smbus_read_byte_data(client,
LM90_REG_R_REMOTE_TEMPH);
- data->temp_input2 = i2c_smbus_read_byte_data(client,
- LM90_REG_R_REMOTE_TEMPL);
+ data->temp11[0] = i2c_smbus_read_byte_data(client,
+ LM90_REG_R_REMOTE_TEMPL);
newh = i2c_smbus_read_byte_data(client,
LM90_REG_R_REMOTE_TEMPH);
if (newh != oldh) {
- data->temp_input2 = i2c_smbus_read_byte_data(client,
- LM90_REG_R_REMOTE_TEMPL);
+ data->temp11[0] = i2c_smbus_read_byte_data(client,
+ LM90_REG_R_REMOTE_TEMPL);
#ifdef DEBUG
oldh = i2c_smbus_read_byte_data(client,
LM90_REG_R_REMOTE_TEMPH);
@@ -586,16 +615,16 @@ static struct lm90_data *lm90_update_device(struct device *dev)
"wrong.\n");
#endif
}
- data->temp_input2 |= (newh << 8);
+ data->temp11[0] |= (newh << 8);
- data->temp_high2 = (i2c_smbus_read_byte_data(client,
+ data->temp11[1] = (i2c_smbus_read_byte_data(client,
+ LM90_REG_R_REMOTE_LOWH) << 8) +
+ i2c_smbus_read_byte_data(client,
+ LM90_REG_R_REMOTE_LOWL);
+ data->temp11[2] = (i2c_smbus_read_byte_data(client,
LM90_REG_R_REMOTE_HIGHH) << 8) +
i2c_smbus_read_byte_data(client,
LM90_REG_R_REMOTE_HIGHL);
- data->temp_low2 = (i2c_smbus_read_byte_data(client,
- LM90_REG_R_REMOTE_LOWH) << 8) +
- i2c_smbus_read_byte_data(client,
- LM90_REG_R_REMOTE_LOWL);
data->alarms = i2c_smbus_read_byte_data(client,
LM90_REG_R_STATUS);
diff --git a/drivers/i2c/chips/lm92.c b/drivers/i2c/chips/lm92.c
index fe6e83d70a7..215c8e40ffd 100644
--- a/drivers/i2c/chips/lm92.c
+++ b/drivers/i2c/chips/lm92.c
@@ -140,7 +140,7 @@ static struct lm92_data *lm92_update_device(struct device *dev)
}
#define show_temp(value) \
-static ssize_t show_##value(struct device *dev, char *buf) \
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct lm92_data *data = lm92_update_device(dev); \
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->value)); \
@@ -151,7 +151,7 @@ show_temp(temp1_min);
show_temp(temp1_max);
#define set_temp(value, reg) \
-static ssize_t set_##value(struct device *dev, const char *buf, \
+static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
@@ -168,26 +168,26 @@ set_temp(temp1_crit, LM92_REG_TEMP_CRIT);
set_temp(temp1_min, LM92_REG_TEMP_LOW);
set_temp(temp1_max, LM92_REG_TEMP_HIGH);
-static ssize_t show_temp1_crit_hyst(struct device *dev, char *buf)
+static ssize_t show_temp1_crit_hyst(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm92_data *data = lm92_update_device(dev);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_crit)
- TEMP_FROM_REG(data->temp1_hyst));
}
-static ssize_t show_temp1_max_hyst(struct device *dev, char *buf)
+static ssize_t show_temp1_max_hyst(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm92_data *data = lm92_update_device(dev);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_max)
- TEMP_FROM_REG(data->temp1_hyst));
}
-static ssize_t show_temp1_min_hyst(struct device *dev, char *buf)
+static ssize_t show_temp1_min_hyst(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm92_data *data = lm92_update_device(dev);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_min)
+ TEMP_FROM_REG(data->temp1_hyst));
}
-static ssize_t set_temp1_crit_hyst(struct device *dev, const char *buf,
+static ssize_t set_temp1_crit_hyst(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -202,7 +202,7 @@ static ssize_t set_temp1_crit_hyst(struct device *dev, const char *buf,
return count;
}
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lm92_data *data = lm92_update_device(dev);
return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->temp1_input));
diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c
index e771566dffa..5e463c47bfb 100644
--- a/drivers/i2c/chips/m41t00.c
+++ b/drivers/i2c/chips/m41t00.c
@@ -40,11 +40,8 @@ static unsigned short normal_addr[] = { 0x68, I2C_CLIENT_END };
static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_addr,
- .normal_i2c_range = ignore,
.probe = ignore,
- .probe_range = ignore,
.ignore = ignore,
- .ignore_range = ignore,
.force = ignore,
};
diff --git a/drivers/i2c/chips/max1619.c b/drivers/i2c/chips/max1619.c
index 5afa961a5e1..bf553dcd97d 100644
--- a/drivers/i2c/chips/max1619.c
+++ b/drivers/i2c/chips/max1619.c
@@ -26,7 +26,6 @@
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -122,7 +121,7 @@ struct max1619_data {
*/
#define show_temp(value) \
-static ssize_t show_##value(struct device *dev, char *buf) \
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct max1619_data *data = max1619_update_device(dev); \
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->value)); \
@@ -135,7 +134,7 @@ show_temp(temp_crit2);
show_temp(temp_hyst2);
#define set_temp2(value, reg) \
-static ssize_t set_##value(struct device *dev, const char *buf, \
+static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
@@ -154,7 +153,7 @@ set_temp2(temp_high2, MAX1619_REG_W_REMOTE_HIGH);
set_temp2(temp_crit2, MAX1619_REG_W_REMOTE_CRIT);
set_temp2(temp_hyst2, MAX1619_REG_W_TCRIT_HYST);
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
{
struct max1619_data *data = max1619_update_device(dev);
return sprintf(buf, "%d\n", data->alarms);
diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c
new file mode 100644
index 00000000000..fe6b150ec4c
--- /dev/null
+++ b/drivers/i2c/chips/max6875.c
@@ -0,0 +1,473 @@
+/*
+ max6875.c - driver for MAX6874/MAX6875
+
+ Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com>
+
+ Based on i2c/chips/eeprom.c
+
+ The MAX6875 has two EEPROM sections: config and user.
+ At reset, the config EEPROM is read into the registers.
+
+ This driver make 3 binary files available in sysfs:
+ reg_config - direct access to the registers
+ eeprom_config - acesses configuration eeprom space
+ eeprom_user - free for application use
+
+ In our application, we put device serial & model numbers in user eeprom.
+
+ Notes:
+ 1) The datasheet says that register 0x44 / EEPROM 0x8044 should NOT
+ be overwritten, so the driver explicitly prevents that.
+ 2) It's a good idea to keep the config (0x45) locked in config EEPROM.
+ You can temporarily enable config writes by changing register 0x45.
+
+ 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; version 2 of the License.
+*/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = {0x50, 0x52, I2C_CLIENT_END};
+static unsigned int normal_isa[] = {I2C_CLIENT_ISA_END};
+
+/* Insmod parameters */
+SENSORS_INSMOD_1(max6875);
+
+/* this param will prevent 'accidental' writes to the eeprom */
+static int allow_write = 0;
+module_param(allow_write, int, 0);
+MODULE_PARM_DESC(allow_write,
+ "Enable write access:\n"
+ "*0: Read only\n"
+ " 1: Read/Write access");
+
+/* The MAX6875 can only read/write 16 bytes at a time */
+#define SLICE_SIZE 16
+#define SLICE_BITS 4
+
+/* CONFIG EEPROM is at addresses 0x8000 - 0x8045, registers are at 0 - 0x45 */
+#define CONFIG_EEPROM_BASE 0x8000
+#define CONFIG_EEPROM_SIZE 0x0046
+#define CONFIG_EEPROM_SLICES 5
+
+/* USER EEPROM is at addresses 0x8100 - 0x82FF */
+#define USER_EEPROM_BASE 0x8100
+#define USER_EEPROM_SIZE 0x0200
+#define USER_EEPROM_SLICES 32
+
+/* MAX6875 commands */
+#define MAX6875_CMD_BLOCK_WRITE 0x83
+#define MAX6875_CMD_BLOCK_READ 0x84
+#define MAX6875_CMD_REBOOT 0x88
+
+enum max6875_area_type {
+ max6875_register_config=0,
+ max6875_eeprom_config,
+ max6875_eeprom_user,
+ max6857_max
+};
+
+struct eeprom_block {
+ enum max6875_area_type type;
+ u8 slices;
+ u32 size;
+ u32 valid;
+ u32 base;
+ unsigned long *updated;
+ u8 *data;
+};
+
+/* Each client has this additional data */
+struct max6875_data {
+ struct i2c_client client;
+ struct semaphore update_lock;
+ struct eeprom_block blocks[max6857_max];
+ /* the above structs point into the arrays below */
+ u8 data[USER_EEPROM_SIZE + (CONFIG_EEPROM_SIZE*2)];
+ unsigned long last_updated[USER_EEPROM_SLICES + (CONFIG_EEPROM_SLICES*2)];
+};
+
+static int max6875_attach_adapter(struct i2c_adapter *adapter);
+static int max6875_detect(struct i2c_adapter *adapter, int address, int kind);
+static int max6875_detach_client(struct i2c_client *client);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver max6875_driver = {
+ .owner = THIS_MODULE,
+ .name = "max6875",
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = max6875_attach_adapter,
+ .detach_client = max6875_detach_client,
+};
+
+static int max6875_update_slice(struct i2c_client *client,
+ struct eeprom_block *blk,
+ int slice)
+{
+ struct max6875_data *data = i2c_get_clientdata(client);
+ int i, j, addr, count;
+ u8 rdbuf[SLICE_SIZE];
+ int retval = 0;
+
+ if (slice >= blk->slices)
+ return -1;
+
+ down(&data->update_lock);
+
+ if (!(blk->valid & (1 << slice)) ||
+ (jiffies - blk->updated[slice] > 300 * HZ) ||
+ (jiffies < blk->updated[slice])) {
+ dev_dbg(&client->dev, "Starting eeprom update, slice %u, base %u\n",
+ slice, blk->base);
+
+ addr = blk->base + (slice << SLICE_BITS);
+ count = blk->size - (slice << SLICE_BITS);
+ if (count > SLICE_SIZE) {
+ count = SLICE_SIZE;
+ }
+
+ /* Preset the read address */
+ if (addr < 0x100) {
+ /* select the register */
+ if (i2c_smbus_write_byte(client, addr & 0xFF)) {
+ dev_dbg(&client->dev, "max6875 register select has failed!\n");
+ retval = -1;
+ goto exit;
+ }
+ } else {
+ /* select the eeprom */
+ if (i2c_smbus_write_byte_data(client, addr >> 8, addr & 0xFF)) {
+ dev_dbg(&client->dev, "max6875 address set has failed!\n");
+ retval = -1;
+ goto exit;
+ }
+ }
+
+ if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
+ if (i2c_smbus_read_i2c_block_data(client, MAX6875_CMD_BLOCK_READ,
+ rdbuf) != SLICE_SIZE)
+ {
+ retval = -1;
+ goto exit;
+ }
+
+ memcpy(&blk->data[slice << SLICE_BITS], rdbuf, count);
+ } else {
+ for (i = 0; i < count; i++) {
+ j = i2c_smbus_read_byte(client);
+ if (j < 0)
+ {
+ retval = -1;
+ goto exit;
+ }
+ blk->data[(slice << SLICE_BITS) + i] = (u8) j;
+ }
+ }
+ blk->updated[slice] = jiffies;
+ blk->valid |= (1 << slice);
+ }
+ exit:
+ up(&data->update_lock);
+ return retval;
+}
+
+static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off, size_t count,
+ enum max6875_area_type area_type)
+{
+ struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
+ struct max6875_data *data = i2c_get_clientdata(client);
+ struct eeprom_block *blk;
+ int slice;
+
+ blk = &data->blocks[area_type];
+
+ if (off > blk->size)
+ return 0;
+ if (off + count > blk->size)
+ count = blk->size - off;
+
+ /* Only refresh slices which contain requested bytes */
+ for (slice = (off >> SLICE_BITS); slice <= ((off + count - 1) >> SLICE_BITS); slice++)
+ max6875_update_slice(client, blk, slice);
+
+ memcpy(buf, &blk->data[off], count);
+
+ return count;
+}
+
+static ssize_t max6875_user_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+ return max6875_read(kobj, buf, off, count, max6875_eeprom_user);
+}
+
+static ssize_t max6875_config_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+ return max6875_read(kobj, buf, off, count, max6875_eeprom_config);
+}
+
+static ssize_t max6875_cfgreg_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+ return max6875_read(kobj, buf, off, count, max6875_register_config);
+}
+
+
+static ssize_t max6875_write(struct kobject *kobj, char *buf, loff_t off, size_t count,
+ enum max6875_area_type area_type)
+{
+ struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
+ struct max6875_data *data = i2c_get_clientdata(client);
+ struct eeprom_block *blk;
+ int slice, addr, retval;
+ ssize_t sent = 0;
+
+ blk = &data->blocks[area_type];
+
+ if (off > blk->size)
+ return 0;
+ if ((off + count) > blk->size)
+ count = blk->size - off;
+
+ if (down_interruptible(&data->update_lock))
+ return -EAGAIN;
+
+ /* writing to a register is done with i2c_smbus_write_byte_data() */
+ if (blk->type == max6875_register_config) {
+ for (sent = 0; sent < count; sent++) {
+ addr = off + sent;
+ if (addr == 0x44)
+ continue;
+
+ retval = i2c_smbus_write_byte_data(client, addr, buf[sent]);
+ }
+ } else {
+ int cmd, val;
+
+ /* We are writing to EEPROM */
+ for (sent = 0; sent < count; sent++) {
+ addr = blk->base + off + sent;
+ cmd = addr >> 8;
+ val = (addr & 0xff) | (buf[sent] << 8); // reversed
+
+ if (addr == 0x8044)
+ continue;
+
+ retval = i2c_smbus_write_word_data(client, cmd, val);
+
+ if (retval) {
+ goto error_exit;
+ }
+
+ /* A write takes up to 11 ms */
+ msleep(11);
+ }
+ }
+
+ /* Invalidate the scratch buffer */
+ for (slice = (off >> SLICE_BITS); slice <= ((off + count - 1) >> SLICE_BITS); slice++)
+ blk->valid &= ~(1 << slice);
+
+ error_exit:
+ up(&data->update_lock);
+
+ return sent;
+}
+
+static ssize_t max6875_user_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+ return max6875_write(kobj, buf, off, count, max6875_eeprom_user);
+}
+
+static ssize_t max6875_config_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+ return max6875_write(kobj, buf, off, count, max6875_eeprom_config);
+}
+
+static ssize_t max6875_cfgreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+ return max6875_write(kobj, buf, off, count, max6875_register_config);
+}
+
+static struct bin_attribute user_eeprom_attr = {
+ .attr = {
+ .name = "eeprom_user",
+ .mode = S_IRUGO | S_IWUSR | S_IWGRP,
+ .owner = THIS_MODULE,
+ },
+ .size = USER_EEPROM_SIZE,
+ .read = max6875_user_read,
+ .write = max6875_user_write,
+};
+
+static struct bin_attribute config_eeprom_attr = {
+ .attr = {
+ .name = "eeprom_config",
+ .mode = S_IRUGO | S_IWUSR,
+ .owner = THIS_MODULE,
+ },
+ .size = CONFIG_EEPROM_SIZE,
+ .read = max6875_config_read,
+ .write = max6875_config_write,
+};
+
+static struct bin_attribute config_register_attr = {
+ .attr = {
+ .name = "reg_config",
+ .mode = S_IRUGO | S_IWUSR,
+ .owner = THIS_MODULE,
+ },
+ .size = CONFIG_EEPROM_SIZE,
+ .read = max6875_cfgreg_read,
+ .write = max6875_cfgreg_write,
+};
+
+static int max6875_attach_adapter(struct i2c_adapter *adapter)
+{
+ return i2c_detect(adapter, &addr_data, max6875_detect);
+}
+
+/* This function is called by i2c_detect */
+static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+ struct i2c_client *new_client;
+ struct max6875_data *data;
+ int err = 0;
+
+ /* There are three ways we can read the EEPROM data:
+ (1) I2C block reads (faster, but unsupported by most adapters)
+ (2) Consecutive byte reads (100% overhead)
+ (3) Regular byte data reads (200% overhead)
+ The third method is not implemented by this driver because all
+ known adapters support at least the second. */
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA |
+ I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+ goto exit;
+
+ /* OK. For now, we presume we have a valid client. We now create the
+ client structure, even though we cannot fill it completely yet.
+ But it allows us to access eeprom_{read,write}_value. */
+ if (!(data = kmalloc(sizeof(struct max6875_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit;
+ }
+ memset(data, 0, sizeof(struct max6875_data));
+
+ new_client = &data->client;
+ i2c_set_clientdata(new_client, data);
+ new_client->addr = address;
+ new_client->adapter = adapter;
+ new_client->driver = &max6875_driver;
+ new_client->flags = 0;
+
+ /* Setup the user section */
+ data->blocks[max6875_eeprom_user].type = max6875_eeprom_user;
+ data->blocks[max6875_eeprom_user].slices = USER_EEPROM_SLICES;
+ data->blocks[max6875_eeprom_user].size = USER_EEPROM_SIZE;
+ data->blocks[max6875_eeprom_user].base = USER_EEPROM_BASE;
+ data->blocks[max6875_eeprom_user].data = data->data;
+ data->blocks[max6875_eeprom_user].updated = data->last_updated;
+
+ /* Setup the config section */
+ data->blocks[max6875_eeprom_config].type = max6875_eeprom_config;
+ data->blocks[max6875_eeprom_config].slices = CONFIG_EEPROM_SLICES;
+ data->blocks[max6875_eeprom_config].size = CONFIG_EEPROM_SIZE;
+ data->blocks[max6875_eeprom_config].base = CONFIG_EEPROM_BASE;
+ data->blocks[max6875_eeprom_config].data = &data->data[USER_EEPROM_SIZE];
+ data->blocks[max6875_eeprom_config].updated = &data->last_updated[USER_EEPROM_SLICES];
+
+ /* Setup the register section */
+ data->blocks[max6875_register_config].type = max6875_register_config;
+ data->blocks[max6875_register_config].slices = CONFIG_EEPROM_SLICES;
+ data->blocks[max6875_register_config].size = CONFIG_EEPROM_SIZE;
+ data->blocks[max6875_register_config].base = 0;
+ data->blocks[max6875_register_config].data = &data->data[USER_EEPROM_SIZE+CONFIG_EEPROM_SIZE];
+ data->blocks[max6875_register_config].updated = &data->last_updated[USER_EEPROM_SLICES+CONFIG_EEPROM_SLICES];
+
+ /* Init the data */
+ memset(data->data, 0xff, sizeof(data->data));
+
+ /* Fill in the remaining client fields */
+ strlcpy(new_client->name, "max6875", I2C_NAME_SIZE);
+ init_MUTEX(&data->update_lock);
+
+ /* Verify that the chip is really what we think it is */
+ if ((max6875_update_slice(new_client, &data->blocks[max6875_eeprom_config], 4) < 0) ||
+ (max6875_update_slice(new_client, &data->blocks[max6875_register_config], 4) < 0))
+ goto exit_kfree;
+
+ /* 0x41,0x42 must be zero and 0x40 must match in eeprom and registers */
+ if ((data->blocks[max6875_eeprom_config].data[0x41] != 0) ||
+ (data->blocks[max6875_eeprom_config].data[0x42] != 0) ||
+ (data->blocks[max6875_register_config].data[0x41] != 0) ||
+ (data->blocks[max6875_register_config].data[0x42] != 0) ||
+ (data->blocks[max6875_eeprom_config].data[0x40] !=
+ data->blocks[max6875_register_config].data[0x40]))
+ goto exit_kfree;
+
+ /* Tell the I2C layer a new client has arrived */
+ if ((err = i2c_attach_client(new_client)))
+ goto exit_kfree;
+
+ /* create the sysfs eeprom files with the correct permissions */
+ if (allow_write == 0) {
+ user_eeprom_attr.attr.mode &= ~S_IWUGO;
+ user_eeprom_attr.write = NULL;
+ config_eeprom_attr.attr.mode &= ~S_IWUGO;
+ config_eeprom_attr.write = NULL;
+ config_register_attr.attr.mode &= ~S_IWUGO;
+ config_register_attr.write = NULL;
+ }
+ sysfs_create_bin_file(&new_client->dev.kobj, &user_eeprom_attr);
+ sysfs_create_bin_file(&new_client->dev.kobj, &config_eeprom_attr);
+ sysfs_create_bin_file(&new_client->dev.kobj, &config_register_attr);
+
+ return 0;
+
+exit_kfree:
+ kfree(data);
+exit:
+ return err;
+}
+
+static int max6875_detach_client(struct i2c_client *client)
+{
+ int err;
+
+ err = i2c_detach_client(client);
+ if (err) {
+ dev_err(&client->dev, "Client deregistration failed, client not detached.\n");
+ return err;
+ }
+
+ kfree(i2c_get_clientdata(client));
+
+ return 0;
+}
+
+static int __init max6875_init(void)
+{
+ return i2c_add_driver(&max6875_driver);
+}
+
+static void __exit max6875_exit(void)
+{
+ i2c_del_driver(&max6875_driver);
+}
+
+
+MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
+MODULE_DESCRIPTION("MAX6875 driver");
+MODULE_LICENSE("GPL");
+
+module_init(max6875_init);
+module_exit(max6875_exit);
diff --git a/drivers/i2c/chips/pc87360.c b/drivers/i2c/chips/pc87360.c
index 6d94c36c921..876c68f3af3 100644
--- a/drivers/i2c/chips/pc87360.c
+++ b/drivers/i2c/chips/pc87360.c
@@ -33,7 +33,6 @@
* the standard Super-I/O addresses is used (0x2E/0x2F or 0x4E/0x4F).
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -282,31 +281,31 @@ static ssize_t set_fan_min(struct device *dev, const char *buf,
}
#define show_and_set_fan(offset) \
-static ssize_t show_fan##offset##_input(struct device *dev, char *buf) \
+static ssize_t show_fan##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct pc87360_data *data = pc87360_update_device(dev); \
return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan[offset-1], \
FAN_DIV_FROM_REG(data->fan_status[offset-1]))); \
} \
-static ssize_t show_fan##offset##_min(struct device *dev, char *buf) \
+static ssize_t show_fan##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct pc87360_data *data = pc87360_update_device(dev); \
return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan_min[offset-1], \
FAN_DIV_FROM_REG(data->fan_status[offset-1]))); \
} \
-static ssize_t show_fan##offset##_div(struct device *dev, char *buf) \
+static ssize_t show_fan##offset##_div(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct pc87360_data *data = pc87360_update_device(dev); \
return sprintf(buf, "%u\n", \
FAN_DIV_FROM_REG(data->fan_status[offset-1])); \
} \
-static ssize_t show_fan##offset##_status(struct device *dev, char *buf) \
+static ssize_t show_fan##offset##_status(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct pc87360_data *data = pc87360_update_device(dev); \
return sprintf(buf, "%u\n", \
FAN_STATUS_FROM_REG(data->fan_status[offset-1])); \
} \
-static ssize_t set_fan##offset##_min(struct device *dev, const char *buf, \
+static ssize_t set_fan##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
return set_fan_min(dev, buf, count, offset-1); \
@@ -324,7 +323,7 @@ show_and_set_fan(2)
show_and_set_fan(3)
#define show_and_set_pwm(offset) \
-static ssize_t show_pwm##offset(struct device *dev, char *buf) \
+static ssize_t show_pwm##offset(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct pc87360_data *data = pc87360_update_device(dev); \
return sprintf(buf, "%u\n", \
@@ -332,7 +331,7 @@ static ssize_t show_pwm##offset(struct device *dev, char *buf) \
FAN_CONFIG_INVERT(data->fan_conf, \
offset-1))); \
} \
-static ssize_t set_pwm##offset(struct device *dev, const char *buf, \
+static ssize_t set_pwm##offset(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
@@ -354,30 +353,30 @@ show_and_set_pwm(2)
show_and_set_pwm(3)
#define show_and_set_in(offset) \
-static ssize_t show_in##offset##_input(struct device *dev, char *buf) \
+static ssize_t show_in##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct pc87360_data *data = pc87360_update_device(dev); \
return sprintf(buf, "%u\n", IN_FROM_REG(data->in[offset], \
data->in_vref)); \
} \
-static ssize_t show_in##offset##_min(struct device *dev, char *buf) \
+static ssize_t show_in##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct pc87360_data *data = pc87360_update_device(dev); \
return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[offset], \
data->in_vref)); \
} \
-static ssize_t show_in##offset##_max(struct device *dev, char *buf) \
+static ssize_t show_in##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct pc87360_data *data = pc87360_update_device(dev); \
return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[offset], \
data->in_vref)); \
} \
-static ssize_t show_in##offset##_status(struct device *dev, char *buf) \
+static ssize_t show_in##offset##_status(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct pc87360_data *data = pc87360_update_device(dev); \
return sprintf(buf, "%u\n", data->in_status[offset]); \
} \
-static ssize_t set_in##offset##_min(struct device *dev, const char *buf, \
+static ssize_t set_in##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
@@ -391,7 +390,7 @@ static ssize_t set_in##offset##_min(struct device *dev, const char *buf, \
up(&data->update_lock); \
return count; \
} \
-static ssize_t set_in##offset##_max(struct device *dev, const char *buf, \
+static ssize_t set_in##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
@@ -427,36 +426,36 @@ show_and_set_in(9)
show_and_set_in(10)
#define show_and_set_therm(offset) \
-static ssize_t show_temp##offset##_input(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct pc87360_data *data = pc87360_update_device(dev); \
return sprintf(buf, "%u\n", IN_FROM_REG(data->in[offset+7], \
data->in_vref)); \
} \
-static ssize_t show_temp##offset##_min(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct pc87360_data *data = pc87360_update_device(dev); \
return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[offset+7], \
data->in_vref)); \
} \
-static ssize_t show_temp##offset##_max(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct pc87360_data *data = pc87360_update_device(dev); \
return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[offset+7], \
data->in_vref)); \
} \
-static ssize_t show_temp##offset##_crit(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_crit(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct pc87360_data *data = pc87360_update_device(dev); \
return sprintf(buf, "%u\n", IN_FROM_REG(data->in_crit[offset-4], \
data->in_vref)); \
} \
-static ssize_t show_temp##offset##_status(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_status(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct pc87360_data *data = pc87360_update_device(dev); \
return sprintf(buf, "%u\n", data->in_status[offset+7]); \
} \
-static ssize_t set_temp##offset##_min(struct device *dev, const char *buf, \
+static ssize_t set_temp##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
@@ -470,7 +469,7 @@ static ssize_t set_temp##offset##_min(struct device *dev, const char *buf, \
up(&data->update_lock); \
return count; \
} \
-static ssize_t set_temp##offset##_max(struct device *dev, const char *buf, \
+static ssize_t set_temp##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
@@ -484,7 +483,7 @@ static ssize_t set_temp##offset##_max(struct device *dev, const char *buf, \
up(&data->update_lock); \
return count; \
} \
-static ssize_t set_temp##offset##_crit(struct device *dev, const char *buf, \
+static ssize_t set_temp##offset##_crit(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
@@ -512,19 +511,19 @@ show_and_set_therm(4)
show_and_set_therm(5)
show_and_set_therm(6)
-static ssize_t show_vid(struct device *dev, char *buf)
+static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pc87360_data *data = pc87360_update_device(dev);
return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm));
}
static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
-static ssize_t show_vrm(struct device *dev, char *buf)
+static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pc87360_data *data = pc87360_update_device(dev);
return sprintf(buf, "%u\n", data->vrm);
}
-static ssize_t set_vrm(struct device *dev, const char *buf, size_t count)
+static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct pc87360_data *data = i2c_get_clientdata(client);
@@ -533,7 +532,7 @@ static ssize_t set_vrm(struct device *dev, const char *buf, size_t count)
}
static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
-static ssize_t show_in_alarms(struct device *dev, char *buf)
+static ssize_t show_in_alarms(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pc87360_data *data = pc87360_update_device(dev);
return sprintf(buf, "%u\n", data->in_alarms);
@@ -541,32 +540,32 @@ static ssize_t show_in_alarms(struct device *dev, char *buf)
static DEVICE_ATTR(alarms_in, S_IRUGO, show_in_alarms, NULL);
#define show_and_set_temp(offset) \
-static ssize_t show_temp##offset##_input(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct pc87360_data *data = pc87360_update_device(dev); \
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[offset-1])); \
} \
-static ssize_t show_temp##offset##_min(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct pc87360_data *data = pc87360_update_device(dev); \
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[offset-1])); \
} \
-static ssize_t show_temp##offset##_max(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct pc87360_data *data = pc87360_update_device(dev); \
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[offset-1])); \
}\
-static ssize_t show_temp##offset##_crit(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_crit(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct pc87360_data *data = pc87360_update_device(dev); \
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[offset-1])); \
}\
-static ssize_t show_temp##offset##_status(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_status(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct pc87360_data *data = pc87360_update_device(dev); \
return sprintf(buf, "%d\n", data->temp_status[offset-1]); \
}\
-static ssize_t set_temp##offset##_min(struct device *dev, const char *buf, \
+static ssize_t set_temp##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
@@ -580,7 +579,7 @@ static ssize_t set_temp##offset##_min(struct device *dev, const char *buf, \
up(&data->update_lock); \
return count; \
} \
-static ssize_t set_temp##offset##_max(struct device *dev, const char *buf, \
+static ssize_t set_temp##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
@@ -594,7 +593,7 @@ static ssize_t set_temp##offset##_max(struct device *dev, const char *buf, \
up(&data->update_lock); \
return count; \
} \
-static ssize_t set_temp##offset##_crit(struct device *dev, const char *buf, \
+static ssize_t set_temp##offset##_crit(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
struct i2c_client *client = to_i2c_client(dev); \
@@ -622,7 +621,7 @@ show_and_set_temp(1)
show_and_set_temp(2)
show_and_set_temp(3)
-static ssize_t show_temp_alarms(struct device *dev, char *buf)
+static ssize_t show_temp_alarms(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pc87360_data *data = pc87360_update_device(dev);
return sprintf(buf, "%u\n", data->temp_alarms);
diff --git a/drivers/i2c/chips/pca9539.c b/drivers/i2c/chips/pca9539.c
new file mode 100644
index 00000000000..9f3ad45daae
--- /dev/null
+++ b/drivers/i2c/chips/pca9539.c
@@ -0,0 +1,192 @@
+/*
+ pca9539.c - 16-bit I/O port with interrupt and reset
+
+ Copyright (C) 2005 Ben Gardner <bgardner@wabtec.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; version 2 of the License.
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/i2c-sensor.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = {0x74, 0x75, 0x76, 0x77, I2C_CLIENT_END};
+static unsigned int normal_isa[] = {I2C_CLIENT_ISA_END};
+
+/* Insmod parameters */
+SENSORS_INSMOD_1(pca9539);
+
+enum pca9539_cmd
+{
+ PCA9539_INPUT_0 = 0,
+ PCA9539_INPUT_1 = 1,
+ PCA9539_OUTPUT_0 = 2,
+ PCA9539_OUTPUT_1 = 3,
+ PCA9539_INVERT_0 = 4,
+ PCA9539_INVERT_1 = 5,
+ PCA9539_DIRECTION_0 = 6,
+ PCA9539_DIRECTION_1 = 7,
+};
+
+static int pca9539_attach_adapter(struct i2c_adapter *adapter);
+static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind);
+static int pca9539_detach_client(struct i2c_client *client);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver pca9539_driver = {
+ .owner = THIS_MODULE,
+ .name = "pca9539",
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = pca9539_attach_adapter,
+ .detach_client = pca9539_detach_client,
+};
+
+struct pca9539_data {
+ struct i2c_client client;
+};
+
+/* following are the sysfs callback functions */
+static ssize_t pca9539_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct sensor_device_attribute *psa = to_sensor_dev_attr(attr);
+ struct i2c_client *client = to_i2c_client(dev);
+ return sprintf(buf, "%d\n", i2c_smbus_read_byte_data(client,
+ psa->index));
+}
+
+static ssize_t pca9539_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct sensor_device_attribute *psa = to_sensor_dev_attr(attr);
+ struct i2c_client *client = to_i2c_client(dev);
+ unsigned long val = simple_strtoul(buf, NULL, 0);
+ if (val > 0xff)
+ return -EINVAL;
+ i2c_smbus_write_byte_data(client, psa->index, val);
+ return count;
+}
+
+/* Define the device attributes */
+
+#define PCA9539_ENTRY_RO(name, cmd_idx) \
+ static SENSOR_DEVICE_ATTR(name, S_IRUGO, pca9539_show, NULL, cmd_idx)
+
+#define PCA9539_ENTRY_RW(name, cmd_idx) \
+ static SENSOR_DEVICE_ATTR(name, S_IRUGO | S_IWUSR, pca9539_show, \
+ pca9539_store, cmd_idx)
+
+PCA9539_ENTRY_RO(input0, PCA9539_INPUT_0);
+PCA9539_ENTRY_RO(input1, PCA9539_INPUT_1);
+PCA9539_ENTRY_RW(output0, PCA9539_OUTPUT_0);
+PCA9539_ENTRY_RW(output1, PCA9539_OUTPUT_1);
+PCA9539_ENTRY_RW(invert0, PCA9539_INVERT_0);
+PCA9539_ENTRY_RW(invert1, PCA9539_INVERT_1);
+PCA9539_ENTRY_RW(direction0, PCA9539_DIRECTION_0);
+PCA9539_ENTRY_RW(direction1, PCA9539_DIRECTION_1);
+
+static struct attribute *pca9539_attributes[] = {
+ &sensor_dev_attr_input0.dev_attr.attr,
+ &sensor_dev_attr_input1.dev_attr.attr,
+ &sensor_dev_attr_output0.dev_attr.attr,
+ &sensor_dev_attr_output1.dev_attr.attr,
+ &sensor_dev_attr_invert0.dev_attr.attr,
+ &sensor_dev_attr_invert1.dev_attr.attr,
+ &sensor_dev_attr_direction0.dev_attr.attr,
+ &sensor_dev_attr_direction1.dev_attr.attr,
+ NULL
+};
+
+static struct attribute_group pca9539_defattr_group = {
+ .attrs = pca9539_attributes,
+};
+
+static int pca9539_attach_adapter(struct i2c_adapter *adapter)
+{
+ return i2c_detect(adapter, &addr_data, pca9539_detect);
+}
+
+/* This function is called by i2c_detect */
+static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+ struct i2c_client *new_client;
+ struct pca9539_data *data;
+ int err = 0;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ goto exit;
+
+ /* OK. For now, we presume we have a valid client. We now create the
+ client structure, even though we cannot fill it completely yet. */
+ if (!(data = kmalloc(sizeof(struct pca9539_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit;
+ }
+ memset(data, 0, sizeof(struct pca9539_data));
+
+ new_client = &data->client;
+ i2c_set_clientdata(new_client, data);
+ new_client->addr = address;
+ new_client->adapter = adapter;
+ new_client->driver = &pca9539_driver;
+ new_client->flags = 0;
+
+ /* Detection: the pca9539 only has 8 registers (0-7).
+ A read of 7 should succeed, but a read of 8 should fail. */
+ if ((i2c_smbus_read_byte_data(new_client, 7) < 0) ||
+ (i2c_smbus_read_byte_data(new_client, 8) >= 0))
+ goto exit_kfree;
+
+ strlcpy(new_client->name, "pca9539", I2C_NAME_SIZE);
+
+ /* Tell the I2C layer a new client has arrived */
+ if ((err = i2c_attach_client(new_client)))
+ goto exit_kfree;
+
+ /* Register sysfs hooks (don't care about failure) */
+ sysfs_create_group(&new_client->dev.kobj, &pca9539_defattr_group);
+
+ return 0;
+
+exit_kfree:
+ kfree(data);
+exit:
+ return err;
+}
+
+static int pca9539_detach_client(struct i2c_client *client)
+{
+ int err;
+
+ if ((err = i2c_detach_client(client))) {
+ dev_err(&client->dev, "Client deregistration failed.\n");
+ return err;
+ }
+
+ kfree(i2c_get_clientdata(client));
+ return 0;
+}
+
+static int __init pca9539_init(void)
+{
+ return i2c_add_driver(&pca9539_driver);
+}
+
+static void __exit pca9539_exit(void)
+{
+ i2c_del_driver(&pca9539_driver);
+}
+
+MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
+MODULE_DESCRIPTION("PCA9539 driver");
+MODULE_LICENSE("GPL");
+
+module_init(pca9539_init);
+module_exit(pca9539_exit);
+
diff --git a/drivers/i2c/chips/pcf8574.c b/drivers/i2c/chips/pcf8574.c
index 48b4e22eaff..cfcf6465408 100644
--- a/drivers/i2c/chips/pcf8574.c
+++ b/drivers/i2c/chips/pcf8574.c
@@ -57,7 +57,7 @@ SENSORS_INSMOD_2(pcf8574, pcf8574a);
struct pcf8574_data {
struct i2c_client client;
- u8 read, write; /* Register values */
+ u8 write; /* Remember last written value */
};
static int pcf8574_attach_adapter(struct i2c_adapter *adapter);
@@ -76,23 +76,21 @@ static struct i2c_driver pcf8574_driver = {
};
/* following are the sysfs callback functions */
-static ssize_t show_read(struct device *dev, char *buf)
+static ssize_t show_read(struct device *dev, struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
- struct pcf8574_data *data = i2c_get_clientdata(client);
- data->read = i2c_smbus_read_byte(client);
- return sprintf(buf, "%u\n", data->read);
+ return sprintf(buf, "%u\n", i2c_smbus_read_byte(client));
}
static DEVICE_ATTR(read, S_IRUGO, show_read, NULL);
-static ssize_t show_write(struct device *dev, char *buf)
+static ssize_t show_write(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pcf8574_data *data = i2c_get_clientdata(to_i2c_client(dev));
return sprintf(buf, "%u\n", data->write);
}
-static ssize_t set_write(struct device *dev, const char *buf,
+static ssize_t set_write(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c
index b6b927d8b37..db812ade856 100644
--- a/drivers/i2c/chips/pcf8591.c
+++ b/drivers/i2c/chips/pcf8591.c
@@ -100,7 +100,7 @@ static struct i2c_driver pcf8591_driver = {
/* following are the sysfs callback functions */
#define show_in_channel(channel) \
-static ssize_t show_in##channel##_input(struct device *dev, char *buf) \
+static ssize_t show_in##channel##_input(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return sprintf(buf, "%d\n", pcf8591_read_channel(dev, channel));\
} \
@@ -112,13 +112,13 @@ show_in_channel(1);
show_in_channel(2);
show_in_channel(3);
-static ssize_t show_out0_ouput(struct device *dev, char *buf)
+static ssize_t show_out0_ouput(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pcf8591_data *data = i2c_get_clientdata(to_i2c_client(dev));
return sprintf(buf, "%d\n", data->aout * 10);
}
-static ssize_t set_out0_output(struct device *dev, const char *buf, size_t count)
+static ssize_t set_out0_output(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
unsigned int value;
struct i2c_client *client = to_i2c_client(dev);
@@ -134,13 +134,13 @@ static ssize_t set_out0_output(struct device *dev, const char *buf, size_t count
static DEVICE_ATTR(out0_output, S_IWUSR | S_IRUGO,
show_out0_ouput, set_out0_output);
-static ssize_t show_out0_enable(struct device *dev, char *buf)
+static ssize_t show_out0_enable(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pcf8591_data *data = i2c_get_clientdata(to_i2c_client(dev));
return sprintf(buf, "%u\n", !(!(data->control & PCF8591_CONTROL_AOEF)));
}
-static ssize_t set_out0_enable(struct device *dev, const char *buf, size_t count)
+static ssize_t set_out0_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct pcf8591_data *data = i2c_get_clientdata(client);
diff --git a/drivers/i2c/chips/rtc8564.c b/drivers/i2c/chips/rtc8564.c
index 5a9deddb626..588fc2261a9 100644
--- a/drivers/i2c/chips/rtc8564.c
+++ b/drivers/i2c/chips/rtc8564.c
@@ -19,7 +19,6 @@
#include <linux/string.h>
#include <linux/rtc.h> /* get the user-level API */
#include <linux/init.h>
-#include <linux/init.h>
#include "rtc8564.h"
@@ -66,11 +65,8 @@ static unsigned short normal_addr[] = { 0x51, I2C_CLIENT_END };
static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_addr,
- .normal_i2c_range = ignore,
.probe = ignore,
- .probe_range = ignore,
.ignore = ignore,
- .ignore_range = ignore,
.force = ignore,
};
diff --git a/drivers/i2c/chips/sis5595.c b/drivers/i2c/chips/sis5595.c
index 7ea84532df3..6bbfc8fb4f1 100644
--- a/drivers/i2c/chips/sis5595.c
+++ b/drivers/i2c/chips/sis5595.c
@@ -57,6 +57,7 @@
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
#include <linux/init.h>
+#include <linux/jiffies.h>
#include <asm/io.h>
@@ -256,28 +257,28 @@ static ssize_t set_in_max(struct device *dev, const char *buf,
#define show_in_offset(offset) \
static ssize_t \
- show_in##offset (struct device *dev, char *buf) \
+ show_in##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_in(dev, buf, offset); \
} \
static DEVICE_ATTR(in##offset##_input, S_IRUGO, \
show_in##offset, NULL); \
static ssize_t \
- show_in##offset##_min (struct device *dev, char *buf) \
+ show_in##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_in_min(dev, buf, offset); \
} \
static ssize_t \
- show_in##offset##_max (struct device *dev, char *buf) \
+ show_in##offset##_max (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_in_max(dev, buf, offset); \
} \
-static ssize_t set_in##offset##_min (struct device *dev, \
+static ssize_t set_in##offset##_min (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_in_min(dev, buf, count, offset); \
} \
-static ssize_t set_in##offset##_max (struct device *dev, \
+static ssize_t set_in##offset##_max (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_in_max(dev, buf, count, offset); \
@@ -294,19 +295,19 @@ show_in_offset(3);
show_in_offset(4);
/* Temperature */
-static ssize_t show_temp(struct device *dev, char *buf)
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf)
{
struct sis5595_data *data = sis5595_update_device(dev);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp));
}
-static ssize_t show_temp_over(struct device *dev, char *buf)
+static ssize_t show_temp_over(struct device *dev, struct device_attribute *attr, char *buf)
{
struct sis5595_data *data = sis5595_update_device(dev);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over));
}
-static ssize_t set_temp_over(struct device *dev, const char *buf, size_t count)
+static ssize_t set_temp_over(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct sis5595_data *data = i2c_get_clientdata(client);
@@ -319,13 +320,13 @@ static ssize_t set_temp_over(struct device *dev, const char *buf, size_t count)
return count;
}
-static ssize_t show_temp_hyst(struct device *dev, char *buf)
+static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *attr, char *buf)
{
struct sis5595_data *data = sis5595_update_device(dev);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_hyst));
}
-static ssize_t set_temp_hyst(struct device *dev, const char *buf, size_t count)
+static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct sis5595_data *data = i2c_get_clientdata(client);
@@ -426,19 +427,19 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
}
#define show_fan_offset(offset) \
-static ssize_t show_fan_##offset (struct device *dev, char *buf) \
+static ssize_t show_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_fan(dev, buf, offset - 1); \
} \
-static ssize_t show_fan_##offset##_min (struct device *dev, char *buf) \
+static ssize_t show_fan_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_fan_min(dev, buf, offset - 1); \
} \
-static ssize_t show_fan_##offset##_div (struct device *dev, char *buf) \
+static ssize_t show_fan_##offset##_div (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_fan_div(dev, buf, offset - 1); \
} \
-static ssize_t set_fan_##offset##_min (struct device *dev, \
+static ssize_t set_fan_##offset##_min (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_fan_min(dev, buf, count, offset - 1); \
@@ -450,13 +451,13 @@ static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
show_fan_offset(1);
show_fan_offset(2);
-static ssize_t set_fan_1_div(struct device *dev, const char *buf,
+static ssize_t set_fan_1_div(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
return set_fan_div(dev, buf, count, 0) ;
}
-static ssize_t set_fan_2_div(struct device *dev, const char *buf,
+static ssize_t set_fan_2_div(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
return set_fan_div(dev, buf, count, 1) ;
@@ -467,7 +468,7 @@ static DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR,
show_fan_2_div, set_fan_2_div);
/* Alarms */
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
{
struct sis5595_data *data = sis5595_update_device(dev);
return sprintf(buf, "%d\n", data->alarms);
diff --git a/drivers/i2c/chips/smsc47b397.c b/drivers/i2c/chips/smsc47b397.c
index 1119c76791d..251ac265955 100644
--- a/drivers/i2c/chips/smsc47b397.c
+++ b/drivers/i2c/chips/smsc47b397.c
@@ -172,7 +172,7 @@ static ssize_t show_temp(struct device *dev, char *buf, int nr)
}
#define sysfs_temp(num) \
-static ssize_t show_temp##num(struct device *dev, char *buf) \
+static ssize_t show_temp##num(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_temp(dev, buf, num-1); \
} \
@@ -201,7 +201,7 @@ static ssize_t show_fan(struct device *dev, char *buf, int nr)
}
#define sysfs_fan(num) \
-static ssize_t show_fan##num(struct device *dev, char *buf) \
+static ssize_t show_fan##num(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_fan(dev, buf, num-1); \
} \
diff --git a/drivers/i2c/chips/smsc47m1.c b/drivers/i2c/chips/smsc47m1.c
index 0e12ca36941..897117a7213 100644
--- a/drivers/i2c/chips/smsc47m1.c
+++ b/drivers/i2c/chips/smsc47m1.c
@@ -184,7 +184,7 @@ static ssize_t get_pwm_en(struct device *dev, char *buf, int nr)
return sprintf(buf, "%d\n", PWM_EN_FROM_REG(data->pwm[nr]));
}
-static ssize_t get_alarms(struct device *dev, char *buf)
+static ssize_t get_alarms(struct device *dev, struct device_attribute *attr, char *buf)
{
struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
return sprintf(buf, "%d\n", data->alarms);
@@ -298,42 +298,42 @@ static ssize_t set_pwm_en(struct device *dev, const char *buf,
}
#define fan_present(offset) \
-static ssize_t get_fan##offset (struct device *dev, char *buf) \
+static ssize_t get_fan##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return get_fan(dev, buf, offset - 1); \
} \
-static ssize_t get_fan##offset##_min (struct device *dev, char *buf) \
+static ssize_t get_fan##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return get_fan_min(dev, buf, offset - 1); \
} \
-static ssize_t set_fan##offset##_min (struct device *dev, \
+static ssize_t set_fan##offset##_min (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_fan_min(dev, buf, count, offset - 1); \
} \
-static ssize_t get_fan##offset##_div (struct device *dev, char *buf) \
+static ssize_t get_fan##offset##_div (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return get_fan_div(dev, buf, offset - 1); \
} \
-static ssize_t set_fan##offset##_div (struct device *dev, \
+static ssize_t set_fan##offset##_div (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_fan_div(dev, buf, count, offset - 1); \
} \
-static ssize_t get_pwm##offset (struct device *dev, char *buf) \
+static ssize_t get_pwm##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return get_pwm(dev, buf, offset - 1); \
} \
-static ssize_t set_pwm##offset (struct device *dev, \
+static ssize_t set_pwm##offset (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_pwm(dev, buf, count, offset - 1); \
} \
-static ssize_t get_pwm##offset##_en (struct device *dev, char *buf) \
+static ssize_t get_pwm##offset##_en (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return get_pwm_en(dev, buf, offset - 1); \
} \
-static ssize_t set_pwm##offset##_en (struct device *dev, \
+static ssize_t set_pwm##offset##_en (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_pwm_en(dev, buf, count, offset - 1); \
@@ -372,14 +372,16 @@ static int smsc47m1_find(int *address)
* SMSC LPC47M10x/LPC47M13x (device id 0x59), LPC47M14x (device id
* 0x5F) and LPC47B27x (device id 0x51) have fan control.
* The LPC47M15x and LPC47M192 chips "with hardware monitoring block"
- * can do much more besides (device id 0x60, unsupported).
+ * can do much more besides (device id 0x60).
*/
if (val == 0x51)
- printk(KERN_INFO "smsc47m1: Found SMSC47B27x\n");
+ printk(KERN_INFO "smsc47m1: Found SMSC LPC47B27x\n");
else if (val == 0x59)
- printk(KERN_INFO "smsc47m1: Found SMSC47M10x/SMSC47M13x\n");
+ printk(KERN_INFO "smsc47m1: Found SMSC LPC47M10x/LPC47M13x\n");
else if (val == 0x5F)
- printk(KERN_INFO "smsc47m1: Found SMSC47M14x\n");
+ printk(KERN_INFO "smsc47m1: Found SMSC LPC47M14x\n");
+ else if (val == 0x60)
+ printk(KERN_INFO "smsc47m1: Found SMSC LPC47M15x/LPC47M192\n");
else {
superio_exit();
return -ENODEV;
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
new file mode 100644
index 00000000000..c0ac01b6003
--- /dev/null
+++ b/drivers/i2c/chips/tps65010.c
@@ -0,0 +1,1072 @@
+/*
+ * tps65010 - driver for tps6501x power management chips
+ *
+ * Copyright (C) 2004 Texas Instruments
+ * Copyright (C) 2004-2005 David Brownell
+ *
+ * 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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#undef DEBUG
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/workqueue.h>
+#include <linux/suspend.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/tps65010.h>
+
+/*-------------------------------------------------------------------------*/
+
+#define DRIVER_VERSION "2 May 2005"
+#define DRIVER_NAME (tps65010_driver.name)
+
+MODULE_DESCRIPTION("TPS6501x Power Management Driver");
+MODULE_LICENSE("GPL");
+
+/* only two addresses possible */
+#define TPS_BASE 0x48
+static unsigned short normal_i2c[] = {
+ TPS_BASE,
+ I2C_CLIENT_END };
+static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
+
+I2C_CLIENT_INSMOD;
+
+static struct i2c_driver tps65010_driver;
+
+/*-------------------------------------------------------------------------*/
+
+/* This driver handles a family of multipurpose chips, which incorporate
+ * voltage regulators, lithium ion/polymer battery charging, GPIOs, LEDs,
+ * and other features often needed in portable devices like cell phones
+ * or digital cameras.
+ *
+ * The tps65011 and tps65013 have different voltage settings compared
+ * to tps65010 and tps65012. The tps65013 has a NO_CHG status/irq.
+ * All except tps65010 have "wait" mode, possibly defaulted so that
+ * battery-insert != device-on.
+ *
+ * We could distinguish between some models by checking VDCDC1.UVLO or
+ * other registers, unless they've been changed already after powerup
+ * as part of board setup by a bootloader.
+ */
+enum tps_model {
+ TPS_UNKNOWN = 0,
+ TPS65010,
+ TPS65011,
+ TPS65012,
+ TPS65013,
+};
+
+struct tps65010 {
+ struct i2c_client client;
+ struct semaphore lock;
+ int irq;
+ struct work_struct work;
+ struct dentry *file;
+ unsigned charging:1;
+ unsigned por:1;
+ unsigned model:8;
+ u16 vbus;
+ unsigned long flags;
+#define FLAG_VBUS_CHANGED 0
+#define FLAG_IRQ_ENABLE 1
+
+ /* copies of last register state */
+ u8 chgstatus, regstatus, chgconf;
+ u8 nmask1, nmask2;
+
+ /* plus four GPIOs, probably used to switch power */
+};
+
+#define POWER_POLL_DELAY msecs_to_jiffies(800)
+
+/*-------------------------------------------------------------------------*/
+
+#if defined(DEBUG) || defined(CONFIG_DEBUG_FS)
+
+static void dbg_chgstat(char *buf, size_t len, u8 chgstatus)
+{
+ snprintf(buf, len, "%02x%s%s%s%s%s%s%s%s\n",
+ chgstatus,
+ (chgstatus & TPS_CHG_USB) ? " USB" : "",
+ (chgstatus & TPS_CHG_AC) ? " AC" : "",
+ (chgstatus & TPS_CHG_THERM) ? " therm" : "",
+ (chgstatus & TPS_CHG_TERM) ? " done" :
+ ((chgstatus & (TPS_CHG_USB|TPS_CHG_AC))
+ ? " (charging)" : ""),
+ (chgstatus & TPS_CHG_TAPER_TMO) ? " taper_tmo" : "",
+ (chgstatus & TPS_CHG_CHG_TMO) ? " charge_tmo" : "",
+ (chgstatus & TPS_CHG_PRECHG_TMO) ? " prechg_tmo" : "",
+ (chgstatus & TPS_CHG_TEMP_ERR) ? " temp_err" : "");
+}
+
+static void dbg_regstat(char *buf, size_t len, u8 regstatus)
+{
+ snprintf(buf, len, "%02x %s%s%s%s%s%s%s%s\n",
+ regstatus,
+ (regstatus & TPS_REG_ONOFF) ? "off" : "(on)",
+ (regstatus & TPS_REG_COVER) ? " uncover" : "",
+ (regstatus & TPS_REG_UVLO) ? " UVLO" : "",
+ (regstatus & TPS_REG_NO_CHG) ? " NO_CHG" : "",
+ (regstatus & TPS_REG_PG_LD02) ? " ld01_bad" : "",
+ (regstatus & TPS_REG_PG_LD01) ? " ld01_bad" : "",
+ (regstatus & TPS_REG_PG_MAIN) ? " main_bad" : "",
+ (regstatus & TPS_REG_PG_CORE) ? " core_bad" : "");
+}
+
+static void dbg_chgconf(int por, char *buf, size_t len, u8 chgconfig)
+{
+ char *hibit;
+
+ if (por)
+ hibit = (chgconfig & TPS_CHARGE_POR)
+ ? "POR=69ms" : "POR=1sec";
+ else
+ hibit = (chgconfig & TPS65013_AUA) ? "AUA" : "";
+
+ snprintf(buf, len, "%02x %s%s%s AC=%d%% USB=%dmA %sCharge\n",
+ chgconfig, hibit,
+ (chgconfig & TPS_CHARGE_RESET) ? " reset" : "",
+ (chgconfig & TPS_CHARGE_FAST) ? " fast" : "",
+ ({int p; switch ((chgconfig >> 3) & 3) {
+ case 3: p = 100; break;
+ case 2: p = 75; break;
+ case 1: p = 50; break;
+ default: p = 25; break;
+ }; p; }),
+ (chgconfig & TPS_VBUS_CHARGING)
+ ? ((chgconfig & TPS_VBUS_500MA) ? 500 : 100)
+ : 0,
+ (chgconfig & TPS_CHARGE_ENABLE) ? "" : "No");
+}
+
+#endif
+
+#ifdef DEBUG
+
+static void show_chgstatus(const char *label, u8 chgstatus)
+{
+ char buf [100];
+
+ dbg_chgstat(buf, sizeof buf, chgstatus);
+ pr_debug("%s: %s %s", DRIVER_NAME, label, buf);
+}
+
+static void show_regstatus(const char *label, u8 regstatus)
+{
+ char buf [100];
+
+ dbg_regstat(buf, sizeof buf, regstatus);
+ pr_debug("%s: %s %s", DRIVER_NAME, label, buf);
+}
+
+static void show_chgconfig(int por, const char *label, u8 chgconfig)
+{
+ char buf [100];
+
+ dbg_chgconf(por, buf, sizeof buf, chgconfig);
+ pr_debug("%s: %s %s", DRIVER_NAME, label, buf);
+}
+
+#else
+
+static inline void show_chgstatus(const char *label, u8 chgstatus) { }
+static inline void show_regstatus(const char *label, u8 chgstatus) { }
+static inline void show_chgconfig(int por, const char *label, u8 chgconfig) { }
+
+#endif
+
+#ifdef CONFIG_DEBUG_FS
+
+static int dbg_show(struct seq_file *s, void *_)
+{
+ struct tps65010 *tps = s->private;
+ u8 value, v2;
+ unsigned i;
+ char buf[100];
+ const char *chip;
+
+ switch (tps->model) {
+ case TPS65010: chip = "tps65010"; break;
+ case TPS65011: chip = "tps65011"; break;
+ case TPS65012: chip = "tps65012"; break;
+ case TPS65013: chip = "tps65013"; break;
+ default: chip = NULL; break;
+ }
+ seq_printf(s, "driver %s\nversion %s\nchip %s\n\n",
+ DRIVER_NAME, DRIVER_VERSION, chip);
+
+ down(&tps->lock);
+
+ /* FIXME how can we tell whether a battery is present?
+ * likely involves a charge gauging chip (like BQ26501).
+ */
+
+ seq_printf(s, "%scharging\n\n", tps->charging ? "" : "(not) ");
+
+
+ /* registers for monitoring battery charging and status; note
+ * that reading chgstat and regstat may ack IRQs...
+ */
+ value = i2c_smbus_read_byte_data(&tps->client, TPS_CHGCONFIG);
+ dbg_chgconf(tps->por, buf, sizeof buf, value);
+ seq_printf(s, "chgconfig %s", buf);
+
+ value = i2c_smbus_read_byte_data(&tps->client, TPS_CHGSTATUS);
+ dbg_chgstat(buf, sizeof buf, value);
+ seq_printf(s, "chgstat %s", buf);
+ value = i2c_smbus_read_byte_data(&tps->client, TPS_MASK1);
+ dbg_chgstat(buf, sizeof buf, value);
+ seq_printf(s, "mask1 %s", buf);
+ /* ignore ackint1 */
+
+ value = i2c_smbus_read_byte_data(&tps->client, TPS_REGSTATUS);
+ dbg_regstat(buf, sizeof buf, value);
+ seq_printf(s, "regstat %s", buf);
+ value = i2c_smbus_read_byte_data(&tps->client, TPS_MASK2);
+ dbg_regstat(buf, sizeof buf, value);
+ seq_printf(s, "mask2 %s\n", buf);
+ /* ignore ackint2 */
+
+ (void) schedule_delayed_work(&tps->work, POWER_POLL_DELAY);
+
+
+ /* VMAIN voltage, enable lowpower, etc */
+ value = i2c_smbus_read_byte_data(&tps->client, TPS_VDCDC1);
+ seq_printf(s, "vdcdc1 %02x\n", value);
+
+ /* VCORE voltage, vibrator on/off */
+ value = i2c_smbus_read_byte_data(&tps->client, TPS_VDCDC2);
+ seq_printf(s, "vdcdc2 %02x\n", value);
+
+ /* both LD0s, and their lowpower behavior */
+ value = i2c_smbus_read_byte_data(&tps->client, TPS_VREGS1);
+ seq_printf(s, "vregs1 %02x\n\n", value);
+
+
+ /* LEDs and GPIOs */
+ value = i2c_smbus_read_byte_data(&tps->client, TPS_LED1_ON);
+ v2 = i2c_smbus_read_byte_data(&tps->client, TPS_LED1_PER);
+ seq_printf(s, "led1 %s, on=%02x, per=%02x, %d/%d msec\n",
+ (value & 0x80)
+ ? ((v2 & 0x80) ? "on" : "off")
+ : ((v2 & 0x80) ? "blink" : "(nPG)"),
+ value, v2,
+ (value & 0x7f) * 10, (v2 & 0x7f) * 100);
+
+ value = i2c_smbus_read_byte_data(&tps->client, TPS_LED2_ON);
+ v2 = i2c_smbus_read_byte_data(&tps->client, TPS_LED2_PER);
+ seq_printf(s, "led2 %s, on=%02x, per=%02x, %d/%d msec\n",
+ (value & 0x80)
+ ? ((v2 & 0x80) ? "on" : "off")
+ : ((v2 & 0x80) ? "blink" : "off"),
+ value, v2,
+ (value & 0x7f) * 10, (v2 & 0x7f) * 100);
+
+ value = i2c_smbus_read_byte_data(&tps->client, TPS_DEFGPIO);
+ v2 = i2c_smbus_read_byte_data(&tps->client, TPS_MASK3);
+ seq_printf(s, "defgpio %02x mask3 %02x\n", value, v2);
+
+ for (i = 0; i < 4; i++) {
+ if (value & (1 << (4 +i)))
+ seq_printf(s, " gpio%d-out %s\n", i + 1,
+ (value & (1 << i)) ? "low" : "hi ");
+ else
+ seq_printf(s, " gpio%d-in %s %s %s\n", i + 1,
+ (value & (1 << i)) ? "hi " : "low",
+ (v2 & (1 << i)) ? "no-irq" : "irq",
+ (v2 & (1 << (4 + i))) ? "rising" : "falling");
+ }
+
+ up(&tps->lock);
+ return 0;
+}
+
+static int dbg_tps_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, dbg_show, inode->u.generic_ip);
+}
+
+static struct file_operations debug_fops = {
+ .open = dbg_tps_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+#define DEBUG_FOPS &debug_fops
+
+#else
+#define DEBUG_FOPS NULL
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/* handle IRQS in a task context, so we can use I2C calls */
+static void tps65010_interrupt(struct tps65010 *tps)
+{
+ u8 tmp = 0, mask, poll;
+
+ /* IRQs won't trigger irqs for certain events, but we can get
+ * others by polling (normally, with external power applied).
+ */
+ poll = 0;
+
+ /* regstatus irqs */
+ if (tps->nmask2) {
+ tmp = i2c_smbus_read_byte_data(&tps->client, TPS_REGSTATUS);
+ mask = tmp ^ tps->regstatus;
+ tps->regstatus = tmp;
+ mask &= tps->nmask2;
+ } else
+ mask = 0;
+ if (mask) {
+ tps->regstatus = tmp;
+ /* may need to shut something down ... */
+
+ /* "off" usually means deep sleep */
+ if (tmp & TPS_REG_ONOFF) {
+ pr_info("%s: power off button\n", DRIVER_NAME);
+#if 0
+ /* REVISIT: this might need its own workqueue
+ * plus tweaks including deadlock avoidance ...
+ */
+ software_suspend();
+#endif
+ poll = 1;
+ }
+ }
+
+ /* chgstatus irqs */
+ if (tps->nmask1) {
+ tmp = i2c_smbus_read_byte_data(&tps->client, TPS_CHGSTATUS);
+ mask = tmp ^ tps->chgstatus;
+ tps->chgstatus = tmp;
+ mask &= tps->nmask1;
+ } else
+ mask = 0;
+ if (mask) {
+ unsigned charging = 0;
+
+ show_chgstatus("chg/irq", tmp);
+ if (tmp & (TPS_CHG_USB|TPS_CHG_AC))
+ show_chgconfig(tps->por, "conf", tps->chgconf);
+
+ /* Unless it was turned off or disabled, we charge any
+ * battery whenever there's power available for it
+ * and the charger hasn't been disabled.
+ */
+ if (!(tps->chgstatus & ~(TPS_CHG_USB|TPS_CHG_AC))
+ && (tps->chgstatus & (TPS_CHG_USB|TPS_CHG_AC))
+ && (tps->chgconf & TPS_CHARGE_ENABLE)
+ ) {
+ if (tps->chgstatus & TPS_CHG_USB) {
+ /* VBUS options are readonly until reconnect */
+ if (mask & TPS_CHG_USB)
+ set_bit(FLAG_VBUS_CHANGED, &tps->flags);
+ charging = 1;
+ } else if (tps->chgstatus & TPS_CHG_AC)
+ charging = 1;
+ }
+ if (charging != tps->charging) {
+ tps->charging = charging;
+ pr_info("%s: battery %scharging\n",
+ DRIVER_NAME, charging ? "" :
+ ((tps->chgstatus & (TPS_CHG_USB|TPS_CHG_AC))
+ ? "NOT " : "dis"));
+ }
+ }
+
+ /* always poll to detect (a) power removal, without tps65013
+ * NO_CHG IRQ; or (b) restart of charging after stop.
+ */
+ if ((tps->model != TPS65013 || !tps->charging)
+ && (tps->chgstatus & (TPS_CHG_USB|TPS_CHG_AC)))
+ poll = 1;
+ if (poll)
+ (void) schedule_delayed_work(&tps->work, POWER_POLL_DELAY);
+
+ /* also potentially gpio-in rise or fall */
+}
+
+/* handle IRQs and polling using keventd for now */
+static void tps65010_work(void *_tps)
+{
+ struct tps65010 *tps = _tps;
+
+ down(&tps->lock);
+
+ tps65010_interrupt(tps);
+
+ if (test_and_clear_bit(FLAG_VBUS_CHANGED, &tps->flags)) {
+ int status;
+ u8 chgconfig, tmp;
+
+ chgconfig = i2c_smbus_read_byte_data(&tps->client,
+ TPS_CHGCONFIG);
+ chgconfig &= ~(TPS_VBUS_500MA | TPS_VBUS_CHARGING);
+ if (tps->vbus == 500)
+ chgconfig |= TPS_VBUS_500MA | TPS_VBUS_CHARGING;
+ else if (tps->vbus >= 100)
+ chgconfig |= TPS_VBUS_CHARGING;
+
+ status = i2c_smbus_write_byte_data(&tps->client,
+ TPS_CHGCONFIG, chgconfig);
+
+ /* vbus update fails unless VBUS is connected! */
+ tmp = i2c_smbus_read_byte_data(&tps->client, TPS_CHGCONFIG);
+ tps->chgconf = tmp;
+ show_chgconfig(tps->por, "update vbus", tmp);
+ }
+
+ if (test_and_clear_bit(FLAG_IRQ_ENABLE, &tps->flags))
+ enable_irq(tps->irq);
+
+ up(&tps->lock);
+}
+
+static irqreturn_t tps65010_irq(int irq, void *_tps, struct pt_regs *regs)
+{
+ struct tps65010 *tps = _tps;
+
+ disable_irq_nosync(irq);
+ set_bit(FLAG_IRQ_ENABLE, &tps->flags);
+ (void) schedule_work(&tps->work);
+ return IRQ_HANDLED;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct tps65010 *the_tps;
+
+static int __exit tps65010_detach_client(struct i2c_client *client)
+{
+ struct tps65010 *tps;
+
+ tps = container_of(client, struct tps65010, client);
+#ifdef CONFIG_ARM
+ if (machine_is_omap_h2())
+ omap_free_gpio(58);
+ if (machine_is_omap_osk())
+ omap_free_gpio(OMAP_MPUIO(1));
+#endif
+ free_irq(tps->irq, tps);
+ debugfs_remove(tps->file);
+ if (i2c_detach_client(client) == 0)
+ kfree(tps);
+ the_tps = 0;
+ return 0;
+}
+
+static int tps65010_noscan(struct i2c_adapter *bus)
+{
+ /* pure paranoia, in case someone adds another i2c bus
+ * after our init section's gone...
+ */
+ return -ENODEV;
+}
+
+/* no error returns, they'd just make bus scanning stop */
+static int __init
+tps65010_probe(struct i2c_adapter *bus, int address, int kind)
+{
+ struct tps65010 *tps;
+ int status;
+
+ if (the_tps) {
+ dev_dbg(&bus->dev, "only one %s for now\n", DRIVER_NAME);
+ return 0;
+ }
+
+ tps = kmalloc(sizeof *tps, GFP_KERNEL);
+ if (!tps)
+ return 0;
+
+ memset(tps, 0, sizeof *tps);
+ init_MUTEX(&tps->lock);
+ INIT_WORK(&tps->work, tps65010_work, tps);
+ tps->irq = -1;
+ tps->client.addr = address;
+ i2c_set_clientdata(&tps->client, tps);
+ tps->client.adapter = bus;
+ tps->client.driver = &tps65010_driver;
+ strlcpy(tps->client.name, DRIVER_NAME, I2C_NAME_SIZE);
+
+ status = i2c_attach_client(&tps->client);
+ if (status < 0) {
+ dev_dbg(&bus->dev, "can't attach %s to device %d, err %d\n",
+ DRIVER_NAME, address, status);
+fail1:
+ kfree(tps);
+ return 0;
+ }
+
+#ifdef CONFIG_ARM
+ if (machine_is_omap_h2()) {
+ tps->model = TPS65010;
+ omap_cfg_reg(W4_GPIO58);
+ tps->irq = OMAP_GPIO_IRQ(58);
+ omap_request_gpio(58);
+ omap_set_gpio_direction(58, 1);
+ omap_set_gpio_edge_ctrl(58, OMAP_GPIO_FALLING_EDGE);
+ }
+ if (machine_is_omap_osk()) {
+ tps->model = TPS65010;
+ // omap_cfg_reg(U19_1610_MPUIO1);
+ tps->irq = OMAP_GPIO_IRQ(OMAP_MPUIO(1));
+ omap_request_gpio(OMAP_MPUIO(1));
+ omap_set_gpio_direction(OMAP_MPUIO(1), 1);
+ omap_set_gpio_edge_ctrl(OMAP_MPUIO(1), OMAP_GPIO_FALLING_EDGE);
+ }
+ if (machine_is_omap_h3()) {
+ tps->model = TPS65013;
+
+ // FIXME set up this board's IRQ ...
+ }
+#else
+#define set_irq_type(num,trigger) do{}while(0)
+#endif
+
+ if (tps->irq > 0) {
+ set_irq_type(tps->irq, IRQT_LOW);
+ status = request_irq(tps->irq, tps65010_irq,
+ SA_SAMPLE_RANDOM, DRIVER_NAME, tps);
+ if (status < 0) {
+ dev_dbg(&tps->client.dev, "can't get IRQ %d, err %d\n",
+ tps->irq, status);
+ i2c_detach_client(&tps->client);
+ goto fail1;
+ }
+#ifdef CONFIG_ARM
+ /* annoying race here, ideally we'd have an option
+ * to claim the irq now and enable it later.
+ */
+ disable_irq(tps->irq);
+ set_bit(FLAG_IRQ_ENABLE, &tps->flags);
+#endif
+ } else
+ printk(KERN_WARNING "%s: IRQ not configured!\n",
+ DRIVER_NAME);
+
+
+ switch (tps->model) {
+ case TPS65010:
+ case TPS65012:
+ tps->por = 1;
+ break;
+ case TPS_UNKNOWN:
+ printk(KERN_WARNING "%s: unknown TPS chip\n", DRIVER_NAME);
+ break;
+ /* else CHGCONFIG.POR is replaced by AUA, enabling a WAIT mode */
+ }
+ tps->chgconf = i2c_smbus_read_byte_data(&tps->client, TPS_CHGCONFIG);
+ show_chgconfig(tps->por, "conf/init", tps->chgconf);
+
+ show_chgstatus("chg/init",
+ i2c_smbus_read_byte_data(&tps->client, TPS_CHGSTATUS));
+ show_regstatus("reg/init",
+ i2c_smbus_read_byte_data(&tps->client, TPS_REGSTATUS));
+
+ pr_debug("%s: vdcdc1 0x%02x, vdcdc2 %02x, vregs1 %02x\n", DRIVER_NAME,
+ i2c_smbus_read_byte_data(&tps->client, TPS_VDCDC1),
+ i2c_smbus_read_byte_data(&tps->client, TPS_VDCDC2),
+ i2c_smbus_read_byte_data(&tps->client, TPS_VREGS1));
+ pr_debug("%s: defgpio 0x%02x, mask3 0x%02x\n", DRIVER_NAME,
+ i2c_smbus_read_byte_data(&tps->client, TPS_DEFGPIO),
+ i2c_smbus_read_byte_data(&tps->client, TPS_MASK3));
+
+ tps65010_driver.attach_adapter = tps65010_noscan;
+ the_tps = tps;
+
+#if defined(CONFIG_USB_GADGET) && !defined(CONFIG_USB_OTG)
+ /* USB hosts can't draw VBUS. OTG devices could, later
+ * when OTG infrastructure enables it. USB peripherals
+ * could be relying on VBUS while booting, though.
+ */
+ tps->vbus = 100;
+#endif
+
+ /* unmask the "interesting" irqs, then poll once to
+ * kickstart monitoring, initialize shadowed status
+ * registers, and maybe disable VBUS draw.
+ */
+ tps->nmask1 = ~0;
+ (void) i2c_smbus_write_byte_data(&tps->client, TPS_MASK1, ~tps->nmask1);
+
+ tps->nmask2 = TPS_REG_ONOFF;
+ if (tps->model == TPS65013)
+ tps->nmask2 |= TPS_REG_NO_CHG;
+ (void) i2c_smbus_write_byte_data(&tps->client, TPS_MASK2, ~tps->nmask2);
+
+ (void) i2c_smbus_write_byte_data(&tps->client, TPS_MASK3, 0x0f
+ | i2c_smbus_read_byte_data(&tps->client, TPS_MASK3));
+
+ tps65010_work(tps);
+
+ tps->file = debugfs_create_file(DRIVER_NAME, S_IRUGO, NULL,
+ tps, DEBUG_FOPS);
+ return 0;
+}
+
+static int __init tps65010_scan_bus(struct i2c_adapter *bus)
+{
+ if (!i2c_check_functionality(bus, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -EINVAL;
+ return i2c_probe(bus, &addr_data, tps65010_probe);
+}
+
+static struct i2c_driver tps65010_driver = {
+ .owner = THIS_MODULE,
+ .name = "tps65010",
+ .id = 888, /* FIXME assign "official" value */
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = tps65010_scan_bus,
+ .detach_client = __exit_p(tps65010_detach_client),
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* Draw from VBUS:
+ * 0 mA -- DON'T DRAW (might supply power instead)
+ * 100 mA -- usb unit load (slowest charge rate)
+ * 500 mA -- usb high power (fast battery charge)
+ */
+int tps65010_set_vbus_draw(unsigned mA)
+{
+ unsigned long flags;
+
+ if (!the_tps)
+ return -ENODEV;
+
+ /* assumes non-SMP */
+ local_irq_save(flags);
+ if (mA >= 500)
+ mA = 500;
+ else if (mA >= 100)
+ mA = 100;
+ else
+ mA = 0;
+ the_tps->vbus = mA;
+ if ((the_tps->chgstatus & TPS_CHG_USB)
+ && test_and_set_bit(
+ FLAG_VBUS_CHANGED, &the_tps->flags)) {
+ /* gadget drivers call this in_irq() */
+ (void) schedule_work(&the_tps->work);
+ }
+ local_irq_restore(flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(tps65010_set_vbus_draw);
+
+/*-------------------------------------------------------------------------*/
+/* tps65010_set_gpio_out_value parameter:
+ * gpio: GPIO1, GPIO2, GPIO3 or GPIO4
+ * value: LOW or HIGH
+ */
+int tps65010_set_gpio_out_value(unsigned gpio, unsigned value)
+{
+ int status;
+ unsigned defgpio;
+
+ if (!the_tps)
+ return -ENODEV;
+ if ((gpio < GPIO1) || (gpio > GPIO4))
+ return -EINVAL;
+
+ down(&the_tps->lock);
+
+ defgpio = i2c_smbus_read_byte_data(&the_tps->client, TPS_DEFGPIO);
+
+ /* Configure GPIO for output */
+ defgpio |= 1 << (gpio + 3);
+
+ /* Writing 1 forces a logic 0 on that GPIO and vice versa */
+ switch (value) {
+ case LOW:
+ defgpio |= 1 << (gpio - 1); /* set GPIO low by writing 1 */
+ break;
+ /* case HIGH: */
+ default:
+ defgpio &= ~(1 << (gpio - 1)); /* set GPIO high by writing 0 */
+ break;
+ }
+
+ status = i2c_smbus_write_byte_data(&the_tps->client,
+ TPS_DEFGPIO, defgpio);
+
+ pr_debug("%s: gpio%dout = %s, defgpio 0x%02x\n", DRIVER_NAME,
+ gpio, value ? "high" : "low",
+ i2c_smbus_read_byte_data(&the_tps->client, TPS_DEFGPIO));
+
+ up(&the_tps->lock);
+ return status;
+}
+EXPORT_SYMBOL(tps65010_set_gpio_out_value);
+
+/*-------------------------------------------------------------------------*/
+/* tps65010_set_led parameter:
+ * led: LED1 or LED2
+ * mode: ON, OFF or BLINK
+ */
+int tps65010_set_led(unsigned led, unsigned mode)
+{
+ int status;
+ unsigned led_on, led_per, offs;
+
+ if (!the_tps)
+ return -ENODEV;
+
+ if(led == LED1)
+ offs = 0;
+ else {
+ offs = 2;
+ led = LED2;
+ }
+
+ down(&the_tps->lock);
+
+ dev_dbg (&the_tps->client.dev, "led%i_on 0x%02x\n", led,
+ i2c_smbus_read_byte_data(&the_tps->client, TPS_LED1_ON + offs));
+
+ dev_dbg (&the_tps->client.dev, "led%i_per 0x%02x\n", led,
+ i2c_smbus_read_byte_data(&the_tps->client, TPS_LED1_PER + offs));
+
+ switch (mode) {
+ case OFF:
+ led_on = 1 << 7;
+ led_per = 0 << 7;
+ break;
+ case ON:
+ led_on = 1 << 7;
+ led_per = 1 << 7;
+ break;
+ case BLINK:
+ led_on = 0x30 | (0 << 7);
+ led_per = 0x08 | (1 << 7);
+ break;
+ default:
+ printk(KERN_ERR "%s: Wrong mode parameter for tps65010_set_led()\n",
+ DRIVER_NAME);
+ up(&the_tps->lock);
+ return -EINVAL;
+ }
+
+ status = i2c_smbus_write_byte_data(&the_tps->client,
+ TPS_LED1_ON + offs, led_on);
+
+ if (status != 0) {
+ printk(KERN_ERR "%s: Failed to write led%i_on register\n",
+ DRIVER_NAME, led);
+ up(&the_tps->lock);
+ return status;
+ }
+
+ dev_dbg (&the_tps->client.dev, "led%i_on 0x%02x\n", led,
+ i2c_smbus_read_byte_data(&the_tps->client, TPS_LED1_ON + offs));
+
+ status = i2c_smbus_write_byte_data(&the_tps->client,
+ TPS_LED1_PER + offs, led_per);
+
+ if (status != 0) {
+ printk(KERN_ERR "%s: Failed to write led%i_per register\n",
+ DRIVER_NAME, led);
+ up(&the_tps->lock);
+ return status;
+ }
+
+ dev_dbg (&the_tps->client.dev, "led%i_per 0x%02x\n", led,
+ i2c_smbus_read_byte_data(&the_tps->client, TPS_LED1_PER + offs));
+
+ up(&the_tps->lock);
+
+ return status;
+}
+EXPORT_SYMBOL(tps65010_set_led);
+
+/*-------------------------------------------------------------------------*/
+/* tps65010_set_vib parameter:
+ * value: ON or OFF
+ */
+int tps65010_set_vib(unsigned value)
+{
+ int status;
+ unsigned vdcdc2;
+
+ if (!the_tps)
+ return -ENODEV;
+
+ down(&the_tps->lock);
+
+ vdcdc2 = i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC2);
+ vdcdc2 &= ~(1 << 1);
+ if (value)
+ vdcdc2 |= (1 << 1);
+ status = i2c_smbus_write_byte_data(&the_tps->client,
+ TPS_VDCDC2, vdcdc2);
+
+ pr_debug("%s: vibrator %s\n", DRIVER_NAME, value ? "on" : "off");
+
+ up(&the_tps->lock);
+ return status;
+}
+EXPORT_SYMBOL(tps65010_set_vib);
+
+/*-------------------------------------------------------------------------*/
+/* tps65010_set_low_pwr parameter:
+ * mode: ON or OFF
+ */
+int tps65010_set_low_pwr(unsigned mode)
+{
+ int status;
+ unsigned vdcdc1;
+
+ if (!the_tps)
+ return -ENODEV;
+
+ down(&the_tps->lock);
+
+ pr_debug("%s: %s low_pwr, vdcdc1 0x%02x\n", DRIVER_NAME,
+ mode ? "enable" : "disable",
+ i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1));
+
+ vdcdc1 = i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1);
+
+ switch (mode) {
+ case OFF:
+ vdcdc1 &= ~TPS_ENABLE_LP; /* disable ENABLE_LP bit */
+ break;
+ /* case ON: */
+ default:
+ vdcdc1 |= TPS_ENABLE_LP; /* enable ENABLE_LP bit */
+ break;
+ }
+
+ status = i2c_smbus_write_byte_data(&the_tps->client,
+ TPS_VDCDC1, vdcdc1);
+
+ if (status != 0)
+ printk(KERN_ERR "%s: Failed to write vdcdc1 register\n",
+ DRIVER_NAME);
+ else
+ pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME,
+ i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1));
+
+ up(&the_tps->lock);
+
+ return status;
+}
+EXPORT_SYMBOL(tps65010_set_low_pwr);
+
+/*-------------------------------------------------------------------------*/
+/* tps65010_config_vregs1 parameter:
+ * value to be written to VREGS1 register
+ * Note: The complete register is written, set all bits you need
+ */
+int tps65010_config_vregs1(unsigned value)
+{
+ int status;
+
+ if (!the_tps)
+ return -ENODEV;
+
+ down(&the_tps->lock);
+
+ pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME,
+ i2c_smbus_read_byte_data(&the_tps->client, TPS_VREGS1));
+
+ status = i2c_smbus_write_byte_data(&the_tps->client,
+ TPS_VREGS1, value);
+
+ if (status != 0)
+ printk(KERN_ERR "%s: Failed to write vregs1 register\n",
+ DRIVER_NAME);
+ else
+ pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME,
+ i2c_smbus_read_byte_data(&the_tps->client, TPS_VREGS1));
+
+ up(&the_tps->lock);
+
+ return status;
+}
+EXPORT_SYMBOL(tps65010_config_vregs1);
+
+/*-------------------------------------------------------------------------*/
+/* tps65013_set_low_pwr parameter:
+ * mode: ON or OFF
+ */
+
+/* FIXME: Assumes AC or USB power is present. Setting AUA bit is not
+ required if power supply is through a battery */
+
+int tps65013_set_low_pwr(unsigned mode)
+{
+ int status;
+ unsigned vdcdc1, chgconfig;
+
+ if (!the_tps || the_tps->por)
+ return -ENODEV;
+
+ down(&the_tps->lock);
+
+ pr_debug("%s: %s low_pwr, chgconfig 0x%02x vdcdc1 0x%02x\n",
+ DRIVER_NAME,
+ mode ? "enable" : "disable",
+ i2c_smbus_read_byte_data(&the_tps->client, TPS_CHGCONFIG),
+ i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1));
+
+ chgconfig = i2c_smbus_read_byte_data(&the_tps->client, TPS_CHGCONFIG);
+ vdcdc1 = i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1);
+
+ switch (mode) {
+ case OFF:
+ chgconfig &= ~TPS65013_AUA; /* disable AUA bit */
+ vdcdc1 &= ~TPS_ENABLE_LP; /* disable ENABLE_LP bit */
+ break;
+ /* case ON: */
+ default:
+ chgconfig |= TPS65013_AUA; /* enable AUA bit */
+ vdcdc1 |= TPS_ENABLE_LP; /* enable ENABLE_LP bit */
+ break;
+ }
+
+ status = i2c_smbus_write_byte_data(&the_tps->client,
+ TPS_CHGCONFIG, chgconfig);
+ if (status != 0) {
+ printk(KERN_ERR "%s: Failed to write chconfig register\n",
+ DRIVER_NAME);
+ up(&the_tps->lock);
+ return status;
+ }
+
+ chgconfig = i2c_smbus_read_byte_data(&the_tps->client, TPS_CHGCONFIG);
+ the_tps->chgconf = chgconfig;
+ show_chgconfig(0, "chgconf", chgconfig);
+
+ status = i2c_smbus_write_byte_data(&the_tps->client,
+ TPS_VDCDC1, vdcdc1);
+
+ if (status != 0)
+ printk(KERN_ERR "%s: Failed to write vdcdc1 register\n",
+ DRIVER_NAME);
+ else
+ pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME,
+ i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1));
+
+ up(&the_tps->lock);
+
+ return status;
+}
+EXPORT_SYMBOL(tps65013_set_low_pwr);
+
+/*-------------------------------------------------------------------------*/
+
+static int __init tps_init(void)
+{
+ u32 tries = 3;
+ int status = -ENODEV;
+
+ printk(KERN_INFO "%s: version %s\n", DRIVER_NAME, DRIVER_VERSION);
+
+ /* some boards have startup glitches */
+ while (tries--) {
+ status = i2c_add_driver(&tps65010_driver);
+ if (the_tps)
+ break;
+ i2c_del_driver(&tps65010_driver);
+ if (!tries) {
+ printk(KERN_ERR "%s: no chip?\n", DRIVER_NAME);
+ return -ENODEV;
+ }
+ pr_debug("%s: re-probe ...\n", DRIVER_NAME);
+ msleep(10);
+ }
+
+#if defined(CONFIG_ARM)
+ if (machine_is_omap_osk()) {
+
+ // FIXME: More should be placed in the initialization code
+ // of the submodules (DSP, ethernet, power management,
+ // board-osk.c). Careful: I2C is initialized "late".
+
+ /* Let LED1 (D9) blink */
+ tps65010_set_led(LED1, BLINK);
+
+ /* Disable LED 2 (D2) */
+ tps65010_set_led(LED2, OFF);
+
+ /* Set GPIO 1 HIGH to disable VBUS power supply;
+ * OHCI driver powers it up/down as needed.
+ */
+ tps65010_set_gpio_out_value(GPIO1, HIGH);
+
+ /* Set GPIO 2 low to turn on LED D3 */
+ tps65010_set_gpio_out_value(GPIO2, HIGH);
+
+ /* Set GPIO 3 low to take ethernet out of reset */
+ tps65010_set_gpio_out_value(GPIO3, LOW);
+
+ /* gpio4 for VDD_DSP */
+
+ /* Enable LOW_PWR */
+ tps65010_set_low_pwr(ON);
+
+ /* Switch VLDO2 to 3.0V for AIC23 */
+ tps65010_config_vregs1(TPS_LDO2_ENABLE | TPS_VLDO2_3_0V | TPS_LDO1_ENABLE);
+
+ } else if (machine_is_omap_h2()) {
+ /* gpio3 for SD, gpio4 for VDD_DSP */
+
+ /* Enable LOW_PWR */
+ tps65010_set_low_pwr(ON);
+ } else if (machine_is_omap_h3()) {
+ /* gpio4 for SD, gpio3 for VDD_DSP */
+#ifdef CONFIG_PM
+ /* Enable LOW_PWR */
+ tps65013_set_low_pwr(ON);
+#endif
+ }
+#endif
+
+ return status;
+}
+/* NOTE: this MUST be initialized before the other parts of the system
+ * that rely on it ... but after the i2c bus on which this relies.
+ * That is, much earlier than on PC-type systems, which don't often use
+ * I2C as a core system bus.
+ */
+subsys_initcall(tps_init);
+
+static void __exit tps_exit(void)
+{
+ i2c_del_driver(&tps65010_driver);
+}
+module_exit(tps_exit);
+
diff --git a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c
index 6614a59cecd..137d9b7cacd 100644
--- a/drivers/i2c/chips/via686a.c
+++ b/drivers/i2c/chips/via686a.c
@@ -1,12 +1,12 @@
/*
via686a.c - Part of lm_sensors, Linux kernel modules
for hardware monitoring
-
+
Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>,
Kyösti Mälkki <kmalkki@cc.hut.fi>,
Mark Studebaker <mdsxyz123@yahoo.com>,
and Bob Dougherty <bobd@stanford.edu>
- (Some conversion-factor data were contributed by Jonathan Teh Soon Yew
+ (Some conversion-factor data were contributed by Jonathan Teh Soon Yew
<j.teh@iname.com> and Alex van Kaam <darkside@chello.nl>.)
This program is free software; you can redistribute it and/or modify
@@ -30,11 +30,9 @@
Warning - only supports a single device.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/pci.h>
-#include <linux/delay.h>
#include <linux/jiffies.h>
#include <linux/i2c.h>
#include <linux/i2c-sensor.h>
@@ -66,49 +64,46 @@ SENSORS_INSMOD_1(via686a);
/* Many VIA686A constants specified below */
/* Length of ISA address segment */
-#define VIA686A_EXTENT 0x80
-#define VIA686A_BASE_REG 0x70
-#define VIA686A_ENABLE_REG 0x74
+#define VIA686A_EXTENT 0x80
+#define VIA686A_BASE_REG 0x70
+#define VIA686A_ENABLE_REG 0x74
/* The VIA686A registers */
/* ins numbered 0-4 */
-#define VIA686A_REG_IN_MAX(nr) (0x2b + ((nr) * 2))
-#define VIA686A_REG_IN_MIN(nr) (0x2c + ((nr) * 2))
-#define VIA686A_REG_IN(nr) (0x22 + (nr))
+#define VIA686A_REG_IN_MAX(nr) (0x2b + ((nr) * 2))
+#define VIA686A_REG_IN_MIN(nr) (0x2c + ((nr) * 2))
+#define VIA686A_REG_IN(nr) (0x22 + (nr))
/* fans numbered 1-2 */
-#define VIA686A_REG_FAN_MIN(nr) (0x3a + (nr))
-#define VIA686A_REG_FAN(nr) (0x28 + (nr))
-
-/* the following values are as speced by VIA: */
-static const u8 regtemp[] = { 0x20, 0x21, 0x1f };
-static const u8 regover[] = { 0x39, 0x3d, 0x1d };
-static const u8 reghyst[] = { 0x3a, 0x3e, 0x1e };
+#define VIA686A_REG_FAN_MIN(nr) (0x3a + (nr))
+#define VIA686A_REG_FAN(nr) (0x28 + (nr))
/* temps numbered 1-3 */
-#define VIA686A_REG_TEMP(nr) (regtemp[nr])
-#define VIA686A_REG_TEMP_OVER(nr) (regover[nr])
-#define VIA686A_REG_TEMP_HYST(nr) (reghyst[nr])
-#define VIA686A_REG_TEMP_LOW1 0x4b // bits 7-6
-#define VIA686A_REG_TEMP_LOW23 0x49 // 2 = bits 5-4, 3 = bits 7-6
-
-#define VIA686A_REG_ALARM1 0x41
-#define VIA686A_REG_ALARM2 0x42
-#define VIA686A_REG_FANDIV 0x47
-#define VIA686A_REG_CONFIG 0x40
-/* The following register sets temp interrupt mode (bits 1-0 for temp1,
+static const u8 VIA686A_REG_TEMP[] = { 0x20, 0x21, 0x1f };
+static const u8 VIA686A_REG_TEMP_OVER[] = { 0x39, 0x3d, 0x1d };
+static const u8 VIA686A_REG_TEMP_HYST[] = { 0x3a, 0x3e, 0x1e };
+/* bits 7-6 */
+#define VIA686A_REG_TEMP_LOW1 0x4b
+/* 2 = bits 5-4, 3 = bits 7-6 */
+#define VIA686A_REG_TEMP_LOW23 0x49
+
+#define VIA686A_REG_ALARM1 0x41
+#define VIA686A_REG_ALARM2 0x42
+#define VIA686A_REG_FANDIV 0x47
+#define VIA686A_REG_CONFIG 0x40
+/* The following register sets temp interrupt mode (bits 1-0 for temp1,
3-2 for temp2, 5-4 for temp3). Modes are:
00 interrupt stays as long as value is out-of-range
01 interrupt is cleared once register is read (default)
10 comparator mode- like 00, but ignores hysteresis
11 same as 00 */
-#define VIA686A_REG_TEMP_MODE 0x4b
+#define VIA686A_REG_TEMP_MODE 0x4b
/* We'll just assume that you want to set all 3 simultaneously: */
-#define VIA686A_TEMP_MODE_MASK 0x3F
-#define VIA686A_TEMP_MODE_CONTINUOUS (0x00)
+#define VIA686A_TEMP_MODE_MASK 0x3F
+#define VIA686A_TEMP_MODE_CONTINUOUS 0x00
/* Conversions. Limit checking is only done on the TO_REG
- variants.
+ variants.
********* VOLTAGE CONVERSIONS (Bob Dougherty) ********
From HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew):
@@ -121,7 +116,7 @@ static const u8 reghyst[] = { 0x3a, 0x3e, 0x1e };
That is:
volts = (25*regVal+133)*factor
regVal = (volts/factor-133)/25
- (These conversions were contributed by Jonathan Teh Soon Yew
+ (These conversions were contributed by Jonathan Teh Soon Yew
<j.teh@iname.com>) */
static inline u8 IN_TO_REG(long val, int inNum)
{
@@ -182,55 +177,55 @@ static inline u8 FAN_TO_REG(long rpm, int div)
else
return double(temp)*0.924-127.33;
- A fifth-order polynomial fits the unofficial data (provided by Alex van
- Kaam <darkside@chello.nl>) a bit better. It also give more reasonable
- numbers on my machine (ie. they agree with what my BIOS tells me).
+ A fifth-order polynomial fits the unofficial data (provided by Alex van
+ Kaam <darkside@chello.nl>) a bit better. It also give more reasonable
+ numbers on my machine (ie. they agree with what my BIOS tells me).
Here's the fifth-order fit to the 8-bit data:
- temp = 1.625093e-10*val^5 - 1.001632e-07*val^4 + 2.457653e-05*val^3 -
+ temp = 1.625093e-10*val^5 - 1.001632e-07*val^4 + 2.457653e-05*val^3 -
2.967619e-03*val^2 + 2.175144e-01*val - 7.090067e+0.
- (2000-10-25- RFD: thanks to Uwe Andersen <uandersen@mayah.com> for
+ (2000-10-25- RFD: thanks to Uwe Andersen <uandersen@mayah.com> for
finding my typos in this formula!)
- Alas, none of the elegant function-fit solutions will work because we
- aren't allowed to use floating point in the kernel and doing it with
- integers doesn't rpovide enough precision. So we'll do boring old
- look-up table stuff. The unofficial data (see below) have effectively
- 7-bit resolution (they are rounded to the nearest degree). I'm assuming
- that the transfer function of the device is monotonic and smooth, so a
- smooth function fit to the data will allow us to get better precision.
+ Alas, none of the elegant function-fit solutions will work because we
+ aren't allowed to use floating point in the kernel and doing it with
+ integers doesn't provide enough precision. So we'll do boring old
+ look-up table stuff. The unofficial data (see below) have effectively
+ 7-bit resolution (they are rounded to the nearest degree). I'm assuming
+ that the transfer function of the device is monotonic and smooth, so a
+ smooth function fit to the data will allow us to get better precision.
I used the 5th-order poly fit described above and solved for
- VIA register values 0-255. I *10 before rounding, so we get tenth-degree
- precision. (I could have done all 1024 values for our 10-bit readings,
- but the function is very linear in the useful range (0-80 deg C), so
- we'll just use linear interpolation for 10-bit readings.) So, tempLUT
+ VIA register values 0-255. I *10 before rounding, so we get tenth-degree
+ precision. (I could have done all 1024 values for our 10-bit readings,
+ but the function is very linear in the useful range (0-80 deg C), so
+ we'll just use linear interpolation for 10-bit readings.) So, tempLUT
is the temp at via register values 0-255: */
static const long tempLUT[] =
- { -709, -688, -667, -646, -627, -607, -589, -570, -553, -536, -519,
- -503, -487, -471, -456, -442, -428, -414, -400, -387, -375,
- -362, -350, -339, -327, -316, -305, -295, -285, -275, -265,
- -255, -246, -237, -229, -220, -212, -204, -196, -188, -180,
- -173, -166, -159, -152, -145, -139, -132, -126, -120, -114,
- -108, -102, -96, -91, -85, -80, -74, -69, -64, -59, -54, -49,
- -44, -39, -34, -29, -25, -20, -15, -11, -6, -2, 3, 7, 12, 16,
- 20, 25, 29, 33, 37, 42, 46, 50, 54, 59, 63, 67, 71, 75, 79, 84,
- 88, 92, 96, 100, 104, 109, 113, 117, 121, 125, 130, 134, 138,
- 142, 146, 151, 155, 159, 163, 168, 172, 176, 181, 185, 189,
- 193, 198, 202, 206, 211, 215, 219, 224, 228, 232, 237, 241,
- 245, 250, 254, 259, 263, 267, 272, 276, 281, 285, 290, 294,
- 299, 303, 307, 312, 316, 321, 325, 330, 334, 339, 344, 348,
- 353, 357, 362, 366, 371, 376, 380, 385, 390, 395, 399, 404,
- 409, 414, 419, 423, 428, 433, 438, 443, 449, 454, 459, 464,
- 469, 475, 480, 486, 491, 497, 502, 508, 514, 520, 526, 532,
- 538, 544, 551, 557, 564, 571, 578, 584, 592, 599, 606, 614,
- 621, 629, 637, 645, 654, 662, 671, 680, 689, 698, 708, 718,
- 728, 738, 749, 759, 770, 782, 793, 805, 818, 830, 843, 856,
- 870, 883, 898, 912, 927, 943, 958, 975, 991, 1008, 1026, 1044,
- 1062, 1081, 1101, 1121, 1141, 1162, 1184, 1206, 1229, 1252,
- 1276, 1301, 1326, 1352, 1378, 1406, 1434, 1462
+{ -709, -688, -667, -646, -627, -607, -589, -570, -553, -536, -519,
+ -503, -487, -471, -456, -442, -428, -414, -400, -387, -375,
+ -362, -350, -339, -327, -316, -305, -295, -285, -275, -265,
+ -255, -246, -237, -229, -220, -212, -204, -196, -188, -180,
+ -173, -166, -159, -152, -145, -139, -132, -126, -120, -114,
+ -108, -102, -96, -91, -85, -80, -74, -69, -64, -59, -54, -49,
+ -44, -39, -34, -29, -25, -20, -15, -11, -6, -2, 3, 7, 12, 16,
+ 20, 25, 29, 33, 37, 42, 46, 50, 54, 59, 63, 67, 71, 75, 79, 84,
+ 88, 92, 96, 100, 104, 109, 113, 117, 121, 125, 130, 134, 138,
+ 142, 146, 151, 155, 159, 163, 168, 172, 176, 181, 185, 189,
+ 193, 198, 202, 206, 211, 215, 219, 224, 228, 232, 237, 241,
+ 245, 250, 254, 259, 263, 267, 272, 276, 281, 285, 290, 294,
+ 299, 303, 307, 312, 316, 321, 325, 330, 334, 339, 344, 348,
+ 353, 357, 362, 366, 371, 376, 380, 385, 390, 395, 399, 404,
+ 409, 414, 419, 423, 428, 433, 438, 443, 449, 454, 459, 464,
+ 469, 475, 480, 486, 491, 497, 502, 508, 514, 520, 526, 532,
+ 538, 544, 551, 557, 564, 571, 578, 584, 592, 599, 606, 614,
+ 621, 629, 637, 645, 654, 662, 671, 680, 689, 698, 708, 718,
+ 728, 738, 749, 759, 770, 782, 793, 805, 818, 830, 843, 856,
+ 870, 883, 898, 912, 927, 943, 958, 975, 991, 1008, 1026, 1044,
+ 1062, 1081, 1101, 1121, 1141, 1162, 1184, 1206, 1229, 1252,
+ 1276, 1301, 1326, 1352, 1378, 1406, 1434, 1462
};
-/* the original LUT values from Alex van Kaam <darkside@chello.nl>
+/* the original LUT values from Alex van Kaam <darkside@chello.nl>
(for via register values 12-240):
{-50,-49,-47,-45,-43,-41,-39,-38,-37,-35,-34,-33,-32,-31,
-30,-29,-28,-27,-26,-25,-24,-24,-23,-22,-21,-20,-20,-19,-18,-17,-17,-16,-15,
@@ -245,26 +240,26 @@ static const long tempLUT[] =
Here's the reverse LUT. I got it by doing a 6-th order poly fit (needed
- an extra term for a good fit to these inverse data!) and then
- solving for each temp value from -50 to 110 (the useable range for
- this chip). Here's the fit:
- viaRegVal = -1.160370e-10*val^6 +3.193693e-08*val^5 - 1.464447e-06*val^4
+ an extra term for a good fit to these inverse data!) and then
+ solving for each temp value from -50 to 110 (the useable range for
+ this chip). Here's the fit:
+ viaRegVal = -1.160370e-10*val^6 +3.193693e-08*val^5 - 1.464447e-06*val^4
- 2.525453e-04*val^3 + 1.424593e-02*val^2 + 2.148941e+00*val +7.275808e+01)
Note that n=161: */
static const u8 viaLUT[] =
- { 12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 22, 23,
- 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40,
- 41, 43, 45, 46, 48, 49, 51, 53, 55, 57, 59, 60, 62, 64, 66,
- 69, 71, 73, 75, 77, 79, 82, 84, 86, 88, 91, 93, 95, 98, 100,
- 103, 105, 107, 110, 112, 115, 117, 119, 122, 124, 126, 129,
- 131, 134, 136, 138, 140, 143, 145, 147, 150, 152, 154, 156,
- 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180,
- 182, 183, 185, 187, 188, 190, 192, 193, 195, 196, 198, 199,
- 200, 202, 203, 205, 206, 207, 208, 209, 210, 211, 212, 213,
- 214, 215, 216, 217, 218, 219, 220, 221, 222, 222, 223, 224,
- 225, 226, 226, 227, 228, 228, 229, 230, 230, 231, 232, 232,
- 233, 233, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239,
- 239, 240
+{ 12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 22, 23,
+ 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40,
+ 41, 43, 45, 46, 48, 49, 51, 53, 55, 57, 59, 60, 62, 64, 66,
+ 69, 71, 73, 75, 77, 79, 82, 84, 86, 88, 91, 93, 95, 98, 100,
+ 103, 105, 107, 110, 112, 115, 117, 119, 122, 124, 126, 129,
+ 131, 134, 136, 138, 140, 143, 145, 147, 150, 152, 154, 156,
+ 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180,
+ 182, 183, 185, 187, 188, 190, 192, 193, 195, 196, 198, 199,
+ 200, 202, 203, 205, 206, 207, 208, 209, 210, 211, 212, 213,
+ 214, 215, 216, 217, 218, 219, 220, 221, 222, 222, 223, 224,
+ 225, 226, 226, 227, 228, 228, 229, 230, 230, 231, 232, 232,
+ 233, 233, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239,
+ 239, 240
};
/* Converting temps to (8-bit) hyst and over registers
@@ -272,7 +267,7 @@ static const u8 viaLUT[] =
The +50 is because the temps start at -50 */
static inline u8 TEMP_TO_REG(long val)
{
- return viaLUT[val <= -50000 ? 0 : val >= 110000 ? 160 :
+ return viaLUT[val <= -50000 ? 0 : val >= 110000 ? 160 :
(val < 0 ? val - 500 : val + 500) / 1000 + 50];
}
@@ -291,11 +286,9 @@ static inline long TEMP_FROM_REG10(u16 val)
/* do some linear interpolation */
return (tempLUT[eightBits] * (4 - twoBits) +
- tempLUT[eightBits + 1] * twoBits) * 25;
+ tempLUT[eightBits + 1] * twoBits) * 25;
}
-#define ALARMS_FROM_REG(val) (val)
-
#define DIV_FROM_REG(val) (1 << (val))
#define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
@@ -358,54 +351,54 @@ static ssize_t show_in_max(struct device *dev, char *buf, int nr) {
return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_max[nr], nr));
}
-static ssize_t set_in_min(struct device *dev, const char *buf,
+static ssize_t set_in_min(struct device *dev, const char *buf,
size_t count, int nr) {
struct i2c_client *client = to_i2c_client(dev);
struct via686a_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock);
- data->in_min[nr] = IN_TO_REG(val,nr);
- via686a_write_value(client, VIA686A_REG_IN_MIN(nr),
+ data->in_min[nr] = IN_TO_REG(val, nr);
+ via686a_write_value(client, VIA686A_REG_IN_MIN(nr),
data->in_min[nr]);
up(&data->update_lock);
return count;
}
-static ssize_t set_in_max(struct device *dev, const char *buf,
+static ssize_t set_in_max(struct device *dev, const char *buf,
size_t count, int nr) {
struct i2c_client *client = to_i2c_client(dev);
struct via686a_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10);
down(&data->update_lock);
- data->in_max[nr] = IN_TO_REG(val,nr);
- via686a_write_value(client, VIA686A_REG_IN_MAX(nr),
+ data->in_max[nr] = IN_TO_REG(val, nr);
+ via686a_write_value(client, VIA686A_REG_IN_MAX(nr),
data->in_max[nr]);
up(&data->update_lock);
return count;
}
#define show_in_offset(offset) \
static ssize_t \
- show_in##offset (struct device *dev, char *buf) \
+ show_in##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_in(dev, buf, offset); \
} \
static ssize_t \
- show_in##offset##_min (struct device *dev, char *buf) \
+ show_in##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_in_min(dev, buf, offset); \
} \
static ssize_t \
- show_in##offset##_max (struct device *dev, char *buf) \
+ show_in##offset##_max (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_in_max(dev, buf, offset); \
} \
-static ssize_t set_in##offset##_min (struct device *dev, \
+static ssize_t set_in##offset##_min (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_in_min(dev, buf, count, offset); \
} \
-static ssize_t set_in##offset##_max (struct device *dev, \
+static ssize_t set_in##offset##_max (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_in_max(dev, buf, count, offset); \
@@ -435,7 +428,7 @@ static ssize_t show_temp_hyst(struct device *dev, char *buf, int nr) {
struct via686a_data *data = via686a_update_device(dev);
return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_hyst[nr]));
}
-static ssize_t set_temp_over(struct device *dev, const char *buf,
+static ssize_t set_temp_over(struct device *dev, const char *buf,
size_t count, int nr) {
struct i2c_client *client = to_i2c_client(dev);
struct via686a_data *data = i2c_get_clientdata(client);
@@ -443,11 +436,12 @@ static ssize_t set_temp_over(struct device *dev, const char *buf,
down(&data->update_lock);
data->temp_over[nr] = TEMP_TO_REG(val);
- via686a_write_value(client, VIA686A_REG_TEMP_OVER(nr), data->temp_over[nr]);
+ via686a_write_value(client, VIA686A_REG_TEMP_OVER[nr],
+ data->temp_over[nr]);
up(&data->update_lock);
return count;
}
-static ssize_t set_temp_hyst(struct device *dev, const char *buf,
+static ssize_t set_temp_hyst(struct device *dev, const char *buf,
size_t count, int nr) {
struct i2c_client *client = to_i2c_client(dev);
struct via686a_data *data = i2c_get_clientdata(client);
@@ -455,31 +449,32 @@ static ssize_t set_temp_hyst(struct device *dev, const char *buf,
down(&data->update_lock);
data->temp_hyst[nr] = TEMP_TO_REG(val);
- via686a_write_value(client, VIA686A_REG_TEMP_HYST(nr), data->temp_hyst[nr]);
+ via686a_write_value(client, VIA686A_REG_TEMP_HYST[nr],
+ data->temp_hyst[nr]);
up(&data->update_lock);
return count;
}
#define show_temp_offset(offset) \
-static ssize_t show_temp_##offset (struct device *dev, char *buf) \
+static ssize_t show_temp_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_temp(dev, buf, offset - 1); \
} \
static ssize_t \
-show_temp_##offset##_over (struct device *dev, char *buf) \
+show_temp_##offset##_over (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_temp_over(dev, buf, offset - 1); \
} \
static ssize_t \
-show_temp_##offset##_hyst (struct device *dev, char *buf) \
+show_temp_##offset##_hyst (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_temp_hyst(dev, buf, offset - 1); \
} \
-static ssize_t set_temp_##offset##_over (struct device *dev, \
+static ssize_t set_temp_##offset##_over (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_temp_over(dev, buf, count, offset - 1); \
} \
-static ssize_t set_temp_##offset##_hyst (struct device *dev, \
+static ssize_t set_temp_##offset##_hyst (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_temp_hyst(dev, buf, count, offset - 1); \
@@ -488,7 +483,7 @@ static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL);\
static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \
show_temp_##offset##_over, set_temp_##offset##_over); \
static DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \
- show_temp_##offset##_hyst, set_temp_##offset##_hyst);
+ show_temp_##offset##_hyst, set_temp_##offset##_hyst);
show_temp_offset(1);
show_temp_offset(2);
@@ -497,19 +492,19 @@ show_temp_offset(3);
/* 2 Fans */
static ssize_t show_fan(struct device *dev, char *buf, int nr) {
struct via686a_data *data = via686a_update_device(dev);
- return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr],
+ return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
DIV_FROM_REG(data->fan_div[nr])) );
}
static ssize_t show_fan_min(struct device *dev, char *buf, int nr) {
struct via686a_data *data = via686a_update_device(dev);
- return sprintf(buf,"%d\n",
+ return sprintf(buf, "%d\n",
FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])) );
}
static ssize_t show_fan_div(struct device *dev, char *buf, int nr) {
struct via686a_data *data = via686a_update_device(dev);
- return sprintf(buf,"%d\n", DIV_FROM_REG(data->fan_div[nr]) );
+ return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]) );
}
-static ssize_t set_fan_min(struct device *dev, const char *buf,
+static ssize_t set_fan_min(struct device *dev, const char *buf,
size_t count, int nr) {
struct i2c_client *client = to_i2c_client(dev);
struct via686a_data *data = i2c_get_clientdata(client);
@@ -521,7 +516,7 @@ static ssize_t set_fan_min(struct device *dev, const char *buf,
up(&data->update_lock);
return count;
}
-static ssize_t set_fan_div(struct device *dev, const char *buf,
+static ssize_t set_fan_div(struct device *dev, const char *buf,
size_t count, int nr) {
struct i2c_client *client = to_i2c_client(dev);
struct via686a_data *data = i2c_get_clientdata(client);
@@ -538,24 +533,24 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
}
#define show_fan_offset(offset) \
-static ssize_t show_fan_##offset (struct device *dev, char *buf) \
+static ssize_t show_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_fan(dev, buf, offset - 1); \
} \
-static ssize_t show_fan_##offset##_min (struct device *dev, char *buf) \
+static ssize_t show_fan_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_fan_min(dev, buf, offset - 1); \
} \
-static ssize_t show_fan_##offset##_div (struct device *dev, char *buf) \
+static ssize_t show_fan_##offset##_div (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_fan_div(dev, buf, offset - 1); \
} \
-static ssize_t set_fan_##offset##_min (struct device *dev, \
+static ssize_t set_fan_##offset##_min (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_fan_min(dev, buf, count, offset - 1); \
} \
-static ssize_t set_fan_##offset##_div (struct device *dev, \
+static ssize_t set_fan_##offset##_div (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return set_fan_div(dev, buf, count, offset - 1); \
@@ -570,9 +565,9 @@ show_fan_offset(1);
show_fan_offset(2);
/* Alarms */
-static ssize_t show_alarms(struct device *dev, char *buf) {
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) {
struct via686a_data *data = via686a_update_device(dev);
- return sprintf(buf,"%d\n", ALARMS_FROM_REG(data->alarms));
+ return sprintf(buf, "%u\n", data->alarms);
}
static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
@@ -612,11 +607,12 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
}
/* 8231 requires multiple of 256, we enforce that on 686 as well */
- if(force_addr)
+ if (force_addr)
address = force_addr & 0xFF00;
- if(force_addr) {
- dev_warn(&adapter->dev,"forcing ISA address 0x%04X\n", address);
+ if (force_addr) {
+ dev_warn(&adapter->dev, "forcing ISA address 0x%04X\n",
+ address);
if (PCIBIOS_SUCCESSFUL !=
pci_write_config_word(s_bridge, VIA686A_BASE_REG, address))
return -ENODEV;
@@ -625,17 +621,17 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
pci_read_config_word(s_bridge, VIA686A_ENABLE_REG, &val))
return -ENODEV;
if (!(val & 0x0001)) {
- dev_warn(&adapter->dev,"enabling sensors\n");
+ dev_warn(&adapter->dev, "enabling sensors\n");
if (PCIBIOS_SUCCESSFUL !=
pci_write_config_word(s_bridge, VIA686A_ENABLE_REG,
- val | 0x0001))
+ val | 0x0001))
return -ENODEV;
}
/* Reserve the ISA region */
if (!request_region(address, VIA686A_EXTENT, via686a_driver.name)) {
- dev_err(&adapter->dev,"region 0x%x already in use!\n",
- address);
+ dev_err(&adapter->dev, "region 0x%x already in use!\n",
+ address);
return -ENODEV;
}
@@ -660,7 +656,7 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
goto ERROR3;
-
+
/* Initialize the VIA686A chip */
via686a_init_client(new_client);
@@ -699,9 +695,9 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
return 0;
- ERROR3:
+ERROR3:
kfree(data);
- ERROR0:
+ERROR0:
release_region(address, VIA686A_EXTENT);
return err;
}
@@ -732,7 +728,7 @@ static void via686a_init_client(struct i2c_client *client)
via686a_write_value(client, VIA686A_REG_CONFIG, (reg|0x01)&0x7F);
/* Configure temp interrupt mode for continuous-interrupt operation */
- via686a_write_value(client, VIA686A_REG_TEMP_MODE,
+ via686a_write_value(client, VIA686A_REG_TEMP_MODE,
via686a_read_value(client, VIA686A_REG_TEMP_MODE) &
!(VIA686A_TEMP_MODE_MASK | VIA686A_TEMP_MODE_CONTINUOUS));
}
@@ -764,15 +760,15 @@ static struct via686a_data *via686a_update_device(struct device *dev)
}
for (i = 0; i <= 2; i++) {
data->temp[i] = via686a_read_value(client,
- VIA686A_REG_TEMP(i)) << 2;
+ VIA686A_REG_TEMP[i]) << 2;
data->temp_over[i] =
via686a_read_value(client,
- VIA686A_REG_TEMP_OVER(i));
+ VIA686A_REG_TEMP_OVER[i]);
data->temp_hyst[i] =
via686a_read_value(client,
- VIA686A_REG_TEMP_HYST(i));
+ VIA686A_REG_TEMP_HYST[i]);
}
- /* add in lower 2 bits
+ /* add in lower 2 bits
temp1 uses bits 7-6 of VIA686A_REG_TEMP_LOW1
temp2 uses bits 5-4 of VIA686A_REG_TEMP_LOW23
temp3 uses bits 7-6 of VIA686A_REG_TEMP_LOW23
@@ -804,35 +800,36 @@ static struct via686a_data *via686a_update_device(struct device *dev)
}
static struct pci_device_id via686a_pci_ids[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4) },
- { 0, }
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4) },
+ { 0, }
};
MODULE_DEVICE_TABLE(pci, via686a_pci_ids);
static int __devinit via686a_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *id)
+ const struct pci_device_id *id)
{
- u16 val;
- int addr = 0;
-
- if (PCIBIOS_SUCCESSFUL !=
- pci_read_config_word(dev, VIA686A_BASE_REG, &val))
- return -ENODEV;
-
- addr = val & ~(VIA686A_EXTENT - 1);
- if (addr == 0 && force_addr == 0) {
- dev_err(&dev->dev,"base address not set - upgrade BIOS or use force_addr=0xaddr\n");
- return -ENODEV;
- }
- if (force_addr)
- addr = force_addr; /* so detect will get called */
-
- if (!addr) {
- dev_err(&dev->dev,"No Via 686A sensors found.\n");
- return -ENODEV;
- }
- normal_isa[0] = addr;
+ u16 val;
+ int addr = 0;
+
+ if (PCIBIOS_SUCCESSFUL !=
+ pci_read_config_word(dev, VIA686A_BASE_REG, &val))
+ return -ENODEV;
+
+ addr = val & ~(VIA686A_EXTENT - 1);
+ if (addr == 0 && force_addr == 0) {
+ dev_err(&dev->dev, "base address not set - upgrade BIOS "
+ "or use force_addr=0xaddr\n");
+ return -ENODEV;
+ }
+ if (force_addr)
+ addr = force_addr; /* so detect will get called */
+
+ if (!addr) {
+ dev_err(&dev->dev, "No Via 686A sensors found.\n");
+ return -ENODEV;
+ }
+ normal_isa[0] = addr;
s_bridge = pci_dev_get(dev);
if (i2c_add_driver(&via686a_driver)) {
@@ -848,14 +845,14 @@ static int __devinit via686a_pci_probe(struct pci_dev *dev,
}
static struct pci_driver via686a_pci_driver = {
- .name = "via686a",
- .id_table = via686a_pci_ids,
- .probe = via686a_pci_probe,
+ .name = "via686a",
+ .id_table = via686a_pci_ids,
+ .probe = via686a_pci_probe,
};
static int __init sm_via686a_init(void)
{
- return pci_register_driver(&via686a_pci_driver);
+ return pci_register_driver(&via686a_pci_driver);
}
static void __exit sm_via686a_exit(void)
@@ -869,8 +866,8 @@ static void __exit sm_via686a_exit(void)
}
MODULE_AUTHOR("Kyösti Mälkki <kmalkki@cc.hut.fi>, "
- "Mark Studebaker <mdsxyz123@yahoo.com> "
- "and Bob Dougherty <bobd@stanford.edu>");
+ "Mark Studebaker <mdsxyz123@yahoo.com> "
+ "and Bob Dougherty <bobd@stanford.edu>");
MODULE_DESCRIPTION("VIA 686A Sensor device");
MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/chips/w83627ehf.c b/drivers/i2c/chips/w83627ehf.c
new file mode 100644
index 00000000000..8a40b6976e1
--- /dev/null
+++ b/drivers/i2c/chips/w83627ehf.c
@@ -0,0 +1,846 @@
+/*
+ w83627ehf - Driver for the hardware monitoring functionality of
+ the Winbond W83627EHF Super-I/O chip
+ Copyright (C) 2005 Jean Delvare <khali@linux-fr.org>
+
+ Shamelessly ripped from the w83627hf driver
+ Copyright (C) 2003 Mark Studebaker
+
+ Thanks to Leon Moonen, Steve Cliffe and Grant Coady for their help
+ in testing and debugging this driver.
+
+ 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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+
+ Supports the following chips:
+
+ Chip #vin #fan #pwm #temp chip_id man_id
+ w83627ehf - 5 - 3 0x88 0x5ca3
+
+ This is a preliminary version of the driver, only supporting the
+ fan and temperature inputs. The chip does much more than that.
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <asm/io.h>
+#include "lm75.h"
+
+/* Addresses to scan
+ The actual ISA address is read from Super-I/O configuration space */
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+static unsigned int normal_isa[] = { 0, I2C_CLIENT_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_1(w83627ehf);
+
+/*
+ * Super-I/O constants and functions
+ */
+
+static int REG; /* The register to read/write */
+static int VAL; /* The value to read/write */
+
+#define W83627EHF_LD_HWM 0x0b
+
+#define SIO_REG_LDSEL 0x07 /* Logical device select */
+#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
+#define SIO_REG_ENABLE 0x30 /* Logical device enable */
+#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
+
+#define SIO_W83627EHF_ID 0x8840
+#define SIO_ID_MASK 0xFFC0
+
+static inline void
+superio_outb(int reg, int val)
+{
+ outb(reg, REG);
+ outb(val, VAL);
+}
+
+static inline int
+superio_inb(int reg)
+{
+ outb(reg, REG);
+ return inb(VAL);
+}
+
+static inline void
+superio_select(int ld)
+{
+ outb(SIO_REG_LDSEL, REG);
+ outb(ld, VAL);
+}
+
+static inline void
+superio_enter(void)
+{
+ outb(0x87, REG);
+ outb(0x87, REG);
+}
+
+static inline void
+superio_exit(void)
+{
+ outb(0x02, REG);
+ outb(0x02, VAL);
+}
+
+/*
+ * ISA constants
+ */
+
+#define REGION_LENGTH 8
+#define ADDR_REG_OFFSET 5
+#define DATA_REG_OFFSET 6
+
+#define W83627EHF_REG_BANK 0x4E
+#define W83627EHF_REG_CONFIG 0x40
+#define W83627EHF_REG_CHIP_ID 0x49
+#define W83627EHF_REG_MAN_ID 0x4F
+
+static const u16 W83627EHF_REG_FAN[] = { 0x28, 0x29, 0x2a, 0x3f, 0x553 };
+static const u16 W83627EHF_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d, 0x3e, 0x55c };
+
+#define W83627EHF_REG_TEMP1 0x27
+#define W83627EHF_REG_TEMP1_HYST 0x3a
+#define W83627EHF_REG_TEMP1_OVER 0x39
+static const u16 W83627EHF_REG_TEMP[] = { 0x150, 0x250 };
+static const u16 W83627EHF_REG_TEMP_HYST[] = { 0x153, 0x253 };
+static const u16 W83627EHF_REG_TEMP_OVER[] = { 0x155, 0x255 };
+static const u16 W83627EHF_REG_TEMP_CONFIG[] = { 0x152, 0x252 };
+
+/* Fan clock dividers are spread over the following five registers */
+#define W83627EHF_REG_FANDIV1 0x47
+#define W83627EHF_REG_FANDIV2 0x4B
+#define W83627EHF_REG_VBAT 0x5D
+#define W83627EHF_REG_DIODE 0x59
+#define W83627EHF_REG_SMI_OVT 0x4C
+
+/*
+ * Conversions
+ */
+
+static inline unsigned int
+fan_from_reg(u8 reg, unsigned int div)
+{
+ if (reg == 0 || reg == 255)
+ return 0;
+ return 1350000U / (reg * div);
+}
+
+static inline unsigned int
+div_from_reg(u8 reg)
+{
+ return 1 << reg;
+}
+
+static inline int
+temp1_from_reg(s8 reg)
+{
+ return reg * 1000;
+}
+
+static inline s8
+temp1_to_reg(int temp)
+{
+ if (temp <= -128000)
+ return -128;
+ if (temp >= 127000)
+ return 127;
+ if (temp < 0)
+ return (temp - 500) / 1000;
+ return (temp + 500) / 1000;
+}
+
+/*
+ * Data structures and manipulation thereof
+ */
+
+struct w83627ehf_data {
+ struct i2c_client client;
+ struct semaphore lock;
+
+ struct semaphore update_lock;
+ char valid; /* !=0 if following fields are valid */
+ unsigned long last_updated; /* In jiffies */
+
+ /* Register values */
+ u8 fan[5];
+ u8 fan_min[5];
+ u8 fan_div[5];
+ u8 has_fan; /* some fan inputs can be disabled */
+ s8 temp1;
+ s8 temp1_max;
+ s8 temp1_max_hyst;
+ s16 temp[2];
+ s16 temp_max[2];
+ s16 temp_max_hyst[2];
+};
+
+static inline int is_word_sized(u16 reg)
+{
+ return (((reg & 0xff00) == 0x100
+ || (reg & 0xff00) == 0x200)
+ && ((reg & 0x00ff) == 0x50
+ || (reg & 0x00ff) == 0x53
+ || (reg & 0x00ff) == 0x55));
+}
+
+/* We assume that the default bank is 0, thus the following two functions do
+ nothing for registers which live in bank 0. For others, they respectively
+ set the bank register to the correct value (before the register is
+ accessed), and back to 0 (afterwards). */
+static inline void w83627ehf_set_bank(struct i2c_client *client, u16 reg)
+{
+ if (reg & 0xff00) {
+ outb_p(W83627EHF_REG_BANK, client->addr + ADDR_REG_OFFSET);
+ outb_p(reg >> 8, client->addr + DATA_REG_OFFSET);
+ }
+}
+
+static inline void w83627ehf_reset_bank(struct i2c_client *client, u16 reg)
+{
+ if (reg & 0xff00) {
+ outb_p(W83627EHF_REG_BANK, client->addr + ADDR_REG_OFFSET);
+ outb_p(0, client->addr + DATA_REG_OFFSET);
+ }
+}
+
+static u16 w83627ehf_read_value(struct i2c_client *client, u16 reg)
+{
+ struct w83627ehf_data *data = i2c_get_clientdata(client);
+ int res, word_sized = is_word_sized(reg);
+
+ down(&data->lock);
+
+ w83627ehf_set_bank(client, reg);
+ outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET);
+ res = inb_p(client->addr + DATA_REG_OFFSET);
+ if (word_sized) {
+ outb_p((reg & 0xff) + 1,
+ client->addr + ADDR_REG_OFFSET);
+ res = (res << 8) + inb_p(client->addr + DATA_REG_OFFSET);
+ }
+ w83627ehf_reset_bank(client, reg);
+
+ up(&data->lock);
+
+ return res;
+}
+
+static int w83627ehf_write_value(struct i2c_client *client, u16 reg, u16 value)
+{
+ struct w83627ehf_data *data = i2c_get_clientdata(client);
+ int word_sized = is_word_sized(reg);
+
+ down(&data->lock);
+
+ w83627ehf_set_bank(client, reg);
+ outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET);
+ if (word_sized) {
+ outb_p(value >> 8, client->addr + DATA_REG_OFFSET);
+ outb_p((reg & 0xff) + 1,
+ client->addr + ADDR_REG_OFFSET);
+ }
+ outb_p(value & 0xff, client->addr + DATA_REG_OFFSET);
+ w83627ehf_reset_bank(client, reg);
+
+ up(&data->lock);
+ return 0;
+}
+
+/* This function assumes that the caller holds data->update_lock */
+static void w83627ehf_write_fan_div(struct i2c_client *client, int nr)
+{
+ struct w83627ehf_data *data = i2c_get_clientdata(client);
+ u8 reg;
+
+ switch (nr) {
+ case 0:
+ reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0xcf)
+ | ((data->fan_div[0] & 0x03) << 4);
+ w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg);
+ reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xdf)
+ | ((data->fan_div[0] & 0x04) << 3);
+ w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg);
+ break;
+ case 1:
+ reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0x3f)
+ | ((data->fan_div[1] & 0x03) << 6);
+ w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg);
+ reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xbf)
+ | ((data->fan_div[1] & 0x04) << 4);
+ w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg);
+ break;
+ case 2:
+ reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV2) & 0x3f)
+ | ((data->fan_div[2] & 0x03) << 6);
+ w83627ehf_write_value(client, W83627EHF_REG_FANDIV2, reg);
+ reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0x7f)
+ | ((data->fan_div[2] & 0x04) << 5);
+ w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg);
+ break;
+ case 3:
+ reg = (w83627ehf_read_value(client, W83627EHF_REG_DIODE) & 0xfc)
+ | (data->fan_div[3] & 0x03);
+ w83627ehf_write_value(client, W83627EHF_REG_DIODE, reg);
+ reg = (w83627ehf_read_value(client, W83627EHF_REG_SMI_OVT) & 0x7f)
+ | ((data->fan_div[3] & 0x04) << 5);
+ w83627ehf_write_value(client, W83627EHF_REG_SMI_OVT, reg);
+ break;
+ case 4:
+ reg = (w83627ehf_read_value(client, W83627EHF_REG_DIODE) & 0x73)
+ | ((data->fan_div[4] & 0x03) << 3)
+ | ((data->fan_div[4] & 0x04) << 5);
+ w83627ehf_write_value(client, W83627EHF_REG_DIODE, reg);
+ break;
+ }
+}
+
+static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83627ehf_data *data = i2c_get_clientdata(client);
+ int i;
+
+ down(&data->update_lock);
+
+ if (time_after(jiffies, data->last_updated + HZ)
+ || !data->valid) {
+ /* Fan clock dividers */
+ i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1);
+ data->fan_div[0] = (i >> 4) & 0x03;
+ data->fan_div[1] = (i >> 6) & 0x03;
+ i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV2);
+ data->fan_div[2] = (i >> 6) & 0x03;
+ i = w83627ehf_read_value(client, W83627EHF_REG_VBAT);
+ data->fan_div[0] |= (i >> 3) & 0x04;
+ data->fan_div[1] |= (i >> 4) & 0x04;
+ data->fan_div[2] |= (i >> 5) & 0x04;
+ if (data->has_fan & ((1 << 3) | (1 << 4))) {
+ i = w83627ehf_read_value(client, W83627EHF_REG_DIODE);
+ data->fan_div[3] = i & 0x03;
+ data->fan_div[4] = ((i >> 2) & 0x03)
+ | ((i >> 5) & 0x04);
+ }
+ if (data->has_fan & (1 << 3)) {
+ i = w83627ehf_read_value(client, W83627EHF_REG_SMI_OVT);
+ data->fan_div[3] |= (i >> 5) & 0x04;
+ }
+
+ /* Measured fan speeds and limits */
+ for (i = 0; i < 5; i++) {
+ if (!(data->has_fan & (1 << i)))
+ continue;
+
+ data->fan[i] = w83627ehf_read_value(client,
+ W83627EHF_REG_FAN[i]);
+ data->fan_min[i] = w83627ehf_read_value(client,
+ W83627EHF_REG_FAN_MIN[i]);
+
+ /* If we failed to measure the fan speed and clock
+ divider can be increased, let's try that for next
+ time */
+ if (data->fan[i] == 0xff
+ && data->fan_div[i] < 0x07) {
+ dev_dbg(&client->dev, "Increasing fan %d "
+ "clock divider from %u to %u\n",
+ i, div_from_reg(data->fan_div[i]),
+ div_from_reg(data->fan_div[i] + 1));
+ data->fan_div[i]++;
+ w83627ehf_write_fan_div(client, i);
+ /* Preserve min limit if possible */
+ if (data->fan_min[i] >= 2
+ && data->fan_min[i] != 255)
+ w83627ehf_write_value(client,
+ W83627EHF_REG_FAN_MIN[i],
+ (data->fan_min[i] /= 2));
+ }
+ }
+
+ /* Measured temperatures and limits */
+ data->temp1 = w83627ehf_read_value(client,
+ W83627EHF_REG_TEMP1);
+ data->temp1_max = w83627ehf_read_value(client,
+ W83627EHF_REG_TEMP1_OVER);
+ data->temp1_max_hyst = w83627ehf_read_value(client,
+ W83627EHF_REG_TEMP1_HYST);
+ for (i = 0; i < 2; i++) {
+ data->temp[i] = w83627ehf_read_value(client,
+ W83627EHF_REG_TEMP[i]);
+ data->temp_max[i] = w83627ehf_read_value(client,
+ W83627EHF_REG_TEMP_OVER[i]);
+ data->temp_max_hyst[i] = w83627ehf_read_value(client,
+ W83627EHF_REG_TEMP_HYST[i]);
+ }
+
+ data->last_updated = jiffies;
+ data->valid = 1;
+ }
+
+ up(&data->update_lock);
+ return data;
+}
+
+/*
+ * Sysfs callback functions
+ */
+
+#define show_fan_reg(reg) \
+static ssize_t \
+show_##reg(struct device *dev, char *buf, int nr) \
+{ \
+ struct w83627ehf_data *data = w83627ehf_update_device(dev); \
+ return sprintf(buf, "%d\n", \
+ fan_from_reg(data->reg[nr], \
+ div_from_reg(data->fan_div[nr]))); \
+}
+show_fan_reg(fan);
+show_fan_reg(fan_min);
+
+static ssize_t
+show_fan_div(struct device *dev, char *buf, int nr)
+{
+ struct w83627ehf_data *data = w83627ehf_update_device(dev);
+ return sprintf(buf, "%u\n",
+ div_from_reg(data->fan_div[nr]));
+}
+
+static ssize_t
+store_fan_min(struct device *dev, const char *buf, size_t count, int nr)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct w83627ehf_data *data = i2c_get_clientdata(client);
+ unsigned int val = simple_strtoul(buf, NULL, 10);
+ unsigned int reg;
+ u8 new_div;
+
+ down(&data->update_lock);
+ if (!val) {
+ /* No min limit, alarm disabled */
+ data->fan_min[nr] = 255;
+ new_div = data->fan_div[nr]; /* No change */
+ dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1);
+ } else if ((reg = 1350000U / val) >= 128 * 255) {
+ /* Speed below this value cannot possibly be represented,
+ even with the highest divider (128) */
+ data->fan_min[nr] = 254;
+ new_div = 7; /* 128 == (1 << 7) */
+ dev_warn(dev, "fan%u low limit %u below minimum %u, set to "
+ "minimum\n", nr + 1, val, fan_from_reg(254, 128));
+ } else if (!reg) {
+ /* Speed above this value cannot possibly be represented,
+ even with the lowest divider (1) */
+ data->fan_min[nr] = 1;
+ new_div = 0; /* 1 == (1 << 0) */
+ dev_warn(dev, "fan%u low limit %u above maximum %u, set to "
+ "maximum\n", nr + 1, val, fan_from_reg(1, 1));
+ } else {
+ /* Automatically pick the best divider, i.e. the one such
+ that the min limit will correspond to a register value
+ in the 96..192 range */
+ new_div = 0;
+ while (reg > 192 && new_div < 7) {
+ reg >>= 1;
+ new_div++;
+ }
+ data->fan_min[nr] = reg;
+ }
+
+ /* Write both the fan clock divider (if it changed) and the new
+ fan min (unconditionally) */
+ if (new_div != data->fan_div[nr]) {
+ if (new_div > data->fan_div[nr])
+ data->fan[nr] >>= (data->fan_div[nr] - new_div);
+ else
+ data->fan[nr] <<= (new_div - data->fan_div[nr]);
+
+ dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
+ nr + 1, div_from_reg(data->fan_div[nr]),
+ div_from_reg(new_div));
+ data->fan_div[nr] = new_div;
+ w83627ehf_write_fan_div(client, nr);
+ }
+ w83627ehf_write_value(client, W83627EHF_REG_FAN_MIN[nr],
+ data->fan_min[nr]);
+ up(&data->update_lock);
+
+ return count;
+}
+
+#define sysfs_fan_offset(offset) \
+static ssize_t \
+show_reg_fan_##offset(struct device *dev, struct device_attribute *attr, \
+ char *buf) \
+{ \
+ return show_fan(dev, buf, offset-1); \
+} \
+static DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
+ show_reg_fan_##offset, NULL);
+
+#define sysfs_fan_min_offset(offset) \
+static ssize_t \
+show_reg_fan##offset##_min(struct device *dev, struct device_attribute *attr, \
+ char *buf) \
+{ \
+ return show_fan_min(dev, buf, offset-1); \
+} \
+static ssize_t \
+store_reg_fan##offset##_min(struct device *dev, struct device_attribute *attr, \
+ const char *buf, size_t count) \
+{ \
+ return store_fan_min(dev, buf, count, offset-1); \
+} \
+static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
+ show_reg_fan##offset##_min, \
+ store_reg_fan##offset##_min);
+
+#define sysfs_fan_div_offset(offset) \
+static ssize_t \
+show_reg_fan##offset##_div(struct device *dev, struct device_attribute *attr, \
+ char *buf) \
+{ \
+ return show_fan_div(dev, buf, offset - 1); \
+} \
+static DEVICE_ATTR(fan##offset##_div, S_IRUGO, \
+ show_reg_fan##offset##_div, NULL);
+
+sysfs_fan_offset(1);
+sysfs_fan_min_offset(1);
+sysfs_fan_div_offset(1);
+sysfs_fan_offset(2);
+sysfs_fan_min_offset(2);
+sysfs_fan_div_offset(2);
+sysfs_fan_offset(3);
+sysfs_fan_min_offset(3);
+sysfs_fan_div_offset(3);
+sysfs_fan_offset(4);
+sysfs_fan_min_offset(4);
+sysfs_fan_div_offset(4);
+sysfs_fan_offset(5);
+sysfs_fan_min_offset(5);
+sysfs_fan_div_offset(5);
+
+#define show_temp1_reg(reg) \
+static ssize_t \
+show_##reg(struct device *dev, struct device_attribute *attr, \
+ char *buf) \
+{ \
+ struct w83627ehf_data *data = w83627ehf_update_device(dev); \
+ return sprintf(buf, "%d\n", temp1_from_reg(data->reg)); \
+}
+show_temp1_reg(temp1);
+show_temp1_reg(temp1_max);
+show_temp1_reg(temp1_max_hyst);
+
+#define store_temp1_reg(REG, reg) \
+static ssize_t \
+store_temp1_##reg(struct device *dev, struct device_attribute *attr, \
+ const char *buf, size_t count) \
+{ \
+ struct i2c_client *client = to_i2c_client(dev); \
+ struct w83627ehf_data *data = i2c_get_clientdata(client); \
+ u32 val = simple_strtoul(buf, NULL, 10); \
+ \
+ down(&data->update_lock); \
+ data->temp1_##reg = temp1_to_reg(val); \
+ w83627ehf_write_value(client, W83627EHF_REG_TEMP1_##REG, \
+ data->temp1_##reg); \
+ up(&data->update_lock); \
+ return count; \
+}
+store_temp1_reg(OVER, max);
+store_temp1_reg(HYST, max_hyst);
+
+static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1, NULL);
+static DEVICE_ATTR(temp1_max, S_IRUGO| S_IWUSR,
+ show_temp1_max, store_temp1_max);
+static DEVICE_ATTR(temp1_max_hyst, S_IRUGO| S_IWUSR,
+ show_temp1_max_hyst, store_temp1_max_hyst);
+
+#define show_temp_reg(reg) \
+static ssize_t \
+show_##reg (struct device *dev, char *buf, int nr) \
+{ \
+ struct w83627ehf_data *data = w83627ehf_update_device(dev); \
+ return sprintf(buf, "%d\n", \
+ LM75_TEMP_FROM_REG(data->reg[nr])); \
+}
+show_temp_reg(temp);
+show_temp_reg(temp_max);
+show_temp_reg(temp_max_hyst);
+
+#define store_temp_reg(REG, reg) \
+static ssize_t \
+store_##reg (struct device *dev, const char *buf, size_t count, int nr) \
+{ \
+ struct i2c_client *client = to_i2c_client(dev); \
+ struct w83627ehf_data *data = i2c_get_clientdata(client); \
+ u32 val = simple_strtoul(buf, NULL, 10); \
+ \
+ down(&data->update_lock); \
+ data->reg[nr] = LM75_TEMP_TO_REG(val); \
+ w83627ehf_write_value(client, W83627EHF_REG_TEMP_##REG[nr], \
+ data->reg[nr]); \
+ up(&data->update_lock); \
+ return count; \
+}
+store_temp_reg(OVER, temp_max);
+store_temp_reg(HYST, temp_max_hyst);
+
+#define sysfs_temp_offset(offset) \
+static ssize_t \
+show_reg_temp##offset (struct device *dev, struct device_attribute *attr, \
+ char *buf) \
+{ \
+ return show_temp(dev, buf, offset - 2); \
+} \
+static DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
+ show_reg_temp##offset, NULL);
+
+#define sysfs_temp_reg_offset(reg, offset) \
+static ssize_t \
+show_reg_temp##offset##_##reg(struct device *dev, struct device_attribute *attr, \
+ char *buf) \
+{ \
+ return show_temp_##reg(dev, buf, offset - 2); \
+} \
+static ssize_t \
+store_reg_temp##offset##_##reg(struct device *dev, struct device_attribute *attr, \
+ const char *buf, size_t count) \
+{ \
+ return store_temp_##reg(dev, buf, count, offset - 2); \
+} \
+static DEVICE_ATTR(temp##offset##_##reg, S_IRUGO| S_IWUSR, \
+ show_reg_temp##offset##_##reg, \
+ store_reg_temp##offset##_##reg);
+
+sysfs_temp_offset(2);
+sysfs_temp_reg_offset(max, 2);
+sysfs_temp_reg_offset(max_hyst, 2);
+sysfs_temp_offset(3);
+sysfs_temp_reg_offset(max, 3);
+sysfs_temp_reg_offset(max_hyst, 3);
+
+/*
+ * Driver and client management
+ */
+
+static struct i2c_driver w83627ehf_driver;
+
+static void w83627ehf_init_client(struct i2c_client *client)
+{
+ int i;
+ u8 tmp;
+
+ /* Start monitoring is needed */
+ tmp = w83627ehf_read_value(client, W83627EHF_REG_CONFIG);
+ if (!(tmp & 0x01))
+ w83627ehf_write_value(client, W83627EHF_REG_CONFIG,
+ tmp | 0x01);
+
+ /* Enable temp2 and temp3 if needed */
+ for (i = 0; i < 2; i++) {
+ tmp = w83627ehf_read_value(client,
+ W83627EHF_REG_TEMP_CONFIG[i]);
+ if (tmp & 0x01)
+ w83627ehf_write_value(client,
+ W83627EHF_REG_TEMP_CONFIG[i],
+ tmp & 0xfe);
+ }
+}
+
+static int w83627ehf_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+ struct i2c_client *client;
+ struct w83627ehf_data *data;
+ int i, err = 0;
+
+ if (!i2c_is_isa_adapter(adapter))
+ return 0;
+
+ if (!request_region(address, REGION_LENGTH, w83627ehf_driver.name)) {
+ err = -EBUSY;
+ goto exit;
+ }
+
+ if (!(data = kmalloc(sizeof(struct w83627ehf_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+ goto exit_release;
+ }
+ memset(data, 0, sizeof(struct w83627ehf_data));
+
+ client = &data->client;
+ i2c_set_clientdata(client, data);
+ client->addr = address;
+ init_MUTEX(&data->lock);
+ client->adapter = adapter;
+ client->driver = &w83627ehf_driver;
+ client->flags = 0;
+
+ strlcpy(client->name, "w83627ehf", I2C_NAME_SIZE);
+ data->valid = 0;
+ init_MUTEX(&data->update_lock);
+
+ /* Tell the i2c layer a new client has arrived */
+ if ((err = i2c_attach_client(client)))
+ goto exit_free;
+
+ /* Initialize the chip */
+ w83627ehf_init_client(client);
+
+ /* A few vars need to be filled upon startup */
+ for (i = 0; i < 5; i++)
+ data->fan_min[i] = w83627ehf_read_value(client,
+ W83627EHF_REG_FAN_MIN[i]);
+
+ /* It looks like fan4 and fan5 pins can be alternatively used
+ as fan on/off switches */
+ data->has_fan = 0x07; /* fan1, fan2 and fan3 */
+ i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1);
+ if (i & (1 << 2))
+ data->has_fan |= (1 << 3);
+ if (i & (1 << 0))
+ data->has_fan |= (1 << 4);
+
+ /* Register sysfs hooks */
+ device_create_file(&client->dev, &dev_attr_fan1_input);
+ device_create_file(&client->dev, &dev_attr_fan1_min);
+ device_create_file(&client->dev, &dev_attr_fan1_div);
+ device_create_file(&client->dev, &dev_attr_fan2_input);
+ device_create_file(&client->dev, &dev_attr_fan2_min);
+ device_create_file(&client->dev, &dev_attr_fan2_div);
+ device_create_file(&client->dev, &dev_attr_fan3_input);
+ device_create_file(&client->dev, &dev_attr_fan3_min);
+ device_create_file(&client->dev, &dev_attr_fan3_div);
+
+ if (data->has_fan & (1 << 3)) {
+ device_create_file(&client->dev, &dev_attr_fan4_input);
+ device_create_file(&client->dev, &dev_attr_fan4_min);
+ device_create_file(&client->dev, &dev_attr_fan4_div);
+ }
+ if (data->has_fan & (1 << 4)) {
+ device_create_file(&client->dev, &dev_attr_fan5_input);
+ device_create_file(&client->dev, &dev_attr_fan5_min);
+ device_create_file(&client->dev, &dev_attr_fan5_div);
+ }
+
+ device_create_file(&client->dev, &dev_attr_temp1_input);
+ device_create_file(&client->dev, &dev_attr_temp1_max);
+ device_create_file(&client->dev, &dev_attr_temp1_max_hyst);
+ device_create_file(&client->dev, &dev_attr_temp2_input);
+ device_create_file(&client->dev, &dev_attr_temp2_max);
+ device_create_file(&client->dev, &dev_attr_temp2_max_hyst);
+ device_create_file(&client->dev, &dev_attr_temp3_input);
+ device_create_file(&client->dev, &dev_attr_temp3_max);
+ device_create_file(&client->dev, &dev_attr_temp3_max_hyst);
+
+ return 0;
+
+exit_free:
+ kfree(data);
+exit_release:
+ release_region(address, REGION_LENGTH);
+exit:
+ return err;
+}
+
+static int w83627ehf_attach_adapter(struct i2c_adapter *adapter)
+{
+ if (!(adapter->class & I2C_CLASS_HWMON))
+ return 0;
+ return i2c_detect(adapter, &addr_data, w83627ehf_detect);
+}
+
+static int w83627ehf_detach_client(struct i2c_client *client)
+{
+ int err;
+
+ if ((err = i2c_detach_client(client))) {
+ dev_err(&client->dev, "Client deregistration failed, "
+ "client not detached.\n");
+ return err;
+ }
+ release_region(client->addr, REGION_LENGTH);
+ kfree(i2c_get_clientdata(client));
+
+ return 0;
+}
+
+static struct i2c_driver w83627ehf_driver = {
+ .owner = THIS_MODULE,
+ .name = "w83627ehf",
+ .flags = I2C_DF_NOTIFY,
+ .attach_adapter = w83627ehf_attach_adapter,
+ .detach_client = w83627ehf_detach_client,
+};
+
+static int __init w83627ehf_find(int sioaddr, int *address)
+{
+ u16 val;
+
+ REG = sioaddr;
+ VAL = sioaddr + 1;
+ superio_enter();
+
+ val = (superio_inb(SIO_REG_DEVID) << 8)
+ | superio_inb(SIO_REG_DEVID + 1);
+ if ((val & SIO_ID_MASK) != SIO_W83627EHF_ID) {
+ superio_exit();
+ return -ENODEV;
+ }
+
+ superio_select(W83627EHF_LD_HWM);
+ val = (superio_inb(SIO_REG_ADDR) << 8)
+ | superio_inb(SIO_REG_ADDR + 1);
+ *address = val & ~(REGION_LENGTH - 1);
+ if (*address == 0) {
+ superio_exit();
+ return -ENODEV;
+ }
+
+ /* Activate logical device if needed */
+ val = superio_inb(SIO_REG_ENABLE);
+ if (!(val & 0x01))
+ superio_outb(SIO_REG_ENABLE, val | 0x01);
+
+ superio_exit();
+ return 0;
+}
+
+static int __init sensors_w83627ehf_init(void)
+{
+ if (w83627ehf_find(0x2e, &normal_isa[0])
+ && w83627ehf_find(0x4e, &normal_isa[0]))
+ return -ENODEV;
+
+ return i2c_add_driver(&w83627ehf_driver);
+}
+
+static void __exit sensors_w83627ehf_exit(void)
+{
+ i2c_del_driver(&w83627ehf_driver);
+}
+
+MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
+MODULE_DESCRIPTION("W83627EHF driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_w83627ehf_init);
+module_exit(sensors_w83627ehf_exit);
diff --git a/drivers/i2c/chips/w83627hf.c b/drivers/i2c/chips/w83627hf.c
index b1da5ed696d..bd87a42e068 100644
--- a/drivers/i2c/chips/w83627hf.c
+++ b/drivers/i2c/chips/w83627hf.c
@@ -264,7 +264,7 @@ static inline u8 DIV_TO_REG(long val)
{
int i;
val = SENSORS_LIMIT(val, 1, 128) >> 1;
- for (i = 0; i < 6; i++) {
+ for (i = 0; i < 7; i++) {
if (val == 0)
break;
val >>= 1;
@@ -368,19 +368,19 @@ store_in_reg(MAX, max)
#define sysfs_in_offset(offset) \
static ssize_t \
-show_regs_in_##offset (struct device *dev, char *buf) \
+show_regs_in_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_in(dev, buf, offset); \
} \
static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_regs_in_##offset, NULL);
#define sysfs_in_reg_offset(reg, offset) \
-static ssize_t show_regs_in_##reg##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_in_##reg##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_in_##reg (dev, buf, offset); \
} \
static ssize_t \
-store_regs_in_##reg##offset (struct device *dev, \
+store_regs_in_##reg##offset (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return store_in_##reg (dev, buf, count, offset); \
@@ -419,25 +419,25 @@ static ssize_t show_in_0(struct w83627hf_data *data, char *buf, u8 reg)
return sprintf(buf,"%ld\n", in0);
}
-static ssize_t show_regs_in_0(struct device *dev, char *buf)
+static ssize_t show_regs_in_0(struct device *dev, struct device_attribute *attr, char *buf)
{
struct w83627hf_data *data = w83627hf_update_device(dev);
return show_in_0(data, buf, data->in[0]);
}
-static ssize_t show_regs_in_min0(struct device *dev, char *buf)
+static ssize_t show_regs_in_min0(struct device *dev, struct device_attribute *attr, char *buf)
{
struct w83627hf_data *data = w83627hf_update_device(dev);
return show_in_0(data, buf, data->in_min[0]);
}
-static ssize_t show_regs_in_max0(struct device *dev, char *buf)
+static ssize_t show_regs_in_max0(struct device *dev, struct device_attribute *attr, char *buf)
{
struct w83627hf_data *data = w83627hf_update_device(dev);
return show_in_0(data, buf, data->in_max[0]);
}
-static ssize_t store_regs_in_min0(struct device *dev,
+static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -462,7 +462,7 @@ static ssize_t store_regs_in_min0(struct device *dev,
return count;
}
-static ssize_t store_regs_in_max0(struct device *dev,
+static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -531,19 +531,19 @@ store_fan_min(struct device *dev, const char *buf, size_t count, int nr)
}
#define sysfs_fan_offset(offset) \
-static ssize_t show_regs_fan_##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_fan(dev, buf, offset); \
} \
static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_regs_fan_##offset, NULL);
#define sysfs_fan_min_offset(offset) \
-static ssize_t show_regs_fan_min##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_fan_min##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_fan_min(dev, buf, offset); \
} \
static ssize_t \
-store_regs_fan_min##offset (struct device *dev, const char *buf, size_t count) \
+store_regs_fan_min##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
{ \
return store_fan_min(dev, buf, count, offset); \
} \
@@ -608,19 +608,19 @@ store_temp_reg(HYST, max_hyst);
#define sysfs_temp_offset(offset) \
static ssize_t \
-show_regs_temp_##offset (struct device *dev, char *buf) \
+show_regs_temp_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_temp(dev, buf, offset); \
} \
static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_regs_temp_##offset, NULL);
#define sysfs_temp_reg_offset(reg, offset) \
-static ssize_t show_regs_temp_##reg##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_temp_##reg##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_temp_##reg (dev, buf, offset); \
} \
static ssize_t \
-store_regs_temp_##reg##offset (struct device *dev, \
+store_regs_temp_##reg##offset (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return store_temp_##reg (dev, buf, count, offset); \
@@ -645,7 +645,7 @@ device_create_file(&client->dev, &dev_attr_temp##offset##_max_hyst); \
} while (0)
static ssize_t
-show_vid_reg(struct device *dev, char *buf)
+show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
{
struct w83627hf_data *data = w83627hf_update_device(dev);
return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
@@ -655,13 +655,13 @@ static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
device_create_file(&client->dev, &dev_attr_cpu0_vid)
static ssize_t
-show_vrm_reg(struct device *dev, char *buf)
+show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
{
struct w83627hf_data *data = w83627hf_update_device(dev);
return sprintf(buf, "%ld\n", (long) data->vrm);
}
static ssize_t
-store_vrm_reg(struct device *dev, const char *buf, size_t count)
+store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct w83627hf_data *data = i2c_get_clientdata(client);
@@ -677,7 +677,7 @@ static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
device_create_file(&client->dev, &dev_attr_vrm)
static ssize_t
-show_alarms_reg(struct device *dev, char *buf)
+show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
{
struct w83627hf_data *data = w83627hf_update_device(dev);
return sprintf(buf, "%ld\n", (long) data->alarms);
@@ -687,7 +687,7 @@ static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
device_create_file(&client->dev, &dev_attr_alarms)
#define show_beep_reg(REG, reg) \
-static ssize_t show_beep_##reg (struct device *dev, char *buf) \
+static ssize_t show_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct w83627hf_data *data = w83627hf_update_device(dev); \
return sprintf(buf,"%ld\n", \
@@ -732,12 +732,12 @@ store_beep_reg(struct device *dev, const char *buf, size_t count,
}
#define sysfs_beep(REG, reg) \
-static ssize_t show_regs_beep_##reg (struct device *dev, char *buf) \
+static ssize_t show_regs_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
- return show_beep_##reg(dev, buf); \
+ return show_beep_##reg(dev, attr, buf); \
} \
static ssize_t \
-store_regs_beep_##reg (struct device *dev, const char *buf, size_t count) \
+store_regs_beep_##reg (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
{ \
return store_beep_reg(dev, buf, count, BEEP_##REG); \
} \
@@ -801,12 +801,12 @@ store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr)
}
#define sysfs_fan_div(offset) \
-static ssize_t show_regs_fan_div_##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_fan_div_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_fan_div_reg(dev, buf, offset); \
} \
static ssize_t \
-store_regs_fan_div_##offset (struct device *dev, \
+store_regs_fan_div_##offset (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return store_fan_div_reg(dev, buf, count, offset - 1); \
@@ -861,12 +861,12 @@ store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr)
}
#define sysfs_pwm(offset) \
-static ssize_t show_regs_pwm_##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_pwm_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_pwm_reg(dev, buf, offset); \
} \
static ssize_t \
-store_regs_pwm_##offset (struct device *dev, const char *buf, size_t count) \
+store_regs_pwm_##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
{ \
return store_pwm_reg(dev, buf, count, offset); \
} \
@@ -937,12 +937,12 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr)
}
#define sysfs_sensor(offset) \
-static ssize_t show_regs_sensor_##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_sensor_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_sensor_reg(dev, buf, offset); \
} \
static ssize_t \
-store_regs_sensor_##offset (struct device *dev, const char *buf, size_t count) \
+store_regs_sensor_##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
{ \
return store_sensor_reg(dev, buf, count, offset); \
} \
diff --git a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c
index 4954e465c41..0bb131ce09e 100644
--- a/drivers/i2c/chips/w83781d.c
+++ b/drivers/i2c/chips/w83781d.c
@@ -28,14 +28,11 @@
as99127f rev.2 (type_name = as99127f) 0x31 0x5ca3 yes no
w83781d 7 3 0 3 0x10-1 0x5ca3 yes yes
w83627hf 9 3 2 3 0x21 0x5ca3 yes yes(LPC)
- w83627thf 9 3 2 3 0x90 0x5ca3 no yes(LPC)
w83782d 9 3 2-4 3 0x30 0x5ca3 yes yes
w83783s 5-6 3 2 1-2 0x40 0x5ca3 yes no
- w83697hf 8 2 2 2 0x60 0x5ca3 no yes(LPC)
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -53,7 +50,7 @@ static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
static unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END };
/* Insmod parameters */
-SENSORS_INSMOD_6(w83781d, w83782d, w83783s, w83627hf, as99127f, w83697hf);
+SENSORS_INSMOD_5(w83781d, w83782d, w83783s, w83627hf, as99127f);
I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
"{bus, clientaddr, subclientaddr1, subclientaddr2}");
@@ -173,7 +170,6 @@ FAN_TO_REG(long rpm, int div)
: (val)) / 1000, 0, 0xff))
#define TEMP_FROM_REG(val) (((val) & 0x80 ? (val)-0x100 : (val)) * 1000)
-#define ALARMS_FROM_REG(val) (val)
#define PWM_FROM_REG(val) (val)
#define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255))
#define BEEP_MASK_FROM_REG(val,type) ((type) == as99127f ? \
@@ -193,7 +189,7 @@ DIV_TO_REG(long val, enum chips type)
val = SENSORS_LIMIT(val, 1,
((type == w83781d
|| type == as99127f) ? 8 : 128)) >> 1;
- for (i = 0; i < 6; i++) {
+ for (i = 0; i < 7; i++) {
if (val == 0)
break;
val >>= 1;
@@ -309,18 +305,18 @@ store_in_reg(MAX, max);
#define sysfs_in_offset(offset) \
static ssize_t \
-show_regs_in_##offset (struct device *dev, char *buf) \
+show_regs_in_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_in(dev, buf, offset); \
} \
static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_regs_in_##offset, NULL);
#define sysfs_in_reg_offset(reg, offset) \
-static ssize_t show_regs_in_##reg##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_in_##reg##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_in_##reg (dev, buf, offset); \
} \
-static ssize_t store_regs_in_##reg##offset (struct device *dev, const char *buf, size_t count) \
+static ssize_t store_regs_in_##reg##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
{ \
return store_in_##reg (dev, buf, count, offset); \
} \
@@ -378,18 +374,18 @@ store_fan_min(struct device *dev, const char *buf, size_t count, int nr)
}
#define sysfs_fan_offset(offset) \
-static ssize_t show_regs_fan_##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_fan(dev, buf, offset); \
} \
static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_regs_fan_##offset, NULL);
#define sysfs_fan_min_offset(offset) \
-static ssize_t show_regs_fan_min##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_fan_min##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_fan_min(dev, buf, offset); \
} \
-static ssize_t store_regs_fan_min##offset (struct device *dev, const char *buf, size_t count) \
+static ssize_t store_regs_fan_min##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
{ \
return store_fan_min(dev, buf, count, offset); \
} \
@@ -452,18 +448,18 @@ store_temp_reg(HYST, max_hyst);
#define sysfs_temp_offset(offset) \
static ssize_t \
-show_regs_temp_##offset (struct device *dev, char *buf) \
+show_regs_temp_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_temp(dev, buf, offset); \
} \
static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_regs_temp_##offset, NULL);
#define sysfs_temp_reg_offset(reg, offset) \
-static ssize_t show_regs_temp_##reg##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_temp_##reg##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_temp_##reg (dev, buf, offset); \
} \
-static ssize_t store_regs_temp_##reg##offset (struct device *dev, const char *buf, size_t count) \
+static ssize_t store_regs_temp_##reg##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
{ \
return store_temp_##reg (dev, buf, count, offset); \
} \
@@ -486,7 +482,7 @@ device_create_file(&client->dev, &dev_attr_temp##offset##_max_hyst); \
} while (0)
static ssize_t
-show_vid_reg(struct device *dev, char *buf)
+show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
{
struct w83781d_data *data = w83781d_update_device(dev);
return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
@@ -497,14 +493,14 @@ DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
#define device_create_file_vid(client) \
device_create_file(&client->dev, &dev_attr_cpu0_vid);
static ssize_t
-show_vrm_reg(struct device *dev, char *buf)
+show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
{
struct w83781d_data *data = w83781d_update_device(dev);
return sprintf(buf, "%ld\n", (long) data->vrm);
}
static ssize_t
-store_vrm_reg(struct device *dev, const char *buf, size_t count)
+store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct w83781d_data *data = i2c_get_clientdata(client);
@@ -521,23 +517,23 @@ DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
#define device_create_file_vrm(client) \
device_create_file(&client->dev, &dev_attr_vrm);
static ssize_t
-show_alarms_reg(struct device *dev, char *buf)
+show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
{
struct w83781d_data *data = w83781d_update_device(dev);
- return sprintf(buf, "%ld\n", (long) ALARMS_FROM_REG(data->alarms));
+ return sprintf(buf, "%u\n", data->alarms);
}
static
DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
#define device_create_file_alarms(client) \
device_create_file(&client->dev, &dev_attr_alarms);
-static ssize_t show_beep_mask (struct device *dev, char *buf)
+static ssize_t show_beep_mask (struct device *dev, struct device_attribute *attr, char *buf)
{
struct w83781d_data *data = w83781d_update_device(dev);
return sprintf(buf, "%ld\n",
(long)BEEP_MASK_FROM_REG(data->beep_mask, data->type));
}
-static ssize_t show_beep_enable (struct device *dev, char *buf)
+static ssize_t show_beep_enable (struct device *dev, struct device_attribute *attr, char *buf)
{
struct w83781d_data *data = w83781d_update_device(dev);
return sprintf(buf, "%ld\n",
@@ -583,11 +579,11 @@ store_beep_reg(struct device *dev, const char *buf, size_t count,
}
#define sysfs_beep(REG, reg) \
-static ssize_t show_regs_beep_##reg (struct device *dev, char *buf) \
+static ssize_t show_regs_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
- return show_beep_##reg(dev, buf); \
+ return show_beep_##reg(dev, attr, buf); \
} \
-static ssize_t store_regs_beep_##reg (struct device *dev, const char *buf, size_t count) \
+static ssize_t store_regs_beep_##reg (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
{ \
return store_beep_reg(dev, buf, count, BEEP_##REG); \
} \
@@ -653,11 +649,11 @@ store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr)
}
#define sysfs_fan_div(offset) \
-static ssize_t show_regs_fan_div_##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_fan_div_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_fan_div_reg(dev, buf, offset); \
} \
-static ssize_t store_regs_fan_div_##offset (struct device *dev, const char *buf, size_t count) \
+static ssize_t store_regs_fan_div_##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
{ \
return store_fan_div_reg(dev, buf, count, offset - 1); \
} \
@@ -737,11 +733,11 @@ store_pwmenable_reg(struct device *dev, const char *buf, size_t count, int nr)
}
#define sysfs_pwm(offset) \
-static ssize_t show_regs_pwm_##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_pwm_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_pwm_reg(dev, buf, offset); \
} \
-static ssize_t store_regs_pwm_##offset (struct device *dev, \
+static ssize_t store_regs_pwm_##offset (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return store_pwm_reg(dev, buf, count, offset); \
@@ -750,11 +746,11 @@ static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \
show_regs_pwm_##offset, store_regs_pwm_##offset);
#define sysfs_pwmenable(offset) \
-static ssize_t show_regs_pwmenable_##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_pwmenable_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_pwmenable_reg(dev, buf, offset); \
} \
-static ssize_t store_regs_pwmenable_##offset (struct device *dev, \
+static ssize_t store_regs_pwmenable_##offset (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
return store_pwmenable_reg(dev, buf, count, offset); \
@@ -832,11 +828,11 @@ store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr)
}
#define sysfs_sensor(offset) \
-static ssize_t show_regs_sensor_##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_sensor_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return show_sensor_reg(dev, buf, offset); \
} \
-static ssize_t store_regs_sensor_##offset (struct device *dev, const char *buf, size_t count) \
+static ssize_t store_regs_sensor_##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
{ \
return store_sensor_reg(dev, buf, count, offset); \
} \
@@ -1000,13 +996,6 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
err = -EINVAL;
goto ERROR0;
}
- if (!is_isa && kind == w83697hf) {
- dev_err(&adapter->dev,
- "Cannot force ISA-only chip for I2C address 0x%02x.\n",
- address);
- err = -EINVAL;
- goto ERROR0;
- }
if (is_isa)
if (!request_region(address, W83781D_EXTENT,
@@ -1139,12 +1128,10 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
else if (val1 == 0x40 && vendid == winbond && !is_isa
&& address == 0x2d)
kind = w83783s;
- else if ((val1 == 0x21 || val1 == 0x90) && vendid == winbond)
+ else if (val1 == 0x21 && vendid == winbond)
kind = w83627hf;
else if (val1 == 0x31 && !is_isa && address >= 0x28)
kind = as99127f;
- else if (val1 == 0x60 && vendid == winbond && is_isa)
- kind = w83697hf;
else {
if (kind == 0)
dev_warn(&new_client->dev, "Ignoring 'force' "
@@ -1163,14 +1150,9 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
} else if (kind == w83783s) {
client_name = "w83783s";
} else if (kind == w83627hf) {
- if (val1 == 0x90)
- client_name = "w83627thf";
- else
- client_name = "w83627hf";
+ client_name = "w83627hf";
} else if (kind == as99127f) {
client_name = "as99127f";
- } else if (kind == w83697hf) {
- client_name = "w83697hf";
}
/* Fill in the remaining client fields and put into the global list */
@@ -1208,7 +1190,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
/* Register sysfs hooks */
device_create_file_in(new_client, 0);
- if (kind != w83783s && kind != w83697hf)
+ if (kind != w83783s)
device_create_file_in(new_client, 1);
device_create_file_in(new_client, 2);
device_create_file_in(new_client, 3);
@@ -1222,24 +1204,19 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
device_create_file_fan(new_client, 1);
device_create_file_fan(new_client, 2);
- if (kind != w83697hf)
- device_create_file_fan(new_client, 3);
+ device_create_file_fan(new_client, 3);
device_create_file_temp(new_client, 1);
device_create_file_temp(new_client, 2);
- if (kind != w83783s && kind != w83697hf)
+ if (kind != w83783s)
device_create_file_temp(new_client, 3);
- if (kind != w83697hf)
- device_create_file_vid(new_client);
-
- if (kind != w83697hf)
- device_create_file_vrm(new_client);
+ device_create_file_vid(new_client);
+ device_create_file_vrm(new_client);
device_create_file_fan_div(new_client, 1);
device_create_file_fan_div(new_client, 2);
- if (kind != w83697hf)
- device_create_file_fan_div(new_client, 3);
+ device_create_file_fan_div(new_client, 3);
device_create_file_alarms(new_client);
@@ -1258,7 +1235,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
if (kind != as99127f && kind != w83781d) {
device_create_file_sensor(new_client, 1);
device_create_file_sensor(new_client, 2);
- if (kind != w83783s && kind != w83697hf)
+ if (kind != w83783s)
device_create_file_sensor(new_client, 3);
}
@@ -1481,7 +1458,7 @@ w83781d_init_client(struct i2c_client *client)
else
data->sens[i - 1] = 2;
}
- if ((type == w83783s || type == w83697hf) && (i == 2))
+ if (type == w83783s && i == 2)
break;
}
}
@@ -1497,7 +1474,7 @@ w83781d_init_client(struct i2c_client *client)
}
/* Enable temp3 */
- if (type != w83783s && type != w83697hf) {
+ if (type != w83783s) {
tmp = w83781d_read_value(client,
W83781D_REG_TEMP3_CONFIG);
if (tmp & 0x01) {
@@ -1538,8 +1515,7 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
dev_dbg(dev, "Starting device update\n");
for (i = 0; i <= 8; i++) {
- if ((data->type == w83783s || data->type == w83697hf)
- && (i == 1))
+ if (data->type == w83783s && i == 1)
continue; /* 783S has no in1 */
data->in[i] =
w83781d_read_value(client, W83781D_REG_IN(i));
@@ -1547,7 +1523,7 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
w83781d_read_value(client, W83781D_REG_IN_MIN(i));
data->in_max[i] =
w83781d_read_value(client, W83781D_REG_IN_MAX(i));
- if ((data->type != w83782d) && (data->type != w83697hf)
+ if ((data->type != w83782d)
&& (data->type != w83627hf) && (i == 6))
break;
}
@@ -1583,7 +1559,7 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
w83781d_read_value(client, W83781D_REG_TEMP_OVER(2));
data->temp_max_hyst_add[0] =
w83781d_read_value(client, W83781D_REG_TEMP_HYST(2));
- if (data->type != w83783s && data->type != w83697hf) {
+ if (data->type != w83783s) {
data->temp_add[1] =
w83781d_read_value(client, W83781D_REG_TEMP(3));
data->temp_max_add[1] =
@@ -1594,26 +1570,18 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
W83781D_REG_TEMP_HYST(3));
}
i = w83781d_read_value(client, W83781D_REG_VID_FANDIV);
- if (data->type != w83697hf) {
- data->vid = i & 0x0f;
- data->vid |=
- (w83781d_read_value(client, W83781D_REG_CHIPID) &
- 0x01)
- << 4;
- }
+ data->vid = i & 0x0f;
+ data->vid |= (w83781d_read_value(client,
+ W83781D_REG_CHIPID) & 0x01) << 4;
data->fan_div[0] = (i >> 4) & 0x03;
data->fan_div[1] = (i >> 6) & 0x03;
- if (data->type != w83697hf) {
- data->fan_div[2] = (w83781d_read_value(client,
- W83781D_REG_PIN)
- >> 6) & 0x03;
- }
+ data->fan_div[2] = (w83781d_read_value(client,
+ W83781D_REG_PIN) >> 6) & 0x03;
if ((data->type != w83781d) && (data->type != as99127f)) {
i = w83781d_read_value(client, W83781D_REG_VBAT);
data->fan_div[0] |= (i >> 3) & 0x04;
data->fan_div[1] |= (i >> 4) & 0x04;
- if (data->type != w83697hf)
- data->fan_div[2] |= (i >> 5) & 0x04;
+ data->fan_div[2] |= (i >> 5) & 0x04;
}
data->alarms =
w83781d_read_value(client,
diff --git a/drivers/i2c/chips/w83l785ts.c b/drivers/i2c/chips/w83l785ts.c
index 59bbc5881fa..4469d52aba4 100644
--- a/drivers/i2c/chips/w83l785ts.c
+++ b/drivers/i2c/chips/w83l785ts.c
@@ -30,7 +30,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/init.h>
@@ -118,13 +117,13 @@ struct w83l785ts_data {
* Sysfs stuff
*/
-static ssize_t show_temp(struct device *dev, char *buf)
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf)
{
struct w83l785ts_data *data = w83l785ts_update_device(dev);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp));
}
-static ssize_t show_temp_over(struct device *dev, char *buf)
+static ssize_t show_temp_over(struct device *dev, struct device_attribute *attr, char *buf)
{
struct w83l785ts_data *data = w83l785ts_update_device(dev);
return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over));
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 9011627d7eb..51ce268998c 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -21,7 +21,6 @@
All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl>
SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> */
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
@@ -103,7 +102,7 @@ static struct class i2c_adapter_class = {
.release = &i2c_adapter_class_dev_release,
};
-static ssize_t show_adapter_name(struct device *dev, char *buf)
+static ssize_t show_adapter_name(struct device *dev, struct device_attribute *attr, char *buf)
{
struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
return sprintf(buf, "%s\n", adap->name);
@@ -117,7 +116,7 @@ static void i2c_client_release(struct device *dev)
complete(&client->released);
}
-static ssize_t show_client_name(struct device *dev, char *buf)
+static ssize_t show_client_name(struct device *dev, struct device_attribute *attr, char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
return sprintf(buf, "%s\n", client->name);
@@ -239,7 +238,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
}
/* detach any active clients. This must be done first, because
- * it can fail; in which case we give upp. */
+ * it can fail; in which case we give up. */
list_for_each_safe(item, _n, &adap->clients) {
client = list_entry(item, struct i2c_client, list);
@@ -612,27 +611,16 @@ int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
struct i2c_adapter *adap=client->adapter;
struct i2c_msg msg;
- if (client->adapter->algo->master_xfer) {
- msg.addr = client->addr;
- msg.flags = client->flags & I2C_M_TEN;
- msg.len = count;
- msg.buf = (char *)buf;
+ msg.addr = client->addr;
+ msg.flags = client->flags & I2C_M_TEN;
+ msg.len = count;
+ msg.buf = (char *)buf;
- dev_dbg(&client->adapter->dev, "master_send: writing %d bytes.\n",
- count);
-
- down(&adap->bus_lock);
- ret = adap->algo->master_xfer(adap,&msg,1);
- up(&adap->bus_lock);
+ ret = i2c_transfer(adap, &msg, 1);
- /* if everything went ok (i.e. 1 msg transmitted), return #bytes
- * transmitted, else error code.
- */
- return (ret == 1 )? count : ret;
- } else {
- dev_err(&client->adapter->dev, "I2C level transfers not supported\n");
- return -ENOSYS;
- }
+ /* If everything went ok (i.e. 1 msg transmitted), return #bytes
+ transmitted, else error code. */
+ return (ret == 1) ? count : ret;
}
int i2c_master_recv(struct i2c_client *client, char *buf ,int count)
@@ -640,31 +628,18 @@ int i2c_master_recv(struct i2c_client *client, char *buf ,int count)
struct i2c_adapter *adap=client->adapter;
struct i2c_msg msg;
int ret;
- if (client->adapter->algo->master_xfer) {
- msg.addr = client->addr;
- msg.flags = client->flags & I2C_M_TEN;
- msg.flags |= I2C_M_RD;
- msg.len = count;
- msg.buf = buf;
-
- dev_dbg(&client->adapter->dev, "master_recv: reading %d bytes.\n",
- count);
-
- down(&adap->bus_lock);
- ret = adap->algo->master_xfer(adap,&msg,1);
- up(&adap->bus_lock);
-
- dev_dbg(&client->adapter->dev, "master_recv: return:%d (count:%d, addr:0x%02x)\n",
- ret, count, client->addr);
-
- /* if everything went ok (i.e. 1 msg transmitted), return #bytes
- * transmitted, else error code.
- */
- return (ret == 1 )? count : ret;
- } else {
- dev_err(&client->adapter->dev, "I2C level transfers not supported\n");
- return -ENOSYS;
- }
+
+ msg.addr = client->addr;
+ msg.flags = client->flags & I2C_M_TEN;
+ msg.flags |= I2C_M_RD;
+ msg.len = count;
+ msg.buf = buf;
+
+ ret = i2c_transfer(adap, &msg, 1);
+
+ /* If everything went ok (i.e. 1 msg transmitted), return #bytes
+ transmitted, else error code. */
+ return (ret == 1) ? count : ret;
}
@@ -742,18 +717,6 @@ int i2c_probe(struct i2c_adapter *adapter,
found = 1;
}
}
- for (i = 0;
- !found && (address_data->ignore_range[i] != I2C_CLIENT_END);
- i += 3) {
- if (((adap_id == address_data->ignore_range[i]) ||
- ((address_data->ignore_range[i]==ANY_I2C_BUS))) &&
- (addr >= address_data->ignore_range[i+1]) &&
- (addr <= address_data->ignore_range[i+2])) {
- dev_dbg(&adapter->dev, "found ignore_range parameter for adapter %d, "
- "addr %04x\n", adap_id,addr);
- found = 1;
- }
- }
if (found)
continue;
@@ -770,17 +733,6 @@ int i2c_probe(struct i2c_adapter *adapter,
}
for (i = 0;
- !found && (address_data->normal_i2c_range[i] != I2C_CLIENT_END);
- i += 2) {
- if ((addr >= address_data->normal_i2c_range[i]) &&
- (addr <= address_data->normal_i2c_range[i+1])) {
- found = 1;
- dev_dbg(&adapter->dev, "found normal i2c_range entry for adapter %d, "
- "addr %04x\n", adap_id,addr);
- }
- }
-
- for (i = 0;
!found && (address_data->probe[i] != I2C_CLIENT_END);
i += 2) {
if (((adap_id == address_data->probe[i]) ||
@@ -791,18 +743,6 @@ int i2c_probe(struct i2c_adapter *adapter,
"addr %04x\n", adap_id,addr);
}
}
- for (i = 0;
- !found && (address_data->probe_range[i] != I2C_CLIENT_END);
- i += 3) {
- if (((adap_id == address_data->probe_range[i]) ||
- (address_data->probe_range[i] == ANY_I2C_BUS)) &&
- (addr >= address_data->probe_range[i+1]) &&
- (addr <= address_data->probe_range[i+2])) {
- found = 1;
- dev_dbg(&adapter->dev, "found probe_range parameter for adapter %d, "
- "addr %04x\n", adap_id,addr);
- }
- }
if (!found)
continue;
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 86c4d0149e8..bc5d557e5dd 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -29,7 +29,6 @@
/* The devfs code is contributed by Philipp Matthias Hahn
<pmhahn@titan.lahn.de> */
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
@@ -214,7 +213,7 @@ static int i2cdev_ioctl(struct inode *inode, struct file *file,
sizeof(rdwr_arg)))
return -EFAULT;
- /* Put an arbritrary limit on the number of messages that can
+ /* Put an arbitrary limit on the number of messages that can
* be sent at once */
if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)
return -EINVAL;
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 3ac0a535b4a..0273f124a4f 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -672,8 +672,8 @@ config BLK_DEV_SVWKS
chipsets.
config BLK_DEV_SGIIOC4
- tristate "Silicon Graphics IOC4 chipset support"
- depends on IA64_SGI_SN2 || IA64_GENERIC
+ tristate "Silicon Graphics IOC4 chipset ATA/ATAPI support"
+ depends on (IA64_SGI_SN2 || IA64_GENERIC) && SGI_IOC4
help
This driver adds PIO & MultiMode DMA-2 support for the SGI IOC4
chipset, which has one channel and can support two devices.
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 33a020faeab..0a31cfda08a 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -1932,8 +1932,11 @@ static ide_startstop_t cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
/*
* check if dma is safe
+ *
+ * NOTE! The "len" and "addr" checks should possibly have
+ * separate masks.
*/
- if ((rq->data_len & mask) || (addr & mask))
+ if ((rq->data_len & 15) || (addr & mask))
info->dma = 0;
}
@@ -2654,16 +2657,63 @@ int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock)
}
static
+int ide_cdrom_get_capabilities(ide_drive_t *drive, struct atapi_capabilities_page *cap)
+{
+ struct cdrom_info *info = drive->driver_data;
+ struct cdrom_device_info *cdi = &info->devinfo;
+ struct packet_command cgc;
+ int stat, attempts = 3, size = sizeof(*cap);
+
+ /*
+ * ACER50 (and others?) require the full spec length mode sense
+ * page capabilities size, but older drives break.
+ */
+ if (!(!strcmp(drive->id->model, "ATAPI CD ROM DRIVE 50X MAX") ||
+ !strcmp(drive->id->model, "WPI CDS-32X")))
+ size -= sizeof(cap->pad);
+
+ init_cdrom_command(&cgc, cap, size, CGC_DATA_UNKNOWN);
+ do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
+ stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
+ if (!stat)
+ break;
+ } while (--attempts);
+ return stat;
+}
+
+static
+void ide_cdrom_update_speed (ide_drive_t *drive, struct atapi_capabilities_page *cap)
+{
+ /* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */
+ if (!drive->id->model[0] &&
+ !strncmp(drive->id->fw_rev, "241N", 4)) {
+ CDROM_STATE_FLAGS(drive)->current_speed =
+ (((unsigned int)cap->curspeed) + (176/2)) / 176;
+ CDROM_CONFIG_FLAGS(drive)->max_speed =
+ (((unsigned int)cap->maxspeed) + (176/2)) / 176;
+ } else {
+ CDROM_STATE_FLAGS(drive)->current_speed =
+ (ntohs(cap->curspeed) + (176/2)) / 176;
+ CDROM_CONFIG_FLAGS(drive)->max_speed =
+ (ntohs(cap->maxspeed) + (176/2)) / 176;
+ }
+}
+
+static
int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed)
{
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
struct request_sense sense;
+ struct atapi_capabilities_page cap;
int stat;
if ((stat = cdrom_select_speed(drive, speed, &sense)) < 0)
return stat;
- cdi->speed = CDROM_STATE_FLAGS(drive)->current_speed;
+ if (!ide_cdrom_get_capabilities(drive, &cap)) {
+ ide_cdrom_update_speed(drive, &cap);
+ cdi->speed = CDROM_STATE_FLAGS(drive)->current_speed;
+ }
return 0;
}
@@ -2866,31 +2916,6 @@ static int ide_cdrom_register (ide_drive_t *drive, int nslots)
}
static
-int ide_cdrom_get_capabilities(ide_drive_t *drive, struct atapi_capabilities_page *cap)
-{
- struct cdrom_info *info = drive->driver_data;
- struct cdrom_device_info *cdi = &info->devinfo;
- struct packet_command cgc;
- int stat, attempts = 3, size = sizeof(*cap);
-
- /*
- * ACER50 (and others?) require the full spec length mode sense
- * page capabilities size, but older drives break.
- */
- if (!(!strcmp(drive->id->model, "ATAPI CD ROM DRIVE 50X MAX") ||
- !strcmp(drive->id->model, "WPI CDS-32X")))
- size -= sizeof(cap->pad);
-
- init_cdrom_command(&cgc, cap, size, CGC_DATA_UNKNOWN);
- do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
- stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
- if (!stat)
- break;
- } while (--attempts);
- return stat;
-}
-
-static
int ide_cdrom_probe_capabilities (ide_drive_t *drive)
{
struct cdrom_info *info = drive->driver_data;
@@ -2975,20 +3000,7 @@ int ide_cdrom_probe_capabilities (ide_drive_t *drive)
}
}
- /* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */
- if (!drive->id->model[0] &&
- !strncmp(drive->id->fw_rev, "241N", 4)) {
- CDROM_STATE_FLAGS(drive)->current_speed =
- (((unsigned int)cap.curspeed) + (176/2)) / 176;
- CDROM_CONFIG_FLAGS(drive)->max_speed =
- (((unsigned int)cap.maxspeed) + (176/2)) / 176;
- } else {
- CDROM_STATE_FLAGS(drive)->current_speed =
- (ntohs(cap.curspeed) + (176/2)) / 176;
- CDROM_CONFIG_FLAGS(drive)->max_speed =
- (ntohs(cap.maxspeed) + (176/2)) / 176;
- }
-
+ ide_cdrom_update_speed(drive, &cap);
/* don't print speed if the drive reported 0.
*/
printk(KERN_INFO "%s: ATAPI", drive->name);
@@ -3255,16 +3267,12 @@ sector_t ide_cdrom_capacity (ide_drive_t *drive)
return capacity * sectors_per_frame;
}
-static
-int ide_cdrom_cleanup(ide_drive_t *drive)
+static int ide_cd_remove(struct device *dev)
{
+ ide_drive_t *drive = to_ide_device(dev);
struct cdrom_info *info = drive->driver_data;
- if (ide_unregister_subdriver(drive)) {
- printk(KERN_ERR "%s: %s: failed to ide_unregister_subdriver\n",
- __FUNCTION__, drive->name);
- return 1;
- }
+ ide_unregister_subdriver(drive, info->driver);
del_gendisk(info->disk);
@@ -3297,7 +3305,7 @@ static void ide_cd_release(struct kref *kref)
kfree(info);
}
-static int ide_cdrom_attach (ide_drive_t *drive);
+static int ide_cd_probe(struct device *);
#ifdef CONFIG_PROC_FS
static int proc_idecd_read_capacity
@@ -3320,19 +3328,20 @@ static ide_proc_entry_t idecd_proc[] = {
static ide_driver_t ide_cdrom_driver = {
.owner = THIS_MODULE,
- .name = "ide-cdrom",
+ .gen_driver = {
+ .name = "ide-cdrom",
+ .bus = &ide_bus_type,
+ .probe = ide_cd_probe,
+ .remove = ide_cd_remove,
+ },
.version = IDECD_VERSION,
.media = ide_cdrom,
- .busy = 0,
.supports_dsc_overlap = 1,
- .cleanup = ide_cdrom_cleanup,
.do_request = ide_do_rw_cdrom,
.end_request = ide_end_request,
.error = __ide_error,
.abort = __ide_abort,
.proc = idecd_proc,
- .attach = ide_cdrom_attach,
- .drives = LIST_HEAD_INIT(ide_cdrom_driver.drives),
};
static int idecd_open(struct inode * inode, struct file * file)
@@ -3418,8 +3427,9 @@ static char *ignore = NULL;
module_param(ignore, charp, 0400);
MODULE_DESCRIPTION("ATAPI CD-ROM Driver");
-static int ide_cdrom_attach (ide_drive_t *drive)
+static int ide_cd_probe(struct device *dev)
{
+ ide_drive_t *drive = to_ide_device(dev);
struct cdrom_info *info;
struct gendisk *g;
struct request_sense sense;
@@ -3453,11 +3463,8 @@ static int ide_cdrom_attach (ide_drive_t *drive)
ide_init_disk(g, drive);
- if (ide_register_subdriver(drive, &ide_cdrom_driver)) {
- printk(KERN_ERR "%s: Failed to register the driver with ide.c\n",
- drive->name);
- goto out_put_disk;
- }
+ ide_register_subdriver(drive, &ide_cdrom_driver);
+
memset(info, 0, sizeof (struct cdrom_info));
kref_init(&info->kref);
@@ -3470,7 +3477,6 @@ static int ide_cdrom_attach (ide_drive_t *drive)
drive->driver_data = info;
- DRIVER(drive)->busy++;
g->minors = 1;
snprintf(g->devfs_name, sizeof(g->devfs_name),
"%s/cd", drive->devfs_name);
@@ -3478,8 +3484,7 @@ static int ide_cdrom_attach (ide_drive_t *drive)
g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE;
if (ide_cdrom_setup(drive)) {
struct cdrom_device_info *devinfo = &info->devinfo;
- DRIVER(drive)->busy--;
- ide_unregister_subdriver(drive);
+ ide_unregister_subdriver(drive, &ide_cdrom_driver);
if (info->buffer != NULL)
kfree(info->buffer);
if (info->toc != NULL)
@@ -3492,7 +3497,6 @@ static int ide_cdrom_attach (ide_drive_t *drive)
drive->driver_data = NULL;
goto failed;
}
- DRIVER(drive)->busy--;
cdrom_read_toc(drive, &sense);
g->fops = &idecd_ops;
@@ -3500,23 +3504,20 @@ static int ide_cdrom_attach (ide_drive_t *drive)
add_disk(g);
return 0;
-out_put_disk:
- put_disk(g);
out_free_cd:
kfree(info);
failed:
- return 1;
+ return -ENODEV;
}
static void __exit ide_cdrom_exit(void)
{
- ide_unregister_driver(&ide_cdrom_driver);
+ driver_unregister(&ide_cdrom_driver.gen_driver);
}
static int ide_cdrom_init(void)
{
- ide_register_driver(&ide_cdrom_driver);
- return 0;
+ return driver_register(&ide_cdrom_driver.gen_driver);
}
module_init(ide_cdrom_init);
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 5d54f775610..d6f934886b0 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -1024,14 +1024,16 @@ static void ide_cacheflush_p(ide_drive_t *drive)
printk(KERN_INFO "%s: wcache flush failed!\n", drive->name);
}
-static int idedisk_cleanup (ide_drive_t *drive)
+static int ide_disk_remove(struct device *dev)
{
+ ide_drive_t *drive = to_ide_device(dev);
struct ide_disk_obj *idkp = drive->driver_data;
struct gendisk *g = idkp->disk;
ide_cacheflush_p(drive);
- if (ide_unregister_subdriver(drive))
- return 1;
+
+ ide_unregister_subdriver(drive, idkp->driver);
+
del_gendisk(g);
ide_disk_put(idkp);
@@ -1052,7 +1054,7 @@ static void ide_disk_release(struct kref *kref)
kfree(idkp);
}
-static int idedisk_attach(ide_drive_t *drive);
+static int ide_disk_probe(struct device *dev);
static void ide_device_shutdown(struct device *dev)
{
@@ -1082,27 +1084,23 @@ static void ide_device_shutdown(struct device *dev)
dev->bus->suspend(dev, PMSG_SUSPEND);
}
-/*
- * IDE subdriver functions, registered with ide.c
- */
static ide_driver_t idedisk_driver = {
.owner = THIS_MODULE,
.gen_driver = {
+ .name = "ide-disk",
+ .bus = &ide_bus_type,
+ .probe = ide_disk_probe,
+ .remove = ide_disk_remove,
.shutdown = ide_device_shutdown,
},
- .name = "ide-disk",
.version = IDEDISK_VERSION,
.media = ide_disk,
- .busy = 0,
.supports_dsc_overlap = 0,
- .cleanup = idedisk_cleanup,
.do_request = ide_do_rw_disk,
.end_request = ide_end_request,
.error = __ide_error,
.abort = __ide_abort,
.proc = idedisk_proc,
- .attach = idedisk_attach,
- .drives = LIST_HEAD_INIT(idedisk_driver.drives),
};
static int idedisk_open(struct inode *inode, struct file *filp)
@@ -1199,8 +1197,9 @@ static struct block_device_operations idedisk_ops = {
MODULE_DESCRIPTION("ATA DISK Driver");
-static int idedisk_attach(ide_drive_t *drive)
+static int ide_disk_probe(struct device *dev)
{
+ ide_drive_t *drive = to_ide_device(dev);
struct ide_disk_obj *idkp;
struct gendisk *g;
@@ -1216,16 +1215,14 @@ static int idedisk_attach(ide_drive_t *drive)
if (!idkp)
goto failed;
- g = alloc_disk(1 << PARTN_BITS);
+ g = alloc_disk_node(1 << PARTN_BITS,
+ pcibus_to_node(drive->hwif->pci_dev->bus));
if (!g)
goto out_free_idkp;
ide_init_disk(g, drive);
- if (ide_register_subdriver(drive, &idedisk_driver)) {
- printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name);
- goto out_put_disk;
- }
+ ide_register_subdriver(drive, &idedisk_driver);
memset(idkp, 0, sizeof(*idkp));
@@ -1239,7 +1236,6 @@ static int idedisk_attach(ide_drive_t *drive)
drive->driver_data = idkp;
- DRIVER(drive)->busy++;
idedisk_setup(drive);
if ((!drive->head || drive->head > 16) && !drive->select.b.lba) {
printk(KERN_ERR "%s: INVALID GEOMETRY: %d PHYSICAL HEADS?\n",
@@ -1247,7 +1243,7 @@ static int idedisk_attach(ide_drive_t *drive)
drive->attach = 0;
} else
drive->attach = 1;
- DRIVER(drive)->busy--;
+
g->minors = 1 << PARTN_BITS;
strcpy(g->devfs_name, drive->devfs_name);
g->driverfs_dev = &drive->gendev;
@@ -1257,22 +1253,20 @@ static int idedisk_attach(ide_drive_t *drive)
add_disk(g);
return 0;
-out_put_disk:
- put_disk(g);
out_free_idkp:
kfree(idkp);
failed:
- return 1;
+ return -ENODEV;
}
static void __exit idedisk_exit (void)
{
- ide_unregister_driver(&idedisk_driver);
+ driver_unregister(&idedisk_driver.gen_driver);
}
static int idedisk_init (void)
{
- return ide_register_driver(&idedisk_driver);
+ return driver_register(&idedisk_driver.gen_driver);
}
module_init(idedisk_init);
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index 36c0b74a4e4..9eab6426148 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -661,10 +661,12 @@ static void idefloppy_output_buffers (ide_drive_t *drive, idefloppy_pc_t *pc, un
idefloppy_do_end_request(drive, 1, done >> 9);
+#if IDEFLOPPY_DEBUG_BUGS
if (bcount) {
printk(KERN_ERR "%s: leftover data in idefloppy_output_buffers, bcount == %d\n", drive->name, bcount);
idefloppy_write_zeros(drive, bcount);
}
+#endif
}
static void idefloppy_update_buffers (ide_drive_t *drive, idefloppy_pc_t *pc)
@@ -1048,6 +1050,9 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p
atapi_bcount_t bcount;
ide_handler_t *pkt_xfer_routine;
+#if 0 /* Accessing floppy->pc is not valid here, the previous pc may be gone
+ and have lived on another thread's stack; that stack may have become
+ unmapped meanwhile (CONFIG_DEBUG_PAGEALLOC). */
#if IDEFLOPPY_DEBUG_BUGS
if (floppy->pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD &&
pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) {
@@ -1055,6 +1060,7 @@ static ide_startstop_t idefloppy_issue_pc (ide_drive_t *drive, idefloppy_pc_t *p
"Two request sense in serial were issued\n");
}
#endif /* IDEFLOPPY_DEBUG_BUGS */
+#endif
if (floppy->failed_pc == NULL &&
pc->c[0] != IDEFLOPPY_REQUEST_SENSE_CMD)
@@ -1865,13 +1871,13 @@ static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy)
idefloppy_add_settings(drive);
}
-static int idefloppy_cleanup (ide_drive_t *drive)
+static int ide_floppy_remove(struct device *dev)
{
+ ide_drive_t *drive = to_ide_device(dev);
idefloppy_floppy_t *floppy = drive->driver_data;
struct gendisk *g = floppy->disk;
- if (ide_unregister_subdriver(drive))
- return 1;
+ ide_unregister_subdriver(drive, floppy->driver);
del_gendisk(g);
@@ -1916,26 +1922,24 @@ static ide_proc_entry_t idefloppy_proc[] = {
#endif /* CONFIG_PROC_FS */
-static int idefloppy_attach(ide_drive_t *drive);
+static int ide_floppy_probe(struct device *);
-/*
- * IDE subdriver functions, registered with ide.c
- */
static ide_driver_t idefloppy_driver = {
.owner = THIS_MODULE,
- .name = "ide-floppy",
+ .gen_driver = {
+ .name = "ide-floppy",
+ .bus = &ide_bus_type,
+ .probe = ide_floppy_probe,
+ .remove = ide_floppy_remove,
+ },
.version = IDEFLOPPY_VERSION,
.media = ide_floppy,
- .busy = 0,
.supports_dsc_overlap = 0,
- .cleanup = idefloppy_cleanup,
.do_request = idefloppy_do_request,
.end_request = idefloppy_do_end_request,
.error = __ide_error,
.abort = __ide_abort,
.proc = idefloppy_proc,
- .attach = idefloppy_attach,
- .drives = LIST_HEAD_INIT(idefloppy_driver.drives),
};
static int idefloppy_open(struct inode *inode, struct file *filp)
@@ -2122,8 +2126,9 @@ static struct block_device_operations idefloppy_ops = {
.revalidate_disk= idefloppy_revalidate_disk
};
-static int idefloppy_attach (ide_drive_t *drive)
+static int ide_floppy_probe(struct device *dev)
{
+ ide_drive_t *drive = to_ide_device(dev);
idefloppy_floppy_t *floppy;
struct gendisk *g;
@@ -2152,10 +2157,7 @@ static int idefloppy_attach (ide_drive_t *drive)
ide_init_disk(g, drive);
- if (ide_register_subdriver(drive, &idefloppy_driver)) {
- printk (KERN_ERR "ide-floppy: %s: Failed to register the driver with ide.c\n", drive->name);
- goto out_put_disk;
- }
+ ide_register_subdriver(drive, &idefloppy_driver);
memset(floppy, 0, sizeof(*floppy));
@@ -2169,9 +2171,8 @@ static int idefloppy_attach (ide_drive_t *drive)
drive->driver_data = floppy;
- DRIVER(drive)->busy++;
idefloppy_setup (drive, floppy);
- DRIVER(drive)->busy--;
+
g->minors = 1 << PARTN_BITS;
g->driverfs_dev = &drive->gendev;
strcpy(g->devfs_name, drive->devfs_name);
@@ -2181,19 +2182,17 @@ static int idefloppy_attach (ide_drive_t *drive)
add_disk(g);
return 0;
-out_put_disk:
- put_disk(g);
out_free_floppy:
kfree(floppy);
failed:
- return 1;
+ return -ENODEV;
}
MODULE_DESCRIPTION("ATAPI FLOPPY Driver");
static void __exit idefloppy_exit (void)
{
- ide_unregister_driver(&idefloppy_driver);
+ driver_unregister(&idefloppy_driver.gen_driver);
}
/*
@@ -2202,8 +2201,7 @@ static void __exit idefloppy_exit (void)
static int idefloppy_init (void)
{
printk("ide-floppy driver " IDEFLOPPY_VERSION "\n");
- ide_register_driver(&idefloppy_driver);
- return 0;
+ return driver_register(&idefloppy_driver.gen_driver);
}
module_init(idefloppy_init);
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 554473a95cf..7df85af7537 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -47,6 +47,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/ide.h>
+#include <linux/devfs_fs_kernel.h>
#include <linux/spinlock.h>
#include <linux/kmod.h>
#include <linux/pci.h>
@@ -696,13 +697,13 @@ static int wait_hwif_ready(ide_hwif_t *hwif)
SELECT_DRIVE(&hwif->drives[0]);
hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
mdelay(2);
- rc = ide_wait_not_busy(hwif, 10000);
+ rc = ide_wait_not_busy(hwif, 35000);
if (rc)
return rc;
SELECT_DRIVE(&hwif->drives[1]);
hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]);
mdelay(2);
- rc = ide_wait_not_busy(hwif, 10000);
+ rc = ide_wait_not_busy(hwif, 35000);
/* Exit function with master reselected (let's be sane) */
SELECT_DRIVE(&hwif->drives[0]);
@@ -918,7 +919,7 @@ int probe_hwif_init_with_fixup(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif)
want them on default or a new "empty" class
for hotplug reprobing ? */
if (drive->present) {
- ata_attach(drive);
+ device_register(&drive->gendev);
}
}
}
@@ -976,8 +977,9 @@ static int ide_init_queue(ide_drive_t *drive)
* limits and LBA48 we could raise it but as yet
* do not.
*/
-
- q = blk_init_queue(do_ide_request, &ide_lock);
+
+ q = blk_init_queue_node(do_ide_request, &ide_lock,
+ pcibus_to_node(drive->hwif->pci_dev->bus));
if (!q)
return 1;
@@ -1094,7 +1096,8 @@ static int init_irq (ide_hwif_t *hwif)
hwgroup->hwif->next = hwif;
spin_unlock_irq(&ide_lock);
} else {
- hwgroup = kmalloc(sizeof(ide_hwgroup_t),GFP_KERNEL);
+ hwgroup = kmalloc_node(sizeof(ide_hwgroup_t), GFP_KERNEL,
+ pcibus_to_node(hwif->drives[0].hwif->pci_dev->bus));
if (!hwgroup)
goto out_up;
@@ -1279,10 +1282,51 @@ void ide_init_disk(struct gendisk *disk, ide_drive_t *drive)
EXPORT_SYMBOL_GPL(ide_init_disk);
+static void ide_remove_drive_from_hwgroup(ide_drive_t *drive)
+{
+ ide_hwgroup_t *hwgroup = drive->hwif->hwgroup;
+
+ if (drive == drive->next) {
+ /* special case: last drive from hwgroup. */
+ BUG_ON(hwgroup->drive != drive);
+ hwgroup->drive = NULL;
+ } else {
+ ide_drive_t *walk;
+
+ walk = hwgroup->drive;
+ while (walk->next != drive)
+ walk = walk->next;
+ walk->next = drive->next;
+ if (hwgroup->drive == drive) {
+ hwgroup->drive = drive->next;
+ hwgroup->hwif = hwgroup->drive->hwif;
+ }
+ }
+ BUG_ON(hwgroup->drive == drive);
+}
+
static void drive_release_dev (struct device *dev)
{
ide_drive_t *drive = container_of(dev, ide_drive_t, gendev);
+ spin_lock_irq(&ide_lock);
+ if (drive->devfs_name[0] != '\0') {
+ devfs_remove(drive->devfs_name);
+ drive->devfs_name[0] = '\0';
+ }
+ ide_remove_drive_from_hwgroup(drive);
+ if (drive->id != NULL) {
+ kfree(drive->id);
+ drive->id = NULL;
+ }
+ drive->present = 0;
+ /* Messed up locking ... */
+ spin_unlock_irq(&ide_lock);
+ blk_cleanup_queue(drive->queue);
+ spin_lock_irq(&ide_lock);
+ drive->queue = NULL;
+ spin_unlock_irq(&ide_lock);
+
up(&drive->gendev_rel_sem);
}
@@ -1306,7 +1350,6 @@ static void init_gendisk (ide_hwif_t *hwif)
drive->gendev.driver_data = drive;
drive->gendev.release = drive_release_dev;
if (drive->present) {
- device_register(&drive->gendev);
sprintf(drive->devfs_name, "ide/host%d/bus%d/target%d/lun%d",
(hwif->channel && hwif->mate) ?
hwif->mate->index : hwif->index,
@@ -1412,7 +1455,7 @@ int ideprobe_init (void)
hwif->chipset = ide_generic;
for (unit = 0; unit < MAX_DRIVES; ++unit)
if (hwif->drives[unit].present)
- ata_attach(&hwif->drives[unit]);
+ device_register(&hwif->drives[unit].gendev);
}
}
return 0;
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index bdff5ac5805..4063d2c34e3 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -307,17 +307,41 @@ static int proc_ide_read_driver
(char *page, char **start, off_t off, int count, int *eof, void *data)
{
ide_drive_t *drive = (ide_drive_t *) data;
- ide_driver_t *driver = drive->driver;
+ struct device *dev = &drive->gendev;
+ ide_driver_t *ide_drv;
int len;
- if (driver) {
+ down_read(&dev->bus->subsys.rwsem);
+ if (dev->driver) {
+ ide_drv = container_of(dev->driver, ide_driver_t, gen_driver);
len = sprintf(page, "%s version %s\n",
- driver->name, driver->version);
+ dev->driver->name, ide_drv->version);
} else
len = sprintf(page, "ide-default version 0.9.newide\n");
+ up_read(&dev->bus->subsys.rwsem);
PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
}
+static int ide_replace_subdriver(ide_drive_t *drive, const char *driver)
+{
+ struct device *dev = &drive->gendev;
+ int ret = 1;
+
+ down_write(&dev->bus->subsys.rwsem);
+ device_release_driver(dev);
+ /* FIXME: device can still be in use by previous driver */
+ strlcpy(drive->driver_req, driver, sizeof(drive->driver_req));
+ device_attach(dev);
+ drive->driver_req[0] = 0;
+ if (dev->driver == NULL)
+ device_attach(dev);
+ if (dev->driver && !strcmp(dev->driver->name, driver))
+ ret = 0;
+ up_write(&dev->bus->subsys.rwsem);
+
+ return ret;
+}
+
static int proc_ide_write_driver
(struct file *file, const char __user *buffer, unsigned long count, void *data)
{
@@ -488,16 +512,32 @@ void destroy_proc_ide_interface(ide_hwif_t *hwif)
}
}
-extern struct seq_operations ide_drivers_op;
+static int proc_print_driver(struct device_driver *drv, void *data)
+{
+ ide_driver_t *ide_drv = container_of(drv, ide_driver_t, gen_driver);
+ struct seq_file *s = data;
+
+ seq_printf(s, "%s version %s\n", drv->name, ide_drv->version);
+
+ return 0;
+}
+
+static int ide_drivers_show(struct seq_file *s, void *p)
+{
+ bus_for_each_drv(&ide_bus_type, NULL, s, proc_print_driver);
+ return 0;
+}
+
static int ide_drivers_open(struct inode *inode, struct file *file)
{
- return seq_open(file, &ide_drivers_op);
+ return single_open(file, &ide_drivers_show, NULL);
}
+
static struct file_operations ide_drivers_operations = {
.open = ide_drivers_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = seq_release,
+ .release = single_release,
};
void proc_ide_create(void)
@@ -516,6 +556,6 @@ void proc_ide_create(void)
void proc_ide_destroy(void)
{
- remove_proc_entry("ide/drivers", proc_ide_root);
+ remove_proc_entry("drivers", proc_ide_root);
remove_proc_entry("ide", NULL);
}
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 48254485498..5a3dc46008e 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -4681,21 +4681,12 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor)
idetape_add_settings(drive);
}
-static int idetape_cleanup (ide_drive_t *drive)
+static int ide_tape_remove(struct device *dev)
{
+ ide_drive_t *drive = to_ide_device(dev);
idetape_tape_t *tape = drive->driver_data;
- unsigned long flags;
-
- spin_lock_irqsave(&ide_lock, flags);
- if (test_bit(IDETAPE_BUSY, &tape->flags) || drive->usage ||
- tape->first_stage != NULL || tape->merge_stage_size) {
- spin_unlock_irqrestore(&ide_lock, flags);
- return 1;
- }
- spin_unlock_irqrestore(&ide_lock, flags);
- DRIVER(drive)->busy = 0;
- (void) ide_unregister_subdriver(drive);
+ ide_unregister_subdriver(drive, tape->driver);
ide_unregister_region(tape->disk);
@@ -4710,6 +4701,8 @@ static void ide_tape_release(struct kref *kref)
ide_drive_t *drive = tape->drive;
struct gendisk *g = tape->disk;
+ BUG_ON(tape->first_stage != NULL || tape->merge_stage_size);
+
drive->dsc_overlap = 0;
drive->driver_data = NULL;
devfs_remove("%s/mt", drive->devfs_name);
@@ -4747,26 +4740,24 @@ static ide_proc_entry_t idetape_proc[] = {
#endif
-static int idetape_attach(ide_drive_t *drive);
+static int ide_tape_probe(struct device *);
-/*
- * IDE subdriver functions, registered with ide.c
- */
static ide_driver_t idetape_driver = {
.owner = THIS_MODULE,
- .name = "ide-tape",
+ .gen_driver = {
+ .name = "ide-tape",
+ .bus = &ide_bus_type,
+ .probe = ide_tape_probe,
+ .remove = ide_tape_remove,
+ },
.version = IDETAPE_VERSION,
.media = ide_tape,
- .busy = 1,
.supports_dsc_overlap = 1,
- .cleanup = idetape_cleanup,
.do_request = idetape_do_request,
.end_request = idetape_end_request,
.error = __ide_error,
.abort = __ide_abort,
.proc = idetape_proc,
- .attach = idetape_attach,
- .drives = LIST_HEAD_INIT(idetape_driver.drives),
};
/*
@@ -4829,8 +4820,9 @@ static struct block_device_operations idetape_block_ops = {
.ioctl = idetape_ioctl,
};
-static int idetape_attach (ide_drive_t *drive)
+static int ide_tape_probe(struct device *dev)
{
+ ide_drive_t *drive = to_ide_device(dev);
idetape_tape_t *tape;
struct gendisk *g;
int minor;
@@ -4865,10 +4857,7 @@ static int idetape_attach (ide_drive_t *drive)
ide_init_disk(g, drive);
- if (ide_register_subdriver(drive, &idetape_driver)) {
- printk(KERN_ERR "ide-tape: %s: Failed to register the driver with ide.c\n", drive->name);
- goto out_put_disk;
- }
+ ide_register_subdriver(drive, &idetape_driver);
memset(tape, 0, sizeof(*tape));
@@ -4902,12 +4891,11 @@ static int idetape_attach (ide_drive_t *drive)
ide_register_region(g);
return 0;
-out_put_disk:
- put_disk(g);
+
out_free_tape:
kfree(tape);
failed:
- return 1;
+ return -ENODEV;
}
MODULE_DESCRIPTION("ATAPI Streaming TAPE Driver");
@@ -4915,7 +4903,7 @@ MODULE_LICENSE("GPL");
static void __exit idetape_exit (void)
{
- ide_unregister_driver(&idetape_driver);
+ driver_unregister(&idetape_driver.gen_driver);
unregister_chrdev(IDETAPE_MAJOR, "ht");
}
@@ -4928,8 +4916,7 @@ static int idetape_init (void)
printk(KERN_ERR "ide-tape: Failed to register character device interface\n");
return -EBUSY;
}
- ide_register_driver(&idetape_driver);
- return 0;
+ return driver_register(&idetape_driver.gen_driver);
}
module_init(idetape_init);
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 973dec799b5..dae1bd5b8c3 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -196,8 +196,6 @@ ide_hwif_t ide_hwifs[MAX_HWIFS]; /* master data repository */
EXPORT_SYMBOL(ide_hwifs);
-static struct list_head ide_drives = LIST_HEAD_INIT(ide_drives);
-
/*
* Do not even *think* about calling this!
*/
@@ -358,54 +356,6 @@ static int ide_system_bus_speed(void)
return system_bus_speed;
}
-/*
- * drives_lock protects the list of drives, drivers_lock the
- * list of drivers. Currently nobody takes both at once.
- */
-
-static DEFINE_SPINLOCK(drives_lock);
-static DEFINE_SPINLOCK(drivers_lock);
-static LIST_HEAD(drivers);
-
-/* Iterator for the driver list. */
-
-static void *m_start(struct seq_file *m, loff_t *pos)
-{
- struct list_head *p;
- loff_t l = *pos;
- spin_lock(&drivers_lock);
- list_for_each(p, &drivers)
- if (!l--)
- return list_entry(p, ide_driver_t, drivers);
- return NULL;
-}
-
-static void *m_next(struct seq_file *m, void *v, loff_t *pos)
-{
- struct list_head *p = ((ide_driver_t *)v)->drivers.next;
- (*pos)++;
- return p==&drivers ? NULL : list_entry(p, ide_driver_t, drivers);
-}
-
-static void m_stop(struct seq_file *m, void *v)
-{
- spin_unlock(&drivers_lock);
-}
-
-static int show_driver(struct seq_file *m, void *v)
-{
- ide_driver_t *driver = v;
- seq_printf(m, "%s version %s\n", driver->name, driver->version);
- return 0;
-}
-
-struct seq_operations ide_drivers_op = {
- .start = m_start,
- .next = m_next,
- .stop = m_stop,
- .show = show_driver
-};
-
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_ide_root;
#endif
@@ -630,7 +580,7 @@ void ide_unregister(unsigned int index)
ide_hwif_t *hwif, *g;
static ide_hwif_t tmp_hwif; /* protected by ide_cfg_sem */
ide_hwgroup_t *hwgroup;
- int irq_count = 0, unit, i;
+ int irq_count = 0, unit;
BUG_ON(index >= MAX_HWIFS);
@@ -643,23 +593,22 @@ void ide_unregister(unsigned int index)
goto abort;
for (unit = 0; unit < MAX_DRIVES; ++unit) {
drive = &hwif->drives[unit];
- if (!drive->present)
+ if (!drive->present) {
+ if (drive->devfs_name[0] != '\0') {
+ devfs_remove(drive->devfs_name);
+ drive->devfs_name[0] = '\0';
+ }
continue;
- if (drive->usage || DRIVER(drive)->busy)
- goto abort;
- drive->dead = 1;
+ }
+ spin_unlock_irq(&ide_lock);
+ device_unregister(&drive->gendev);
+ down(&drive->gendev_rel_sem);
+ spin_lock_irq(&ide_lock);
}
hwif->present = 0;
spin_unlock_irq(&ide_lock);
- for (unit = 0; unit < MAX_DRIVES; ++unit) {
- drive = &hwif->drives[unit];
- if (!drive->present)
- continue;
- DRIVER(drive)->cleanup(drive);
- }
-
destroy_proc_ide_interface(hwif);
hwgroup = hwif->hwgroup;
@@ -687,44 +636,6 @@ void ide_unregister(unsigned int index)
* Remove us from the hwgroup, and free
* the hwgroup if we were the only member
*/
- for (i = 0; i < MAX_DRIVES; ++i) {
- drive = &hwif->drives[i];
- if (drive->devfs_name[0] != '\0') {
- devfs_remove(drive->devfs_name);
- drive->devfs_name[0] = '\0';
- }
- if (!drive->present)
- continue;
- if (drive == drive->next) {
- /* special case: last drive from hwgroup. */
- BUG_ON(hwgroup->drive != drive);
- hwgroup->drive = NULL;
- } else {
- ide_drive_t *walk;
-
- walk = hwgroup->drive;
- while (walk->next != drive)
- walk = walk->next;
- walk->next = drive->next;
- if (hwgroup->drive == drive) {
- hwgroup->drive = drive->next;
- hwgroup->hwif = HWIF(hwgroup->drive);
- }
- }
- BUG_ON(hwgroup->drive == drive);
- if (drive->id != NULL) {
- kfree(drive->id);
- drive->id = NULL;
- }
- drive->present = 0;
- /* Messed up locking ... */
- spin_unlock_irq(&ide_lock);
- blk_cleanup_queue(drive->queue);
- device_unregister(&drive->gendev);
- down(&drive->gendev_rel_sem);
- spin_lock_irq(&ide_lock);
- drive->queue = NULL;
- }
if (hwif->next == hwif) {
BUG_ON(hwgroup->hwif != hwif);
kfree(hwgroup);
@@ -1304,73 +1215,6 @@ int system_bus_clock (void)
EXPORT_SYMBOL(system_bus_clock);
-/*
- * Locking is badly broken here - since way back. That sucker is
- * root-only, but that's not an excuse... The real question is what
- * exclusion rules do we want here.
- */
-int ide_replace_subdriver (ide_drive_t *drive, const char *driver)
-{
- if (!drive->present || drive->usage || drive->dead)
- goto abort;
- if (DRIVER(drive)->cleanup(drive))
- goto abort;
- strlcpy(drive->driver_req, driver, sizeof(drive->driver_req));
- if (ata_attach(drive)) {
- spin_lock(&drives_lock);
- list_del_init(&drive->list);
- spin_unlock(&drives_lock);
- drive->driver_req[0] = 0;
- ata_attach(drive);
- } else {
- drive->driver_req[0] = 0;
- }
- if (drive->driver && !strcmp(drive->driver->name, driver))
- return 0;
-abort:
- return 1;
-}
-
-/**
- * ata_attach - attach an ATA/ATAPI device
- * @drive: drive to attach
- *
- * Takes a drive that is as yet not assigned to any midlayer IDE
- * driver (or is assigned to the default driver) and figures out
- * which driver would like to own it. If nobody claims the drive
- * then it is automatically attached to the default driver used for
- * unclaimed objects.
- *
- * A return of zero indicates attachment to a driver, of one
- * attachment to the default driver.
- *
- * Takes drivers_lock.
- */
-
-int ata_attach(ide_drive_t *drive)
-{
- struct list_head *p;
- spin_lock(&drivers_lock);
- list_for_each(p, &drivers) {
- ide_driver_t *driver = list_entry(p, ide_driver_t, drivers);
- if (!try_module_get(driver->owner))
- continue;
- spin_unlock(&drivers_lock);
- if (driver->attach(drive) == 0) {
- module_put(driver->owner);
- drive->gendev.driver = &driver->gen_driver;
- return 0;
- }
- spin_lock(&drivers_lock);
- module_put(driver->owner);
- }
- drive->gendev.driver = NULL;
- spin_unlock(&drivers_lock);
- if (ide_register_subdriver(drive, NULL))
- panic("ide: default attach failed");
- return 1;
-}
-
static int generic_ide_suspend(struct device *dev, pm_message_t state)
{
ide_drive_t *drive = dev->driver_data;
@@ -2013,27 +1857,11 @@ static void __init probe_for_hwifs (void)
#endif
}
-int ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver)
+void ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver)
{
- unsigned long flags;
-
- spin_lock_irqsave(&ide_lock, flags);
- if (!drive->present || drive->driver != NULL ||
- drive->usage || drive->dead) {
- spin_unlock_irqrestore(&ide_lock, flags);
- return 1;
- }
- drive->driver = driver;
- spin_unlock_irqrestore(&ide_lock, flags);
- spin_lock(&drives_lock);
- list_add_tail(&drive->list, driver ? &driver->drives : &ide_drives);
- spin_unlock(&drives_lock);
-// printk(KERN_INFO "%s: attached %s driver.\n", drive->name, driver->name);
#ifdef CONFIG_PROC_FS
- if (driver)
- ide_add_proc_entries(drive->proc, driver->proc, drive);
+ ide_add_proc_entries(drive->proc, driver->proc, drive);
#endif
- return 0;
}
EXPORT_SYMBOL(ide_register_subdriver);
@@ -2041,136 +1869,51 @@ EXPORT_SYMBOL(ide_register_subdriver);
/**
* ide_unregister_subdriver - disconnect drive from driver
* @drive: drive to unplug
+ * @driver: driver
*
* Disconnect a drive from the driver it was attached to and then
* clean up the various proc files and other objects attached to it.
*
- * Takes ide_setting_sem, ide_lock and drives_lock.
+ * Takes ide_setting_sem and ide_lock.
* Caller must hold none of the locks.
- *
- * No locking versus subdriver unload because we are moving to the
- * default driver anyway. Wants double checking.
*/
-int ide_unregister_subdriver (ide_drive_t *drive)
+void ide_unregister_subdriver(ide_drive_t *drive, ide_driver_t *driver)
{
unsigned long flags;
down(&ide_setting_sem);
spin_lock_irqsave(&ide_lock, flags);
- if (drive->usage || drive->driver == NULL || DRIVER(drive)->busy) {
- spin_unlock_irqrestore(&ide_lock, flags);
- up(&ide_setting_sem);
- return 1;
- }
#ifdef CONFIG_PROC_FS
- ide_remove_proc_entries(drive->proc, DRIVER(drive)->proc);
+ ide_remove_proc_entries(drive->proc, driver->proc);
#endif
auto_remove_settings(drive);
- drive->driver = NULL;
spin_unlock_irqrestore(&ide_lock, flags);
up(&ide_setting_sem);
- spin_lock(&drives_lock);
- list_del_init(&drive->list);
- spin_unlock(&drives_lock);
- /* drive will be added to &ide_drives in ata_attach() */
- return 0;
}
EXPORT_SYMBOL(ide_unregister_subdriver);
-static int ide_drive_remove(struct device * dev)
-{
- ide_drive_t * drive = container_of(dev,ide_drive_t,gendev);
- DRIVER(drive)->cleanup(drive);
- return 0;
-}
-
-/**
- * ide_register_driver - register IDE device driver
- * @driver: the IDE device driver
- *
- * Register a new device driver and then scan the devices
- * on the IDE bus in case any should be attached to the
- * driver we have just registered. If so attach them.
- *
- * Takes drivers_lock and drives_lock.
- */
-
-int ide_register_driver(ide_driver_t *driver)
-{
- struct list_head list;
- struct list_head *list_loop;
- struct list_head *tmp_storage;
-
- spin_lock(&drivers_lock);
- list_add(&driver->drivers, &drivers);
- spin_unlock(&drivers_lock);
-
- INIT_LIST_HEAD(&list);
- spin_lock(&drives_lock);
- list_splice_init(&ide_drives, &list);
- spin_unlock(&drives_lock);
-
- list_for_each_safe(list_loop, tmp_storage, &list) {
- ide_drive_t *drive = container_of(list_loop, ide_drive_t, list);
- list_del_init(&drive->list);
- if (drive->present)
- ata_attach(drive);
- }
- driver->gen_driver.name = (char *) driver->name;
- driver->gen_driver.bus = &ide_bus_type;
- driver->gen_driver.remove = ide_drive_remove;
- return driver_register(&driver->gen_driver);
-}
-
-EXPORT_SYMBOL(ide_register_driver);
-
-/**
- * ide_unregister_driver - unregister IDE device driver
- * @driver: the IDE device driver
- *
- * Called when a driver module is being unloaded. We reattach any
- * devices to whatever driver claims them next (typically the default
- * driver).
- *
- * Takes drivers_lock and called functions will take ide_setting_sem.
- */
-
-void ide_unregister_driver(ide_driver_t *driver)
-{
- ide_drive_t *drive;
-
- spin_lock(&drivers_lock);
- list_del(&driver->drivers);
- spin_unlock(&drivers_lock);
-
- driver_unregister(&driver->gen_driver);
-
- while(!list_empty(&driver->drives)) {
- drive = list_entry(driver->drives.next, ide_drive_t, list);
- if (driver->cleanup(drive)) {
- printk(KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name);
- BUG();
- }
- ata_attach(drive);
- }
-}
-
-EXPORT_SYMBOL(ide_unregister_driver);
-
/*
* Probe module
*/
EXPORT_SYMBOL(ide_lock);
+static int ide_bus_match(struct device *dev, struct device_driver *drv)
+{
+ return 1;
+}
+
struct bus_type ide_bus_type = {
.name = "ide",
+ .match = ide_bus_match,
.suspend = generic_ide_suspend,
.resume = generic_ide_resume,
};
+EXPORT_SYMBOL_GPL(ide_bus_type);
+
/*
* This is gets invoked once during initialization, to set *everything* up
*/
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
index 47225e32435..4e0f13d1d06 100644
--- a/drivers/ide/pci/amd74xx.c
+++ b/drivers/ide/pci/amd74xx.c
@@ -72,6 +72,7 @@ static struct amd_ide_chip {
{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, 0x50, AMD_UDMA_133 },
{ PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, 0x50, AMD_UDMA_133 },
{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, 0x50, AMD_UDMA_133 },
+ { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, 0x50, AMD_UDMA_133 },
{ 0 }
};
@@ -487,6 +488,7 @@ static ide_pci_device_t amd74xx_chipsets[] __devinitdata = {
/* 12 */ DECLARE_NV_DEV("NFORCE3-250-SATA2"),
/* 13 */ DECLARE_NV_DEV("NFORCE-CK804"),
/* 14 */ DECLARE_NV_DEV("NFORCE-MCP04"),
+ /* 15 */ DECLARE_NV_DEV("NFORCE-MCP51"),
};
static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
@@ -521,6 +523,7 @@ static struct pci_device_id amd74xx_pci_tbl[] = {
#endif
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 },
+ { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl);
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index 4651a22bf12..af526b671c4 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -34,7 +34,7 @@
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/blkdev.h>
-#include <linux/ioc4_common.h>
+#include <linux/ioc4.h>
#include <asm/io.h>
#include <linux/ide.h>
@@ -715,14 +715,34 @@ static ide_pci_device_t sgiioc4_chipsets[] __devinitdata = {
};
int
-ioc4_ide_attach_one(struct pci_dev *dev, const struct pci_device_id *id)
+ioc4_ide_attach_one(struct ioc4_driver_data *idd)
{
- return pci_init_sgiioc4(dev, &sgiioc4_chipsets[id->driver_data]);
+ return pci_init_sgiioc4(idd->idd_pdev,
+ &sgiioc4_chipsets[idd->idd_pci_id->driver_data]);
}
+static struct ioc4_submodule ioc4_ide_submodule = {
+ .is_name = "IOC4_ide",
+ .is_owner = THIS_MODULE,
+ .is_probe = ioc4_ide_attach_one,
+/* .is_remove = ioc4_ide_remove_one, */
+};
+
+static int __devinit
+ioc4_ide_init(void)
+{
+ return ioc4_register_submodule(&ioc4_ide_submodule);
+}
+
+static void __devexit
+ioc4_ide_exit(void)
+{
+ ioc4_unregister_submodule(&ioc4_ide_submodule);
+}
+
+module_init(ioc4_ide_init);
+module_exit(ioc4_ide_exit);
MODULE_AUTHOR("Aniket Malatpure - Silicon Graphics Inc. (SGI)");
MODULE_DESCRIPTION("IDE PCI driver module for SGI IOC4 Base-IO Card");
MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(ioc4_ide_attach_one);
diff --git a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig
index 78b201fb5e8..7d58af1ae30 100644
--- a/drivers/ieee1394/Kconfig
+++ b/drivers/ieee1394/Kconfig
@@ -84,11 +84,6 @@ config IEEE1394_PCILYNX
To compile this driver as a module, say M here: the
module will be called pcilynx.
-# Non-maintained pcilynx options
-# if [ "$CONFIG_IEEE1394_PCILYNX" != "n" ]; then
-# bool ' Use PCILynx local RAM' CONFIG_IEEE1394_PCILYNX_LOCALRAM
-# bool ' Support for non-IEEE1394 local ports' CONFIG_IEEE1394_PCILYNX_PORTS
-# fi
config IEEE1394_OHCI1394
tristate "OHCI-1394 support"
depends on PCI && IEEE1394
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index 68c7a5f0784..4538b0235ca 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -2343,8 +2343,8 @@ static void dv1394_remove_host (struct hpsb_host *host)
dv1394_un_init(video);
} while (video != NULL);
- class_simple_device_remove(MKDEV(
- IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)));
+ class_device_destroy(hpsb_protocol_class,
+ MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)));
devfs_remove("ieee1394/dv/host%d/NTSC", id);
devfs_remove("ieee1394/dv/host%d/PAL", id);
devfs_remove("ieee1394/dv/host%d", id);
@@ -2361,7 +2361,7 @@ static void dv1394_add_host (struct hpsb_host *host)
ohci = (struct ti_ohci *)host->hostdata;
- class_simple_device_add(hpsb_protocol_class, MKDEV(
+ class_device_create(hpsb_protocol_class, MKDEV(
IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
NULL, "dv1394-%d", id);
devfs_mk_dir("ieee1394/dv/host%d", id);
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index 1c5845f7e4a..629070b83a3 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -67,7 +67,7 @@ MODULE_LICENSE("GPL");
/* Some globals used */
const char *hpsb_speedto_str[] = { "S100", "S200", "S400", "S800", "S1600", "S3200" };
-struct class_simple *hpsb_protocol_class;
+struct class *hpsb_protocol_class;
#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
static void dump_packet(const char *text, quadlet_t *data, int size)
@@ -520,7 +520,7 @@ int hpsb_send_packet(struct hpsb_packet *packet)
if (!packet->no_waiter || packet->expect_response) {
atomic_inc(&packet->refcnt);
- packet->sendtime = jiffies;
+ packet->sendtime = jiffies + 10 * HZ;
skb_queue_tail(&host->pending_packet_queue, packet->skb);
}
@@ -1041,10 +1041,8 @@ static int hpsbpkt_thread(void *__hi)
while (1) {
if (down_interruptible(&khpsbpkt_sig)) {
- if (current->flags & PF_FREEZE) {
- refrigerator(0);
+ if (try_to_freeze())
continue;
- }
printk("khpsbpkt: received unexpected signal?!\n" );
break;
}
@@ -1121,7 +1119,7 @@ static int __init ieee1394_init(void)
if (ret < 0)
goto release_all_bus;
- hpsb_protocol_class = class_simple_create(THIS_MODULE, "ieee1394_protocol");
+ hpsb_protocol_class = class_create(THIS_MODULE, "ieee1394_protocol");
if (IS_ERR(hpsb_protocol_class)) {
ret = PTR_ERR(hpsb_protocol_class);
goto release_class_host;
@@ -1159,7 +1157,7 @@ static int __init ieee1394_init(void)
cleanup_csr:
cleanup_csr();
release_class_protocol:
- class_simple_destroy(hpsb_protocol_class);
+ class_destroy(hpsb_protocol_class);
release_class_host:
class_unregister(&hpsb_host_class);
release_all_bus:
@@ -1189,7 +1187,7 @@ static void __exit ieee1394_cleanup(void)
cleanup_csr();
- class_simple_destroy(hpsb_protocol_class);
+ class_destroy(hpsb_protocol_class);
class_unregister(&hpsb_host_class);
for (i = 0; fw_bus_attrs[i]; i++)
bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]);
@@ -1248,7 +1246,6 @@ EXPORT_SYMBOL(hpsb_make_phypacket);
EXPORT_SYMBOL(hpsb_make_isopacket);
EXPORT_SYMBOL(hpsb_read);
EXPORT_SYMBOL(hpsb_write);
-EXPORT_SYMBOL(hpsb_lock);
EXPORT_SYMBOL(hpsb_packet_success);
/** highlevel.c **/
diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
index c4b4408e2e0..73bd8efd2b6 100644
--- a/drivers/ieee1394/ieee1394_core.h
+++ b/drivers/ieee1394/ieee1394_core.h
@@ -223,6 +223,7 @@ extern int hpsb_disable_irm;
/* Our sysfs bus entry */
extern struct bus_type ieee1394_bus_type;
extern struct class hpsb_host_class;
-extern struct class_simple *hpsb_protocol_class;
+extern struct class *hpsb_protocol_class;
#endif /* _IEEE1394_CORE_H */
+
diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c
index 09908b9564d..0aa876360f9 100644
--- a/drivers/ieee1394/ieee1394_transactions.c
+++ b/drivers/ieee1394/ieee1394_transactions.c
@@ -535,6 +535,7 @@ hpsb_write_fail:
return retval;
}
+#if 0
int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, int extcode, quadlet_t *data, quadlet_t arg)
@@ -599,3 +600,5 @@ int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
return retval;
}
+
+#endif /* 0 */
diff --git a/drivers/ieee1394/ieee1394_transactions.h b/drivers/ieee1394/ieee1394_transactions.h
index 526a43ceb49..45ba784fe6d 100644
--- a/drivers/ieee1394/ieee1394_transactions.h
+++ b/drivers/ieee1394/ieee1394_transactions.h
@@ -53,12 +53,5 @@ int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, quadlet_t *buffer, size_t length);
int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
u64 addr, quadlet_t *buffer, size_t length);
-int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
- u64 addr, int extcode, quadlet_t *data, quadlet_t arg);
-int hpsb_lock64(struct hpsb_host *host, nodeid_t node, unsigned int generation,
- u64 addr, int extcode, octlet_t *data, octlet_t arg);
-int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
- quadlet_t *buffer, size_t length, u32 specifier_id,
- unsigned int version);
#endif /* _IEEE1394_TRANSACTIONS_H */
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index a1e30a66297..9a46c3b44bf 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -220,7 +220,7 @@ struct device nodemgr_dev_template_host = {
#define fw_attr(class, class_type, field, type, format_string) \
-static ssize_t fw_show_##class##_##field (struct device *dev, char *buf)\
+static ssize_t fw_show_##class##_##field (struct device *dev, struct device_attribute *attr, char *buf)\
{ \
class_type *class; \
class = container_of(dev, class_type, device); \
@@ -232,7 +232,7 @@ static struct device_attribute dev_attr_##class##_##field = { \
};
#define fw_attr_td(class, class_type, td_kv) \
-static ssize_t fw_show_##class##_##td_kv (struct device *dev, char *buf)\
+static ssize_t fw_show_##class##_##td_kv (struct device *dev, struct device_attribute *attr, char *buf)\
{ \
int len; \
class_type *class = container_of(dev, class_type, device); \
@@ -265,7 +265,7 @@ static struct driver_attribute driver_attr_drv_##field = { \
};
-static ssize_t fw_show_ne_bus_options(struct device *dev, char *buf)
+static ssize_t fw_show_ne_bus_options(struct device *dev, struct device_attribute *attr, char *buf)
{
struct node_entry *ne = container_of(dev, struct node_entry, device);
@@ -281,7 +281,7 @@ static ssize_t fw_show_ne_bus_options(struct device *dev, char *buf)
static DEVICE_ATTR(bus_options,S_IRUGO,fw_show_ne_bus_options,NULL);
-static ssize_t fw_show_ne_tlabels_free(struct device *dev, char *buf)
+static ssize_t fw_show_ne_tlabels_free(struct device *dev, struct device_attribute *attr, char *buf)
{
struct node_entry *ne = container_of(dev, struct node_entry, device);
return sprintf(buf, "%d\n", atomic_read(&ne->tpool->count.count) + 1);
@@ -289,7 +289,7 @@ static ssize_t fw_show_ne_tlabels_free(struct device *dev, char *buf)
static DEVICE_ATTR(tlabels_free,S_IRUGO,fw_show_ne_tlabels_free,NULL);
-static ssize_t fw_show_ne_tlabels_allocations(struct device *dev, char *buf)
+static ssize_t fw_show_ne_tlabels_allocations(struct device *dev, struct device_attribute *attr, char *buf)
{
struct node_entry *ne = container_of(dev, struct node_entry, device);
return sprintf(buf, "%u\n", ne->tpool->allocations);
@@ -297,7 +297,7 @@ static ssize_t fw_show_ne_tlabels_allocations(struct device *dev, char *buf)
static DEVICE_ATTR(tlabels_allocations,S_IRUGO,fw_show_ne_tlabels_allocations,NULL);
-static ssize_t fw_show_ne_tlabels_mask(struct device *dev, char *buf)
+static ssize_t fw_show_ne_tlabels_mask(struct device *dev, struct device_attribute *attr, char *buf)
{
struct node_entry *ne = container_of(dev, struct node_entry, device);
#if (BITS_PER_LONG <= 32)
@@ -309,7 +309,7 @@ static ssize_t fw_show_ne_tlabels_mask(struct device *dev, char *buf)
static DEVICE_ATTR(tlabels_mask, S_IRUGO, fw_show_ne_tlabels_mask, NULL);
-static ssize_t fw_set_ignore_driver(struct device *dev, const char *buf, size_t count)
+static ssize_t fw_set_ignore_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct unit_directory *ud = container_of(dev, struct unit_directory, device);
int state = simple_strtoul(buf, NULL, 10);
@@ -324,7 +324,7 @@ static ssize_t fw_set_ignore_driver(struct device *dev, const char *buf, size_t
return count;
}
-static ssize_t fw_get_ignore_driver(struct device *dev, char *buf)
+static ssize_t fw_get_ignore_driver(struct device *dev, struct device_attribute *attr, char *buf)
{
struct unit_directory *ud = container_of(dev, struct unit_directory, device);
@@ -695,14 +695,15 @@ static void nodemgr_remove_ne(struct node_entry *ne)
put_device(dev);
}
+static int __nodemgr_remove_host_dev(struct device *dev, void *data)
+{
+ nodemgr_remove_ne(container_of(dev, struct node_entry, device));
+ return 0;
+}
static void nodemgr_remove_host_dev(struct device *dev)
{
- struct device *ne_dev, *next;
-
- list_for_each_entry_safe(ne_dev, next, &dev->children, node)
- nodemgr_remove_ne(container_of(ne_dev, struct node_entry, device));
-
+ device_for_each_child(dev, NULL, __nodemgr_remove_host_dev);
sysfs_remove_link(&dev->kobj, "irm_id");
sysfs_remove_link(&dev->kobj, "busmgr_id");
sysfs_remove_link(&dev->kobj, "host_id");
@@ -1005,8 +1006,7 @@ static struct unit_directory *nodemgr_process_unit_directory
return ud;
unit_directory_error:
- if (ud != NULL)
- kfree(ud);
+ kfree(ud);
return NULL;
}
@@ -1510,7 +1510,7 @@ static int nodemgr_host_thread(void *__hi)
if (down_interruptible(&hi->reset_sem) ||
down_interruptible(&nodemgr_serialize)) {
- if (try_to_freeze(PF_FREEZE))
+ if (try_to_freeze())
continue;
printk("NodeMgr: received unexpected signal?!\n" );
break;
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index 6cb0b586c29..36e25ac823d 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -2931,7 +2931,7 @@ static void free_dma_rcv_ctx(struct dma_rcv_ctx *d)
kfree(d->prg_cpu);
kfree(d->prg_bus);
}
- if (d->spb) kfree(d->spb);
+ kfree(d->spb);
/* Mark this context as freed. */
d->ohci = NULL;
diff --git a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h
index d1758d40961..cc66c1cae25 100644
--- a/drivers/ieee1394/ohci1394.h
+++ b/drivers/ieee1394/ohci1394.h
@@ -236,6 +236,9 @@ struct ti_ohci {
static inline int cross_bound(unsigned long addr, unsigned int size)
{
+ if (size == 0)
+ return 0;
+
if (size > PAGE_SIZE)
return 1;
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
index a261d2b0e5a..bdb3a85cafa 100644
--- a/drivers/ieee1394/pcilynx.c
+++ b/drivers/ieee1394/pcilynx.c
@@ -43,6 +43,7 @@
#include <linux/fs.h>
#include <linux/poll.h>
#include <linux/kdev_t.h>
+#include <linux/dma-mapping.h>
#include <asm/byteorder.h>
#include <asm/atomic.h>
#include <asm/io.h>
@@ -834,327 +835,6 @@ static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
* IEEE-1394 functionality section END *
***************************************/
-#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
-/* VFS functions for local bus / aux device access. Access to those
- * is implemented as a character device instead of block devices
- * because buffers are not wanted for this. Therefore llseek (from
- * VFS) can be used for these char devices with obvious effects.
- */
-static int mem_open(struct inode*, struct file*);
-static int mem_release(struct inode*, struct file*);
-static unsigned int aux_poll(struct file*, struct poll_table_struct*);
-static loff_t mem_llseek(struct file*, loff_t, int);
-static ssize_t mem_read (struct file*, char*, size_t, loff_t*);
-static ssize_t mem_write(struct file*, const char*, size_t, loff_t*);
-
-
-static struct file_operations aux_ops = {
- .owner = THIS_MODULE,
- .read = mem_read,
- .write = mem_write,
- .poll = aux_poll,
- .llseek = mem_llseek,
- .open = mem_open,
- .release = mem_release,
-};
-
-
-static void aux_setup_pcls(struct ti_lynx *lynx)
-{
- struct ti_pcl pcl;
-
- pcl.next = PCL_NEXT_INVALID;
- pcl.user_data = pcl_bus(lynx, lynx->dmem_pcl);
- put_pcl(lynx, lynx->dmem_pcl, &pcl);
-}
-
-static int mem_open(struct inode *inode, struct file *file)
-{
- int cid = iminor(inode);
- enum { t_rom, t_aux, t_ram } type;
- struct memdata *md;
-
- if (cid < PCILYNX_MINOR_AUX_START) {
- /* just for completeness */
- return -ENXIO;
- } else if (cid < PCILYNX_MINOR_ROM_START) {
- cid -= PCILYNX_MINOR_AUX_START;
- if (cid >= num_of_cards || !cards[cid].aux_port)
- return -ENXIO;
- type = t_aux;
- } else if (cid < PCILYNX_MINOR_RAM_START) {
- cid -= PCILYNX_MINOR_ROM_START;
- if (cid >= num_of_cards || !cards[cid].local_rom)
- return -ENXIO;
- type = t_rom;
- } else {
- /* WARNING: Know what you are doing when opening RAM.
- * It is currently used inside the driver! */
- cid -= PCILYNX_MINOR_RAM_START;
- if (cid >= num_of_cards || !cards[cid].local_ram)
- return -ENXIO;
- type = t_ram;
- }
-
- md = (struct memdata *)kmalloc(sizeof(struct memdata), SLAB_KERNEL);
- if (md == NULL)
- return -ENOMEM;
-
- md->lynx = &cards[cid];
- md->cid = cid;
-
- switch (type) {
- case t_rom:
- md->type = rom;
- break;
- case t_ram:
- md->type = ram;
- break;
- case t_aux:
- atomic_set(&md->aux_intr_last_seen,
- atomic_read(&cards[cid].aux_intr_seen));
- md->type = aux;
- break;
- }
-
- file->private_data = md;
-
- return 0;
-}
-
-static int mem_release(struct inode *inode, struct file *file)
-{
- kfree(file->private_data);
- return 0;
-}
-
-static unsigned int aux_poll(struct file *file, poll_table *pt)
-{
- struct memdata *md = (struct memdata *)file->private_data;
- int cid = md->cid;
- unsigned int mask;
-
- /* reading and writing is always allowed */
- mask = POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM;
-
- if (md->type == aux) {
- poll_wait(file, &cards[cid].aux_intr_wait, pt);
-
- if (atomic_read(&md->aux_intr_last_seen)
- != atomic_read(&cards[cid].aux_intr_seen)) {
- mask |= POLLPRI;
- atomic_inc(&md->aux_intr_last_seen);
- }
- }
-
- return mask;
-}
-
-loff_t mem_llseek(struct file *file, loff_t offs, int orig)
-{
- loff_t newoffs;
-
- switch (orig) {
- case 0:
- newoffs = offs;
- break;
- case 1:
- newoffs = offs + file->f_pos;
- break;
- case 2:
- newoffs = PCILYNX_MAX_MEMORY + 1 + offs;
- break;
- default:
- return -EINVAL;
- }
-
- if (newoffs < 0 || newoffs > PCILYNX_MAX_MEMORY + 1) return -EINVAL;
-
- file->f_pos = newoffs;
- return newoffs;
-}
-
-/*
- * do not DMA if count is too small because this will have a serious impact
- * on performance - the value 2400 was found by experiment and may not work
- * everywhere as good as here - use mem_mindma option for modules to change
- */
-static short mem_mindma = 2400;
-module_param(mem_mindma, short, 0444);
-MODULE_PARM_DESC(mem_mindma, "Minimum amount of data required to use DMA");
-
-static ssize_t mem_dmaread(struct memdata *md, u32 physbuf, ssize_t count,
- int offset)
-{
- pcltmp_t pcltmp;
- struct ti_pcl *pcl;
- size_t retval;
- int i;
- DECLARE_WAITQUEUE(wait, current);
-
- count &= ~3;
- count = min(count, 53196);
- retval = count;
-
- if (reg_read(md->lynx, DMA_CHAN_CTRL(CHANNEL_LOCALBUS))
- & DMA_CHAN_CTRL_BUSY) {
- PRINT(KERN_WARNING, md->lynx->id, "DMA ALREADY ACTIVE!");
- }
-
- reg_write(md->lynx, LBUS_ADDR, md->type | offset);
-
- pcl = edit_pcl(md->lynx, md->lynx->dmem_pcl, &pcltmp);
- pcl->buffer[0].control = PCL_CMD_LBUS_TO_PCI | min(count, 4092);
- pcl->buffer[0].pointer = physbuf;
- count -= 4092;
-
- i = 0;
- while (count > 0) {
- i++;
- pcl->buffer[i].control = min(count, 4092);
- pcl->buffer[i].pointer = physbuf + i * 4092;
- count -= 4092;
- }
- pcl->buffer[i].control |= PCL_LAST_BUFF;
- commit_pcl(md->lynx, md->lynx->dmem_pcl, &pcltmp);
-
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&md->lynx->mem_dma_intr_wait, &wait);
- run_sub_pcl(md->lynx, md->lynx->dmem_pcl, 2, CHANNEL_LOCALBUS);
-
- schedule();
- while (reg_read(md->lynx, DMA_CHAN_CTRL(CHANNEL_LOCALBUS))
- & DMA_CHAN_CTRL_BUSY) {
- if (signal_pending(current)) {
- retval = -EINTR;
- break;
- }
- schedule();
- }
-
- reg_write(md->lynx, DMA_CHAN_CTRL(CHANNEL_LOCALBUS), 0);
- remove_wait_queue(&md->lynx->mem_dma_intr_wait, &wait);
-
- if (reg_read(md->lynx, DMA_CHAN_CTRL(CHANNEL_LOCALBUS))
- & DMA_CHAN_CTRL_BUSY) {
- PRINT(KERN_ERR, md->lynx->id, "DMA STILL ACTIVE!");
- }
-
- return retval;
-}
-
-static ssize_t mem_read(struct file *file, char *buffer, size_t count,
- loff_t *offset)
-{
- struct memdata *md = (struct memdata *)file->private_data;
- ssize_t bcount;
- size_t alignfix;
- loff_t off = *offset; /* avoid useless 64bit-arithmetic */
- ssize_t retval;
- void *membase;
-
- if ((off + count) > PCILYNX_MAX_MEMORY+1) {
- count = PCILYNX_MAX_MEMORY+1 - off;
- }
- if (count == 0 || off > PCILYNX_MAX_MEMORY) {
- return -ENOSPC;
- }
-
- switch (md->type) {
- case rom:
- membase = md->lynx->local_rom;
- break;
- case ram:
- membase = md->lynx->local_ram;
- break;
- case aux:
- membase = md->lynx->aux_port;
- break;
- default:
- panic("pcilynx%d: unsupported md->type %d in %s",
- md->lynx->id, md->type, __FUNCTION__);
- }
-
- down(&md->lynx->mem_dma_mutex);
-
- if (count < mem_mindma) {
- memcpy_fromio(md->lynx->mem_dma_buffer, membase+off, count);
- goto out;
- }
-
- bcount = count;
- alignfix = 4 - (off % 4);
- if (alignfix != 4) {
- if (bcount < alignfix) {
- alignfix = bcount;
- }
- memcpy_fromio(md->lynx->mem_dma_buffer, membase+off,
- alignfix);
- if (bcount == alignfix) {
- goto out;
- }
- bcount -= alignfix;
- off += alignfix;
- }
-
- while (bcount >= 4) {
- retval = mem_dmaread(md, md->lynx->mem_dma_buffer_dma
- + count - bcount, bcount, off);
- if (retval < 0) return retval;
-
- bcount -= retval;
- off += retval;
- }
-
- if (bcount) {
- memcpy_fromio(md->lynx->mem_dma_buffer + count - bcount,
- membase+off, bcount);
- }
-
- out:
- retval = copy_to_user(buffer, md->lynx->mem_dma_buffer, count);
- up(&md->lynx->mem_dma_mutex);
-
- if (retval) return -EFAULT;
- *offset += count;
- return count;
-}
-
-
-static ssize_t mem_write(struct file *file, const char *buffer, size_t count,
- loff_t *offset)
-{
- struct memdata *md = (struct memdata *)file->private_data;
-
- if (((*offset) + count) > PCILYNX_MAX_MEMORY+1) {
- count = PCILYNX_MAX_MEMORY+1 - *offset;
- }
- if (count == 0 || *offset > PCILYNX_MAX_MEMORY) {
- return -ENOSPC;
- }
-
- /* FIXME: dereferencing pointers to PCI mem doesn't work everywhere */
- switch (md->type) {
- case aux:
- if (copy_from_user(md->lynx->aux_port+(*offset), buffer, count))
- return -EFAULT;
- break;
- case ram:
- if (copy_from_user(md->lynx->local_ram+(*offset), buffer, count))
- return -EFAULT;
- break;
- case rom:
- /* the ROM may be writeable */
- if (copy_from_user(md->lynx->local_rom+(*offset), buffer, count))
- return -EFAULT;
- break;
- }
-
- file->f_pos += count;
- return count;
-}
-#endif /* CONFIG_IEEE1394_PCILYNX_PORTS */
-
/********************************************************
* Global stuff (interrupt handler, init/shutdown code) *
@@ -1181,18 +861,6 @@ static irqreturn_t lynx_irq_handler(int irq, void *dev_id,
reg_write(lynx, LINK_INT_STATUS, linkint);
reg_write(lynx, PCI_INT_STATUS, intmask);
-#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
- if (intmask & PCI_INT_AUX_INT) {
- atomic_inc(&lynx->aux_intr_seen);
- wake_up_interruptible(&lynx->aux_intr_wait);
- }
-
- if (intmask & PCI_INT_DMA_HLT(CHANNEL_LOCALBUS)) {
- wake_up_interruptible(&lynx->mem_dma_intr_wait);
- }
-#endif
-
-
if (intmask & PCI_INT_1394) {
if (linkint & LINK_INT_PHY_TIMEOUT) {
PRINT(KERN_INFO, lynx->id, "PHY timeout occurred");
@@ -1484,15 +1152,9 @@ static void remove_card(struct pci_dev *dev)
pci_free_consistent(lynx->dev, PAGE_SIZE, lynx->rcv_page,
lynx->rcv_page_dma);
case have_aux_buf:
-#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
- pci_free_consistent(lynx->dev, 65536, lynx->mem_dma_buffer,
- lynx->mem_dma_buffer_dma);
-#endif
case have_pcl_mem:
-#ifndef CONFIG_IEEE1394_PCILYNX_LOCALRAM
pci_free_consistent(lynx->dev, LOCALRAM_SIZE, lynx->pcl_mem,
lynx->pcl_mem_dma);
-#endif
case clear:
/* do nothing - already freed */
;
@@ -1524,7 +1186,7 @@ static int __devinit add_card(struct pci_dev *dev,
error = -ENXIO;
- if (pci_set_dma_mask(dev, 0xffffffff))
+ if (pci_set_dma_mask(dev, DMA_32BIT_MASK))
FAIL("DMA address limits not supported for PCILynx hardware");
if (pci_enable_device(dev))
FAIL("failed to enable PCILynx hardware");
@@ -1546,7 +1208,6 @@ static int __devinit add_card(struct pci_dev *dev,
spin_lock_init(&lynx->lock);
spin_lock_init(&lynx->phy_reg_lock);
-#ifndef CONFIG_IEEE1394_PCILYNX_LOCALRAM
lynx->pcl_mem = pci_alloc_consistent(dev, LOCALRAM_SIZE,
&lynx->pcl_mem_dma);
@@ -1558,16 +1219,6 @@ static int __devinit add_card(struct pci_dev *dev,
} else {
FAIL("failed to allocate PCL memory area");
}
-#endif
-
-#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
- lynx->mem_dma_buffer = pci_alloc_consistent(dev, 65536,
- &lynx->mem_dma_buffer_dma);
- if (lynx->mem_dma_buffer == NULL) {
- FAIL("failed to allocate DMA buffer for aux");
- }
- lynx->state = have_aux_buf;
-#endif
lynx->rcv_page = pci_alloc_consistent(dev, PAGE_SIZE,
&lynx->rcv_page_dma);
@@ -1597,13 +1248,6 @@ static int __devinit add_card(struct pci_dev *dev,
FAIL("failed to remap registers - card not accessible");
}
-#ifdef CONFIG_IEEE1394_PCILYNX_LOCALRAM
- if (lynx->local_ram == NULL) {
- FAIL("failed to remap local RAM which is required for "
- "operation");
- }
-#endif
-
reg_set_bits(lynx, MISC_CONTROL, MISC_CONTROL_SWRESET);
/* Fix buggy cards with autoboot pin not tied low: */
reg_write(lynx, DMA0_CHAN_CTRL, 0);
@@ -1624,13 +1268,6 @@ static int __devinit add_card(struct pci_dev *dev,
/* alloc_pcl return values are not checked, it is expected that the
* provided PCL space is sufficient for the initial allocations */
-#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
- if (lynx->aux_port != NULL) {
- lynx->dmem_pcl = alloc_pcl(lynx);
- aux_setup_pcls(lynx);
- sema_init(&lynx->mem_dma_mutex, 1);
- }
-#endif
lynx->rcv_pcl = alloc_pcl(lynx);
lynx->rcv_pcl_start = alloc_pcl(lynx);
lynx->async.pcl = alloc_pcl(lynx);
@@ -1647,12 +1284,6 @@ static int __devinit add_card(struct pci_dev *dev,
reg_write(lynx, PCI_INT_ENABLE, PCI_INT_DMA_ALL);
-#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
- reg_set_bits(lynx, PCI_INT_ENABLE, PCI_INT_AUX_INT);
- init_waitqueue_head(&lynx->mem_dma_intr_wait);
- init_waitqueue_head(&lynx->aux_intr_wait);
-#endif
-
tasklet_init(&lynx->iso_rcv.tq, (void (*)(unsigned long))iso_rcv_bh,
(unsigned long)lynx);
@@ -1944,37 +1575,18 @@ static int __init pcilynx_init(void)
{
int ret;
-#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
- if (register_chrdev(PCILYNX_MAJOR, PCILYNX_DRIVER_NAME, &aux_ops)) {
- PRINT_G(KERN_ERR, "allocation of char major number %d failed",
- PCILYNX_MAJOR);
- return -EBUSY;
- }
-#endif
-
ret = pci_register_driver(&lynx_pci_driver);
if (ret < 0) {
PRINT_G(KERN_ERR, "PCI module init failed");
- goto free_char_dev;
+ return ret;
}
return 0;
-
- free_char_dev:
-#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
- unregister_chrdev(PCILYNX_MAJOR, PCILYNX_DRIVER_NAME);
-#endif
-
- return ret;
}
static void __exit pcilynx_cleanup(void)
{
pci_unregister_driver(&lynx_pci_driver);
-
-#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
- unregister_chrdev(PCILYNX_MAJOR, PCILYNX_DRIVER_NAME);
-#endif
}
diff --git a/drivers/ieee1394/pcilynx.h b/drivers/ieee1394/pcilynx.h
index 644ec55d3d4..d631aa8383a 100644
--- a/drivers/ieee1394/pcilynx.h
+++ b/drivers/ieee1394/pcilynx.h
@@ -55,16 +55,6 @@ struct ti_lynx {
void __iomem *aux_port;
quadlet_t bus_info_block[5];
-#ifdef CONFIG_IEEE1394_PCILYNX_PORTS
- atomic_t aux_intr_seen;
- wait_queue_head_t aux_intr_wait;
-
- void *mem_dma_buffer;
- dma_addr_t mem_dma_buffer_dma;
- struct semaphore mem_dma_mutex;
- wait_queue_head_t mem_dma_intr_wait;
-#endif
-
/*
* use local RAM of LOCALRAM_SIZE bytes for PCLs, which allows for
* LOCALRAM_SIZE * 8 PCLs (each sized 128 bytes);
@@ -72,11 +62,9 @@ struct ti_lynx {
*/
u8 pcl_bmap[LOCALRAM_SIZE / 1024];
-#ifndef CONFIG_IEEE1394_PCILYNX_LOCALRAM
/* point to PCLs memory area if needed */
void *pcl_mem;
dma_addr_t pcl_mem_dma;
-#endif
/* PCLs for local mem / aux transfers */
pcl_t dmem_pcl;
@@ -378,39 +366,6 @@ struct ti_pcl {
#define pcloffs(MEMBER) (offsetof(struct ti_pcl, MEMBER))
-#ifdef CONFIG_IEEE1394_PCILYNX_LOCALRAM
-
-static inline void put_pcl(const struct ti_lynx *lynx, pcl_t pclid,
- const struct ti_pcl *pcl)
-{
- int i;
- u32 *in = (u32 *)pcl;
- u32 *out = (u32 *)(lynx->local_ram + pclid * sizeof(struct ti_pcl));
-
- for (i = 0; i < 32; i++, out++, in++) {
- writel(*in, out);
- }
-}
-
-static inline void get_pcl(const struct ti_lynx *lynx, pcl_t pclid,
- struct ti_pcl *pcl)
-{
- int i;
- u32 *out = (u32 *)pcl;
- u32 *in = (u32 *)(lynx->local_ram + pclid * sizeof(struct ti_pcl));
-
- for (i = 0; i < 32; i++, out++, in++) {
- *out = readl(in);
- }
-}
-
-static inline u32 pcl_bus(const struct ti_lynx *lynx, pcl_t pclid)
-{
- return pci_resource_start(lynx->dev, 1) + pclid * sizeof(struct ti_pcl);
-}
-
-#else /* CONFIG_IEEE1394_PCILYNX_LOCALRAM */
-
static inline void put_pcl(const struct ti_lynx *lynx, pcl_t pclid,
const struct ti_pcl *pcl)
{
@@ -431,10 +386,8 @@ static inline u32 pcl_bus(const struct ti_lynx *lynx, pcl_t pclid)
return lynx->pcl_mem_dma + pclid * sizeof(struct ti_pcl);
}
-#endif /* CONFIG_IEEE1394_PCILYNX_LOCALRAM */
-
-#if defined (CONFIG_IEEE1394_PCILYNX_LOCALRAM) || defined (__BIG_ENDIAN)
+#if defined (__BIG_ENDIAN)
typedef struct ti_pcl pcltmp_t;
static inline struct ti_pcl *edit_pcl(const struct ti_lynx *lynx, pcl_t pclid,
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index 6a08a8982ea..7419af450bd 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -2901,7 +2901,7 @@ static int __init init_raw1394(void)
hpsb_register_highlevel(&raw1394_highlevel);
- if (IS_ERR(class_simple_device_add(hpsb_protocol_class, MKDEV(
+ if (IS_ERR(class_device_create(hpsb_protocol_class, MKDEV(
IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
NULL, RAW1394_DEVICE_NAME))) {
ret = -EFAULT;
@@ -2934,8 +2934,8 @@ static int __init init_raw1394(void)
out_dev:
devfs_remove(RAW1394_DEVICE_NAME);
- class_simple_device_remove(MKDEV(
- IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+ class_device_destroy(hpsb_protocol_class,
+ MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16));
out_unreg:
hpsb_unregister_highlevel(&raw1394_highlevel);
out:
@@ -2944,8 +2944,8 @@ out:
static void __exit cleanup_raw1394(void)
{
- class_simple_device_remove(MKDEV(
- IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+ class_device_destroy(hpsb_protocol_class,
+ MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16));
cdev_del(&raw1394_cdev);
devfs_remove(RAW1394_DEVICE_NAME);
hpsb_unregister_highlevel(&raw1394_highlevel);
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 00c7b958361..32368f3428e 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -745,7 +745,8 @@ static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud
list_add_tail(&scsi_id->scsi_list, &hi->scsi_ids);
/* Register our host with the SCSI stack. */
- scsi_host = scsi_host_alloc(&scsi_driver_template, 0);
+ scsi_host = scsi_host_alloc(&scsi_driver_template,
+ sizeof (unsigned long));
if (!scsi_host) {
SBP2_ERR("failed to register scsi host");
goto failed_alloc;
@@ -1070,7 +1071,7 @@ static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid, quadlet_
static __inline__ int sbp2_command_conversion_device_type(u8 device_type)
{
return (((device_type == TYPE_DISK) ||
- (device_type == TYPE_SDAD) ||
+ (device_type == TYPE_RBC) ||
(device_type == TYPE_ROM)) ? 1:0);
}
@@ -2111,102 +2112,6 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
*/
static void sbp2_check_sbp2_command(struct scsi_id_instance_data *scsi_id, unchar *cmd)
{
- unchar new_cmd[16];
- u8 device_type = SBP2_DEVICE_TYPE (scsi_id->sbp2_device_type_and_lun);
-
- SBP2_DEBUG("sbp2_check_sbp2_command");
-
- switch (*cmd) {
-
- case READ_6:
-
- if (sbp2_command_conversion_device_type(device_type)) {
-
- SBP2_DEBUG("Convert READ_6 to READ_10");
-
- /*
- * Need to turn read_6 into read_10
- */
- new_cmd[0] = 0x28;
- new_cmd[1] = (cmd[1] & 0xe0);
- new_cmd[2] = 0x0;
- new_cmd[3] = (cmd[1] & 0x1f);
- new_cmd[4] = cmd[2];
- new_cmd[5] = cmd[3];
- new_cmd[6] = 0x0;
- new_cmd[7] = 0x0;
- new_cmd[8] = cmd[4];
- new_cmd[9] = cmd[5];
-
- memcpy(cmd, new_cmd, 10);
-
- }
-
- break;
-
- case WRITE_6:
-
- if (sbp2_command_conversion_device_type(device_type)) {
-
- SBP2_DEBUG("Convert WRITE_6 to WRITE_10");
-
- /*
- * Need to turn write_6 into write_10
- */
- new_cmd[0] = 0x2a;
- new_cmd[1] = (cmd[1] & 0xe0);
- new_cmd[2] = 0x0;
- new_cmd[3] = (cmd[1] & 0x1f);
- new_cmd[4] = cmd[2];
- new_cmd[5] = cmd[3];
- new_cmd[6] = 0x0;
- new_cmd[7] = 0x0;
- new_cmd[8] = cmd[4];
- new_cmd[9] = cmd[5];
-
- memcpy(cmd, new_cmd, 10);
-
- }
-
- break;
-
- case MODE_SENSE:
-
- if (sbp2_command_conversion_device_type(device_type)) {
-
- SBP2_DEBUG("Convert MODE_SENSE_6 to MODE_SENSE_10");
-
- /*
- * Need to turn mode_sense_6 into mode_sense_10
- */
- new_cmd[0] = 0x5a;
- new_cmd[1] = cmd[1];
- new_cmd[2] = cmd[2];
- new_cmd[3] = 0x0;
- new_cmd[4] = 0x0;
- new_cmd[5] = 0x0;
- new_cmd[6] = 0x0;
- new_cmd[7] = 0x0;
- new_cmd[8] = cmd[4];
- new_cmd[9] = cmd[5];
-
- memcpy(cmd, new_cmd, 10);
-
- }
-
- break;
-
- case MODE_SELECT:
-
- /*
- * TODO. Probably need to change mode select to 10 byte version
- */
-
- default:
- break;
- }
-
- return;
}
/*
@@ -2247,7 +2152,6 @@ static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
struct scsi_cmnd *SCpnt)
{
u8 *scsi_buf = SCpnt->request_buffer;
- u8 device_type = SBP2_DEVICE_TYPE (scsi_id->sbp2_device_type_and_lun);
SBP2_DEBUG("sbp2_check_sbp2_response");
@@ -2272,14 +2176,6 @@ static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
}
/*
- * Check for Simple Direct Access Device and change it to TYPE_DISK
- */
- if ((scsi_buf[0] & 0x1f) == TYPE_SDAD) {
- SBP2_DEBUG("Changing TYPE_SDAD to TYPE_DISK");
- scsi_buf[0] &= 0xe0;
- }
-
- /*
* Fix ansi revision and response data format
*/
scsi_buf[2] |= 2;
@@ -2287,27 +2183,6 @@ static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
break;
- case MODE_SENSE:
-
- if (sbp2_command_conversion_device_type(device_type)) {
-
- SBP2_DEBUG("Modify mode sense response (10 byte version)");
-
- scsi_buf[0] = scsi_buf[1]; /* Mode data length */
- scsi_buf[1] = scsi_buf[2]; /* Medium type */
- scsi_buf[2] = scsi_buf[3]; /* Device specific parameter */
- scsi_buf[3] = scsi_buf[7]; /* Block descriptor length */
- memcpy(scsi_buf + 4, scsi_buf + 8, scsi_buf[0]);
- }
-
- break;
-
- case MODE_SELECT:
-
- /*
- * TODO. Probably need to change mode select to 10 byte version
- */
-
default:
break;
}
@@ -2579,8 +2454,6 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
u32 scsi_status, struct scsi_cmnd *SCpnt,
void (*done)(struct scsi_cmnd *))
{
- unsigned long flags;
-
SBP2_DEBUG("sbp2scsi_complete_command");
/*
@@ -2679,18 +2552,15 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
/*
* Tell scsi stack that we're done with this command
*/
- spin_lock_irqsave(scsi_id->scsi_host->host_lock,flags);
done (SCpnt);
- spin_unlock_irqrestore(scsi_id->scsi_host->host_lock,flags);
-
- return;
}
static int sbp2scsi_slave_configure (struct scsi_device *sdev)
{
blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
-
+ sdev->use_10_for_rw = 1;
+ sdev->use_10_for_ms = 1;
return 0;
}
@@ -2746,7 +2616,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
/*
* Called by scsi stack when something has really gone wrong.
*/
-static int sbp2scsi_reset(struct scsi_cmnd *SCpnt)
+static int __sbp2scsi_reset(struct scsi_cmnd *SCpnt)
{
struct scsi_id_instance_data *scsi_id =
(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
@@ -2761,12 +2631,24 @@ static int sbp2scsi_reset(struct scsi_cmnd *SCpnt)
return(SUCCESS);
}
+static int sbp2scsi_reset(struct scsi_cmnd *SCpnt)
+{
+ unsigned long flags;
+ int rc;
+
+ spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
+ rc = __sbp2scsi_reset(SCpnt);
+ spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
+
+ return rc;
+}
+
static const char *sbp2scsi_info (struct Scsi_Host *host)
{
return "SCSI emulation for IEEE-1394 SBP-2 Devices";
}
-static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev, char *buf)
+static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct scsi_device *sdev;
struct scsi_id_instance_data *scsi_id;
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
index a84b039a05b..cd425be7484 100644
--- a/drivers/ieee1394/sbp2.h
+++ b/drivers/ieee1394/sbp2.h
@@ -266,10 +266,6 @@ struct sbp2_status_block {
#define SBP2_MAX_UDS_PER_NODE 16 /* Maximum scsi devices per node */
#define SBP2_MAX_SECTORS 255 /* Max sectors supported */
-#ifndef TYPE_SDAD
-#define TYPE_SDAD 0x0e /* simplified direct access device */
-#endif
-
/*
* SCSI direction table...
* (now used as a back-up in case the direction passed down from above is "unknown")
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index 4bedf7113f4..06759b36afe 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -35,6 +35,11 @@
*
*/
+/* Markus Tavenrath <speedygoo@speedygoo.de> :
+ - fixed checks for valid buffer-numbers in video1394_icotl
+ - changed the ways the dma prg's are used, now it's possible to use
+ even a single dma buffer
+*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/list.h>
@@ -112,6 +117,7 @@ struct dma_iso_ctx {
struct it_dma_prg **it_prg;
unsigned int *buffer_status;
+ unsigned int *buffer_prg_assignment;
struct timeval *buffer_time; /* time when the buffer was received */
unsigned int *last_used_cmd; /* For ISO Transmit with
variable sized packets only ! */
@@ -180,23 +186,14 @@ static int free_dma_iso_ctx(struct dma_iso_ctx *d)
kfree(d->prg_reg);
}
- if (d->ir_prg)
- kfree(d->ir_prg);
-
- if (d->it_prg)
- kfree(d->it_prg);
-
- if (d->buffer_status)
- kfree(d->buffer_status);
- if (d->buffer_time)
- kfree(d->buffer_time);
- if (d->last_used_cmd)
- kfree(d->last_used_cmd);
- if (d->next_buffer)
- kfree(d->next_buffer);
-
+ kfree(d->ir_prg);
+ kfree(d->it_prg);
+ kfree(d->buffer_status);
+ kfree(d->buffer_prg_assignment);
+ kfree(d->buffer_time);
+ kfree(d->last_used_cmd);
+ kfree(d->next_buffer);
list_del(&d->link);
-
kfree(d);
return 0;
@@ -230,7 +227,7 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int num_desc,
/* Init the regions for easy cleanup */
dma_region_init(&d->dma);
- if (dma_region_alloc(&d->dma, d->num_desc * d->buf_size, ohci->dev,
+ if (dma_region_alloc(&d->dma, (d->num_desc - 1) * d->buf_size, ohci->dev,
PCI_DMA_BIDIRECTIONAL)) {
PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma buffer");
free_dma_iso_ctx(d);
@@ -342,6 +339,8 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int num_desc,
d->buffer_status = kmalloc(d->num_desc * sizeof(unsigned int),
GFP_KERNEL);
+ d->buffer_prg_assignment = kmalloc(d->num_desc * sizeof(unsigned int),
+ GFP_KERNEL);
d->buffer_time = kmalloc(d->num_desc * sizeof(struct timeval),
GFP_KERNEL);
d->last_used_cmd = kmalloc(d->num_desc * sizeof(unsigned int),
@@ -354,6 +353,11 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int num_desc,
free_dma_iso_ctx(d);
return NULL;
}
+ if (d->buffer_prg_assignment == NULL) {
+ PRINT(KERN_ERR, ohci->host->id, "Failed to allocate buffer_prg_assignment");
+ free_dma_iso_ctx(d);
+ return NULL;
+ }
if (d->buffer_time == NULL) {
PRINT(KERN_ERR, ohci->host->id, "Failed to allocate buffer_time");
free_dma_iso_ctx(d);
@@ -370,6 +374,7 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int num_desc,
return NULL;
}
memset(d->buffer_status, 0, d->num_desc * sizeof(unsigned int));
+ memset(d->buffer_prg_assignment, 0, d->num_desc * sizeof(unsigned int));
memset(d->buffer_time, 0, d->num_desc * sizeof(struct timeval));
memset(d->last_used_cmd, 0, d->num_desc * sizeof(unsigned int));
memset(d->next_buffer, -1, d->num_desc * sizeof(int));
@@ -379,7 +384,7 @@ alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int num_desc,
PRINT(KERN_INFO, ohci->host->id, "Iso %s DMA: %d buffers "
"of size %d allocated for a frame size %d, each with %d prgs",
(type == OHCI_ISO_RECEIVE) ? "receive" : "transmit",
- d->num_desc, d->buf_size, d->frame_size, d->nb_cmd);
+ d->num_desc - 1, d->buf_size, d->frame_size, d->nb_cmd);
return d;
}
@@ -394,11 +399,36 @@ static void reset_ir_status(struct dma_iso_ctx *d, int n)
d->ir_prg[n][i].status = cpu_to_le32(d->left_size);
}
+static void reprogram_dma_ir_prg(struct dma_iso_ctx *d, int n, int buffer, int flags)
+{
+ struct dma_cmd *ir_prg = d->ir_prg[n];
+ unsigned long buf = (unsigned long)d->dma.kvirt + buffer * d->buf_size;
+ int i;
+
+ d->buffer_prg_assignment[n] = buffer;
+
+ ir_prg[0].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, buf -
+ (unsigned long)d->dma.kvirt));
+ ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
+ (buf + 4) - (unsigned long)d->dma.kvirt));
+
+ for (i=2;i<d->nb_cmd-1;i++) {
+ ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
+ (buf+(i-1)*PAGE_SIZE) -
+ (unsigned long)d->dma.kvirt));
+ }
+
+ ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
+ DMA_CTL_IRQ | DMA_CTL_BRANCH | d->left_size);
+ ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
+ (buf+(i-1)*PAGE_SIZE) - (unsigned long)d->dma.kvirt));
+}
+
static void initialize_dma_ir_prg(struct dma_iso_ctx *d, int n, int flags)
{
struct dma_cmd *ir_prg = d->ir_prg[n];
struct dma_prog_region *ir_reg = &d->prg_reg[n];
- unsigned long buf = (unsigned long)d->dma.kvirt + n * d->buf_size;
+ unsigned long buf = (unsigned long)d->dma.kvirt;
int i;
/* the first descriptor will read only 4 bytes */
@@ -508,7 +538,7 @@ static void wakeup_dma_ir_ctx(unsigned long l)
for (i = 0; i < d->num_desc; i++) {
if (d->ir_prg[i][d->nb_cmd-1].status & cpu_to_le32(0xFFFF0000)) {
reset_ir_status(d, i);
- d->buffer_status[i] = VIDEO1394_BUFFER_READY;
+ d->buffer_status[d->buffer_prg_assignment[i]] = VIDEO1394_BUFFER_READY;
do_gettimeofday(&d->buffer_time[i]);
}
}
@@ -585,7 +615,7 @@ static void wakeup_dma_it_ctx(unsigned long l)
int next = d->next_buffer[i];
put_timestamp(ohci, d, next);
d->it_prg[i][d->last_used_cmd[i]].end.status = 0;
- d->buffer_status[i] = VIDEO1394_BUFFER_READY;
+ d->buffer_status[d->buffer_prg_assignment[i]] = VIDEO1394_BUFFER_READY;
}
}
@@ -595,11 +625,25 @@ static void wakeup_dma_it_ctx(unsigned long l)
wake_up_interruptible(&d->waitq);
}
+static void reprogram_dma_it_prg(struct dma_iso_ctx *d, int n, int buffer)
+{
+ struct it_dma_prg *it_prg = d->it_prg[n];
+ unsigned long buf = (unsigned long)d->dma.kvirt + buffer * d->buf_size;
+ int i;
+
+ d->buffer_prg_assignment[n] = buffer;
+ for (i=0;i<d->nb_cmd;i++) {
+ it_prg[i].end.address =
+ cpu_to_le32(dma_region_offset_to_bus(&d->dma,
+ (buf+i*d->packet_size) - (unsigned long)d->dma.kvirt));
+ }
+}
+
static void initialize_dma_it_prg(struct dma_iso_ctx *d, int n, int sync_tag)
{
struct it_dma_prg *it_prg = d->it_prg[n];
struct dma_prog_region *it_reg = &d->prg_reg[n];
- unsigned long buf = (unsigned long)d->dma.kvirt + n * d->buf_size;
+ unsigned long buf = (unsigned long)d->dma.kvirt;
int i;
d->last_used_cmd[n] = d->nb_cmd - 1;
for (i=0;i<d->nb_cmd;i++) {
@@ -796,7 +840,7 @@ static int __video1394_ioctl(struct file *file,
if (cmd == VIDEO1394_IOC_LISTEN_CHANNEL) {
d = alloc_dma_iso_ctx(ohci, OHCI_ISO_RECEIVE,
- v.nb_buffers, v.buf_size,
+ v.nb_buffers + 1, v.buf_size,
v.channel, 0);
if (d == NULL) {
@@ -817,7 +861,7 @@ static int __video1394_ioctl(struct file *file,
}
else {
d = alloc_dma_iso_ctx(ohci, OHCI_ISO_TRANSMIT,
- v.nb_buffers, v.buf_size,
+ v.nb_buffers + 1, v.buf_size,
v.channel, v.packet_size);
if (d == NULL) {
@@ -889,6 +933,7 @@ static int __video1394_ioctl(struct file *file,
{
struct video1394_wait v;
struct dma_iso_ctx *d;
+ int next_prg;
if (copy_from_user(&v, argp, sizeof(v)))
return -EFAULT;
@@ -896,7 +941,7 @@ static int __video1394_ioctl(struct file *file,
d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel);
if (d == NULL) return -EFAULT;
- if ((v.buffer<0) || (v.buffer>d->num_desc)) {
+ if ((v.buffer<0) || (v.buffer>=d->num_desc - 1)) {
PRINT(KERN_ERR, ohci->host->id,
"Buffer %d out of range",v.buffer);
return -EINVAL;
@@ -913,12 +958,14 @@ static int __video1394_ioctl(struct file *file,
d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED;
+ next_prg = (d->last_buffer + 1) % d->num_desc;
if (d->last_buffer>=0)
d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress =
- cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], 0)
+ cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[next_prg], 0)
& 0xfffffff0) | 0x1);
- d->last_buffer = v.buffer;
+ d->last_buffer = next_prg;
+ reprogram_dma_ir_prg(d, d->last_buffer, v.buffer, d->flags);
d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress = 0;
@@ -930,7 +977,7 @@ static int __video1394_ioctl(struct file *file,
/* Tell the controller where the first program is */
reg_write(ohci, d->cmdPtr,
- dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], 0) | 0x1);
+ dma_prog_region_offset_to_bus(&d->prg_reg[d->last_buffer], 0) | 0x1);
/* Run IR context */
reg_write(ohci, d->ctrlSet, 0x8000);
@@ -951,7 +998,7 @@ static int __video1394_ioctl(struct file *file,
{
struct video1394_wait v;
struct dma_iso_ctx *d;
- int i;
+ int i = 0;
if (copy_from_user(&v, argp, sizeof(v)))
return -EFAULT;
@@ -959,7 +1006,7 @@ static int __video1394_ioctl(struct file *file,
d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel);
if (d == NULL) return -EFAULT;
- if ((v.buffer<0) || (v.buffer>d->num_desc)) {
+ if ((v.buffer<0) || (v.buffer>d->num_desc - 1)) {
PRINT(KERN_ERR, ohci->host->id,
"Buffer %d out of range",v.buffer);
return -EINVAL;
@@ -1005,9 +1052,9 @@ static int __video1394_ioctl(struct file *file,
* Look ahead to see how many more buffers have been received
*/
i=0;
- while (d->buffer_status[(v.buffer+1)%d->num_desc]==
+ while (d->buffer_status[(v.buffer+1)%(d->num_desc - 1)]==
VIDEO1394_BUFFER_READY) {
- v.buffer=(v.buffer+1)%d->num_desc;
+ v.buffer=(v.buffer+1)%(d->num_desc - 1);
i++;
}
spin_unlock_irqrestore(&d->lock, flags);
@@ -1023,6 +1070,7 @@ static int __video1394_ioctl(struct file *file,
struct video1394_wait v;
unsigned int *psizes = NULL;
struct dma_iso_ctx *d;
+ int next_prg;
if (copy_from_user(&v, argp, sizeof(v)))
return -EFAULT;
@@ -1030,7 +1078,7 @@ static int __video1394_ioctl(struct file *file,
d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel);
if (d == NULL) return -EFAULT;
- if ((v.buffer<0) || (v.buffer>d->num_desc)) {
+ if ((v.buffer<0) || (v.buffer>=d->num_desc - 1)) {
PRINT(KERN_ERR, ohci->host->id,
"Buffer %d out of range",v.buffer);
return -EINVAL;
@@ -1056,19 +1104,19 @@ static int __video1394_ioctl(struct file *file,
spin_lock_irqsave(&d->lock,flags);
+ // last_buffer is last_prg
+ next_prg = (d->last_buffer + 1) % d->num_desc;
if (d->buffer_status[v.buffer]!=VIDEO1394_BUFFER_FREE) {
PRINT(KERN_ERR, ohci->host->id,
"Buffer %d is already used",v.buffer);
spin_unlock_irqrestore(&d->lock,flags);
- if (psizes)
- kfree(psizes);
+ kfree(psizes);
return -EBUSY;
}
if (d->flags & VIDEO1394_VARIABLE_PACKET_SIZE) {
initialize_dma_it_prg_var_packet_queue(
- d, v.buffer, psizes,
- ohci);
+ d, next_prg, psizes, ohci);
}
d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED;
@@ -1076,16 +1124,17 @@ static int __video1394_ioctl(struct file *file,
if (d->last_buffer >= 0) {
d->it_prg[d->last_buffer]
[ d->last_used_cmd[d->last_buffer] ].end.branchAddress =
- cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer],
+ cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[next_prg],
0) & 0xfffffff0) | 0x3);
d->it_prg[d->last_buffer]
[ d->last_used_cmd[d->last_buffer] ].begin.branchAddress =
- cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer],
+ cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[next_prg],
0) & 0xfffffff0) | 0x3);
- d->next_buffer[d->last_buffer] = v.buffer;
+ d->next_buffer[d->last_buffer] = (v.buffer + 1) % (d->num_desc - 1);
}
- d->last_buffer = v.buffer;
+ d->last_buffer = next_prg;
+ reprogram_dma_it_prg(d, d->last_buffer, v.buffer);
d->next_buffer[d->last_buffer] = -1;
d->it_prg[d->last_buffer][d->last_used_cmd[d->last_buffer]].end.branchAddress = 0;
@@ -1100,7 +1149,7 @@ static int __video1394_ioctl(struct file *file,
/* Tell the controller where the first program is */
reg_write(ohci, d->cmdPtr,
- dma_prog_region_offset_to_bus(&d->prg_reg[v.buffer], 0) | 0x3);
+ dma_prog_region_offset_to_bus(&d->prg_reg[next_prg], 0) | 0x3);
/* Run IT context */
reg_write(ohci, d->ctrlSet, 0x8000);
@@ -1116,9 +1165,7 @@ static int __video1394_ioctl(struct file *file,
}
}
- if (psizes)
- kfree(psizes);
-
+ kfree(psizes);
return 0;
}
@@ -1133,7 +1180,7 @@ static int __video1394_ioctl(struct file *file,
d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel);
if (d == NULL) return -EFAULT;
- if ((v.buffer<0) || (v.buffer>d->num_desc)) {
+ if ((v.buffer<0) || (v.buffer>=d->num_desc-1)) {
PRINT(KERN_ERR, ohci->host->id,
"Buffer %d out of range",v.buffer);
return -EINVAL;
@@ -1323,7 +1370,7 @@ static void video1394_add_host (struct hpsb_host *host)
hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id);
minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id;
- class_simple_device_add(hpsb_protocol_class, MKDEV(
+ class_device_create(hpsb_protocol_class, MKDEV(
IEEE1394_MAJOR, minor),
NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor),
@@ -1337,7 +1384,7 @@ static void video1394_remove_host (struct hpsb_host *host)
struct ti_ohci *ohci = hpsb_get_hostinfo(&video1394_highlevel, host);
if (ohci) {
- class_simple_device_remove(MKDEV(IEEE1394_MAJOR,
+ class_device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id));
devfs_remove("%s/%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
}
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index d4233ee61c3..276e1a53010 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -587,7 +587,7 @@ int ib_sa_path_rec_get(struct ib_device *device, u8 port_num,
init_mad(query->sa_query.mad, agent);
- query->sa_query.callback = ib_sa_path_rec_callback;
+ query->sa_query.callback = callback ? ib_sa_path_rec_callback : NULL;
query->sa_query.release = ib_sa_path_rec_release;
query->sa_query.port = port;
query->sa_query.mad->mad_hdr.method = IB_MGMT_METHOD_GET;
@@ -663,7 +663,7 @@ int ib_sa_mcmember_rec_query(struct ib_device *device, u8 port_num,
init_mad(query->sa_query.mad, agent);
- query->sa_query.callback = ib_sa_mcmember_rec_callback;
+ query->sa_query.callback = callback ? ib_sa_mcmember_rec_callback : NULL;
query->sa_query.release = ib_sa_mcmember_rec_release;
query->sa_query.port = port;
query->sa_query.mad->mad_hdr.method = method;
@@ -698,20 +698,21 @@ static void send_handler(struct ib_mad_agent *agent,
if (!query)
return;
- switch (mad_send_wc->status) {
- case IB_WC_SUCCESS:
- /* No callback -- already got recv */
- break;
- case IB_WC_RESP_TIMEOUT_ERR:
- query->callback(query, -ETIMEDOUT, NULL);
- break;
- case IB_WC_WR_FLUSH_ERR:
- query->callback(query, -EINTR, NULL);
- break;
- default:
- query->callback(query, -EIO, NULL);
- break;
- }
+ if (query->callback)
+ switch (mad_send_wc->status) {
+ case IB_WC_SUCCESS:
+ /* No callback -- already got recv */
+ break;
+ case IB_WC_RESP_TIMEOUT_ERR:
+ query->callback(query, -ETIMEDOUT, NULL);
+ break;
+ case IB_WC_WR_FLUSH_ERR:
+ query->callback(query, -EINTR, NULL);
+ break;
+ default:
+ query->callback(query, -EIO, NULL);
+ break;
+ }
dma_unmap_single(agent->device->dma_device,
pci_unmap_addr(query, mapping),
@@ -736,7 +737,7 @@ static void recv_handler(struct ib_mad_agent *mad_agent,
query = idr_find(&query_idr, mad_recv_wc->wc->wr_id);
spin_unlock_irqrestore(&idr_lock, flags);
- if (query) {
+ if (query && query->callback) {
if (mad_recv_wc->wc->status == IB_WC_SUCCESS)
query->callback(query,
mad_recv_wc->recv_buf.mad->mad_hdr.status ?
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 3a413f72ff6..90d51b179ab 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -40,9 +40,7 @@ struct ib_port {
struct kobject kobj;
struct ib_device *ibdev;
struct attribute_group gid_group;
- struct attribute **gid_attr;
struct attribute_group pkey_group;
- struct attribute **pkey_attr;
u8 port_num;
};
@@ -60,8 +58,9 @@ struct port_attribute port_attr_##_name = __ATTR(_name, _mode, _show, _store)
struct port_attribute port_attr_##_name = __ATTR_RO(_name)
struct port_table_attribute {
- struct port_attribute attr;
- int index;
+ struct port_attribute attr;
+ char name[8];
+ int index;
};
static ssize_t port_attr_show(struct kobject *kobj,
@@ -72,7 +71,7 @@ static ssize_t port_attr_show(struct kobject *kobj,
struct ib_port *p = container_of(kobj, struct ib_port, kobj);
if (!port_attr->show)
- return 0;
+ return -EIO;
return port_attr->show(p, port_attr, buf);
}
@@ -398,17 +397,16 @@ static void ib_port_release(struct kobject *kobj)
struct attribute *a;
int i;
- for (i = 0; (a = p->gid_attr[i]); ++i) {
- kfree(a->name);
+ for (i = 0; (a = p->gid_group.attrs[i]); ++i)
kfree(a);
- }
- for (i = 0; (a = p->pkey_attr[i]); ++i) {
- kfree(a->name);
+ kfree(p->gid_group.attrs);
+
+ for (i = 0; (a = p->pkey_group.attrs[i]); ++i)
kfree(a);
- }
- kfree(p->gid_attr);
+ kfree(p->pkey_group.attrs);
+
kfree(p);
}
@@ -449,58 +447,45 @@ static int ib_device_hotplug(struct class_device *cdev, char **envp,
return 0;
}
-static int alloc_group(struct attribute ***attr,
- ssize_t (*show)(struct ib_port *,
- struct port_attribute *, char *buf),
- int len)
+static struct attribute **
+alloc_group_attrs(ssize_t (*show)(struct ib_port *,
+ struct port_attribute *, char *buf),
+ int len)
{
- struct port_table_attribute ***tab_attr =
- (struct port_table_attribute ***) attr;
+ struct attribute **tab_attr;
+ struct port_table_attribute *element;
int i;
- int ret;
-
- *tab_attr = kmalloc((1 + len) * sizeof *tab_attr, GFP_KERNEL);
- if (!*tab_attr)
- return -ENOMEM;
- memset(*tab_attr, 0, (1 + len) * sizeof *tab_attr);
+ tab_attr = kcalloc(1 + len, sizeof(struct attribute *), GFP_KERNEL);
+ if (!tab_attr)
+ return NULL;
- for (i = 0; i < len; ++i) {
- (*tab_attr)[i] = kmalloc(sizeof *(*tab_attr)[i], GFP_KERNEL);
- if (!(*tab_attr)[i]) {
- ret = -ENOMEM;
+ for (i = 0; i < len; i++) {
+ element = kcalloc(1, sizeof(struct port_table_attribute),
+ GFP_KERNEL);
+ if (!element)
goto err;
- }
- memset((*tab_attr)[i], 0, sizeof *(*tab_attr)[i]);
- (*tab_attr)[i]->attr.attr.name = kmalloc(8, GFP_KERNEL);
- if (!(*tab_attr)[i]->attr.attr.name) {
- ret = -ENOMEM;
- goto err;
- }
- if (snprintf((*tab_attr)[i]->attr.attr.name, 8, "%d", i) >= 8) {
- ret = -ENOMEM;
+ if (snprintf(element->name, sizeof(element->name),
+ "%d", i) >= sizeof(element->name))
goto err;
- }
- (*tab_attr)[i]->attr.attr.mode = S_IRUGO;
- (*tab_attr)[i]->attr.attr.owner = THIS_MODULE;
- (*tab_attr)[i]->attr.show = show;
- (*tab_attr)[i]->index = i;
- }
-
- return 0;
+ element->attr.attr.name = element->name;
+ element->attr.attr.mode = S_IRUGO;
+ element->attr.attr.owner = THIS_MODULE;
+ element->attr.show = show;
+ element->index = i;
-err:
- for (i = 0; i < len; ++i) {
- if ((*tab_attr)[i])
- kfree((*tab_attr)[i]->attr.attr.name);
- kfree((*tab_attr)[i]);
+ tab_attr[i] = &element->attr.attr;
}
- kfree(*tab_attr);
+ return tab_attr;
- return ret;
+err:
+ while (--i >= 0)
+ kfree(tab_attr[i]);
+ kfree(tab_attr);
+ return NULL;
}
static int add_port(struct ib_device *device, int port_num)
@@ -541,23 +526,20 @@ static int add_port(struct ib_device *device, int port_num)
if (ret)
goto err_put;
- ret = alloc_group(&p->gid_attr, show_port_gid, attr.gid_tbl_len);
- if (ret)
- goto err_remove_pma;
-
p->gid_group.name = "gids";
- p->gid_group.attrs = p->gid_attr;
+ p->gid_group.attrs = alloc_group_attrs(show_port_gid, attr.gid_tbl_len);
+ if (!p->gid_group.attrs)
+ goto err_remove_pma;
ret = sysfs_create_group(&p->kobj, &p->gid_group);
if (ret)
goto err_free_gid;
- ret = alloc_group(&p->pkey_attr, show_port_pkey, attr.pkey_tbl_len);
- if (ret)
- goto err_remove_gid;
-
p->pkey_group.name = "pkeys";
- p->pkey_group.attrs = p->pkey_attr;
+ p->pkey_group.attrs = alloc_group_attrs(show_port_pkey,
+ attr.pkey_tbl_len);
+ if (!p->pkey_group.attrs)
+ goto err_remove_gid;
ret = sysfs_create_group(&p->kobj, &p->pkey_group);
if (ret)
@@ -568,23 +550,19 @@ static int add_port(struct ib_device *device, int port_num)
return 0;
err_free_pkey:
- for (i = 0; i < attr.pkey_tbl_len; ++i) {
- kfree(p->pkey_attr[i]->name);
- kfree(p->pkey_attr[i]);
- }
+ for (i = 0; i < attr.pkey_tbl_len; ++i)
+ kfree(p->pkey_group.attrs[i]);
- kfree(p->pkey_attr);
+ kfree(p->pkey_group.attrs);
err_remove_gid:
sysfs_remove_group(&p->kobj, &p->gid_group);
err_free_gid:
- for (i = 0; i < attr.gid_tbl_len; ++i) {
- kfree(p->gid_attr[i]->name);
- kfree(p->gid_attr[i]);
- }
+ for (i = 0; i < attr.gid_tbl_len; ++i)
+ kfree(p->gid_group.attrs[i]);
- kfree(p->gid_attr);
+ kfree(p->gid_group.attrs);
err_remove_pma:
sysfs_remove_group(&p->kobj, &pma_group);
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index 56b9c2fa2ec..9d912d6877f 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -499,6 +499,7 @@ static int ib_umad_open(struct inode *inode, struct file *filp)
static int ib_umad_close(struct inode *inode, struct file *filp)
{
struct ib_umad_file *file = filp->private_data;
+ struct ib_umad_packet *packet, *tmp;
int i;
for (i = 0; i < IB_UMAD_MAX_AGENTS; ++i)
@@ -507,6 +508,9 @@ static int ib_umad_close(struct inode *inode, struct file *filp)
ib_unregister_mad_agent(file->agent[i]);
}
+ list_for_each_entry_safe(packet, tmp, &file->recv_list, list)
+ kfree(packet);
+
kfree(file);
return 0;
diff --git a/drivers/infiniband/include/ib_sa.h b/drivers/infiniband/include/ib_sa.h
index f4f747707b3..00222285eb9 100644
--- a/drivers/infiniband/include/ib_sa.h
+++ b/drivers/infiniband/include/ib_sa.h
@@ -147,7 +147,7 @@ struct ib_sa_path_rec {
/* reserved */
u8 sl;
u8 mtu_selector;
- enum ib_mtu mtu;
+ u8 mtu;
u8 rate_selector;
u8 rate;
u8 packet_life_time_selector;
@@ -180,7 +180,7 @@ struct ib_sa_mcmember_rec {
u32 qkey;
u16 mlid;
u8 mtu_selector;
- enum ib_mtu mtu;
+ u8 mtu;
u8 traffic_class;
u16 pkey;
u8 rate_selector;
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 17552a29978..556264b4342 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -431,9 +431,9 @@ static struct input_handle *evdev_connect(struct input_handler *handler, struct
devfs_mk_cdev(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
S_IFCHR|S_IRUGO|S_IWUSR, "input/event%d", minor);
- class_simple_device_add(input_class,
- MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
- dev->dev, "event%d", minor);
+ class_device_create(input_class,
+ MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
+ dev->dev, "event%d", minor);
return &evdev->handle;
}
@@ -443,7 +443,8 @@ static void evdev_disconnect(struct input_handle *handle)
struct evdev *evdev = handle->private;
struct evdev_list *list;
- class_simple_device_remove(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
+ class_device_destroy(input_class,
+ MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
devfs_remove("input/event%d", evdev->minor);
evdev->exist = 0;
diff --git a/drivers/input/gameport/Kconfig b/drivers/input/gameport/Kconfig
index 6282f460aba..1d93f509290 100644
--- a/drivers/input/gameport/Kconfig
+++ b/drivers/input/gameport/Kconfig
@@ -68,23 +68,3 @@ config GAMEPORT_CS461X
depends on PCI
endif
-
-# Yes, SOUND_GAMEPORT looks a bit odd. Yes, it ends up being turned on
-# in every .config. Please don't touch it. It is here to handle an
-# unusual dependency between GAMEPORT and sound drivers.
-#
-# Some sound drivers call gameport functions. If GAMEPORT is
-# not selected, empty stubs are provided for the functions and all is
-# well.
-# If GAMEPORT is built in, everything is fine.
-# If GAMEPORT is a module, however, it would need to be loaded for the
-# sound driver to be able to link properly. Therefore, the sound
-# driver must be a module as well in that case. Since there's no way
-# to express that directly in Kconfig, we use SOUND_GAMEPORT to
-# express it. SOUND_GAMEPORT boils down to "if GAMEPORT is 'm',
-# anything that depends on SOUND_GAMEPORT must be 'm' as well. if
-# GAMEPORT is 'y' or 'n', it can be anything".
-config SOUND_GAMEPORT
- tristate
- default m if GAMEPORT=m
- default y
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index f20c3f23388..c77a82e4605 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -134,7 +134,7 @@ static int gameport_measure_speed(struct gameport *gameport)
}
gameport_close(gameport);
- return (cpu_data[_smp_processor_id()].loops_per_jiffy * (unsigned long)HZ / (1000 / 50)) / (tx < 1 ? 1 : tx);
+ return (cpu_data[raw_smp_processor_id()].loops_per_jiffy * (unsigned long)HZ / (1000 / 50)) / (tx < 1 ? 1 : tx);
#else
@@ -439,7 +439,7 @@ static int gameport_thread(void *nothing)
do {
gameport_handle_events();
wait_event_interruptible(gameport_wait, !list_empty(&gameport_event_list));
- try_to_freeze(PF_FREEZE);
+ try_to_freeze();
} while (!signal_pending(current));
printk(KERN_DEBUG "gameport: kgameportd exiting\n");
@@ -453,13 +453,13 @@ static int gameport_thread(void *nothing)
* Gameport port operations
*/
-static ssize_t gameport_show_description(struct device *dev, char *buf)
+static ssize_t gameport_show_description(struct device *dev, struct device_attribute *attr, char *buf)
{
struct gameport *gameport = to_gameport_port(dev);
return sprintf(buf, "%s\n", gameport->name);
}
-static ssize_t gameport_rebind_driver(struct device *dev, const char *buf, size_t count)
+static ssize_t gameport_rebind_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct gameport *gameport = to_gameport_port(dev);
struct device_driver *drv;
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 3385dd03abf..83c77c990dd 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -702,13 +702,13 @@ static int __init input_proc_init(void)
static inline int input_proc_init(void) { return 0; }
#endif
-struct class_simple *input_class;
+struct class *input_class;
static int __init input_init(void)
{
int retval = -ENOMEM;
- input_class = class_simple_create(THIS_MODULE, "input");
+ input_class = class_create(THIS_MODULE, "input");
if (IS_ERR(input_class))
return PTR_ERR(input_class);
input_proc_init();
@@ -718,7 +718,7 @@ static int __init input_init(void)
remove_proc_entry("devices", proc_bus_input_dir);
remove_proc_entry("handlers", proc_bus_input_dir);
remove_proc_entry("input", proc_bus);
- class_simple_destroy(input_class);
+ class_destroy(input_class);
return retval;
}
@@ -728,7 +728,7 @@ static int __init input_init(void)
remove_proc_entry("handlers", proc_bus_input_dir);
remove_proc_entry("input", proc_bus);
unregister_chrdev(INPUT_MAJOR, "input");
- class_simple_destroy(input_class);
+ class_destroy(input_class);
}
return retval;
}
@@ -741,7 +741,7 @@ static void __exit input_exit(void)
devfs_remove("input");
unregister_chrdev(INPUT_MAJOR, "input");
- class_simple_destroy(input_class);
+ class_destroy(input_class);
}
subsys_initcall(input_init);
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 7d7527f8b02..39775fc380c 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -422,7 +422,7 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct
joydev->nkey++;
}
- for (i = 0; i < BTN_JOYSTICK - BTN_MISC + 1; i++)
+ for (i = 0; i < BTN_JOYSTICK - BTN_MISC; i++)
if (test_bit(i + BTN_MISC, dev->keybit)) {
joydev->keymap[i] = joydev->nkey;
joydev->keypam[joydev->nkey] = i + BTN_MISC;
@@ -452,9 +452,9 @@ static struct input_handle *joydev_connect(struct input_handler *handler, struct
devfs_mk_cdev(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
S_IFCHR|S_IRUGO|S_IWUSR, "input/js%d", minor);
- class_simple_device_add(input_class,
- MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
- dev->dev, "js%d", minor);
+ class_device_create(input_class,
+ MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
+ dev->dev, "js%d", minor);
return &joydev->handle;
}
@@ -464,7 +464,7 @@ static void joydev_disconnect(struct input_handle *handle)
struct joydev *joydev = handle->private;
struct joydev_list *list;
- class_simple_device_remove(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
+ class_device_destroy(input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
devfs_remove("input/js%d", joydev->minor);
joydev->exist = 0;
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index ff66ed4ee2c..82fad9a23ac 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -54,7 +54,7 @@ static int atkbd_softraw = 1;
module_param_named(softraw, atkbd_softraw, bool, 0);
MODULE_PARM_DESC(softraw, "Use software generated rawmode");
-static int atkbd_scroll = 1;
+static int atkbd_scroll = 0;
module_param_named(scroll, atkbd_scroll, bool, 0);
MODULE_PARM_DESC(scroll, "Enable scroll-wheel on MS Office and similar keyboards");
@@ -171,9 +171,9 @@ static struct {
unsigned char set2;
} atkbd_scroll_keys[] = {
{ ATKBD_SCR_1, 0xc5 },
- { ATKBD_SCR_2, 0xa9 },
- { ATKBD_SCR_4, 0xb6 },
- { ATKBD_SCR_8, 0xa7 },
+ { ATKBD_SCR_2, 0x9d },
+ { ATKBD_SCR_4, 0xa4 },
+ { ATKBD_SCR_8, 0x9b },
{ ATKBD_SCR_CLICK, 0xe0 },
{ ATKBD_SCR_LEFT, 0xcb },
{ ATKBD_SCR_RIGHT, 0xd2 },
@@ -219,11 +219,11 @@ static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t
#define ATKBD_DEFINE_ATTR(_name) \
static ssize_t atkbd_show_##_name(struct atkbd *, char *); \
static ssize_t atkbd_set_##_name(struct atkbd *, const char *, size_t); \
-static ssize_t atkbd_do_show_##_name(struct device *d, char *b) \
+static ssize_t atkbd_do_show_##_name(struct device *d, struct device_attribute *attr, char *b) \
{ \
return atkbd_attr_show_helper(d, b, atkbd_show_##_name); \
} \
-static ssize_t atkbd_do_set_##_name(struct device *d, const char *b, size_t s) \
+static ssize_t atkbd_do_set_##_name(struct device *d, struct device_attribute *attr, const char *b, size_t s) \
{ \
return atkbd_attr_set_helper(d, b, s, atkbd_set_##_name); \
} \
@@ -465,8 +465,10 @@ static int atkbd_event(struct input_dev *dev, unsigned int type, unsigned int co
if (atkbd->softrepeat) return 0;
i = j = 0;
- while (i < 32 && period[i] < dev->rep[REP_PERIOD]) i++;
- while (j < 4 && delay[j] < dev->rep[REP_DELAY]) j++;
+ while (i < 31 && period[i] < dev->rep[REP_PERIOD])
+ i++;
+ while (j < 3 && delay[j] < dev->rep[REP_DELAY])
+ j++;
dev->rep[REP_PERIOD] = period[i];
dev->rep[REP_DELAY] = delay[j];
param[0] = i | (j << 5);
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 1f85a9718c8..7bf4be733e9 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -341,6 +341,8 @@ static int alps_reconnect(struct psmouse *psmouse)
unsigned char param[4];
int version;
+ psmouse_reset(psmouse);
+
if (!(priv->i = alps_get_model(psmouse, &version)))
return -1;
@@ -350,7 +352,7 @@ static int alps_reconnect(struct psmouse *psmouse)
if (alps_get_status(psmouse, param))
return -1;
- if (param[0] & 0x04)
+ if (!(param[0] & 0x04))
alps_tap_mode(psmouse, 1);
if (alps_absolute_mode(psmouse)) {
@@ -395,7 +397,7 @@ int alps_init(struct psmouse *psmouse)
}
if (param[0] & 0x04) {
- printk(KERN_INFO " Enabling hardware tapping\n");
+ printk(KERN_INFO "alps.c: Enabling hardware tapping\n");
if (alps_tap_mode(psmouse, 1))
printk(KERN_WARNING "alps.c: Failed to enable hardware tapping\n");
}
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
index cd8509549ea..019034b21a0 100644
--- a/drivers/input/mouse/psmouse-base.c
+++ b/drivers/input/mouse/psmouse-base.c
@@ -518,13 +518,16 @@ static int psmouse_probe(struct psmouse *psmouse)
/*
* First, we check if it's a mouse. It should send 0x00 or 0x03
* in case of an IntelliMouse in 4-byte mode or 0x04 for IM Explorer.
+ * Sunrex K8561 IR Keyboard/Mouse reports 0xff on second and subsequent
+ * ID queries, probably due to a firmware bug.
*/
param[0] = 0xa5;
if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETID))
return -1;
- if (param[0] != 0x00 && param[0] != 0x03 && param[0] != 0x04)
+ if (param[0] != 0x00 && param[0] != 0x03 &&
+ param[0] != 0x04 && param[0] != 0xff)
return -1;
/*
@@ -972,7 +975,7 @@ static int psmouse_set_maxproto(const char *val, struct kernel_param *kp)
return -EINVAL;
if (!strncmp(val, "any", 3)) {
- *((unsigned int *)kp->arg) = -1UL;
+ *((unsigned int *)kp->arg) = -1U;
return 0;
}
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index bda5b065d03..79e17a0c466 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -91,11 +91,11 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun
#define PSMOUSE_DEFINE_ATTR(_name) \
static ssize_t psmouse_attr_show_##_name(struct psmouse *, char *); \
static ssize_t psmouse_attr_set_##_name(struct psmouse *, const char *, size_t);\
-static ssize_t psmouse_do_show_##_name(struct device *d, char *b) \
+static ssize_t psmouse_do_show_##_name(struct device *d, struct device_attribute *attr, char *b) \
{ \
return psmouse_attr_show_helper(d, b, psmouse_attr_show_##_name); \
} \
-static ssize_t psmouse_do_set_##_name(struct device *d, const char *b, size_t s)\
+static ssize_t psmouse_do_set_##_name(struct device *d, struct device_attribute *attr, const char *b, size_t s)\
{ \
return psmouse_attr_set_helper(d, b, s, psmouse_attr_set_##_name); \
} \
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 69832f8fb72..36c721227b6 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -143,39 +143,6 @@ static int synaptics_identify(struct psmouse *psmouse)
return -1;
}
-static void print_ident(struct synaptics_data *priv)
-{
- printk(KERN_INFO "Synaptics Touchpad, model: %ld\n", SYN_ID_MODEL(priv->identity));
- printk(KERN_INFO " Firmware: %ld.%ld\n", SYN_ID_MAJOR(priv->identity),
- SYN_ID_MINOR(priv->identity));
- if (SYN_MODEL_ROT180(priv->model_id))
- printk(KERN_INFO " 180 degree mounted touchpad\n");
- if (SYN_MODEL_PORTRAIT(priv->model_id))
- printk(KERN_INFO " portrait touchpad\n");
- printk(KERN_INFO " Sensor: %ld\n", SYN_MODEL_SENSOR(priv->model_id));
- if (SYN_MODEL_NEWABS(priv->model_id))
- printk(KERN_INFO " new absolute packet format\n");
- if (SYN_MODEL_PEN(priv->model_id))
- printk(KERN_INFO " pen detection\n");
-
- if (SYN_CAP_EXTENDED(priv->capabilities)) {
- printk(KERN_INFO " Touchpad has extended capability bits\n");
- if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap))
- printk(KERN_INFO " -> %d multi-buttons, i.e. besides standard buttons\n",
- (int)(SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap)));
- if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
- printk(KERN_INFO " -> middle button\n");
- if (SYN_CAP_FOUR_BUTTON(priv->capabilities))
- printk(KERN_INFO " -> four buttons\n");
- if (SYN_CAP_MULTIFINGER(priv->capabilities))
- printk(KERN_INFO " -> multifinger detection\n");
- if (SYN_CAP_PALMDETECT(priv->capabilities))
- printk(KERN_INFO " -> palm detection\n");
- if (SYN_CAP_PASS_THROUGH(priv->capabilities))
- printk(KERN_INFO " -> pass-through port\n");
- }
-}
-
static int synaptics_query_hardware(struct psmouse *psmouse)
{
int retries = 0;
@@ -666,7 +633,11 @@ int synaptics_init(struct psmouse *psmouse)
priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS;
- print_ident(priv);
+ printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx\n",
+ SYN_ID_MODEL(priv->identity),
+ SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
+ priv->model_id, priv->capabilities, priv->ext_cap);
+
set_input_params(&psmouse->dev, priv);
psmouse->protocol_handler = synaptics_process_byte;
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 564974ce579..062848ac7e6 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -101,6 +101,7 @@ struct mousedev_list {
unsigned char ready, buffer, bufsiz;
unsigned char imexseq, impsseq;
enum mousedev_emul mode;
+ unsigned long last_buttons;
};
#define MOUSEDEV_SEQ_LEN 6
@@ -224,7 +225,7 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h
spin_lock_irqsave(&list->packet_lock, flags);
p = &list->packets[list->head];
- if (list->ready && p->buttons != packet->buttons) {
+ if (list->ready && p->buttons != mousedev->packet.buttons) {
unsigned int new_head = (list->head + 1) % PACKET_QUEUE_LEN;
if (new_head != list->tail) {
p = &list->packets[list->head = new_head];
@@ -249,10 +250,13 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h
p->dz += packet->dz;
p->buttons = mousedev->packet.buttons;
- list->ready = 1;
+ if (p->dx || p->dy || p->dz || p->buttons != list->last_buttons)
+ list->ready = 1;
spin_unlock_irqrestore(&list->packet_lock, flags);
- kill_fasync(&list->fasync, SIGIO, POLL_IN);
+
+ if (list->ready)
+ kill_fasync(&list->fasync, SIGIO, POLL_IN);
}
wake_up_interruptible(&mousedev->wait);
@@ -477,9 +481,10 @@ static void mousedev_packet(struct mousedev_list *list, signed char *ps2_data)
}
if (!p->dx && !p->dy && !p->dz) {
- if (list->tail == list->head)
+ if (list->tail == list->head) {
list->ready = 0;
- else
+ list->last_buttons = p->buttons;
+ } else
list->tail = (list->tail + 1) % PACKET_QUEUE_LEN;
}
@@ -642,9 +647,9 @@ static struct input_handle *mousedev_connect(struct input_handler *handler, stru
devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
S_IFCHR|S_IRUGO|S_IWUSR, "input/mouse%d", minor);
- class_simple_device_add(input_class,
- MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
- dev->dev, "mouse%d", minor);
+ class_device_create(input_class,
+ MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
+ dev->dev, "mouse%d", minor);
return &mousedev->handle;
}
@@ -654,7 +659,8 @@ static void mousedev_disconnect(struct input_handle *handle)
struct mousedev *mousedev = handle->private;
struct mousedev_list *list;
- class_simple_device_remove(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
+ class_device_destroy(input_class,
+ MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
devfs_remove("input/mouse%d", mousedev->minor);
mousedev->exist = 0;
@@ -730,8 +736,8 @@ static int __init mousedev_init(void)
devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX),
S_IFCHR|S_IRUGO|S_IWUSR, "input/mice");
- class_simple_device_add(input_class, MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX),
- NULL, "mice");
+ class_device_create(input_class,
+ MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), NULL, "mice");
#ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
if (!(psaux_registered = !misc_register(&psaux_mouse)))
@@ -750,7 +756,8 @@ static void __exit mousedev_exit(void)
misc_deregister(&psaux_mouse);
#endif
devfs_remove("input/mice");
- class_simple_device_remove(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX));
+ class_device_destroy(input_class,
+ MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX));
input_unregister_handler(&mousedev_handler);
}
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index f64867808fe..0487ecbb8a4 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -88,9 +88,11 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = {
};
/*
- * Some Fujitsu notebooks are ahving trouble with touhcpads if
+ * Some Fujitsu notebooks are having trouble with touchpads if
* active multiplexing mode is activated. Luckily they don't have
* external PS/2 ports so we can safely disable it.
+ * ... apparently some Toshibas don't like MUX mode either and
+ * die horrible death on reboot.
*/
static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
{
@@ -115,12 +117,26 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
},
},
{
+ .ident = "Fujitsu Lifebook S6230",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S6230"),
+ },
+ },
+ {
.ident = "Fujitsu T70H",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
DMI_MATCH(DMI_PRODUCT_NAME, "FMVLT70H"),
},
},
+ {
+ .ident = "Toshiba P10",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P10"),
+ },
+ },
{ }
};
@@ -215,11 +231,15 @@ static struct pnp_driver i8042_pnp_aux_driver = {
static void i8042_pnp_exit(void)
{
- if (i8042_pnp_kbd_registered)
+ if (i8042_pnp_kbd_registered) {
+ i8042_pnp_kbd_registered = 0;
pnp_unregister_driver(&i8042_pnp_kbd_driver);
+ }
- if (i8042_pnp_aux_registered)
+ if (i8042_pnp_aux_registered) {
+ i8042_pnp_aux_registered = 0;
pnp_unregister_driver(&i8042_pnp_aux_driver);
+ }
}
static int i8042_pnp_init(void)
@@ -227,7 +247,7 @@ static int i8042_pnp_init(void)
int result_kbd, result_aux;
if (i8042_nopnp) {
- printk("i8042: PNP detection disabled\n");
+ printk(KERN_INFO "i8042: PNP detection disabled\n");
return 0;
}
@@ -241,7 +261,7 @@ static int i8042_pnp_init(void)
#if defined(__ia64__)
return -ENODEV;
#else
- printk(KERN_WARNING "PNP: No PS/2 controller found. Probing ports directly.\n");
+ printk(KERN_INFO "PNP: No PS/2 controller found. Probing ports directly.\n");
return 0;
#endif
}
@@ -265,7 +285,7 @@ static int i8042_pnp_init(void)
i8042_pnp_kbd_irq = i8042_kbd_irq;
}
- if (result_aux > 0 && !i8042_pnp_aux_irq) {
+ if (!i8042_pnp_aux_irq) {
printk(KERN_WARNING "PNP: PS/2 controller doesn't have AUX irq; using default %#x\n", i8042_aux_irq);
i8042_pnp_aux_irq = i8042_aux_irq;
}
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 8e63e464d36..a9bf549c8dc 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -396,7 +396,7 @@ static void i8042_stop(struct serio *serio)
struct i8042_port *port = serio->port_data;
port->exists = 0;
- synchronize_kernel();
+ synchronize_sched();
port->serio = NULL;
}
@@ -698,6 +698,26 @@ static void i8042_timer_func(unsigned long data)
i8042_interrupt(0, NULL, NULL);
}
+static int i8042_ctl_test(void)
+{
+ unsigned char param;
+
+ if (!i8042_reset)
+ return 0;
+
+ if (i8042_command(&param, I8042_CMD_CTL_TEST)) {
+ printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n");
+ return -1;
+ }
+
+ if (param != I8042_RET_CTL_TEST) {
+ printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n",
+ param, I8042_RET_CTL_TEST);
+ return -1;
+ }
+
+ return 0;
+}
/*
* i8042_controller init initializes the i8042 controller, and,
@@ -719,21 +739,8 @@ static int i8042_controller_init(void)
return -1;
}
- if (i8042_reset) {
-
- unsigned char param;
-
- if (i8042_command(&param, I8042_CMD_CTL_TEST)) {
- printk(KERN_ERR "i8042.c: i8042 controller self test timeout.\n");
- return -1;
- }
-
- if (param != I8042_RET_CTL_TEST) {
- printk(KERN_ERR "i8042.c: i8042 controller selftest failed. (%#x != %#x)\n",
- param, I8042_RET_CTL_TEST);
- return -1;
- }
- }
+ if (i8042_ctl_test())
+ return -1;
/*
* Save the CTR for restoral on unload / reboot.
@@ -802,15 +809,11 @@ static int i8042_controller_init(void)
*/
static void i8042_controller_reset(void)
{
- unsigned char param;
-
/*
* Reset the controller if requested.
*/
- if (i8042_reset)
- if (i8042_command(&param, I8042_CMD_CTL_TEST))
- printk(KERN_ERR "i8042.c: i8042 controller reset timeout.\n");
+ i8042_ctl_test();
/*
* Disable MUX mode if present.
@@ -922,8 +925,11 @@ static int i8042_resume(struct device *dev, u32 level)
if (level != RESUME_ENABLE)
return 0;
- if (i8042_controller_init()) {
- printk(KERN_ERR "i8042: resume failed\n");
+ if (i8042_ctl_test())
+ return -1;
+
+ if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
+ printk(KERN_ERR "i8042: Can't write CTR\n");
return -1;
}
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 3313e2daeab..341824c4852 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -344,7 +344,7 @@ static int serio_thread(void *nothing)
do {
serio_handle_events();
wait_event_interruptible(serio_wait, !list_empty(&serio_event_list));
- try_to_freeze(PF_FREEZE);
+ try_to_freeze();
} while (!signal_pending(current));
printk(KERN_DEBUG "serio: kseriod exiting\n");
@@ -358,37 +358,55 @@ static int serio_thread(void *nothing)
* Serio port operations
*/
-static ssize_t serio_show_description(struct device *dev, char *buf)
+static ssize_t serio_show_description(struct device *dev, struct device_attribute *attr, char *buf)
{
struct serio *serio = to_serio_port(dev);
return sprintf(buf, "%s\n", serio->name);
}
-static ssize_t serio_show_id_type(struct device *dev, char *buf)
+static ssize_t serio_show_id_type(struct device *dev, struct device_attribute *attr, char *buf)
{
struct serio *serio = to_serio_port(dev);
return sprintf(buf, "%02x\n", serio->id.type);
}
-static ssize_t serio_show_id_proto(struct device *dev, char *buf)
+static ssize_t serio_show_id_proto(struct device *dev, struct device_attribute *attr, char *buf)
{
struct serio *serio = to_serio_port(dev);
return sprintf(buf, "%02x\n", serio->id.proto);
}
-static ssize_t serio_show_id_id(struct device *dev, char *buf)
+static ssize_t serio_show_id_id(struct device *dev, struct device_attribute *attr, char *buf)
{
struct serio *serio = to_serio_port(dev);
return sprintf(buf, "%02x\n", serio->id.id);
}
-static ssize_t serio_show_id_extra(struct device *dev, char *buf)
+static ssize_t serio_show_id_extra(struct device *dev, struct device_attribute *attr, char *buf)
{
struct serio *serio = to_serio_port(dev);
return sprintf(buf, "%02x\n", serio->id.extra);
}
-static ssize_t serio_rebind_driver(struct device *dev, const char *buf, size_t count)
+static DEVICE_ATTR(type, S_IRUGO, serio_show_id_type, NULL);
+static DEVICE_ATTR(proto, S_IRUGO, serio_show_id_proto, NULL);
+static DEVICE_ATTR(id, S_IRUGO, serio_show_id_id, NULL);
+static DEVICE_ATTR(extra, S_IRUGO, serio_show_id_extra, NULL);
+
+static struct attribute *serio_device_id_attrs[] = {
+ &dev_attr_type.attr,
+ &dev_attr_proto.attr,
+ &dev_attr_id.attr,
+ &dev_attr_extra.attr,
+ NULL
+};
+
+static struct attribute_group serio_id_attr_group = {
+ .name = "id",
+ .attrs = serio_device_id_attrs,
+};
+
+static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct serio *serio = to_serio_port(dev);
struct device_driver *drv;
@@ -419,13 +437,13 @@ static ssize_t serio_rebind_driver(struct device *dev, const char *buf, size_t c
return retval;
}
-static ssize_t serio_show_bind_mode(struct device *dev, char *buf)
+static ssize_t serio_show_bind_mode(struct device *dev, struct device_attribute *attr, char *buf)
{
struct serio *serio = to_serio_port(dev);
return sprintf(buf, "%s\n", serio->manual_bind ? "manual" : "auto");
}
-static ssize_t serio_set_bind_mode(struct device *dev, const char *buf, size_t count)
+static ssize_t serio_set_bind_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct serio *serio = to_serio_port(dev);
int retval;
@@ -444,10 +462,6 @@ static ssize_t serio_set_bind_mode(struct device *dev, const char *buf, size_t c
static struct device_attribute serio_device_attrs[] = {
__ATTR(description, S_IRUGO, serio_show_description, NULL),
- __ATTR(id_type, S_IRUGO, serio_show_id_type, NULL),
- __ATTR(id_proto, S_IRUGO, serio_show_id_proto, NULL),
- __ATTR(id_id, S_IRUGO, serio_show_id_id, NULL),
- __ATTR(id_extra, S_IRUGO, serio_show_id_extra, NULL),
__ATTR(drvctl, S_IWUSR, NULL, serio_rebind_driver),
__ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode),
__ATTR_NULL
@@ -498,6 +512,7 @@ static void serio_add_port(struct serio *serio)
if (serio->start)
serio->start(serio);
device_add(&serio->dev);
+ sysfs_create_group(&serio->dev.kobj, &serio_id_attr_group);
serio->registered = 1;
}
@@ -526,6 +541,7 @@ static void serio_destroy_port(struct serio *serio)
}
if (serio->registered) {
+ sysfs_remove_group(&serio->dev.kobj, &serio_id_attr_group);
device_del(&serio->dev);
list_del_init(&serio->node);
serio->registered = 0;
@@ -779,7 +795,6 @@ static int serio_resume(struct device *dev)
struct serio *serio = to_serio_port(dev);
if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) {
- serio_disconnect_port(serio);
/*
* Driver re-probing can take a while, so better let kseriod
* deal with it.
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c
index 22f73683952..79ca3846915 100644
--- a/drivers/input/serio/serport.c
+++ b/drivers/input/serio/serport.c
@@ -27,11 +27,15 @@ MODULE_LICENSE("GPL");
MODULE_ALIAS_LDISC(N_MOUSE);
#define SERPORT_BUSY 1
+#define SERPORT_ACTIVE 2
+#define SERPORT_DEAD 3
struct serport {
struct tty_struct *tty;
wait_queue_head_t wait;
struct serio *serio;
+ struct serio_device_id id;
+ spinlock_t lock;
unsigned long flags;
};
@@ -45,11 +49,29 @@ static int serport_serio_write(struct serio *serio, unsigned char data)
return -(serport->tty->driver->write(serport->tty, &data, 1) != 1);
}
+static int serport_serio_open(struct serio *serio)
+{
+ struct serport *serport = serio->port_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&serport->lock, flags);
+ set_bit(SERPORT_ACTIVE, &serport->flags);
+ spin_unlock_irqrestore(&serport->lock, flags);
+
+ return 0;
+}
+
+
static void serport_serio_close(struct serio *serio)
{
struct serport *serport = serio->port_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&serport->lock, flags);
+ clear_bit(SERPORT_ACTIVE, &serport->flags);
+ set_bit(SERPORT_DEAD, &serport->flags);
+ spin_unlock_irqrestore(&serport->lock, flags);
- serport->serio->id.type = 0;
wake_up_interruptible(&serport->wait);
}
@@ -61,36 +83,21 @@ static void serport_serio_close(struct serio *serio)
static int serport_ldisc_open(struct tty_struct *tty)
{
struct serport *serport;
- struct serio *serio;
- char name[64];
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- serport = kmalloc(sizeof(struct serport), GFP_KERNEL);
- serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
- if (unlikely(!serport || !serio)) {
- kfree(serport);
- kfree(serio);
+ serport = kcalloc(1, sizeof(struct serport), GFP_KERNEL);
+ if (!serport)
return -ENOMEM;
- }
- memset(serport, 0, sizeof(struct serport));
- serport->serio = serio;
- set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
serport->tty = tty;
- tty->disc_data = serport;
-
- memset(serio, 0, sizeof(struct serio));
- strlcpy(serio->name, "Serial port", sizeof(serio->name));
- snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", tty_name(tty, name));
- serio->id.type = SERIO_RS232;
- serio->write = serport_serio_write;
- serio->close = serport_serio_close;
- serio->port_data = serport;
-
+ spin_lock_init(&serport->lock);
init_waitqueue_head(&serport->wait);
+ tty->disc_data = serport;
+ set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
+
return 0;
}
@@ -100,7 +107,8 @@ static int serport_ldisc_open(struct tty_struct *tty)
static void serport_ldisc_close(struct tty_struct *tty)
{
- struct serport *serport = (struct serport*) tty->disc_data;
+ struct serport *serport = (struct serport *) tty->disc_data;
+
kfree(serport);
}
@@ -116,9 +124,19 @@ static void serport_ldisc_close(struct tty_struct *tty)
static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
{
struct serport *serport = (struct serport*) tty->disc_data;
+ unsigned long flags;
int i;
+
+ spin_lock_irqsave(&serport->lock, flags);
+
+ if (!test_bit(SERPORT_ACTIVE, &serport->flags))
+ goto out;
+
for (i = 0; i < count; i++)
serio_interrupt(serport->serio, cp[i], 0, NULL);
+
+out:
+ spin_unlock_irqrestore(&serport->lock, flags);
}
/*
@@ -141,16 +159,33 @@ static int serport_ldisc_room(struct tty_struct *tty)
static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, unsigned char __user * buf, size_t nr)
{
struct serport *serport = (struct serport*) tty->disc_data;
+ struct serio *serio;
char name[64];
if (test_and_set_bit(SERPORT_BUSY, &serport->flags))
return -EBUSY;
+ serport->serio = serio = kcalloc(1, sizeof(struct serio), GFP_KERNEL);
+ if (!serio)
+ return -ENOMEM;
+
+ strlcpy(serio->name, "Serial port", sizeof(serio->name));
+ snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", tty_name(tty, name));
+ serio->id = serport->id;
+ serio->id.type = SERIO_RS232;
+ serio->write = serport_serio_write;
+ serio->open = serport_serio_open;
+ serio->close = serport_serio_close;
+ serio->port_data = serport;
+
serio_register_port(serport->serio);
printk(KERN_INFO "serio: Serial port %s\n", tty_name(tty, name));
- wait_event_interruptible(serport->wait, !serport->serio->id.type);
+
+ wait_event_interruptible(serport->wait, test_bit(SERPORT_DEAD, &serport->flags));
serio_unregister_port(serport->serio);
+ serport->serio = NULL;
+ clear_bit(SERPORT_DEAD, &serport->flags);
clear_bit(SERPORT_BUSY, &serport->flags);
return 0;
@@ -163,16 +198,15 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u
static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg)
{
struct serport *serport = (struct serport*) tty->disc_data;
- struct serio *serio = serport->serio;
unsigned long type;
if (cmd == SPIOCSTYPE) {
if (get_user(type, (unsigned long __user *) arg))
return -EFAULT;
- serio->id.proto = type & 0x000000ff;
- serio->id.id = (type & 0x0000ff00) >> 8;
- serio->id.extra = (type & 0x00ff0000) >> 16;
+ serport->id.proto = type & 0x000000ff;
+ serport->id.id = (type & 0x0000ff00) >> 8;
+ serport->id.extra = (type & 0x00ff0000) >> 16;
return 0;
}
@@ -182,9 +216,13 @@ static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsi
static void serport_ldisc_write_wakeup(struct tty_struct * tty)
{
- struct serport *sp = (struct serport *) tty->disc_data;
+ struct serport *serport = (struct serport *) tty->disc_data;
+ unsigned long flags;
- serio_drv_write_wakeup(sp->serio);
+ spin_lock_irqsave(&serport->lock, flags);
+ if (test_bit(SERPORT_ACTIVE, &serport->flags))
+ serio_drv_write_wakeup(serport->serio);
+ spin_unlock_irqrestore(&serport->lock, flags);
}
/*
@@ -219,7 +257,7 @@ static int __init serport_init(void)
static void __exit serport_exit(void)
{
- tty_register_ldisc(N_MOUSE, NULL);
+ tty_unregister_ldisc(N_MOUSE);
}
module_init(serport_init);
diff --git a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c
index c9d0a153671..53a27e43dd2 100644
--- a/drivers/input/touchscreen/gunze.c
+++ b/drivers/input/touchscreen/gunze.c
@@ -68,8 +68,7 @@ static void gunze_process_packet(struct gunze* gunze, struct pt_regs *regs)
if (gunze->idx != GUNZE_MAX_LENGTH || gunze->data[5] != ',' ||
(gunze->data[0] != 'T' && gunze->data[0] != 'R')) {
- gunze->data[10] = 0;
- printk(KERN_WARNING "gunze.c: bad packet: >%s<\n", gunze->data);
+ printk(KERN_WARNING "gunze.c: bad packet: >%.*s<\n", GUNZE_MAX_LENGTH, gunze->data);
return;
}
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c
index d0afba85720..50c63a15515 100644
--- a/drivers/input/tsdev.c
+++ b/drivers/input/tsdev.c
@@ -414,9 +414,9 @@ static struct input_handle *tsdev_connect(struct input_handler *handler,
S_IFCHR|S_IRUGO|S_IWUSR, "input/ts%d", minor);
devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor + TSDEV_MINORS/2),
S_IFCHR|S_IRUGO|S_IWUSR, "input/tsraw%d", minor);
- class_simple_device_add(input_class,
- MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
- dev->dev, "ts%d", minor);
+ class_device_create(input_class,
+ MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
+ dev->dev, "ts%d", minor);
return &tsdev->handle;
}
@@ -426,7 +426,8 @@ static void tsdev_disconnect(struct input_handle *handle)
struct tsdev *tsdev = handle->private;
struct tsdev_list *list;
- class_simple_device_remove(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor));
+ class_device_destroy(input_class,
+ MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor));
devfs_remove("input/ts%d", tsdev->minor);
devfs_remove("input/tsraw%d", tsdev->minor);
tsdev->exist = 0;
diff --git a/drivers/isdn/act2000/capi.c b/drivers/isdn/act2000/capi.c
index 40395f56723..afa46681f98 100644
--- a/drivers/isdn/act2000/capi.c
+++ b/drivers/isdn/act2000/capi.c
@@ -224,6 +224,7 @@ actcapi_manufacturer_req_net(act2000_card *card)
/*
* Switch V.42 on or off
*/
+#if 0
int
actcapi_manufacturer_req_v42(act2000_card *card, ulong arg)
{
@@ -242,6 +243,7 @@ actcapi_manufacturer_req_v42(act2000_card *card, ulong arg)
ACTCAPI_QUEUE_TX;
return 0;
}
+#endif /* 0 */
/*
* Set error-handler
diff --git a/drivers/isdn/act2000/capi.h b/drivers/isdn/act2000/capi.h
index 04d2bcdd37a..f6d5f530b86 100644
--- a/drivers/isdn/act2000/capi.h
+++ b/drivers/isdn/act2000/capi.h
@@ -350,7 +350,6 @@ actcapi_nextsmsg(act2000_card *card)
extern int actcapi_chkhdr(act2000_card *, actcapi_msghdr *);
extern int actcapi_listen_req(act2000_card *);
extern int actcapi_manufacturer_req_net(act2000_card *);
-extern int actcapi_manufacturer_req_v42(act2000_card *, ulong);
extern int actcapi_manufacturer_req_errh(act2000_card *);
extern int actcapi_manufacturer_req_msn(act2000_card *);
extern int actcapi_connect_req(act2000_card *, act2000_chan *, char *, char, int, int);
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 12dee8e9fbb..04fb606b5dd 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -58,7 +58,7 @@ MODULE_LICENSE("GPL");
/* -------- driver information -------------------------------------- */
-static struct class_simple *capi_class;
+static struct class *capi_class;
static int capi_major = 68; /* allocated */
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
@@ -1499,20 +1499,20 @@ static int __init capi_init(void)
return -EIO;
}
- capi_class = class_simple_create(THIS_MODULE, "capi");
+ capi_class = class_create(THIS_MODULE, "capi");
if (IS_ERR(capi_class)) {
unregister_chrdev(capi_major, "capi20");
return PTR_ERR(capi_class);
}
- class_simple_device_add(capi_class, MKDEV(capi_major, 0), NULL, "capi");
+ class_device_create(capi_class, MKDEV(capi_major, 0), NULL, "capi");
devfs_mk_cdev(MKDEV(capi_major, 0), S_IFCHR | S_IRUSR | S_IWUSR,
"isdn/capi20");
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
if (capinc_tty_init() < 0) {
- class_simple_device_remove(MKDEV(capi_major, 0));
- class_simple_destroy(capi_class);
+ class_device_destroy(capi_class, MKDEV(capi_major, 0));
+ class_destroy(capi_class);
unregister_chrdev(capi_major, "capi20");
return -ENOMEM;
}
@@ -1539,8 +1539,8 @@ static void __exit capi_exit(void)
{
proc_exit();
- class_simple_device_remove(MKDEV(capi_major, 0));
- class_simple_destroy(capi_class);
+ class_device_destroy(capi_class, MKDEV(capi_major, 0));
+ class_destroy(capi_class);
unregister_chrdev(capi_major, "capi20");
devfs_remove("isdn/capi20");
diff --git a/drivers/isdn/hardware/avm/b1dma.c b/drivers/isdn/hardware/avm/b1dma.c
index 55bed00ca86..91dd0551fc7 100644
--- a/drivers/isdn/hardware/avm/b1dma.c
+++ b/drivers/isdn/hardware/avm/b1dma.c
@@ -955,7 +955,7 @@ EXPORT_SYMBOL(b1dma_release_appl);
EXPORT_SYMBOL(b1dma_send_message);
EXPORT_SYMBOL(b1dmactl_read_proc);
-int b1dma_init(void)
+static int __init b1dma_init(void)
{
char *p;
char rev[32];
@@ -972,7 +972,7 @@ int b1dma_init(void)
return 0;
}
-void b1dma_exit(void)
+static void __exit b1dma_exit(void)
{
}
diff --git a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c
index fa6b93b1a42..724aac2c1cc 100644
--- a/drivers/isdn/hardware/avm/c4.c
+++ b/drivers/isdn/hardware/avm/c4.c
@@ -885,7 +885,7 @@ static int c4_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
}
-void c4_reset_ctr(struct capi_ctr *ctrl)
+static void c4_reset_ctr(struct capi_ctr *ctrl)
{
avmcard *card = ((avmctrl_info *)(ctrl->driverdata))->card;
avmctrl_info *cinfo;
@@ -933,7 +933,7 @@ static void c4_remove(struct pci_dev *pdev)
/* ------------------------------------------------------------- */
-void c4_register_appl(struct capi_ctr *ctrl,
+static void c4_register_appl(struct capi_ctr *ctrl,
u16 appl,
capi_register_params *rp)
{
@@ -978,7 +978,7 @@ void c4_register_appl(struct capi_ctr *ctrl,
/* ------------------------------------------------------------- */
-void c4_release_appl(struct capi_ctr *ctrl, u16 appl)
+static void c4_release_appl(struct capi_ctr *ctrl, u16 appl)
{
avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
avmcard *card = cinfo->card;
diff --git a/drivers/isdn/hardware/avm/t1isa.c b/drivers/isdn/hardware/avm/t1isa.c
index cb9d9cee2a6..3b701d97bdf 100644
--- a/drivers/isdn/hardware/avm/t1isa.c
+++ b/drivers/isdn/hardware/avm/t1isa.c
@@ -328,7 +328,7 @@ static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
return 0;
}
-void t1isa_reset_ctr(struct capi_ctr *ctrl)
+static void t1isa_reset_ctr(struct capi_ctr *ctrl)
{
avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
avmcard *card = cinfo->card;
diff --git a/drivers/isdn/hisax/Makefile b/drivers/isdn/hisax/Makefile
index 8d6bb56754b..293e27789d5 100644
--- a/drivers/isdn/hisax/Makefile
+++ b/drivers/isdn/hisax/Makefile
@@ -23,7 +23,7 @@ endif
# Multipart objects.
hisax_st5481-y := st5481_init.o st5481_usb.o st5481_d.o \
- st5481_b.o st5481_hdlc.o
+ st5481_b.o
hisax-y := config.o isdnl1.o tei.o isdnl2.o isdnl3.o \
lmgr.o q931.o callc.o fsm.o
diff --git a/drivers/isdn/hisax/amd7930_fn.c b/drivers/isdn/hisax/amd7930_fn.c
index c4f861a5db2..8ae08c41c85 100644
--- a/drivers/isdn/hisax/amd7930_fn.c
+++ b/drivers/isdn/hisax/amd7930_fn.c
@@ -97,7 +97,7 @@ static WORD initAMD[] = {
};
-void /* macro wWordAMD */
+static void /* macro wWordAMD */
WriteWordAmd7930(struct IsdnCardState *cs, BYTE reg, WORD val)
{
wByteAMD(cs, 0x00, reg);
@@ -105,7 +105,7 @@ WriteWordAmd7930(struct IsdnCardState *cs, BYTE reg, WORD val)
wByteAMD(cs, 0x01, HIBYTE(val));
}
-WORD /* macro rWordAMD */
+static WORD /* macro rWordAMD */
ReadWordAmd7930(struct IsdnCardState *cs, BYTE reg)
{
WORD res;
@@ -665,7 +665,7 @@ Amd7930_l1hw(struct PStack *st, int pr, void *arg)
}
}
-void
+static void
setstack_Amd7930(struct PStack *st, struct IsdnCardState *cs)
{
@@ -676,7 +676,7 @@ setstack_Amd7930(struct PStack *st, struct IsdnCardState *cs)
}
-void
+static void
DC_Close_Amd7930(struct IsdnCardState *cs) {
if (cs->debug & L1_DEB_ISAC)
debugl1(cs, "Amd7930: DC_Close called");
diff --git a/drivers/isdn/hisax/asuscom.c b/drivers/isdn/hisax/asuscom.c
index 7546e2e4a94..a98c5e38bbb 100644
--- a/drivers/isdn/hisax/asuscom.c
+++ b/drivers/isdn/hisax/asuscom.c
@@ -22,7 +22,7 @@
extern const char *CardType[];
-const char *Asuscom_revision = "$Revision: 1.14.2.4 $";
+static const char *Asuscom_revision = "$Revision: 1.14.2.4 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -239,7 +239,7 @@ Start_IPAC:
return IRQ_HANDLED;
}
-void
+static void
release_io_asuscom(struct IsdnCardState *cs)
{
int bytecnt = 8;
diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c
index 6fcb2cf7b0b..625799ab0d1 100644
--- a/drivers/isdn/hisax/avm_pci.c
+++ b/drivers/isdn/hisax/avm_pci.c
@@ -172,7 +172,7 @@ struct BCState *Sel_BCS(struct IsdnCardState *cs, int channel)
return(NULL);
}
-void
+static void
write_ctrl(struct BCState *bcs, int which) {
if (bcs->cs->debug & L1_DEB_HSCX)
@@ -193,7 +193,7 @@ write_ctrl(struct BCState *bcs, int which) {
}
}
-void
+static void
modehdlc(struct BCState *bcs, int mode, int bc)
{
struct IsdnCardState *cs = bcs->cs;
@@ -451,7 +451,7 @@ HDLC_irq(struct BCState *bcs, u_int stat) {
}
}
-inline void
+static inline void
HDLC_irq_main(struct IsdnCardState *cs)
{
u_int stat;
@@ -487,7 +487,7 @@ HDLC_irq_main(struct IsdnCardState *cs)
}
}
-void
+static void
hdlc_l2l1(struct PStack *st, int pr, void *arg)
{
struct BCState *bcs = st->l1.bcs;
@@ -547,7 +547,7 @@ hdlc_l2l1(struct PStack *st, int pr, void *arg)
}
}
-void
+static void
close_hdlcstate(struct BCState *bcs)
{
modehdlc(bcs, 0, 0);
@@ -570,7 +570,7 @@ close_hdlcstate(struct BCState *bcs)
}
}
-int
+static int
open_hdlcstate(struct IsdnCardState *cs, struct BCState *bcs)
{
if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
@@ -598,7 +598,7 @@ open_hdlcstate(struct IsdnCardState *cs, struct BCState *bcs)
return (0);
}
-int
+static int
setstack_hdlc(struct PStack *st, struct BCState *bcs)
{
bcs->channel = st->l1.bc;
@@ -612,6 +612,7 @@ setstack_hdlc(struct PStack *st, struct BCState *bcs)
return (0);
}
+#if 0
void __init
clear_pending_hdlc_ints(struct IsdnCardState *cs)
{
@@ -641,8 +642,9 @@ clear_pending_hdlc_ints(struct IsdnCardState *cs)
debugl1(cs, "HDLC 2 VIN %x", val);
}
}
+#endif /* 0 */
-void __init
+static void __init
inithdlc(struct IsdnCardState *cs)
{
cs->bcs[0].BC_SetStack = setstack_hdlc;
diff --git a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c
index f410f628a3e..dcb308aeb50 100644
--- a/drivers/isdn/hisax/bkm_a4t.c
+++ b/drivers/isdn/hisax/bkm_a4t.c
@@ -23,7 +23,7 @@
extern const char *CardType[];
-const char *bkm_a4t_revision = "$Revision: 1.22.2.4 $";
+static const char *bkm_a4t_revision = "$Revision: 1.22.2.4 $";
static inline u_char
@@ -167,7 +167,7 @@ bkm_interrupt(int intno, void *dev_id, struct pt_regs *regs)
}
}
-void
+static void
release_io_bkm(struct IsdnCardState *cs)
{
if (cs->hw.ax.base) {
diff --git a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c
index 94bb83ce7fd..5f21b82c8c8 100644
--- a/drivers/isdn/hisax/bkm_a8.c
+++ b/drivers/isdn/hisax/bkm_a8.c
@@ -27,7 +27,7 @@
extern const char *CardType[];
-const char sct_quadro_revision[] = "$Revision: 1.22.2.4 $";
+static const char sct_quadro_revision[] = "$Revision: 1.22.2.4 $";
static const char *sct_quadro_subtypes[] =
{
@@ -193,7 +193,7 @@ bkm_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-void
+static void
release_io_sct_quadro(struct IsdnCardState *cs)
{
release_region(cs->hw.ax.base & 0xffffffc0, 128);
@@ -261,7 +261,7 @@ BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return (0);
}
-int __init
+static int __init
sct_alloc_io(u_int adr, u_int len)
{
if (!request_region(adr, len, "scitel")) {
diff --git a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c
index 04065ab2610..7c56c44f0fd 100644
--- a/drivers/isdn/hisax/callc.c
+++ b/drivers/isdn/hisax/callc.c
@@ -874,7 +874,7 @@ release_b_st(struct Channel *chanp)
}
}
-struct Channel
+static struct Channel
*selectfreechannel(struct PStack *st, int bch)
{
struct IsdnCardState *cs = st->l1.hardware;
@@ -1429,7 +1429,7 @@ capi_debug(struct Channel *chanp, capi_msg *cm)
HiSax_putstatus(chanp->cs, "Ch", "%d CAPIMSG %s", chanp->chan, tmpbuf);
}
-void
+static void
lli_got_fac_req(struct Channel *chanp, capi_msg *cm) {
if ((cm->para[0] != 3) || (cm->para[1] != 0))
return;
@@ -1454,7 +1454,7 @@ lli_got_fac_req(struct Channel *chanp, capi_msg *cm) {
}
}
-void
+static void
lli_got_manufacturer(struct Channel *chanp, struct IsdnCardState *cs, capi_msg *cm) {
if ((cs->typ == ISDN_CTYPE_ELSA) || (cs->typ == ISDN_CTYPE_ELSA_PNP) ||
(cs->typ == ISDN_CTYPE_ELSA_PCI)) {
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index 1663ee69d41..c542e6fb2bd 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -332,7 +332,7 @@ struct IsdnCard cards[HISAX_MAX_CARDS] = {
#define HISAX_IDSIZE (HISAX_MAX_CARDS*8)
static char HiSaxID[HISAX_IDSIZE] = { 0, };
-char *HiSax_id = HiSaxID;
+static char *HiSax_id = HiSaxID;
#ifdef MODULE
/* Variables for insmod */
static int type[HISAX_MAX_CARDS] = { 0, };
@@ -391,7 +391,7 @@ char *HiSax_getrev(const char *revision)
return rev;
}
-void __init HiSaxVersion(void)
+static void __init HiSaxVersion(void)
{
char tmp[64];
@@ -608,6 +608,7 @@ static inline struct IsdnCardState *hisax_findcard(int driverid)
/*
* Find card with given card number
*/
+#if 0
struct IsdnCardState *hisax_get_card(int cardnr)
{
if ((cardnr <= nrcards) && (cardnr > 0))
@@ -615,8 +616,9 @@ struct IsdnCardState *hisax_get_card(int cardnr)
return cards[cardnr - 1].cs;
return NULL;
}
+#endif /* 0 */
-int HiSax_readstatus(u_char __user *buf, int len, int id, int channel)
+static int HiSax_readstatus(u_char __user *buf, int len, int id, int channel)
{
int count, cnt;
u_char __user *p = buf;
@@ -768,7 +770,7 @@ int ll_run(struct IsdnCardState *cs, int addfeatures)
return 0;
}
-void ll_stop(struct IsdnCardState *cs)
+static void ll_stop(struct IsdnCardState *cs)
{
isdn_ctrl ic;
@@ -1184,7 +1186,7 @@ static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockow
return ret;
}
-void HiSax_shiftcards(int idx)
+static void HiSax_shiftcards(int idx)
{
int i;
@@ -1192,7 +1194,7 @@ void HiSax_shiftcards(int idx)
memcpy(&cards[i], &cards[i + 1], sizeof(cards[i]));
}
-int HiSax_inithardware(int *busy_flag)
+static int HiSax_inithardware(int *busy_flag)
{
int foundcards = 0;
int i = 0;
diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c
index 394d481e093..b62d6b30b72 100644
--- a/drivers/isdn/hisax/diva.c
+++ b/drivers/isdn/hisax/diva.c
@@ -28,7 +28,7 @@
extern const char *CardType[];
-const char *Diva_revision = "$Revision: 1.33.2.6 $";
+static const char *Diva_revision = "$Revision: 1.33.2.6 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -706,7 +706,7 @@ diva_irq_ipacx_pci(int intno, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-void
+static void
release_io_diva(struct IsdnCardState *cs)
{
int bytecnt;
diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c
index 4d7a0250d7e..110e9fd669c 100644
--- a/drivers/isdn/hisax/elsa.c
+++ b/drivers/isdn/hisax/elsa.c
@@ -33,13 +33,13 @@
extern const char *CardType[];
-const char *Elsa_revision = "$Revision: 2.32.2.4 $";
-const char *Elsa_Types[] =
+static const char *Elsa_revision = "$Revision: 2.32.2.4 $";
+static const char *Elsa_Types[] =
{"None", "PC", "PCC-8", "PCC-16", "PCF", "PCF-Pro",
"PCMCIA", "QS 1000", "QS 3000", "Microlink PCI", "QS 3000 PCI",
"PCMCIA-IPAC" };
-const char *ITACVer[] =
+static const char *ITACVer[] =
{"?0?", "?1?", "?2?", "?3?", "?4?", "V2.2",
"B1", "A1"};
@@ -425,7 +425,7 @@ Start_IPAC:
return IRQ_HANDLED;
}
-void
+static void
release_io_elsa(struct IsdnCardState *cs)
{
int bytecnt = 8;
diff --git a/drivers/isdn/hisax/elsa_ser.c b/drivers/isdn/hisax/elsa_ser.c
index 689c8339569..898ec091619 100644
--- a/drivers/isdn/hisax/elsa_ser.c
+++ b/drivers/isdn/hisax/elsa_ser.c
@@ -237,7 +237,7 @@ static void mshutdown(struct IsdnCardState *cs)
#endif
}
-inline int
+static inline int
write_modem(struct BCState *bcs) {
int ret=0;
struct IsdnCardState *cs = bcs->cs;
@@ -275,7 +275,7 @@ write_modem(struct BCState *bcs) {
return(ret);
}
-inline void
+static inline void
modem_fill(struct BCState *bcs) {
if (bcs->tx_skb) {
@@ -422,7 +422,7 @@ extern int open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs);
extern void modehscx(struct BCState *bcs, int mode, int bc);
extern void hscx_l2l1(struct PStack *st, int pr, void *arg);
-void
+static void
close_elsastate(struct BCState *bcs)
{
modehscx(bcs, 0, bcs->channel);
@@ -442,7 +442,7 @@ close_elsastate(struct BCState *bcs)
}
}
-void
+static void
modem_write_cmd(struct IsdnCardState *cs, u_char *buf, int len) {
int count, fp;
u_char *msg = buf;
@@ -472,7 +472,7 @@ modem_write_cmd(struct IsdnCardState *cs, u_char *buf, int len) {
}
}
-void
+static void
modem_set_init(struct IsdnCardState *cs) {
int timeout;
@@ -521,7 +521,7 @@ modem_set_init(struct IsdnCardState *cs) {
udelay(RCV_DELAY);
}
-void
+static void
modem_set_dial(struct IsdnCardState *cs, int outgoing) {
int timeout;
#define RCV_DELAY 20000
@@ -543,7 +543,7 @@ modem_set_dial(struct IsdnCardState *cs, int outgoing) {
udelay(RCV_DELAY);
}
-void
+static void
modem_l2l1(struct PStack *st, int pr, void *arg)
{
struct BCState *bcs = st->l1.bcs;
@@ -579,7 +579,7 @@ modem_l2l1(struct PStack *st, int pr, void *arg)
}
}
-int
+static int
setstack_elsa(struct PStack *st, struct BCState *bcs)
{
@@ -614,7 +614,7 @@ setstack_elsa(struct PStack *st, struct BCState *bcs)
return (0);
}
-void
+static void
init_modem(struct IsdnCardState *cs) {
cs->bcs[0].BC_SetStack = setstack_elsa;
@@ -641,7 +641,7 @@ init_modem(struct IsdnCardState *cs) {
modem_set_init(cs);
}
-void
+static void
release_modem(struct IsdnCardState *cs) {
cs->hw.elsa.MFlag = 0;
diff --git a/drivers/isdn/hisax/enternow.h b/drivers/isdn/hisax/enternow.h
deleted file mode 100644
index ed2eec5874c..00000000000
--- a/drivers/isdn/hisax/enternow.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* 2001/10/02
- *
- * enternow.h Header-file included by
- * enternow_pci.c
- *
- * Author Christoph Ersfeld <info@formula-n.de>
- * Formula-n Europe AG (www.formula-n.com)
- * previously Gerdes AG
- *
- *
- * This file is (c) under GNU PUBLIC LICENSE
- */
-
-
-/* ***************************************************************************************** *
- * ****************************** datatypes and macros ************************************* *
- * ***************************************************************************************** */
-
-#define BYTE unsigned char
-#define WORD unsigned int
-#define HIBYTE(w) ((unsigned char)((w & 0xff00) / 256))
-#define LOBYTE(w) ((unsigned char)(w & 0x00ff))
-#define InByte(addr) inb(addr)
-#define OutByte(addr,val) outb(val,addr)
-
-
-
-/* ***************************************************************************************** *
- * *********************************** card-specific *************************************** *
- * ***************************************************************************************** */
-
-/* für PowerISDN PCI */
-#define TJ_AMD_IRQ 0x20
-#define TJ_LED1 0x40
-#define TJ_LED2 0x80
-
-
-/* Das Fenster zum AMD...
- * Ab Adresse hw.njet.base + TJ_AMD_PORT werden vom AMD jeweils 8 Bit in
- * den TigerJet i/o-Raum gemappt
- * -> 0x01 des AMD bei hw.njet.base + 0C4 */
-#define TJ_AMD_PORT 0xC0
-
-
-
-/* ***************************************************************************************** *
- * *************************************** Prototypen ************************************** *
- * ***************************************************************************************** */
-
-BYTE ReadByteAmd7930(struct IsdnCardState *cs, BYTE offset);
-void WriteByteAmd7930(struct IsdnCardState *cs, BYTE offset, BYTE value);
diff --git a/drivers/isdn/hisax/enternow_pci.c b/drivers/isdn/hisax/enternow_pci.c
index 1cc4d11e007..3341cf15553 100644
--- a/drivers/isdn/hisax/enternow_pci.c
+++ b/drivers/isdn/hisax/enternow_pci.c
@@ -65,7 +65,6 @@
#include "isac.h"
#include "isdnl1.h"
#include "amd7930_fn.h"
-#include "enternow.h"
#include <linux/interrupt.h>
#include <linux/ppp_defs.h>
#include <linux/pci.h>
@@ -74,58 +73,72 @@
-const char *enternow_pci_rev = "$Revision: 1.1.4.5 $";
+static const char *enternow_pci_rev = "$Revision: 1.1.4.5 $";
+
+
+/* für PowerISDN PCI */
+#define TJ_AMD_IRQ 0x20
+#define TJ_LED1 0x40
+#define TJ_LED2 0x80
+
+
+/* Das Fenster zum AMD...
+ * Ab Adresse hw.njet.base + TJ_AMD_PORT werden vom AMD jeweils 8 Bit in
+ * den TigerJet i/o-Raum gemappt
+ * -> 0x01 des AMD bei hw.njet.base + 0C4 */
+#define TJ_AMD_PORT 0xC0
+
/* *************************** I/O-Interface functions ************************************* */
/* cs->readisac, macro rByteAMD */
-BYTE
-ReadByteAmd7930(struct IsdnCardState *cs, BYTE offset)
+static unsigned char
+ReadByteAmd7930(struct IsdnCardState *cs, unsigned char offset)
{
/* direktes Register */
if(offset < 8)
- return (InByte(cs->hw.njet.isac + 4*offset));
+ return (inb(cs->hw.njet.isac + 4*offset));
/* indirektes Register */
else {
- OutByte(cs->hw.njet.isac + 4*AMD_CR, offset);
- return(InByte(cs->hw.njet.isac + 4*AMD_DR));
+ outb(offset, cs->hw.njet.isac + 4*AMD_CR);
+ return(inb(cs->hw.njet.isac + 4*AMD_DR));
}
}
/* cs->writeisac, macro wByteAMD */
-void
-WriteByteAmd7930(struct IsdnCardState *cs, BYTE offset, BYTE value)
+static void
+WriteByteAmd7930(struct IsdnCardState *cs, unsigned char offset, unsigned char value)
{
/* direktes Register */
if(offset < 8)
- OutByte(cs->hw.njet.isac + 4*offset, value);
+ outb(value, cs->hw.njet.isac + 4*offset);
/* indirektes Register */
else {
- OutByte(cs->hw.njet.isac + 4*AMD_CR, offset);
- OutByte(cs->hw.njet.isac + 4*AMD_DR, value);
+ outb(offset, cs->hw.njet.isac + 4*AMD_CR);
+ outb(value, cs->hw.njet.isac + 4*AMD_DR);
}
}
-void
-enpci_setIrqMask(struct IsdnCardState *cs, BYTE val) {
+static void
+enpci_setIrqMask(struct IsdnCardState *cs, unsigned char val) {
if (!val)
- OutByte(cs->hw.njet.base+NETJET_IRQMASK1, 0x00);
+ outb(0x00, cs->hw.njet.base+NETJET_IRQMASK1);
else
- OutByte(cs->hw.njet.base+NETJET_IRQMASK1, TJ_AMD_IRQ);
+ outb(TJ_AMD_IRQ, cs->hw.njet.base+NETJET_IRQMASK1);
}
-static BYTE dummyrr(struct IsdnCardState *cs, int chan, BYTE off)
+static unsigned char dummyrr(struct IsdnCardState *cs, int chan, unsigned char off)
{
return(5);
}
-static void dummywr(struct IsdnCardState *cs, int chan, BYTE off, BYTE value)
+static void dummywr(struct IsdnCardState *cs, int chan, unsigned char off, unsigned char value)
{
}
@@ -142,18 +155,18 @@ reset_enpci(struct IsdnCardState *cs)
/* Reset on, (also for AMD) */
cs->hw.njet.ctrl_reg = 0x07;
- OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+ outb(cs->hw.njet.ctrl_reg, cs->hw.njet.base + NETJET_CTRL);
mdelay(20);
/* Reset off */
cs->hw.njet.ctrl_reg = 0x30;
- OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+ outb(cs->hw.njet.ctrl_reg, cs->hw.njet.base + NETJET_CTRL);
/* 20ms delay */
mdelay(20);
cs->hw.njet.auxd = 0; // LED-status
cs->hw.njet.dmactrl = 0;
- OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ);
- OutByte(cs->hw.njet.base + NETJET_IRQMASK1, TJ_AMD_IRQ);
- OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd); // LED off
+ outb(~TJ_AMD_IRQ, cs->hw.njet.base + NETJET_AUXCTRL);
+ outb(TJ_AMD_IRQ, cs->hw.njet.base + NETJET_IRQMASK1);
+ outb(cs->hw.njet.auxd, cs->hw.njet.auxa); // LED off
}
@@ -161,7 +174,7 @@ static int
enpci_card_msg(struct IsdnCardState *cs, int mt, void *arg)
{
u_long flags;
- BYTE *chan;
+ unsigned char *chan;
if (cs->debug & L1_DEB_ISAC)
debugl1(cs, "enter:now PCI: card_msg: 0x%04X", mt);
@@ -187,16 +200,16 @@ enpci_card_msg(struct IsdnCardState *cs, int mt, void *arg)
case MDL_ASSIGN:
/* TEI assigned, LED1 on */
cs->hw.njet.auxd = TJ_AMD_IRQ << 1;
- OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd);
+ outb(cs->hw.njet.auxd, cs->hw.njet.base + NETJET_AUXDATA);
break;
case MDL_REMOVE:
/* TEI removed, LEDs off */
cs->hw.njet.auxd = 0;
- OutByte(cs->hw.njet.base + NETJET_AUXDATA, 0x00);
+ outb(0x00, cs->hw.njet.base + NETJET_AUXDATA);
break;
case MDL_BC_ASSIGN:
/* activate B-channel */
- chan = (BYTE *)arg;
+ chan = (unsigned char *)arg;
if (cs->debug & L1_DEB_ISAC)
debugl1(cs, "enter:now PCI: assign phys. BC %d in AMD LMR1", *chan);
@@ -204,11 +217,11 @@ enpci_card_msg(struct IsdnCardState *cs, int mt, void *arg)
cs->dc.amd7930.ph_command(cs, (cs->dc.amd7930.lmr1 | (*chan + 1)), "MDL_BC_ASSIGN");
/* at least one b-channel in use, LED 2 on */
cs->hw.njet.auxd |= TJ_AMD_IRQ << 2;
- OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd);
+ outb(cs->hw.njet.auxd, cs->hw.njet.base + NETJET_AUXDATA);
break;
case MDL_BC_RELEASE:
/* deactivate B-channel */
- chan = (BYTE *)arg;
+ chan = (unsigned char *)arg;
if (cs->debug & L1_DEB_ISAC)
debugl1(cs, "enter:now PCI: release phys. BC %d in Amd LMR1", *chan);
@@ -217,7 +230,7 @@ enpci_card_msg(struct IsdnCardState *cs, int mt, void *arg)
/* no b-channel active -> LED2 off */
if (!(cs->dc.amd7930.lmr1 & 3)) {
cs->hw.njet.auxd &= ~(TJ_AMD_IRQ << 2);
- OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd);
+ outb(cs->hw.njet.auxd, cs->hw.njet.base + NETJET_AUXDATA);
}
break;
default:
@@ -231,11 +244,11 @@ static irqreturn_t
enpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
{
struct IsdnCardState *cs = dev_id;
- BYTE s0val, s1val, ir;
+ unsigned char s0val, s1val, ir;
u_long flags;
spin_lock_irqsave(&cs->lock, flags);
- s1val = InByte(cs->hw.njet.base + NETJET_IRQSTAT1);
+ s1val = inb(cs->hw.njet.base + NETJET_IRQSTAT1);
/* AMD threw an interrupt */
if (!(s1val & TJ_AMD_IRQ)) {
@@ -245,13 +258,13 @@ enpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
s1val = 1;
} else
s1val = 0;
- s0val = InByte(cs->hw.njet.base + NETJET_IRQSTAT0);
+ s0val = inb(cs->hw.njet.base + NETJET_IRQSTAT0);
if ((s0val | s1val)==0) { // shared IRQ
spin_unlock_irqrestore(&cs->lock, flags);
return IRQ_NONE;
}
if (s0val)
- OutByte(cs->hw.njet.base + NETJET_IRQSTAT0, s0val);
+ outb(s0val, cs->hw.njet.base + NETJET_IRQSTAT0);
/* DMA-Interrupt: B-channel-stuff */
/* set bits in sval to indicate which page is free */
@@ -342,20 +355,20 @@ setup_enternow_pci(struct IsdnCard *card)
/* Reset an */
cs->hw.njet.ctrl_reg = 0x07; // geändert von 0xff
- OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+ outb(cs->hw.njet.ctrl_reg, cs->hw.njet.base + NETJET_CTRL);
/* 20 ms Pause */
mdelay(20);
cs->hw.njet.ctrl_reg = 0x30; /* Reset Off and status read clear */
- OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+ outb(cs->hw.njet.ctrl_reg, cs->hw.njet.base + NETJET_CTRL);
mdelay(10);
cs->hw.njet.auxd = 0x00; // war 0xc0
cs->hw.njet.dmactrl = 0;
- OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ);
- OutByte(cs->hw.njet.base + NETJET_IRQMASK1, TJ_AMD_IRQ);
- OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd);
+ outb(~TJ_AMD_IRQ, cs->hw.njet.base + NETJET_AUXCTRL);
+ outb(TJ_AMD_IRQ, cs->hw.njet.base + NETJET_IRQMASK1);
+ outb(cs->hw.njet.auxd, cs->hw.njet.auxa);
break;
}
diff --git a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c
index 24a05a43f33..352b45ac534 100644
--- a/drivers/isdn/hisax/gazel.c
+++ b/drivers/isdn/hisax/gazel.c
@@ -21,7 +21,7 @@
#include <linux/pci.h>
extern const char *CardType[];
-const char *gazel_revision = "$Revision: 2.19.2.4 $";
+static const char *gazel_revision = "$Revision: 2.19.2.4 $";
#define R647 1
#define R685 2
@@ -317,7 +317,8 @@ gazel_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs)
spin_unlock_irqrestore(&cs->lock, flags);
return IRQ_HANDLED;
}
-void
+
+static void
release_io_gazel(struct IsdnCardState *cs)
{
unsigned int i;
diff --git a/drivers/isdn/hisax/hfc4s8s_l1.c b/drivers/isdn/hisax/hfc4s8s_l1.c
index ba1d028343e..6e7e060716b 100644
--- a/drivers/isdn/hisax/hfc4s8s_l1.c
+++ b/drivers/isdn/hisax/hfc4s8s_l1.c
@@ -1358,7 +1358,7 @@ chipreset(hfc4s8s_hw * hw)
/********************************************/
/* disable/enable hardware in nt or te mode */
/********************************************/
-void
+static void
hfc_hardware_enable(hfc4s8s_hw * hw, int enable, int nt_mode)
{
u_long flags;
diff --git a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c
index ebea3feef00..7cf87793e79 100644
--- a/drivers/isdn/hisax/hfc_2bds0.c
+++ b/drivers/isdn/hisax/hfc_2bds0.c
@@ -345,7 +345,7 @@ hfc_send_data(struct BCState *bcs)
debugl1(cs,"send_data %d blocked", bcs->channel);
}
-void
+static void
main_rec_2bds0(struct BCState *bcs)
{
struct IsdnCardState *cs = bcs->cs;
@@ -399,7 +399,7 @@ main_rec_2bds0(struct BCState *bcs)
return;
}
-void
+static void
mode_2bs0(struct BCState *bcs, int mode, int bc)
{
struct IsdnCardState *cs = bcs->cs;
@@ -505,7 +505,7 @@ hfc_l2l1(struct PStack *st, int pr, void *arg)
}
}
-void
+static void
close_2bs0(struct BCState *bcs)
{
mode_2bs0(bcs, 0, bcs->channel);
@@ -534,7 +534,7 @@ open_hfcstate(struct IsdnCardState *cs, struct BCState *bcs)
return (0);
}
-int
+static int
setstack_2b(struct PStack *st, struct BCState *bcs)
{
bcs->channel = st->l1.bc;
@@ -1004,7 +1004,7 @@ HFCD_l1hw(struct PStack *st, int pr, void *arg)
}
}
-void
+static void
setstack_hfcd(struct PStack *st, struct IsdnCardState *cs)
{
st->l1.l1hw = HFCD_l1hw;
@@ -1015,7 +1015,7 @@ hfc_dbusy_timer(struct IsdnCardState *cs)
{
}
-unsigned int __init
+static unsigned int __init
*init_send_hfcd(int cnt)
{
int i, *send;
diff --git a/drivers/isdn/hisax/hfc_2bs0.c b/drivers/isdn/hisax/hfc_2bs0.c
index bb376f39ac8..f978a5af866 100644
--- a/drivers/isdn/hisax/hfc_2bs0.c
+++ b/drivers/isdn/hisax/hfc_2bs0.c
@@ -52,7 +52,7 @@ WaitNoBusy(struct IsdnCardState *cs)
return (to);
}
-int
+static int
GetFreeFifoBytes(struct BCState *bcs)
{
int s;
@@ -66,7 +66,7 @@ GetFreeFifoBytes(struct BCState *bcs)
return (s);
}
-int
+static int
ReadZReg(struct BCState *bcs, u_char reg)
{
int val;
@@ -394,7 +394,7 @@ main_irq_hfc(struct BCState *bcs)
return;
}
-void
+static void
mode_hfc(struct BCState *bcs, int mode, int bc)
{
struct IsdnCardState *cs = bcs->cs;
@@ -507,7 +507,7 @@ hfc_l2l1(struct PStack *st, int pr, void *arg)
}
-void
+static void
close_hfcstate(struct BCState *bcs)
{
mode_hfc(bcs, 0, bcs->channel);
@@ -537,7 +537,7 @@ open_hfcstate(struct IsdnCardState *cs, struct BCState *bcs)
return (0);
}
-int
+static int
setstack_hfc(struct PStack *st, struct BCState *bcs)
{
bcs->channel = st->l1.bc;
@@ -551,7 +551,7 @@ setstack_hfc(struct PStack *st, struct BCState *bcs)
return (0);
}
-void __init
+static void __init
init_send(struct BCState *bcs)
{
int i;
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
index c2db52696a8..8337b0f26cc 100644
--- a/drivers/isdn/hisax/hfc_pci.c
+++ b/drivers/isdn/hisax/hfc_pci.c
@@ -70,7 +70,7 @@ static const PCI_ENTRY id_list[] =
/******************************************/
/* free hardware resources used by driver */
/******************************************/
-void
+static void
release_io_hfcpci(struct IsdnCardState *cs)
{
printk(KERN_INFO "HiSax: release hfcpci at %p\n",
@@ -394,7 +394,7 @@ receive_dmsg(struct IsdnCardState *cs)
/*******************************************************************************/
/* check for transparent receive data and read max one threshold size if avail */
/*******************************************************************************/
-int
+static int
hfcpci_empty_fifo_trans(struct BCState *bcs, bzfifo_type * bz, u_char * bdata)
{
unsigned short *z1r, *z2r;
@@ -446,7 +446,7 @@ hfcpci_empty_fifo_trans(struct BCState *bcs, bzfifo_type * bz, u_char * bdata)
/**********************************/
/* B-channel main receive routine */
/**********************************/
-void
+static void
main_rec_hfcpci(struct BCState *bcs)
{
struct IsdnCardState *cs = bcs->cs;
@@ -1244,7 +1244,7 @@ HFCPCI_l1hw(struct PStack *st, int pr, void *arg)
/***********************************************/
/* called during init setting l1 stack pointer */
/***********************************************/
-void
+static void
setstack_hfcpci(struct PStack *st, struct IsdnCardState *cs)
{
st->l1.l1hw = HFCPCI_l1hw;
@@ -1268,7 +1268,7 @@ hfcpci_send_data(struct BCState *bcs)
/***************************************************************/
/* activate/deactivate hardware for selected channels and mode */
/***************************************************************/
-void
+static void
mode_hfcpci(struct BCState *bcs, int mode, int bc)
{
struct IsdnCardState *cs = bcs->cs;
@@ -1579,7 +1579,7 @@ hfcpci_bh(struct IsdnCardState *cs)
/********************************/
/* called for card init message */
/********************************/
-void __init
+static void __init
inithfcpci(struct IsdnCardState *cs)
{
cs->bcs[0].BC_SetStack = setstack_2b;
diff --git a/drivers/isdn/hisax/hfc_pci.h b/drivers/isdn/hisax/hfc_pci.h
index 4df036ed1af..9ef2981e404 100644
--- a/drivers/isdn/hisax/hfc_pci.h
+++ b/drivers/isdn/hisax/hfc_pci.h
@@ -232,5 +232,4 @@ typedef union {
#define Read_hfc(a,b) (*(((u_char *)a->hw.hfcpci.pci_io)+b))
extern void main_irq_hcpci(struct BCState *bcs);
-extern void inithfcpci(struct IsdnCardState *cs);
extern void releasehfcpci(struct IsdnCardState *cs);
diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c
index a307fcb6c63..f27c1608a3a 100644
--- a/drivers/isdn/hisax/hfc_sx.c
+++ b/drivers/isdn/hisax/hfc_sx.c
@@ -308,7 +308,7 @@ read_fifo(struct IsdnCardState *cs, u_char fifo, int trans_max)
/******************************************/
/* free hardware resources used by driver */
/******************************************/
-void
+static void
release_io_hfcsx(struct IsdnCardState *cs)
{
cs->hw.hfcsx.int_m2 = 0; /* interrupt output off ! */
@@ -472,7 +472,7 @@ receive_dmsg(struct IsdnCardState *cs)
/**********************************/
/* B-channel main receive routine */
/**********************************/
-void
+static void
main_rec_hfcsx(struct BCState *bcs)
{
struct IsdnCardState *cs = bcs->cs;
@@ -1003,7 +1003,7 @@ HFCSX_l1hw(struct PStack *st, int pr, void *arg)
/***********************************************/
/* called during init setting l1 stack pointer */
/***********************************************/
-void
+static void
setstack_hfcsx(struct PStack *st, struct IsdnCardState *cs)
{
st->l1.l1hw = HFCSX_l1hw;
@@ -1027,7 +1027,7 @@ hfcsx_send_data(struct BCState *bcs)
/***************************************************************/
/* activate/deactivate hardware for selected channels and mode */
/***************************************************************/
-void
+static void
mode_hfcsx(struct BCState *bcs, int mode, int bc)
{
struct IsdnCardState *cs = bcs->cs;
@@ -1328,7 +1328,7 @@ hfcsx_bh(struct IsdnCardState *cs)
/********************************/
/* called for card init message */
/********************************/
-void __devinit
+static void __devinit
inithfcsx(struct IsdnCardState *cs)
{
cs->setstack_d = setstack_hfcsx;
diff --git a/drivers/isdn/hisax/hfc_sx.h b/drivers/isdn/hisax/hfc_sx.h
index 12f54159344..6792f13dc22 100644
--- a/drivers/isdn/hisax/hfc_sx.h
+++ b/drivers/isdn/hisax/hfc_sx.h
@@ -193,5 +193,4 @@ struct hfcsx_extra {
};
extern void main_irq_hfcsx(struct BCState *bcs);
-extern void inithfcsx(struct IsdnCardState *cs);
extern void releasehfcsx(struct IsdnCardState *cs);
diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c
index ffd74b84f50..e2c3af49d72 100644
--- a/drivers/isdn/hisax/hfc_usb.c
+++ b/drivers/isdn/hisax/hfc_usb.c
@@ -60,7 +60,7 @@ static const char *hfcusb_revision =
#include "hisax_debug.h"
static u_int debug;
module_param(debug, uint, 0);
-int hfc_debug;
+static int hfc_debug;
#endif
@@ -85,7 +85,7 @@ static struct usb_device_id hfc_usb_idtab[] = {
* VendorID, ProductID, Devicename, LED_SCHEME,
* LED's BitMask in HFCUSB_P_DATA Register : LED_USB, LED_S0, LED_B1, LED_B2
*/
-vendor_data vdata[] = {
+static vendor_data vdata[] = {
/* CologneChip Eval TA */
{0x0959, 0x2bd0, "ISDN USB TA (Cologne Chip HFC-S USB based)",
LED_OFF, {4, 0, 2, 1}
@@ -1137,7 +1137,7 @@ set_hfcmode(hfcusb_data * hfc, int channel, int mode)
}
}
-void
+static void
hfc_usb_l2l1(struct hisax_if *my_hisax_if, int pr, void *arg)
{
usb_fifo *fifo = my_hisax_if->priv;
diff --git a/drivers/isdn/hisax/hfc_usb.h b/drivers/isdn/hisax/hfc_usb.h
index b171600cf64..280dd29b30d 100644
--- a/drivers/isdn/hisax/hfc_usb.h
+++ b/drivers/isdn/hisax/hfc_usb.h
@@ -168,7 +168,7 @@ static struct hfcusb_symbolic_list urb_errlist[] = {
* 3 entries are the configuration number, the minimum interval for
* Interrupt endpoints & boolean if E-channel logging possible
*/
-int validconf[][19] = {
+static int validconf[][19] = {
// INT in, ISO out config
{EP_NUL, EP_INT, EP_NUL, EP_INT, EP_NUL, EP_INT, EP_NOP, EP_INT,
EP_ISO, EP_NUL, EP_ISO, EP_NUL, EP_ISO, EP_NUL, EP_NUL, EP_NUL,
@@ -187,7 +187,7 @@ int validconf[][19] = {
};
// string description of chosen config
-char *conf_str[] = {
+static char *conf_str[] = {
"4 Interrupt IN + 3 Isochron OUT",
"3 Interrupt IN + 3 Isochron OUT",
"4 Isochron IN + 3 Isochron OUT",
diff --git a/drivers/isdn/hisax/hfcscard.c b/drivers/isdn/hisax/hfcscard.c
index 6fc55fea170..86ab1c13f6b 100644
--- a/drivers/isdn/hisax/hfcscard.c
+++ b/drivers/isdn/hisax/hfcscard.c
@@ -52,7 +52,7 @@ hfcs_Timer(struct IsdnCardState *cs)
*/
}
-void
+static void
release_io_hfcs(struct IsdnCardState *cs)
{
release2bds0(cs);
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index dc5791728d5..17cf7663c58 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -1271,7 +1271,6 @@ extern void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf,
void init_bcstate(struct IsdnCardState *cs, int bc);
void setstack_HiSax(struct PStack *st, struct IsdnCardState *cs);
-unsigned int random_ri(void);
void HiSax_addlist(struct IsdnCardState *sp, struct PStack *st);
void HiSax_rmlist(struct IsdnCardState *sp, struct PStack *st);
@@ -1315,15 +1314,11 @@ int QuickHex(char *txt, u_char * p, int cnt);
void LogFrame(struct IsdnCardState *cs, u_char * p, int size);
void dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir);
void iecpy(u_char * dest, u_char * iestart, int ieoffset);
-#ifdef ISDN_CHIP_ISAC
-void setstack_isac(struct PStack *st, struct IsdnCardState *cs);
-#endif /* ISDN_CHIP_ISAC */
#endif /* __KERNEL__ */
#define HZDELAY(jiffs) {int tout = jiffs; while (tout--) udelay(1000000/HZ);}
int ll_run(struct IsdnCardState *cs, int addfeatures);
-void ll_stop(struct IsdnCardState *cs);
int CallcNew(void);
void CallcFree(void);
int CallcNewChan(struct IsdnCardState *cs);
diff --git a/drivers/isdn/hisax/hscx.c b/drivers/isdn/hisax/hscx.c
index 5bbbe3e9512..66dbaee77bf 100644
--- a/drivers/isdn/hisax/hscx.c
+++ b/drivers/isdn/hisax/hscx.c
@@ -151,7 +151,7 @@ hscx_l2l1(struct PStack *st, int pr, void *arg)
}
}
-void
+static void
close_hscxstate(struct BCState *bcs)
{
modehscx(bcs, 0, bcs->channel);
@@ -203,7 +203,7 @@ open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs)
return (0);
}
-int
+static int
setstack_hscx(struct PStack *st, struct BCState *bcs)
{
bcs->channel = st->l1.bc;
diff --git a/drivers/isdn/hisax/icc.c b/drivers/isdn/hisax/icc.c
index dcf31f83c60..b4ca5859b17 100644
--- a/drivers/isdn/hisax/icc.c
+++ b/drivers/isdn/hisax/icc.c
@@ -108,7 +108,7 @@ icc_bh(struct IsdnCardState *cs)
#endif
}
-void
+static void
icc_empty_fifo(struct IsdnCardState *cs, int count)
{
u_char *ptr;
@@ -563,13 +563,13 @@ ICC_l1hw(struct PStack *st, int pr, void *arg)
}
}
-void
+static void
setstack_icc(struct PStack *st, struct IsdnCardState *cs)
{
st->l1.l1hw = ICC_l1hw;
}
-void
+static void
DC_Close_icc(struct IsdnCardState *cs) {
if (cs->dc.icc.mon_rx) {
kfree(cs->dc.icc.mon_rx);
diff --git a/drivers/isdn/hisax/ipacx.c b/drivers/isdn/hisax/ipacx.c
index 6485e232d86..efba2f44801 100644
--- a/drivers/isdn/hisax/ipacx.c
+++ b/drivers/isdn/hisax/ipacx.c
@@ -36,8 +36,6 @@ static void ph_command(struct IsdnCardState *cs, unsigned int command);
static inline void cic_int(struct IsdnCardState *cs);
static void dch_l2l1(struct PStack *st, int pr, void *arg);
static void dbusy_timer_handler(struct IsdnCardState *cs);
-static void ipacx_new_ph(struct IsdnCardState *cs);
-static void dch_bh(struct IsdnCardState *cs);
static void dch_empty_fifo(struct IsdnCardState *cs, int count);
static void dch_fill_fifo(struct IsdnCardState *cs);
static inline void dch_int(struct IsdnCardState *cs);
@@ -232,81 +230,6 @@ dbusy_timer_handler(struct IsdnCardState *cs)
}
//----------------------------------------------------------
-// L1 state machine intermediate layer to isdnl1 module
-//----------------------------------------------------------
-static void
-ipacx_new_ph(struct IsdnCardState *cs)
-{
- switch (cs->dc.isac.ph_state) {
- case (IPACX_IND_RES):
- ph_command(cs, IPACX_CMD_DI);
- l1_msg(cs, HW_RESET | INDICATION, NULL);
- break;
-
- case (IPACX_IND_DC):
- l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL);
- break;
-
- case (IPACX_IND_DR):
- l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
- break;
-
- case (IPACX_IND_PU):
- l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
- break;
-
- case (IPACX_IND_RSY):
- l1_msg(cs, HW_RSYNC | INDICATION, NULL);
- break;
-
- case (IPACX_IND_AR):
- l1_msg(cs, HW_INFO2 | INDICATION, NULL);
- break;
-
- case (IPACX_IND_AI8):
- l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
- break;
-
- case (IPACX_IND_AI10):
- l1_msg(cs, HW_INFO4_P10 | INDICATION, NULL);
- break;
-
- default:
- break;
- }
-}
-
-//----------------------------------------------------------
-// bottom half handler for D channel
-//----------------------------------------------------------
-static void
-dch_bh(struct IsdnCardState *cs)
-{
- struct PStack *st;
-
- if (!cs) return;
-
- if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
- if (cs->debug) debugl1(cs, "D-Channel Busy cleared");
- for (st = cs->stlist; st; st = st->next) {
- st->l1.l1l2(st, PH_PAUSE | CONFIRM, NULL);
- }
- }
-
- if (test_and_clear_bit(D_RCVBUFREADY, &cs->event)) {
- DChannel_proc_rcv(cs);
- }
-
- if (test_and_clear_bit(D_XMTBUFREADY, &cs->event)) {
- DChannel_proc_xmt(cs);
- }
-
- if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
- ipacx_new_ph(cs);
- }
-}
-
-//----------------------------------------------------------
// Fill buffer from receive FIFO
//----------------------------------------------------------
static void
@@ -991,14 +914,5 @@ init_ipacx(struct IsdnCardState *cs, int part)
}
}
-
-void __devinit
-setup_ipacx(struct IsdnCardState *cs)
-{
- INIT_WORK(&cs->tqueue, (void *)(void *) dch_bh, cs);
- cs->dbusytimer.function = (void *) dbusy_timer_handler;
- cs->dbusytimer.data = (long) cs;
- init_timer(&cs->dbusytimer);
-}
//----------------- end of file -----------------------
diff --git a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c
index 20b94995295..85e063a08d2 100644
--- a/drivers/isdn/hisax/isac.c
+++ b/drivers/isdn/hisax/isac.c
@@ -112,7 +112,7 @@ isac_bh(struct IsdnCardState *cs)
#endif
}
-void
+static void
isac_empty_fifo(struct IsdnCardState *cs, int count)
{
u_char *ptr;
@@ -563,13 +563,13 @@ ISAC_l1hw(struct PStack *st, int pr, void *arg)
}
}
-void
+static void
setstack_isac(struct PStack *st, struct IsdnCardState *cs)
{
st->l1.l1hw = ISAC_l1hw;
}
-void
+static void
DC_Close_isac(struct IsdnCardState *cs) {
if (cs->dc.isac.mon_rx) {
kfree(cs->dc.isac.mon_rx);
diff --git a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c
index ee081321efb..642a87c5129 100644
--- a/drivers/isdn/hisax/isar.c
+++ b/drivers/isdn/hisax/isar.c
@@ -21,13 +21,13 @@
#define ETX 0x03
#define FAXMODCNT 13
-const u_char faxmodulation[] = {3,24,48,72,73,74,96,97,98,121,122,145,146};
+static const u_char faxmodulation[] = {3,24,48,72,73,74,96,97,98,121,122,145,146};
static u_int modmask = 0x1fff;
static int frm_extra_delay = 2;
static int para_TOA = 6;
-const u_char *FC1_CMD[] = {"FAE", "FTS", "FRS", "FTM", "FRM", "FTH", "FRH", "CTRL" };
+static const u_char *FC1_CMD[] = {"FAE", "FTS", "FRS", "FTM", "FRM", "FTH", "FRH", "CTRL" };
-void isar_setup(struct IsdnCardState *cs);
+static void isar_setup(struct IsdnCardState *cs);
static void isar_pump_cmd(struct BCState *bcs, u_char cmd, u_char para);
static void ll_deliver_faxstat(struct BCState *bcs, u_char status);
@@ -45,7 +45,7 @@ waitforHIA(struct IsdnCardState *cs, int timeout)
}
-int
+static int
sendmsg(struct IsdnCardState *cs, u_char his, u_char creg, u_char len,
u_char *msg)
{
@@ -85,7 +85,7 @@ sendmsg(struct IsdnCardState *cs, u_char his, u_char creg, u_char len,
}
/* Call only with IRQ disabled !!! */
-inline void
+static inline void
rcv_mbox(struct IsdnCardState *cs, struct isar_reg *ireg, u_char *msg)
{
int i;
@@ -114,7 +114,7 @@ rcv_mbox(struct IsdnCardState *cs, struct isar_reg *ireg, u_char *msg)
}
/* Call only with IRQ disabled !!! */
-inline void
+static inline void
get_irq_infos(struct IsdnCardState *cs, struct isar_reg *ireg)
{
ireg->iis = cs->BC_Read_Reg(cs, 1, ISAR_IIS);
@@ -127,7 +127,7 @@ get_irq_infos(struct IsdnCardState *cs, struct isar_reg *ireg)
#endif
}
-int
+static int
waitrecmsg(struct IsdnCardState *cs, u_char *len,
u_char *msg, int maxdelay)
{
@@ -185,7 +185,7 @@ ISARVersion(struct IsdnCardState *cs, char *s)
return(ver);
}
-int
+static int
isar_load_firmware(struct IsdnCardState *cs, u_char __user *buf)
{
int ret, size, cnt, debug;
@@ -739,7 +739,7 @@ isar_fill_fifo(struct BCState *bcs)
}
}
-inline
+static inline
struct BCState *sel_bcs_isar(struct IsdnCardState *cs, u_char dpath)
{
if ((!dpath) || (dpath == 3))
@@ -751,7 +751,7 @@ struct BCState *sel_bcs_isar(struct IsdnCardState *cs, u_char dpath)
return(NULL);
}
-void
+static void
send_frames(struct BCState *bcs)
{
if (bcs->tx_skb) {
@@ -806,7 +806,7 @@ send_frames(struct BCState *bcs)
}
}
-inline void
+static inline void
check_send(struct IsdnCardState *cs, u_char rdm)
{
struct BCState *bcs;
@@ -828,11 +828,13 @@ check_send(struct IsdnCardState *cs, u_char rdm)
}
-const char *dmril[] = {"NO SPEED", "1200/75", "NODEF2", "75/1200", "NODEF4",
- "300", "600", "1200", "2400", "4800", "7200",
- "9600nt", "9600t", "12000", "14400", "WRONG"};
-const char *dmrim[] = {"NO MOD", "NO DEF", "V32/V32b", "V22", "V21",
- "Bell103", "V23", "Bell202", "V17", "V29", "V27ter"};
+static const char *dmril[] = {"NO SPEED", "1200/75", "NODEF2", "75/1200",
+ "NODEF4", "300", "600", "1200", "2400",
+ "4800", "7200", "9600nt", "9600t", "12000",
+ "14400", "WRONG"};
+static const char *dmrim[] = {"NO MOD", "NO DEF", "V32/V32b", "V22", "V21",
+ "Bell103", "V23", "Bell202", "V17", "V29",
+ "V27ter"};
static void
isar_pump_status_rsp(struct BCState *bcs, struct isar_reg *ireg) {
@@ -1388,7 +1390,7 @@ setup_iom2(struct BCState *bcs) {
udelay(1000);
}
-int
+static int
modeisar(struct BCState *bcs, int mode, int bc)
{
struct IsdnCardState *cs = bcs->cs;
@@ -1562,7 +1564,7 @@ isar_pump_cmd(struct BCState *bcs, u_char cmd, u_char para)
sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, ctrl, nom, &p1);
}
-void
+static void
isar_setup(struct IsdnCardState *cs)
{
u_char msg;
@@ -1582,7 +1584,7 @@ isar_setup(struct IsdnCardState *cs)
}
}
-void
+static void
isar_l2l1(struct PStack *st, int pr, void *arg)
{
struct BCState *bcs = st->l1.bcs;
@@ -1681,7 +1683,7 @@ isar_l2l1(struct PStack *st, int pr, void *arg)
}
}
-void
+static void
close_isarstate(struct BCState *bcs)
{
modeisar(bcs, 0, bcs->channel);
@@ -1703,7 +1705,7 @@ close_isarstate(struct BCState *bcs)
del_timer(&bcs->hw.isar.ftimer);
}
-int
+static int
open_isarstate(struct IsdnCardState *cs, struct BCState *bcs)
{
if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
@@ -1725,7 +1727,7 @@ open_isarstate(struct IsdnCardState *cs, struct BCState *bcs)
return (0);
}
-int
+static int
setstack_isar(struct PStack *st, struct BCState *bcs)
{
bcs->channel = st->l1.bc;
diff --git a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c
index 4d08d27f149..ac899503a74 100644
--- a/drivers/isdn/hisax/isdnl1.c
+++ b/drivers/isdn/hisax/isdnl1.c
@@ -151,7 +151,7 @@ l1m_debug(struct FsmInst *fi, char *fmt, ...)
va_end(args);
}
-void
+static void
L1activated(struct IsdnCardState *cs)
{
struct PStack *st;
@@ -166,7 +166,7 @@ L1activated(struct IsdnCardState *cs)
}
}
-void
+static void
L1deactivated(struct IsdnCardState *cs)
{
struct PStack *st;
@@ -370,7 +370,7 @@ init_bcstate(struct IsdnCardState *cs, int bc)
#ifdef L2FRAME_DEBUG /* psa */
-char *
+static char *
l2cmd(u_char cmd)
{
switch (cmd & ~0x10) {
@@ -404,7 +404,7 @@ l2cmd(u_char cmd)
static char tmpdeb[32];
-char *
+static char *
l2frames(u_char * ptr)
{
switch (ptr[2] & ~0x10) {
diff --git a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c
index d311b5fbf89..9022583fd6a 100644
--- a/drivers/isdn/hisax/isdnl2.c
+++ b/drivers/isdn/hisax/isdnl2.c
@@ -142,7 +142,7 @@ freewin1(struct Layer2 *l2)
return cnt;
}
-inline void
+static inline void
freewin(struct PStack *st)
{
freewin1(&st->l2);
@@ -157,7 +157,7 @@ ReleaseWin(struct Layer2 *l2)
printk(KERN_WARNING "isdl2 freed %d skbuffs in release\n", cnt);
}
-inline unsigned int
+static inline unsigned int
cansend(struct PStack *st)
{
unsigned int p1;
@@ -169,7 +169,7 @@ cansend(struct PStack *st)
return ((p1 < st->l2.window) && !test_bit(FLG_PEER_BUSY, &st->l2.flag));
}
-inline void
+static inline void
clear_exception(struct Layer2 *l2)
{
test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
@@ -178,7 +178,7 @@ clear_exception(struct Layer2 *l2)
clear_peer_busy(l2);
}
-inline int
+static inline int
l2headersize(struct Layer2 *l2, int ui)
{
return (((test_bit(FLG_MOD128, &l2->flag) && (!ui)) ? 2 : 1) +
@@ -223,40 +223,31 @@ enqueue_super(struct PStack *st,
#define enqueue_ui(a, b) enqueue_super(a, b)
-inline int
+static inline int
IsUI(u_char * data)
{
return ((data[0] & 0xef) == UI);
}
-inline int
+static inline int
IsUA(u_char * data)
{
return ((data[0] & 0xef) == UA);
}
-inline int
+static inline int
IsDM(u_char * data)
{
return ((data[0] & 0xef) == DM);
}
-inline int
+static inline int
IsDISC(u_char * data)
{
return ((data[0] & 0xef) == DISC);
}
-inline int
-IsRR(u_char * data, struct PStack *st)
-{
- if (test_bit(FLG_MOD128, &st->l2.flag))
- return (data[0] == RR);
- else
- return ((data[0] & 0xf) == 1);
-}
-
-inline int
+static inline int
IsSFrame(u_char * data, struct PStack *st)
{
register u_char d = *data;
@@ -266,7 +257,7 @@ IsSFrame(u_char * data, struct PStack *st)
return(((d & 0xf3) == 1) && ((d & 0x0c) != 0x0c));
}
-inline int
+static inline int
IsSABME(u_char * data, struct PStack *st)
{
u_char d = data[0] & ~0x10;
@@ -274,25 +265,25 @@ IsSABME(u_char * data, struct PStack *st)
return (test_bit(FLG_MOD128, &st->l2.flag) ? d == SABME : d == SABM);
}
-inline int
+static inline int
IsREJ(u_char * data, struct PStack *st)
{
return (test_bit(FLG_MOD128, &st->l2.flag) ? data[0] == REJ : (data[0] & 0xf) == REJ);
}
-inline int
+static inline int
IsFRMR(u_char * data)
{
return ((data[0] & 0xef) == FRMR);
}
-inline int
+static inline int
IsRNR(u_char * data, struct PStack *st)
{
return (test_bit(FLG_MOD128, &st->l2.flag) ? data[0] == RNR : (data[0] & 0xf) == RNR);
}
-int
+static int
iframe_error(struct PStack *st, struct sk_buff *skb)
{
int i = l2addrsize(&st->l2) + (test_bit(FLG_MOD128, &st->l2.flag) ? 2 : 1);
@@ -315,7 +306,7 @@ iframe_error(struct PStack *st, struct sk_buff *skb)
return 0;
}
-int
+static int
super_error(struct PStack *st, struct sk_buff *skb)
{
if (skb->len != l2addrsize(&st->l2) +
@@ -325,7 +316,7 @@ super_error(struct PStack *st, struct sk_buff *skb)
return 0;
}
-int
+static int
unnum_error(struct PStack *st, struct sk_buff *skb, int wantrsp)
{
int rsp = (*skb->data & 0x2) >> 1;
@@ -341,7 +332,7 @@ unnum_error(struct PStack *st, struct sk_buff *skb, int wantrsp)
return 0;
}
-int
+static int
UI_error(struct PStack *st, struct sk_buff *skb)
{
int rsp = *skb->data & 0x2;
@@ -357,7 +348,7 @@ UI_error(struct PStack *st, struct sk_buff *skb)
return 0;
}
-int
+static int
FRMR_error(struct PStack *st, struct sk_buff *skb)
{
int headers = l2addrsize(&st->l2) + 1;
@@ -444,51 +435,44 @@ send_uframe(struct PStack *st, u_char cmd, u_char cr)
enqueue_super(st, skb);
}
-inline u_char
+static inline u_char
get_PollFlag(struct PStack * st, struct sk_buff * skb)
{
return (skb->data[l2addrsize(&(st->l2))] & 0x10);
}
-inline void
-FreeSkb(struct sk_buff *skb)
-{
- dev_kfree_skb(skb);
-}
-
-
-inline u_char
+static inline u_char
get_PollFlagFree(struct PStack *st, struct sk_buff *skb)
{
u_char PF;
PF = get_PollFlag(st, skb);
- FreeSkb(skb);
+ dev_kfree_skb(skb);
return (PF);
}
-inline void
+static inline void
start_t200(struct PStack *st, int i)
{
FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, i);
test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
}
-inline void
+static inline void
restart_t200(struct PStack *st, int i)
{
FsmRestartTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, i);
test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
}
-inline void
+static inline void
stop_t200(struct PStack *st, int i)
{
if(test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
FsmDelTimer(&st->l2.t200, i);
}
-inline void
+static inline void
st5_dl_release_l2l3(struct PStack *st)
{
int pr;
@@ -501,7 +485,7 @@ st5_dl_release_l2l3(struct PStack *st)
st->l2.l2l3(st, pr, NULL);
}
-inline void
+static inline void
lapb_dl_release_l2l3(struct PStack *st, int f)
{
if (test_bit(FLG_LAPB, &st->l2.flag))
@@ -802,7 +786,7 @@ l2_connected(struct FsmInst *fi, int event, void *arg)
l2_mdl_error_ua(fi, event, arg);
return;
}
- FreeSkb(skb);
+ dev_kfree_skb(skb);
if (test_and_clear_bit(FLG_PEND_REL, &st->l2.flag))
l2_disconnect(fi, event, arg);
@@ -840,7 +824,7 @@ l2_released(struct FsmInst *fi, int event, void *arg)
l2_mdl_error_ua(fi, event, arg);
return;
}
- FreeSkb(skb);
+ dev_kfree_skb(skb);
stop_t200(st, 6);
lapb_dl_release_l2l3(st, CONFIRM);
@@ -889,7 +873,7 @@ l2_st6_dm_release(struct FsmInst *fi, int event, void *arg)
}
}
-inline void
+static inline void
enquiry_cr(struct PStack *st, u_char typ, u_char cr, u_char pf)
{
struct sk_buff *skb;
@@ -912,7 +896,7 @@ enquiry_cr(struct PStack *st, u_char typ, u_char cr, u_char pf)
enqueue_super(st, skb);
}
-inline void
+static inline void
enquiry_response(struct PStack *st)
{
if (test_bit(FLG_OWN_BUSY, &st->l2.flag))
@@ -922,7 +906,7 @@ enquiry_response(struct PStack *st)
test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
}
-inline void
+static inline void
transmit_enquiry(struct PStack *st)
{
if (test_bit(FLG_OWN_BUSY, &st->l2.flag))
@@ -1004,7 +988,7 @@ l2_st7_got_super(struct FsmInst *fi, int event, void *arg)
PollFlag = (skb->data[0] & 0x10);
nr = (skb->data[0] >> 5) & 0x7;
}
- FreeSkb(skb);
+ dev_kfree_skb(skb);
if (PollFlag) {
if (rsp)
@@ -1047,7 +1031,7 @@ l2_feed_i_if_reest(struct FsmInst *fi, int event, void *arg)
if (!test_bit(FLG_L3_INIT, &st->l2.flag))
skb_queue_tail(&st->l2.i_queue, skb);
else
- FreeSkb(skb);
+ dev_kfree_skb(skb);
}
static void
@@ -1093,7 +1077,7 @@ l2_got_iframe(struct FsmInst *fi, int event, void *arg)
nr = (skb->data[i] >> 5) & 0x7;
}
if (test_bit(FLG_OWN_BUSY, &l2->flag)) {
- FreeSkb(skb);
+ dev_kfree_skb(skb);
if(PollFlag) enquiry_response(st);
} else if (l2->vr == ns) {
(l2->vr)++;
@@ -1111,7 +1095,7 @@ l2_got_iframe(struct FsmInst *fi, int event, void *arg)
st->l2.l2l3(st, DL_DATA | INDICATION, skb);
} else {
/* n(s)!=v(r) */
- FreeSkb(skb);
+ dev_kfree_skb(skb);
if (test_and_set_bit(FLG_REJEXC, &l2->flag)) {
if (PollFlag)
enquiry_response(st);
@@ -1309,7 +1293,7 @@ l2_pull_iqueue(struct FsmInst *fi, int event, void *arg)
skb = alloc_skb(oskb->len + i, GFP_ATOMIC);
memcpy(skb_put(skb, i), header, i);
memcpy(skb_put(skb, oskb->len), oskb->data, oskb->len);
- FreeSkb(oskb);
+ dev_kfree_skb(oskb);
}
st->l2.l2l1(st, PH_PULL | INDICATION, skb);
test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
@@ -1349,7 +1333,7 @@ l2_st8_got_super(struct FsmInst *fi, int event, void *arg)
PollFlag = (skb->data[0] & 0x10);
nr = (skb->data[0] >> 5) & 0x7;
}
- FreeSkb(skb);
+ dev_kfree_skb(skb);
if (rsp && PollFlag) {
if (legalnr(st, nr)) {
@@ -1391,7 +1375,7 @@ l2_got_FRMR(struct FsmInst *fi, int event, void *arg)
establishlink(fi);
test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
}
- FreeSkb(skb);
+ dev_kfree_skb(skb);
}
static void
@@ -1655,7 +1639,7 @@ isdnl2_l1l2(struct PStack *st, int pr, void *arg)
datap += len;
else {
FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *) 'N');
- FreeSkb(skb);
+ dev_kfree_skb(skb);
return;
}
if (!(*datap & 1)) { /* I-Frame */
@@ -1684,16 +1668,16 @@ isdnl2_l1l2(struct PStack *st, int pr, void *arg)
ret = FsmEvent(&st->l2.l2m, EV_L2_FRMR, skb);
} else {
FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *) 'L');
- FreeSkb(skb);
+ dev_kfree_skb(skb);
ret = 0;
}
if(c) {
- FreeSkb(skb);
+ dev_kfree_skb(skb);
FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *)(long)c);
ret = 0;
}
if (ret)
- FreeSkb(skb);
+ dev_kfree_skb(skb);
break;
case (PH_PULL | CONFIRM):
FsmEvent(&st->l2.l2m, EV_L2_ACK_PULL, arg);
diff --git a/drivers/isdn/hisax/isdnl3.c b/drivers/isdn/hisax/isdnl3.c
index f571b5d18e9..abcc9530eb3 100644
--- a/drivers/isdn/hisax/isdnl3.c
+++ b/drivers/isdn/hisax/isdnl3.c
@@ -390,7 +390,7 @@ setstack_l3dc(struct PStack *st, struct Channel *chanp)
}
}
-void
+static void
isdnl3_trans(struct PStack *st, int pr, void *arg) {
st->l3.l3l2(st, pr, arg);
}
diff --git a/drivers/isdn/hisax/isurf.c b/drivers/isdn/hisax/isurf.c
index af5171da734..33747afc984 100644
--- a/drivers/isdn/hisax/isurf.c
+++ b/drivers/isdn/hisax/isurf.c
@@ -122,7 +122,7 @@ isurf_interrupt(int intno, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-void
+static void
release_io_isurf(struct IsdnCardState *cs)
{
release_region(cs->hw.isurf.reset, 1);
diff --git a/drivers/isdn/hisax/ix1_micro.c b/drivers/isdn/hisax/ix1_micro.c
index b843b7509ae..908a7e14442 100644
--- a/drivers/isdn/hisax/ix1_micro.c
+++ b/drivers/isdn/hisax/ix1_micro.c
@@ -25,7 +25,7 @@
#include "isdnl1.h"
extern const char *CardType[];
-const char *ix1_revision = "$Revision: 2.12.2.4 $";
+static const char *ix1_revision = "$Revision: 2.12.2.4 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -162,7 +162,7 @@ ix1micro_interrupt(int intno, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-void
+static void
release_io_ix1micro(struct IsdnCardState *cs)
{
if (cs->hw.ix1.cfg_reg)
diff --git a/drivers/isdn/hisax/jade.c b/drivers/isdn/hisax/jade.c
index f05d5275755..363ae3179bb 100644
--- a/drivers/isdn/hisax/jade.c
+++ b/drivers/isdn/hisax/jade.c
@@ -74,7 +74,7 @@ jade_write_indirect(struct IsdnCardState *cs, u_char reg, u_char value)
-void
+static void
modejade(struct BCState *bcs, int mode, int bc)
{
struct IsdnCardState *cs = bcs->cs;
@@ -190,7 +190,7 @@ jade_l2l1(struct PStack *st, int pr, void *arg)
}
}
-void
+static void
close_jadestate(struct BCState *bcs)
{
modejade(bcs, 0, bcs->channel);
@@ -243,7 +243,7 @@ open_jadestate(struct IsdnCardState *cs, struct BCState *bcs)
}
-int
+static int
setstack_jade(struct PStack *st, struct BCState *bcs)
{
bcs->channel = st->l1.bc;
diff --git a/drivers/isdn/hisax/jade.h b/drivers/isdn/hisax/jade.h
index fa294448599..29055e1ee38 100644
--- a/drivers/isdn/hisax/jade.h
+++ b/drivers/isdn/hisax/jade.h
@@ -128,7 +128,6 @@
#define jade_TXAUDIOCH2CFG 0x1A
extern int JadeVersion(struct IsdnCardState *cs, char *s);
-extern void modejade(struct BCState *bcs, int mode, int bc);
extern void clear_pending_jade_ints(struct IsdnCardState *cs);
extern void initjade(struct IsdnCardState *cs);
diff --git a/drivers/isdn/hisax/l3_1tr6.c b/drivers/isdn/hisax/l3_1tr6.c
index d6c1c8f8329..c5c36eeff26 100644
--- a/drivers/isdn/hisax/l3_1tr6.c
+++ b/drivers/isdn/hisax/l3_1tr6.c
@@ -19,7 +19,7 @@
#include <linux/ctype.h>
extern char *HiSax_getrev(const char *revision);
-const char *l3_1tr6_revision = "$Revision: 2.15.2.3 $";
+static const char *l3_1tr6_revision = "$Revision: 2.15.2.3 $";
#define MsgHead(ptr, cref, mty, dis) \
*ptr++ = dis; \
diff --git a/drivers/isdn/hisax/l3dss1.c b/drivers/isdn/hisax/l3dss1.c
index ec92308c1ef..a6d2abdb478 100644
--- a/drivers/isdn/hisax/l3dss1.c
+++ b/drivers/isdn/hisax/l3dss1.c
@@ -26,7 +26,7 @@
#include <linux/config.h>
extern char *HiSax_getrev(const char *revision);
-const char *dss1_revision = "$Revision: 2.32.2.3 $";
+static const char *dss1_revision = "$Revision: 2.32.2.3 $";
#define EXT_BEARER_CAPS 1
diff --git a/drivers/isdn/hisax/l3ni1.c b/drivers/isdn/hisax/l3ni1.c
index 3ab3a54daac..f7041d5ba64 100644
--- a/drivers/isdn/hisax/l3ni1.c
+++ b/drivers/isdn/hisax/l3ni1.c
@@ -24,7 +24,7 @@
#include <linux/ctype.h>
extern char *HiSax_getrev(const char *revision);
-const char *ni1_revision = "$Revision: 2.8.2.3 $";
+static const char *ni1_revision = "$Revision: 2.8.2.3 $";
#define EXT_BEARER_CAPS 1
@@ -2665,7 +2665,7 @@ static void l3ni1_spid_send( struct l3_process *pc, u_char pr, void *arg )
l3ni1_SendSpid( pc, pr, arg, 20 );
}
-void l3ni1_spid_epid( struct l3_process *pc, u_char pr, void *arg )
+static void l3ni1_spid_epid( struct l3_process *pc, u_char pr, void *arg )
{
struct sk_buff *skb = arg;
diff --git a/drivers/isdn/hisax/mic.c b/drivers/isdn/hisax/mic.c
index 3ac4484a488..fe11f226b28 100644
--- a/drivers/isdn/hisax/mic.c
+++ b/drivers/isdn/hisax/mic.c
@@ -18,7 +18,7 @@
extern const char *CardType[];
-const char *mic_revision = "$Revision: 1.12.2.4 $";
+static const char *mic_revision = "$Revision: 1.12.2.4 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -157,7 +157,7 @@ mic_interrupt(int intno, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-void
+static void
release_io_mic(struct IsdnCardState *cs)
{
int bytecnt = 8;
diff --git a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c
index fe61d26365d..94da03c30c5 100644
--- a/drivers/isdn/hisax/netjet.c
+++ b/drivers/isdn/hisax/netjet.c
@@ -25,8 +25,6 @@
#include <asm/io.h>
#include "netjet.h"
-const char *NETjet_revision = "$Revision: 1.29.2.4 $";
-
/* Interface functions */
u_char
@@ -66,7 +64,7 @@ NETjet_WriteICfifo(struct IsdnCardState *cs, u_char *data, int size)
outsb(cs->hw.njet.isac, data, size);
}
-void fill_mem(struct BCState *bcs, u_int *pos, u_int cnt, int chan, u_char fill)
+static void fill_mem(struct BCState *bcs, u_int *pos, u_int cnt, int chan, u_char fill)
{
u_int mask=0x000000ff, val = 0, *p=pos;
u_int i;
@@ -85,7 +83,7 @@ void fill_mem(struct BCState *bcs, u_int *pos, u_int cnt, int chan, u_char fill)
}
}
-void
+static void
mode_tiger(struct BCState *bcs, int mode, int bc)
{
struct IsdnCardState *cs = bcs->cs;
@@ -852,7 +850,7 @@ tiger_l2l1(struct PStack *st, int pr, void *arg)
}
-void
+static void
close_tigerstate(struct BCState *bcs)
{
mode_tiger(bcs, 0, bcs->channel);
@@ -900,7 +898,7 @@ open_tigerstate(struct IsdnCardState *cs, struct BCState *bcs)
return (0);
}
-int
+static int
setstack_tiger(struct PStack *st, struct BCState *bcs)
{
bcs->channel = st->l1.bc;
@@ -966,7 +964,7 @@ inittiger(struct IsdnCardState *cs)
cs->bcs[1].BC_Close = close_tigerstate;
}
-void
+static void
releasetiger(struct IsdnCardState *cs)
{
if (cs->bcs[0].hw.tiger.send) {
diff --git a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c
index cf77d836097..68a2159cbd1 100644
--- a/drivers/isdn/hisax/niccy.c
+++ b/drivers/isdn/hisax/niccy.c
@@ -24,7 +24,7 @@
#include <linux/isapnp.h>
extern const char *CardType[];
-const char *niccy_revision = "$Revision: 1.21.2.4 $";
+static const char *niccy_revision = "$Revision: 1.21.2.4 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -178,7 +178,7 @@ niccy_interrupt(int intno, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-void
+static void
release_io_niccy(struct IsdnCardState *cs)
{
if (cs->subtyp == NICCY_PCI) {
diff --git a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c
index fd664697f82..a7d3cd3f36f 100644
--- a/drivers/isdn/hisax/nj_s.c
+++ b/drivers/isdn/hisax/nj_s.c
@@ -15,7 +15,7 @@
#include <linux/ppp_defs.h>
#include "netjet.h"
-const char *NETjet_S_revision = "$Revision: 2.13.2.4 $";
+static const char *NETjet_S_revision = "$Revision: 2.13.2.4 $";
static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off)
{
diff --git a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c
index 3d6441e9633..1ae7cac98a8 100644
--- a/drivers/isdn/hisax/nj_u.c
+++ b/drivers/isdn/hisax/nj_u.c
@@ -15,7 +15,7 @@
#include <linux/ppp_defs.h>
#include "netjet.h"
-const char *NETjet_U_revision = "$Revision: 2.14.2.3 $";
+static const char *NETjet_U_revision = "$Revision: 2.14.2.3 $";
static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off)
{
diff --git a/drivers/isdn/hisax/q931.c b/drivers/isdn/hisax/q931.c
index 170fcd4a398..abecabf8c27 100644
--- a/drivers/isdn/hisax/q931.c
+++ b/drivers/isdn/hisax/q931.c
@@ -516,7 +516,7 @@ struct MessageType cause_1tr6[] =
{CAUSE_UserInfoDiscarded, "User Info Discarded"}
};
-int cause_1tr6_len = (sizeof(cause_1tr6) / sizeof(struct MessageType));
+static int cause_1tr6_len = (sizeof(cause_1tr6) / sizeof(struct MessageType));
static int
prcause_1tr6(char *dest, u_char * p)
@@ -935,7 +935,7 @@ display(char *dest, u_char * p)
return (dp - dest);
}
-int
+static int
prfacility(char *dest, u_char * p)
{
char *dp = dest;
diff --git a/drivers/isdn/hisax/s0box.c b/drivers/isdn/hisax/s0box.c
index f3c481384a4..7b63085ea6e 100644
--- a/drivers/isdn/hisax/s0box.c
+++ b/drivers/isdn/hisax/s0box.c
@@ -17,7 +17,7 @@
#include "isdnl1.h"
extern const char *CardType[];
-const char *s0box_revision = "$Revision: 2.6.2.4 $";
+static const char *s0box_revision = "$Revision: 2.6.2.4 $";
static inline void
writereg(unsigned int padr, signed int addr, u_char off, u_char val) {
@@ -183,7 +183,7 @@ s0box_interrupt(int intno, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-void
+static void
release_io_s0box(struct IsdnCardState *cs)
{
release_region(cs->hw.teles3.cfg_reg, 8);
diff --git a/drivers/isdn/hisax/saphir.c b/drivers/isdn/hisax/saphir.c
index 9e6d3d686cc..821776e1561 100644
--- a/drivers/isdn/hisax/saphir.c
+++ b/drivers/isdn/hisax/saphir.c
@@ -171,7 +171,7 @@ SaphirWatchDog(struct IsdnCardState *cs)
mod_timer(&cs->hw.saphir.timer, jiffies+1*HZ);
}
-void
+static void
release_io_saphir(struct IsdnCardState *cs)
{
byteout(cs->hw.saphir.cfg_reg + IRQ_REG, 0xff);
diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c
index 8390f160685..8c044a6a7fe 100644
--- a/drivers/isdn/hisax/sedlbauer.c
+++ b/drivers/isdn/hisax/sedlbauer.c
@@ -51,9 +51,9 @@
extern const char *CardType[];
-const char *Sedlbauer_revision = "$Revision: 1.34.2.6 $";
+static const char *Sedlbauer_revision = "$Revision: 1.34.2.6 $";
-const char *Sedlbauer_Types[] =
+static const char *Sedlbauer_Types[] =
{"None", "speed card/win", "speed star", "speed fax+",
"speed win II / ISDN PC/104", "speed star II", "speed pci",
"speed fax+ pyramid", "speed fax+ pci", "HST Saphir III"};
@@ -394,7 +394,7 @@ sedlbauer_interrupt_isar(int intno, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-void
+static void
release_io_sedlbauer(struct IsdnCardState *cs)
{
int bytecnt = 8;
diff --git a/drivers/isdn/hisax/sportster.c b/drivers/isdn/hisax/sportster.c
index 132840b750c..cdf35dc564c 100644
--- a/drivers/isdn/hisax/sportster.c
+++ b/drivers/isdn/hisax/sportster.c
@@ -19,7 +19,7 @@
#include "isdnl1.h"
extern const char *CardType[];
-const char *sportster_revision = "$Revision: 1.16.2.4 $";
+static const char *sportster_revision = "$Revision: 1.16.2.4 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -132,7 +132,7 @@ sportster_interrupt(int intno, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-void
+static void
release_io_sportster(struct IsdnCardState *cs)
{
int i, adr;
@@ -144,7 +144,7 @@ release_io_sportster(struct IsdnCardState *cs)
}
}
-void
+static void
reset_sportster(struct IsdnCardState *cs)
{
cs->hw.spt.res_irq |= SPORTSTER_RESET; /* Reset On */
diff --git a/drivers/isdn/hisax/st5481.h b/drivers/isdn/hisax/st5481.h
index e8177b017b1..0fda5c89429 100644
--- a/drivers/isdn/hisax/st5481.h
+++ b/drivers/isdn/hisax/st5481.h
@@ -450,12 +450,8 @@ int st5481_setup_isocpipes(struct urb* urb[2], struct usb_device *dev,
usb_complete_t complete, void *context);
void st5481_release_isocpipes(struct urb* urb[2]);
-int st5481_isoc_flatten(struct urb *urb);
void st5481_usb_pipe_reset(struct st5481_adapter *adapter,
u_char pipe, ctrl_complete_t complete, void *context);
-void st5481_usb_ctrl_msg(struct st5481_adapter *adapter,
- u8 request, u8 requesttype, u16 value, u16 index,
- ctrl_complete_t complete, void *context);
void st5481_usb_device_ctrl_msg(struct st5481_adapter *adapter,
u8 request, u16 value,
ctrl_complete_t complete, void *context);
diff --git a/drivers/isdn/hisax/st5481_hdlc.c b/drivers/isdn/hisax/st5481_hdlc.c
deleted file mode 100644
index 680f42e9a99..00000000000
--- a/drivers/isdn/hisax/st5481_hdlc.c
+++ /dev/null
@@ -1,580 +0,0 @@
-/*
- * Driver for ST5481 USB ISDN modem
- *
- * Author Frode Isaksen
- * Copyright 2001 by Frode Isaksen <fisaksen@bewan.com>
- * 2001 by Kai Germaschewski <kai.germaschewski@gmx.de>
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#include <linux/crc-ccitt.h>
-#include "st5481_hdlc.h"
-
-
-enum {
- HDLC_FAST_IDLE,HDLC_GET_FLAG_B0,HDLC_GETFLAG_B1A6,HDLC_GETFLAG_B7,
- HDLC_GET_DATA,HDLC_FAST_FLAG
-};
-
-enum {
- HDLC_SEND_DATA,HDLC_SEND_CRC1,HDLC_SEND_FAST_FLAG,
- HDLC_SEND_FIRST_FLAG,HDLC_SEND_CRC2,HDLC_SEND_CLOSING_FLAG,
- HDLC_SEND_IDLE1,HDLC_SEND_FAST_IDLE,HDLC_SENDFLAG_B0,
- HDLC_SENDFLAG_B1A6,HDLC_SENDFLAG_B7,STOPPED
-};
-
-void
-hdlc_rcv_init(struct hdlc_vars *hdlc, int do_adapt56)
-{
- hdlc->bit_shift = 0;
- hdlc->hdlc_bits1 = 0;
- hdlc->data_bits = 0;
- hdlc->ffbit_shift = 0;
- hdlc->data_received = 0;
- hdlc->state = HDLC_GET_DATA;
- hdlc->do_adapt56 = do_adapt56;
- hdlc->dchannel = 0;
- hdlc->crc = 0;
- hdlc->cbin = 0;
- hdlc->shift_reg = 0;
- hdlc->ffvalue = 0;
- hdlc->dstpos = 0;
-}
-
-void
-hdlc_out_init(struct hdlc_vars *hdlc, int is_d_channel, int do_adapt56)
-{
- hdlc->bit_shift = 0;
- hdlc->hdlc_bits1 = 0;
- hdlc->data_bits = 0;
- hdlc->ffbit_shift = 0;
- hdlc->data_received = 0;
- hdlc->do_closing = 0;
- hdlc->ffvalue = 0;
- if (is_d_channel) {
- hdlc->dchannel = 1;
- hdlc->state = HDLC_SEND_FIRST_FLAG;
- } else {
- hdlc->dchannel = 0;
- hdlc->state = HDLC_SEND_FAST_FLAG;
- hdlc->ffvalue = 0x7e;
- }
- hdlc->cbin = 0x7e;
- hdlc->bit_shift = 0;
- if(do_adapt56){
- hdlc->do_adapt56 = 1;
- hdlc->data_bits = 0;
- hdlc->state = HDLC_SENDFLAG_B0;
- } else {
- hdlc->do_adapt56 = 0;
- hdlc->data_bits = 8;
- }
- hdlc->shift_reg = 0;
-}
-
-/*
- hdlc_decode - decodes HDLC frames from a transparent bit stream.
-
- The source buffer is scanned for valid HDLC frames looking for
- flags (01111110) to indicate the start of a frame. If the start of
- the frame is found, the bit stuffing is removed (0 after 5 1's).
- When a new flag is found, the complete frame has been received
- and the CRC is checked.
- If a valid frame is found, the function returns the frame length
- excluding the CRC with the bit HDLC_END_OF_FRAME set.
- If the beginning of a valid frame is found, the function returns
- the length.
- If a framing error is found (too many 1s and not a flag) the function
- returns the length with the bit HDLC_FRAMING_ERROR set.
- If a CRC error is found the function returns the length with the
- bit HDLC_CRC_ERROR set.
- If the frame length exceeds the destination buffer size, the function
- returns the length with the bit HDLC_LENGTH_ERROR set.
-
- src - source buffer
- slen - source buffer length
- count - number of bytes removed (decoded) from the source buffer
- dst _ destination buffer
- dsize - destination buffer size
- returns - number of decoded bytes in the destination buffer and status
- flag.
- */
-int hdlc_decode(struct hdlc_vars *hdlc, const unsigned char *src,
- int slen, int *count, unsigned char *dst, int dsize)
-{
- int status=0;
-
- static const unsigned char fast_flag[]={
- 0x00,0x00,0x00,0x20,0x30,0x38,0x3c,0x3e,0x3f
- };
-
- static const unsigned char fast_flag_value[]={
- 0x00,0x7e,0xfc,0xf9,0xf3,0xe7,0xcf,0x9f,0x3f
- };
-
- static const unsigned char fast_abort[]={
- 0x00,0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff
- };
-
- *count = slen;
-
- while(slen > 0){
- if(hdlc->bit_shift==0){
- hdlc->cbin = *src++;
- slen--;
- hdlc->bit_shift = 8;
- if(hdlc->do_adapt56){
- hdlc->bit_shift --;
- }
- }
-
- switch(hdlc->state){
- case STOPPED:
- return 0;
- case HDLC_FAST_IDLE:
- if(hdlc->cbin == 0xff){
- hdlc->bit_shift = 0;
- break;
- }
- hdlc->state = HDLC_GET_FLAG_B0;
- hdlc->hdlc_bits1 = 0;
- hdlc->bit_shift = 8;
- break;
- case HDLC_GET_FLAG_B0:
- if(!(hdlc->cbin & 0x80)) {
- hdlc->state = HDLC_GETFLAG_B1A6;
- hdlc->hdlc_bits1 = 0;
- } else {
- if(!hdlc->do_adapt56){
- if(++hdlc->hdlc_bits1 >=8 ) if(hdlc->bit_shift==1)
- hdlc->state = HDLC_FAST_IDLE;
- }
- }
- hdlc->cbin<<=1;
- hdlc->bit_shift --;
- break;
- case HDLC_GETFLAG_B1A6:
- if(hdlc->cbin & 0x80){
- hdlc->hdlc_bits1++;
- if(hdlc->hdlc_bits1==6){
- hdlc->state = HDLC_GETFLAG_B7;
- }
- } else {
- hdlc->hdlc_bits1 = 0;
- }
- hdlc->cbin<<=1;
- hdlc->bit_shift --;
- break;
- case HDLC_GETFLAG_B7:
- if(hdlc->cbin & 0x80) {
- hdlc->state = HDLC_GET_FLAG_B0;
- } else {
- hdlc->state = HDLC_GET_DATA;
- hdlc->crc = 0xffff;
- hdlc->shift_reg = 0;
- hdlc->hdlc_bits1 = 0;
- hdlc->data_bits = 0;
- hdlc->data_received = 0;
- }
- hdlc->cbin<<=1;
- hdlc->bit_shift --;
- break;
- case HDLC_GET_DATA:
- if(hdlc->cbin & 0x80){
- hdlc->hdlc_bits1++;
- switch(hdlc->hdlc_bits1){
- case 6:
- break;
- case 7:
- if(hdlc->data_received) {
- // bad frame
- status = -HDLC_FRAMING_ERROR;
- }
- if(!hdlc->do_adapt56){
- if(hdlc->cbin==fast_abort[hdlc->bit_shift+1]){
- hdlc->state = HDLC_FAST_IDLE;
- hdlc->bit_shift=1;
- break;
- }
- } else {
- hdlc->state = HDLC_GET_FLAG_B0;
- }
- break;
- default:
- hdlc->shift_reg>>=1;
- hdlc->shift_reg |= 0x80;
- hdlc->data_bits++;
- break;
- }
- } else {
- switch(hdlc->hdlc_bits1){
- case 5:
- break;
- case 6:
- if(hdlc->data_received){
- if (hdlc->dstpos < 2) {
- status = -HDLC_FRAMING_ERROR;
- } else if (hdlc->crc != 0xf0b8){
- // crc error
- status = -HDLC_CRC_ERROR;
- } else {
- // remove CRC
- hdlc->dstpos -= 2;
- // good frame
- status = hdlc->dstpos;
- }
- }
- hdlc->crc = 0xffff;
- hdlc->shift_reg = 0;
- hdlc->data_bits = 0;
- if(!hdlc->do_adapt56){
- if(hdlc->cbin==fast_flag[hdlc->bit_shift]){
- hdlc->ffvalue = fast_flag_value[hdlc->bit_shift];
- hdlc->state = HDLC_FAST_FLAG;
- hdlc->ffbit_shift = hdlc->bit_shift;
- hdlc->bit_shift = 1;
- } else {
- hdlc->state = HDLC_GET_DATA;
- hdlc->data_received = 0;
- }
- } else {
- hdlc->state = HDLC_GET_DATA;
- hdlc->data_received = 0;
- }
- break;
- default:
- hdlc->shift_reg>>=1;
- hdlc->data_bits++;
- break;
- }
- hdlc->hdlc_bits1 = 0;
- }
- if (status) {
- hdlc->dstpos = 0;
- *count -= slen;
- hdlc->cbin <<= 1;
- hdlc->bit_shift--;
- return status;
- }
- if(hdlc->data_bits==8){
- hdlc->data_bits = 0;
- hdlc->data_received = 1;
- hdlc->crc = crc_ccitt_byte(hdlc->crc, hdlc->shift_reg);
-
- // good byte received
- if (dsize--) {
- dst[hdlc->dstpos++] = hdlc->shift_reg;
- } else {
- // frame too long
- status = -HDLC_LENGTH_ERROR;
- hdlc->dstpos = 0;
- }
- }
- hdlc->cbin <<= 1;
- hdlc->bit_shift--;
- break;
- case HDLC_FAST_FLAG:
- if(hdlc->cbin==hdlc->ffvalue){
- hdlc->bit_shift = 0;
- break;
- } else {
- if(hdlc->cbin == 0xff){
- hdlc->state = HDLC_FAST_IDLE;
- hdlc->bit_shift=0;
- } else if(hdlc->ffbit_shift==8){
- hdlc->state = HDLC_GETFLAG_B7;
- break;
- } else {
- hdlc->shift_reg = fast_abort[hdlc->ffbit_shift-1];
- hdlc->hdlc_bits1 = hdlc->ffbit_shift-2;
- if(hdlc->hdlc_bits1<0)hdlc->hdlc_bits1 = 0;
- hdlc->data_bits = hdlc->ffbit_shift-1;
- hdlc->state = HDLC_GET_DATA;
- hdlc->data_received = 0;
- }
- }
- break;
- default:
- break;
- }
- }
- *count -= slen;
- return 0;
-}
-
-/*
- hdlc_encode - encodes HDLC frames to a transparent bit stream.
-
- The bit stream starts with a beginning flag (01111110). After
- that each byte is added to the bit stream with bit stuffing added
- (0 after 5 1's).
- When the last byte has been removed from the source buffer, the
- CRC (2 bytes is added) and the frame terminates with the ending flag.
- For the dchannel, the idle character (all 1's) is also added at the end.
- If this function is called with empty source buffer (slen=0), flags or
- idle character will be generated.
-
- src - source buffer
- slen - source buffer length
- count - number of bytes removed (encoded) from source buffer
- dst _ destination buffer
- dsize - destination buffer size
- returns - number of encoded bytes in the destination buffer
-*/
-int hdlc_encode(struct hdlc_vars *hdlc, const unsigned char *src,
- unsigned short slen, int *count,
- unsigned char *dst, int dsize)
-{
- static const unsigned char xfast_flag_value[] = {
- 0x7e,0x3f,0x9f,0xcf,0xe7,0xf3,0xf9,0xfc,0x7e
- };
-
- int len = 0;
-
- *count = slen;
-
- while (dsize > 0) {
- if(hdlc->bit_shift==0){
- if(slen && !hdlc->do_closing){
- hdlc->shift_reg = *src++;
- slen--;
- if (slen == 0)
- hdlc->do_closing = 1; /* closing sequence, CRC + flag(s) */
- hdlc->bit_shift = 8;
- } else {
- if(hdlc->state == HDLC_SEND_DATA){
- if(hdlc->data_received){
- hdlc->state = HDLC_SEND_CRC1;
- hdlc->crc ^= 0xffff;
- hdlc->bit_shift = 8;
- hdlc->shift_reg = hdlc->crc & 0xff;
- } else if(!hdlc->do_adapt56){
- hdlc->state = HDLC_SEND_FAST_FLAG;
- } else {
- hdlc->state = HDLC_SENDFLAG_B0;
- }
- }
-
- }
- }
-
- switch(hdlc->state){
- case STOPPED:
- while (dsize--)
- *dst++ = 0xff;
-
- return dsize;
- case HDLC_SEND_FAST_FLAG:
- hdlc->do_closing = 0;
- if(slen == 0){
- *dst++ = hdlc->ffvalue;
- len++;
- dsize--;
- break;
- }
- if(hdlc->bit_shift==8){
- hdlc->cbin = hdlc->ffvalue>>(8-hdlc->data_bits);
- hdlc->state = HDLC_SEND_DATA;
- hdlc->crc = 0xffff;
- hdlc->hdlc_bits1 = 0;
- hdlc->data_received = 1;
- }
- break;
- case HDLC_SENDFLAG_B0:
- hdlc->do_closing = 0;
- hdlc->cbin <<= 1;
- hdlc->data_bits++;
- hdlc->hdlc_bits1 = 0;
- hdlc->state = HDLC_SENDFLAG_B1A6;
- break;
- case HDLC_SENDFLAG_B1A6:
- hdlc->cbin <<= 1;
- hdlc->data_bits++;
- hdlc->cbin++;
- if(++hdlc->hdlc_bits1 == 6)
- hdlc->state = HDLC_SENDFLAG_B7;
- break;
- case HDLC_SENDFLAG_B7:
- hdlc->cbin <<= 1;
- hdlc->data_bits++;
- if(slen == 0){
- hdlc->state = HDLC_SENDFLAG_B0;
- break;
- }
- if(hdlc->bit_shift==8){
- hdlc->state = HDLC_SEND_DATA;
- hdlc->crc = 0xffff;
- hdlc->hdlc_bits1 = 0;
- hdlc->data_received = 1;
- }
- break;
- case HDLC_SEND_FIRST_FLAG:
- hdlc->data_received = 1;
- if(hdlc->data_bits==8){
- hdlc->state = HDLC_SEND_DATA;
- hdlc->crc = 0xffff;
- hdlc->hdlc_bits1 = 0;
- break;
- }
- hdlc->cbin <<= 1;
- hdlc->data_bits++;
- if(hdlc->shift_reg & 0x01)
- hdlc->cbin++;
- hdlc->shift_reg >>= 1;
- hdlc->bit_shift--;
- if(hdlc->bit_shift==0){
- hdlc->state = HDLC_SEND_DATA;
- hdlc->crc = 0xffff;
- hdlc->hdlc_bits1 = 0;
- }
- break;
- case HDLC_SEND_DATA:
- hdlc->cbin <<= 1;
- hdlc->data_bits++;
- if(hdlc->hdlc_bits1 == 5){
- hdlc->hdlc_bits1 = 0;
- break;
- }
- if(hdlc->bit_shift==8){
- hdlc->crc = crc_ccitt_byte(hdlc->crc, hdlc->shift_reg);
- }
- if(hdlc->shift_reg & 0x01){
- hdlc->hdlc_bits1++;
- hdlc->cbin++;
- hdlc->shift_reg >>= 1;
- hdlc->bit_shift--;
- } else {
- hdlc->hdlc_bits1 = 0;
- hdlc->shift_reg >>= 1;
- hdlc->bit_shift--;
- }
- break;
- case HDLC_SEND_CRC1:
- hdlc->cbin <<= 1;
- hdlc->data_bits++;
- if(hdlc->hdlc_bits1 == 5){
- hdlc->hdlc_bits1 = 0;
- break;
- }
- if(hdlc->shift_reg & 0x01){
- hdlc->hdlc_bits1++;
- hdlc->cbin++;
- hdlc->shift_reg >>= 1;
- hdlc->bit_shift--;
- } else {
- hdlc->hdlc_bits1 = 0;
- hdlc->shift_reg >>= 1;
- hdlc->bit_shift--;
- }
- if(hdlc->bit_shift==0){
- hdlc->shift_reg = (hdlc->crc >> 8);
- hdlc->state = HDLC_SEND_CRC2;
- hdlc->bit_shift = 8;
- }
- break;
- case HDLC_SEND_CRC2:
- hdlc->cbin <<= 1;
- hdlc->data_bits++;
- if(hdlc->hdlc_bits1 == 5){
- hdlc->hdlc_bits1 = 0;
- break;
- }
- if(hdlc->shift_reg & 0x01){
- hdlc->hdlc_bits1++;
- hdlc->cbin++;
- hdlc->shift_reg >>= 1;
- hdlc->bit_shift--;
- } else {
- hdlc->hdlc_bits1 = 0;
- hdlc->shift_reg >>= 1;
- hdlc->bit_shift--;
- }
- if(hdlc->bit_shift==0){
- hdlc->shift_reg = 0x7e;
- hdlc->state = HDLC_SEND_CLOSING_FLAG;
- hdlc->bit_shift = 8;
- }
- break;
- case HDLC_SEND_CLOSING_FLAG:
- hdlc->cbin <<= 1;
- hdlc->data_bits++;
- if(hdlc->hdlc_bits1 == 5){
- hdlc->hdlc_bits1 = 0;
- break;
- }
- if(hdlc->shift_reg & 0x01){
- hdlc->cbin++;
- }
- hdlc->shift_reg >>= 1;
- hdlc->bit_shift--;
- if(hdlc->bit_shift==0){
- hdlc->ffvalue = xfast_flag_value[hdlc->data_bits];
- if(hdlc->dchannel){
- hdlc->ffvalue = 0x7e;
- hdlc->state = HDLC_SEND_IDLE1;
- hdlc->bit_shift = 8-hdlc->data_bits;
- if(hdlc->bit_shift==0)
- hdlc->state = HDLC_SEND_FAST_IDLE;
- } else {
- if(!hdlc->do_adapt56){
- hdlc->state = HDLC_SEND_FAST_FLAG;
- hdlc->data_received = 0;
- } else {
- hdlc->state = HDLC_SENDFLAG_B0;
- hdlc->data_received = 0;
- }
- // Finished with this frame, send flags
- if (dsize > 1) dsize = 1;
- }
- }
- break;
- case HDLC_SEND_IDLE1:
- hdlc->do_closing = 0;
- hdlc->cbin <<= 1;
- hdlc->cbin++;
- hdlc->data_bits++;
- hdlc->bit_shift--;
- if(hdlc->bit_shift==0){
- hdlc->state = HDLC_SEND_FAST_IDLE;
- hdlc->bit_shift = 0;
- }
- break;
- case HDLC_SEND_FAST_IDLE:
- hdlc->do_closing = 0;
- hdlc->cbin = 0xff;
- hdlc->data_bits = 8;
- if(hdlc->bit_shift == 8){
- hdlc->cbin = 0x7e;
- hdlc->state = HDLC_SEND_FIRST_FLAG;
- } else {
- *dst++ = hdlc->cbin;
- hdlc->bit_shift = hdlc->data_bits = 0;
- len++;
- dsize = 0;
- }
- break;
- default:
- break;
- }
- if(hdlc->do_adapt56){
- if(hdlc->data_bits==7){
- hdlc->cbin <<= 1;
- hdlc->cbin++;
- hdlc->data_bits++;
- }
- }
- if(hdlc->data_bits==8){
- *dst++ = hdlc->cbin;
- hdlc->data_bits = 0;
- len++;
- dsize--;
- }
- }
- *count -= slen;
-
- return len;
-}
-
diff --git a/drivers/isdn/hisax/st5481_hdlc.h b/drivers/isdn/hisax/st5481_hdlc.h
deleted file mode 100644
index 495432f0f6b..00000000000
--- a/drivers/isdn/hisax/st5481_hdlc.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Driver for ST5481 USB ISDN modem
- *
- * Author Frode Isaksen
- * Copyright 2001 by Frode Isaksen <fisaksen@bewan.com>
- * 2001 by Kai Germaschewski <kai.germaschewski@gmx.de>
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#ifndef __ST5481_HDLC_H__
-#define __ST5481_HDLC_H__
-
-struct hdlc_vars {
- int bit_shift;
- int hdlc_bits1;
- int data_bits;
- int ffbit_shift; // encoding only
- int state;
- int dstpos;
-
- int data_received:1; // set if transferring data
- int dchannel:1; // set if D channel (send idle instead of flags)
- int do_adapt56:1; // set if 56K adaptation
- int do_closing:1; // set if in closing phase (need to send CRC + flag
-
- unsigned short crc;
-
- unsigned char cbin;
- unsigned char shift_reg;
- unsigned char ffvalue;
-
-};
-
-
-/*
- The return value from hdlc_decode is
- the frame length, 0 if no complete frame was decoded,
- or a negative error number
-*/
-
-#define HDLC_FRAMING_ERROR 1
-#define HDLC_CRC_ERROR 2
-#define HDLC_LENGTH_ERROR 3
-
-void
-hdlc_rcv_init(struct hdlc_vars *hdlc, int do_adapt56);
-
-int
-hdlc_decode(struct hdlc_vars *hdlc, const unsigned char *src, int slen,int *count,
- unsigned char *dst, int dsize);
-
-void
-hdlc_out_init(struct hdlc_vars *hdlc,int is_d_channel,int do_adapt56);
-
-int
-hdlc_encode(struct hdlc_vars *hdlc,const unsigned char *src,unsigned short slen,int *count,
- unsigned char *dst,int dsize);
-
-#endif
diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c
index 2369180b1cb..ab62223297a 100644
--- a/drivers/isdn/hisax/st5481_usb.c
+++ b/drivers/isdn/hisax/st5481_usb.c
@@ -15,6 +15,8 @@
#include <linux/slab.h>
#include "st5481.h"
+static int st5481_isoc_flatten(struct urb *urb);
+
/* ======================================================================
* control pipe
*/
@@ -55,9 +57,9 @@ static void usb_next_ctrl_msg(struct urb *urb,
* Asynchronous endpoint 0 request (async version of usb_control_msg).
* The request will be queued up in a FIFO if the endpoint is busy.
*/
-void usb_ctrl_msg(struct st5481_adapter *adapter,
- u8 request, u8 requesttype, u16 value, u16 index,
- ctrl_complete_t complete, void *context)
+static void usb_ctrl_msg(struct st5481_adapter *adapter,
+ u8 request, u8 requesttype, u16 value, u16 index,
+ ctrl_complete_t complete, void *context)
{
struct st5481_ctrl *ctrl = &adapter->ctrl;
int w_index;
@@ -571,7 +573,7 @@ void st5481_release_in(struct st5481_in *in)
* Make the transfer_buffer contiguous by
* copying from the iso descriptors if necessary.
*/
-int st5481_isoc_flatten(struct urb *urb)
+static int st5481_isoc_flatten(struct urb *urb)
{
struct usb_iso_packet_descriptor *pipd,*pend;
unsigned char *src,*dst;
diff --git a/drivers/isdn/hisax/tei.c b/drivers/isdn/hisax/tei.c
index 082726db398..ceb0df92fd3 100644
--- a/drivers/isdn/hisax/tei.c
+++ b/drivers/isdn/hisax/tei.c
@@ -74,7 +74,7 @@ static char *strTeiEvent[] =
"EV_T202",
};
-unsigned int
+static unsigned int
random_ri(void)
{
unsigned int x;
diff --git a/drivers/isdn/hisax/teleint.c b/drivers/isdn/hisax/teleint.c
index ef8984c5f1f..a2b1816af37 100644
--- a/drivers/isdn/hisax/teleint.c
+++ b/drivers/isdn/hisax/teleint.c
@@ -18,7 +18,7 @@
extern const char *CardType[];
-const char *TeleInt_revision = "$Revision: 1.16.2.5 $";
+static const char *TeleInt_revision = "$Revision: 1.16.2.5 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -203,7 +203,7 @@ TeleInt_Timer(struct IsdnCardState *cs)
add_timer(&cs->hw.hfc.timer);
}
-void
+static void
release_io_TeleInt(struct IsdnCardState *cs)
{
del_timer(&cs->hw.hfc.timer);
diff --git a/drivers/isdn/hisax/teles0.c b/drivers/isdn/hisax/teles0.c
index 5ec5ec3e1ea..2b7df8f9823 100644
--- a/drivers/isdn/hisax/teles0.c
+++ b/drivers/isdn/hisax/teles0.c
@@ -23,7 +23,7 @@
extern const char *CardType[];
-const char *teles0_revision = "$Revision: 2.15.2.4 $";
+static const char *teles0_revision = "$Revision: 2.15.2.4 $";
#define TELES_IOMEM_SIZE 0x400
#define byteout(addr,val) outb(val,addr)
@@ -183,7 +183,7 @@ teles0_interrupt(int intno, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-void
+static void
release_io_teles0(struct IsdnCardState *cs)
{
if (cs->hw.teles0.cfg_reg)
diff --git a/drivers/isdn/hisax/teles3.c b/drivers/isdn/hisax/teles3.c
index c5b1f65f727..adeaad62d35 100644
--- a/drivers/isdn/hisax/teles3.c
+++ b/drivers/isdn/hisax/teles3.c
@@ -21,7 +21,7 @@
#include "isdnl1.h"
extern const char *CardType[];
-const char *teles3_revision = "$Revision: 2.19.2.4 $";
+static const char *teles3_revision = "$Revision: 2.19.2.4 $";
#define byteout(addr,val) outb(val,addr)
#define bytein(addr) inb(addr)
@@ -154,7 +154,7 @@ release_ioregs(struct IsdnCardState *cs, int mask)
release_region(cs->hw.teles3.hscx[1] + 32, 32);
}
-void
+static void
release_io_teles3(struct IsdnCardState *cs)
{
if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
diff --git a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c
index 0661c6c31ad..e2bb4fd8e25 100644
--- a/drivers/isdn/hisax/telespci.c
+++ b/drivers/isdn/hisax/telespci.c
@@ -21,7 +21,7 @@
#include <linux/pci.h>
extern const char *CardType[];
-const char *telespci_revision = "$Revision: 2.23.2.3 $";
+static const char *telespci_revision = "$Revision: 2.23.2.3 $";
#define ZORAN_PO_RQ_PEN 0x02000000
#define ZORAN_PO_WR 0x00800000
@@ -257,7 +257,7 @@ telespci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-void
+static void
release_io_telespci(struct IsdnCardState *cs)
{
iounmap(cs->hw.teles0.membase);
diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c
index d2b6b8e7298..7baf8e48847 100644
--- a/drivers/isdn/hisax/w6692.c
+++ b/drivers/isdn/hisax/w6692.c
@@ -41,7 +41,7 @@ static const PCI_ENTRY id_list[] =
extern const char *CardType[];
-const char *w6692_revision = "$Revision: 1.18.2.4 $";
+static const char *w6692_revision = "$Revision: 1.18.2.4 $";
#define DBUSY_TIMER_VALUE 80
@@ -880,7 +880,7 @@ setstack_w6692(struct PStack *st, struct BCState *bcs)
return (0);
}
-void resetW6692(struct IsdnCardState *cs)
+static void resetW6692(struct IsdnCardState *cs)
{
cs->writeW6692(cs, W_D_CTL, W_D_CTL_SRST);
mdelay(10);
@@ -902,7 +902,7 @@ void resetW6692(struct IsdnCardState *cs)
}
}
-void __init initW6692(struct IsdnCardState *cs, int part)
+static void __init initW6692(struct IsdnCardState *cs, int part)
{
if (part & 1) {
cs->setstack_d = setstack_W6692;
diff --git a/drivers/isdn/i4l/isdn_audio.c b/drivers/isdn/i4l/isdn_audio.c
index 5350836a4f9..2cc56d6a9fa 100644
--- a/drivers/isdn/i4l/isdn_audio.c
+++ b/drivers/isdn/i4l/isdn_audio.c
@@ -392,16 +392,6 @@ isdn_audio_adpcm2xlaw(adpcm_state * s, int fmt, unsigned char *in,
}
int
-isdn_audio_2adpcm_flush(adpcm_state * s, unsigned char *out)
-{
- int olen = 0;
-
- if (s->nleft)
- isdn_audio_put_bits(0, 8 - s->nleft, s, &out, &olen);
- return olen;
-}
-
-int
isdn_audio_xlaw2adpcm(adpcm_state * s, int fmt, unsigned char *in,
unsigned char *out, int len)
{
diff --git a/drivers/isdn/i4l/isdn_audio.h b/drivers/isdn/i4l/isdn_audio.h
index 5a977b21dcf..013c3582e0d 100644
--- a/drivers/isdn/i4l/isdn_audio.h
+++ b/drivers/isdn/i4l/isdn_audio.h
@@ -35,7 +35,6 @@ extern void isdn_audio_alaw2ulaw(unsigned char *, unsigned long);
extern adpcm_state *isdn_audio_adpcm_init(adpcm_state *, int);
extern int isdn_audio_adpcm2xlaw(adpcm_state *, int, unsigned char *, unsigned char *, int);
extern int isdn_audio_xlaw2adpcm(adpcm_state *, int, unsigned char *, unsigned char *, int);
-extern int isdn_audio_2adpcm_flush(adpcm_state * s, unsigned char *out);
extern void isdn_audio_calc_dtmf(modem_info *, unsigned char *, int, int);
extern void isdn_audio_eval_dtmf(modem_info *);
dtmf_state *isdn_audio_dtmf_init(dtmf_state *);
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index c406df6f268..eebcb0b97f0 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -67,7 +67,7 @@ static isdn_divert_if *divert_if; /* = NULL */
static int isdn_writebuf_stub(int, int, const u_char __user *, int);
static void set_global_features(void);
static int isdn_wildmat(char *s, char *p);
-
+static int isdn_add_channels(isdn_driver_t *d, int drvidx, int n, int adding);
static inline void
isdn_lock_driver(isdn_driver_t *drv)
@@ -388,7 +388,7 @@ isdn_all_eaz(int di, int ch)
*/
#include <linux/isdn/capicmd.h>
-int
+static int
isdn_capi_rec_hl_msg(capi_msg *cm) {
int di;
@@ -1923,7 +1923,7 @@ isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb)
return ret;
}
-int
+static int
isdn_add_channels(isdn_driver_t *d, int drvidx, int n, int adding)
{
int j, k, m;
diff --git a/drivers/isdn/i4l/isdn_common.h b/drivers/isdn/i4l/isdn_common.h
index 808135c427a..e27e9c3a81e 100644
--- a/drivers/isdn/i4l/isdn_common.h
+++ b/drivers/isdn/i4l/isdn_common.h
@@ -41,7 +41,6 @@ extern int isdn_get_free_channel(int, int, int, int, int, char *);
extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *);
extern int register_isdn(isdn_if * i);
extern int isdn_msncmp( const char *, const char *);
-extern int isdn_add_channels(isdn_driver_t *, int, int, int);
#if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
extern void isdn_dumppkt(char *, u_char *, int, int);
#endif
diff --git a/drivers/isdn/i4l/isdn_concap.c b/drivers/isdn/i4l/isdn_concap.c
index 83a4f5382bc..0193b6f7c70 100644
--- a/drivers/isdn/i4l/isdn_concap.c
+++ b/drivers/isdn/i4l/isdn_concap.c
@@ -39,7 +39,7 @@
*/
-int isdn_concap_dl_data_req(struct concap_proto *concap, struct sk_buff *skb)
+static int isdn_concap_dl_data_req(struct concap_proto *concap, struct sk_buff *skb)
{
struct net_device *ndev = concap -> net_dev;
isdn_net_dev *nd = ((isdn_net_local *) ndev->priv)->netdev;
@@ -58,7 +58,7 @@ int isdn_concap_dl_data_req(struct concap_proto *concap, struct sk_buff *skb)
}
-int isdn_concap_dl_connect_req(struct concap_proto *concap)
+static int isdn_concap_dl_connect_req(struct concap_proto *concap)
{
struct net_device *ndev = concap -> net_dev;
isdn_net_local *lp = (isdn_net_local *) ndev->priv;
@@ -71,7 +71,7 @@ int isdn_concap_dl_connect_req(struct concap_proto *concap)
return ret;
}
-int isdn_concap_dl_disconn_req(struct concap_proto *concap)
+static int isdn_concap_dl_disconn_req(struct concap_proto *concap)
{
IX25DEBUG( "isdn_concap_dl_disconn_req: %s \n", concap -> net_dev -> name);
@@ -85,15 +85,6 @@ struct concap_device_ops isdn_concap_reliable_dl_dops = {
&isdn_concap_dl_disconn_req
};
-struct concap_device_ops isdn_concap_demand_dial_dops = {
- NULL, /* set this first entry to something like &isdn_net_start_xmit,
- but the entry part of the current isdn_net_start_xmit must be
- separated first. */
- /* no connection control for demand dial semantics */
- NULL,
- NULL,
-};
-
/* The following should better go into a dedicated source file such that
this sourcefile does not need to include any protocol specific header
files. For now:
diff --git a/drivers/isdn/i4l/isdn_concap.h b/drivers/isdn/i4l/isdn_concap.h
index 306eb180438..6ac7e0445ea 100644
--- a/drivers/isdn/i4l/isdn_concap.h
+++ b/drivers/isdn/i4l/isdn_concap.h
@@ -8,7 +8,6 @@
*/
extern struct concap_device_ops isdn_concap_reliable_dl_dops;
-extern struct concap_device_ops isdn_concap_demand_dial_dops;
extern struct concap_proto * isdn_concap_new( int );
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
index e2b790e3451..f30e8e63ae0 100644
--- a/drivers/isdn/i4l/isdn_net.c
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -176,7 +176,7 @@ static __inline__ void isdn_net_zero_frame_cnt(isdn_net_local *lp)
/* Prototypes */
-int isdn_net_force_dial_lp(isdn_net_local *);
+static int isdn_net_force_dial_lp(isdn_net_local *);
static int isdn_net_start_xmit(struct sk_buff *, struct net_device *);
static void isdn_net_ciscohdlck_connected(isdn_net_local *lp);
@@ -312,7 +312,7 @@ isdn_net_unbind_channel(isdn_net_local * lp)
* Since this function is called every second, simply reset the
* byte-counter of the interface after copying it to the cps-variable.
*/
-unsigned long last_jiffies = -HZ;
+static unsigned long last_jiffies = -HZ;
void
isdn_net_autohup(void)
@@ -1131,7 +1131,7 @@ isdn_net_adjust_hdr(struct sk_buff *skb, struct net_device *dev)
}
-void isdn_net_tx_timeout(struct net_device * ndev)
+static void isdn_net_tx_timeout(struct net_device * ndev)
{
isdn_net_local *lp = (isdn_net_local *) ndev->priv;
@@ -1424,7 +1424,7 @@ isdn_net_ciscohdlck_alloc_skb(isdn_net_local *lp, int len)
}
/* cisco hdlck device private ioctls */
-int
+static int
isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
isdn_net_local *lp = (isdn_net_local *) dev->priv;
@@ -2461,7 +2461,7 @@ isdn_net_findif(char *name)
* This is called from the userlevel-routine below or
* from isdn_net_start_xmit().
*/
-int
+static int
isdn_net_force_dial_lp(isdn_net_local * lp)
{
if ((!(lp->flags & ISDN_NET_CONNECTED)) && !lp->dialstate) {
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index e21007eca0f..ad5aa38fb5a 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -273,7 +273,7 @@ isdn_tty_rcv_skb(int i, int di, int channel, struct sk_buff *skb)
return 1;
}
-void
+static void
isdn_tty_cleanup_xmit(modem_info * info)
{
skb_queue_purge(&info->xmit_queue);
@@ -560,7 +560,7 @@ isdn_tty_modem_ncarrier(modem_info * info)
/*
* return the usage calculated by si and layer 2 protocol
*/
-int
+static int
isdn_calc_usage(int si, int l2)
{
int usg = ISDN_USAGE_MODEM;
diff --git a/drivers/isdn/i4l/isdn_tty.h b/drivers/isdn/i4l/isdn_tty.h
index 2423a7ff0cc..9f0fa9501f4 100644
--- a/drivers/isdn/i4l/isdn_tty.h
+++ b/drivers/isdn/i4l/isdn_tty.h
@@ -109,7 +109,6 @@ extern int isdn_tty_modem_init(void);
extern void isdn_tty_exit(void);
extern void isdn_tty_readmodem(void);
extern int isdn_tty_find_icall(int, int, setup_parm *);
-extern void isdn_tty_cleanup_xmit(modem_info *);
extern int isdn_tty_stat_callback(int, isdn_ctrl *);
extern int isdn_tty_rcv_skb(int, int, int, struct sk_buff *);
extern int isdn_tty_capi_facility(capi_msg *cm);
diff --git a/drivers/isdn/i4l/isdn_ttyfax.c b/drivers/isdn/i4l/isdn_ttyfax.c
index ce2c3ef92e4..a943d078bac 100644
--- a/drivers/isdn/i4l/isdn_ttyfax.c
+++ b/drivers/isdn/i4l/isdn_ttyfax.c
@@ -148,7 +148,7 @@ isdn_tty_fax_modem_result(int code, modem_info * info)
}
}
-int
+static int
isdn_tty_fax_command1(modem_info * info, isdn_ctrl * c)
{
static char *msg[] =
@@ -316,7 +316,7 @@ isdn_tty_fax_bitorder(modem_info * info, struct sk_buff *skb)
* Parse AT+F.. FAX class 1 commands
*/
-int
+static int
isdn_tty_cmd_FCLASS1(char **p, modem_info * info)
{
static char *cmd[] =
@@ -408,7 +408,7 @@ isdn_tty_cmd_FCLASS1(char **p, modem_info * info)
* Parse AT+F.. FAX class 2 commands
*/
-int
+static int
isdn_tty_cmd_FCLASS2(char **p, modem_info * info)
{
atemu *m = &info->emu;
diff --git a/drivers/isdn/i4l/isdn_x25iface.c b/drivers/isdn/i4l/isdn_x25iface.c
index 4ab7600cf9c..edf14a2aa3c 100644
--- a/drivers/isdn/i4l/isdn_x25iface.c
+++ b/drivers/isdn/i4l/isdn_x25iface.c
@@ -40,15 +40,15 @@ typedef struct isdn_x25iface_proto_data {
/* is now in header file (extern): struct concap_proto * isdn_x25iface_proto_new(void); */
-void isdn_x25iface_proto_del( struct concap_proto * );
-int isdn_x25iface_proto_close( struct concap_proto * );
-int isdn_x25iface_proto_restart( struct concap_proto *,
- struct net_device *,
- struct concap_device_ops *);
-int isdn_x25iface_xmit( struct concap_proto *, struct sk_buff * );
-int isdn_x25iface_receive( struct concap_proto *, struct sk_buff * );
-int isdn_x25iface_connect_ind( struct concap_proto * );
-int isdn_x25iface_disconn_ind( struct concap_proto * );
+static void isdn_x25iface_proto_del( struct concap_proto * );
+static int isdn_x25iface_proto_close( struct concap_proto * );
+static int isdn_x25iface_proto_restart( struct concap_proto *,
+ struct net_device *,
+ struct concap_device_ops *);
+static int isdn_x25iface_xmit( struct concap_proto *, struct sk_buff * );
+static int isdn_x25iface_receive( struct concap_proto *, struct sk_buff * );
+static int isdn_x25iface_connect_ind( struct concap_proto * );
+static int isdn_x25iface_disconn_ind( struct concap_proto * );
static struct concap_proto_ops ix25_pops = {
@@ -102,7 +102,7 @@ struct concap_proto * isdn_x25iface_proto_new(void)
/* close the x25iface encapsulation protocol
*/
-int isdn_x25iface_proto_close(struct concap_proto *cprot){
+static int isdn_x25iface_proto_close(struct concap_proto *cprot){
ix25_pdata_t *tmp;
int ret = 0;
@@ -129,7 +129,7 @@ int isdn_x25iface_proto_close(struct concap_proto *cprot){
/* Delete the x25iface encapsulation protocol instance
*/
-void isdn_x25iface_proto_del(struct concap_proto *cprot){
+static void isdn_x25iface_proto_del(struct concap_proto *cprot){
ix25_pdata_t * tmp;
@@ -158,9 +158,9 @@ void isdn_x25iface_proto_del(struct concap_proto *cprot){
/* (re-)initialize the data structures for x25iface encapsulation
*/
-int isdn_x25iface_proto_restart(struct concap_proto *cprot,
- struct net_device *ndev,
- struct concap_device_ops *dops)
+static int isdn_x25iface_proto_restart(struct concap_proto *cprot,
+ struct net_device *ndev,
+ struct concap_device_ops *dops)
{
ix25_pdata_t * pda = cprot -> proto_data ;
ulong flags;
@@ -187,7 +187,7 @@ int isdn_x25iface_proto_restart(struct concap_proto *cprot,
/* deliver a dl_data frame received from i4l HL driver to the network layer
*/
-int isdn_x25iface_receive(struct concap_proto *cprot, struct sk_buff *skb)
+static int isdn_x25iface_receive(struct concap_proto *cprot, struct sk_buff *skb)
{
IX25DEBUG( "isdn_x25iface_receive %s \n", MY_DEVNAME(cprot->net_dev) );
if ( ( (ix25_pdata_t*) (cprot->proto_data) )
@@ -206,7 +206,7 @@ int isdn_x25iface_receive(struct concap_proto *cprot, struct sk_buff *skb)
/* a connection set up is indicated by lower layer
*/
-int isdn_x25iface_connect_ind(struct concap_proto *cprot)
+static int isdn_x25iface_connect_ind(struct concap_proto *cprot)
{
struct sk_buff * skb = dev_alloc_skb(1);
enum wan_states *state_p
@@ -235,7 +235,7 @@ int isdn_x25iface_connect_ind(struct concap_proto *cprot)
/* a disconnect is indicated by lower layer
*/
-int isdn_x25iface_disconn_ind(struct concap_proto *cprot)
+static int isdn_x25iface_disconn_ind(struct concap_proto *cprot)
{
struct sk_buff *skb;
enum wan_states *state_p
@@ -264,7 +264,7 @@ int isdn_x25iface_disconn_ind(struct concap_proto *cprot)
/* process a frame handed over to us from linux network layer. First byte
semantics as defined in Documentation/networking/x25-iface.txt
*/
-int isdn_x25iface_xmit(struct concap_proto *cprot, struct sk_buff *skb)
+static int isdn_x25iface_xmit(struct concap_proto *cprot, struct sk_buff *skb)
{
unsigned char firstbyte = skb->data[0];
enum wan_states *state = &((ix25_pdata_t*)cprot->proto_data)->state;
diff --git a/drivers/isdn/pcbit/callbacks.c b/drivers/isdn/pcbit/callbacks.c
index 692ec72d1ee..f151f36c825 100644
--- a/drivers/isdn/pcbit/callbacks.c
+++ b/drivers/isdn/pcbit/callbacks.c
@@ -125,23 +125,6 @@ void cb_out_2(struct pcbit_dev * dev, struct pcbit_chan* chan,
/*
- * Disconnect received (actually RELEASE COMPLETE)
- * This means we were not able to establish connection with remote
- * Inform the big boss above
- */
-void cb_out_3(struct pcbit_dev * dev, struct pcbit_chan* chan,
- struct callb_data *data)
-{
- isdn_ctrl ictl;
-
- ictl.command = ISDN_STAT_DHUP;
- ictl.driver=dev->id;
- ictl.arg=chan->id;
- dev->dev_if->statcallb(&ictl);
-}
-
-
-/*
* Incoming call received
* inform user
*/
diff --git a/drivers/isdn/pcbit/callbacks.h b/drivers/isdn/pcbit/callbacks.h
index f510dc56b57..17aa0f54bfc 100644
--- a/drivers/isdn/pcbit/callbacks.h
+++ b/drivers/isdn/pcbit/callbacks.h
@@ -19,9 +19,6 @@ extern void cb_out_1(struct pcbit_dev * dev, struct pcbit_chan* chan,
extern void cb_out_2(struct pcbit_dev * dev, struct pcbit_chan* chan,
struct callb_data *data);
-extern void cb_out_3(struct pcbit_dev * dev, struct pcbit_chan* chan,
- struct callb_data *data);
-
extern void cb_in_1(struct pcbit_dev * dev, struct pcbit_chan* chan,
struct callb_data *data);
extern void cb_in_2(struct pcbit_dev * dev, struct pcbit_chan* chan,
diff --git a/drivers/isdn/pcbit/capi.c b/drivers/isdn/pcbit/capi.c
index 29eb03a8c29..bef321d0e51 100644
--- a/drivers/isdn/pcbit/capi.c
+++ b/drivers/isdn/pcbit/capi.c
@@ -627,16 +627,6 @@ int capi_decode_disc_ind(struct pcbit_chan *chan, struct sk_buff *skb)
return 0;
}
-int capi_decode_disc_conf(struct pcbit_chan *chan, struct sk_buff *skb)
-{
- ushort errcode;
-
- errcode = *((ushort*) skb->data);
- skb_pull(skb, 2);
-
- return errcode;
-}
-
#ifdef DEBUG
int capi_decode_debug_188(u_char *hdr, ushort hdrlen)
{
diff --git a/drivers/isdn/pcbit/capi.h b/drivers/isdn/pcbit/capi.h
index 18e6aa360a8..df8e73c04d7 100644
--- a/drivers/isdn/pcbit/capi.h
+++ b/drivers/isdn/pcbit/capi.h
@@ -54,7 +54,6 @@ extern int capi_tdata_resp(struct pcbit_chan *chan, struct sk_buff ** skb);
/* Connection Termination */
extern int capi_disc_req(ushort callref, struct sk_buff **skb, u_char cause);
-extern int capi_decode_disc_conf(struct pcbit_chan *chan, struct sk_buff *skb);
extern int capi_decode_disc_ind(struct pcbit_chan *chan, struct sk_buff *skb);
extern int capi_disc_resp(struct pcbit_chan *chan, struct sk_buff **skb);
diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c
index e98f9c48c18..5de861f4081 100644
--- a/drivers/isdn/pcbit/drv.c
+++ b/drivers/isdn/pcbit/drv.c
@@ -56,10 +56,10 @@ static char* pcbit_devname[MAX_PCBIT_CARDS] = {
* prototypes
*/
-int pcbit_command(isdn_ctrl* ctl);
-int pcbit_stat(u_char __user * buf, int len, int, int);
-int pcbit_xmit(int driver, int chan, int ack, struct sk_buff *skb);
-int pcbit_writecmd(const u_char __user *, int, int, int);
+static int pcbit_command(isdn_ctrl* ctl);
+static int pcbit_stat(u_char __user * buf, int len, int, int);
+static int pcbit_xmit(int driver, int chan, int ack, struct sk_buff *skb);
+static int pcbit_writecmd(const u_char __user *, int, int, int);
static int set_protocol_running(struct pcbit_dev * dev);
@@ -238,7 +238,7 @@ void pcbit_terminate(int board)
}
#endif
-int pcbit_command(isdn_ctrl* ctl)
+static int pcbit_command(isdn_ctrl* ctl)
{
struct pcbit_dev *dev;
struct pcbit_chan *chan;
@@ -330,7 +330,7 @@ static void pcbit_block_timer(unsigned long data)
}
#endif
-int pcbit_xmit(int driver, int chnum, int ack, struct sk_buff *skb)
+static int pcbit_xmit(int driver, int chnum, int ack, struct sk_buff *skb)
{
ushort hdrlen;
int refnum, len;
@@ -389,7 +389,7 @@ int pcbit_xmit(int driver, int chnum, int ack, struct sk_buff *skb)
return len;
}
-int pcbit_writecmd(const u_char __user *buf, int len, int driver, int channel)
+static int pcbit_writecmd(const u_char __user *buf, int len, int driver, int channel)
{
struct pcbit_dev * dev;
int i, j;
@@ -713,7 +713,7 @@ static char statbuf[STATBUF_LEN];
static int stat_st = 0;
static int stat_end = 0;
-int pcbit_stat(u_char __user *buf, int len, int driver, int channel)
+static int pcbit_stat(u_char __user *buf, int len, int driver, int channel)
{
int stat_count;
stat_count = stat_end - stat_st;
diff --git a/drivers/isdn/sc/Makefile b/drivers/isdn/sc/Makefile
index 9cc474cd0c4..0f2b7d602ac 100644
--- a/drivers/isdn/sc/Makefile
+++ b/drivers/isdn/sc/Makefile
@@ -6,5 +6,5 @@ obj-$(CONFIG_ISDN_DRV_SC) += sc.o
# Multipart objects.
-sc-y := shmem.o init.o debug.o packet.o command.o event.o \
+sc-y := shmem.o init.o packet.o command.o event.o \
ioctl.o interrupt.o message.o timer.o
diff --git a/drivers/isdn/sc/command.c b/drivers/isdn/sc/command.c
index b2c4eac7cef..19f2fcf0ae4 100644
--- a/drivers/isdn/sc/command.c
+++ b/drivers/isdn/sc/command.c
@@ -22,14 +22,14 @@
#include "card.h"
#include "scioc.h"
-int dial(int card, unsigned long channel, setup_parm setup);
-int hangup(int card, unsigned long channel);
-int answer(int card, unsigned long channel);
-int clreaz(int card, unsigned long channel);
-int seteaz(int card, unsigned long channel, char *);
-int setl2(int card, unsigned long arg);
-int setl3(int card, unsigned long arg);
-int acceptb(int card, unsigned long channel);
+static int dial(int card, unsigned long channel, setup_parm setup);
+static int hangup(int card, unsigned long channel);
+static int answer(int card, unsigned long channel);
+static int clreaz(int card, unsigned long channel);
+static int seteaz(int card, unsigned long channel, char *);
+static int setl2(int card, unsigned long arg);
+static int setl3(int card, unsigned long arg);
+static int acceptb(int card, unsigned long channel);
extern int cinst;
extern board *sc_adapter[];
@@ -148,56 +148,6 @@ int command(isdn_ctrl *cmd)
}
/*
- * Confirm our ability to communicate with the board. This test assumes no
- * other message activity is present
- */
-int loopback(int card)
-{
-
- int status;
- static char testmsg[] = "Test Message";
- RspMessage rspmsg;
-
- if(!IS_VALID_CARD(card)) {
- pr_debug("Invalid param: %d is not a valid card id\n", card);
- return -ENODEV;
- }
-
- pr_debug("%s: Sending loopback message\n",
- sc_adapter[card]->devicename);
-
- /*
- * Send the loopback message to confirm that memory transfer is
- * operational
- */
- status = send_and_receive(card, CMPID, cmReqType1,
- cmReqClass0,
- cmReqMsgLpbk,
- 0,
- (unsigned char) strlen(testmsg),
- (unsigned char *)testmsg,
- &rspmsg, SAR_TIMEOUT);
-
-
- if (!status) {
- pr_debug("%s: Loopback message successfully sent\n",
- sc_adapter[card]->devicename);
- if(strcmp(rspmsg.msg_data.byte_array, testmsg)) {
- pr_debug("%s: Loopback return != sent\n",
- sc_adapter[card]->devicename);
- return -EIO;
- }
- return 0;
- }
- else {
- pr_debug("%s: Send loopback message failed\n",
- sc_adapter[card]->devicename);
- return -EIO;
- }
-
-}
-
-/*
* start the onboard firmware
*/
int startproc(int card)
@@ -222,16 +172,10 @@ int startproc(int card)
}
-int loadproc(int card, char *data)
-{
- return -1;
-}
-
-
/*
* Dials the number passed in
*/
-int dial(int card, unsigned long channel, setup_parm setup)
+static int dial(int card, unsigned long channel, setup_parm setup)
{
int status;
char Phone[48];
@@ -261,7 +205,7 @@ int dial(int card, unsigned long channel, setup_parm setup)
/*
* Answer an incoming call
*/
-int answer(int card, unsigned long channel)
+static int answer(int card, unsigned long channel)
{
if(!IS_VALID_CARD(card)) {
pr_debug("Invalid param: %d is not a valid card id\n", card);
@@ -282,7 +226,7 @@ int answer(int card, unsigned long channel)
/*
* Hangup up the call on specified channel
*/
-int hangup(int card, unsigned long channel)
+static int hangup(int card, unsigned long channel)
{
int status;
@@ -305,7 +249,7 @@ int hangup(int card, unsigned long channel)
/*
* Set the layer 2 protocol (X.25, HDLC, Raw)
*/
-int setl2(int card, unsigned long arg)
+static int setl2(int card, unsigned long arg)
{
int status =0;
int protocol,channel;
@@ -340,7 +284,7 @@ int setl2(int card, unsigned long arg)
/*
* Set the layer 3 protocol
*/
-int setl3(int card, unsigned long channel)
+static int setl3(int card, unsigned long channel)
{
int protocol = channel >> 8;
@@ -355,7 +299,7 @@ int setl3(int card, unsigned long channel)
return 0;
}
-int acceptb(int card, unsigned long channel)
+static int acceptb(int card, unsigned long channel)
{
if(!IS_VALID_CARD(card)) {
pr_debug("Invalid param: %d is not a valid card id\n", card);
@@ -374,7 +318,7 @@ int acceptb(int card, unsigned long channel)
return 0;
}
-int clreaz(int card, unsigned long arg)
+static int clreaz(int card, unsigned long arg)
{
if(!IS_VALID_CARD(card)) {
pr_debug("Invalid param: %d is not a valid card id\n", card);
@@ -388,7 +332,7 @@ int clreaz(int card, unsigned long arg)
return 0;
}
-int seteaz(int card, unsigned long arg, char *num)
+static int seteaz(int card, unsigned long arg, char *num)
{
if(!IS_VALID_CARD(card)) {
pr_debug("Invalid param: %d is not a valid card id\n", card);
diff --git a/drivers/isdn/sc/debug.c b/drivers/isdn/sc/debug.c
deleted file mode 100644
index 1a992a75868..00000000000
--- a/drivers/isdn/sc/debug.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/* $Id: debug.c,v 1.5.6.1 2001/09/23 22:24:59 kai Exp $
- *
- * Copyright (C) 1996 SpellCaster Telecommunications Inc.
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * For more information, please contact gpl-info@spellcast.com or write:
- *
- * SpellCaster Telecommunications Inc.
- * 5621 Finch Avenue East, Unit #3
- * Scarborough, Ontario Canada
- * M1B 2T9
- * +1 (416) 297-8565
- * +1 (416) 297-6433 Facsimile
- */
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-
-int dbg_level = 0;
-static char dbg_funcname[255];
-
-void dbg_endfunc(void)
-{
- if (dbg_level) {
- printk("<-- Leaving function %s\n", dbg_funcname);
- strcpy(dbg_funcname, "");
- }
-}
-
-void dbg_func(char *func)
-{
- strcpy(dbg_funcname, func);
- if(dbg_level)
- printk("--> Entering function %s\n", dbg_funcname);
-}
-
-inline void pullphone(char *dn, char *str)
-{
- int i = 0;
-
- while(dn[i] != ',')
- str[i] = dn[i], i++;
- str[i] = 0x0;
-}
diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c
index efefedea37b..40b0df04ed9 100644
--- a/drivers/isdn/sc/init.c
+++ b/drivers/isdn/sc/init.c
@@ -20,9 +20,9 @@ board *sc_adapter[MAX_CARDS];
int cinst;
static char devname[] = "scX";
-const char version[] = "2.0b1";
+static const char version[] = "2.0b1";
-const char *boardname[] = { "DataCommute/BRI", "DataCommute/PRI", "TeleCommute/BRI" };
+static const char *boardname[] = { "DataCommute/BRI", "DataCommute/PRI", "TeleCommute/BRI" };
/* insmod set parameters */
static unsigned int io[] = {0,0,0,0};
@@ -35,26 +35,13 @@ module_param_array(irq, int, NULL, 0);
module_param_array(ram, int, NULL, 0);
module_param(do_reset, bool, 0);
-static int sup_irq[] = { 11, 10, 9, 5, 12, 14, 7, 3, 4, 6 };
-#define MAX_IRQS 10
-
extern irqreturn_t interrupt_handler(int, void *, struct pt_regs *);
extern int sndpkt(int, int, int, struct sk_buff *);
extern int command(isdn_ctrl *);
extern int indicate_status(int, int, ulong, char*);
extern int reset(int);
-int identify_board(unsigned long, unsigned int);
-
-int irq_supported(int irq_x)
-{
- int i;
- for(i=0 ; i < MAX_IRQS ; i++) {
- if(sup_irq[i] == irq_x)
- return 1;
- }
- return 0;
-}
+static int identify_board(unsigned long, unsigned int);
static int __init sc_init(void)
{
@@ -454,7 +441,7 @@ static void __exit sc_exit(void)
pr_info("SpellCaster ISA ISDN Adapter Driver Unloaded.\n");
}
-int identify_board(unsigned long rambase, unsigned int iobase)
+static int identify_board(unsigned long rambase, unsigned int iobase)
{
unsigned int pgport;
unsigned long sig;
diff --git a/drivers/isdn/sc/interrupt.c b/drivers/isdn/sc/interrupt.c
index e5e164aca7f..8631d338d69 100644
--- a/drivers/isdn/sc/interrupt.c
+++ b/drivers/isdn/sc/interrupt.c
@@ -31,7 +31,7 @@ extern void rcvpkt(int, RspMessage *);
extern int cinst;
extern board *sc_adapter[];
-int get_card_from_irq(int irq)
+static int get_card_from_irq(int irq)
{
int i;
diff --git a/drivers/isdn/sc/ioctl.c b/drivers/isdn/sc/ioctl.c
index 1371a990416..3314a5a1985 100644
--- a/drivers/isdn/sc/ioctl.c
+++ b/drivers/isdn/sc/ioctl.c
@@ -14,7 +14,6 @@
extern int indicate_status(int, int, unsigned long, char *);
extern int startproc(int);
-extern int loadproc(int, char *record);
extern int reset(int);
extern int send_and_receive(int, unsigned int, unsigned char,unsigned char,
unsigned char,unsigned char,
@@ -23,7 +22,7 @@ extern int send_and_receive(int, unsigned int, unsigned char,unsigned char,
extern board *sc_adapter[];
-int GetStatus(int card, boardInfo *);
+static int GetStatus(int card, boardInfo *);
/*
* Process private IOCTL messages (typically from scctrl)
@@ -428,7 +427,7 @@ int sc_ioctl(int card, scs_ioctl *data)
return 0;
}
-int GetStatus(int card, boardInfo *bi)
+static int GetStatus(int card, boardInfo *bi)
{
RspMessage rcvmsg;
int i, status;
diff --git a/drivers/isdn/sc/packet.c b/drivers/isdn/sc/packet.c
index 8e3fac3ba1a..f50defc38ae 100644
--- a/drivers/isdn/sc/packet.c
+++ b/drivers/isdn/sc/packet.c
@@ -213,19 +213,3 @@ int setup_buffers(int card, int c)
return 0;
}
-int print_skb(int card,char *skb_p, int len){
- int i,data;
- pr_debug("%s: data at 0x%x len: 0x%x\n", sc_adapter[card]->devicename,
- skb_p,len);
- for(i=1;i<=len;i++,skb_p++){
- data = (int) (0xff & (*skb_p));
- pr_debug("%s: data = 0x%x", sc_adapter[card]->devicename,data);
- if(!(i%4))
- pr_debug(" ");
- if(!(i%32))
- pr_debug("\n");
- }
- pr_debug("\n");
- return 0;
-}
-
diff --git a/drivers/isdn/sc/shmem.c b/drivers/isdn/sc/shmem.c
index 7bc2dfad077..24854826ca4 100644
--- a/drivers/isdn/sc/shmem.c
+++ b/drivers/isdn/sc/shmem.c
@@ -108,6 +108,7 @@ void memcpy_fromshmem(int card, void *dest, const void *src, size_t n)
sc_adapter[card]->rambase + ((unsigned long) src %0x4000), (unsigned long) dest); */
}
+#if 0
void memset_shmem(int card, void *dest, int c, size_t n)
{
unsigned long flags;
@@ -141,3 +142,4 @@ void memset_shmem(int card, void *dest, int c, size_t n)
((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80);
spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
}
+#endif /* 0 */
diff --git a/drivers/isdn/sc/timer.c b/drivers/isdn/sc/timer.c
index 710d0f47ca3..aced19aac5a 100644
--- a/drivers/isdn/sc/timer.c
+++ b/drivers/isdn/sc/timer.c
@@ -32,7 +32,7 @@ extern int sendmessage(int, unsigned int, unsigned int, unsigned int,
/*
* Write the proper values into the I/O ports following a reset
*/
-void setup_ports(int card)
+static void setup_ports(int card)
{
outb((sc_adapter[card]->rambase >> 12), sc_adapter[card]->ioport[EXP_BASE]);
@@ -129,19 +129,3 @@ void check_phystat(unsigned long data)
ceReqPhyStatus,0,0,NULL);
}
-/*
- * When in trace mode, this callback is used to swap the working shared
- * RAM page to the trace page(s) and process all received messages. It
- * must be called often enough to get all of the messages out of RAM before
- * it loops around.
- * Trace messages are \n terminated strings.
- * We output the messages in 64 byte chunks through readstat. Each chunk
- * is scanned for a \n followed by a time stamp. If the timerstamp is older
- * than the current time, scanning stops and the page and offset are recorded
- * as the starting point the next time the trace timer is called. The final
- * step is to restore the working page and reset the timer.
- */
-void trace_timer(unsigned long data)
-{
- /* not implemented */
-}
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index 7297c77f99c..493e2afa191 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -77,7 +77,7 @@ static struct adb_driver *adb_driver_list[] = {
NULL
};
-static struct class_simple *adb_dev_class;
+static struct class *adb_dev_class;
struct adb_driver *adb_controller;
struct notifier_block *adb_client_list = NULL;
@@ -902,9 +902,8 @@ adbdev_init(void)
devfs_mk_cdev(MKDEV(ADB_MAJOR, 0), S_IFCHR | S_IRUSR | S_IWUSR, "adb");
- adb_dev_class = class_simple_create(THIS_MODULE, "adb");
- if (IS_ERR(adb_dev_class)) {
+ adb_dev_class = class_create(THIS_MODULE, "adb");
+ if (IS_ERR(adb_dev_class))
return;
- }
- class_simple_device_add(adb_dev_class, MKDEV(ADB_MAJOR, 0), NULL, "adb");
+ class_device_create(adb_dev_class, MKDEV(ADB_MAJOR, 0), NULL, "adb");
}
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index e0ac63effa5..c9ca1118e44 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -39,15 +39,16 @@
#define MANUAL_MASK 0xe0
#define AUTO_MASK 0x20
-static u8 TEMP_REG[3] = {0x26, 0x25, 0x27}; /* local, cpu, gpu */
-static u8 LIMIT_REG[3] = {0x6b, 0x6a, 0x6c}; /* local, cpu, gpu */
+static u8 TEMP_REG[3] = {0x26, 0x25, 0x27}; /* local, sensor1, sensor2 */
+static u8 LIMIT_REG[3] = {0x6b, 0x6a, 0x6c}; /* local, sensor1, sensor2 */
static u8 MANUAL_MODE[2] = {0x5c, 0x5d};
static u8 REM_CONTROL[2] = {0x00, 0x40};
static u8 FAN_SPEED[2] = {0x28, 0x2a};
static u8 FAN_SPD_SET[2] = {0x30, 0x31};
-static u8 default_limits_local[3] = {70, 50, 70}; /* local, cpu, gpu */
-static u8 default_limits_chip[3] = {80, 65, 80}; /* local, cpu, gpu */
+static u8 default_limits_local[3] = {70, 50, 70}; /* local, sensor1, sensor2 */
+static u8 default_limits_chip[3] = {80, 65, 80}; /* local, sensor1, sensor2 */
+static char *sensor_location[3] = {NULL, NULL, NULL};
static int limit_adjust = 0;
static int fan_speed = -1;
@@ -58,7 +59,7 @@ MODULE_DESCRIPTION("Driver for ADT746x thermostat in iBook G4 and "
MODULE_LICENSE("GPL");
module_param(limit_adjust, int, 0644);
-MODULE_PARM_DESC(limit_adjust,"Adjust maximum temperatures (50 cpu, 70 gpu) "
+MODULE_PARM_DESC(limit_adjust,"Adjust maximum temperatures (50 sensor1, 70 sensor2) "
"by N degrees.");
module_param(fan_speed, int, 0644);
@@ -213,10 +214,10 @@ static void write_fan_speed(struct thermostat *th, int speed, int fan)
if (th->last_speed[fan] != speed) {
if (speed == -1)
printk(KERN_DEBUG "adt746x: Setting speed to automatic "
- "for %s fan.\n", fan?"GPU":"CPU");
+ "for %s fan.\n", sensor_location[fan+1]);
else
printk(KERN_DEBUG "adt746x: Setting speed to %d "
- "for %s fan.\n", speed, fan?"GPU":"CPU");
+ "for %s fan.\n", speed, sensor_location[fan+1]);
} else
return;
@@ -300,11 +301,11 @@ static void update_fans_speed (struct thermostat *th)
printk(KERN_DEBUG "adt746x: setting fans speed to %d "
"(limit exceeded by %d on %s) \n",
new_speed, var,
- fan_number?"GPU/pwr":"CPU");
+ sensor_location[fan_number+1]);
write_both_fan_speed(th, new_speed);
th->last_var[fan_number] = var;
} else if (var < -2) {
- /* don't stop fan if GPU/power is cold and CPU is not
+ /* don't stop fan if sensor2 is cold and sensor1 is not
* so cold (lastvar >= -1) */
if (i == 2 && lastvar < -1) {
if (th->last_speed[fan_number] != 0)
@@ -318,7 +319,7 @@ static void update_fans_speed (struct thermostat *th)
if (started)
return; /* we don't want to re-stop the fan
- * if CPU is heating and GPU/power is not */
+ * if sensor1 is heating and sensor2 is not */
}
}
@@ -327,9 +328,7 @@ static int monitor_task(void *arg)
struct thermostat* th = arg;
while(!kthread_should_stop()) {
- if (current->flags & PF_FREEZE)
- refrigerator(PF_FREEZE);
-
+ try_to_freeze();
msleep_interruptible(2000);
#ifndef DEBUG
@@ -353,7 +352,7 @@ static int monitor_task(void *arg)
static void set_limit(struct thermostat *th, int i)
{
- /* Set CPU limit higher to avoid powerdowns */
+ /* Set sensor1 limit higher to avoid powerdowns */
th->limits[i] = default_limits_chip[i] + limit_adjust;
write_reg(th, LIMIT_REG[i], th->limits[i]);
@@ -454,15 +453,22 @@ static int attach_one_thermostat(struct i2c_adapter *adapter, int addr,
* pass around to the attribute functions, so we don't really have
* choice but implement a bunch of them...
*
+ * FIXME, it does now...
*/
#define BUILD_SHOW_FUNC_INT(name, data) \
-static ssize_t show_##name(struct device *dev, char *buf) \
+static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return sprintf(buf, "%d\n", data); \
}
+#define BUILD_SHOW_FUNC_STR(name, data) \
+static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf) \
+{ \
+ return sprintf(buf, "%s\n", data); \
+}
+
#define BUILD_SHOW_FUNC_FAN(name, data) \
-static ssize_t show_##name(struct device *dev, char *buf) \
+static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return sprintf(buf, "%d (%d rpm)\n", \
thermostat->last_speed[data], \
@@ -471,12 +477,12 @@ static ssize_t show_##name(struct device *dev, char *buf) \
}
#define BUILD_STORE_FUNC_DEG(name, data) \
-static ssize_t store_##name(struct device *dev, const char *buf, size_t n) \
+static ssize_t store_##name(struct device *dev, struct device_attribute *attr, const char *buf, size_t n) \
{ \
int val; \
int i; \
val = simple_strtol(buf, NULL, 10); \
- printk(KERN_INFO "Adjusting limits by %d°C\n", val); \
+ printk(KERN_INFO "Adjusting limits by %d degrees\n", val); \
limit_adjust = val; \
for (i=0; i < 3; i++) \
set_limit(thermostat, i); \
@@ -484,7 +490,7 @@ static ssize_t store_##name(struct device *dev, const char *buf, size_t n) \
}
#define BUILD_STORE_FUNC_INT(name, data) \
-static ssize_t store_##name(struct device *dev, const char *buf, size_t n) \
+static ssize_t store_##name(struct device *dev, struct device_attribute *attr, const char *buf, size_t n) \
{ \
u32 val; \
val = simple_strtoul(buf, NULL, 10); \
@@ -495,35 +501,41 @@ static ssize_t store_##name(struct device *dev, const char *buf, size_t n) \
return n; \
}
-BUILD_SHOW_FUNC_INT(cpu_temperature, (read_reg(thermostat, TEMP_REG[1])))
-BUILD_SHOW_FUNC_INT(gpu_temperature, (read_reg(thermostat, TEMP_REG[2])))
-BUILD_SHOW_FUNC_INT(cpu_limit, thermostat->limits[1])
-BUILD_SHOW_FUNC_INT(gpu_limit, thermostat->limits[2])
+BUILD_SHOW_FUNC_INT(sensor1_temperature, (read_reg(thermostat, TEMP_REG[1])))
+BUILD_SHOW_FUNC_INT(sensor2_temperature, (read_reg(thermostat, TEMP_REG[2])))
+BUILD_SHOW_FUNC_INT(sensor1_limit, thermostat->limits[1])
+BUILD_SHOW_FUNC_INT(sensor2_limit, thermostat->limits[2])
+BUILD_SHOW_FUNC_STR(sensor1_location, sensor_location[1])
+BUILD_SHOW_FUNC_STR(sensor2_location, sensor_location[2])
BUILD_SHOW_FUNC_INT(specified_fan_speed, fan_speed)
-BUILD_SHOW_FUNC_FAN(cpu_fan_speed, 0)
-BUILD_SHOW_FUNC_FAN(gpu_fan_speed, 1)
+BUILD_SHOW_FUNC_FAN(sensor1_fan_speed, 0)
+BUILD_SHOW_FUNC_FAN(sensor2_fan_speed, 1)
BUILD_STORE_FUNC_INT(specified_fan_speed,fan_speed)
BUILD_SHOW_FUNC_INT(limit_adjust, limit_adjust)
BUILD_STORE_FUNC_DEG(limit_adjust, thermostat)
-static DEVICE_ATTR(cpu_temperature, S_IRUGO,
- show_cpu_temperature,NULL);
-static DEVICE_ATTR(gpu_temperature, S_IRUGO,
- show_gpu_temperature,NULL);
-static DEVICE_ATTR(cpu_limit, S_IRUGO,
- show_cpu_limit, NULL);
-static DEVICE_ATTR(gpu_limit, S_IRUGO,
- show_gpu_limit, NULL);
+static DEVICE_ATTR(sensor1_temperature, S_IRUGO,
+ show_sensor1_temperature,NULL);
+static DEVICE_ATTR(sensor2_temperature, S_IRUGO,
+ show_sensor2_temperature,NULL);
+static DEVICE_ATTR(sensor1_limit, S_IRUGO,
+ show_sensor1_limit, NULL);
+static DEVICE_ATTR(sensor2_limit, S_IRUGO,
+ show_sensor2_limit, NULL);
+static DEVICE_ATTR(sensor1_location, S_IRUGO,
+ show_sensor1_location, NULL);
+static DEVICE_ATTR(sensor2_location, S_IRUGO,
+ show_sensor2_location, NULL);
static DEVICE_ATTR(specified_fan_speed, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH,
show_specified_fan_speed,store_specified_fan_speed);
-static DEVICE_ATTR(cpu_fan_speed, S_IRUGO,
- show_cpu_fan_speed, NULL);
-static DEVICE_ATTR(gpu_fan_speed, S_IRUGO,
- show_gpu_fan_speed, NULL);
+static DEVICE_ATTR(sensor1_fan_speed, S_IRUGO,
+ show_sensor1_fan_speed, NULL);
+static DEVICE_ATTR(sensor2_fan_speed, S_IRUGO,
+ show_sensor2_fan_speed, NULL);
static DEVICE_ATTR(limit_adjust, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH,
show_limit_adjust, store_limit_adjust);
@@ -534,6 +546,7 @@ thermostat_init(void)
{
struct device_node* np;
u32 *prop;
+ int i = 0, offset = 0;
np = of_find_node_by_name(NULL, "fan");
if (!np)
@@ -545,6 +558,12 @@ thermostat_init(void)
else
return -ENODEV;
+ prop = (u32 *)get_property(np, "hwsensor-params-version", NULL);
+ printk(KERN_INFO "adt746x: version %d (%ssupported)\n", *prop,
+ (*prop == 1)?"":"un");
+ if (*prop != 1)
+ return -ENODEV;
+
prop = (u32 *)get_property(np, "reg", NULL);
if (!prop)
return -ENODEV;
@@ -563,6 +582,23 @@ thermostat_init(void)
"limit_adjust: %d, fan_speed: %d\n",
therm_bus, therm_address, limit_adjust, fan_speed);
+ if (get_property(np, "hwsensor-location", NULL)) {
+ for (i = 0; i < 3; i++) {
+ sensor_location[i] = get_property(np,
+ "hwsensor-location", NULL) + offset;
+
+ if (sensor_location[i] == NULL)
+ sensor_location[i] = "";
+
+ printk(KERN_INFO "sensor %d: %s\n", i, sensor_location[i]);
+ offset += strlen(sensor_location[i]) + 1;
+ }
+ } else {
+ sensor_location[0] = "?";
+ sensor_location[1] = "?";
+ sensor_location[2] = "?";
+ }
+
of_dev = of_platform_device_create(np, "temperatures");
if (of_dev == NULL) {
@@ -570,15 +606,17 @@ thermostat_init(void)
return -ENODEV;
}
- device_create_file(&of_dev->dev, &dev_attr_cpu_temperature);
- device_create_file(&of_dev->dev, &dev_attr_gpu_temperature);
- device_create_file(&of_dev->dev, &dev_attr_cpu_limit);
- device_create_file(&of_dev->dev, &dev_attr_gpu_limit);
+ device_create_file(&of_dev->dev, &dev_attr_sensor1_temperature);
+ device_create_file(&of_dev->dev, &dev_attr_sensor2_temperature);
+ device_create_file(&of_dev->dev, &dev_attr_sensor1_limit);
+ device_create_file(&of_dev->dev, &dev_attr_sensor2_limit);
+ device_create_file(&of_dev->dev, &dev_attr_sensor1_location);
+ device_create_file(&of_dev->dev, &dev_attr_sensor2_location);
device_create_file(&of_dev->dev, &dev_attr_limit_adjust);
device_create_file(&of_dev->dev, &dev_attr_specified_fan_speed);
- device_create_file(&of_dev->dev, &dev_attr_cpu_fan_speed);
+ device_create_file(&of_dev->dev, &dev_attr_sensor1_fan_speed);
if(therm_type == ADT7460)
- device_create_file(&of_dev->dev, &dev_attr_gpu_fan_speed);
+ device_create_file(&of_dev->dev, &dev_attr_sensor2_fan_speed);
#ifndef CONFIG_I2C_KEYWEST
request_module("i2c-keywest");
@@ -591,17 +629,19 @@ static void __exit
thermostat_exit(void)
{
if (of_dev) {
- device_remove_file(&of_dev->dev, &dev_attr_cpu_temperature);
- device_remove_file(&of_dev->dev, &dev_attr_gpu_temperature);
- device_remove_file(&of_dev->dev, &dev_attr_cpu_limit);
- device_remove_file(&of_dev->dev, &dev_attr_gpu_limit);
+ device_remove_file(&of_dev->dev, &dev_attr_sensor1_temperature);
+ device_remove_file(&of_dev->dev, &dev_attr_sensor2_temperature);
+ device_remove_file(&of_dev->dev, &dev_attr_sensor1_limit);
+ device_remove_file(&of_dev->dev, &dev_attr_sensor2_limit);
+ device_remove_file(&of_dev->dev, &dev_attr_sensor1_location);
+ device_remove_file(&of_dev->dev, &dev_attr_sensor2_location);
device_remove_file(&of_dev->dev, &dev_attr_limit_adjust);
device_remove_file(&of_dev->dev, &dev_attr_specified_fan_speed);
- device_remove_file(&of_dev->dev, &dev_attr_cpu_fan_speed);
+ device_remove_file(&of_dev->dev, &dev_attr_sensor1_fan_speed);
if(therm_type == ADT7460)
device_remove_file(&of_dev->dev,
- &dev_attr_gpu_fan_speed);
+ &dev_attr_sensor2_fan_speed);
of_device_unregister(of_dev);
}
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c
index 82336a5a547..feb4e241385 100644
--- a/drivers/macintosh/therm_pm72.c
+++ b/drivers/macintosh/therm_pm72.c
@@ -685,7 +685,7 @@ static void fetch_cpu_pumps_minmax(void)
* the input twice... I accept patches :)
*/
#define BUILD_SHOW_FUNC_FIX(name, data) \
-static ssize_t show_##name(struct device *dev, char *buf) \
+static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
ssize_t r; \
down(&driver_lock); \
@@ -694,7 +694,7 @@ static ssize_t show_##name(struct device *dev, char *buf) \
return r; \
}
#define BUILD_SHOW_FUNC_INT(name, data) \
-static ssize_t show_##name(struct device *dev, char *buf) \
+static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
return sprintf(buf, "%d", data); \
}
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index c153699d0f8..61400f04015 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -51,8 +51,10 @@
static int do_probe( struct i2c_adapter *adapter, int addr, int kind);
/* scan 0x48-0x4f (DS1775) and 0x2c-2x2f (ADM1030) */
-static unsigned short normal_i2c[] = { 0x49, 0x2c, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { 0x48, 0x4f, 0x2c, 0x2f, I2C_CLIENT_END };
+static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
+ 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x2c, 0x2d, 0x2e, 0x2f,
+ I2C_CLIENT_END };
I2C_CLIENT_INSMOD;
@@ -107,13 +109,13 @@ print_temp( const char *s, int temp )
}
static ssize_t
-show_cpu_temperature( struct device *dev, char *buf )
+show_cpu_temperature( struct device *dev, struct device_attribute *attr, char *buf )
{
return sprintf(buf, "%d.%d\n", x.temp>>8, (x.temp & 255)*10/256 );
}
static ssize_t
-show_case_temperature( struct device *dev, char *buf )
+show_case_temperature( struct device *dev, struct device_attribute *attr, char *buf )
{
return sprintf(buf, "%d.%d\n", x.casetemp>>8, (x.casetemp & 255)*10/256 );
}
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index e654aa5eecd..b941ee22099 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -2421,7 +2421,7 @@ pmac_wakeup_devices(void)
/* Re-enable local CPU interrupts */
local_irq_enable();
- mdelay(100);
+ mdelay(10);
preempt_enable();
/* Re-enable clock spreading on some machines */
@@ -2549,7 +2549,9 @@ powerbook_sleep_Core99(void)
return ret;
}
- printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1));
+ /* Stop environment and ADB interrupts */
+ pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0);
+ pmu_wait_complete(&req);
/* Tell PMU what events will wake us up */
pmu_request(&req, NULL, 4, PMU_POWER_EVENTS, PMU_PWR_CLR_WAKEUP_EVENTS,
@@ -2591,6 +2593,9 @@ powerbook_sleep_Core99(void)
/* Restore VIA */
restore_via_state();
+ /* tweak LPJ before cpufreq is there */
+ loops_per_jiffy *= 2;
+
/* Restore video */
pmac_call_early_video_resume();
@@ -2611,7 +2616,8 @@ powerbook_sleep_Core99(void)
pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask);
pmu_wait_complete(&req);
- printk(KERN_DEBUG "HID1, after: %x\n", mfspr(SPRN_HID1));
+ /* Restore LPJ, cpufreq will adjust the cpu frequency */
+ loops_per_jiffy /= 2;
pmac_wakeup_devices();
diff --git a/drivers/mca/mca-bus.c b/drivers/mca/mca-bus.c
index ff9be67c2a1..09baa43b259 100644
--- a/drivers/mca/mca-bus.c
+++ b/drivers/mca/mca-bus.c
@@ -69,7 +69,7 @@ struct bus_type mca_bus_type = {
};
EXPORT_SYMBOL (mca_bus_type);
-static ssize_t mca_show_pos_id(struct device *dev, char *buf)
+static ssize_t mca_show_pos_id(struct device *dev, struct device_attribute *attr, char *buf)
{
/* four digits, \n and trailing \0 */
struct mca_device *mca_dev = to_mca_device(dev);
@@ -81,7 +81,7 @@ static ssize_t mca_show_pos_id(struct device *dev, char *buf)
len = sprintf(buf, "none\n");
return len;
}
-static ssize_t mca_show_pos(struct device *dev, char *buf)
+static ssize_t mca_show_pos(struct device *dev, struct device_attribute *attr, char *buf)
{
/* enough for 8 two byte hex chars plus space and new line */
int j, len=0;
diff --git a/drivers/mca/mca-legacy.c b/drivers/mca/mca-legacy.c
index af56313ba0a..0c7bfa74c8e 100644
--- a/drivers/mca/mca-legacy.c
+++ b/drivers/mca/mca-legacy.c
@@ -180,7 +180,6 @@ struct mca_device *mca_find_device_by_slot(int slot)
return info.mca_dev;
}
-EXPORT_SYMBOL(mca_find_device_by_slot);
/**
* mca_read_stored_pos - read POS register from boot data
diff --git a/drivers/md/Makefile b/drivers/md/Makefile
index 90de9c146a5..d3efedf6a6a 100644
--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
@@ -7,6 +7,7 @@ dm-mod-objs := dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \
dm-multipath-objs := dm-hw-handler.o dm-path-selector.o dm-mpath.o
dm-snapshot-objs := dm-snap.o dm-exception-store.o
dm-mirror-objs := dm-log.o dm-raid1.o
+md-mod-objs := md.o bitmap.o
raid6-objs := raid6main.o raid6algos.o raid6recov.o raid6tables.o \
raid6int1.o raid6int2.o raid6int4.o \
raid6int8.o raid6int16.o raid6int32.o \
@@ -28,7 +29,7 @@ obj-$(CONFIG_MD_RAID5) += raid5.o xor.o
obj-$(CONFIG_MD_RAID6) += raid6.o xor.o
obj-$(CONFIG_MD_MULTIPATH) += multipath.o
obj-$(CONFIG_MD_FAULTY) += faulty.o
-obj-$(CONFIG_BLK_DEV_MD) += md.o
+obj-$(CONFIG_BLK_DEV_MD) += md-mod.o
obj-$(CONFIG_BLK_DEV_DM) += dm-mod.o
obj-$(CONFIG_DM_CRYPT) += dm-crypt.o
obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o dm-round-robin.o
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
new file mode 100644
index 00000000000..95980ad6b27
--- /dev/null
+++ b/drivers/md/bitmap.c
@@ -0,0 +1,1586 @@
+/*
+ * bitmap.c two-level bitmap (C) Peter T. Breuer (ptb@ot.uc3m.es) 2003
+ *
+ * bitmap_create - sets up the bitmap structure
+ * bitmap_destroy - destroys the bitmap structure
+ *
+ * additions, Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, Inc.:
+ * - added disk storage for bitmap
+ * - changes to allow various bitmap chunk sizes
+ * - added bitmap daemon (to asynchronously clear bitmap bits from disk)
+ */
+
+/*
+ * Still to do:
+ *
+ * flush after percent set rather than just time based. (maybe both).
+ * wait if count gets too high, wake when it drops to half.
+ * allow bitmap to be mirrored with superblock (before or after...)
+ * allow hot-add to re-instate a current device.
+ * allow hot-add of bitmap after quiessing device
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/config.h>
+#include <linux/timer.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/file.h>
+#include <linux/mount.h>
+#include <linux/buffer_head.h>
+#include <linux/raid/md.h>
+#include <linux/raid/bitmap.h>
+
+/* debug macros */
+
+#define DEBUG 0
+
+#if DEBUG
+/* these are for debugging purposes only! */
+
+/* define one and only one of these */
+#define INJECT_FAULTS_1 0 /* cause bitmap_alloc_page to fail always */
+#define INJECT_FAULTS_2 0 /* cause bitmap file to be kicked when first bit set*/
+#define INJECT_FAULTS_3 0 /* treat bitmap file as kicked at init time */
+#define INJECT_FAULTS_4 0 /* undef */
+#define INJECT_FAULTS_5 0 /* undef */
+#define INJECT_FAULTS_6 0
+
+/* if these are defined, the driver will fail! debug only */
+#define INJECT_FATAL_FAULT_1 0 /* fail kmalloc, causing bitmap_create to fail */
+#define INJECT_FATAL_FAULT_2 0 /* undef */
+#define INJECT_FATAL_FAULT_3 0 /* undef */
+#endif
+
+//#define DPRINTK PRINTK /* set this NULL to avoid verbose debug output */
+#define DPRINTK(x...) do { } while(0)
+
+#ifndef PRINTK
+# if DEBUG > 0
+# define PRINTK(x...) printk(KERN_DEBUG x)
+# else
+# define PRINTK(x...)
+# endif
+#endif
+
+static inline char * bmname(struct bitmap *bitmap)
+{
+ return bitmap->mddev ? mdname(bitmap->mddev) : "mdX";
+}
+
+
+/*
+ * test if the bitmap is active
+ */
+int bitmap_active(struct bitmap *bitmap)
+{
+ unsigned long flags;
+ int res = 0;
+
+ if (!bitmap)
+ return res;
+ spin_lock_irqsave(&bitmap->lock, flags);
+ res = bitmap->flags & BITMAP_ACTIVE;
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+ return res;
+}
+
+#define WRITE_POOL_SIZE 256
+/* mempool for queueing pending writes on the bitmap file */
+static void *write_pool_alloc(unsigned int gfp_flags, void *data)
+{
+ return kmalloc(sizeof(struct page_list), gfp_flags);
+}
+
+static void write_pool_free(void *ptr, void *data)
+{
+ kfree(ptr);
+}
+
+/*
+ * just a placeholder - calls kmalloc for bitmap pages
+ */
+static unsigned char *bitmap_alloc_page(struct bitmap *bitmap)
+{
+ unsigned char *page;
+
+#if INJECT_FAULTS_1
+ page = NULL;
+#else
+ page = kmalloc(PAGE_SIZE, GFP_NOIO);
+#endif
+ if (!page)
+ printk("%s: bitmap_alloc_page FAILED\n", bmname(bitmap));
+ else
+ PRINTK("%s: bitmap_alloc_page: allocated page at %p\n",
+ bmname(bitmap), page);
+ return page;
+}
+
+/*
+ * for now just a placeholder -- just calls kfree for bitmap pages
+ */
+static void bitmap_free_page(struct bitmap *bitmap, unsigned char *page)
+{
+ PRINTK("%s: bitmap_free_page: free page %p\n", bmname(bitmap), page);
+ kfree(page);
+}
+
+/*
+ * check a page and, if necessary, allocate it (or hijack it if the alloc fails)
+ *
+ * 1) check to see if this page is allocated, if it's not then try to alloc
+ * 2) if the alloc fails, set the page's hijacked flag so we'll use the
+ * page pointer directly as a counter
+ *
+ * if we find our page, we increment the page's refcount so that it stays
+ * allocated while we're using it
+ */
+static int bitmap_checkpage(struct bitmap *bitmap, unsigned long page, int create)
+{
+ unsigned char *mappage;
+
+ if (page >= bitmap->pages) {
+ printk(KERN_ALERT
+ "%s: invalid bitmap page request: %lu (> %lu)\n",
+ bmname(bitmap), page, bitmap->pages-1);
+ return -EINVAL;
+ }
+
+
+ if (bitmap->bp[page].hijacked) /* it's hijacked, don't try to alloc */
+ return 0;
+
+ if (bitmap->bp[page].map) /* page is already allocated, just return */
+ return 0;
+
+ if (!create)
+ return -ENOENT;
+
+ spin_unlock_irq(&bitmap->lock);
+
+ /* this page has not been allocated yet */
+
+ if ((mappage = bitmap_alloc_page(bitmap)) == NULL) {
+ PRINTK("%s: bitmap map page allocation failed, hijacking\n",
+ bmname(bitmap));
+ /* failed - set the hijacked flag so that we can use the
+ * pointer as a counter */
+ spin_lock_irq(&bitmap->lock);
+ if (!bitmap->bp[page].map)
+ bitmap->bp[page].hijacked = 1;
+ goto out;
+ }
+
+ /* got a page */
+
+ spin_lock_irq(&bitmap->lock);
+
+ /* recheck the page */
+
+ if (bitmap->bp[page].map || bitmap->bp[page].hijacked) {
+ /* somebody beat us to getting the page */
+ bitmap_free_page(bitmap, mappage);
+ return 0;
+ }
+
+ /* no page was in place and we have one, so install it */
+
+ memset(mappage, 0, PAGE_SIZE);
+ bitmap->bp[page].map = mappage;
+ bitmap->missing_pages--;
+out:
+ return 0;
+}
+
+
+/* if page is completely empty, put it back on the free list, or dealloc it */
+/* if page was hijacked, unmark the flag so it might get alloced next time */
+/* Note: lock should be held when calling this */
+static inline void bitmap_checkfree(struct bitmap *bitmap, unsigned long page)
+{
+ char *ptr;
+
+ if (bitmap->bp[page].count) /* page is still busy */
+ return;
+
+ /* page is no longer in use, it can be released */
+
+ if (bitmap->bp[page].hijacked) { /* page was hijacked, undo this now */
+ bitmap->bp[page].hijacked = 0;
+ bitmap->bp[page].map = NULL;
+ return;
+ }
+
+ /* normal case, free the page */
+
+#if 0
+/* actually ... let's not. We will probably need the page again exactly when
+ * memory is tight and we are flusing to disk
+ */
+ return;
+#else
+ ptr = bitmap->bp[page].map;
+ bitmap->bp[page].map = NULL;
+ bitmap->missing_pages++;
+ bitmap_free_page(bitmap, ptr);
+ return;
+#endif
+}
+
+
+/*
+ * bitmap file handling - read and write the bitmap file and its superblock
+ */
+
+/* copy the pathname of a file to a buffer */
+char *file_path(struct file *file, char *buf, int count)
+{
+ struct dentry *d;
+ struct vfsmount *v;
+
+ if (!buf)
+ return NULL;
+
+ d = file->f_dentry;
+ v = file->f_vfsmnt;
+
+ buf = d_path(d, v, buf, count);
+
+ return IS_ERR(buf) ? NULL : buf;
+}
+
+/*
+ * basic page I/O operations
+ */
+
+/* IO operations when bitmap is stored near all superblocks */
+static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long index)
+{
+ /* choose a good rdev and read the page from there */
+
+ mdk_rdev_t *rdev;
+ struct list_head *tmp;
+ struct page *page = alloc_page(GFP_KERNEL);
+ sector_t target;
+
+ if (!page)
+ return ERR_PTR(-ENOMEM);
+ do {
+ ITERATE_RDEV(mddev, rdev, tmp)
+ if (rdev->in_sync && !rdev->faulty)
+ goto found;
+ return ERR_PTR(-EIO);
+
+ found:
+ target = (rdev->sb_offset << 1) + offset + index * (PAGE_SIZE/512);
+
+ } while (!sync_page_io(rdev->bdev, target, PAGE_SIZE, page, READ));
+
+ page->index = index;
+ return page;
+}
+
+static int write_sb_page(mddev_t *mddev, long offset, struct page *page, int wait)
+{
+ mdk_rdev_t *rdev;
+ struct list_head *tmp;
+
+ ITERATE_RDEV(mddev, rdev, tmp)
+ if (rdev->in_sync && !rdev->faulty)
+ md_super_write(mddev, rdev,
+ (rdev->sb_offset<<1) + offset
+ + page->index * (PAGE_SIZE/512),
+ PAGE_SIZE,
+ page);
+
+ if (wait)
+ wait_event(mddev->sb_wait, atomic_read(&mddev->pending_writes)==0);
+ return 0;
+}
+
+/*
+ * write out a page to a file
+ */
+static int write_page(struct bitmap *bitmap, struct page *page, int wait)
+{
+ int ret = -ENOMEM;
+
+ if (bitmap->file == NULL)
+ return write_sb_page(bitmap->mddev, bitmap->offset, page, wait);
+
+ if (wait)
+ lock_page(page);
+ else {
+ if (TestSetPageLocked(page))
+ return -EAGAIN; /* already locked */
+ if (PageWriteback(page)) {
+ unlock_page(page);
+ return -EAGAIN;
+ }
+ }
+
+ ret = page->mapping->a_ops->prepare_write(NULL, page, 0, PAGE_SIZE);
+ if (!ret)
+ ret = page->mapping->a_ops->commit_write(NULL, page, 0,
+ PAGE_SIZE);
+ if (ret) {
+ unlock_page(page);
+ return ret;
+ }
+
+ set_page_dirty(page); /* force it to be written out */
+
+ if (!wait) {
+ /* add to list to be waited for by daemon */
+ struct page_list *item = mempool_alloc(bitmap->write_pool, GFP_NOIO);
+ item->page = page;
+ page_cache_get(page);
+ spin_lock(&bitmap->write_lock);
+ list_add(&item->list, &bitmap->complete_pages);
+ spin_unlock(&bitmap->write_lock);
+ md_wakeup_thread(bitmap->writeback_daemon);
+ }
+ return write_one_page(page, wait);
+}
+
+/* read a page from a file, pinning it into cache, and return bytes_read */
+static struct page *read_page(struct file *file, unsigned long index,
+ unsigned long *bytes_read)
+{
+ struct inode *inode = file->f_mapping->host;
+ struct page *page = NULL;
+ loff_t isize = i_size_read(inode);
+ unsigned long end_index = isize >> PAGE_CACHE_SHIFT;
+
+ PRINTK("read bitmap file (%dB @ %Lu)\n", (int)PAGE_CACHE_SIZE,
+ (unsigned long long)index << PAGE_CACHE_SHIFT);
+
+ page = read_cache_page(inode->i_mapping, index,
+ (filler_t *)inode->i_mapping->a_ops->readpage, file);
+ if (IS_ERR(page))
+ goto out;
+ wait_on_page_locked(page);
+ if (!PageUptodate(page) || PageError(page)) {
+ page_cache_release(page);
+ page = ERR_PTR(-EIO);
+ goto out;
+ }
+
+ if (index > end_index) /* we have read beyond EOF */
+ *bytes_read = 0;
+ else if (index == end_index) /* possible short read */
+ *bytes_read = isize & ~PAGE_CACHE_MASK;
+ else
+ *bytes_read = PAGE_CACHE_SIZE; /* got a full page */
+out:
+ if (IS_ERR(page))
+ printk(KERN_ALERT "md: bitmap read error: (%dB @ %Lu): %ld\n",
+ (int)PAGE_CACHE_SIZE,
+ (unsigned long long)index << PAGE_CACHE_SHIFT,
+ PTR_ERR(page));
+ return page;
+}
+
+/*
+ * bitmap file superblock operations
+ */
+
+/* update the event counter and sync the superblock to disk */
+int bitmap_update_sb(struct bitmap *bitmap)
+{
+ bitmap_super_t *sb;
+ unsigned long flags;
+
+ if (!bitmap || !bitmap->mddev) /* no bitmap for this array */
+ return 0;
+ spin_lock_irqsave(&bitmap->lock, flags);
+ if (!bitmap->sb_page) { /* no superblock */
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+ return 0;
+ }
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+ sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+ sb->events = cpu_to_le64(bitmap->mddev->events);
+ if (!bitmap->mddev->degraded)
+ sb->events_cleared = cpu_to_le64(bitmap->mddev->events);
+ kunmap(bitmap->sb_page);
+ return write_page(bitmap, bitmap->sb_page, 1);
+}
+
+/* print out the bitmap file superblock */
+void bitmap_print_sb(struct bitmap *bitmap)
+{
+ bitmap_super_t *sb;
+
+ if (!bitmap || !bitmap->sb_page)
+ return;
+ sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+ printk(KERN_DEBUG "%s: bitmap file superblock:\n", bmname(bitmap));
+ printk(KERN_DEBUG " magic: %08x\n", le32_to_cpu(sb->magic));
+ printk(KERN_DEBUG " version: %d\n", le32_to_cpu(sb->version));
+ printk(KERN_DEBUG " uuid: %08x.%08x.%08x.%08x\n",
+ *(__u32 *)(sb->uuid+0),
+ *(__u32 *)(sb->uuid+4),
+ *(__u32 *)(sb->uuid+8),
+ *(__u32 *)(sb->uuid+12));
+ printk(KERN_DEBUG " events: %llu\n",
+ (unsigned long long) le64_to_cpu(sb->events));
+ printk(KERN_DEBUG "events cleared: %llu\n",
+ (unsigned long long) le64_to_cpu(sb->events_cleared));
+ printk(KERN_DEBUG " state: %08x\n", le32_to_cpu(sb->state));
+ printk(KERN_DEBUG " chunksize: %d B\n", le32_to_cpu(sb->chunksize));
+ printk(KERN_DEBUG " daemon sleep: %ds\n", le32_to_cpu(sb->daemon_sleep));
+ printk(KERN_DEBUG " sync size: %llu KB\n",
+ (unsigned long long)le64_to_cpu(sb->sync_size)/2);
+ kunmap(bitmap->sb_page);
+}
+
+/* read the superblock from the bitmap file and initialize some bitmap fields */
+static int bitmap_read_sb(struct bitmap *bitmap)
+{
+ char *reason = NULL;
+ bitmap_super_t *sb;
+ unsigned long chunksize, daemon_sleep;
+ unsigned long bytes_read;
+ unsigned long long events;
+ int err = -EINVAL;
+
+ /* page 0 is the superblock, read it... */
+ if (bitmap->file)
+ bitmap->sb_page = read_page(bitmap->file, 0, &bytes_read);
+ else {
+ bitmap->sb_page = read_sb_page(bitmap->mddev, bitmap->offset, 0);
+ bytes_read = PAGE_SIZE;
+ }
+ if (IS_ERR(bitmap->sb_page)) {
+ err = PTR_ERR(bitmap->sb_page);
+ bitmap->sb_page = NULL;
+ return err;
+ }
+
+ sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+
+ if (bytes_read < sizeof(*sb)) { /* short read */
+ printk(KERN_INFO "%s: bitmap file superblock truncated\n",
+ bmname(bitmap));
+ err = -ENOSPC;
+ goto out;
+ }
+
+ chunksize = le32_to_cpu(sb->chunksize);
+ daemon_sleep = le32_to_cpu(sb->daemon_sleep);
+
+ /* verify that the bitmap-specific fields are valid */
+ if (sb->magic != cpu_to_le32(BITMAP_MAGIC))
+ reason = "bad magic";
+ else if (sb->version != cpu_to_le32(BITMAP_MAJOR))
+ reason = "unrecognized superblock version";
+ else if (chunksize < 512 || chunksize > (1024 * 1024 * 4))
+ reason = "bitmap chunksize out of range (512B - 4MB)";
+ else if ((1 << ffz(~chunksize)) != chunksize)
+ reason = "bitmap chunksize not a power of 2";
+ else if (daemon_sleep < 1 || daemon_sleep > 15)
+ reason = "daemon sleep period out of range";
+ if (reason) {
+ printk(KERN_INFO "%s: invalid bitmap file superblock: %s\n",
+ bmname(bitmap), reason);
+ goto out;
+ }
+
+ /* keep the array size field of the bitmap superblock up to date */
+ sb->sync_size = cpu_to_le64(bitmap->mddev->resync_max_sectors);
+
+ if (!bitmap->mddev->persistent)
+ goto success;
+
+ /*
+ * if we have a persistent array superblock, compare the
+ * bitmap's UUID and event counter to the mddev's
+ */
+ if (memcmp(sb->uuid, bitmap->mddev->uuid, 16)) {
+ printk(KERN_INFO "%s: bitmap superblock UUID mismatch\n",
+ bmname(bitmap));
+ goto out;
+ }
+ events = le64_to_cpu(sb->events);
+ if (events < bitmap->mddev->events) {
+ printk(KERN_INFO "%s: bitmap file is out of date (%llu < %llu) "
+ "-- forcing full recovery\n", bmname(bitmap), events,
+ (unsigned long long) bitmap->mddev->events);
+ sb->state |= BITMAP_STALE;
+ }
+success:
+ /* assign fields using values from superblock */
+ bitmap->chunksize = chunksize;
+ bitmap->daemon_sleep = daemon_sleep;
+ bitmap->flags |= sb->state;
+ bitmap->events_cleared = le64_to_cpu(sb->events_cleared);
+ err = 0;
+out:
+ kunmap(bitmap->sb_page);
+ if (err)
+ bitmap_print_sb(bitmap);
+ return err;
+}
+
+enum bitmap_mask_op {
+ MASK_SET,
+ MASK_UNSET
+};
+
+/* record the state of the bitmap in the superblock */
+static void bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
+ enum bitmap_mask_op op)
+{
+ bitmap_super_t *sb;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bitmap->lock, flags);
+ if (!bitmap || !bitmap->sb_page) { /* can't set the state */
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+ return;
+ }
+ page_cache_get(bitmap->sb_page);
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+ sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+ switch (op) {
+ case MASK_SET: sb->state |= bits;
+ break;
+ case MASK_UNSET: sb->state &= ~bits;
+ break;
+ default: BUG();
+ }
+ kunmap(bitmap->sb_page);
+ page_cache_release(bitmap->sb_page);
+}
+
+/*
+ * general bitmap file operations
+ */
+
+/* calculate the index of the page that contains this bit */
+static inline unsigned long file_page_index(unsigned long chunk)
+{
+ return CHUNK_BIT_OFFSET(chunk) >> PAGE_BIT_SHIFT;
+}
+
+/* calculate the (bit) offset of this bit within a page */
+static inline unsigned long file_page_offset(unsigned long chunk)
+{
+ return CHUNK_BIT_OFFSET(chunk) & (PAGE_BITS - 1);
+}
+
+/*
+ * return a pointer to the page in the filemap that contains the given bit
+ *
+ * this lookup is complicated by the fact that the bitmap sb might be exactly
+ * 1 page (e.g., x86) or less than 1 page -- so the bitmap might start on page
+ * 0 or page 1
+ */
+static inline struct page *filemap_get_page(struct bitmap *bitmap,
+ unsigned long chunk)
+{
+ return bitmap->filemap[file_page_index(chunk) - file_page_index(0)];
+}
+
+
+static void bitmap_file_unmap(struct bitmap *bitmap)
+{
+ struct page **map, *sb_page;
+ unsigned long *attr;
+ int pages;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bitmap->lock, flags);
+ map = bitmap->filemap;
+ bitmap->filemap = NULL;
+ attr = bitmap->filemap_attr;
+ bitmap->filemap_attr = NULL;
+ pages = bitmap->file_pages;
+ bitmap->file_pages = 0;
+ sb_page = bitmap->sb_page;
+ bitmap->sb_page = NULL;
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+
+ while (pages--)
+ if (map[pages]->index != 0) /* 0 is sb_page, release it below */
+ page_cache_release(map[pages]);
+ kfree(map);
+ kfree(attr);
+
+ if (sb_page)
+ page_cache_release(sb_page);
+}
+
+static void bitmap_stop_daemons(struct bitmap *bitmap);
+
+/* dequeue the next item in a page list -- don't call from irq context */
+static struct page_list *dequeue_page(struct bitmap *bitmap)
+{
+ struct page_list *item = NULL;
+ struct list_head *head = &bitmap->complete_pages;
+
+ spin_lock(&bitmap->write_lock);
+ if (list_empty(head))
+ goto out;
+ item = list_entry(head->prev, struct page_list, list);
+ list_del(head->prev);
+out:
+ spin_unlock(&bitmap->write_lock);
+ return item;
+}
+
+static void drain_write_queues(struct bitmap *bitmap)
+{
+ struct page_list *item;
+
+ while ((item = dequeue_page(bitmap))) {
+ /* don't bother to wait */
+ page_cache_release(item->page);
+ mempool_free(item, bitmap->write_pool);
+ }
+
+ wake_up(&bitmap->write_wait);
+}
+
+static void bitmap_file_put(struct bitmap *bitmap)
+{
+ struct file *file;
+ struct inode *inode;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bitmap->lock, flags);
+ file = bitmap->file;
+ bitmap->file = NULL;
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+
+ bitmap_stop_daemons(bitmap);
+
+ drain_write_queues(bitmap);
+
+ bitmap_file_unmap(bitmap);
+
+ if (file) {
+ inode = file->f_mapping->host;
+ spin_lock(&inode->i_lock);
+ atomic_set(&inode->i_writecount, 1); /* allow writes again */
+ spin_unlock(&inode->i_lock);
+ fput(file);
+ }
+}
+
+
+/*
+ * bitmap_file_kick - if an error occurs while manipulating the bitmap file
+ * then it is no longer reliable, so we stop using it and we mark the file
+ * as failed in the superblock
+ */
+static void bitmap_file_kick(struct bitmap *bitmap)
+{
+ char *path, *ptr = NULL;
+
+ bitmap_mask_state(bitmap, BITMAP_STALE, MASK_SET);
+ bitmap_update_sb(bitmap);
+
+ if (bitmap->file) {
+ path = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (path)
+ ptr = file_path(bitmap->file, path, PAGE_SIZE);
+
+ printk(KERN_ALERT "%s: kicking failed bitmap file %s from array!\n",
+ bmname(bitmap), ptr ? ptr : "");
+
+ kfree(path);
+ }
+
+ bitmap_file_put(bitmap);
+
+ return;
+}
+
+enum bitmap_page_attr {
+ BITMAP_PAGE_DIRTY = 1, // there are set bits that need to be synced
+ BITMAP_PAGE_CLEAN = 2, // there are bits that might need to be cleared
+ BITMAP_PAGE_NEEDWRITE=4, // there are cleared bits that need to be synced
+};
+
+static inline void set_page_attr(struct bitmap *bitmap, struct page *page,
+ enum bitmap_page_attr attr)
+{
+ bitmap->filemap_attr[page->index] |= attr;
+}
+
+static inline void clear_page_attr(struct bitmap *bitmap, struct page *page,
+ enum bitmap_page_attr attr)
+{
+ bitmap->filemap_attr[page->index] &= ~attr;
+}
+
+static inline unsigned long get_page_attr(struct bitmap *bitmap, struct page *page)
+{
+ return bitmap->filemap_attr[page->index];
+}
+
+/*
+ * bitmap_file_set_bit -- called before performing a write to the md device
+ * to set (and eventually sync) a particular bit in the bitmap file
+ *
+ * we set the bit immediately, then we record the page number so that
+ * when an unplug occurs, we can flush the dirty pages out to disk
+ */
+static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
+{
+ unsigned long bit;
+ struct page *page;
+ void *kaddr;
+ unsigned long chunk = block >> CHUNK_BLOCK_SHIFT(bitmap);
+
+ if (!bitmap->filemap) {
+ return;
+ }
+
+ page = filemap_get_page(bitmap, chunk);
+ bit = file_page_offset(chunk);
+
+
+ /* make sure the page stays cached until it gets written out */
+ if (! (get_page_attr(bitmap, page) & BITMAP_PAGE_DIRTY))
+ page_cache_get(page);
+
+ /* set the bit */
+ kaddr = kmap_atomic(page, KM_USER0);
+ set_bit(bit, kaddr);
+ kunmap_atomic(kaddr, KM_USER0);
+ PRINTK("set file bit %lu page %lu\n", bit, page->index);
+
+ /* record page number so it gets flushed to disk when unplug occurs */
+ set_page_attr(bitmap, page, BITMAP_PAGE_DIRTY);
+
+}
+
+/* this gets called when the md device is ready to unplug its underlying
+ * (slave) device queues -- before we let any writes go down, we need to
+ * sync the dirty pages of the bitmap file to disk */
+int bitmap_unplug(struct bitmap *bitmap)
+{
+ unsigned long i, attr, flags;
+ struct page *page;
+ int wait = 0;
+ int err;
+
+ if (!bitmap)
+ return 0;
+
+ /* look at each page to see if there are any set bits that need to be
+ * flushed out to disk */
+ for (i = 0; i < bitmap->file_pages; i++) {
+ spin_lock_irqsave(&bitmap->lock, flags);
+ if (!bitmap->filemap) {
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+ return 0;
+ }
+ page = bitmap->filemap[i];
+ attr = get_page_attr(bitmap, page);
+ clear_page_attr(bitmap, page, BITMAP_PAGE_DIRTY);
+ clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
+ if ((attr & BITMAP_PAGE_DIRTY))
+ wait = 1;
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+
+ if (attr & (BITMAP_PAGE_DIRTY | BITMAP_PAGE_NEEDWRITE)) {
+ err = write_page(bitmap, page, 0);
+ if (err == -EAGAIN) {
+ if (attr & BITMAP_PAGE_DIRTY)
+ err = write_page(bitmap, page, 1);
+ else
+ err = 0;
+ }
+ if (err)
+ return 1;
+ }
+ }
+ if (wait) { /* if any writes were performed, we need to wait on them */
+ if (bitmap->file) {
+ spin_lock_irq(&bitmap->write_lock);
+ wait_event_lock_irq(bitmap->write_wait,
+ list_empty(&bitmap->complete_pages), bitmap->write_lock,
+ wake_up_process(bitmap->writeback_daemon->tsk));
+ spin_unlock_irq(&bitmap->write_lock);
+ } else
+ wait_event(bitmap->mddev->sb_wait,
+ atomic_read(&bitmap->mddev->pending_writes)==0);
+ }
+ return 0;
+}
+
+static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
+ unsigned long sectors, int in_sync);
+/* * bitmap_init_from_disk -- called at bitmap_create time to initialize
+ * the in-memory bitmap from the on-disk bitmap -- also, sets up the
+ * memory mapping of the bitmap file
+ * Special cases:
+ * if there's no bitmap file, or if the bitmap file had been
+ * previously kicked from the array, we mark all the bits as
+ * 1's in order to cause a full resync.
+ */
+static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
+{
+ unsigned long i, chunks, index, oldindex, bit;
+ struct page *page = NULL, *oldpage = NULL;
+ unsigned long num_pages, bit_cnt = 0;
+ struct file *file;
+ unsigned long bytes, offset, dummy;
+ int outofdate;
+ int ret = -ENOSPC;
+
+ chunks = bitmap->chunks;
+ file = bitmap->file;
+
+ BUG_ON(!file && !bitmap->offset);
+
+#if INJECT_FAULTS_3
+ outofdate = 1;
+#else
+ outofdate = bitmap->flags & BITMAP_STALE;
+#endif
+ if (outofdate)
+ printk(KERN_INFO "%s: bitmap file is out of date, doing full "
+ "recovery\n", bmname(bitmap));
+
+ bytes = (chunks + 7) / 8;
+
+ num_pages = (bytes + sizeof(bitmap_super_t) + PAGE_SIZE - 1) / PAGE_SIZE;
+
+ if (file && i_size_read(file->f_mapping->host) < bytes + sizeof(bitmap_super_t)) {
+ printk(KERN_INFO "%s: bitmap file too short %lu < %lu\n",
+ bmname(bitmap),
+ (unsigned long) i_size_read(file->f_mapping->host),
+ bytes + sizeof(bitmap_super_t));
+ goto out;
+ }
+
+ ret = -ENOMEM;
+
+ bitmap->filemap = kmalloc(sizeof(struct page *) * num_pages, GFP_KERNEL);
+ if (!bitmap->filemap)
+ goto out;
+
+ bitmap->filemap_attr = kmalloc(sizeof(long) * num_pages, GFP_KERNEL);
+ if (!bitmap->filemap_attr)
+ goto out;
+
+ memset(bitmap->filemap_attr, 0, sizeof(long) * num_pages);
+
+ oldindex = ~0L;
+
+ for (i = 0; i < chunks; i++) {
+ index = file_page_index(i);
+ bit = file_page_offset(i);
+ if (index != oldindex) { /* this is a new page, read it in */
+ /* unmap the old page, we're done with it */
+ if (oldpage != NULL)
+ kunmap(oldpage);
+ if (index == 0) {
+ /*
+ * if we're here then the superblock page
+ * contains some bits (PAGE_SIZE != sizeof sb)
+ * we've already read it in, so just use it
+ */
+ page = bitmap->sb_page;
+ offset = sizeof(bitmap_super_t);
+ } else if (file) {
+ page = read_page(file, index, &dummy);
+ offset = 0;
+ } else {
+ page = read_sb_page(bitmap->mddev, bitmap->offset, index);
+ offset = 0;
+ }
+ if (IS_ERR(page)) { /* read error */
+ ret = PTR_ERR(page);
+ goto out;
+ }
+
+ oldindex = index;
+ oldpage = page;
+ kmap(page);
+
+ if (outofdate) {
+ /*
+ * if bitmap is out of date, dirty the
+ * whole page and write it out
+ */
+ memset(page_address(page) + offset, 0xff,
+ PAGE_SIZE - offset);
+ ret = write_page(bitmap, page, 1);
+ if (ret) {
+ kunmap(page);
+ /* release, page not in filemap yet */
+ page_cache_release(page);
+ goto out;
+ }
+ }
+
+ bitmap->filemap[bitmap->file_pages++] = page;
+ }
+ if (test_bit(bit, page_address(page))) {
+ /* if the disk bit is set, set the memory bit */
+ bitmap_set_memory_bits(bitmap,
+ i << CHUNK_BLOCK_SHIFT(bitmap), 1, in_sync);
+ bit_cnt++;
+ }
+ }
+
+ /* everything went OK */
+ ret = 0;
+ bitmap_mask_state(bitmap, BITMAP_STALE, MASK_UNSET);
+
+ if (page) /* unmap the last page */
+ kunmap(page);
+
+ if (bit_cnt) { /* Kick recovery if any bits were set */
+ set_bit(MD_RECOVERY_NEEDED, &bitmap->mddev->recovery);
+ md_wakeup_thread(bitmap->mddev->thread);
+ }
+
+out:
+ printk(KERN_INFO "%s: bitmap initialized from disk: "
+ "read %lu/%lu pages, set %lu bits, status: %d\n",
+ bmname(bitmap), bitmap->file_pages, num_pages, bit_cnt, ret);
+
+ return ret;
+}
+
+void bitmap_write_all(struct bitmap *bitmap)
+{
+ /* We don't actually write all bitmap blocks here,
+ * just flag them as needing to be written
+ */
+
+ unsigned long chunks = bitmap->chunks;
+ unsigned long bytes = (chunks+7)/8 + sizeof(bitmap_super_t);
+ unsigned long num_pages = (bytes + PAGE_SIZE-1) / PAGE_SIZE;
+ while (num_pages--)
+ bitmap->filemap_attr[num_pages] |= BITMAP_PAGE_NEEDWRITE;
+}
+
+
+static void bitmap_count_page(struct bitmap *bitmap, sector_t offset, int inc)
+{
+ sector_t chunk = offset >> CHUNK_BLOCK_SHIFT(bitmap);
+ unsigned long page = chunk >> PAGE_COUNTER_SHIFT;
+ bitmap->bp[page].count += inc;
+/*
+ if (page == 0) printk("count page 0, offset %llu: %d gives %d\n",
+ (unsigned long long)offset, inc, bitmap->bp[page].count);
+*/
+ bitmap_checkfree(bitmap, page);
+}
+static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
+ sector_t offset, int *blocks,
+ int create);
+
+/*
+ * bitmap daemon -- periodically wakes up to clean bits and flush pages
+ * out to disk
+ */
+
+int bitmap_daemon_work(struct bitmap *bitmap)
+{
+ unsigned long j;
+ unsigned long flags;
+ struct page *page = NULL, *lastpage = NULL;
+ int err = 0;
+ int blocks;
+ int attr;
+
+ if (bitmap == NULL)
+ return 0;
+ if (time_before(jiffies, bitmap->daemon_lastrun + bitmap->daemon_sleep*HZ))
+ return 0;
+ bitmap->daemon_lastrun = jiffies;
+
+ for (j = 0; j < bitmap->chunks; j++) {
+ bitmap_counter_t *bmc;
+ spin_lock_irqsave(&bitmap->lock, flags);
+ if (!bitmap->filemap) {
+ /* error or shutdown */
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+ break;
+ }
+
+ page = filemap_get_page(bitmap, j);
+
+ if (page != lastpage) {
+ /* skip this page unless it's marked as needing cleaning */
+ if (!((attr=get_page_attr(bitmap, page)) & BITMAP_PAGE_CLEAN)) {
+ if (attr & BITMAP_PAGE_NEEDWRITE) {
+ page_cache_get(page);
+ clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
+ }
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+ if (attr & BITMAP_PAGE_NEEDWRITE) {
+ switch (write_page(bitmap, page, 0)) {
+ case -EAGAIN:
+ set_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
+ break;
+ case 0:
+ break;
+ default:
+ bitmap_file_kick(bitmap);
+ }
+ page_cache_release(page);
+ }
+ continue;
+ }
+
+ /* grab the new page, sync and release the old */
+ page_cache_get(page);
+ if (lastpage != NULL) {
+ if (get_page_attr(bitmap, lastpage) & BITMAP_PAGE_NEEDWRITE) {
+ clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+ err = write_page(bitmap, lastpage, 0);
+ if (err == -EAGAIN) {
+ err = 0;
+ set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+ }
+ } else {
+ set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+ }
+ kunmap(lastpage);
+ page_cache_release(lastpage);
+ if (err)
+ bitmap_file_kick(bitmap);
+ } else
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+ lastpage = page;
+ kmap(page);
+/*
+ printk("bitmap clean at page %lu\n", j);
+*/
+ spin_lock_irqsave(&bitmap->lock, flags);
+ clear_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
+ }
+ bmc = bitmap_get_counter(bitmap, j << CHUNK_BLOCK_SHIFT(bitmap),
+ &blocks, 0);
+ if (bmc) {
+/*
+ if (j < 100) printk("bitmap: j=%lu, *bmc = 0x%x\n", j, *bmc);
+*/
+ if (*bmc == 2) {
+ *bmc=1; /* maybe clear the bit next time */
+ set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
+ } else if (*bmc == 1) {
+ /* we can clear the bit */
+ *bmc = 0;
+ bitmap_count_page(bitmap, j << CHUNK_BLOCK_SHIFT(bitmap),
+ -1);
+
+ /* clear the bit */
+ clear_bit(file_page_offset(j), page_address(page));
+ }
+ }
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+ }
+
+ /* now sync the final page */
+ if (lastpage != NULL) {
+ kunmap(lastpage);
+ spin_lock_irqsave(&bitmap->lock, flags);
+ if (get_page_attr(bitmap, lastpage) &BITMAP_PAGE_NEEDWRITE) {
+ clear_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+ err = write_page(bitmap, lastpage, 0);
+ if (err == -EAGAIN) {
+ set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+ err = 0;
+ }
+ } else {
+ set_page_attr(bitmap, lastpage, BITMAP_PAGE_NEEDWRITE);
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+ }
+
+ page_cache_release(lastpage);
+ }
+
+ return err;
+}
+
+static void daemon_exit(struct bitmap *bitmap, mdk_thread_t **daemon)
+{
+ mdk_thread_t *dmn;
+ unsigned long flags;
+
+ /* if no one is waiting on us, we'll free the md thread struct
+ * and exit, otherwise we let the waiter clean things up */
+ spin_lock_irqsave(&bitmap->lock, flags);
+ if ((dmn = *daemon)) { /* no one is waiting, cleanup and exit */
+ *daemon = NULL;
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+ kfree(dmn);
+ complete_and_exit(NULL, 0); /* do_exit not exported */
+ }
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+}
+
+static void bitmap_writeback_daemon(mddev_t *mddev)
+{
+ struct bitmap *bitmap = mddev->bitmap;
+ struct page *page;
+ struct page_list *item;
+ int err = 0;
+
+ if (signal_pending(current)) {
+ printk(KERN_INFO
+ "%s: bitmap writeback daemon got signal, exiting...\n",
+ bmname(bitmap));
+ err = -EINTR;
+ goto out;
+ }
+
+ PRINTK("%s: bitmap writeback daemon woke up...\n", bmname(bitmap));
+ /* wait on bitmap page writebacks */
+ while ((item = dequeue_page(bitmap))) {
+ page = item->page;
+ mempool_free(item, bitmap->write_pool);
+ PRINTK("wait on page writeback: %p\n", page);
+ wait_on_page_writeback(page);
+ PRINTK("finished page writeback: %p\n", page);
+
+ err = PageError(page);
+ page_cache_release(page);
+ if (err) {
+ printk(KERN_WARNING "%s: bitmap file writeback "
+ "failed (page %lu): %d\n",
+ bmname(bitmap), page->index, err);
+ bitmap_file_kick(bitmap);
+ goto out;
+ }
+ }
+ out:
+ wake_up(&bitmap->write_wait);
+ if (err) {
+ printk(KERN_INFO "%s: bitmap writeback daemon exiting (%d)\n",
+ bmname(bitmap), err);
+ daemon_exit(bitmap, &bitmap->writeback_daemon);
+ }
+}
+
+static int bitmap_start_daemon(struct bitmap *bitmap, mdk_thread_t **ptr,
+ void (*func)(mddev_t *), char *name)
+{
+ mdk_thread_t *daemon;
+ unsigned long flags;
+ char namebuf[32];
+
+ spin_lock_irqsave(&bitmap->lock, flags);
+ *ptr = NULL;
+
+ if (!bitmap->file) /* no need for daemon if there's no backing file */
+ goto out_unlock;
+
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+
+#if INJECT_FATAL_FAULT_2
+ daemon = NULL;
+#else
+ sprintf(namebuf, "%%s_%s", name);
+ daemon = md_register_thread(func, bitmap->mddev, namebuf);
+#endif
+ if (!daemon) {
+ printk(KERN_ERR "%s: failed to start bitmap daemon\n",
+ bmname(bitmap));
+ return -ECHILD;
+ }
+
+ spin_lock_irqsave(&bitmap->lock, flags);
+ *ptr = daemon;
+
+ md_wakeup_thread(daemon); /* start it running */
+
+ PRINTK("%s: %s daemon (pid %d) started...\n",
+ bmname(bitmap), name, daemon->tsk->pid);
+out_unlock:
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+ return 0;
+}
+
+static int bitmap_start_daemons(struct bitmap *bitmap)
+{
+ int err = bitmap_start_daemon(bitmap, &bitmap->writeback_daemon,
+ bitmap_writeback_daemon, "bitmap_wb");
+ return err;
+}
+
+static void bitmap_stop_daemon(struct bitmap *bitmap, mdk_thread_t **ptr)
+{
+ mdk_thread_t *daemon;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bitmap->lock, flags);
+ daemon = *ptr;
+ *ptr = NULL;
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+ if (daemon)
+ md_unregister_thread(daemon); /* destroy the thread */
+}
+
+static void bitmap_stop_daemons(struct bitmap *bitmap)
+{
+ /* the daemons can't stop themselves... they'll just exit instead... */
+ if (bitmap->writeback_daemon &&
+ current->pid != bitmap->writeback_daemon->tsk->pid)
+ bitmap_stop_daemon(bitmap, &bitmap->writeback_daemon);
+}
+
+static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
+ sector_t offset, int *blocks,
+ int create)
+{
+ /* If 'create', we might release the lock and reclaim it.
+ * The lock must have been taken with interrupts enabled.
+ * If !create, we don't release the lock.
+ */
+ sector_t chunk = offset >> CHUNK_BLOCK_SHIFT(bitmap);
+ unsigned long page = chunk >> PAGE_COUNTER_SHIFT;
+ unsigned long pageoff = (chunk & PAGE_COUNTER_MASK) << COUNTER_BYTE_SHIFT;
+ sector_t csize;
+
+ if (bitmap_checkpage(bitmap, page, create) < 0) {
+ csize = ((sector_t)1) << (CHUNK_BLOCK_SHIFT(bitmap));
+ *blocks = csize - (offset & (csize- 1));
+ return NULL;
+ }
+ /* now locked ... */
+
+ if (bitmap->bp[page].hijacked) { /* hijacked pointer */
+ /* should we use the first or second counter field
+ * of the hijacked pointer? */
+ int hi = (pageoff > PAGE_COUNTER_MASK);
+ csize = ((sector_t)1) << (CHUNK_BLOCK_SHIFT(bitmap) +
+ PAGE_COUNTER_SHIFT - 1);
+ *blocks = csize - (offset & (csize- 1));
+ return &((bitmap_counter_t *)
+ &bitmap->bp[page].map)[hi];
+ } else { /* page is allocated */
+ csize = ((sector_t)1) << (CHUNK_BLOCK_SHIFT(bitmap));
+ *blocks = csize - (offset & (csize- 1));
+ return (bitmap_counter_t *)
+ &(bitmap->bp[page].map[pageoff]);
+ }
+}
+
+int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors)
+{
+ if (!bitmap) return 0;
+ while (sectors) {
+ int blocks;
+ bitmap_counter_t *bmc;
+
+ spin_lock_irq(&bitmap->lock);
+ bmc = bitmap_get_counter(bitmap, offset, &blocks, 1);
+ if (!bmc) {
+ spin_unlock_irq(&bitmap->lock);
+ return 0;
+ }
+
+ switch(*bmc) {
+ case 0:
+ bitmap_file_set_bit(bitmap, offset);
+ bitmap_count_page(bitmap,offset, 1);
+ blk_plug_device(bitmap->mddev->queue);
+ /* fall through */
+ case 1:
+ *bmc = 2;
+ }
+ if ((*bmc & COUNTER_MAX) == COUNTER_MAX) BUG();
+ (*bmc)++;
+
+ spin_unlock_irq(&bitmap->lock);
+
+ offset += blocks;
+ if (sectors > blocks)
+ sectors -= blocks;
+ else sectors = 0;
+ }
+ return 0;
+}
+
+void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors,
+ int success)
+{
+ if (!bitmap) return;
+ while (sectors) {
+ int blocks;
+ unsigned long flags;
+ bitmap_counter_t *bmc;
+
+ spin_lock_irqsave(&bitmap->lock, flags);
+ bmc = bitmap_get_counter(bitmap, offset, &blocks, 0);
+ if (!bmc) {
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+ return;
+ }
+
+ if (!success && ! (*bmc & NEEDED_MASK))
+ *bmc |= NEEDED_MASK;
+
+ (*bmc)--;
+ if (*bmc <= 2) {
+ set_page_attr(bitmap,
+ filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)),
+ BITMAP_PAGE_CLEAN);
+ }
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+ offset += blocks;
+ if (sectors > blocks)
+ sectors -= blocks;
+ else sectors = 0;
+ }
+}
+
+int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks)
+{
+ bitmap_counter_t *bmc;
+ int rv;
+ if (bitmap == NULL) {/* FIXME or bitmap set as 'failed' */
+ *blocks = 1024;
+ return 1; /* always resync if no bitmap */
+ }
+ spin_lock_irq(&bitmap->lock);
+ bmc = bitmap_get_counter(bitmap, offset, blocks, 0);
+ rv = 0;
+ if (bmc) {
+ /* locked */
+ if (RESYNC(*bmc))
+ rv = 1;
+ else if (NEEDED(*bmc)) {
+ rv = 1;
+ *bmc |= RESYNC_MASK;
+ *bmc &= ~NEEDED_MASK;
+ }
+ }
+ spin_unlock_irq(&bitmap->lock);
+ return rv;
+}
+
+void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int aborted)
+{
+ bitmap_counter_t *bmc;
+ unsigned long flags;
+/*
+ if (offset == 0) printk("bitmap_end_sync 0 (%d)\n", aborted);
+*/ if (bitmap == NULL) {
+ *blocks = 1024;
+ return;
+ }
+ spin_lock_irqsave(&bitmap->lock, flags);
+ bmc = bitmap_get_counter(bitmap, offset, blocks, 0);
+ if (bmc == NULL)
+ goto unlock;
+ /* locked */
+/*
+ if (offset == 0) printk("bitmap_end sync found 0x%x, blocks %d\n", *bmc, *blocks);
+*/
+ if (RESYNC(*bmc)) {
+ *bmc &= ~RESYNC_MASK;
+
+ if (!NEEDED(*bmc) && aborted)
+ *bmc |= NEEDED_MASK;
+ else {
+ if (*bmc <= 2) {
+ set_page_attr(bitmap,
+ filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)),
+ BITMAP_PAGE_CLEAN);
+ }
+ }
+ }
+ unlock:
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+}
+
+void bitmap_close_sync(struct bitmap *bitmap)
+{
+ /* Sync has finished, and any bitmap chunks that weren't synced
+ * properly have been aborted. It remains to us to clear the
+ * RESYNC bit wherever it is still on
+ */
+ sector_t sector = 0;
+ int blocks;
+ if (!bitmap) return;
+ while (sector < bitmap->mddev->resync_max_sectors) {
+ bitmap_end_sync(bitmap, sector, &blocks, 0);
+/*
+ if (sector < 500) printk("bitmap_close_sync: sec %llu blks %d\n",
+ (unsigned long long)sector, blocks);
+*/ sector += blocks;
+ }
+}
+
+static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
+ unsigned long sectors, int in_sync)
+{
+ /* For each chunk covered by any of these sectors, set the
+ * counter to 1 and set resync_needed unless in_sync. They should all
+ * be 0 at this point
+ */
+ while (sectors) {
+ int secs;
+ bitmap_counter_t *bmc;
+ spin_lock_irq(&bitmap->lock);
+ bmc = bitmap_get_counter(bitmap, offset, &secs, 1);
+ if (!bmc) {
+ spin_unlock_irq(&bitmap->lock);
+ return;
+ }
+ if (! *bmc) {
+ struct page *page;
+ *bmc = 1 | (in_sync? 0 : NEEDED_MASK);
+ bitmap_count_page(bitmap, offset, 1);
+ page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
+ set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
+ }
+ spin_unlock_irq(&bitmap->lock);
+ if (sectors > secs)
+ sectors -= secs;
+ else
+ sectors = 0;
+ }
+}
+
+/*
+ * free memory that was allocated
+ */
+void bitmap_destroy(mddev_t *mddev)
+{
+ unsigned long k, pages;
+ struct bitmap_page *bp;
+ struct bitmap *bitmap = mddev->bitmap;
+
+ if (!bitmap) /* there was no bitmap */
+ return;
+
+ mddev->bitmap = NULL; /* disconnect from the md device */
+
+ /* release the bitmap file and kill the daemon */
+ bitmap_file_put(bitmap);
+
+ bp = bitmap->bp;
+ pages = bitmap->pages;
+
+ /* free all allocated memory */
+
+ mempool_destroy(bitmap->write_pool);
+
+ if (bp) /* deallocate the page memory */
+ for (k = 0; k < pages; k++)
+ if (bp[k].map && !bp[k].hijacked)
+ kfree(bp[k].map);
+ kfree(bp);
+ kfree(bitmap);
+}
+
+/*
+ * initialize the bitmap structure
+ * if this returns an error, bitmap_destroy must be called to do clean up
+ */
+int bitmap_create(mddev_t *mddev)
+{
+ struct bitmap *bitmap;
+ unsigned long blocks = mddev->resync_max_sectors;
+ unsigned long chunks;
+ unsigned long pages;
+ struct file *file = mddev->bitmap_file;
+ int err;
+
+ BUG_ON(sizeof(bitmap_super_t) != 256);
+
+ if (!file && !mddev->bitmap_offset) /* bitmap disabled, nothing to do */
+ return 0;
+
+ BUG_ON(file && mddev->bitmap_offset);
+
+ bitmap = kmalloc(sizeof(*bitmap), GFP_KERNEL);
+ if (!bitmap)
+ return -ENOMEM;
+
+ memset(bitmap, 0, sizeof(*bitmap));
+
+ spin_lock_init(&bitmap->lock);
+ bitmap->mddev = mddev;
+ mddev->bitmap = bitmap;
+
+ spin_lock_init(&bitmap->write_lock);
+ INIT_LIST_HEAD(&bitmap->complete_pages);
+ init_waitqueue_head(&bitmap->write_wait);
+ bitmap->write_pool = mempool_create(WRITE_POOL_SIZE, write_pool_alloc,
+ write_pool_free, NULL);
+ if (!bitmap->write_pool)
+ return -ENOMEM;
+
+ bitmap->file = file;
+ bitmap->offset = mddev->bitmap_offset;
+ if (file) get_file(file);
+ /* read superblock from bitmap file (this sets bitmap->chunksize) */
+ err = bitmap_read_sb(bitmap);
+ if (err)
+ return err;
+
+ bitmap->chunkshift = find_first_bit(&bitmap->chunksize,
+ sizeof(bitmap->chunksize));
+
+ /* now that chunksize and chunkshift are set, we can use these macros */
+ chunks = (blocks + CHUNK_BLOCK_RATIO(bitmap) - 1) /
+ CHUNK_BLOCK_RATIO(bitmap);
+ pages = (chunks + PAGE_COUNTER_RATIO - 1) / PAGE_COUNTER_RATIO;
+
+ BUG_ON(!pages);
+
+ bitmap->chunks = chunks;
+ bitmap->pages = pages;
+ bitmap->missing_pages = pages;
+ bitmap->counter_bits = COUNTER_BITS;
+
+ bitmap->syncchunk = ~0UL;
+
+#if INJECT_FATAL_FAULT_1
+ bitmap->bp = NULL;
+#else
+ bitmap->bp = kmalloc(pages * sizeof(*bitmap->bp), GFP_KERNEL);
+#endif
+ if (!bitmap->bp)
+ return -ENOMEM;
+ memset(bitmap->bp, 0, pages * sizeof(*bitmap->bp));
+
+ bitmap->flags |= BITMAP_ACTIVE;
+
+ /* now that we have some pages available, initialize the in-memory
+ * bitmap from the on-disk bitmap */
+ err = bitmap_init_from_disk(bitmap, mddev->recovery_cp == MaxSector);
+ if (err)
+ return err;
+
+ printk(KERN_INFO "created bitmap (%lu pages) for device %s\n",
+ pages, bmname(bitmap));
+
+ /* kick off the bitmap daemons */
+ err = bitmap_start_daemons(bitmap);
+ if (err)
+ return err;
+ return bitmap_update_sb(bitmap);
+}
+
+/* the bitmap API -- for raid personalities */
+EXPORT_SYMBOL(bitmap_startwrite);
+EXPORT_SYMBOL(bitmap_endwrite);
+EXPORT_SYMBOL(bitmap_start_sync);
+EXPORT_SYMBOL(bitmap_end_sync);
+EXPORT_SYMBOL(bitmap_unplug);
+EXPORT_SYMBOL(bitmap_close_sync);
+EXPORT_SYMBOL(bitmap_daemon_work);
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 0dd6c2b5391..d0a4bab220e 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -704,8 +704,7 @@ static void crypt_dtr(struct dm_target *ti)
mempool_destroy(cc->page_pool);
mempool_destroy(cc->io_pool);
- if (cc->iv_mode)
- kfree(cc->iv_mode);
+ kfree(cc->iv_mode);
if (cc->iv_gen_ops && cc->iv_gen_ops->dtr)
cc->iv_gen_ops->dtr(cc);
crypto_free_tfm(cc->tfm);
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index ee3c869d970..200a0688f71 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -122,14 +122,6 @@ static struct hash_cell *__get_uuid_cell(const char *str)
/*-----------------------------------------------------------------
* Inserting, removing and renaming a device.
*---------------------------------------------------------------*/
-static inline char *kstrdup(const char *str)
-{
- char *r = kmalloc(strlen(str) + 1, GFP_KERNEL);
- if (r)
- strcpy(r, str);
- return r;
-}
-
static struct hash_cell *alloc_cell(const char *name, const char *uuid,
struct mapped_device *md)
{
@@ -139,7 +131,7 @@ static struct hash_cell *alloc_cell(const char *name, const char *uuid,
if (!hc)
return NULL;
- hc->name = kstrdup(name);
+ hc->name = kstrdup(name, GFP_KERNEL);
if (!hc->name) {
kfree(hc);
return NULL;
@@ -149,7 +141,7 @@ static struct hash_cell *alloc_cell(const char *name, const char *uuid,
hc->uuid = NULL;
else {
- hc->uuid = kstrdup(uuid);
+ hc->uuid = kstrdup(uuid, GFP_KERNEL);
if (!hc->uuid) {
kfree(hc->name);
kfree(hc);
@@ -273,7 +265,7 @@ static int dm_hash_rename(const char *old, const char *new)
/*
* duplicate new.
*/
- new_name = kstrdup(new);
+ new_name = kstrdup(new, GFP_KERNEL);
if (!new_name)
return -ENOMEM;
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 1e97b3c12bd..0c1b8520ef8 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -985,6 +985,9 @@ static int do_end_io(struct multipath *m, struct bio *bio,
if (!error)
return 0; /* I/O complete */
+ if ((error == -EWOULDBLOCK) && bio_rw_ahead(bio))
+ return error;
+
spin_lock(&m->lock);
if (!m->nr_valid_paths) {
if (!m->queue_if_no_path || m->suspended) {
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index 161e9aa8729..8d740013d74 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -217,8 +217,7 @@ static int linear_run (mddev_t *mddev)
return 0;
out:
- if (conf)
- kfree(conf);
+ kfree(conf);
return 1;
}
@@ -269,9 +268,8 @@ static int linear_make_request (request_queue_t *q, struct bio *bio)
* split it.
*/
struct bio_pair *bp;
- bp = bio_split(bio, bio_split_pool,
- (bio->bi_sector + (bio->bi_size >> 9) -
- (tmp_dev->offset + tmp_dev->size))<<1);
+ bp = bio_split(bio, bio_split_pool,
+ ((tmp_dev->offset + tmp_dev->size)<<1) - bio->bi_sector);
if (linear_make_request(q, &bp->bio1))
generic_make_request(&bp->bio1);
if (linear_make_request(q, &bp->bio2))
diff --git a/drivers/md/md.c b/drivers/md/md.c
index d899204d374..3802f7a17f1 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -19,6 +19,9 @@
Neil Brown <neilb@cse.unsw.edu.au>.
+ - persistent bitmap code
+ Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, 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, or (at your option)
@@ -33,6 +36,7 @@
#include <linux/config.h>
#include <linux/linkage.h>
#include <linux/raid/md.h>
+#include <linux/raid/bitmap.h>
#include <linux/sysctl.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/buffer_head.h> /* for invalidate_bdev */
@@ -40,6 +44,8 @@
#include <linux/init.h>
+#include <linux/file.h>
+
#ifdef CONFIG_KMOD
#include <linux/kmod.h>
#endif
@@ -189,8 +195,7 @@ static mddev_t * mddev_find(dev_t unit)
if (mddev->unit == unit) {
mddev_get(mddev);
spin_unlock(&all_mddevs_lock);
- if (new)
- kfree(new);
+ kfree(new);
return mddev;
}
@@ -218,6 +223,8 @@ static mddev_t * mddev_find(dev_t unit)
INIT_LIST_HEAD(&new->all_mddevs);
init_timer(&new->safemode_timer);
atomic_set(&new->active, 1);
+ spin_lock_init(&new->write_lock);
+ init_waitqueue_head(&new->sb_wait);
new->queue = blk_alloc_queue(GFP_KERNEL);
if (!new->queue) {
@@ -320,6 +327,40 @@ static void free_disk_sb(mdk_rdev_t * rdev)
}
+static int super_written(struct bio *bio, unsigned int bytes_done, int error)
+{
+ mdk_rdev_t *rdev = bio->bi_private;
+ if (bio->bi_size)
+ return 1;
+
+ if (error || !test_bit(BIO_UPTODATE, &bio->bi_flags))
+ md_error(rdev->mddev, rdev);
+
+ if (atomic_dec_and_test(&rdev->mddev->pending_writes))
+ wake_up(&rdev->mddev->sb_wait);
+ return 0;
+}
+
+void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
+ sector_t sector, int size, struct page *page)
+{
+ /* write first size bytes of page to sector of rdev
+ * Increment mddev->pending_writes before returning
+ * and decrement it on completion, waking up sb_wait
+ * if zero is reached.
+ * If an error occurred, call md_error
+ */
+ struct bio *bio = bio_alloc(GFP_NOIO, 1);
+
+ bio->bi_bdev = rdev->bdev;
+ bio->bi_sector = sector;
+ bio_add_page(bio, page, size, 0);
+ bio->bi_private = rdev;
+ bio->bi_end_io = super_written;
+ atomic_inc(&mddev->pending_writes);
+ submit_bio((1<<BIO_RW)|(1<<BIO_RW_SYNC), bio);
+}
+
static int bi_complete(struct bio *bio, unsigned int bytes_done, int error)
{
if (bio->bi_size)
@@ -329,7 +370,7 @@ static int bi_complete(struct bio *bio, unsigned int bytes_done, int error)
return 0;
}
-static int sync_page_io(struct block_device *bdev, sector_t sector, int size,
+int sync_page_io(struct block_device *bdev, sector_t sector, int size,
struct page *page, int rw)
{
struct bio *bio = bio_alloc(GFP_NOIO, 1);
@@ -416,11 +457,8 @@ static int sb_equal(mdp_super_t *sb1, mdp_super_t *sb2)
ret = 1;
abort:
- if (tmp1)
- kfree(tmp1);
- if (tmp2)
- kfree(tmp2);
-
+ kfree(tmp1);
+ kfree(tmp2);
return ret;
}
@@ -569,6 +607,8 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
mdp_disk_t *desc;
mdp_super_t *sb = (mdp_super_t *)page_address(rdev->sb_page);
+ rdev->raid_disk = -1;
+ rdev->in_sync = 0;
if (mddev->raid_disks == 0) {
mddev->major_version = 0;
mddev->minor_version = sb->minor_version;
@@ -599,16 +639,35 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
memcpy(mddev->uuid+12,&sb->set_uuid3, 4);
mddev->max_disks = MD_SB_DISKS;
- } else {
- __u64 ev1;
- ev1 = md_event(sb);
+
+ if (sb->state & (1<<MD_SB_BITMAP_PRESENT) &&
+ mddev->bitmap_file == NULL) {
+ if (mddev->level != 1) {
+ /* FIXME use a better test */
+ printk(KERN_WARNING "md: bitmaps only support for raid1\n");
+ return -EINVAL;
+ }
+ mddev->bitmap_offset = (MD_SB_BYTES >> 9);
+ }
+
+ } else if (mddev->pers == NULL) {
+ /* Insist on good event counter while assembling */
+ __u64 ev1 = md_event(sb);
++ev1;
if (ev1 < mddev->events)
return -EINVAL;
- }
+ } else if (mddev->bitmap) {
+ /* if adding to array with a bitmap, then we can accept an
+ * older device ... but not too old.
+ */
+ __u64 ev1 = md_event(sb);
+ if (ev1 < mddev->bitmap->events_cleared)
+ return 0;
+ } else /* just a hot-add of a new device, leave raid_disk at -1 */
+ return 0;
+
if (mddev->level != LEVEL_MULTIPATH) {
- rdev->raid_disk = -1;
- rdev->in_sync = rdev->faulty = 0;
+ rdev->faulty = 0;
desc = sb->disks + rdev->desc_nr;
if (desc->state & (1<<MD_DISK_FAULTY))
@@ -618,7 +677,8 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
rdev->in_sync = 1;
rdev->raid_disk = desc->raid_disk;
}
- }
+ } else /* MULTIPATH are always insync */
+ rdev->in_sync = 1;
return 0;
}
@@ -683,6 +743,9 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
sb->layout = mddev->layout;
sb->chunk_size = mddev->chunk_size;
+ if (mddev->bitmap && mddev->bitmap_file == NULL)
+ sb->state |= (1<<MD_SB_BITMAP_PRESENT);
+
sb->disks[0].state = (1<<MD_DISK_REMOVED);
ITERATE_RDEV(mddev,rdev2,tmp) {
mdp_disk_t *d;
@@ -780,7 +843,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
case 0:
sb_offset = rdev->bdev->bd_inode->i_size >> 9;
sb_offset -= 8*2;
- sb_offset &= ~(4*2-1);
+ sb_offset &= ~(sector_t)(4*2-1);
/* convert from sectors to K */
sb_offset /= 2;
break;
@@ -860,6 +923,8 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
{
struct mdp_superblock_1 *sb = (struct mdp_superblock_1*)page_address(rdev->sb_page);
+ rdev->raid_disk = -1;
+ rdev->in_sync = 0;
if (mddev->raid_disks == 0) {
mddev->major_version = 1;
mddev->patch_version = 0;
@@ -877,13 +942,30 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
memcpy(mddev->uuid, sb->set_uuid, 16);
mddev->max_disks = (4096-256)/2;
- } else {
- __u64 ev1;
- ev1 = le64_to_cpu(sb->events);
+
+ if ((le32_to_cpu(sb->feature_map) & 1) &&
+ mddev->bitmap_file == NULL ) {
+ if (mddev->level != 1) {
+ printk(KERN_WARNING "md: bitmaps only supported for raid1\n");
+ return -EINVAL;
+ }
+ mddev->bitmap_offset = (__s32)le32_to_cpu(sb->bitmap_offset);
+ }
+ } else if (mddev->pers == NULL) {
+ /* Insist of good event counter while assembling */
+ __u64 ev1 = le64_to_cpu(sb->events);
++ev1;
if (ev1 < mddev->events)
return -EINVAL;
- }
+ } else if (mddev->bitmap) {
+ /* If adding to array with a bitmap, then we can accept an
+ * older device, but not too old.
+ */
+ __u64 ev1 = le64_to_cpu(sb->events);
+ if (ev1 < mddev->bitmap->events_cleared)
+ return 0;
+ } else /* just a hot-add of a new device, leave raid_disk at -1 */
+ return 0;
if (mddev->level != LEVEL_MULTIPATH) {
int role;
@@ -891,14 +973,10 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
role = le16_to_cpu(sb->dev_roles[rdev->desc_nr]);
switch(role) {
case 0xffff: /* spare */
- rdev->in_sync = 0;
rdev->faulty = 0;
- rdev->raid_disk = -1;
break;
case 0xfffe: /* faulty */
- rdev->in_sync = 0;
rdev->faulty = 1;
- rdev->raid_disk = -1;
break;
default:
rdev->in_sync = 1;
@@ -906,7 +984,9 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
rdev->raid_disk = role;
break;
}
- }
+ } else /* MULTIPATH are always insync */
+ rdev->in_sync = 1;
+
return 0;
}
@@ -933,6 +1013,11 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
else
sb->resync_offset = cpu_to_le64(0);
+ if (mddev->bitmap && mddev->bitmap_file == NULL) {
+ sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset);
+ sb->feature_map = cpu_to_le32(1);
+ }
+
max_dev = 0;
ITERATE_RDEV(mddev,rdev2,tmp)
if (rdev2->desc_nr+1 > max_dev)
@@ -1196,8 +1281,11 @@ void md_print_devices(void)
printk("md: * <COMPLETE RAID STATE PRINTOUT> *\n");
printk("md: **********************************\n");
ITERATE_MDDEV(mddev,tmp) {
- printk("%s: ", mdname(mddev));
+ if (mddev->bitmap)
+ bitmap_print_sb(mddev->bitmap);
+ else
+ printk("%s: ", mdname(mddev));
ITERATE_RDEV(mddev,rdev,tmp2)
printk("<%s>", bdevname(rdev->bdev,b));
printk("\n");
@@ -1210,30 +1298,6 @@ void md_print_devices(void)
}
-static int write_disk_sb(mdk_rdev_t * rdev)
-{
- char b[BDEVNAME_SIZE];
- if (!rdev->sb_loaded) {
- MD_BUG();
- return 1;
- }
- if (rdev->faulty) {
- MD_BUG();
- return 1;
- }
-
- dprintk(KERN_INFO "(write) %s's sb offset: %llu\n",
- bdevname(rdev->bdev,b),
- (unsigned long long)rdev->sb_offset);
-
- if (sync_page_io(rdev->bdev, rdev->sb_offset<<1, MD_SB_BYTES, rdev->sb_page, WRITE))
- return 0;
-
- printk("md: write_disk_sb failed for device %s\n",
- bdevname(rdev->bdev,b));
- return 1;
-}
-
static void sync_sbs(mddev_t * mddev)
{
mdk_rdev_t *rdev;
@@ -1248,12 +1312,14 @@ static void sync_sbs(mddev_t * mddev)
static void md_update_sb(mddev_t * mddev)
{
- int err, count = 100;
+ int err;
struct list_head *tmp;
mdk_rdev_t *rdev;
+ int sync_req;
- mddev->sb_dirty = 0;
repeat:
+ spin_lock(&mddev->write_lock);
+ sync_req = mddev->in_sync;
mddev->utime = get_seconds();
mddev->events ++;
@@ -1266,20 +1332,26 @@ repeat:
MD_BUG();
mddev->events --;
}
+ mddev->sb_dirty = 2;
sync_sbs(mddev);
/*
* do not write anything to disk if using
* nonpersistent superblocks
*/
- if (!mddev->persistent)
+ if (!mddev->persistent) {
+ mddev->sb_dirty = 0;
+ spin_unlock(&mddev->write_lock);
+ wake_up(&mddev->sb_wait);
return;
+ }
+ spin_unlock(&mddev->write_lock);
dprintk(KERN_INFO
"md: updating %s RAID superblock on device (in sync %d)\n",
mdname(mddev),mddev->in_sync);
- err = 0;
+ err = bitmap_update_sb(mddev->bitmap);
ITERATE_RDEV(mddev,rdev,tmp) {
char b[BDEVNAME_SIZE];
dprintk(KERN_INFO "md: ");
@@ -1288,22 +1360,32 @@ repeat:
dprintk("%s ", bdevname(rdev->bdev,b));
if (!rdev->faulty) {
- err += write_disk_sb(rdev);
+ md_super_write(mddev,rdev,
+ rdev->sb_offset<<1, MD_SB_BYTES,
+ rdev->sb_page);
+ dprintk(KERN_INFO "(write) %s's sb offset: %llu\n",
+ bdevname(rdev->bdev,b),
+ (unsigned long long)rdev->sb_offset);
+
} else
dprintk(")\n");
- if (!err && mddev->level == LEVEL_MULTIPATH)
+ if (mddev->level == LEVEL_MULTIPATH)
/* only need to write one superblock... */
break;
}
- if (err) {
- if (--count) {
- printk(KERN_ERR "md: errors occurred during superblock"
- " update, repeating\n");
- goto repeat;
- }
- printk(KERN_ERR \
- "md: excessive errors occurred during superblock update, exiting\n");
+ wait_event(mddev->sb_wait, atomic_read(&mddev->pending_writes)==0);
+ /* if there was a failure, sb_dirty was set to 1, and we re-write super */
+
+ spin_lock(&mddev->write_lock);
+ if (mddev->in_sync != sync_req|| mddev->sb_dirty == 1) {
+ /* have to write it out again */
+ spin_unlock(&mddev->write_lock);
+ goto repeat;
}
+ mddev->sb_dirty = 0;
+ spin_unlock(&mddev->write_lock);
+ wake_up(&mddev->sb_wait);
+
}
/*
@@ -1607,12 +1689,19 @@ static int do_md_run(mddev_t * mddev)
mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */
- err = mddev->pers->run(mddev);
+ /* before we start the array running, initialise the bitmap */
+ err = bitmap_create(mddev);
+ if (err)
+ printk(KERN_ERR "%s: failed to create bitmap (%d)\n",
+ mdname(mddev), err);
+ else
+ err = mddev->pers->run(mddev);
if (err) {
printk(KERN_ERR "md: pers->run() failed ...\n");
module_put(mddev->pers->owner);
mddev->pers = NULL;
- return -EINVAL;
+ bitmap_destroy(mddev);
+ return err;
}
atomic_set(&mddev->writes_pending,0);
mddev->safemode = 0;
@@ -1725,6 +1814,14 @@ static int do_md_stop(mddev_t * mddev, int ro)
if (ro)
set_disk_ro(disk, 1);
}
+
+ bitmap_destroy(mddev);
+ if (mddev->bitmap_file) {
+ atomic_set(&mddev->bitmap_file->f_dentry->d_inode->i_writecount, 1);
+ fput(mddev->bitmap_file);
+ mddev->bitmap_file = NULL;
+ }
+
/*
* Free resources if final stop
*/
@@ -1983,6 +2080,42 @@ static int get_array_info(mddev_t * mddev, void __user * arg)
return 0;
}
+static int get_bitmap_file(mddev_t * mddev, void * arg)
+{
+ mdu_bitmap_file_t *file = NULL; /* too big for stack allocation */
+ char *ptr, *buf = NULL;
+ int err = -ENOMEM;
+
+ file = kmalloc(sizeof(*file), GFP_KERNEL);
+ if (!file)
+ goto out;
+
+ /* bitmap disabled, zero the first byte and copy out */
+ if (!mddev->bitmap || !mddev->bitmap->file) {
+ file->pathname[0] = '\0';
+ goto copy_out;
+ }
+
+ buf = kmalloc(sizeof(file->pathname), GFP_KERNEL);
+ if (!buf)
+ goto out;
+
+ ptr = file_path(mddev->bitmap->file, buf, sizeof(file->pathname));
+ if (!ptr)
+ goto out;
+
+ strcpy(file->pathname, ptr);
+
+copy_out:
+ err = 0;
+ if (copy_to_user(arg, file, sizeof(*file)))
+ err = -EFAULT;
+out:
+ kfree(buf);
+ kfree(file);
+ return err;
+}
+
static int get_disk_info(mddev_t * mddev, void __user * arg)
{
mdu_disk_info_t info;
@@ -2078,11 +2211,25 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
PTR_ERR(rdev));
return PTR_ERR(rdev);
}
+ /* set save_raid_disk if appropriate */
+ if (!mddev->persistent) {
+ if (info->state & (1<<MD_DISK_SYNC) &&
+ info->raid_disk < mddev->raid_disks)
+ rdev->raid_disk = info->raid_disk;
+ else
+ rdev->raid_disk = -1;
+ } else
+ super_types[mddev->major_version].
+ validate_super(mddev, rdev);
+ rdev->saved_raid_disk = rdev->raid_disk;
+
rdev->in_sync = 0; /* just to be sure */
rdev->raid_disk = -1;
err = bind_rdev_to_array(rdev, mddev);
if (err)
export_rdev(rdev);
+
+ set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
if (mddev->thread)
md_wakeup_thread(mddev->thread);
return err;
@@ -2256,6 +2403,49 @@ abort_export:
return err;
}
+/* similar to deny_write_access, but accounts for our holding a reference
+ * to the file ourselves */
+static int deny_bitmap_write_access(struct file * file)
+{
+ struct inode *inode = file->f_mapping->host;
+
+ spin_lock(&inode->i_lock);
+ if (atomic_read(&inode->i_writecount) > 1) {
+ spin_unlock(&inode->i_lock);
+ return -ETXTBSY;
+ }
+ atomic_set(&inode->i_writecount, -1);
+ spin_unlock(&inode->i_lock);
+
+ return 0;
+}
+
+static int set_bitmap_file(mddev_t *mddev, int fd)
+{
+ int err;
+
+ if (mddev->pers)
+ return -EBUSY;
+
+ mddev->bitmap_file = fget(fd);
+
+ if (mddev->bitmap_file == NULL) {
+ printk(KERN_ERR "%s: error: failed to get bitmap file\n",
+ mdname(mddev));
+ return -EBADF;
+ }
+
+ err = deny_bitmap_write_access(mddev->bitmap_file);
+ if (err) {
+ printk(KERN_ERR "%s: error: bitmap file is already in use\n",
+ mdname(mddev));
+ fput(mddev->bitmap_file);
+ mddev->bitmap_file = NULL;
+ } else
+ mddev->bitmap_offset = 0; /* file overrides offset */
+ return err;
+}
+
/*
* set_array_info is used two different ways
* The original usage is when creating a new array.
@@ -2567,8 +2757,10 @@ static int md_ioctl(struct inode *inode, struct file *file,
/*
* Commands querying/configuring an existing array:
*/
- /* if we are initialised yet, only ADD_NEW_DISK or STOP_ARRAY is allowed */
- if (!mddev->raid_disks && cmd != ADD_NEW_DISK && cmd != STOP_ARRAY && cmd != RUN_ARRAY) {
+ /* if we are not initialised yet, only ADD_NEW_DISK, STOP_ARRAY,
+ * RUN_ARRAY, and SET_BITMAP_FILE are allowed */
+ if (!mddev->raid_disks && cmd != ADD_NEW_DISK && cmd != STOP_ARRAY
+ && cmd != RUN_ARRAY && cmd != SET_BITMAP_FILE) {
err = -ENODEV;
goto abort_unlock;
}
@@ -2582,6 +2774,10 @@ static int md_ioctl(struct inode *inode, struct file *file,
err = get_array_info(mddev, argp);
goto done_unlock;
+ case GET_BITMAP_FILE:
+ err = get_bitmap_file(mddev, (void *)arg);
+ goto done_unlock;
+
case GET_DISK_INFO:
err = get_disk_info(mddev, argp);
goto done_unlock;
@@ -2662,6 +2858,10 @@ static int md_ioctl(struct inode *inode, struct file *file,
err = do_md_run (mddev);
goto done_unlock;
+ case SET_BITMAP_FILE:
+ err = set_bitmap_file(mddev, (int)arg);
+ goto done_unlock;
+
default:
if (_IOC_TYPE(cmd) == MD_MAJOR)
printk(KERN_WARNING "md: %s(pid %d) used"
@@ -2773,10 +2973,10 @@ static int md_thread(void * arg)
while (thread->run) {
void (*run)(mddev_t *);
- wait_event_interruptible(thread->wqueue,
- test_bit(THREAD_WAKEUP, &thread->flags));
- if (current->flags & PF_FREEZE)
- refrigerator(PF_FREEZE);
+ wait_event_interruptible_timeout(thread->wqueue,
+ test_bit(THREAD_WAKEUP, &thread->flags),
+ thread->timeout);
+ try_to_freeze();
clear_bit(THREAD_WAKEUP, &thread->flags);
@@ -2820,6 +3020,7 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev,
thread->run = run;
thread->mddev = mddev;
thread->name = name;
+ thread->timeout = MAX_SCHEDULE_TIMEOUT;
ret = kernel_thread(md_thread, thread, 0);
if (ret < 0) {
kfree(thread);
@@ -2858,13 +3059,13 @@ void md_error(mddev_t *mddev, mdk_rdev_t *rdev)
if (!rdev || rdev->faulty)
return;
-
+/*
dprintk("md_error dev:%s, rdev:(%d:%d), (caller: %p,%p,%p,%p).\n",
mdname(mddev),
MAJOR(rdev->bdev->bd_dev), MINOR(rdev->bdev->bd_dev),
__builtin_return_address(0),__builtin_return_address(1),
__builtin_return_address(2),__builtin_return_address(3));
-
+*/
if (!mddev->pers->error_handler)
return;
mddev->pers->error_handler(mddev,rdev);
@@ -3018,6 +3219,7 @@ static int md_seq_show(struct seq_file *seq, void *v)
struct list_head *tmp2;
mdk_rdev_t *rdev;
int i;
+ struct bitmap *bitmap;
if (v == (void*)1) {
seq_printf(seq, "Personalities : ");
@@ -3070,10 +3272,35 @@ static int md_seq_show(struct seq_file *seq, void *v)
if (mddev->pers) {
mddev->pers->status (seq, mddev);
seq_printf(seq, "\n ");
- if (mddev->curr_resync > 2)
+ if (mddev->curr_resync > 2) {
status_resync (seq, mddev);
- else if (mddev->curr_resync == 1 || mddev->curr_resync == 2)
- seq_printf(seq, " resync=DELAYED");
+ seq_printf(seq, "\n ");
+ } else if (mddev->curr_resync == 1 || mddev->curr_resync == 2)
+ seq_printf(seq, " resync=DELAYED\n ");
+ } else
+ seq_printf(seq, "\n ");
+
+ if ((bitmap = mddev->bitmap)) {
+ unsigned long chunk_kb;
+ unsigned long flags;
+ spin_lock_irqsave(&bitmap->lock, flags);
+ chunk_kb = bitmap->chunksize >> 10;
+ seq_printf(seq, "bitmap: %lu/%lu pages [%luKB], "
+ "%lu%s chunk",
+ bitmap->pages - bitmap->missing_pages,
+ bitmap->pages,
+ (bitmap->pages - bitmap->missing_pages)
+ << (PAGE_SHIFT - 10),
+ chunk_kb ? chunk_kb : bitmap->chunksize,
+ chunk_kb ? "KB" : "B");
+ if (bitmap->file) {
+ seq_printf(seq, ", file: ");
+ seq_path(seq, bitmap->file->f_vfsmnt,
+ bitmap->file->f_dentry," \t\n");
+ }
+
+ seq_printf(seq, "\n");
+ spin_unlock_irqrestore(&bitmap->lock, flags);
}
seq_printf(seq, "\n");
@@ -3176,19 +3403,28 @@ void md_done_sync(mddev_t *mddev, int blocks, int ok)
}
-void md_write_start(mddev_t *mddev)
+/* md_write_start(mddev, bi)
+ * If we need to update some array metadata (e.g. 'active' flag
+ * in superblock) before writing, schedule a superblock update
+ * and wait for it to complete.
+ */
+void md_write_start(mddev_t *mddev, struct bio *bi)
{
- if (!atomic_read(&mddev->writes_pending)) {
- mddev_lock_uninterruptible(mddev);
+ DEFINE_WAIT(w);
+ if (bio_data_dir(bi) != WRITE)
+ return;
+
+ atomic_inc(&mddev->writes_pending);
+ if (mddev->in_sync) {
+ spin_lock(&mddev->write_lock);
if (mddev->in_sync) {
mddev->in_sync = 0;
- del_timer(&mddev->safemode_timer);
- md_update_sb(mddev);
+ mddev->sb_dirty = 1;
+ md_wakeup_thread(mddev->thread);
}
- atomic_inc(&mddev->writes_pending);
- mddev_unlock(mddev);
- } else
- atomic_inc(&mddev->writes_pending);
+ spin_unlock(&mddev->write_lock);
+ }
+ wait_event(mddev->sb_wait, mddev->sb_dirty==0);
}
void md_write_end(mddev_t *mddev)
@@ -3201,37 +3437,6 @@ void md_write_end(mddev_t *mddev)
}
}
-static inline void md_enter_safemode(mddev_t *mddev)
-{
- if (!mddev->safemode) return;
- if (mddev->safemode == 2 &&
- (atomic_read(&mddev->writes_pending) || mddev->in_sync ||
- mddev->recovery_cp != MaxSector))
- return; /* avoid the lock */
- mddev_lock_uninterruptible(mddev);
- if (mddev->safemode && !atomic_read(&mddev->writes_pending) &&
- !mddev->in_sync && mddev->recovery_cp == MaxSector) {
- mddev->in_sync = 1;
- md_update_sb(mddev);
- }
- mddev_unlock(mddev);
-
- if (mddev->safemode == 1)
- mddev->safemode = 0;
-}
-
-void md_handle_safemode(mddev_t *mddev)
-{
- if (signal_pending(current)) {
- printk(KERN_INFO "md: %s in immediate safe mode\n",
- mdname(mddev));
- mddev->safemode = 2;
- flush_signals(current);
- }
- md_enter_safemode(mddev);
-}
-
-
static DECLARE_WAIT_QUEUE_HEAD(resync_wait);
#define SYNC_MARKS 10
@@ -3241,12 +3446,13 @@ static void md_do_sync(mddev_t *mddev)
mddev_t *mddev2;
unsigned int currspeed = 0,
window;
- sector_t max_sectors,j;
+ sector_t max_sectors,j, io_sectors;
unsigned long mark[SYNC_MARKS];
sector_t mark_cnt[SYNC_MARKS];
int last_mark,m;
struct list_head *tmp;
sector_t last_check;
+ int skipped = 0;
/* just incase thread restarts... */
if (test_bit(MD_RECOVERY_DONE, &mddev->recovery))
@@ -3312,7 +3518,7 @@ static void md_do_sync(mddev_t *mddev)
if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
/* resync follows the size requested by the personality,
- * which default to physical size, but can be virtual size
+ * which defaults to physical size, but can be virtual size
*/
max_sectors = mddev->resync_max_sectors;
else
@@ -3327,13 +3533,15 @@ static void md_do_sync(mddev_t *mddev)
sysctl_speed_limit_max);
is_mddev_idle(mddev); /* this also initializes IO event counters */
- if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
+ /* we don't use the checkpoint if there's a bitmap */
+ if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && !mddev->bitmap)
j = mddev->recovery_cp;
else
j = 0;
+ io_sectors = 0;
for (m = 0; m < SYNC_MARKS; m++) {
mark[m] = jiffies;
- mark_cnt[m] = j;
+ mark_cnt[m] = io_sectors;
}
last_mark = 0;
mddev->resync_mark = mark[last_mark];
@@ -3358,21 +3566,29 @@ static void md_do_sync(mddev_t *mddev)
}
while (j < max_sectors) {
- int sectors;
+ sector_t sectors;
- sectors = mddev->pers->sync_request(mddev, j, currspeed < sysctl_speed_limit_min);
- if (sectors < 0) {
+ skipped = 0;
+ sectors = mddev->pers->sync_request(mddev, j, &skipped,
+ currspeed < sysctl_speed_limit_min);
+ if (sectors == 0) {
set_bit(MD_RECOVERY_ERR, &mddev->recovery);
goto out;
}
- atomic_add(sectors, &mddev->recovery_active);
+
+ if (!skipped) { /* actual IO requested */
+ io_sectors += sectors;
+ atomic_add(sectors, &mddev->recovery_active);
+ }
+
j += sectors;
if (j>1) mddev->curr_resync = j;
- if (last_check + window > j || j == max_sectors)
+
+ if (last_check + window > io_sectors || j == max_sectors)
continue;
- last_check = j;
+ last_check = io_sectors;
if (test_bit(MD_RECOVERY_INTR, &mddev->recovery) ||
test_bit(MD_RECOVERY_ERR, &mddev->recovery))
@@ -3386,7 +3602,7 @@ static void md_do_sync(mddev_t *mddev)
mddev->resync_mark = mark[next];
mddev->resync_mark_cnt = mark_cnt[next];
mark[next] = jiffies;
- mark_cnt[next] = j - atomic_read(&mddev->recovery_active);
+ mark_cnt[next] = io_sectors - atomic_read(&mddev->recovery_active);
last_mark = next;
}
@@ -3413,7 +3629,8 @@ static void md_do_sync(mddev_t *mddev)
mddev->queue->unplug_fn(mddev->queue);
cond_resched();
- currspeed = ((unsigned long)(j-mddev->resync_mark_cnt))/2/((jiffies-mddev->resync_mark)/HZ +1) +1;
+ currspeed = ((unsigned long)(io_sectors-mddev->resync_mark_cnt))/2
+ /((jiffies-mddev->resync_mark)/HZ +1) +1;
if (currspeed > sysctl_speed_limit_min) {
if ((currspeed > sysctl_speed_limit_max) ||
@@ -3433,7 +3650,7 @@ static void md_do_sync(mddev_t *mddev)
wait_event(mddev->recovery_wait, !atomic_read(&mddev->recovery_active));
/* tell personality that we are finished */
- mddev->pers->sync_request(mddev, max_sectors, 1);
+ mddev->pers->sync_request(mddev, max_sectors, &skipped, 1);
if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) &&
mddev->curr_resync > 2 &&
@@ -3447,7 +3664,6 @@ static void md_do_sync(mddev_t *mddev)
mddev->recovery_cp = MaxSector;
}
- md_enter_safemode(mddev);
skip:
mddev->curr_resync = 0;
wake_up(&resync_wait);
@@ -3484,20 +3700,48 @@ void md_check_recovery(mddev_t *mddev)
struct list_head *rtmp;
- dprintk(KERN_INFO "md: recovery thread got woken up ...\n");
+ if (mddev->bitmap)
+ bitmap_daemon_work(mddev->bitmap);
if (mddev->ro)
return;
+
+ if (signal_pending(current)) {
+ if (mddev->pers->sync_request) {
+ printk(KERN_INFO "md: %s in immediate safe mode\n",
+ mdname(mddev));
+ mddev->safemode = 2;
+ }
+ flush_signals(current);
+ }
+
if ( ! (
mddev->sb_dirty ||
test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) ||
- test_bit(MD_RECOVERY_DONE, &mddev->recovery)
+ test_bit(MD_RECOVERY_DONE, &mddev->recovery) ||
+ (mddev->safemode == 1) ||
+ (mddev->safemode == 2 && ! atomic_read(&mddev->writes_pending)
+ && !mddev->in_sync && mddev->recovery_cp == MaxSector)
))
return;
+
if (mddev_trylock(mddev)==0) {
int spares =0;
+
+ spin_lock(&mddev->write_lock);
+ if (mddev->safemode && !atomic_read(&mddev->writes_pending) &&
+ !mddev->in_sync && mddev->recovery_cp == MaxSector) {
+ mddev->in_sync = 1;
+ mddev->sb_dirty = 1;
+ }
+ if (mddev->safemode == 1)
+ mddev->safemode = 0;
+ spin_unlock(&mddev->write_lock);
+
if (mddev->sb_dirty)
md_update_sb(mddev);
+
+
if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) &&
!test_bit(MD_RECOVERY_DONE, &mddev->recovery)) {
/* resync/recovery still happening */
@@ -3515,6 +3759,14 @@ void md_check_recovery(mddev_t *mddev)
mddev->pers->spare_active(mddev);
}
md_update_sb(mddev);
+
+ /* if array is no-longer degraded, then any saved_raid_disk
+ * information must be scrapped
+ */
+ if (!mddev->degraded)
+ ITERATE_RDEV(mddev,rdev,rtmp)
+ rdev->saved_raid_disk = -1;
+
mddev->recovery = 0;
/* flag recovery needed just to double check */
set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
@@ -3557,6 +3809,13 @@ void md_check_recovery(mddev_t *mddev)
set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
if (!spares)
set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
+ if (spares && mddev->bitmap && ! mddev->bitmap->file) {
+ /* We are adding a device or devices to an array
+ * which has the bitmap stored on all devices.
+ * So make sure all bitmap pages get written
+ */
+ bitmap_write_all(mddev->bitmap);
+ }
mddev->sync_thread = md_register_thread(md_do_sync,
mddev,
"%s_resync");
@@ -3624,6 +3883,8 @@ static int __init md_init(void)
" MD_SB_DISKS=%d\n",
MD_MAJOR_VERSION, MD_MINOR_VERSION,
MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MD_SB_DISKS);
+ printk(KERN_INFO "md: bitmap version %d.%d\n", BITMAP_MAJOR,
+ BITMAP_MINOR);
if (register_blkdev(MAJOR_NR, "md"))
return -1;
@@ -3739,7 +4000,6 @@ EXPORT_SYMBOL(md_error);
EXPORT_SYMBOL(md_done_sync);
EXPORT_SYMBOL(md_write_start);
EXPORT_SYMBOL(md_write_end);
-EXPORT_SYMBOL(md_handle_safemode);
EXPORT_SYMBOL(md_register_thread);
EXPORT_SYMBOL(md_unregister_thread);
EXPORT_SYMBOL(md_wakeup_thread);
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 4e4bfde3db5..2d2ca7fa026 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -462,10 +462,6 @@ static int multipath_run (mddev_t *mddev)
}
memset(conf->multipaths, 0, sizeof(struct multipath_info)*mddev->raid_disks);
- mddev->queue->unplug_fn = multipath_unplug;
-
- mddev->queue->issue_flush_fn = multipath_issue_flush;
-
conf->working_disks = 0;
ITERATE_RDEV(mddev,rdev,tmp) {
disk_idx = rdev->raid_disk;
@@ -528,13 +524,16 @@ static int multipath_run (mddev_t *mddev)
* Ok, everything is just fine now
*/
mddev->array_size = mddev->size;
+
+ mddev->queue->unplug_fn = multipath_unplug;
+ mddev->queue->issue_flush_fn = multipath_issue_flush;
+
return 0;
out_free_conf:
if (conf->pool)
mempool_destroy(conf->pool);
- if (conf->multipaths)
- kfree(conf->multipaths);
+ kfree(conf->multipaths);
kfree(conf);
mddev->private = NULL;
out:
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index e7d934eca06..e11dd14d0b4 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -371,10 +371,8 @@ static int raid0_run (mddev_t *mddev)
return 0;
out_free_conf:
- if (conf->strip_zone)
- kfree(conf->strip_zone);
- if (conf->devlist)
- kfree (conf->devlist);
+ kfree(conf->strip_zone);
+ kfree(conf->devlist);
kfree(conf);
mddev->private = NULL;
out:
@@ -386,11 +384,11 @@ static int raid0_stop (mddev_t *mddev)
raid0_conf_t *conf = mddev_to_conf(mddev);
blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
- kfree (conf->hash_table);
+ kfree(conf->hash_table);
conf->hash_table = NULL;
- kfree (conf->strip_zone);
+ kfree(conf->strip_zone);
conf->strip_zone = NULL;
- kfree (conf);
+ kfree(conf);
mddev->private = NULL;
return 0;
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 83380b5d659..ff1dbec864a 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -12,6 +12,15 @@
* Fixes to reconstruction by Jakob Østergaard" <jakob@ostenfeld.dk>
* Various fixes by Neil Brown <neilb@cse.unsw.edu.au>
*
+ * Changes by Peter T. Breuer <ptb@it.uc3m.es> 31/1/2003 to support
+ * bitmapped intelligence in resync:
+ *
+ * - bitmap marked during normal i/o
+ * - bitmap used to skip nondirty blocks during sync
+ *
+ * Additions to bitmap code, (C) 2003-2004 Paul Clements, SteelEye Technology:
+ * - persistent bitmap code
+ *
* 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)
@@ -22,7 +31,16 @@
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include "dm-bio-list.h"
#include <linux/raid/raid1.h>
+#include <linux/raid/bitmap.h>
+
+#define DEBUG 0
+#if DEBUG
+#define PRINTK(x...) printk(x)
+#else
+#define PRINTK(x...)
+#endif
/*
* Number of guaranteed r1bios in case of extreme VM load:
@@ -287,9 +305,11 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
/*
* this branch is our 'one mirror IO has finished' event handler:
*/
- if (!uptodate)
+ if (!uptodate) {
md_error(r1_bio->mddev, conf->mirrors[mirror].rdev);
- else
+ /* an I/O failed, we can't clear the bitmap */
+ set_bit(R1BIO_Degraded, &r1_bio->state);
+ } else
/*
* Set R1BIO_Uptodate in our master bio, so that
* we will return a good error code for to the higher
@@ -309,6 +329,10 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int
* already.
*/
if (atomic_dec_and_test(&r1_bio->remaining)) {
+ /* clear the bitmap if all writes complete successfully */
+ bitmap_endwrite(r1_bio->mddev->bitmap, r1_bio->sector,
+ r1_bio->sectors,
+ !test_bit(R1BIO_Degraded, &r1_bio->state));
md_write_end(r1_bio->mddev);
raid_end_bio_io(r1_bio);
}
@@ -458,7 +482,10 @@ static void unplug_slaves(mddev_t *mddev)
static void raid1_unplug(request_queue_t *q)
{
- unplug_slaves(q->queuedata);
+ mddev_t *mddev = q->queuedata;
+
+ unplug_slaves(mddev);
+ md_wakeup_thread(mddev->thread);
}
static int raid1_issue_flush(request_queue_t *q, struct gendisk *disk,
@@ -501,16 +528,16 @@ static void device_barrier(conf_t *conf, sector_t sect)
{
spin_lock_irq(&conf->resync_lock);
wait_event_lock_irq(conf->wait_idle, !waitqueue_active(&conf->wait_resume),
- conf->resync_lock, unplug_slaves(conf->mddev));
+ conf->resync_lock, raid1_unplug(conf->mddev->queue));
if (!conf->barrier++) {
wait_event_lock_irq(conf->wait_idle, !conf->nr_pending,
- conf->resync_lock, unplug_slaves(conf->mddev));
+ conf->resync_lock, raid1_unplug(conf->mddev->queue));
if (conf->nr_pending)
BUG();
}
wait_event_lock_irq(conf->wait_resume, conf->barrier < RESYNC_DEPTH,
- conf->resync_lock, unplug_slaves(conf->mddev));
+ conf->resync_lock, raid1_unplug(conf->mddev->queue));
conf->next_resync = sect;
spin_unlock_irq(&conf->resync_lock);
}
@@ -522,14 +549,20 @@ static int make_request(request_queue_t *q, struct bio * bio)
mirror_info_t *mirror;
r1bio_t *r1_bio;
struct bio *read_bio;
- int i, disks;
+ int i, targets = 0, disks;
mdk_rdev_t *rdev;
+ struct bitmap *bitmap = mddev->bitmap;
+ unsigned long flags;
+ struct bio_list bl;
+
/*
* Register the new request and wait if the reconstruction
* thread has put up a bar for new requests.
* Continue immediately if no resync is active currently.
*/
+ md_write_start(mddev, bio); /* wait on superblock update early */
+
spin_lock_irq(&conf->resync_lock);
wait_event_lock_irq(conf->wait_resume, !conf->barrier, conf->resync_lock, );
conf->nr_pending++;
@@ -552,7 +585,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
r1_bio->master_bio = bio;
r1_bio->sectors = bio->bi_size >> 9;
-
+ r1_bio->state = 0;
r1_bio->mddev = mddev;
r1_bio->sector = bio->bi_sector;
@@ -595,6 +628,13 @@ static int make_request(request_queue_t *q, struct bio * bio)
* bios[x] to bio
*/
disks = conf->raid_disks;
+#if 0
+ { static int first=1;
+ if (first) printk("First Write sector %llu disks %d\n",
+ (unsigned long long)r1_bio->sector, disks);
+ first = 0;
+ }
+#endif
rcu_read_lock();
for (i = 0; i < disks; i++) {
if ((rdev=conf->mirrors[i].rdev) != NULL &&
@@ -605,13 +645,21 @@ static int make_request(request_queue_t *q, struct bio * bio)
r1_bio->bios[i] = NULL;
} else
r1_bio->bios[i] = bio;
+ targets++;
} else
r1_bio->bios[i] = NULL;
}
rcu_read_unlock();
- atomic_set(&r1_bio->remaining, 1);
- md_write_start(mddev);
+ if (targets < conf->raid_disks) {
+ /* array is degraded, we will not clear the bitmap
+ * on I/O completion (see raid1_end_write_request) */
+ set_bit(R1BIO_Degraded, &r1_bio->state);
+ }
+
+ atomic_set(&r1_bio->remaining, 0);
+
+ bio_list_init(&bl);
for (i = 0; i < disks; i++) {
struct bio *mbio;
if (!r1_bio->bios[i])
@@ -627,14 +675,23 @@ static int make_request(request_queue_t *q, struct bio * bio)
mbio->bi_private = r1_bio;
atomic_inc(&r1_bio->remaining);
- generic_make_request(mbio);
- }
- if (atomic_dec_and_test(&r1_bio->remaining)) {
- md_write_end(mddev);
- raid_end_bio_io(r1_bio);
+ bio_list_add(&bl, mbio);
}
+ bitmap_startwrite(bitmap, bio->bi_sector, r1_bio->sectors);
+ spin_lock_irqsave(&conf->device_lock, flags);
+ bio_list_merge(&conf->pending_bio_list, &bl);
+ bio_list_init(&bl);
+
+ blk_plug_device(mddev->queue);
+ spin_unlock_irqrestore(&conf->device_lock, flags);
+
+#if 0
+ while ((bio = bio_list_pop(&bl)) != NULL)
+ generic_make_request(bio);
+#endif
+
return 0;
}
@@ -714,7 +771,7 @@ static void close_sync(conf_t *conf)
{
spin_lock_irq(&conf->resync_lock);
wait_event_lock_irq(conf->wait_resume, !conf->barrier,
- conf->resync_lock, unplug_slaves(conf->mddev));
+ conf->resync_lock, raid1_unplug(conf->mddev->queue));
spin_unlock_irq(&conf->resync_lock);
if (conf->barrier) BUG();
@@ -754,9 +811,12 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
{
conf_t *conf = mddev->private;
int found = 0;
- int mirror;
+ int mirror = 0;
mirror_info_t *p;
+ if (rdev->saved_raid_disk >= 0 &&
+ conf->mirrors[rdev->saved_raid_disk].rdev == NULL)
+ mirror = rdev->saved_raid_disk;
for (mirror=0; mirror < mddev->raid_disks; mirror++)
if ( !(p=conf->mirrors+mirror)->rdev) {
@@ -773,6 +833,8 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
p->head_position = 0;
rdev->raid_disk = mirror;
found = 1;
+ if (rdev->saved_raid_disk != mirror)
+ conf->fullsync = 1;
p->rdev = rdev;
break;
}
@@ -828,10 +890,11 @@ static int end_sync_read(struct bio *bio, unsigned int bytes_done, int error)
* or re-read if the read failed.
* We don't do much here, just schedule handling by raid1d
*/
- if (!uptodate)
+ if (!uptodate) {
md_error(r1_bio->mddev,
conf->mirrors[r1_bio->read_disk].rdev);
- else
+ set_bit(R1BIO_Degraded, &r1_bio->state);
+ } else
set_bit(R1BIO_Uptodate, &r1_bio->state);
rdev_dec_pending(conf->mirrors[r1_bio->read_disk].rdev, conf->mddev);
reschedule_retry(r1_bio);
@@ -855,8 +918,10 @@ static int end_sync_write(struct bio *bio, unsigned int bytes_done, int error)
mirror = i;
break;
}
- if (!uptodate)
+ if (!uptodate) {
md_error(mddev, conf->mirrors[mirror].rdev);
+ set_bit(R1BIO_Degraded, &r1_bio->state);
+ }
update_head_pos(mirror, r1_bio);
if (atomic_dec_and_test(&r1_bio->remaining)) {
@@ -876,6 +941,9 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
bio = r1_bio->bios[r1_bio->read_disk];
+/*
+ if (r1_bio->sector == 0) printk("First sync write startss\n");
+*/
/*
* schedule writes
*/
@@ -903,10 +971,12 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
atomic_inc(&conf->mirrors[i].rdev->nr_pending);
atomic_inc(&r1_bio->remaining);
md_sync_acct(conf->mirrors[i].rdev->bdev, wbio->bi_size >> 9);
+
generic_make_request(wbio);
}
if (atomic_dec_and_test(&r1_bio->remaining)) {
+ /* if we're here, all write(s) have completed, so clean up */
md_done_sync(mddev, r1_bio->sectors, 1);
put_buf(r1_bio);
}
@@ -931,11 +1001,30 @@ static void raid1d(mddev_t *mddev)
mdk_rdev_t *rdev;
md_check_recovery(mddev);
- md_handle_safemode(mddev);
for (;;) {
char b[BDEVNAME_SIZE];
spin_lock_irqsave(&conf->device_lock, flags);
+
+ if (conf->pending_bio_list.head) {
+ bio = bio_list_get(&conf->pending_bio_list);
+ blk_remove_plug(mddev->queue);
+ spin_unlock_irqrestore(&conf->device_lock, flags);
+ /* flush any pending bitmap writes to disk before proceeding w/ I/O */
+ if (bitmap_unplug(mddev->bitmap) != 0)
+ printk("%s: bitmap file write failed!\n", mdname(mddev));
+
+ while (bio) { /* submit pending writes */
+ struct bio *next = bio->bi_next;
+ bio->bi_next = NULL;
+ generic_make_request(bio);
+ bio = next;
+ }
+ unplug = 1;
+
+ continue;
+ }
+
if (list_empty(head))
break;
r1_bio = list_entry(head->prev, r1bio_t, retry_list);
@@ -1009,7 +1098,7 @@ static int init_resync(conf_t *conf)
* that can be installed to exclude normal IO requests.
*/
-static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
+static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
{
conf_t *conf = mddev_to_conf(mddev);
mirror_info_t *mirror;
@@ -1019,17 +1108,43 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
int disk;
int i;
int write_targets = 0;
+ int sync_blocks;
if (!conf->r1buf_pool)
+ {
+/*
+ printk("sync start - bitmap %p\n", mddev->bitmap);
+*/
if (init_resync(conf))
- return -ENOMEM;
+ return 0;
+ }
max_sector = mddev->size << 1;
if (sector_nr >= max_sector) {
+ /* If we aborted, we need to abort the
+ * sync on the 'current' bitmap chunk (there will
+ * only be one in raid1 resync.
+ * We can find the current addess in mddev->curr_resync
+ */
+ if (!conf->fullsync) {
+ if (mddev->curr_resync < max_sector)
+ bitmap_end_sync(mddev->bitmap,
+ mddev->curr_resync,
+ &sync_blocks, 1);
+ bitmap_close_sync(mddev->bitmap);
+ }
+ if (mddev->curr_resync >= max_sector)
+ conf->fullsync = 0;
close_sync(conf);
return 0;
}
+ if (!conf->fullsync &&
+ !bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks)) {
+ /* We can skip this block, and probably several more */
+ *skipped = 1;
+ return sync_blocks;
+ }
/*
* If there is non-resync activity waiting for us then
* put in a delay to throttle resync.
@@ -1068,6 +1183,7 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
r1_bio->mddev = mddev;
r1_bio->sector = sector_nr;
+ r1_bio->state = 0;
set_bit(R1BIO_IsSync, &r1_bio->state);
r1_bio->read_disk = disk;
@@ -1102,18 +1218,24 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
bio->bi_bdev = conf->mirrors[i].rdev->bdev;
bio->bi_private = r1_bio;
}
+
+ if (write_targets + 1 < conf->raid_disks)
+ /* array degraded, can't clear bitmap */
+ set_bit(R1BIO_Degraded, &r1_bio->state);
+
if (write_targets == 0) {
/* There is nowhere to write, so all non-sync
* drives must be failed - so we are finished
*/
- int rv = max_sector - sector_nr;
- md_done_sync(mddev, rv, 1);
+ sector_t rv = max_sector - sector_nr;
+ *skipped = 1;
put_buf(r1_bio);
rdev_dec_pending(conf->mirrors[disk].rdev, mddev);
return rv;
}
nr_sectors = 0;
+ sync_blocks = 0;
do {
struct page *page;
int len = PAGE_SIZE;
@@ -1121,6 +1243,17 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
len = (max_sector - sector_nr) << 9;
if (len == 0)
break;
+ if (!conf->fullsync) {
+ if (sync_blocks == 0) {
+ if (!bitmap_start_sync(mddev->bitmap,
+ sector_nr, &sync_blocks))
+ break;
+ if (sync_blocks < (PAGE_SIZE>>9))
+ BUG();
+ if (len > (sync_blocks<<9)) len = sync_blocks<<9;
+ }
+ }
+
for (i=0 ; i < conf->raid_disks; i++) {
bio = r1_bio->bios[i];
if (bio->bi_end_io) {
@@ -1143,6 +1276,7 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
}
nr_sectors += len>>9;
sector_nr += len>>9;
+ sync_blocks -= (len>>9);
} while (r1_bio->bios[disk]->bi_vcnt < RESYNC_PAGES);
bio_full:
bio = r1_bio->bios[disk];
@@ -1197,10 +1331,6 @@ static int run(mddev_t *mddev)
if (!conf->r1bio_pool)
goto out_no_mem;
- mddev->queue->unplug_fn = raid1_unplug;
-
- mddev->queue->issue_flush_fn = raid1_issue_flush;
-
ITERATE_RDEV(mddev, rdev, tmp) {
disk_idx = rdev->raid_disk;
if (disk_idx >= mddev->raid_disks
@@ -1235,6 +1365,9 @@ static int run(mddev_t *mddev)
init_waitqueue_head(&conf->wait_idle);
init_waitqueue_head(&conf->wait_resume);
+ bio_list_init(&conf->pending_bio_list);
+ bio_list_init(&conf->flushing_bio_list);
+
if (!conf->working_disks) {
printk(KERN_ERR "raid1: no operational mirrors for %s\n",
mdname(mddev));
@@ -1263,16 +1396,15 @@ static int run(mddev_t *mddev)
conf->last_used = j;
-
- {
- mddev->thread = md_register_thread(raid1d, mddev, "%s_raid1");
- if (!mddev->thread) {
- printk(KERN_ERR
- "raid1: couldn't allocate thread for %s\n",
- mdname(mddev));
- goto out_free_conf;
- }
+ mddev->thread = md_register_thread(raid1d, mddev, "%s_raid1");
+ if (!mddev->thread) {
+ printk(KERN_ERR
+ "raid1: couldn't allocate thread for %s\n",
+ mdname(mddev));
+ goto out_free_conf;
}
+ if (mddev->bitmap) mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
+
printk(KERN_INFO
"raid1: raid set %s active with %d out of %d mirrors\n",
mdname(mddev), mddev->raid_disks - mddev->degraded,
@@ -1282,6 +1414,9 @@ static int run(mddev_t *mddev)
*/
mddev->array_size = mddev->size;
+ mddev->queue->unplug_fn = raid1_unplug;
+ mddev->queue->issue_flush_fn = raid1_issue_flush;
+
return 0;
out_no_mem:
@@ -1292,10 +1427,8 @@ out_free_conf:
if (conf) {
if (conf->r1bio_pool)
mempool_destroy(conf->r1bio_pool);
- if (conf->mirrors)
- kfree(conf->mirrors);
- if (conf->poolinfo)
- kfree(conf->poolinfo);
+ kfree(conf->mirrors);
+ kfree(conf->poolinfo);
kfree(conf);
mddev->private = NULL;
}
@@ -1312,10 +1445,8 @@ static int stop(mddev_t *mddev)
blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
if (conf->r1bio_pool)
mempool_destroy(conf->r1bio_pool);
- if (conf->mirrors)
- kfree(conf->mirrors);
- if (conf->poolinfo)
- kfree(conf->poolinfo);
+ kfree(conf->mirrors);
+ kfree(conf->poolinfo);
kfree(conf);
mddev->private = NULL;
return 0;
@@ -1350,17 +1481,26 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
* We allocate a new r1bio_pool if we can.
* Then raise a device barrier and wait until all IO stops.
* Then resize conf->mirrors and swap in the new r1bio pool.
+ *
+ * At the same time, we "pack" the devices so that all the missing
+ * devices have the higher raid_disk numbers.
*/
mempool_t *newpool, *oldpool;
struct pool_info *newpoolinfo;
mirror_info_t *newmirrors;
conf_t *conf = mddev_to_conf(mddev);
+ int cnt;
- int d;
+ int d, d2;
- for (d= raid_disks; d < conf->raid_disks; d++)
- if (conf->mirrors[d].rdev)
+ if (raid_disks < conf->raid_disks) {
+ cnt=0;
+ for (d= 0; d < conf->raid_disks; d++)
+ if (conf->mirrors[d].rdev)
+ cnt++;
+ if (cnt > raid_disks)
return -EBUSY;
+ }
newpoolinfo = kmalloc(sizeof(*newpoolinfo), GFP_KERNEL);
if (!newpoolinfo)
@@ -1385,14 +1525,18 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
spin_lock_irq(&conf->resync_lock);
conf->barrier++;
wait_event_lock_irq(conf->wait_idle, !conf->nr_pending,
- conf->resync_lock, unplug_slaves(mddev));
+ conf->resync_lock, raid1_unplug(mddev->queue));
spin_unlock_irq(&conf->resync_lock);
/* ok, everything is stopped */
oldpool = conf->r1bio_pool;
conf->r1bio_pool = newpool;
- for (d=0; d < raid_disks && d < conf->raid_disks; d++)
- newmirrors[d] = conf->mirrors[d];
+
+ for (d=d2=0; d < conf->raid_disks; d++)
+ if (conf->mirrors[d].rdev) {
+ conf->mirrors[d].rdev->raid_disk = d2;
+ newmirrors[d2++].rdev = conf->mirrors[d].rdev;
+ }
kfree(conf->mirrors);
conf->mirrors = newmirrors;
kfree(conf->poolinfo);
@@ -1401,6 +1545,7 @@ static int raid1_reshape(mddev_t *mddev, int raid_disks)
mddev->degraded += (raid_disks - conf->raid_disks);
conf->raid_disks = mddev->raid_disks = raid_disks;
+ conf->last_used = 0; /* just make sure it is in-range */
spin_lock_irq(&conf->resync_lock);
conf->barrier--;
spin_unlock_irq(&conf->resync_lock);
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index e9dc2876a62..62ebb1bc72b 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -700,6 +700,8 @@ static int make_request(request_queue_t *q, struct bio * bio)
return 0;
}
+ md_write_start(mddev, bio);
+
/*
* Register the new request and wait if the reconstruction
* thread has put up a bar for new requests.
@@ -774,7 +776,7 @@ static int make_request(request_queue_t *q, struct bio * bio)
rcu_read_unlock();
atomic_set(&r10_bio->remaining, 1);
- md_write_start(mddev);
+
for (i = 0; i < conf->copies; i++) {
struct bio *mbio;
int d = r10_bio->devs[i].devnum;
@@ -1216,7 +1218,6 @@ static void raid10d(mddev_t *mddev)
mdk_rdev_t *rdev;
md_check_recovery(mddev);
- md_handle_safemode(mddev);
for (;;) {
char b[BDEVNAME_SIZE];
@@ -1319,7 +1320,7 @@ static int init_resync(conf_t *conf)
*
*/
-static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
+static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
{
conf_t *conf = mddev_to_conf(mddev);
r10bio_t *r10_bio;
@@ -1333,7 +1334,7 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
if (!conf->r10buf_pool)
if (init_resync(conf))
- return -ENOMEM;
+ return 0;
skipped:
max_sector = mddev->size << 1;
@@ -1341,15 +1342,15 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
max_sector = mddev->resync_max_sectors;
if (sector_nr >= max_sector) {
close_sync(conf);
+ *skipped = 1;
return sectors_skipped;
}
if (chunks_skipped >= conf->raid_disks) {
/* if there has been nothing to do on any drive,
* then there is nothing to do at all..
*/
- sector_t sec = max_sector - sector_nr;
- md_done_sync(mddev, sec, 1);
- return sec + sectors_skipped;
+ *skipped = 1;
+ return (max_sector - sector_nr) + sectors_skipped;
}
/* make sure whole request will fit in a chunk - if chunks
@@ -1563,17 +1564,22 @@ static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
}
}
+ if (sectors_skipped)
+ /* pretend they weren't skipped, it makes
+ * no important difference in this case
+ */
+ md_done_sync(mddev, sectors_skipped, 1);
+
return sectors_skipped + nr_sectors;
giveup:
/* There is nowhere to write, so all non-sync
* drives must be failed, so try the next chunk...
*/
{
- int sec = max_sector - sector_nr;
+ sector_t sec = max_sector - sector_nr;
sectors_skipped += sec;
chunks_skipped ++;
sector_nr = max_sector;
- md_done_sync(mddev, sec, 1);
goto skipped;
}
}
@@ -1639,9 +1645,6 @@ static int run(mddev_t *mddev)
mdname(mddev));
goto out_free_conf;
}
- mddev->queue->unplug_fn = raid10_unplug;
-
- mddev->queue->issue_flush_fn = raid10_issue_flush;
ITERATE_RDEV(mddev, rdev, tmp) {
disk_idx = rdev->raid_disk;
@@ -1713,6 +1716,9 @@ static int run(mddev_t *mddev)
mddev->array_size = size/2;
mddev->resync_max_sectors = size;
+ mddev->queue->unplug_fn = raid10_unplug;
+ mddev->queue->issue_flush_fn = raid10_issue_flush;
+
/* Calculate max read-ahead size.
* We need to readahead at least twice a whole stripe....
* maybe...
@@ -1731,8 +1737,7 @@ static int run(mddev_t *mddev)
out_free_conf:
if (conf->r10bio_pool)
mempool_destroy(conf->r10bio_pool);
- if (conf->mirrors)
- kfree(conf->mirrors);
+ kfree(conf->mirrors);
kfree(conf);
mddev->private = NULL;
out:
@@ -1748,8 +1753,7 @@ static int stop(mddev_t *mddev)
blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
if (conf->r10bio_pool)
mempool_destroy(conf->r10bio_pool);
- if (conf->mirrors)
- kfree(conf->mirrors);
+ kfree(conf->mirrors);
kfree(conf);
mddev->private = NULL;
return 0;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index e96e2a10a9c..93a9726cc2d 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -1411,6 +1411,8 @@ static int make_request (request_queue_t *q, struct bio * bi)
sector_t logical_sector, last_sector;
struct stripe_head *sh;
+ md_write_start(mddev, bi);
+
if (bio_data_dir(bi)==WRITE) {
disk_stat_inc(mddev->gendisk, writes);
disk_stat_add(mddev->gendisk, write_sectors, bio_sectors(bi));
@@ -1423,8 +1425,7 @@ static int make_request (request_queue_t *q, struct bio * bi)
last_sector = bi->bi_sector + (bi->bi_size>>9);
bi->bi_next = NULL;
bi->bi_phys_segments = 1; /* over-loaded to count active stripes */
- if ( bio_data_dir(bi) == WRITE )
- md_write_start(mddev);
+
for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) {
DEFINE_WAIT(w);
@@ -1475,7 +1476,7 @@ static int make_request (request_queue_t *q, struct bio * bi)
}
/* FIXME go_faster isn't used */
-static int sync_request (mddev_t *mddev, sector_t sector_nr, int go_faster)
+static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
{
raid5_conf_t *conf = (raid5_conf_t *) mddev->private;
struct stripe_head *sh;
@@ -1498,8 +1499,8 @@ static int sync_request (mddev_t *mddev, sector_t sector_nr, int go_faster)
* nothing we can do.
*/
if (mddev->degraded >= 1 && test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
- int rv = (mddev->size << 1) - sector_nr;
- md_done_sync(mddev, rv, 1);
+ sector_t rv = (mddev->size << 1) - sector_nr;
+ *skipped = 1;
return rv;
}
@@ -1546,7 +1547,6 @@ static void raid5d (mddev_t *mddev)
PRINTK("+++ raid5d active\n");
md_check_recovery(mddev);
- md_handle_safemode(mddev);
handled = 0;
spin_lock_irq(&conf->device_lock);
@@ -1620,9 +1620,6 @@ static int run (mddev_t *mddev)
atomic_set(&conf->active_stripes, 0);
atomic_set(&conf->preread_active_stripes, 0);
- mddev->queue->unplug_fn = raid5_unplug_device;
- mddev->queue->issue_flush_fn = raid5_issue_flush;
-
PRINTK("raid5: run(%s) called.\n", mdname(mddev));
ITERATE_RDEV(mddev,rdev,tmp) {
@@ -1728,6 +1725,10 @@ memory = conf->max_nr_stripes * (sizeof(struct stripe_head) +
}
/* Ok, everything is just fine now */
+
+ mddev->queue->unplug_fn = raid5_unplug_device;
+ mddev->queue->issue_flush_fn = raid5_issue_flush;
+
mddev->array_size = mddev->size * (mddev->raid_disks - 1);
return 0;
abort:
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
index 8a33f351e09..f62ea1a73d0 100644
--- a/drivers/md/raid6main.c
+++ b/drivers/md/raid6main.c
@@ -1570,6 +1570,8 @@ static int make_request (request_queue_t *q, struct bio * bi)
sector_t logical_sector, last_sector;
struct stripe_head *sh;
+ md_write_start(mddev, bi);
+
if (bio_data_dir(bi)==WRITE) {
disk_stat_inc(mddev->gendisk, writes);
disk_stat_add(mddev->gendisk, write_sectors, bio_sectors(bi));
@@ -1583,8 +1585,7 @@ static int make_request (request_queue_t *q, struct bio * bi)
bi->bi_next = NULL;
bi->bi_phys_segments = 1; /* over-loaded to count active stripes */
- if ( bio_data_dir(bi) == WRITE )
- md_write_start(mddev);
+
for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) {
DEFINE_WAIT(w);
@@ -1634,7 +1635,7 @@ static int make_request (request_queue_t *q, struct bio * bi)
}
/* FIXME go_faster isn't used */
-static int sync_request (mddev_t *mddev, sector_t sector_nr, int go_faster)
+static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
{
raid6_conf_t *conf = (raid6_conf_t *) mddev->private;
struct stripe_head *sh;
@@ -1657,8 +1658,8 @@ static int sync_request (mddev_t *mddev, sector_t sector_nr, int go_faster)
* nothing we can do.
*/
if (mddev->degraded >= 2 && test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
- int rv = (mddev->size << 1) - sector_nr;
- md_done_sync(mddev, rv, 1);
+ sector_t rv = (mddev->size << 1) - sector_nr;
+ *skipped = 1;
return rv;
}
@@ -1705,7 +1706,6 @@ static void raid6d (mddev_t *mddev)
PRINTK("+++ raid6d active\n");
md_check_recovery(mddev);
- md_handle_safemode(mddev);
handled = 0;
spin_lock_irq(&conf->device_lock);
@@ -1779,9 +1779,6 @@ static int run (mddev_t *mddev)
atomic_set(&conf->active_stripes, 0);
atomic_set(&conf->preread_active_stripes, 0);
- mddev->queue->unplug_fn = raid6_unplug_device;
- mddev->queue->issue_flush_fn = raid6_issue_flush;
-
PRINTK("raid6: run(%s) called.\n", mdname(mddev));
ITERATE_RDEV(mddev,rdev,tmp) {
@@ -1895,6 +1892,9 @@ static int run (mddev_t *mddev)
/* Ok, everything is just fine now */
mddev->array_size = mddev->size * (mddev->raid_disks - 2);
+
+ mddev->queue->unplug_fn = raid6_unplug_device;
+ mddev->queue->issue_flush_fn = raid6_issue_flush;
return 0;
abort:
if (conf) {
diff --git a/drivers/media/common/ir-common.c b/drivers/media/common/ir-common.c
index 84a49d2ec91..4adb2843f8b 100644
--- a/drivers/media/common/ir-common.c
+++ b/drivers/media/common/ir-common.c
@@ -1,5 +1,5 @@
/*
- * $Id: ir-common.c,v 1.8 2005/02/22 12:28:40 kraxel Exp $
+ * $Id: ir-common.c,v 1.10 2005/05/22 19:23:39 nsh Exp $
*
* some common structs and functions to handle infrared remotes via
* input layer ...
@@ -131,10 +131,10 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = {
[ 18 ] = KEY_KP0,
[ 0 ] = KEY_POWER,
- [ 27 ] = KEY_LANGUAGE, //MTS button
+// [ 27 ] = MTS button
[ 2 ] = KEY_TUNER, // TV/FM
[ 30 ] = KEY_VIDEO,
- [ 22 ] = KEY_INFO, //display button
+// [ 22 ] = display button
[ 4 ] = KEY_VOLUMEUP,
[ 8 ] = KEY_VOLUMEDOWN,
[ 12 ] = KEY_CHANNELUP,
@@ -142,7 +142,7 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = {
[ 3 ] = KEY_ZOOM, // fullscreen
[ 31 ] = KEY_SUBTITLE, // closed caption/teletext
[ 32 ] = KEY_SLEEP,
- [ 41 ] = KEY_SEARCH, //boss key
+// [ 41 ] = boss key
[ 20 ] = KEY_MUTE,
[ 43 ] = KEY_RED,
[ 44 ] = KEY_GREEN,
@@ -150,17 +150,17 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = {
[ 46 ] = KEY_BLUE,
[ 24 ] = KEY_KPPLUS, //fine tune +
[ 25 ] = KEY_KPMINUS, //fine tune -
- [ 42 ] = KEY_ANGLE, //picture in picture
- [ 33 ] = KEY_KPDOT,
+// [ 42 ] = picture in picture
+ [ 33 ] = KEY_KPDOT,
[ 19 ] = KEY_KPENTER,
- [ 17 ] = KEY_AGAIN, //recall
+// [ 17 ] = recall
[ 34 ] = KEY_BACK,
[ 35 ] = KEY_PLAYPAUSE,
[ 36 ] = KEY_NEXT,
- [ 37 ] = KEY_T, //time shifting
+// [ 37 ] = time shifting
[ 38 ] = KEY_STOP,
- [ 39 ] = KEY_RECORD,
- [ 40 ] = KEY_SHUFFLE //snapshot
+ [ 39 ] = KEY_RECORD
+// [ 40 ] = snapshot
};
EXPORT_SYMBOL_GPL(ir_codes_winfast);
@@ -184,18 +184,30 @@ IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = {
[ 0x07 ] = KEY_KP7, // 7
[ 0x08 ] = KEY_KP8, // 8
[ 0x09 ] = KEY_KP9, // 9
+ [ 0x0a ] = KEY_TEXT, // keypad asterisk as well
[ 0x0b ] = KEY_RED, // red button
- [ 0x0c ] = KEY_OPTION, // black key without text
+ [ 0x0c ] = KEY_RADIO, // radio
[ 0x0d ] = KEY_MENU, // menu
+ [ 0x0e ] = KEY_SUBTITLE, // also the # key
[ 0x0f ] = KEY_MUTE, // mute
[ 0x10 ] = KEY_VOLUMEUP, // volume +
[ 0x11 ] = KEY_VOLUMEDOWN, // volume -
- [ 0x1e ] = KEY_NEXT, // skip >|
+ [ 0x12 ] = KEY_PREVIOUS, // previous channel
+ [ 0x14 ] = KEY_UP, // up
+ [ 0x15 ] = KEY_DOWN, // down
+ [ 0x16 ] = KEY_LEFT, // left
+ [ 0x17 ] = KEY_RIGHT, // right
+ [ 0x18 ] = KEY_VIDEO, // Videos
+ [ 0x19 ] = KEY_AUDIO, // Music
+ [ 0x1a ] = KEY_MHP, // Pictures - presume this means "Multimedia Home Platform"- no "PICTURES" key in input.h
+ [ 0x1b ] = KEY_EPG, // Guide
+ [ 0x1c ] = KEY_TV, // TV
+ [ 0x1e ] = KEY_NEXTSONG, // skip >|
[ 0x1f ] = KEY_EXIT, // back/exit
[ 0x20 ] = KEY_CHANNELUP, // channel / program +
[ 0x21 ] = KEY_CHANNELDOWN, // channel / program -
[ 0x22 ] = KEY_CHANNEL, // source (old black remote)
- [ 0x24 ] = KEY_PREVIOUS, // replay |<
+ [ 0x24 ] = KEY_PREVIOUSSONG, // replay |<
[ 0x25 ] = KEY_ENTER, // OK
[ 0x26 ] = KEY_SLEEP, // minimize (old black remote)
[ 0x29 ] = KEY_BLUE, // blue key
@@ -213,6 +225,39 @@ IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE] = {
};
EXPORT_SYMBOL(ir_codes_hauppauge_new);
+IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = {
+ [ 2 ] = KEY_KP0,
+ [ 1 ] = KEY_KP1,
+ [ 11 ] = KEY_KP2,
+ [ 27 ] = KEY_KP3,
+ [ 5 ] = KEY_KP4,
+ [ 9 ] = KEY_KP5,
+ [ 21 ] = KEY_KP6,
+ [ 6 ] = KEY_KP7,
+ [ 10 ] = KEY_KP8,
+ [ 18 ] = KEY_KP9,
+
+ [ 3 ] = KEY_TUNER, // TV/FM
+ [ 7 ] = KEY_SEARCH, // scan
+ [ 28 ] = KEY_ZOOM, // full screen
+ [ 30 ] = KEY_POWER,
+ [ 23 ] = KEY_VOLUMEDOWN,
+ [ 31 ] = KEY_VOLUMEUP,
+ [ 20 ] = KEY_CHANNELDOWN,
+ [ 22 ] = KEY_CHANNELUP,
+ [ 24 ] = KEY_MUTE,
+
+ [ 0 ] = KEY_LIST, // source
+ [ 19 ] = KEY_INFO, // loop
+ [ 16 ] = KEY_LAST, // +100
+ [ 13 ] = KEY_CLEAR, // reset
+ [ 12 ] = BTN_RIGHT, // fun++
+ [ 4 ] = BTN_LEFT, // fun--
+ [ 14 ] = KEY_GOTO, // function
+ [ 15 ] = KEY_STOP, // freeze
+};
+EXPORT_SYMBOL(ir_codes_pixelview);
+
/* -------------------------------------------------------------------------- */
static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir)
@@ -379,3 +424,4 @@ EXPORT_SYMBOL_GPL(ir_decode_biphase);
* c-basic-offset: 8
* End:
*/
+
diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c
index 9f6c19ac128..50e8b865401 100644
--- a/drivers/media/common/saa7146_core.c
+++ b/drivers/media/common/saa7146_core.c
@@ -23,9 +23,9 @@
LIST_HEAD(saa7146_devices);
DECLARE_MUTEX(saa7146_devices_lock);
-static int saa7146_num = 0;
+static int saa7146_num;
-unsigned int saa7146_debug = 0;
+unsigned int saa7146_debug;
module_param(saa7146_debug, int, 0644);
MODULE_PARM_DESC(saa7146_debug, "debug level (default: 0)");
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index cb826c9adfe..c04fd11526e 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -403,7 +403,7 @@ static struct file_operations video_fops =
.llseek = no_llseek,
};
-void vv_callback(struct saa7146_dev *dev, unsigned long status)
+static void vv_callback(struct saa7146_dev *dev, unsigned long status)
{
u32 isr = status;
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig
index 883ec08490f..01387f883cd 100644
--- a/drivers/media/dvb/Kconfig
+++ b/drivers/media/dvb/Kconfig
@@ -27,13 +27,13 @@ source "drivers/media/dvb/ttpci/Kconfig"
comment "Supported USB Adapters"
depends on DVB_CORE && USB
+source "drivers/media/dvb/dvb-usb/Kconfig"
source "drivers/media/dvb/ttusb-budget/Kconfig"
source "drivers/media/dvb/ttusb-dec/Kconfig"
-source "drivers/media/dvb/dibusb/Kconfig"
source "drivers/media/dvb/cinergyT2/Kconfig"
comment "Supported FlexCopII (B2C2) Adapters"
- depends on DVB_CORE && PCI
+ depends on DVB_CORE && (PCI || USB)
source "drivers/media/dvb/b2c2/Kconfig"
comment "Supported BT878 Adapters"
diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile
index 520fc390281..3c6ff161910 100644
--- a/drivers/media/dvb/Makefile
+++ b/drivers/media/dvb/Makefile
@@ -2,4 +2,4 @@
# Makefile for the kernel multimedia device drivers.
#
-obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dibusb/ cinergyT2/
+obj-y := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/
diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig
index 52596907a0b..fafd0ab3a28 100644
--- a/drivers/media/dvb/b2c2/Kconfig
+++ b/drivers/media/dvb/b2c2/Kconfig
@@ -1,26 +1,51 @@
-config DVB_B2C2_SKYSTAR
- tristate "B2C2/Technisat Air/Sky/CableStar 2 PCI"
- depends on DVB_CORE && PCI
+config DVB_B2C2_FLEXCOP
+ tristate "Technisat/B2C2 FlexCopII(b) and FlexCopIII adapters"
+ depends on DVB_CORE
select DVB_STV0299
select DVB_MT352
select DVB_MT312
select DVB_NXT2002
+ select DVB_STV0297
+ select DVB_BCM3510
help
- Support for the Skystar2 PCI DVB card by Technisat, which
- is equipped with the FlexCopII chipset by B2C2, and
- for the B2C2/BBTI Air2PC-ATSC card.
+ Support for the digital TV receiver chip made by B2C2 Inc. included in
+ Technisats PCI cards and USB boxes.
Say Y if you own such a device and want to use it.
-config DVB_B2C2_USB
- tristate "B2C2/Technisat Air/Sky/Cable2PC USB"
- depends on DVB_CORE && USB && EXPERIMENTAL
+config DVB_B2C2_FLEXCOP_PCI
+ tristate "Technisat/B2C2 Air/Sky/Cable2PC PCI"
+ depends on DVB_B2C2_FLEXCOP && PCI
+ help
+ Support for the Air/Sky/CableStar2 PCI card (DVB/ATSC) by Technisat/B2C2.
+
+ Say Y if you own such a device and want to use it.
+
+config DVB_B2C2_FLEXCOP_USB
+ tristate "Technisat/B2C2 Air/Sky/Cable2PC USB"
+ depends on DVB_B2C2_FLEXCOP && USB
+ help
+ Support for the Air/Sky/Cable2PC USB1.1 box (DVB/ATSC) by Technisat/B2C2,
+
+ Say Y if you own such a device and want to use it.
+
+config DVB_B2C2_FLEXCOP_DEBUG
+ bool "Enable debug for the B2C2 FlexCop drivers"
+ depends on DVB_B2C2_FLEXCOP
+ help
+ Say Y if you want to enable the module option to control debug messages
+ of all B2C2 FlexCop drivers.
+
+config DVB_B2C2_SKYSTAR
+ tristate "B2C2/Technisat Air/Sky/CableStar 2 PCI"
+ depends on DVB_CORE && PCI
select DVB_STV0299
select DVB_MT352
+ select DVB_MT312
+ select DVB_NXT2002
help
- Support for the Air/Sky/Cable2PC USB DVB device by B2C2. Currently
- the does nothing, but providing basic function for the used usb
- protocol.
+ Support for the Skystar2 PCI DVB card by Technisat, which
+ is equipped with the FlexCopII chipset by B2C2, and
+ for the B2C2/BBTI Air2PC-ATSC card.
Say Y if you own such a device and want to use it.
-
diff --git a/drivers/media/dvb/b2c2/Makefile b/drivers/media/dvb/b2c2/Makefile
index 9fb1247bfab..7703812af34 100644
--- a/drivers/media/dvb/b2c2/Makefile
+++ b/drivers/media/dvb/b2c2/Makefile
@@ -1,6 +1,14 @@
-obj-b2c2-usb = b2c2-usb-core.o b2c2-common.o
+b2c2-flexcop-objs = flexcop.o flexcop-fe-tuner.o flexcop-i2c.o \
+ flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o \
+ flexcop-dma.o
+obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o
+
+b2c2-flexcop-pci-objs = flexcop-pci.o
+obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o
+
+b2c2-flexcop-usb-objs = flexcop-usb.o
+obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o
obj-$(CONFIG_DVB_B2C2_SKYSTAR) += skystar2.o
-obj-$(CONFIG_DVB_B2C2_USB) + = b2c2-usb.o
EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff --git a/drivers/media/dvb/b2c2/b2c2-common.c b/drivers/media/dvb/b2c2/b2c2-common.c
deleted file mode 100644
index 000d60c405e..00000000000
--- a/drivers/media/dvb/b2c2/b2c2-common.c
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * b2c2-common.c - common methods for the B2C2/Technisat SkyStar2 PCI DVB card and
- * for the B2C2/Technisat Sky/Cable/AirStar USB devices
- * based on the FlexCopII/FlexCopIII by B2C2, Inc.
- *
- * Copyright (C) 2003 Vadim Catana, skystar@moldova.cc
- *
- * FIX: DISEQC Tone Burst in flexcop_diseqc_ioctl()
- * FIX: FULL soft DiSEqC for skystar2 (FlexCopII rev 130) VP310 equipped
- * Vincenzo Di Massa, hawk.it at tiscalinet.it
- *
- * Converted to Linux coding style
- * Misc reorganization, polishing, restyling
- * Roberto Ragusa, r.ragusa at libero.it
- *
- * Added hardware filtering support,
- * Niklas Peinecke, peinecke at gdv.uni-hannover.de
- *
- * This program 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 (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 Lesser 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 "stv0299.h"
-#include "mt352.h"
-#include "mt312.h"
-
-static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio)
-{
- u8 aclk = 0;
- u8 bclk = 0;
-
- if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; }
- else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; }
- else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; }
- else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; }
- else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; }
- else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; }
-
- stv0299_writereg (fe, 0x13, aclk);
- stv0299_writereg (fe, 0x14, bclk);
- stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff);
- stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff);
- stv0299_writereg (fe, 0x21, (ratio ) & 0xf0);
-
- return 0;
-}
-
-static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
-{
- u8 buf[4];
- u32 div;
- struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
-// struct adapter* adapter = (struct adapter*) fe->dvb->priv;
-
- div = params->frequency / 125;
-
- buf[0] = (div >> 8) & 0x7f;
- buf[1] = div & 0xff;
- buf[2] = 0x84; // 0xC4
- buf[3] = 0x08;
-
- if (params->frequency < 1500000) buf[3] |= 0x10;
-
-// if (i2c_transfer (&adapter->i2c_adap, &msg, 1) != 1) return -EIO;
- return 0;
-}
-
-static u8 samsung_tbmu24112_inittab[] = {
- 0x01, 0x15,
- 0x02, 0x30,
- 0x03, 0x00,
- 0x04, 0x7D,
- 0x05, 0x35,
- 0x06, 0x02,
- 0x07, 0x00,
- 0x08, 0xC3,
- 0x0C, 0x00,
- 0x0D, 0x81,
- 0x0E, 0x23,
- 0x0F, 0x12,
- 0x10, 0x7E,
- 0x11, 0x84,
- 0x12, 0xB9,
- 0x13, 0x88,
- 0x14, 0x89,
- 0x15, 0xC9,
- 0x16, 0x00,
- 0x17, 0x5C,
- 0x18, 0x00,
- 0x19, 0x00,
- 0x1A, 0x00,
- 0x1C, 0x00,
- 0x1D, 0x00,
- 0x1E, 0x00,
- 0x1F, 0x3A,
- 0x20, 0x2E,
- 0x21, 0x80,
- 0x22, 0xFF,
- 0x23, 0xC1,
- 0x28, 0x00,
- 0x29, 0x1E,
- 0x2A, 0x14,
- 0x2B, 0x0F,
- 0x2C, 0x09,
- 0x2D, 0x05,
- 0x31, 0x1F,
- 0x32, 0x19,
- 0x33, 0xFE,
- 0x34, 0x93,
- 0xff, 0xff,
-};
-
-static struct stv0299_config samsung_tbmu24112_config = {
- .demod_address = 0x68,
- .inittab = samsung_tbmu24112_inittab,
- .mclk = 88000000UL,
- .invert = 0,
- .enhanced_tuning = 0,
- .skip_reinit = 0,
- .lock_output = STV0229_LOCKOUTPUT_LK,
- .volt13_op0_op1 = STV0299_VOLT13_OP1,
- .min_delay_ms = 100,
- .set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
- .pll_set = samsung_tbmu24112_pll_set,
-};
-
-
-
-
-
-static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
-{
- static u8 mt352_clock_config [] = { 0x89, 0x10, 0x2d };
- static u8 mt352_reset [] = { 0x50, 0x80 };
- static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 };
- static u8 mt352_agc_cfg [] = { 0x67, 0x28, 0xa1 };
- static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
-
- mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
- udelay(2000);
- mt352_write(fe, mt352_reset, sizeof(mt352_reset));
- mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
-
- mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
- mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
-
- return 0;
-}
-
-static int samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
-{
- u32 div;
- unsigned char bs = 0;
-
- #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
- div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
-
- if (params->frequency >= 48000000 && params->frequency <= 154000000) bs = 0x09;
- if (params->frequency >= 161000000 && params->frequency <= 439000000) bs = 0x0a;
- if (params->frequency >= 447000000 && params->frequency <= 863000000) bs = 0x08;
-
- pllbuf[0] = 0xc2; // Note: non-linux standard PLL i2c address
- pllbuf[1] = div >> 8;
- pllbuf[2] = div & 0xff;
- pllbuf[3] = 0xcc;
- pllbuf[4] = bs;
-
- return 0;
-}
-
-static struct mt352_config samsung_tdtc9251dh0_config = {
-
- .demod_address = 0x0f,
- .demod_init = samsung_tdtc9251dh0_demod_init,
- .pll_set = samsung_tdtc9251dh0_pll_set,
-};
-
-static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
-{
- u8 buf[4];
- u32 div;
- struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
-// struct adapter* adapter = (struct adapter*) fe->dvb->priv;
-
- div = (params->frequency + (125/2)) / 125;
-
- buf[0] = (div >> 8) & 0x7f;
- buf[1] = (div >> 0) & 0xff;
- buf[2] = 0x84 | ((div >> 10) & 0x60);
- buf[3] = 0x80;
-
- if (params->frequency < 1550000)
- buf[3] |= 0x02;
-
- //if (i2c_transfer (&adapter->i2c_adap, &msg, 1) != 1) return -EIO;
- return 0;
-}
-
-static struct mt312_config skystar23_samsung_tbdu18132_config = {
-
- .demod_address = 0x0e,
- .pll_set = skystar23_samsung_tbdu18132_pll_set,
-};
diff --git a/drivers/media/dvb/b2c2/b2c2-usb-core.c b/drivers/media/dvb/b2c2/b2c2-usb-core.c
deleted file mode 100644
index 9306da046c9..00000000000
--- a/drivers/media/dvb/b2c2/b2c2-usb-core.c
+++ /dev/null
@@ -1,549 +0,0 @@
-/*
- * Copyright (C) 2004 Patrick Boettcher <patrick.boettcher@desy.de>,
- * Luca Bertagnolio <>,
- *
- * based on information provided by John Jurrius from BBTI, 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, version 2.
- *
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/usb.h>
-#include <linux/moduleparam.h>
-#include <linux/pci.h>
-#include <linux/version.h>
-
-#include "dmxdev.h"
-#include "dvb_demux.h"
-#include "dvb_filter.h"
-#include "dvb_net.h"
-#include "dvb_frontend.h"
-
-/* debug */
-#define dprintk(level,args...) \
- do { if ((debug & level)) { printk(args); } } while (0)
-#define debug_dump(b,l) if (debug) {\
- int i; deb_xfer("%s: %d > ",__FUNCTION__,l); \
- for (i = 0; i < l; i++) deb_xfer("%02x ", b[i]); \
- deb_xfer("\n");\
-}
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,ts=2,ctrl=4 (or-able)).");
-
-#define deb_info(args...) dprintk(0x01,args)
-#define deb_ts(args...) dprintk(0x02,args)
-#define deb_ctrl(args...) dprintk(0x04,args)
-
-/* Version information */
-#define DRIVER_VERSION "0.0"
-#define DRIVER_DESC "Driver for B2C2/Technisat Air/Cable/Sky-2-PC USB devices"
-#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de"
-
-/* transfer parameters */
-#define B2C2_USB_FRAMES_PER_ISO 4
-#define B2C2_USB_NUM_ISO_URB 4 /* TODO check out a good value */
-
-#define B2C2_USB_CTRL_PIPE_IN usb_rcvctrlpipe(b2c2->udev,0)
-#define B2C2_USB_CTRL_PIPE_OUT usb_sndctrlpipe(b2c2->udev,0)
-#define B2C2_USB_DATA_PIPE usb_rcvisocpipe(b2c2->udev,0x81)
-
-struct usb_b2c2_usb {
- struct usb_device *udev;
- struct usb_interface *uintf;
-
- u8 *iso_buffer;
- int buffer_size;
- dma_addr_t iso_dma_handle;
- struct urb *iso_urb[B2C2_USB_NUM_ISO_URB];
-};
-
-
-/*
- * USB
- * 10 90 34 12 78 56 04 00
- * usb_control_msg(udev, usb_sndctrlpipe(udev,0),
- * 0x90,
- * 0x10,
- * 0x1234,
- * 0x5678,
- * buf,
- * 4,
- * 5*HZ);
- *
- * extern int usb_control_msg(struct usb_device *dev, unsigned int pipe,
- * __u8 request,
- * __u8 requesttype,
- * __u16 value,
- * __u16 index,
- * void *data,
- * __u16 size,
- * int timeout);
- *
- */
-
-/* request types */
-typedef enum {
-
-/* something is wrong with this part
- RTYPE_READ_DW = (1 << 6),
- RTYPE_WRITE_DW_1 = (3 << 6),
- RTYPE_READ_V8_MEMORY = (6 << 6),
- RTYPE_WRITE_V8_MEMORY = (7 << 6),
- RTYPE_WRITE_V8_FLASH = (8 << 6),
- RTYPE_GENERIC = (9 << 6),
-*/
- RTYPE_READ_DW = (3 << 6),
- RTYPE_WRITE_DW_1 = (1 << 6),
-
- RTYPE_READ_V8_MEMORY = (6 << 6),
- RTYPE_WRITE_V8_MEMORY = (7 << 6),
- RTYPE_WRITE_V8_FLASH = (8 << 6),
- RTYPE_GENERIC = (9 << 6),
-} b2c2_usb_request_type_t;
-
-/* request */
-typedef enum {
- B2C2_USB_WRITE_V8_MEM = 0x04,
- B2C2_USB_READ_V8_MEM = 0x05,
- B2C2_USB_READ_REG = 0x08,
- B2C2_USB_WRITE_REG = 0x0A,
-/* B2C2_USB_WRITEREGLO = 0x0A, */
- B2C2_USB_WRITEREGHI = 0x0B,
- B2C2_USB_FLASH_BLOCK = 0x10,
- B2C2_USB_I2C_REQUEST = 0x11,
- B2C2_USB_UTILITY = 0x12,
-} b2c2_usb_request_t;
-
-/* function definition for I2C_REQUEST */
-typedef enum {
- USB_FUNC_I2C_WRITE = 0x01,
- USB_FUNC_I2C_MULTIWRITE = 0x02,
- USB_FUNC_I2C_READ = 0x03,
- USB_FUNC_I2C_REPEATWRITE = 0x04,
- USB_FUNC_GET_DESCRIPTOR = 0x05,
- USB_FUNC_I2C_REPEATREAD = 0x06,
-/* DKT 020208 - add this to support special case of DiSEqC */
- USB_FUNC_I2C_CHECKWRITE = 0x07,
- USB_FUNC_I2C_CHECKRESULT = 0x08,
-} b2c2_usb_i2c_function_t;
-
-/*
- * function definition for UTILITY request 0x12
- * DKT 020304 - new utility function
- */
-typedef enum {
- UTILITY_SET_FILTER = 0x01,
- UTILITY_DATA_ENABLE = 0x02,
- UTILITY_FLEX_MULTIWRITE = 0x03,
- UTILITY_SET_BUFFER_SIZE = 0x04,
- UTILITY_FLEX_OPERATOR = 0x05,
- UTILITY_FLEX_RESET300_START = 0x06,
- UTILITY_FLEX_RESET300_STOP = 0x07,
- UTILITY_FLEX_RESET300 = 0x08,
- UTILITY_SET_ISO_SIZE = 0x09,
- UTILITY_DATA_RESET = 0x0A,
- UTILITY_GET_DATA_STATUS = 0x10,
- UTILITY_GET_V8_REG = 0x11,
-/* DKT 020326 - add function for v1.14 */
- UTILITY_SRAM_WRITE = 0x12,
- UTILITY_SRAM_READ = 0x13,
- UTILITY_SRAM_TESTFILL = 0x14,
- UTILITY_SRAM_TESTSET = 0x15,
- UTILITY_SRAM_TESTVERIFY = 0x16,
-} b2c2_usb_utility_function_t;
-
-#define B2C2_WAIT_FOR_OPERATION_RW 1 // 1 s
-#define B2C2_WAIT_FOR_OPERATION_RDW 3 // 3 s
-#define B2C2_WAIT_FOR_OPERATION_WDW 1 // 1 s
-
-#define B2C2_WAIT_FOR_OPERATION_V8READ 3 // 3 s
-#define B2C2_WAIT_FOR_OPERATION_V8WRITE 3 // 3 s
-#define B2C2_WAIT_FOR_OPERATION_V8FLASH 3 // 3 s
-
-/* JLP 111700: we will include the 1 bit gap between the upper and lower 3 bits
- * in the IBI address, to make the V8 code simpler.
- * PCI ADDRESS FORMAT: 0x71C -> 0000 0111 0001 1100 (these are the six bits used)
- * in general: 0000 0HHH 000L LL00
- * IBI ADDRESS FORMAT: RHHH BLLL
- *
- * where R is the read(1)/write(0) bit, B is the busy bit
- * and HHH and LLL are the two sets of three bits from the PCI address.
- */
-#define B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(usPCI) (u8) (((usPCI >> 2) & 0x07) + ((usPCI >> 4) & 0x70))
-#define B2C2_FLEX_INTERNALADDR_TO_PCIOFFSET(ucAddr) (u16) (((ucAddr & 0x07) << 2) + ((ucAddr & 0x70) << 4))
-
-/*
- * DKT 020228 - forget about this VENDOR_BUFFER_SIZE, read and write register
- * deal with DWORD or 4 bytes, that should be should from now on
- */
-static u32 b2c2_usb_read_dw(struct usb_b2c2_usb *b2c2, u16 wRegOffsPCI)
-{
- u32 val;
- u16 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) | 0x0080;
- int len = usb_control_msg(b2c2->udev,
- B2C2_USB_CTRL_PIPE_IN,
- B2C2_USB_READ_REG,
- RTYPE_READ_DW,
- wAddress,
- 0,
- &val,
- sizeof(u32),
- B2C2_WAIT_FOR_OPERATION_RDW * 1000);
-
- if (len != sizeof(u32)) {
- err("error while reading dword from %d (%d).",wAddress,wRegOffsPCI);
- return -EIO;
- } else
- return val;
-}
-
-/*
- * DKT 020228 - from now on, we don't support anything older than firm 1.00
- * I eliminated the write register as a 2 trip of writing hi word and lo word
- * and force this to write only 4 bytes at a time.
- * NOTE: this should work with all the firmware from 1.00 and newer
- */
-static int b2c2_usb_write_dw(struct usb_b2c2_usb *b2c2, u16 wRegOffsPCI, u32 val)
-{
- u16 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI);
- int len = usb_control_msg(b2c2->udev,
- B2C2_USB_CTRL_PIPE_OUT,
- B2C2_USB_WRITE_REG,
- RTYPE_WRITE_DW_1,
- wAddress,
- 0,
- &val,
- sizeof(u32),
- B2C2_WAIT_FOR_OPERATION_RDW * 1000);
-
- if (len != sizeof(u32)) {
- err("error while reading dword from %d (%d).",wAddress,wRegOffsPCI);
- return -EIO;
- } else
- return 0;
-}
-
-/*
- * DKT 010817 - add support for V8 memory read/write and flash update
- */
-static int b2c2_usb_v8_memory_req(struct usb_b2c2_usb *b2c2,
- b2c2_usb_request_t req, u8 page, u16 wAddress,
- u16 buflen, u8 *pbBuffer)
-{
- u8 dwRequestType;
- u16 wIndex;
- int nWaitTime,pipe,len;
-
- wIndex = page << 8;
-
- switch (req) {
- case B2C2_USB_READ_V8_MEM:
- nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ;
- dwRequestType = (u8) RTYPE_READ_V8_MEMORY;
- pipe = B2C2_USB_CTRL_PIPE_IN;
- break;
- case B2C2_USB_WRITE_V8_MEM:
- wIndex |= pbBuffer[0];
- nWaitTime = B2C2_WAIT_FOR_OPERATION_V8WRITE;
- dwRequestType = (u8) RTYPE_WRITE_V8_MEMORY;
- pipe = B2C2_USB_CTRL_PIPE_OUT;
- break;
- case B2C2_USB_FLASH_BLOCK:
- nWaitTime = B2C2_WAIT_FOR_OPERATION_V8FLASH;
- dwRequestType = (u8) RTYPE_WRITE_V8_FLASH;
- pipe = B2C2_USB_CTRL_PIPE_OUT;
- break;
- default:
- deb_info("unsupported request for v8_mem_req %x.\n",req);
- return -EINVAL;
- }
- len = usb_control_msg(b2c2->udev,pipe,
- req,
- dwRequestType,
- wAddress,
- wIndex,
- pbBuffer,
- buflen,
- nWaitTime * 1000);
- return len == buflen ? 0 : -EIO;
-}
-
-static int b2c2_usb_i2c_req(struct usb_b2c2_usb *b2c2,
- b2c2_usb_request_t req, b2c2_usb_i2c_function_t func,
- u8 port, u8 chipaddr, u8 addr, u8 buflen, u8 *buf)
-{
- u16 wValue, wIndex;
- int nWaitTime,pipe,len;
- u8 dwRequestType;
-
- switch (func) {
- case USB_FUNC_I2C_WRITE:
- case USB_FUNC_I2C_MULTIWRITE:
- case USB_FUNC_I2C_REPEATWRITE:
- /* DKT 020208 - add this to support special case of DiSEqC */
- case USB_FUNC_I2C_CHECKWRITE:
- pipe = B2C2_USB_CTRL_PIPE_OUT;
- nWaitTime = 2;
- dwRequestType = (u8) RTYPE_GENERIC;
- break;
- case USB_FUNC_I2C_READ:
- case USB_FUNC_I2C_REPEATREAD:
- pipe = B2C2_USB_CTRL_PIPE_IN;
- nWaitTime = 2;
- dwRequestType = (u8) RTYPE_GENERIC;
- break;
- default:
- deb_info("unsupported function for i2c_req %x\n",func);
- return -EINVAL;
- }
- wValue = (func << 8 ) | port;
- wIndex = (chipaddr << 8 ) | addr;
-
- len = usb_control_msg(b2c2->udev,pipe,
- req,
- dwRequestType,
- addr,
- wIndex,
- buf,
- buflen,
- nWaitTime * 1000);
- return len == buflen ? 0 : -EIO;
-}
-
-int static b2c2_usb_utility_req(struct usb_b2c2_usb *b2c2, int set,
- b2c2_usb_utility_function_t func, u8 extra, u16 wIndex,
- u16 buflen, u8 *pvBuffer)
-{
- u16 wValue;
- int nWaitTime = 2,
- pipe = set ? B2C2_USB_CTRL_PIPE_OUT : B2C2_USB_CTRL_PIPE_IN,
- len;
-
- wValue = (func << 8) | extra;
-
- len = usb_control_msg(b2c2->udev,pipe,
- B2C2_USB_UTILITY,
- (u8) RTYPE_GENERIC,
- wValue,
- wIndex,
- pvBuffer,
- buflen,
- nWaitTime * 1000);
- return len == buflen ? 0 : -EIO;
-}
-
-
-
-static void b2c2_dumpfourreg(struct usb_b2c2_usb *b2c2, u16 offs)
-{
- u32 r0,r1,r2,r3;
- r0 = r1 = r2 = r3 = 0;
- r0 = b2c2_usb_read_dw(b2c2,offs);
- r1 = b2c2_usb_read_dw(b2c2,offs + 0x04);
- r2 = b2c2_usb_read_dw(b2c2,offs + 0x08);
- r3 = b2c2_usb_read_dw(b2c2,offs + 0x0c);
- deb_ctrl("dump: offset: %03x, %08x, %08x, %08x, %08x\n",offs,r0,r1,r2,r3);
-}
-
-static void b2c2_urb_complete(struct urb *urb, struct pt_regs *ptregs)
-{
- struct usb_b2c2_usb *b2c2 = urb->context;
- deb_ts("urb completed, bufsize: %d\n",urb->transfer_buffer_length);
-
-// urb_submit_urb(urb,GFP_ATOMIC); enable for real action
-}
-
-static void b2c2_exit_usb(struct usb_b2c2_usb *b2c2)
-{
- int i;
- for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++)
- if (b2c2->iso_urb[i] != NULL) { /* not sure about unlink_urb and iso-urbs TODO */
- deb_info("unlinking/killing urb no. %d\n",i);
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,7)
- usb_unlink_urb(b2c2->iso_urb[i]);
-#else
- usb_kill_urb(b2c2->iso_urb[i]);
-#endif
- usb_free_urb(b2c2->iso_urb[i]);
- }
-
- if (b2c2->iso_buffer != NULL)
- pci_free_consistent(NULL,b2c2->buffer_size, b2c2->iso_buffer, b2c2->iso_dma_handle);
-
-}
-
-static int b2c2_init_usb(struct usb_b2c2_usb *b2c2)
-{
- u16 frame_size = le16_to_cpu(b2c2->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize);
- int bufsize = B2C2_USB_NUM_ISO_URB * B2C2_USB_FRAMES_PER_ISO * frame_size,i,j,ret;
- int buffer_offset = 0;
-
- deb_info("creating %d iso-urbs with %d frames each of %d bytes size = %d.\n",
- B2C2_USB_NUM_ISO_URB, B2C2_USB_FRAMES_PER_ISO, frame_size,bufsize);
-
- b2c2->iso_buffer = pci_alloc_consistent(NULL,bufsize,&b2c2->iso_dma_handle);
- if (b2c2->iso_buffer == NULL)
- return -ENOMEM;
- memset(b2c2->iso_buffer, 0, bufsize);
- b2c2->buffer_size = bufsize;
-
- /* creating iso urbs */
- for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++)
- if (!(b2c2->iso_urb[i] = usb_alloc_urb(B2C2_USB_FRAMES_PER_ISO,GFP_ATOMIC))) {
- ret = -ENOMEM;
- goto urb_error;
- }
- /* initialising and submitting iso urbs */
- for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) {
- int frame_offset = 0;
- struct urb *urb = b2c2->iso_urb[i];
- deb_info("initializing and submitting urb no. %d (buf_offset: %d).\n",i,buffer_offset);
-
- urb->dev = b2c2->udev;
- urb->context = b2c2;
- urb->complete = b2c2_urb_complete;
- urb->pipe = B2C2_USB_DATA_PIPE;
- urb->transfer_flags = URB_ISO_ASAP;
- urb->interval = 1;
- urb->number_of_packets = B2C2_USB_FRAMES_PER_ISO;
- urb->transfer_buffer_length = frame_size * B2C2_USB_FRAMES_PER_ISO;
- urb->transfer_buffer = b2c2->iso_buffer + buffer_offset;
-
- buffer_offset += frame_size * B2C2_USB_FRAMES_PER_ISO;
- for (j = 0; j < B2C2_USB_FRAMES_PER_ISO; j++) {
- deb_info("urb no: %d, frame: %d, frame_offset: %d\n",i,j,frame_offset);
- urb->iso_frame_desc[j].offset = frame_offset;
- urb->iso_frame_desc[j].length = frame_size;
- frame_offset += frame_size;
- }
-
- if ((ret = usb_submit_urb(b2c2->iso_urb[i],GFP_ATOMIC))) {
- err("submitting urb %d failed with %d.",i,ret);
- goto urb_error;
- }
- deb_info("submitted urb no. %d.\n",i);
- }
-
- ret = 0;
- goto success;
-urb_error:
- b2c2_exit_usb(b2c2);
-success:
- return ret;
-}
-
-static int b2c2_usb_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- struct usb_device *udev = interface_to_usbdev(intf);
- struct usb_b2c2_usb *b2c2 = NULL;
- int ret;
-
- b2c2 = kmalloc(sizeof(struct usb_b2c2_usb),GFP_KERNEL);
- if (b2c2 == NULL) {
- err("no memory");
- return -ENOMEM;
- }
- b2c2->udev = udev;
- b2c2->uintf = intf;
-
- /* use the alternate setting with the larges buffer */
- usb_set_interface(udev,0,1);
-
- if ((ret = b2c2_init_usb(b2c2)))
- goto usb_init_error;
-
- usb_set_intfdata(intf,b2c2);
-
- switch (udev->speed) {
- case USB_SPEED_LOW:
- err("cannot handle USB speed because it is to sLOW.");
- break;
- case USB_SPEED_FULL:
- info("running at FULL speed.");
- break;
- case USB_SPEED_HIGH:
- info("running at HIGH speed.");
- break;
- case USB_SPEED_UNKNOWN: /* fall through */
- default:
- err("cannot handle USB speed because it is unkown.");
- break;
- }
-
- b2c2_dumpfourreg(b2c2,0x200);
- b2c2_dumpfourreg(b2c2,0x300);
- b2c2_dumpfourreg(b2c2,0x400);
- b2c2_dumpfourreg(b2c2,0x700);
-
-
- if (ret == 0)
- info("%s successfully initialized and connected.",DRIVER_DESC);
- else
- info("%s error while loading driver (%d)",DRIVER_DESC,ret);
-
- ret = 0;
- goto success;
-
-usb_init_error:
- kfree(b2c2);
-success:
- return ret;
-}
-
-static void b2c2_usb_disconnect(struct usb_interface *intf)
-{
- struct usb_b2c2_usb *b2c2 = usb_get_intfdata(intf);
- usb_set_intfdata(intf,NULL);
- if (b2c2 != NULL) {
- b2c2_exit_usb(b2c2);
- kfree(b2c2);
- }
- info("%s successfully deinitialized and disconnected.",DRIVER_DESC);
-
-}
-
-static struct usb_device_id b2c2_usb_table [] = {
- { USB_DEVICE(0x0af7, 0x0101) }
-};
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver b2c2_usb_driver = {
- .owner = THIS_MODULE,
- .name = "dvb_b2c2_usb",
- .probe = b2c2_usb_probe,
- .disconnect = b2c2_usb_disconnect,
- .id_table = b2c2_usb_table,
-};
-
-/* module stuff */
-static int __init b2c2_usb_init(void)
-{
- int result;
- if ((result = usb_register(&b2c2_usb_driver))) {
- err("usb_register failed. Error number %d",result);
- return result;
- }
-
- return 0;
-}
-
-static void __exit b2c2_usb_exit(void)
-{
- /* deregister this driver from the USB subsystem */
- usb_deregister(&b2c2_usb_driver);
-}
-
-module_init (b2c2_usb_init);
-module_exit (b2c2_usb_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(usb, b2c2_usb_table);
diff --git a/drivers/media/dvb/b2c2/flexcop-common.h b/drivers/media/dvb/b2c2/flexcop-common.h
new file mode 100644
index 00000000000..773d158032d
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop-common.h
@@ -0,0 +1,164 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
+ *
+ * flexcop-common.h - common header file for device-specific source files also.
+ *
+ * see flexcop.c for copyright information.
+ */
+#ifndef __FLEXCOP_COMMON_H__
+#define __FLEXCOP_COMMON_H__
+
+#include <linux/config.h>
+#include <linux/pci.h>
+
+#include "flexcop-reg.h"
+
+#include "dmxdev.h"
+#include "dvb_demux.h"
+#include "dvb_filter.h"
+#include "dvb_net.h"
+#include "dvb_frontend.h"
+
+#define FC_MAX_FEED 256
+
+#ifndef FC_LOG_PREFIX
+#warning please define a log prefix for your file, using a default one
+#define FC_LOG_PREFIX "b2c2-undef"
+#endif
+
+/* Steal from usb.h */
+#undef err
+#define err(format, arg...) printk(KERN_ERR FC_LOG_PREFIX ": " format "\n" , ## arg)
+#undef info
+#define info(format, arg...) printk(KERN_INFO FC_LOG_PREFIX ": " format "\n" , ## arg)
+#undef warn
+#define warn(format, arg...) printk(KERN_WARNING FC_LOG_PREFIX ": " format "\n" , ## arg)
+
+struct flexcop_dma {
+ struct pci_dev *pdev;
+
+ u8 *cpu_addr0;
+ dma_addr_t dma_addr0;
+ u8 *cpu_addr1;
+ dma_addr_t dma_addr1;
+ u32 size; /* size of each address in bytes */
+};
+
+/* Control structure for data definitions that are common to
+ * the B2C2-based PCI and USB devices.
+ */
+struct flexcop_device {
+ /* general */
+ struct device *dev; /* for firmware_class */
+
+#define FC_STATE_DVB_INIT 0x01
+#define FC_STATE_I2C_INIT 0x02
+#define FC_STATE_FE_INIT 0x04
+ int init_state;
+
+ /* device information */
+ int has_32_hw_pid_filter;
+ flexcop_revision_t rev;
+ flexcop_device_type_t dev_type;
+ flexcop_bus_t bus_type;
+
+ /* dvb stuff */
+ struct dvb_adapter dvb_adapter;
+ struct dvb_frontend *fe;
+ struct dvb_net dvbnet;
+ struct dvb_demux demux;
+ struct dmxdev dmxdev;
+ struct dmx_frontend hw_frontend;
+ struct dmx_frontend mem_frontend;
+ int (*fe_sleep) (struct dvb_frontend *);
+
+ struct i2c_adapter i2c_adap;
+ struct semaphore i2c_sem;
+
+ struct module *owner;
+
+ /* options and status */
+ int extra_feedcount;
+ int feedcount;
+ int pid_filtering;
+ int fullts_streaming_state;
+
+ /* bus specific callbacks */
+ flexcop_ibi_value (*read_ibi_reg) (struct flexcop_device *, flexcop_ibi_register);
+ int (*write_ibi_reg) (struct flexcop_device *, flexcop_ibi_register, flexcop_ibi_value);
+
+
+ int (*i2c_request) (struct flexcop_device*, flexcop_access_op_t, flexcop_i2c_port_t, u8 chipaddr, u8 addr, u8 *buf, u16 len);
+ int (*stream_control) (struct flexcop_device*, int);
+
+ int (*get_mac_addr) (struct flexcop_device *fc, int extended);
+
+ void *bus_specific;
+};
+
+/* exported prototypes */
+
+/* from flexcop.c */
+void flexcop_pass_dmx_data(struct flexcop_device *fc, u8 *buf, u32 len);
+void flexcop_pass_dmx_packets(struct flexcop_device *fc, u8 *buf, u32 no);
+
+struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len);
+void flexcop_device_kfree(struct flexcop_device*);
+
+int flexcop_device_initialize(struct flexcop_device*);
+void flexcop_device_exit(struct flexcop_device *fc);
+
+/* from flexcop-dma.c */
+int flexcop_dma_allocate(struct pci_dev *pdev, struct flexcop_dma *dma, u32 size);
+void flexcop_dma_free(struct flexcop_dma *dma);
+
+int flexcop_dma_control_timer_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff);
+int flexcop_dma_control_size_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff);
+int flexcop_dma_control_packet_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff);
+int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, flexcop_dma_index_t dma_idx,flexcop_dma_addr_index_t index);
+int flexcop_dma_config_timer(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 cycles);
+int flexcop_dma_config_packet_count(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 packets);
+
+/* from flexcop-eeprom.c */
+/* the PCI part uses this call to get the MAC address, the USB part has its own */
+int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended);
+
+/* from flexcop-i2c.c */
+/* the PCI part uses this a i2c_request callback, whereas the usb part has its own
+ * one. We have it in flexcop-i2c.c, because it is going via the actual
+ * I2C-channel of the flexcop.
+ */
+int flexcop_i2c_request(struct flexcop_device*, flexcop_access_op_t,
+ flexcop_i2c_port_t, u8 chipaddr, u8 addr, u8 *buf, u16 len);
+
+/* from flexcop-sram.c */
+int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest, flexcop_sram_dest_target_t target);
+void flexcop_wan_set_speed(struct flexcop_device *fc, flexcop_wan_speed_t s);
+void flexcop_sram_ctrl(struct flexcop_device *fc, int usb_wan, int sramdma, int maximumfill);
+
+/* global prototypes for the flexcop-chip */
+/* from flexcop-fe-tuner.c */
+int flexcop_frontend_init(struct flexcop_device *card);
+void flexcop_frontend_exit(struct flexcop_device *fc);
+
+/* from flexcop-i2c.c */
+int flexcop_i2c_init(struct flexcop_device *fc);
+void flexcop_i2c_exit(struct flexcop_device *fc);
+
+/* from flexcop-sram.c */
+int flexcop_sram_init(struct flexcop_device *fc);
+
+/* from flexcop-misc.c */
+void flexcop_determine_revision(struct flexcop_device *fc);
+void flexcop_device_name(struct flexcop_device *fc,const char *prefix,const char *suffix);
+
+/* from flexcop-hw-filter.c */
+int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *dvbdmxfeed, int onoff);
+void flexcop_hw_filter_init(struct flexcop_device *fc);
+
+void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff);
+
+void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6]);
+void flexcop_mac_filter_ctrl(struct flexcop_device *fc, int onoff);
+
+#endif
diff --git a/drivers/media/dvb/b2c2/flexcop-dma.c b/drivers/media/dvb/b2c2/flexcop-dma.c
new file mode 100644
index 00000000000..8d270607536
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop-dma.c
@@ -0,0 +1,149 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
+ *
+ * flexcop-dma.c - methods for configuring and controlling the DMA of the FlexCop.
+ *
+ * see flexcop.c for copyright information.
+ */
+#include "flexcop.h"
+
+int flexcop_dma_allocate(struct pci_dev *pdev, struct flexcop_dma *dma, u32 size)
+{
+ u8 *tcpu;
+ dma_addr_t tdma;
+
+ if (size % 2) {
+ err("dma buffersize has to be even.");
+ return -EINVAL;
+ }
+
+ if ((tcpu = pci_alloc_consistent(pdev, size, &tdma)) != NULL) {
+ dma->pdev = pdev;
+ dma->cpu_addr0 = tcpu;
+ dma->dma_addr0 = tdma;
+ dma->cpu_addr1 = tcpu + size/2;
+ dma->dma_addr1 = tdma + size/2;
+ dma->size = size/2;
+ return 0;
+ }
+ return -ENOMEM;
+}
+EXPORT_SYMBOL(flexcop_dma_allocate);
+
+void flexcop_dma_free(struct flexcop_dma *dma)
+{
+ pci_free_consistent(dma->pdev, dma->size*2,dma->cpu_addr0, dma->dma_addr0);
+ memset(dma,0,sizeof(struct flexcop_dma));
+}
+EXPORT_SYMBOL(flexcop_dma_free);
+
+int flexcop_dma_control_timer_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff)
+{
+ flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208);
+
+ if (no & FC_DMA_1)
+ v.ctrl_208.DMA1_Timer_Enable_sig = onoff;
+
+ if (no & FC_DMA_2)
+ v.ctrl_208.DMA2_Timer_Enable_sig = onoff;
+
+ fc->write_ibi_reg(fc,ctrl_208,v);
+ return 0;
+}
+EXPORT_SYMBOL(flexcop_dma_control_timer_irq);
+
+int flexcop_dma_control_size_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff)
+{
+ flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208);
+
+ if (no & FC_DMA_1)
+ v.ctrl_208.DMA1_IRQ_Enable_sig = onoff;
+
+ if (no & FC_DMA_2)
+ v.ctrl_208.DMA2_IRQ_Enable_sig = onoff;
+
+ fc->write_ibi_reg(fc,ctrl_208,v);
+ return 0;
+}
+EXPORT_SYMBOL(flexcop_dma_control_size_irq);
+
+int flexcop_dma_control_packet_irq(struct flexcop_device *fc, flexcop_dma_index_t no, int onoff)
+{
+ flexcop_ibi_value v = fc->read_ibi_reg(fc,ctrl_208);
+
+ if (no & FC_DMA_1)
+ v.ctrl_208.DMA1_Size_IRQ_Enable_sig = onoff;
+
+ if (no & FC_DMA_2)
+ v.ctrl_208.DMA2_Size_IRQ_Enable_sig = onoff;
+
+ fc->write_ibi_reg(fc,ctrl_208,v);
+ return 0;
+}
+EXPORT_SYMBOL(flexcop_dma_control_packet_irq);
+
+int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, flexcop_dma_index_t dma_idx,flexcop_dma_addr_index_t index)
+{
+
+ flexcop_ibi_value v0x0,v0x4,v0xc;
+ v0x0.raw = v0x4.raw = v0xc.raw = 0;
+
+ v0x0.dma_0x0.dma_address0 = dma->dma_addr0 >> 2;
+ v0xc.dma_0xc.dma_address1 = dma->dma_addr1 >> 2;
+ v0x4.dma_0x4_write.dma_addr_size = dma->size / 4;
+
+ if (index & FC_DMA_SUBADDR_0)
+ v0x0.dma_0x0.dma_0start = 1;
+
+ if (index & FC_DMA_SUBADDR_1)
+ v0xc.dma_0xc.dma_1start = 1;
+
+ if (dma_idx & FC_DMA_1) {
+ fc->write_ibi_reg(fc,dma1_000,v0x0);
+ fc->write_ibi_reg(fc,dma1_004,v0x4);
+ fc->write_ibi_reg(fc,dma1_00c,v0xc);
+ } else { /* (dma_idx & FC_DMA_2) */
+ fc->write_ibi_reg(fc,dma2_010,v0x0);
+ fc->write_ibi_reg(fc,dma2_014,v0x4);
+ fc->write_ibi_reg(fc,dma2_01c,v0xc);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(flexcop_dma_config);
+
+static int flexcop_dma_remap(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, int onoff)
+{
+ flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_00c : dma2_01c;
+ flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
+ v.dma_0xc.remap_enable = onoff;
+ fc->write_ibi_reg(fc,r,v);
+ return 0;
+}
+
+/* 1 cycles = 1.97 msec */
+int flexcop_dma_config_timer(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 cycles)
+{
+ flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014;
+ flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
+
+ flexcop_dma_remap(fc,dma_idx,0);
+
+ v.dma_0x4_write.dmatimer = cycles >> 1;
+ fc->write_ibi_reg(fc,r,v);
+ return 0;
+}
+EXPORT_SYMBOL(flexcop_dma_config_timer);
+
+int flexcop_dma_config_packet_count(struct flexcop_device *fc, flexcop_dma_index_t dma_idx, u8 packets)
+{
+ flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014;
+ flexcop_ibi_value v = fc->read_ibi_reg(fc,r);
+
+ flexcop_dma_remap(fc,dma_idx,1);
+
+ v.dma_0x4_remap.DMA_maxpackets = packets;
+ fc->write_ibi_reg(fc,r,v);
+ return 0;
+}
+EXPORT_SYMBOL(flexcop_dma_config_packet_count);
diff --git a/drivers/media/dvb/b2c2/flexcop-eeprom.c b/drivers/media/dvb/b2c2/flexcop-eeprom.c
new file mode 100644
index 00000000000..bbcf070a178
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop-eeprom.c
@@ -0,0 +1,153 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
+ *
+ * flexcop-eeprom.c - eeprom access methods (currently only MAC address reading is used)
+ *
+ * see flexcop.c for copyright information.
+ */
+#include "flexcop.h"
+
+#if 0
+/*EEPROM (Skystar2 has one "24LC08B" chip on board) */
+static int eeprom_write(struct adapter *adapter, u16 addr, u8 *buf, u16 len)
+{
+ return flex_i2c_write(adapter, 0x20000000, 0x50, addr, buf, len);
+}
+
+static int eeprom_lrc_write(struct adapter *adapter, u32 addr, u32 len, u8 *wbuf, u8 *rbuf, int retries)
+{
+ int i;
+
+ for (i = 0; i < retries; i++) {
+ if (eeprom_write(adapter, addr, wbuf, len) == len) {
+ if (eeprom_lrc_read(adapter, addr, len, rbuf, retries) == 1)
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/* These functions could be used to unlock SkyStar2 cards. */
+
+static int eeprom_writeKey(struct adapter *adapter, u8 *key, u32 len)
+{
+ u8 rbuf[20];
+ u8 wbuf[20];
+
+ if (len != 16)
+ return 0;
+
+ memcpy(wbuf, key, len);
+
+ wbuf[16] = 0;
+ wbuf[17] = 0;
+ wbuf[18] = 0;
+ wbuf[19] = calc_lrc(wbuf, 19);
+
+ return eeprom_lrc_write(adapter, 0x3e4, 20, wbuf, rbuf, 4);
+}
+
+static int eeprom_readKey(struct adapter *adapter, u8 *key, u32 len)
+{
+ u8 buf[20];
+
+ if (len != 16)
+ return 0;
+
+ if (eeprom_lrc_read(adapter, 0x3e4, 20, buf, 4) == 0)
+ return 0;
+
+ memcpy(key, buf, len);
+
+ return 1;
+}
+
+static char eeprom_set_mac_addr(struct adapter *adapter, char type, u8 *mac)
+{
+ u8 tmp[8];
+
+ if (type != 0) {
+ tmp[0] = mac[0];
+ tmp[1] = mac[1];
+ tmp[2] = mac[2];
+ tmp[3] = mac[5];
+ tmp[4] = mac[6];
+ tmp[5] = mac[7];
+
+ } else {
+
+ tmp[0] = mac[0];
+ tmp[1] = mac[1];
+ tmp[2] = mac[2];
+ tmp[3] = mac[3];
+ tmp[4] = mac[4];
+ tmp[5] = mac[5];
+ }
+
+ tmp[6] = 0;
+ tmp[7] = calc_lrc(tmp, 7);
+
+ if (eeprom_write(adapter, 0x3f8, tmp, 8) == 8)
+ return 1;
+
+ return 0;
+}
+
+static int flexcop_eeprom_read(struct flexcop_device *fc, u16 addr, u8 *buf, u16 len)
+{
+ return fc->i2c_request(fc,FC_READ,FC_I2C_PORT_EEPROM,0x50,addr,buf,len);
+}
+
+#endif
+
+static u8 calc_lrc(u8 *buf, int len)
+{
+ int i;
+ u8 sum = 0;
+ for (i = 0; i < len; i++)
+ sum = sum ^ buf[i];
+ return sum;
+}
+
+static int flexcop_eeprom_request(struct flexcop_device *fc, flexcop_access_op_t op, u16 addr, u8 *buf, u16 len, int retries)
+{
+ int i,ret = 0;
+ u8 chipaddr = 0x50 | ((addr >> 8) & 3);
+ for (i = 0; i < retries; i++)
+ if ((ret = fc->i2c_request(fc,op,FC_I2C_PORT_EEPROM,chipaddr,addr & 0xff,buf,len)) == 0)
+ break;
+ return ret;
+}
+
+static int flexcop_eeprom_lrc_read(struct flexcop_device *fc, u16 addr, u8 *buf, u16 len, int retries)
+{
+ int ret = flexcop_eeprom_request(fc,FC_READ,addr,buf,len,retries);
+ if (ret == 0)
+ if (calc_lrc(buf, len - 1) != buf[len - 1])
+ ret = -EINVAL;
+ return ret;
+}
+
+/* JJ's comment about extended == 1: it is not presently used anywhere but was
+ * added to the low-level functions for possible support of EUI64
+ */
+int flexcop_eeprom_check_mac_addr(struct flexcop_device *fc, int extended)
+{
+ u8 buf[8];
+ int ret = 0;
+
+ if ((ret = flexcop_eeprom_lrc_read(fc,0x3f8,buf,8,4)) == 0) {
+ if (extended != 0) {
+ err("TODO: extended (EUI64) MAC addresses aren't completely supported yet");
+ ret = -EINVAL;
+/* memcpy(fc->dvb_adapter.proposed_mac,buf,3);
+ mac[3] = 0xfe;
+ mac[4] = 0xff;
+ memcpy(&fc->dvb_adapter.proposed_mac[3],&buf[5],3); */
+ } else
+ memcpy(fc->dvb_adapter.proposed_mac,buf,6);
+ }
+ return ret;
+}
+EXPORT_SYMBOL(flexcop_eeprom_check_mac_addr);
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
new file mode 100644
index 00000000000..0410cc96a48
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -0,0 +1,413 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
+ *
+ * flexcop-fe-tuner.c - methods for attaching a frontend and controlling DiSEqC.
+ *
+ * see flexcop.c for copyright information.
+ */
+#include "flexcop.h"
+
+#include "stv0299.h"
+#include "mt352.h"
+#include "nxt2002.h"
+#include "bcm3510.h"
+#include "stv0297.h"
+#include "mt312.h"
+
+/* lnb control */
+
+static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+ struct flexcop_device *fc = fe->dvb->priv;
+ flexcop_ibi_value v;
+ deb_tuner("polarity/voltage = %u\n", voltage);
+
+ v = fc->read_ibi_reg(fc, misc_204);
+ switch (voltage) {
+ case SEC_VOLTAGE_OFF:
+ v.misc_204.ACPI1_sig = 1;
+ break;
+ case SEC_VOLTAGE_13:
+ v.misc_204.ACPI1_sig = 0;
+ v.misc_204.LNB_L_H_sig = 0;
+ break;
+ case SEC_VOLTAGE_18:
+ v.misc_204.ACPI1_sig = 0;
+ v.misc_204.LNB_L_H_sig = 1;
+ break;
+ default:
+ err("unknown SEC_VOLTAGE value");
+ return -EINVAL;
+ }
+ return fc->write_ibi_reg(fc, misc_204, v);
+}
+
+static int flexcop_sleep(struct dvb_frontend* fe)
+{
+ struct flexcop_device *fc = fe->dvb->priv;
+/* flexcop_ibi_value v = fc->read_ibi_reg(fc,misc_204); */
+
+ if (fc->fe_sleep)
+ return fc->fe_sleep(fe);
+
+/* v.misc_204.ACPI3_sig = 1;
+ fc->write_ibi_reg(fc,misc_204,v);*/
+
+ return 0;
+}
+
+static int flexcop_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
+{
+ /* u16 wz_half_period_for_45_mhz[] = { 0x01ff, 0x0154, 0x00ff, 0x00cc }; */
+ struct flexcop_device *fc = fe->dvb->priv;
+ flexcop_ibi_value v;
+ u16 ax;
+ v.raw = 0;
+
+ deb_tuner("tone = %u\n",tone);
+
+ switch (tone) {
+ case SEC_TONE_ON:
+ ax = 0x01ff;
+ break;
+ case SEC_TONE_OFF:
+ ax = 0;
+ break;
+ default:
+ err("unknown SEC_TONE value");
+ return -EINVAL;
+ }
+
+ v.lnb_switch_freq_200.LNB_CTLPrescaler_sig = 1; /* divide by 2 */
+
+ v.lnb_switch_freq_200.LNB_CTLHighCount_sig = ax;
+ v.lnb_switch_freq_200.LNB_CTLLowCount_sig = ax == 0 ? 0x1ff : ax;
+
+ return fc->write_ibi_reg(fc,lnb_switch_freq_200,v);
+}
+
+static void flexcop_diseqc_send_bit(struct dvb_frontend* fe, int data)
+{
+ flexcop_set_tone(fe, SEC_TONE_ON);
+ udelay(data ? 500 : 1000);
+ flexcop_set_tone(fe, SEC_TONE_OFF);
+ udelay(data ? 1000 : 500);
+}
+
+static void flexcop_diseqc_send_byte(struct dvb_frontend* fe, int data)
+{
+ int i, par = 1, d;
+
+ for (i = 7; i >= 0; i--) {
+ d = (data >> i) & 1;
+ par ^= d;
+ flexcop_diseqc_send_bit(fe, d);
+ }
+
+ flexcop_diseqc_send_bit(fe, par);
+}
+
+static int flexcop_send_diseqc_msg(struct dvb_frontend* fe, int len, u8 *msg, unsigned long burst)
+{
+ int i;
+
+ flexcop_set_tone(fe, SEC_TONE_OFF);
+ mdelay(16);
+
+ for (i = 0; i < len; i++)
+ flexcop_diseqc_send_byte(fe,msg[i]);
+
+ mdelay(16);
+
+ if (burst != -1) {
+ if (burst)
+ flexcop_diseqc_send_byte(fe, 0xff);
+ else {
+ flexcop_set_tone(fe, SEC_TONE_ON);
+ udelay(12500);
+ flexcop_set_tone(fe, SEC_TONE_OFF);
+ }
+ msleep(20);
+ }
+ return 0;
+}
+
+static int flexcop_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
+{
+ return flexcop_send_diseqc_msg(fe, cmd->msg_len, cmd->msg, 0);
+}
+
+static int flexcop_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd)
+{
+ return flexcop_send_diseqc_msg(fe, 0, NULL, minicmd);
+}
+
+/* dvb-s stv0299 */
+static int samsung_tbmu24112_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio)
+{
+ u8 aclk = 0;
+ u8 bclk = 0;
+
+ if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; }
+ else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; }
+ else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; }
+ else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; }
+ else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; }
+ else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; }
+
+ stv0299_writereg (fe, 0x13, aclk);
+ stv0299_writereg (fe, 0x14, bclk);
+ stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff);
+ stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff);
+ stv0299_writereg (fe, 0x21, (ratio ) & 0xf0);
+
+ return 0;
+}
+
+static int samsung_tbmu24112_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+{
+ u8 buf[4];
+ u32 div;
+ struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
+ struct flexcop_device *fc = fe->dvb->priv;
+
+ div = params->frequency / 125;
+
+ buf[0] = (div >> 8) & 0x7f;
+ buf[1] = div & 0xff;
+ buf[2] = 0x84; /* 0xC4 */
+ buf[3] = 0x08;
+
+ if (params->frequency < 1500000) buf[3] |= 0x10;
+
+ if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1)
+ return -EIO;
+ return 0;
+}
+
+static u8 samsung_tbmu24112_inittab[] = {
+ 0x01, 0x15,
+ 0x02, 0x30,
+ 0x03, 0x00,
+ 0x04, 0x7D,
+ 0x05, 0x35,
+ 0x06, 0x02,
+ 0x07, 0x00,
+ 0x08, 0xC3,
+ 0x0C, 0x00,
+ 0x0D, 0x81,
+ 0x0E, 0x23,
+ 0x0F, 0x12,
+ 0x10, 0x7E,
+ 0x11, 0x84,
+ 0x12, 0xB9,
+ 0x13, 0x88,
+ 0x14, 0x89,
+ 0x15, 0xC9,
+ 0x16, 0x00,
+ 0x17, 0x5C,
+ 0x18, 0x00,
+ 0x19, 0x00,
+ 0x1A, 0x00,
+ 0x1C, 0x00,
+ 0x1D, 0x00,
+ 0x1E, 0x00,
+ 0x1F, 0x3A,
+ 0x20, 0x2E,
+ 0x21, 0x80,
+ 0x22, 0xFF,
+ 0x23, 0xC1,
+ 0x28, 0x00,
+ 0x29, 0x1E,
+ 0x2A, 0x14,
+ 0x2B, 0x0F,
+ 0x2C, 0x09,
+ 0x2D, 0x05,
+ 0x31, 0x1F,
+ 0x32, 0x19,
+ 0x33, 0xFE,
+ 0x34, 0x93,
+ 0xff, 0xff,
+};
+
+static struct stv0299_config samsung_tbmu24112_config = {
+ .demod_address = 0x68,
+ .inittab = samsung_tbmu24112_inittab,
+ .mclk = 88000000UL,
+ .invert = 0,
+ .enhanced_tuning = 0,
+ .skip_reinit = 0,
+ .lock_output = STV0229_LOCKOUTPUT_LK,
+ .volt13_op0_op1 = STV0299_VOLT13_OP1,
+ .min_delay_ms = 100,
+ .set_symbol_rate = samsung_tbmu24112_set_symbol_rate,
+ .pll_set = samsung_tbmu24112_pll_set,
+};
+
+/* dvb-t mt352 */
+static int samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
+{
+ static u8 mt352_clock_config [] = { 0x89, 0x18, 0x2d };
+ static u8 mt352_reset [] = { 0x50, 0x80 };
+ static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 };
+ static u8 mt352_agc_cfg [] = { 0x67, 0x28, 0xa1 };
+ static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
+
+ mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
+ udelay(2000);
+ mt352_write(fe, mt352_reset, sizeof(mt352_reset));
+ mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
+
+ mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
+ mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
+
+ return 0;
+}
+
+static int samsung_tdtc9251dh0_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params, u8* pllbuf)
+{
+ u32 div;
+ unsigned char bs = 0;
+
+ #define IF_FREQUENCYx6 217 /* 6 * 36.16666666667MHz */
+ div = (((params->frequency + 83333) * 3) / 500000) + IF_FREQUENCYx6;
+
+ if (params->frequency >= 48000000 && params->frequency <= 154000000) bs = 0x09;
+ if (params->frequency >= 161000000 && params->frequency <= 439000000) bs = 0x0a;
+ if (params->frequency >= 447000000 && params->frequency <= 863000000) bs = 0x08;
+
+ pllbuf[0] = 0xc2; /* Note: non-linux standard PLL i2c address */
+ pllbuf[1] = div >> 8;
+ pllbuf[2] = div & 0xff;
+ pllbuf[3] = 0xcc;
+ pllbuf[4] = bs;
+
+ return 0;
+}
+
+static struct mt352_config samsung_tdtc9251dh0_config = {
+ .demod_address = 0x0f,
+ .demod_init = samsung_tdtc9251dh0_demod_init,
+ .pll_set = samsung_tdtc9251dh0_pll_set,
+};
+
+static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
+{
+ struct flexcop_device *fc = fe->dvb->priv;
+ return request_firmware(fw, name, fc->dev);
+}
+
+static struct nxt2002_config samsung_tbmv_config = {
+ .demod_address = 0x0a,
+ .request_firmware = flexcop_fe_request_firmware,
+};
+
+static struct bcm3510_config air2pc_atsc_first_gen_config = {
+ .demod_address = 0x0f,
+ .request_firmware = flexcop_fe_request_firmware,
+};
+
+static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+{
+ u8 buf[4];
+ u32 div;
+ struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };
+ struct flexcop_device *fc = fe->dvb->priv;
+
+ div = (params->frequency + (125/2)) / 125;
+
+ buf[0] = (div >> 8) & 0x7f;
+ buf[1] = (div >> 0) & 0xff;
+ buf[2] = 0x84 | ((div >> 10) & 0x60);
+ buf[3] = 0x80;
+
+ if (params->frequency < 1550000)
+ buf[3] |= 0x02;
+
+ if (i2c_transfer(&fc->i2c_adap, &msg, 1) != 1)
+ return -EIO;
+ return 0;
+}
+
+static struct mt312_config skystar23_samsung_tbdu18132_config = {
+
+ .demod_address = 0x0e,
+ .pll_set = skystar23_samsung_tbdu18132_pll_set,
+};
+
+static struct stv0297_config alps_tdee4_stv0297_config = {
+ .demod_address = 0x1c,
+// .invert = 1,
+// .pll_set = alps_tdee4_stv0297_pll_set,
+};
+
+/* try to figure out the frontend, each card/box can have on of the following list */
+int flexcop_frontend_init(struct flexcop_device *fc)
+{
+ /* try the sky v2.6 (stv0299/Samsung tbmu24112(sl1935)) */
+ if ((fc->fe = stv0299_attach(&samsung_tbmu24112_config, &fc->i2c_adap)) != NULL) {
+ fc->fe->ops->set_voltage = flexcop_set_voltage;
+
+ fc->fe_sleep = fc->fe->ops->sleep;
+ fc->fe->ops->sleep = flexcop_sleep;
+
+ fc->dev_type = FC_SKY;
+ info("found the stv0299 at i2c address: 0x%02x",samsung_tbmu24112_config.demod_address);
+ } else
+ /* try the air dvb-t (mt352/Samsung tdtc9251dh0(??)) */
+ if ((fc->fe = mt352_attach(&samsung_tdtc9251dh0_config, &fc->i2c_adap)) != NULL ) {
+ fc->dev_type = FC_AIR_DVB;
+ info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address);
+ } else
+ /* try the air atsc 2nd generation (nxt2002) */
+ if ((fc->fe = nxt2002_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
+ fc->dev_type = FC_AIR_ATSC2;
+ info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
+ } else
+ /* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
+ if ((fc->fe = bcm3510_attach(&air2pc_atsc_first_gen_config, &fc->i2c_adap)) != NULL) {
+ fc->dev_type = FC_AIR_ATSC1;
+ info("found the bcm3510 at i2c address: 0x%02x",air2pc_atsc_first_gen_config.demod_address);
+ } else
+ /* try the cable dvb (stv0297) */
+ if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap, 0xf8)) != NULL) {
+ fc->dev_type = FC_CABLE;
+ info("found the stv0297 at i2c address: 0x%02x",alps_tdee4_stv0297_config.demod_address);
+ } else
+ /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */
+ if ((fc->fe = vp310_attach(&skystar23_samsung_tbdu18132_config, &fc->i2c_adap)) != NULL) {
+ fc->fe->ops->diseqc_send_master_cmd = flexcop_diseqc_send_master_cmd;
+ fc->fe->ops->diseqc_send_burst = flexcop_diseqc_send_burst;
+ fc->fe->ops->set_tone = flexcop_set_tone;
+ fc->fe->ops->set_voltage = flexcop_set_voltage;
+
+ fc->fe_sleep = fc->fe->ops->sleep;
+ fc->fe->ops->sleep = flexcop_sleep;
+
+ fc->dev_type = FC_SKY_OLD;
+ info("found the vp310 (aka mt312) at i2c address: 0x%02x",skystar23_samsung_tbdu18132_config.demod_address);
+ }
+
+ if (fc->fe == NULL) {
+ err("no frontend driver found for this B2C2/FlexCop adapter");
+ return -ENODEV;
+ } else {
+ if (dvb_register_frontend(&fc->dvb_adapter, fc->fe)) {
+ err("frontend registration failed!");
+ if (fc->fe->ops->release != NULL)
+ fc->fe->ops->release(fc->fe);
+ fc->fe = NULL;
+ return -EINVAL;
+ }
+ }
+ fc->init_state |= FC_STATE_FE_INIT;
+ return 0;
+}
+
+void flexcop_frontend_exit(struct flexcop_device *fc)
+{
+ if (fc->init_state & FC_STATE_FE_INIT)
+ dvb_unregister_frontend(fc->fe);
+
+ fc->init_state &= ~FC_STATE_FE_INIT;
+}
diff --git a/drivers/media/dvb/b2c2/flexcop-hw-filter.c b/drivers/media/dvb/b2c2/flexcop-hw-filter.c
new file mode 100644
index 00000000000..2baf43d3ce8
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop-hw-filter.c
@@ -0,0 +1,204 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
+ *
+ * flexcop-hw-filter.c - pid and mac address filtering and corresponding control functions.
+ *
+ * see flexcop.c for copyright information.
+ */
+#include "flexcop.h"
+
+static void flexcop_rcv_data_ctrl(struct flexcop_device *fc, int onoff)
+{
+ flexcop_set_ibi_value(ctrl_208,Rcv_Data_sig,onoff);
+}
+
+void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff)
+{
+ flexcop_set_ibi_value(ctrl_208,SMC_Enable_sig,onoff);
+}
+
+void flexcop_null_filter_ctrl(struct flexcop_device *fc, int onoff)
+{
+ flexcop_set_ibi_value(ctrl_208,Null_filter_sig,onoff);
+}
+
+void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6])
+{
+ flexcop_ibi_value v418,v41c;
+ v41c = fc->read_ibi_reg(fc,mac_address_41c);
+
+ v418.mac_address_418.MAC1 = mac[0];
+ v418.mac_address_418.MAC2 = mac[1];
+ v418.mac_address_418.MAC3 = mac[2];
+ v418.mac_address_418.MAC6 = mac[3];
+ v41c.mac_address_41c.MAC7 = mac[4];
+ v41c.mac_address_41c.MAC8 = mac[5];
+
+ fc->write_ibi_reg(fc,mac_address_418,v418);
+ fc->write_ibi_reg(fc,mac_address_41c,v41c);
+}
+
+void flexcop_mac_filter_ctrl(struct flexcop_device *fc, int onoff)
+{
+ flexcop_set_ibi_value(ctrl_208,MAC_filter_Mode_sig,onoff);
+}
+
+static void flexcop_pid_group_filter(struct flexcop_device *fc, u16 pid, u16 mask)
+{
+ /* index_reg_310.extra_index_reg need to 0 or 7 to work */
+ flexcop_ibi_value v30c;
+ v30c.pid_filter_30c_ext_ind_0_7.Group_PID = pid;
+ v30c.pid_filter_30c_ext_ind_0_7.Group_mask = mask;
+ fc->write_ibi_reg(fc,pid_filter_30c,v30c);
+}
+
+static void flexcop_pid_group_filter_ctrl(struct flexcop_device *fc, int onoff)
+{
+ flexcop_set_ibi_value(ctrl_208,Mask_filter_sig,onoff);
+}
+
+/* this fancy define reduces the code size of the quite similar PID controlling of
+ * the first 6 PIDs
+ */
+
+#define pid_ctrl(vregname,field,enablefield,trans_field,transval) \
+ flexcop_ibi_value vpid = fc->read_ibi_reg(fc, vregname), \
+ v208 = fc->read_ibi_reg(fc, ctrl_208); \
+\
+ vpid.vregname.field = onoff ? pid : 0x1fff; \
+ vpid.vregname.trans_field = transval; \
+ v208.ctrl_208.enablefield = onoff; \
+\
+ fc->write_ibi_reg(fc,vregname,vpid); \
+ fc->write_ibi_reg(fc,ctrl_208,v208);
+
+static void flexcop_pid_Stream1_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff)
+{
+ pid_ctrl(pid_filter_300,Stream1_PID,Stream1_filter_sig,Stream1_trans,0);
+}
+
+static void flexcop_pid_Stream2_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff)
+{
+ pid_ctrl(pid_filter_300,Stream2_PID,Stream2_filter_sig,Stream2_trans,0);
+}
+
+static void flexcop_pid_PCR_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff)
+{
+ pid_ctrl(pid_filter_304,PCR_PID,PCR_filter_sig,PCR_trans,0);
+}
+
+static void flexcop_pid_PMT_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff)
+{
+ pid_ctrl(pid_filter_304,PMT_PID,PMT_filter_sig,PMT_trans,0);
+}
+
+static void flexcop_pid_EMM_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff)
+{
+ pid_ctrl(pid_filter_308,EMM_PID,EMM_filter_sig,EMM_trans,0);
+}
+
+static void flexcop_pid_ECM_PID_ctrl(struct flexcop_device *fc, u16 pid, int onoff)
+{
+ pid_ctrl(pid_filter_308,ECM_PID,ECM_filter_sig,ECM_trans,0);
+}
+
+static void flexcop_pid_control(struct flexcop_device *fc, int index, u16 pid,int onoff)
+{
+ if (pid == 0x2000)
+ return;
+
+ deb_ts("setting pid: %5d %04x at index %d '%s'\n",pid,pid,index,onoff ? "on" : "off");
+
+ /* We could use bit magic here to reduce source code size.
+ * I decided against it, but to use the real register names */
+ switch (index) {
+ case 0: flexcop_pid_Stream1_PID_ctrl(fc,pid,onoff); break;
+ case 1: flexcop_pid_Stream2_PID_ctrl(fc,pid,onoff); break;
+ case 2: flexcop_pid_PCR_PID_ctrl(fc,pid,onoff); break;
+ case 3: flexcop_pid_PMT_PID_ctrl(fc,pid,onoff); break;
+ case 4: flexcop_pid_EMM_PID_ctrl(fc,pid,onoff); break;
+ case 5: flexcop_pid_ECM_PID_ctrl(fc,pid,onoff); break;
+ default:
+ if (fc->has_32_hw_pid_filter && index < 38) {
+ flexcop_ibi_value vpid,vid;
+
+ /* set the index */
+ vid = fc->read_ibi_reg(fc,index_reg_310);
+ vid.index_reg_310.index_reg = index - 6;
+ fc->write_ibi_reg(fc,index_reg_310, vid);
+
+ vpid = fc->read_ibi_reg(fc,pid_n_reg_314);
+ vpid.pid_n_reg_314.PID = onoff ? pid : 0x1fff;
+ vpid.pid_n_reg_314.PID_enable_bit = onoff;
+ fc->write_ibi_reg(fc,pid_n_reg_314, vpid);
+ }
+ break;
+ }
+}
+
+static int flexcop_toggle_fullts_streaming(struct flexcop_device *fc,int onoff)
+{
+ if (fc->fullts_streaming_state != onoff) {
+ deb_ts("%s full TS transfer\n",onoff ? "enabling" : "disabling");
+ flexcop_pid_group_filter(fc, 0, 0x1fe0 * (!onoff));
+ flexcop_pid_group_filter_ctrl(fc,onoff);
+ fc->fullts_streaming_state = onoff;
+ }
+ return 0;
+}
+
+int flexcop_pid_feed_control(struct flexcop_device *fc, struct dvb_demux_feed *dvbdmxfeed, int onoff)
+{
+ int max_pid_filter = 6 + fc->has_32_hw_pid_filter*32;
+
+ fc->feedcount += onoff ? 1 : -1;
+ if (dvbdmxfeed->index >= max_pid_filter)
+ fc->extra_feedcount += onoff ? 1 : -1;
+
+ /* toggle complete-TS-streaming when:
+ * - pid_filtering is not enabled and it is the first or last feed requested
+ * - pid_filtering is enabled,
+ * - but the number of requested feeds is exceeded
+ * - or the requested pid is 0x2000 */
+
+ if (!fc->pid_filtering && fc->feedcount == onoff)
+ flexcop_toggle_fullts_streaming(fc,onoff);
+
+ if (fc->pid_filtering) {
+ flexcop_pid_control(fc,dvbdmxfeed->index,dvbdmxfeed->pid,onoff);
+
+ if (fc->extra_feedcount > 0)
+ flexcop_toggle_fullts_streaming(fc,1);
+ else if (dvbdmxfeed->pid == 0x2000)
+ flexcop_toggle_fullts_streaming(fc,onoff);
+ else
+ flexcop_toggle_fullts_streaming(fc,0);
+ }
+
+ /* if it was the first or last feed request change the stream-status */
+ if (fc->feedcount == onoff) {
+ flexcop_rcv_data_ctrl(fc,onoff);
+ if (fc->stream_control)
+ fc->stream_control(fc,onoff);
+ }
+
+ return 0;
+}
+
+void flexcop_hw_filter_init(struct flexcop_device *fc)
+{
+ int i;
+ flexcop_ibi_value v;
+ for (i = 0; i < 6 + 32*fc->has_32_hw_pid_filter; i++)
+ flexcop_pid_control(fc,i,0x1fff,0);
+
+ flexcop_pid_group_filter(fc, 0, 0x1fe0);
+ flexcop_pid_group_filter_ctrl(fc,0);
+
+ v = fc->read_ibi_reg(fc,pid_filter_308);
+ v.pid_filter_308.EMM_filter_4 = 1;
+ v.pid_filter_308.EMM_filter_6 = 0;
+ fc->write_ibi_reg(fc,pid_filter_308,v);
+
+ flexcop_null_filter_ctrl(fc, 1);
+}
diff --git a/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/dvb/b2c2/flexcop-i2c.c
new file mode 100644
index 00000000000..be4266d4ae9
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop-i2c.c
@@ -0,0 +1,210 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
+ *
+ * flexcop-i2c.c - flexcop internal 2Wire bus (I2C) and dvb i2c initialization
+ *
+ * see flexcop.c for copyright information.
+ */
+#include "flexcop.h"
+
+#define FC_MAX_I2C_RETRIES 100000
+
+static int flexcop_i2c_operation(struct flexcop_device *fc, flexcop_ibi_value *r100)
+{
+ int i;
+ flexcop_ibi_value r;
+
+ r100->tw_sm_c_100.working_start = 1;
+ deb_i2c("r100 before: %08x\n",r100->raw);
+
+ fc->write_ibi_reg(fc, tw_sm_c_100, ibi_zero);
+ fc->write_ibi_reg(fc, tw_sm_c_100, *r100); /* initiating i2c operation */
+
+ for (i = 0; i < FC_MAX_I2C_RETRIES; i++) {
+ r = fc->read_ibi_reg(fc, tw_sm_c_100);
+
+ if (!r.tw_sm_c_100.no_base_addr_ack_error) {
+ if (r.tw_sm_c_100.st_done) { /* && !r.tw_sm_c_100.working_start */
+ *r100 = r;
+ deb_i2c("i2c success\n");
+ return 0;
+ }
+ } else {
+ deb_i2c("suffering from an i2c ack_error\n");
+ return -EREMOTEIO;
+ }
+ }
+ deb_i2c("tried %d times i2c operation, never finished or too many ack errors.\n",i);
+ return -EREMOTEIO;
+}
+
+static int flexcop_i2c_read4(struct flexcop_device *fc, flexcop_ibi_value r100, u8 *buf)
+{
+ flexcop_ibi_value r104;
+ int len = r100.tw_sm_c_100.total_bytes, /* remember total_bytes is buflen-1 */
+ ret;
+
+ if ((ret = flexcop_i2c_operation(fc,&r100)) != 0) {
+ /* The Cablestar needs a different kind of i2c-transfer (does not
+ * support "Repeat Start"):
+ * wait for the ACK failure,
+ * and do a subsequent read with the Bit 30 enabled
+ */
+ r100.tw_sm_c_100.no_base_addr_ack_error = 1;
+ if ((ret = flexcop_i2c_operation(fc,&r100)) != 0) {
+ deb_i2c("no_base_addr read failed. %d\n",ret);
+ return ret;
+ }
+ }
+
+ buf[0] = r100.tw_sm_c_100.data1_reg;
+
+ if (len > 0) {
+ r104 = fc->read_ibi_reg(fc,tw_sm_c_104);
+ deb_i2c("read: r100: %08x, r104: %08x\n",r100.raw,r104.raw);
+
+ /* there is at least one more byte, otherwise we wouldn't be here */
+ buf[1] = r104.tw_sm_c_104.data2_reg;
+ if (len > 1) buf[2] = r104.tw_sm_c_104.data3_reg;
+ if (len > 2) buf[3] = r104.tw_sm_c_104.data4_reg;
+ }
+
+ return 0;
+}
+
+static int flexcop_i2c_write4(struct flexcop_device *fc, flexcop_ibi_value r100, u8 *buf)
+{
+ flexcop_ibi_value r104;
+ int len = r100.tw_sm_c_100.total_bytes; /* remember total_bytes is buflen-1 */
+ r104.raw = 0;
+
+ /* there is at least one byte, otherwise we wouldn't be here */
+ r100.tw_sm_c_100.data1_reg = buf[0];
+
+ r104.tw_sm_c_104.data2_reg = len > 0 ? buf[1] : 0;
+ r104.tw_sm_c_104.data3_reg = len > 1 ? buf[2] : 0;
+ r104.tw_sm_c_104.data4_reg = len > 2 ? buf[3] : 0;
+
+ deb_i2c("write: r100: %08x, r104: %08x\n",r100.raw,r104.raw);
+
+ /* write the additional i2c data before doing the actual i2c operation */
+ fc->write_ibi_reg(fc,tw_sm_c_104,r104);
+ return flexcop_i2c_operation(fc,&r100);
+}
+
+int flexcop_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
+ flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u16 len)
+{
+ int ret;
+ u16 bytes_to_transfer;
+ flexcop_ibi_value r100;
+
+ deb_i2c("op = %d\n",op);
+ r100.raw = 0;
+ r100.tw_sm_c_100.chipaddr = chipaddr;
+ r100.tw_sm_c_100.twoWS_rw = op;
+ r100.tw_sm_c_100.twoWS_port_reg = port;
+
+ while (len != 0) {
+ bytes_to_transfer = len > 4 ? 4 : len;
+
+ r100.tw_sm_c_100.total_bytes = bytes_to_transfer - 1;
+ r100.tw_sm_c_100.baseaddr = addr;
+
+ if (op == FC_READ)
+ ret = flexcop_i2c_read4(fc, r100, buf);
+ else
+ ret = flexcop_i2c_write4(fc,r100, buf);
+
+ if (ret < 0)
+ return ret;
+
+ buf += bytes_to_transfer;
+ addr += bytes_to_transfer;
+ len -= bytes_to_transfer;
+ };
+
+ return 0;
+}
+/* exported for PCI i2c */
+EXPORT_SYMBOL(flexcop_i2c_request);
+
+/* master xfer callback for demodulator */
+static int flexcop_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
+{
+ struct flexcop_device *fc = i2c_get_adapdata(i2c_adap);
+ int i, ret = 0;
+
+ if (down_interruptible(&fc->i2c_sem))
+ return -ERESTARTSYS;
+
+ /* reading */
+ if (num == 2 &&
+ msgs[0].flags == 0 &&
+ msgs[1].flags == I2C_M_RD &&
+ msgs[0].buf != NULL &&
+ msgs[1].buf != NULL) {
+
+ ret = fc->i2c_request(fc, FC_READ, FC_I2C_PORT_DEMOD, msgs[0].addr, msgs[0].buf[0], msgs[1].buf, msgs[1].len);
+
+ } else for (i = 0; i < num; i++) { /* writing command */
+ if (msgs[i].flags != 0 || msgs[i].buf == NULL || msgs[i].len < 2) {
+ ret = -EINVAL;
+ break;
+ }
+
+ ret = fc->i2c_request(fc, FC_WRITE, FC_I2C_PORT_DEMOD, msgs[i].addr, msgs[i].buf[0], &msgs[i].buf[1], msgs[i].len - 1);
+ }
+
+ if (ret < 0)
+ err("i2c master_xfer failed");
+ else
+ ret = num;
+
+ up(&fc->i2c_sem);
+
+ return ret;
+}
+
+static u32 flexcop_i2c_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm flexcop_algo = {
+ .name = "FlexCop I2C algorithm",
+ .id = I2C_ALGO_BIT,
+ .master_xfer = flexcop_master_xfer,
+ .functionality = flexcop_i2c_func,
+};
+
+int flexcop_i2c_init(struct flexcop_device *fc)
+{
+ int ret;
+
+ sema_init(&fc->i2c_sem,1);
+
+ memset(&fc->i2c_adap, 0, sizeof(struct i2c_adapter));
+ strncpy(fc->i2c_adap.name, "B2C2 FlexCop device",I2C_NAME_SIZE);
+
+ i2c_set_adapdata(&fc->i2c_adap,fc);
+
+ fc->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
+ fc->i2c_adap.algo = &flexcop_algo;
+ fc->i2c_adap.algo_data = NULL;
+ fc->i2c_adap.id = I2C_ALGO_BIT;
+
+ if ((ret = i2c_add_adapter(&fc->i2c_adap)) < 0)
+ return ret;
+
+ fc->init_state |= FC_STATE_I2C_INIT;
+ return 0;
+}
+
+void flexcop_i2c_exit(struct flexcop_device *fc)
+{
+ if (fc->init_state & FC_STATE_I2C_INIT)
+ i2c_del_adapter(&fc->i2c_adap);
+
+ fc->init_state &= ~FC_STATE_I2C_INIT;
+}
diff --git a/drivers/media/dvb/b2c2/flexcop-misc.c b/drivers/media/dvb/b2c2/flexcop-misc.c
new file mode 100644
index 00000000000..23082545651
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop-misc.c
@@ -0,0 +1,67 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
+ *
+ * flexcop-misc.c - miscellaneous functions.
+ *
+ * see flexcop.c for copyright information.
+ */
+#include "flexcop.h"
+
+void flexcop_determine_revision(struct flexcop_device *fc)
+{
+ flexcop_ibi_value v = fc->read_ibi_reg(fc,misc_204);
+
+ switch (v.misc_204.Rev_N_sig_revision_hi) {
+ case 0x2:
+ deb_info("found a FlexCopII.\n");
+ fc->rev = FLEXCOP_II;
+ break;
+ case 0x3:
+ deb_info("found a FlexCopIIb.\n");
+ fc->rev = FLEXCOP_IIB;
+ break;
+ case 0x0:
+ deb_info("found a FlexCopIII.\n");
+ fc->rev = FLEXCOP_III;
+ break;
+ default:
+ err("unkown FlexCop Revision: %x. Please report the linux-dvb@linuxtv.org.",v.misc_204.Rev_N_sig_revision_hi);
+ break;
+ }
+
+ if ((fc->has_32_hw_pid_filter = v.misc_204.Rev_N_sig_caps))
+ deb_info("this FlexCop has the additional 32 hardware pid filter.\n");
+ else
+ deb_info("this FlexCop has only the 6 basic main hardware pid filter.\n");
+ /* bus parts have to decide if hw pid filtering is used or not. */
+}
+
+const char *flexcop_revision_names[] = {
+ "Unkown chip",
+ "FlexCopII",
+ "FlexCopIIb",
+ "FlexCopIII",
+};
+
+const char *flexcop_device_names[] = {
+ "Unkown device",
+ "Air2PC/AirStar 2 DVB-T",
+ "Air2PC/AirStar 2 ATSC 1st generation",
+ "Air2PC/AirStar 2 ATSC 2nd generation",
+ "Sky2PC/SkyStar 2 DVB-S",
+ "Sky2PC/SkyStar 2 DVB-S (old version)",
+ "Cable2PC/CableStar 2 DVB-C",
+};
+
+const char *flexcop_bus_names[] = {
+ "USB",
+ "PCI",
+};
+
+void flexcop_device_name(struct flexcop_device *fc,const char *prefix,const
+ char *suffix)
+{
+ info("%s '%s' at the '%s' bus controlled by a '%s' %s",prefix,
+ flexcop_device_names[fc->dev_type],flexcop_bus_names[fc->bus_type],
+ flexcop_revision_names[fc->rev],suffix);
+}
diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c
new file mode 100644
index 00000000000..ed717c0073d
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop-pci.c
@@ -0,0 +1,381 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
+ *
+ * flexcop-pci.c - covers the PCI part including DMA transfers.
+ *
+ * see flexcop.c for copyright information.
+ */
+
+#define FC_LOG_PREFIX "flexcop-pci"
+#include "flexcop-common.h"
+
+static int enable_pid_filtering = 1;
+module_param(enable_pid_filtering, int, 0444);
+MODULE_PARM_DESC(enable_pid_filtering, "enable hardware pid filtering: supported values: 0 (fullts), 1");
+
+#ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG
+#define dprintk(level,args...) \
+ do { if ((debug & level)) printk(args); } while (0)
+#define DEBSTATUS ""
+#else
+#define dprintk(level,args...)
+#define DEBSTATUS " (debugging is not enabled)"
+#endif
+
+#define deb_info(args...) dprintk(0x01,args)
+#define deb_reg(args...) dprintk(0x02,args)
+#define deb_ts(args...) dprintk(0x04,args)
+#define deb_irq(args...) dprintk(0x08,args)
+
+static int debug = 0;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debug level (1=info,2=regs,4=TS,8=irqdma (|-able))." DEBSTATUS);
+
+#define DRIVER_VERSION "0.1"
+#define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV PCI Driver"
+#define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de>"
+
+struct flexcop_pci {
+ struct pci_dev *pdev;
+
+#define FC_PCI_INIT 0x01
+#define FC_PCI_DMA_INIT 0x02
+ int init_state;
+
+ void __iomem *io_mem;
+ u32 irq;
+/* buffersize (at least for DMA1, need to be % 188 == 0,
+ * this logic is required */
+#define FC_DEFAULT_DMA1_BUFSIZE (1280 * 188)
+#define FC_DEFAULT_DMA2_BUFSIZE (10 * 188)
+ struct flexcop_dma dma[2];
+
+ int active_dma1_addr; /* 0 = addr0 of dma1; 1 = addr1 of dma1 */
+ u32 last_dma1_cur_pos; /* position of the pointer last time the timer/packet irq occured */
+ int count;
+
+ spinlock_t irq_lock;
+
+ struct flexcop_device *fc_dev;
+};
+
+static int lastwreg,lastwval,lastrreg,lastrval;
+
+static flexcop_ibi_value flexcop_pci_read_ibi_reg (struct flexcop_device *fc, flexcop_ibi_register r)
+{
+ struct flexcop_pci *fc_pci = fc->bus_specific;
+ flexcop_ibi_value v;
+ v.raw = readl(fc_pci->io_mem + r);
+
+ if (lastrreg != r || lastrval != v.raw) {
+ lastrreg = r; lastrval = v.raw;
+ deb_reg("new rd: %3x: %08x\n",r,v.raw);
+ }
+
+ return v;
+}
+
+static int flexcop_pci_write_ibi_reg(struct flexcop_device *fc, flexcop_ibi_register r, flexcop_ibi_value v)
+{
+ struct flexcop_pci *fc_pci = fc->bus_specific;
+
+ if (lastwreg != r || lastwval != v.raw) {
+ lastwreg = r; lastwval = v.raw;
+ deb_reg("new wr: %3x: %08x\n",r,v.raw);
+ }
+
+ writel(v.raw, fc_pci->io_mem + r);
+ return 0;
+}
+
+/* When PID filtering is turned on, we use the timer IRQ, because small amounts
+ * of data need to be passed to the user space instantly as well. When PID
+ * filtering is turned off, we use the page-change-IRQ */
+static irqreturn_t flexcop_pci_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct flexcop_pci *fc_pci = dev_id;
+ struct flexcop_device *fc = fc_pci->fc_dev;
+ flexcop_ibi_value v = fc->read_ibi_reg(fc,irq_20c);
+ irqreturn_t ret = IRQ_HANDLED;
+
+ spin_lock_irq(&fc_pci->irq_lock);
+
+ if (v.irq_20c.DMA1_IRQ_Status == 1) {
+ if (fc_pci->active_dma1_addr == 0)
+ flexcop_pass_dmx_packets(fc_pci->fc_dev,fc_pci->dma[0].cpu_addr0,fc_pci->dma[0].size / 188);
+ else
+ flexcop_pass_dmx_packets(fc_pci->fc_dev,fc_pci->dma[0].cpu_addr1,fc_pci->dma[0].size / 188);
+
+ deb_irq("page change to page: %d\n",!fc_pci->active_dma1_addr);
+ fc_pci->active_dma1_addr = !fc_pci->active_dma1_addr;
+ } else if (v.irq_20c.DMA1_Timer_Status == 1) {
+ /* for the timer IRQ we only can use buffer dmx feeding, because we don't have
+ * complete TS packets when reading from the DMA memory */
+ dma_addr_t cur_addr =
+ fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2;
+ u32 cur_pos = cur_addr - fc_pci->dma[0].dma_addr0;
+
+ deb_irq("irq: %08x cur_addr: %08x: cur_pos: %08x, last_cur_pos: %08x ",
+ v.raw,cur_addr,cur_pos,fc_pci->last_dma1_cur_pos);
+
+ /* buffer end was reached, restarted from the beginning
+ * pass the data from last_cur_pos to the buffer end to the demux
+ */
+ if (cur_pos < fc_pci->last_dma1_cur_pos) {
+ deb_irq(" end was reached: passing %d bytes ",(fc_pci->dma[0].size*2 - 1) - fc_pci->last_dma1_cur_pos);
+ flexcop_pass_dmx_data(fc_pci->fc_dev,
+ fc_pci->dma[0].cpu_addr0 + fc_pci->last_dma1_cur_pos,
+ (fc_pci->dma[0].size*2) - fc_pci->last_dma1_cur_pos);
+ fc_pci->last_dma1_cur_pos = 0;
+ fc_pci->count = 0;
+ }
+
+ if (cur_pos > fc_pci->last_dma1_cur_pos) {
+ deb_irq(" passing %d bytes ",cur_pos - fc_pci->last_dma1_cur_pos);
+ flexcop_pass_dmx_data(fc_pci->fc_dev,
+ fc_pci->dma[0].cpu_addr0 + fc_pci->last_dma1_cur_pos,
+ cur_pos - fc_pci->last_dma1_cur_pos);
+ }
+ deb_irq("\n");
+
+ fc_pci->last_dma1_cur_pos = cur_pos;
+ } else
+ ret = IRQ_NONE;
+
+ spin_unlock_irq(&fc_pci->irq_lock);
+
+/* packet count would be ideal for hw filtering, but it isn't working. Either
+ * the data book is wrong, or I'm unable to read it correctly */
+
+/* if (v.irq_20c.DMA1_Size_IRQ_Status == 1) { packet counter */
+
+ return ret;
+}
+
+static int flexcop_pci_stream_control(struct flexcop_device *fc, int onoff)
+{
+ struct flexcop_pci *fc_pci = fc->bus_specific;
+ if (onoff) {
+ flexcop_dma_config(fc,&fc_pci->dma[0],FC_DMA_1,FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1);
+ flexcop_dma_config(fc,&fc_pci->dma[1],FC_DMA_2,FC_DMA_SUBADDR_0 | FC_DMA_SUBADDR_1);
+ flexcop_dma_config_timer(fc,FC_DMA_1,1);
+
+ if (fc_pci->fc_dev->pid_filtering) {
+ fc_pci->last_dma1_cur_pos = 0;
+ flexcop_dma_control_timer_irq(fc,FC_DMA_1,1);
+ } else {
+ fc_pci->active_dma1_addr = 0;
+ flexcop_dma_control_size_irq(fc,FC_DMA_1,1);
+ }
+
+/* flexcop_dma_config_packet_count(fc,FC_DMA_1,0xc0);
+ flexcop_dma_control_packet_irq(fc,FC_DMA_1,1); */
+
+ deb_irq("irqs enabled\n");
+ } else {
+ if (fc_pci->fc_dev->pid_filtering)
+ flexcop_dma_control_timer_irq(fc,FC_DMA_1,0);
+ else
+ flexcop_dma_control_size_irq(fc,FC_DMA_1,0);
+
+// flexcop_dma_control_packet_irq(fc,FC_DMA_1,0);
+ deb_irq("irqs disabled\n");
+ }
+
+ return 0;
+}
+
+static int flexcop_pci_dma_init(struct flexcop_pci *fc_pci)
+{
+ int ret;
+ if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[0],FC_DEFAULT_DMA1_BUFSIZE)) != 0)
+ return ret;
+
+ if ((ret = flexcop_dma_allocate(fc_pci->pdev,&fc_pci->dma[1],FC_DEFAULT_DMA2_BUFSIZE)) != 0)
+ goto dma1_free;
+
+ flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_MEDIA | FC_SRAM_DEST_NET, FC_SRAM_DEST_TARGET_DMA1);
+ flexcop_sram_set_dest(fc_pci->fc_dev,FC_SRAM_DEST_CAO | FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_DMA2);
+
+ fc_pci->init_state |= FC_PCI_DMA_INIT;
+ goto success;
+dma1_free:
+ flexcop_dma_free(&fc_pci->dma[0]);
+
+success:
+ return ret;
+}
+
+static void flexcop_pci_dma_exit(struct flexcop_pci *fc_pci)
+{
+ if (fc_pci->init_state & FC_PCI_DMA_INIT) {
+ flexcop_dma_free(&fc_pci->dma[0]);
+ flexcop_dma_free(&fc_pci->dma[1]);
+ }
+ fc_pci->init_state &= ~FC_PCI_DMA_INIT;
+}
+
+static int flexcop_pci_init(struct flexcop_pci *fc_pci)
+{
+ int ret;
+ u8 card_rev;
+
+ pci_read_config_byte(fc_pci->pdev, PCI_CLASS_REVISION, &card_rev);
+ info("card revision %x", card_rev);
+
+ if ((ret = pci_enable_device(fc_pci->pdev)) != 0)
+ return ret;
+
+ pci_set_master(fc_pci->pdev);
+
+ /* enable interrupts */
+ // pci_write_config_dword(pdev, 0x6c, 0x8000);
+
+ if ((ret = pci_request_regions(fc_pci->pdev, DRIVER_NAME)) != 0)
+ goto err_pci_disable_device;
+
+ fc_pci->io_mem = pci_iomap(fc_pci->pdev, 0, 0x800);
+
+ if (!fc_pci->io_mem) {
+ err("cannot map io memory\n");
+ ret = -EIO;
+ goto err_pci_release_regions;
+ }
+
+ pci_set_drvdata(fc_pci->pdev, fc_pci);
+
+ if ((ret = request_irq(fc_pci->pdev->irq, flexcop_pci_irq,
+ SA_SHIRQ, DRIVER_NAME, fc_pci)) != 0)
+ goto err_pci_iounmap;
+
+ spin_lock_init(&fc_pci->irq_lock);
+
+ fc_pci->init_state |= FC_PCI_INIT;
+ goto success;
+
+err_pci_iounmap:
+ pci_iounmap(fc_pci->pdev, fc_pci->io_mem);
+ pci_set_drvdata(fc_pci->pdev, NULL);
+err_pci_release_regions:
+ pci_release_regions(fc_pci->pdev);
+err_pci_disable_device:
+ pci_disable_device(fc_pci->pdev);
+
+success:
+ return ret;
+}
+
+static void flexcop_pci_exit(struct flexcop_pci *fc_pci)
+{
+ if (fc_pci->init_state & FC_PCI_INIT) {
+ free_irq(fc_pci->pdev->irq, fc_pci);
+ pci_iounmap(fc_pci->pdev, fc_pci->io_mem);
+ pci_set_drvdata(fc_pci->pdev, NULL);
+ pci_release_regions(fc_pci->pdev);
+ pci_disable_device(fc_pci->pdev);
+ }
+ fc_pci->init_state &= ~FC_PCI_INIT;
+}
+
+
+static int flexcop_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ struct flexcop_device *fc;
+ struct flexcop_pci *fc_pci;
+ int ret = -ENOMEM;
+
+ if ((fc = flexcop_device_kmalloc(sizeof(struct flexcop_pci))) == NULL) {
+ err("out of memory\n");
+ return -ENOMEM;
+ }
+
+/* general flexcop init */
+ fc_pci = fc->bus_specific;
+ fc_pci->fc_dev = fc;
+
+ fc->read_ibi_reg = flexcop_pci_read_ibi_reg;
+ fc->write_ibi_reg = flexcop_pci_write_ibi_reg;
+ fc->i2c_request = flexcop_i2c_request;
+ fc->get_mac_addr = flexcop_eeprom_check_mac_addr;
+
+ fc->stream_control = flexcop_pci_stream_control;
+
+ if (enable_pid_filtering)
+ info("will use the HW PID filter.");
+ else
+ info("will pass the complete TS to the demuxer.");
+
+ fc->pid_filtering = enable_pid_filtering;
+ fc->bus_type = FC_PCI;
+
+ fc->dev = &pdev->dev;
+ fc->owner = THIS_MODULE;
+
+/* bus specific part */
+ fc_pci->pdev = pdev;
+ if ((ret = flexcop_pci_init(fc_pci)) != 0)
+ goto err_kfree;
+
+/* init flexcop */
+ if ((ret = flexcop_device_initialize(fc)) != 0)
+ goto err_pci_exit;
+
+/* init dma */
+ if ((ret = flexcop_pci_dma_init(fc_pci)) != 0)
+ goto err_fc_exit;
+
+ goto success;
+err_fc_exit:
+ flexcop_device_exit(fc);
+err_pci_exit:
+ flexcop_pci_exit(fc_pci);
+err_kfree:
+ flexcop_device_kfree(fc);
+success:
+ return ret;
+}
+
+/* in theory every _exit function should be called exactly two times,
+ * here and in the bail-out-part of the _init-function
+ */
+static void flexcop_pci_remove(struct pci_dev *pdev)
+{
+ struct flexcop_pci *fc_pci = pci_get_drvdata(pdev);
+
+ flexcop_pci_dma_exit(fc_pci);
+ flexcop_device_exit(fc_pci->fc_dev);
+ flexcop_pci_exit(fc_pci);
+ flexcop_device_kfree(fc_pci->fc_dev);
+}
+
+static struct pci_device_id flexcop_pci_tbl[] = {
+ { PCI_DEVICE(0x13d0, 0x2103) },
+/* { PCI_DEVICE(0x13d0, 0x2200) }, PCI FlexCopIII ? */
+ { },
+};
+
+MODULE_DEVICE_TABLE(pci, flexcop_pci_tbl);
+
+static struct pci_driver flexcop_pci_driver = {
+ .name = "Technisat/B2C2 FlexCop II/IIb/III PCI",
+ .id_table = flexcop_pci_tbl,
+ .probe = flexcop_pci_probe,
+ .remove = flexcop_pci_remove,
+};
+
+static int __init flexcop_pci_module_init(void)
+{
+ return pci_register_driver(&flexcop_pci_driver);
+}
+
+static void __exit flexcop_pci_module_exit(void)
+{
+ pci_unregister_driver(&flexcop_pci_driver);
+}
+
+module_init(flexcop_pci_module_init);
+module_exit(flexcop_pci_module_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_NAME);
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h
new file mode 100644
index 00000000000..75b50f21afe
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop-reg.h
@@ -0,0 +1,702 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
+ *
+ * flexcop-reg.h - register abstraction for FlexCopII, FlexCopIIb and FlexCopIII
+ *
+ * see flexcop.c for copyright information.
+ */
+#ifndef __FLEXCOP_REG_H__
+#define __FLEXCOP_REG_H__
+
+
+typedef enum {
+ FLEXCOP_UNK = 0,
+ FLEXCOP_II,
+ FLEXCOP_IIB,
+ FLEXCOP_III,
+} flexcop_revision_t;
+
+extern const char *flexcop_revision_names[];
+
+typedef enum {
+ FC_UNK = 0,
+ FC_AIR_DVB,
+ FC_AIR_ATSC1,
+ FC_AIR_ATSC2,
+ FC_SKY,
+ FC_SKY_OLD,
+ FC_CABLE,
+} flexcop_device_type_t;
+
+typedef enum {
+ FC_USB = 0,
+ FC_PCI,
+} flexcop_bus_t;
+
+extern const char *flexcop_device_names[];
+
+/* FlexCop IBI Registers */
+
+/* flexcop_ibi_reg - a huge union representing the register structure */
+typedef union {
+ u32 raw;
+
+/* DMA 0x000 to 0x01c
+ * DMA1 0x000 to 0x00c
+ * DMA2 0x010 to 0x01c
+ */
+ struct {
+ u32 dma_0start : 1; /* set: data will be delivered to dma1_address0 */
+ u32 dma_0No_update : 1; /* set: dma1_cur_address will be updated, unset: no update */
+ u32 dma_address0 :30; /* physical/virtual host memory address0 DMA */
+ } dma_0x0;
+
+ struct {
+ u32 DMA_maxpackets : 8; /* (remapped) PCI DMA1 Packet Count Interrupt. This variable
+ is able to be read and written while bit(1) of register
+ 0x00c (remap_enable) is set. This variable represents
+ the number of packets that will be transmitted to the PCI
+ host using PCI DMA1 before an interrupt to the PCI is
+ asserted. This functionality may be enabled using bit(20)
+ of register 0x208. N=0 disables the IRQ. */
+ u32 dma_addr_size :24; /* size of memory buffer in DWORDs (bytesize / 4) for DMA */
+ } dma_0x4_remap;
+
+ struct {
+ u32 dma1timer : 7; /* reading PCI DMA1 timer ... when remap_enable is 0 */
+ u32 unused : 1;
+ u32 dma_addr_size :24;
+ } dma_0x4_read;
+
+ struct {
+ u32 unused : 1;
+ u32 dmatimer : 7; /* writing PCI DMA1 timer ... when remap_enable is 0 */
+ u32 dma_addr_size :24;
+ } dma_0x4_write;
+
+ struct {
+ u32 unused : 2;
+ u32 dma_cur_addr :30; /* current physical host memory address pointer for DMA */
+ } dma_0x8;
+
+ struct {
+ u32 dma_1start : 1; /* set: data will be delivered to dma_address1, when dma_address0 is full */
+ u32 remap_enable : 1; /* remap enable for 0x0x4(7:0) */
+ u32 dma_address1 :30; /* Physical/virtual address 1 on DMA */
+ } dma_0xc;
+
+/* Two-wire Serial Master and Clock 0x100-0x110 */
+ struct {
+// u32 slave_transmitter : 1; /* ???*/
+ u32 chipaddr : 7; /* two-line serial address of the target slave */
+ u32 reserved1 : 1;
+ u32 baseaddr : 8; /* address of the location of the read/write operation */
+ u32 data1_reg : 8; /* first byte in two-line serial read/write operation */
+ u32 working_start : 1; /* when doing a write operation this indicator is 0 when ready
+ * set to 1 when doing a write operation */
+ u32 twoWS_rw : 1; /* read/write indicator (1 = read, 0 write) */
+ u32 total_bytes : 2; /* number of data bytes in each two-line serial transaction (0 = 1 byte, 11 = 4byte)*/
+ u32 twoWS_port_reg : 2; /* port selection: 01 - Front End/Demod, 10 - EEPROM, 11 - Tuner */
+ u32 no_base_addr_ack_error : 1; /* writing: write-req: frame is produced w/o baseaddr, read-req: read-cycles w/o
+ * preceding address assignment write frame
+ * ACK_ERROR = 1 when no ACK from slave in the last transaction */
+ u32 st_done : 1; /* indicator for transaction is done */
+ } tw_sm_c_100;
+
+ struct {
+ u32 data2_reg : 8; /* 2nd data byte */
+ u32 data3_reg : 8; /* 3rd data byte */
+ u32 data4_reg : 8; /* 4th data byte */
+ u32 exlicit_stops : 1; /* when set, transactions are produced w/o trailing STOP flag, then send isolated STOP flags */
+ u32 force_stop : 1; /* isolated stop flag */
+ u32 unused : 6;
+ } tw_sm_c_104;
+
+/* Clock. The register allows the FCIII to convert an incoming Master clock
+ * (MCLK) signal into a lower frequency clock through the use of a LowCounter
+ * (TLO) and a High- Counter (THI). The time counts for THI and TLO are
+ * measured in MCLK; each count represents 4 MCLK input clock cycles.
+ *
+ * The default output for port #1 is set for Front End Demod communication. (0x108)
+ * The default output for port #2 is set for EEPROM communication. (0x10c)
+ * The default output for port #3 is set for Tuner communication. (0x110)
+ */
+ struct {
+ u32 thi1 : 6; /* Thi for port #1 (def: 100110b; 38) */
+ u32 reserved1 : 2;
+ u32 tlo1 : 5; /* Tlo for port #1 (def: 11100b; 28) */
+ u32 reserved2 :19;
+ } tw_sm_c_108;
+
+ struct {
+ u32 thi1 : 6; /* Thi for port #2 (def: 111001b; 57) */
+ u32 reserved1 : 2;
+ u32 tlo1 : 5; /* Tlo for port #2 (def: 11100b; 28) */
+ u32 reserved2 :19;
+ } tw_sm_c_10c;
+
+ struct {
+ u32 thi1 : 6; /* Thi for port #3 (def: 111001b; 57) */
+ u32 reserved1 : 2;
+ u32 tlo1 : 5; /* Tlo for port #3 (def: 11100b; 28) */
+ u32 reserved2 :19;
+ } tw_sm_c_110;
+
+/* LNB Switch Frequency 0x200
+ * Clock that creates the LNB switch tone. The default is set to have a fixed
+ * low output (not oscillating) to the LNB_CTL line.
+ */
+ struct {
+ u32 LNB_CTLHighCount_sig :15; /* It is the number of pre-scaled clock cycles that will be low. */
+ u32 LNB_CTLLowCount_sig :15; /* For example, to obtain a 22KHz output given a 45 Mhz Master
+ Clock signal (MCLK), set PreScalar=01 and LowCounter value to 0x1ff. */
+ u32 LNB_CTLPrescaler_sig : 2; /* pre-scaler divides MCLK: 00 (no division), 01 by 2, 10 by 4, 11 by 12 */
+ } lnb_switch_freq_200;
+
+/* ACPI, Peripheral Reset, LNB Polarity
+ * ACPI power conservation mode, LNB polarity selection (low or high voltage),
+ * and peripheral reset.
+ */
+ struct {
+ u32 ACPI1_sig : 1; /* turn of the power of tuner and LNB, not implemented in FCIII */
+ u32 ACPI3_sig : 1; /* turn of power of the complete satelite receiver board (except FCIII) */
+ u32 LNB_L_H_sig : 1; /* low or high voltage for LNB. (0 = low, 1 = high) */
+ u32 Per_reset_sig : 1; /* misc. init reset (default: 1), to reset set to low and back to high */
+ u32 reserved :20;
+ u32 Rev_N_sig_revision_hi : 4;/* 0xc in case of FCIII */
+ u32 Rev_N_sig_reserved1 : 2;
+ u32 Rev_N_sig_caps : 1; /* if 1, FCIII has 32 PID- and MAC-filters and is capable of IP multicast */
+ u32 Rev_N_sig_reserved2 : 1;
+ } misc_204;
+
+/* Control and Status 0x208 to 0x21c */
+/* Gross enable and disable control */
+ struct {
+ u32 Stream1_filter_sig : 1; /* Stream1 PID filtering */
+ u32 Stream2_filter_sig : 1; /* Stream2 PID filtering */
+ u32 PCR_filter_sig : 1; /* PCR PID filter */
+ u32 PMT_filter_sig : 1; /* PMT PID filter */
+
+ u32 EMM_filter_sig : 1; /* EMM PID filter */
+ u32 ECM_filter_sig : 1; /* ECM PID filter */
+ u32 Null_filter_sig : 1; /* Filters null packets, PID=0x1fff. */
+ u32 Mask_filter_sig : 1; /* mask PID filter */
+
+ u32 WAN_Enable_sig : 1; /* WAN output line through V8 memory space is activated. */
+ u32 WAN_CA_Enable_sig : 1; /* not in FCIII */
+ u32 CA_Enable_sig : 1; /* not in FCIII */
+ u32 SMC_Enable_sig : 1; /* CI stream data (CAI) goes directly to the smart card intf (opposed IBI 0x600 or SC-cmd buf). */
+
+ u32 Per_CA_Enable_sig : 1; /* not in FCIII */
+ u32 Multi2_Enable_sig : 1; /* ? */
+ u32 MAC_filter_Mode_sig : 1; /* (MAC_filter_enable) Globally enables MAC filters for Net PID filteres. */
+ u32 Rcv_Data_sig : 1; /* PID filtering module enable. When this bit is a one, the PID filter will
+ examine and process packets according to all other (individual) PID
+ filtering controls. If it a zero, no packet processing of any kind will
+ take place. All data from the tuner will be thrown away. */
+
+ u32 DMA1_IRQ_Enable_sig : 1; /* When set, a DWORD counter is enabled on PCI DMA1 that asserts the PCI
+ * interrupt after the specified count for filling the buffer. */
+ u32 DMA1_Timer_Enable_sig : 1; /* When set, a timer is enabled on PCI DMA1 that asserts the PCI interrupt
+ after a specified amount of time. */
+ u32 DMA2_IRQ_Enable_sig : 1; /* same as DMA1_IRQ_Enable_sig but for DMA2 */
+ u32 DMA2_Timer_Enable_sig : 1; /* same as DMA1_Timer_Enable_sig but for DMA2 */
+
+ u32 DMA1_Size_IRQ_Enable_sig : 1; /* When set, a packet count detector is enabled on PCI DMA1 that asserts the PCI interrupt. */
+ u32 DMA2_Size_IRQ_Enable_sig : 1; /* When set, a packet count detector is enabled on PCI DMA2 that asserts the PCI interrupt. */
+ u32 Mailbox_from_V8_Enable_sig: 1; /* When set, writes to the mailbox register produce an interrupt to the
+ PCI host to indicate that mailbox data is available. */
+
+ u32 unused : 9;
+ } ctrl_208;
+
+/* General status. When a PCI interrupt occurs, this register is read to
+ * discover the reason for the interrupt.
+ */
+ struct {
+ u32 DMA1_IRQ_Status : 1; /* When set(1) the DMA1 counter had generated an IRQ. Read Only. */
+ u32 DMA1_Timer_Status : 1; /* When set(1) the DMA1 timer had generated an IRQ. Read Only. */
+ u32 DMA2_IRQ_Status : 1; /* When set(1) the DMA2 counter had generated an IRQ. Read Only. */
+ u32 DMA2_Timer_Status : 1; /* When set(1) the DMA2 timer had generated an IRQ. Read Only. */
+ u32 DMA1_Size_IRQ_Status : 1; /* (Read only). This register is read after an interrupt to */
+ u32 DMA2_Size_IRQ_Status : 1; /* find out why we had an IRQ. Reading this register will clear this bit. Packet count*/
+ u32 Mailbox_from_V8_Status_sig: 1; /* Same as above. Reading this register will clear this bit. */
+ u32 Data_receiver_error : 1; /* 1 indicate an error in the receiver Front End (Tuner module) */
+ u32 Continuity_error_flag : 1; /* 1 indicates a continuity error in the TS stream. */
+ u32 LLC_SNAP_FLAG_set : 1; /* 1 indicates that the LCC_SNAP_FLAG was set. */
+ u32 Transport_Error : 1; /* When set indicates that an unexpected packet was received. */
+ u32 reserved :21;
+ } irq_20c;
+
+
+/* Software reset register */
+ struct {
+ u32 reset_blocks : 8; /* Enabled when Block_reset_enable = 0xB2 and 0x208 bits 15:8 = 0x00.
+ Each bit location represents a 0x100 block of registers. Writing
+ a one in a bit location resets that block of registers and the logic
+ that it controls. */
+ u32 Block_reset_enable : 8; /* This variable is set to 0xB2 when the register is written. */
+ u32 Special_controls :16; /* Asserts Reset_V8 => 0xC258; Turns on pci encryption => 0xC25A;
+ Turns off pci encryption => 0xC259 Note: pci_encryption default
+ at power-up is ON. */
+ } sw_reset_210;
+
+ struct {
+ u32 vuart_oe_sig : 1; /* When clear, the V8 processor has sole control of the serial UART
+ (RS-232 Smart Card interface). When set, the IBI interface
+ defined by register 0x600 controls the serial UART. */
+ u32 v2WS_oe_sig : 1; /* When clear, the V8 processor has direct control of the Two-line
+ Serial Master EEPROM target. When set, the Two-line Serial Master
+ EEPROM target interface is controlled by IBI register 0x100. */
+ u32 halt_V8_sig : 1; /* When set, contiguous wait states are applied to the V8-space
+ bus masters. Once this signal is cleared, normal V8-space
+ operations resume. */
+ u32 section_pkg_enable_sig: 1; /* When set, this signal enables the front end translation circuitry
+ to process section packed transport streams. */
+ u32 s2p_sel_sig : 1; /* Serial to parallel conversion. When set, polarized transport data
+ within the FlexCop3 front end circuitry is converted from a serial
+ stream into parallel data before downstream processing otherwise
+ interprets the data. */
+ u32 unused1 : 3;
+ u32 polarity_PS_CLK_sig: 1; /* This signal is used to invert the input polarity of the tranport
+ stream CLOCK signal before any processing occurs on the transport
+ stream within FlexCop3. */
+ u32 polarity_PS_VALID_sig: 1; /* This signal is used to invert the input polarity of the tranport
+ stream VALID signal before any processing occurs on the transport
+ stream within FlexCop3. */
+ u32 polarity_PS_SYNC_sig: 1; /* This signal is used to invert the input polarity of the tranport
+ stream SYNC signal before any processing occurs on the transport
+ stream within FlexCop3. */
+ u32 polarity_PS_ERR_sig: 1; /* This signal is used to invert the input polarity of the tranport
+ stream ERROR signal before any processing occurs on the transport
+ stream within FlexCop3. */
+ u32 unused2 :20;
+ } misc_214;
+
+/* Mailbox from V8 to host */
+ struct {
+ u32 Mailbox_from_V8 :32; /* When this register is written by either the V8 processor or by an
+ end host, an interrupt is generated to the PCI host to indicate
+ that mailbox data is available. Reading register 20c will clear
+ the IRQ. */
+ } mbox_v8_to_host_218;
+
+/* Mailbox from host to v8 Mailbox_to_V8
+ * Mailbox_to_V8 mailbox storage register
+ * used to send messages from PCI to V8. Writing to this register will send an
+ * IRQ to the V8. Then it can read the data from here. Reading this register
+ * will clear the IRQ. If the V8 is halted and bit 31 of this register is set,
+ * then this register is used instead as a direct interface to access the
+ * V8space memory.
+ */
+ struct {
+ u32 sysramaccess_data : 8; /* Data byte written or read from the specified address in V8 SysRAM. */
+ u32 sysramaccess_addr :15; /* 15 bit address used to access V8 Sys-RAM. */
+ u32 unused : 7;
+ u32 sysramaccess_write: 1; /* Write flag used to latch data into the V8 SysRAM. */
+ u32 sysramaccess_busmuster: 1; /* Setting this bit when the V8 is halted at 0x214 Bit(2) allows
+ this IBI register interface to directly drive the V8-space memory. */
+ } mbox_host_to_v8_21c;
+
+
+/* PIDs, Translation Bit, SMC Filter Select 0x300 to 0x31c */
+ struct {
+ u32 Stream1_PID :13; /* Primary use is receiving Net data, so these 13 bits normally
+ hold the PID value for the desired network stream. */
+ u32 Stream1_trans : 1; /* When set, Net translation will take place for Net data ferried in TS packets. */
+ u32 MAC_Multicast_filter : 1; /* When clear, multicast MAC filtering is not allowed for Stream1 and PID_n filters. */
+ u32 debug_flag_pid_saved : 1;
+ u32 Stream2_PID :13; /* 13 bits for Stream 2 PID filter value. General use. */
+ u32 Stream2_trans : 1; /* When set Tables/CAI translation will take place for the data ferried in
+ Stream2_PID TS packets. */
+ u32 debug_flag_write_status00 : 1;
+ u32 debug_fifo_problem : 1;
+ } pid_filter_300;
+
+ struct {
+ u32 PCR_PID :13; /* PCR stream PID filter value. Primary use is Program Clock Reference stream filtering. */
+ u32 PCR_trans : 1; /* When set, Tables/CAI translation will take place for these packets. */
+ u32 debug_overrun3 : 1;
+ u32 debug_overrun2 : 1;
+ u32 PMT_PID :13; /* stream PID filter value. Primary use is Program Management Table segment filtering. */
+ u32 PMT_trans : 1; /* When set, Tables/CAI translation will take place for these packets. */
+ u32 reserved : 2;
+ } pid_filter_304;
+
+ struct {
+ u32 EMM_PID :13; /* EMM PID filter value. Primary use is Entitlement Management Messaging for
+ conditional access-related data. */
+ u32 EMM_trans : 1; /* When set, Tables/CAI translation will take place for these packets. */
+ u32 EMM_filter_4 : 1; /* When set will pass only EMM data possessing the same ID code as the
+ first four bytes (32 bits) of the end-user s 6-byte Smart Card ID number Select */
+ u32 EMM_filter_6 : 1; /* When set will pass only EMM data possessing the same 6-byte code as the end-users
+ complete 6-byte Smart Card ID number. */
+ u32 ECM_PID :13; /* ECM PID filter value. Primary use is Entitlement Control Messaging for conditional
+ access-related data. */
+ u32 ECM_trans : 1; /* When set, Tables/CAI translation will take place for these packets. */
+ u32 reserved : 2;
+ } pid_filter_308;
+
+ struct {
+ u32 Group_PID :13; /* PID value for group filtering. */
+ u32 Group_trans : 1; /* When set, Tables/CAI translation will take place for these packets. */
+ u32 unused1 : 2;
+ u32 Group_mask :13; /* Mask value used in logical "and" equation that defines group filtering */
+ u32 unused2 : 3;
+ } pid_filter_30c_ext_ind_0_7;
+
+ struct {
+ u32 net_master_read :17;
+ u32 unused :15;
+ } pid_filter_30c_ext_ind_1;
+
+ struct {
+ u32 net_master_write :17;
+ u32 unused :15;
+ } pid_filter_30c_ext_ind_2;
+
+ struct {
+ u32 next_net_master_write :17;
+ u32 unused :15;
+ } pid_filter_30c_ext_ind_3;
+
+ struct {
+ u32 unused1 : 1;
+ u32 state_write :10;
+ u32 reserved1 : 6; /* default: 000100 */
+ u32 stack_read :10;
+ u32 reserved2 : 5; /* default: 00100 */
+ } pid_filter_30c_ext_ind_4;
+
+ struct {
+ u32 stack_cnt :10;
+ u32 unused :22;
+ } pid_filter_30c_ext_ind_5;
+
+ struct {
+ u32 pid_fsm_save_reg0 : 2;
+ u32 pid_fsm_save_reg1 : 2;
+ u32 pid_fsm_save_reg2 : 2;
+ u32 pid_fsm_save_reg3 : 2;
+ u32 pid_fsm_save_reg4 : 2;
+ u32 pid_fsm_save_reg300 : 2;
+ u32 write_status1 : 2;
+ u32 write_status4 : 2;
+ u32 data_size_reg :12;
+ u32 unused : 4;
+ } pid_filter_30c_ext_ind_6;
+
+ struct {
+ u32 index_reg : 5; /* (Index pointer) Points at an internal PIDn register. A binary code
+ representing one of 32 internal PIDn registers as well as its
+ corresponding internal MAC_lown register. */
+ u32 extra_index_reg : 3; /* This vector is used to select between sets of debug signals routed to register 0x30c. */
+ u32 AB_select : 1; /* Used in conjunction with 0x31c. read/write to the MAC_highA or MAC_highB register
+ 0=MAC_highB register, 1=MAC_highA */
+ u32 pass_alltables : 1; /* 1=Net packets are not filtered against the Network Table ID found in register 0x400.
+ All types of networks (DVB, ATSC, ISDB) are passed. */
+ u32 unused :22;
+ } index_reg_310;
+
+ struct {
+ u32 PID :13; /* PID value */
+ u32 PID_trans : 1; /* translation will take place for packets filtered */
+ u32 PID_enable_bit : 1; /* When set this PID filter is enabled */
+ u32 reserved :17;
+ } pid_n_reg_314;
+
+ struct {
+ u32 A4_byte : 8;
+ u32 A5_byte : 8;
+ u32 A6_byte : 8;
+ u32 Enable_bit : 1; /* enabled (1) or disabled (1) */
+ u32 HighAB_bit : 1; /* use MAC_highA (1) or MAC_highB (0) as MSB */
+ u32 reserved : 6;
+ } mac_low_reg_318;
+
+ struct {
+ u32 A1_byte : 8;
+ u32 A2_byte : 8;
+ u32 A3_byte : 8;
+ u32 reserved : 8;
+ } mac_high_reg_31c;
+
+/* Table, SMCID,MACDestination Filters 0x400 to 0x41c */
+ struct {
+ u32 reserved :16;
+#define fc_data_Tag_ID_DVB 0x3e
+#define fc_data_Tag_ID_ATSC 0x3f
+#define fc_data_Tag_ID_IDSB 0x8b
+ u32 data_Tag_ID :16;
+ } data_tag_400;
+
+ struct {
+ u32 Card_IDbyte6 : 8;
+ u32 Card_IDbyte5 : 8;
+ u32 Card_IDbyte4 : 8;
+ u32 Card_IDbyte3 : 8;
+ } card_id_408;
+
+ struct {
+ u32 Card_IDbyte2 : 8;
+ u32 Card_IDbyte1 : 8;
+ } card_id_40c;
+
+ /* holding the unique mac address of the receiver which houses the FlexCopIII */
+ struct {
+ u32 MAC1 : 8;
+ u32 MAC2 : 8;
+ u32 MAC3 : 8;
+ u32 MAC6 : 8;
+ } mac_address_418;
+
+ struct {
+ u32 MAC7 : 8;
+ u32 MAC8 : 8;
+ u32 reserved : 16;
+ } mac_address_41c;
+
+ struct {
+ u32 transmitter_data_byte : 8;
+ u32 ReceiveDataReady : 1;
+ u32 ReceiveByteFrameError: 1;
+ u32 txbuffempty : 1;
+ u32 reserved :21;
+ } ci_600;
+
+ struct {
+ u32 pi_d : 8;
+ u32 pi_ha :20;
+ u32 pi_rw : 1;
+ u32 pi_component_reg : 3;
+ } pi_604;
+
+ struct {
+ u32 serialReset : 1;
+ u32 oncecycle_read : 1;
+ u32 Timer_Read_req : 1;
+ u32 Timer_Load_req : 1;
+ u32 timer_data : 7;
+ u32 unused : 1; /* ??? not mentioned in data book */
+ u32 Timer_addr : 5;
+ u32 reserved : 3;
+ u32 pcmcia_a_mod_pwr_n : 1;
+ u32 pcmcia_b_mod_pwr_n : 1;
+ u32 config_Done_stat : 1;
+ u32 config_Init_stat : 1;
+ u32 config_Prog_n : 1;
+ u32 config_wr_n : 1;
+ u32 config_cs_n : 1;
+ u32 config_cclk : 1;
+ u32 pi_CiMax_IRQ_n : 1;
+ u32 pi_timeout_status : 1;
+ u32 pi_wait_n : 1;
+ u32 pi_busy_n : 1;
+ } pi_608;
+
+ struct {
+ u32 PID :13;
+ u32 key_enable : 1;
+#define fc_key_code_default 0x1
+#define fc_key_code_even 0x2
+#define fc_key_code_odd 0x3
+ u32 key_code : 2;
+ u32 key_array_col : 3;
+ u32 key_array_row : 5;
+ u32 dvb_en : 1; /* 0=TS bypasses the Descrambler */
+ u32 rw_flag : 1;
+ u32 reserved : 6;
+ } dvb_reg_60c;
+
+/* SRAM and Output Destination 0x700 to 0x714 */
+ struct {
+ u32 sram_addr :15;
+ u32 sram_rw : 1; /* 0=write, 1=read */
+ u32 sram_data : 8;
+ u32 sc_xfer_bit : 1;
+ u32 reserved1 : 3;
+ u32 oe_pin_reg : 1;
+ u32 ce_pin_reg : 1;
+ u32 reserved2 : 1;
+ u32 start_sram_ibi : 1;
+ } sram_ctrl_reg_700;
+
+ struct {
+ u32 net_addr_read :16;
+ u32 net_addr_write :16;
+ } net_buf_reg_704;
+
+ struct {
+ u32 cai_read :11;
+ u32 reserved1 : 5;
+ u32 cai_write :11;
+ u32 reserved2 : 6;
+ u32 cai_cnt : 4;
+ } cai_buf_reg_708;
+
+ struct {
+ u32 cao_read :11;
+ u32 reserved1 : 5;
+ u32 cap_write :11;
+ u32 reserved2 : 6;
+ u32 cao_cnt : 4;
+ } cao_buf_reg_70c;
+
+ struct {
+ u32 media_read :11;
+ u32 reserved1 : 5;
+ u32 media_write :11;
+ u32 reserved2 : 6;
+ u32 media_cnt : 4;
+ } media_buf_reg_710;
+
+ struct {
+ u32 NET_Dest : 2;
+ u32 CAI_Dest : 2;
+ u32 CAO_Dest : 2;
+ u32 MEDIA_Dest : 2;
+ u32 net_ovflow_error : 1;
+ u32 media_ovflow_error : 1;
+ u32 cai_ovflow_error : 1;
+ u32 cao_ovflow_error : 1;
+ u32 ctrl_usb_wan : 1;
+ u32 ctrl_sramdma : 1;
+ u32 ctrl_maximumfill : 1;
+ u32 reserved :17;
+ } sram_dest_reg_714;
+
+ struct {
+ u32 net_cnt :12;
+ u32 reserved1 : 4;
+ u32 net_addr_read : 1;
+ u32 reserved2 : 3;
+ u32 net_addr_write : 1;
+ u32 reserved3 :11;
+ } net_buf_reg_718;
+
+ struct {
+ u32 wan_speed_sig : 2;
+ u32 reserved1 : 6;
+ u32 wan_wait_state : 8;
+ u32 sram_chip : 2;
+ u32 sram_memmap : 2;
+ u32 reserved2 : 4;
+ u32 wan_pkt_frame : 4;
+ u32 reserved3 : 4;
+ } wan_ctrl_reg_71c;
+} flexcop_ibi_value;
+
+extern flexcop_ibi_value ibi_zero;
+
+typedef enum {
+ FC_I2C_PORT_DEMOD = 1,
+ FC_I2C_PORT_EEPROM = 2,
+ FC_I2C_PORT_TUNER = 3,
+} flexcop_i2c_port_t;
+
+typedef enum {
+ FC_WRITE = 0,
+ FC_READ = 1,
+} flexcop_access_op_t;
+
+typedef enum {
+ FC_SRAM_DEST_NET = 1,
+ FC_SRAM_DEST_CAI = 2,
+ FC_SRAM_DEST_CAO = 4,
+ FC_SRAM_DEST_MEDIA = 8
+} flexcop_sram_dest_t;
+
+typedef enum {
+ FC_SRAM_DEST_TARGET_WAN_USB = 0,
+ FC_SRAM_DEST_TARGET_DMA1 = 1,
+ FC_SRAM_DEST_TARGET_DMA2 = 2,
+ FC_SRAM_DEST_TARGET_FC3_CA = 3
+} flexcop_sram_dest_target_t;
+
+typedef enum {
+ FC_SRAM_2_32KB = 0, /* 64KB */
+ FC_SRAM_1_32KB = 1, /* 32KB - default fow FCII */
+ FC_SRAM_1_128KB = 2, /* 128KB */
+ FC_SRAM_1_48KB = 3, /* 48KB - default for FCIII */
+} flexcop_sram_type_t;
+
+typedef enum {
+ FC_WAN_SPEED_4MBITS = 0,
+ FC_WAN_SPEED_8MBITS = 1,
+ FC_WAN_SPEED_12MBITS = 2,
+ FC_WAN_SPEED_16MBITS = 3,
+} flexcop_wan_speed_t;
+
+typedef enum {
+ FC_DMA_1 = 1,
+ FC_DMA_2 = 2,
+} flexcop_dma_index_t;
+
+typedef enum {
+ FC_DMA_SUBADDR_0 = 1,
+ FC_DMA_SUBADDR_1 = 2,
+} flexcop_dma_addr_index_t;
+
+/* names of the particular registers */
+typedef enum {
+ dma1_000 = 0x000,
+ dma1_004 = 0x004,
+ dma1_008 = 0x008,
+ dma1_00c = 0x00c,
+ dma2_010 = 0x010,
+ dma2_014 = 0x014,
+ dma2_018 = 0x018,
+ dma2_01c = 0x01c,
+
+ tw_sm_c_100 = 0x100,
+ tw_sm_c_104 = 0x104,
+ tw_sm_c_108 = 0x108,
+ tw_sm_c_10c = 0x10c,
+ tw_sm_c_110 = 0x110,
+
+ lnb_switch_freq_200 = 0x200,
+ misc_204 = 0x204,
+ ctrl_208 = 0x208,
+ irq_20c = 0x20c,
+ sw_reset_210 = 0x210,
+ misc_214 = 0x214,
+ mbox_v8_to_host_218 = 0x218,
+ mbox_host_to_v8_21c = 0x21c,
+
+ pid_filter_300 = 0x300,
+ pid_filter_304 = 0x304,
+ pid_filter_308 = 0x308,
+ pid_filter_30c = 0x30c,
+ index_reg_310 = 0x310,
+ pid_n_reg_314 = 0x314,
+ mac_low_reg_318 = 0x318,
+ mac_high_reg_31c = 0x31c,
+
+ data_tag_400 = 0x400,
+ card_id_408 = 0x408,
+ card_id_40c = 0x40c,
+ mac_address_418 = 0x418,
+ mac_address_41c = 0x41c,
+
+ ci_600 = 0x600,
+ pi_604 = 0x604,
+ pi_608 = 0x608,
+ dvb_reg_60c = 0x60c,
+
+ sram_ctrl_reg_700 = 0x700,
+ net_buf_reg_704 = 0x704,
+ cai_buf_reg_708 = 0x708,
+ cao_buf_reg_70c = 0x70c,
+ media_buf_reg_710 = 0x710,
+ sram_dest_reg_714 = 0x714,
+ net_buf_reg_718 = 0x718,
+ wan_ctrl_reg_71c = 0x71c,
+} flexcop_ibi_register;
+
+#define flexcop_set_ibi_value(reg,attr,val) { \
+ flexcop_ibi_value v = fc->read_ibi_reg(fc,reg); \
+ v.reg.attr = val; \
+ fc->write_ibi_reg(fc,reg,v); \
+}
+
+#endif
diff --git a/drivers/media/dvb/b2c2/flexcop-sram.c b/drivers/media/dvb/b2c2/flexcop-sram.c
new file mode 100644
index 00000000000..01570ec8096
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop-sram.c
@@ -0,0 +1,403 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
+ *
+ * flexcop-sram.c - functions for controlling the SRAM.
+ *
+ * see flexcop.c for copyright information.
+ */
+#include "flexcop.h"
+
+static void flexcop_sram_set_chip (struct flexcop_device *fc, flexcop_sram_type_t type)
+{
+ flexcop_set_ibi_value(wan_ctrl_reg_71c,sram_chip,type);
+}
+
+int flexcop_sram_init(struct flexcop_device *fc)
+{
+ switch (fc->rev) {
+ case FLEXCOP_II:
+ case FLEXCOP_IIB:
+ flexcop_sram_set_chip(fc,FC_SRAM_1_32KB);
+ break;
+ case FLEXCOP_III:
+ flexcop_sram_set_chip(fc,FC_SRAM_1_48KB);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int flexcop_sram_set_dest(struct flexcop_device *fc, flexcop_sram_dest_t dest, flexcop_sram_dest_target_t target)
+{
+ flexcop_ibi_value v;
+
+ v = fc->read_ibi_reg(fc,sram_dest_reg_714);
+
+ if (fc->rev != FLEXCOP_III && target == FC_SRAM_DEST_TARGET_FC3_CA) {
+ err("SRAM destination target to available on FlexCopII(b)\n");
+ return -EINVAL;
+ }
+
+ deb_sram("sram dest: %x target: %x\n",dest, target);
+
+ if (dest & FC_SRAM_DEST_NET)
+ v.sram_dest_reg_714.NET_Dest = target;
+ if (dest & FC_SRAM_DEST_CAI)
+ v.sram_dest_reg_714.CAI_Dest = target;
+ if (dest & FC_SRAM_DEST_CAO)
+ v.sram_dest_reg_714.CAO_Dest = target;
+ if (dest & FC_SRAM_DEST_MEDIA)
+ v.sram_dest_reg_714.MEDIA_Dest = target;
+
+ fc->write_ibi_reg(fc,sram_dest_reg_714,v);
+ udelay(1000); /* TODO delay really necessary */
+
+ return 0;
+}
+EXPORT_SYMBOL(flexcop_sram_set_dest);
+
+void flexcop_wan_set_speed(struct flexcop_device *fc, flexcop_wan_speed_t s)
+{
+ flexcop_set_ibi_value(wan_ctrl_reg_71c,wan_speed_sig,s);
+}
+EXPORT_SYMBOL(flexcop_wan_set_speed);
+
+void flexcop_sram_ctrl(struct flexcop_device *fc, int usb_wan, int sramdma, int maximumfill)
+{
+ flexcop_ibi_value v = fc->read_ibi_reg(fc,sram_dest_reg_714);
+ v.sram_dest_reg_714.ctrl_usb_wan = usb_wan;
+ v.sram_dest_reg_714.ctrl_sramdma = sramdma;
+ v.sram_dest_reg_714.ctrl_maximumfill = maximumfill;
+ fc->write_ibi_reg(fc,sram_dest_reg_714,v);
+}
+EXPORT_SYMBOL(flexcop_sram_ctrl);
+
+#if 0
+static void flexcop_sram_write(struct adapter *adapter, u32 bank, u32 addr, u8 *buf, u32 len)
+{
+ int i, retries;
+ u32 command;
+
+ for (i = 0; i < len; i++) {
+ command = bank | addr | 0x04000000 | (*buf << 0x10);
+
+ retries = 2;
+
+ while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
+ mdelay(1);
+ retries--;
+ };
+
+ if (retries == 0)
+ printk("%s: SRAM timeout\n", __FUNCTION__);
+
+ write_reg_dw(adapter, 0x700, command);
+
+ buf++;
+ addr++;
+ }
+}
+
+static void flex_sram_read(struct adapter *adapter, u32 bank, u32 addr, u8 *buf, u32 len)
+{
+ int i, retries;
+ u32 command, value;
+
+ for (i = 0; i < len; i++) {
+ command = bank | addr | 0x04008000;
+
+ retries = 10000;
+
+ while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
+ mdelay(1);
+ retries--;
+ };
+
+ if (retries == 0)
+ printk("%s: SRAM timeout\n", __FUNCTION__);
+
+ write_reg_dw(adapter, 0x700, command);
+
+ retries = 10000;
+
+ while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {
+ mdelay(1);
+ retries--;
+ };
+
+ if (retries == 0)
+ printk("%s: SRAM timeout\n", __FUNCTION__);
+
+ value = read_reg_dw(adapter, 0x700) >> 0x10;
+
+ *buf = (value & 0xff);
+
+ addr++;
+ buf++;
+ }
+}
+
+static void sram_write_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len)
+{
+ u32 bank;
+
+ bank = 0;
+
+ if (adapter->dw_sram_type == 0x20000) {
+ bank = (addr & 0x18000) << 0x0d;
+ }
+
+ if (adapter->dw_sram_type == 0x00000) {
+ if ((addr >> 0x0f) == 0)
+ bank = 0x20000000;
+ else
+ bank = 0x10000000;
+ }
+
+ flex_sram_write(adapter, bank, addr & 0x7fff, buf, len);
+}
+
+static void sram_read_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len)
+{
+ u32 bank;
+
+ bank = 0;
+
+ if (adapter->dw_sram_type == 0x20000) {
+ bank = (addr & 0x18000) << 0x0d;
+ }
+
+ if (adapter->dw_sram_type == 0x00000) {
+ if ((addr >> 0x0f) == 0)
+ bank = 0x20000000;
+ else
+ bank = 0x10000000;
+ }
+
+ flex_sram_read(adapter, bank, addr & 0x7fff, buf, len);
+}
+
+static void sram_read(struct adapter *adapter, u32 addr, u8 *buf, u32 len)
+{
+ u32 length;
+
+ while (len != 0) {
+ length = len;
+
+ // check if the address range belongs to the same
+ // 32K memory chip. If not, the data is read from
+ // one chip at a time.
+ if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) {
+ length = (((addr >> 0x0f) + 1) << 0x0f) - addr;
+ }
+
+ sram_read_chunk(adapter, addr, buf, length);
+
+ addr = addr + length;
+ buf = buf + length;
+ len = len - length;
+ }
+}
+
+static void sram_write(struct adapter *adapter, u32 addr, u8 *buf, u32 len)
+{
+ u32 length;
+
+ while (len != 0) {
+ length = len;
+
+ // check if the address range belongs to the same
+ // 32K memory chip. If not, the data is written to
+ // one chip at a time.
+ if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) {
+ length = (((addr >> 0x0f) + 1) << 0x0f) - addr;
+ }
+
+ sram_write_chunk(adapter, addr, buf, length);
+
+ addr = addr + length;
+ buf = buf + length;
+ len = len - length;
+ }
+}
+
+static void sram_set_size(struct adapter *adapter, u32 mask)
+{
+ write_reg_dw(adapter, 0x71c, (mask | (~0x30000 & read_reg_dw(adapter, 0x71c))));
+}
+
+static void sram_init(struct adapter *adapter)
+{
+ u32 tmp;
+
+ tmp = read_reg_dw(adapter, 0x71c);
+
+ write_reg_dw(adapter, 0x71c, 1);
+
+ if (read_reg_dw(adapter, 0x71c) != 0) {
+ write_reg_dw(adapter, 0x71c, tmp);
+
+ adapter->dw_sram_type = tmp & 0x30000;
+
+ ddprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type);
+
+ } else {
+
+ adapter->dw_sram_type = 0x10000;
+
+ ddprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type);
+ }
+
+ /* return value is never used? */
+/* return adapter->dw_sram_type; */
+}
+
+static int sram_test_location(struct adapter *adapter, u32 mask, u32 addr)
+{
+ u8 tmp1, tmp2;
+
+ dprintk("%s: mask = %x, addr = %x\n", __FUNCTION__, mask, addr);
+
+ sram_set_size(adapter, mask);
+ sram_init(adapter);
+
+ tmp2 = 0xa5;
+ tmp1 = 0x4f;
+
+ sram_write(adapter, addr, &tmp2, 1);
+ sram_write(adapter, addr + 4, &tmp1, 1);
+
+ tmp2 = 0;
+
+ mdelay(20);
+
+ sram_read(adapter, addr, &tmp2, 1);
+ sram_read(adapter, addr, &tmp2, 1);
+
+ dprintk("%s: wrote 0xa5, read 0x%2x\n", __FUNCTION__, tmp2);
+
+ if (tmp2 != 0xa5)
+ return 0;
+
+ tmp2 = 0x5a;
+ tmp1 = 0xf4;
+
+ sram_write(adapter, addr, &tmp2, 1);
+ sram_write(adapter, addr + 4, &tmp1, 1);
+
+ tmp2 = 0;
+
+ mdelay(20);
+
+ sram_read(adapter, addr, &tmp2, 1);
+ sram_read(adapter, addr, &tmp2, 1);
+
+ dprintk("%s: wrote 0x5a, read 0x%2x\n", __FUNCTION__, tmp2);
+
+ if (tmp2 != 0x5a)
+ return 0;
+
+ return 1;
+}
+
+static u32 sram_length(struct adapter *adapter)
+{
+ if (adapter->dw_sram_type == 0x10000)
+ return 32768; // 32K
+ if (adapter->dw_sram_type == 0x00000)
+ return 65536; // 64K
+ if (adapter->dw_sram_type == 0x20000)
+ return 131072; // 128K
+
+ return 32768; // 32K
+}
+
+/* FlexcopII can work with 32K, 64K or 128K of external SRAM memory.
+ - for 128K there are 4x32K chips at bank 0,1,2,3.
+ - for 64K there are 2x32K chips at bank 1,2.
+ - for 32K there is one 32K chip at bank 0.
+
+ FlexCop works only with one bank at a time. The bank is selected
+ by bits 28-29 of the 0x700 register.
+
+ bank 0 covers addresses 0x00000-0x07fff
+ bank 1 covers addresses 0x08000-0x0ffff
+ bank 2 covers addresses 0x10000-0x17fff
+ bank 3 covers addresses 0x18000-0x1ffff
+*/
+
+static int flexcop_sram_detect(struct flexcop_device *fc)
+{
+ flexcop_ibi_value r208,r71c_0,vr71c_1;
+
+ r208 = fc->read_ibi_reg(fc, ctrl_208);
+ fc->write_ibi_reg(fc, ctrl_208, ibi_zero);
+
+ r71c_0 = fc->read_ibi_reg(fc, wan_ctrl_reg_71c);
+
+ write_reg_dw(adapter, 0x71c, 1);
+
+ tmp3 = read_reg_dw(adapter, 0x71c);
+
+ dprintk("%s: tmp3 = %x\n", __FUNCTION__, tmp3);
+
+ write_reg_dw(adapter, 0x71c, tmp2);
+
+ // check for internal SRAM ???
+ tmp3--;
+ if (tmp3 != 0) {
+ sram_set_size(adapter, 0x10000);
+ sram_init(adapter);
+ write_reg_dw(adapter, 0x208, tmp);
+
+ dprintk("%s: sram size = 32K\n", __FUNCTION__);
+
+ return 32;
+ }
+
+ if (sram_test_location(adapter, 0x20000, 0x18000) != 0) {
+ sram_set_size(adapter, 0x20000);
+ sram_init(adapter);
+ write_reg_dw(adapter, 0x208, tmp);
+
+ dprintk("%s: sram size = 128K\n", __FUNCTION__);
+
+ return 128;
+ }
+
+ if (sram_test_location(adapter, 0x00000, 0x10000) != 0) {
+ sram_set_size(adapter, 0x00000);
+ sram_init(adapter);
+ write_reg_dw(adapter, 0x208, tmp);
+
+ dprintk("%s: sram size = 64K\n", __FUNCTION__);
+
+ return 64;
+ }
+
+ if (sram_test_location(adapter, 0x10000, 0x00000) != 0) {
+ sram_set_size(adapter, 0x10000);
+ sram_init(adapter);
+ write_reg_dw(adapter, 0x208, tmp);
+
+ dprintk("%s: sram size = 32K\n", __FUNCTION__);
+
+ return 32;
+ }
+
+ sram_set_size(adapter, 0x10000);
+ sram_init(adapter);
+ write_reg_dw(adapter, 0x208, tmp);
+
+ dprintk("%s: SRAM detection failed. Set to 32K \n", __FUNCTION__);
+
+ return 0;
+}
+
+static void sll_detect_sram_size(struct adapter *adapter)
+{
+ sram_detect_for_flex2(adapter);
+}
+
+#endif
diff --git a/drivers/media/dvb/b2c2/flexcop-usb.c b/drivers/media/dvb/b2c2/flexcop-usb.c
new file mode 100644
index 00000000000..0113449abd1
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop-usb.c
@@ -0,0 +1,577 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
+ *
+ * flexcop-usb.c - covers the USB part.
+ *
+ * see flexcop.c for copyright information.
+ */
+
+#define FC_LOG_PREFIX "flexcop_usb"
+#include "flexcop-usb.h"
+#include "flexcop-common.h"
+
+/* Version information */
+#define DRIVER_VERSION "0.1"
+#define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV USB Driver"
+#define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de>"
+
+/* debug */
+#ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG
+#define dprintk(level,args...) \
+ do { if ((debug & level)) { printk(args); } } while (0)
+#define debug_dump(b,l,method) {\
+ int i; \
+ for (i = 0; i < l; i++) method("%02x ", b[i]); \
+ method("\n");\
+}
+
+#define DEBSTATUS ""
+#else
+#define dprintk(level,args...)
+#define debug_dump(b,l,method)
+#define DEBSTATUS " (debugging is not enabled)"
+#endif
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,ts=2,ctrl=4,i2c=8,v8mem=16 (or-able))." DEBSTATUS);
+#undef DEBSTATUS
+
+#define deb_info(args...) dprintk(0x01,args)
+#define deb_ts(args...) dprintk(0x02,args)
+#define deb_ctrl(args...) dprintk(0x04,args)
+#define deb_i2c(args...) dprintk(0x08,args)
+#define deb_v8(args...) dprintk(0x10,args)
+
+/* JLP 111700: we will include the 1 bit gap between the upper and lower 3 bits
+ * in the IBI address, to make the V8 code simpler.
+ * PCI ADDRESS FORMAT: 0x71C -> 0000 0111 0001 1100 (these are the six bits used)
+ * in general: 0000 0HHH 000L LL00
+ * IBI ADDRESS FORMAT: RHHH BLLL
+ *
+ * where R is the read(1)/write(0) bit, B is the busy bit
+ * and HHH and LLL are the two sets of three bits from the PCI address.
+ */
+#define B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(usPCI) (u8) (((usPCI >> 2) & 0x07) + ((usPCI >> 4) & 0x70))
+#define B2C2_FLEX_INTERNALADDR_TO_PCIOFFSET(ucAddr) (u16) (((ucAddr & 0x07) << 2) + ((ucAddr & 0x70) << 4))
+
+/*
+ * DKT 020228
+ * - forget about this VENDOR_BUFFER_SIZE, read and write register
+ * deal with DWORD or 4 bytes, that should be should from now on
+ * - from now on, we don't support anything older than firm 1.00
+ * I eliminated the write register as a 2 trip of writing hi word and lo word
+ * and force this to write only 4 bytes at a time.
+ * NOTE: this should work with all the firmware from 1.00 and newer
+ */
+static int flexcop_usb_readwrite_dw(struct flexcop_device *fc, u16 wRegOffsPCI, u32 *val, u8 read)
+{
+ struct flexcop_usb *fc_usb = fc->bus_specific;
+ u8 request = read ? B2C2_USB_READ_REG : B2C2_USB_WRITE_REG;
+ u8 request_type = (read ? USB_DIR_IN : USB_DIR_OUT) | USB_TYPE_VENDOR;
+ u8 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) | (read ? 0x80 : 0);
+
+ int len = usb_control_msg(fc_usb->udev,
+ read ? B2C2_USB_CTRL_PIPE_IN : B2C2_USB_CTRL_PIPE_OUT,
+ request,
+ request_type, /* 0xc0 read or 0x40 write*/
+ wAddress,
+ 0,
+ val,
+ sizeof(u32),
+ B2C2_WAIT_FOR_OPERATION_RDW * HZ);
+
+ if (len != sizeof(u32)) {
+ err("error while %s dword from %d (%d).",read ? "reading" : "writing",
+ wAddress,wRegOffsPCI);
+ return -EIO;
+ }
+ return 0;
+}
+
+/*
+ * DKT 010817 - add support for V8 memory read/write and flash update
+ */
+static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb,
+ flexcop_usb_request_t req, u8 page, u16 wAddress,
+ u8 *pbBuffer,u32 buflen)
+{
+// u8 dwRequestType;
+ u8 request_type = USB_TYPE_VENDOR;
+ u16 wIndex;
+ int nWaitTime,pipe,len;
+
+ wIndex = page << 8;
+
+ switch (req) {
+ case B2C2_USB_READ_V8_MEM:
+ nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ;
+ request_type |= USB_DIR_IN;
+// dwRequestType = (u8) RTYPE_READ_V8_MEMORY;
+ pipe = B2C2_USB_CTRL_PIPE_IN;
+ break;
+ case B2C2_USB_WRITE_V8_MEM:
+ wIndex |= pbBuffer[0];
+ request_type |= USB_DIR_OUT;
+ nWaitTime = B2C2_WAIT_FOR_OPERATION_V8WRITE;
+// dwRequestType = (u8) RTYPE_WRITE_V8_MEMORY;
+ pipe = B2C2_USB_CTRL_PIPE_OUT;
+ break;
+ case B2C2_USB_FLASH_BLOCK:
+ request_type |= USB_DIR_OUT;
+ nWaitTime = B2C2_WAIT_FOR_OPERATION_V8FLASH;
+// dwRequestType = (u8) RTYPE_WRITE_V8_FLASH;
+ pipe = B2C2_USB_CTRL_PIPE_OUT;
+ break;
+ default:
+ deb_info("unsupported request for v8_mem_req %x.\n",req);
+ return -EINVAL;
+ }
+ deb_v8("v8mem: %02x %02x %04x %04x, len: %d\n",request_type,req,
+ wAddress,wIndex,buflen);
+
+ len = usb_control_msg(fc_usb->udev,pipe,
+ req,
+ request_type,
+ wAddress,
+ wIndex,
+ pbBuffer,
+ buflen,
+ nWaitTime * HZ);
+
+ debug_dump(pbBuffer,len,deb_v8);
+
+ return len == buflen ? 0 : -EIO;
+}
+
+#define bytes_left_to_read_on_page(paddr,buflen) \
+ ((V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK)) > buflen \
+ ? buflen : (V8_MEMORY_PAGE_SIZE - (paddr & V8_MEMORY_PAGE_MASK)))
+
+static int flexcop_usb_memory_req(struct flexcop_usb *fc_usb,flexcop_usb_request_t req,
+ flexcop_usb_mem_page_t page_start, u32 addr, int extended, u8 *buf, u32 len)
+{
+ int i,ret = 0;
+ u16 wMax;
+ u32 pagechunk = 0;
+
+ switch(req) {
+ case B2C2_USB_READ_V8_MEM: wMax = USB_MEM_READ_MAX; break;
+ case B2C2_USB_WRITE_V8_MEM: wMax = USB_MEM_WRITE_MAX; break;
+ case B2C2_USB_FLASH_BLOCK: wMax = USB_FLASH_MAX; break;
+ default:
+ return -EINVAL;
+ break;
+ }
+ for (i = 0; i < len;) {
+ pagechunk = wMax < bytes_left_to_read_on_page(addr,len) ? wMax : bytes_left_to_read_on_page(addr,len);
+ deb_info("%x\n",(addr & V8_MEMORY_PAGE_MASK) | (V8_MEMORY_EXTENDED*extended));
+ if ((ret = flexcop_usb_v8_memory_req(fc_usb,req,
+ page_start + (addr / V8_MEMORY_PAGE_SIZE), /* actual page */
+ (addr & V8_MEMORY_PAGE_MASK) | (V8_MEMORY_EXTENDED*extended),
+ &buf[i],pagechunk)) < 0)
+ return ret;
+
+ addr += pagechunk;
+ len -= pagechunk;
+ }
+ return 0;
+}
+
+static int flexcop_usb_get_mac_addr(struct flexcop_device *fc, int extended)
+{
+ return flexcop_usb_memory_req(fc->bus_specific,B2C2_USB_READ_V8_MEM,
+ V8_MEMORY_PAGE_FLASH,0x1f010,1,fc->dvb_adapter.proposed_mac,6);
+}
+
+#if 0
+static int flexcop_usb_utility_req(struct flexcop_usb *fc_usb, int set,
+ flexcop_usb_utility_function_t func, u8 extra, u16 wIndex,
+ u16 buflen, u8 *pvBuffer)
+{
+ u16 wValue;
+ u8 request_type = (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR;
+// u8 dwRequestType = (u8) RTYPE_GENERIC,
+ int nWaitTime = 2,
+ pipe = set ? B2C2_USB_CTRL_PIPE_OUT : B2C2_USB_CTRL_PIPE_IN,
+ len;
+
+ wValue = (func << 8) | extra;
+
+ len = usb_control_msg(fc_usb->udev,pipe,
+ B2C2_USB_UTILITY,
+ request_type,
+ wValue,
+ wIndex,
+ pvBuffer,
+ buflen,
+ nWaitTime * HZ);
+ return len == buflen ? 0 : -EIO;
+}
+#endif
+
+/* usb i2c stuff */
+static int flexcop_usb_i2c_req(struct flexcop_usb *fc_usb,
+ flexcop_usb_request_t req, flexcop_usb_i2c_function_t func,
+ flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u8 buflen)
+{
+ u16 wValue, wIndex;
+ int nWaitTime,pipe,len;
+// u8 dwRequestType;
+ u8 request_type = USB_TYPE_VENDOR;
+
+ switch (func) {
+ case USB_FUNC_I2C_WRITE:
+ case USB_FUNC_I2C_MULTIWRITE:
+ case USB_FUNC_I2C_REPEATWRITE:
+ /* DKT 020208 - add this to support special case of DiSEqC */
+ case USB_FUNC_I2C_CHECKWRITE:
+ pipe = B2C2_USB_CTRL_PIPE_OUT;
+ nWaitTime = 2;
+// dwRequestType = (u8) RTYPE_GENERIC;
+ request_type |= USB_DIR_OUT;
+ break;
+ case USB_FUNC_I2C_READ:
+ case USB_FUNC_I2C_REPEATREAD:
+ pipe = B2C2_USB_CTRL_PIPE_IN;
+ nWaitTime = 2;
+// dwRequestType = (u8) RTYPE_GENERIC;
+ request_type |= USB_DIR_IN;
+ break;
+ default:
+ deb_info("unsupported function for i2c_req %x\n",func);
+ return -EINVAL;
+ }
+ wValue = (func << 8 ) | (port << 4);
+ wIndex = (chipaddr << 8 ) | addr;
+
+ deb_i2c("i2c %2d: %02x %02x %02x %02x %02x %02x\n",func,request_type,req,
+ ((wValue && 0xff) << 8),wValue >> 8,((wIndex && 0xff) << 8),wIndex >> 8);
+
+ len = usb_control_msg(fc_usb->udev,pipe,
+ req,
+ request_type,
+ wValue,
+ wIndex,
+ buf,
+ buflen,
+ nWaitTime * HZ);
+
+ return len == buflen ? 0 : -EREMOTEIO;
+}
+
+/* actual bus specific access functions, make sure prototype are/will be equal to pci */
+static flexcop_ibi_value flexcop_usb_read_ibi_reg(struct flexcop_device *fc, flexcop_ibi_register reg)
+{
+ flexcop_ibi_value val;
+ val.raw = 0;
+ flexcop_usb_readwrite_dw(fc,reg, &val.raw, 1);
+ return val;
+}
+
+static int flexcop_usb_write_ibi_reg(struct flexcop_device *fc, flexcop_ibi_register reg, flexcop_ibi_value val)
+{
+ return flexcop_usb_readwrite_dw(fc,reg, &val.raw, 0);
+}
+
+static int flexcop_usb_i2c_request(struct flexcop_device *fc, flexcop_access_op_t op,
+ flexcop_i2c_port_t port, u8 chipaddr, u8 addr, u8 *buf, u16 len)
+{
+ if (op == FC_READ)
+ return flexcop_usb_i2c_req(fc->bus_specific,B2C2_USB_I2C_REQUEST,USB_FUNC_I2C_READ,port,chipaddr,addr,buf,len);
+ else
+ return flexcop_usb_i2c_req(fc->bus_specific,B2C2_USB_I2C_REQUEST,USB_FUNC_I2C_WRITE,port,chipaddr,addr,buf,len);
+}
+
+static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb, u8 *buffer, int buffer_length)
+{
+ u8 *b;
+ int l;
+
+ deb_ts("tmp_buffer_length=%d, buffer_length=%d\n", fc_usb->tmp_buffer_length, buffer_length);
+
+ if (fc_usb->tmp_buffer_length > 0) {
+ memcpy(fc_usb->tmp_buffer+fc_usb->tmp_buffer_length, buffer, buffer_length);
+ fc_usb->tmp_buffer_length += buffer_length;
+ b = fc_usb->tmp_buffer;
+ l = fc_usb->tmp_buffer_length;
+ } else {
+ b=buffer;
+ l=buffer_length;
+ }
+
+ while (l >= 190) {
+ if (*b == 0xff)
+ switch (*(b+1) & 0x03) {
+ case 0x01: /* media packet */
+ if ( *(b+2) == 0x47 )
+ flexcop_pass_dmx_packets(fc_usb->fc_dev, b+2, 1);
+ else
+ deb_ts("not ts packet %02x %02x %02x %02x \n", *(b+2), *(b+3), *(b+4), *(b+5) );
+
+ b += 190;
+ l -= 190;
+ break;
+ default:
+ deb_ts("wrong packet type\n");
+ l = 0;
+ break;
+ }
+ else {
+ deb_ts("wrong header\n");
+ l = 0;
+ }
+ }
+
+ if (l>0)
+ memcpy(fc_usb->tmp_buffer, b, l);
+ fc_usb->tmp_buffer_length = l;
+}
+
+static void flexcop_usb_urb_complete(struct urb *urb, struct pt_regs *ptregs)
+{
+ struct flexcop_usb *fc_usb = urb->context;
+ int i;
+
+ if (urb->actual_length > 0)
+ deb_ts("urb completed, bufsize: %d actlen; %d\n",urb->transfer_buffer_length, urb->actual_length);
+
+ for (i = 0; i < urb->number_of_packets; i++) {
+ if (urb->iso_frame_desc[i].status < 0) {
+ err("iso frame descriptor %d has an error: %d\n",i,urb->iso_frame_desc[i].status);
+ } else
+ if (urb->iso_frame_desc[i].actual_length > 0) {
+ deb_ts("passed %d bytes to the demux\n",urb->iso_frame_desc[i].actual_length);
+
+ flexcop_usb_process_frame(fc_usb,
+ urb->transfer_buffer + urb->iso_frame_desc[i].offset,
+ urb->iso_frame_desc[i].actual_length);
+ }
+ urb->iso_frame_desc[i].status = 0;
+ urb->iso_frame_desc[i].actual_length = 0;
+ }
+
+ usb_submit_urb(urb,GFP_ATOMIC);
+}
+
+static int flexcop_usb_stream_control(struct flexcop_device *fc, int onoff)
+{
+ /* submit/kill iso packets */
+ return 0;
+}
+
+static void flexcop_usb_transfer_exit(struct flexcop_usb *fc_usb)
+{
+ int i;
+ for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++)
+ if (fc_usb->iso_urb[i] != NULL) {
+ deb_ts("unlinking/killing urb no. %d\n",i);
+ usb_kill_urb(fc_usb->iso_urb[i]);
+ usb_free_urb(fc_usb->iso_urb[i]);
+ }
+
+ if (fc_usb->iso_buffer != NULL)
+ pci_free_consistent(NULL,fc_usb->buffer_size, fc_usb->iso_buffer, fc_usb->dma_addr);
+}
+
+static int flexcop_usb_transfer_init(struct flexcop_usb *fc_usb)
+{
+ u16 frame_size = fc_usb->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize;
+ int bufsize = B2C2_USB_NUM_ISO_URB * B2C2_USB_FRAMES_PER_ISO * frame_size,i,j,ret;
+ int buffer_offset = 0;
+
+ deb_ts("creating %d iso-urbs with %d frames each of %d bytes size = %d.\n",
+ B2C2_USB_NUM_ISO_URB, B2C2_USB_FRAMES_PER_ISO, frame_size,bufsize);
+
+ fc_usb->iso_buffer = pci_alloc_consistent(NULL,bufsize,&fc_usb->dma_addr);
+ if (fc_usb->iso_buffer == NULL)
+ return -ENOMEM;
+ memset(fc_usb->iso_buffer, 0, bufsize);
+ fc_usb->buffer_size = bufsize;
+
+ /* creating iso urbs */
+ for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++)
+ if (!(fc_usb->iso_urb[i] = usb_alloc_urb(B2C2_USB_FRAMES_PER_ISO,GFP_ATOMIC))) {
+ ret = -ENOMEM;
+ goto urb_error;
+ }
+ /* initialising and submitting iso urbs */
+ for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) {
+ int frame_offset = 0;
+ struct urb *urb = fc_usb->iso_urb[i];
+ deb_ts("initializing and submitting urb no. %d (buf_offset: %d).\n",i,buffer_offset);
+
+ urb->dev = fc_usb->udev;
+ urb->context = fc_usb;
+ urb->complete = flexcop_usb_urb_complete;
+ urb->pipe = B2C2_USB_DATA_PIPE;
+ urb->transfer_flags = URB_ISO_ASAP;
+ urb->interval = 1;
+ urb->number_of_packets = B2C2_USB_FRAMES_PER_ISO;
+ urb->transfer_buffer_length = frame_size * B2C2_USB_FRAMES_PER_ISO;
+ urb->transfer_buffer = fc_usb->iso_buffer + buffer_offset;
+
+ buffer_offset += frame_size * B2C2_USB_FRAMES_PER_ISO;
+ for (j = 0; j < B2C2_USB_FRAMES_PER_ISO; j++) {
+ deb_ts("urb no: %d, frame: %d, frame_offset: %d\n",i,j,frame_offset);
+ urb->iso_frame_desc[j].offset = frame_offset;
+ urb->iso_frame_desc[j].length = frame_size;
+ frame_offset += frame_size;
+ }
+
+ if ((ret = usb_submit_urb(fc_usb->iso_urb[i],GFP_ATOMIC))) {
+ err("submitting urb %d failed with %d.",i,ret);
+ goto urb_error;
+ }
+ deb_ts("submitted urb no. %d.\n",i);
+ }
+
+/* SRAM */
+
+ flexcop_sram_set_dest(fc_usb->fc_dev,FC_SRAM_DEST_MEDIA | FC_SRAM_DEST_NET |
+ FC_SRAM_DEST_CAO | FC_SRAM_DEST_CAI, FC_SRAM_DEST_TARGET_WAN_USB);
+ flexcop_wan_set_speed(fc_usb->fc_dev,FC_WAN_SPEED_8MBITS);
+ flexcop_sram_ctrl(fc_usb->fc_dev,1,1,1);
+
+ ret = 0;
+ goto success;
+urb_error:
+ flexcop_usb_transfer_exit(fc_usb);
+success:
+ return ret;
+}
+
+static int flexcop_usb_init(struct flexcop_usb *fc_usb)
+{
+ /* use the alternate setting with the larges buffer */
+ usb_set_interface(fc_usb->udev,0,1);
+ switch (fc_usb->udev->speed) {
+ case USB_SPEED_LOW:
+ err("cannot handle USB speed because it is to sLOW.");
+ return -ENODEV;
+ break;
+ case USB_SPEED_FULL:
+ info("running at FULL speed.");
+ break;
+ case USB_SPEED_HIGH:
+ info("running at HIGH speed.");
+ break;
+ case USB_SPEED_UNKNOWN: /* fall through */
+ default:
+ err("cannot handle USB speed because it is unkown.");
+ return -ENODEV;
+ }
+ usb_set_intfdata(fc_usb->uintf, fc_usb);
+ return 0;
+}
+
+static void flexcop_usb_exit(struct flexcop_usb *fc_usb)
+{
+ usb_set_intfdata(fc_usb->uintf, NULL);
+}
+
+static int flexcop_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct flexcop_usb *fc_usb = NULL;
+ struct flexcop_device *fc = NULL;
+ int ret;
+
+ if ((fc = flexcop_device_kmalloc(sizeof(struct flexcop_usb))) == NULL) {
+ err("out of memory\n");
+ return -ENOMEM;
+ }
+
+/* general flexcop init */
+ fc_usb = fc->bus_specific;
+ fc_usb->fc_dev = fc;
+
+ fc->read_ibi_reg = flexcop_usb_read_ibi_reg;
+ fc->write_ibi_reg = flexcop_usb_write_ibi_reg;
+ fc->i2c_request = flexcop_usb_i2c_request;
+ fc->get_mac_addr = flexcop_usb_get_mac_addr;
+
+ fc->stream_control = flexcop_usb_stream_control;
+
+ fc->pid_filtering = 1;
+ fc->bus_type = FC_USB;
+
+ fc->dev = &udev->dev;
+ fc->owner = THIS_MODULE;
+
+/* bus specific part */
+ fc_usb->udev = udev;
+ fc_usb->uintf = intf;
+ if ((ret = flexcop_usb_init(fc_usb)) != 0)
+ goto err_kfree;
+
+/* init flexcop */
+ if ((ret = flexcop_device_initialize(fc)) != 0)
+ goto err_usb_exit;
+
+/* xfer init */
+ if ((ret = flexcop_usb_transfer_init(fc_usb)) != 0)
+ goto err_fc_exit;
+
+ info("%s successfully initialized and connected.",DRIVER_NAME);
+ ret = 0;
+ goto success;
+err_fc_exit:
+ flexcop_device_exit(fc);
+err_usb_exit:
+ flexcop_usb_exit(fc_usb);
+err_kfree:
+ flexcop_device_kfree(fc);
+success:
+ return ret;
+}
+
+static void flexcop_usb_disconnect(struct usb_interface *intf)
+{
+ struct flexcop_usb *fc_usb = usb_get_intfdata(intf);
+ flexcop_usb_transfer_exit(fc_usb);
+ flexcop_device_exit(fc_usb->fc_dev);
+ flexcop_usb_exit(fc_usb);
+ flexcop_device_kfree(fc_usb->fc_dev);
+ info("%s successfully deinitialized and disconnected.",DRIVER_NAME);
+}
+
+static struct usb_device_id flexcop_usb_table [] = {
+ { USB_DEVICE(0x0af7, 0x0101) },
+ { }
+};
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver flexcop_usb_driver = {
+ .owner = THIS_MODULE,
+ .name = "Technisat/B2C2 FlexCop II/IIb/III USB",
+ .probe = flexcop_usb_probe,
+ .disconnect = flexcop_usb_disconnect,
+ .id_table = flexcop_usb_table,
+};
+
+/* module stuff */
+static int __init flexcop_usb_module_init(void)
+{
+ int result;
+ if ((result = usb_register(&flexcop_usb_driver))) {
+ err("usb_register failed. (%d)",result);
+ return result;
+ }
+
+ return 0;
+}
+
+static void __exit flexcop_usb_module_exit(void)
+{
+ /* deregister this driver from the USB subsystem */
+ usb_deregister(&flexcop_usb_driver);
+}
+
+module_init(flexcop_usb_module_init);
+module_exit(flexcop_usb_module_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_NAME);
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/b2c2/flexcop-usb.h b/drivers/media/dvb/b2c2/flexcop-usb.h
new file mode 100644
index 00000000000..630e647a2ca
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop-usb.h
@@ -0,0 +1,119 @@
+#ifndef __FLEXCOP_USB_H_INCLUDED__
+#define __FLEXCOP_USB_H_INCLUDED__
+
+#include <linux/usb.h>
+
+/* transfer parameters */
+#define B2C2_USB_FRAMES_PER_ISO 4
+#define B2C2_USB_NUM_ISO_URB 4
+
+#define B2C2_USB_CTRL_PIPE_IN usb_rcvctrlpipe(fc_usb->udev,0)
+#define B2C2_USB_CTRL_PIPE_OUT usb_sndctrlpipe(fc_usb->udev,0)
+#define B2C2_USB_DATA_PIPE usb_rcvisocpipe(fc_usb->udev,0x81)
+
+struct flexcop_usb {
+ struct usb_device *udev;
+ struct usb_interface *uintf;
+
+ u8 *iso_buffer;
+ int buffer_size;
+ dma_addr_t dma_addr;
+ struct urb *iso_urb[B2C2_USB_NUM_ISO_URB];
+
+ struct flexcop_device *fc_dev;
+
+ u8 tmp_buffer[1023+190];
+ int tmp_buffer_length;
+};
+
+#if 0
+/* request types TODO What is its use?*/
+typedef enum {
+
+/* something is wrong with this part
+ RTYPE_READ_DW = (1 << 6),
+ RTYPE_WRITE_DW_1 = (3 << 6),
+ RTYPE_READ_V8_MEMORY = (6 << 6),
+ RTYPE_WRITE_V8_MEMORY = (7 << 6),
+ RTYPE_WRITE_V8_FLASH = (8 << 6),
+ RTYPE_GENERIC = (9 << 6),
+*/
+} flexcop_usb_request_type_t;
+#endif
+
+/* request */
+typedef enum {
+ B2C2_USB_WRITE_V8_MEM = 0x04,
+ B2C2_USB_READ_V8_MEM = 0x05,
+ B2C2_USB_READ_REG = 0x08,
+ B2C2_USB_WRITE_REG = 0x0A,
+/* B2C2_USB_WRITEREGLO = 0x0A, */
+ B2C2_USB_WRITEREGHI = 0x0B,
+ B2C2_USB_FLASH_BLOCK = 0x10,
+ B2C2_USB_I2C_REQUEST = 0x11,
+ B2C2_USB_UTILITY = 0x12,
+} flexcop_usb_request_t;
+
+/* function definition for I2C_REQUEST */
+typedef enum {
+ USB_FUNC_I2C_WRITE = 0x01,
+ USB_FUNC_I2C_MULTIWRITE = 0x02,
+ USB_FUNC_I2C_READ = 0x03,
+ USB_FUNC_I2C_REPEATWRITE = 0x04,
+ USB_FUNC_GET_DESCRIPTOR = 0x05,
+ USB_FUNC_I2C_REPEATREAD = 0x06,
+/* DKT 020208 - add this to support special case of DiSEqC */
+ USB_FUNC_I2C_CHECKWRITE = 0x07,
+ USB_FUNC_I2C_CHECKRESULT = 0x08,
+} flexcop_usb_i2c_function_t;
+
+/*
+ * function definition for UTILITY request 0x12
+ * DKT 020304 - new utility function
+ */
+typedef enum {
+ UTILITY_SET_FILTER = 0x01,
+ UTILITY_DATA_ENABLE = 0x02,
+ UTILITY_FLEX_MULTIWRITE = 0x03,
+ UTILITY_SET_BUFFER_SIZE = 0x04,
+ UTILITY_FLEX_OPERATOR = 0x05,
+ UTILITY_FLEX_RESET300_START = 0x06,
+ UTILITY_FLEX_RESET300_STOP = 0x07,
+ UTILITY_FLEX_RESET300 = 0x08,
+ UTILITY_SET_ISO_SIZE = 0x09,
+ UTILITY_DATA_RESET = 0x0A,
+ UTILITY_GET_DATA_STATUS = 0x10,
+ UTILITY_GET_V8_REG = 0x11,
+/* DKT 020326 - add function for v1.14 */
+ UTILITY_SRAM_WRITE = 0x12,
+ UTILITY_SRAM_READ = 0x13,
+ UTILITY_SRAM_TESTFILL = 0x14,
+ UTILITY_SRAM_TESTSET = 0x15,
+ UTILITY_SRAM_TESTVERIFY = 0x16,
+} flexcop_usb_utility_function_t;
+
+#define B2C2_WAIT_FOR_OPERATION_RW 1*HZ /* 1 s */
+#define B2C2_WAIT_FOR_OPERATION_RDW 3*HZ /* 3 s */
+#define B2C2_WAIT_FOR_OPERATION_WDW 1*HZ /* 1 s */
+
+#define B2C2_WAIT_FOR_OPERATION_V8READ 3*HZ /* 3 s */
+#define B2C2_WAIT_FOR_OPERATION_V8WRITE 3*HZ /* 3 s */
+#define B2C2_WAIT_FOR_OPERATION_V8FLASH 3*HZ /* 3 s */
+
+typedef enum {
+ V8_MEMORY_PAGE_DVB_CI = 0x20,
+ V8_MEMORY_PAGE_DVB_DS = 0x40,
+ V8_MEMORY_PAGE_MULTI2 = 0x60,
+ V8_MEMORY_PAGE_FLASH = 0x80
+} flexcop_usb_mem_page_t;
+
+#define V8_MEMORY_EXTENDED (1 << 15)
+
+#define USB_MEM_READ_MAX 32
+#define USB_MEM_WRITE_MAX 1
+#define USB_FLASH_MAX 8
+
+#define V8_MEMORY_PAGE_SIZE 0x8000 // 32K
+#define V8_MEMORY_PAGE_MASK 0x7FFF
+
+#endif
diff --git a/drivers/media/dvb/b2c2/flexcop.c b/drivers/media/dvb/b2c2/flexcop.c
new file mode 100644
index 00000000000..8b5d14dd36e
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop.c
@@ -0,0 +1,286 @@
+/*
+ * flexcop.c - driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher <patrick.boettcher@desy.de>
+ *
+ * based on the skystar2-driver
+ * Copyright (C) 2003 Vadim Catana, skystar@moldova.cc
+ *
+ * Acknowledgements:
+ * John Jurrius from BBTI, Inc. for extensive support with
+ * code examples and data books
+ *
+ * Bjarne Steinsbo, bjarne at steinsbo.com (some ideas for rewriting)
+ *
+ * Contributions to the skystar2-driver have been done by
+ * Vincenzo Di Massa, hawk.it at tiscalinet.it (several DiSEqC fixes)
+ * Roberto Ragusa, r.ragusa at libero.it (polishing, restyling the code)
+ * Niklas Peinecke, peinecke at gdv.uni-hannover.de (hardware pid/mac filtering)
+ *
+ *
+ * This program 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 (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 Lesser 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 "flexcop.h"
+
+#define DRIVER_NAME "B2C2 FlexcopII/II(b)/III digital TV receiver chip"
+#define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de"
+
+#ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG
+#define DEBSTATUS ""
+#else
+#define DEBSTATUS " (debugging is not enabled)"
+#endif
+
+int b2c2_flexcop_debug;
+module_param_named(debug, b2c2_flexcop_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debug level (1=info,2=tuner,4=i2c,8=ts,16=sram (|-able))." DEBSTATUS);
+#undef DEBSTATUS
+
+/* global zero for ibi values */
+flexcop_ibi_value ibi_zero;
+
+static int flexcop_dvb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+ struct flexcop_device *fc = dvbdmxfeed->demux->priv;
+ return flexcop_pid_feed_control(fc,dvbdmxfeed,1);
+}
+
+static int flexcop_dvb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+ struct flexcop_device *fc = dvbdmxfeed->demux->priv;
+ return flexcop_pid_feed_control(fc,dvbdmxfeed,0);
+}
+
+static int flexcop_dvb_init(struct flexcop_device *fc)
+{
+ int ret;
+ if ((ret = dvb_register_adapter(&fc->dvb_adapter,"FlexCop Digital TV device",fc->owner)) < 0) {
+ err("error registering DVB adapter");
+ return ret;
+ }
+ fc->dvb_adapter.priv = fc;
+
+ fc->demux.dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING);
+ fc->demux.priv = fc;
+
+ fc->demux.filternum = fc->demux.feednum = FC_MAX_FEED;
+
+ fc->demux.start_feed = flexcop_dvb_start_feed;
+ fc->demux.stop_feed = flexcop_dvb_stop_feed;
+ fc->demux.write_to_decoder = NULL;
+
+ if ((ret = dvb_dmx_init(&fc->demux)) < 0) {
+ err("dvb_dmx failed: error %d",ret);
+ goto err_dmx;
+ }
+
+ fc->hw_frontend.source = DMX_FRONTEND_0;
+
+ fc->dmxdev.filternum = fc->demux.feednum;
+ fc->dmxdev.demux = &fc->demux.dmx;
+ fc->dmxdev.capabilities = 0;
+ if ((ret = dvb_dmxdev_init(&fc->dmxdev, &fc->dvb_adapter)) < 0) {
+ err("dvb_dmxdev_init failed: error %d",ret);
+ goto err_dmx_dev;
+ }
+
+ if ((ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->hw_frontend)) < 0) {
+ err("adding hw_frontend to dmx failed: error %d",ret);
+ goto err_dmx_add_hw_frontend;
+ }
+
+ fc->mem_frontend.source = DMX_MEMORY_FE;
+ if ((ret = fc->demux.dmx.add_frontend(&fc->demux.dmx, &fc->mem_frontend)) < 0) {
+ err("adding mem_frontend to dmx failed: error %d",ret);
+ goto err_dmx_add_mem_frontend;
+ }
+
+ if ((ret = fc->demux.dmx.connect_frontend(&fc->demux.dmx, &fc->hw_frontend)) < 0) {
+ err("connect frontend failed: error %d",ret);
+ goto err_connect_frontend;
+ }
+
+ dvb_net_init(&fc->dvb_adapter, &fc->dvbnet, &fc->demux.dmx);
+
+ fc->init_state |= FC_STATE_DVB_INIT;
+ goto success;
+
+err_connect_frontend:
+ fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->mem_frontend);
+err_dmx_add_mem_frontend:
+ fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->hw_frontend);
+err_dmx_add_hw_frontend:
+ dvb_dmxdev_release(&fc->dmxdev);
+err_dmx_dev:
+ dvb_dmx_release(&fc->demux);
+err_dmx:
+ dvb_unregister_adapter(&fc->dvb_adapter);
+ return ret;
+
+success:
+ return 0;
+}
+
+static void flexcop_dvb_exit(struct flexcop_device *fc)
+{
+ if (fc->init_state & FC_STATE_DVB_INIT) {
+ dvb_net_release(&fc->dvbnet);
+
+ fc->demux.dmx.close(&fc->demux.dmx);
+ fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->mem_frontend);
+ fc->demux.dmx.remove_frontend(&fc->demux.dmx,&fc->hw_frontend);
+ dvb_dmxdev_release(&fc->dmxdev);
+ dvb_dmx_release(&fc->demux);
+ dvb_unregister_adapter(&fc->dvb_adapter);
+
+ deb_info("deinitialized dvb stuff\n");
+ }
+ fc->init_state &= ~FC_STATE_DVB_INIT;
+}
+
+/* these methods are necessary to achieve the long-term-goal of hiding the
+ * struct flexcop_device from the bus-parts */
+void flexcop_pass_dmx_data(struct flexcop_device *fc, u8 *buf, u32 len)
+{
+ dvb_dmx_swfilter(&fc->demux, buf, len);
+}
+EXPORT_SYMBOL(flexcop_pass_dmx_data);
+
+void flexcop_pass_dmx_packets(struct flexcop_device *fc, u8 *buf, u32 no)
+{
+ dvb_dmx_swfilter_packets(&fc->demux, buf, no);
+}
+EXPORT_SYMBOL(flexcop_pass_dmx_packets);
+
+static void flexcop_reset(struct flexcop_device *fc)
+{
+ flexcop_ibi_value v210,v204;
+
+/* reset the flexcop itself */
+ fc->write_ibi_reg(fc,ctrl_208,ibi_zero);
+
+ v210.raw = 0;
+ v210.sw_reset_210.reset_blocks = 0xff;
+ v210.sw_reset_210.Block_reset_enable = 0xb2;
+ fc->write_ibi_reg(fc,sw_reset_210,v210);
+
+/* reset the periphical devices */
+
+ v204 = fc->read_ibi_reg(fc,misc_204);
+ v204.misc_204.Per_reset_sig = 0;
+ fc->write_ibi_reg(fc,misc_204,v204);
+ v204.misc_204.Per_reset_sig = 1;
+ fc->write_ibi_reg(fc,misc_204,v204);
+}
+
+struct flexcop_device *flexcop_device_kmalloc(size_t bus_specific_len)
+{
+ void *bus;
+ struct flexcop_device *fc = kmalloc(sizeof(struct flexcop_device), GFP_KERNEL);
+ if (!fc) {
+ err("no memory");
+ return NULL;
+ }
+ memset(fc, 0, sizeof(struct flexcop_device));
+
+ bus = kmalloc(bus_specific_len, GFP_KERNEL);
+ if (!bus) {
+ err("no memory");
+ kfree(fc);
+ return NULL;
+ }
+ memset(bus, 0, bus_specific_len);
+
+ fc->bus_specific = bus;
+
+ return fc;
+}
+EXPORT_SYMBOL(flexcop_device_kmalloc);
+
+void flexcop_device_kfree(struct flexcop_device *fc)
+{
+ kfree(fc->bus_specific);
+ kfree(fc);
+}
+EXPORT_SYMBOL(flexcop_device_kfree);
+
+int flexcop_device_initialize(struct flexcop_device *fc)
+{
+ int ret;
+ ibi_zero.raw = 0;
+
+ flexcop_reset(fc);
+ flexcop_determine_revision(fc);
+ flexcop_sram_init(fc);
+ flexcop_hw_filter_init(fc);
+
+ flexcop_smc_ctrl(fc, 0);
+
+ if ((ret = flexcop_dvb_init(fc)))
+ goto error;
+
+ /* do the MAC address reading after initializing the dvb_adapter */
+ if (fc->get_mac_addr(fc, 0) == 0) {
+ u8 *b = fc->dvb_adapter.proposed_mac;
+ info("MAC address = %02x:%02x:%02x:%02x:%02x:%02x", b[0],b[1],b[2],b[3],b[4],b[5]);
+ flexcop_set_mac_filter(fc,b);
+ flexcop_mac_filter_ctrl(fc,1);
+ } else
+ warn("reading of MAC address failed.\n");
+
+
+ if ((ret = flexcop_i2c_init(fc)))
+ goto error;
+
+ if ((ret = flexcop_frontend_init(fc)))
+ goto error;
+
+ flexcop_device_name(fc,"initialization of","complete");
+
+ ret = 0;
+ goto success;
+error:
+ flexcop_device_exit(fc);
+success:
+ return ret;
+}
+EXPORT_SYMBOL(flexcop_device_initialize);
+
+void flexcop_device_exit(struct flexcop_device *fc)
+{
+ flexcop_frontend_exit(fc);
+ flexcop_i2c_exit(fc);
+ flexcop_dvb_exit(fc);
+}
+EXPORT_SYMBOL(flexcop_device_exit);
+
+static int flexcop_module_init(void)
+{
+ info(DRIVER_NAME " loaded successfully");
+ return 0;
+}
+
+static void flexcop_module_cleanup(void)
+{
+ info(DRIVER_NAME " unloaded successfully");
+}
+
+module_init(flexcop_module_init);
+module_exit(flexcop_module_cleanup);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_NAME);
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/b2c2/flexcop.h b/drivers/media/dvb/b2c2/flexcop.h
new file mode 100644
index 00000000000..caa343a97bd
--- /dev/null
+++ b/drivers/media/dvb/b2c2/flexcop.h
@@ -0,0 +1,30 @@
+/*
+ * This file is part of linux driver the digital TV devices equipped with B2C2 FlexcopII(b)/III
+ *
+ * flexcop.h - private header file for all flexcop-chip-source files.
+ *
+ * see flexcop.c for copyright information.
+ */
+#ifndef __FLEXCOP_H__
+#define __FLEXCOP_H___
+
+#define FC_LOG_PREFIX "b2c2-flexcop"
+#include "flexcop-common.h"
+
+extern int b2c2_flexcop_debug;
+
+/* debug */
+#ifdef CONFIG_DVB_B2C2_FLEXCOP_DEBUG
+#define dprintk(level,args...) \
+ do { if ((b2c2_flexcop_debug & level)) printk(args); } while (0)
+#else
+#define dprintk(level,args...)
+#endif
+
+#define deb_info(args...) dprintk(0x01,args)
+#define deb_tuner(args...) dprintk(0x02,args)
+#define deb_i2c(args...) dprintk(0x04,args)
+#define deb_ts(args...) dprintk(0x08,args)
+#define deb_sram(args...) dprintk(0x10,args)
+
+#endif
diff --git a/drivers/media/dvb/b2c2/skystar2.c b/drivers/media/dvb/b2c2/skystar2.c
index 336c178fcd5..acbc4c34f72 100644
--- a/drivers/media/dvb/b2c2/skystar2.c
+++ b/drivers/media/dvb/b2c2/skystar2.c
@@ -97,7 +97,7 @@ struct adapter {
u8 mac_addr[8];
u32 dw_sram_type;
- struct dvb_adapter *dvb_adapter;
+ struct dvb_adapter dvb_adapter;
struct dvb_demux demux;
struct dmxdev dmxdev;
struct dmx_frontend hw_frontend;
@@ -2461,7 +2461,7 @@ static void frontend_init(struct adapter *skystar2)
skystar2->pdev->subsystem_vendor,
skystar2->pdev->subsystem_device);
} else {
- if (dvb_register_frontend(skystar2->dvb_adapter, skystar2->fe)) {
+ if (dvb_register_frontend(&skystar2->dvb_adapter, skystar2->fe)) {
printk("skystar2: Frontend registration failed!\n");
if (skystar2->fe->ops->release)
skystar2->fe->ops->release(skystar2->fe);
@@ -2486,17 +2486,17 @@ static int skystar2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ret < 0)
goto out;
- ret = dvb_register_adapter(&dvb_adapter, skystar2_pci_driver.name,
+ adapter = pci_get_drvdata(pdev);
+ dvb_adapter = &adapter->dvb_adapter;
+
+ ret = dvb_register_adapter(dvb_adapter, skystar2_pci_driver.name,
THIS_MODULE);
if (ret < 0) {
printk("%s: Error registering DVB adapter\n", __FUNCTION__);
goto err_halt;
}
- adapter = pci_get_drvdata(pdev);
-
dvb_adapter->priv = adapter;
- adapter->dvb_adapter = dvb_adapter;
init_MUTEX(&adapter->i2c_sem);
@@ -2541,7 +2541,7 @@ static int skystar2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->dmxdev.demux = dmx;
adapter->dmxdev.capabilities = 0;
- ret = dvb_dmxdev_init(&adapter->dmxdev, adapter->dvb_adapter);
+ ret = dvb_dmxdev_init(&adapter->dmxdev, &adapter->dvb_adapter);
if (ret < 0)
goto err_dmx_release;
@@ -2559,7 +2559,7 @@ static int skystar2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ret < 0)
goto err_remove_mem_frontend;
- dvb_net_init(adapter->dvb_adapter, &adapter->dvbnet, &dvbdemux->dmx);
+ dvb_net_init(&adapter->dvb_adapter, &adapter->dvbnet, &dvbdemux->dmx);
frontend_init(adapter);
out:
@@ -2576,7 +2576,7 @@ err_dmx_release:
err_i2c_del:
i2c_del_adapter(&adapter->i2c_adap);
err_dvb_unregister:
- dvb_unregister_adapter(adapter->dvb_adapter);
+ dvb_unregister_adapter(&adapter->dvb_adapter);
err_halt:
driver_halt(pdev);
goto out;
@@ -2605,7 +2605,7 @@ static void skystar2_remove(struct pci_dev *pdev)
if (adapter->fe != NULL)
dvb_unregister_frontend(adapter->fe);
- dvb_unregister_adapter(adapter->dvb_adapter);
+ dvb_unregister_adapter(&adapter->dvb_adapter);
i2c_del_adapter(&adapter->i2c_adap);
diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig
index e7d11e0667a..b12545f093f 100644
--- a/drivers/media/dvb/bt8xx/Kconfig
+++ b/drivers/media/dvb/bt8xx/Kconfig
@@ -11,9 +11,8 @@ config DVB_BT8XX
the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards and
pcHDTV HD2000 cards.
- Since these cards have no MPEG decoder onboard, they transmit
+ Since these cards have no MPEG decoder onboard, they transmit
only compressed MPEG data over the PCI bus, so you need
an external software decoder to watch TV on your computer.
Say Y if you own such a device and want to use it.
-
diff --git a/drivers/media/dvb/bt8xx/Makefile b/drivers/media/dvb/bt8xx/Makefile
index 9da8604b9e1..d188e4c670b 100644
--- a/drivers/media/dvb/bt8xx/Makefile
+++ b/drivers/media/dvb/bt8xx/Makefile
@@ -1,5 +1,3 @@
-
-obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o
+obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o
EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/video -Idrivers/media/dvb/frontends
-
diff --git a/drivers/media/dvb/bt8xx/bt878.c b/drivers/media/dvb/bt8xx/bt878.c
index 213ff790202..3c5a8e273c4 100644
--- a/drivers/media/dvb/bt8xx/bt878.c
+++ b/drivers/media/dvb/bt8xx/bt878.c
@@ -4,27 +4,27 @@
* Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de>
*
* large parts based on the bttv driver
- * Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de)
- * & Marcus Metzler (mocm@thp.uni-koeln.de)
+ * Copyright (C) 1996,97,98 Ralph Metzler (rjkm@metzlerbros.de)
+ * & Marcus Metzler (mocm@metzlerbros.de)
* (c) 1999,2000 Gerd Knorr <kraxel@goldbach.in-berlin.de>
*
* 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 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.
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
- *
+ *
*/
#include <linux/module.h>
@@ -58,7 +58,7 @@ module_param_named(verbose, bt878_verbose, int, 0444);
MODULE_PARM_DESC(verbose,
"verbose startup messages, default is 1 (yes)");
module_param_named(debug, bt878_debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+MODULE_PARM_DESC(debug, "Turn on/off debugging, default is 0 (off).");
int bt878_num;
struct bt878 bt878[BT878_MAX];
@@ -128,21 +128,21 @@ static int bt878_mem_alloc(struct bt878 *bt)
}
/* RISC instructions */
-#define RISC_WRITE (0x01 << 28)
-#define RISC_JUMP (0x07 << 28)
-#define RISC_SYNC (0x08 << 28)
+#define RISC_WRITE (0x01 << 28)
+#define RISC_JUMP (0x07 << 28)
+#define RISC_SYNC (0x08 << 28)
/* RISC bits */
-#define RISC_WR_SOL (1 << 27)
-#define RISC_WR_EOL (1 << 26)
-#define RISC_IRQ (1 << 24)
+#define RISC_WR_SOL (1 << 27)
+#define RISC_WR_EOL (1 << 26)
+#define RISC_IRQ (1 << 24)
#define RISC_STATUS(status) ((((~status) & 0x0F) << 20) | ((status & 0x0F) << 16))
-#define RISC_SYNC_RESYNC (1 << 15)
-#define RISC_SYNC_FM1 0x06
-#define RISC_SYNC_VRO 0x0C
+#define RISC_SYNC_RESYNC (1 << 15)
+#define RISC_SYNC_FM1 0x06
+#define RISC_SYNC_VRO 0x0C
#define RISC_FLUSH() bt->risc_pos = 0
-#define RISC_INSTR(instr) bt->risc_cpu[bt->risc_pos++] = cpu_to_le32(instr)
+#define RISC_INSTR(instr) bt->risc_cpu[bt->risc_pos++] = cpu_to_le32(instr)
static int bt878_make_risc(struct bt878 *bt)
{
@@ -173,7 +173,7 @@ static void bt878_risc_program(struct bt878 *bt, u32 op_sync_orin)
RISC_INSTR(RISC_SYNC | RISC_SYNC_FM1 | op_sync_orin);
RISC_INSTR(0);
- dprintk("bt878: risc len lines %u, bytes per line %u\n",
+ dprintk("bt878: risc len lines %u, bytes per line %u\n",
bt->line_count, bt->line_bytes);
for (line = 0; line < bt->line_count; line++) {
// At the beginning of every block we issue an IRQ with previous (finished) block number set
@@ -228,14 +228,14 @@ void bt878_start(struct bt878 *bt, u32 controlreg, u32 op_sync_orin,
* Hacked for DST to:
* SCERR | OCERR | FDSR | FTRGT | FBUS | RISCI
*/
- int_mask = BT878_ASCERR | BT878_AOCERR | BT878_APABORT |
- BT878_ARIPERR | BT878_APPERR | BT878_AFDSR | BT878_AFTRGT |
+ int_mask = BT878_ASCERR | BT878_AOCERR | BT878_APABORT |
+ BT878_ARIPERR | BT878_APPERR | BT878_AFDSR | BT878_AFTRGT |
BT878_AFBUS | BT878_ARISCI;
/* ignore pesky bits */
int_mask &= ~irq_err_ignore;
-
+
btwrite(int_mask, BT878_AINT_MASK);
btwrite(controlreg, BT878_AGPIO_DMA_CTL);
}
@@ -461,9 +461,9 @@ static int __devinit bt878_probe(struct pci_dev *dev,
pci_set_drvdata(dev, bt);
/* if(init_bt878(btv) < 0) {
- bt878_remove(dev);
- return -EIO;
- }
+ bt878_remove(dev);
+ return -EIO;
+ }
*/
if ((result = bt878_mem_alloc(bt))) {
@@ -536,10 +536,10 @@ static struct pci_device_id bt878_pci_tbl[] __devinitdata = {
MODULE_DEVICE_TABLE(pci, bt878_pci_tbl);
static struct pci_driver bt878_pci_driver = {
- .name = "bt878",
+ .name = "bt878",
.id_table = bt878_pci_tbl,
- .probe = bt878_probe,
- .remove = bt878_remove,
+ .probe = bt878_probe,
+ .remove = bt878_remove,
};
static int bt878_pci_driver_registered = 0;
@@ -558,7 +558,7 @@ static int bt878_init_module(void)
(BT878_VERSION_CODE >> 8) & 0xff,
BT878_VERSION_CODE & 0xff);
/*
- bt878_check_chipset();
+ bt878_check_chipset();
*/
/* later we register inside of bt878_find_audio_dma()
* because we may want to ignore certain cards */
diff --git a/drivers/media/dvb/bt8xx/bt878.h b/drivers/media/dvb/bt8xx/bt878.h
index e1b9809d1b0..837623f7fcd 100644
--- a/drivers/media/dvb/bt8xx/bt878.h
+++ b/drivers/media/dvb/bt8xx/bt878.h
@@ -1,4 +1,4 @@
-/*
+/*
bt878.h - Bt878 audio module (register offsets)
Copyright (C) 2002 Peter Hettkamp <peter.hettkamp@t-online.de>
@@ -120,14 +120,14 @@ struct bt878 {
u32 risc_pos;
struct tasklet_struct tasklet;
- int shutdown;
+ int shutdown;
};
extern struct bt878 bt878[BT878_MAX];
void bt878_start(struct bt878 *bt, u32 controlreg, u32 op_sync_orin,
u32 irq_err_ignore);
-void bt878_stop(struct bt878 *bt);
+void bt878_stop(struct bt878 *bt);
#if defined(__powerpc__) /* big-endian */
extern __inline__ void io_st_le32(volatile unsigned __iomem *addr, unsigned val)
diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c
index eac83768dfd..1339912c308 100644
--- a/drivers/media/dvb/bt8xx/dst.c
+++ b/drivers/media/dvb/bt8xx/dst.c
@@ -1,25 +1,25 @@
/*
- Frontend-driver for TwinHan DST Frontend
- Copyright (C) 2003 Jamie Honan
+ Frontend/Card driver for TwinHan DST Frontend
+ Copyright (C) 2003 Jamie Honan
+ Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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 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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -31,59 +31,22 @@
#include "dvb_frontend.h"
#include "dst_priv.h"
-#include "dst.h"
-
-struct dst_state {
-
- struct i2c_adapter* i2c;
-
- struct bt878* bt;
-
- struct dvb_frontend_ops ops;
-
- /* configuration settings */
- const struct dst_config* config;
-
- struct dvb_frontend frontend;
-
- /* private demodulator data */
- u8 tx_tuna[10];
- u8 rx_tuna[10];
- u8 rxbuffer[10];
- u8 diseq_flags;
- u8 dst_type;
- u32 type_flags;
- u32 frequency; /* intermediate frequency in kHz for QPSK */
- fe_spectral_inversion_t inversion;
- u32 symbol_rate; /* symbol rate in Symbols per second */
- fe_code_rate_t fec;
- fe_sec_voltage_t voltage;
- fe_sec_tone_mode_t tone;
- u32 decode_freq;
- u8 decode_lock;
- u16 decode_strength;
- u16 decode_snr;
- unsigned long cur_jiff;
- u8 k22;
- fe_bandwidth_t bandwidth;
-};
+#include "dst_common.h"
+
-static unsigned int dst_verbose = 0;
-module_param(dst_verbose, int, 0644);
-MODULE_PARM_DESC(dst_verbose, "verbose startup messages, default is 1 (yes)");
-static unsigned int dst_debug = 0;
-module_param(dst_debug, int, 0644);
-MODULE_PARM_DESC(dst_debug, "debug messages, default is 0 (no)");
+static unsigned int verbose = 1;
+module_param(verbose, int, 0644);
+MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
-#define dprintk if (dst_debug) printk
+static unsigned int debug = 1;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "debug messages, default is 0 (yes)");
-#define DST_TYPE_IS_SAT 0
-#define DST_TYPE_IS_TERR 1
-#define DST_TYPE_IS_CABLE 2
+static unsigned int dst_addons;
+module_param(dst_addons, int, 0644);
+MODULE_PARM_DESC(dst_addons, "CA daughterboard, default is 0 (No addons)");
-#define DST_TYPE_HAS_NEWTUNE 1
-#define DST_TYPE_HAS_TS204 2
-#define DST_TYPE_HAS_SYMDIV 4
+#define dprintk if (debug) printk
#define HAS_LOCK 1
#define ATTEMPT_TUNE 2
@@ -97,7 +60,7 @@ static void dst_packsize(struct dst_state* state, int psize)
bt878_device_control(state->bt, DST_IG_TS, &bits);
}
-static int dst_gpio_outb(struct dst_state* state, u32 mask, u32 enbb, u32 outhigh)
+int dst_gpio_outb(struct dst_state* state, u32 mask, u32 enbb, u32 outhigh, int delay)
{
union dst_gpio_packet enb;
union dst_gpio_packet bits;
@@ -105,26 +68,33 @@ static int dst_gpio_outb(struct dst_state* state, u32 mask, u32 enbb, u32 outhig
enb.enb.mask = mask;
enb.enb.enable = enbb;
+ if (verbose > 4)
+ dprintk("%s: mask=[%04x], enbb=[%04x], outhigh=[%04x]\n", __FUNCTION__, mask, enbb, outhigh);
+
if ((err = bt878_device_control(state->bt, DST_IG_ENABLE, &enb)) < 0) {
- dprintk("%s: dst_gpio_enb error (err == %i, mask == 0x%02x, enb == 0x%02x)\n", __FUNCTION__, err, mask, enbb);
+ dprintk("%s: dst_gpio_enb error (err == %i, mask == %02x, enb == %02x)\n", __FUNCTION__, err, mask, enbb);
return -EREMOTEIO;
}
-
+ udelay(1000);
/* because complete disabling means no output, no need to do output packet */
if (enbb == 0)
return 0;
+ if (delay)
+ msleep(10);
+
bits.outp.mask = enbb;
bits.outp.highvals = outhigh;
if ((err = bt878_device_control(state->bt, DST_IG_WRITE, &bits)) < 0) {
- dprintk("%s: dst_gpio_outb error (err == %i, enbb == 0x%02x, outhigh == 0x%02x)\n", __FUNCTION__, err, enbb, outhigh);
+ dprintk("%s: dst_gpio_outb error (err == %i, enbb == %02x, outhigh == %02x)\n", __FUNCTION__, err, enbb, outhigh);
return -EREMOTEIO;
}
return 0;
}
+EXPORT_SYMBOL(dst_gpio_outb);
-static int dst_gpio_inb(struct dst_state *state, u8 * result)
+int dst_gpio_inb(struct dst_state *state, u8 * result)
{
union dst_gpio_packet rd_packet;
int err;
@@ -139,143 +109,225 @@ static int dst_gpio_inb(struct dst_state *state, u8 * result)
*result = (u8) rd_packet.rd.value;
return 0;
}
+EXPORT_SYMBOL(dst_gpio_inb);
-#define DST_I2C_ENABLE 1
-#define DST_8820 2
-
-static int dst_reset8820(struct dst_state *state)
+int rdc_reset_state(struct dst_state *state)
{
- int retval;
- /* pull 8820 gpio pin low, wait, high, wait, then low */
- // dprintk ("%s: reset 8820\n", __FUNCTION__);
- retval = dst_gpio_outb(state, DST_8820, DST_8820, 0);
- if (retval < 0)
- return retval;
+ if (verbose > 1)
+ dprintk("%s: Resetting state machine\n", __FUNCTION__);
+
+ if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, 0, NO_DELAY) < 0) {
+ dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+ return -1;
+ }
+
msleep(10);
- retval = dst_gpio_outb(state, DST_8820, DST_8820, DST_8820);
- if (retval < 0)
- return retval;
- /* wait for more feedback on what works here *
- msleep(10);
- retval = dst_gpio_outb(dst, DST_8820, DST_8820, 0);
- if (retval < 0)
- return retval;
- */
+
+ if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, RDC_8820_INT, NO_DELAY) < 0) {
+ dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+ msleep(10);
+ return -1;
+ }
+
return 0;
}
+EXPORT_SYMBOL(rdc_reset_state);
-static int dst_i2c_enable(struct dst_state *state)
+int rdc_8820_reset(struct dst_state *state)
{
- int retval;
- /* pull I2C enable gpio pin low, wait */
- // dprintk ("%s: i2c enable\n", __FUNCTION__);
- retval = dst_gpio_outb(state, ~0, DST_I2C_ENABLE, 0);
- if (retval < 0)
- return retval;
- // dprintk ("%s: i2c enable delay\n", __FUNCTION__);
- msleep(33);
+ if (verbose > 1)
+ dprintk("%s: Resetting DST\n", __FUNCTION__);
+
+ if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, 0, NO_DELAY) < 0) {
+ dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+ return -1;
+ }
+ udelay(1000);
+ if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, RDC_8820_RESET, DELAY) < 0) {
+ dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+ return -1;
+ }
+
return 0;
}
+EXPORT_SYMBOL(rdc_8820_reset);
-static int dst_i2c_disable(struct dst_state *state)
+int dst_pio_enable(struct dst_state *state)
{
- int retval;
- /* release I2C enable gpio pin, wait */
- // dprintk ("%s: i2c disable\n", __FUNCTION__);
- retval = dst_gpio_outb(state, ~0, 0, 0);
- if (retval < 0)
- return retval;
- // dprintk ("%s: i2c disable delay\n", __FUNCTION__);
- msleep(33);
+ if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_ENABLE, 0, NO_DELAY) < 0) {
+ dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+ return -1;
+ }
+ udelay(1000);
+ return 0;
+}
+EXPORT_SYMBOL(dst_pio_enable);
+
+int dst_pio_disable(struct dst_state *state)
+{
+ if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_DISABLE, RDC_8820_PIO_0_DISABLE, NO_DELAY) < 0) {
+ dprintk("%s: dst_gpio_outb ERROR !\n", __FUNCTION__);
+ return -1;
+ }
+ if (state->type_flags & DST_TYPE_HAS_FW_1)
+ udelay(1000);
+
return 0;
}
+EXPORT_SYMBOL(dst_pio_disable);
-static int dst_wait_dst_ready(struct dst_state *state)
+int dst_wait_dst_ready(struct dst_state *state, u8 delay_mode)
{
u8 reply;
- int retval;
int i;
+
for (i = 0; i < 200; i++) {
- retval = dst_gpio_inb(state, &reply);
- if (retval < 0)
- return retval;
- if ((reply & DST_I2C_ENABLE) == 0) {
- dprintk("%s: dst wait ready after %d\n", __FUNCTION__, i);
+ if (dst_gpio_inb(state, &reply) < 0) {
+ dprintk("%s: dst_gpio_inb ERROR !\n", __FUNCTION__);
+ return -1;
+ }
+
+ if ((reply & RDC_8820_PIO_0_ENABLE) == 0) {
+ if (verbose > 4)
+ dprintk("%s: dst wait ready after %d\n", __FUNCTION__, i);
return 1;
}
msleep(10);
}
- dprintk("%s: dst wait NOT ready after %d\n", __FUNCTION__, i);
+ if (verbose > 1)
+ dprintk("%s: dst wait NOT ready after %d\n", __FUNCTION__, i);
+
+ return 0;
+}
+EXPORT_SYMBOL(dst_wait_dst_ready);
+
+int dst_error_recovery(struct dst_state *state)
+{
+ dprintk("%s: Trying to return from previous errors...\n", __FUNCTION__);
+ dst_pio_disable(state);
+ msleep(10);
+ dst_pio_enable(state);
+ msleep(10);
+
return 0;
}
+EXPORT_SYMBOL(dst_error_recovery);
+
+int dst_error_bailout(struct dst_state *state)
+{
+ dprintk("%s: Trying to bailout from previous error...\n", __FUNCTION__);
+ rdc_8820_reset(state);
+ dst_pio_disable(state);
+ msleep(10);
+
+ return 0;
+}
+EXPORT_SYMBOL(dst_error_bailout);
+
+
+int dst_comm_init(struct dst_state* state)
+{
+ if (verbose > 1)
+ dprintk ("%s: Initializing DST..\n", __FUNCTION__);
+ if ((dst_pio_enable(state)) < 0) {
+ dprintk("%s: PIO Enable Failed.\n", __FUNCTION__);
+ return -1;
+ }
+ if ((rdc_reset_state(state)) < 0) {
+ dprintk("%s: RDC 8820 State RESET Failed.\n", __FUNCTION__);
+ return -1;
+ }
+ if (state->type_flags & DST_TYPE_HAS_FW_1)
+ msleep(100);
+ else
+ msleep(5);
+
+ return 0;
+}
+EXPORT_SYMBOL(dst_comm_init);
+
-static int write_dst(struct dst_state *state, u8 * data, u8 len)
+int write_dst(struct dst_state *state, u8 *data, u8 len)
{
struct i2c_msg msg = {
.addr = state->config->demod_address,.flags = 0,.buf = data,.len = len
};
+
int err;
int cnt;
-
- if (dst_debug && dst_verbose) {
+ if (debug && (verbose > 4)) {
u8 i;
- dprintk("%s writing", __FUNCTION__);
- for (i = 0; i < len; i++) {
- dprintk(" 0x%02x", data[i]);
+ if (verbose > 4) {
+ dprintk("%s writing", __FUNCTION__);
+ for (i = 0; i < len; i++)
+ dprintk(" %02x", data[i]);
+ dprintk("\n");
}
- dprintk("\n");
}
- msleep(30);
- for (cnt = 0; cnt < 4; cnt++) {
+ for (cnt = 0; cnt < 2; cnt++) {
if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) {
- dprintk("%s: write_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n", __FUNCTION__, err, len, data[0]);
- dst_i2c_disable(state);
- msleep(500);
- dst_i2c_enable(state);
- msleep(500);
+ dprintk("%s: _write_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n", __FUNCTION__, err, len, data[0]);
+ dst_error_recovery(state);
continue;
} else
break;
}
- if (cnt >= 4)
- return -EREMOTEIO;
+
+ if (cnt >= 2) {
+ if (verbose > 1)
+ printk("%s: RDC 8820 RESET...\n", __FUNCTION__);
+ dst_error_bailout(state);
+
+ return -1;
+ }
+
return 0;
}
+EXPORT_SYMBOL(write_dst);
-static int read_dst(struct dst_state *state, u8 * ret, u8 len)
+int read_dst(struct dst_state *state, u8 * ret, u8 len)
{
struct i2c_msg msg = {.addr = state->config->demod_address,.flags = I2C_M_RD,.buf = ret,.len = len };
int err;
int cnt;
- for (cnt = 0; cnt < 4; cnt++) {
+ for (cnt = 0; cnt < 2; cnt++) {
if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) {
+
dprintk("%s: read_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n", __FUNCTION__, err, len, ret[0]);
- dst_i2c_disable(state);
- dst_i2c_enable(state);
+ dst_error_recovery(state);
+
continue;
} else
break;
}
- if (cnt >= 4)
- return -EREMOTEIO;
- dprintk("%s reply is 0x%x\n", __FUNCTION__, ret[0]);
- if (dst_debug && dst_verbose) {
+ if (cnt >= 2) {
+ if (verbose > 1)
+ printk("%s: RDC 8820 RESET...\n", __FUNCTION__);
+ dst_error_bailout(state);
+
+ return -1;
+ }
+ if (debug && (verbose > 4)) {
+ dprintk("%s reply is 0x%x\n", __FUNCTION__, ret[0]);
for (err = 1; err < len; err++)
dprintk(" 0x%x", ret[err]);
if (err > 1)
dprintk("\n");
}
+
return 0;
}
+EXPORT_SYMBOL(read_dst);
static int dst_set_freq(struct dst_state *state, u32 freq)
{
u8 *val;
state->frequency = freq;
+ if (debug > 4)
+ dprintk("%s: set Frequency %u\n", __FUNCTION__, freq);
- // dprintk("%s: set frequency %u\n", __FUNCTION__, freq);
if (state->dst_type == DST_TYPE_IS_SAT) {
freq = freq / 1000;
if (freq < 950 || freq > 2150)
@@ -398,7 +450,8 @@ static int dst_set_symbolrate(struct dst_state* state, u32 srate)
if (state->dst_type == DST_TYPE_IS_TERR) {
return 0;
}
- // dprintk("%s: set srate %u\n", __FUNCTION__, srate);
+ if (debug > 4)
+ dprintk("%s: set symrate %u\n", __FUNCTION__, srate);
srate /= 1000;
val = &state->tx_tuna[0];
@@ -407,7 +460,10 @@ static int dst_set_symbolrate(struct dst_state* state, u32 srate)
sval <<= 20;
do_div(sval, 88000);
symcalc = (u32) sval;
- // dprintk("%s: set symcalc %u\n", __FUNCTION__, symcalc);
+
+ if (debug > 4)
+ dprintk("%s: set symcalc %u\n", __FUNCTION__, symcalc);
+
val[5] = (u8) (symcalc >> 12);
val[6] = (u8) (symcalc >> 4);
val[7] = (u8) (symcalc << 4);
@@ -422,7 +478,7 @@ static int dst_set_symbolrate(struct dst_state* state, u32 srate)
return 0;
}
-static u8 dst_check_sum(u8 * buf, u32 len)
+u8 dst_check_sum(u8 * buf, u32 len)
{
u32 i;
u8 val = 0;
@@ -433,28 +489,7 @@ static u8 dst_check_sum(u8 * buf, u32 len)
}
return ((~val) + 1);
}
-
-struct dst_types {
- char *mstr;
- int offs;
- u8 dst_type;
- u32 type_flags;
-};
-
-static struct dst_types dst_tlist[] = {
- {"DST-020", 0, DST_TYPE_IS_SAT, DST_TYPE_HAS_SYMDIV},
- {"DST-030", 0, DST_TYPE_IS_SAT, DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE},
- {"DST-03T", 0, DST_TYPE_IS_SAT, DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_TS204},
- {"DST-MOT", 0, DST_TYPE_IS_SAT, DST_TYPE_HAS_SYMDIV},
- {"DST-CI", 1, DST_TYPE_IS_SAT, DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE},
- {"DSTMCI", 1, DST_TYPE_IS_SAT, DST_TYPE_HAS_NEWTUNE},
- {"DSTFCI", 1, DST_TYPE_IS_SAT, DST_TYPE_HAS_NEWTUNE},
- {"DCTNEW", 1, DST_TYPE_IS_CABLE, DST_TYPE_HAS_NEWTUNE},
- {"DCT-CI", 1, DST_TYPE_IS_CABLE, DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_TS204},
- {"DTTDIG", 1, DST_TYPE_IS_TERR, 0}
-};
-
-/* DCTNEW and DCT-CI are guesses */
+EXPORT_SYMBOL(dst_check_sum);
static void dst_type_flags_print(u32 type_flags)
{
@@ -465,93 +500,270 @@ static void dst_type_flags_print(u32 type_flags)
printk(" 0x%x ts204", DST_TYPE_HAS_TS204);
if (type_flags & DST_TYPE_HAS_SYMDIV)
printk(" 0x%x symdiv", DST_TYPE_HAS_SYMDIV);
+ if (type_flags & DST_TYPE_HAS_FW_1)
+ printk(" 0x%x firmware version = 1", DST_TYPE_HAS_FW_1);
+ if (type_flags & DST_TYPE_HAS_FW_2)
+ printk(" 0x%x firmware version = 2", DST_TYPE_HAS_FW_2);
+ if (type_flags & DST_TYPE_HAS_FW_3)
+ printk(" 0x%x firmware version = 3", DST_TYPE_HAS_FW_3);
+// if ((type_flags & DST_TYPE_HAS_FW_BUILD) && new_fw)
+
printk("\n");
}
-static int dst_type_print(u8 type)
+
+static int dst_type_print (u8 type)
{
char *otype;
switch (type) {
case DST_TYPE_IS_SAT:
otype = "satellite";
break;
+
case DST_TYPE_IS_TERR:
otype = "terrestrial";
break;
+
case DST_TYPE_IS_CABLE:
otype = "cable";
break;
+
default:
printk("%s: invalid dst type %d\n", __FUNCTION__, type);
return -EINVAL;
}
printk("DST type : %s\n", otype);
+
return 0;
}
-static int dst_check_ci(struct dst_state *state)
+/*
+ Known cards list
+ Satellite
+ -------------------
+ 200103A
+ VP-1020 DST-MOT LG(old), TS=188
+
+ VP-1020 DST-03T LG(new), TS=204
+ VP-1022 DST-03T LG(new), TS=204
+ VP-1025 DST-03T LG(new), TS=204
+
+ VP-1030 DSTMCI, LG(new), TS=188
+ VP-1032 DSTMCI, LG(new), TS=188
+
+ Cable
+ -------------------
+ VP-2030 DCT-CI, Samsung, TS=204
+ VP-2021 DCT-CI, Unknown, TS=204
+ VP-2031 DCT-CI, Philips, TS=188
+ VP-2040 DCT-CI, Philips, TS=188, with CA daughter board
+ VP-2040 DCT-CI, Philips, TS=204, without CA daughter board
+
+ Terrestrial
+ -------------------
+ VP-3050 DTTNXT TS=188
+ VP-3040 DTT-CI, Philips, TS=188
+ VP-3040 DTT-CI, Philips, TS=204
+
+ ATSC
+ -------------------
+ VP-3220 ATSCDI, TS=188
+ VP-3250 ATSCAD, TS=188
+
+*/
+
+struct dst_types dst_tlist[] = {
+ {
+ .device_id = "200103A",
+ .offset = 0,
+ .dst_type = DST_TYPE_IS_SAT,
+ .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
+ .dst_feature = 0
+ }, /* obsolete */
+
+ {
+ .device_id = "DST-020",
+ .offset = 0,
+ .dst_type = DST_TYPE_IS_SAT,
+ .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
+ .dst_feature = 0
+ }, /* obsolete */
+
+ {
+ .device_id = "DST-030",
+ .offset = 0,
+ .dst_type = DST_TYPE_IS_SAT,
+ .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1,
+ .dst_feature = 0
+ }, /* obsolete */
+
+ {
+ .device_id = "DST-03T",
+ .offset = 0,
+ .dst_type = DST_TYPE_IS_SAT,
+ .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2,
+ .dst_feature = DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4 | DST_TYPE_HAS_DISEQC5
+ | DST_TYPE_HAS_MAC | DST_TYPE_HAS_MOTO
+ },
+
+ {
+ .device_id = "DST-MOT",
+ .offset = 0,
+ .dst_type = DST_TYPE_IS_SAT,
+ .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1,
+ .dst_feature = 0
+ }, /* obsolete */
+
+ {
+ .device_id = "DST-CI",
+ .offset = 1,
+ .dst_type = DST_TYPE_IS_SAT,
+ .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1,
+ .dst_feature = DST_TYPE_HAS_CA
+ }, /* An OEM board */
+
+ {
+ .device_id = "DSTMCI",
+ .offset = 1,
+ .dst_type = DST_TYPE_IS_SAT,
+ .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD,
+ .dst_feature = DST_TYPE_HAS_CA | DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4
+ | DST_TYPE_HAS_MOTO | DST_TYPE_HAS_MAC
+ },
+
+ {
+ .device_id = "DSTFCI",
+ .offset = 1,
+ .dst_type = DST_TYPE_IS_SAT,
+ .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1,
+ .dst_feature = 0
+ }, /* unknown to vendor */
+
+ {
+ .device_id = "DCT-CI",
+ .offset = 1,
+ .dst_type = DST_TYPE_IS_CABLE,
+ .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_1
+ | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD,
+ .dst_feature = DST_TYPE_HAS_CA
+ },
+
+ {
+ .device_id = "DCTNEW",
+ .offset = 1,
+ .dst_type = DST_TYPE_IS_CABLE,
+ .type_flags = DST_TYPE_HAS_NEWTUNE | DST_TYPE_HAS_FW_3,
+ .dst_feature = 0
+ },
+
+ {
+ .device_id = "DTT-CI",
+ .offset = 1,
+ .dst_type = DST_TYPE_IS_TERR,
+ .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD,
+ .dst_feature = 0
+ },
+
+ {
+ .device_id = "DTTDIG",
+ .offset = 1,
+ .dst_type = DST_TYPE_IS_TERR,
+ .type_flags = DST_TYPE_HAS_FW_2,
+ .dst_feature = 0
+ },
+
+ {
+ .device_id = "DTTNXT",
+ .offset = 1,
+ .dst_type = DST_TYPE_IS_TERR,
+ .type_flags = DST_TYPE_HAS_FW_2,
+ .dst_feature = DST_TYPE_HAS_ANALOG
+ },
+
+ {
+ .device_id = "ATSCDI",
+ .offset = 1,
+ .dst_type = DST_TYPE_IS_ATSC,
+ .type_flags = DST_TYPE_HAS_FW_2,
+ .dst_feature = 0
+ },
+
+ {
+ .device_id = "ATSCAD",
+ .offset = 1,
+ .dst_type = DST_TYPE_IS_ATSC,
+ .type_flags = DST_TYPE_HAS_FW_2,
+ .dst_feature = 0
+ },
+
+ { }
+
+};
+
+
+static int dst_get_device_id(struct dst_state *state)
{
- u8 txbuf[8];
- u8 rxbuf[8];
- int retval;
+ u8 reply;
+
int i;
- struct dst_types *dsp;
- u8 use_dst_type;
- u32 use_type_flags;
+ struct dst_types *p_dst_type;
+ u8 use_dst_type = 0;
+ u32 use_type_flags = 0;
- memset(txbuf, 0, sizeof(txbuf));
- txbuf[1] = 6;
- txbuf[7] = dst_check_sum(txbuf, 7);
+ static u8 device_type[8] = {0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff};
- dst_i2c_enable(state);
- dst_reset8820(state);
- retval = write_dst(state, txbuf, 8);
- if (retval < 0) {
- dst_i2c_disable(state);
- dprintk("%s: write not successful, maybe no card?\n", __FUNCTION__);
- return retval;
- }
- msleep(3);
- retval = read_dst(state, rxbuf, 1);
- dst_i2c_disable(state);
- if (retval < 0) {
- dprintk("%s: read not successful, maybe no card?\n", __FUNCTION__);
- return retval;
- }
- if (rxbuf[0] != 0xff) {
- dprintk("%s: write reply not 0xff, not ci (%02x)\n", __FUNCTION__, rxbuf[0]);
- return retval;
- }
- if (!dst_wait_dst_ready(state))
- return 0;
- // dst_i2c_enable(i2c); Dimitri
- retval = read_dst(state, rxbuf, 8);
- dst_i2c_disable(state);
- if (retval < 0) {
- dprintk("%s: read not successful\n", __FUNCTION__);
- return retval;
+ device_type[7] = dst_check_sum(device_type, 7);
+
+ if (write_dst(state, device_type, FIXED_COMM))
+ return -1; /* Write failed */
+
+ if ((dst_pio_disable(state)) < 0)
+ return -1;
+
+ if (read_dst(state, &reply, GET_ACK))
+ return -1; /* Read failure */
+
+ if (reply != ACK) {
+ dprintk("%s: Write not Acknowledged! [Reply=0x%02x]\n", __FUNCTION__, reply);
+ return -1; /* Unack'd write */
}
- if (rxbuf[7] != dst_check_sum(rxbuf, 7)) {
- dprintk("%s: checksum failure\n", __FUNCTION__);
- return retval;
+
+ if (!dst_wait_dst_ready(state, DEVICE_INIT))
+ return -1; /* DST not ready yet */
+
+ if (read_dst(state, state->rxbuffer, FIXED_COMM))
+ return -1;
+
+ dst_pio_disable(state);
+
+ if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) {
+ dprintk("%s: Checksum failure! \n", __FUNCTION__);
+ return -1; /* Checksum failure */
}
- rxbuf[7] = '\0';
- for (i = 0, dsp = &dst_tlist[0]; i < sizeof(dst_tlist) / sizeof(dst_tlist[0]); i++, dsp++) {
- if (!strncmp(&rxbuf[dsp->offs], dsp->mstr, strlen(dsp->mstr))) {
- use_type_flags = dsp->type_flags;
- use_dst_type = dsp->dst_type;
- printk("%s: recognize %s\n", __FUNCTION__, dsp->mstr);
+
+ state->rxbuffer[7] = '\0';
+
+ for (i = 0, p_dst_type = dst_tlist; i < ARRAY_SIZE (dst_tlist); i++, p_dst_type++) {
+ if (!strncmp (&state->rxbuffer[p_dst_type->offset], p_dst_type->device_id, strlen (p_dst_type->device_id))) {
+ use_type_flags = p_dst_type->type_flags;
+ use_dst_type = p_dst_type->dst_type;
+
+ /* Card capabilities */
+ state->dst_hw_cap = p_dst_type->dst_feature;
+ printk ("%s: Recognise [%s]\n", __FUNCTION__, p_dst_type->device_id);
+
break;
}
}
- if (i >= sizeof(dst_tlist) / sizeof(dst_tlist[0])) {
- printk("%s: unable to recognize %s or %s\n", __FUNCTION__, &rxbuf[0], &rxbuf[1]);
- printk("%s please email linux-dvb@linuxtv.org with this type in\n", __FUNCTION__);
+
+ if (i >= sizeof (dst_tlist) / sizeof (dst_tlist [0])) {
+ printk("%s: Unable to recognize %s or %s\n", __FUNCTION__, &state->rxbuffer[0], &state->rxbuffer[1]);
+ printk("%s: please email linux-dvb@linuxtv.org with this type in\n", __FUNCTION__);
use_dst_type = DST_TYPE_IS_SAT;
use_type_flags = DST_TYPE_HAS_SYMDIV;
}
- dst_type_print(use_dst_type);
+ dst_type_print(use_dst_type);
state->type_flags = use_type_flags;
state->dst_type = use_dst_type;
dst_type_flags_print(state->type_flags);
@@ -559,50 +771,102 @@ static int dst_check_ci(struct dst_state *state)
if (state->type_flags & DST_TYPE_HAS_TS204) {
dst_packsize(state, 204);
}
+
return 0;
}
-static int dst_command(struct dst_state* state, u8 * data, u8 len)
+static int dst_probe(struct dst_state *state)
+{
+ if ((rdc_8820_reset(state)) < 0) {
+ dprintk("%s: RDC 8820 RESET Failed.\n", __FUNCTION__);
+ return -1;
+ }
+ if (dst_addons & DST_TYPE_HAS_CA)
+ msleep(4000);
+ else
+ msleep(100);
+
+ if ((dst_comm_init(state)) < 0) {
+ dprintk("%s: DST Initialization Failed.\n", __FUNCTION__);
+ return -1;
+ }
+ msleep(100);
+ if (dst_get_device_id(state) < 0) {
+ dprintk("%s: unknown device.\n", __FUNCTION__);
+ return -1;
+ }
+
+ return 0;
+}
+
+int dst_command(struct dst_state* state, u8 * data, u8 len)
{
- int retval;
u8 reply;
+ if ((dst_comm_init(state)) < 0) {
+ dprintk("%s: DST Communication Initialization Failed.\n", __FUNCTION__);
+ return -1;
+ }
- dst_i2c_enable(state);
- dst_reset8820(state);
- retval = write_dst(state, data, len);
- if (retval < 0) {
- dst_i2c_disable(state);
- dprintk("%s: write not successful\n", __FUNCTION__);
- return retval;
+ if (write_dst(state, data, len)) {
+ if (verbose > 1)
+ dprintk("%s: Tring to recover.. \n", __FUNCTION__);
+ if ((dst_error_recovery(state)) < 0) {
+ dprintk("%s: Recovery Failed.\n", __FUNCTION__);
+ return -1;
+ }
+ return -1;
}
- msleep(33);
- retval = read_dst(state, &reply, 1);
- dst_i2c_disable(state);
- if (retval < 0) {
- dprintk("%s: read verify not successful\n", __FUNCTION__);
- return retval;
+ if ((dst_pio_disable(state)) < 0) {
+ dprintk("%s: PIO Disable Failed.\n", __FUNCTION__);
+ return -1;
}
- if (reply != 0xff) {
- dprintk("%s: write reply not 0xff 0x%02x \n", __FUNCTION__, reply);
- return 0;
+ if (state->type_flags & DST_TYPE_HAS_FW_1)
+ udelay(3000);
+
+ if (read_dst(state, &reply, GET_ACK)) {
+ if (verbose > 1)
+ dprintk("%s: Trying to recover.. \n", __FUNCTION__);
+ if ((dst_error_recovery(state)) < 0) {
+ dprintk("%s: Recovery Failed.\n", __FUNCTION__);
+ return -1;
+ }
+ return -1;
+ }
+
+ if (reply != ACK) {
+ dprintk("%s: write not acknowledged 0x%02x \n", __FUNCTION__, reply);
+ return -1;
}
if (len >= 2 && data[0] == 0 && (data[1] == 1 || data[1] == 3))
return 0;
- if (!dst_wait_dst_ready(state))
- return 0;
- // dst_i2c_enable(i2c); Per dimitri
- retval = read_dst(state, state->rxbuffer, 8);
- dst_i2c_disable(state);
- if (retval < 0) {
- dprintk("%s: read not successful\n", __FUNCTION__);
- return 0;
+
+// udelay(3000);
+ if (state->type_flags & DST_TYPE_HAS_FW_1)
+ udelay(3000);
+ else
+ udelay(2000);
+
+ if (!dst_wait_dst_ready(state, NO_DELAY))
+ return -1;
+
+ if (read_dst(state, state->rxbuffer, FIXED_COMM)) {
+ if (verbose > 1)
+ dprintk("%s: Trying to recover.. \n", __FUNCTION__);
+ if ((dst_error_recovery(state)) < 0) {
+ dprintk("%s: Recovery failed.\n", __FUNCTION__);
+ return -1;
+ }
+ return -1;
}
+
if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) {
dprintk("%s: checksum failure\n", __FUNCTION__);
- return 0;
+ return -1;
}
+
return 0;
}
+EXPORT_SYMBOL(dst_command);
static int dst_get_signal(struct dst_state* state)
{
@@ -642,37 +906,38 @@ static int dst_tone_power_cmd(struct dst_state* state)
if (state->dst_type == DST_TYPE_IS_TERR)
return 0;
- if (state->voltage == SEC_VOLTAGE_OFF)
- paket[4] = 0;
- else
- paket[4] = 1;
- if (state->tone == SEC_TONE_ON)
- paket[2] = state->k22;
- else
- paket[2] = 0;
- paket[7] = dst_check_sum(&paket[0], 7);
+ paket[4] = state->tx_tuna[4];
+ paket[2] = state->tx_tuna[2];
+ paket[3] = state->tx_tuna[3];
+ paket[7] = dst_check_sum (paket, 7);
dst_command(state, paket, 8);
+
return 0;
}
static int dst_get_tuna(struct dst_state* state)
{
int retval;
+
if ((state->diseq_flags & ATTEMPT_TUNE) == 0)
return 0;
+
state->diseq_flags &= ~(HAS_LOCK);
- if (!dst_wait_dst_ready(state))
+ if (!dst_wait_dst_ready(state, NO_DELAY))
return 0;
+
if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
/* how to get variable length reply ???? */
retval = read_dst(state, state->rx_tuna, 10);
} else {
- retval = read_dst(state, &state->rx_tuna[2], 8);
+ retval = read_dst(state, &state->rx_tuna[2], FIXED_COMM);
}
+
if (retval < 0) {
dprintk("%s: read not successful\n", __FUNCTION__);
return 0;
}
+
if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) {
dprintk("%s: checksum failure?\n", __FUNCTION__);
@@ -705,11 +970,13 @@ static int dst_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage);
static int dst_write_tuna(struct dvb_frontend* fe)
{
- struct dst_state* state = (struct dst_state*) fe->demodulator_priv;
+ struct dst_state* state = fe->demodulator_priv;
int retval;
u8 reply;
- dprintk("%s: type_flags 0x%x \n", __FUNCTION__, state->type_flags);
+ if (debug > 4)
+ dprintk("%s: type_flags 0x%x \n", __FUNCTION__, state->type_flags);
+
state->decode_freq = 0;
state->decode_lock = state->decode_strength = state->decode_snr = 0;
if (state->dst_type == DST_TYPE_IS_SAT) {
@@ -717,32 +984,41 @@ static int dst_write_tuna(struct dvb_frontend* fe)
dst_set_voltage(fe, SEC_VOLTAGE_13);
}
state->diseq_flags &= ~(HAS_LOCK | ATTEMPT_TUNE);
- dst_i2c_enable(state);
+
+ if ((dst_comm_init(state)) < 0) {
+ dprintk("%s: DST Communication initialization failed.\n", __FUNCTION__);
+ return -1;
+ }
+
if (state->type_flags & DST_TYPE_HAS_NEWTUNE) {
- dst_reset8820(state);
state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[0], 9);
retval = write_dst(state, &state->tx_tuna[0], 10);
+
} else {
state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[2], 7);
- retval = write_dst(state, &state->tx_tuna[2], 8);
+ retval = write_dst(state, &state->tx_tuna[2], FIXED_COMM);
}
if (retval < 0) {
- dst_i2c_disable(state);
+ dst_pio_disable(state);
dprintk("%s: write not successful\n", __FUNCTION__);
return retval;
}
- msleep(3);
- retval = read_dst(state, &reply, 1);
- dst_i2c_disable(state);
- if (retval < 0) {
- dprintk("%s: read verify not successful\n", __FUNCTION__);
- return retval;
+
+ if ((dst_pio_disable(state)) < 0) {
+ dprintk("%s: DST PIO disable failed !\n", __FUNCTION__);
+ return -1;
}
- if (reply != 0xff) {
- dprintk("%s: write reply not 0xff 0x%02x \n", __FUNCTION__, reply);
+
+ if ((read_dst(state, &reply, GET_ACK) < 0)) {
+ dprintk("%s: read verify not successful.\n", __FUNCTION__);
+ return -1;
+ }
+ if (reply != ACK) {
+ dprintk("%s: write not acknowledged 0x%02x \n", __FUNCTION__, reply);
return 0;
}
state->diseq_flags |= ATTEMPT_TUNE;
+
return dst_get_tuna(state);
}
@@ -762,10 +1038,10 @@ static int dst_write_tuna(struct dvb_frontend* fe)
static int dst_set_diseqc(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd)
{
- struct dst_state* state = (struct dst_state*) fe->demodulator_priv;
+ struct dst_state* state = fe->demodulator_priv;
u8 paket[8] = { 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec };
- if (state->dst_type == DST_TYPE_IS_TERR)
+ if (state->dst_type != DST_TYPE_IS_SAT)
return 0;
if (cmd->msg_len == 0 || cmd->msg_len > 4)
@@ -778,73 +1054,91 @@ static int dst_set_diseqc(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd*
static int dst_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
{
- u8 *val;
int need_cmd;
- struct dst_state* state = (struct dst_state*) fe->demodulator_priv;
+ struct dst_state* state = fe->demodulator_priv;
state->voltage = voltage;
- if (state->dst_type == DST_TYPE_IS_TERR)
+ if (state->dst_type != DST_TYPE_IS_SAT)
return 0;
need_cmd = 0;
- val = &state->tx_tuna[0];
- val[8] &= ~0x40;
switch (voltage) {
- case SEC_VOLTAGE_13:
- if ((state->diseq_flags & HAS_POWER) == 0)
- need_cmd = 1;
- state->diseq_flags |= HAS_POWER;
- break;
- case SEC_VOLTAGE_18:
- if ((state->diseq_flags & HAS_POWER) == 0)
+ case SEC_VOLTAGE_13:
+ case SEC_VOLTAGE_18:
+ if ((state->diseq_flags & HAS_POWER) == 0)
+ need_cmd = 1;
+ state->diseq_flags |= HAS_POWER;
+ state->tx_tuna[4] = 0x01;
+ break;
+
+ case SEC_VOLTAGE_OFF:
need_cmd = 1;
- state->diseq_flags |= HAS_POWER;
- val[8] |= 0x40;
- break;
- case SEC_VOLTAGE_OFF:
- need_cmd = 1;
- state->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE);
- break;
- default:
- return -EINVAL;
+ state->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE);
+ state->tx_tuna[4] = 0x00;
+ break;
+
+ default:
+ return -EINVAL;
}
- if (need_cmd) {
+ if (need_cmd)
dst_tone_power_cmd(state);
- }
+
return 0;
}
static int dst_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
{
- u8 *val;
- struct dst_state* state = (struct dst_state*) fe->demodulator_priv;
+ struct dst_state* state = fe->demodulator_priv;
state->tone = tone;
- if (state->dst_type == DST_TYPE_IS_TERR)
+ if (state->dst_type != DST_TYPE_IS_SAT)
return 0;
- val = &state->tx_tuna[0];
+ switch (tone) {
+ case SEC_TONE_OFF:
+ state->tx_tuna[2] = 0xff;
+ break;
- val[8] &= ~0x1;
+ case SEC_TONE_ON:
+ state->tx_tuna[2] = 0x02;
+ break;
- switch (tone) {
- case SEC_TONE_OFF:
- break;
- case SEC_TONE_ON:
- val[8] |= 1;
- break;
- default:
- return -EINVAL;
+ default:
+ return -EINVAL;
}
dst_tone_power_cmd(state);
+
+ return 0;
+}
+
+static int dst_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t minicmd)
+{
+ struct dst_state *state = fe->demodulator_priv;
+
+ if (state->dst_type != DST_TYPE_IS_SAT)
+ return 0;
+
+ state->minicmd = minicmd;
+
+ switch (minicmd) {
+ case SEC_MINI_A:
+ state->tx_tuna[3] = 0x02;
+ break;
+ case SEC_MINI_B:
+ state->tx_tuna[3] = 0xff;
+ break;
+ }
+ dst_tone_power_cmd(state);
+
return 0;
}
+
static int dst_init(struct dvb_frontend* fe)
{
- struct dst_state* state = (struct dst_state*) fe->demodulator_priv;
+ struct dst_state* state = fe->demodulator_priv;
static u8 ini_satci_tuna[] = { 9, 0, 3, 0xb6, 1, 0, 0x73, 0x21, 0, 0 };
static u8 ini_satfta_tuna[] = { 0, 0, 3, 0xb6, 1, 0x55, 0xbd, 0x50, 0, 0 };
static u8 ini_tvfta_tuna[] = { 0, 0, 3, 0xb6, 1, 7, 0x0, 0x0, 0, 0 };
@@ -876,7 +1170,7 @@ static int dst_init(struct dvb_frontend* fe)
static int dst_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
- struct dst_state* state = (struct dst_state*) fe->demodulator_priv;
+ struct dst_state* state = fe->demodulator_priv;
*status = 0;
if (state->diseq_flags & HAS_LOCK) {
@@ -890,7 +1184,7 @@ static int dst_read_status(struct dvb_frontend* fe, fe_status_t* status)
static int dst_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
- struct dst_state* state = (struct dst_state*) fe->demodulator_priv;
+ struct dst_state* state = fe->demodulator_priv;
dst_get_signal(state);
*strength = state->decode_strength;
@@ -900,7 +1194,7 @@ static int dst_read_signal_strength(struct dvb_frontend* fe, u16* strength)
static int dst_read_snr(struct dvb_frontend* fe, u16* snr)
{
- struct dst_state* state = (struct dst_state*) fe->demodulator_priv;
+ struct dst_state* state = fe->demodulator_priv;
dst_get_signal(state);
*snr = state->decode_snr;
@@ -910,13 +1204,19 @@ static int dst_read_snr(struct dvb_frontend* fe, u16* snr)
static int dst_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
- struct dst_state* state = (struct dst_state*) fe->demodulator_priv;
+ struct dst_state* state = fe->demodulator_priv;
dst_set_freq(state, p->frequency);
+ if (verbose > 4)
+ dprintk("Set Frequency = [%d]\n", p->frequency);
+
dst_set_inversion(state, p->inversion);
if (state->dst_type == DST_TYPE_IS_SAT) {
dst_set_fec(state, p->u.qpsk.fec_inner);
dst_set_symbolrate(state, p->u.qpsk.symbol_rate);
+ if (verbose > 4)
+ dprintk("Set Symbolrate = [%d]\n", p->u.qpsk.symbol_rate);
+
} else if (state->dst_type == DST_TYPE_IS_TERR) {
dst_set_bandwidth(state, p->u.ofdm.bandwidth);
} else if (state->dst_type == DST_TYPE_IS_CABLE) {
@@ -930,7 +1230,7 @@ static int dst_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_paramet
static int dst_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
- struct dst_state* state = (struct dst_state*) fe->demodulator_priv;
+ struct dst_state* state = fe->demodulator_priv;
p->frequency = state->decode_freq;
p->inversion = state->inversion;
@@ -950,7 +1250,7 @@ static int dst_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_paramet
static void dst_release(struct dvb_frontend* fe)
{
- struct dst_state* state = (struct dst_state*) fe->demodulator_priv;
+ struct dst_state* state = fe->demodulator_priv;
kfree(state);
}
@@ -958,50 +1258,47 @@ static struct dvb_frontend_ops dst_dvbt_ops;
static struct dvb_frontend_ops dst_dvbs_ops;
static struct dvb_frontend_ops dst_dvbc_ops;
-struct dvb_frontend* dst_attach(const struct dst_config* config,
- struct i2c_adapter* i2c,
- struct bt878 *bt)
+struct dst_state* dst_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter)
{
- struct dst_state* state = NULL;
-
- /* allocate memory for the internal state */
- state = (struct dst_state*) kmalloc(sizeof(struct dst_state), GFP_KERNEL);
- if (state == NULL) goto error;
- /* setup the state */
- state->config = config;
- state->i2c = i2c;
- state->bt = bt;
-
- /* check if the demod is there */
- if (dst_check_ci(state) < 0) goto error;
+ /* check if the ASIC is there */
+ if (dst_probe(state) < 0) {
+ if (state)
+ kfree(state);
+ return NULL;
+ }
/* determine settings based on type */
switch (state->dst_type) {
case DST_TYPE_IS_TERR:
memcpy(&state->ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops));
break;
+
case DST_TYPE_IS_CABLE:
memcpy(&state->ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops));
break;
+
case DST_TYPE_IS_SAT:
memcpy(&state->ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops));
break;
+
default:
- printk("dst: unknown frontend type. please report to the LinuxTV.org DVB mailinglist.\n");
- goto error;
+ printk("%s: unknown DST type. please report to the LinuxTV.org DVB mailinglist.\n", __FUNCTION__);
+ if (state)
+ kfree(state);
+
+ return NULL;
}
/* create dvb_frontend */
state->frontend.ops = &state->ops;
state->frontend.demodulator_priv = state;
- return &state->frontend;
-error:
- kfree(state);
- return NULL;
+ return state; /* Manu (DST is a card not a frontend) */
}
+EXPORT_SYMBOL(dst_attach);
+
static struct dvb_frontend_ops dst_dvbt_ops = {
.info = {
@@ -1051,6 +1348,7 @@ static struct dvb_frontend_ops dst_dvbs_ops = {
.read_signal_strength = dst_read_signal_strength,
.read_snr = dst_read_snr,
+ .diseqc_send_burst = dst_send_burst,
.diseqc_send_master_cmd = dst_set_diseqc,
.set_voltage = dst_set_voltage,
.set_tone = dst_set_tone,
@@ -1082,8 +1380,7 @@ static struct dvb_frontend_ops dst_dvbc_ops = {
.read_snr = dst_read_snr,
};
+
MODULE_DESCRIPTION("DST DVB-S/T/C Combo Frontend driver");
-MODULE_AUTHOR("Jamie Honan");
+MODULE_AUTHOR("Jamie Honan, Manu Abraham");
MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(dst_attach);
diff --git a/drivers/media/dvb/bt8xx/dst.h b/drivers/media/dvb/bt8xx/dst.h
deleted file mode 100644
index bcb418c5c12..00000000000
--- a/drivers/media/dvb/bt8xx/dst.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- Frontend-driver for TwinHan DST Frontend
-
- Copyright (C) 2003 Jamie Honan
-
- 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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#ifndef DST_H
-#define DST_H
-
-#include <linux/dvb/frontend.h>
-#include <linux/device.h>
-#include "bt878.h"
-
-struct dst_config
-{
- /* the demodulator's i2c address */
- u8 demod_address;
-};
-
-extern struct dvb_frontend* dst_attach(const struct dst_config* config,
- struct i2c_adapter* i2c,
- struct bt878 *bt);
-
-#endif // DST_H
diff --git a/drivers/media/dvb/bt8xx/dst_ca.c b/drivers/media/dvb/bt8xx/dst_ca.c
new file mode 100644
index 00000000000..d781504cc2f
--- /dev/null
+++ b/drivers/media/dvb/bt8xx/dst_ca.c
@@ -0,0 +1,861 @@
+/*
+ CA-driver for TwinHan DST Frontend/Card
+
+ Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <linux/dvb/ca.h>
+#include "dvbdev.h"
+#include "dvb_frontend.h"
+
+#include "dst_ca.h"
+#include "dst_common.h"
+
+static unsigned int verbose = 1;
+module_param(verbose, int, 0644);
+MODULE_PARM_DESC(verbose, "verbose startup messages, default is 1 (yes)");
+
+static unsigned int debug = 1;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "debug messages, default is 1 (yes)");
+
+#define dprintk if (debug) printk
+
+/* Need some more work */
+static int ca_set_slot_descr(void)
+{
+ /* We could make this more graceful ? */
+ return -EOPNOTSUPP;
+}
+
+/* Need some more work */
+static int ca_set_pid(void)
+{
+ /* We could make this more graceful ? */
+ return -EOPNOTSUPP;
+}
+
+
+static int put_checksum(u8 *check_string, int length)
+{
+ u8 i = 0, checksum = 0;
+
+ if (verbose > 3) {
+ dprintk("%s: ========================= Checksum calculation ===========================\n", __FUNCTION__);
+ dprintk("%s: String Length=[0x%02x]\n", __FUNCTION__, length);
+
+ dprintk("%s: String=[", __FUNCTION__);
+ }
+ while (i < length) {
+ if (verbose > 3)
+ dprintk(" %02x", check_string[i]);
+ checksum += check_string[i];
+ i++;
+ }
+ if (verbose > 3) {
+ dprintk(" ]\n");
+ dprintk("%s: Sum=[%02x]\n", __FUNCTION__, checksum);
+ }
+ check_string[length] = ~checksum + 1;
+ if (verbose > 3) {
+ dprintk("%s: Checksum=[%02x]\n", __FUNCTION__, check_string[length]);
+ dprintk("%s: ==========================================================================\n", __FUNCTION__);
+ }
+
+ return 0;
+}
+
+static int dst_ci_command(struct dst_state* state, u8 * data, u8 *ca_string, u8 len, int read)
+{
+ u8 reply;
+
+ dst_comm_init(state);
+ msleep(65);
+
+ if (write_dst(state, data, len)) {
+ dprintk("%s: Write not successful, trying to recover\n", __FUNCTION__);
+ dst_error_recovery(state);
+ return -1;
+ }
+
+ if ((dst_pio_disable(state)) < 0) {
+ dprintk("%s: DST PIO disable failed.\n", __FUNCTION__);
+ return -1;
+ }
+
+ if (read_dst(state, &reply, GET_ACK) < 0) {
+ dprintk("%s: Read not successful, trying to recover\n", __FUNCTION__);
+ dst_error_recovery(state);
+ return -1;
+ }
+
+ if (read) {
+ if (! dst_wait_dst_ready(state, LONG_DELAY)) {
+ dprintk("%s: 8820 not ready\n", __FUNCTION__);
+ return -1;
+ }
+
+ if (read_dst(state, ca_string, 128) < 0) { /* Try to make this dynamic */
+ dprintk("%s: Read not successful, trying to recover\n", __FUNCTION__);
+ dst_error_recovery(state);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
+static int dst_put_ci(struct dst_state *state, u8 *data, int len, u8 *ca_string, int read)
+{
+ u8 dst_ca_comm_err = 0;
+
+ while (dst_ca_comm_err < RETRIES) {
+ dst_comm_init(state);
+ if (verbose > 2)
+ dprintk("%s: Put Command\n", __FUNCTION__);
+ if (dst_ci_command(state, data, ca_string, len, read)) { // If error
+ dst_error_recovery(state);
+ dst_ca_comm_err++; // work required here.
+ }
+ break;
+ }
+
+ return 0;
+}
+
+
+
+static int ca_get_app_info(struct dst_state *state)
+{
+ static u8 command[8] = {0x07, 0x40, 0x01, 0x00, 0x01, 0x00, 0x00, 0xff};
+
+ put_checksum(&command[0], command[0]);
+ if ((dst_put_ci(state, command, sizeof(command), state->messages, GET_REPLY)) < 0) {
+ dprintk("%s: -->dst_put_ci FAILED !\n", __FUNCTION__);
+ return -1;
+ }
+ if (verbose > 1) {
+ dprintk("%s: -->dst_put_ci SUCCESS !\n", __FUNCTION__);
+
+ dprintk("%s: ================================ CI Module Application Info ======================================\n", __FUNCTION__);
+ dprintk("%s: Application Type=[%d], Application Vendor=[%d], Vendor Code=[%d]\n%s: Application info=[%s]\n",
+ __FUNCTION__, state->messages[7], (state->messages[8] << 8) | state->messages[9],
+ (state->messages[10] << 8) | state->messages[11], __FUNCTION__, (char *)(&state->messages[12]));
+ dprintk("%s: ==================================================================================================\n", __FUNCTION__);
+ }
+
+ return 0;
+}
+
+static int ca_get_slot_caps(struct dst_state *state, struct ca_caps *p_ca_caps, void *arg)
+{
+ int i;
+ u8 slot_cap[256];
+ static u8 slot_command[8] = {0x07, 0x40, 0x02, 0x00, 0x02, 0x00, 0x00, 0xff};
+
+ put_checksum(&slot_command[0], slot_command[0]);
+ if ((dst_put_ci(state, slot_command, sizeof (slot_command), slot_cap, GET_REPLY)) < 0) {
+ dprintk("%s: -->dst_put_ci FAILED !\n", __FUNCTION__);
+ return -1;
+ }
+ if (verbose > 1)
+ dprintk("%s: -->dst_put_ci SUCCESS !\n", __FUNCTION__);
+
+ /* Will implement the rest soon */
+
+ if (verbose > 1) {
+ dprintk("%s: Slot cap = [%d]\n", __FUNCTION__, slot_cap[7]);
+ dprintk("===================================\n");
+ for (i = 0; i < 8; i++)
+ dprintk(" %d", slot_cap[i]);
+ dprintk("\n");
+ }
+
+ p_ca_caps->slot_num = 1;
+ p_ca_caps->slot_type = 1;
+ p_ca_caps->descr_num = slot_cap[7];
+ p_ca_caps->descr_type = 1;
+
+
+ if (copy_to_user((struct ca_caps *)arg, p_ca_caps, sizeof (struct ca_caps))) {
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+/* Need some more work */
+static int ca_get_slot_descr(struct dst_state *state, struct ca_msg *p_ca_message, void *arg)
+{
+ return -EOPNOTSUPP;
+}
+
+
+static int ca_get_slot_info(struct dst_state *state, struct ca_slot_info *p_ca_slot_info, void *arg)
+{
+ int i;
+ static u8 slot_command[8] = {0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff};
+
+ u8 *slot_info = state->rxbuffer;
+
+ put_checksum(&slot_command[0], 7);
+ if ((dst_put_ci(state, slot_command, sizeof (slot_command), slot_info, GET_REPLY)) < 0) {
+ dprintk("%s: -->dst_put_ci FAILED !\n", __FUNCTION__);
+ return -1;
+ }
+ if (verbose > 1)
+ dprintk("%s: -->dst_put_ci SUCCESS !\n", __FUNCTION__);
+
+ /* Will implement the rest soon */
+
+ if (verbose > 1) {
+ dprintk("%s: Slot info = [%d]\n", __FUNCTION__, slot_info[3]);
+ dprintk("===================================\n");
+ for (i = 0; i < 8; i++)
+ dprintk(" %d", slot_info[i]);
+ dprintk("\n");
+ }
+
+ if (slot_info[4] & 0x80) {
+ p_ca_slot_info->flags = CA_CI_MODULE_PRESENT;
+ p_ca_slot_info->num = 1;
+ p_ca_slot_info->type = CA_CI;
+ }
+ else if (slot_info[4] & 0x40) {
+ p_ca_slot_info->flags = CA_CI_MODULE_READY;
+ p_ca_slot_info->num = 1;
+ p_ca_slot_info->type = CA_CI;
+ }
+ else {
+ p_ca_slot_info->flags = 0;
+ }
+
+ if (copy_to_user((struct ca_slot_info *)arg, p_ca_slot_info, sizeof (struct ca_slot_info))) {
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+
+
+
+static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message, void *arg)
+{
+ u8 i = 0;
+ u32 command = 0;
+
+ if (copy_from_user(p_ca_message, (void *)arg, sizeof (struct ca_msg)))
+ return -EFAULT;
+
+
+ if (p_ca_message->msg) {
+ if (verbose > 3)
+ dprintk("Message = [%02x %02x %02x]\n", p_ca_message->msg[0], p_ca_message->msg[1], p_ca_message->msg[2]);
+
+ for (i = 0; i < 3; i++) {
+ command = command | p_ca_message->msg[i];
+ if (i < 2)
+ command = command << 8;
+ }
+ if (verbose > 3)
+ dprintk("%s:Command=[0x%x]\n", __FUNCTION__, command);
+
+ switch (command) {
+ case CA_APP_INFO:
+ memcpy(p_ca_message->msg, state->messages, 128);
+ if (copy_to_user((void *)arg, p_ca_message, sizeof (struct ca_msg)) )
+ return -EFAULT;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int handle_en50221_tag(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer)
+{
+ if (state->dst_hw_cap & DST_TYPE_HAS_SESSION) {
+ hw_buffer->msg[2] = p_ca_message->msg[1]; /* MSB */
+ hw_buffer->msg[3] = p_ca_message->msg[2]; /* LSB */
+ }
+ else {
+ hw_buffer->msg[2] = 0x03;
+ hw_buffer->msg[3] = 0x00;
+ }
+ return 0;
+}
+
+static int debug_8820_buffer(struct ca_msg *hw_buffer)
+{
+ unsigned int i;
+
+ dprintk("%s:Debug=[", __FUNCTION__);
+ for (i = 0; i < (hw_buffer->msg[0] + 1); i++)
+ dprintk(" %02x", hw_buffer->msg[i]);
+ dprintk("]\n");
+
+ return 0;
+}
+
+static int write_to_8820(struct dst_state *state, struct ca_msg *hw_buffer, u8 reply)
+{
+ if ((dst_put_ci(state, hw_buffer->msg, (hw_buffer->length + 1), hw_buffer->msg, reply)) < 0) {
+ dprintk("%s: DST-CI Command failed.\n", __FUNCTION__);
+ dprintk("%s: Resetting DST.\n", __FUNCTION__);
+ rdc_reset_state(state);
+ return -1;
+ }
+ if (verbose > 2)
+ dprintk("%s: DST-CI Command succes.\n", __FUNCTION__);
+
+ return 0;
+}
+
+
+static int ca_set_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer, u8 reply, u8 query)
+{
+ u32 hw_offset, buf_offset, i, k;
+ u32 program_info_length = 0, es_info_length = 0, length = 0, words = 0;
+ u8 found_prog_ca_desc = 0, found_stream_ca_desc = 0, error_condition = 0, hw_buffer_length = 0;
+
+ if (verbose > 3)
+ dprintk("%s, p_ca_message length %d (0x%x)\n", __FUNCTION__,p_ca_message->length,p_ca_message->length );
+
+ handle_en50221_tag(state, p_ca_message, hw_buffer); /* EN50221 tag */
+
+ /* Handle the length field (variable) */
+ if (!(p_ca_message->msg[3] & 0x80)) { /* Length = 1 */
+ length = p_ca_message->msg[3] & 0x7f;
+ words = 0; /* domi's suggestion */
+ }
+ else { /* Length = words */
+ words = p_ca_message->msg[3] & 0x7f;
+ for (i = 0; i < words; i++) {
+ length = length << 8;
+ length = length | p_ca_message->msg[4 + i];
+ }
+ }
+ if (verbose > 4) {
+ dprintk("%s:Length=[%d (0x%x)], Words=[%d]\n", __FUNCTION__, length,length, words);
+
+ /* Debug Input string */
+ for (i = 0; i < length; i++)
+ dprintk(" %02x", p_ca_message->msg[i]);
+ dprintk("]\n");
+ }
+
+ hw_offset = 7;
+ buf_offset = words + 4;
+
+ /* Program Header */
+ if (verbose > 4)
+ dprintk("\n%s:Program Header=[", __FUNCTION__);
+ for (i = 0; i < 6; i++) {
+ hw_buffer->msg[hw_offset] = p_ca_message->msg[buf_offset];
+ if (verbose > 4)
+ dprintk(" %02x", p_ca_message->msg[buf_offset]);
+ hw_offset++, buf_offset++, hw_buffer_length++;
+ }
+ if (verbose > 4)
+ dprintk("]\n");
+
+ program_info_length = 0;
+ program_info_length = (((program_info_length | p_ca_message->msg[words + 8]) & 0x0f) << 8) | p_ca_message->msg[words + 9];
+ if (verbose > 4)
+ dprintk("%s:Program info Length=[%d][%02x], hw_offset=[%d], buf_offset=[%d] \n",
+ __FUNCTION__, program_info_length, program_info_length, hw_offset, buf_offset);
+
+ if (program_info_length && (program_info_length < 256)) { /* If program_info_length */
+ hw_buffer->msg[11] = hw_buffer->msg[11] & 0x0f; /* req only 4 bits */
+ hw_buffer->msg[12] = hw_buffer->msg[12] + 1; /* increment! ASIC bug! */
+
+ if (p_ca_message->msg[buf_offset + 1] == 0x09) { /* Check CA descriptor */
+ found_prog_ca_desc = 1;
+ if (verbose > 4)
+ dprintk("%s: Found CA descriptor @ Program level\n", __FUNCTION__);
+ }
+
+ if (found_prog_ca_desc) { /* Command only if CA descriptor */
+ hw_buffer->msg[13] = p_ca_message->msg[buf_offset]; /* CA PMT command ID */
+ hw_offset++, buf_offset++, hw_buffer_length++;
+ }
+
+ /* Program descriptors */
+ if (verbose > 4) {
+ dprintk("%s:**********>buf_offset=[%d], hw_offset=[%d]\n", __FUNCTION__, buf_offset, hw_offset);
+ dprintk("%s:Program descriptors=[", __FUNCTION__);
+ }
+ while (program_info_length && !error_condition) { /* Copy prog descriptors */
+ if (program_info_length > p_ca_message->length) { /* Error situation */
+ dprintk ("%s:\"WARNING\" Length error, line=[%d], prog_info_length=[%d]\n",
+ __FUNCTION__, __LINE__, program_info_length);
+ dprintk("%s:\"WARNING\" Bailing out of possible loop\n", __FUNCTION__);
+ error_condition = 1;
+ break;
+ }
+
+ hw_buffer->msg[hw_offset] = p_ca_message->msg[buf_offset];
+ dprintk(" %02x", p_ca_message->msg[buf_offset]);
+ hw_offset++, buf_offset++, hw_buffer_length++, program_info_length--;
+ }
+ if (verbose > 4) {
+ dprintk("]\n");
+ dprintk("%s:**********>buf_offset=[%d], hw_offset=[%d]\n", __FUNCTION__, buf_offset, hw_offset);
+ }
+ if (found_prog_ca_desc) {
+ if (!reply) {
+ hw_buffer->msg[13] = 0x01; /* OK descrambling */
+ if (verbose > 1)
+ dprintk("CA PMT Command = OK Descrambling\n");
+ }
+ else {
+ hw_buffer->msg[13] = 0x02; /* Ok MMI */
+ if (verbose > 1)
+ dprintk("CA PMT Command = Ok MMI\n");
+ }
+ if (query) {
+ hw_buffer->msg[13] = 0x03; /* Query */
+ if (verbose > 1)
+ dprintk("CA PMT Command = CA PMT query\n");
+ }
+ }
+ }
+ else {
+ hw_buffer->msg[11] = hw_buffer->msg[11] & 0xf0; /* Don't write to ASIC */
+ hw_buffer->msg[12] = hw_buffer->msg[12] = 0x00;
+ }
+ if (verbose > 4)
+ dprintk("%s:**********>p_ca_message->length=[%d], buf_offset=[%d], hw_offset=[%d]\n",
+ __FUNCTION__, p_ca_message->length, buf_offset, hw_offset);
+
+ while ((buf_offset < p_ca_message->length) && !error_condition) {
+ /* Bail out in case of an indefinite loop */
+ if ((es_info_length > p_ca_message->length) || (buf_offset > p_ca_message->length)) {
+ dprintk("%s:\"WARNING\" Length error, line=[%d], prog_info_length=[%d], buf_offset=[%d]\n",
+ __FUNCTION__, __LINE__, program_info_length, buf_offset);
+
+ dprintk("%s:\"WARNING\" Bailing out of possible loop\n", __FUNCTION__);
+ error_condition = 1;
+ break;
+ }
+
+ /* Stream Header */
+
+ for (k = 0; k < 5; k++) {
+ hw_buffer->msg[hw_offset + k] = p_ca_message->msg[buf_offset + k];
+ }
+
+ es_info_length = 0;
+ es_info_length = (es_info_length | (p_ca_message->msg[buf_offset + 3] & 0x0f)) << 8 | p_ca_message->msg[buf_offset + 4];
+
+ if (verbose > 4) {
+ dprintk("\n%s:----->Stream header=[%02x %02x %02x %02x %02x]\n", __FUNCTION__,
+ p_ca_message->msg[buf_offset + 0], p_ca_message->msg[buf_offset + 1],
+ p_ca_message->msg[buf_offset + 2], p_ca_message->msg[buf_offset + 3],
+ p_ca_message->msg[buf_offset + 4]);
+
+ dprintk("%s:----->Stream type=[%02x], es length=[%d (0x%x)], Chars=[%02x] [%02x], buf_offset=[%d]\n", __FUNCTION__,
+ p_ca_message->msg[buf_offset + 0], es_info_length, es_info_length,
+ p_ca_message->msg[buf_offset + 3], p_ca_message->msg[buf_offset + 4], buf_offset);
+ }
+
+ hw_buffer->msg[hw_offset + 3] &= 0x0f; /* req only 4 bits */
+
+ if (found_prog_ca_desc) {
+ hw_buffer->msg[hw_offset + 3] = 0x00;
+ hw_buffer->msg[hw_offset + 4] = 0x00;
+ }
+
+ hw_offset += 5, buf_offset += 5, hw_buffer_length += 5;
+
+ /* Check for CA descriptor */
+ if (p_ca_message->msg[buf_offset + 1] == 0x09) {
+ if (verbose > 4)
+ dprintk("%s:Found CA descriptor @ Stream level\n", __FUNCTION__);
+ found_stream_ca_desc = 1;
+ }
+
+ /* ES descriptors */
+
+ if (es_info_length && !error_condition && !found_prog_ca_desc && found_stream_ca_desc) {
+// if (!ca_pmt_done) {
+ hw_buffer->msg[hw_offset] = p_ca_message->msg[buf_offset]; /* CA PMT cmd(es) */
+ if (verbose > 4)
+ printk("%s:----->CA PMT Command ID=[%02x]\n", __FUNCTION__, p_ca_message->msg[buf_offset]);
+// hw_offset++, buf_offset++, hw_buffer_length++, es_info_length--, ca_pmt_done = 1;
+ hw_offset++, buf_offset++, hw_buffer_length++, es_info_length--;
+// }
+ if (verbose > 4)
+ dprintk("%s:----->ES descriptors=[", __FUNCTION__);
+
+ while (es_info_length && !error_condition) { /* ES descriptors */
+ if ((es_info_length > p_ca_message->length) || (buf_offset > p_ca_message->length)) {
+ if (verbose > 4) {
+ dprintk("%s:\"WARNING\" ES Length error, line=[%d], es_info_length=[%d], buf_offset=[%d]\n",
+ __FUNCTION__, __LINE__, es_info_length, buf_offset);
+
+ dprintk("%s:\"WARNING\" Bailing out of possible loop\n", __FUNCTION__);
+ }
+ error_condition = 1;
+ break;
+ }
+
+ hw_buffer->msg[hw_offset] = p_ca_message->msg[buf_offset];
+ if (verbose > 3)
+ dprintk("%02x ", hw_buffer->msg[hw_offset]);
+ hw_offset++, buf_offset++, hw_buffer_length++, es_info_length--;
+ }
+ found_stream_ca_desc = 0; /* unset for new streams */
+ dprintk("]\n");
+ }
+ }
+
+ /* MCU Magic words */
+
+ hw_buffer_length += 7;
+ hw_buffer->msg[0] = hw_buffer_length;
+ hw_buffer->msg[1] = 64;
+ hw_buffer->msg[4] = 3;
+ hw_buffer->msg[5] = hw_buffer->msg[0] - 7;
+ hw_buffer->msg[6] = 0;
+
+
+ /* Fix length */
+ hw_buffer->length = hw_buffer->msg[0];
+
+ put_checksum(&hw_buffer->msg[0], hw_buffer->msg[0]);
+ /* Do the actual write */
+ if (verbose > 4) {
+ dprintk("%s:======================DEBUGGING================================\n", __FUNCTION__);
+ dprintk("%s: Actual Length=[%d]\n", __FUNCTION__, hw_buffer_length);
+ }
+ /* Only for debugging! */
+ if (verbose > 2)
+ debug_8820_buffer(hw_buffer);
+ if (verbose > 3)
+ dprintk("%s: Reply = [%d]\n", __FUNCTION__, reply);
+ write_to_8820(state, hw_buffer, reply);
+
+ return 0;
+}
+
+/* Board supports CA PMT reply ? */
+static int dst_check_ca_pmt(struct dst_state *state, struct ca_msg *p_ca_message, struct ca_msg *hw_buffer)
+{
+ int ca_pmt_reply_test = 0;
+
+ /* Do test board */
+ /* Not there yet but soon */
+
+
+ /* CA PMT Reply capable */
+ if (ca_pmt_reply_test) {
+ if ((ca_set_pmt(state, p_ca_message, hw_buffer, 1, GET_REPLY)) < 0) {
+ dprintk("%s: ca_set_pmt.. failed !\n", __FUNCTION__);
+ return -1;
+ }
+
+ /* Process CA PMT Reply */
+ /* will implement soon */
+ dprintk("%s: Not there yet\n", __FUNCTION__);
+ }
+ /* CA PMT Reply not capable */
+ if (!ca_pmt_reply_test) {
+ if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, NO_REPLY)) < 0) {
+ dprintk("%s: ca_set_pmt.. failed !\n", __FUNCTION__);
+ return -1;
+ }
+ if (verbose > 3)
+ dprintk("%s: ca_set_pmt.. success !\n", __FUNCTION__);
+ /* put a dummy message */
+
+ }
+ return 0;
+}
+
+static int ca_send_message(struct dst_state *state, struct ca_msg *p_ca_message, void *arg)
+{
+ int i = 0;
+ unsigned int ca_message_header_len;
+
+ u32 command = 0;
+ struct ca_msg *hw_buffer;
+
+ if ((hw_buffer = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
+ printk("%s: Memory allocation failure\n", __FUNCTION__);
+ return -ENOMEM;
+ }
+ if (verbose > 3)
+ dprintk("%s\n", __FUNCTION__);
+
+ if (copy_from_user(p_ca_message, (void *)arg, sizeof (struct ca_msg)))
+ return -EFAULT;
+
+ if (p_ca_message->msg) {
+ ca_message_header_len = p_ca_message->length; /* Restore it back when you are done */
+ /* EN50221 tag */
+ command = 0;
+
+ for (i = 0; i < 3; i++) {
+ command = command | p_ca_message->msg[i];
+ if (i < 2)
+ command = command << 8;
+ }
+ if (verbose > 3)
+ dprintk("%s:Command=[0x%x]\n", __FUNCTION__, command);
+
+ switch (command) {
+ case CA_PMT:
+ if (verbose > 3)
+ dprintk("Command = SEND_CA_PMT\n");
+ if ((ca_set_pmt(state, p_ca_message, hw_buffer, 0, 0)) < 0) {
+ dprintk("%s: -->CA_PMT Failed !\n", __FUNCTION__);
+ return -1;
+ }
+ if (verbose > 3)
+ dprintk("%s: -->CA_PMT Success !\n", __FUNCTION__);
+// retval = dummy_set_pmt(state, p_ca_message, hw_buffer, 0, 0);
+
+ break;
+
+ case CA_PMT_REPLY:
+ if (verbose > 3)
+ dprintk("Command = CA_PMT_REPLY\n");
+ /* Have to handle the 2 basic types of cards here */
+ if ((dst_check_ca_pmt(state, p_ca_message, hw_buffer)) < 0) {
+ dprintk("%s: -->CA_PMT_REPLY Failed !\n", __FUNCTION__);
+ return -1;
+ }
+ if (verbose > 3)
+ dprintk("%s: -->CA_PMT_REPLY Success !\n", __FUNCTION__);
+
+ /* Certain boards do behave different ? */
+// retval = ca_set_pmt(state, p_ca_message, hw_buffer, 1, 1);
+
+ case CA_APP_INFO_ENQUIRY: // only for debugging
+ if (verbose > 3)
+ dprintk("%s: Getting Cam Application information\n", __FUNCTION__);
+
+ if ((ca_get_app_info(state)) < 0) {
+ dprintk("%s: -->CA_APP_INFO_ENQUIRY Failed !\n", __FUNCTION__);
+ return -1;
+ }
+ if (verbose > 3)
+ printk("%s: -->CA_APP_INFO_ENQUIRY Success !\n", __FUNCTION__);
+
+ break;
+ }
+ }
+ return 0;
+}
+
+static int dst_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg)
+{
+ struct dvb_device* dvbdev = (struct dvb_device*) file->private_data;
+ struct dst_state* state = (struct dst_state*) dvbdev->priv;
+ struct ca_slot_info *p_ca_slot_info;
+ struct ca_caps *p_ca_caps;
+ struct ca_msg *p_ca_message;
+
+ if ((p_ca_message = (struct ca_msg *) kmalloc(sizeof (struct ca_msg), GFP_KERNEL)) == NULL) {
+ printk("%s: Memory allocation failure\n", __FUNCTION__);
+ return -ENOMEM;
+ }
+
+ if ((p_ca_slot_info = (struct ca_slot_info *) kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL)) == NULL) {
+ printk("%s: Memory allocation failure\n", __FUNCTION__);
+ return -ENOMEM;
+ }
+
+ if ((p_ca_caps = (struct ca_caps *) kmalloc(sizeof (struct ca_caps), GFP_KERNEL)) == NULL) {
+ printk("%s: Memory allocation failure\n", __FUNCTION__);
+ return -ENOMEM;
+ }
+
+ /* We have now only the standard ioctl's, the driver is upposed to handle internals. */
+ switch (cmd) {
+ case CA_SEND_MSG:
+ if (verbose > 1)
+ dprintk("%s: Sending message\n", __FUNCTION__);
+ if ((ca_send_message(state, p_ca_message, arg)) < 0) {
+ dprintk("%s: -->CA_SEND_MSG Failed !\n", __FUNCTION__);
+ return -1;
+ }
+
+ break;
+
+ case CA_GET_MSG:
+ if (verbose > 1)
+ dprintk("%s: Getting message\n", __FUNCTION__);
+ if ((ca_get_message(state, p_ca_message, arg)) < 0) {
+ dprintk("%s: -->CA_GET_MSG Failed !\n", __FUNCTION__);
+ return -1;
+ }
+ if (verbose > 1)
+ dprintk("%s: -->CA_GET_MSG Success !\n", __FUNCTION__);
+
+ break;
+
+ case CA_RESET:
+ if (verbose > 1)
+ dprintk("%s: Resetting DST\n", __FUNCTION__);
+ dst_error_bailout(state);
+ msleep(4000);
+
+ break;
+
+ case CA_GET_SLOT_INFO:
+ if (verbose > 1)
+ dprintk("%s: Getting Slot info\n", __FUNCTION__);
+ if ((ca_get_slot_info(state, p_ca_slot_info, arg)) < 0) {
+ dprintk("%s: -->CA_GET_SLOT_INFO Failed !\n", __FUNCTION__);
+ return -1;
+ }
+ if (verbose > 1)
+ dprintk("%s: -->CA_GET_SLOT_INFO Success !\n", __FUNCTION__);
+
+ break;
+
+ case CA_GET_CAP:
+ if (verbose > 1)
+ dprintk("%s: Getting Slot capabilities\n", __FUNCTION__);
+ if ((ca_get_slot_caps(state, p_ca_caps, arg)) < 0) {
+ dprintk("%s: -->CA_GET_CAP Failed !\n", __FUNCTION__);
+ return -1;
+ }
+ if (verbose > 1)
+ dprintk("%s: -->CA_GET_CAP Success !\n", __FUNCTION__);
+
+ break;
+
+ case CA_GET_DESCR_INFO:
+ if (verbose > 1)
+ dprintk("%s: Getting descrambler description\n", __FUNCTION__);
+ if ((ca_get_slot_descr(state, p_ca_message, arg)) < 0) {
+ dprintk("%s: -->CA_GET_DESCR_INFO Failed !\n", __FUNCTION__);
+ return -1;
+ }
+ if (verbose > 1)
+ dprintk("%s: -->CA_GET_DESCR_INFO Success !\n", __FUNCTION__);
+
+ break;
+
+ case CA_SET_DESCR:
+ if (verbose > 1)
+ dprintk("%s: Setting descrambler\n", __FUNCTION__);
+ if ((ca_set_slot_descr()) < 0) {
+ dprintk("%s: -->CA_SET_DESCR Failed !\n", __FUNCTION__);
+ return -1;
+ }
+ if (verbose > 1)
+ dprintk("%s: -->CA_SET_DESCR Success !\n", __FUNCTION__);
+
+ break;
+
+ case CA_SET_PID:
+ if (verbose > 1)
+ dprintk("%s: Setting PID\n", __FUNCTION__);
+ if ((ca_set_pid()) < 0) {
+ dprintk("%s: -->CA_SET_PID Failed !\n", __FUNCTION__);
+ return -1;
+ }
+ if (verbose > 1)
+ dprintk("%s: -->CA_SET_PID Success !\n", __FUNCTION__);
+
+ default:
+ return -EOPNOTSUPP;
+ };
+
+ return 0;
+}
+
+static int dst_ca_open(struct inode *inode, struct file *file)
+{
+ if (verbose > 4)
+ dprintk("%s:Device opened [%p]\n", __FUNCTION__, file);
+ try_module_get(THIS_MODULE);
+
+ return 0;
+}
+
+static int dst_ca_release(struct inode *inode, struct file *file)
+{
+ if (verbose > 4)
+ dprintk("%s:Device closed.\n", __FUNCTION__);
+ module_put(THIS_MODULE);
+
+ return 0;
+}
+
+static int dst_ca_read(struct file *file, char __user * buffer, size_t length, loff_t * offset)
+{
+ int bytes_read = 0;
+
+ if (verbose > 4)
+ dprintk("%s:Device read.\n", __FUNCTION__);
+
+ return bytes_read;
+}
+
+static int dst_ca_write(struct file *file, const char __user * buffer, size_t length, loff_t * offset)
+{
+ if (verbose > 4)
+ dprintk("%s:Device write.\n", __FUNCTION__);
+
+ return 0;
+}
+
+static struct file_operations dst_ca_fops = {
+ .owner = THIS_MODULE,
+ .ioctl = (void *)dst_ca_ioctl,
+ .open = dst_ca_open,
+ .release = dst_ca_release,
+ .read = dst_ca_read,
+ .write = dst_ca_write
+};
+
+static struct dvb_device dvbdev_ca = {
+ .priv = NULL,
+ .users = 1,
+ .readers = 1,
+ .writers = 1,
+ .fops = &dst_ca_fops
+};
+
+int dst_ca_attach(struct dst_state *dst, struct dvb_adapter *dvb_adapter)
+{
+ struct dvb_device *dvbdev;
+ if (verbose > 4)
+ dprintk("%s:registering DST-CA device\n", __FUNCTION__);
+ dvb_register_device(dvb_adapter, &dvbdev, &dvbdev_ca, dst, DVB_DEVICE_CA);
+ return 0;
+}
+
+EXPORT_SYMBOL(dst_ca_attach);
+
+MODULE_DESCRIPTION("DST DVB-S/T/C Combo CA driver");
+MODULE_AUTHOR("Manu Abraham");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/bt8xx/dst_ca.h b/drivers/media/dvb/bt8xx/dst_ca.h
new file mode 100644
index 00000000000..59cd0ddd6d8
--- /dev/null
+++ b/drivers/media/dvb/bt8xx/dst_ca.h
@@ -0,0 +1,58 @@
+/*
+ CA-driver for TwinHan DST Frontend/Card
+
+ Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef _DST_CA_H_
+#define _DST_CA_H_
+
+#define RETRIES 5
+
+
+#define CA_APP_INFO_ENQUIRY 0x9f8020
+#define CA_APP_INFO 0x9f8021
+#define CA_ENTER_MENU 0x9f8022
+#define CA_INFO_ENQUIRY 0x9f8030
+#define CA_INFO 0x9f8031
+#define CA_PMT 0x9f8032
+#define CA_PMT_REPLY 0x9f8033
+
+#define CA_CLOSE_MMI 0x9f8800
+#define CA_DISPLAY_CONTROL 0x9f8801
+#define CA_DISPLAY_REPLY 0x9f8802
+#define CA_TEXT_LAST 0x9f8803
+#define CA_TEXT_MORE 0x9f8804
+#define CA_KEYPAD_CONTROL 0x9f8805
+#define CA_KEYPRESS 0x9f8806
+
+#define CA_ENQUIRY 0x9f8807
+#define CA_ANSWER 0x9f8808
+#define CA_MENU_LAST 0x9f8809
+#define CA_MENU_MORE 0x9f880a
+#define CA_MENU_ANSWER 0x9f880b
+#define CA_LIST_LAST 0x9f880c
+#define CA_LIST_MORE 0x9f880d
+
+
+struct dst_ca_private {
+ struct dst_state *dst;
+ struct dvb_device *dvbdev;
+};
+
+
+#endif
diff --git a/drivers/media/dvb/bt8xx/dst_common.h b/drivers/media/dvb/bt8xx/dst_common.h
new file mode 100644
index 00000000000..0b3da29245f
--- /dev/null
+++ b/drivers/media/dvb/bt8xx/dst_common.h
@@ -0,0 +1,153 @@
+/*
+ Frontend-driver for TwinHan DST Frontend
+
+ Copyright (C) 2003 Jamie Honan
+ Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef DST_COMMON_H
+#define DST_COMMON_H
+
+#include <linux/dvb/frontend.h>
+#include <linux/device.h>
+#include "bt878.h"
+
+#include "dst_ca.h"
+
+
+#define NO_DELAY 0
+#define LONG_DELAY 1
+#define DEVICE_INIT 2
+
+#define DELAY 1
+
+#define DST_TYPE_IS_SAT 0
+#define DST_TYPE_IS_TERR 1
+#define DST_TYPE_IS_CABLE 2
+#define DST_TYPE_IS_ATSC 3
+
+#define DST_TYPE_HAS_NEWTUNE 1
+#define DST_TYPE_HAS_TS204 2
+#define DST_TYPE_HAS_SYMDIV 4
+#define DST_TYPE_HAS_FW_1 8
+#define DST_TYPE_HAS_FW_2 16
+#define DST_TYPE_HAS_FW_3 32
+#define DST_TYPE_HAS_FW_BUILD 64
+
+/* Card capability list */
+
+#define DST_TYPE_HAS_MAC 1
+#define DST_TYPE_HAS_DISEQC3 2
+#define DST_TYPE_HAS_DISEQC4 4
+#define DST_TYPE_HAS_DISEQC5 8
+#define DST_TYPE_HAS_MOTO 16
+#define DST_TYPE_HAS_CA 32
+#define DST_TYPE_HAS_ANALOG 64 /* Analog inputs */
+#define DST_TYPE_HAS_SESSION 128
+
+
+#define RDC_8820_PIO_0_DISABLE 0
+#define RDC_8820_PIO_0_ENABLE 1
+#define RDC_8820_INT 2
+#define RDC_8820_RESET 4
+
+/* DST Communication */
+#define GET_REPLY 1
+#define NO_REPLY 0
+
+#define GET_ACK 1
+#define FIXED_COMM 8
+
+#define ACK 0xff
+
+struct dst_state {
+
+ struct i2c_adapter* i2c;
+
+ struct bt878* bt;
+
+ struct dvb_frontend_ops ops;
+
+ /* configuration settings */
+ const struct dst_config* config;
+
+ struct dvb_frontend frontend;
+
+ /* private ASIC data */
+ u8 tx_tuna[10];
+ u8 rx_tuna[10];
+ u8 rxbuffer[10];
+ u8 diseq_flags;
+ u8 dst_type;
+ u32 type_flags;
+ u32 frequency; /* intermediate frequency in kHz for QPSK */
+ fe_spectral_inversion_t inversion;
+ u32 symbol_rate; /* symbol rate in Symbols per second */
+ fe_code_rate_t fec;
+ fe_sec_voltage_t voltage;
+ fe_sec_tone_mode_t tone;
+ u32 decode_freq;
+ u8 decode_lock;
+ u16 decode_strength;
+ u16 decode_snr;
+ unsigned long cur_jiff;
+ u8 k22;
+ fe_bandwidth_t bandwidth;
+ u32 dst_hw_cap;
+ u8 dst_fw_version;
+ fe_sec_mini_cmd_t minicmd;
+ u8 messages[256];
+};
+
+struct dst_types {
+ char *device_id;
+ int offset;
+ u8 dst_type;
+ u32 type_flags;
+ u32 dst_feature;
+};
+
+
+
+struct dst_config
+{
+ /* the ASIC i2c address */
+ u8 demod_address;
+};
+
+
+int rdc_reset_state(struct dst_state *state);
+int rdc_8820_reset(struct dst_state *state);
+
+int dst_wait_dst_ready(struct dst_state *state, u8 delay_mode);
+int dst_pio_enable(struct dst_state *state);
+int dst_pio_disable(struct dst_state *state);
+int dst_error_recovery(struct dst_state* state);
+int dst_error_bailout(struct dst_state *state);
+int dst_comm_init(struct dst_state* state);
+
+int write_dst(struct dst_state *state, u8 * data, u8 len);
+int read_dst(struct dst_state *state, u8 * ret, u8 len);
+u8 dst_check_sum(u8 * buf, u32 len);
+struct dst_state* dst_attach(struct dst_state* state, struct dvb_adapter *dvb_adapter);
+int dst_ca_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter);
+int dst_gpio_outb(struct dst_state* state, u32 mask, u32 enbb, u32 outhigh, int delay);
+
+int dst_command(struct dst_state* state, u8 * data, u8 len);
+
+
+#endif // DST_COMMON_H
diff --git a/drivers/media/dvb/bt8xx/dst_priv.h b/drivers/media/dvb/bt8xx/dst_priv.h
index 80488aa628b..3974a4c6ebe 100644
--- a/drivers/media/dvb/bt8xx/dst_priv.h
+++ b/drivers/media/dvb/bt8xx/dst_priv.h
@@ -33,4 +33,3 @@ union dst_gpio_packet {
struct bt878;
int bt878_device_control(struct bt878 *bt, unsigned int cmd, union dst_gpio_packet *mp);
-
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
index b735397f59a..6f857c6091f 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c
@@ -142,7 +142,7 @@ static int thomson_dtt7579_demod_init(struct dvb_frontend* fe)
mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
- mt352_write(fe, mt352_gpp_ctl_cfg, sizeof(mt352_gpp_ctl_cfg));
+ mt352_write(fe, mt352_gpp_ctl_cfg, sizeof(mt352_gpp_ctl_cfg));
mt352_write(fe, mt352_capt_range_cfg, sizeof(mt352_capt_range_cfg));
return 0;
@@ -161,7 +161,7 @@ static int thomson_dtt7579_pll_set(struct dvb_frontend* fe, struct dvb_frontend_
else if (params->frequency < 771000000) cp = 0xbc;
else cp = 0xf4;
- if (params->frequency == 0) bs = 0x03;
+ if (params->frequency == 0) bs = 0x03;
else if (params->frequency < 443250000) bs = 0x02;
else bs = 0x08;
@@ -190,44 +190,44 @@ static int cx24108_pll_set(struct dvb_frontend* fe, struct dvb_frontend_paramete
u32 osci[]={950000,1019000,1075000,1178000,1296000,1432000,
- 1576000,1718000,1856000,2036000,2150000};
+ 1576000,1718000,1856000,2036000,2150000};
u32 bandsel[]={0,0x00020000,0x00040000,0x00100800,0x00101000,
- 0x00102000,0x00104000,0x00108000,0x00110000,
- 0x00120000,0x00140000};
+ 0x00102000,0x00104000,0x00108000,0x00110000,
+ 0x00120000,0x00140000};
#define XTAL 1011100 /* Hz, really 1.0111 MHz and a /10 prescaler */
- printk("cx24108 debug: entering SetTunerFreq, freq=%d\n",freq);
-
- /* This is really the bit driving the tuner chip cx24108 */
-
- if(freq<950000) freq=950000; /* kHz */
- if(freq>2150000) freq=2150000; /* satellite IF is 950..2150MHz */
-
- /* decide which VCO to use for the input frequency */
- for(i=1;(i<sizeof(osci)/sizeof(osci[0]))&&(osci[i]<freq);i++);
- printk("cx24108 debug: select vco #%d (f=%d)\n",i,freq);
- band=bandsel[i];
- /* the gain values must be set by SetSymbolrate */
- /* compute the pll divider needed, from Conexant data sheet,
- resolved for (n*32+a), remember f(vco) is f(receive) *2 or *4,
- depending on the divider bit. It is set to /4 on the 2 lowest
- bands */
- n=((i<=2?2:1)*freq*10L)/(XTAL/100);
- a=n%32; n/=32; if(a==0) n--;
- pump=(freq<(osci[i-1]+osci[i])/2);
- pll=0xf8000000|
- ((pump?1:2)<<(14+11))|
- ((n&0x1ff)<<(5+11))|
- ((a&0x1f)<<11);
- /* everything is shifted left 11 bits to left-align the bits in the
- 32bit word. Output to the tuner goes MSB-aligned, after all */
- printk("cx24108 debug: pump=%d, n=%d, a=%d\n",pump,n,a);
- cx24110_pll_write(fe,band);
- /* set vga and vca to their widest-band settings, as a precaution.
- SetSymbolrate might not be called to set this up */
- cx24110_pll_write(fe,0x500c0000);
- cx24110_pll_write(fe,0x83f1f800);
- cx24110_pll_write(fe,pll);
+ printk("cx24108 debug: entering SetTunerFreq, freq=%d\n",freq);
+
+ /* This is really the bit driving the tuner chip cx24108 */
+
+ if(freq<950000) freq=950000; /* kHz */
+ if(freq>2150000) freq=2150000; /* satellite IF is 950..2150MHz */
+
+ /* decide which VCO to use for the input frequency */
+ for(i=1;(i<sizeof(osci)/sizeof(osci[0]))&&(osci[i]<freq);i++);
+ printk("cx24108 debug: select vco #%d (f=%d)\n",i,freq);
+ band=bandsel[i];
+ /* the gain values must be set by SetSymbolrate */
+ /* compute the pll divider needed, from Conexant data sheet,
+ resolved for (n*32+a), remember f(vco) is f(receive) *2 or *4,
+ depending on the divider bit. It is set to /4 on the 2 lowest
+ bands */
+ n=((i<=2?2:1)*freq*10L)/(XTAL/100);
+ a=n%32; n/=32; if(a==0) n--;
+ pump=(freq<(osci[i-1]+osci[i])/2);
+ pll=0xf8000000|
+ ((pump?1:2)<<(14+11))|
+ ((n&0x1ff)<<(5+11))|
+ ((a&0x1f)<<11);
+ /* everything is shifted left 11 bits to left-align the bits in the
+ 32bit word. Output to the tuner goes MSB-aligned, after all */
+ printk("cx24108 debug: pump=%d, n=%d, a=%d\n",pump,n,a);
+ cx24110_pll_write(fe,band);
+ /* set vga and vca to their widest-band settings, as a precaution.
+ SetSymbolrate might not be called to set this up */
+ cx24110_pll_write(fe,0x500c0000);
+ cx24110_pll_write(fe,0x83f1f800);
+ cx24110_pll_write(fe,pll);
/* writereg(client,0x56,0x7f);*/
return 0;
@@ -299,7 +299,7 @@ static int advbt771_samsung_tdtc9251dh0_demod_init(struct dvb_frontend* fe)
static u8 mt352_reset [] = { 0x50, 0x80 };
static u8 mt352_adc_ctl_1_cfg [] = { 0x8E, 0x40 };
static u8 mt352_agc_cfg [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF,
- 0x00, 0xFF, 0x00, 0x40, 0x40 };
+ 0x00, 0xFF, 0x00, 0x40, 0x40 };
static u8 mt352_av771_extra[] = { 0xB5, 0x7A };
static u8 mt352_capt_range_cfg[] = { 0x75, 0x32 };
@@ -463,6 +463,9 @@ static struct nxt6000_config vp3021_alps_tded4_config = {
static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
{
+ int ret;
+ struct dst_state* state = NULL;
+
switch(type) {
#ifdef BTTV_DVICO_DVBT_LITE
case BTTV_DVICO_DVBT_LITE:
@@ -503,7 +506,25 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
break;
case BTTV_TWINHAN_DST:
- card->fe = dst_attach(&dst_config, card->i2c_adapter, card->bt);
+ /* DST is not a frontend driver !!! */
+ state = (struct dst_state *) kmalloc(sizeof (struct dst_state), GFP_KERNEL);
+ /* Setup the Card */
+ state->config = &dst_config;
+ state->i2c = card->i2c_adapter;
+ state->bt = card->bt;
+
+ /* DST is not a frontend, attaching the ASIC */
+ if ((dst_attach(state, &card->dvb_adapter)) == NULL) {
+ printk("%s: Could not find a Twinhan DST.\n", __FUNCTION__);
+ break;
+ }
+ card->fe = &state->frontend;
+
+ /* Attach other DST peripherals if any */
+ /* Conditional Access device */
+ if (state->dst_hw_cap & DST_TYPE_HAS_CA) {
+ ret = dst_ca_attach(state, &card->dvb_adapter);
+ }
if (card->fe != NULL) {
break;
}
@@ -531,7 +552,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type)
card->bt->dev->subsystem_vendor,
card->bt->dev->subsystem_device);
} else {
- if (dvb_register_frontend(card->dvb_adapter, card->fe)) {
+ if (dvb_register_frontend(&card->dvb_adapter, card->fe)) {
printk("dvb-bt8xx: Frontend registration failed!\n");
if (card->fe->ops->release)
card->fe->ops->release(card->fe);
@@ -550,7 +571,7 @@ static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
return result;
}
- card->dvb_adapter->priv = card;
+ card->dvb_adapter.priv = card;
card->bt->adapter = card->i2c_adapter;
@@ -568,7 +589,7 @@ static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
if ((result = dvb_dmx_init(&card->demux)) < 0) {
printk("dvb_bt8xx: dvb_dmx_init failed (errno = %d)\n", result);
- dvb_unregister_adapter(card->dvb_adapter);
+ dvb_unregister_adapter(&card->dvb_adapter);
return result;
}
@@ -576,11 +597,11 @@ static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
card->dmxdev.demux = &card->demux.dmx;
card->dmxdev.capabilities = 0;
- if ((result = dvb_dmxdev_init(&card->dmxdev, card->dvb_adapter)) < 0) {
+ if ((result = dvb_dmxdev_init(&card->dmxdev, &card->dvb_adapter)) < 0) {
printk("dvb_bt8xx: dvb_dmxdev_init failed (errno = %d)\n", result);
dvb_dmx_release(&card->demux);
- dvb_unregister_adapter(card->dvb_adapter);
+ dvb_unregister_adapter(&card->dvb_adapter);
return result;
}
@@ -591,7 +612,7 @@ static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
dvb_dmxdev_release(&card->dmxdev);
dvb_dmx_release(&card->demux);
- dvb_unregister_adapter(card->dvb_adapter);
+ dvb_unregister_adapter(&card->dvb_adapter);
return result;
}
@@ -603,7 +624,7 @@ static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
dvb_dmxdev_release(&card->dmxdev);
dvb_dmx_release(&card->demux);
- dvb_unregister_adapter(card->dvb_adapter);
+ dvb_unregister_adapter(&card->dvb_adapter);
return result;
}
@@ -614,11 +635,11 @@ static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type)
card->demux.dmx.remove_frontend(&card->demux.dmx, &card->fe_hw);
dvb_dmxdev_release(&card->dmxdev);
dvb_dmx_release(&card->demux);
- dvb_unregister_adapter(card->dvb_adapter);
+ dvb_unregister_adapter(&card->dvb_adapter);
return result;
}
- dvb_net_init(card->dvb_adapter, &card->dvbnet, &card->demux.dmx);
+ dvb_net_init(&card->dvb_adapter, &card->dvbnet, &card->demux.dmx);
tasklet_init(&card->bt->tasklet, dvb_bt8xx_task, (unsigned long) card);
@@ -648,7 +669,7 @@ static int dvb_bt8xx_probe(struct device *dev)
case BTTV_PINNACLESAT:
card->gpio_mode = 0x0400c060;
/* should be: BT878_A_GAIN=0,BT878_A_PWRDN,BT878_DA_DPM,BT878_DA_SBR,
- BT878_DA_IOM=1,BT878_DA_APP to enable serial highspeed mode. */
+ BT878_DA_IOM=1,BT878_DA_APP to enable serial highspeed mode. */
card->op_sync_orin = 0;
card->irq_err_ignore = 0;
break;
@@ -759,7 +780,7 @@ static int dvb_bt8xx_remove(struct device *dev)
dvb_dmxdev_release(&card->dmxdev);
dvb_dmx_release(&card->demux);
if (card->fe) dvb_unregister_frontend(card->fe);
- dvb_unregister_adapter(card->dvb_adapter);
+ dvb_unregister_adapter(&card->dvb_adapter);
kfree(card);
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.h b/drivers/media/dvb/bt8xx/dvb-bt8xx.h
index 80ef189f930..2923b3b0dd3 100644
--- a/drivers/media/dvb/bt8xx/dvb-bt8xx.h
+++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.h
@@ -31,7 +31,7 @@
#include "bttv.h"
#include "mt352.h"
#include "sp887x.h"
-#include "dst.h"
+#include "dst_common.h"
#include "nxt6000.h"
#include "cx24110.h"
#include "or51211.h"
@@ -40,7 +40,7 @@ struct dvb_bt8xx_card {
struct semaphore lock;
int nfeeds;
char card_name[32];
- struct dvb_adapter *dvb_adapter;
+ struct dvb_adapter dvb_adapter;
struct bt878 *bt;
unsigned int bttv_nr;
struct dvb_demux demux;
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
index 28d4d926de3..96c57fde95a 100644
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c
@@ -119,7 +119,7 @@ struct cinergyt2 {
struct dvb_demux demux;
struct usb_device *udev;
struct semaphore sem;
- struct dvb_adapter *adapter;
+ struct dvb_adapter adapter;
struct dvb_device *fedev;
struct dmxdev dmxdev;
struct dvb_net dvbnet;
@@ -813,15 +813,15 @@ static int cinergyt2_probe (struct usb_interface *intf,
cinergyt2->dmxdev.demux = &cinergyt2->demux.dmx;
cinergyt2->dmxdev.capabilities = 0;
- if ((err = dvb_dmxdev_init(&cinergyt2->dmxdev, cinergyt2->adapter)) < 0) {
+ if ((err = dvb_dmxdev_init(&cinergyt2->dmxdev, &cinergyt2->adapter)) < 0) {
dprintk(1, "dvb_dmxdev_init() failed (err = %d)\n", err);
goto bailout;
}
- if (dvb_net_init(cinergyt2->adapter, &cinergyt2->dvbnet, &cinergyt2->demux.dmx))
+ if (dvb_net_init(&cinergyt2->adapter, &cinergyt2->dvbnet, &cinergyt2->demux.dmx))
dprintk(1, "dvb_net_init() failed!\n");
- dvb_register_device(cinergyt2->adapter, &cinergyt2->fedev,
+ dvb_register_device(&cinergyt2->adapter, &cinergyt2->fedev,
&cinergyt2_fe_template, cinergyt2,
DVB_DEVICE_FRONTEND);
@@ -848,7 +848,7 @@ static int cinergyt2_probe (struct usb_interface *intf,
bailout:
dvb_dmxdev_release(&cinergyt2->dmxdev);
dvb_dmx_release(&cinergyt2->demux);
- dvb_unregister_adapter (cinergyt2->adapter);
+ dvb_unregister_adapter (&cinergyt2->adapter);
cinergyt2_free_stream_urbs (cinergyt2);
kfree(cinergyt2);
return -ENOMEM;
@@ -872,7 +872,7 @@ static void cinergyt2_disconnect (struct usb_interface *intf)
dvb_dmxdev_release(&cinergyt2->dmxdev);
dvb_dmx_release(&cinergyt2->demux);
dvb_unregister_device(cinergyt2->fedev);
- dvb_unregister_adapter(cinergyt2->adapter);
+ dvb_unregister_adapter(&cinergyt2->adapter);
cinergyt2_free_stream_urbs(cinergyt2);
up(&cinergyt2->sem);
diff --git a/drivers/media/dvb/dibusb/Kconfig b/drivers/media/dvb/dibusb/Kconfig
deleted file mode 100644
index 74dfc73ae5b..00000000000
--- a/drivers/media/dvb/dibusb/Kconfig
+++ /dev/null
@@ -1,62 +0,0 @@
-config DVB_DIBUSB
- tristate "DiBcom USB DVB-T devices (see help for a complete device list)"
- depends on DVB_CORE && USB
- select FW_LOADER
- select DVB_DIB3000MB
- select DVB_DIB3000MC
- select DVB_MT352
- help
- Support for USB 1.1 and 2.0 DVB-T devices based on reference designs made by
- DiBcom (http://www.dibcom.fr) and C&E.
-
- Devices supported by this driver:
-
- TwinhanDTV USB-Ter (VP7041)
- TwinhanDTV Magic Box (VP7041e)
- KWorld/JetWay/ADSTech V-Stream XPERT DTV - DVB-T USB1.1 and USB2.0
- Hama DVB-T USB-Box
- DiBcom reference devices (non-public)
- Ultima Electronic/Artec T1 USB TVBOX
- Compro Videomate DVB-U2000 - DVB-T USB
- Grandtec DVB-T USB
- Avermedia AverTV DVBT USB
- Artec T1 USB1.1 and USB2.0 boxes
- Yakumo/Typhoon DVB-T USB2.0
- Hanftek UMT-010 USB2.0
- Hauppauge WinTV NOVA-T USB2
-
- The VP7041 seems to be identical to "CTS Portable" (Chinese
- Television System).
-
- These devices can be understood as budget ones, they "only" deliver
- (a part of) the MPEG2 transport stream.
-
- A firmware is needed to get the device working. See Documentation/dvb/README.dibusb
- details.
-
- Say Y if you own such a device and want to use it. You should build it as
- a module.
-
-config DVB_DIBUSB_MISDESIGNED_DEVICES
- bool "Enable support for some misdesigned (see help) devices, which identify with wrong IDs"
- depends on DVB_DIBUSB
- help
- Somehow Artec/Ultima Electronic forgot to program the eeprom of some of their
- USB1.1/USB2.0 devices.
- So comes that they identify with the default Vendor and Product ID of the Cypress
- CY7C64613 (AN2235) or Cypress FX2.
-
- Affected device IDs:
- 0x0574:0x2235 (Artec T1 USB1.1, cold)
- 0x04b4:0x8613 (Artec T1 USB2.0, cold)
- 0x0574:0x1002 (Artec T1 USB2.0, warm)
- 0x0574:0x2131 (aged DiBcom USB1.1 test device)
-
- Say Y if your device has one of the mentioned IDs.
-
-config DVB_DIBCOM_DEBUG
- bool "Enable extended debug support for DiBcom USB device"
- depends on DVB_DIBUSB
- help
- Say Y if you want to enable debuging. See modinfo dvb-dibusb for
- debug levels.
diff --git a/drivers/media/dvb/dibusb/Makefile b/drivers/media/dvb/dibusb/Makefile
deleted file mode 100644
index e941c508624..00000000000
--- a/drivers/media/dvb/dibusb/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-dvb-dibusb-objs = dvb-dibusb-core.o \
- dvb-dibusb-dvb.o \
- dvb-dibusb-fe-i2c.o \
- dvb-dibusb-firmware.o \
- dvb-dibusb-remote.o \
- dvb-dibusb-usb.o \
- dvb-fe-dtt200u.o
-
-obj-$(CONFIG_DVB_DIBUSB) += dvb-dibusb.o
-
-EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-core.c b/drivers/media/dvb/dibusb/dvb-dibusb-core.c
deleted file mode 100644
index 26235f9247e..00000000000
--- a/drivers/media/dvb/dibusb/dvb-dibusb-core.c
+++ /dev/null
@@ -1,558 +0,0 @@
-/*
- * Driver for mobile USB Budget DVB-T devices based on reference
- * design made by DiBcom (http://www.dibcom.fr/)
- *
- * dvb-dibusb-core.c
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * based on GPL code from DiBcom, which has
- * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr)
- *
- * Remote control code added by David Matthews (dm@prolingua.co.uk)
- *
- * 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, version 2.
- *
- * Acknowledgements
- *
- * Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
- * sources, on which this driver (and the dib3000mb/mc/p frontends) are based.
- *
- * see Documentation/dvb/README.dibusb for more information
- */
-#include "dvb-dibusb.h"
-
-#include <linux/moduleparam.h>
-
-/* debug */
-int dvb_dibusb_debug;
-module_param_named(debug, dvb_dibusb_debug, int, 0644);
-
-#ifdef CONFIG_DVB_DIBCOM_DEBUG
-#define DBSTATUS ""
-#else
-#define DBSTATUS " (debugging is not enabled)"
-#endif
-MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=alotmore,8=ts,16=err,32=rc (|-able))." DBSTATUS);
-#undef DBSTATUS
-
-static int pid_parse;
-module_param(pid_parse, int, 0644);
-MODULE_PARM_DESC(pid_parse, "enable pid parsing (filtering) when running at USB2.0");
-
-static int rc_query_interval = 100;
-module_param(rc_query_interval, int, 0644);
-MODULE_PARM_DESC(rc_query_interval, "interval in msecs for remote control query (default: 100; min: 40)");
-
-static int rc_key_repeat_count = 2;
-module_param(rc_key_repeat_count, int, 0644);
-MODULE_PARM_DESC(rc_key_repeat_count, "how many key repeats will be dropped before passing the key event again (default: 2)");
-
-/* Vendor IDs */
-#define USB_VID_ADSTECH 0x06e1
-#define USB_VID_ANCHOR 0x0547
-#define USB_VID_AVERMEDIA 0x14aa
-#define USB_VID_COMPRO 0x185b
-#define USB_VID_COMPRO_UNK 0x145f
-#define USB_VID_CYPRESS 0x04b4
-#define USB_VID_DIBCOM 0x10b8
-#define USB_VID_EMPIA 0xeb1a
-#define USB_VID_GRANDTEC 0x5032
-#define USB_VID_HANFTEK 0x15f4
-#define USB_VID_HAUPPAUGE 0x2040
-#define USB_VID_HYPER_PALTEK 0x1025
-#define USB_VID_IMC_NETWORKS 0x13d3
-#define USB_VID_TWINHAN 0x1822
-#define USB_VID_ULTIMA_ELECTRONIC 0x05d8
-
-/* Product IDs */
-#define USB_PID_ADSTECH_USB2_COLD 0xa333
-#define USB_PID_ADSTECH_USB2_WARM 0xa334
-#define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001
-#define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002
-#define USB_PID_COMPRO_DVBU2000_COLD 0xd000
-#define USB_PID_COMPRO_DVBU2000_WARM 0xd001
-#define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c
-#define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d
-#define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8
-#define USB_PID_DIBCOM_MOD3000_WARM 0x0bb9
-#define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6
-#define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7
-#define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131
-#define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0
-#define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1
-#define USB_PID_KWORLD_VSTREAM_COLD 0x17de
-#define USB_PID_KWORLD_VSTREAM_WARM 0x17df
-#define USB_PID_TWINHAN_VP7041_COLD 0x3201
-#define USB_PID_TWINHAN_VP7041_WARM 0x3202
-#define USB_PID_ULTIMA_TVBOX_COLD 0x8105
-#define USB_PID_ULTIMA_TVBOX_WARM 0x8106
-#define USB_PID_ULTIMA_TVBOX_AN2235_COLD 0x8107
-#define USB_PID_ULTIMA_TVBOX_AN2235_WARM 0x8108
-#define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD 0x2235
-#define USB_PID_ULTIMA_TVBOX_USB2_COLD 0x8109
-#define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD 0x8613
-#define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM 0x1002
-#define USB_PID_UNK_HYPER_PALTEK_COLD 0x005e
-#define USB_PID_UNK_HYPER_PALTEK_WARM 0x005f
-#define USB_PID_HANFTEK_UMT_010_COLD 0x0001
-#define USB_PID_HANFTEK_UMT_010_WARM 0x0015
-#define USB_PID_YAKUMO_DTT200U_COLD 0x0201
-#define USB_PID_YAKUMO_DTT200U_WARM 0x0301
-#define USB_PID_WINTV_NOVA_T_USB2_COLD 0x9300
-#define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301
-
-/* USB Driver stuff
- * table of devices that this driver is working with
- *
- * ATTENTION: Never ever change the order of this table, the particular
- * devices depend on this order
- *
- * Each entry is used as a reference in the device_struct. Currently this is
- * the only non-redundant way of assigning USB ids to actual devices I'm aware
- * of, because there is only one place in the code where the assignment of
- * vendor and product id is done, here.
- */
-static struct usb_device_id dib_table [] = {
-/* 00 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB_COLD)},
-/* 01 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB_WARM)},
-/* 02 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_YAKUMO_DTT200U_COLD) },
-/* 03 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_YAKUMO_DTT200U_WARM) },
-
-/* 04 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_COLD) },
-/* 05 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_WARM) },
-/* 06 */ { USB_DEVICE(USB_VID_COMPRO_UNK, USB_PID_COMPRO_DVBU2000_UNK_COLD) },
-/* 07 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_COLD) },
-/* 08 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_WARM) },
-/* 09 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3001_COLD) },
-/* 10 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3001_WARM) },
-/* 11 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_COLD) },
-/* 12 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_WARM) },
-/* 13 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_COLD) },
-/* 14 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_WARM) },
-/* 15 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_COLD) },
-/* 16 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_WARM) },
-/* 17 */ { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_COLD) },
-/* 18 */ { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_WARM) },
-/* 19 */ { USB_DEVICE(USB_VID_IMC_NETWORKS, USB_PID_TWINHAN_VP7041_COLD) },
-/* 20 */ { USB_DEVICE(USB_VID_IMC_NETWORKS, USB_PID_TWINHAN_VP7041_WARM) },
-/* 21 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_COLD) },
-/* 22 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_WARM) },
-/* 23 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) },
-/* 24 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) },
-/* 25 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) },
-/* 26 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) },
-/* 27 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) },
-
-/* 28 */ { USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_COLD) },
-/* 29 */ { USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_WARM) },
-
-/* 30 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_COLD) },
-/* 31 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_WARM) },
-/* 32 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_COLD) },
-/* 33 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_WARM) },
-/*
- * activate the following define when you have one of the devices and want to
- * build it from build-2.6 in dvb-kernel
- */
-// #define CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES
-#ifdef CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES
-/* 34 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) },
-/* 35 */ { USB_DEVICE(USB_VID_CYPRESS, USB_PID_ULTIMA_TVBOX_USB2_FX_COLD) },
-/* 36 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_ULTIMA_TVBOX_USB2_FX_WARM) },
-/* 37 */ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_DIBCOM_ANCHOR_2135_COLD) },
-#endif
- { } /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, dib_table);
-
-static struct dibusb_usb_controller dibusb_usb_ctrl[] = {
- { .name = "Cypress AN2135", .cpu_cs_register = 0x7f92 },
- { .name = "Cypress AN2235", .cpu_cs_register = 0x7f92 },
- { .name = "Cypress FX2", .cpu_cs_register = 0xe600 },
-};
-
-struct dibusb_tuner dibusb_tuner[] = {
- { DIBUSB_TUNER_CABLE_THOMSON,
- 0x61
- },
- { DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5,
- 0x60
- },
- { DIBUSB_TUNER_CABLE_LG_TDTP_E102P,
- 0x61
- },
- { DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5,
- 0x60
- },
-};
-
-static struct dibusb_demod dibusb_demod[] = {
- { DIBUSB_DIB3000MB,
- 16,
- { 0x8, 0 },
- },
- { DIBUSB_DIB3000MC,
- 32,
- { 0x9, 0xa, 0xb, 0xc },
- },
- { DIBUSB_MT352,
- 254,
- { 0xf, 0 },
- },
- { DTT200U_FE,
- 8,
- { 0xff,0 }, /* there is no i2c bus in this device */
- }
-};
-
-static struct dibusb_device_class dibusb_device_classes[] = {
- { .id = DIBUSB1_1, .usb_ctrl = &dibusb_usb_ctrl[0],
- .firmware = "dvb-dibusb-5.0.0.11.fw",
- .pipe_cmd = 0x01, .pipe_data = 0x02,
- .urb_count = 7, .urb_buffer_size = 4096,
- DIBUSB_RC_NEC_PROTOCOL,
- &dibusb_demod[DIBUSB_DIB3000MB],
- &dibusb_tuner[DIBUSB_TUNER_CABLE_THOMSON],
- },
- { DIBUSB1_1_AN2235, &dibusb_usb_ctrl[1],
- "dvb-dibusb-an2235-1.fw",
- 0x01, 0x02,
- 7, 4096,
- DIBUSB_RC_NEC_PROTOCOL,
- &dibusb_demod[DIBUSB_DIB3000MB],
- &dibusb_tuner[DIBUSB_TUNER_CABLE_THOMSON],
- },
- { DIBUSB2_0,&dibusb_usb_ctrl[2],
- "dvb-dibusb-6.0.0.5.fw",
- 0x01, 0x06,
- 7, 4096,
- DIBUSB_RC_NEC_PROTOCOL,
- &dibusb_demod[DIBUSB_DIB3000MC],
- &dibusb_tuner[DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5],
- },
- { UMT2_0, &dibusb_usb_ctrl[2],
- "dvb-dibusb-umt-2.fw",
- 0x01, 0x06,
- 20, 512,
- DIBUSB_RC_NO,
- &dibusb_demod[DIBUSB_MT352],
- &dibusb_tuner[DIBUSB_TUNER_CABLE_LG_TDTP_E102P],
- },
- { DIBUSB2_0B,&dibusb_usb_ctrl[2],
- "dvb-dibusb-adstech-usb2-1.fw",
- 0x01, 0x06,
- 7, 4096,
- DIBUSB_RC_NEC_PROTOCOL,
- &dibusb_demod[DIBUSB_DIB3000MB],
- &dibusb_tuner[DIBUSB_TUNER_CABLE_THOMSON],
- },
- { NOVAT_USB2,&dibusb_usb_ctrl[2],
- "dvb-dibusb-nova-t-1.fw",
- 0x01, 0x06,
- 7, 4096,
- DIBUSB_RC_HAUPPAUGE_PROTO,
- &dibusb_demod[DIBUSB_DIB3000MC],
- &dibusb_tuner[DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5],
- },
- { DTT200U,&dibusb_usb_ctrl[2],
- "dvb-dtt200u-1.fw",
- 0x01, 0x02,
- 7, 4096,
- DIBUSB_RC_NO,
- &dibusb_demod[DTT200U_FE],
- NULL, /* no explicit tuner/pll-programming necessary (it has the ENV57H1XD5) */
- },
-};
-
-static struct dibusb_usb_device dibusb_devices[] = {
- { "TwinhanDTV USB1.1 / Magic Box / HAMA USB1.1 DVB-T device",
- &dibusb_device_classes[DIBUSB1_1],
- { &dib_table[19], &dib_table[21], NULL},
- { &dib_table[20], &dib_table[22], NULL},
- },
- { "KWorld V-Stream XPERT DTV - DVB-T USB1.1",
- &dibusb_device_classes[DIBUSB1_1],
- { &dib_table[11], NULL },
- { &dib_table[12], NULL },
- },
- { "Grandtec USB1.1 DVB-T",
- &dibusb_device_classes[DIBUSB1_1],
- { &dib_table[13], &dib_table[15], NULL },
- { &dib_table[14], &dib_table[16], NULL },
- },
- { "DiBcom USB1.1 DVB-T reference design (MOD3000)",
- &dibusb_device_classes[DIBUSB1_1],
- { &dib_table[7], NULL },
- { &dib_table[8], NULL },
- },
- { "Artec T1 USB1.1 TVBOX with AN2135",
- &dibusb_device_classes[DIBUSB1_1],
- { &dib_table[23], NULL },
- { &dib_table[24], NULL },
- },
- { "Artec T1 USB1.1 TVBOX with AN2235",
- &dibusb_device_classes[DIBUSB1_1_AN2235],
- { &dib_table[25], NULL },
- { &dib_table[26], NULL },
- },
- { "Avermedia AverTV DVBT USB1.1",
- &dibusb_device_classes[DIBUSB1_1],
- { &dib_table[0], NULL },
- { &dib_table[1], NULL },
- },
- { "Compro Videomate DVB-U2000 - DVB-T USB1.1 (please confirm to linux-dvb)",
- &dibusb_device_classes[DIBUSB1_1],
- { &dib_table[4], &dib_table[6], NULL},
- { &dib_table[5], NULL },
- },
- { "Unkown USB1.1 DVB-T device ???? please report the name to the author",
- &dibusb_device_classes[DIBUSB1_1],
- { &dib_table[17], NULL },
- { &dib_table[18], NULL },
- },
- { "DiBcom USB2.0 DVB-T reference design (MOD3000P)",
- &dibusb_device_classes[DIBUSB2_0],
- { &dib_table[9], NULL },
- { &dib_table[10], NULL },
- },
- { "Artec T1 USB2.0 TVBOX (please report the warm ID)",
- &dibusb_device_classes[DIBUSB2_0],
- { &dib_table[27], NULL },
- { NULL },
- },
- { "Hauppauge WinTV NOVA-T USB2",
- &dibusb_device_classes[NOVAT_USB2],
- { &dib_table[30], NULL },
- { &dib_table[31], NULL },
- },
- { "DTT200U (Yakumo/Hama/Typhoon) DVB-T USB2.0",
- &dibusb_device_classes[DTT200U],
- { &dib_table[2], NULL },
- { &dib_table[3], NULL },
- },
- { "Hanftek UMT-010 DVB-T USB2.0",
- &dibusb_device_classes[UMT2_0],
- { &dib_table[28], NULL },
- { &dib_table[29], NULL },
- },
- { "KWorld/ADSTech Instant DVB-T USB 2.0",
- &dibusb_device_classes[DIBUSB2_0B],
- { &dib_table[32], NULL },
- { &dib_table[33], NULL }, /* device ID with default DIBUSB2_0-firmware */
- },
-#ifdef CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES
- { "Artec T1 USB1.1 TVBOX with AN2235 (misdesigned)",
- &dibusb_device_classes[DIBUSB1_1_AN2235],
- { &dib_table[34], NULL },
- { NULL },
- },
- { "Artec T1 USB2.0 TVBOX with FX2 IDs (misdesigned, please report the warm ID)",
- &dibusb_device_classes[DTT200U],
- { &dib_table[35], NULL },
- { &dib_table[36], NULL }, /* undefined, it could be that the device will get another USB ID in warm state */
- },
- { "DiBcom USB1.1 DVB-T reference design (MOD3000) with AN2135 default IDs",
- &dibusb_device_classes[DIBUSB1_1],
- { &dib_table[37], NULL },
- { NULL },
- },
-#endif
-};
-
-static int dibusb_exit(struct usb_dibusb *dib)
-{
- deb_info("init_state before exiting everything: %x\n",dib->init_state);
- dibusb_remote_exit(dib);
- dibusb_fe_exit(dib);
- dibusb_i2c_exit(dib);
- dibusb_dvb_exit(dib);
- dibusb_urb_exit(dib);
- deb_info("init_state should be zero now: %x\n",dib->init_state);
- dib->init_state = DIBUSB_STATE_INIT;
- kfree(dib);
- return 0;
-}
-
-static int dibusb_init(struct usb_dibusb *dib)
-{
- int ret = 0;
- sema_init(&dib->usb_sem, 1);
- sema_init(&dib->i2c_sem, 1);
-
- dib->init_state = DIBUSB_STATE_INIT;
-
- if ((ret = dibusb_urb_init(dib)) ||
- (ret = dibusb_dvb_init(dib)) ||
- (ret = dibusb_i2c_init(dib))) {
- dibusb_exit(dib);
- return ret;
- }
-
- if ((ret = dibusb_fe_init(dib)))
- err("could not initialize a frontend.");
-
- if ((ret = dibusb_remote_init(dib)))
- err("could not initialize remote control.");
-
- return 0;
-}
-
-static struct dibusb_usb_device * dibusb_device_class_quirk(struct usb_device *udev, struct dibusb_usb_device *dev)
-{
- int i;
-
- /* Quirk for the Kworld/ADSTech Instant USB2.0 device. It has the same USB
- * IDs like the USB1.1 KWorld after loading the firmware. Which is a bad
- * idea and make this quirk necessary.
- */
- if (dev->dev_cl->id == DIBUSB1_1 && udev->speed == USB_SPEED_HIGH) {
- info("this seems to be the Kworld/ADSTech Instant USB2.0 device or equal.");
- for (i = 0; i < sizeof(dibusb_devices)/sizeof(struct dibusb_usb_device); i++) {
- if (dibusb_devices[i].dev_cl->id == DIBUSB2_0B) {
- dev = &dibusb_devices[i];
- break;
- }
- }
- }
-
- return dev;
-}
-
-static struct dibusb_usb_device * dibusb_find_device (struct usb_device *udev,int *cold)
-{
- int i,j;
- struct dibusb_usb_device *dev = NULL;
- *cold = -1;
-
- for (i = 0; i < sizeof(dibusb_devices)/sizeof(struct dibusb_usb_device); i++) {
- for (j = 0; j < DIBUSB_ID_MAX_NUM && dibusb_devices[i].cold_ids[j] != NULL; j++) {
- deb_info("check for cold %x %x\n",dibusb_devices[i].cold_ids[j]->idVendor, dibusb_devices[i].cold_ids[j]->idProduct);
- if (dibusb_devices[i].cold_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) &&
- dibusb_devices[i].cold_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) {
- *cold = 1;
- dev = &dibusb_devices[i];
- break;
- }
- }
-
- if (dev != NULL)
- break;
-
- for (j = 0; j < DIBUSB_ID_MAX_NUM && dibusb_devices[i].warm_ids[j] != NULL; j++) {
- deb_info("check for warm %x %x\n",dibusb_devices[i].warm_ids[j]->idVendor, dibusb_devices[i].warm_ids[j]->idProduct);
- if (dibusb_devices[i].warm_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) &&
- dibusb_devices[i].warm_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) {
- *cold = 0;
- dev = &dibusb_devices[i];
- break;
- }
- }
- }
-
- if (dev != NULL)
- dev = dibusb_device_class_quirk(udev,dev);
-
- return dev;
-}
-
-/*
- * USB
- */
-static int dibusb_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- struct usb_device *udev = interface_to_usbdev(intf);
- struct usb_dibusb *dib = NULL;
- struct dibusb_usb_device *dibdev = NULL;
-
- int ret = -ENOMEM,cold=0;
-
- if ((dibdev = dibusb_find_device(udev,&cold)) == NULL) {
- err("something went very wrong, "
- "unknown product ID: %.4x",le16_to_cpu(udev->descriptor.idProduct));
- return -ENODEV;
- }
-
- if (cold == 1) {
- info("found a '%s' in cold state, will try to load a firmware",dibdev->name);
- ret = dibusb_loadfirmware(udev,dibdev);
- } else {
- info("found a '%s' in warm state.",dibdev->name);
- dib = kmalloc(sizeof(struct usb_dibusb),GFP_KERNEL);
- if (dib == NULL) {
- err("no memory");
- return ret;
- }
- memset(dib,0,sizeof(struct usb_dibusb));
-
- dib->udev = udev;
- dib->dibdev = dibdev;
-
- /* store parameters to structures */
- dib->rc_query_interval = rc_query_interval;
- dib->pid_parse = pid_parse;
- dib->rc_key_repeat_count = rc_key_repeat_count;
-
- usb_set_intfdata(intf, dib);
-
- ret = dibusb_init(dib);
- }
-
- if (ret == 0)
- info("%s successfully initialized and connected.",dibdev->name);
- else
- info("%s error while loading driver (%d)",dibdev->name,ret);
- return ret;
-}
-
-static void dibusb_disconnect(struct usb_interface *intf)
-{
- struct usb_dibusb *dib = usb_get_intfdata(intf);
- const char *name = DRIVER_DESC;
-
- usb_set_intfdata(intf,NULL);
- if (dib != NULL && dib->dibdev != NULL) {
- name = dib->dibdev->name;
- dibusb_exit(dib);
- }
- info("%s successfully deinitialized and disconnected.",name);
-
-}
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver dibusb_driver = {
- .owner = THIS_MODULE,
- .name = DRIVER_DESC,
- .probe = dibusb_probe,
- .disconnect = dibusb_disconnect,
- .id_table = dib_table,
-};
-
-/* module stuff */
-static int __init usb_dibusb_init(void)
-{
- int result;
- if ((result = usb_register(&dibusb_driver))) {
- err("usb_register failed. Error number %d",result);
- return result;
- }
-
- return 0;
-}
-
-static void __exit usb_dibusb_exit(void)
-{
- /* deregister this driver from the USB subsystem */
- usb_deregister(&dibusb_driver);
-}
-
-module_init (usb_dibusb_init);
-module_exit (usb_dibusb_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c b/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c
deleted file mode 100644
index 04e54ec093f..00000000000
--- a/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * dvb-dibusb-dvb.c is part of the driver for mobile USB Budget DVB-T devices
- * based on reference design made by DiBcom (http://www.dibcom.fr/)
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * see dvb-dibusb-core.c for more copyright details.
- *
- * This file contains functions for initializing and handling the
- * linux-dvb API.
- */
-#include "dvb-dibusb.h"
-
-#include <linux/usb.h>
-#include <linux/version.h>
-
-static u32 urb_compl_count;
-
-/*
- * MPEG2 TS DVB stuff
- */
-void dibusb_urb_complete(struct urb *urb, struct pt_regs *ptregs)
-{
- struct usb_dibusb *dib = urb->context;
-
- deb_ts("urb complete feedcount: %d, status: %d, length: %d\n",dib->feedcount,urb->status,
- urb->actual_length);
-
- urb_compl_count++;
- if (urb_compl_count % 1000 == 0)
- deb_info("%d urbs completed so far.\n",urb_compl_count);
-
- switch (urb->status) {
- case 0: /* success */
- case -ETIMEDOUT: /* NAK */
- break;
- case -ECONNRESET: /* kill */
- case -ENOENT:
- case -ESHUTDOWN:
- return;
- default: /* error */
- deb_ts("urb completition error %d.", urb->status);
- break;
- }
-
- if (dib->feedcount > 0 && urb->actual_length > 0) {
- if (dib->init_state & DIBUSB_STATE_DVB)
- dvb_dmx_swfilter(&dib->demux, (u8*) urb->transfer_buffer,urb->actual_length);
- } else
- deb_ts("URB dropped because of feedcount.\n");
-
- usb_submit_urb(urb,GFP_ATOMIC);
-}
-
-static int dibusb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
-{
- struct usb_dibusb *dib = dvbdmxfeed->demux->priv;
- int newfeedcount;
-
- if (dib == NULL)
- return -ENODEV;
-
- newfeedcount = dib->feedcount + (onoff ? 1 : -1);
-
- /*
- * stop feed before setting a new pid if there will be no pid anymore
- */
- if (newfeedcount == 0) {
- deb_ts("stop feeding\n");
- if (dib->xfer_ops.fifo_ctrl != NULL) {
- if (dib->xfer_ops.fifo_ctrl(dib->fe,0)) {
- err("error while inhibiting fifo.");
- return -ENODEV;
- }
- }
- dibusb_streaming(dib,0);
- }
-
- dib->feedcount = newfeedcount;
-
- /* activate the pid on the device specific pid_filter */
- deb_ts("setting pid: %5d %04x at index %d '%s'\n",dvbdmxfeed->pid,dvbdmxfeed->pid,dvbdmxfeed->index,onoff ? "on" : "off");
- if (dib->pid_parse && dib->xfer_ops.pid_ctrl != NULL)
- dib->xfer_ops.pid_ctrl(dib->fe,dvbdmxfeed->index,dvbdmxfeed->pid,onoff);
-
- /*
- * start the feed if this was the first pid to set and there is still a pid
- * for reception.
- */
- if (dib->feedcount == onoff && dib->feedcount > 0) {
-
- deb_ts("controlling pid parser\n");
- if (dib->xfer_ops.pid_parse != NULL) {
- if (dib->xfer_ops.pid_parse(dib->fe,dib->pid_parse) < 0) {
- err("could not handle pid_parser");
- }
- }
-
- deb_ts("start feeding\n");
- if (dib->xfer_ops.fifo_ctrl != NULL) {
- if (dib->xfer_ops.fifo_ctrl(dib->fe,1)) {
- err("error while enabling fifo.");
- return -ENODEV;
- }
- }
- dibusb_streaming(dib,1);
- }
- return 0;
-}
-
-static int dibusb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
- deb_ts("start pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid,dvbdmxfeed->type);
- return dibusb_ctrl_feed(dvbdmxfeed,1);
-}
-
-static int dibusb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
- deb_ts("stop pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid, dvbdmxfeed->type);
- return dibusb_ctrl_feed(dvbdmxfeed,0);
-}
-
-int dibusb_dvb_init(struct usb_dibusb *dib)
-{
- int ret;
-
- urb_compl_count = 0;
-
- if ((ret = dvb_register_adapter(&dib->adapter, DRIVER_DESC,
- THIS_MODULE)) < 0) {
- deb_info("dvb_register_adapter failed: error %d", ret);
- goto err;
- }
- dib->adapter->priv = dib;
-
-/* i2c is done in dibusb_i2c_init */
-
- dib->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
-
- dib->demux.priv = (void *)dib;
- /* get pidcount from demod */
- dib->demux.feednum = dib->demux.filternum = 255;
- dib->demux.start_feed = dibusb_start_feed;
- dib->demux.stop_feed = dibusb_stop_feed;
- dib->demux.write_to_decoder = NULL;
- if ((ret = dvb_dmx_init(&dib->demux)) < 0) {
- err("dvb_dmx_init failed: error %d",ret);
- goto err_dmx;
- }
-
- dib->dmxdev.filternum = dib->demux.filternum;
- dib->dmxdev.demux = &dib->demux.dmx;
- dib->dmxdev.capabilities = 0;
- if ((ret = dvb_dmxdev_init(&dib->dmxdev, dib->adapter)) < 0) {
- err("dvb_dmxdev_init failed: error %d",ret);
- goto err_dmx_dev;
- }
-
- dvb_net_init(dib->adapter, &dib->dvb_net, &dib->demux.dmx);
-
- goto success;
-err_dmx_dev:
- dvb_dmx_release(&dib->demux);
-err_dmx:
- dvb_unregister_adapter(dib->adapter);
-err:
- return ret;
-success:
- dib->init_state |= DIBUSB_STATE_DVB;
- return 0;
-}
-
-int dibusb_dvb_exit(struct usb_dibusb *dib)
-{
- if (dib->init_state & DIBUSB_STATE_DVB) {
- dib->init_state &= ~DIBUSB_STATE_DVB;
- deb_info("unregistering DVB part\n");
- dvb_net_release(&dib->dvb_net);
- dib->demux.dmx.close(&dib->demux.dmx);
- dvb_dmxdev_release(&dib->dmxdev);
- dvb_dmx_release(&dib->demux);
- dvb_unregister_adapter(dib->adapter);
- }
- return 0;
-}
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c b/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c
deleted file mode 100644
index 2ed89488c7c..00000000000
--- a/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c
+++ /dev/null
@@ -1,582 +0,0 @@
-/*
- * dvb-dibusb-fe-i2c.c is part of the driver for mobile USB Budget DVB-T devices
- * based on reference design made by DiBcom (http://www.dibcom.fr/)
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * see dvb-dibusb-core.c for more copyright details.
- *
- * This file contains functions for attaching, initializing of an appropriate
- * demodulator/frontend. I2C-stuff is also located here.
- *
- */
-#include "dvb-dibusb.h"
-
-#include <linux/usb.h>
-
-static int dibusb_i2c_msg(struct usb_dibusb *dib, u8 addr,
- u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
-{
- u8 sndbuf[wlen+4]; /* lead(1) devaddr,direction(1) addr(2) data(wlen) (len(2) (when reading)) */
- /* write only ? */
- int wo = (rbuf == NULL || rlen == 0),
- len = 2 + wlen + (wo ? 0 : 2);
-
- sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ;
- sndbuf[1] = (addr << 1) | (wo ? 0 : 1);
-
- memcpy(&sndbuf[2],wbuf,wlen);
-
- if (!wo) {
- sndbuf[wlen+2] = (rlen >> 8) & 0xff;
- sndbuf[wlen+3] = rlen & 0xff;
- }
-
- return dibusb_readwrite_usb(dib,sndbuf,len,rbuf,rlen);
-}
-
-/*
- * I2C master xfer function
- */
-static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg *msg,int num)
-{
- struct usb_dibusb *dib = i2c_get_adapdata(adap);
- int i;
-
- if (down_interruptible(&dib->i2c_sem) < 0)
- return -EAGAIN;
-
- if (num > 2)
- warn("more than 2 i2c messages at a time is not handled yet. TODO.");
-
- for (i = 0; i < num; i++) {
- /* write/read request */
- if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
- if (dibusb_i2c_msg(dib, msg[i].addr, msg[i].buf,msg[i].len,
- msg[i+1].buf,msg[i+1].len) < 0)
- break;
- i++;
- } else
- if (dibusb_i2c_msg(dib, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0)
- break;
- }
-
- up(&dib->i2c_sem);
- return i;
-}
-
-static u32 dibusb_i2c_func(struct i2c_adapter *adapter)
-{
- return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm dibusb_algo = {
- .name = "DiBcom USB i2c algorithm",
- .id = I2C_ALGO_BIT,
- .master_xfer = dibusb_i2c_xfer,
- .functionality = dibusb_i2c_func,
-};
-
-static int dibusb_general_demod_init(struct dvb_frontend *fe);
-static u8 dibusb_general_pll_addr(struct dvb_frontend *fe);
-static int dibusb_general_pll_init(struct dvb_frontend *fe, u8 pll_buf[5]);
-static int dibusb_general_pll_set(struct dvb_frontend *fe,
- struct dvb_frontend_parameters* params, u8 pll_buf[5]);
-
-static struct mt352_config mt352_hanftek_umt_010_config = {
- .demod_address = 0x1e,
- .demod_init = dibusb_general_demod_init,
- .pll_set = dibusb_general_pll_set,
-};
-
-static int dibusb_tuner_quirk(struct usb_dibusb *dib)
-{
- switch (dib->dibdev->dev_cl->id) {
- case DIBUSB1_1: /* some these device have the ENV77H11D5 and some the THOMSON CABLE */
- case DIBUSB1_1_AN2235: { /* actually its this device, but in warm state they are indistinguishable */
- struct dibusb_tuner *t;
- u8 b[2] = { 0,0 } ,b2[1];
- struct i2c_msg msg[2] = {
- { .flags = 0, .buf = b, .len = 2 },
- { .flags = I2C_M_RD, .buf = b2, .len = 1},
- };
-
- t = &dibusb_tuner[DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5];
-
- msg[0].addr = msg[1].addr = t->pll_addr;
-
- if (dib->xfer_ops.tuner_pass_ctrl != NULL)
- dib->xfer_ops.tuner_pass_ctrl(dib->fe,1,t->pll_addr);
- dibusb_i2c_xfer(&dib->i2c_adap,msg,2);
- if (dib->xfer_ops.tuner_pass_ctrl != NULL)
- dib->xfer_ops.tuner_pass_ctrl(dib->fe,0,t->pll_addr);
-
- if (b2[0] == 0xfe)
- info("this device has the Thomson Cable onboard. Which is default.");
- else {
- dib->tuner = t;
- info("this device has the Panasonic ENV77H11D5 onboard.");
- }
- break;
- }
- default:
- break;
- }
- return 0;
-}
-
-int dibusb_fe_init(struct usb_dibusb* dib)
-{
- struct dib3000_config demod_cfg;
- int i;
-
- if (dib->init_state & DIBUSB_STATE_I2C) {
- for (i = 0; i < sizeof(dib->dibdev->dev_cl->demod->i2c_addrs) / sizeof(unsigned char) &&
- dib->dibdev->dev_cl->demod->i2c_addrs[i] != 0; i++) {
-
- demod_cfg.demod_address = dib->dibdev->dev_cl->demod->i2c_addrs[i];
- demod_cfg.pll_addr = dibusb_general_pll_addr;
- demod_cfg.pll_set = dibusb_general_pll_set;
- demod_cfg.pll_init = dibusb_general_pll_init;
-
- deb_info("demod id: %d %d\n",dib->dibdev->dev_cl->demod->id,DTT200U_FE);
-
- switch (dib->dibdev->dev_cl->demod->id) {
- case DIBUSB_DIB3000MB:
- dib->fe = dib3000mb_attach(&demod_cfg,&dib->i2c_adap,&dib->xfer_ops);
- break;
- case DIBUSB_DIB3000MC:
- dib->fe = dib3000mc_attach(&demod_cfg,&dib->i2c_adap,&dib->xfer_ops);
- break;
- case DIBUSB_MT352:
- mt352_hanftek_umt_010_config.demod_address = dib->dibdev->dev_cl->demod->i2c_addrs[i];
- dib->fe = mt352_attach(&mt352_hanftek_umt_010_config, &dib->i2c_adap);
- break;
- case DTT200U_FE:
- dib->fe = dtt200u_fe_attach(dib,&dib->xfer_ops);
- break;
- }
- if (dib->fe != NULL) {
- info("found demodulator at i2c address 0x%x",dib->dibdev->dev_cl->demod->i2c_addrs[i]);
- break;
- }
- }
- /* if a frontend was found */
- if (dib->fe != NULL) {
- if (dib->fe->ops->sleep != NULL)
- dib->fe_sleep = dib->fe->ops->sleep;
- dib->fe->ops->sleep = dibusb_hw_sleep;
-
- if (dib->fe->ops->init != NULL )
- dib->fe_init = dib->fe->ops->init;
- dib->fe->ops->init = dibusb_hw_wakeup;
-
- /* setting the default tuner */
- dib->tuner = dib->dibdev->dev_cl->tuner;
-
- /* check which tuner is mounted on this device, in case this is unsure */
- dibusb_tuner_quirk(dib);
- }
- }
- if (dib->fe == NULL) {
- err("A frontend driver was not found for device '%s'.",
- dib->dibdev->name);
- return -ENODEV;
- } else {
- if (dvb_register_frontend(dib->adapter, dib->fe)) {
- err("Frontend registration failed.");
- if (dib->fe->ops->release)
- dib->fe->ops->release(dib->fe);
- dib->fe = NULL;
- return -ENODEV;
- }
- }
-
- return 0;
-}
-
-int dibusb_fe_exit(struct usb_dibusb *dib)
-{
- if (dib->fe != NULL)
- dvb_unregister_frontend(dib->fe);
- return 0;
-}
-
-int dibusb_i2c_init(struct usb_dibusb *dib)
-{
- int ret = 0;
-
- dib->adapter->priv = dib;
-
- strncpy(dib->i2c_adap.name,dib->dibdev->name,I2C_NAME_SIZE);
-#ifdef I2C_ADAP_CLASS_TV_DIGITAL
- dib->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL,
-#else
- dib->i2c_adap.class = I2C_CLASS_TV_DIGITAL,
-#endif
- dib->i2c_adap.algo = &dibusb_algo;
- dib->i2c_adap.algo_data = NULL;
- dib->i2c_adap.id = I2C_ALGO_BIT;
-
- i2c_set_adapdata(&dib->i2c_adap, dib);
-
- if ((ret = i2c_add_adapter(&dib->i2c_adap)) < 0)
- err("could not add i2c adapter");
-
- dib->init_state |= DIBUSB_STATE_I2C;
-
- return ret;
-}
-
-int dibusb_i2c_exit(struct usb_dibusb *dib)
-{
- if (dib->init_state & DIBUSB_STATE_I2C)
- i2c_del_adapter(&dib->i2c_adap);
- dib->init_state &= ~DIBUSB_STATE_I2C;
- return 0;
-}
-
-
-/* pll stuff, maybe removed soon (thx to Gerd/Andrew in advance) */
-static int thomson_cable_eu_pll_set(struct dvb_frontend_parameters *fep, u8 pllbuf[4])
-{
- u32 tfreq = (fep->frequency + 36125000) / 62500;
- int vu,p0,p1,p2;
-
- if (fep->frequency > 403250000)
- vu = 1, p2 = 1, p1 = 0, p0 = 1;
- else if (fep->frequency > 115750000)
- vu = 0, p2 = 1, p1 = 1, p0 = 0;
- else if (fep->frequency > 44250000)
- vu = 0, p2 = 0, p1 = 1, p0 = 1;
- else
- return -EINVAL;
-
- pllbuf[0] = (tfreq >> 8) & 0x7f;
- pllbuf[1] = tfreq & 0xff;
- pllbuf[2] = 0x8e;
- pllbuf[3] = (vu << 7) | (p2 << 2) | (p1 << 1) | p0;
- return 0;
-}
-
-static int panasonic_cofdm_env57h1xd5_pll_set(struct dvb_frontend_parameters *fep, u8 pllbuf[4])
-{
- u32 freq_khz = fep->frequency / 1000;
- u32 tfreq = ((freq_khz + 36125)*6 + 500) / 1000;
- u8 TA, T210, R210, ctrl1, cp210, p4321;
- if (freq_khz > 858000) {
- err("frequency cannot be larger than 858 MHz.");
- return -EINVAL;
- }
-
- // contol data 1 : 1 | T/A=1 | T2,T1,T0 = 0,0,0 | R2,R1,R0 = 0,1,0
- TA = 1;
- T210 = 0;
- R210 = 0x2;
- ctrl1 = (1 << 7) | (TA << 6) | (T210 << 3) | R210;
-
-// ******** CHARGE PUMP CONFIG vs RF FREQUENCIES *****************
- if (freq_khz < 470000)
- cp210 = 2; // VHF Low and High band ch E12 to E4 to E12
- else if (freq_khz < 526000)
- cp210 = 4; // UHF band Ch E21 to E27
- else // if (freq < 862000000)
- cp210 = 5; // UHF band ch E28 to E69
-
-//********************* BW select *******************************
- if (freq_khz < 153000)
- p4321 = 1; // BW selected for VHF low
- else if (freq_khz < 470000)
- p4321 = 2; // BW selected for VHF high E5 to E12
- else // if (freq < 862000000)
- p4321 = 4; // BW selection for UHF E21 to E69
-
- pllbuf[0] = (tfreq >> 8) & 0xff;
- pllbuf[1] = (tfreq >> 0) & 0xff;
- pllbuf[2] = 0xff & ctrl1;
- pllbuf[3] = (cp210 << 5) | (p4321);
-
- return 0;
-}
-
-/*
- * 7 6 5 4 3 2 1 0
- * Address Byte 1 1 0 0 0 MA1 MA0 R/~W=0
- *
- * Program divider byte 1 0 n14 n13 n12 n11 n10 n9 n8
- * Program divider byte 2 n7 n6 n5 n4 n3 n2 n1 n0
- *
- * Control byte 1 1 T/A=1 T2 T1 T0 R2 R1 R0
- * 1 T/A=0 0 0 ATC AL2 AL1 AL0
- *
- * Control byte 2 CP2 CP1 CP0 BS5 BS4 BS3 BS2 BS1
- *
- * MA0/1 = programmable address bits
- * R/~W = read/write bit (0 for writing)
- * N14-0 = programmable LO frequency
- *
- * T/A = test AGC bit (0 = next 6 bits AGC setting,
- * 1 = next 6 bits test and reference divider ratio settings)
- * T2-0 = test bits
- * R2-0 = reference divider ratio and programmable frequency step
- * ATC = AGC current setting and time constant
- * ATC = 0: AGC current = 220nA, AGC time constant = 2s
- * ATC = 1: AGC current = 9uA, AGC time constant = 50ms
- * AL2-0 = AGC take-over point bits
- * CP2-0 = charge pump current
- * BS5-1 = PMOS ports control bits;
- * BSn = 0 corresponding port is off, high-impedance state (at power-on)
- * BSn = 1 corresponding port is on
- */
-static int panasonic_cofdm_env77h11d5_tda6650_init(struct dvb_frontend *fe, u8 pllbuf[4])
-{
- pllbuf[0] = 0x0b;
- pllbuf[1] = 0xf5;
- pllbuf[2] = 0x85;
- pllbuf[3] = 0xab;
- return 0;
-}
-
-static int panasonic_cofdm_env77h11d5_tda6650_set (struct dvb_frontend_parameters *fep,u8 pllbuf[4])
-{
- int tuner_frequency = 0;
- u8 band, cp, filter;
-
- // determine charge pump
- tuner_frequency = fep->frequency + 36166000;
- if (tuner_frequency < 87000000)
- return -EINVAL;
- else if (tuner_frequency < 130000000)
- cp = 3;
- else if (tuner_frequency < 160000000)
- cp = 5;
- else if (tuner_frequency < 200000000)
- cp = 6;
- else if (tuner_frequency < 290000000)
- cp = 3;
- else if (tuner_frequency < 420000000)
- cp = 5;
- else if (tuner_frequency < 480000000)
- cp = 6;
- else if (tuner_frequency < 620000000)
- cp = 3;
- else if (tuner_frequency < 830000000)
- cp = 5;
- else if (tuner_frequency < 895000000)
- cp = 7;
- else
- return -EINVAL;
-
- // determine band
- if (fep->frequency < 49000000)
- return -EINVAL;
- else if (fep->frequency < 161000000)
- band = 1;
- else if (fep->frequency < 444000000)
- band = 2;
- else if (fep->frequency < 861000000)
- band = 4;
- else
- return -EINVAL;
-
- // setup PLL filter
- switch (fep->u.ofdm.bandwidth) {
- case BANDWIDTH_6_MHZ:
- case BANDWIDTH_7_MHZ:
- filter = 0;
- break;
- case BANDWIDTH_8_MHZ:
- filter = 1;
- break;
- default:
- return -EINVAL;
- }
-
- // calculate divisor
- // ((36166000+((1000000/6)/2)) + Finput)/(1000000/6)
- tuner_frequency = (((fep->frequency / 1000) * 6) + 217496) / 1000;
-
- // setup tuner buffer
- pllbuf[0] = (tuner_frequency >> 8) & 0x7f;
- pllbuf[1] = tuner_frequency & 0xff;
- pllbuf[2] = 0xca;
- pllbuf[3] = (cp << 5) | (filter << 3) | band;
- return 0;
-}
-
-/*
- * 7 6 5 4 3 2 1 0
- * Address Byte 1 1 0 0 0 MA1 MA0 R/~W=0
- *
- * Program divider byte 1 0 n14 n13 n12 n11 n10 n9 n8
- * Program divider byte 2 n7 n6 n5 n4 n3 n2 n1 n0
- *
- * Control byte 1 CP T2 T1 T0 RSA RSB OS
- *
- * Band Switch byte X X X P4 P3 P2 P1 P0
- *
- * Auxiliary byte ATC AL2 AL1 AL0 0 0 0 0
- *
- * Address: MA1 MA0 Address
- * 0 0 c0
- * 0 1 c2 (always valid)
- * 1 0 c4
- * 1 1 c6
- */
-static int lg_tdtp_e102p_tua6034(struct dvb_frontend_parameters* fep, u8 pllbuf[4])
-{
- u32 div;
- u8 p210, p3;
-
-#define TUNER_MUL 62500
-
- div = (fep->frequency + 36125000 + TUNER_MUL / 2) / TUNER_MUL;
-// div = ((fep->frequency/1000 + 36166) * 6) / 1000;
-
- if (fep->frequency < 174500000)
- p210 = 1; // not supported by the tdtp_e102p
- else if (fep->frequency < 230000000) // VHF
- p210 = 2;
- else
- p210 = 4;
-
- if (fep->u.ofdm.bandwidth == BANDWIDTH_7_MHZ)
- p3 = 0;
- else
- p3 = 1;
-
- pllbuf[0] = (div >> 8) & 0x7f;
- pllbuf[1] = div & 0xff;
- pllbuf[2] = 0xce;
-// pllbuf[2] = 0xcc;
- pllbuf[3] = (p3 << 3) | p210;
-
- return 0;
-}
-
-static int lg_tdtp_e102p_mt352_demod_init(struct dvb_frontend *fe)
-{
- static u8 mt352_clock_config[] = { 0x89, 0xb8, 0x2d };
- static u8 mt352_reset[] = { 0x50, 0x80 };
- static u8 mt352_mclk_ratio[] = { 0x8b, 0x00 };
- static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 };
- static u8 mt352_agc_cfg[] = { 0x67, 0x10, 0xa0 };
-
- static u8 mt352_sec_agc_cfg1[] = { 0x6a, 0xff };
- static u8 mt352_sec_agc_cfg2[] = { 0x6d, 0xff };
- static u8 mt352_sec_agc_cfg3[] = { 0x70, 0x40 };
- static u8 mt352_sec_agc_cfg4[] = { 0x7b, 0x03 };
- static u8 mt352_sec_agc_cfg5[] = { 0x7d, 0x0f };
-
- static u8 mt352_acq_ctl[] = { 0x53, 0x50 };
- static u8 mt352_input_freq_1[] = { 0x56, 0x31, 0x06 };
-
- mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
- udelay(2000);
- mt352_write(fe, mt352_reset, sizeof(mt352_reset));
- mt352_write(fe, mt352_mclk_ratio, sizeof(mt352_mclk_ratio));
-
- mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
- mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
-
- mt352_write(fe, mt352_sec_agc_cfg1, sizeof(mt352_sec_agc_cfg1));
- mt352_write(fe, mt352_sec_agc_cfg2, sizeof(mt352_sec_agc_cfg2));
- mt352_write(fe, mt352_sec_agc_cfg3, sizeof(mt352_sec_agc_cfg3));
- mt352_write(fe, mt352_sec_agc_cfg4, sizeof(mt352_sec_agc_cfg4));
- mt352_write(fe, mt352_sec_agc_cfg5, sizeof(mt352_sec_agc_cfg5));
-
- mt352_write(fe, mt352_acq_ctl, sizeof(mt352_acq_ctl));
- mt352_write(fe, mt352_input_freq_1, sizeof(mt352_input_freq_1));
-
- return 0;
-}
-
-static int dibusb_general_demod_init(struct dvb_frontend *fe)
-{
- struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv;
- switch (dib->dibdev->dev_cl->id) {
- case UMT2_0:
- return lg_tdtp_e102p_mt352_demod_init(fe);
- default: /* other device classes do not have device specific demod inits */
- break;
- }
- return 0;
-}
-
-static u8 dibusb_general_pll_addr(struct dvb_frontend *fe)
-{
- struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv;
- return dib->tuner->pll_addr;
-}
-
-static int dibusb_pll_i2c_helper(struct usb_dibusb *dib, u8 pll_buf[5], u8 buf[4])
-{
- if (pll_buf == NULL) {
- struct i2c_msg msg = {
- .addr = dib->tuner->pll_addr,
- .flags = 0,
- .buf = buf,
- .len = sizeof(buf)
- };
- if (i2c_transfer (&dib->i2c_adap, &msg, 1) != 1)
- return -EIO;
- msleep(1);
- } else {
- pll_buf[0] = dib->tuner->pll_addr << 1;
- memcpy(&pll_buf[1],buf,4);
- }
-
- return 0;
-}
-
-static int dibusb_general_pll_init(struct dvb_frontend *fe,
- u8 pll_buf[5])
-{
- struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv;
- u8 buf[4];
- int ret=0;
- switch (dib->tuner->id) {
- case DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5:
- ret = panasonic_cofdm_env77h11d5_tda6650_init(fe,buf);
- break;
- default:
- break;
- }
-
- if (ret)
- return ret;
-
- return dibusb_pll_i2c_helper(dib,pll_buf,buf);
-}
-
-static int dibusb_general_pll_set(struct dvb_frontend *fe,
- struct dvb_frontend_parameters *fep, u8 pll_buf[5])
-{
- struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv;
- u8 buf[4];
- int ret=0;
-
- switch (dib->tuner->id) {
- case DIBUSB_TUNER_CABLE_THOMSON:
- ret = thomson_cable_eu_pll_set(fep, buf);
- break;
- case DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5:
- ret = panasonic_cofdm_env57h1xd5_pll_set(fep, buf);
- break;
- case DIBUSB_TUNER_CABLE_LG_TDTP_E102P:
- ret = lg_tdtp_e102p_tua6034(fep, buf);
- break;
- case DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5:
- ret = panasonic_cofdm_env77h11d5_tda6650_set(fep,buf);
- break;
- default:
- warn("no pll programming routine found for tuner %d.\n",dib->tuner->id);
- ret = -ENODEV;
- break;
- }
-
- if (ret)
- return ret;
-
- return dibusb_pll_i2c_helper(dib,pll_buf,buf);
-}
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-firmware.c b/drivers/media/dvb/dibusb/dvb-dibusb-firmware.c
deleted file mode 100644
index 504ba47afdf..00000000000
--- a/drivers/media/dvb/dibusb/dvb-dibusb-firmware.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * dvb-dibusb-firmware.c is part of the driver for mobile USB Budget DVB-T devices
- * based on reference design made by DiBcom (http://www.dibcom.fr/)
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * see dvb-dibusb-core.c for more copyright details.
- *
- * This file contains functions for downloading the firmware to the device.
- */
-#include "dvb-dibusb.h"
-
-#include <linux/firmware.h>
-#include <linux/usb.h>
-
-/*
- * load a firmware packet to the device
- */
-static int dibusb_writemem(struct usb_device *udev,u16 addr,u8 *data, u8 len)
-{
- return usb_control_msg(udev, usb_sndctrlpipe(udev,0),
- 0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5000);
-}
-
-int dibusb_loadfirmware(struct usb_device *udev, struct dibusb_usb_device *dibdev)
-{
- const struct firmware *fw = NULL;
- u16 addr;
- u8 *b,*p;
- int ret = 0,i;
-
- if ((ret = request_firmware(&fw, dibdev->dev_cl->firmware, &udev->dev)) != 0) {
- err("did not find the firmware file. (%s) "
- "Please see linux/Documentation/dvb/ for more details on firmware-problems.",
- dibdev->dev_cl->firmware);
- return ret;
- }
-
- info("downloading firmware from file '%s'.",dibdev->dev_cl->firmware);
-
- p = kmalloc(fw->size,GFP_KERNEL);
- if (p != NULL) {
- u8 reset;
- /*
- * you cannot use the fw->data as buffer for
- * usb_control_msg, a new buffer has to be
- * created
- */
- memcpy(p,fw->data,fw->size);
-
- /* stop the CPU */
- reset = 1;
- if ((ret = dibusb_writemem(udev,dibdev->dev_cl->usb_ctrl->cpu_cs_register,&reset,1)) != 1)
- err("could not stop the USB controller CPU.");
- for(i = 0; p[i+3] == 0 && i < fw->size; ) {
- b = (u8 *) &p[i];
- addr = *((u16 *) &b[1]);
-
- ret = dibusb_writemem(udev,addr,&b[4],b[0]);
-
- if (ret != b[0]) {
- err("error while transferring firmware "
- "(transferred size: %d, block size: %d)",
- ret,b[0]);
- ret = -EINVAL;
- break;
- }
- i += 5 + b[0];
- }
- /* length in ret */
- if (ret > 0)
- ret = 0;
- /* restart the CPU */
- reset = 0;
- if (ret || dibusb_writemem(udev,dibdev->dev_cl->usb_ctrl->cpu_cs_register,&reset,1) != 1) {
- err("could not restart the USB controller CPU.");
- ret = -EINVAL;
- }
-
- kfree(p);
- } else {
- ret = -ENOMEM;
- }
- release_firmware(fw);
-
- return ret;
-}
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-remote.c b/drivers/media/dvb/dibusb/dvb-dibusb-remote.c
deleted file mode 100644
index 9dc8b15517b..00000000000
--- a/drivers/media/dvb/dibusb/dvb-dibusb-remote.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * dvb-dibusb-remote.c is part of the driver for mobile USB Budget DVB-T devices
- * based on reference design made by DiBcom (http://www.dibcom.fr/)
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * see dvb-dibusb-core.c for more copyright details.
- *
- * This file contains functions for handling the event device on the software
- * side and the remote control on the hardware side.
- */
-#include "dvb-dibusb.h"
-
-/* Table to map raw key codes to key events. This should not be hard-wired
- into the kernel. */
-static const struct { u8 c0, c1, c2; uint32_t key; } nec_rc_keys [] =
-{
- /* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */
- { 0x00, 0xff, 0x16, KEY_POWER },
- { 0x00, 0xff, 0x10, KEY_MUTE },
- { 0x00, 0xff, 0x03, KEY_1 },
- { 0x00, 0xff, 0x01, KEY_2 },
- { 0x00, 0xff, 0x06, KEY_3 },
- { 0x00, 0xff, 0x09, KEY_4 },
- { 0x00, 0xff, 0x1d, KEY_5 },
- { 0x00, 0xff, 0x1f, KEY_6 },
- { 0x00, 0xff, 0x0d, KEY_7 },
- { 0x00, 0xff, 0x19, KEY_8 },
- { 0x00, 0xff, 0x1b, KEY_9 },
- { 0x00, 0xff, 0x15, KEY_0 },
- { 0x00, 0xff, 0x05, KEY_CHANNELUP },
- { 0x00, 0xff, 0x02, KEY_CHANNELDOWN },
- { 0x00, 0xff, 0x1e, KEY_VOLUMEUP },
- { 0x00, 0xff, 0x0a, KEY_VOLUMEDOWN },
- { 0x00, 0xff, 0x11, KEY_RECORD },
- { 0x00, 0xff, 0x17, KEY_FAVORITES }, /* Heart symbol - Channel list. */
- { 0x00, 0xff, 0x14, KEY_PLAY },
- { 0x00, 0xff, 0x1a, KEY_STOP },
- { 0x00, 0xff, 0x40, KEY_REWIND },
- { 0x00, 0xff, 0x12, KEY_FASTFORWARD },
- { 0x00, 0xff, 0x0e, KEY_PREVIOUS }, /* Recall - Previous channel. */
- { 0x00, 0xff, 0x4c, KEY_PAUSE },
- { 0x00, 0xff, 0x4d, KEY_SCREEN }, /* Full screen mode. */
- { 0x00, 0xff, 0x54, KEY_AUDIO }, /* MTS - Switch to secondary audio. */
- /* additional keys TwinHan VisionPlus, the Artec seemingly not have */
- { 0x00, 0xff, 0x0c, KEY_CANCEL }, /* Cancel */
- { 0x00, 0xff, 0x1c, KEY_EPG }, /* EPG */
- { 0x00, 0xff, 0x00, KEY_TAB }, /* Tab */
- { 0x00, 0xff, 0x48, KEY_INFO }, /* Preview */
- { 0x00, 0xff, 0x04, KEY_LIST }, /* RecordList */
- { 0x00, 0xff, 0x0f, KEY_TEXT }, /* Teletext */
- /* Key codes for the KWorld/ADSTech/JetWay remote. */
- { 0x86, 0x6b, 0x12, KEY_POWER },
- { 0x86, 0x6b, 0x0f, KEY_SELECT }, /* source */
- { 0x86, 0x6b, 0x0c, KEY_UNKNOWN }, /* scan */
- { 0x86, 0x6b, 0x0b, KEY_EPG },
- { 0x86, 0x6b, 0x10, KEY_MUTE },
- { 0x86, 0x6b, 0x01, KEY_1 },
- { 0x86, 0x6b, 0x02, KEY_2 },
- { 0x86, 0x6b, 0x03, KEY_3 },
- { 0x86, 0x6b, 0x04, KEY_4 },
- { 0x86, 0x6b, 0x05, KEY_5 },
- { 0x86, 0x6b, 0x06, KEY_6 },
- { 0x86, 0x6b, 0x07, KEY_7 },
- { 0x86, 0x6b, 0x08, KEY_8 },
- { 0x86, 0x6b, 0x09, KEY_9 },
- { 0x86, 0x6b, 0x0a, KEY_0 },
- { 0x86, 0x6b, 0x18, KEY_ZOOM },
- { 0x86, 0x6b, 0x1c, KEY_UNKNOWN }, /* preview */
- { 0x86, 0x6b, 0x13, KEY_UNKNOWN }, /* snap */
- { 0x86, 0x6b, 0x00, KEY_UNDO },
- { 0x86, 0x6b, 0x1d, KEY_RECORD },
- { 0x86, 0x6b, 0x0d, KEY_STOP },
- { 0x86, 0x6b, 0x0e, KEY_PAUSE },
- { 0x86, 0x6b, 0x16, KEY_PLAY },
- { 0x86, 0x6b, 0x11, KEY_BACK },
- { 0x86, 0x6b, 0x19, KEY_FORWARD },
- { 0x86, 0x6b, 0x14, KEY_UNKNOWN }, /* pip */
- { 0x86, 0x6b, 0x15, KEY_ESC },
- { 0x86, 0x6b, 0x1a, KEY_UP },
- { 0x86, 0x6b, 0x1e, KEY_DOWN },
- { 0x86, 0x6b, 0x1f, KEY_LEFT },
- { 0x86, 0x6b, 0x1b, KEY_RIGHT },
-};
-
-/* Hauppauge NOVA-T USB2 keys */
-static const struct { u16 raw; uint32_t key; } haupp_rc_keys [] = {
- { 0xddf, KEY_GOTO },
- { 0xdef, KEY_POWER },
- { 0xce7, KEY_TV },
- { 0xcc7, KEY_VIDEO },
- { 0xccf, KEY_AUDIO },
- { 0xcd7, KEY_MEDIA },
- { 0xcdf, KEY_EPG },
- { 0xca7, KEY_UP },
- { 0xc67, KEY_RADIO },
- { 0xcb7, KEY_LEFT },
- { 0xd2f, KEY_OK },
- { 0xcbf, KEY_RIGHT },
- { 0xcff, KEY_BACK },
- { 0xcaf, KEY_DOWN },
- { 0xc6f, KEY_MENU },
- { 0xc87, KEY_VOLUMEUP },
- { 0xc8f, KEY_VOLUMEDOWN },
- { 0xc97, KEY_CHANNEL },
- { 0xc7f, KEY_MUTE },
- { 0xd07, KEY_CHANNELUP },
- { 0xd0f, KEY_CHANNELDOWN },
- { 0xdbf, KEY_RECORD },
- { 0xdb7, KEY_STOP },
- { 0xd97, KEY_REWIND },
- { 0xdaf, KEY_PLAY },
- { 0xda7, KEY_FASTFORWARD },
- { 0xd27, KEY_LAST }, /* Skip backwards */
- { 0xd87, KEY_PAUSE },
- { 0xcf7, KEY_NEXT },
- { 0xc07, KEY_0 },
- { 0xc0f, KEY_1 },
- { 0xc17, KEY_2 },
- { 0xc1f, KEY_3 },
- { 0xc27, KEY_4 },
- { 0xc2f, KEY_5 },
- { 0xc37, KEY_6 },
- { 0xc3f, KEY_7 },
- { 0xc47, KEY_8 },
- { 0xc4f, KEY_9 },
- { 0xc57, KEY_KPASTERISK },
- { 0xc77, KEY_GRAVE }, /* # */
- { 0xc5f, KEY_RED },
- { 0xd77, KEY_GREEN },
- { 0xdc7, KEY_YELLOW },
- { 0xd4f, KEY_BLUE},
-};
-
-static int dibusb_key2event_nec(struct usb_dibusb *dib,u8 rb[5])
-{
- int i;
- switch (rb[0]) {
- case DIBUSB_RC_NEC_KEY_PRESSED:
- /* rb[1-3] is the actual key, rb[4] is a checksum */
- deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
- rb[1], rb[2], rb[3], rb[4]);
-
- if ((0xff - rb[3]) != rb[4]) {
- deb_rc("remote control checksum failed.\n");
- break;
- }
-
- /* See if we can match the raw key code. */
- for (i = 0; i < sizeof(nec_rc_keys)/sizeof(nec_rc_keys[0]); i++) {
- if (nec_rc_keys[i].c0 == rb[1] &&
- nec_rc_keys[i].c1 == rb[2] &&
- nec_rc_keys[i].c2 == rb[3]) {
-
- dib->last_event = nec_rc_keys[i].key;
- return 1;
- }
- }
- break;
- case DIBUSB_RC_NEC_KEY_REPEATED:
- /* rb[1]..rb[4] are always zero.*/
- /* Repeats often seem to occur so for the moment just ignore this. */
- return 0;
- case DIBUSB_RC_NEC_EMPTY: /* No (more) remote control keys. */
- default:
- break;
- }
- return -1;
-}
-
-static int dibusb_key2event_hauppauge(struct usb_dibusb *dib,u8 rb[4])
-{
- u16 raw;
- int i,state;
- switch (rb[0]) {
- case DIBUSB_RC_HAUPPAUGE_KEY_PRESSED:
- raw = ((rb[1] & 0x0f) << 8) | rb[2];
-
- state = !!(rb[1] & 0x40);
-
- deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to %04x state: %d\n",rb[1],rb[2],rb[3],raw,state);
- for (i = 0; i < sizeof(haupp_rc_keys)/sizeof(haupp_rc_keys[0]); i++) {
- if (haupp_rc_keys[i].raw == raw) {
- if (dib->last_event == haupp_rc_keys[i].key &&
- dib->last_state == state) {
- deb_rc("key repeat\n");
- return 0;
- } else {
- dib->last_event = haupp_rc_keys[i].key;
- dib->last_state = state;
- return 1;
- }
- }
- }
-
- break;
- case DIBUSB_RC_HAUPPAUGE_KEY_EMPTY:
- default:
- break;
- }
- return -1;
-}
-
-/*
- * Read the remote control and feed the appropriate event.
- * NEC protocol is used for remote controls
- */
-static int dibusb_read_remote_control(struct usb_dibusb *dib)
-{
- u8 b[1] = { DIBUSB_REQ_POLL_REMOTE }, rb[5];
- int ret,event = 0;
-
- if ((ret = dibusb_readwrite_usb(dib,b,1,rb,5)))
- return ret;
-
- switch (dib->dibdev->dev_cl->remote_type) {
- case DIBUSB_RC_NEC_PROTOCOL:
- event = dibusb_key2event_nec(dib,rb);
- break;
- case DIBUSB_RC_HAUPPAUGE_PROTO:
- event = dibusb_key2event_hauppauge(dib,rb);
- default:
- break;
- }
-
- /* key repeat */
- if (event == 0)
- if (++dib->repeat_key_count < dib->rc_key_repeat_count) {
- deb_rc("key repeat dropped. (%d)\n",dib->repeat_key_count);
- event = -1; /* skip this key repeat */
- }
-
- if (event == 1 || event == 0) {
- deb_rc("Translated key 0x%04x\n",event);
-
- /* Signal down and up events for this key. */
- input_report_key(&dib->rc_input_dev, dib->last_event, 1);
- input_report_key(&dib->rc_input_dev, dib->last_event, 0);
- input_sync(&dib->rc_input_dev);
-
- if (event == 1)
- dib->repeat_key_count = 0;
- }
- return 0;
-}
-
-/* Remote-control poll function - called every dib->rc_query_interval ms to see
- whether the remote control has received anything. */
-static void dibusb_remote_query(void *data)
-{
- struct usb_dibusb *dib = (struct usb_dibusb *) data;
- /* TODO: need a lock here. We can simply skip checking for the remote control
- if we're busy. */
- dibusb_read_remote_control(dib);
- schedule_delayed_work(&dib->rc_query_work,
- msecs_to_jiffies(dib->rc_query_interval));
-}
-
-int dibusb_remote_init(struct usb_dibusb *dib)
-{
- int i;
-
- if (dib->dibdev->dev_cl->remote_type == DIBUSB_RC_NO)
- return 0;
-
- /* Initialise the remote-control structures.*/
- init_input_dev(&dib->rc_input_dev);
-
- dib->rc_input_dev.evbit[0] = BIT(EV_KEY);
- dib->rc_input_dev.keycodesize = sizeof(unsigned char);
- dib->rc_input_dev.keycodemax = KEY_MAX;
- dib->rc_input_dev.name = DRIVER_DESC " remote control";
-
- switch (dib->dibdev->dev_cl->remote_type) {
- case DIBUSB_RC_NEC_PROTOCOL:
- for (i=0; i<sizeof(nec_rc_keys)/sizeof(nec_rc_keys[0]); i++)
- set_bit(nec_rc_keys[i].key, dib->rc_input_dev.keybit);
- break;
- case DIBUSB_RC_HAUPPAUGE_PROTO:
- for (i=0; i<sizeof(haupp_rc_keys)/sizeof(haupp_rc_keys[0]); i++)
- set_bit(haupp_rc_keys[i].key, dib->rc_input_dev.keybit);
- break;
- default:
- break;
- }
-
-
- input_register_device(&dib->rc_input_dev);
-
- INIT_WORK(&dib->rc_query_work, dibusb_remote_query, dib);
-
- /* Start the remote-control polling. */
- if (dib->rc_query_interval < 40)
- dib->rc_query_interval = 100; /* default */
-
- info("schedule remote query interval to %d msecs.",dib->rc_query_interval);
- schedule_delayed_work(&dib->rc_query_work,msecs_to_jiffies(dib->rc_query_interval));
-
- dib->init_state |= DIBUSB_STATE_REMOTE;
-
- return 0;
-}
-
-int dibusb_remote_exit(struct usb_dibusb *dib)
-{
- if (dib->dibdev->dev_cl->remote_type == DIBUSB_RC_NO)
- return 0;
-
- if (dib->init_state & DIBUSB_STATE_REMOTE) {
- cancel_delayed_work(&dib->rc_query_work);
- flush_scheduled_work();
- input_unregister_device(&dib->rc_input_dev);
- }
- dib->init_state &= ~DIBUSB_STATE_REMOTE;
- return 0;
-}
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-usb.c b/drivers/media/dvb/dibusb/dvb-dibusb-usb.c
deleted file mode 100644
index 642f0596a5b..00000000000
--- a/drivers/media/dvb/dibusb/dvb-dibusb-usb.c
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * dvb-dibusb-usb.c is part of the driver for mobile USB Budget DVB-T devices
- * based on reference design made by DiBcom (http://www.dibcom.fr/)
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * see dvb-dibusb-core.c for more copyright details.
- *
- * This file contains functions for initializing and handling the
- * usb specific stuff.
- */
-#include "dvb-dibusb.h"
-
-#include <linux/version.h>
-#include <linux/pci.h>
-
-int dibusb_readwrite_usb(struct usb_dibusb *dib, u8 *wbuf, u16 wlen, u8 *rbuf,
- u16 rlen)
-{
- int actlen,ret = -ENOMEM;
-
- if (wbuf == NULL || wlen == 0)
- return -EINVAL;
-
- if ((ret = down_interruptible(&dib->usb_sem)))
- return ret;
-
- debug_dump(wbuf,wlen);
-
- ret = usb_bulk_msg(dib->udev,usb_sndbulkpipe(dib->udev,
- dib->dibdev->dev_cl->pipe_cmd), wbuf,wlen,&actlen,
- DIBUSB_I2C_TIMEOUT);
-
- if (ret)
- err("bulk message failed: %d (%d/%d)",ret,wlen,actlen);
- else
- ret = actlen != wlen ? -1 : 0;
-
- /* an answer is expected, and no error before */
- if (!ret && rbuf && rlen) {
- ret = usb_bulk_msg(dib->udev,usb_rcvbulkpipe(dib->udev,
- dib->dibdev->dev_cl->pipe_cmd),rbuf,rlen,&actlen,
- DIBUSB_I2C_TIMEOUT);
-
- if (ret)
- err("recv bulk message failed: %d",ret);
- else {
- deb_alot("rlen: %d\n",rlen);
- debug_dump(rbuf,actlen);
- }
- }
-
- up(&dib->usb_sem);
- return ret;
-}
-
-/*
- * Cypress controls
- */
-int dibusb_write_usb(struct usb_dibusb *dib, u8 *buf, u16 len)
-{
- return dibusb_readwrite_usb(dib,buf,len,NULL,0);
-}
-
-#if 0
-/*
- * #if 0'ing the following functions as they are not in use _now_,
- * but probably will be sometime.
- */
-/*
- * do not use this, just a workaround for a bug,
- * which will hopefully never occur :).
- */
-int dibusb_interrupt_read_loop(struct usb_dibusb *dib)
-{
- u8 b[1] = { DIBUSB_REQ_INTR_READ };
- return dibusb_write_usb(dib,b,1);
-}
-#endif
-
-/*
- * ioctl for the firmware
- */
-static int dibusb_ioctl_cmd(struct usb_dibusb *dib, u8 cmd, u8 *param, int plen)
-{
- u8 b[34];
- int size = plen > 32 ? 32 : plen;
- memset(b,0,34);
- b[0] = DIBUSB_REQ_SET_IOCTL;
- b[1] = cmd;
-
- if (size > 0)
- memcpy(&b[2],param,size);
-
- return dibusb_write_usb(dib,b,34); //2+size);
-}
-
-/*
- * ioctl for power control
- */
-int dibusb_hw_wakeup(struct dvb_frontend *fe)
-{
- struct usb_dibusb *dib = (struct usb_dibusb *) fe->dvb->priv;
- u8 b[1] = { DIBUSB_IOCTL_POWER_WAKEUP };
- deb_info("dibusb-device is getting up.\n");
-
- switch (dib->dibdev->dev_cl->id) {
- case DTT200U:
- break;
- default:
- dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1);
- break;
- }
-
- if (dib->fe_init)
- return dib->fe_init(fe);
-
- return 0;
-}
-
-int dibusb_hw_sleep(struct dvb_frontend *fe)
-{
- struct usb_dibusb *dib = (struct usb_dibusb *) fe->dvb->priv;
- u8 b[1] = { DIBUSB_IOCTL_POWER_SLEEP };
- deb_info("dibusb-device is going to bed.\n");
- /* workaround, something is wrong, when dibusb 1.1 device are going to bed too late */
- switch (dib->dibdev->dev_cl->id) {
- case DIBUSB1_1:
- case NOVAT_USB2:
- case DTT200U:
- break;
- default:
- dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1);
- break;
- }
- if (dib->fe_sleep)
- return dib->fe_sleep(fe);
-
- return 0;
-}
-
-int dibusb_set_streaming_mode(struct usb_dibusb *dib,u8 mode)
-{
- u8 b[2] = { DIBUSB_REQ_SET_STREAMING_MODE, mode };
- return dibusb_readwrite_usb(dib,b,2,NULL,0);
-}
-
-static int dibusb_urb_kill(struct usb_dibusb *dib)
-{
- int i;
-deb_info("trying to kill urbs\n");
- if (dib->init_state & DIBUSB_STATE_URB_SUBMIT) {
- for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) {
- deb_info("killing URB no. %d.\n",i);
-
- /* stop the URB */
- usb_kill_urb(dib->urb_list[i]);
- }
- } else
- deb_info(" URBs not killed.\n");
- dib->init_state &= ~DIBUSB_STATE_URB_SUBMIT;
- return 0;
-}
-
-static int dibusb_urb_submit(struct usb_dibusb *dib)
-{
- int i,ret;
- if (dib->init_state & DIBUSB_STATE_URB_INIT) {
- for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) {
- deb_info("submitting URB no. %d\n",i);
- if ((ret = usb_submit_urb(dib->urb_list[i],GFP_ATOMIC))) {
- err("could not submit buffer urb no. %d - get them all back\n",i);
- dibusb_urb_kill(dib);
- return ret;
- }
- dib->init_state |= DIBUSB_STATE_URB_SUBMIT;
- }
- }
- return 0;
-}
-
-int dibusb_streaming(struct usb_dibusb *dib,int onoff)
-{
- if (onoff)
- dibusb_urb_submit(dib);
- else
- dibusb_urb_kill(dib);
-
- switch (dib->dibdev->dev_cl->id) {
- case DIBUSB2_0:
- case DIBUSB2_0B:
- case NOVAT_USB2:
- case UMT2_0:
- if (onoff)
- return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_ENABLE_STREAM,NULL,0);
- else
- return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_DISABLE_STREAM,NULL,0);
- break;
- default:
- break;
- }
- return 0;
-}
-
-int dibusb_urb_init(struct usb_dibusb *dib)
-{
- int i,bufsize,def_pid_parse = 1;
-
- /*
- * when reloading the driver w/o replugging the device
- * a timeout occures, this helps
- */
- usb_clear_halt(dib->udev,usb_sndbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_cmd));
- usb_clear_halt(dib->udev,usb_rcvbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_cmd));
- usb_clear_halt(dib->udev,usb_rcvbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_data));
-
- /* allocate the array for the data transfer URBs */
- dib->urb_list = kmalloc(dib->dibdev->dev_cl->urb_count*sizeof(struct urb *),GFP_KERNEL);
- if (dib->urb_list == NULL)
- return -ENOMEM;
- memset(dib->urb_list,0,dib->dibdev->dev_cl->urb_count*sizeof(struct urb *));
-
- dib->init_state |= DIBUSB_STATE_URB_LIST;
-
- bufsize = dib->dibdev->dev_cl->urb_count*dib->dibdev->dev_cl->urb_buffer_size;
- deb_info("allocate %d bytes as buffersize for all URBs\n",bufsize);
- /* allocate the actual buffer for the URBs */
- if ((dib->buffer = pci_alloc_consistent(NULL,bufsize,&dib->dma_handle)) == NULL) {
- deb_info("not enough memory.\n");
- return -ENOMEM;
- }
- deb_info("allocation complete\n");
- memset(dib->buffer,0,bufsize);
-
- dib->init_state |= DIBUSB_STATE_URB_BUF;
-
- /* allocate and submit the URBs */
- for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) {
- if (!(dib->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC))) {
- return -ENOMEM;
- }
-
- usb_fill_bulk_urb( dib->urb_list[i], dib->udev,
- usb_rcvbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_data),
- &dib->buffer[i*dib->dibdev->dev_cl->urb_buffer_size],
- dib->dibdev->dev_cl->urb_buffer_size,
- dibusb_urb_complete, dib);
-
- dib->urb_list[i]->transfer_flags = 0;
-
- dib->init_state |= DIBUSB_STATE_URB_INIT;
- }
-
- /* dib->pid_parse here contains the value of the module parameter */
- /* decide if pid parsing can be deactivated:
- * is possible (by device type) and wanted (by user)
- */
- switch (dib->dibdev->dev_cl->id) {
- case DIBUSB2_0:
- case DIBUSB2_0B:
- if (dib->udev->speed == USB_SPEED_HIGH && !dib->pid_parse) {
- def_pid_parse = 0;
- info("running at HIGH speed, will deliver the complete TS.");
- } else
- info("will use pid_parsing.");
- break;
- default:
- break;
- }
- /* from here on it contains the device and user decision */
- dib->pid_parse = def_pid_parse;
-
- return 0;
-}
-
-int dibusb_urb_exit(struct usb_dibusb *dib)
-{
- int i;
-
- dibusb_urb_kill(dib);
-
- if (dib->init_state & DIBUSB_STATE_URB_LIST) {
- for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) {
- if (dib->urb_list[i] != NULL) {
- deb_info("freeing URB no. %d.\n",i);
- /* free the URBs */
- usb_free_urb(dib->urb_list[i]);
- }
- }
- /* free the urb array */
- kfree(dib->urb_list);
- dib->init_state &= ~DIBUSB_STATE_URB_LIST;
- }
-
- if (dib->init_state & DIBUSB_STATE_URB_BUF)
- pci_free_consistent(NULL,
- dib->dibdev->dev_cl->urb_buffer_size*dib->dibdev->dev_cl->urb_count,
- dib->buffer,dib->dma_handle);
-
- dib->init_state &= ~DIBUSB_STATE_URB_BUF;
- dib->init_state &= ~DIBUSB_STATE_URB_INIT;
- return 0;
-}
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb.h b/drivers/media/dvb/dibusb/dvb-dibusb.h
deleted file mode 100644
index 52cd35dd9d8..00000000000
--- a/drivers/media/dvb/dibusb/dvb-dibusb.h
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * dvb-dibusb.h
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * 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, version 2.
- *
- * for more information see dvb-dibusb-core.c .
- */
-#ifndef __DVB_DIBUSB_H__
-#define __DVB_DIBUSB_H__
-
-#include <linux/input.h>
-#include <linux/config.h>
-#include <linux/usb.h>
-
-#include "dvb_frontend.h"
-#include "dvb_demux.h"
-#include "dvb_net.h"
-#include "dmxdev.h"
-
-#include "dib3000.h"
-#include "mt352.h"
-
-/* debug */
-#ifdef CONFIG_DVB_DIBCOM_DEBUG
-#define dprintk(level,args...) \
- do { if ((dvb_dibusb_debug & level)) { printk(args); } } while (0)
-
-#define debug_dump(b,l) {\
- int i; \
- for (i = 0; i < l; i++) deb_xfer("%02x ", b[i]); \
- deb_xfer("\n");\
-}
-
-#else
-#define dprintk(args...)
-#define debug_dump(b,l)
-#endif
-
-extern int dvb_dibusb_debug;
-
-/* Version information */
-#define DRIVER_VERSION "0.3"
-#define DRIVER_DESC "DiBcom based USB Budget DVB-T device"
-#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de"
-
-#define deb_info(args...) dprintk(0x01,args)
-#define deb_xfer(args...) dprintk(0x02,args)
-#define deb_alot(args...) dprintk(0x04,args)
-#define deb_ts(args...) dprintk(0x08,args)
-#define deb_err(args...) dprintk(0x10,args)
-#define deb_rc(args...) dprintk(0x20,args)
-
-/* generic log methods - taken from usb.h */
-#undef err
-#define err(format, arg...) printk(KERN_ERR "dvb-dibusb: " format "\n" , ## arg)
-#undef info
-#define info(format, arg...) printk(KERN_INFO "dvb-dibusb: " format "\n" , ## arg)
-#undef warn
-#define warn(format, arg...) printk(KERN_WARNING "dvb-dibusb: " format "\n" , ## arg)
-
-struct dibusb_usb_controller {
- const char *name; /* name of the usb controller */
- u16 cpu_cs_register; /* needs to be restarted, when the firmware has been downloaded. */
-};
-
-typedef enum {
- DIBUSB1_1 = 0,
- DIBUSB1_1_AN2235,
- DIBUSB2_0,
- UMT2_0,
- DIBUSB2_0B,
- NOVAT_USB2,
- DTT200U,
-} dibusb_class_t;
-
-typedef enum {
- DIBUSB_TUNER_CABLE_THOMSON = 0,
- DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5,
- DIBUSB_TUNER_CABLE_LG_TDTP_E102P,
- DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5,
-} dibusb_tuner_t;
-
-typedef enum {
- DIBUSB_DIB3000MB = 0,
- DIBUSB_DIB3000MC,
- DIBUSB_MT352,
- DTT200U_FE,
-} dibusb_demodulator_t;
-
-typedef enum {
- DIBUSB_RC_NO = 0,
- DIBUSB_RC_NEC_PROTOCOL,
- DIBUSB_RC_HAUPPAUGE_PROTO,
-} dibusb_remote_t;
-
-struct dibusb_tuner {
- dibusb_tuner_t id;
-
- u8 pll_addr; /* tuner i2c address */
-};
-extern struct dibusb_tuner dibusb_tuner[];
-
-#define DIBUSB_POSSIBLE_I2C_ADDR_NUM 4
-struct dibusb_demod {
- dibusb_demodulator_t id;
-
- int pid_filter_count; /* counter of the internal pid_filter */
- u8 i2c_addrs[DIBUSB_POSSIBLE_I2C_ADDR_NUM]; /* list of possible i2c addresses of the demod */
-};
-
-#define DIBUSB_MAX_TUNER_NUM 2
-struct dibusb_device_class {
- dibusb_class_t id;
-
- const struct dibusb_usb_controller *usb_ctrl; /* usb controller */
- const char *firmware; /* valid firmware filenames */
-
- int pipe_cmd; /* command pipe (read/write) */
- int pipe_data; /* data pipe */
-
- int urb_count; /* number of data URBs to be submitted */
- int urb_buffer_size; /* the size of the buffer for each URB */
-
- dibusb_remote_t remote_type; /* does this device have a ir-receiver */
-
- struct dibusb_demod *demod; /* which demodulator is mount */
- struct dibusb_tuner *tuner; /* which tuner can be found here */
-};
-
-#define DIBUSB_ID_MAX_NUM 15
-struct dibusb_usb_device {
- const char *name; /* real name of the box */
- struct dibusb_device_class *dev_cl; /* which dibusb_device_class is this device part of */
-
- struct usb_device_id *cold_ids[DIBUSB_ID_MAX_NUM]; /* list of USB ids when this device is at pre firmware state */
- struct usb_device_id *warm_ids[DIBUSB_ID_MAX_NUM]; /* list of USB ids when this device is at post firmware state */
-};
-
-/* a PID for the pid_filter list, when in use */
-struct dibusb_pid
-{
- int index;
- u16 pid;
- int active;
-};
-
-struct usb_dibusb {
- /* usb */
- struct usb_device * udev;
-
- struct dibusb_usb_device * dibdev;
-
-#define DIBUSB_STATE_INIT 0x000
-#define DIBUSB_STATE_URB_LIST 0x001
-#define DIBUSB_STATE_URB_BUF 0x002
-#define DIBUSB_STATE_URB_INIT 0x004
-#define DIBUSB_STATE_DVB 0x008
-#define DIBUSB_STATE_I2C 0x010
-#define DIBUSB_STATE_REMOTE 0x020
-#define DIBUSB_STATE_URB_SUBMIT 0x040
- int init_state;
-
- int feedcount;
- struct dib_fe_xfer_ops xfer_ops;
-
- struct dibusb_tuner *tuner;
-
- struct urb **urb_list;
- u8 *buffer;
- dma_addr_t dma_handle;
-
- /* I2C */
- struct i2c_adapter i2c_adap;
-
- /* locking */
- struct semaphore usb_sem;
- struct semaphore i2c_sem;
-
- /* dvb */
- struct dvb_adapter *adapter;
- struct dmxdev dmxdev;
- struct dvb_demux demux;
- struct dvb_net dvb_net;
- struct dvb_frontend* fe;
-
- int (*fe_sleep) (struct dvb_frontend *);
- int (*fe_init) (struct dvb_frontend *);
-
- /* remote control */
- struct input_dev rc_input_dev;
- struct work_struct rc_query_work;
- int last_event;
- int last_state; /* for Hauppauge RC protocol */
- int repeat_key_count;
- int rc_key_repeat_count; /* module parameter */
-
- /* module parameters */
- int pid_parse;
- int rc_query_interval;
-};
-
-/* commonly used functions in the separated files */
-
-/* dvb-dibusb-firmware.c */
-int dibusb_loadfirmware(struct usb_device *udev, struct dibusb_usb_device *dibdev);
-
-/* dvb-dibusb-remote.c */
-int dibusb_remote_exit(struct usb_dibusb *dib);
-int dibusb_remote_init(struct usb_dibusb *dib);
-
-/* dvb-dibusb-fe-i2c.c */
-int dibusb_fe_init(struct usb_dibusb* dib);
-int dibusb_fe_exit(struct usb_dibusb *dib);
-int dibusb_i2c_init(struct usb_dibusb *dib);
-int dibusb_i2c_exit(struct usb_dibusb *dib);
-
-/* dvb-dibusb-dvb.c */
-void dibusb_urb_complete(struct urb *urb, struct pt_regs *ptregs);
-int dibusb_dvb_init(struct usb_dibusb *dib);
-int dibusb_dvb_exit(struct usb_dibusb *dib);
-
-/* dvb-dibusb-usb.c */
-int dibusb_readwrite_usb(struct usb_dibusb *dib, u8 *wbuf, u16 wlen, u8 *rbuf,
- u16 rlen);
-int dibusb_write_usb(struct usb_dibusb *dib, u8 *buf, u16 len);
-
-int dibusb_hw_wakeup(struct dvb_frontend *);
-int dibusb_hw_sleep(struct dvb_frontend *);
-int dibusb_set_streaming_mode(struct usb_dibusb *,u8);
-int dibusb_streaming(struct usb_dibusb *,int);
-
-int dibusb_urb_init(struct usb_dibusb *);
-int dibusb_urb_exit(struct usb_dibusb *);
-
-/* dvb-fe-dtt200u.c */
-struct dvb_frontend* dtt200u_fe_attach(struct usb_dibusb *,struct dib_fe_xfer_ops *);
-
-/* i2c and transfer stuff */
-#define DIBUSB_I2C_TIMEOUT 5000
-
-/*
- * protocol of all dibusb related devices
- */
-
-/*
- * bulk msg to/from endpoint 0x01
- *
- * general structure:
- * request_byte parameter_bytes
- */
-
-#define DIBUSB_REQ_START_READ 0x00
-#define DIBUSB_REQ_START_DEMOD 0x01
-
-/*
- * i2c read
- * bulk write: 0x02 ((7bit i2c_addr << 1) & 0x01) register_bytes length_word
- * bulk read: byte_buffer (length_word bytes)
- */
-#define DIBUSB_REQ_I2C_READ 0x02
-
-/*
- * i2c write
- * bulk write: 0x03 (7bit i2c_addr << 1) register_bytes value_bytes
- */
-#define DIBUSB_REQ_I2C_WRITE 0x03
-
-/*
- * polling the value of the remote control
- * bulk write: 0x04
- * bulk read: byte_buffer (5 bytes)
- *
- * first byte of byte_buffer shows the status (0x00, 0x01, 0x02)
- */
-#define DIBUSB_REQ_POLL_REMOTE 0x04
-
-#define DIBUSB_RC_NEC_EMPTY 0x00
-#define DIBUSB_RC_NEC_KEY_PRESSED 0x01
-#define DIBUSB_RC_NEC_KEY_REPEATED 0x02
-
-/* additional status values for Hauppauge Remote Control Protocol */
-#define DIBUSB_RC_HAUPPAUGE_KEY_PRESSED 0x01
-#define DIBUSB_RC_HAUPPAUGE_KEY_EMPTY 0x03
-
-/* streaming mode:
- * bulk write: 0x05 mode_byte
- *
- * mode_byte is mostly 0x00
- */
-#define DIBUSB_REQ_SET_STREAMING_MODE 0x05
-
-/* interrupt the internal read loop, when blocking */
-#define DIBUSB_REQ_INTR_READ 0x06
-
-/* io control
- * 0x07 cmd_byte param_bytes
- *
- * param_bytes can be up to 32 bytes
- *
- * cmd_byte function parameter name
- * 0x00 power mode
- * 0x00 sleep
- * 0x01 wakeup
- *
- * 0x01 enable streaming
- * 0x02 disable streaming
- *
- *
- */
-#define DIBUSB_REQ_SET_IOCTL 0x07
-
-/* IOCTL commands */
-
-/* change the power mode in firmware */
-#define DIBUSB_IOCTL_CMD_POWER_MODE 0x00
-#define DIBUSB_IOCTL_POWER_SLEEP 0x00
-#define DIBUSB_IOCTL_POWER_WAKEUP 0x01
-
-/* modify streaming of the FX2 */
-#define DIBUSB_IOCTL_CMD_ENABLE_STREAM 0x01
-#define DIBUSB_IOCTL_CMD_DISABLE_STREAM 0x02
-
-#endif
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 1863f1dfb00..c225de7ffd8 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -175,8 +175,8 @@ static inline void dvb_dmxdev_dvr_state_set(struct dmxdev_dvr *dmxdevdvr, int st
static int dvb_dvr_open(struct inode *inode, struct file *file)
{
- struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
- struct dmxdev *dmxdev=(struct dmxdev *) dvbdev->priv;
+ struct dvb_device *dvbdev = file->private_data;
+ struct dmxdev *dmxdev = dvbdev->priv;
struct dmx_frontend *front;
dprintk ("function : %s\n", __FUNCTION__);
@@ -224,8 +224,8 @@ static int dvb_dvr_open(struct inode *inode, struct file *file)
static int dvb_dvr_release(struct inode *inode, struct file *file)
{
- struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
- struct dmxdev *dmxdev=(struct dmxdev *) dvbdev->priv;
+ struct dvb_device *dvbdev = file->private_data;
+ struct dmxdev *dmxdev = dvbdev->priv;
if (down_interruptible (&dmxdev->mutex))
return -ERESTARTSYS;
@@ -252,8 +252,8 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
static ssize_t dvb_dvr_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
- struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
- struct dmxdev *dmxdev=(struct dmxdev *) dvbdev->priv;
+ struct dvb_device *dvbdev = file->private_data;
+ struct dmxdev *dmxdev = dvbdev->priv;
int ret;
if (!dmxdev->demux->write)
@@ -270,8 +270,8 @@ static ssize_t dvb_dvr_write(struct file *file, const char __user *buf,
static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos)
{
- struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
- struct dmxdev *dmxdev=(struct dmxdev *) dvbdev->priv;
+ struct dvb_device *dvbdev = file->private_data;
+ struct dmxdev *dmxdev = dvbdev->priv;
int ret;
//down(&dmxdev->mutex);
@@ -345,7 +345,7 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
const u8 *buffer2, size_t buffer2_len,
struct dmx_section_filter *filter, enum dmx_success success)
{
- struct dmxdev_filter *dmxdevfilter=(struct dmxdev_filter *) filter->priv;
+ struct dmxdev_filter *dmxdevfilter = filter->priv;
int ret;
if (dmxdevfilter->buffer.error) {
@@ -381,7 +381,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
const u8 *buffer2, size_t buffer2_len,
struct dmx_ts_feed *feed, enum dmx_success success)
{
- struct dmxdev_filter *dmxdevfilter=(struct dmxdev_filter *) feed->priv;
+ struct dmxdev_filter *dmxdevfilter = feed->priv;
struct dmxdev_buffer *buffer;
int ret;
@@ -684,8 +684,8 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
static int dvb_demux_open(struct inode *inode, struct file *file)
{
- struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
- struct dmxdev *dmxdev=(struct dmxdev *) dvbdev->priv;
+ struct dvb_device *dvbdev = file->private_data;
+ struct dmxdev *dmxdev = dvbdev->priv;
int i;
struct dmxdev_filter *dmxdevfilter;
@@ -1013,8 +1013,8 @@ static struct dvb_device dvbdev_demux = {
static int dvb_dvr_do_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, void *parg)
{
- struct dvb_device *dvbdev=(struct dvb_device *) file->private_data;
- struct dmxdev *dmxdev=(struct dmxdev *) dvbdev->priv;
+ struct dvb_device *dvbdev = file->private_data;
+ struct dmxdev *dmxdev = dvbdev->priv;
int ret=0;
@@ -1044,8 +1044,8 @@ static int dvb_dvr_ioctl(struct inode *inode, struct file *file,
static unsigned int dvb_dvr_poll (struct file *file, poll_table *wait)
{
- struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
- struct dmxdev *dmxdev = (struct dmxdev *) dvbdev->priv;
+ struct dvb_device *dvbdev = file->private_data;
+ struct dmxdev *dmxdev = dvbdev->priv;
unsigned int mask = 0;
dprintk ("function : %s\n", __FUNCTION__);
diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
index c1ea89f2880..0eb9aa711fb 100644
--- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c
@@ -829,7 +829,7 @@ EXPORT_SYMBOL(dvb_ca_en50221_camready_irq);
*/
void dvb_ca_en50221_camchange_irq(struct dvb_ca_en50221 *pubca, int slot, int change_type)
{
- struct dvb_ca_private *ca = (struct dvb_ca_private *) pubca->private;
+ struct dvb_ca_private *ca = pubca->private;
dprintk("CAMCHANGE IRQ slot:%i change_type:%i\n", slot, change_type);
@@ -857,7 +857,7 @@ EXPORT_SYMBOL(dvb_ca_en50221_frda_irq);
*/
void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221 *pubca, int slot)
{
- struct dvb_ca_private *ca = (struct dvb_ca_private *) pubca->private;
+ struct dvb_ca_private *ca = pubca->private;
dprintk("CAMREADY IRQ slot:%i\n", slot);
@@ -876,7 +876,7 @@ void dvb_ca_en50221_camready_irq(struct dvb_ca_en50221 *pubca, int slot)
*/
void dvb_ca_en50221_frda_irq(struct dvb_ca_en50221 *pubca, int slot)
{
- struct dvb_ca_private *ca = (struct dvb_ca_private *) pubca->private;
+ struct dvb_ca_private *ca = pubca->private;
int flags;
dprintk("FR/DA IRQ slot:%i\n", slot);
@@ -993,7 +993,7 @@ static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca)
*/
static int dvb_ca_en50221_thread(void *data)
{
- struct dvb_ca_private *ca = (struct dvb_ca_private *) data;
+ struct dvb_ca_private *ca = data;
char name[15];
int slot;
int flags;
@@ -1202,8 +1202,8 @@ static int dvb_ca_en50221_thread(void *data)
static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, void *parg)
{
- struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
- struct dvb_ca_private *ca = (struct dvb_ca_private *) dvbdev->priv;
+ struct dvb_device *dvbdev = file->private_data;
+ struct dvb_ca_private *ca = dvbdev->priv;
int err = 0;
int slot;
@@ -1225,7 +1225,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file,
break;
case CA_GET_CAP: {
- struct ca_caps *caps = (struct ca_caps *) parg;
+ struct ca_caps *caps = parg;
caps->slot_num = ca->slot_count;
caps->slot_type = CA_CI_LINK;
@@ -1235,7 +1235,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct inode *inode, struct file *file,
}
case CA_GET_SLOT_INFO: {
- struct ca_slot_info *info = (struct ca_slot_info *) parg;
+ struct ca_slot_info *info = parg;
if ((info->num > ca->slot_count) || (info->num < 0))
return -EINVAL;
@@ -1291,8 +1291,8 @@ static int dvb_ca_en50221_io_ioctl(struct inode *inode, struct file *file,
static ssize_t dvb_ca_en50221_io_write(struct file *file,
const char __user * buf, size_t count, loff_t * ppos)
{
- struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
- struct dvb_ca_private *ca = (struct dvb_ca_private *) dvbdev->priv;
+ struct dvb_device *dvbdev = file->private_data;
+ struct dvb_ca_private *ca = dvbdev->priv;
u8 slot, connection_id;
int status;
char fragbuf[HOST_LINK_BUF_SIZE];
@@ -1428,8 +1428,8 @@ static int dvb_ca_en50221_io_read_condition(struct dvb_ca_private *ca, int *resu
static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf,
size_t count, loff_t * ppos)
{
- struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
- struct dvb_ca_private *ca = (struct dvb_ca_private *) dvbdev->priv;
+ struct dvb_device *dvbdev = file->private_data;
+ struct dvb_ca_private *ca = dvbdev->priv;
int status;
int result = 0;
u8 hdr[2];
@@ -1526,8 +1526,8 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf,
*/
static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
{
- struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
- struct dvb_ca_private *ca = (struct dvb_ca_private *) dvbdev->priv;
+ struct dvb_device *dvbdev = file->private_data;
+ struct dvb_ca_private *ca = dvbdev->priv;
int err;
int i;
@@ -1569,8 +1569,8 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)
*/
static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
{
- struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
- struct dvb_ca_private *ca = (struct dvb_ca_private *) dvbdev->priv;
+ struct dvb_device *dvbdev = file->private_data;
+ struct dvb_ca_private *ca = dvbdev->priv;
int err = 0;
dprintk("%s\n", __FUNCTION__);
@@ -1597,8 +1597,8 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)
*/
static unsigned int dvb_ca_en50221_io_poll(struct file *file, poll_table * wait)
{
- struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
- struct dvb_ca_private *ca = (struct dvb_ca_private *) dvbdev->priv;
+ struct dvb_device *dvbdev = file->private_data;
+ struct dvb_ca_private *ca = dvbdev->priv;
unsigned int mask = 0;
int slot;
int result = 0;
@@ -1750,7 +1750,7 @@ EXPORT_SYMBOL(dvb_ca_en50221_release);
*/
void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
{
- struct dvb_ca_private *ca = (struct dvb_ca_private *) pubca->private;
+ struct dvb_ca_private *ca = pubca->private;
int i;
dprintk("%s\n", __FUNCTION__);
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index 59a9adfae1e..f11daae91cd 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -35,6 +35,7 @@
#include <linux/moduleparam.h>
#include <linux/list.h>
#include <linux/suspend.h>
+#include <linux/jiffies.h>
#include <asm/processor.h>
#include <asm/semaphore.h>
@@ -48,7 +49,7 @@ static int dvb_override_tune_delay;
static int dvb_powerdown_on_sleep = 1;
module_param_named(frontend_debug, dvb_frontend_debug, int, 0644);
-MODULE_PARM_DESC(dvb_frontend_debug, "Turn on/off frontend core debugging (default:off).");
+MODULE_PARM_DESC(frontend_debug, "Turn on/off frontend core debugging (default:off).");
module_param(dvb_shutdown_timeout, int, 0444);
MODULE_PARM_DESC(dvb_shutdown_timeout, "wait <shutdown_timeout> seconds after close() before suspending hardware");
module_param(dvb_force_auto_inversion, int, 0444);
@@ -117,7 +118,7 @@ struct dvb_frontend_private {
static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
{
- struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) fe->frontend_priv;
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
struct dvb_fe_events *events = &fepriv->events;
struct dvb_frontend_event *e;
int wp;
@@ -155,7 +156,7 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
static int dvb_frontend_get_event(struct dvb_frontend *fe,
struct dvb_frontend_event *event, int flags)
{
- struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) fe->frontend_priv;
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
struct dvb_fe_events *events = &fepriv->events;
dprintk ("%s\n", __FUNCTION__);
@@ -234,7 +235,7 @@ static int dvb_frontend_autotune(struct dvb_frontend *fe, int check_wrapped)
{
int autoinversion;
int ready = 0;
- struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) fe->frontend_priv;
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
int original_inversion = fepriv->parameters.inversion;
u32 original_frequency = fepriv->parameters.frequency;
@@ -321,13 +322,14 @@ static int dvb_frontend_autotune(struct dvb_frontend *fe, int check_wrapped)
static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
{
- struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) fe->frontend_priv;
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
if (fepriv->exit)
return 1;
if (fepriv->dvbdev->writers == 1)
- if (jiffies - fepriv->release_jiffies > dvb_shutdown_timeout * HZ)
+ if (time_after(jiffies, fepriv->release_jiffies +
+ dvb_shutdown_timeout * HZ))
return 1;
return 0;
@@ -335,7 +337,7 @@ static int dvb_frontend_is_exiting(struct dvb_frontend *fe)
static int dvb_frontend_should_wakeup(struct dvb_frontend *fe)
{
- struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) fe->frontend_priv;
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
if (fepriv->wakeup) {
fepriv->wakeup = 0;
@@ -346,7 +348,7 @@ static int dvb_frontend_should_wakeup(struct dvb_frontend *fe)
static void dvb_frontend_wakeup(struct dvb_frontend *fe)
{
- struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) fe->frontend_priv;
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
fepriv->wakeup = 1;
wake_up_interruptible(&fepriv->wait_queue);
@@ -357,8 +359,8 @@ static void dvb_frontend_wakeup(struct dvb_frontend *fe)
*/
static int dvb_frontend_thread(void *data)
{
- struct dvb_frontend *fe = (struct dvb_frontend *) data;
- struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) fe->frontend_priv;
+ struct dvb_frontend *fe = data;
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
unsigned long timeout;
char name [15];
int quality = 0, delay = 3*HZ;
@@ -389,8 +391,7 @@ static int dvb_frontend_thread(void *data)
break;
}
- if (current->flags & PF_FREEZE)
- refrigerator(PF_FREEZE);
+ try_to_freeze();
if (down_interruptible(&fepriv->sem))
break;
@@ -520,7 +521,7 @@ static int dvb_frontend_thread(void *data)
static void dvb_frontend_stop(struct dvb_frontend *fe)
{
unsigned long ret;
- struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) fe->frontend_priv;
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
dprintk ("%s\n", __FUNCTION__);
@@ -559,7 +560,7 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
static int dvb_frontend_start(struct dvb_frontend *fe)
{
int ret;
- struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) fe->frontend_priv;
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
dprintk ("%s\n", __FUNCTION__);
@@ -597,7 +598,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
{
struct dvb_device *dvbdev = file->private_data;
struct dvb_frontend *fe = dvbdev->priv;
- struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) fe->frontend_priv;
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
int err = -EOPNOTSUPP;
dprintk ("%s\n", __FUNCTION__);
@@ -615,7 +616,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file,
switch (cmd) {
case FE_GET_INFO: {
- struct dvb_frontend_info* info = (struct dvb_frontend_info*) parg;
+ struct dvb_frontend_info* info = parg;
memcpy(info, &fe->ops->info, sizeof(struct dvb_frontend_info));
/* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't
@@ -793,7 +794,7 @@ static unsigned int dvb_frontend_poll(struct file *file, struct poll_table_struc
{
struct dvb_device *dvbdev = file->private_data;
struct dvb_frontend *fe = dvbdev->priv;
- struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) fe->frontend_priv;
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
dprintk ("%s\n", __FUNCTION__);
@@ -809,7 +810,7 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev = file->private_data;
struct dvb_frontend *fe = dvbdev->priv;
- struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) fe->frontend_priv;
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
int ret;
dprintk ("%s\n", __FUNCTION__);
@@ -833,7 +834,7 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev = file->private_data;
struct dvb_frontend *fe = dvbdev->priv;
- struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) fe->frontend_priv;
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
dprintk ("%s\n", __FUNCTION__);
@@ -873,7 +874,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
up(&frontend_mutex);
return -ENOMEM;
}
- fepriv = (struct dvb_frontend_private*) fe->frontend_priv;
+ fepriv = fe->frontend_priv;
memset(fe->frontend_priv, 0, sizeof(struct dvb_frontend_private));
init_MUTEX (&fepriv->sem);
@@ -897,7 +898,7 @@ EXPORT_SYMBOL(dvb_register_frontend);
int dvb_unregister_frontend(struct dvb_frontend* fe)
{
- struct dvb_frontend_private *fepriv = (struct dvb_frontend_private*) fe->frontend_priv;
+ struct dvb_frontend_private *fepriv = fe->frontend_priv;
dprintk ("%s\n", __FUNCTION__);
down (&frontend_mutex);
diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
index 44892e7abd3..6a968c346a3 100644
--- a/drivers/media/dvb/dvb-core/dvb_net.c
+++ b/drivers/media/dvb/dvb-core/dvb_net.c
@@ -315,7 +315,7 @@ static inline void reset_ule( struct dvb_net_priv *p )
*/
static void dvb_net_ule( struct net_device *dev, const u8 *buf, size_t buf_len )
{
- struct dvb_net_priv *priv = (struct dvb_net_priv *)dev->priv;
+ struct dvb_net_priv *priv = dev->priv;
unsigned long skipped = 0L;
u8 *ts, *ts_end, *from_where = NULL, ts_remain = 0, how_much = 0, new_ts = 1;
struct ethhdr *ethh = NULL;
@@ -709,7 +709,7 @@ static int dvb_net_ts_callback(const u8 *buffer1, size_t buffer1_len,
const u8 *buffer2, size_t buffer2_len,
struct dmx_ts_feed *feed, enum dmx_success success)
{
- struct net_device *dev = (struct net_device *)feed->priv;
+ struct net_device *dev = feed->priv;
if (buffer2 != 0)
printk(KERN_WARNING "buffer2 not 0: %p.\n", buffer2);
@@ -727,6 +727,7 @@ static void dvb_net_sec(struct net_device *dev, u8 *pkt, int pkt_len)
u8 *eth;
struct sk_buff *skb;
struct net_device_stats *stats = &(((struct dvb_net_priv *) dev->priv)->stats);
+ int snap = 0;
/* note: pkt_len includes a 32bit checksum */
if (pkt_len < 16) {
@@ -750,9 +751,12 @@ static void dvb_net_sec(struct net_device *dev, u8 *pkt, int pkt_len)
return;
}
if (pkt[5] & 0x02) {
- //FIXME: handle LLC/SNAP
- stats->rx_dropped++;
- return;
+ /* handle LLC/SNAP, see rfc-1042 */
+ if (pkt_len < 24 || memcmp(&pkt[12], "\xaa\xaa\x03\0\0\0", 6)) {
+ stats->rx_dropped++;
+ return;
+ }
+ snap = 8;
}
if (pkt[7]) {
/* FIXME: assemble datagram from multiple sections */
@@ -762,9 +766,9 @@ static void dvb_net_sec(struct net_device *dev, u8 *pkt, int pkt_len)
}
/* we have 14 byte ethernet header (ip header follows);
- * 12 byte MPE header; 4 byte checksum; + 2 byte alignment
+ * 12 byte MPE header; 4 byte checksum; + 2 byte alignment, 8 byte LLC/SNAP
*/
- if (!(skb = dev_alloc_skb(pkt_len - 4 - 12 + 14 + 2))) {
+ if (!(skb = dev_alloc_skb(pkt_len - 4 - 12 + 14 + 2 - snap))) {
//printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
stats->rx_dropped++;
return;
@@ -773,8 +777,8 @@ static void dvb_net_sec(struct net_device *dev, u8 *pkt, int pkt_len)
skb->dev = dev;
/* copy L3 payload */
- eth = (u8 *) skb_put(skb, pkt_len - 12 - 4 + 14);
- memcpy(eth + 14, pkt + 12, pkt_len - 12 - 4);
+ eth = (u8 *) skb_put(skb, pkt_len - 12 - 4 + 14 - snap);
+ memcpy(eth + 14, pkt + 12 + snap, pkt_len - 12 - 4 - snap);
/* create ethernet header: */
eth[0]=pkt[0x0b];
@@ -786,8 +790,21 @@ static void dvb_net_sec(struct net_device *dev, u8 *pkt, int pkt_len)
eth[6]=eth[7]=eth[8]=eth[9]=eth[10]=eth[11]=0;
- eth[12] = 0x08; /* ETH_P_IP */
- eth[13] = 0x00;
+ if (snap) {
+ eth[12] = pkt[18];
+ eth[13] = pkt[19];
+ } else {
+ /* protocol numbers are from rfc-1700 or
+ * http://www.iana.org/assignments/ethernet-numbers
+ */
+ if (pkt[12] >> 4 == 6) { /* version field from IP header */
+ eth[12] = 0x86; /* IPv6 */
+ eth[13] = 0xdd;
+ } else {
+ eth[12] = 0x08; /* IPv4 */
+ eth[13] = 0x00;
+ }
+ }
skb->protocol = dvb_net_eth_type_trans(skb, dev);
@@ -801,7 +818,7 @@ static int dvb_net_sec_callback(const u8 *buffer1, size_t buffer1_len,
struct dmx_section_filter *filter,
enum dmx_success success)
{
- struct net_device *dev=(struct net_device *) filter->priv;
+ struct net_device *dev = filter->priv;
/**
* we rely on the DVB API definition where exactly one complete
@@ -826,7 +843,7 @@ static int dvb_net_filter_sec_set(struct net_device *dev,
struct dmx_section_filter **secfilter,
u8 *mac, u8 *mac_mask)
{
- struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
+ struct dvb_net_priv *priv = dev->priv;
int ret;
*secfilter=NULL;
@@ -870,7 +887,7 @@ static int dvb_net_filter_sec_set(struct net_device *dev,
static int dvb_net_feed_start(struct net_device *dev)
{
int ret, i;
- struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
+ struct dvb_net_priv *priv = dev->priv;
struct dmx_demux *demux = priv->demux;
unsigned char *mac = (unsigned char *) dev->dev_addr;
@@ -965,7 +982,7 @@ static int dvb_net_feed_start(struct net_device *dev)
static int dvb_net_feed_stop(struct net_device *dev)
{
- struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
+ struct dvb_net_priv *priv = dev->priv;
int i;
dprintk("%s\n", __FUNCTION__);
@@ -1016,7 +1033,7 @@ static int dvb_net_feed_stop(struct net_device *dev)
static int dvb_set_mc_filter (struct net_device *dev, struct dev_mc_list *mc)
{
- struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
+ struct dvb_net_priv *priv = dev->priv;
if (priv->multi_num == DVB_NET_MULTICAST_MAX)
return -ENOMEM;
@@ -1031,7 +1048,7 @@ static int dvb_set_mc_filter (struct net_device *dev, struct dev_mc_list *mc)
static void wq_set_multicast_list (void *data)
{
struct net_device *dev = data;
- struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
+ struct dvb_net_priv *priv = dev->priv;
dvb_net_feed_stop(dev);
@@ -1066,7 +1083,7 @@ static void wq_set_multicast_list (void *data)
static void dvb_net_set_multicast_list (struct net_device *dev)
{
- struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
+ struct dvb_net_priv *priv = dev->priv;
schedule_work(&priv->set_multicast_list_wq);
}
@@ -1084,7 +1101,7 @@ static void wq_restart_net_feed (void *data)
static int dvb_net_set_mac (struct net_device *dev, void *p)
{
- struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
+ struct dvb_net_priv *priv = dev->priv;
struct sockaddr *addr=p;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
@@ -1098,7 +1115,7 @@ static int dvb_net_set_mac (struct net_device *dev, void *p)
static int dvb_net_open(struct net_device *dev)
{
- struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
+ struct dvb_net_priv *priv = dev->priv;
priv->in_use++;
dvb_net_feed_start(dev);
@@ -1108,7 +1125,7 @@ static int dvb_net_open(struct net_device *dev)
static int dvb_net_stop(struct net_device *dev)
{
- struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv;
+ struct dvb_net_priv *priv = dev->priv;
priv->in_use--;
return dvb_net_feed_stop(dev);
@@ -1228,8 +1245,8 @@ static int dvb_net_remove_if(struct dvb_net *dvbnet, unsigned int num)
static int dvb_net_do_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, void *parg)
{
- struct dvb_device *dvbdev = (struct dvb_device *) file->private_data;
- struct dvb_net *dvbnet = (struct dvb_net *) dvbdev->priv;
+ struct dvb_device *dvbdev = file->private_data;
+ struct dvb_net *dvbnet = dvbdev->priv;
if (((file->f_flags&O_ACCMODE)==O_RDONLY))
return -EPERM;
@@ -1237,7 +1254,7 @@ static int dvb_net_do_ioctl(struct inode *inode, struct file *file,
switch (cmd) {
case NET_ADD_IF:
{
- struct dvb_net_if *dvbnetif=(struct dvb_net_if *)parg;
+ struct dvb_net_if *dvbnetif = parg;
int result;
if (!capable(CAP_SYS_ADMIN))
@@ -1258,7 +1275,7 @@ static int dvb_net_do_ioctl(struct inode *inode, struct file *file,
{
struct net_device *netdev;
struct dvb_net_priv *priv_data;
- struct dvb_net_if *dvbnetif=(struct dvb_net_if *)parg;
+ struct dvb_net_if *dvbnetif = parg;
if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX ||
!dvbnet->state[dvbnetif->if_num])
@@ -1266,7 +1283,7 @@ static int dvb_net_do_ioctl(struct inode *inode, struct file *file,
netdev = dvbnet->device[dvbnetif->if_num];
- priv_data=(struct dvb_net_priv*)netdev->priv;
+ priv_data = netdev->priv;
dvbnetif->pid=priv_data->pid;
dvbnetif->feedtype=priv_data->feedtype;
break;
@@ -1288,7 +1305,7 @@ static int dvb_net_do_ioctl(struct inode *inode, struct file *file,
/* binary compatiblity cruft */
case __NET_ADD_IF_OLD:
{
- struct __dvb_net_if_old *dvbnetif=(struct __dvb_net_if_old *)parg;
+ struct __dvb_net_if_old *dvbnetif = parg;
int result;
if (!capable(CAP_SYS_ADMIN))
@@ -1309,7 +1326,7 @@ static int dvb_net_do_ioctl(struct inode *inode, struct file *file,
{
struct net_device *netdev;
struct dvb_net_priv *priv_data;
- struct __dvb_net_if_old *dvbnetif=(struct __dvb_net_if_old *)parg;
+ struct __dvb_net_if_old *dvbnetif = parg;
if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX ||
!dvbnet->state[dvbnetif->if_num])
@@ -1317,7 +1334,7 @@ static int dvb_net_do_ioctl(struct inode *inode, struct file *file,
netdev = dvbnet->device[dvbnetif->if_num];
- priv_data=(struct dvb_net_priv*)netdev->priv;
+ priv_data = netdev->priv;
dvbnetif->pid=priv_data->pid;
break;
}
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index cf4ffe38fda..4b7adca3e28 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -56,8 +56,7 @@ static const char * const dnames[] = {
#define nums2minor(num,type,id) ((num << 6) | (id << 4) | type)
#define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64)
-struct class_simple *dvb_class;
-EXPORT_SYMBOL(dvb_class);
+static struct class *dvb_class;
static struct dvb_device* dvbdev_find_device (int minor)
{
@@ -236,8 +235,8 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
S_IFCHR | S_IRUSR | S_IWUSR,
"dvb/adapter%d/%s%d", adap->num, dnames[type], id);
- class_simple_device_add(dvb_class, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
- NULL, "dvb%d.%s%d", adap->num, dnames[type], id);
+ class_device_create(dvb_class, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
+ NULL, "dvb%d.%s%d", adap->num, dnames[type], id);
dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
adap->num, dnames[type], id, nums2minor(adap->num, type, id),
@@ -256,7 +255,7 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
devfs_remove("dvb/adapter%d/%s%d", dvbdev->adapter->num,
dnames[dvbdev->type], dvbdev->id);
- class_simple_device_remove(MKDEV(DVB_MAJOR, nums2minor(dvbdev->adapter->num,
+ class_device_destroy(dvb_class, MKDEV(DVB_MAJOR, nums2minor(dvbdev->adapter->num,
dvbdev->type, dvbdev->id)));
list_del (&dvbdev->list_head);
@@ -286,9 +285,8 @@ skip:
}
-int dvb_register_adapter(struct dvb_adapter **padap, const char *name, struct module *module)
+int dvb_register_adapter(struct dvb_adapter *adap, const char *name, struct module *module)
{
- struct dvb_adapter *adap;
int num;
if (down_interruptible (&dvbdev_register_lock))
@@ -299,11 +297,6 @@ int dvb_register_adapter(struct dvb_adapter **padap, const char *name, struct mo
return -ENFILE;
}
- if (!(*padap = adap = kmalloc(sizeof(struct dvb_adapter), GFP_KERNEL))) {
- up(&dvbdev_register_lock);
- return -ENOMEM;
- }
-
memset (adap, 0, sizeof(struct dvb_adapter));
INIT_LIST_HEAD (&adap->device_list);
@@ -331,7 +324,6 @@ int dvb_unregister_adapter(struct dvb_adapter *adap)
return -ERESTARTSYS;
list_del (&adap->list_head);
up (&dvbdev_register_lock);
- kfree (adap);
return 0;
}
EXPORT_SYMBOL(dvb_unregister_adapter);
@@ -419,7 +411,7 @@ static int __init init_dvbdev(void)
devfs_mk_dir("dvb");
- dvb_class = class_simple_create(THIS_MODULE, "dvb");
+ dvb_class = class_create(THIS_MODULE, "dvb");
if (IS_ERR(dvb_class)) {
retval = PTR_ERR(dvb_class);
goto error;
@@ -436,7 +428,7 @@ error:
static void __exit exit_dvbdev(void)
{
devfs_remove("dvb");
- class_simple_destroy(dvb_class);
+ class_destroy(dvb_class);
cdev_del(&dvb_device_cdev);
unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS);
}
diff --git a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h
index 184edba3caa..a251867f30f 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.h
+++ b/drivers/media/dvb/dvb-core/dvbdev.h
@@ -76,7 +76,7 @@ struct dvb_device {
};
-extern int dvb_register_adapter (struct dvb_adapter **padap, const char *name, struct module *module);
+extern int dvb_register_adapter (struct dvb_adapter *adap, const char *name, struct module *module);
extern int dvb_unregister_adapter (struct dvb_adapter *adap);
extern int dvb_register_device (struct dvb_adapter *adap,
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
new file mode 100644
index 00000000000..8aa32f6e447
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -0,0 +1,99 @@
+config DVB_USB
+ tristate "Support for various USB DVB devices"
+ depends on DVB_CORE && USB
+ select FW_LOADER
+ help
+ By enabling this you will be able to choose the various USB 1.1 and
+ USB2.0 DVB devices.
+
+ Almost every USB device needs a firmware, please look into
+ <file:Documentation/dvb/README.dvb-usb>
+
+ Say Y if you own an USB DVB device.
+
+config DVB_USB_DEBUG
+ bool "Enable extended debug support for all DVB-USB devices"
+ depends on DVB_USB
+ help
+ Say Y if you want to enable debuging. See modinfo dvb-usb (and the
+ appropriate drivers) for debug levels.
+
+config DVB_USB_A800
+ tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)"
+ depends on DVB_USB
+ help
+ Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver.
+
+config DVB_USB_DIBUSB_MB
+ tristate "DiBcom USB DVB-T devices (based on the DiB3000M-B) (see help for device list)"
+ depends on DVB_USB
+ help
+ Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by
+ DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator.
+
+ Devices supported by this driver:
+ TwinhanDTV USB-Ter (VP7041)
+ TwinhanDTV Magic Box (VP7041e)
+ KWorld/JetWay/ADSTech V-Stream XPERT DTV - DVB-T USB1.1 and USB2.0
+ Hama DVB-T USB1.1-Box
+ DiBcom USB1.1 reference devices (non-public)
+ Ultima Electronic/Artec T1 USB TVBOX
+ Compro Videomate DVB-U2000 - DVB-T USB
+ Grandtec DVB-T USB
+ Avermedia AverTV DVBT USB1.1
+ Artec T1 USB1.1 boxes
+
+ The VP7041 seems to be identical to "CTS Portable" (Chinese
+ Television System).
+
+ Say Y if you own such a device and want to use it. You should build it as
+ a module.
+
+config DVB_USB_DIBUSB_MC
+ tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)"
+ depends on DVB_USB
+ help
+ Support for 2.0 DVB-T receivers based on reference designs made by
+ DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator.
+
+ Devices supported by this driver:
+ DiBcom USB2.0 reference devices (non-public)
+ Artec T1 USB2.0 boxes
+
+ Say Y if you own such a device and want to use it. You should build it as
+ a module.
+
+config DVB_USB_UMT_010
+ tristate "HanfTek UMT-010 DVB-T USB2.0 support"
+ depends on DVB_USB
+ help
+ Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver.
+
+config DVB_USB_DIGITV
+ tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support"
+ depends on DVB_USB
+ help
+ Say Y here to support the Nebula Electronics uDigitV USB2.0 DVB-T receiver.
+
+config DVB_USB_VP7045
+ tristate "TwinhanDTV Alpha/MagicBoxII and DNTV tinyUSB2 DVB-T USB2.0 support"
+ depends on DVB_USB
+ help
+ Say Y here to support the
+ TwinhanDTV Alpha (stick) (VP-7045),
+ TwinhanDTV MagicBox II (VP-7046) and
+ DigitalNow TinyUSB 2 DVB-t DVB-T USB2.0 receivers.
+
+config DVB_USB_NOVA_T_USB2
+ tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
+ depends on DVB_USB
+ help
+ Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver.
+
+config DVB_USB_DTT200U
+ tristate "Yakumo/Hama/Typhoon/Yuan DVB-T USB2.0 support"
+ depends on DVB_USB
+ help
+ Say Y here to support the Yakumo/Hama/Typhoon/Yuan DVB-T USB2.0 receiver.
+
+ The receivers are also known as DTT200U (Yakumo) and UB300 (Yuan).
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile
new file mode 100644
index 00000000000..d65b50f9abb
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/Makefile
@@ -0,0 +1,30 @@
+dvb-usb-objs = dvb-usb-firmware.o dvb-usb-init.o dvb-usb-urb.o dvb-usb-i2c.o dvb-usb-dvb.o dvb-usb-remote.o
+obj-$(CONFIG_DVB_USB) += dvb-usb.o
+
+dvb-usb-vp7045-objs = vp7045.o vp7045-fe.o
+obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o
+
+dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o
+obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o
+
+dvb-usb-dibusb-common-objs = dibusb-common.o
+
+dvb-usb-a800-objs = a800.o
+obj-$(CONFIG_DVB_USB_A800) += dvb-usb-dibusb-common.o dvb-usb-a800.o
+
+dvb-usb-dibusb-mb-objs = dibusb-mb.o
+obj-$(CONFIG_DVB_USB_DIBUSB_MB) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mb.o
+
+dvb-usb-dibusb-mc-objs = dibusb-mc.o
+obj-$(CONFIG_DVB_USB_DIBUSB_MC) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mc.o
+
+dvb-usb-nova-t-usb2-objs = nova-t-usb2.o
+obj-$(CONFIG_DVB_USB_NOVA_T_USB2) += dvb-usb-dibusb-common.o dvb-usb-nova-t-usb2.o
+
+dvb-usb-umt-010-objs = umt-010.o
+obj-$(CONFIG_DVB_USB_UMT_010) += dvb-usb-dibusb-common.o dvb-usb-umt-010.o
+
+dvb-usb-digitv-objs = digitv.o
+obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o
+
+EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c
new file mode 100644
index 00000000000..a3542935604
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/a800.c
@@ -0,0 +1,176 @@
+/* DVB USB framework compliant Linux driver for the AVerMedia AverTV DVB-T
+ * USB2.0 (A800) DVB-T receiver.
+ *
+ * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * Thanks to
+ * - AVerMedia who kindly provided information and
+ * - Glen Harris who suffered from my mistakes during development.
+ *
+ * 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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "dibusb.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (rc=1 (or-able))." DVB_USB_DEBUG_STATUS);
+#define deb_rc(args...) dprintk(debug,0x01,args)
+
+static int a800_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+ /* do nothing for the AVerMedia */
+ return 0;
+}
+
+static struct dvb_usb_rc_key a800_rc_keys[] = {
+ { 0x02, 0x01, KEY_PROG1 }, /* SOURCE */
+ { 0x02, 0x00, KEY_POWER }, /* POWER */
+ { 0x02, 0x05, KEY_1 }, /* 1 */
+ { 0x02, 0x06, KEY_2 }, /* 2 */
+ { 0x02, 0x07, KEY_3 }, /* 3 */
+ { 0x02, 0x09, KEY_4 }, /* 4 */
+ { 0x02, 0x0a, KEY_5 }, /* 5 */
+ { 0x02, 0x0b, KEY_6 }, /* 6 */
+ { 0x02, 0x0d, KEY_7 }, /* 7 */
+ { 0x02, 0x0e, KEY_8 }, /* 8 */
+ { 0x02, 0x0f, KEY_9 }, /* 9 */
+ { 0x02, 0x12, KEY_LEFT }, /* L / DISPLAY */
+ { 0x02, 0x11, KEY_0 }, /* 0 */
+ { 0x02, 0x13, KEY_RIGHT }, /* R / CH RTN */
+ { 0x02, 0x17, KEY_PROG2 }, /* SNAP SHOT */
+ { 0x02, 0x10, KEY_PROG3 }, /* 16-CH PREV */
+ { 0x02, 0x03, KEY_CHANNELUP }, /* CH UP */
+ { 0x02, 0x1e, KEY_VOLUMEDOWN }, /* VOL DOWN */
+ { 0x02, 0x0c, KEY_ZOOM }, /* FULL SCREEN */
+ { 0x02, 0x1f, KEY_VOLUMEUP }, /* VOL UP */
+ { 0x02, 0x02, KEY_CHANNELDOWN }, /* CH DOWN */
+ { 0x02, 0x14, KEY_MUTE }, /* MUTE */
+ { 0x02, 0x08, KEY_AUDIO }, /* AUDIO */
+ { 0x02, 0x19, KEY_RECORD }, /* RECORD */
+ { 0x02, 0x18, KEY_PLAY }, /* PLAY */
+ { 0x02, 0x1b, KEY_STOP }, /* STOP */
+ { 0x02, 0x1a, KEY_PLAYPAUSE }, /* TIMESHIFT / PAUSE */
+ { 0x02, 0x1d, KEY_BACK }, /* << / RED */
+ { 0x02, 0x1c, KEY_FORWARD }, /* >> / YELLOW */
+ { 0x02, 0x03, KEY_TEXT }, /* TELETEXT */
+ { 0x02, 0x01, KEY_FIRST }, /* |<< / GREEN */
+ { 0x02, 0x00, KEY_LAST }, /* >>| / BLUE */
+ { 0x02, 0x04, KEY_EPG }, /* EPG */
+ { 0x02, 0x15, KEY_MENU }, /* MENU */
+};
+
+int a800_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+ u8 key[5];
+ if (usb_control_msg(d->udev,usb_rcvctrlpipe(d->udev,0),
+ 0x04, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, key, 5,
+ 2*HZ) != 5)
+ return -ENODEV;
+
+ /* call the universal NEC remote processor, to find out the key's state and event */
+ dvb_usb_nec_rc_key_to_event(d,key,event,state);
+ if (key[0] != 0)
+ deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
+ return 0;
+}
+
+/* USB Driver stuff */
+static struct dvb_usb_properties a800_properties;
+
+static int a800_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return dvb_usb_device_init(intf,&a800_properties,THIS_MODULE);
+}
+
+/* do not change the order of the ID table */
+static struct usb_device_id a800_table [] = {
+/* 00 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB2_COLD) },
+/* 01 */ { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_DVBT_USB2_WARM) },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, a800_table);
+
+static struct dvb_usb_properties a800_properties = {
+ .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
+ .pid_filter_count = 32,
+
+ .usb_ctrl = CYPRESS_FX2,
+
+ .firmware = "dvb-usb-avertv-a800-02.fw",
+
+ .size_of_priv = sizeof(struct dibusb_state),
+
+ .streaming_ctrl = dibusb2_0_streaming_ctrl,
+ .pid_filter = dibusb_pid_filter,
+ .pid_filter_ctrl = dibusb_pid_filter_ctrl,
+ .power_ctrl = a800_power_ctrl,
+ .frontend_attach = dibusb_dib3000mc_frontend_attach,
+ .tuner_attach = dibusb_dib3000mc_tuner_attach,
+
+ .rc_interval = DEFAULT_RC_INTERVAL,
+ .rc_key_map = a800_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(a800_rc_keys),
+ .rc_query = a800_rc_query,
+
+ .i2c_algo = &dibusb_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+ /* parameter for the MPEG2-data transfer */
+ .urb = {
+ .type = DVB_USB_BULK,
+ .count = 7,
+ .endpoint = 0x06,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
+
+ .num_device_descs = 1,
+ .devices = {
+ { "AVerMedia AverTV DVB-T USB 2.0 (A800)",
+ { &a800_table[0], NULL },
+ { &a800_table[1], NULL },
+ },
+ }
+};
+
+static struct usb_driver a800_driver = {
+ .owner = THIS_MODULE,
+ .name = "AVerMedia AverTV DVB-T USB 2.0 (A800)",
+ .probe = a800_probe,
+ .disconnect = dvb_usb_device_exit,
+ .id_table = a800_table,
+};
+
+/* module stuff */
+static int __init a800_module_init(void)
+{
+ int result;
+ if ((result = usb_register(&a800_driver))) {
+ err("usb_register failed. Error number %d",result);
+ return result;
+ }
+
+ return 0;
+}
+
+static void __exit a800_module_exit(void)
+{
+ /* deregister this driver from the USB subsystem */
+ usb_deregister(&a800_driver);
+}
+
+module_init (a800_module_init);
+module_exit (a800_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("AVerMedia AverTV DVB-T USB 2.0 (A800)");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c
new file mode 100644
index 00000000000..63b626f70c8
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dibusb-common.c
@@ -0,0 +1,272 @@
+/* Common methods for dibusb-based-receivers.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * 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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "dibusb.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info (|-able))." DVB_USB_DEBUG_STATUS);
+MODULE_LICENSE("GPL");
+
+#define deb_info(args...) dprintk(debug,0x01,args)
+
+/* common stuff used by the different dibusb modules */
+int dibusb_streaming_ctrl(struct dvb_usb_device *d, int onoff)
+{
+ if (d->priv != NULL) {
+ struct dib_fe_xfer_ops *ops = d->priv;
+ if (ops->fifo_ctrl != NULL)
+ if (ops->fifo_ctrl(d->fe,onoff)) {
+ err("error while controlling the fifo of the demod.");
+ return -ENODEV;
+ }
+ }
+ return 0;
+}
+EXPORT_SYMBOL(dibusb_streaming_ctrl);
+
+int dibusb_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int onoff)
+{
+ if (d->priv != NULL) {
+ struct dib_fe_xfer_ops *ops = d->priv;
+ if (d->pid_filtering && ops->pid_ctrl != NULL)
+ ops->pid_ctrl(d->fe,index,pid,onoff);
+ }
+ return 0;
+}
+EXPORT_SYMBOL(dibusb_pid_filter);
+
+int dibusb_pid_filter_ctrl(struct dvb_usb_device *d, int onoff)
+{
+ if (d->priv != NULL) {
+ struct dib_fe_xfer_ops *ops = d->priv;
+ if (ops->pid_parse != NULL)
+ if (ops->pid_parse(d->fe,onoff) < 0)
+ err("could not handle pid_parser");
+ }
+ return 0;
+}
+EXPORT_SYMBOL(dibusb_pid_filter_ctrl);
+
+int dibusb_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+ u8 b[3];
+ int ret;
+ b[0] = DIBUSB_REQ_SET_IOCTL;
+ b[1] = DIBUSB_IOCTL_CMD_POWER_MODE;
+ b[2] = onoff ? DIBUSB_IOCTL_POWER_WAKEUP : DIBUSB_IOCTL_POWER_SLEEP;
+ ret = dvb_usb_generic_write(d,b,3);
+ msleep(10);
+ return ret;
+}
+EXPORT_SYMBOL(dibusb_power_ctrl);
+
+int dibusb2_0_streaming_ctrl(struct dvb_usb_device *d, int onoff)
+{
+ u8 b[2];
+ b[0] = DIBUSB_REQ_SET_IOCTL;
+ b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM;
+
+ dvb_usb_generic_write(d,b,3);
+
+ return dibusb_streaming_ctrl(d,onoff);
+}
+EXPORT_SYMBOL(dibusb2_0_streaming_ctrl);
+
+int dibusb2_0_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+ if (onoff) {
+ u8 b[3] = { DIBUSB_REQ_SET_IOCTL, DIBUSB_IOCTL_CMD_POWER_MODE, DIBUSB_IOCTL_POWER_WAKEUP };
+ return dvb_usb_generic_write(d,b,3);
+ } else
+ return 0;
+}
+EXPORT_SYMBOL(dibusb2_0_power_ctrl);
+
+static int dibusb_i2c_msg(struct dvb_usb_device *d, u8 addr,
+ u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
+{
+ u8 sndbuf[wlen+4]; /* lead(1) devaddr,direction(1) addr(2) data(wlen) (len(2) (when reading)) */
+ /* write only ? */
+ int wo = (rbuf == NULL || rlen == 0),
+ len = 2 + wlen + (wo ? 0 : 2);
+
+ sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ;
+ sndbuf[1] = (addr << 1) | (wo ? 0 : 1);
+
+ memcpy(&sndbuf[2],wbuf,wlen);
+
+ if (!wo) {
+ sndbuf[wlen+2] = (rlen >> 8) & 0xff;
+ sndbuf[wlen+3] = rlen & 0xff;
+ }
+
+ return dvb_usb_generic_rw(d,sndbuf,len,rbuf,rlen,0);
+}
+
+/*
+ * I2C master xfer function
+ */
+static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
+{
+ struct dvb_usb_device *d = i2c_get_adapdata(adap);
+ int i;
+
+ if (down_interruptible(&d->i2c_sem) < 0)
+ return -EAGAIN;
+
+ if (num > 2)
+ warn("more than 2 i2c messages at a time is not handled yet. TODO.");
+
+ for (i = 0; i < num; i++) {
+ /* write/read request */
+ if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
+ if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,
+ msg[i+1].buf,msg[i+1].len) < 0)
+ break;
+ i++;
+ } else
+ if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0)
+ break;
+ }
+
+ up(&d->i2c_sem);
+ return i;
+}
+
+static u32 dibusb_i2c_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C;
+}
+
+struct i2c_algorithm dibusb_i2c_algo = {
+ .name = "DiBcom USB I2C algorithm",
+ .id = I2C_ALGO_BIT,
+ .master_xfer = dibusb_i2c_xfer,
+ .functionality = dibusb_i2c_func,
+};
+EXPORT_SYMBOL(dibusb_i2c_algo);
+
+int dibusb_read_eeprom_byte(struct dvb_usb_device *d, u8 offs, u8 *val)
+{
+ u8 wbuf[1] = { offs };
+ return dibusb_i2c_msg(d, 0x50, wbuf, 1, val, 1);
+}
+EXPORT_SYMBOL(dibusb_read_eeprom_byte);
+
+int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *d)
+{
+ struct dib3000_config demod_cfg;
+ struct dibusb_state *st = d->priv;
+
+ demod_cfg.pll_set = dvb_usb_pll_set_i2c;
+ demod_cfg.pll_init = dvb_usb_pll_init_i2c;
+
+ for (demod_cfg.demod_address = 0x8; demod_cfg.demod_address < 0xd; demod_cfg.demod_address++)
+ if ((d->fe = dib3000mc_attach(&demod_cfg,&d->i2c_adap,&st->ops)) != NULL) {
+ d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
+ return 0;
+ }
+
+ return -ENODEV;
+}
+EXPORT_SYMBOL(dibusb_dib3000mc_frontend_attach);
+
+int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *d)
+{
+ d->pll_addr = 0x60;
+ d->pll_desc = &dvb_pll_env57h1xd5;
+ return 0;
+}
+EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach);
+
+/*
+ * common remote control stuff
+ */
+struct dvb_usb_rc_key dibusb_rc_keys[] = {
+ /* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */
+ { 0x00, 0x16, KEY_POWER },
+ { 0x00, 0x10, KEY_MUTE },
+ { 0x00, 0x03, KEY_1 },
+ { 0x00, 0x01, KEY_2 },
+ { 0x00, 0x06, KEY_3 },
+ { 0x00, 0x09, KEY_4 },
+ { 0x00, 0x1d, KEY_5 },
+ { 0x00, 0x1f, KEY_6 },
+ { 0x00, 0x0d, KEY_7 },
+ { 0x00, 0x19, KEY_8 },
+ { 0x00, 0x1b, KEY_9 },
+ { 0x00, 0x15, KEY_0 },
+ { 0x00, 0x05, KEY_CHANNELUP },
+ { 0x00, 0x02, KEY_CHANNELDOWN },
+ { 0x00, 0x1e, KEY_VOLUMEUP },
+ { 0x00, 0x0a, KEY_VOLUMEDOWN },
+ { 0x00, 0x11, KEY_RECORD },
+ { 0x00, 0x17, KEY_FAVORITES }, /* Heart symbol - Channel list. */
+ { 0x00, 0x14, KEY_PLAY },
+ { 0x00, 0x1a, KEY_STOP },
+ { 0x00, 0x40, KEY_REWIND },
+ { 0x00, 0x12, KEY_FASTFORWARD },
+ { 0x00, 0x0e, KEY_PREVIOUS }, /* Recall - Previous channel. */
+ { 0x00, 0x4c, KEY_PAUSE },
+ { 0x00, 0x4d, KEY_SCREEN }, /* Full screen mode. */
+ { 0x00, 0x54, KEY_AUDIO }, /* MTS - Switch to secondary audio. */
+ /* additional keys TwinHan VisionPlus, the Artec seemingly not have */
+ { 0x00, 0x0c, KEY_CANCEL }, /* Cancel */
+ { 0x00, 0x1c, KEY_EPG }, /* EPG */
+ { 0x00, 0x00, KEY_TAB }, /* Tab */
+ { 0x00, 0x48, KEY_INFO }, /* Preview */
+ { 0x00, 0x04, KEY_LIST }, /* RecordList */
+ { 0x00, 0x0f, KEY_TEXT }, /* Teletext */
+ /* Key codes for the KWorld/ADSTech/JetWay remote. */
+ { 0x86, 0x12, KEY_POWER },
+ { 0x86, 0x0f, KEY_SELECT }, /* source */
+ { 0x86, 0x0c, KEY_UNKNOWN }, /* scan */
+ { 0x86, 0x0b, KEY_EPG },
+ { 0x86, 0x10, KEY_MUTE },
+ { 0x86, 0x01, KEY_1 },
+ { 0x86, 0x02, KEY_2 },
+ { 0x86, 0x03, KEY_3 },
+ { 0x86, 0x04, KEY_4 },
+ { 0x86, 0x05, KEY_5 },
+ { 0x86, 0x06, KEY_6 },
+ { 0x86, 0x07, KEY_7 },
+ { 0x86, 0x08, KEY_8 },
+ { 0x86, 0x09, KEY_9 },
+ { 0x86, 0x0a, KEY_0 },
+ { 0x86, 0x18, KEY_ZOOM },
+ { 0x86, 0x1c, KEY_UNKNOWN }, /* preview */
+ { 0x86, 0x13, KEY_UNKNOWN }, /* snap */
+ { 0x86, 0x00, KEY_UNDO },
+ { 0x86, 0x1d, KEY_RECORD },
+ { 0x86, 0x0d, KEY_STOP },
+ { 0x86, 0x0e, KEY_PAUSE },
+ { 0x86, 0x16, KEY_PLAY },
+ { 0x86, 0x11, KEY_BACK },
+ { 0x86, 0x19, KEY_FORWARD },
+ { 0x86, 0x14, KEY_UNKNOWN }, /* pip */
+ { 0x86, 0x15, KEY_ESC },
+ { 0x86, 0x1a, KEY_UP },
+ { 0x86, 0x1e, KEY_DOWN },
+ { 0x86, 0x1f, KEY_LEFT },
+ { 0x86, 0x1b, KEY_RIGHT },
+};
+EXPORT_SYMBOL(dibusb_rc_keys);
+
+int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+ u8 key[5],cmd = DIBUSB_REQ_POLL_REMOTE;
+ dvb_usb_generic_rw(d,&cmd,1,key,5,0);
+ dvb_usb_nec_rc_key_to_event(d,key,event,state);
+ if (key[0] != 0)
+ deb_info("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
+ return 0;
+}
+EXPORT_SYMBOL(dibusb_rc_query);
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c
new file mode 100644
index 00000000000..a0ffbb59fa1
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c
@@ -0,0 +1,316 @@
+/* DVB USB compliant linux driver for mobile DVB-T USB devices based on
+ * reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-B)
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * based on GPL code from DiBcom, which has
+ * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr)
+ *
+ * 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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "dibusb.h"
+
+static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_device *d)
+{
+ struct dib3000_config demod_cfg;
+ struct dibusb_state *st = d->priv;
+
+ demod_cfg.demod_address = 0x8;
+ demod_cfg.pll_set = dvb_usb_pll_set_i2c;
+ demod_cfg.pll_init = dvb_usb_pll_init_i2c;
+
+ if ((d->fe = dib3000mb_attach(&demod_cfg,&d->i2c_adap,&st->ops)) == NULL)
+ return -ENODEV;
+
+ d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
+
+ return 0;
+}
+
+/* some of the dibusb 1.1 device aren't equipped with the default tuner
+ * (Thomson Cable), but with a Panasonic ENV77H11D5. This function figures
+ * this out. */
+static int dibusb_dib3000mb_tuner_attach (struct dvb_usb_device *d)
+{
+ u8 b[2] = { 0,0 }, b2[1];
+ int ret = 0;
+ struct i2c_msg msg[2] = {
+ { .flags = 0, .buf = b, .len = 2 },
+ { .flags = I2C_M_RD, .buf = b2, .len = 1 },
+ };
+
+ /* the Panasonic sits on I2C addrass 0x60, the Thomson on 0x61 */
+ msg[0].addr = msg[1].addr = 0x60;
+
+ if (d->tuner_pass_ctrl)
+ d->tuner_pass_ctrl(d->fe,1,msg[0].addr);
+
+ if (i2c_transfer (&d->i2c_adap, msg, 2) != 2) {
+ err("tuner i2c write failed.");
+ ret = -EREMOTEIO;
+ }
+
+ if (d->tuner_pass_ctrl)
+ d->tuner_pass_ctrl(d->fe,0,msg[0].addr);
+
+ if (b2[0] == 0xfe) {
+ info("this device has the Thomson Cable onboard. Which is default.");
+ d->pll_addr = 0x61;
+ d->pll_desc = &dvb_pll_tua6010xs;
+ } else {
+ u8 bpll[4] = { 0x0b, 0xf5, 0x85, 0xab };
+ info("this device has the Panasonic ENV77H11D5 onboard.");
+ d->pll_addr = 0x60;
+ memcpy(d->pll_init,bpll,4);
+ d->pll_desc = &dvb_pll_tda665x;
+ }
+
+ return ret;
+}
+
+/* USB Driver stuff */
+static struct dvb_usb_properties dibusb1_1_properties;
+static struct dvb_usb_properties dibusb1_1_an2235_properties;
+static struct dvb_usb_properties dibusb2_0b_properties;
+
+static int dibusb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ if (dvb_usb_device_init(intf,&dibusb1_1_properties,THIS_MODULE) == 0 ||
+ dvb_usb_device_init(intf,&dibusb1_1_an2235_properties,THIS_MODULE) == 0 ||
+ dvb_usb_device_init(intf,&dibusb2_0b_properties,THIS_MODULE) == 0)
+ return 0;
+
+ return -EINVAL;
+}
+
+/* do not change the order of the ID table */
+static struct usb_device_id dibusb_dib3000mb_table [] = {
+/* 00 */ { USB_DEVICE(USB_VID_AVERMEDIA_UNK, USB_PID_AVERMEDIA_DVBT_USB_COLD)},
+/* 01 */ { USB_DEVICE(USB_VID_AVERMEDIA_UNK, USB_PID_AVERMEDIA_DVBT_USB_WARM)},
+/* 02 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_COLD) },
+/* 03 */ { USB_DEVICE(USB_VID_COMPRO, USB_PID_COMPRO_DVBU2000_WARM) },
+/* 04 */ { USB_DEVICE(USB_VID_COMPRO_UNK, USB_PID_COMPRO_DVBU2000_UNK_COLD) },
+/* 05 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_COLD) },
+/* 06 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3000_WARM) },
+/* 07 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_COLD) },
+/* 08 */ { USB_DEVICE(USB_VID_EMPIA, USB_PID_KWORLD_VSTREAM_WARM) },
+/* 09 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_COLD) },
+/* 10 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_GRANDTEC_DVBT_USB_WARM) },
+/* 11 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_COLD) },
+/* 12 */ { USB_DEVICE(USB_VID_GRANDTEC, USB_PID_DIBCOM_MOD3000_WARM) },
+/* 13 */ { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_COLD) },
+/* 14 */ { USB_DEVICE(USB_VID_HYPER_PALTEK, USB_PID_UNK_HYPER_PALTEK_WARM) },
+/* 15 */ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7041_COLD) },
+/* 16 */ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7041_WARM) },
+/* 17 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_COLD) },
+/* 18 */ { USB_DEVICE(USB_VID_TWINHAN, USB_PID_TWINHAN_VP7041_WARM) },
+/* 19 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) },
+/* 20 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) },
+/* 21 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) },
+/* 22 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) },
+/* 23 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_COLD) },
+/* 24 */ { USB_DEVICE(USB_VID_ADSTECH, USB_PID_ADSTECH_USB2_WARM) },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, dibusb_dib3000mb_table);
+
+static struct dvb_usb_properties dibusb1_1_properties = {
+ .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
+ .pid_filter_count = 16,
+
+ .usb_ctrl = CYPRESS_AN2135,
+
+ .firmware = "dvb-usb-dibusb-5.0.0.11.fw",
+
+ .size_of_priv = sizeof(struct dibusb_state),
+
+ .streaming_ctrl = dibusb_streaming_ctrl,
+ .pid_filter = dibusb_pid_filter,
+ .pid_filter_ctrl = dibusb_pid_filter_ctrl,
+ .power_ctrl = dibusb_power_ctrl,
+ .frontend_attach = dibusb_dib3000mb_frontend_attach,
+ .tuner_attach = dibusb_dib3000mb_tuner_attach,
+
+ .rc_interval = DEFAULT_RC_INTERVAL,
+ .rc_key_map = dibusb_rc_keys,
+ .rc_key_map_size = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
+ .rc_query = dibusb_rc_query,
+
+ .i2c_algo = &dibusb_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+ /* parameter for the MPEG2-data transfer */
+ .urb = {
+ .type = DVB_USB_BULK,
+ .count = 7,
+ .endpoint = 0x02,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
+
+ .num_device_descs = 8,
+ .devices = {
+ { "AVerMedia AverTV DVBT USB1.1",
+ { &dibusb_dib3000mb_table[0], NULL },
+ { &dibusb_dib3000mb_table[1], NULL },
+ },
+ { "Compro Videomate DVB-U2000 - DVB-T USB1.1 (please confirm to linux-dvb)",
+ { &dibusb_dib3000mb_table[2], &dibusb_dib3000mb_table[4], NULL},
+ { &dibusb_dib3000mb_table[3], NULL },
+ },
+ { "DiBcom USB1.1 DVB-T reference design (MOD3000)",
+ { &dibusb_dib3000mb_table[5], NULL },
+ { &dibusb_dib3000mb_table[6], NULL },
+ },
+ { "KWorld V-Stream XPERT DTV - DVB-T USB1.1",
+ { &dibusb_dib3000mb_table[7], NULL },
+ { &dibusb_dib3000mb_table[8], NULL },
+ },
+ { "Grandtec USB1.1 DVB-T",
+ { &dibusb_dib3000mb_table[9], &dibusb_dib3000mb_table[11], NULL },
+ { &dibusb_dib3000mb_table[10], &dibusb_dib3000mb_table[12], NULL },
+ },
+ { "Unkown USB1.1 DVB-T device ???? please report the name to the author",
+ { &dibusb_dib3000mb_table[13], NULL },
+ { &dibusb_dib3000mb_table[14], NULL },
+ },
+ { "TwinhanDTV USB-Ter USB1.1 / Magic Box I / HAMA USB1.1 DVB-T device",
+ { &dibusb_dib3000mb_table[15], &dibusb_dib3000mb_table[17], NULL},
+ { &dibusb_dib3000mb_table[16], &dibusb_dib3000mb_table[18], NULL},
+ },
+ { "Artec T1 USB1.1 TVBOX with AN2135",
+ { &dibusb_dib3000mb_table[19], NULL },
+ { &dibusb_dib3000mb_table[20], NULL },
+ },
+ }
+};
+
+static struct dvb_usb_properties dibusb1_1_an2235_properties = {
+ .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
+ .usb_ctrl = CYPRESS_AN2235,
+
+ .firmware = "dvb-usb-dibusb-an2235-01.fw",
+
+ .size_of_priv = sizeof(struct dibusb_state),
+
+ .streaming_ctrl = dibusb_streaming_ctrl,
+ .pid_filter = dibusb_pid_filter,
+ .pid_filter_ctrl = dibusb_pid_filter_ctrl,
+ .power_ctrl = dibusb_power_ctrl,
+ .frontend_attach = dibusb_dib3000mb_frontend_attach,
+ .tuner_attach = dibusb_dib3000mb_tuner_attach,
+
+ .rc_interval = DEFAULT_RC_INTERVAL,
+ .rc_key_map = dibusb_rc_keys,
+ .rc_key_map_size = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
+ .rc_query = dibusb_rc_query,
+
+ .i2c_algo = &dibusb_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+ /* parameter for the MPEG2-data transfer */
+ .urb = {
+ .type = DVB_USB_BULK,
+ .count = 7,
+ .endpoint = 0x02,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
+
+ .num_device_descs = 1,
+ .devices = {
+ { "Artec T1 USB1.1 TVBOX with AN2235",
+ { &dibusb_dib3000mb_table[20], NULL },
+ { &dibusb_dib3000mb_table[21], NULL },
+ },
+ }
+};
+
+static struct dvb_usb_properties dibusb2_0b_properties = {
+ .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
+ .usb_ctrl = CYPRESS_FX2,
+
+ .firmware = "dvb-usb-adstech-usb2-01.fw",
+
+ .size_of_priv = sizeof(struct dibusb_state),
+
+ .streaming_ctrl = dibusb2_0_streaming_ctrl,
+ .pid_filter = dibusb_pid_filter,
+ .pid_filter_ctrl = dibusb_pid_filter_ctrl,
+ .power_ctrl = dibusb2_0_power_ctrl,
+ .frontend_attach = dibusb_dib3000mb_frontend_attach,
+ .tuner_attach = dibusb_dib3000mb_tuner_attach,
+
+ .rc_interval = DEFAULT_RC_INTERVAL,
+ .rc_key_map = dibusb_rc_keys,
+ .rc_key_map_size = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
+ .rc_query = dibusb_rc_query,
+
+ .i2c_algo = &dibusb_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+ /* parameter for the MPEG2-data transfer */
+ .urb = {
+ .type = DVB_USB_BULK,
+ .count = 7,
+ .endpoint = 0x06,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
+
+ .num_device_descs = 2,
+ .devices = {
+ { "KWorld/ADSTech Instant DVB-T USB 2.0",
+ { &dibusb_dib3000mb_table[23], NULL },
+ { &dibusb_dib3000mb_table[24], NULL }, /* device ID with default DIBUSB2_0-firmware */
+ },
+ }
+};
+
+static struct usb_driver dibusb_driver = {
+ .owner = THIS_MODULE,
+ .name = "DiBcom based USB DVB-T devices (DiB3000M-B based)",
+ .probe = dibusb_probe,
+ .disconnect = dvb_usb_device_exit,
+ .id_table = dibusb_dib3000mb_table,
+};
+
+/* module stuff */
+static int __init dibusb_module_init(void)
+{
+ int result;
+ if ((result = usb_register(&dibusb_driver))) {
+ err("usb_register failed. Error number %d",result);
+ return result;
+ }
+
+ return 0;
+}
+
+static void __exit dibusb_module_exit(void)
+{
+ /* deregister this driver from the USB subsystem */
+ usb_deregister(&dibusb_driver);
+}
+
+module_init (dibusb_module_init);
+module_exit (dibusb_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("Driver for DiBcom USB DVB-T devices (DiB3000M-B based)");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c
new file mode 100644
index 00000000000..aad8ed3fe00
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dibusb-mc.c
@@ -0,0 +1,116 @@
+/* DVB USB compliant linux driver for mobile DVB-T USB devices based on
+ * reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-C/P)
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * based on GPL code from DiBcom, which has
+ * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr)
+ *
+ * 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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "dibusb.h"
+
+/* USB Driver stuff */
+static struct dvb_usb_properties dibusb_mc_properties;
+
+static int dibusb_mc_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return dvb_usb_device_init(intf,&dibusb_mc_properties,THIS_MODULE);
+}
+
+/* do not change the order of the ID table */
+static struct usb_device_id dibusb_dib3000mc_table [] = {
+/* 00 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3001_COLD) },
+/* 01 */ { USB_DEVICE(USB_VID_DIBCOM, USB_PID_DIBCOM_MOD3001_WARM) },
+/* 02 */ { USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_USB2_COLD) },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, dibusb_dib3000mc_table);
+
+static struct dvb_usb_properties dibusb_mc_properties = {
+ .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
+ .pid_filter_count = 32,
+
+ .usb_ctrl = CYPRESS_FX2,
+ .firmware = "dvb-usb-dibusb-6.0.0.8.fw",
+
+ .size_of_priv = sizeof(struct dibusb_state),
+
+ .streaming_ctrl = dibusb2_0_streaming_ctrl,
+ .pid_filter = dibusb_pid_filter,
+ .pid_filter_ctrl = dibusb_pid_filter_ctrl,
+ .power_ctrl = dibusb2_0_power_ctrl,
+ .frontend_attach = dibusb_dib3000mc_frontend_attach,
+ .tuner_attach = dibusb_dib3000mc_tuner_attach,
+
+ .rc_interval = DEFAULT_RC_INTERVAL,
+ .rc_key_map = dibusb_rc_keys,
+ .rc_key_map_size = 63, /* FIXME */
+ .rc_query = dibusb_rc_query,
+
+ .i2c_algo = &dibusb_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+ /* parameter for the MPEG2-data transfer */
+ .urb = {
+ .type = DVB_USB_BULK,
+ .count = 7,
+ .endpoint = 0x06,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
+
+ .num_device_descs = 2,
+ .devices = {
+ { "DiBcom USB2.0 DVB-T reference design (MOD3000P)",
+ { &dibusb_dib3000mc_table[0], NULL },
+ { &dibusb_dib3000mc_table[1], NULL },
+ },
+ { "Artec T1 USB2.0 TVBOX (please report the warm ID)",
+ { &dibusb_dib3000mc_table[2], NULL },
+ { NULL },
+ },
+ }
+};
+
+static struct usb_driver dibusb_mc_driver = {
+ .owner = THIS_MODULE,
+ .name = "DiBcom based USB2.0 DVB-T (DiB3000M-C/P based) devices",
+ .probe = dibusb_mc_probe,
+ .disconnect = dvb_usb_device_exit,
+ .id_table = dibusb_dib3000mc_table,
+};
+
+/* module stuff */
+static int __init dibusb_mc_module_init(void)
+{
+ int result;
+ if ((result = usb_register(&dibusb_mc_driver))) {
+ err("usb_register failed. Error number %d",result);
+ return result;
+ }
+
+ return 0;
+}
+
+static void __exit dibusb_mc_module_exit(void)
+{
+ /* deregister this driver from the USB subsystem */
+ usb_deregister(&dibusb_mc_driver);
+}
+
+module_init (dibusb_mc_module_init);
+module_exit (dibusb_mc_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("Driver for DiBcom USB2.0 DVB-T (DiB3000M-C/P based) devices");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dibusb.h b/drivers/media/dvb/dvb-usb/dibusb.h
new file mode 100644
index 00000000000..6611f62977c
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dibusb.h
@@ -0,0 +1,122 @@
+/* Header file for all dibusb-based-receivers.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * 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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#ifndef _DVB_USB_DIBUSB_H_
+#define _DVB_USB_DIBUSB_H_
+
+#define DVB_USB_LOG_PREFIX "dibusb"
+#include "dvb-usb.h"
+
+#include "dib3000.h"
+
+/*
+ * protocol of all dibusb related devices
+ */
+
+/*
+ * bulk msg to/from endpoint 0x01
+ *
+ * general structure:
+ * request_byte parameter_bytes
+ */
+
+#define DIBUSB_REQ_START_READ 0x00
+#define DIBUSB_REQ_START_DEMOD 0x01
+
+/*
+ * i2c read
+ * bulk write: 0x02 ((7bit i2c_addr << 1) & 0x01) register_bytes length_word
+ * bulk read: byte_buffer (length_word bytes)
+ */
+#define DIBUSB_REQ_I2C_READ 0x02
+
+/*
+ * i2c write
+ * bulk write: 0x03 (7bit i2c_addr << 1) register_bytes value_bytes
+ */
+#define DIBUSB_REQ_I2C_WRITE 0x03
+
+/*
+ * polling the value of the remote control
+ * bulk write: 0x04
+ * bulk read: byte_buffer (5 bytes)
+ */
+#define DIBUSB_REQ_POLL_REMOTE 0x04
+
+/* additional status values for Hauppauge Remote Control Protocol */
+#define DIBUSB_RC_HAUPPAUGE_KEY_PRESSED 0x01
+#define DIBUSB_RC_HAUPPAUGE_KEY_EMPTY 0x03
+
+/* streaming mode:
+ * bulk write: 0x05 mode_byte
+ *
+ * mode_byte is mostly 0x00
+ */
+#define DIBUSB_REQ_SET_STREAMING_MODE 0x05
+
+/* interrupt the internal read loop, when blocking */
+#define DIBUSB_REQ_INTR_READ 0x06
+
+/* io control
+ * 0x07 cmd_byte param_bytes
+ *
+ * param_bytes can be up to 32 bytes
+ *
+ * cmd_byte function parameter name
+ * 0x00 power mode
+ * 0x00 sleep
+ * 0x01 wakeup
+ *
+ * 0x01 enable streaming
+ * 0x02 disable streaming
+ *
+ *
+ */
+#define DIBUSB_REQ_SET_IOCTL 0x07
+
+/* IOCTL commands */
+
+/* change the power mode in firmware */
+#define DIBUSB_IOCTL_CMD_POWER_MODE 0x00
+#define DIBUSB_IOCTL_POWER_SLEEP 0x00
+#define DIBUSB_IOCTL_POWER_WAKEUP 0x01
+
+/* modify streaming of the FX2 */
+#define DIBUSB_IOCTL_CMD_ENABLE_STREAM 0x01
+#define DIBUSB_IOCTL_CMD_DISABLE_STREAM 0x02
+
+struct dibusb_state {
+ struct dib_fe_xfer_ops ops;
+
+ /* for RC5 remote control */
+ int old_toggle;
+ int last_repeat_count;
+};
+
+extern struct i2c_algorithm dibusb_i2c_algo;
+
+extern int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *);
+extern int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *);
+
+extern int dibusb_streaming_ctrl(struct dvb_usb_device *, int);
+extern int dibusb_pid_filter(struct dvb_usb_device *, int, u16, int);
+extern int dibusb_pid_filter_ctrl(struct dvb_usb_device *, int);
+extern int dibusb_power_ctrl(struct dvb_usb_device *, int);
+extern int dibusb2_0_streaming_ctrl(struct dvb_usb_device *, int);
+extern int dibusb2_0_power_ctrl(struct dvb_usb_device *, int);
+
+#define DEFAULT_RC_INTERVAL 150
+//#define DEFAULT_RC_INTERVAL 100000
+
+extern struct dvb_usb_rc_key dibusb_rc_keys[];
+extern int dibusb_rc_query(struct dvb_usb_device *, u32 *, int *);
+extern int dibusb_read_eeprom_byte(struct dvb_usb_device *, u8, u8 *);
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
new file mode 100644
index 00000000000..5acf3fde952
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/digitv.c
@@ -0,0 +1,282 @@
+/* DVB USB compliant linux driver for Nebula Electronics uDigiTV DVB-T USB2.0
+ * receiver
+ *
+ * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) and
+ * Allan Third (allan.third@cs.man.ac.uk)
+ *
+ * partly based on the SDK published by Nebula Electronics (TODO do we want this line ?)
+ *
+ * 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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "digitv.h"
+
+#include "mt352.h"
+#include "nxt6000.h"
+
+/* debug */
+int dvb_usb_digitv_debug;
+module_param_named(debug,dvb_usb_digitv_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
+
+static int digitv_ctrl_msg(struct dvb_usb_device *d,
+ u8 cmd, u8 vv, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
+{
+ int wo = (rbuf == NULL || rlen == 0); /* write-only */
+ u8 sndbuf[7],rcvbuf[7];
+ memset(sndbuf,0,7); memset(rcvbuf,0,7);
+
+ sndbuf[0] = cmd;
+ sndbuf[1] = vv;
+ sndbuf[2] = wo ? wlen : rlen;
+
+ if (!wo) {
+ memcpy(&sndbuf[3],wbuf,wlen);
+ dvb_usb_generic_write(d,sndbuf,7);
+ } else {
+ dvb_usb_generic_rw(d,sndbuf,7,rcvbuf,7,10);
+ memcpy(&rbuf,&rcvbuf[3],rlen);
+ }
+ return 0;
+}
+
+/* I2C */
+static int digitv_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
+{
+ struct dvb_usb_device *d = i2c_get_adapdata(adap);
+ int i;
+
+ if (down_interruptible(&d->i2c_sem) < 0)
+ return -EAGAIN;
+
+ if (num > 2)
+ warn("more than 2 i2c messages at a time is not handled yet. TODO.");
+
+ for (i = 0; i < num; i++) {
+ /* write/read request */
+ if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
+ if (digitv_ctrl_msg(d, USB_READ_COFDM, msg[i].buf[0], NULL, 0,
+ msg[i+1].buf,msg[i+1].len) < 0)
+ break;
+ i++;
+ } else
+ if (digitv_ctrl_msg(d,USB_WRITE_COFDM, msg[i].buf[0],
+ &msg[i].buf[1],msg[i].len-1,NULL,0) < 0)
+ break;
+ }
+
+ up(&d->i2c_sem);
+ return i;
+}
+
+static u32 digitv_i2c_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm digitv_i2c_algo = {
+ .name = "Nebula DigiTV USB I2C algorithm",
+ .id = I2C_ALGO_BIT,
+ .master_xfer = digitv_i2c_xfer,
+ .functionality = digitv_i2c_func,
+};
+
+/* Callbacks for DVB USB */
+static int digitv_identify_state (struct usb_device *udev, struct
+ dvb_usb_properties *props, struct dvb_usb_device_description **desc,
+ int *cold)
+{
+ *cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0;
+ return 0;
+}
+
+static int digitv_mt352_demod_init(struct dvb_frontend *fe)
+{
+ static u8 mt352_clock_config[] = { 0x89, 0x38, 0x2d };
+ static u8 mt352_reset[] = { 0x50, 0x80 };
+ static u8 mt352_mclk_ratio[] = { 0x8b, 0x00 };
+
+ static u8 mt352_agc_cfg[] = { 0x68, 0xa0 };
+ static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0xa0 };
+ static u8 mt352_acq_ctl[] = { 0x53, 0x50 };
+ static u8 mt352_agc_target[] = { 0x67, 0x20 };
+
+ static u8 mt352_rs_err_per[] = { 0x7c, 0x00, 0x01 };
+ static u8 mt352_snr_select[] = { 0x79, 0x00, 0x20 };
+
+ static u8 mt352_input_freq_1[] = { 0x56, 0x31, 0x05 };
+
+ static u8 mt352_scan_ctl[] = { 0x88, 0x0f };
+ static u8 mt352_capt_range[] = { 0x75, 0x32 };
+
+ mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
+ mt352_write(fe, mt352_reset, sizeof(mt352_reset));
+ msleep(1);
+ mt352_write(fe, mt352_mclk_ratio, sizeof(mt352_mclk_ratio));
+
+ mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
+ mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
+ mt352_write(fe, mt352_acq_ctl, sizeof(mt352_acq_ctl));
+ mt352_write(fe, mt352_agc_target, sizeof(mt352_agc_target));
+
+
+ mt352_write(fe, mt352_rs_err_per, sizeof(mt352_rs_err_per));
+ mt352_write(fe, mt352_snr_select, sizeof(mt352_snr_select));
+
+ mt352_write(fe, mt352_input_freq_1, sizeof(mt352_input_freq_1));
+
+ mt352_write(fe, mt352_scan_ctl, sizeof(mt352_scan_ctl));
+ mt352_write(fe, mt352_capt_range, sizeof(mt352_capt_range));
+
+ return 0;
+}
+
+static struct mt352_config digitv_mt352_config = {
+ .demod_address = 0x0, /* ignored by the digitv anyway */
+ .demod_init = digitv_mt352_demod_init,
+ .pll_set = NULL, /* TODO */
+};
+
+static struct nxt6000_config digitv_nxt6000_config = {
+ .demod_address = 0x0, /* ignored by the digitv anyway */
+ .clock_inversion = 0x0,
+
+ .pll_init = NULL,
+ .pll_set = NULL,
+};
+
+static int digitv_frontend_attach(struct dvb_usb_device *d)
+{
+ if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) == NULL)
+ return 0;
+ if ((d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) == NULL) {
+
+ warn("nxt6000 support is not done yet, in fact you are one of the first "
+ "person who wants to use this device in Linux. Please report to "
+ "linux-dvb@linuxtv.org");
+
+ return 0;
+ }
+ return -EIO;
+}
+
+static struct dvb_usb_rc_key digitv_rc_keys[] = {
+ { 0x00, 0x16, KEY_POWER }, /* dummy key */
+};
+
+/* TODO is it really the NEC protocol ? */
+int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+ u8 key[5];
+
+ digitv_ctrl_msg(d,USB_READ_REMOTE,0,NULL,0,&key[1],4);
+ /* TODO state, maybe it is VV ? */
+ if (key[1] != 0)
+ key[0] = 0x01; /* if something is inside the buffer, simulate key press */
+
+ /* call the universal NEC remote processor, to find out the key's state and event */
+ dvb_usb_nec_rc_key_to_event(d,key,event,state);
+ if (key[0] != 0)
+ deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
+ return 0;
+}
+
+
+/* DVB USB Driver stuff */
+static struct dvb_usb_properties digitv_properties;
+
+static int digitv_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE);
+}
+
+static struct usb_device_id digitv_table [] = {
+ { USB_DEVICE(USB_VID_ANCHOR, USB_PID_NEBULA_DIGITV) },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, digitv_table);
+
+static struct dvb_usb_properties digitv_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = CYPRESS_FX2,
+ .firmware = "dvb-usb-digitv-01.fw",
+
+ .size_of_priv = 0,
+
+ .streaming_ctrl = NULL,
+ .pid_filter = NULL,
+ .pid_filter_ctrl = NULL,
+ .power_ctrl = NULL,
+ .frontend_attach = digitv_frontend_attach,
+ .tuner_attach = NULL, // digitv_tuner_attach,
+ .read_mac_address = NULL,
+
+ .rc_interval = 1000,
+ .rc_key_map = digitv_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(digitv_rc_keys),
+ .rc_query = digitv_rc_query,
+
+ .identify_state = digitv_identify_state,
+
+ .i2c_algo = &digitv_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+ /* parameter for the MPEG2-data transfer */
+ .urb = {
+ .type = DVB_USB_BULK,
+ .count = 7,
+ .endpoint = 0x02,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
+
+ .num_device_descs = 2,
+ .devices = {
+ { "Nebula Electronics uDigiTV DVB-T USB2.0)",
+ { &digitv_table[0], NULL },
+ { NULL },
+ },
+ }
+};
+
+static struct usb_driver digitv_driver = {
+ .owner = THIS_MODULE,
+ .name = "Nebula Electronics uDigiTV DVB-T USB2.0 device",
+ .probe = digitv_probe,
+ .disconnect = dvb_usb_device_exit,
+ .id_table = digitv_table,
+};
+
+/* module stuff */
+static int __init digitv_module_init(void)
+{
+ int result;
+ if ((result = usb_register(&digitv_driver))) {
+ err("usb_register failed. Error number %d",result);
+ return result;
+ }
+
+ return 0;
+}
+
+static void __exit digitv_module_exit(void)
+{
+ /* deregister this driver from the USB subsystem */
+ usb_deregister(&digitv_driver);
+}
+
+module_init (digitv_module_init);
+module_exit (digitv_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("Driver for Nebula Electronics uDigiTV DVB-T USB2.0");
+MODULE_VERSION("1.0-alpha");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/digitv.h b/drivers/media/dvb/dvb-usb/digitv.h
new file mode 100644
index 00000000000..477ee428a70
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/digitv.h
@@ -0,0 +1,65 @@
+#ifndef _DVB_USB_DIGITV_H_
+#define _DVB_USB_DIGITV_H_
+
+#define DVB_USB_LOG_PREFIX "digitv"
+#include "dvb-usb.h"
+
+extern int dvb_usb_digitv_debug;
+#define deb_rc(args...) dprintk(dvb_usb_digitv_debug,0x01,args)
+
+/* protocol (from usblogging and the SDK:
+ *
+ * Always 7 bytes bulk message(s) for controlling
+ *
+ * First byte describes the command. Reads are 2 consecutive transfer (as always).
+ *
+ * General structure:
+ *
+ * write or first message of a read:
+ * <cmdbyte> VV <len> B0 B1 B2 B3
+ *
+ * second message of a read
+ * <cmdbyte> VV <len> R0 R1 R2 R3
+ *
+ * whereas 0 < len <= 4
+ *
+ * I2C address is stored somewhere inside the device.
+ *
+ * 0x01 read from EEPROM
+ * VV = offset; B* = 0; R* = value(s)
+ *
+ * 0x02 read register of the COFDM
+ * VV = register; B* = 0; R* = value(s)
+ *
+ * 0x05 write register of the COFDM
+ * VV = register; B* = value(s);
+ *
+ * 0x06 write to the tuner (only for NXT6000)
+ * VV = 0; B* = PLL data; len = 4;
+ *
+ * 0x03 read remote control
+ * VV = 0; B* = 0; len = 4; R* = key
+ *
+ * 0x07 write to the remote (don't know why one should this, resetting ?)
+ * VV = 0; B* = key; len = 4;
+ *
+ * 0x08 write remote type
+ * VV = 0; B[0] = 0x01, len = 4
+ *
+ * 0x09 write device init
+ * TODO
+ */
+#define USB_READ_EEPROM 1
+
+#define USB_READ_COFDM 2
+#define USB_WRITE_COFDM 5
+
+#define USB_WRITE_TUNER 6
+
+#define USB_READ_REMOTE 3
+#define USB_WRITE_REMOTE 7
+#define USB_WRITE_REMOTE_TYPE 8
+
+#define USB_DEV_INIT 9
+
+#endif
diff --git a/drivers/media/dvb/dibusb/dvb-fe-dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u-fe.c
index 1872aa6d200..d17d768038c 100644
--- a/drivers/media/dvb/dibusb/dvb-fe-dtt200u.c
+++ b/drivers/media/dvb/dvb-usb/dtt200u-fe.c
@@ -1,42 +1,18 @@
-/*
- * dvb-dtt200u-fe.c is a driver which implements the frontend-part of the
- * Yakumo/Typhoon/Hama USB2.0 boxes. It is hard-wired to the dibusb-driver as
- * it uses the usb-transfer functions directly (maybe creating a
- * generic-dvb-usb-lib for all usb-drivers will be reduce some more code.)
+/* Frontend part of the Linux driver for the Yakumo/Hama/Typhoon DVB-T
+ * USB2.0 receiver.
*
* Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de>
*
- * see dvb-dibusb-core.c for copyright details.
- */
-
-/* guessed protocol description (reverse engineered):
- * read
- * 00 - USB type 0x02 for usb2.0, 0x01 for usb1.1
- * 81 - <TS_LOCK> <current frequency divided by 250000>
- * 82 - crash - do not touch
- * 83 - crash - do not touch
- * 84 - remote control
- * 85 - crash - do not touch (OK, stop testing here)
- * 88 - locking 2 bytes (0x80 0x40 == no signal, 0x89 0x20 == nice signal)
- * 89 - noise-to-signal
- * 8a - unkown 1 byte - signal_strength
- * 8c - ber ???
- * 8d - ber
- * 8e - unc
+ * 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, version 2.
*
- * write
- * 02 - bandwidth
- * 03 - frequency (divided by 250000)
- * 04 - pid table (index pid(7:0) pid(12:8))
- * 05 - reset the pid table
- * 08 - demod transfer enabled or not (FX2 transfer is enabled by default)
+ * see Documentation/dvb/README.dvb-usb for more information
*/
-
-#include "dvb-dibusb.h"
-#include "dvb_frontend.h"
+#include "dtt200u.h"
struct dtt200u_fe_state {
- struct usb_dibusb *dib;
+ struct dvb_usb_device *d;
struct dvb_frontend_parameters fep;
struct dvb_frontend frontend;
@@ -47,11 +23,11 @@ struct dtt200u_fe_state {
static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat)
{
struct dtt200u_fe_state *state = fe->demodulator_priv;
- u8 bw[1] = { 0x81 };
+ u8 bw = GET_TUNE_STAT;
u8 br[3] = { 0 };
// u8 bdeb[5] = { 0 };
- dibusb_readwrite_usb(state->dib,bw,1,br,3);
+ dvb_usb_generic_rw(state->d,&bw,1,br,3,0);
switch (br[0]) {
case 0x01:
*stat = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
@@ -60,12 +36,12 @@ static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat)
*stat = 0;
break;
default:
- moan("br[0]",0x81);
+ moan("br[0]",GET_TUNE_STAT);
break;
}
// bw[0] = 0x88;
-// dibusb_readwrite_usb(state->dib,bw,1,bdeb,5);
+// dvb_usb_generic_rw(state->d,bw,1,bdeb,5,0);
// deb_info("%02x: %02x %02x %02x %02x %02x\n",bw[0],bdeb[0],bdeb[1],bdeb[2],bdeb[3],bdeb[4]);
@@ -74,27 +50,26 @@ static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat)
static int dtt200u_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
{
struct dtt200u_fe_state *state = fe->demodulator_priv;
- u8 bw[1] = { 0x8d };
+ u8 bw = GET_BER;
*ber = 0;
- dibusb_readwrite_usb(state->dib,bw,1,(u8*) ber, 3);
+ dvb_usb_generic_rw(state->d,&bw,1,(u8*) ber,3,0);
return 0;
}
static int dtt200u_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
{
struct dtt200u_fe_state *state = fe->demodulator_priv;
- u8 bw[1] = { 0x8c };
+ u8 bw = GET_UNK;
*unc = 0;
- dibusb_readwrite_usb(state->dib,bw,1,(u8*) unc, 3);
+ dvb_usb_generic_rw(state->d,&bw,1,(u8*) unc,3,0);
return 0;
}
static int dtt200u_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
{
struct dtt200u_fe_state *state = fe->demodulator_priv;
- u8 bw[1] = { 0x8a };
- u8 b;
- dibusb_readwrite_usb(state->dib,bw,1,&b, 1);
+ u8 bw = GET_SIG_STRENGTH, b;
+ dvb_usb_generic_rw(state->d,&bw,1,&b,1,0);
*strength = (b << 8) | b;
return 0;
}
@@ -102,18 +77,17 @@ static int dtt200u_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strengt
static int dtt200u_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
{
struct dtt200u_fe_state *state = fe->demodulator_priv;
- u8 bw[1] = { 0x89 };
- u8 br[1] = { 0 };
- dibusb_readwrite_usb(state->dib,bw,1,br,1);
- *snr = ((0xff - br[0]) << 8) | (0xff - br[0]);
+ u8 bw = GET_SNR,br;
+ dvb_usb_generic_rw(state->d,&bw,1,&br,1,0);
+ *snr = ~((br << 8) | br);
return 0;
}
static int dtt200u_fe_init(struct dvb_frontend* fe)
{
struct dtt200u_fe_state *state = fe->demodulator_priv;
- u8 b[] = { 0x01 };
- return dibusb_write_usb(state->dib,b,1);
+ u8 b = RESET_DEMOD;
+ return dvb_usb_generic_write(state->d,&b,1);
}
static int dtt200u_fe_sleep(struct dvb_frontend* fe)
@@ -134,7 +108,7 @@ static int dtt200u_fe_set_frontend(struct dvb_frontend* fe,
{
struct dtt200u_fe_state *state = fe->demodulator_priv;
u16 freq = fep->frequency / 250000;
- u8 bw,bwbuf[2] = { 0x03, 0 }, freqbuf[3] = { 0x02, 0, 0 };
+ u8 bw,bwbuf[2] = { SET_BANDWIDTH, 0 }, freqbuf[3] = { SET_FREQUENCY, 0, 0 };
switch (fep->u.ofdm.bandwidth) {
case BANDWIDTH_8_MHZ: bw = 8; break;
@@ -147,11 +121,11 @@ static int dtt200u_fe_set_frontend(struct dvb_frontend* fe,
deb_info("set_frontend\n");
bwbuf[1] = bw;
- dibusb_write_usb(state->dib,bwbuf,2);
+ dvb_usb_generic_write(state->d,bwbuf,2);
freqbuf[1] = freq & 0xff;
freqbuf[2] = (freq >> 8) & 0xff;
- dibusb_write_usb(state->dib,freqbuf,3);
+ dvb_usb_generic_write(state->d,freqbuf,3);
memcpy(&state->fep,fep,sizeof(struct dvb_frontend_parameters));
@@ -172,37 +146,9 @@ static void dtt200u_fe_release(struct dvb_frontend* fe)
kfree(state);
}
-static int dtt200u_pid_control(struct dvb_frontend *fe,int index, int pid,int onoff)
-{
- struct dtt200u_fe_state *state = (struct dtt200u_fe_state*) fe->demodulator_priv;
- u8 b_pid[4];
- pid = onoff ? pid : 0;
-
- b_pid[0] = 0x04;
- b_pid[1] = index;
- b_pid[2] = pid & 0xff;
- b_pid[3] = (pid >> 8) & 0xff;
-
- dibusb_write_usb(state->dib,b_pid,4);
- return 0;
-}
-
-static int dtt200u_fifo_control(struct dvb_frontend *fe, int onoff)
-{
- struct dtt200u_fe_state *state = (struct dtt200u_fe_state*) fe->demodulator_priv;
- u8 b_streaming[2] = { 0x08, onoff };
- u8 b_rst_pid[1] = { 0x05 };
-
- dibusb_write_usb(state->dib,b_streaming,2);
-
- if (!onoff)
- dibusb_write_usb(state->dib,b_rst_pid,1);
- return 0;
-}
-
static struct dvb_frontend_ops dtt200u_fe_ops;
-struct dvb_frontend* dtt200u_fe_attach(struct usb_dibusb *dib, struct dib_fe_xfer_ops *xfer_ops)
+struct dvb_frontend* dtt200u_fe_attach(struct dvb_usb_device *d)
{
struct dtt200u_fe_state* state = NULL;
@@ -214,14 +160,11 @@ struct dvb_frontend* dtt200u_fe_attach(struct usb_dibusb *dib, struct dib_fe_xfe
deb_info("attaching frontend dtt200u\n");
- state->dib = dib;
+ state->d = d;
state->frontend.ops = &dtt200u_fe_ops;
state->frontend.demodulator_priv = state;
- xfer_ops->fifo_ctrl = dtt200u_fifo_control;
- xfer_ops->pid_ctrl = dtt200u_pid_control;
-
goto success;
error:
return NULL;
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c
new file mode 100644
index 00000000000..fb2b5a2da13
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dtt200u.c
@@ -0,0 +1,171 @@
+/* DVB USB library compliant Linux driver for the Yakumo/Hama/Typhoon DVB-T
+ * USB2.0 receiver.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * 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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "dtt200u.h"
+
+/* debug */
+int dvb_usb_dtt200u_debug;
+module_param_named(debug,dvb_usb_dtt200u_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB_DEBUG_STATUS);
+
+static int dtt200u_streaming_ctrl(struct dvb_usb_device *d, int onoff)
+{
+ u8 b_streaming[2] = { SET_TS_CTRL, onoff };
+ u8 b_rst_pid = RESET_PID_FILTER;
+
+ dvb_usb_generic_write(d,b_streaming,2);
+
+ if (!onoff)
+ dvb_usb_generic_write(d,&b_rst_pid,1);
+ return 0;
+}
+
+static int dtt200u_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int onoff)
+{
+ u8 b_pid[4];
+ pid = onoff ? pid : 0;
+
+ b_pid[0] = SET_PID_FILTER;
+ b_pid[1] = index;
+ b_pid[2] = pid & 0xff;
+ b_pid[3] = (pid >> 8) & 0xff;
+
+ return dvb_usb_generic_write(d,b_pid,4);
+}
+
+/* remote control */
+/* key list for the tiny remote control (Yakumo, don't know about the others) */
+static struct dvb_usb_rc_key dtt200u_rc_keys[] = {
+ { 0x80, 0x01, KEY_MUTE },
+ { 0x80, 0x02, KEY_CHANNELDOWN },
+ { 0x80, 0x03, KEY_VOLUMEDOWN },
+ { 0x80, 0x04, KEY_1 },
+ { 0x80, 0x05, KEY_2 },
+ { 0x80, 0x06, KEY_3 },
+ { 0x80, 0x07, KEY_4 },
+ { 0x80, 0x08, KEY_5 },
+ { 0x80, 0x09, KEY_6 },
+ { 0x80, 0x0a, KEY_7 },
+ { 0x00, 0x0c, KEY_ZOOM },
+ { 0x80, 0x0d, KEY_0 },
+ { 0x00, 0x0e, KEY_SELECT },
+ { 0x80, 0x12, KEY_POWER },
+ { 0x80, 0x1a, KEY_CHANNELUP },
+ { 0x80, 0x1b, KEY_8 },
+ { 0x80, 0x1e, KEY_VOLUMEUP },
+ { 0x80, 0x1f, KEY_9 },
+};
+
+static int dtt200u_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+ u8 key[5],cmd = GET_RC_KEY;
+ dvb_usb_generic_rw(d,&cmd,1,key,5,0);
+ dvb_usb_nec_rc_key_to_event(d,key,event,state);
+ if (key[0] != 0)
+ deb_info("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
+ return 0;
+}
+
+static int dtt200u_frontend_attach(struct dvb_usb_device *d)
+{
+ d->fe = dtt200u_fe_attach(d);
+ return 0;
+}
+
+static struct dvb_usb_properties dtt200u_properties;
+
+static int dtt200u_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE);
+}
+
+static struct usb_device_id dtt200u_usb_table [] = {
+ { USB_DEVICE(USB_VID_AVERMEDIA_UNK, USB_PID_DTT200U_COLD) },
+ { USB_DEVICE(USB_VID_AVERMEDIA_UNK, USB_PID_DTT200U_WARM) },
+ { 0 },
+};
+MODULE_DEVICE_TABLE(usb, dtt200u_usb_table);
+
+static struct dvb_usb_properties dtt200u_properties = {
+ .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING,
+ .pid_filter_count = 255, /* It is a guess, but there are at least 10 */
+
+ .usb_ctrl = CYPRESS_FX2,
+ .firmware = "dvb-usb-dtt200u-01.fw",
+
+ .streaming_ctrl = dtt200u_streaming_ctrl,
+ .pid_filter = dtt200u_pid_filter,
+ .frontend_attach = dtt200u_frontend_attach,
+
+ .rc_interval = 200,
+ .rc_key_map = dtt200u_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys),
+ .rc_query = dtt200u_rc_query,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+
+ /* parameter for the MPEG2-data transfer */
+ .urb = {
+ .type = DVB_USB_BULK,
+ .count = 7,
+ .endpoint = 0x02,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
+
+ .num_device_descs = 1,
+ .devices = {
+ { .name = "Yakumo/Hama/Typhoon DVB-T USB2.0)",
+ .cold_ids = { &dtt200u_usb_table[0], &dtt200u_usb_table[2] },
+ .warm_ids = { &dtt200u_usb_table[1], NULL },
+ },
+ { 0 },
+ }
+};
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver dtt200u_usb_driver = {
+ .owner = THIS_MODULE,
+ .name = "Yakumo/Hama/Typhoon DVB-T USB2.0",
+ .probe = dtt200u_usb_probe,
+ .disconnect = dvb_usb_device_exit,
+ .id_table = dtt200u_usb_table,
+};
+
+/* module stuff */
+static int __init dtt200u_usb_module_init(void)
+{
+ int result;
+ if ((result = usb_register(&dtt200u_usb_driver))) {
+ err("usb_register failed. (%d)",result);
+ return result;
+ }
+
+ return 0;
+}
+
+static void __exit dtt200u_usb_module_exit(void)
+{
+ /* deregister this driver from the USB subsystem */
+ usb_deregister(&dtt200u_usb_driver);
+}
+
+module_init(dtt200u_usb_module_init);
+module_exit(dtt200u_usb_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("Driver for the Yakumo/Hama/Typhoon DVB-T USB2.0 device");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.h b/drivers/media/dvb/dvb-usb/dtt200u.h
new file mode 100644
index 00000000000..ed414207151
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dtt200u.h
@@ -0,0 +1,66 @@
+/* Common header file of Linux driver for the Yakumo/Hama/Typhoon DVB-T
+ * USB2.0 receiver.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * 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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#ifndef _DVB_USB_DTT200U_H_
+#define _DVB_USB_DTT200U_H_
+
+#define DVB_USB_LOG_PREFIX "dtt200u"
+#include "dvb-usb.h"
+
+extern int dvb_usb_dtt200u_debug;
+#define deb_info(args...) dprintk(dvb_usb_dtt200u_debug,0x01,args)
+#define deb_xfer(args...) dprintk(dvb_usb_dtt200u_debug,0x02,args)
+
+/* guessed protocol description (reverse engineered):
+ * read
+ * 00 - USB type 0x02 for usb2.0, 0x01 for usb1.1
+ * 81 - <TS_LOCK> <current frequency divided by 250000>
+ * 82 - crash - do not touch
+ * 83 - crash - do not touch
+ * 84 - remote control
+ * 85 - crash - do not touch (OK, stop testing here)
+ * 88 - locking 2 bytes (0x80 0x40 == no signal, 0x89 0x20 == nice signal)
+ * 89 - noise-to-signal
+ * 8a - unkown 1 byte - signal_strength
+ * 8c - ber ???
+ * 8d - ber
+ * 8e - unc
+ */
+
+#define GET_SPEED 0x00
+#define GET_TUNE_STAT 0x81
+#define GET_RC_KEY 0x84
+#define GET_STATUS 0x88
+#define GET_SNR 0x89
+#define GET_SIG_STRENGTH 0x8a
+#define GET_UNK 0x8c
+#define GET_BER 0x8d
+#define GET_UNC 0x8e
+
+/* write
+ * 01 - reset the demod
+ * 02 - frequency (divided by 250000)
+ * 03 - bandwidth
+ * 04 - pid table (index pid(7:0) pid(12:8))
+ * 05 - reset the pid table
+ * 08 - demod transfer enabled or not (FX2 transfer is enabled by default)
+ */
+
+#define RESET_DEMOD 0x01
+#define SET_FREQUENCY 0x02
+#define SET_BANDWIDTH 0x03
+#define SET_PID_FILTER 0x04
+#define RESET_PID_FILTER 0x05
+#define SET_TS_CTRL 0x08
+
+extern struct dvb_frontend * dtt200u_fe_attach(struct dvb_usb_device *d);
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-common.h b/drivers/media/dvb/dvb-usb/dvb-usb-common.h
new file mode 100644
index 00000000000..67e0d73fbce
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-common.h
@@ -0,0 +1,44 @@
+/* dvb-usb-common.h is part of the DVB USB library.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ * see dvb-usb-init.c for copyright information.
+ *
+ * a header file containing prototypes and types for internal use of the dvb-usb-lib
+ */
+#ifndef _DVB_USB_COMMON_H_
+#define _DVB_USB_COMMON_H_
+
+#define DVB_USB_LOG_PREFIX "dvb-usb"
+#include "dvb-usb.h"
+
+extern int dvb_usb_debug;
+
+#define deb_info(args...) dprintk(dvb_usb_debug,0x01,args)
+#define deb_xfer(args...) dprintk(dvb_usb_debug,0x02,args)
+#define deb_pll(args...) dprintk(dvb_usb_debug,0x04,args)
+#define deb_ts(args...) dprintk(dvb_usb_debug,0x08,args)
+#define deb_err(args...) dprintk(dvb_usb_debug,0x10,args)
+#define deb_rc(args...) dprintk(dvb_usb_debug,0x20,args)
+#define deb_fw(args...) dprintk(dvb_usb_debug,0x40,args)
+
+/* commonly used methods */
+extern int usb_cypress_load_firmware(struct usb_device *, const char *, int);
+
+extern int dvb_usb_urb_submit(struct dvb_usb_device *);
+extern int dvb_usb_urb_kill(struct dvb_usb_device *);
+extern int dvb_usb_urb_init(struct dvb_usb_device *);
+extern int dvb_usb_urb_exit(struct dvb_usb_device *);
+
+extern int dvb_usb_i2c_init(struct dvb_usb_device *);
+extern int dvb_usb_i2c_exit(struct dvb_usb_device *);
+
+extern int dvb_usb_dvb_init(struct dvb_usb_device *);
+extern int dvb_usb_dvb_exit(struct dvb_usb_device *);
+
+extern int dvb_usb_fe_init(struct dvb_usb_device *);
+extern int dvb_usb_fe_exit(struct dvb_usb_device *);
+
+extern int dvb_usb_remote_init(struct dvb_usb_device *);
+extern int dvb_usb_remote_exit(struct dvb_usb_device *);
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
new file mode 100644
index 00000000000..bdd72f77970
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
@@ -0,0 +1,210 @@
+/* dvb-usb-dvb.c is part of the DVB USB library.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ * see dvb-usb-init.c for copyright information.
+ *
+ * This file contains functions for initializing and handling the
+ * linux-dvb API.
+ */
+#include "dvb-usb-common.h"
+
+static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
+{
+ struct dvb_usb_device *d = dvbdmxfeed->demux->priv;
+ int newfeedcount,ret;
+
+ if (d == NULL)
+ return -ENODEV;
+
+ newfeedcount = d->feedcount + (onoff ? 1 : -1);
+
+ /*
+ * stop feed before setting a new pid if there will be no pid anymore
+ */
+ if (newfeedcount == 0) {
+ deb_ts("stop feeding\n");
+
+ if (d->props.streaming_ctrl != NULL)
+ if ((ret = d->props.streaming_ctrl(d,0)))
+ err("error while stopping stream.");
+
+ dvb_usb_urb_kill(d);
+ }
+
+ d->feedcount = newfeedcount;
+
+ /* activate the pid on the device specific pid_filter */
+ deb_ts("setting pid: %5d %04x at index %d '%s'\n",dvbdmxfeed->pid,dvbdmxfeed->pid,dvbdmxfeed->index,onoff ? "on" : "off");
+ if (d->props.caps & DVB_USB_HAS_PID_FILTER &&
+ d->pid_filtering &&
+ d->props.pid_filter != NULL)
+ d->props.pid_filter(d,dvbdmxfeed->index,dvbdmxfeed->pid,onoff);
+
+ /* start the feed if this was the first feed and there is still a feed
+ * for reception.
+ */
+ if (d->feedcount == onoff && d->feedcount > 0) {
+
+ deb_ts("controlling pid parser\n");
+ if (d->props.caps & DVB_USB_HAS_PID_FILTER &&
+ d->props.caps & DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF &&
+ d->props.pid_filter_ctrl != NULL)
+ if (d->props.pid_filter_ctrl(d,d->pid_filtering) < 0)
+ err("could not handle pid_parser");
+
+ deb_ts("start feeding\n");
+ if (d->props.streaming_ctrl != NULL)
+ if (d->props.streaming_ctrl(d,1)) {
+ err("error while enabling fifo.");
+ return -ENODEV;
+ }
+
+ dvb_usb_urb_submit(d);
+ }
+ return 0;
+}
+
+static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+ deb_ts("start pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid,dvbdmxfeed->type);
+ return dvb_usb_ctrl_feed(dvbdmxfeed,1);
+}
+
+static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+ deb_ts("stop pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid, dvbdmxfeed->type);
+ return dvb_usb_ctrl_feed(dvbdmxfeed,0);
+}
+
+int dvb_usb_dvb_init(struct dvb_usb_device *d)
+{
+ int ret;
+
+ if ((ret = dvb_register_adapter(&d->dvb_adap, d->desc->name,
+ d->owner)) < 0) {
+ deb_info("dvb_register_adapter failed: error %d", ret);
+ goto err;
+ }
+ d->dvb_adap.priv = d;
+
+ if (d->props.read_mac_address) {
+ if (d->props.read_mac_address(d,d->dvb_adap.proposed_mac) == 0)
+ info("MAC address: %02x:%02x:%02x:%02x:%02x:%02x",d->dvb_adap.proposed_mac[0],
+ d->dvb_adap.proposed_mac[1],d->dvb_adap.proposed_mac[2],
+ d->dvb_adap.proposed_mac[3],d->dvb_adap.proposed_mac[4],
+ d->dvb_adap.proposed_mac[5]);
+ else
+ err("MAC address reading failed.");
+ }
+
+
+ d->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
+ d->demux.priv = d;
+
+ d->demux.feednum = d->demux.filternum = d->max_feed_count;
+ d->demux.start_feed = dvb_usb_start_feed;
+ d->demux.stop_feed = dvb_usb_stop_feed;
+ d->demux.write_to_decoder = NULL;
+ if ((ret = dvb_dmx_init(&d->demux)) < 0) {
+ err("dvb_dmx_init failed: error %d",ret);
+ goto err_dmx;
+ }
+
+ d->dmxdev.filternum = d->demux.filternum;
+ d->dmxdev.demux = &d->demux.dmx;
+ d->dmxdev.capabilities = 0;
+ if ((ret = dvb_dmxdev_init(&d->dmxdev, &d->dvb_adap)) < 0) {
+ err("dvb_dmxdev_init failed: error %d",ret);
+ goto err_dmx_dev;
+ }
+
+ dvb_net_init(&d->dvb_adap, &d->dvb_net, &d->demux.dmx);
+
+ goto success;
+err_dmx_dev:
+ dvb_dmx_release(&d->demux);
+err_dmx:
+ dvb_unregister_adapter(&d->dvb_adap);
+err:
+ return ret;
+success:
+ d->state |= DVB_USB_STATE_DVB;
+ return 0;
+}
+
+int dvb_usb_dvb_exit(struct dvb_usb_device *d)
+{
+ if (d->state & DVB_USB_STATE_DVB) {
+ deb_info("unregistering DVB part\n");
+ dvb_net_release(&d->dvb_net);
+ d->demux.dmx.close(&d->demux.dmx);
+ dvb_dmxdev_release(&d->dmxdev);
+ dvb_dmx_release(&d->demux);
+ dvb_unregister_adapter(&d->dvb_adap);
+ d->state &= ~DVB_USB_STATE_DVB;
+ }
+ return 0;
+}
+
+static int dvb_usb_fe_wakeup(struct dvb_frontend *fe)
+{
+ struct dvb_usb_device *d = fe->dvb->priv;
+
+ if (d->props.power_ctrl)
+ d->props.power_ctrl(d,1);
+
+ if (d->fe_init)
+ d->fe_init(fe);
+
+ return 0;
+}
+
+static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
+{
+ struct dvb_usb_device *d = fe->dvb->priv;
+
+ if (d->fe_sleep)
+ d->fe_sleep(fe);
+
+ if (d->props.power_ctrl)
+ d->props.power_ctrl(d,0);
+
+ return 0;
+}
+
+int dvb_usb_fe_init(struct dvb_usb_device* d)
+{
+ if (d->props.frontend_attach == NULL) {
+ err("strange '%s' don't want to attach a frontend.",d->desc->name);
+ return 0;
+ }
+
+ d->props.frontend_attach(d);
+
+ /* re-assign sleep and wakeup functions */
+ if (d->fe != NULL) {
+ d->fe_init = d->fe->ops->init; d->fe->ops->init = dvb_usb_fe_wakeup;
+ d->fe_sleep = d->fe->ops->sleep; d->fe->ops->sleep = dvb_usb_fe_sleep;
+
+ if (dvb_register_frontend(&d->dvb_adap, d->fe)) {
+ err("Frontend registration failed.");
+ if (d->fe->ops->release)
+ d->fe->ops->release(d->fe);
+ d->fe = NULL;
+ return -ENODEV;
+ }
+ } else
+ err("no frontend was attached by '%s'",d->desc->name);
+
+ if (d->props.tuner_attach != NULL)
+ d->props.tuner_attach(d);
+
+ return 0;
+}
+
+int dvb_usb_fe_exit(struct dvb_usb_device *d)
+{
+ if (d->fe != NULL)
+ dvb_unregister_frontend(d->fe);
+ return 0;
+}
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
new file mode 100644
index 00000000000..5244e39770a
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
@@ -0,0 +1,100 @@
+/* dvb-usb-firmware.c is part of the DVB USB library.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ * see dvb-usb-init.c for copyright information.
+ *
+ * This file contains functions for downloading the firmware to Cypress FX 1 and 2 based devices.
+ *
+ * FIXME: This part does actually not belong to dvb-usb, but to the usb-subsystem.
+ */
+#include "dvb-usb-common.h"
+
+#include <linux/firmware.h>
+#include <linux/usb.h>
+
+struct usb_cypress_controller {
+ int id;
+ const char *name; /* name of the usb controller */
+ u16 cpu_cs_register; /* needs to be restarted, when the firmware has been downloaded. */
+};
+
+static struct usb_cypress_controller cypress[] = {
+ { .id = CYPRESS_AN2135, .name = "Cypress AN2135", .cpu_cs_register = 0x7f92 },
+ { .id = CYPRESS_AN2235, .name = "Cypress AN2235", .cpu_cs_register = 0x7f92 },
+ { .id = CYPRESS_FX2, .name = "Cypress FX2", .cpu_cs_register = 0xe600 },
+};
+
+/*
+ * load a firmware packet to the device
+ */
+static int usb_cypress_writemem(struct usb_device *udev,u16 addr,u8 *data, u8 len)
+{
+ return usb_control_msg(udev, usb_sndctrlpipe(udev,0),
+ 0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5*HZ);
+}
+
+int usb_cypress_load_firmware(struct usb_device *udev, const char *filename, int type)
+{
+ const struct firmware *fw = NULL;
+ u16 addr;
+ u8 *b,*p;
+ int ret = 0,i;
+
+ if ((ret = request_firmware(&fw, filename, &udev->dev)) != 0) {
+ err("did not find the firmware file. (%s) "
+ "Please see linux/Documentation/dvb/ for more details on firmware-problems.",
+ filename);
+ return ret;
+ }
+
+ info("downloading firmware from file '%s' to the '%s'",filename,cypress[type].name);
+
+ p = kmalloc(fw->size,GFP_KERNEL);
+ if (p != NULL) {
+ u8 reset;
+ /*
+ * you cannot use the fw->data as buffer for
+ * usb_control_msg, a new buffer has to be
+ * created
+ */
+ memcpy(p,fw->data,fw->size);
+
+ /* stop the CPU */
+ reset = 1;
+ if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1)
+ err("could not stop the USB controller CPU.");
+ for(i = 0; p[i+3] == 0 && i < fw->size; ) {
+ b = (u8 *) &p[i];
+ addr = cpu_to_le16( *((u16 *) &b[1]) );
+
+ deb_fw("writing to address 0x%04x (buffer: 0x%02x%02x)\n",addr,b[1],b[2]);
+
+ ret = usb_cypress_writemem(udev,addr,&b[4],b[0]);
+
+ if (ret != b[0]) {
+ err("error while transferring firmware "
+ "(transferred size: %d, block size: %d)",
+ ret,b[0]);
+ ret = -EINVAL;
+ break;
+ }
+ i += 5 + b[0];
+ }
+ /* length in ret */
+ if (ret > 0)
+ ret = 0;
+ /* restart the CPU */
+ reset = 0;
+ if (ret || usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1) != 1) {
+ err("could not restart the USB controller CPU.");
+ ret = -EINVAL;
+ }
+
+ kfree(p);
+ } else {
+ ret = -ENOMEM;
+ }
+ release_firmware(fw);
+
+ return ret;
+}
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
new file mode 100644
index 00000000000..9f0a8d90d14
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
@@ -0,0 +1,118 @@
+/* dvb-usb-i2c.c is part of the DVB USB library.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ * see dvb-usb-init.c for copyright information.
+ *
+ * This file contains functions for (de-)initializing an I2C adapter.
+ */
+#include "dvb-usb-common.h"
+
+int dvb_usb_i2c_init(struct dvb_usb_device *d)
+{
+ int ret = 0;
+
+ if (!(d->props.caps & DVB_USB_IS_AN_I2C_ADAPTER))
+ return 0;
+
+ if (d->props.i2c_algo == NULL) {
+ err("no i2c algorithm specified");
+ return -EINVAL;
+ }
+
+ strncpy(d->i2c_adap.name,d->desc->name,I2C_NAME_SIZE);
+#ifdef I2C_ADAP_CLASS_TV_DIGITAL
+ d->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL,
+#else
+ d->i2c_adap.class = I2C_CLASS_TV_DIGITAL,
+#endif
+ d->i2c_adap.algo = d->props.i2c_algo;
+ d->i2c_adap.algo_data = NULL;
+ d->i2c_adap.id = I2C_ALGO_BIT;
+
+ i2c_set_adapdata(&d->i2c_adap, d);
+
+ if ((ret = i2c_add_adapter(&d->i2c_adap)) < 0)
+ err("could not add i2c adapter");
+
+ d->state |= DVB_USB_STATE_I2C;
+
+ return ret;
+}
+
+int dvb_usb_i2c_exit(struct dvb_usb_device *d)
+{
+ if (d->state & DVB_USB_STATE_I2C)
+ i2c_del_adapter(&d->i2c_adap);
+ d->state &= ~DVB_USB_STATE_I2C;
+ return 0;
+}
+
+int dvb_usb_pll_init_i2c(struct dvb_frontend *fe)
+{
+ struct dvb_usb_device *d = fe->dvb->priv;
+ struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = d->pll_init, .len = 4 };
+ int ret = 0;
+
+ /* if there is nothing to initialize */
+ if (d->pll_init[0] == 0x00 && d->pll_init[1] == 0x00 &&
+ d->pll_init[2] == 0x00 && d->pll_init[3] == 0x00)
+ return 0;
+
+ if (d->tuner_pass_ctrl)
+ d->tuner_pass_ctrl(fe,1,d->pll_addr);
+
+ deb_pll("pll init: %x\n",d->pll_addr);
+ deb_pll("pll-buf: %x %x %x %x\n",d->pll_init[0],d->pll_init[1],
+ d->pll_init[2],d->pll_init[3]);
+
+ if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) {
+ err("tuner i2c write failed for pll_init.");
+ ret = -EREMOTEIO;
+ }
+ msleep(1);
+
+ if (d->tuner_pass_ctrl)
+ d->tuner_pass_ctrl(fe,0,d->pll_addr);
+ return ret;
+}
+EXPORT_SYMBOL(dvb_usb_pll_init_i2c);
+
+int dvb_usb_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep, u8 b[5])
+{
+ struct dvb_usb_device *d = fe->dvb->priv;
+
+ deb_pll("pll addr: %x, freq: %d %p\n",d->pll_addr,fep->frequency,d->pll_desc);
+
+ b[0] = d->pll_addr << 1;
+ dvb_pll_configure(d->pll_desc,&b[1],fep->frequency,fep->u.ofdm.bandwidth);
+
+ deb_pll("pll-buf: %x %x %x %x %x\n",b[0],b[1],b[2],b[3],b[4]);
+
+ return 0;
+}
+EXPORT_SYMBOL(dvb_usb_pll_set);
+
+int dvb_usb_pll_set_i2c(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+{
+ struct dvb_usb_device *d = fe->dvb->priv;
+ int ret = 0;
+ u8 b[5];
+ struct i2c_msg msg = { .addr = d->pll_addr, .flags = 0, .buf = &b[1], .len = 4 };
+
+ dvb_usb_pll_set(fe,fep,b);
+
+ if (d->tuner_pass_ctrl)
+ d->tuner_pass_ctrl(fe,1,d->pll_addr);
+
+ if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) {
+ err("tuner i2c write failed for pll_set.");
+ ret = -EREMOTEIO;
+ }
+ msleep(1);
+
+ if (d->tuner_pass_ctrl)
+ d->tuner_pass_ctrl(fe,0,d->pll_addr);
+
+ return ret;
+}
+EXPORT_SYMBOL(dvb_usb_pll_set_i2c);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
new file mode 100644
index 00000000000..bcb34191868
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -0,0 +1,83 @@
+/* dvb-usb-ids.h is part of the DVB USB library.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) see
+ * dvb-usb-init.c for copyright information.
+ *
+ * a header file containing define's for the USB device supported by the
+ * various drivers.
+ */
+#ifndef _DVB_USB_IDS_H_
+#define _DVB_USB_IDS_H_
+
+/* Vendor IDs */
+#define USB_VID_ADSTECH 0x06e1
+#define USB_VID_ANCHOR 0x0547
+#define USB_VID_AVERMEDIA_UNK 0x14aa
+#define USB_VID_AVERMEDIA 0x07ca
+#define USB_VID_COMPRO 0x185b
+#define USB_VID_COMPRO_UNK 0x145f
+#define USB_VID_CYPRESS 0x04b4
+#define USB_VID_DIBCOM 0x10b8
+#define USB_VID_DVICO 0x0fe9
+#define USB_VID_EMPIA 0xeb1a
+#define USB_VID_GRANDTEC 0x5032
+#define USB_VID_HANFTEK 0x15f4
+#define USB_VID_HAUPPAUGE 0x2040
+#define USB_VID_HYPER_PALTEK 0x1025
+#define USB_VID_VISIONPLUS 0x13d3
+#define USB_VID_TWINHAN 0x1822
+#define USB_VID_ULTIMA_ELECTRONIC 0x05d8
+
+/* Product IDs */
+#define USB_PID_ADSTECH_USB2_COLD 0xa333
+#define USB_PID_ADSTECH_USB2_WARM 0xa334
+#define USB_PID_AVERMEDIA_DVBT_USB_COLD 0x0001
+#define USB_PID_AVERMEDIA_DVBT_USB_WARM 0x0002
+#define USB_PID_AVERMEDIA_DVBT_USB2_COLD 0xa800
+#define USB_PID_AVERMEDIA_DVBT_USB2_WARM 0xa801
+#define USB_PID_COMPRO_DVBU2000_COLD 0xd000
+#define USB_PID_COMPRO_DVBU2000_WARM 0xd001
+#define USB_PID_COMPRO_DVBU2000_UNK_COLD 0x010c
+#define USB_PID_COMPRO_DVBU2000_UNK_WARM 0x010d
+#define USB_PID_DIBCOM_MOD3000_COLD 0x0bb8
+#define USB_PID_DIBCOM_MOD3000_WARM 0x0bb9
+#define USB_PID_DIBCOM_MOD3001_COLD 0x0bc6
+#define USB_PID_DIBCOM_MOD3001_WARM 0x0bc7
+#define USB_PID_DIBCOM_ANCHOR_2135_COLD 0x2131
+#define USB_PID_GRANDTEC_DVBT_USB_COLD 0x0fa0
+#define USB_PID_GRANDTEC_DVBT_USB_WARM 0x0fa1
+#define USB_PID_KWORLD_VSTREAM_COLD 0x17de
+#define USB_PID_KWORLD_VSTREAM_WARM 0x17df
+#define USB_PID_TWINHAN_VP7041_COLD 0x3201
+#define USB_PID_TWINHAN_VP7041_WARM 0x3202
+#define USB_PID_TWINHAN_VP7045_COLD 0x3205
+#define USB_PID_TWINHAN_VP7045_WARM 0x3206
+#define USB_PID_DNTV_TINYUSB2_COLD 0x3223
+#define USB_PID_DNTV_TINYUSB2_WARM 0x3224
+#define USB_PID_TWINHAN_VP7021_COLD 0x3207
+#define USB_PID_TWINHAN_VP7021_WARM 0x3208
+#define USB_PID_ULTIMA_TVBOX_COLD 0x8105
+#define USB_PID_ULTIMA_TVBOX_WARM 0x8106
+#define USB_PID_ULTIMA_TVBOX_AN2235_COLD 0x8107
+#define USB_PID_ULTIMA_TVBOX_AN2235_WARM 0x8108
+#define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD 0x2235
+#define USB_PID_ULTIMA_TVBOX_USB2_COLD 0x8109
+#define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD 0x8613
+#define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM 0x1002
+#define USB_PID_UNK_HYPER_PALTEK_COLD 0x005e
+#define USB_PID_UNK_HYPER_PALTEK_WARM 0x005f
+#define USB_PID_HANFTEK_UMT_010_COLD 0x0001
+#define USB_PID_HANFTEK_UMT_010_WARM 0x0015
+#define USB_PID_DTT200U_COLD 0x0201
+#define USB_PID_DTT200U_WARM 0x0301
+#define USB_PID_WINTV_NOVA_T_USB2_COLD 0x9300
+#define USB_PID_WINTV_NOVA_T_USB2_WARM 0x9301
+#define USB_PID_NEBULA_DIGITV 0x0201
+#define USB_PID_DVICO_BLUEBIRD_LGZ201 0xdb00
+#define USB_PID_DVICO_BLUEBIRD_TH7579 0xdb10
+#define USB_PID_DVICO_BLUEBIRD_LGDT 0xd820
+#define USB_PID_DVICO_BLUEBIRD_LGZ201_1 0xdb01
+#define USB_PID_DVICO_BLUEBIRD_TH7579_2 0xdb11
+
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
new file mode 100644
index 00000000000..3aadec974cf
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
@@ -0,0 +1,211 @@
+/*
+ * DVB USB library - provides a generic interface for a DVB USB device driver.
+ *
+ * dvb-usb-init.c
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * 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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "dvb-usb-common.h"
+
+/* debug */
+int dvb_usb_debug;
+module_param_named(debug,dvb_usb_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64 (or-able))." DVB_USB_DEBUG_STATUS);
+
+/* general initialization functions */
+int dvb_usb_exit(struct dvb_usb_device *d)
+{
+ deb_info("state before exiting everything: %x\n",d->state);
+ dvb_usb_remote_exit(d);
+ dvb_usb_fe_exit(d);
+ dvb_usb_i2c_exit(d);
+ dvb_usb_dvb_exit(d);
+ dvb_usb_urb_exit(d);
+ deb_info("state should be zero now: %x\n",d->state);
+ d->state = DVB_USB_STATE_INIT;
+ kfree(d->priv);
+ kfree(d);
+ return 0;
+}
+
+static int dvb_usb_init(struct dvb_usb_device *d)
+{
+ int ret = 0;
+
+ sema_init(&d->usb_sem, 1);
+ sema_init(&d->i2c_sem, 1);
+
+ d->state = DVB_USB_STATE_INIT;
+
+/* check the capabilites and set appropriate variables */
+
+/* speed - when running at FULL speed we need a HW PID filter */
+ if (d->udev->speed == USB_SPEED_FULL && !(d->props.caps & DVB_USB_HAS_PID_FILTER)) {
+ err("This USB2.0 device cannot be run on a USB1.1 port. (it lacks a HW PID filter)");
+ return -ENODEV;
+ }
+
+ if ((d->udev->speed == USB_SPEED_FULL && d->props.caps & DVB_USB_HAS_PID_FILTER) ||
+ (d->props.caps & DVB_USB_NEED_PID_FILTERING)) {
+ info("will use the device's hw PID filter.");
+ d->pid_filtering = 1;
+ d->max_feed_count = d->props.pid_filter_count;
+ } else {
+ info("will pass the complete MPEG2 transport stream to the demuxer.");
+ d->pid_filtering = 0;
+ d->max_feed_count = 255;
+ }
+
+ if (d->props.power_ctrl)
+ d->props.power_ctrl(d,1);
+
+ if ((ret = dvb_usb_urb_init(d)) ||
+ (ret = dvb_usb_dvb_init(d)) ||
+ (ret = dvb_usb_i2c_init(d)) ||
+ (ret = dvb_usb_fe_init(d))) {
+ dvb_usb_exit(d);
+ return ret;
+ }
+
+ if ((ret = dvb_usb_remote_init(d)))
+ err("could not initialize remote control.");
+
+ if (d->props.power_ctrl)
+ d->props.power_ctrl(d,0);
+
+ return 0;
+}
+
+/* determine the name and the state of the just found USB device */
+static struct dvb_usb_device_description * dvb_usb_find_device(struct usb_device *udev,struct dvb_usb_properties *props, int *cold)
+{
+ int i,j;
+ struct dvb_usb_device_description *desc = NULL;
+ *cold = -1;
+
+ for (i = 0; i < props->num_device_descs; i++) {
+
+ for (j = 0; j < DVB_USB_ID_MAX_NUM && props->devices[i].cold_ids[j] != NULL; j++) {
+ deb_info("check for cold %x %x\n",props->devices[i].cold_ids[j]->idVendor, props->devices[i].cold_ids[j]->idProduct);
+ if (props->devices[i].cold_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) &&
+ props->devices[i].cold_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) {
+ *cold = 1;
+ desc = &props->devices[i];
+ break;
+ }
+ }
+
+ if (desc != NULL)
+ break;
+
+ for (j = 0; j < DVB_USB_ID_MAX_NUM && props->devices[i].warm_ids[j] != NULL; j++) {
+ deb_info("check for warm %x %x\n",props->devices[i].warm_ids[j]->idVendor, props->devices[i].warm_ids[j]->idProduct);
+ if (props->devices[i].warm_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) &&
+ props->devices[i].warm_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) {
+ *cold = 0;
+ desc = &props->devices[i];
+ break;
+ }
+ }
+ }
+
+ if (desc != NULL && props->identify_state != NULL)
+ props->identify_state(udev,props,&desc,cold);
+
+ return desc;
+}
+
+/*
+ * USB
+ */
+int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties *props, struct module *owner)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct dvb_usb_device *d = NULL;
+ struct dvb_usb_device_description *desc = NULL;
+
+ int ret = -ENOMEM,cold=0;
+
+ if ((desc = dvb_usb_find_device(udev,props,&cold)) == NULL) {
+ deb_err("something went very wrong, device was not found in current device list - let's see what comes next.\n");
+ return -ENODEV;
+ }
+
+ if (cold) {
+ info("found a '%s' in cold state, will try to load a firmware",desc->name);
+ ret = usb_cypress_load_firmware(udev,props->firmware,props->usb_ctrl);
+ } else {
+ info("found a '%s' in warm state.",desc->name);
+ d = kmalloc(sizeof(struct dvb_usb_device),GFP_KERNEL);
+ if (d == NULL) {
+ err("no memory for 'struct dvb_usb_device'");
+ return ret;
+ }
+ memset(d,0,sizeof(struct dvb_usb_device));
+
+ d->udev = udev;
+ memcpy(&d->props,props,sizeof(struct dvb_usb_properties));
+ d->desc = desc;
+ d->owner = owner;
+
+ if (d->props.size_of_priv > 0) {
+ d->priv = kmalloc(d->props.size_of_priv,GFP_KERNEL);
+ if (d->priv == NULL) {
+ err("no memory for priv in 'struct dvb_usb_device'");
+ kfree(d);
+ return -ENOMEM;
+ }
+ memset(d->priv,0,d->props.size_of_priv);
+ }
+
+ usb_set_intfdata(intf, d);
+
+ ret = dvb_usb_init(d);
+ }
+
+ if (ret == 0)
+ info("%s successfully initialized and connected.",desc->name);
+ else
+ info("%s error while loading driver (%d)",desc->name,ret);
+ return ret;
+}
+EXPORT_SYMBOL(dvb_usb_device_init);
+
+void dvb_usb_device_exit(struct usb_interface *intf)
+{
+ struct dvb_usb_device *d = usb_get_intfdata(intf);
+ const char *name = "generic DVB-USB module";
+
+ usb_set_intfdata(intf,NULL);
+ if (d != NULL && d->desc != NULL) {
+ name = d->desc->name;
+ dvb_usb_exit(d);
+ }
+ info("%s successfully deinitialized and disconnected.",name);
+
+}
+EXPORT_SYMBOL(dvb_usb_device_exit);
+
+/* module stuff */
+static int __init dvb_usb_module_init(void)
+{
+ return 0;
+}
+
+static void __exit dvb_usb_module_exit(void)
+{
+}
+
+module_init (dvb_usb_module_init);
+module_exit (dvb_usb_module_exit);
+
+MODULE_VERSION("0.3");
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("A library module containing commonly used USB and DVB function USB DVB devices");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
new file mode 100644
index 00000000000..9f1e23f82ba
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
@@ -0,0 +1,175 @@
+/* dvb-usb-remote.c is part of the DVB USB library.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ * see dvb-usb-init.c for copyright information.
+ *
+ * This file contains functions for initializing the the input-device and for handling remote-control-queries.
+ */
+#include "dvb-usb-common.h"
+
+/* Remote-control poll function - called every dib->rc_query_interval ms to see
+ * whether the remote control has received anything.
+ *
+ * TODO: Fix the repeat rate of the input device.
+ */
+static void dvb_usb_read_remote_control(void *data)
+{
+ struct dvb_usb_device *d = data;
+ u32 event;
+ int state;
+
+ /* TODO: need a lock here. We can simply skip checking for the remote control
+ if we're busy. */
+
+ if (d->props.rc_query(d,&event,&state)) {
+ err("error while querying for an remote control event.");
+ goto schedule;
+ }
+
+
+ switch (state) {
+ case REMOTE_NO_KEY_PRESSED:
+ break;
+ case REMOTE_KEY_PRESSED:
+ deb_rc("key pressed\n");
+ d->last_event = event;
+ case REMOTE_KEY_REPEAT:
+ deb_rc("key repeated\n");
+ input_event(&d->rc_input_dev, EV_KEY, event, 1);
+ input_event(&d->rc_input_dev, EV_KEY, d->last_event, 0);
+ input_sync(&d->rc_input_dev);
+ break;
+ default:
+ break;
+ }
+
+/* improved repeat handling ???
+ switch (state) {
+ case REMOTE_NO_KEY_PRESSED:
+ deb_rc("NO KEY PRESSED\n");
+ if (d->last_state != REMOTE_NO_KEY_PRESSED) {
+ deb_rc("releasing event %d\n",d->last_event);
+ input_event(&d->rc_input_dev, EV_KEY, d->last_event, 0);
+ input_sync(&d->rc_input_dev);
+ }
+ d->last_state = REMOTE_NO_KEY_PRESSED;
+ d->last_event = 0;
+ break;
+ case REMOTE_KEY_PRESSED:
+ deb_rc("KEY PRESSED\n");
+ deb_rc("pressing event %d\n",event);
+
+ input_event(&d->rc_input_dev, EV_KEY, event, 1);
+ input_sync(&d->rc_input_dev);
+
+ d->last_event = event;
+ d->last_state = REMOTE_KEY_PRESSED;
+ break;
+ case REMOTE_KEY_REPEAT:
+ deb_rc("KEY_REPEAT\n");
+ if (d->last_state != REMOTE_NO_KEY_PRESSED) {
+ deb_rc("repeating event %d\n",d->last_event);
+ input_event(&d->rc_input_dev, EV_KEY, d->last_event, 2);
+ input_sync(&d->rc_input_dev);
+ d->last_state = REMOTE_KEY_REPEAT;
+ }
+ default:
+ break;
+ }
+*/
+
+schedule:
+ schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval));
+}
+
+int dvb_usb_remote_init(struct dvb_usb_device *d)
+{
+ int i;
+ if (d->props.rc_key_map == NULL)
+ return 0;
+
+ /* Initialise the remote-control structures.*/
+ init_input_dev(&d->rc_input_dev);
+
+ d->rc_input_dev.evbit[0] = BIT(EV_KEY);
+ d->rc_input_dev.keycodesize = sizeof(unsigned char);
+ d->rc_input_dev.keycodemax = KEY_MAX;
+ d->rc_input_dev.name = "IR-receiver inside an USB DVB receiver";
+
+ /* set the bits for the keys */
+ deb_rc("key map size: %d\n",d->props.rc_key_map_size);
+ for (i = 0; i < d->props.rc_key_map_size; i++) {
+ deb_rc("setting bit for event %d item %d\n",d->props.rc_key_map[i].event, i);
+ set_bit(d->props.rc_key_map[i].event, d->rc_input_dev.keybit);
+ }
+
+ /* Start the remote-control polling. */
+ if (d->props.rc_interval < 40)
+ d->props.rc_interval = 100; /* default */
+
+ /* setting these two values to non-zero, we have to manage key repeats */
+ d->rc_input_dev.rep[REP_PERIOD] = d->props.rc_interval;
+ d->rc_input_dev.rep[REP_DELAY] = d->props.rc_interval + 150;
+
+ input_register_device(&d->rc_input_dev);
+
+ INIT_WORK(&d->rc_query_work, dvb_usb_read_remote_control, d);
+
+ info("schedule remote query interval to %d msecs.",d->props.rc_interval);
+ schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval));
+
+ d->state |= DVB_USB_STATE_REMOTE;
+
+ return 0;
+}
+
+int dvb_usb_remote_exit(struct dvb_usb_device *d)
+{
+ if (d->state & DVB_USB_STATE_REMOTE) {
+ cancel_delayed_work(&d->rc_query_work);
+ flush_scheduled_work();
+ input_unregister_device(&d->rc_input_dev);
+ }
+ d->state &= ~DVB_USB_STATE_REMOTE;
+ return 0;
+}
+
+#define DVB_USB_RC_NEC_EMPTY 0x00
+#define DVB_USB_RC_NEC_KEY_PRESSED 0x01
+#define DVB_USB_RC_NEC_KEY_REPEATED 0x02
+int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d,
+ u8 keybuf[5], u32 *event, int *state)
+{
+ int i;
+ struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
+ *event = 0;
+ *state = REMOTE_NO_KEY_PRESSED;
+ switch (keybuf[0]) {
+ case DVB_USB_RC_NEC_EMPTY:
+ break;
+ case DVB_USB_RC_NEC_KEY_PRESSED:
+ if ((u8) ~keybuf[1] != keybuf[2] ||
+ (u8) ~keybuf[3] != keybuf[4]) {
+ deb_err("remote control checksum failed.\n");
+ break;
+ }
+ /* See if we can match the raw key code. */
+ for (i = 0; i < sizeof(keymap)/sizeof(struct dvb_usb_rc_key); i++)
+ if (keymap[i].custom == keybuf[1] &&
+ keymap[i].data == keybuf[3]) {
+ *event = keymap[i].event;
+ *state = REMOTE_KEY_PRESSED;
+ break;
+ }
+ deb_err("key mapping failed - no appropriate key found in keymapping\n");
+ break;
+ case DVB_USB_RC_NEC_KEY_REPEATED:
+ *state = REMOTE_KEY_REPEAT;
+ break;
+ default:
+ deb_err("unkown type of remote status: %d\n",keybuf[0]);
+ break;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(dvb_usb_nec_rc_key_to_event);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
new file mode 100644
index 00000000000..83d476fb410
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
@@ -0,0 +1,211 @@
+/* dvb-usb-urb.c is part of the DVB USB library.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ * see dvb-usb-init.c for copyright information.
+ *
+ * This file contains functions for initializing and handling the
+ * USB and URB stuff.
+ */
+#include "dvb-usb-common.h"
+
+int dvb_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf,
+ u16 rlen, int delay_ms)
+{
+ int actlen,ret = -ENOMEM;
+
+ if (d->props.generic_bulk_ctrl_endpoint == 0) {
+ err("endpoint for generic control not specified.");
+ return -EINVAL;
+ }
+
+ if (wbuf == NULL || wlen == 0)
+ return -EINVAL;
+
+ if ((ret = down_interruptible(&d->usb_sem)))
+ return ret;
+
+ debug_dump(wbuf,wlen,deb_xfer);
+
+ ret = usb_bulk_msg(d->udev,usb_sndbulkpipe(d->udev,
+ d->props.generic_bulk_ctrl_endpoint), wbuf,wlen,&actlen,
+ 2*HZ);
+
+ if (ret)
+ err("bulk message failed: %d (%d/%d)",ret,wlen,actlen);
+ else
+ ret = actlen != wlen ? -1 : 0;
+
+ /* an answer is expected, and no error before */
+ if (!ret && rbuf && rlen) {
+ if (delay_ms)
+ msleep(delay_ms);
+
+ ret = usb_bulk_msg(d->udev,usb_rcvbulkpipe(d->udev,
+ d->props.generic_bulk_ctrl_endpoint),rbuf,rlen,&actlen,
+ 2*HZ);
+
+ if (ret)
+ err("recv bulk message failed: %d",ret);
+ else
+ debug_dump(rbuf,actlen,deb_xfer);
+ }
+
+ up(&d->usb_sem);
+ return ret;
+}
+EXPORT_SYMBOL(dvb_usb_generic_rw);
+
+int dvb_usb_generic_write(struct dvb_usb_device *d, u8 *buf, u16 len)
+{
+ return dvb_usb_generic_rw(d,buf,len,NULL,0,0);
+}
+EXPORT_SYMBOL(dvb_usb_generic_write);
+
+static void dvb_usb_bulk_urb_complete(struct urb *urb, struct pt_regs *ptregs)
+{
+ struct dvb_usb_device *d = urb->context;
+
+ deb_ts("bulk urb completed. feedcount: %d, status: %d, length: %d\n",d->feedcount,urb->status,
+ urb->actual_length);
+
+ switch (urb->status) {
+ case 0: /* success */
+ case -ETIMEDOUT: /* NAK */
+ break;
+ case -ECONNRESET: /* kill */
+ case -ENOENT:
+ case -ESHUTDOWN:
+ return;
+ default: /* error */
+ deb_ts("urb completition error %d.", urb->status);
+ break;
+ }
+
+ if (d->feedcount > 0 && urb->actual_length > 0) {
+ if (d->state & DVB_USB_STATE_DVB)
+ dvb_dmx_swfilter(&d->demux, (u8*) urb->transfer_buffer,urb->actual_length);
+ } else
+ deb_ts("URB dropped because of feedcount.\n");
+
+ usb_submit_urb(urb,GFP_ATOMIC);
+}
+
+int dvb_usb_urb_kill(struct dvb_usb_device *d)
+{
+ int i;
+ for (i = 0; i < d->urbs_submitted; i++) {
+ deb_info("killing URB no. %d.\n",i);
+
+ /* stop the URB */
+ usb_kill_urb(d->urb_list[i]);
+ }
+ d->urbs_submitted = 0;
+ return 0;
+}
+
+int dvb_usb_urb_submit(struct dvb_usb_device *d)
+{
+ int i,ret;
+ for (i = 0; i < d->urbs_initialized; i++) {
+ deb_info("submitting URB no. %d\n",i);
+ if ((ret = usb_submit_urb(d->urb_list[i],GFP_ATOMIC))) {
+ err("could not submit URB no. %d - get them all back\n",i);
+ dvb_usb_urb_kill(d);
+ return ret;
+ }
+ d->urbs_submitted++;
+ }
+ return 0;
+}
+
+static int dvb_usb_bulk_urb_init(struct dvb_usb_device *d)
+{
+ int i,bufsize = d->props.urb.count * d->props.urb.u.bulk.buffersize;
+
+ deb_info("allocate %d bytes as buffersize for all URBs\n",bufsize);
+ /* allocate the actual buffer for the URBs */
+ if ((d->buffer = usb_buffer_alloc(d->udev, bufsize, SLAB_ATOMIC, &d->dma_handle)) == NULL) {
+ deb_info("not enough memory for urb-buffer allocation.\n");
+ return -ENOMEM;
+ }
+ deb_info("allocation successful\n");
+ memset(d->buffer,0,bufsize);
+
+ d->state |= DVB_USB_STATE_URB_BUF;
+
+ /* allocate the URBs */
+ for (i = 0; i < d->props.urb.count; i++) {
+ if (!(d->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC))) {
+ return -ENOMEM;
+ }
+
+ usb_fill_bulk_urb( d->urb_list[i], d->udev,
+ usb_rcvbulkpipe(d->udev,d->props.urb.endpoint),
+ &d->buffer[i*d->props.urb.u.bulk.buffersize],
+ d->props.urb.u.bulk.buffersize,
+ dvb_usb_bulk_urb_complete, d);
+
+ d->urb_list[i]->transfer_flags = 0;
+ d->urbs_initialized++;
+ }
+ return 0;
+}
+
+int dvb_usb_urb_init(struct dvb_usb_device *d)
+{
+ /*
+ * when reloading the driver w/o replugging the device
+ * sometimes a timeout occures, this helps
+ */
+ if (d->props.generic_bulk_ctrl_endpoint != 0) {
+ usb_clear_halt(d->udev,usb_sndbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint));
+ usb_clear_halt(d->udev,usb_rcvbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint));
+ }
+ usb_clear_halt(d->udev,usb_rcvbulkpipe(d->udev,d->props.urb.endpoint));
+
+ /* allocate the array for the data transfer URBs */
+ d->urb_list = kmalloc(d->props.urb.count * sizeof(struct urb *),GFP_KERNEL);
+ if (d->urb_list == NULL)
+ return -ENOMEM;
+ memset(d->urb_list,0,d->props.urb.count * sizeof(struct urb *));
+ d->state |= DVB_USB_STATE_URB_LIST;
+
+ switch (d->props.urb.type) {
+ case DVB_USB_BULK:
+ return dvb_usb_bulk_urb_init(d);
+ case DVB_USB_ISOC:
+ err("isochronous transfer not yet implemented in dvb-usb.");
+ return -EINVAL;
+ default:
+ err("unkown URB-type for data transfer.");
+ return -EINVAL;
+ }
+}
+
+int dvb_usb_urb_exit(struct dvb_usb_device *d)
+{
+ int i;
+
+ dvb_usb_urb_kill(d);
+
+ if (d->state & DVB_USB_STATE_URB_LIST) {
+ for (i = 0; i < d->urbs_initialized; i++) {
+ if (d->urb_list[i] != NULL) {
+ deb_info("freeing URB no. %d.\n",i);
+ /* free the URBs */
+ usb_free_urb(d->urb_list[i]);
+ }
+ }
+ d->urbs_initialized = 0;
+ /* free the urb array */
+ kfree(d->urb_list);
+ d->state &= ~DVB_USB_STATE_URB_LIST;
+ }
+
+ if (d->state & DVB_USB_STATE_URB_BUF)
+ usb_buffer_free(d->udev, d->props.urb.u.bulk.buffersize * d->props.urb.count,
+ d->buffer, d->dma_handle);
+
+ d->state &= ~DVB_USB_STATE_URB_BUF;
+ return 0;
+}
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
new file mode 100644
index 00000000000..abcee1943f6
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -0,0 +1,315 @@
+/* dvb-usb.h is part of the DVB USB library.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ * see dvb-usb-init.c for copyright information.
+ *
+ * the headerfile, all dvb-usb-drivers have to include.
+ */
+#ifndef __DVB_USB_H__
+#define __DVB_USB_H__
+
+#include <linux/config.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#include "dvb_frontend.h"
+#include "dvb_demux.h"
+#include "dvb_net.h"
+#include "dmxdev.h"
+
+#include "dvb-pll.h"
+
+#include "dvb-usb-ids.h"
+
+/* debug */
+#ifdef CONFIG_DVB_USB_DEBUG
+#define dprintk(var,level,args...) \
+ do { if ((var & level)) { printk(args); } } while (0)
+
+#define debug_dump(b,l,func) {\
+ int loop_; \
+ for (loop_ = 0; loop_ < l; loop_++) func("%02x ", b[loop_]); \
+ func("\n");\
+}
+#define DVB_USB_DEBUG_STATUS
+#else
+#define dprintk(args...)
+#define debug_dump(b,l,func)
+
+#define DVB_USB_DEBUG_STATUS " (debugging is not enabled)"
+
+#endif
+
+/* generic log methods - taken from usb.h */
+#ifndef DVB_USB_LOG_PREFIX
+ #define DVB_USB_LOG_PREFIX "dvb-usb (please define a log prefix)"
+#endif
+
+#undef err
+#define err(format, arg...) printk(KERN_ERR DVB_USB_LOG_PREFIX ": " format "\n" , ## arg)
+#undef info
+#define info(format, arg...) printk(KERN_INFO DVB_USB_LOG_PREFIX ": " format "\n" , ## arg)
+#undef warn
+#define warn(format, arg...) printk(KERN_WARNING DVB_USB_LOG_PREFIX ": " format "\n" , ## arg)
+
+/**
+ * struct dvb_usb_device_description - name and its according USB IDs
+ * @name: real name of the box, regardless which DVB USB device class is in use
+ * @cold_ids: array of struct usb_device_id which describe the device in
+ * pre-firmware state
+ * @warm_ids: array of struct usb_device_id which describe the device in
+ * post-firmware state
+ *
+ * Each DVB USB device class can have one or more actual devices, this struct
+ * assigns a name to it.
+ */
+struct dvb_usb_device_description {
+ const char *name;
+
+#define DVB_USB_ID_MAX_NUM 15
+ struct usb_device_id *cold_ids[DVB_USB_ID_MAX_NUM];
+ struct usb_device_id *warm_ids[DVB_USB_ID_MAX_NUM];
+};
+
+/**
+ * struct dvb_usb_rc_key - a remote control key and its input-event
+ * @custom: the vendor/custom part of the key
+ * @data: the actual key part
+ * @event: the input event assigned to key identified by custom and data
+ */
+struct dvb_usb_rc_key {
+ u8 custom,data;
+ u32 event;
+};
+
+struct dvb_usb_device;
+
+/**
+ * struct dvb_usb_properties - properties of a dvb-usb-device
+ * @caps: capabilites of the DVB USB device.
+ * @pid_filter_count: number of PID filter position in the optional hardware
+ * PID-filter.
+ *
+ * @usb_ctrl: which USB device-side controller is in use. Needed for firmware
+ * download.
+ * @firmware: name of the firmware file.
+ *
+ * @size_of_priv: how many bytes shall be allocated for the private field
+ * of struct dvb_usb_device.
+ *
+ * @power_ctrl: called to enable/disable power of the device.
+ * @streaming_crtl: called to start and stop the MPEG2-TS streaming of the
+ * device (not URB submitting/killing).
+ * @pid_filter_ctrl: called to en/disable the PID filter, if any.
+ * @pid_filter: called to set/unset a PID for filtering.
+ *
+ * @read_mac_address: called to read the MAC address of the device.
+ *
+ * @frontend_attach: called to attach the possible frontends (fill fe-field
+ * of struct dvb_usb_device).
+ * @tuner_attach: called to attach the correct tuner and to fill pll_addr,
+ * pll_desc and pll_init_buf of struct dvb_usb_device).
+ * @identify_state: called to determine the state (cold or warm), when it
+ * is not distinguishable by the USB IDs.
+ *
+ * @rc_key_map: a hard-wired array of struct dvb_usb_rc_key (NULL to disable
+ * remote control handling).
+ * @rc_key_map_size: number of items in @rc_key_map.
+ * @rc_query: called to query an event event.
+ * @rc_interval: time in ms between two queries.
+ *
+ * @i2c_algo: i2c_algorithm if the device has I2CoverUSB.
+ *
+ * @generic_bulk_ctrl_endpoint: most of the DVB USB devices have a generic
+ * endpoint which received control messages with bulk transfers. When this
+ * is non-zero, one can use dvb_usb_generic_rw and dvb_usb_generic_write-
+ * helper functions.
+ *
+ * @urb: describes the kind of USB transfer used for MPEG2-TS-streaming.
+ * Currently only BULK is implemented
+ *
+ * @num_device_descs: number of struct dvb_usb_device_description in @devices
+ * @devices: array of struct dvb_usb_device_description compatibles with these
+ * properties.
+ */
+struct dvb_usb_properties {
+
+#define DVB_USB_HAS_PID_FILTER 0x01
+#define DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF 0x02
+#define DVB_USB_NEED_PID_FILTERING 0x04
+#define DVB_USB_IS_AN_I2C_ADAPTER 0x08
+ int caps;
+ int pid_filter_count;
+
+#define CYPRESS_AN2135 0
+#define CYPRESS_AN2235 1
+#define CYPRESS_FX2 2
+ int usb_ctrl;
+ const char *firmware;
+
+ int size_of_priv;
+
+ int (*power_ctrl) (struct dvb_usb_device *, int);
+ int (*streaming_ctrl) (struct dvb_usb_device *, int);
+ int (*pid_filter_ctrl) (struct dvb_usb_device *, int);
+ int (*pid_filter) (struct dvb_usb_device *, int, u16, int);
+
+ int (*read_mac_address) (struct dvb_usb_device *, u8 []);
+ int (*frontend_attach) (struct dvb_usb_device *);
+ int (*tuner_attach) (struct dvb_usb_device *);
+
+ int (*identify_state) (struct usb_device *, struct dvb_usb_properties *,
+ struct dvb_usb_device_description **, int *);
+
+/* remote control properties */
+#define REMOTE_NO_KEY_PRESSED 0x00
+#define REMOTE_KEY_PRESSED 0x01
+#define REMOTE_KEY_REPEAT 0x02
+ struct dvb_usb_rc_key *rc_key_map;
+ int rc_key_map_size;
+ int (*rc_query) (struct dvb_usb_device *, u32 *, int *);
+ int rc_interval;
+
+ struct i2c_algorithm *i2c_algo;
+
+ int generic_bulk_ctrl_endpoint;
+
+ struct {
+#define DVB_USB_BULK 1
+#define DVB_USB_ISOC 2
+ int type;
+ int count;
+ int endpoint;
+
+ union {
+ struct {
+ int buffersize; /* per URB */
+ } bulk;
+ struct {
+ int framesperurb;
+ int framesize;
+ } isoc;
+ } u;
+ } urb;
+
+ int num_device_descs;
+ struct dvb_usb_device_description devices[8];
+};
+
+
+/**
+ * struct dvb_usb_device - object of a DVB USB device
+ * @props: copy of the struct dvb_usb_properties this device belongs to.
+ * @desc: pointer to the device's struct dvb_usb_device_description.
+ * @state: initialization and runtime state of the device.
+ *
+ * @udev: pointer to the device's struct usb_device.
+ * @urb_list: array of dynamically allocated struct urb for the MPEG2-TS-
+ * streaming.
+ * @buffer: buffer used to streaming.
+ * @dma_handle: dma_addr_t for buffer.
+ * @urbs_initialized: number of URBs initialized.
+ * @urbs_submitted: number of URBs submitted.
+ * @feedcount: number of reqested feeds (used for streaming-activation)
+ * @pid_filtering: is hardware pid_filtering used or not.
+ * @usb_sem: semaphore of USB control messages (reading needs two messages)
+ * @i2c_sem: semaphore for i2c-transfers
+ * @i2c_adap: device's i2c_adapter if it uses I2CoverUSB
+ * @pll_addr: I2C address of the tuner for programming
+ * @pll_init: array containing the initialization buffer
+ * @pll_desc: pointer to the appropriate struct dvb_pll_desc
+ * @tuner_pass_ctrl: called to (de)activate tuner passthru of the demod
+ * @dvb_adap: device's dvb_adapter.
+ * @dmxdev: device's dmxdev.
+ * @demux: device's software demuxer.
+ * @dvb_net: device's dvb_net interfaces.
+ * @dvb_frontend: device's frontend.
+ * @max_feed_count: how many feeds can be handled simultaneously by this
+ * device
+ * @fe_sleep: rerouted frontend-sleep function.
+ * @fe_init: rerouted frontend-init (wakeup) function.
+ * @rc_input_dev: input device for the remote control.
+ * @rc_query_work: struct work_struct frequent rc queries
+ * @last_event: last triggered event
+ * @last_state: last state (no, pressed, repeat)
+ * @owner: owner of the dvb_adapter
+ * @priv: private data of the actual driver (allocate by dvb-usb, size defined
+ * in size_of_priv of dvb_usb_properties).
+ */
+struct dvb_usb_device {
+ struct dvb_usb_properties props;
+ struct dvb_usb_device_description *desc;
+
+#define DVB_USB_STATE_INIT 0x000
+#define DVB_USB_STATE_URB_LIST 0x001
+#define DVB_USB_STATE_URB_BUF 0x002
+#define DVB_USB_STATE_DVB 0x004
+#define DVB_USB_STATE_I2C 0x008
+#define DVB_USB_STATE_REMOTE 0x010
+#define DVB_USB_STATE_URB_SUBMIT 0x020
+ int state;
+
+ /* usb */
+ struct usb_device *udev;
+ struct urb **urb_list;
+ u8 *buffer;
+ dma_addr_t dma_handle;
+ int urbs_initialized;
+ int urbs_submitted;
+
+ int feedcount;
+ int pid_filtering;
+
+ /* locking */
+ struct semaphore usb_sem;
+
+ /* i2c */
+ struct semaphore i2c_sem;
+ struct i2c_adapter i2c_adap;
+
+ /* tuner programming information */
+ u8 pll_addr;
+ u8 pll_init[4];
+ struct dvb_pll_desc *pll_desc;
+ int (*tuner_pass_ctrl)(struct dvb_frontend *, int, u8);
+
+ /* dvb */
+ struct dvb_adapter dvb_adap;
+ struct dmxdev dmxdev;
+ struct dvb_demux demux;
+ struct dvb_net dvb_net;
+ struct dvb_frontend* fe;
+ int max_feed_count;
+
+ int (*fe_sleep) (struct dvb_frontend *);
+ int (*fe_init) (struct dvb_frontend *);
+
+ /* remote control */
+ struct input_dev rc_input_dev;
+ struct work_struct rc_query_work;
+ u32 last_event;
+ int last_state;
+
+ struct module *owner;
+
+ void *priv;
+};
+
+extern int dvb_usb_device_init(struct usb_interface *, struct dvb_usb_properties *, struct module *);
+extern void dvb_usb_device_exit(struct usb_interface *);
+
+/* the generic read/write method for device control */
+extern int dvb_usb_generic_rw(struct dvb_usb_device *, u8 *, u16, u8 *, u16,int);
+extern int dvb_usb_generic_write(struct dvb_usb_device *, u8 *, u16);
+
+/* commonly used remote control parsing */
+extern int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *, u8[], u32 *, int *);
+
+/* commonly used pll init and set functions */
+extern int dvb_usb_pll_init_i2c(struct dvb_frontend *);
+extern int dvb_usb_pll_set(struct dvb_frontend *, struct dvb_frontend_parameters *, u8[]);
+extern int dvb_usb_pll_set_i2c(struct dvb_frontend *, struct dvb_frontend_parameters *);
+
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
new file mode 100644
index 00000000000..9d83781aef9
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
@@ -0,0 +1,236 @@
+/* DVB USB framework compliant Linux driver for the Hauppauge WinTV-NOVA-T usb2
+ * DVB-T receiver.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * 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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "dibusb.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=rc,2=eeprom (|-able))." DVB_USB_DEBUG_STATUS);
+
+#define deb_rc(args...) dprintk(debug,0x01,args)
+#define deb_ee(args...) dprintk(debug,0x02,args)
+
+/* Hauppauge NOVA-T USB2 keys */
+static struct dvb_usb_rc_key haupp_rc_keys [] = {
+ { 0x1e, 0x00, KEY_0 },
+ { 0x1e, 0x01, KEY_1 },
+ { 0x1e, 0x02, KEY_2 },
+ { 0x1e, 0x03, KEY_3 },
+ { 0x1e, 0x04, KEY_4 },
+ { 0x1e, 0x05, KEY_5 },
+ { 0x1e, 0x06, KEY_6 },
+ { 0x1e, 0x07, KEY_7 },
+ { 0x1e, 0x08, KEY_8 },
+ { 0x1e, 0x09, KEY_9 },
+ { 0x1e, 0x0a, KEY_KPASTERISK },
+ { 0x1e, 0x0b, KEY_RED },
+ { 0x1e, 0x0c, KEY_RADIO },
+ { 0x1e, 0x0d, KEY_MENU },
+ { 0x1e, 0x0e, KEY_GRAVE }, /* # */
+ { 0x1e, 0x0f, KEY_MUTE },
+ { 0x1e, 0x10, KEY_VOLUMEUP },
+ { 0x1e, 0x11, KEY_VOLUMEDOWN },
+ { 0x1e, 0x12, KEY_CHANNEL },
+ { 0x1e, 0x14, KEY_UP },
+ { 0x1e, 0x15, KEY_DOWN },
+ { 0x1e, 0x16, KEY_LEFT },
+ { 0x1e, 0x17, KEY_RIGHT },
+ { 0x1e, 0x18, KEY_VIDEO },
+ { 0x1e, 0x19, KEY_AUDIO },
+ { 0x1e, 0x1a, KEY_MEDIA },
+ { 0x1e, 0x1b, KEY_EPG },
+ { 0x1e, 0x1c, KEY_TV },
+ { 0x1e, 0x1e, KEY_NEXT },
+ { 0x1e, 0x1f, KEY_BACK },
+ { 0x1e, 0x20, KEY_CHANNELUP },
+ { 0x1e, 0x21, KEY_CHANNELDOWN },
+ { 0x1e, 0x24, KEY_LAST }, /* Skip backwards */
+ { 0x1e, 0x25, KEY_OK },
+ { 0x1e, 0x29, KEY_BLUE},
+ { 0x1e, 0x2e, KEY_GREEN },
+ { 0x1e, 0x30, KEY_PAUSE },
+ { 0x1e, 0x32, KEY_REWIND },
+ { 0x1e, 0x34, KEY_FASTFORWARD },
+ { 0x1e, 0x35, KEY_PLAY },
+ { 0x1e, 0x36, KEY_STOP },
+ { 0x1e, 0x37, KEY_RECORD },
+ { 0x1e, 0x38, KEY_YELLOW },
+ { 0x1e, 0x3b, KEY_GOTO },
+ { 0x1e, 0x3d, KEY_POWER },
+};
+
+/* Firmware bug? sometimes, when a new key is pressed, the previous pressed key
+ * is delivered. No workaround yet, maybe a new firmware.
+ */
+static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+ u8 key[5],cmd[2] = { DIBUSB_REQ_POLL_REMOTE, 0x35 }, data,toggle,custom;
+ u16 raw;
+ int i;
+ struct dibusb_state *st = d->priv;
+
+ dvb_usb_generic_rw(d,cmd,2,key,5,0);
+
+ *state = REMOTE_NO_KEY_PRESSED;
+ switch (key[0]) {
+ case DIBUSB_RC_HAUPPAUGE_KEY_PRESSED:
+ raw = ((key[1] << 8) | key[2]) >> 3;
+ toggle = !!(raw & 0x800);
+ data = raw & 0x3f;
+ custom = (raw >> 6) & 0x1f;
+
+ deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to c: %02x d: %02x toggle: %d\n",key[1],key[2],key[3],custom,data,toggle);
+
+ for (i = 0; i < ARRAY_SIZE(haupp_rc_keys); i++) {
+ deb_rc("c: %x, d: %x\n",haupp_rc_keys[i].data,haupp_rc_keys[i].custom);
+ if (haupp_rc_keys[i].data == data &&
+ haupp_rc_keys[i].custom == custom) {
+ *event = haupp_rc_keys[i].event;
+ *state = REMOTE_KEY_PRESSED;
+ if (st->old_toggle == toggle) {
+ if (st->last_repeat_count++ < 2)
+ *state = REMOTE_NO_KEY_PRESSED;
+ } else {
+ st->last_repeat_count = 0;
+ st->old_toggle = toggle;
+ }
+ break;
+ }
+ }
+
+ break;
+ case DIBUSB_RC_HAUPPAUGE_KEY_EMPTY:
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6])
+{
+ int i;
+ u8 b;
+
+ mac[0] = 0x00;
+ mac[1] = 0x0d;
+ mac[2] = 0xfe;
+
+ /* this is a complete guess, but works for my box */
+ for (i = 136; i < 139; i++) {
+ dibusb_read_eeprom_byte(d,i, &b);
+
+ mac[5 - (i - 136)] = b;
+
+/* deb_ee("%02x ",b);
+ if ((i+1) % 16 == 0)
+ deb_ee("\n");*/
+ }
+
+ return 0;
+}
+
+/* USB Driver stuff */
+static struct dvb_usb_properties nova_t_properties;
+
+static int nova_t_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return dvb_usb_device_init(intf,&nova_t_properties,THIS_MODULE);
+}
+
+/* do not change the order of the ID table */
+static struct usb_device_id nova_t_table [] = {
+/* 00 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_COLD) },
+/* 01 */ { USB_DEVICE(USB_VID_HAUPPAUGE, USB_PID_WINTV_NOVA_T_USB2_WARM) },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, nova_t_table);
+
+static struct dvb_usb_properties nova_t_properties = {
+ .caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
+ .pid_filter_count = 32,
+
+ .usb_ctrl = CYPRESS_FX2,
+ .firmware = "dvb-usb-nova-t-usb2-01.fw",
+
+ .size_of_priv = sizeof(struct dibusb_state),
+
+ .streaming_ctrl = dibusb2_0_streaming_ctrl,
+ .pid_filter = dibusb_pid_filter,
+ .pid_filter_ctrl = dibusb_pid_filter_ctrl,
+ .power_ctrl = dibusb2_0_power_ctrl,
+ .frontend_attach = dibusb_dib3000mc_frontend_attach,
+ .tuner_attach = dibusb_dib3000mc_tuner_attach,
+ .read_mac_address = nova_t_read_mac_address,
+
+ .rc_interval = 100,
+ .rc_key_map = haupp_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(haupp_rc_keys),
+ .rc_query = nova_t_rc_query,
+
+ .i2c_algo = &dibusb_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+ /* parameter for the MPEG2-data transfer */
+ .urb = {
+ .type = DVB_USB_BULK,
+ .count = 7,
+ .endpoint = 0x06,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
+
+ .num_device_descs = 1,
+ .devices = {
+ { "Hauppauge WinTV-NOVA-T usb2",
+ { &nova_t_table[0], NULL },
+ { &nova_t_table[1], NULL },
+ },
+ }
+};
+
+static struct usb_driver nova_t_driver = {
+ .owner = THIS_MODULE,
+ .name = "Hauppauge WinTV-NOVA-T usb2",
+ .probe = nova_t_probe,
+ .disconnect = dvb_usb_device_exit,
+ .id_table = nova_t_table,
+};
+
+/* module stuff */
+static int __init nova_t_module_init(void)
+{
+ int result;
+ if ((result = usb_register(&nova_t_driver))) {
+ err("usb_register failed. Error number %d",result);
+ return result;
+ }
+
+ return 0;
+}
+
+static void __exit nova_t_module_exit(void)
+{
+ /* deregister this driver from the USB subsystem */
+ usb_deregister(&nova_t_driver);
+}
+
+module_init (nova_t_module_init);
+module_exit (nova_t_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("Hauppauge WinTV-NOVA-T usb2");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c
new file mode 100644
index 00000000000..aa560422ce7
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/umt-010.c
@@ -0,0 +1,162 @@
+/* DVB USB framework compliant Linux driver for the HanfTek UMT-010 USB2.0
+ * DVB-T receiver.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * 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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "dibusb.h"
+
+#include "mt352.h"
+
+static int umt_mt352_demod_init(struct dvb_frontend *fe)
+{
+ static u8 mt352_clock_config[] = { 0x89, 0xb8, 0x2d };
+ static u8 mt352_reset[] = { 0x50, 0x80 };
+ static u8 mt352_mclk_ratio[] = { 0x8b, 0x00 };
+ static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 };
+ static u8 mt352_agc_cfg[] = { 0x67, 0x10, 0xa0 };
+
+ static u8 mt352_sec_agc_cfg1[] = { 0x6a, 0xff };
+ static u8 mt352_sec_agc_cfg2[] = { 0x6d, 0xff };
+ static u8 mt352_sec_agc_cfg3[] = { 0x70, 0x40 };
+ static u8 mt352_sec_agc_cfg4[] = { 0x7b, 0x03 };
+ static u8 mt352_sec_agc_cfg5[] = { 0x7d, 0x0f };
+
+ static u8 mt352_acq_ctl[] = { 0x53, 0x50 };
+ static u8 mt352_input_freq_1[] = { 0x56, 0x31, 0x06 };
+
+ mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
+ udelay(2000);
+ mt352_write(fe, mt352_reset, sizeof(mt352_reset));
+ mt352_write(fe, mt352_mclk_ratio, sizeof(mt352_mclk_ratio));
+
+ mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
+ mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
+
+ mt352_write(fe, mt352_sec_agc_cfg1, sizeof(mt352_sec_agc_cfg1));
+ mt352_write(fe, mt352_sec_agc_cfg2, sizeof(mt352_sec_agc_cfg2));
+ mt352_write(fe, mt352_sec_agc_cfg3, sizeof(mt352_sec_agc_cfg3));
+ mt352_write(fe, mt352_sec_agc_cfg4, sizeof(mt352_sec_agc_cfg4));
+ mt352_write(fe, mt352_sec_agc_cfg5, sizeof(mt352_sec_agc_cfg5));
+
+ mt352_write(fe, mt352_acq_ctl, sizeof(mt352_acq_ctl));
+ mt352_write(fe, mt352_input_freq_1, sizeof(mt352_input_freq_1));
+
+ return 0;
+}
+
+static int umt_mt352_frontend_attach(struct dvb_usb_device *d)
+{
+ struct mt352_config umt_config;
+
+ memset(&umt_config,0,sizeof(struct mt352_config));
+ umt_config.demod_init = umt_mt352_demod_init;
+ umt_config.demod_address = 0xf;
+ umt_config.pll_set = dvb_usb_pll_set;
+
+ d->fe = mt352_attach(&umt_config, &d->i2c_adap);
+
+ return 0;
+}
+
+static int umt_tuner_attach (struct dvb_usb_device *d)
+{
+ d->pll_addr = 0x61;
+ d->pll_desc = &dvb_pll_tua6034;
+ return 0;
+}
+
+/* USB Driver stuff */
+static struct dvb_usb_properties umt_properties;
+
+static int umt_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ if (dvb_usb_device_init(intf,&umt_properties,THIS_MODULE) == 0)
+ return 0;
+ return -EINVAL;
+}
+
+/* do not change the order of the ID table */
+static struct usb_device_id umt_table [] = {
+/* 00 */ { USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_COLD) },
+/* 01 */ { USB_DEVICE(USB_VID_HANFTEK, USB_PID_HANFTEK_UMT_010_WARM) },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, umt_table);
+
+static struct dvb_usb_properties umt_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = CYPRESS_FX2,
+ .firmware = "dvb-usb-umt-010-02.fw",
+
+ .size_of_priv = sizeof(struct dibusb_state),
+
+ .streaming_ctrl = dibusb2_0_streaming_ctrl,
+ .power_ctrl = dibusb_power_ctrl,
+ .frontend_attach = umt_mt352_frontend_attach,
+ .tuner_attach = umt_tuner_attach,
+
+ .i2c_algo = &dibusb_i2c_algo,
+
+ .generic_bulk_ctrl_endpoint = 0x01,
+ /* parameter for the MPEG2-data transfer */
+ .urb = {
+ .type = DVB_USB_BULK,
+ .count = 20,
+ .endpoint = 0x06,
+ .u = {
+ .bulk = {
+ .buffersize = 512,
+ }
+ }
+ },
+
+ .num_device_descs = 1,
+ .devices = {
+ { "Hanftek UMT-010 DVB-T USB2.0",
+ { &umt_table[0], NULL },
+ { &umt_table[1], NULL },
+ },
+ }
+};
+
+static struct usb_driver umt_driver = {
+ .owner = THIS_MODULE,
+ .name = "HanfTek UMT-010 USB2.0 DVB-T devices",
+ .probe = umt_probe,
+ .disconnect = dvb_usb_device_exit,
+ .id_table = umt_table,
+};
+
+/* module stuff */
+static int __init umt_module_init(void)
+{
+ int result;
+ if ((result = usb_register(&umt_driver))) {
+ err("usb_register failed. Error number %d",result);
+ return result;
+ }
+
+ return 0;
+}
+
+static void __exit umt_module_exit(void)
+{
+ /* deregister this driver from the USB subsystem */
+ usb_deregister(&umt_driver);
+}
+
+module_init (umt_module_init);
+module_exit (umt_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("Driver for HanfTek UMT 010 USB2.0 DVB-T device");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/vp7045-fe.c b/drivers/media/dvb/dvb-usb/vp7045-fe.c
new file mode 100644
index 00000000000..2746edfeccb
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/vp7045-fe.c
@@ -0,0 +1,196 @@
+/* DVB frontend part of the Linux driver for TwinhanDTV Alpha/MagicBoxII USB2.0
+ * DVB-T receiver.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * Thanks to Twinhan who kindly provided hardware and information.
+ *
+ * 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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ *
+ */
+#include "vp7045.h"
+
+/* It is a Zarlink MT352 within a Samsung Tuner (DNOS404ZH102A) - 040929 - AAT
+ *
+ * Programming is hidden inside the firmware, so set_frontend is very easy.
+ * Even though there is a Firmware command that one can use to access the demod
+ * via its registers. This is used for status information.
+ */
+
+struct vp7045_fe_state {
+ struct dvb_frontend fe;
+ struct dvb_usb_device *d;
+};
+
+
+static int vp7045_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
+{
+ struct vp7045_fe_state *state = fe->demodulator_priv;
+ u8 s0 = vp7045_read_reg(state->d,0x00),
+ s1 = vp7045_read_reg(state->d,0x01),
+ s3 = vp7045_read_reg(state->d,0x03);
+
+ *status = 0;
+ if (s0 & (1 << 4))
+ *status |= FE_HAS_CARRIER;
+ if (s0 & (1 << 1))
+ *status |= FE_HAS_VITERBI;
+ if (s0 & (1 << 5))
+ *status |= FE_HAS_LOCK;
+ if (s1 & (1 << 1))
+ *status |= FE_HAS_SYNC;
+ if (s3 & (1 << 6))
+ *status |= FE_HAS_SIGNAL;
+
+ if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) !=
+ (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC))
+ *status &= ~FE_HAS_LOCK;
+
+ return 0;
+}
+
+static int vp7045_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
+{
+ struct vp7045_fe_state *state = fe->demodulator_priv;
+ *ber = (vp7045_read_reg(state->d, 0x0D) << 16) |
+ (vp7045_read_reg(state->d, 0x0E) << 8) |
+ vp7045_read_reg(state->d, 0x0F);
+ return 0;
+}
+
+static int vp7045_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
+{
+ struct vp7045_fe_state *state = fe->demodulator_priv;
+ *unc = (vp7045_read_reg(state->d, 0x10) << 8) |
+ vp7045_read_reg(state->d, 0x11);
+ return 0;
+}
+
+static int vp7045_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
+{
+ struct vp7045_fe_state *state = fe->demodulator_priv;
+ u16 signal = (vp7045_read_reg(state->d, 0x14) << 8) |
+ vp7045_read_reg(state->d, 0x15);
+
+ *strength = ~signal;
+ return 0;
+}
+
+static int vp7045_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
+{
+ struct vp7045_fe_state *state = fe->demodulator_priv;
+ u8 _snr = vp7045_read_reg(state->d, 0x09);
+ *snr = (_snr << 8) | _snr;
+ return 0;
+}
+
+static int vp7045_fe_init(struct dvb_frontend* fe)
+{
+ return 0;
+}
+
+static int vp7045_fe_sleep(struct dvb_frontend* fe)
+{
+ return 0;
+}
+
+static int vp7045_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+{
+ tune->min_delay_ms = 800;
+ return 0;
+}
+
+static int vp7045_fe_set_frontend(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *fep)
+{
+ struct vp7045_fe_state *state = fe->demodulator_priv;
+ u8 buf[5];
+ u32 freq = fep->frequency / 1000;
+
+ buf[0] = (freq >> 16) & 0xff;
+ buf[1] = (freq >> 8) & 0xff;
+ buf[2] = freq & 0xff;
+ buf[3] = 0;
+
+ switch (fep->u.ofdm.bandwidth) {
+ case BANDWIDTH_8_MHZ: buf[4] = 8; break;
+ case BANDWIDTH_7_MHZ: buf[4] = 7; break;
+ case BANDWIDTH_6_MHZ: buf[4] = 6; break;
+ case BANDWIDTH_AUTO: return -EOPNOTSUPP;
+ default:
+ return -EINVAL;
+ }
+
+ vp7045_usb_op(state->d,LOCK_TUNER_COMMAND,buf,5,NULL,0,200);
+ return 0;
+}
+
+static int vp7045_fe_get_frontend(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *fep)
+{
+ return 0;
+}
+
+static void vp7045_fe_release(struct dvb_frontend* fe)
+{
+ struct vp7045_fe_state *state = fe->demodulator_priv;
+ kfree(state);
+}
+
+static struct dvb_frontend_ops vp7045_fe_ops;
+
+struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d)
+{
+ struct vp7045_fe_state *s = kmalloc(sizeof(struct vp7045_fe_state), GFP_KERNEL);
+ if (s == NULL)
+ goto error;
+ memset(s,0,sizeof(struct vp7045_fe_state));
+
+ s->d = d;
+ s->fe.ops = &vp7045_fe_ops;
+ s->fe.demodulator_priv = s;
+
+ goto success;
+error:
+ return NULL;
+success:
+ return &s->fe;
+}
+
+
+static struct dvb_frontend_ops vp7045_fe_ops = {
+ .info = {
+ .name = "Twinhan VP7045/46 USB DVB-T",
+ .type = FE_OFDM,
+ .frequency_min = 44250000,
+ .frequency_max = 867250000,
+ .frequency_stepsize = 1000,
+ .caps = FE_CAN_INVERSION_AUTO |
+ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+ FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+ FE_CAN_TRANSMISSION_MODE_AUTO |
+ FE_CAN_GUARD_INTERVAL_AUTO |
+ FE_CAN_RECOVER |
+ FE_CAN_HIERARCHY_AUTO,
+ },
+
+ .release = vp7045_fe_release,
+
+ .init = vp7045_fe_init,
+ .sleep = vp7045_fe_sleep,
+
+ .set_frontend = vp7045_fe_set_frontend,
+ .get_frontend = vp7045_fe_get_frontend,
+ .get_tune_settings = vp7045_fe_get_tune_settings,
+
+ .read_status = vp7045_fe_read_status,
+ .read_ber = vp7045_fe_read_ber,
+ .read_signal_strength = vp7045_fe_read_signal_strength,
+ .read_snr = vp7045_fe_read_snr,
+ .read_ucblocks = vp7045_fe_read_unc_blocks,
+};
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c
new file mode 100644
index 00000000000..02ecc9a8e3b
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/vp7045.c
@@ -0,0 +1,263 @@
+/* DVB USB compliant Linux driver for the
+ * - TwinhanDTV Alpha/MagicBoxII USB2.0 DVB-T receiver
+ * - DigitalNow TinyUSB2 DVB-t receiver
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * Thanks to Twinhan who kindly provided hardware and information.
+ *
+ * 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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "vp7045.h"
+
+/* debug */
+int dvb_usb_vp7045_debug;
+module_param_named(debug,dvb_usb_vp7045_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
+
+int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen, int msec)
+{
+ int ret = 0;
+ u8 inbuf[12] = { 0 }, outbuf[20] = { 0 };
+
+ outbuf[0] = cmd;
+
+ if (outlen > 19)
+ outlen = 19;
+
+ if (inlen > 11)
+ inlen = 11;
+
+ if (out != NULL && outlen > 0)
+ memcpy(&outbuf[1], out, outlen);
+
+ deb_xfer("out buffer: ");
+ debug_dump(outbuf,outlen+1,deb_xfer);
+
+ if ((ret = down_interruptible(&d->usb_sem)))
+ return ret;
+
+ if (usb_control_msg(d->udev,
+ usb_sndctrlpipe(d->udev,0),
+ TH_COMMAND_OUT, USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0,
+ outbuf, 20, 2*HZ) != 20) {
+ err("USB control message 'out' went wrong.");
+ ret = -EIO;
+ goto unlock;
+ }
+
+ msleep(msec);
+
+ if (usb_control_msg(d->udev,
+ usb_rcvctrlpipe(d->udev,0),
+ TH_COMMAND_IN, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
+ inbuf, 12, 2*HZ) != 12) {
+ err("USB control message 'in' went wrong.");
+ ret = -EIO;
+ goto unlock;
+ }
+
+ deb_xfer("in buffer: ");
+ debug_dump(inbuf,12,deb_xfer);
+
+ if (in != NULL && inlen > 0)
+ memcpy(in,&inbuf[1],inlen);
+
+unlock:
+ up(&d->usb_sem);
+
+ return ret;
+}
+
+u8 vp7045_read_reg(struct dvb_usb_device *d, u8 reg)
+{
+ u8 obuf[2] = { 0 },v;
+ obuf[1] = reg;
+
+ vp7045_usb_op(d,TUNER_REG_READ,obuf,2,&v,1,30);
+
+ return v;
+}
+
+static int vp7045_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+ u8 v = onoff;
+ return vp7045_usb_op(d,SET_TUNER_POWER,&v,1,NULL,0,150);
+}
+
+/* remote control stuff */
+
+/* The keymapping struct. Somehow this should be loaded to the driver, but
+ * currently it is hardcoded. */
+static struct dvb_usb_rc_key vp7045_rc_keys[] = {
+ /* insert the keys like this. to make the raw keys visible, enable
+ * debug=0x04 when loading dvb-usb-vp7045. */
+
+ /* these keys are probably wrong. I don't have a working IR-receiver on my
+ * vp7045, so I can't test it. Patches are welcome. */
+ { 0x00, 0x01, KEY_1 },
+ { 0x00, 0x02, KEY_2 },
+};
+
+static int vp7045_rc_query(struct dvb_usb_device *d, u32 *key_buf, int *state)
+{
+ u8 key;
+ int i;
+ vp7045_usb_op(d,RC_VAL_READ,NULL,0,&key,1,20);
+
+ deb_rc("remote query key: %x %d\n",key,key);
+
+ if (key == 0x44) {
+ *state = REMOTE_NO_KEY_PRESSED;
+ return 0;
+ }
+
+ for (i = 0; i < sizeof(vp7045_rc_keys)/sizeof(struct dvb_usb_rc_key); i++)
+ if (vp7045_rc_keys[i].data == key) {
+ *state = REMOTE_KEY_PRESSED;
+ *key_buf = vp7045_rc_keys[i].event;
+ break;
+ }
+ return 0;
+}
+
+static int vp7045_read_eeprom(struct dvb_usb_device *d,u8 *buf, int len, int offset)
+{
+ int i = 0;
+ u8 v,br[2];
+ for (i=0; i < len; i++) {
+ v = offset + i;
+ vp7045_usb_op(d,GET_EE_VALUE,&v,1,br,2,5);
+ buf[i] = br[1];
+ }
+ deb_info("VP7045 EEPROM read (offs: %d, len: %d) : ",offset, i);
+ debug_dump(buf,i,deb_info);
+ return 0;
+}
+
+
+static int vp7045_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
+{
+ return vp7045_read_eeprom(d,mac, 6, MAC_0_ADDR);
+}
+
+static int vp7045_frontend_attach(struct dvb_usb_device *d)
+{
+ u8 buf[255] = { 0 };
+
+ vp7045_usb_op(d,VENDOR_STRING_READ,NULL,0,buf,20,0);
+ buf[10] = '\0';
+ deb_info("firmware says: %s ",buf);
+
+ vp7045_usb_op(d,PRODUCT_STRING_READ,NULL,0,buf,20,0);
+ buf[10] = '\0';
+ deb_info("%s ",buf);
+
+ vp7045_usb_op(d,FW_VERSION_READ,NULL,0,buf,20,0);
+ buf[10] = '\0';
+ deb_info("v%s\n",buf);
+
+/* Dump the EEPROM */
+/* vp7045_read_eeprom(d,buf, 255, FX2_ID_ADDR); */
+
+ d->fe = vp7045_fe_attach(d);
+
+ return 0;
+}
+
+static struct dvb_usb_properties vp7045_properties;
+
+static int vp7045_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ return dvb_usb_device_init(intf,&vp7045_properties,THIS_MODULE);
+}
+
+static struct usb_device_id vp7045_usb_table [] = {
+ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7045_COLD) },
+ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7045_WARM) },
+ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_DNTV_TINYUSB2_COLD) },
+ { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_DNTV_TINYUSB2_WARM) },
+ { 0 },
+};
+MODULE_DEVICE_TABLE(usb, vp7045_usb_table);
+
+static struct dvb_usb_properties vp7045_properties = {
+ .caps = 0,
+
+ .usb_ctrl = CYPRESS_FX2,
+ .firmware = "dvb-usb-vp7045-01.fw",
+
+ .power_ctrl = vp7045_power_ctrl,
+ .frontend_attach = vp7045_frontend_attach,
+ .read_mac_address = vp7045_read_mac_addr,
+
+ .rc_interval = 400,
+ .rc_key_map = vp7045_rc_keys,
+ .rc_key_map_size = ARRAY_SIZE(vp7045_rc_keys),
+ .rc_query = vp7045_rc_query,
+
+ /* parameter for the MPEG2-data transfer */
+ .urb = {
+ .type = DVB_USB_BULK,
+ .count = 7,
+ .endpoint = 0x02,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
+
+ .num_device_descs = 2,
+ .devices = {
+ { .name = "Twinhan USB2.0 DVB-T receiver (TwinhanDTV Alpha/MagicBox II)",
+ .cold_ids = { &vp7045_usb_table[0], NULL },
+ .warm_ids = { &vp7045_usb_table[1], NULL },
+ },
+ { .name = "DigitalNow TinyUSB 2 DVB-t Receiver",
+ .cold_ids = { &vp7045_usb_table[2], NULL },
+ .warm_ids = { &vp7045_usb_table[3], NULL },
+ },
+ { 0 },
+ }
+};
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver vp7045_usb_driver = {
+ .owner = THIS_MODULE,
+ .name = "dvb-usb-vp7045",
+ .probe = vp7045_usb_probe,
+ .disconnect = dvb_usb_device_exit,
+ .id_table = vp7045_usb_table,
+};
+
+/* module stuff */
+static int __init vp7045_usb_module_init(void)
+{
+ int result;
+ if ((result = usb_register(&vp7045_usb_driver))) {
+ err("usb_register failed. (%d)",result);
+ return result;
+ }
+
+ return 0;
+}
+
+static void __exit vp7045_usb_module_exit(void)
+{
+ /* deregister this driver from the USB subsystem */
+ usb_deregister(&vp7045_usb_driver);
+}
+
+module_init(vp7045_usb_module_init);
+module_exit(vp7045_usb_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("Driver for Twinhan MagicBox/Alpha and DNTV tinyUSB2 DVB-T USB2.0");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/vp7045.h b/drivers/media/dvb/dvb-usb/vp7045.h
new file mode 100644
index 00000000000..9ce21a20fa8
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/vp7045.h
@@ -0,0 +1,78 @@
+/* Common header-file of the Linux driver for the TwinhanDTV Alpha/MagicBoxII
+ * USB2.0 DVB-T receiver.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * Thanks to Twinhan who kindly provided hardware and information.
+ *
+ * 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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#ifndef _DVB_USB_VP7045_H_
+#define _DVB_USB_VP7045_H_
+
+#define DVB_USB_LOG_PREFIX "vp7045"
+#include "dvb-usb.h"
+
+extern int dvb_usb_vp7045_debug;
+#define deb_info(args...) dprintk(dvb_usb_vp7045_debug,0x01,args)
+#define deb_xfer(args...) dprintk(dvb_usb_vp7045_debug,0x02,args)
+#define deb_rc(args...) dprintk(dvb_usb_vp7045_debug,0x04,args)
+
+/* vp7045 commands */
+
+/* Twinhan Vendor requests */
+#define TH_COMMAND_IN 0xC0
+#define TH_COMMAND_OUT 0xC1
+
+/* command bytes */
+#define TUNER_REG_READ 0x03
+#define TUNER_REG_WRITE 0x04
+
+#define RC_VAL_READ 0x05
+ #define RC_NO_KEY 0x44
+
+#define SET_TUNER_POWER 0x06
+#define CHECK_TUNER_POWER 0x12
+ #define Tuner_Power_ON 1
+ #define Tuner_Power_OFF 0
+
+#define GET_USB_SPEED 0x07
+ #define USB_SPEED_LOW 0
+ #define USB_SPEED_FULL 1
+ #define USB_SPEED_HIGH 2
+
+#define LOCK_TUNER_COMMAND 0x09
+
+#define TUNER_SIGNAL_READ 0x0A
+
+/* FX2 eeprom */
+#define SET_EE_VALUE 0x10
+#define GET_EE_VALUE 0x11
+ #define FX2_ID_ADDR 0x00
+ #define VID_MSB_ADDR 0x02
+ #define VID_LSB_ADDR 0x01
+ #define PID_MSB_ADDR 0x04
+ #define PID_LSB_ADDR 0x03
+ #define MAC_0_ADDR 0x07
+ #define MAC_1_ADDR 0x08
+ #define MAC_2_ADDR 0x09
+ #define MAC_3_ADDR 0x0a
+ #define MAC_4_ADDR 0x0b
+ #define MAC_5_ADDR 0x0c
+
+#define RESET_FX2 0x13
+
+#define FW_VERSION_READ 0x0B
+#define VENDOR_STRING_READ 0x0C
+#define PRODUCT_STRING_READ 0x0D
+#define FW_BCD_VERSION_READ 0x14
+
+extern struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d);
+extern int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen,int msec);
+extern u8 vp7045_read_reg(struct dvb_usb_device *d, u8 reg);
+
+#endif
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 0bfd4df17d0..b4fddf513eb 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -12,10 +12,10 @@ config DVB_STV0299
config DVB_CX24110
tristate "Conexant CX24110 based"
- depends on DVB_CORE
- help
+ depends on DVB_CORE
+ help
A DVB-S tuner module. Say Y when you want to support this frontend.
-
+
config DVB_TDA8083
tristate "Philips TDA8083 based"
depends on DVB_CORE
@@ -127,8 +127,8 @@ comment "DVB-C (cable) frontends"
config DVB_ATMEL_AT76C651
tristate "Atmel AT76C651 based"
depends on DVB_CORE
- help
- A DVB-C tuner module. Say Y when you want to support this frontend.
+ help
+ A DVB-C tuner module. Say Y when you want to support this frontend.
config DVB_VES1820
tristate "VLSI VES1820 based"
@@ -158,10 +158,6 @@ config DVB_NXT2002
help
An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
-config DVB_OR51132
- tristate "OR51132 based (pcHDTV)"
- depends on DVB_CORE
-
config DVB_OR51211
tristate "or51211 based (pcHDTV HD2000 card)"
depends on DVB_CORE
@@ -169,4 +165,20 @@ config DVB_OR51211
help
An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
+config DVB_OR51132
+ tristate "OR51132 based (pcHDTV HD3000 card)"
+ depends on DVB_CORE
+ select FW_LOADER
+ help
+ An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
+ to support this frontend.
+
+config DVB_BCM3510
+ tristate "Broadcom BCM3510"
+ depends on DVB_CORE
+ select FW_LOADER
+ help
+ An ATSC 8VSB/16VSB and QAM64/256 tuner module. Say Y when you want to
+ support this frontend.
+
endmenu
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index 7f8784870ea..91d6d3576d3 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -28,3 +28,4 @@ obj-$(CONFIG_DVB_STV0297) += stv0297.o
obj-$(CONFIG_DVB_NXT2002) += nxt2002.o
obj-$(CONFIG_DVB_OR51211) += or51211.o
obj-$(CONFIG_DVB_OR51132) += or51132.o
+obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
diff --git a/drivers/media/dvb/frontends/at76c651.c b/drivers/media/dvb/frontends/at76c651.c
index ce2eaa1640e..72a2b5455b0 100644
--- a/drivers/media/dvb/frontends/at76c651.c
+++ b/drivers/media/dvb/frontends/at76c651.c
@@ -259,7 +259,7 @@ static int at76c651_set_parameters(struct dvb_frontend* fe,
struct dvb_frontend_parameters *p)
{
int ret;
- struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv;
+ struct at76c651_state* state = fe->demodulator_priv;
at76c651_writereg(state, 0x0c, 0xc3);
state->config->pll_set(fe, p);
@@ -276,7 +276,7 @@ static int at76c651_set_parameters(struct dvb_frontend* fe,
static int at76c651_set_defaults(struct dvb_frontend* fe)
{
- struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv;
+ struct at76c651_state* state = fe->demodulator_priv;
at76c651_set_symbol_rate(state, 6900000);
at76c651_set_qam(state, QAM_64);
@@ -294,7 +294,7 @@ static int at76c651_set_defaults(struct dvb_frontend* fe)
static int at76c651_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
- struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv;
+ struct at76c651_state* state = fe->demodulator_priv;
u8 sync;
/*
@@ -319,7 +319,7 @@ static int at76c651_read_status(struct dvb_frontend* fe, fe_status_t* status)
static int at76c651_read_ber(struct dvb_frontend* fe, u32* ber)
{
- struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv;
+ struct at76c651_state* state = fe->demodulator_priv;
*ber = (at76c651_readreg(state, 0x81) & 0x0F) << 16;
*ber |= at76c651_readreg(state, 0x82) << 8;
@@ -331,7 +331,7 @@ static int at76c651_read_ber(struct dvb_frontend* fe, u32* ber)
static int at76c651_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
- struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv;
+ struct at76c651_state* state = fe->demodulator_priv;
u8 gain = ~at76c651_readreg(state, 0x91);
*strength = (gain << 8) | gain;
@@ -341,7 +341,7 @@ static int at76c651_read_signal_strength(struct dvb_frontend* fe, u16* strength)
static int at76c651_read_snr(struct dvb_frontend* fe, u16* snr)
{
- struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv;
+ struct at76c651_state* state = fe->demodulator_priv;
*snr = 0xFFFF -
((at76c651_readreg(state, 0x8F) << 8) |
@@ -352,7 +352,7 @@ static int at76c651_read_snr(struct dvb_frontend* fe, u16* snr)
static int at76c651_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
- struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv;
+ struct at76c651_state* state = fe->demodulator_priv;
*ucblocks = at76c651_readreg(state, 0x82);
@@ -369,7 +369,7 @@ static int at76c651_get_tune_settings(struct dvb_frontend* fe, struct dvb_fronte
static void at76c651_release(struct dvb_frontend* fe)
{
- struct at76c651_state* state = (struct at76c651_state*) fe->demodulator_priv;
+ struct at76c651_state* state = fe->demodulator_priv;
kfree(state);
}
@@ -381,7 +381,7 @@ struct dvb_frontend* at76c651_attach(const struct at76c651_config* config,
struct at76c651_state* state = NULL;
/* allocate memory for the internal state */
- state = (struct at76c651_state*) kmalloc(sizeof(struct at76c651_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct at76c651_state), GFP_KERNEL);
if (state == NULL) goto error;
/* setup the state */
diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c
new file mode 100644
index 00000000000..f5fdc5c3e60
--- /dev/null
+++ b/drivers/media/dvb/frontends/bcm3510.c
@@ -0,0 +1,853 @@
+/*
+ * Support for the Broadcom BCM3510 ATSC demodulator (1st generation Air2PC)
+ *
+ * Copyright (C) 2001-5, B2C2 inc.
+ *
+ * GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@desy.de>
+ *
+ * This driver is "hard-coded" to be used with the 1st generation of
+ * Technisat/B2C2's Air2PC ATSC PCI/USB cards/boxes. The pll-programming
+ * (Panasonic CT10S) is located here, which is actually wrong. Unless there is
+ * another device with a BCM3510, this is no problem.
+ *
+ * The driver works also with QAM64 DVB-C, but had an unreasonable high
+ * UNC. (Tested with the Air2PC ATSC 1st generation)
+ *
+ * You'll need a firmware for this driver in order to get it running. It is
+ * called "dvb-fe-bcm3510-01.fw".
+ *
+ * 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 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., 675 Mass
+ * Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+
+#include "dvb_frontend.h"
+#include "bcm3510.h"
+#include "bcm3510_priv.h"
+
+struct bcm3510_state {
+
+ struct i2c_adapter* i2c;
+ struct dvb_frontend_ops ops;
+ const struct bcm3510_config* config;
+ struct dvb_frontend frontend;
+
+ /* demodulator private data */
+ struct semaphore hab_sem;
+ u8 firmware_loaded:1;
+
+ unsigned long next_status_check;
+ unsigned long status_check_interval;
+ struct bcm3510_hab_cmd_status1 status1;
+ struct bcm3510_hab_cmd_status2 status2;
+};
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,2=i2c (|-able)).");
+
+#define dprintk(level,x...) if (level & debug) printk(x)
+#define dbufout(b,l,m) {\
+ int i; \
+ for (i = 0; i < l; i++) \
+ m("%02x ",b[i]); \
+}
+#define deb_info(args...) dprintk(0x01,args)
+#define deb_i2c(args...) dprintk(0x02,args)
+#define deb_hab(args...) dprintk(0x04,args)
+
+/* transfer functions */
+static int bcm3510_writebytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8 len)
+{
+ u8 b[256];
+ int err;
+ struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = b, .len = len + 1 };
+
+ b[0] = reg;
+ memcpy(&b[1],buf,len);
+
+ deb_i2c("i2c wr %02x: ",reg);
+ dbufout(buf,len,deb_i2c);
+ deb_i2c("\n");
+
+ if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+
+ deb_info("%s: i2c write error (addr %02x, reg %02x, err == %i)\n",
+ __FUNCTION__, state->config->demod_address, reg, err);
+ return -EREMOTEIO;
+ }
+
+ return 0;
+}
+
+static int bcm3510_readbytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8 len)
+{
+ struct i2c_msg msg[] = {
+ { .addr = state->config->demod_address, .flags = 0, .buf = &reg, .len = 1 },
+ { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf, .len = len }
+ };
+ int err;
+
+ memset(buf,0,len);
+
+ if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
+ deb_info("%s: i2c read error (addr %02x, reg %02x, err == %i)\n",
+ __FUNCTION__, state->config->demod_address, reg, err);
+ return -EREMOTEIO;
+ }
+ deb_i2c("i2c rd %02x: ",reg);
+ dbufout(buf,len,deb_i2c);
+ deb_i2c("\n");
+
+ return 0;
+}
+
+static int bcm3510_writeB(struct bcm3510_state *state, u8 reg, bcm3510_register_value v)
+{
+ return bcm3510_writebytes(state,reg,&v.raw,1);
+}
+
+static int bcm3510_readB(struct bcm3510_state *state, u8 reg, bcm3510_register_value *v)
+{
+ return bcm3510_readbytes(state,reg,&v->raw,1);
+}
+
+/* Host Access Buffer transfers */
+static int bcm3510_hab_get_response(struct bcm3510_state *st, u8 *buf, int len)
+{
+ bcm3510_register_value v;
+ int ret,i;
+
+ v.HABADR_a6.HABADR = 0;
+ if ((ret = bcm3510_writeB(st,0xa6,v)) < 0)
+ return ret;
+
+ for (i = 0; i < len; i++) {
+ if ((ret = bcm3510_readB(st,0xa7,&v)) < 0)
+ return ret;
+ buf[i] = v.HABDATA_a7;
+ }
+ return 0;
+}
+
+static int bcm3510_hab_send_request(struct bcm3510_state *st, u8 *buf, int len)
+{
+ bcm3510_register_value v,hab;
+ int ret,i;
+ unsigned long t;
+
+/* Check if any previous HAB request still needs to be serviced by the
+ * Aquisition Processor before sending new request */
+ if ((ret = bcm3510_readB(st,0xa8,&v)) < 0)
+ return ret;
+ if (v.HABSTAT_a8.HABR) {
+ deb_info("HAB is running already - clearing it.\n");
+ v.HABSTAT_a8.HABR = 0;
+ bcm3510_writeB(st,0xa8,v);
+// return -EBUSY;
+ }
+
+/* Send the start HAB Address (automatically incremented after write of
+ * HABDATA) and write the HAB Data */
+ hab.HABADR_a6.HABADR = 0;
+ if ((ret = bcm3510_writeB(st,0xa6,hab)) < 0)
+ return ret;
+
+ for (i = 0; i < len; i++) {
+ hab.HABDATA_a7 = buf[i];
+ if ((ret = bcm3510_writeB(st,0xa7,hab)) < 0)
+ return ret;
+ }
+
+/* Set the HABR bit to indicate AP request in progress (LBHABR allows HABR to
+ * be written) */
+ v.raw = 0; v.HABSTAT_a8.HABR = 1; v.HABSTAT_a8.LDHABR = 1;
+ if ((ret = bcm3510_writeB(st,0xa8,v)) < 0)
+ return ret;
+
+/* Polling method: Wait until the AP finishes processing the HAB request */
+ t = jiffies + 1*HZ;
+ while (time_before(jiffies, t)) {
+ deb_info("waiting for HAB to complete\n");
+ msleep(10);
+ if ((ret = bcm3510_readB(st,0xa8,&v)) < 0)
+ return ret;
+
+ if (!v.HABSTAT_a8.HABR)
+ return 0;
+ }
+
+ deb_info("send_request execution timed out.\n");
+ return -ETIMEDOUT;
+}
+
+static int bcm3510_do_hab_cmd(struct bcm3510_state *st, u8 cmd, u8 msgid, u8 *obuf, u8 olen, u8 *ibuf, u8 ilen)
+{
+ u8 ob[olen+2],ib[ilen+2];
+ int ret = 0;
+
+ ob[0] = cmd;
+ ob[1] = msgid;
+ memcpy(&ob[2],obuf,olen);
+
+ deb_hab("hab snd: ");
+ dbufout(ob,olen+2,deb_hab);
+ deb_hab("\n");
+
+ if (down_interruptible(&st->hab_sem) < 0)
+ return -EAGAIN;
+
+ if ((ret = bcm3510_hab_send_request(st, ob, olen+2)) < 0 ||
+ (ret = bcm3510_hab_get_response(st, ib, ilen+2)) < 0)
+ goto error;
+
+ deb_hab("hab get: ");
+ dbufout(ib,ilen+2,deb_hab);
+ deb_hab("\n");
+
+ memcpy(ibuf,&ib[2],ilen);
+error:
+ up(&st->hab_sem);
+ return ret;
+}
+
+#if 0
+/* not needed, we use a semaphore to prevent HAB races */
+static int bcm3510_is_ap_ready(struct bcm3510_state *st)
+{
+ bcm3510_register_value ap,hab;
+ int ret;
+
+ if ((ret = bcm3510_readB(st,0xa8,&hab)) < 0 ||
+ (ret = bcm3510_readB(st,0xa2,&ap) < 0))
+ return ret;
+
+ if (ap.APSTAT1_a2.RESET || ap.APSTAT1_a2.IDLE || ap.APSTAT1_a2.STOP || hab.HABSTAT_a8.HABR) {
+ deb_info("AP is busy\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+#endif
+
+static int bcm3510_bert_reset(struct bcm3510_state *st)
+{
+ bcm3510_register_value b;
+ int ret;
+
+ if ((ret < bcm3510_readB(st,0xfa,&b)) < 0)
+ return ret;
+
+ b.BERCTL_fa.RESYNC = 0; bcm3510_writeB(st,0xfa,b);
+ b.BERCTL_fa.RESYNC = 1; bcm3510_writeB(st,0xfa,b);
+ b.BERCTL_fa.RESYNC = 0; bcm3510_writeB(st,0xfa,b);
+ b.BERCTL_fa.CNTCTL = 1; b.BERCTL_fa.BITCNT = 1; bcm3510_writeB(st,0xfa,b);
+
+ /* clear residual bit counter TODO */
+ return 0;
+}
+
+static int bcm3510_refresh_state(struct bcm3510_state *st)
+{
+ if (time_after(jiffies,st->next_status_check)) {
+ bcm3510_do_hab_cmd(st, CMD_STATUS, MSGID_STATUS1, NULL,0, (u8 *)&st->status1, sizeof(st->status1));
+ bcm3510_do_hab_cmd(st, CMD_STATUS, MSGID_STATUS2, NULL,0, (u8 *)&st->status2, sizeof(st->status2));
+ st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000;
+ }
+ return 0;
+}
+
+static int bcm3510_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+ struct bcm3510_state* st = fe->demodulator_priv;
+ bcm3510_refresh_state(st);
+
+ *status = 0;
+ if (st->status1.STATUS1.RECEIVER_LOCK)
+ *status |= FE_HAS_LOCK | FE_HAS_SYNC;
+
+ if (st->status1.STATUS1.FEC_LOCK)
+ *status |= FE_HAS_VITERBI;
+
+ if (st->status1.STATUS1.OUT_PLL_LOCK)
+ *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
+
+ if (*status & FE_HAS_LOCK)
+ st->status_check_interval = 1500;
+ else /* more frequently checks if no lock has been achieved yet */
+ st->status_check_interval = 500;
+
+ deb_info("real_status: %02x\n",*status);
+ return 0;
+}
+
+static int bcm3510_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+ struct bcm3510_state* st = fe->demodulator_priv;
+ bcm3510_refresh_state(st);
+
+ *ber = (st->status2.LDBER0 << 16) | (st->status2.LDBER1 << 8) | st->status2.LDBER2;
+ return 0;
+}
+
+static int bcm3510_read_unc(struct dvb_frontend* fe, u32* unc)
+{
+ struct bcm3510_state* st = fe->demodulator_priv;
+ bcm3510_refresh_state(st);
+ *unc = (st->status2.LDUERC0 << 8) | st->status2.LDUERC1;
+ return 0;
+}
+
+static int bcm3510_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+{
+ struct bcm3510_state* st = fe->demodulator_priv;
+ s32 t;
+
+ bcm3510_refresh_state(st);
+ t = st->status2.SIGNAL;
+
+ if (t > 190)
+ t = 190;
+ if (t < 90)
+ t = 90;
+
+ t -= 90;
+ t = t * 0xff / 100;
+ /* normalize if necessary */
+ *strength = (t << 8) | t;
+ return 0;
+}
+
+static int bcm3510_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+ struct bcm3510_state* st = fe->demodulator_priv;
+ bcm3510_refresh_state(st);
+
+ *snr = st->status1.SNR_EST0*1000 + ((st->status1.SNR_EST1*1000) >> 8);
+ return 0;
+}
+
+/* tuner frontend programming */
+static int bcm3510_tuner_cmd(struct bcm3510_state* st,u8 bc, u16 n, u8 a)
+{
+ struct bcm3510_hab_cmd_tune c;
+ memset(&c,0,sizeof(struct bcm3510_hab_cmd_tune));
+
+/* I2C Mode disabled, set 16 control / Data pairs */
+ c.length = 0x10;
+ c.clock_width = 0;
+/* CS1, CS0, DATA, CLK bits control the tuner RF_AGC_SEL pin is set to
+ * logic high (as Configuration) */
+ c.misc = 0x10;
+/* Set duration of the initial state of TUNCTL = 3.34 micro Sec */
+ c.TUNCTL_state = 0x40;
+
+/* PRESCALER DEVIDE RATIO | BC1_2_3_4; (band switch), 1stosc REFERENCE COUNTER REF_S12 and REF_S11 */
+ c.ctl_dat[0].ctrl.size = BITS_8;
+ c.ctl_dat[0].data = 0x80 | bc;
+
+/* Control DATA pin, 1stosc REFERENCE COUNTER REF_S10 to REF_S3 */
+ c.ctl_dat[1].ctrl.size = BITS_8;
+ c.ctl_dat[1].data = 4;
+
+/* set CONTROL BIT 1 to 1, 1stosc REFERENCE COUNTER REF_S2 to REF_S1 */
+ c.ctl_dat[2].ctrl.size = BITS_3;
+ c.ctl_dat[2].data = 0x20;
+
+/* control CS0 pin, pulse byte ? */
+ c.ctl_dat[3].ctrl.size = BITS_3;
+ c.ctl_dat[3].ctrl.clk_off = 1;
+ c.ctl_dat[3].ctrl.cs0 = 1;
+ c.ctl_dat[3].data = 0x40;
+
+/* PGM_S18 to PGM_S11 */
+ c.ctl_dat[4].ctrl.size = BITS_8;
+ c.ctl_dat[4].data = n >> 3;
+
+/* PGM_S10 to PGM_S8, SWL_S7 to SWL_S3 */
+ c.ctl_dat[5].ctrl.size = BITS_8;
+ c.ctl_dat[5].data = ((n & 0x7) << 5) | (a >> 2);
+
+/* SWL_S2 and SWL_S1, set CONTROL BIT 2 to 0 */
+ c.ctl_dat[6].ctrl.size = BITS_3;
+ c.ctl_dat[6].data = (a << 6) & 0xdf;
+
+/* control CS0 pin, pulse byte ? */
+ c.ctl_dat[7].ctrl.size = BITS_3;
+ c.ctl_dat[7].ctrl.clk_off = 1;
+ c.ctl_dat[7].ctrl.cs0 = 1;
+ c.ctl_dat[7].data = 0x40;
+
+/* PRESCALER DEVIDE RATIO, 2ndosc REFERENCE COUNTER REF_S12 and REF_S11 */
+ c.ctl_dat[8].ctrl.size = BITS_8;
+ c.ctl_dat[8].data = 0x80;
+
+/* 2ndosc REFERENCE COUNTER REF_S10 to REF_S3 */
+ c.ctl_dat[9].ctrl.size = BITS_8;
+ c.ctl_dat[9].data = 0x10;
+
+/* set CONTROL BIT 1 to 1, 2ndosc REFERENCE COUNTER REF_S2 to REF_S1 */
+ c.ctl_dat[10].ctrl.size = BITS_3;
+ c.ctl_dat[10].data = 0x20;
+
+/* pulse byte */
+ c.ctl_dat[11].ctrl.size = BITS_3;
+ c.ctl_dat[11].ctrl.clk_off = 1;
+ c.ctl_dat[11].ctrl.cs1 = 1;
+ c.ctl_dat[11].data = 0x40;
+
+/* PGM_S18 to PGM_S11 */
+ c.ctl_dat[12].ctrl.size = BITS_8;
+ c.ctl_dat[12].data = 0x2a;
+
+/* PGM_S10 to PGM_S8 and SWL_S7 to SWL_S3 */
+ c.ctl_dat[13].ctrl.size = BITS_8;
+ c.ctl_dat[13].data = 0x8e;
+
+/* SWL_S2 and SWL_S1 and set CONTROL BIT 2 to 0 */
+ c.ctl_dat[14].ctrl.size = BITS_3;
+ c.ctl_dat[14].data = 0;
+
+/* Pulse Byte */
+ c.ctl_dat[15].ctrl.size = BITS_3;
+ c.ctl_dat[15].ctrl.clk_off = 1;
+ c.ctl_dat[15].ctrl.cs1 = 1;
+ c.ctl_dat[15].data = 0x40;
+
+ return bcm3510_do_hab_cmd(st,CMD_TUNE, MSGID_TUNE,(u8 *) &c,sizeof(c), NULL, 0);
+}
+
+static int bcm3510_set_freq(struct bcm3510_state* st,u32 freq)
+{
+ u8 bc,a;
+ u16 n;
+ s32 YIntercept,Tfvco1;
+
+ freq /= 1000;
+
+ deb_info("%dkHz:",freq);
+ /* set Band Switch */
+ if (freq <= 168000)
+ bc = 0x1c;
+ else if (freq <= 378000)
+ bc = 0x2c;
+ else
+ bc = 0x30;
+
+ if (freq >= 470000) {
+ freq -= 470001;
+ YIntercept = 18805;
+ } else if (freq >= 90000) {
+ freq -= 90001;
+ YIntercept = 15005;
+ } else if (freq >= 76000){
+ freq -= 76001;
+ YIntercept = 14865;
+ } else {
+ freq -= 54001;
+ YIntercept = 14645;
+ }
+
+ Tfvco1 = (((freq/6000)*60 + YIntercept)*4)/10;
+
+ n = Tfvco1 >> 6;
+ a = Tfvco1 & 0x3f;
+
+ deb_info(" BC1_2_3_4: %x, N: %x A: %x\n", bc, n, a);
+ if (n >= 16 && n <= 2047)
+ return bcm3510_tuner_cmd(st,bc,n,a);
+
+ return -EINVAL;
+}
+
+static int bcm3510_set_frontend(struct dvb_frontend* fe,
+ struct dvb_frontend_parameters *p)
+{
+ struct bcm3510_state* st = fe->demodulator_priv;
+ struct bcm3510_hab_cmd_ext_acquire cmd;
+ struct bcm3510_hab_cmd_bert_control bert;
+ int ret;
+
+ memset(&cmd,0,sizeof(cmd));
+ switch (p->u.vsb.modulation) {
+ case QAM_256:
+ cmd.ACQUIRE0.MODE = 0x1;
+ cmd.ACQUIRE1.SYM_RATE = 0x1;
+ cmd.ACQUIRE1.IF_FREQ = 0x1;
+ break;
+ case QAM_64:
+ cmd.ACQUIRE0.MODE = 0x2;
+ cmd.ACQUIRE1.SYM_RATE = 0x2;
+ cmd.ACQUIRE1.IF_FREQ = 0x1;
+ break;
+/* case QAM_256:
+ cmd.ACQUIRE0.MODE = 0x3;
+ break;
+ case QAM_128:
+ cmd.ACQUIRE0.MODE = 0x4;
+ break;
+ case QAM_64:
+ cmd.ACQUIRE0.MODE = 0x5;
+ break;
+ case QAM_32:
+ cmd.ACQUIRE0.MODE = 0x6;
+ break;
+ case QAM_16:
+ cmd.ACQUIRE0.MODE = 0x7;
+ break;*/
+ case VSB_8:
+ cmd.ACQUIRE0.MODE = 0x8;
+ cmd.ACQUIRE1.SYM_RATE = 0x0;
+ cmd.ACQUIRE1.IF_FREQ = 0x0;
+ break;
+ case VSB_16:
+ cmd.ACQUIRE0.MODE = 0x9;
+ cmd.ACQUIRE1.SYM_RATE = 0x0;
+ cmd.ACQUIRE1.IF_FREQ = 0x0;
+ default:
+ return -EINVAL;
+ };
+ cmd.ACQUIRE0.OFFSET = 0;
+ cmd.ACQUIRE0.NTSCSWEEP = 1;
+ cmd.ACQUIRE0.FA = 1;
+ cmd.ACQUIRE0.BW = 0;
+
+/* if (enableOffset) {
+ cmd.IF_OFFSET0 = xx;
+ cmd.IF_OFFSET1 = xx;
+
+ cmd.SYM_OFFSET0 = xx;
+ cmd.SYM_OFFSET1 = xx;
+ if (enableNtscSweep) {
+ cmd.NTSC_OFFSET0;
+ cmd.NTSC_OFFSET1;
+ }
+ } */
+ bcm3510_do_hab_cmd(st, CMD_ACQUIRE, MSGID_EXT_TUNER_ACQUIRE, (u8 *) &cmd, sizeof(cmd), NULL, 0);
+
+/* doing it with different MSGIDs, data book and source differs */
+ bert.BE = 0;
+ bert.unused = 0;
+ bcm3510_do_hab_cmd(st, CMD_STATE_CONTROL, MSGID_BERT_CONTROL, (u8 *) &bert, sizeof(bert), NULL, 0);
+ bcm3510_do_hab_cmd(st, CMD_STATE_CONTROL, MSGID_BERT_SET, (u8 *) &bert, sizeof(bert), NULL, 0);
+
+ bcm3510_bert_reset(st);
+
+ if ((ret = bcm3510_set_freq(st,p->frequency)) < 0)
+ return ret;
+
+ memset(&st->status1,0,sizeof(st->status1));
+ memset(&st->status2,0,sizeof(st->status2));
+ st->status_check_interval = 500;
+
+/* Give the AP some time */
+ msleep(200);
+
+ return 0;
+}
+
+static int bcm3510_sleep(struct dvb_frontend* fe)
+{
+ return 0;
+}
+
+static int bcm3510_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *s)
+{
+ s->min_delay_ms = 1000;
+ s->step_size = 0;
+ s->max_drift = 0;
+ return 0;
+}
+
+static void bcm3510_release(struct dvb_frontend* fe)
+{
+ struct bcm3510_state* state = fe->demodulator_priv;
+ kfree(state);
+}
+
+/* firmware download:
+ * firmware file is build up like this:
+ * 16bit addr, 16bit length, 8byte of length
+ */
+#define BCM3510_DEFAULT_FIRMWARE "dvb-fe-bcm3510-01.fw"
+
+static int bcm3510_write_ram(struct bcm3510_state *st, u16 addr, u8 *b, u16 len)
+{
+ int ret = 0,i;
+ bcm3510_register_value vH, vL,vD;
+
+ vH.MADRH_a9 = addr >> 8;
+ vL.MADRL_aa = addr;
+ if ((ret = bcm3510_writeB(st,0xa9,vH)) < 0) return ret;
+ if ((ret = bcm3510_writeB(st,0xaa,vL)) < 0) return ret;
+
+ for (i = 0; i < len; i++) {
+ vD.MDATA_ab = b[i];
+ if ((ret = bcm3510_writeB(st,0xab,vD)) < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int bcm3510_download_firmware(struct dvb_frontend* fe)
+{
+ struct bcm3510_state* st = fe->demodulator_priv;
+ const struct firmware *fw;
+ u16 addr,len;
+ u8 *b;
+ int ret,i;
+
+ deb_info("requesting firmware\n");
+ if ((ret = st->config->request_firmware(fe, &fw, BCM3510_DEFAULT_FIRMWARE)) < 0) {
+ err("could not load firmware (%s): %d",BCM3510_DEFAULT_FIRMWARE,ret);
+ return ret;
+ }
+ deb_info("got firmware: %d\n",fw->size);
+
+ b = fw->data;
+ for (i = 0; i < fw->size;) {
+ addr = le16_to_cpu( *( (u16 *)&b[i] ) );
+ len = le16_to_cpu( *( (u16 *)&b[i+2] ) );
+ deb_info("firmware chunk, addr: 0x%04x, len: 0x%04x, total length: 0x%04x\n",addr,len,fw->size);
+ if ((ret = bcm3510_write_ram(st,addr,&b[i+4],len)) < 0) {
+ err("firmware download failed: %d\n",ret);
+ return ret;
+ }
+ i += 4 + len;
+ }
+ release_firmware(fw);
+ deb_info("firmware download successfully completed\n");
+ return 0;
+}
+
+static int bcm3510_check_firmware_version(struct bcm3510_state *st)
+{
+ struct bcm3510_hab_cmd_get_version_info ver;
+ bcm3510_do_hab_cmd(st,CMD_GET_VERSION_INFO,MSGID_GET_VERSION_INFO,NULL,0,(u8*)&ver,sizeof(ver));
+
+ deb_info("Version information: 0x%02x 0x%02x 0x%02x 0x%02x\n",
+ ver.microcode_version, ver.script_version, ver.config_version, ver.demod_version);
+
+ if (ver.script_version == BCM3510_DEF_SCRIPT_VERSION &&
+ ver.config_version == BCM3510_DEF_CONFIG_VERSION &&
+ ver.demod_version == BCM3510_DEF_DEMOD_VERSION)
+ return 0;
+
+ deb_info("version check failed\n");
+ return -ENODEV;
+}
+
+/* (un)resetting the AP */
+static int bcm3510_reset(struct bcm3510_state *st)
+{
+ int ret;
+ unsigned long t;
+ bcm3510_register_value v;
+
+ bcm3510_readB(st,0xa0,&v); v.HCTL1_a0.RESET = 1;
+ if ((ret = bcm3510_writeB(st,0xa0,v)) < 0)
+ return ret;
+
+ t = jiffies + 3*HZ;
+ while (time_before(jiffies, t)) {
+ msleep(10);
+ if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
+ return ret;
+
+ if (v.APSTAT1_a2.RESET)
+ return 0;
+ }
+ deb_info("reset timed out\n");
+ return -ETIMEDOUT;
+}
+
+static int bcm3510_clear_reset(struct bcm3510_state *st)
+{
+ bcm3510_register_value v;
+ int ret;
+ unsigned long t;
+
+ v.raw = 0;
+ if ((ret = bcm3510_writeB(st,0xa0,v)) < 0)
+ return ret;
+
+ t = jiffies + 3*HZ;
+ while (time_before(jiffies, t)) {
+ msleep(10);
+ if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
+ return ret;
+
+ /* verify that reset is cleared */
+ if (!v.APSTAT1_a2.RESET)
+ return 0;
+ }
+ deb_info("reset clear timed out\n");
+ return -ETIMEDOUT;
+}
+
+static int bcm3510_init_cold(struct bcm3510_state *st)
+{
+ int ret;
+ bcm3510_register_value v;
+
+ /* read Acquisation Processor status register and check it is not in RUN mode */
+ if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
+ return ret;
+ if (v.APSTAT1_a2.RUN) {
+ deb_info("AP is already running - firmware already loaded.\n");
+ return 0;
+ }
+
+ deb_info("reset?\n");
+ if ((ret = bcm3510_reset(st)) < 0)
+ return ret;
+
+ deb_info("tristate?\n");
+ /* tri-state */
+ v.TSTCTL_2e.CTL = 0;
+ if ((ret = bcm3510_writeB(st,0x2e,v)) < 0)
+ return ret;
+
+ deb_info("firmware?\n");
+ if ((ret = bcm3510_download_firmware(&st->frontend)) < 0 ||
+ (ret = bcm3510_clear_reset(st)) < 0)
+ return ret;
+
+ /* anything left here to Let the acquisition processor begin execution at program counter 0000 ??? */
+
+ return 0;
+}
+
+static int bcm3510_init(struct dvb_frontend* fe)
+{
+ struct bcm3510_state* st = fe->demodulator_priv;
+ bcm3510_register_value j;
+ struct bcm3510_hab_cmd_set_agc c;
+ int ret;
+
+ if ((ret = bcm3510_readB(st,0xca,&j)) < 0)
+ return ret;
+
+ deb_info("JDEC: %02x\n",j.raw);
+
+ switch (j.JDEC_ca.JDEC) {
+ case JDEC_WAIT_AT_RAM:
+ deb_info("attempting to download firmware\n");
+ if ((ret = bcm3510_init_cold(st)) < 0)
+ return ret;
+ case JDEC_EEPROM_LOAD_WAIT: /* fall-through is wanted */
+ deb_info("firmware is loaded\n");
+ bcm3510_check_firmware_version(st);
+ break;
+ default:
+ return -ENODEV;
+ }
+
+ memset(&c,0,1);
+ c.SEL = 1;
+ bcm3510_do_hab_cmd(st,CMD_AUTO_PARAM,MSGID_SET_RF_AGC_SEL,(u8 *)&c,sizeof(c),NULL,0);
+
+ return 0;
+}
+
+
+static struct dvb_frontend_ops bcm3510_ops;
+
+struct dvb_frontend* bcm3510_attach(const struct bcm3510_config *config,
+ struct i2c_adapter *i2c)
+{
+ struct bcm3510_state* state = NULL;
+ int ret;
+ bcm3510_register_value v;
+
+ /* allocate memory for the internal state */
+ state = kmalloc(sizeof(struct bcm3510_state), GFP_KERNEL);
+ if (state == NULL)
+ goto error;
+ memset(state,0,sizeof(struct bcm3510_state));
+
+ /* setup the state */
+
+ state->config = config;
+ state->i2c = i2c;
+ memcpy(&state->ops, &bcm3510_ops, sizeof(struct dvb_frontend_ops));
+
+ /* create dvb_frontend */
+ state->frontend.ops = &state->ops;
+ state->frontend.demodulator_priv = state;
+
+ sema_init(&state->hab_sem, 1);
+
+ if ((ret = bcm3510_readB(state,0xe0,&v)) < 0)
+ goto error;
+
+ deb_info("Revision: 0x%1x, Layer: 0x%1x.\n",v.REVID_e0.REV,v.REVID_e0.LAYER);
+
+ if ((v.REVID_e0.REV != 0x1 && v.REVID_e0.LAYER != 0xb) && /* cold */
+ (v.REVID_e0.REV != 0x8 && v.REVID_e0.LAYER != 0x0)) /* warm */
+ goto error;
+
+ info("Revision: 0x%1x, Layer: 0x%1x.",v.REVID_e0.REV,v.REVID_e0.LAYER);
+
+ bcm3510_reset(state);
+
+ return &state->frontend;
+
+error:
+ kfree(state);
+ return NULL;
+}
+EXPORT_SYMBOL(bcm3510_attach);
+
+static struct dvb_frontend_ops bcm3510_ops = {
+
+ .info = {
+ .name = "Broadcom BCM3510 VSB/QAM frontend",
+ .type = FE_ATSC,
+ .frequency_min = 54000000,
+ .frequency_max = 803000000,
+ /* stepsize is just a guess */
+ .frequency_stepsize = 0,
+ .caps =
+ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+ FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+ FE_CAN_8VSB | FE_CAN_16VSB |
+ FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256
+ },
+
+ .release = bcm3510_release,
+
+ .init = bcm3510_init,
+ .sleep = bcm3510_sleep,
+
+ .set_frontend = bcm3510_set_frontend,
+ .get_tune_settings = bcm3510_get_tune_settings,
+
+ .read_status = bcm3510_read_status,
+ .read_ber = bcm3510_read_ber,
+ .read_signal_strength = bcm3510_read_signal_strength,
+ .read_snr = bcm3510_read_snr,
+ .read_ucblocks = bcm3510_read_unc,
+};
+
+MODULE_DESCRIPTION("Broadcom BCM3510 ATSC (8VSB/16VSB & ITU J83 AnnexB FEC QAM64/256) demodulator driver");
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/bcm3510.h b/drivers/media/dvb/frontends/bcm3510.h
new file mode 100644
index 00000000000..80f5d0953d0
--- /dev/null
+++ b/drivers/media/dvb/frontends/bcm3510.h
@@ -0,0 +1,40 @@
+/*
+ * Support for the Broadcom BCM3510 ATSC demodulator (1st generation Air2PC)
+ *
+ * Copyright (C) 2001-5, B2C2 inc.
+ *
+ * GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@desy.de>
+ *
+ * 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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef BCM3510_H
+#define BCM3510_H
+
+#include <linux/dvb/frontend.h>
+#include <linux/firmware.h>
+
+struct bcm3510_config
+{
+ /* the demodulator's i2c address */
+ u8 demod_address;
+
+ /* request firmware for device */
+ int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
+};
+
+extern struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
+ struct i2c_adapter* i2c);
+
+#endif
diff --git a/drivers/media/dvb/frontends/bcm3510_priv.h b/drivers/media/dvb/frontends/bcm3510_priv.h
new file mode 100644
index 00000000000..3bb1bc2a04f
--- /dev/null
+++ b/drivers/media/dvb/frontends/bcm3510_priv.h
@@ -0,0 +1,460 @@
+/*
+ * Support for the Broadcom BCM3510 ATSC demodulator (1st generation Air2PC)
+ *
+ * Copyright (C) 2001-5, B2C2 inc.
+ *
+ * GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@desy.de>
+ *
+ * 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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __BCM3510_PRIV_H__
+#define __BCM3510_PRIV_H__
+
+#define PACKED __attribute__((packed))
+
+#undef err
+#define err(format, arg...) printk(KERN_ERR "bcm3510: " format "\n" , ## arg)
+#undef info
+#define info(format, arg...) printk(KERN_INFO "bcm3510: " format "\n" , ## arg)
+#undef warn
+#define warn(format, arg...) printk(KERN_WARNING "bcm3510: " format "\n" , ## arg)
+
+
+#define PANASONIC_FIRST_IF_BASE_IN_KHz 1407500
+#define BCM3510_SYMBOL_RATE 5381000
+
+typedef union {
+ u8 raw;
+
+ struct {
+ u8 CTL :8;
+ } TSTCTL_2e;
+
+ u8 LDCERC_4e;
+ u8 LDUERC_4f;
+ u8 LD_BER0_65;
+ u8 LD_BER1_66;
+ u8 LD_BER2_67;
+ u8 LD_BER3_68;
+
+ struct {
+ u8 RESET :1;
+ u8 IDLE :1;
+ u8 STOP :1;
+ u8 HIRQ0 :1;
+ u8 HIRQ1 :1;
+ u8 na0 :1;
+ u8 HABAV :1;
+ u8 na1 :1;
+ } HCTL1_a0;
+
+ struct {
+ u8 na0 :1;
+ u8 IDLMSK :1;
+ u8 STMSK :1;
+ u8 I0MSK :1;
+ u8 I1MSK :1;
+ u8 na1 :1;
+ u8 HABMSK :1;
+ u8 na2 :1;
+ } HCTLMSK_a1;
+
+ struct {
+ u8 RESET :1;
+ u8 IDLE :1;
+ u8 STOP :1;
+ u8 RUN :1;
+ u8 HABAV :1;
+ u8 MEMAV :1;
+ u8 ALDONE :1;
+ u8 REIRQ :1;
+ } APSTAT1_a2;
+
+ struct {
+ u8 RSTMSK :1;
+ u8 IMSK :1;
+ u8 SMSK :1;
+ u8 RMSK :1;
+ u8 HABMSK :1;
+ u8 MAVMSK :1;
+ u8 ALDMSK :1;
+ u8 REMSK :1;
+ } APMSK1_a3;
+
+ u8 APSTAT2_a4;
+ u8 APMSK2_a5;
+
+ struct {
+ u8 HABADR :7;
+ u8 na :1;
+ } HABADR_a6;
+
+ u8 HABDATA_a7;
+
+ struct {
+ u8 HABR :1;
+ u8 LDHABR :1;
+ u8 APMSK :1;
+ u8 HMSK :1;
+ u8 LDMSK :1;
+ u8 na :3;
+ } HABSTAT_a8;
+
+ u8 MADRH_a9;
+ u8 MADRL_aa;
+ u8 MDATA_ab;
+
+ struct {
+#define JDEC_WAIT_AT_RAM 0x7
+#define JDEC_EEPROM_LOAD_WAIT 0x4
+ u8 JDEC :3;
+ u8 na :5;
+ } JDEC_ca;
+
+ struct {
+ u8 REV :4;
+ u8 LAYER :4;
+ } REVID_e0;
+
+ struct {
+ u8 unk0 :1;
+ u8 CNTCTL :1;
+ u8 BITCNT :1;
+ u8 unk1 :1;
+ u8 RESYNC :1;
+ u8 unk2 :3;
+ } BERCTL_fa;
+
+ struct {
+ u8 CSEL0 :1;
+ u8 CLKED0 :1;
+ u8 CSEL1 :1;
+ u8 CLKED1 :1;
+ u8 CLKLEV :1;
+ u8 SPIVAR :1;
+ u8 na :2;
+ } TUNSET_fc;
+
+ struct {
+ u8 CLK :1;
+ u8 DATA :1;
+ u8 CS0 :1;
+ u8 CS1 :1;
+ u8 AGCSEL :1;
+ u8 na0 :1;
+ u8 TUNSEL :1;
+ u8 na1 :1;
+ } TUNCTL_fd;
+
+ u8 TUNSEL0_fe;
+ u8 TUNSEL1_ff;
+
+} bcm3510_register_value;
+
+/* HAB commands */
+
+/* version */
+#define CMD_GET_VERSION_INFO 0x3D
+#define MSGID_GET_VERSION_INFO 0x15
+struct bcm3510_hab_cmd_get_version_info {
+ u8 microcode_version;
+ u8 script_version;
+ u8 config_version;
+ u8 demod_version;
+} PACKED;
+
+#define BCM3510_DEF_MICROCODE_VERSION 0x0E
+#define BCM3510_DEF_SCRIPT_VERSION 0x06
+#define BCM3510_DEF_CONFIG_VERSION 0x01
+#define BCM3510_DEF_DEMOD_VERSION 0xB1
+
+/* acquire */
+#define CMD_ACQUIRE 0x38
+
+#define MSGID_EXT_TUNER_ACQUIRE 0x0A
+struct bcm3510_hab_cmd_ext_acquire {
+ struct {
+ u8 MODE :4;
+ u8 BW :1;
+ u8 FA :1;
+ u8 NTSCSWEEP :1;
+ u8 OFFSET :1;
+ } PACKED ACQUIRE0; /* control_byte */
+
+ struct {
+ u8 IF_FREQ :3;
+ u8 zero0 :1;
+ u8 SYM_RATE :3;
+ u8 zero1 :1;
+ } PACKED ACQUIRE1; /* sym_if */
+
+ u8 IF_OFFSET0; /* IF_Offset_10hz */
+ u8 IF_OFFSET1;
+ u8 SYM_OFFSET0; /* SymbolRateOffset */
+ u8 SYM_OFFSET1;
+ u8 NTSC_OFFSET0; /* NTSC_Offset_10hz */
+ u8 NTSC_OFFSET1;
+} PACKED;
+
+#define MSGID_INT_TUNER_ACQUIRE 0x0B
+struct bcm3510_hab_cmd_int_acquire {
+ struct {
+ u8 MODE :4;
+ u8 BW :1;
+ u8 FA :1;
+ u8 NTSCSWEEP :1;
+ u8 OFFSET :1;
+ } PACKED ACQUIRE0; /* control_byte */
+
+ struct {
+ u8 IF_FREQ :3;
+ u8 zero0 :1;
+ u8 SYM_RATE :3;
+ u8 zero1 :1;
+ } PACKED ACQUIRE1; /* sym_if */
+
+ u8 TUNER_FREQ0;
+ u8 TUNER_FREQ1;
+ u8 TUNER_FREQ2;
+ u8 TUNER_FREQ3;
+ u8 IF_OFFSET0; /* IF_Offset_10hz */
+ u8 IF_OFFSET1;
+ u8 SYM_OFFSET0; /* SymbolRateOffset */
+ u8 SYM_OFFSET1;
+ u8 NTSC_OFFSET0; /* NTSC_Offset_10hz */
+ u8 NTSC_OFFSET1;
+} PACKED;
+
+/* modes */
+#define BCM3510_QAM16 = 0x01
+#define BCM3510_QAM32 = 0x02
+#define BCM3510_QAM64 = 0x03
+#define BCM3510_QAM128 = 0x04
+#define BCM3510_QAM256 = 0x05
+#define BCM3510_8VSB = 0x0B
+#define BCM3510_16VSB = 0x0D
+
+/* IF_FREQS */
+#define BCM3510_IF_TERRESTRIAL 0x0
+#define BCM3510_IF_CABLE 0x1
+#define BCM3510_IF_USE_CMD 0x7
+
+/* SYM_RATE */
+#define BCM3510_SR_8VSB 0x0 /* 5381119 s/sec */
+#define BCM3510_SR_256QAM 0x1 /* 5360537 s/sec */
+#define BCM3510_SR_16QAM 0x2 /* 5056971 s/sec */
+#define BCM3510_SR_MISC 0x3 /* 5000000 s/sec */
+#define BCM3510_SR_USE_CMD 0x7
+
+/* special symbol rate */
+#define CMD_SET_VALUE_NOT_LISTED 0x2d
+#define MSGID_SET_SYMBOL_RATE_NOT_LISTED 0x0c
+struct bcm3510_hab_cmd_set_sr_not_listed {
+ u8 HOST_SYM_RATE0;
+ u8 HOST_SYM_RATE1;
+ u8 HOST_SYM_RATE2;
+ u8 HOST_SYM_RATE3;
+} PACKED;
+
+/* special IF */
+#define MSGID_SET_IF_FREQ_NOT_LISTED 0x0d
+struct bcm3510_hab_cmd_set_if_freq_not_listed {
+ u8 HOST_IF_FREQ0;
+ u8 HOST_IF_FREQ1;
+ u8 HOST_IF_FREQ2;
+ u8 HOST_IF_FREQ3;
+} PACKED;
+
+/* auto reacquire */
+#define CMD_AUTO_PARAM 0x2a
+#define MSGID_AUTO_REACQUIRE 0x0e
+struct bcm3510_hab_cmd_auto_reacquire {
+ u8 ACQ :1; /* on/off*/
+ u8 unused :7;
+} PACKED;
+
+#define MSGID_SET_RF_AGC_SEL 0x12
+struct bcm3510_hab_cmd_set_agc {
+ u8 LVL :1;
+ u8 unused :6;
+ u8 SEL :1;
+} PACKED;
+
+#define MSGID_SET_AUTO_INVERSION 0x14
+struct bcm3510_hab_cmd_auto_inversion {
+ u8 AI :1;
+ u8 unused :7;
+} PACKED;
+
+
+/* bert control */
+#define CMD_STATE_CONTROL 0x12
+#define MSGID_BERT_CONTROL 0x0e
+#define MSGID_BERT_SET 0xfa
+struct bcm3510_hab_cmd_bert_control {
+ u8 BE :1;
+ u8 unused :7;
+} PACKED;
+
+#define MSGID_TRI_STATE 0x2e
+struct bcm3510_hab_cmd_tri_state {
+ u8 RE :1; /* a/d ram port pins */
+ u8 PE :1; /* baud clock pin */
+ u8 AC :1; /* a/d clock pin */
+ u8 BE :1; /* baud clock pin */
+ u8 unused :4;
+} PACKED;
+
+
+/* tune */
+#define CMD_TUNE 0x38
+#define MSGID_TUNE 0x16
+struct bcm3510_hab_cmd_tune_ctrl_data_pair {
+ struct {
+#define BITS_8 0x07
+#define BITS_7 0x06
+#define BITS_6 0x05
+#define BITS_5 0x04
+#define BITS_4 0x03
+#define BITS_3 0x02
+#define BITS_2 0x01
+#define BITS_1 0x00
+ u8 size :3;
+ u8 unk :2;
+ u8 clk_off :1;
+ u8 cs0 :1;
+ u8 cs1 :1;
+
+ } PACKED ctrl;
+
+ u8 data;
+} PACKED;
+
+struct bcm3510_hab_cmd_tune {
+ u8 length;
+ u8 clock_width;
+ u8 misc;
+ u8 TUNCTL_state;
+
+ struct bcm3510_hab_cmd_tune_ctrl_data_pair ctl_dat[16];
+} PACKED;
+
+#define CMD_STATUS 0x38
+#define MSGID_STATUS1 0x08
+struct bcm3510_hab_cmd_status1 {
+ struct {
+ u8 EQ_MODE :4;
+ u8 reserved :2;
+ u8 QRE :1; /* if QSE and the spectrum is inversed */
+ u8 QSE :1; /* automatic spectral inversion */
+ } PACKED STATUS0;
+
+ struct {
+ u8 RECEIVER_LOCK :1;
+ u8 FEC_LOCK :1;
+ u8 OUT_PLL_LOCK :1;
+ u8 reserved :5;
+ } PACKED STATUS1;
+
+ struct {
+ u8 reserved :2;
+ u8 BW :1;
+ u8 NTE :1; /* NTSC filter sweep enabled */
+ u8 AQI :1; /* currently acquiring */
+ u8 FA :1; /* fast acquisition */
+ u8 ARI :1; /* auto reacquire */
+ u8 TI :1; /* programming the tuner */
+ } PACKED STATUS2;
+ u8 STATUS3;
+ u8 SNR_EST0;
+ u8 SNR_EST1;
+ u8 TUNER_FREQ0;
+ u8 TUNER_FREQ1;
+ u8 TUNER_FREQ2;
+ u8 TUNER_FREQ3;
+ u8 SYM_RATE0;
+ u8 SYM_RATE1;
+ u8 SYM_RATE2;
+ u8 SYM_RATE3;
+ u8 SYM_OFFSET0;
+ u8 SYM_OFFSET1;
+ u8 SYM_ERROR0;
+ u8 SYM_ERROR1;
+ u8 IF_FREQ0;
+ u8 IF_FREQ1;
+ u8 IF_FREQ2;
+ u8 IF_FREQ3;
+ u8 IF_OFFSET0;
+ u8 IF_OFFSET1;
+ u8 IF_ERROR0;
+ u8 IF_ERROR1;
+ u8 NTSC_FILTER0;
+ u8 NTSC_FILTER1;
+ u8 NTSC_FILTER2;
+ u8 NTSC_FILTER3;
+ u8 NTSC_OFFSET0;
+ u8 NTSC_OFFSET1;
+ u8 NTSC_ERROR0;
+ u8 NTSC_ERROR1;
+ u8 INT_AGC_LEVEL0;
+ u8 INT_AGC_LEVEL1;
+ u8 EXT_AGC_LEVEL0;
+ u8 EXT_AGC_LEVEL1;
+} PACKED;
+
+#define MSGID_STATUS2 0x14
+struct bcm3510_hab_cmd_status2 {
+ struct {
+ u8 EQ_MODE :4;
+ u8 reserved :2;
+ u8 QRE :1;
+ u8 QSR :1;
+ } PACKED STATUS0;
+ struct {
+ u8 RL :1;
+ u8 FL :1;
+ u8 OL :1;
+ u8 reserved :5;
+ } PACKED STATUS1;
+ u8 SYMBOL_RATE0;
+ u8 SYMBOL_RATE1;
+ u8 SYMBOL_RATE2;
+ u8 SYMBOL_RATE3;
+ u8 LDCERC0;
+ u8 LDCERC1;
+ u8 LDCERC2;
+ u8 LDCERC3;
+ u8 LDUERC0;
+ u8 LDUERC1;
+ u8 LDUERC2;
+ u8 LDUERC3;
+ u8 LDBER0;
+ u8 LDBER1;
+ u8 LDBER2;
+ u8 LDBER3;
+ struct {
+ u8 MODE_TYPE :4; /* acquire mode 0 */
+ u8 reservd :4;
+ } MODE_TYPE;
+ u8 SNR_EST0;
+ u8 SNR_EST1;
+ u8 SIGNAL;
+} PACKED;
+
+#define CMD_SET_RF_BW_NOT_LISTED 0x3f
+#define MSGID_SET_RF_BW_NOT_LISTED 0x11
+/* TODO */
+
+#endif
diff --git a/drivers/media/dvb/frontends/cx22700.c b/drivers/media/dvb/frontends/cx22700.c
index a212279042b..0c2ed443861 100644
--- a/drivers/media/dvb/frontends/cx22700.c
+++ b/drivers/media/dvb/frontends/cx22700.c
@@ -232,7 +232,7 @@ static int cx22700_get_tps (struct cx22700_state* state, struct dvb_ofdm_paramet
static int cx22700_init (struct dvb_frontend* fe)
-{ struct cx22700_state* state = (struct cx22700_state*) fe->demodulator_priv;
+{ struct cx22700_state* state = fe->demodulator_priv;
int i;
dprintk("cx22700_init: init chip\n");
@@ -258,7 +258,7 @@ static int cx22700_init (struct dvb_frontend* fe)
static int cx22700_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
- struct cx22700_state* state = (struct cx22700_state*) fe->demodulator_priv;
+ struct cx22700_state* state = fe->demodulator_priv;
u16 rs_ber = (cx22700_readreg (state, 0x0d) << 9)
| (cx22700_readreg (state, 0x0e) << 1);
@@ -286,7 +286,7 @@ static int cx22700_read_status(struct dvb_frontend* fe, fe_status_t* status)
static int cx22700_read_ber(struct dvb_frontend* fe, u32* ber)
{
- struct cx22700_state* state = (struct cx22700_state*) fe->demodulator_priv;
+ struct cx22700_state* state = fe->demodulator_priv;
*ber = cx22700_readreg (state, 0x0c) & 0x7f;
cx22700_writereg (state, 0x0c, 0x00);
@@ -296,7 +296,7 @@ static int cx22700_read_ber(struct dvb_frontend* fe, u32* ber)
static int cx22700_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
{
- struct cx22700_state* state = (struct cx22700_state*) fe->demodulator_priv;
+ struct cx22700_state* state = fe->demodulator_priv;
u16 rs_ber = (cx22700_readreg (state, 0x0d) << 9)
| (cx22700_readreg (state, 0x0e) << 1);
@@ -307,7 +307,7 @@ static int cx22700_read_signal_strength(struct dvb_frontend* fe, u16* signal_str
static int cx22700_read_snr(struct dvb_frontend* fe, u16* snr)
{
- struct cx22700_state* state = (struct cx22700_state*) fe->demodulator_priv;
+ struct cx22700_state* state = fe->demodulator_priv;
u16 rs_ber = (cx22700_readreg (state, 0x0d) << 9)
| (cx22700_readreg (state, 0x0e) << 1);
@@ -318,7 +318,7 @@ static int cx22700_read_snr(struct dvb_frontend* fe, u16* snr)
static int cx22700_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
- struct cx22700_state* state = (struct cx22700_state*) fe->demodulator_priv;
+ struct cx22700_state* state = fe->demodulator_priv;
*ucblocks = cx22700_readreg (state, 0x0f);
cx22700_writereg (state, 0x0f, 0x00);
@@ -328,7 +328,7 @@ static int cx22700_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
static int cx22700_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
- struct cx22700_state* state = (struct cx22700_state*) fe->demodulator_priv;
+ struct cx22700_state* state = fe->demodulator_priv;
cx22700_writereg (state, 0x00, 0x02); /* XXX CHECKME: soft reset*/
cx22700_writereg (state, 0x00, 0x00);
@@ -346,7 +346,7 @@ static int cx22700_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
static int cx22700_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
- struct cx22700_state* state = (struct cx22700_state*) fe->demodulator_priv;
+ struct cx22700_state* state = fe->demodulator_priv;
u8 reg09 = cx22700_readreg (state, 0x09);
p->inversion = reg09 & 0x1 ? INVERSION_ON : INVERSION_OFF;
@@ -363,7 +363,7 @@ static int cx22700_get_tune_settings(struct dvb_frontend* fe, struct dvb_fronten
static void cx22700_release(struct dvb_frontend* fe)
{
- struct cx22700_state* state = (struct cx22700_state*) fe->demodulator_priv;
+ struct cx22700_state* state = fe->demodulator_priv;
kfree(state);
}
@@ -375,7 +375,7 @@ struct dvb_frontend* cx22700_attach(const struct cx22700_config* config,
struct cx22700_state* state = NULL;
/* allocate memory for the internal state */
- state = (struct cx22700_state*) kmalloc(sizeof(struct cx22700_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct cx22700_state), GFP_KERNEL);
if (state == NULL) goto error;
/* setup the state */
diff --git a/drivers/media/dvb/frontends/cx22702.c b/drivers/media/dvb/frontends/cx22702.c
index 011860ce36c..f4aa44136c7 100644
--- a/drivers/media/dvb/frontends/cx22702.c
+++ b/drivers/media/dvb/frontends/cx22702.c
@@ -200,7 +200,7 @@ static int cx22702_get_tps (struct cx22702_state *state, struct dvb_ofdm_paramet
static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
u8 val;
- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv;
+ struct cx22702_state* state = fe->demodulator_priv;
/* set PLL */
cx22702_writereg (state, 0x0D, cx22702_readreg(state,0x0D) &0xfe);
@@ -338,7 +338,7 @@ static int cx22702_set_tps (struct dvb_frontend* fe, struct dvb_frontend_paramet
static int cx22702_init (struct dvb_frontend* fe)
{
int i;
- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv;
+ struct cx22702_state* state = fe->demodulator_priv;
cx22702_writereg (state, 0x00, 0x02);
@@ -360,7 +360,7 @@ static int cx22702_init (struct dvb_frontend* fe)
static int cx22702_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv;
+ struct cx22702_state* state = fe->demodulator_priv;
u8 reg0A;
u8 reg23;
@@ -389,7 +389,7 @@ static int cx22702_read_status(struct dvb_frontend* fe, fe_status_t* status)
static int cx22702_read_ber(struct dvb_frontend* fe, u32* ber)
{
- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv;
+ struct cx22702_state* state = fe->demodulator_priv;
if(cx22702_readreg (state, 0xE4) & 0x02) {
/* Realtime statistics */
@@ -406,7 +406,7 @@ static int cx22702_read_ber(struct dvb_frontend* fe, u32* ber)
static int cx22702_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
{
- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv;
+ struct cx22702_state* state = fe->demodulator_priv;
*signal_strength = cx22702_readreg (state, 0x23);
@@ -415,7 +415,7 @@ static int cx22702_read_signal_strength(struct dvb_frontend* fe, u16* signal_str
static int cx22702_read_snr(struct dvb_frontend* fe, u16* snr)
{
- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv;
+ struct cx22702_state* state = fe->demodulator_priv;
u16 rs_ber=0;
if(cx22702_readreg (state, 0xE4) & 0x02) {
@@ -434,7 +434,7 @@ static int cx22702_read_snr(struct dvb_frontend* fe, u16* snr)
static int cx22702_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv;
+ struct cx22702_state* state = fe->demodulator_priv;
u8 _ucblocks;
@@ -449,7 +449,7 @@ static int cx22702_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
static int cx22702_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv;
+ struct cx22702_state* state = fe->demodulator_priv;
u8 reg0C = cx22702_readreg (state, 0x0C);
@@ -459,7 +459,7 @@ static int cx22702_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
static void cx22702_release(struct dvb_frontend* fe)
{
- struct cx22702_state* state = (struct cx22702_state*) fe->demodulator_priv;
+ struct cx22702_state* state = fe->demodulator_priv;
kfree(state);
}
@@ -471,7 +471,7 @@ struct dvb_frontend* cx22702_attach(const struct cx22702_config* config,
struct cx22702_state* state = NULL;
/* allocate memory for the internal state */
- state = (struct cx22702_state*) kmalloc(sizeof(struct cx22702_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct cx22702_state), GFP_KERNEL);
if (state == NULL) goto error;
/* setup the state */
diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c
index ae16112a065..8222b88cb48 100644
--- a/drivers/media/dvb/frontends/cx24110.c
+++ b/drivers/media/dvb/frontends/cx24110.c
@@ -315,7 +315,7 @@ dprintk("cx24110 debug: entering %s(%d)\n",__FUNCTION__,srate);
int cx24110_pll_write (struct dvb_frontend* fe, u32 data)
{
- struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv;
+ struct cx24110_state *state = fe->demodulator_priv;
/* tuner data is 21 bits long, must be left-aligned in data */
/* tuner cx24108 is written through a dedicated 3wire interface on the demod chip */
@@ -356,7 +356,7 @@ int cx24110_pll_write (struct dvb_frontend* fe, u32 data)
static int cx24110_initfe(struct dvb_frontend* fe)
{
- struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv;
+ struct cx24110_state *state = fe->demodulator_priv;
/* fixme (low): error handling */
int i;
@@ -373,7 +373,7 @@ static int cx24110_initfe(struct dvb_frontend* fe)
static int cx24110_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
{
- struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv;
+ struct cx24110_state *state = fe->demodulator_priv;
switch (voltage) {
case SEC_VOLTAGE_13:
@@ -385,8 +385,7 @@ static int cx24110_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
};
}
-static int cx24110_diseqc_send_burst(struct dvb_frontend* fe,
- fe_sec_mini_cmd_t burst)
+static int cx24110_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
{
int rv, bit, i;
struct cx24110_state *state = fe->demodulator_priv;
@@ -413,7 +412,7 @@ static int cx24110_send_diseqc_msg(struct dvb_frontend* fe,
struct dvb_diseqc_master_cmd *cmd)
{
int i, rv;
- struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv;
+ struct cx24110_state *state = fe->demodulator_priv;
for (i = 0; i < cmd->msg_len; i++)
cx24110_writereg(state, 0x79 + i, cmd->msg[i]);
@@ -432,7 +431,7 @@ static int cx24110_send_diseqc_msg(struct dvb_frontend* fe,
static int cx24110_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
- struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv;
+ struct cx24110_state *state = fe->demodulator_priv;
int sync = cx24110_readreg (state, 0x55);
@@ -460,7 +459,7 @@ static int cx24110_read_status(struct dvb_frontend* fe, fe_status_t* status)
static int cx24110_read_ber(struct dvb_frontend* fe, u32* ber)
{
- struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv;
+ struct cx24110_state *state = fe->demodulator_priv;
/* fixme (maybe): value range is 16 bit. Scale? */
if(cx24110_readreg(state,0x24)&0x10) {
@@ -478,7 +477,7 @@ static int cx24110_read_ber(struct dvb_frontend* fe, u32* ber)
static int cx24110_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
{
- struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv;
+ struct cx24110_state *state = fe->demodulator_priv;
/* no provision in hardware. Read the frontend AGC accumulator. No idea how to scale this, but I know it is 2s complement */
u8 signal = cx24110_readreg (state, 0x27)+128;
@@ -489,7 +488,7 @@ static int cx24110_read_signal_strength(struct dvb_frontend* fe, u16* signal_str
static int cx24110_read_snr(struct dvb_frontend* fe, u16* snr)
{
- struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv;
+ struct cx24110_state *state = fe->demodulator_priv;
/* no provision in hardware. Can be computed from the Es/N0 estimator, but I don't know how. */
if(cx24110_readreg(state,0x6a)&0x80) {
@@ -505,7 +504,7 @@ static int cx24110_read_snr(struct dvb_frontend* fe, u16* snr)
static int cx24110_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
- struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv;
+ struct cx24110_state *state = fe->demodulator_priv;
u32 lastbyer;
if(cx24110_readreg(state,0x10)&0x40) {
@@ -527,7 +526,7 @@ static int cx24110_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
static int cx24110_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
- struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv;
+ struct cx24110_state *state = fe->demodulator_priv;
state->config->pll_set(fe, p);
cx24110_set_inversion (state, p->inversion);
@@ -540,7 +539,7 @@ static int cx24110_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
static int cx24110_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
- struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv;
+ struct cx24110_state *state = fe->demodulator_priv;
s32 afc; unsigned sclk;
/* cannot read back tuner settings (freq). Need to have some private storage */
@@ -567,14 +566,14 @@ static int cx24110_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
static int cx24110_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
{
- struct cx24110_state *state = (struct cx24110_state*) fe->demodulator_priv;
+ struct cx24110_state *state = fe->demodulator_priv;
return cx24110_writereg(state,0x76,(cx24110_readreg(state,0x76)&~0x10)|(((tone==SEC_TONE_ON))?0x10:0));
}
static void cx24110_release(struct dvb_frontend* fe)
{
- struct cx24110_state* state = (struct cx24110_state*) fe->demodulator_priv;
+ struct cx24110_state* state = fe->demodulator_priv;
kfree(state);
}
@@ -587,7 +586,7 @@ struct dvb_frontend* cx24110_attach(const struct cx24110_config* config,
int ret;
/* allocate memory for the internal state */
- state = (struct cx24110_state*) kmalloc(sizeof(struct cx24110_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct cx24110_state), GFP_KERNEL);
if (state == NULL) goto error;
/* setup the state */
diff --git a/drivers/media/dvb/frontends/dib3000-common.c b/drivers/media/dvb/frontends/dib3000-common.c
index 47ab02e133d..1a4f1f7c228 100644
--- a/drivers/media/dvb/frontends/dib3000-common.c
+++ b/drivers/media/dvb/frontends/dib3000-common.c
@@ -73,7 +73,7 @@ u16 dib3000_seq[2][2][2] = /* fft,gua, inv */
};
MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de");
-MODULE_DESCRIPTION("Common functions for the dib3000mb/dib3000mc dvb-frontend drivers");
+MODULE_DESCRIPTION("Common functions for the dib3000mb/dib3000mc dvb frontend drivers");
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(dib3000_seq);
diff --git a/drivers/media/dvb/frontends/dib3000.h b/drivers/media/dvb/frontends/dib3000.h
index 80687c13083..2d5475b5c06 100644
--- a/drivers/media/dvb/frontends/dib3000.h
+++ b/drivers/media/dvb/frontends/dib3000.h
@@ -32,9 +32,8 @@ struct dib3000_config
u8 demod_address;
/* PLL maintenance and the i2c address of the PLL */
- u8 (*pll_addr)(struct dvb_frontend *fe);
- int (*pll_init)(struct dvb_frontend *fe, u8 pll_buf[5]);
- int (*pll_set)(struct dvb_frontend *fe, struct dvb_frontend_parameters* params, u8 pll_buf[5]);
+ int (*pll_init)(struct dvb_frontend *fe);
+ int (*pll_set)(struct dvb_frontend *fe, struct dvb_frontend_parameters* params);
};
struct dib_fe_xfer_ops
diff --git a/drivers/media/dvb/frontends/dib3000mb.c b/drivers/media/dvb/frontends/dib3000mb.c
index a853d12a26f..cd434b7cf9d 100644
--- a/drivers/media/dvb/frontends/dib3000mb.c
+++ b/drivers/media/dvb/frontends/dib3000mb.c
@@ -48,23 +48,19 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-a
#define deb_setf(args...) dprintk(0x04,args)
#define deb_getf(args...) dprintk(0x08,args)
-static int dib3000mb_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr);
-
static int dib3000mb_get_frontend(struct dvb_frontend* fe,
struct dvb_frontend_parameters *fep);
static int dib3000mb_set_frontend(struct dvb_frontend* fe,
struct dvb_frontend_parameters *fep, int tuner)
{
- struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv;
+ struct dib3000_state* state = fe->demodulator_priv;
struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;
fe_code_rate_t fe_cr = FEC_NONE;
int search_state, seq;
- if (tuner) {
- dib3000mb_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe));
- state->config.pll_set(fe, fep, NULL);
- dib3000mb_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe));
+ if (tuner && state->config.pll_set) {
+ state->config.pll_set(fe, fep);
deb_setf("bandwidth: ");
switch (ofdm->bandwidth) {
@@ -317,7 +313,7 @@ static int dib3000mb_set_frontend(struct dvb_frontend* fe,
static int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode)
{
- struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv;
+ struct dib3000_state* state = fe->demodulator_priv;
deb_info("dib3000mb is getting up.\n");
wr(DIB3000MB_REG_POWER_CONTROL, DIB3000MB_POWER_UP);
@@ -389,11 +385,8 @@ static int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode)
wr(DIB3000MB_REG_DATA_IN_DIVERSITY, DIB3000MB_DATA_DIVERSITY_IN_OFF);
- if (state->config.pll_init) {
- dib3000mb_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe));
- state->config.pll_init(fe,NULL);
- dib3000mb_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe));
- }
+ if (state->config.pll_init)
+ state->config.pll_init(fe);
return 0;
}
@@ -401,7 +394,7 @@ static int dib3000mb_fe_init(struct dvb_frontend* fe, int mobile_mode)
static int dib3000mb_get_frontend(struct dvb_frontend* fe,
struct dvb_frontend_parameters *fep)
{
- struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv;
+ struct dib3000_state* state = fe->demodulator_priv;
struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;
fe_code_rate_t *cr;
u16 tps_val;
@@ -562,7 +555,7 @@ static int dib3000mb_get_frontend(struct dvb_frontend* fe,
static int dib3000mb_read_status(struct dvb_frontend* fe, fe_status_t *stat)
{
- struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv;
+ struct dib3000_state* state = fe->demodulator_priv;
*stat = 0;
@@ -594,7 +587,7 @@ static int dib3000mb_read_status(struct dvb_frontend* fe, fe_status_t *stat)
static int dib3000mb_read_ber(struct dvb_frontend* fe, u32 *ber)
{
- struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv;
+ struct dib3000_state* state = fe->demodulator_priv;
*ber = ((rd(DIB3000MB_REG_BER_MSB) << 16) | rd(DIB3000MB_REG_BER_LSB));
return 0;
@@ -603,7 +596,7 @@ static int dib3000mb_read_ber(struct dvb_frontend* fe, u32 *ber)
/* see dib3000-watch dvb-apps for exact calcuations of signal_strength and snr */
static int dib3000mb_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
{
- struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv;
+ struct dib3000_state* state = fe->demodulator_priv;
*strength = rd(DIB3000MB_REG_SIGNAL_POWER) * 0xffff / 0x170;
return 0;
@@ -611,7 +604,7 @@ static int dib3000mb_read_signal_strength(struct dvb_frontend* fe, u16 *strength
static int dib3000mb_read_snr(struct dvb_frontend* fe, u16 *snr)
{
- struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv;
+ struct dib3000_state* state = fe->demodulator_priv;
short sigpow = rd(DIB3000MB_REG_SIGNAL_POWER);
int icipow = ((rd(DIB3000MB_REG_NOISE_POWER_MSB) & 0xff) << 16) |
rd(DIB3000MB_REG_NOISE_POWER_LSB);
@@ -621,15 +614,15 @@ static int dib3000mb_read_snr(struct dvb_frontend* fe, u16 *snr)
static int dib3000mb_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
{
- struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv;
+ struct dib3000_state* state = fe->demodulator_priv;
- *unc = rd(DIB3000MB_REG_UNC);
+ *unc = rd(DIB3000MB_REG_PACKET_ERROR_RATE);
return 0;
}
static int dib3000mb_sleep(struct dvb_frontend* fe)
{
- struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv;
+ struct dib3000_state* state = fe->demodulator_priv;
deb_info("dib3000mb is going to bed.\n");
wr(DIB3000MB_REG_POWER_CONTROL, DIB3000MB_POWER_DOWN);
return 0;
@@ -638,9 +631,6 @@ static int dib3000mb_sleep(struct dvb_frontend* fe)
static int dib3000mb_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
{
tune->min_delay_ms = 800;
- tune->step_size = 166667;
- tune->max_drift = 166667 * 2;
-
return 0;
}
@@ -656,7 +646,7 @@ static int dib3000mb_set_frontend_and_tuner(struct dvb_frontend* fe, struct dvb_
static void dib3000mb_release(struct dvb_frontend* fe)
{
- struct dib3000_state *state = (struct dib3000_state*) fe->demodulator_priv;
+ struct dib3000_state *state = fe->demodulator_priv;
kfree(state);
}
@@ -671,7 +661,7 @@ static int dib3000mb_pid_control(struct dvb_frontend *fe,int index, int pid,int
static int dib3000mb_fifo_control(struct dvb_frontend *fe, int onoff)
{
- struct dib3000_state *state = (struct dib3000_state*) fe->demodulator_priv;
+ struct dib3000_state *state = fe->demodulator_priv;
deb_xfer("%s fifo\n",onoff ? "enabling" : "disabling");
if (onoff) {
@@ -692,7 +682,7 @@ static int dib3000mb_pid_parse(struct dvb_frontend *fe, int onoff)
static int dib3000mb_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr)
{
- struct dib3000_state *state = (struct dib3000_state*) fe->demodulator_priv;
+ struct dib3000_state *state = fe->demodulator_priv;
if (onoff) {
wr(DIB3000MB_REG_TUNER, DIB3000_TUNER_WRITE_ENABLE(pll_addr));
} else {
@@ -709,7 +699,7 @@ struct dvb_frontend* dib3000mb_attach(const struct dib3000_config* config,
struct dib3000_state* state = NULL;
/* allocate memory for the internal state */
- state = (struct dib3000_state*) kmalloc(sizeof(struct dib3000_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct dib3000_state), GFP_KERNEL);
if (state == NULL)
goto error;
memset(state,0,sizeof(struct dib3000_state));
diff --git a/drivers/media/dvb/frontends/dib3000mb_priv.h b/drivers/media/dvb/frontends/dib3000mb_priv.h
index 57e61aa5b07..999b1904781 100644
--- a/drivers/media/dvb/frontends/dib3000mb_priv.h
+++ b/drivers/media/dvb/frontends/dib3000mb_priv.h
@@ -294,7 +294,7 @@ static u16 dib3000mb_reg_filter_coeffs[] = {
static u16 dib3000mb_filter_coeffs[] = {
226, 160, 29,
- 979, 998, 19,
+ 979, 998, 19,
22, 1019, 1006,
1022, 12, 6,
1017, 1017, 3,
diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c
index 4a31c05eaec..cd33705a432 100644
--- a/drivers/media/dvb/frontends/dib3000mc.c
+++ b/drivers/media/dvb/frontends/dib3000mc.c
@@ -48,8 +48,6 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe,16=s
#define deb_getf(args...) dprintk(0x08,args)
#define deb_stat(args...) dprintk(0x10,args)
-static int dib3000mc_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr);
-
static int dib3000mc_set_impulse_noise(struct dib3000_state * state, int mode,
fe_transmit_mode_t transmission_mode, fe_bandwidth_t bandwidth)
{
@@ -297,7 +295,7 @@ static int dib3000mc_set_general_cfg(struct dib3000_state *state, struct dvb_fro
static int dib3000mc_get_frontend(struct dvb_frontend* fe,
struct dvb_frontend_parameters *fep)
{
- struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv;
+ struct dib3000_state* state = fe->demodulator_priv;
struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;
fe_code_rate_t *cr;
u16 tps_val,cr_val;
@@ -458,15 +456,13 @@ static int dib3000mc_get_frontend(struct dvb_frontend* fe,
static int dib3000mc_set_frontend(struct dvb_frontend* fe,
struct dvb_frontend_parameters *fep, int tuner)
{
- struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv;
+ struct dib3000_state* state = fe->demodulator_priv;
struct dvb_ofdm_parameters *ofdm = &fep->u.ofdm;
int search_state,auto_val;
u16 val;
- if (tuner) { /* initial call from dvb */
- dib3000mc_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe));
- state->config.pll_set(fe,fep,NULL);
- dib3000mc_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe));
+ if (tuner && state->config.pll_set) { /* initial call from dvb */
+ state->config.pll_set(fe,fep);
state->last_tuned_freq = fep->frequency;
// if (!scanboost) {
@@ -554,19 +550,15 @@ static int dib3000mc_set_frontend(struct dvb_frontend* fe,
dib3000mc_set_adp_cfg(state,ofdm->constellation);
wr_foreach(dib3000mc_reg_offset,
dib3000mc_offset[(ofdm->transmission_mode == TRANSMISSION_MODE_8K)+1]);
-
-
}
return 0;
}
static int dib3000mc_fe_init(struct dvb_frontend* fe, int mobile_mode)
{
- struct dib3000_state *state;
-
+ struct dib3000_state *state = fe->demodulator_priv;
deb_info("init start\n");
- state = fe->demodulator_priv;
state->timing_offset = 0;
state->timing_offset_comp_done = 0;
@@ -649,17 +641,15 @@ static int dib3000mc_fe_init(struct dvb_frontend* fe, int mobile_mode)
set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_DIV_IN_OFF);
-/* if (state->config->pll_init) {
- dib3000mc_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe));
- state->config->pll_init(fe,NULL);
- dib3000mc_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe));
- }*/
+ if (state->config.pll_init)
+ state->config.pll_init(fe);
+
deb_info("init end\n");
return 0;
}
static int dib3000mc_read_status(struct dvb_frontend* fe, fe_status_t *stat)
{
- struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv;
+ struct dib3000_state* state = fe->demodulator_priv;
u16 lock = rd(DIB3000MC_REG_LOCKING);
*stat = 0;
@@ -679,23 +669,23 @@ static int dib3000mc_read_status(struct dvb_frontend* fe, fe_status_t *stat)
static int dib3000mc_read_ber(struct dvb_frontend* fe, u32 *ber)
{
- struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv;
+ struct dib3000_state* state = fe->demodulator_priv;
*ber = ((rd(DIB3000MC_REG_BER_MSB) << 16) | rd(DIB3000MC_REG_BER_LSB));
return 0;
}
static int dib3000mc_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
{
- struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv;
+ struct dib3000_state* state = fe->demodulator_priv;
- *unc = rd(DIB3000MC_REG_PACKET_ERROR_COUNT);
+ *unc = rd(DIB3000MC_REG_PACKET_ERRORS);
return 0;
}
/* see dib3000mb.c for calculation comments */
static int dib3000mc_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
{
- struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv;
+ struct dib3000_state* state = fe->demodulator_priv;
u16 val = rd(DIB3000MC_REG_SIGNAL_NOISE_LSB);
*strength = (((val >> 6) & 0xff) << 8) + (val & 0x3f);
@@ -706,7 +696,7 @@ static int dib3000mc_read_signal_strength(struct dvb_frontend* fe, u16 *strength
/* see dib3000mb.c for calculation comments */
static int dib3000mc_read_snr(struct dvb_frontend* fe, u16 *snr)
{
- struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv;
+ struct dib3000_state* state = fe->demodulator_priv;
u16 val = rd(DIB3000MC_REG_SIGNAL_NOISE_LSB),
val2 = rd(DIB3000MC_REG_SIGNAL_NOISE_MSB);
u16 sig,noise;
@@ -726,7 +716,7 @@ static int dib3000mc_read_snr(struct dvb_frontend* fe, u16 *snr)
static int dib3000mc_sleep(struct dvb_frontend* fe)
{
- struct dib3000_state* state = (struct dib3000_state*) fe->demodulator_priv;
+ struct dib3000_state* state = fe->demodulator_priv;
set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_PWR_DOWN);
wr(DIB3000MC_REG_CLK_CFG_1,DIB3000MC_CLK_CFG_1_POWER_DOWN);
@@ -737,10 +727,7 @@ static int dib3000mc_sleep(struct dvb_frontend* fe)
static int dib3000mc_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
{
- tune->min_delay_ms = 2000;
- tune->step_size = 166667;
- tune->max_drift = 166667 * 2;
-
+ tune->min_delay_ms = 1000;
return 0;
}
@@ -756,7 +743,7 @@ static int dib3000mc_set_frontend_and_tuner(struct dvb_frontend* fe, struct dvb_
static void dib3000mc_release(struct dvb_frontend* fe)
{
- struct dib3000_state *state = (struct dib3000_state *) fe->demodulator_priv;
+ struct dib3000_state *state = fe->demodulator_priv;
kfree(state);
}
@@ -771,7 +758,7 @@ static int dib3000mc_pid_control(struct dvb_frontend *fe,int index, int pid,int
static int dib3000mc_fifo_control(struct dvb_frontend *fe, int onoff)
{
- struct dib3000_state *state = (struct dib3000_state*) fe->demodulator_priv;
+ struct dib3000_state *state = fe->demodulator_priv;
u16 tmp = rd(DIB3000MC_REG_SMO_MODE);
deb_xfer("%s fifo\n",onoff ? "enabling" : "disabling");
@@ -803,7 +790,7 @@ static int dib3000mc_pid_parse(struct dvb_frontend *fe, int onoff)
static int dib3000mc_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr)
{
- struct dib3000_state *state = (struct dib3000_state*) fe->demodulator_priv;
+ struct dib3000_state *state = fe->demodulator_priv;
if (onoff) {
wr(DIB3000MC_REG_TUNER, DIB3000_TUNER_WRITE_ENABLE(pll_addr));
} else {
@@ -844,7 +831,7 @@ struct dvb_frontend* dib3000mc_attach(const struct dib3000_config* config,
u16 devid;
/* allocate memory for the internal state */
- state = (struct dib3000_state*) kmalloc(sizeof(struct dib3000_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct dib3000_state), GFP_KERNEL);
if (state == NULL)
goto error;
memset(state,0,sizeof(struct dib3000_state));
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
index 2a3c2ce7b2a..f73b5f48e23 100644
--- a/drivers/media/dvb/frontends/dvb-pll.c
+++ b/drivers/media/dvb/frontends/dvb-pll.c
@@ -1,6 +1,4 @@
/*
- * $Id: dvb-pll.c,v 1.7 2005/02/10 11:52:02 kraxel Exp $
- *
* descriptions + helper functions for simple dvb plls.
*
* (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
@@ -114,6 +112,92 @@ struct dvb_pll_desc dvb_pll_unknown_1 = {
};
EXPORT_SYMBOL(dvb_pll_unknown_1);
+/* Infineon TUA6010XS
+ * used in Thomson Cable Tuner
+ */
+struct dvb_pll_desc dvb_pll_tua6010xs = {
+ .name = "Infineon TUA6010XS",
+ .min = 44250000,
+ .max = 858000000,
+ .count = 3,
+ .entries = {
+ { 115750000, 36125000, 62500, 0x8e, 0x03 },
+ { 403250000, 36125000, 62500, 0x8e, 0x06 },
+ { 999999999, 36125000, 62500, 0x8e, 0x85 },
+ },
+};
+EXPORT_SYMBOL(dvb_pll_tua6010xs);
+
+/* Panasonic env57h1xd5 (some Philips PLL ?) */
+struct dvb_pll_desc dvb_pll_env57h1xd5 = {
+ .name = "Panasonic ENV57H1XD5",
+ .min = 44250000,
+ .max = 858000000,
+ .count = 4,
+ .entries = {
+ { 153000000, 36291666, 166666, 0xc2, 0x41 },
+ { 470000000, 36291666, 166666, 0xc2, 0x42 },
+ { 526000000, 36291666, 166666, 0xc2, 0x84 },
+ { 999999999, 36291666, 166666, 0xc2, 0xa4 },
+ },
+};
+EXPORT_SYMBOL(dvb_pll_env57h1xd5);
+
+/* Philips TDA6650/TDA6651
+ * used in Panasonic ENV77H11D5
+ */
+static void tda665x_bw(u8 *buf, int bandwidth)
+{
+ if (bandwidth == BANDWIDTH_8_MHZ)
+ buf[3] |= 0x08;
+}
+
+struct dvb_pll_desc dvb_pll_tda665x = {
+ .name = "Philips TDA6650/TDA6651",
+ .min = 44250000,
+ .max = 858000000,
+ .setbw = tda665x_bw,
+ .count = 12,
+ .entries = {
+ { 93834000, 36249333, 166667, 0xca, 0x61 /* 011 0 0 0 01 */ },
+ { 123834000, 36249333, 166667, 0xca, 0xa1 /* 101 0 0 0 01 */ },
+ { 161000000, 36249333, 166667, 0xca, 0xa1 /* 101 0 0 0 01 */ },
+ { 163834000, 36249333, 166667, 0xca, 0xc2 /* 110 0 0 0 10 */ },
+ { 253834000, 36249333, 166667, 0xca, 0x62 /* 011 0 0 0 10 */ },
+ { 383834000, 36249333, 166667, 0xca, 0xa2 /* 101 0 0 0 10 */ },
+ { 443834000, 36249333, 166667, 0xca, 0xc2 /* 110 0 0 0 10 */ },
+ { 444000000, 36249333, 166667, 0xca, 0xc3 /* 110 0 0 0 11 */ },
+ { 583834000, 36249333, 166667, 0xca, 0x63 /* 011 0 0 0 11 */ },
+ { 793834000, 36249333, 166667, 0xca, 0xa3 /* 101 0 0 0 11 */ },
+ { 444834000, 36249333, 166667, 0xca, 0xc3 /* 110 0 0 0 11 */ },
+ { 861000000, 36249333, 166667, 0xca, 0xe3 /* 111 0 0 0 11 */ },
+ }
+};
+EXPORT_SYMBOL(dvb_pll_tda665x);
+
+/* Infineon TUA6034
+ * used in LG TDTP E102P
+ */
+static void tua6034_bw(u8 *buf, int bandwidth)
+{
+ if (BANDWIDTH_7_MHZ != bandwidth)
+ buf[3] |= 0x08;
+}
+
+struct dvb_pll_desc dvb_pll_tua6034 = {
+ .name = "Infineon TUA6034",
+ .min = 44250000,
+ .max = 858000000,
+ .count = 3,
+ .setbw = tua6034_bw,
+ .entries = {
+ { 174500000, 36166667, 62500, 0xce, 0x01 },
+ { 230000000, 36166667, 62500, 0xce, 0x02 },
+ { 999999999, 36166667, 62500, 0xce, 0x04 },
+ },
+};
+EXPORT_SYMBOL(dvb_pll_tua6034);
+
/* ----------------------------------------------------------- */
/* code */
@@ -160,9 +244,3 @@ EXPORT_SYMBOL(dvb_pll_configure);
MODULE_DESCRIPTION("dvb pll library");
MODULE_AUTHOR("Gerd Knorr");
MODULE_LICENSE("GPL");
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h
index 016c794a567..b796778624b 100644
--- a/drivers/media/dvb/frontends/dvb-pll.h
+++ b/drivers/media/dvb/frontends/dvb-pll.h
@@ -1,7 +1,10 @@
/*
- * $Id: dvb-pll.h,v 1.2 2005/02/10 11:43:41 kraxel Exp $
+ * descriptions + helper functions for simple dvb plls.
*/
+#ifndef __DVB_PLL_H__
+#define __DVB_PLL_H__
+
struct dvb_pll_desc {
char *name;
u32 min;
@@ -14,7 +17,7 @@ struct dvb_pll_desc {
u32 stepsize;
u8 cb1;
u8 cb2;
- } entries[9];
+ } entries[12];
};
extern struct dvb_pll_desc dvb_pll_thomson_dtt7579;
@@ -23,12 +26,12 @@ extern struct dvb_pll_desc dvb_pll_thomson_dtt7610;
extern struct dvb_pll_desc dvb_pll_lg_z201;
extern struct dvb_pll_desc dvb_pll_unknown_1;
+extern struct dvb_pll_desc dvb_pll_tua6010xs;
+extern struct dvb_pll_desc dvb_pll_env57h1xd5;
+extern struct dvb_pll_desc dvb_pll_tua6034;
+extern struct dvb_pll_desc dvb_pll_tda665x;
+
int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
u32 freq, int bandwidth);
-/*
- * Local variables:
- * c-basic-offset: 8
- * compile-command: "make DVB=1"
- * End:
- */
+#endif
diff --git a/drivers/media/dvb/frontends/dvb_dummy_fe.c b/drivers/media/dvb/frontends/dvb_dummy_fe.c
index c05a9b05600..cff93b9d8ab 100644
--- a/drivers/media/dvb/frontends/dvb_dummy_fe.c
+++ b/drivers/media/dvb/frontends/dvb_dummy_fe.c
@@ -100,7 +100,7 @@ static int dvb_dummy_fe_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t vo
static void dvb_dummy_fe_release(struct dvb_frontend* fe)
{
- struct dvb_dummy_fe_state* state = (struct dvb_dummy_fe_state*) fe->demodulator_priv;
+ struct dvb_dummy_fe_state* state = fe->demodulator_priv;
kfree(state);
}
@@ -111,7 +111,7 @@ struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void)
struct dvb_dummy_fe_state* state = NULL;
/* allocate memory for the internal state */
- state = (struct dvb_dummy_fe_state*) kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
if (state == NULL) goto error;
/* setup the state */
@@ -134,7 +134,7 @@ struct dvb_frontend* dvb_dummy_fe_qpsk_attach()
struct dvb_dummy_fe_state* state = NULL;
/* allocate memory for the internal state */
- state = (struct dvb_dummy_fe_state*) kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
if (state == NULL) goto error;
/* setup the state */
@@ -157,7 +157,7 @@ struct dvb_frontend* dvb_dummy_fe_qam_attach()
struct dvb_dummy_fe_state* state = NULL;
/* allocate memory for the internal state */
- state = (struct dvb_dummy_fe_state*) kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct dvb_dummy_fe_state), GFP_KERNEL);
if (state == NULL) goto error;
/* setup the state */
diff --git a/drivers/media/dvb/frontends/l64781.c b/drivers/media/dvb/frontends/l64781.c
index 9ac95de9834..031a1ddc7d1 100644
--- a/drivers/media/dvb/frontends/l64781.c
+++ b/drivers/media/dvb/frontends/l64781.c
@@ -121,7 +121,7 @@ static int reset_and_configure (struct l64781_state* state)
static int apply_frontend_param (struct dvb_frontend* fe, struct dvb_frontend_parameters *param)
{
- struct l64781_state* state = (struct l64781_state*) fe->demodulator_priv;
+ struct l64781_state* state = fe->demodulator_priv;
/* The coderates for FEC_NONE, FEC_4_5 and FEC_FEC_6_7 are arbitrary */
static const u8 fec_tab[] = { 7, 0, 1, 2, 9, 3, 10, 4 };
/* QPSK, QAM_16, QAM_64 */
@@ -234,7 +234,7 @@ static int apply_frontend_param (struct dvb_frontend* fe, struct dvb_frontend_pa
static int get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters* param)
{
- struct l64781_state* state = (struct l64781_state*) fe->demodulator_priv;
+ struct l64781_state* state = fe->demodulator_priv;
int tmp;
@@ -352,7 +352,7 @@ static int get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters*
static int l64781_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
- struct l64781_state* state = (struct l64781_state*) fe->demodulator_priv;
+ struct l64781_state* state = fe->demodulator_priv;
int sync = l64781_readreg (state, 0x32);
int gain = l64781_readreg (state, 0x0e);
@@ -381,7 +381,7 @@ static int l64781_read_status(struct dvb_frontend* fe, fe_status_t* status)
static int l64781_read_ber(struct dvb_frontend* fe, u32* ber)
{
- struct l64781_state* state = (struct l64781_state*) fe->demodulator_priv;
+ struct l64781_state* state = fe->demodulator_priv;
/* XXX FIXME: set up counting period (reg 0x26...0x28)
*/
@@ -393,7 +393,7 @@ static int l64781_read_ber(struct dvb_frontend* fe, u32* ber)
static int l64781_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
{
- struct l64781_state* state = (struct l64781_state*) fe->demodulator_priv;
+ struct l64781_state* state = fe->demodulator_priv;
u8 gain = l64781_readreg (state, 0x0e);
*signal_strength = (gain << 8) | gain;
@@ -403,7 +403,7 @@ static int l64781_read_signal_strength(struct dvb_frontend* fe, u16* signal_stre
static int l64781_read_snr(struct dvb_frontend* fe, u16* snr)
{
- struct l64781_state* state = (struct l64781_state*) fe->demodulator_priv;
+ struct l64781_state* state = fe->demodulator_priv;
u8 avg_quality = 0xff - l64781_readreg (state, 0x33);
*snr = (avg_quality << 8) | avg_quality; /* not exact, but...*/
@@ -413,7 +413,7 @@ static int l64781_read_snr(struct dvb_frontend* fe, u16* snr)
static int l64781_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
- struct l64781_state* state = (struct l64781_state*) fe->demodulator_priv;
+ struct l64781_state* state = fe->demodulator_priv;
*ucblocks = l64781_readreg (state, 0x37)
| (l64781_readreg (state, 0x38) << 8);
@@ -423,7 +423,7 @@ static int l64781_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
static int l64781_sleep(struct dvb_frontend* fe)
{
- struct l64781_state* state = (struct l64781_state*) fe->demodulator_priv;
+ struct l64781_state* state = fe->demodulator_priv;
/* Power down */
return l64781_writereg (state, 0x3e, 0x5a);
@@ -431,7 +431,7 @@ static int l64781_sleep(struct dvb_frontend* fe)
static int l64781_init(struct dvb_frontend* fe)
{
- struct l64781_state* state = (struct l64781_state*) fe->demodulator_priv;
+ struct l64781_state* state = fe->demodulator_priv;
reset_and_configure (state);
@@ -484,7 +484,7 @@ static int l64781_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend
static void l64781_release(struct dvb_frontend* fe)
{
- struct l64781_state* state = (struct l64781_state*) fe->demodulator_priv;
+ struct l64781_state* state = fe->demodulator_priv;
kfree(state);
}
@@ -501,7 +501,7 @@ struct dvb_frontend* l64781_attach(const struct l64781_config* config,
{ .addr = config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 1 } };
/* allocate memory for the internal state */
- state = (struct l64781_state*) kmalloc(sizeof(struct l64781_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct l64781_state), GFP_KERNEL);
if (state == NULL) goto error;
/* setup the state */
diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c
index 176a22e3441..e455aecd76b 100644
--- a/drivers/media/dvb/frontends/mt312.c
+++ b/drivers/media/dvb/frontends/mt312.c
@@ -226,7 +226,7 @@ static int mt312_get_code_rate(struct mt312_state* state, fe_code_rate_t *cr)
static int mt312_initfe(struct dvb_frontend* fe)
{
- struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
+ struct mt312_state *state = fe->demodulator_priv;
int ret;
u8 buf[2];
@@ -287,7 +287,7 @@ static int mt312_initfe(struct dvb_frontend* fe)
static int mt312_send_master_cmd(struct dvb_frontend* fe,
struct dvb_diseqc_master_cmd *c)
{
- struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
+ struct mt312_state *state = fe->demodulator_priv;
int ret;
u8 diseqc_mode;
@@ -318,7 +318,7 @@ static int mt312_send_master_cmd(struct dvb_frontend* fe,
static int mt312_send_burst(struct dvb_frontend* fe, const fe_sec_mini_cmd_t c)
{
- struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
+ struct mt312_state *state = fe->demodulator_priv;
const u8 mini_tab[2] = { 0x02, 0x03 };
int ret;
@@ -340,7 +340,7 @@ static int mt312_send_burst(struct dvb_frontend* fe, const fe_sec_mini_cmd_t c)
static int mt312_set_tone(struct dvb_frontend* fe, const fe_sec_tone_mode_t t)
{
- struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
+ struct mt312_state *state = fe->demodulator_priv;
const u8 tone_tab[2] = { 0x01, 0x00 };
int ret;
@@ -362,7 +362,7 @@ static int mt312_set_tone(struct dvb_frontend* fe, const fe_sec_tone_mode_t t)
static int mt312_set_voltage(struct dvb_frontend* fe, const fe_sec_voltage_t v)
{
- struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
+ struct mt312_state *state = fe->demodulator_priv;
const u8 volt_tab[3] = { 0x00, 0x40, 0x00 };
if (v > SEC_VOLTAGE_OFF)
@@ -373,7 +373,7 @@ static int mt312_set_voltage(struct dvb_frontend* fe, const fe_sec_voltage_t v)
static int mt312_read_status(struct dvb_frontend* fe, fe_status_t *s)
{
- struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
+ struct mt312_state *state = fe->demodulator_priv;
int ret;
u8 status[3];
@@ -400,7 +400,7 @@ static int mt312_read_status(struct dvb_frontend* fe, fe_status_t *s)
static int mt312_read_ber(struct dvb_frontend* fe, u32 *ber)
{
- struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
+ struct mt312_state *state = fe->demodulator_priv;
int ret;
u8 buf[3];
@@ -414,7 +414,7 @@ static int mt312_read_ber(struct dvb_frontend* fe, u32 *ber)
static int mt312_read_signal_strength(struct dvb_frontend* fe, u16 *signal_strength)
{
- struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
+ struct mt312_state *state = fe->demodulator_priv;
int ret;
u8 buf[3];
u16 agc;
@@ -435,7 +435,7 @@ static int mt312_read_signal_strength(struct dvb_frontend* fe, u16 *signal_stren
static int mt312_read_snr(struct dvb_frontend* fe, u16 *snr)
{
- struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
+ struct mt312_state *state = fe->demodulator_priv;
int ret;
u8 buf[2];
@@ -449,7 +449,7 @@ static int mt312_read_snr(struct dvb_frontend* fe, u16 *snr)
static int mt312_read_ucblocks(struct dvb_frontend* fe, u32 *ubc)
{
- struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
+ struct mt312_state *state = fe->demodulator_priv;
int ret;
u8 buf[2];
@@ -464,7 +464,7 @@ static int mt312_read_ucblocks(struct dvb_frontend* fe, u32 *ubc)
static int mt312_set_frontend(struct dvb_frontend* fe,
struct dvb_frontend_parameters *p)
{
- struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
+ struct mt312_state *state = fe->demodulator_priv;
int ret;
u8 buf[5], config_val;
u16 sr;
@@ -560,7 +560,7 @@ static int mt312_set_frontend(struct dvb_frontend* fe,
static int mt312_get_frontend(struct dvb_frontend* fe,
struct dvb_frontend_parameters *p)
{
- struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
+ struct mt312_state *state = fe->demodulator_priv;
int ret;
if ((ret = mt312_get_inversion(state, &p->inversion)) < 0)
@@ -577,7 +577,7 @@ static int mt312_get_frontend(struct dvb_frontend* fe,
static int mt312_sleep(struct dvb_frontend* fe)
{
- struct mt312_state *state = (struct mt312_state*) fe->demodulator_priv;
+ struct mt312_state *state = fe->demodulator_priv;
int ret;
u8 config;
@@ -605,7 +605,7 @@ static int mt312_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_
static void mt312_release(struct dvb_frontend* fe)
{
- struct mt312_state* state = (struct mt312_state*) fe->demodulator_priv;
+ struct mt312_state* state = fe->demodulator_priv;
kfree(state);
}
@@ -617,7 +617,7 @@ struct dvb_frontend* vp310_attach(const struct mt312_config* config,
struct mt312_state* state = NULL;
/* allocate memory for the internal state */
- state = (struct mt312_state*) kmalloc(sizeof(struct mt312_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct mt312_state), GFP_KERNEL);
if (state == NULL)
goto error;
@@ -651,7 +651,7 @@ struct dvb_frontend* mt312_attach(const struct mt312_config* config,
struct mt312_state* state = NULL;
/* allocate memory for the internal state */
- state = (struct mt312_state*) kmalloc(sizeof(struct mt312_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct mt312_state), GFP_KERNEL);
if (state == NULL)
goto error;
diff --git a/drivers/media/dvb/frontends/mt352.c b/drivers/media/dvb/frontends/mt352.c
index 50326c7248f..d32dc4de9e7 100644
--- a/drivers/media/dvb/frontends/mt352.c
+++ b/drivers/media/dvb/frontends/mt352.c
@@ -46,7 +46,7 @@ struct mt352_state {
struct dvb_frontend_ops ops;
/* configuration settings */
- const struct mt352_config* config;
+ struct mt352_config config;
};
static int debug;
@@ -59,7 +59,7 @@ static int mt352_single_write(struct dvb_frontend *fe, u8 reg, u8 val)
{
struct mt352_state* state = fe->demodulator_priv;
u8 buf[2] = { reg, val };
- struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0,
+ struct i2c_msg msg = { .addr = state->config.demod_address, .flags = 0,
.buf = buf, .len = 2 };
int err = i2c_transfer(state->i2c, &msg, 1);
if (err != 1) {
@@ -84,10 +84,10 @@ static int mt352_read_register(struct mt352_state* state, u8 reg)
int ret;
u8 b0 [] = { reg };
u8 b1 [] = { 0 };
- struct i2c_msg msg [] = { { .addr = state->config->demod_address,
+ struct i2c_msg msg [] = { { .addr = state->config.demod_address,
.flags = 0,
.buf = b0, .len = 1 },
- { .addr = state->config->demod_address,
+ { .addr = state->config.demod_address,
.flags = I2C_M_RD,
.buf = b1, .len = 1 } };
@@ -102,11 +102,6 @@ static int mt352_read_register(struct mt352_state* state, u8 reg)
return b1[0];
}
-int mt352_read(struct dvb_frontend *fe, u8 reg)
-{
- return mt352_read_register(fe->demodulator_priv,reg);
-}
-
static int mt352_sleep(struct dvb_frontend* fe)
{
static u8 mt352_softdown[] = { CLOCK_CTL, 0x20, 0x08 };
@@ -134,8 +129,8 @@ static void mt352_calc_nominal_rate(struct mt352_state* state,
bw = 8;
break;
}
- if (state->config->adc_clock)
- adc_clock = state->config->adc_clock;
+ if (state->config.adc_clock)
+ adc_clock = state->config.adc_clock;
value = 64 * bw * (1<<16) / (7 * 8);
value = value * 1000 / adc_clock;
@@ -152,10 +147,10 @@ static void mt352_calc_input_freq(struct mt352_state* state,
int if2 = 36167; /* 36.166667 MHz */
int ife,value;
- if (state->config->adc_clock)
- adc_clock = state->config->adc_clock;
- if (state->config->if2)
- if2 = state->config->if2;
+ if (state->config.adc_clock)
+ adc_clock = state->config.adc_clock;
+ if (state->config.if2)
+ if2 = state->config.if2;
ife = (2*adc_clock - if2);
value = -16374 * ife / adc_clock;
@@ -289,10 +284,10 @@ static int mt352_set_parameters(struct dvb_frontend* fe,
mt352_calc_nominal_rate(state, op->bandwidth, buf+4);
mt352_calc_input_freq(state, buf+6);
- state->config->pll_set(fe, param, buf+8);
+ state->config.pll_set(fe, param, buf+8);
mt352_write(fe, buf, sizeof(buf));
- if (state->config->no_tuner) {
+ if (state->config.no_tuner) {
/* start decoding */
mt352_write(fe, fsm_go, 2);
} else {
@@ -516,7 +511,7 @@ static int mt352_init(struct dvb_frontend* fe)
/* Do a "hard" reset */
mt352_write(fe, mt352_reset_attach, sizeof(mt352_reset_attach));
- return state->config->demod_init(fe);
+ return state->config.demod_init(fe);
}
return 0;
@@ -541,8 +536,8 @@ struct dvb_frontend* mt352_attach(const struct mt352_config* config,
memset(state,0,sizeof(*state));
/* setup the state */
- state->config = config;
state->i2c = i2c;
+ memcpy(&state->config,config,sizeof(struct mt352_config));
memcpy(&state->ops, &mt352_ops, sizeof(struct dvb_frontend_ops));
/* check if the demod is there */
@@ -601,10 +596,3 @@ MODULE_LICENSE("GPL");
EXPORT_SYMBOL(mt352_attach);
EXPORT_SYMBOL(mt352_write);
-EXPORT_SYMBOL(mt352_read);
-/*
- * Local variables:
- * c-basic-offset: 8
- * compile-command: "make DVB=1"
- * End:
- */
diff --git a/drivers/media/dvb/frontends/mt352.h b/drivers/media/dvb/frontends/mt352.h
index f5d8a5aed8a..03040cd595b 100644
--- a/drivers/media/dvb/frontends/mt352.h
+++ b/drivers/media/dvb/frontends/mt352.h
@@ -61,12 +61,5 @@ extern struct dvb_frontend* mt352_attach(const struct mt352_config* config,
struct i2c_adapter* i2c);
extern int mt352_write(struct dvb_frontend* fe, u8* ibuf, int ilen);
-extern int mt352_read(struct dvb_frontend *fe, u8 reg);
#endif // MT352_H
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb/frontends/nxt2002.c b/drivers/media/dvb/frontends/nxt2002.c
index 4743aa17406..35a1d60f192 100644
--- a/drivers/media/dvb/frontends/nxt2002.c
+++ b/drivers/media/dvb/frontends/nxt2002.c
@@ -241,7 +241,7 @@ static void nxt2002_agc_reset(struct nxt2002_state* state)
static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
{
- struct nxt2002_state* state = (struct nxt2002_state*) fe->demodulator_priv;
+ struct nxt2002_state* state = fe->demodulator_priv;
u8 buf[256],written = 0,chunkpos = 0;
u16 rambase,position,crc = 0;
@@ -309,7 +309,7 @@ static int nxt2002_load_firmware (struct dvb_frontend* fe, const struct firmware
static int nxt2002_setup_frontend_parameters (struct dvb_frontend* fe,
struct dvb_frontend_parameters *p)
{
- struct nxt2002_state* state = (struct nxt2002_state*) fe->demodulator_priv;
+ struct nxt2002_state* state = fe->demodulator_priv;
u32 freq = 0;
u16 tunerfreq = 0;
u8 buf[4];
@@ -343,8 +343,6 @@ static int nxt2002_setup_frontend_parameters (struct dvb_frontend* fe,
/* reset the agc now that tuning has been completed */
nxt2002_agc_reset(state);
-
-
/* set target power level */
switch (p->u.vsb.modulation) {
case QAM_64:
@@ -453,7 +451,7 @@ static int nxt2002_setup_frontend_parameters (struct dvb_frontend* fe,
static int nxt2002_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
- struct nxt2002_state* state = (struct nxt2002_state*) fe->demodulator_priv;
+ struct nxt2002_state* state = fe->demodulator_priv;
u8 lock;
i2c_readbytes(state,0x31,&lock,1);
@@ -470,7 +468,7 @@ static int nxt2002_read_status(struct dvb_frontend* fe, fe_status_t* status)
static int nxt2002_read_ber(struct dvb_frontend* fe, u32* ber)
{
- struct nxt2002_state* state = (struct nxt2002_state*) fe->demodulator_priv;
+ struct nxt2002_state* state = fe->demodulator_priv;
u8 b[3];
nxt2002_readreg_multibyte(state,0xE6,b,3);
@@ -482,7 +480,7 @@ static int nxt2002_read_ber(struct dvb_frontend* fe, u32* ber)
static int nxt2002_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
- struct nxt2002_state* state = (struct nxt2002_state*) fe->demodulator_priv;
+ struct nxt2002_state* state = fe->demodulator_priv;
u8 b[2];
u16 temp = 0;
@@ -502,7 +500,7 @@ static int nxt2002_read_signal_strength(struct dvb_frontend* fe, u16* strength)
static int nxt2002_read_snr(struct dvb_frontend* fe, u16* snr)
{
- struct nxt2002_state* state = (struct nxt2002_state*) fe->demodulator_priv;
+ struct nxt2002_state* state = fe->demodulator_priv;
u8 b[2];
u16 temp = 0, temp2;
u32 snrdb = 0;
@@ -536,7 +534,7 @@ static int nxt2002_read_snr(struct dvb_frontend* fe, u16* snr)
static int nxt2002_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
- struct nxt2002_state* state = (struct nxt2002_state*) fe->demodulator_priv;
+ struct nxt2002_state* state = fe->demodulator_priv;
u8 b[3];
nxt2002_readreg_multibyte(state,0xE6,b,3);
@@ -552,7 +550,7 @@ static int nxt2002_sleep(struct dvb_frontend* fe)
static int nxt2002_init(struct dvb_frontend* fe)
{
- struct nxt2002_state* state = (struct nxt2002_state*) fe->demodulator_priv;
+ struct nxt2002_state* state = fe->demodulator_priv;
const struct firmware *fw;
int ret;
u8 buf[2];
@@ -624,7 +622,7 @@ static int nxt2002_get_tune_settings(struct dvb_frontend* fe, struct dvb_fronten
static void nxt2002_release(struct dvb_frontend* fe)
{
- struct nxt2002_state* state = (struct nxt2002_state*) fe->demodulator_priv;
+ struct nxt2002_state* state = fe->demodulator_priv;
kfree(state);
}
@@ -637,7 +635,7 @@ struct dvb_frontend* nxt2002_attach(const struct nxt2002_config* config,
u8 buf [] = {0,0,0,0,0};
/* allocate memory for the internal state */
- state = (struct nxt2002_state*) kmalloc(sizeof(struct nxt2002_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct nxt2002_state), GFP_KERNEL);
if (state == NULL) goto error;
/* setup the state */
diff --git a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb/frontends/nxt6000.c
index a41f7da8b84..966de9853d1 100644
--- a/drivers/media/dvb/frontends/nxt6000.c
+++ b/drivers/media/dvb/frontends/nxt6000.c
@@ -176,11 +176,16 @@ static int nxt6000_set_transmission_mode(struct nxt6000_state* state, fe_transmi
static void nxt6000_setup(struct dvb_frontend* fe)
{
- struct nxt6000_state* state = (struct nxt6000_state*) fe->demodulator_priv;
+ struct nxt6000_state* state = fe->demodulator_priv;
nxt6000_writereg(state, RS_COR_SYNC_PARAM, SYNC_PARAM);
nxt6000_writereg(state, BER_CTRL, /*(1 << 2) | */ (0x01 << 1) | 0x01);
- nxt6000_writereg(state, VIT_COR_CTL, VIT_COR_RESYNC);
+ nxt6000_writereg(state, VIT_BERTIME_2, 0x00); // BER Timer = 0x000200 * 256 = 131072 bits
+ nxt6000_writereg(state, VIT_BERTIME_1, 0x02); //
+ nxt6000_writereg(state, VIT_BERTIME_0, 0x00); //
+ nxt6000_writereg(state, VIT_COR_INTEN, 0x98); // Enable BER interrupts
+ nxt6000_writereg(state, VIT_COR_CTL, 0x82); // Enable BER measurement
+ nxt6000_writereg(state, VIT_COR_CTL, VIT_COR_RESYNC | 0x02 );
nxt6000_writereg(state, OFDM_COR_CTL, (0x01 << 5) | (nxt6000_readreg(state, OFDM_COR_CTL) & 0x0F));
nxt6000_writereg(state, OFDM_COR_MODEGUARD, FORCEMODE8K | 0x02);
nxt6000_writereg(state, OFDM_AGC_CTL, AGCLAST | INITIAL_AGC_BW);
@@ -422,7 +427,7 @@ static void nxt6000_dump_status(struct nxt6000_state *state)
static int nxt6000_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
u8 core_status;
- struct nxt6000_state* state = (struct nxt6000_state*) fe->demodulator_priv;
+ struct nxt6000_state* state = fe->demodulator_priv;
*status = 0;
@@ -451,7 +456,7 @@ static int nxt6000_read_status(struct dvb_frontend* fe, fe_status_t* status)
static int nxt6000_init(struct dvb_frontend* fe)
{
- struct nxt6000_state* state = (struct nxt6000_state*) fe->demodulator_priv;
+ struct nxt6000_state* state = fe->demodulator_priv;
nxt6000_reset(state);
nxt6000_setup(fe);
@@ -461,7 +466,7 @@ static int nxt6000_init(struct dvb_frontend* fe)
static int nxt6000_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *param)
{
- struct nxt6000_state* state = (struct nxt6000_state*) fe->demodulator_priv;
+ struct nxt6000_state* state = fe->demodulator_priv;
int result;
nxt6000_writereg(state, ENABLE_TUNER_IIC, 0x01); /* open i2c bus switch */
@@ -482,10 +487,44 @@ static int nxt6000_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
static void nxt6000_release(struct dvb_frontend* fe)
{
- struct nxt6000_state* state = (struct nxt6000_state*) fe->demodulator_priv;
+ struct nxt6000_state* state = fe->demodulator_priv;
kfree(state);
}
+static int nxt6000_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+ struct nxt6000_state* state = fe->demodulator_priv;
+
+ *snr = nxt6000_readreg( state, OFDM_CHC_SNR) / 8;
+
+ return 0;
+}
+
+static int nxt6000_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+ struct nxt6000_state* state = fe->demodulator_priv;
+
+ nxt6000_writereg( state, VIT_COR_INTSTAT, 0x18 );
+
+ *ber = (nxt6000_readreg( state, VIT_BER_1 ) << 8 ) |
+ nxt6000_readreg( state, VIT_BER_0 );
+
+ nxt6000_writereg( state, VIT_COR_INTSTAT, 0x18); // Clear BER Done interrupts
+
+ return 0;
+}
+
+static int nxt6000_read_signal_strength(struct dvb_frontend* fe, u16* signal_strength)
+{
+ struct nxt6000_state* state = fe->demodulator_priv;
+
+ *signal_strength = (short) (511 -
+ (nxt6000_readreg(state, AGC_GAIN_1) +
+ ((nxt6000_readreg(state, AGC_GAIN_2) & 0x03) << 8)));
+
+ return 0;
+}
+
static struct dvb_frontend_ops nxt6000_ops;
struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
@@ -494,7 +533,7 @@ struct dvb_frontend* nxt6000_attach(const struct nxt6000_config* config,
struct nxt6000_state* state = NULL;
/* allocate memory for the internal state */
- state = (struct nxt6000_state*) kmalloc(sizeof(struct nxt6000_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct nxt6000_state), GFP_KERNEL);
if (state == NULL) goto error;
/* setup the state */
@@ -542,6 +581,9 @@ static struct dvb_frontend_ops nxt6000_ops = {
.set_frontend = nxt6000_set_frontend,
.read_status = nxt6000_read_status,
+ .read_ber = nxt6000_read_ber,
+ .read_signal_strength = nxt6000_read_signal_strength,
+ .read_snr = nxt6000_read_snr,
};
module_param(debug, int, 0644);
diff --git a/drivers/media/dvb/frontends/nxt6000_priv.h b/drivers/media/dvb/frontends/nxt6000_priv.h
index 64b1a89b2a2..0422e580038 100644
--- a/drivers/media/dvb/frontends/nxt6000_priv.h
+++ b/drivers/media/dvb/frontends/nxt6000_priv.h
@@ -65,12 +65,27 @@
#define BER_DONE (0x08)
#define BER_OVERFLOW (0x10)
+/* 0x38 VIT_BERTIME_2 */
+#define VIT_BERTIME_2 (0x38)
+
+/* 0x39 VIT_BERTIME_1 */
+#define VIT_BERTIME_1 (0x39)
+
+/* 0x3A VIT_BERTIME_0 */
+#define VIT_BERTIME_0 (0x3a)
+
/* 0x38 OFDM_BERTimer *//* Use the alias registers */
#define A_VIT_BER_TIMER_0 (0x1D)
/* 0x3A VIT_BER_TIMER_0 *//* Use the alias registers */
#define A_VIT_BER_0 (0x1B)
+/* 0x3B VIT_BER_1 */
+#define VIT_BER_1 (0x3b)
+
+/* 0x3C VIT_BER_0 */
+#define VIT_BER_0 (0x3c)
+
/* 0x40 OFDM_COR_CTL */
#define OFDM_COR_CTL (0x40)
#define COREACT (0x20)
@@ -117,6 +132,12 @@
#define OFDM_ITB_CTL (0x4B)
#define ITBINV (0x01)
+/* 0x49 AGC_GAIN_1 */
+#define AGC_GAIN_1 (0x49)
+
+/* 0x4A AGC_GAIN_2 */
+#define AGC_GAIN_2 (0x4A)
+
/* 0x4C OFDM_ITB_FREQ_1 */
#define OFDM_ITB_FREQ_1 (0x4C)
diff --git a/drivers/media/dvb/frontends/or51132.c b/drivers/media/dvb/frontends/or51132.c
index df5dee7760a..cc0a77c790f 100644
--- a/drivers/media/dvb/frontends/or51132.c
+++ b/drivers/media/dvb/frontends/or51132.c
@@ -102,7 +102,7 @@ static u8 i2c_readbytes (struct or51132_state* state, u8 reg, u8* buf, int len)
static int or51132_load_firmware (struct dvb_frontend* fe, const struct firmware *fw)
{
- struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv;
+ struct or51132_state* state = fe->demodulator_priv;
static u8 run_buf[] = {0x7F,0x01};
static u8 get_ver_buf[] = {0x04,0x00,0x30,0x00,0x00};
u8 rec_buf[14];
@@ -240,7 +240,7 @@ static int or51132_sleep(struct dvb_frontend* fe)
static int or51132_setmode(struct dvb_frontend* fe)
{
- struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv;
+ struct or51132_state* state = fe->demodulator_priv;
unsigned char cmd_buf[4];
dprintk("setmode %d\n",(int)state->current_modulation);
@@ -316,7 +316,7 @@ static int or51132_set_parameters(struct dvb_frontend* fe,
{
int ret;
u8 buf[4];
- struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv;
+ struct or51132_state* state = fe->demodulator_priv;
const struct firmware *fw;
/* Change only if we are actually changing the modulation */
@@ -391,7 +391,7 @@ static int or51132_set_parameters(struct dvb_frontend* fe,
static int or51132_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
- struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv;
+ struct or51132_state* state = fe->demodulator_priv;
unsigned char rec_buf[2];
unsigned char snd_buf[2];
*status = 0;
@@ -464,7 +464,7 @@ static unsigned int i20Log10(unsigned short val)
static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
- struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv;
+ struct or51132_state* state = fe->demodulator_priv;
unsigned char rec_buf[2];
unsigned char snd_buf[2];
u8 rcvr_stat;
@@ -512,7 +512,7 @@ static int or51132_read_signal_strength(struct dvb_frontend* fe, u16* strength)
static int or51132_read_snr(struct dvb_frontend* fe, u16* snr)
{
- struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv;
+ struct or51132_state* state = fe->demodulator_priv;
unsigned char rec_buf[2];
unsigned char snd_buf[2];
u16 snr_equ;
@@ -549,7 +549,7 @@ static int or51132_get_tune_settings(struct dvb_frontend* fe, struct dvb_fronten
static void or51132_release(struct dvb_frontend* fe)
{
- struct or51132_state* state = (struct or51132_state*) fe->demodulator_priv;
+ struct or51132_state* state = fe->demodulator_priv;
kfree(state);
}
diff --git a/drivers/media/dvb/frontends/sp8870.c b/drivers/media/dvb/frontends/sp8870.c
index 58ad34ef0a0..764a95a2e21 100644
--- a/drivers/media/dvb/frontends/sp8870.c
+++ b/drivers/media/dvb/frontends/sp8870.c
@@ -248,7 +248,7 @@ static int sp8870_wake_up(struct sp8870_state* state)
static int sp8870_set_frontend_parameters (struct dvb_frontend* fe,
struct dvb_frontend_parameters *p)
{
- struct sp8870_state* state = (struct sp8870_state*) fe->demodulator_priv;
+ struct sp8870_state* state = fe->demodulator_priv;
int err;
u16 reg0xc05;
@@ -302,7 +302,7 @@ static int sp8870_set_frontend_parameters (struct dvb_frontend* fe,
static int sp8870_init (struct dvb_frontend* fe)
{
- struct sp8870_state* state = (struct sp8870_state*) fe->demodulator_priv;
+ struct sp8870_state* state = fe->demodulator_priv;
const struct firmware *fw = NULL;
sp8870_wake_up(state);
@@ -358,7 +358,7 @@ static int sp8870_init (struct dvb_frontend* fe)
static int sp8870_read_status (struct dvb_frontend* fe, fe_status_t * fe_status)
{
- struct sp8870_state* state = (struct sp8870_state*) fe->demodulator_priv;
+ struct sp8870_state* state = fe->demodulator_priv;
int status;
int signal;
@@ -384,7 +384,7 @@ static int sp8870_read_status (struct dvb_frontend* fe, fe_status_t * fe_status)
static int sp8870_read_ber (struct dvb_frontend* fe, u32 * ber)
{
- struct sp8870_state* state = (struct sp8870_state*) fe->demodulator_priv;
+ struct sp8870_state* state = fe->demodulator_priv;
int ret;
u32 tmp;
@@ -412,7 +412,7 @@ static int sp8870_read_ber (struct dvb_frontend* fe, u32 * ber)
static int sp8870_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
{
- struct sp8870_state* state = (struct sp8870_state*) fe->demodulator_priv;
+ struct sp8870_state* state = fe->demodulator_priv;
int ret;
u16 tmp;
@@ -438,7 +438,7 @@ static int sp8870_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
static int sp8870_read_uncorrected_blocks (struct dvb_frontend* fe, u32* ublocks)
{
- struct sp8870_state* state = (struct sp8870_state*) fe->demodulator_priv;
+ struct sp8870_state* state = fe->demodulator_priv;
int ret;
*ublocks = 0;
@@ -467,7 +467,7 @@ static int switches = 0;
static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
- struct sp8870_state* state = (struct sp8870_state*) fe->demodulator_priv;
+ struct sp8870_state* state = fe->demodulator_priv;
/*
The firmware of the sp8870 sometimes locks up after setting frontend parameters.
@@ -524,7 +524,7 @@ static int sp8870_set_frontend (struct dvb_frontend* fe, struct dvb_frontend_par
static int sp8870_sleep(struct dvb_frontend* fe)
{
- struct sp8870_state* state = (struct sp8870_state*) fe->demodulator_priv;
+ struct sp8870_state* state = fe->demodulator_priv;
// tristate TS output and disable interface pins
return sp8870_writereg(state, 0xC18, 0x000);
@@ -540,7 +540,7 @@ static int sp8870_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend
static void sp8870_release(struct dvb_frontend* fe)
{
- struct sp8870_state* state = (struct sp8870_state*) fe->demodulator_priv;
+ struct sp8870_state* state = fe->demodulator_priv;
kfree(state);
}
@@ -552,7 +552,7 @@ struct dvb_frontend* sp8870_attach(const struct sp8870_config* config,
struct sp8870_state* state = NULL;
/* allocate memory for the internal state */
- state = (struct sp8870_state*) kmalloc(sizeof(struct sp8870_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct sp8870_state), GFP_KERNEL);
if (state == NULL) goto error;
/* setup the state */
diff --git a/drivers/media/dvb/frontends/sp887x.c b/drivers/media/dvb/frontends/sp887x.c
index 7eae833ece4..d868a6927a1 100644
--- a/drivers/media/dvb/frontends/sp887x.c
+++ b/drivers/media/dvb/frontends/sp887x.c
@@ -135,7 +135,7 @@ static void sp887x_setup_agc (struct sp887x_state* state)
*/
static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware *fw)
{
- struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv;
+ struct sp887x_state* state = fe->demodulator_priv;
u8 buf [BLOCKSIZE+2];
int i;
int fw_size = fw->size;
@@ -344,7 +344,7 @@ static void sp887x_correct_offsets (struct sp887x_state* state,
static int sp887x_setup_frontend_parameters (struct dvb_frontend* fe,
struct dvb_frontend_parameters *p)
{
- struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv;
+ struct sp887x_state* state = fe->demodulator_priv;
int actual_freq, err;
u16 val, reg0xc05;
@@ -405,7 +405,7 @@ static int sp887x_setup_frontend_parameters (struct dvb_frontend* fe,
static int sp887x_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
- struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv;
+ struct sp887x_state* state = fe->demodulator_priv;
u16 snr12 = sp887x_readreg(state, 0xf16);
u16 sync0x200 = sp887x_readreg(state, 0x200);
u16 sync0xf17 = sp887x_readreg(state, 0xf17);
@@ -439,7 +439,7 @@ static int sp887x_read_status(struct dvb_frontend* fe, fe_status_t* status)
static int sp887x_read_ber(struct dvb_frontend* fe, u32* ber)
{
- struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv;
+ struct sp887x_state* state = fe->demodulator_priv;
*ber = (sp887x_readreg(state, 0xc08) & 0x3f) |
(sp887x_readreg(state, 0xc07) << 6);
@@ -453,7 +453,7 @@ static int sp887x_read_ber(struct dvb_frontend* fe, u32* ber)
static int sp887x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
- struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv;
+ struct sp887x_state* state = fe->demodulator_priv;
u16 snr12 = sp887x_readreg(state, 0xf16);
u32 signal = 3 * (snr12 << 4);
@@ -464,7 +464,7 @@ static int sp887x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
static int sp887x_read_snr(struct dvb_frontend* fe, u16* snr)
{
- struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv;
+ struct sp887x_state* state = fe->demodulator_priv;
u16 snr12 = sp887x_readreg(state, 0xf16);
*snr = (snr12 << 4) | (snr12 >> 8);
@@ -474,7 +474,7 @@ static int sp887x_read_snr(struct dvb_frontend* fe, u16* snr)
static int sp887x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
- struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv;
+ struct sp887x_state* state = fe->demodulator_priv;
*ucblocks = sp887x_readreg(state, 0xc0c);
if (*ucblocks == 0xfff)
@@ -485,7 +485,7 @@ static int sp887x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
static int sp887x_sleep(struct dvb_frontend* fe)
{
- struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv;
+ struct sp887x_state* state = fe->demodulator_priv;
/* tristate TS output and disable interface pins */
sp887x_writereg(state, 0xc18, 0x000);
@@ -495,7 +495,7 @@ static int sp887x_sleep(struct dvb_frontend* fe)
static int sp887x_init(struct dvb_frontend* fe)
{
- struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv;
+ struct sp887x_state* state = fe->demodulator_priv;
const struct firmware *fw = NULL;
int ret;
@@ -534,7 +534,7 @@ static int sp887x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend
static void sp887x_release(struct dvb_frontend* fe)
{
- struct sp887x_state* state = (struct sp887x_state*) fe->demodulator_priv;
+ struct sp887x_state* state = fe->demodulator_priv;
kfree(state);
}
@@ -546,7 +546,7 @@ struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
struct sp887x_state* state = NULL;
/* allocate memory for the internal state */
- state = (struct sp887x_state*) kmalloc(sizeof(struct sp887x_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct sp887x_state), GFP_KERNEL);
if (state == NULL) goto error;
/* setup the state */
diff --git a/drivers/media/dvb/frontends/stv0297.c b/drivers/media/dvb/frontends/stv0297.c
index 502c6403dfc..e681263bf07 100644
--- a/drivers/media/dvb/frontends/stv0297.c
+++ b/drivers/media/dvb/frontends/stv0297.c
@@ -365,7 +365,7 @@ static int stv0297_set_inversion(struct stv0297_state *state, fe_spectral_invers
int stv0297_enable_plli2c(struct dvb_frontend *fe)
{
- struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv;
+ struct stv0297_state *state = fe->demodulator_priv;
stv0297_writereg(state, 0x87, 0x78);
stv0297_writereg(state, 0x86, 0xc8);
@@ -375,7 +375,7 @@ int stv0297_enable_plli2c(struct dvb_frontend *fe)
static int stv0297_init(struct dvb_frontend *fe)
{
- struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv;
+ struct stv0297_state *state = fe->demodulator_priv;
int i;
/* soft reset */
@@ -416,7 +416,7 @@ static int stv0297_init(struct dvb_frontend *fe)
static int stv0297_sleep(struct dvb_frontend *fe)
{
- struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv;
+ struct stv0297_state *state = fe->demodulator_priv;
stv0297_writereg_mask(state, 0x80, 1, 1);
@@ -425,7 +425,7 @@ static int stv0297_sleep(struct dvb_frontend *fe)
static int stv0297_read_status(struct dvb_frontend *fe, fe_status_t * status)
{
- struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv;
+ struct stv0297_state *state = fe->demodulator_priv;
u8 sync = stv0297_readreg(state, 0xDF);
@@ -438,7 +438,7 @@ static int stv0297_read_status(struct dvb_frontend *fe, fe_status_t * status)
static int stv0297_read_ber(struct dvb_frontend *fe, u32 * ber)
{
- struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv;
+ struct stv0297_state *state = fe->demodulator_priv;
u8 BER[3];
stv0297_writereg(state, 0xA0, 0x80); // Start Counting bit errors for 4096 Bytes
@@ -453,7 +453,7 @@ static int stv0297_read_ber(struct dvb_frontend *fe, u32 * ber)
static int stv0297_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
{
- struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv;
+ struct stv0297_state *state = fe->demodulator_priv;
u8 STRENGTH[2];
stv0297_readregs(state, 0x41, STRENGTH, 2);
@@ -464,7 +464,7 @@ static int stv0297_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
static int stv0297_read_snr(struct dvb_frontend *fe, u16 * snr)
{
- struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv;
+ struct stv0297_state *state = fe->demodulator_priv;
u8 SNR[2];
stv0297_readregs(state, 0x07, SNR, 2);
@@ -475,7 +475,7 @@ static int stv0297_read_snr(struct dvb_frontend *fe, u16 * snr)
static int stv0297_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks)
{
- struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv;
+ struct stv0297_state *state = fe->demodulator_priv;
*ucblocks = (stv0297_readreg(state, 0xD5) << 8)
| stv0297_readreg(state, 0xD4);
@@ -485,7 +485,7 @@ static int stv0297_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks)
static int stv0297_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
{
- struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv;
+ struct stv0297_state *state = fe->demodulator_priv;
int u_threshold;
int initial_u;
int blind_u;
@@ -689,7 +689,7 @@ timeout:
static int stv0297_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
{
- struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv;
+ struct stv0297_state *state = fe->demodulator_priv;
int reg_00, reg_83;
reg_00 = stv0297_readreg(state, 0x00);
@@ -725,7 +725,7 @@ static int stv0297_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_par
static void stv0297_release(struct dvb_frontend *fe)
{
- struct stv0297_state *state = (struct stv0297_state *) fe->demodulator_priv;
+ struct stv0297_state *state = fe->demodulator_priv;
kfree(state);
}
@@ -737,7 +737,7 @@ struct dvb_frontend *stv0297_attach(const struct stv0297_config *config,
struct stv0297_state *state = NULL;
/* allocate memory for the internal state */
- state = (struct stv0297_state *) kmalloc(sizeof(struct stv0297_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct stv0297_state), GFP_KERNEL);
if (state == NULL)
goto error;
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c
index 15b40541b62..cfa3928bb48 100644
--- a/drivers/media/dvb/frontends/stv0299.c
+++ b/drivers/media/dvb/frontends/stv0299.c
@@ -70,6 +70,7 @@ struct stv0299_state {
#define STATUS_UCBLOCKS 1
static int debug;
+static int debug_legacy_dish_switch;
#define dprintk(args...) \
do { \
if (debug) printk(KERN_DEBUG "stv0299: " args); \
@@ -93,7 +94,7 @@ static int stv0299_writeregI (struct stv0299_state* state, u8 reg, u8 data)
int stv0299_writereg (struct dvb_frontend* fe, u8 reg, u8 data)
{
- struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
+ struct stv0299_state* state = fe->demodulator_priv;
return stv0299_writeregI(state, reg, data);
}
@@ -218,7 +219,7 @@ static int stv0299_wait_diseqc_idle (struct stv0299_state* state, int timeout)
static int stv0299_set_symbolrate (struct dvb_frontend* fe, u32 srate)
{
- struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
+ struct stv0299_state* state = fe->demodulator_priv;
u64 big = srate;
u32 ratio;
@@ -269,7 +270,7 @@ static int stv0299_get_symbolrate (struct stv0299_state* state)
static int stv0299_send_diseqc_msg (struct dvb_frontend* fe,
struct dvb_diseqc_master_cmd *m)
{
- struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
+ struct stv0299_state* state = fe->demodulator_priv;
u8 val;
int i;
@@ -299,7 +300,7 @@ static int stv0299_send_diseqc_msg (struct dvb_frontend* fe,
static int stv0299_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
{
- struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
+ struct stv0299_state* state = fe->demodulator_priv;
u8 val;
dprintk ("%s\n", __FUNCTION__);
@@ -326,7 +327,7 @@ static int stv0299_send_diseqc_burst (struct dvb_frontend* fe, fe_sec_mini_cmd_t
static int stv0299_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
{
- struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
+ struct stv0299_state* state = fe->demodulator_priv;
u8 val;
if (stv0299_wait_diseqc_idle (state, 100) < 0)
@@ -348,7 +349,7 @@ static int stv0299_set_tone (struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
{
- struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
+ struct stv0299_state* state = fe->demodulator_priv;
u8 reg0x08;
u8 reg0x0c;
@@ -385,34 +386,84 @@ static int stv0299_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
};
}
-static int stv0299_send_legacy_dish_cmd(struct dvb_frontend* fe, u32 cmd)
+static inline s32 stv0299_calc_usec_delay (struct timeval lasttime, struct timeval curtime)
{
+ return ((curtime.tv_usec < lasttime.tv_usec) ?
+ 1000000 - lasttime.tv_usec + curtime.tv_usec :
+ curtime.tv_usec - lasttime.tv_usec);
+}
+
+static void stv0299_sleep_until (struct timeval *waketime, u32 add_usec)
+{
+ struct timeval lasttime;
+ s32 delta, newdelta;
+
+ waketime->tv_usec += add_usec;
+ if (waketime->tv_usec >= 1000000) {
+ waketime->tv_usec -= 1000000;
+ waketime->tv_sec++;
+ }
+
+ do_gettimeofday (&lasttime);
+ delta = stv0299_calc_usec_delay (lasttime, *waketime);
+ if (delta > 2500) {
+ msleep ((delta - 1500) / 1000);
+ do_gettimeofday (&lasttime);
+ newdelta = stv0299_calc_usec_delay (lasttime, *waketime);
+ delta = (newdelta > delta) ? 0 : newdelta;
+ }
+ if (delta > 0)
+ udelay (delta);
+}
+
+static int stv0299_send_legacy_dish_cmd (struct dvb_frontend* fe, u32 cmd)
+{
+ struct stv0299_state* state = fe->demodulator_priv;
+ u8 reg0x08;
+ u8 reg0x0c;
+ u8 lv_mask = 0x40;
u8 last = 1;
int i;
+ struct timeval nexttime;
+ struct timeval tv[10];
- /* reset voltage at the end
- if((0x50 & stv0299_readreg (i2c, 0x0c)) == 0x50)
- cmd |= 0x80;
- else
- cmd &= 0x7F;
- */
+ reg0x08 = stv0299_readreg (state, 0x08);
+ reg0x0c = stv0299_readreg (state, 0x0c);
+ reg0x0c &= 0x0f;
+ stv0299_writeregI (state, 0x08, (reg0x08 & 0x3f) | (state->config->lock_output << 6));
+ if (state->config->volt13_op0_op1 == STV0299_VOLT13_OP0)
+ lv_mask = 0x10;
cmd = cmd << 1;
- dprintk("%s switch command: 0x%04x\n",__FUNCTION__, cmd);
+ if (debug_legacy_dish_switch)
+ printk ("%s switch command: 0x%04x\n",__FUNCTION__, cmd);
+
+ do_gettimeofday (&nexttime);
+ if (debug_legacy_dish_switch)
+ memcpy (&tv[0], &nexttime, sizeof (struct timeval));
+ stv0299_writeregI (state, 0x0c, reg0x0c | 0x50); /* set LNB to 18V */
- stv0299_set_voltage(fe,SEC_VOLTAGE_18);
- msleep(32);
+ stv0299_sleep_until (&nexttime, 32000);
for (i=0; i<9; i++) {
+ if (debug_legacy_dish_switch)
+ do_gettimeofday (&tv[i+1]);
if((cmd & 0x01) != last) {
- stv0299_set_voltage(fe, last ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18);
+ /* set voltage to (last ? 13V : 18V) */
+ stv0299_writeregI (state, 0x0c, reg0x0c | (last ? lv_mask : 0x50));
last = (last) ? 0 : 1;
}
cmd = cmd >> 1;
if (i != 8)
- msleep(8);
+ stv0299_sleep_until (&nexttime, 8000);
+ }
+ if (debug_legacy_dish_switch) {
+ printk ("%s(%d): switch delay (should be 32k followed by all 8k\n",
+ __FUNCTION__, fe->dvb->num);
+ for (i=1; i < 10; i++)
+ printk ("%d: %d\n", i, stv0299_calc_usec_delay (tv[i-1] , tv[i]));
}
return 0;
@@ -420,7 +471,7 @@ static int stv0299_send_legacy_dish_cmd(struct dvb_frontend* fe, u32 cmd)
static int stv0299_init (struct dvb_frontend* fe)
{
- struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
+ struct stv0299_state* state = fe->demodulator_priv;
int i;
dprintk("stv0299: init chip\n");
@@ -439,7 +490,7 @@ static int stv0299_init (struct dvb_frontend* fe)
static int stv0299_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
- struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
+ struct stv0299_state* state = fe->demodulator_priv;
u8 signal = 0xff - stv0299_readreg (state, 0x18);
u8 sync = stv0299_readreg (state, 0x1b);
@@ -467,7 +518,7 @@ static int stv0299_read_status(struct dvb_frontend* fe, fe_status_t* status)
static int stv0299_read_ber(struct dvb_frontend* fe, u32* ber)
{
- struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
+ struct stv0299_state* state = fe->demodulator_priv;
if (state->errmode != STATUS_BER) return 0;
*ber = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e);
@@ -477,7 +528,7 @@ static int stv0299_read_ber(struct dvb_frontend* fe, u32* ber)
static int stv0299_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
- struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
+ struct stv0299_state* state = fe->demodulator_priv;
s32 signal = 0xffff - ((stv0299_readreg (state, 0x18) << 8)
| stv0299_readreg (state, 0x19));
@@ -494,7 +545,7 @@ static int stv0299_read_signal_strength(struct dvb_frontend* fe, u16* strength)
static int stv0299_read_snr(struct dvb_frontend* fe, u16* snr)
{
- struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
+ struct stv0299_state* state = fe->demodulator_priv;
s32 xsnr = 0xffff - ((stv0299_readreg (state, 0x24) << 8)
| stv0299_readreg (state, 0x25));
@@ -506,7 +557,7 @@ static int stv0299_read_snr(struct dvb_frontend* fe, u16* snr)
static int stv0299_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
- struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
+ struct stv0299_state* state = fe->demodulator_priv;
if (state->errmode != STATUS_UCBLOCKS) *ucblocks = 0;
else *ucblocks = (stv0299_readreg (state, 0x1d) << 8) | stv0299_readreg (state, 0x1e);
@@ -516,7 +567,7 @@ static int stv0299_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters * p)
{
- struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
+ struct stv0299_state* state = fe->demodulator_priv;
int invval = 0;
dprintk ("%s : FE_SET_FRONTEND\n", __FUNCTION__);
@@ -584,7 +635,7 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
static int stv0299_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters * p)
{
- struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
+ struct stv0299_state* state = fe->demodulator_priv;
s32 derot_freq;
int invval;
@@ -609,7 +660,7 @@ static int stv0299_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
static int stv0299_sleep(struct dvb_frontend* fe)
{
- struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
+ struct stv0299_state* state = fe->demodulator_priv;
stv0299_writeregI(state, 0x02, 0x80);
state->initialised = 0;
@@ -619,7 +670,7 @@ static int stv0299_sleep(struct dvb_frontend* fe)
static int stv0299_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
{
- struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
+ struct stv0299_state* state = fe->demodulator_priv;
fesettings->min_delay_ms = state->config->min_delay_ms;
if (fesettings->parameters.u.qpsk.symbol_rate < 10000000) {
@@ -634,7 +685,7 @@ static int stv0299_get_tune_settings(struct dvb_frontend* fe, struct dvb_fronten
static void stv0299_release(struct dvb_frontend* fe)
{
- struct stv0299_state* state = (struct stv0299_state*) fe->demodulator_priv;
+ struct stv0299_state* state = fe->demodulator_priv;
kfree(state);
}
@@ -647,7 +698,7 @@ struct dvb_frontend* stv0299_attach(const struct stv0299_config* config,
int id;
/* allocate memory for the internal state */
- state = (struct stv0299_state*) kmalloc(sizeof(struct stv0299_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct stv0299_state), GFP_KERNEL);
if (state == NULL) goto error;
/* setup the state */
@@ -719,6 +770,9 @@ static struct dvb_frontend_ops stv0299_ops = {
.dishnetwork_send_legacy_command = stv0299_send_legacy_dish_cmd,
};
+module_param(debug_legacy_dish_switch, int, 0444);
+MODULE_PARM_DESC(debug_legacy_dish_switch, "Enable timing analysis for Dish Network legacy switches");
+
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c
index 4e40d95ee95..87d5f4d8790 100644
--- a/drivers/media/dvb/frontends/tda10021.c
+++ b/drivers/media/dvb/frontends/tda10021.c
@@ -205,7 +205,7 @@ static int tda10021_set_symbolrate (struct tda10021_state* state, u32 symbolrate
static int tda10021_init (struct dvb_frontend *fe)
{
- struct tda10021_state* state = (struct tda10021_state*) fe->demodulator_priv;
+ struct tda10021_state* state = fe->demodulator_priv;
int i;
dprintk("DVB: TDA10021(%d): init chip\n", fe->adapter->num);
@@ -238,7 +238,7 @@ static int tda10021_init (struct dvb_frontend *fe)
static int tda10021_set_parameters (struct dvb_frontend *fe,
struct dvb_frontend_parameters *p)
{
- struct tda10021_state* state = (struct tda10021_state*) fe->demodulator_priv;
+ struct tda10021_state* state = fe->demodulator_priv;
//table for QAM4-QAM256 ready QAM4 QAM16 QAM32 QAM64 QAM128 QAM256
//CONF
@@ -278,7 +278,7 @@ static int tda10021_set_parameters (struct dvb_frontend *fe,
static int tda10021_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
- struct tda10021_state* state = (struct tda10021_state*) fe->demodulator_priv;
+ struct tda10021_state* state = fe->demodulator_priv;
int sync;
*status = 0;
@@ -303,7 +303,7 @@ static int tda10021_read_status(struct dvb_frontend* fe, fe_status_t* status)
static int tda10021_read_ber(struct dvb_frontend* fe, u32* ber)
{
- struct tda10021_state* state = (struct tda10021_state*) fe->demodulator_priv;
+ struct tda10021_state* state = fe->demodulator_priv;
u32 _ber = tda10021_readreg(state, 0x14) |
(tda10021_readreg(state, 0x15) << 8) |
@@ -315,7 +315,7 @@ static int tda10021_read_ber(struct dvb_frontend* fe, u32* ber)
static int tda10021_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
- struct tda10021_state* state = (struct tda10021_state*) fe->demodulator_priv;
+ struct tda10021_state* state = fe->demodulator_priv;
u8 gain = tda10021_readreg(state, 0x17);
*strength = (gain << 8) | gain;
@@ -325,7 +325,7 @@ static int tda10021_read_signal_strength(struct dvb_frontend* fe, u16* strength)
static int tda10021_read_snr(struct dvb_frontend* fe, u16* snr)
{
- struct tda10021_state* state = (struct tda10021_state*) fe->demodulator_priv;
+ struct tda10021_state* state = fe->demodulator_priv;
u8 quality = ~tda10021_readreg(state, 0x18);
*snr = (quality << 8) | quality;
@@ -335,7 +335,7 @@ static int tda10021_read_snr(struct dvb_frontend* fe, u16* snr)
static int tda10021_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
- struct tda10021_state* state = (struct tda10021_state*) fe->demodulator_priv;
+ struct tda10021_state* state = fe->demodulator_priv;
*ucblocks = tda10021_readreg (state, 0x13) & 0x7f;
if (*ucblocks == 0x7f)
@@ -350,7 +350,7 @@ static int tda10021_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
static int tda10021_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
- struct tda10021_state* state = (struct tda10021_state*) fe->demodulator_priv;
+ struct tda10021_state* state = fe->demodulator_priv;
int sync;
s8 afc = 0;
@@ -378,7 +378,7 @@ static int tda10021_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_pa
static int tda10021_sleep(struct dvb_frontend* fe)
{
- struct tda10021_state* state = (struct tda10021_state*) fe->demodulator_priv;
+ struct tda10021_state* state = fe->demodulator_priv;
tda10021_writereg (state, 0x1b, 0x02); /* pdown ADC */
tda10021_writereg (state, 0x00, 0x80); /* standby */
@@ -388,7 +388,7 @@ static int tda10021_sleep(struct dvb_frontend* fe)
static void tda10021_release(struct dvb_frontend* fe)
{
- struct tda10021_state* state = (struct tda10021_state*) fe->demodulator_priv;
+ struct tda10021_state* state = fe->demodulator_priv;
kfree(state);
}
@@ -401,7 +401,7 @@ struct dvb_frontend* tda10021_attach(const struct tda10021_config* config,
struct tda10021_state* state = NULL;
/* allocate memory for the internal state */
- state = (struct tda10021_state*) kmalloc(sizeof(struct tda10021_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct tda10021_state), GFP_KERNEL);
if (state == NULL) goto error;
/* setup the state */
diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
index 687ad9cf338..0beb370792a 100644
--- a/drivers/media/dvb/frontends/tda1004x.c
+++ b/drivers/media/dvb/frontends/tda1004x.c
@@ -35,9 +35,10 @@
#include "dvb_frontend.h"
#include "tda1004x.h"
-#define TDA1004X_DEMOD_TDA10045 0
-#define TDA1004X_DEMOD_TDA10046 1
-
+enum tda1004x_demod {
+ TDA1004X_DEMOD_TDA10045,
+ TDA1004X_DEMOD_TDA10046,
+};
struct tda1004x_state {
struct i2c_adapter* i2c;
@@ -46,8 +47,9 @@ struct tda1004x_state {
struct dvb_frontend frontend;
/* private demod data */
- u8 initialised:1;
- u8 demod_type;
+ u8 initialised;
+ enum tda1004x_demod demod_type;
+ u8 fw_version;
};
@@ -139,7 +141,7 @@ static int tda1004x_write_byteI(struct tda1004x_state *state, int reg, int data)
{
int ret;
u8 buf[] = { reg, data };
- struct i2c_msg msg = { .addr=0, .flags=0, .buf=buf, .len=2 };
+ struct i2c_msg msg = { .flags = 0, .buf = buf, .len = 2 };
dprintk("%s: reg=0x%x, data=0x%x\n", __FUNCTION__, reg, data);
@@ -160,8 +162,8 @@ static int tda1004x_read_byte(struct tda1004x_state *state, int reg)
int ret;
u8 b0[] = { reg };
u8 b1[] = { 0 };
- struct i2c_msg msg[] = {{ .addr=0, .flags=0, .buf=b0, .len=1},
- { .addr=0, .flags=I2C_M_RD, .buf=b1, .len = 1}};
+ struct i2c_msg msg[] = {{ .flags = 0, .buf = b0, .len = 1 },
+ { .flags = I2C_M_RD, .buf = b1, .len = 1 }};
dprintk("%s: reg=0x%x\n", __FUNCTION__, reg);
@@ -294,7 +296,7 @@ static int tda1004x_do_upload(struct tda1004x_state *state,
u8 dspCodeCounterReg, u8 dspCodeInReg)
{
u8 buf[65];
- struct i2c_msg fw_msg = {.addr = 0,.flags = 0,.buf = buf,.len = 0 };
+ struct i2c_msg fw_msg = { .flags = 0, .buf = buf, .len = 0 };
int tx_size;
int pos = 0;
@@ -304,12 +306,10 @@ static int tda1004x_do_upload(struct tda1004x_state *state,
buf[0] = dspCodeInReg;
while (pos != len) {
-
// work out how much to send this time
tx_size = len - pos;
- if (tx_size > 0x10) {
+ if (tx_size > 0x10)
tx_size = 0x10;
- }
// send the chunk
memcpy(buf + 1, mem + pos, tx_size);
@@ -322,6 +322,7 @@ static int tda1004x_do_upload(struct tda1004x_state *state,
dprintk("%s: fw_pos=0x%x\n", __FUNCTION__, pos);
}
+
return 0;
}
@@ -335,9 +336,8 @@ static int tda1004x_check_upload_ok(struct tda1004x_state *state, u8 dspVersion)
data1 = tda1004x_read_byte(state, TDA1004X_DSP_DATA1);
data2 = tda1004x_read_byte(state, TDA1004X_DSP_DATA2);
- if (data1 != 0x67 || data2 != dspVersion) {
+ if ((data1 != 0x67) || (data2 != dspVersion))
return -EIO;
- }
return 0;
}
@@ -348,9 +348,9 @@ static int tda10045_fwupload(struct dvb_frontend* fe)
int ret;
const struct firmware *fw;
-
/* don't re-upload unless necessary */
- if (tda1004x_check_upload_ok(state, 0x2c) == 0) return 0;
+ if (tda1004x_check_upload_ok(state, 0x2c) == 0)
+ return 0;
/* request the firmware, this will block until someone uploads it */
printk("tda1004x: waiting for firmware upload (%s)...\n", TDA10045_DEFAULT_FIRMWARE);
@@ -381,6 +381,25 @@ static int tda10045_fwupload(struct dvb_frontend* fe)
return tda1004x_check_upload_ok(state, 0x2c);
}
+static int tda10046_get_fw_version(struct tda1004x_state *state,
+ const struct firmware *fw)
+{
+ const unsigned char pattern[] = { 0x67, 0x00, 0x50, 0x62, 0x5e, 0x18, 0x67 };
+ unsigned int i;
+
+ /* area guessed from firmware v20, v21 and v25 */
+ for (i = 0x660; i < 0x700; i++) {
+ if (!memcmp(&fw->data[i], pattern, sizeof(pattern))) {
+ state->fw_version = fw->data[i + sizeof(pattern)];
+ printk(KERN_INFO "tda1004x: using firmware v%02x\n",
+ state->fw_version);
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
static int tda10046_fwupload(struct dvb_frontend* fe)
{
struct tda1004x_state* state = fe->demodulator_priv;
@@ -394,7 +413,8 @@ static int tda10046_fwupload(struct dvb_frontend* fe)
msleep(100);
/* don't re-upload unless necessary */
- if (tda1004x_check_upload_ok(state, 0x20) == 0) return 0;
+ if (tda1004x_check_upload_ok(state, state->fw_version) == 0)
+ return 0;
/* request the firmware, this will block until someone uploads it */
printk("tda1004x: waiting for firmware upload (%s)...\n", TDA10046_DEFAULT_FIRMWARE);
@@ -404,9 +424,20 @@ static int tda10046_fwupload(struct dvb_frontend* fe)
return ret;
}
+ if (fw->size < 24478) { /* size of firmware v20, which is the smallest of v20, v21 and v25 */
+ printk("tda1004x: firmware file seems to be too small (%d bytes)\n", fw->size);
+ return -EINVAL;
+ }
+
+ ret = tda10046_get_fw_version(state, fw);
+ if (ret < 0) {
+ printk("tda1004x: unable to find firmware version\n");
+ return ret;
+ }
+
/* set parameters */
tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 10);
- tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0);
+ tda1004x_write_byteI(state, TDA10046H_CONFPLL3, state->config->n_i2c);
tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 99);
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd4);
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x2c);
@@ -419,7 +450,7 @@ static int tda10046_fwupload(struct dvb_frontend* fe)
/* wait for DSP to initialise */
timeout = jiffies + HZ;
- while(!(tda1004x_read_byte(state, TDA1004X_STATUS_CD) & 0x20)) {
+ while (!(tda1004x_read_byte(state, TDA1004X_STATUS_CD) & 0x20)) {
if (time_after(jiffies, timeout)) {
printk("tda1004x: DSP failed to initialised.\n");
return -EIO;
@@ -427,7 +458,7 @@ static int tda10046_fwupload(struct dvb_frontend* fe)
msleep(1);
}
- return tda1004x_check_upload_ok(state, 0x20);
+ return tda1004x_check_upload_ok(state, state->fw_version);
}
static int tda1004x_encode_fec(int fec)
@@ -483,7 +514,8 @@ static int tda10045_init(struct dvb_frontend* fe)
dprintk("%s\n", __FUNCTION__);
- if (state->initialised) return 0;
+ if (state->initialised)
+ return 0;
if (tda10045_fwupload(fe)) {
printk("tda1004x: firmware upload failed\n");
@@ -523,7 +555,8 @@ static int tda10046_init(struct dvb_frontend* fe)
struct tda1004x_state* state = fe->demodulator_priv;
dprintk("%s\n", __FUNCTION__);
- if (state->initialised) return 0;
+ if (state->initialised)
+ return 0;
if (tda10046_fwupload(fe)) {
printk("tda1004x: firmware upload failed\n");
@@ -545,7 +578,7 @@ static int tda10046_init(struct dvb_frontend* fe)
tda1004x_write_mask(state, TDA1004X_AUTO, 8, 0); // select HP stream
tda1004x_write_mask(state, TDA1004X_CONFC1, 0x80, 0); // disable pulse killer
tda1004x_write_byteI(state, TDA10046H_CONFPLL2, 10); // PLL M = 10
- tda1004x_write_byteI(state, TDA10046H_CONFPLL3, 0); // PLL P = N = 0
+ tda1004x_write_byteI(state, TDA10046H_CONFPLL3, state->config->n_i2c); // PLL P = N = 0
tda1004x_write_byteI(state, TDA10046H_FREQ_OFFSET, 99); // FREQOFFS = 99
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_MSB, 0xd4); // } PHY2 = -11221
tda1004x_write_byteI(state, TDA10046H_FREQ_PHY2_LSB, 0x2c); // }
@@ -621,12 +654,14 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
// set HP FEC
tmp = tda1004x_encode_fec(fe_params->u.ofdm.code_rate_HP);
- if (tmp < 0) return tmp;
+ if (tmp < 0)
+ return tmp;
tda1004x_write_mask(state, TDA1004X_IN_CONF2, 7, tmp);
// set LP FEC
tmp = tda1004x_encode_fec(fe_params->u.ofdm.code_rate_LP);
- if (tmp < 0) return tmp;
+ if (tmp < 0)
+ return tmp;
tda1004x_write_mask(state, TDA1004X_IN_CONF2, 0x38, tmp << 3);
// set constellation
@@ -671,7 +706,7 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
}
// set bandwidth
- switch(state->demod_type) {
+ switch (state->demod_type) {
case TDA1004X_DEMOD_TDA10045:
tda10045h_set_bandwidth(state, fe_params->u.ofdm.bandwidth);
break;
@@ -683,7 +718,8 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
// set inversion
inversion = fe_params->inversion;
- if (state->config->invert) inversion = inversion ? INVERSION_OFF : INVERSION_ON;
+ if (state->config->invert)
+ inversion = inversion ? INVERSION_OFF : INVERSION_ON;
switch (inversion) {
case INVERSION_OFF:
tda1004x_write_mask(state, TDA1004X_CONFC1, 0x20, 0);
@@ -750,19 +786,19 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
}
// start the lock
- switch(state->demod_type) {
+ switch (state->demod_type) {
case TDA1004X_DEMOD_TDA10045:
tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 8);
tda1004x_write_mask(state, TDA1004X_CONFC4, 8, 0);
- msleep(10);
break;
case TDA1004X_DEMOD_TDA10046:
tda1004x_write_mask(state, TDA1004X_AUTO, 0x40, 0x40);
- msleep(10);
break;
}
+ msleep(10);
+
return 0;
}
@@ -773,13 +809,13 @@ static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_paramete
// inversion status
fe_params->inversion = INVERSION_OFF;
- if (tda1004x_read_byte(state, TDA1004X_CONFC1) & 0x20) {
+ if (tda1004x_read_byte(state, TDA1004X_CONFC1) & 0x20)
fe_params->inversion = INVERSION_ON;
- }
- if (state->config->invert) fe_params->inversion = fe_params->inversion ? INVERSION_OFF : INVERSION_ON;
+ if (state->config->invert)
+ fe_params->inversion = fe_params->inversion ? INVERSION_OFF : INVERSION_ON;
// bandwidth
- switch(state->demod_type) {
+ switch (state->demod_type) {
case TDA1004X_DEMOD_TDA10045:
switch (tda1004x_read_byte(state, TDA10045H_WREF_LSB)) {
case 0x14:
@@ -830,9 +866,8 @@ static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_paramete
// transmission mode
fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K;
- if (tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x10) {
+ if (tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x10)
fe_params->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
- }
// guard interval
switch ((tda1004x_read_byte(state, TDA1004X_OUT_CONF1) & 0x0c) >> 2) {
@@ -880,30 +915,33 @@ static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status
// read status
status = tda1004x_read_byte(state, TDA1004X_STATUS_CD);
- if (status == -1) {
+ if (status == -1)
return -EIO;
- }
// decode
*fe_status = 0;
- if (status & 4) *fe_status |= FE_HAS_SIGNAL;
- if (status & 2) *fe_status |= FE_HAS_CARRIER;
- if (status & 8) *fe_status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+ if (status & 4)
+ *fe_status |= FE_HAS_SIGNAL;
+ if (status & 2)
+ *fe_status |= FE_HAS_CARRIER;
+ if (status & 8)
+ *fe_status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
// if we don't already have VITERBI (i.e. not LOCKED), see if the viterbi
// is getting anything valid
if (!(*fe_status & FE_HAS_VITERBI)) {
// read the CBER
cber = tda1004x_read_byte(state, TDA1004X_CBER_LSB);
- if (cber == -1) return -EIO;
+ if (cber == -1)
+ return -EIO;
status = tda1004x_read_byte(state, TDA1004X_CBER_MSB);
- if (status == -1) return -EIO;
+ if (status == -1)
+ return -EIO;
cber |= (status << 8);
tda1004x_read_byte(state, TDA1004X_CBER_RESET);
- if (cber != 65535) {
+ if (cber != 65535)
*fe_status |= FE_HAS_VITERBI;
- }
}
// if we DO have some valid VITERBI output, but don't already have SYNC
@@ -911,20 +949,22 @@ static int tda1004x_read_status(struct dvb_frontend* fe, fe_status_t * fe_status
if ((*fe_status & FE_HAS_VITERBI) && (!(*fe_status & FE_HAS_SYNC))) {
// read the VBER
vber = tda1004x_read_byte(state, TDA1004X_VBER_LSB);
- if (vber == -1) return -EIO;
+ if (vber == -1)
+ return -EIO;
status = tda1004x_read_byte(state, TDA1004X_VBER_MID);
- if (status == -1) return -EIO;
+ if (status == -1)
+ return -EIO;
vber |= (status << 8);
status = tda1004x_read_byte(state, TDA1004X_VBER_MSB);
- if (status == -1) return -EIO;
+ if (status == -1)
+ return -EIO;
vber |= ((status << 16) & 0x0f);
tda1004x_read_byte(state, TDA1004X_CVBER_LUT);
// if RS has passed some valid TS packets, then we must be
// getting some SYNC bytes
- if (vber < 16632) {
+ if (vber < 16632)
*fe_status |= FE_HAS_SYNC;
- }
}
// success
@@ -941,7 +981,7 @@ static int tda1004x_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
dprintk("%s\n", __FUNCTION__);
// determine the register to use
- switch(state->demod_type) {
+ switch (state->demod_type) {
case TDA1004X_DEMOD_TDA10045:
reg = TDA10045H_S_AGC;
break;
@@ -972,9 +1012,8 @@ static int tda1004x_read_snr(struct dvb_frontend* fe, u16 * snr)
tmp = tda1004x_read_byte(state, TDA1004X_SNR);
if (tmp < 0)
return -EIO;
- if (tmp) {
+ if (tmp)
tmp = 255 - tmp;
- }
*snr = ((tmp << 8) | tmp);
dprintk("%s: snr=0x%x\n", __FUNCTION__, *snr);
@@ -1009,11 +1048,11 @@ static int tda1004x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
break;
}
- if (tmp != 0x7f) {
+ if (tmp != 0x7f)
*ucblocks = tmp;
- } else {
+ else
*ucblocks = 0xffffffff;
- }
+
dprintk("%s: ucblocks=0x%x\n", __FUNCTION__, *ucblocks);
return 0;
}
@@ -1027,10 +1066,12 @@ static int tda1004x_read_ber(struct dvb_frontend* fe, u32* ber)
// read it in
tmp = tda1004x_read_byte(state, TDA1004X_CBER_LSB);
- if (tmp < 0) return -EIO;
+ if (tmp < 0)
+ return -EIO;
*ber = tmp << 1;
tmp = tda1004x_read_byte(state, TDA1004X_CBER_MSB);
- if (tmp < 0) return -EIO;
+ if (tmp < 0)
+ return -EIO;
*ber |= (tmp << 9);
tda1004x_read_byte(state, TDA1004X_CBER_RESET);
@@ -1042,7 +1083,7 @@ static int tda1004x_sleep(struct dvb_frontend* fe)
{
struct tda1004x_state* state = fe->demodulator_priv;
- switch(state->demod_type) {
+ switch (state->demod_type) {
case TDA1004X_DEMOD_TDA10045:
tda1004x_write_mask(state, TDA1004X_CONFADC1, 0x10, 0x10);
break;
@@ -1066,74 +1107,11 @@ static int tda1004x_get_tune_settings(struct dvb_frontend* fe, struct dvb_fronte
static void tda1004x_release(struct dvb_frontend* fe)
{
- struct tda1004x_state* state = (struct tda1004x_state*) fe->demodulator_priv;
- kfree(state);
-}
-
-static struct dvb_frontend_ops tda10045_ops;
-
-struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
- struct i2c_adapter* i2c)
-{
- struct tda1004x_state* state = NULL;
-
- /* allocate memory for the internal state */
- state = (struct tda1004x_state*) kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL);
- if (state == NULL) goto error;
-
- /* setup the state */
- state->config = config;
- state->i2c = i2c;
- memcpy(&state->ops, &tda10045_ops, sizeof(struct dvb_frontend_ops));
- state->initialised = 0;
- state->demod_type = TDA1004X_DEMOD_TDA10045;
-
- /* check if the demod is there */
- if (tda1004x_read_byte(state, TDA1004X_CHIPID) != 0x25) goto error;
-
- /* create dvb_frontend */
- state->frontend.ops = &state->ops;
- state->frontend.demodulator_priv = state;
- return &state->frontend;
-
-error:
+ struct tda1004x_state *state = fe->demodulator_priv;
kfree(state);
- return NULL;
-}
-
-static struct dvb_frontend_ops tda10046_ops;
-
-struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
- struct i2c_adapter* i2c)
-{
- struct tda1004x_state* state = NULL;
-
- /* allocate memory for the internal state */
- state = (struct tda1004x_state*) kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL);
- if (state == NULL) goto error;
-
- /* setup the state */
- state->config = config;
- state->i2c = i2c;
- memcpy(&state->ops, &tda10046_ops, sizeof(struct dvb_frontend_ops));
- state->initialised = 0;
- state->demod_type = TDA1004X_DEMOD_TDA10046;
-
- /* check if the demod is there */
- if (tda1004x_read_byte(state, TDA1004X_CHIPID) != 0x46) goto error;
-
- /* create dvb_frontend */
- state->frontend.ops = &state->ops;
- state->frontend.demodulator_priv = state;
- return &state->frontend;
-
-error:
- if (state) kfree(state);
- return NULL;
}
static struct dvb_frontend_ops tda10045_ops = {
-
.info = {
.name = "Philips TDA10045H DVB-T",
.type = FE_OFDM,
@@ -1163,8 +1141,36 @@ static struct dvb_frontend_ops tda10045_ops = {
.read_ucblocks = tda1004x_read_ucblocks,
};
-static struct dvb_frontend_ops tda10046_ops = {
+struct dvb_frontend* tda10045_attach(const struct tda1004x_config* config,
+ struct i2c_adapter* i2c)
+{
+ struct tda1004x_state *state;
+
+ /* allocate memory for the internal state */
+ state = kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL);
+ if (!state)
+ return NULL;
+
+ /* setup the state */
+ state->config = config;
+ state->i2c = i2c;
+ memcpy(&state->ops, &tda10045_ops, sizeof(struct dvb_frontend_ops));
+ state->initialised = 0;
+ state->demod_type = TDA1004X_DEMOD_TDA10045;
+
+ /* check if the demod is there */
+ if (tda1004x_read_byte(state, TDA1004X_CHIPID) != 0x25) {
+ kfree(state);
+ return NULL;
+ }
+ /* create dvb_frontend */
+ state->frontend.ops = &state->ops;
+ state->frontend.demodulator_priv = state;
+ return &state->frontend;
+}
+
+static struct dvb_frontend_ops tda10046_ops = {
.info = {
.name = "Philips TDA10046H DVB-T",
.type = FE_OFDM,
@@ -1194,6 +1200,36 @@ static struct dvb_frontend_ops tda10046_ops = {
.read_ucblocks = tda1004x_read_ucblocks,
};
+struct dvb_frontend* tda10046_attach(const struct tda1004x_config* config,
+ struct i2c_adapter* i2c)
+{
+ struct tda1004x_state *state;
+
+ /* allocate memory for the internal state */
+ state = kmalloc(sizeof(struct tda1004x_state), GFP_KERNEL);
+ if (!state)
+ return NULL;
+
+ /* setup the state */
+ state->config = config;
+ state->i2c = i2c;
+ memcpy(&state->ops, &tda10046_ops, sizeof(struct dvb_frontend_ops));
+ state->initialised = 0;
+ state->demod_type = TDA1004X_DEMOD_TDA10046;
+ state->fw_version = 0x20; /* dummy default value */
+
+ /* check if the demod is there */
+ if (tda1004x_read_byte(state, TDA1004X_CHIPID) != 0x46) {
+ kfree(state);
+ return NULL;
+ }
+
+ /* create dvb_frontend */
+ state->frontend.ops = &state->ops;
+ state->frontend.demodulator_priv = state;
+ return &state->frontend;
+}
+
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
diff --git a/drivers/media/dvb/frontends/tda1004x.h b/drivers/media/dvb/frontends/tda1004x.h
index e452fc0bad1..c8e1d54ff26 100644
--- a/drivers/media/dvb/frontends/tda1004x.h
+++ b/drivers/media/dvb/frontends/tda1004x.h
@@ -32,10 +32,13 @@ struct tda1004x_config
u8 demod_address;
/* does the "inversion" need inverted? */
- u8 invert:1;
+ u8 invert;
/* Does the OCLK signal need inverted? */
- u8 invert_oclk:1;
+ u8 invert_oclk;
+
+ /* value of N_I2C of the CONF_PLL3 register */
+ u8 n_i2c;
/* PLL maintenance */
int (*pll_init)(struct dvb_frontend* fe);
diff --git a/drivers/media/dvb/frontends/tda8083.c b/drivers/media/dvb/frontends/tda8083.c
index da82e90d6d1..168e013d23b 100644
--- a/drivers/media/dvb/frontends/tda8083.c
+++ b/drivers/media/dvb/frontends/tda8083.c
@@ -226,7 +226,7 @@ static int tda8083_send_diseqc_burst (struct tda8083_state* state, fe_sec_mini_c
static int tda8083_send_diseqc_msg (struct dvb_frontend* fe,
struct dvb_diseqc_master_cmd *m)
{
- struct tda8083_state* state = (struct tda8083_state*) fe->demodulator_priv;
+ struct tda8083_state* state = fe->demodulator_priv;
int i;
tda8083_writereg (state, 0x29, (m->msg_len - 3) | (1 << 2)); /* enable */
@@ -243,7 +243,7 @@ static int tda8083_send_diseqc_msg (struct dvb_frontend* fe,
static int tda8083_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
- struct tda8083_state* state = (struct tda8083_state*) fe->demodulator_priv;
+ struct tda8083_state* state = fe->demodulator_priv;
u8 signal = ~tda8083_readreg (state, 0x01);
u8 sync = tda8083_readreg (state, 0x02);
@@ -270,7 +270,7 @@ static int tda8083_read_status(struct dvb_frontend* fe, fe_status_t* status)
static int tda8083_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
- struct tda8083_state* state = (struct tda8083_state*) fe->demodulator_priv;
+ struct tda8083_state* state = fe->demodulator_priv;
u8 signal = ~tda8083_readreg (state, 0x01);
*strength = (signal << 8) | signal;
@@ -280,7 +280,7 @@ static int tda8083_read_signal_strength(struct dvb_frontend* fe, u16* strength)
static int tda8083_read_snr(struct dvb_frontend* fe, u16* snr)
{
- struct tda8083_state* state = (struct tda8083_state*) fe->demodulator_priv;
+ struct tda8083_state* state = fe->demodulator_priv;
u8 _snr = tda8083_readreg (state, 0x08);
*snr = (_snr << 8) | _snr;
@@ -290,7 +290,7 @@ static int tda8083_read_snr(struct dvb_frontend* fe, u16* snr)
static int tda8083_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
- struct tda8083_state* state = (struct tda8083_state*) fe->demodulator_priv;
+ struct tda8083_state* state = fe->demodulator_priv;
state->config->pll_set(fe, p);
tda8083_set_inversion (state, p->inversion);
@@ -305,7 +305,7 @@ static int tda8083_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
static int tda8083_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
- struct tda8083_state* state = (struct tda8083_state*) fe->demodulator_priv;
+ struct tda8083_state* state = fe->demodulator_priv;
/* FIXME: get symbolrate & frequency offset...*/
/*p->frequency = ???;*/
@@ -319,7 +319,7 @@ static int tda8083_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
static int tda8083_sleep(struct dvb_frontend* fe)
{
- struct tda8083_state* state = (struct tda8083_state*) fe->demodulator_priv;
+ struct tda8083_state* state = fe->demodulator_priv;
tda8083_writereg (state, 0x00, 0x02);
return 0;
@@ -327,7 +327,7 @@ static int tda8083_sleep(struct dvb_frontend* fe)
static int tda8083_init(struct dvb_frontend* fe)
{
- struct tda8083_state* state = (struct tda8083_state*) fe->demodulator_priv;
+ struct tda8083_state* state = fe->demodulator_priv;
int i;
for (i=0; i<44; i++)
@@ -343,7 +343,7 @@ static int tda8083_init(struct dvb_frontend* fe)
static int tda8083_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst)
{
- struct tda8083_state* state = (struct tda8083_state*) fe->demodulator_priv;
+ struct tda8083_state* state = fe->demodulator_priv;
tda8083_send_diseqc_burst (state, burst);
tda8083_writereg (state, 0x00, 0x3c);
@@ -354,7 +354,7 @@ static int tda8083_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t
static int tda8083_diseqc_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
{
- struct tda8083_state* state = (struct tda8083_state*) fe->demodulator_priv;
+ struct tda8083_state* state = fe->demodulator_priv;
tda8083_set_tone (state, tone);
tda8083_writereg (state, 0x00, 0x3c);
@@ -365,7 +365,7 @@ static int tda8083_diseqc_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t t
static int tda8083_diseqc_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
{
- struct tda8083_state* state = (struct tda8083_state*) fe->demodulator_priv;
+ struct tda8083_state* state = fe->demodulator_priv;
tda8083_set_voltage (state, voltage);
tda8083_writereg (state, 0x00, 0x3c);
@@ -376,7 +376,7 @@ static int tda8083_diseqc_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t
static void tda8083_release(struct dvb_frontend* fe)
{
- struct tda8083_state* state = (struct tda8083_state*) fe->demodulator_priv;
+ struct tda8083_state* state = fe->demodulator_priv;
kfree(state);
}
@@ -388,7 +388,7 @@ struct dvb_frontend* tda8083_attach(const struct tda8083_config* config,
struct tda8083_state* state = NULL;
/* allocate memory for the internal state */
- state = (struct tda8083_state*) kmalloc(sizeof(struct tda8083_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct tda8083_state), GFP_KERNEL);
if (state == NULL) goto error;
/* setup the state */
diff --git a/drivers/media/dvb/frontends/tda80xx.c b/drivers/media/dvb/frontends/tda80xx.c
index c9963211428..032d348dafb 100644
--- a/drivers/media/dvb/frontends/tda80xx.c
+++ b/drivers/media/dvb/frontends/tda80xx.c
@@ -27,7 +27,7 @@
#include <linux/spinlock.h>
#include <linux/threads.h>
#include <linux/interrupt.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -400,7 +400,7 @@ static void tda80xx_wait_diseqc_fifo(struct tda80xx_state* state)
static int tda8044_init(struct dvb_frontend* fe)
{
- struct tda80xx_state* state = (struct tda80xx_state*) fe->demodulator_priv;
+ struct tda80xx_state* state = fe->demodulator_priv;
int ret;
/*
@@ -432,7 +432,7 @@ static int tda8044_init(struct dvb_frontend* fe)
static int tda8083_init(struct dvb_frontend* fe)
{
- struct tda80xx_state* state = (struct tda80xx_state*) fe->demodulator_priv;
+ struct tda80xx_state* state = fe->demodulator_priv;
tda80xx_write(state, 0x00, tda8083_inittab, sizeof(tda8083_inittab));
@@ -447,7 +447,7 @@ static int tda8083_init(struct dvb_frontend* fe)
static int tda80xx_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
{
- struct tda80xx_state* state = (struct tda80xx_state*) fe->demodulator_priv;
+ struct tda80xx_state* state = fe->demodulator_priv;
switch (voltage) {
case SEC_VOLTAGE_13:
@@ -463,7 +463,7 @@ static int tda80xx_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage
static int tda80xx_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
{
- struct tda80xx_state* state = (struct tda80xx_state*) fe->demodulator_priv;
+ struct tda80xx_state* state = fe->demodulator_priv;
switch (tone) {
case SEC_TONE_OFF:
@@ -477,7 +477,7 @@ static int tda80xx_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
static int tda80xx_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd)
{
- struct tda80xx_state* state = (struct tda80xx_state*) fe->demodulator_priv;
+ struct tda80xx_state* state = fe->demodulator_priv;
if (cmd->msg_len > 6)
return -EINVAL;
@@ -492,7 +492,7 @@ static int tda80xx_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma
static int tda80xx_send_diseqc_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t cmd)
{
- struct tda80xx_state* state = (struct tda80xx_state*) fe->demodulator_priv;
+ struct tda80xx_state* state = fe->demodulator_priv;
switch (cmd) {
case SEC_MINI_A:
@@ -512,7 +512,7 @@ static int tda80xx_send_diseqc_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t
static int tda80xx_sleep(struct dvb_frontend* fe)
{
- struct tda80xx_state* state = (struct tda80xx_state*) fe->demodulator_priv;
+ struct tda80xx_state* state = fe->demodulator_priv;
tda80xx_writereg(state, 0x00, 0x02); /* enter standby */
@@ -521,7 +521,7 @@ static int tda80xx_sleep(struct dvb_frontend* fe)
static int tda80xx_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
- struct tda80xx_state* state = (struct tda80xx_state*) fe->demodulator_priv;
+ struct tda80xx_state* state = fe->demodulator_priv;
tda80xx_writereg(state, 0x1c, 0x80);
state->config->pll_set(fe, p);
@@ -537,7 +537,7 @@ static int tda80xx_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
static int tda80xx_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
- struct tda80xx_state* state = (struct tda80xx_state*) fe->demodulator_priv;
+ struct tda80xx_state* state = fe->demodulator_priv;
if (!state->config->irq)
tda80xx_read_status_int(state);
@@ -550,7 +550,7 @@ static int tda80xx_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
static int tda80xx_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
- struct tda80xx_state* state = (struct tda80xx_state*) fe->demodulator_priv;
+ struct tda80xx_state* state = fe->demodulator_priv;
if (!state->config->irq)
tda80xx_read_status_int(state);
@@ -561,7 +561,7 @@ static int tda80xx_read_status(struct dvb_frontend* fe, fe_status_t* status)
static int tda80xx_read_ber(struct dvb_frontend* fe, u32* ber)
{
- struct tda80xx_state* state = (struct tda80xx_state*) fe->demodulator_priv;
+ struct tda80xx_state* state = fe->demodulator_priv;
int ret;
u8 buf[3];
@@ -575,7 +575,7 @@ static int tda80xx_read_ber(struct dvb_frontend* fe, u32* ber)
static int tda80xx_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
- struct tda80xx_state* state = (struct tda80xx_state*) fe->demodulator_priv;
+ struct tda80xx_state* state = fe->demodulator_priv;
u8 gain = ~tda80xx_readreg(state, 0x01);
*strength = (gain << 8) | gain;
@@ -585,7 +585,7 @@ static int tda80xx_read_signal_strength(struct dvb_frontend* fe, u16* strength)
static int tda80xx_read_snr(struct dvb_frontend* fe, u16* snr)
{
- struct tda80xx_state* state = (struct tda80xx_state*) fe->demodulator_priv;
+ struct tda80xx_state* state = fe->demodulator_priv;
u8 quality = tda80xx_readreg(state, 0x08);
*snr = (quality << 8) | quality;
@@ -595,7 +595,7 @@ static int tda80xx_read_snr(struct dvb_frontend* fe, u16* snr)
static int tda80xx_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
- struct tda80xx_state* state = (struct tda80xx_state*) fe->demodulator_priv;
+ struct tda80xx_state* state = fe->demodulator_priv;
*ucblocks = tda80xx_readreg(state, 0x0f);
if (*ucblocks == 0xff)
@@ -606,7 +606,7 @@ static int tda80xx_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
static int tda80xx_init(struct dvb_frontend* fe)
{
- struct tda80xx_state* state = (struct tda80xx_state*) fe->demodulator_priv;
+ struct tda80xx_state* state = fe->demodulator_priv;
switch(state->id) {
case ID_TDA8044:
@@ -620,7 +620,7 @@ static int tda80xx_init(struct dvb_frontend* fe)
static void tda80xx_release(struct dvb_frontend* fe)
{
- struct tda80xx_state* state = (struct tda80xx_state*) fe->demodulator_priv;
+ struct tda80xx_state* state = fe->demodulator_priv;
if (state->config->irq)
free_irq(state->config->irq, &state->worklet);
@@ -637,7 +637,7 @@ struct dvb_frontend* tda80xx_attach(const struct tda80xx_config* config,
int ret;
/* allocate memory for the internal state */
- state = (struct tda80xx_state*) kmalloc(sizeof(struct tda80xx_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct tda80xx_state), GFP_KERNEL);
if (state == NULL) goto error;
/* setup the state */
diff --git a/drivers/media/dvb/frontends/ves1820.c b/drivers/media/dvb/frontends/ves1820.c
index 9c0d23e1d9e..70fb44b391a 100644
--- a/drivers/media/dvb/frontends/ves1820.c
+++ b/drivers/media/dvb/frontends/ves1820.c
@@ -70,7 +70,6 @@ static int ves1820_writereg(struct ves1820_state *state, u8 reg, u8 data)
printk("ves1820: %s(): writereg error (reg == 0x%02x,"
"val == 0x%02x, ret == %i)\n", __FUNCTION__, reg, data, ret);
- msleep(10);
return (ret != 1) ? -EREMOTEIO : 0;
}
@@ -193,7 +192,7 @@ static int ves1820_set_symbolrate(struct ves1820_state *state, u32 symbolrate)
static int ves1820_init(struct dvb_frontend* fe)
{
- struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv;
+ struct ves1820_state* state = fe->demodulator_priv;
int i;
int val;
@@ -214,7 +213,7 @@ static int ves1820_init(struct dvb_frontend* fe)
static int ves1820_set_parameters(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
- struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv;
+ struct ves1820_state* state = fe->demodulator_priv;
static const u8 reg0x00[] = { 0x00, 0x04, 0x08, 0x0c, 0x10 };
static const u8 reg0x01[] = { 140, 140, 106, 100, 92 };
static const u8 reg0x05[] = { 135, 100, 70, 54, 38 };
@@ -241,7 +240,7 @@ static int ves1820_set_parameters(struct dvb_frontend* fe, struct dvb_frontend_p
static int ves1820_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
- struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv;
+ struct ves1820_state* state = fe->demodulator_priv;
int sync;
*status = 0;
@@ -267,7 +266,7 @@ static int ves1820_read_status(struct dvb_frontend* fe, fe_status_t* status)
static int ves1820_read_ber(struct dvb_frontend* fe, u32* ber)
{
- struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv;
+ struct ves1820_state* state = fe->demodulator_priv;
u32 _ber = ves1820_readreg(state, 0x14) |
(ves1820_readreg(state, 0x15) << 8) |
@@ -279,7 +278,7 @@ static int ves1820_read_ber(struct dvb_frontend* fe, u32* ber)
static int ves1820_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
- struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv;
+ struct ves1820_state* state = fe->demodulator_priv;
u8 gain = ves1820_readreg(state, 0x17);
*strength = (gain << 8) | gain;
@@ -289,7 +288,7 @@ static int ves1820_read_signal_strength(struct dvb_frontend* fe, u16* strength)
static int ves1820_read_snr(struct dvb_frontend* fe, u16* snr)
{
- struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv;
+ struct ves1820_state* state = fe->demodulator_priv;
u8 quality = ~ves1820_readreg(state, 0x18);
*snr = (quality << 8) | quality;
@@ -299,7 +298,7 @@ static int ves1820_read_snr(struct dvb_frontend* fe, u16* snr)
static int ves1820_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
- struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv;
+ struct ves1820_state* state = fe->demodulator_priv;
*ucblocks = ves1820_readreg(state, 0x13) & 0x7f;
if (*ucblocks == 0x7f)
@@ -314,7 +313,7 @@ static int ves1820_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
static int ves1820_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
- struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv;
+ struct ves1820_state* state = fe->demodulator_priv;
int sync;
s8 afc = 0;
@@ -345,7 +344,7 @@ static int ves1820_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
static int ves1820_sleep(struct dvb_frontend* fe)
{
- struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv;
+ struct ves1820_state* state = fe->demodulator_priv;
ves1820_writereg(state, 0x1b, 0x02); /* pdown ADC */
ves1820_writereg(state, 0x00, 0x80); /* standby */
@@ -364,7 +363,7 @@ static int ves1820_get_tune_settings(struct dvb_frontend* fe, struct dvb_fronten
static void ves1820_release(struct dvb_frontend* fe)
{
- struct ves1820_state* state = (struct ves1820_state*) fe->demodulator_priv;
+ struct ves1820_state* state = fe->demodulator_priv;
kfree(state);
}
@@ -377,7 +376,7 @@ struct dvb_frontend* ves1820_attach(const struct ves1820_config* config,
struct ves1820_state* state = NULL;
/* allocate memory for the internal state */
- state = (struct ves1820_state*) kmalloc(sizeof(struct ves1820_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct ves1820_state), GFP_KERNEL);
if (state == NULL)
goto error;
diff --git a/drivers/media/dvb/frontends/ves1x93.c b/drivers/media/dvb/frontends/ves1x93.c
index edcad283aa8..821df8e839d 100644
--- a/drivers/media/dvb/frontends/ves1x93.c
+++ b/drivers/media/dvb/frontends/ves1x93.c
@@ -263,7 +263,7 @@ static int ves1x93_set_symbolrate (struct ves1x93_state* state, u32 srate)
static int ves1x93_init (struct dvb_frontend* fe)
{
- struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv;
+ struct ves1x93_state* state = fe->demodulator_priv;
int i;
int val;
@@ -289,7 +289,7 @@ static int ves1x93_init (struct dvb_frontend* fe)
static int ves1x93_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltage)
{
- struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv;
+ struct ves1x93_state* state = fe->demodulator_priv;
switch (voltage) {
case SEC_VOLTAGE_13:
@@ -305,7 +305,7 @@ static int ves1x93_set_voltage (struct dvb_frontend* fe, fe_sec_voltage_t voltag
static int ves1x93_read_status(struct dvb_frontend* fe, fe_status_t* status)
{
- struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv;
+ struct ves1x93_state* state = fe->demodulator_priv;
u8 sync = ves1x93_readreg (state, 0x0e);
@@ -346,7 +346,7 @@ static int ves1x93_read_status(struct dvb_frontend* fe, fe_status_t* status)
static int ves1x93_read_ber(struct dvb_frontend* fe, u32* ber)
{
- struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv;
+ struct ves1x93_state* state = fe->demodulator_priv;
*ber = ves1x93_readreg (state, 0x15);
*ber |= (ves1x93_readreg (state, 0x16) << 8);
@@ -358,7 +358,7 @@ static int ves1x93_read_ber(struct dvb_frontend* fe, u32* ber)
static int ves1x93_read_signal_strength(struct dvb_frontend* fe, u16* strength)
{
- struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv;
+ struct ves1x93_state* state = fe->demodulator_priv;
u8 signal = ~ves1x93_readreg (state, 0x0b);
*strength = (signal << 8) | signal;
@@ -368,7 +368,7 @@ static int ves1x93_read_signal_strength(struct dvb_frontend* fe, u16* strength)
static int ves1x93_read_snr(struct dvb_frontend* fe, u16* snr)
{
- struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv;
+ struct ves1x93_state* state = fe->demodulator_priv;
u8 _snr = ~ves1x93_readreg (state, 0x1c);
*snr = (_snr << 8) | _snr;
@@ -378,7 +378,7 @@ static int ves1x93_read_snr(struct dvb_frontend* fe, u16* snr)
static int ves1x93_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
{
- struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv;
+ struct ves1x93_state* state = fe->demodulator_priv;
*ucblocks = ves1x93_readreg (state, 0x18) & 0x7f;
@@ -393,7 +393,7 @@ static int ves1x93_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
static int ves1x93_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
- struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv;
+ struct ves1x93_state* state = fe->demodulator_priv;
ves1x93_writereg(state, 0x00, 0x11);
state->config->pll_set(fe, p);
@@ -408,7 +408,7 @@ static int ves1x93_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
static int ves1x93_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_parameters *p)
{
- struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv;
+ struct ves1x93_state* state = fe->demodulator_priv;
int afc;
afc = ((int)((char)(ves1x93_readreg (state, 0x0a) << 1)))/2;
@@ -431,14 +431,14 @@ static int ves1x93_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
static int ves1x93_sleep(struct dvb_frontend* fe)
{
- struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv;
+ struct ves1x93_state* state = fe->demodulator_priv;
return ves1x93_writereg (state, 0x00, 0x08);
}
static void ves1x93_release(struct dvb_frontend* fe)
{
- struct ves1x93_state* state = (struct ves1x93_state*) fe->demodulator_priv;
+ struct ves1x93_state* state = fe->demodulator_priv;
kfree(state);
}
@@ -451,7 +451,7 @@ struct dvb_frontend* ves1x93_attach(const struct ves1x93_config* config,
u8 identity;
/* allocate memory for the internal state */
- state = (struct ves1x93_state*) kmalloc(sizeof(struct ves1x93_state), GFP_KERNEL);
+ state = kmalloc(sizeof(struct ves1x93_state), GFP_KERNEL);
if (state == NULL) goto error;
/* setup the state */
diff --git a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c
index 922c205a265..8e33a850e13 100644
--- a/drivers/media/dvb/ttpci/av7110.c
+++ b/drivers/media/dvb/ttpci/av7110.c
@@ -130,7 +130,7 @@ static void init_av7110_av(struct av7110 *av7110)
av7110->current_input = 0;
if (i2c_writereg(av7110, 0x20, 0x00, 0x00) == 1) {
printk ("dvb-ttpci: Crystal audio DAC @ card %d detected\n",
- av7110->dvb_adapter->num);
+ av7110->dvb_adapter.num);
av7110->adac_type = DVB_ADAC_CRYSTAL;
i2c_writereg(av7110, 0x20, 0x01, 0xd2);
i2c_writereg(av7110, 0x20, 0x02, 0x49);
@@ -145,13 +145,13 @@ static void init_av7110_av(struct av7110 *av7110)
}
else if (dev->pci->subsystem_vendor == 0x110a) {
printk("dvb-ttpci: DVB-C w/o analog module @ card %d detected\n",
- av7110->dvb_adapter->num);
+ av7110->dvb_adapter.num);
av7110->adac_type = DVB_ADAC_NONE;
}
else {
av7110->adac_type = adac;
printk("dvb-ttpci: adac type set to %d @ card %d\n",
- av7110->dvb_adapter->num, av7110->adac_type);
+ av7110->dvb_adapter.num, av7110->adac_type);
}
if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP) {
@@ -231,7 +231,7 @@ static int arm_thread(void *data)
if (newloops == av7110->arm_loops) {
printk(KERN_ERR "dvb-ttpci: ARM crashed @ card %d\n",
- av7110->dvb_adapter->num);
+ av7110->dvb_adapter.num);
arm_error(av7110);
av7710_set_video_mode(av7110, vidmode);
@@ -1282,7 +1282,7 @@ static int av7110_register(struct av7110 *av7110)
av7110->dmxdev.demux = &dvbdemux->dmx;
av7110->dmxdev.capabilities = 0;
- dvb_dmxdev_init(&av7110->dmxdev, av7110->dvb_adapter);
+ dvb_dmxdev_init(&av7110->dmxdev, &av7110->dvb_adapter);
av7110->hw_frontend.source = DMX_FRONTEND_0;
@@ -1307,11 +1307,11 @@ static int av7110_register(struct av7110 *av7110)
av7110_ca_register(av7110);
#ifdef CONFIG_DVB_AV7110_OSD
- dvb_register_device(av7110->dvb_adapter, &av7110->osd_dev,
+ dvb_register_device(&av7110->dvb_adapter, &av7110->osd_dev,
&dvbdev_osd, av7110, DVB_DEVICE_OSD);
#endif
- dvb_net_init(av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);
+ dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net, &dvbdemux->dmx);
if (budgetpatch) {
/* initialize software demux1 without its own frontend
@@ -1334,9 +1334,9 @@ static int av7110_register(struct av7110 *av7110)
av7110->dmxdev1.demux = &dvbdemux1->dmx;
av7110->dmxdev1.capabilities = 0;
- dvb_dmxdev_init(&av7110->dmxdev1, av7110->dvb_adapter);
+ dvb_dmxdev_init(&av7110->dmxdev1, &av7110->dvb_adapter);
- dvb_net_init(av7110->dvb_adapter, &av7110->dvb_net1, &dvbdemux1->dmx);
+ dvb_net_init(&av7110->dvb_adapter, &av7110->dvb_net1, &dvbdemux1->dmx);
printk("dvb-ttpci: additional demux1 for budget-patch registered\n");
}
return 0;
@@ -1673,6 +1673,106 @@ static struct stv0299_config alps_bsru6_config = {
};
+static u8 alps_bsbe1_inittab[] = {
+ 0x01, 0x15,
+ 0x02, 0x30,
+ 0x03, 0x00,
+ 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */
+ 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */
+ 0x06, 0x40, /* DAC not used, set to high impendance mode */
+ 0x07, 0x00, /* DAC LSB */
+ 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */
+ 0x09, 0x00, /* FIFO */
+ 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */
+ 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */
+ 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */
+ 0x10, 0x3f, // AGC2 0x3d
+ 0x11, 0x84,
+ 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on
+ 0x15, 0xc9, // lock detector threshold
+ 0x16, 0x00,
+ 0x17, 0x00,
+ 0x18, 0x00,
+ 0x19, 0x00,
+ 0x1a, 0x00,
+ 0x1f, 0x50,
+ 0x20, 0x00,
+ 0x21, 0x00,
+ 0x22, 0x00,
+ 0x23, 0x00,
+ 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0
+ 0x29, 0x1e, // 1/2 threshold
+ 0x2a, 0x14, // 2/3 threshold
+ 0x2b, 0x0f, // 3/4 threshold
+ 0x2c, 0x09, // 5/6 threshold
+ 0x2d, 0x05, // 7/8 threshold
+ 0x2e, 0x01,
+ 0x31, 0x1f, // test all FECs
+ 0x32, 0x19, // viterbi and synchro search
+ 0x33, 0xfc, // rs control
+ 0x34, 0x93, // error control
+ 0x0f, 0x92,
+ 0xff, 0xff
+};
+
+static int alps_bsbe1_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
+{
+ struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
+ int ret;
+ u8 data[4];
+ u32 div;
+ struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) };
+
+ if ((params->frequency < 950000) || (params->frequency > 2150000))
+ return -EINVAL;
+
+ div = (params->frequency + (125 - 1)) / 125; // round correctly
+ data[0] = (div >> 8) & 0x7f;
+ data[1] = div & 0xff;
+ data[2] = 0x80 | ((div & 0x18000) >> 10) | 4;
+ data[3] = (params->frequency > 1530000) ? 0xE0 : 0xE4;
+
+ ret = i2c_transfer(&av7110->i2c_adap, &msg, 1);
+ return (ret != 1) ? -EIO : 0;
+}
+
+static struct stv0299_config alps_bsbe1_config = {
+ .demod_address = 0x68,
+ .inittab = alps_bsbe1_inittab,
+ .mclk = 88000000UL,
+ .invert = 1,
+ .enhanced_tuning = 0,
+ .skip_reinit = 0,
+ .min_delay_ms = 100,
+ .set_symbol_rate = alps_bsru6_set_symbol_rate,
+ .pll_set = alps_bsbe1_pll_set,
+};
+
+static int lnbp21_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage)
+{
+ struct av7110* av7110 = (struct av7110*) fe->dvb->priv;
+ int ret;
+ u8 data[1];
+ struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = data, .len = sizeof(data) };
+
+ switch(voltage) {
+ case SEC_VOLTAGE_OFF:
+ data[0] = 0x00;
+ break;
+ case SEC_VOLTAGE_13:
+ data[0] = 0x44;
+ break;
+ case SEC_VOLTAGE_18:
+ data[0] = 0x4c;
+ break;
+ default:
+ return -EINVAL;
+ };
+
+ ret = i2c_transfer(&av7110->i2c_adap, &msg, 1);
+ return (ret != 1) ? -EIO : 0;
+}
+
static int alps_tdbe2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
{
@@ -2116,6 +2216,14 @@ static int frontend_init(struct av7110 *av7110)
av7110->dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;
break;
}
+ break;
+
+ case 0x000E: /* Hauppauge/TT Nexus-S rev 2.3 */
+ /* ALPS BSBE1 */
+ av7110->fe = stv0299_attach(&alps_bsbe1_config, &av7110->i2c_adap);
+ if (av7110->fe)
+ av7110->fe->ops->set_voltage = lnbp21_set_voltage;
+ break;
}
}
@@ -2138,7 +2246,7 @@ static int frontend_init(struct av7110 *av7110)
FE_FUNC_OVERRIDE(av7110->fe->ops->dishnetwork_send_legacy_command, av7110->fe_dishnetwork_send_legacy_command, av7110_fe_dishnetwork_send_legacy_command);
FE_FUNC_OVERRIDE(av7110->fe->ops->set_frontend, av7110->fe_set_frontend, av7110_fe_set_frontend);
- ret = dvb_register_frontend(av7110->dvb_adapter, av7110->fe);
+ ret = dvb_register_frontend(&av7110->dvb_adapter, av7110->fe);
if (ret < 0) {
printk("av7110: Frontend registration failed!\n");
if (av7110->fe->ops->release)
@@ -2352,7 +2460,7 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d
goto err_dvb_unregister_adapter_2;
ttpci_eeprom_parse_mac(&av7110->i2c_adap,
- av7110->dvb_adapter->proposed_mac);
+ av7110->dvb_adapter.proposed_mac);
ret = -ENOMEM;
if (budgetpatch) {
@@ -2523,7 +2631,7 @@ static int av7110_attach(struct saa7146_dev* dev, struct saa7146_pci_extension_d
if (ret < 0)
goto err_av7110_unregister_11;
- av7110->dvb_adapter->priv = av7110;
+ av7110->dvb_adapter.priv = av7110;
ret = frontend_init(av7110);
if (ret < 0)
goto err_av7110_exit_v4l_12;
@@ -2558,7 +2666,7 @@ err_saa71466_vfree_4:
err_i2c_del_3:
i2c_del_adapter(&av7110->i2c_adap);
err_dvb_unregister_adapter_2:
- dvb_unregister_adapter(av7110->dvb_adapter);
+ dvb_unregister_adapter(&av7110->dvb_adapter);
err_put_firmware_1:
put_firmware(av7110);
err_kfree_0:
@@ -2604,7 +2712,7 @@ static int av7110_detach(struct saa7146_dev* saa)
i2c_del_adapter(&av7110->i2c_adap);
- dvb_unregister_adapter (av7110->dvb_adapter);
+ dvb_unregister_adapter (&av7110->dvb_adapter);
av7110_num--;
@@ -2672,21 +2780,23 @@ MAKE_AV7110_INFO(ttt_1_X, "Technotrend/Hauppauge WinTV DVB-T rev1.X");
MAKE_AV7110_INFO(ttc_1_X, "Technotrend/Hauppauge WinTV Nexus-CA rev1.X");
MAKE_AV7110_INFO(ttc_2_X, "Technotrend/Hauppauge WinTV DVB-C rev2.X");
MAKE_AV7110_INFO(tts_2_X, "Technotrend/Hauppauge WinTV Nexus-S rev2.X");
+MAKE_AV7110_INFO(tts_2_3, "Technotrend/Hauppauge WinTV Nexus-S rev2.3");
MAKE_AV7110_INFO(tts_1_3se, "Technotrend/Hauppauge WinTV DVB-S rev1.3 SE");
MAKE_AV7110_INFO(ttt, "Technotrend/Hauppauge DVB-T");
MAKE_AV7110_INFO(fsc, "Fujitsu Siemens DVB-C");
MAKE_AV7110_INFO(fss, "Fujitsu Siemens DVB-S rev1.6");
static struct pci_device_id pci_tbl[] = {
+ MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
MAKE_EXTENSION_PCI(tts_1_X, 0x13c2, 0x0000),
MAKE_EXTENSION_PCI(ttt_1_X, 0x13c2, 0x0001),
MAKE_EXTENSION_PCI(ttc_2_X, 0x13c2, 0x0002),
MAKE_EXTENSION_PCI(tts_2_X, 0x13c2, 0x0003),
- MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
- MAKE_EXTENSION_PCI(fsc, 0x110a, 0x0000),
- MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
MAKE_EXTENSION_PCI(fss, 0x13c2, 0x0006),
MAKE_EXTENSION_PCI(ttt, 0x13c2, 0x0008),
+ MAKE_EXTENSION_PCI(ttc_1_X, 0x13c2, 0x000a),
+ MAKE_EXTENSION_PCI(tts_2_3, 0x13c2, 0x000e),
+ MAKE_EXTENSION_PCI(tts_1_3se, 0x13c2, 0x1002),
/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0004), UNDEFINED CARD */ // Galaxis DVB PC-Sat-Carte
/* MAKE_EXTENSION_PCI(???, 0x13c2, 0x0005), UNDEFINED CARD */ // Technisat SkyStar1
diff --git a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h
index 5070e0523da..4f69b4d0147 100644
--- a/drivers/media/dvb/ttpci/av7110.h
+++ b/drivers/media/dvb/ttpci/av7110.h
@@ -220,7 +220,7 @@ struct av7110 {
struct audio_mixer mixer;
- struct dvb_adapter *dvb_adapter;
+ struct dvb_adapter dvb_adapter;
struct dvb_device *video_dev;
struct dvb_device *audio_dev;
struct dvb_device *ca_dev;
@@ -274,7 +274,6 @@ extern void av7110_ir_exit (void);
extern int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val);
extern u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg);
extern int msp_writereg(struct av7110 *av7110, u8 dev, u16 reg, u16 val);
-extern int msp_readreg(struct av7110 *av7110, u8 dev, u16 reg, u16 *val);
extern int av7110_init_analog_module(struct av7110 *av7110);
diff --git a/drivers/media/dvb/ttpci/av7110_av.c b/drivers/media/dvb/ttpci/av7110_av.c
index d77e8a00688..ccf946125d0 100644
--- a/drivers/media/dvb/ttpci/av7110_av.c
+++ b/drivers/media/dvb/ttpci/av7110_av.c
@@ -1075,7 +1075,7 @@ static int dvb_video_ioctl(struct inode *inode, struct file *file,
}
if (ret < 0)
break;
- av7110->videostate.video_format = format;
+ av7110->videostate.display_format = format;
ret = av7110_fw_cmd(av7110, COMTYPE_ENCODER, SetPanScanType,
1, (u16) val);
break;
@@ -1230,14 +1230,20 @@ static int dvb_audio_ioctl(struct inode *inode, struct file *file,
switch(av7110->audiostate.channel_select) {
case AUDIO_STEREO:
audcom(av7110, AUDIO_CMD_STEREO);
+ if (av7110->adac_type == DVB_ADAC_CRYSTAL)
+ i2c_writereg(av7110, 0x20, 0x02, 0x49);
break;
case AUDIO_MONO_LEFT:
audcom(av7110, AUDIO_CMD_MONO_L);
+ if (av7110->adac_type == DVB_ADAC_CRYSTAL)
+ i2c_writereg(av7110, 0x20, 0x02, 0x4a);
break;
case AUDIO_MONO_RIGHT:
audcom(av7110, AUDIO_CMD_MONO_R);
+ if (av7110->adac_type == DVB_ADAC_CRYSTAL)
+ i2c_writereg(av7110, 0x20, 0x02, 0x45);
break;
default:
@@ -1409,10 +1415,10 @@ int av7110_av_register(struct av7110 *av7110)
av7110->video_events.overflow = 0;
memset(&av7110->video_size, 0, sizeof (video_size_t));
- dvb_register_device(av7110->dvb_adapter, &av7110->video_dev,
+ dvb_register_device(&av7110->dvb_adapter, &av7110->video_dev,
&dvbdev_video, av7110, DVB_DEVICE_VIDEO);
- dvb_register_device(av7110->dvb_adapter, &av7110->audio_dev,
+ dvb_register_device(&av7110->dvb_adapter, &av7110->audio_dev,
&dvbdev_audio, av7110, DVB_DEVICE_AUDIO);
return 0;
diff --git a/drivers/media/dvb/ttpci/av7110_ca.c b/drivers/media/dvb/ttpci/av7110_ca.c
index 21f7aacf772..c3801e328fe 100644
--- a/drivers/media/dvb/ttpci/av7110_ca.c
+++ b/drivers/media/dvb/ttpci/av7110_ca.c
@@ -123,7 +123,7 @@ static void ci_ll_release(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *
}
static int ci_ll_reset(struct dvb_ringbuffer *cibuf, struct file *file,
- int slots, ca_slot_info_t *slot)
+ int slots, ca_slot_info_t *slot)
{
int i;
int len = 0;
@@ -370,7 +370,7 @@ static struct dvb_device dvbdev_ca = {
int av7110_ca_register(struct av7110 *av7110)
{
- return dvb_register_device(av7110->dvb_adapter, &av7110->ca_dev,
+ return dvb_register_device(&av7110->dvb_adapter, &av7110->ca_dev,
&dvbdev_ca, av7110, DVB_DEVICE_CA);
}
diff --git a/drivers/media/dvb/ttpci/av7110_hw.c b/drivers/media/dvb/ttpci/av7110_hw.c
index bd6e5ea4aef..7fa4a0ebe13 100644
--- a/drivers/media/dvb/ttpci/av7110_hw.c
+++ b/drivers/media/dvb/ttpci/av7110_hw.c
@@ -104,7 +104,7 @@ u32 av7110_debiread(struct av7110 *av7110, u32 config, int addr, int count)
/* av7110 ARM core boot stuff */
-
+#if 0
void av7110_reset_arm(struct av7110 *av7110)
{
saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTLO);
@@ -124,7 +124,7 @@ void av7110_reset_arm(struct av7110 *av7110)
av7110->arm_ready = 1;
dprintk(1, "reset ARM\n");
}
-
+#endif /* 0 */
static int waitdebi(struct av7110 *av7110, int adr, int state)
{
@@ -335,7 +335,7 @@ int av7110_wait_msgstate(struct av7110 *av7110, u16 flags)
return 0;
}
-int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
+static int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
{
int i;
unsigned long start;
@@ -455,7 +455,7 @@ int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
return 0;
}
-int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
+static int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length)
{
int ret;
@@ -500,6 +500,7 @@ int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...)
return ret;
}
+#if 0
int av7110_send_ci_cmd(struct av7110 *av7110, u8 subcom, u8 *buf, u8 len)
{
int i, ret;
@@ -521,6 +522,7 @@ int av7110_send_ci_cmd(struct av7110 *av7110, u8 subcom, u8 *buf, u8 len)
printk(KERN_ERR "dvb-ttpci: av7110_send_ci_cmd error %d\n", ret);
return ret;
}
+#endif /* 0 */
int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
int request_buf_len, u16 *reply_buf, int reply_buf_len)
@@ -593,7 +595,7 @@ int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
return 0;
}
-int av7110_fw_query(struct av7110 *av7110, u16 tag, u16* buf, s16 length)
+static int av7110_fw_query(struct av7110 *av7110, u16 tag, u16* buf, s16 length)
{
int ret;
ret = av7110_fw_request(av7110, &tag, 0, buf, length);
@@ -617,7 +619,7 @@ int av7110_firmversion(struct av7110 *av7110)
if (av7110_fw_query(av7110, tag, buf, 16)) {
printk("dvb-ttpci: failed to boot firmware @ card %d\n",
- av7110->dvb_adapter->num);
+ av7110->dvb_adapter.num);
return -EIO;
}
@@ -628,16 +630,16 @@ int av7110_firmversion(struct av7110 *av7110)
av7110->avtype = (buf[8] << 16) + buf[9];
printk("dvb-ttpci: info @ card %d: firm %08x, rtsl %08x, vid %08x, app %08x\n",
- av7110->dvb_adapter->num, av7110->arm_fw,
+ av7110->dvb_adapter.num, av7110->arm_fw,
av7110->arm_rtsl, av7110->arm_vid, av7110->arm_app);
/* print firmware capabilities */
if (FW_CI_LL_SUPPORT(av7110->arm_app))
printk("dvb-ttpci: firmware @ card %d supports CI link layer interface\n",
- av7110->dvb_adapter->num);
+ av7110->dvb_adapter.num);
else
printk("dvb-ttpci: no firmware support for CI link layer interface @ card %d\n",
- av7110->dvb_adapter->num);
+ av7110->dvb_adapter.num);
return 0;
}
diff --git a/drivers/media/dvb/ttpci/av7110_hw.h b/drivers/media/dvb/ttpci/av7110_hw.h
index bf901c62468..52061e17c6d 100644
--- a/drivers/media/dvb/ttpci/av7110_hw.h
+++ b/drivers/media/dvb/ttpci/av7110_hw.h
@@ -364,7 +364,6 @@ enum av7110_command_type {
-extern void av7110_reset_arm(struct av7110 *av7110);
extern int av7110_bootarm(struct av7110 *av7110);
extern int av7110_firmversion(struct av7110 *av7110);
#define FW_CI_LL_SUPPORT(arm_app) ((arm_app) & 0x80000000)
@@ -373,12 +372,8 @@ extern int av7110_firmversion(struct av7110 *av7110);
extern int av7110_wait_msgstate(struct av7110 *av7110, u16 flags);
extern int av7110_fw_cmd(struct av7110 *av7110, int type, int com, int num, ...);
-extern int __av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length);
-extern int av7110_send_fw_cmd(struct av7110 *av7110, u16* buf, int length);
-extern int av7110_send_ci_cmd(struct av7110 *av7110, u8 subcom, u8 *buf, u8 len);
extern int av7110_fw_request(struct av7110 *av7110, u16 *request_buf,
int request_buf_len, u16 *reply_buf, int reply_buf_len);
-extern int av7110_fw_query(struct av7110 *av7110, u16 tag, u16* Buff, s16 length);
/* DEBI (saa7146 data extension bus interface) access */
diff --git a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c
index 6d2256f1e35..665cdb8a3f7 100644
--- a/drivers/media/dvb/ttpci/av7110_ir.c
+++ b/drivers/media/dvb/ttpci/av7110_ir.c
@@ -10,7 +10,7 @@
#define UP_TIMEOUT (HZ/4)
-/* enable ir debugging by or'ing av7110_debug with 16 */
+/* enable ir debugging by or'ing debug with 16 */
static int ir_initialized;
static struct input_dev input_dev;
diff --git a/drivers/media/dvb/ttpci/av7110_v4l.c b/drivers/media/dvb/ttpci/av7110_v4l.c
index eb84fb08d95..e65fc36e2ce 100644
--- a/drivers/media/dvb/ttpci/av7110_v4l.c
+++ b/drivers/media/dvb/ttpci/av7110_v4l.c
@@ -46,13 +46,13 @@ int msp_writereg(struct av7110 *av7110, u8 dev, u16 reg, u16 val)
if (i2c_transfer(&av7110->i2c_adap, &msgs, 1) != 1) {
dprintk(1, "dvb-ttpci: failed @ card %d, %u = %u\n",
- av7110->dvb_adapter->num, reg, val);
+ av7110->dvb_adapter.num, reg, val);
return -EIO;
}
return 0;
}
-int msp_readreg(struct av7110 *av7110, u8 dev, u16 reg, u16 *val)
+static int msp_readreg(struct av7110 *av7110, u8 dev, u16 reg, u16 *val)
{
u8 msg1[3] = { dev, reg >> 8, reg & 0xff };
u8 msg2[2];
@@ -63,7 +63,7 @@ int msp_readreg(struct av7110 *av7110, u8 dev, u16 reg, u16 *val)
if (i2c_transfer(&av7110->i2c_adap, &msgs[0], 2) != 2) {
dprintk(1, "dvb-ttpci: failed @ card %d, %u\n",
- av7110->dvb_adapter->num, reg);
+ av7110->dvb_adapter.num, reg);
return -EIO;
}
*val = (msg2[0] << 8) | msg2[1];
@@ -552,13 +552,13 @@ int av7110_init_analog_module(struct av7110 *av7110)
return -ENODEV;
printk("dvb-ttpci: DVB-C analog module @ card %d detected, initializing MSP3400\n",
- av7110->dvb_adapter->num);
+ av7110->dvb_adapter.num);
av7110->adac_type = DVB_ADAC_MSP;
msleep(100); // the probing above resets the msp...
msp_readreg(av7110, MSP_RD_DSP, 0x001e, &version1);
msp_readreg(av7110, MSP_RD_DSP, 0x001f, &version2);
dprintk(1, "dvb-ttpci: @ card %d MSP3400 version 0x%04x 0x%04x\n",
- av7110->dvb_adapter->num, version1, version2);
+ av7110->dvb_adapter.num, version1, version2);
msp_writereg(av7110, MSP_WR_DSP, 0x0013, 0x0c00);
msp_writereg(av7110, MSP_WR_DSP, 0x0000, 0x7f00); // loudspeaker + headphone
msp_writereg(av7110, MSP_WR_DSP, 0x0008, 0x0220); // loudspeaker source
@@ -596,7 +596,7 @@ int av7110_init_analog_module(struct av7110 *av7110)
/* init the saa7113 */
while (*i != 0xff) {
if (i2c_writereg(av7110, 0x48, i[0], i[1]) != 1) {
- dprintk(1, "saa7113 initialization failed @ card %d", av7110->dvb_adapter->num);
+ dprintk(1, "saa7113 initialization failed @ card %d", av7110->dvb_adapter.num);
break;
}
i += 2;
@@ -726,11 +726,11 @@ static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std)
{
struct av7110 *av7110 = (struct av7110*) dev->ext_priv;
- if (std->id == V4L2_STD_PAL) {
+ if (std->id & V4L2_STD_PAL) {
av7110->vidmode = VIDEO_MODE_PAL;
av7110_set_vidmode(av7110, av7110->vidmode);
}
- else if (std->id == V4L2_STD_NTSC) {
+ else if (std->id & V4L2_STD_NTSC) {
av7110->vidmode = VIDEO_MODE_NTSC;
av7110_set_vidmode(av7110, av7110->vidmode);
}
diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c
index 14e963206b8..6e0f5d307c5 100644
--- a/drivers/media/dvb/ttpci/budget-av.c
+++ b/drivers/media/dvb/ttpci/budget-av.c
@@ -59,8 +59,12 @@ struct budget_av {
struct dvb_ca_en50221 ca;
};
-static int enable_ci = 0;
-
+/* GPIO CI Connections:
+ * 0 - Vcc/Reset (Reset is controlled by capacitor)
+ * 1 - Attribute Memory
+ * 2 - Card Enable (Active Low)
+ * 3 - Card Detect
+ */
/****************************************************************************
* INITIALIZATION
@@ -188,22 +192,35 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)
{
struct budget_av *budget_av = (struct budget_av *) ca->data;
struct saa7146_dev *saa = budget_av->budget.dev;
- int max = 20;
+ int timeout = 50; // 5 seconds (4.4.6 Ready)
if (slot != 0)
return -EINVAL;
dprintk(1, "ciintf_slot_reset\n");
- /* reset the card */
- saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI);
- msleep(100);
- saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
+ saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
- while (--max > 0 && ciintf_read_attribute_mem(ca, slot, 0) != 0x1d)
+ saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); /* Vcc off */
+ msleep(2);
+ saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); /* Vcc on */
+ msleep(20); /* 20 ms Vcc settling time */
+
+ saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); /* enable card */
+
+ /* This should have been based on pin 16 READY of the pcmcia port,
+ * but AFAICS it is not routed to the saa7146 */
+ while (--timeout > 0 && ciintf_read_attribute_mem(ca, slot, 0) != 0x1d)
msleep(100);
- ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);
+ if (timeout <= 0)
+ {
+ printk(KERN_ERR "budget-av: cam reset failed (timeout).\n");
+ saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
+ saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); /* Vcc off */
+ return -ETIMEDOUT;
+ }
+
return 0;
}
@@ -240,7 +257,6 @@ static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open
{
struct budget_av *budget_av = (struct budget_av *) ca->data;
struct saa7146_dev *saa = budget_av->budget.dev;
- int cam = 0;
if (slot != 0)
return -EINVAL;
@@ -248,15 +264,21 @@ static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open
if (!budget_av->slot_status) {
saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);
udelay(1);
- cam = saa7146_read(saa, PSR) & MASK_06;
- saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
-
- if (cam)
+ if (saa7146_read(saa, PSR) & MASK_06)
+ {
+ printk(KERN_INFO "budget-av: cam inserted\n");
budget_av->slot_status = 1;
+ }
+ saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
} else if (!open) {
saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);
if (ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1) == -ETIMEDOUT)
+ {
+ printk(KERN_INFO "budget-av: cam ejected\n");
+ saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */
+ saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); /* Vcc off */
budget_av->slot_status = 0;
+ }
}
if (budget_av->slot_status == 1)
@@ -272,17 +294,11 @@ static int ciintf_init(struct budget_av *budget_av)
memset(&budget_av->ca, 0, sizeof(struct dvb_ca_en50221));
- /* setup GPIOs */
- saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTHI);
+ saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
+ saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);
saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO);
saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);
- /* Reset the card */
- saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI);
- msleep(50);
- saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);
- msleep(100);
-
/* Enable DEBI pins */
saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800);
@@ -297,13 +313,14 @@ static int ciintf_init(struct budget_av *budget_av)
budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable;
budget_av->ca.poll_slot_status = ciintf_poll_slot_status;
budget_av->ca.data = budget_av;
- if ((result = dvb_ca_en50221_init(budget_av->budget.dvb_adapter,
+
+ if ((result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter,
&budget_av->ca, 0, 1)) != 0) {
- printk("budget_av: CI interface detected, but initialisation failed.\n");
+ printk(KERN_ERR "budget-av: ci initialisation failed.\n");
goto error;
}
- // success!
- printk("ciintf_init: CI interface initialised\n");
+
+ printk(KERN_INFO "budget-av: ci interface initialised.\n");
budget_av->budget.ci_present = 1;
return 0;
@@ -361,8 +378,12 @@ static const u8 saa7113_tab[] = {
static int saa7113_init(struct budget_av *budget_av)
{
struct budget *budget = &budget_av->budget;
+ struct saa7146_dev *saa = budget->dev;
const u8 *data = saa7113_tab;
+ saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI);
+ msleep(200);
+
if (i2c_writereg(&budget->i2c_adap, 0x4a, 0x01, 0x08) != 1) {
dprintk(1, "saa7113 not found on KNC card\n");
return -ENODEV;
@@ -697,75 +718,90 @@ static u8 read_pwm(struct budget_av *budget_av)
return pwm;
}
+#define SUBID_DVBS_KNC1 0x0010
+#define SUBID_DVBS_KNC1_PLUS 0x0011
+#define SUBID_DVBS_TYPHOON 0x4f56
+#define SUBID_DVBS_CINERGY1200 0x1154
+
+#define SUBID_DVBC_KNC1 0x0020
+#define SUBID_DVBC_KNC1_PLUS 0x0021
+#define SUBID_DVBC_CINERGY1200 0x1156
+
+#define SUBID_DVBT_KNC1_PLUS 0x0031
+#define SUBID_DVBT_KNC1 0x0030
+#define SUBID_DVBT_CINERGY1200 0x1157
static void frontend_init(struct budget_av *budget_av)
{
- switch (budget_av->budget.dev->pci->subsystem_device) {
- case 0x4f56: // Typhoon/KNC1 DVB-S budget (stv0299/Philips SU1278(tsa5059))
- budget_av->budget.dvb_frontend =
- stv0299_attach(&typhoon_config, &budget_av->budget.i2c_adap);
- if (budget_av->budget.dvb_frontend != NULL) {
+ struct saa7146_dev * saa = budget_av->budget.dev;
+ struct dvb_frontend * fe = NULL;
+
+ switch (saa->pci->subsystem_device) {
+ case SUBID_DVBS_KNC1_PLUS:
+ case SUBID_DVBC_KNC1_PLUS:
+ case SUBID_DVBT_KNC1_PLUS:
+ // Enable / PowerON Frontend
+ saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI);
break;
- }
+ }
+
+ switch (saa->pci->subsystem_device) {
+
+ case SUBID_DVBS_KNC1:
+ case SUBID_DVBS_KNC1_PLUS:
+ case SUBID_DVBS_TYPHOON:
+ fe = stv0299_attach(&typhoon_config,
+ &budget_av->budget.i2c_adap);
break;
- case 0x0020: // KNC1 DVB-C budget (tda10021/Philips CU1216(tua6034))
- budget_av->budget.dvb_frontend =
- tda10021_attach(&philips_cu1216_config,
- &budget_av->budget.i2c_adap, read_pwm(budget_av));
- if (budget_av->budget.dvb_frontend != NULL) {
- break;
- }
+ case SUBID_DVBS_CINERGY1200:
+ fe = stv0299_attach(&cinergy_1200s_config,
+ &budget_av->budget.i2c_adap);
break;
- case 0x0030: // KNC1 DVB-T budget (tda10046/Philips TU1216(tda6651tt))
- budget_av->budget.dvb_frontend =
- tda10046_attach(&philips_tu1216_config, &budget_av->budget.i2c_adap);
- if (budget_av->budget.dvb_frontend != NULL) {
- break;
- }
+ case SUBID_DVBC_KNC1:
+ case SUBID_DVBC_KNC1_PLUS:
+ fe = tda10021_attach(&philips_cu1216_config,
+ &budget_av->budget.i2c_adap,
+ read_pwm(budget_av));
break;
- case 0x1154: // TerraTec Cinergy 1200 DVB-S (stv0299/Philips SU1278(tsa5059))
- budget_av->budget.dvb_frontend =
- stv0299_attach(&cinergy_1200s_config, &budget_av->budget.i2c_adap);
- if (budget_av->budget.dvb_frontend != NULL) {
- break;
- }
+ case SUBID_DVBT_KNC1:
+ case SUBID_DVBT_KNC1_PLUS:
+ fe = tda10046_attach(&philips_tu1216_config,
+ &budget_av->budget.i2c_adap);
break;
- case 0x1156: // Terratec Cinergy 1200 DVB-C (tda10021/Philips CU1216(tua6034))
- budget_av->budget.dvb_frontend =
- tda10021_attach(&philips_cu1216_config,
- &budget_av->budget.i2c_adap, read_pwm(budget_av));
- if (budget_av->budget.dvb_frontend) {
- break;
- }
+ case SUBID_DVBC_CINERGY1200:
+ fe = tda10021_attach(&philips_cu1216_config,
+ &budget_av->budget.i2c_adap,
+ read_pwm(budget_av));
break;
- case 0x1157: // Terratec Cinergy 1200 DVB-T (tda10046/Philips TU1216(tda6651tt))
- budget_av->budget.dvb_frontend =
- tda10046_attach(&philips_tu1216_config, &budget_av->budget.i2c_adap);
- if (budget_av->budget.dvb_frontend) {
- break;
- }
+ case SUBID_DVBT_CINERGY1200:
+ fe = tda10046_attach(&philips_tu1216_config,
+ &budget_av->budget.i2c_adap);
break;
}
- if (budget_av->budget.dvb_frontend == NULL) {
- printk("budget_av: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n",
- budget_av->budget.dev->pci->vendor,
- budget_av->budget.dev->pci->device,
- budget_av->budget.dev->pci->subsystem_vendor,
- budget_av->budget.dev->pci->subsystem_device);
- } else {
- if (dvb_register_frontend
- (budget_av->budget.dvb_adapter, budget_av->budget.dvb_frontend)) {
- printk("budget-av: Frontend registration failed!\n");
- if (budget_av->budget.dvb_frontend->ops->release)
- budget_av->budget.dvb_frontend->ops->release(budget_av->budget.dvb_frontend);
- budget_av->budget.dvb_frontend = NULL;
- }
+ if (fe == NULL) {
+ printk(KERN_ERR "budget-av: A frontend driver was not found "
+ "for device %04x/%04x subsystem %04x/%04x\n",
+ saa->pci->vendor,
+ saa->pci->device,
+ saa->pci->subsystem_vendor,
+ saa->pci->subsystem_device);
+ return;
+ }
+
+ budget_av->budget.dvb_frontend = fe;
+
+ if (dvb_register_frontend(&budget_av->budget.dvb_adapter,
+ budget_av->budget.dvb_frontend)) {
+ printk(KERN_ERR "budget-av: Frontend registration failed!\n");
+ if (budget_av->budget.dvb_frontend->ops->release)
+ budget_av->budget.dvb_frontend->ops->release(budget_av->budget.dvb_frontend);
+ budget_av->budget.dvb_frontend = NULL;
}
}
@@ -822,6 +858,7 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
memset(budget_av, 0, sizeof(struct budget_av));
+ budget_av->has_saa7113 = 0;
budget_av->budget.ci_present = 0;
dev->ext_priv = budget_av;
@@ -836,10 +873,7 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
saa7146_write(dev, DD1_INIT, 0x07000600);
saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26);
- saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI);
- msleep(500);
-
- if (0 == saa7113_init(budget_av)) {
+ if (saa7113_init(budget_av) == 0) {
budget_av->has_saa7113 = 1;
if (0 != saa7146_vv_init(dev, &vv_data)) {
@@ -860,31 +894,26 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
saa7113_setinput(budget_av, 0);
} else {
- budget_av->has_saa7113 = 0;
-
- saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);
+ ciintf_init(budget_av);
}
/* fixme: find some sane values here... */
saa7146_write(dev, PCI_BT_V1, 0x1c00101f);
- mac = budget_av->budget.dvb_adapter->proposed_mac;
+ mac = budget_av->budget.dvb_adapter.proposed_mac;
if (i2c_readregs(&budget_av->budget.i2c_adap, 0xa0, 0x30, mac, 6)) {
- printk("KNC1-%d: Could not read MAC from KNC1 card\n",
- budget_av->budget.dvb_adapter->num);
+ printk(KERN_ERR "KNC1-%d: Could not read MAC from KNC1 card\n",
+ budget_av->budget.dvb_adapter.num);
memset(mac, 0, 6);
} else {
- printk("KNC1-%d: MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
- budget_av->budget.dvb_adapter->num,
+ printk(KERN_INFO "KNC1-%d: MAC addr = %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
+ budget_av->budget.dvb_adapter.num,
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
- budget_av->budget.dvb_adapter->priv = budget_av;
+ budget_av->budget.dvb_adapter.priv = budget_av;
frontend_init(budget_av);
- if (enable_ci)
- ciintf_init(budget_av);
-
return 0;
}
@@ -963,14 +992,21 @@ static struct saa7146_extension budget_extension;
MAKE_BUDGET_INFO(knc1s, "KNC1 DVB-S", BUDGET_KNC1S);
MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BUDGET_KNC1C);
MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T);
+MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP);
+MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP);
+MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP);
MAKE_BUDGET_INFO(cin1200s, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);
MAKE_BUDGET_INFO(cin1200c, "Terratec Cinergy 1200 DVB-C", BUDGET_CIN1200C);
MAKE_BUDGET_INFO(cin1200t, "Terratec Cinergy 1200 DVB-T", BUDGET_CIN1200T);
static struct pci_device_id pci_tbl[] = {
MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56),
+ MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x0010),
+ MAKE_EXTENSION_PCI(knc1sp, 0x1131, 0x0011),
MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),
+ MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),
MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),
+ MAKE_EXTENSION_PCI(knc1tp, 0x1894, 0x0031),
MAKE_EXTENSION_PCI(cin1200s, 0x153b, 0x1154),
MAKE_EXTENSION_PCI(cin1200c, 0x153b, 0x1156),
MAKE_EXTENSION_PCI(cin1200t, 0x153b, 0x1157),
@@ -1010,5 +1046,3 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");
MODULE_DESCRIPTION("driver for the SAA7146 based so-called "
"budget PCI DVB w/ analog input and CI-module (e.g. the KNC cards)");
-module_param_named(enable_ci, enable_ci, int, 0644);
-MODULE_PARM_DESC(enable_ci, "Turn on/off CI module (default:off).");
diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c
index 521111be355..dce11611137 100644
--- a/drivers/media/dvb/ttpci/budget-ci.c
+++ b/drivers/media/dvb/ttpci/budget-ci.c
@@ -395,7 +395,7 @@ static int ciintf_init(struct budget_ci *budget_ci)
budget_ci->ca.slot_shutdown = ciintf_slot_shutdown;
budget_ci->ca.slot_ts_enable = ciintf_slot_ts_enable;
budget_ci->ca.data = budget_ci;
- if ((result = dvb_ca_en50221_init(budget_ci->budget.dvb_adapter,
+ if ((result = dvb_ca_en50221_init(&budget_ci->budget.dvb_adapter,
&budget_ci->ca,
DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE |
DVB_CA_EN50221_FLAG_IRQ_FR |
@@ -881,7 +881,7 @@ static void frontend_init(struct budget_ci *budget_ci)
budget_ci->budget.dev->pci->subsystem_device);
} else {
if (dvb_register_frontend
- (budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) {
+ (&budget_ci->budget.dvb_adapter, budget_ci->budget.dvb_frontend)) {
printk("budget-ci: Frontend registration failed!\n");
if (budget_ci->budget.dvb_frontend->ops->release)
budget_ci->budget.dvb_frontend->ops->release(budget_ci->budget.dvb_frontend);
@@ -916,7 +916,7 @@ static int budget_ci_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio
ciintf_init(budget_ci);
- budget_ci->budget.dvb_adapter->priv = budget_ci;
+ budget_ci->budget.dvb_adapter.priv = budget_ci;
frontend_init(budget_ci);
return 0;
diff --git a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c
index 93a9b40917e..0498a055a4c 100644
--- a/drivers/media/dvb/ttpci/budget-core.c
+++ b/drivers/media/dvb/ttpci/budget-core.c
@@ -298,7 +298,7 @@ static int budget_register(struct budget *budget)
budget->dmxdev.demux = &dvbdemux->dmx;
budget->dmxdev.capabilities = 0;
- dvb_dmxdev_init(&budget->dmxdev, budget->dvb_adapter);
+ dvb_dmxdev_init(&budget->dmxdev, &budget->dvb_adapter);
budget->hw_frontend.source = DMX_FRONTEND_0;
@@ -316,7 +316,7 @@ static int budget_register(struct budget *budget)
if (ret < 0)
return ret;
- dvb_net_init(budget->dvb_adapter, &budget->dvb_net, &dvbdemux->dmx);
+ dvb_net_init(&budget->dvb_adapter, &budget->dvb_net, &dvbdemux->dmx);
return 0;
}
@@ -385,11 +385,11 @@ int ttpci_budget_init(struct budget *budget, struct saa7146_dev *dev,
strcpy(budget->i2c_adap.name, budget->card->name);
if (i2c_add_adapter(&budget->i2c_adap) < 0) {
- dvb_unregister_adapter(budget->dvb_adapter);
+ dvb_unregister_adapter(&budget->dvb_adapter);
return -ENOMEM;
}
- ttpci_eeprom_parse_mac(&budget->i2c_adap, budget->dvb_adapter->proposed_mac);
+ ttpci_eeprom_parse_mac(&budget->i2c_adap, budget->dvb_adapter.proposed_mac);
if (NULL ==
(budget->grabbing = saa7146_vmalloc_build_pgtable(dev->pci, length, &budget->pt))) {
@@ -417,7 +417,7 @@ err:
vfree(budget->grabbing);
- dvb_unregister_adapter(budget->dvb_adapter);
+ dvb_unregister_adapter(&budget->dvb_adapter);
return ret;
}
@@ -432,7 +432,7 @@ int ttpci_budget_deinit(struct budget *budget)
i2c_del_adapter(&budget->i2c_adap);
- dvb_unregister_adapter(budget->dvb_adapter);
+ dvb_unregister_adapter(&budget->dvb_adapter);
tasklet_kill(&budget->vpe_tasklet);
diff --git a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c
index 5d524a4f213..8142e26b47f 100644
--- a/drivers/media/dvb/ttpci/budget-patch.c
+++ b/drivers/media/dvb/ttpci/budget-patch.c
@@ -453,7 +453,7 @@ static void frontend_init(struct budget_patch* budget)
budget->dev->pci->subsystem_vendor,
budget->dev->pci->subsystem_device);
} else {
- if (dvb_register_frontend(budget->dvb_adapter, budget->dvb_frontend)) {
+ if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend)) {
printk("budget-av: Frontend registration failed!\n");
if (budget->dvb_frontend->ops->release)
budget->dvb_frontend->ops->release(budget->dvb_frontend);
@@ -702,7 +702,7 @@ static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_exte
dev->ext_priv = budget;
- budget->dvb_adapter->priv = budget;
+ budget->dvb_adapter.priv = budget;
frontend_init(budget);
return 0;
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c
index 5e6a10f4ad9..083fd44e5f9 100644
--- a/drivers/media/dvb/ttpci/budget.c
+++ b/drivers/media/dvb/ttpci/budget.c
@@ -468,7 +468,7 @@ static void frontend_init(struct budget *budget)
budget->dev->pci->subsystem_vendor,
budget->dev->pci->subsystem_device);
} else {
- if (dvb_register_frontend(budget->dvb_adapter, budget->dvb_frontend)) {
+ if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend)) {
printk("budget: Frontend registration failed!\n");
if (budget->dvb_frontend->ops->release)
budget->dvb_frontend->ops->release(budget->dvb_frontend);
@@ -497,7 +497,7 @@ static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_
return err;
}
- budget->dvb_adapter->priv = budget;
+ budget->dvb_adapter.priv = budget;
frontend_init(budget);
return 0;
diff --git a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h
index 10bd41f0363..c6ef496ba70 100644
--- a/drivers/media/dvb/ttpci/budget.h
+++ b/drivers/media/dvb/ttpci/budget.h
@@ -64,7 +64,7 @@ struct budget {
spinlock_t debilock;
- struct dvb_adapter *dvb_adapter;
+ struct dvb_adapter dvb_adapter;
struct dvb_frontend *dvb_frontend;
void *priv;
};
@@ -92,6 +92,9 @@ static struct saa7146_pci_extension_data x_var = { \
#define BUDGET_KNC1S 8
#define BUDGET_KNC1C 9
#define BUDGET_KNC1T 10
+#define BUDGET_KNC1SP 11
+#define BUDGET_KNC1CP 12
+#define BUDGET_KNC1TP 13
#define BUDGET_VIDEO_PORTA 0
#define BUDGET_VIDEO_PORTB 1
diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
index 4c046ece883..afa0e7a0e50 100644
--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
@@ -84,7 +84,7 @@ struct ttusb {
struct semaphore semi2c;
struct semaphore semusb;
- struct dvb_adapter *adapter;
+ struct dvb_adapter adapter;
struct usb_device *dev;
struct i2c_adapter i2c_adap;
@@ -1065,7 +1065,7 @@ static int alps_tdmb7_pll_set(struct dvb_frontend* fe, struct dvb_frontend_param
return 0;
}
-struct cx22700_config alps_tdmb7_config = {
+static struct cx22700_config alps_tdmb7_config = {
.demod_address = 0x43,
.pll_set = alps_tdmb7_pll_set,
};
@@ -1412,7 +1412,7 @@ static void frontend_init(struct ttusb* ttusb)
le16_to_cpu(ttusb->dev->descriptor.idVendor),
le16_to_cpu(ttusb->dev->descriptor.idProduct));
} else {
- if (dvb_register_frontend(ttusb->adapter, ttusb->fe)) {
+ if (dvb_register_frontend(&ttusb->adapter, ttusb->fe)) {
printk("dvb-ttusb-budget: Frontend registration failed!\n");
if (ttusb->fe->ops->release)
ttusb->fe->ops->release(ttusb->fe);
@@ -1462,7 +1462,7 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
up(&ttusb->semi2c);
dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE);
- ttusb->adapter->priv = ttusb;
+ ttusb->adapter.priv = ttusb;
/* i2c */
memset(&ttusb->i2c_adap, 0, sizeof(struct i2c_adapter));
@@ -1481,7 +1481,7 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
result = i2c_add_adapter(&ttusb->i2c_adap);
if (result) {
- dvb_unregister_adapter (ttusb->adapter);
+ dvb_unregister_adapter (&ttusb->adapter);
return result;
}
@@ -1503,7 +1503,7 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
if ((result = dvb_dmx_init(&ttusb->dvb_demux)) < 0) {
printk("ttusb_dvb: dvb_dmx_init failed (errno = %d)\n", result);
i2c_del_adapter(&ttusb->i2c_adap);
- dvb_unregister_adapter (ttusb->adapter);
+ dvb_unregister_adapter (&ttusb->adapter);
return -ENODEV;
}
//FIXME dmxdev (nur WAS?)
@@ -1511,21 +1511,21 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
ttusb->dmxdev.demux = &ttusb->dvb_demux.dmx;
ttusb->dmxdev.capabilities = 0;
- if ((result = dvb_dmxdev_init(&ttusb->dmxdev, ttusb->adapter)) < 0) {
+ if ((result = dvb_dmxdev_init(&ttusb->dmxdev, &ttusb->adapter)) < 0) {
printk("ttusb_dvb: dvb_dmxdev_init failed (errno = %d)\n",
result);
dvb_dmx_release(&ttusb->dvb_demux);
i2c_del_adapter(&ttusb->i2c_adap);
- dvb_unregister_adapter (ttusb->adapter);
+ dvb_unregister_adapter (&ttusb->adapter);
return -ENODEV;
}
- if (dvb_net_init(ttusb->adapter, &ttusb->dvbnet, &ttusb->dvb_demux.dmx)) {
+ if (dvb_net_init(&ttusb->adapter, &ttusb->dvbnet, &ttusb->dvb_demux.dmx)) {
printk("ttusb_dvb: dvb_net_init failed!\n");
dvb_dmxdev_release(&ttusb->dmxdev);
dvb_dmx_release(&ttusb->dvb_demux);
i2c_del_adapter(&ttusb->i2c_adap);
- dvb_unregister_adapter (ttusb->adapter);
+ dvb_unregister_adapter (&ttusb->adapter);
return -ENODEV;
}
@@ -1559,7 +1559,7 @@ static void ttusb_disconnect(struct usb_interface *intf)
dvb_dmx_release(&ttusb->dvb_demux);
if (ttusb->fe != NULL) dvb_unregister_frontend(ttusb->fe);
i2c_del_adapter(&ttusb->i2c_adap);
- dvb_unregister_adapter(ttusb->adapter);
+ dvb_unregister_adapter(&ttusb->adapter);
ttusb_free_iso_urbs(ttusb);
diff --git a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
index 64e771bd890..505bdaff5a7 100644
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
@@ -98,7 +98,7 @@ struct ttusb_dec {
int can_playback;
/* DVB bits */
- struct dvb_adapter *adapter;
+ struct dvb_adapter adapter;
struct dmxdev dmxdev;
struct dvb_demux demux;
struct dmx_frontend frontend;
@@ -1435,7 +1435,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
printk("%s: dvb_dmx_init failed: error %d\n", __FUNCTION__,
result);
- dvb_unregister_adapter(dec->adapter);
+ dvb_unregister_adapter(&dec->adapter);
return result;
}
@@ -1444,12 +1444,12 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
dec->dmxdev.demux = &dec->demux.dmx;
dec->dmxdev.capabilities = 0;
- if ((result = dvb_dmxdev_init(&dec->dmxdev, dec->adapter)) < 0) {
+ if ((result = dvb_dmxdev_init(&dec->dmxdev, &dec->adapter)) < 0) {
printk("%s: dvb_dmxdev_init failed: error %d\n",
__FUNCTION__, result);
dvb_dmx_release(&dec->demux);
- dvb_unregister_adapter(dec->adapter);
+ dvb_unregister_adapter(&dec->adapter);
return result;
}
@@ -1463,7 +1463,7 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
dvb_dmxdev_release(&dec->dmxdev);
dvb_dmx_release(&dec->demux);
- dvb_unregister_adapter(dec->adapter);
+ dvb_unregister_adapter(&dec->adapter);
return result;
}
@@ -1476,12 +1476,12 @@ static int ttusb_dec_init_dvb(struct ttusb_dec *dec)
dec->demux.dmx.remove_frontend(&dec->demux.dmx, &dec->frontend);
dvb_dmxdev_release(&dec->dmxdev);
dvb_dmx_release(&dec->demux);
- dvb_unregister_adapter(dec->adapter);
+ dvb_unregister_adapter(&dec->adapter);
return result;
}
- dvb_net_init(dec->adapter, &dec->dvb_net, &dec->demux.dmx);
+ dvb_net_init(&dec->adapter, &dec->dvb_net, &dec->demux.dmx);
return 0;
}
@@ -1496,7 +1496,7 @@ static void ttusb_dec_exit_dvb(struct ttusb_dec *dec)
dvb_dmxdev_release(&dec->dmxdev);
dvb_dmx_release(&dec->demux);
if (dec->fe) dvb_unregister_frontend(dec->fe);
- dvb_unregister_adapter(dec->adapter);
+ dvb_unregister_adapter(&dec->adapter);
}
static void ttusb_dec_exit_rc(struct ttusb_dec *dec)
@@ -1565,15 +1565,15 @@ static void ttusb_dec_exit_filters(struct ttusb_dec *dec)
}
}
-int fe_send_command(struct dvb_frontend* fe, const u8 command,
- int param_length, const u8 params[],
- int *result_length, u8 cmd_result[])
+static int fe_send_command(struct dvb_frontend* fe, const u8 command,
+ int param_length, const u8 params[],
+ int *result_length, u8 cmd_result[])
{
struct ttusb_dec* dec = (struct ttusb_dec*) fe->dvb->priv;
return ttusb_dec_send_command(dec, command, param_length, params, result_length, cmd_result);
}
-struct ttusbdecfe_config fe_config = {
+static struct ttusbdecfe_config fe_config = {
.send_command = fe_send_command
};
@@ -1620,7 +1620,7 @@ static int ttusb_dec_probe(struct usb_interface *intf,
}
ttusb_dec_init_dvb(dec);
- dec->adapter->priv = dec;
+ dec->adapter.priv = dec;
switch (le16_to_cpu(id->idProduct)) {
case 0x1006:
dec->fe = ttusbdecfe_dvbs_attach(&fe_config);
@@ -1637,7 +1637,7 @@ static int ttusb_dec_probe(struct usb_interface *intf,
le16_to_cpu(dec->udev->descriptor.idVendor),
le16_to_cpu(dec->udev->descriptor.idProduct));
} else {
- if (dvb_register_frontend(dec->adapter, dec->fe)) {
+ if (dvb_register_frontend(&dec->adapter, dec->fe)) {
printk("budget-ci: Frontend registration failed!\n");
if (dec->fe->ops->release)
dec->fe->ops->release(dec->fe);
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index d3dd4228b72..f9383e7f34f 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -7,6 +7,19 @@ menu "Video For Linux"
comment "Video Adapters"
+config CONFIG_TUNER_MULTI_I2C
+ bool "Enable support for multiple I2C devices on Video Adapters (EXPERIMENTAL)"
+ depends on VIDEO_DEV && EXPERIMENTAL
+ ---help---
+ Some video adapters have more than one tuner inside. This patch
+ enables support for using more than one tuner. This is required
+ for some cards to allow tunning both video and radio.
+ It also improves I2C autodetection for these cards.
+
+ Only few tuners currently is supporting this. More to come.
+
+ It is safe to say 'Y' here even if your card has only one I2C tuner.
+
config VIDEO_BT848
tristate "BT848 Video For Linux"
depends on VIDEO_DEV && PCI && I2C
@@ -240,6 +253,7 @@ config VIDEO_SAA7134
select VIDEO_BUF
select VIDEO_IR
select VIDEO_TUNER
+ select CRC32
---help---
This is a video4linux driver for Philips SAA7130/7134 based
TV cards.
@@ -329,6 +343,7 @@ config VIDEO_CX88_DVB
select VIDEO_BUF_DVB
select DVB_MT352
select DVB_OR51132
+ select DVB_CX22702
---help---
This adds support for DVB/ATSC cards based on the
Connexant 2388x chip.
diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c
index 80254caa444..48989eda240 100644
--- a/drivers/media/video/adv7170.c
+++ b/drivers/media/video/adv7170.c
@@ -384,22 +384,14 @@ static unsigned short normal_i2c[] =
I2C_ADV7171 >> 1, (I2C_ADV7171 >> 1) + 1,
I2C_CLIENT_END
};
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
- .normal_i2c_range = normal_i2c_range,
- .probe = probe,
- .probe_range = probe_range,
- .ignore = ignore,
- .ignore_range = ignore_range,
- .force = force
+ .probe = &ignore,
+ .ignore = &ignore,
+ .force = &ignore,
};
static struct i2c_driver i2c_driver_adv7170;
diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
index 95d0974b0ab..f898b658637 100644
--- a/drivers/media/video/adv7175.c
+++ b/drivers/media/video/adv7175.c
@@ -434,22 +434,14 @@ static unsigned short normal_i2c[] =
I2C_ADV7176 >> 1, (I2C_ADV7176 >> 1) + 1,
I2C_CLIENT_END
};
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
- .normal_i2c_range = normal_i2c_range,
- .probe = probe,
- .probe_range = probe_range,
- .ignore = ignore,
- .ignore_range = ignore_range,
- .force = force
+ .probe = &ignore,
+ .ignore = &ignore,
+ .force = &ignore,
};
static struct i2c_driver i2c_driver_adv7175;
diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c
index cf0db2554a8..8733588f6db 100644
--- a/drivers/media/video/bt819.c
+++ b/drivers/media/video/bt819.c
@@ -500,22 +500,14 @@ static unsigned short normal_i2c[] = {
I2C_BT819 >> 1,
I2C_CLIENT_END,
};
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
- .normal_i2c_range = normal_i2c_range,
- .probe = probe,
- .probe_range = probe_range,
- .ignore = ignore,
- .ignore_range = ignore_range,
- .force = force
+ .probe = &ignore,
+ .ignore = &ignore,
+ .force = &ignore,
};
static struct i2c_driver i2c_driver_bt819;
diff --git a/drivers/media/video/bt832.c b/drivers/media/video/bt832.c
index efe605a113a..9a642c7de54 100644
--- a/drivers/media/video/bt832.c
+++ b/drivers/media/video/bt832.c
@@ -6,7 +6,7 @@
It outputs an 8-bit 4:2:2 YUV or YCrCb video signal which can be directly
connected to bt848/bt878 GPIO pins on this purpose.
(see: VLSI Vision Ltd. www.vvl.co.uk for camera datasheets)
-
+
Supported Cards:
- Pixelview Rev.4E: 0x8a
GPIO 0x400000 toggles Bt832 RESET, and the chip changes to i2c 0x88 !
@@ -31,16 +31,16 @@
#include <linux/errno.h>
#include <linux/slab.h>
-#include "id.h"
-#include "audiochip.h"
+#include <media/audiochip.h>
+#include <media/id.h>
#include "bttv.h"
#include "bt832.h"
MODULE_LICENSE("GPL");
/* Addresses to scan */
-static unsigned short normal_i2c[] = {I2C_CLIENT_END};
-static unsigned short normal_i2c_range[] = {I2C_BT832_ALT1>>1,I2C_BT832_ALT2>>1,I2C_CLIENT_END};
+static unsigned short normal_i2c[] = { I2C_BT832_ALT1>>1, I2C_BT832_ALT2>>1,
+ I2C_CLIENT_END };
I2C_CLIENT_INSMOD;
/* ---------------------------------------------------------------------- */
@@ -95,7 +95,7 @@ int bt832_init(struct i2c_client *i2c_client_s)
buf=kmalloc(65,GFP_KERNEL);
bt832_hexdump(i2c_client_s,buf);
-
+
if(buf[0x40] != 0x31) {
printk("bt832: this i2c chip is no bt832 (id=%02x). Detaching.\n",buf[0x40]);
kfree(buf);
@@ -135,7 +135,7 @@ int bt832_init(struct i2c_client *i2c_client_s)
buf[1]= 0x27 & (~0x01); // Default | !skip
if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
printk("bt832: i2c i/o error EO: rc == %d (should be 2)\n",rc);
-
+
bt832_hexdump(i2c_client_s,buf);
#if 0
@@ -168,8 +168,7 @@ int bt832_init(struct i2c_client *i2c_client_s)
-static int bt832_attach(struct i2c_adapter *adap, int addr,
- unsigned short flags, int kind)
+static int bt832_attach(struct i2c_adapter *adap, int addr, int kind)
{
struct bt832 *t;
@@ -184,27 +183,32 @@ static int bt832_attach(struct i2c_adapter *adap, int addr,
return -ENOMEM;
memset(t,0,sizeof(*t));
t->client = client_template;
- t->client.data = t;
+ i2c_set_clientdata(&t->client, t);
i2c_attach_client(&t->client);
if(! bt832_init(&t->client)) {
bt832_detach(&t->client);
return -1;
}
-
+
return 0;
}
static int bt832_probe(struct i2c_adapter *adap)
{
+#ifdef I2C_CLASS_TV_ANALOG
if (adap->class & I2C_CLASS_TV_ANALOG)
return i2c_probe(adap, &addr_data, bt832_attach);
+#else
+ if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
+ return i2c_probe(adap, &addr_data, bt832_attach);
+#endif
return 0;
}
static int bt832_detach(struct i2c_client *client)
{
- struct bt832 *t = (struct bt832*)client->data;
+ struct bt832 *t = i2c_get_clientdata(client);
printk("bt832: detach.\n");
i2c_detach_client(client);
@@ -215,7 +219,7 @@ static int bt832_detach(struct i2c_client *client)
static int
bt832_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
- struct bt832 *t = (struct bt832*)client->data;
+ struct bt832 *t = i2c_get_clientdata(client);
printk("bt832: command %x\n",cmd);
@@ -249,19 +253,18 @@ static struct i2c_driver driver = {
};
static struct i2c_client client_template =
{
- .name = "bt832",
- .flags = I2C_CLIENT_ALLOW_USE,
- .driver = &driver,
+ I2C_DEVNAME("bt832"),
+ .flags = I2C_CLIENT_ALLOW_USE,
+ .driver = &driver,
};
-int bt832_init_module(void)
+static int __init bt832_init_module(void)
{
- i2c_add_driver(&driver);
- return 0;
+ return i2c_add_driver(&driver);
}
-static void bt832_cleanup_module(void)
+static void __exit bt832_cleanup_module(void)
{
i2c_del_driver(&driver);
}
@@ -269,3 +272,10 @@ static void bt832_cleanup_module(void)
module_init(bt832_init_module);
module_exit(bt832_cleanup_module);
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/video/bt832.h b/drivers/media/video/bt832.h
index 7a98c06e0e3..9b6a8d2c96b 100644
--- a/drivers/media/video/bt832.h
+++ b/drivers/media/video/bt832.h
@@ -1,6 +1,6 @@
/* Bt832 CMOS Camera Video Processor (VP)
- The Bt832 CMOS Camera Video Processor chip connects a Quartsight CMOS
+ The Bt832 CMOS Camera Video Processor chip connects a Quartsight CMOS
color digital camera directly to video capture devices via an 8-bit,
4:2:2 YUV or YCrCb video interface.
@@ -85,7 +85,7 @@
#define BT832_DEVICE_ID 63
# define BT832_DEVICE_ID__31 0x31 // Bt832 has ID 0x31
-/* STMicroelectronivcs VV5404 camera module
+/* STMicroelectronivcs VV5404 camera module
i2c: 0x20: sensor address
i2c: 0xa0: eeprom for ccd defect map
*/
@@ -256,26 +256,26 @@ For the CCIR-601 standards, the sampling is based on a static orthogonal samplin
//===========================================================================
// Timing generator SRAM table values for CCIR601 720x480 NTSC
//===========================================================================
-// For NTSC CCIR656
+// For NTSC CCIR656
BYTE BtCard::SRAMTable_NTSC[] =
{
// SRAM Timing Table for NTSC
- 0x0c, 0xc0, 0x00,
- 0x00, 0x90, 0xc2,
- 0x03, 0x10, 0x03,
- 0x06, 0x10, 0x34,
- 0x12, 0x12, 0x65,
- 0x02, 0x13, 0x24,
- 0x19, 0x00, 0x24,
- 0x39, 0x00, 0x96,
- 0x59, 0x08, 0x93,
+ 0x0c, 0xc0, 0x00,
+ 0x00, 0x90, 0xc2,
+ 0x03, 0x10, 0x03,
+ 0x06, 0x10, 0x34,
+ 0x12, 0x12, 0x65,
+ 0x02, 0x13, 0x24,
+ 0x19, 0x00, 0x24,
+ 0x39, 0x00, 0x96,
+ 0x59, 0x08, 0x93,
0x83, 0x08, 0x97,
- 0x03, 0x50, 0x30,
- 0xc0, 0x40, 0x30,
- 0x86, 0x01, 0x01,
- 0xa6, 0x0d, 0x62,
- 0x03, 0x11, 0x61,
- 0x05, 0x37, 0x30,
+ 0x03, 0x50, 0x30,
+ 0xc0, 0x40, 0x30,
+ 0x86, 0x01, 0x01,
+ 0xa6, 0x0d, 0x62,
+ 0x03, 0x11, 0x61,
+ 0x05, 0x37, 0x30,
0xac, 0x21, 0x50
};
diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c
index 72c7eb0f8c2..a5d529ccf3a 100644
--- a/drivers/media/video/bt856.c
+++ b/drivers/media/video/bt856.c
@@ -288,22 +288,14 @@ bt856_command (struct i2c_client *client,
* concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
*/
static unsigned short normal_i2c[] = { I2C_BT856 >> 1, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
- .normal_i2c_range = normal_i2c_range,
- .probe = probe,
- .probe_range = probe_range,
- .ignore = ignore,
- .ignore_range = ignore_range,
- .force = force
+ .probe = &ignore,
+ .ignore = &ignore,
+ .force = &ignore,
};
static struct i2c_driver i2c_driver_bt856;
diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c
index 85224b90e39..251092e7f19 100644
--- a/drivers/media/video/bttv-cards.c
+++ b/drivers/media/video/bttv-cards.c
@@ -1,5 +1,5 @@
/*
- $Id: bttv-cards.c,v 1.47 2005/02/22 14:06:32 kraxel Exp $
+ $Id: bttv-cards.c,v 1.49 2005/06/10 17:20:24 mchehab Exp $
bttv-cards.c
@@ -51,6 +51,7 @@ static void avermedia_eeprom(struct bttv *btv);
static void osprey_eeprom(struct bttv *btv);
static void modtec_eeprom(struct bttv *btv);
static void init_PXC200(struct bttv *btv);
+static void init_RTV24(struct bttv *btv);
static void winview_audio(struct bttv *btv, struct video_audio *v, int set);
static void lt9415_audio(struct bttv *btv, struct video_audio *v, int set);
@@ -1946,7 +1947,6 @@ struct tvcard bttv_tvcards[] = {
.no_tda9875 = 1,
.no_tda7432 = 1,
.tuner_type = TUNER_ABSENT,
- .no_video = 1,
.pll = PLL_28,
},{
.name = "Teppro TEV-560/InterVision IV-560",
@@ -2252,6 +2252,20 @@ struct tvcard bttv_tvcards[] = {
.no_tda7432 = 1,
.no_tda9875 = 1,
.muxsel_hook = kodicom4400r_muxsel,
+},
+{
+ /* ---- card 0x85---------------------------------- */
+ /* Michael Henson <mhenson@clarityvi.com> */
+ /* Adlink RTV24 with special unlock codes */
+ .name = "Adlink RTV24",
+ .video_inputs = 4,
+ .audio_inputs = 1,
+ .tuner = 0,
+ .svhs = 2,
+ .muxsel = { 2, 3, 1, 0},
+ .tuner_type = -1,
+ .pll = PLL_28,
+
}};
static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
@@ -2637,6 +2651,10 @@ void __devinit bttv_init_card1(struct bttv *btv)
case BTTV_AVDVBT_771:
btv->use_i2c_hw = 1;
break;
+ case BTTV_ADLINK_RTV24:
+ init_RTV24( btv );
+ break;
+
}
if (!bttv_tvcards[btv->c.type].has_dvb)
bttv_reset_audio(btv);
@@ -2785,6 +2803,8 @@ void __devinit bttv_init_card2(struct bttv *btv)
}
btv->pll.pll_current = -1;
+ bttv_reset_audio(btv);
+
/* tuner configuration (from card list / autodetect / insmod option) */
if (UNSET != bttv_tvcards[btv->c.type].tuner_type)
if(UNSET == btv->tuner_type)
@@ -3305,6 +3325,83 @@ static void __devinit init_PXC200(struct bttv *btv)
}
+
+/* ----------------------------------------------------------------------- */
+/*
+ * The Adlink RTV-24 (aka Angelo) has some special initialisation to unlock
+ * it. This apparently involves the following procedure for each 878 chip:
+ *
+ * 1) write 0x00C3FEFF to the GPIO_OUT_EN register
+ *
+ * 2) write to GPIO_DATA
+ * - 0x0E
+ * - sleep 1ms
+ * - 0x10 + 0x0E
+ * - sleep 10ms
+ * - 0x0E
+ * read from GPIO_DATA into buf (uint_32)
+ * - if ( data>>18 & 0x01 != 0) || ( buf>>19 & 0x01 != 1 )
+ * error. ERROR_CPLD_Check_Failed stop.
+ *
+ * 3) write to GPIO_DATA
+ * - write 0x4400 + 0x0E
+ * - sleep 10ms
+ * - write 0x4410 + 0x0E
+ * - sleep 1ms
+ * - write 0x0E
+ * read from GPIO_DATA into buf (uint_32)
+ * - if ( buf>>18 & 0x01 ) || ( buf>>19 && 0x01 != 0 )
+ * error. ERROR_CPLD_Check_Failed.
+ */
+/* ----------------------------------------------------------------------- */
+void
+init_RTV24 (struct bttv *btv)
+{
+ uint32_t dataRead = 0;
+ long watchdog_value = 0x0E;
+
+ printk (KERN_INFO
+ "bttv%d: Adlink RTV-24 initialisation in progress ...\n",
+ btv->c.nr);
+
+ btwrite (0x00c3feff, BT848_GPIO_OUT_EN);
+
+ btwrite (0 + watchdog_value, BT848_GPIO_DATA);
+ msleep (1);
+ btwrite (0x10 + watchdog_value, BT848_GPIO_DATA);
+ msleep (10);
+ btwrite (0 + watchdog_value, BT848_GPIO_DATA);
+
+ dataRead = btread (BT848_GPIO_DATA);
+
+ if ((((dataRead >> 18) & 0x01) != 0) || (((dataRead >> 19) & 0x01) != 1)) {
+ printk (KERN_INFO
+ "bttv%d: Adlink RTV-24 initialisation(1) ERROR_CPLD_Check_Failed (read %d)\n",
+ btv->c.nr, dataRead);
+ }
+
+ btwrite (0x4400 + watchdog_value, BT848_GPIO_DATA);
+ msleep (10);
+ btwrite (0x4410 + watchdog_value, BT848_GPIO_DATA);
+ msleep (1);
+ btwrite (watchdog_value, BT848_GPIO_DATA);
+ msleep (1);
+ dataRead = btread (BT848_GPIO_DATA);
+
+ if ((((dataRead >> 18) & 0x01) != 0) || (((dataRead >> 19) & 0x01) != 0)) {
+ printk (KERN_INFO
+ "bttv%d: Adlink RTV-24 initialisation(2) ERROR_CPLD_Check_Failed (read %d)\n",
+ btv->c.nr, dataRead);
+
+ return;
+ }
+
+ printk (KERN_INFO
+ "bttv%d: Adlink RTV-24 initialisation complete.\n", btv->c.nr);
+}
+
+
+
/* ----------------------------------------------------------------------- */
/* Miro Pro radio stuff -- the tea5757 is connected to some GPIO ports */
/*
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
index 033cc5498f2..290289a9975 100644
--- a/drivers/media/video/bttv-driver.c
+++ b/drivers/media/video/bttv-driver.c
@@ -1,5 +1,5 @@
/*
- $Id: bttv-driver.c,v 1.37 2005/02/21 13:57:59 kraxel Exp $
+ $Id: bttv-driver.c,v 1.38 2005/06/10 17:20:24 mchehab Exp $
bttv - Bt848 frame grabber driver
diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c
index e3f477dff82..da448a5f9e9 100644
--- a/drivers/media/video/bttv-i2c.c
+++ b/drivers/media/video/bttv-i2c.c
@@ -1,5 +1,5 @@
/*
- $Id: bttv-i2c.c,v 1.18 2005/02/16 12:14:10 kraxel Exp $
+ $Id: bttv-i2c.c,v 1.21 2005/06/10 17:20:24 mchehab Exp $
bttv-i2c.c -- all the i2c code is here
@@ -363,6 +363,9 @@ int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1,
/* read EEPROM content */
void __devinit bttv_readee(struct bttv *btv, unsigned char *eedata, int addr)
{
+ memset(eedata, 0, 256);
+ if (0 != btv->i2c_rc)
+ return;
btv->i2c_client.addr = addr >> 1;
tveeprom_read(&btv->i2c_client, eedata, 256);
}
diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h
index 8322b66e090..191eaf1714b 100644
--- a/drivers/media/video/bttv.h
+++ b/drivers/media/video/bttv.h
@@ -1,5 +1,5 @@
/*
- * $Id: bttv.h,v 1.17 2005/02/22 14:06:32 kraxel Exp $
+ * $Id: bttv.h,v 1.18 2005/05/24 23:41:42 nsh Exp $
*
* bttv - Bt848 frame grabber driver
*
@@ -135,6 +135,7 @@
#define BTTV_DVICO_DVBT_LITE 0x80
#define BTTV_TIBET_CS16 0x83
#define BTTV_KODICOM_4400R 0x84
+#define BTTV_ADLINK_RTV24 0x85
/* i2c address list */
#define I2C_TSA5522 0xc2
diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h
index 1a9ba7e1cf5..7b6f1e85602 100644
--- a/drivers/media/video/bttvp.h
+++ b/drivers/media/video/bttvp.h
@@ -226,10 +226,6 @@ extern int fini_bttv_i2c(struct bttv *btv);
#define dprintk if (bttv_debug >= 1) printk
#define d2printk if (bttv_debug >= 2) printk
-/* our devices */
-#define BTTV_MAX 16
-extern unsigned int bttv_num;
-
#define BTTV_MAX_FBUF 0x208000
#define VBIBUF_SIZE (2048*VBI_MAXLINES*2)
#define BTTV_TIMEOUT (HZ/2) /* 0.5 seconds */
@@ -375,6 +371,10 @@ struct bttv {
unsigned int users;
struct bttv_fh init;
};
+
+/* our devices */
+#define BTTV_MAX 16
+extern unsigned int bttv_num;
extern struct bttv bttvs[BTTV_MAX];
/* private ioctls */
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index 46d6778b863..91f8afeded8 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -1,5 +1,5 @@
/*
- * $Id: cx88-blackbird.c,v 1.26 2005/03/07 15:58:05 kraxel Exp $
+ * $Id: cx88-blackbird.c,v 1.27 2005/06/03 13:31:50 mchehab Exp $
*
* Support for a cx23416 mpeg encoder via cx2388x host port.
* "blackbird" reference design.
@@ -61,37 +61,304 @@ static LIST_HEAD(cx8802_devlist);
#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF
-/*Firmware API commands*/
-#define IVTV_API_ENC_PING_FW 0x00000080
-#define IVTV_API_ENC_GETVER 0x000000C4
-#define IVTV_API_ENC_HALT_FW 0x000000C3
-#define IVTV_API_STD_TIMEOUT 0x00010000 /*units??*/
-//#define IVTV_API_ASSIGN_PGM_INDEX_INFO 0x000000c7
-#define IVTV_API_ASSIGN_STREAM_TYPE 0x000000b9
-#define IVTV_API_ASSIGN_OUTPUT_PORT 0x000000bb
-#define IVTV_API_ASSIGN_FRAMERATE 0x0000008f
-#define IVTV_API_ASSIGN_FRAME_SIZE 0x00000091
-#define IVTV_API_ASSIGN_ASPECT_RATIO 0x00000099
-#define IVTV_API_ASSIGN_BITRATES 0x00000095
-#define IVTV_API_ASSIGN_GOP_PROPERTIES 0x00000097
-#define IVTV_API_ASSIGN_3_2_PULLDOWN 0x000000b1
-#define IVTV_API_ASSIGN_GOP_CLOSURE 0x000000c5
-#define IVTV_API_ASSIGN_AUDIO_PROPERTIES 0x000000bd
-#define IVTV_API_ASSIGN_DNR_FILTER_MODE 0x0000009b
-#define IVTV_API_ASSIGN_DNR_FILTER_PROPS 0x0000009d
-#define IVTV_API_ASSIGN_CORING_LEVELS 0x0000009f
-#define IVTV_API_ASSIGN_SPATIAL_FILTER_TYPE 0x000000a1
-#define IVTV_API_ASSIGN_FRAME_DROP_RATE 0x000000d0
-#define IVTV_API_ASSIGN_PLACEHOLDER 0x000000d8
-#define IVTV_API_MUTE_VIDEO 0x000000d9
-#define IVTV_API_MUTE_AUDIO 0x000000da
-#define IVTV_API_INITIALIZE_INPUT 0x000000cd
-#define IVTV_API_REFRESH_INPUT 0x000000d3
-#define IVTV_API_ASSIGN_NUM_VSYNC_LINES 0x000000d6
-#define IVTV_API_BEGIN_CAPTURE 0x00000081
-//#define IVTV_API_PAUSE_ENCODER 0x000000d2
-//#define IVTV_API_EVENT_NOTIFICATION 0x000000d5
-#define IVTV_API_END_CAPTURE 0x00000082
+/* Firmware API commands */
+/* #define IVTV_API_STD_TIMEOUT 0x00010000 // 65536, units?? */
+#define IVTV_API_STD_TIMEOUT 500
+
+#define BLACKBIRD_API_PING 0x80
+#define BLACKBIRD_API_BEGIN_CAPTURE 0x81
+enum blackbird_capture_type {
+ BLACKBIRD_MPEG_CAPTURE,
+ BLACKBIRD_RAW_CAPTURE,
+ BLACKBIRD_RAW_PASSTHRU_CAPTURE
+};
+enum blackbird_capture_bits {
+ BLACKBIRD_RAW_BITS_NONE = 0x00,
+ BLACKBIRD_RAW_BITS_YUV_CAPTURE = 0x01,
+ BLACKBIRD_RAW_BITS_PCM_CAPTURE = 0x02,
+ BLACKBIRD_RAW_BITS_VBI_CAPTURE = 0x04,
+ BLACKBIRD_RAW_BITS_PASSTHRU_CAPTURE = 0x08,
+ BLACKBIRD_RAW_BITS_TO_HOST_CAPTURE = 0x10
+};
+#define BLACKBIRD_API_END_CAPTURE 0x82
+enum blackbird_capture_end {
+ BLACKBIRD_END_AT_GOP, /* stop at the end of gop, generate irq */
+ BLACKBIRD_END_NOW, /* stop immediately, no irq */
+};
+#define BLACKBIRD_API_SET_AUDIO_ID 0x89
+#define BLACKBIRD_API_SET_VIDEO_ID 0x8B
+#define BLACKBIRD_API_SET_PCR_ID 0x8D
+#define BLACKBIRD_API_SET_FRAMERATE 0x8F
+enum blackbird_framerate {
+ BLACKBIRD_FRAMERATE_NTSC_30, /* NTSC: 30fps */
+ BLACKBIRD_FRAMERATE_PAL_25 /* PAL: 25fps */
+};
+#define BLACKBIRD_API_SET_RESOLUTION 0x91
+#define BLACKBIRD_API_SET_VIDEO_BITRATE 0x95
+enum blackbird_video_bitrate_type {
+ BLACKBIRD_VIDEO_VBR,
+ BLACKBIRD_VIDEO_CBR
+};
+#define BLACKBIRD_PEAK_RATE_DIVISOR 400
+enum blackbird_mux_rate {
+ BLACKBIRD_MUX_RATE_DEFAULT,
+ /* dvd mux rate: multiply by 400 to get the actual rate */
+ BLACKBIRD_MUX_RATE_DVD = 25200
+};
+#define BLACKBIRD_API_SET_GOP_STRUCTURE 0x97
+#define BLACKBIRD_API_SET_ASPECT_RATIO 0x99
+enum blackbird_aspect_ratio {
+ BLACKBIRD_ASPECT_RATIO_FORBIDDEN,
+ BLACKBIRD_ASPECT_RATIO_1_1_SQUARE,
+ BLACKBIRD_ASPECT_RATIO_4_3,
+ BLACKBIRD_ASPECT_RATIO_16_9,
+ BLACKBIRD_ASPECT_RATIO_221_100,
+ BLACKBIRD_ASPECT_RATIO_RESERVED
+};
+#define BLACKBIRD_API_SET_DNR_MODE 0x9B
+enum blackbird_dnr_bits {
+ BLACKBIRD_DNR_BITS_MANUAL,
+ BLACKBIRD_DNR_BITS_AUTO_SPATIAL,
+ BLACKBIRD_DNR_BITS_AUTO_TEMPORAL,
+ BLACKBIRD_DNR_BITS_AUTO
+};
+enum blackbird_median_filter {
+ BLACKBIRD_MEDIAN_FILTER_DISABLED,
+ BLACKBIRD_MEDIAN_FILTER_HORIZONTAL,
+ BLACKBIRD_MEDIAN_FILTER_VERTICAL,
+ BLACKBIRD_MEDIAN_FILTER_HV,
+ BLACKBIRD_MEDIAN_FILTER_DIAGONAL
+};
+#define BLACKBIRD_API_SET_MANUAL_DNR 0x9D
+#define BLACKBIRD_API_SET_DNR_MEDIAN 0x9F
+#define BLACKBIRD_API_SET_SPATIAL_FILTER 0xA1
+enum blackbird_spatial_filter_luma {
+ BLACKBIRD_SPATIAL_FILTER_LUMA_DISABLED,
+ BLACKBIRD_SPATIAL_FILTER_LUMA_1D_HORIZ,
+ BLACKBIRD_SPATIAL_FILTER_LUMA_1D_VERT,
+ BLACKBIRD_SPATIAL_FILTER_LUMA_2D_HV, /* separable, default */
+ BLACKBIRD_SPATIAL_FILTER_LUMA_2D_SYMM /* symmetric non-separable */
+};
+enum blackbird_spatial_filter_chroma {
+ BLACKBIRD_SPATIAL_FILTER_CHROMA_DISABLED,
+ BLACKBIRD_SPATIAL_FILTER_CHROMA_1D_HORIZ /* default */
+};
+#define BLACKBIRD_API_SET_3_2_PULLDOWN 0xB1
+enum blackbird_pulldown {
+ BLACKBIRD_3_2_PULLDOWN_DISABLED,
+ BLACKBIRD_3_2_PULLDOWN_ENABLED
+};
+#define BLACKBIRD_API_SET_VBI_LINE_NO 0xB7
+enum blackbird_vbi_line_bits {
+ BLACKBIRD_VBI_LINE_BITS_TOP_FIELD,
+ BLACKBIRD_VBI_LINE_BITS_BOT_FIELD = (1 << 31),
+ BLACKBIRD_VBI_LINE_BITS_ALL_LINES = 0xFFFFFFFF
+};
+enum blackbird_vbi_line {
+ BLACKBIRD_VBI_LINE_DISABLED,
+ BLACKBIRD_VBI_LINE_ENABLED
+};
+enum blackbird_vbi_slicing {
+ BLACKBIRD_VBI_SLICING_NONE,
+ BLACKBIRD_VBI_SLICING_CLOSED_CAPTION
+};
+#define BLACKBIRD_API_SET_STREAM_TYPE 0xB9
+enum blackbird_stream_type {
+ BLACKBIRD_STREAM_PROGRAM,
+ BLACKBIRD_STREAM_TRANSPORT,
+ BLACKBIRD_STREAM_MPEG1,
+ BLACKBIRD_STREAM_PES_AV,
+ BLACKBIRD_STREAM_UNKNOWN4,
+ BLACKBIRD_STREAM_PES_VIDEO,
+ BLACKBIRD_STREAM_UNKNOWN6,
+ BLACKBIRD_STREAM_PES_AUDIO,
+ BLACKBIRD_STREAM_UNKNOWN8,
+ BLACKBIRD_STREAM_UNKNOWN9, /* audio/pcm ? */
+ BLACKBIRD_STREAM_DVD,
+ BLACKBIRD_STREAM_VCD,
+ BLACKBIRD_STREAM_UNKNOWN12 /* svcd/xvcd ? */
+};
+#define BLACKBIRD_API_SET_OUTPUT_PORT 0xBB
+enum blackbird_stream_port {
+ BLACKBIRD_OUTPUT_PORT_MEMORY,
+ BLACKBIRD_OUTPUT_PORT_STREAMING,
+ BLACKBIRD_OUTPUT_PORT_SERIAL
+};
+#define BLACKBIRD_API_SET_AUDIO_PARAMS 0xBD
+enum blackbird_audio_bits_sample_rate {
+ BLACKBIRD_AUDIO_BITS_44100HZ,
+ BLACKBIRD_AUDIO_BITS_48000HZ,
+ BLACKBIRD_AUDIO_BITS_32000HZ,
+ BLACKBIRD_AUDIO_BITS_RESERVED_HZ,
+};
+enum blackbird_audio_bits_encoding {
+ BLACKBIRD_AUDIO_BITS_LAYER_1 = 0x1 << 2,
+ BLACKBIRD_AUDIO_BITS_LAYER_2 = 0x2 << 2,
+};
+enum blackbird_audio_bits_bitrate_layer_1 {
+ BLACKBIRD_AUDIO_BITS_LAYER_1_FREE_FORMAT,
+ BLACKBIRD_AUDIO_BITS_LAYER_1_32 = 0x01 << 4,
+ BLACKBIRD_AUDIO_BITS_LAYER_1_64 = 0x02 << 4,
+ BLACKBIRD_AUDIO_BITS_LAYER_1_96 = 0x03 << 4,
+ BLACKBIRD_AUDIO_BITS_LAYER_1_128 = 0x04 << 4,
+ BLACKBIRD_AUDIO_BITS_LAYER_1_160 = 0x05 << 4,
+ BLACKBIRD_AUDIO_BITS_LAYER_1_192 = 0x06 << 4,
+ BLACKBIRD_AUDIO_BITS_LAYER_1_224 = 0x07 << 4,
+ BLACKBIRD_AUDIO_BITS_LAYER_1_256 = 0x08 << 4,
+ BLACKBIRD_AUDIO_BITS_LAYER_1_288 = 0x09 << 4,
+ BLACKBIRD_AUDIO_BITS_LAYER_1_320 = 0x0A << 4,
+ BLACKBIRD_AUDIO_BITS_LAYER_1_352 = 0x0B << 4,
+ BLACKBIRD_AUDIO_BITS_LAYER_1_384 = 0x0C << 4,
+ BLACKBIRD_AUDIO_BITS_LAYER_1_416 = 0x0D << 4,
+ BLACKBIRD_AUDIO_BITS_LAYER_1_448 = 0x0E << 4,
+};
+enum blackbird_audio_bits_bitrate_layer_2 {
+ BLACKBIRD_AUDIO_BITS_LAYER_2_FREE_FORMAT,
+ BLACKBIRD_AUDIO_BITS_LAYER_2_32 = 0x01 << 4,
+ BLACKBIRD_AUDIO_BITS_LAYER_2_48 = 0x02 << 4,
+ BLACKBIRD_AUDIO_BITS_LAYER_2_56 = 0x03 << 4,
+ BLACKBIRD_AUDIO_BITS_LAYER_2_64 = 0x04 << 4,
+ BLACKBIRD_AUDIO_BITS_LAYER_2_80 = 0x05 << 4,
+ BLACKBIRD_AUDIO_BITS_LAYER_2_96 = 0x06 << 4,
+ BLACKBIRD_AUDIO_BITS_LAYER_2_112 = 0x07 << 4,
+ BLACKBIRD_AUDIO_BITS_LAYER_2_128 = 0x08 << 4,
+ BLACKBIRD_AUDIO_BITS_LAYER_2_160 = 0x09 << 4,
+ BLACKBIRD_AUDIO_BITS_LAYER_2_192 = 0x0A << 4,
+ BLACKBIRD_AUDIO_BITS_LAYER_2_224 = 0x0B << 4,
+ BLACKBIRD_AUDIO_BITS_LAYER_2_256 = 0x0C << 4,
+ BLACKBIRD_AUDIO_BITS_LAYER_2_320 = 0x0D << 4,
+ BLACKBIRD_AUDIO_BITS_LAYER_2_384 = 0x0E << 4,
+};
+enum blackbird_audio_bits_mode {
+ BLACKBIRD_AUDIO_BITS_STEREO,
+ BLACKBIRD_AUDIO_BITS_JOINT_STEREO = 0x1 << 8,
+ BLACKBIRD_AUDIO_BITS_DUAL = 0x2 << 8,
+ BLACKBIRD_AUDIO_BITS_MONO = 0x3 << 8,
+};
+enum blackbird_audio_bits_mode_extension {
+ BLACKBIRD_AUDIO_BITS_BOUND_4,
+ BLACKBIRD_AUDIO_BITS_BOUND_8 = 0x1 << 10,
+ BLACKBIRD_AUDIO_BITS_BOUND_12 = 0x2 << 10,
+ BLACKBIRD_AUDIO_BITS_BOUND_16 = 0x3 << 10,
+};
+enum blackbird_audio_bits_emphasis {
+ BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE,
+ BLACKBIRD_AUDIO_BITS_EMPHASIS_50_15 = 0x1 << 12,
+ BLACKBIRD_AUDIO_BITS_EMPHASIS_RESERVED = 0x2 << 12,
+ BLACKBIRD_AUDIO_BITS_EMPHASIS_CCITT_J17 = 0x3 << 12,
+};
+enum blackbird_audio_bits_crc {
+ BLACKBIRD_AUDIO_BITS_CRC_OFF,
+ BLACKBIRD_AUDIO_BITS_CRC_ON = 0x1 << 14,
+};
+enum blackbird_audio_bits_copyright {
+ BLACKBIRD_AUDIO_BITS_COPYRIGHT_OFF,
+ BLACKBIRD_AUDIO_BITS_COPYRIGHT_ON = 0x1 << 15,
+};
+enum blackbird_audio_bits_original {
+ BLACKBIRD_AUDIO_BITS_COPY,
+ BLACKBIRD_AUDIO_BITS_ORIGINAL = 0x1 << 16,
+};
+#define BLACKBIRD_API_HALT 0xC3
+#define BLACKBIRD_API_GET_VERSION 0xC4
+#define BLACKBIRD_API_SET_GOP_CLOSURE 0xC5
+enum blackbird_gop_closure {
+ BLACKBIRD_GOP_CLOSURE_OFF,
+ BLACKBIRD_GOP_CLOSURE_ON,
+};
+#define BLACKBIRD_API_DATA_XFER_STATUS 0xC6
+enum blackbird_data_xfer_status {
+ BLACKBIRD_MORE_BUFFERS_FOLLOW,
+ BLACKBIRD_LAST_BUFFER,
+};
+#define BLACKBIRD_API_PROGRAM_INDEX_INFO 0xC7
+enum blackbird_picture_mask {
+ BLACKBIRD_PICTURE_MASK_NONE,
+ BLACKBIRD_PICTURE_MASK_I_FRAMES,
+ BLACKBIRD_PICTURE_MASK_I_P_FRAMES = 0x3,
+ BLACKBIRD_PICTURE_MASK_ALL_FRAMES = 0x7,
+};
+#define BLACKBIRD_API_SET_VBI_PARAMS 0xC8
+enum blackbird_vbi_mode_bits {
+ BLACKBIRD_VBI_BITS_SLICED,
+ BLACKBIRD_VBI_BITS_RAW,
+};
+enum blackbird_vbi_insertion_bits {
+ BLACKBIRD_VBI_BITS_INSERT_IN_XTENSION_USR_DATA,
+ BLACKBIRD_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1,
+ BLACKBIRD_VBI_BITS_SEPARATE_STREAM = 0x2 << 1,
+ BLACKBIRD_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1,
+ BLACKBIRD_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1,
+};
+#define BLACKBIRD_API_SET_DMA_BLOCK_SIZE 0xC9
+enum blackbird_dma_unit {
+ BLACKBIRD_DMA_BYTES,
+ BLACKBIRD_DMA_FRAMES,
+};
+#define BLACKBIRD_API_DMA_TRANSFER_INFO 0xCA
+#define BLACKBIRD_API_DMA_TRANSFER_STAT 0xCB
+enum blackbird_dma_transfer_status_bits {
+ BLACKBIRD_DMA_TRANSFER_BITS_DONE = 0x01,
+ BLACKBIRD_DMA_TRANSFER_BITS_ERROR = 0x04,
+ BLACKBIRD_DMA_TRANSFER_BITS_LL_ERROR = 0x10,
+};
+#define BLACKBIRD_API_SET_DMA2HOST_ADDR 0xCC
+#define BLACKBIRD_API_INIT_VIDEO_INPUT 0xCD
+#define BLACKBIRD_API_SET_FRAMESKIP 0xD0
+#define BLACKBIRD_API_PAUSE 0xD2
+enum blackbird_pause {
+ BLACKBIRD_PAUSE_ENCODING,
+ BLACKBIRD_RESUME_ENCODING,
+};
+#define BLACKBIRD_API_REFRESH_INPUT 0xD3
+#define BLACKBIRD_API_SET_COPYRIGHT 0xD4
+enum blackbird_copyright {
+ BLACKBIRD_COPYRIGHT_OFF,
+ BLACKBIRD_COPYRIGHT_ON,
+};
+#define BLACKBIRD_API_SET_NOTIFICATION 0xD5
+enum blackbird_notification_type {
+ BLACKBIRD_NOTIFICATION_REFRESH,
+};
+enum blackbird_notification_status {
+ BLACKBIRD_NOTIFICATION_OFF,
+ BLACKBIRD_NOTIFICATION_ON,
+};
+enum blackbird_notification_mailbox {
+ BLACKBIRD_NOTIFICATION_NO_MAILBOX = -1,
+};
+#define BLACKBIRD_API_SET_CAPTURE_LINES 0xD6
+enum blackbird_field1_lines {
+ BLACKBIRD_FIELD1_SAA7114 = 0x00EF, /* 239 */
+ BLACKBIRD_FIELD1_SAA7115 = 0x00F0, /* 240 */
+ BLACKBIRD_FIELD1_MICRONAS = 0x0105, /* 261 */
+};
+enum blackbird_field2_lines {
+ BLACKBIRD_FIELD2_SAA7114 = 0x00EF, /* 239 */
+ BLACKBIRD_FIELD2_SAA7115 = 0x00F0, /* 240 */
+ BLACKBIRD_FIELD2_MICRONAS = 0x0106, /* 262 */
+};
+#define BLACKBIRD_API_SET_CUSTOM_DATA 0xD7
+enum blackbird_custom_data_type {
+ BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
+ BLACKBIRD_CUSTOM_PRIVATE_PACKET,
+};
+#define BLACKBIRD_API_MUTE_VIDEO 0xD9
+enum blackbird_mute {
+ BLACKBIRD_UNMUTE,
+ BLACKBIRD_MUTE,
+};
+enum blackbird_mute_video_mask {
+ BLACKBIRD_MUTE_VIDEO_V_MASK = 0x0000FF00,
+ BLACKBIRD_MUTE_VIDEO_U_MASK = 0x00FF0000,
+ BLACKBIRD_MUTE_VIDEO_Y_MASK = 0xFF000000,
+};
+enum blackbird_mute_video_shift {
+ BLACKBIRD_MUTE_VIDEO_V_SHIFT = 8,
+ BLACKBIRD_MUTE_VIDEO_U_SHIFT = 16,
+ BLACKBIRD_MUTE_VIDEO_Y_SHIFT = 24,
+};
+#define BLACKBIRD_API_MUTE_AUDIO 0xDA
/* Registers */
#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8 /*| IVTV_REG_OFFSET*/)
@@ -405,68 +672,100 @@ static int blackbird_load_firmware(struct cx8802_dev *dev)
return 0;
}
+/**
+ Settings used by the windows tv app for PVR2000:
+=================================================================================================================
+Profile | Codec | Resolution | CBR/VBR | Video Qlty | V. Bitrate | Frmrate | Audio Codec | A. Bitrate | A. Mode
+-----------------------------------------------------------------------------------------------------------------
+MPEG-1 | MPEG1 | 352x288PAL | (CBR) | 1000:Optimal | 2000 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo
+MPEG-2 | MPEG2 | 720x576PAL | VBR | 600 :Good | 4000 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo
+VCD | MPEG1 | 352x288PAL | (CBR) | 1000:Optimal | 1150 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo
+DVD | MPEG2 | 720x576PAL | VBR | 600 :Good | 6000 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo
+DB* DVD | MPEG2 | 720x576PAL | CBR | 600 :Good | 6000 Kbps | 25fps | MPG1 Layer2 | 224kbps | Stereo
+=================================================================================================================
+*DB: "DirectBurn"
+*/
static void blackbird_codec_settings(struct cx8802_dev *dev)
{
int bitrate_mode = 1;
int bitrate = 7500000;
int bitrate_peak = 7500000;
+#if 1
+ bitrate_mode = BLACKBIRD_VIDEO_CBR;
+ bitrate = 4000*1024;
+ bitrate_peak = 4000*1024;
+#endif
/* assign stream type */
- blackbird_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 0); /* program stream */
- //blackbird_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 2); /* MPEG1 stream */
- //blackbird_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 3); /* PES A/V */
- //blackbird_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 10); /* DVD stream */
+ blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, BLACKBIRD_STREAM_PROGRAM);
+ /* blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, BLACKBIRD_STREAM_TRANSPORT); */
- /* assign output port */
- blackbird_api_cmd(dev, IVTV_API_ASSIGN_OUTPUT_PORT, 1, 0, 1); /* 1 = Host */
+ /* assign output port */
+ blackbird_api_cmd(dev, BLACKBIRD_API_SET_OUTPUT_PORT, 1, 0, BLACKBIRD_OUTPUT_PORT_STREAMING); /* Host */
- /* assign framerate */
- blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAMERATE, 1, 0, 0);
+ /* assign framerate */
+ blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_PAL_25);
- /* assign frame size */
- blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_SIZE, 2, 0,
+ /* assign frame size */
+ blackbird_api_cmd(dev, BLACKBIRD_API_SET_RESOLUTION, 2, 0,
dev->height, dev->width);
- /* assign aspect ratio */
- blackbird_api_cmd(dev, IVTV_API_ASSIGN_ASPECT_RATIO, 1, 0, 2);
+ /* assign aspect ratio */
+ blackbird_api_cmd(dev, BLACKBIRD_API_SET_ASPECT_RATIO, 1, 0, BLACKBIRD_ASPECT_RATIO_4_3);
- /* assign bitrates */
- blackbird_api_cmd(dev, IVTV_API_ASSIGN_BITRATES, 5, 0,
+ /* assign bitrates */
+ blackbird_api_cmd(dev, BLACKBIRD_API_SET_VIDEO_BITRATE, 5, 0,
bitrate_mode, /* mode */
bitrate, /* bps */
- bitrate_peak / 400, /* peak/400 */
- 0, 0x70); /* encoding buffer, ckennedy */
-
- /* assign gop properties */
- blackbird_api_cmd(dev, IVTV_API_ASSIGN_GOP_PROPERTIES, 2, 0, 15, 3);
- //blackbird_api_cmd(dev, IVTV_API_ASSIGN_GOP_PROPERTIES, 2, 0, 2, 1);
-
- /* assign 3 2 pulldown */
- blackbird_api_cmd(dev, IVTV_API_ASSIGN_3_2_PULLDOWN, 1, 0, 0);
-
- /* note: it's not necessary to set the samplerate, the mpeg encoder seems to autodetect/adjust */
- blackbird_api_cmd(dev, IVTV_API_ASSIGN_AUDIO_PROPERTIES, 1, 0, (2<<2) | (8<<4));
+ bitrate_peak / BLACKBIRD_PEAK_RATE_DIVISOR, /* peak/400 */
+ BLACKBIRD_MUX_RATE_DEFAULT /*, 0x70*/); /* encoding buffer, ckennedy */
+
+ /* assign gop properties */
+ blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_STRUCTURE, 2, 0, 15, 3);
+
+ /* assign 3 2 pulldown */
+ blackbird_api_cmd(dev, BLACKBIRD_API_SET_3_2_PULLDOWN, 1, 0, BLACKBIRD_3_2_PULLDOWN_DISABLED);
+
+ /* assign audio properties */
+ /* note: it's not necessary to set the samplerate, the mpeg encoder seems to autodetect/adjust */
+ /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_AUDIO_PROPERTIES, 1, 0, (2<<2) | (8<<4));
+ blackbird_api_cmd(dev, IVTV_API_ASSIGN_AUDIO_PROPERTIES, 1, 0, 0 | (2 << 2) | (14 << 4)); */
+ blackbird_api_cmd(dev, BLACKBIRD_API_SET_AUDIO_PARAMS, 1, 0,
+ BLACKBIRD_AUDIO_BITS_44100HZ |
+ BLACKBIRD_AUDIO_BITS_LAYER_2 |
+ BLACKBIRD_AUDIO_BITS_LAYER_2_224 |
+ BLACKBIRD_AUDIO_BITS_STEREO |
+ /* BLACKBIRD_AUDIO_BITS_BOUND_4 | */
+ BLACKBIRD_AUDIO_BITS_EMPHASIS_NONE |
+ BLACKBIRD_AUDIO_BITS_CRC_OFF |
+ BLACKBIRD_AUDIO_BITS_COPYRIGHT_OFF |
+ BLACKBIRD_AUDIO_BITS_COPY
+ );
/* assign gop closure */
- blackbird_api_cmd(dev, IVTV_API_ASSIGN_GOP_CLOSURE, 1, 0, 0);
+ blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_CLOSURE, 1, 0, BLACKBIRD_GOP_CLOSURE_OFF);
- /* assign audio properties */
- blackbird_api_cmd(dev, IVTV_API_ASSIGN_AUDIO_PROPERTIES, 1, 0, 0 | (2 << 2) | (14 << 4));
- /* assign dnr filter mode */
- blackbird_api_cmd(dev, IVTV_API_ASSIGN_DNR_FILTER_MODE, 2, 0, 0, 0);
+ /* assign dnr filter mode */
+ blackbird_api_cmd(dev, BLACKBIRD_API_SET_DNR_MODE, 2, 0,
+ BLACKBIRD_DNR_BITS_MANUAL,
+ BLACKBIRD_MEDIAN_FILTER_DISABLED
+ );
- /* assign dnr filter props*/
- blackbird_api_cmd(dev, IVTV_API_ASSIGN_DNR_FILTER_PROPS, 2, 0, 0, 0);
+ /* assign dnr filter props*/
+ blackbird_api_cmd(dev, BLACKBIRD_API_SET_MANUAL_DNR, 2, 0, 0, 0);
- /* assign coring levels (luma_h, luma_l, chroma_h, chroma_l) */
- blackbird_api_cmd(dev, IVTV_API_ASSIGN_CORING_LEVELS, 4, 0, 0, 255, 0, 255);
+ /* assign coring levels (luma_h, luma_l, chroma_h, chroma_l) */
+ blackbird_api_cmd(dev, BLACKBIRD_API_SET_DNR_MEDIAN, 4, 0, 0, 255, 0, 255);
- /* assign spatial filter type: luma_t: 1 = horiz_only, chroma_t: 1 = horiz_only */
- blackbird_api_cmd(dev, IVTV_API_ASSIGN_SPATIAL_FILTER_TYPE, 2, 0, 1, 1);
+ /* assign spatial filter type: luma_t: horiz_only, chroma_t: horiz_only */
+ blackbird_api_cmd(dev, BLACKBIRD_API_SET_SPATIAL_FILTER, 2, 0,
+ BLACKBIRD_SPATIAL_FILTER_LUMA_1D_HORIZ,
+ BLACKBIRD_SPATIAL_FILTER_CHROMA_1D_HORIZ
+ );
- /* assign frame drop rate */
- blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_DROP_RATE, 1, 0, 0);
+ /* assign frame drop rate */
+ /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_DROP_RATE, 1, 0, 0); */
}
static int blackbird_initialize_codec(struct cx8802_dev *dev)
@@ -476,7 +775,7 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev)
int retval;
dprintk(1,"Initialize codec\n");
- retval = blackbird_api_cmd(dev, IVTV_API_ENC_PING_FW, 0, 0); /* ping */
+ retval = blackbird_api_cmd(dev, BLACKBIRD_API_PING, 0, 0); /* ping */
if (retval < 0) {
/* ping was not successful, reset and upload firmware */
cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */
@@ -491,13 +790,13 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev)
if (dev->mailbox < 0)
return -1;
- retval = blackbird_api_cmd(dev, IVTV_API_ENC_PING_FW, 0, 0); /* ping */
+ retval = blackbird_api_cmd(dev, BLACKBIRD_API_PING, 0, 0); /* ping */
if (retval < 0) {
dprintk(0, "ERROR: Firmware ping failed!\n");
return -1;
}
- retval = blackbird_api_cmd(dev, IVTV_API_ENC_GETVER, 0, 1, &version);
+ retval = blackbird_api_cmd(dev, BLACKBIRD_API_GET_VERSION, 0, 1, &version);
if (retval < 0) {
dprintk(0, "ERROR: Firmware get encoder version failed!\n");
return -1;
@@ -517,25 +816,36 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev)
blackbird_codec_settings(dev);
msleep(1);
- //blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xef, 0xef);
- blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xf0, 0xf0);
- //blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0x180, 0x180);
- blackbird_api_cmd(dev, IVTV_API_ASSIGN_PLACEHOLDER, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+ /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xef, 0xef);
+ blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xf0, 0xf0);
+ blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0x180, 0x180); */
+ blackbird_api_cmd(dev, BLACKBIRD_API_SET_CAPTURE_LINES, 2, 0,
+ BLACKBIRD_FIELD1_SAA7115,
+ BLACKBIRD_FIELD1_SAA7115
+ );
+
+ /* blackbird_api_cmd(dev, IVTV_API_ASSIGN_PLACEHOLDER, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); */
+ blackbird_api_cmd(dev, BLACKBIRD_API_SET_CUSTOM_DATA, 12, 0,
+ BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
- blackbird_api_cmd(dev, IVTV_API_INITIALIZE_INPUT, 0, 0); /* initialize the video input */
+ blackbird_api_cmd(dev, BLACKBIRD_API_INIT_VIDEO_INPUT, 0, 0); /* initialize the video input */
msleep(1);
- blackbird_api_cmd(dev, IVTV_API_MUTE_VIDEO, 1, 0, 0);
+ blackbird_api_cmd(dev, BLACKBIRD_API_MUTE_VIDEO, 1, 0, BLACKBIRD_UNMUTE);
msleep(1);
- blackbird_api_cmd(dev, IVTV_API_MUTE_AUDIO, 1, 0, 0);
+ blackbird_api_cmd(dev, BLACKBIRD_API_MUTE_AUDIO, 1, 0, BLACKBIRD_UNMUTE);
msleep(1);
- blackbird_api_cmd(dev, IVTV_API_BEGIN_CAPTURE, 2, 0, 0, 0x13); /* start capturing to the host interface */
- //blackbird_api_cmd(dev, IVTV_API_BEGIN_CAPTURE, 2, 0, 0, 0); /* start capturing to the host interface */
- msleep(1);
+ /* blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0, 0, 0x13); // start capturing to the host interface */
+ blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0,
+ BLACKBIRD_MPEG_CAPTURE,
+ BLACKBIRD_RAW_BITS_NONE
+ ); /* start capturing to the host interface */
+ msleep(10);
- blackbird_api_cmd(dev, IVTV_API_REFRESH_INPUT, 0,0);
+ blackbird_api_cmd(dev, BLACKBIRD_API_REFRESH_INPUT, 0,0);
return 0;
}
@@ -709,7 +1019,12 @@ static int mpeg_release(struct inode *inode, struct file *file)
{
struct cx8802_fh *fh = file->private_data;
- blackbird_api_cmd(fh->dev, IVTV_API_END_CAPTURE, 3, 0, 1, 0, 0x13);
+ /* blackbird_api_cmd(fh->dev, BLACKBIRD_API_END_CAPTURE, 3, 0, BLACKBIRD_END_NOW, 0, 0x13); */
+ blackbird_api_cmd(fh->dev, BLACKBIRD_API_END_CAPTURE, 3, 0,
+ BLACKBIRD_END_NOW,
+ BLACKBIRD_MPEG_CAPTURE,
+ BLACKBIRD_RAW_BITS_NONE
+ );
/* stop mpeg capture */
if (fh->mpegq.streaming)
@@ -908,4 +1223,5 @@ module_exit(blackbird_fini);
* Local variables:
* c-basic-offset: 8
* End:
+ * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
*/
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index 367624822d7..b3fb04356b7 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -1,5 +1,5 @@
/*
- * $Id: cx88-cards.c,v 1.66 2005/03/04 09:12:23 kraxel Exp $
+ * $Id: cx88-cards.c,v 1.76 2005/06/08 01:28:09 mchehab Exp $
*
* device driver for Conexant 2388x based TV cards
* card-specific stuff.
@@ -35,6 +35,9 @@ struct cx88_board cx88_boards[] = {
[CX88_BOARD_UNKNOWN] = {
.name = "UNKNOWN/GENERIC",
.tuner_type = UNSET,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
.input = {{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 0,
@@ -52,6 +55,9 @@ struct cx88_board cx88_boards[] = {
[CX88_BOARD_HAUPPAUGE] = {
.name = "Hauppauge WinTV 34xxx models",
.tuner_type = UNSET,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
.input = {{
.type = CX88_VMUX_TELEVISION,
@@ -78,6 +84,9 @@ struct cx88_board cx88_boards[] = {
[CX88_BOARD_GDI] = {
.name = "GDI Black Gold",
.tuner_type = UNSET,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
@@ -85,7 +94,10 @@ struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_PIXELVIEW] = {
.name = "PixelView",
- .tuner_type = 5,
+ .tuner_type = TUNER_PHILIPS_PAL,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
@@ -104,7 +116,10 @@ struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_ATI_WONDER_PRO] = {
.name = "ATI TV Wonder Pro",
- .tuner_type = 44,
+ .tuner_type = TUNER_PHILIPS_4IN1,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT | TDA9887_INTERCARRIER,
.input = {{
.type = CX88_VMUX_TELEVISION,
@@ -122,7 +137,10 @@ struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_WINFAST2000XP_EXPERT] = {
.name = "Leadtek Winfast 2000XP Expert",
- .tuner_type = 44,
+ .tuner_type = TUNER_PHILIPS_4IN1,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
.input = {{
.type = CX88_VMUX_TELEVISION,
@@ -156,7 +174,10 @@ struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_AVERTV_303] = {
.name = "AverTV Studio 303 (M126)",
- .tuner_type = 38,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
.input = {{
.type = CX88_VMUX_TELEVISION,
@@ -179,7 +200,10 @@ struct cx88_board cx88_boards[] = {
// added gpio values thanks to Michal
// values for PAL from DScaler
.name = "MSI TV-@nywhere Master",
- .tuner_type = 33,
+ .tuner_type = TUNER_MT2032,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
.input = {{
.type = CX88_VMUX_TELEVISION,
@@ -206,7 +230,10 @@ struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_WINFAST_DV2000] = {
.name = "Leadtek Winfast DV2000",
- .tuner_type = 38,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
.input = {{
.type = CX88_VMUX_TELEVISION,
@@ -239,34 +266,40 @@ struct cx88_board cx88_boards[] = {
.gpio3 = 0x02000000,
},
},
- [CX88_BOARD_LEADTEK_PVR2000] = {
+ [CX88_BOARD_LEADTEK_PVR2000] = {
// gpio values for PAL version from regspy by DScaler
- .name = "Leadtek PVR 2000",
- .tuner_type = 38,
+ .name = "Leadtek PVR 2000",
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
- .input = {{
- .type = CX88_VMUX_TELEVISION,
- .vmux = 0,
- .gpio0 = 0x0000bde6,
- },{
- .type = CX88_VMUX_COMPOSITE1,
- .vmux = 1,
- .gpio0 = 0x0000bde6,
- },{
- .type = CX88_VMUX_SVIDEO,
- .vmux = 2,
- .gpio0 = 0x0000bde6,
- }},
- .radio = {
- .type = CX88_RADIO,
- .gpio0 = 0x0000bd62,
- },
+ .input = {{
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ .gpio0 = 0x0000bde2,
+ },{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0x0000bde6,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0x0000bde6,
+ }},
+ .radio = {
+ .type = CX88_RADIO,
+ .gpio0 = 0x0000bd62,
+ },
.blackbird = 1,
- },
+ },
[CX88_BOARD_IODATA_GVVCP3PCI] = {
.name = "IODATA GV-VCP3/PCI",
.tuner_type = TUNER_ABSENT,
- .input = {{
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .input = {{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 0,
},{
@@ -279,7 +312,10 @@ struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_PROLINK_PLAYTVPVR] = {
.name = "Prolink PlayTV PVR",
- .tuner_type = 43,
+ .tuner_type = TUNER_PHILIPS_FM1236_MK3,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
.input = {{
.type = CX88_VMUX_TELEVISION,
@@ -301,8 +337,11 @@ struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_ASUS_PVR_416] = {
.name = "ASUS PVR-416",
- .tuner_type = 43,
- .tda9887_conf = TDA9887_PRESENT,
+ .tuner_type = TUNER_PHILIPS_FM1236_MK3,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .tda9887_conf = TDA9887_PRESENT,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
@@ -320,7 +359,10 @@ struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_MSI_TVANYWHERE] = {
.name = "MSI TV-@nywhere",
- .tuner_type = 33,
+ .tuner_type = TUNER_MT2032,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
.input = {{
.type = CX88_VMUX_TELEVISION,
@@ -342,6 +384,9 @@ struct cx88_board cx88_boards[] = {
[CX88_BOARD_KWORLD_DVB_T] = {
.name = "KWorld/VStream XPert DVB-T",
.tuner_type = TUNER_ABSENT,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
.input = {{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
@@ -358,6 +403,9 @@ struct cx88_board cx88_boards[] = {
[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1] = {
.name = "DVICO FusionHDTV DVB-T1",
.tuner_type = TUNER_ABSENT, /* No analog tuner */
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
.input = {{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
@@ -371,7 +419,10 @@ struct cx88_board cx88_boards[] = {
},
[CX88_BOARD_KWORLD_LTV883] = {
.name = "KWorld LTV883RF",
- .tuner_type = 48,
+ .tuner_type = TUNER_TNF_8831BGFF,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
@@ -397,6 +448,9 @@ struct cx88_board cx88_boards[] = {
[CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD] = {
.name = "DViCO - FusionHDTV 3 Gold",
.tuner_type = TUNER_MICROTUNE_4042FI5,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
/*
GPIO[0] resets DT3302 DTV receiver
0 - reset asserted
@@ -428,17 +482,14 @@ struct cx88_board cx88_boards[] = {
.vmux = 2,
.gpio0 = 0x0f00,
}},
-#if 0
- .ts = {
- .type = CX88_TS,
- .gpio0 = 0x00000f01, /* Hooked to tuner reset bit */
- }
-#endif
},
[CX88_BOARD_HAUPPAUGE_DVB_T1] = {
- .name = "Hauppauge Nova-T DVB-T",
+ .name = "Hauppauge Nova-T DVB-T",
.tuner_type = TUNER_ABSENT,
- .input = {{
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ .input = {{
.type = CX88_VMUX_DVB,
.vmux = 0,
}},
@@ -447,6 +498,9 @@ struct cx88_board cx88_boards[] = {
[CX88_BOARD_CONEXANT_DVB_T1] = {
.name = "Conexant DVB-T reference design",
.tuner_type = TUNER_ABSENT,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
.input = {{
.type = CX88_VMUX_DVB,
.vmux = 0,
@@ -456,6 +510,9 @@ struct cx88_board cx88_boards[] = {
[CX88_BOARD_PROVIDEO_PV259] = {
.name = "Provideo PV259",
.tuner_type = TUNER_PHILIPS_FQ1216ME,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
@@ -465,6 +522,9 @@ struct cx88_board cx88_boards[] = {
[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS] = {
.name = "DVICO FusionHDTV DVB-T Plus",
.tuner_type = TUNER_ABSENT, /* No analog tuner */
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
.input = {{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
@@ -479,6 +539,9 @@ struct cx88_board cx88_boards[] = {
[CX88_BOARD_DNTV_LIVE_DVB_T] = {
.name = "digitalnow DNTV Live! DVB-T",
.tuner_type = TUNER_ABSENT,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
.input = {{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
@@ -495,6 +558,9 @@ struct cx88_board cx88_boards[] = {
[CX88_BOARD_PCHDTV_HD3000] = {
.name = "pcHDTV HD3000 HDTV",
.tuner_type = TUNER_THOMSON_DTT7610,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
@@ -530,8 +596,11 @@ struct cx88_board cx88_boards[] = {
[CX88_BOARD_HAUPPAUGE_ROSLYN] = {
// entry added by Kaustubh D. Bhalerao <bhalerao.1@osu.edu>
// GPIO values obtained from regspy, courtesy Sean Covel
- .name = "Hauppauge WinTV 28xxx (Roslyn) models",
- .tuner_type = UNSET,
+ .name = "Hauppauge WinTV 28xxx (Roslyn) models",
+ .tuner_type = UNSET,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
@@ -559,33 +628,37 @@ struct cx88_board cx88_boards[] = {
.blackbird = 1,
},
[CX88_BOARD_DIGITALLOGIC_MEC] = {
- /* params copied over from Leadtek PVR 2000 */
.name = "Digital-Logic MICROSPACE Entertainment Center (MEC)",
- /* not sure yet about the tuner type */
- .tuner_type = 38,
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
.input = {{
.type = CX88_VMUX_TELEVISION,
.vmux = 0,
- .gpio0 = 0x0000bde6,
+ .gpio0 = 0x00009d80,
},{
.type = CX88_VMUX_COMPOSITE1,
.vmux = 1,
- .gpio0 = 0x0000bde6,
+ .gpio0 = 0x00009d76,
},{
.type = CX88_VMUX_SVIDEO,
.vmux = 2,
- .gpio0 = 0x0000bde6,
+ .gpio0 = 0x00009d76,
}},
.radio = {
.type = CX88_RADIO,
- .gpio0 = 0x0000bd62,
+ .gpio0 = 0x00009d00,
},
.blackbird = 1,
},
[CX88_BOARD_IODATA_GVBCTV7E] = {
.name = "IODATA GV/BCTV7E",
.tuner_type = TUNER_PHILIPS_FQ1286,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
.tda9887_conf = TDA9887_PRESENT,
.input = {{
.type = CX88_VMUX_TELEVISION,
@@ -601,6 +674,56 @@ struct cx88_board cx88_boards[] = {
.gpio1 = 0x0000e07f,
}}
},
+ [CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO] = {
+ .name = "PixelView PlayTV Ultra Pro (Stereo)",
+ /* May be also TUNER_YMEC_TVF_5533MF for NTSC/M or PAL/M */
+ .tuner_type = TUNER_PHILIPS_FM1216ME_MK3,
+ .radio_type = TUNER_TEA5767,
+ .tuner_addr = 0xc2>>1,
+ .radio_addr = 0xc0>>1,
+ .input = {{
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ .gpio0 = 0xbf61, /* internal decoder */
+ },{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0xbf63,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0xbf63,
+ }},
+ .radio = {
+ .type = CX88_RADIO,
+ .gpio0 = 0xbf60,
+ },
+ },
+ [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T] = {
+ .name = "DViCO - FusionHDTV 3 Gold-T",
+ .tuner_type = TUNER_THOMSON_DTT7611,
+ .radio_type = UNSET,
+ .tuner_addr = ADDR_UNSET,
+ .radio_addr = ADDR_UNSET,
+ /* See DViCO FusionHDTV 3 Gold for GPIO documentation. */
+ .input = {{
+ .type = CX88_VMUX_TELEVISION,
+ .vmux = 0,
+ .gpio0 = 0x0f0d,
+ },{
+ .type = CX88_VMUX_CABLE,
+ .vmux = 0,
+ .gpio0 = 0x0f05,
+ },{
+ .type = CX88_VMUX_COMPOSITE1,
+ .vmux = 1,
+ .gpio0 = 0x0f00,
+ },{
+ .type = CX88_VMUX_SVIDEO,
+ .vmux = 2,
+ .gpio0 = 0x0f00,
+ }},
+ },
};
const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
@@ -673,6 +796,10 @@ struct cx88_subid cx88_subids[] = {
.subdevice = 0xd810,
.card = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD,
},{
+ .subvendor = 0x18ac,
+ .subdevice = 0xd820,
+ .card = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T,
+ },{
.subvendor = 0x18AC,
.subdevice = 0xDB00,
.card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1,
@@ -935,4 +1062,5 @@ EXPORT_SYMBOL(cx88_card_setup);
* Local variables:
* c-basic-offset: 8
* End:
+ * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
*/
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index 1ff79b5a883..c046a23537d 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -1,5 +1,5 @@
/*
- * $Id: cx88-core.c,v 1.24 2005/01/19 12:01:55 kraxel Exp $
+ * $Id: cx88-core.c,v 1.28 2005/06/12 04:19:19 mchehab Exp $
*
* device driver for Conexant 2388x based TV cards
* driver core
@@ -51,12 +51,15 @@ module_param(latency,int,0444);
MODULE_PARM_DESC(latency,"pci latency timer");
static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
+static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
static unsigned int card[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
module_param_array(tuner, int, NULL, 0444);
+module_param_array(radio, int, NULL, 0444);
module_param_array(card, int, NULL, 0444);
MODULE_PARM_DESC(tuner,"tuner type");
+MODULE_PARM_DESC(radio,"radio tuner type");
MODULE_PARM_DESC(card,"card type");
static unsigned int nicam = 0;
@@ -429,7 +432,7 @@ int cx88_sram_channel_setup(struct cx88_core *core,
/* ------------------------------------------------------------------ */
/* debug helper code */
-static int cx88_risc_decode(u32 risc)
+int cx88_risc_decode(u32 risc)
{
static char *instr[16] = {
[ RISC_SYNC >> 28 ] = "sync",
@@ -736,6 +739,10 @@ static unsigned int inline norm_fsc8(struct cx88_tvnorm *norm)
{
static const unsigned int ntsc = 28636360;
static const unsigned int pal = 35468950;
+ static const unsigned int palm = 28604892;
+
+ if (norm->id & V4L2_STD_PAL_M)
+ return palm;
return (norm->id & V4L2_STD_625_50) ? pal : ntsc;
}
@@ -749,6 +756,11 @@ static unsigned int inline norm_notchfilter(struct cx88_tvnorm *norm)
static unsigned int inline norm_htotal(struct cx88_tvnorm *norm)
{
+ /* Should always be Line Draw Time / (4*FSC) */
+
+ if (norm->id & V4L2_STD_PAL_M)
+ return 909;
+
return (norm->id & V4L2_STD_625_50) ? 1135 : 910;
}
@@ -1164,8 +1176,20 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci)
"insmod option" : "autodetected");
core->tuner_type = tuner[core->nr];
+ core->radio_type = radio[core->nr];
if (UNSET == core->tuner_type)
core->tuner_type = cx88_boards[core->board].tuner_type;
+ if (UNSET == core->radio_type)
+ core->radio_type = cx88_boards[core->board].radio_type;
+ if (!core->tuner_addr)
+ core->tuner_addr = cx88_boards[core->board].tuner_addr;
+ if (!core->radio_addr)
+ core->radio_addr = cx88_boards[core->board].radio_addr;
+
+ printk(KERN_INFO "TV tuner %d at 0x%02x, Radio tuner %d at 0x%02x\n",
+ core->tuner_type, core->tuner_addr<<1,
+ core->radio_type, core->radio_addr<<1);
+
core->tda9887_conf = cx88_boards[core->board].tda9887_conf;
/* init hardware */
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index 9d15d3d5a2b..1a259c3966c 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -1,5 +1,5 @@
/*
- * $Id: cx88-dvb.c,v 1.31 2005/03/07 15:58:05 kraxel Exp $
+ * $Id: cx88-dvb.c,v 1.33 2005/06/12 04:19:19 mchehab Exp $
*
* device driver for Conexant 2388x based TV cards
* MPEG Transport Stream (DVB) routines
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index 0725b1288f4..e20adefcfc6 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -1,5 +1,5 @@
/*
- $Id: cx88-i2c.c,v 1.20 2005/02/15 15:59:35 kraxel Exp $
+ $Id: cx88-i2c.c,v 1.23 2005/06/12 04:19:19 mchehab Exp $
cx88-i2c.c -- all the i2c code is here
@@ -91,6 +91,7 @@ static int cx8800_bit_getsda(void *data)
static int attach_inform(struct i2c_client *client)
{
+ struct tuner_addr tun_addr;
struct cx88_core *core = i2c_get_adapdata(client->adapter);
dprintk(1, "i2c attach [addr=0x%x,client=%s]\n",
@@ -98,8 +99,19 @@ static int attach_inform(struct i2c_client *client)
if (!client->driver->command)
return 0;
- if (core->tuner_type != UNSET)
- client->driver->command(client, TUNER_SET_TYPE, &core->tuner_type);
+ if (core->radio_type != UNSET) {
+ tun_addr.v4l2_tuner = V4L2_TUNER_RADIO;
+ tun_addr.type = core->radio_type;
+ tun_addr.addr = core->radio_addr;
+ client->driver->command(client,TUNER_SET_TYPE_ADDR, &tun_addr);
+ }
+ if (core->tuner_type != UNSET) {
+ tun_addr.v4l2_tuner = V4L2_TUNER_ANALOG_TV;
+ tun_addr.type = core->tuner_type;
+ tun_addr.addr = core->tuner_addr;
+ client->driver->command(client,TUNER_SET_TYPE_ADDR, &tun_addr);
+ }
+
if (core->tda9887_conf)
client->driver->command(client, TDA9887_SET_CONFIG, &core->tda9887_conf);
return 0;
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index af6ad8cdbdb..dc0dcf249aa 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -1,5 +1,5 @@
/*
- * $Id: cx88-input.c,v 1.9 2005/03/04 09:12:23 kraxel Exp $
+ * $Id: cx88-input.c,v 1.11 2005/05/22 20:57:56 nsh Exp $
*
* Device driver for GPIO attached remote control interfaces
* on Conexant 2388x based TV/DVB cards.
@@ -235,6 +235,7 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
/* detect & configure */
switch (core->board) {
case CX88_BOARD_DNTV_LIVE_DVB_T:
+ case CX88_BOARD_KWORLD_DVB_T:
ir_codes = ir_codes_dntv_live_dvb_t;
ir->gpio_addr = MO_GP1_IO;
ir->mask_keycode = 0x1f;
@@ -261,7 +262,15 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci)
ir->mask_keydown = 0x02;
ir->polling = 5; // ms
break;
+ case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO:
+ ir_codes = ir_codes_pixelview;
+ ir->gpio_addr = MO_GP1_IO;
+ ir->mask_keycode = 0x1f;
+ ir->mask_keyup = 0x80;
+ ir->polling = 1; // ms
+ break;
}
+
if (NULL == ir_codes) {
kfree(ir);
return -ENODEV;
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index 07aae1899e1..9ade2ae91e9 100644
--- a/drivers/media/video/cx88/cx88-mpeg.c
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -1,5 +1,5 @@
/*
- * $Id: cx88-mpeg.c,v 1.25 2005/03/07 14:18:00 kraxel Exp $
+ * $Id: cx88-mpeg.c,v 1.26 2005/06/03 13:31:51 mchehab Exp $
*
* Support for the mpeg transport stream transfers
* PCI function #2 of the cx2388x.
@@ -55,7 +55,7 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
{
struct cx88_core *core = dev->core;
- dprintk(1, "cx8802_start_mpegport_dma %d\n", buf->vb.width);
+ dprintk(0, "cx8802_start_dma %d\n", buf->vb.width);
/* setup fifo + format */
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28],
@@ -100,18 +100,21 @@ static int cx8802_start_dma(struct cx8802_dev *dev,
q->count = 1;
/* enable irqs */
+ dprintk( 0, "setting the interrupt mask\n" );
cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x04);
- cx_write(MO_TS_INTMSK, 0x1f0011);
+ cx_set(MO_TS_INTMSK, 0x1f0011);
+ //cx_write(MO_TS_INTMSK, 0x0f0011);
/* start dma */
- cx_write(MO_DEV_CNTRL2, (1<<5)); /* FIXME: s/write/set/ ??? */
- cx_write(MO_TS_DMACNTRL, 0x11);
+ cx_set(MO_DEV_CNTRL2, (1<<5));
+ cx_set(MO_TS_DMACNTRL, 0x11);
return 0;
}
static int cx8802_stop_dma(struct cx8802_dev *dev)
{
struct cx88_core *core = dev->core;
+ dprintk( 0, "cx8802_stop_dma\n" );
/* stop dma */
cx_clear(MO_TS_DMACNTRL, 0x11);
@@ -131,8 +134,12 @@ static int cx8802_restart_queue(struct cx8802_dev *dev,
struct cx88_buffer *buf;
struct list_head *item;
+ dprintk( 0, "cx8802_restart_queue\n" );
if (list_empty(&q->active))
+ {
+ dprintk( 0, "cx8802_restart_queue: queue is empty\n" );
return 0;
+ }
buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
dprintk(2,"restart_queue [%p/%d]: restart dma\n",
@@ -182,27 +189,32 @@ void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
struct cx88_buffer *prev;
struct cx88_dmaqueue *q = &dev->mpegq;
+ dprintk( 1, "cx8802_buf_queue\n" );
/* add jump to stopper */
buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
if (list_empty(&q->active)) {
+ dprintk( 0, "queue is empty - first active\n" );
list_add_tail(&buf->vb.queue,&q->active);
cx8802_start_dma(dev, q, buf);
buf->vb.state = STATE_ACTIVE;
buf->count = q->count++;
mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
- dprintk(2,"[%p/%d] %s - first active\n",
+ dprintk(0,"[%p/%d] %s - first active\n",
buf, buf->vb.i, __FUNCTION__);
+ //udelay(100);
} else {
+ dprintk( 1, "queue is not empty - append to active\n" );
prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue);
list_add_tail(&buf->vb.queue,&q->active);
buf->vb.state = STATE_ACTIVE;
buf->count = q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
- dprintk(2,"[%p/%d] %s - append to active\n",
+ dprintk( 1, "[%p/%d] %s - append to active\n",
buf, buf->vb.i, __FUNCTION__);
+ //udelay(100);
}
}
@@ -224,7 +236,10 @@ static void do_cancel_buffers(struct cx8802_dev *dev, char *reason, int restart)
buf, buf->vb.i, reason, (unsigned long)buf->risc.dma);
}
if (restart)
+ {
+ dprintk(0, "restarting queue\n" );
cx8802_restart_queue(dev,q);
+ }
spin_unlock_irqrestore(&dev->slock,flags);
}
@@ -232,6 +247,7 @@ void cx8802_cancel_buffers(struct cx8802_dev *dev)
{
struct cx88_dmaqueue *q = &dev->mpegq;
+ dprintk( 1, "cx8802_cancel_buffers" );
del_timer_sync(&q->timeout);
cx8802_stop_dma(dev);
do_cancel_buffers(dev,"cancel",0);
@@ -241,7 +257,7 @@ static void cx8802_timeout(unsigned long data)
{
struct cx8802_dev *dev = (struct cx8802_dev*)data;
- dprintk(1, "%s\n",__FUNCTION__);
+ dprintk(0, "%s\n",__FUNCTION__);
if (debug)
cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
@@ -254,12 +270,17 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev)
struct cx88_core *core = dev->core;
u32 status, mask, count;
+ dprintk( 1, "cx8802_mpeg_irq\n" );
status = cx_read(MO_TS_INTSTAT);
mask = cx_read(MO_TS_INTMSK);
if (0 == (status & mask))
return;
cx_write(MO_TS_INTSTAT, status);
+#if 0
+ cx88_print_irqbits(core->name, "irq mpeg ",
+ cx88_mpeg_irqs, status, mask);
+#endif
if (debug || (status & mask & ~0xff))
cx88_print_irqbits(core->name, "irq mpeg ",
cx88_mpeg_irqs, status, mask);
@@ -273,6 +294,7 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev)
/* risc1 y */
if (status & 0x01) {
+ dprintk( 1, "wake up\n" );
spin_lock(&dev->slock);
count = cx_read(MO_TS_GPCNT);
cx88_wakeup(dev->core, &dev->mpegq, count);
@@ -288,6 +310,7 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev)
/* other general errors */
if (status & 0x1f0100) {
+ dprintk( 0, "general errors: 0x%08x\n", status & 0x1f0100 );
spin_lock(&dev->slock);
cx8802_stop_dma(dev);
cx8802_restart_queue(dev,&dev->mpegq);
@@ -295,6 +318,8 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev)
}
}
+#define MAX_IRQ_LOOP 10
+
static irqreturn_t cx8802_irq(int irq, void *dev_id, struct pt_regs *regs)
{
struct cx8802_dev *dev = dev_id;
@@ -302,10 +327,13 @@ static irqreturn_t cx8802_irq(int irq, void *dev_id, struct pt_regs *regs)
u32 status;
int loop, handled = 0;
- for (loop = 0; loop < 10; loop++) {
+ for (loop = 0; loop < MAX_IRQ_LOOP; loop++) {
status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x04);
if (0 == status)
goto out;
+ dprintk( 1, "cx8802_irq\n" );
+ dprintk( 1, " loop: %d/%d\n", loop, MAX_IRQ_LOOP );
+ dprintk( 1, " status: %d\n", status );
handled = 1;
cx_write(MO_PCI_INTSTAT, status);
@@ -314,7 +342,8 @@ static irqreturn_t cx8802_irq(int irq, void *dev_id, struct pt_regs *regs)
if (status & 0x04)
cx8802_mpeg_irq(dev);
};
- if (10 == loop) {
+ if (MAX_IRQ_LOOP == loop) {
+ dprintk( 0, "clearing mask\n" );
printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n",
core->name);
cx_write(MO_PCI_INTMSK,0);
@@ -378,6 +407,7 @@ int cx8802_init_common(struct cx8802_dev *dev)
void cx8802_fini_common(struct cx8802_dev *dev)
{
+ dprintk( 2, "cx8802_fini_common\n" );
cx8802_stop_dma(dev);
pci_disable_device(dev->pci);
@@ -399,6 +429,7 @@ int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state)
/* stop mpeg dma */
spin_lock(&dev->slock);
if (!list_empty(&dev->mpegq.active)) {
+ dprintk( 2, "suspend\n" );
printk("%s: suspend mpeg\n", core->name);
cx8802_stop_dma(dev);
del_timer(&dev->mpegq.timeout);
@@ -463,4 +494,5 @@ EXPORT_SYMBOL(cx8802_resume_common);
* Local variables:
* c-basic-offset: 8
* End:
+ * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
*/
diff --git a/drivers/media/video/cx88/cx88-reg.h b/drivers/media/video/cx88/cx88-reg.h
index 8638ce57d84..63ad33f5818 100644
--- a/drivers/media/video/cx88/cx88-reg.h
+++ b/drivers/media/video/cx88/cx88-reg.h
@@ -1,5 +1,5 @@
/*
- $Id: cx88-reg.h,v 1.6 2004/10/13 10:39:00 kraxel Exp $
+ $Id: cx88-reg.h,v 1.7 2005/06/03 13:31:51 mchehab Exp $
cx88x-hw.h - CX2388x register offsets
@@ -397,6 +397,7 @@
#define AUD_RATE_ADJ4 0x3205e4
#define AUD_RATE_ADJ5 0x3205e8
#define AUD_APB_IN_RATE_ADJ 0x3205ec
+#define AUD_I2SCNTL 0x3205ec
#define AUD_PHASE_FIX_CTL 0x3205f0
#define AUD_PLL_PRESCALE 0x320600
#define AUD_PLL_DDS 0x320604
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
index f2a9475a2fe..46d78b1dc9b 100644
--- a/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -1,5 +1,5 @@
/*
- $Id: cx88-tvaudio.c,v 1.34 2005/03/07 16:10:51 kraxel Exp $
+ $Id: cx88-tvaudio.c,v 1.36 2005/06/05 05:53:45 mchehab Exp $
cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver
@@ -127,7 +127,8 @@ static void set_audio_start(struct cx88_core *core,
cx_write(AUD_VOL_CTL, (1 << 6));
// increase level of input by 12dB
- cx_write(AUD_AFE_12DB_EN, 0x0001);
+// cx_write(AUD_AFE_12DB_EN, 0x0001);
+ cx_write(AUD_AFE_12DB_EN, 0x0000);
// start programming
cx_write(AUD_CTL, 0x0000);
@@ -143,9 +144,15 @@ static void set_audio_finish(struct cx88_core *core)
u32 volume;
if (cx88_boards[core->board].blackbird) {
+ // sets sound input from external adc
+ cx_set(AUD_CTL, EN_I2SIN_ENABLE);
+ //cx_write(AUD_I2SINPUTCNTL, 0);
+ cx_write(AUD_I2SINPUTCNTL, 4);
+ cx_write(AUD_BAUDRATE, 1);
// 'pass-thru mode': this enables the i2s output to the mpeg encoder
- cx_set(AUD_CTL, 0x2000);
+ cx_set(AUD_CTL, EN_I2SOUT_ENABLE);
cx_write(AUD_I2SOUTPUTCNTL, 1);
+ cx_write(AUD_I2SCNTL, 0);
//cx_write(AUD_APB_IN_RATE_ADJ, 0);
}
@@ -707,50 +714,65 @@ static void set_audio_standard_EIAJ(struct cx88_core *core)
set_audio_finish(core);
}
-static void set_audio_standard_FM(struct cx88_core *core)
+static void set_audio_standard_FM(struct cx88_core *core, enum cx88_deemph_type deemph)
{
-#if 0 /* FIXME */
- switch (dev->audio_properties.FM_deemphasis)
- {
- case WW_FM_DEEMPH_50:
- //Set De-emphasis filter coefficients for 50 usec
- cx_write(AUD_DEEMPH0_G0, 0x0C45);
- cx_write(AUD_DEEMPH0_A0, 0x6262);
- cx_write(AUD_DEEMPH0_B0, 0x1C29);
- cx_write(AUD_DEEMPH0_A1, 0x3FC66);
- cx_write(AUD_DEEMPH0_B1, 0x399A);
-
- cx_write(AUD_DEEMPH1_G0, 0x0D80);
- cx_write(AUD_DEEMPH1_A0, 0x6262);
- cx_write(AUD_DEEMPH1_B0, 0x1C29);
- cx_write(AUD_DEEMPH1_A1, 0x3FC66);
- cx_write(AUD_DEEMPH1_B1, 0x399A);
+ static const struct rlist fm_deemph_50[] = {
+ { AUD_DEEMPH0_G0, 0x0C45 },
+ { AUD_DEEMPH0_A0, 0x6262 },
+ { AUD_DEEMPH0_B0, 0x1C29 },
+ { AUD_DEEMPH0_A1, 0x3FC66},
+ { AUD_DEEMPH0_B1, 0x399A },
+
+ { AUD_DEEMPH1_G0, 0x0D80 },
+ { AUD_DEEMPH1_A0, 0x6262 },
+ { AUD_DEEMPH1_B0, 0x1C29 },
+ { AUD_DEEMPH1_A1, 0x3FC66},
+ { AUD_DEEMPH1_B1, 0x399A},
+
+ { AUD_POLYPH80SCALEFAC, 0x0003},
+ { /* end of list */ },
+ };
+ static const struct rlist fm_deemph_75[] = {
+ { AUD_DEEMPH0_G0, 0x091B },
+ { AUD_DEEMPH0_A0, 0x6B68 },
+ { AUD_DEEMPH0_B0, 0x11EC },
+ { AUD_DEEMPH0_A1, 0x3FC66},
+ { AUD_DEEMPH0_B1, 0x399A },
+
+ { AUD_DEEMPH1_G0, 0x0AA0 },
+ { AUD_DEEMPH1_A0, 0x6B68 },
+ { AUD_DEEMPH1_B0, 0x11EC },
+ { AUD_DEEMPH1_A1, 0x3FC66},
+ { AUD_DEEMPH1_B1, 0x399A},
+
+ { AUD_POLYPH80SCALEFAC, 0x0003},
+ { /* end of list */ },
+ };
- break;
+ /* It is enough to leave default values? */
+ static const struct rlist fm_no_deemph[] = {
- case WW_FM_DEEMPH_75:
- //Set De-emphasis filter coefficients for 75 usec
- cx_write(AUD_DEEMPH0_G0, 0x91B );
- cx_write(AUD_DEEMPH0_A0, 0x6B68);
- cx_write(AUD_DEEMPH0_B0, 0x11EC);
- cx_write(AUD_DEEMPH0_A1, 0x3FC66);
- cx_write(AUD_DEEMPH0_B1, 0x399A);
+ { AUD_POLYPH80SCALEFAC, 0x0003},
+ { /* end of list */ },
+ };
- cx_write(AUD_DEEMPH1_G0, 0xAA0 );
- cx_write(AUD_DEEMPH1_A0, 0x6B68);
- cx_write(AUD_DEEMPH1_B0, 0x11EC);
- cx_write(AUD_DEEMPH1_A1, 0x3FC66);
- cx_write(AUD_DEEMPH1_B1, 0x399A);
+ dprintk("%s (status: unknown)\n",__FUNCTION__);
+ set_audio_start(core, 0x0020, EN_FMRADIO_AUTO_STEREO);
+ switch (deemph)
+ {
+ case FM_NO_DEEMPH:
+ set_audio_registers(core, fm_no_deemph);
break;
- }
-#endif
- dprintk("%s (status: unknown)\n",__FUNCTION__);
- set_audio_start(core, 0x0020, EN_FMRADIO_AUTO_STEREO);
+ case FM_DEEMPH_50:
+ set_audio_registers(core, fm_deemph_50);
+ break;
- // AB: 10/2/01: this register is not being reset appropriately on occasion.
- cx_write(AUD_POLYPH80SCALEFAC,3);
+ case FM_DEEMPH_75:
+ set_audio_registers(core, fm_deemph_75);
+ break;
+ }
set_audio_finish(core);
}
@@ -778,7 +800,7 @@ void cx88_set_tvaudio(struct cx88_core *core)
set_audio_standard_EIAJ(core);
break;
case WW_FM:
- set_audio_standard_FM(core);
+ set_audio_standard_FM(core,FM_NO_DEEMPH);
break;
case WW_SYSTEM_L_AM:
set_audio_standard_NICAM_L(core, 1);
@@ -1029,4 +1051,5 @@ EXPORT_SYMBOL(cx88_audio_thread);
* Local variables:
* c-basic-offset: 8
* End:
+ * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
*/
diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c
index 0584ff47638..320d57888bb 100644
--- a/drivers/media/video/cx88/cx88-vbi.c
+++ b/drivers/media/video/cx88/cx88-vbi.c
@@ -1,5 +1,5 @@
/*
- * $Id: cx88-vbi.c,v 1.16 2004/12/10 12:33:39 kraxel Exp $
+ * $Id: cx88-vbi.c,v 1.17 2005/06/12 04:19:19 mchehab Exp $
*/
#include <linux/kernel.h>
#include <linux/module.h>
@@ -47,8 +47,8 @@ void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f)
}
static int cx8800_start_vbi_dma(struct cx8800_dev *dev,
- struct cx88_dmaqueue *q,
- struct cx88_buffer *buf)
+ struct cx88_dmaqueue *q,
+ struct cx88_buffer *buf)
{
struct cx88_core *core = dev->core;
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index d1f5c92f0ce..e4ca7350df1 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -1,5 +1,5 @@
/*
- * $Id: cx88-video.c,v 1.58 2005/03/07 15:58:05 kraxel Exp $
+ * $Id: cx88-video.c,v 1.63 2005/06/12 04:19:19 mchehab Exp $
*
* device driver for Conexant 2388x based TV cards
* video4linux video interface
@@ -1187,9 +1187,24 @@ static void init_controls(struct cx8800_dev *dev)
.id = V4L2_CID_AUDIO_VOLUME,
.value = 0x3f,
};
+ static struct v4l2_control hue = {
+ .id = V4L2_CID_HUE,
+ .value = 0x80,
+ };
+ static struct v4l2_control contrast = {
+ .id = V4L2_CID_CONTRAST,
+ .value = 0x80,
+ };
+ static struct v4l2_control brightness = {
+ .id = V4L2_CID_BRIGHTNESS,
+ .value = 0x80,
+ };
set_control(dev,&mute);
set_control(dev,&volume);
+ set_control(dev,&hue);
+ set_control(dev,&contrast);
+ set_control(dev,&brightness);
}
/* ------------------------------------------------------------------ */
@@ -1336,6 +1351,9 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
V4L2_CAP_STREAMING |
V4L2_CAP_VBI_CAPTURE |
#if 0
+ V4L2_TUNER_CAP_LOW |
+#endif
+#if 0
V4L2_CAP_VIDEO_OVERLAY |
#endif
0;
@@ -1696,7 +1714,11 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
sizeof(cap->card));
sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci));
cap->version = CX88_VERSION_CODE;
- cap->capabilities = V4L2_CAP_TUNER;
+ cap->capabilities = V4L2_CAP_TUNER
+#if 0
+ | V4L2_TUNER_CAP_LOW
+#endif
+ ;
return 0;
}
case VIDIOC_G_TUNER:
@@ -1992,6 +2014,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
{
struct cx8800_dev *dev;
struct cx88_core *core;
+ struct tuner_addr tun_addr;
int err;
dev = kmalloc(sizeof(*dev),GFP_KERNEL);
@@ -2065,8 +2088,19 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
request_module("tuner");
if (core->tda9887_conf)
request_module("tda9887");
- if (core->tuner_type != UNSET)
- cx88_call_i2c_clients(dev->core,TUNER_SET_TYPE,&core->tuner_type);
+ if (core->radio_type != UNSET) {
+ tun_addr.v4l2_tuner = V4L2_TUNER_RADIO;
+ tun_addr.type = core->radio_type;
+ tun_addr.addr = core->radio_addr;
+ cx88_call_i2c_clients(dev->core,TUNER_SET_TYPE_ADDR, &tun_addr);
+ }
+ if (core->tuner_type != UNSET) {
+ tun_addr.v4l2_tuner = V4L2_TUNER_ANALOG_TV;
+ tun_addr.type = core->tuner_type;
+ tun_addr.addr = core->tuner_addr;
+ cx88_call_i2c_clients(dev->core,TUNER_SET_TYPE_ADDR, &tun_addr);
+ }
+
if (core->tda9887_conf)
cx88_call_i2c_clients(dev->core,TDA9887_SET_CONFIG,&core->tda9887_conf);
@@ -2162,7 +2196,7 @@ static void __devexit cx8800_finidev(struct pci_dev *pci_dev)
static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state)
{
- struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
+ struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
struct cx88_core *core = dev->core;
/* stop video+vbi capture */
@@ -2194,7 +2228,7 @@ static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state)
static int cx8800_resume(struct pci_dev *pci_dev)
{
- struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
+ struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
struct cx88_core *core = dev->core;
if (dev->state.disabled) {
@@ -2230,8 +2264,8 @@ static struct pci_device_id cx8800_pci_tbl[] = {
{
.vendor = 0x14f1,
.device = 0x8800,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
},{
/* --- end of list --- */
}
@@ -2239,10 +2273,10 @@ static struct pci_device_id cx8800_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, cx8800_pci_tbl);
static struct pci_driver cx8800_pci_driver = {
- .name = "cx8800",
- .id_table = cx8800_pci_tbl,
- .probe = cx8800_initdev,
- .remove = __devexit_p(cx8800_finidev),
+ .name = "cx8800",
+ .id_table = cx8800_pci_tbl,
+ .probe = cx8800_initdev,
+ .remove = __devexit_p(cx8800_finidev),
.suspend = cx8800_suspend,
.resume = cx8800_resume,
@@ -2274,4 +2308,5 @@ module_exit(cx8800_fini);
* Local variables:
* c-basic-offset: 8
* End:
+ * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
*/
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index 88eaaaba5ad..867e988a5a9 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -1,5 +1,5 @@
/*
- * $Id: cx88.h,v 1.56 2005/03/04 09:12:23 kraxel Exp $
+ * $Id: cx88.h,v 1.62 2005/06/12 04:19:19 mchehab Exp $
*
* v4l2 device driver for cx2388x based TV cards
*
@@ -64,6 +64,13 @@
#define SHADOW_AUD_BAL_CTL 2
#define SHADOW_MAX 2
+/* FM Radio deemphasis type */
+enum cx88_deemph_type {
+ FM_NO_DEEMPH = 0,
+ FM_DEEMPH_50,
+ FM_DEEMPH_75
+};
+
/* ----------------------------------------------------------- */
/* tv norms */
@@ -162,6 +169,8 @@ extern struct sram_channel cx88_sram_channels[];
#define CX88_BOARD_HAUPPAUGE_ROSLYN 24
#define CX88_BOARD_DIGITALLOGIC_MEC 25
#define CX88_BOARD_IODATA_GVBCTV7E 26
+#define CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO 27
+#define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T 28
enum cx88_itype {
CX88_VMUX_COMPOSITE1 = 1,
@@ -185,6 +194,9 @@ struct cx88_input {
struct cx88_board {
char *name;
unsigned int tuner_type;
+ unsigned int radio_type;
+ unsigned char tuner_addr;
+ unsigned char radio_addr;
int tda9887_conf;
struct cx88_input input[8];
struct cx88_input radio;
@@ -255,6 +267,9 @@ struct cx88_core {
/* config info -- analog */
unsigned int board;
unsigned int tuner_type;
+ unsigned int radio_type;
+ unsigned char tuner_addr;
+ unsigned char radio_addr;
unsigned int tda9887_conf;
unsigned int has_radio;
@@ -471,6 +486,11 @@ extern void cx88_core_put(struct cx88_core *core,
/* cx88-vbi.c */
void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f);
+/*
+int cx8800_start_vbi_dma(struct cx8800_dev *dev,
+ struct cx88_dmaqueue *q,
+ struct cx88_buffer *buf);
+*/
int cx8800_stop_vbi_dma(struct cx8800_dev *dev);
int cx8800_restart_vbi_queue(struct cx8800_dev *dev,
struct cx88_dmaqueue *q);
diff --git a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/ir-kbd-gpio.c
index ab6620de4b3..a565823330a 100644
--- a/drivers/media/video/ir-kbd-gpio.c
+++ b/drivers/media/video/ir-kbd-gpio.c
@@ -1,5 +1,5 @@
/*
- * $Id: ir-kbd-gpio.c,v 1.12 2005/02/22 12:28:40 kraxel Exp $
+ * $Id: ir-kbd-gpio.c,v 1.13 2005/05/15 19:01:26 mchehab Exp $
*
* Copyright (c) 2003 Gerd Knorr
* Copyright (c) 2003 Pavel Machek
@@ -114,38 +114,6 @@ static IR_KEYTAB_TYPE ir_codes_avermedia_dvbt[IR_KEYTAB_SIZE] = {
[ 0x3e ] = KEY_VOLUMEUP, // 'volume +'
};
-static IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = {
- [ 2 ] = KEY_KP0,
- [ 1 ] = KEY_KP1,
- [ 11 ] = KEY_KP2,
- [ 27 ] = KEY_KP3,
- [ 5 ] = KEY_KP4,
- [ 9 ] = KEY_KP5,
- [ 21 ] = KEY_KP6,
- [ 6 ] = KEY_KP7,
- [ 10 ] = KEY_KP8,
- [ 18 ] = KEY_KP9,
-
- [ 3 ] = KEY_TUNER, // TV/FM
- [ 7 ] = KEY_SEARCH, // scan
- [ 28 ] = KEY_ZOOM, // full screen
- [ 30 ] = KEY_POWER,
- [ 23 ] = KEY_VOLUMEDOWN,
- [ 31 ] = KEY_VOLUMEUP,
- [ 20 ] = KEY_CHANNELDOWN,
- [ 22 ] = KEY_CHANNELUP,
- [ 24 ] = KEY_MUTE,
-
- [ 0 ] = KEY_LIST, // source
- [ 19 ] = KEY_INFO, // loop
- [ 16 ] = KEY_LAST, // +100
- [ 13 ] = KEY_CLEAR, // reset
- [ 12 ] = BTN_RIGHT, // fun++
- [ 4 ] = BTN_LEFT, // fun--
- [ 14 ] = KEY_GOTO, // function
- [ 15 ] = KEY_STOP, // freeze
-};
-
/* Attila Kondoros <attila.kondoros@chello.hu> */
static IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = {
diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c
index 7fbb8581a87..b4ee9dfe6d4 100644
--- a/drivers/media/video/msp3400.c
+++ b/drivers/media/video/msp3400.c
@@ -147,7 +147,6 @@ static unsigned short normal_i2c[] = {
I2C_MSP3400C_ALT >> 1,
I2C_CLIENT_END
};
-static unsigned short normal_i2c_range[] = {I2C_CLIENT_END,I2C_CLIENT_END};
I2C_CLIENT_INSMOD;
/* ----------------------------------------------------------------------- */
@@ -736,7 +735,6 @@ static int msp34xx_sleep(struct msp3400c *msp, int timeout)
{
DECLARE_WAITQUEUE(wait, current);
-again:
add_wait_queue(&msp->wq, &wait);
if (!kthread_should_stop()) {
if (timeout < 0) {
@@ -752,12 +750,8 @@ again:
#endif
}
}
-
+ try_to_freeze();
remove_wait_queue(&msp->wq, &wait);
-
- if (try_to_freeze(PF_FREEZE))
- goto again;
-
return msp->restart;
}
@@ -1437,7 +1431,7 @@ static int msp_detach(struct i2c_client *client);
static int msp_probe(struct i2c_adapter *adap);
static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg);
-static int msp_suspend(struct device * dev, pm_message_t state, u32 level);
+static int msp_suspend(struct device * dev, u32 state, u32 level);
static int msp_resume(struct device * dev, u32 level);
static void msp_wake_thread(struct i2c_client *client);
@@ -1842,7 +1836,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0;
}
-static int msp_suspend(struct device * dev, pm_message_t state, u32 level)
+static int msp_suspend(struct device * dev, u32 state, u32 level)
{
struct i2c_client *c = container_of(dev, struct i2c_client, dev);
diff --git a/drivers/media/video/msp3400.h b/drivers/media/video/msp3400.h
index d70a954e13a..023f33056a4 100644
--- a/drivers/media/video/msp3400.h
+++ b/drivers/media/video/msp3400.h
@@ -1,3 +1,7 @@
+/*
+ * $Id: msp3400.h,v 1.3 2005/06/12 04:19:19 mchehab Exp $
+ */
+
#ifndef MSP3400_H
#define MSP3400_H
diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c
index ba69f09cbdd..b8054da31ff 100644
--- a/drivers/media/video/saa5246a.c
+++ b/drivers/media/video/saa5246a.c
@@ -64,7 +64,6 @@ static struct video_device saa_template; /* Declared near bottom */
/* Addresses to scan */
static unsigned short normal_i2c[] = { I2C_ADDRESS, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
I2C_CLIENT_INSMOD;
static struct i2c_client client_template;
diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c
index d74caa139f0..7ffa2e9a9bf 100644
--- a/drivers/media/video/saa5249.c
+++ b/drivers/media/video/saa5249.c
@@ -132,7 +132,6 @@ static struct video_device saa_template; /* Declared near bottom */
/* Addresses to scan */
static unsigned short normal_i2c[] = {34>>1,I2C_CLIENT_END};
-static unsigned short normal_i2c_range[] = {I2C_CLIENT_END};
I2C_CLIENT_INSMOD;
static struct i2c_client client_template;
diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c
index 64273b43853..22d055d8a69 100644
--- a/drivers/media/video/saa7110.c
+++ b/drivers/media/video/saa7110.c
@@ -463,22 +463,14 @@ static unsigned short normal_i2c[] = {
(I2C_SAA7110 >> 1) + 1,
I2C_CLIENT_END
};
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
- .normal_i2c_range = normal_i2c_range,
- .probe = probe,
- .probe_range = probe_range,
- .ignore = ignore,
- .ignore_range = ignore_range,
- .force = force
+ .probe = &ignore,
+ .ignore = &ignore,
+ .force = &ignore,
};
static struct i2c_driver i2c_driver_saa7110;
diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c
index 0a873112ae2..fcd897382fc 100644
--- a/drivers/media/video/saa7111.c
+++ b/drivers/media/video/saa7111.c
@@ -482,22 +482,14 @@ saa7111_command (struct i2c_client *client,
* concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
*/
static unsigned short normal_i2c[] = { I2C_SAA7111 >> 1, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
- .normal_i2c_range = normal_i2c_range,
- .probe = probe,
- .probe_range = probe_range,
- .ignore = ignore,
- .ignore_range = ignore_range,
- .force = force
+ .probe = &ignore,
+ .ignore = &ignore,
+ .force = &ignore,
};
static struct i2c_driver i2c_driver_saa7111;
diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c
index e73023695e5..2ba997f5ef1 100644
--- a/drivers/media/video/saa7114.c
+++ b/drivers/media/video/saa7114.c
@@ -820,22 +820,14 @@ saa7114_command (struct i2c_client *client,
*/
static unsigned short normal_i2c[] =
{ I2C_SAA7114 >> 1, I2C_SAA7114A >> 1, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
- .normal_i2c_range = normal_i2c_range,
- .probe = probe,
- .probe_range = probe_range,
- .ignore = ignore,
- .ignore_range = ignore_range,
- .force = force
+ .probe = &ignore,
+ .ignore = &ignore,
+ .force = &ignore,
};
static struct i2c_driver i2c_driver_saa7114;
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c
index fe6abe34168..e6d0a18833d 100644
--- a/drivers/media/video/saa7134/saa6752hs.c
+++ b/drivers/media/video/saa7134/saa6752hs.c
@@ -22,7 +22,6 @@
/* Addresses to scan */
static unsigned short normal_i2c[] = {0x20, I2C_CLIENT_END};
-static unsigned short normal_i2c_range[] = {I2C_CLIENT_END};
I2C_CLIENT_INSMOD;
MODULE_DESCRIPTION("device driver for saa6752hs MPEG2 encoder");
@@ -42,16 +41,16 @@ enum saa6752hs_videoformat {
static const struct v4l2_format v4l2_format_table[] =
{
- [SAA6752HS_VF_D1] = {
- .fmt.pix.width = 720, .fmt.pix.height = 576 },
- [SAA6752HS_VF_2_3_D1] = {
- .fmt.pix.width = 480, .fmt.pix.height = 576 },
- [SAA6752HS_VF_1_2_D1] = {
- .fmt.pix.width = 352, .fmt.pix.height = 576 },
- [SAA6752HS_VF_SIF] = {
- .fmt.pix.width = 352, .fmt.pix.height = 288 },
- [SAA6752HS_VF_UNKNOWN] = {
- .fmt.pix.width = 0, .fmt.pix.height = 0},
+ [SAA6752HS_VF_D1] =
+ { .fmt = { .pix = { .width = 720, .height = 576 }}},
+ [SAA6752HS_VF_2_3_D1] =
+ { .fmt = { .pix = { .width = 480, .height = 576 }}},
+ [SAA6752HS_VF_1_2_D1] =
+ { .fmt = { .pix = { .width = 352, .height = 576 }}},
+ [SAA6752HS_VF_SIF] =
+ { .fmt = { .pix = { .width = 352, .height = 288 }}},
+ [SAA6752HS_VF_UNKNOWN] =
+ { .fmt = { .pix = { .width = 0, .height = 0}}},
};
struct saa6752hs_state {
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index c51eb7f078d..0c781e24c44 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -1,6 +1,6 @@
/*
- * $Id: saa7134-cards.c,v 1.54 2005/03/07 12:01:51 kraxel Exp $
+ * $Id: saa7134-cards.c,v 1.58 2005/06/07 18:05:00 nsh Exp $
*
* device driver for philips saa7134 based TV cards
* card-specific stuff.
@@ -165,7 +165,7 @@ struct saa7134_board saa7134_boards[] = {
.inputs = {{
.name = name_tv,
.vmux = 1,
- .amux = LINE2,
+ .amux = TV,
.tv = 1,
},{
.name = name_comp1,
@@ -878,7 +878,7 @@ struct saa7134_board saa7134_boards[] = {
},
[SAA7134_BOARD_MANLI_MTV002] = {
/* Ognjen Nastic <ognjen@logosoft.ba> */
- .name = "Manli MuchTV M-TV002",
+ .name = "Manli MuchTV M-TV002/Behold TV 403 FM",
.audio_clock = 0x00200000,
.tuner_type = TUNER_PHILIPS_PAL,
.inputs = {{
@@ -899,14 +899,10 @@ struct saa7134_board saa7134_boards[] = {
.name = name_radio,
.amux = LINE2,
},
- .mute = {
- .name = name_mute,
- .amux = LINE1,
- },
},
[SAA7134_BOARD_MANLI_MTV001] = {
/* Ognjen Nastic <ognjen@logosoft.ba> UNTESTED */
- .name = "Manli MuchTV M-TV001",
+ .name = "Manli MuchTV M-TV001/Behold TV 401",
.audio_clock = 0x00200000,
.tuner_type = TUNER_PHILIPS_PAL,
.inputs = {{
@@ -923,6 +919,10 @@ struct saa7134_board saa7134_boards[] = {
.amux = LINE2,
.tv = 1,
}},
+ .mute = {
+ .name = name_mute,
+ .amux = LINE1,
+ },
},
[SAA7134_BOARD_TG3000TV] = {
/* TransGear 3000TV */
@@ -1078,7 +1078,6 @@ struct saa7134_board saa7134_boards[] = {
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_FM1256_IH3,
.tda9887_conf = TDA9887_PRESENT,
- .gpiomask = 0x3,
.inputs = {{
.name = name_tv,
.vmux = 1,
@@ -1285,7 +1284,7 @@ struct saa7134_board saa7134_boards[] = {
.gpio =0x8000,
}
},
- [SAA7134_BOARD_AVERMEDIA_307] = {
+ [SAA7134_BOARD_AVERMEDIA_STUDIO_307] = {
/*
Nickolay V. Shmyrev <nshmyrev@yandex.ru>
Lots of thanks to Andrey Zolotarev <zolotarev_andrey@mail.ru>
@@ -1323,6 +1322,35 @@ struct saa7134_board saa7134_boards[] = {
.gpio = 0x01,
},
},
+ [SAA7134_BOARD_AVERMEDIA_GO_007_FM] = {
+ .name = "Avermedia AVerTV GO 007 FM",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .gpiomask = 0x00300003,
+// .gpiomask = 0x8c240003,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ .gpio = 0x01,
+ },{
+ .name = name_comp1,
+ .vmux = 0,
+ .amux = LINE2,
+ .gpio = 0x02,
+ },{
+ .name = name_svideo,
+ .vmux = 6,
+ .amux = LINE2,
+ .gpio = 0x02,
+ }},
+ .radio = {
+ .name = name_radio,
+ .amux = LINE1,
+ .gpio = 0x00300001,
+ },
+ },
[SAA7134_BOARD_AVERMEDIA_CARDBUS] = {
/* Jon Westgate <oryn@oryn.fsck.tv> */
.name = "AVerMedia Cardbus TV/Radio",
@@ -1492,7 +1520,6 @@ struct saa7134_board saa7134_boards[] = {
.audio_clock = 0x00187de7,
.tuner_type = TUNER_PHILIPS_FQ1216ME,
.tda9887_conf = TDA9887_PRESENT,
- .gpiomask = 0x3,
.inputs = {{
.name = name_tv,
.vmux = 1,
@@ -1546,7 +1573,82 @@ struct saa7134_board saa7134_boards[] = {
// .gpio = 0x4000,
}},
},
-};
+ [SAA7134_BOARD_AVERMEDIA_307] = {
+ /*
+ Davydov Vladimir <vladimir@iqmedia.com>
+ */
+ .name = "Avermedia AVerTV 307",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_FQ1216ME,
+ .tda9887_conf = TDA9887_PRESENT,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_comp1,
+ .vmux = 0,
+ .amux = LINE1,
+ },{
+ .name = name_comp2,
+ .vmux = 3,
+ .amux = LINE1,
+ },{
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE1,
+ }},
+ },
+ [SAA7134_BOARD_ADS_INSTANT_TV] = {
+ .name = "ADS Tech Instant TV (saa7135)",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_TDA8290,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ },{
+ .name = name_comp1,
+ .vmux = 3,
+ .amux = LINE2,
+ },{
+ .name = name_svideo,
+ .vmux = 8,
+ .amux = LINE2,
+ }},
+ },
+ [SAA7134_BOARD_KWORLD_VSTREAM_XPERT] = {
+ .name = "Kworld/Tevion V-Stream Xpert TV PVR7134",
+ .audio_clock = 0x00187de7,
+ .tuner_type = TUNER_PHILIPS_PAL_I,
+ .gpiomask = 0x0700,
+ .inputs = {{
+ .name = name_tv,
+ .vmux = 1,
+ .amux = TV,
+ .tv = 1,
+ .gpio = 0x000,
+ },{
+ .name = name_comp1,
+ .vmux = 3,
+ .amux = LINE1,
+ .gpio = 0x200, //gpio by DScaler
+ },{
+ .name = name_svideo,
+ .vmux = 0,
+ .amux = LINE1,
+ .gpio = 0x200,
+ }},
+ .radio = {
+ .name = name_radio,
+ .amux = LINE1,
+ .gpio = 0x100,
+ },
+ },
+ };
+
const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
/* ------------------------------------------------------------------ */
@@ -1663,7 +1765,7 @@ struct pci_device_id saa7134_pci_tbl[] = {
.driver_data = SAA7134_BOARD_ASUSTeK_TVFM7134,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
- .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7135,
.subvendor = PCI_VENDOR_ID_ASUSTEK,
.subdevice = 0x4845,
.driver_data = SAA7135_BOARD_ASUSTeK_TVFM7135,
@@ -1824,6 +1926,12 @@ struct pci_device_id saa7134_pci_tbl[] = {
.device = PCI_DEVICE_ID_PHILIPS_SAA7134,
.subvendor = 0x1461, /* Avermedia Technologies Inc */
.subdevice = 0x9715,
+ .driver_data = SAA7134_BOARD_AVERMEDIA_STUDIO_307,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7134,
+ .subvendor = 0x1461, /* Avermedia Technologies Inc */
+ .subdevice = 0xa70a,
.driver_data = SAA7134_BOARD_AVERMEDIA_307,
},{
.vendor = PCI_VENDOR_ID_PHILIPS,
@@ -1844,6 +1952,26 @@ struct pci_device_id saa7134_pci_tbl[] = {
.subvendor = 0x5168,
.subdevice = 0x0306,
.driver_data = SAA7134_BOARD_FLYDVBTDUO,
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7133,
+ .subvendor = 0x1461, /* Avermedia Technologies Inc */
+ .subdevice = 0xf31f,
+ .driver_data = SAA7134_BOARD_AVERMEDIA_GO_007_FM,
+
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7135,
+ .subvendor = 0x1421,
+ .subdevice = 0x0350, /* PCI version */
+ .driver_data = SAA7134_BOARD_ADS_INSTANT_TV,
+
+ },{
+ .vendor = PCI_VENDOR_ID_PHILIPS,
+ .device = PCI_DEVICE_ID_PHILIPS_SAA7135,
+ .subvendor = 0x1421,
+ .subdevice = 0x0370, /* cardbus version */
+ .driver_data = SAA7134_BOARD_ADS_INSTANT_TV,
},{
/* --- boards without eeprom + subsystem ID --- */
@@ -1954,20 +2082,23 @@ int saa7134_board_init1(struct saa7134_dev *dev)
dev->has_remote = 1;
board_flyvideo(dev);
break;
- case SAA7134_BOARD_FLYTVPLATINUM_FM:
+ case SAA7134_BOARD_FLYTVPLATINUM_FM:
case SAA7134_BOARD_CINERGY400:
case SAA7134_BOARD_CINERGY600:
case SAA7134_BOARD_CINERGY600_MK3:
case SAA7134_BOARD_ECS_TVP3XP:
case SAA7134_BOARD_ECS_TVP3XP_4CB5:
case SAA7134_BOARD_MD2819:
+ case SAA7134_BOARD_KWORLD_VSTREAM_XPERT:
case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
case SAA7134_BOARD_AVERMEDIA_305:
+ case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
case SAA7134_BOARD_AVERMEDIA_307:
+ case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
// case SAA7134_BOARD_SABRENT_SBTTVFM: /* not finished yet */
case SAA7134_BOARD_VIDEOMATE_TV_PVR:
- dev->has_remote = 1;
- break;
+ case SAA7134_BOARD_MANLI_MTV001:
+ case SAA7134_BOARD_MANLI_MTV002:
case SAA7134_BOARD_AVACSSMARTTV:
dev->has_remote = 1;
break;
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index d506cafba8f..f61ed1849a2 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -1,5 +1,5 @@
/*
- * $Id: saa7134-core.c,v 1.28 2005/02/22 09:56:29 kraxel Exp $
+ * $Id: saa7134-core.c,v 1.30 2005/05/22 19:23:39 nsh Exp $
*
* device driver for philips saa7134 based TV cards
* driver core
@@ -316,7 +316,7 @@ unsigned long saa7134_buffer_base(struct saa7134_buf *buf)
int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt)
{
- u32 *cpu;
+ __le32 *cpu;
dma_addr_t dma_addr;
cpu = pci_alloc_consistent(pci, SAA7134_PGTABLE_SIZE, &dma_addr);
@@ -332,7 +332,7 @@ int saa7134_pgtable_build(struct pci_dev *pci, struct saa7134_pgtable *pt,
struct scatterlist *list, unsigned int length,
unsigned int startpage)
{
- u32 *ptr;
+ __le32 *ptr;
unsigned int i,p;
BUG_ON(NULL == pt || NULL == pt->cpu);
@@ -340,7 +340,7 @@ int saa7134_pgtable_build(struct pci_dev *pci, struct saa7134_pgtable *pt,
ptr = pt->cpu + startpage;
for (i = 0; i < length; i++, list++)
for (p = 0; p * 4096 < list->length; p++, ptr++)
- *ptr = sg_dma_address(list) - list->offset;
+ *ptr = cpu_to_le32(sg_dma_address(list) - list->offset);
return 0;
}
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index c2873ae029f..aa8e2cf62d5 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -1,5 +1,5 @@
/*
- * $Id: saa7134-dvb.c,v 1.12 2005/02/18 12:28:29 kraxel Exp $
+ * $Id: saa7134-dvb.c,v 1.13 2005/06/12 04:19:19 mchehab Exp $
*
* (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
*
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index fa135733690..c85348d0239 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -1,5 +1,5 @@
/*
- * $Id: saa7134-empress.c,v 1.10 2005/02/03 10:24:33 kraxel Exp $
+ * $Id: saa7134-empress.c,v 1.11 2005/05/22 19:23:39 nsh Exp $
*
* (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
*
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
index 702bb63d981..b6f002e8421 100644
--- a/drivers/media/video/saa7134/saa7134-i2c.c
+++ b/drivers/media/video/saa7134/saa7134-i2c.c
@@ -1,5 +1,5 @@
/*
- * $Id: saa7134-i2c.c,v 1.10 2005/01/24 17:37:23 kraxel Exp $
+ * $Id: saa7134-i2c.c,v 1.11 2005/06/12 01:36:14 mchehab Exp $
*
* device driver for philips saa7134 based TV cards
* i2c interface support
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index ca50cf531f2..aba2b9de60d 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -1,5 +1,5 @@
/*
- * $Id: saa7134-input.c,v 1.16 2004/12/10 12:33:39 kraxel Exp $
+ * $Id: saa7134-input.c,v 1.19 2005/06/07 18:02:26 nsh Exp $
*
* handle saa7134 IR remotes via linux kernel input layer.
*
@@ -308,6 +308,102 @@ static IR_KEYTAB_TYPE videomate_tv_pvr_codes[IR_KEYTAB_SIZE] = {
[ 32 ] = KEY_LANGUAGE,
[ 33 ] = KEY_SLEEP,
};
+
+/* Michael Tokarev <mjt@tls.msk.ru>
+ http://www.corpit.ru/mjt/beholdTV/remote_control.jpg
+ keytable is used by MANLI MTV00[12] and BeholdTV 40[13] at
+ least, and probably other cards too.
+ The "ascii-art picture" below (in comments, first row
+ is the keycode in hex, and subsequent row(s) shows
+ the button labels (several variants when appropriate)
+ helps to descide which keycodes to assign to the buttons.
+ */
+static IR_KEYTAB_TYPE manli_codes[IR_KEYTAB_SIZE] = {
+
+ /* 0x1c 0x12 *
+ * FUNCTION POWER *
+ * FM (|) *
+ * */
+ [ 0x1c ] = KEY_RADIO, /*XXX*/
+ [ 0x12 ] = KEY_POWER,
+
+ /* 0x01 0x02 0x03 *
+ * 1 2 3 *
+ * *
+ * 0x04 0x05 0x06 *
+ * 4 5 6 *
+ * *
+ * 0x07 0x08 0x09 *
+ * 7 8 9 *
+ * */
+ [ 0x01 ] = KEY_KP1,
+ [ 0x02 ] = KEY_KP2,
+ [ 0x03 ] = KEY_KP3,
+ [ 0x04 ] = KEY_KP4,
+ [ 0x05 ] = KEY_KP5,
+ [ 0x06 ] = KEY_KP6,
+ [ 0x07 ] = KEY_KP7,
+ [ 0x08 ] = KEY_KP8,
+ [ 0x09 ] = KEY_KP9,
+
+ /* 0x0a 0x00 0x17 *
+ * RECALL 0 +100 *
+ * PLUS *
+ * */
+ [ 0x0a ] = KEY_AGAIN, /*XXX KEY_REWIND? */
+ [ 0x00 ] = KEY_KP0,
+ [ 0x17 ] = KEY_DIGITS, /*XXX*/
+
+ /* 0x14 0x10 *
+ * MENU INFO *
+ * OSD */
+ [ 0x14 ] = KEY_MENU,
+ [ 0x10 ] = KEY_INFO,
+
+ /* 0x0b *
+ * Up *
+ * *
+ * 0x18 0x16 0x0c *
+ * Left Ok Right *
+ * *
+ * 0x015 *
+ * Down *
+ * */
+ [ 0x0b ] = KEY_UP, /*XXX KEY_SCROLLUP? */
+ [ 0x18 ] = KEY_LEFT, /*XXX KEY_BACK? */
+ [ 0x16 ] = KEY_OK, /*XXX KEY_SELECT? KEY_ENTER? */
+ [ 0x0c ] = KEY_RIGHT, /*XXX KEY_FORWARD? */
+ [ 0x15 ] = KEY_DOWN, /*XXX KEY_SCROLLDOWN? */
+
+ /* 0x11 0x0d *
+ * TV/AV MODE *
+ * SOURCE STEREO *
+ * */
+ [ 0x11 ] = KEY_TV, /*XXX*/
+ [ 0x0d ] = KEY_MODE, /*XXX there's no KEY_STEREO */
+
+ /* 0x0f 0x1b 0x1a *
+ * AUDIO Vol+ Chan+ *
+ * TIMESHIFT??? *
+ * *
+ * 0x0e 0x1f 0x1e *
+ * SLEEP Vol- Chan- *
+ * */
+ [ 0x0f ] = KEY_AUDIO,
+ [ 0x1b ] = KEY_VOLUMEUP,
+ [ 0x1a ] = KEY_CHANNELUP,
+ [ 0x0e ] = KEY_SLEEP, /*XXX maybe KEY_PAUSE */
+ [ 0x1f ] = KEY_VOLUMEDOWN,
+ [ 0x1e ] = KEY_CHANNELDOWN,
+
+ /* 0x13 0x19 *
+ * MUTE SNAPSHOT*
+ * */
+ [ 0x13 ] = KEY_MUTE,
+ [ 0x19 ] = KEY_RECORD, /*XXX*/
+
+ // 0x1d unused ?
+};
/* ---------------------------------------------------------------------- */
static int build_key(struct saa7134_dev *dev)
@@ -379,7 +475,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
switch (dev->board) {
case SAA7134_BOARD_FLYVIDEO2000:
case SAA7134_BOARD_FLYVIDEO3000:
- case SAA7134_BOARD_FLYTVPLATINUM_FM:
+ case SAA7134_BOARD_FLYTVPLATINUM_FM:
ir_codes = flyvideo_codes;
mask_keycode = 0xEC00000;
mask_keydown = 0x0040000;
@@ -405,8 +501,12 @@ int saa7134_input_init1(struct saa7134_dev *dev)
polling = 50; // ms
break;
case SAA7134_BOARD_MD2819:
+ case SAA7134_BOARD_KWORLD_VSTREAM_XPERT:
case SAA7134_BOARD_AVERMEDIA_305:
case SAA7134_BOARD_AVERMEDIA_307:
+ case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
+ case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
+ case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
ir_codes = md2819_codes;
mask_keycode = 0x0007C8;
mask_keydown = 0x000010;
@@ -415,6 +515,14 @@ int saa7134_input_init1(struct saa7134_dev *dev)
saa_setb(SAA7134_GPIO_GPMODE0, 0x4);
saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4);
break;
+ case SAA7134_BOARD_MANLI_MTV001:
+ case SAA7134_BOARD_MANLI_MTV002:
+ ir_codes = manli_codes;
+ mask_keycode = 0x001f00;
+ mask_keyup = 0x004000;
+ mask_keydown = 0x002000;
+ polling = 50; // ms
+ break;
case SAA7134_BOARD_VIDEOMATE_TV_PVR:
ir_codes = videomate_tv_pvr_codes;
mask_keycode = 0x00003F;
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c
index 6b6a643bf1c..81732904623 100644
--- a/drivers/media/video/saa7134/saa7134-oss.c
+++ b/drivers/media/video/saa7134/saa7134-oss.c
@@ -1,5 +1,5 @@
/*
- * $Id: saa7134-oss.c,v 1.13 2004/12/10 12:33:39 kraxel Exp $
+ * $Id: saa7134-oss.c,v 1.14 2005/05/18 22:45:16 hhackmann Exp $
*
* device driver for philips saa7134 based TV cards
* oss dsp interface
@@ -49,7 +49,6 @@ MODULE_PARM_DESC(oss_rate,"sample rate (valid are: 32000,48000)");
static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks)
{
- blksize &= ~0xff;
if (blksize < 0x100)
blksize = 0x100;
if (blksize > 0x10000)
@@ -57,8 +56,6 @@ static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks)
if (blocks < 2)
blocks = 2;
- while ((blksize * blocks) & ~PAGE_MASK)
- blocks++;
if ((blksize * blocks) > 1024*1024)
blocks = 1024*1024 / blksize;
@@ -79,7 +76,7 @@ static int dsp_buffer_init(struct saa7134_dev *dev)
BUG();
videobuf_dma_init(&dev->oss.dma);
err = videobuf_dma_init_kernel(&dev->oss.dma, PCI_DMA_FROMDEVICE,
- dev->oss.bufsize >> PAGE_SHIFT);
+ (dev->oss.bufsize + PAGE_SIZE) >> PAGE_SHIFT);
if (0 != err)
return err;
return 0;
@@ -163,10 +160,11 @@ static int dsp_rec_start(struct saa7134_dev *dev)
fmt |= 0x04;
fmt |= (TV == dev->oss.input) ? 0xc0 : 0x80;
- saa_writeb(SAA7134_NUM_SAMPLES0, (dev->oss.blksize & 0x0000ff));
- saa_writeb(SAA7134_NUM_SAMPLES1, (dev->oss.blksize & 0x00ff00) >> 8);
- saa_writeb(SAA7134_NUM_SAMPLES2, (dev->oss.blksize & 0xff0000) >> 16);
+ saa_writeb(SAA7134_NUM_SAMPLES0, ((dev->oss.blksize - 1) & 0x0000ff));
+ saa_writeb(SAA7134_NUM_SAMPLES1, ((dev->oss.blksize - 1) & 0x00ff00) >> 8);
+ saa_writeb(SAA7134_NUM_SAMPLES2, ((dev->oss.blksize - 1) & 0xff0000) >> 16);
saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt);
+
break;
case PCI_DEVICE_ID_PHILIPS_SAA7133:
case PCI_DEVICE_ID_PHILIPS_SAA7135:
@@ -817,7 +815,7 @@ void saa7134_irq_oss_done(struct saa7134_dev *dev, unsigned long status)
reg = SAA7134_RS_BA1(6);
} else {
/* even */
- if (0 == (dev->oss.dma_blk & 0x00))
+ if (1 == (dev->oss.dma_blk & 0x01))
reg = SAA7134_RS_BA2(6);
}
if (0 == reg) {
diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c
index ecac13c006d..3617e7f7a41 100644
--- a/drivers/media/video/saa7134/saa7134-tvaudio.c
+++ b/drivers/media/video/saa7134/saa7134-tvaudio.c
@@ -1,5 +1,5 @@
/*
- * $Id: saa7134-tvaudio.c,v 1.22 2005/01/07 13:11:19 kraxel Exp $
+ * $Id: saa7134-tvaudio.c,v 1.25 2005/06/07 19:00:38 nsh Exp $
*
* device driver for philips saa7134 based TV cards
* tv audio decoder (fm stereo, nicam, ...)
@@ -181,7 +181,8 @@ static void tvaudio_init(struct saa7134_dev *dev)
saa_writeb(SAA7134_AUDIO_CLOCK0, clock & 0xff);
saa_writeb(SAA7134_AUDIO_CLOCK1, (clock >> 8) & 0xff);
saa_writeb(SAA7134_AUDIO_CLOCK2, (clock >> 16) & 0xff);
- saa_writeb(SAA7134_AUDIO_PLL_CTRL, 0x01);
+ // frame locked audio was reported not to be reliable
+ saa_writeb(SAA7134_AUDIO_PLL_CTRL, 0x02);
saa_writeb(SAA7134_NICAM_ERROR_LOW, 0x14);
saa_writeb(SAA7134_NICAM_ERROR_HIGH, 0x50);
@@ -250,6 +251,11 @@ static void mute_input_7134(struct saa7134_dev *dev)
saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, ausel);
saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, ics);
saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x07, ocs);
+ // for oss, we need to change the clock configuration
+ if (in->amux == TV)
+ saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, 0x00);
+ else
+ saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, 0x01);
/* switch gpio-connected external audio mux */
if (0 == card(dev).gpiomask)
@@ -439,16 +445,15 @@ static int tvaudio_getstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *au
nicam = saa_readb(SAA7134_NICAM_STATUS);
dprintk("getstereo: nicam=0x%x\n",nicam);
switch (nicam & 0x0b) {
+ case 0x08:
+ retval = V4L2_TUNER_SUB_MONO;
+ break;
case 0x09:
retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
break;
case 0x0a:
retval = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
break;
- case 0x08:
- default:
- retval = V4L2_TUNER_SUB_MONO;
- break;
}
break;
}
@@ -572,14 +577,14 @@ static int tvaudio_thread(void *data)
} else if (0 != dev->last_carrier) {
/* no carrier -- try last detected one as fallback */
carrier = dev->last_carrier;
- printk(KERN_WARNING "%s/audio: audio carrier scan failed, "
+ dprintk(KERN_WARNING "%s/audio: audio carrier scan failed, "
"using %d.%03d MHz [last detected]\n",
dev->name, carrier/1000, carrier%1000);
} else {
/* no carrier + no fallback -- use default */
carrier = default_carrier;
- printk(KERN_WARNING "%s/audio: audio carrier scan failed, "
+ dprintk(KERN_WARNING "%s/audio: audio carrier scan failed, "
"using %d.%03d MHz [default]\n",
dev->name, carrier/1000, carrier%1000);
}
diff --git a/drivers/media/video/saa7134/saa7134-vbi.c b/drivers/media/video/saa7134/saa7134-vbi.c
index 86954cc7c37..3c33c591cc8 100644
--- a/drivers/media/video/saa7134/saa7134-vbi.c
+++ b/drivers/media/video/saa7134/saa7134-vbi.c
@@ -1,5 +1,5 @@
/*
- * $Id: saa7134-vbi.c,v 1.6 2004/12/10 12:33:39 kraxel Exp $
+ * $Id: saa7134-vbi.c,v 1.7 2005/05/24 23:13:06 nsh Exp $
*
* device driver for philips saa7134 based TV cards
* video4linux video interface
@@ -60,10 +60,10 @@ static void task_init(struct saa7134_dev *dev, struct saa7134_buf *buf,
saa_writeb(SAA7134_VBI_H_START2(task), norm->h_start >> 8);
saa_writeb(SAA7134_VBI_H_STOP1(task), norm->h_stop & 0xff);
saa_writeb(SAA7134_VBI_H_STOP2(task), norm->h_stop >> 8);
- saa_writeb(SAA7134_VBI_V_START1(task), norm->vbi_v_start & 0xff);
- saa_writeb(SAA7134_VBI_V_START2(task), norm->vbi_v_start >> 8);
- saa_writeb(SAA7134_VBI_V_STOP1(task), norm->vbi_v_stop & 0xff);
- saa_writeb(SAA7134_VBI_V_STOP2(task), norm->vbi_v_stop >> 8);
+ saa_writeb(SAA7134_VBI_V_START1(task), norm->vbi_v_start_0 & 0xff);
+ saa_writeb(SAA7134_VBI_V_START2(task), norm->vbi_v_start_0 >> 8);
+ saa_writeb(SAA7134_VBI_V_STOP1(task), norm->vbi_v_stop_0 & 0xff);
+ saa_writeb(SAA7134_VBI_V_STOP2(task), norm->vbi_v_stop_0 >> 8);
saa_writeb(SAA7134_VBI_H_SCALE_INC1(task), VBI_SCALE & 0xff);
saa_writeb(SAA7134_VBI_H_SCALE_INC2(task), VBI_SCALE >> 8);
@@ -127,7 +127,7 @@ static int buffer_prepare(struct videobuf_queue *q,
unsigned int lines, llength, size;
int err;
- lines = norm->vbi_v_stop - norm->vbi_v_start +1;
+ lines = norm->vbi_v_stop_0 - norm->vbi_v_start_0 +1;
if (lines > VBI_LINE_COUNT)
lines = VBI_LINE_COUNT;
#if 1
@@ -177,7 +177,7 @@ buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
struct saa7134_dev *dev = fh->dev;
int llength,lines;
- lines = dev->tvnorm->vbi_v_stop - dev->tvnorm->vbi_v_start +1;
+ lines = dev->tvnorm->vbi_v_stop_0 - dev->tvnorm->vbi_v_start_0 +1;
#if 1
llength = VBI_LINE_LENGTH;
#else
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index 5d66060026f..c0a2ee52053 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -1,5 +1,5 @@
/*
- * $Id: saa7134-video.c,v 1.28 2005/02/15 15:59:35 kraxel Exp $
+ * $Id: saa7134-video.c,v 1.30 2005/06/07 19:00:38 nsh Exp $
*
* device driver for philips saa7134 based TV cards
* video4linux video interface
@@ -31,8 +31,6 @@
#include "saa7134-reg.h"
#include "saa7134.h"
-#define V4L2_I2C_CLIENTS 1
-
/* ------------------------------------------------------------------ */
static unsigned int video_debug = 0;
@@ -158,18 +156,20 @@ static struct saa7134_format formats[] = {
.h_stop = 719, \
.video_v_start = 24, \
.video_v_stop = 311, \
- .vbi_v_start = 7, \
- .vbi_v_stop = 22, \
+ .vbi_v_start_0 = 7, \
+ .vbi_v_stop_0 = 22, \
+ .vbi_v_start_1 = 319, \
.src_timing = 4
#define NORM_525_60 \
.h_start = 0, \
.h_stop = 703, \
- .video_v_start = 22, \
- .video_v_stop = 22+239, \
- .vbi_v_start = 10, /* FIXME */ \
- .vbi_v_stop = 21, /* FIXME */ \
- .src_timing = 1
+ .video_v_start = 23, \
+ .video_v_stop = 262, \
+ .vbi_v_start_0 = 10, \
+ .vbi_v_stop_0 = 21, \
+ .vbi_v_start_1 = 273, \
+ .src_timing = 7
static struct saa7134_tvnorm tvnorms[] = {
{
@@ -274,11 +274,12 @@ static struct saa7134_tvnorm tvnorms[] = {
.h_start = 0,
.h_stop = 719,
- .video_v_start = 22,
- .video_v_stop = 22+239,
- .vbi_v_start = 10, /* FIXME */
- .vbi_v_stop = 21, /* FIXME */
- .src_timing = 1,
+ .video_v_start = 23,
+ .video_v_stop = 262,
+ .vbi_v_start_0 = 10,
+ .vbi_v_stop_0 = 21,
+ .vbi_v_start_1 = 273,
+ .src_timing = 7,
.sync_control = 0x18,
.luma_control = 0x40,
@@ -335,8 +336,8 @@ static const struct v4l2_queryctrl video_ctrls[] = {
.default_value = 0,
.type = V4L2_CTRL_TYPE_INTEGER,
},{
- .id = V4L2_CID_VFLIP,
- .name = "vertical flip",
+ .id = V4L2_CID_HFLIP,
+ .name = "Mirror",
.minimum = 0,
.maximum = 1,
.type = V4L2_CTRL_TYPE_BOOLEAN,
@@ -482,7 +483,7 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
dev->crop_bounds.width = norm->h_stop - norm->h_start +1;
dev->crop_defrect.width = norm->h_stop - norm->h_start +1;
- dev->crop_bounds.top = (norm->vbi_v_stop+1)*2;
+ dev->crop_bounds.top = (norm->vbi_v_stop_0+1)*2;
dev->crop_defrect.top = norm->video_v_start*2;
dev->crop_bounds.height = ((norm->id & V4L2_STD_525_60) ? 524 : 624)
- dev->crop_bounds.top;
@@ -521,22 +522,7 @@ static void set_tvnorm(struct saa7134_dev *dev, struct saa7134_tvnorm *norm)
saa_writeb(SAA7134_RAW_DATA_GAIN, 0x40);
saa_writeb(SAA7134_RAW_DATA_OFFSET, 0x80);
-#ifdef V4L2_I2C_CLIENTS
saa7134_i2c_call_clients(dev,VIDIOC_S_STD,&norm->id);
-#else
- {
- /* pass down info to the i2c chips (v4l1) */
- struct video_channel c;
- memset(&c,0,sizeof(c));
- c.channel = dev->ctl_input;
- c.norm = VIDEO_MODE_PAL;
- if (norm->id & V4L2_STD_NTSC)
- c.norm = VIDEO_MODE_NTSC;
- if (norm->id & V4L2_STD_SECAM)
- c.norm = VIDEO_MODE_SECAM;
- saa7134_i2c_call_clients(dev,VIDIOCSCHAN,&c);
- }
-#endif
}
static void video_mux(struct saa7134_dev *dev, int input)
@@ -1064,7 +1050,7 @@ static int get_control(struct saa7134_dev *dev, struct v4l2_control *c)
case V4L2_CID_PRIVATE_INVERT:
c->value = dev->ctl_invert;
break;
- case V4L2_CID_VFLIP:
+ case V4L2_CID_HFLIP:
c->value = dev->ctl_mirror;
break;
case V4L2_CID_PRIVATE_Y_EVEN:
@@ -1139,7 +1125,7 @@ static int set_control(struct saa7134_dev *dev, struct saa7134_fh *fh,
saa_writeb(SAA7134_DEC_CHROMA_SATURATION,
dev->ctl_invert ? -dev->ctl_saturation : dev->ctl_saturation);
break;
- case V4L2_CID_VFLIP:
+ case V4L2_CID_HFLIP:
dev->ctl_mirror = c->value;
restart_overlay = 1;
break;
@@ -1407,9 +1393,9 @@ static void saa7134_vbi_fmt(struct saa7134_dev *dev, struct v4l2_format *f)
f->fmt.vbi.samples_per_line = 2048 /* VBI_LINE_LENGTH */;
f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
f->fmt.vbi.offset = 64 * 4;
- f->fmt.vbi.start[0] = norm->vbi_v_start;
- f->fmt.vbi.count[0] = norm->vbi_v_stop - norm->vbi_v_start +1;
- f->fmt.vbi.start[1] = norm->video_v_stop + norm->vbi_v_start +1;
+ f->fmt.vbi.start[0] = norm->vbi_v_start_0;
+ f->fmt.vbi.count[0] = norm->vbi_v_stop_0 - norm->vbi_v_start_0 +1;
+ f->fmt.vbi.start[1] = norm->vbi_v_start_1;
f->fmt.vbi.count[1] = f->fmt.vbi.count[0];
f->fmt.vbi.flags = 0; /* VBI_UNSYNC VBI_INTERLACED */
@@ -1880,11 +1866,9 @@ static int video_do_ioctl(struct inode *inode, struct file *file,
return -EINVAL;
down(&dev->lock);
dev->ctl_freq = f->frequency;
-#ifdef V4L2_I2C_CLIENTS
+
saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,f);
-#else
- saa7134_i2c_call_clients(dev,VIDIOCSFREQ,&dev->ctl_freq);
-#endif
+
saa7134_tvaudio_do_scan(dev);
up(&dev->lock);
return 0;
@@ -2139,16 +2123,19 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
t->rangelow = (int)(65*16);
t->rangehigh = (int)(108*16);
-#ifdef V4L2_I2C_CLIENTS
- saa7134_i2c_call_clients(dev,VIDIOC_G_TUNER,t);
-#else
- {
- struct video_tuner vt;
- memset(&vt,0,sizeof(vt));
- saa7134_i2c_call_clients(dev,VIDIOCGTUNER,&vt);
- t->signal = vt.signal;
- }
-#endif
+ saa7134_i2c_call_clients(dev, VIDIOC_G_TUNER, t);
+
+ return 0;
+ }
+ case VIDIOC_S_TUNER:
+ {
+ struct v4l2_tuner *t = arg;
+
+ if (0 != t->index)
+ return -EINVAL;
+
+ saa7134_i2c_call_clients(dev,VIDIOC_S_TUNER,t);
+
return 0;
}
case VIDIOC_ENUMINPUT:
@@ -2182,7 +2169,6 @@ static int radio_do_ioctl(struct inode *inode, struct file *file,
return 0;
}
case VIDIOC_S_AUDIO:
- case VIDIOC_S_TUNER:
case VIDIOC_S_INPUT:
case VIDIOC_S_STD:
return 0;
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index ac90a985323..d6b1c0d4d0f 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -1,5 +1,5 @@
/*
- * $Id: saa7134.h,v 1.38 2005/03/07 12:01:51 kraxel Exp $
+ * $Id: saa7134.h,v 1.41 2005/06/07 18:02:26 nsh Exp $
*
* v4l2 device driver for philips saa7134 based TV cards
*
@@ -21,7 +21,7 @@
*/
#include <linux/version.h>
-#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,12)
+#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,13)
#include <linux/pci.h>
#include <linux/i2c.h>
@@ -91,9 +91,10 @@ struct saa7134_tvnorm {
unsigned int h_stop;
unsigned int video_v_start;
unsigned int video_v_stop;
- unsigned int vbi_v_start;
- unsigned int vbi_v_stop;
+ unsigned int vbi_v_start_0;
+ unsigned int vbi_v_stop_0;
unsigned int src_timing;
+ unsigned int vbi_v_start_1;
};
struct saa7134_tvaudio {
@@ -167,7 +168,7 @@ struct saa7134_format {
#define SAA7134_BOARD_SABRENT_SBTTVFM 42
#define SAA7134_BOARD_ZOLID_XPERT_TV7134 43
#define SAA7134_BOARD_EMPIRE_PCI_TV_RADIO_LE 44
-#define SAA7134_BOARD_AVERMEDIA_307 45
+#define SAA7134_BOARD_AVERMEDIA_STUDIO_307 45
#define SAA7134_BOARD_AVERMEDIA_CARDBUS 46
#define SAA7134_BOARD_CINERGY400_CARDBUS 47
#define SAA7134_BOARD_CINERGY600_MK3 48
@@ -178,6 +179,10 @@ struct saa7134_format {
#define SAA7135_BOARD_ASUSTeK_TVFM7135 53
#define SAA7134_BOARD_FLYTVPLATINUM_FM 54
#define SAA7134_BOARD_FLYDVBTDUO 55
+#define SAA7134_BOARD_AVERMEDIA_307 56
+#define SAA7134_BOARD_AVERMEDIA_GO_007_FM 57
+#define SAA7134_BOARD_ADS_INSTANT_TV 58
+#define SAA7134_BOARD_KWORLD_VSTREAM_XPERT 59
#define SAA7134_MAXBOARDS 8
#define SAA7134_INPUT_MAX 8
@@ -241,7 +246,7 @@ struct saa7134_dma;
/* saa7134 page table */
struct saa7134_pgtable {
unsigned int size;
- u32 *cpu;
+ __le32 *cpu;
dma_addr_t dma;
};
diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c
index 5f0b224c3cb..108e7a4a027 100644
--- a/drivers/media/video/saa7185.c
+++ b/drivers/media/video/saa7185.c
@@ -380,22 +380,14 @@ saa7185_command (struct i2c_client *client,
* concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
*/
static unsigned short normal_i2c[] = { I2C_SAA7185 >> 1, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
- .normal_i2c_range = normal_i2c_range,
- .probe = probe,
- .probe_range = probe_range,
- .ignore = ignore,
- .ignore_range = ignore_range,
- .force = force
+ .probe = &ignore,
+ .ignore = &ignore,
+ .force = &ignore,
};
static struct i2c_driver i2c_driver_saa7185;
diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c
index 376a4a439e9..07ba6d3ed08 100644
--- a/drivers/media/video/tda7432.c
+++ b/drivers/media/video/tda7432.c
@@ -74,7 +74,6 @@ static unsigned short normal_i2c[] = {
I2C_TDA7432 >> 1,
I2C_CLIENT_END,
};
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END, I2C_CLIENT_END };
I2C_CLIENT_INSMOD;
/* Structure of address and subaddresses for the tda7432 */
diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c
index b5177c6f54f..c29bdfc3244 100644
--- a/drivers/media/video/tda9840.c
+++ b/drivers/media/video/tda9840.c
@@ -43,7 +43,6 @@ MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
/* addresses to scan, found only at 0x42 (7-Bit) */
static unsigned short normal_i2c[] = { I2C_TDA9840, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
/* magic definition of all other variables and things */
I2C_CLIENT_INSMOD;
diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c
index 4f1114c033a..97b113e070f 100644
--- a/drivers/media/video/tda9875.c
+++ b/drivers/media/video/tda9875.c
@@ -44,7 +44,6 @@ static unsigned short normal_i2c[] = {
I2C_TDA9875 >> 1,
I2C_CLIENT_END
};
-static unsigned short normal_i2c_range[] = {I2C_CLIENT_END};
I2C_CLIENT_INSMOD;
/* This is a superset of the TDA9875 */
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
index debef1910c3..39773633cc3 100644
--- a/drivers/media/video/tda9887.c
+++ b/drivers/media/video/tda9887.c
@@ -33,7 +33,6 @@ static unsigned short normal_i2c[] = {
0x96 >>1,
I2C_CLIENT_END,
};
-static unsigned short normal_i2c_range[] = {I2C_CLIENT_END,I2C_CLIENT_END};
I2C_CLIENT_INSMOD;
/* insmod options */
@@ -54,6 +53,7 @@ struct tda9887 {
unsigned int config;
unsigned int pinnacle_id;
unsigned int using_v4l2;
+ unsigned int radio_mode;
};
struct tvnorm {
@@ -213,12 +213,22 @@ static struct tvnorm tvnorms[] = {
}
};
-static struct tvnorm radio = {
- .name = "radio",
+static struct tvnorm radio_stereo = {
+ .name = "Radio Stereo",
+ .b = ( cFmRadio |
+ cQSS ),
+ .c = ( cDeemphasisOFF |
+ cAudioGain6 ),
+ .e = ( cAudioIF_5_5 |
+ cRadioIF_38_90 ),
+};
+
+static struct tvnorm radio_mono = {
+ .name = "Radio Mono",
.b = ( cFmRadio |
cQSS ),
.c = ( cDeemphasisON |
- cDeemphasis50 ),
+ cDeemphasis50),
.e = ( cAudioIF_5_5 |
cRadioIF_38_90 ),
};
@@ -355,7 +365,10 @@ static int tda9887_set_tvnorm(struct tda9887 *t, char *buf)
int i;
if (t->radio) {
- norm = &radio;
+ if (t->radio_mode == V4L2_TUNER_MODE_MONO)
+ norm = &radio_mono;
+ else
+ norm = &radio_stereo;
} else {
for (i = 0; i < ARRAY_SIZE(tvnorms); i++) {
if (tvnorms[i].std & t->std) {
@@ -546,11 +559,14 @@ static int tda9887_configure(struct tda9887 *t)
memset(buf,0,sizeof(buf));
tda9887_set_tvnorm(t,buf);
+
buf[1] |= cOutputPort1Inactive;
buf[1] |= cOutputPort2Inactive;
+
if (UNSET != t->pinnacle_id) {
tda9887_set_pinnacle(t,buf);
}
+
tda9887_set_config(t,buf);
tda9887_set_insmod(t,buf);
@@ -593,9 +609,12 @@ static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind)
if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL)))
return -ENOMEM;
memset(t,0,sizeof(*t));
+
t->client = client_template;
t->std = 0;
t->pinnacle_id = UNSET;
+ t->radio_mode = V4L2_TUNER_MODE_STEREO;
+
i2c_set_clientdata(&t->client, t);
i2c_attach_client(&t->client);
@@ -734,6 +753,16 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
}
break;
}
+ case VIDIOC_S_TUNER:
+ {
+ struct v4l2_tuner* tuner = arg;
+
+ if (t->radio) {
+ t->radio_mode = tuner->audmode;
+ tda9887_configure (t);
+ }
+ break;
+ }
default:
/* nothing */
break;
@@ -741,7 +770,7 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0;
}
-static int tda9887_suspend(struct device * dev, pm_message_t state, u32 level)
+static int tda9887_suspend(struct device * dev, u32 state, u32 level)
{
dprintk("tda9887: suspend\n");
return 0;
diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c
index 3ec39550bf4..b44db8a7b94 100644
--- a/drivers/media/video/tea6415c.c
+++ b/drivers/media/video/tea6415c.c
@@ -43,7 +43,6 @@ MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
/* addresses to scan, found only at 0x03 and/or 0x43 (7-bit) */
static unsigned short normal_i2c[] = { I2C_TEA6415C_1, I2C_TEA6415C_2, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
/* magic definition of all other variables and things */
I2C_CLIENT_INSMOD;
diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c
index bd10710fd90..48d4db7d507 100644
--- a/drivers/media/video/tea6420.c
+++ b/drivers/media/video/tea6420.c
@@ -40,7 +40,6 @@ MODULE_PARM_DESC(debug, "Turn on/off device debugging (default:off).");
/* addresses to scan, found only at 0x4c and/or 0x4d (7-Bit) */
static unsigned short normal_i2c[] = { I2C_TEA6420_1, I2C_TEA6420_2, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
/* magic definition of all other variables and things */
I2C_CLIENT_INSMOD;
diff --git a/drivers/media/video/tuner-3036.c b/drivers/media/video/tuner-3036.c
index 6b20aa902a8..51748c6578d 100644
--- a/drivers/media/video/tuner-3036.c
+++ b/drivers/media/video/tuner-3036.c
@@ -34,19 +34,14 @@ static int this_adap;
static struct i2c_client client_template;
/* Addresses to scan */
-static unsigned short normal_i2c[] = {I2C_CLIENT_END};
-static unsigned short normal_i2c_range[] = {0x60, 0x61, I2C_CLIENT_END};
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short normal_i2c[] = { 0x60, 0x61, I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
static struct i2c_client_address_data addr_data = {
- normal_i2c, normal_i2c_range,
- probe, probe_range,
- ignore, ignore_range,
- force
+ .normal_i2c = normal_i2c,
+ .probe = &ignore,
+ .ignore = &ignore,
+ .force = &ignore,
};
/* ---------------------------------------------------------------------- */
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index 6212388edb7..eaabfc85870 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -1,5 +1,5 @@
/*
- * $Id: tuner-core.c,v 1.5 2005/02/15 15:59:35 kraxel Exp $
+ * $Id: tuner-core.c,v 1.15 2005/06/12 01:36:14 mchehab Exp $
*
* i2c tv tuner chip device driver
* core core, i.e. kernel interfaces, registering and so on
@@ -23,15 +23,18 @@
#include <media/tuner.h>
#include <media/audiochip.h>
+/*
+ * comment line bellow to return to old behavor, where only one I2C device is supported
+ */
+#define CONFIG_TUNER_MULTI_I2C /**/
+
#define UNSET (-1U)
/* standard i2c insmod options */
static unsigned short normal_i2c[] = {
0x4b, /* tda8290 */
- I2C_CLIENT_END
-};
-static unsigned short normal_i2c_range[] = {
- 0x60, 0x6f,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
I2C_CLIENT_END
};
I2C_CLIENT_INSMOD;
@@ -55,13 +58,16 @@ MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
MODULE_LICENSE("GPL");
static int this_adap;
+#ifdef CONFIG_TUNER_MULTI_I2C
+static unsigned short first_tuner, tv_tuner, radio_tuner;
+#endif
static struct i2c_driver driver;
static struct i2c_client client_template;
/* ---------------------------------------------------------------------- */
-// Set tuner frequency, freq in Units of 62.5kHz = 1/16MHz
+/* Set tuner frequency, freq in Units of 62.5kHz = 1/16MHz */
static void set_tv_freq(struct i2c_client *c, unsigned int freq)
{
struct tuner *t = i2c_get_clientdata(c);
@@ -75,14 +81,26 @@ static void set_tv_freq(struct i2c_client *c, unsigned int freq)
return;
}
if (freq < tv_range[0]*16 || freq > tv_range[1]*16) {
- /* FIXME: better do that chip-specific, but
- right now we don't have that in the config
- struct and this way is still better than no
- check at all */
- tuner_info("TV freq (%d.%02d) out of range (%d-%d)\n",
- freq/16,freq%16*100/16,tv_range[0],tv_range[1]);
- return;
+
+ if (freq >= tv_range[0]*16364 && freq <= tv_range[1]*16384) {
+ /* V4L2_TUNER_CAP_LOW frequency */
+
+ tuner_dbg("V4L2_TUNER_CAP_LOW freq selected for TV. Tuners yet doesn't support converting it to valid freq.\n");
+
+ t->tv_freq(c,freq>>10);
+
+ return;
+ } else {
+ /* FIXME: better do that chip-specific, but
+ right now we don't have that in the config
+ struct and this way is still better than no
+ check at all */
+ tuner_info("TV freq (%d.%02d) out of range (%d-%d)\n",
+ freq/16,freq%16*100/16,tv_range[0],tv_range[1]);
+ return;
+ }
}
+ tuner_dbg("62.5 Khz freq step selected for TV.\n");
t->tv_freq(c,freq);
}
@@ -99,11 +117,29 @@ static void set_radio_freq(struct i2c_client *c, unsigned int freq)
return;
}
if (freq < radio_range[0]*16 || freq > radio_range[1]*16) {
- tuner_info("radio freq (%d.%02d) out of range (%d-%d)\n",
+ if (freq >= tv_range[0]*16364 && freq <= tv_range[1]*16384) {
+ /* V4L2_TUNER_CAP_LOW frequency */
+ if (t->type == TUNER_TEA5767) {
+ tuner_info("radio freq step 62.5Hz (%d.%06d)\n",(freq>>14),freq%(1<<14)*10000);
+ t->radio_freq(c,freq>>10);
+ return;
+ }
+
+ tuner_dbg("V4L2_TUNER_CAP_LOW freq selected for Radio. Tuners yet doesn't support converting it to valid freq.\n");
+
+ tuner_info("radio freq (%d.%06d)\n",(freq>>14),freq%(1<<14)*10000);
+
+ t->radio_freq(c,freq>>10);
+ return;
+
+ } else {
+ tuner_info("radio freq (%d.%02d) out of range (%d-%d)\n",
freq/16,freq%16*100/16,
- radio_range[0],radio_range[1]);
- return;
+ radio_range[0],radio_range[1]);
+ return;
+ }
}
+ tuner_dbg("62.5 Khz freq step selected for Radio.\n");
t->radio_freq(c,freq);
}
@@ -131,8 +167,9 @@ static void set_type(struct i2c_client *c, unsigned int type)
{
struct tuner *t = i2c_get_clientdata(c);
+ tuner_dbg ("I2C addr 0x%02x with type %d\n",c->addr<<1,type);
/* sanity check */
- if (type == UNSET || type == TUNER_ABSENT)
+ if (type == UNSET || type == TUNER_ABSENT)
return;
if (type >= tuner_count)
return;
@@ -147,6 +184,7 @@ static void set_type(struct i2c_client *c, unsigned int type)
return;
t->initialized = 1;
+
t->type = type;
switch (t->type) {
case TUNER_MT2032:
@@ -161,6 +199,53 @@ static void set_type(struct i2c_client *c, unsigned int type)
}
}
+#ifdef CONFIG_TUNER_MULTI_I2C
+#define CHECK_ADDR(tp,cmd,tun) if (client->addr!=tp) { \
+ return 0; } else \
+ tuner_info ("Cmd %s accepted to "tun"\n",cmd);
+#define CHECK_MODE(cmd) if (t->mode == V4L2_TUNER_RADIO) { \
+ CHECK_ADDR(radio_tuner,cmd,"radio") } else \
+ { CHECK_ADDR(tv_tuner,cmd,"TV"); }
+#else
+#define CHECK_ADDR(tp,cmd,tun) tuner_info ("Cmd %s accepted to "tun"\n",cmd);
+#define CHECK_MODE(cmd) tuner_info ("Cmd %s accepted\n",cmd);
+#endif
+
+#ifdef CONFIG_TUNER_MULTI_I2C
+
+static void set_addr(struct i2c_client *c, struct tuner_addr *tun_addr)
+{
+ /* ADDR_UNSET defaults to first available tuner */
+ if ( tun_addr->addr == ADDR_UNSET ) {
+ if (first_tuner != c->addr)
+ return;
+ switch (tun_addr->v4l2_tuner) {
+ case V4L2_TUNER_RADIO:
+ radio_tuner=c->addr;
+ break;
+ default:
+ tv_tuner=c->addr;
+ break;
+ }
+ } else {
+ /* Sets tuner to its configured value */
+ switch (tun_addr->v4l2_tuner) {
+ case V4L2_TUNER_RADIO:
+ radio_tuner=tun_addr->addr;
+ if ( tun_addr->addr == c->addr ) set_type(c,tun_addr->type);
+ return;
+ default:
+ tv_tuner=tun_addr->addr;
+ if ( tun_addr->addr == c->addr ) set_type(c,tun_addr->type);
+ return;
+ }
+ }
+ set_type(c,tun_addr->type);
+}
+#else
+#define set_addr(c,tun_addr) set_type(c,(tun_addr)->type)
+#endif
+
static char pal[] = "-";
module_param_string(pal, pal, sizeof(pal), 0644);
@@ -199,8 +284,17 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
{
struct tuner *t;
+#ifndef CONFIG_TUNER_MULTI_I2C
if (this_adap > 0)
return -1;
+#else
+ /* by default, first I2C card is both tv and radio tuner */
+ if (this_adap == 0) {
+ first_tuner = addr;
+ tv_tuner = addr;
+ radio_tuner = addr;
+ }
+#endif
this_adap++;
client_template.adapter = adap;
@@ -213,11 +307,12 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
memcpy(&t->i2c,&client_template,sizeof(struct i2c_client));
i2c_set_clientdata(&t->i2c, t);
t->type = UNSET;
- t->radio_if2 = 10700*1000; // 10.7MHz - FM radio
+ t->radio_if2 = 10700*1000; /* 10.7MHz - FM radio */
i2c_attach_client(&t->i2c);
tuner_info("chip found @ 0x%x (%s)\n",
addr << 1, adap->name);
+
set_type(&t->i2c, t->type);
return 0;
}
@@ -225,12 +320,17 @@ static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
static int tuner_probe(struct i2c_adapter *adap)
{
if (0 != addr) {
- normal_i2c[0] = addr;
- normal_i2c_range[0] = addr;
- normal_i2c_range[1] = addr;
+ normal_i2c[0] = addr;
+ normal_i2c[1] = I2C_CLIENT_END;
}
this_adap = 0;
+#ifdef CONFIG_TUNER_MULTI_I2C
+ first_tuner = 0;
+ tv_tuner = 0;
+ radio_tuner = 0;
+#endif
+
if (adap->class & I2C_CLASS_TV_ANALOG)
return i2c_probe(adap, &addr_data, tuner_attach);
return 0;
@@ -239,8 +339,14 @@ static int tuner_probe(struct i2c_adapter *adap)
static int tuner_detach(struct i2c_client *client)
{
struct tuner *t = i2c_get_clientdata(client);
+ int err;
+
+ err=i2c_detach_client(&t->i2c);
+ if (err) {
+ tuner_warn ("Client deregistration failed, client not detached.\n");
+ return err;
+ }
- i2c_detach_client(&t->i2c);
kfree(t);
return 0;
}
@@ -259,18 +365,23 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
unsigned int *iarg = (int*)arg;
switch (cmd) {
-
/* --- configuration --- */
case TUNER_SET_TYPE:
set_type(client,*iarg);
break;
+ case TUNER_SET_TYPE_ADDR:
+ set_addr(client,(struct tuner_addr *)arg);
+ break;
case AUDC_SET_RADIO:
+ t->mode = V4L2_TUNER_RADIO;
+ CHECK_ADDR(tv_tuner,"AUDC_SET_RADIO","TV");
+
if (V4L2_TUNER_RADIO != t->mode) {
set_tv_freq(client,400 * 16);
- t->mode = V4L2_TUNER_RADIO;
}
break;
case AUDC_CONFIG_PINNACLE:
+ CHECK_ADDR(tv_tuner,"AUDC_CONFIG_PINNACLE","TV");
switch (*iarg) {
case 2:
tuner_dbg("pinnacle pal\n");
@@ -300,6 +411,8 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
CHECK_V4L2;
t->mode = V4L2_TUNER_ANALOG_TV;
+ CHECK_ADDR(tv_tuner,"VIDIOCSCHAN","TV");
+
if (vc->norm < ARRAY_SIZE(map))
t->std = map[vc->norm];
tuner_fixup_std(t);
@@ -311,6 +424,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
unsigned long *v = arg;
+ CHECK_MODE("VIDIOCSFREQ");
CHECK_V4L2;
set_freq(client,*v);
return 0;
@@ -319,15 +433,27 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct video_tuner *vt = arg;
+ CHECK_ADDR(radio_tuner,"VIDIOCGTUNER","radio");
CHECK_V4L2;
- if (V4L2_TUNER_RADIO == t->mode && t->has_signal)
- vt->signal = t->has_signal(client);
+ if (V4L2_TUNER_RADIO == t->mode) {
+ if (t->has_signal)
+ vt->signal = t->has_signal(client);
+ if (t->is_stereo) {
+ if (t->is_stereo(client))
+ vt-> flags |= VIDEO_TUNER_STEREO_ON;
+ else
+ vt-> flags &= 0xffff ^ VIDEO_TUNER_STEREO_ON;
+ }
+ vt->flags |= V4L2_TUNER_CAP_LOW; /* Allow freqs at 62.5 Hz */
+ }
+
return 0;
}
case VIDIOCGAUDIO:
{
struct video_audio *va = arg;
+ CHECK_ADDR(radio_tuner,"VIDIOCGAUDIO","radio");
CHECK_V4L2;
if (V4L2_TUNER_RADIO == t->mode && t->is_stereo)
va->mode = t->is_stereo(client)
@@ -342,6 +468,8 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
SWITCH_V4L2;
t->mode = V4L2_TUNER_ANALOG_TV;
+ CHECK_ADDR(tv_tuner,"VIDIOC_S_STD","TV");
+
t->std = *id;
tuner_fixup_std(t);
if (t->freq)
@@ -352,6 +480,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct v4l2_frequency *f = arg;
+ CHECK_MODE("VIDIOC_S_FREQUENCY");
SWITCH_V4L2;
if (V4L2_TUNER_RADIO == f->type &&
V4L2_TUNER_RADIO != t->mode)
@@ -364,6 +493,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct v4l2_frequency *f = arg;
+ CHECK_MODE("VIDIOC_G_FREQUENCY");
SWITCH_V4L2;
f->type = t->mode;
f->frequency = t->freq;
@@ -373,14 +503,29 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
{
struct v4l2_tuner *tuner = arg;
+ CHECK_MODE("VIDIOC_G_TUNER");
SWITCH_V4L2;
- if (V4L2_TUNER_RADIO == t->mode && t->has_signal)
- tuner->signal = t->has_signal(client);
+ if (V4L2_TUNER_RADIO == t->mode) {
+ if (t->has_signal)
+ tuner -> signal = t->has_signal(client);
+ if (t->is_stereo) {
+ if (t->is_stereo(client)) {
+ tuner -> capability |= V4L2_TUNER_CAP_STEREO;
+ tuner -> rxsubchans |= V4L2_TUNER_SUB_STEREO;
+ } else {
+ tuner -> rxsubchans &= 0xffff ^ V4L2_TUNER_SUB_STEREO;
+ }
+ }
+ }
+ /* Wow to deal with V4L2_TUNER_CAP_LOW ? For now, it accepts from low at 62.5KHz step to high at 62.5 Hz */
tuner->rangelow = tv_range[0] * 16;
- tuner->rangehigh = tv_range[1] * 16;
+// tuner->rangehigh = tv_range[1] * 16;
+// tuner->rangelow = tv_range[0] * 16384;
+ tuner->rangehigh = tv_range[1] * 16384;
break;
}
default:
+ tuner_dbg ("Unimplemented IOCTL 0x%08x called to tuner.\n", cmd);
/* nothing */
break;
}
@@ -388,7 +533,7 @@ tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
return 0;
}
-static int tuner_suspend(struct device * dev, pm_message_t state, u32 level)
+static int tuner_suspend(struct device * dev, u32 state, u32 level)
{
struct i2c_client *c = container_of(dev, struct i2c_client, dev);
struct tuner *t = i2c_get_clientdata(c);
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c
index 48c6ceff1dc..539f3055731 100644
--- a/drivers/media/video/tuner-simple.c
+++ b/drivers/media/video/tuner-simple.c
@@ -1,5 +1,5 @@
/*
- * $Id: tuner-simple.c,v 1.10 2005/03/08 08:38:00 kraxel Exp $
+ * $Id: tuner-simple.c,v 1.21 2005/06/10 19:53:26 nsh Exp $
*
* i2c tv tuner chip device driver
* controls all those simple 4-control-bytes style tuners.
@@ -212,7 +212,25 @@ static struct tunertype tuners[] = {
{ "Philips FQ1236A MK4", Philips, NTSC,
16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 },
+ /* Should work for TVF8531MF, TVF8831MF, TVF8731MF */
+ { "Ymec TVision TVF-8531MF", Philips, NTSC,
+ 16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732},
+ { "Ymec TVision TVF-5533MF", Philips, NTSC,
+ 16*160.00,16*454.00,0x01,0x02,0x04,0x8e,732},
+
+ { "Thomson DDT 7611 (ATSC/NTSC)", THOMSON, ATSC,
+ 16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732},
+ { "Tena TNF9533-D/IF", LGINNOTEK, PAL,
+ 16*160.25, 16*464.25, 0x01,0x02,0x08,0x8e,623},
+
+ /*
+ * This entry is for TEA5767 FM radio only chip used on several boards
+ * w/TV tuner
+ */
+ { TEA5767_TUNER_NAME, Philips, RADIO,
+ -1, -1, 0, 0, 0, TEA5767_LOW_LO_32768,0},
};
+
unsigned const int tuner_count = ARRAY_SIZE(tuners);
/* ---------------------------------------------------------------------- */
@@ -223,6 +241,7 @@ static int tuner_getstatus(struct i2c_client *c)
if (1 != i2c_master_recv(c,&byte,1))
return 0;
+
return byte;
}
@@ -231,17 +250,33 @@ static int tuner_getstatus(struct i2c_client *c)
#define TUNER_MODE 0x38
#define TUNER_AFC 0x07
-#define TUNER_STEREO 0x10 /* radio mode */
-#define TUNER_SIGNAL 0x07 /* radio mode */
+#define TUNER_STEREO 0x10 /* radio mode */
+#define TUNER_STEREO_MK3 0x04 /* radio mode */
+#define TUNER_SIGNAL 0x07 /* radio mode */
static int tuner_signal(struct i2c_client *c)
{
- return (tuner_getstatus(c) & TUNER_SIGNAL)<<13;
+ return (tuner_getstatus(c) & TUNER_SIGNAL) << 13;
}
static int tuner_stereo(struct i2c_client *c)
{
- return (tuner_getstatus (c) & TUNER_STEREO);
+ int stereo, status;
+ struct tuner *t = i2c_get_clientdata(c);
+
+ status = tuner_getstatus (c);
+
+ switch (t->type) {
+ case TUNER_PHILIPS_FM1216ME_MK3:
+ case TUNER_PHILIPS_FM1236_MK3:
+ case TUNER_PHILIPS_FM1256_IH3:
+ stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3);
+ break;
+ default:
+ stereo = status & TUNER_STEREO;
+ }
+
+ return stereo;
}
#if 0 /* unused */
@@ -424,6 +459,14 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
buffer[2] = tun->config;
switch (t->type) {
+ case TUNER_TENA_9533_DI:
+ case TUNER_YMEC_TVF_5533MF:
+
+ /*These values are empirically determinated */
+ div = (freq*122)/16 - 20;
+ buffer[2] = 0x88; /* could be also 0x80 */
+ buffer[3] = 0x19; /* could be also 0x10, 0x18, 0x99 */
+ break;
case TUNER_PHILIPS_FM1216ME_MK3:
case TUNER_PHILIPS_FM1236_MK3:
buffer[3] = 0x19;
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index 80dc34f18c2..9a493bea76d 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -148,7 +148,6 @@ static unsigned short normal_i2c[] = {
I2C_TDA9874 >> 1,
I2C_PIC16C54 >> 1,
I2C_CLIENT_END };
-static unsigned short normal_i2c_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
I2C_CLIENT_INSMOD;
static struct i2c_driver driver;
@@ -286,7 +285,6 @@ static int chip_thread(void *data)
schedule();
}
remove_wait_queue(&chip->wq, &wait);
- try_to_freeze(PF_FREEZE);
if (chip->done || signal_pending(current))
break;
dprintk("%s: thread wakeup\n", i2c_clientname(&chip->c));
@@ -1238,17 +1236,17 @@ static int ta8874z_checkit(struct CHIPSTATE *chip)
/* audio chip descriptions - struct CHIPDESC */
/* insmod options to enable/disable individual audio chips */
-int tda8425 = 1;
-int tda9840 = 1;
-int tda9850 = 1;
-int tda9855 = 1;
-int tda9873 = 1;
-int tda9874a = 1;
-int tea6300 = 0; // address clash with msp34xx
-int tea6320 = 0; // address clash with msp34xx
-int tea6420 = 1;
-int pic16c54 = 1;
-int ta8874z = 0; // address clash with tda9840
+static int tda8425 = 1;
+static int tda9840 = 1;
+static int tda9850 = 1;
+static int tda9855 = 1;
+static int tda9873 = 1;
+static int tda9874a = 1;
+static int tea6300 = 0; // address clash with msp34xx
+static int tea6320 = 0; // address clash with msp34xx
+static int tea6420 = 1;
+static int pic16c54 = 1;
+static int ta8874z = 0; // address clash with tda9840
module_param(tda8425, int, 0444);
module_param(tda9840, int, 0444);
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index e1443a0937e..0f03c25489f 100644
--- a/drivers/media/video/tveeprom.c
+++ b/drivers/media/video/tveeprom.c
@@ -75,7 +75,7 @@ hauppauge_tuner_fmt[] =
{ 0x00000007, "PAL(B/G)" },
{ 0x00001000, "NTSC(M)" },
{ 0x00000010, "PAL(I)" },
- { 0x00400000, "SECAM(L/L�)" },
+ { 0x00400000, "SECAM(L/L´)" },
{ 0x00000e00, "PAL(D/K)" },
{ 0x03000000, "ATSC Digital" },
};
@@ -482,7 +482,6 @@ static unsigned short normal_i2c[] = {
0xa0 >> 1,
I2C_CLIENT_END,
};
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
I2C_CLIENT_INSMOD;
struct i2c_driver i2c_driver_tveeprom;
diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c
index eafd7061b31..51b99cdbf29 100644
--- a/drivers/media/video/tvmixer.c
+++ b/drivers/media/video/tvmixer.c
@@ -1,3 +1,7 @@
+/*
+ * $Id: tvmixer.c,v 1.8 2005/06/12 04:19:19 mchehab Exp $
+ */
+
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c
index b0d4bcb027d..70ecbdb8027 100644
--- a/drivers/media/video/v4l1-compat.c
+++ b/drivers/media/video/v4l1-compat.c
@@ -1,4 +1,6 @@
/*
+ * $Id: v4l1-compat.c,v 1.9 2005/06/12 04:19:19 mchehab Exp $
+ *
* Video for Linux Two
* Backward Compatibility Layer
*
@@ -15,14 +17,11 @@
*
*/
-#ifndef __KERNEL__
-#define __KERNEL__
-#endif
-
#include <linux/config.h>
#include <linux/init.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/sched.h>
@@ -787,12 +786,15 @@ v4l_compat_translate_ioctl(struct inode *inode,
!(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
aud->step = qctrl2.step;
aud->mode = 0;
+
+ memset(&tun2,0,sizeof(tun2));
err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
if (err < 0) {
dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n",err);
err = 0;
break;
}
+
if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2)
aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
diff --git a/drivers/media/video/video-buf-dvb.c b/drivers/media/video/video-buf-dvb.c
index 31cc4ed9b74..15f5bb48696 100644
--- a/drivers/media/video/video-buf-dvb.c
+++ b/drivers/media/video/video-buf-dvb.c
@@ -62,8 +62,7 @@ static int videobuf_dvb_thread(void *data)
break;
if (kthread_should_stop())
break;
- if (current->flags & PF_FREEZE)
- refrigerator(PF_FREEZE);
+ try_to_freeze();
/* feed buffer data to demux */
if (buf->state == STATE_DONE)
@@ -149,10 +148,10 @@ int videobuf_dvb_register(struct videobuf_dvb *dvb,
dvb->name, result);
goto fail_adapter;
}
- dvb->adapter->priv = adapter_priv;
+ dvb->adapter.priv = adapter_priv;
/* register frontend */
- result = dvb_register_frontend(dvb->adapter, dvb->frontend);
+ result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
if (result < 0) {
printk(KERN_WARNING "%s: dvb_register_frontend failed (errno = %d)\n",
dvb->name, result);
@@ -178,7 +177,7 @@ int videobuf_dvb_register(struct videobuf_dvb *dvb,
dvb->dmxdev.filternum = 256;
dvb->dmxdev.demux = &dvb->demux.dmx;
dvb->dmxdev.capabilities = 0;
- result = dvb_dmxdev_init(&dvb->dmxdev, dvb->adapter);
+ result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
if (result < 0) {
printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n",
dvb->name, result);
@@ -209,7 +208,7 @@ int videobuf_dvb_register(struct videobuf_dvb *dvb,
}
/* register network adapter */
- dvb_net_init(dvb->adapter, &dvb->net, &dvb->demux.dmx);
+ dvb_net_init(&dvb->adapter, &dvb->net, &dvb->demux.dmx);
return 0;
fail_fe_conn:
@@ -223,7 +222,7 @@ fail_dmxdev:
fail_dmx:
dvb_unregister_frontend(dvb->frontend);
fail_frontend:
- dvb_unregister_adapter(dvb->adapter);
+ dvb_unregister_adapter(&dvb->adapter);
fail_adapter:
return result;
}
@@ -236,7 +235,7 @@ void videobuf_dvb_unregister(struct videobuf_dvb *dvb)
dvb_dmxdev_release(&dvb->dmxdev);
dvb_dmx_release(&dvb->demux);
dvb_unregister_frontend(dvb->frontend);
- dvb_unregister_adapter(dvb->adapter);
+ dvb_unregister_adapter(&dvb->adapter);
}
EXPORT_SYMBOL(videobuf_dvb_register);
diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c
index 0fd6c9a7091..5dbd9f6bf35 100644
--- a/drivers/media/video/vpx3220.c
+++ b/drivers/media/video/vpx3220.c
@@ -569,22 +569,14 @@ static unsigned short normal_i2c[] =
{ I2C_VPX3220 >> 1, (I2C_VPX3220 >> 1) + 4,
I2C_CLIENT_END
};
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_i2c,
- .normal_i2c_range = normal_i2c_range,
- .probe = probe,
- .probe_range = probe_range,
- .ignore = ignore,
- .ignore_range = ignore_range,
- .force = force
+ .probe = &ignore,
+ .ignore = &ignore,
+ .force = &ignore,
};
static struct i2c_driver vpx3220_i2c_driver;
diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig
index 452418b24d7..33f209a39cb 100644
--- a/drivers/message/fusion/Kconfig
+++ b/drivers/message/fusion/Kconfig
@@ -2,34 +2,54 @@
menu "Fusion MPT device support"
config FUSION
- tristate "Fusion MPT (base + ScsiHost) drivers"
+ bool
+ default n
+
+config FUSION_SPI
+ tristate "Fusion MPT ScsiHost drivers for SPI"
+ depends on PCI && SCSI
+ select FUSION
+ ---help---
+ SCSI HOST support for a parallel SCSI host adapters.
+
+ List of supported controllers:
+
+ LSI53C1020
+ LSI53C1020A
+ LSI53C1030
+ LSI53C1035
+
+config FUSION_FC
+ tristate "Fusion MPT ScsiHost drivers for FC"
depends on PCI && SCSI
+ select FUSION
---help---
- LSI Logic Fusion(TM) Message Passing Technology (MPT) device support
- provides high performance SCSI host initiator, and LAN [1] interface
- services to a host system. The Fusion architecture is capable of
- duplexing these protocols on high-speed Fibre Channel
- (up to 2 GHz x 2 ports = 4 GHz) and parallel SCSI (up to Ultra-320)
- physical medium.
+ SCSI HOST support for a Fiber Channel host adapters.
- [1] LAN is not supported on parallel SCSI medium.
+ List of supported controllers:
+
+ LSIFC909
+ LSIFC919
+ LSIFC919X
+ LSIFC929
+ LSIFC929X
+ LSIFC929XL
config FUSION_MAX_SGE
- int "Maximum number of scatter gather entries"
+ int "Maximum number of scatter gather entries (16 - 128)"
depends on FUSION
- default "40"
+ default "128"
+ range 16 128
help
This option allows you to specify the maximum number of scatter-
- gather entries per I/O. The driver defaults to 40, a reasonable number
- for most systems. However, the user may increase this up to 128.
- Increasing this parameter will require significantly more memory
- on a per controller instance. Increasing the parameter is not
- necessary (or recommended) unless the user will be running
- large I/O's via the raw interface.
+ gather entries per I/O. The driver default is 128, which matches
+ SCSI_MAX_PHYS_SEGMENTS. However, it may decreased down to 16.
+ Decreasing this parameter will reduce memory requirements
+ on a per controller instance.
config FUSION_CTL
tristate "Fusion MPT misc device (ioctl) driver"
- depends on FUSION
+ depends on FUSION_SPI || FUSION_FC
---help---
The Fusion MPT misc device driver provides specialized control
of MPT adapters via system ioctl calls. Use of ioctl calls to
@@ -48,7 +68,7 @@ config FUSION_CTL
config FUSION_LAN
tristate "Fusion MPT LAN driver"
- depends on FUSION && NET_FC
+ depends on FUSION_FC && NET_FC
---help---
This module supports LAN IP traffic over Fibre Channel port(s)
on Fusion MPT compatible hardware (LSIFC9xx chips).
diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile
index f6fdcaaefc8..1d2f9db813c 100644
--- a/drivers/message/fusion/Makefile
+++ b/drivers/message/fusion/Makefile
@@ -1,52 +1,38 @@
-#
-# Makefile for the LSI Logic Fusion MPT (Message Passing Technology) drivers.
-#
-# Note! If you want to turn on various debug defines for an extended period of
-# time but don't want them lingering around in the Makefile when you pass it on
-# to someone else, use the MPT_CFLAGS env variable (thanks Steve). -nromer
-
-#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-{ LSI_LOGIC
-
-# Architecture-specific...
-# # intel
-#EXTRA_CFLAGS += -g
-# # sparc64
-#EXTRA_CFLAGS += -gstabs+
-
-EXTRA_CFLAGS += ${MPT_CFLAGS}
-
# Fusion MPT drivers; recognized debug defines...
# MPT general:
-#EXTRA_CFLAGS += -DMPT_DEBUG_SCSI
#EXTRA_CFLAGS += -DMPT_DEBUG
#EXTRA_CFLAGS += -DMPT_DEBUG_MSG_FRAME
#EXTRA_CFLAGS += -DMPT_DEBUG_SG
+#EXTRA_CFLAGS += -DMPT_DEBUG_EVENTS
+#EXTRA_CFLAGS += -DMPT_DEBUG_INIT
+#EXTRA_CFLAGS += -DMPT_DEBUG_EXIT
+#EXTRA_CFLAGS += -DMPT_DEBUG_FAIL
+
#
# driver/module specifics...
#
# For mptbase:
#CFLAGS_mptbase.o += -DMPT_DEBUG_HANDSHAKE
+#CFLAGS_mptbase.o += -DMPT_DEBUG_CONFIG
+#CFLAGS_mptbase.o += -DMPT_DEBUG_DL
#CFLAGS_mptbase.o += -DMPT_DEBUG_IRQ
+#CFLAGS_mptbase.o += -DMPT_DEBUG_RESET
#
# For mptscsih:
-#CFLAGS_mptscsih.o += -DMPT_DEBUG_SCANDV
-#CFLAGS_mptscsih.o += -DMPT_DEBUG_RESET
-#CFLAGS_mptscsih.o += -DMPT_DEBUG_NEH
+#CFLAGS_mptscsih.o += -DMPT_DEBUG_DV
+#CFLAGS_mptscsih.o += -DMPT_DEBUG_NEGO
+#CFLAGS_mptscsih.o += -DMPT_DEBUG_TM
+#CFLAGS_mptscsih.o += -DMPT_DEBUG_SCSI
+#CFLAGS_mptscsih.o += -DMPT_DEBUG_REPLY
#
# For mptctl:
#CFLAGS_mptctl.o += -DMPT_DEBUG_IOCTL
#
-# For mptlan:
-#CFLAGS_mptlan.o += -DMPT_LAN_IO_DEBUG
-#
-# For isense:
-
-# EXP...
-##mptscsih-objs := scsihost.o scsiherr.o
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC
-obj-$(CONFIG_FUSION) += mptbase.o mptscsih.o
+obj-$(CONFIG_FUSION_SPI) += mptbase.o mptscsih.o mptspi.o
+obj-$(CONFIG_FUSION_FC) += mptbase.o mptscsih.o mptfc.o
obj-$(CONFIG_FUSION_CTL) += mptctl.o
obj-$(CONFIG_FUSION_LAN) += mptlan.o
diff --git a/drivers/message/fusion/lsi/mpi.h b/drivers/message/fusion/lsi/mpi.h
index 9dbb061265f..9f98334e507 100644
--- a/drivers/message/fusion/lsi/mpi.h
+++ b/drivers/message/fusion/lsi/mpi.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2000-2003 LSI Logic Corporation.
+ * Copyright (c) 2000-2005 LSI Logic Corporation.
*
*
* Name: mpi.h
* Title: MPI Message independent structures and definitions
* Creation Date: July 27, 2000
*
- * mpi.h Version: 01.05.xx
+ * mpi.h Version: 01.05.07
*
* Version History
* ---------------
@@ -52,6 +52,25 @@
* obsoleted define MPI_IOCSTATUS_TARGET_INVALID_IOCINDEX.
* 04-01-03 01.02.09 New IOCStatus code: MPI_IOCSTATUS_FC_EXCHANGE_CANCELED
* 06-26-03 01.02.10 Bumped MPI_HEADER_VERSION_UNIT value.
+ * 01-16-04 01.02.11 Added define for MPI_IOCLOGINFO_TYPE_SHIFT.
+ * 04-29-04 01.02.12 Added function codes for MPI_FUNCTION_DIAG_BUFFER_POST
+ * and MPI_FUNCTION_DIAG_RELEASE.
+ * Added MPI_IOCSTATUS_DIAGNOSTIC_RELEASED define.
+ * Bumped MPI_HEADER_VERSION_UNIT value.
+ * 05-11-04 01.03.01 Bumped MPI_VERSION_MINOR for MPI v1.3.
+ * Added codes for Inband.
+ * 08-19-04 01.05.01 Added defines for Host Buffer Access Control doorbell.
+ * Added define for offset of High Priority Request Queue.
+ * Added new function codes and new IOCStatus codes.
+ * Added a IOCLogInfo type of SAS.
+ * 12-07-04 01.05.02 Bumped MPI_HEADER_VERSION_UNIT.
+ * 12-09-04 01.05.03 Bumped MPI_HEADER_VERSION_UNIT.
+ * 01-15-05 01.05.04 Bumped MPI_HEADER_VERSION_UNIT.
+ * 02-09-05 01.05.05 Bumped MPI_HEADER_VERSION_UNIT.
+ * 02-22-05 01.05.06 Bumped MPI_HEADER_VERSION_UNIT.
+ * 03-11-05 01.05.07 Removed function codes for SCSI IO 32 and
+ * TargetAssistExtended requests.
+ * Removed EEDP IOCStatus codes.
* --------------------------------------------------------------------------
*/
@@ -82,7 +101,7 @@
/* Note: The major versions of 0xe0 through 0xff are reserved */
/* versioning for this MPI header set */
-#define MPI_HEADER_VERSION_UNIT (0x00)
+#define MPI_HEADER_VERSION_UNIT (0x09)
#define MPI_HEADER_VERSION_DEV (0x00)
#define MPI_HEADER_VERSION_UNIT_MASK (0xFF00)
#define MPI_HEADER_VERSION_UNIT_SHIFT (8)
@@ -122,7 +141,11 @@
*
*****************************************************************************/
-/* S y s t e m D o o r b e l l */
+/*
+ * Defines for working with the System Doorbell register.
+ * Values for doorbell function codes are included in the section that defines
+ * all the function codes (further on in this file).
+ */
#define MPI_DOORBELL_OFFSET (0x00000000)
#define MPI_DOORBELL_ACTIVE (0x08000000) /* DoorbellUsed */
#define MPI_DOORBELL_USED (MPI_DOORBELL_ACTIVE)
@@ -134,6 +157,13 @@
#define MPI_DOORBELL_ADD_DWORDS_MASK (0x00FF0000)
#define MPI_DOORBELL_ADD_DWORDS_SHIFT (16)
#define MPI_DOORBELL_DATA_MASK (0x0000FFFF)
+#define MPI_DOORBELL_FUNCTION_SPECIFIC_MASK (0x0000FFFF)
+
+/* values for Host Buffer Access Control doorbell function */
+#define MPI_DB_HPBAC_VALUE_MASK (0x0000F000)
+#define MPI_DB_HPBAC_ENABLE_ACCESS (0x01)
+#define MPI_DB_HPBAC_DISABLE_ACCESS (0x02)
+#define MPI_DB_HPBAC_FREE_BUFFER (0x03)
#define MPI_WRITE_SEQUENCE_OFFSET (0x00000004)
@@ -257,16 +287,18 @@
#define MPI_FUNCTION_SMP_PASSTHROUGH (0x1A)
#define MPI_FUNCTION_SAS_IO_UNIT_CONTROL (0x1B)
+#define MPI_FUNCTION_SATA_PASSTHROUGH (0x1C)
-#define MPI_DIAG_BUFFER_POST (0x1D)
-#define MPI_DIAG_RELEASE (0x1E)
-
-#define MPI_FUNCTION_SCSI_IO_32 (0x1F)
+#define MPI_FUNCTION_DIAG_BUFFER_POST (0x1D)
+#define MPI_FUNCTION_DIAG_RELEASE (0x1E)
#define MPI_FUNCTION_LAN_SEND (0x20)
#define MPI_FUNCTION_LAN_RECEIVE (0x21)
#define MPI_FUNCTION_LAN_RESET (0x22)
+#define MPI_FUNCTION_TARGET_CMD_BUF_BASE_POST (0x24)
+#define MPI_FUNCTION_TARGET_CMD_BUF_LIST_POST (0x25)
+
#define MPI_FUNCTION_INBAND_BUFFER_POST (0x28)
#define MPI_FUNCTION_INBAND_SEND (0x29)
#define MPI_FUNCTION_INBAND_RSP (0x2A)
@@ -276,6 +308,7 @@
#define MPI_FUNCTION_IO_UNIT_RESET (0x41)
#define MPI_FUNCTION_HANDSHAKE (0x42)
#define MPI_FUNCTION_REPLY_FRAME_REMOVAL (0x43)
+#define MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL (0x44)
/* standard version format */
@@ -328,8 +361,8 @@ typedef struct _SGE_SIMPLE_UNION
U32 Address32;
U64 Address64;
}u;
-} SGESimpleUnion_t, MPI_POINTER pSGESimpleUnion_t,
- SGE_SIMPLE_UNION, MPI_POINTER PTR_SGE_SIMPLE_UNION;
+} SGE_SIMPLE_UNION, MPI_POINTER PTR_SGE_SIMPLE_UNION,
+ SGESimpleUnion_t, MPI_POINTER pSGESimpleUnion_t;
/****************************************************************************/
/* Chain element structures */
@@ -648,27 +681,21 @@ typedef struct _MSG_DEFAULT_REPLY
#define MPI_IOCSTATUS_SCSI_EXT_TERMINATED (0x004C)
/****************************************************************************/
-/* For use by SCSI Initiator and SCSI Target end-to-end data protection */
-/****************************************************************************/
-
-#define MPI_IOCSTATUS_EEDP_CRC_ERROR (0x004D)
-#define MPI_IOCSTATUS_EEDP_LBA_TAG_ERROR (0x004E)
-#define MPI_IOCSTATUS_EEDP_APP_TAG_ERROR (0x004F)
-
-
-/****************************************************************************/
-/* SCSI (SPI & FCP) target values */
+/* SCSI Target values */
/****************************************************************************/
#define MPI_IOCSTATUS_TARGET_PRIORITY_IO (0x0060)
#define MPI_IOCSTATUS_TARGET_INVALID_PORT (0x0061)
-#define MPI_IOCSTATUS_TARGET_INVALID_IOCINDEX (0x0062) /* obsolete */
+#define MPI_IOCSTATUS_TARGET_INVALID_IOCINDEX (0x0062) /* obsolete name */
#define MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX (0x0062)
#define MPI_IOCSTATUS_TARGET_ABORTED (0x0063)
#define MPI_IOCSTATUS_TARGET_NO_CONN_RETRYABLE (0x0064)
#define MPI_IOCSTATUS_TARGET_NO_CONNECTION (0x0065)
#define MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH (0x006A)
#define MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT (0x006B)
+#define MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D)
+#define MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E)
+#define MPI_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F)
/****************************************************************************/
/* Additional FCP target values (obsolete) */
@@ -707,6 +734,7 @@ typedef struct _MSG_DEFAULT_REPLY
/****************************************************************************/
#define MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090)
+#define MPI_IOCSTATUS_SAS_SMP_DATA_OVERRUN (0x0091)
/****************************************************************************/
/* Inband values */
diff --git a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h
index a5680d864bf..15b12b06799 100644
--- a/drivers/message/fusion/lsi/mpi_cnfg.h
+++ b/drivers/message/fusion/lsi/mpi_cnfg.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2000-2003 LSI Logic Corporation.
+ * Copyright (c) 2000-2005 LSI Logic Corporation.
*
*
* Name: mpi_cnfg.h
* Title: MPI Config message, structures, and Pages
* Creation Date: July 27, 2000
*
- * mpi_cnfg.h Version: 01.05.xx
+ * mpi_cnfg.h Version: 01.05.08
*
* Version History
* ---------------
@@ -145,6 +145,93 @@
* In CONFIG_PAGE_FC_DEVICE_0, replaced Reserved1 field
* with ADISCHardALPA.
* Added MPI_FC_DEVICE_PAGE0_PROT_FCP_RETRY define.
+ * 01-16-04 01.02.13 Added InitiatorDeviceTimeout and InitiatorIoPendTimeout
+ * fields and related defines to CONFIG_PAGE_FC_PORT_1.
+ * Added define for
+ * MPI_FCPORTPAGE1_FLAGS_SOFT_ALPA_FALLBACK.
+ * Added new fields to the substructures of
+ * CONFIG_PAGE_FC_PORT_10.
+ * 04-29-04 01.02.14 Added define for IDP bit for CONFIG_PAGE_SCSI_PORT_0,
+ * CONFIG_PAGE_SCSI_DEVICE_0, and
+ * CONFIG_PAGE_SCSI_DEVICE_1. Also bumped Page Version for
+ * these pages.
+ * 05-11-04 01.03.01 Added structure for CONFIG_PAGE_INBAND_0.
+ * 08-19-04 01.05.01 Modified MSG_CONFIG request to support extended config
+ * pages.
+ * Added a new structure for extended config page header.
+ * Added new extended config pages types and structures for
+ * SAS IO Unit, SAS Expander, SAS Device, and SAS PHY.
+ * Replaced a reserved byte in CONFIG_PAGE_MANUFACTURING_4
+ * to add a Flags field.
+ * Two new Manufacturing config pages (5 and 6).
+ * Two new bits defined for IO Unit Page 1 Flags field.
+ * Modified CONFIG_PAGE_IO_UNIT_2 to add three new fields
+ * to specify the BIOS boot device.
+ * Four new Flags bits defined for IO Unit Page 2.
+ * Added IO Unit Page 4.
+ * Added EEDP Flags settings to IOC Page 1.
+ * Added new BIOS Page 1 config page.
+ * 10-05-04 01.05.02 Added define for
+ * MPI_IOCPAGE1_INITIATOR_CONTEXT_REPLY_DISABLE.
+ * Added new Flags field to CONFIG_PAGE_MANUFACTURING_5 and
+ * associated defines.
+ * Added more defines for SAS IO Unit Page 0
+ * DiscoveryStatus field.
+ * Added define for MPI_SAS_IOUNIT0_DS_SUBTRACTIVE_LINK
+ * and MPI_SAS_IOUNIT0_DS_TABLE_LINK.
+ * Added defines for Physical Mapping Modes to SAS IO Unit
+ * Page 2.
+ * Added define for
+ * MPI_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH.
+ * 10-27-04 01.05.03 Added defines for new SAS PHY page addressing mode.
+ * Added defines for MaxTargetSpinUp to BIOS Page 1.
+ * Added 5 new ControlFlags defines for SAS IO Unit
+ * Page 1.
+ * Added MaxNumPhysicalMappedIDs field to SAS IO Unit
+ * Page 2.
+ * Added AccessStatus field to SAS Device Page 0 and added
+ * new Flags bits for supported SATA features.
+ * 12-07-04 01.05.04 Added config page structures for BIOS Page 2, RAID
+ * Volume Page 1, and RAID Physical Disk Page 1.
+ * Replaced IO Unit Page 1 BootTargetID,BootBus, and
+ * BootAdapterNum with reserved field.
+ * Added DataScrubRate and ResyncRate to RAID Volume
+ * Page 0.
+ * Added MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT
+ * define.
+ * 12-09-04 01.05.05 Added Target Mode Large CDB Enable to FC Port Page 1
+ * Flags field.
+ * Added Auto Port Config flag define for SAS IOUNIT
+ * Page 1 ControlFlags.
+ * Added Disabled bad Phy define to Expander Page 1
+ * Discovery Info field.
+ * Added SAS/SATA device support to SAS IOUnit Page 1
+ * ControlFlags.
+ * Added Unsupported device to SAS Dev Page 0 Flags field
+ * Added disable use SATA Hash Address for SAS IOUNIT
+ * page 1 in ControlFields.
+ * 01-15-05 01.05.06 Added defaults for data scrub rate and resync rate to
+ * Manufacturing Page 4.
+ * Added new defines for BIOS Page 1 IOCSettings field.
+ * Added ExtDiskIdentifier field to RAID Physical Disk
+ * Page 0.
+ * Added new defines for SAS IO Unit Page 1 ControlFlags
+ * and to SAS Device Page 0 Flags to control SATA devices.
+ * Added defines and structures for the new Log Page 0, a
+ * new type of configuration page.
+ * 02-09-05 01.05.07 Added InactiveStatus field to RAID Volume Page 0.
+ * Added WWID field to RAID Volume Page 1.
+ * Added PhysicalPort field to SAS Expander pages 0 and 1.
+ * 03-11-05 01.05.08 Removed the EEDP flags from IOC Page 1.
+ * Added Enclosure/Slot boot device format to BIOS Page 2.
+ * New status value for RAID Volume Page 0 VolumeStatus
+ * (VolumeState subfield).
+ * New value for RAID Physical Page 0 InactiveStatus.
+ * Added Inactive Volume Member flag RAID Physical Disk
+ * Page 0 PhysDiskStatus field.
+ * New physical mapping mode in SAS IO Unit Page 2.
+ * Added CONFIG_PAGE_SAS_ENCLOSURE_0.
+ * Added Slot and Enclosure fields to SAS Device Page 0.
* --------------------------------------------------------------------------
*/
@@ -164,7 +251,7 @@ typedef struct _CONFIG_PAGE_HEADER
U8 PageLength; /* 01h */
U8 PageNumber; /* 02h */
U8 PageType; /* 03h */
-} fCONFIG_PAGE_HEADER, MPI_POINTER PTR_CONFIG_PAGE_HEADER,
+} CONFIG_PAGE_HEADER, MPI_POINTER PTR_CONFIG_PAGE_HEADER,
ConfigPageHeader_t, MPI_POINTER pConfigPageHeader_t;
typedef union _CONFIG_PAGE_HEADER_UNION
@@ -174,7 +261,7 @@ typedef union _CONFIG_PAGE_HEADER_UNION
U16 Word16[2];
U32 Word32;
} ConfigPageHeaderUnion, MPI_POINTER pConfigPageHeaderUnion,
- fCONFIG_PAGE_HEADER_UNION, MPI_POINTER PTR_CONFIG_PAGE_HEADER_UNION;
+ CONFIG_PAGE_HEADER_UNION, MPI_POINTER PTR_CONFIG_PAGE_HEADER_UNION;
typedef struct _CONFIG_EXTENDED_PAGE_HEADER
{
@@ -185,7 +272,7 @@ typedef struct _CONFIG_EXTENDED_PAGE_HEADER
U16 ExtPageLength; /* 04h */
U8 ExtPageType; /* 06h */
U8 Reserved2; /* 07h */
-} fCONFIG_EXTENDED_PAGE_HEADER, MPI_POINTER PTR_CONFIG_EXTENDED_PAGE_HEADER,
+} CONFIG_EXTENDED_PAGE_HEADER, MPI_POINTER PTR_CONFIG_EXTENDED_PAGE_HEADER,
ConfigExtendedPageHeader_t, MPI_POINTER pConfigExtendedPageHeader_t;
@@ -224,6 +311,8 @@ typedef struct _CONFIG_EXTENDED_PAGE_HEADER
#define MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER (0x11)
#define MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE (0x12)
#define MPI_CONFIG_EXTPAGETYPE_SAS_PHY (0x13)
+#define MPI_CONFIG_EXTPAGETYPE_LOG (0x14)
+#define MPI_CONFIG_EXTPAGETYPE_ENCLOSURE (0x15)
/****************************************************************************
@@ -231,10 +320,19 @@ typedef struct _CONFIG_EXTENDED_PAGE_HEADER
****************************************************************************/
#define MPI_SCSI_PORT_PGAD_PORT_MASK (0x000000FF)
+#define MPI_SCSI_DEVICE_FORM_MASK (0xF0000000)
+#define MPI_SCSI_DEVICE_FORM_BUS_TID (0x00000000)
#define MPI_SCSI_DEVICE_TARGET_ID_MASK (0x000000FF)
#define MPI_SCSI_DEVICE_TARGET_ID_SHIFT (0)
#define MPI_SCSI_DEVICE_BUS_MASK (0x0000FF00)
#define MPI_SCSI_DEVICE_BUS_SHIFT (8)
+#define MPI_SCSI_DEVICE_FORM_TARGET_MODE (0x10000000)
+#define MPI_SCSI_DEVICE_TM_RESPOND_ID_MASK (0x000000FF)
+#define MPI_SCSI_DEVICE_TM_RESPOND_ID_SHIFT (0)
+#define MPI_SCSI_DEVICE_TM_BUS_MASK (0x0000FF00)
+#define MPI_SCSI_DEVICE_TM_BUS_SHIFT (8)
+#define MPI_SCSI_DEVICE_TM_INIT_ID_MASK (0x00FF0000)
+#define MPI_SCSI_DEVICE_TM_INIT_ID_SHIFT (16)
#define MPI_FC_PORT_PGAD_PORT_MASK (0xF0000000)
#define MPI_FC_PORT_PGAD_PORT_SHIFT (28)
@@ -260,6 +358,20 @@ typedef struct _CONFIG_EXTENDED_PAGE_HEADER
#define MPI_PHYSDISK_PGAD_PHYSDISKNUM_MASK (0x000000FF)
#define MPI_PHYSDISK_PGAD_PHYSDISKNUM_SHIFT (0)
+#define MPI_SAS_EXPAND_PGAD_FORM_MASK (0xF0000000)
+#define MPI_SAS_EXPAND_PGAD_FORM_SHIFT (28)
+#define MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE (0x00000000)
+#define MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM (0x00000001)
+#define MPI_SAS_EXPAND_PGAD_FORM_HANDLE (0x00000002)
+#define MPI_SAS_EXPAND_PGAD_GNH_MASK_HANDLE (0x0000FFFF)
+#define MPI_SAS_EXPAND_PGAD_GNH_SHIFT_HANDLE (0)
+#define MPI_SAS_EXPAND_PGAD_HPN_MASK_PHY (0x00FF0000)
+#define MPI_SAS_EXPAND_PGAD_HPN_SHIFT_PHY (16)
+#define MPI_SAS_EXPAND_PGAD_HPN_MASK_HANDLE (0x0000FFFF)
+#define MPI_SAS_EXPAND_PGAD_HPN_SHIFT_HANDLE (0)
+#define MPI_SAS_EXPAND_PGAD_H_MASK_HANDLE (0x0000FFFF)
+#define MPI_SAS_EXPAND_PGAD_H_SHIFT_HANDLE (0)
+
#define MPI_SAS_DEVICE_PGAD_FORM_MASK (0xF0000000)
#define MPI_SAS_DEVICE_PGAD_FORM_SHIFT (28)
#define MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE (0x00000000)
@@ -274,10 +386,24 @@ typedef struct _CONFIG_EXTENDED_PAGE_HEADER
#define MPI_SAS_DEVICE_PGAD_H_HANDLE_MASK (0x0000FFFF)
#define MPI_SAS_DEVICE_PGAD_H_HANDLE_SHIFT (0)
-#define MPI_SAS_PHY_PGAD_PHY_NUMBER_MASK (0x00FF0000)
-#define MPI_SAS_PHY_PGAD_PHY_NUMBER_SHIFT (16)
-#define MPI_SAS_PHY_PGAD_DEVHANDLE_MASK (0x0000FFFF)
-#define MPI_SAS_PHY_PGAD_DEVHANDLE_SHIFT (0)
+#define MPI_SAS_PHY_PGAD_FORM_MASK (0xF0000000)
+#define MPI_SAS_PHY_PGAD_FORM_SHIFT (28)
+#define MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER (0x0)
+#define MPI_SAS_PHY_PGAD_FORM_PHY_TBL_INDEX (0x1)
+#define MPI_SAS_PHY_PGAD_PHY_NUMBER_MASK (0x000000FF)
+#define MPI_SAS_PHY_PGAD_PHY_NUMBER_SHIFT (0)
+#define MPI_SAS_PHY_PGAD_PHY_TBL_INDEX_MASK (0x0000FFFF)
+#define MPI_SAS_PHY_PGAD_PHY_TBL_INDEX_SHIFT (0)
+
+#define MPI_SAS_ENCLOS_PGAD_FORM_MASK (0xF0000000)
+#define MPI_SAS_ENCLOS_PGAD_FORM_SHIFT (28)
+#define MPI_SAS_ENCLOS_PGAD_FORM_GET_NEXT_HANDLE (0x00000000)
+#define MPI_SAS_ENCLOS_PGAD_FORM_HANDLE (0x00000001)
+#define MPI_SAS_ENCLOS_PGAD_GNH_HANDLE_MASK (0x0000FFFF)
+#define MPI_SAS_ENCLOS_PGAD_GNH_HANDLE_SHIFT (0)
+#define MPI_SAS_ENCLOS_PGAD_H_HANDLE_MASK (0x0000FFFF)
+#define MPI_SAS_ENCLOS_PGAD_H_HANDLE_SHIFT (0)
+
/****************************************************************************
@@ -294,7 +420,7 @@ typedef struct _MSG_CONFIG
U8 MsgFlags; /* 07h */
U32 MsgContext; /* 08h */
U8 Reserved2[8]; /* 0Ch */
- fCONFIG_PAGE_HEADER Header; /* 14h */
+ CONFIG_PAGE_HEADER Header; /* 14h */
U32 PageAddress; /* 18h */
SGE_IO_UNION PageBufferSGE; /* 1Ch */
} MSG_CONFIG, MPI_POINTER PTR_MSG_CONFIG,
@@ -327,7 +453,7 @@ typedef struct _MSG_CONFIG_REPLY
U8 Reserved2[2]; /* 0Ch */
U16 IOCStatus; /* 0Eh */
U32 IOCLogInfo; /* 10h */
- fCONFIG_PAGE_HEADER Header; /* 14h */
+ CONFIG_PAGE_HEADER Header; /* 14h */
} MSG_CONFIG_REPLY, MPI_POINTER PTR_MSG_CONFIG_REPLY,
ConfigReply_t, MPI_POINTER pConfigReply_t;
@@ -349,6 +475,8 @@ typedef struct _MSG_CONFIG_REPLY
#define MPI_MANUFACTPAGE_DEVICEID_FC929 (0x0622)
#define MPI_MANUFACTPAGE_DEVICEID_FC919X (0x0628)
#define MPI_MANUFACTPAGE_DEVICEID_FC929X (0x0626)
+#define MPI_MANUFACTPAGE_DEVICEID_FC939X (0x0642)
+#define MPI_MANUFACTPAGE_DEVICEID_FC949X (0x0640)
/* SCSI */
#define MPI_MANUFACTPAGE_DEVID_53C1030 (0x0030)
#define MPI_MANUFACTPAGE_DEVID_53C1030ZC (0x0031)
@@ -358,18 +486,25 @@ typedef struct _MSG_CONFIG_REPLY
#define MPI_MANUFACTPAGE_DEVID_53C1035ZC (0x0041)
/* SAS */
#define MPI_MANUFACTPAGE_DEVID_SAS1064 (0x0050)
+#define MPI_MANUFACTPAGE_DEVID_SAS1064A (0x005C)
+#define MPI_MANUFACTPAGE_DEVID_SAS1064E (0x0056)
+#define MPI_MANUFACTPAGE_DEVID_SAS1066 (0x005E)
+#define MPI_MANUFACTPAGE_DEVID_SAS1066E (0x005A)
+#define MPI_MANUFACTPAGE_DEVID_SAS1068 (0x0054)
+#define MPI_MANUFACTPAGE_DEVID_SAS1068E (0x0058)
+#define MPI_MANUFACTPAGE_DEVID_SAS1078 (0x0060)
typedef struct _CONFIG_PAGE_MANUFACTURING_0
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U8 ChipName[16]; /* 04h */
U8 ChipRevision[8]; /* 14h */
U8 BoardName[16]; /* 1Ch */
U8 BoardAssembly[16]; /* 2Ch */
U8 BoardTracerNumber[16]; /* 3Ch */
-} fCONFIG_PAGE_MANUFACTURING_0, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_0,
+} CONFIG_PAGE_MANUFACTURING_0, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_0,
ManufacturingPage0_t, MPI_POINTER pManufacturingPage0_t;
#define MPI_MANUFACTURING0_PAGEVERSION (0x00)
@@ -377,9 +512,9 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_0
typedef struct _CONFIG_PAGE_MANUFACTURING_1
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U8 VPD[256]; /* 04h */
-} fCONFIG_PAGE_MANUFACTURING_1, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_1,
+} CONFIG_PAGE_MANUFACTURING_1, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_1,
ManufacturingPage1_t, MPI_POINTER pManufacturingPage1_t;
#define MPI_MANUFACTURING1_PAGEVERSION (0x00)
@@ -404,10 +539,10 @@ typedef struct _MPI_CHIP_REVISION_ID
typedef struct _CONFIG_PAGE_MANUFACTURING_2
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
MPI_CHIP_REVISION_ID ChipId; /* 04h */
U32 HwSettings[MPI_MAN_PAGE_2_HW_SETTINGS_WORDS];/* 08h */
-} fCONFIG_PAGE_MANUFACTURING_2, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_2,
+} CONFIG_PAGE_MANUFACTURING_2, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_2,
ManufacturingPage2_t, MPI_POINTER pManufacturingPage2_t;
#define MPI_MANUFACTURING2_PAGEVERSION (0x00)
@@ -423,10 +558,10 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_2
typedef struct _CONFIG_PAGE_MANUFACTURING_3
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
MPI_CHIP_REVISION_ID ChipId; /* 04h */
U32 Info[MPI_MAN_PAGE_3_INFO_WORDS];/* 08h */
-} fCONFIG_PAGE_MANUFACTURING_3, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_3,
+} CONFIG_PAGE_MANUFACTURING_3, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_3,
ManufacturingPage3_t, MPI_POINTER pManufacturingPage3_t;
#define MPI_MANUFACTURING3_PAGEVERSION (0x00)
@@ -434,7 +569,7 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_3
typedef struct _CONFIG_PAGE_MANUFACTURING_4
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U32 Reserved1; /* 04h */
U8 InfoOffset0; /* 08h */
U8 InfoSize0; /* 09h */
@@ -447,10 +582,23 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_4
U32 ISVolumeSettings; /* 48h */
U32 IMEVolumeSettings; /* 4Ch */
U32 IMVolumeSettings; /* 50h */
-} fCONFIG_PAGE_MANUFACTURING_4, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_4,
+ U32 Reserved3; /* 54h */
+ U32 Reserved4; /* 58h */
+ U8 ISDataScrubRate; /* 5Ch */
+ U8 ISResyncRate; /* 5Dh */
+ U16 Reserved5; /* 5Eh */
+ U8 IMEDataScrubRate; /* 60h */
+ U8 IMEResyncRate; /* 61h */
+ U16 Reserved6; /* 62h */
+ U8 IMDataScrubRate; /* 64h */
+ U8 IMResyncRate; /* 65h */
+ U16 Reserved7; /* 66h */
+ U32 Reserved8; /* 68h */
+ U32 Reserved9; /* 6Ch */
+} CONFIG_PAGE_MANUFACTURING_4, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_4,
ManufacturingPage4_t, MPI_POINTER pManufacturingPage4_t;
-#define MPI_MANUFACTURING4_PAGEVERSION (0x01)
+#define MPI_MANUFACTURING4_PAGEVERSION (0x02)
/* defines for the Flags field */
#define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA (0x01)
@@ -458,19 +606,25 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_4
typedef struct _CONFIG_PAGE_MANUFACTURING_5
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U64 BaseWWID; /* 04h */
-} fCONFIG_PAGE_MANUFACTURING_5, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_5,
+ U8 Flags; /* 0Ch */
+ U8 Reserved1; /* 0Dh */
+ U16 Reserved2; /* 0Eh */
+} CONFIG_PAGE_MANUFACTURING_5, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_5,
ManufacturingPage5_t, MPI_POINTER pManufacturingPage5_t;
-#define MPI_MANUFACTURING5_PAGEVERSION (0x00)
+#define MPI_MANUFACTURING5_PAGEVERSION (0x01)
+
+/* defines for the Flags field */
+#define MPI_MANPAGE5_TWO_WWID_PER_PHY (0x01)
typedef struct _CONFIG_PAGE_MANUFACTURING_6
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U32 ProductSpecificInfo;/* 04h */
-} fCONFIG_PAGE_MANUFACTURING_6, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_6,
+} CONFIG_PAGE_MANUFACTURING_6, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_6,
ManufacturingPage6_t, MPI_POINTER pManufacturingPage6_t;
#define MPI_MANUFACTURING6_PAGEVERSION (0x00)
@@ -482,9 +636,9 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_6
typedef struct _CONFIG_PAGE_IO_UNIT_0
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U64 UniqueValue; /* 04h */
-} fCONFIG_PAGE_IO_UNIT_0, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_0,
+} CONFIG_PAGE_IO_UNIT_0, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_0,
IOUnitPage0_t, MPI_POINTER pIOUnitPage0_t;
#define MPI_IOUNITPAGE0_PAGEVERSION (0x00)
@@ -492,9 +646,9 @@ typedef struct _CONFIG_PAGE_IO_UNIT_0
typedef struct _CONFIG_PAGE_IO_UNIT_1
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U32 Flags; /* 04h */
-} fCONFIG_PAGE_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_1,
+} CONFIG_PAGE_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_1,
IOUnitPage1_t, MPI_POINTER pIOUnitPage1_t;
#define MPI_IOUNITPAGE1_PAGEVERSION (0x01)
@@ -524,14 +678,15 @@ typedef struct _MPI_ADAPTER_INFO
typedef struct _CONFIG_PAGE_IO_UNIT_2
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U32 Flags; /* 04h */
U32 BiosVersion; /* 08h */
MPI_ADAPTER_INFO AdapterOrder[4]; /* 0Ch */
-} fCONFIG_PAGE_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_2,
+ U32 Reserved1; /* 1Ch */
+} CONFIG_PAGE_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_2,
IOUnitPage2_t, MPI_POINTER pIOUnitPage2_t;
-#define MPI_IOUNITPAGE2_PAGEVERSION (0x00)
+#define MPI_IOUNITPAGE2_PAGEVERSION (0x02)
#define MPI_IOUNITPAGE2_FLAGS_PAUSE_ON_ERROR (0x00000002)
#define MPI_IOUNITPAGE2_FLAGS_VERBOSE_ENABLE (0x00000004)
@@ -554,12 +709,12 @@ typedef struct _CONFIG_PAGE_IO_UNIT_2
typedef struct _CONFIG_PAGE_IO_UNIT_3
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U8 GPIOCount; /* 04h */
U8 Reserved1; /* 05h */
U16 Reserved2; /* 06h */
U16 GPIOVal[MPI_IO_UNIT_PAGE_3_GPIO_VAL_MAX]; /* 08h */
-} fCONFIG_PAGE_IO_UNIT_3, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_3,
+} CONFIG_PAGE_IO_UNIT_3, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_3,
IOUnitPage3_t, MPI_POINTER pIOUnitPage3_t;
#define MPI_IOUNITPAGE3_PAGEVERSION (0x01)
@@ -570,13 +725,24 @@ typedef struct _CONFIG_PAGE_IO_UNIT_3
#define MPI_IOUNITPAGE3_GPIO_SETTING_ON (0x01)
+typedef struct _CONFIG_PAGE_IO_UNIT_4
+{
+ CONFIG_PAGE_HEADER Header; /* 00h */
+ U32 Reserved1; /* 04h */
+ SGE_SIMPLE_UNION FWImageSGE; /* 08h */
+} CONFIG_PAGE_IO_UNIT_4, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_4,
+ IOUnitPage4_t, MPI_POINTER pIOUnitPage4_t;
+
+#define MPI_IOUNITPAGE4_PAGEVERSION (0x00)
+
+
/****************************************************************************
* IOC Config Pages
****************************************************************************/
typedef struct _CONFIG_PAGE_IOC_0
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U32 TotalNVStore; /* 04h */
U32 FreeNVStore; /* 08h */
U16 VendorID; /* 0Ch */
@@ -586,7 +752,7 @@ typedef struct _CONFIG_PAGE_IOC_0
U32 ClassCode; /* 14h */
U16 SubsystemVendorID; /* 18h */
U16 SubsystemID; /* 1Ah */
-} fCONFIG_PAGE_IOC_0, MPI_POINTER PTR_CONFIG_PAGE_IOC_0,
+} CONFIG_PAGE_IOC_0, MPI_POINTER PTR_CONFIG_PAGE_IOC_0,
IOCPage0_t, MPI_POINTER pIOCPage0_t;
#define MPI_IOCPAGE0_PAGEVERSION (0x01)
@@ -594,23 +760,19 @@ typedef struct _CONFIG_PAGE_IOC_0
typedef struct _CONFIG_PAGE_IOC_1
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U32 Flags; /* 04h */
U32 CoalescingTimeout; /* 08h */
U8 CoalescingDepth; /* 0Ch */
U8 PCISlotNum; /* 0Dh */
U8 Reserved[2]; /* 0Eh */
-} fCONFIG_PAGE_IOC_1, MPI_POINTER PTR_CONFIG_PAGE_IOC_1,
+} CONFIG_PAGE_IOC_1, MPI_POINTER PTR_CONFIG_PAGE_IOC_1,
IOCPage1_t, MPI_POINTER pIOCPage1_t;
-#define MPI_IOCPAGE1_PAGEVERSION (0x01)
+#define MPI_IOCPAGE1_PAGEVERSION (0x02)
/* defines for the Flags field */
-#define MPI_IOCPAGE1_EEDP_HOST_SUPPORTS_DIF (0x08000000)
-#define MPI_IOCPAGE1_EEDP_MODE_MASK (0x07000000)
-#define MPI_IOCPAGE1_EEDP_MODE_OFF (0x00000000)
-#define MPI_IOCPAGE1_EEDP_MODE_T10 (0x01000000)
-#define MPI_IOCPAGE1_EEDP_MODE_LSI_1 (0x02000000)
+#define MPI_IOCPAGE1_INITIATOR_CONTEXT_REPLY_DISABLE (0x00000010)
#define MPI_IOCPAGE1_REPLY_COALESCING (0x00000001)
#define MPI_IOCPAGE1_PCISLOTNUM_UNKNOWN (0xFF)
@@ -625,7 +787,7 @@ typedef struct _CONFIG_PAGE_IOC_2_RAID_VOL
U8 VolumeType; /* 04h */
U8 Flags; /* 05h */
U16 Reserved3; /* 06h */
-} fCONFIG_PAGE_IOC_2_RAID_VOL, MPI_POINTER PTR_CONFIG_PAGE_IOC_2_RAID_VOL,
+} CONFIG_PAGE_IOC_2_RAID_VOL, MPI_POINTER PTR_CONFIG_PAGE_IOC_2_RAID_VOL,
ConfigPageIoc2RaidVol_t, MPI_POINTER pConfigPageIoc2RaidVol_t;
/* IOC Page 2 Volume RAID Type values, also used in RAID Volume pages */
@@ -648,14 +810,14 @@ typedef struct _CONFIG_PAGE_IOC_2_RAID_VOL
typedef struct _CONFIG_PAGE_IOC_2
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U32 CapabilitiesFlags; /* 04h */
U8 NumActiveVolumes; /* 08h */
U8 MaxVolumes; /* 09h */
U8 NumActivePhysDisks; /* 0Ah */
U8 MaxPhysDisks; /* 0Bh */
- fCONFIG_PAGE_IOC_2_RAID_VOL RaidVolume[MPI_IOC_PAGE_2_RAID_VOLUME_MAX];/* 0Ch */
-} fCONFIG_PAGE_IOC_2, MPI_POINTER PTR_CONFIG_PAGE_IOC_2,
+ CONFIG_PAGE_IOC_2_RAID_VOL RaidVolume[MPI_IOC_PAGE_2_RAID_VOLUME_MAX];/* 0Ch */
+} CONFIG_PAGE_IOC_2, MPI_POINTER PTR_CONFIG_PAGE_IOC_2,
IOCPage2_t, MPI_POINTER pIOCPage2_t;
#define MPI_IOCPAGE2_PAGEVERSION (0x02)
@@ -689,12 +851,12 @@ typedef struct _IOC_3_PHYS_DISK
typedef struct _CONFIG_PAGE_IOC_3
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U8 NumPhysDisks; /* 04h */
U8 Reserved1; /* 05h */
U16 Reserved2; /* 06h */
IOC_3_PHYS_DISK PhysDisk[MPI_IOC_PAGE_3_PHYSDISK_MAX]; /* 08h */
-} fCONFIG_PAGE_IOC_3, MPI_POINTER PTR_CONFIG_PAGE_IOC_3,
+} CONFIG_PAGE_IOC_3, MPI_POINTER PTR_CONFIG_PAGE_IOC_3,
IOCPage3_t, MPI_POINTER pIOCPage3_t;
#define MPI_IOCPAGE3_PAGEVERSION (0x00)
@@ -718,12 +880,12 @@ typedef struct _IOC_4_SEP
typedef struct _CONFIG_PAGE_IOC_4
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U8 ActiveSEP; /* 04h */
U8 MaxSEP; /* 05h */
U16 Reserved1; /* 06h */
IOC_4_SEP SEP[MPI_IOC_PAGE_4_SEP_MAX]; /* 08h */
-} fCONFIG_PAGE_IOC_4, MPI_POINTER PTR_CONFIG_PAGE_IOC_4,
+} CONFIG_PAGE_IOC_4, MPI_POINTER PTR_CONFIG_PAGE_IOC_4,
IOCPage4_t, MPI_POINTER pIOCPage4_t;
#define MPI_IOCPAGE4_PAGEVERSION (0x00)
@@ -751,25 +913,25 @@ typedef struct _IOC_5_HOT_SPARE
typedef struct _CONFIG_PAGE_IOC_5
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U32 Reserved1; /* 04h */
U8 NumHotSpares; /* 08h */
U8 Reserved2; /* 09h */
U16 Reserved3; /* 0Ah */
IOC_5_HOT_SPARE HotSpare[MPI_IOC_PAGE_5_HOT_SPARE_MAX]; /* 0Ch */
-} fCONFIG_PAGE_IOC_5, MPI_POINTER PTR_CONFIG_PAGE_IOC_5,
+} CONFIG_PAGE_IOC_5, MPI_POINTER PTR_CONFIG_PAGE_IOC_5,
IOCPage5_t, MPI_POINTER pIOCPage5_t;
#define MPI_IOCPAGE5_PAGEVERSION (0x00)
/****************************************************************************
-* BIOS Port Config Pages
+* BIOS Config Pages
****************************************************************************/
typedef struct _CONFIG_PAGE_BIOS_1
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U32 BiosOptions; /* 04h */
U32 IOCSettings; /* 08h */
U32 Reserved1; /* 0Ch */
@@ -780,10 +942,10 @@ typedef struct _CONFIG_PAGE_BIOS_1
U16 IOTimeoutSequential; /* 1Ah */
U16 IOTimeoutOther; /* 1Ch */
U16 IOTimeoutBlockDevicesRM; /* 1Eh */
-} fCONFIG_PAGE_BIOS_1, MPI_POINTER PTR_CONFIG_PAGE_BIOS_1,
+} CONFIG_PAGE_BIOS_1, MPI_POINTER PTR_CONFIG_PAGE_BIOS_1,
BIOSPage1_t, MPI_POINTER pBIOSPage1_t;
-#define MPI_BIOSPAGE1_PAGEVERSION (0x00)
+#define MPI_BIOSPAGE1_PAGEVERSION (0x01)
/* values for the BiosOptions field */
#define MPI_BIOSPAGE1_OPTIONS_SPI_ENABLE (0x00000400)
@@ -792,6 +954,13 @@ typedef struct _CONFIG_PAGE_BIOS_1
#define MPI_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001)
/* values for the IOCSettings field */
+#define MPI_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE (0x00030000)
+#define MPI_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT (0x00000000)
+#define MPI_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT (0x00010000)
+
+#define MPI_BIOSPAGE1_IOCSET_MASK_MAX_TARGET_SPIN_UP (0x0000F000)
+#define MPI_BIOSPAGE1_IOCSET_SHIFT_MAX_TARGET_SPIN_UP (12)
+
#define MPI_BIOSPAGE1_IOCSET_MASK_SPINUP_DELAY (0x00000F00)
#define MPI_BIOSPAGE1_IOCSET_SHIFT_SPINUP_DELAY (8)
@@ -814,6 +983,191 @@ typedef struct _CONFIG_PAGE_BIOS_1
#define MPI_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN (0x00000002)
#define MPI_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN (0x00000001)
+typedef struct _MPI_BOOT_DEVICE_ADAPTER_ORDER
+{
+ U32 Reserved1; /* 00h */
+ U32 Reserved2; /* 04h */
+ U32 Reserved3; /* 08h */
+ U32 Reserved4; /* 0Ch */
+ U32 Reserved5; /* 10h */
+ U32 Reserved6; /* 14h */
+ U32 Reserved7; /* 18h */
+ U32 Reserved8; /* 1Ch */
+ U32 Reserved9; /* 20h */
+ U32 Reserved10; /* 24h */
+ U32 Reserved11; /* 28h */
+ U32 Reserved12; /* 2Ch */
+ U32 Reserved13; /* 30h */
+ U32 Reserved14; /* 34h */
+ U32 Reserved15; /* 38h */
+ U32 Reserved16; /* 3Ch */
+ U32 Reserved17; /* 40h */
+} MPI_BOOT_DEVICE_ADAPTER_ORDER, MPI_POINTER PTR_MPI_BOOT_DEVICE_ADAPTER_ORDER;
+
+typedef struct _MPI_BOOT_DEVICE_ADAPTER_NUMBER
+{
+ U8 TargetID; /* 00h */
+ U8 Bus; /* 01h */
+ U8 AdapterNumber; /* 02h */
+ U8 Reserved1; /* 03h */
+ U32 Reserved2; /* 04h */
+ U32 Reserved3; /* 08h */
+ U32 Reserved4; /* 0Ch */
+ U8 LUN[8]; /* 10h */
+ U32 Reserved5; /* 18h */
+ U32 Reserved6; /* 1Ch */
+ U32 Reserved7; /* 20h */
+ U32 Reserved8; /* 24h */
+ U32 Reserved9; /* 28h */
+ U32 Reserved10; /* 2Ch */
+ U32 Reserved11; /* 30h */
+ U32 Reserved12; /* 34h */
+ U32 Reserved13; /* 38h */
+ U32 Reserved14; /* 3Ch */
+ U32 Reserved15; /* 40h */
+} MPI_BOOT_DEVICE_ADAPTER_NUMBER, MPI_POINTER PTR_MPI_BOOT_DEVICE_ADAPTER_NUMBER;
+
+typedef struct _MPI_BOOT_DEVICE_PCI_ADDRESS
+{
+ U8 TargetID; /* 00h */
+ U8 Bus; /* 01h */
+ U16 PCIAddress; /* 02h */
+ U32 Reserved1; /* 04h */
+ U32 Reserved2; /* 08h */
+ U32 Reserved3; /* 0Ch */
+ U8 LUN[8]; /* 10h */
+ U32 Reserved4; /* 18h */
+ U32 Reserved5; /* 1Ch */
+ U32 Reserved6; /* 20h */
+ U32 Reserved7; /* 24h */
+ U32 Reserved8; /* 28h */
+ U32 Reserved9; /* 2Ch */
+ U32 Reserved10; /* 30h */
+ U32 Reserved11; /* 34h */
+ U32 Reserved12; /* 38h */
+ U32 Reserved13; /* 3Ch */
+ U32 Reserved14; /* 40h */
+} MPI_BOOT_DEVICE_PCI_ADDRESS, MPI_POINTER PTR_MPI_BOOT_DEVICE_PCI_ADDRESS;
+
+typedef struct _MPI_BOOT_DEVICE_SLOT_NUMBER
+{
+ U8 TargetID; /* 00h */
+ U8 Bus; /* 01h */
+ U8 PCISlotNumber; /* 02h */
+ U8 Reserved1; /* 03h */
+ U32 Reserved2; /* 04h */
+ U32 Reserved3; /* 08h */
+ U32 Reserved4; /* 0Ch */
+ U8 LUN[8]; /* 10h */
+ U32 Reserved5; /* 18h */
+ U32 Reserved6; /* 1Ch */
+ U32 Reserved7; /* 20h */
+ U32 Reserved8; /* 24h */
+ U32 Reserved9; /* 28h */
+ U32 Reserved10; /* 2Ch */
+ U32 Reserved11; /* 30h */
+ U32 Reserved12; /* 34h */
+ U32 Reserved13; /* 38h */
+ U32 Reserved14; /* 3Ch */
+ U32 Reserved15; /* 40h */
+} MPI_BOOT_DEVICE_PCI_SLOT_NUMBER, MPI_POINTER PTR_MPI_BOOT_DEVICE_PCI_SLOT_NUMBER;
+
+typedef struct _MPI_BOOT_DEVICE_FC_WWN
+{
+ U64 WWPN; /* 00h */
+ U32 Reserved1; /* 08h */
+ U32 Reserved2; /* 0Ch */
+ U8 LUN[8]; /* 10h */
+ U32 Reserved3; /* 18h */
+ U32 Reserved4; /* 1Ch */
+ U32 Reserved5; /* 20h */
+ U32 Reserved6; /* 24h */
+ U32 Reserved7; /* 28h */
+ U32 Reserved8; /* 2Ch */
+ U32 Reserved9; /* 30h */
+ U32 Reserved10; /* 34h */
+ U32 Reserved11; /* 38h */
+ U32 Reserved12; /* 3Ch */
+ U32 Reserved13; /* 40h */
+} MPI_BOOT_DEVICE_FC_WWN, MPI_POINTER PTR_MPI_BOOT_DEVICE_FC_WWN;
+
+typedef struct _MPI_BOOT_DEVICE_SAS_WWN
+{
+ U64 SASAddress; /* 00h */
+ U32 Reserved1; /* 08h */
+ U32 Reserved2; /* 0Ch */
+ U8 LUN[8]; /* 10h */
+ U32 Reserved3; /* 18h */
+ U32 Reserved4; /* 1Ch */
+ U32 Reserved5; /* 20h */
+ U32 Reserved6; /* 24h */
+ U32 Reserved7; /* 28h */
+ U32 Reserved8; /* 2Ch */
+ U32 Reserved9; /* 30h */
+ U32 Reserved10; /* 34h */
+ U32 Reserved11; /* 38h */
+ U32 Reserved12; /* 3Ch */
+ U32 Reserved13; /* 40h */
+} MPI_BOOT_DEVICE_SAS_WWN, MPI_POINTER PTR_MPI_BOOT_DEVICE_SAS_WWN;
+
+typedef struct _MPI_BOOT_DEVICE_ENCLOSURE_SLOT
+{
+ U64 EnclosureLogicalID; /* 00h */
+ U32 Reserved1; /* 08h */
+ U32 Reserved2; /* 0Ch */
+ U8 LUN[8]; /* 10h */
+ U16 SlotNumber; /* 18h */
+ U16 Reserved3; /* 1Ah */
+ U32 Reserved4; /* 1Ch */
+ U32 Reserved5; /* 20h */
+ U32 Reserved6; /* 24h */
+ U32 Reserved7; /* 28h */
+ U32 Reserved8; /* 2Ch */
+ U32 Reserved9; /* 30h */
+ U32 Reserved10; /* 34h */
+ U32 Reserved11; /* 38h */
+ U32 Reserved12; /* 3Ch */
+ U32 Reserved13; /* 40h */
+} MPI_BOOT_DEVICE_ENCLOSURE_SLOT,
+ MPI_POINTER PTR_MPI_BOOT_DEVICE_ENCLOSURE_SLOT;
+
+typedef union _MPI_BIOSPAGE2_BOOT_DEVICE
+{
+ MPI_BOOT_DEVICE_ADAPTER_ORDER AdapterOrder;
+ MPI_BOOT_DEVICE_ADAPTER_NUMBER AdapterNumber;
+ MPI_BOOT_DEVICE_PCI_ADDRESS PCIAddress;
+ MPI_BOOT_DEVICE_PCI_SLOT_NUMBER PCISlotNumber;
+ MPI_BOOT_DEVICE_FC_WWN FcWwn;
+ MPI_BOOT_DEVICE_SAS_WWN SasWwn;
+ MPI_BOOT_DEVICE_ENCLOSURE_SLOT EnclosureSlot;
+} MPI_BIOSPAGE2_BOOT_DEVICE, MPI_POINTER PTR_MPI_BIOSPAGE2_BOOT_DEVICE;
+
+typedef struct _CONFIG_PAGE_BIOS_2
+{
+ CONFIG_PAGE_HEADER Header; /* 00h */
+ U32 Reserved1; /* 04h */
+ U32 Reserved2; /* 08h */
+ U32 Reserved3; /* 0Ch */
+ U32 Reserved4; /* 10h */
+ U32 Reserved5; /* 14h */
+ U32 Reserved6; /* 18h */
+ U8 BootDeviceForm; /* 1Ch */
+ U8 Reserved7; /* 1Dh */
+ U16 Reserved8; /* 1Eh */
+ MPI_BIOSPAGE2_BOOT_DEVICE BootDevice; /* 20h */
+} CONFIG_PAGE_BIOS_2, MPI_POINTER PTR_CONFIG_PAGE_BIOS_2,
+ BIOSPage2_t, MPI_POINTER pBIOSPage2_t;
+
+#define MPI_BIOSPAGE2_PAGEVERSION (0x01)
+
+#define MPI_BIOSPAGE2_FORM_MASK (0x0F)
+#define MPI_BIOSPAGE2_FORM_ADAPTER_ORDER (0x00)
+#define MPI_BIOSPAGE2_FORM_ADAPTER_NUMBER (0x01)
+#define MPI_BIOSPAGE2_FORM_PCI_ADDRESS (0x02)
+#define MPI_BIOSPAGE2_FORM_PCI_SLOT_NUMBER (0x03)
+#define MPI_BIOSPAGE2_FORM_FC_WWN (0x04)
+#define MPI_BIOSPAGE2_FORM_SAS_WWN (0x05)
+
/****************************************************************************
* SCSI Port Config Pages
@@ -821,13 +1175,13 @@ typedef struct _CONFIG_PAGE_BIOS_1
typedef struct _CONFIG_PAGE_SCSI_PORT_0
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U32 Capabilities; /* 04h */
U32 PhysicalInterface; /* 08h */
-} fCONFIG_PAGE_SCSI_PORT_0, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_0,
+} CONFIG_PAGE_SCSI_PORT_0, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_0,
SCSIPortPage0_t, MPI_POINTER pSCSIPortPage0_t;
-#define MPI_SCSIPORTPAGE0_PAGEVERSION (0x01)
+#define MPI_SCSIPORTPAGE0_PAGEVERSION (0x02)
#define MPI_SCSIPORTPAGE0_CAP_IU (0x00000001)
#define MPI_SCSIPORTPAGE0_CAP_DT (0x00000002)
@@ -854,6 +1208,7 @@ typedef struct _CONFIG_PAGE_SCSI_PORT_0
( ((Cap) & MPI_SCSIPORTPAGE0_CAP_MASK_MAX_SYNC_OFFSET) \
>> MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET \
)
+#define MPI_SCSIPORTPAGE0_CAP_IDP (0x08000000)
#define MPI_SCSIPORTPAGE0_CAP_WIDE (0x20000000)
#define MPI_SCSIPORTPAGE0_CAP_AIP (0x80000000)
@@ -869,13 +1224,13 @@ typedef struct _CONFIG_PAGE_SCSI_PORT_0
typedef struct _CONFIG_PAGE_SCSI_PORT_1
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U32 Configuration; /* 04h */
U32 OnBusTimerValue; /* 08h */
U8 TargetConfig; /* 0Ch */
U8 Reserved1; /* 0Dh */
U16 IDConfig; /* 0Eh */
-} fCONFIG_PAGE_SCSI_PORT_1, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_1,
+} CONFIG_PAGE_SCSI_PORT_1, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_1,
SCSIPortPage1_t, MPI_POINTER pSCSIPortPage1_t;
#define MPI_SCSIPORTPAGE1_PAGEVERSION (0x03)
@@ -900,11 +1255,11 @@ typedef struct _MPI_DEVICE_INFO
typedef struct _CONFIG_PAGE_SCSI_PORT_2
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U32 PortFlags; /* 04h */
U32 PortSettings; /* 08h */
MPI_DEVICE_INFO DeviceSettings[16]; /* 0Ch */
-} fCONFIG_PAGE_SCSI_PORT_2, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_2,
+} CONFIG_PAGE_SCSI_PORT_2, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_2,
SCSIPortPage2_t, MPI_POINTER pSCSIPortPage2_t;
#define MPI_SCSIPORTPAGE2_PAGEVERSION (0x02)
@@ -953,13 +1308,13 @@ typedef struct _CONFIG_PAGE_SCSI_PORT_2
typedef struct _CONFIG_PAGE_SCSI_DEVICE_0
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U32 NegotiatedParameters; /* 04h */
U32 Information; /* 08h */
-} fCONFIG_PAGE_SCSI_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_0,
+} CONFIG_PAGE_SCSI_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_0,
SCSIDevicePage0_t, MPI_POINTER pSCSIDevicePage0_t;
-#define MPI_SCSIDEVPAGE0_PAGEVERSION (0x03)
+#define MPI_SCSIDEVPAGE0_PAGEVERSION (0x04)
#define MPI_SCSIDEVPAGE0_NP_IU (0x00000001)
#define MPI_SCSIDEVPAGE0_NP_DT (0x00000002)
@@ -973,6 +1328,7 @@ typedef struct _CONFIG_PAGE_SCSI_DEVICE_0
#define MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_PERIOD (8)
#define MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK (0x00FF0000)
#define MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_OFFSET (16)
+#define MPI_SCSIDEVPAGE0_NP_IDP (0x08000000)
#define MPI_SCSIDEVPAGE0_NP_WIDE (0x20000000)
#define MPI_SCSIDEVPAGE0_NP_AIP (0x80000000)
@@ -984,14 +1340,14 @@ typedef struct _CONFIG_PAGE_SCSI_DEVICE_0
typedef struct _CONFIG_PAGE_SCSI_DEVICE_1
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U32 RequestedParameters; /* 04h */
U32 Reserved; /* 08h */
U32 Configuration; /* 0Ch */
-} fCONFIG_PAGE_SCSI_DEVICE_1, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_1,
+} CONFIG_PAGE_SCSI_DEVICE_1, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_1,
SCSIDevicePage1_t, MPI_POINTER pSCSIDevicePage1_t;
-#define MPI_SCSIDEVPAGE1_PAGEVERSION (0x04)
+#define MPI_SCSIDEVPAGE1_PAGEVERSION (0x05)
#define MPI_SCSIDEVPAGE1_RP_IU (0x00000001)
#define MPI_SCSIDEVPAGE1_RP_DT (0x00000002)
@@ -1005,6 +1361,7 @@ typedef struct _CONFIG_PAGE_SCSI_DEVICE_1
#define MPI_SCSIDEVPAGE1_RP_SHIFT_MIN_SYNC_PERIOD (8)
#define MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK (0x00FF0000)
#define MPI_SCSIDEVPAGE1_RP_SHIFT_MAX_SYNC_OFFSET (16)
+#define MPI_SCSIDEVPAGE1_RP_IDP (0x08000000)
#define MPI_SCSIDEVPAGE1_RP_WIDE (0x20000000)
#define MPI_SCSIDEVPAGE1_RP_AIP (0x80000000)
@@ -1016,11 +1373,11 @@ typedef struct _CONFIG_PAGE_SCSI_DEVICE_1
typedef struct _CONFIG_PAGE_SCSI_DEVICE_2
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U32 DomainValidation; /* 04h */
U32 ParityPipeSelect; /* 08h */
U32 DataPipeSelect; /* 0Ch */
-} fCONFIG_PAGE_SCSI_DEVICE_2, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_2,
+} CONFIG_PAGE_SCSI_DEVICE_2, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_2,
SCSIDevicePage2_t, MPI_POINTER pSCSIDevicePage2_t;
#define MPI_SCSIDEVPAGE2_PAGEVERSION (0x01)
@@ -1057,12 +1414,12 @@ typedef struct _CONFIG_PAGE_SCSI_DEVICE_2
typedef struct _CONFIG_PAGE_SCSI_DEVICE_3
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U16 MsgRejectCount; /* 04h */
U16 PhaseErrorCount; /* 06h */
U16 ParityErrorCount; /* 08h */
U16 Reserved; /* 0Ah */
-} fCONFIG_PAGE_SCSI_DEVICE_3, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_3,
+} CONFIG_PAGE_SCSI_DEVICE_3, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_3,
SCSIDevicePage3_t, MPI_POINTER pSCSIDevicePage3_t;
#define MPI_SCSIDEVPAGE3_PAGEVERSION (0x00)
@@ -1077,7 +1434,7 @@ typedef struct _CONFIG_PAGE_SCSI_DEVICE_3
typedef struct _CONFIG_PAGE_FC_PORT_0
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U32 Flags; /* 04h */
U8 MPIPortNumber; /* 08h */
U8 LinkType; /* 09h */
@@ -1098,7 +1455,7 @@ typedef struct _CONFIG_PAGE_FC_PORT_0
U8 MaxHardAliasesSupported; /* 49h */
U8 NumCurrentAliases; /* 4Ah */
U8 Reserved1; /* 4Bh */
-} fCONFIG_PAGE_FC_PORT_0, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_0,
+} CONFIG_PAGE_FC_PORT_0, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_0,
FCPortPage0_t, MPI_POINTER pFCPortPage0_t;
#define MPI_FCPORTPAGE0_PAGEVERSION (0x02)
@@ -1164,10 +1521,9 @@ typedef struct _CONFIG_PAGE_FC_PORT_0
#define MPI_FCPORTPAGE0_CURRENT_SPEED_NOT_NEGOTIATED (0x00008000) /* (SNIA)HBA_PORTSPEED_NOT_NEGOTIATED (1<<15) Speed not established */
-
typedef struct _CONFIG_PAGE_FC_PORT_1
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U32 Flags; /* 04h */
U64 NoSEEPROMWWNN; /* 08h */
U64 NoSEEPROMWWPN; /* 10h */
@@ -1179,7 +1535,7 @@ typedef struct _CONFIG_PAGE_FC_PORT_1
U8 RR_TOV; /* 1Dh */
U8 InitiatorDeviceTimeout; /* 1Eh */
U8 InitiatorIoPendTimeout; /* 1Fh */
-} fCONFIG_PAGE_FC_PORT_1, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_1,
+} CONFIG_PAGE_FC_PORT_1, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_1,
FCPortPage1_t, MPI_POINTER pFCPortPage1_t;
#define MPI_FCPORTPAGE1_PAGEVERSION (0x06)
@@ -1191,6 +1547,7 @@ typedef struct _CONFIG_PAGE_FC_PORT_1
#define MPI_FCPORTPAGE1_FLAGS_TARGET_MODE_OXID (0x00800000)
#define MPI_FCPORTPAGE1_FLAGS_PORT_OFFLINE (0x00400000)
#define MPI_FCPORTPAGE1_FLAGS_SOFT_ALPA_FALLBACK (0x00200000)
+#define MPI_FCPORTPAGE1_FLAGS_TARGET_LARGE_CDB_ENABLE (0x00000080)
#define MPI_FCPORTPAGE1_FLAGS_MASK_RR_TOV_UNITS (0x00000070)
#define MPI_FCPORTPAGE1_FLAGS_SUPPRESS_PROT_REG (0x00000008)
#define MPI_FCPORTPAGE1_FLAGS_PLOGI_ON_LOGO (0x00000004)
@@ -1227,14 +1584,15 @@ typedef struct _CONFIG_PAGE_FC_PORT_1
#define MPI_FCPORTPAGE1_ALT_CONN_UNKNOWN (0x00)
#define MPI_FCPORTPAGE1_INITIATOR_DEV_TIMEOUT_MASK (0x7F)
+#define MPI_FCPORTPAGE1_INITIATOR_DEV_UNIT_16 (0x80)
typedef struct _CONFIG_PAGE_FC_PORT_2
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U8 NumberActive; /* 04h */
U8 ALPA[127]; /* 05h */
-} fCONFIG_PAGE_FC_PORT_2, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_2,
+} CONFIG_PAGE_FC_PORT_2, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_2,
FCPortPage2_t, MPI_POINTER pFCPortPage2_t;
#define MPI_FCPORTPAGE2_PAGEVERSION (0x01)
@@ -1280,9 +1638,9 @@ typedef struct _FC_PORT_PERSISTENT
typedef struct _CONFIG_PAGE_FC_PORT_3
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
FC_PORT_PERSISTENT Entry[MPI_FC_PORT_PAGE_3_ENTRY_MAX]; /* 04h */
-} fCONFIG_PAGE_FC_PORT_3, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_3,
+} CONFIG_PAGE_FC_PORT_3, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_3,
FCPortPage3_t, MPI_POINTER pFCPortPage3_t;
#define MPI_FCPORTPAGE3_PAGEVERSION (0x01)
@@ -1290,10 +1648,10 @@ typedef struct _CONFIG_PAGE_FC_PORT_3
typedef struct _CONFIG_PAGE_FC_PORT_4
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U32 PortFlags; /* 04h */
U32 PortSettings; /* 08h */
-} fCONFIG_PAGE_FC_PORT_4, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_4,
+} CONFIG_PAGE_FC_PORT_4, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_4,
FCPortPage4_t, MPI_POINTER pFCPortPage4_t;
#define MPI_FCPORTPAGE4_PAGEVERSION (0x00)
@@ -1316,15 +1674,15 @@ typedef struct _CONFIG_PAGE_FC_PORT_5_ALIAS_INFO
U16 Reserved; /* 02h */
U64 AliasWWNN; /* 04h */
U64 AliasWWPN; /* 0Ch */
-} fCONFIG_PAGE_FC_PORT_5_ALIAS_INFO,
+} CONFIG_PAGE_FC_PORT_5_ALIAS_INFO,
MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_5_ALIAS_INFO,
FcPortPage5AliasInfo_t, MPI_POINTER pFcPortPage5AliasInfo_t;
typedef struct _CONFIG_PAGE_FC_PORT_5
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
- fCONFIG_PAGE_FC_PORT_5_ALIAS_INFO AliasInfo; /* 04h */
-} fCONFIG_PAGE_FC_PORT_5, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_5,
+ CONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_FC_PORT_5_ALIAS_INFO AliasInfo; /* 04h */
+} CONFIG_PAGE_FC_PORT_5, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_5,
FCPortPage5_t, MPI_POINTER pFCPortPage5_t;
#define MPI_FCPORTPAGE5_PAGEVERSION (0x02)
@@ -1337,7 +1695,7 @@ typedef struct _CONFIG_PAGE_FC_PORT_5
typedef struct _CONFIG_PAGE_FC_PORT_6
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U32 Reserved; /* 04h */
U64 TimeSinceReset; /* 08h */
U64 TxFrames; /* 10h */
@@ -1355,7 +1713,7 @@ typedef struct _CONFIG_PAGE_FC_PORT_6
U64 InvalidTxWordCount; /* 70h */
U64 InvalidCrcCount; /* 78h */
U64 FcpInitiatorIoCount; /* 80h */
-} fCONFIG_PAGE_FC_PORT_6, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_6,
+} CONFIG_PAGE_FC_PORT_6, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_6,
FCPortPage6_t, MPI_POINTER pFCPortPage6_t;
#define MPI_FCPORTPAGE6_PAGEVERSION (0x00)
@@ -1363,10 +1721,10 @@ typedef struct _CONFIG_PAGE_FC_PORT_6
typedef struct _CONFIG_PAGE_FC_PORT_7
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U32 Reserved; /* 04h */
U8 PortSymbolicName[256]; /* 08h */
-} fCONFIG_PAGE_FC_PORT_7, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_7,
+} CONFIG_PAGE_FC_PORT_7, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_7,
FCPortPage7_t, MPI_POINTER pFCPortPage7_t;
#define MPI_FCPORTPAGE7_PAGEVERSION (0x00)
@@ -1374,9 +1732,9 @@ typedef struct _CONFIG_PAGE_FC_PORT_7
typedef struct _CONFIG_PAGE_FC_PORT_8
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U32 BitVector[8]; /* 04h */
-} fCONFIG_PAGE_FC_PORT_8, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_8,
+} CONFIG_PAGE_FC_PORT_8, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_8,
FCPortPage8_t, MPI_POINTER pFCPortPage8_t;
#define MPI_FCPORTPAGE8_PAGEVERSION (0x00)
@@ -1384,7 +1742,7 @@ typedef struct _CONFIG_PAGE_FC_PORT_8
typedef struct _CONFIG_PAGE_FC_PORT_9
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U32 Reserved; /* 04h */
U64 GlobalWWPN; /* 08h */
U64 GlobalWWNN; /* 10h */
@@ -1396,7 +1754,7 @@ typedef struct _CONFIG_PAGE_FC_PORT_9
U8 IPAddress[16]; /* 28h */
U16 Reserved1; /* 38h */
U16 TopologyDiscoveryFlags; /* 3Ah */
-} fCONFIG_PAGE_FC_PORT_9, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_9,
+} CONFIG_PAGE_FC_PORT_9, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_9,
FCPortPage9_t, MPI_POINTER pFCPortPage9_t;
#define MPI_FCPORTPAGE9_PAGEVERSION (0x00)
@@ -1422,10 +1780,10 @@ typedef struct _CONFIG_PAGE_FC_PORT_10_BASE_SFP_DATA
U8 VendorOUI[3]; /* 35h */
U8 VendorPN[16]; /* 38h */
U8 VendorRev[4]; /* 48h */
- U16 Reserved4; /* 4Ch */
- U8 Reserved5; /* 4Eh */
+ U16 Wavelength; /* 4Ch */
+ U8 Reserved4; /* 4Eh */
U8 CC_BASE; /* 4Fh */
-} fCONFIG_PAGE_FC_PORT_10_BASE_SFP_DATA,
+} CONFIG_PAGE_FC_PORT_10_BASE_SFP_DATA,
MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_10_BASE_SFP_DATA,
FCPortPage10BaseSfpData_t, MPI_POINTER pFCPortPage10BaseSfpData_t;
@@ -1481,9 +1839,11 @@ typedef struct _CONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA
U8 BitRateMin; /* 53h */
U8 VendorSN[16]; /* 54h */
U8 DateCode[8]; /* 64h */
- U8 Reserved5[3]; /* 6Ch */
+ U8 DiagMonitoringType; /* 6Ch */
+ U8 EnhancedOptions; /* 6Dh */
+ U8 SFF8472Compliance; /* 6Eh */
U8 CC_EXT; /* 6Fh */
-} fCONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA,
+} CONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA,
MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA,
FCPortPage10ExtendedSfpData_t, MPI_POINTER pFCPortPage10ExtendedSfpData_t;
@@ -1496,19 +1856,19 @@ typedef struct _CONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA
typedef struct _CONFIG_PAGE_FC_PORT_10
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U8 Flags; /* 04h */
U8 Reserved1; /* 05h */
U16 Reserved2; /* 06h */
U32 HwConfig1; /* 08h */
U32 HwConfig2; /* 0Ch */
- fCONFIG_PAGE_FC_PORT_10_BASE_SFP_DATA Base; /* 10h */
- fCONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA Extended; /* 50h */
+ CONFIG_PAGE_FC_PORT_10_BASE_SFP_DATA Base; /* 10h */
+ CONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA Extended; /* 50h */
U8 VendorSpecific[32]; /* 70h */
-} fCONFIG_PAGE_FC_PORT_10, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_10,
+} CONFIG_PAGE_FC_PORT_10, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_10,
FCPortPage10_t, MPI_POINTER pFCPortPage10_t;
-#define MPI_FCPORTPAGE10_PAGEVERSION (0x00)
+#define MPI_FCPORTPAGE10_PAGEVERSION (0x01)
/* standard MODDEF pin definitions (from GBIC spec.) */
#define MPI_FCPORTPAGE10_FLAGS_MODDEF_MASK (0x00000007)
@@ -1534,7 +1894,7 @@ typedef struct _CONFIG_PAGE_FC_PORT_10
typedef struct _CONFIG_PAGE_FC_DEVICE_0
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U64 WWNN; /* 04h */
U64 WWPN; /* 0Ch */
U32 PortIdentifier; /* 14h */
@@ -1548,7 +1908,7 @@ typedef struct _CONFIG_PAGE_FC_DEVICE_0
U8 FcPhHighestVersion; /* 21h */
U8 CurrentTargetID; /* 22h */
U8 CurrentBus; /* 23h */
-} fCONFIG_PAGE_FC_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_FC_DEVICE_0,
+} CONFIG_PAGE_FC_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_FC_DEVICE_0,
FCDevicePage0_t, MPI_POINTER pFCDevicePage0_t;
#define MPI_FC_DEVICE_PAGE0_PAGEVERSION (0x03)
@@ -1606,6 +1966,7 @@ typedef struct _RAID_VOL0_STATUS
#define MPI_RAIDVOL0_STATUS_STATE_OPTIMAL (0x00)
#define MPI_RAIDVOL0_STATUS_STATE_DEGRADED (0x01)
#define MPI_RAIDVOL0_STATUS_STATE_FAILED (0x02)
+#define MPI_RAIDVOL0_STATUS_STATE_MISSING (0x03)
typedef struct _RAID_VOL0_SETTINGS
{
@@ -1616,11 +1977,11 @@ typedef struct _RAID_VOL0_SETTINGS
RaidVol0Settings, MPI_POINTER pRaidVol0Settings;
/* RAID Volume Page 0 VolumeSettings defines */
-
#define MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE (0x0001)
#define MPI_RAIDVOL0_SETTING_OFFLINE_ON_SMART (0x0002)
#define MPI_RAIDVOL0_SETTING_AUTO_CONFIGURE (0x0004)
#define MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC (0x0008)
+#define MPI_RAIDVOL0_SETTING_FAST_DATA_SCRUBBING_0102 (0x0020) /* obsolete */
#define MPI_RAIDVOL0_SETTING_USE_PRODUCT_ID_SUFFIX (0x0010)
#define MPI_RAIDVOL0_SETTING_USE_DEFAULTS (0x8000)
@@ -1644,7 +2005,7 @@ typedef struct _RAID_VOL0_SETTINGS
typedef struct _CONFIG_PAGE_RAID_VOL_0
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U8 VolumeID; /* 04h */
U8 VolumeBus; /* 05h */
U8 VolumeIOC; /* 06h */
@@ -1657,13 +2018,41 @@ typedef struct _CONFIG_PAGE_RAID_VOL_0
U32 Reserved2; /* 1Ch */
U32 Reserved3; /* 20h */
U8 NumPhysDisks; /* 24h */
- U8 Reserved4; /* 25h */
- U16 Reserved5; /* 26h */
+ U8 DataScrubRate; /* 25h */
+ U8 ResyncRate; /* 26h */
+ U8 InactiveStatus; /* 27h */
RAID_VOL0_PHYS_DISK PhysDisk[MPI_RAID_VOL_PAGE_0_PHYSDISK_MAX];/* 28h */
-} fCONFIG_PAGE_RAID_VOL_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_VOL_0,
+} CONFIG_PAGE_RAID_VOL_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_VOL_0,
RaidVolumePage0_t, MPI_POINTER pRaidVolumePage0_t;
-#define MPI_RAIDVOLPAGE0_PAGEVERSION (0x01)
+#define MPI_RAIDVOLPAGE0_PAGEVERSION (0x04)
+
+/* values for RAID Volume Page 0 InactiveStatus field */
+#define MPI_RAIDVOLPAGE0_UNKNOWN_INACTIVE (0x00)
+#define MPI_RAIDVOLPAGE0_STALE_METADATA_INACTIVE (0x01)
+#define MPI_RAIDVOLPAGE0_FOREIGN_VOLUME_INACTIVE (0x02)
+#define MPI_RAIDVOLPAGE0_INSUFFICIENT_RESOURCE_INACTIVE (0x03)
+#define MPI_RAIDVOLPAGE0_CLONE_VOLUME_INACTIVE (0x04)
+#define MPI_RAIDVOLPAGE0_INSUFFICIENT_METADATA_INACTIVE (0x05)
+#define MPI_RAIDVOLPAGE0_PREVIOUSLY_DELETED (0x06)
+
+
+typedef struct _CONFIG_PAGE_RAID_VOL_1
+{
+ CONFIG_PAGE_HEADER Header; /* 00h */
+ U8 VolumeID; /* 01h */
+ U8 VolumeBus; /* 02h */
+ U8 VolumeIOC; /* 03h */
+ U8 Reserved0; /* 04h */
+ U8 GUID[24]; /* 05h */
+ U8 Name[32]; /* 20h */
+ U64 WWID; /* 40h */
+ U32 Reserved1; /* 48h */
+ U32 Reserved2; /* 4Ch */
+} CONFIG_PAGE_RAID_VOL_1, MPI_POINTER PTR_CONFIG_PAGE_RAID_VOL_1,
+ RaidVolumePage1_t, MPI_POINTER pRaidVolumePage1_t;
+
+#define MPI_RAIDVOLPAGE1_PAGEVERSION (0x01)
/****************************************************************************
@@ -1714,6 +2103,7 @@ typedef struct _RAID_PHYS_DISK0_STATUS
#define MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC (0x01)
#define MPI_PHYSDISK0_STATUS_FLAG_QUIESCED (0x02)
+#define MPI_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME (0x04)
#define MPI_PHYSDISK0_STATUS_ONLINE (0x00)
#define MPI_PHYSDISK0_STATUS_MISSING (0x01)
@@ -1726,24 +2116,54 @@ typedef struct _RAID_PHYS_DISK0_STATUS
typedef struct _CONFIG_PAGE_RAID_PHYS_DISK_0
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
U8 PhysDiskID; /* 04h */
U8 PhysDiskBus; /* 05h */
U8 PhysDiskIOC; /* 06h */
U8 PhysDiskNum; /* 07h */
RAID_PHYS_DISK0_SETTINGS PhysDiskSettings; /* 08h */
U32 Reserved1; /* 0Ch */
- U32 Reserved2; /* 10h */
- U32 Reserved3; /* 14h */
+ U8 ExtDiskIdentifier[8]; /* 10h */
U8 DiskIdentifier[16]; /* 18h */
RAID_PHYS_DISK0_INQUIRY_DATA InquiryData; /* 28h */
RAID_PHYS_DISK0_STATUS PhysDiskStatus; /* 64h */
U32 MaxLBA; /* 68h */
RAID_PHYS_DISK0_ERROR_DATA ErrorData; /* 6Ch */
-} fCONFIG_PAGE_RAID_PHYS_DISK_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_PHYS_DISK_0,
+} CONFIG_PAGE_RAID_PHYS_DISK_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_PHYS_DISK_0,
RaidPhysDiskPage0_t, MPI_POINTER pRaidPhysDiskPage0_t;
-#define MPI_RAIDPHYSDISKPAGE0_PAGEVERSION (0x00)
+#define MPI_RAIDPHYSDISKPAGE0_PAGEVERSION (0x01)
+
+
+typedef struct _RAID_PHYS_DISK1_PATH
+{
+ U8 PhysDiskID; /* 00h */
+ U8 PhysDiskBus; /* 01h */
+ U16 Reserved1; /* 02h */
+ U64 WWID; /* 04h */
+ U64 OwnerWWID; /* 0Ch */
+ U8 OwnerIdentifier; /* 14h */
+ U8 Reserved2; /* 15h */
+ U16 Flags; /* 16h */
+} RAID_PHYS_DISK1_PATH, MPI_POINTER PTR_RAID_PHYS_DISK1_PATH,
+ RaidPhysDisk1Path_t, MPI_POINTER pRaidPhysDisk1Path_t;
+
+/* RAID Physical Disk Page 1 Flags field defines */
+#define MPI_RAID_PHYSDISK1_FLAG_BROKEN (0x0002)
+#define MPI_RAID_PHYSDISK1_FLAG_INVALID (0x0001)
+
+typedef struct _CONFIG_PAGE_RAID_PHYS_DISK_1
+{
+ CONFIG_PAGE_HEADER Header; /* 00h */
+ U8 NumPhysDiskPaths; /* 04h */
+ U8 PhysDiskNum; /* 05h */
+ U16 Reserved2; /* 06h */
+ U32 Reserved1; /* 08h */
+ RAID_PHYS_DISK1_PATH Path[1]; /* 0Ch */
+} CONFIG_PAGE_RAID_PHYS_DISK_1, MPI_POINTER PTR_CONFIG_PAGE_RAID_PHYS_DISK_1,
+ RaidPhysDiskPage1_t, MPI_POINTER pRaidPhysDiskPage1_t;
+
+#define MPI_RAIDPHYSDISKPAGE1_PAGEVERSION (0x00)
/****************************************************************************
@@ -1756,7 +2176,7 @@ typedef struct _CONFIG_PAGE_LAN_0
U16 TxRxModes; /* 04h */
U16 Reserved; /* 06h */
U32 PacketPrePad; /* 08h */
-} fCONFIG_PAGE_LAN_0, MPI_POINTER PTR_CONFIG_PAGE_LAN_0,
+} CONFIG_PAGE_LAN_0, MPI_POINTER PTR_CONFIG_PAGE_LAN_0,
LANPage0_t, MPI_POINTER pLANPage0_t;
#define MPI_LAN_PAGE0_PAGEVERSION (0x01)
@@ -1781,7 +2201,7 @@ typedef struct _CONFIG_PAGE_LAN_1
U32 MaxReplySize; /* 24h */
U32 NegWireSpeedLow; /* 28h */
U32 NegWireSpeedHigh; /* 2Ch */
-} fCONFIG_PAGE_LAN_1, MPI_POINTER PTR_CONFIG_PAGE_LAN_1,
+} CONFIG_PAGE_LAN_1, MPI_POINTER PTR_CONFIG_PAGE_LAN_1,
LANPage1_t, MPI_POINTER pLANPage1_t;
#define MPI_LAN_PAGE1_PAGEVERSION (0x03)
@@ -1796,11 +2216,11 @@ typedef struct _CONFIG_PAGE_LAN_1
typedef struct _CONFIG_PAGE_INBAND_0
{
- fCONFIG_PAGE_HEADER Header; /* 00h */
+ CONFIG_PAGE_HEADER Header; /* 00h */
MPI_VERSION_FORMAT InbandVersion; /* 04h */
U16 MaximumBuffers; /* 08h */
U16 Reserved1; /* 0Ah */
-} fCONFIG_PAGE_INBAND_0, MPI_POINTER PTR_CONFIG_PAGE_INBAND_0,
+} CONFIG_PAGE_INBAND_0, MPI_POINTER PTR_CONFIG_PAGE_INBAND_0,
InbandPage0_t, MPI_POINTER pInbandPage0_t;
#define MPI_INBAND_PAGEVERSION (0x00)
@@ -1820,7 +2240,7 @@ typedef struct _MPI_SAS_IO_UNIT0_PHY_DATA
U32 ControllerPhyDeviceInfo;/* 04h */
U16 AttachedDeviceHandle; /* 08h */
U16 ControllerDevHandle; /* 0Ah */
- U32 Reserved2; /* 0Ch */
+ U32 DiscoveryStatus; /* 0Ch */
} MPI_SAS_IO_UNIT0_PHY_DATA, MPI_POINTER PTR_MPI_SAS_IO_UNIT0_PHY_DATA,
SasIOUnit0PhyData, MPI_POINTER pSasIOUnit0PhyData;
@@ -1834,22 +2254,21 @@ typedef struct _MPI_SAS_IO_UNIT0_PHY_DATA
typedef struct _CONFIG_PAGE_SAS_IO_UNIT_0
{
- fCONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
+ CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
U32 Reserved1; /* 08h */
U8 NumPhys; /* 0Ch */
U8 Reserved2; /* 0Dh */
U16 Reserved3; /* 0Eh */
MPI_SAS_IO_UNIT0_PHY_DATA PhyData[MPI_SAS_IOUNIT0_PHY_MAX]; /* 10h */
-} fCONFIG_PAGE_SAS_IO_UNIT_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_0,
+} CONFIG_PAGE_SAS_IO_UNIT_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_0,
SasIOUnitPage0_t, MPI_POINTER pSasIOUnitPage0_t;
-#define MPI_SASIOUNITPAGE0_PAGEVERSION (0x00)
+#define MPI_SASIOUNITPAGE0_PAGEVERSION (0x02)
/* values for SAS IO Unit Page 0 PortFlags */
#define MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS (0x08)
#define MPI_SAS_IOUNIT0_PORT_FLAGS_0_TARGET_IOC_NUM (0x00)
#define MPI_SAS_IOUNIT0_PORT_FLAGS_1_TARGET_IOC_NUM (0x04)
-#define MPI_SAS_IOUNIT0_PORT_FLAGS_WAIT_FOR_PORTENABLE (0x02)
#define MPI_SAS_IOUNIT0_PORT_FLAGS_AUTO_PORT_CONFIG (0x01)
/* values for SAS IO Unit Page 0 PhyFlags */
@@ -1867,6 +2286,20 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_0
/* see mpi_sas.h for values for SAS IO Unit Page 0 ControllerPhyDeviceInfo values */
+/* values for SAS IO Unit Page 0 DiscoveryStatus */
+#define MPI_SAS_IOUNIT0_DS_LOOP_DETECTED (0x00000001)
+#define MPI_SAS_IOUNIT0_DS_UNADDRESSABLE_DEVICE (0x00000002)
+#define MPI_SAS_IOUNIT0_DS_MULTIPLE_PORTS (0x00000004)
+#define MPI_SAS_IOUNIT0_DS_EXPANDER_ERR (0x00000008)
+#define MPI_SAS_IOUNIT0_DS_SMP_TIMEOUT (0x00000010)
+#define MPI_SAS_IOUNIT0_DS_OUT_ROUTE_ENTRIES (0x00000020)
+#define MPI_SAS_IOUNIT0_DS_INDEX_NOT_EXIST (0x00000040)
+#define MPI_SAS_IOUNIT0_DS_SMP_FUNCTION_FAILED (0x00000080)
+#define MPI_SAS_IOUNIT0_DS_SMP_CRC_ERROR (0x00000100)
+#define MPI_SAS_IOUNIT0_DS_SUBTRACTIVE_LINK (0x00000200)
+#define MPI_SAS_IOUNIT0_DS_TABLE_LINK (0x00000400)
+#define MPI_SAS_IOUNIT0_DS_UNSUPPORTED_DEVICE (0x00000800)
+
typedef struct _MPI_SAS_IO_UNIT1_PHY_DATA
{
@@ -1889,52 +2322,75 @@ typedef struct _MPI_SAS_IO_UNIT1_PHY_DATA
typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1
{
- fCONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
- U32 Reserved1; /* 08h */
- U8 NumPhys; /* 0Ch */
- U8 Reserved2; /* 0Dh */
- U16 Reserved3; /* 0Eh */
- MPI_SAS_IO_UNIT1_PHY_DATA PhyData[MPI_SAS_IOUNIT1_PHY_MAX]; /* 10h */
-} fCONFIG_PAGE_SAS_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_1,
+ CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
+ U16 ControlFlags; /* 08h */
+ U16 MaxNumSATATargets; /* 0Ah */
+ U32 Reserved1; /* 0Ch */
+ U8 NumPhys; /* 10h */
+ U8 SATAMaxQDepth; /* 11h */
+ U16 Reserved2; /* 12h */
+ MPI_SAS_IO_UNIT1_PHY_DATA PhyData[MPI_SAS_IOUNIT1_PHY_MAX]; /* 14h */
+} CONFIG_PAGE_SAS_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_1,
SasIOUnitPage1_t, MPI_POINTER pSasIOUnitPage1_t;
-#define MPI_SASIOUNITPAGE1_PAGEVERSION (0x00)
-
-/* values for SAS IO Unit Page 0 PortFlags */
-#define MPI_SAS_IOUNIT1_PORT_FLAGS_0_TARGET_IOC_NUM (0x00)
-#define MPI_SAS_IOUNIT1_PORT_FLAGS_1_TARGET_IOC_NUM (0x04)
-#define MPI_SAS_IOUNIT1_PORT_FLAGS_WAIT_FOR_PORTENABLE (0x02)
-#define MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01)
+#define MPI_SASIOUNITPAGE1_PAGEVERSION (0x04)
+
+/* values for SAS IO Unit Page 1 ControlFlags */
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_3_0_MAX (0x4000)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_1_5_MAX (0x2000)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_SW_PRESERVE (0x1000)
+#define MPI_SAS_IOUNIT1_CONTROL_DISABLE_SAS_HASH (0x0800)
+
+#define MPI_SAS_IOUNIT1_CONTROL_MASK_DEV_SUPPORT (0x0600)
+#define MPI_SAS_IOUNIT1_CONTROL_SHIFT_DEV_SUPPORT (9)
+#define MPI_SAS_IOUNIT1_CONTROL_DEV_SUPPORT_BOTH (0x00)
+#define MPI_SAS_IOUNIT1_CONTROL_DEV_SAS_SUPPORT (0x01)
+#define MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT (0x10)
+
+#define MPI_SAS_IOUNIT1_CONTROL_AUTO_PORT_SAME_SAS_ADDR (0x0100)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_SMART_REQUIRED (0x0040)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_NCQ_REQUIRED (0x0020)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_FUA_REQUIRED (0x0010)
+#define MPI_SAS_IOUNIT1_CONTROL_PHY_ENABLE_ORDER_HIGH (0x0008)
+#define MPI_SAS_IOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL (0x0004)
+#define MPI_SAS_IOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002)
+#define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001)
+
+/* values for SAS IO Unit Page 1 PortFlags */
+#define MPI_SAS_IOUNIT1_PORT_FLAGS_0_TARGET_IOC_NUM (0x00)
+#define MPI_SAS_IOUNIT1_PORT_FLAGS_1_TARGET_IOC_NUM (0x04)
+#define MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01)
/* values for SAS IO Unit Page 0 PhyFlags */
-#define MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE (0x04)
-#define MPI_SAS_IOUNIT1_PHY_FLAGS_TX_INVERT (0x02)
-#define MPI_SAS_IOUNIT1_PHY_FLAGS_RX_INVERT (0x01)
+#define MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE (0x04)
+#define MPI_SAS_IOUNIT1_PHY_FLAGS_TX_INVERT (0x02)
+#define MPI_SAS_IOUNIT1_PHY_FLAGS_RX_INVERT (0x01)
/* values for SAS IO Unit Page 0 MaxMinLinkRate */
-#define MPI_SAS_IOUNIT1_MAX_RATE_MASK (0xF0)
-#define MPI_SAS_IOUNIT1_MAX_RATE_1_5 (0x80)
-#define MPI_SAS_IOUNIT1_MAX_RATE_3_0 (0x90)
-#define MPI_SAS_IOUNIT1_MIN_RATE_MASK (0x0F)
-#define MPI_SAS_IOUNIT1_MIN_RATE_1_5 (0x08)
-#define MPI_SAS_IOUNIT1_MIN_RATE_3_0 (0x09)
+#define MPI_SAS_IOUNIT1_MAX_RATE_MASK (0xF0)
+#define MPI_SAS_IOUNIT1_MAX_RATE_1_5 (0x80)
+#define MPI_SAS_IOUNIT1_MAX_RATE_3_0 (0x90)
+#define MPI_SAS_IOUNIT1_MIN_RATE_MASK (0x0F)
+#define MPI_SAS_IOUNIT1_MIN_RATE_1_5 (0x08)
+#define MPI_SAS_IOUNIT1_MIN_RATE_3_0 (0x09)
/* see mpi_sas.h for values for SAS IO Unit Page 1 ControllerPhyDeviceInfo values */
typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2
{
- fCONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
+ CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
U32 Reserved1; /* 08h */
U16 MaxPersistentIDs; /* 0Ch */
U16 NumPersistentIDsUsed; /* 0Eh */
U8 Status; /* 10h */
U8 Flags; /* 11h */
- U16 Reserved2; /* 12h */
-} fCONFIG_PAGE_SAS_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_2,
+ U16 MaxNumPhysicalMappedIDs;/* 12h */ /* 12h */
+} CONFIG_PAGE_SAS_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_2,
SasIOUnitPage2_t, MPI_POINTER pSasIOUnitPage2_t;
-#define MPI_SASIOUNITPAGE2_PAGEVERSION (0x00)
+#define MPI_SASIOUNITPAGE2_PAGEVERSION (0x03)
/* values for SAS IO Unit Page 2 Status field */
#define MPI_SAS_IOUNIT2_STATUS_DISABLED_PERSISTENT_MAPPINGS (0x02)
@@ -1942,11 +2398,19 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2
/* values for SAS IO Unit Page 2 Flags field */
#define MPI_SAS_IOUNIT2_FLAGS_DISABLE_PERSISTENT_MAPPINGS (0x01)
+/* Physical Mapping Modes */
+#define MPI_SAS_IOUNIT2_FLAGS_MASK_PHYS_MAP_MODE (0x0E)
+#define MPI_SAS_IOUNIT2_FLAGS_SHIFT_PHYS_MAP_MODE (1)
+#define MPI_SAS_IOUNIT2_FLAGS_NO_PHYS_MAP (0x00)
+#define MPI_SAS_IOUNIT2_FLAGS_DIRECT_ATTACH_PHYS_MAP (0x01)
+#define MPI_SAS_IOUNIT2_FLAGS_ENCLOSURE_SLOT_PHYS_MAP (0x02)
+
+#define MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT (0x10)
typedef struct _CONFIG_PAGE_SAS_IO_UNIT_3
{
- fCONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
+ CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
U32 Reserved1; /* 08h */
U32 MaxInvalidDwordCount; /* 0Ch */
U32 InvalidDwordCountTime; /* 10h */
@@ -1956,18 +2420,24 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_3
U32 LossDwordSynchCountTime; /* 20h */
U32 MaxPhyResetProblemCount; /* 24h */
U32 PhyResetProblemTime; /* 28h */
-} fCONFIG_PAGE_SAS_IO_UNIT_3, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_3,
+} CONFIG_PAGE_SAS_IO_UNIT_3, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_3,
SasIOUnitPage3_t, MPI_POINTER pSasIOUnitPage3_t;
#define MPI_SASIOUNITPAGE3_PAGEVERSION (0x00)
+/****************************************************************************
+* SAS Expander Config Pages
+****************************************************************************/
+
typedef struct _CONFIG_PAGE_SAS_EXPANDER_0
{
- fCONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
- U32 Reserved1; /* 08h */
+ CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
+ U8 PhysicalPort; /* 08h */
+ U8 Reserved1; /* 09h */
+ U16 Reserved2; /* 0Ah */
U64 SASAddress; /* 0Ch */
- U32 Reserved2; /* 14h */
+ U32 DiscoveryStatus; /* 14h */
U16 DevHandle; /* 18h */
U16 ParentDevHandle; /* 1Ah */
U16 ExpanderChangeCount; /* 1Ch */
@@ -1976,45 +2446,127 @@ typedef struct _CONFIG_PAGE_SAS_EXPANDER_0
U8 SASLevel; /* 21h */
U8 Flags; /* 22h */
U8 Reserved3; /* 23h */
-} fCONFIG_PAGE_SAS_EXPANDER_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_0,
+} CONFIG_PAGE_SAS_EXPANDER_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_0,
SasExpanderPage0_t, MPI_POINTER pSasExpanderPage0_t;
-#define MPI_SASEXPANDER0_PAGEVERSION (0x00)
+#define MPI_SASEXPANDER0_PAGEVERSION (0x02)
+
+/* values for SAS Expander Page 0 DiscoveryStatus field */
+#define MPI_SAS_EXPANDER0_DS_LOOP_DETECTED (0x00000001)
+#define MPI_SAS_EXPANDER0_DS_UNADDRESSABLE_DEVICE (0x00000002)
+#define MPI_SAS_EXPANDER0_DS_MULTIPLE_PORTS (0x00000004)
+#define MPI_SAS_EXPANDER0_DS_EXPANDER_ERR (0x00000008)
+#define MPI_SAS_EXPANDER0_DS_SMP_TIMEOUT (0x00000010)
+#define MPI_SAS_EXPANDER0_DS_OUT_ROUTE_ENTRIES (0x00000020)
+#define MPI_SAS_EXPANDER0_DS_INDEX_NOT_EXIST (0x00000040)
+#define MPI_SAS_EXPANDER0_DS_SMP_FUNCTION_FAILED (0x00000080)
+#define MPI_SAS_EXPANDER0_DS_SMP_CRC_ERROR (0x00000100)
+#define MPI_SAS_EXPANDER0_DS_SUBTRACTIVE_LINK (0x00000200)
+#define MPI_SAS_EXPANDER0_DS_TABLE_LINK (0x00000400)
+#define MPI_SAS_EXPANDER0_DS_UNSUPPORTED_DEVICE (0x00000800)
/* values for SAS Expander Page 0 Flags field */
#define MPI_SAS_EXPANDER0_FLAGS_ROUTE_TABLE_CONFIG (0x02)
#define MPI_SAS_EXPANDER0_FLAGS_CONFIG_IN_PROGRESS (0x01)
+typedef struct _CONFIG_PAGE_SAS_EXPANDER_1
+{
+ CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
+ U8 PhysicalPort; /* 08h */
+ U8 Reserved1; /* 09h */
+ U16 Reserved2; /* 0Ah */
+ U8 NumPhys; /* 0Ch */
+ U8 Phy; /* 0Dh */
+ U16 NumTableEntriesProgrammed; /* 0Eh */
+ U8 ProgrammedLinkRate; /* 10h */
+ U8 HwLinkRate; /* 11h */
+ U16 AttachedDevHandle; /* 12h */
+ U32 PhyInfo; /* 14h */
+ U32 AttachedDeviceInfo; /* 18h */
+ U16 OwnerDevHandle; /* 1Ch */
+ U8 ChangeCount; /* 1Eh */
+ U8 NegotiatedLinkRate; /* 1Fh */
+ U8 PhyIdentifier; /* 20h */
+ U8 AttachedPhyIdentifier; /* 21h */
+ U8 NumTableEntriesProg; /* 22h */
+ U8 DiscoveryInfo; /* 23h */
+ U32 Reserved3; /* 24h */
+} CONFIG_PAGE_SAS_EXPANDER_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_1,
+ SasExpanderPage1_t, MPI_POINTER pSasExpanderPage1_t;
+
+#define MPI_SASEXPANDER1_PAGEVERSION (0x01)
+
+/* use MPI_SAS_PHY0_PRATE_ defines for ProgrammedLinkRate */
+
+/* use MPI_SAS_PHY0_HWRATE_ defines for HwLinkRate */
+
+/* use MPI_SAS_PHY0_PHYINFO_ defines for PhyInfo */
+
+/* see mpi_sas.h for values for SAS Expander Page 1 AttachedDeviceInfo values */
+
+/* values for SAS Expander Page 1 DiscoveryInfo field */
+#define MPI_SAS_EXPANDER1_DISCINFO_BAD_PHY DISABLED (0x04)
+#define MPI_SAS_EXPANDER1_DISCINFO_LINK_STATUS_CHANGE (0x02)
+#define MPI_SAS_EXPANDER1_DISCINFO_NO_ROUTING_ENTRIES (0x01)
+
+/* values for SAS Expander Page 1 NegotiatedLinkRate field */
+#define MPI_SAS_EXPANDER1_NEG_RATE_UNKNOWN (0x00)
+#define MPI_SAS_EXPANDER1_NEG_RATE_PHY_DISABLED (0x01)
+#define MPI_SAS_EXPANDER1_NEG_RATE_FAILED_NEGOTIATION (0x02)
+#define MPI_SAS_EXPANDER1_NEG_RATE_SATA_OOB_COMPLETE (0x03)
+#define MPI_SAS_EXPANDER1_NEG_RATE_1_5 (0x08)
+#define MPI_SAS_EXPANDER1_NEG_RATE_3_0 (0x09)
+
+
+/****************************************************************************
+* SAS Device Config Pages
+****************************************************************************/
+
typedef struct _CONFIG_PAGE_SAS_DEVICE_0
{
- fCONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
- U32 Reserved1; /* 08h */
+ CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
+ U16 Slot; /* 08h */
+ U16 EnclosureHandle; /* 0Ah */
U64 SASAddress; /* 0Ch */
- U32 Reserved2; /* 14h */
+ U16 ParentDevHandle; /* 14h */
+ U8 PhyNum; /* 16h */
+ U8 AccessStatus; /* 17h */
U16 DevHandle; /* 18h */
U8 TargetID; /* 1Ah */
U8 Bus; /* 1Bh */
U32 DeviceInfo; /* 1Ch */
U16 Flags; /* 20h */
U8 PhysicalPort; /* 22h */
- U8 Reserved3; /* 23h */
-} fCONFIG_PAGE_SAS_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_0,
+ U8 Reserved2; /* 23h */
+} CONFIG_PAGE_SAS_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_0,
SasDevicePage0_t, MPI_POINTER pSasDevicePage0_t;
-#define MPI_SASDEVICE0_PAGEVERSION (0x00)
+#define MPI_SASDEVICE0_PAGEVERSION (0x04)
+
+/* values for SAS Device Page 0 AccessStatus field */
+#define MPI_SAS_DEVICE0_ASTATUS_NO_ERRORS (0x00)
+#define MPI_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED (0x01)
+#define MPI_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED (0x02)
/* values for SAS Device Page 0 Flags field */
-#define MPI_SAS_DEVICE0_FLAGS_MAPPING_PERSISTENT (0x04)
-#define MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED (0x02)
-#define MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT (0x01)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE (0x0200)
+#define MPI_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE (0x0100)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_48BIT_LBA_SUPPORTED (0x0080)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED (0x0040)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED (0x0020)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED (0x0010)
+#define MPI_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH (0x0008)
+#define MPI_SAS_DEVICE0_FLAGS_MAPPING_PERSISTENT (0x0004)
+#define MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED (0x0002)
+#define MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT (0x0001)
/* see mpi_sas.h for values for SAS Device Page 0 DeviceInfo values */
typedef struct _CONFIG_PAGE_SAS_DEVICE_1
{
- fCONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
+ CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
U32 Reserved1; /* 08h */
U64 SASAddress; /* 0Ch */
U32 Reserved2; /* 14h */
@@ -2022,15 +2574,30 @@ typedef struct _CONFIG_PAGE_SAS_DEVICE_1
U8 TargetID; /* 1Ah */
U8 Bus; /* 1Bh */
U8 InitialRegDeviceFIS[20];/* 1Ch */
-} fCONFIG_PAGE_SAS_DEVICE_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_1,
+} CONFIG_PAGE_SAS_DEVICE_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_1,
SasDevicePage1_t, MPI_POINTER pSasDevicePage1_t;
#define MPI_SASDEVICE1_PAGEVERSION (0x00)
+typedef struct _CONFIG_PAGE_SAS_DEVICE_2
+{
+ CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
+ U64 PhysicalIdentifier; /* 08h */
+ U32 Reserved1; /* 10h */
+} CONFIG_PAGE_SAS_DEVICE_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_2,
+ SasDevicePage2_t, MPI_POINTER pSasDevicePage2_t;
+
+#define MPI_SASDEVICE2_PAGEVERSION (0x00)
+
+
+/****************************************************************************
+* SAS PHY Config Pages
+****************************************************************************/
+
typedef struct _CONFIG_PAGE_SAS_PHY_0
{
- fCONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
+ CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
U32 Reserved1; /* 08h */
U64 SASAddress; /* 0Ch */
U16 AttachedDevHandle; /* 14h */
@@ -2042,7 +2609,7 @@ typedef struct _CONFIG_PAGE_SAS_PHY_0
U8 ChangeCount; /* 22h */
U8 Reserved3; /* 23h */
U32 PhyInfo; /* 24h */
-} fCONFIG_PAGE_SAS_PHY_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_PHY_0,
+} CONFIG_PAGE_SAS_PHY_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_PHY_0,
SasPhyPage0_t, MPI_POINTER pSasPhyPage0_t;
#define MPI_SASPHY0_PAGEVERSION (0x00)
@@ -2089,17 +2656,95 @@ typedef struct _CONFIG_PAGE_SAS_PHY_0
typedef struct _CONFIG_PAGE_SAS_PHY_1
{
- fCONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
+ CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
U32 Reserved1; /* 08h */
U32 InvalidDwordCount; /* 0Ch */
U32 RunningDisparityErrorCount; /* 10h */
U32 LossDwordSynchCount; /* 14h */
U32 PhyResetProblemCount; /* 18h */
-} fCONFIG_PAGE_SAS_PHY_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_PHY_1,
+} CONFIG_PAGE_SAS_PHY_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_PHY_1,
SasPhyPage1_t, MPI_POINTER pSasPhyPage1_t;
#define MPI_SASPHY1_PAGEVERSION (0x00)
+/****************************************************************************
+* SAS Enclosure Config Pages
+****************************************************************************/
+
+typedef struct _CONFIG_PAGE_SAS_ENCLOSURE_0
+{
+ CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
+ U32 Reserved1; /* 08h */
+ U64 EnclosureLogicalID; /* 0Ch */
+ U16 Flags; /* 14h */
+ U16 EnclosureHandle; /* 16h */
+ U16 NumSlots; /* 18h */
+ U16 StartSlot; /* 1Ah */
+ U8 StartTargetID; /* 1Ch */
+ U8 StartBus; /* 1Dh */
+ U8 SEPTargetID; /* 1Eh */
+ U8 SEPBus; /* 1Fh */
+ U32 Reserved2; /* 20h */
+ U32 Reserved3; /* 24h */
+} CONFIG_PAGE_SAS_ENCLOSURE_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_ENCLOSURE_0,
+ SasEnclosurePage0_t, MPI_POINTER pSasEnclosurePage0_t;
+
+#define MPI_SASENCLOSURE0_PAGEVERSION (0x00)
+
+/* values for SAS Enclosure Page 0 Flags field */
+#define MPI_SAS_ENCLS0_FLAGS_SEP_BUS_ID_VALID (0x0020)
+#define MPI_SAS_ENCLS0_FLAGS_START_BUS_ID_VALID (0x0010)
+
+#define MPI_SAS_ENCLS0_FLAGS_MNG_MASK (0x000F)
+#define MPI_SAS_ENCLS0_FLAGS_MNG_UNKNOWN (0x0000)
+#define MPI_SAS_ENCLS0_FLAGS_MNG_IOC_SES (0x0001)
+#define MPI_SAS_ENCLS0_FLAGS_MNG_IOC_SGPIO (0x0002)
+#define MPI_SAS_ENCLS0_FLAGS_MNG_EXP_SGPIO (0x0003)
+#define MPI_SAS_ENCLS0_FLAGS_MNG_SES_ENCLOSURE (0x0004)
+
+
+/****************************************************************************
+* Log Config Pages
+****************************************************************************/
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check NumLogEntries at runtime.
+ */
+#ifndef MPI_LOG_0_NUM_LOG_ENTRIES
+#define MPI_LOG_0_NUM_LOG_ENTRIES (1)
+#endif
+
+#define MPI_LOG_0_LOG_DATA_LENGTH (20)
+
+typedef struct _MPI_LOG_0_ENTRY
+{
+ U64 WWID; /* 00h */
+ U32 TimeStamp; /* 08h */
+ U32 Reserved1; /* 0Ch */
+ U16 LogSequence; /* 10h */
+ U16 LogEntryQualifier; /* 12h */
+ U8 LogData[MPI_LOG_0_LOG_DATA_LENGTH]; /* 14h */
+} MPI_LOG_0_ENTRY, MPI_POINTER PTR_MPI_LOG_0_ENTRY,
+ MpiLog0Entry_t, MPI_POINTER pMpiLog0Entry_t;
+
+/* values for Log Page 0 LogEntry LogEntryQualifier field */
+#define MPI_LOG_0_ENTRY_QUAL_ENTRY_UNUSED (0x0000)
+#define MPI_LOG_0_ENTRY_QUAL_POWER_ON_RESET (0x0001)
+
+typedef struct _CONFIG_PAGE_LOG_0
+{
+ CONFIG_EXTENDED_PAGE_HEADER Header; /* 00h */
+ U32 Reserved1; /* 08h */
+ U32 Reserved2; /* 0Ch */
+ U16 NumLogEntries; /* 10h */
+ U16 Reserved3; /* 12h */
+ MPI_LOG_0_ENTRY LogEntry[MPI_LOG_0_NUM_LOG_ENTRIES]; /* 14h */
+} CONFIG_PAGE_LOG_0, MPI_POINTER PTR_CONFIG_PAGE_LOG_0,
+ LogPage0_t, MPI_POINTER pLogPage0_t;
+
+#define MPI_LOG_0_PAGEVERSION (0x00)
+
+
#endif
diff --git a/drivers/message/fusion/lsi/mpi_fc.h b/drivers/message/fusion/lsi/mpi_fc.h
index ea266b236c1..51a6aeb990b 100644
--- a/drivers/message/fusion/lsi/mpi_fc.h
+++ b/drivers/message/fusion/lsi/mpi_fc.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2000-2003 LSI Logic Corporation.
+ * Copyright (c) 2000-2004 LSI Logic Corporation.
*
*
* Name: mpi_fc.h
* Title: MPI Fibre Channel messages and structures
* Creation Date: June 12, 2000
*
- * mpi_fc.h Version: 01.05.xx
+ * mpi_fc.h Version: 01.05.01
*
* Version History
* ---------------
@@ -36,6 +36,9 @@
* 09-28-01 01.02.02 Change name of reserved field in
* MSG_LINK_SERVICE_RSP_REPLY.
* 05-31-02 01.02.03 Adding AliasIndex to FC Direct Access requests.
+ * 01-16-04 01.02.04 Added define for MPI_FC_PRIM_SEND_FLAGS_ML_RESET_LINK.
+ * 05-11-04 01.03.01 Original release for MPI v1.3.
+ * 08-19-04 01.05.01 Original release for MPI v1.5.
* --------------------------------------------------------------------------
*/
diff --git a/drivers/message/fusion/lsi/mpi_history.txt b/drivers/message/fusion/lsi/mpi_history.txt
index 0deb7721e93..c9edbee41ed 100644
--- a/drivers/message/fusion/lsi/mpi_history.txt
+++ b/drivers/message/fusion/lsi/mpi_history.txt
@@ -3,25 +3,28 @@
MPI Header File Change History
==============================
- Copyright (c) 2000-2001 LSI Logic Corporation.
+ Copyright (c) 2000-2005 LSI Logic Corporation.
---------------------------------------
- Header Set Release Version: 01.01.10
- Header Set Release Date: 04-09-01
+ Header Set Release Version: 01.05.09
+ Header Set Release Date: 03-11-05
---------------------------------------
Filename Current version Prior version
---------- --------------- -------------
- mpi.h 01.01.07 01.01.06
- mpi_ioc.h 01.01.07 01.01.06
- mpi_cnfg.h 01.01.11 01.01.10
- mpi_init.h 01.01.05 01.01.04
- mpi_targ.h 01.01.04 01.01.04
- mpi_fc.h 01.01.07 01.01.06
- mpi_lan.h 01.01.03 01.01.03
- mpi_raid.h 01.01.02 01.01.02
- mpi_type.h 01.01.02 01.01.02
- mpi_history.txt 01.01.09 01.01.09
+ mpi.h 01.05.07 01.05.06
+ mpi_ioc.h 01.05.08 01.05.07
+ mpi_cnfg.h 01.05.08 01.05.07
+ mpi_init.h 01.05.04 01.05.03
+ mpi_targ.h 01.05.04 01.05.03
+ mpi_fc.h 01.05.01 01.05.01
+ mpi_lan.h 01.05.01 01.05.01
+ mpi_raid.h 01.05.02 01.05.02
+ mpi_tool.h 01.05.03 01.05.03
+ mpi_inb.h 01.05.01 01.05.01
+ mpi_sas.h 01.05.01 01.05.01
+ mpi_type.h 01.05.01 01.05.01
+ mpi_history.txt 01.05.09 01.05.08
* Date Version Description
@@ -53,6 +56,38 @@ mpi.h
* Added function codes for RAID.
* 04-09-01 01.01.07 Added alternate define for MPI_DOORBELL_ACTIVE,
* MPI_DOORBELL_USED, to better match the spec.
+ * 08-08-01 01.02.01 Original release for v1.2 work.
+ * Changed MPI_VERSION_MINOR from 0x01 to 0x02.
+ * Added define MPI_FUNCTION_TOOLBOX.
+ * 09-28-01 01.02.02 New function code MPI_SCSI_ENCLOSURE_PROCESSOR.
+ * 11-01-01 01.02.03 Changed name to MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR.
+ * 03-14-02 01.02.04 Added MPI_HEADER_VERSION_ defines.
+ * 05-31-02 01.02.05 Bumped MPI_HEADER_VERSION_UNIT.
+ * 07-12-02 01.02.06 Added define for MPI_FUNCTION_MAILBOX.
+ * 09-16-02 01.02.07 Bumped value for MPI_HEADER_VERSION_UNIT.
+ * 11-15-02 01.02.08 Added define MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX and
+ * obsoleted define MPI_IOCSTATUS_TARGET_INVALID_IOCINDEX.
+ * 04-01-03 01.02.09 New IOCStatus code: MPI_IOCSTATUS_FC_EXCHANGE_CANCELED
+ * 06-26-03 01.02.10 Bumped MPI_HEADER_VERSION_UNIT value.
+ * 01-16-04 01.02.11 Added define for MPI_IOCLOGINFO_TYPE_SHIFT.
+ * 04-29-04 01.02.12 Added function codes for MPI_FUNCTION_DIAG_BUFFER_POST
+ * and MPI_FUNCTION_DIAG_RELEASE.
+ * Added MPI_IOCSTATUS_DIAGNOSTIC_RELEASED define.
+ * Bumped MPI_HEADER_VERSION_UNIT value.
+ * 05-11-04 01.03.01 Bumped MPI_VERSION_MINOR for MPI v1.3.
+ * Added codes for Inband.
+ * 08-19-04 01.05.01 Added defines for Host Buffer Access Control doorbell.
+ * Added define for offset of High Priority Request Queue.
+ * Added new function codes and new IOCStatus codes.
+ * Added a IOCLogInfo type of SAS.
+ * 12-07-04 01.05.02 Bumped MPI_HEADER_VERSION_UNIT.
+ * 12-09-04 01.05.03 Bumped MPI_HEADER_VERSION_UNIT.
+ * 01-15-05 01.05.04 Bumped MPI_HEADER_VERSION_UNIT.
+ * 02-09-05 01.05.05 Bumped MPI_HEADER_VERSION_UNIT.
+ * 02-22-05 01.05.06 Bumped MPI_HEADER_VERSION_UNIT.
+ * 03-11-05 01.05.07 Removed function codes for SCSI IO 32 and
+ * TargetAssistExtended requests.
+ * Removed EEDP IOCStatus codes.
* --------------------------------------------------------------------------
mpi_ioc.h
@@ -81,6 +116,49 @@ mpi_ioc.h
* 03-27-01 01.01.06 Added defines for ProductId field of MPI_FW_HEADER.
* Added structure offset comments.
* 04-09-01 01.01.07 Added structure EVENT_DATA_EVENT_CHANGE.
+ * 08-08-01 01.02.01 Original release for v1.2 work.
+ * New format for FWVersion and ProductId in
+ * MSG_IOC_FACTS_REPLY and MPI_FW_HEADER.
+ * 08-31-01 01.02.02 Addded event MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE and
+ * related structure and defines.
+ * Added event MPI_EVENT_ON_BUS_TIMER_EXPIRED.
+ * Added MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE.
+ * Replaced a reserved field in MSG_IOC_FACTS_REPLY with
+ * IOCExceptions and changed DataImageSize to reserved.
+ * Added MPI_FW_DOWNLOAD_ITYPE_NVSTORE_DATA and
+ * MPI_FW_UPLOAD_ITYPE_NVDATA.
+ * 09-28-01 01.02.03 Modified Event Data for Integrated RAID.
+ * 11-01-01 01.02.04 Added defines for MPI_EXT_IMAGE_HEADER ImageType field.
+ * 03-14-02 01.02.05 Added HeaderVersion field to MSG_IOC_FACTS_REPLY.
+ * 05-31-02 01.02.06 Added define for
+ * MPI_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID.
+ * Added AliasIndex to EVENT_DATA_LOGOUT structure.
+ * 04-01-03 01.02.07 Added defines for MPI_FW_HEADER_SIGNATURE_.
+ * 06-26-03 01.02.08 Added new values to the product family defines.
+ * 04-29-04 01.02.09 Added IOCCapabilities field to MSG_IOC_FACTS_REPLY and
+ * added related defines.
+ * 05-11-04 01.03.01 Original release for MPI v1.3.
+ * 08-19-04 01.05.01 Added four new fields to MSG_IOC_INIT.
+ * Added three new fields to MSG_IOC_FACTS_REPLY.
+ * Defined four new bits for the IOCCapabilities field of
+ * the IOCFacts reply.
+ * Added two new PortTypes for the PortFacts reply.
+ * Added six new events along with their EventData
+ * structures.
+ * Added a new MsgFlag to the FwDownload request to
+ * indicate last segment.
+ * Defined a new image type of boot loader.
+ * Added FW family codes for SAS product families.
+ * 10-05-04 01.05.02 Added ReplyFifoHostSignalingAddr field to
+ * MSG_IOC_FACTS_REPLY.
+ * 12-07-04 01.05.03 Added more defines for SAS Discovery Error event.
+ * 12-09-04 01.05.04 Added Unsupported device to SAS Device event.
+ * 01-15-05 01.05.05 Added event data for SAS SES Event.
+ * 02-09-05 01.05.06 Added MPI_FW_UPLOAD_ITYPE_FW_BACKUP define.
+ * 02-22-05 01.05.07 Added Host Page Buffer Persistent flag to IOC Facts
+ * Reply and IOC Init Request.
+ * 03-11-05 01.05.08 Added family code for 1068E family.
+ * Removed IOCFacts Reply EEDP Capability bit.
* --------------------------------------------------------------------------
mpi_cnfg.h
@@ -142,6 +220,166 @@ mpi_cnfg.h
* Added IO Unit Page 3.
* Modified defines for Scsi Port Page 2.
* Modified RAID Volume Pages.
+ * 08-08-01 01.02.01 Original release for v1.2 work.
+ * Added SepID and SepBus to RVP2 IMPhysicalDisk struct.
+ * Added defines for the SEP bits in RVP2 VolumeSettings.
+ * Modified the DeviceSettings field in RVP2 to use the
+ * proper structure.
+ * Added defines for SES, SAF-TE, and cross channel for
+ * IOCPage2 CapabilitiesFlags.
+ * Removed define for MPI_IOUNITPAGE2_FLAGS_RAID_DISABLE.
+ * Removed define for
+ * MPI_SCSIPORTPAGE2_PORT_FLAGS_PARITY_ENABLE.
+ * Added define for MPI_CONFIG_PAGEATTR_RO_PERSISTENT.
+ * 08-29-01 01.02.02 Fixed value for MPI_MANUFACTPAGE_DEVID_53C1035.
+ * Added defines for MPI_FCPORTPAGE1_FLAGS_HARD_ALPA_ONLY
+ * and MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY.
+ * Removed MPI_SCSIPORTPAGE0_CAP_PACING_TRANSFERS,
+ * MPI_SCSIDEVPAGE0_NP_PACING_TRANSFERS, and
+ * MPI_SCSIDEVPAGE1_RP_PACING_TRANSFERS, and
+ * MPI_SCSIDEVPAGE1_CONF_PPR_ALLOWED.
+ * Added defines for MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED
+ * and MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED.
+ * Added OnBusTimerValue to CONFIG_PAGE_SCSI_PORT_1.
+ * Added rejected bits to SCSI Device Page 0 Information.
+ * Increased size of ALPA array in FC Port Page 2 by one
+ * and removed a one byte reserved field.
+ * 09-28-01 01.02.03 Swapped NegWireSpeedLow and NegWireSpeedLow in
+ * CONFIG_PAGE_LAN_1 to match preferred 64-bit ordering.
+ * Added structures for Manufacturing Page 4, IO Unit
+ * Page 3, IOC Page 3, IOC Page 4, RAID Volume Page 0, and
+ * RAID PhysDisk Page 0.
+ * 10-04-01 01.02.04 Added define for MPI_CONFIG_PAGETYPE_RAID_PHYSDISK.
+ * Modified some of the new defines to make them 32
+ * character unique.
+ * Modified how variable length pages (arrays) are defined.
+ * Added generic defines for hot spare pools and RAID
+ * volume types.
+ * 11-01-01 01.02.05 Added define for MPI_IOUNITPAGE1_DISABLE_IR.
+ * 03-14-02 01.02.06 Added PCISlotNum field to CONFIG_PAGE_IOC_1 along with
+ * related define, and bumped the page version define.
+ * 05-31-02 01.02.07 Added a Flags field to CONFIG_PAGE_IOC_2_RAID_VOL in a
+ * reserved byte and added a define.
+ * Added define for
+ * MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE.
+ * Added new config page: CONFIG_PAGE_IOC_5.
+ * Added MaxAliases, MaxHardAliases, and NumCurrentAliases
+ * fields to CONFIG_PAGE_FC_PORT_0.
+ * Added AltConnector and NumRequestedAliases fields to
+ * CONFIG_PAGE_FC_PORT_1.
+ * Added new config page: CONFIG_PAGE_FC_PORT_10.
+ * 07-12-02 01.02.08 Added more MPI_MANUFACTPAGE_DEVID_ defines.
+ * Added additional MPI_SCSIDEVPAGE0_NP_ defines.
+ * Added more MPI_SCSIDEVPAGE1_RP_ defines.
+ * Added define for
+ * MPI_SCSIDEVPAGE1_CONF_EXTENDED_PARAMS_ENABLE.
+ * Added new config page: CONFIG_PAGE_SCSI_DEVICE_3.
+ * Modified MPI_FCPORTPAGE5_FLAGS_ defines.
+ * 09-16-02 01.02.09 Added MPI_SCSIDEVPAGE1_CONF_FORCE_PPR_MSG define.
+ * 11-15-02 01.02.10 Added ConnectedID defines for CONFIG_PAGE_SCSI_PORT_0.
+ * Added more Flags defines for CONFIG_PAGE_FC_PORT_1.
+ * Added more Flags defines for CONFIG_PAGE_FC_DEVICE_0.
+ * 04-01-03 01.02.11 Added RR_TOV field and additional Flags defines for
+ * CONFIG_PAGE_FC_PORT_1.
+ * Added define MPI_FCPORTPAGE5_FLAGS_DISABLE to disable
+ * an alias.
+ * Added more device id defines.
+ * 06-26-03 01.02.12 Added MPI_IOUNITPAGE1_IR_USE_STATIC_VOLUME_ID define.
+ * Added TargetConfig and IDConfig fields to
+ * CONFIG_PAGE_SCSI_PORT_1.
+ * Added more PortFlags defines for CONFIG_PAGE_SCSI_PORT_2
+ * to control DV.
+ * Added more Flags defines for CONFIG_PAGE_FC_PORT_1.
+ * In CONFIG_PAGE_FC_DEVICE_0, replaced Reserved1 field
+ * with ADISCHardALPA.
+ * Added MPI_FC_DEVICE_PAGE0_PROT_FCP_RETRY define.
+ * 01-16-04 01.02.13 Added InitiatorDeviceTimeout and InitiatorIoPendTimeout
+ * fields and related defines to CONFIG_PAGE_FC_PORT_1.
+ * Added define for
+ * MPI_FCPORTPAGE1_FLAGS_SOFT_ALPA_FALLBACK.
+ * Added new fields to the substructures of
+ * CONFIG_PAGE_FC_PORT_10.
+ * 04-29-04 01.02.14 Added define for IDP bit for CONFIG_PAGE_SCSI_PORT_0,
+ * CONFIG_PAGE_SCSI_DEVICE_0, and
+ * CONFIG_PAGE_SCSI_DEVICE_1. Also bumped Page Version for
+ * these pages.
+ * 05-11-04 01.03.01 Added structure for CONFIG_PAGE_INBAND_0.
+ * 08-19-04 01.05.01 Modified MSG_CONFIG request to support extended config
+ * pages.
+ * Added a new structure for extended config page header.
+ * Added new extended config pages types and structures for
+ * SAS IO Unit, SAS Expander, SAS Device, and SAS PHY.
+ * Replaced a reserved byte in CONFIG_PAGE_MANUFACTURING_4
+ * to add a Flags field.
+ * Two new Manufacturing config pages (5 and 6).
+ * Two new bits defined for IO Unit Page 1 Flags field.
+ * Modified CONFIG_PAGE_IO_UNIT_2 to add three new fields
+ * to specify the BIOS boot device.
+ * Four new Flags bits defined for IO Unit Page 2.
+ * Added IO Unit Page 4.
+ * Added EEDP Flags settings to IOC Page 1.
+ * Added new BIOS Page 1 config page.
+ * 10-05-04 01.05.02 Added define for
+ * MPI_IOCPAGE1_INITIATOR_CONTEXT_REPLY_DISABLE.
+ * Added new Flags field to CONFIG_PAGE_MANUFACTURING_5 and
+ * associated defines.
+ * Added more defines for SAS IO Unit Page 0
+ * DiscoveryStatus field.
+ * Added define for MPI_SAS_IOUNIT0_DS_SUBTRACTIVE_LINK
+ * and MPI_SAS_IOUNIT0_DS_TABLE_LINK.
+ * Added defines for Physical Mapping Modes to SAS IO Unit
+ * Page 2.
+ * Added define for
+ * MPI_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH.
+ * 10-27-04 01.05.03 Added defines for new SAS PHY page addressing mode.
+ * Added defines for MaxTargetSpinUp to BIOS Page 1.
+ * Added 5 new ControlFlags defines for SAS IO Unit
+ * Page 1.
+ * Added MaxNumPhysicalMappedIDs field to SAS IO Unit
+ * Page 2.
+ * Added AccessStatus field to SAS Device Page 0 and added
+ * new Flags bits for supported SATA features.
+ * 12-07-04 01.05.04 Added config page structures for BIOS Page 2, RAID
+ * Volume Page 1, and RAID Physical Disk Page 1.
+ * Replaced IO Unit Page 1 BootTargetID,BootBus, and
+ * BootAdapterNum with reserved field.
+ * Added DataScrubRate and ResyncRate to RAID Volume
+ * Page 0.
+ * Added MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT
+ * define.
+ * 12-09-04 01.05.05 Added Target Mode Large CDB Enable to FC Port Page 1
+ * Flags field.
+ * Added Auto Port Config flag define for SAS IOUNIT
+ * Page 1 ControlFlags.
+ * Added Disabled bad Phy define to Expander Page 1
+ * Discovery Info field.
+ * Added SAS/SATA device support to SAS IOUnit Page 1
+ * ControlFlags.
+ * Added Unsupported device to SAS Dev Page 0 Flags field
+ * Added disable use SATA Hash Address for SAS IOUNIT
+ * page 1 in ControlFields.
+ * 01-15-05 01.05.06 Added defaults for data scrub rate and resync rate to
+ * Manufacturing Page 4.
+ * Added new defines for BIOS Page 1 IOCSettings field.
+ * Added ExtDiskIdentifier field to RAID Physical Disk
+ * Page 0.
+ * Added new defines for SAS IO Unit Page 1 ControlFlags
+ * and to SAS Device Page 0 Flags to control SATA devices.
+ * Added defines and structures for the new Log Page 0, a
+ * new type of configuration page.
+ * 02-09-05 01.05.07 Added InactiveStatus field to RAID Volume Page 0.
+ * Added WWID field to RAID Volume Page 1.
+ * Added PhysicalPort field to SAS Expander pages 0 and 1.
+ * 03-11-05 01.05.08 Removed the EEDP flags from IOC Page 1.
+ * Added Enclosure/Slot boot device format to BIOS Page 2.
+ * New status value for RAID Volume Page 0 VolumeStatus
+ * (VolumeState subfield).
+ * New value for RAID Physical Page 0 InactiveStatus.
+ * Added Inactive Volume Member flag RAID Physical Disk
+ * Page 0 PhysDiskStatus field.
+ * New physical mapping mode in SAS IO Unit Page 2.
+ * Added CONFIG_PAGE_SAS_ENCLOSURE_0.
+ * Added Slot and Enclosure fields to SAS Device Page 0.
* --------------------------------------------------------------------------
mpi_init.h
@@ -154,6 +392,32 @@ mpi_init.h
* 02-20-01 01.01.03 Started using MPI_POINTER.
* 03-27-01 01.01.04 Added structure offset comments.
* 04-10-01 01.01.05 Added new MsgFlag for MSG_SCSI_TASK_MGMT.
+ * 08-08-01 01.02.01 Original release for v1.2 work.
+ * 08-29-01 01.02.02 Added MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET.
+ * Added MPI_SCSI_STATE_QUEUE_TAG_REJECTED for
+ * MSG_SCSI_IO_REPLY.
+ * 09-28-01 01.02.03 Added structures and defines for SCSI Enclosure
+ * Processor messages.
+ * 10-04-01 01.02.04 Added defines for SEP request Action field.
+ * 05-31-02 01.02.05 Added MPI_SCSIIO_MSGFLGS_CMD_DETERMINES_DATA_DIR define
+ * for SCSI IO requests.
+ * 11-15-02 01.02.06 Added special extended SCSI Status defines for FCP.
+ * 06-26-03 01.02.07 Added MPI_SCSI_STATUS_FCPEXT_UNASSIGNED define.
+ * 05-11-04 01.03.01 Original release for MPI v1.3.
+ * 08-19-04 01.05.01 Added MsgFlags defines for EEDP to SCSI IO request.
+ * Added new word to MSG_SCSI_IO_REPLY to add TaskTag field
+ * and a reserved U16.
+ * Added new MSG_SCSI_IO32_REQUEST structure.
+ * Added a TaskType of Clear Task Set to SCSI
+ * Task Management request.
+ * 12-07-04 01.05.02 Added support for Task Management Query Task.
+ * 01-15-05 01.05.03 Modified SCSI Enclosure Processor Request to support
+ * WWID addressing.
+ * 03-11-05 01.05.04 Removed EEDP flags from SCSI IO Request.
+ * Removed SCSI IO 32 Request.
+ * Modified SCSI Enclosure Processor Request and Reply to
+ * support Enclosure/Slot addressing rather than WWID
+ * addressing.
* --------------------------------------------------------------------------
mpi_targ.h
@@ -170,6 +434,33 @@ mpi_targ.h
* Added structures for MPI_TARGET_SCSI_SPI_CMD_BUFFER and
* MPI_TARGET_FCP_CMD_BUFFER.
* 03-27-01 01.01.04 Added structure offset comments.
+ * 08-08-01 01.02.01 Original release for v1.2 work.
+ * 09-28-01 01.02.02 Added structure for MPI_TARGET_SCSI_SPI_STATUS_IU.
+ * Added PriorityReason field to some replies and
+ * defined more PriorityReason codes.
+ * Added some defines for to support previous version
+ * of MPI.
+ * 10-04-01 01.02.03 Added PriorityReason to MSG_TARGET_ERROR_REPLY.
+ * 11-01-01 01.02.04 Added define for TARGET_STATUS_SEND_FLAGS_HIGH_PRIORITY.
+ * 03-14-02 01.02.05 Modified MPI_TARGET_FCP_RSP_BUFFER to get the proper
+ * byte ordering.
+ * 05-31-02 01.02.06 Modified TARGET_MODE_REPLY_ALIAS_MASK to only include
+ * one bit.
+ * Added AliasIndex field to MPI_TARGET_FCP_CMD_BUFFER.
+ * 09-16-02 01.02.07 Added flags for confirmed completion.
+ * Added PRIORITY_REASON_TARGET_BUSY.
+ * 11-15-02 01.02.08 Added AliasID field to MPI_TARGET_SCSI_SPI_CMD_BUFFER.
+ * 04-01-03 01.02.09 Added OptionalOxid field to MPI_TARGET_FCP_CMD_BUFFER.
+ * 05-11-04 01.03.01 Original release for MPI v1.3.
+ * 08-19-04 01.05.01 Added new request message structures for
+ * MSG_TARGET_CMD_BUF_POST_BASE_REQUEST,
+ * MSG_TARGET_CMD_BUF_POST_LIST_REQUEST, and
+ * MSG_TARGET_ASSIST_EXT_REQUEST.
+ * Added new structures for SAS SSP Command buffer, SSP
+ * Task buffer, and SSP Status IU.
+ * 10-05-04 01.05.02 MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY added.
+ * 02-22-05 01.05.03 Changed a comment.
+ * 03-11-05 01.05.04 Removed TargetAssistExtended Request.
* --------------------------------------------------------------------------
mpi_fc.h
@@ -192,6 +483,13 @@ mpi_fc.h
* Added MPI_FC_PRIM_SEND_FLAGS_RESET_LINK define.
* Added structure offset comments.
* 04-09-01 01.01.07 Added RspLength field to MSG_LINK_SERVICE_RSP_REQUEST.
+ * 08-08-01 01.02.01 Original release for v1.2 work.
+ * 09-28-01 01.02.02 Change name of reserved field in
+ * MSG_LINK_SERVICE_RSP_REPLY.
+ * 05-31-02 01.02.03 Adding AliasIndex to FC Direct Access requests.
+ * 01-16-04 01.02.04 Added define for MPI_FC_PRIM_SEND_FLAGS_ML_RESET_LINK.
+ * 05-11-04 01.03.01 Original release for MPI v1.3.
+ * 08-19-04 01.05.01 Original release for MPI v1.5.
* --------------------------------------------------------------------------
mpi_lan.h
@@ -209,11 +507,56 @@ mpi_lan.h
* 11-02-00 01.01.01 Original release for post 1.0 work
* 02-20-01 01.01.02 Started using MPI_POINTER.
* 03-27-01 01.01.03 Added structure offset comments.
+ * 08-08-01 01.02.01 Original release for v1.2 work.
+ * 05-11-04 01.03.01 Original release for MPI v1.3.
+ * 08-19-04 01.05.01 Original release for MPI v1.5.
* --------------------------------------------------------------------------
mpi_raid.h
* 02-27-01 01.01.01 Original release for this file.
* 03-27-01 01.01.02 Added structure offset comments.
+ * 08-08-01 01.02.01 Original release for v1.2 work.
+ * 08-29-01 01.02.02 Added DIAG_DATA_UPLOAD_HEADER and related defines.
+ * 09-28-01 01.02.02 Major rework for MPI v1.2 Integrated RAID changes.
+ * 10-04-01 01.02.03 Added ActionData defines for
+ * MPI_RAID_ACTION_DELETE_VOLUME action.
+ * 11-01-01 01.02.04 Added define for MPI_RAID_ACTION_ADATA_DO_NOT_SYNC.
+ * 03-14-02 01.02.05 Added define for MPI_RAID_ACTION_ADATA_LOW_LEVEL_INIT.
+ * 05-07-02 01.02.06 Added define for MPI_RAID_ACTION_ACTIVATE_VOLUME,
+ * MPI_RAID_ACTION_INACTIVATE_VOLUME, and
+ * MPI_RAID_ACTION_ADATA_INACTIVATE_ALL.
+ * 07-12-02 01.02.07 Added structures for Mailbox request and reply.
+ * 11-15-02 01.02.08 Added missing MsgContext field to MSG_MAILBOX_REQUEST.
+ * 04-01-03 01.02.09 New action data option flag for
+ * MPI_RAID_ACTION_DELETE_VOLUME.
+ * 05-11-04 01.03.01 Original release for MPI v1.3.
+ * 08-19-04 01.05.01 Original release for MPI v1.5.
+ * 01-15-05 01.05.02 Added defines for the two new RAID Actions for
+ * _SET_RESYNC_RATE and _SET_DATA_SCRUB_RATE.
+ * --------------------------------------------------------------------------
+
+mpi_tool.h
+ * 08-08-01 01.02.01 Original release.
+ * 08-29-01 01.02.02 Added DIAG_DATA_UPLOAD_HEADER and related defines.
+ * 01-16-04 01.02.03 Added defines and structures for new tools
+ *. MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL and
+ * MPI_TOOLBOX_FC_MANAGEMENT_TOOL.
+ * 04-29-04 01.02.04 Added message structures for Diagnostic Buffer Post and
+ * Diagnostic Release requests and replies.
+ * 05-11-04 01.03.01 Original release for MPI v1.3.
+ * 08-19-04 01.05.01 Original release for MPI v1.5.
+ * 10-06-04 01.05.02 Added define for MPI_DIAG_BUF_TYPE_COUNT.
+ * 02-09-05 01.05.03 Added frame size option to FC management tool.
+ * Added Beacon tool to the Toolbox.
+ * --------------------------------------------------------------------------
+
+mpi_inb.h
+ * 05-11-04 01.03.01 Original release.
+ * 08-19-04 01.05.01 Original release for MPI v1.5.
+ * --------------------------------------------------------------------------
+
+mpi_sas.h
+ * 08-19-04 01.05.01 Original release.
* --------------------------------------------------------------------------
mpi_type.h
@@ -221,21 +564,83 @@ mpi_type.h
* 06-06-00 01.00.01 Update version number for 1.0 release.
* 11-02-00 01.01.01 Original release for post 1.0 work
* 02-20-01 01.01.02 Added define and ifdef for MPI_POINTER.
+ * 08-08-01 01.02.01 Original release for v1.2 work.
+ * 05-11-04 01.03.01 Original release for MPI v1.3.
+ * 08-19-04 01.05.01 Original release for MPI v1.5.
* --------------------------------------------------------------------------
mpi_history.txt Parts list history
-Filename 01.01.10
+Filename 01.05.09
---------- --------
-mpi.h 01.01.07
-mpi_ioc.h 01.01.07
-mpi_cnfg.h 01.01.11
-mpi_init.h 01.01.05
-mpi_targ.h 01.01.04
-mpi_fc.h 01.01.07
-mpi_lan.h 01.01.03
-mpi_raid.h 01.01.02
-mpi_type.h 01.01.02
+mpi.h 01.05.07
+mpi_ioc.h 01.05.08
+mpi_cnfg.h 01.05.08
+mpi_init.h 01.05.04
+mpi_targ.h 01.05.04
+mpi_fc.h 01.05.01
+mpi_lan.h 01.05.01
+mpi_raid.h 01.05.02
+mpi_tool.h 01.05.03
+mpi_inb.h 01.05.01
+mpi_sas.h 01.05.01
+mpi_type.h 01.05.01
+
+Filename 01.05.08 01.05.07 01.05.06 01.05.05 01.05.04 01.05.03
+---------- -------- -------- -------- -------- -------- --------
+mpi.h 01.05.06 01.05.05 01.05.04 01.05.03 01.05.02 01.05.01
+mpi_ioc.h 01.05.07 01.05.06 01.05.05 01.05.04 01.05.03 01.05.02
+mpi_cnfg.h 01.05.07 01.05.07 01.05.06 01.05.05 01.05.04 01.05.03
+mpi_init.h 01.05.03 01.05.03 01.05.03 01.05.02 01.05.02 01.05.01
+mpi_targ.h 01.05.03 01.05.02 01.05.02 01.05.02 01.05.02 01.05.02
+mpi_fc.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01
+mpi_lan.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01
+mpi_raid.h 01.05.02 01.05.02 01.05.02 01.05.01 01.05.01 01.05.01
+mpi_tool.h 01.05.03 01.05.03 01.05.02 01.05.02 01.05.02 01.05.02
+mpi_inb.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01
+mpi_sas.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01
+mpi_type.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01
+
+Filename 01.05.02 01.05.01 01.03.01 01.02.14 01.02.13 01.02.12
+---------- -------- -------- -------- -------- -------- --------
+mpi.h 01.05.01 01.05.01 01.03.01 01.02.12 01.02.11 01.02.10
+mpi_ioc.h 01.05.02 01.05.01 01.03.01 01.02.09 01.02.08 01.02.08
+mpi_cnfg.h 01.05.02 01.05.01 01.03.01 01.02.14 01.02.13 01.02.12
+mpi_init.h 01.05.01 01.05.01 01.03.01 01.02.07 01.02.07 01.02.07
+mpi_targ.h 01.05.02 01.05.01 01.03.01 01.02.09 01.02.09 01.02.09
+mpi_fc.h 01.05.01 01.05.01 01.03.01 01.02.04 01.02.04 01.02.03
+mpi_lan.h 01.05.01 01.05.01 01.03.01 01.02.01 01.02.01 01.02.01
+mpi_raid.h 01.05.01 01.05.01 01.03.01 01.02.09 01.02.09 01.02.09
+mpi_tool.h 01.05.02 01.05.01 01.03.01 01.02.01 01.02.01 01.02.01
+mpi_inb.h 01.05.01 01.05.01 01.03.01
+mpi_sas.h 01.05.01 01.05.01
+mpi_type.h 01.05.01 01.05.01 01.03.01 01.02.04 01.02.03 01.02.02
+
+Filename 01.02.11 01.02.10 01.02.09 01.02.08 01.02.07 01.02.06
+---------- -------- -------- -------- -------- -------- --------
+mpi.h 01.02.09 01.02.08 01.02.07 01.02.06 01.02.05 01.02.04
+mpi_ioc.h 01.02.07 01.02.06 01.02.06 01.02.06 01.02.06 01.02.05
+mpi_cnfg.h 01.02.11 01.02.10 01.02.09 01.02.08 01.02.07 01.02.06
+mpi_init.h 01.02.06 01.02.06 01.02.05 01.02.05 01.02.05 01.02.04
+mpi_targ.h 01.02.09 01.02.08 01.02.07 01.02.06 01.02.06 01.02.05
+mpi_fc.h 01.02.03 01.02.03 01.02.03 01.02.03 01.02.03 01.02.02
+mpi_lan.h 01.02.01 01.02.01 01.02.01 01.02.01 01.02.01 01.02.01
+mpi_raid.h 01.02.09 01.02.08 01.02.07 01.02.07 01.02.06 01.02.05
+mpi_tool.h 01.02.01 01.02.01 01.02.01 01.02.01 01.02.01 01.02.01
+mpi_type.h 01.02.02 01.02.02 01.02.02 01.02.02 01.02.02 01.02.02
+
+Filename 01.02.05 01.02.04 01.02.03 01.02.02 01.02.01 01.01.10
+---------- -------- -------- -------- -------- -------- --------
+mpi.h 01.02.03 01.02.02 01.02.02 01.02.01 01.02.01 01.01.07
+mpi_ioc.h 01.02.04 01.02.03 01.02.03 01.02.02 01.02.01 01.01.07
+mpi_cnfg.h 01.02.05 01.02.04 01.02.03 01.02.02 01.02.01 01.01.11
+mpi_init.h 01.02.04 01.02.04 01.02.03 01.02.02 01.02.01 01.01.05
+mpi_targ.h 01.02.04 01.02.03 01.02.02 01.02.01 01.02.01 01.01.04
+mpi_fc.h 01.02.02 01.02.02 01.02.02 01.02.01 01.02.01 01.01.07
+mpi_lan.h 01.02.01 01.02.01 01.02.01 01.02.01 01.02.01 01.01.03
+mpi_raid.h 01.02.04 01.02.03 01.02.02 01.02.01 01.02.01 01.01.02
+mpi_tool.h 01.02.02 01.02.02 01.02.02 01.02.02 01.02.01
+mpi_type.h 01.02.02 01.02.02 01.02.02 01.02.02 01.02.01 01.01.02
Filename 01.01.09 01.01.08 01.01.07 01.01.06 01.01.05 01.01.04
---------- -------- -------- -------- -------- -------- --------
diff --git a/drivers/message/fusion/lsi/mpi_inb.h b/drivers/message/fusion/lsi/mpi_inb.h
index dae29fbed56..ff167309ba2 100644
--- a/drivers/message/fusion/lsi/mpi_inb.h
+++ b/drivers/message/fusion/lsi/mpi_inb.h
@@ -1,19 +1,20 @@
/*
- * Copyright (c) 2003 LSI Logic Corporation.
+ * Copyright (c) 2003-2004 LSI Logic Corporation.
*
*
* Name: mpi_inb.h
* Title: MPI Inband structures and definitions
* Creation Date: September 30, 2003
*
- * mpi_inb.h Version: 01.03.xx
+ * mpi_inb.h Version: 01.05.01
*
* Version History
* ---------------
*
* Date Version Description
* -------- -------- ------------------------------------------------------
- * ??-??-?? 01.03.01 Original release.
+ * 05-11-04 01.03.01 Original release.
+ * 08-19-04 01.05.01 Original release for MPI v1.5.
* --------------------------------------------------------------------------
*/
diff --git a/drivers/message/fusion/lsi/mpi_init.h b/drivers/message/fusion/lsi/mpi_init.h
index b3c95fd7256..aca035801a8 100644
--- a/drivers/message/fusion/lsi/mpi_init.h
+++ b/drivers/message/fusion/lsi/mpi_init.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2000-2003 LSI Logic Corporation.
+ * Copyright (c) 2000-2005 LSI Logic Corporation.
*
*
* Name: mpi_init.h
* Title: MPI initiator mode messages and structures
* Creation Date: June 8, 2000
*
- * mpi_init.h Version: 01.05.xx
+ * mpi_init.h Version: 01.05.04
*
* Version History
* ---------------
@@ -33,6 +33,21 @@
* for SCSI IO requests.
* 11-15-02 01.02.06 Added special extended SCSI Status defines for FCP.
* 06-26-03 01.02.07 Added MPI_SCSI_STATUS_FCPEXT_UNASSIGNED define.
+ * 05-11-04 01.03.01 Original release for MPI v1.3.
+ * 08-19-04 01.05.01 Added MsgFlags defines for EEDP to SCSI IO request.
+ * Added new word to MSG_SCSI_IO_REPLY to add TaskTag field
+ * and a reserved U16.
+ * Added new MSG_SCSI_IO32_REQUEST structure.
+ * Added a TaskType of Clear Task Set to SCSI
+ * Task Management request.
+ * 12-07-04 01.05.02 Added support for Task Management Query Task.
+ * 01-15-05 01.05.03 Modified SCSI Enclosure Processor Request to support
+ * WWID addressing.
+ * 03-11-05 01.05.04 Removed EEDP flags from SCSI IO Request.
+ * Removed SCSI IO 32 Request.
+ * Modified SCSI Enclosure Processor Request and Reply to
+ * support Enclosure/Slot addressing rather than WWID
+ * addressing.
* --------------------------------------------------------------------------
*/
@@ -76,20 +91,12 @@ typedef struct _MSG_SCSI_IO_REQUEST
#define MPI_SCSIIO_MSGFLGS_SENSE_WIDTH (0x01)
#define MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_32 (0x00)
#define MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_64 (0x01)
+
#define MPI_SCSIIO_MSGFLGS_SENSE_LOCATION (0x02)
#define MPI_SCSIIO_MSGFLGS_SENSE_LOC_HOST (0x00)
#define MPI_SCSIIO_MSGFLGS_SENSE_LOC_IOC (0x02)
-#define MPI_SCSIIO_MSGFLGS_CMD_DETERMINES_DATA_DIR (0x04)
-#define MPI_SCSIIO_MSGFLGS_EEDP_TYPE_MASK (0xE0)
-#define MPI_SCSIIO_MSGFLGS_EEDP_NONE (0x00)
-#define MPI_SCSIIO_MSGFLGS_EEDP_RDPROTECT_T10 (0x20)
-#define MPI_SCSIIO_MSGFLGS_EEDP_VRPROTECT_T10 (0x40)
-#define MPI_SCSIIO_MSGFLGS_EEDP_WRPROTECT_T10 (0x60)
-#define MPI_SCSIIO_MSGFLGS_EEDP_520_READ_MODE1 (0x20)
-#define MPI_SCSIIO_MSGFLGS_EEDP_520_WRITE_MODE1 (0x40)
-#define MPI_SCSIIO_MSGFLGS_EEDP_8_9_READ_MODE1 (0x60)
-#define MPI_SCSIIO_MSGFLGS_EEDP_8_9_WRITE_MODE1 (0x80)
+#define MPI_SCSIIO_MSGFLGS_CMD_DETERMINES_DATA_DIR (0x04)
/* SCSI IO LUN fields */
@@ -148,6 +155,8 @@ typedef struct _MSG_SCSI_IO_REPLY
U32 TransferCount; /* 14h */
U32 SenseCount; /* 18h */
U32 ResponseInfo; /* 1Ch */
+ U16 TaskTag; /* 20h */
+ U16 Reserved1; /* 22h */
} MSG_SCSI_IO_REPLY, MPI_POINTER PTR_MSG_SCSI_IO_REPLY,
SCSIIOReply_t, MPI_POINTER pSCSIIOReply_t;
@@ -190,32 +199,7 @@ typedef struct _MSG_SCSI_IO_REPLY
#define MPI_SCSI_RSP_INFO_TASK_MGMT_FAILED (0x05000000)
#define MPI_SCSI_RSP_INFO_SPI_LQ_INVALID_TYPE (0x06000000)
-
-/****************************************************************************/
-/* SCSI IO 32 Request message structure */
-/****************************************************************************/
-
-typedef struct _MSG_SCSI_IO32_REQUEST
-{
- U8 TargetID; /* 00h */
- U8 Bus; /* 01h */
- U8 ChainOffset; /* 02h */
- U8 Function; /* 03h */
- U8 CDBLength; /* 04h */
- U8 SenseBufferLength; /* 05h */
- U8 Reserved; /* 06h */
- U8 MsgFlags; /* 07h */
- U32 MsgContext; /* 08h */
- U8 LUN[8]; /* 0Ch */
- U32 Control; /* 14h */
- U8 CDB[32]; /* 18h */
- U32 DataLength; /* 38h */
- U32 SenseBufferLowAddr; /* 3Ch */
- SGE_IO_UNION SGL; /* 40h */
-} MSG_SCSI_IO32_REQUEST, MPI_POINTER PTR_MSG_SCSI_IO32_REQUEST,
- SCSIIO32Request_t, MPI_POINTER pSCSIIO32Request_t;
-
-/* SCSI IO 32 uses the same defines as above for SCSI IO */
+#define MPI_SCSI_TASKTAG_UNKNOWN (0xFFFF)
/****************************************************************************/
@@ -247,6 +231,7 @@ typedef struct _MSG_SCSI_TASK_MGMT
#define MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS (0x04)
#define MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET (0x05)
#define MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET (0x06)
+#define MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK (0x07)
/* MsgFlags bits */
#define MPI_SCSITASKMGMT_MSGFLAGS_TARGET_RESET_OPTION (0x00)
@@ -260,7 +245,7 @@ typedef struct _MSG_SCSI_TASK_MGMT_REPLY
U8 Bus; /* 01h */
U8 MsgLength; /* 02h */
U8 Function; /* 03h */
- U8 Reserved; /* 04h */
+ U8 ResponseCode; /* 04h */
U8 TaskType; /* 05h */
U8 Reserved1; /* 06h */
U8 MsgFlags; /* 07h */
@@ -272,6 +257,15 @@ typedef struct _MSG_SCSI_TASK_MGMT_REPLY
} MSG_SCSI_TASK_MGMT_REPLY, MPI_POINTER PTR_MSG_SCSI_TASK_MGMT_REPLY,
SCSITaskMgmtReply_t, MPI_POINTER pSCSITaskMgmtReply_t;
+/* ResponseCode values */
+#define MPI_SCSITASKMGMT_RSP_TM_COMPLETE (0x00)
+#define MPI_SCSITASKMGMT_RSP_INVALID_FRAME (0x02)
+#define MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED (0x04)
+#define MPI_SCSITASKMGMT_RSP_TM_FAILED (0x05)
+#define MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED (0x08)
+#define MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN (0x09)
+#define MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC (0x80)
+
/****************************************************************************/
/* SCSI Enclosure Processor messages */
@@ -284,11 +278,16 @@ typedef struct _MSG_SEP_REQUEST
U8 ChainOffset; /* 02h */
U8 Function; /* 03h */
U8 Action; /* 04h */
- U8 Reserved1; /* 05h */
- U8 Reserved2; /* 06h */
+ U8 Flags; /* 05h */
+ U8 Reserved1; /* 06h */
U8 MsgFlags; /* 07h */
U32 MsgContext; /* 08h */
U32 SlotStatus; /* 0Ch */
+ U32 Reserved2; /* 10h */
+ U32 Reserved3; /* 14h */
+ U32 Reserved4; /* 18h */
+ U16 Slot; /* 1Ch */
+ U16 EnclosureHandle; /* 1Eh */
} MSG_SEP_REQUEST, MPI_POINTER PTR_MSG_SEP_REQUEST,
SEPRequest_t, MPI_POINTER pSEPRequest_t;
@@ -296,6 +295,10 @@ typedef struct _MSG_SEP_REQUEST
#define MPI_SEP_REQ_ACTION_WRITE_STATUS (0x00)
#define MPI_SEP_REQ_ACTION_READ_STATUS (0x01)
+/* Flags defines */
+#define MPI_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS (0x01)
+#define MPI_SEP_REQ_FLAGS_BUS_TARGETID_ADDRESS (0x00)
+
/* SlotStatus bits for MSG_SEP_REQUEST */
#define MPI_SEP_REQ_SLOTSTATUS_NO_ERROR (0x00000001)
#define MPI_SEP_REQ_SLOTSTATUS_DEV_FAULTY (0x00000002)
@@ -332,6 +335,9 @@ typedef struct _MSG_SEP_REPLY
U16 IOCStatus; /* 0Eh */
U32 IOCLogInfo; /* 10h */
U32 SlotStatus; /* 14h */
+ U32 Reserved4; /* 18h */
+ U16 Slot; /* 1Ch */
+ U16 EnclosureHandle; /* 1Eh */
} MSG_SEP_REPLY, MPI_POINTER PTR_MSG_SEP_REPLY,
SEPReply_t, MPI_POINTER pSEPReply_t;
diff --git a/drivers/message/fusion/lsi/mpi_ioc.h b/drivers/message/fusion/lsi/mpi_ioc.h
index 82445d18b4d..f91eb4efe8c 100644
--- a/drivers/message/fusion/lsi/mpi_ioc.h
+++ b/drivers/message/fusion/lsi/mpi_ioc.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2000-2003 LSI Logic Corporation.
+ * Copyright (c) 2000-2005 LSI Logic Corporation.
*
*
* Name: mpi_ioc.h
* Title: MPI IOC, Port, Event, FW Download, and FW Upload messages
* Creation Date: August 11, 2000
*
- * mpi_ioc.h Version: 01.05.xx
+ * mpi_ioc.h Version: 01.05.08
*
* Version History
* ---------------
@@ -57,6 +57,30 @@
* Added AliasIndex to EVENT_DATA_LOGOUT structure.
* 04-01-03 01.02.07 Added defines for MPI_FW_HEADER_SIGNATURE_.
* 06-26-03 01.02.08 Added new values to the product family defines.
+ * 04-29-04 01.02.09 Added IOCCapabilities field to MSG_IOC_FACTS_REPLY and
+ * added related defines.
+ * 05-11-04 01.03.01 Original release for MPI v1.3.
+ * 08-19-04 01.05.01 Added four new fields to MSG_IOC_INIT.
+ * Added three new fields to MSG_IOC_FACTS_REPLY.
+ * Defined four new bits for the IOCCapabilities field of
+ * the IOCFacts reply.
+ * Added two new PortTypes for the PortFacts reply.
+ * Added six new events along with their EventData
+ * structures.
+ * Added a new MsgFlag to the FwDownload request to
+ * indicate last segment.
+ * Defined a new image type of boot loader.
+ * Added FW family codes for SAS product families.
+ * 10-05-04 01.05.02 Added ReplyFifoHostSignalingAddr field to
+ * MSG_IOC_FACTS_REPLY.
+ * 12-07-04 01.05.03 Added more defines for SAS Discovery Error event.
+ * 12-09-04 01.05.04 Added Unsupported device to SAS Device event.
+ * 01-15-05 01.05.05 Added event data for SAS SES Event.
+ * 02-09-05 01.05.06 Added MPI_FW_UPLOAD_ITYPE_FW_BACKUP define.
+ * 02-22-05 01.05.07 Added Host Page Buffer Persistent flag to IOC Facts
+ * Reply and IOC Init Request.
+ * 03-11-05 01.05.08 Added family code for 1068E family.
+ * Removed IOCFacts Reply EEDP Capability bit.
* --------------------------------------------------------------------------
*/
@@ -90,20 +114,37 @@ typedef struct _MSG_IOC_INIT
U32 HostMfaHighAddr; /* 10h */
U32 SenseBufferHighAddr; /* 14h */
U32 ReplyFifoHostSignalingAddr; /* 18h */
+ SGE_SIMPLE_UNION HostPageBufferSGE; /* 1Ch */
+ U16 MsgVersion; /* 28h */
+ U16 HeaderVersion; /* 2Ah */
} MSG_IOC_INIT, MPI_POINTER PTR_MSG_IOC_INIT,
IOCInit_t, MPI_POINTER pIOCInit_t;
/* WhoInit values */
-#define MPI_WHOINIT_NO_ONE (0x00)
-#define MPI_WHOINIT_SYSTEM_BIOS (0x01)
-#define MPI_WHOINIT_ROM_BIOS (0x02)
-#define MPI_WHOINIT_PCI_PEER (0x03)
-#define MPI_WHOINIT_HOST_DRIVER (0x04)
-#define MPI_WHOINIT_MANUFACTURER (0x05)
+#define MPI_WHOINIT_NO_ONE (0x00)
+#define MPI_WHOINIT_SYSTEM_BIOS (0x01)
+#define MPI_WHOINIT_ROM_BIOS (0x02)
+#define MPI_WHOINIT_PCI_PEER (0x03)
+#define MPI_WHOINIT_HOST_DRIVER (0x04)
+#define MPI_WHOINIT_MANUFACTURER (0x05)
/* Flags values */
-#define MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE (0x01)
-#define MPI_IOCINIT_FLAGS_REPLY_FIFO_HOST_SIGNAL (0x02)
+#define MPI_IOCINIT_FLAGS_HOST_PAGE_BUFFER_PERSISTENT (0x04)
+#define MPI_IOCINIT_FLAGS_REPLY_FIFO_HOST_SIGNAL (0x02)
+#define MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE (0x01)
+
+/* MsgVersion */
+#define MPI_IOCINIT_MSGVERSION_MAJOR_MASK (0xFF00)
+#define MPI_IOCINIT_MSGVERSION_MAJOR_SHIFT (8)
+#define MPI_IOCINIT_MSGVERSION_MINOR_MASK (0x00FF)
+#define MPI_IOCINIT_MSGVERSION_MINOR_SHIFT (0)
+
+/* HeaderVersion */
+#define MPI_IOCINIT_HEADERVERSION_UNIT_MASK (0xFF00)
+#define MPI_IOCINIT_HEADERVERSION_UNIT_SHIFT (8)
+#define MPI_IOCINIT_HEADERVERSION_DEV_MASK (0x00FF)
+#define MPI_IOCINIT_HEADERVERSION_DEV_SHIFT (0)
+
typedef struct _MSG_IOC_INIT_REPLY
{
@@ -187,32 +228,39 @@ typedef struct _MSG_IOC_FACTS_REPLY
MPI_FW_VERSION FWVersion; /* 38h */
U16 HighPriorityQueueDepth; /* 3Ch */
U16 Reserved2; /* 3Eh */
+ SGE_SIMPLE_UNION HostPageBufferSGE; /* 40h */
+ U32 ReplyFifoHostSignalingAddr; /* 4Ch */
} MSG_IOC_FACTS_REPLY, MPI_POINTER PTR_MSG_IOC_FACTS_REPLY,
IOCFactsReply_t, MPI_POINTER pIOCFactsReply_t;
-#define MPI_IOCFACTS_MSGVERSION_MAJOR_MASK (0xFF00)
-#define MPI_IOCFACTS_MSGVERSION_MINOR_MASK (0x00FF)
+#define MPI_IOCFACTS_MSGVERSION_MAJOR_MASK (0xFF00)
+#define MPI_IOCFACTS_MSGVERSION_MAJOR_SHIFT (8)
+#define MPI_IOCFACTS_MSGVERSION_MINOR_MASK (0x00FF)
+#define MPI_IOCFACTS_MSGVERSION_MINOR_SHIFT (0)
-#define MPI_IOCFACTS_HEADERVERSION_UNIT_MASK (0xFF00)
-#define MPI_IOCFACTS_HEADERVERSION_DEV_MASK (0x00FF)
+#define MPI_IOCFACTS_HDRVERSION_UNIT_MASK (0xFF00)
+#define MPI_IOCFACTS_HDRVERSION_UNIT_SHIFT (8)
+#define MPI_IOCFACTS_HDRVERSION_DEV_MASK (0x00FF)
+#define MPI_IOCFACTS_HDRVERSION_DEV_SHIFT (0)
-#define MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL (0x0001)
-#define MPI_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID (0x0002)
-#define MPI_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL (0x0004)
-#define MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL (0x0008)
+#define MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL (0x0001)
+#define MPI_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID (0x0002)
+#define MPI_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL (0x0004)
+#define MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL (0x0008)
-#define MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT (0x01)
+#define MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT (0x01)
+#define MPI_IOCFACTS_FLAGS_REPLY_FIFO_HOST_SIGNAL (0x02)
+#define MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT (0x04)
-#define MPI_IOCFACTS_EVENTSTATE_DISABLED (0x00)
-#define MPI_IOCFACTS_EVENTSTATE_ENABLED (0x01)
+#define MPI_IOCFACTS_EVENTSTATE_DISABLED (0x00)
+#define MPI_IOCFACTS_EVENTSTATE_ENABLED (0x01)
-#define MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q (0x00000001)
-#define MPI_IOCFACTS_CAPABILITY_REPLY_HOST_SIGNAL (0x00000002)
-#define MPI_IOCFACTS_CAPABILITY_QUEUE_FULL_HANDLING (0x00000004)
-#define MPI_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER (0x00000008)
-#define MPI_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER (0x00000010)
-#define MPI_IOCFACTS_CAPABILITY_EXTENDED_BUFFER (0x00000020)
-#define MPI_IOCFACTS_CAPABILITY_EEDP (0x00000040)
+#define MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q (0x00000001)
+#define MPI_IOCFACTS_CAPABILITY_REPLY_HOST_SIGNAL (0x00000002)
+#define MPI_IOCFACTS_CAPABILITY_QUEUE_FULL_HANDLING (0x00000004)
+#define MPI_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER (0x00000008)
+#define MPI_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER (0x00000010)
+#define MPI_IOCFACTS_CAPABILITY_EXTENDED_BUFFER (0x00000020)
@@ -408,6 +456,8 @@ typedef struct _MSG_EVENT_ACK_REPLY
#define MPI_EVENT_SAS_DEVICE_STATUS_CHANGE (0x0000000F)
#define MPI_EVENT_SAS_SES (0x00000010)
#define MPI_EVENT_PERSISTENT_TABLE_FULL (0x00000011)
+#define MPI_EVENT_SAS_PHY_LINK_STATUS (0x00000012)
+#define MPI_EVENT_SAS_DISCOVERY_ERROR (0x00000013)
/* AckRequired field values */
@@ -467,6 +517,10 @@ typedef struct _EVENT_DATA_SAS_DEVICE_STATUS_CHANGE
U8 ASCQ; /* 05h */
U16 DevHandle; /* 06h */
U32 DeviceInfo; /* 08h */
+ U16 ParentDevHandle; /* 0Ch */
+ U8 PhyNum; /* 0Eh */
+ U8 Reserved1; /* 0Fh */
+ U64 SASAddress; /* 10h */
} EVENT_DATA_SAS_DEVICE_STATUS_CHANGE,
MPI_POINTER PTR_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE,
MpiEventDataSasDeviceStatusChange_t,
@@ -477,6 +531,8 @@ typedef struct _EVENT_DATA_SAS_DEVICE_STATUS_CHANGE
#define MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING (0x04)
#define MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA (0x05)
#define MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED (0x06)
+#define MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED (0x07)
+
/* SCSI Event data for Queue Full event */
@@ -488,6 +544,35 @@ typedef struct _EVENT_DATA_QUEUE_FULL
} EVENT_DATA_QUEUE_FULL, MPI_POINTER PTR_EVENT_DATA_QUEUE_FULL,
EventDataQueueFull_t, MPI_POINTER pEventDataQueueFull_t;
+/* MPI Integrated RAID Event data */
+
+typedef struct _EVENT_DATA_RAID
+{
+ U8 VolumeID; /* 00h */
+ U8 VolumeBus; /* 01h */
+ U8 ReasonCode; /* 02h */
+ U8 PhysDiskNum; /* 03h */
+ U8 ASC; /* 04h */
+ U8 ASCQ; /* 05h */
+ U16 Reserved; /* 06h */
+ U32 SettingsStatus; /* 08h */
+} EVENT_DATA_RAID, MPI_POINTER PTR_EVENT_DATA_RAID,
+ MpiEventDataRaid_t, MPI_POINTER pMpiEventDataRaid_t;
+
+/* MPI Integrated RAID Event data ReasonCode values */
+#define MPI_EVENT_RAID_RC_VOLUME_CREATED (0x00)
+#define MPI_EVENT_RAID_RC_VOLUME_DELETED (0x01)
+#define MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED (0x02)
+#define MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED (0x03)
+#define MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED (0x04)
+#define MPI_EVENT_RAID_RC_PHYSDISK_CREATED (0x05)
+#define MPI_EVENT_RAID_RC_PHYSDISK_DELETED (0x06)
+#define MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED (0x07)
+#define MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED (0x08)
+#define MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED (0x09)
+#define MPI_EVENT_RAID_RC_SMART_DATA (0x0A)
+#define MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED (0x0B)
+
/* MPI Link Status Change Event data */
typedef struct _EVENT_DATA_LINK_STATUS
@@ -535,35 +620,63 @@ typedef struct _EVENT_DATA_LOGOUT
#define MPI_EVENT_LOGOUT_ALL_ALIASES (0xFF)
+/* SAS SES Event data */
-/* MPI Integrated RAID Event data */
-
-typedef struct _EVENT_DATA_RAID
+typedef struct _EVENT_DATA_SAS_SES
{
- U8 VolumeID; /* 00h */
- U8 VolumeBus; /* 01h */
- U8 ReasonCode; /* 02h */
- U8 PhysDiskNum; /* 03h */
- U8 ASC; /* 04h */
- U8 ASCQ; /* 05h */
- U16 Reserved; /* 06h */
- U32 SettingsStatus; /* 08h */
-} EVENT_DATA_RAID, MPI_POINTER PTR_EVENT_DATA_RAID,
- MpiEventDataRaid_t, MPI_POINTER pMpiEventDataRaid_t;
+ U8 PhyNum; /* 00h */
+ U8 Port; /* 01h */
+ U8 PortWidth; /* 02h */
+ U8 Reserved1; /* 04h */
+} EVENT_DATA_SAS_SES, MPI_POINTER PTR_EVENT_DATA_SAS_SES,
+ MpiEventDataSasSes_t, MPI_POINTER pMpiEventDataSasSes_t;
-/* MPI Integrated RAID Event data ReasonCode values */
-#define MPI_EVENT_RAID_RC_VOLUME_CREATED (0x00)
-#define MPI_EVENT_RAID_RC_VOLUME_DELETED (0x01)
-#define MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED (0x02)
-#define MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED (0x03)
-#define MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED (0x04)
-#define MPI_EVENT_RAID_RC_PHYSDISK_CREATED (0x05)
-#define MPI_EVENT_RAID_RC_PHYSDISK_DELETED (0x06)
-#define MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED (0x07)
-#define MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED (0x08)
-#define MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED (0x09)
-#define MPI_EVENT_RAID_RC_SMART_DATA (0x0A)
-#define MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED (0x0B)
+/* SAS Phy Link Status Event data */
+
+typedef struct _EVENT_DATA_SAS_PHY_LINK_STATUS
+{
+ U8 PhyNum; /* 00h */
+ U8 LinkRates; /* 01h */
+ U16 DevHandle; /* 02h */
+ U64 SASAddress; /* 04h */
+} EVENT_DATA_SAS_PHY_LINK_STATUS, MPI_POINTER PTR_EVENT_DATA_SAS_PHY_LINK_STATUS,
+ MpiEventDataSasPhyLinkStatus_t, MPI_POINTER pMpiEventDataSasPhyLinkStatus_t;
+
+/* defines for the LinkRates field of the SAS PHY Link Status event */
+#define MPI_EVENT_SAS_PLS_LR_CURRENT_MASK (0xF0)
+#define MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT (4)
+#define MPI_EVENT_SAS_PLS_LR_PREVIOUS_MASK (0x0F)
+#define MPI_EVENT_SAS_PLS_LR_PREVIOUS_SHIFT (0)
+#define MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN (0x00)
+#define MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED (0x01)
+#define MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION (0x02)
+#define MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE (0x03)
+#define MPI_EVENT_SAS_PLS_LR_RATE_1_5 (0x08)
+#define MPI_EVENT_SAS_PLS_LR_RATE_3_0 (0x09)
+
+/* SAS Discovery Errror Event data */
+
+typedef struct _EVENT_DATA_DISCOVERY_ERROR
+{
+ U32 DiscoveryStatus; /* 00h */
+ U8 Port; /* 04h */
+ U8 Reserved1; /* 05h */
+ U16 Reserved2; /* 06h */
+} EVENT_DATA_DISCOVERY_ERROR, MPI_POINTER PTR_EVENT_DATA_DISCOVERY_ERROR,
+ EventDataDiscoveryError_t, MPI_POINTER pEventDataDiscoveryError_t;
+
+#define MPI_EVENT_DSCVRY_ERR_DS_LOOP_DETECTED (0x00000001)
+#define MPI_EVENT_DSCVRY_ERR_DS_UNADDRESSABLE_DEVICE (0x00000002)
+#define MPI_EVENT_DSCVRY_ERR_DS_MULTIPLE_PORTS (0x00000004)
+#define MPI_EVENT_DSCVRY_ERR_DS_EXPANDER_ERR (0x00000008)
+#define MPI_EVENT_DSCVRY_ERR_DS_SMP_TIMEOUT (0x00000010)
+#define MPI_EVENT_DSCVRY_ERR_DS_OUT_ROUTE_ENTRIES (0x00000020)
+#define MPI_EVENT_DSCVRY_ERR_DS_INDEX_NOT_EXIST (0x00000040)
+#define MPI_EVENT_DSCVRY_ERR_DS_SMP_FUNCTION_FAILED (0x00000080)
+#define MPI_EVENT_DSCVRY_ERR_DS_SMP_CRC_ERROR (0x00000100)
+#define MPI_EVENT_DSCVRY_ERR_DS_MULTPL_SUBTRACTIVE (0x00000200)
+#define MPI_EVENT_DSCVRY_ERR_DS_TABLE_TO_TABLE (0x00000400)
+#define MPI_EVENT_DSCVRY_ERR_DS_MULTPL_PATHS (0x00000800)
/*****************************************************************************
@@ -589,11 +702,13 @@ typedef struct _MSG_FW_DOWNLOAD
} MSG_FW_DOWNLOAD, MPI_POINTER PTR_MSG_FW_DOWNLOAD,
FWDownload_t, MPI_POINTER pFWDownload_t;
-#define MPI_FW_DOWNLOAD_ITYPE_RESERVED (0x00)
-#define MPI_FW_DOWNLOAD_ITYPE_FW (0x01)
-#define MPI_FW_DOWNLOAD_ITYPE_BIOS (0x02)
-#define MPI_FW_DOWNLOAD_ITYPE_NVDATA (0x03)
-#define MPI_FW_DOWNLOAD_ITYPE_BOOTLOADER (0x04)
+#define MPI_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT (0x01)
+
+#define MPI_FW_DOWNLOAD_ITYPE_RESERVED (0x00)
+#define MPI_FW_DOWNLOAD_ITYPE_FW (0x01)
+#define MPI_FW_DOWNLOAD_ITYPE_BIOS (0x02)
+#define MPI_FW_DOWNLOAD_ITYPE_NVDATA (0x03)
+#define MPI_FW_DOWNLOAD_ITYPE_BOOTLOADER (0x04)
typedef struct _FWDownloadTCSGE
@@ -647,6 +762,7 @@ typedef struct _MSG_FW_UPLOAD
#define MPI_FW_UPLOAD_ITYPE_BIOS_FLASH (0x02)
#define MPI_FW_UPLOAD_ITYPE_NVDATA (0x03)
#define MPI_FW_UPLOAD_ITYPE_BOOTLOADER (0x04)
+#define MPI_FW_UPLOAD_ITYPE_FW_BACKUP (0x05)
typedef struct _FWUploadTCSGE
{
@@ -723,6 +839,7 @@ typedef struct _MPI_FW_HEADER
#define MPI_FW_HEADER_PID_PROD_IM_SCSI (0x0400)
#define MPI_FW_HEADER_PID_PROD_IS_SCSI (0x0500)
#define MPI_FW_HEADER_PID_PROD_CTX_SCSI (0x0600)
+#define MPI_FW_HEADER_PID_PROD_IR_SCSI (0x0700)
#define MPI_FW_HEADER_PID_FAMILY_MASK (0x00FF)
/* SCSI */
@@ -740,13 +857,16 @@ typedef struct _MPI_FW_HEADER
#define MPI_FW_HEADER_PID_FAMILY_1020TA0_SCSI (0x000C)
/* Fibre Channel */
#define MPI_FW_HEADER_PID_FAMILY_909_FC (0x0000)
-#define MPI_FW_HEADER_PID_FAMILY_919_FC (0x0001)
-#define MPI_FW_HEADER_PID_FAMILY_919X_FC (0x0002)
-#define MPI_FW_HEADER_PID_FAMILY_919XL_FC (0x0003)
-#define MPI_FW_HEADER_PID_FAMILY_949_FC (0x0004)
+#define MPI_FW_HEADER_PID_FAMILY_919_FC (0x0001) /* 919 and 929 */
+#define MPI_FW_HEADER_PID_FAMILY_919X_FC (0x0002) /* 919X and 929X */
+#define MPI_FW_HEADER_PID_FAMILY_919XL_FC (0x0003) /* 919XL and 929XL */
+#define MPI_FW_HEADER_PID_FAMILY_939X_FC (0x0004) /* 939X and 949X */
#define MPI_FW_HEADER_PID_FAMILY_959_FC (0x0005)
/* SAS */
#define MPI_FW_HEADER_PID_FAMILY_1064_SAS (0x0001)
+#define MPI_FW_HEADER_PID_FAMILY_1068_SAS (0x0002)
+#define MPI_FW_HEADER_PID_FAMILY_1078_SAS (0x0003)
+#define MPI_FW_HEADER_PID_FAMILY_106xE_SAS (0x0004) /* 1068E, 1066E, and 1064E */
typedef struct _MPI_EXT_IMAGE_HEADER
{
diff --git a/drivers/message/fusion/lsi/mpi_lan.h b/drivers/message/fusion/lsi/mpi_lan.h
index 3ced12784ee..dc0b52ae83d 100644
--- a/drivers/message/fusion/lsi/mpi_lan.h
+++ b/drivers/message/fusion/lsi/mpi_lan.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2000-2003 LSI Logic Corporation.
+ * Copyright (c) 2000-2004 LSI Logic Corporation.
*
*
* Name: mpi_lan.h
* Title: MPI LAN messages and structures
* Creation Date: June 30, 2000
*
- * mpi_lan.h Version: 01.05.xx
+ * mpi_lan.h Version: 01.05.01
*
* Version History
* ---------------
@@ -28,6 +28,8 @@
* 02-20-01 01.01.02 Started using MPI_POINTER.
* 03-27-01 01.01.03 Added structure offset comments.
* 08-08-01 01.02.01 Original release for v1.2 work.
+ * 05-11-04 01.03.01 Original release for MPI v1.3.
+ * 08-19-04 01.05.01 Original release for MPI v1.5.
* --------------------------------------------------------------------------
*/
diff --git a/drivers/message/fusion/lsi/mpi_raid.h b/drivers/message/fusion/lsi/mpi_raid.h
index 9580a9de7fd..802255d2747 100644
--- a/drivers/message/fusion/lsi/mpi_raid.h
+++ b/drivers/message/fusion/lsi/mpi_raid.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2001-2003 LSI Logic Corporation.
+ * Copyright (c) 2001-2005 LSI Logic Corporation.
*
*
* Name: mpi_raid.h
* Title: MPI RAID message and structures
* Creation Date: February 27, 2001
*
- * mpi_raid.h Version: 01.05.xx
+ * mpi_raid.h Version: 01.05.02
*
* Version History
* ---------------
@@ -28,6 +28,10 @@
* 11-15-02 01.02.08 Added missing MsgContext field to MSG_MAILBOX_REQUEST.
* 04-01-03 01.02.09 New action data option flag for
* MPI_RAID_ACTION_DELETE_VOLUME.
+ * 05-11-04 01.03.01 Original release for MPI v1.3.
+ * 08-19-04 01.05.01 Original release for MPI v1.5.
+ * 01-15-05 01.05.02 Added defines for the two new RAID Actions for
+ * _SET_RESYNC_RATE and _SET_DATA_SCRUB_RATE.
* --------------------------------------------------------------------------
*/
@@ -84,6 +88,8 @@ typedef struct _MSG_RAID_ACTION
#define MPI_RAID_ACTION_REPLACE_PHYSDISK (0x10)
#define MPI_RAID_ACTION_ACTIVATE_VOLUME (0x11)
#define MPI_RAID_ACTION_INACTIVATE_VOLUME (0x12)
+#define MPI_RAID_ACTION_SET_RESYNC_RATE (0x13)
+#define MPI_RAID_ACTION_SET_DATA_SCRUB_RATE (0x14)
/* ActionDataWord defines for use with MPI_RAID_ACTION_CREATE_VOLUME action */
#define MPI_RAID_ACTION_ADATA_DO_NOT_SYNC (0x00000001)
@@ -99,6 +105,13 @@ typedef struct _MSG_RAID_ACTION
/* ActionDataWord defines for use with MPI_RAID_ACTION_ACTIVATE_VOLUME action */
#define MPI_RAID_ACTION_ADATA_INACTIVATE_ALL (0x00000001)
+/* ActionDataWord defines for use with MPI_RAID_ACTION_SET_RESYNC_RATE action */
+#define MPI_RAID_ACTION_ADATA_RESYNC_RATE_MASK (0x000000FF)
+
+/* ActionDataWord defines for use with MPI_RAID_ACTION_SET_DATA_SCRUB_RATE action */
+#define MPI_RAID_ACTION_ADATA_DATA_SCRUB_RATE_MASK (0x000000FF)
+
+
/* RAID Action reply message */
diff --git a/drivers/message/fusion/lsi/mpi_sas.h b/drivers/message/fusion/lsi/mpi_sas.h
index cb878f9c65d..230fa69b535 100644
--- a/drivers/message/fusion/lsi/mpi_sas.h
+++ b/drivers/message/fusion/lsi/mpi_sas.h
@@ -1,25 +1,76 @@
/*
- * Copyright (c) 2003 LSI Logic Corporation.
+ * Copyright (c) 2004 LSI Logic Corporation.
*
*
* Name: mpi_sas.h
* Title: MPI Serial Attached SCSI structures and definitions
- * Creation Date: April 23, 2003
+ * Creation Date: August 19, 2004
*
- * mpi_sas.h Version: 01.05.xx
+ * mpi_sas.h Version: 01.05.01
*
* Version History
* ---------------
*
* Date Version Description
* -------- -------- ------------------------------------------------------
- * xx-yy-zz 01.05.01 Original release.
+ * 08-19-04 01.05.01 Original release.
* --------------------------------------------------------------------------
*/
#ifndef MPI_SAS_H
#define MPI_SAS_H
+
+/*
+ * Values for SASStatus.
+ */
+#define MPI_SASSTATUS_SUCCESS (0x00)
+#define MPI_SASSTATUS_UNKNOWN_ERROR (0x01)
+#define MPI_SASSTATUS_INVALID_FRAME (0x02)
+#define MPI_SASSTATUS_UTC_BAD_DEST (0x03)
+#define MPI_SASSTATUS_UTC_BREAK_RECEIVED (0x04)
+#define MPI_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED (0x05)
+#define MPI_SASSTATUS_UTC_PORT_LAYER_REQUEST (0x06)
+#define MPI_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED (0x07)
+#define MPI_SASSTATUS_UTC_STP_RESOURCES_BUSY (0x08)
+#define MPI_SASSTATUS_UTC_WRONG_DESTINATION (0x09)
+#define MPI_SASSTATUS_SHORT_INFORMATION_UNIT (0x0A)
+#define MPI_SASSTATUS_LONG_INFORMATION_UNIT (0x0B)
+#define MPI_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA (0x0C)
+#define MPI_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR (0x0D)
+#define MPI_SASSTATUS_XFER_RDY_NOT_EXPECTED (0x0E)
+#define MPI_SASSTATUS_DATA_INCORRECT_DATA_LENGTH (0x0F)
+#define MPI_SASSTATUS_DATA_TOO_MUCH_READ_DATA (0x10)
+#define MPI_SASSTATUS_DATA_OFFSET_ERROR (0x11)
+#define MPI_SASSTATUS_SDSF_NAK_RECEIVED (0x12)
+#define MPI_SASSTATUS_SDSF_CONNECTION_FAILED (0x13)
+#define MPI_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT (0x14)
+
+
+/*
+ * Values for the SAS DeviceInfo field used in SAS Device Status Change Event
+ * data and SAS IO Unit Configuration pages.
+ */
+#define MPI_SAS_DEVICE_INFO_ATAPI_DEVICE (0x00002000)
+#define MPI_SAS_DEVICE_INFO_LSI_DEVICE (0x00001000)
+#define MPI_SAS_DEVICE_INFO_DIRECT_ATTACH (0x00000800)
+#define MPI_SAS_DEVICE_INFO_SSP_TARGET (0x00000400)
+#define MPI_SAS_DEVICE_INFO_STP_TARGET (0x00000200)
+#define MPI_SAS_DEVICE_INFO_SMP_TARGET (0x00000100)
+#define MPI_SAS_DEVICE_INFO_SATA_DEVICE (0x00000080)
+#define MPI_SAS_DEVICE_INFO_SSP_INITIATOR (0x00000040)
+#define MPI_SAS_DEVICE_INFO_STP_INITIATOR (0x00000020)
+#define MPI_SAS_DEVICE_INFO_SMP_INITIATOR (0x00000010)
+#define MPI_SAS_DEVICE_INFO_SATA_HOST (0x00000008)
+
+#define MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE (0x00000007)
+#define MPI_SAS_DEVICE_INFO_NO_DEVICE (0x00000000)
+#define MPI_SAS_DEVICE_INFO_END_DEVICE (0x00000001)
+#define MPI_SAS_DEVICE_INFO_EDGE_EXPANDER (0x00000002)
+#define MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER (0x00000003)
+
+
+
/*****************************************************************************
*
* S e r i a l A t t a c h e d S C S I M e s s a g e s
@@ -48,8 +99,10 @@ typedef struct _MSG_SMP_PASSTHROUGH_REQUEST
} MSG_SMP_PASSTHROUGH_REQUEST, MPI_POINTER PTR_MSG_SMP_PASSTHROUGH_REQUEST,
SmpPassthroughRequest_t, MPI_POINTER pSmpPassthroughRequest_t;
+/* values for PassthroughFlags field */
#define MPI_SMP_PT_REQ_PT_FLAGS_IMMEDIATE (0x80)
+/* values for ConnectionRate field */
#define MPI_SMP_PT_REQ_CONNECT_RATE_NEGOTIATED (0x00)
#define MPI_SMP_PT_REQ_CONNECT_RATE_1_5 (0x08)
#define MPI_SMP_PT_REQ_CONNECT_RATE_3_0 (0x09)
@@ -77,51 +130,69 @@ typedef struct _MSG_SMP_PASSTHROUGH_REPLY
#define MPI_SMP_PT_REPLY_PT_FLAGS_IMMEDIATE (0x80)
-/* values for the SASStatus field */
-#define MPI_SASSTATUS_SUCCESS (0x00)
-#define MPI_SASSTATUS_UNKNOWN_ERROR (0x01)
-#define MPI_SASSTATUS_INVALID_FRAME (0x02)
-#define MPI_SASSTATUS_UTC_BAD_DEST (0x03)
-#define MPI_SASSTATUS_UTC_BREAK_RECEIVED (0x04)
-#define MPI_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED (0x05)
-#define MPI_SASSTATUS_UTC_PORT_LAYER_REQUEST (0x06)
-#define MPI_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED (0x07)
-#define MPI_SASSTATUS_UTC_STP_RESOURCES_BUSY (0x08)
-#define MPI_SASSTATUS_UTC_WRONG_DESTINATION (0x09)
-#define MPI_SASSTATUS_SHORT_INFORMATION_UNIT (0x0A)
-#define MPI_SASSTATUS_LONG_INFORMATION_UNIT (0x0B)
-#define MPI_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA (0x0C)
-#define MPI_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR (0x0D)
-#define MPI_SASSTATUS_XFER_RDY_NOT_EXPECTED (0x0E)
-#define MPI_SASSTATUS_DATA_INCORRECT_DATA_LENGTH (0x0F)
-#define MPI_SASSTATUS_DATA_TOO_MUCH_READ_DATA (0x10)
-#define MPI_SASSTATUS_DATA_OFFSET_ERROR (0x11)
-#define MPI_SASSTATUS_SDSF_NAK_RECEIVED (0x12)
-#define MPI_SASSTATUS_SDSF_CONNECTION_FAILED (0x13)
-#define MPI_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT (0x14)
+/****************************************************************************/
+/* SATA Passthrough Request */
+/****************************************************************************/
+
+typedef struct _MSG_SATA_PASSTHROUGH_REQUEST
+{
+ U8 TargetID; /* 00h */
+ U8 Bus; /* 01h */
+ U8 ChainOffset; /* 02h */
+ U8 Function; /* 03h */
+ U16 PassthroughFlags; /* 04h */
+ U8 ConnectionRate; /* 06h */
+ U8 MsgFlags; /* 07h */
+ U32 MsgContext; /* 08h */
+ U32 Reserved1; /* 0Ch */
+ U32 Reserved2; /* 10h */
+ U32 Reserved3; /* 14h */
+ U32 DataLength; /* 18h */
+ U8 CommandFIS[20]; /* 1Ch */
+ SGE_SIMPLE_UNION SGL; /* 30h */
+} MSG_SATA_PASSTHROUGH_REQUEST, MPI_POINTER PTR_MSG_SATA_PASSTHROUGH_REQUEST,
+ SataPassthroughRequest_t, MPI_POINTER pSataPassthroughRequest_t;
+
+/* values for PassthroughFlags field */
+#define MPI_SATA_PT_REQ_PT_FLAGS_RESET_DEVICE (0x0200)
+#define MPI_SATA_PT_REQ_PT_FLAGS_EXECUTE_DIAG (0x0100)
+#define MPI_SATA_PT_REQ_PT_FLAGS_DMA_QUEUED (0x0080)
+#define MPI_SATA_PT_REQ_PT_FLAGS_PACKET_COMMAND (0x0040)
+#define MPI_SATA_PT_REQ_PT_FLAGS_DMA (0x0020)
+#define MPI_SATA_PT_REQ_PT_FLAGS_PIO (0x0010)
+#define MPI_SATA_PT_REQ_PT_FLAGS_UNSPECIFIED_VU (0x0004)
+#define MPI_SATA_PT_REQ_PT_FLAGS_WRITE (0x0002)
+#define MPI_SATA_PT_REQ_PT_FLAGS_READ (0x0001)
+
+/* values for ConnectionRate field */
+#define MPI_SATA_PT_REQ_CONNECT_RATE_NEGOTIATED (0x00)
+#define MPI_SATA_PT_REQ_CONNECT_RATE_1_5 (0x08)
+#define MPI_SATA_PT_REQ_CONNECT_RATE_3_0 (0x09)
+
+
+/* SATA Passthrough Reply */
+typedef struct _MSG_SATA_PASSTHROUGH_REPLY
+{
+ U8 TargetID; /* 00h */
+ U8 Bus; /* 01h */
+ U8 MsgLength; /* 02h */
+ U8 Function; /* 03h */
+ U16 PassthroughFlags; /* 04h */
+ U8 Reserved1; /* 06h */
+ U8 MsgFlags; /* 07h */
+ U32 MsgContext; /* 08h */
+ U8 Reserved2; /* 0Ch */
+ U8 SASStatus; /* 0Dh */
+ U16 IOCStatus; /* 0Eh */
+ U32 IOCLogInfo; /* 10h */
+ U8 StatusFIS[20]; /* 14h */
+ U32 StatusControlRegisters; /* 28h */
+ U32 TransferCount; /* 2Ch */
+} MSG_SATA_PASSTHROUGH_REPLY, MPI_POINTER PTR_MSG_SATA_PASSTHROUGH_REPLY,
+ SataPassthroughReply_t, MPI_POINTER pSataPassthroughReply_t;
-/*
- * Values for the SAS DeviceInfo field used in SAS Device Status Change Event
- * data and SAS IO Unit Configuration pages.
- */
-#define MPI_SAS_DEVICE_INFO_ATAPI_DEVICE (0x00002000)
-#define MPI_SAS_DEVICE_INFO_LSI_DEVICE (0x00001000)
-#define MPI_SAS_DEVICE_INFO_DIRECT_ATTACH (0x00000800)
-#define MPI_SAS_DEVICE_INFO_SSP_TARGET (0x00000400)
-#define MPI_SAS_DEVICE_INFO_STP_TARGET (0x00000200)
-#define MPI_SAS_DEVICE_INFO_SMP_TARGET (0x00000100)
-#define MPI_SAS_DEVICE_INFO_SATA_DEVICE (0x00000080)
-#define MPI_SAS_DEVICE_INFO_SSP_INITIATOR (0x00000040)
-#define MPI_SAS_DEVICE_INFO_STP_INITIATOR (0x00000020)
-#define MPI_SAS_DEVICE_INFO_SMP_INITIATOR (0x00000010)
-#define MPI_SAS_DEVICE_INFO_SATA_HOST (0x00000008)
-#define MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE (0x00000007)
-#define MPI_SAS_DEVICE_INFO_NO_DEVICE (0x00000000)
-#define MPI_SAS_DEVICE_INFO_END_DEVICE (0x00000001)
-#define MPI_SAS_DEVICE_INFO_EDGE_EXPANDER (0x00000002)
-#define MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER (0x00000003)
/****************************************************************************/
@@ -148,15 +219,13 @@ typedef struct _MSG_SAS_IOUNIT_CONTROL_REQUEST
} MSG_SAS_IOUNIT_CONTROL_REQUEST, MPI_POINTER PTR_MSG_SAS_IOUNIT_CONTROL_REQUEST,
SasIoUnitControlRequest_t, MPI_POINTER pSasIoUnitControlRequest_t;
-/* values for the ... field */
+/* values for the Operation field */
#define MPI_SAS_OP_CLEAR_NOT_PRESENT (0x01)
-#define MPI_SAS_OP_CLEAR_ALL (0x02)
-#define MPI_SAS_OP_MAP (0x03)
-#define MPI_SAS_OP_MOVE (0x04)
-#define MPI_SAS_OP_CLEAR (0x05)
+#define MPI_SAS_OP_CLEAR_ALL_PERSISTENT (0x02)
#define MPI_SAS_OP_PHY_LINK_RESET (0x06)
#define MPI_SAS_OP_PHY_HARD_RESET (0x07)
#define MPI_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08)
+#define MPI_SAS_OP_MAP_CURRENT (0x09)
/* SAS IO Unit Control Reply */
diff --git a/drivers/message/fusion/lsi/mpi_targ.h b/drivers/message/fusion/lsi/mpi_targ.h
index 804dc85426c..623901fd82b 100644
--- a/drivers/message/fusion/lsi/mpi_targ.h
+++ b/drivers/message/fusion/lsi/mpi_targ.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2000-2003 LSI Logic Corporation.
+ * Copyright (c) 2000-2004 LSI Logic Corporation.
*
*
* Name: mpi_targ.h
* Title: MPI Target mode messages and structures
* Creation Date: June 22, 2000
*
- * mpi_targ.h Version: 01.05.xx
+ * mpi_targ.h Version: 01.05.04
*
* Version History
* ---------------
@@ -43,6 +43,16 @@
* Added PRIORITY_REASON_TARGET_BUSY.
* 11-15-02 01.02.08 Added AliasID field to MPI_TARGET_SCSI_SPI_CMD_BUFFER.
* 04-01-03 01.02.09 Added OptionalOxid field to MPI_TARGET_FCP_CMD_BUFFER.
+ * 05-11-04 01.03.01 Original release for MPI v1.3.
+ * 08-19-04 01.05.01 Added new request message structures for
+ * MSG_TARGET_CMD_BUF_POST_BASE_REQUEST,
+ * MSG_TARGET_CMD_BUF_POST_LIST_REQUEST, and
+ * MSG_TARGET_ASSIST_EXT_REQUEST.
+ * Added new structures for SAS SSP Command buffer, SSP
+ * Task buffer, and SSP Status IU.
+ * 10-05-04 01.05.02 MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY added.
+ * 02-22-05 01.05.03 Changed a comment.
+ * 03-11-05 01.05.04 Removed TargetAssistExtended Request.
* --------------------------------------------------------------------------
*/
@@ -133,6 +143,25 @@ typedef struct _MSG_PRIORITY_CMD_RECEIVED_REPLY
} MSG_PRIORITY_CMD_RECEIVED_REPLY, MPI_POINTER PTR_MSG_PRIORITY_CMD_RECEIVED_REPLY,
PriorityCommandReceivedReply_t, MPI_POINTER pPriorityCommandReceivedReply_t;
+
+typedef struct _MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY
+{
+ U16 Reserved; /* 00h */
+ U8 MsgLength; /* 02h */
+ U8 Function; /* 03h */
+ U16 Reserved1; /* 04h */
+ U8 Reserved2; /* 06h */
+ U8 MsgFlags; /* 07h */
+ U32 MsgContext; /* 08h */
+ U8 PriorityReason; /* 0Ch */
+ U8 Reserved3; /* 0Dh */
+ U16 IOCStatus; /* 0Eh */
+ U32 IOCLogInfo; /* 10h */
+ U32 ReplyWord; /* 14h */
+} MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY,
+ MPI_POINTER PTR_MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY,
+ TargetCmdBufferPostErrorReply_t, MPI_POINTER pTargetCmdBufferPostErrorReply_t;
+
#define PRIORITY_REASON_NO_DISCONNECT (0x00)
#define PRIORITY_REASON_SCSI_TASK_MANAGEMENT (0x01)
#define PRIORITY_REASON_CMD_PARITY_ERR (0x02)
@@ -146,7 +175,34 @@ typedef struct _MSG_PRIORITY_CMD_RECEIVED_REPLY
#define PRIORITY_REASON_UNKNOWN (0xFF)
-typedef struct _MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY
+/****************************************************************************/
+/* Target Command Buffer Post Base Request */
+/****************************************************************************/
+
+typedef struct _MSG_TARGET_CMD_BUF_POST_BASE_REQUEST
+{
+ U8 BufferPostFlags; /* 00h */
+ U8 PortNumber; /* 01h */
+ U8 ChainOffset; /* 02h */
+ U8 Function; /* 03h */
+ U16 TotalCmdBuffers; /* 04h */
+ U8 Reserved; /* 06h */
+ U8 MsgFlags; /* 07h */
+ U32 MsgContext; /* 08h */
+ U32 Reserved1; /* 0Ch */
+ U16 CmdBufferLength; /* 10h */
+ U16 NextCmdBufferOffset; /* 12h */
+ U32 BaseAddressLow; /* 14h */
+ U32 BaseAddressHigh; /* 18h */
+} MSG_TARGET_CMD_BUF_POST_BASE_REQUEST,
+ MPI_POINTER PTR__MSG_TARGET_CMD_BUF_POST_BASE_REQUEST,
+ TargetCmdBufferPostBaseRequest_t,
+ MPI_POINTER pTargetCmdBufferPostBaseRequest_t;
+
+#define CMD_BUFFER_POST_BASE_FLAGS_AUTO_POST_ALL (0x01)
+
+
+typedef struct _MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY
{
U16 Reserved; /* 00h */
U8 MsgLength; /* 02h */
@@ -155,16 +211,41 @@ typedef struct _MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY
U8 Reserved2; /* 06h */
U8 MsgFlags; /* 07h */
U32 MsgContext; /* 08h */
- U8 PriorityReason; /* 0Ch */
- U8 Reserved3; /* 0Dh */
+ U16 Reserved3; /* 0Ch */
U16 IOCStatus; /* 0Eh */
U32 IOCLogInfo; /* 10h */
- U32 ReplyWord; /* 14h */
-} MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY,
- MPI_POINTER PTR_MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY,
- TargetCmdBufferPostErrorReply_t, MPI_POINTER pTargetCmdBufferPostErrorReply_t;
+} MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY,
+ MPI_POINTER PTR_MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY,
+ TargetCmdBufferPostBaseListReply_t,
+ MPI_POINTER pTargetCmdBufferPostBaseListReply_t;
+
+
+/****************************************************************************/
+/* Target Command Buffer Post List Request */
+/****************************************************************************/
+
+typedef struct _MSG_TARGET_CMD_BUF_POST_LIST_REQUEST
+{
+ U8 Reserved; /* 00h */
+ U8 PortNumber; /* 01h */
+ U8 ChainOffset; /* 02h */
+ U8 Function; /* 03h */
+ U16 CmdBufferCount; /* 04h */
+ U8 Reserved1; /* 06h */
+ U8 MsgFlags; /* 07h */
+ U32 MsgContext; /* 08h */
+ U32 Reserved2; /* 0Ch */
+ U16 IoIndex[2]; /* 10h */
+} MSG_TARGET_CMD_BUF_POST_LIST_REQUEST,
+ MPI_POINTER PTR_MSG_TARGET_CMD_BUF_POST_LIST_REQUEST,
+ TargetCmdBufferPostListRequest_t,
+ MPI_POINTER pTargetCmdBufferPostListRequest_t;
+/****************************************************************************/
+/* Command Buffer Formats (with 16 byte CDB) */
+/****************************************************************************/
+
typedef struct _MPI_TARGET_FCP_CMD_BUFFER
{
U8 FcpLun[8]; /* 00h */
@@ -201,6 +282,46 @@ typedef struct _MPI_TARGET_SCSI_SPI_CMD_BUFFER
MpiTargetScsiSpiCmdBuffer, MPI_POINTER pMpiTargetScsiSpiCmdBuffer;
+typedef struct _MPI_TARGET_SSP_CMD_BUFFER
+{
+ U8 FrameType; /* 00h */
+ U8 Reserved1; /* 01h */
+ U16 Reserved2; /* 02h */
+ U16 InitiatorTag; /* 04h */
+ U16 DevHandle; /* 06h */
+ /* COMMAND information unit starts here */
+ U8 LogicalUnitNumber[8]; /* 08h */
+ U8 Reserved3; /* 10h */
+ U8 TaskAttribute; /* lower 3 bits */ /* 11h */
+ U8 Reserved4; /* 12h */
+ U8 AdditionalCDBLength; /* upper 5 bits */ /* 13h */
+ U8 CDB[16]; /* 14h */
+ /* Additional CDB bytes extend past the CDB field */
+} MPI_TARGET_SSP_CMD_BUFFER, MPI_POINTER PTR_MPI_TARGET_SSP_CMD_BUFFER,
+ MpiTargetSspCmdBuffer, MPI_POINTER pMpiTargetSspCmdBuffer;
+
+typedef struct _MPI_TARGET_SSP_TASK_BUFFER
+{
+ U8 FrameType; /* 00h */
+ U8 Reserved1; /* 01h */
+ U16 Reserved2; /* 02h */
+ U16 InitiatorTag; /* 04h */
+ U16 DevHandle; /* 06h */
+ /* TASK information unit starts here */
+ U8 LogicalUnitNumber[8]; /* 08h */
+ U8 Reserved3; /* 10h */
+ U8 Reserved4; /* 11h */
+ U8 TaskManagementFunction; /* 12h */
+ U8 Reserved5; /* 13h */
+ U16 ManagedTaskTag; /* 14h */
+ U16 Reserved6; /* 16h */
+ U32 Reserved7; /* 18h */
+ U32 Reserved8; /* 1Ch */
+ U32 Reserved9; /* 20h */
+} MPI_TARGET_SSP_TASK_BUFFER, MPI_POINTER PTR_MPI_TARGET_SSP_TASK_BUFFER,
+ MpiTargetSspTaskBuffer, MPI_POINTER pMpiTargetSspTaskBuffer;
+
+
/****************************************************************************/
/* Target Assist Request */
/****************************************************************************/
@@ -308,6 +429,27 @@ typedef struct _MPI_TARGET_SCSI_SPI_STATUS_IU
} MPI_TARGET_SCSI_SPI_STATUS_IU, MPI_POINTER PTR_MPI_TARGET_SCSI_SPI_STATUS_IU,
TargetScsiSpiStatusIU_t, MPI_POINTER pTargetScsiSpiStatusIU_t;
+/*
+ * NOTE: The SSP status IU is big-endian. When used on a little-endian system,
+ * this structure properly orders the bytes.
+ */
+typedef struct _MPI_TARGET_SSP_RSP_IU
+{
+ U32 Reserved0[6]; /* reserved for SSP header */ /* 00h */
+ /* start of RESPONSE information unit */
+ U32 Reserved1; /* 18h */
+ U32 Reserved2; /* 1Ch */
+ U16 Reserved3; /* 20h */
+ U8 DataPres; /* lower 2 bits */ /* 22h */
+ U8 Status; /* 23h */
+ U32 Reserved4; /* 24h */
+ U32 SenseDataLength; /* 28h */
+ U32 ResponseDataLength; /* 2Ch */
+ U8 ResponseSenseData[4]; /* 30h */
+} MPI_TARGET_SSP_RSP_IU, MPI_POINTER PTR_MPI_TARGET_SSP_RSP_IU,
+ MpiTargetSspRspIu_t, MPI_POINTER pMpiTargetSspRspIu_t;
+
+
/****************************************************************************/
/* Target Mode Abort Request */
/****************************************************************************/
diff --git a/drivers/message/fusion/lsi/mpi_tool.h b/drivers/message/fusion/lsi/mpi_tool.h
index 536d197c414..aa9053da1f5 100644
--- a/drivers/message/fusion/lsi/mpi_tool.h
+++ b/drivers/message/fusion/lsi/mpi_tool.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2001-2003 LSI Logic Corporation.
+ * Copyright (c) 2001-2005 LSI Logic Corporation.
*
*
* Name: mpi_tool.h
* Title: MPI Toolbox structures and definitions
* Creation Date: July 30, 2001
*
- * mpi_tool.h Version: 01.05.xx
+ * mpi_tool.h Version: 01.05.03
*
* Version History
* ---------------
@@ -15,6 +15,16 @@
* -------- -------- ------------------------------------------------------
* 08-08-01 01.02.01 Original release.
* 08-29-01 01.02.02 Added DIAG_DATA_UPLOAD_HEADER and related defines.
+ * 01-16-04 01.02.03 Added defines and structures for new tools
+ *. MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL and
+ * MPI_TOOLBOX_FC_MANAGEMENT_TOOL.
+ * 04-29-04 01.02.04 Added message structures for Diagnostic Buffer Post and
+ * Diagnostic Release requests and replies.
+ * 05-11-04 01.03.01 Original release for MPI v1.3.
+ * 08-19-04 01.05.01 Original release for MPI v1.5.
+ * 10-06-04 01.05.02 Added define for MPI_DIAG_BUF_TYPE_COUNT.
+ * 02-09-05 01.05.03 Added frame size option to FC management tool.
+ * Added Beacon tool to the Toolbox.
* --------------------------------------------------------------------------
*/
@@ -26,6 +36,7 @@
#define MPI_TOOLBOX_DIAG_DATA_UPLOAD_TOOL (0x02)
#define MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL (0x03)
#define MPI_TOOLBOX_FC_MANAGEMENT_TOOL (0x04)
+#define MPI_TOOLBOX_BEACON_TOOL (0x05)
/****************************************************************************/
@@ -185,11 +196,21 @@ typedef struct _MPI_TB_FC_MANAGE_PID_AI
} MPI_TB_FC_MANAGE_PID_AI, MPI_POINTER PTR_MPI_TB_FC_MANAGE_PID_AI,
MpiTbFcManagePidAi_t, MPI_POINTER pMpiTbFcManagePidAi_t;
+/* ActionInfo for set max frame size */
+typedef struct _MPI_TB_FC_MANAGE_FRAME_SIZE_AI
+{
+ U16 FrameSize; /* 00h */
+ U8 PortNum; /* 02h */
+ U8 Reserved1; /* 03h */
+} MPI_TB_FC_MANAGE_FRAME_SIZE_AI, MPI_POINTER PTR_MPI_TB_FC_MANAGE_FRAME_SIZE_AI,
+ MpiTbFcManageFrameSizeAi_t, MPI_POINTER pMpiTbFcManageFrameSizeAi_t;
+
/* union of ActionInfo */
typedef union _MPI_TB_FC_MANAGE_AI_UNION
{
MPI_TB_FC_MANAGE_BUS_TID_AI BusTid;
MPI_TB_FC_MANAGE_PID_AI Port;
+ MPI_TB_FC_MANAGE_FRAME_SIZE_AI FrameSize;
} MPI_TB_FC_MANAGE_AI_UNION, MPI_POINTER PTR_MPI_TB_FC_MANAGE_AI_UNION,
MpiTbFcManageAiUnion_t, MPI_POINTER pMpiTbFcManageAiUnion_t;
@@ -214,6 +235,32 @@ typedef struct _MSG_TOOLBOX_FC_MANAGE_REQUEST
#define MPI_TB_FC_MANAGE_ACTION_DISC_ALL (0x00)
#define MPI_TB_FC_MANAGE_ACTION_DISC_PID (0x01)
#define MPI_TB_FC_MANAGE_ACTION_DISC_BUS_TID (0x02)
+#define MPI_TB_FC_MANAGE_ACTION_SET_MAX_FRAME_SIZE (0x03)
+
+
+/****************************************************************************/
+/* Toolbox Beacon Tool request */
+/****************************************************************************/
+
+typedef struct _MSG_TOOLBOX_BEACON_REQUEST
+{
+ U8 Tool; /* 00h */
+ U8 Reserved; /* 01h */
+ U8 ChainOffset; /* 02h */
+ U8 Function; /* 03h */
+ U16 Reserved1; /* 04h */
+ U8 Reserved2; /* 06h */
+ U8 MsgFlags; /* 07h */
+ U32 MsgContext; /* 08h */
+ U8 ConnectNum; /* 0Ch */
+ U8 PortNum; /* 0Dh */
+ U8 Reserved3; /* 0Eh */
+ U8 Flags; /* 0Fh */
+} MSG_TOOLBOX_BEACON_REQUEST, MPI_POINTER PTR_MSG_TOOLBOX_BEACON_REQUEST,
+ ToolboxBeaconRequest_t, MPI_POINTER pToolboxBeaconRequest_t;
+
+#define MPI_TOOLBOX_FLAGS_BEACON_MODE_OFF (0x00)
+#define MPI_TOOLBOX_FLAGS_BEACON_MODE_ON (0x01)
/****************************************************************************/
@@ -233,14 +280,16 @@ typedef struct _MSG_DIAG_BUFFER_POST_REQUEST
U32 ExtendedType; /* 0Ch */
U32 BufferLength; /* 10h */
U32 ProductSpecific[4]; /* 14h */
- U32 Reserved3; /* 18h */
- SGE_SIMPLE_UNION SGL; /* 28h */
+ U32 Reserved3; /* 24h */
+ U64 BufferAddress; /* 28h */
} MSG_DIAG_BUFFER_POST_REQUEST, MPI_POINTER PTR_MSG_DIAG_BUFFER_POST_REQUEST,
DiagBufferPostRequest_t, MPI_POINTER pDiagBufferPostRequest_t;
#define MPI_DIAG_BUF_TYPE_TRACE (0x00)
#define MPI_DIAG_BUF_TYPE_SNAPSHOT (0x01)
#define MPI_DIAG_BUF_TYPE_EXTENDED (0x02)
+/* count of the number of buffer types */
+#define MPI_DIAG_BUF_TYPE_COUNT (0x03)
#define MPI_DIAG_EXTENDED_QTAG (0x00000001)
diff --git a/drivers/message/fusion/lsi/mpi_type.h b/drivers/message/fusion/lsi/mpi_type.h
index 239328a7689..32cc9b1151b 100644
--- a/drivers/message/fusion/lsi/mpi_type.h
+++ b/drivers/message/fusion/lsi/mpi_type.h
@@ -1,12 +1,12 @@
/*
- * Copyright (c) 2000-2003 LSI Logic Corporation.
+ * Copyright (c) 2000-2004 LSI Logic Corporation.
*
*
* Name: mpi_type.h
* Title: MPI Basic type definitions
* Creation Date: June 6, 2000
*
- * mpi_type.h Version: 01.05.xx
+ * mpi_type.h Version: 01.05.01
*
* Version History
* ---------------
@@ -18,6 +18,8 @@
* 11-02-00 01.01.01 Original release for post 1.0 work
* 02-20-01 01.01.02 Added define and ifdef for MPI_POINTER.
* 08-08-01 01.02.01 Original release for v1.2 work.
+ * 05-11-04 01.03.01 Original release for MPI v1.3.
+ * 08-19-04 01.05.01 Original release for MPI v1.5.
* --------------------------------------------------------------------------
*/
@@ -50,11 +52,6 @@ typedef unsigned short U16;
typedef int32_t S32;
typedef u_int32_t U32;
-/*
- * The only way crap below could work on big-endian boxen would be if it
- * wasn't used at all.
- */
-
typedef struct _S64
{
U32 Low;
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 8b22630f1ae..8b623278ccd 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -1,55 +1,13 @@
/*
* linux/drivers/message/fusion/mptbase.c
- * High performance SCSI + LAN / Fibre Channel device drivers.
* This is the Fusion MPT base driver which supports multiple
* (SCSI + LAN) specialized protocol drivers.
- * For use with PCI chip/adapter(s):
- * LSIFC9xx/LSI409xx Fibre Channel
+ * For use with LSI Logic PCI chip/adapter(s)
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
- * Credits:
- * There are lots of people not mentioned below that deserve credit
- * and thanks but won't get it here - sorry in advance that you
- * got overlooked.
- *
- * This driver would not exist if not for Alan Cox's development
- * of the linux i2o driver.
- *
- * A special thanks to Noah Romer (LSI Logic) for tons of work
- * and tough debugging on the LAN driver, especially early on;-)
- * And to Roger Hickerson (LSI Logic) for tirelessly supporting
- * this driver project.
- *
- * A special thanks to Pamela Delaney (LSI Logic) for tons of work
- * and countless enhancements while adding support for the 1030
- * chip family. Pam has been instrumental in the development of
- * of the 2.xx.xx series fusion drivers, and her contributions are
- * far too numerous to hope to list in one place.
- *
- * All manner of help from Stephen Shirron (LSI Logic):
- * low-level FC analysis, debug + various fixes in FCxx firmware,
- * initial port to alpha platform, various driver code optimizations,
- * being a faithful sounding board on all sorts of issues & ideas,
- * etc.
- *
- * A huge debt of gratitude is owed to David S. Miller (DaveM)
- * for fixing much of the stupid and broken stuff in the early
- * driver while porting to sparc64 platform. THANK YOU!
- *
- * Special thanks goes to the I2O LAN driver people at the
- * University of Helsinki, who, unbeknownst to them, provided
- * the inspiration and initial structure for this driver.
- *
- * A really huge debt of gratitude is owed to Eddie C. Dost
- * for gobs of hard work fixing and optimizing LAN code.
- * THANK YOU!
- *
- * Copyright (c) 1999-2004 LSI Logic Corporation
- * Originally By: Steven J. Ralston
- * (mailto:sjralston1@netscape.net)
+ * Copyright (c) 1999-2005 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
*
- * $Id: mptbase.c,v 1.126 2002/12/16 15:28:45 pdelaney Exp $
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@@ -101,6 +59,7 @@
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/interrupt.h> /* needed for in_interrupt() proto */
+#include <linux/dma-mapping.h>
#include <asm/io.h>
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
@@ -218,41 +177,35 @@ static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
static void mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info);
/* module entry point */
-static int __devinit mptbase_probe (struct pci_dev *, const struct pci_device_id *);
-static void __devexit mptbase_remove(struct pci_dev *);
-static void mptbase_shutdown(struct device * );
static int __init fusion_init (void);
static void __exit fusion_exit (void);
-/****************************************************************************
- * Supported hardware
- */
-
-static struct pci_device_id mptbase_pci_table[] = {
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC909,
- PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929,
- PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919,
- PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929X,
- PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919X,
- PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C1030,
- PCI_ANY_ID, PCI_ANY_ID },
- { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_1030_53C1035,
- PCI_ANY_ID, PCI_ANY_ID },
- {0} /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(pci, mptbase_pci_table);
-
#define CHIPREG_READ32(addr) readl_relaxed(addr)
#define CHIPREG_READ32_dmasync(addr) readl(addr)
#define CHIPREG_WRITE32(addr,val) writel(val, addr)
#define CHIPREG_PIO_WRITE32(addr,val) outl(val, (unsigned long)addr)
#define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr)
+static void
+pci_disable_io_access(struct pci_dev *pdev)
+{
+ u16 command_reg;
+
+ pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
+ command_reg &= ~1;
+ pci_write_config_word(pdev, PCI_COMMAND, command_reg);
+}
+
+static void
+pci_enable_io_access(struct pci_dev *pdev)
+{
+ u16 command_reg;
+
+ pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
+ command_reg |= 1;
+ pci_write_config_word(pdev, PCI_COMMAND, command_reg);
+}
+
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
@@ -330,8 +283,7 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
ioc->name, mr, req_idx));
DBG_DUMP_REPLY_FRAME(mr)
- /* NEW! 20010301 -sralston
- * Check/log IOC log info
+ /* Check/log IOC log info
*/
ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
@@ -357,9 +309,7 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
} else if (type == MPI_CONTEXT_REPLY_TYPE_LAN) {
cb_idx = mpt_lan_index;
- /*
- * BUG FIX! 20001218 -sralston
- * Blind set of mf to NULL here was fatal
+ /* Blind set of mf to NULL here was fatal
* after lan_reply says "freeme"
* Fix sort of combined with an optimization here;
* added explicit check for case where lan_reply
@@ -430,15 +380,8 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
}
if (freeme) {
- unsigned long flags;
-
/* Put Request back on FreeQ! */
- spin_lock_irqsave(&ioc->FreeQlock, flags);
- list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
-#ifdef MFCNT
- ioc->mfcnt--;
-#endif
- spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+ mpt_free_msg_frame(ioc, mf);
}
mb();
@@ -725,11 +668,9 @@ int
mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
{
MPT_ADAPTER *ioc;
- int error=0;
if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) {
- error= -EINVAL;
- return error;
+ return -EINVAL;
}
MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
@@ -737,14 +678,12 @@ mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
/* call per pci device probe entry point */
list_for_each_entry(ioc, &ioc_list, list) {
if(dd_cbfunc->probe) {
- error = dd_cbfunc->probe(ioc->pcidev,
+ dd_cbfunc->probe(ioc->pcidev,
ioc->pcidev->driver->id_table);
- if(error != 0)
- return error;
}
}
- return error;
+ return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -809,8 +748,8 @@ mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
/* u16! */
- req_idx = cpu_to_le16(req_offset / ioc->req_sz);
- mf->u.frame.hwhdr.msgctxu.fld.req_idx = req_idx;
+ req_idx = req_offset / ioc->req_sz;
+ mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; /* Default, will be changed if necessary in SG generation */
#ifdef MFCNT
@@ -856,8 +795,8 @@ mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
/* u16! */
- req_idx = cpu_to_le16(req_offset / ioc->req_sz);
- mf->u.frame.hwhdr.msgctxu.fld.req_idx = req_idx;
+ req_idx = req_offset / ioc->req_sz;
+ mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
#ifdef MPT_DEBUG_MSG_FRAME
@@ -1058,7 +997,7 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
- * mptbase_probe - Install a PCI intelligent MPT adapter.
+ * mpt_attach - Install a PCI intelligent MPT adapter.
* @pdev: Pointer to pci_dev structure
*
* This routine performs all the steps necessary to bring the IOC of
@@ -1073,8 +1012,8 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
*
* TODO: Add support for polled controllers
*/
-static int __devinit
-mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+int
+mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
{
MPT_ADAPTER *ioc;
u8 __iomem *mem;
@@ -1084,7 +1023,6 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
u32 psize;
int ii;
int r = -ENODEV;
- u64 mask = 0xffffffffffffffffULL;
u8 revision;
u8 pcixcmd;
static int mpt_ids = 0;
@@ -1097,15 +1035,15 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n"));
- if (!pci_set_dma_mask(pdev, mask)) {
+ if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
dprintk((KERN_INFO MYNAM
": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));
- } else if (pci_set_dma_mask(pdev, (u64) 0xffffffff)) {
+ } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n");
return r;
}
- if (!pci_set_consistent_dma_mask(pdev, mask))
+ if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
dprintk((KERN_INFO MYNAM
": Using 64 bit consistent mask\n"));
else
@@ -1243,6 +1181,16 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pcixcmd &= 0x8F;
pci_write_config_byte(pdev, 0x6a, pcixcmd);
}
+ else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC939X) {
+ ioc->prod_name = "LSIFC939X";
+ ioc->bus_type = FC;
+ ioc->errata_flag_1064 = 1;
+ }
+ else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949X) {
+ ioc->prod_name = "LSIFC949X";
+ ioc->bus_type = FC;
+ ioc->errata_flag_1064 = 1;
+ }
else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
ioc->prod_name = "LSI53C1030";
ioc->bus_type = SCSI;
@@ -1261,6 +1209,9 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->bus_type = SCSI;
}
+ if (ioc->errata_flag_1064)
+ pci_disable_io_access(pdev);
+
sprintf(ioc->name, "ioc%d", ioc->id);
spin_lock_init(&ioc->FreeQlock);
@@ -1303,8 +1254,7 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
#endif
}
- /* NEW! 20010220 -sralston
- * Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
+ /* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
*/
mpt_detect_bound_ports(ioc, pdev);
@@ -1354,13 +1304,13 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
- * mptbase_remove - Remove a PCI intelligent MPT adapter.
+ * mpt_detach - Remove a PCI intelligent MPT adapter.
* @pdev: Pointer to pci_dev structure
*
*/
-static void __devexit
-mptbase_remove(struct pci_dev *pdev)
+void
+mpt_detach(struct pci_dev *pdev)
{
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
char pname[32];
@@ -1397,43 +1347,21 @@ mptbase_remove(struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL);
}
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- * mptbase_shutdown -
- *
- */
-static void
-mptbase_shutdown(struct device * dev)
-{
- int ii;
-
- /* call per device driver shutdown entry point */
- for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
- if(MptDeviceDriverHandlers[ii] &&
- MptDeviceDriverHandlers[ii]->shutdown) {
- MptDeviceDriverHandlers[ii]->shutdown(dev);
- }
- }
-
-}
-
-
/**************************************************************************
* Power Management
*/
#ifdef CONFIG_PM
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
- * mptbase_suspend - Fusion MPT base driver suspend routine.
+ * mpt_suspend - Fusion MPT base driver suspend routine.
*
*
*/
-static int
-mptbase_suspend(struct pci_dev *pdev, pm_message_t state)
+int
+mpt_suspend(struct pci_dev *pdev, pm_message_t state)
{
u32 device_state;
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
- int ii;
switch(state)
{
@@ -1453,14 +1381,6 @@ mptbase_suspend(struct pci_dev *pdev, pm_message_t state)
"pci-suspend: pdev=0x%p, slot=%s, Entering operating state [D%d]\n",
ioc->name, pdev, pci_name(pdev), device_state);
- /* call per device driver suspend entry point */
- for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
- if(MptDeviceDriverHandlers[ii] &&
- MptDeviceDriverHandlers[ii]->suspend) {
- MptDeviceDriverHandlers[ii]->suspend(pdev, state);
- }
- }
-
pci_save_state(pdev);
/* put ioc into READY_STATE */
@@ -1484,18 +1404,18 @@ mptbase_suspend(struct pci_dev *pdev, pm_message_t state)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
- * mptbase_resume - Fusion MPT base driver resume routine.
+ * mpt_resume - Fusion MPT base driver resume routine.
*
*
*/
-static int
-mptbase_resume(struct pci_dev *pdev)
+int
+mpt_resume(struct pci_dev *pdev)
{
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
u32 device_state = pdev->current_state;
int recovery_state;
int ii;
-
+
printk(MYIOC_s_INFO_FMT
"pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
ioc->name, pdev, pci_name(pdev), device_state);
@@ -1533,14 +1453,6 @@ mptbase_resume(struct pci_dev *pdev)
"pci-resume: success\n", ioc->name);
}
- /* call per device driver resume entry point */
- for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
- if(MptDeviceDriverHandlers[ii] &&
- MptDeviceDriverHandlers[ii]->resume) {
- MptDeviceDriverHandlers[ii]->resume(pdev);
- }
- }
-
return 0;
}
#endif
@@ -1719,8 +1631,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
ioc->alt_ioc->active = 1;
}
- /* NEW! 20010120 -sralston
- * Enable MPT base driver management of EventNotification
+ /* Enable MPT base driver management of EventNotification
* and EventAck handling.
*/
if ((ret == 0) && (!ioc->facts.EventState))
@@ -1729,9 +1640,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
(void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */
- /* (Bugzilla:fibrebugs, #513)
- * Bug fix (part 2)! 20010905 -sralston
- * Add additional "reason" check before call to GetLanConfigPages
+ /* Add additional "reason" check before call to GetLanConfigPages
* (combined with GetIoUnitPage2 call). This prevents a somewhat
* recursive scenario; GetLanConfigPages times out, timer expired
* routine calls HardResetHandler, which calls into here again,
@@ -1829,37 +1738,43 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
static void
mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
{
- unsigned int match_lo, match_hi;
+ struct pci_dev *peer=NULL;
+ unsigned int slot = PCI_SLOT(pdev->devfn);
+ unsigned int func = PCI_FUNC(pdev->devfn);
MPT_ADAPTER *ioc_srch;
- match_lo = pdev->devfn-1;
- match_hi = pdev->devfn+1;
- dprintk((MYIOC_s_INFO_FMT "PCI bus/devfn=%x/%x, searching for devfn match on %x or %x\n",
- ioc->name, pdev->bus->number, pdev->devfn, match_lo, match_hi));
+ dprintk((MYIOC_s_INFO_FMT "PCI device %s devfn=%x/%x,"
+ " searching for devfn match on %x or %x\n",
+ ioc->name, pci_name(pdev), pdev->devfn,
+ func-1, func+1));
+
+ peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
+ if (!peer) {
+ peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1));
+ if (!peer)
+ return;
+ }
list_for_each_entry(ioc_srch, &ioc_list, list) {
struct pci_dev *_pcidev = ioc_srch->pcidev;
-
- if ((_pcidev->device == pdev->device) &&
- (_pcidev->bus->number == pdev->bus->number) &&
- (_pcidev->devfn == match_lo || _pcidev->devfn == match_hi) ) {
+ if (_pcidev == peer) {
/* Paranoia checks */
if (ioc->alt_ioc != NULL) {
printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
- ioc->name, ioc->alt_ioc->name);
+ ioc->name, ioc->alt_ioc->name);
break;
} else if (ioc_srch->alt_ioc != NULL) {
printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
- ioc_srch->name, ioc_srch->alt_ioc->name);
+ ioc_srch->name, ioc_srch->alt_ioc->name);
break;
}
dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n",
- ioc->name, ioc_srch->name));
+ ioc->name, ioc_srch->name));
ioc_srch->alt_ioc = ioc;
ioc->alt_ioc = ioc_srch;
- break;
}
}
+ pci_dev_put(peer);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1922,15 +1837,10 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
ioc->alloc_total -= sz;
}
- if (ioc->spi_data.nvram != NULL) {
- kfree(ioc->spi_data.nvram);
- ioc->spi_data.nvram = NULL;
- }
-
- if (ioc->spi_data.pIocPg3 != NULL) {
- kfree(ioc->spi_data.pIocPg3);
- ioc->spi_data.pIocPg3 = NULL;
- }
+ kfree(ioc->spi_data.nvram);
+ kfree(ioc->spi_data.pIocPg3);
+ ioc->spi_data.nvram = NULL;
+ ioc->spi_data.pIocPg3 = NULL;
if (ioc->spi_data.pIocPg4 != NULL) {
sz = ioc->spi_data.IocPg4Sz;
@@ -1947,10 +1857,8 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
ioc->ReqToChain = NULL;
}
- if (ioc->ChainToChain != NULL) {
- kfree(ioc->ChainToChain);
- ioc->ChainToChain = NULL;
- }
+ kfree(ioc->ChainToChain);
+ ioc->ChainToChain = NULL;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2333,7 +2241,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
return -55;
}
- r = sz = le32_to_cpu(facts->BlockSize);
+ r = sz = facts->BlockSize;
vv = ((63 / (sz * 4)) + 1) & 0x03;
ioc->NB_for_64_byte_frame = vv;
while ( sz )
@@ -2785,7 +2693,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
/* prevent a second downloadboot and memory free with alt_ioc */
if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
ioc->alt_ioc->cached_fw = NULL;
-
+
CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
@@ -2843,6 +2751,9 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
/* Write the LoadStartAddress to the DiagRw Address Register
* using Programmed IO
*/
+ if (ioc->errata_flag_1064)
+ pci_enable_io_access(ioc->pcidev);
+
CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n",
ioc->name, pFwHeader->LoadStartAddress));
@@ -2889,6 +2800,9 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
+ if (ioc->errata_flag_1064)
+ pci_disable_io_access(ioc->pcidev);
+
diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT, DISABLE_ARM\n",
ioc->name, diag0val));
@@ -4250,7 +4164,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
(ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) {
- if (ioc->spi_data.minSyncFactor < MPT_ULTRA)
+ if (ioc->spi_data.minSyncFactor < MPT_ULTRA)
ioc->spi_data.minSyncFactor = MPT_ULTRA;
}
}
@@ -4482,10 +4396,8 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
/* Free the old page
*/
- if (ioc->spi_data.pIocPg3) {
- kfree(ioc->spi_data.pIocPg3);
- ioc->spi_data.pIocPg3 = NULL;
- }
+ kfree(ioc->spi_data.pIocPg3);
+ ioc->spi_data.pIocPg3 = NULL;
/* There is at least one physical disk.
* Read and save IOC Page 3
@@ -4753,9 +4665,7 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
u32 flagsLength;
int in_isr;
- /* (Bugzilla:fibrebugs, #513)
- * Bug fix (part 1)! 20010905 -sralston
- * Prevent calling wait_event() (below), if caller happens
+ /* Prevent calling wait_event() (below), if caller happens
* to be in ISR context, because that is fatal!
*/
in_isr = in_interrupt();
@@ -4861,9 +4771,7 @@ mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
u32 flagsLength;
int in_isr;
- /* (Bugzilla:fibrebugs, #513)
- * Bug fix (part 1)! 20010905 -sralston
- * Prevent calling wait_event() (below), if caller happens
+ /* Prevent calling wait_event() (below), if caller happens
* to be in ISR context, because that is fatal!
*/
in_isr = in_interrupt();
@@ -5130,20 +5038,26 @@ static int
procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
{
int ii;
- int scsi, lan, ctl, targ, dmp;
+ int scsi, fc, sas, lan, ctl, targ, dmp;
char *drvname;
int len;
len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
len += sprintf(buf+len, " Fusion MPT base driver\n");
- scsi = lan = ctl = targ = dmp = 0;
+ scsi = fc = sas = lan = ctl = targ = dmp = 0;
for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
drvname = NULL;
if (MptCallbacks[ii]) {
switch (MptDriverClass[ii]) {
- case MPTSCSIH_DRIVER:
- if (!scsi++) drvname = "SCSI host";
+ case MPTSPI_DRIVER:
+ if (!scsi++) drvname = "SPI host";
+ break;
+ case MPTFC_DRIVER:
+ if (!fc++) drvname = "FC host";
+ break;
+ case MPTSAS_DRIVER:
+ if (!sas++) drvname = "SAS host";
break;
case MPTLAN_DRIVER:
if (!lan++) drvname = "LAN";
@@ -5832,6 +5746,12 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+EXPORT_SYMBOL(mpt_attach);
+EXPORT_SYMBOL(mpt_detach);
+#ifdef CONFIG_PM
+EXPORT_SYMBOL(mpt_resume);
+EXPORT_SYMBOL(mpt_suspend);
+#endif
EXPORT_SYMBOL(ioc_list);
EXPORT_SYMBOL(mpt_proc_root_dir);
EXPORT_SYMBOL(mpt_register);
@@ -5860,19 +5780,6 @@ EXPORT_SYMBOL(mpt_read_ioc_pg_3);
EXPORT_SYMBOL(mpt_alloc_fw_memory);
EXPORT_SYMBOL(mpt_free_fw_memory);
-static struct pci_driver mptbase_driver = {
- .name = "mptbase",
- .id_table = mptbase_pci_table,
- .probe = mptbase_probe,
- .remove = __devexit_p(mptbase_remove),
- .driver = {
- .shutdown = mptbase_shutdown,
- },
-#ifdef CONFIG_PM
- .suspend = mptbase_suspend,
- .resume = mptbase_resume,
-#endif
-};
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@@ -5884,7 +5791,6 @@ static int __init
fusion_init(void)
{
int i;
- int r;
show_mptmod_ver(my_NAME, my_VERSION);
printk(KERN_INFO COPYRIGHT "\n");
@@ -5896,8 +5802,7 @@ fusion_init(void)
MptResetHandlers[i] = NULL;
}
- /* NEW! 20010120 -sralston
- * Register ourselves (mptbase) in order to facilitate
+ /* Register ourselves (mptbase) in order to facilitate
* EventNotification handling.
*/
mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
@@ -5913,11 +5818,7 @@ fusion_init(void)
#ifdef CONFIG_PROC_FS
(void) procmpt_create();
#endif
- r = pci_register_driver(&mptbase_driver);
- if(r)
- return(r);
-
- return r;
+ return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -5933,7 +5834,6 @@ fusion_exit(void)
dexitprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
- pci_unregister_driver(&mptbase_driver);
mpt_reset_deregister(mpt_base_index);
#ifdef CONFIG_PROC_FS
@@ -5941,6 +5841,5 @@ fusion_exit(void)
#endif
}
-
module_init(fusion_init);
module_exit(fusion_exit);
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 6d16acc7a17..848fb236b17 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -5,15 +5,9 @@
* LSIFC9xx/LSI409xx Fibre Channel
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
- * Credits:
- * (see mptbase.c)
- *
- * Copyright (c) 1999-2004 LSI Logic Corporation
- * Originally By: Steven J. Ralston
- * (mailto:sjralston1@netscape.net)
+ * Copyright (c) 1999-2005 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
*
- * $Id: mptbase.h,v 1.144 2003/01/28 21:31:56 pdelaney Exp $
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@@ -71,7 +65,6 @@
#include "lsi/mpi_fc.h" /* Fibre Channel (lowlevel) support */
#include "lsi/mpi_targ.h" /* SCSI/FCP Target protcol support */
#include "lsi/mpi_tool.h" /* Tools support */
-#include "lsi/fc_log.h"
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -80,11 +73,11 @@
#endif
#ifndef COPYRIGHT
-#define COPYRIGHT "Copyright (c) 1999-2004 " MODULEAUTHOR
+#define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR
#endif
-#define MPT_LINUX_VERSION_COMMON "3.01.20"
-#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.01.20"
+#define MPT_LINUX_VERSION_COMMON "3.03.02"
+#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.02"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \
@@ -203,7 +196,9 @@
typedef enum {
MPTBASE_DRIVER, /* MPT base class */
MPTCTL_DRIVER, /* MPT ioctl class */
- MPTSCSIH_DRIVER, /* MPT SCSI host (initiator) class */
+ MPTSPI_DRIVER, /* MPT SPI host class */
+ MPTFC_DRIVER, /* MPT FC host class */
+ MPTSAS_DRIVER, /* MPT SAS host class */
MPTLAN_DRIVER, /* MPT LAN class */
MPTSTM_DRIVER, /* MPT SCSI target mode class */
MPTUNKNOWN_DRIVER
@@ -212,11 +207,6 @@ typedef enum {
struct mpt_pci_driver{
int (*probe) (struct pci_dev *dev, const struct pci_device_id *id);
void (*remove) (struct pci_dev *dev);
- void (*shutdown) (struct device * dev);
-#ifdef CONFIG_PM
- int (*resume) (struct pci_dev *dev);
- int (*suspend) (struct pci_dev *dev, pm_message_t state);
-#endif
};
/*
@@ -483,6 +473,7 @@ typedef struct _ScsiCfgData {
u8 forceDv; /* 1 to force DV scheduling */
u8 noQas; /* Disable QAS for this adapter */
u8 Saf_Te; /* 1 to force all Processors as SAF-TE if Inquiry data length is too short to check for SAF-TE */
+ u8 mpt_dv; /* command line option: enhanced=1, basic=0 */
u8 rsvd[1];
} ScsiCfgData;
@@ -571,11 +562,21 @@ typedef struct _MPT_ADAPTER
FCPortPage0_t fc_port_page0[2];
LANPage0_t lan_cnfg_page0;
LANPage1_t lan_cnfg_page1;
+ /*
+ * Description: errata_flag_1064
+ * If a PCIX read occurs within 1 or 2 cycles after the chip receives
+ * a split completion for a read data, an internal address pointer incorrectly
+ * increments by 32 bytes
+ */
+ int errata_flag_1064;
u8 FirstWhoInit;
u8 upload_fw; /* If set, do a fw upload */
u8 reload_fw; /* Force a FW Reload on next reset */
u8 NBShiftFactor; /* NB Shift Factor based on Block Size (Facts) */
u8 pad1[4];
+ int DoneCtx;
+ int TaskCtx;
+ int InternalCtx;
struct list_head list;
struct net_device *netdev;
} MPT_ADAPTER;
@@ -773,12 +774,6 @@ typedef struct _mpt_sge {
#define DBG_DUMP_TM_REPLY_FRAME(mfp)
#endif
-#ifdef MPT_DEBUG_NEH
-#define nehprintk(x) printk x
-#else
-#define nehprintk(x)
-#endif
-
#if defined(MPT_DEBUG_CONFIG) || defined(MPT_DEBUG)
#define dcprintk(x) printk x
#else
@@ -898,6 +893,11 @@ typedef struct _MPT_SCSI_HOST {
unsigned long soft_resets; /* fw/external bus resets count */
unsigned long timeouts; /* cmd timeouts */
ushort sel_timeout[MPT_MAX_FC_DEVICES];
+ char *info_kbuf;
+ wait_queue_head_t scandv_waitq;
+ int scandv_wait_done;
+ long last_queue_full;
+ u8 mpt_pq_filter;
} MPT_SCSI_HOST;
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -931,6 +931,12 @@ typedef struct _x_config_parms {
/*
* Public entry points...
*/
+extern int mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id);
+extern void mpt_detach(struct pci_dev *pdev);
+#ifdef CONFIG_PM
+extern int mpt_suspend(struct pci_dev *pdev, pm_message_t state);
+extern int mpt_resume(struct pci_dev *pdev);
+#endif
extern int mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass);
extern void mpt_deregister(int cb_idx);
extern int mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc);
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 70b0cfb5ac5..05ea5944c48 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -1,40 +1,12 @@
/*
* linux/drivers/message/fusion/mptctl.c
- * Fusion MPT misc device (ioctl) driver.
- * For use with PCI chip/adapter(s):
- * LSIFC9xx/LSI409xx Fibre Channel
+ * mpt Ioctl driver.
+ * For use with LSI Logic PCI chip/adapters
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
- * Credits:
- * This driver would not exist if not for Alan Cox's development
- * of the linux i2o driver.
- *
- * A special thanks to Pamela Delaney (LSI Logic) for tons of work
- * and countless enhancements while adding support for the 1030
- * chip family. Pam has been instrumental in the development of
- * of the 2.xx.xx series fusion drivers, and her contributions are
- * far too numerous to hope to list in one place.
- *
- * A huge debt of gratitude is owed to David S. Miller (DaveM)
- * for fixing much of the stupid and broken stuff in the early
- * driver while porting to sparc64 platform. THANK YOU!
- *
- * A big THANKS to Eddie C. Dost for fixing the ioctl path
- * and most importantly f/w download on sparc64 platform!
- * (plus Eddie's other helpful hints and insights)
- *
- * Thanks to Arnaldo Carvalho de Melo for finding and patching
- * a potential memory leak in mptctl_do_fw_download(),
- * and for some kmalloc insight:-)
- *
- * (see also mptbase.c)
- *
- * Copyright (c) 1999-2004 LSI Logic Corporation
- * Originally By: Steven J. Ralston, Noah Romer
- * (mailto:sjralston1@netscape.net)
+ * Copyright (c) 1999-2005 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
*
- * $Id: mptctl.c,v 1.63 2002/12/03 21:26:33 pdelaney Exp $
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@@ -95,8 +67,8 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
-#define COPYRIGHT "Copyright (c) 1999-2004 LSI Logic Corporation"
-#define MODULEAUTHOR "Steven J. Ralston, Noah Romer, Pamela Delaney"
+#define COPYRIGHT "Copyright (c) 1999-2005 LSI Logic Corporation"
+#define MODULEAUTHOR "LSI Logic Corporation"
#include "mptbase.h"
#include "mptctl.h"
@@ -127,14 +99,14 @@ struct buflist {
* arg contents specific to function.
*/
static int mptctl_fw_download(unsigned long arg);
-static int mptctl_getiocinfo (unsigned long arg, unsigned int cmd);
-static int mptctl_gettargetinfo (unsigned long arg);
-static int mptctl_readtest (unsigned long arg);
-static int mptctl_mpt_command (unsigned long arg);
-static int mptctl_eventquery (unsigned long arg);
-static int mptctl_eventenable (unsigned long arg);
-static int mptctl_eventreport (unsigned long arg);
-static int mptctl_replace_fw (unsigned long arg);
+static int mptctl_getiocinfo(unsigned long arg, unsigned int cmd);
+static int mptctl_gettargetinfo(unsigned long arg);
+static int mptctl_readtest(unsigned long arg);
+static int mptctl_mpt_command(unsigned long arg);
+static int mptctl_eventquery(unsigned long arg);
+static int mptctl_eventenable(unsigned long arg);
+static int mptctl_eventreport(unsigned long arg);
+static int mptctl_replace_fw(unsigned long arg);
static int mptctl_do_reset(unsigned long arg);
static int mptctl_hp_hostinfo(unsigned long arg, unsigned int cmd);
@@ -149,11 +121,11 @@ static long compat_mpctl_ioctl(struct file *f, unsigned cmd, unsigned long arg);
/*
* Private function calls.
*/
-static int mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr);
+static int mptctl_do_mpt_command(struct mpt_ioctl_command karg, void __user *mfPtr);
static int mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen);
-static MptSge_t *kbuf_alloc_2_sgl( int bytes, u32 dir, int sge_offset, int *frags,
+static MptSge_t *kbuf_alloc_2_sgl(int bytes, u32 dir, int sge_offset, int *frags,
struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc);
-static void kfree_sgl( MptSge_t *sgl, dma_addr_t sgl_dma,
+static void kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma,
struct buflist *buflist, MPT_ADAPTER *ioc);
static void mptctl_timeout_expired (MPT_IOCTL *ioctl);
static int mptctl_bus_reset(MPT_IOCTL *ioctl);
@@ -1119,7 +1091,7 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
int numDevices = 0;
unsigned int max_id;
int ii;
- int port;
+ unsigned int port;
int cim_rev;
u8 revision;
@@ -1162,9 +1134,7 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
return -ENODEV;
}
- /* Verify the data transfer size is correct.
- * Ignore the port setting.
- */
+ /* Verify the data transfer size is correct. */
if (karg->hdr.maxDataSize != data_size) {
printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "
"Structure size mismatch. Command not completed.\n",
@@ -1181,6 +1151,8 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
else
karg->adapterType = MPT_IOCTL_INTERFACE_SCSI;
+ if (karg->hdr.port > 1)
+ return -EINVAL;
port = karg->hdr.port;
karg->port = port;
diff --git a/drivers/message/fusion/mptctl.h b/drivers/message/fusion/mptctl.h
index cc4ecf0382d..28754a9cb80 100644
--- a/drivers/message/fusion/mptctl.h
+++ b/drivers/message/fusion/mptctl.h
@@ -5,22 +5,9 @@
* LSIFC9xx/LSI409xx Fibre Channel
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
- * Credits:
- * This driver would not exist if not for Alan Cox's development
- * of the linux i2o driver.
- *
- * A huge debt of gratitude is owed to David S. Miller (DaveM)
- * for fixing much of the stupid and broken stuff in the early
- * driver while porting to sparc64 platform. THANK YOU!
- *
- * (see also mptbase.c)
- *
- * Copyright (c) 1999-2004 LSI Logic Corporation
- * Originally By: Steven J. Ralston
- * (mailto:sjralston1@netscape.net)
+ * Copyright (c) 1999-2005 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
*
- * $Id: mptctl.h,v 1.13 2002/12/03 21:26:33 pdelaney Exp $
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
new file mode 100644
index 00000000000..d8d65397e06
--- /dev/null
+++ b/drivers/message/fusion/mptfc.c
@@ -0,0 +1,431 @@
+/*
+ * linux/drivers/message/fusion/mptfc.c
+ * For use with LSI Logic PCI chip/adapter(s)
+ * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+ *
+ * Copyright (c) 1999-2005 LSI Logic Corporation
+ * (mailto:mpt_linux_developer@lsil.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; version 2 of the License.
+
+ 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.
+
+ NO WARRANTY
+ THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ solely responsible for determining the appropriateness of using and
+ distributing the Program and assumes all risks associated with its
+ exercise of rights under this Agreement, including but not limited to
+ the risks and costs of program errors, damage to or loss of data,
+ programs or equipment, and unavailability or interruption of operations.
+
+ DISCLAIMER OF LIABILITY
+ NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+ 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 "linux_compat.h" /* linux-2.6 tweaks */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/kdev_t.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h> /* for mdelay */
+#include <linux/interrupt.h> /* needed for in_interrupt() proto */
+#include <linux/reboot.h> /* notifier code */
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+
+#include "mptbase.h"
+#include "mptscsih.h"
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+#define my_NAME "Fusion MPT FC Host driver"
+#define my_VERSION MPT_LINUX_VERSION_COMMON
+#define MYNAM "mptfc"
+
+MODULE_AUTHOR(MODULEAUTHOR);
+MODULE_DESCRIPTION(my_NAME);
+MODULE_LICENSE("GPL");
+
+/* Command line args */
+static int mpt_pq_filter = 0;
+module_param(mpt_pq_filter, int, 0);
+MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)");
+
+static int mptfcDoneCtx = -1;
+static int mptfcTaskCtx = -1;
+static int mptfcInternalCtx = -1; /* Used only for internal commands */
+
+static struct device_attribute mptfc_queue_depth_attr = {
+ .attr = {
+ .name = "queue_depth",
+ .mode = S_IWUSR,
+ },
+ .store = mptscsih_store_queue_depth,
+};
+
+static struct device_attribute *mptfc_dev_attrs[] = {
+ &mptfc_queue_depth_attr,
+ NULL,
+};
+
+static struct scsi_host_template mptfc_driver_template = {
+ .proc_name = "mptfc",
+ .proc_info = mptscsih_proc_info,
+ .name = "MPT FC Host",
+ .info = mptscsih_info,
+ .queuecommand = mptscsih_qcmd,
+ .slave_alloc = mptscsih_slave_alloc,
+ .slave_configure = mptscsih_slave_configure,
+ .slave_destroy = mptscsih_slave_destroy,
+ .eh_abort_handler = mptscsih_abort,
+ .eh_device_reset_handler = mptscsih_dev_reset,
+ .eh_bus_reset_handler = mptscsih_bus_reset,
+ .eh_host_reset_handler = mptscsih_host_reset,
+ .bios_param = mptscsih_bios_param,
+ .can_queue = MPT_FC_CAN_QUEUE,
+ .this_id = -1,
+ .sg_tablesize = MPT_SCSI_SG_DEPTH,
+ .max_sectors = 8192,
+ .cmd_per_lun = 7,
+ .use_clustering = ENABLE_CLUSTERING,
+ .sdev_attrs = mptfc_dev_attrs,
+};
+
+/****************************************************************************
+ * Supported hardware
+ */
+
+static struct pci_device_id mptfc_pci_table[] = {
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC909,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919X,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929X,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC939X,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949X,
+ PCI_ANY_ID, PCI_ANY_ID },
+ {0} /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ * mptfc_probe - Installs scsi devices per bus.
+ * @pdev: Pointer to pci_dev structure
+ *
+ * Returns 0 for success, non-zero for failure.
+ *
+ */
+static int
+mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ struct Scsi_Host *sh;
+ MPT_SCSI_HOST *hd;
+ MPT_ADAPTER *ioc;
+ unsigned long flags;
+ int sz, ii;
+ int numSGE = 0;
+ int scale;
+ int ioc_cap;
+ u8 *mem;
+ int error=0;
+ int r;
+
+ if ((r = mpt_attach(pdev,id)) != 0)
+ return r;
+
+ ioc = pci_get_drvdata(pdev);
+ ioc->DoneCtx = mptfcDoneCtx;
+ ioc->TaskCtx = mptfcTaskCtx;
+ ioc->InternalCtx = mptfcInternalCtx;
+
+ /* Added sanity check on readiness of the MPT adapter.
+ */
+ if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
+ printk(MYIOC_s_WARN_FMT
+ "Skipping because it's not operational!\n",
+ ioc->name);
+ return -ENODEV;
+ }
+
+ if (!ioc->active) {
+ printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
+ ioc->name);
+ return -ENODEV;
+ }
+
+ /* Sanity check - ensure at least 1 port is INITIATOR capable
+ */
+ ioc_cap = 0;
+ for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
+ if (ioc->pfacts[ii].ProtocolFlags &
+ MPI_PORTFACTS_PROTOCOL_INITIATOR)
+ ioc_cap ++;
+ }
+
+ if (!ioc_cap) {
+ printk(MYIOC_s_WARN_FMT
+ "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
+ ioc->name, ioc);
+ return -ENODEV;
+ }
+
+ sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
+
+ if (!sh) {
+ printk(MYIOC_s_WARN_FMT
+ "Unable to register controller with SCSI subsystem\n",
+ ioc->name);
+ return -1;
+ }
+
+ spin_lock_irqsave(&ioc->FreeQlock, flags);
+
+ /* Attach the SCSI Host to the IOC structure
+ */
+ ioc->sh = sh;
+
+ sh->io_port = 0;
+ sh->n_io_port = 0;
+ sh->irq = 0;
+
+ /* set 16 byte cdb's */
+ sh->max_cmd_len = 16;
+
+ sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
+
+ sh->max_lun = MPT_LAST_LUN + 1;
+ sh->max_channel = 0;
+ sh->this_id = ioc->pfacts[0].PortSCSIID;
+
+ /* Required entry.
+ */
+ sh->unique_id = ioc->id;
+
+ /* Verify that we won't exceed the maximum
+ * number of chain buffers
+ * We can optimize: ZZ = req_sz/sizeof(SGE)
+ * For 32bit SGE's:
+ * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
+ * + (req_sz - 64)/sizeof(SGE)
+ * A slightly different algorithm is required for
+ * 64bit SGEs.
+ */
+ scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
+ if (sizeof(dma_addr_t) == sizeof(u64)) {
+ numSGE = (scale - 1) *
+ (ioc->facts.MaxChainDepth-1) + scale +
+ (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
+ sizeof(u32));
+ } else {
+ numSGE = 1 + (scale - 1) *
+ (ioc->facts.MaxChainDepth-1) + scale +
+ (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
+ sizeof(u32));
+ }
+
+ if (numSGE < sh->sg_tablesize) {
+ /* Reset this value */
+ dprintk((MYIOC_s_INFO_FMT
+ "Resetting sg_tablesize to %d from %d\n",
+ ioc->name, numSGE, sh->sg_tablesize));
+ sh->sg_tablesize = numSGE;
+ }
+
+ /* Set the pci device pointer in Scsi_Host structure.
+ */
+ scsi_set_device(sh, &ioc->pcidev->dev);
+
+ spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+
+ hd = (MPT_SCSI_HOST *) sh->hostdata;
+ hd->ioc = ioc;
+
+ /* SCSI needs scsi_cmnd lookup table!
+ * (with size equal to req_depth*PtrSz!)
+ */
+ sz = ioc->req_depth * sizeof(void *);
+ mem = kmalloc(sz, GFP_ATOMIC);
+ if (mem == NULL) {
+ error = -ENOMEM;
+ goto mptfc_probe_failed;
+ }
+
+ memset(mem, 0, sz);
+ hd->ScsiLookup = (struct scsi_cmnd **) mem;
+
+ dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
+ ioc->name, hd->ScsiLookup, sz));
+
+ /* Allocate memory for the device structures.
+ * A non-Null pointer at an offset
+ * indicates a device exists.
+ * max_id = 1 + maximum id (hosts.h)
+ */
+ sz = sh->max_id * sizeof(void *);
+ mem = kmalloc(sz, GFP_ATOMIC);
+ if (mem == NULL) {
+ error = -ENOMEM;
+ goto mptfc_probe_failed;
+ }
+
+ memset(mem, 0, sz);
+ hd->Targets = (VirtDevice **) mem;
+
+ dprintk((KERN_INFO
+ " Targets @ %p, sz=%d\n", hd->Targets, sz));
+
+ /* Clear the TM flags
+ */
+ hd->tmPending = 0;
+ hd->tmState = TM_STATE_NONE;
+ hd->resetPending = 0;
+ hd->abortSCpnt = NULL;
+
+ /* Clear the pointer used to store
+ * single-threaded commands, i.e., those
+ * issued during a bus scan, dv and
+ * configuration pages.
+ */
+ hd->cmdPtr = NULL;
+
+ /* Initialize this SCSI Hosts' timers
+ * To use, set the timer expires field
+ * and add_timer
+ */
+ init_timer(&hd->timer);
+ hd->timer.data = (unsigned long) hd;
+ hd->timer.function = mptscsih_timer_expired;
+
+ hd->mpt_pq_filter = mpt_pq_filter;
+
+ ddvprintk((MYIOC_s_INFO_FMT
+ "mpt_pq_filter %x\n",
+ ioc->name,
+ mpt_pq_filter));
+
+ init_waitqueue_head(&hd->scandv_waitq);
+ hd->scandv_wait_done = 0;
+ hd->last_queue_full = 0;
+
+ error = scsi_add_host (sh, &ioc->pcidev->dev);
+ if(error) {
+ dprintk((KERN_ERR MYNAM
+ "scsi_add_host failed\n"));
+ goto mptfc_probe_failed;
+ }
+
+ scsi_scan_host(sh);
+ return 0;
+
+mptfc_probe_failed:
+
+ mptscsih_remove(pdev);
+ return error;
+}
+
+static struct pci_driver mptfc_driver = {
+ .name = "mptfc",
+ .id_table = mptfc_pci_table,
+ .probe = mptfc_probe,
+ .remove = __devexit_p(mptscsih_remove),
+ .driver = {
+ .shutdown = mptscsih_shutdown,
+ },
+#ifdef CONFIG_PM
+ .suspend = mptscsih_suspend,
+ .resume = mptscsih_resume,
+#endif
+};
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ * mptfc_init - Register MPT adapter(s) as SCSI host(s) with
+ * linux scsi mid-layer.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int __init
+mptfc_init(void)
+{
+
+ show_mptmod_ver(my_NAME, my_VERSION);
+
+ mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER);
+ mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
+ mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
+
+ if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) {
+ devtprintk((KERN_INFO MYNAM
+ ": Registered for IOC event notifications\n"));
+ }
+
+ if (mpt_reset_register(mptfcDoneCtx, mptscsih_ioc_reset) == 0) {
+ dprintk((KERN_INFO MYNAM
+ ": Registered for IOC reset notifications\n"));
+ }
+
+ return pci_register_driver(&mptfc_driver);
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ * mptfc_exit - Unregisters MPT adapter(s)
+ *
+ */
+static void __exit
+mptfc_exit(void)
+{
+ pci_unregister_driver(&mptfc_driver);
+
+ mpt_reset_deregister(mptfcDoneCtx);
+ dprintk((KERN_INFO MYNAM
+ ": Deregistered for IOC reset notifications\n"));
+
+ mpt_event_deregister(mptfcDoneCtx);
+ dprintk((KERN_INFO MYNAM
+ ": Deregistered for IOC event notifications\n"));
+
+ mpt_deregister(mptfcInternalCtx);
+ mpt_deregister(mptfcTaskCtx);
+ mpt_deregister(mptfcDoneCtx);
+}
+
+module_init(mptfc_init);
+module_exit(mptfc_exit);
diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
index ef2713b93fa..52794be5a95 100644
--- a/drivers/message/fusion/mptlan.c
+++ b/drivers/message/fusion/mptlan.c
@@ -1,33 +1,11 @@
/*
* linux/drivers/message/fusion/mptlan.c
* IP Over Fibre Channel device driver.
- * For use with PCI chip/adapter(s):
- * LSIFC9xx/LSI409xx Fibre Channel
+ * For use with LSI Logic Fibre Channel PCI chip/adapters
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
- * Credits:
- * This driver would not exist if not for Alan Cox's development
- * of the linux i2o driver.
+ * Copyright (c) 2000-2005 LSI Logic Corporation
*
- * Special thanks goes to the I2O LAN driver people at the
- * University of Helsinki, who, unbeknownst to them, provided
- * the inspiration and initial structure for this driver.
- *
- * A huge debt of gratitude is owed to David S. Miller (DaveM)
- * for fixing much of the stupid and broken stuff in the early
- * driver while porting to sparc64 platform. THANK YOU!
- *
- * A really huge debt of gratitude is owed to Eddie C. Dost
- * for gobs of hard work fixing and optimizing LAN code.
- * THANK YOU!
- *
- * (see also mptbase.c)
- *
- * Copyright (c) 2000-2004 LSI Logic Corporation
- * Originally By: Noah Romer
- * (mailto:mpt_linux_developer@lsil.com)
- *
- * $Id: mptlan.c,v 1.53 2002/10/17 20:15:58 pdelaney Exp $
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@@ -221,7 +199,7 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
// NOTE! (Optimization) First case here is now caught in
// mptbase.c::mpt_interrupt() routine and callcack here
- // is now skipped for this case! 20001218 -sralston
+ // is now skipped for this case!
#if 0
case LAN_REPLY_FORM_MESSAGE_CONTEXT:
// dioprintk((KERN_INFO MYNAM "/lan_reply: "
@@ -234,7 +212,7 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
// dioprintk((MYNAM "/lan_reply: "
// "calling mpt_lan_send_reply (turbo)\n"));
- // Potential BUG here? -sralston
+ // Potential BUG here?
// FreeReqFrame = mpt_lan_send_turbo(dev, tmsg);
// If/when mpt_lan_send_turbo would return 1 here,
// calling routine (mptbase.c|mpt_interrupt)
@@ -310,8 +288,7 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
case MPI_FUNCTION_EVENT_NOTIFICATION:
case MPI_FUNCTION_EVENT_ACK:
- /* UPDATE! 20010120 -sralston
- * _EVENT_NOTIFICATION should NOT come down this path any more.
+ /* _EVENT_NOTIFICATION should NOT come down this path any more.
* Should be routed to mpt_lan_event_process(), but just in case...
*/
FreeReqFrame = 1;
@@ -561,8 +538,8 @@ mpt_lan_close(struct net_device *dev)
}
}
- kfree (priv->RcvCtl);
- kfree (priv->mpt_rxfidx);
+ kfree(priv->RcvCtl);
+ kfree(priv->mpt_rxfidx);
for (i = 0; i < priv->tx_max_out; i++) {
if (priv->SendCtl[i].skb != NULL) {
diff --git a/drivers/message/fusion/mptlan.h b/drivers/message/fusion/mptlan.h
index 057904260ab..750e343eb98 100644
--- a/drivers/message/fusion/mptlan.h
+++ b/drivers/message/fusion/mptlan.h
@@ -1,3 +1,49 @@
+/*
+ * linux/drivers/message/fusion/mptlan.h
+ * IP Over Fibre Channel device driver.
+ * For use with LSI Logic Fibre Channel PCI chip/adapters
+ * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+ *
+ * Copyright (c) 2000-2005 LSI Logic Corporation
+ *
+ */
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ 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; version 2 of the License.
+
+ 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.
+
+ NO WARRANTY
+ THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ solely responsible for determining the appropriateness of using and
+ distributing the Program and assumes all risks associated with its
+ exercise of rights under this Agreement, including but not limited to
+ the risks and costs of program errors, damage to or loss of data,
+ programs or equipment, and unavailability or interruption of operations.
+
+ DISCLAIMER OF LIABILITY
+ NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+ 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
+*/
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
/* mptlan.h */
#ifndef LINUX_MPTLAN_H_INCLUDED
@@ -29,7 +75,7 @@
#include <asm/io.h>
/* Override mptbase.h by pre-defining these! */
- #define MODULEAUTHOR "Noah Romer, Eddie C. Dost"
+#define MODULEAUTHOR "LSI Logic Corporation"
#include "mptbase.h"
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 3a3ef127df0..a0078ae5b9b 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -1,32 +1,11 @@
/*
* linux/drivers/message/fusion/mptscsih.c
- * High performance SCSI / Fibre Channel SCSI Host device driver.
- * For use with PCI chip/adapter(s):
- * LSIFC9xx/LSI409xx Fibre Channel
+ * For use with LSI Logic PCI chip/adapter(s)
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
- * Credits:
- * This driver would not exist if not for Alan Cox's development
- * of the linux i2o driver.
- *
- * A special thanks to Pamela Delaney (LSI Logic) for tons of work
- * and countless enhancements while adding support for the 1030
- * chip family. Pam has been instrumental in the development of
- * of the 2.xx.xx series fusion drivers, and her contributions are
- * far too numerous to hope to list in one place.
- *
- * A huge debt of gratitude is owed to David S. Miller (DaveM)
- * for fixing much of the stupid and broken stuff in the early
- * driver while porting to sparc64 platform. THANK YOU!
- *
- * (see mptbase.c)
- *
- * Copyright (c) 1999-2004 LSI Logic Corporation
- * Original author: Steven J. Ralston
- * (mailto:sjralston1@netscape.net)
+ * Copyright (c) 1999-2005 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
*
- * $Id: mptscsih.c,v 1.104 2002/12/03 21:26:34 pdelaney Exp $
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@@ -96,27 +75,6 @@ MODULE_AUTHOR(MODULEAUTHOR);
MODULE_DESCRIPTION(my_NAME);
MODULE_LICENSE("GPL");
-/* Command line args */
-static int mpt_dv = MPTSCSIH_DOMAIN_VALIDATION;
-MODULE_PARM(mpt_dv, "i");
-MODULE_PARM_DESC(mpt_dv, " DV Algorithm: enhanced=1, basic=0 (default=MPTSCSIH_DOMAIN_VALIDATION=1)");
-
-static int mpt_width = MPTSCSIH_MAX_WIDTH;
-MODULE_PARM(mpt_width, "i");
-MODULE_PARM_DESC(mpt_width, " Max Bus Width: wide=1, narrow=0 (default=MPTSCSIH_MAX_WIDTH=1)");
-
-static int mpt_factor = MPTSCSIH_MIN_SYNC;
-MODULE_PARM(mpt_factor, "h");
-MODULE_PARM_DESC(mpt_factor, " Min Sync Factor (default=MPTSCSIH_MIN_SYNC=0x08)");
-
-static int mpt_saf_te = MPTSCSIH_SAF_TE;
-MODULE_PARM(mpt_saf_te, "i");
-MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1 (default=MPTSCSIH_SAF_TE=0)");
-
-static int mpt_pq_filter = 0;
-MODULE_PARM(mpt_pq_filter, "i");
-MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)");
-
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
typedef struct _BIG_SENSE_BUF {
@@ -169,18 +127,17 @@ typedef struct _dv_parameters {
u16 pad1;
} DVPARAMETERS;
-
/*
* Other private/forward protos...
*/
-static int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
+int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
static void mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
-static int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
+int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
static int mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
SCSIIORequest_t *pReq, int req_idx);
static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
-static void copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
+static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
@@ -188,8 +145,8 @@ static u32 SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
static int mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
-static int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
-static int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
+int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
+int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
static void mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen);
static void mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56);
@@ -198,8 +155,7 @@ static void mptscsih_setDevicePage1Flags (u8 width, u8 factor, u8 offset, int *r
static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id);
static int mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags);
static int mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
-static int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
-static void mptscsih_timer_expired(unsigned long data);
+int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
static int mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
static int mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum);
@@ -212,29 +168,14 @@ static int mptscsih_doDv(MPT_SCSI_HOST *hd, int channel, int target);
static void mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage);
static void mptscsih_fillbuf(char *buffer, int size, int index, int width);
#endif
-/* module entry point */
-static int __init mptscsih_init (void);
-static void __exit mptscsih_exit (void);
-static int mptscsih_probe (struct pci_dev *, const struct pci_device_id *);
-static void mptscsih_remove(struct pci_dev *);
-static void mptscsih_shutdown(struct device *);
+void mptscsih_remove(struct pci_dev *);
+void mptscsih_shutdown(struct device *);
#ifdef CONFIG_PM
-static int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
-static int mptscsih_resume(struct pci_dev *pdev);
+int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
+int mptscsih_resume(struct pci_dev *pdev);
#endif
-
-/*
- * Private data...
- */
-
-static int mpt_scsi_hosts = 0;
-
-static int ScsiDoneCtx = -1;
-static int ScsiTaskCtx = -1;
-static int ScsiScanDvCtx = -1; /* Used only for bus scan and dv */
-
#define SNS_LEN(scp) sizeof((scp)->sense_buffer)
#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
@@ -244,20 +185,9 @@ static int ScsiScanDvCtx = -1; /* Used only for bus scan and dv */
static DEFINE_SPINLOCK(dvtaskQ_lock);
static int dvtaskQ_active = 0;
static int dvtaskQ_release = 0;
-static struct work_struct mptscsih_dvTask;
+static struct work_struct dvTaskQ_task;
#endif
-/*
- * Wait Queue setup
- */
-static DECLARE_WAIT_QUEUE_HEAD (scandv_waitq);
-static int scandv_wait_done = 1;
-
-
-/* Driver command line structure
- */
-static struct scsi_host_template driver_template;
-
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mptscsih_add_sge - Place a simple SGE at address pAddr.
@@ -619,7 +549,7 @@ nextSGEset:
*
* Returns 1 indicating alloc'd request frame ptr should be freed.
*/
-static int
+int
mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
{
struct scsi_cmnd *sc;
@@ -677,8 +607,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
sc->request_bufflen, xfer_cnt));
if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
- copy_sense_data(sc, hd, mf, pScsiReply);
-
+ mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
+
/*
* Look for + dump FCP ResponseInfo[]!
*/
@@ -740,7 +670,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
}
dreplyprintk((KERN_NOTICE "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->target));
break;
-
+
case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */
/*
* Do upfront check for valid SenseData and give it
@@ -773,7 +703,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
*/
if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
-
+
break;
case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */
@@ -905,18 +835,16 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
* Do OS callback
* Free driver resources (chain, msg buffers)
*/
- if (scsi_device_online(SCpnt->device)) {
- if (SCpnt->use_sg) {
- pci_unmap_sg(ioc->pcidev,
- (struct scatterlist *) SCpnt->request_buffer,
- SCpnt->use_sg,
- SCpnt->sc_data_direction);
- } else if (SCpnt->request_bufflen) {
- pci_unmap_single(ioc->pcidev,
- SCpnt->SCp.dma_handle,
- SCpnt->request_bufflen,
- SCpnt->sc_data_direction);
- }
+ if (SCpnt->use_sg) {
+ pci_unmap_sg(ioc->pcidev,
+ (struct scatterlist *) SCpnt->request_buffer,
+ SCpnt->use_sg,
+ SCpnt->sc_data_direction);
+ } else if (SCpnt->request_bufflen) {
+ pci_unmap_single(ioc->pcidev,
+ SCpnt->SCp.dma_handle,
+ SCpnt->request_bufflen,
+ SCpnt->sc_data_direction);
}
SCpnt->result = DID_RESET << 16;
SCpnt->host_scribble = NULL;
@@ -981,11 +909,6 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, uint target, uint lun)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- * Hack! It might be nice to report if a device is returning QUEUE_FULL
- * but maybe not each and every time...
- */
-static long last_queue_full = 0;
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@@ -1003,280 +926,20 @@ static void
mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
{
long time = jiffies;
-
- if (time - last_queue_full > 10 * HZ) {
- char *ioc_str = "ioc?";
-
- if (sc->device && sc->device->host != NULL && sc->device->host->hostdata != NULL)
- ioc_str = ((MPT_SCSI_HOST *)sc->device->host->hostdata)->ioc->name;
- dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
- ioc_str, 0, sc->device->id, sc->device->lun));
- last_queue_full = time;
- }
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static char *info_kbuf = NULL;
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- * mptscsih_probe - Installs scsi devices per bus.
- * @pdev: Pointer to pci_dev structure
- *
- * Returns 0 for success, non-zero for failure.
- *
- */
-
-static int
-mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
- struct Scsi_Host *sh;
MPT_SCSI_HOST *hd;
- MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
- unsigned long flags;
- int sz, ii;
- int numSGE = 0;
- int scale;
- int ioc_cap;
- u8 *mem;
- int error=0;
-
-
- /* 20010202 -sralston
- * Added sanity check on readiness of the MPT adapter.
- */
- if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
- printk(MYIOC_s_WARN_FMT
- "Skipping because it's not operational!\n",
- ioc->name);
- return -ENODEV;
- }
-
- if (!ioc->active) {
- printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
- ioc->name);
- return -ENODEV;
- }
-
- /* Sanity check - ensure at least 1 port is INITIATOR capable
- */
- ioc_cap = 0;
- for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
- if (ioc->pfacts[ii].ProtocolFlags &
- MPI_PORTFACTS_PROTOCOL_INITIATOR)
- ioc_cap ++;
- }
-
- if (!ioc_cap) {
- printk(MYIOC_s_WARN_FMT
- "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
- ioc->name, ioc);
- return -ENODEV;
- }
-
- sh = scsi_host_alloc(&driver_template, sizeof(MPT_SCSI_HOST));
-
- if (!sh) {
- printk(MYIOC_s_WARN_FMT
- "Unable to register controller with SCSI subsystem\n",
- ioc->name);
- return -1;
- }
-
- spin_lock_irqsave(&ioc->FreeQlock, flags);
-
- /* Attach the SCSI Host to the IOC structure
- */
- ioc->sh = sh;
-
- sh->io_port = 0;
- sh->n_io_port = 0;
- sh->irq = 0;
-
- /* set 16 byte cdb's */
- sh->max_cmd_len = 16;
-
- /* Yikes! This is important!
- * Otherwise, by default, linux
- * only scans target IDs 0-7!
- * pfactsN->MaxDevices unreliable
- * (not supported in early
- * versions of the FW).
- * max_id = 1 + actual max id,
- * max_lun = 1 + actual last lun,
- * see hosts.h :o(
- */
- if (ioc->bus_type == SCSI) {
- sh->max_id = MPT_MAX_SCSI_DEVICES;
- } else {
- /* For FC, increase the queue depth
- * from MPT_SCSI_CAN_QUEUE (31)
- * to MPT_FC_CAN_QUEUE (63).
- */
- sh->can_queue = MPT_FC_CAN_QUEUE;
- sh->max_id =
- MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
- }
-
- sh->max_lun = MPT_LAST_LUN + 1;
- sh->max_channel = 0;
- sh->this_id = ioc->pfacts[0].PortSCSIID;
-
- /* Required entry.
- */
- sh->unique_id = ioc->id;
-
- /* Verify that we won't exceed the maximum
- * number of chain buffers
- * We can optimize: ZZ = req_sz/sizeof(SGE)
- * For 32bit SGE's:
- * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
- * + (req_sz - 64)/sizeof(SGE)
- * A slightly different algorithm is required for
- * 64bit SGEs.
- */
- scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
- if (sizeof(dma_addr_t) == sizeof(u64)) {
- numSGE = (scale - 1) *
- (ioc->facts.MaxChainDepth-1) + scale +
- (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
- sizeof(u32));
- } else {
- numSGE = 1 + (scale - 1) *
- (ioc->facts.MaxChainDepth-1) + scale +
- (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
- sizeof(u32));
- }
-
- if (numSGE < sh->sg_tablesize) {
- /* Reset this value */
- dprintk((MYIOC_s_INFO_FMT
- "Resetting sg_tablesize to %d from %d\n",
- ioc->name, numSGE, sh->sg_tablesize));
- sh->sg_tablesize = numSGE;
- }
-
- /* Set the pci device pointer in Scsi_Host structure.
- */
- scsi_set_device(sh, &ioc->pcidev->dev);
-
- spin_unlock_irqrestore(&ioc->FreeQlock, flags);
-
- hd = (MPT_SCSI_HOST *) sh->hostdata;
- hd->ioc = ioc;
-
- /* SCSI needs scsi_cmnd lookup table!
- * (with size equal to req_depth*PtrSz!)
- */
- sz = ioc->req_depth * sizeof(void *);
- mem = kmalloc(sz, GFP_ATOMIC);
- if (mem == NULL) {
- error = -ENOMEM;
- goto mptscsih_probe_failed;
- }
-
- memset(mem, 0, sz);
- hd->ScsiLookup = (struct scsi_cmnd **) mem;
-
- dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
- ioc->name, hd->ScsiLookup, sz));
-
- /* Allocate memory for the device structures.
- * A non-Null pointer at an offset
- * indicates a device exists.
- * max_id = 1 + maximum id (hosts.h)
- */
- sz = sh->max_id * sizeof(void *);
- mem = kmalloc(sz, GFP_ATOMIC);
- if (mem == NULL) {
- error = -ENOMEM;
- goto mptscsih_probe_failed;
- }
-
- memset(mem, 0, sz);
- hd->Targets = (VirtDevice **) mem;
-
- dprintk((KERN_INFO
- " Targets @ %p, sz=%d\n", hd->Targets, sz));
-
- /* Clear the TM flags
- */
- hd->tmPending = 0;
- hd->tmState = TM_STATE_NONE;
- hd->resetPending = 0;
- hd->abortSCpnt = NULL;
-
- /* Clear the pointer used to store
- * single-threaded commands, i.e., those
- * issued during a bus scan, dv and
- * configuration pages.
- */
- hd->cmdPtr = NULL;
- /* Initialize this SCSI Hosts' timers
- * To use, set the timer expires field
- * and add_timer
- */
- init_timer(&hd->timer);
- hd->timer.data = (unsigned long) hd;
- hd->timer.function = mptscsih_timer_expired;
-
- if (ioc->bus_type == SCSI) {
- /* Update with the driver setup
- * values.
- */
- if (ioc->spi_data.maxBusWidth > mpt_width)
- ioc->spi_data.maxBusWidth = mpt_width;
- if (ioc->spi_data.minSyncFactor < mpt_factor)
- ioc->spi_data.minSyncFactor = mpt_factor;
-
- if (ioc->spi_data.minSyncFactor == MPT_ASYNC) {
- ioc->spi_data.maxSyncOffset = 0;
- }
-
- ioc->spi_data.Saf_Te = mpt_saf_te;
-
- hd->negoNvram = 0;
-#ifndef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
- hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
-#endif
- ioc->spi_data.forceDv = 0;
- ioc->spi_data.noQas = 0;
- for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
- ioc->spi_data.dvStatus[ii] =
- MPT_SCSICFG_NEGOTIATE;
- }
-
- for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
- ioc->spi_data.dvStatus[ii] |=
- MPT_SCSICFG_DV_NOT_DONE;
-
- dinitprintk((MYIOC_s_INFO_FMT
- "dv %x width %x factor %x saf_te %x\n",
- ioc->name, mpt_dv,
- mpt_width,
- mpt_factor,
- mpt_saf_te));
- }
-
- mpt_scsi_hosts++;
+ if (sc->device == NULL)
+ return;
+ if (sc->device->host == NULL)
+ return;
+ if ((hd = (MPT_SCSI_HOST *)sc->device->host->hostdata) == NULL)
+ return;
- error = scsi_add_host (sh, &ioc->pcidev->dev);
- if(error) {
- dprintk((KERN_ERR MYNAM
- "scsi_add_host failed\n"));
- goto mptscsih_probe_failed;
+ if (time - hd->last_queue_full > 10 * HZ) {
+ dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
+ hd->ioc->name, 0, sc->device->id, sc->device->lun));
+ hd->last_queue_full = time;
}
-
- scsi_scan_host(sh);
- return 0;
-
-mptscsih_probe_failed:
-
- mptscsih_remove(pdev);
- return error;
-
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1286,7 +949,7 @@ mptscsih_probe_failed:
*
*
*/
-static void
+void
mptscsih_remove(struct pci_dev *pdev)
{
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
@@ -1294,12 +957,16 @@ mptscsih_remove(struct pci_dev *pdev)
MPT_SCSI_HOST *hd;
int count;
unsigned long flags;
+ int sz1;
if(!host)
return;
scsi_remove_host(host);
+ if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL)
+ return;
+
#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
/* Check DV thread active */
count = 10 * HZ;
@@ -1321,40 +988,36 @@ mptscsih_remove(struct pci_dev *pdev)
#endif
#endif
- hd = (MPT_SCSI_HOST *)host->hostdata;
- if (hd != NULL) {
- int sz1;
+ mptscsih_shutdown(&pdev->dev);
- mptscsih_shutdown(&pdev->dev);
+ sz1=0;
- sz1=0;
+ if (hd->ScsiLookup != NULL) {
+ sz1 = hd->ioc->req_depth * sizeof(void *);
+ kfree(hd->ScsiLookup);
+ hd->ScsiLookup = NULL;
+ }
- if (hd->ScsiLookup != NULL) {
- sz1 = hd->ioc->req_depth * sizeof(void *);
- kfree(hd->ScsiLookup);
- hd->ScsiLookup = NULL;
- }
+ /*
+ * Free pointer array.
+ */
+ kfree(hd->Targets);
+ hd->Targets = NULL;
- if (hd->Targets != NULL) {
- /*
- * Free pointer array.
- */
- kfree(hd->Targets);
- hd->Targets = NULL;
- }
+ dprintk((MYIOC_s_INFO_FMT
+ "Free'd ScsiLookup (%d) memory\n",
+ hd->ioc->name, sz1));
- dprintk((MYIOC_s_INFO_FMT
- "Free'd ScsiLookup (%d) memory\n",
- hd->ioc->name, sz1));
+ kfree(hd->info_kbuf);
- /* NULL the Scsi_Host pointer
- */
- hd->ioc->sh = NULL;
- }
+ /* NULL the Scsi_Host pointer
+ */
+ hd->ioc->sh = NULL;
scsi_host_put(host);
- mpt_scsi_hosts--;
+ mpt_detach(pdev);
+
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1362,7 +1025,7 @@ mptscsih_remove(struct pci_dev *pdev)
* mptscsih_shutdown - reboot notifier
*
*/
-static void
+void
mptscsih_shutdown(struct device * dev)
{
MPT_ADAPTER *ioc = pci_get_drvdata(to_pci_dev(dev));
@@ -1384,15 +1047,15 @@ mptscsih_shutdown(struct device * dev)
#ifdef CONFIG_PM
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
- * mptscsih_suspend - Fusion MPT scsie driver suspend routine.
+ * mptscsih_suspend - Fusion MPT scsi driver suspend routine.
*
*
*/
-static int
+int
mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
{
mptscsih_shutdown(&pdev->dev);
- return 0;
+ return mpt_suspend(pdev,state);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1401,13 +1064,15 @@ mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
*
*
*/
-static int
+int
mptscsih_resume(struct pci_dev *pdev)
{
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
struct Scsi_Host *host = ioc->sh;
MPT_SCSI_HOST *hd;
+ mpt_resume(pdev);
+
if(!host)
return 0;
@@ -1422,9 +1087,9 @@ mptscsih_resume(struct pci_dev *pdev)
if (!dvtaskQ_active) {
dvtaskQ_active = 1;
spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
- INIT_WORK(&mptscsih_dvTask,
+ INIT_WORK(&dvTaskQ_task,
mptscsih_domainValidation, (void *) hd);
- schedule_work(&mptscsih_dvTask);
+ schedule_work(&dvTaskQ_task);
} else {
spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
}
@@ -1435,82 +1100,6 @@ mptscsih_resume(struct pci_dev *pdev)
#endif
-static struct mpt_pci_driver mptscsih_driver = {
- .probe = mptscsih_probe,
- .remove = mptscsih_remove,
- .shutdown = mptscsih_shutdown,
-#ifdef CONFIG_PM
- .suspend = mptscsih_suspend,
- .resume = mptscsih_resume,
-#endif
-};
-
-/* SCSI host fops start here... */
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- * mptscsih_init - Register MPT adapter(s) as SCSI host(s) with
- * linux scsi mid-layer.
- *
- * Returns 0 for success, non-zero for failure.
- */
-static int __init
-mptscsih_init(void)
-{
-
- show_mptmod_ver(my_NAME, my_VERSION);
-
- ScsiDoneCtx = mpt_register(mptscsih_io_done, MPTSCSIH_DRIVER);
- ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER);
- ScsiScanDvCtx = mpt_register(mptscsih_scandv_complete, MPTSCSIH_DRIVER);
-
- if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) {
- devtprintk((KERN_INFO MYNAM
- ": Registered for IOC event notifications\n"));
- }
-
- if (mpt_reset_register(ScsiDoneCtx, mptscsih_ioc_reset) == 0) {
- dprintk((KERN_INFO MYNAM
- ": Registered for IOC reset notifications\n"));
- }
-
- if(mpt_device_driver_register(&mptscsih_driver,
- MPTSCSIH_DRIVER) != 0 ) {
- dprintk((KERN_INFO MYNAM
- ": failed to register dd callbacks\n"));
- }
-
- return 0;
-
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- * mptscsih_exit - Unregisters MPT adapter(s)
- *
- */
-static void __exit
-mptscsih_exit(void)
-{
- mpt_device_driver_deregister(MPTSCSIH_DRIVER);
-
- mpt_reset_deregister(ScsiDoneCtx);
- dprintk((KERN_INFO MYNAM
- ": Deregistered for IOC reset notifications\n"));
-
- mpt_event_deregister(ScsiDoneCtx);
- dprintk((KERN_INFO MYNAM
- ": Deregistered for IOC event notifications\n"));
-
- mpt_deregister(ScsiScanDvCtx);
- mpt_deregister(ScsiTaskCtx);
- mpt_deregister(ScsiDoneCtx);
-
- if (info_kbuf != NULL)
- kfree(info_kbuf);
-
-}
-
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mptscsih_info - Return information about MPT adapter
@@ -1520,24 +1109,25 @@ mptscsih_exit(void)
*
* Returns pointer to buffer where information was written.
*/
-static const char *
+const char *
mptscsih_info(struct Scsi_Host *SChost)
{
MPT_SCSI_HOST *h;
int size = 0;
- if (info_kbuf == NULL)
- if ((info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
- return info_kbuf;
-
h = (MPT_SCSI_HOST *)SChost->hostdata;
- info_kbuf[0] = '\0';
+
if (h) {
- mpt_print_ioc_summary(h->ioc, info_kbuf, &size, 0, 0);
- info_kbuf[size-1] = '\0';
+ if (h->info_kbuf == NULL)
+ if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
+ return h->info_kbuf;
+ h->info_kbuf[0] = '\0';
+
+ mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
+ h->info_kbuf[size-1] = '\0';
}
- return info_kbuf;
+ return h->info_kbuf;
}
struct info_str {
@@ -1547,7 +1137,8 @@ struct info_str {
int pos;
};
-static void copy_mem_info(struct info_str *info, char *data, int len)
+static void
+mptscsih_copy_mem_info(struct info_str *info, char *data, int len)
{
if (info->pos + len > info->length)
len = info->length - info->pos;
@@ -1568,7 +1159,8 @@ static void copy_mem_info(struct info_str *info, char *data, int len)
}
}
-static int copy_info(struct info_str *info, char *fmt, ...)
+static int
+mptscsih_copy_info(struct info_str *info, char *fmt, ...)
{
va_list args;
char buf[81];
@@ -1578,11 +1170,12 @@ static int copy_info(struct info_str *info, char *fmt, ...)
len = vsprintf(buf, fmt, args);
va_end(args);
- copy_mem_info(info, buf, len);
+ mptscsih_copy_mem_info(info, buf, len);
return len;
}
-static int mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
+static int
+mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
{
struct info_str info;
@@ -1591,10 +1184,10 @@ static int mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int le
info.offset = offset;
info.pos = 0;
- copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
- copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
- copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
- copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
+ mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
+ mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
+ mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
+ mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
return ((info.pos > info.offset) ? info.pos - info.offset : 0);
}
@@ -1612,7 +1205,7 @@ static int mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int le
* hostno: scsi host number
* func: if write = 1; if read = 0
*/
-static int
+int
mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
int length, int func)
{
@@ -1649,7 +1242,7 @@ mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t off
*
* Returns 0. (rtn value discarded by linux scsi mid-layer)
*/
-static int
+int
mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
{
MPT_SCSI_HOST *hd;
@@ -1684,7 +1277,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
/*
* Put together a MPT SCSI request...
*/
- if ((mf = mpt_get_msg_frame(ScsiDoneCtx, hd->ioc)) == NULL) {
+ if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) {
dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
hd->ioc->name));
return SCSI_MLQUEUE_HOST_BUSY;
@@ -1696,8 +1289,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
ADD_INDEX_LOG(my_idx);
- /* BUG FIX! 19991030 -sralston
- * TUR's being issued with scsictl=0x02000000 (DATA_IN)!
+ /* TUR's being issued with scsictl=0x02000000 (DATA_IN)!
* Seems we may receive a buffer (datalen>0) even when there
* will be no data transfer! GRRRRR...
*/
@@ -1791,9 +1383,9 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
if (!dvtaskQ_active) {
dvtaskQ_active = 1;
spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
- INIT_WORK(&mptscsih_dvTask, mptscsih_domainValidation, (void *) hd);
+ INIT_WORK(&dvTaskQ_task, mptscsih_domainValidation, (void *) hd);
- schedule_work(&mptscsih_dvTask);
+ schedule_work(&dvTaskQ_task);
} else {
spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
}
@@ -1819,7 +1411,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
}
#endif
- mpt_put_msg_frame(ScsiDoneCtx, hd->ioc, mf);
+ mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
hd->ioc->name, SCpnt, mf, my_idx));
DBG_DUMP_REQUEST_FRAME(mf)
@@ -2036,7 +1628,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun
/* Return Fail to calling function if no message frames available.
*/
- if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc)) == NULL) {
+ if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) {
dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
hd->ioc->name));
//return FAILED;
@@ -2075,7 +1667,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun
DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
- if ((retval = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc,
+ if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
sizeof(SCSITaskMgmt_t), (u32*)pScsiTm,
CAN_SLEEP)) != 0) {
dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
@@ -2107,7 +1699,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun
*
* Returns SUCCESS or FAILED.
*/
-static int
+int
mptscsih_abort(struct scsi_cmnd * SCpnt)
{
MPT_SCSI_HOST *hd;
@@ -2115,7 +1707,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
MPT_FRAME_HDR *mf;
u32 ctx2abort;
int scpnt_idx;
- spinlock_t *host_lock = SCpnt->device->host->host_lock;
/* If we can't locate our host adapter structure, return FAILED status.
*/
@@ -2163,7 +1754,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
hd->abortSCpnt = SCpnt;
- spin_unlock_irq(host_lock);
if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun,
ctx2abort, 2 /* 2 second timeout */)
@@ -2180,8 +1770,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
hd->tmPending = 0;
hd->tmState = TM_STATE_NONE;
- spin_lock_irq(host_lock);
-
/* Unmap the DMA buffers, if any. */
if (SCpnt->use_sg) {
pci_unmap_sg(ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer,
@@ -2197,7 +1785,6 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
mpt_free_msg_frame(ioc, mf);
return FAILED;
}
- spin_lock_irq(host_lock);
return SUCCESS;
}
@@ -2210,11 +1797,10 @@ mptscsih_abort(struct scsi_cmnd * SCpnt)
*
* Returns SUCCESS or FAILED.
*/
-static int
+int
mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
{
MPT_SCSI_HOST *hd;
- spinlock_t *host_lock = SCpnt->device->host->host_lock;
/* If we can't locate our host adapter structure, return FAILED status.
*/
@@ -2231,7 +1817,6 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n",
hd->ioc->name, SCpnt);
- spin_unlock_irq(host_lock);
if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
SCpnt->device->channel, SCpnt->device->id,
0, 0, 5 /* 5 second timeout */)
@@ -2243,12 +1828,10 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
hd->ioc->name, SCpnt);
hd->tmPending = 0;
hd->tmState = TM_STATE_NONE;
- spin_lock_irq(host_lock);
return FAILED;
}
- spin_lock_irq(host_lock);
- return SUCCESS;
+ return SUCCESS;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2260,7 +1843,7 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
*
* Returns SUCCESS or FAILED.
*/
-static int
+int
mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
{
MPT_SCSI_HOST *hd;
@@ -2282,7 +1865,6 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
hd->timeouts++;
/* We are now ready to execute the task management request. */
- spin_unlock_irq(host_lock);
if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
SCpnt->device->channel, 0, 0, 0, 5 /* 5 second timeout */)
< 0){
@@ -2298,7 +1880,7 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
spin_lock_irq(host_lock);
return FAILED;
}
- spin_lock_irq(host_lock);
+
return SUCCESS;
}
@@ -2312,12 +1894,11 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
*
* Returns SUCCESS or FAILED.
*/
-static int
+int
mptscsih_host_reset(struct scsi_cmnd *SCpnt)
{
MPT_SCSI_HOST * hd;
int status = SUCCESS;
- spinlock_t *host_lock = SCpnt->device->host->host_lock;
/* If we can't locate the host to reset, then we failed. */
if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
@@ -2333,7 +1914,6 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt)
/* If our attempts to reset the host failed, then return a failed
* status. The host will be taken off line by the SCSI mid-layer.
*/
- spin_unlock_irq(host_lock);
if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
status = FAILED;
} else {
@@ -2343,8 +1923,6 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt)
hd->tmPending = 0;
hd->tmState = TM_STATE_NONE;
}
- spin_lock_irq(host_lock);
-
dtmprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
"Status = %s\n",
@@ -2426,7 +2004,7 @@ mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout )
*
* Returns 1 indicating alloc'd request frame ptr should be freed.
*/
-static int
+int
mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
{
SCSITaskMgmtReply_t *pScsiTmReply;
@@ -2509,7 +2087,7 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m
/*
* This is anyones guess quite frankly.
*/
-static int
+int
mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
sector_t capacity, int geom[])
{
@@ -2556,7 +2134,7 @@ mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
* Return non-zero if allocation fails.
* Init memory once per id (not LUN).
*/
-static int
+int
mptscsih_slave_alloc(struct scsi_device *device)
{
struct Scsi_Host *host = device->host;
@@ -2599,7 +2177,8 @@ mptscsih_slave_alloc(struct scsi_device *device)
return 0;
}
-static int mptscsih_is_raid_volume(MPT_SCSI_HOST *hd, uint id)
+static int
+mptscsih_is_raid_volume(MPT_SCSI_HOST *hd, uint id)
{
int i;
@@ -2618,7 +2197,7 @@ static int mptscsih_is_raid_volume(MPT_SCSI_HOST *hd, uint id)
* OS entry point to allow for host driver to free allocated memory
* Called if no device present or device being unloaded
*/
-static void
+void
mptscsih_slave_destroy(struct scsi_device *device)
{
struct Scsi_Host *host = device->host;
@@ -2639,7 +2218,7 @@ mptscsih_slave_destroy(struct scsi_device *device)
kfree(hd->Targets[target]);
hd->Targets[target] = NULL;
-
+
if (hd->ioc->bus_type == SCSI) {
if (mptscsih_is_raid_volume(hd, target)) {
hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3;
@@ -2695,7 +2274,7 @@ mptscsih_set_queue_depth(struct scsi_device *device, MPT_SCSI_HOST *hd,
* member to 1 if a device does not support Q tags.
* Return non-zero if fails.
*/
-static int
+int
mptscsih_slave_configure(struct scsi_device *device)
{
struct Scsi_Host *sh = device->host;
@@ -2758,8 +2337,8 @@ slave_configure_exit:
return 0;
}
-static ssize_t
-mptscsih_store_queue_depth(struct device *dev, const char *buf, size_t count)
+ssize_t
+mptscsih_store_queue_depth(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int depth;
struct scsi_device *sdev = to_scsi_device(dev);
@@ -2788,7 +2367,7 @@ mptscsih_store_queue_depth(struct device *dev, const char *buf, size_t count)
*
*/
static void
-copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
+mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
{
VirtDevice *target;
SCSIIORequest_t *pReq;
@@ -2854,7 +2433,7 @@ SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static int
+int
mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
{
MPT_SCSI_HOST *hd;
@@ -2949,8 +2528,8 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
*/
hd->pLocal = &hd->localReply;
hd->pLocal->completion = MPT_SCANDV_DID_RESET;
- scandv_wait_done = 1;
- wake_up(&scandv_waitq);
+ hd->scandv_wait_done = 1;
+ wake_up(&hd->scandv_waitq);
hd->cmdPtr = NULL;
}
@@ -2969,7 +2548,7 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static int
+int
mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
{
MPT_SCSI_HOST *hd;
@@ -3085,42 +2664,6 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
return 1; /* currently means nothing really */
}
-static struct device_attribute mptscsih_queue_depth_attr = {
- .attr = {
- .name = "queue_depth",
- .mode = S_IWUSR,
- },
- .store = mptscsih_store_queue_depth,
-};
-
-static struct device_attribute *mptscsih_dev_attrs[] = {
- &mptscsih_queue_depth_attr,
- NULL,
-};
-
-static struct scsi_host_template driver_template = {
- .proc_name = "mptscsih",
- .proc_info = mptscsih_proc_info,
- .name = "MPT SCSI Host",
- .info = mptscsih_info,
- .queuecommand = mptscsih_qcmd,
- .slave_alloc = mptscsih_slave_alloc,
- .slave_configure = mptscsih_slave_configure,
- .slave_destroy = mptscsih_slave_destroy,
- .eh_abort_handler = mptscsih_abort,
- .eh_device_reset_handler = mptscsih_dev_reset,
- .eh_bus_reset_handler = mptscsih_bus_reset,
- .eh_host_reset_handler = mptscsih_host_reset,
- .bios_param = mptscsih_bios_param,
- .can_queue = MPT_SCSI_CAN_QUEUE,
- .this_id = -1,
- .sg_tablesize = MPT_SCSI_SG_DEPTH,
- .max_sectors = 8192,
- .cmd_per_lun = 7,
- .use_clustering = ENABLE_CLUSTERING,
- .sdev_attrs = mptscsih_dev_attrs,
-};
-
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mptscsih_initTarget - Target, LUN alloc/free functionality.
@@ -3158,9 +2701,9 @@ mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *
* around a bug in th emid-layer in some distributions in which the mid-layer will
* continue to try to communicate to the LUN and evntually create a dummy LUN.
*/
- if (mpt_pq_filter && dlen && (data[0] & 0xE0))
+ if (hd->mpt_pq_filter && dlen && (data[0] & 0xE0))
data[0] |= 0x40;
-
+
/* Is LUN supported? If so, upper 2 bits will be 0
* in first byte of inquiry data.
*/
@@ -3307,7 +2850,7 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
ddvtprintk((KERN_INFO "Enabling QAS on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id));
noQas = 0;
}
-
+
offset = pspi_data->maxSyncOffset;
/* If RAID, never disable QAS
@@ -3401,7 +2944,7 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
if ( (vdev = hd->Targets[ii]) ) {
vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
mptscsih_writeSDP1(hd, 0, ii, vdev->negoFlags);
- }
+ }
}
}
}
@@ -3426,14 +2969,15 @@ mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56)
* Tapes, initTarget will set this flag on completion of Inquiry command.
* Called only if DV_NOT_DONE flag is set
*/
-static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
+static void
+mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
{
u8 cmd;
ScsiCfgData *pSpi;
ddvtprintk((" set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n",
pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0]));
-
+
if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0))
return;
@@ -3464,7 +3008,8 @@ static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
* If no Target, bus reset on 1st I/O. Set the flag to
* prevent any future negotiations to this device.
*/
-static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id)
+static void
+mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id)
{
if ((hd->Targets) && (hd->Targets[target_id] == NULL))
@@ -3631,7 +3176,7 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
offset = pTarget->maxOffset;
negoFlags = pTarget->negoFlags;
}
-
+
#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
/* Force to async and narrow if DV has not been executed
* for this ID
@@ -3653,7 +3198,7 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
/* Get a MF for this command.
*/
- if ((mf = mpt_get_msg_frame(ScsiDoneCtx, ioc)) == NULL) {
+ if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
dprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n",
ioc->name));
return -EAGAIN;
@@ -3717,7 +3262,7 @@ mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target_id, int flags)
ioc->name, id, (id | (bus<<8)),
requested, configuration));
- mpt_put_msg_frame(ScsiDoneCtx, ioc, mf);
+ mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
}
return 0;
@@ -3748,7 +3293,7 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
/* Get a MF for this command.
*/
- if ((mf = mpt_get_msg_frame(ScsiDoneCtx, ioc)) == NULL) {
+ if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
dprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
ioc->name));
return -EAGAIN;
@@ -3794,7 +3339,7 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
"writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, target_id, bus));
- mpt_put_msg_frame(ScsiDoneCtx, ioc, mf);
+ mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
return 0;
}
@@ -3824,7 +3369,7 @@ mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus)
* in the IOC member localReply structure.
* Used ONLY for DV and other internal commands.
*/
-static int
+int
mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
{
MPT_SCSI_HOST *hd;
@@ -3832,6 +3377,8 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
int completionCode;
u16 req_idx;
+ hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
+
if ((mf == NULL) ||
(mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
printk(MYIOC_s_ERR_FMT
@@ -3840,7 +3387,6 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
goto wakeup;
}
- hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
del_timer(&hd->timer);
req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
hd->ScsiLookup[req_idx] = NULL;
@@ -3972,8 +3518,8 @@ wakeup:
/*
* Wake up the original calling thread
*/
- scandv_wait_done = 1;
- wake_up(&scandv_waitq);
+ hd->scandv_wait_done = 1;
+ wake_up(&hd->scandv_waitq);
return 1;
}
@@ -3984,7 +3530,8 @@ wakeup:
* @data: Pointer to MPT_SCSI_HOST recast as an unsigned long
*
*/
-static void mptscsih_timer_expired(unsigned long data)
+void
+mptscsih_timer_expired(unsigned long data)
{
MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
@@ -4051,7 +3598,7 @@ mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io)
/* Get and Populate a free Frame
*/
- if ((mf = mpt_get_msg_frame(ScsiScanDvCtx, hd->ioc)) == NULL) {
+ if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
hd->ioc->name));
return -EAGAIN;
@@ -4077,7 +3624,7 @@ mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io)
hd->pLocal = NULL;
hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
- scandv_wait_done = 0;
+ hd->scandv_wait_done = 0;
/* Save cmd pointer, for resource free if timeout or
* FW reload occurs
@@ -4085,8 +3632,8 @@ mptscsih_do_raid(MPT_SCSI_HOST *hd, u8 action, INTERNAL_CMD *io)
hd->cmdPtr = mf;
add_timer(&hd->timer);
- mpt_put_msg_frame(ScsiScanDvCtx, hd->ioc, mf);
- wait_event(scandv_waitq, scandv_wait_done);
+ mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
+ wait_event(hd->scandv_waitq, hd->scandv_wait_done);
if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD))
return -1;
@@ -4232,7 +3779,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
/* Get and Populate a free Frame
*/
- if ((mf = mpt_get_msg_frame(ScsiScanDvCtx, hd->ioc)) == NULL) {
+ if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n",
hd->ioc->name));
return -EBUSY;
@@ -4314,7 +3861,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
*/
hd->pLocal = NULL;
hd->timer.expires = jiffies + HZ*cmdTimeout;
- scandv_wait_done = 0;
+ hd->scandv_wait_done = 0;
/* Save cmd pointer, for resource free if timeout or
* FW reload occurs
@@ -4322,8 +3869,8 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io)
hd->cmdPtr = mf;
add_timer(&hd->timer);
- mpt_put_msg_frame(ScsiScanDvCtx, hd->ioc, mf);
- wait_event(scandv_waitq, scandv_wait_done);
+ mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
+ wait_event(hd->scandv_waitq, hd->scandv_wait_done);
if (hd->pLocal) {
rc = hd->pLocal->completion;
@@ -4640,7 +4187,8 @@ mptscsih_domainValidation(void *arg)
/* Search IOC page 3 to determine if this is hidden physical disk
*/
-static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
+static int
+mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
{
if (ioc->spi_data.pIocPg3) {
Ioc3PhysDisk_t *pPDisk = ioc->spi_data.pIocPg3->PhysDisk;
@@ -4659,7 +4207,8 @@ static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
/* Write SDP1 if no QAS has been enabled
*/
-static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
+static void
+mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
{
VirtDevice *pTarget;
int ii;
@@ -5157,7 +4706,7 @@ mptscsih_doDv(MPT_SCSI_HOST *hd, int bus_number, int id)
}
ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
- if (mpt_dv == 0)
+ if (ioc->spi_data.mpt_dv == 0)
goto target_done;
inq0 = (*pbuf1) & 0x1F;
@@ -6015,7 +5564,29 @@ mptscsih_fillbuf(char *buffer, int size, int index, int width)
}
#endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+EXPORT_SYMBOL(mptscsih_remove);
+EXPORT_SYMBOL(mptscsih_shutdown);
+#ifdef CONFIG_PM
+EXPORT_SYMBOL(mptscsih_suspend);
+EXPORT_SYMBOL(mptscsih_resume);
+#endif
+EXPORT_SYMBOL(mptscsih_proc_info);
+EXPORT_SYMBOL(mptscsih_info);
+EXPORT_SYMBOL(mptscsih_qcmd);
+EXPORT_SYMBOL(mptscsih_slave_alloc);
+EXPORT_SYMBOL(mptscsih_slave_destroy);
+EXPORT_SYMBOL(mptscsih_slave_configure);
+EXPORT_SYMBOL(mptscsih_abort);
+EXPORT_SYMBOL(mptscsih_dev_reset);
+EXPORT_SYMBOL(mptscsih_bus_reset);
+EXPORT_SYMBOL(mptscsih_host_reset);
+EXPORT_SYMBOL(mptscsih_bios_param);
+EXPORT_SYMBOL(mptscsih_io_done);
+EXPORT_SYMBOL(mptscsih_taskmgmt_complete);
+EXPORT_SYMBOL(mptscsih_scandv_complete);
+EXPORT_SYMBOL(mptscsih_event_process);
+EXPORT_SYMBOL(mptscsih_ioc_reset);
+EXPORT_SYMBOL(mptscsih_store_queue_depth);
+EXPORT_SYMBOL(mptscsih_timer_expired);
-module_init(mptscsih_init);
-module_exit(mptscsih_exit);
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index 5cb2fd45c38..d73aec33e16 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -1,26 +1,13 @@
/*
- * linux/drivers/message/fusion/mptscsih.h
+ * linux/drivers/message/fusion/mptscsi.h
* High performance SCSI / Fibre Channel SCSI Host device driver.
* For use with PCI chip/adapter(s):
* LSIFC9xx/LSI409xx Fibre Channel
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
- * Credits:
- * This driver would not exist if not for Alan Cox's development
- * of the linux i2o driver.
- *
- * A huge debt of gratitude is owed to David S. Miller (DaveM)
- * for fixing much of the stupid and broken stuff in the early
- * driver while porting to sparc64 platform. THANK YOU!
- *
- * (see also mptbase.c)
- *
- * Copyright (c) 1999-2004 LSI Logic Corporation
- * Originally By: Steven J. Ralston
- * (mailto:netscape.net)
+ * Copyright (c) 1999-2005 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
*
- * $Id: mptscsih.h,v 1.21 2002/12/03 21:26:35 pdelaney Exp $
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@@ -91,4 +78,30 @@
#define MPTSCSIH_MIN_SYNC 0x08
#define MPTSCSIH_SAF_TE 0
+
+#endif
+
+extern void mptscsih_remove(struct pci_dev *);
+extern void mptscsih_shutdown(struct device *);
+#ifdef CONFIG_PM
+extern int mptscsih_suspend(struct pci_dev *pdev, u32 state);
+extern int mptscsih_resume(struct pci_dev *pdev);
#endif
+extern int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func);
+extern const char * mptscsih_info(struct Scsi_Host *SChost);
+extern int mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *));
+extern int mptscsih_slave_alloc(struct scsi_device *device);
+extern void mptscsih_slave_destroy(struct scsi_device *device);
+extern int mptscsih_slave_configure(struct scsi_device *device);
+extern int mptscsih_abort(struct scsi_cmnd * SCpnt);
+extern int mptscsih_dev_reset(struct scsi_cmnd * SCpnt);
+extern int mptscsih_bus_reset(struct scsi_cmnd * SCpnt);
+extern int mptscsih_host_reset(struct scsi_cmnd *SCpnt);
+extern int mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, sector_t capacity, int geom[]);
+extern int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
+extern int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
+extern int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
+extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
+extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
+extern ssize_t mptscsih_store_queue_depth(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+extern void mptscsih_timer_expired(unsigned long data);
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
new file mode 100644
index 00000000000..5f9a61b85b3
--- /dev/null
+++ b/drivers/message/fusion/mptspi.c
@@ -0,0 +1,486 @@
+/*
+ * linux/drivers/message/fusion/mptspi.c
+ * For use with LSI Logic PCI chip/adapter(s)
+ * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+ *
+ * Copyright (c) 1999-2005 LSI Logic Corporation
+ * (mailto:mpt_linux_developer@lsil.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; version 2 of the License.
+
+ 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.
+
+ NO WARRANTY
+ THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ solely responsible for determining the appropriateness of using and
+ distributing the Program and assumes all risks associated with its
+ exercise of rights under this Agreement, including but not limited to
+ the risks and costs of program errors, damage to or loss of data,
+ programs or equipment, and unavailability or interruption of operations.
+
+ DISCLAIMER OF LIABILITY
+ NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+ 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 "linux_compat.h" /* linux-2.6 tweaks */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/kdev_t.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h> /* for mdelay */
+#include <linux/interrupt.h> /* needed for in_interrupt() proto */
+#include <linux/reboot.h> /* notifier code */
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+
+#include "mptbase.h"
+#include "mptscsih.h"
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+#define my_NAME "Fusion MPT SPI Host driver"
+#define my_VERSION MPT_LINUX_VERSION_COMMON
+#define MYNAM "mptspi"
+
+MODULE_AUTHOR(MODULEAUTHOR);
+MODULE_DESCRIPTION(my_NAME);
+MODULE_LICENSE("GPL");
+
+/* Command line args */
+#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
+static int mpt_dv = MPTSCSIH_DOMAIN_VALIDATION;
+module_param(mpt_dv, int, 0);
+MODULE_PARM_DESC(mpt_dv, " DV Algorithm: enhanced=1, basic=0 (default=MPTSCSIH_DOMAIN_VALIDATION=1)");
+
+static int mpt_width = MPTSCSIH_MAX_WIDTH;
+module_param(mpt_width, int, 0);
+MODULE_PARM_DESC(mpt_width, " Max Bus Width: wide=1, narrow=0 (default=MPTSCSIH_MAX_WIDTH=1)");
+
+static ushort mpt_factor = MPTSCSIH_MIN_SYNC;
+module_param(mpt_factor, ushort, 0);
+MODULE_PARM_DESC(mpt_factor, " Min Sync Factor (default=MPTSCSIH_MIN_SYNC=0x08)");
+#endif
+
+static int mpt_saf_te = MPTSCSIH_SAF_TE;
+module_param(mpt_saf_te, int, 0);
+MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1 (default=MPTSCSIH_SAF_TE=0)");
+
+static int mpt_pq_filter = 0;
+module_param(mpt_pq_filter, int, 0);
+MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)");
+
+static int mptspiDoneCtx = -1;
+static int mptspiTaskCtx = -1;
+static int mptspiInternalCtx = -1; /* Used only for internal commands */
+
+static struct device_attribute mptspi_queue_depth_attr = {
+ .attr = {
+ .name = "queue_depth",
+ .mode = S_IWUSR,
+ },
+ .store = mptscsih_store_queue_depth,
+};
+
+static struct device_attribute *mptspi_dev_attrs[] = {
+ &mptspi_queue_depth_attr,
+ NULL,
+};
+
+static struct scsi_host_template mptspi_driver_template = {
+ .proc_name = "mptspi",
+ .proc_info = mptscsih_proc_info,
+ .name = "MPT SPI Host",
+ .info = mptscsih_info,
+ .queuecommand = mptscsih_qcmd,
+ .slave_alloc = mptscsih_slave_alloc,
+ .slave_configure = mptscsih_slave_configure,
+ .slave_destroy = mptscsih_slave_destroy,
+ .eh_abort_handler = mptscsih_abort,
+ .eh_device_reset_handler = mptscsih_dev_reset,
+ .eh_bus_reset_handler = mptscsih_bus_reset,
+ .eh_host_reset_handler = mptscsih_host_reset,
+ .bios_param = mptscsih_bios_param,
+ .can_queue = MPT_SCSI_CAN_QUEUE,
+ .this_id = -1,
+ .sg_tablesize = MPT_SCSI_SG_DEPTH,
+ .max_sectors = 8192,
+ .cmd_per_lun = 7,
+ .use_clustering = ENABLE_CLUSTERING,
+ .sdev_attrs = mptspi_dev_attrs,
+};
+
+
+/****************************************************************************
+ * Supported hardware
+ */
+
+static struct pci_device_id mptspi_pci_table[] = {
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C1030,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_1030_53C1035,
+ PCI_ANY_ID, PCI_ANY_ID },
+ {0} /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, mptspi_pci_table);
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ * mptspi_probe - Installs scsi devices per bus.
+ * @pdev: Pointer to pci_dev structure
+ *
+ * Returns 0 for success, non-zero for failure.
+ *
+ */
+static int
+mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ struct Scsi_Host *sh;
+ MPT_SCSI_HOST *hd;
+ MPT_ADAPTER *ioc;
+ unsigned long flags;
+ int sz, ii;
+ int numSGE = 0;
+ int scale;
+ int ioc_cap;
+ u8 *mem;
+ int error=0;
+ int r;
+
+ if ((r = mpt_attach(pdev,id)) != 0)
+ return r;
+
+ ioc = pci_get_drvdata(pdev);
+ ioc->DoneCtx = mptspiDoneCtx;
+ ioc->TaskCtx = mptspiTaskCtx;
+ ioc->InternalCtx = mptspiInternalCtx;
+
+ /* Added sanity check on readiness of the MPT adapter.
+ */
+ if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
+ printk(MYIOC_s_WARN_FMT
+ "Skipping because it's not operational!\n",
+ ioc->name);
+ return -ENODEV;
+ }
+
+ if (!ioc->active) {
+ printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
+ ioc->name);
+ return -ENODEV;
+ }
+
+ /* Sanity check - ensure at least 1 port is INITIATOR capable
+ */
+ ioc_cap = 0;
+ for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
+ if (ioc->pfacts[ii].ProtocolFlags &
+ MPI_PORTFACTS_PROTOCOL_INITIATOR)
+ ioc_cap ++;
+ }
+
+ if (!ioc_cap) {
+ printk(MYIOC_s_WARN_FMT
+ "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
+ ioc->name, ioc);
+ return -ENODEV;
+ }
+
+ sh = scsi_host_alloc(&mptspi_driver_template, sizeof(MPT_SCSI_HOST));
+
+ if (!sh) {
+ printk(MYIOC_s_WARN_FMT
+ "Unable to register controller with SCSI subsystem\n",
+ ioc->name);
+ return -1;
+ }
+
+ spin_lock_irqsave(&ioc->FreeQlock, flags);
+
+ /* Attach the SCSI Host to the IOC structure
+ */
+ ioc->sh = sh;
+
+ sh->io_port = 0;
+ sh->n_io_port = 0;
+ sh->irq = 0;
+
+ /* set 16 byte cdb's */
+ sh->max_cmd_len = 16;
+
+ /* Yikes! This is important!
+ * Otherwise, by default, linux
+ * only scans target IDs 0-7!
+ * pfactsN->MaxDevices unreliable
+ * (not supported in early
+ * versions of the FW).
+ * max_id = 1 + actual max id,
+ * max_lun = 1 + actual last lun,
+ * see hosts.h :o(
+ */
+ sh->max_id = MPT_MAX_SCSI_DEVICES;
+
+ sh->max_lun = MPT_LAST_LUN + 1;
+ sh->max_channel = 0;
+ sh->this_id = ioc->pfacts[0].PortSCSIID;
+
+ /* Required entry.
+ */
+ sh->unique_id = ioc->id;
+
+ /* Verify that we won't exceed the maximum
+ * number of chain buffers
+ * We can optimize: ZZ = req_sz/sizeof(SGE)
+ * For 32bit SGE's:
+ * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
+ * + (req_sz - 64)/sizeof(SGE)
+ * A slightly different algorithm is required for
+ * 64bit SGEs.
+ */
+ scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
+ if (sizeof(dma_addr_t) == sizeof(u64)) {
+ numSGE = (scale - 1) *
+ (ioc->facts.MaxChainDepth-1) + scale +
+ (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
+ sizeof(u32));
+ } else {
+ numSGE = 1 + (scale - 1) *
+ (ioc->facts.MaxChainDepth-1) + scale +
+ (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
+ sizeof(u32));
+ }
+
+ if (numSGE < sh->sg_tablesize) {
+ /* Reset this value */
+ dprintk((MYIOC_s_INFO_FMT
+ "Resetting sg_tablesize to %d from %d\n",
+ ioc->name, numSGE, sh->sg_tablesize));
+ sh->sg_tablesize = numSGE;
+ }
+
+ /* Set the pci device pointer in Scsi_Host structure.
+ */
+ scsi_set_device(sh, &ioc->pcidev->dev);
+
+ spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+
+ hd = (MPT_SCSI_HOST *) sh->hostdata;
+ hd->ioc = ioc;
+
+ /* SCSI needs scsi_cmnd lookup table!
+ * (with size equal to req_depth*PtrSz!)
+ */
+ sz = ioc->req_depth * sizeof(void *);
+ mem = kmalloc(sz, GFP_ATOMIC);
+ if (mem == NULL) {
+ error = -ENOMEM;
+ goto mptspi_probe_failed;
+ }
+
+ memset(mem, 0, sz);
+ hd->ScsiLookup = (struct scsi_cmnd **) mem;
+
+ dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
+ ioc->name, hd->ScsiLookup, sz));
+
+ /* Allocate memory for the device structures.
+ * A non-Null pointer at an offset
+ * indicates a device exists.
+ * max_id = 1 + maximum id (hosts.h)
+ */
+ sz = sh->max_id * sizeof(void *);
+ mem = kmalloc(sz, GFP_ATOMIC);
+ if (mem == NULL) {
+ error = -ENOMEM;
+ goto mptspi_probe_failed;
+ }
+
+ memset(mem, 0, sz);
+ hd->Targets = (VirtDevice **) mem;
+
+ dprintk((KERN_INFO
+ " Targets @ %p, sz=%d\n", hd->Targets, sz));
+
+ /* Clear the TM flags
+ */
+ hd->tmPending = 0;
+ hd->tmState = TM_STATE_NONE;
+ hd->resetPending = 0;
+ hd->abortSCpnt = NULL;
+
+ /* Clear the pointer used to store
+ * single-threaded commands, i.e., those
+ * issued during a bus scan, dv and
+ * configuration pages.
+ */
+ hd->cmdPtr = NULL;
+
+ /* Initialize this SCSI Hosts' timers
+ * To use, set the timer expires field
+ * and add_timer
+ */
+ init_timer(&hd->timer);
+ hd->timer.data = (unsigned long) hd;
+ hd->timer.function = mptscsih_timer_expired;
+
+ ioc->spi_data.Saf_Te = mpt_saf_te;
+ hd->mpt_pq_filter = mpt_pq_filter;
+
+#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
+ if (ioc->spi_data.maxBusWidth > mpt_width)
+ ioc->spi_data.maxBusWidth = mpt_width;
+ if (ioc->spi_data.minSyncFactor < mpt_factor)
+ ioc->spi_data.minSyncFactor = mpt_factor;
+ if (ioc->spi_data.minSyncFactor == MPT_ASYNC) {
+ ioc->spi_data.maxSyncOffset = 0;
+ }
+ ioc->spi_data.mpt_dv = mpt_dv;
+ hd->negoNvram = 0;
+
+ ddvprintk((MYIOC_s_INFO_FMT
+ "dv %x width %x factor %x saf_te %x mpt_pq_filter %x\n",
+ ioc->name,
+ mpt_dv,
+ mpt_width,
+ mpt_factor,
+ mpt_saf_te,
+ mpt_pq_filter));
+#else
+ hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
+ ddvprintk((MYIOC_s_INFO_FMT
+ "saf_te %x mpt_pq_filter %x\n",
+ ioc->name,
+ mpt_saf_te,
+ mpt_pq_filter));
+#endif
+
+ ioc->spi_data.forceDv = 0;
+ ioc->spi_data.noQas = 0;
+
+ for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
+ ioc->spi_data.dvStatus[ii] =
+ MPT_SCSICFG_NEGOTIATE;
+
+ for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
+ ioc->spi_data.dvStatus[ii] |=
+ MPT_SCSICFG_DV_NOT_DONE;
+
+ init_waitqueue_head(&hd->scandv_waitq);
+ hd->scandv_wait_done = 0;
+ hd->last_queue_full = 0;
+
+ error = scsi_add_host (sh, &ioc->pcidev->dev);
+ if(error) {
+ dprintk((KERN_ERR MYNAM
+ "scsi_add_host failed\n"));
+ goto mptspi_probe_failed;
+ }
+
+ scsi_scan_host(sh);
+ return 0;
+
+mptspi_probe_failed:
+
+ mptscsih_remove(pdev);
+ return error;
+}
+
+static struct pci_driver mptspi_driver = {
+ .name = "mptspi",
+ .id_table = mptspi_pci_table,
+ .probe = mptspi_probe,
+ .remove = __devexit_p(mptscsih_remove),
+ .driver = {
+ .shutdown = mptscsih_shutdown,
+ },
+#ifdef CONFIG_PM
+ .suspend = mptscsih_suspend,
+ .resume = mptscsih_resume,
+#endif
+};
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ * mptspi_init - Register MPT adapter(s) as SCSI host(s) with
+ * linux scsi mid-layer.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int __init
+mptspi_init(void)
+{
+
+ show_mptmod_ver(my_NAME, my_VERSION);
+
+ mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER);
+ mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER);
+ mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER);
+
+ if (mpt_event_register(mptspiDoneCtx, mptscsih_event_process) == 0) {
+ devtprintk((KERN_INFO MYNAM
+ ": Registered for IOC event notifications\n"));
+ }
+
+ if (mpt_reset_register(mptspiDoneCtx, mptscsih_ioc_reset) == 0) {
+ dprintk((KERN_INFO MYNAM
+ ": Registered for IOC reset notifications\n"));
+ }
+
+ return pci_register_driver(&mptspi_driver);
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ * mptspi_exit - Unregisters MPT adapter(s)
+ *
+ */
+static void __exit
+mptspi_exit(void)
+{
+ pci_unregister_driver(&mptspi_driver);
+
+ mpt_reset_deregister(mptspiDoneCtx);
+ dprintk((KERN_INFO MYNAM
+ ": Deregistered for IOC reset notifications\n"));
+
+ mpt_event_deregister(mptspiDoneCtx);
+ dprintk((KERN_INFO MYNAM
+ ": Deregistered for IOC event notifications\n"));
+
+ mpt_deregister(mptspiInternalCtx);
+ mpt_deregister(mptspiTaskCtx);
+ mpt_deregister(mptspiDoneCtx);
+}
+
+module_init(mptspi_init);
+module_exit(mptspi_exit);
diff --git a/drivers/message/i2o/Kconfig b/drivers/message/i2o/Kconfig
index 8d132b0d6b1..06e8eb19a05 100644
--- a/drivers/message/i2o/Kconfig
+++ b/drivers/message/i2o/Kconfig
@@ -24,10 +24,28 @@ config I2O
If unsure, say N.
+config I2O_EXT_ADAPTEC
+ bool "Enable Adaptec extensions"
+ depends on I2O
+ default y
+ ---help---
+ Say Y for support of raidutils for Adaptec I2O controllers. You also
+ have to say Y to "I2O Configuration support", "I2O SCSI OSM" below
+ and to "SCSI generic support" under "SCSI device configuration".
+
+config I2O_EXT_ADAPTEC_DMA64
+ bool "Enable 64-bit DMA"
+ depends on I2O_EXT_ADAPTEC && ( 64BIT || HIGHMEM64G )
+ default y
+ ---help---
+ Say Y for support of 64-bit DMA transfer mode on Adaptec I2O
+ controllers.
+ Note: You need at least firmware version 3709.
+
config I2O_CONFIG
tristate "I2O Configuration support"
- depends on PCI && I2O
- help
+ depends on I2O
+ ---help---
Say Y for support of the configuration interface for the I2O adapters.
If you have a RAID controller from Adaptec and you want to use the
raidutils to manage your RAID array, you have to say Y here.
@@ -35,10 +53,28 @@ config I2O_CONFIG
To compile this support as a module, choose M here: the
module will be called i2o_config.
+config I2O_CONFIG_OLD_IOCTL
+ bool "Enable ioctls (OBSOLETE)"
+ depends on I2O_CONFIG
+ default y
+ ---help---
+ Enables old ioctls.
+
+config I2O_BUS
+ tristate "I2O Bus Adapter OSM"
+ depends on I2O
+ ---help---
+ Include support for the I2O Bus Adapter OSM. The Bus Adapter OSM
+ provides access to the busses on the I2O controller. The main purpose
+ is to rescan the bus to find new devices.
+
+ To compile this support as a module, choose M here: the
+ module will be called i2o_bus.
+
config I2O_BLOCK
tristate "I2O Block OSM"
depends on I2O
- help
+ ---help---
Include support for the I2O Block OSM. The Block OSM presents disk
and other structured block devices to the operating system. If you
are using an RAID controller, you could access the array only by
@@ -51,7 +87,7 @@ config I2O_BLOCK
config I2O_SCSI
tristate "I2O SCSI OSM"
depends on I2O && SCSI
- help
+ ---help---
Allows direct SCSI access to SCSI devices on a SCSI or FibreChannel
I2O controller. You can use both the SCSI and Block OSM together if
you wish. To access a RAID array, you must use the Block OSM driver.
@@ -63,7 +99,7 @@ config I2O_SCSI
config I2O_PROC
tristate "I2O /proc support"
depends on I2O
- help
+ ---help---
If you say Y here and to "/proc file system support", you will be
able to read I2O related information from the virtual directory
/proc/i2o.
diff --git a/drivers/message/i2o/Makefile b/drivers/message/i2o/Makefile
index aabc6cdc3fc..2c2e39aa1ef 100644
--- a/drivers/message/i2o/Makefile
+++ b/drivers/message/i2o/Makefile
@@ -6,8 +6,11 @@
#
i2o_core-y += iop.o driver.o device.o debug.o pci.o exec-osm.o
+i2o_bus-y += bus-osm.o
+i2o_config-y += config-osm.o
obj-$(CONFIG_I2O) += i2o_core.o
obj-$(CONFIG_I2O_CONFIG)+= i2o_config.o
+obj-$(CONFIG_I2O_BUS) += i2o_bus.o
obj-$(CONFIG_I2O_BLOCK) += i2o_block.o
obj-$(CONFIG_I2O_SCSI) += i2o_scsi.o
obj-$(CONFIG_I2O_PROC) += i2o_proc.o
diff --git a/drivers/message/i2o/bus-osm.c b/drivers/message/i2o/bus-osm.c
new file mode 100644
index 00000000000..151b228e1cb
--- /dev/null
+++ b/drivers/message/i2o/bus-osm.c
@@ -0,0 +1,164 @@
+/*
+ * Bus Adapter OSM
+ *
+ * Copyright (C) 2005 Markus Lidel <Markus.Lidel@shadowconnect.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.
+ *
+ * Fixes/additions:
+ * Markus Lidel <Markus.Lidel@shadowconnect.com>
+ * initial version.
+ */
+
+#include <linux/module.h>
+#include <linux/i2o.h>
+
+#define OSM_NAME "bus-osm"
+#define OSM_VERSION "$Rev$"
+#define OSM_DESCRIPTION "I2O Bus Adapter OSM"
+
+static struct i2o_driver i2o_bus_driver;
+
+/* Bus OSM class handling definition */
+static struct i2o_class_id i2o_bus_class_id[] = {
+ {I2O_CLASS_BUS_ADAPTER},
+ {I2O_CLASS_END}
+};
+
+/**
+ * i2o_bus_scan - Scan the bus for new devices
+ * @dev: I2O device of the bus, which should be scanned
+ *
+ * Scans the bus dev for new / removed devices. After the scan a new LCT
+ * will be fetched automatically.
+ *
+ * Returns 0 on success or negative error code on failure.
+ */
+static int i2o_bus_scan(struct i2o_device *dev)
+{
+ struct i2o_message __iomem *msg;
+ u32 m;
+
+ m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
+ if (m == I2O_QUEUE_EMPTY)
+ return -ETIMEDOUT;
+
+ writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+ writel(I2O_CMD_BUS_SCAN << 24 | HOST_TID << 12 | dev->lct_data.tid,
+ &msg->u.head[1]);
+
+ return i2o_msg_post_wait(dev->iop, m, 60);
+};
+
+/**
+ * i2o_bus_store_scan - Scan the I2O Bus Adapter
+ * @d: device which should be scanned
+ *
+ * Returns count.
+ */
+static ssize_t i2o_bus_store_scan(struct device *d, struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ struct i2o_device *i2o_dev = to_i2o_device(d);
+ int rc;
+
+ if ((rc = i2o_bus_scan(i2o_dev)))
+ osm_warn("bus scan failed %d\n", rc);
+
+ return count;
+}
+
+/* Bus Adapter OSM device attributes */
+static DEVICE_ATTR(scan, S_IWUSR, NULL, i2o_bus_store_scan);
+
+/**
+ * i2o_bus_probe - verify if dev is a I2O Bus Adapter device and install it
+ * @dev: device to verify if it is a I2O Bus Adapter device
+ *
+ * Because we want all Bus Adapters always return 0.
+ *
+ * Returns 0.
+ */
+static int i2o_bus_probe(struct device *dev)
+{
+ struct i2o_device *i2o_dev = to_i2o_device(get_device(dev));
+
+ device_create_file(dev, &dev_attr_scan);
+
+ osm_info("device added (TID: %03x)\n", i2o_dev->lct_data.tid);
+
+ return 0;
+};
+
+/**
+ * i2o_bus_remove - remove the I2O Bus Adapter device from the system again
+ * @dev: I2O Bus Adapter device which should be removed
+ *
+ * Always returns 0.
+ */
+static int i2o_bus_remove(struct device *dev)
+{
+ struct i2o_device *i2o_dev = to_i2o_device(dev);
+
+ device_remove_file(dev, &dev_attr_scan);
+
+ put_device(dev);
+
+ osm_info("device removed (TID: %03x)\n", i2o_dev->lct_data.tid);
+
+ return 0;
+};
+
+/* Bus Adapter OSM driver struct */
+static struct i2o_driver i2o_bus_driver = {
+ .name = OSM_NAME,
+ .classes = i2o_bus_class_id,
+ .driver = {
+ .probe = i2o_bus_probe,
+ .remove = i2o_bus_remove,
+ },
+};
+
+/**
+ * i2o_bus_init - Bus Adapter OSM initialization function
+ *
+ * Only register the Bus Adapter OSM in the I2O core.
+ *
+ * Returns 0 on success or negative error code on failure.
+ */
+static int __init i2o_bus_init(void)
+{
+ int rc;
+
+ printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n");
+
+ /* Register Bus Adapter OSM into I2O core */
+ rc = i2o_driver_register(&i2o_bus_driver);
+ if (rc) {
+ osm_err("Could not register Bus Adapter OSM\n");
+ return rc;
+ }
+
+ return 0;
+};
+
+/**
+ * i2o_bus_exit - Bus Adapter OSM exit function
+ *
+ * Unregisters Bus Adapter OSM from I2O core.
+ */
+static void __exit i2o_bus_exit(void)
+{
+ i2o_driver_unregister(&i2o_bus_driver);
+};
+
+MODULE_AUTHOR("Markus Lidel <Markus.Lidel@shadowconnect.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION(OSM_DESCRIPTION);
+MODULE_VERSION(OSM_VERSION);
+
+module_init(i2o_bus_init);
+module_exit(i2o_bus_exit);
diff --git a/drivers/message/i2o/config-osm.c b/drivers/message/i2o/config-osm.c
new file mode 100644
index 00000000000..d0267609a94
--- /dev/null
+++ b/drivers/message/i2o/config-osm.c
@@ -0,0 +1,579 @@
+/*
+ * Configuration OSM
+ *
+ * Copyright (C) 2005 Markus Lidel <Markus.Lidel@shadowconnect.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.
+ *
+ * Fixes/additions:
+ * Markus Lidel <Markus.Lidel@shadowconnect.com>
+ * initial version.
+ */
+
+#include <linux/module.h>
+#include <linux/i2o.h>
+#include <linux/namei.h>
+
+#include <asm/uaccess.h>
+
+#define OSM_NAME "config-osm"
+#define OSM_VERSION "1.248"
+#define OSM_DESCRIPTION "I2O Configuration OSM"
+
+/* access mode user rw */
+#define S_IWRSR (S_IRUSR | S_IWUSR)
+
+static struct i2o_driver i2o_config_driver;
+
+/* Special file operations for sysfs */
+struct fops_attribute {
+ struct bin_attribute bin;
+ struct file_operations fops;
+};
+
+/**
+ * sysfs_read_dummy
+ */
+static ssize_t sysfs_read_dummy(struct kobject *kobj, char *buf, loff_t offset,
+ size_t count)
+{
+ return 0;
+};
+
+/**
+ * sysfs_write_dummy
+ */
+static ssize_t sysfs_write_dummy(struct kobject *kobj, char *buf, loff_t offset,
+ size_t count)
+{
+ return 0;
+};
+
+/**
+ * sysfs_create_fops_file - Creates attribute with special file operations
+ * @kobj: kobject which should contains the attribute
+ * @attr: attributes which should be used to create file
+ *
+ * First creates attribute @attr in kobject @kobj. If it is the first time
+ * this function is called, merge old fops from sysfs with new one and
+ * write it back. Afterwords the new fops will be set for the created
+ * attribute.
+ *
+ * Returns 0 on success or negative error code on failure.
+ */
+static int sysfs_create_fops_file(struct kobject *kobj,
+ struct fops_attribute *attr)
+{
+ struct file_operations tmp, *fops;
+ struct dentry *d;
+ struct qstr qstr;
+ int rc;
+
+ fops = &attr->fops;
+
+ if (fops->read)
+ attr->bin.read = sysfs_read_dummy;
+
+ if (fops->write)
+ attr->bin.write = sysfs_write_dummy;
+
+ if ((rc = sysfs_create_bin_file(kobj, &attr->bin)))
+ return rc;
+
+ qstr.name = attr->bin.attr.name;
+ qstr.len = strlen(qstr.name);
+ qstr.hash = full_name_hash(qstr.name, qstr.len);
+
+ if ((d = lookup_hash(&qstr, kobj->dentry))) {
+ if (!fops->owner) {
+ memcpy(&tmp, d->d_inode->i_fop, sizeof(tmp));
+ if (fops->read)
+ tmp.read = fops->read;
+ if (fops->write)
+ tmp.write = fops->write;
+ memcpy(fops, &tmp, sizeof(tmp));
+ }
+
+ d->d_inode->i_fop = fops;
+ } else
+ sysfs_remove_bin_file(kobj, &attr->bin);
+
+ return -ENOENT;
+};
+
+/**
+ * sysfs_remove_fops_file - Remove attribute with special file operations
+ * @kobj: kobject which contains the attribute
+ * @attr: attributes which are used to create file
+ *
+ * Only wrapper arround sysfs_remove_bin_file()
+ *
+ * Returns 0 on success or negative error code on failure.
+ */
+static inline int sysfs_remove_fops_file(struct kobject *kobj,
+ struct fops_attribute *attr)
+{
+ return sysfs_remove_bin_file(kobj, &attr->bin);
+};
+
+/**
+ * i2o_config_read_hrt - Returns the HRT of the controller
+ * @kob: kernel object handle
+ * @buf: buffer into which the HRT should be copied
+ * @off: file offset
+ * @count: number of bytes to read
+ *
+ * Put @count bytes starting at @off into @buf from the HRT of the I2O
+ * controller corresponding to @kobj.
+ *
+ * Returns number of bytes copied into buffer.
+ */
+static ssize_t i2o_config_read_hrt(struct kobject *kobj, char *buf,
+ loff_t offset, size_t count)
+{
+ struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
+ i2o_hrt *hrt = c->hrt.virt;
+
+ u32 size = (hrt->num_entries * hrt->entry_len + 2) * 4;
+
+ if (offset > size)
+ return 0;
+
+ if (offset + count > size)
+ count = size - offset;
+
+ memcpy(buf, (u8 *) hrt + offset, count);
+
+ return count;
+};
+
+/**
+ * i2o_config_read_lct - Returns the LCT of the controller
+ * @kob: kernel object handle
+ * @buf: buffer into which the LCT should be copied
+ * @off: file offset
+ * @count: number of bytes to read
+ *
+ * Put @count bytes starting at @off into @buf from the LCT of the I2O
+ * controller corresponding to @kobj.
+ *
+ * Returns number of bytes copied into buffer.
+ */
+static ssize_t i2o_config_read_lct(struct kobject *kobj, char *buf,
+ loff_t offset, size_t count)
+{
+ struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
+ u32 size = c->lct->table_size * 4;
+
+ if (offset > size)
+ return 0;
+
+ if (offset + count > size)
+ count = size - offset;
+
+ memcpy(buf, (u8 *) c->lct + offset, count);
+
+ return count;
+};
+
+#define I2O_CONFIG_SW_ATTR(_name,_mode,_type,_swid) \
+static ssize_t i2o_config_##_name##_read(struct file *file, char __user *buf, size_t count, loff_t * offset) { \
+ return i2o_config_sw_read(file, buf, count, offset, _type, _swid); \
+};\
+\
+static ssize_t i2o_config_##_name##_write(struct file *file, const char __user *buf, size_t count, loff_t * offset) { \
+ return i2o_config_sw_write(file, buf, count, offset, _type, _swid); \
+}; \
+\
+static struct fops_attribute i2o_config_attr_##_name = { \
+ .bin = { .attr = { .name = __stringify(_name), .mode = _mode, \
+ .owner = THIS_MODULE }, \
+ .size = 0, }, \
+ .fops = { .write = i2o_config_##_name##_write, \
+ .read = i2o_config_##_name##_read} \
+};
+
+#ifdef CONFIG_I2O_EXT_ADAPTEC
+
+/**
+ * i2o_config_dpt_reagion - Converts type and id to flash region
+ * @swtype: type of software module reading
+ * @swid: id of software which should be read
+ *
+ * Converts type and id from I2O spec to the matching region for DPT /
+ * Adaptec controllers.
+ *
+ * Returns region which match type and id or -1 on error.
+ */
+static u32 i2o_config_dpt_region(u8 swtype, u8 swid)
+{
+ switch (swtype) {
+ case I2O_SOFTWARE_MODULE_IRTOS:
+ /*
+ * content: operation firmware
+ * region size:
+ * 0xbc000 for 2554, 3754, 2564, 3757
+ * 0x170000 for 2865
+ * 0x17c000 for 3966
+ */
+ if (!swid)
+ return 0;
+
+ break;
+
+ case I2O_SOFTWARE_MODULE_IOP_PRIVATE:
+ /*
+ * content: BIOS and SMOR
+ * BIOS size: first 0x8000 bytes
+ * region size:
+ * 0x40000 for 2554, 3754, 2564, 3757
+ * 0x80000 for 2865, 3966
+ */
+ if (!swid)
+ return 1;
+
+ break;
+
+ case I2O_SOFTWARE_MODULE_IOP_CONFIG:
+ switch (swid) {
+ case 0:
+ /*
+ * content: NVRAM defaults
+ * region size: 0x2000 bytes
+ */
+ return 2;
+ case 1:
+ /*
+ * content: serial number
+ * region size: 0x2000 bytes
+ */
+ return 3;
+ }
+ break;
+ }
+
+ return -1;
+};
+
+#endif
+
+/**
+ * i2o_config_sw_read - Read a software module from controller
+ * @file: file pointer
+ * @buf: buffer into which the data should be copied
+ * @count: number of bytes to read
+ * @off: file offset
+ * @swtype: type of software module reading
+ * @swid: id of software which should be read
+ *
+ * Transfers @count bytes at offset @offset from IOP into buffer using
+ * type @swtype and id @swid as described in I2O spec.
+ *
+ * Returns number of bytes copied into buffer or error code on failure.
+ */
+static ssize_t i2o_config_sw_read(struct file *file, char __user * buf,
+ size_t count, loff_t * offset, u8 swtype,
+ u32 swid)
+{
+ struct sysfs_dirent *sd = file->f_dentry->d_parent->d_fsdata;
+ struct kobject *kobj = sd->s_element;
+ struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
+ u32 m, function = I2O_CMD_SW_UPLOAD;
+ struct i2o_dma buffer;
+ struct i2o_message __iomem *msg;
+ u32 __iomem *mptr;
+ int rc, status;
+
+ m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+ if (m == I2O_QUEUE_EMPTY)
+ return -EBUSY;
+
+ mptr = &msg->body[3];
+
+ if ((rc = i2o_dma_alloc(&c->pdev->dev, &buffer, count, GFP_KERNEL))) {
+ i2o_msg_nop(c, m);
+ return rc;
+ }
+#ifdef CONFIG_I2O_EXT_ADAPTEC
+ if (c->adaptec) {
+ mptr = &msg->body[4];
+ function = I2O_CMD_PRIVATE;
+
+ writel(TEN_WORD_MSG_SIZE | SGL_OFFSET_8, &msg->u.head[0]);
+
+ writel(I2O_VENDOR_DPT << 16 | I2O_DPT_FLASH_READ,
+ &msg->body[0]);
+ writel(i2o_config_dpt_region(swtype, swid), &msg->body[1]);
+ writel(*offset, &msg->body[2]);
+ writel(count, &msg->body[3]);
+ } else
+#endif
+ writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]);
+
+ writel(0xD0000000 | count, mptr++);
+ writel(buffer.phys, mptr);
+
+ writel(function << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]);
+ writel(i2o_config_driver.context, &msg->u.head[2]);
+ writel(0, &msg->u.head[3]);
+
+#ifdef CONFIG_I2O_EXT_ADAPTEC
+ if (!c->adaptec)
+#endif
+ {
+ writel((u32) swtype << 16 | (u32) 1 << 8, &msg->body[0]);
+ writel(0, &msg->body[1]);
+ writel(swid, &msg->body[2]);
+ }
+
+ status = i2o_msg_post_wait_mem(c, m, 60, &buffer);
+
+ if (status == I2O_POST_WAIT_OK) {
+ if (!(rc = copy_to_user(buf, buffer.virt, count))) {
+ rc = count;
+ *offset += count;
+ }
+ } else
+ rc = -EIO;
+
+ if (status != -ETIMEDOUT)
+ i2o_dma_free(&c->pdev->dev, &buffer);
+
+ return rc;
+};
+
+/**
+ * i2o_config_sw_write - Write a software module to controller
+ * @file: file pointer
+ * @buf: buffer into which the data should be copied
+ * @count: number of bytes to read
+ * @off: file offset
+ * @swtype: type of software module writing
+ * @swid: id of software which should be written
+ *
+ * Transfers @count bytes at offset @offset from buffer to IOP using
+ * type @swtype and id @swid as described in I2O spec.
+ *
+ * Returns number of bytes copied from buffer or error code on failure.
+ */
+static ssize_t i2o_config_sw_write(struct file *file, const char __user * buf,
+ size_t count, loff_t * offset, u8 swtype,
+ u32 swid)
+{
+ struct sysfs_dirent *sd = file->f_dentry->d_parent->d_fsdata;
+ struct kobject *kobj = sd->s_element;
+ struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
+ u32 m, function = I2O_CMD_SW_DOWNLOAD;
+ struct i2o_dma buffer;
+ struct i2o_message __iomem *msg;
+ u32 __iomem *mptr;
+ int rc, status;
+
+ m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+ if (m == I2O_QUEUE_EMPTY)
+ return -EBUSY;
+
+ mptr = &msg->body[3];
+
+ if ((rc = i2o_dma_alloc(&c->pdev->dev, &buffer, count, GFP_KERNEL)))
+ goto nop_msg;
+
+ if ((rc = copy_from_user(buffer.virt, buf, count)))
+ goto free_buffer;
+
+#ifdef CONFIG_I2O_EXT_ADAPTEC
+ if (c->adaptec) {
+ mptr = &msg->body[4];
+ function = I2O_CMD_PRIVATE;
+
+ writel(TEN_WORD_MSG_SIZE | SGL_OFFSET_8, &msg->u.head[0]);
+
+ writel(I2O_VENDOR_DPT << 16 | I2O_DPT_FLASH_WRITE,
+ &msg->body[0]);
+ writel(i2o_config_dpt_region(swtype, swid), &msg->body[1]);
+ writel(*offset, &msg->body[2]);
+ writel(count, &msg->body[3]);
+ } else
+#endif
+ writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]);
+
+ writel(0xD4000000 | count, mptr++);
+ writel(buffer.phys, mptr);
+
+ writel(function << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]);
+ writel(i2o_config_driver.context, &msg->u.head[2]);
+ writel(0, &msg->u.head[3]);
+
+#ifdef CONFIG_I2O_EXT_ADAPTEC
+ if (!c->adaptec)
+#endif
+ {
+ writel((u32) swtype << 16 | (u32) 1 << 8, &msg->body[0]);
+ writel(0, &msg->body[1]);
+ writel(swid, &msg->body[2]);
+ }
+
+ status = i2o_msg_post_wait_mem(c, m, 60, &buffer);
+
+ if (status != -ETIMEDOUT)
+ i2o_dma_free(&c->pdev->dev, &buffer);
+
+ if (status != I2O_POST_WAIT_OK)
+ return -EIO;
+
+ *offset += count;
+
+ return count;
+
+ free_buffer:
+ i2o_dma_free(&c->pdev->dev, &buffer);
+
+ nop_msg:
+ i2o_msg_nop(c, m);
+
+ return rc;
+};
+
+/* attribute for HRT in sysfs */
+static struct bin_attribute i2o_config_hrt_attr = {
+ .attr = {
+ .name = "hrt",
+ .mode = S_IRUGO,
+ .owner = THIS_MODULE},
+ .size = 0,
+ .read = i2o_config_read_hrt
+};
+
+/* attribute for LCT in sysfs */
+static struct bin_attribute i2o_config_lct_attr = {
+ .attr = {
+ .name = "lct",
+ .mode = S_IRUGO,
+ .owner = THIS_MODULE},
+ .size = 0,
+ .read = i2o_config_read_lct
+};
+
+/* IRTOS firmware access */
+I2O_CONFIG_SW_ATTR(irtos, S_IWRSR, I2O_SOFTWARE_MODULE_IRTOS, 0);
+
+#ifdef CONFIG_I2O_EXT_ADAPTEC
+
+/*
+ * attribute for BIOS / SMOR, nvram and serial number access on DPT / Adaptec
+ * controllers
+ */
+I2O_CONFIG_SW_ATTR(bios, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_PRIVATE, 0);
+I2O_CONFIG_SW_ATTR(nvram, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_CONFIG, 0);
+I2O_CONFIG_SW_ATTR(serial, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_CONFIG, 1);
+
+#endif
+
+/**
+ * i2o_config_notify_controller_add - Notify of added controller
+ * @c: the controller which was added
+ *
+ * If a I2O controller is added, we catch the notification to add sysfs
+ * entries.
+ */
+static void i2o_config_notify_controller_add(struct i2o_controller *c)
+{
+ struct kobject *kobj = &c->exec->device.kobj;
+
+ sysfs_create_bin_file(kobj, &i2o_config_hrt_attr);
+ sysfs_create_bin_file(kobj, &i2o_config_lct_attr);
+
+ sysfs_create_fops_file(kobj, &i2o_config_attr_irtos);
+#ifdef CONFIG_I2O_EXT_ADAPTEC
+ if (c->adaptec) {
+ sysfs_create_fops_file(kobj, &i2o_config_attr_bios);
+ sysfs_create_fops_file(kobj, &i2o_config_attr_nvram);
+ sysfs_create_fops_file(kobj, &i2o_config_attr_serial);
+ }
+#endif
+};
+
+/**
+ * i2o_config_notify_controller_remove - Notify of removed controller
+ * @c: the controller which was removed
+ *
+ * If a I2O controller is removed, we catch the notification to remove the
+ * sysfs entries.
+ */
+static void i2o_config_notify_controller_remove(struct i2o_controller *c)
+{
+ struct kobject *kobj = &c->exec->device.kobj;
+
+#ifdef CONFIG_I2O_EXT_ADAPTEC
+ if (c->adaptec) {
+ sysfs_remove_fops_file(kobj, &i2o_config_attr_serial);
+ sysfs_remove_fops_file(kobj, &i2o_config_attr_nvram);
+ sysfs_remove_fops_file(kobj, &i2o_config_attr_bios);
+ }
+#endif
+ sysfs_remove_fops_file(kobj, &i2o_config_attr_irtos);
+
+ sysfs_remove_bin_file(kobj, &i2o_config_lct_attr);
+ sysfs_remove_bin_file(kobj, &i2o_config_hrt_attr);
+};
+
+/* Config OSM driver struct */
+static struct i2o_driver i2o_config_driver = {
+ .name = OSM_NAME,
+ .notify_controller_add = i2o_config_notify_controller_add,
+ .notify_controller_remove = i2o_config_notify_controller_remove
+};
+
+#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL
+#include "i2o_config.c"
+#endif
+
+/**
+ * i2o_config_init - Configuration OSM initialization function
+ *
+ * Registers Configuration OSM in the I2O core and if old ioctl's are
+ * compiled in initialize them.
+ *
+ * Returns 0 on success or negative error code on failure.
+ */
+static int __init i2o_config_init(void)
+{
+ printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n");
+
+ if (i2o_driver_register(&i2o_config_driver)) {
+ osm_err("handler register failed.\n");
+ return -EBUSY;
+ }
+#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL
+ if (i2o_config_old_init())
+ i2o_driver_unregister(&i2o_config_driver);
+#endif
+
+ return 0;
+}
+
+/**
+ * i2o_config_exit - Configuration OSM exit function
+ *
+ * If old ioctl's are compiled in exit remove them and unregisters
+ * Configuration OSM from I2O core.
+ */
+static void i2o_config_exit(void)
+{
+#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL
+ i2o_config_old_exit();
+#endif
+
+ i2o_driver_unregister(&i2o_config_driver);
+}
+
+MODULE_AUTHOR("Markus Lidel <Markus.Lidel@shadowconnect.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION(OSM_DESCRIPTION);
+MODULE_VERSION(OSM_VERSION);
+
+module_init(i2o_config_init);
+module_exit(i2o_config_exit);
diff --git a/drivers/message/i2o/core.h b/drivers/message/i2o/core.h
new file mode 100644
index 00000000000..c5bcfd70f71
--- /dev/null
+++ b/drivers/message/i2o/core.h
@@ -0,0 +1,58 @@
+/*
+ * I2O core internal declarations
+ *
+ * Copyright (C) 2005 Markus Lidel <Markus.Lidel@shadowconnect.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.
+ *
+ * Fixes/additions:
+ * Markus Lidel <Markus.Lidel@shadowconnect.com>
+ * initial version.
+ */
+
+/* Exec-OSM */
+extern struct bus_type i2o_bus_type;
+
+extern struct i2o_driver i2o_exec_driver;
+extern int i2o_exec_lct_get(struct i2o_controller *);
+
+extern int __init i2o_exec_init(void);
+extern void __exit i2o_exec_exit(void);
+
+/* driver */
+extern int i2o_driver_dispatch(struct i2o_controller *, u32);
+
+extern int __init i2o_driver_init(void);
+extern void __exit i2o_driver_exit(void);
+
+/* PCI */
+extern int __init i2o_pci_init(void);
+extern void __exit i2o_pci_exit(void);
+
+/* device */
+extern void i2o_device_remove(struct i2o_device *);
+extern int i2o_device_parse_lct(struct i2o_controller *);
+
+extern int i2o_device_init(void);
+extern void i2o_device_exit(void);
+
+/* IOP */
+extern struct i2o_controller *i2o_iop_alloc(void);
+extern void i2o_iop_free(struct i2o_controller *);
+
+extern int i2o_iop_add(struct i2o_controller *);
+extern void i2o_iop_remove(struct i2o_controller *);
+
+/* config */
+extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int);
+
+/* control registers relative to c->base */
+#define I2O_IRQ_STATUS 0x30
+#define I2O_IRQ_MASK 0x34
+#define I2O_IN_PORT 0x40
+#define I2O_OUT_PORT 0x44
+
+#define I2O_IRQ_OUTBOUND_POST 0x00000008
diff --git a/drivers/message/i2o/debug.c b/drivers/message/i2o/debug.c
index 2a5d478fc60..018ca887ca8 100644
--- a/drivers/message/i2o/debug.c
+++ b/drivers/message/i2o/debug.c
@@ -4,8 +4,6 @@
#include <linux/pci.h>
#include <linux/i2o.h>
-extern struct i2o_driver **i2o_drivers;
-extern unsigned int i2o_max_drivers;
static void i2o_report_util_cmd(u8 cmd);
static void i2o_report_exec_cmd(u8 cmd);
static void i2o_report_fail_status(u8 req_status, u32 * msg);
@@ -23,7 +21,6 @@ void i2o_report_status(const char *severity, const char *str,
u8 cmd = (msg[1] >> 24) & 0xFF;
u8 req_status = (msg[4] >> 24) & 0xFF;
u16 detailed_status = msg[4] & 0xFFFF;
- //struct i2o_driver *h = i2o_drivers[msg[2] & (i2o_max_drivers-1)];
if (cmd == I2O_CMD_UTIL_EVT_REGISTER)
return; // No status in this reply
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c
index eb907e87bc7..21f16ba3ac3 100644
--- a/drivers/message/i2o/device.c
+++ b/drivers/message/i2o/device.c
@@ -16,9 +16,7 @@
#include <linux/module.h>
#include <linux/i2o.h>
#include <linux/delay.h>
-
-/* Exec OSM functions */
-extern struct bus_type i2o_bus_type;
+#include "core.h"
/**
* i2o_device_issue_claim - claim or release a device
@@ -282,8 +280,7 @@ int i2o_device_parse_lct(struct i2o_controller *c)
down(&c->lct_lock);
- if (c->lct)
- kfree(c->lct);
+ kfree(c->lct);
lct = c->dlct.virt;
@@ -294,12 +291,12 @@ int i2o_device_parse_lct(struct i2o_controller *c)
}
if (lct->table_size * 4 > c->dlct.len) {
- memcpy_fromio(c->lct, c->dlct.virt, c->dlct.len);
+ memcpy(c->lct, c->dlct.virt, c->dlct.len);
up(&c->lct_lock);
return -EAGAIN;
}
- memcpy_fromio(c->lct, c->dlct.virt, lct->table_size * 4);
+ memcpy(c->lct, c->dlct.virt, lct->table_size * 4);
lct = c->lct;
@@ -354,7 +351,7 @@ static ssize_t i2o_device_class_show_class_id(struct class_device *cd,
{
struct i2o_device *dev = to_i2o_device(cd->dev);
- sprintf(buf, "%03x\n", dev->lct_data.class_id);
+ sprintf(buf, "0x%03x\n", dev->lct_data.class_id);
return strlen(buf) + 1;
};
@@ -369,7 +366,7 @@ static ssize_t i2o_device_class_show_tid(struct class_device *cd, char *buf)
{
struct i2o_device *dev = to_i2o_device(cd->dev);
- sprintf(buf, "%03x\n", dev->lct_data.tid);
+ sprintf(buf, "0x%03x\n", dev->lct_data.tid);
return strlen(buf) + 1;
};
@@ -401,25 +398,27 @@ static int i2o_device_class_add(struct class_device *cd)
/* create user entries for this device */
tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid);
- if (tmp)
+ if (tmp && (tmp != i2o_dev))
sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
"user");
/* create user entries refering to this device */
list_for_each_entry(tmp, &c->devices, list)
- if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
+ if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
+ && (tmp != i2o_dev))
sysfs_create_link(&tmp->device.kobj,
&i2o_dev->device.kobj, "user");
/* create parent entries for this device */
tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid);
- if (tmp)
+ if (tmp && (tmp != i2o_dev))
sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
"parent");
/* create parent entries refering to this device */
list_for_each_entry(tmp, &c->devices, list)
- if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
+ if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
+ && (tmp != i2o_dev))
sysfs_create_link(&tmp->device.kobj,
&i2o_dev->device.kobj, "parent");
@@ -444,9 +443,8 @@ static struct class_interface i2o_device_class_interface = {
* Note that the minimum sized reslist is 8 bytes and contains
* ResultCount, ErrorInfoSize, BlockStatus and BlockSize.
*/
-
int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
- int oplen, void *reslist, int reslen)
+ int oplen, void *reslist, int reslen)
{
struct i2o_message __iomem *msg;
u32 m;
@@ -489,7 +487,7 @@ int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
if (rc == -ETIMEDOUT)
return rc;
- memcpy_fromio(reslist, res.virt, res.len);
+ memcpy(reslist, res.virt, res.len);
i2o_dma_free(dev, &res);
/* Query failed */
@@ -531,17 +529,23 @@ int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field,
void *buf, int buflen)
{
u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field };
- u8 resblk[8 + buflen]; /* 8 bytes for header */
+ u8 *resblk; /* 8 bytes for header */
int size;
if (field == -1) /* whole group */
opblk[4] = -1;
+ resblk = kmalloc(buflen + 8, GFP_KERNEL | GFP_ATOMIC);
+ if (!resblk)
+ return -ENOMEM;
+
size = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk,
- sizeof(opblk), resblk, sizeof(resblk));
+ sizeof(opblk), resblk, buflen + 8);
memcpy(buf, resblk + 8, buflen); /* cut off header */
+ kfree(resblk);
+
if (size > buflen)
return buflen;
diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c
index 91f4edbb2a2..739bfdef0c6 100644
--- a/drivers/message/i2o/driver.c
+++ b/drivers/message/i2o/driver.c
@@ -17,9 +17,12 @@
#include <linux/module.h>
#include <linux/rwsem.h>
#include <linux/i2o.h>
+#include "core.h"
+
+#define OSM_NAME "i2o"
/* max_drivers - Maximum I2O drivers (OSMs) which could be registered */
-unsigned int i2o_max_drivers = I2O_MAX_DRIVERS;
+static unsigned int i2o_max_drivers = I2O_MAX_DRIVERS;
module_param_named(max_drivers, i2o_max_drivers, uint, 0);
MODULE_PARM_DESC(max_drivers, "maximum number of OSM's to support");
@@ -76,17 +79,16 @@ int i2o_driver_register(struct i2o_driver *drv)
int rc = 0;
unsigned long flags;
- pr_debug("i2o: Register driver %s\n", drv->name);
+ osm_debug("Register driver %s\n", drv->name);
if (drv->event) {
drv->event_queue = create_workqueue(drv->name);
if (!drv->event_queue) {
- printk(KERN_ERR "i2o: Could not initialize event queue "
- "for driver %s\n", drv->name);
+ osm_err("Could not initialize event queue for driver "
+ "%s\n", drv->name);
return -EFAULT;
}
- pr_debug("i2o: Event queue initialized for driver %s\n",
- drv->name);
+ osm_debug("Event queue initialized for driver %s\n", drv->name);
} else
drv->event_queue = NULL;
@@ -97,8 +99,8 @@ int i2o_driver_register(struct i2o_driver *drv)
for (i = 0; i2o_drivers[i]; i++)
if (i >= i2o_max_drivers) {
- printk(KERN_ERR "i2o: too many drivers registered, "
- "increase max_drivers\n");
+ osm_err("too many drivers registered, increase "
+ "max_drivers\n");
spin_unlock_irqrestore(&i2o_drivers_lock, flags);
return -EFAULT;
}
@@ -108,18 +110,16 @@ int i2o_driver_register(struct i2o_driver *drv)
spin_unlock_irqrestore(&i2o_drivers_lock, flags);
- pr_debug("i2o: driver %s gets context id %d\n", drv->name,
- drv->context);
+ osm_debug("driver %s gets context id %d\n", drv->name, drv->context);
list_for_each_entry(c, &i2o_controllers, list) {
struct i2o_device *i2o_dev;
i2o_driver_notify_controller_add(drv, c);
list_for_each_entry(i2o_dev, &c->devices, list)
- i2o_driver_notify_device_add(drv, i2o_dev);
+ i2o_driver_notify_device_add(drv, i2o_dev);
}
-
rc = driver_register(&drv->driver);
if (rc)
destroy_workqueue(drv->event_queue);
@@ -139,7 +139,7 @@ void i2o_driver_unregister(struct i2o_driver *drv)
struct i2o_controller *c;
unsigned long flags;
- pr_debug("i2o: unregister driver %s\n", drv->name);
+ osm_debug("unregister driver %s\n", drv->name);
driver_unregister(&drv->driver);
@@ -159,7 +159,7 @@ void i2o_driver_unregister(struct i2o_driver *drv)
if (drv->event_queue) {
destroy_workqueue(drv->event_queue);
drv->event_queue = NULL;
- pr_debug("i2o: event queue removed for %s\n", drv->name);
+ osm_debug("event queue removed for %s\n", drv->name);
}
};
@@ -176,68 +176,70 @@ void i2o_driver_unregister(struct i2o_driver *drv)
* on success and if the message should be flushed afterwords. Returns
* negative error code on failure (the message will be flushed too).
*/
-int i2o_driver_dispatch(struct i2o_controller *c, u32 m,
- struct i2o_message __iomem *msg)
+int i2o_driver_dispatch(struct i2o_controller *c, u32 m)
{
struct i2o_driver *drv;
- u32 context = readl(&msg->u.s.icntxt);
+ struct i2o_message *msg = i2o_msg_out_to_virt(c, m);
+ u32 context = le32_to_cpu(msg->u.s.icntxt);
+ unsigned long flags;
- if (likely(context < i2o_max_drivers)) {
- spin_lock(&i2o_drivers_lock);
- drv = i2o_drivers[context];
- spin_unlock(&i2o_drivers_lock);
+ if (unlikely(context >= i2o_max_drivers)) {
+ osm_warn("%s: Spurious reply to unknown driver %d\n", c->name,
+ context);
+ return -EIO;
+ }
- if (unlikely(!drv)) {
- printk(KERN_WARNING "%s: Spurious reply to unknown "
- "driver %d\n", c->name, context);
- return -EIO;
- }
+ spin_lock_irqsave(&i2o_drivers_lock, flags);
+ drv = i2o_drivers[context];
+ spin_unlock_irqrestore(&i2o_drivers_lock, flags);
- if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) {
- struct i2o_device *dev, *tmp;
- struct i2o_event *evt;
- u16 size;
- u16 tid;
+ if (unlikely(!drv)) {
+ osm_warn("%s: Spurious reply to unknown driver %d\n", c->name,
+ context);
+ return -EIO;
+ }
- tid = readl(&msg->u.head[1]) & 0x1fff;
+ if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) {
+ struct i2o_device *dev, *tmp;
+ struct i2o_event *evt;
+ u16 size;
+ u16 tid = le32_to_cpu(msg->u.head[1]) & 0xfff;
- pr_debug("%s: event received from device %d\n", c->name,
- tid);
+ osm_debug("event received from device %d\n", tid);
- /* cut of header from message size (in 32-bit words) */
- size = (readl(&msg->u.head[0]) >> 16) - 5;
+ if (!drv->event)
+ return -EIO;
- evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC);
- if (!evt)
- return -ENOMEM;
- memset(evt, 0, size * 4 + sizeof(*evt));
+ /* cut of header from message size (in 32-bit words) */
+ size = (le32_to_cpu(msg->u.head[0]) >> 16) - 5;
- evt->size = size;
- memcpy_fromio(&evt->tcntxt, &msg->u.s.tcntxt,
- (size + 2) * 4);
+ evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC | __GFP_ZERO);
+ if (!evt)
+ return -ENOMEM;
- list_for_each_entry_safe(dev, tmp, &c->devices, list)
- if (dev->lct_data.tid == tid) {
- evt->i2o_dev = dev;
- break;
- }
+ evt->size = size;
+ evt->tcntxt = le32_to_cpu(msg->u.s.tcntxt);
+ evt->event_indicator = le32_to_cpu(msg->body[0]);
+ memcpy(&evt->tcntxt, &msg->u.s.tcntxt, size * 4);
- INIT_WORK(&evt->work, (void (*)(void *))drv->event,
- evt);
- queue_work(drv->event_queue, &evt->work);
- return 1;
+ list_for_each_entry_safe(dev, tmp, &c->devices, list)
+ if (dev->lct_data.tid == tid) {
+ evt->i2o_dev = dev;
+ break;
}
- if (likely(drv->reply))
- return drv->reply(c, m, msg);
- else
- pr_debug("%s: Reply to driver %s, but no reply function"
- " defined!\n", c->name, drv->name);
+ INIT_WORK(&evt->work, (void (*)(void *))drv->event, evt);
+ queue_work(drv->event_queue, &evt->work);
+ return 1;
+ }
+
+ if (unlikely(!drv->reply)) {
+ osm_debug("%s: Reply to driver %s, but no reply function"
+ " defined!\n", c->name, drv->name);
return -EIO;
- } else
- printk(KERN_WARNING "%s: Spurious reply to unknown driver "
- "%d\n", c->name, readl(&msg->u.s.icntxt));
- return -EIO;
+ }
+
+ return drv->reply(c, m, msg);
}
/**
@@ -334,11 +336,11 @@ int __init i2o_driver_init(void)
if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64) ||
((i2o_max_drivers ^ (i2o_max_drivers - 1)) !=
(2 * i2o_max_drivers - 1))) {
- printk(KERN_WARNING "i2o: max_drivers set to %d, but must be "
- ">=2 and <= 64 and a power of 2\n", i2o_max_drivers);
+ osm_warn("max_drivers set to %d, but must be >=2 and <= 64 and "
+ "a power of 2\n", i2o_max_drivers);
i2o_max_drivers = I2O_MAX_DRIVERS;
}
- printk(KERN_INFO "i2o: max drivers = %d\n", i2o_max_drivers);
+ osm_info("max drivers = %d\n", i2o_max_drivers);
i2o_drivers =
kmalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL);
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c
index 79c1cbfb8f4..bda2c62648b 100644
--- a/drivers/message/i2o/exec-osm.c
+++ b/drivers/message/i2o/exec-osm.c
@@ -30,6 +30,7 @@
#include <linux/module.h>
#include <linux/i2o.h>
#include <linux/delay.h>
+#include "core.h"
#define OSM_NAME "exec-osm"
@@ -37,9 +38,6 @@ struct i2o_driver i2o_exec_driver;
static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind);
-/* Module internal functions from other sources */
-extern int i2o_device_parse_lct(struct i2o_controller *);
-
/* global wait list for POST WAIT */
static LIST_HEAD(i2o_exec_wait_list);
@@ -50,7 +48,7 @@ struct i2o_exec_wait {
u32 tcntxt; /* transaction context from reply */
int complete; /* 1 if reply received otherwise 0 */
u32 m; /* message id */
- struct i2o_message __iomem *msg; /* pointer to the reply message */
+ struct i2o_message *msg; /* pointer to the reply message */
struct list_head list; /* node in global wait list */
};
@@ -108,7 +106,8 @@ static void i2o_exec_wait_free(struct i2o_exec_wait *wait)
* buffer must not be freed. Instead the event completion will free them
* for you. In all other cases the buffer are your problem.
*
- * Returns 0 on success or negative error code on failure.
+ * Returns 0 on success, negative error code on timeout or positive error
+ * code from reply.
*/
int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
timeout, struct i2o_dma *dma)
@@ -116,7 +115,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
DECLARE_WAIT_QUEUE_HEAD(wq);
struct i2o_exec_wait *wait;
static u32 tcntxt = 0x80000000;
- struct i2o_message __iomem *msg = c->in_queue.virt + m;
+ struct i2o_message __iomem *msg = i2o_msg_in_to_virt(c, m);
int rc = 0;
wait = i2o_exec_wait_alloc();
@@ -153,7 +152,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
list_add(&wait->list, &i2o_exec_wait_list);
wait_event_interruptible_timeout(wq, wait->complete,
- timeout * HZ);
+ timeout * HZ);
wait->wq = NULL;
}
@@ -161,8 +160,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
barrier();
if (wait->complete) {
- if (readl(&wait->msg->body[0]) >> 24)
- rc = readl(&wait->msg->body[0]) & 0xff;
+ rc = le32_to_cpu(wait->msg->body[0]) >> 24;
i2o_flush_reply(c, wait->m);
i2o_exec_wait_free(wait);
} else {
@@ -187,6 +185,7 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
* @c: I2O controller which answers
* @m: message id
* @msg: pointer to the I2O reply message
+ * @context: transaction context of request
*
* This function is called in interrupt context only. If the reply reached
* before the timeout, the i2o_exec_wait struct is filled with the message
@@ -201,16 +200,12 @@ int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
* message must also be given back to the controller.
*/
static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
- struct i2o_message __iomem *msg)
+ struct i2o_message *msg, u32 context)
{
struct i2o_exec_wait *wait, *tmp;
- static spinlock_t lock;
+ unsigned long flags;
+ static spinlock_t lock = SPIN_LOCK_UNLOCKED;
int rc = 1;
- u32 context;
-
- spin_lock_init(&lock);
-
- context = readl(&msg->u.s.tcntxt);
/*
* We need to search through the i2o_exec_wait_list to see if the given
@@ -219,11 +214,13 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
* already expired. Not much we can do about that except log it for
* debug purposes, increase timeout, and recompile.
*/
- spin_lock(&lock);
+ spin_lock_irqsave(&lock, flags);
list_for_each_entry_safe(wait, tmp, &i2o_exec_wait_list, list) {
if (wait->tcntxt == context) {
list_del(&wait->list);
+ spin_unlock_irqrestore(&lock, flags);
+
wait->m = m;
wait->msg = msg;
wait->complete = 1;
@@ -245,21 +242,63 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
rc = -1;
}
- spin_unlock(&lock);
-
return rc;
}
}
- spin_unlock(&lock);
+ spin_unlock_irqrestore(&lock, flags);
- pr_debug("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name,
+ osm_warn("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name,
context);
return -1;
};
/**
+ * i2o_exec_show_vendor_id - Displays Vendor ID of controller
+ * @d: device of which the Vendor ID should be displayed
+ * @buf: buffer into which the Vendor ID should be printed
+ *
+ * Returns number of bytes printed into buffer.
+ */
+static ssize_t i2o_exec_show_vendor_id(struct device *d, struct device_attribute *attr, char *buf)
+{
+ struct i2o_device *dev = to_i2o_device(d);
+ u16 id;
+
+ if (i2o_parm_field_get(dev, 0x0000, 0, &id, 2)) {
+ sprintf(buf, "0x%04x", id);
+ return strlen(buf) + 1;
+ }
+
+ return 0;
+};
+
+/**
+ * i2o_exec_show_product_id - Displays Product ID of controller
+ * @d: device of which the Product ID should be displayed
+ * @buf: buffer into which the Product ID should be printed
+ *
+ * Returns number of bytes printed into buffer.
+ */
+static ssize_t i2o_exec_show_product_id(struct device *d, struct device_attribute *attr, char *buf)
+{
+ struct i2o_device *dev = to_i2o_device(d);
+ u16 id;
+
+ if (i2o_parm_field_get(dev, 0x0000, 1, &id, 2)) {
+ sprintf(buf, "0x%04x", id);
+ return strlen(buf) + 1;
+ }
+
+ return 0;
+};
+
+/* Exec-OSM device attributes */
+static DEVICE_ATTR(vendor_id, S_IRUGO, i2o_exec_show_vendor_id, NULL);
+static DEVICE_ATTR(product_id, S_IRUGO, i2o_exec_show_product_id, NULL);
+
+/**
* i2o_exec_probe - Called if a new I2O device (executive class) appears
* @dev: I2O device which should be probed
*
@@ -271,10 +310,16 @@ static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
static int i2o_exec_probe(struct device *dev)
{
struct i2o_device *i2o_dev = to_i2o_device(dev);
+ struct i2o_controller *c = i2o_dev->iop;
i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff);
- i2o_dev->iop->exec = i2o_dev;
+ c->exec = i2o_dev;
+
+ i2o_exec_lct_notify(c, c->lct->change_ind + 1);
+
+ device_create_file(dev, &dev_attr_vendor_id);
+ device_create_file(dev, &dev_attr_product_id);
return 0;
};
@@ -289,6 +334,9 @@ static int i2o_exec_probe(struct device *dev)
*/
static int i2o_exec_remove(struct device *dev)
{
+ device_remove_file(dev, &dev_attr_product_id);
+ device_remove_file(dev, &dev_attr_vendor_id);
+
i2o_event_register(to_i2o_device(dev), &i2o_exec_driver, 0, 0);
return 0;
@@ -300,12 +348,16 @@ static int i2o_exec_remove(struct device *dev)
*
* This function handles asynchronus LCT NOTIFY replies. It parses the
* new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY
- * again.
+ * again, otherwise send LCT NOTIFY to get informed on next LCT change.
*/
static void i2o_exec_lct_modified(struct i2o_controller *c)
{
- if (i2o_device_parse_lct(c) == -EAGAIN)
- i2o_exec_lct_notify(c, 0);
+ u32 change_ind = 0;
+
+ if (i2o_device_parse_lct(c) != -EAGAIN)
+ change_ind = c->lct->change_ind + 1;
+
+ i2o_exec_lct_notify(c, change_ind);
};
/**
@@ -325,8 +377,14 @@ static void i2o_exec_lct_modified(struct i2o_controller *c)
static int i2o_exec_reply(struct i2o_controller *c, u32 m,
struct i2o_message *msg)
{
- if (le32_to_cpu(msg->u.head[0]) & MSG_FAIL) { // Fail bit is set
- struct i2o_message __iomem *pmsg; /* preserved message */
+ u32 context;
+
+ if (le32_to_cpu(msg->u.head[0]) & MSG_FAIL) {
+ /*
+ * If Fail bit is set we must take the transaction context of
+ * the preserved message to find the right request again.
+ */
+ struct i2o_message __iomem *pmsg;
u32 pm;
pm = le32_to_cpu(msg->body[3]);
@@ -335,15 +393,15 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m,
i2o_report_status(KERN_INFO, "i2o_core", msg);
- /* Release the preserved msg by resubmitting it as a NOP */
- i2o_msg_nop(c, pm);
+ context = readl(&pmsg->u.s.tcntxt);
- /* If reply to i2o_post_wait failed, return causes a timeout */
- return -1;
- }
+ /* Release the preserved msg */
+ i2o_msg_nop(c, pm);
+ } else
+ context = le32_to_cpu(msg->u.s.tcntxt);
- if (le32_to_cpu(msg->u.s.tcntxt) & 0x80000000)
- return i2o_msg_post_wait_complete(c, m, msg);
+ if (context & 0x80000000)
+ return i2o_msg_post_wait_complete(c, m, msg, context);
if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) {
struct work_struct *work;
@@ -381,8 +439,9 @@ static int i2o_exec_reply(struct i2o_controller *c, u32 m,
*/
static void i2o_exec_event(struct i2o_event *evt)
{
- osm_info("Event received from device: %d\n",
- evt->i2o_dev->lct_data.tid);
+ if (likely(evt->i2o_dev))
+ osm_debug("Event received from device: %d\n",
+ evt->i2o_dev->lct_data.tid);
kfree(evt);
};
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index 7b74c87b569..f283b5bafdd 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -62,7 +62,7 @@
#include "i2o_block.h"
#define OSM_NAME "block-osm"
-#define OSM_VERSION "$Rev$"
+#define OSM_VERSION "1.287"
#define OSM_DESCRIPTION "I2O Block Device OSM"
static struct i2o_driver i2o_block_driver;
@@ -104,7 +104,8 @@ static int i2o_block_remove(struct device *dev)
struct i2o_device *i2o_dev = to_i2o_device(dev);
struct i2o_block_device *i2o_blk_dev = dev_get_drvdata(dev);
- osm_info("Device removed %s\n", i2o_blk_dev->gd->disk_name);
+ osm_info("device removed (TID: %03x): %s\n", i2o_dev->lct_data.tid,
+ i2o_blk_dev->gd->disk_name);
i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0);
@@ -146,6 +147,29 @@ static int i2o_block_device_flush(struct i2o_device *dev)
};
/**
+ * i2o_block_issue_flush - device-flush interface for block-layer
+ * @queue: the request queue of the device which should be flushed
+ * @disk: gendisk
+ * @error_sector: error offset
+ *
+ * Helper function to provide flush functionality to block-layer.
+ *
+ * Returns 0 on success or negative error code on failure.
+ */
+
+static int i2o_block_issue_flush(request_queue_t * queue, struct gendisk *disk,
+ sector_t * error_sector)
+{
+ struct i2o_block_device *i2o_blk_dev = queue->queuedata;
+ int rc = -ENODEV;
+
+ if (likely(i2o_blk_dev))
+ rc = i2o_block_device_flush(i2o_blk_dev->i2o_dev);
+
+ return rc;
+}
+
+/**
* i2o_block_device_mount - Mount (load) the media of device dev
* @dev: I2O device which should receive the mount request
* @media_id: Media Identifier
@@ -298,28 +322,31 @@ static inline void i2o_block_request_free(struct i2o_block_request *ireq)
/**
* i2o_block_sglist_alloc - Allocate the SG list and map it
+ * @c: I2O controller to which the request belongs
* @ireq: I2O block request
*
- * Builds the SG list and map it into to be accessable by the controller.
+ * Builds the SG list and map it to be accessable by the controller.
*
- * Returns the number of elements in the SG list or 0 on failure.
+ * Returns 0 on failure or 1 on success.
*/
-static inline int i2o_block_sglist_alloc(struct i2o_block_request *ireq)
+static inline int i2o_block_sglist_alloc(struct i2o_controller *c,
+ struct i2o_block_request *ireq,
+ u32 __iomem ** mptr)
{
- struct device *dev = &ireq->i2o_blk_dev->i2o_dev->iop->pdev->dev;
int nents;
+ enum dma_data_direction direction;
+ ireq->dev = &c->pdev->dev;
nents = blk_rq_map_sg(ireq->req->q, ireq->req, ireq->sg_table);
if (rq_data_dir(ireq->req) == READ)
- ireq->sg_dma_direction = PCI_DMA_FROMDEVICE;
+ direction = PCI_DMA_FROMDEVICE;
else
- ireq->sg_dma_direction = PCI_DMA_TODEVICE;
+ direction = PCI_DMA_TODEVICE;
- ireq->sg_nents = dma_map_sg(dev, ireq->sg_table, nents,
- ireq->sg_dma_direction);
+ ireq->sg_nents = nents;
- return ireq->sg_nents;
+ return i2o_dma_map_sg(c, ireq->sg_table, nents, direction, mptr);
};
/**
@@ -330,10 +357,14 @@ static inline int i2o_block_sglist_alloc(struct i2o_block_request *ireq)
*/
static inline void i2o_block_sglist_free(struct i2o_block_request *ireq)
{
- struct device *dev = &ireq->i2o_blk_dev->i2o_dev->iop->pdev->dev;
+ enum dma_data_direction direction;
- dma_unmap_sg(dev, ireq->sg_table, ireq->sg_nents,
- ireq->sg_dma_direction);
+ if (rq_data_dir(ireq->req) == READ)
+ direction = PCI_DMA_FROMDEVICE;
+ else
+ direction = PCI_DMA_TODEVICE;
+
+ dma_unmap_sg(ireq->dev, ireq->sg_table, ireq->sg_nents, direction);
};
/**
@@ -351,6 +382,11 @@ static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req)
struct i2o_block_device *i2o_blk_dev = q->queuedata;
struct i2o_block_request *ireq;
+ if (unlikely(!i2o_blk_dev)) {
+ osm_err("block device already removed\n");
+ return BLKPREP_KILL;
+ }
+
/* request is already processed by us, so return */
if (req->flags & REQ_SPECIAL) {
osm_debug("REQ_SPECIAL already set!\n");
@@ -400,71 +436,65 @@ static void i2o_block_delayed_request_fn(void *delayed_request)
};
/**
- * i2o_block_reply - Block OSM reply handler.
- * @c: I2O controller from which the message arrives
- * @m: message id of reply
- * qmsg: the actuall I2O message reply
+ * i2o_block_end_request - Post-processing of completed commands
+ * @req: request which should be completed
+ * @uptodate: 1 for success, 0 for I/O error, < 0 for specific error
+ * @nr_bytes: number of bytes to complete
*
- * This function gets all the message replies.
+ * Mark the request as complete. The lock must not be held when entering.
*
*/
-static int i2o_block_reply(struct i2o_controller *c, u32 m,
- struct i2o_message *msg)
+static void i2o_block_end_request(struct request *req, int uptodate,
+ int nr_bytes)
{
- struct i2o_block_request *ireq;
- struct request *req;
- struct i2o_block_device *dev;
- struct request_queue *q;
- u8 st;
+ struct i2o_block_request *ireq = req->special;
+ struct i2o_block_device *dev = ireq->i2o_blk_dev;
+ request_queue_t *q = req->q;
unsigned long flags;
- /* FAILed message */
- if (unlikely(le32_to_cpu(msg->u.head[0]) & (1 << 13))) {
- struct i2o_message *pmsg;
- u32 pm;
+ if (end_that_request_chunk(req, uptodate, nr_bytes)) {
+ int leftover = (req->hard_nr_sectors << KERNEL_SECTOR_SHIFT);
- /*
- * FAILed message from controller
- * We increment the error count and abort it
- *
- * In theory this will never happen. The I2O block class
- * specification states that block devices never return
- * FAILs but instead use the REQ status field...but
- * better be on the safe side since no one really follows
- * the spec to the book :)
- */
- pm = le32_to_cpu(msg->body[3]);
- pmsg = i2o_msg_in_to_virt(c, pm);
+ if (blk_pc_request(req))
+ leftover = req->data_len;
- req = i2o_cntxt_list_get(c, le32_to_cpu(pmsg->u.s.tcntxt));
- if (unlikely(!req)) {
- osm_err("NULL reply received!\n");
- return -1;
- }
+ if (end_io_error(uptodate))
+ end_that_request_chunk(req, 0, leftover);
+ }
- ireq = req->special;
- dev = ireq->i2o_blk_dev;
- q = dev->gd->queue;
+ add_disk_randomness(req->rq_disk);
- req->errors++;
-
- spin_lock_irqsave(q->queue_lock, flags);
+ spin_lock_irqsave(q->queue_lock, flags);
- while (end_that_request_chunk(req, !req->errors,
- le32_to_cpu(pmsg->body[1]))) ;
- end_that_request_last(req);
+ end_that_request_last(req);
+ if (likely(dev)) {
dev->open_queue_depth--;
list_del(&ireq->queue);
- blk_start_queue(q);
+ }
- spin_unlock_irqrestore(q->queue_lock, flags);
+ blk_start_queue(q);
- /* Now flush the message by making it a NOP */
- i2o_msg_nop(c, pm);
+ spin_unlock_irqrestore(q->queue_lock, flags);
- return -1;
- }
+ i2o_block_sglist_free(ireq);
+ i2o_block_request_free(ireq);
+};
+
+/**
+ * i2o_block_reply - Block OSM reply handler.
+ * @c: I2O controller from which the message arrives
+ * @m: message id of reply
+ * qmsg: the actuall I2O message reply
+ *
+ * This function gets all the message replies.
+ *
+ */
+static int i2o_block_reply(struct i2o_controller *c, u32 m,
+ struct i2o_message *msg)
+{
+ struct request *req;
+ int uptodate = 1;
req = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt));
if (unlikely(!req)) {
@@ -472,61 +502,13 @@ static int i2o_block_reply(struct i2o_controller *c, u32 m,
return -1;
}
- ireq = req->special;
- dev = ireq->i2o_blk_dev;
- q = dev->gd->queue;
-
- if (unlikely(!dev->i2o_dev)) {
- /*
- * This is HACK, but Intel Integrated RAID allows user
- * to delete a volume that is claimed, locked, and in use
- * by the OS. We have to check for a reply from a
- * non-existent device and flag it as an error or the system
- * goes kaput...
- */
- req->errors++;
- osm_warn("Data transfer to deleted device!\n");
- spin_lock_irqsave(q->queue_lock, flags);
- while (end_that_request_chunk
- (req, !req->errors, le32_to_cpu(msg->body[1]))) ;
- end_that_request_last(req);
-
- dev->open_queue_depth--;
- list_del(&ireq->queue);
- blk_start_queue(q);
-
- spin_unlock_irqrestore(q->queue_lock, flags);
- return -1;
- }
-
/*
* Lets see what is cooking. We stuffed the
* request in the context.
*/
- st = le32_to_cpu(msg->body[0]) >> 24;
-
- if (st != 0) {
- int err;
- char *bsa_errors[] = {
- "Success",
- "Media Error",
- "Failure communicating to device",
- "Device Failure",
- "Device is not ready",
- "Media not present",
- "Media is locked by another user",
- "Media has failed",
- "Failure communicating to device",
- "Device bus failure",
- "Device is locked by another user",
- "Device is write protected",
- "Device has reset",
- "Volume has changed, waiting for acknowledgement"
- };
-
- err = le32_to_cpu(msg->body[0]) & 0xffff;
-
+ if ((le32_to_cpu(msg->body[0]) >> 24) != 0) {
+ u32 status = le32_to_cpu(msg->body[0]);
/*
* Device not ready means two things. One is that the
* the thing went offline (but not a removal media)
@@ -539,40 +521,24 @@ static int i2o_block_reply(struct i2o_controller *c, u32 m,
* Don't stick a supertrak100 into cache aggressive modes
*/
- osm_err("block-osm: /dev/%s error: %s", dev->gd->disk_name,
- bsa_errors[le32_to_cpu(msg->body[0]) & 0xffff]);
- if (le32_to_cpu(msg->body[0]) & 0x00ff0000)
- printk(KERN_ERR " - DDM attempted %d retries",
- (le32_to_cpu(msg->body[0]) >> 16) & 0x00ff);
- printk(KERN_ERR ".\n");
- req->errors++;
- } else
- req->errors = 0;
+ osm_err("TID %03x error status: 0x%02x, detailed status: "
+ "0x%04x\n", (le32_to_cpu(msg->u.head[1]) >> 12 & 0xfff),
+ status >> 24, status & 0xffff);
- if (!end_that_request_chunk
- (req, !req->errors, le32_to_cpu(msg->body[1]))) {
- add_disk_randomness(req->rq_disk);
- spin_lock_irqsave(q->queue_lock, flags);
-
- end_that_request_last(req);
+ req->errors++;
- dev->open_queue_depth--;
- list_del(&ireq->queue);
- blk_start_queue(q);
+ uptodate = 0;
+ }
- spin_unlock_irqrestore(q->queue_lock, flags);
-
- i2o_block_sglist_free(ireq);
- i2o_block_request_free(ireq);
- } else
- osm_err("still remaining chunks\n");
+ i2o_block_end_request(req, uptodate, le32_to_cpu(msg->body[1]));
return 1;
};
static void i2o_block_event(struct i2o_event *evt)
{
- osm_info("block-osm: event received\n");
+ osm_debug("event received\n");
+ kfree(evt);
};
/*
@@ -777,18 +743,25 @@ static int i2o_block_media_changed(struct gendisk *disk)
static int i2o_block_transfer(struct request *req)
{
struct i2o_block_device *dev = req->rq_disk->private_data;
- struct i2o_controller *c = dev->i2o_dev->iop;
+ struct i2o_controller *c;
int tid = dev->i2o_dev->lct_data.tid;
struct i2o_message __iomem *msg;
- void __iomem *mptr;
+ u32 __iomem *mptr;
struct i2o_block_request *ireq = req->special;
- struct scatterlist *sg;
- int sgnum;
- int i;
u32 m;
u32 tcntxt;
- u32 sg_flags;
+ u32 sgl_offset = SGL_OFFSET_8;
+ u32 ctl_flags = 0x00000000;
int rc;
+ u32 cmd;
+
+ if (unlikely(!dev->i2o_dev)) {
+ osm_err("transfer to removed drive\n");
+ rc = -ENODEV;
+ goto exit;
+ }
+
+ c = dev->i2o_dev->iop;
m = i2o_msg_get(c, &msg);
if (m == I2O_QUEUE_EMPTY) {
@@ -802,82 +775,109 @@ static int i2o_block_transfer(struct request *req)
goto nop_msg;
}
- if ((sgnum = i2o_block_sglist_alloc(ireq)) <= 0) {
- rc = -ENOMEM;
- goto context_remove;
- }
-
- /* Build the message based on the request. */
writel(i2o_block_driver.context, &msg->u.s.icntxt);
writel(tcntxt, &msg->u.s.tcntxt);
- writel(req->nr_sectors << 9, &msg->body[1]);
-
- writel((((u64) req->sector) << 9) & 0xffffffff, &msg->body[2]);
- writel(req->sector >> 23, &msg->body[3]);
- mptr = &msg->body[4];
-
- sg = ireq->sg_table;
+ mptr = &msg->body[0];
if (rq_data_dir(req) == READ) {
- writel(I2O_CMD_BLOCK_READ << 24 | HOST_TID << 12 | tid,
- &msg->u.head[1]);
- sg_flags = 0x10000000;
+ cmd = I2O_CMD_BLOCK_READ << 24;
+
switch (dev->rcache) {
- case CACHE_NULL:
- writel(0, &msg->body[0]);
- break;
case CACHE_PREFETCH:
- writel(0x201F0008, &msg->body[0]);
+ ctl_flags = 0x201F0008;
break;
+
case CACHE_SMARTFETCH:
if (req->nr_sectors > 16)
- writel(0x201F0008, &msg->body[0]);
+ ctl_flags = 0x201F0008;
else
- writel(0x001F0000, &msg->body[0]);
+ ctl_flags = 0x001F0000;
+ break;
+
+ default:
break;
}
} else {
- writel(I2O_CMD_BLOCK_WRITE << 24 | HOST_TID << 12 | tid,
- &msg->u.head[1]);
- sg_flags = 0x14000000;
+ cmd = I2O_CMD_BLOCK_WRITE << 24;
+
switch (dev->wcache) {
- case CACHE_NULL:
- writel(0, &msg->body[0]);
- break;
case CACHE_WRITETHROUGH:
- writel(0x001F0008, &msg->body[0]);
+ ctl_flags = 0x001F0008;
break;
case CACHE_WRITEBACK:
- writel(0x001F0010, &msg->body[0]);
+ ctl_flags = 0x001F0010;
break;
case CACHE_SMARTBACK:
if (req->nr_sectors > 16)
- writel(0x001F0004, &msg->body[0]);
+ ctl_flags = 0x001F0004;
else
- writel(0x001F0010, &msg->body[0]);
+ ctl_flags = 0x001F0010;
break;
case CACHE_SMARTTHROUGH:
if (req->nr_sectors > 16)
- writel(0x001F0004, &msg->body[0]);
+ ctl_flags = 0x001F0004;
else
- writel(0x001F0010, &msg->body[0]);
+ ctl_flags = 0x001F0010;
+ default:
+ break;
+ }
+ }
+
+#ifdef CONFIG_I2O_EXT_ADAPTEC
+ if (c->adaptec) {
+ u8 cmd[10];
+ u32 scsi_flags;
+ u16 hwsec = queue_hardsect_size(req->q) >> KERNEL_SECTOR_SHIFT;
+
+ memset(cmd, 0, 10);
+
+ sgl_offset = SGL_OFFSET_12;
+
+ writel(I2O_CMD_PRIVATE << 24 | HOST_TID << 12 | tid,
+ &msg->u.head[1]);
+
+ writel(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC, mptr++);
+ writel(tid, mptr++);
+
+ /*
+ * ENABLE_DISCONNECT
+ * SIMPLE_TAG
+ * RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME
+ */
+ if (rq_data_dir(req) == READ) {
+ cmd[0] = 0x28;
+ scsi_flags = 0x60a0000a;
+ } else {
+ cmd[0] = 0x2A;
+ scsi_flags = 0xa0a0000a;
}
+
+ writel(scsi_flags, mptr++);
+
+ *((u32 *) & cmd[2]) = cpu_to_be32(req->sector * hwsec);
+ *((u16 *) & cmd[7]) = cpu_to_be16(req->nr_sectors * hwsec);
+
+ memcpy_toio(mptr, cmd, 10);
+ mptr += 4;
+ writel(req->nr_sectors << KERNEL_SECTOR_SHIFT, mptr++);
+ } else
+#endif
+ {
+ writel(cmd | HOST_TID << 12 | tid, &msg->u.head[1]);
+ writel(ctl_flags, mptr++);
+ writel(req->nr_sectors << KERNEL_SECTOR_SHIFT, mptr++);
+ writel((u32) (req->sector << KERNEL_SECTOR_SHIFT), mptr++);
+ writel(req->sector >> (32 - KERNEL_SECTOR_SHIFT), mptr++);
}
- for (i = sgnum; i > 0; i--) {
- if (i == 1)
- sg_flags |= 0x80000000;
- writel(sg_flags | sg_dma_len(sg), mptr);
- writel(sg_dma_address(sg), mptr + 4);
- mptr += 8;
- sg++;
+ if (!i2o_block_sglist_alloc(c, ireq, &mptr)) {
+ rc = -ENOMEM;
+ goto context_remove;
}
- writel(I2O_MESSAGE_SIZE
- (((unsigned long)mptr -
- (unsigned long)&msg->u.head[0]) >> 2) | SGL_OFFSET_8,
- &msg->u.head[0]);
+ writel(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) |
+ sgl_offset, &msg->u.head[0]);
list_add_tail(&ireq->queue, &dev->open_queue);
dev->open_queue_depth++;
@@ -920,11 +920,13 @@ static void i2o_block_request_fn(struct request_queue *q)
queue_depth = ireq->i2o_blk_dev->open_queue_depth;
- if (queue_depth < I2O_BLOCK_MAX_OPEN_REQUESTS)
+ if (queue_depth < I2O_BLOCK_MAX_OPEN_REQUESTS) {
if (!i2o_block_transfer(req)) {
blkdev_dequeue_request(req);
continue;
- }
+ } else
+ osm_info("transfer error\n");
+ }
if (queue_depth)
break;
@@ -938,7 +940,6 @@ static void i2o_block_request_fn(struct request_queue *q)
INIT_WORK(&dreq->work, i2o_block_delayed_request_fn,
dreq);
- osm_info("transfer error\n");
if (!queue_delayed_work(i2o_block_driver.event_queue,
&dreq->work,
I2O_BLOCK_RETRY_TIME))
@@ -1007,6 +1008,7 @@ static struct i2o_block_device *i2o_block_device_alloc(void)
}
blk_queue_prep_rq(queue, i2o_block_prep_req_fn);
+ blk_queue_issue_flush_fn(queue, i2o_block_issue_flush);
gd->major = I2O_MAJOR;
gd->queue = queue;
@@ -1039,17 +1041,27 @@ static struct i2o_block_device *i2o_block_device_alloc(void)
static int i2o_block_probe(struct device *dev)
{
struct i2o_device *i2o_dev = to_i2o_device(dev);
- struct i2o_block_device *i2o_blk_dev;
struct i2o_controller *c = i2o_dev->iop;
+ struct i2o_block_device *i2o_blk_dev;
struct gendisk *gd;
struct request_queue *queue;
static int unit = 0;
int rc;
u64 size;
u32 blocksize;
- u16 power;
u32 flags, status;
- int segments;
+ u16 body_size = 4;
+ unsigned short max_sectors;
+
+#ifdef CONFIG_I2O_EXT_ADAPTEC
+ if (c->adaptec)
+ body_size = 8;
+#endif
+
+ if (c->limit_sectors)
+ max_sectors = I2O_MAX_SECTORS_LIMITED;
+ else
+ max_sectors = I2O_MAX_SECTORS;
/* skip devices which are used by IOP */
if (i2o_dev->lct_data.user_tid != 0xfff) {
@@ -1057,8 +1069,6 @@ static int i2o_block_probe(struct device *dev)
return -ENODEV;
}
- osm_info("New device detected (TID: %03x)\n", i2o_dev->lct_data.tid);
-
if (i2o_device_claim(i2o_dev)) {
osm_warn("Unable to claim device. Installation aborted\n");
rc = -EFAULT;
@@ -1086,50 +1096,44 @@ static int i2o_block_probe(struct device *dev)
queue = gd->queue;
queue->queuedata = i2o_blk_dev;
- blk_queue_max_phys_segments(queue, I2O_MAX_SEGMENTS);
- blk_queue_max_sectors(queue, I2O_MAX_SECTORS);
-
- if (c->short_req)
- segments = 8;
- else {
- i2o_status_block *sb;
+ blk_queue_max_phys_segments(queue, I2O_MAX_PHYS_SEGMENTS);
+ blk_queue_max_sectors(queue, max_sectors);
+ blk_queue_max_hw_segments(queue, i2o_sg_tablesize(c, body_size));
- sb = c->status_block.virt;
-
- segments = (sb->inbound_frame_size -
- sizeof(struct i2o_message) / 4 - 4) / 2;
- }
-
- blk_queue_max_hw_segments(queue, segments);
-
- osm_debug("max sectors = %d\n", I2O_MAX_SECTORS);
- osm_debug("phys segments = %d\n", I2O_MAX_SEGMENTS);
- osm_debug("hw segments = %d\n", segments);
+ osm_debug("max sectors = %d\n", queue->max_phys_segments);
+ osm_debug("phys segments = %d\n", queue->max_sectors);
+ osm_debug("max hw segments = %d\n", queue->max_hw_segments);
/*
* Ask for the current media data. If that isn't supported
* then we ask for the device capacity data
*/
- if (i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) != 0
- || i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) != 0) {
- i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4);
- i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8);
- }
- osm_debug("blocksize = %d\n", blocksize);
+ if (i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) ||
+ i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4)) {
+ blk_queue_hardsect_size(queue, blocksize);
+ } else
+ osm_warn("unable to get blocksize of %s\n", gd->disk_name);
- if (i2o_parm_field_get(i2o_dev, 0x0000, 2, &power, 2))
- power = 0;
+ if (i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) ||
+ i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8)) {
+ set_capacity(gd, size >> KERNEL_SECTOR_SHIFT);
+ } else
+ osm_warn("could not get size of %s\n", gd->disk_name);
+
+ if (!i2o_parm_field_get(i2o_dev, 0x0000, 2, &i2o_blk_dev->power, 2))
+ i2o_blk_dev->power = 0;
i2o_parm_field_get(i2o_dev, 0x0000, 5, &flags, 4);
i2o_parm_field_get(i2o_dev, 0x0000, 6, &status, 4);
- set_capacity(gd, size >> 9);
-
i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0xffffffff);
add_disk(gd);
unit++;
+ osm_info("device added (TID: %03x): %s\n", i2o_dev->lct_data.tid,
+ i2o_blk_dev->gd->disk_name);
+
return 0;
claim_release:
@@ -1177,7 +1181,7 @@ static int __init i2o_block_init(void)
goto exit;
}
- i2o_blk_req_pool.pool = mempool_create(I2O_REQ_MEMPOOL_SIZE,
+ i2o_blk_req_pool.pool = mempool_create(I2O_BLOCK_REQ_MEMPOOL_SIZE,
mempool_alloc_slab,
mempool_free_slab,
i2o_blk_req_pool.slab);
diff --git a/drivers/message/i2o/i2o_block.h b/drivers/message/i2o/i2o_block.h
index ddd9a15679c..4fdaa5bda41 100644
--- a/drivers/message/i2o/i2o_block.h
+++ b/drivers/message/i2o/i2o_block.h
@@ -56,42 +56,46 @@
#define I2O_BLOCK_RETRY_TIME HZ/4
#define I2O_BLOCK_MAX_OPEN_REQUESTS 50
+/* request queue sizes */
+#define I2O_BLOCK_REQ_MEMPOOL_SIZE 32
+
+#define KERNEL_SECTOR_SHIFT 9
+#define KERNEL_SECTOR_SIZE (1 << KERNEL_SECTOR_SHIFT)
+
/* I2O Block OSM mempool struct */
struct i2o_block_mempool {
- kmem_cache_t *slab;
- mempool_t *pool;
+ kmem_cache_t *slab;
+ mempool_t *pool;
};
/* I2O Block device descriptor */
struct i2o_block_device {
struct i2o_device *i2o_dev; /* pointer to I2O device */
struct gendisk *gd;
- spinlock_t lock; /* queue lock */
+ spinlock_t lock; /* queue lock */
struct list_head open_queue; /* list of transfered, but unfinished
requests */
unsigned int open_queue_depth; /* number of requests in the queue */
- int rcache; /* read cache flags */
- int wcache; /* write cache flags */
+ int rcache; /* read cache flags */
+ int wcache; /* write cache flags */
int flags;
- int power; /* power state */
- int media_change_flag; /* media changed flag */
+ u16 power; /* power state */
+ int media_change_flag; /* media changed flag */
};
/* I2O Block device request */
-struct i2o_block_request
-{
+struct i2o_block_request {
struct list_head queue;
- struct request *req; /* corresponding request */
+ struct request *req; /* corresponding request */
struct i2o_block_device *i2o_blk_dev; /* I2O block device */
- int sg_dma_direction; /* direction of DMA buffer read/write */
- int sg_nents; /* number of SG elements */
- struct scatterlist sg_table[I2O_MAX_SEGMENTS]; /* SG table */
+ struct device *dev; /* device used for DMA */
+ int sg_nents; /* number of SG elements */
+ struct scatterlist sg_table[I2O_MAX_PHYS_SEGMENTS]; /* SG table */
};
/* I2O Block device delayed request */
-struct i2o_block_delayed_request
-{
+struct i2o_block_delayed_request {
struct work_struct work;
struct request_queue *queue;
};
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index 1fb5cdf67f8..3c3a7abebb1 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -30,29 +30,15 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/i2o.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
#include <linux/miscdevice.h>
-#include <linux/mm.h>
-#include <linux/spinlock.h>
#include <linux/smp_lock.h>
-#include <linux/ioctl32.h>
#include <linux/compat.h>
-#include <linux/syscalls.h>
#include <asm/uaccess.h>
-#include <asm/io.h>
-#define OSM_NAME "config-osm"
-#define OSM_VERSION "$Rev$"
-#define OSM_DESCRIPTION "I2O Configuration OSM"
+#include "core.h"
-extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int);
+#define SG_TABLESIZE 30
static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd,
unsigned long arg);
@@ -80,15 +66,6 @@ struct i2o_cfg_info {
static struct i2o_cfg_info *open_files = NULL;
static ulong i2o_cfg_info_id = 0;
-/*
- * Each of these describes an i2o message handler. They are
- * multiplexed by the i2o_core code
- */
-
-static struct i2o_driver i2o_config_driver = {
- .name = OSM_NAME
-};
-
static int i2o_cfg_getiops(unsigned long arg)
{
struct i2o_controller *c;
@@ -391,9 +368,9 @@ static int i2o_cfg_swul(unsigned long arg)
i2o_dma_free(&c->pdev->dev, &buffer);
-return_ret:
+ return_ret:
return ret;
-return_fault:
+ return_fault:
ret = -EFAULT;
goto return_ret;
};
@@ -540,8 +517,10 @@ static int i2o_cfg_evt_get(unsigned long arg, struct file *fp)
return 0;
}
+#ifdef CONFIG_I2O_EXT_ADAPTEC
#ifdef CONFIG_COMPAT
-static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long arg)
+static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
+ unsigned long arg)
{
struct i2o_cmd_passthru32 __user *cmd;
struct i2o_controller *c;
@@ -555,6 +534,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
u32 sg_offset = 0;
u32 sg_count = 0;
u32 i = 0;
+ u32 sg_index = 0;
i2o_status_block *sb;
struct i2o_message *msg;
u32 m;
@@ -634,8 +614,8 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
if (sg_count > SG_TABLESIZE) {
printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n",
c->name, sg_count);
- kfree(reply);
- return -EINVAL;
+ rcode = -EINVAL;
+ goto cleanup;
}
for (i = 0; i < sg_count; i++) {
@@ -651,7 +631,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
goto cleanup;
}
sg_size = sg[i].flag_count & 0xffffff;
- p = &(sg_list[i]);
+ p = &(sg_list[sg_index++]);
/* Allocate memory for the transfer */
if (i2o_dma_alloc
(&c->pdev->dev, p, sg_size,
@@ -660,20 +640,21 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
"%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
c->name, sg_size, i, sg_count);
rcode = -ENOMEM;
- goto cleanup;
+ goto sg_list_cleanup;
}
/* Copy in the user's SG buffer if necessary */
if (sg[i].
flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) {
// TODO 64bit fix
if (copy_from_user
- (p->virt, (void __user *)(unsigned long)sg[i].addr_bus,
- sg_size)) {
+ (p->virt,
+ (void __user *)(unsigned long)sg[i].
+ addr_bus, sg_size)) {
printk(KERN_DEBUG
"%s: Could not copy SG buf %d FROM user\n",
c->name, i);
rcode = -EFAULT;
- goto cleanup;
+ goto sg_list_cleanup;
}
}
//TODO 64bit fix
@@ -683,10 +664,10 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
rcode = i2o_msg_post_wait(c, m, 60);
if (rcode)
- goto cleanup;
+ goto sg_list_cleanup;
if (sg_offset) {
- u32 msg[128];
+ u32 msg[I2O_OUTBOUND_MSG_FRAME_SIZE];
/* Copy back the Scatter Gather buffers back to user space */
u32 j;
// TODO 64bit fix
@@ -694,18 +675,18 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
int sg_size;
// re-acquire the original message to handle correctly the sg copy operation
- memset(&msg, 0, MSG_FRAME_SIZE * 4);
+ memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);
// get user msg size in u32s
if (get_user(size, &user_msg[0])) {
rcode = -EFAULT;
- goto cleanup;
+ goto sg_list_cleanup;
}
size = size >> 16;
size *= 4;
/* Copy in the user's I2O command */
if (copy_from_user(msg, user_msg, size)) {
rcode = -EFAULT;
- goto cleanup;
+ goto sg_list_cleanup;
}
sg_count =
(size - sg_offset * 4) / sizeof(struct sg_simple_element);
@@ -727,7 +708,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
c->name, sg_list[j].virt,
sg[j].addr_bus);
rcode = -EFAULT;
- goto cleanup;
+ goto sg_list_cleanup;
}
}
}
@@ -741,6 +722,7 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
"%s: Could not copy message context FROM user\n",
c->name);
rcode = -EFAULT;
+ goto sg_list_cleanup;
}
if (copy_to_user(user_reply, reply, reply_size)) {
printk(KERN_WARNING
@@ -749,16 +731,21 @@ static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long ar
}
}
+ sg_list_cleanup:
+ for (i = 0; i < sg_index; i++)
+ i2o_dma_free(&c->pdev->dev, &sg_list[i]);
+
cleanup:
kfree(reply);
return rcode;
}
-static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
+static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd,
+ unsigned long arg)
{
int ret;
- lock_kernel();
- switch (cmd) {
+ lock_kernel();
+ switch (cmd) {
case I2OGETIOPS:
ret = i2o_cfg_ioctl(NULL, file, cmd, arg);
break;
@@ -862,8 +849,8 @@ static int i2o_cfg_passthru(unsigned long arg)
if (sg_count > SG_TABLESIZE) {
printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n",
c->name, sg_count);
- kfree(reply);
- return -EINVAL;
+ rcode = -EINVAL;
+ goto cleanup;
}
for (i = 0; i < sg_count; i++) {
@@ -875,7 +862,7 @@ static int i2o_cfg_passthru(unsigned long arg)
"%s:Bad SG element %d - not simple (%x)\n",
c->name, i, sg[i].flag_count);
rcode = -EINVAL;
- goto cleanup;
+ goto sg_list_cleanup;
}
sg_size = sg[i].flag_count & 0xffffff;
/* Allocate memory for the transfer */
@@ -885,7 +872,7 @@ static int i2o_cfg_passthru(unsigned long arg)
"%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
c->name, sg_size, i, sg_count);
rcode = -ENOMEM;
- goto cleanup;
+ goto sg_list_cleanup;
}
sg_list[sg_index++] = p; // sglist indexed with input frame, not our internal frame.
/* Copy in the user's SG buffer if necessary */
@@ -899,7 +886,7 @@ static int i2o_cfg_passthru(unsigned long arg)
"%s: Could not copy SG buf %d FROM user\n",
c->name, i);
rcode = -EFAULT;
- goto cleanup;
+ goto sg_list_cleanup;
}
}
//TODO 64bit fix
@@ -909,7 +896,7 @@ static int i2o_cfg_passthru(unsigned long arg)
rcode = i2o_msg_post_wait(c, m, 60);
if (rcode)
- goto cleanup;
+ goto sg_list_cleanup;
if (sg_offset) {
u32 msg[128];
@@ -920,18 +907,18 @@ static int i2o_cfg_passthru(unsigned long arg)
int sg_size;
// re-acquire the original message to handle correctly the sg copy operation
- memset(&msg, 0, MSG_FRAME_SIZE * 4);
+ memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);
// get user msg size in u32s
if (get_user(size, &user_msg[0])) {
rcode = -EFAULT;
- goto cleanup;
+ goto sg_list_cleanup;
}
size = size >> 16;
size *= 4;
/* Copy in the user's I2O command */
if (copy_from_user(msg, user_msg, size)) {
rcode = -EFAULT;
- goto cleanup;
+ goto sg_list_cleanup;
}
sg_count =
(size - sg_offset * 4) / sizeof(struct sg_simple_element);
@@ -953,7 +940,7 @@ static int i2o_cfg_passthru(unsigned long arg)
c->name, sg_list[j],
sg[j].addr_bus);
rcode = -EFAULT;
- goto cleanup;
+ goto sg_list_cleanup;
}
}
}
@@ -975,10 +962,15 @@ static int i2o_cfg_passthru(unsigned long arg)
}
}
+ sg_list_cleanup:
+ for (i = 0; i < sg_index; i++)
+ kfree(sg_list[i]);
+
cleanup:
kfree(reply);
return rcode;
}
+#endif
/*
* IOCTL Handler
@@ -1033,9 +1025,11 @@ static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd,
ret = i2o_cfg_evt_get(arg, fp);
break;
+#ifdef CONFIG_I2O_EXT_ADAPTEC
case I2OPASSTHRU:
ret = i2o_cfg_passthru(arg);
break;
+#endif
default:
osm_debug("unknown ioctl called!\n");
@@ -1137,37 +1131,21 @@ static struct miscdevice i2o_miscdev = {
&config_fops
};
-static int __init i2o_config_init(void)
+static int __init i2o_config_old_init(void)
{
- printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n");
-
spin_lock_init(&i2o_config_lock);
if (misc_register(&i2o_miscdev) < 0) {
osm_err("can't register device.\n");
return -EBUSY;
}
- /*
- * Install our handler
- */
- if (i2o_driver_register(&i2o_config_driver)) {
- osm_err("handler register failed.\n");
- misc_deregister(&i2o_miscdev);
- return -EBUSY;
- }
+
return 0;
}
-static void i2o_config_exit(void)
+static void i2o_config_old_exit(void)
{
misc_deregister(&i2o_miscdev);
- i2o_driver_unregister(&i2o_config_driver);
}
MODULE_AUTHOR("Red Hat Software");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION(OSM_DESCRIPTION);
-MODULE_VERSION(OSM_VERSION);
-
-module_init(i2o_config_init);
-module_exit(i2o_config_exit);
diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c
index b176d0eeff7..d559a175836 100644
--- a/drivers/message/i2o/i2o_proc.c
+++ b/drivers/message/i2o/i2o_proc.c
@@ -28,7 +28,7 @@
*/
#define OSM_NAME "proc-osm"
-#define OSM_VERSION "$Rev$"
+#define OSM_VERSION "1.145"
#define OSM_DESCRIPTION "I2O ProcFS OSM"
#define I2O_MAX_MODULES 4
@@ -228,7 +228,7 @@ static const char *i2o_get_class_name(int class)
case I2O_CLASS_FLOPPY_DEVICE:
idx = 12;
break;
- case I2O_CLASS_BUS_ADAPTER_PORT:
+ case I2O_CLASS_BUS_ADAPTER:
idx = 13;
break;
case I2O_CLASS_PEER_TRANSPORT_AGENT:
@@ -490,7 +490,7 @@ static int i2o_seq_show_lct(struct seq_file *seq, void *v)
seq_printf(seq, ", Unknown Device Type");
break;
- case I2O_CLASS_BUS_ADAPTER_PORT:
+ case I2O_CLASS_BUS_ADAPTER:
if (lct->lct_entry[i].sub_class < BUS_TABLE_SIZE)
seq_printf(seq, ", %s",
bus_ports[lct->lct_entry[i].
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
index 43f5875e0be..9f1744c3933 100644
--- a/drivers/message/i2o/i2o_scsi.c
+++ b/drivers/message/i2o/i2o_scsi.c
@@ -54,6 +54,7 @@
#include <linux/pci.h>
#include <linux/blkdev.h>
#include <linux/i2o.h>
+#include <linux/scatterlist.h>
#include <asm/dma.h>
#include <asm/system.h>
@@ -64,19 +65,23 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_request.h>
+#include <scsi/sg.h>
+#include <scsi/sg_request.h>
#define OSM_NAME "scsi-osm"
-#define OSM_VERSION "$Rev$"
+#define OSM_VERSION "1.282"
#define OSM_DESCRIPTION "I2O SCSI Peripheral OSM"
static struct i2o_driver i2o_scsi_driver;
-static int i2o_scsi_max_id = 16;
-static int i2o_scsi_max_lun = 8;
+static unsigned int i2o_scsi_max_id = 16;
+static unsigned int i2o_scsi_max_lun = 255;
struct i2o_scsi_host {
struct Scsi_Host *scsi_host; /* pointer to the SCSI host */
struct i2o_controller *iop; /* pointer to the I2O controller */
+ unsigned int lun; /* lun's used for block devices */
struct i2o_device *channel[0]; /* channel->i2o_dev mapping table */
};
@@ -99,11 +104,17 @@ static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c)
u8 type;
int i;
size_t size;
- i2o_status_block *sb;
+ u16 body_size = 6;
+
+#ifdef CONFIG_I2O_EXT_ADAPTEC
+ if (c->adaptec)
+ body_size = 8;
+#endif
list_for_each_entry(i2o_dev, &c->devices, list)
- if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER_PORT) {
- if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) || (type == 1)) /* SCSI bus */
+ if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) {
+ if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1)
+ && (type == 0x01)) /* SCSI bus */
max_channel++;
}
@@ -125,20 +136,18 @@ static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c)
scsi_host->max_id = i2o_scsi_max_id;
scsi_host->max_lun = i2o_scsi_max_lun;
scsi_host->this_id = c->unit;
-
- sb = c->status_block.virt;
-
- scsi_host->sg_tablesize = (sb->inbound_frame_size -
- sizeof(struct i2o_message) / 4 - 6) / 2;
+ scsi_host->sg_tablesize = i2o_sg_tablesize(c, body_size);
i2o_shost = (struct i2o_scsi_host *)scsi_host->hostdata;
i2o_shost->scsi_host = scsi_host;
i2o_shost->iop = c;
+ i2o_shost->lun = 1;
i = 0;
list_for_each_entry(i2o_dev, &c->devices, list)
- if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER_PORT) {
- if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) || (type == 1)) /* only SCSI bus */
+ if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) {
+ if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1)
+ && (type == 0x01)) /* only SCSI bus */
i2o_shost->channel[i++] = i2o_dev;
if (i >= max_channel)
@@ -178,10 +187,13 @@ static int i2o_scsi_remove(struct device *dev)
struct i2o_scsi_host *i2o_shost;
struct scsi_device *scsi_dev;
+ osm_info("device removed (TID: %03x)\n", i2o_dev->lct_data.tid);
+
i2o_shost = i2o_scsi_get_host(c);
shost_for_each_device(scsi_dev, i2o_shost->scsi_host)
if (scsi_dev->hostdata == i2o_dev) {
+ sysfs_remove_link(&i2o_dev->device.kobj, "scsi");
scsi_remove_device(scsi_dev);
scsi_device_put(scsi_dev);
break;
@@ -207,8 +219,8 @@ static int i2o_scsi_probe(struct device *dev)
struct Scsi_Host *scsi_host;
struct i2o_device *parent;
struct scsi_device *scsi_dev;
- u32 id;
- u64 lun;
+ u32 id = -1;
+ u64 lun = -1;
int channel = -1;
int i;
@@ -218,8 +230,56 @@ static int i2o_scsi_probe(struct device *dev)
scsi_host = i2o_shost->scsi_host;
- if (i2o_parm_field_get(i2o_dev, 0, 3, &id, 4) < 0)
+ switch (i2o_dev->lct_data.class_id) {
+ case I2O_CLASS_RANDOM_BLOCK_STORAGE:
+ case I2O_CLASS_EXECUTIVE:
+#ifdef CONFIG_I2O_EXT_ADAPTEC
+ if (c->adaptec) {
+ u8 type;
+ struct i2o_device *d = i2o_shost->channel[0];
+
+ if (i2o_parm_field_get(d, 0x0000, 0, &type, 1)
+ && (type == 0x01)) /* SCSI bus */
+ if (i2o_parm_field_get(d, 0x0200, 4, &id, 4)) {
+ channel = 0;
+ if (i2o_dev->lct_data.class_id ==
+ I2O_CLASS_RANDOM_BLOCK_STORAGE)
+ lun = i2o_shost->lun++;
+ else
+ lun = 0;
+ }
+ }
+#endif
+ break;
+
+ case I2O_CLASS_SCSI_PERIPHERAL:
+ if (i2o_parm_field_get(i2o_dev, 0x0000, 3, &id, 4) < 0)
+ return -EFAULT;
+
+ if (i2o_parm_field_get(i2o_dev, 0x0000, 4, &lun, 8) < 0)
+ return -EFAULT;
+
+ parent = i2o_iop_find_device(c, i2o_dev->lct_data.parent_tid);
+ if (!parent) {
+ osm_warn("can not find parent of device %03x\n",
+ i2o_dev->lct_data.tid);
+ return -EFAULT;
+ }
+
+ for (i = 0; i <= i2o_shost->scsi_host->max_channel; i++)
+ if (i2o_shost->channel[i] == parent)
+ channel = i;
+ break;
+
+ default:
return -EFAULT;
+ }
+
+ if (channel == -1) {
+ osm_warn("can not find channel of device %03x\n",
+ i2o_dev->lct_data.tid);
+ return -EFAULT;
+ }
if (id >= scsi_host->max_id) {
osm_warn("SCSI device id (%d) >= max_id of I2O host (%d)", id,
@@ -227,42 +287,26 @@ static int i2o_scsi_probe(struct device *dev)
return -EFAULT;
}
- if (i2o_parm_field_get(i2o_dev, 0, 4, &lun, 8) < 0)
- return -EFAULT;
if (lun >= scsi_host->max_lun) {
osm_warn("SCSI device id (%d) >= max_lun of I2O host (%d)",
(unsigned int)lun, scsi_host->max_lun);
return -EFAULT;
}
- parent = i2o_iop_find_device(c, i2o_dev->lct_data.parent_tid);
- if (!parent) {
- osm_warn("can not find parent of device %03x\n",
- i2o_dev->lct_data.tid);
- return -EFAULT;
- }
-
- for (i = 0; i <= i2o_shost->scsi_host->max_channel; i++)
- if (i2o_shost->channel[i] == parent)
- channel = i;
-
- if (channel == -1) {
- osm_warn("can not find channel of device %03x\n",
- i2o_dev->lct_data.tid);
- return -EFAULT;
- }
-
scsi_dev =
__scsi_add_device(i2o_shost->scsi_host, channel, id, lun, i2o_dev);
- if (!scsi_dev) {
+ if (IS_ERR(scsi_dev)) {
osm_warn("can not add SCSI device %03x\n",
i2o_dev->lct_data.tid);
- return -EFAULT;
+ return PTR_ERR(scsi_dev);
}
- osm_debug("added new SCSI device %03x (cannel: %d, id: %d, lun: %d)\n",
- i2o_dev->lct_data.tid, channel, id, (unsigned int)lun);
+ sysfs_create_link(&i2o_dev->device.kobj, &scsi_dev->sdev_gendev.kobj,
+ "scsi");
+
+ osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %d\n",
+ i2o_dev->lct_data.tid, channel, id, (unsigned int)lun);
return 0;
};
@@ -293,162 +337,89 @@ static int i2o_scsi_reply(struct i2o_controller *c, u32 m,
struct i2o_message *msg)
{
struct scsi_cmnd *cmd;
+ u32 error;
struct device *dev;
- u8 as, ds, st;
cmd = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt));
-
- if (msg->u.head[0] & (1 << 13)) {
- struct i2o_message __iomem *pmsg; /* preserved message */
- u32 pm;
- int err = DID_ERROR;
-
- pm = le32_to_cpu(msg->body[3]);
-
- pmsg = i2o_msg_in_to_virt(c, pm);
-
- osm_err("IOP fail.\n");
- osm_err("From %d To %d Cmd %d.\n",
- (msg->u.head[1] >> 12) & 0xFFF,
- msg->u.head[1] & 0xFFF, msg->u.head[1] >> 24);
- osm_err("Failure Code %d.\n", msg->body[0] >> 24);
- if (msg->body[0] & (1 << 16))
- osm_err("Format error.\n");
- if (msg->body[0] & (1 << 17))
- osm_err("Path error.\n");
- if (msg->body[0] & (1 << 18))
- osm_err("Path State.\n");
- if (msg->body[0] & (1 << 18))
- {
- osm_err("Congestion.\n");
- err = DID_BUS_BUSY;
- }
-
- osm_debug("Failing message is %p.\n", pmsg);
-
- cmd = i2o_cntxt_list_get(c, readl(&pmsg->u.s.tcntxt));
- if (!cmd)
- return 1;
-
- cmd->result = err << 16;
- cmd->scsi_done(cmd);
-
- /* Now flush the message by making it a NOP */
- i2o_msg_nop(c, pm);
-
- return 1;
+ if (unlikely(!cmd)) {
+ osm_err("NULL reply received!\n");
+ return -1;
}
/*
* Low byte is device status, next is adapter status,
* (then one byte reserved), then request status.
*/
- ds = (u8) le32_to_cpu(msg->body[0]);
- as = (u8) (le32_to_cpu(msg->body[0]) >> 8);
- st = (u8) (le32_to_cpu(msg->body[0]) >> 24);
+ error = le32_to_cpu(msg->body[0]);
+
+ osm_debug("Completed %ld\n", cmd->serial_number);
+ cmd->result = error & 0xff;
/*
- * Is this a control request coming back - eg an abort ?
+ * if DeviceStatus is not SCSI_SUCCESS copy over the sense data and let
+ * the SCSI layer handle the error
*/
+ if (cmd->result)
+ memcpy(cmd->sense_buffer, &msg->body[3],
+ min(sizeof(cmd->sense_buffer), (size_t) 40));
- if (!cmd) {
- if (st)
- osm_warn("SCSI abort: %08X", le32_to_cpu(msg->body[0]));
- osm_info("SCSI abort completed.\n");
- return -EFAULT;
- }
+ /* only output error code if AdapterStatus is not HBA_SUCCESS */
+ if ((error >> 8) & 0xff)
+ osm_err("SCSI error %08x\n", error);
- osm_debug("Completed %ld\n", cmd->serial_number);
+ dev = &c->pdev->dev;
+ if (cmd->use_sg)
+ dma_unmap_sg(dev, cmd->request_buffer, cmd->use_sg,
+ cmd->sc_data_direction);
+ else if (cmd->SCp.dma_handle)
+ dma_unmap_single(dev, cmd->SCp.dma_handle, cmd->request_bufflen,
+ cmd->sc_data_direction);
- if (st) {
- u32 count, error;
- /* An error has occurred */
-
- switch (st) {
- case 0x06:
- count = le32_to_cpu(msg->body[1]);
- if (count < cmd->underflow) {
- int i;
-
- osm_err("SCSI underflow 0x%08X 0x%08X\n", count,
- cmd->underflow);
- osm_debug("Cmd: ");
- for (i = 0; i < 15; i++)
- pr_debug("%02X ", cmd->cmnd[i]);
- pr_debug(".\n");
- cmd->result = (DID_ERROR << 16);
- }
- break;
+ cmd->scsi_done(cmd);
- default:
- error = le32_to_cpu(msg->body[0]);
-
- osm_err("SCSI error %08x\n", error);
-
- if ((error & 0xff) == 0x02 /*CHECK_CONDITION */ ) {
- int i;
- u32 len = sizeof(cmd->sense_buffer);
- len = (len > 40) ? 40 : len;
- // Copy over the sense data
- memcpy(cmd->sense_buffer, (void *)&msg->body[3],
- len);
- for (i = 0; i <= len; i++)
- osm_info("%02x\n",
- cmd->sense_buffer[i]);
- if (cmd->sense_buffer[0] == 0x70
- && cmd->sense_buffer[2] == DATA_PROTECT) {
- /* This is to handle an array failed */
- cmd->result = (DID_TIME_OUT << 16);
- printk(KERN_WARNING "%s: SCSI Data "
- "Protect-Device (%d,%d,%d) "
- "hba_status=0x%x, dev_status="
- "0x%x, cmd=0x%x\n", c->name,
- (u32) cmd->device->channel,
- (u32) cmd->device->id,
- (u32) cmd->device->lun,
- (error >> 8) & 0xff,
- error & 0xff, cmd->cmnd[0]);
- } else
- cmd->result = (DID_ERROR << 16);
-
- break;
- }
-
- switch (as) {
- case 0x0E:
- /* SCSI Reset */
- cmd->result = DID_RESET << 16;
- break;
-
- case 0x0F:
- cmd->result = DID_PARITY << 16;
- break;
-
- default:
- cmd->result = DID_ERROR << 16;
- break;
- }
+ return 1;
+};
- break;
- }
+/**
+ * i2o_scsi_notify_device_add - Retrieve notifications of added devices
+ * @i2o_dev: the I2O device which was added
+ *
+ * If a I2O device is added we catch the notification, because I2O classes
+ * other then SCSI peripheral will not be received through
+ * i2o_scsi_probe().
+ */
+static void i2o_scsi_notify_device_add(struct i2o_device *i2o_dev)
+{
+ switch (i2o_dev->lct_data.class_id) {
+ case I2O_CLASS_EXECUTIVE:
+ case I2O_CLASS_RANDOM_BLOCK_STORAGE:
+ i2o_scsi_probe(&i2o_dev->device);
+ break;
- cmd->scsi_done(cmd);
- return 1;
+ default:
+ break;
}
+};
- cmd->result = DID_OK << 16 | ds;
-
- cmd->scsi_done(cmd);
-
- dev = &c->pdev->dev;
- if (cmd->use_sg)
- dma_unmap_sg(dev, (struct scatterlist *)cmd->buffer,
- cmd->use_sg, cmd->sc_data_direction);
- else if (cmd->request_bufflen)
- dma_unmap_single(dev, (dma_addr_t) ((long)cmd->SCp.ptr),
- cmd->request_bufflen, cmd->sc_data_direction);
+/**
+ * i2o_scsi_notify_device_remove - Retrieve notifications of removed
+ * devices
+ * @i2o_dev: the I2O device which was removed
+ *
+ * If a I2O device is removed, we catch the notification to remove the
+ * corresponding SCSI device.
+ */
+static void i2o_scsi_notify_device_remove(struct i2o_device *i2o_dev)
+{
+ switch (i2o_dev->lct_data.class_id) {
+ case I2O_CLASS_EXECUTIVE:
+ case I2O_CLASS_RANDOM_BLOCK_STORAGE:
+ i2o_scsi_remove(&i2o_dev->device);
+ break;
- return 1;
+ default:
+ break;
+ }
};
/**
@@ -501,7 +472,7 @@ static void i2o_scsi_notify_controller_remove(struct i2o_controller *c)
scsi_remove_host(i2o_shost->scsi_host);
scsi_host_put(i2o_shost->scsi_host);
- pr_info("I2O SCSI host removed\n");
+ osm_debug("I2O SCSI host removed\n");
};
/* SCSI OSM driver struct */
@@ -509,6 +480,8 @@ static struct i2o_driver i2o_scsi_driver = {
.name = OSM_NAME,
.reply = i2o_scsi_reply,
.classes = i2o_scsi_class_id,
+ .notify_device_add = i2o_scsi_notify_device_add,
+ .notify_device_remove = i2o_scsi_notify_device_remove,
.notify_controller_add = i2o_scsi_notify_controller_add,
.notify_controller_remove = i2o_scsi_notify_controller_remove,
.driver = {
@@ -535,26 +508,26 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
void (*done) (struct scsi_cmnd *))
{
struct i2o_controller *c;
- struct Scsi_Host *host;
struct i2o_device *i2o_dev;
- struct device *dev;
int tid;
struct i2o_message __iomem *msg;
u32 m;
- u32 scsi_flags, sg_flags;
+ /*
+ * ENABLE_DISCONNECT
+ * SIMPLE_TAG
+ * RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME
+ */
+ u32 scsi_flags = 0x20a00000;
+ u32 sgl_offset;
u32 __iomem *mptr;
- u32 __iomem *lenptr;
- u32 len, reqlen;
- int i;
+ u32 cmd = I2O_CMD_SCSI_EXEC << 24;
+ int rc = 0;
/*
* Do the incoming paperwork
*/
-
i2o_dev = SCpnt->device->hostdata;
- host = SCpnt->device->host;
c = i2o_dev->iop;
- dev = &c->pdev->dev;
SCpnt->scsi_done = done;
@@ -562,7 +535,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
osm_warn("no I2O device in request\n");
SCpnt->result = DID_NO_CONNECT << 16;
done(SCpnt);
- return 0;
+ goto exit;
}
tid = i2o_dev->lct_data.tid;
@@ -571,44 +544,85 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
osm_debug("Real scsi messages.\n");
/*
- * Obtain an I2O message. If there are none free then
- * throw it back to the scsi layer
- */
-
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return SCSI_MLQUEUE_HOST_BUSY;
-
- /*
* Put together a scsi execscb message
*/
-
- len = SCpnt->request_bufflen;
-
switch (SCpnt->sc_data_direction) {
case PCI_DMA_NONE:
- scsi_flags = 0x00000000; // DATA NO XFER
- sg_flags = 0x00000000;
+ /* DATA NO XFER */
+ sgl_offset = SGL_OFFSET_0;
break;
case PCI_DMA_TODEVICE:
- scsi_flags = 0x80000000; // DATA OUT (iop-->dev)
- sg_flags = 0x14000000;
+ /* DATA OUT (iop-->dev) */
+ scsi_flags |= 0x80000000;
+ sgl_offset = SGL_OFFSET_10;
break;
case PCI_DMA_FROMDEVICE:
- scsi_flags = 0x40000000; // DATA IN (iop<--dev)
- sg_flags = 0x10000000;
+ /* DATA IN (iop<--dev) */
+ scsi_flags |= 0x40000000;
+ sgl_offset = SGL_OFFSET_10;
break;
default:
/* Unknown - kill the command */
SCpnt->result = DID_NO_CONNECT << 16;
done(SCpnt);
- return 0;
+ goto exit;
}
- writel(I2O_CMD_SCSI_EXEC << 24 | HOST_TID << 12 | tid, &msg->u.head[1]);
+ /*
+ * Obtain an I2O message. If there are none free then
+ * throw it back to the scsi layer
+ */
+
+ m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+ if (m == I2O_QUEUE_EMPTY) {
+ rc = SCSI_MLQUEUE_HOST_BUSY;
+ goto exit;
+ }
+
+ mptr = &msg->body[0];
+
+#ifdef CONFIG_I2O_EXT_ADAPTEC
+ if (c->adaptec) {
+ u32 adpt_flags = 0;
+
+ if (SCpnt->sc_request && SCpnt->sc_request->upper_private_data) {
+ i2o_sg_io_hdr_t __user *usr_ptr =
+ ((Sg_request *) (SCpnt->sc_request->
+ upper_private_data))->header.
+ usr_ptr;
+
+ if (usr_ptr)
+ get_user(adpt_flags, &usr_ptr->flags);
+ }
+
+ switch (i2o_dev->lct_data.class_id) {
+ case I2O_CLASS_EXECUTIVE:
+ case I2O_CLASS_RANDOM_BLOCK_STORAGE:
+ /* interpret flag has to be set for executive */
+ adpt_flags ^= I2O_DPT_SG_FLAG_INTERPRET;
+ break;
+
+ default:
+ break;
+ }
+
+ /*
+ * for Adaptec controllers we use the PRIVATE command, because
+ * the normal SCSI EXEC doesn't support all SCSI commands on
+ * all controllers (for example READ CAPACITY).
+ */
+ if (sgl_offset == SGL_OFFSET_10)
+ sgl_offset = SGL_OFFSET_12;
+ cmd = I2O_CMD_PRIVATE << 24;
+ writel(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC, mptr++);
+ writel(adpt_flags | tid, mptr++);
+ }
+#endif
+
+ writel(cmd | HOST_TID << 12 | tid, &msg->u.head[1]);
writel(i2o_scsi_driver.context, &msg->u.s.icntxt);
/* We want the SCSI control block back */
@@ -626,7 +640,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
*/
/* Attach tags to the devices */
- /*
+ /* FIXME: implement
if(SCpnt->device->tagged_supported) {
if(SCpnt->tag == HEAD_OF_QUEUE_TAG)
scsi_flags |= 0x01000000;
@@ -635,67 +649,35 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
}
*/
- /* Direction, disconnect ok, tag, CDBLen */
- writel(scsi_flags | 0x20200000 | SCpnt->cmd_len, &msg->body[0]);
-
- mptr = &msg->body[1];
+ writel(scsi_flags | SCpnt->cmd_len, mptr++);
/* Write SCSI command into the message - always 16 byte block */
memcpy_toio(mptr, SCpnt->cmnd, 16);
mptr += 4;
- lenptr = mptr++; /* Remember me - fill in when we know */
-
- reqlen = 12; // SINGLE SGE
-
- /* Now fill in the SGList and command */
- if (SCpnt->use_sg) {
- struct scatterlist *sg;
- int sg_count;
-
- sg = SCpnt->request_buffer;
- len = 0;
-
- sg_count = dma_map_sg(dev, sg, SCpnt->use_sg,
- SCpnt->sc_data_direction);
- if (unlikely(sg_count <= 0))
- return -ENOMEM;
-
- for (i = SCpnt->use_sg; i > 0; i--) {
- if (i == 1)
- sg_flags |= 0xC0000000;
- writel(sg_flags | sg_dma_len(sg), mptr++);
- writel(sg_dma_address(sg), mptr++);
- len += sg_dma_len(sg);
- sg++;
+ if (sgl_offset != SGL_OFFSET_0) {
+ /* write size of data addressed by SGL */
+ writel(SCpnt->request_bufflen, mptr++);
+
+ /* Now fill in the SGList and command */
+ if (SCpnt->use_sg) {
+ if (!i2o_dma_map_sg(c, SCpnt->request_buffer,
+ SCpnt->use_sg,
+ SCpnt->sc_data_direction, &mptr))
+ goto nomem;
+ } else {
+ SCpnt->SCp.dma_handle =
+ i2o_dma_map_single(c, SCpnt->request_buffer,
+ SCpnt->request_bufflen,
+ SCpnt->sc_data_direction, &mptr);
+ if (dma_mapping_error(SCpnt->SCp.dma_handle))
+ goto nomem;
}
-
- reqlen = mptr - &msg->u.head[0];
- writel(len, lenptr);
- } else {
- len = SCpnt->request_bufflen;
-
- writel(len, lenptr);
-
- if (len > 0) {
- dma_addr_t dma_addr;
-
- dma_addr = dma_map_single(dev, SCpnt->request_buffer,
- SCpnt->request_bufflen,
- SCpnt->sc_data_direction);
- if (!dma_addr)
- return -ENOMEM;
-
- SCpnt->SCp.ptr = (void *)(unsigned long)dma_addr;
- sg_flags |= 0xC0000000;
- writel(sg_flags | SCpnt->request_bufflen, mptr++);
- writel(dma_addr, mptr++);
- } else
- reqlen = 9;
}
/* Stick the headers on */
- writel(reqlen << 16 | SGL_OFFSET_10, &msg->u.head[0]);
+ writel(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset,
+ &msg->u.head[0]);
/* Queue the message */
i2o_msg_post(c, m);
@@ -703,6 +685,13 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,
osm_debug("Issued %ld\n", SCpnt->serial_number);
return 0;
+
+ nomem:
+ rc = -ENOMEM;
+ i2o_msg_nop(c, m);
+
+ exit:
+ return rc;
};
/**
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index 50c8cedf7a2..42f8b810d6e 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -28,8 +28,10 @@
#include <linux/module.h>
#include <linux/i2o.h>
#include <linux/delay.h>
+#include "core.h"
-#define OSM_VERSION "$Rev$"
+#define OSM_NAME "i2o"
+#define OSM_VERSION "1.288"
#define OSM_DESCRIPTION "I2O subsystem"
/* global I2O controller list */
@@ -43,20 +45,6 @@ static struct i2o_dma i2o_systab;
static int i2o_hrt_get(struct i2o_controller *c);
-/* Module internal functions from other sources */
-extern struct i2o_driver i2o_exec_driver;
-extern int i2o_exec_lct_get(struct i2o_controller *);
-extern void i2o_device_remove(struct i2o_device *);
-
-extern int __init i2o_driver_init(void);
-extern void __exit i2o_driver_exit(void);
-extern int __init i2o_exec_init(void);
-extern void __exit i2o_exec_exit(void);
-extern int __init i2o_pci_init(void);
-extern void __exit i2o_pci_exit(void);
-extern int i2o_device_init(void);
-extern void i2o_device_exit(void);
-
/**
* i2o_msg_nop - Returns a message which is not used
* @c: I2O controller from which the message was created
@@ -68,7 +56,7 @@ extern void i2o_device_exit(void);
*/
void i2o_msg_nop(struct i2o_controller *c, u32 m)
{
- struct i2o_message __iomem *msg = c->in_queue.virt + m;
+ struct i2o_message __iomem *msg = i2o_msg_in_to_virt(c, m);
writel(THREE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
writel(I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | ADAPTER_TID,
@@ -92,16 +80,16 @@ void i2o_msg_nop(struct i2o_controller *c, u32 m)
* address from the read port (see the i2o spec). If no message is
* available returns I2O_QUEUE_EMPTY and msg is leaved untouched.
*/
-u32 i2o_msg_get_wait(struct i2o_controller *c, struct i2o_message __iomem **msg,
- int wait)
+u32 i2o_msg_get_wait(struct i2o_controller *c,
+ struct i2o_message __iomem ** msg, int wait)
{
unsigned long timeout = jiffies + wait * HZ;
u32 m;
while ((m = i2o_msg_get(c, msg)) == I2O_QUEUE_EMPTY) {
if (time_after(jiffies, timeout)) {
- pr_debug("%s: Timeout waiting for message frame.\n",
- c->name);
+ osm_debug("%s: Timeout waiting for message frame.\n",
+ c->name);
return I2O_QUEUE_EMPTY;
}
set_current_state(TASK_UNINTERRUPTIBLE);
@@ -129,13 +117,13 @@ u32 i2o_cntxt_list_add(struct i2o_controller * c, void *ptr)
unsigned long flags;
if (!ptr)
- printk(KERN_ERR "%s: couldn't add NULL pointer to context list!"
- "\n", c->name);
+ osm_err("%s: couldn't add NULL pointer to context list!\n",
+ c->name);
entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
if (!entry) {
- printk(KERN_ERR "%s: Could not allocate memory for context "
- "list element\n", c->name);
+ osm_err("%s: Could not allocate memory for context list element"
+ "\n", c->name);
return 0;
}
@@ -154,7 +142,7 @@ u32 i2o_cntxt_list_add(struct i2o_controller * c, void *ptr)
spin_unlock_irqrestore(&c->context_list_lock, flags);
- pr_debug("%s: Add context to list %p -> %d\n", c->name, ptr, context);
+ osm_debug("%s: Add context to list %p -> %d\n", c->name, ptr, context);
return entry->context;
};
@@ -186,11 +174,11 @@ u32 i2o_cntxt_list_remove(struct i2o_controller * c, void *ptr)
spin_unlock_irqrestore(&c->context_list_lock, flags);
if (!context)
- printk(KERN_WARNING "%s: Could not remove nonexistent ptr "
- "%p\n", c->name, ptr);
+ osm_warn("%s: Could not remove nonexistent ptr %p\n", c->name,
+ ptr);
- pr_debug("%s: remove ptr from context list %d -> %p\n", c->name,
- context, ptr);
+ osm_debug("%s: remove ptr from context list %d -> %p\n", c->name,
+ context, ptr);
return context;
};
@@ -220,11 +208,10 @@ void *i2o_cntxt_list_get(struct i2o_controller *c, u32 context)
spin_unlock_irqrestore(&c->context_list_lock, flags);
if (!ptr)
- printk(KERN_WARNING "%s: context id %d not found\n", c->name,
- context);
+ osm_warn("%s: context id %d not found\n", c->name, context);
- pr_debug("%s: get ptr from context list %d -> %p\n", c->name, context,
- ptr);
+ osm_debug("%s: get ptr from context list %d -> %p\n", c->name, context,
+ ptr);
return ptr;
};
@@ -252,11 +239,11 @@ u32 i2o_cntxt_list_get_ptr(struct i2o_controller * c, void *ptr)
spin_unlock_irqrestore(&c->context_list_lock, flags);
if (!context)
- printk(KERN_WARNING "%s: Could not find nonexistent ptr "
- "%p\n", c->name, ptr);
+ osm_warn("%s: Could not find nonexistent ptr %p\n", c->name,
+ ptr);
- pr_debug("%s: get context id from context list %p -> %d\n", c->name,
- ptr, context);
+ osm_debug("%s: get context id from context list %p -> %d\n", c->name,
+ ptr, context);
return context;
};
@@ -336,10 +323,9 @@ static int i2o_iop_quiesce(struct i2o_controller *c)
/* Long timeout needed for quiesce if lots of devices */
if ((rc = i2o_msg_post_wait(c, m, 240)))
- printk(KERN_INFO "%s: Unable to quiesce (status=%#x).\n",
- c->name, -rc);
+ osm_info("%s: Unable to quiesce (status=%#x).\n", c->name, -rc);
else
- pr_debug("%s: Quiesced.\n", c->name);
+ osm_debug("%s: Quiesced.\n", c->name);
i2o_status_get(c); // Entered READY state
@@ -377,10 +363,9 @@ static int i2o_iop_enable(struct i2o_controller *c)
/* How long of a timeout do we need? */
if ((rc = i2o_msg_post_wait(c, m, 240)))
- printk(KERN_ERR "%s: Could not enable (status=%#x).\n",
- c->name, -rc);
+ osm_err("%s: Could not enable (status=%#x).\n", c->name, -rc);
else
- pr_debug("%s: Enabled.\n", c->name);
+ osm_debug("%s: Enabled.\n", c->name);
i2o_status_get(c); // entered OPERATIONAL state
@@ -444,20 +429,78 @@ static int i2o_iop_clear(struct i2o_controller *c)
&msg->u.head[1]);
if ((rc = i2o_msg_post_wait(c, m, 30)))
- printk(KERN_INFO "%s: Unable to clear (status=%#x).\n",
- c->name, -rc);
+ osm_info("%s: Unable to clear (status=%#x).\n", c->name, -rc);
else
- pr_debug("%s: Cleared.\n", c->name);
+ osm_debug("%s: Cleared.\n", c->name);
/* Enable all IOPs */
i2o_iop_enable_all();
- i2o_status_get(c);
-
return rc;
}
/**
+ * i2o_iop_init_outbound_queue - setup the outbound message queue
+ * @c: I2O controller
+ *
+ * Clear and (re)initialize IOP's outbound queue and post the message
+ * frames to the IOP.
+ *
+ * Returns 0 on success or a negative errno code on failure.
+ */
+static int i2o_iop_init_outbound_queue(struct i2o_controller *c)
+{
+ volatile u8 *status = c->status.virt;
+ u32 m;
+ struct i2o_message __iomem *msg;
+ ulong timeout;
+ int i;
+
+ osm_debug("%s: Initializing Outbound Queue...\n", c->name);
+
+ memset(c->status.virt, 0, 4);
+
+ m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+ if (m == I2O_QUEUE_EMPTY)
+ return -ETIMEDOUT;
+
+ writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6, &msg->u.head[0]);
+ writel(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | ADAPTER_TID,
+ &msg->u.head[1]);
+ writel(i2o_exec_driver.context, &msg->u.s.icntxt);
+ writel(0x00000000, &msg->u.s.tcntxt);
+ writel(PAGE_SIZE, &msg->body[0]);
+ /* Outbound msg frame size in words and Initcode */
+ writel(I2O_OUTBOUND_MSG_FRAME_SIZE << 16 | 0x80, &msg->body[1]);
+ writel(0xd0000004, &msg->body[2]);
+ writel(i2o_dma_low(c->status.phys), &msg->body[3]);
+ writel(i2o_dma_high(c->status.phys), &msg->body[4]);
+
+ i2o_msg_post(c, m);
+
+ timeout = jiffies + I2O_TIMEOUT_INIT_OUTBOUND_QUEUE * HZ;
+ while (*status <= I2O_CMD_IN_PROGRESS) {
+ if (time_after(jiffies, timeout)) {
+ osm_warn("%s: Timeout Initializing\n", c->name);
+ return -ETIMEDOUT;
+ }
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(1);
+ }
+
+ m = c->out_queue.phys;
+
+ /* Post frames */
+ for (i = 0; i < I2O_MAX_OUTBOUND_MSG_FRAMES; i++) {
+ i2o_flush_reply(c, m);
+ udelay(1); /* Promise */
+ m += I2O_OUTBOUND_MSG_FRAME_SIZE * sizeof(u32);
+ }
+
+ return 0;
+}
+
+/**
* i2o_iop_reset - reset an I2O controller
* @c: controller to reset
*
@@ -468,20 +511,20 @@ static int i2o_iop_clear(struct i2o_controller *c)
*/
static int i2o_iop_reset(struct i2o_controller *c)
{
- u8 *status = c->status.virt;
+ volatile u8 *status = c->status.virt;
struct i2o_message __iomem *msg;
u32 m;
unsigned long timeout;
i2o_status_block *sb = c->status_block.virt;
int rc = 0;
- pr_debug("%s: Resetting controller\n", c->name);
+ osm_debug("%s: Resetting controller\n", c->name);
m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
if (m == I2O_QUEUE_EMPTY)
return -ETIMEDOUT;
- memset(status, 0, 8);
+ memset(c->status_block.virt, 0, 8);
/* Quiesce all IOPs first */
i2o_iop_quiesce_all();
@@ -493,49 +536,43 @@ static int i2o_iop_reset(struct i2o_controller *c)
writel(0, &msg->u.s.tcntxt); //FIXME: use reasonable transaction context
writel(0, &msg->body[0]);
writel(0, &msg->body[1]);
- writel(i2o_ptr_low((void *)c->status.phys), &msg->body[2]);
- writel(i2o_ptr_high((void *)c->status.phys), &msg->body[3]);
+ writel(i2o_dma_low(c->status.phys), &msg->body[2]);
+ writel(i2o_dma_high(c->status.phys), &msg->body[3]);
i2o_msg_post(c, m);
/* Wait for a reply */
timeout = jiffies + I2O_TIMEOUT_RESET * HZ;
while (!*status) {
- if (time_after(jiffies, timeout)) {
- printk(KERN_ERR "%s: IOP reset timeout.\n", c->name);
- rc = -ETIMEDOUT;
- goto exit;
- }
-
- /* Promise bug */
- if (status[1] || status[4]) {
- *status = 0;
+ if (time_after(jiffies, timeout))
break;
- }
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
-
- rmb();
}
- if (*status == I2O_CMD_IN_PROGRESS) {
+ switch (*status) {
+ case I2O_CMD_REJECTED:
+ osm_warn("%s: IOP reset rejected\n", c->name);
+ rc = -EPERM;
+ break;
+
+ case I2O_CMD_IN_PROGRESS:
/*
* Once the reset is sent, the IOP goes into the INIT state
- * which is indeterminate. We need to wait until the IOP
- * has rebooted before we can let the system talk to
- * it. We read the inbound Free_List until a message is
- * available. If we can't read one in the given ammount of
- * time, we assume the IOP could not reboot properly.
+ * which is indeterminate. We need to wait until the IOP has
+ * rebooted before we can let the system talk to it. We read
+ * the inbound Free_List until a message is available. If we
+ * can't read one in the given ammount of time, we assume the
+ * IOP could not reboot properly.
*/
- pr_debug("%s: Reset in progress, waiting for reboot...\n",
- c->name);
+ osm_debug("%s: Reset in progress, waiting for reboot...\n",
+ c->name);
m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET);
while (m == I2O_QUEUE_EMPTY) {
if (time_after(jiffies, timeout)) {
- printk(KERN_ERR "%s: IOP reset timeout.\n",
- c->name);
+ osm_err("%s: IOP reset timeout.\n", c->name);
rc = -ETIMEDOUT;
goto exit;
}
@@ -545,19 +582,26 @@ static int i2o_iop_reset(struct i2o_controller *c)
m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET);
}
i2o_msg_nop(c, m);
- }
- /* from here all quiesce commands are safe */
- c->no_quiesce = 0;
+ /* from here all quiesce commands are safe */
+ c->no_quiesce = 0;
- /* If IopReset was rejected or didn't perform reset, try IopClear */
- i2o_status_get(c);
- if (*status == I2O_CMD_REJECTED || sb->iop_state != ADAPTER_STATE_RESET) {
- printk(KERN_WARNING "%s: Reset rejected, trying to clear\n",
- c->name);
- i2o_iop_clear(c);
- } else
- pr_debug("%s: Reset completed.\n", c->name);
+ /* verify if controller is in state RESET */
+ i2o_status_get(c);
+
+ if (!c->promise && (sb->iop_state != ADAPTER_STATE_RESET))
+ osm_warn("%s: reset completed, but adapter not in RESET"
+ " state.\n", c->name);
+ else
+ osm_debug("%s: reset completed.\n", c->name);
+
+ break;
+
+ default:
+ osm_err("%s: IOP reset timeout.\n", c->name);
+ rc = -ETIMEDOUT;
+ break;
+ }
exit:
/* Enable all IOPs */
@@ -567,88 +611,6 @@ static int i2o_iop_reset(struct i2o_controller *c)
};
/**
- * i2o_iop_init_outbound_queue - setup the outbound message queue
- * @c: I2O controller
- *
- * Clear and (re)initialize IOP's outbound queue and post the message
- * frames to the IOP.
- *
- * Returns 0 on success or a negative errno code on failure.
- */
-static int i2o_iop_init_outbound_queue(struct i2o_controller *c)
-{
- u8 *status = c->status.virt;
- u32 m;
- struct i2o_message __iomem *msg;
- ulong timeout;
- int i;
-
- pr_debug("%s: Initializing Outbound Queue...\n", c->name);
-
- memset(status, 0, 4);
-
- m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
-
- writel(EIGHT_WORD_MSG_SIZE | TRL_OFFSET_6, &msg->u.head[0]);
- writel(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | ADAPTER_TID,
- &msg->u.head[1]);
- writel(i2o_exec_driver.context, &msg->u.s.icntxt);
- writel(0x0106, &msg->u.s.tcntxt); /* FIXME: why 0x0106, maybe in
- Spec? */
- writel(PAGE_SIZE, &msg->body[0]);
- writel(MSG_FRAME_SIZE << 16 | 0x80, &msg->body[1]); /* Outbound msg frame
- size in words and Initcode */
- writel(0xd0000004, &msg->body[2]);
- writel(i2o_ptr_low((void *)c->status.phys), &msg->body[3]);
- writel(i2o_ptr_high((void *)c->status.phys), &msg->body[4]);
-
- i2o_msg_post(c, m);
-
- timeout = jiffies + I2O_TIMEOUT_INIT_OUTBOUND_QUEUE * HZ;
- while (*status <= I2O_CMD_IN_PROGRESS) {
- if (time_after(jiffies, timeout)) {
- printk(KERN_WARNING "%s: Timeout Initializing\n",
- c->name);
- return -ETIMEDOUT;
- }
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(1);
-
- rmb();
- }
-
- m = c->out_queue.phys;
-
- /* Post frames */
- for (i = 0; i < NMBR_MSG_FRAMES; i++) {
- i2o_flush_reply(c, m);
- udelay(1); /* Promise */
- m += MSG_FRAME_SIZE * 4;
- }
-
- return 0;
-}
-
-/**
- * i2o_iop_send_nop - send a core NOP message
- * @c: controller
- *
- * Send a no-operation message with a reply set to cause no
- * action either. Needed for bringing up promise controllers.
- */
-static int i2o_iop_send_nop(struct i2o_controller *c)
-{
- struct i2o_message __iomem *msg;
- u32 m = i2o_msg_get_wait(c, &msg, HZ);
- if (m == I2O_QUEUE_EMPTY)
- return -ETIMEDOUT;
- i2o_msg_nop(c, m);
- return 0;
-}
-
-/**
* i2o_iop_activate - Bring controller up to HOLD
* @c: controller
*
@@ -659,78 +621,62 @@ static int i2o_iop_send_nop(struct i2o_controller *c)
*/
static int i2o_iop_activate(struct i2o_controller *c)
{
- struct pci_dev *i960 = NULL;
i2o_status_block *sb = c->status_block.virt;
int rc;
-
- if (c->promise) {
- /* Beat up the hardware first of all */
- i960 =
- pci_find_slot(c->pdev->bus->number,
- PCI_DEVFN(PCI_SLOT(c->pdev->devfn), 0));
- if (i960)
- pci_write_config_word(i960, 0x42, 0);
-
- /* Follow this sequence precisely or the controller
- ceases to perform useful functions until reboot */
- if ((rc = i2o_iop_send_nop(c)))
- return rc;
-
- if ((rc = i2o_iop_reset(c)))
- return rc;
- }
+ int state;
/* In INIT state, Wait Inbound Q to initialize (in i2o_status_get) */
/* In READY state, Get status */
rc = i2o_status_get(c);
if (rc) {
- printk(KERN_INFO "%s: Unable to obtain status, "
- "attempting a reset.\n", c->name);
- if (i2o_iop_reset(c))
+ osm_info("%s: Unable to obtain status, attempting a reset.\n",
+ c->name);
+ rc = i2o_iop_reset(c);
+ if (rc)
return rc;
}
if (sb->i2o_version > I2OVER15) {
- printk(KERN_ERR "%s: Not running version 1.5 of the I2O "
- "Specification.\n", c->name);
+ osm_err("%s: Not running version 1.5 of the I2O Specification."
+ "\n", c->name);
return -ENODEV;
}
switch (sb->iop_state) {
case ADAPTER_STATE_FAULTED:
- printk(KERN_CRIT "%s: hardware fault\n", c->name);
- return -ENODEV;
+ osm_err("%s: hardware fault\n", c->name);
+ return -EFAULT;
case ADAPTER_STATE_READY:
case ADAPTER_STATE_OPERATIONAL:
case ADAPTER_STATE_HOLD:
case ADAPTER_STATE_FAILED:
- pr_debug("%s: already running, trying to reset...\n", c->name);
- if (i2o_iop_reset(c))
- return -ENODEV;
+ osm_debug("%s: already running, trying to reset...\n", c->name);
+ rc = i2o_iop_reset(c);
+ if (rc)
+ return rc;
}
+ /* preserve state */
+ state = sb->iop_state;
+
rc = i2o_iop_init_outbound_queue(c);
if (rc)
return rc;
- if (c->promise) {
- if ((rc = i2o_iop_send_nop(c)))
- return rc;
+ /* if adapter was not in RESET state clear now */
+ if (state != ADAPTER_STATE_RESET)
+ i2o_iop_clear(c);
- if ((rc = i2o_status_get(c)))
- return rc;
+ i2o_status_get(c);
- if (i960)
- pci_write_config_word(i960, 0x42, 0x3FF);
+ if (sb->iop_state != ADAPTER_STATE_HOLD) {
+ osm_err("%s: failed to bring IOP into HOLD state\n", c->name);
+ return -EIO;
}
- /* In HOLD state */
-
- rc = i2o_hrt_get(c);
-
- return rc;
+ return i2o_hrt_get(c);
};
/**
@@ -756,20 +702,18 @@ static int i2o_iop_systab_set(struct i2o_controller *c)
res->flags = IORESOURCE_MEM;
res->start = 0;
res->end = 0;
- printk(KERN_INFO "%s: requires private memory resources.\n",
- c->name);
+ osm_info("%s: requires private memory resources.\n", c->name);
root = pci_find_parent_resource(c->pdev, res);
if (root == NULL)
- printk(KERN_WARNING "%s: Can't find parent resource!\n",
- c->name);
+ osm_warn("%s: Can't find parent resource!\n", c->name);
if (root && allocate_resource(root, res, sb->desired_mem_size, sb->desired_mem_size, sb->desired_mem_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */
NULL, NULL) >= 0) {
c->mem_alloc = 1;
sb->current_mem_size = 1 + res->end - res->start;
sb->current_mem_base = res->start;
- printk(KERN_INFO "%s: allocated %ld bytes of PCI memory"
- " at 0x%08lX.\n", c->name,
- 1 + res->end - res->start, res->start);
+ osm_info("%s: allocated %ld bytes of PCI memory at "
+ "0x%08lX.\n", c->name,
+ 1 + res->end - res->start, res->start);
}
}
@@ -779,20 +723,18 @@ static int i2o_iop_systab_set(struct i2o_controller *c)
res->flags = IORESOURCE_IO;
res->start = 0;
res->end = 0;
- printk(KERN_INFO "%s: requires private memory resources.\n",
- c->name);
+ osm_info("%s: requires private memory resources.\n", c->name);
root = pci_find_parent_resource(c->pdev, res);
if (root == NULL)
- printk(KERN_WARNING "%s: Can't find parent resource!\n",
- c->name);
+ osm_warn("%s: Can't find parent resource!\n", c->name);
if (root && allocate_resource(root, res, sb->desired_io_size, sb->desired_io_size, sb->desired_io_size, 1 << 20, /* Unspecified, so use 1Mb and play safe */
NULL, NULL) >= 0) {
c->io_alloc = 1;
sb->current_io_size = 1 + res->end - res->start;
sb->current_mem_base = res->start;
- printk(KERN_INFO "%s: allocated %ld bytes of PCI I/O at"
- " 0x%08lX.\n", c->name,
- 1 + res->end - res->start, res->start);
+ osm_info("%s: allocated %ld bytes of PCI I/O at 0x%08lX"
+ ".\n", c->name, 1 + res->end - res->start,
+ res->start);
}
}
@@ -836,10 +778,10 @@ static int i2o_iop_systab_set(struct i2o_controller *c)
PCI_DMA_TODEVICE);
if (rc < 0)
- printk(KERN_ERR "%s: Unable to set SysTab (status=%#x).\n",
- c->name, -rc);
+ osm_err("%s: Unable to set SysTab (status=%#x).\n", c->name,
+ -rc);
else
- pr_debug("%s: SysTab set.\n", c->name);
+ osm_debug("%s: SysTab set.\n", c->name);
i2o_status_get(c); // Entered READY state
@@ -863,7 +805,7 @@ static int i2o_iop_online(struct i2o_controller *c)
return rc;
/* In READY state */
- pr_debug("%s: Attempting to enable...\n", c->name);
+ osm_debug("%s: Attempting to enable...\n", c->name);
rc = i2o_iop_enable(c);
if (rc)
return rc;
@@ -882,7 +824,7 @@ void i2o_iop_remove(struct i2o_controller *c)
{
struct i2o_device *dev, *tmp;
- pr_debug("%s: deleting controller\n", c->name);
+ osm_debug("%s: deleting controller\n", c->name);
i2o_driver_notify_controller_remove_all(c);
@@ -891,8 +833,12 @@ void i2o_iop_remove(struct i2o_controller *c)
list_for_each_entry_safe(dev, tmp, &c->devices, list)
i2o_device_remove(dev);
+ device_del(&c->device);
+
/* Ask the IOP to switch to RESET state */
i2o_iop_reset(c);
+
+ put_device(&c->device);
}
/**
@@ -927,8 +873,7 @@ static int i2o_systab_build(void)
systab = i2o_systab.virt = kmalloc(i2o_systab.len, GFP_KERNEL);
if (!systab) {
- printk(KERN_ERR "i2o: unable to allocate memory for System "
- "Table\n");
+ osm_err("unable to allocate memory for System Table\n");
return -ENOMEM;
}
memset(systab, 0, i2o_systab.len);
@@ -940,8 +885,8 @@ static int i2o_systab_build(void)
i2o_status_block *sb;
if (count >= num_controllers) {
- printk(KERN_ERR "i2o: controller added while building "
- "system table\n");
+ osm_err("controller added while building system table"
+ "\n");
break;
}
@@ -955,9 +900,8 @@ static int i2o_systab_build(void)
* it is techninically not part of the I2O subsystem...
*/
if (unlikely(i2o_status_get(c))) {
- printk(KERN_ERR "%s: Deleting b/c could not get status"
- " while attempting to build system table\n",
- c->name);
+ osm_err("%s: Deleting b/c could not get status while "
+ "attempting to build system table\n", c->name);
i2o_iop_remove(c);
continue; // try the next one
}
@@ -971,8 +915,10 @@ static int i2o_systab_build(void)
systab->iops[count].frame_size = sb->inbound_frame_size;
systab->iops[count].last_changed = change_ind;
systab->iops[count].iop_capabilities = sb->iop_capabilities;
- systab->iops[count].inbound_low = i2o_ptr_low(c->post_port);
- systab->iops[count].inbound_high = i2o_ptr_high(c->post_port);
+ systab->iops[count].inbound_low =
+ i2o_dma_low(c->base.phys + I2O_IN_PORT);
+ systab->iops[count].inbound_high =
+ i2o_dma_high(c->base.phys + I2O_IN_PORT);
count++;
}
@@ -1010,11 +956,11 @@ int i2o_status_get(struct i2o_controller *c)
{
struct i2o_message __iomem *msg;
u32 m;
- u8 *status_block;
+ volatile u8 *status_block;
unsigned long timeout;
status_block = (u8 *) c->status_block.virt;
- memset(status_block, 0, sizeof(i2o_status_block));
+ memset(c->status_block.virt, 0, sizeof(i2o_status_block));
m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
if (m == I2O_QUEUE_EMPTY)
@@ -1027,8 +973,8 @@ int i2o_status_get(struct i2o_controller *c)
writel(0, &msg->u.s.tcntxt); // FIXME: use resonable transaction context
writel(0, &msg->body[0]);
writel(0, &msg->body[1]);
- writel(i2o_ptr_low((void *)c->status_block.phys), &msg->body[2]);
- writel(i2o_ptr_high((void *)c->status_block.phys), &msg->body[3]);
+ writel(i2o_dma_low(c->status_block.phys), &msg->body[2]);
+ writel(i2o_dma_high(c->status_block.phys), &msg->body[3]);
writel(sizeof(i2o_status_block), &msg->body[4]); /* always 88 bytes */
i2o_msg_post(c, m);
@@ -1037,14 +983,12 @@ int i2o_status_get(struct i2o_controller *c)
timeout = jiffies + I2O_TIMEOUT_STATUS_GET * HZ;
while (status_block[87] != 0xFF) {
if (time_after(jiffies, timeout)) {
- printk(KERN_ERR "%s: Get status timeout.\n", c->name);
+ osm_err("%s: Get status timeout.\n", c->name);
return -ETIMEDOUT;
}
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
-
- rmb();
}
#ifdef DEBUG
@@ -1088,8 +1032,8 @@ static int i2o_hrt_get(struct i2o_controller *c)
rc = i2o_msg_post_wait_mem(c, m, 20, &c->hrt);
if (rc < 0) {
- printk(KERN_ERR "%s: Unable to get HRT (status=%#x)\n",
- c->name, -rc);
+ osm_err("%s: Unable to get HRT (status=%#x)\n", c->name,
+ -rc);
return rc;
}
@@ -1103,13 +1047,41 @@ static int i2o_hrt_get(struct i2o_controller *c)
return i2o_parse_hrt(c);
}
- printk(KERN_ERR "%s: Unable to get HRT after %d tries, giving up\n",
- c->name, I2O_HRT_GET_TRIES);
+ osm_err("%s: Unable to get HRT after %d tries, giving up\n", c->name,
+ I2O_HRT_GET_TRIES);
return -EBUSY;
}
/**
+ * i2o_iop_free - Free the i2o_controller struct
+ * @c: I2O controller to free
+ */
+void i2o_iop_free(struct i2o_controller *c)
+{
+ kfree(c);
+};
+
+/**
+ * i2o_iop_release - release the memory for a I2O controller
+ * @dev: I2O controller which should be released
+ *
+ * Release the allocated memory. This function is called if refcount of
+ * device reaches 0 automatically.
+ */
+static void i2o_iop_release(struct device *dev)
+{
+ struct i2o_controller *c = to_i2o_controller(dev);
+
+ i2o_iop_free(c);
+};
+
+/* I2O controller class */
+static struct class i2o_controller_class = {
+ .name = "i2o_controller",
+};
+
+/**
* i2o_iop_alloc - Allocate and initialize a i2o_controller struct
*
* Allocate the necessary memory for a i2o_controller struct and
@@ -1125,8 +1097,8 @@ struct i2o_controller *i2o_iop_alloc(void)
c = kmalloc(sizeof(*c), GFP_KERNEL);
if (!c) {
- printk(KERN_ERR "i2o: Insufficient memory to allocate a I2O "
- "controller.\n");
+ osm_err("i2o: Insufficient memory to allocate a I2O controller."
+ "\n");
return ERR_PTR(-ENOMEM);
}
memset(c, 0, sizeof(*c));
@@ -1137,6 +1109,16 @@ struct i2o_controller *i2o_iop_alloc(void)
c->unit = unit++;
sprintf(c->name, "iop%d", c->unit);
+ device_initialize(&c->device);
+ class_device_initialize(&c->classdev);
+
+ c->device.release = &i2o_iop_release;
+ c->classdev.class = &i2o_controller_class;
+ c->classdev.dev = &c->device;
+
+ snprintf(c->device.bus_id, BUS_ID_SIZE, "iop%d", c->unit);
+ snprintf(c->classdev.class_id, BUS_ID_SIZE, "iop%d", c->unit);
+
#if BITS_PER_LONG == 64
spin_lock_init(&c->context_list_lock);
atomic_set(&c->context_list_counter, 0);
@@ -1147,15 +1129,6 @@ struct i2o_controller *i2o_iop_alloc(void)
};
/**
- * i2o_iop_free - Free the i2o_controller struct
- * @c: I2O controller to free
- */
-void i2o_iop_free(struct i2o_controller *c)
-{
- kfree(c);
-};
-
-/**
* i2o_iop_add - Initialize the I2O controller and add him to the I2O core
* @c: controller
*
@@ -1168,45 +1141,58 @@ int i2o_iop_add(struct i2o_controller *c)
{
int rc;
- printk(KERN_INFO "%s: Activating I2O controller...\n", c->name);
- printk(KERN_INFO "%s: This may take a few minutes if there are many "
- "devices\n", c->name);
+ if ((rc = device_add(&c->device))) {
+ osm_err("%s: could not add controller\n", c->name);
+ goto iop_reset;
+ }
- if ((rc = i2o_iop_activate(c))) {
- printk(KERN_ERR "%s: could not activate controller\n",
- c->name);
- i2o_iop_reset(c);
- return rc;
+ if ((rc = class_device_add(&c->classdev))) {
+ osm_err("%s: could not add controller class\n", c->name);
+ goto device_del;
}
- pr_debug("%s: building sys table...\n", c->name);
+ osm_info("%s: Activating I2O controller...\n", c->name);
+ osm_info("%s: This may take a few minutes if there are many devices\n",
+ c->name);
- if ((rc = i2o_systab_build())) {
- i2o_iop_reset(c);
- return rc;
+ if ((rc = i2o_iop_activate(c))) {
+ osm_err("%s: could not activate controller\n", c->name);
+ goto class_del;
}
- pr_debug("%s: online controller...\n", c->name);
+ osm_debug("%s: building sys table...\n", c->name);
- if ((rc = i2o_iop_online(c))) {
- i2o_iop_reset(c);
- return rc;
- }
+ if ((rc = i2o_systab_build()))
+ goto class_del;
- pr_debug("%s: getting LCT...\n", c->name);
+ osm_debug("%s: online controller...\n", c->name);
- if ((rc = i2o_exec_lct_get(c))) {
- i2o_iop_reset(c);
- return rc;
- }
+ if ((rc = i2o_iop_online(c)))
+ goto class_del;
+
+ osm_debug("%s: getting LCT...\n", c->name);
+
+ if ((rc = i2o_exec_lct_get(c)))
+ goto class_del;
list_add(&c->list, &i2o_controllers);
i2o_driver_notify_controller_add_all(c);
- printk(KERN_INFO "%s: Controller added\n", c->name);
+ osm_info("%s: Controller added\n", c->name);
return 0;
+
+ class_del:
+ class_device_del(&c->classdev);
+
+ device_del:
+ device_del(&c->device);
+
+ iop_reset:
+ i2o_iop_reset(c);
+
+ return rc;
};
/**
@@ -1264,16 +1250,18 @@ static int __init i2o_iop_init(void)
if (rc)
goto exit;
- rc = i2o_driver_init();
- if (rc)
+ if ((rc = class_register(&i2o_controller_class))) {
+ osm_err("can't register class i2o_controller\n");
goto device_exit;
+ }
- rc = i2o_exec_init();
- if (rc)
+ if ((rc = i2o_driver_init()))
+ goto class_exit;
+
+ if ((rc = i2o_exec_init()))
goto driver_exit;
- rc = i2o_pci_init();
- if (rc < 0)
+ if ((rc = i2o_pci_init()))
goto exec_exit;
return 0;
@@ -1284,6 +1272,9 @@ static int __init i2o_iop_init(void)
driver_exit:
i2o_driver_exit();
+ class_exit:
+ class_unregister(&i2o_controller_class);
+
device_exit:
i2o_device_exit();
@@ -1301,6 +1292,7 @@ static void __exit i2o_iop_exit(void)
i2o_pci_exit();
i2o_exec_exit();
i2o_driver_exit();
+ class_unregister(&i2o_controller_class);
i2o_device_exit();
};
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
index e772752f056..7a60fd7be8a 100644
--- a/drivers/message/i2o/pci.c
+++ b/drivers/message/i2o/pci.c
@@ -30,53 +30,18 @@
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/i2o.h>
-
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif // CONFIG_MTRR
-
-/* Module internal functions from other sources */
-extern struct i2o_controller *i2o_iop_alloc(void);
-extern void i2o_iop_free(struct i2o_controller *);
-
-extern int i2o_iop_add(struct i2o_controller *);
-extern void i2o_iop_remove(struct i2o_controller *);
-
-extern int i2o_driver_dispatch(struct i2o_controller *, u32,
- struct i2o_message *);
+#include "core.h"
/* PCI device id table for all I2O controllers */
static struct pci_device_id __devinitdata i2o_pci_ids[] = {
{PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)},
{PCI_DEVICE(PCI_VENDOR_ID_DPT, 0xa511)},
+ {.vendor = PCI_VENDOR_ID_INTEL,.device = 0x1962,
+ .subvendor = PCI_VENDOR_ID_PROMISE,.subdevice = PCI_ANY_ID},
{0}
};
/**
- * i2o_dma_realloc - Realloc DMA memory
- * @dev: struct device pointer to the PCI device of the I2O controller
- * @addr: pointer to a i2o_dma struct DMA buffer
- * @len: new length of memory
- * @gfp_mask: GFP mask
- *
- * If there was something allocated in the addr, free it first. If len > 0
- * than try to allocate it and write the addresses back to the addr
- * structure. If len == 0 set the virtual address to NULL.
- *
- * Returns the 0 on success or negative error code on failure.
- */
-int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr, size_t len,
- unsigned int gfp_mask)
-{
- i2o_dma_free(dev, addr);
-
- if (len)
- return i2o_dma_alloc(dev, addr, len, gfp_mask);
-
- return 0;
-};
-
-/**
* i2o_pci_free - Frees the DMA memory for the I2O controller
* @c: I2O controller to free
*
@@ -91,19 +56,11 @@ static void i2o_pci_free(struct i2o_controller *c)
i2o_dma_free(dev, &c->out_queue);
i2o_dma_free(dev, &c->status_block);
- if (c->lct)
- kfree(c->lct);
+ kfree(c->lct);
i2o_dma_free(dev, &c->dlct);
i2o_dma_free(dev, &c->hrt);
i2o_dma_free(dev, &c->status);
-#ifdef CONFIG_MTRR
- if (c->mtrr_reg0 >= 0)
- mtrr_del(c->mtrr_reg0, 0, 0);
- if (c->mtrr_reg1 >= 0)
- mtrr_del(c->mtrr_reg1, 0, 0);
-#endif
-
if (c->raptor && c->in_queue.virt)
iounmap(c->in_queue.virt);
@@ -178,14 +135,15 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
c->name, (unsigned long)c->base.phys,
(unsigned long)c->base.len);
- c->base.virt = ioremap(c->base.phys, c->base.len);
+ c->base.virt = ioremap_nocache(c->base.phys, c->base.len);
if (!c->base.virt) {
printk(KERN_ERR "%s: Unable to map controller.\n", c->name);
return -ENOMEM;
}
if (c->raptor) {
- c->in_queue.virt = ioremap(c->in_queue.phys, c->in_queue.len);
+ c->in_queue.virt =
+ ioremap_nocache(c->in_queue.phys, c->in_queue.len);
if (!c->in_queue.virt) {
printk(KERN_ERR "%s: Unable to map controller.\n",
c->name);
@@ -195,43 +153,10 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
} else
c->in_queue = c->base;
- c->irq_mask = c->base.virt + 0x34;
- c->post_port = c->base.virt + 0x40;
- c->reply_port = c->base.virt + 0x44;
-
-#ifdef CONFIG_MTRR
- /* Enable Write Combining MTRR for IOP's memory region */
- c->mtrr_reg0 = mtrr_add(c->in_queue.phys, c->in_queue.len,
- MTRR_TYPE_WRCOMB, 1);
- c->mtrr_reg1 = -1;
-
- if (c->mtrr_reg0 < 0)
- printk(KERN_WARNING "%s: could not enable write combining "
- "MTRR\n", c->name);
- else
- printk(KERN_INFO "%s: using write combining MTRR\n", c->name);
-
- /*
- * If it is an INTEL i960 I/O processor then set the first 64K to
- * Uncacheable since the region contains the messaging unit which
- * shouldn't be cached.
- */
- if ((pdev->vendor == PCI_VENDOR_ID_INTEL ||
- pdev->vendor == PCI_VENDOR_ID_DPT) && !c->raptor) {
- printk(KERN_INFO "%s: MTRR workaround for Intel i960 processor"
- "\n", c->name);
- c->mtrr_reg1 = mtrr_add(c->base.phys, 0x10000,
- MTRR_TYPE_UNCACHABLE, 1);
-
- if (c->mtrr_reg1 < 0) {
- printk(KERN_WARNING "%s: Error in setting "
- "MTRR_TYPE_UNCACHABLE\n", c->name);
- mtrr_del(c->mtrr_reg0, c->in_queue.phys,
- c->in_queue.len);
- c->mtrr_reg0 = -1;
- }
- }
-#endif
+ c->irq_status = c->base.virt + I2O_IRQ_STATUS;
+ c->irq_mask = c->base.virt + I2O_IRQ_MASK;
+ c->in_port = c->base.virt + I2O_IN_PORT;
+ c->out_port = c->base.virt + I2O_OUT_PORT;
if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) {
i2o_pci_free(c);
@@ -254,7 +179,10 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
return -ENOMEM;
}
- if (i2o_dma_alloc(dev, &c->out_queue, MSG_POOL_SIZE, GFP_KERNEL)) {
+ if (i2o_dma_alloc
+ (dev, &c->out_queue,
+ I2O_MAX_OUTBOUND_MSG_FRAMES * I2O_OUTBOUND_MSG_FRAME_SIZE *
+ sizeof(u32), GFP_KERNEL)) {
i2o_pci_free(c);
return -ENOMEM;
}
@@ -276,51 +204,30 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r)
{
struct i2o_controller *c = dev_id;
- struct device *dev = &c->pdev->dev;
- struct i2o_message *m;
- u32 mv;
-
- /*
- * Old 960 steppings had a bug in the I2O unit that caused
- * the queue to appear empty when it wasn't.
- */
- mv = I2O_REPLY_READ32(c);
- if (mv == I2O_QUEUE_EMPTY) {
- mv = I2O_REPLY_READ32(c);
- if (unlikely(mv == I2O_QUEUE_EMPTY)) {
- return IRQ_NONE;
- } else
- pr_debug("%s: 960 bug detected\n", c->name);
- }
-
- while (mv != I2O_QUEUE_EMPTY) {
- /*
- * Map the message from the page frame map to kernel virtual.
- * Because bus_to_virt is deprecated, we have calculate the
- * location by ourself!
- */
- m = i2o_msg_out_to_virt(c, mv);
-
- /*
- * Ensure this message is seen coherently but cachably by
- * the processor
- */
- dma_sync_single_for_cpu(dev, mv, MSG_FRAME_SIZE * 4,
- PCI_DMA_FROMDEVICE);
+ u32 m;
+ irqreturn_t rc = IRQ_NONE;
+
+ while (readl(c->irq_status) & I2O_IRQ_OUTBOUND_POST) {
+ m = readl(c->out_port);
+ if (m == I2O_QUEUE_EMPTY) {
+ /*
+ * Old 960 steppings had a bug in the I2O unit that
+ * caused the queue to appear empty when it wasn't.
+ */
+ m = readl(c->out_port);
+ if (unlikely(m == I2O_QUEUE_EMPTY))
+ break;
+ }
/* dispatch it */
- if (i2o_driver_dispatch(c, mv, m))
+ if (i2o_driver_dispatch(c, m))
/* flush it if result != 0 */
- i2o_flush_reply(c, mv);
+ i2o_flush_reply(c, m);
- /*
- * That 960 bug again...
- */
- mv = I2O_REPLY_READ32(c);
- if (mv == I2O_QUEUE_EMPTY)
- mv = I2O_REPLY_READ32(c);
+ rc = IRQ_HANDLED;
}
- return IRQ_HANDLED;
+
+ return rc;
}
/**
@@ -336,7 +243,7 @@ static int i2o_pci_irq_enable(struct i2o_controller *c)
struct pci_dev *pdev = c->pdev;
int rc;
- I2O_IRQ_WRITE32(c, 0xffffffff);
+ writel(0xffffffff, c->irq_mask);
if (pdev->irq) {
rc = request_irq(pdev->irq, i2o_pci_interrupt, SA_SHIRQ,
@@ -348,7 +255,7 @@ static int i2o_pci_irq_enable(struct i2o_controller *c)
}
}
- I2O_IRQ_WRITE32(c, 0x00000000);
+ writel(0x00000000, c->irq_mask);
printk(KERN_INFO "%s: Installed at IRQ %d\n", c->name, pdev->irq);
@@ -363,7 +270,7 @@ static int i2o_pci_irq_enable(struct i2o_controller *c)
*/
static void i2o_pci_irq_disable(struct i2o_controller *c)
{
- I2O_IRQ_WRITE32(c, 0xffffffff);
+ writel(0xffffffff, c->irq_mask);
if (c->pdev->irq > 0)
free_irq(c->pdev->irq, c);
@@ -385,28 +292,25 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
{
struct i2o_controller *c;
int rc;
+ struct pci_dev *i960 = NULL;
printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n");
if ((pdev->class & 0xff) > 1) {
- printk(KERN_WARNING "i2o: I2O controller found but does not "
- "support I2O 1.5 (skipping).\n");
+ printk(KERN_WARNING "i2o: %s does not support I2O 1.5 "
+ "(skipping).\n", pci_name(pdev));
return -ENODEV;
}
if ((rc = pci_enable_device(pdev))) {
- printk(KERN_WARNING "i2o: I2O controller found but could not be"
- " enabled.\n");
+ printk(KERN_WARNING "i2o: couldn't enable device %s\n",
+ pci_name(pdev));
return rc;
}
- printk(KERN_INFO "i2o: I2O controller found on bus %d at %d.\n",
- pdev->bus->number, pdev->devfn);
-
if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
- printk(KERN_WARNING "i2o: I2O controller on bus %d at %d: No "
- "suitable DMA available!\n", pdev->bus->number,
- pdev->devfn);
+ printk(KERN_WARNING "i2o: no suitable DMA found for %s\n",
+ pci_name(pdev));
rc = -ENODEV;
goto disable;
}
@@ -415,14 +319,16 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
c = i2o_iop_alloc();
if (IS_ERR(c)) {
- printk(KERN_ERR "i2o: memory for I2O controller could not be "
- "allocated\n");
+ printk(KERN_ERR "i2o: couldn't allocate memory for %s\n",
+ pci_name(pdev));
rc = PTR_ERR(c);
goto disable;
- }
+ } else
+ printk(KERN_INFO "%s: controller found (%s)\n", c->name,
+ pci_name(pdev));
c->pdev = pdev;
- c->device = pdev->dev;
+ c->device.parent = get_device(&pdev->dev);
/* Cards that fall apart if you hit them with large I/O loads... */
if (pdev->vendor == PCI_VENDOR_ID_NCR && pdev->device == 0x0630) {
@@ -432,16 +338,48 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
}
if (pdev->subsystem_vendor == PCI_VENDOR_ID_PROMISE) {
+ /*
+ * Expose the ship behind i960 for initialization, or it will
+ * failed
+ */
+ i960 =
+ pci_find_slot(c->pdev->bus->number,
+ PCI_DEVFN(PCI_SLOT(c->pdev->devfn), 0));
+
+ if (i960)
+ pci_write_config_word(i960, 0x42, 0);
+
c->promise = 1;
- printk(KERN_INFO "%s: Promise workarounds activated.\n",
- c->name);
+ c->limit_sectors = 1;
}
+ if (pdev->subsystem_vendor == PCI_VENDOR_ID_DPT)
+ c->adaptec = 1;
+
/* Cards that go bananas if you quiesce them before you reset them. */
if (pdev->vendor == PCI_VENDOR_ID_DPT) {
c->no_quiesce = 1;
if (pdev->device == 0xa511)
c->raptor = 1;
+
+ if (pdev->subsystem_device == 0xc05a) {
+ c->limit_sectors = 1;
+ printk(KERN_INFO
+ "%s: limit sectors per request to %d\n", c->name,
+ I2O_MAX_SECTORS_LIMITED);
+ }
+#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
+ if (sizeof(dma_addr_t) > 4) {
+ if (pci_set_dma_mask(pdev, DMA_64BIT_MASK))
+ printk(KERN_INFO "%s: 64-bit DMA unavailable\n",
+ c->name);
+ else {
+ c->pae_support = 1;
+ printk(KERN_INFO "%s: using 64-bit DMA\n",
+ c->name);
+ }
+ }
+#endif
}
if ((rc = i2o_pci_alloc(c))) {
@@ -459,6 +397,11 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
if ((rc = i2o_iop_add(c)))
goto uninstall;
+ get_device(&c->device);
+
+ if (i960)
+ pci_write_config_word(i960, 0x42, 0x03ff);
+
return 0;
uninstall:
@@ -469,6 +412,7 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
free_controller:
i2o_iop_free(c);
+ put_device(c->device.parent);
disable:
pci_disable_device(pdev);
@@ -492,15 +436,17 @@ static void __devexit i2o_pci_remove(struct pci_dev *pdev)
i2o_pci_irq_disable(c);
i2o_pci_free(c);
+ pci_disable_device(pdev);
+
printk(KERN_INFO "%s: Controller removed.\n", c->name);
- i2o_iop_free(c);
- pci_disable_device(pdev);
+ put_device(c->device.parent);
+ put_device(&c->device);
};
/* PCI driver for I2O controller */
static struct pci_driver i2o_pci_driver = {
- .name = "I2O controller",
+ .name = "PCI_I2O",
.id_table = i2o_pci_ids,
.probe = i2o_pci_probe,
.remove = __devexit_p(i2o_pci_remove),
@@ -523,6 +469,4 @@ void __exit i2o_pci_exit(void)
{
pci_unregister_driver(&i2o_pci_driver);
};
-
-EXPORT_SYMBOL(i2o_dma_realloc);
MODULE_DEVICE_TABLE(pci, i2o_pci_ids);
diff --git a/drivers/misc/ibmasm/command.c b/drivers/misc/ibmasm/command.c
index 245b0058381..07a085ccbd5 100644
--- a/drivers/misc/ibmasm/command.c
+++ b/drivers/misc/ibmasm/command.c
@@ -23,6 +23,7 @@
*/
#include "ibmasm.h"
+#include "lowlevel.h"
static void exec_next_command(struct service_processor *sp);
static void free_command(struct kobject *kobj);
@@ -31,8 +32,9 @@ static struct kobj_type ibmasm_cmd_kobj_type = {
.release = free_command,
};
+static atomic_t command_count = ATOMIC_INIT(0);
-struct command *ibmasm_new_command(size_t buffer_size)
+struct command *ibmasm_new_command(struct service_processor *sp, size_t buffer_size)
{
struct command *cmd;
@@ -55,11 +57,15 @@ struct command *ibmasm_new_command(size_t buffer_size)
kobject_init(&cmd->kobj);
cmd->kobj.ktype = &ibmasm_cmd_kobj_type;
+ cmd->lock = &sp->lock;
cmd->status = IBMASM_CMD_PENDING;
init_waitqueue_head(&cmd->wait);
INIT_LIST_HEAD(&cmd->queue_node);
+ atomic_inc(&command_count);
+ dbg("command count: %d\n", atomic_read(&command_count));
+
return cmd;
}
@@ -68,6 +74,8 @@ static void free_command(struct kobject *kobj)
struct command *cmd = to_command(kobj);
list_del(&cmd->queue_node);
+ atomic_dec(&command_count);
+ dbg("command count: %d\n", atomic_read(&command_count));
kfree(cmd->buffer);
kfree(cmd);
}
@@ -94,8 +102,14 @@ static struct command *dequeue_command(struct service_processor *sp)
static inline void do_exec_command(struct service_processor *sp)
{
+ char tsbuf[32];
+
+ dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
+
if (ibmasm_send_i2o_message(sp)) {
sp->current_command->status = IBMASM_CMD_FAILED;
+ wake_up(&sp->current_command->wait);
+ command_put(sp->current_command);
exec_next_command(sp);
}
}
@@ -111,14 +125,16 @@ static inline void do_exec_command(struct service_processor *sp)
void ibmasm_exec_command(struct service_processor *sp, struct command *cmd)
{
unsigned long flags;
+ char tsbuf[32];
+
+ dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
spin_lock_irqsave(&sp->lock, flags);
if (!sp->current_command) {
- command_get(cmd);
sp->current_command = cmd;
+ command_get(sp->current_command);
spin_unlock_irqrestore(&sp->lock, flags);
-
do_exec_command(sp);
} else {
enqueue_command(sp, cmd);
@@ -129,9 +145,9 @@ void ibmasm_exec_command(struct service_processor *sp, struct command *cmd)
static void exec_next_command(struct service_processor *sp)
{
unsigned long flags;
+ char tsbuf[32];
- wake_up(&sp->current_command->wait);
- command_put(sp->current_command);
+ dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
spin_lock_irqsave(&sp->lock, flags);
sp->current_command = dequeue_command(sp);
@@ -169,7 +185,9 @@ void ibmasm_receive_command_response(struct service_processor *sp, void *respons
if (!sp->current_command)
return;
- memcpy(cmd->buffer, response, min(size, cmd->buffer_size));
+ memcpy_fromio(cmd->buffer, response, min(size, cmd->buffer_size));
cmd->status = IBMASM_CMD_COMPLETE;
+ wake_up(&sp->current_command->wait);
+ command_put(sp->current_command);
exec_next_command(sp);
}
diff --git a/drivers/misc/ibmasm/dot_command.c b/drivers/misc/ibmasm/dot_command.c
index 478a8d898fc..13c52f866e2 100644
--- a/drivers/misc/ibmasm/dot_command.c
+++ b/drivers/misc/ibmasm/dot_command.c
@@ -33,7 +33,13 @@ void ibmasm_receive_message(struct service_processor *sp, void *message, int mes
u32 size;
struct dot_command_header *header = (struct dot_command_header *)message;
+ if (message_size == 0)
+ return;
+
size = get_dot_command_size(message);
+ if (size == 0)
+ return;
+
if (size > message_size)
size = message_size;
@@ -67,7 +73,7 @@ int ibmasm_send_driver_vpd(struct service_processor *sp)
u8 *vpd_data;
int result = 0;
- command = ibmasm_new_command(INIT_BUFFER_SIZE);
+ command = ibmasm_new_command(sp, INIT_BUFFER_SIZE);
if (command == NULL)
return -ENOMEM;
@@ -121,7 +127,7 @@ int ibmasm_send_os_state(struct service_processor *sp, int os_state)
struct os_state_command *os_state_cmd;
int result = 0;
- cmd = ibmasm_new_command(sizeof(struct os_state_command));
+ cmd = ibmasm_new_command(sp, sizeof(struct os_state_command));
if (cmd == NULL)
return -ENOMEM;
diff --git a/drivers/misc/ibmasm/event.c b/drivers/misc/ibmasm/event.c
index e100f34f158..fe1e819235a 100644
--- a/drivers/misc/ibmasm/event.c
+++ b/drivers/misc/ibmasm/event.c
@@ -23,6 +23,7 @@
*/
#include "ibmasm.h"
+#include "lowlevel.h"
/*
* ASM service processor event handling routines.
@@ -34,7 +35,6 @@
* circular buffer.
*/
-
static void wake_up_event_readers(struct service_processor *sp)
{
struct event_reader *reader;
@@ -63,7 +63,7 @@ void ibmasm_receive_event(struct service_processor *sp, void *data, unsigned int
spin_lock_irqsave(&sp->lock, flags);
/* copy the event into the next slot in the circular buffer */
event = &buffer->events[buffer->next_index];
- memcpy(event->data, data, data_size);
+ memcpy_fromio(event->data, data, data_size);
event->data_size = data_size;
event->serial_number = buffer->next_serial_number;
@@ -93,7 +93,10 @@ int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *rea
unsigned int index;
unsigned long flags;
- if (wait_event_interruptible(reader->wait, event_available(buffer, reader)))
+ reader->cancelled = 0;
+
+ if (wait_event_interruptible(reader->wait,
+ event_available(buffer, reader) || reader->cancelled))
return -ERESTARTSYS;
if (!event_available(buffer, reader))
@@ -116,6 +119,12 @@ int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *rea
return event->data_size;
}
+void ibmasm_cancel_next_event(struct event_reader *reader)
+{
+ reader->cancelled = 1;
+ wake_up_interruptible(&reader->wait);
+}
+
void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader)
{
unsigned long flags;
@@ -131,8 +140,6 @@ void ibmasm_event_reader_unregister(struct service_processor *sp, struct event_r
{
unsigned long flags;
- wake_up_interruptible(&reader->wait);
-
spin_lock_irqsave(&sp->lock, flags);
list_del(&reader->node);
spin_unlock_irqrestore(&sp->lock, flags);
@@ -164,6 +171,5 @@ int ibmasm_event_buffer_init(struct service_processor *sp)
void ibmasm_event_buffer_exit(struct service_processor *sp)
{
- wake_up_event_readers(sp);
kfree(sp->event_buffer);
}
diff --git a/drivers/misc/ibmasm/heartbeat.c b/drivers/misc/ibmasm/heartbeat.c
index ce09309174d..f295401fac2 100644
--- a/drivers/misc/ibmasm/heartbeat.c
+++ b/drivers/misc/ibmasm/heartbeat.c
@@ -25,6 +25,7 @@
#include <linux/notifier.h>
#include "ibmasm.h"
#include "dot_command.h"
+#include "lowlevel.h"
static int suspend_heartbeats = 0;
@@ -62,7 +63,7 @@ void ibmasm_unregister_panic_notifier(void)
int ibmasm_heartbeat_init(struct service_processor *sp)
{
- sp->heartbeat = ibmasm_new_command(HEARTBEAT_BUFFER_SIZE);
+ sp->heartbeat = ibmasm_new_command(sp, HEARTBEAT_BUFFER_SIZE);
if (sp->heartbeat == NULL)
return -ENOMEM;
@@ -71,6 +72,12 @@ int ibmasm_heartbeat_init(struct service_processor *sp)
void ibmasm_heartbeat_exit(struct service_processor *sp)
{
+ char tsbuf[32];
+
+ dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
+ ibmasm_wait_for_response(sp->heartbeat, IBMASM_CMD_TIMEOUT_NORMAL);
+ dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
+ suspend_heartbeats = 1;
command_put(sp->heartbeat);
}
@@ -78,14 +85,16 @@ void ibmasm_receive_heartbeat(struct service_processor *sp, void *message, size
{
struct command *cmd = sp->heartbeat;
struct dot_command_header *header = (struct dot_command_header *)cmd->buffer;
+ char tsbuf[32];
+ dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
if (suspend_heartbeats)
return;
/* return the received dot command to sender */
cmd->status = IBMASM_CMD_PENDING;
size = min(size, cmd->buffer_size);
- memcpy(cmd->buffer, message, size);
+ memcpy_fromio(cmd->buffer, message, size);
header->type = sp_write;
ibmasm_exec_command(sp, cmd);
}
diff --git a/drivers/misc/ibmasm/ibmasm.h b/drivers/misc/ibmasm/ibmasm.h
index 6fec7fd8cd1..ecce4ffd3e2 100644
--- a/drivers/misc/ibmasm/ibmasm.h
+++ b/drivers/misc/ibmasm/ibmasm.h
@@ -34,16 +34,31 @@
#include <linux/version.h>
#include <linux/interrupt.h>
#include <linux/device.h>
+#include <linux/input.h>
/* Driver identification */
#define DRIVER_NAME "ibmasm"
-#define DRIVER_VERSION "0.4"
-#define DRIVER_AUTHOR "Max Asbock"
+#define DRIVER_VERSION "1.0"
+#define DRIVER_AUTHOR "Max Asbock <masbock@us.ibm.com>, Vernon Mauery <vernux@us.ibm.com>"
#define DRIVER_DESC "IBM ASM Service Processor Driver"
#define err(msg) printk(KERN_ERR "%s: " msg "\n", DRIVER_NAME)
#define info(msg) printk(KERN_INFO "%s: " msg "\n", DRIVER_NAME)
+extern int ibmasm_debug;
+#define dbg(STR, ARGS...) \
+ do { \
+ if (ibmasm_debug) \
+ printk(KERN_DEBUG STR , ##ARGS); \
+ } while (0)
+
+static inline char *get_timestamp(char *buf)
+{
+ struct timeval now;
+ do_gettimeofday(&now);
+ sprintf(buf, "%lu.%lu", now.tv_sec, now.tv_usec);
+ return buf;
+}
#define IBMASM_CMD_PENDING 0
#define IBMASM_CMD_COMPLETE 1
@@ -52,7 +67,7 @@
#define IBMASM_CMD_TIMEOUT_NORMAL 45
#define IBMASM_CMD_TIMEOUT_EXTRA 240
-#define IBMASM_CMD_MAX_BUFFER_SIZE 0x4000
+#define IBMASM_CMD_MAX_BUFFER_SIZE 0x8000
#define REVERSE_HEARTBEAT_TIMEOUT 120
@@ -80,12 +95,17 @@ struct command {
size_t buffer_size;
int status;
struct kobject kobj;
+ spinlock_t *lock;
};
#define to_command(c) container_of(c, struct command, kobj)
static inline void command_put(struct command *cmd)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(cmd->lock, flags);
kobject_put(&cmd->kobj);
+ spin_unlock_irqrestore(cmd->lock, flags);
}
static inline void command_get(struct command *cmd)
@@ -108,6 +128,7 @@ struct event_buffer {
};
struct event_reader {
+ int cancelled;
unsigned int next_serial_number;
wait_queue_head_t wait;
struct list_head node;
@@ -120,41 +141,11 @@ struct reverse_heartbeat {
unsigned int stopped;
};
-
-/* remote console events */
-struct mouse_event {
- long x;
- long y;
- unsigned char buttons;
- unsigned char transitions;
-};
-
-struct keyboard_event {
- unsigned long key_code;
- unsigned char key_down;
+struct ibmasm_remote {
+ struct input_dev keybd_dev;
+ struct input_dev mouse_dev;
};
-struct remote_event {
- unsigned long type;
- union {
- struct mouse_event mouse;
- struct keyboard_event keyboard;
- } data;
-};
-
-#define DRIVER_REMOTE_QUEUE_SIZE 240
-
-struct remote_queue {
- struct remote_event *start;
- struct remote_event *end;
- struct remote_event *reader;
- struct remote_event *writer;
- unsigned int size;
- int open;
- wait_queue_head_t wait;
-};
-
-
struct service_processor {
struct list_head node;
spinlock_t lock;
@@ -167,13 +158,13 @@ struct service_processor {
char dirname[IBMASM_NAME_SIZE];
char devname[IBMASM_NAME_SIZE];
unsigned int number;
- struct remote_queue remote_queue;
+ struct ibmasm_remote *remote;
int serial_line;
struct device *dev;
};
/* command processing */
-extern struct command *ibmasm_new_command(size_t buffer_size);
+extern struct command *ibmasm_new_command(struct service_processor *sp, size_t buffer_size);
extern void ibmasm_exec_command(struct service_processor *sp, struct command *cmd);
extern void ibmasm_wait_for_response(struct command *cmd, int timeout);
extern void ibmasm_receive_command_response(struct service_processor *sp, void *response, size_t size);
@@ -185,6 +176,7 @@ extern void ibmasm_receive_event(struct service_processor *sp, void *data, unsi
extern void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader);
extern void ibmasm_event_reader_unregister(struct service_processor *sp, struct event_reader *reader);
extern int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *reader);
+extern void ibmasm_cancel_next_event(struct event_reader *reader);
/* heartbeat - from SP to OS */
extern void ibmasm_register_panic_notifier(void);
@@ -208,11 +200,9 @@ extern int ibmasm_send_i2o_message(struct service_processor *sp);
extern irqreturn_t ibmasm_interrupt_handler(int irq, void * dev_id, struct pt_regs *regs);
/* remote console */
-extern void ibmasm_handle_mouse_interrupt(struct service_processor *sp);
-extern int ibmasm_init_remote_queue(struct service_processor *sp);
-extern void ibmasm_free_remote_queue(struct service_processor *sp);
-extern void ibmasm_advance_reader(struct remote_queue *q, unsigned int n);
-extern size_t ibmasm_events_available(struct remote_queue *q);
+extern void ibmasm_handle_mouse_interrupt(struct service_processor *sp, struct pt_regs *regs);
+extern int ibmasm_init_remote_input_dev(struct service_processor *sp);
+extern void ibmasm_free_remote_input_dev(struct service_processor *sp);
/* file system */
extern int ibmasmfs_register(void);
diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c
index 866e867e68f..5c550fcac2c 100644
--- a/drivers/misc/ibmasm/ibmasmfs.c
+++ b/drivers/misc/ibmasm/ibmasmfs.c
@@ -37,9 +37,7 @@
* | |-- event
* | |-- reverse_heartbeat
* | `-- remote_video
- * | |-- connected
* | |-- depth
- * | |-- events
* | |-- height
* | `-- width
* .
@@ -50,9 +48,7 @@
* |-- event
* |-- reverse_heartbeat
* `-- remote_video
- * |-- connected
* |-- depth
- * |-- events
* |-- height
* `-- width
*
@@ -75,14 +71,6 @@
* remote_video/width: control remote display settings
* write: set value
* read: read value
- *
- * remote_video/connected
- * read: return "1" if web browser VNC java applet is connected,
- * "0" otherwise
- *
- * remote_video/events
- * read: sleep until a remote mouse or keyboard event occurs, then return
- * then event.
*/
#include <linux/fs.h>
@@ -333,7 +321,7 @@ static ssize_t command_file_write(struct file *file, const char __user *ubuff, s
if (command_data->command)
return -EAGAIN;
- cmd = ibmasm_new_command(count);
+ cmd = ibmasm_new_command(command_data->sp, count);
if (!cmd)
return -ENOMEM;
@@ -374,6 +362,7 @@ static int event_file_open(struct inode *inode, struct file *file)
ibmasm_event_reader_register(sp, &event_data->reader);
event_data->sp = sp;
+ event_data->active = 0;
file->private_data = event_data;
return 0;
}
@@ -391,7 +380,9 @@ static ssize_t event_file_read(struct file *file, char __user *buf, size_t count
{
struct ibmasmfs_event_data *event_data = file->private_data;
struct event_reader *reader = &event_data->reader;
+ struct service_processor *sp = event_data->sp;
int ret;
+ unsigned long flags;
if (*offset < 0)
return -EINVAL;
@@ -400,17 +391,32 @@ static ssize_t event_file_read(struct file *file, char __user *buf, size_t count
if (*offset != 0)
return 0;
- ret = ibmasm_get_next_event(event_data->sp, reader);
+ spin_lock_irqsave(&sp->lock, flags);
+ if (event_data->active) {
+ spin_unlock_irqrestore(&sp->lock, flags);
+ return -EBUSY;
+ }
+ event_data->active = 1;
+ spin_unlock_irqrestore(&sp->lock, flags);
+
+ ret = ibmasm_get_next_event(sp, reader);
if (ret <= 0)
- return ret;
+ goto out;
- if (count < reader->data_size)
- return -EINVAL;
+ if (count < reader->data_size) {
+ ret = -EINVAL;
+ goto out;
+ }
- if (copy_to_user(buf, reader->data, reader->data_size))
- return -EFAULT;
+ if (copy_to_user(buf, reader->data, reader->data_size)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ ret = reader->data_size;
- return reader->data_size;
+out:
+ event_data->active = 0;
+ return ret;
}
static ssize_t event_file_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
@@ -424,7 +430,7 @@ static ssize_t event_file_write(struct file *file, const char __user *buf, size_
if (*offset != 0)
return 0;
- wake_up_interruptible(&event_data->reader.wait);
+ ibmasm_cancel_next_event(&event_data->reader);
return 0;
}
@@ -575,75 +581,6 @@ static ssize_t remote_settings_file_write(struct file *file, const char __user *
return count;
}
-static int remote_event_file_open(struct inode *inode, struct file *file)
-{
- struct service_processor *sp;
- unsigned long flags;
- struct remote_queue *q;
-
- file->private_data = inode->u.generic_ip;
- sp = file->private_data;
- q = &sp->remote_queue;
-
- /* allow only one event reader */
- spin_lock_irqsave(&sp->lock, flags);
- if (q->open) {
- spin_unlock_irqrestore(&sp->lock, flags);
- return -EBUSY;
- }
- q->open = 1;
- spin_unlock_irqrestore(&sp->lock, flags);
-
- enable_mouse_interrupts(sp);
-
- return 0;
-}
-
-static int remote_event_file_close(struct inode *inode, struct file *file)
-{
- struct service_processor *sp = file->private_data;
-
- disable_mouse_interrupts(sp);
- wake_up_interruptible(&sp->remote_queue.wait);
- sp->remote_queue.open = 0;
-
- return 0;
-}
-
-static ssize_t remote_event_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
-{
- struct service_processor *sp = file->private_data;
- struct remote_queue *q = &sp->remote_queue;
- size_t data_size;
- struct remote_event *reader = q->reader;
- size_t num_events;
-
- if (*offset < 0)
- return -EINVAL;
- if (count == 0 || count > 1024)
- return 0;
- if (*offset != 0)
- return 0;
-
- if (wait_event_interruptible(q->wait, q->reader != q->writer))
- return -ERESTARTSYS;
-
- /* only get multiples of struct remote_event */
- num_events = min((count/sizeof(struct remote_event)), ibmasm_events_available(q));
- if (!num_events)
- return 0;
-
- data_size = num_events * sizeof(struct remote_event);
-
- if (copy_to_user(buf, reader, data_size))
- return -EFAULT;
-
- ibmasm_advance_reader(q, num_events);
-
- return data_size;
-}
-
-
static struct file_operations command_fops = {
.open = command_file_open,
.release = command_file_close,
@@ -672,12 +609,6 @@ static struct file_operations remote_settings_fops = {
.write = remote_settings_file_write,
};
-static struct file_operations remote_event_fops = {
- .open = remote_event_file_open,
- .release = remote_event_file_close,
- .read = remote_event_file_read,
-};
-
static void ibmasmfs_create_files (struct super_block *sb, struct dentry *root)
{
@@ -703,7 +634,5 @@ static void ibmasmfs_create_files (struct super_block *sb, struct dentry *root)
ibmasmfs_create_file(sb, remote_dir, "width", &remote_settings_fops, (void *)display_width(sp), S_IRUSR|S_IWUSR);
ibmasmfs_create_file(sb, remote_dir, "height", &remote_settings_fops, (void *)display_height(sp), S_IRUSR|S_IWUSR);
ibmasmfs_create_file(sb, remote_dir, "depth", &remote_settings_fops, (void *)display_depth(sp), S_IRUSR|S_IWUSR);
- ibmasmfs_create_file(sb, remote_dir, "connected", &remote_settings_fops, (void *)vnc_status(sp), S_IRUSR);
- ibmasmfs_create_file(sb, remote_dir, "events", &remote_event_fops, (void *)sp, S_IRUSR);
}
}
diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
index 5156de2759d..47949a2c7e9 100644
--- a/drivers/misc/ibmasm/lowlevel.c
+++ b/drivers/misc/ibmasm/lowlevel.c
@@ -46,8 +46,8 @@ int ibmasm_send_i2o_message(struct service_processor *sp)
message = get_i2o_message(sp->base_address, mfa);
- memcpy(&message->header, &header, sizeof(struct i2o_header));
- memcpy(&message->data, command->buffer, command_size);
+ memcpy_toio(&message->header, &header, sizeof(struct i2o_header));
+ memcpy_toio(&message->data, command->buffer, command_size);
set_mfa_inbound(sp->base_address, mfa);
@@ -59,23 +59,27 @@ irqreturn_t ibmasm_interrupt_handler(int irq, void * dev_id, struct pt_regs *reg
u32 mfa;
struct service_processor *sp = (struct service_processor *)dev_id;
void __iomem *base_address = sp->base_address;
+ char tsbuf[32];
if (!sp_interrupt_pending(base_address))
return IRQ_NONE;
+ dbg("respond to interrupt at %s\n", get_timestamp(tsbuf));
+
if (mouse_interrupt_pending(sp)) {
- ibmasm_handle_mouse_interrupt(sp);
- mfa = get_mfa_outbound(base_address);
+ ibmasm_handle_mouse_interrupt(sp, regs);
clear_mouse_interrupt(sp);
- set_mfa_outbound(base_address, mfa);
- return IRQ_HANDLED;
}
mfa = get_mfa_outbound(base_address);
if (valid_mfa(mfa)) {
struct i2o_message *msg = get_i2o_message(base_address, mfa);
ibmasm_receive_message(sp, &msg->data, incoming_data_size(msg));
- }
+ } else
+ dbg("didn't get a valid MFA\n");
+
set_mfa_outbound(base_address, mfa);
+ dbg("finished interrupt at %s\n", get_timestamp(tsbuf));
+
return IRQ_HANDLED;
}
diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c
index 777432ae764..1fdf03fd2da 100644
--- a/drivers/misc/ibmasm/module.c
+++ b/drivers/misc/ibmasm/module.c
@@ -56,17 +56,26 @@
#include "lowlevel.h"
#include "remote.h"
+int ibmasm_debug = 0;
+module_param(ibmasm_debug, int , S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ibmasm_debug, " Set debug mode on or off");
+
static int __devinit ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
- int err, result = -ENOMEM;
+ int result;
struct service_processor *sp;
- if ((err = pci_enable_device(pdev))) {
- printk(KERN_ERR "%s: can't enable PCI device at %s\n",
- DRIVER_NAME, pci_name(pdev));
- return err;
+ if ((result = pci_enable_device(pdev))) {
+ dev_err(&pdev->dev, "Failed to enable PCI device\n");
+ return result;
}
+ if ((result = pci_request_regions(pdev, DRIVER_NAME))) {
+ dev_err(&pdev->dev, "Failed to allocate PCI resources\n");
+ goto error_resources;
+ }
+ /* vnc client won't work without bus-mastering */
+ pci_set_master(pdev);
sp = kmalloc(sizeof(struct service_processor), GFP_KERNEL);
if (sp == NULL) {
@@ -76,6 +85,9 @@ static int __devinit ibmasm_init_one(struct pci_dev *pdev, const struct pci_devi
}
memset(sp, 0, sizeof(struct service_processor));
+ sp->lock = SPIN_LOCK_UNLOCKED;
+ INIT_LIST_HEAD(&sp->command_queue);
+
pci_set_drvdata(pdev, (void *)sp);
sp->dev = &pdev->dev;
sp->number = pdev->bus->number;
@@ -101,15 +113,6 @@ static int __devinit ibmasm_init_one(struct pci_dev *pdev, const struct pci_devi
goto error_ioremap;
}
- result = ibmasm_init_remote_queue(sp);
- if (result) {
- dev_err(sp->dev, "Failed to initialize remote queue\n");
- goto error_remote_queue;
- }
-
- spin_lock_init(&sp->lock);
- INIT_LIST_HEAD(&sp->command_queue);
-
result = request_irq(sp->irq, ibmasm_interrupt_handler, SA_SHIRQ, sp->devname, (void*)sp);
if (result) {
dev_err(sp->dev, "Failed to register interrupt handler\n");
@@ -117,7 +120,12 @@ static int __devinit ibmasm_init_one(struct pci_dev *pdev, const struct pci_devi
}
enable_sp_interrupts(sp->base_address);
- disable_mouse_interrupts(sp);
+
+ result = ibmasm_init_remote_input_dev(sp);
+ if (result) {
+ dev_err(sp->dev, "Failed to initialize remote queue\n");
+ goto error_send_message;
+ }
result = ibmasm_send_driver_vpd(sp);
if (result) {
@@ -133,30 +141,25 @@ static int __devinit ibmasm_init_one(struct pci_dev *pdev, const struct pci_devi
ibmasm_register_uart(sp);
- dev_printk(KERN_DEBUG, &pdev->dev, "WARNING: This software may not be supported or function\n");
- dev_printk(KERN_DEBUG, &pdev->dev, "correctly on your IBM server. Please consult the IBM\n");
- dev_printk(KERN_DEBUG, &pdev->dev, "ServerProven website\n");
- dev_printk(KERN_DEBUG, &pdev->dev, "http://www.pc.ibm.com/ww/eserver/xseries/serverproven\n");
- dev_printk(KERN_DEBUG, &pdev->dev, "for information on the specific driver level and support\n");
- dev_printk(KERN_DEBUG, &pdev->dev, "statement for your IBM server.\n");
-
return 0;
error_send_message:
disable_sp_interrupts(sp->base_address);
+ ibmasm_free_remote_input_dev(sp);
free_irq(sp->irq, (void *)sp);
error_request_irq:
- ibmasm_free_remote_queue(sp);
-error_remote_queue:
iounmap(sp->base_address);
error_ioremap:
ibmasm_heartbeat_exit(sp);
error_heartbeat:
ibmasm_event_buffer_exit(sp);
error_eventbuffer:
+ pci_set_drvdata(pdev, NULL);
kfree(sp);
error_kmalloc:
- pci_disable_device(pdev);
+ pci_release_regions(pdev);
+error_resources:
+ pci_disable_device(pdev);
return result;
}
@@ -165,16 +168,24 @@ static void __devexit ibmasm_remove_one(struct pci_dev *pdev)
{
struct service_processor *sp = (struct service_processor *)pci_get_drvdata(pdev);
+ dbg("Unregistering UART\n");
ibmasm_unregister_uart(sp);
- ibmasm_send_os_state(sp, SYSTEM_STATE_OS_DOWN);
+ dbg("Sending OS down message\n");
+ if (ibmasm_send_os_state(sp, SYSTEM_STATE_OS_DOWN))
+ err("failed to get repsonse to 'Send OS State' command\n");
+ dbg("Disabling heartbeats\n");
+ ibmasm_heartbeat_exit(sp);
+ dbg("Disabling interrupts\n");
disable_sp_interrupts(sp->base_address);
- disable_mouse_interrupts(sp);
+ dbg("Freeing SP irq\n");
free_irq(sp->irq, (void *)sp);
- ibmasm_heartbeat_exit(sp);
- ibmasm_free_remote_queue(sp);
+ dbg("Cleaning up\n");
+ ibmasm_free_remote_input_dev(sp);
iounmap(sp->base_address);
ibmasm_event_buffer_exit(sp);
+ pci_set_drvdata(pdev, NULL);
kfree(sp);
+ pci_release_regions(pdev);
pci_disable_device(pdev);
}
diff --git a/drivers/misc/ibmasm/r_heartbeat.c b/drivers/misc/ibmasm/r_heartbeat.c
index 93d9c1b2ad6..f8fdb2d5417 100644
--- a/drivers/misc/ibmasm/r_heartbeat.c
+++ b/drivers/misc/ibmasm/r_heartbeat.c
@@ -63,7 +63,7 @@ int ibmasm_start_reverse_heartbeat(struct service_processor *sp, struct reverse_
int times_failed = 0;
int result = 1;
- cmd = ibmasm_new_command(sizeof rhb_dot_cmd);
+ cmd = ibmasm_new_command(sp, sizeof rhb_dot_cmd);
if (!cmd)
return -ENOMEM;
diff --git a/drivers/misc/ibmasm/remote.c b/drivers/misc/ibmasm/remote.c
index 520c3f10c27..d3c48d23ee5 100644
--- a/drivers/misc/ibmasm/remote.c
+++ b/drivers/misc/ibmasm/remote.c
@@ -1,4 +1,3 @@
-
/*
* IBM ASM Service Processor Device Driver
*
@@ -18,135 +17,256 @@
*
* Copyright (C) IBM Corporation, 2004
*
- * Author: Max Asböck <amax@us.ibm.com>
+ * Authors: Max Asböck <amax@us.ibm.com>
+ * Vernon Mauery <vernux@us.ibm.com>
*
*/
/* Remote mouse and keyboard event handling functions */
+#include <linux/pci.h>
#include "ibmasm.h"
#include "remote.h"
-int ibmasm_init_remote_queue(struct service_processor *sp)
-{
- struct remote_queue *q = &sp->remote_queue;
-
- disable_mouse_interrupts(sp);
+static int xmax = 1600;
+static int ymax = 1200;
- q->open = 0;
- q->size = 0;
- q->start = kmalloc(DRIVER_REMOTE_QUEUE_SIZE * sizeof(struct remote_event), GFP_KERNEL);
- if (q->start == 0)
- return -ENOMEM;
+static unsigned short xlate_high[XLATE_SIZE] = {
+ [KEY_SYM_ENTER & 0xff] = KEY_ENTER,
+ [KEY_SYM_KPSLASH & 0xff] = KEY_KPSLASH,
+ [KEY_SYM_KPSTAR & 0xff] = KEY_KPASTERISK,
+ [KEY_SYM_KPMINUS & 0xff] = KEY_KPMINUS,
+ [KEY_SYM_KPDOT & 0xff] = KEY_KPDOT,
+ [KEY_SYM_KPPLUS & 0xff] = KEY_KPPLUS,
+ [KEY_SYM_KP0 & 0xff] = KEY_KP0,
+ [KEY_SYM_KP1 & 0xff] = KEY_KP1,
+ [KEY_SYM_KP2 & 0xff] = KEY_KP2, [KEY_SYM_KPDOWN & 0xff] = KEY_KP2,
+ [KEY_SYM_KP3 & 0xff] = KEY_KP3,
+ [KEY_SYM_KP4 & 0xff] = KEY_KP4, [KEY_SYM_KPLEFT & 0xff] = KEY_KP4,
+ [KEY_SYM_KP5 & 0xff] = KEY_KP5,
+ [KEY_SYM_KP6 & 0xff] = KEY_KP6, [KEY_SYM_KPRIGHT & 0xff] = KEY_KP6,
+ [KEY_SYM_KP7 & 0xff] = KEY_KP7,
+ [KEY_SYM_KP8 & 0xff] = KEY_KP8, [KEY_SYM_KPUP & 0xff] = KEY_KP8,
+ [KEY_SYM_KP9 & 0xff] = KEY_KP9,
+ [KEY_SYM_BK_SPC & 0xff] = KEY_BACKSPACE,
+ [KEY_SYM_TAB & 0xff] = KEY_TAB,
+ [KEY_SYM_CTRL & 0xff] = KEY_LEFTCTRL,
+ [KEY_SYM_ALT & 0xff] = KEY_LEFTALT,
+ [KEY_SYM_INSERT & 0xff] = KEY_INSERT,
+ [KEY_SYM_DELETE & 0xff] = KEY_DELETE,
+ [KEY_SYM_SHIFT & 0xff] = KEY_LEFTSHIFT,
+ [KEY_SYM_UARROW & 0xff] = KEY_UP,
+ [KEY_SYM_DARROW & 0xff] = KEY_DOWN,
+ [KEY_SYM_LARROW & 0xff] = KEY_LEFT,
+ [KEY_SYM_RARROW & 0xff] = KEY_RIGHT,
+ [KEY_SYM_ESCAPE & 0xff] = KEY_ESC,
+ [KEY_SYM_PAGEUP & 0xff] = KEY_PAGEUP,
+ [KEY_SYM_PAGEDOWN & 0xff] = KEY_PAGEDOWN,
+ [KEY_SYM_HOME & 0xff] = KEY_HOME,
+ [KEY_SYM_END & 0xff] = KEY_END,
+ [KEY_SYM_F1 & 0xff] = KEY_F1,
+ [KEY_SYM_F2 & 0xff] = KEY_F2,
+ [KEY_SYM_F3 & 0xff] = KEY_F3,
+ [KEY_SYM_F4 & 0xff] = KEY_F4,
+ [KEY_SYM_F5 & 0xff] = KEY_F5,
+ [KEY_SYM_F6 & 0xff] = KEY_F6,
+ [KEY_SYM_F7 & 0xff] = KEY_F7,
+ [KEY_SYM_F8 & 0xff] = KEY_F8,
+ [KEY_SYM_F9 & 0xff] = KEY_F9,
+ [KEY_SYM_F10 & 0xff] = KEY_F10,
+ [KEY_SYM_F11 & 0xff] = KEY_F11,
+ [KEY_SYM_F12 & 0xff] = KEY_F12,
+ [KEY_SYM_CAP_LOCK & 0xff] = KEY_CAPSLOCK,
+ [KEY_SYM_NUM_LOCK & 0xff] = KEY_NUMLOCK,
+ [KEY_SYM_SCR_LOCK & 0xff] = KEY_SCROLLLOCK,
+};
+static unsigned short xlate[XLATE_SIZE] = {
+ [NO_KEYCODE] = KEY_RESERVED,
+ [KEY_SYM_SPACE] = KEY_SPACE,
+ [KEY_SYM_TILDE] = KEY_GRAVE, [KEY_SYM_BKTIC] = KEY_GRAVE,
+ [KEY_SYM_ONE] = KEY_1, [KEY_SYM_BANG] = KEY_1,
+ [KEY_SYM_TWO] = KEY_2, [KEY_SYM_AT] = KEY_2,
+ [KEY_SYM_THREE] = KEY_3, [KEY_SYM_POUND] = KEY_3,
+ [KEY_SYM_FOUR] = KEY_4, [KEY_SYM_DOLLAR] = KEY_4,
+ [KEY_SYM_FIVE] = KEY_5, [KEY_SYM_PERCENT] = KEY_5,
+ [KEY_SYM_SIX] = KEY_6, [KEY_SYM_CARAT] = KEY_6,
+ [KEY_SYM_SEVEN] = KEY_7, [KEY_SYM_AMPER] = KEY_7,
+ [KEY_SYM_EIGHT] = KEY_8, [KEY_SYM_STAR] = KEY_8,
+ [KEY_SYM_NINE] = KEY_9, [KEY_SYM_LPAREN] = KEY_9,
+ [KEY_SYM_ZERO] = KEY_0, [KEY_SYM_RPAREN] = KEY_0,
+ [KEY_SYM_MINUS] = KEY_MINUS, [KEY_SYM_USCORE] = KEY_MINUS,
+ [KEY_SYM_EQUAL] = KEY_EQUAL, [KEY_SYM_PLUS] = KEY_EQUAL,
+ [KEY_SYM_LBRKT] = KEY_LEFTBRACE, [KEY_SYM_LCURLY] = KEY_LEFTBRACE,
+ [KEY_SYM_RBRKT] = KEY_RIGHTBRACE, [KEY_SYM_RCURLY] = KEY_RIGHTBRACE,
+ [KEY_SYM_SLASH] = KEY_BACKSLASH, [KEY_SYM_PIPE] = KEY_BACKSLASH,
+ [KEY_SYM_TIC] = KEY_APOSTROPHE, [KEY_SYM_QUOTE] = KEY_APOSTROPHE,
+ [KEY_SYM_SEMIC] = KEY_SEMICOLON, [KEY_SYM_COLON] = KEY_SEMICOLON,
+ [KEY_SYM_COMMA] = KEY_COMMA, [KEY_SYM_LT] = KEY_COMMA,
+ [KEY_SYM_PERIOD] = KEY_DOT, [KEY_SYM_GT] = KEY_DOT,
+ [KEY_SYM_BSLASH] = KEY_SLASH, [KEY_SYM_QMARK] = KEY_SLASH,
+ [KEY_SYM_A] = KEY_A, [KEY_SYM_a] = KEY_A,
+ [KEY_SYM_B] = KEY_B, [KEY_SYM_b] = KEY_B,
+ [KEY_SYM_C] = KEY_C, [KEY_SYM_c] = KEY_C,
+ [KEY_SYM_D] = KEY_D, [KEY_SYM_d] = KEY_D,
+ [KEY_SYM_E] = KEY_E, [KEY_SYM_e] = KEY_E,
+ [KEY_SYM_F] = KEY_F, [KEY_SYM_f] = KEY_F,
+ [KEY_SYM_G] = KEY_G, [KEY_SYM_g] = KEY_G,
+ [KEY_SYM_H] = KEY_H, [KEY_SYM_h] = KEY_H,
+ [KEY_SYM_I] = KEY_I, [KEY_SYM_i] = KEY_I,
+ [KEY_SYM_J] = KEY_J, [KEY_SYM_j] = KEY_J,
+ [KEY_SYM_K] = KEY_K, [KEY_SYM_k] = KEY_K,
+ [KEY_SYM_L] = KEY_L, [KEY_SYM_l] = KEY_L,
+ [KEY_SYM_M] = KEY_M, [KEY_SYM_m] = KEY_M,
+ [KEY_SYM_N] = KEY_N, [KEY_SYM_n] = KEY_N,
+ [KEY_SYM_O] = KEY_O, [KEY_SYM_o] = KEY_O,
+ [KEY_SYM_P] = KEY_P, [KEY_SYM_p] = KEY_P,
+ [KEY_SYM_Q] = KEY_Q, [KEY_SYM_q] = KEY_Q,
+ [KEY_SYM_R] = KEY_R, [KEY_SYM_r] = KEY_R,
+ [KEY_SYM_S] = KEY_S, [KEY_SYM_s] = KEY_S,
+ [KEY_SYM_T] = KEY_T, [KEY_SYM_t] = KEY_T,
+ [KEY_SYM_U] = KEY_U, [KEY_SYM_u] = KEY_U,
+ [KEY_SYM_V] = KEY_V, [KEY_SYM_v] = KEY_V,
+ [KEY_SYM_W] = KEY_W, [KEY_SYM_w] = KEY_W,
+ [KEY_SYM_X] = KEY_X, [KEY_SYM_x] = KEY_X,
+ [KEY_SYM_Y] = KEY_Y, [KEY_SYM_y] = KEY_Y,
+ [KEY_SYM_Z] = KEY_Z, [KEY_SYM_z] = KEY_Z,
+};
- q->end = q->start + DRIVER_REMOTE_QUEUE_SIZE;
- q->reader = q->start;
- q->writer = q->start;
- q->size = DRIVER_REMOTE_QUEUE_SIZE;
- init_waitqueue_head(&q->wait);
+static char remote_mouse_name[] = "ibmasm RSA I remote mouse";
+static char remote_keybd_name[] = "ibmasm RSA I remote keyboard";
- return 0;
-}
-
-void ibmasm_free_remote_queue(struct service_processor *sp)
+static void print_input(struct remote_input *input)
{
- kfree(sp->remote_queue.start);
+ if (input->type == INPUT_TYPE_MOUSE) {
+ unsigned char buttons = input->mouse_buttons;
+ dbg("remote mouse movement: (x,y)=(%d,%d)%s%s%s%s\n",
+ input->data.mouse.x, input->data.mouse.y,
+ (buttons)?" -- buttons:":"",
+ (buttons & REMOTE_BUTTON_LEFT)?"left ":"",
+ (buttons & REMOTE_BUTTON_MIDDLE)?"middle ":"",
+ (buttons & REMOTE_BUTTON_RIGHT)?"right":""
+ );
+ } else {
+ dbg("remote keypress (code, flag, down):"
+ "%d (0x%x) [0x%x] [0x%x]\n",
+ input->data.keyboard.key_code,
+ input->data.keyboard.key_code,
+ input->data.keyboard.key_flag,
+ input->data.keyboard.key_down
+ );
+ }
}
-void ibmasm_advance_reader(struct remote_queue *q, unsigned int n)
+static void send_mouse_event(struct input_dev *dev, struct pt_regs *regs,
+ struct remote_input *input)
{
- q->reader += n;
- if (q->reader >= q->end)
- q->reader -= q->size;
-}
+ unsigned char buttons = input->mouse_buttons;
-size_t ibmasm_events_available(struct remote_queue *q)
-{
- ssize_t diff = q->writer - q->reader;
-
- return (diff >= 0) ? diff : q->end - q->reader;
+ input_regs(dev, regs);
+ input_report_abs(dev, ABS_X, input->data.mouse.x);
+ input_report_abs(dev, ABS_Y, input->data.mouse.y);
+ input_report_key(dev, BTN_LEFT, buttons & REMOTE_BUTTON_LEFT);
+ input_report_key(dev, BTN_MIDDLE, buttons & REMOTE_BUTTON_MIDDLE);
+ input_report_key(dev, BTN_RIGHT, buttons & REMOTE_BUTTON_RIGHT);
+ input_sync(dev);
}
-
-static int space_free(struct remote_queue *q)
+static void send_keyboard_event(struct input_dev *dev, struct pt_regs *regs,
+ struct remote_input *input)
{
- if (q->reader == q->writer)
- return q->size - 1;
+ unsigned int key;
+ unsigned short code = input->data.keyboard.key_code;
- return ( (q->reader + q->size - q->writer) % q->size ) - 1;
+ if (code & 0xff00)
+ key = xlate_high[code & 0xff];
+ else
+ key = xlate[code];
+ input_regs(dev, regs);
+ input_report_key(dev, key, (input->data.keyboard.key_down) ? 1 : 0);
+ input_sync(dev);
}
-static void set_mouse_event(struct remote_input *input, struct mouse_event *mouse)
+void ibmasm_handle_mouse_interrupt(struct service_processor *sp,
+ struct pt_regs *regs)
{
- static char last_buttons = 0;
+ unsigned long reader;
+ unsigned long writer;
+ struct remote_input input;
- mouse->x = input->data.mouse.x;
- mouse->y = input->data.mouse.y;
+ reader = get_queue_reader(sp);
+ writer = get_queue_writer(sp);
- if (input->mouse_buttons == REMOTE_MOUSE_DOUBLE_CLICK) {
- mouse->buttons = REMOTE_MOUSE_DOUBLE_CLICK;
- last_buttons = 0;
- return;
- }
- mouse->transitions = last_buttons ^ input->mouse_buttons;
- mouse->buttons = input->mouse_buttons;
+ while (reader != writer) {
+ memcpy_fromio(&input, get_queue_entry(sp, reader),
+ sizeof(struct remote_input));
- last_buttons = input->mouse_buttons;
-}
+ print_input(&input);
+ if (input.type == INPUT_TYPE_MOUSE) {
+ send_mouse_event(&sp->remote->mouse_dev, regs, &input);
+ } else if (input.type == INPUT_TYPE_KEYBOARD) {
+ send_keyboard_event(&sp->remote->keybd_dev, regs, &input);
+ } else
+ break;
-static void set_keyboard_event(struct remote_input *input, struct keyboard_event *keyboard)
-{
- keyboard->key_code = input->data.keyboard.key_code;
- keyboard->key_down = input->data.keyboard.key_down;
+ reader = advance_queue_reader(sp, reader);
+ writer = get_queue_writer(sp);
+ }
}
-static int add_to_driver_queue(struct remote_queue *q, struct remote_input *input)
+int ibmasm_init_remote_input_dev(struct service_processor *sp)
{
- struct remote_event *event = q->writer;
+ /* set up the mouse input device */
+ struct ibmasm_remote *remote;
+ struct pci_dev *pdev = to_pci_dev(sp->dev);
+ int i;
- if (space_free(q) < 1) {
- return 1;
- }
+ sp->remote = remote = kmalloc(sizeof(*remote), GFP_KERNEL);
+ if (!remote)
+ return -ENOMEM;
- switch(input->type) {
- case (INPUT_TYPE_MOUSE):
- event->type = INPUT_TYPE_MOUSE;
- set_mouse_event(input, &event->data.mouse);
- break;
- case (INPUT_TYPE_KEYBOARD):
- event->type = INPUT_TYPE_KEYBOARD;
- set_keyboard_event(input, &event->data.keyboard);
- break;
- default:
- return 0;
- }
- event->type = input->type;
+ memset(remote, 0, sizeof(*remote));
- q->writer++;
- if (q->writer == q->end)
- q->writer = q->start;
+ remote->mouse_dev.private = remote;
+ init_input_dev(&remote->mouse_dev);
+ remote->mouse_dev.id.vendor = pdev->vendor;
+ remote->mouse_dev.id.product = pdev->device;
+ remote->mouse_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+ remote->mouse_dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) |
+ BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+ set_bit(BTN_TOUCH, remote->mouse_dev.keybit);
+ remote->mouse_dev.name = remote_mouse_name;
+ input_set_abs_params(&remote->mouse_dev, ABS_X, 0, xmax, 0, 0);
+ input_set_abs_params(&remote->mouse_dev, ABS_Y, 0, ymax, 0, 0);
- return 0;
-}
-
+ remote->keybd_dev.private = remote;
+ init_input_dev(&remote->keybd_dev);
+ remote->keybd_dev.id.vendor = pdev->vendor;
+ remote->keybd_dev.id.product = pdev->device;
+ remote->keybd_dev.evbit[0] = BIT(EV_KEY);
+ remote->keybd_dev.name = remote_keybd_name;
-void ibmasm_handle_mouse_interrupt(struct service_processor *sp)
-{
- unsigned long reader;
- unsigned long writer;
- struct remote_input input;
+ for (i=0; i<XLATE_SIZE; i++) {
+ if (xlate_high[i])
+ set_bit(xlate_high[i], remote->keybd_dev.keybit);
+ if (xlate[i])
+ set_bit(xlate[i], remote->keybd_dev.keybit);
+ }
- reader = get_queue_reader(sp);
- writer = get_queue_writer(sp);
+ input_register_device(&remote->mouse_dev);
+ input_register_device(&remote->keybd_dev);
+ enable_mouse_interrupts(sp);
- while (reader != writer) {
- memcpy(&input, (void *)get_queue_entry(sp, reader), sizeof(struct remote_input));
+ printk(KERN_INFO "ibmasm remote responding to events on RSA card %d\n", sp->number);
- if (add_to_driver_queue(&sp->remote_queue, &input))
- break;
+ return 0;
+}
- reader = advance_queue_reader(sp, reader);
- }
- wake_up_interruptible(&sp->remote_queue.wait);
+void ibmasm_free_remote_input_dev(struct service_processor *sp)
+{
+ disable_mouse_interrupts(sp);
+ input_unregister_device(&sp->remote->keybd_dev);
+ input_unregister_device(&sp->remote->mouse_dev);
+ kfree(sp->remote);
}
+
diff --git a/drivers/misc/ibmasm/remote.h b/drivers/misc/ibmasm/remote.h
index a8eb19f02d3..b7076a8442d 100644
--- a/drivers/misc/ibmasm/remote.h
+++ b/drivers/misc/ibmasm/remote.h
@@ -51,11 +51,13 @@
/* mouse button states received from SP */
-#define REMOTE_MOUSE_DOUBLE_CLICK 0xF0
-#define REMOTE_MOUSE_BUTTON_LEFT 0x01
-#define REMOTE_MOUSE_BUTTON_MIDDLE 0x02
-#define REMOTE_MOUSE_BUTTON_RIGHT 0x04
+#define REMOTE_DOUBLE_CLICK 0xF0
+#define REMOTE_BUTTON_LEFT 0x01
+#define REMOTE_BUTTON_MIDDLE 0x02
+#define REMOTE_BUTTON_RIGHT 0x04
+/* size of keysym/keycode translation matricies */
+#define XLATE_SIZE 256
struct mouse_input {
unsigned short y;
@@ -83,11 +85,13 @@ struct remote_input {
unsigned char pad3;
};
-#define mouse_addr(sp) sp->base_address + CONDOR_MOUSE_DATA
-#define display_width(sp) mouse_addr(sp) + CONDOR_INPUT_DISPLAY_RESX
-#define display_height(sp) mouse_addr(sp) + CONDOR_INPUT_DISPLAY_RESY
-#define display_depth(sp) mouse_addr(sp) + CONDOR_INPUT_DISPLAY_BITS
-#define vnc_status(sp) mouse_addr(sp) + CONDOR_OUTPUT_VNC_STATUS
+#define mouse_addr(sp) (sp->base_address + CONDOR_MOUSE_DATA)
+#define display_width(sp) (mouse_addr(sp) + CONDOR_INPUT_DISPLAY_RESX)
+#define display_height(sp) (mouse_addr(sp) + CONDOR_INPUT_DISPLAY_RESY)
+#define display_depth(sp) (mouse_addr(sp) + CONDOR_INPUT_DISPLAY_BITS)
+#define desktop_info(sp) (mouse_addr(sp) + CONDOR_INPUT_DESKTOP_INFO)
+#define vnc_status(sp) (mouse_addr(sp) + CONDOR_OUTPUT_VNC_STATUS)
+#define isr_control(sp) (mouse_addr(sp) + CONDOR_MOUSE_ISR_CONTROL)
#define mouse_interrupt_pending(sp) readl(mouse_addr(sp) + CONDOR_MOUSE_ISR_STATUS)
#define clear_mouse_interrupt(sp) writel(0, mouse_addr(sp) + CONDOR_MOUSE_ISR_STATUS)
@@ -101,10 +105,10 @@ struct remote_input {
#define get_queue_reader(sp) readl(mouse_addr(sp) + CONDOR_MOUSE_Q_READER)
#define set_queue_reader(sp, reader) writel(reader, mouse_addr(sp) + CONDOR_MOUSE_Q_READER)
-#define queue_begin mouse_addr(sp) + CONDOR_MOUSE_Q_BEGIN
+#define queue_begin (mouse_addr(sp) + CONDOR_MOUSE_Q_BEGIN)
#define get_queue_entry(sp, read_index) \
- queue_begin + read_index * sizeof(struct remote_input)
+ ((void*)(queue_begin + read_index * sizeof(struct remote_input)))
static inline int advance_queue_reader(struct service_processor *sp, unsigned long reader)
{
@@ -116,4 +120,151 @@ static inline int advance_queue_reader(struct service_processor *sp, unsigned lo
return reader;
}
+#define NO_KEYCODE 0
+#define KEY_SYM_BK_SPC 0xFF08
+#define KEY_SYM_TAB 0xFF09
+#define KEY_SYM_ENTER 0xFF0D
+#define KEY_SYM_SCR_LOCK 0xFF14
+#define KEY_SYM_ESCAPE 0xFF1B
+#define KEY_SYM_HOME 0xFF50
+#define KEY_SYM_LARROW 0xFF51
+#define KEY_SYM_UARROW 0xFF52
+#define KEY_SYM_RARROW 0xFF53
+#define KEY_SYM_DARROW 0xFF54
+#define KEY_SYM_PAGEUP 0xFF55
+#define KEY_SYM_PAGEDOWN 0xFF56
+#define KEY_SYM_END 0xFF57
+#define KEY_SYM_INSERT 0xFF63
+#define KEY_SYM_NUM_LOCK 0xFF7F
+#define KEY_SYM_KPSTAR 0xFFAA
+#define KEY_SYM_KPPLUS 0xFFAB
+#define KEY_SYM_KPMINUS 0xFFAD
+#define KEY_SYM_KPDOT 0xFFAE
+#define KEY_SYM_KPSLASH 0xFFAF
+#define KEY_SYM_KPRIGHT 0xFF96
+#define KEY_SYM_KPUP 0xFF97
+#define KEY_SYM_KPLEFT 0xFF98
+#define KEY_SYM_KPDOWN 0xFF99
+#define KEY_SYM_KP0 0xFFB0
+#define KEY_SYM_KP1 0xFFB1
+#define KEY_SYM_KP2 0xFFB2
+#define KEY_SYM_KP3 0xFFB3
+#define KEY_SYM_KP4 0xFFB4
+#define KEY_SYM_KP5 0xFFB5
+#define KEY_SYM_KP6 0xFFB6
+#define KEY_SYM_KP7 0xFFB7
+#define KEY_SYM_KP8 0xFFB8
+#define KEY_SYM_KP9 0xFFB9
+#define KEY_SYM_F1 0xFFBE // 1B 5B 5B 41
+#define KEY_SYM_F2 0xFFBF // 1B 5B 5B 42
+#define KEY_SYM_F3 0xFFC0 // 1B 5B 5B 43
+#define KEY_SYM_F4 0xFFC1 // 1B 5B 5B 44
+#define KEY_SYM_F5 0xFFC2 // 1B 5B 5B 45
+#define KEY_SYM_F6 0xFFC3 // 1B 5B 31 37 7E
+#define KEY_SYM_F7 0xFFC4 // 1B 5B 31 38 7E
+#define KEY_SYM_F8 0xFFC5 // 1B 5B 31 39 7E
+#define KEY_SYM_F9 0xFFC6 // 1B 5B 32 30 7E
+#define KEY_SYM_F10 0xFFC7 // 1B 5B 32 31 7E
+#define KEY_SYM_F11 0xFFC8 // 1B 5B 32 33 7E
+#define KEY_SYM_F12 0xFFC9 // 1B 5B 32 34 7E
+#define KEY_SYM_SHIFT 0xFFE1
+#define KEY_SYM_CTRL 0xFFE3
+#define KEY_SYM_ALT 0xFFE9
+#define KEY_SYM_CAP_LOCK 0xFFE5
+#define KEY_SYM_DELETE 0xFFFF
+#define KEY_SYM_TILDE 0x60
+#define KEY_SYM_BKTIC 0x7E
+#define KEY_SYM_ONE 0x31
+#define KEY_SYM_BANG 0x21
+#define KEY_SYM_TWO 0x32
+#define KEY_SYM_AT 0x40
+#define KEY_SYM_THREE 0x33
+#define KEY_SYM_POUND 0x23
+#define KEY_SYM_FOUR 0x34
+#define KEY_SYM_DOLLAR 0x24
+#define KEY_SYM_FIVE 0x35
+#define KEY_SYM_PERCENT 0x25
+#define KEY_SYM_SIX 0x36
+#define KEY_SYM_CARAT 0x5E
+#define KEY_SYM_SEVEN 0x37
+#define KEY_SYM_AMPER 0x26
+#define KEY_SYM_EIGHT 0x38
+#define KEY_SYM_STAR 0x2A
+#define KEY_SYM_NINE 0x39
+#define KEY_SYM_LPAREN 0x28
+#define KEY_SYM_ZERO 0x30
+#define KEY_SYM_RPAREN 0x29
+#define KEY_SYM_MINUS 0x2D
+#define KEY_SYM_USCORE 0x5F
+#define KEY_SYM_EQUAL 0x2B
+#define KEY_SYM_PLUS 0x3D
+#define KEY_SYM_LBRKT 0x5B
+#define KEY_SYM_LCURLY 0x7B
+#define KEY_SYM_RBRKT 0x5D
+#define KEY_SYM_RCURLY 0x7D
+#define KEY_SYM_SLASH 0x5C
+#define KEY_SYM_PIPE 0x7C
+#define KEY_SYM_TIC 0x27
+#define KEY_SYM_QUOTE 0x22
+#define KEY_SYM_SEMIC 0x3B
+#define KEY_SYM_COLON 0x3A
+#define KEY_SYM_COMMA 0x2C
+#define KEY_SYM_LT 0x3C
+#define KEY_SYM_PERIOD 0x2E
+#define KEY_SYM_GT 0x3E
+#define KEY_SYM_BSLASH 0x2F
+#define KEY_SYM_QMARK 0x3F
+#define KEY_SYM_A 0x41
+#define KEY_SYM_B 0x42
+#define KEY_SYM_C 0x43
+#define KEY_SYM_D 0x44
+#define KEY_SYM_E 0x45
+#define KEY_SYM_F 0x46
+#define KEY_SYM_G 0x47
+#define KEY_SYM_H 0x48
+#define KEY_SYM_I 0x49
+#define KEY_SYM_J 0x4A
+#define KEY_SYM_K 0x4B
+#define KEY_SYM_L 0x4C
+#define KEY_SYM_M 0x4D
+#define KEY_SYM_N 0x4E
+#define KEY_SYM_O 0x4F
+#define KEY_SYM_P 0x50
+#define KEY_SYM_Q 0x51
+#define KEY_SYM_R 0x52
+#define KEY_SYM_S 0x53
+#define KEY_SYM_T 0x54
+#define KEY_SYM_U 0x55
+#define KEY_SYM_V 0x56
+#define KEY_SYM_W 0x57
+#define KEY_SYM_X 0x58
+#define KEY_SYM_Y 0x59
+#define KEY_SYM_Z 0x5A
+#define KEY_SYM_a 0x61
+#define KEY_SYM_b 0x62
+#define KEY_SYM_c 0x63
+#define KEY_SYM_d 0x64
+#define KEY_SYM_e 0x65
+#define KEY_SYM_f 0x66
+#define KEY_SYM_g 0x67
+#define KEY_SYM_h 0x68
+#define KEY_SYM_i 0x69
+#define KEY_SYM_j 0x6A
+#define KEY_SYM_k 0x6B
+#define KEY_SYM_l 0x6C
+#define KEY_SYM_m 0x6D
+#define KEY_SYM_n 0x6E
+#define KEY_SYM_o 0x6F
+#define KEY_SYM_p 0x70
+#define KEY_SYM_q 0x71
+#define KEY_SYM_r 0x72
+#define KEY_SYM_s 0x73
+#define KEY_SYM_t 0x74
+#define KEY_SYM_u 0x75
+#define KEY_SYM_v 0x76
+#define KEY_SYM_w 0x77
+#define KEY_SYM_x 0x78
+#define KEY_SYM_y 0x79
+#define KEY_SYM_z 0x7A
+#define KEY_SYM_SPACE 0x20
#endif /* _IBMASM_REMOTE_H_ */
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 2e70d74fbde..4991bbd054f 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -51,7 +51,7 @@ config MMC_PXA
config MMC_WBSD
tristate "Winbond W83L51xD SD/MMC Card Interface support"
- depends on MMC && ISA && ISA_DMA_API
+ depends on MMC && ISA_DMA_API
help
This selects the Winbond(R) W83L51xD Secure digital and
Multimedia card Interface.
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c
index b5b4a7b1190..d4eee99c2bf 100644
--- a/drivers/mmc/mmc_block.c
+++ b/drivers/mmc/mmc_block.c
@@ -383,7 +383,10 @@ static int mmc_blk_probe(struct mmc_card *card)
struct mmc_blk_data *md;
int err;
- if (card->csd.cmdclass & ~0x1ff)
+ /*
+ * Check that the card supports the command class(es) we need.
+ */
+ if (!(card->csd.cmdclass & CCC_BLOCK_READ))
return -ENODEV;
if (card->csd.read_blkbits < 9) {
diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c
index 29a56e9cd5b..5556cd3b555 100644
--- a/drivers/mmc/mmc_sysfs.c
+++ b/drivers/mmc/mmc_sysfs.c
@@ -22,7 +22,7 @@
#define to_mmc_driver(d) container_of(d, struct mmc_driver, drv)
#define MMC_ATTR(name, fmt, args...) \
-static ssize_t mmc_##name##_show (struct device *dev, char *buf) \
+static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct mmc_card *card = dev_to_mmc_card(dev); \
return sprintf(buf, fmt, args); \
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c
index 39747526c71..b7fbd30b49a 100644
--- a/drivers/mmc/wbsd.c
+++ b/drivers/mmc/wbsd.c
@@ -28,7 +28,9 @@
#include <linux/ioport.h>
#include <linux/device.h>
#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
#include <linux/delay.h>
+#include <linux/pnp.h>
#include <linux/highmem.h>
#include <linux/mmc/host.h>
#include <linux/mmc/protocol.h>
@@ -40,7 +42,7 @@
#include "wbsd.h"
#define DRIVER_NAME "wbsd"
-#define DRIVER_VERSION "1.1"
+#define DRIVER_VERSION "1.2"
#ifdef CONFIG_MMC_DEBUG
#define DBG(x...) \
@@ -52,10 +54,6 @@
#define DBGF(x...) do { } while (0)
#endif
-static unsigned int io = 0x248;
-static unsigned int irq = 6;
-static int dma = 2;
-
#ifdef CONFIG_MMC_DEBUG
void DBG_REG(int reg, u8 value)
{
@@ -79,28 +77,61 @@ void DBG_REG(int reg, u8 value)
#endif
/*
+ * Device resources
+ */
+
+#ifdef CONFIG_PNP
+
+static const struct pnp_device_id pnp_dev_table[] = {
+ { "WEC0517", 0 },
+ { "WEC0518", 0 },
+ { "", 0 },
+};
+
+MODULE_DEVICE_TABLE(pnp, pnp_dev_table);
+
+#endif /* CONFIG_PNP */
+
+#ifdef CONFIG_PNP
+static unsigned int nopnp = 0;
+#else
+static const unsigned int nopnp = 1;
+#endif
+static unsigned int io = 0x248;
+static unsigned int irq = 6;
+static int dma = 2;
+
+/*
* Basic functions
*/
static inline void wbsd_unlock_config(struct wbsd_host* host)
{
+ BUG_ON(host->config == 0);
+
outb(host->unlock_code, host->config);
outb(host->unlock_code, host->config);
}
static inline void wbsd_lock_config(struct wbsd_host* host)
{
+ BUG_ON(host->config == 0);
+
outb(LOCK_CODE, host->config);
}
static inline void wbsd_write_config(struct wbsd_host* host, u8 reg, u8 value)
{
+ BUG_ON(host->config == 0);
+
outb(reg, host->config);
outb(value, host->config + 1);
}
static inline u8 wbsd_read_config(struct wbsd_host* host, u8 reg)
{
+ BUG_ON(host->config == 0);
+
outb(reg, host->config);
return inb(host->config + 1);
}
@@ -133,6 +164,13 @@ static void wbsd_init_device(struct wbsd_host* host)
wbsd_write_index(host, WBSD_IDX_SETUP, setup);
/*
+ * Set DAT3 to input
+ */
+ setup &= ~WBSD_DAT3_H;
+ wbsd_write_index(host, WBSD_IDX_SETUP, setup);
+ host->flags &= ~WBSD_FIGNORE_DETECT;
+
+ /*
* Read back default clock.
*/
host->clk = wbsd_read_index(host, WBSD_IDX_CLK);
@@ -148,6 +186,14 @@ static void wbsd_init_device(struct wbsd_host* host)
wbsd_write_index(host, WBSD_IDX_TAAC, 0x7F);
/*
+ * Test for card presence
+ */
+ if (inb(host->base + WBSD_CSR) & WBSD_CARDPRESENT)
+ host->flags |= WBSD_FCARD_PRESENT;
+ else
+ host->flags &= ~WBSD_FCARD_PRESENT;
+
+ /*
* Enable interesting interrupts.
*/
ier = 0;
@@ -407,8 +453,6 @@ static inline void wbsd_get_long_reply(struct wbsd_host* host,
}
}
-static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs);
-
static void wbsd_send_command(struct wbsd_host* host, struct mmc_command* cmd)
{
int i;
@@ -646,6 +690,13 @@ static void wbsd_fill_fifo(struct wbsd_host* host)
}
wbsd_kunmap_sg(host);
+
+ /*
+ * The controller stops sending interrupts for
+ * 'FIFO empty' under certain conditions. So we
+ * need to be a bit more pro-active.
+ */
+ tasklet_schedule(&host->fifo_tasklet);
}
static void wbsd_prepare_data(struct wbsd_host* host, struct mmc_data* data)
@@ -850,9 +901,11 @@ static void wbsd_finish_data(struct wbsd_host* host, struct mmc_data* data)
wbsd_request_end(host, host->mrq);
}
-/*
- * MMC Callbacks
- */
+/*****************************************************************************\
+ * *
+ * MMC layer callbacks *
+ * *
+\*****************************************************************************/
static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
{
@@ -874,7 +927,7 @@ static void wbsd_request(struct mmc_host* mmc, struct mmc_request* mrq)
* If there is no card in the slot then
* timeout immediatly.
*/
- if (!(inb(host->base + WBSD_CSR) & WBSD_CARDPRESENT))
+ if (!(host->flags & WBSD_FCARD_PRESENT))
{
cmd->error = MMC_ERR_TIMEOUT;
goto done;
@@ -953,33 +1006,50 @@ static void wbsd_set_ios(struct mmc_host* mmc, struct mmc_ios* ios)
host->clk = clk;
}
+ /*
+ * Power up card.
+ */
if (ios->power_mode != MMC_POWER_OFF)
{
- /*
- * Power up card.
- */
pwr = inb(host->base + WBSD_CSR);
pwr &= ~WBSD_POWER_N;
outb(pwr, host->base + WBSD_CSR);
-
- /*
- * This behaviour is stolen from the
- * Windows driver. Don't know why, but
- * it is needed.
- */
- setup = wbsd_read_index(host, WBSD_IDX_SETUP);
- if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
- setup |= WBSD_DAT3_H;
- else
- setup &= ~WBSD_DAT3_H;
- wbsd_write_index(host, WBSD_IDX_SETUP, setup);
-
- mdelay(1);
}
+ /*
+ * MMC cards need to have pin 1 high during init.
+ * Init time corresponds rather nicely with the bus mode.
+ * It wreaks havoc with the card detection though so
+ * that needs to be disabed.
+ */
+ setup = wbsd_read_index(host, WBSD_IDX_SETUP);
+ if ((ios->power_mode == MMC_POWER_ON) &&
+ (ios->bus_mode == MMC_BUSMODE_OPENDRAIN))
+ {
+ setup |= WBSD_DAT3_H;
+ host->flags |= WBSD_FIGNORE_DETECT;
+ }
+ else
+ {
+ setup &= ~WBSD_DAT3_H;
+ host->flags &= ~WBSD_FIGNORE_DETECT;
+ }
+ wbsd_write_index(host, WBSD_IDX_SETUP, setup);
+
spin_unlock_bh(&host->lock);
}
+static struct mmc_host_ops wbsd_ops = {
+ .request = wbsd_request,
+ .set_ios = wbsd_set_ios,
+};
+
+/*****************************************************************************\
+ * *
+ * Interrupt handling *
+ * *
+\*****************************************************************************/
+
/*
* Tasklets
*/
@@ -1005,17 +1075,33 @@ static void wbsd_tasklet_card(unsigned long param)
{
struct wbsd_host* host = (struct wbsd_host*)param;
u8 csr;
+ int change = 0;
spin_lock(&host->lock);
+ if (host->flags & WBSD_FIGNORE_DETECT)
+ {
+ spin_unlock(&host->lock);
+ return;
+ }
+
csr = inb(host->base + WBSD_CSR);
WARN_ON(csr == 0xff);
if (csr & WBSD_CARDPRESENT)
- DBG("Card inserted\n");
- else
+ {
+ if (!(host->flags & WBSD_FCARD_PRESENT))
+ {
+ DBG("Card inserted\n");
+ host->flags |= WBSD_FCARD_PRESENT;
+ change = 1;
+ }
+ }
+ else if (host->flags & WBSD_FCARD_PRESENT)
{
DBG("Card removed\n");
+ host->flags &= ~WBSD_FCARD_PRESENT;
+ change = 1;
if (host->mrq)
{
@@ -1033,7 +1119,8 @@ static void wbsd_tasklet_card(unsigned long param)
*/
spin_unlock(&host->lock);
- mmc_detect_change(host->mmc);
+ if (change)
+ mmc_detect_change(host->mmc);
}
static void wbsd_tasklet_fifo(unsigned long param)
@@ -1200,11 +1287,85 @@ static irqreturn_t wbsd_irq(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
+/*****************************************************************************\
+ * *
+ * Device initialisation and shutdown *
+ * *
+\*****************************************************************************/
+
/*
- * Support functions for probe
+ * Allocate/free MMC structure.
*/
-static int wbsd_scan(struct wbsd_host* host)
+static int __devinit wbsd_alloc_mmc(struct device* dev)
+{
+ struct mmc_host* mmc;
+ struct wbsd_host* host;
+
+ /*
+ * Allocate MMC structure.
+ */
+ mmc = mmc_alloc_host(sizeof(struct wbsd_host), dev);
+ if (!mmc)
+ return -ENOMEM;
+
+ host = mmc_priv(mmc);
+ host->mmc = mmc;
+
+ host->dma = -1;
+
+ /*
+ * Set host parameters.
+ */
+ mmc->ops = &wbsd_ops;
+ mmc->f_min = 375000;
+ mmc->f_max = 24000000;
+ mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
+
+ spin_lock_init(&host->lock);
+
+ /*
+ * Maximum number of segments. Worst case is one sector per segment
+ * so this will be 64kB/512.
+ */
+ mmc->max_hw_segs = 128;
+ mmc->max_phys_segs = 128;
+
+ /*
+ * Maximum number of sectors in one transfer. Also limited by 64kB
+ * buffer.
+ */
+ mmc->max_sectors = 128;
+
+ /*
+ * Maximum segment size. Could be one segment with the maximum number
+ * of segments.
+ */
+ mmc->max_seg_size = mmc->max_sectors * 512;
+
+ dev_set_drvdata(dev, mmc);
+
+ return 0;
+}
+
+static void __devexit wbsd_free_mmc(struct device* dev)
+{
+ struct mmc_host* mmc;
+
+ mmc = dev_get_drvdata(dev);
+ if (!mmc)
+ return;
+
+ mmc_free_host(mmc);
+
+ dev_set_drvdata(dev, NULL);
+}
+
+/*
+ * Scan for known chip id:s
+ */
+
+static int __devinit wbsd_scan(struct wbsd_host* host)
{
int i, j, k;
int id;
@@ -1258,12 +1419,16 @@ static int wbsd_scan(struct wbsd_host* host)
return -ENODEV;
}
-static int wbsd_request_regions(struct wbsd_host* host)
+/*
+ * Allocate/free io port ranges
+ */
+
+static int __devinit wbsd_request_region(struct wbsd_host* host, int base)
{
if (io & 0x7)
return -EINVAL;
- if (!request_region(io, 8, DRIVER_NAME))
+ if (!request_region(base, 8, DRIVER_NAME))
return -EIO;
host->base = io;
@@ -1271,19 +1436,25 @@ static int wbsd_request_regions(struct wbsd_host* host)
return 0;
}
-static void wbsd_release_regions(struct wbsd_host* host)
+static void __devexit wbsd_release_regions(struct wbsd_host* host)
{
if (host->base)
release_region(host->base, 8);
+
+ host->base = 0;
if (host->config)
release_region(host->config, 2);
+
+ host->config = 0;
}
-static void wbsd_init_dma(struct wbsd_host* host)
+/*
+ * Allocate/free DMA port and buffer
+ */
+
+static void __devinit wbsd_request_dma(struct wbsd_host* host, int dma)
{
- host->dma = -1;
-
if (dma < 0)
return;
@@ -1294,7 +1465,7 @@ static void wbsd_init_dma(struct wbsd_host* host)
* We need to allocate a special buffer in
* order for ISA to be able to DMA to it.
*/
- host->dma_buffer = kmalloc(65536,
+ host->dma_buffer = kmalloc(WBSD_DMA_SIZE,
GFP_NOIO | GFP_DMA | __GFP_REPEAT | __GFP_NOWARN);
if (!host->dma_buffer)
goto free;
@@ -1302,7 +1473,8 @@ static void wbsd_init_dma(struct wbsd_host* host)
/*
* Translate the address to a physical address.
*/
- host->dma_addr = isa_virt_to_bus(host->dma_buffer);
+ host->dma_addr = dma_map_single(host->mmc->dev, host->dma_buffer,
+ WBSD_DMA_SIZE, DMA_BIDIRECTIONAL);
/*
* ISA DMA must be aligned on a 64k basis.
@@ -1325,6 +1497,10 @@ kfree:
*/
BUG_ON(1);
+ dma_unmap_single(host->mmc->dev, host->dma_addr, WBSD_DMA_SIZE,
+ DMA_BIDIRECTIONAL);
+ host->dma_addr = (dma_addr_t)NULL;
+
kfree(host->dma_buffer);
host->dma_buffer = NULL;
@@ -1336,60 +1512,122 @@ err:
"Falling back on FIFO.\n", dma);
}
-static struct mmc_host_ops wbsd_ops = {
- .request = wbsd_request,
- .set_ios = wbsd_set_ios,
-};
+static void __devexit wbsd_release_dma(struct wbsd_host* host)
+{
+ if (host->dma_addr)
+ dma_unmap_single(host->mmc->dev, host->dma_addr, WBSD_DMA_SIZE,
+ DMA_BIDIRECTIONAL);
+ if (host->dma_buffer)
+ kfree(host->dma_buffer);
+ if (host->dma >= 0)
+ free_dma(host->dma);
+
+ host->dma = -1;
+ host->dma_buffer = NULL;
+ host->dma_addr = (dma_addr_t)NULL;
+}
/*
- * Device probe
+ * Allocate/free IRQ.
*/
-static int wbsd_probe(struct device* dev)
+static int __devinit wbsd_request_irq(struct wbsd_host* host, int irq)
{
- struct wbsd_host* host = NULL;
- struct mmc_host* mmc = NULL;
int ret;
/*
- * Allocate MMC structure.
+ * Allocate interrupt.
*/
- mmc = mmc_alloc_host(sizeof(struct wbsd_host), dev);
- if (!mmc)
- return -ENOMEM;
-
- host = mmc_priv(mmc);
- host->mmc = mmc;
+
+ ret = request_irq(irq, wbsd_irq, SA_SHIRQ, DRIVER_NAME, host);
+ if (ret)
+ return ret;
+ host->irq = irq;
+
/*
- * Scan for hardware.
+ * Set up tasklets.
*/
- ret = wbsd_scan(host);
- if (ret)
- goto freemmc;
+ tasklet_init(&host->card_tasklet, wbsd_tasklet_card, (unsigned long)host);
+ tasklet_init(&host->fifo_tasklet, wbsd_tasklet_fifo, (unsigned long)host);
+ tasklet_init(&host->crc_tasklet, wbsd_tasklet_crc, (unsigned long)host);
+ tasklet_init(&host->timeout_tasklet, wbsd_tasklet_timeout, (unsigned long)host);
+ tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish, (unsigned long)host);
+ tasklet_init(&host->block_tasklet, wbsd_tasklet_block, (unsigned long)host);
+
+ return 0;
+}
- /*
- * Reset the chip.
- */
- wbsd_write_config(host, WBSD_CONF_SWRST, 1);
- wbsd_write_config(host, WBSD_CONF_SWRST, 0);
+static void __devexit wbsd_release_irq(struct wbsd_host* host)
+{
+ if (!host->irq)
+ return;
+ free_irq(host->irq, host);
+
+ host->irq = 0;
+
+ tasklet_kill(&host->card_tasklet);
+ tasklet_kill(&host->fifo_tasklet);
+ tasklet_kill(&host->crc_tasklet);
+ tasklet_kill(&host->timeout_tasklet);
+ tasklet_kill(&host->finish_tasklet);
+ tasklet_kill(&host->block_tasklet);
+}
+
+/*
+ * Allocate all resources for the host.
+ */
+
+static int __devinit wbsd_request_resources(struct wbsd_host* host,
+ int base, int irq, int dma)
+{
+ int ret;
+
/*
* Allocate I/O ports.
*/
- ret = wbsd_request_regions(host);
+ ret = wbsd_request_region(host, base);
if (ret)
- goto release;
+ return ret;
/*
- * Set host parameters.
+ * Allocate interrupt.
*/
- mmc->ops = &wbsd_ops;
- mmc->f_min = 375000;
- mmc->f_max = 24000000;
- mmc->ocr_avail = MMC_VDD_32_33|MMC_VDD_33_34;
+ ret = wbsd_request_irq(host, irq);
+ if (ret)
+ return ret;
+
+ /*
+ * Allocate DMA.
+ */
+ wbsd_request_dma(host, dma);
- spin_lock_init(&host->lock);
+ return 0;
+}
+
+/*
+ * Release all resources for the host.
+ */
+
+static void __devexit wbsd_release_resources(struct wbsd_host* host)
+{
+ wbsd_release_dma(host);
+ wbsd_release_irq(host);
+ wbsd_release_regions(host);
+}
+
+/*
+ * Configure the resources the chip should use.
+ */
+
+static void __devinit wbsd_chip_config(struct wbsd_host* host)
+{
+ /*
+ * Reset the chip.
+ */
+ wbsd_write_config(host, WBSD_CONF_SWRST, 1);
+ wbsd_write_config(host, WBSD_CONF_SWRST, 0);
/*
* Select SD/MMC function.
@@ -1399,165 +1637,241 @@ static int wbsd_probe(struct device* dev)
/*
* Set up card detection.
*/
- wbsd_write_config(host, WBSD_CONF_PINS, 0x02);
+ wbsd_write_config(host, WBSD_CONF_PINS, WBSD_PINS_DETECT_GP11);
/*
- * Configure I/O port.
+ * Configure chip
*/
wbsd_write_config(host, WBSD_CONF_PORT_HI, host->base >> 8);
wbsd_write_config(host, WBSD_CONF_PORT_LO, host->base & 0xff);
-
- /*
- * Allocate interrupt.
- */
- ret = request_irq(irq, wbsd_irq, SA_SHIRQ, DRIVER_NAME, host);
- if (ret)
- goto release;
- host->irq = irq;
+ wbsd_write_config(host, WBSD_CONF_IRQ, host->irq);
- /*
- * Set up tasklets.
- */
- tasklet_init(&host->card_tasklet, wbsd_tasklet_card, (unsigned long)host);
- tasklet_init(&host->fifo_tasklet, wbsd_tasklet_fifo, (unsigned long)host);
- tasklet_init(&host->crc_tasklet, wbsd_tasklet_crc, (unsigned long)host);
- tasklet_init(&host->timeout_tasklet, wbsd_tasklet_timeout, (unsigned long)host);
- tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish, (unsigned long)host);
- tasklet_init(&host->block_tasklet, wbsd_tasklet_block, (unsigned long)host);
+ if (host->dma >= 0)
+ wbsd_write_config(host, WBSD_CONF_DRQ, host->dma);
/*
- * Configure interrupt.
+ * Enable and power up chip.
*/
- wbsd_write_config(host, WBSD_CONF_IRQ, host->irq);
+ wbsd_write_config(host, WBSD_CONF_ENABLE, 1);
+ wbsd_write_config(host, WBSD_CONF_POWER, 0x20);
+}
+
+/*
+ * Check that configured resources are correct.
+ */
+
+static int __devinit wbsd_chip_validate(struct wbsd_host* host)
+{
+ int base, irq, dma;
/*
- * Allocate DMA.
+ * Select SD/MMC function.
*/
- wbsd_init_dma(host);
+ wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
/*
- * If all went well, then configure DMA.
+ * Read configuration.
*/
- if (host->dma >= 0)
- wbsd_write_config(host, WBSD_CONF_DRQ, host->dma);
+ base = wbsd_read_config(host, WBSD_CONF_PORT_HI) << 8;
+ base |= wbsd_read_config(host, WBSD_CONF_PORT_LO);
- /*
- * Maximum number of segments. Worst case is one sector per segment
- * so this will be 64kB/512.
- */
- mmc->max_hw_segs = 128;
- mmc->max_phys_segs = 128;
+ irq = wbsd_read_config(host, WBSD_CONF_IRQ);
+
+ dma = wbsd_read_config(host, WBSD_CONF_DRQ);
/*
- * Maximum number of sectors in one transfer. Also limited by 64kB
- * buffer.
+ * Validate against given configuration.
*/
- mmc->max_sectors = 128;
+ if (base != host->base)
+ return 0;
+ if (irq != host->irq)
+ return 0;
+ if ((dma != host->dma) && (host->dma != -1))
+ return 0;
+
+ return 1;
+}
+
+/*****************************************************************************\
+ * *
+ * Devices setup and shutdown *
+ * *
+\*****************************************************************************/
+
+static int __devinit wbsd_init(struct device* dev, int base, int irq, int dma,
+ int pnp)
+{
+ struct wbsd_host* host = NULL;
+ struct mmc_host* mmc = NULL;
+ int ret;
+
+ ret = wbsd_alloc_mmc(dev);
+ if (ret)
+ return ret;
+
+ mmc = dev_get_drvdata(dev);
+ host = mmc_priv(mmc);
/*
- * Maximum segment size. Could be one segment with the maximum number
- * of segments.
+ * Scan for hardware.
*/
- mmc->max_seg_size = mmc->max_sectors * 512;
+ ret = wbsd_scan(host);
+ if (ret)
+ {
+ if (pnp && (ret == -ENODEV))
+ {
+ printk(KERN_WARNING DRIVER_NAME
+ ": Unable to confirm device presence. You may "
+ "experience lock-ups.\n");
+ }
+ else
+ {
+ wbsd_free_mmc(dev);
+ return ret;
+ }
+ }
/*
- * Enable chip.
+ * Request resources.
*/
- wbsd_write_config(host, WBSD_CONF_ENABLE, 1);
+ ret = wbsd_request_resources(host, io, irq, dma);
+ if (ret)
+ {
+ wbsd_release_resources(host);
+ wbsd_free_mmc(dev);
+ return ret;
+ }
/*
- * Power up chip.
+ * See if chip needs to be configured.
*/
- wbsd_write_config(host, WBSD_CONF_POWER, 0x20);
+ if (pnp && (host->config != 0))
+ {
+ if (!wbsd_chip_validate(host))
+ {
+ printk(KERN_WARNING DRIVER_NAME
+ ": PnP active but chip not configured! "
+ "You probably have a buggy BIOS. "
+ "Configuring chip manually.\n");
+ wbsd_chip_config(host);
+ }
+ }
+ else
+ wbsd_chip_config(host);
/*
* Power Management stuff. No idea how this works.
* Not tested.
*/
#ifdef CONFIG_PM
- wbsd_write_config(host, WBSD_CONF_PME, 0xA0);
+ if (host->config)
+ wbsd_write_config(host, WBSD_CONF_PME, 0xA0);
#endif
+ /*
+ * Allow device to initialise itself properly.
+ */
+ mdelay(5);
/*
* Reset the chip into a known state.
*/
wbsd_init_device(host);
- dev_set_drvdata(dev, mmc);
-
- /*
- * Add host to MMC layer.
- */
mmc_add_host(mmc);
- printk(KERN_INFO "%s: W83L51xD id %x at 0x%x irq %d dma %d\n",
- mmc->host_name, (int)host->chip_id, (int)host->base,
- (int)host->irq, (int)host->dma);
+ printk(KERN_INFO "%s: W83L51xD", mmc->host_name);
+ if (host->chip_id != 0)
+ printk(" id %x", (int)host->chip_id);
+ printk(" at 0x%x irq %d", (int)host->base, (int)host->irq);
+ if (host->dma >= 0)
+ printk(" dma %d", (int)host->dma);
+ else
+ printk(" FIFO");
+ if (pnp)
+ printk(" PnP");
+ printk("\n");
return 0;
-
-release:
- wbsd_release_regions(host);
-
-freemmc:
- mmc_free_host(mmc);
-
- return ret;
}
-/*
- * Device remove
- */
-
-static int wbsd_remove(struct device* dev)
+static void __devexit wbsd_shutdown(struct device* dev, int pnp)
{
struct mmc_host* mmc = dev_get_drvdata(dev);
struct wbsd_host* host;
if (!mmc)
- return 0;
+ return;
host = mmc_priv(mmc);
- /*
- * Unregister host with MMC layer.
- */
mmc_remove_host(mmc);
- /*
- * Power down the SD/MMC function.
- */
- wbsd_unlock_config(host);
- wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
- wbsd_write_config(host, WBSD_CONF_ENABLE, 0);
- wbsd_lock_config(host);
+ if (!pnp)
+ {
+ /*
+ * Power down the SD/MMC function.
+ */
+ wbsd_unlock_config(host);
+ wbsd_write_config(host, WBSD_CONF_DEVICE, DEVICE_SD);
+ wbsd_write_config(host, WBSD_CONF_ENABLE, 0);
+ wbsd_lock_config(host);
+ }
- /*
- * Free resources.
- */
- if (host->dma_buffer)
- kfree(host->dma_buffer);
+ wbsd_release_resources(host);
- if (host->dma >= 0)
- free_dma(host->dma);
+ wbsd_free_mmc(dev);
+}
- free_irq(host->irq, host);
+/*
+ * Non-PnP
+ */
+
+static int __devinit wbsd_probe(struct device* dev)
+{
+ return wbsd_init(dev, io, irq, dma, 0);
+}
+
+static int __devexit wbsd_remove(struct device* dev)
+{
+ wbsd_shutdown(dev, 0);
+
+ return 0;
+}
+
+/*
+ * PnP
+ */
+
+#ifdef CONFIG_PNP
+
+static int __devinit
+wbsd_pnp_probe(struct pnp_dev * pnpdev, const struct pnp_device_id *dev_id)
+{
+ int io, irq, dma;
- tasklet_kill(&host->card_tasklet);
- tasklet_kill(&host->fifo_tasklet);
- tasklet_kill(&host->crc_tasklet);
- tasklet_kill(&host->timeout_tasklet);
- tasklet_kill(&host->finish_tasklet);
- tasklet_kill(&host->block_tasklet);
+ /*
+ * Get resources from PnP layer.
+ */
+ io = pnp_port_start(pnpdev, 0);
+ irq = pnp_irq(pnpdev, 0);
+ if (pnp_dma_valid(pnpdev, 0))
+ dma = pnp_dma(pnpdev, 0);
+ else
+ dma = -1;
- wbsd_release_regions(host);
+ DBGF("PnP resources: port %3x irq %d dma %d\n", io, irq, dma);
- mmc_free_host(mmc);
+ return wbsd_init(&pnpdev->dev, io, irq, dma, 1);
+}
- return 0;
+static void __devexit wbsd_pnp_remove(struct pnp_dev * dev)
+{
+ wbsd_shutdown(&dev->dev, 1);
}
+#endif /* CONFIG_PNP */
+
/*
* Power management
*/
@@ -1581,17 +1895,7 @@ static int wbsd_resume(struct device *dev, u32 level)
#define wbsd_resume NULL
#endif
-static void wbsd_release(struct device *dev)
-{
-}
-
-static struct platform_device wbsd_device = {
- .name = DRIVER_NAME,
- .id = -1,
- .dev = {
- .release = wbsd_release,
- },
-};
+static struct platform_device *wbsd_device;
static struct device_driver wbsd_driver = {
.name = DRIVER_NAME,
@@ -1603,6 +1907,17 @@ static struct device_driver wbsd_driver = {
.resume = wbsd_resume,
};
+#ifdef CONFIG_PNP
+
+static struct pnp_driver wbsd_pnp_driver = {
+ .name = DRIVER_NAME,
+ .id_table = pnp_dev_table,
+ .probe = wbsd_pnp_probe,
+ .remove = wbsd_pnp_remove,
+};
+
+#endif /* CONFIG_PNP */
+
/*
* Module loading/unloading
*/
@@ -1615,29 +1930,57 @@ static int __init wbsd_drv_init(void)
": Winbond W83L51xD SD/MMC card interface driver, "
DRIVER_VERSION "\n");
printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n");
-
- result = driver_register(&wbsd_driver);
- if (result < 0)
- return result;
- result = platform_device_register(&wbsd_device);
- if (result < 0)
- return result;
+#ifdef CONFIG_PNP
+
+ if (!nopnp)
+ {
+ result = pnp_register_driver(&wbsd_pnp_driver);
+ if (result < 0)
+ return result;
+ }
+
+#endif /* CONFIG_PNP */
+
+ if (nopnp)
+ {
+ result = driver_register(&wbsd_driver);
+ if (result < 0)
+ return result;
+
+ wbsd_device = platform_device_register_simple(DRIVER_NAME, -1,
+ NULL, 0);
+ if (IS_ERR(wbsd_device))
+ return PTR_ERR(wbsd_device);
+ }
return 0;
}
static void __exit wbsd_drv_exit(void)
{
- platform_device_unregister(&wbsd_device);
+#ifdef CONFIG_PNP
+
+ if (!nopnp)
+ pnp_unregister_driver(&wbsd_pnp_driver);
- driver_unregister(&wbsd_driver);
+#endif /* CONFIG_PNP */
+
+ if (nopnp)
+ {
+ platform_device_unregister(wbsd_device);
+
+ driver_unregister(&wbsd_driver);
+ }
DBG("unloaded\n");
}
module_init(wbsd_drv_init);
module_exit(wbsd_drv_exit);
+#ifdef CONFIG_PNP
+module_param(nopnp, uint, 0444);
+#endif
module_param(io, uint, 0444);
module_param(irq, uint, 0444);
module_param(dma, int, 0444);
@@ -1646,6 +1989,9 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Winbond W83L51xD SD/MMC card interface driver");
MODULE_VERSION(DRIVER_VERSION);
+#ifdef CONFIG_PNP
+MODULE_PARM_DESC(nopnp, "Scan for device instead of relying on PNP. (default 0)");
+#endif
MODULE_PARM_DESC(io, "I/O base to allocate. Must be 8 byte aligned. (default 0x248)");
MODULE_PARM_DESC(irq, "IRQ to allocate. (default 6)");
MODULE_PARM_DESC(dma, "DMA channel to allocate. -1 for no DMA. (default 2)");
diff --git a/drivers/mmc/wbsd.h b/drivers/mmc/wbsd.h
index fdc03b56a81..864f30828d0 100644
--- a/drivers/mmc/wbsd.h
+++ b/drivers/mmc/wbsd.h
@@ -35,6 +35,12 @@ const int valid_ids[] = {
#define DEVICE_SD 0x03
+#define WBSD_PINS_DAT3_HI 0x20
+#define WBSD_PINS_DAT3_OUT 0x10
+#define WBSD_PINS_GP11_HI 0x04
+#define WBSD_PINS_DETECT_GP11 0x02
+#define WBSD_PINS_DETECT_DAT3 0x01
+
#define WBSD_CMDR 0x00
#define WBSD_DFR 0x01
#define WBSD_EIR 0x02
@@ -133,6 +139,7 @@ const int valid_ids[] = {
#define WBSD_CRC_OK 0x05 /* S010E (00101) */
#define WBSD_CRC_FAIL 0x0B /* S101E (01011) */
+#define WBSD_DMA_SIZE 65536
struct wbsd_host
{
@@ -140,6 +147,11 @@ struct wbsd_host
spinlock_t lock; /* Mutex */
+ int flags; /* Driver states */
+
+#define WBSD_FCARD_PRESENT (1<<0) /* Card is present */
+#define WBSD_FIGNORE_DETECT (1<<1) /* Ignore card detection */
+
struct mmc_request* mrq; /* Current request */
u8 isr; /* Accumulated ISR */
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index b5e07604343..80ec9aa575b 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -2202,9 +2202,8 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (vortex_debug > 6) {
printk(KERN_DEBUG "boomerang_start_xmit()\n");
- if (vortex_debug > 3)
- printk(KERN_DEBUG "%s: Trying to send a packet, Tx index %d.\n",
- dev->name, vp->cur_tx);
+ printk(KERN_DEBUG "%s: Trying to send a packet, Tx index %d.\n",
+ dev->name, vp->cur_tx);
}
if (vp->cur_tx - vp->dirty_tx >= TX_RING_SIZE) {
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index ca4c9ac7e11..ca7746dd164 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -54,6 +54,7 @@
#include <linux/config.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/compiler.h>
#include <linux/netdevice.h>
@@ -92,16 +93,17 @@ KERN_INFO DRV_NAME ": 10/100 PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE
MODULE_AUTHOR("Jeff Garzik <jgarzik@pobox.com>");
MODULE_DESCRIPTION("RealTek RTL-8139C+ series 10/100 PCI Ethernet driver");
+MODULE_VERSION(DRV_VERSION);
MODULE_LICENSE("GPL");
static int debug = -1;
-MODULE_PARM (debug, "i");
+module_param(debug, int, 0);
MODULE_PARM_DESC (debug, "8139cp: bitmapped message enable number");
/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
The RTL chips use a 64 element hash table based on the Ethernet CRC. */
static int multicast_filter_limit = 32;
-MODULE_PARM (multicast_filter_limit, "i");
+module_param(multicast_filter_limit, int, 0);
MODULE_PARM_DESC (multicast_filter_limit, "8139cp: maximum number of filtered multicast addresses");
#define PFX DRV_NAME ": "
@@ -187,6 +189,9 @@ enum {
RingEnd = (1 << 30), /* End of descriptor ring */
FirstFrag = (1 << 29), /* First segment of a packet */
LastFrag = (1 << 28), /* Final segment of a packet */
+ LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */
+ MSSShift = 16, /* MSS value position */
+ MSSMask = 0xfff, /* MSS value: 11 bits */
TxError = (1 << 23), /* Tx error summary */
RxError = (1 << 20), /* Rx error summary */
IPCS = (1 << 18), /* Calculate IP checksum */
@@ -313,7 +318,7 @@ struct cp_desc {
struct ring_info {
struct sk_buff *skb;
dma_addr_t mapping;
- unsigned frag;
+ u32 len;
};
struct cp_dma_stats {
@@ -395,6 +400,9 @@ struct cp_private {
static void __cp_set_rx_mode (struct net_device *dev);
static void cp_tx (struct cp_private *cp);
static void cp_clean_rings (struct cp_private *cp);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void cp_poll_controller(struct net_device *dev);
+#endif
static struct pci_device_id cp_pci_tbl[] = {
{ PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139,
@@ -689,6 +697,19 @@ cp_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
return IRQ_HANDLED;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling receive - used by netconsole and other diagnostic tools
+ * to allow network i/o with interrupts disabled.
+ */
+static void cp_poll_controller(struct net_device *dev)
+{
+ disable_irq(dev->irq);
+ cp_interrupt(dev->irq, dev, NULL);
+ enable_irq(dev->irq);
+}
+#endif
+
static void cp_tx (struct cp_private *cp)
{
unsigned tx_head = cp->tx_head;
@@ -708,7 +729,7 @@ static void cp_tx (struct cp_private *cp)
BUG();
pci_unmap_single(cp->pdev, cp->tx_skb[tx_tail].mapping,
- skb->len, PCI_DMA_TODEVICE);
+ cp->tx_skb[tx_tail].len, PCI_DMA_TODEVICE);
if (status & LastFrag) {
if (status & (TxError | TxFIFOUnder)) {
@@ -750,10 +771,11 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
{
struct cp_private *cp = netdev_priv(dev);
unsigned entry;
- u32 eor;
+ u32 eor, flags;
#if CP_VLAN_TAG_USED
u32 vlan_tag = 0;
#endif
+ int mss = 0;
spin_lock_irq(&cp->lock);
@@ -773,6 +795,9 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
entry = cp->tx_head;
eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
+ if (dev->features & NETIF_F_TSO)
+ mss = skb_shinfo(skb)->tso_size;
+
if (skb_shinfo(skb)->nr_frags == 0) {
struct cp_desc *txd = &cp->tx_ring[entry];
u32 len;
@@ -784,26 +809,26 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
txd->addr = cpu_to_le64(mapping);
wmb();
- if (skb->ip_summed == CHECKSUM_HW) {
+ flags = eor | len | DescOwn | FirstFrag | LastFrag;
+
+ if (mss)
+ flags |= LargeSend | ((mss & MSSMask) << MSSShift);
+ else if (skb->ip_summed == CHECKSUM_HW) {
const struct iphdr *ip = skb->nh.iph;
if (ip->protocol == IPPROTO_TCP)
- txd->opts1 = cpu_to_le32(eor | len | DescOwn |
- FirstFrag | LastFrag |
- IPCS | TCPCS);
+ flags |= IPCS | TCPCS;
else if (ip->protocol == IPPROTO_UDP)
- txd->opts1 = cpu_to_le32(eor | len | DescOwn |
- FirstFrag | LastFrag |
- IPCS | UDPCS);
+ flags |= IPCS | UDPCS;
else
- BUG();
- } else
- txd->opts1 = cpu_to_le32(eor | len | DescOwn |
- FirstFrag | LastFrag);
+ WARN_ON(1); /* we need a WARN() */
+ }
+
+ txd->opts1 = cpu_to_le32(flags);
wmb();
cp->tx_skb[entry].skb = skb;
cp->tx_skb[entry].mapping = mapping;
- cp->tx_skb[entry].frag = 0;
+ cp->tx_skb[entry].len = len;
entry = NEXT_TX(entry);
} else {
struct cp_desc *txd;
@@ -821,7 +846,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
first_len, PCI_DMA_TODEVICE);
cp->tx_skb[entry].skb = skb;
cp->tx_skb[entry].mapping = first_mapping;
- cp->tx_skb[entry].frag = 1;
+ cp->tx_skb[entry].len = first_len;
entry = NEXT_TX(entry);
for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
@@ -837,16 +862,19 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
len, PCI_DMA_TODEVICE);
eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
- if (skb->ip_summed == CHECKSUM_HW) {
- ctrl = eor | len | DescOwn | IPCS;
+ ctrl = eor | len | DescOwn;
+
+ if (mss)
+ ctrl |= LargeSend |
+ ((mss & MSSMask) << MSSShift);
+ else if (skb->ip_summed == CHECKSUM_HW) {
if (ip->protocol == IPPROTO_TCP)
- ctrl |= TCPCS;
+ ctrl |= IPCS | TCPCS;
else if (ip->protocol == IPPROTO_UDP)
- ctrl |= UDPCS;
+ ctrl |= IPCS | UDPCS;
else
BUG();
- } else
- ctrl = eor | len | DescOwn;
+ }
if (frag == skb_shinfo(skb)->nr_frags - 1)
ctrl |= LastFrag;
@@ -861,7 +889,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
cp->tx_skb[entry].skb = skb;
cp->tx_skb[entry].mapping = mapping;
- cp->tx_skb[entry].frag = frag + 2;
+ cp->tx_skb[entry].len = len;
entry = NEXT_TX(entry);
}
@@ -1075,7 +1103,6 @@ static int cp_refill_rx (struct cp_private *cp)
cp->rx_skb[i].mapping = pci_map_single(cp->pdev,
skb->tail, cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
cp->rx_skb[i].skb = skb;
- cp->rx_skb[i].frag = 0;
cp->rx_ring[i].opts2 = 0;
cp->rx_ring[i].addr = cpu_to_le64(cp->rx_skb[i].mapping);
@@ -1127,9 +1154,6 @@ static void cp_clean_rings (struct cp_private *cp)
{
unsigned i;
- memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE);
- memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
-
for (i = 0; i < CP_RX_RING_SIZE; i++) {
if (cp->rx_skb[i].skb) {
pci_unmap_single(cp->pdev, cp->rx_skb[i].mapping,
@@ -1141,13 +1165,18 @@ static void cp_clean_rings (struct cp_private *cp)
for (i = 0; i < CP_TX_RING_SIZE; i++) {
if (cp->tx_skb[i].skb) {
struct sk_buff *skb = cp->tx_skb[i].skb;
+
pci_unmap_single(cp->pdev, cp->tx_skb[i].mapping,
- skb->len, PCI_DMA_TODEVICE);
- dev_kfree_skb(skb);
+ cp->tx_skb[i].len, PCI_DMA_TODEVICE);
+ if (le32_to_cpu(cp->tx_ring[i].opts1) & LastFrag)
+ dev_kfree_skb(skb);
cp->net_stats.tx_dropped++;
}
}
+ memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE);
+ memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
+
memset(&cp->rx_skb, 0, sizeof(struct ring_info) * CP_RX_RING_SIZE);
memset(&cp->tx_skb, 0, sizeof(struct ring_info) * CP_TX_RING_SIZE);
}
@@ -1539,6 +1568,8 @@ static struct ethtool_ops cp_ethtool_ops = {
.set_tx_csum = ethtool_op_set_tx_csum, /* local! */
.get_sg = ethtool_op_get_sg,
.set_sg = ethtool_op_set_sg,
+ .get_tso = ethtool_op_get_tso,
+ .set_tso = ethtool_op_set_tso,
.get_regs = cp_get_regs,
.get_wol = cp_get_wol,
.set_wol = cp_set_wol,
@@ -1750,6 +1781,9 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
dev->get_stats = cp_get_stats;
dev->do_ioctl = cp_ioctl;
dev->poll = cp_rx_poll;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = cp_poll_controller;
+#endif
dev->weight = 16; /* arbitrary? from NAPI_HOWTO.txt. */
#ifdef BROKEN
dev->change_mtu = cp_change_mtu;
@@ -1769,6 +1803,10 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (pci_using_dac)
dev->features |= NETIF_F_HIGHDMA;
+#if 0 /* disabled by default until verified */
+ dev->features |= NETIF_F_TSO;
+#endif
+
dev->irq = pdev->irq;
rc = register_netdev(dev);
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index d4bd20c21a1..5a4a08a7c95 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -569,7 +569,7 @@ struct rtl_extra_stats {
};
struct rtl8139_private {
- void *mmio_addr;
+ void __iomem *mmio_addr;
int drv_flags;
struct pci_dev *pci_dev;
u32 msg_enable;
@@ -614,7 +614,7 @@ MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered mu
MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps");
MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)");
-static int read_eeprom (void *ioaddr, int location, int addr_len);
+static int read_eeprom (void __iomem *ioaddr, int location, int addr_len);
static int rtl8139_open (struct net_device *dev);
static int mdio_read (struct net_device *dev, int phy_id, int location);
static void mdio_write (struct net_device *dev, int phy_id, int location,
@@ -638,46 +638,20 @@ static void __set_rx_mode (struct net_device *dev);
static void rtl8139_hw_start (struct net_device *dev);
static struct ethtool_ops rtl8139_ethtool_ops;
-#ifdef USE_IO_OPS
-
-#define RTL_R8(reg) inb (((unsigned long)ioaddr) + (reg))
-#define RTL_R16(reg) inw (((unsigned long)ioaddr) + (reg))
-#define RTL_R32(reg) ((unsigned long) inl (((unsigned long)ioaddr) + (reg)))
-#define RTL_W8(reg, val8) outb ((val8), ((unsigned long)ioaddr) + (reg))
-#define RTL_W16(reg, val16) outw ((val16), ((unsigned long)ioaddr) + (reg))
-#define RTL_W32(reg, val32) outl ((val32), ((unsigned long)ioaddr) + (reg))
-#define RTL_W8_F RTL_W8
-#define RTL_W16_F RTL_W16
-#define RTL_W32_F RTL_W32
-#undef readb
-#undef readw
-#undef readl
-#undef writeb
-#undef writew
-#undef writel
-#define readb(addr) inb((unsigned long)(addr))
-#define readw(addr) inw((unsigned long)(addr))
-#define readl(addr) inl((unsigned long)(addr))
-#define writeb(val,addr) outb((val),(unsigned long)(addr))
-#define writew(val,addr) outw((val),(unsigned long)(addr))
-#define writel(val,addr) outl((val),(unsigned long)(addr))
-
-#else
-
/* write MMIO register, with flush */
/* Flush avoids rtl8139 bug w/ posted MMIO writes */
-#define RTL_W8_F(reg, val8) do { writeb ((val8), ioaddr + (reg)); readb (ioaddr + (reg)); } while (0)
-#define RTL_W16_F(reg, val16) do { writew ((val16), ioaddr + (reg)); readw (ioaddr + (reg)); } while (0)
-#define RTL_W32_F(reg, val32) do { writel ((val32), ioaddr + (reg)); readl (ioaddr + (reg)); } while (0)
+#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0)
+#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0)
+#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0)
#define MMIO_FLUSH_AUDIT_COMPLETE 1
#if MMIO_FLUSH_AUDIT_COMPLETE
/* write MMIO register */
-#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg))
-#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg))
-#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg))
+#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg))
+#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg))
+#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg))
#else
@@ -689,11 +663,9 @@ static struct ethtool_ops rtl8139_ethtool_ops;
#endif /* MMIO_FLUSH_AUDIT_COMPLETE */
/* read MMIO register */
-#define RTL_R8(reg) readb (ioaddr + (reg))
-#define RTL_R16(reg) readw (ioaddr + (reg))
-#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg)))
-
-#endif /* USE_IO_OPS */
+#define RTL_R8(reg) ioread8 (ioaddr + (reg))
+#define RTL_R16(reg) ioread16 (ioaddr + (reg))
+#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg)))
static const u16 rtl8139_intr_mask =
@@ -740,10 +712,13 @@ static void __rtl8139_cleanup_dev (struct net_device *dev)
assert (tp->pci_dev != NULL);
pdev = tp->pci_dev;
-#ifndef USE_IO_OPS
+#ifdef USE_IO_OPS
+ if (tp->mmio_addr)
+ ioport_unmap (tp->mmio_addr);
+#else
if (tp->mmio_addr)
- iounmap (tp->mmio_addr);
-#endif /* !USE_IO_OPS */
+ pci_iounmap (pdev, tp->mmio_addr);
+#endif /* USE_IO_OPS */
/* it's ok to call this even if we have no regions to free */
pci_release_regions (pdev);
@@ -753,7 +728,7 @@ static void __rtl8139_cleanup_dev (struct net_device *dev)
}
-static void rtl8139_chip_reset (void *ioaddr)
+static void rtl8139_chip_reset (void __iomem *ioaddr)
{
int i;
@@ -773,7 +748,7 @@ static void rtl8139_chip_reset (void *ioaddr)
static int __devinit rtl8139_init_board (struct pci_dev *pdev,
struct net_device **dev_out)
{
- void *ioaddr;
+ void __iomem *ioaddr;
struct net_device *dev;
struct rtl8139_private *tp;
u8 tmp8;
@@ -855,13 +830,18 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
pci_set_master (pdev);
#ifdef USE_IO_OPS
- ioaddr = (void *) pio_start;
+ ioaddr = ioport_map(pio_start, pio_len);
+ if (!ioaddr) {
+ printk (KERN_ERR PFX "%s: cannot map PIO, aborting\n", pci_name(pdev));
+ rc = -EIO;
+ goto err_out;
+ }
dev->base_addr = pio_start;
tp->mmio_addr = ioaddr;
tp->regs_len = pio_len;
#else
/* ioremap MMIO region */
- ioaddr = ioremap (mmio_start, mmio_len);
+ ioaddr = pci_iomap(pdev, 1, 0);
if (ioaddr == NULL) {
printk (KERN_ERR PFX "%s: cannot remap MMIO, aborting\n", pci_name(pdev));
rc = -EIO;
@@ -947,7 +927,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
struct net_device *dev = NULL;
struct rtl8139_private *tp;
int i, addr_len, option;
- void *ioaddr;
+ void __iomem *ioaddr;
static int board_idx = -1;
u8 pci_rev;
@@ -1147,47 +1127,46 @@ static void __devexit rtl8139_remove_one (struct pci_dev *pdev)
No extra delay is needed with 33Mhz PCI, but 66Mhz may change this.
*/
-#define eeprom_delay() readl(ee_addr)
+#define eeprom_delay() RTL_R32(Cfg9346)
/* The EEPROM commands include the alway-set leading bit. */
#define EE_WRITE_CMD (5)
#define EE_READ_CMD (6)
#define EE_ERASE_CMD (7)
-static int __devinit read_eeprom (void *ioaddr, int location, int addr_len)
+static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len)
{
int i;
unsigned retval = 0;
- void *ee_addr = ioaddr + Cfg9346;
int read_cmd = location | (EE_READ_CMD << addr_len);
- writeb (EE_ENB & ~EE_CS, ee_addr);
- writeb (EE_ENB, ee_addr);
+ RTL_W8 (Cfg9346, EE_ENB & ~EE_CS);
+ RTL_W8 (Cfg9346, EE_ENB);
eeprom_delay ();
/* Shift the read command bits out. */
for (i = 4 + addr_len; i >= 0; i--) {
int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
- writeb (EE_ENB | dataval, ee_addr);
+ RTL_W8 (Cfg9346, EE_ENB | dataval);
eeprom_delay ();
- writeb (EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
+ RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK);
eeprom_delay ();
}
- writeb (EE_ENB, ee_addr);
+ RTL_W8 (Cfg9346, EE_ENB);
eeprom_delay ();
for (i = 16; i > 0; i--) {
- writeb (EE_ENB | EE_SHIFT_CLK, ee_addr);
+ RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK);
eeprom_delay ();
retval =
- (retval << 1) | ((readb (ee_addr) & EE_DATA_READ) ? 1 :
+ (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 :
0);
- writeb (EE_ENB, ee_addr);
+ RTL_W8 (Cfg9346, EE_ENB);
eeprom_delay ();
}
/* Terminate the EEPROM access. */
- writeb (~EE_CS, ee_addr);
+ RTL_W8 (Cfg9346, ~EE_CS);
eeprom_delay ();
return retval;
@@ -1206,7 +1185,7 @@ static int __devinit read_eeprom (void *ioaddr, int location, int addr_len)
#define MDIO_WRITE0 (MDIO_DIR)
#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT)
-#define mdio_delay(mdio_addr) readb(mdio_addr)
+#define mdio_delay() RTL_R8(Config4)
static char mii_2_8139_map[8] = {
@@ -1223,15 +1202,15 @@ static char mii_2_8139_map[8] = {
#ifdef CONFIG_8139TOO_8129
/* Syncronize the MII management interface by shifting 32 one bits out. */
-static void mdio_sync (void *mdio_addr)
+static void mdio_sync (void __iomem *ioaddr)
{
int i;
for (i = 32; i >= 0; i--) {
- writeb (MDIO_WRITE1, mdio_addr);
- mdio_delay (mdio_addr);
- writeb (MDIO_WRITE1 | MDIO_CLK, mdio_addr);
- mdio_delay (mdio_addr);
+ RTL_W8 (Config4, MDIO_WRITE1);
+ mdio_delay ();
+ RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK);
+ mdio_delay ();
}
}
#endif
@@ -1241,35 +1220,36 @@ static int mdio_read (struct net_device *dev, int phy_id, int location)
struct rtl8139_private *tp = netdev_priv(dev);
int retval = 0;
#ifdef CONFIG_8139TOO_8129
- void *mdio_addr = tp->mmio_addr + Config4;
+ void __iomem *ioaddr = tp->mmio_addr;
int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
int i;
#endif
if (phy_id > 31) { /* Really a 8139. Use internal registers. */
+ void __iomem *ioaddr = tp->mmio_addr;
return location < 8 && mii_2_8139_map[location] ?
- readw (tp->mmio_addr + mii_2_8139_map[location]) : 0;
+ RTL_R16 (mii_2_8139_map[location]) : 0;
}
#ifdef CONFIG_8139TOO_8129
- mdio_sync (mdio_addr);
+ mdio_sync (ioaddr);
/* Shift the read command bits out. */
for (i = 15; i >= 0; i--) {
int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0;
- writeb (MDIO_DIR | dataval, mdio_addr);
- mdio_delay (mdio_addr);
- writeb (MDIO_DIR | dataval | MDIO_CLK, mdio_addr);
- mdio_delay (mdio_addr);
+ RTL_W8 (Config4, MDIO_DIR | dataval);
+ mdio_delay ();
+ RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK);
+ mdio_delay ();
}
/* Read the two transition, 16 data, and wire-idle bits. */
for (i = 19; i > 0; i--) {
- writeb (0, mdio_addr);
- mdio_delay (mdio_addr);
- retval = (retval << 1) | ((readb (mdio_addr) & MDIO_DATA_IN) ? 1 : 0);
- writeb (MDIO_CLK, mdio_addr);
- mdio_delay (mdio_addr);
+ RTL_W8 (Config4, 0);
+ mdio_delay ();
+ retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0);
+ RTL_W8 (Config4, MDIO_CLK);
+ mdio_delay ();
}
#endif
@@ -1282,13 +1262,13 @@ static void mdio_write (struct net_device *dev, int phy_id, int location,
{
struct rtl8139_private *tp = netdev_priv(dev);
#ifdef CONFIG_8139TOO_8129
- void *mdio_addr = tp->mmio_addr + Config4;
+ void __iomem *ioaddr = tp->mmio_addr;
int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;
int i;
#endif
if (phy_id > 31) { /* Really a 8139. Use internal registers. */
- void *ioaddr = tp->mmio_addr;
+ void __iomem *ioaddr = tp->mmio_addr;
if (location == 0) {
RTL_W8 (Cfg9346, Cfg9346_Unlock);
RTL_W16 (BasicModeCtrl, value);
@@ -1299,23 +1279,23 @@ static void mdio_write (struct net_device *dev, int phy_id, int location,
}
#ifdef CONFIG_8139TOO_8129
- mdio_sync (mdio_addr);
+ mdio_sync (ioaddr);
/* Shift the command bits out. */
for (i = 31; i >= 0; i--) {
int dataval =
(mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
- writeb (dataval, mdio_addr);
- mdio_delay (mdio_addr);
- writeb (dataval | MDIO_CLK, mdio_addr);
- mdio_delay (mdio_addr);
+ RTL_W8 (Config4, dataval);
+ mdio_delay ();
+ RTL_W8 (Config4, dataval | MDIO_CLK);
+ mdio_delay ();
}
/* Clear out extra bits. */
for (i = 2; i > 0; i--) {
- writeb (0, mdio_addr);
- mdio_delay (mdio_addr);
- writeb (MDIO_CLK, mdio_addr);
- mdio_delay (mdio_addr);
+ RTL_W8 (Config4, 0);
+ mdio_delay ();
+ RTL_W8 (Config4, MDIO_CLK);
+ mdio_delay ();
}
#endif
}
@@ -1325,7 +1305,7 @@ static int rtl8139_open (struct net_device *dev)
{
struct rtl8139_private *tp = netdev_priv(dev);
int retval;
- void *ioaddr = tp->mmio_addr;
+ void __iomem *ioaddr = tp->mmio_addr;
retval = request_irq (dev->irq, rtl8139_interrupt, SA_SHIRQ, dev->name, dev);
if (retval)
@@ -1382,7 +1362,7 @@ static void rtl_check_media (struct net_device *dev, unsigned int init_media)
static void rtl8139_hw_start (struct net_device *dev)
{
struct rtl8139_private *tp = netdev_priv(dev);
- void *ioaddr = tp->mmio_addr;
+ void __iomem *ioaddr = tp->mmio_addr;
u32 i;
u8 tmp;
@@ -1484,7 +1464,7 @@ static void rtl8139_tune_twister (struct net_device *dev,
struct rtl8139_private *tp)
{
int linkcase;
- void *ioaddr = tp->mmio_addr;
+ void __iomem *ioaddr = tp->mmio_addr;
/* This is a complicated state machine to configure the "twister" for
impedance/echos based on the cable length.
@@ -1568,7 +1548,7 @@ static void rtl8139_tune_twister (struct net_device *dev,
static inline void rtl8139_thread_iter (struct net_device *dev,
struct rtl8139_private *tp,
- void *ioaddr)
+ void __iomem *ioaddr)
{
int mii_lpa;
@@ -1626,7 +1606,7 @@ static int rtl8139_thread (void *data)
do {
timeout = interruptible_sleep_on_timeout (&tp->thr_wait, timeout);
/* make swsusp happy with our thread */
- try_to_freeze(PF_FREEZE);
+ try_to_freeze();
} while (!signal_pending (current) && (timeout > 0));
if (signal_pending (current)) {
@@ -1676,7 +1656,7 @@ static inline void rtl8139_tx_clear (struct rtl8139_private *tp)
static void rtl8139_tx_timeout (struct net_device *dev)
{
struct rtl8139_private *tp = netdev_priv(dev);
- void *ioaddr = tp->mmio_addr;
+ void __iomem *ioaddr = tp->mmio_addr;
int i;
u8 tmp8;
unsigned long flags;
@@ -1721,7 +1701,7 @@ static void rtl8139_tx_timeout (struct net_device *dev)
static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
{
struct rtl8139_private *tp = netdev_priv(dev);
- void *ioaddr = tp->mmio_addr;
+ void __iomem *ioaddr = tp->mmio_addr;
unsigned int entry;
unsigned int len = skb->len;
@@ -1763,7 +1743,7 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
static void rtl8139_tx_interrupt (struct net_device *dev,
struct rtl8139_private *tp,
- void *ioaddr)
+ void __iomem *ioaddr)
{
unsigned long dirty_tx, tx_left;
@@ -1833,7 +1813,7 @@ static void rtl8139_tx_interrupt (struct net_device *dev,
/* TODO: clean this up! Rx reset need not be this intensive */
static void rtl8139_rx_err (u32 rx_status, struct net_device *dev,
- struct rtl8139_private *tp, void *ioaddr)
+ struct rtl8139_private *tp, void __iomem *ioaddr)
{
u8 tmp8;
#ifdef CONFIG_8139_OLD_RX_RESET
@@ -1930,7 +1910,7 @@ static __inline__ void wrap_copy(struct sk_buff *skb, const unsigned char *ring,
static void rtl8139_isr_ack(struct rtl8139_private *tp)
{
- void *ioaddr = tp->mmio_addr;
+ void __iomem *ioaddr = tp->mmio_addr;
u16 status;
status = RTL_R16 (IntrStatus) & RxAckBits;
@@ -1949,7 +1929,7 @@ static void rtl8139_isr_ack(struct rtl8139_private *tp)
static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
int budget)
{
- void *ioaddr = tp->mmio_addr;
+ void __iomem *ioaddr = tp->mmio_addr;
int received = 0;
unsigned char *rx_ring = tp->rx_ring;
unsigned int cur_rx = tp->cur_rx;
@@ -2087,7 +2067,7 @@ out:
static void rtl8139_weird_interrupt (struct net_device *dev,
struct rtl8139_private *tp,
- void *ioaddr,
+ void __iomem *ioaddr,
int status, int link_changed)
{
DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n",
@@ -2127,7 +2107,7 @@ static void rtl8139_weird_interrupt (struct net_device *dev,
static int rtl8139_poll(struct net_device *dev, int *budget)
{
struct rtl8139_private *tp = netdev_priv(dev);
- void *ioaddr = tp->mmio_addr;
+ void __iomem *ioaddr = tp->mmio_addr;
int orig_budget = min(*budget, dev->quota);
int done = 1;
@@ -2165,7 +2145,7 @@ static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
{
struct net_device *dev = (struct net_device *) dev_instance;
struct rtl8139_private *tp = netdev_priv(dev);
- void *ioaddr = tp->mmio_addr;
+ void __iomem *ioaddr = tp->mmio_addr;
u16 status, ackstat;
int link_changed = 0; /* avoid bogus "uninit" warning */
int handled = 0;
@@ -2241,7 +2221,7 @@ static void rtl8139_poll_controller(struct net_device *dev)
static int rtl8139_close (struct net_device *dev)
{
struct rtl8139_private *tp = netdev_priv(dev);
- void *ioaddr = tp->mmio_addr;
+ void __iomem *ioaddr = tp->mmio_addr;
int ret = 0;
unsigned long flags;
@@ -2304,7 +2284,7 @@ static int rtl8139_close (struct net_device *dev)
static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct rtl8139_private *np = netdev_priv(dev);
- void *ioaddr = np->mmio_addr;
+ void __iomem *ioaddr = np->mmio_addr;
spin_lock_irq(&np->lock);
if (rtl_chip_info[np->chipset].flags & HasLWake) {
@@ -2338,7 +2318,7 @@ static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct rtl8139_private *np = netdev_priv(dev);
- void *ioaddr = np->mmio_addr;
+ void __iomem *ioaddr = np->mmio_addr;
u32 support;
u8 cfg3, cfg5;
@@ -2506,7 +2486,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
static struct net_device_stats *rtl8139_get_stats (struct net_device *dev)
{
struct rtl8139_private *tp = netdev_priv(dev);
- void *ioaddr = tp->mmio_addr;
+ void __iomem *ioaddr = tp->mmio_addr;
unsigned long flags;
if (netif_running(dev)) {
@@ -2525,7 +2505,7 @@ static struct net_device_stats *rtl8139_get_stats (struct net_device *dev)
static void __set_rx_mode (struct net_device *dev)
{
struct rtl8139_private *tp = netdev_priv(dev);
- void *ioaddr = tp->mmio_addr;
+ void __iomem *ioaddr = tp->mmio_addr;
u32 mc_filter[2]; /* Multicast hash filter */
int i, rx_mode;
u32 tmp;
@@ -2586,7 +2566,7 @@ static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata (pdev);
struct rtl8139_private *tp = netdev_priv(dev);
- void *ioaddr = tp->mmio_addr;
+ void __iomem *ioaddr = tp->mmio_addr;
unsigned long flags;
pci_save_state (pdev);
diff --git a/drivers/net/8390.c b/drivers/net/8390.c
index bab16bcc9ae..6d76f3a99b1 100644
--- a/drivers/net/8390.c
+++ b/drivers/net/8390.c
@@ -225,9 +225,9 @@ void ei_tx_timeout(struct net_device *dev)
unsigned long icucr;
local_irq_save(flags);
- icucr = inl(ICUCR1);
+ icucr = inl(M32R_ICU_CR1_PORTL);
icucr |= M32R_ICUCR_ISMOD11;
- outl(icucr, ICUCR1);
+ outl(icucr, M32R_ICU_CR1_PORTL);
local_irq_restore(flags);
#endif
ei_local->stat.tx_errors++;
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 3a0a55b62aa..fa9f76c953d 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -824,6 +824,18 @@ config SMC9194
<file:Documentation/networking/net-modules.txt>. The module
will be called smc9194.
+config DM9000
+ tristate "DM9000 support"
+ depends on ARM && NET_ETHERNET
+ select CRC32
+ select MII
+ ---help---
+ Support for DM9000 chipset.
+
+ To compile this driver as a module, choose M here and read
+ <file:Documentation/networking/net-modules.txt>. The module will be
+ called dm9000.
+
config NET_VENDOR_RACAL
bool "Racal-Interlan (Micom) NI cards"
depends on NET_ETHERNET && ISA
@@ -989,21 +1001,6 @@ config EEXPRESS_PRO
<file:Documentation/networking/net-modules.txt>. The module
will be called eepro.
-config FMV18X
- tristate "FMV-181/182/183/184 support (OBSOLETE)"
- depends on NET_ISA && OBSOLETE
- ---help---
- If you have a Fujitsu FMV-181/182/183/184 network (Ethernet) card,
- say Y and read the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- If you use an FMV-183 or FMV-184 and it is not working, you may need
- to disable Plug & Play mode of the card.
-
- To compile this driver as a module, choose M here and read
- <file:Documentation/networking/net-modules.txt>. The module
- will be called fmv18x.
-
config HPLAN_PLUS
tristate "HP PCLAN+ (27247B and 27252A) support"
depends on NET_ISA
@@ -1092,14 +1089,6 @@ config SEEQ8005
<file:Documentation/networking/net-modules.txt>. The module
will be called seeq8005.
-config SK_G16
- tristate "SK_G16 support (OBSOLETE)"
- depends on NET_ISA && OBSOLETE
- help
- If you have a network (Ethernet) card of this type, say Y and read
- the Ethernet-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
config SKMC
tristate "SKnet MCA support"
depends on NET_ETHERNET && MCA && BROKEN
@@ -1555,6 +1544,7 @@ config SIS900
tristate "SiS 900/7016 PCI Fast Ethernet Adapter support"
depends on NET_PCI && PCI
select CRC32
+ select MII
---help---
This is a driver for the Fast Ethernet PCI network cards based on
the SiS 900 and SiS 7016 chips. The SiS 900 core is also embedded in
@@ -1931,6 +1921,18 @@ config R8169_VLAN
If in doubt, say Y.
+config SKGE
+ tristate "New SysKonnect GigaEthernet support (EXPERIMENTAL)"
+ depends on PCI && EXPERIMENTAL
+ select CRC32
+ ---help---
+ This driver support the Marvell Yukon or SysKonnect SK-98xx/SK-95xx
+ and related Gigabit Ethernet adapters. It is a new smaller driver
+ driver with better performance and more complete ethtool support.
+
+ It does not support the link failover and network management
+ features that "portable" vendor supplied sk98lin driver does.
+
config SK98LIN
tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support"
depends on PCI
@@ -2031,6 +2033,15 @@ config TIGON3
To compile this driver as a module, choose M here: the module
will be called tg3. This is recommended.
+config BNX2
+ tristate "Broadcom NetXtremeII support"
+ depends on PCI
+ help
+ This driver supports Broadcom NetXtremeII gigabit Ethernet cards.
+
+ To compile this driver as a module, choose M here: the module
+ will be called bnx2. This is recommended.
+
config GIANFAR
tristate "Gianfar Ethernet"
depends on 85xx || 83xx
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 6202b10dbb4..63c6d1e6d4d 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -51,7 +51,9 @@ obj-$(CONFIG_NS83820) += ns83820.o
obj-$(CONFIG_STNIC) += stnic.o 8390.o
obj-$(CONFIG_FEALNX) += fealnx.o
obj-$(CONFIG_TIGON3) += tg3.o
+obj-$(CONFIG_BNX2) += bnx2.o
obj-$(CONFIG_TC35815) += tc35815.o
+obj-$(CONFIG_SKGE) += skge.o
obj-$(CONFIG_SK98LIN) += sk98lin/
obj-$(CONFIG_SKFP) += skfp/
obj-$(CONFIG_VIA_RHINE) += via-rhine.o
@@ -73,7 +75,6 @@ obj-$(CONFIG_MAC8390) += mac8390.o 8390.o
obj-$(CONFIG_APNE) += apne.o 8390.o
obj-$(CONFIG_PCMCIA_PCNET) += 8390.o
obj-$(CONFIG_SHAPER) += shaper.o
-obj-$(CONFIG_SK_G16) += sk_g16.o
obj-$(CONFIG_HP100) += hp100.o
obj-$(CONFIG_SMC9194) += smc9194.o
obj-$(CONFIG_FEC) += fec.o
@@ -121,7 +122,6 @@ obj-$(CONFIG_DEFXX) += defxx.o
obj-$(CONFIG_SGISEEQ) += sgiseeq.o
obj-$(CONFIG_SGI_O2MACE_ETH) += meth.o
obj-$(CONFIG_AT1700) += at1700.o
-obj-$(CONFIG_FMV18X) += fmv18x.o
obj-$(CONFIG_EL1) += 3c501.o
obj-$(CONFIG_EL16) += 3c507.o
obj-$(CONFIG_ELMC) += 3c523.o
@@ -179,6 +179,7 @@ obj-$(CONFIG_AMD8111_ETH) += amd8111e.o
obj-$(CONFIG_IBMVETH) += ibmveth.o
obj-$(CONFIG_S2IO) += s2io.o
obj-$(CONFIG_SMC91X) += smc91x.o
+obj-$(CONFIG_DM9000) += dm9000.o
obj-$(CONFIG_FEC_8XX) += fec_8xx/
obj-$(CONFIG_ARM) += arm/
@@ -187,7 +188,7 @@ obj-$(CONFIG_TR) += tokenring/
obj-$(CONFIG_WAN) += wan/
obj-$(CONFIG_ARCNET) += arcnet/
obj-$(CONFIG_NET_PCMCIA) += pcmcia/
-obj-$(CONFIG_NET_WIRELESS) += wireless/
+obj-$(CONFIG_NET_RADIO) += wireless/
obj-$(CONFIG_NET_TULIP) += tulip/
obj-$(CONFIG_HAMRADIO) += hamradio/
obj-$(CONFIG_IRDA) += irda/
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index fb433325aa2..3707df6b0cf 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -210,9 +210,6 @@ static struct devprobe2 isa_probes[] __initdata = {
#ifdef CONFIG_AT1700
{at1700_probe, 0},
#endif
-#ifdef CONFIG_FMV18X /* Fujitsu FMV-181/182 */
- {fmv18x_probe, 0},
-#endif
#ifdef CONFIG_ETH16I
{eth16i_probe, 0}, /* ICL EtherTeam 16i/32 */
#endif
@@ -243,9 +240,6 @@ static struct devprobe2 isa_probes[] __initdata = {
#ifdef CONFIG_ELPLUS /* 3c505 */
{elplus_probe, 0},
#endif
-#ifdef CONFIG_SK_G16
- {SK_init, 0},
-#endif
#ifdef CONFIG_NI5010
{ni5010_probe, 0},
#endif
diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
index f2e937abf7b..b7dd7260caf 100755
--- a/drivers/net/amd8111e.c
+++ b/drivers/net/amd8111e.c
@@ -738,6 +738,7 @@ static int amd8111e_rx_poll(struct net_device *dev, int * budget)
short vtag;
#endif
int rx_pkt_limit = dev->quota;
+ unsigned long flags;
do{
/* process receive packets until we use the quota*/
@@ -841,18 +842,19 @@ static int amd8111e_rx_poll(struct net_device *dev, int * budget)
/* Receive descriptor is empty now */
dev->quota -= num_rx_pkt;
*budget -= num_rx_pkt;
+
+ spin_lock_irqsave(&lp->lock, flags);
netif_rx_complete(dev);
- /* enable receive interrupt */
writel(VAL0|RINTEN0, mmio + INTEN0);
writel(VAL2 | RDMD0, mmio + CMD0);
+ spin_unlock_irqrestore(&lp->lock, flags);
return 0;
+
rx_not_empty:
/* Do not call a netif_rx_complete */
dev->quota -= num_rx_pkt;
*budget -= num_rx_pkt;
return 1;
-
-
}
#else
@@ -1261,18 +1263,20 @@ static irqreturn_t amd8111e_interrupt(int irq, void *dev_id, struct pt_regs *reg
struct net_device * dev = (struct net_device *) dev_id;
struct amd8111e_priv *lp = netdev_priv(dev);
void __iomem *mmio = lp->mmio;
- unsigned int intr0;
+ unsigned int intr0, intren0;
unsigned int handled = 1;
- if(dev == NULL)
+ if(unlikely(dev == NULL))
return IRQ_NONE;
- if (regs) spin_lock (&lp->lock);
+ spin_lock(&lp->lock);
+
/* disabling interrupt */
writel(INTREN, mmio + CMD0);
/* Read interrupt status */
intr0 = readl(mmio + INT0);
+ intren0 = readl(mmio + INTEN0);
/* Process all the INT event until INTR bit is clear. */
@@ -1293,11 +1297,11 @@ static irqreturn_t amd8111e_interrupt(int irq, void *dev_id, struct pt_regs *reg
/* Schedule a polling routine */
__netif_rx_schedule(dev);
}
- else {
+ else if (intren0 & RINTEN0) {
printk("************Driver bug! \
interrupt while in poll\n");
- /* Fix by disabling interrupts */
- writel(RINT0, mmio + INT0);
+ /* Fix by disable receive interrupts */
+ writel(RINTEN0, mmio + INTEN0);
}
}
#else
@@ -1321,7 +1325,7 @@ static irqreturn_t amd8111e_interrupt(int irq, void *dev_id, struct pt_regs *reg
err_no_interrupt:
writel( VAL0 | INTREN,mmio + CMD0);
- if (regs) spin_unlock(&lp->lock);
+ spin_unlock(&lp->lock);
return IRQ_RETVAL(handled);
}
diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c
index db4f369637b..d5666c37cb0 100644
--- a/drivers/net/appletalk/ltpc.c
+++ b/drivers/net/appletalk/ltpc.c
@@ -1109,8 +1109,7 @@ struct net_device * __init ltpc_probe(void)
inb_p(io+1);
inb_p(io+3);
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(2*HZ/100);
+ msleep(20);
inb_p(io+0);
inb_p(io+2);
@@ -1120,8 +1119,7 @@ struct net_device * __init ltpc_probe(void)
inb_p(io+5); /* enable dma */
inb_p(io+6); /* tri-state interrupt line */
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(HZ);
+ ssleep(1);
/* now, figure out which dma channel we're using, unless it's
already been specified */
diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c
index 942a2819576..2e28c201dcc 100644
--- a/drivers/net/arm/etherh.c
+++ b/drivers/net/arm/etherh.c
@@ -68,6 +68,7 @@ struct etherh_priv {
void __iomem *dma_base;
unsigned int id;
void __iomem *ctrl_port;
+ void __iomem *base;
unsigned char ctrl;
u32 supported;
};
@@ -177,7 +178,7 @@ etherh_setif(struct net_device *dev)
switch (etherh_priv(dev)->id) {
case PROD_I3_ETHERLAN600:
case PROD_I3_ETHERLAN600A:
- addr = (void *)dev->base_addr + EN0_RCNTHI;
+ addr = etherh_priv(dev)->base + EN0_RCNTHI;
switch (dev->if_port) {
case IF_PORT_10BASE2:
@@ -218,7 +219,7 @@ etherh_getifstat(struct net_device *dev)
switch (etherh_priv(dev)->id) {
case PROD_I3_ETHERLAN600:
case PROD_I3_ETHERLAN600A:
- addr = (void *)dev->base_addr + EN0_RCNTHI;
+ addr = etherh_priv(dev)->base + EN0_RCNTHI;
switch (dev->if_port) {
case IF_PORT_10BASE2:
stat = 1;
@@ -281,7 +282,7 @@ static void
etherh_reset(struct net_device *dev)
{
struct ei_device *ei_local = netdev_priv(dev);
- void __iomem *addr = (void *)dev->base_addr;
+ void __iomem *addr = etherh_priv(dev)->base;
writeb(E8390_NODMA+E8390_PAGE0+E8390_STOP, addr);
@@ -327,7 +328,7 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf
ei_local->dmaing = 1;
- addr = (void *)dev->base_addr;
+ addr = etherh_priv(dev)->base;
dma_base = etherh_priv(dev)->dma_base;
count = (count + 1) & ~1;
@@ -387,7 +388,7 @@ etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int
ei_local->dmaing = 1;
- addr = (void *)dev->base_addr;
+ addr = etherh_priv(dev)->base;
dma_base = etherh_priv(dev)->dma_base;
buf = skb->data;
@@ -427,7 +428,7 @@ etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_p
ei_local->dmaing = 1;
- addr = (void *)dev->base_addr;
+ addr = etherh_priv(dev)->base;
dma_base = etherh_priv(dev)->dma_base;
writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
@@ -696,7 +697,8 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
eh->ctrl_port = eh->ioc_fast;
}
- dev->base_addr = (unsigned long)eh->memc + data->ns8390_offset;
+ eh->base = eh->memc + data->ns8390_offset;
+ dev->base_addr = (unsigned long)eh->base;
eh->dma_base = eh->memc + data->dataport_offset;
eh->ctrl_port += data->ctrlport_offset;
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index 5a2efd343db..c82b9cd1c92 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -1681,10 +1681,6 @@ static int au1000_init(struct net_device *dev)
control |= MAC_FULL_DUPLEX;
}
- /* fix for startup without cable */
- if (!link)
- dev->flags &= ~IFF_RUNNING;
-
aup->mac->control = control;
aup->mac->vlan1_tag = 0x8100; /* activate vlan support */
au_sync();
@@ -1709,16 +1705,14 @@ static void au1000_timer(unsigned long data)
if_port = dev->if_port;
if (aup->phy_ops->phy_status(dev, aup->phy_addr, &link, &speed) == 0) {
if (link) {
- if (!(dev->flags & IFF_RUNNING)) {
+ if (!netif_carrier_ok(dev)) {
netif_carrier_on(dev);
- dev->flags |= IFF_RUNNING;
printk(KERN_INFO "%s: link up\n", dev->name);
}
}
else {
- if (dev->flags & IFF_RUNNING) {
+ if (netif_carrier_ok(dev)) {
netif_carrier_off(dev);
- dev->flags &= ~IFF_RUNNING;
dev->if_port = 0;
printk(KERN_INFO "%s: link down\n", dev->name);
}
diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c
index 734bd4ee3f9..00e5257b176 100644
--- a/drivers/net/bmac.c
+++ b/drivers/net/bmac.c
@@ -1412,7 +1412,6 @@ static int bmac_open(struct net_device *dev)
bp->opened = 1;
bmac_reset_and_enable(dev);
enable_irq(dev->irq);
- dev->flags |= IFF_RUNNING;
return 0;
}
@@ -1425,7 +1424,6 @@ static int bmac_close(struct net_device *dev)
int i;
bp->sleeping = 1;
- dev->flags &= ~(IFF_UP | IFF_RUNNING);
/* disable rx and tx */
config = bmread(dev, RXCFG);
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
new file mode 100644
index 00000000000..8acc655ec1e
--- /dev/null
+++ b/drivers/net/bnx2.c
@@ -0,0 +1,5530 @@
+/* bnx2.c: Broadcom NX2 network driver.
+ *
+ * Copyright (c) 2004, 2005 Broadcom Corporation
+ *
+ * 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.
+ *
+ * Written by: Michael Chan (mchan@broadcom.com)
+ */
+
+#include "bnx2.h"
+#include "bnx2_fw.h"
+
+#define DRV_MODULE_NAME "bnx2"
+#define PFX DRV_MODULE_NAME ": "
+#define DRV_MODULE_VERSION "1.2.19"
+#define DRV_MODULE_RELDATE "May 23, 2005"
+
+#define RUN_AT(x) (jiffies + (x))
+
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT (5*HZ)
+
+static char version[] __devinitdata =
+ "Broadcom NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+
+MODULE_AUTHOR("Michael Chan <mchan@broadcom.com>");
+MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706 Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+static int disable_msi = 0;
+
+module_param(disable_msi, int, 0);
+MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
+
+typedef enum {
+ BCM5706 = 0,
+ NC370T,
+ NC370I,
+ BCM5706S,
+ NC370F,
+} board_t;
+
+/* indexed by board_t, above */
+static struct {
+ char *name;
+} board_info[] __devinitdata = {
+ { "Broadcom NetXtreme II BCM5706 1000Base-T" },
+ { "HP NC370T Multifunction Gigabit Server Adapter" },
+ { "HP NC370i Multifunction Gigabit Server Adapter" },
+ { "Broadcom NetXtreme II BCM5706 1000Base-SX" },
+ { "HP NC370F Multifunction Gigabit Server Adapter" },
+ { 0 },
+ };
+
+static struct pci_device_id bnx2_pci_tbl[] = {
+ { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706,
+ PCI_VENDOR_ID_HP, 0x3101, 0, 0, NC370T },
+ { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706,
+ PCI_VENDOR_ID_HP, 0x3106, 0, 0, NC370I },
+ { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5706 },
+ { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706S,
+ PCI_VENDOR_ID_HP, 0x3102, 0, 0, NC370F },
+ { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706S,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5706S },
+ { 0, }
+};
+
+static struct flash_spec flash_table[] =
+{
+ /* Slow EEPROM */
+ {0x00000000, 0x40030380, 0x009f0081, 0xa184a053, 0xaf000400,
+ 1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE,
+ SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE,
+ "EEPROM - slow"},
+ /* Fast EEPROM */
+ {0x02000000, 0x62008380, 0x009f0081, 0xa184a053, 0xaf000400,
+ 1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE,
+ SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE,
+ "EEPROM - fast"},
+ /* ATMEL AT45DB011B (buffered flash) */
+ {0x02000003, 0x6e008173, 0x00570081, 0x68848353, 0xaf000400,
+ 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
+ BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE,
+ "Buffered flash"},
+ /* Saifun SA25F005 (non-buffered flash) */
+ /* strap, cfg1, & write1 need updates */
+ {0x01000003, 0x5f008081, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE,
+ "Non-buffered flash (64kB)"},
+ /* Saifun SA25F010 (non-buffered flash) */
+ /* strap, cfg1, & write1 need updates */
+ {0x00000001, 0x47008081, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*2,
+ "Non-buffered flash (128kB)"},
+ /* Saifun SA25F020 (non-buffered flash) */
+ /* strap, cfg1, & write1 need updates */
+ {0x00000003, 0x4f008081, 0x00050081, 0x03840253, 0xaf020406,
+ 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
+ SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*4,
+ "Non-buffered flash (256kB)"},
+};
+
+MODULE_DEVICE_TABLE(pci, bnx2_pci_tbl);
+
+static u32
+bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset)
+{
+ REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
+ return (REG_RD(bp, BNX2_PCICFG_REG_WINDOW));
+}
+
+static void
+bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val)
+{
+ REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
+ REG_WR(bp, BNX2_PCICFG_REG_WINDOW, val);
+}
+
+static void
+bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val)
+{
+ offset += cid_addr;
+ REG_WR(bp, BNX2_CTX_DATA_ADR, offset);
+ REG_WR(bp, BNX2_CTX_DATA, val);
+}
+
+static int
+bnx2_read_phy(struct bnx2 *bp, u32 reg, u32 *val)
+{
+ u32 val1;
+ int i, ret;
+
+ if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) {
+ val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+ val1 &= ~BNX2_EMAC_MDIO_MODE_AUTO_POLL;
+
+ REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
+ REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+
+ udelay(40);
+ }
+
+ val1 = (bp->phy_addr << 21) | (reg << 16) |
+ BNX2_EMAC_MDIO_COMM_COMMAND_READ | BNX2_EMAC_MDIO_COMM_DISEXT |
+ BNX2_EMAC_MDIO_COMM_START_BUSY;
+ REG_WR(bp, BNX2_EMAC_MDIO_COMM, val1);
+
+ for (i = 0; i < 50; i++) {
+ udelay(10);
+
+ val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM);
+ if (!(val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)) {
+ udelay(5);
+
+ val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM);
+ val1 &= BNX2_EMAC_MDIO_COMM_DATA;
+
+ break;
+ }
+ }
+
+ if (val1 & BNX2_EMAC_MDIO_COMM_START_BUSY) {
+ *val = 0x0;
+ ret = -EBUSY;
+ }
+ else {
+ *val = val1;
+ ret = 0;
+ }
+
+ if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) {
+ val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+ val1 |= BNX2_EMAC_MDIO_MODE_AUTO_POLL;
+
+ REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
+ REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+
+ udelay(40);
+ }
+
+ return ret;
+}
+
+static int
+bnx2_write_phy(struct bnx2 *bp, u32 reg, u32 val)
+{
+ u32 val1;
+ int i, ret;
+
+ if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) {
+ val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+ val1 &= ~BNX2_EMAC_MDIO_MODE_AUTO_POLL;
+
+ REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
+ REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+
+ udelay(40);
+ }
+
+ val1 = (bp->phy_addr << 21) | (reg << 16) | val |
+ BNX2_EMAC_MDIO_COMM_COMMAND_WRITE |
+ BNX2_EMAC_MDIO_COMM_START_BUSY | BNX2_EMAC_MDIO_COMM_DISEXT;
+ REG_WR(bp, BNX2_EMAC_MDIO_COMM, val1);
+
+ for (i = 0; i < 50; i++) {
+ udelay(10);
+
+ val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM);
+ if (!(val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)) {
+ udelay(5);
+ break;
+ }
+ }
+
+ if (val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)
+ ret = -EBUSY;
+ else
+ ret = 0;
+
+ if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) {
+ val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+ val1 |= BNX2_EMAC_MDIO_MODE_AUTO_POLL;
+
+ REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
+ REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+
+ udelay(40);
+ }
+
+ return ret;
+}
+
+static void
+bnx2_disable_int(struct bnx2 *bp)
+{
+ REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+ BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
+ REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD);
+}
+
+static void
+bnx2_enable_int(struct bnx2 *bp)
+{
+ u32 val;
+
+ REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+ BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | bp->last_status_idx);
+
+ val = REG_RD(bp, BNX2_HC_COMMAND);
+ REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW);
+}
+
+static void
+bnx2_disable_int_sync(struct bnx2 *bp)
+{
+ atomic_inc(&bp->intr_sem);
+ bnx2_disable_int(bp);
+ synchronize_irq(bp->pdev->irq);
+}
+
+static void
+bnx2_netif_stop(struct bnx2 *bp)
+{
+ bnx2_disable_int_sync(bp);
+ if (netif_running(bp->dev)) {
+ netif_poll_disable(bp->dev);
+ netif_tx_disable(bp->dev);
+ bp->dev->trans_start = jiffies; /* prevent tx timeout */
+ }
+}
+
+static void
+bnx2_netif_start(struct bnx2 *bp)
+{
+ if (atomic_dec_and_test(&bp->intr_sem)) {
+ if (netif_running(bp->dev)) {
+ netif_wake_queue(bp->dev);
+ netif_poll_enable(bp->dev);
+ bnx2_enable_int(bp);
+ }
+ }
+}
+
+static void
+bnx2_free_mem(struct bnx2 *bp)
+{
+ if (bp->stats_blk) {
+ pci_free_consistent(bp->pdev, sizeof(struct statistics_block),
+ bp->stats_blk, bp->stats_blk_mapping);
+ bp->stats_blk = NULL;
+ }
+ if (bp->status_blk) {
+ pci_free_consistent(bp->pdev, sizeof(struct status_block),
+ bp->status_blk, bp->status_blk_mapping);
+ bp->status_blk = NULL;
+ }
+ if (bp->tx_desc_ring) {
+ pci_free_consistent(bp->pdev,
+ sizeof(struct tx_bd) * TX_DESC_CNT,
+ bp->tx_desc_ring, bp->tx_desc_mapping);
+ bp->tx_desc_ring = NULL;
+ }
+ if (bp->tx_buf_ring) {
+ kfree(bp->tx_buf_ring);
+ bp->tx_buf_ring = NULL;
+ }
+ if (bp->rx_desc_ring) {
+ pci_free_consistent(bp->pdev,
+ sizeof(struct rx_bd) * RX_DESC_CNT,
+ bp->rx_desc_ring, bp->rx_desc_mapping);
+ bp->rx_desc_ring = NULL;
+ }
+ if (bp->rx_buf_ring) {
+ kfree(bp->rx_buf_ring);
+ bp->rx_buf_ring = NULL;
+ }
+}
+
+static int
+bnx2_alloc_mem(struct bnx2 *bp)
+{
+ bp->tx_buf_ring = kmalloc(sizeof(struct sw_bd) * TX_DESC_CNT,
+ GFP_KERNEL);
+ if (bp->tx_buf_ring == NULL)
+ return -ENOMEM;
+
+ memset(bp->tx_buf_ring, 0, sizeof(struct sw_bd) * TX_DESC_CNT);
+ bp->tx_desc_ring = pci_alloc_consistent(bp->pdev,
+ sizeof(struct tx_bd) *
+ TX_DESC_CNT,
+ &bp->tx_desc_mapping);
+ if (bp->tx_desc_ring == NULL)
+ goto alloc_mem_err;
+
+ bp->rx_buf_ring = kmalloc(sizeof(struct sw_bd) * RX_DESC_CNT,
+ GFP_KERNEL);
+ if (bp->rx_buf_ring == NULL)
+ goto alloc_mem_err;
+
+ memset(bp->rx_buf_ring, 0, sizeof(struct sw_bd) * RX_DESC_CNT);
+ bp->rx_desc_ring = pci_alloc_consistent(bp->pdev,
+ sizeof(struct rx_bd) *
+ RX_DESC_CNT,
+ &bp->rx_desc_mapping);
+ if (bp->rx_desc_ring == NULL)
+ goto alloc_mem_err;
+
+ bp->status_blk = pci_alloc_consistent(bp->pdev,
+ sizeof(struct status_block),
+ &bp->status_blk_mapping);
+ if (bp->status_blk == NULL)
+ goto alloc_mem_err;
+
+ memset(bp->status_blk, 0, sizeof(struct status_block));
+
+ bp->stats_blk = pci_alloc_consistent(bp->pdev,
+ sizeof(struct statistics_block),
+ &bp->stats_blk_mapping);
+ if (bp->stats_blk == NULL)
+ goto alloc_mem_err;
+
+ memset(bp->stats_blk, 0, sizeof(struct statistics_block));
+
+ return 0;
+
+alloc_mem_err:
+ bnx2_free_mem(bp);
+ return -ENOMEM;
+}
+
+static void
+bnx2_report_link(struct bnx2 *bp)
+{
+ if (bp->link_up) {
+ netif_carrier_on(bp->dev);
+ printk(KERN_INFO PFX "%s NIC Link is Up, ", bp->dev->name);
+
+ printk("%d Mbps ", bp->line_speed);
+
+ if (bp->duplex == DUPLEX_FULL)
+ printk("full duplex");
+ else
+ printk("half duplex");
+
+ if (bp->flow_ctrl) {
+ if (bp->flow_ctrl & FLOW_CTRL_RX) {
+ printk(", receive ");
+ if (bp->flow_ctrl & FLOW_CTRL_TX)
+ printk("& transmit ");
+ }
+ else {
+ printk(", transmit ");
+ }
+ printk("flow control ON");
+ }
+ printk("\n");
+ }
+ else {
+ netif_carrier_off(bp->dev);
+ printk(KERN_ERR PFX "%s NIC Link is Down\n", bp->dev->name);
+ }
+}
+
+static void
+bnx2_resolve_flow_ctrl(struct bnx2 *bp)
+{
+ u32 local_adv, remote_adv;
+
+ bp->flow_ctrl = 0;
+ if ((bp->autoneg & (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) !=
+ (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) {
+
+ if (bp->duplex == DUPLEX_FULL) {
+ bp->flow_ctrl = bp->req_flow_ctrl;
+ }
+ return;
+ }
+
+ if (bp->duplex != DUPLEX_FULL) {
+ return;
+ }
+
+ bnx2_read_phy(bp, MII_ADVERTISE, &local_adv);
+ bnx2_read_phy(bp, MII_LPA, &remote_adv);
+
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ u32 new_local_adv = 0;
+ u32 new_remote_adv = 0;
+
+ if (local_adv & ADVERTISE_1000XPAUSE)
+ new_local_adv |= ADVERTISE_PAUSE_CAP;
+ if (local_adv & ADVERTISE_1000XPSE_ASYM)
+ new_local_adv |= ADVERTISE_PAUSE_ASYM;
+ if (remote_adv & ADVERTISE_1000XPAUSE)
+ new_remote_adv |= ADVERTISE_PAUSE_CAP;
+ if (remote_adv & ADVERTISE_1000XPSE_ASYM)
+ new_remote_adv |= ADVERTISE_PAUSE_ASYM;
+
+ local_adv = new_local_adv;
+ remote_adv = new_remote_adv;
+ }
+
+ /* See Table 28B-3 of 802.3ab-1999 spec. */
+ if (local_adv & ADVERTISE_PAUSE_CAP) {
+ if(local_adv & ADVERTISE_PAUSE_ASYM) {
+ if (remote_adv & ADVERTISE_PAUSE_CAP) {
+ bp->flow_ctrl = FLOW_CTRL_TX | FLOW_CTRL_RX;
+ }
+ else if (remote_adv & ADVERTISE_PAUSE_ASYM) {
+ bp->flow_ctrl = FLOW_CTRL_RX;
+ }
+ }
+ else {
+ if (remote_adv & ADVERTISE_PAUSE_CAP) {
+ bp->flow_ctrl = FLOW_CTRL_TX | FLOW_CTRL_RX;
+ }
+ }
+ }
+ else if (local_adv & ADVERTISE_PAUSE_ASYM) {
+ if ((remote_adv & ADVERTISE_PAUSE_CAP) &&
+ (remote_adv & ADVERTISE_PAUSE_ASYM)) {
+
+ bp->flow_ctrl = FLOW_CTRL_TX;
+ }
+ }
+}
+
+static int
+bnx2_serdes_linkup(struct bnx2 *bp)
+{
+ u32 bmcr, local_adv, remote_adv, common;
+
+ bp->link_up = 1;
+ bp->line_speed = SPEED_1000;
+
+ bnx2_read_phy(bp, MII_BMCR, &bmcr);
+ if (bmcr & BMCR_FULLDPLX) {
+ bp->duplex = DUPLEX_FULL;
+ }
+ else {
+ bp->duplex = DUPLEX_HALF;
+ }
+
+ if (!(bmcr & BMCR_ANENABLE)) {
+ return 0;
+ }
+
+ bnx2_read_phy(bp, MII_ADVERTISE, &local_adv);
+ bnx2_read_phy(bp, MII_LPA, &remote_adv);
+
+ common = local_adv & remote_adv;
+ if (common & (ADVERTISE_1000XHALF | ADVERTISE_1000XFULL)) {
+
+ if (common & ADVERTISE_1000XFULL) {
+ bp->duplex = DUPLEX_FULL;
+ }
+ else {
+ bp->duplex = DUPLEX_HALF;
+ }
+ }
+
+ return 0;
+}
+
+static int
+bnx2_copper_linkup(struct bnx2 *bp)
+{
+ u32 bmcr;
+
+ bnx2_read_phy(bp, MII_BMCR, &bmcr);
+ if (bmcr & BMCR_ANENABLE) {
+ u32 local_adv, remote_adv, common;
+
+ bnx2_read_phy(bp, MII_CTRL1000, &local_adv);
+ bnx2_read_phy(bp, MII_STAT1000, &remote_adv);
+
+ common = local_adv & (remote_adv >> 2);
+ if (common & ADVERTISE_1000FULL) {
+ bp->line_speed = SPEED_1000;
+ bp->duplex = DUPLEX_FULL;
+ }
+ else if (common & ADVERTISE_1000HALF) {
+ bp->line_speed = SPEED_1000;
+ bp->duplex = DUPLEX_HALF;
+ }
+ else {
+ bnx2_read_phy(bp, MII_ADVERTISE, &local_adv);
+ bnx2_read_phy(bp, MII_LPA, &remote_adv);
+
+ common = local_adv & remote_adv;
+ if (common & ADVERTISE_100FULL) {
+ bp->line_speed = SPEED_100;
+ bp->duplex = DUPLEX_FULL;
+ }
+ else if (common & ADVERTISE_100HALF) {
+ bp->line_speed = SPEED_100;
+ bp->duplex = DUPLEX_HALF;
+ }
+ else if (common & ADVERTISE_10FULL) {
+ bp->line_speed = SPEED_10;
+ bp->duplex = DUPLEX_FULL;
+ }
+ else if (common & ADVERTISE_10HALF) {
+ bp->line_speed = SPEED_10;
+ bp->duplex = DUPLEX_HALF;
+ }
+ else {
+ bp->line_speed = 0;
+ bp->link_up = 0;
+ }
+ }
+ }
+ else {
+ if (bmcr & BMCR_SPEED100) {
+ bp->line_speed = SPEED_100;
+ }
+ else {
+ bp->line_speed = SPEED_10;
+ }
+ if (bmcr & BMCR_FULLDPLX) {
+ bp->duplex = DUPLEX_FULL;
+ }
+ else {
+ bp->duplex = DUPLEX_HALF;
+ }
+ }
+
+ return 0;
+}
+
+static int
+bnx2_set_mac_link(struct bnx2 *bp)
+{
+ u32 val;
+
+ REG_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x2620);
+ if (bp->link_up && (bp->line_speed == SPEED_1000) &&
+ (bp->duplex == DUPLEX_HALF)) {
+ REG_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x26ff);
+ }
+
+ /* Configure the EMAC mode register. */
+ val = REG_RD(bp, BNX2_EMAC_MODE);
+
+ val &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX |
+ BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK);
+
+ if (bp->link_up) {
+ if (bp->line_speed != SPEED_1000)
+ val |= BNX2_EMAC_MODE_PORT_MII;
+ else
+ val |= BNX2_EMAC_MODE_PORT_GMII;
+ }
+ else {
+ val |= BNX2_EMAC_MODE_PORT_GMII;
+ }
+
+ /* Set the MAC to operate in the appropriate duplex mode. */
+ if (bp->duplex == DUPLEX_HALF)
+ val |= BNX2_EMAC_MODE_HALF_DUPLEX;
+ REG_WR(bp, BNX2_EMAC_MODE, val);
+
+ /* Enable/disable rx PAUSE. */
+ bp->rx_mode &= ~BNX2_EMAC_RX_MODE_FLOW_EN;
+
+ if (bp->flow_ctrl & FLOW_CTRL_RX)
+ bp->rx_mode |= BNX2_EMAC_RX_MODE_FLOW_EN;
+ REG_WR(bp, BNX2_EMAC_RX_MODE, bp->rx_mode);
+
+ /* Enable/disable tx PAUSE. */
+ val = REG_RD(bp, BNX2_EMAC_TX_MODE);
+ val &= ~BNX2_EMAC_TX_MODE_FLOW_EN;
+
+ if (bp->flow_ctrl & FLOW_CTRL_TX)
+ val |= BNX2_EMAC_TX_MODE_FLOW_EN;
+ REG_WR(bp, BNX2_EMAC_TX_MODE, val);
+
+ /* Acknowledge the interrupt. */
+ REG_WR(bp, BNX2_EMAC_STATUS, BNX2_EMAC_STATUS_LINK_CHANGE);
+
+ return 0;
+}
+
+static int
+bnx2_set_link(struct bnx2 *bp)
+{
+ u32 bmsr;
+ u8 link_up;
+
+ if (bp->loopback == MAC_LOOPBACK) {
+ bp->link_up = 1;
+ return 0;
+ }
+
+ link_up = bp->link_up;
+
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+
+ if ((bp->phy_flags & PHY_SERDES_FLAG) &&
+ (CHIP_NUM(bp) == CHIP_NUM_5706)) {
+ u32 val;
+
+ val = REG_RD(bp, BNX2_EMAC_STATUS);
+ if (val & BNX2_EMAC_STATUS_LINK)
+ bmsr |= BMSR_LSTATUS;
+ else
+ bmsr &= ~BMSR_LSTATUS;
+ }
+
+ if (bmsr & BMSR_LSTATUS) {
+ bp->link_up = 1;
+
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ bnx2_serdes_linkup(bp);
+ }
+ else {
+ bnx2_copper_linkup(bp);
+ }
+ bnx2_resolve_flow_ctrl(bp);
+ }
+ else {
+ if ((bp->phy_flags & PHY_SERDES_FLAG) &&
+ (bp->autoneg & AUTONEG_SPEED)) {
+
+ u32 bmcr;
+
+ bnx2_read_phy(bp, MII_BMCR, &bmcr);
+ if (!(bmcr & BMCR_ANENABLE)) {
+ bnx2_write_phy(bp, MII_BMCR, bmcr |
+ BMCR_ANENABLE);
+ }
+ }
+ bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG;
+ bp->link_up = 0;
+ }
+
+ if (bp->link_up != link_up) {
+ bnx2_report_link(bp);
+ }
+
+ bnx2_set_mac_link(bp);
+
+ return 0;
+}
+
+static int
+bnx2_reset_phy(struct bnx2 *bp)
+{
+ int i;
+ u32 reg;
+
+ bnx2_write_phy(bp, MII_BMCR, BMCR_RESET);
+
+#define PHY_RESET_MAX_WAIT 100
+ for (i = 0; i < PHY_RESET_MAX_WAIT; i++) {
+ udelay(10);
+
+ bnx2_read_phy(bp, MII_BMCR, &reg);
+ if (!(reg & BMCR_RESET)) {
+ udelay(20);
+ break;
+ }
+ }
+ if (i == PHY_RESET_MAX_WAIT) {
+ return -EBUSY;
+ }
+ return 0;
+}
+
+static u32
+bnx2_phy_get_pause_adv(struct bnx2 *bp)
+{
+ u32 adv = 0;
+
+ if ((bp->req_flow_ctrl & (FLOW_CTRL_RX | FLOW_CTRL_TX)) ==
+ (FLOW_CTRL_RX | FLOW_CTRL_TX)) {
+
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ adv = ADVERTISE_1000XPAUSE;
+ }
+ else {
+ adv = ADVERTISE_PAUSE_CAP;
+ }
+ }
+ else if (bp->req_flow_ctrl & FLOW_CTRL_TX) {
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ adv = ADVERTISE_1000XPSE_ASYM;
+ }
+ else {
+ adv = ADVERTISE_PAUSE_ASYM;
+ }
+ }
+ else if (bp->req_flow_ctrl & FLOW_CTRL_RX) {
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ adv = ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM;
+ }
+ else {
+ adv = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+ }
+ }
+ return adv;
+}
+
+static int
+bnx2_setup_serdes_phy(struct bnx2 *bp)
+{
+ u32 adv, bmcr;
+ u32 new_adv = 0;
+
+ if (!(bp->autoneg & AUTONEG_SPEED)) {
+ u32 new_bmcr;
+
+ bnx2_read_phy(bp, MII_BMCR, &bmcr);
+ new_bmcr = bmcr & ~BMCR_ANENABLE;
+ new_bmcr |= BMCR_SPEED1000;
+ if (bp->req_duplex == DUPLEX_FULL) {
+ new_bmcr |= BMCR_FULLDPLX;
+ }
+ else {
+ new_bmcr &= ~BMCR_FULLDPLX;
+ }
+ if (new_bmcr != bmcr) {
+ /* Force a link down visible on the other side */
+ if (bp->link_up) {
+ bnx2_read_phy(bp, MII_ADVERTISE, &adv);
+ adv &= ~(ADVERTISE_1000XFULL |
+ ADVERTISE_1000XHALF);
+ bnx2_write_phy(bp, MII_ADVERTISE, adv);
+ bnx2_write_phy(bp, MII_BMCR, bmcr |
+ BMCR_ANRESTART | BMCR_ANENABLE);
+
+ bp->link_up = 0;
+ netif_carrier_off(bp->dev);
+ }
+ bnx2_write_phy(bp, MII_BMCR, new_bmcr);
+ }
+ return 0;
+ }
+
+ if (bp->advertising & ADVERTISED_1000baseT_Full)
+ new_adv |= ADVERTISE_1000XFULL;
+
+ new_adv |= bnx2_phy_get_pause_adv(bp);
+
+ bnx2_read_phy(bp, MII_ADVERTISE, &adv);
+ bnx2_read_phy(bp, MII_BMCR, &bmcr);
+
+ bp->serdes_an_pending = 0;
+ if ((adv != new_adv) || ((bmcr & BMCR_ANENABLE) == 0)) {
+ /* Force a link down visible on the other side */
+ if (bp->link_up) {
+ int i;
+
+ bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK);
+ for (i = 0; i < 110; i++) {
+ udelay(100);
+ }
+ }
+
+ bnx2_write_phy(bp, MII_ADVERTISE, new_adv);
+ bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART |
+ BMCR_ANENABLE);
+ bp->serdes_an_pending = SERDES_AN_TIMEOUT / bp->timer_interval;
+ }
+
+ return 0;
+}
+
+#define ETHTOOL_ALL_FIBRE_SPEED \
+ (ADVERTISED_1000baseT_Full)
+
+#define ETHTOOL_ALL_COPPER_SPEED \
+ (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \
+ ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
+ ADVERTISED_1000baseT_Full)
+
+#define PHY_ALL_10_100_SPEED (ADVERTISE_10HALF | ADVERTISE_10FULL | \
+ ADVERTISE_100HALF | ADVERTISE_100FULL | ADVERTISE_CSMA)
+
+#define PHY_ALL_1000_SPEED (ADVERTISE_1000HALF | ADVERTISE_1000FULL)
+
+static int
+bnx2_setup_copper_phy(struct bnx2 *bp)
+{
+ u32 bmcr;
+ u32 new_bmcr;
+
+ bnx2_read_phy(bp, MII_BMCR, &bmcr);
+
+ if (bp->autoneg & AUTONEG_SPEED) {
+ u32 adv_reg, adv1000_reg;
+ u32 new_adv_reg = 0;
+ u32 new_adv1000_reg = 0;
+
+ bnx2_read_phy(bp, MII_ADVERTISE, &adv_reg);
+ adv_reg &= (PHY_ALL_10_100_SPEED | ADVERTISE_PAUSE_CAP |
+ ADVERTISE_PAUSE_ASYM);
+
+ bnx2_read_phy(bp, MII_CTRL1000, &adv1000_reg);
+ adv1000_reg &= PHY_ALL_1000_SPEED;
+
+ if (bp->advertising & ADVERTISED_10baseT_Half)
+ new_adv_reg |= ADVERTISE_10HALF;
+ if (bp->advertising & ADVERTISED_10baseT_Full)
+ new_adv_reg |= ADVERTISE_10FULL;
+ if (bp->advertising & ADVERTISED_100baseT_Half)
+ new_adv_reg |= ADVERTISE_100HALF;
+ if (bp->advertising & ADVERTISED_100baseT_Full)
+ new_adv_reg |= ADVERTISE_100FULL;
+ if (bp->advertising & ADVERTISED_1000baseT_Full)
+ new_adv1000_reg |= ADVERTISE_1000FULL;
+
+ new_adv_reg |= ADVERTISE_CSMA;
+
+ new_adv_reg |= bnx2_phy_get_pause_adv(bp);
+
+ if ((adv1000_reg != new_adv1000_reg) ||
+ (adv_reg != new_adv_reg) ||
+ ((bmcr & BMCR_ANENABLE) == 0)) {
+
+ bnx2_write_phy(bp, MII_ADVERTISE, new_adv_reg);
+ bnx2_write_phy(bp, MII_CTRL1000, new_adv1000_reg);
+ bnx2_write_phy(bp, MII_BMCR, BMCR_ANRESTART |
+ BMCR_ANENABLE);
+ }
+ else if (bp->link_up) {
+ /* Flow ctrl may have changed from auto to forced */
+ /* or vice-versa. */
+
+ bnx2_resolve_flow_ctrl(bp);
+ bnx2_set_mac_link(bp);
+ }
+ return 0;
+ }
+
+ new_bmcr = 0;
+ if (bp->req_line_speed == SPEED_100) {
+ new_bmcr |= BMCR_SPEED100;
+ }
+ if (bp->req_duplex == DUPLEX_FULL) {
+ new_bmcr |= BMCR_FULLDPLX;
+ }
+ if (new_bmcr != bmcr) {
+ u32 bmsr;
+ int i = 0;
+
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+
+ if (bmsr & BMSR_LSTATUS) {
+ /* Force link down */
+ bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK);
+ do {
+ udelay(100);
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+ i++;
+ } while ((bmsr & BMSR_LSTATUS) && (i < 620));
+ }
+
+ bnx2_write_phy(bp, MII_BMCR, new_bmcr);
+
+ /* Normally, the new speed is setup after the link has
+ * gone down and up again. In some cases, link will not go
+ * down so we need to set up the new speed here.
+ */
+ if (bmsr & BMSR_LSTATUS) {
+ bp->line_speed = bp->req_line_speed;
+ bp->duplex = bp->req_duplex;
+ bnx2_resolve_flow_ctrl(bp);
+ bnx2_set_mac_link(bp);
+ }
+ }
+ return 0;
+}
+
+static int
+bnx2_setup_phy(struct bnx2 *bp)
+{
+ if (bp->loopback == MAC_LOOPBACK)
+ return 0;
+
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ return (bnx2_setup_serdes_phy(bp));
+ }
+ else {
+ return (bnx2_setup_copper_phy(bp));
+ }
+}
+
+static int
+bnx2_init_serdes_phy(struct bnx2 *bp)
+{
+ bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG;
+
+ if (CHIP_NUM(bp) == CHIP_NUM_5706) {
+ REG_WR(bp, BNX2_MISC_UNUSED0, 0x300);
+ }
+
+ if (bp->dev->mtu > 1500) {
+ u32 val;
+
+ /* Set extended packet length bit */
+ bnx2_write_phy(bp, 0x18, 0x7);
+ bnx2_read_phy(bp, 0x18, &val);
+ bnx2_write_phy(bp, 0x18, (val & 0xfff8) | 0x4000);
+
+ bnx2_write_phy(bp, 0x1c, 0x6c00);
+ bnx2_read_phy(bp, 0x1c, &val);
+ bnx2_write_phy(bp, 0x1c, (val & 0x3ff) | 0xec02);
+ }
+ else {
+ u32 val;
+
+ bnx2_write_phy(bp, 0x18, 0x7);
+ bnx2_read_phy(bp, 0x18, &val);
+ bnx2_write_phy(bp, 0x18, val & ~0x4007);
+
+ bnx2_write_phy(bp, 0x1c, 0x6c00);
+ bnx2_read_phy(bp, 0x1c, &val);
+ bnx2_write_phy(bp, 0x1c, (val & 0x3fd) | 0xec00);
+ }
+
+ return 0;
+}
+
+static int
+bnx2_init_copper_phy(struct bnx2 *bp)
+{
+ bp->phy_flags |= PHY_CRC_FIX_FLAG;
+
+ if (bp->phy_flags & PHY_CRC_FIX_FLAG) {
+ bnx2_write_phy(bp, 0x18, 0x0c00);
+ bnx2_write_phy(bp, 0x17, 0x000a);
+ bnx2_write_phy(bp, 0x15, 0x310b);
+ bnx2_write_phy(bp, 0x17, 0x201f);
+ bnx2_write_phy(bp, 0x15, 0x9506);
+ bnx2_write_phy(bp, 0x17, 0x401f);
+ bnx2_write_phy(bp, 0x15, 0x14e2);
+ bnx2_write_phy(bp, 0x18, 0x0400);
+ }
+
+ if (bp->dev->mtu > 1500) {
+ u32 val;
+
+ /* Set extended packet length bit */
+ bnx2_write_phy(bp, 0x18, 0x7);
+ bnx2_read_phy(bp, 0x18, &val);
+ bnx2_write_phy(bp, 0x18, val | 0x4000);
+
+ bnx2_read_phy(bp, 0x10, &val);
+ bnx2_write_phy(bp, 0x10, val | 0x1);
+ }
+ else {
+ u32 val;
+
+ bnx2_write_phy(bp, 0x18, 0x7);
+ bnx2_read_phy(bp, 0x18, &val);
+ bnx2_write_phy(bp, 0x18, val & ~0x4007);
+
+ bnx2_read_phy(bp, 0x10, &val);
+ bnx2_write_phy(bp, 0x10, val & ~0x1);
+ }
+
+ return 0;
+}
+
+
+static int
+bnx2_init_phy(struct bnx2 *bp)
+{
+ u32 val;
+ int rc = 0;
+
+ bp->phy_flags &= ~PHY_INT_MODE_MASK_FLAG;
+ bp->phy_flags |= PHY_INT_MODE_LINK_READY_FLAG;
+
+ REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
+
+ bnx2_reset_phy(bp);
+
+ bnx2_read_phy(bp, MII_PHYSID1, &val);
+ bp->phy_id = val << 16;
+ bnx2_read_phy(bp, MII_PHYSID2, &val);
+ bp->phy_id |= val & 0xffff;
+
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ rc = bnx2_init_serdes_phy(bp);
+ }
+ else {
+ rc = bnx2_init_copper_phy(bp);
+ }
+
+ bnx2_setup_phy(bp);
+
+ return rc;
+}
+
+static int
+bnx2_set_mac_loopback(struct bnx2 *bp)
+{
+ u32 mac_mode;
+
+ mac_mode = REG_RD(bp, BNX2_EMAC_MODE);
+ mac_mode &= ~BNX2_EMAC_MODE_PORT;
+ mac_mode |= BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK;
+ REG_WR(bp, BNX2_EMAC_MODE, mac_mode);
+ bp->link_up = 1;
+ return 0;
+}
+
+static int
+bnx2_fw_sync(struct bnx2 *bp, u32 msg_data)
+{
+ int i;
+ u32 val;
+
+ if (bp->fw_timed_out)
+ return -EBUSY;
+
+ bp->fw_wr_seq++;
+ msg_data |= bp->fw_wr_seq;
+
+ REG_WR_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_DRV_MB, msg_data);
+
+ /* wait for an acknowledgement. */
+ for (i = 0; i < (FW_ACK_TIME_OUT_MS * 1000)/5; i++) {
+ udelay(5);
+
+ val = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_FW_MB);
+
+ if ((val & BNX2_FW_MSG_ACK) == (msg_data & BNX2_DRV_MSG_SEQ))
+ break;
+ }
+
+ /* If we timed out, inform the firmware that this is the case. */
+ if (((val & BNX2_FW_MSG_ACK) != (msg_data & BNX2_DRV_MSG_SEQ)) &&
+ ((msg_data & BNX2_DRV_MSG_DATA) != BNX2_DRV_MSG_DATA_WAIT0)) {
+
+ msg_data &= ~BNX2_DRV_MSG_CODE;
+ msg_data |= BNX2_DRV_MSG_CODE_FW_TIMEOUT;
+
+ REG_WR_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_DRV_MB, msg_data);
+
+ bp->fw_timed_out = 1;
+
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static void
+bnx2_init_context(struct bnx2 *bp)
+{
+ u32 vcid;
+
+ vcid = 96;
+ while (vcid) {
+ u32 vcid_addr, pcid_addr, offset;
+
+ vcid--;
+
+ if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
+ u32 new_vcid;
+
+ vcid_addr = GET_PCID_ADDR(vcid);
+ if (vcid & 0x8) {
+ new_vcid = 0x60 + (vcid & 0xf0) + (vcid & 0x7);
+ }
+ else {
+ new_vcid = vcid;
+ }
+ pcid_addr = GET_PCID_ADDR(new_vcid);
+ }
+ else {
+ vcid_addr = GET_CID_ADDR(vcid);
+ pcid_addr = vcid_addr;
+ }
+
+ REG_WR(bp, BNX2_CTX_VIRT_ADDR, 0x00);
+ REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
+
+ /* Zero out the context. */
+ for (offset = 0; offset < PHY_CTX_SIZE; offset += 4) {
+ CTX_WR(bp, 0x00, offset, 0);
+ }
+
+ REG_WR(bp, BNX2_CTX_VIRT_ADDR, vcid_addr);
+ REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
+ }
+}
+
+static int
+bnx2_alloc_bad_rbuf(struct bnx2 *bp)
+{
+ u16 *good_mbuf;
+ u32 good_mbuf_cnt;
+ u32 val;
+
+ good_mbuf = kmalloc(512 * sizeof(u16), GFP_KERNEL);
+ if (good_mbuf == NULL) {
+ printk(KERN_ERR PFX "Failed to allocate memory in "
+ "bnx2_alloc_bad_rbuf\n");
+ return -ENOMEM;
+ }
+
+ REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
+ BNX2_MISC_ENABLE_SET_BITS_RX_MBUF_ENABLE);
+
+ good_mbuf_cnt = 0;
+
+ /* Allocate a bunch of mbufs and save the good ones in an array. */
+ val = REG_RD_IND(bp, BNX2_RBUF_STATUS1);
+ while (val & BNX2_RBUF_STATUS1_FREE_COUNT) {
+ REG_WR_IND(bp, BNX2_RBUF_COMMAND, BNX2_RBUF_COMMAND_ALLOC_REQ);
+
+ val = REG_RD_IND(bp, BNX2_RBUF_FW_BUF_ALLOC);
+
+ val &= BNX2_RBUF_FW_BUF_ALLOC_VALUE;
+
+ /* The addresses with Bit 9 set are bad memory blocks. */
+ if (!(val & (1 << 9))) {
+ good_mbuf[good_mbuf_cnt] = (u16) val;
+ good_mbuf_cnt++;
+ }
+
+ val = REG_RD_IND(bp, BNX2_RBUF_STATUS1);
+ }
+
+ /* Free the good ones back to the mbuf pool thus discarding
+ * all the bad ones. */
+ while (good_mbuf_cnt) {
+ good_mbuf_cnt--;
+
+ val = good_mbuf[good_mbuf_cnt];
+ val = (val << 9) | val | 1;
+
+ REG_WR_IND(bp, BNX2_RBUF_FW_BUF_FREE, val);
+ }
+ kfree(good_mbuf);
+ return 0;
+}
+
+static void
+bnx2_set_mac_addr(struct bnx2 *bp)
+{
+ u32 val;
+ u8 *mac_addr = bp->dev->dev_addr;
+
+ val = (mac_addr[0] << 8) | mac_addr[1];
+
+ REG_WR(bp, BNX2_EMAC_MAC_MATCH0, val);
+
+ val = (mac_addr[2] << 24) | (mac_addr[3] << 16) |
+ (mac_addr[4] << 8) | mac_addr[5];
+
+ REG_WR(bp, BNX2_EMAC_MAC_MATCH1, val);
+}
+
+static inline int
+bnx2_alloc_rx_skb(struct bnx2 *bp, u16 index)
+{
+ struct sk_buff *skb;
+ struct sw_bd *rx_buf = &bp->rx_buf_ring[index];
+ dma_addr_t mapping;
+ struct rx_bd *rxbd = &bp->rx_desc_ring[index];
+ unsigned long align;
+
+ skb = dev_alloc_skb(bp->rx_buf_size);
+ if (skb == NULL) {
+ return -ENOMEM;
+ }
+
+ if (unlikely((align = (unsigned long) skb->data & 0x7))) {
+ skb_reserve(skb, 8 - align);
+ }
+
+ skb->dev = bp->dev;
+ mapping = pci_map_single(bp->pdev, skb->data, bp->rx_buf_use_size,
+ PCI_DMA_FROMDEVICE);
+
+ rx_buf->skb = skb;
+ pci_unmap_addr_set(rx_buf, mapping, mapping);
+
+ rxbd->rx_bd_haddr_hi = (u64) mapping >> 32;
+ rxbd->rx_bd_haddr_lo = (u64) mapping & 0xffffffff;
+
+ bp->rx_prod_bseq += bp->rx_buf_use_size;
+
+ return 0;
+}
+
+static void
+bnx2_phy_int(struct bnx2 *bp)
+{
+ u32 new_link_state, old_link_state;
+
+ new_link_state = bp->status_blk->status_attn_bits &
+ STATUS_ATTN_BITS_LINK_STATE;
+ old_link_state = bp->status_blk->status_attn_bits_ack &
+ STATUS_ATTN_BITS_LINK_STATE;
+ if (new_link_state != old_link_state) {
+ if (new_link_state) {
+ REG_WR(bp, BNX2_PCICFG_STATUS_BIT_SET_CMD,
+ STATUS_ATTN_BITS_LINK_STATE);
+ }
+ else {
+ REG_WR(bp, BNX2_PCICFG_STATUS_BIT_CLEAR_CMD,
+ STATUS_ATTN_BITS_LINK_STATE);
+ }
+ bnx2_set_link(bp);
+ }
+}
+
+static void
+bnx2_tx_int(struct bnx2 *bp)
+{
+ u16 hw_cons, sw_cons, sw_ring_cons;
+ int tx_free_bd = 0;
+
+ hw_cons = bp->status_blk->status_tx_quick_consumer_index0;
+ if ((hw_cons & MAX_TX_DESC_CNT) == MAX_TX_DESC_CNT) {
+ hw_cons++;
+ }
+ sw_cons = bp->tx_cons;
+
+ while (sw_cons != hw_cons) {
+ struct sw_bd *tx_buf;
+ struct sk_buff *skb;
+ int i, last;
+
+ sw_ring_cons = TX_RING_IDX(sw_cons);
+
+ tx_buf = &bp->tx_buf_ring[sw_ring_cons];
+ skb = tx_buf->skb;
+#ifdef BCM_TSO
+ /* partial BD completions possible with TSO packets */
+ if (skb_shinfo(skb)->tso_size) {
+ u16 last_idx, last_ring_idx;
+
+ last_idx = sw_cons +
+ skb_shinfo(skb)->nr_frags + 1;
+ last_ring_idx = sw_ring_cons +
+ skb_shinfo(skb)->nr_frags + 1;
+ if (unlikely(last_ring_idx >= MAX_TX_DESC_CNT)) {
+ last_idx++;
+ }
+ if (((s16) ((s16) last_idx - (s16) hw_cons)) > 0) {
+ break;
+ }
+ }
+#endif
+ pci_unmap_single(bp->pdev, pci_unmap_addr(tx_buf, mapping),
+ skb_headlen(skb), PCI_DMA_TODEVICE);
+
+ tx_buf->skb = NULL;
+ last = skb_shinfo(skb)->nr_frags;
+
+ for (i = 0; i < last; i++) {
+ sw_cons = NEXT_TX_BD(sw_cons);
+
+ pci_unmap_page(bp->pdev,
+ pci_unmap_addr(
+ &bp->tx_buf_ring[TX_RING_IDX(sw_cons)],
+ mapping),
+ skb_shinfo(skb)->frags[i].size,
+ PCI_DMA_TODEVICE);
+ }
+
+ sw_cons = NEXT_TX_BD(sw_cons);
+
+ tx_free_bd += last + 1;
+
+ dev_kfree_skb_irq(skb);
+
+ hw_cons = bp->status_blk->status_tx_quick_consumer_index0;
+ if ((hw_cons & MAX_TX_DESC_CNT) == MAX_TX_DESC_CNT) {
+ hw_cons++;
+ }
+ }
+
+ atomic_add(tx_free_bd, &bp->tx_avail_bd);
+
+ if (unlikely(netif_queue_stopped(bp->dev))) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&bp->tx_lock, flags);
+ if ((netif_queue_stopped(bp->dev)) &&
+ (atomic_read(&bp->tx_avail_bd) > MAX_SKB_FRAGS)) {
+
+ netif_wake_queue(bp->dev);
+ }
+ spin_unlock_irqrestore(&bp->tx_lock, flags);
+ }
+
+ bp->tx_cons = sw_cons;
+
+}
+
+static inline void
+bnx2_reuse_rx_skb(struct bnx2 *bp, struct sk_buff *skb,
+ u16 cons, u16 prod)
+{
+ struct sw_bd *cons_rx_buf = &bp->rx_buf_ring[cons];
+ struct sw_bd *prod_rx_buf = &bp->rx_buf_ring[prod];
+ struct rx_bd *cons_bd = &bp->rx_desc_ring[cons];
+ struct rx_bd *prod_bd = &bp->rx_desc_ring[prod];
+
+ pci_dma_sync_single_for_device(bp->pdev,
+ pci_unmap_addr(cons_rx_buf, mapping),
+ bp->rx_offset + RX_COPY_THRESH, PCI_DMA_FROMDEVICE);
+
+ prod_rx_buf->skb = cons_rx_buf->skb;
+ pci_unmap_addr_set(prod_rx_buf, mapping,
+ pci_unmap_addr(cons_rx_buf, mapping));
+
+ memcpy(prod_bd, cons_bd, 8);
+
+ bp->rx_prod_bseq += bp->rx_buf_use_size;
+
+}
+
+static int
+bnx2_rx_int(struct bnx2 *bp, int budget)
+{
+ u16 hw_cons, sw_cons, sw_ring_cons, sw_prod, sw_ring_prod;
+ struct l2_fhdr *rx_hdr;
+ int rx_pkt = 0;
+
+ hw_cons = bp->status_blk->status_rx_quick_consumer_index0;
+ if ((hw_cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT) {
+ hw_cons++;
+ }
+ sw_cons = bp->rx_cons;
+ sw_prod = bp->rx_prod;
+
+ /* Memory barrier necessary as speculative reads of the rx
+ * buffer can be ahead of the index in the status block
+ */
+ rmb();
+ while (sw_cons != hw_cons) {
+ unsigned int len;
+ u16 status;
+ struct sw_bd *rx_buf;
+ struct sk_buff *skb;
+
+ sw_ring_cons = RX_RING_IDX(sw_cons);
+ sw_ring_prod = RX_RING_IDX(sw_prod);
+
+ rx_buf = &bp->rx_buf_ring[sw_ring_cons];
+ skb = rx_buf->skb;
+ pci_dma_sync_single_for_cpu(bp->pdev,
+ pci_unmap_addr(rx_buf, mapping),
+ bp->rx_offset + RX_COPY_THRESH, PCI_DMA_FROMDEVICE);
+
+ rx_hdr = (struct l2_fhdr *) skb->data;
+ len = rx_hdr->l2_fhdr_pkt_len - 4;
+
+ if (rx_hdr->l2_fhdr_errors &
+ (L2_FHDR_ERRORS_BAD_CRC |
+ L2_FHDR_ERRORS_PHY_DECODE |
+ L2_FHDR_ERRORS_ALIGNMENT |
+ L2_FHDR_ERRORS_TOO_SHORT |
+ L2_FHDR_ERRORS_GIANT_FRAME)) {
+
+ goto reuse_rx;
+ }
+
+ /* Since we don't have a jumbo ring, copy small packets
+ * if mtu > 1500
+ */
+ if ((bp->dev->mtu > 1500) && (len <= RX_COPY_THRESH)) {
+ struct sk_buff *new_skb;
+
+ new_skb = dev_alloc_skb(len + 2);
+ if (new_skb == NULL)
+ goto reuse_rx;
+
+ /* aligned copy */
+ memcpy(new_skb->data,
+ skb->data + bp->rx_offset - 2,
+ len + 2);
+
+ skb_reserve(new_skb, 2);
+ skb_put(new_skb, len);
+ new_skb->dev = bp->dev;
+
+ bnx2_reuse_rx_skb(bp, skb,
+ sw_ring_cons, sw_ring_prod);
+
+ skb = new_skb;
+ }
+ else if (bnx2_alloc_rx_skb(bp, sw_ring_prod) == 0) {
+ pci_unmap_single(bp->pdev,
+ pci_unmap_addr(rx_buf, mapping),
+ bp->rx_buf_use_size, PCI_DMA_FROMDEVICE);
+
+ skb_reserve(skb, bp->rx_offset);
+ skb_put(skb, len);
+ }
+ else {
+reuse_rx:
+ bnx2_reuse_rx_skb(bp, skb,
+ sw_ring_cons, sw_ring_prod);
+ goto next_rx;
+ }
+
+ skb->protocol = eth_type_trans(skb, bp->dev);
+
+ if ((len > (bp->dev->mtu + ETH_HLEN)) &&
+ (htons(skb->protocol) != 0x8100)) {
+
+ dev_kfree_skb_irq(skb);
+ goto next_rx;
+
+ }
+
+ status = rx_hdr->l2_fhdr_status;
+ skb->ip_summed = CHECKSUM_NONE;
+ if (bp->rx_csum &&
+ (status & (L2_FHDR_STATUS_TCP_SEGMENT |
+ L2_FHDR_STATUS_UDP_DATAGRAM))) {
+
+ u16 cksum = rx_hdr->l2_fhdr_tcp_udp_xsum;
+
+ if (cksum == 0xffff)
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ }
+
+#ifdef BCM_VLAN
+ if ((status & L2_FHDR_STATUS_L2_VLAN_TAG) && (bp->vlgrp != 0)) {
+ vlan_hwaccel_receive_skb(skb, bp->vlgrp,
+ rx_hdr->l2_fhdr_vlan_tag);
+ }
+ else
+#endif
+ netif_receive_skb(skb);
+
+ bp->dev->last_rx = jiffies;
+ rx_pkt++;
+
+next_rx:
+ rx_buf->skb = NULL;
+
+ sw_cons = NEXT_RX_BD(sw_cons);
+ sw_prod = NEXT_RX_BD(sw_prod);
+
+ if ((rx_pkt == budget))
+ break;
+ }
+ bp->rx_cons = sw_cons;
+ bp->rx_prod = sw_prod;
+
+ REG_WR16(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BDIDX, sw_prod);
+
+ REG_WR(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BSEQ, bp->rx_prod_bseq);
+
+ mmiowb();
+
+ return rx_pkt;
+
+}
+
+/* MSI ISR - The only difference between this and the INTx ISR
+ * is that the MSI interrupt is always serviced.
+ */
+static irqreturn_t
+bnx2_msi(int irq, void *dev_instance, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_instance;
+ struct bnx2 *bp = dev->priv;
+
+ REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+ BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM |
+ BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
+
+ /* Return here if interrupt is disabled. */
+ if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
+ return IRQ_RETVAL(1);
+ }
+
+ if (netif_rx_schedule_prep(dev)) {
+ __netif_rx_schedule(dev);
+ }
+
+ return IRQ_RETVAL(1);
+}
+
+static irqreturn_t
+bnx2_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_instance;
+ struct bnx2 *bp = dev->priv;
+
+ /* When using INTx, it is possible for the interrupt to arrive
+ * at the CPU before the status block posted prior to the
+ * interrupt. Reading a register will flush the status block.
+ * When using MSI, the MSI message will always complete after
+ * the status block write.
+ */
+ if ((bp->status_blk->status_idx == bp->last_status_idx) ||
+ (REG_RD(bp, BNX2_PCICFG_MISC_STATUS) &
+ BNX2_PCICFG_MISC_STATUS_INTA_VALUE))
+ return IRQ_RETVAL(0);
+
+ REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+ BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM |
+ BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
+
+ /* Return here if interrupt is shared and is disabled. */
+ if (unlikely(atomic_read(&bp->intr_sem) != 0)) {
+ return IRQ_RETVAL(1);
+ }
+
+ if (netif_rx_schedule_prep(dev)) {
+ __netif_rx_schedule(dev);
+ }
+
+ return IRQ_RETVAL(1);
+}
+
+static int
+bnx2_poll(struct net_device *dev, int *budget)
+{
+ struct bnx2 *bp = dev->priv;
+ int rx_done = 1;
+
+ bp->last_status_idx = bp->status_blk->status_idx;
+
+ rmb();
+ if ((bp->status_blk->status_attn_bits &
+ STATUS_ATTN_BITS_LINK_STATE) !=
+ (bp->status_blk->status_attn_bits_ack &
+ STATUS_ATTN_BITS_LINK_STATE)) {
+
+ unsigned long flags;
+
+ spin_lock_irqsave(&bp->phy_lock, flags);
+ bnx2_phy_int(bp);
+ spin_unlock_irqrestore(&bp->phy_lock, flags);
+ }
+
+ if (bp->status_blk->status_tx_quick_consumer_index0 != bp->tx_cons) {
+ bnx2_tx_int(bp);
+ }
+
+ if (bp->status_blk->status_rx_quick_consumer_index0 != bp->rx_cons) {
+ int orig_budget = *budget;
+ int work_done;
+
+ if (orig_budget > dev->quota)
+ orig_budget = dev->quota;
+
+ work_done = bnx2_rx_int(bp, orig_budget);
+ *budget -= work_done;
+ dev->quota -= work_done;
+
+ if (work_done >= orig_budget) {
+ rx_done = 0;
+ }
+ }
+
+ if (rx_done) {
+ netif_rx_complete(dev);
+ REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+ BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+ bp->last_status_idx);
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Called with rtnl_lock from vlan functions and also dev->xmit_lock
+ * from set_multicast.
+ */
+static void
+bnx2_set_rx_mode(struct net_device *dev)
+{
+ struct bnx2 *bp = dev->priv;
+ u32 rx_mode, sort_mode;
+ int i;
+ unsigned long flags;
+
+ spin_lock_irqsave(&bp->phy_lock, flags);
+
+ rx_mode = bp->rx_mode & ~(BNX2_EMAC_RX_MODE_PROMISCUOUS |
+ BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG);
+ sort_mode = 1 | BNX2_RPM_SORT_USER0_BC_EN;
+#ifdef BCM_VLAN
+ if (!bp->vlgrp) {
+ rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG;
+ }
+#else
+ rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG;
+#endif
+ if (dev->flags & IFF_PROMISC) {
+ /* Promiscuous mode. */
+ rx_mode |= BNX2_EMAC_RX_MODE_PROMISCUOUS;
+ sort_mode |= BNX2_RPM_SORT_USER0_PROM_EN;
+ }
+ else if (dev->flags & IFF_ALLMULTI) {
+ for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) {
+ REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4),
+ 0xffffffff);
+ }
+ sort_mode |= BNX2_RPM_SORT_USER0_MC_EN;
+ }
+ else {
+ /* Accept one or more multicast(s). */
+ struct dev_mc_list *mclist;
+ u32 mc_filter[NUM_MC_HASH_REGISTERS];
+ u32 regidx;
+ u32 bit;
+ u32 crc;
+
+ memset(mc_filter, 0, 4 * NUM_MC_HASH_REGISTERS);
+
+ for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
+ i++, mclist = mclist->next) {
+
+ crc = ether_crc_le(ETH_ALEN, mclist->dmi_addr);
+ bit = crc & 0xff;
+ regidx = (bit & 0xe0) >> 5;
+ bit &= 0x1f;
+ mc_filter[regidx] |= (1 << bit);
+ }
+
+ for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) {
+ REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4),
+ mc_filter[i]);
+ }
+
+ sort_mode |= BNX2_RPM_SORT_USER0_MC_HSH_EN;
+ }
+
+ if (rx_mode != bp->rx_mode) {
+ bp->rx_mode = rx_mode;
+ REG_WR(bp, BNX2_EMAC_RX_MODE, rx_mode);
+ }
+
+ REG_WR(bp, BNX2_RPM_SORT_USER0, 0x0);
+ REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode);
+ REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode | BNX2_RPM_SORT_USER0_ENA);
+
+ spin_unlock_irqrestore(&bp->phy_lock, flags);
+}
+
+static void
+load_rv2p_fw(struct bnx2 *bp, u32 *rv2p_code, u32 rv2p_code_len,
+ u32 rv2p_proc)
+{
+ int i;
+ u32 val;
+
+
+ for (i = 0; i < rv2p_code_len; i += 8) {
+ REG_WR(bp, BNX2_RV2P_INSTR_HIGH, *rv2p_code);
+ rv2p_code++;
+ REG_WR(bp, BNX2_RV2P_INSTR_LOW, *rv2p_code);
+ rv2p_code++;
+
+ if (rv2p_proc == RV2P_PROC1) {
+ val = (i / 8) | BNX2_RV2P_PROC1_ADDR_CMD_RDWR;
+ REG_WR(bp, BNX2_RV2P_PROC1_ADDR_CMD, val);
+ }
+ else {
+ val = (i / 8) | BNX2_RV2P_PROC2_ADDR_CMD_RDWR;
+ REG_WR(bp, BNX2_RV2P_PROC2_ADDR_CMD, val);
+ }
+ }
+
+ /* Reset the processor, un-stall is done later. */
+ if (rv2p_proc == RV2P_PROC1) {
+ REG_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC1_RESET);
+ }
+ else {
+ REG_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC2_RESET);
+ }
+}
+
+static void
+load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw)
+{
+ u32 offset;
+ u32 val;
+
+ /* Halt the CPU. */
+ val = REG_RD_IND(bp, cpu_reg->mode);
+ val |= cpu_reg->mode_value_halt;
+ REG_WR_IND(bp, cpu_reg->mode, val);
+ REG_WR_IND(bp, cpu_reg->state, cpu_reg->state_value_clear);
+
+ /* Load the Text area. */
+ offset = cpu_reg->spad_base + (fw->text_addr - cpu_reg->mips_view_base);
+ if (fw->text) {
+ int j;
+
+ for (j = 0; j < (fw->text_len / 4); j++, offset += 4) {
+ REG_WR_IND(bp, offset, fw->text[j]);
+ }
+ }
+
+ /* Load the Data area. */
+ offset = cpu_reg->spad_base + (fw->data_addr - cpu_reg->mips_view_base);
+ if (fw->data) {
+ int j;
+
+ for (j = 0; j < (fw->data_len / 4); j++, offset += 4) {
+ REG_WR_IND(bp, offset, fw->data[j]);
+ }
+ }
+
+ /* Load the SBSS area. */
+ offset = cpu_reg->spad_base + (fw->sbss_addr - cpu_reg->mips_view_base);
+ if (fw->sbss) {
+ int j;
+
+ for (j = 0; j < (fw->sbss_len / 4); j++, offset += 4) {
+ REG_WR_IND(bp, offset, fw->sbss[j]);
+ }
+ }
+
+ /* Load the BSS area. */
+ offset = cpu_reg->spad_base + (fw->bss_addr - cpu_reg->mips_view_base);
+ if (fw->bss) {
+ int j;
+
+ for (j = 0; j < (fw->bss_len/4); j++, offset += 4) {
+ REG_WR_IND(bp, offset, fw->bss[j]);
+ }
+ }
+
+ /* Load the Read-Only area. */
+ offset = cpu_reg->spad_base +
+ (fw->rodata_addr - cpu_reg->mips_view_base);
+ if (fw->rodata) {
+ int j;
+
+ for (j = 0; j < (fw->rodata_len / 4); j++, offset += 4) {
+ REG_WR_IND(bp, offset, fw->rodata[j]);
+ }
+ }
+
+ /* Clear the pre-fetch instruction. */
+ REG_WR_IND(bp, cpu_reg->inst, 0);
+ REG_WR_IND(bp, cpu_reg->pc, fw->start_addr);
+
+ /* Start the CPU. */
+ val = REG_RD_IND(bp, cpu_reg->mode);
+ val &= ~cpu_reg->mode_value_halt;
+ REG_WR_IND(bp, cpu_reg->state, cpu_reg->state_value_clear);
+ REG_WR_IND(bp, cpu_reg->mode, val);
+}
+
+static void
+bnx2_init_cpus(struct bnx2 *bp)
+{
+ struct cpu_reg cpu_reg;
+ struct fw_info fw;
+
+ /* Initialize the RV2P processor. */
+ load_rv2p_fw(bp, bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1), RV2P_PROC1);
+ load_rv2p_fw(bp, bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2), RV2P_PROC2);
+
+ /* Initialize the RX Processor. */
+ cpu_reg.mode = BNX2_RXP_CPU_MODE;
+ cpu_reg.mode_value_halt = BNX2_RXP_CPU_MODE_SOFT_HALT;
+ cpu_reg.mode_value_sstep = BNX2_RXP_CPU_MODE_STEP_ENA;
+ cpu_reg.state = BNX2_RXP_CPU_STATE;
+ cpu_reg.state_value_clear = 0xffffff;
+ cpu_reg.gpr0 = BNX2_RXP_CPU_REG_FILE;
+ cpu_reg.evmask = BNX2_RXP_CPU_EVENT_MASK;
+ cpu_reg.pc = BNX2_RXP_CPU_PROGRAM_COUNTER;
+ cpu_reg.inst = BNX2_RXP_CPU_INSTRUCTION;
+ cpu_reg.bp = BNX2_RXP_CPU_HW_BREAKPOINT;
+ cpu_reg.spad_base = BNX2_RXP_SCRATCH;
+ cpu_reg.mips_view_base = 0x8000000;
+
+ fw.ver_major = bnx2_RXP_b06FwReleaseMajor;
+ fw.ver_minor = bnx2_RXP_b06FwReleaseMinor;
+ fw.ver_fix = bnx2_RXP_b06FwReleaseFix;
+ fw.start_addr = bnx2_RXP_b06FwStartAddr;
+
+ fw.text_addr = bnx2_RXP_b06FwTextAddr;
+ fw.text_len = bnx2_RXP_b06FwTextLen;
+ fw.text_index = 0;
+ fw.text = bnx2_RXP_b06FwText;
+
+ fw.data_addr = bnx2_RXP_b06FwDataAddr;
+ fw.data_len = bnx2_RXP_b06FwDataLen;
+ fw.data_index = 0;
+ fw.data = bnx2_RXP_b06FwData;
+
+ fw.sbss_addr = bnx2_RXP_b06FwSbssAddr;
+ fw.sbss_len = bnx2_RXP_b06FwSbssLen;
+ fw.sbss_index = 0;
+ fw.sbss = bnx2_RXP_b06FwSbss;
+
+ fw.bss_addr = bnx2_RXP_b06FwBssAddr;
+ fw.bss_len = bnx2_RXP_b06FwBssLen;
+ fw.bss_index = 0;
+ fw.bss = bnx2_RXP_b06FwBss;
+
+ fw.rodata_addr = bnx2_RXP_b06FwRodataAddr;
+ fw.rodata_len = bnx2_RXP_b06FwRodataLen;
+ fw.rodata_index = 0;
+ fw.rodata = bnx2_RXP_b06FwRodata;
+
+ load_cpu_fw(bp, &cpu_reg, &fw);
+
+ /* Initialize the TX Processor. */
+ cpu_reg.mode = BNX2_TXP_CPU_MODE;
+ cpu_reg.mode_value_halt = BNX2_TXP_CPU_MODE_SOFT_HALT;
+ cpu_reg.mode_value_sstep = BNX2_TXP_CPU_MODE_STEP_ENA;
+ cpu_reg.state = BNX2_TXP_CPU_STATE;
+ cpu_reg.state_value_clear = 0xffffff;
+ cpu_reg.gpr0 = BNX2_TXP_CPU_REG_FILE;
+ cpu_reg.evmask = BNX2_TXP_CPU_EVENT_MASK;
+ cpu_reg.pc = BNX2_TXP_CPU_PROGRAM_COUNTER;
+ cpu_reg.inst = BNX2_TXP_CPU_INSTRUCTION;
+ cpu_reg.bp = BNX2_TXP_CPU_HW_BREAKPOINT;
+ cpu_reg.spad_base = BNX2_TXP_SCRATCH;
+ cpu_reg.mips_view_base = 0x8000000;
+
+ fw.ver_major = bnx2_TXP_b06FwReleaseMajor;
+ fw.ver_minor = bnx2_TXP_b06FwReleaseMinor;
+ fw.ver_fix = bnx2_TXP_b06FwReleaseFix;
+ fw.start_addr = bnx2_TXP_b06FwStartAddr;
+
+ fw.text_addr = bnx2_TXP_b06FwTextAddr;
+ fw.text_len = bnx2_TXP_b06FwTextLen;
+ fw.text_index = 0;
+ fw.text = bnx2_TXP_b06FwText;
+
+ fw.data_addr = bnx2_TXP_b06FwDataAddr;
+ fw.data_len = bnx2_TXP_b06FwDataLen;
+ fw.data_index = 0;
+ fw.data = bnx2_TXP_b06FwData;
+
+ fw.sbss_addr = bnx2_TXP_b06FwSbssAddr;
+ fw.sbss_len = bnx2_TXP_b06FwSbssLen;
+ fw.sbss_index = 0;
+ fw.sbss = bnx2_TXP_b06FwSbss;
+
+ fw.bss_addr = bnx2_TXP_b06FwBssAddr;
+ fw.bss_len = bnx2_TXP_b06FwBssLen;
+ fw.bss_index = 0;
+ fw.bss = bnx2_TXP_b06FwBss;
+
+ fw.rodata_addr = bnx2_TXP_b06FwRodataAddr;
+ fw.rodata_len = bnx2_TXP_b06FwRodataLen;
+ fw.rodata_index = 0;
+ fw.rodata = bnx2_TXP_b06FwRodata;
+
+ load_cpu_fw(bp, &cpu_reg, &fw);
+
+ /* Initialize the TX Patch-up Processor. */
+ cpu_reg.mode = BNX2_TPAT_CPU_MODE;
+ cpu_reg.mode_value_halt = BNX2_TPAT_CPU_MODE_SOFT_HALT;
+ cpu_reg.mode_value_sstep = BNX2_TPAT_CPU_MODE_STEP_ENA;
+ cpu_reg.state = BNX2_TPAT_CPU_STATE;
+ cpu_reg.state_value_clear = 0xffffff;
+ cpu_reg.gpr0 = BNX2_TPAT_CPU_REG_FILE;
+ cpu_reg.evmask = BNX2_TPAT_CPU_EVENT_MASK;
+ cpu_reg.pc = BNX2_TPAT_CPU_PROGRAM_COUNTER;
+ cpu_reg.inst = BNX2_TPAT_CPU_INSTRUCTION;
+ cpu_reg.bp = BNX2_TPAT_CPU_HW_BREAKPOINT;
+ cpu_reg.spad_base = BNX2_TPAT_SCRATCH;
+ cpu_reg.mips_view_base = 0x8000000;
+
+ fw.ver_major = bnx2_TPAT_b06FwReleaseMajor;
+ fw.ver_minor = bnx2_TPAT_b06FwReleaseMinor;
+ fw.ver_fix = bnx2_TPAT_b06FwReleaseFix;
+ fw.start_addr = bnx2_TPAT_b06FwStartAddr;
+
+ fw.text_addr = bnx2_TPAT_b06FwTextAddr;
+ fw.text_len = bnx2_TPAT_b06FwTextLen;
+ fw.text_index = 0;
+ fw.text = bnx2_TPAT_b06FwText;
+
+ fw.data_addr = bnx2_TPAT_b06FwDataAddr;
+ fw.data_len = bnx2_TPAT_b06FwDataLen;
+ fw.data_index = 0;
+ fw.data = bnx2_TPAT_b06FwData;
+
+ fw.sbss_addr = bnx2_TPAT_b06FwSbssAddr;
+ fw.sbss_len = bnx2_TPAT_b06FwSbssLen;
+ fw.sbss_index = 0;
+ fw.sbss = bnx2_TPAT_b06FwSbss;
+
+ fw.bss_addr = bnx2_TPAT_b06FwBssAddr;
+ fw.bss_len = bnx2_TPAT_b06FwBssLen;
+ fw.bss_index = 0;
+ fw.bss = bnx2_TPAT_b06FwBss;
+
+ fw.rodata_addr = bnx2_TPAT_b06FwRodataAddr;
+ fw.rodata_len = bnx2_TPAT_b06FwRodataLen;
+ fw.rodata_index = 0;
+ fw.rodata = bnx2_TPAT_b06FwRodata;
+
+ load_cpu_fw(bp, &cpu_reg, &fw);
+
+ /* Initialize the Completion Processor. */
+ cpu_reg.mode = BNX2_COM_CPU_MODE;
+ cpu_reg.mode_value_halt = BNX2_COM_CPU_MODE_SOFT_HALT;
+ cpu_reg.mode_value_sstep = BNX2_COM_CPU_MODE_STEP_ENA;
+ cpu_reg.state = BNX2_COM_CPU_STATE;
+ cpu_reg.state_value_clear = 0xffffff;
+ cpu_reg.gpr0 = BNX2_COM_CPU_REG_FILE;
+ cpu_reg.evmask = BNX2_COM_CPU_EVENT_MASK;
+ cpu_reg.pc = BNX2_COM_CPU_PROGRAM_COUNTER;
+ cpu_reg.inst = BNX2_COM_CPU_INSTRUCTION;
+ cpu_reg.bp = BNX2_COM_CPU_HW_BREAKPOINT;
+ cpu_reg.spad_base = BNX2_COM_SCRATCH;
+ cpu_reg.mips_view_base = 0x8000000;
+
+ fw.ver_major = bnx2_COM_b06FwReleaseMajor;
+ fw.ver_minor = bnx2_COM_b06FwReleaseMinor;
+ fw.ver_fix = bnx2_COM_b06FwReleaseFix;
+ fw.start_addr = bnx2_COM_b06FwStartAddr;
+
+ fw.text_addr = bnx2_COM_b06FwTextAddr;
+ fw.text_len = bnx2_COM_b06FwTextLen;
+ fw.text_index = 0;
+ fw.text = bnx2_COM_b06FwText;
+
+ fw.data_addr = bnx2_COM_b06FwDataAddr;
+ fw.data_len = bnx2_COM_b06FwDataLen;
+ fw.data_index = 0;
+ fw.data = bnx2_COM_b06FwData;
+
+ fw.sbss_addr = bnx2_COM_b06FwSbssAddr;
+ fw.sbss_len = bnx2_COM_b06FwSbssLen;
+ fw.sbss_index = 0;
+ fw.sbss = bnx2_COM_b06FwSbss;
+
+ fw.bss_addr = bnx2_COM_b06FwBssAddr;
+ fw.bss_len = bnx2_COM_b06FwBssLen;
+ fw.bss_index = 0;
+ fw.bss = bnx2_COM_b06FwBss;
+
+ fw.rodata_addr = bnx2_COM_b06FwRodataAddr;
+ fw.rodata_len = bnx2_COM_b06FwRodataLen;
+ fw.rodata_index = 0;
+ fw.rodata = bnx2_COM_b06FwRodata;
+
+ load_cpu_fw(bp, &cpu_reg, &fw);
+
+}
+
+static int
+bnx2_set_power_state(struct bnx2 *bp, int state)
+{
+ u16 pmcsr;
+
+ pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pmcsr);
+
+ switch (state) {
+ case 0: {
+ u32 val;
+
+ pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL,
+ (pmcsr & ~PCI_PM_CTRL_STATE_MASK) |
+ PCI_PM_CTRL_PME_STATUS);
+
+ if (pmcsr & PCI_PM_CTRL_STATE_MASK)
+ /* delay required during transition out of D3hot */
+ msleep(20);
+
+ val = REG_RD(bp, BNX2_EMAC_MODE);
+ val |= BNX2_EMAC_MODE_MPKT_RCVD | BNX2_EMAC_MODE_ACPI_RCVD;
+ val &= ~BNX2_EMAC_MODE_MPKT;
+ REG_WR(bp, BNX2_EMAC_MODE, val);
+
+ val = REG_RD(bp, BNX2_RPM_CONFIG);
+ val &= ~BNX2_RPM_CONFIG_ACPI_ENA;
+ REG_WR(bp, BNX2_RPM_CONFIG, val);
+ break;
+ }
+ case 3: {
+ int i;
+ u32 val, wol_msg;
+
+ if (bp->wol) {
+ u32 advertising;
+ u8 autoneg;
+
+ autoneg = bp->autoneg;
+ advertising = bp->advertising;
+
+ bp->autoneg = AUTONEG_SPEED;
+ bp->advertising = ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full |
+ ADVERTISED_Autoneg;
+
+ bnx2_setup_copper_phy(bp);
+
+ bp->autoneg = autoneg;
+ bp->advertising = advertising;
+
+ bnx2_set_mac_addr(bp);
+
+ val = REG_RD(bp, BNX2_EMAC_MODE);
+
+ /* Enable port mode. */
+ val &= ~BNX2_EMAC_MODE_PORT;
+ val |= BNX2_EMAC_MODE_PORT_MII |
+ BNX2_EMAC_MODE_MPKT_RCVD |
+ BNX2_EMAC_MODE_ACPI_RCVD |
+ BNX2_EMAC_MODE_FORCE_LINK |
+ BNX2_EMAC_MODE_MPKT;
+
+ REG_WR(bp, BNX2_EMAC_MODE, val);
+
+ /* receive all multicast */
+ for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) {
+ REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4),
+ 0xffffffff);
+ }
+ REG_WR(bp, BNX2_EMAC_RX_MODE,
+ BNX2_EMAC_RX_MODE_SORT_MODE);
+
+ val = 1 | BNX2_RPM_SORT_USER0_BC_EN |
+ BNX2_RPM_SORT_USER0_MC_EN;
+ REG_WR(bp, BNX2_RPM_SORT_USER0, 0x0);
+ REG_WR(bp, BNX2_RPM_SORT_USER0, val);
+ REG_WR(bp, BNX2_RPM_SORT_USER0, val |
+ BNX2_RPM_SORT_USER0_ENA);
+
+ /* Need to enable EMAC and RPM for WOL. */
+ REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
+ BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_MAC_ENABLE |
+ BNX2_MISC_ENABLE_SET_BITS_TX_HEADER_Q_ENABLE |
+ BNX2_MISC_ENABLE_SET_BITS_EMAC_ENABLE);
+
+ val = REG_RD(bp, BNX2_RPM_CONFIG);
+ val &= ~BNX2_RPM_CONFIG_ACPI_ENA;
+ REG_WR(bp, BNX2_RPM_CONFIG, val);
+
+ wol_msg = BNX2_DRV_MSG_CODE_SUSPEND_WOL;
+ }
+ else {
+ wol_msg = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
+ }
+
+ bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT3 | wol_msg);
+
+ pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+ if ((CHIP_ID(bp) == CHIP_ID_5706_A0) ||
+ (CHIP_ID(bp) == CHIP_ID_5706_A1)) {
+
+ if (bp->wol)
+ pmcsr |= 3;
+ }
+ else {
+ pmcsr |= 3;
+ }
+ if (bp->wol) {
+ pmcsr |= PCI_PM_CTRL_PME_ENABLE;
+ }
+ pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL,
+ pmcsr);
+
+ /* No more memory access after this point until
+ * device is brought back to D0.
+ */
+ udelay(50);
+ break;
+ }
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int
+bnx2_acquire_nvram_lock(struct bnx2 *bp)
+{
+ u32 val;
+ int j;
+
+ /* Request access to the flash interface. */
+ REG_WR(bp, BNX2_NVM_SW_ARB, BNX2_NVM_SW_ARB_ARB_REQ_SET2);
+ for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
+ val = REG_RD(bp, BNX2_NVM_SW_ARB);
+ if (val & BNX2_NVM_SW_ARB_ARB_ARB2)
+ break;
+
+ udelay(5);
+ }
+
+ if (j >= NVRAM_TIMEOUT_COUNT)
+ return -EBUSY;
+
+ return 0;
+}
+
+static int
+bnx2_release_nvram_lock(struct bnx2 *bp)
+{
+ int j;
+ u32 val;
+
+ /* Relinquish nvram interface. */
+ REG_WR(bp, BNX2_NVM_SW_ARB, BNX2_NVM_SW_ARB_ARB_REQ_CLR2);
+
+ for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
+ val = REG_RD(bp, BNX2_NVM_SW_ARB);
+ if (!(val & BNX2_NVM_SW_ARB_ARB_ARB2))
+ break;
+
+ udelay(5);
+ }
+
+ if (j >= NVRAM_TIMEOUT_COUNT)
+ return -EBUSY;
+
+ return 0;
+}
+
+
+static int
+bnx2_enable_nvram_write(struct bnx2 *bp)
+{
+ u32 val;
+
+ val = REG_RD(bp, BNX2_MISC_CFG);
+ REG_WR(bp, BNX2_MISC_CFG, val | BNX2_MISC_CFG_NVM_WR_EN_PCI);
+
+ if (!bp->flash_info->buffered) {
+ int j;
+
+ REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
+ REG_WR(bp, BNX2_NVM_COMMAND,
+ BNX2_NVM_COMMAND_WREN | BNX2_NVM_COMMAND_DOIT);
+
+ for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
+ udelay(5);
+
+ val = REG_RD(bp, BNX2_NVM_COMMAND);
+ if (val & BNX2_NVM_COMMAND_DONE)
+ break;
+ }
+
+ if (j >= NVRAM_TIMEOUT_COUNT)
+ return -EBUSY;
+ }
+ return 0;
+}
+
+static void
+bnx2_disable_nvram_write(struct bnx2 *bp)
+{
+ u32 val;
+
+ val = REG_RD(bp, BNX2_MISC_CFG);
+ REG_WR(bp, BNX2_MISC_CFG, val & ~BNX2_MISC_CFG_NVM_WR_EN);
+}
+
+
+static void
+bnx2_enable_nvram_access(struct bnx2 *bp)
+{
+ u32 val;
+
+ val = REG_RD(bp, BNX2_NVM_ACCESS_ENABLE);
+ /* Enable both bits, even on read. */
+ REG_WR(bp, BNX2_NVM_ACCESS_ENABLE,
+ val | BNX2_NVM_ACCESS_ENABLE_EN | BNX2_NVM_ACCESS_ENABLE_WR_EN);
+}
+
+static void
+bnx2_disable_nvram_access(struct bnx2 *bp)
+{
+ u32 val;
+
+ val = REG_RD(bp, BNX2_NVM_ACCESS_ENABLE);
+ /* Disable both bits, even after read. */
+ REG_WR(bp, BNX2_NVM_ACCESS_ENABLE,
+ val & ~(BNX2_NVM_ACCESS_ENABLE_EN |
+ BNX2_NVM_ACCESS_ENABLE_WR_EN));
+}
+
+static int
+bnx2_nvram_erase_page(struct bnx2 *bp, u32 offset)
+{
+ u32 cmd;
+ int j;
+
+ if (bp->flash_info->buffered)
+ /* Buffered flash, no erase needed */
+ return 0;
+
+ /* Build an erase command */
+ cmd = BNX2_NVM_COMMAND_ERASE | BNX2_NVM_COMMAND_WR |
+ BNX2_NVM_COMMAND_DOIT;
+
+ /* Need to clear DONE bit separately. */
+ REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
+
+ /* Address of the NVRAM to read from. */
+ REG_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE);
+
+ /* Issue an erase command. */
+ REG_WR(bp, BNX2_NVM_COMMAND, cmd);
+
+ /* Wait for completion. */
+ for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
+ u32 val;
+
+ udelay(5);
+
+ val = REG_RD(bp, BNX2_NVM_COMMAND);
+ if (val & BNX2_NVM_COMMAND_DONE)
+ break;
+ }
+
+ if (j >= NVRAM_TIMEOUT_COUNT)
+ return -EBUSY;
+
+ return 0;
+}
+
+static int
+bnx2_nvram_read_dword(struct bnx2 *bp, u32 offset, u8 *ret_val, u32 cmd_flags)
+{
+ u32 cmd;
+ int j;
+
+ /* Build the command word. */
+ cmd = BNX2_NVM_COMMAND_DOIT | cmd_flags;
+
+ /* Calculate an offset of a buffered flash. */
+ if (bp->flash_info->buffered) {
+ offset = ((offset / bp->flash_info->page_size) <<
+ bp->flash_info->page_bits) +
+ (offset % bp->flash_info->page_size);
+ }
+
+ /* Need to clear DONE bit separately. */
+ REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
+
+ /* Address of the NVRAM to read from. */
+ REG_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE);
+
+ /* Issue a read command. */
+ REG_WR(bp, BNX2_NVM_COMMAND, cmd);
+
+ /* Wait for completion. */
+ for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
+ u32 val;
+
+ udelay(5);
+
+ val = REG_RD(bp, BNX2_NVM_COMMAND);
+ if (val & BNX2_NVM_COMMAND_DONE) {
+ val = REG_RD(bp, BNX2_NVM_READ);
+
+ val = be32_to_cpu(val);
+ memcpy(ret_val, &val, 4);
+ break;
+ }
+ }
+ if (j >= NVRAM_TIMEOUT_COUNT)
+ return -EBUSY;
+
+ return 0;
+}
+
+
+static int
+bnx2_nvram_write_dword(struct bnx2 *bp, u32 offset, u8 *val, u32 cmd_flags)
+{
+ u32 cmd, val32;
+ int j;
+
+ /* Build the command word. */
+ cmd = BNX2_NVM_COMMAND_DOIT | BNX2_NVM_COMMAND_WR | cmd_flags;
+
+ /* Calculate an offset of a buffered flash. */
+ if (bp->flash_info->buffered) {
+ offset = ((offset / bp->flash_info->page_size) <<
+ bp->flash_info->page_bits) +
+ (offset % bp->flash_info->page_size);
+ }
+
+ /* Need to clear DONE bit separately. */
+ REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
+
+ memcpy(&val32, val, 4);
+ val32 = cpu_to_be32(val32);
+
+ /* Write the data. */
+ REG_WR(bp, BNX2_NVM_WRITE, val32);
+
+ /* Address of the NVRAM to write to. */
+ REG_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE);
+
+ /* Issue the write command. */
+ REG_WR(bp, BNX2_NVM_COMMAND, cmd);
+
+ /* Wait for completion. */
+ for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
+ udelay(5);
+
+ if (REG_RD(bp, BNX2_NVM_COMMAND) & BNX2_NVM_COMMAND_DONE)
+ break;
+ }
+ if (j >= NVRAM_TIMEOUT_COUNT)
+ return -EBUSY;
+
+ return 0;
+}
+
+static int
+bnx2_init_nvram(struct bnx2 *bp)
+{
+ u32 val;
+ int j, entry_count, rc;
+ struct flash_spec *flash;
+
+ /* Determine the selected interface. */
+ val = REG_RD(bp, BNX2_NVM_CFG1);
+
+ entry_count = sizeof(flash_table) / sizeof(struct flash_spec);
+
+ rc = 0;
+ if (val & 0x40000000) {
+
+ /* Flash interface has been reconfigured */
+ for (j = 0, flash = &flash_table[0]; j < entry_count;
+ j++, flash++) {
+
+ if (val == flash->config1) {
+ bp->flash_info = flash;
+ break;
+ }
+ }
+ }
+ else {
+ /* Not yet been reconfigured */
+
+ for (j = 0, flash = &flash_table[0]; j < entry_count;
+ j++, flash++) {
+
+ if ((val & FLASH_STRAP_MASK) == flash->strapping) {
+ bp->flash_info = flash;
+
+ /* Request access to the flash interface. */
+ if ((rc = bnx2_acquire_nvram_lock(bp)) != 0)
+ return rc;
+
+ /* Enable access to flash interface */
+ bnx2_enable_nvram_access(bp);
+
+ /* Reconfigure the flash interface */
+ REG_WR(bp, BNX2_NVM_CFG1, flash->config1);
+ REG_WR(bp, BNX2_NVM_CFG2, flash->config2);
+ REG_WR(bp, BNX2_NVM_CFG3, flash->config3);
+ REG_WR(bp, BNX2_NVM_WRITE1, flash->write1);
+
+ /* Disable access to flash interface */
+ bnx2_disable_nvram_access(bp);
+ bnx2_release_nvram_lock(bp);
+
+ break;
+ }
+ }
+ } /* if (val & 0x40000000) */
+
+ if (j == entry_count) {
+ bp->flash_info = NULL;
+ printk(KERN_ALERT "Unknown flash/EEPROM type.\n");
+ rc = -ENODEV;
+ }
+
+ return rc;
+}
+
+static int
+bnx2_nvram_read(struct bnx2 *bp, u32 offset, u8 *ret_buf,
+ int buf_size)
+{
+ int rc = 0;
+ u32 cmd_flags, offset32, len32, extra;
+
+ if (buf_size == 0)
+ return 0;
+
+ /* Request access to the flash interface. */
+ if ((rc = bnx2_acquire_nvram_lock(bp)) != 0)
+ return rc;
+
+ /* Enable access to flash interface */
+ bnx2_enable_nvram_access(bp);
+
+ len32 = buf_size;
+ offset32 = offset;
+ extra = 0;
+
+ cmd_flags = 0;
+
+ if (offset32 & 3) {
+ u8 buf[4];
+ u32 pre_len;
+
+ offset32 &= ~3;
+ pre_len = 4 - (offset & 3);
+
+ if (pre_len >= len32) {
+ pre_len = len32;
+ cmd_flags = BNX2_NVM_COMMAND_FIRST |
+ BNX2_NVM_COMMAND_LAST;
+ }
+ else {
+ cmd_flags = BNX2_NVM_COMMAND_FIRST;
+ }
+
+ rc = bnx2_nvram_read_dword(bp, offset32, buf, cmd_flags);
+
+ if (rc)
+ return rc;
+
+ memcpy(ret_buf, buf + (offset & 3), pre_len);
+
+ offset32 += 4;
+ ret_buf += pre_len;
+ len32 -= pre_len;
+ }
+ if (len32 & 3) {
+ extra = 4 - (len32 & 3);
+ len32 = (len32 + 4) & ~3;
+ }
+
+ if (len32 == 4) {
+ u8 buf[4];
+
+ if (cmd_flags)
+ cmd_flags = BNX2_NVM_COMMAND_LAST;
+ else
+ cmd_flags = BNX2_NVM_COMMAND_FIRST |
+ BNX2_NVM_COMMAND_LAST;
+
+ rc = bnx2_nvram_read_dword(bp, offset32, buf, cmd_flags);
+
+ memcpy(ret_buf, buf, 4 - extra);
+ }
+ else if (len32 > 0) {
+ u8 buf[4];
+
+ /* Read the first word. */
+ if (cmd_flags)
+ cmd_flags = 0;
+ else
+ cmd_flags = BNX2_NVM_COMMAND_FIRST;
+
+ rc = bnx2_nvram_read_dword(bp, offset32, ret_buf, cmd_flags);
+
+ /* Advance to the next dword. */
+ offset32 += 4;
+ ret_buf += 4;
+ len32 -= 4;
+
+ while (len32 > 4 && rc == 0) {
+ rc = bnx2_nvram_read_dword(bp, offset32, ret_buf, 0);
+
+ /* Advance to the next dword. */
+ offset32 += 4;
+ ret_buf += 4;
+ len32 -= 4;
+ }
+
+ if (rc)
+ return rc;
+
+ cmd_flags = BNX2_NVM_COMMAND_LAST;
+ rc = bnx2_nvram_read_dword(bp, offset32, buf, cmd_flags);
+
+ memcpy(ret_buf, buf, 4 - extra);
+ }
+
+ /* Disable access to flash interface */
+ bnx2_disable_nvram_access(bp);
+
+ bnx2_release_nvram_lock(bp);
+
+ return rc;
+}
+
+static int
+bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf,
+ int buf_size)
+{
+ u32 written, offset32, len32;
+ u8 *buf, start[4], end[4];
+ int rc = 0;
+ int align_start, align_end;
+
+ buf = data_buf;
+ offset32 = offset;
+ len32 = buf_size;
+ align_start = align_end = 0;
+
+ if ((align_start = (offset32 & 3))) {
+ offset32 &= ~3;
+ len32 += align_start;
+ if ((rc = bnx2_nvram_read(bp, offset32, start, 4)))
+ return rc;
+ }
+
+ if (len32 & 3) {
+ if ((len32 > 4) || !align_start) {
+ align_end = 4 - (len32 & 3);
+ len32 += align_end;
+ if ((rc = bnx2_nvram_read(bp, offset32 + len32 - 4,
+ end, 4))) {
+ return rc;
+ }
+ }
+ }
+
+ if (align_start || align_end) {
+ buf = kmalloc(len32, GFP_KERNEL);
+ if (buf == 0)
+ return -ENOMEM;
+ if (align_start) {
+ memcpy(buf, start, 4);
+ }
+ if (align_end) {
+ memcpy(buf + len32 - 4, end, 4);
+ }
+ memcpy(buf + align_start, data_buf, buf_size);
+ }
+
+ written = 0;
+ while ((written < len32) && (rc == 0)) {
+ u32 page_start, page_end, data_start, data_end;
+ u32 addr, cmd_flags;
+ int i;
+ u8 flash_buffer[264];
+
+ /* Find the page_start addr */
+ page_start = offset32 + written;
+ page_start -= (page_start % bp->flash_info->page_size);
+ /* Find the page_end addr */
+ page_end = page_start + bp->flash_info->page_size;
+ /* Find the data_start addr */
+ data_start = (written == 0) ? offset32 : page_start;
+ /* Find the data_end addr */
+ data_end = (page_end > offset32 + len32) ?
+ (offset32 + len32) : page_end;
+
+ /* Request access to the flash interface. */
+ if ((rc = bnx2_acquire_nvram_lock(bp)) != 0)
+ goto nvram_write_end;
+
+ /* Enable access to flash interface */
+ bnx2_enable_nvram_access(bp);
+
+ cmd_flags = BNX2_NVM_COMMAND_FIRST;
+ if (bp->flash_info->buffered == 0) {
+ int j;
+
+ /* Read the whole page into the buffer
+ * (non-buffer flash only) */
+ for (j = 0; j < bp->flash_info->page_size; j += 4) {
+ if (j == (bp->flash_info->page_size - 4)) {
+ cmd_flags |= BNX2_NVM_COMMAND_LAST;
+ }
+ rc = bnx2_nvram_read_dword(bp,
+ page_start + j,
+ &flash_buffer[j],
+ cmd_flags);
+
+ if (rc)
+ goto nvram_write_end;
+
+ cmd_flags = 0;
+ }
+ }
+
+ /* Enable writes to flash interface (unlock write-protect) */
+ if ((rc = bnx2_enable_nvram_write(bp)) != 0)
+ goto nvram_write_end;
+
+ /* Erase the page */
+ if ((rc = bnx2_nvram_erase_page(bp, page_start)) != 0)
+ goto nvram_write_end;
+
+ /* Re-enable the write again for the actual write */
+ bnx2_enable_nvram_write(bp);
+
+ /* Loop to write back the buffer data from page_start to
+ * data_start */
+ i = 0;
+ if (bp->flash_info->buffered == 0) {
+ for (addr = page_start; addr < data_start;
+ addr += 4, i += 4) {
+
+ rc = bnx2_nvram_write_dword(bp, addr,
+ &flash_buffer[i], cmd_flags);
+
+ if (rc != 0)
+ goto nvram_write_end;
+
+ cmd_flags = 0;
+ }
+ }
+
+ /* Loop to write the new data from data_start to data_end */
+ for (addr = data_start; addr < data_end; addr += 4, i++) {
+ if ((addr == page_end - 4) ||
+ ((bp->flash_info->buffered) &&
+ (addr == data_end - 4))) {
+
+ cmd_flags |= BNX2_NVM_COMMAND_LAST;
+ }
+ rc = bnx2_nvram_write_dword(bp, addr, buf,
+ cmd_flags);
+
+ if (rc != 0)
+ goto nvram_write_end;
+
+ cmd_flags = 0;
+ buf += 4;
+ }
+
+ /* Loop to write back the buffer data from data_end
+ * to page_end */
+ if (bp->flash_info->buffered == 0) {
+ for (addr = data_end; addr < page_end;
+ addr += 4, i += 4) {
+
+ if (addr == page_end-4) {
+ cmd_flags = BNX2_NVM_COMMAND_LAST;
+ }
+ rc = bnx2_nvram_write_dword(bp, addr,
+ &flash_buffer[i], cmd_flags);
+
+ if (rc != 0)
+ goto nvram_write_end;
+
+ cmd_flags = 0;
+ }
+ }
+
+ /* Disable writes to flash interface (lock write-protect) */
+ bnx2_disable_nvram_write(bp);
+
+ /* Disable access to flash interface */
+ bnx2_disable_nvram_access(bp);
+ bnx2_release_nvram_lock(bp);
+
+ /* Increment written */
+ written += data_end - data_start;
+ }
+
+nvram_write_end:
+ if (align_start || align_end)
+ kfree(buf);
+ return rc;
+}
+
+static int
+bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
+{
+ u32 val;
+ int i, rc = 0;
+
+ /* Wait for the current PCI transaction to complete before
+ * issuing a reset. */
+ REG_WR(bp, BNX2_MISC_ENABLE_CLR_BITS,
+ BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE |
+ BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE |
+ BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE |
+ BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE);
+ val = REG_RD(bp, BNX2_MISC_ENABLE_CLR_BITS);
+ udelay(5);
+
+ /* Deposit a driver reset signature so the firmware knows that
+ * this is a soft reset. */
+ REG_WR_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_DRV_RESET_SIGNATURE,
+ BNX2_DRV_RESET_SIGNATURE_MAGIC);
+
+ bp->fw_timed_out = 0;
+
+ /* Wait for the firmware to tell us it is ok to issue a reset. */
+ bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT0 | reset_code);
+
+ /* Do a dummy read to force the chip to complete all current transaction
+ * before we issue a reset. */
+ val = REG_RD(bp, BNX2_MISC_ID);
+
+ val = BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
+ BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
+ BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP;
+
+ /* Chip reset. */
+ REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, val);
+
+ if ((CHIP_ID(bp) == CHIP_ID_5706_A0) ||
+ (CHIP_ID(bp) == CHIP_ID_5706_A1))
+ msleep(15);
+
+ /* Reset takes approximate 30 usec */
+ for (i = 0; i < 10; i++) {
+ val = REG_RD(bp, BNX2_PCICFG_MISC_CONFIG);
+ if ((val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
+ BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) == 0) {
+ break;
+ }
+ udelay(10);
+ }
+
+ if (val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
+ BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) {
+ printk(KERN_ERR PFX "Chip reset did not complete\n");
+ return -EBUSY;
+ }
+
+ /* Make sure byte swapping is properly configured. */
+ val = REG_RD(bp, BNX2_PCI_SWAP_DIAG0);
+ if (val != 0x01020304) {
+ printk(KERN_ERR PFX "Chip not in correct endian mode\n");
+ return -ENODEV;
+ }
+
+ bp->fw_timed_out = 0;
+
+ /* Wait for the firmware to finish its initialization. */
+ bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT1 | reset_code);
+
+ if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
+ /* Adjust the voltage regular to two steps lower. The default
+ * of this register is 0x0000000e. */
+ REG_WR(bp, BNX2_MISC_VREG_CONTROL, 0x000000fa);
+
+ /* Remove bad rbuf memory from the free pool. */
+ rc = bnx2_alloc_bad_rbuf(bp);
+ }
+
+ return rc;
+}
+
+static int
+bnx2_init_chip(struct bnx2 *bp)
+{
+ u32 val;
+
+ /* Make sure the interrupt is not active. */
+ REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
+
+ val = BNX2_DMA_CONFIG_DATA_BYTE_SWAP |
+ BNX2_DMA_CONFIG_DATA_WORD_SWAP |
+#ifdef __BIG_ENDIAN
+ BNX2_DMA_CONFIG_CNTL_BYTE_SWAP |
+#endif
+ BNX2_DMA_CONFIG_CNTL_WORD_SWAP |
+ DMA_READ_CHANS << 12 |
+ DMA_WRITE_CHANS << 16;
+
+ val |= (0x2 << 20) | (1 << 11);
+
+ if ((bp->flags & PCIX_FLAG) && (bp->bus_speed_mhz = 133))
+ val |= (1 << 23);
+
+ if ((CHIP_NUM(bp) == CHIP_NUM_5706) &&
+ (CHIP_ID(bp) != CHIP_ID_5706_A0) && !(bp->flags & PCIX_FLAG))
+ val |= BNX2_DMA_CONFIG_CNTL_PING_PONG_DMA;
+
+ REG_WR(bp, BNX2_DMA_CONFIG, val);
+
+ if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
+ val = REG_RD(bp, BNX2_TDMA_CONFIG);
+ val |= BNX2_TDMA_CONFIG_ONE_DMA;
+ REG_WR(bp, BNX2_TDMA_CONFIG, val);
+ }
+
+ if (bp->flags & PCIX_FLAG) {
+ u16 val16;
+
+ pci_read_config_word(bp->pdev, bp->pcix_cap + PCI_X_CMD,
+ &val16);
+ pci_write_config_word(bp->pdev, bp->pcix_cap + PCI_X_CMD,
+ val16 & ~PCI_X_CMD_ERO);
+ }
+
+ REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
+ BNX2_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE |
+ BNX2_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE |
+ BNX2_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE);
+
+ /* Initialize context mapping and zero out the quick contexts. The
+ * context block must have already been enabled. */
+ bnx2_init_context(bp);
+
+ bnx2_init_cpus(bp);
+ bnx2_init_nvram(bp);
+
+ bnx2_set_mac_addr(bp);
+
+ val = REG_RD(bp, BNX2_MQ_CONFIG);
+ val &= ~BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE;
+ val |= BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_256;
+ REG_WR(bp, BNX2_MQ_CONFIG, val);
+
+ val = 0x10000 + (MAX_CID_CNT * MB_KERNEL_CTX_SIZE);
+ REG_WR(bp, BNX2_MQ_KNL_BYP_WIND_START, val);
+ REG_WR(bp, BNX2_MQ_KNL_WIND_END, val);
+
+ val = (BCM_PAGE_BITS - 8) << 24;
+ REG_WR(bp, BNX2_RV2P_CONFIG, val);
+
+ /* Configure page size. */
+ val = REG_RD(bp, BNX2_TBDR_CONFIG);
+ val &= ~BNX2_TBDR_CONFIG_PAGE_SIZE;
+ val |= (BCM_PAGE_BITS - 8) << 24 | 0x40;
+ REG_WR(bp, BNX2_TBDR_CONFIG, val);
+
+ val = bp->mac_addr[0] +
+ (bp->mac_addr[1] << 8) +
+ (bp->mac_addr[2] << 16) +
+ bp->mac_addr[3] +
+ (bp->mac_addr[4] << 8) +
+ (bp->mac_addr[5] << 16);
+ REG_WR(bp, BNX2_EMAC_BACKOFF_SEED, val);
+
+ /* Program the MTU. Also include 4 bytes for CRC32. */
+ val = bp->dev->mtu + ETH_HLEN + 4;
+ if (val > (MAX_ETHERNET_PACKET_SIZE + 4))
+ val |= BNX2_EMAC_RX_MTU_SIZE_JUMBO_ENA;
+ REG_WR(bp, BNX2_EMAC_RX_MTU_SIZE, val);
+
+ bp->last_status_idx = 0;
+ bp->rx_mode = BNX2_EMAC_RX_MODE_SORT_MODE;
+
+ /* Set up how to generate a link change interrupt. */
+ REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
+
+ REG_WR(bp, BNX2_HC_STATUS_ADDR_L,
+ (u64) bp->status_blk_mapping & 0xffffffff);
+ REG_WR(bp, BNX2_HC_STATUS_ADDR_H, (u64) bp->status_blk_mapping >> 32);
+
+ REG_WR(bp, BNX2_HC_STATISTICS_ADDR_L,
+ (u64) bp->stats_blk_mapping & 0xffffffff);
+ REG_WR(bp, BNX2_HC_STATISTICS_ADDR_H,
+ (u64) bp->stats_blk_mapping >> 32);
+
+ REG_WR(bp, BNX2_HC_TX_QUICK_CONS_TRIP,
+ (bp->tx_quick_cons_trip_int << 16) | bp->tx_quick_cons_trip);
+
+ REG_WR(bp, BNX2_HC_RX_QUICK_CONS_TRIP,
+ (bp->rx_quick_cons_trip_int << 16) | bp->rx_quick_cons_trip);
+
+ REG_WR(bp, BNX2_HC_COMP_PROD_TRIP,
+ (bp->comp_prod_trip_int << 16) | bp->comp_prod_trip);
+
+ REG_WR(bp, BNX2_HC_TX_TICKS, (bp->tx_ticks_int << 16) | bp->tx_ticks);
+
+ REG_WR(bp, BNX2_HC_RX_TICKS, (bp->rx_ticks_int << 16) | bp->rx_ticks);
+
+ REG_WR(bp, BNX2_HC_COM_TICKS,
+ (bp->com_ticks_int << 16) | bp->com_ticks);
+
+ REG_WR(bp, BNX2_HC_CMD_TICKS,
+ (bp->cmd_ticks_int << 16) | bp->cmd_ticks);
+
+ REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks & 0xffff00);
+ REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */
+
+ if (CHIP_ID(bp) == CHIP_ID_5706_A1)
+ REG_WR(bp, BNX2_HC_CONFIG, BNX2_HC_CONFIG_COLLECT_STATS);
+ else {
+ REG_WR(bp, BNX2_HC_CONFIG, BNX2_HC_CONFIG_RX_TMR_MODE |
+ BNX2_HC_CONFIG_TX_TMR_MODE |
+ BNX2_HC_CONFIG_COLLECT_STATS);
+ }
+
+ /* Clear internal stats counters. */
+ REG_WR(bp, BNX2_HC_COMMAND, BNX2_HC_COMMAND_CLR_STAT_NOW);
+
+ REG_WR(bp, BNX2_HC_ATTN_BITS_ENABLE, STATUS_ATTN_BITS_LINK_STATE);
+
+ /* Initialize the receive filter. */
+ bnx2_set_rx_mode(bp->dev);
+
+ bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET);
+
+ REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, 0x5ffffff);
+ REG_RD(bp, BNX2_MISC_ENABLE_SET_BITS);
+
+ udelay(20);
+
+ return 0;
+}
+
+
+static void
+bnx2_init_tx_ring(struct bnx2 *bp)
+{
+ struct tx_bd *txbd;
+ u32 val;
+
+ txbd = &bp->tx_desc_ring[MAX_TX_DESC_CNT];
+
+ txbd->tx_bd_haddr_hi = (u64) bp->tx_desc_mapping >> 32;
+ txbd->tx_bd_haddr_lo = (u64) bp->tx_desc_mapping & 0xffffffff;
+
+ bp->tx_prod = 0;
+ bp->tx_cons = 0;
+ bp->tx_prod_bseq = 0;
+ atomic_set(&bp->tx_avail_bd, bp->tx_ring_size);
+
+ val = BNX2_L2CTX_TYPE_TYPE_L2;
+ val |= BNX2_L2CTX_TYPE_SIZE_L2;
+ CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_TYPE, val);
+
+ val = BNX2_L2CTX_CMD_TYPE_TYPE_L2;
+ val |= 8 << 16;
+ CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_CMD_TYPE, val);
+
+ val = (u64) bp->tx_desc_mapping >> 32;
+ CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_TBDR_BHADDR_HI, val);
+
+ val = (u64) bp->tx_desc_mapping & 0xffffffff;
+ CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_TBDR_BHADDR_LO, val);
+}
+
+static void
+bnx2_init_rx_ring(struct bnx2 *bp)
+{
+ struct rx_bd *rxbd;
+ int i;
+ u16 prod, ring_prod;
+ u32 val;
+
+ /* 8 for CRC and VLAN */
+ bp->rx_buf_use_size = bp->dev->mtu + ETH_HLEN + bp->rx_offset + 8;
+ /* 8 for alignment */
+ bp->rx_buf_size = bp->rx_buf_use_size + 8;
+
+ ring_prod = prod = bp->rx_prod = 0;
+ bp->rx_cons = 0;
+ bp->rx_prod_bseq = 0;
+
+ rxbd = &bp->rx_desc_ring[0];
+ for (i = 0; i < MAX_RX_DESC_CNT; i++, rxbd++) {
+ rxbd->rx_bd_len = bp->rx_buf_use_size;
+ rxbd->rx_bd_flags = RX_BD_FLAGS_START | RX_BD_FLAGS_END;
+ }
+
+ rxbd->rx_bd_haddr_hi = (u64) bp->rx_desc_mapping >> 32;
+ rxbd->rx_bd_haddr_lo = (u64) bp->rx_desc_mapping & 0xffffffff;
+
+ val = BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE;
+ val |= BNX2_L2CTX_CTX_TYPE_SIZE_L2;
+ val |= 0x02 << 8;
+ CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_CTX_TYPE, val);
+
+ val = (u64) bp->rx_desc_mapping >> 32;
+ CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_NX_BDHADDR_HI, val);
+
+ val = (u64) bp->rx_desc_mapping & 0xffffffff;
+ CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_NX_BDHADDR_LO, val);
+
+ for ( ;ring_prod < bp->rx_ring_size; ) {
+ if (bnx2_alloc_rx_skb(bp, ring_prod) < 0) {
+ break;
+ }
+ prod = NEXT_RX_BD(prod);
+ ring_prod = RX_RING_IDX(prod);
+ }
+ bp->rx_prod = prod;
+
+ REG_WR16(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BDIDX, prod);
+
+ REG_WR(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BSEQ, bp->rx_prod_bseq);
+}
+
+static void
+bnx2_free_tx_skbs(struct bnx2 *bp)
+{
+ int i;
+
+ if (bp->tx_buf_ring == NULL)
+ return;
+
+ for (i = 0; i < TX_DESC_CNT; ) {
+ struct sw_bd *tx_buf = &bp->tx_buf_ring[i];
+ struct sk_buff *skb = tx_buf->skb;
+ int j, last;
+
+ if (skb == NULL) {
+ i++;
+ continue;
+ }
+
+ pci_unmap_single(bp->pdev, pci_unmap_addr(tx_buf, mapping),
+ skb_headlen(skb), PCI_DMA_TODEVICE);
+
+ tx_buf->skb = NULL;
+
+ last = skb_shinfo(skb)->nr_frags;
+ for (j = 0; j < last; j++) {
+ tx_buf = &bp->tx_buf_ring[i + j + 1];
+ pci_unmap_page(bp->pdev,
+ pci_unmap_addr(tx_buf, mapping),
+ skb_shinfo(skb)->frags[j].size,
+ PCI_DMA_TODEVICE);
+ }
+ dev_kfree_skb_any(skb);
+ i += j + 1;
+ }
+
+}
+
+static void
+bnx2_free_rx_skbs(struct bnx2 *bp)
+{
+ int i;
+
+ if (bp->rx_buf_ring == NULL)
+ return;
+
+ for (i = 0; i < RX_DESC_CNT; i++) {
+ struct sw_bd *rx_buf = &bp->rx_buf_ring[i];
+ struct sk_buff *skb = rx_buf->skb;
+
+ if (skb == 0)
+ continue;
+
+ pci_unmap_single(bp->pdev, pci_unmap_addr(rx_buf, mapping),
+ bp->rx_buf_use_size, PCI_DMA_FROMDEVICE);
+
+ rx_buf->skb = NULL;
+
+ dev_kfree_skb_any(skb);
+ }
+}
+
+static void
+bnx2_free_skbs(struct bnx2 *bp)
+{
+ bnx2_free_tx_skbs(bp);
+ bnx2_free_rx_skbs(bp);
+}
+
+static int
+bnx2_reset_nic(struct bnx2 *bp, u32 reset_code)
+{
+ int rc;
+
+ rc = bnx2_reset_chip(bp, reset_code);
+ bnx2_free_skbs(bp);
+ if (rc)
+ return rc;
+
+ bnx2_init_chip(bp);
+ bnx2_init_tx_ring(bp);
+ bnx2_init_rx_ring(bp);
+ return 0;
+}
+
+static int
+bnx2_init_nic(struct bnx2 *bp)
+{
+ int rc;
+
+ if ((rc = bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET)) != 0)
+ return rc;
+
+ bnx2_init_phy(bp);
+ bnx2_set_link(bp);
+ return 0;
+}
+
+static int
+bnx2_test_registers(struct bnx2 *bp)
+{
+ int ret;
+ int i;
+ static struct {
+ u16 offset;
+ u16 flags;
+ u32 rw_mask;
+ u32 ro_mask;
+ } reg_tbl[] = {
+ { 0x006c, 0, 0x00000000, 0x0000003f },
+ { 0x0090, 0, 0xffffffff, 0x00000000 },
+ { 0x0094, 0, 0x00000000, 0x00000000 },
+
+ { 0x0404, 0, 0x00003f00, 0x00000000 },
+ { 0x0418, 0, 0x00000000, 0xffffffff },
+ { 0x041c, 0, 0x00000000, 0xffffffff },
+ { 0x0420, 0, 0x00000000, 0x80ffffff },
+ { 0x0424, 0, 0x00000000, 0x00000000 },
+ { 0x0428, 0, 0x00000000, 0x00000001 },
+ { 0x0450, 0, 0x00000000, 0x0000ffff },
+ { 0x0454, 0, 0x00000000, 0xffffffff },
+ { 0x0458, 0, 0x00000000, 0xffffffff },
+
+ { 0x0808, 0, 0x00000000, 0xffffffff },
+ { 0x0854, 0, 0x00000000, 0xffffffff },
+ { 0x0868, 0, 0x00000000, 0x77777777 },
+ { 0x086c, 0, 0x00000000, 0x77777777 },
+ { 0x0870, 0, 0x00000000, 0x77777777 },
+ { 0x0874, 0, 0x00000000, 0x77777777 },
+
+ { 0x0c00, 0, 0x00000000, 0x00000001 },
+ { 0x0c04, 0, 0x00000000, 0x03ff0001 },
+ { 0x0c08, 0, 0x0f0ff073, 0x00000000 },
+ { 0x0c0c, 0, 0x00ffffff, 0x00000000 },
+ { 0x0c30, 0, 0x00000000, 0xffffffff },
+ { 0x0c34, 0, 0x00000000, 0xffffffff },
+ { 0x0c38, 0, 0x00000000, 0xffffffff },
+ { 0x0c3c, 0, 0x00000000, 0xffffffff },
+ { 0x0c40, 0, 0x00000000, 0xffffffff },
+ { 0x0c44, 0, 0x00000000, 0xffffffff },
+ { 0x0c48, 0, 0x00000000, 0x0007ffff },
+ { 0x0c4c, 0, 0x00000000, 0xffffffff },
+ { 0x0c50, 0, 0x00000000, 0xffffffff },
+ { 0x0c54, 0, 0x00000000, 0xffffffff },
+ { 0x0c58, 0, 0x00000000, 0xffffffff },
+ { 0x0c5c, 0, 0x00000000, 0xffffffff },
+ { 0x0c60, 0, 0x00000000, 0xffffffff },
+ { 0x0c64, 0, 0x00000000, 0xffffffff },
+ { 0x0c68, 0, 0x00000000, 0xffffffff },
+ { 0x0c6c, 0, 0x00000000, 0xffffffff },
+ { 0x0c70, 0, 0x00000000, 0xffffffff },
+ { 0x0c74, 0, 0x00000000, 0xffffffff },
+ { 0x0c78, 0, 0x00000000, 0xffffffff },
+ { 0x0c7c, 0, 0x00000000, 0xffffffff },
+ { 0x0c80, 0, 0x00000000, 0xffffffff },
+ { 0x0c84, 0, 0x00000000, 0xffffffff },
+ { 0x0c88, 0, 0x00000000, 0xffffffff },
+ { 0x0c8c, 0, 0x00000000, 0xffffffff },
+ { 0x0c90, 0, 0x00000000, 0xffffffff },
+ { 0x0c94, 0, 0x00000000, 0xffffffff },
+ { 0x0c98, 0, 0x00000000, 0xffffffff },
+ { 0x0c9c, 0, 0x00000000, 0xffffffff },
+ { 0x0ca0, 0, 0x00000000, 0xffffffff },
+ { 0x0ca4, 0, 0x00000000, 0xffffffff },
+ { 0x0ca8, 0, 0x00000000, 0x0007ffff },
+ { 0x0cac, 0, 0x00000000, 0xffffffff },
+ { 0x0cb0, 0, 0x00000000, 0xffffffff },
+ { 0x0cb4, 0, 0x00000000, 0xffffffff },
+ { 0x0cb8, 0, 0x00000000, 0xffffffff },
+ { 0x0cbc, 0, 0x00000000, 0xffffffff },
+ { 0x0cc0, 0, 0x00000000, 0xffffffff },
+ { 0x0cc4, 0, 0x00000000, 0xffffffff },
+ { 0x0cc8, 0, 0x00000000, 0xffffffff },
+ { 0x0ccc, 0, 0x00000000, 0xffffffff },
+ { 0x0cd0, 0, 0x00000000, 0xffffffff },
+ { 0x0cd4, 0, 0x00000000, 0xffffffff },
+ { 0x0cd8, 0, 0x00000000, 0xffffffff },
+ { 0x0cdc, 0, 0x00000000, 0xffffffff },
+ { 0x0ce0, 0, 0x00000000, 0xffffffff },
+ { 0x0ce4, 0, 0x00000000, 0xffffffff },
+ { 0x0ce8, 0, 0x00000000, 0xffffffff },
+ { 0x0cec, 0, 0x00000000, 0xffffffff },
+ { 0x0cf0, 0, 0x00000000, 0xffffffff },
+ { 0x0cf4, 0, 0x00000000, 0xffffffff },
+ { 0x0cf8, 0, 0x00000000, 0xffffffff },
+ { 0x0cfc, 0, 0x00000000, 0xffffffff },
+ { 0x0d00, 0, 0x00000000, 0xffffffff },
+ { 0x0d04, 0, 0x00000000, 0xffffffff },
+
+ { 0x1000, 0, 0x00000000, 0x00000001 },
+ { 0x1004, 0, 0x00000000, 0x000f0001 },
+ { 0x1044, 0, 0x00000000, 0xffc003ff },
+ { 0x1080, 0, 0x00000000, 0x0001ffff },
+ { 0x1084, 0, 0x00000000, 0xffffffff },
+ { 0x1088, 0, 0x00000000, 0xffffffff },
+ { 0x108c, 0, 0x00000000, 0xffffffff },
+ { 0x1090, 0, 0x00000000, 0xffffffff },
+ { 0x1094, 0, 0x00000000, 0xffffffff },
+ { 0x1098, 0, 0x00000000, 0xffffffff },
+ { 0x109c, 0, 0x00000000, 0xffffffff },
+ { 0x10a0, 0, 0x00000000, 0xffffffff },
+
+ { 0x1408, 0, 0x01c00800, 0x00000000 },
+ { 0x149c, 0, 0x8000ffff, 0x00000000 },
+ { 0x14a8, 0, 0x00000000, 0x000001ff },
+ { 0x14ac, 0, 0x4fffffff, 0x10000000 },
+ { 0x14b0, 0, 0x00000002, 0x00000001 },
+ { 0x14b8, 0, 0x00000000, 0x00000000 },
+ { 0x14c0, 0, 0x00000000, 0x00000009 },
+ { 0x14c4, 0, 0x00003fff, 0x00000000 },
+ { 0x14cc, 0, 0x00000000, 0x00000001 },
+ { 0x14d0, 0, 0xffffffff, 0x00000000 },
+ { 0x1500, 0, 0x00000000, 0xffffffff },
+ { 0x1504, 0, 0x00000000, 0xffffffff },
+ { 0x1508, 0, 0x00000000, 0xffffffff },
+ { 0x150c, 0, 0x00000000, 0xffffffff },
+ { 0x1510, 0, 0x00000000, 0xffffffff },
+ { 0x1514, 0, 0x00000000, 0xffffffff },
+ { 0x1518, 0, 0x00000000, 0xffffffff },
+ { 0x151c, 0, 0x00000000, 0xffffffff },
+ { 0x1520, 0, 0x00000000, 0xffffffff },
+ { 0x1524, 0, 0x00000000, 0xffffffff },
+ { 0x1528, 0, 0x00000000, 0xffffffff },
+ { 0x152c, 0, 0x00000000, 0xffffffff },
+ { 0x1530, 0, 0x00000000, 0xffffffff },
+ { 0x1534, 0, 0x00000000, 0xffffffff },
+ { 0x1538, 0, 0x00000000, 0xffffffff },
+ { 0x153c, 0, 0x00000000, 0xffffffff },
+ { 0x1540, 0, 0x00000000, 0xffffffff },
+ { 0x1544, 0, 0x00000000, 0xffffffff },
+ { 0x1548, 0, 0x00000000, 0xffffffff },
+ { 0x154c, 0, 0x00000000, 0xffffffff },
+ { 0x1550, 0, 0x00000000, 0xffffffff },
+ { 0x1554, 0, 0x00000000, 0xffffffff },
+ { 0x1558, 0, 0x00000000, 0xffffffff },
+ { 0x1600, 0, 0x00000000, 0xffffffff },
+ { 0x1604, 0, 0x00000000, 0xffffffff },
+ { 0x1608, 0, 0x00000000, 0xffffffff },
+ { 0x160c, 0, 0x00000000, 0xffffffff },
+ { 0x1610, 0, 0x00000000, 0xffffffff },
+ { 0x1614, 0, 0x00000000, 0xffffffff },
+ { 0x1618, 0, 0x00000000, 0xffffffff },
+ { 0x161c, 0, 0x00000000, 0xffffffff },
+ { 0x1620, 0, 0x00000000, 0xffffffff },
+ { 0x1624, 0, 0x00000000, 0xffffffff },
+ { 0x1628, 0, 0x00000000, 0xffffffff },
+ { 0x162c, 0, 0x00000000, 0xffffffff },
+ { 0x1630, 0, 0x00000000, 0xffffffff },
+ { 0x1634, 0, 0x00000000, 0xffffffff },
+ { 0x1638, 0, 0x00000000, 0xffffffff },
+ { 0x163c, 0, 0x00000000, 0xffffffff },
+ { 0x1640, 0, 0x00000000, 0xffffffff },
+ { 0x1644, 0, 0x00000000, 0xffffffff },
+ { 0x1648, 0, 0x00000000, 0xffffffff },
+ { 0x164c, 0, 0x00000000, 0xffffffff },
+ { 0x1650, 0, 0x00000000, 0xffffffff },
+ { 0x1654, 0, 0x00000000, 0xffffffff },
+
+ { 0x1800, 0, 0x00000000, 0x00000001 },
+ { 0x1804, 0, 0x00000000, 0x00000003 },
+ { 0x1840, 0, 0x00000000, 0xffffffff },
+ { 0x1844, 0, 0x00000000, 0xffffffff },
+ { 0x1848, 0, 0x00000000, 0xffffffff },
+ { 0x184c, 0, 0x00000000, 0xffffffff },
+ { 0x1850, 0, 0x00000000, 0xffffffff },
+ { 0x1900, 0, 0x7ffbffff, 0x00000000 },
+ { 0x1904, 0, 0xffffffff, 0x00000000 },
+ { 0x190c, 0, 0xffffffff, 0x00000000 },
+ { 0x1914, 0, 0xffffffff, 0x00000000 },
+ { 0x191c, 0, 0xffffffff, 0x00000000 },
+ { 0x1924, 0, 0xffffffff, 0x00000000 },
+ { 0x192c, 0, 0xffffffff, 0x00000000 },
+ { 0x1934, 0, 0xffffffff, 0x00000000 },
+ { 0x193c, 0, 0xffffffff, 0x00000000 },
+ { 0x1944, 0, 0xffffffff, 0x00000000 },
+ { 0x194c, 0, 0xffffffff, 0x00000000 },
+ { 0x1954, 0, 0xffffffff, 0x00000000 },
+ { 0x195c, 0, 0xffffffff, 0x00000000 },
+ { 0x1964, 0, 0xffffffff, 0x00000000 },
+ { 0x196c, 0, 0xffffffff, 0x00000000 },
+ { 0x1974, 0, 0xffffffff, 0x00000000 },
+ { 0x197c, 0, 0xffffffff, 0x00000000 },
+ { 0x1980, 0, 0x0700ffff, 0x00000000 },
+
+ { 0x1c00, 0, 0x00000000, 0x00000001 },
+ { 0x1c04, 0, 0x00000000, 0x00000003 },
+ { 0x1c08, 0, 0x0000000f, 0x00000000 },
+ { 0x1c40, 0, 0x00000000, 0xffffffff },
+ { 0x1c44, 0, 0x00000000, 0xffffffff },
+ { 0x1c48, 0, 0x00000000, 0xffffffff },
+ { 0x1c4c, 0, 0x00000000, 0xffffffff },
+ { 0x1c50, 0, 0x00000000, 0xffffffff },
+ { 0x1d00, 0, 0x7ffbffff, 0x00000000 },
+ { 0x1d04, 0, 0xffffffff, 0x00000000 },
+ { 0x1d0c, 0, 0xffffffff, 0x00000000 },
+ { 0x1d14, 0, 0xffffffff, 0x00000000 },
+ { 0x1d1c, 0, 0xffffffff, 0x00000000 },
+ { 0x1d24, 0, 0xffffffff, 0x00000000 },
+ { 0x1d2c, 0, 0xffffffff, 0x00000000 },
+ { 0x1d34, 0, 0xffffffff, 0x00000000 },
+ { 0x1d3c, 0, 0xffffffff, 0x00000000 },
+ { 0x1d44, 0, 0xffffffff, 0x00000000 },
+ { 0x1d4c, 0, 0xffffffff, 0x00000000 },
+ { 0x1d54, 0, 0xffffffff, 0x00000000 },
+ { 0x1d5c, 0, 0xffffffff, 0x00000000 },
+ { 0x1d64, 0, 0xffffffff, 0x00000000 },
+ { 0x1d6c, 0, 0xffffffff, 0x00000000 },
+ { 0x1d74, 0, 0xffffffff, 0x00000000 },
+ { 0x1d7c, 0, 0xffffffff, 0x00000000 },
+ { 0x1d80, 0, 0x0700ffff, 0x00000000 },
+
+ { 0x2004, 0, 0x00000000, 0x0337000f },
+ { 0x2008, 0, 0xffffffff, 0x00000000 },
+ { 0x200c, 0, 0xffffffff, 0x00000000 },
+ { 0x2010, 0, 0xffffffff, 0x00000000 },
+ { 0x2014, 0, 0x801fff80, 0x00000000 },
+ { 0x2018, 0, 0x000003ff, 0x00000000 },
+
+ { 0x2800, 0, 0x00000000, 0x00000001 },
+ { 0x2804, 0, 0x00000000, 0x00003f01 },
+ { 0x2808, 0, 0x0f3f3f03, 0x00000000 },
+ { 0x2810, 0, 0xffff0000, 0x00000000 },
+ { 0x2814, 0, 0xffff0000, 0x00000000 },
+ { 0x2818, 0, 0xffff0000, 0x00000000 },
+ { 0x281c, 0, 0xffff0000, 0x00000000 },
+ { 0x2834, 0, 0xffffffff, 0x00000000 },
+ { 0x2840, 0, 0x00000000, 0xffffffff },
+ { 0x2844, 0, 0x00000000, 0xffffffff },
+ { 0x2848, 0, 0xffffffff, 0x00000000 },
+ { 0x284c, 0, 0xf800f800, 0x07ff07ff },
+
+ { 0x2c00, 0, 0x00000000, 0x00000011 },
+ { 0x2c04, 0, 0x00000000, 0x00030007 },
+
+ { 0x3000, 0, 0x00000000, 0x00000001 },
+ { 0x3004, 0, 0x00000000, 0x007007ff },
+ { 0x3008, 0, 0x00000003, 0x00000000 },
+ { 0x300c, 0, 0xffffffff, 0x00000000 },
+ { 0x3010, 0, 0xffffffff, 0x00000000 },
+ { 0x3014, 0, 0xffffffff, 0x00000000 },
+ { 0x3034, 0, 0xffffffff, 0x00000000 },
+ { 0x3038, 0, 0xffffffff, 0x00000000 },
+ { 0x3050, 0, 0x00000001, 0x00000000 },
+
+ { 0x3c00, 0, 0x00000000, 0x00000001 },
+ { 0x3c04, 0, 0x00000000, 0x00070000 },
+ { 0x3c08, 0, 0x00007f71, 0x07f00000 },
+ { 0x3c0c, 0, 0x1f3ffffc, 0x00000000 },
+ { 0x3c10, 0, 0xffffffff, 0x00000000 },
+ { 0x3c14, 0, 0x00000000, 0xffffffff },
+ { 0x3c18, 0, 0x00000000, 0xffffffff },
+ { 0x3c1c, 0, 0xfffff000, 0x00000000 },
+ { 0x3c20, 0, 0xffffff00, 0x00000000 },
+ { 0x3c24, 0, 0xffffffff, 0x00000000 },
+ { 0x3c28, 0, 0xffffffff, 0x00000000 },
+ { 0x3c2c, 0, 0xffffffff, 0x00000000 },
+ { 0x3c30, 0, 0xffffffff, 0x00000000 },
+ { 0x3c34, 0, 0xffffffff, 0x00000000 },
+ { 0x3c38, 0, 0xffffffff, 0x00000000 },
+ { 0x3c3c, 0, 0xffffffff, 0x00000000 },
+ { 0x3c40, 0, 0xffffffff, 0x00000000 },
+ { 0x3c44, 0, 0xffffffff, 0x00000000 },
+ { 0x3c48, 0, 0xffffffff, 0x00000000 },
+ { 0x3c4c, 0, 0xffffffff, 0x00000000 },
+ { 0x3c50, 0, 0xffffffff, 0x00000000 },
+ { 0x3c54, 0, 0xffffffff, 0x00000000 },
+ { 0x3c58, 0, 0xffffffff, 0x00000000 },
+ { 0x3c5c, 0, 0xffffffff, 0x00000000 },
+ { 0x3c60, 0, 0xffffffff, 0x00000000 },
+ { 0x3c64, 0, 0xffffffff, 0x00000000 },
+ { 0x3c68, 0, 0xffffffff, 0x00000000 },
+ { 0x3c6c, 0, 0xffffffff, 0x00000000 },
+ { 0x3c70, 0, 0xffffffff, 0x00000000 },
+ { 0x3c74, 0, 0x0000003f, 0x00000000 },
+ { 0x3c78, 0, 0x00000000, 0x00000000 },
+ { 0x3c7c, 0, 0x00000000, 0x00000000 },
+ { 0x3c80, 0, 0x3fffffff, 0x00000000 },
+ { 0x3c84, 0, 0x0000003f, 0x00000000 },
+ { 0x3c88, 0, 0x00000000, 0xffffffff },
+ { 0x3c8c, 0, 0x00000000, 0xffffffff },
+
+ { 0x4000, 0, 0x00000000, 0x00000001 },
+ { 0x4004, 0, 0x00000000, 0x00030000 },
+ { 0x4008, 0, 0x00000ff0, 0x00000000 },
+ { 0x400c, 0, 0xffffffff, 0x00000000 },
+ { 0x4088, 0, 0x00000000, 0x00070303 },
+
+ { 0x4400, 0, 0x00000000, 0x00000001 },
+ { 0x4404, 0, 0x00000000, 0x00003f01 },
+ { 0x4408, 0, 0x7fff00ff, 0x00000000 },
+ { 0x440c, 0, 0xffffffff, 0x00000000 },
+ { 0x4410, 0, 0xffff, 0x0000 },
+ { 0x4414, 0, 0xffff, 0x0000 },
+ { 0x4418, 0, 0xffff, 0x0000 },
+ { 0x441c, 0, 0xffff, 0x0000 },
+ { 0x4428, 0, 0xffffffff, 0x00000000 },
+ { 0x442c, 0, 0xffffffff, 0x00000000 },
+ { 0x4430, 0, 0xffffffff, 0x00000000 },
+ { 0x4434, 0, 0xffffffff, 0x00000000 },
+ { 0x4438, 0, 0xffffffff, 0x00000000 },
+ { 0x443c, 0, 0xffffffff, 0x00000000 },
+ { 0x4440, 0, 0xffffffff, 0x00000000 },
+ { 0x4444, 0, 0xffffffff, 0x00000000 },
+
+ { 0x4c00, 0, 0x00000000, 0x00000001 },
+ { 0x4c04, 0, 0x00000000, 0x0000003f },
+ { 0x4c08, 0, 0xffffffff, 0x00000000 },
+ { 0x4c0c, 0, 0x0007fc00, 0x00000000 },
+ { 0x4c10, 0, 0x80003fe0, 0x00000000 },
+ { 0x4c14, 0, 0xffffffff, 0x00000000 },
+ { 0x4c44, 0, 0x00000000, 0x9fff9fff },
+ { 0x4c48, 0, 0x00000000, 0xb3009fff },
+ { 0x4c4c, 0, 0x00000000, 0x77f33b30 },
+ { 0x4c50, 0, 0x00000000, 0xffffffff },
+
+ { 0x5004, 0, 0x00000000, 0x0000007f },
+ { 0x5008, 0, 0x0f0007ff, 0x00000000 },
+ { 0x500c, 0, 0xf800f800, 0x07ff07ff },
+
+ { 0x5400, 0, 0x00000008, 0x00000001 },
+ { 0x5404, 0, 0x00000000, 0x0000003f },
+ { 0x5408, 0, 0x0000001f, 0x00000000 },
+ { 0x540c, 0, 0xffffffff, 0x00000000 },
+ { 0x5410, 0, 0xffffffff, 0x00000000 },
+ { 0x5414, 0, 0x0000ffff, 0x00000000 },
+ { 0x5418, 0, 0x0000ffff, 0x00000000 },
+ { 0x541c, 0, 0x0000ffff, 0x00000000 },
+ { 0x5420, 0, 0x0000ffff, 0x00000000 },
+ { 0x5428, 0, 0x000000ff, 0x00000000 },
+ { 0x542c, 0, 0xff00ffff, 0x00000000 },
+ { 0x5430, 0, 0x001fff80, 0x00000000 },
+ { 0x5438, 0, 0xffffffff, 0x00000000 },
+ { 0x543c, 0, 0xffffffff, 0x00000000 },
+ { 0x5440, 0, 0xf800f800, 0x07ff07ff },
+
+ { 0x5c00, 0, 0x00000000, 0x00000001 },
+ { 0x5c04, 0, 0x00000000, 0x0003000f },
+ { 0x5c08, 0, 0x00000003, 0x00000000 },
+ { 0x5c0c, 0, 0x0000fff8, 0x00000000 },
+ { 0x5c10, 0, 0x00000000, 0xffffffff },
+ { 0x5c80, 0, 0x00000000, 0x0f7113f1 },
+ { 0x5c84, 0, 0x00000000, 0x0000f333 },
+ { 0x5c88, 0, 0x00000000, 0x00077373 },
+ { 0x5c8c, 0, 0x00000000, 0x0007f737 },
+
+ { 0x6808, 0, 0x0000ff7f, 0x00000000 },
+ { 0x680c, 0, 0xffffffff, 0x00000000 },
+ { 0x6810, 0, 0xffffffff, 0x00000000 },
+ { 0x6814, 0, 0xffffffff, 0x00000000 },
+ { 0x6818, 0, 0xffffffff, 0x00000000 },
+ { 0x681c, 0, 0xffffffff, 0x00000000 },
+ { 0x6820, 0, 0x00ff00ff, 0x00000000 },
+ { 0x6824, 0, 0x00ff00ff, 0x00000000 },
+ { 0x6828, 0, 0x00ff00ff, 0x00000000 },
+ { 0x682c, 0, 0x03ff03ff, 0x00000000 },
+ { 0x6830, 0, 0x03ff03ff, 0x00000000 },
+ { 0x6834, 0, 0x03ff03ff, 0x00000000 },
+ { 0x6838, 0, 0x03ff03ff, 0x00000000 },
+ { 0x683c, 0, 0x0000ffff, 0x00000000 },
+ { 0x6840, 0, 0x00000ff0, 0x00000000 },
+ { 0x6844, 0, 0x00ffff00, 0x00000000 },
+ { 0x684c, 0, 0xffffffff, 0x00000000 },
+ { 0x6850, 0, 0x7f7f7f7f, 0x00000000 },
+ { 0x6854, 0, 0x7f7f7f7f, 0x00000000 },
+ { 0x6858, 0, 0x7f7f7f7f, 0x00000000 },
+ { 0x685c, 0, 0x7f7f7f7f, 0x00000000 },
+ { 0x6908, 0, 0x00000000, 0x0001ff0f },
+ { 0x690c, 0, 0x00000000, 0x0ffe00f0 },
+
+ { 0xffff, 0, 0x00000000, 0x00000000 },
+ };
+
+ ret = 0;
+ for (i = 0; reg_tbl[i].offset != 0xffff; i++) {
+ u32 offset, rw_mask, ro_mask, save_val, val;
+
+ offset = (u32) reg_tbl[i].offset;
+ rw_mask = reg_tbl[i].rw_mask;
+ ro_mask = reg_tbl[i].ro_mask;
+
+ save_val = readl((u8 *) bp->regview + offset);
+
+ writel(0, (u8 *) bp->regview + offset);
+
+ val = readl((u8 *) bp->regview + offset);
+ if ((val & rw_mask) != 0) {
+ goto reg_test_err;
+ }
+
+ if ((val & ro_mask) != (save_val & ro_mask)) {
+ goto reg_test_err;
+ }
+
+ writel(0xffffffff, (u8 *) bp->regview + offset);
+
+ val = readl((u8 *) bp->regview + offset);
+ if ((val & rw_mask) != rw_mask) {
+ goto reg_test_err;
+ }
+
+ if ((val & ro_mask) != (save_val & ro_mask)) {
+ goto reg_test_err;
+ }
+
+ writel(save_val, (u8 *) bp->regview + offset);
+ continue;
+
+reg_test_err:
+ writel(save_val, (u8 *) bp->regview + offset);
+ ret = -ENODEV;
+ break;
+ }
+ return ret;
+}
+
+static int
+bnx2_do_mem_test(struct bnx2 *bp, u32 start, u32 size)
+{
+ static u32 test_pattern[] = { 0x00000000, 0xffffffff, 0x55555555,
+ 0xaaaaaaaa , 0xaa55aa55, 0x55aa55aa };
+ int i;
+
+ for (i = 0; i < sizeof(test_pattern) / 4; i++) {
+ u32 offset;
+
+ for (offset = 0; offset < size; offset += 4) {
+
+ REG_WR_IND(bp, start + offset, test_pattern[i]);
+
+ if (REG_RD_IND(bp, start + offset) !=
+ test_pattern[i]) {
+ return -ENODEV;
+ }
+ }
+ }
+ return 0;
+}
+
+static int
+bnx2_test_memory(struct bnx2 *bp)
+{
+ int ret = 0;
+ int i;
+ static struct {
+ u32 offset;
+ u32 len;
+ } mem_tbl[] = {
+ { 0x60000, 0x4000 },
+ { 0xa0000, 0x4000 },
+ { 0xe0000, 0x4000 },
+ { 0x120000, 0x4000 },
+ { 0x1a0000, 0x4000 },
+ { 0x160000, 0x4000 },
+ { 0xffffffff, 0 },
+ };
+
+ for (i = 0; mem_tbl[i].offset != 0xffffffff; i++) {
+ if ((ret = bnx2_do_mem_test(bp, mem_tbl[i].offset,
+ mem_tbl[i].len)) != 0) {
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+static int
+bnx2_test_loopback(struct bnx2 *bp)
+{
+ unsigned int pkt_size, num_pkts, i;
+ struct sk_buff *skb, *rx_skb;
+ unsigned char *packet;
+ u16 rx_start_idx, rx_idx, send_idx;
+ u32 send_bseq, val;
+ dma_addr_t map;
+ struct tx_bd *txbd;
+ struct sw_bd *rx_buf;
+ struct l2_fhdr *rx_hdr;
+ int ret = -ENODEV;
+
+ if (!netif_running(bp->dev))
+ return -ENODEV;
+
+ bp->loopback = MAC_LOOPBACK;
+ bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_DIAG);
+ bnx2_set_mac_loopback(bp);
+
+ pkt_size = 1514;
+ skb = dev_alloc_skb(pkt_size);
+ packet = skb_put(skb, pkt_size);
+ memcpy(packet, bp->mac_addr, 6);
+ memset(packet + 6, 0x0, 8);
+ for (i = 14; i < pkt_size; i++)
+ packet[i] = (unsigned char) (i & 0xff);
+
+ map = pci_map_single(bp->pdev, skb->data, pkt_size,
+ PCI_DMA_TODEVICE);
+
+ val = REG_RD(bp, BNX2_HC_COMMAND);
+ REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+ REG_RD(bp, BNX2_HC_COMMAND);
+
+ udelay(5);
+ rx_start_idx = bp->status_blk->status_rx_quick_consumer_index0;
+
+ send_idx = 0;
+ send_bseq = 0;
+ num_pkts = 0;
+
+ txbd = &bp->tx_desc_ring[send_idx];
+
+ txbd->tx_bd_haddr_hi = (u64) map >> 32;
+ txbd->tx_bd_haddr_lo = (u64) map & 0xffffffff;
+ txbd->tx_bd_mss_nbytes = pkt_size;
+ txbd->tx_bd_vlan_tag_flags = TX_BD_FLAGS_START | TX_BD_FLAGS_END;
+
+ num_pkts++;
+ send_idx = NEXT_TX_BD(send_idx);
+
+ send_bseq += pkt_size;
+
+ REG_WR16(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BIDX, send_idx);
+ REG_WR(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BSEQ, send_bseq);
+
+
+ udelay(100);
+
+ val = REG_RD(bp, BNX2_HC_COMMAND);
+ REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+ REG_RD(bp, BNX2_HC_COMMAND);
+
+ udelay(5);
+
+ pci_unmap_single(bp->pdev, map, pkt_size, PCI_DMA_TODEVICE);
+ dev_kfree_skb_irq(skb);
+
+ if (bp->status_blk->status_tx_quick_consumer_index0 != send_idx) {
+ goto loopback_test_done;
+ }
+
+ rx_idx = bp->status_blk->status_rx_quick_consumer_index0;
+ if (rx_idx != rx_start_idx + num_pkts) {
+ goto loopback_test_done;
+ }
+
+ rx_buf = &bp->rx_buf_ring[rx_start_idx];
+ rx_skb = rx_buf->skb;
+
+ rx_hdr = (struct l2_fhdr *) rx_skb->data;
+ skb_reserve(rx_skb, bp->rx_offset);
+
+ pci_dma_sync_single_for_cpu(bp->pdev,
+ pci_unmap_addr(rx_buf, mapping),
+ bp->rx_buf_size, PCI_DMA_FROMDEVICE);
+
+ if (rx_hdr->l2_fhdr_errors &
+ (L2_FHDR_ERRORS_BAD_CRC |
+ L2_FHDR_ERRORS_PHY_DECODE |
+ L2_FHDR_ERRORS_ALIGNMENT |
+ L2_FHDR_ERRORS_TOO_SHORT |
+ L2_FHDR_ERRORS_GIANT_FRAME)) {
+
+ goto loopback_test_done;
+ }
+
+ if ((rx_hdr->l2_fhdr_pkt_len - 4) != pkt_size) {
+ goto loopback_test_done;
+ }
+
+ for (i = 14; i < pkt_size; i++) {
+ if (*(rx_skb->data + i) != (unsigned char) (i & 0xff)) {
+ goto loopback_test_done;
+ }
+ }
+
+ ret = 0;
+
+loopback_test_done:
+ bp->loopback = 0;
+ return ret;
+}
+
+#define NVRAM_SIZE 0x200
+#define CRC32_RESIDUAL 0xdebb20e3
+
+static int
+bnx2_test_nvram(struct bnx2 *bp)
+{
+ u32 buf[NVRAM_SIZE / 4];
+ u8 *data = (u8 *) buf;
+ int rc = 0;
+ u32 magic, csum;
+
+ if ((rc = bnx2_nvram_read(bp, 0, data, 4)) != 0)
+ goto test_nvram_done;
+
+ magic = be32_to_cpu(buf[0]);
+ if (magic != 0x669955aa) {
+ rc = -ENODEV;
+ goto test_nvram_done;
+ }
+
+ if ((rc = bnx2_nvram_read(bp, 0x100, data, NVRAM_SIZE)) != 0)
+ goto test_nvram_done;
+
+ csum = ether_crc_le(0x100, data);
+ if (csum != CRC32_RESIDUAL) {
+ rc = -ENODEV;
+ goto test_nvram_done;
+ }
+
+ csum = ether_crc_le(0x100, data + 0x100);
+ if (csum != CRC32_RESIDUAL) {
+ rc = -ENODEV;
+ }
+
+test_nvram_done:
+ return rc;
+}
+
+static int
+bnx2_test_link(struct bnx2 *bp)
+{
+ u32 bmsr;
+
+ spin_lock_irq(&bp->phy_lock);
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+ bnx2_read_phy(bp, MII_BMSR, &bmsr);
+ spin_unlock_irq(&bp->phy_lock);
+
+ if (bmsr & BMSR_LSTATUS) {
+ return 0;
+ }
+ return -ENODEV;
+}
+
+static int
+bnx2_test_intr(struct bnx2 *bp)
+{
+ int i;
+ u32 val;
+ u16 status_idx;
+
+ if (!netif_running(bp->dev))
+ return -ENODEV;
+
+ status_idx = REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff;
+
+ /* This register is not touched during run-time. */
+ val = REG_RD(bp, BNX2_HC_COMMAND);
+ REG_WR(bp, BNX2_HC_COMMAND, val | BNX2_HC_COMMAND_COAL_NOW);
+ REG_RD(bp, BNX2_HC_COMMAND);
+
+ for (i = 0; i < 10; i++) {
+ if ((REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff) !=
+ status_idx) {
+
+ break;
+ }
+
+ msleep_interruptible(10);
+ }
+ if (i < 10)
+ return 0;
+
+ return -ENODEV;
+}
+
+static void
+bnx2_timer(unsigned long data)
+{
+ struct bnx2 *bp = (struct bnx2 *) data;
+ u32 msg;
+
+ if (atomic_read(&bp->intr_sem) != 0)
+ goto bnx2_restart_timer;
+
+ msg = (u32) ++bp->fw_drv_pulse_wr_seq;
+ REG_WR_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_DRV_PULSE_MB, msg);
+
+ if ((bp->phy_flags & PHY_SERDES_FLAG) &&
+ (CHIP_NUM(bp) == CHIP_NUM_5706)) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&bp->phy_lock, flags);
+ if (bp->serdes_an_pending) {
+ bp->serdes_an_pending--;
+ }
+ else if ((bp->link_up == 0) && (bp->autoneg & AUTONEG_SPEED)) {
+ u32 bmcr;
+
+ bnx2_read_phy(bp, MII_BMCR, &bmcr);
+
+ if (bmcr & BMCR_ANENABLE) {
+ u32 phy1, phy2;
+
+ bnx2_write_phy(bp, 0x1c, 0x7c00);
+ bnx2_read_phy(bp, 0x1c, &phy1);
+
+ bnx2_write_phy(bp, 0x17, 0x0f01);
+ bnx2_read_phy(bp, 0x15, &phy2);
+ bnx2_write_phy(bp, 0x17, 0x0f01);
+ bnx2_read_phy(bp, 0x15, &phy2);
+
+ if ((phy1 & 0x10) && /* SIGNAL DETECT */
+ !(phy2 & 0x20)) { /* no CONFIG */
+
+ bmcr &= ~BMCR_ANENABLE;
+ bmcr |= BMCR_SPEED1000 |
+ BMCR_FULLDPLX;
+ bnx2_write_phy(bp, MII_BMCR, bmcr);
+ bp->phy_flags |=
+ PHY_PARALLEL_DETECT_FLAG;
+ }
+ }
+ }
+ else if ((bp->link_up) && (bp->autoneg & AUTONEG_SPEED) &&
+ (bp->phy_flags & PHY_PARALLEL_DETECT_FLAG)) {
+ u32 phy2;
+
+ bnx2_write_phy(bp, 0x17, 0x0f01);
+ bnx2_read_phy(bp, 0x15, &phy2);
+ if (phy2 & 0x20) {
+ u32 bmcr;
+
+ bnx2_read_phy(bp, MII_BMCR, &bmcr);
+ bmcr |= BMCR_ANENABLE;
+ bnx2_write_phy(bp, MII_BMCR, bmcr);
+
+ bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG;
+
+ }
+ }
+
+ spin_unlock_irqrestore(&bp->phy_lock, flags);
+ }
+
+bnx2_restart_timer:
+ bp->timer.expires = RUN_AT(bp->timer_interval);
+
+ add_timer(&bp->timer);
+}
+
+/* Called with rtnl_lock */
+static int
+bnx2_open(struct net_device *dev)
+{
+ struct bnx2 *bp = dev->priv;
+ int rc;
+
+ bnx2_set_power_state(bp, 0);
+ bnx2_disable_int(bp);
+
+ rc = bnx2_alloc_mem(bp);
+ if (rc)
+ return rc;
+
+ if ((CHIP_ID(bp) != CHIP_ID_5706_A0) &&
+ (CHIP_ID(bp) != CHIP_ID_5706_A1) &&
+ !disable_msi) {
+
+ if (pci_enable_msi(bp->pdev) == 0) {
+ bp->flags |= USING_MSI_FLAG;
+ rc = request_irq(bp->pdev->irq, bnx2_msi, 0, dev->name,
+ dev);
+ }
+ else {
+ rc = request_irq(bp->pdev->irq, bnx2_interrupt,
+ SA_SHIRQ, dev->name, dev);
+ }
+ }
+ else {
+ rc = request_irq(bp->pdev->irq, bnx2_interrupt, SA_SHIRQ,
+ dev->name, dev);
+ }
+ if (rc) {
+ bnx2_free_mem(bp);
+ return rc;
+ }
+
+ rc = bnx2_init_nic(bp);
+
+ if (rc) {
+ free_irq(bp->pdev->irq, dev);
+ if (bp->flags & USING_MSI_FLAG) {
+ pci_disable_msi(bp->pdev);
+ bp->flags &= ~USING_MSI_FLAG;
+ }
+ bnx2_free_skbs(bp);
+ bnx2_free_mem(bp);
+ return rc;
+ }
+
+ init_timer(&bp->timer);
+
+ bp->timer.expires = RUN_AT(bp->timer_interval);
+ bp->timer.data = (unsigned long) bp;
+ bp->timer.function = bnx2_timer;
+ add_timer(&bp->timer);
+
+ atomic_set(&bp->intr_sem, 0);
+
+ bnx2_enable_int(bp);
+
+ if (bp->flags & USING_MSI_FLAG) {
+ /* Test MSI to make sure it is working
+ * If MSI test fails, go back to INTx mode
+ */
+ if (bnx2_test_intr(bp) != 0) {
+ printk(KERN_WARNING PFX "%s: No interrupt was generated"
+ " using MSI, switching to INTx mode. Please"
+ " report this failure to the PCI maintainer"
+ " and include system chipset information.\n",
+ bp->dev->name);
+
+ bnx2_disable_int(bp);
+ free_irq(bp->pdev->irq, dev);
+ pci_disable_msi(bp->pdev);
+ bp->flags &= ~USING_MSI_FLAG;
+
+ rc = bnx2_init_nic(bp);
+
+ if (!rc) {
+ rc = request_irq(bp->pdev->irq, bnx2_interrupt,
+ SA_SHIRQ, dev->name, dev);
+ }
+ if (rc) {
+ bnx2_free_skbs(bp);
+ bnx2_free_mem(bp);
+ del_timer_sync(&bp->timer);
+ return rc;
+ }
+ bnx2_enable_int(bp);
+ }
+ }
+ if (bp->flags & USING_MSI_FLAG) {
+ printk(KERN_INFO PFX "%s: using MSI\n", dev->name);
+ }
+
+ netif_start_queue(dev);
+
+ return 0;
+}
+
+static void
+bnx2_reset_task(void *data)
+{
+ struct bnx2 *bp = data;
+
+ bnx2_netif_stop(bp);
+
+ bnx2_init_nic(bp);
+
+ atomic_set(&bp->intr_sem, 1);
+ bnx2_netif_start(bp);
+}
+
+static void
+bnx2_tx_timeout(struct net_device *dev)
+{
+ struct bnx2 *bp = dev->priv;
+
+ /* This allows the netif to be shutdown gracefully before resetting */
+ schedule_work(&bp->reset_task);
+}
+
+#ifdef BCM_VLAN
+/* Called with rtnl_lock */
+static void
+bnx2_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp)
+{
+ struct bnx2 *bp = dev->priv;
+
+ bnx2_netif_stop(bp);
+
+ bp->vlgrp = vlgrp;
+ bnx2_set_rx_mode(dev);
+
+ bnx2_netif_start(bp);
+}
+
+/* Called with rtnl_lock */
+static void
+bnx2_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
+{
+ struct bnx2 *bp = dev->priv;
+
+ bnx2_netif_stop(bp);
+
+ if (bp->vlgrp)
+ bp->vlgrp->vlan_devices[vid] = NULL;
+ bnx2_set_rx_mode(dev);
+
+ bnx2_netif_start(bp);
+}
+#endif
+
+/* Called with dev->xmit_lock.
+ * hard_start_xmit is pseudo-lockless - a lock is only required when
+ * the tx queue is full. This way, we get the benefit of lockless
+ * operations most of the time without the complexities to handle
+ * netif_stop_queue/wake_queue race conditions.
+ */
+static int
+bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct bnx2 *bp = dev->priv;
+ dma_addr_t mapping;
+ struct tx_bd *txbd;
+ struct sw_bd *tx_buf;
+ u32 len, vlan_tag_flags, last_frag, mss;
+ u16 prod, ring_prod;
+ int i;
+
+ if (unlikely(atomic_read(&bp->tx_avail_bd) <
+ (skb_shinfo(skb)->nr_frags + 1))) {
+
+ netif_stop_queue(dev);
+ printk(KERN_ERR PFX "%s: BUG! Tx ring full when queue awake!\n",
+ dev->name);
+
+ return NETDEV_TX_BUSY;
+ }
+ len = skb_headlen(skb);
+ prod = bp->tx_prod;
+ ring_prod = TX_RING_IDX(prod);
+
+ vlan_tag_flags = 0;
+ if (skb->ip_summed == CHECKSUM_HW) {
+ vlan_tag_flags |= TX_BD_FLAGS_TCP_UDP_CKSUM;
+ }
+
+ if (bp->vlgrp != 0 && vlan_tx_tag_present(skb)) {
+ vlan_tag_flags |=
+ (TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16));
+ }
+#ifdef BCM_TSO
+ if ((mss = skb_shinfo(skb)->tso_size) &&
+ (skb->len > (bp->dev->mtu + ETH_HLEN))) {
+ u32 tcp_opt_len, ip_tcp_len;
+
+ if (skb_header_cloned(skb) &&
+ pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ tcp_opt_len = ((skb->h.th->doff - 5) * 4);
+ vlan_tag_flags |= TX_BD_FLAGS_SW_LSO;
+
+ tcp_opt_len = 0;
+ if (skb->h.th->doff > 5) {
+ tcp_opt_len = (skb->h.th->doff - 5) << 2;
+ }
+ ip_tcp_len = (skb->nh.iph->ihl << 2) + sizeof(struct tcphdr);
+
+ skb->nh.iph->check = 0;
+ skb->nh.iph->tot_len = ntohs(mss + ip_tcp_len + tcp_opt_len);
+ skb->h.th->check =
+ ~csum_tcpudp_magic(skb->nh.iph->saddr,
+ skb->nh.iph->daddr,
+ 0, IPPROTO_TCP, 0);
+
+ if (tcp_opt_len || (skb->nh.iph->ihl > 5)) {
+ vlan_tag_flags |= ((skb->nh.iph->ihl - 5) +
+ (tcp_opt_len >> 2)) << 8;
+ }
+ }
+ else
+#endif
+ {
+ mss = 0;
+ }
+
+ mapping = pci_map_single(bp->pdev, skb->data, len, PCI_DMA_TODEVICE);
+
+ tx_buf = &bp->tx_buf_ring[ring_prod];
+ tx_buf->skb = skb;
+ pci_unmap_addr_set(tx_buf, mapping, mapping);
+
+ txbd = &bp->tx_desc_ring[ring_prod];
+
+ txbd->tx_bd_haddr_hi = (u64) mapping >> 32;
+ txbd->tx_bd_haddr_lo = (u64) mapping & 0xffffffff;
+ txbd->tx_bd_mss_nbytes = len | (mss << 16);
+ txbd->tx_bd_vlan_tag_flags = vlan_tag_flags | TX_BD_FLAGS_START;
+
+ last_frag = skb_shinfo(skb)->nr_frags;
+
+ for (i = 0; i < last_frag; i++) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+ prod = NEXT_TX_BD(prod);
+ ring_prod = TX_RING_IDX(prod);
+ txbd = &bp->tx_desc_ring[ring_prod];
+
+ len = frag->size;
+ mapping = pci_map_page(bp->pdev, frag->page, frag->page_offset,
+ len, PCI_DMA_TODEVICE);
+ pci_unmap_addr_set(&bp->tx_buf_ring[ring_prod],
+ mapping, mapping);
+
+ txbd->tx_bd_haddr_hi = (u64) mapping >> 32;
+ txbd->tx_bd_haddr_lo = (u64) mapping & 0xffffffff;
+ txbd->tx_bd_mss_nbytes = len | (mss << 16);
+ txbd->tx_bd_vlan_tag_flags = vlan_tag_flags;
+
+ }
+ txbd->tx_bd_vlan_tag_flags |= TX_BD_FLAGS_END;
+
+ prod = NEXT_TX_BD(prod);
+ bp->tx_prod_bseq += skb->len;
+
+ atomic_sub(last_frag + 1, &bp->tx_avail_bd);
+
+ REG_WR16(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BIDX, prod);
+ REG_WR(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BSEQ, bp->tx_prod_bseq);
+
+ mmiowb();
+
+ bp->tx_prod = prod;
+ dev->trans_start = jiffies;
+
+ if (unlikely(atomic_read(&bp->tx_avail_bd) <= MAX_SKB_FRAGS)) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&bp->tx_lock, flags);
+ if (atomic_read(&bp->tx_avail_bd) <= MAX_SKB_FRAGS) {
+ netif_stop_queue(dev);
+
+ if (atomic_read(&bp->tx_avail_bd) > MAX_SKB_FRAGS)
+ netif_wake_queue(dev);
+ }
+ spin_unlock_irqrestore(&bp->tx_lock, flags);
+ }
+
+ return NETDEV_TX_OK;
+}
+
+/* Called with rtnl_lock */
+static int
+bnx2_close(struct net_device *dev)
+{
+ struct bnx2 *bp = dev->priv;
+ u32 reset_code;
+
+ flush_scheduled_work();
+ bnx2_netif_stop(bp);
+ del_timer_sync(&bp->timer);
+ if (bp->wol)
+ reset_code = BNX2_DRV_MSG_CODE_SUSPEND_WOL;
+ else
+ reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
+ bnx2_reset_chip(bp, reset_code);
+ free_irq(bp->pdev->irq, dev);
+ if (bp->flags & USING_MSI_FLAG) {
+ pci_disable_msi(bp->pdev);
+ bp->flags &= ~USING_MSI_FLAG;
+ }
+ bnx2_free_skbs(bp);
+ bnx2_free_mem(bp);
+ bp->link_up = 0;
+ netif_carrier_off(bp->dev);
+ bnx2_set_power_state(bp, 3);
+ return 0;
+}
+
+#define GET_NET_STATS64(ctr) \
+ (unsigned long) ((unsigned long) (ctr##_hi) << 32) + \
+ (unsigned long) (ctr##_lo)
+
+#define GET_NET_STATS32(ctr) \
+ (ctr##_lo)
+
+#if (BITS_PER_LONG == 64)
+#define GET_NET_STATS GET_NET_STATS64
+#else
+#define GET_NET_STATS GET_NET_STATS32
+#endif
+
+static struct net_device_stats *
+bnx2_get_stats(struct net_device *dev)
+{
+ struct bnx2 *bp = dev->priv;
+ struct statistics_block *stats_blk = bp->stats_blk;
+ struct net_device_stats *net_stats = &bp->net_stats;
+
+ if (bp->stats_blk == NULL) {
+ return net_stats;
+ }
+ net_stats->rx_packets =
+ GET_NET_STATS(stats_blk->stat_IfHCInUcastPkts) +
+ GET_NET_STATS(stats_blk->stat_IfHCInMulticastPkts) +
+ GET_NET_STATS(stats_blk->stat_IfHCInBroadcastPkts);
+
+ net_stats->tx_packets =
+ GET_NET_STATS(stats_blk->stat_IfHCOutUcastPkts) +
+ GET_NET_STATS(stats_blk->stat_IfHCOutMulticastPkts) +
+ GET_NET_STATS(stats_blk->stat_IfHCOutBroadcastPkts);
+
+ net_stats->rx_bytes =
+ GET_NET_STATS(stats_blk->stat_IfHCInOctets);
+
+ net_stats->tx_bytes =
+ GET_NET_STATS(stats_blk->stat_IfHCOutOctets);
+
+ net_stats->multicast =
+ GET_NET_STATS(stats_blk->stat_IfHCOutMulticastPkts);
+
+ net_stats->collisions =
+ (unsigned long) stats_blk->stat_EtherStatsCollisions;
+
+ net_stats->rx_length_errors =
+ (unsigned long) (stats_blk->stat_EtherStatsUndersizePkts +
+ stats_blk->stat_EtherStatsOverrsizePkts);
+
+ net_stats->rx_over_errors =
+ (unsigned long) stats_blk->stat_IfInMBUFDiscards;
+
+ net_stats->rx_frame_errors =
+ (unsigned long) stats_blk->stat_Dot3StatsAlignmentErrors;
+
+ net_stats->rx_crc_errors =
+ (unsigned long) stats_blk->stat_Dot3StatsFCSErrors;
+
+ net_stats->rx_errors = net_stats->rx_length_errors +
+ net_stats->rx_over_errors + net_stats->rx_frame_errors +
+ net_stats->rx_crc_errors;
+
+ net_stats->tx_aborted_errors =
+ (unsigned long) (stats_blk->stat_Dot3StatsExcessiveCollisions +
+ stats_blk->stat_Dot3StatsLateCollisions);
+
+ if (CHIP_NUM(bp) == CHIP_NUM_5706)
+ net_stats->tx_carrier_errors = 0;
+ else {
+ net_stats->tx_carrier_errors =
+ (unsigned long)
+ stats_blk->stat_Dot3StatsCarrierSenseErrors;
+ }
+
+ net_stats->tx_errors =
+ (unsigned long)
+ stats_blk->stat_emac_tx_stat_dot3statsinternalmactransmiterrors
+ +
+ net_stats->tx_aborted_errors +
+ net_stats->tx_carrier_errors;
+
+ return net_stats;
+}
+
+/* All ethtool functions called with rtnl_lock */
+
+static int
+bnx2_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct bnx2 *bp = dev->priv;
+
+ cmd->supported = SUPPORTED_Autoneg;
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ cmd->supported |= SUPPORTED_1000baseT_Full |
+ SUPPORTED_FIBRE;
+
+ cmd->port = PORT_FIBRE;
+ }
+ else {
+ cmd->supported |= SUPPORTED_10baseT_Half |
+ SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Full |
+ SUPPORTED_TP;
+
+ cmd->port = PORT_TP;
+ }
+
+ cmd->advertising = bp->advertising;
+
+ if (bp->autoneg & AUTONEG_SPEED) {
+ cmd->autoneg = AUTONEG_ENABLE;
+ }
+ else {
+ cmd->autoneg = AUTONEG_DISABLE;
+ }
+
+ if (netif_carrier_ok(dev)) {
+ cmd->speed = bp->line_speed;
+ cmd->duplex = bp->duplex;
+ }
+ else {
+ cmd->speed = -1;
+ cmd->duplex = -1;
+ }
+
+ cmd->transceiver = XCVR_INTERNAL;
+ cmd->phy_address = bp->phy_addr;
+
+ return 0;
+}
+
+static int
+bnx2_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct bnx2 *bp = dev->priv;
+ u8 autoneg = bp->autoneg;
+ u8 req_duplex = bp->req_duplex;
+ u16 req_line_speed = bp->req_line_speed;
+ u32 advertising = bp->advertising;
+
+ if (cmd->autoneg == AUTONEG_ENABLE) {
+ autoneg |= AUTONEG_SPEED;
+
+ cmd->advertising &= ETHTOOL_ALL_COPPER_SPEED;
+
+ /* allow advertising 1 speed */
+ if ((cmd->advertising == ADVERTISED_10baseT_Half) ||
+ (cmd->advertising == ADVERTISED_10baseT_Full) ||
+ (cmd->advertising == ADVERTISED_100baseT_Half) ||
+ (cmd->advertising == ADVERTISED_100baseT_Full)) {
+
+ if (bp->phy_flags & PHY_SERDES_FLAG)
+ return -EINVAL;
+
+ advertising = cmd->advertising;
+
+ }
+ else if (cmd->advertising == ADVERTISED_1000baseT_Full) {
+ advertising = cmd->advertising;
+ }
+ else if (cmd->advertising == ADVERTISED_1000baseT_Half) {
+ return -EINVAL;
+ }
+ else {
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ advertising = ETHTOOL_ALL_FIBRE_SPEED;
+ }
+ else {
+ advertising = ETHTOOL_ALL_COPPER_SPEED;
+ }
+ }
+ advertising |= ADVERTISED_Autoneg;
+ }
+ else {
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ if ((cmd->speed != SPEED_1000) ||
+ (cmd->duplex != DUPLEX_FULL)) {
+ return -EINVAL;
+ }
+ }
+ else if (cmd->speed == SPEED_1000) {
+ return -EINVAL;
+ }
+ autoneg &= ~AUTONEG_SPEED;
+ req_line_speed = cmd->speed;
+ req_duplex = cmd->duplex;
+ advertising = 0;
+ }
+
+ bp->autoneg = autoneg;
+ bp->advertising = advertising;
+ bp->req_line_speed = req_line_speed;
+ bp->req_duplex = req_duplex;
+
+ spin_lock_irq(&bp->phy_lock);
+
+ bnx2_setup_phy(bp);
+
+ spin_unlock_irq(&bp->phy_lock);
+
+ return 0;
+}
+
+static void
+bnx2_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+ struct bnx2 *bp = dev->priv;
+
+ strcpy(info->driver, DRV_MODULE_NAME);
+ strcpy(info->version, DRV_MODULE_VERSION);
+ strcpy(info->bus_info, pci_name(bp->pdev));
+ info->fw_version[0] = ((bp->fw_ver & 0xff000000) >> 24) + '0';
+ info->fw_version[2] = ((bp->fw_ver & 0xff0000) >> 16) + '0';
+ info->fw_version[4] = ((bp->fw_ver & 0xff00) >> 8) + '0';
+ info->fw_version[6] = (bp->fw_ver & 0xff) + '0';
+ info->fw_version[1] = info->fw_version[3] = info->fw_version[5] = '.';
+ info->fw_version[7] = 0;
+}
+
+static void
+bnx2_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct bnx2 *bp = dev->priv;
+
+ if (bp->flags & NO_WOL_FLAG) {
+ wol->supported = 0;
+ wol->wolopts = 0;
+ }
+ else {
+ wol->supported = WAKE_MAGIC;
+ if (bp->wol)
+ wol->wolopts = WAKE_MAGIC;
+ else
+ wol->wolopts = 0;
+ }
+ memset(&wol->sopass, 0, sizeof(wol->sopass));
+}
+
+static int
+bnx2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct bnx2 *bp = dev->priv;
+
+ if (wol->wolopts & ~WAKE_MAGIC)
+ return -EINVAL;
+
+ if (wol->wolopts & WAKE_MAGIC) {
+ if (bp->flags & NO_WOL_FLAG)
+ return -EINVAL;
+
+ bp->wol = 1;
+ }
+ else {
+ bp->wol = 0;
+ }
+ return 0;
+}
+
+static int
+bnx2_nway_reset(struct net_device *dev)
+{
+ struct bnx2 *bp = dev->priv;
+ u32 bmcr;
+
+ if (!(bp->autoneg & AUTONEG_SPEED)) {
+ return -EINVAL;
+ }
+
+ spin_lock_irq(&bp->phy_lock);
+
+ /* Force a link down visible on the other side */
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK);
+ spin_unlock_irq(&bp->phy_lock);
+
+ msleep(20);
+
+ spin_lock_irq(&bp->phy_lock);
+ if (CHIP_NUM(bp) == CHIP_NUM_5706) {
+ bp->serdes_an_pending = SERDES_AN_TIMEOUT /
+ bp->timer_interval;
+ }
+ }
+
+ bnx2_read_phy(bp, MII_BMCR, &bmcr);
+ bmcr &= ~BMCR_LOOPBACK;
+ bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART | BMCR_ANENABLE);
+
+ spin_unlock_irq(&bp->phy_lock);
+
+ return 0;
+}
+
+static int
+bnx2_get_eeprom_len(struct net_device *dev)
+{
+ struct bnx2 *bp = dev->priv;
+
+ if (bp->flash_info == 0)
+ return 0;
+
+ return (int) bp->flash_info->total_size;
+}
+
+static int
+bnx2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
+ u8 *eebuf)
+{
+ struct bnx2 *bp = dev->priv;
+ int rc;
+
+ if (eeprom->offset > bp->flash_info->total_size)
+ return -EINVAL;
+
+ if ((eeprom->offset + eeprom->len) > bp->flash_info->total_size)
+ eeprom->len = bp->flash_info->total_size - eeprom->offset;
+
+ rc = bnx2_nvram_read(bp, eeprom->offset, eebuf, eeprom->len);
+
+ return rc;
+}
+
+static int
+bnx2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
+ u8 *eebuf)
+{
+ struct bnx2 *bp = dev->priv;
+ int rc;
+
+ if (eeprom->offset > bp->flash_info->total_size)
+ return -EINVAL;
+
+ if ((eeprom->offset + eeprom->len) > bp->flash_info->total_size)
+ eeprom->len = bp->flash_info->total_size - eeprom->offset;
+
+ rc = bnx2_nvram_write(bp, eeprom->offset, eebuf, eeprom->len);
+
+ return rc;
+}
+
+static int
+bnx2_get_coalesce(struct net_device *dev, struct ethtool_coalesce *coal)
+{
+ struct bnx2 *bp = dev->priv;
+
+ memset(coal, 0, sizeof(struct ethtool_coalesce));
+
+ coal->rx_coalesce_usecs = bp->rx_ticks;
+ coal->rx_max_coalesced_frames = bp->rx_quick_cons_trip;
+ coal->rx_coalesce_usecs_irq = bp->rx_ticks_int;
+ coal->rx_max_coalesced_frames_irq = bp->rx_quick_cons_trip_int;
+
+ coal->tx_coalesce_usecs = bp->tx_ticks;
+ coal->tx_max_coalesced_frames = bp->tx_quick_cons_trip;
+ coal->tx_coalesce_usecs_irq = bp->tx_ticks_int;
+ coal->tx_max_coalesced_frames_irq = bp->tx_quick_cons_trip_int;
+
+ coal->stats_block_coalesce_usecs = bp->stats_ticks;
+
+ return 0;
+}
+
+static int
+bnx2_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal)
+{
+ struct bnx2 *bp = dev->priv;
+
+ bp->rx_ticks = (u16) coal->rx_coalesce_usecs;
+ if (bp->rx_ticks > 0x3ff) bp->rx_ticks = 0x3ff;
+
+ bp->rx_quick_cons_trip = (u16) coal->rx_max_coalesced_frames;
+ if (bp->rx_quick_cons_trip > 0xff) bp->rx_quick_cons_trip = 0xff;
+
+ bp->rx_ticks_int = (u16) coal->rx_coalesce_usecs_irq;
+ if (bp->rx_ticks_int > 0x3ff) bp->rx_ticks_int = 0x3ff;
+
+ bp->rx_quick_cons_trip_int = (u16) coal->rx_max_coalesced_frames_irq;
+ if (bp->rx_quick_cons_trip_int > 0xff)
+ bp->rx_quick_cons_trip_int = 0xff;
+
+ bp->tx_ticks = (u16) coal->tx_coalesce_usecs;
+ if (bp->tx_ticks > 0x3ff) bp->tx_ticks = 0x3ff;
+
+ bp->tx_quick_cons_trip = (u16) coal->tx_max_coalesced_frames;
+ if (bp->tx_quick_cons_trip > 0xff) bp->tx_quick_cons_trip = 0xff;
+
+ bp->tx_ticks_int = (u16) coal->tx_coalesce_usecs_irq;
+ if (bp->tx_ticks_int > 0x3ff) bp->tx_ticks_int = 0x3ff;
+
+ bp->tx_quick_cons_trip_int = (u16) coal->tx_max_coalesced_frames_irq;
+ if (bp->tx_quick_cons_trip_int > 0xff) bp->tx_quick_cons_trip_int =
+ 0xff;
+
+ bp->stats_ticks = coal->stats_block_coalesce_usecs;
+ if (bp->stats_ticks > 0xffff00) bp->stats_ticks = 0xffff00;
+ bp->stats_ticks &= 0xffff00;
+
+ if (netif_running(bp->dev)) {
+ bnx2_netif_stop(bp);
+ bnx2_init_nic(bp);
+ bnx2_netif_start(bp);
+ }
+
+ return 0;
+}
+
+static void
+bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
+{
+ struct bnx2 *bp = dev->priv;
+
+ ering->rx_max_pending = MAX_RX_DESC_CNT;
+ ering->rx_mini_max_pending = 0;
+ ering->rx_jumbo_max_pending = 0;
+
+ ering->rx_pending = bp->rx_ring_size;
+ ering->rx_mini_pending = 0;
+ ering->rx_jumbo_pending = 0;
+
+ ering->tx_max_pending = MAX_TX_DESC_CNT;
+ ering->tx_pending = bp->tx_ring_size;
+}
+
+static int
+bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
+{
+ struct bnx2 *bp = dev->priv;
+
+ if ((ering->rx_pending > MAX_RX_DESC_CNT) ||
+ (ering->tx_pending > MAX_TX_DESC_CNT) ||
+ (ering->tx_pending <= MAX_SKB_FRAGS)) {
+
+ return -EINVAL;
+ }
+ bp->rx_ring_size = ering->rx_pending;
+ bp->tx_ring_size = ering->tx_pending;
+
+ if (netif_running(bp->dev)) {
+ bnx2_netif_stop(bp);
+ bnx2_init_nic(bp);
+ bnx2_netif_start(bp);
+ }
+
+ return 0;
+}
+
+static void
+bnx2_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
+{
+ struct bnx2 *bp = dev->priv;
+
+ epause->autoneg = ((bp->autoneg & AUTONEG_FLOW_CTRL) != 0);
+ epause->rx_pause = ((bp->flow_ctrl & FLOW_CTRL_RX) != 0);
+ epause->tx_pause = ((bp->flow_ctrl & FLOW_CTRL_TX) != 0);
+}
+
+static int
+bnx2_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
+{
+ struct bnx2 *bp = dev->priv;
+
+ bp->req_flow_ctrl = 0;
+ if (epause->rx_pause)
+ bp->req_flow_ctrl |= FLOW_CTRL_RX;
+ if (epause->tx_pause)
+ bp->req_flow_ctrl |= FLOW_CTRL_TX;
+
+ if (epause->autoneg) {
+ bp->autoneg |= AUTONEG_FLOW_CTRL;
+ }
+ else {
+ bp->autoneg &= ~AUTONEG_FLOW_CTRL;
+ }
+
+ spin_lock_irq(&bp->phy_lock);
+
+ bnx2_setup_phy(bp);
+
+ spin_unlock_irq(&bp->phy_lock);
+
+ return 0;
+}
+
+static u32
+bnx2_get_rx_csum(struct net_device *dev)
+{
+ struct bnx2 *bp = dev->priv;
+
+ return bp->rx_csum;
+}
+
+static int
+bnx2_set_rx_csum(struct net_device *dev, u32 data)
+{
+ struct bnx2 *bp = dev->priv;
+
+ bp->rx_csum = data;
+ return 0;
+}
+
+#define BNX2_NUM_STATS 45
+
+struct {
+ char string[ETH_GSTRING_LEN];
+} bnx2_stats_str_arr[BNX2_NUM_STATS] = {
+ { "rx_bytes" },
+ { "rx_error_bytes" },
+ { "tx_bytes" },
+ { "tx_error_bytes" },
+ { "rx_ucast_packets" },
+ { "rx_mcast_packets" },
+ { "rx_bcast_packets" },
+ { "tx_ucast_packets" },
+ { "tx_mcast_packets" },
+ { "tx_bcast_packets" },
+ { "tx_mac_errors" },
+ { "tx_carrier_errors" },
+ { "rx_crc_errors" },
+ { "rx_align_errors" },
+ { "tx_single_collisions" },
+ { "tx_multi_collisions" },
+ { "tx_deferred" },
+ { "tx_excess_collisions" },
+ { "tx_late_collisions" },
+ { "tx_total_collisions" },
+ { "rx_fragments" },
+ { "rx_jabbers" },
+ { "rx_undersize_packets" },
+ { "rx_oversize_packets" },
+ { "rx_64_byte_packets" },
+ { "rx_65_to_127_byte_packets" },
+ { "rx_128_to_255_byte_packets" },
+ { "rx_256_to_511_byte_packets" },
+ { "rx_512_to_1023_byte_packets" },
+ { "rx_1024_to_1522_byte_packets" },
+ { "rx_1523_to_9022_byte_packets" },
+ { "tx_64_byte_packets" },
+ { "tx_65_to_127_byte_packets" },
+ { "tx_128_to_255_byte_packets" },
+ { "tx_256_to_511_byte_packets" },
+ { "tx_512_to_1023_byte_packets" },
+ { "tx_1024_to_1522_byte_packets" },
+ { "tx_1523_to_9022_byte_packets" },
+ { "rx_xon_frames" },
+ { "rx_xoff_frames" },
+ { "tx_xon_frames" },
+ { "tx_xoff_frames" },
+ { "rx_mac_ctrl_frames" },
+ { "rx_filtered_packets" },
+ { "rx_discards" },
+};
+
+#define STATS_OFFSET32(offset_name) (offsetof(struct statistics_block, offset_name) / 4)
+
+unsigned long bnx2_stats_offset_arr[BNX2_NUM_STATS] = {
+ STATS_OFFSET32(stat_IfHCInOctets_hi),
+ STATS_OFFSET32(stat_IfHCInBadOctets_hi),
+ STATS_OFFSET32(stat_IfHCOutOctets_hi),
+ STATS_OFFSET32(stat_IfHCOutBadOctets_hi),
+ STATS_OFFSET32(stat_IfHCInUcastPkts_hi),
+ STATS_OFFSET32(stat_IfHCInMulticastPkts_hi),
+ STATS_OFFSET32(stat_IfHCInBroadcastPkts_hi),
+ STATS_OFFSET32(stat_IfHCOutUcastPkts_hi),
+ STATS_OFFSET32(stat_IfHCOutMulticastPkts_hi),
+ STATS_OFFSET32(stat_IfHCOutBroadcastPkts_hi),
+ STATS_OFFSET32(stat_emac_tx_stat_dot3statsinternalmactransmiterrors),
+ STATS_OFFSET32(stat_Dot3StatsCarrierSenseErrors),
+ STATS_OFFSET32(stat_Dot3StatsFCSErrors),
+ STATS_OFFSET32(stat_Dot3StatsAlignmentErrors),
+ STATS_OFFSET32(stat_Dot3StatsSingleCollisionFrames),
+ STATS_OFFSET32(stat_Dot3StatsMultipleCollisionFrames),
+ STATS_OFFSET32(stat_Dot3StatsDeferredTransmissions),
+ STATS_OFFSET32(stat_Dot3StatsExcessiveCollisions),
+ STATS_OFFSET32(stat_Dot3StatsLateCollisions),
+ STATS_OFFSET32(stat_EtherStatsCollisions),
+ STATS_OFFSET32(stat_EtherStatsFragments),
+ STATS_OFFSET32(stat_EtherStatsJabbers),
+ STATS_OFFSET32(stat_EtherStatsUndersizePkts),
+ STATS_OFFSET32(stat_EtherStatsOverrsizePkts),
+ STATS_OFFSET32(stat_EtherStatsPktsRx64Octets),
+ STATS_OFFSET32(stat_EtherStatsPktsRx65Octetsto127Octets),
+ STATS_OFFSET32(stat_EtherStatsPktsRx128Octetsto255Octets),
+ STATS_OFFSET32(stat_EtherStatsPktsRx256Octetsto511Octets),
+ STATS_OFFSET32(stat_EtherStatsPktsRx512Octetsto1023Octets),
+ STATS_OFFSET32(stat_EtherStatsPktsRx1024Octetsto1522Octets),
+ STATS_OFFSET32(stat_EtherStatsPktsRx1523Octetsto9022Octets),
+ STATS_OFFSET32(stat_EtherStatsPktsTx64Octets),
+ STATS_OFFSET32(stat_EtherStatsPktsTx65Octetsto127Octets),
+ STATS_OFFSET32(stat_EtherStatsPktsTx128Octetsto255Octets),
+ STATS_OFFSET32(stat_EtherStatsPktsTx256Octetsto511Octets),
+ STATS_OFFSET32(stat_EtherStatsPktsTx512Octetsto1023Octets),
+ STATS_OFFSET32(stat_EtherStatsPktsTx1024Octetsto1522Octets),
+ STATS_OFFSET32(stat_EtherStatsPktsTx1523Octetsto9022Octets),
+ STATS_OFFSET32(stat_XonPauseFramesReceived),
+ STATS_OFFSET32(stat_XoffPauseFramesReceived),
+ STATS_OFFSET32(stat_OutXonSent),
+ STATS_OFFSET32(stat_OutXoffSent),
+ STATS_OFFSET32(stat_MacControlFramesReceived),
+ STATS_OFFSET32(stat_IfInFramesL2FilterDiscards),
+ STATS_OFFSET32(stat_IfInMBUFDiscards),
+};
+
+/* stat_IfHCInBadOctets and stat_Dot3StatsCarrierSenseErrors are
+ * skipped because of errata.
+ */
+u8 bnx2_5706_stats_len_arr[BNX2_NUM_STATS] = {
+ 8,0,8,8,8,8,8,8,8,8,
+ 4,0,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,
+};
+
+#define BNX2_NUM_TESTS 6
+
+struct {
+ char string[ETH_GSTRING_LEN];
+} bnx2_tests_str_arr[BNX2_NUM_TESTS] = {
+ { "register_test (offline)" },
+ { "memory_test (offline)" },
+ { "loopback_test (offline)" },
+ { "nvram_test (online)" },
+ { "interrupt_test (online)" },
+ { "link_test (online)" },
+};
+
+static int
+bnx2_self_test_count(struct net_device *dev)
+{
+ return BNX2_NUM_TESTS;
+}
+
+static void
+bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf)
+{
+ struct bnx2 *bp = dev->priv;
+
+ memset(buf, 0, sizeof(u64) * BNX2_NUM_TESTS);
+ if (etest->flags & ETH_TEST_FL_OFFLINE) {
+ bnx2_netif_stop(bp);
+ bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_DIAG);
+ bnx2_free_skbs(bp);
+
+ if (bnx2_test_registers(bp) != 0) {
+ buf[0] = 1;
+ etest->flags |= ETH_TEST_FL_FAILED;
+ }
+ if (bnx2_test_memory(bp) != 0) {
+ buf[1] = 1;
+ etest->flags |= ETH_TEST_FL_FAILED;
+ }
+ if (bnx2_test_loopback(bp) != 0) {
+ buf[2] = 1;
+ etest->flags |= ETH_TEST_FL_FAILED;
+ }
+
+ if (!netif_running(bp->dev)) {
+ bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET);
+ }
+ else {
+ bnx2_init_nic(bp);
+ bnx2_netif_start(bp);
+ }
+
+ /* wait for link up */
+ msleep_interruptible(3000);
+ if ((!bp->link_up) && !(bp->phy_flags & PHY_SERDES_FLAG))
+ msleep_interruptible(4000);
+ }
+
+ if (bnx2_test_nvram(bp) != 0) {
+ buf[3] = 1;
+ etest->flags |= ETH_TEST_FL_FAILED;
+ }
+ if (bnx2_test_intr(bp) != 0) {
+ buf[4] = 1;
+ etest->flags |= ETH_TEST_FL_FAILED;
+ }
+
+ if (bnx2_test_link(bp) != 0) {
+ buf[5] = 1;
+ etest->flags |= ETH_TEST_FL_FAILED;
+
+ }
+}
+
+static void
+bnx2_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
+{
+ switch (stringset) {
+ case ETH_SS_STATS:
+ memcpy(buf, bnx2_stats_str_arr,
+ sizeof(bnx2_stats_str_arr));
+ break;
+ case ETH_SS_TEST:
+ memcpy(buf, bnx2_tests_str_arr,
+ sizeof(bnx2_tests_str_arr));
+ break;
+ }
+}
+
+static int
+bnx2_get_stats_count(struct net_device *dev)
+{
+ return BNX2_NUM_STATS;
+}
+
+static void
+bnx2_get_ethtool_stats(struct net_device *dev,
+ struct ethtool_stats *stats, u64 *buf)
+{
+ struct bnx2 *bp = dev->priv;
+ int i;
+ u32 *hw_stats = (u32 *) bp->stats_blk;
+ u8 *stats_len_arr = 0;
+
+ if (hw_stats == NULL) {
+ memset(buf, 0, sizeof(u64) * BNX2_NUM_STATS);
+ return;
+ }
+
+ if (CHIP_NUM(bp) == CHIP_NUM_5706)
+ stats_len_arr = bnx2_5706_stats_len_arr;
+
+ for (i = 0; i < BNX2_NUM_STATS; i++) {
+ if (stats_len_arr[i] == 0) {
+ /* skip this counter */
+ buf[i] = 0;
+ continue;
+ }
+ if (stats_len_arr[i] == 4) {
+ /* 4-byte counter */
+ buf[i] = (u64)
+ *(hw_stats + bnx2_stats_offset_arr[i]);
+ continue;
+ }
+ /* 8-byte counter */
+ buf[i] = (((u64) *(hw_stats +
+ bnx2_stats_offset_arr[i])) << 32) +
+ *(hw_stats + bnx2_stats_offset_arr[i] + 1);
+ }
+}
+
+static int
+bnx2_phys_id(struct net_device *dev, u32 data)
+{
+ struct bnx2 *bp = dev->priv;
+ int i;
+ u32 save;
+
+ if (data == 0)
+ data = 2;
+
+ save = REG_RD(bp, BNX2_MISC_CFG);
+ REG_WR(bp, BNX2_MISC_CFG, BNX2_MISC_CFG_LEDMODE_MAC);
+
+ for (i = 0; i < (data * 2); i++) {
+ if ((i % 2) == 0) {
+ REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE);
+ }
+ else {
+ REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE |
+ BNX2_EMAC_LED_1000MB_OVERRIDE |
+ BNX2_EMAC_LED_100MB_OVERRIDE |
+ BNX2_EMAC_LED_10MB_OVERRIDE |
+ BNX2_EMAC_LED_TRAFFIC_OVERRIDE |
+ BNX2_EMAC_LED_TRAFFIC);
+ }
+ msleep_interruptible(500);
+ if (signal_pending(current))
+ break;
+ }
+ REG_WR(bp, BNX2_EMAC_LED, 0);
+ REG_WR(bp, BNX2_MISC_CFG, save);
+ return 0;
+}
+
+static struct ethtool_ops bnx2_ethtool_ops = {
+ .get_settings = bnx2_get_settings,
+ .set_settings = bnx2_set_settings,
+ .get_drvinfo = bnx2_get_drvinfo,
+ .get_wol = bnx2_get_wol,
+ .set_wol = bnx2_set_wol,
+ .nway_reset = bnx2_nway_reset,
+ .get_link = ethtool_op_get_link,
+ .get_eeprom_len = bnx2_get_eeprom_len,
+ .get_eeprom = bnx2_get_eeprom,
+ .set_eeprom = bnx2_set_eeprom,
+ .get_coalesce = bnx2_get_coalesce,
+ .set_coalesce = bnx2_set_coalesce,
+ .get_ringparam = bnx2_get_ringparam,
+ .set_ringparam = bnx2_set_ringparam,
+ .get_pauseparam = bnx2_get_pauseparam,
+ .set_pauseparam = bnx2_set_pauseparam,
+ .get_rx_csum = bnx2_get_rx_csum,
+ .set_rx_csum = bnx2_set_rx_csum,
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .set_tx_csum = ethtool_op_set_tx_csum,
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = ethtool_op_set_sg,
+#ifdef BCM_TSO
+ .get_tso = ethtool_op_get_tso,
+ .set_tso = ethtool_op_set_tso,
+#endif
+ .self_test_count = bnx2_self_test_count,
+ .self_test = bnx2_self_test,
+ .get_strings = bnx2_get_strings,
+ .phys_id = bnx2_phys_id,
+ .get_stats_count = bnx2_get_stats_count,
+ .get_ethtool_stats = bnx2_get_ethtool_stats,
+};
+
+/* Called with rtnl_lock */
+static int
+bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data;
+ struct bnx2 *bp = dev->priv;
+ int err;
+
+ switch(cmd) {
+ case SIOCGMIIPHY:
+ data->phy_id = bp->phy_addr;
+
+ /* fallthru */
+ case SIOCGMIIREG: {
+ u32 mii_regval;
+
+ spin_lock_irq(&bp->phy_lock);
+ err = bnx2_read_phy(bp, data->reg_num & 0x1f, &mii_regval);
+ spin_unlock_irq(&bp->phy_lock);
+
+ data->val_out = mii_regval;
+
+ return err;
+ }
+
+ case SIOCSMIIREG:
+ if (!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ spin_lock_irq(&bp->phy_lock);
+ err = bnx2_write_phy(bp, data->reg_num & 0x1f, data->val_in);
+ spin_unlock_irq(&bp->phy_lock);
+
+ return err;
+
+ default:
+ /* do nothing */
+ break;
+ }
+ return -EOPNOTSUPP;
+}
+
+/* Called with rtnl_lock */
+static int
+bnx2_change_mac_addr(struct net_device *dev, void *p)
+{
+ struct sockaddr *addr = p;
+ struct bnx2 *bp = dev->priv;
+
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+ if (netif_running(dev))
+ bnx2_set_mac_addr(bp);
+
+ return 0;
+}
+
+/* Called with rtnl_lock */
+static int
+bnx2_change_mtu(struct net_device *dev, int new_mtu)
+{
+ struct bnx2 *bp = dev->priv;
+
+ if (((new_mtu + ETH_HLEN) > MAX_ETHERNET_JUMBO_PACKET_SIZE) ||
+ ((new_mtu + ETH_HLEN) < MIN_ETHERNET_PACKET_SIZE))
+ return -EINVAL;
+
+ dev->mtu = new_mtu;
+ if (netif_running(dev)) {
+ bnx2_netif_stop(bp);
+
+ bnx2_init_nic(bp);
+
+ bnx2_netif_start(bp);
+ }
+ return 0;
+}
+
+#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
+static void
+poll_bnx2(struct net_device *dev)
+{
+ struct bnx2 *bp = dev->priv;
+
+ disable_irq(bp->pdev->irq);
+ bnx2_interrupt(bp->pdev->irq, dev, NULL);
+ enable_irq(bp->pdev->irq);
+}
+#endif
+
+static int __devinit
+bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
+{
+ struct bnx2 *bp;
+ unsigned long mem_len;
+ int rc;
+ u32 reg;
+
+ SET_MODULE_OWNER(dev);
+ SET_NETDEV_DEV(dev, &pdev->dev);
+ bp = dev->priv;
+
+ bp->flags = 0;
+ bp->phy_flags = 0;
+
+ /* enable device (incl. PCI PM wakeup), and bus-mastering */
+ rc = pci_enable_device(pdev);
+ if (rc) {
+ printk(KERN_ERR PFX "Cannot enable PCI device, aborting.");
+ goto err_out;
+ }
+
+ if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+ printk(KERN_ERR PFX "Cannot find PCI device base address, "
+ "aborting.\n");
+ rc = -ENODEV;
+ goto err_out_disable;
+ }
+
+ rc = pci_request_regions(pdev, DRV_MODULE_NAME);
+ if (rc) {
+ printk(KERN_ERR PFX "Cannot obtain PCI resources, aborting.\n");
+ goto err_out_disable;
+ }
+
+ pci_set_master(pdev);
+
+ bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
+ if (bp->pm_cap == 0) {
+ printk(KERN_ERR PFX "Cannot find power management capability, "
+ "aborting.\n");
+ rc = -EIO;
+ goto err_out_release;
+ }
+
+ bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX);
+ if (bp->pcix_cap == 0) {
+ printk(KERN_ERR PFX "Cannot find PCIX capability, aborting.\n");
+ rc = -EIO;
+ goto err_out_release;
+ }
+
+ if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) == 0) {
+ bp->flags |= USING_DAC_FLAG;
+ if (pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK) != 0) {
+ printk(KERN_ERR PFX "pci_set_consistent_dma_mask "
+ "failed, aborting.\n");
+ rc = -EIO;
+ goto err_out_release;
+ }
+ }
+ else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) != 0) {
+ printk(KERN_ERR PFX "System does not support DMA, aborting.\n");
+ rc = -EIO;
+ goto err_out_release;
+ }
+
+ bp->dev = dev;
+ bp->pdev = pdev;
+
+ spin_lock_init(&bp->phy_lock);
+ spin_lock_init(&bp->tx_lock);
+ INIT_WORK(&bp->reset_task, bnx2_reset_task, bp);
+
+ dev->base_addr = dev->mem_start = pci_resource_start(pdev, 0);
+ mem_len = MB_GET_CID_ADDR(17);
+ dev->mem_end = dev->mem_start + mem_len;
+ dev->irq = pdev->irq;
+
+ bp->regview = ioremap_nocache(dev->base_addr, mem_len);
+
+ if (!bp->regview) {
+ printk(KERN_ERR PFX "Cannot map register space, aborting.\n");
+ rc = -ENOMEM;
+ goto err_out_release;
+ }
+
+ /* Configure byte swap and enable write to the reg_window registers.
+ * Rely on CPU to do target byte swapping on big endian systems
+ * The chip's target access swapping will not swap all accesses
+ */
+ pci_write_config_dword(bp->pdev, BNX2_PCICFG_MISC_CONFIG,
+ BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
+ BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP);
+
+ bnx2_set_power_state(bp, 0);
+
+ bp->chip_id = REG_RD(bp, BNX2_MISC_ID);
+
+ bp->phy_addr = 1;
+
+ /* Get bus information. */
+ reg = REG_RD(bp, BNX2_PCICFG_MISC_STATUS);
+ if (reg & BNX2_PCICFG_MISC_STATUS_PCIX_DET) {
+ u32 clkreg;
+
+ bp->flags |= PCIX_FLAG;
+
+ clkreg = REG_RD(bp, BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS);
+
+ clkreg &= BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET;
+ switch (clkreg) {
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ:
+ bp->bus_speed_mhz = 133;
+ break;
+
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ:
+ bp->bus_speed_mhz = 100;
+ break;
+
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ:
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ:
+ bp->bus_speed_mhz = 66;
+ break;
+
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ:
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ:
+ bp->bus_speed_mhz = 50;
+ break;
+
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW:
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ:
+ case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ:
+ bp->bus_speed_mhz = 33;
+ break;
+ }
+ }
+ else {
+ if (reg & BNX2_PCICFG_MISC_STATUS_M66EN)
+ bp->bus_speed_mhz = 66;
+ else
+ bp->bus_speed_mhz = 33;
+ }
+
+ if (reg & BNX2_PCICFG_MISC_STATUS_32BIT_DET)
+ bp->flags |= PCI_32BIT_FLAG;
+
+ /* 5706A0 may falsely detect SERR and PERR. */
+ if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
+ reg = REG_RD(bp, PCI_COMMAND);
+ reg &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
+ REG_WR(bp, PCI_COMMAND, reg);
+ }
+ else if ((CHIP_ID(bp) == CHIP_ID_5706_A1) &&
+ !(bp->flags & PCIX_FLAG)) {
+
+ printk(KERN_ERR PFX "5706 A1 can only be used in a PCIX bus, "
+ "aborting.\n");
+ goto err_out_unmap;
+ }
+
+ bnx2_init_nvram(bp);
+
+ /* Get the permanent MAC address. First we need to make sure the
+ * firmware is actually running.
+ */
+ reg = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_DEV_INFO_SIGNATURE);
+
+ if ((reg & BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK) !=
+ BNX2_DEV_INFO_SIGNATURE_MAGIC) {
+ printk(KERN_ERR PFX "Firmware not running, aborting.\n");
+ rc = -ENODEV;
+ goto err_out_unmap;
+ }
+
+ bp->fw_ver = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE +
+ BNX2_DEV_INFO_BC_REV);
+
+ reg = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_PORT_HW_CFG_MAC_UPPER);
+ bp->mac_addr[0] = (u8) (reg >> 8);
+ bp->mac_addr[1] = (u8) reg;
+
+ reg = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_PORT_HW_CFG_MAC_LOWER);
+ bp->mac_addr[2] = (u8) (reg >> 24);
+ bp->mac_addr[3] = (u8) (reg >> 16);
+ bp->mac_addr[4] = (u8) (reg >> 8);
+ bp->mac_addr[5] = (u8) reg;
+
+ bp->tx_ring_size = MAX_TX_DESC_CNT;
+ bp->rx_ring_size = 100;
+
+ bp->rx_csum = 1;
+
+ bp->rx_offset = sizeof(struct l2_fhdr) + 2;
+
+ bp->tx_quick_cons_trip_int = 20;
+ bp->tx_quick_cons_trip = 20;
+ bp->tx_ticks_int = 80;
+ bp->tx_ticks = 80;
+
+ bp->rx_quick_cons_trip_int = 6;
+ bp->rx_quick_cons_trip = 6;
+ bp->rx_ticks_int = 18;
+ bp->rx_ticks = 18;
+
+ bp->stats_ticks = 1000000 & 0xffff00;
+
+ bp->timer_interval = HZ;
+
+ /* Disable WOL support if we are running on a SERDES chip. */
+ if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT) {
+ bp->phy_flags |= PHY_SERDES_FLAG;
+ bp->flags |= NO_WOL_FLAG;
+ }
+
+ if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
+ bp->tx_quick_cons_trip_int =
+ bp->tx_quick_cons_trip;
+ bp->tx_ticks_int = bp->tx_ticks;
+ bp->rx_quick_cons_trip_int =
+ bp->rx_quick_cons_trip;
+ bp->rx_ticks_int = bp->rx_ticks;
+ bp->comp_prod_trip_int = bp->comp_prod_trip;
+ bp->com_ticks_int = bp->com_ticks;
+ bp->cmd_ticks_int = bp->cmd_ticks;
+ }
+
+ bp->autoneg = AUTONEG_SPEED | AUTONEG_FLOW_CTRL;
+ bp->req_line_speed = 0;
+ if (bp->phy_flags & PHY_SERDES_FLAG) {
+ bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg;
+ }
+ else {
+ bp->advertising = ETHTOOL_ALL_COPPER_SPEED | ADVERTISED_Autoneg;
+ }
+
+ bp->req_flow_ctrl = FLOW_CTRL_RX | FLOW_CTRL_TX;
+
+ return 0;
+
+err_out_unmap:
+ if (bp->regview) {
+ iounmap(bp->regview);
+ }
+
+err_out_release:
+ pci_release_regions(pdev);
+
+err_out_disable:
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+
+err_out:
+ return rc;
+}
+
+static int __devinit
+bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+ static int version_printed = 0;
+ struct net_device *dev = NULL;
+ struct bnx2 *bp;
+ int rc, i;
+
+ if (version_printed++ == 0)
+ printk(KERN_INFO "%s", version);
+
+ /* dev zeroed in init_etherdev */
+ dev = alloc_etherdev(sizeof(*bp));
+
+ if (!dev)
+ return -ENOMEM;
+
+ rc = bnx2_init_board(pdev, dev);
+ if (rc < 0) {
+ free_netdev(dev);
+ return rc;
+ }
+
+ dev->open = bnx2_open;
+ dev->hard_start_xmit = bnx2_start_xmit;
+ dev->stop = bnx2_close;
+ dev->get_stats = bnx2_get_stats;
+ dev->set_multicast_list = bnx2_set_rx_mode;
+ dev->do_ioctl = bnx2_ioctl;
+ dev->set_mac_address = bnx2_change_mac_addr;
+ dev->change_mtu = bnx2_change_mtu;
+ dev->tx_timeout = bnx2_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+#ifdef BCM_VLAN
+ dev->vlan_rx_register = bnx2_vlan_rx_register;
+ dev->vlan_rx_kill_vid = bnx2_vlan_rx_kill_vid;
+#endif
+ dev->poll = bnx2_poll;
+ dev->ethtool_ops = &bnx2_ethtool_ops;
+ dev->weight = 64;
+
+ bp = dev->priv;
+
+#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
+ dev->poll_controller = poll_bnx2;
+#endif
+
+ if ((rc = register_netdev(dev))) {
+ printk(KERN_ERR PFX "Cannot register net device\n");
+ if (bp->regview)
+ iounmap(bp->regview);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+ free_netdev(dev);
+ return rc;
+ }
+
+ pci_set_drvdata(pdev, dev);
+
+ memcpy(dev->dev_addr, bp->mac_addr, 6);
+ bp->name = board_info[ent->driver_data].name,
+ printk(KERN_INFO "%s: %s (%c%d) PCI%s %s %dMHz found at mem %lx, "
+ "IRQ %d, ",
+ dev->name,
+ bp->name,
+ ((CHIP_ID(bp) & 0xf000) >> 12) + 'A',
+ ((CHIP_ID(bp) & 0x0ff0) >> 4),
+ ((bp->flags & PCIX_FLAG) ? "-X" : ""),
+ ((bp->flags & PCI_32BIT_FLAG) ? "32-bit" : "64-bit"),
+ bp->bus_speed_mhz,
+ dev->base_addr,
+ bp->pdev->irq);
+
+ printk("node addr ");
+ for (i = 0; i < 6; i++)
+ printk("%2.2x", dev->dev_addr[i]);
+ printk("\n");
+
+ dev->features |= NETIF_F_SG;
+ if (bp->flags & USING_DAC_FLAG)
+ dev->features |= NETIF_F_HIGHDMA;
+ dev->features |= NETIF_F_IP_CSUM;
+#ifdef BCM_VLAN
+ dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+#endif
+#ifdef BCM_TSO
+ dev->features |= NETIF_F_TSO;
+#endif
+
+ netif_carrier_off(bp->dev);
+
+ return 0;
+}
+
+static void __devexit
+bnx2_remove_one(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct bnx2 *bp = dev->priv;
+
+ unregister_netdev(dev);
+
+ if (bp->regview)
+ iounmap(bp->regview);
+
+ free_netdev(dev);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+}
+
+static int
+bnx2_suspend(struct pci_dev *pdev, u32 state)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct bnx2 *bp = dev->priv;
+ u32 reset_code;
+
+ if (!netif_running(dev))
+ return 0;
+
+ bnx2_netif_stop(bp);
+ netif_device_detach(dev);
+ del_timer_sync(&bp->timer);
+ if (bp->wol)
+ reset_code = BNX2_DRV_MSG_CODE_SUSPEND_WOL;
+ else
+ reset_code = BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL;
+ bnx2_reset_chip(bp, reset_code);
+ bnx2_free_skbs(bp);
+ bnx2_set_power_state(bp, state);
+ return 0;
+}
+
+static int
+bnx2_resume(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct bnx2 *bp = dev->priv;
+
+ if (!netif_running(dev))
+ return 0;
+
+ bnx2_set_power_state(bp, 0);
+ netif_device_attach(dev);
+ bnx2_init_nic(bp);
+ bnx2_netif_start(bp);
+ return 0;
+}
+
+static struct pci_driver bnx2_pci_driver = {
+ name: DRV_MODULE_NAME,
+ id_table: bnx2_pci_tbl,
+ probe: bnx2_init_one,
+ remove: __devexit_p(bnx2_remove_one),
+ suspend: bnx2_suspend,
+ resume: bnx2_resume,
+};
+
+static int __init bnx2_init(void)
+{
+ return pci_module_init(&bnx2_pci_driver);
+}
+
+static void __exit bnx2_cleanup(void)
+{
+ pci_unregister_driver(&bnx2_pci_driver);
+}
+
+module_init(bnx2_init);
+module_exit(bnx2_cleanup);
+
+
+
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
new file mode 100644
index 00000000000..8214a2853d0
--- /dev/null
+++ b/drivers/net/bnx2.h
@@ -0,0 +1,4352 @@
+/* bnx2.h: Broadcom NX2 network driver.
+ *
+ * Copyright (c) 2004, 2005 Broadcom Corporation
+ *
+ * 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.
+ *
+ * Written by: Michael Chan (mchan@broadcom.com)
+ */
+
+
+#ifndef BNX2_H
+#define BNX2_H
+
+#include <linux/config.h>
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/dma-mapping.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <linux/delay.h>
+#include <asm/byteorder.h>
+#include <linux/time.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#ifdef NETIF_F_HW_VLAN_TX
+#include <linux/if_vlan.h>
+#define BCM_VLAN 1
+#endif
+#ifdef NETIF_F_TSO
+#include <net/ip.h>
+#include <net/tcp.h>
+#include <net/checksum.h>
+#define BCM_TSO 1
+#endif
+#include <linux/workqueue.h>
+#include <linux/crc32.h>
+
+/* Hardware data structures and register definitions automatically
+ * generated from RTL code. Do not modify.
+ */
+
+/*
+ * tx_bd definition
+ */
+struct tx_bd {
+ u32 tx_bd_haddr_hi;
+ u32 tx_bd_haddr_lo;
+ u32 tx_bd_mss_nbytes;
+ u32 tx_bd_vlan_tag_flags;
+ #define TX_BD_FLAGS_CONN_FAULT (1<<0)
+ #define TX_BD_FLAGS_TCP_UDP_CKSUM (1<<1)
+ #define TX_BD_FLAGS_IP_CKSUM (1<<2)
+ #define TX_BD_FLAGS_VLAN_TAG (1<<3)
+ #define TX_BD_FLAGS_COAL_NOW (1<<4)
+ #define TX_BD_FLAGS_DONT_GEN_CRC (1<<5)
+ #define TX_BD_FLAGS_END (1<<6)
+ #define TX_BD_FLAGS_START (1<<7)
+ #define TX_BD_FLAGS_SW_OPTION_WORD (0x1f<<8)
+ #define TX_BD_FLAGS_SW_FLAGS (1<<13)
+ #define TX_BD_FLAGS_SW_SNAP (1<<14)
+ #define TX_BD_FLAGS_SW_LSO (1<<15)
+
+};
+
+
+/*
+ * rx_bd definition
+ */
+struct rx_bd {
+ u32 rx_bd_haddr_hi;
+ u32 rx_bd_haddr_lo;
+ u32 rx_bd_len;
+ u32 rx_bd_flags;
+ #define RX_BD_FLAGS_NOPUSH (1<<0)
+ #define RX_BD_FLAGS_DUMMY (1<<1)
+ #define RX_BD_FLAGS_END (1<<2)
+ #define RX_BD_FLAGS_START (1<<3)
+
+};
+
+
+/*
+ * status_block definition
+ */
+struct status_block {
+ u32 status_attn_bits;
+ #define STATUS_ATTN_BITS_LINK_STATE (1L<<0)
+ #define STATUS_ATTN_BITS_TX_SCHEDULER_ABORT (1L<<1)
+ #define STATUS_ATTN_BITS_TX_BD_READ_ABORT (1L<<2)
+ #define STATUS_ATTN_BITS_TX_BD_CACHE_ABORT (1L<<3)
+ #define STATUS_ATTN_BITS_TX_PROCESSOR_ABORT (1L<<4)
+ #define STATUS_ATTN_BITS_TX_DMA_ABORT (1L<<5)
+ #define STATUS_ATTN_BITS_TX_PATCHUP_ABORT (1L<<6)
+ #define STATUS_ATTN_BITS_TX_ASSEMBLER_ABORT (1L<<7)
+ #define STATUS_ATTN_BITS_RX_PARSER_MAC_ABORT (1L<<8)
+ #define STATUS_ATTN_BITS_RX_PARSER_CATCHUP_ABORT (1L<<9)
+ #define STATUS_ATTN_BITS_RX_MBUF_ABORT (1L<<10)
+ #define STATUS_ATTN_BITS_RX_LOOKUP_ABORT (1L<<11)
+ #define STATUS_ATTN_BITS_RX_PROCESSOR_ABORT (1L<<12)
+ #define STATUS_ATTN_BITS_RX_V2P_ABORT (1L<<13)
+ #define STATUS_ATTN_BITS_RX_BD_CACHE_ABORT (1L<<14)
+ #define STATUS_ATTN_BITS_RX_DMA_ABORT (1L<<15)
+ #define STATUS_ATTN_BITS_COMPLETION_ABORT (1L<<16)
+ #define STATUS_ATTN_BITS_HOST_COALESCE_ABORT (1L<<17)
+ #define STATUS_ATTN_BITS_MAILBOX_QUEUE_ABORT (1L<<18)
+ #define STATUS_ATTN_BITS_CONTEXT_ABORT (1L<<19)
+ #define STATUS_ATTN_BITS_CMD_SCHEDULER_ABORT (1L<<20)
+ #define STATUS_ATTN_BITS_CMD_PROCESSOR_ABORT (1L<<21)
+ #define STATUS_ATTN_BITS_MGMT_PROCESSOR_ABORT (1L<<22)
+ #define STATUS_ATTN_BITS_MAC_ABORT (1L<<23)
+ #define STATUS_ATTN_BITS_TIMER_ABORT (1L<<24)
+ #define STATUS_ATTN_BITS_DMAE_ABORT (1L<<25)
+ #define STATUS_ATTN_BITS_FLSH_ABORT (1L<<26)
+ #define STATUS_ATTN_BITS_GRC_ABORT (1L<<27)
+ #define STATUS_ATTN_BITS_PARITY_ERROR (1L<<31)
+
+ u32 status_attn_bits_ack;
+#if defined(__BIG_ENDIAN)
+ u16 status_tx_quick_consumer_index0;
+ u16 status_tx_quick_consumer_index1;
+ u16 status_tx_quick_consumer_index2;
+ u16 status_tx_quick_consumer_index3;
+ u16 status_rx_quick_consumer_index0;
+ u16 status_rx_quick_consumer_index1;
+ u16 status_rx_quick_consumer_index2;
+ u16 status_rx_quick_consumer_index3;
+ u16 status_rx_quick_consumer_index4;
+ u16 status_rx_quick_consumer_index5;
+ u16 status_rx_quick_consumer_index6;
+ u16 status_rx_quick_consumer_index7;
+ u16 status_rx_quick_consumer_index8;
+ u16 status_rx_quick_consumer_index9;
+ u16 status_rx_quick_consumer_index10;
+ u16 status_rx_quick_consumer_index11;
+ u16 status_rx_quick_consumer_index12;
+ u16 status_rx_quick_consumer_index13;
+ u16 status_rx_quick_consumer_index14;
+ u16 status_rx_quick_consumer_index15;
+ u16 status_completion_producer_index;
+ u16 status_cmd_consumer_index;
+ u16 status_idx;
+ u16 status_unused;
+#elif defined(__LITTLE_ENDIAN)
+ u16 status_tx_quick_consumer_index1;
+ u16 status_tx_quick_consumer_index0;
+ u16 status_tx_quick_consumer_index3;
+ u16 status_tx_quick_consumer_index2;
+ u16 status_rx_quick_consumer_index1;
+ u16 status_rx_quick_consumer_index0;
+ u16 status_rx_quick_consumer_index3;
+ u16 status_rx_quick_consumer_index2;
+ u16 status_rx_quick_consumer_index5;
+ u16 status_rx_quick_consumer_index4;
+ u16 status_rx_quick_consumer_index7;
+ u16 status_rx_quick_consumer_index6;
+ u16 status_rx_quick_consumer_index9;
+ u16 status_rx_quick_consumer_index8;
+ u16 status_rx_quick_consumer_index11;
+ u16 status_rx_quick_consumer_index10;
+ u16 status_rx_quick_consumer_index13;
+ u16 status_rx_quick_consumer_index12;
+ u16 status_rx_quick_consumer_index15;
+ u16 status_rx_quick_consumer_index14;
+ u16 status_cmd_consumer_index;
+ u16 status_completion_producer_index;
+ u16 status_unused;
+ u16 status_idx;
+#endif
+};
+
+
+/*
+ * statistics_block definition
+ */
+struct statistics_block {
+ u32 stat_IfHCInOctets_hi;
+ u32 stat_IfHCInOctets_lo;
+ u32 stat_IfHCInBadOctets_hi;
+ u32 stat_IfHCInBadOctets_lo;
+ u32 stat_IfHCOutOctets_hi;
+ u32 stat_IfHCOutOctets_lo;
+ u32 stat_IfHCOutBadOctets_hi;
+ u32 stat_IfHCOutBadOctets_lo;
+ u32 stat_IfHCInUcastPkts_hi;
+ u32 stat_IfHCInUcastPkts_lo;
+ u32 stat_IfHCInMulticastPkts_hi;
+ u32 stat_IfHCInMulticastPkts_lo;
+ u32 stat_IfHCInBroadcastPkts_hi;
+ u32 stat_IfHCInBroadcastPkts_lo;
+ u32 stat_IfHCOutUcastPkts_hi;
+ u32 stat_IfHCOutUcastPkts_lo;
+ u32 stat_IfHCOutMulticastPkts_hi;
+ u32 stat_IfHCOutMulticastPkts_lo;
+ u32 stat_IfHCOutBroadcastPkts_hi;
+ u32 stat_IfHCOutBroadcastPkts_lo;
+ u32 stat_emac_tx_stat_dot3statsinternalmactransmiterrors;
+ u32 stat_Dot3StatsCarrierSenseErrors;
+ u32 stat_Dot3StatsFCSErrors;
+ u32 stat_Dot3StatsAlignmentErrors;
+ u32 stat_Dot3StatsSingleCollisionFrames;
+ u32 stat_Dot3StatsMultipleCollisionFrames;
+ u32 stat_Dot3StatsDeferredTransmissions;
+ u32 stat_Dot3StatsExcessiveCollisions;
+ u32 stat_Dot3StatsLateCollisions;
+ u32 stat_EtherStatsCollisions;
+ u32 stat_EtherStatsFragments;
+ u32 stat_EtherStatsJabbers;
+ u32 stat_EtherStatsUndersizePkts;
+ u32 stat_EtherStatsOverrsizePkts;
+ u32 stat_EtherStatsPktsRx64Octets;
+ u32 stat_EtherStatsPktsRx65Octetsto127Octets;
+ u32 stat_EtherStatsPktsRx128Octetsto255Octets;
+ u32 stat_EtherStatsPktsRx256Octetsto511Octets;
+ u32 stat_EtherStatsPktsRx512Octetsto1023Octets;
+ u32 stat_EtherStatsPktsRx1024Octetsto1522Octets;
+ u32 stat_EtherStatsPktsRx1523Octetsto9022Octets;
+ u32 stat_EtherStatsPktsTx64Octets;
+ u32 stat_EtherStatsPktsTx65Octetsto127Octets;
+ u32 stat_EtherStatsPktsTx128Octetsto255Octets;
+ u32 stat_EtherStatsPktsTx256Octetsto511Octets;
+ u32 stat_EtherStatsPktsTx512Octetsto1023Octets;
+ u32 stat_EtherStatsPktsTx1024Octetsto1522Octets;
+ u32 stat_EtherStatsPktsTx1523Octetsto9022Octets;
+ u32 stat_XonPauseFramesReceived;
+ u32 stat_XoffPauseFramesReceived;
+ u32 stat_OutXonSent;
+ u32 stat_OutXoffSent;
+ u32 stat_FlowControlDone;
+ u32 stat_MacControlFramesReceived;
+ u32 stat_XoffStateEntered;
+ u32 stat_IfInFramesL2FilterDiscards;
+ u32 stat_IfInRuleCheckerDiscards;
+ u32 stat_IfInFTQDiscards;
+ u32 stat_IfInMBUFDiscards;
+ u32 stat_IfInRuleCheckerP4Hit;
+ u32 stat_CatchupInRuleCheckerDiscards;
+ u32 stat_CatchupInFTQDiscards;
+ u32 stat_CatchupInMBUFDiscards;
+ u32 stat_CatchupInRuleCheckerP4Hit;
+ u32 stat_GenStat00;
+ u32 stat_GenStat01;
+ u32 stat_GenStat02;
+ u32 stat_GenStat03;
+ u32 stat_GenStat04;
+ u32 stat_GenStat05;
+ u32 stat_GenStat06;
+ u32 stat_GenStat07;
+ u32 stat_GenStat08;
+ u32 stat_GenStat09;
+ u32 stat_GenStat10;
+ u32 stat_GenStat11;
+ u32 stat_GenStat12;
+ u32 stat_GenStat13;
+ u32 stat_GenStat14;
+ u32 stat_GenStat15;
+};
+
+
+/*
+ * l2_fhdr definition
+ */
+struct l2_fhdr {
+#if defined(__BIG_ENDIAN)
+ u16 l2_fhdr_errors;
+ u16 l2_fhdr_status;
+#elif defined(__LITTLE_ENDIAN)
+ u16 l2_fhdr_status;
+ u16 l2_fhdr_errors;
+#endif
+ #define L2_FHDR_ERRORS_BAD_CRC (1<<1)
+ #define L2_FHDR_ERRORS_PHY_DECODE (1<<2)
+ #define L2_FHDR_ERRORS_ALIGNMENT (1<<3)
+ #define L2_FHDR_ERRORS_TOO_SHORT (1<<4)
+ #define L2_FHDR_ERRORS_GIANT_FRAME (1<<5)
+
+ #define L2_FHDR_STATUS_RULE_CLASS (0x7<<0)
+ #define L2_FHDR_STATUS_RULE_P2 (1<<3)
+ #define L2_FHDR_STATUS_RULE_P3 (1<<4)
+ #define L2_FHDR_STATUS_RULE_P4 (1<<5)
+ #define L2_FHDR_STATUS_L2_VLAN_TAG (1<<6)
+ #define L2_FHDR_STATUS_L2_LLC_SNAP (1<<7)
+ #define L2_FHDR_STATUS_RSS_HASH (1<<8)
+ #define L2_FHDR_STATUS_IP_DATAGRAM (1<<13)
+ #define L2_FHDR_STATUS_TCP_SEGMENT (1<<14)
+ #define L2_FHDR_STATUS_UDP_DATAGRAM (1<<15)
+
+ u32 l2_fhdr_hash;
+#if defined(__BIG_ENDIAN)
+ u16 l2_fhdr_pkt_len;
+ u16 l2_fhdr_vlan_tag;
+ u16 l2_fhdr_ip_xsum;
+ u16 l2_fhdr_tcp_udp_xsum;
+#elif defined(__LITTLE_ENDIAN)
+ u16 l2_fhdr_vlan_tag;
+ u16 l2_fhdr_pkt_len;
+ u16 l2_fhdr_tcp_udp_xsum;
+ u16 l2_fhdr_ip_xsum;
+#endif
+};
+
+
+/*
+ * l2_context definition
+ */
+#define BNX2_L2CTX_TYPE 0x00000000
+#define BNX2_L2CTX_TYPE_SIZE_L2 ((0xc0/0x20)<<16)
+#define BNX2_L2CTX_TYPE_TYPE (0xf<<28)
+#define BNX2_L2CTX_TYPE_TYPE_EMPTY (0<<28)
+#define BNX2_L2CTX_TYPE_TYPE_L2 (1<<28)
+
+#define BNX2_L2CTX_TX_HOST_BIDX 0x00000088
+#define BNX2_L2CTX_EST_NBD 0x00000088
+#define BNX2_L2CTX_CMD_TYPE 0x00000088
+#define BNX2_L2CTX_CMD_TYPE_TYPE (0xf<<24)
+#define BNX2_L2CTX_CMD_TYPE_TYPE_L2 (0<<24)
+#define BNX2_L2CTX_CMD_TYPE_TYPE_TCP (1<<24)
+
+#define BNX2_L2CTX_TX_HOST_BSEQ 0x00000090
+#define BNX2_L2CTX_TSCH_BSEQ 0x00000094
+#define BNX2_L2CTX_TBDR_BSEQ 0x00000098
+#define BNX2_L2CTX_TBDR_BOFF 0x0000009c
+#define BNX2_L2CTX_TBDR_BIDX 0x0000009c
+#define BNX2_L2CTX_TBDR_BHADDR_HI 0x000000a0
+#define BNX2_L2CTX_TBDR_BHADDR_LO 0x000000a4
+#define BNX2_L2CTX_TXP_BOFF 0x000000a8
+#define BNX2_L2CTX_TXP_BIDX 0x000000a8
+#define BNX2_L2CTX_TXP_BSEQ 0x000000ac
+
+
+/*
+ * l2_bd_chain_context definition
+ */
+#define BNX2_L2CTX_BD_PRE_READ 0x00000000
+#define BNX2_L2CTX_CTX_SIZE 0x00000000
+#define BNX2_L2CTX_CTX_TYPE 0x00000000
+#define BNX2_L2CTX_CTX_TYPE_SIZE_L2 ((0x20/20)<<16)
+#define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE (0xf<<28)
+#define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_UNDEFINED (0<<28)
+#define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE (1<<28)
+
+#define BNX2_L2CTX_HOST_BDIDX 0x00000004
+#define BNX2_L2CTX_HOST_BSEQ 0x00000008
+#define BNX2_L2CTX_NX_BSEQ 0x0000000c
+#define BNX2_L2CTX_NX_BDHADDR_HI 0x00000010
+#define BNX2_L2CTX_NX_BDHADDR_LO 0x00000014
+#define BNX2_L2CTX_NX_BDIDX 0x00000018
+
+
+/*
+ * pci_config_l definition
+ * offset: 0000
+ */
+#define BNX2_PCICFG_MISC_CONFIG 0x00000068
+#define BNX2_PCICFG_MISC_CONFIG_TARGET_BYTE_SWAP (1L<<2)
+#define BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP (1L<<3)
+#define BNX2_PCICFG_MISC_CONFIG_CLOCK_CTL_ENA (1L<<5)
+#define BNX2_PCICFG_MISC_CONFIG_TARGET_GRC_WORD_SWAP (1L<<6)
+#define BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA (1L<<7)
+#define BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ (1L<<8)
+#define BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY (1L<<9)
+#define BNX2_PCICFG_MISC_CONFIG_ASIC_METAL_REV (0xffL<<16)
+#define BNX2_PCICFG_MISC_CONFIG_ASIC_BASE_REV (0xfL<<24)
+#define BNX2_PCICFG_MISC_CONFIG_ASIC_ID (0xfL<<28)
+
+#define BNX2_PCICFG_MISC_STATUS 0x0000006c
+#define BNX2_PCICFG_MISC_STATUS_INTA_VALUE (1L<<0)
+#define BNX2_PCICFG_MISC_STATUS_32BIT_DET (1L<<1)
+#define BNX2_PCICFG_MISC_STATUS_M66EN (1L<<2)
+#define BNX2_PCICFG_MISC_STATUS_PCIX_DET (1L<<3)
+#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED (0x3L<<4)
+#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_66 (0L<<4)
+#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_100 (1L<<4)
+#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_133 (2L<<4)
+#define BNX2_PCICFG_MISC_STATUS_PCIX_SPEED_PCI_MODE (3L<<4)
+
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS 0x00000070
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET (0xfL<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ (0L<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ (1L<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ (2L<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ (3L<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ (4L<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ (5L<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ (6L<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ (7L<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW (0xfL<<0)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_DISABLE (1L<<6)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT (1L<<7)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC (0x7L<<8)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_UNDEF (0L<<8)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_12 (1L<<8)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_6 (2L<<8)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_62 (4L<<8)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PLAY_DEAD (1L<<11)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED (0xfL<<12)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_100 (0L<<12)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_80 (1L<<12)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_50 (2L<<12)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_40 (4L<<12)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_25 (8L<<12)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_CORE_CLK_PLL_STOP (1L<<16)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_PLL_STOP (1L<<17)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED_18 (1L<<18)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_USE_SPD_DET (1L<<19)
+#define BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_RESERVED (0xfffL<<20)
+
+#define BNX2_PCICFG_REG_WINDOW_ADDRESS 0x00000078
+#define BNX2_PCICFG_REG_WINDOW 0x00000080
+#define BNX2_PCICFG_INT_ACK_CMD 0x00000084
+#define BNX2_PCICFG_INT_ACK_CMD_INDEX (0xffffL<<0)
+#define BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID (1L<<16)
+#define BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM (1L<<17)
+#define BNX2_PCICFG_INT_ACK_CMD_MASK_INT (1L<<18)
+
+#define BNX2_PCICFG_STATUS_BIT_SET_CMD 0x00000088
+#define BNX2_PCICFG_STATUS_BIT_CLEAR_CMD 0x0000008c
+#define BNX2_PCICFG_MAILBOX_QUEUE_ADDR 0x00000090
+#define BNX2_PCICFG_MAILBOX_QUEUE_DATA 0x00000094
+
+
+/*
+ * pci_reg definition
+ * offset: 0x400
+ */
+#define BNX2_PCI_GRC_WINDOW_ADDR 0x00000400
+#define BNX2_PCI_GRC_WINDOW_ADDR_PCI_GRC_WINDOW_ADDR_VALUE (0x3ffffL<<8)
+
+#define BNX2_PCI_CONFIG_1 0x00000404
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY (0x7L<<8)
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_OFF (0L<<8)
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_16 (1L<<8)
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_32 (2L<<8)
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_64 (3L<<8)
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_128 (4L<<8)
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_256 (5L<<8)
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_512 (6L<<8)
+#define BNX2_PCI_CONFIG_1_READ_BOUNDARY_1024 (7L<<8)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY (0x7L<<11)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_OFF (0L<<11)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_16 (1L<<11)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_32 (2L<<11)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_64 (3L<<11)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_128 (4L<<11)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_256 (5L<<11)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_512 (6L<<11)
+#define BNX2_PCI_CONFIG_1_WRITE_BOUNDARY_1024 (7L<<11)
+
+#define BNX2_PCI_CONFIG_2 0x00000408
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE (0xfL<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_DISABLED (0L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_64K (1L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_128K (2L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_256K (3L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_512K (4L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_1M (5L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_2M (6L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_4M (7L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_8M (8L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_16M (9L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_32M (10L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_64M (11L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_128M (12L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_256M (13L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_512M (14L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_SIZE_1G (15L<<0)
+#define BNX2_PCI_CONFIG_2_BAR1_64ENA (1L<<4)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_RETRY (1L<<5)
+#define BNX2_PCI_CONFIG_2_CFG_CYCLE_RETRY (1L<<6)
+#define BNX2_PCI_CONFIG_2_FIRST_CFG_DONE (1L<<7)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE (0xffL<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_DISABLED (0L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_1K (1L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_2K (2L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_4K (3L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_8K (4L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_16K (5L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_32K (6L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_64K (7L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_128K (8L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_256K (9L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_512K (10L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_1M (11L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_2M (12L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_4M (13L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_8M (14L<<8)
+#define BNX2_PCI_CONFIG_2_EXP_ROM_SIZE_16M (15L<<8)
+#define BNX2_PCI_CONFIG_2_MAX_SPLIT_LIMIT (0x1fL<<16)
+#define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT (0x3L<<21)
+#define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_512 (0L<<21)
+#define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_1K (1L<<21)
+#define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_2K (2L<<21)
+#define BNX2_PCI_CONFIG_2_MAX_READ_LIMIT_4K (3L<<21)
+#define BNX2_PCI_CONFIG_2_FORCE_32_BIT_MSTR (1L<<23)
+#define BNX2_PCI_CONFIG_2_FORCE_32_BIT_TGT (1L<<24)
+#define BNX2_PCI_CONFIG_2_KEEP_REQ_ASSERT (1L<<25)
+
+#define BNX2_PCI_CONFIG_3 0x0000040c
+#define BNX2_PCI_CONFIG_3_STICKY_BYTE (0xffL<<0)
+#define BNX2_PCI_CONFIG_3_FORCE_PME (1L<<24)
+#define BNX2_PCI_CONFIG_3_PME_STATUS (1L<<25)
+#define BNX2_PCI_CONFIG_3_PME_ENABLE (1L<<26)
+#define BNX2_PCI_CONFIG_3_PM_STATE (0x3L<<27)
+#define BNX2_PCI_CONFIG_3_VAUX_PRESET (1L<<30)
+#define BNX2_PCI_CONFIG_3_PCI_POWER (1L<<31)
+
+#define BNX2_PCI_PM_DATA_A 0x00000410
+#define BNX2_PCI_PM_DATA_A_PM_DATA_0_PRG (0xffL<<0)
+#define BNX2_PCI_PM_DATA_A_PM_DATA_1_PRG (0xffL<<8)
+#define BNX2_PCI_PM_DATA_A_PM_DATA_2_PRG (0xffL<<16)
+#define BNX2_PCI_PM_DATA_A_PM_DATA_3_PRG (0xffL<<24)
+
+#define BNX2_PCI_PM_DATA_B 0x00000414
+#define BNX2_PCI_PM_DATA_B_PM_DATA_4_PRG (0xffL<<0)
+#define BNX2_PCI_PM_DATA_B_PM_DATA_5_PRG (0xffL<<8)
+#define BNX2_PCI_PM_DATA_B_PM_DATA_6_PRG (0xffL<<16)
+#define BNX2_PCI_PM_DATA_B_PM_DATA_7_PRG (0xffL<<24)
+
+#define BNX2_PCI_SWAP_DIAG0 0x00000418
+#define BNX2_PCI_SWAP_DIAG1 0x0000041c
+#define BNX2_PCI_EXP_ROM_ADDR 0x00000420
+#define BNX2_PCI_EXP_ROM_ADDR_ADDRESS (0x3fffffL<<2)
+#define BNX2_PCI_EXP_ROM_ADDR_REQ (1L<<31)
+
+#define BNX2_PCI_EXP_ROM_DATA 0x00000424
+#define BNX2_PCI_VPD_INTF 0x00000428
+#define BNX2_PCI_VPD_INTF_INTF_REQ (1L<<0)
+
+#define BNX2_PCI_VPD_ADDR_FLAG 0x0000042c
+#define BNX2_PCI_VPD_ADDR_FLAG_ADDRESS (0x1fff<<2)
+#define BNX2_PCI_VPD_ADDR_FLAG_WR (1<<15)
+
+#define BNX2_PCI_VPD_DATA 0x00000430
+#define BNX2_PCI_ID_VAL1 0x00000434
+#define BNX2_PCI_ID_VAL1_DEVICE_ID (0xffffL<<0)
+#define BNX2_PCI_ID_VAL1_VENDOR_ID (0xffffL<<16)
+
+#define BNX2_PCI_ID_VAL2 0x00000438
+#define BNX2_PCI_ID_VAL2_SUBSYSTEM_VENDOR_ID (0xffffL<<0)
+#define BNX2_PCI_ID_VAL2_SUBSYSTEM_ID (0xffffL<<16)
+
+#define BNX2_PCI_ID_VAL3 0x0000043c
+#define BNX2_PCI_ID_VAL3_CLASS_CODE (0xffffffL<<0)
+#define BNX2_PCI_ID_VAL3_REVISION_ID (0xffL<<24)
+
+#define BNX2_PCI_ID_VAL4 0x00000440
+#define BNX2_PCI_ID_VAL4_CAP_ENA (0xfL<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_0 (0L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_1 (1L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_2 (2L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_3 (3L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_4 (4L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_5 (5L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_6 (6L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_7 (7L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_8 (8L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_9 (9L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_10 (10L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_11 (11L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_12 (12L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_13 (13L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_14 (14L<<0)
+#define BNX2_PCI_ID_VAL4_CAP_ENA_15 (15L<<0)
+#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG (0x3L<<6)
+#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_0 (0L<<6)
+#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_1 (1L<<6)
+#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_2 (2L<<6)
+#define BNX2_PCI_ID_VAL4_PM_SCALE_PRG_3 (3L<<6)
+#define BNX2_PCI_ID_VAL4_MSI_LIMIT (0x7L<<9)
+#define BNX2_PCI_ID_VAL4_MSI_ADVERTIZE (0x7L<<12)
+#define BNX2_PCI_ID_VAL4_MSI_ENABLE (1L<<15)
+#define BNX2_PCI_ID_VAL4_MAX_64_ADVERTIZE (1L<<16)
+#define BNX2_PCI_ID_VAL4_MAX_133_ADVERTIZE (1L<<17)
+#define BNX2_PCI_ID_VAL4_MAX_MEM_READ_SIZE (0x3L<<21)
+#define BNX2_PCI_ID_VAL4_MAX_SPLIT_SIZE (0x7L<<23)
+#define BNX2_PCI_ID_VAL4_MAX_CUMULATIVE_SIZE (0x7L<<26)
+
+#define BNX2_PCI_ID_VAL5 0x00000444
+#define BNX2_PCI_ID_VAL5_D1_SUPPORT (1L<<0)
+#define BNX2_PCI_ID_VAL5_D2_SUPPORT (1L<<1)
+#define BNX2_PCI_ID_VAL5_PME_IN_D0 (1L<<2)
+#define BNX2_PCI_ID_VAL5_PME_IN_D1 (1L<<3)
+#define BNX2_PCI_ID_VAL5_PME_IN_D2 (1L<<4)
+#define BNX2_PCI_ID_VAL5_PME_IN_D3_HOT (1L<<5)
+
+#define BNX2_PCI_PCIX_EXTENDED_STATUS 0x00000448
+#define BNX2_PCI_PCIX_EXTENDED_STATUS_NO_SNOOP (1L<<8)
+#define BNX2_PCI_PCIX_EXTENDED_STATUS_LONG_BURST (1L<<9)
+#define BNX2_PCI_PCIX_EXTENDED_STATUS_SPLIT_COMP_MSG_CLASS (0xfL<<16)
+#define BNX2_PCI_PCIX_EXTENDED_STATUS_SPLIT_COMP_MSG_IDX (0xffL<<24)
+
+#define BNX2_PCI_ID_VAL6 0x0000044c
+#define BNX2_PCI_ID_VAL6_MAX_LAT (0xffL<<0)
+#define BNX2_PCI_ID_VAL6_MIN_GNT (0xffL<<8)
+#define BNX2_PCI_ID_VAL6_BIST (0xffL<<16)
+
+#define BNX2_PCI_MSI_DATA 0x00000450
+#define BNX2_PCI_MSI_DATA_PCI_MSI_DATA (0xffffL<<0)
+
+#define BNX2_PCI_MSI_ADDR_H 0x00000454
+#define BNX2_PCI_MSI_ADDR_L 0x00000458
+
+
+/*
+ * misc_reg definition
+ * offset: 0x800
+ */
+#define BNX2_MISC_COMMAND 0x00000800
+#define BNX2_MISC_COMMAND_ENABLE_ALL (1L<<0)
+#define BNX2_MISC_COMMAND_DISABLE_ALL (1L<<1)
+#define BNX2_MISC_COMMAND_CORE_RESET (1L<<4)
+#define BNX2_MISC_COMMAND_HARD_RESET (1L<<5)
+#define BNX2_MISC_COMMAND_PAR_ERROR (1L<<8)
+#define BNX2_MISC_COMMAND_PAR_ERR_RAM (0x7fL<<16)
+
+#define BNX2_MISC_CFG 0x00000804
+#define BNX2_MISC_CFG_PCI_GRC_TMOUT (1L<<0)
+#define BNX2_MISC_CFG_NVM_WR_EN (0x3L<<1)
+#define BNX2_MISC_CFG_NVM_WR_EN_PROTECT (0L<<1)
+#define BNX2_MISC_CFG_NVM_WR_EN_PCI (1L<<1)
+#define BNX2_MISC_CFG_NVM_WR_EN_ALLOW (2L<<1)
+#define BNX2_MISC_CFG_NVM_WR_EN_ALLOW2 (3L<<1)
+#define BNX2_MISC_CFG_BIST_EN (1L<<3)
+#define BNX2_MISC_CFG_CK25_OUT_ALT_SRC (1L<<4)
+#define BNX2_MISC_CFG_BYPASS_BSCAN (1L<<5)
+#define BNX2_MISC_CFG_BYPASS_EJTAG (1L<<6)
+#define BNX2_MISC_CFG_CLK_CTL_OVERRIDE (1L<<7)
+#define BNX2_MISC_CFG_LEDMODE (0x3L<<8)
+#define BNX2_MISC_CFG_LEDMODE_MAC (0L<<8)
+#define BNX2_MISC_CFG_LEDMODE_GPHY1 (1L<<8)
+#define BNX2_MISC_CFG_LEDMODE_GPHY2 (2L<<8)
+
+#define BNX2_MISC_ID 0x00000808
+#define BNX2_MISC_ID_BOND_ID (0xfL<<0)
+#define BNX2_MISC_ID_CHIP_METAL (0xffL<<4)
+#define BNX2_MISC_ID_CHIP_REV (0xfL<<12)
+#define BNX2_MISC_ID_CHIP_NUM (0xffffL<<16)
+
+#define BNX2_MISC_ENABLE_STATUS_BITS 0x0000080c
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_SCHEDULER_ENABLE (1L<<0)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_BD_READ_ENABLE (1L<<1)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_BD_CACHE_ENABLE (1L<<2)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_PROCESSOR_ENABLE (1L<<3)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_DMA_ENABLE (1L<<4)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_PATCHUP_ENABLE (1L<<5)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_PAYLOAD_Q_ENABLE (1L<<6)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_HEADER_Q_ENABLE (1L<<7)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TX_ASSEMBLER_ENABLE (1L<<8)
+#define BNX2_MISC_ENABLE_STATUS_BITS_EMAC_ENABLE (1L<<9)
+#define BNX2_MISC_ENABLE_STATUS_BITS_RX_PARSER_MAC_ENABLE (1L<<10)
+#define BNX2_MISC_ENABLE_STATUS_BITS_RX_PARSER_CATCHUP_ENABLE (1L<<11)
+#define BNX2_MISC_ENABLE_STATUS_BITS_RX_MBUF_ENABLE (1L<<12)
+#define BNX2_MISC_ENABLE_STATUS_BITS_RX_LOOKUP_ENABLE (1L<<13)
+#define BNX2_MISC_ENABLE_STATUS_BITS_RX_PROCESSOR_ENABLE (1L<<14)
+#define BNX2_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE (1L<<15)
+#define BNX2_MISC_ENABLE_STATUS_BITS_RX_BD_CACHE_ENABLE (1L<<16)
+#define BNX2_MISC_ENABLE_STATUS_BITS_RX_DMA_ENABLE (1L<<17)
+#define BNX2_MISC_ENABLE_STATUS_BITS_COMPLETION_ENABLE (1L<<18)
+#define BNX2_MISC_ENABLE_STATUS_BITS_HOST_COALESCE_ENABLE (1L<<19)
+#define BNX2_MISC_ENABLE_STATUS_BITS_MAILBOX_QUEUE_ENABLE (1L<<20)
+#define BNX2_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE (1L<<21)
+#define BNX2_MISC_ENABLE_STATUS_BITS_CMD_SCHEDULER_ENABLE (1L<<22)
+#define BNX2_MISC_ENABLE_STATUS_BITS_CMD_PROCESSOR_ENABLE (1L<<23)
+#define BNX2_MISC_ENABLE_STATUS_BITS_MGMT_PROCESSOR_ENABLE (1L<<24)
+#define BNX2_MISC_ENABLE_STATUS_BITS_TIMER_ENABLE (1L<<25)
+#define BNX2_MISC_ENABLE_STATUS_BITS_DMA_ENGINE_ENABLE (1L<<26)
+#define BNX2_MISC_ENABLE_STATUS_BITS_UMP_ENABLE (1L<<27)
+
+#define BNX2_MISC_ENABLE_SET_BITS 0x00000810
+#define BNX2_MISC_ENABLE_SET_BITS_TX_SCHEDULER_ENABLE (1L<<0)
+#define BNX2_MISC_ENABLE_SET_BITS_TX_BD_READ_ENABLE (1L<<1)
+#define BNX2_MISC_ENABLE_SET_BITS_TX_BD_CACHE_ENABLE (1L<<2)
+#define BNX2_MISC_ENABLE_SET_BITS_TX_PROCESSOR_ENABLE (1L<<3)
+#define BNX2_MISC_ENABLE_SET_BITS_TX_DMA_ENABLE (1L<<4)
+#define BNX2_MISC_ENABLE_SET_BITS_TX_PATCHUP_ENABLE (1L<<5)
+#define BNX2_MISC_ENABLE_SET_BITS_TX_PAYLOAD_Q_ENABLE (1L<<6)
+#define BNX2_MISC_ENABLE_SET_BITS_TX_HEADER_Q_ENABLE (1L<<7)
+#define BNX2_MISC_ENABLE_SET_BITS_TX_ASSEMBLER_ENABLE (1L<<8)
+#define BNX2_MISC_ENABLE_SET_BITS_EMAC_ENABLE (1L<<9)
+#define BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_MAC_ENABLE (1L<<10)
+#define BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_CATCHUP_ENABLE (1L<<11)
+#define BNX2_MISC_ENABLE_SET_BITS_RX_MBUF_ENABLE (1L<<12)
+#define BNX2_MISC_ENABLE_SET_BITS_RX_LOOKUP_ENABLE (1L<<13)
+#define BNX2_MISC_ENABLE_SET_BITS_RX_PROCESSOR_ENABLE (1L<<14)
+#define BNX2_MISC_ENABLE_SET_BITS_RX_V2P_ENABLE (1L<<15)
+#define BNX2_MISC_ENABLE_SET_BITS_RX_BD_CACHE_ENABLE (1L<<16)
+#define BNX2_MISC_ENABLE_SET_BITS_RX_DMA_ENABLE (1L<<17)
+#define BNX2_MISC_ENABLE_SET_BITS_COMPLETION_ENABLE (1L<<18)
+#define BNX2_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE (1L<<19)
+#define BNX2_MISC_ENABLE_SET_BITS_MAILBOX_QUEUE_ENABLE (1L<<20)
+#define BNX2_MISC_ENABLE_SET_BITS_CONTEXT_ENABLE (1L<<21)
+#define BNX2_MISC_ENABLE_SET_BITS_CMD_SCHEDULER_ENABLE (1L<<22)
+#define BNX2_MISC_ENABLE_SET_BITS_CMD_PROCESSOR_ENABLE (1L<<23)
+#define BNX2_MISC_ENABLE_SET_BITS_MGMT_PROCESSOR_ENABLE (1L<<24)
+#define BNX2_MISC_ENABLE_SET_BITS_TIMER_ENABLE (1L<<25)
+#define BNX2_MISC_ENABLE_SET_BITS_DMA_ENGINE_ENABLE (1L<<26)
+#define BNX2_MISC_ENABLE_SET_BITS_UMP_ENABLE (1L<<27)
+
+#define BNX2_MISC_ENABLE_CLR_BITS 0x00000814
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_SCHEDULER_ENABLE (1L<<0)
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_BD_READ_ENABLE (1L<<1)
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_BD_CACHE_ENABLE (1L<<2)
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_PROCESSOR_ENABLE (1L<<3)
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE (1L<<4)
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_PATCHUP_ENABLE (1L<<5)
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_PAYLOAD_Q_ENABLE (1L<<6)
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_HEADER_Q_ENABLE (1L<<7)
+#define BNX2_MISC_ENABLE_CLR_BITS_TX_ASSEMBLER_ENABLE (1L<<8)
+#define BNX2_MISC_ENABLE_CLR_BITS_EMAC_ENABLE (1L<<9)
+#define BNX2_MISC_ENABLE_CLR_BITS_RX_PARSER_MAC_ENABLE (1L<<10)
+#define BNX2_MISC_ENABLE_CLR_BITS_RX_PARSER_CATCHUP_ENABLE (1L<<11)
+#define BNX2_MISC_ENABLE_CLR_BITS_RX_MBUF_ENABLE (1L<<12)
+#define BNX2_MISC_ENABLE_CLR_BITS_RX_LOOKUP_ENABLE (1L<<13)
+#define BNX2_MISC_ENABLE_CLR_BITS_RX_PROCESSOR_ENABLE (1L<<14)
+#define BNX2_MISC_ENABLE_CLR_BITS_RX_V2P_ENABLE (1L<<15)
+#define BNX2_MISC_ENABLE_CLR_BITS_RX_BD_CACHE_ENABLE (1L<<16)
+#define BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE (1L<<17)
+#define BNX2_MISC_ENABLE_CLR_BITS_COMPLETION_ENABLE (1L<<18)
+#define BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE (1L<<19)
+#define BNX2_MISC_ENABLE_CLR_BITS_MAILBOX_QUEUE_ENABLE (1L<<20)
+#define BNX2_MISC_ENABLE_CLR_BITS_CONTEXT_ENABLE (1L<<21)
+#define BNX2_MISC_ENABLE_CLR_BITS_CMD_SCHEDULER_ENABLE (1L<<22)
+#define BNX2_MISC_ENABLE_CLR_BITS_CMD_PROCESSOR_ENABLE (1L<<23)
+#define BNX2_MISC_ENABLE_CLR_BITS_MGMT_PROCESSOR_ENABLE (1L<<24)
+#define BNX2_MISC_ENABLE_CLR_BITS_TIMER_ENABLE (1L<<25)
+#define BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE (1L<<26)
+#define BNX2_MISC_ENABLE_CLR_BITS_UMP_ENABLE (1L<<27)
+
+#define BNX2_MISC_CLOCK_CONTROL_BITS 0x00000818
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET (0xfL<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ (0L<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ (1L<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ (2L<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ (3L<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ (4L<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ (5L<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ (6L<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ (7L<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW (0xfL<<0)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_DISABLE (1L<<6)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT (1L<<7)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC (0x7L<<8)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_UNDEF (0L<<8)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_12 (1L<<8)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_6 (2L<<8)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_ALT_SRC_62 (4L<<8)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PLAY_DEAD (1L<<11)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED (0xfL<<12)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_100 (0L<<12)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_80 (1L<<12)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_50 (2L<<12)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_40 (4L<<12)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_SPEED_25 (8L<<12)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_CORE_CLK_PLL_STOP (1L<<16)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_PCI_PLL_STOP (1L<<17)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED_18 (1L<<18)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_USE_SPD_DET (1L<<19)
+#define BNX2_MISC_CLOCK_CONTROL_BITS_RESERVED (0xfffL<<20)
+
+#define BNX2_MISC_GPIO 0x0000081c
+#define BNX2_MISC_GPIO_VALUE (0xffL<<0)
+#define BNX2_MISC_GPIO_SET (0xffL<<8)
+#define BNX2_MISC_GPIO_CLR (0xffL<<16)
+#define BNX2_MISC_GPIO_FLOAT (0xffL<<24)
+
+#define BNX2_MISC_GPIO_INT 0x00000820
+#define BNX2_MISC_GPIO_INT_INT_STATE (0xfL<<0)
+#define BNX2_MISC_GPIO_INT_OLD_VALUE (0xfL<<8)
+#define BNX2_MISC_GPIO_INT_OLD_SET (0xfL<<16)
+#define BNX2_MISC_GPIO_INT_OLD_CLR (0xfL<<24)
+
+#define BNX2_MISC_CONFIG_LFSR 0x00000824
+#define BNX2_MISC_CONFIG_LFSR_DIV (0xffffL<<0)
+
+#define BNX2_MISC_LFSR_MASK_BITS 0x00000828
+#define BNX2_MISC_LFSR_MASK_BITS_TX_SCHEDULER_ENABLE (1L<<0)
+#define BNX2_MISC_LFSR_MASK_BITS_TX_BD_READ_ENABLE (1L<<1)
+#define BNX2_MISC_LFSR_MASK_BITS_TX_BD_CACHE_ENABLE (1L<<2)
+#define BNX2_MISC_LFSR_MASK_BITS_TX_PROCESSOR_ENABLE (1L<<3)
+#define BNX2_MISC_LFSR_MASK_BITS_TX_DMA_ENABLE (1L<<4)
+#define BNX2_MISC_LFSR_MASK_BITS_TX_PATCHUP_ENABLE (1L<<5)
+#define BNX2_MISC_LFSR_MASK_BITS_TX_PAYLOAD_Q_ENABLE (1L<<6)
+#define BNX2_MISC_LFSR_MASK_BITS_TX_HEADER_Q_ENABLE (1L<<7)
+#define BNX2_MISC_LFSR_MASK_BITS_TX_ASSEMBLER_ENABLE (1L<<8)
+#define BNX2_MISC_LFSR_MASK_BITS_EMAC_ENABLE (1L<<9)
+#define BNX2_MISC_LFSR_MASK_BITS_RX_PARSER_MAC_ENABLE (1L<<10)
+#define BNX2_MISC_LFSR_MASK_BITS_RX_PARSER_CATCHUP_ENABLE (1L<<11)
+#define BNX2_MISC_LFSR_MASK_BITS_RX_MBUF_ENABLE (1L<<12)
+#define BNX2_MISC_LFSR_MASK_BITS_RX_LOOKUP_ENABLE (1L<<13)
+#define BNX2_MISC_LFSR_MASK_BITS_RX_PROCESSOR_ENABLE (1L<<14)
+#define BNX2_MISC_LFSR_MASK_BITS_RX_V2P_ENABLE (1L<<15)
+#define BNX2_MISC_LFSR_MASK_BITS_RX_BD_CACHE_ENABLE (1L<<16)
+#define BNX2_MISC_LFSR_MASK_BITS_RX_DMA_ENABLE (1L<<17)
+#define BNX2_MISC_LFSR_MASK_BITS_COMPLETION_ENABLE (1L<<18)
+#define BNX2_MISC_LFSR_MASK_BITS_HOST_COALESCE_ENABLE (1L<<19)
+#define BNX2_MISC_LFSR_MASK_BITS_MAILBOX_QUEUE_ENABLE (1L<<20)
+#define BNX2_MISC_LFSR_MASK_BITS_CONTEXT_ENABLE (1L<<21)
+#define BNX2_MISC_LFSR_MASK_BITS_CMD_SCHEDULER_ENABLE (1L<<22)
+#define BNX2_MISC_LFSR_MASK_BITS_CMD_PROCESSOR_ENABLE (1L<<23)
+#define BNX2_MISC_LFSR_MASK_BITS_MGMT_PROCESSOR_ENABLE (1L<<24)
+#define BNX2_MISC_LFSR_MASK_BITS_TIMER_ENABLE (1L<<25)
+#define BNX2_MISC_LFSR_MASK_BITS_DMA_ENGINE_ENABLE (1L<<26)
+#define BNX2_MISC_LFSR_MASK_BITS_UMP_ENABLE (1L<<27)
+
+#define BNX2_MISC_ARB_REQ0 0x0000082c
+#define BNX2_MISC_ARB_REQ1 0x00000830
+#define BNX2_MISC_ARB_REQ2 0x00000834
+#define BNX2_MISC_ARB_REQ3 0x00000838
+#define BNX2_MISC_ARB_REQ4 0x0000083c
+#define BNX2_MISC_ARB_FREE0 0x00000840
+#define BNX2_MISC_ARB_FREE1 0x00000844
+#define BNX2_MISC_ARB_FREE2 0x00000848
+#define BNX2_MISC_ARB_FREE3 0x0000084c
+#define BNX2_MISC_ARB_FREE4 0x00000850
+#define BNX2_MISC_ARB_REQ_STATUS0 0x00000854
+#define BNX2_MISC_ARB_REQ_STATUS1 0x00000858
+#define BNX2_MISC_ARB_REQ_STATUS2 0x0000085c
+#define BNX2_MISC_ARB_REQ_STATUS3 0x00000860
+#define BNX2_MISC_ARB_REQ_STATUS4 0x00000864
+#define BNX2_MISC_ARB_GNT0 0x00000868
+#define BNX2_MISC_ARB_GNT0_0 (0x7L<<0)
+#define BNX2_MISC_ARB_GNT0_1 (0x7L<<4)
+#define BNX2_MISC_ARB_GNT0_2 (0x7L<<8)
+#define BNX2_MISC_ARB_GNT0_3 (0x7L<<12)
+#define BNX2_MISC_ARB_GNT0_4 (0x7L<<16)
+#define BNX2_MISC_ARB_GNT0_5 (0x7L<<20)
+#define BNX2_MISC_ARB_GNT0_6 (0x7L<<24)
+#define BNX2_MISC_ARB_GNT0_7 (0x7L<<28)
+
+#define BNX2_MISC_ARB_GNT1 0x0000086c
+#define BNX2_MISC_ARB_GNT1_8 (0x7L<<0)
+#define BNX2_MISC_ARB_GNT1_9 (0x7L<<4)
+#define BNX2_MISC_ARB_GNT1_10 (0x7L<<8)
+#define BNX2_MISC_ARB_GNT1_11 (0x7L<<12)
+#define BNX2_MISC_ARB_GNT1_12 (0x7L<<16)
+#define BNX2_MISC_ARB_GNT1_13 (0x7L<<20)
+#define BNX2_MISC_ARB_GNT1_14 (0x7L<<24)
+#define BNX2_MISC_ARB_GNT1_15 (0x7L<<28)
+
+#define BNX2_MISC_ARB_GNT2 0x00000870
+#define BNX2_MISC_ARB_GNT2_16 (0x7L<<0)
+#define BNX2_MISC_ARB_GNT2_17 (0x7L<<4)
+#define BNX2_MISC_ARB_GNT2_18 (0x7L<<8)
+#define BNX2_MISC_ARB_GNT2_19 (0x7L<<12)
+#define BNX2_MISC_ARB_GNT2_20 (0x7L<<16)
+#define BNX2_MISC_ARB_GNT2_21 (0x7L<<20)
+#define BNX2_MISC_ARB_GNT2_22 (0x7L<<24)
+#define BNX2_MISC_ARB_GNT2_23 (0x7L<<28)
+
+#define BNX2_MISC_ARB_GNT3 0x00000874
+#define BNX2_MISC_ARB_GNT3_24 (0x7L<<0)
+#define BNX2_MISC_ARB_GNT3_25 (0x7L<<4)
+#define BNX2_MISC_ARB_GNT3_26 (0x7L<<8)
+#define BNX2_MISC_ARB_GNT3_27 (0x7L<<12)
+#define BNX2_MISC_ARB_GNT3_28 (0x7L<<16)
+#define BNX2_MISC_ARB_GNT3_29 (0x7L<<20)
+#define BNX2_MISC_ARB_GNT3_30 (0x7L<<24)
+#define BNX2_MISC_ARB_GNT3_31 (0x7L<<28)
+
+#define BNX2_MISC_PRBS_CONTROL 0x00000878
+#define BNX2_MISC_PRBS_CONTROL_EN (1L<<0)
+#define BNX2_MISC_PRBS_CONTROL_RSTB (1L<<1)
+#define BNX2_MISC_PRBS_CONTROL_INV (1L<<2)
+#define BNX2_MISC_PRBS_CONTROL_ERR_CLR (1L<<3)
+#define BNX2_MISC_PRBS_CONTROL_ORDER (0x3L<<4)
+#define BNX2_MISC_PRBS_CONTROL_ORDER_7TH (0L<<4)
+#define BNX2_MISC_PRBS_CONTROL_ORDER_15TH (1L<<4)
+#define BNX2_MISC_PRBS_CONTROL_ORDER_23RD (2L<<4)
+#define BNX2_MISC_PRBS_CONTROL_ORDER_31ST (3L<<4)
+
+#define BNX2_MISC_PRBS_STATUS 0x0000087c
+#define BNX2_MISC_PRBS_STATUS_LOCK (1L<<0)
+#define BNX2_MISC_PRBS_STATUS_STKY (1L<<1)
+#define BNX2_MISC_PRBS_STATUS_ERRORS (0x3fffL<<2)
+#define BNX2_MISC_PRBS_STATUS_STATE (0xfL<<16)
+
+#define BNX2_MISC_SM_ASF_CONTROL 0x00000880
+#define BNX2_MISC_SM_ASF_CONTROL_ASF_RST (1L<<0)
+#define BNX2_MISC_SM_ASF_CONTROL_TSC_EN (1L<<1)
+#define BNX2_MISC_SM_ASF_CONTROL_WG_TO (1L<<2)
+#define BNX2_MISC_SM_ASF_CONTROL_HB_TO (1L<<3)
+#define BNX2_MISC_SM_ASF_CONTROL_PA_TO (1L<<4)
+#define BNX2_MISC_SM_ASF_CONTROL_PL_TO (1L<<5)
+#define BNX2_MISC_SM_ASF_CONTROL_RT_TO (1L<<6)
+#define BNX2_MISC_SM_ASF_CONTROL_SMB_EVENT (1L<<7)
+#define BNX2_MISC_SM_ASF_CONTROL_RES (0xfL<<8)
+#define BNX2_MISC_SM_ASF_CONTROL_SMB_EN (1L<<12)
+#define BNX2_MISC_SM_ASF_CONTROL_SMB_BB_EN (1L<<13)
+#define BNX2_MISC_SM_ASF_CONTROL_SMB_NO_ADDR_FILT (1L<<14)
+#define BNX2_MISC_SM_ASF_CONTROL_SMB_AUTOREAD (1L<<15)
+#define BNX2_MISC_SM_ASF_CONTROL_NIC_SMB_ADDR1 (0x3fL<<16)
+#define BNX2_MISC_SM_ASF_CONTROL_NIC_SMB_ADDR2 (0x3fL<<24)
+#define BNX2_MISC_SM_ASF_CONTROL_EN_NIC_SMB_ADDR_0 (1L<<30)
+#define BNX2_MISC_SM_ASF_CONTROL_SMB_EARLY_ATTN (1L<<31)
+
+#define BNX2_MISC_SMB_IN 0x00000884
+#define BNX2_MISC_SMB_IN_DAT_IN (0xffL<<0)
+#define BNX2_MISC_SMB_IN_RDY (1L<<8)
+#define BNX2_MISC_SMB_IN_DONE (1L<<9)
+#define BNX2_MISC_SMB_IN_FIRSTBYTE (1L<<10)
+#define BNX2_MISC_SMB_IN_STATUS (0x7L<<11)
+#define BNX2_MISC_SMB_IN_STATUS_OK (0x0L<<11)
+#define BNX2_MISC_SMB_IN_STATUS_PEC (0x1L<<11)
+#define BNX2_MISC_SMB_IN_STATUS_OFLOW (0x2L<<11)
+#define BNX2_MISC_SMB_IN_STATUS_STOP (0x3L<<11)
+#define BNX2_MISC_SMB_IN_STATUS_TIMEOUT (0x4L<<11)
+
+#define BNX2_MISC_SMB_OUT 0x00000888
+#define BNX2_MISC_SMB_OUT_DAT_OUT (0xffL<<0)
+#define BNX2_MISC_SMB_OUT_RDY (1L<<8)
+#define BNX2_MISC_SMB_OUT_START (1L<<9)
+#define BNX2_MISC_SMB_OUT_LAST (1L<<10)
+#define BNX2_MISC_SMB_OUT_ACC_TYPE (1L<<11)
+#define BNX2_MISC_SMB_OUT_ENB_PEC (1L<<12)
+#define BNX2_MISC_SMB_OUT_GET_RX_LEN (1L<<13)
+#define BNX2_MISC_SMB_OUT_SMB_READ_LEN (0x3fL<<14)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS (0xfL<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_OK (0L<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_FIRST_NACK (1L<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_SUB_NACK (9L<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_UFLOW (2L<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_STOP (3L<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_TIMEOUT (4L<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_FIRST_LOST (5L<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_SUB_LOST (0xdL<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_STATUS_BADACK (0x6L<<20)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_SLAVEMODE (1L<<24)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_DAT_EN (1L<<25)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_DAT_IN (1L<<26)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_CLK_EN (1L<<27)
+#define BNX2_MISC_SMB_OUT_SMB_OUT_CLK_IN (1L<<28)
+
+#define BNX2_MISC_SMB_WATCHDOG 0x0000088c
+#define BNX2_MISC_SMB_WATCHDOG_WATCHDOG (0xffffL<<0)
+
+#define BNX2_MISC_SMB_HEARTBEAT 0x00000890
+#define BNX2_MISC_SMB_HEARTBEAT_HEARTBEAT (0xffffL<<0)
+
+#define BNX2_MISC_SMB_POLL_ASF 0x00000894
+#define BNX2_MISC_SMB_POLL_ASF_POLL_ASF (0xffffL<<0)
+
+#define BNX2_MISC_SMB_POLL_LEGACY 0x00000898
+#define BNX2_MISC_SMB_POLL_LEGACY_POLL_LEGACY (0xffffL<<0)
+
+#define BNX2_MISC_SMB_RETRAN 0x0000089c
+#define BNX2_MISC_SMB_RETRAN_RETRAN (0xffL<<0)
+
+#define BNX2_MISC_SMB_TIMESTAMP 0x000008a0
+#define BNX2_MISC_SMB_TIMESTAMP_TIMESTAMP (0xffffffffL<<0)
+
+#define BNX2_MISC_PERR_ENA0 0x000008a4
+#define BNX2_MISC_PERR_ENA0_COM_MISC_CTXC (1L<<0)
+#define BNX2_MISC_PERR_ENA0_COM_MISC_REGF (1L<<1)
+#define BNX2_MISC_PERR_ENA0_COM_MISC_SCPAD (1L<<2)
+#define BNX2_MISC_PERR_ENA0_CP_MISC_CTXC (1L<<3)
+#define BNX2_MISC_PERR_ENA0_CP_MISC_REGF (1L<<4)
+#define BNX2_MISC_PERR_ENA0_CP_MISC_SCPAD (1L<<5)
+#define BNX2_MISC_PERR_ENA0_CS_MISC_TMEM (1L<<6)
+#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM0 (1L<<7)
+#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM1 (1L<<8)
+#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM2 (1L<<9)
+#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM3 (1L<<10)
+#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM4 (1L<<11)
+#define BNX2_MISC_PERR_ENA0_CTX_MISC_ACCM5 (1L<<12)
+#define BNX2_MISC_PERR_ENA0_CTX_MISC_PGTBL (1L<<13)
+#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR0 (1L<<14)
+#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR1 (1L<<15)
+#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR2 (1L<<16)
+#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR3 (1L<<17)
+#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DR4 (1L<<18)
+#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DW0 (1L<<19)
+#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DW1 (1L<<20)
+#define BNX2_MISC_PERR_ENA0_DMAE_MISC_DW2 (1L<<21)
+#define BNX2_MISC_PERR_ENA0_HC_MISC_DMA (1L<<22)
+#define BNX2_MISC_PERR_ENA0_MCP_MISC_REGF (1L<<23)
+#define BNX2_MISC_PERR_ENA0_MCP_MISC_SCPAD (1L<<24)
+#define BNX2_MISC_PERR_ENA0_MQ_MISC_CTX (1L<<25)
+#define BNX2_MISC_PERR_ENA0_RBDC_MISC (1L<<26)
+#define BNX2_MISC_PERR_ENA0_RBUF_MISC_MB (1L<<27)
+#define BNX2_MISC_PERR_ENA0_RBUF_MISC_PTR (1L<<28)
+#define BNX2_MISC_PERR_ENA0_RDE_MISC_RPC (1L<<29)
+#define BNX2_MISC_PERR_ENA0_RDE_MISC_RPM (1L<<30)
+#define BNX2_MISC_PERR_ENA0_RV2P_MISC_CB0REGS (1L<<31)
+
+#define BNX2_MISC_PERR_ENA1 0x000008a8
+#define BNX2_MISC_PERR_ENA1_RV2P_MISC_CB1REGS (1L<<0)
+#define BNX2_MISC_PERR_ENA1_RV2P_MISC_P1IRAM (1L<<1)
+#define BNX2_MISC_PERR_ENA1_RV2P_MISC_P2IRAM (1L<<2)
+#define BNX2_MISC_PERR_ENA1_RXP_MISC_CTXC (1L<<3)
+#define BNX2_MISC_PERR_ENA1_RXP_MISC_REGF (1L<<4)
+#define BNX2_MISC_PERR_ENA1_RXP_MISC_SCPAD (1L<<5)
+#define BNX2_MISC_PERR_ENA1_RXP_MISC_RBUFC (1L<<6)
+#define BNX2_MISC_PERR_ENA1_TBDC_MISC (1L<<7)
+#define BNX2_MISC_PERR_ENA1_TDMA_MISC (1L<<8)
+#define BNX2_MISC_PERR_ENA1_THBUF_MISC_MB0 (1L<<9)
+#define BNX2_MISC_PERR_ENA1_THBUF_MISC_MB1 (1L<<10)
+#define BNX2_MISC_PERR_ENA1_TPAT_MISC_REGF (1L<<11)
+#define BNX2_MISC_PERR_ENA1_TPAT_MISC_SCPAD (1L<<12)
+#define BNX2_MISC_PERR_ENA1_TPBUF_MISC_MB (1L<<13)
+#define BNX2_MISC_PERR_ENA1_TSCH_MISC_LR (1L<<14)
+#define BNX2_MISC_PERR_ENA1_TXP_MISC_CTXC (1L<<15)
+#define BNX2_MISC_PERR_ENA1_TXP_MISC_REGF (1L<<16)
+#define BNX2_MISC_PERR_ENA1_TXP_MISC_SCPAD (1L<<17)
+#define BNX2_MISC_PERR_ENA1_UMP_MISC_FIORX (1L<<18)
+#define BNX2_MISC_PERR_ENA1_UMP_MISC_FIOTX (1L<<19)
+#define BNX2_MISC_PERR_ENA1_UMP_MISC_RX (1L<<20)
+#define BNX2_MISC_PERR_ENA1_UMP_MISC_TX (1L<<21)
+#define BNX2_MISC_PERR_ENA1_RDMAQ_MISC (1L<<22)
+#define BNX2_MISC_PERR_ENA1_CSQ_MISC (1L<<23)
+#define BNX2_MISC_PERR_ENA1_CPQ_MISC (1L<<24)
+#define BNX2_MISC_PERR_ENA1_MCPQ_MISC (1L<<25)
+#define BNX2_MISC_PERR_ENA1_RV2PMQ_MISC (1L<<26)
+#define BNX2_MISC_PERR_ENA1_RV2PPQ_MISC (1L<<27)
+#define BNX2_MISC_PERR_ENA1_RV2PTQ_MISC (1L<<28)
+#define BNX2_MISC_PERR_ENA1_RXPQ_MISC (1L<<29)
+#define BNX2_MISC_PERR_ENA1_RXPCQ_MISC (1L<<30)
+#define BNX2_MISC_PERR_ENA1_RLUPQ_MISC (1L<<31)
+
+#define BNX2_MISC_PERR_ENA2 0x000008ac
+#define BNX2_MISC_PERR_ENA2_COMQ_MISC (1L<<0)
+#define BNX2_MISC_PERR_ENA2_COMXQ_MISC (1L<<1)
+#define BNX2_MISC_PERR_ENA2_COMTQ_MISC (1L<<2)
+#define BNX2_MISC_PERR_ENA2_TSCHQ_MISC (1L<<3)
+#define BNX2_MISC_PERR_ENA2_TBDRQ_MISC (1L<<4)
+#define BNX2_MISC_PERR_ENA2_TXPQ_MISC (1L<<5)
+#define BNX2_MISC_PERR_ENA2_TDMAQ_MISC (1L<<6)
+#define BNX2_MISC_PERR_ENA2_TPATQ_MISC (1L<<7)
+#define BNX2_MISC_PERR_ENA2_TASQ_MISC (1L<<8)
+
+#define BNX2_MISC_DEBUG_VECTOR_SEL 0x000008b0
+#define BNX2_MISC_DEBUG_VECTOR_SEL_0 (0xfffL<<0)
+#define BNX2_MISC_DEBUG_VECTOR_SEL_1 (0xfffL<<12)
+
+#define BNX2_MISC_VREG_CONTROL 0x000008b4
+#define BNX2_MISC_VREG_CONTROL_1_2 (0xfL<<0)
+#define BNX2_MISC_VREG_CONTROL_2_5 (0xfL<<4)
+
+#define BNX2_MISC_FINAL_CLK_CTL_VAL 0x000008b8
+#define BNX2_MISC_FINAL_CLK_CTL_VAL_MISC_FINAL_CLK_CTL_VAL (0x3ffffffL<<6)
+
+#define BNX2_MISC_UNUSED0 0x000008bc
+
+
+/*
+ * nvm_reg definition
+ * offset: 0x6400
+ */
+#define BNX2_NVM_COMMAND 0x00006400
+#define BNX2_NVM_COMMAND_RST (1L<<0)
+#define BNX2_NVM_COMMAND_DONE (1L<<3)
+#define BNX2_NVM_COMMAND_DOIT (1L<<4)
+#define BNX2_NVM_COMMAND_WR (1L<<5)
+#define BNX2_NVM_COMMAND_ERASE (1L<<6)
+#define BNX2_NVM_COMMAND_FIRST (1L<<7)
+#define BNX2_NVM_COMMAND_LAST (1L<<8)
+#define BNX2_NVM_COMMAND_WREN (1L<<16)
+#define BNX2_NVM_COMMAND_WRDI (1L<<17)
+#define BNX2_NVM_COMMAND_EWSR (1L<<18)
+#define BNX2_NVM_COMMAND_WRSR (1L<<19)
+
+#define BNX2_NVM_STATUS 0x00006404
+#define BNX2_NVM_STATUS_PI_FSM_STATE (0xfL<<0)
+#define BNX2_NVM_STATUS_EE_FSM_STATE (0xfL<<4)
+#define BNX2_NVM_STATUS_EQ_FSM_STATE (0xfL<<8)
+
+#define BNX2_NVM_WRITE 0x00006408
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE (0xffffffffL<<0)
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_BIT_BANG (0L<<0)
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_EECLK (1L<<0)
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_EEDATA (2L<<0)
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SCLK (4L<<0)
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_CS_B (8L<<0)
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SO (16L<<0)
+#define BNX2_NVM_WRITE_NVM_WRITE_VALUE_SI (32L<<0)
+
+#define BNX2_NVM_ADDR 0x0000640c
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE (0xffffffL<<0)
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_BIT_BANG (0L<<0)
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_EECLK (1L<<0)
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_EEDATA (2L<<0)
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SCLK (4L<<0)
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_CS_B (8L<<0)
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SO (16L<<0)
+#define BNX2_NVM_ADDR_NVM_ADDR_VALUE_SI (32L<<0)
+
+#define BNX2_NVM_READ 0x00006410
+#define BNX2_NVM_READ_NVM_READ_VALUE (0xffffffffL<<0)
+#define BNX2_NVM_READ_NVM_READ_VALUE_BIT_BANG (0L<<0)
+#define BNX2_NVM_READ_NVM_READ_VALUE_EECLK (1L<<0)
+#define BNX2_NVM_READ_NVM_READ_VALUE_EEDATA (2L<<0)
+#define BNX2_NVM_READ_NVM_READ_VALUE_SCLK (4L<<0)
+#define BNX2_NVM_READ_NVM_READ_VALUE_CS_B (8L<<0)
+#define BNX2_NVM_READ_NVM_READ_VALUE_SO (16L<<0)
+#define BNX2_NVM_READ_NVM_READ_VALUE_SI (32L<<0)
+
+#define BNX2_NVM_CFG1 0x00006414
+#define BNX2_NVM_CFG1_FLASH_MODE (1L<<0)
+#define BNX2_NVM_CFG1_BUFFER_MODE (1L<<1)
+#define BNX2_NVM_CFG1_PASS_MODE (1L<<2)
+#define BNX2_NVM_CFG1_BITBANG_MODE (1L<<3)
+#define BNX2_NVM_CFG1_STATUS_BIT (0x7L<<4)
+#define BNX2_NVM_CFG1_STATUS_BIT_FLASH_RDY (0L<<4)
+#define BNX2_NVM_CFG1_STATUS_BIT_BUFFER_RDY (7L<<4)
+#define BNX2_NVM_CFG1_SPI_CLK_DIV (0xfL<<7)
+#define BNX2_NVM_CFG1_SEE_CLK_DIV (0x7ffL<<11)
+#define BNX2_NVM_CFG1_PROTECT_MODE (1L<<24)
+#define BNX2_NVM_CFG1_FLASH_SIZE (1L<<25)
+#define BNX2_NVM_CFG1_COMPAT_BYPASSS (1L<<31)
+
+#define BNX2_NVM_CFG2 0x00006418
+#define BNX2_NVM_CFG2_ERASE_CMD (0xffL<<0)
+#define BNX2_NVM_CFG2_DUMMY (0xffL<<8)
+#define BNX2_NVM_CFG2_STATUS_CMD (0xffL<<16)
+
+#define BNX2_NVM_CFG3 0x0000641c
+#define BNX2_NVM_CFG3_BUFFER_RD_CMD (0xffL<<0)
+#define BNX2_NVM_CFG3_WRITE_CMD (0xffL<<8)
+#define BNX2_NVM_CFG3_BUFFER_WRITE_CMD (0xffL<<16)
+#define BNX2_NVM_CFG3_READ_CMD (0xffL<<24)
+
+#define BNX2_NVM_SW_ARB 0x00006420
+#define BNX2_NVM_SW_ARB_ARB_REQ_SET0 (1L<<0)
+#define BNX2_NVM_SW_ARB_ARB_REQ_SET1 (1L<<1)
+#define BNX2_NVM_SW_ARB_ARB_REQ_SET2 (1L<<2)
+#define BNX2_NVM_SW_ARB_ARB_REQ_SET3 (1L<<3)
+#define BNX2_NVM_SW_ARB_ARB_REQ_CLR0 (1L<<4)
+#define BNX2_NVM_SW_ARB_ARB_REQ_CLR1 (1L<<5)
+#define BNX2_NVM_SW_ARB_ARB_REQ_CLR2 (1L<<6)
+#define BNX2_NVM_SW_ARB_ARB_REQ_CLR3 (1L<<7)
+#define BNX2_NVM_SW_ARB_ARB_ARB0 (1L<<8)
+#define BNX2_NVM_SW_ARB_ARB_ARB1 (1L<<9)
+#define BNX2_NVM_SW_ARB_ARB_ARB2 (1L<<10)
+#define BNX2_NVM_SW_ARB_ARB_ARB3 (1L<<11)
+#define BNX2_NVM_SW_ARB_REQ0 (1L<<12)
+#define BNX2_NVM_SW_ARB_REQ1 (1L<<13)
+#define BNX2_NVM_SW_ARB_REQ2 (1L<<14)
+#define BNX2_NVM_SW_ARB_REQ3 (1L<<15)
+
+#define BNX2_NVM_ACCESS_ENABLE 0x00006424
+#define BNX2_NVM_ACCESS_ENABLE_EN (1L<<0)
+#define BNX2_NVM_ACCESS_ENABLE_WR_EN (1L<<1)
+
+#define BNX2_NVM_WRITE1 0x00006428
+#define BNX2_NVM_WRITE1_WREN_CMD (0xffL<<0)
+#define BNX2_NVM_WRITE1_WRDI_CMD (0xffL<<8)
+#define BNX2_NVM_WRITE1_SR_DATA (0xffL<<16)
+
+
+
+/*
+ * dma_reg definition
+ * offset: 0xc00
+ */
+#define BNX2_DMA_COMMAND 0x00000c00
+#define BNX2_DMA_COMMAND_ENABLE (1L<<0)
+
+#define BNX2_DMA_STATUS 0x00000c04
+#define BNX2_DMA_STATUS_PAR_ERROR_STATE (1L<<0)
+#define BNX2_DMA_STATUS_READ_TRANSFERS_STAT (1L<<16)
+#define BNX2_DMA_STATUS_READ_DELAY_PCI_CLKS_STAT (1L<<17)
+#define BNX2_DMA_STATUS_BIG_READ_TRANSFERS_STAT (1L<<18)
+#define BNX2_DMA_STATUS_BIG_READ_DELAY_PCI_CLKS_STAT (1L<<19)
+#define BNX2_DMA_STATUS_BIG_READ_RETRY_AFTER_DATA_STAT (1L<<20)
+#define BNX2_DMA_STATUS_WRITE_TRANSFERS_STAT (1L<<21)
+#define BNX2_DMA_STATUS_WRITE_DELAY_PCI_CLKS_STAT (1L<<22)
+#define BNX2_DMA_STATUS_BIG_WRITE_TRANSFERS_STAT (1L<<23)
+#define BNX2_DMA_STATUS_BIG_WRITE_DELAY_PCI_CLKS_STAT (1L<<24)
+#define BNX2_DMA_STATUS_BIG_WRITE_RETRY_AFTER_DATA_STAT (1L<<25)
+
+#define BNX2_DMA_CONFIG 0x00000c08
+#define BNX2_DMA_CONFIG_DATA_BYTE_SWAP (1L<<0)
+#define BNX2_DMA_CONFIG_DATA_WORD_SWAP (1L<<1)
+#define BNX2_DMA_CONFIG_CNTL_BYTE_SWAP (1L<<4)
+#define BNX2_DMA_CONFIG_CNTL_WORD_SWAP (1L<<5)
+#define BNX2_DMA_CONFIG_ONE_DMA (1L<<6)
+#define BNX2_DMA_CONFIG_CNTL_TWO_DMA (1L<<7)
+#define BNX2_DMA_CONFIG_CNTL_FPGA_MODE (1L<<8)
+#define BNX2_DMA_CONFIG_CNTL_PING_PONG_DMA (1L<<10)
+#define BNX2_DMA_CONFIG_CNTL_PCI_COMP_DLY (1L<<11)
+#define BNX2_DMA_CONFIG_NO_RCHANS_IN_USE (0xfL<<12)
+#define BNX2_DMA_CONFIG_NO_WCHANS_IN_USE (0xfL<<16)
+#define BNX2_DMA_CONFIG_PCI_CLK_CMP_BITS (0x7L<<20)
+#define BNX2_DMA_CONFIG_PCI_FAST_CLK_CMP (1L<<23)
+#define BNX2_DMA_CONFIG_BIG_SIZE (0xfL<<24)
+#define BNX2_DMA_CONFIG_BIG_SIZE_NONE (0x0L<<24)
+#define BNX2_DMA_CONFIG_BIG_SIZE_64 (0x1L<<24)
+#define BNX2_DMA_CONFIG_BIG_SIZE_128 (0x2L<<24)
+#define BNX2_DMA_CONFIG_BIG_SIZE_256 (0x4L<<24)
+#define BNX2_DMA_CONFIG_BIG_SIZE_512 (0x8L<<24)
+
+#define BNX2_DMA_BLACKOUT 0x00000c0c
+#define BNX2_DMA_BLACKOUT_RD_RETRY_BLACKOUT (0xffL<<0)
+#define BNX2_DMA_BLACKOUT_2ND_RD_RETRY_BLACKOUT (0xffL<<8)
+#define BNX2_DMA_BLACKOUT_WR_RETRY_BLACKOUT (0xffL<<16)
+
+#define BNX2_DMA_RCHAN_STAT 0x00000c30
+#define BNX2_DMA_RCHAN_STAT_COMP_CODE_0 (0x7L<<0)
+#define BNX2_DMA_RCHAN_STAT_PAR_ERR_0 (1L<<3)
+#define BNX2_DMA_RCHAN_STAT_COMP_CODE_1 (0x7L<<4)
+#define BNX2_DMA_RCHAN_STAT_PAR_ERR_1 (1L<<7)
+#define BNX2_DMA_RCHAN_STAT_COMP_CODE_2 (0x7L<<8)
+#define BNX2_DMA_RCHAN_STAT_PAR_ERR_2 (1L<<11)
+#define BNX2_DMA_RCHAN_STAT_COMP_CODE_3 (0x7L<<12)
+#define BNX2_DMA_RCHAN_STAT_PAR_ERR_3 (1L<<15)
+#define BNX2_DMA_RCHAN_STAT_COMP_CODE_4 (0x7L<<16)
+#define BNX2_DMA_RCHAN_STAT_PAR_ERR_4 (1L<<19)
+#define BNX2_DMA_RCHAN_STAT_COMP_CODE_5 (0x7L<<20)
+#define BNX2_DMA_RCHAN_STAT_PAR_ERR_5 (1L<<23)
+#define BNX2_DMA_RCHAN_STAT_COMP_CODE_6 (0x7L<<24)
+#define BNX2_DMA_RCHAN_STAT_PAR_ERR_6 (1L<<27)
+#define BNX2_DMA_RCHAN_STAT_COMP_CODE_7 (0x7L<<28)
+#define BNX2_DMA_RCHAN_STAT_PAR_ERR_7 (1L<<31)
+
+#define BNX2_DMA_WCHAN_STAT 0x00000c34
+#define BNX2_DMA_WCHAN_STAT_COMP_CODE_0 (0x7L<<0)
+#define BNX2_DMA_WCHAN_STAT_PAR_ERR_0 (1L<<3)
+#define BNX2_DMA_WCHAN_STAT_COMP_CODE_1 (0x7L<<4)
+#define BNX2_DMA_WCHAN_STAT_PAR_ERR_1 (1L<<7)
+#define BNX2_DMA_WCHAN_STAT_COMP_CODE_2 (0x7L<<8)
+#define BNX2_DMA_WCHAN_STAT_PAR_ERR_2 (1L<<11)
+#define BNX2_DMA_WCHAN_STAT_COMP_CODE_3 (0x7L<<12)
+#define BNX2_DMA_WCHAN_STAT_PAR_ERR_3 (1L<<15)
+#define BNX2_DMA_WCHAN_STAT_COMP_CODE_4 (0x7L<<16)
+#define BNX2_DMA_WCHAN_STAT_PAR_ERR_4 (1L<<19)
+#define BNX2_DMA_WCHAN_STAT_COMP_CODE_5 (0x7L<<20)
+#define BNX2_DMA_WCHAN_STAT_PAR_ERR_5 (1L<<23)
+#define BNX2_DMA_WCHAN_STAT_COMP_CODE_6 (0x7L<<24)
+#define BNX2_DMA_WCHAN_STAT_PAR_ERR_6 (1L<<27)
+#define BNX2_DMA_WCHAN_STAT_COMP_CODE_7 (0x7L<<28)
+#define BNX2_DMA_WCHAN_STAT_PAR_ERR_7 (1L<<31)
+
+#define BNX2_DMA_RCHAN_ASSIGNMENT 0x00000c38
+#define BNX2_DMA_RCHAN_ASSIGNMENT_0 (0xfL<<0)
+#define BNX2_DMA_RCHAN_ASSIGNMENT_1 (0xfL<<4)
+#define BNX2_DMA_RCHAN_ASSIGNMENT_2 (0xfL<<8)
+#define BNX2_DMA_RCHAN_ASSIGNMENT_3 (0xfL<<12)
+#define BNX2_DMA_RCHAN_ASSIGNMENT_4 (0xfL<<16)
+#define BNX2_DMA_RCHAN_ASSIGNMENT_5 (0xfL<<20)
+#define BNX2_DMA_RCHAN_ASSIGNMENT_6 (0xfL<<24)
+#define BNX2_DMA_RCHAN_ASSIGNMENT_7 (0xfL<<28)
+
+#define BNX2_DMA_WCHAN_ASSIGNMENT 0x00000c3c
+#define BNX2_DMA_WCHAN_ASSIGNMENT_0 (0xfL<<0)
+#define BNX2_DMA_WCHAN_ASSIGNMENT_1 (0xfL<<4)
+#define BNX2_DMA_WCHAN_ASSIGNMENT_2 (0xfL<<8)
+#define BNX2_DMA_WCHAN_ASSIGNMENT_3 (0xfL<<12)
+#define BNX2_DMA_WCHAN_ASSIGNMENT_4 (0xfL<<16)
+#define BNX2_DMA_WCHAN_ASSIGNMENT_5 (0xfL<<20)
+#define BNX2_DMA_WCHAN_ASSIGNMENT_6 (0xfL<<24)
+#define BNX2_DMA_WCHAN_ASSIGNMENT_7 (0xfL<<28)
+
+#define BNX2_DMA_RCHAN_STAT_00 0x00000c40
+#define BNX2_DMA_RCHAN_STAT_00_RCHAN_STA_HOST_ADDR_LOW (0xffffffffL<<0)
+
+#define BNX2_DMA_RCHAN_STAT_01 0x00000c44
+#define BNX2_DMA_RCHAN_STAT_01_RCHAN_STA_HOST_ADDR_HIGH (0xffffffffL<<0)
+
+#define BNX2_DMA_RCHAN_STAT_02 0x00000c48
+#define BNX2_DMA_RCHAN_STAT_02_LENGTH (0xffffL<<0)
+#define BNX2_DMA_RCHAN_STAT_02_WORD_SWAP (1L<<16)
+#define BNX2_DMA_RCHAN_STAT_02_BYTE_SWAP (1L<<17)
+#define BNX2_DMA_RCHAN_STAT_02_PRIORITY_LVL (1L<<18)
+
+#define BNX2_DMA_RCHAN_STAT_10 0x00000c4c
+#define BNX2_DMA_RCHAN_STAT_11 0x00000c50
+#define BNX2_DMA_RCHAN_STAT_12 0x00000c54
+#define BNX2_DMA_RCHAN_STAT_20 0x00000c58
+#define BNX2_DMA_RCHAN_STAT_21 0x00000c5c
+#define BNX2_DMA_RCHAN_STAT_22 0x00000c60
+#define BNX2_DMA_RCHAN_STAT_30 0x00000c64
+#define BNX2_DMA_RCHAN_STAT_31 0x00000c68
+#define BNX2_DMA_RCHAN_STAT_32 0x00000c6c
+#define BNX2_DMA_RCHAN_STAT_40 0x00000c70
+#define BNX2_DMA_RCHAN_STAT_41 0x00000c74
+#define BNX2_DMA_RCHAN_STAT_42 0x00000c78
+#define BNX2_DMA_RCHAN_STAT_50 0x00000c7c
+#define BNX2_DMA_RCHAN_STAT_51 0x00000c80
+#define BNX2_DMA_RCHAN_STAT_52 0x00000c84
+#define BNX2_DMA_RCHAN_STAT_60 0x00000c88
+#define BNX2_DMA_RCHAN_STAT_61 0x00000c8c
+#define BNX2_DMA_RCHAN_STAT_62 0x00000c90
+#define BNX2_DMA_RCHAN_STAT_70 0x00000c94
+#define BNX2_DMA_RCHAN_STAT_71 0x00000c98
+#define BNX2_DMA_RCHAN_STAT_72 0x00000c9c
+#define BNX2_DMA_WCHAN_STAT_00 0x00000ca0
+#define BNX2_DMA_WCHAN_STAT_00_WCHAN_STA_HOST_ADDR_LOW (0xffffffffL<<0)
+
+#define BNX2_DMA_WCHAN_STAT_01 0x00000ca4
+#define BNX2_DMA_WCHAN_STAT_01_WCHAN_STA_HOST_ADDR_HIGH (0xffffffffL<<0)
+
+#define BNX2_DMA_WCHAN_STAT_02 0x00000ca8
+#define BNX2_DMA_WCHAN_STAT_02_LENGTH (0xffffL<<0)
+#define BNX2_DMA_WCHAN_STAT_02_WORD_SWAP (1L<<16)
+#define BNX2_DMA_WCHAN_STAT_02_BYTE_SWAP (1L<<17)
+#define BNX2_DMA_WCHAN_STAT_02_PRIORITY_LVL (1L<<18)
+
+#define BNX2_DMA_WCHAN_STAT_10 0x00000cac
+#define BNX2_DMA_WCHAN_STAT_11 0x00000cb0
+#define BNX2_DMA_WCHAN_STAT_12 0x00000cb4
+#define BNX2_DMA_WCHAN_STAT_20 0x00000cb8
+#define BNX2_DMA_WCHAN_STAT_21 0x00000cbc
+#define BNX2_DMA_WCHAN_STAT_22 0x00000cc0
+#define BNX2_DMA_WCHAN_STAT_30 0x00000cc4
+#define BNX2_DMA_WCHAN_STAT_31 0x00000cc8
+#define BNX2_DMA_WCHAN_STAT_32 0x00000ccc
+#define BNX2_DMA_WCHAN_STAT_40 0x00000cd0
+#define BNX2_DMA_WCHAN_STAT_41 0x00000cd4
+#define BNX2_DMA_WCHAN_STAT_42 0x00000cd8
+#define BNX2_DMA_WCHAN_STAT_50 0x00000cdc
+#define BNX2_DMA_WCHAN_STAT_51 0x00000ce0
+#define BNX2_DMA_WCHAN_STAT_52 0x00000ce4
+#define BNX2_DMA_WCHAN_STAT_60 0x00000ce8
+#define BNX2_DMA_WCHAN_STAT_61 0x00000cec
+#define BNX2_DMA_WCHAN_STAT_62 0x00000cf0
+#define BNX2_DMA_WCHAN_STAT_70 0x00000cf4
+#define BNX2_DMA_WCHAN_STAT_71 0x00000cf8
+#define BNX2_DMA_WCHAN_STAT_72 0x00000cfc
+#define BNX2_DMA_ARB_STAT_00 0x00000d00
+#define BNX2_DMA_ARB_STAT_00_MASTER (0xffffL<<0)
+#define BNX2_DMA_ARB_STAT_00_MASTER_ENC (0xffL<<16)
+#define BNX2_DMA_ARB_STAT_00_CUR_BINMSTR (0xffL<<24)
+
+#define BNX2_DMA_ARB_STAT_01 0x00000d04
+#define BNX2_DMA_ARB_STAT_01_LPR_RPTR (0xfL<<0)
+#define BNX2_DMA_ARB_STAT_01_LPR_WPTR (0xfL<<4)
+#define BNX2_DMA_ARB_STAT_01_LPB_RPTR (0xfL<<8)
+#define BNX2_DMA_ARB_STAT_01_LPB_WPTR (0xfL<<12)
+#define BNX2_DMA_ARB_STAT_01_HPR_RPTR (0xfL<<16)
+#define BNX2_DMA_ARB_STAT_01_HPR_WPTR (0xfL<<20)
+#define BNX2_DMA_ARB_STAT_01_HPB_RPTR (0xfL<<24)
+#define BNX2_DMA_ARB_STAT_01_HPB_WPTR (0xfL<<28)
+
+#define BNX2_DMA_FUSE_CTRL0_CMD 0x00000f00
+#define BNX2_DMA_FUSE_CTRL0_CMD_PWRUP_DONE (1L<<0)
+#define BNX2_DMA_FUSE_CTRL0_CMD_SHIFT_DONE (1L<<1)
+#define BNX2_DMA_FUSE_CTRL0_CMD_SHIFT (1L<<2)
+#define BNX2_DMA_FUSE_CTRL0_CMD_LOAD (1L<<3)
+#define BNX2_DMA_FUSE_CTRL0_CMD_SEL (0xfL<<8)
+
+#define BNX2_DMA_FUSE_CTRL0_DATA 0x00000f04
+#define BNX2_DMA_FUSE_CTRL1_CMD 0x00000f08
+#define BNX2_DMA_FUSE_CTRL1_CMD_PWRUP_DONE (1L<<0)
+#define BNX2_DMA_FUSE_CTRL1_CMD_SHIFT_DONE (1L<<1)
+#define BNX2_DMA_FUSE_CTRL1_CMD_SHIFT (1L<<2)
+#define BNX2_DMA_FUSE_CTRL1_CMD_LOAD (1L<<3)
+#define BNX2_DMA_FUSE_CTRL1_CMD_SEL (0xfL<<8)
+
+#define BNX2_DMA_FUSE_CTRL1_DATA 0x00000f0c
+#define BNX2_DMA_FUSE_CTRL2_CMD 0x00000f10
+#define BNX2_DMA_FUSE_CTRL2_CMD_PWRUP_DONE (1L<<0)
+#define BNX2_DMA_FUSE_CTRL2_CMD_SHIFT_DONE (1L<<1)
+#define BNX2_DMA_FUSE_CTRL2_CMD_SHIFT (1L<<2)
+#define BNX2_DMA_FUSE_CTRL2_CMD_LOAD (1L<<3)
+#define BNX2_DMA_FUSE_CTRL2_CMD_SEL (0xfL<<8)
+
+#define BNX2_DMA_FUSE_CTRL2_DATA 0x00000f14
+
+
+/*
+ * context_reg definition
+ * offset: 0x1000
+ */
+#define BNX2_CTX_COMMAND 0x00001000
+#define BNX2_CTX_COMMAND_ENABLED (1L<<0)
+
+#define BNX2_CTX_STATUS 0x00001004
+#define BNX2_CTX_STATUS_LOCK_WAIT (1L<<0)
+#define BNX2_CTX_STATUS_READ_STAT (1L<<16)
+#define BNX2_CTX_STATUS_WRITE_STAT (1L<<17)
+#define BNX2_CTX_STATUS_ACC_STALL_STAT (1L<<18)
+#define BNX2_CTX_STATUS_LOCK_STALL_STAT (1L<<19)
+
+#define BNX2_CTX_VIRT_ADDR 0x00001008
+#define BNX2_CTX_VIRT_ADDR_VIRT_ADDR (0x7fffL<<6)
+
+#define BNX2_CTX_PAGE_TBL 0x0000100c
+#define BNX2_CTX_PAGE_TBL_PAGE_TBL (0x3fffL<<6)
+
+#define BNX2_CTX_DATA_ADR 0x00001010
+#define BNX2_CTX_DATA_ADR_DATA_ADR (0x7ffffL<<2)
+
+#define BNX2_CTX_DATA 0x00001014
+#define BNX2_CTX_LOCK 0x00001018
+#define BNX2_CTX_LOCK_TYPE (0x7L<<0)
+#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_VOID (0x0L<<0)
+#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_COMPLETE (0x7L<<0)
+#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_PROTOCOL (0x1L<<0)
+#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_TX (0x2L<<0)
+#define BNX2_CTX_LOCK_TYPE_LOCK_TYPE_TIMER (0x4L<<0)
+#define BNX2_CTX_LOCK_CID_VALUE (0x3fffL<<7)
+#define BNX2_CTX_LOCK_GRANTED (1L<<26)
+#define BNX2_CTX_LOCK_MODE (0x7L<<27)
+#define BNX2_CTX_LOCK_MODE_UNLOCK (0x0L<<27)
+#define BNX2_CTX_LOCK_MODE_IMMEDIATE (0x1L<<27)
+#define BNX2_CTX_LOCK_MODE_SURE (0x2L<<27)
+#define BNX2_CTX_LOCK_STATUS (1L<<30)
+#define BNX2_CTX_LOCK_REQ (1L<<31)
+
+#define BNX2_CTX_ACCESS_STATUS 0x00001040
+#define BNX2_CTX_ACCESS_STATUS_MASTERENCODED (0xfL<<0)
+#define BNX2_CTX_ACCESS_STATUS_ACCESSMEMORYSM (0x3L<<10)
+#define BNX2_CTX_ACCESS_STATUS_PAGETABLEINITSM (0x3L<<12)
+#define BNX2_CTX_ACCESS_STATUS_ACCESSMEMORYINITSM (0x3L<<14)
+#define BNX2_CTX_ACCESS_STATUS_QUALIFIED_REQUEST (0x7ffL<<17)
+
+#define BNX2_CTX_DBG_LOCK_STATUS 0x00001044
+#define BNX2_CTX_DBG_LOCK_STATUS_SM (0x3ffL<<0)
+#define BNX2_CTX_DBG_LOCK_STATUS_MATCH (0x3ffL<<22)
+
+#define BNX2_CTX_CHNL_LOCK_STATUS_0 0x00001080
+#define BNX2_CTX_CHNL_LOCK_STATUS_0_CID (0x3fffL<<0)
+#define BNX2_CTX_CHNL_LOCK_STATUS_0_TYPE (0x3L<<14)
+#define BNX2_CTX_CHNL_LOCK_STATUS_0_MODE (1L<<16)
+
+#define BNX2_CTX_CHNL_LOCK_STATUS_1 0x00001084
+#define BNX2_CTX_CHNL_LOCK_STATUS_2 0x00001088
+#define BNX2_CTX_CHNL_LOCK_STATUS_3 0x0000108c
+#define BNX2_CTX_CHNL_LOCK_STATUS_4 0x00001090
+#define BNX2_CTX_CHNL_LOCK_STATUS_5 0x00001094
+#define BNX2_CTX_CHNL_LOCK_STATUS_6 0x00001098
+#define BNX2_CTX_CHNL_LOCK_STATUS_7 0x0000109c
+#define BNX2_CTX_CHNL_LOCK_STATUS_8 0x000010a0
+
+
+/*
+ * emac_reg definition
+ * offset: 0x1400
+ */
+#define BNX2_EMAC_MODE 0x00001400
+#define BNX2_EMAC_MODE_RESET (1L<<0)
+#define BNX2_EMAC_MODE_HALF_DUPLEX (1L<<1)
+#define BNX2_EMAC_MODE_PORT (0x3L<<2)
+#define BNX2_EMAC_MODE_PORT_NONE (0L<<2)
+#define BNX2_EMAC_MODE_PORT_MII (1L<<2)
+#define BNX2_EMAC_MODE_PORT_GMII (2L<<2)
+#define BNX2_EMAC_MODE_PORT_UNDEF (3L<<2)
+#define BNX2_EMAC_MODE_MAC_LOOP (1L<<4)
+#define BNX2_EMAC_MODE_TAGGED_MAC_CTL (1L<<7)
+#define BNX2_EMAC_MODE_TX_BURST (1L<<8)
+#define BNX2_EMAC_MODE_MAX_DEFER_DROP_ENA (1L<<9)
+#define BNX2_EMAC_MODE_EXT_LINK_POL (1L<<10)
+#define BNX2_EMAC_MODE_FORCE_LINK (1L<<11)
+#define BNX2_EMAC_MODE_MPKT (1L<<18)
+#define BNX2_EMAC_MODE_MPKT_RCVD (1L<<19)
+#define BNX2_EMAC_MODE_ACPI_RCVD (1L<<20)
+
+#define BNX2_EMAC_STATUS 0x00001404
+#define BNX2_EMAC_STATUS_LINK (1L<<11)
+#define BNX2_EMAC_STATUS_LINK_CHANGE (1L<<12)
+#define BNX2_EMAC_STATUS_MI_COMPLETE (1L<<22)
+#define BNX2_EMAC_STATUS_MI_INT (1L<<23)
+#define BNX2_EMAC_STATUS_AP_ERROR (1L<<24)
+#define BNX2_EMAC_STATUS_PARITY_ERROR_STATE (1L<<31)
+
+#define BNX2_EMAC_ATTENTION_ENA 0x00001408
+#define BNX2_EMAC_ATTENTION_ENA_LINK (1L<<11)
+#define BNX2_EMAC_ATTENTION_ENA_MI_COMPLETE (1L<<22)
+#define BNX2_EMAC_ATTENTION_ENA_MI_INT (1L<<23)
+#define BNX2_EMAC_ATTENTION_ENA_AP_ERROR (1L<<24)
+
+#define BNX2_EMAC_LED 0x0000140c
+#define BNX2_EMAC_LED_OVERRIDE (1L<<0)
+#define BNX2_EMAC_LED_1000MB_OVERRIDE (1L<<1)
+#define BNX2_EMAC_LED_100MB_OVERRIDE (1L<<2)
+#define BNX2_EMAC_LED_10MB_OVERRIDE (1L<<3)
+#define BNX2_EMAC_LED_TRAFFIC_OVERRIDE (1L<<4)
+#define BNX2_EMAC_LED_BLNK_TRAFFIC (1L<<5)
+#define BNX2_EMAC_LED_TRAFFIC (1L<<6)
+#define BNX2_EMAC_LED_1000MB (1L<<7)
+#define BNX2_EMAC_LED_100MB (1L<<8)
+#define BNX2_EMAC_LED_10MB (1L<<9)
+#define BNX2_EMAC_LED_TRAFFIC_STAT (1L<<10)
+#define BNX2_EMAC_LED_BLNK_RATE (0xfffL<<19)
+#define BNX2_EMAC_LED_BLNK_RATE_ENA (1L<<31)
+
+#define BNX2_EMAC_MAC_MATCH0 0x00001410
+#define BNX2_EMAC_MAC_MATCH1 0x00001414
+#define BNX2_EMAC_MAC_MATCH2 0x00001418
+#define BNX2_EMAC_MAC_MATCH3 0x0000141c
+#define BNX2_EMAC_MAC_MATCH4 0x00001420
+#define BNX2_EMAC_MAC_MATCH5 0x00001424
+#define BNX2_EMAC_MAC_MATCH6 0x00001428
+#define BNX2_EMAC_MAC_MATCH7 0x0000142c
+#define BNX2_EMAC_MAC_MATCH8 0x00001430
+#define BNX2_EMAC_MAC_MATCH9 0x00001434
+#define BNX2_EMAC_MAC_MATCH10 0x00001438
+#define BNX2_EMAC_MAC_MATCH11 0x0000143c
+#define BNX2_EMAC_MAC_MATCH12 0x00001440
+#define BNX2_EMAC_MAC_MATCH13 0x00001444
+#define BNX2_EMAC_MAC_MATCH14 0x00001448
+#define BNX2_EMAC_MAC_MATCH15 0x0000144c
+#define BNX2_EMAC_MAC_MATCH16 0x00001450
+#define BNX2_EMAC_MAC_MATCH17 0x00001454
+#define BNX2_EMAC_MAC_MATCH18 0x00001458
+#define BNX2_EMAC_MAC_MATCH19 0x0000145c
+#define BNX2_EMAC_MAC_MATCH20 0x00001460
+#define BNX2_EMAC_MAC_MATCH21 0x00001464
+#define BNX2_EMAC_MAC_MATCH22 0x00001468
+#define BNX2_EMAC_MAC_MATCH23 0x0000146c
+#define BNX2_EMAC_MAC_MATCH24 0x00001470
+#define BNX2_EMAC_MAC_MATCH25 0x00001474
+#define BNX2_EMAC_MAC_MATCH26 0x00001478
+#define BNX2_EMAC_MAC_MATCH27 0x0000147c
+#define BNX2_EMAC_MAC_MATCH28 0x00001480
+#define BNX2_EMAC_MAC_MATCH29 0x00001484
+#define BNX2_EMAC_MAC_MATCH30 0x00001488
+#define BNX2_EMAC_MAC_MATCH31 0x0000148c
+#define BNX2_EMAC_BACKOFF_SEED 0x00001498
+#define BNX2_EMAC_BACKOFF_SEED_EMAC_BACKOFF_SEED (0x3ffL<<0)
+
+#define BNX2_EMAC_RX_MTU_SIZE 0x0000149c
+#define BNX2_EMAC_RX_MTU_SIZE_MTU_SIZE (0xffffL<<0)
+#define BNX2_EMAC_RX_MTU_SIZE_JUMBO_ENA (1L<<31)
+
+#define BNX2_EMAC_SERDES_CNTL 0x000014a4
+#define BNX2_EMAC_SERDES_CNTL_RXR (0x7L<<0)
+#define BNX2_EMAC_SERDES_CNTL_RXG (0x3L<<3)
+#define BNX2_EMAC_SERDES_CNTL_RXCKSEL (1L<<6)
+#define BNX2_EMAC_SERDES_CNTL_TXBIAS (0x7L<<7)
+#define BNX2_EMAC_SERDES_CNTL_BGMAX (1L<<10)
+#define BNX2_EMAC_SERDES_CNTL_BGMIN (1L<<11)
+#define BNX2_EMAC_SERDES_CNTL_TXMODE (1L<<12)
+#define BNX2_EMAC_SERDES_CNTL_TXEDGE (1L<<13)
+#define BNX2_EMAC_SERDES_CNTL_SERDES_MODE (1L<<14)
+#define BNX2_EMAC_SERDES_CNTL_PLLTEST (1L<<15)
+#define BNX2_EMAC_SERDES_CNTL_CDET_EN (1L<<16)
+#define BNX2_EMAC_SERDES_CNTL_TBI_LBK (1L<<17)
+#define BNX2_EMAC_SERDES_CNTL_REMOTE_LBK (1L<<18)
+#define BNX2_EMAC_SERDES_CNTL_REV_PHASE (1L<<19)
+#define BNX2_EMAC_SERDES_CNTL_REGCTL12 (0x3L<<20)
+#define BNX2_EMAC_SERDES_CNTL_REGCTL25 (0x3L<<22)
+
+#define BNX2_EMAC_SERDES_STATUS 0x000014a8
+#define BNX2_EMAC_SERDES_STATUS_RX_STAT (0xffL<<0)
+#define BNX2_EMAC_SERDES_STATUS_COMMA_DET (1L<<8)
+
+#define BNX2_EMAC_MDIO_COMM 0x000014ac
+#define BNX2_EMAC_MDIO_COMM_DATA (0xffffL<<0)
+#define BNX2_EMAC_MDIO_COMM_REG_ADDR (0x1fL<<16)
+#define BNX2_EMAC_MDIO_COMM_PHY_ADDR (0x1fL<<21)
+#define BNX2_EMAC_MDIO_COMM_COMMAND (0x3L<<26)
+#define BNX2_EMAC_MDIO_COMM_COMMAND_UNDEFINED_0 (0L<<26)
+#define BNX2_EMAC_MDIO_COMM_COMMAND_WRITE (1L<<26)
+#define BNX2_EMAC_MDIO_COMM_COMMAND_READ (2L<<26)
+#define BNX2_EMAC_MDIO_COMM_COMMAND_UNDEFINED_3 (3L<<26)
+#define BNX2_EMAC_MDIO_COMM_FAIL (1L<<28)
+#define BNX2_EMAC_MDIO_COMM_START_BUSY (1L<<29)
+#define BNX2_EMAC_MDIO_COMM_DISEXT (1L<<30)
+
+#define BNX2_EMAC_MDIO_STATUS 0x000014b0
+#define BNX2_EMAC_MDIO_STATUS_LINK (1L<<0)
+#define BNX2_EMAC_MDIO_STATUS_10MB (1L<<1)
+
+#define BNX2_EMAC_MDIO_MODE 0x000014b4
+#define BNX2_EMAC_MDIO_MODE_SHORT_PREAMBLE (1L<<1)
+#define BNX2_EMAC_MDIO_MODE_AUTO_POLL (1L<<4)
+#define BNX2_EMAC_MDIO_MODE_BIT_BANG (1L<<8)
+#define BNX2_EMAC_MDIO_MODE_MDIO (1L<<9)
+#define BNX2_EMAC_MDIO_MODE_MDIO_OE (1L<<10)
+#define BNX2_EMAC_MDIO_MODE_MDC (1L<<11)
+#define BNX2_EMAC_MDIO_MODE_MDINT (1L<<12)
+#define BNX2_EMAC_MDIO_MODE_CLOCK_CNT (0x1fL<<16)
+
+#define BNX2_EMAC_MDIO_AUTO_STATUS 0x000014b8
+#define BNX2_EMAC_MDIO_AUTO_STATUS_AUTO_ERR (1L<<0)
+
+#define BNX2_EMAC_TX_MODE 0x000014bc
+#define BNX2_EMAC_TX_MODE_RESET (1L<<0)
+#define BNX2_EMAC_TX_MODE_EXT_PAUSE_EN (1L<<3)
+#define BNX2_EMAC_TX_MODE_FLOW_EN (1L<<4)
+#define BNX2_EMAC_TX_MODE_BIG_BACKOFF (1L<<5)
+#define BNX2_EMAC_TX_MODE_LONG_PAUSE (1L<<6)
+#define BNX2_EMAC_TX_MODE_LINK_AWARE (1L<<7)
+
+#define BNX2_EMAC_TX_STATUS 0x000014c0
+#define BNX2_EMAC_TX_STATUS_XOFFED (1L<<0)
+#define BNX2_EMAC_TX_STATUS_XOFF_SENT (1L<<1)
+#define BNX2_EMAC_TX_STATUS_XON_SENT (1L<<2)
+#define BNX2_EMAC_TX_STATUS_LINK_UP (1L<<3)
+#define BNX2_EMAC_TX_STATUS_UNDERRUN (1L<<4)
+
+#define BNX2_EMAC_TX_LENGTHS 0x000014c4
+#define BNX2_EMAC_TX_LENGTHS_SLOT (0xffL<<0)
+#define BNX2_EMAC_TX_LENGTHS_IPG (0xfL<<8)
+#define BNX2_EMAC_TX_LENGTHS_IPG_CRS (0x3L<<12)
+
+#define BNX2_EMAC_RX_MODE 0x000014c8
+#define BNX2_EMAC_RX_MODE_RESET (1L<<0)
+#define BNX2_EMAC_RX_MODE_FLOW_EN (1L<<2)
+#define BNX2_EMAC_RX_MODE_KEEP_MAC_CONTROL (1L<<3)
+#define BNX2_EMAC_RX_MODE_KEEP_PAUSE (1L<<4)
+#define BNX2_EMAC_RX_MODE_ACCEPT_OVERSIZE (1L<<5)
+#define BNX2_EMAC_RX_MODE_ACCEPT_RUNTS (1L<<6)
+#define BNX2_EMAC_RX_MODE_LLC_CHK (1L<<7)
+#define BNX2_EMAC_RX_MODE_PROMISCUOUS (1L<<8)
+#define BNX2_EMAC_RX_MODE_NO_CRC_CHK (1L<<9)
+#define BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG (1L<<10)
+#define BNX2_EMAC_RX_MODE_FILT_BROADCAST (1L<<11)
+#define BNX2_EMAC_RX_MODE_SORT_MODE (1L<<12)
+
+#define BNX2_EMAC_RX_STATUS 0x000014cc
+#define BNX2_EMAC_RX_STATUS_FFED (1L<<0)
+#define BNX2_EMAC_RX_STATUS_FF_RECEIVED (1L<<1)
+#define BNX2_EMAC_RX_STATUS_N_RECEIVED (1L<<2)
+
+#define BNX2_EMAC_MULTICAST_HASH0 0x000014d0
+#define BNX2_EMAC_MULTICAST_HASH1 0x000014d4
+#define BNX2_EMAC_MULTICAST_HASH2 0x000014d8
+#define BNX2_EMAC_MULTICAST_HASH3 0x000014dc
+#define BNX2_EMAC_MULTICAST_HASH4 0x000014e0
+#define BNX2_EMAC_MULTICAST_HASH5 0x000014e4
+#define BNX2_EMAC_MULTICAST_HASH6 0x000014e8
+#define BNX2_EMAC_MULTICAST_HASH7 0x000014ec
+#define BNX2_EMAC_RX_STAT_IFHCINOCTETS 0x00001500
+#define BNX2_EMAC_RX_STAT_IFHCINBADOCTETS 0x00001504
+#define BNX2_EMAC_RX_STAT_ETHERSTATSFRAGMENTS 0x00001508
+#define BNX2_EMAC_RX_STAT_IFHCINUCASTPKTS 0x0000150c
+#define BNX2_EMAC_RX_STAT_IFHCINMULTICASTPKTS 0x00001510
+#define BNX2_EMAC_RX_STAT_IFHCINBROADCASTPKTS 0x00001514
+#define BNX2_EMAC_RX_STAT_DOT3STATSFCSERRORS 0x00001518
+#define BNX2_EMAC_RX_STAT_DOT3STATSALIGNMENTERRORS 0x0000151c
+#define BNX2_EMAC_RX_STAT_DOT3STATSCARRIERSENSEERRORS 0x00001520
+#define BNX2_EMAC_RX_STAT_XONPAUSEFRAMESRECEIVED 0x00001524
+#define BNX2_EMAC_RX_STAT_XOFFPAUSEFRAMESRECEIVED 0x00001528
+#define BNX2_EMAC_RX_STAT_MACCONTROLFRAMESRECEIVED 0x0000152c
+#define BNX2_EMAC_RX_STAT_XOFFSTATEENTERED 0x00001530
+#define BNX2_EMAC_RX_STAT_DOT3STATSFRAMESTOOLONG 0x00001534
+#define BNX2_EMAC_RX_STAT_ETHERSTATSJABBERS 0x00001538
+#define BNX2_EMAC_RX_STAT_ETHERSTATSUNDERSIZEPKTS 0x0000153c
+#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS64OCTETS 0x00001540
+#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS65OCTETSTO127OCTETS 0x00001544
+#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS128OCTETSTO255OCTETS 0x00001548
+#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS256OCTETSTO511OCTETS 0x0000154c
+#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS512OCTETSTO1023OCTETS 0x00001550
+#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS1024OCTETSTO1522OCTETS 0x00001554
+#define BNX2_EMAC_RX_STAT_ETHERSTATSPKTS1523OCTETSTO9022OCTETS 0x00001558
+#define BNX2_EMAC_RXMAC_DEBUG0 0x0000155c
+#define BNX2_EMAC_RXMAC_DEBUG1 0x00001560
+#define BNX2_EMAC_RXMAC_DEBUG1_LENGTH_NE_BYTE_COUNT (1L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG1_LENGTH_OUT_RANGE (1L<<1)
+#define BNX2_EMAC_RXMAC_DEBUG1_BAD_CRC (1L<<2)
+#define BNX2_EMAC_RXMAC_DEBUG1_RX_ERROR (1L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG1_ALIGN_ERROR (1L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG1_LAST_DATA (1L<<5)
+#define BNX2_EMAC_RXMAC_DEBUG1_ODD_BYTE_START (1L<<6)
+#define BNX2_EMAC_RXMAC_DEBUG1_BYTE_COUNT (0xffffL<<7)
+#define BNX2_EMAC_RXMAC_DEBUG1_SLOT_TIME (0xffL<<23)
+
+#define BNX2_EMAC_RXMAC_DEBUG2 0x00001564
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE (0x7L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_IDLE (0x0L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_SFD (0x1L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_DATA (0x2L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_SKEEP (0x3L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_EXT (0x4L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_DROP (0x5L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_SDROP (0x6L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_SM_STATE_FC (0x7L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE (0xfL<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_IDLE (0x0L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA0 (0x1L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA1 (0x2L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA2 (0x3L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_DATA3 (0x4L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_ABORT (0x5L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_WAIT (0x6L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_STATUS (0x7L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_IDI_STATE_LAST (0x8L<<3)
+#define BNX2_EMAC_RXMAC_DEBUG2_BYTE_IN (0xffL<<7)
+#define BNX2_EMAC_RXMAC_DEBUG2_FALSEC (1L<<15)
+#define BNX2_EMAC_RXMAC_DEBUG2_TAGGED (1L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG2_PAUSE_STATE (1L<<18)
+#define BNX2_EMAC_RXMAC_DEBUG2_PAUSE_STATE_IDLE (0L<<18)
+#define BNX2_EMAC_RXMAC_DEBUG2_PAUSE_STATE_PAUSED (1L<<18)
+#define BNX2_EMAC_RXMAC_DEBUG2_SE_COUNTER (0xfL<<19)
+#define BNX2_EMAC_RXMAC_DEBUG2_QUANTA (0x1fL<<23)
+
+#define BNX2_EMAC_RXMAC_DEBUG3 0x00001568
+#define BNX2_EMAC_RXMAC_DEBUG3_PAUSE_CTR (0xffffL<<0)
+#define BNX2_EMAC_RXMAC_DEBUG3_TMP_PAUSE_CTR (0xffffL<<16)
+
+#define BNX2_EMAC_RXMAC_DEBUG4 0x0000156c
+#define BNX2_EMAC_RXMAC_DEBUG4_TYPE_FIELD (0xffffL<<0)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE (0x3fL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_IDLE (0x0L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UMAC2 (0x1L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UMAC3 (0x2L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UNI (0x3L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MMAC2 (0x7L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MMAC3 (0x5L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA1 (0x6L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA2 (0x7L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PSA3 (0x8L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MC2 (0x9L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MC3 (0xaL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MWAIT1 (0xeL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MWAIT2 (0xfL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MCHECK (0x10L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MC (0x11L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BC2 (0x12L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BC3 (0x13L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BSA1 (0x14L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BSA2 (0x15L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BSA3 (0x16L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BTYPE (0x17L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_BC (0x18L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PTYPE (0x19L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_CMD (0x1aL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MAC (0x1bL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_LATCH (0x1cL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_XOFF (0x1dL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_XON (0x1eL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_PAUSED (0x1fL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_NPAUSED (0x20L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_TTYPE (0x21L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_TVAL (0x22L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_USA1 (0x23L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_USA2 (0x24L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_USA3 (0x25L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UTYPE (0x26L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UTTYPE (0x27L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_UTVAL (0x28L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_MTYPE (0x29L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_FILT_STATE_DROP (0x2aL<<16)
+#define BNX2_EMAC_RXMAC_DEBUG4_DROP_PKT (1L<<22)
+#define BNX2_EMAC_RXMAC_DEBUG4_SLOT_FILLED (1L<<23)
+#define BNX2_EMAC_RXMAC_DEBUG4_FALSE_CARRIER (1L<<24)
+#define BNX2_EMAC_RXMAC_DEBUG4_LAST_DATA (1L<<25)
+#define BNX2_EMAC_RXMAC_DEBUG4_sfd_FOUND (1L<<26)
+#define BNX2_EMAC_RXMAC_DEBUG4_ADVANCE (1L<<27)
+#define BNX2_EMAC_RXMAC_DEBUG4_START (1L<<28)
+
+#define BNX2_EMAC_RXMAC_DEBUG5 0x00001570
+#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM (0x7L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_IDLE (0L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_WAIT_EOF (1L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_WAIT_STAT (2L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_SET_EOF4FCRC (3L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_SET_EOF4RDE (4L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_SET_EOF4ALL (5L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG5_PS_IDISM_1WD_WAIT_STAT (6L<<0)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1 (0x7L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_VDW (0x0L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_STAT (0x1L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_AEOF (0x2L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_NEOF (0x3L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_SOF (0x4L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_SAEOF (0x6L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF1_SNEOF (0x7L<<4)
+#define BNX2_EMAC_RXMAC_DEBUG5_EOF_DETECTED (1L<<7)
+#define BNX2_EMAC_RXMAC_DEBUG5_CCODE_BUF0 (0x7L<<8)
+#define BNX2_EMAC_RXMAC_DEBUG5_RPM_IDI_FIFO_FULL (1L<<11)
+#define BNX2_EMAC_RXMAC_DEBUG5_LOAD_CCODE (1L<<12)
+#define BNX2_EMAC_RXMAC_DEBUG5_LOAD_DATA (1L<<13)
+#define BNX2_EMAC_RXMAC_DEBUG5_LOAD_STAT (1L<<14)
+#define BNX2_EMAC_RXMAC_DEBUG5_CLR_STAT (1L<<15)
+#define BNX2_EMAC_RXMAC_DEBUG5_IDI_RPM_CCODE (0x3L<<16)
+#define BNX2_EMAC_RXMAC_DEBUG5_IDI_RPM_ACCEPT (1L<<19)
+#define BNX2_EMAC_RXMAC_DEBUG5_FMLEN (0xfffL<<20)
+
+#define BNX2_EMAC_RX_STAT_AC0 0x00001580
+#define BNX2_EMAC_RX_STAT_AC1 0x00001584
+#define BNX2_EMAC_RX_STAT_AC2 0x00001588
+#define BNX2_EMAC_RX_STAT_AC3 0x0000158c
+#define BNX2_EMAC_RX_STAT_AC4 0x00001590
+#define BNX2_EMAC_RX_STAT_AC5 0x00001594
+#define BNX2_EMAC_RX_STAT_AC6 0x00001598
+#define BNX2_EMAC_RX_STAT_AC7 0x0000159c
+#define BNX2_EMAC_RX_STAT_AC8 0x000015a0
+#define BNX2_EMAC_RX_STAT_AC9 0x000015a4
+#define BNX2_EMAC_RX_STAT_AC10 0x000015a8
+#define BNX2_EMAC_RX_STAT_AC11 0x000015ac
+#define BNX2_EMAC_RX_STAT_AC12 0x000015b0
+#define BNX2_EMAC_RX_STAT_AC13 0x000015b4
+#define BNX2_EMAC_RX_STAT_AC14 0x000015b8
+#define BNX2_EMAC_RX_STAT_AC15 0x000015bc
+#define BNX2_EMAC_RX_STAT_AC16 0x000015c0
+#define BNX2_EMAC_RX_STAT_AC17 0x000015c4
+#define BNX2_EMAC_RX_STAT_AC18 0x000015c8
+#define BNX2_EMAC_RX_STAT_AC19 0x000015cc
+#define BNX2_EMAC_RX_STAT_AC20 0x000015d0
+#define BNX2_EMAC_RX_STAT_AC21 0x000015d4
+#define BNX2_EMAC_RX_STAT_AC22 0x000015d8
+#define BNX2_EMAC_RXMAC_SUC_DBG_OVERRUNVEC 0x000015dc
+#define BNX2_EMAC_TX_STAT_IFHCOUTOCTETS 0x00001600
+#define BNX2_EMAC_TX_STAT_IFHCOUTBADOCTETS 0x00001604
+#define BNX2_EMAC_TX_STAT_ETHERSTATSCOLLISIONS 0x00001608
+#define BNX2_EMAC_TX_STAT_OUTXONSENT 0x0000160c
+#define BNX2_EMAC_TX_STAT_OUTXOFFSENT 0x00001610
+#define BNX2_EMAC_TX_STAT_FLOWCONTROLDONE 0x00001614
+#define BNX2_EMAC_TX_STAT_DOT3STATSSINGLECOLLISIONFRAMES 0x00001618
+#define BNX2_EMAC_TX_STAT_DOT3STATSMULTIPLECOLLISIONFRAMES 0x0000161c
+#define BNX2_EMAC_TX_STAT_DOT3STATSDEFERREDTRANSMISSIONS 0x00001620
+#define BNX2_EMAC_TX_STAT_DOT3STATSEXCESSIVECOLLISIONS 0x00001624
+#define BNX2_EMAC_TX_STAT_DOT3STATSLATECOLLISIONS 0x00001628
+#define BNX2_EMAC_TX_STAT_IFHCOUTUCASTPKTS 0x0000162c
+#define BNX2_EMAC_TX_STAT_IFHCOUTMULTICASTPKTS 0x00001630
+#define BNX2_EMAC_TX_STAT_IFHCOUTBROADCASTPKTS 0x00001634
+#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS64OCTETS 0x00001638
+#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS65OCTETSTO127OCTETS 0x0000163c
+#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS128OCTETSTO255OCTETS 0x00001640
+#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS256OCTETSTO511OCTETS 0x00001644
+#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS512OCTETSTO1023OCTETS 0x00001648
+#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS1024OCTETSTO1522OCTETS 0x0000164c
+#define BNX2_EMAC_TX_STAT_ETHERSTATSPKTS1523OCTETSTO9022OCTETS 0x00001650
+#define BNX2_EMAC_TX_STAT_DOT3STATSINTERNALMACTRANSMITERRORS 0x00001654
+#define BNX2_EMAC_TXMAC_DEBUG0 0x00001658
+#define BNX2_EMAC_TXMAC_DEBUG1 0x0000165c
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE (0xfL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_IDLE (0x0L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_START0 (0x1L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA0 (0x4L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA1 (0x5L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA2 (0x6L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_DATA3 (0x7L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_WAIT0 (0x8L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_ODI_STATE_WAIT1 (0x9L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG1_CRS_ENABLE (1L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG1_BAD_CRC (1L<<5)
+#define BNX2_EMAC_TXMAC_DEBUG1_SE_COUNTER (0xfL<<6)
+#define BNX2_EMAC_TXMAC_DEBUG1_SEND_PAUSE (1L<<10)
+#define BNX2_EMAC_TXMAC_DEBUG1_LATE_COLLISION (1L<<11)
+#define BNX2_EMAC_TXMAC_DEBUG1_MAX_DEFER (1L<<12)
+#define BNX2_EMAC_TXMAC_DEBUG1_DEFERRED (1L<<13)
+#define BNX2_EMAC_TXMAC_DEBUG1_ONE_BYTE (1L<<14)
+#define BNX2_EMAC_TXMAC_DEBUG1_IPG_TIME (0xfL<<15)
+#define BNX2_EMAC_TXMAC_DEBUG1_SLOT_TIME (0xffL<<19)
+
+#define BNX2_EMAC_TXMAC_DEBUG2 0x00001660
+#define BNX2_EMAC_TXMAC_DEBUG2_BACK_OFF (0x3ffL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG2_BYTE_COUNT (0xffffL<<10)
+#define BNX2_EMAC_TXMAC_DEBUG2_COL_COUNT (0x1fL<<26)
+#define BNX2_EMAC_TXMAC_DEBUG2_COL_BIT (1L<<31)
+
+#define BNX2_EMAC_TXMAC_DEBUG3 0x00001664
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE (0xfL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_IDLE (0x0L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_PRE1 (0x1L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_PRE2 (0x2L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_SFD (0x3L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_DATA (0x4L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_CRC1 (0x5L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_CRC2 (0x6L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_EXT (0x7L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_STATB (0x8L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_STATG (0x9L<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_JAM (0xaL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_EJAM (0xbL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_BJAM (0xcL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_SWAIT (0xdL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_SM_STATE_BACKOFF (0xeL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE (0x7L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_IDLE (0x0L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_WAIT (0x1L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_UNI (0x2L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_MC (0x3L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_BC2 (0x4L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_BC3 (0x5L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG3_FILT_STATE_BC (0x6L<<4)
+#define BNX2_EMAC_TXMAC_DEBUG3_CRS_DONE (1L<<7)
+#define BNX2_EMAC_TXMAC_DEBUG3_XOFF (1L<<8)
+#define BNX2_EMAC_TXMAC_DEBUG3_SE_COUNTER (0xfL<<9)
+#define BNX2_EMAC_TXMAC_DEBUG3_QUANTA_COUNTER (0x1fL<<13)
+
+#define BNX2_EMAC_TXMAC_DEBUG4 0x00001668
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_COUNTER (0xffffL<<0)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE (0xfL<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_IDLE (0x0L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA1 (0x2L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA2 (0x3L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_MCA3 (0x6L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC1 (0x7L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC2 (0x5L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_SRC3 (0x4L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_TYPE (0xcL<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CMD (0xeL<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_TIME (0xaL<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CRC1 (0x8L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_CRC2 (0x9L<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_PAUSE_STATE_WAIT (0xdL<<16)
+#define BNX2_EMAC_TXMAC_DEBUG4_STATS0_VALID (1L<<20)
+#define BNX2_EMAC_TXMAC_DEBUG4_APPEND_CRC (1L<<21)
+#define BNX2_EMAC_TXMAC_DEBUG4_SLOT_FILLED (1L<<22)
+#define BNX2_EMAC_TXMAC_DEBUG4_MAX_DEFER (1L<<23)
+#define BNX2_EMAC_TXMAC_DEBUG4_SEND_EXTEND (1L<<24)
+#define BNX2_EMAC_TXMAC_DEBUG4_SEND_PADDING (1L<<25)
+#define BNX2_EMAC_TXMAC_DEBUG4_EOF_LOC (1L<<26)
+#define BNX2_EMAC_TXMAC_DEBUG4_COLLIDING (1L<<27)
+#define BNX2_EMAC_TXMAC_DEBUG4_COL_IN (1L<<28)
+#define BNX2_EMAC_TXMAC_DEBUG4_BURSTING (1L<<29)
+#define BNX2_EMAC_TXMAC_DEBUG4_ADVANCE (1L<<30)
+#define BNX2_EMAC_TXMAC_DEBUG4_GO (1L<<31)
+
+#define BNX2_EMAC_TX_STAT_AC0 0x00001680
+#define BNX2_EMAC_TX_STAT_AC1 0x00001684
+#define BNX2_EMAC_TX_STAT_AC2 0x00001688
+#define BNX2_EMAC_TX_STAT_AC3 0x0000168c
+#define BNX2_EMAC_TX_STAT_AC4 0x00001690
+#define BNX2_EMAC_TX_STAT_AC5 0x00001694
+#define BNX2_EMAC_TX_STAT_AC6 0x00001698
+#define BNX2_EMAC_TX_STAT_AC7 0x0000169c
+#define BNX2_EMAC_TX_STAT_AC8 0x000016a0
+#define BNX2_EMAC_TX_STAT_AC9 0x000016a4
+#define BNX2_EMAC_TX_STAT_AC10 0x000016a8
+#define BNX2_EMAC_TX_STAT_AC11 0x000016ac
+#define BNX2_EMAC_TX_STAT_AC12 0x000016b0
+#define BNX2_EMAC_TX_STAT_AC13 0x000016b4
+#define BNX2_EMAC_TX_STAT_AC14 0x000016b8
+#define BNX2_EMAC_TX_STAT_AC15 0x000016bc
+#define BNX2_EMAC_TX_STAT_AC16 0x000016c0
+#define BNX2_EMAC_TX_STAT_AC17 0x000016c4
+#define BNX2_EMAC_TX_STAT_AC18 0x000016c8
+#define BNX2_EMAC_TX_STAT_AC19 0x000016cc
+#define BNX2_EMAC_TX_STAT_AC20 0x000016d0
+#define BNX2_EMAC_TX_STAT_AC21 0x000016d4
+#define BNX2_EMAC_TXMAC_SUC_DBG_OVERRUNVEC 0x000016d8
+
+
+/*
+ * rpm_reg definition
+ * offset: 0x1800
+ */
+#define BNX2_RPM_COMMAND 0x00001800
+#define BNX2_RPM_COMMAND_ENABLED (1L<<0)
+#define BNX2_RPM_COMMAND_OVERRUN_ABORT (1L<<4)
+
+#define BNX2_RPM_STATUS 0x00001804
+#define BNX2_RPM_STATUS_MBUF_WAIT (1L<<0)
+#define BNX2_RPM_STATUS_FREE_WAIT (1L<<1)
+
+#define BNX2_RPM_CONFIG 0x00001808
+#define BNX2_RPM_CONFIG_NO_PSD_HDR_CKSUM (1L<<0)
+#define BNX2_RPM_CONFIG_ACPI_ENA (1L<<1)
+#define BNX2_RPM_CONFIG_ACPI_KEEP (1L<<2)
+#define BNX2_RPM_CONFIG_MP_KEEP (1L<<3)
+#define BNX2_RPM_CONFIG_SORT_VECT_VAL (0xfL<<4)
+#define BNX2_RPM_CONFIG_IGNORE_VLAN (1L<<31)
+
+#define BNX2_RPM_VLAN_MATCH0 0x00001810
+#define BNX2_RPM_VLAN_MATCH0_RPM_VLAN_MTCH0_VALUE (0xfffL<<0)
+
+#define BNX2_RPM_VLAN_MATCH1 0x00001814
+#define BNX2_RPM_VLAN_MATCH1_RPM_VLAN_MTCH1_VALUE (0xfffL<<0)
+
+#define BNX2_RPM_VLAN_MATCH2 0x00001818
+#define BNX2_RPM_VLAN_MATCH2_RPM_VLAN_MTCH2_VALUE (0xfffL<<0)
+
+#define BNX2_RPM_VLAN_MATCH3 0x0000181c
+#define BNX2_RPM_VLAN_MATCH3_RPM_VLAN_MTCH3_VALUE (0xfffL<<0)
+
+#define BNX2_RPM_SORT_USER0 0x00001820
+#define BNX2_RPM_SORT_USER0_PM_EN (0xffffL<<0)
+#define BNX2_RPM_SORT_USER0_BC_EN (1L<<16)
+#define BNX2_RPM_SORT_USER0_MC_EN (1L<<17)
+#define BNX2_RPM_SORT_USER0_MC_HSH_EN (1L<<18)
+#define BNX2_RPM_SORT_USER0_PROM_EN (1L<<19)
+#define BNX2_RPM_SORT_USER0_VLAN_EN (0xfL<<20)
+#define BNX2_RPM_SORT_USER0_PROM_VLAN (1L<<24)
+#define BNX2_RPM_SORT_USER0_ENA (1L<<31)
+
+#define BNX2_RPM_SORT_USER1 0x00001824
+#define BNX2_RPM_SORT_USER1_PM_EN (0xffffL<<0)
+#define BNX2_RPM_SORT_USER1_BC_EN (1L<<16)
+#define BNX2_RPM_SORT_USER1_MC_EN (1L<<17)
+#define BNX2_RPM_SORT_USER1_MC_HSH_EN (1L<<18)
+#define BNX2_RPM_SORT_USER1_PROM_EN (1L<<19)
+#define BNX2_RPM_SORT_USER1_VLAN_EN (0xfL<<20)
+#define BNX2_RPM_SORT_USER1_PROM_VLAN (1L<<24)
+#define BNX2_RPM_SORT_USER1_ENA (1L<<31)
+
+#define BNX2_RPM_SORT_USER2 0x00001828
+#define BNX2_RPM_SORT_USER2_PM_EN (0xffffL<<0)
+#define BNX2_RPM_SORT_USER2_BC_EN (1L<<16)
+#define BNX2_RPM_SORT_USER2_MC_EN (1L<<17)
+#define BNX2_RPM_SORT_USER2_MC_HSH_EN (1L<<18)
+#define BNX2_RPM_SORT_USER2_PROM_EN (1L<<19)
+#define BNX2_RPM_SORT_USER2_VLAN_EN (0xfL<<20)
+#define BNX2_RPM_SORT_USER2_PROM_VLAN (1L<<24)
+#define BNX2_RPM_SORT_USER2_ENA (1L<<31)
+
+#define BNX2_RPM_SORT_USER3 0x0000182c
+#define BNX2_RPM_SORT_USER3_PM_EN (0xffffL<<0)
+#define BNX2_RPM_SORT_USER3_BC_EN (1L<<16)
+#define BNX2_RPM_SORT_USER3_MC_EN (1L<<17)
+#define BNX2_RPM_SORT_USER3_MC_HSH_EN (1L<<18)
+#define BNX2_RPM_SORT_USER3_PROM_EN (1L<<19)
+#define BNX2_RPM_SORT_USER3_VLAN_EN (0xfL<<20)
+#define BNX2_RPM_SORT_USER3_PROM_VLAN (1L<<24)
+#define BNX2_RPM_SORT_USER3_ENA (1L<<31)
+
+#define BNX2_RPM_STAT_L2_FILTER_DISCARDS 0x00001840
+#define BNX2_RPM_STAT_RULE_CHECKER_DISCARDS 0x00001844
+#define BNX2_RPM_STAT_IFINFTQDISCARDS 0x00001848
+#define BNX2_RPM_STAT_IFINMBUFDISCARD 0x0000184c
+#define BNX2_RPM_STAT_RULE_CHECKER_P4_HIT 0x00001850
+#define BNX2_RPM_STAT_AC0 0x00001880
+#define BNX2_RPM_STAT_AC1 0x00001884
+#define BNX2_RPM_STAT_AC2 0x00001888
+#define BNX2_RPM_STAT_AC3 0x0000188c
+#define BNX2_RPM_STAT_AC4 0x00001890
+#define BNX2_RPM_RC_CNTL_0 0x00001900
+#define BNX2_RPM_RC_CNTL_0_OFFSET (0xffL<<0)
+#define BNX2_RPM_RC_CNTL_0_CLASS (0x7L<<8)
+#define BNX2_RPM_RC_CNTL_0_PRIORITY (1L<<11)
+#define BNX2_RPM_RC_CNTL_0_P4 (1L<<12)
+#define BNX2_RPM_RC_CNTL_0_HDR_TYPE (0x7L<<13)
+#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_START (0L<<13)
+#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_IP (1L<<13)
+#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_TCP (2L<<13)
+#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_UDP (3L<<13)
+#define BNX2_RPM_RC_CNTL_0_HDR_TYPE_DATA (4L<<13)
+#define BNX2_RPM_RC_CNTL_0_COMP (0x3L<<16)
+#define BNX2_RPM_RC_CNTL_0_COMP_EQUAL (0L<<16)
+#define BNX2_RPM_RC_CNTL_0_COMP_NEQUAL (1L<<16)
+#define BNX2_RPM_RC_CNTL_0_COMP_GREATER (2L<<16)
+#define BNX2_RPM_RC_CNTL_0_COMP_LESS (3L<<16)
+#define BNX2_RPM_RC_CNTL_0_SBIT (1L<<19)
+#define BNX2_RPM_RC_CNTL_0_CMDSEL (0xfL<<20)
+#define BNX2_RPM_RC_CNTL_0_MAP (1L<<24)
+#define BNX2_RPM_RC_CNTL_0_DISCARD (1L<<25)
+#define BNX2_RPM_RC_CNTL_0_MASK (1L<<26)
+#define BNX2_RPM_RC_CNTL_0_P1 (1L<<27)
+#define BNX2_RPM_RC_CNTL_0_P2 (1L<<28)
+#define BNX2_RPM_RC_CNTL_0_P3 (1L<<29)
+#define BNX2_RPM_RC_CNTL_0_NBIT (1L<<30)
+
+#define BNX2_RPM_RC_VALUE_MASK_0 0x00001904
+#define BNX2_RPM_RC_VALUE_MASK_0_VALUE (0xffffL<<0)
+#define BNX2_RPM_RC_VALUE_MASK_0_MASK (0xffffL<<16)
+
+#define BNX2_RPM_RC_CNTL_1 0x00001908
+#define BNX2_RPM_RC_CNTL_1_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_1_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_1 0x0000190c
+#define BNX2_RPM_RC_CNTL_2 0x00001910
+#define BNX2_RPM_RC_CNTL_2_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_2_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_2 0x00001914
+#define BNX2_RPM_RC_CNTL_3 0x00001918
+#define BNX2_RPM_RC_CNTL_3_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_3_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_3 0x0000191c
+#define BNX2_RPM_RC_CNTL_4 0x00001920
+#define BNX2_RPM_RC_CNTL_4_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_4_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_4 0x00001924
+#define BNX2_RPM_RC_CNTL_5 0x00001928
+#define BNX2_RPM_RC_CNTL_5_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_5_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_5 0x0000192c
+#define BNX2_RPM_RC_CNTL_6 0x00001930
+#define BNX2_RPM_RC_CNTL_6_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_6_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_6 0x00001934
+#define BNX2_RPM_RC_CNTL_7 0x00001938
+#define BNX2_RPM_RC_CNTL_7_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_7_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_7 0x0000193c
+#define BNX2_RPM_RC_CNTL_8 0x00001940
+#define BNX2_RPM_RC_CNTL_8_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_8_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_8 0x00001944
+#define BNX2_RPM_RC_CNTL_9 0x00001948
+#define BNX2_RPM_RC_CNTL_9_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_9_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_9 0x0000194c
+#define BNX2_RPM_RC_CNTL_10 0x00001950
+#define BNX2_RPM_RC_CNTL_10_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_10_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_10 0x00001954
+#define BNX2_RPM_RC_CNTL_11 0x00001958
+#define BNX2_RPM_RC_CNTL_11_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_11_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_11 0x0000195c
+#define BNX2_RPM_RC_CNTL_12 0x00001960
+#define BNX2_RPM_RC_CNTL_12_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_12_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_12 0x00001964
+#define BNX2_RPM_RC_CNTL_13 0x00001968
+#define BNX2_RPM_RC_CNTL_13_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_13_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_13 0x0000196c
+#define BNX2_RPM_RC_CNTL_14 0x00001970
+#define BNX2_RPM_RC_CNTL_14_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_14_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_14 0x00001974
+#define BNX2_RPM_RC_CNTL_15 0x00001978
+#define BNX2_RPM_RC_CNTL_15_A (0x3ffffL<<0)
+#define BNX2_RPM_RC_CNTL_15_B (0xfffL<<19)
+
+#define BNX2_RPM_RC_VALUE_MASK_15 0x0000197c
+#define BNX2_RPM_RC_CONFIG 0x00001980
+#define BNX2_RPM_RC_CONFIG_RULE_ENABLE (0xffffL<<0)
+#define BNX2_RPM_RC_CONFIG_DEF_CLASS (0x7L<<24)
+
+#define BNX2_RPM_DEBUG0 0x00001984
+#define BNX2_RPM_DEBUG0_FM_BCNT (0xffffL<<0)
+#define BNX2_RPM_DEBUG0_T_DATA_OFST_VLD (1L<<16)
+#define BNX2_RPM_DEBUG0_T_UDP_OFST_VLD (1L<<17)
+#define BNX2_RPM_DEBUG0_T_TCP_OFST_VLD (1L<<18)
+#define BNX2_RPM_DEBUG0_T_IP_OFST_VLD (1L<<19)
+#define BNX2_RPM_DEBUG0_IP_MORE_FRGMT (1L<<20)
+#define BNX2_RPM_DEBUG0_T_IP_NO_TCP_UDP_HDR (1L<<21)
+#define BNX2_RPM_DEBUG0_LLC_SNAP (1L<<22)
+#define BNX2_RPM_DEBUG0_FM_STARTED (1L<<23)
+#define BNX2_RPM_DEBUG0_DONE (1L<<24)
+#define BNX2_RPM_DEBUG0_WAIT_4_DONE (1L<<25)
+#define BNX2_RPM_DEBUG0_USE_TPBUF_CKSUM (1L<<26)
+#define BNX2_RPM_DEBUG0_RX_NO_PSD_HDR_CKSUM (1L<<27)
+#define BNX2_RPM_DEBUG0_IGNORE_VLAN (1L<<28)
+#define BNX2_RPM_DEBUG0_RP_ENA_ACTIVE (1L<<31)
+
+#define BNX2_RPM_DEBUG1 0x00001988
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST (0xffffL<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_IDLE (0L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B6_ALL (1L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B2_IPLLC (2L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B6_IP (4L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ETYPE_B2_IP (8L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_IP_START (16L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_IP (32L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_TCP (64L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_UDP (128L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_AH (256L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ESP (512L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ESP_PAYLOAD (1024L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_DATA (2048L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ADD_CARRY (0x2000L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_ADD_CARRYOUT (0x4000L<<0)
+#define BNX2_RPM_DEBUG1_FSM_CUR_ST_LATCH_RESULT (0x8000L<<0)
+#define BNX2_RPM_DEBUG1_HDR_BCNT (0x7ffL<<16)
+#define BNX2_RPM_DEBUG1_UNKNOWN_ETYPE_D (1L<<28)
+#define BNX2_RPM_DEBUG1_VLAN_REMOVED_D2 (1L<<29)
+#define BNX2_RPM_DEBUG1_VLAN_REMOVED_D1 (1L<<30)
+#define BNX2_RPM_DEBUG1_EOF_0XTRA_WD (1L<<31)
+
+#define BNX2_RPM_DEBUG2 0x0000198c
+#define BNX2_RPM_DEBUG2_CMD_HIT_VEC (0xffffL<<0)
+#define BNX2_RPM_DEBUG2_IP_BCNT (0xffL<<16)
+#define BNX2_RPM_DEBUG2_THIS_CMD_M4 (1L<<24)
+#define BNX2_RPM_DEBUG2_THIS_CMD_M3 (1L<<25)
+#define BNX2_RPM_DEBUG2_THIS_CMD_M2 (1L<<26)
+#define BNX2_RPM_DEBUG2_THIS_CMD_M1 (1L<<27)
+#define BNX2_RPM_DEBUG2_IPIPE_EMPTY (1L<<28)
+#define BNX2_RPM_DEBUG2_FM_DISCARD (1L<<29)
+#define BNX2_RPM_DEBUG2_LAST_RULE_IN_FM_D2 (1L<<30)
+#define BNX2_RPM_DEBUG2_LAST_RULE_IN_FM_D1 (1L<<31)
+
+#define BNX2_RPM_DEBUG3 0x00001990
+#define BNX2_RPM_DEBUG3_AVAIL_MBUF_PTR (0x1ffL<<0)
+#define BNX2_RPM_DEBUG3_RDE_RLUPQ_WR_REQ_INT (1L<<9)
+#define BNX2_RPM_DEBUG3_RDE_RBUF_WR_LAST_INT (1L<<10)
+#define BNX2_RPM_DEBUG3_RDE_RBUF_WR_REQ_INT (1L<<11)
+#define BNX2_RPM_DEBUG3_RDE_RBUF_FREE_REQ (1L<<12)
+#define BNX2_RPM_DEBUG3_RDE_RBUF_ALLOC_REQ (1L<<13)
+#define BNX2_RPM_DEBUG3_DFSM_MBUF_NOTAVAIL (1L<<14)
+#define BNX2_RPM_DEBUG3_RBUF_RDE_SOF_DROP (1L<<15)
+#define BNX2_RPM_DEBUG3_DFIFO_VLD_ENTRY_CT (0xfL<<16)
+#define BNX2_RPM_DEBUG3_RDE_SRC_FIFO_ALMFULL (1L<<21)
+#define BNX2_RPM_DEBUG3_DROP_NXT_VLD (1L<<22)
+#define BNX2_RPM_DEBUG3_DROP_NXT (1L<<23)
+#define BNX2_RPM_DEBUG3_FTQ_FSM (0x3L<<24)
+#define BNX2_RPM_DEBUG3_FTQ_FSM_IDLE (0x0L<<24)
+#define BNX2_RPM_DEBUG3_FTQ_FSM_WAIT_ACK (0x1L<<24)
+#define BNX2_RPM_DEBUG3_FTQ_FSM_WAIT_FREE (0x2L<<24)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM (0x3L<<26)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_SOF (0x0L<<26)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM_GET_MBUF (0x1L<<26)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM_DMA_DATA (0x2L<<26)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_DATA (0x3L<<26)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_EOF (0x4L<<26)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_MF_ACK (0x5L<<26)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM_WAIT_DROP_NXT_VLD (0x6L<<26)
+#define BNX2_RPM_DEBUG3_MBWRITE_FSM_DONE (0x7L<<26)
+#define BNX2_RPM_DEBUG3_MBFREE_FSM (1L<<29)
+#define BNX2_RPM_DEBUG3_MBFREE_FSM_IDLE (0L<<29)
+#define BNX2_RPM_DEBUG3_MBFREE_FSM_WAIT_ACK (1L<<29)
+#define BNX2_RPM_DEBUG3_MBALLOC_FSM (1L<<30)
+#define BNX2_RPM_DEBUG3_MBALLOC_FSM_ET_MBUF (0x0L<<30)
+#define BNX2_RPM_DEBUG3_MBALLOC_FSM_IVE_MBUF (0x1L<<30)
+#define BNX2_RPM_DEBUG3_CCODE_EOF_ERROR (1L<<31)
+
+#define BNX2_RPM_DEBUG4 0x00001994
+#define BNX2_RPM_DEBUG4_DFSM_MBUF_CLUSTER (0x1ffffffL<<0)
+#define BNX2_RPM_DEBUG4_DFIFO_CUR_CCODE (0x7L<<25)
+#define BNX2_RPM_DEBUG4_MBWRITE_FSM (0x7L<<28)
+#define BNX2_RPM_DEBUG4_DFIFO_EMPTY (1L<<31)
+
+#define BNX2_RPM_DEBUG5 0x00001998
+#define BNX2_RPM_DEBUG5_RDROP_WPTR (0x1fL<<0)
+#define BNX2_RPM_DEBUG5_RDROP_ACPI_RPTR (0x1fL<<5)
+#define BNX2_RPM_DEBUG5_RDROP_MC_RPTR (0x1fL<<10)
+#define BNX2_RPM_DEBUG5_RDROP_RC_RPTR (0x1fL<<15)
+#define BNX2_RPM_DEBUG5_RDROP_ACPI_EMPTY (1L<<20)
+#define BNX2_RPM_DEBUG5_RDROP_MC_EMPTY (1L<<21)
+#define BNX2_RPM_DEBUG5_RDROP_AEOF_VEC_AT_RDROP_MC_RPTR (1L<<22)
+#define BNX2_RPM_DEBUG5_HOLDREG_WOL_DROP_INT (1L<<23)
+#define BNX2_RPM_DEBUG5_HOLDREG_DISCARD (1L<<24)
+#define BNX2_RPM_DEBUG5_HOLDREG_MBUF_NOTAVAIL (1L<<25)
+#define BNX2_RPM_DEBUG5_HOLDREG_MC_EMPTY (1L<<26)
+#define BNX2_RPM_DEBUG5_HOLDREG_RC_EMPTY (1L<<27)
+#define BNX2_RPM_DEBUG5_HOLDREG_FC_EMPTY (1L<<28)
+#define BNX2_RPM_DEBUG5_HOLDREG_ACPI_EMPTY (1L<<29)
+#define BNX2_RPM_DEBUG5_HOLDREG_FULL_T (1L<<30)
+#define BNX2_RPM_DEBUG5_HOLDREG_RD (1L<<31)
+
+#define BNX2_RPM_DEBUG6 0x0000199c
+#define BNX2_RPM_DEBUG6_ACPI_VEC (0xffffL<<0)
+#define BNX2_RPM_DEBUG6_VEC (0xffffL<<16)
+
+#define BNX2_RPM_DEBUG7 0x000019a0
+#define BNX2_RPM_DEBUG7_RPM_DBG7_LAST_CRC (0xffffffffL<<0)
+
+#define BNX2_RPM_DEBUG8 0x000019a4
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM (0xfL<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_IDLE (0L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_W1_ADDR (1L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_W2_ADDR (2L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_W3_ADDR (3L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_SOF_WAIT_THBUF (4L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W3_DATA (5L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W0_ADDR (6L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W1_ADDR (7L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W2_ADDR (8L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_W3_ADDR (9L<<0)
+#define BNX2_RPM_DEBUG8_PS_ACPI_FSM_WAIT_THBUF (10L<<0)
+#define BNX2_RPM_DEBUG8_COMPARE_AT_W0 (1L<<4)
+#define BNX2_RPM_DEBUG8_COMPARE_AT_W3_DATA (1L<<5)
+#define BNX2_RPM_DEBUG8_COMPARE_AT_SOF_WAIT (1L<<6)
+#define BNX2_RPM_DEBUG8_COMPARE_AT_SOF_W3 (1L<<7)
+#define BNX2_RPM_DEBUG8_COMPARE_AT_SOF_W2 (1L<<8)
+#define BNX2_RPM_DEBUG8_EOF_W_LTEQ6_VLDBYTES (1L<<9)
+#define BNX2_RPM_DEBUG8_EOF_W_LTEQ4_VLDBYTES (1L<<10)
+#define BNX2_RPM_DEBUG8_NXT_EOF_W_12_VLDBYTES (1L<<11)
+#define BNX2_RPM_DEBUG8_EOF_DET (1L<<12)
+#define BNX2_RPM_DEBUG8_SOF_DET (1L<<13)
+#define BNX2_RPM_DEBUG8_WAIT_4_SOF (1L<<14)
+#define BNX2_RPM_DEBUG8_ALL_DONE (1L<<15)
+#define BNX2_RPM_DEBUG8_THBUF_ADDR (0x7fL<<16)
+#define BNX2_RPM_DEBUG8_BYTE_CTR (0xffL<<24)
+
+#define BNX2_RPM_DEBUG9 0x000019a8
+#define BNX2_RPM_DEBUG9_OUTFIFO_COUNT (0x7L<<0)
+#define BNX2_RPM_DEBUG9_RDE_ACPI_RDY (1L<<3)
+#define BNX2_RPM_DEBUG9_VLD_RD_ENTRY_CT (0x7L<<4)
+#define BNX2_RPM_DEBUG9_OUTFIFO_OVERRUN_OCCURRED (1L<<28)
+#define BNX2_RPM_DEBUG9_INFIFO_OVERRUN_OCCURRED (1L<<29)
+#define BNX2_RPM_DEBUG9_ACPI_MATCH_INT (1L<<30)
+#define BNX2_RPM_DEBUG9_ACPI_ENABLE_SYN (1L<<31)
+
+#define BNX2_RPM_ACPI_DBG_BUF_W00 0x000019c0
+#define BNX2_RPM_ACPI_DBG_BUF_W01 0x000019c4
+#define BNX2_RPM_ACPI_DBG_BUF_W02 0x000019c8
+#define BNX2_RPM_ACPI_DBG_BUF_W03 0x000019cc
+#define BNX2_RPM_ACPI_DBG_BUF_W10 0x000019d0
+#define BNX2_RPM_ACPI_DBG_BUF_W11 0x000019d4
+#define BNX2_RPM_ACPI_DBG_BUF_W12 0x000019d8
+#define BNX2_RPM_ACPI_DBG_BUF_W13 0x000019dc
+#define BNX2_RPM_ACPI_DBG_BUF_W20 0x000019e0
+#define BNX2_RPM_ACPI_DBG_BUF_W21 0x000019e4
+#define BNX2_RPM_ACPI_DBG_BUF_W22 0x000019e8
+#define BNX2_RPM_ACPI_DBG_BUF_W23 0x000019ec
+#define BNX2_RPM_ACPI_DBG_BUF_W30 0x000019f0
+#define BNX2_RPM_ACPI_DBG_BUF_W31 0x000019f4
+#define BNX2_RPM_ACPI_DBG_BUF_W32 0x000019f8
+#define BNX2_RPM_ACPI_DBG_BUF_W33 0x000019fc
+
+
+/*
+ * rbuf_reg definition
+ * offset: 0x200000
+ */
+#define BNX2_RBUF_COMMAND 0x00200000
+#define BNX2_RBUF_COMMAND_ENABLED (1L<<0)
+#define BNX2_RBUF_COMMAND_FREE_INIT (1L<<1)
+#define BNX2_RBUF_COMMAND_RAM_INIT (1L<<2)
+#define BNX2_RBUF_COMMAND_OVER_FREE (1L<<4)
+#define BNX2_RBUF_COMMAND_ALLOC_REQ (1L<<5)
+
+#define BNX2_RBUF_STATUS1 0x00200004
+#define BNX2_RBUF_STATUS1_FREE_COUNT (0x3ffL<<0)
+
+#define BNX2_RBUF_STATUS2 0x00200008
+#define BNX2_RBUF_STATUS2_FREE_TAIL (0x3ffL<<0)
+#define BNX2_RBUF_STATUS2_FREE_HEAD (0x3ffL<<16)
+
+#define BNX2_RBUF_CONFIG 0x0020000c
+#define BNX2_RBUF_CONFIG_XOFF_TRIP (0x3ffL<<0)
+#define BNX2_RBUF_CONFIG_XON_TRIP (0x3ffL<<16)
+
+#define BNX2_RBUF_FW_BUF_ALLOC 0x00200010
+#define BNX2_RBUF_FW_BUF_ALLOC_VALUE (0x1ffL<<7)
+
+#define BNX2_RBUF_FW_BUF_FREE 0x00200014
+#define BNX2_RBUF_FW_BUF_FREE_COUNT (0x7fL<<0)
+#define BNX2_RBUF_FW_BUF_FREE_TAIL (0x1ffL<<7)
+#define BNX2_RBUF_FW_BUF_FREE_HEAD (0x1ffL<<16)
+
+#define BNX2_RBUF_FW_BUF_SEL 0x00200018
+#define BNX2_RBUF_FW_BUF_SEL_COUNT (0x7fL<<0)
+#define BNX2_RBUF_FW_BUF_SEL_TAIL (0x1ffL<<7)
+#define BNX2_RBUF_FW_BUF_SEL_HEAD (0x1ffL<<16)
+
+#define BNX2_RBUF_CONFIG2 0x0020001c
+#define BNX2_RBUF_CONFIG2_MAC_DROP_TRIP (0x3ffL<<0)
+#define BNX2_RBUF_CONFIG2_MAC_KEEP_TRIP (0x3ffL<<16)
+
+#define BNX2_RBUF_CONFIG3 0x00200020
+#define BNX2_RBUF_CONFIG3_CU_DROP_TRIP (0x3ffL<<0)
+#define BNX2_RBUF_CONFIG3_CU_KEEP_TRIP (0x3ffL<<16)
+
+#define BNX2_RBUF_PKT_DATA 0x00208000
+#define BNX2_RBUF_CLIST_DATA 0x00210000
+#define BNX2_RBUF_BUF_DATA 0x00220000
+
+
+/*
+ * rv2p_reg definition
+ * offset: 0x2800
+ */
+#define BNX2_RV2P_COMMAND 0x00002800
+#define BNX2_RV2P_COMMAND_ENABLED (1L<<0)
+#define BNX2_RV2P_COMMAND_PROC1_INTRPT (1L<<1)
+#define BNX2_RV2P_COMMAND_PROC2_INTRPT (1L<<2)
+#define BNX2_RV2P_COMMAND_ABORT0 (1L<<4)
+#define BNX2_RV2P_COMMAND_ABORT1 (1L<<5)
+#define BNX2_RV2P_COMMAND_ABORT2 (1L<<6)
+#define BNX2_RV2P_COMMAND_ABORT3 (1L<<7)
+#define BNX2_RV2P_COMMAND_ABORT4 (1L<<8)
+#define BNX2_RV2P_COMMAND_ABORT5 (1L<<9)
+#define BNX2_RV2P_COMMAND_PROC1_RESET (1L<<16)
+#define BNX2_RV2P_COMMAND_PROC2_RESET (1L<<17)
+#define BNX2_RV2P_COMMAND_CTXIF_RESET (1L<<18)
+
+#define BNX2_RV2P_STATUS 0x00002804
+#define BNX2_RV2P_STATUS_ALWAYS_0 (1L<<0)
+#define BNX2_RV2P_STATUS_RV2P_GEN_STAT0_CNT (1L<<8)
+#define BNX2_RV2P_STATUS_RV2P_GEN_STAT1_CNT (1L<<9)
+#define BNX2_RV2P_STATUS_RV2P_GEN_STAT2_CNT (1L<<10)
+#define BNX2_RV2P_STATUS_RV2P_GEN_STAT3_CNT (1L<<11)
+#define BNX2_RV2P_STATUS_RV2P_GEN_STAT4_CNT (1L<<12)
+#define BNX2_RV2P_STATUS_RV2P_GEN_STAT5_CNT (1L<<13)
+
+#define BNX2_RV2P_CONFIG 0x00002808
+#define BNX2_RV2P_CONFIG_STALL_PROC1 (1L<<0)
+#define BNX2_RV2P_CONFIG_STALL_PROC2 (1L<<1)
+#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT0 (1L<<8)
+#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT1 (1L<<9)
+#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT2 (1L<<10)
+#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT3 (1L<<11)
+#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT4 (1L<<12)
+#define BNX2_RV2P_CONFIG_PROC1_STALL_ON_ABORT5 (1L<<13)
+#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT0 (1L<<16)
+#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT1 (1L<<17)
+#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT2 (1L<<18)
+#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT3 (1L<<19)
+#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT4 (1L<<20)
+#define BNX2_RV2P_CONFIG_PROC2_STALL_ON_ABORT5 (1L<<21)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE (0xfL<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_256 (0L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_512 (1L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_1K (2L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_2K (3L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_4K (4L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_8K (5L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_16K (6L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_32K (7L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_64K (8L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_128K (9L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_256K (10L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_512K (11L<<24)
+#define BNX2_RV2P_CONFIG_PAGE_SIZE_1M (12L<<24)
+
+#define BNX2_RV2P_GEN_BFR_ADDR_0 0x00002810
+#define BNX2_RV2P_GEN_BFR_ADDR_0_VALUE (0xffffL<<16)
+
+#define BNX2_RV2P_GEN_BFR_ADDR_1 0x00002814
+#define BNX2_RV2P_GEN_BFR_ADDR_1_VALUE (0xffffL<<16)
+
+#define BNX2_RV2P_GEN_BFR_ADDR_2 0x00002818
+#define BNX2_RV2P_GEN_BFR_ADDR_2_VALUE (0xffffL<<16)
+
+#define BNX2_RV2P_GEN_BFR_ADDR_3 0x0000281c
+#define BNX2_RV2P_GEN_BFR_ADDR_3_VALUE (0xffffL<<16)
+
+#define BNX2_RV2P_INSTR_HIGH 0x00002830
+#define BNX2_RV2P_INSTR_HIGH_HIGH (0x1fL<<0)
+
+#define BNX2_RV2P_INSTR_LOW 0x00002834
+#define BNX2_RV2P_PROC1_ADDR_CMD 0x00002838
+#define BNX2_RV2P_PROC1_ADDR_CMD_ADD (0x3ffL<<0)
+#define BNX2_RV2P_PROC1_ADDR_CMD_RDWR (1L<<31)
+
+#define BNX2_RV2P_PROC2_ADDR_CMD 0x0000283c
+#define BNX2_RV2P_PROC2_ADDR_CMD_ADD (0x3ffL<<0)
+#define BNX2_RV2P_PROC2_ADDR_CMD_RDWR (1L<<31)
+
+#define BNX2_RV2P_PROC1_GRC_DEBUG 0x00002840
+#define BNX2_RV2P_PROC2_GRC_DEBUG 0x00002844
+#define BNX2_RV2P_GRC_PROC_DEBUG 0x00002848
+#define BNX2_RV2P_DEBUG_VECT_PEEK 0x0000284c
+#define BNX2_RV2P_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_RV2P_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_RV2P_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_RV2P_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_RV2P_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_RV2P_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+#define BNX2_RV2P_PFTQ_DATA 0x00002b40
+#define BNX2_RV2P_PFTQ_CMD 0x00002b78
+#define BNX2_RV2P_PFTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_RV2P_PFTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_RV2P_PFTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_RV2P_PFTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_RV2P_PFTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_RV2P_PFTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_RV2P_PFTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_RV2P_PFTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_RV2P_PFTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_RV2P_PFTQ_CMD_POP (1L<<30)
+#define BNX2_RV2P_PFTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_RV2P_PFTQ_CTL 0x00002b7c
+#define BNX2_RV2P_PFTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_RV2P_PFTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_RV2P_PFTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_RV2P_PFTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_RV2P_PFTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_RV2P_TFTQ_DATA 0x00002b80
+#define BNX2_RV2P_TFTQ_CMD 0x00002bb8
+#define BNX2_RV2P_TFTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_RV2P_TFTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_RV2P_TFTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_RV2P_TFTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_RV2P_TFTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_RV2P_TFTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_RV2P_TFTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_RV2P_TFTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_RV2P_TFTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_RV2P_TFTQ_CMD_POP (1L<<30)
+#define BNX2_RV2P_TFTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_RV2P_TFTQ_CTL 0x00002bbc
+#define BNX2_RV2P_TFTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_RV2P_TFTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_RV2P_TFTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_RV2P_TFTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_RV2P_TFTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_RV2P_MFTQ_DATA 0x00002bc0
+#define BNX2_RV2P_MFTQ_CMD 0x00002bf8
+#define BNX2_RV2P_MFTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_RV2P_MFTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_RV2P_MFTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_RV2P_MFTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_RV2P_MFTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_RV2P_MFTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_RV2P_MFTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_RV2P_MFTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_RV2P_MFTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_RV2P_MFTQ_CMD_POP (1L<<30)
+#define BNX2_RV2P_MFTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_RV2P_MFTQ_CTL 0x00002bfc
+#define BNX2_RV2P_MFTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_RV2P_MFTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_RV2P_MFTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_RV2P_MFTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_RV2P_MFTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+
+
+/*
+ * mq_reg definition
+ * offset: 0x3c00
+ */
+#define BNX2_MQ_COMMAND 0x00003c00
+#define BNX2_MQ_COMMAND_ENABLED (1L<<0)
+#define BNX2_MQ_COMMAND_OVERFLOW (1L<<4)
+#define BNX2_MQ_COMMAND_WR_ERROR (1L<<5)
+#define BNX2_MQ_COMMAND_RD_ERROR (1L<<6)
+
+#define BNX2_MQ_STATUS 0x00003c04
+#define BNX2_MQ_STATUS_CTX_ACCESS_STAT (1L<<16)
+#define BNX2_MQ_STATUS_CTX_ACCESS64_STAT (1L<<17)
+#define BNX2_MQ_STATUS_PCI_STALL_STAT (1L<<18)
+
+#define BNX2_MQ_CONFIG 0x00003c08
+#define BNX2_MQ_CONFIG_TX_HIGH_PRI (1L<<0)
+#define BNX2_MQ_CONFIG_HALT_DIS (1L<<1)
+#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE (0x7L<<4)
+#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_256 (0L<<4)
+#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_512 (1L<<4)
+#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_1K (2L<<4)
+#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_2K (3L<<4)
+#define BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_4K (4L<<4)
+#define BNX2_MQ_CONFIG_MAX_DEPTH (0x7fL<<8)
+#define BNX2_MQ_CONFIG_CUR_DEPTH (0x7fL<<20)
+
+#define BNX2_MQ_ENQUEUE1 0x00003c0c
+#define BNX2_MQ_ENQUEUE1_OFFSET (0x3fL<<2)
+#define BNX2_MQ_ENQUEUE1_CID (0x3fffL<<8)
+#define BNX2_MQ_ENQUEUE1_BYTE_MASK (0xfL<<24)
+#define BNX2_MQ_ENQUEUE1_KNL_MODE (1L<<28)
+
+#define BNX2_MQ_ENQUEUE2 0x00003c10
+#define BNX2_MQ_BAD_WR_ADDR 0x00003c14
+#define BNX2_MQ_BAD_RD_ADDR 0x00003c18
+#define BNX2_MQ_KNL_BYP_WIND_START 0x00003c1c
+#define BNX2_MQ_KNL_BYP_WIND_START_VALUE (0xfffffL<<12)
+
+#define BNX2_MQ_KNL_WIND_END 0x00003c20
+#define BNX2_MQ_KNL_WIND_END_VALUE (0xffffffL<<8)
+
+#define BNX2_MQ_KNL_WRITE_MASK1 0x00003c24
+#define BNX2_MQ_KNL_TX_MASK1 0x00003c28
+#define BNX2_MQ_KNL_CMD_MASK1 0x00003c2c
+#define BNX2_MQ_KNL_COND_ENQUEUE_MASK1 0x00003c30
+#define BNX2_MQ_KNL_RX_V2P_MASK1 0x00003c34
+#define BNX2_MQ_KNL_WRITE_MASK2 0x00003c38
+#define BNX2_MQ_KNL_TX_MASK2 0x00003c3c
+#define BNX2_MQ_KNL_CMD_MASK2 0x00003c40
+#define BNX2_MQ_KNL_COND_ENQUEUE_MASK2 0x00003c44
+#define BNX2_MQ_KNL_RX_V2P_MASK2 0x00003c48
+#define BNX2_MQ_KNL_BYP_WRITE_MASK1 0x00003c4c
+#define BNX2_MQ_KNL_BYP_TX_MASK1 0x00003c50
+#define BNX2_MQ_KNL_BYP_CMD_MASK1 0x00003c54
+#define BNX2_MQ_KNL_BYP_COND_ENQUEUE_MASK1 0x00003c58
+#define BNX2_MQ_KNL_BYP_RX_V2P_MASK1 0x00003c5c
+#define BNX2_MQ_KNL_BYP_WRITE_MASK2 0x00003c60
+#define BNX2_MQ_KNL_BYP_TX_MASK2 0x00003c64
+#define BNX2_MQ_KNL_BYP_CMD_MASK2 0x00003c68
+#define BNX2_MQ_KNL_BYP_COND_ENQUEUE_MASK2 0x00003c6c
+#define BNX2_MQ_KNL_BYP_RX_V2P_MASK2 0x00003c70
+#define BNX2_MQ_MEM_WR_ADDR 0x00003c74
+#define BNX2_MQ_MEM_WR_ADDR_VALUE (0x3fL<<0)
+
+#define BNX2_MQ_MEM_WR_DATA0 0x00003c78
+#define BNX2_MQ_MEM_WR_DATA0_VALUE (0xffffffffL<<0)
+
+#define BNX2_MQ_MEM_WR_DATA1 0x00003c7c
+#define BNX2_MQ_MEM_WR_DATA1_VALUE (0xffffffffL<<0)
+
+#define BNX2_MQ_MEM_WR_DATA2 0x00003c80
+#define BNX2_MQ_MEM_WR_DATA2_VALUE (0x3fffffffL<<0)
+
+#define BNX2_MQ_MEM_RD_ADDR 0x00003c84
+#define BNX2_MQ_MEM_RD_ADDR_VALUE (0x3fL<<0)
+
+#define BNX2_MQ_MEM_RD_DATA0 0x00003c88
+#define BNX2_MQ_MEM_RD_DATA0_VALUE (0xffffffffL<<0)
+
+#define BNX2_MQ_MEM_RD_DATA1 0x00003c8c
+#define BNX2_MQ_MEM_RD_DATA1_VALUE (0xffffffffL<<0)
+
+#define BNX2_MQ_MEM_RD_DATA2 0x00003c90
+#define BNX2_MQ_MEM_RD_DATA2_VALUE (0x3fffffffL<<0)
+
+
+
+/*
+ * tbdr_reg definition
+ * offset: 0x5000
+ */
+#define BNX2_TBDR_COMMAND 0x00005000
+#define BNX2_TBDR_COMMAND_ENABLE (1L<<0)
+#define BNX2_TBDR_COMMAND_SOFT_RST (1L<<1)
+#define BNX2_TBDR_COMMAND_MSTR_ABORT (1L<<4)
+
+#define BNX2_TBDR_STATUS 0x00005004
+#define BNX2_TBDR_STATUS_DMA_WAIT (1L<<0)
+#define BNX2_TBDR_STATUS_FTQ_WAIT (1L<<1)
+#define BNX2_TBDR_STATUS_FIFO_OVERFLOW (1L<<2)
+#define BNX2_TBDR_STATUS_FIFO_UNDERFLOW (1L<<3)
+#define BNX2_TBDR_STATUS_SEARCHMISS_ERROR (1L<<4)
+#define BNX2_TBDR_STATUS_FTQ_ENTRY_CNT (1L<<5)
+#define BNX2_TBDR_STATUS_BURST_CNT (1L<<6)
+
+#define BNX2_TBDR_CONFIG 0x00005008
+#define BNX2_TBDR_CONFIG_MAX_BDS (0xffL<<0)
+#define BNX2_TBDR_CONFIG_SWAP_MODE (1L<<8)
+#define BNX2_TBDR_CONFIG_PRIORITY (1L<<9)
+#define BNX2_TBDR_CONFIG_CACHE_NEXT_PAGE_PTRS (1L<<10)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE (0xfL<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_256 (0L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_512 (1L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_1K (2L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_2K (3L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_4K (4L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_8K (5L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_16K (6L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_32K (7L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_64K (8L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_128K (9L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_256K (10L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_512K (11L<<24)
+#define BNX2_TBDR_CONFIG_PAGE_SIZE_1M (12L<<24)
+
+#define BNX2_TBDR_DEBUG_VECT_PEEK 0x0000500c
+#define BNX2_TBDR_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_TBDR_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_TBDR_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_TBDR_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_TBDR_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_TBDR_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+#define BNX2_TBDR_FTQ_DATA 0x000053c0
+#define BNX2_TBDR_FTQ_CMD 0x000053f8
+#define BNX2_TBDR_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_TBDR_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_TBDR_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_TBDR_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_TBDR_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_TBDR_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_TBDR_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_TBDR_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_TBDR_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_TBDR_FTQ_CMD_POP (1L<<30)
+#define BNX2_TBDR_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_TBDR_FTQ_CTL 0x000053fc
+#define BNX2_TBDR_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_TBDR_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_TBDR_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_TBDR_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_TBDR_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+
+
+/*
+ * tdma_reg definition
+ * offset: 0x5c00
+ */
+#define BNX2_TDMA_COMMAND 0x00005c00
+#define BNX2_TDMA_COMMAND_ENABLED (1L<<0)
+#define BNX2_TDMA_COMMAND_MASTER_ABORT (1L<<4)
+#define BNX2_TDMA_COMMAND_BAD_L2_LENGTH_ABORT (1L<<7)
+
+#define BNX2_TDMA_STATUS 0x00005c04
+#define BNX2_TDMA_STATUS_DMA_WAIT (1L<<0)
+#define BNX2_TDMA_STATUS_PAYLOAD_WAIT (1L<<1)
+#define BNX2_TDMA_STATUS_PATCH_FTQ_WAIT (1L<<2)
+#define BNX2_TDMA_STATUS_LOCK_WAIT (1L<<3)
+#define BNX2_TDMA_STATUS_FTQ_ENTRY_CNT (1L<<16)
+#define BNX2_TDMA_STATUS_BURST_CNT (1L<<17)
+
+#define BNX2_TDMA_CONFIG 0x00005c08
+#define BNX2_TDMA_CONFIG_ONE_DMA (1L<<0)
+#define BNX2_TDMA_CONFIG_ONE_RECORD (1L<<1)
+#define BNX2_TDMA_CONFIG_LIMIT_SZ (0xfL<<4)
+#define BNX2_TDMA_CONFIG_LIMIT_SZ_64 (0L<<4)
+#define BNX2_TDMA_CONFIG_LIMIT_SZ_128 (0x4L<<4)
+#define BNX2_TDMA_CONFIG_LIMIT_SZ_256 (0x6L<<4)
+#define BNX2_TDMA_CONFIG_LIMIT_SZ_512 (0x8L<<4)
+#define BNX2_TDMA_CONFIG_LINE_SZ (0xfL<<8)
+#define BNX2_TDMA_CONFIG_LINE_SZ_64 (0L<<8)
+#define BNX2_TDMA_CONFIG_LINE_SZ_128 (4L<<8)
+#define BNX2_TDMA_CONFIG_LINE_SZ_256 (6L<<8)
+#define BNX2_TDMA_CONFIG_LINE_SZ_512 (8L<<8)
+#define BNX2_TDMA_CONFIG_ALIGN_ENA (1L<<15)
+#define BNX2_TDMA_CONFIG_CHK_L2_BD (1L<<16)
+#define BNX2_TDMA_CONFIG_FIFO_CMP (0xfL<<20)
+
+#define BNX2_TDMA_PAYLOAD_PROD 0x00005c0c
+#define BNX2_TDMA_PAYLOAD_PROD_VALUE (0x1fffL<<3)
+
+#define BNX2_TDMA_DBG_WATCHDOG 0x00005c10
+#define BNX2_TDMA_DBG_TRIGGER 0x00005c14
+#define BNX2_TDMA_DMAD_FSM 0x00005c80
+#define BNX2_TDMA_DMAD_FSM_BD_INVLD (1L<<0)
+#define BNX2_TDMA_DMAD_FSM_PUSH (0xfL<<4)
+#define BNX2_TDMA_DMAD_FSM_ARB_TBDC (0x3L<<8)
+#define BNX2_TDMA_DMAD_FSM_ARB_CTX (1L<<12)
+#define BNX2_TDMA_DMAD_FSM_DR_INTF (1L<<16)
+#define BNX2_TDMA_DMAD_FSM_DMAD (0x7L<<20)
+#define BNX2_TDMA_DMAD_FSM_BD (0xfL<<24)
+
+#define BNX2_TDMA_DMAD_STATUS 0x00005c84
+#define BNX2_TDMA_DMAD_STATUS_RHOLD_PUSH_ENTRY (0x3L<<0)
+#define BNX2_TDMA_DMAD_STATUS_RHOLD_DMAD_ENTRY (0x3L<<4)
+#define BNX2_TDMA_DMAD_STATUS_RHOLD_BD_ENTRY (0x3L<<8)
+#define BNX2_TDMA_DMAD_STATUS_IFTQ_ENUM (0xfL<<12)
+
+#define BNX2_TDMA_DR_INTF_FSM 0x00005c88
+#define BNX2_TDMA_DR_INTF_FSM_L2_COMP (0x3L<<0)
+#define BNX2_TDMA_DR_INTF_FSM_TPATQ (0x7L<<4)
+#define BNX2_TDMA_DR_INTF_FSM_TPBUF (0x3L<<8)
+#define BNX2_TDMA_DR_INTF_FSM_DR_BUF (0x7L<<12)
+#define BNX2_TDMA_DR_INTF_FSM_DMAD (0x7L<<16)
+
+#define BNX2_TDMA_DR_INTF_STATUS 0x00005c8c
+#define BNX2_TDMA_DR_INTF_STATUS_HOLE_PHASE (0x7L<<0)
+#define BNX2_TDMA_DR_INTF_STATUS_DATA_AVAIL (0x3L<<4)
+#define BNX2_TDMA_DR_INTF_STATUS_SHIFT_ADDR (0x7L<<8)
+#define BNX2_TDMA_DR_INTF_STATUS_NXT_PNTR (0xfL<<12)
+#define BNX2_TDMA_DR_INTF_STATUS_BYTE_COUNT (0x7L<<16)
+
+#define BNX2_TDMA_FTQ_DATA 0x00005fc0
+#define BNX2_TDMA_FTQ_CMD 0x00005ff8
+#define BNX2_TDMA_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_TDMA_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_TDMA_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_TDMA_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_TDMA_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_TDMA_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_TDMA_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_TDMA_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_TDMA_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_TDMA_FTQ_CMD_POP (1L<<30)
+#define BNX2_TDMA_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_TDMA_FTQ_CTL 0x00005ffc
+#define BNX2_TDMA_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_TDMA_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_TDMA_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_TDMA_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_TDMA_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+
+
+/*
+ * hc_reg definition
+ * offset: 0x6800
+ */
+#define BNX2_HC_COMMAND 0x00006800
+#define BNX2_HC_COMMAND_ENABLE (1L<<0)
+#define BNX2_HC_COMMAND_SKIP_ABORT (1L<<4)
+#define BNX2_HC_COMMAND_COAL_NOW (1L<<16)
+#define BNX2_HC_COMMAND_COAL_NOW_WO_INT (1L<<17)
+#define BNX2_HC_COMMAND_STATS_NOW (1L<<18)
+#define BNX2_HC_COMMAND_FORCE_INT (0x3L<<19)
+#define BNX2_HC_COMMAND_FORCE_INT_NULL (0L<<19)
+#define BNX2_HC_COMMAND_FORCE_INT_HIGH (1L<<19)
+#define BNX2_HC_COMMAND_FORCE_INT_LOW (2L<<19)
+#define BNX2_HC_COMMAND_FORCE_INT_FREE (3L<<19)
+#define BNX2_HC_COMMAND_CLR_STAT_NOW (1L<<21)
+
+#define BNX2_HC_STATUS 0x00006804
+#define BNX2_HC_STATUS_MASTER_ABORT (1L<<0)
+#define BNX2_HC_STATUS_PARITY_ERROR_STATE (1L<<1)
+#define BNX2_HC_STATUS_PCI_CLK_CNT_STAT (1L<<16)
+#define BNX2_HC_STATUS_CORE_CLK_CNT_STAT (1L<<17)
+#define BNX2_HC_STATUS_NUM_STATUS_BLOCKS_STAT (1L<<18)
+#define BNX2_HC_STATUS_NUM_INT_GEN_STAT (1L<<19)
+#define BNX2_HC_STATUS_NUM_INT_MBOX_WR_STAT (1L<<20)
+#define BNX2_HC_STATUS_CORE_CLKS_TO_HW_INTACK_STAT (1L<<23)
+#define BNX2_HC_STATUS_CORE_CLKS_TO_SW_INTACK_STAT (1L<<24)
+#define BNX2_HC_STATUS_CORE_CLKS_DURING_SW_INTACK_STAT (1L<<25)
+
+#define BNX2_HC_CONFIG 0x00006808
+#define BNX2_HC_CONFIG_COLLECT_STATS (1L<<0)
+#define BNX2_HC_CONFIG_RX_TMR_MODE (1L<<1)
+#define BNX2_HC_CONFIG_TX_TMR_MODE (1L<<2)
+#define BNX2_HC_CONFIG_COM_TMR_MODE (1L<<3)
+#define BNX2_HC_CONFIG_CMD_TMR_MODE (1L<<4)
+#define BNX2_HC_CONFIG_STATISTIC_PRIORITY (1L<<5)
+#define BNX2_HC_CONFIG_STATUS_PRIORITY (1L<<6)
+#define BNX2_HC_CONFIG_STAT_MEM_ADDR (0xffL<<8)
+
+#define BNX2_HC_ATTN_BITS_ENABLE 0x0000680c
+#define BNX2_HC_STATUS_ADDR_L 0x00006810
+#define BNX2_HC_STATUS_ADDR_H 0x00006814
+#define BNX2_HC_STATISTICS_ADDR_L 0x00006818
+#define BNX2_HC_STATISTICS_ADDR_H 0x0000681c
+#define BNX2_HC_TX_QUICK_CONS_TRIP 0x00006820
+#define BNX2_HC_TX_QUICK_CONS_TRIP_VALUE (0xffL<<0)
+#define BNX2_HC_TX_QUICK_CONS_TRIP_INT (0xffL<<16)
+
+#define BNX2_HC_COMP_PROD_TRIP 0x00006824
+#define BNX2_HC_COMP_PROD_TRIP_VALUE (0xffL<<0)
+#define BNX2_HC_COMP_PROD_TRIP_INT (0xffL<<16)
+
+#define BNX2_HC_RX_QUICK_CONS_TRIP 0x00006828
+#define BNX2_HC_RX_QUICK_CONS_TRIP_VALUE (0xffL<<0)
+#define BNX2_HC_RX_QUICK_CONS_TRIP_INT (0xffL<<16)
+
+#define BNX2_HC_RX_TICKS 0x0000682c
+#define BNX2_HC_RX_TICKS_VALUE (0x3ffL<<0)
+#define BNX2_HC_RX_TICKS_INT (0x3ffL<<16)
+
+#define BNX2_HC_TX_TICKS 0x00006830
+#define BNX2_HC_TX_TICKS_VALUE (0x3ffL<<0)
+#define BNX2_HC_TX_TICKS_INT (0x3ffL<<16)
+
+#define BNX2_HC_COM_TICKS 0x00006834
+#define BNX2_HC_COM_TICKS_VALUE (0x3ffL<<0)
+#define BNX2_HC_COM_TICKS_INT (0x3ffL<<16)
+
+#define BNX2_HC_CMD_TICKS 0x00006838
+#define BNX2_HC_CMD_TICKS_VALUE (0x3ffL<<0)
+#define BNX2_HC_CMD_TICKS_INT (0x3ffL<<16)
+
+#define BNX2_HC_PERIODIC_TICKS 0x0000683c
+#define BNX2_HC_PERIODIC_TICKS_HC_PERIODIC_TICKS (0xffffL<<0)
+
+#define BNX2_HC_STAT_COLLECT_TICKS 0x00006840
+#define BNX2_HC_STAT_COLLECT_TICKS_HC_STAT_COLL_TICKS (0xffL<<4)
+
+#define BNX2_HC_STATS_TICKS 0x00006844
+#define BNX2_HC_STATS_TICKS_HC_STAT_TICKS (0xffffL<<8)
+
+#define BNX2_HC_STAT_MEM_DATA 0x0000684c
+#define BNX2_HC_STAT_GEN_SEL_0 0x00006850
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0 (0x7fL<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT0 (0L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT1 (1L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT2 (2L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT3 (3L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT4 (4L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT5 (5L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT6 (6L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT7 (7L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT8 (8L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT9 (9L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT10 (10L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXP_STAT11 (11L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT0 (12L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT1 (13L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT2 (14L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT3 (15L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT4 (16L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT5 (17L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT6 (18L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXP_STAT7 (19L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT0 (20L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT1 (21L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT2 (22L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT3 (23L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT4 (24L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT5 (25L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT6 (26L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT7 (27L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT8 (28L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT9 (29L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT10 (30L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COM_STAT11 (31L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT0 (32L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT1 (33L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT2 (34L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPAT_STAT3 (35L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT0 (36L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT1 (37L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT2 (38L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT3 (39L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT4 (40L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT5 (41L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT6 (42L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CP_STAT7 (43L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT0 (44L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT1 (45L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT2 (46L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT3 (47L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT4 (48L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT5 (49L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT6 (50L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MCP_STAT7 (51L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_PCI_CLK_CNT (52L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CORE_CLK_CNT (53L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_STATUS_BLOCKS (54L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_GEN (55L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_NUM_INT_MBOX_WR (56L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_HW_INTACK (59L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_TO_SW_INTACK (60L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_HC_CORE_CLKS_DURING_SW_INTACK (61L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TSCH_CMD_CNT (62L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TSCH_SLOT_CNT (63L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CSCH_CMD_CNT (64L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CSCH_SLOT_CNT (65L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RLUPQ_VALID_CNT (66L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXPQ_VALID_CNT (67L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RXPCQ_VALID_CNT (68L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PPQ_VALID_CNT (69L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PMQ_VALID_CNT (70L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2PTQ_VALID_CNT (71L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RDMAQ_VALID_CNT (72L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TSCHQ_VALID_CNT (73L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TBDRQ_VALID_CNT (74L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TXPQ_VALID_CNT (75L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TDMAQ_VALID_CNT (76L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TPATQ_VALID_CNT (77L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TASQ_VALID_CNT (78L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CSQ_VALID_CNT (79L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CPQ_VALID_CNT (80L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COMXQ_VALID_CNT (81L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COMTQ_VALID_CNT (82L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_COMQ_VALID_CNT (83L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MGMQ_VALID_CNT (84L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_READ_TRANSFERS_CNT (85L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_READ_DELAY_PCI_CLKS_CNT (86L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_READ_TRANSFERS_CNT (87L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_READ_DELAY_PCI_CLKS_CNT (88L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_READ_RETRY_AFTER_DATA_CNT (89L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_WRITE_TRANSFERS_CNT (90L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_WRITE_DELAY_PCI_CLKS_CNT (91L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_WRITE_TRANSFERS_CNT (92L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_WRITE_DELAY_PCI_CLKS_CNT (93L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_DMAE_BIG_WRITE_RETRY_AFTER_DATA_CNT (94L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_WR_CNT64 (95L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_RD_CNT64 (96L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_ACC_STALL_CLKS (97L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_CTX_LOCK_STALL_CLKS (98L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MBQ_CTX_ACCESS_STAT (99L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MBQ_CTX_ACCESS64_STAT (100L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_MBQ_PCI_STALL_STAT (101L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TBDR_FTQ_ENTRY_CNT (102L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TBDR_BURST_CNT (103L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TDMA_FTQ_ENTRY_CNT (104L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TDMA_BURST_CNT (105L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RDMA_FTQ_ENTRY_CNT (106L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RDMA_BURST_CNT (107L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RLUP_MATCH_CNT (108L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_POLL_PASS_CNT (109L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR1_CNT (110L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR2_CNT (111L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR3_CNT (112L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR4_CNT (113L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_TMR_TMR5_CNT (114L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT0 (115L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT1 (116L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT2 (117L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT3 (118L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT4 (119L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RV2P_STAT5 (120L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RBDC_PROC1_MISS (121L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RBDC_PROC2_MISS (122L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_0_RBDC_BURST_CNT (127L<<0)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_1 (0x7fL<<8)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_2 (0x7fL<<16)
+#define BNX2_HC_STAT_GEN_SEL_0_GEN_SEL_3 (0x7fL<<24)
+
+#define BNX2_HC_STAT_GEN_SEL_1 0x00006854
+#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_4 (0x7fL<<0)
+#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_5 (0x7fL<<8)
+#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_6 (0x7fL<<16)
+#define BNX2_HC_STAT_GEN_SEL_1_GEN_SEL_7 (0x7fL<<24)
+
+#define BNX2_HC_STAT_GEN_SEL_2 0x00006858
+#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_8 (0x7fL<<0)
+#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_9 (0x7fL<<8)
+#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_10 (0x7fL<<16)
+#define BNX2_HC_STAT_GEN_SEL_2_GEN_SEL_11 (0x7fL<<24)
+
+#define BNX2_HC_STAT_GEN_SEL_3 0x0000685c
+#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_12 (0x7fL<<0)
+#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_13 (0x7fL<<8)
+#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_14 (0x7fL<<16)
+#define BNX2_HC_STAT_GEN_SEL_3_GEN_SEL_15 (0x7fL<<24)
+
+#define BNX2_HC_STAT_GEN_STAT0 0x00006888
+#define BNX2_HC_STAT_GEN_STAT1 0x0000688c
+#define BNX2_HC_STAT_GEN_STAT2 0x00006890
+#define BNX2_HC_STAT_GEN_STAT3 0x00006894
+#define BNX2_HC_STAT_GEN_STAT4 0x00006898
+#define BNX2_HC_STAT_GEN_STAT5 0x0000689c
+#define BNX2_HC_STAT_GEN_STAT6 0x000068a0
+#define BNX2_HC_STAT_GEN_STAT7 0x000068a4
+#define BNX2_HC_STAT_GEN_STAT8 0x000068a8
+#define BNX2_HC_STAT_GEN_STAT9 0x000068ac
+#define BNX2_HC_STAT_GEN_STAT10 0x000068b0
+#define BNX2_HC_STAT_GEN_STAT11 0x000068b4
+#define BNX2_HC_STAT_GEN_STAT12 0x000068b8
+#define BNX2_HC_STAT_GEN_STAT13 0x000068bc
+#define BNX2_HC_STAT_GEN_STAT14 0x000068c0
+#define BNX2_HC_STAT_GEN_STAT15 0x000068c4
+#define BNX2_HC_STAT_GEN_STAT_AC0 0x000068c8
+#define BNX2_HC_STAT_GEN_STAT_AC1 0x000068cc
+#define BNX2_HC_STAT_GEN_STAT_AC2 0x000068d0
+#define BNX2_HC_STAT_GEN_STAT_AC3 0x000068d4
+#define BNX2_HC_STAT_GEN_STAT_AC4 0x000068d8
+#define BNX2_HC_STAT_GEN_STAT_AC5 0x000068dc
+#define BNX2_HC_STAT_GEN_STAT_AC6 0x000068e0
+#define BNX2_HC_STAT_GEN_STAT_AC7 0x000068e4
+#define BNX2_HC_STAT_GEN_STAT_AC8 0x000068e8
+#define BNX2_HC_STAT_GEN_STAT_AC9 0x000068ec
+#define BNX2_HC_STAT_GEN_STAT_AC10 0x000068f0
+#define BNX2_HC_STAT_GEN_STAT_AC11 0x000068f4
+#define BNX2_HC_STAT_GEN_STAT_AC12 0x000068f8
+#define BNX2_HC_STAT_GEN_STAT_AC13 0x000068fc
+#define BNX2_HC_STAT_GEN_STAT_AC14 0x00006900
+#define BNX2_HC_STAT_GEN_STAT_AC15 0x00006904
+#define BNX2_HC_VIS 0x00006908
+#define BNX2_HC_VIS_STAT_BUILD_STATE (0xfL<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_IDLE (0L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_START (1L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_REQUEST (2L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_UPDATE64 (3L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_UPDATE32 (4L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_UPDATE_DONE (5L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_DMA (6L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_CONTROL (7L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_LOW (8L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_HIGH (9L<<0)
+#define BNX2_HC_VIS_STAT_BUILD_STATE_MSI_DATA (10L<<0)
+#define BNX2_HC_VIS_DMA_STAT_STATE (0xfL<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_IDLE (0L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_STATUS_PARAM (1L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_STATUS_DMA (2L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_WRITE_COMP (3L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_COMP (4L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_STATISTIC_PARAM (5L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_STATISTIC_DMA (6L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_WRITE_COMP_1 (7L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_WRITE_COMP_2 (8L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_WAIT (9L<<8)
+#define BNX2_HC_VIS_DMA_STAT_STATE_ABORT (15L<<8)
+#define BNX2_HC_VIS_DMA_MSI_STATE (0x7L<<12)
+#define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE (0x3L<<15)
+#define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE_IDLE (0L<<15)
+#define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE_COUNT (1L<<15)
+#define BNX2_HC_VIS_STATISTIC_DMA_EN_STATE_START (2L<<15)
+
+#define BNX2_HC_VIS_1 0x0000690c
+#define BNX2_HC_VIS_1_HW_INTACK_STATE (1L<<4)
+#define BNX2_HC_VIS_1_HW_INTACK_STATE_IDLE (0L<<4)
+#define BNX2_HC_VIS_1_HW_INTACK_STATE_COUNT (1L<<4)
+#define BNX2_HC_VIS_1_SW_INTACK_STATE (1L<<5)
+#define BNX2_HC_VIS_1_SW_INTACK_STATE_IDLE (0L<<5)
+#define BNX2_HC_VIS_1_SW_INTACK_STATE_COUNT (1L<<5)
+#define BNX2_HC_VIS_1_DURING_SW_INTACK_STATE (1L<<6)
+#define BNX2_HC_VIS_1_DURING_SW_INTACK_STATE_IDLE (0L<<6)
+#define BNX2_HC_VIS_1_DURING_SW_INTACK_STATE_COUNT (1L<<6)
+#define BNX2_HC_VIS_1_MAILBOX_COUNT_STATE (1L<<7)
+#define BNX2_HC_VIS_1_MAILBOX_COUNT_STATE_IDLE (0L<<7)
+#define BNX2_HC_VIS_1_MAILBOX_COUNT_STATE_COUNT (1L<<7)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE (0xfL<<17)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_IDLE (0L<<17)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_DMA (1L<<17)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_UPDATE (2L<<17)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_ASSIGN (3L<<17)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_WAIT (4L<<17)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_REG_UPDATE (5L<<17)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_REG_ASSIGN (6L<<17)
+#define BNX2_HC_VIS_1_RAM_RD_ARB_STATE_REG_WAIT (7L<<17)
+#define BNX2_HC_VIS_1_RAM_WR_ARB_STATE (0x3L<<21)
+#define BNX2_HC_VIS_1_RAM_WR_ARB_STATE_NORMAL (0L<<21)
+#define BNX2_HC_VIS_1_RAM_WR_ARB_STATE_CLEAR (1L<<21)
+#define BNX2_HC_VIS_1_INT_GEN_STATE (1L<<23)
+#define BNX2_HC_VIS_1_INT_GEN_STATE_DLE (0L<<23)
+#define BNX2_HC_VIS_1_INT_GEN_STATE_NTERRUPT (1L<<23)
+#define BNX2_HC_VIS_1_STAT_CHAN_ID (0x7L<<24)
+#define BNX2_HC_VIS_1_INT_B (1L<<27)
+
+#define BNX2_HC_DEBUG_VECT_PEEK 0x00006910
+#define BNX2_HC_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_HC_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_HC_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_HC_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_HC_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_HC_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+
+
+/*
+ * txp_reg definition
+ * offset: 0x40000
+ */
+#define BNX2_TXP_CPU_MODE 0x00045000
+#define BNX2_TXP_CPU_MODE_LOCAL_RST (1L<<0)
+#define BNX2_TXP_CPU_MODE_STEP_ENA (1L<<1)
+#define BNX2_TXP_CPU_MODE_PAGE_0_DATA_ENA (1L<<2)
+#define BNX2_TXP_CPU_MODE_PAGE_0_INST_ENA (1L<<3)
+#define BNX2_TXP_CPU_MODE_MSG_BIT1 (1L<<6)
+#define BNX2_TXP_CPU_MODE_INTERRUPT_ENA (1L<<7)
+#define BNX2_TXP_CPU_MODE_SOFT_HALT (1L<<10)
+#define BNX2_TXP_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11)
+#define BNX2_TXP_CPU_MODE_BAD_INST_HALT_ENA (1L<<12)
+#define BNX2_TXP_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13)
+#define BNX2_TXP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15)
+
+#define BNX2_TXP_CPU_STATE 0x00045004
+#define BNX2_TXP_CPU_STATE_BREAKPOINT (1L<<0)
+#define BNX2_TXP_CPU_STATE_BAD_INST_HALTED (1L<<2)
+#define BNX2_TXP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
+#define BNX2_TXP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
+#define BNX2_TXP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
+#define BNX2_TXP_CPU_STATE_BAD_pc_HALTED (1L<<6)
+#define BNX2_TXP_CPU_STATE_ALIGN_HALTED (1L<<7)
+#define BNX2_TXP_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
+#define BNX2_TXP_CPU_STATE_SOFT_HALTED (1L<<10)
+#define BNX2_TXP_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
+#define BNX2_TXP_CPU_STATE_INTERRRUPT (1L<<12)
+#define BNX2_TXP_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
+#define BNX2_TXP_CPU_STATE_INST_FETCH_STALL (1L<<15)
+#define BNX2_TXP_CPU_STATE_BLOCKED_READ (1L<<31)
+
+#define BNX2_TXP_CPU_EVENT_MASK 0x00045008
+#define BNX2_TXP_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0)
+#define BNX2_TXP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2)
+#define BNX2_TXP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3)
+#define BNX2_TXP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4)
+#define BNX2_TXP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5)
+#define BNX2_TXP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6)
+#define BNX2_TXP_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7)
+#define BNX2_TXP_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8)
+#define BNX2_TXP_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10)
+#define BNX2_TXP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11)
+#define BNX2_TXP_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12)
+
+#define BNX2_TXP_CPU_PROGRAM_COUNTER 0x0004501c
+#define BNX2_TXP_CPU_INSTRUCTION 0x00045020
+#define BNX2_TXP_CPU_DATA_ACCESS 0x00045024
+#define BNX2_TXP_CPU_INTERRUPT_ENABLE 0x00045028
+#define BNX2_TXP_CPU_INTERRUPT_VECTOR 0x0004502c
+#define BNX2_TXP_CPU_INTERRUPT_SAVED_PC 0x00045030
+#define BNX2_TXP_CPU_HW_BREAKPOINT 0x00045034
+#define BNX2_TXP_CPU_HW_BREAKPOINT_DISABLE (1L<<0)
+#define BNX2_TXP_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2)
+
+#define BNX2_TXP_CPU_DEBUG_VECT_PEEK 0x00045038
+#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_TXP_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+#define BNX2_TXP_CPU_LAST_BRANCH_ADDR 0x00045048
+#define BNX2_TXP_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1)
+#define BNX2_TXP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1)
+#define BNX2_TXP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1)
+#define BNX2_TXP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
+
+#define BNX2_TXP_CPU_REG_FILE 0x00045200
+#define BNX2_TXP_FTQ_DATA 0x000453c0
+#define BNX2_TXP_FTQ_CMD 0x000453f8
+#define BNX2_TXP_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_TXP_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_TXP_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_TXP_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_TXP_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_TXP_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_TXP_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_TXP_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_TXP_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_TXP_FTQ_CMD_POP (1L<<30)
+#define BNX2_TXP_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_TXP_FTQ_CTL 0x000453fc
+#define BNX2_TXP_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_TXP_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_TXP_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_TXP_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_TXP_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_TXP_SCRATCH 0x00060000
+
+
+/*
+ * tpat_reg definition
+ * offset: 0x80000
+ */
+#define BNX2_TPAT_CPU_MODE 0x00085000
+#define BNX2_TPAT_CPU_MODE_LOCAL_RST (1L<<0)
+#define BNX2_TPAT_CPU_MODE_STEP_ENA (1L<<1)
+#define BNX2_TPAT_CPU_MODE_PAGE_0_DATA_ENA (1L<<2)
+#define BNX2_TPAT_CPU_MODE_PAGE_0_INST_ENA (1L<<3)
+#define BNX2_TPAT_CPU_MODE_MSG_BIT1 (1L<<6)
+#define BNX2_TPAT_CPU_MODE_INTERRUPT_ENA (1L<<7)
+#define BNX2_TPAT_CPU_MODE_SOFT_HALT (1L<<10)
+#define BNX2_TPAT_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11)
+#define BNX2_TPAT_CPU_MODE_BAD_INST_HALT_ENA (1L<<12)
+#define BNX2_TPAT_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13)
+#define BNX2_TPAT_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15)
+
+#define BNX2_TPAT_CPU_STATE 0x00085004
+#define BNX2_TPAT_CPU_STATE_BREAKPOINT (1L<<0)
+#define BNX2_TPAT_CPU_STATE_BAD_INST_HALTED (1L<<2)
+#define BNX2_TPAT_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
+#define BNX2_TPAT_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
+#define BNX2_TPAT_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
+#define BNX2_TPAT_CPU_STATE_BAD_pc_HALTED (1L<<6)
+#define BNX2_TPAT_CPU_STATE_ALIGN_HALTED (1L<<7)
+#define BNX2_TPAT_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
+#define BNX2_TPAT_CPU_STATE_SOFT_HALTED (1L<<10)
+#define BNX2_TPAT_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
+#define BNX2_TPAT_CPU_STATE_INTERRRUPT (1L<<12)
+#define BNX2_TPAT_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
+#define BNX2_TPAT_CPU_STATE_INST_FETCH_STALL (1L<<15)
+#define BNX2_TPAT_CPU_STATE_BLOCKED_READ (1L<<31)
+
+#define BNX2_TPAT_CPU_EVENT_MASK 0x00085008
+#define BNX2_TPAT_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0)
+#define BNX2_TPAT_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2)
+#define BNX2_TPAT_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3)
+#define BNX2_TPAT_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4)
+#define BNX2_TPAT_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5)
+#define BNX2_TPAT_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6)
+#define BNX2_TPAT_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7)
+#define BNX2_TPAT_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8)
+#define BNX2_TPAT_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10)
+#define BNX2_TPAT_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11)
+#define BNX2_TPAT_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12)
+
+#define BNX2_TPAT_CPU_PROGRAM_COUNTER 0x0008501c
+#define BNX2_TPAT_CPU_INSTRUCTION 0x00085020
+#define BNX2_TPAT_CPU_DATA_ACCESS 0x00085024
+#define BNX2_TPAT_CPU_INTERRUPT_ENABLE 0x00085028
+#define BNX2_TPAT_CPU_INTERRUPT_VECTOR 0x0008502c
+#define BNX2_TPAT_CPU_INTERRUPT_SAVED_PC 0x00085030
+#define BNX2_TPAT_CPU_HW_BREAKPOINT 0x00085034
+#define BNX2_TPAT_CPU_HW_BREAKPOINT_DISABLE (1L<<0)
+#define BNX2_TPAT_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2)
+
+#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK 0x00085038
+#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_TPAT_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+#define BNX2_TPAT_CPU_LAST_BRANCH_ADDR 0x00085048
+#define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1)
+#define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1)
+#define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1)
+#define BNX2_TPAT_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
+
+#define BNX2_TPAT_CPU_REG_FILE 0x00085200
+#define BNX2_TPAT_FTQ_DATA 0x000853c0
+#define BNX2_TPAT_FTQ_CMD 0x000853f8
+#define BNX2_TPAT_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_TPAT_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_TPAT_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_TPAT_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_TPAT_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_TPAT_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_TPAT_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_TPAT_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_TPAT_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_TPAT_FTQ_CMD_POP (1L<<30)
+#define BNX2_TPAT_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_TPAT_FTQ_CTL 0x000853fc
+#define BNX2_TPAT_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_TPAT_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_TPAT_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_TPAT_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_TPAT_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_TPAT_SCRATCH 0x000a0000
+
+
+/*
+ * rxp_reg definition
+ * offset: 0xc0000
+ */
+#define BNX2_RXP_CPU_MODE 0x000c5000
+#define BNX2_RXP_CPU_MODE_LOCAL_RST (1L<<0)
+#define BNX2_RXP_CPU_MODE_STEP_ENA (1L<<1)
+#define BNX2_RXP_CPU_MODE_PAGE_0_DATA_ENA (1L<<2)
+#define BNX2_RXP_CPU_MODE_PAGE_0_INST_ENA (1L<<3)
+#define BNX2_RXP_CPU_MODE_MSG_BIT1 (1L<<6)
+#define BNX2_RXP_CPU_MODE_INTERRUPT_ENA (1L<<7)
+#define BNX2_RXP_CPU_MODE_SOFT_HALT (1L<<10)
+#define BNX2_RXP_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11)
+#define BNX2_RXP_CPU_MODE_BAD_INST_HALT_ENA (1L<<12)
+#define BNX2_RXP_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13)
+#define BNX2_RXP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15)
+
+#define BNX2_RXP_CPU_STATE 0x000c5004
+#define BNX2_RXP_CPU_STATE_BREAKPOINT (1L<<0)
+#define BNX2_RXP_CPU_STATE_BAD_INST_HALTED (1L<<2)
+#define BNX2_RXP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
+#define BNX2_RXP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
+#define BNX2_RXP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
+#define BNX2_RXP_CPU_STATE_BAD_pc_HALTED (1L<<6)
+#define BNX2_RXP_CPU_STATE_ALIGN_HALTED (1L<<7)
+#define BNX2_RXP_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
+#define BNX2_RXP_CPU_STATE_SOFT_HALTED (1L<<10)
+#define BNX2_RXP_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
+#define BNX2_RXP_CPU_STATE_INTERRRUPT (1L<<12)
+#define BNX2_RXP_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
+#define BNX2_RXP_CPU_STATE_INST_FETCH_STALL (1L<<15)
+#define BNX2_RXP_CPU_STATE_BLOCKED_READ (1L<<31)
+
+#define BNX2_RXP_CPU_EVENT_MASK 0x000c5008
+#define BNX2_RXP_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0)
+#define BNX2_RXP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2)
+#define BNX2_RXP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3)
+#define BNX2_RXP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4)
+#define BNX2_RXP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5)
+#define BNX2_RXP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6)
+#define BNX2_RXP_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7)
+#define BNX2_RXP_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8)
+#define BNX2_RXP_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10)
+#define BNX2_RXP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11)
+#define BNX2_RXP_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12)
+
+#define BNX2_RXP_CPU_PROGRAM_COUNTER 0x000c501c
+#define BNX2_RXP_CPU_INSTRUCTION 0x000c5020
+#define BNX2_RXP_CPU_DATA_ACCESS 0x000c5024
+#define BNX2_RXP_CPU_INTERRUPT_ENABLE 0x000c5028
+#define BNX2_RXP_CPU_INTERRUPT_VECTOR 0x000c502c
+#define BNX2_RXP_CPU_INTERRUPT_SAVED_PC 0x000c5030
+#define BNX2_RXP_CPU_HW_BREAKPOINT 0x000c5034
+#define BNX2_RXP_CPU_HW_BREAKPOINT_DISABLE (1L<<0)
+#define BNX2_RXP_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2)
+
+#define BNX2_RXP_CPU_DEBUG_VECT_PEEK 0x000c5038
+#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_RXP_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+#define BNX2_RXP_CPU_LAST_BRANCH_ADDR 0x000c5048
+#define BNX2_RXP_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1)
+#define BNX2_RXP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1)
+#define BNX2_RXP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1)
+#define BNX2_RXP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
+
+#define BNX2_RXP_CPU_REG_FILE 0x000c5200
+#define BNX2_RXP_CFTQ_DATA 0x000c5380
+#define BNX2_RXP_CFTQ_CMD 0x000c53b8
+#define BNX2_RXP_CFTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_RXP_CFTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_RXP_CFTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_RXP_CFTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_RXP_CFTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_RXP_CFTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_RXP_CFTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_RXP_CFTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_RXP_CFTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_RXP_CFTQ_CMD_POP (1L<<30)
+#define BNX2_RXP_CFTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_RXP_CFTQ_CTL 0x000c53bc
+#define BNX2_RXP_CFTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_RXP_CFTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_RXP_CFTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_RXP_CFTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_RXP_CFTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_RXP_FTQ_DATA 0x000c53c0
+#define BNX2_RXP_FTQ_CMD 0x000c53f8
+#define BNX2_RXP_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_RXP_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_RXP_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_RXP_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_RXP_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_RXP_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_RXP_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_RXP_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_RXP_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_RXP_FTQ_CMD_POP (1L<<30)
+#define BNX2_RXP_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_RXP_FTQ_CTL 0x000c53fc
+#define BNX2_RXP_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_RXP_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_RXP_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_RXP_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_RXP_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_RXP_SCRATCH 0x000e0000
+
+
+/*
+ * com_reg definition
+ * offset: 0x100000
+ */
+#define BNX2_COM_CPU_MODE 0x00105000
+#define BNX2_COM_CPU_MODE_LOCAL_RST (1L<<0)
+#define BNX2_COM_CPU_MODE_STEP_ENA (1L<<1)
+#define BNX2_COM_CPU_MODE_PAGE_0_DATA_ENA (1L<<2)
+#define BNX2_COM_CPU_MODE_PAGE_0_INST_ENA (1L<<3)
+#define BNX2_COM_CPU_MODE_MSG_BIT1 (1L<<6)
+#define BNX2_COM_CPU_MODE_INTERRUPT_ENA (1L<<7)
+#define BNX2_COM_CPU_MODE_SOFT_HALT (1L<<10)
+#define BNX2_COM_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11)
+#define BNX2_COM_CPU_MODE_BAD_INST_HALT_ENA (1L<<12)
+#define BNX2_COM_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13)
+#define BNX2_COM_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15)
+
+#define BNX2_COM_CPU_STATE 0x00105004
+#define BNX2_COM_CPU_STATE_BREAKPOINT (1L<<0)
+#define BNX2_COM_CPU_STATE_BAD_INST_HALTED (1L<<2)
+#define BNX2_COM_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
+#define BNX2_COM_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
+#define BNX2_COM_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
+#define BNX2_COM_CPU_STATE_BAD_pc_HALTED (1L<<6)
+#define BNX2_COM_CPU_STATE_ALIGN_HALTED (1L<<7)
+#define BNX2_COM_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
+#define BNX2_COM_CPU_STATE_SOFT_HALTED (1L<<10)
+#define BNX2_COM_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
+#define BNX2_COM_CPU_STATE_INTERRRUPT (1L<<12)
+#define BNX2_COM_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
+#define BNX2_COM_CPU_STATE_INST_FETCH_STALL (1L<<15)
+#define BNX2_COM_CPU_STATE_BLOCKED_READ (1L<<31)
+
+#define BNX2_COM_CPU_EVENT_MASK 0x00105008
+#define BNX2_COM_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0)
+#define BNX2_COM_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2)
+#define BNX2_COM_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3)
+#define BNX2_COM_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4)
+#define BNX2_COM_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5)
+#define BNX2_COM_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6)
+#define BNX2_COM_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7)
+#define BNX2_COM_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8)
+#define BNX2_COM_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10)
+#define BNX2_COM_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11)
+#define BNX2_COM_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12)
+
+#define BNX2_COM_CPU_PROGRAM_COUNTER 0x0010501c
+#define BNX2_COM_CPU_INSTRUCTION 0x00105020
+#define BNX2_COM_CPU_DATA_ACCESS 0x00105024
+#define BNX2_COM_CPU_INTERRUPT_ENABLE 0x00105028
+#define BNX2_COM_CPU_INTERRUPT_VECTOR 0x0010502c
+#define BNX2_COM_CPU_INTERRUPT_SAVED_PC 0x00105030
+#define BNX2_COM_CPU_HW_BREAKPOINT 0x00105034
+#define BNX2_COM_CPU_HW_BREAKPOINT_DISABLE (1L<<0)
+#define BNX2_COM_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2)
+
+#define BNX2_COM_CPU_DEBUG_VECT_PEEK 0x00105038
+#define BNX2_COM_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_COM_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_COM_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_COM_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_COM_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_COM_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+#define BNX2_COM_CPU_LAST_BRANCH_ADDR 0x00105048
+#define BNX2_COM_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1)
+#define BNX2_COM_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1)
+#define BNX2_COM_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1)
+#define BNX2_COM_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
+
+#define BNX2_COM_CPU_REG_FILE 0x00105200
+#define BNX2_COM_COMXQ_FTQ_DATA 0x00105340
+#define BNX2_COM_COMXQ_FTQ_CMD 0x00105378
+#define BNX2_COM_COMXQ_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_COM_COMXQ_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_COM_COMXQ_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_COM_COMXQ_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_COM_COMXQ_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_COM_COMXQ_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_COM_COMXQ_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_COM_COMXQ_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_COM_COMXQ_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_COM_COMXQ_FTQ_CMD_POP (1L<<30)
+#define BNX2_COM_COMXQ_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_COM_COMXQ_FTQ_CTL 0x0010537c
+#define BNX2_COM_COMXQ_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_COM_COMXQ_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_COM_COMXQ_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_COM_COMXQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_COM_COMXQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_COM_COMTQ_FTQ_DATA 0x00105380
+#define BNX2_COM_COMTQ_FTQ_CMD 0x001053b8
+#define BNX2_COM_COMTQ_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_COM_COMTQ_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_COM_COMTQ_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_COM_COMTQ_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_COM_COMTQ_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_COM_COMTQ_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_COM_COMTQ_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_COM_COMTQ_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_COM_COMTQ_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_COM_COMTQ_FTQ_CMD_POP (1L<<30)
+#define BNX2_COM_COMTQ_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_COM_COMTQ_FTQ_CTL 0x001053bc
+#define BNX2_COM_COMTQ_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_COM_COMTQ_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_COM_COMTQ_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_COM_COMTQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_COM_COMTQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_COM_COMQ_FTQ_DATA 0x001053c0
+#define BNX2_COM_COMQ_FTQ_CMD 0x001053f8
+#define BNX2_COM_COMQ_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_COM_COMQ_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_COM_COMQ_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_COM_COMQ_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_COM_COMQ_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_COM_COMQ_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_COM_COMQ_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_COM_COMQ_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_COM_COMQ_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_COM_COMQ_FTQ_CMD_POP (1L<<30)
+#define BNX2_COM_COMQ_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_COM_COMQ_FTQ_CTL 0x001053fc
+#define BNX2_COM_COMQ_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_COM_COMQ_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_COM_COMQ_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_COM_COMQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_COM_COMQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_COM_SCRATCH 0x00120000
+
+
+/*
+ * cp_reg definition
+ * offset: 0x180000
+ */
+#define BNX2_CP_CPU_MODE 0x00185000
+#define BNX2_CP_CPU_MODE_LOCAL_RST (1L<<0)
+#define BNX2_CP_CPU_MODE_STEP_ENA (1L<<1)
+#define BNX2_CP_CPU_MODE_PAGE_0_DATA_ENA (1L<<2)
+#define BNX2_CP_CPU_MODE_PAGE_0_INST_ENA (1L<<3)
+#define BNX2_CP_CPU_MODE_MSG_BIT1 (1L<<6)
+#define BNX2_CP_CPU_MODE_INTERRUPT_ENA (1L<<7)
+#define BNX2_CP_CPU_MODE_SOFT_HALT (1L<<10)
+#define BNX2_CP_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11)
+#define BNX2_CP_CPU_MODE_BAD_INST_HALT_ENA (1L<<12)
+#define BNX2_CP_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13)
+#define BNX2_CP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15)
+
+#define BNX2_CP_CPU_STATE 0x00185004
+#define BNX2_CP_CPU_STATE_BREAKPOINT (1L<<0)
+#define BNX2_CP_CPU_STATE_BAD_INST_HALTED (1L<<2)
+#define BNX2_CP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
+#define BNX2_CP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
+#define BNX2_CP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
+#define BNX2_CP_CPU_STATE_BAD_pc_HALTED (1L<<6)
+#define BNX2_CP_CPU_STATE_ALIGN_HALTED (1L<<7)
+#define BNX2_CP_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
+#define BNX2_CP_CPU_STATE_SOFT_HALTED (1L<<10)
+#define BNX2_CP_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
+#define BNX2_CP_CPU_STATE_INTERRRUPT (1L<<12)
+#define BNX2_CP_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
+#define BNX2_CP_CPU_STATE_INST_FETCH_STALL (1L<<15)
+#define BNX2_CP_CPU_STATE_BLOCKED_READ (1L<<31)
+
+#define BNX2_CP_CPU_EVENT_MASK 0x00185008
+#define BNX2_CP_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0)
+#define BNX2_CP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2)
+#define BNX2_CP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3)
+#define BNX2_CP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4)
+#define BNX2_CP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5)
+#define BNX2_CP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6)
+#define BNX2_CP_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7)
+#define BNX2_CP_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8)
+#define BNX2_CP_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10)
+#define BNX2_CP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11)
+#define BNX2_CP_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12)
+
+#define BNX2_CP_CPU_PROGRAM_COUNTER 0x0018501c
+#define BNX2_CP_CPU_INSTRUCTION 0x00185020
+#define BNX2_CP_CPU_DATA_ACCESS 0x00185024
+#define BNX2_CP_CPU_INTERRUPT_ENABLE 0x00185028
+#define BNX2_CP_CPU_INTERRUPT_VECTOR 0x0018502c
+#define BNX2_CP_CPU_INTERRUPT_SAVED_PC 0x00185030
+#define BNX2_CP_CPU_HW_BREAKPOINT 0x00185034
+#define BNX2_CP_CPU_HW_BREAKPOINT_DISABLE (1L<<0)
+#define BNX2_CP_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2)
+
+#define BNX2_CP_CPU_DEBUG_VECT_PEEK 0x00185038
+#define BNX2_CP_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_CP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_CP_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_CP_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_CP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_CP_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+#define BNX2_CP_CPU_LAST_BRANCH_ADDR 0x00185048
+#define BNX2_CP_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1)
+#define BNX2_CP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1)
+#define BNX2_CP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1)
+#define BNX2_CP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
+
+#define BNX2_CP_CPU_REG_FILE 0x00185200
+#define BNX2_CP_CPQ_FTQ_DATA 0x001853c0
+#define BNX2_CP_CPQ_FTQ_CMD 0x001853f8
+#define BNX2_CP_CPQ_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_CP_CPQ_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_CP_CPQ_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_CP_CPQ_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_CP_CPQ_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_CP_CPQ_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_CP_CPQ_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_CP_CPQ_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_CP_CPQ_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_CP_CPQ_FTQ_CMD_POP (1L<<30)
+#define BNX2_CP_CPQ_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_CP_CPQ_FTQ_CTL 0x001853fc
+#define BNX2_CP_CPQ_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_CP_CPQ_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_CP_CPQ_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_CP_CPQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_CP_CPQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_CP_SCRATCH 0x001a0000
+
+
+/*
+ * mcp_reg definition
+ * offset: 0x140000
+ */
+#define BNX2_MCP_CPU_MODE 0x00145000
+#define BNX2_MCP_CPU_MODE_LOCAL_RST (1L<<0)
+#define BNX2_MCP_CPU_MODE_STEP_ENA (1L<<1)
+#define BNX2_MCP_CPU_MODE_PAGE_0_DATA_ENA (1L<<2)
+#define BNX2_MCP_CPU_MODE_PAGE_0_INST_ENA (1L<<3)
+#define BNX2_MCP_CPU_MODE_MSG_BIT1 (1L<<6)
+#define BNX2_MCP_CPU_MODE_INTERRUPT_ENA (1L<<7)
+#define BNX2_MCP_CPU_MODE_SOFT_HALT (1L<<10)
+#define BNX2_MCP_CPU_MODE_BAD_DATA_HALT_ENA (1L<<11)
+#define BNX2_MCP_CPU_MODE_BAD_INST_HALT_ENA (1L<<12)
+#define BNX2_MCP_CPU_MODE_FIO_ABORT_HALT_ENA (1L<<13)
+#define BNX2_MCP_CPU_MODE_SPAD_UNDERFLOW_HALT_ENA (1L<<15)
+
+#define BNX2_MCP_CPU_STATE 0x00145004
+#define BNX2_MCP_CPU_STATE_BREAKPOINT (1L<<0)
+#define BNX2_MCP_CPU_STATE_BAD_INST_HALTED (1L<<2)
+#define BNX2_MCP_CPU_STATE_PAGE_0_DATA_HALTED (1L<<3)
+#define BNX2_MCP_CPU_STATE_PAGE_0_INST_HALTED (1L<<4)
+#define BNX2_MCP_CPU_STATE_BAD_DATA_ADDR_HALTED (1L<<5)
+#define BNX2_MCP_CPU_STATE_BAD_pc_HALTED (1L<<6)
+#define BNX2_MCP_CPU_STATE_ALIGN_HALTED (1L<<7)
+#define BNX2_MCP_CPU_STATE_FIO_ABORT_HALTED (1L<<8)
+#define BNX2_MCP_CPU_STATE_SOFT_HALTED (1L<<10)
+#define BNX2_MCP_CPU_STATE_SPAD_UNDERFLOW (1L<<11)
+#define BNX2_MCP_CPU_STATE_INTERRRUPT (1L<<12)
+#define BNX2_MCP_CPU_STATE_DATA_ACCESS_STALL (1L<<14)
+#define BNX2_MCP_CPU_STATE_INST_FETCH_STALL (1L<<15)
+#define BNX2_MCP_CPU_STATE_BLOCKED_READ (1L<<31)
+
+#define BNX2_MCP_CPU_EVENT_MASK 0x00145008
+#define BNX2_MCP_CPU_EVENT_MASK_BREAKPOINT_MASK (1L<<0)
+#define BNX2_MCP_CPU_EVENT_MASK_BAD_INST_HALTED_MASK (1L<<2)
+#define BNX2_MCP_CPU_EVENT_MASK_PAGE_0_DATA_HALTED_MASK (1L<<3)
+#define BNX2_MCP_CPU_EVENT_MASK_PAGE_0_INST_HALTED_MASK (1L<<4)
+#define BNX2_MCP_CPU_EVENT_MASK_BAD_DATA_ADDR_HALTED_MASK (1L<<5)
+#define BNX2_MCP_CPU_EVENT_MASK_BAD_PC_HALTED_MASK (1L<<6)
+#define BNX2_MCP_CPU_EVENT_MASK_ALIGN_HALTED_MASK (1L<<7)
+#define BNX2_MCP_CPU_EVENT_MASK_FIO_ABORT_MASK (1L<<8)
+#define BNX2_MCP_CPU_EVENT_MASK_SOFT_HALTED_MASK (1L<<10)
+#define BNX2_MCP_CPU_EVENT_MASK_SPAD_UNDERFLOW_MASK (1L<<11)
+#define BNX2_MCP_CPU_EVENT_MASK_INTERRUPT_MASK (1L<<12)
+
+#define BNX2_MCP_CPU_PROGRAM_COUNTER 0x0014501c
+#define BNX2_MCP_CPU_INSTRUCTION 0x00145020
+#define BNX2_MCP_CPU_DATA_ACCESS 0x00145024
+#define BNX2_MCP_CPU_INTERRUPT_ENABLE 0x00145028
+#define BNX2_MCP_CPU_INTERRUPT_VECTOR 0x0014502c
+#define BNX2_MCP_CPU_INTERRUPT_SAVED_PC 0x00145030
+#define BNX2_MCP_CPU_HW_BREAKPOINT 0x00145034
+#define BNX2_MCP_CPU_HW_BREAKPOINT_DISABLE (1L<<0)
+#define BNX2_MCP_CPU_HW_BREAKPOINT_ADDRESS (0x3fffffffL<<2)
+
+#define BNX2_MCP_CPU_DEBUG_VECT_PEEK 0x00145038
+#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_1_VALUE (0x7ffL<<0)
+#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_1_PEEK_EN (1L<<11)
+#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_1_SEL (0xfL<<12)
+#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_2_VALUE (0x7ffL<<16)
+#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_2_PEEK_EN (1L<<27)
+#define BNX2_MCP_CPU_DEBUG_VECT_PEEK_2_SEL (0xfL<<28)
+
+#define BNX2_MCP_CPU_LAST_BRANCH_ADDR 0x00145048
+#define BNX2_MCP_CPU_LAST_BRANCH_ADDR_TYPE (1L<<1)
+#define BNX2_MCP_CPU_LAST_BRANCH_ADDR_TYPE_JUMP (0L<<1)
+#define BNX2_MCP_CPU_LAST_BRANCH_ADDR_TYPE_BRANCH (1L<<1)
+#define BNX2_MCP_CPU_LAST_BRANCH_ADDR_LBA (0x3fffffffL<<2)
+
+#define BNX2_MCP_CPU_REG_FILE 0x00145200
+#define BNX2_MCP_MCPQ_FTQ_DATA 0x001453c0
+#define BNX2_MCP_MCPQ_FTQ_CMD 0x001453f8
+#define BNX2_MCP_MCPQ_FTQ_CMD_OFFSET (0x3ffL<<0)
+#define BNX2_MCP_MCPQ_FTQ_CMD_WR_TOP (1L<<10)
+#define BNX2_MCP_MCPQ_FTQ_CMD_WR_TOP_0 (0L<<10)
+#define BNX2_MCP_MCPQ_FTQ_CMD_WR_TOP_1 (1L<<10)
+#define BNX2_MCP_MCPQ_FTQ_CMD_SFT_RESET (1L<<25)
+#define BNX2_MCP_MCPQ_FTQ_CMD_RD_DATA (1L<<26)
+#define BNX2_MCP_MCPQ_FTQ_CMD_ADD_INTERVEN (1L<<27)
+#define BNX2_MCP_MCPQ_FTQ_CMD_ADD_DATA (1L<<28)
+#define BNX2_MCP_MCPQ_FTQ_CMD_INTERVENE_CLR (1L<<29)
+#define BNX2_MCP_MCPQ_FTQ_CMD_POP (1L<<30)
+#define BNX2_MCP_MCPQ_FTQ_CMD_BUSY (1L<<31)
+
+#define BNX2_MCP_MCPQ_FTQ_CTL 0x001453fc
+#define BNX2_MCP_MCPQ_FTQ_CTL_INTERVENE (1L<<0)
+#define BNX2_MCP_MCPQ_FTQ_CTL_OVERFLOW (1L<<1)
+#define BNX2_MCP_MCPQ_FTQ_CTL_FORCE_INTERVENE (1L<<2)
+#define BNX2_MCP_MCPQ_FTQ_CTL_MAX_DEPTH (0x3ffL<<12)
+#define BNX2_MCP_MCPQ_FTQ_CTL_CUR_DEPTH (0x3ffL<<22)
+
+#define BNX2_MCP_ROM 0x00150000
+#define BNX2_MCP_SCRATCH 0x00160000
+
+
+#define NUM_MC_HASH_REGISTERS 8
+
+
+/* PHY_ID1: bits 31-16; PHY_ID2: bits 15-0. */
+#define PHY_BCM5706_PHY_ID 0x00206160
+
+#define PHY_ID(id) ((id) & 0xfffffff0)
+#define PHY_REV_ID(id) ((id) & 0xf)
+
+#define MIN_ETHERNET_PACKET_SIZE 60
+#define MAX_ETHERNET_PACKET_SIZE 1514
+#define MAX_ETHERNET_JUMBO_PACKET_SIZE 9014
+
+#define RX_COPY_THRESH 92
+
+#define DMA_READ_CHANS 5
+#define DMA_WRITE_CHANS 3
+
+#define BCM_PAGE_BITS 12
+#define BCM_PAGE_SIZE (1 << BCM_PAGE_BITS)
+
+#define TX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct tx_bd))
+#define MAX_TX_DESC_CNT (TX_DESC_CNT - 1)
+
+#define RX_DESC_CNT (BCM_PAGE_SIZE / sizeof(struct rx_bd))
+#define MAX_RX_DESC_CNT (RX_DESC_CNT - 1)
+
+#define NEXT_TX_BD(x) (((x) & (MAX_TX_DESC_CNT - 1)) == \
+ (MAX_TX_DESC_CNT - 1)) ? \
+ (x) + 2 : (x) + 1
+
+#define TX_RING_IDX(x) ((x) & MAX_TX_DESC_CNT)
+
+#define NEXT_RX_BD(x) (((x) & (MAX_RX_DESC_CNT - 1)) == \
+ (MAX_RX_DESC_CNT - 1)) ? \
+ (x) + 2 : (x) + 1
+
+#define RX_RING_IDX(x) ((x) & MAX_RX_DESC_CNT)
+
+
+/* Context size. */
+#define CTX_SHIFT 7
+#define CTX_SIZE (1 << CTX_SHIFT)
+#define CTX_MASK (CTX_SIZE - 1)
+#define GET_CID_ADDR(_cid) ((_cid) << CTX_SHIFT)
+#define GET_CID(_cid_addr) ((_cid_addr) >> CTX_SHIFT)
+
+#define PHY_CTX_SHIFT 6
+#define PHY_CTX_SIZE (1 << PHY_CTX_SHIFT)
+#define PHY_CTX_MASK (PHY_CTX_SIZE - 1)
+#define GET_PCID_ADDR(_pcid) ((_pcid) << PHY_CTX_SHIFT)
+#define GET_PCID(_pcid_addr) ((_pcid_addr) >> PHY_CTX_SHIFT)
+
+#define MB_KERNEL_CTX_SHIFT 8
+#define MB_KERNEL_CTX_SIZE (1 << MB_KERNEL_CTX_SHIFT)
+#define MB_KERNEL_CTX_MASK (MB_KERNEL_CTX_SIZE - 1)
+#define MB_GET_CID_ADDR(_cid) (0x10000 + ((_cid) << MB_KERNEL_CTX_SHIFT))
+
+#define MAX_CID_CNT 0x4000
+#define MAX_CID_ADDR (GET_CID_ADDR(MAX_CID_CNT))
+#define INVALID_CID_ADDR 0xffffffff
+
+#define TX_CID 16
+#define RX_CID 0
+
+#define MB_TX_CID_ADDR MB_GET_CID_ADDR(TX_CID)
+#define MB_RX_CID_ADDR MB_GET_CID_ADDR(RX_CID)
+
+struct sw_bd {
+ struct sk_buff *skb;
+ DECLARE_PCI_UNMAP_ADDR(mapping)
+};
+
+/* Buffered flash (Atmel: AT45DB011B) specific information */
+#define SEEPROM_PAGE_BITS 2
+#define SEEPROM_PHY_PAGE_SIZE (1 << SEEPROM_PAGE_BITS)
+#define SEEPROM_BYTE_ADDR_MASK (SEEPROM_PHY_PAGE_SIZE-1)
+#define SEEPROM_PAGE_SIZE 4
+#define SEEPROM_TOTAL_SIZE 65536
+
+#define BUFFERED_FLASH_PAGE_BITS 9
+#define BUFFERED_FLASH_PHY_PAGE_SIZE (1 << BUFFERED_FLASH_PAGE_BITS)
+#define BUFFERED_FLASH_BYTE_ADDR_MASK (BUFFERED_FLASH_PHY_PAGE_SIZE-1)
+#define BUFFERED_FLASH_PAGE_SIZE 264
+#define BUFFERED_FLASH_TOTAL_SIZE 131072
+
+#define SAIFUN_FLASH_PAGE_BITS 8
+#define SAIFUN_FLASH_PHY_PAGE_SIZE (1 << SAIFUN_FLASH_PAGE_BITS)
+#define SAIFUN_FLASH_BYTE_ADDR_MASK (SAIFUN_FLASH_PHY_PAGE_SIZE-1)
+#define SAIFUN_FLASH_PAGE_SIZE 256
+#define SAIFUN_FLASH_BASE_TOTAL_SIZE 65536
+
+#define NVRAM_TIMEOUT_COUNT 30000
+
+
+#define FLASH_STRAP_MASK (BNX2_NVM_CFG1_FLASH_MODE | \
+ BNX2_NVM_CFG1_BUFFER_MODE | \
+ BNX2_NVM_CFG1_PROTECT_MODE | \
+ BNX2_NVM_CFG1_FLASH_SIZE)
+
+struct flash_spec {
+ u32 strapping;
+ u32 config1;
+ u32 config2;
+ u32 config3;
+ u32 write1;
+ u32 buffered;
+ u32 page_bits;
+ u32 page_size;
+ u32 addr_mask;
+ u32 total_size;
+ u8 *name;
+};
+
+struct bnx2 {
+ /* Fields used in the tx and intr/napi performance paths are grouped */
+ /* together in the beginning of the structure. */
+ void __iomem *regview;
+
+ struct net_device *dev;
+ struct pci_dev *pdev;
+
+ atomic_t intr_sem;
+
+ struct status_block *status_blk;
+ u32 last_status_idx;
+
+ atomic_t tx_avail_bd;
+ struct tx_bd *tx_desc_ring;
+ struct sw_bd *tx_buf_ring;
+ u32 tx_prod_bseq;
+ u16 tx_prod;
+ u16 tx_cons;
+
+#ifdef BCM_VLAN
+ struct vlan_group *vlgrp;
+#endif
+
+ u32 rx_offset;
+ u32 rx_buf_use_size; /* useable size */
+ u32 rx_buf_size; /* with alignment */
+ struct rx_bd *rx_desc_ring;
+ struct sw_bd *rx_buf_ring;
+ u32 rx_prod_bseq;
+ u16 rx_prod;
+ u16 rx_cons;
+
+ u32 rx_csum;
+
+ /* Only used to synchronize netif_stop_queue/wake_queue when tx */
+ /* ring is full */
+ spinlock_t tx_lock;
+
+ /* End of fileds used in the performance code paths. */
+
+ char *name;
+
+ int timer_interval;
+ struct timer_list timer;
+ struct work_struct reset_task;
+
+ /* Used to synchronize phy accesses. */
+ spinlock_t phy_lock;
+
+ u32 flags;
+#define PCIX_FLAG 1
+#define PCI_32BIT_FLAG 2
+#define ONE_TDMA_FLAG 4 /* no longer used */
+#define NO_WOL_FLAG 8
+#define USING_DAC_FLAG 0x10
+#define USING_MSI_FLAG 0x20
+
+ u32 phy_flags;
+#define PHY_SERDES_FLAG 1
+#define PHY_CRC_FIX_FLAG 2
+#define PHY_PARALLEL_DETECT_FLAG 4
+#define PHY_INT_MODE_MASK_FLAG 0x300
+#define PHY_INT_MODE_AUTO_POLLING_FLAG 0x100
+#define PHY_INT_MODE_LINK_READY_FLAG 0x200
+
+ u32 chip_id;
+ /* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */
+#define CHIP_NUM(bp) (((bp)->chip_id) & 0xffff0000)
+#define CHIP_NUM_5706 0x57060000
+
+#define CHIP_REV(bp) (((bp)->chip_id) & 0x0000f000)
+#define CHIP_REV_Ax 0x00000000
+#define CHIP_REV_Bx 0x00001000
+#define CHIP_REV_Cx 0x00002000
+
+#define CHIP_METAL(bp) (((bp)->chip_id) & 0x00000ff0)
+#define CHIP_BONDING(bp) (((bp)->chip_id) & 0x0000000f)
+
+#define CHIP_ID(bp) (((bp)->chip_id) & 0xfffffff0)
+#define CHIP_ID_5706_A0 0x57060000
+#define CHIP_ID_5706_A1 0x57060010
+
+#define CHIP_BOND_ID(bp) (((bp)->chip_id) & 0xf)
+
+/* A serdes chip will have the first bit of the bond id set. */
+#define CHIP_BOND_ID_SERDES_BIT 0x01
+
+ u32 phy_addr;
+ u32 phy_id;
+
+ u16 bus_speed_mhz;
+ u8 wol;
+
+ u8 fw_timed_out;
+
+ u16 fw_wr_seq;
+ u16 fw_drv_pulse_wr_seq;
+
+ int tx_ring_size;
+ dma_addr_t tx_desc_mapping;
+
+
+ int rx_ring_size;
+ dma_addr_t rx_desc_mapping;
+
+ u16 tx_quick_cons_trip;
+ u16 tx_quick_cons_trip_int;
+ u16 rx_quick_cons_trip;
+ u16 rx_quick_cons_trip_int;
+ u16 comp_prod_trip;
+ u16 comp_prod_trip_int;
+ u16 tx_ticks;
+ u16 tx_ticks_int;
+ u16 com_ticks;
+ u16 com_ticks_int;
+ u16 cmd_ticks;
+ u16 cmd_ticks_int;
+ u16 rx_ticks;
+ u16 rx_ticks_int;
+
+ u32 stats_ticks;
+
+ dma_addr_t status_blk_mapping;
+
+ struct statistics_block *stats_blk;
+ dma_addr_t stats_blk_mapping;
+
+ u32 rx_mode;
+
+ u16 req_line_speed;
+ u8 req_duplex;
+
+ u8 link_up;
+
+ u16 line_speed;
+ u8 duplex;
+ u8 flow_ctrl; /* actual flow ctrl settings */
+ /* may be different from */
+ /* req_flow_ctrl if autoneg */
+#define FLOW_CTRL_TX 1
+#define FLOW_CTRL_RX 2
+
+ u32 advertising;
+
+ u8 req_flow_ctrl; /* flow ctrl advertisement */
+ /* settings or forced */
+ /* settings */
+ u8 autoneg;
+#define AUTONEG_SPEED 1
+#define AUTONEG_FLOW_CTRL 2
+
+ u8 loopback;
+#define MAC_LOOPBACK 1
+#define PHY_LOOPBACK 2
+
+ u8 serdes_an_pending;
+#define SERDES_AN_TIMEOUT (2 * HZ)
+
+ u8 mac_addr[8];
+
+ u32 fw_ver;
+
+ int pm_cap;
+ int pcix_cap;
+
+ struct net_device_stats net_stats;
+
+ struct flash_spec *flash_info;
+};
+
+static u32 bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset);
+static void bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val);
+
+#define REG_RD(bp, offset) \
+ readl(bp->regview + offset)
+
+#define REG_WR(bp, offset, val) \
+ writel(val, bp->regview + offset)
+
+#define REG_WR16(bp, offset, val) \
+ writew(val, bp->regview + offset)
+
+#define REG_RD_IND(bp, offset) \
+ bnx2_reg_rd_ind(bp, offset)
+
+#define REG_WR_IND(bp, offset, val) \
+ bnx2_reg_wr_ind(bp, offset, val)
+
+/* Indirect context access. Unlike the MBQ_WR, these macros will not
+ * trigger a chip event. */
+static void bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val);
+
+#define CTX_WR(bp, cid_addr, offset, val) \
+ bnx2_ctx_wr(bp, cid_addr, offset, val)
+
+struct cpu_reg {
+ u32 mode;
+ u32 mode_value_halt;
+ u32 mode_value_sstep;
+
+ u32 state;
+ u32 state_value_clear;
+
+ u32 gpr0;
+ u32 evmask;
+ u32 pc;
+ u32 inst;
+ u32 bp;
+
+ u32 spad_base;
+
+ u32 mips_view_base;
+};
+
+struct fw_info {
+ u32 ver_major;
+ u32 ver_minor;
+ u32 ver_fix;
+
+ u32 start_addr;
+
+ /* Text section. */
+ u32 text_addr;
+ u32 text_len;
+ u32 text_index;
+ u32 *text;
+
+ /* Data section. */
+ u32 data_addr;
+ u32 data_len;
+ u32 data_index;
+ u32 *data;
+
+ /* SBSS section. */
+ u32 sbss_addr;
+ u32 sbss_len;
+ u32 sbss_index;
+ u32 *sbss;
+
+ /* BSS section. */
+ u32 bss_addr;
+ u32 bss_len;
+ u32 bss_index;
+ u32 *bss;
+
+ /* Read-only section. */
+ u32 rodata_addr;
+ u32 rodata_len;
+ u32 rodata_index;
+ u32 *rodata;
+};
+
+#define RV2P_PROC1 0
+#define RV2P_PROC2 1
+
+
+/* This value (in milliseconds) determines the frequency of the driver
+ * issuing the PULSE message code. The firmware monitors this periodic
+ * pulse to determine when to switch to an OS-absent mode. */
+#define DRV_PULSE_PERIOD_MS 250
+
+/* This value (in milliseconds) determines how long the driver should
+ * wait for an acknowledgement from the firmware before timing out. Once
+ * the firmware has timed out, the driver will assume there is no firmware
+ * running and there won't be any firmware-driver synchronization during a
+ * driver reset. */
+#define FW_ACK_TIME_OUT_MS 50
+
+
+#define BNX2_DRV_RESET_SIGNATURE 0x00000000
+#define BNX2_DRV_RESET_SIGNATURE_MAGIC 0x4841564b /* HAVK */
+//#define DRV_RESET_SIGNATURE_MAGIC 0x47495352 /* RSIG */
+
+#define BNX2_DRV_MB 0x00000004
+#define BNX2_DRV_MSG_CODE 0xff000000
+#define BNX2_DRV_MSG_CODE_RESET 0x01000000
+#define BNX2_DRV_MSG_CODE_UNLOAD 0x02000000
+#define BNX2_DRV_MSG_CODE_SHUTDOWN 0x03000000
+#define BNX2_DRV_MSG_CODE_SUSPEND_WOL 0x04000000
+#define BNX2_DRV_MSG_CODE_FW_TIMEOUT 0x05000000
+#define BNX2_DRV_MSG_CODE_PULSE 0x06000000
+#define BNX2_DRV_MSG_CODE_DIAG 0x07000000
+#define BNX2_DRV_MSG_CODE_SUSPEND_NO_WOL 0x09000000
+
+#define BNX2_DRV_MSG_DATA 0x00ff0000
+#define BNX2_DRV_MSG_DATA_WAIT0 0x00010000
+#define BNX2_DRV_MSG_DATA_WAIT1 0x00020000
+#define BNX2_DRV_MSG_DATA_WAIT2 0x00030000
+#define BNX2_DRV_MSG_DATA_WAIT3 0x00040000
+
+#define BNX2_DRV_MSG_SEQ 0x0000ffff
+
+#define BNX2_FW_MB 0x00000008
+#define BNX2_FW_MSG_ACK 0x0000ffff
+#define BNX2_FW_MSG_STATUS_MASK 0x00ff0000
+#define BNX2_FW_MSG_STATUS_OK 0x00000000
+#define BNX2_FW_MSG_STATUS_FAILURE 0x00ff0000
+
+#define BNX2_LINK_STATUS 0x0000000c
+
+#define BNX2_DRV_PULSE_MB 0x00000010
+#define BNX2_DRV_PULSE_SEQ_MASK 0x0000ffff
+
+/* Indicate to the firmware not to go into the
+ * OS absent when it is not getting driver pulse.
+ * This is used for debugging. */
+#define BNX2_DRV_MSG_DATA_PULSE_CODE_ALWAYS_ALIVE 0x00010000
+
+#define BNX2_DEV_INFO_SIGNATURE 0x00000020
+#define BNX2_DEV_INFO_SIGNATURE_MAGIC 0x44564900
+#define BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK 0xffffff00
+#define BNX2_DEV_INFO_FEATURE_CFG_VALID 0x01
+#define BNX2_DEV_INFO_SECONDARY_PORT 0x80
+#define BNX2_DEV_INFO_DRV_ALWAYS_ALIVE 0x40
+
+#define BNX2_SHARED_HW_CFG_PART_NUM 0x00000024
+
+#define BNX2_SHARED_HW_CFG_POWER_DISSIPATED 0x00000034
+#define BNX2_SHARED_HW_CFG_POWER_STATE_D3_MASK 0xff000000
+#define BNX2_SHARED_HW_CFG_POWER_STATE_D2_MASK 0xff0000
+#define BNX2_SHARED_HW_CFG_POWER_STATE_D1_MASK 0xff00
+#define BNX2_SHARED_HW_CFG_POWER_STATE_D0_MASK 0xff
+
+#define BNX2_SHARED_HW_CFG POWER_CONSUMED 0x00000038
+#define BNX2_SHARED_HW_CFG_CONFIG 0x0000003c
+#define BNX2_SHARED_HW_CFG_DESIGN_NIC 0
+#define BNX2_SHARED_HW_CFG_DESIGN_LOM 0x1
+#define BNX2_SHARED_HW_CFG_PHY_COPPER 0
+#define BNX2_SHARED_HW_CFG_PHY_FIBER 0x2
+#define BNX2_SHARED_HW_CFG_LED_MODE_SHIFT_BITS 8
+#define BNX2_SHARED_HW_CFG_LED_MODE_MASK 0x300
+#define BNX2_SHARED_HW_CFG_LED_MODE_MAC 0
+#define BNX2_SHARED_HW_CFG_LED_MODE_GPHY1 0x100
+#define BNX2_SHARED_HW_CFG_LED_MODE_GPHY2 0x200
+
+#define BNX2_DEV_INFO_BC_REV 0x0000004c
+
+#define BNX2_PORT_HW_CFG_MAC_UPPER 0x00000050
+#define BNX2_PORT_HW_CFG_UPPERMAC_MASK 0xffff
+
+#define BNX2_PORT_HW_CFG_MAC_LOWER 0x00000054
+#define BNX2_PORT_HW_CFG_CONFIG 0x00000058
+
+#define BNX2_PORT_HW_CFG_IMD_MAC_A_UPPER 0x00000068
+#define BNX2_PORT_HW_CFG_IMD_MAC_A_LOWER 0x0000006c
+#define BNX2_PORT_HW_CFG_IMD_MAC_B_UPPER 0x00000070
+#define BNX2_PORT_HW_CFG_IMD_MAC_B_LOWER 0x00000074
+#define BNX2_PORT_HW_CFG_ISCSI_MAC_UPPER 0x00000078
+#define BNX2_PORT_HW_CFG_ISCSI_MAC_LOWER 0x0000007c
+
+#define BNX2_DEV_INFO_PER_PORT_HW_CONFIG2 0x000000b4
+
+#define BNX2_DEV_INFO_FORMAT_REV 0x000000c4
+#define BNX2_DEV_INFO_FORMAT_REV_MASK 0xff000000
+#define BNX2_DEV_INFO_FORMAT_REV_ID ('A' << 24)
+
+#define BNX2_SHARED_FEATURE 0x000000c8
+#define BNX2_SHARED_FEATURE_MASK 0xffffffff
+
+#define BNX2_PORT_FEATURE 0x000000d8
+#define BNX2_PORT2_FEATURE 0x00000014c
+#define BNX2_PORT_FEATURE_WOL_ENABLED 0x01000000
+#define BNX2_PORT_FEATURE_MBA_ENABLED 0x02000000
+#define BNX2_PORT_FEATURE_ASF_ENABLED 0x04000000
+#define BNX2_PORT_FEATURE_IMD_ENABLED 0x08000000
+#define BNX2_PORT_FEATURE_BAR1_SIZE_MASK 0xf
+#define BNX2_PORT_FEATURE_BAR1_SIZE_DISABLED 0x0
+#define BNX2_PORT_FEATURE_BAR1_SIZE_64K 0x1
+#define BNX2_PORT_FEATURE_BAR1_SIZE_128K 0x2
+#define BNX2_PORT_FEATURE_BAR1_SIZE_256K 0x3
+#define BNX2_PORT_FEATURE_BAR1_SIZE_512K 0x4
+#define BNX2_PORT_FEATURE_BAR1_SIZE_1M 0x5
+#define BNX2_PORT_FEATURE_BAR1_SIZE_2M 0x6
+#define BNX2_PORT_FEATURE_BAR1_SIZE_4M 0x7
+#define BNX2_PORT_FEATURE_BAR1_SIZE_8M 0x8
+#define BNX2_PORT_FEATURE_BAR1_SIZE_16M 0x9
+#define BNX2_PORT_FEATURE_BAR1_SIZE_32M 0xa
+#define BNX2_PORT_FEATURE_BAR1_SIZE_64M 0xb
+#define BNX2_PORT_FEATURE_BAR1_SIZE_128M 0xc
+#define BNX2_PORT_FEATURE_BAR1_SIZE_256M 0xd
+#define BNX2_PORT_FEATURE_BAR1_SIZE_512M 0xe
+#define BNX2_PORT_FEATURE_BAR1_SIZE_1G 0xf
+
+#define BNX2_PORT_FEATURE_WOL 0xdc
+#define BNX2_PORT2_FEATURE_WOL 0x150
+#define BNX2_PORT_FEATURE_WOL_DEFAULT_SHIFT_BITS 4
+#define BNX2_PORT_FEATURE_WOL_DEFAULT_MASK 0x30
+#define BNX2_PORT_FEATURE_WOL_DEFAULT_DISABLE 0
+#define BNX2_PORT_FEATURE_WOL_DEFAULT_MAGIC 0x10
+#define BNX2_PORT_FEATURE_WOL_DEFAULT_ACPI 0x20
+#define BNX2_PORT_FEATURE_WOL_DEFAULT_MAGIC_AND_ACPI 0x30
+#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_MASK 0xf
+#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_AUTONEG 0
+#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_10HALF 1
+#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_10FULL 2
+#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_100HALF 3
+#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_100FULL 4
+#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_1000HALF 5
+#define BNX2_PORT_FEATURE_WOL_LINK_SPEED_1000FULL 6
+#define BNX2_PORT_FEATURE_WOL_AUTONEG_ADVERTISE_1000 0x40
+#define BNX2_PORT_FEATURE_WOL_RESERVED_PAUSE_CAP 0x400
+#define BNX2_PORT_FEATURE_WOL_RESERVED_ASYM_PAUSE_CAP 0x800
+
+#define BNX2_PORT_FEATURE_MBA 0xe0
+#define BNX2_PORT2_FEATURE_MBA 0x154
+#define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_SHIFT_BITS 0
+#define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_MASK 0x3
+#define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_PXE 0
+#define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_RPL 1
+#define BNX2_PORT_FEATURE_MBA_BOOT_AGENT_TYPE_BOOTP 2
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_SHIFT_BITS 2
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_MASK 0x3c
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_AUTONEG 0
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_10HALF 0x4
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_10FULL 0x8
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_100HALF 0xc
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_100FULL 0x10
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_1000HALF 0x14
+#define BNX2_PORT_FEATURE_MBA_LINK_SPEED_1000FULL 0x18
+#define BNX2_PORT_FEATURE_MBA_SETUP_PROMPT_ENABLE 0x40
+#define BNX2_PORT_FEATURE_MBA_HOTKEY_CTRL_S 0
+#define BNX2_PORT_FEATURE_MBA_HOTKEY_CTRL_B 0x80
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_SHIFT_BITS 8
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_MASK 0xff00
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_DISABLED 0
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_1K 0x100
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_2K 0x200
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_4K 0x300
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_8K 0x400
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_16K 0x500
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_32K 0x600
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_64K 0x700
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_128K 0x800
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_256K 0x900
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_512K 0xa00
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_1M 0xb00
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_2M 0xc00
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_4M 0xd00
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_8M 0xe00
+#define BNX2_PORT_FEATURE_MBA_EXP_ROM_SIZE_16M 0xf00
+#define BNX2_PORT_FEATURE_MBA_MSG_TIMEOUT_SHIFT_BITS 16
+#define BNX2_PORT_FEATURE_MBA_MSG_TIMEOUT_MASK 0xf0000
+#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_SHIFT_BITS 20
+#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_MASK 0x300000
+#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_AUTO 0
+#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_BBS 0x100000
+#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT18H 0x200000
+#define BNX2_PORT_FEATURE_MBA_BIOS_BOOTSTRAP_INT19H 0x300000
+
+#define BNX2_PORT_FEATURE_IMD 0xe4
+#define BNX2_PORT2_FEATURE_IMD 0x158
+#define BNX2_PORT_FEATURE_IMD_LINK_OVERRIDE_DEFAULT 0
+#define BNX2_PORT_FEATURE_IMD_LINK_OVERRIDE_ENABLE 1
+
+#define BNX2_PORT_FEATURE_VLAN 0xe8
+#define BNX2_PORT2_FEATURE_VLAN 0x15c
+#define BNX2_PORT_FEATURE_MBA_VLAN_TAG_MASK 0xffff
+#define BNX2_PORT_FEATURE_MBA_VLAN_ENABLE 0x10000
+
+#define BNX2_BC_STATE_RESET_TYPE 0x000001c0
+#define BNX2_BC_STATE_RESET_TYPE_SIG 0x00005254
+#define BNX2_BC_STATE_RESET_TYPE_SIG_MASK 0x0000ffff
+#define BNX2_BC_STATE_RESET_TYPE_NONE (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ 0x00010000)
+#define BNX2_BC_STATE_RESET_TYPE_PCI (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ 0x00020000)
+#define BNX2_BC_STATE_RESET_TYPE_VAUX (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ 0x00030000)
+#define BNX2_BC_STATE_RESET_TYPE_DRV_MASK DRV_MSG_CODE
+#define BNX2_BC_STATE_RESET_TYPE_DRV_RESET (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ DRV_MSG_CODE_RESET)
+#define BNX2_BC_STATE_RESET_TYPE_DRV_UNLOAD (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ DRV_MSG_CODE_UNLOAD)
+#define BNX2_BC_STATE_RESET_TYPE_DRV_SHUTDOWN (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ DRV_MSG_CODE_SHUTDOWN)
+#define BNX2_BC_STATE_RESET_TYPE_DRV_WOL (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ DRV_MSG_CODE_WOL)
+#define BNX2_BC_STATE_RESET_TYPE_DRV_DIAG (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ DRV_MSG_CODE_DIAG)
+#define BNX2_BC_STATE_RESET_TYPE_VALUE(msg) (BNX2_BC_STATE_RESET_TYPE_SIG | \
+ (msg))
+
+#define BNX2_BC_STATE 0x000001c4
+#define BNX2_BC_STATE_ERR_MASK 0x0000ff00
+#define BNX2_BC_STATE_SIGN 0x42530000
+#define BNX2_BC_STATE_SIGN_MASK 0xffff0000
+#define BNX2_BC_STATE_BC1_START (BNX2_BC_STATE_SIGN | 0x1)
+#define BNX2_BC_STATE_GET_NVM_CFG1 (BNX2_BC_STATE_SIGN | 0x2)
+#define BNX2_BC_STATE_PROG_BAR (BNX2_BC_STATE_SIGN | 0x3)
+#define BNX2_BC_STATE_INIT_VID (BNX2_BC_STATE_SIGN | 0x4)
+#define BNX2_BC_STATE_GET_NVM_CFG2 (BNX2_BC_STATE_SIGN | 0x5)
+#define BNX2_BC_STATE_APPLY_WKARND (BNX2_BC_STATE_SIGN | 0x6)
+#define BNX2_BC_STATE_LOAD_BC2 (BNX2_BC_STATE_SIGN | 0x7)
+#define BNX2_BC_STATE_GOING_BC2 (BNX2_BC_STATE_SIGN | 0x8)
+#define BNX2_BC_STATE_GOING_DIAG (BNX2_BC_STATE_SIGN | 0x9)
+#define BNX2_BC_STATE_RT_FINAL_INIT (BNX2_BC_STATE_SIGN | 0x81)
+#define BNX2_BC_STATE_RT_WKARND (BNX2_BC_STATE_SIGN | 0x82)
+#define BNX2_BC_STATE_RT_DRV_PULSE (BNX2_BC_STATE_SIGN | 0x83)
+#define BNX2_BC_STATE_RT_FIOEVTS (BNX2_BC_STATE_SIGN | 0x84)
+#define BNX2_BC_STATE_RT_DRV_CMD (BNX2_BC_STATE_SIGN | 0x85)
+#define BNX2_BC_STATE_RT_LOW_POWER (BNX2_BC_STATE_SIGN | 0x86)
+#define BNX2_BC_STATE_RT_SET_WOL (BNX2_BC_STATE_SIGN | 0x87)
+#define BNX2_BC_STATE_RT_OTHER_FW (BNX2_BC_STATE_SIGN | 0x88)
+#define BNX2_BC_STATE_RT_GOING_D3 (BNX2_BC_STATE_SIGN | 0x89)
+#define BNX2_BC_STATE_ERR_BAD_VERSION (BNX2_BC_STATE_SIGN | 0x0100)
+#define BNX2_BC_STATE_ERR_BAD_BC2_CRC (BNX2_BC_STATE_SIGN | 0x0200)
+#define BNX2_BC_STATE_ERR_BC1_LOOP (BNX2_BC_STATE_SIGN | 0x0300)
+#define BNX2_BC_STATE_ERR_UNKNOWN_CMD (BNX2_BC_STATE_SIGN | 0x0400)
+#define BNX2_BC_STATE_ERR_DRV_DEAD (BNX2_BC_STATE_SIGN | 0x0500)
+#define BNX2_BC_STATE_ERR_NO_RXP (BNX2_BC_STATE_SIGN | 0x0600)
+#define BNX2_BC_STATE_ERR_TOO_MANY_RBUF (BNX2_BC_STATE_SIGN | 0x0700)
+
+#define BNX2_BC_STATE_DEBUG_CMD 0x1dc
+#define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE 0x42440000
+#define BNX2_BC_STATE_BC_DBG_CMD_SIGNATURE_MASK 0xffff0000
+#define BNX2_BC_STATE_BC_DBG_CMD_LOOP_CNT_MASK 0xffff
+#define BNX2_BC_STATE_BC_DBG_CMD_LOOP_INFINITE 0xffff
+
+#define HOST_VIEW_SHMEM_BASE 0x167c00
+
+#endif
diff --git a/drivers/net/bnx2_fw.h b/drivers/net/bnx2_fw.h
new file mode 100644
index 00000000000..35f3a2ae5ef
--- /dev/null
+++ b/drivers/net/bnx2_fw.h
@@ -0,0 +1,2468 @@
+/* bnx2_fw.h: Broadcom NX2 network driver.
+ *
+ * Copyright (c) 2004, 2005 Broadcom Corporation
+ *
+ * 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, except as noted below.
+ *
+ * This file contains firmware data derived from proprietary unpublished
+ * source code, Copyright (c) 2004, 2005 Broadcom Corporation.
+ *
+ * Permission is hereby granted for the distribution of this firmware data
+ * in hexadecimal or equivalent format, provided this copyright notice is
+ * accompanying it.
+ */
+
+
+static int bnx2_COM_b06FwReleaseMajor = 0x0;
+static int bnx2_COM_b06FwReleaseMinor = 0x0;
+static int bnx2_COM_b06FwReleaseFix = 0x0;
+static u32 bnx2_COM_b06FwStartAddr = 0x080004a0;
+static u32 bnx2_COM_b06FwTextAddr = 0x08000000;
+static int bnx2_COM_b06FwTextLen = 0x4594;
+static u32 bnx2_COM_b06FwDataAddr = 0x080045e0;
+static int bnx2_COM_b06FwDataLen = 0x0;
+static u32 bnx2_COM_b06FwRodataAddr = 0x08004598;
+static int bnx2_COM_b06FwRodataLen = 0x18;
+static u32 bnx2_COM_b06FwBssAddr = 0x08004600;
+static int bnx2_COM_b06FwBssLen = 0x88;
+static u32 bnx2_COM_b06FwSbssAddr = 0x080045e0;
+static int bnx2_COM_b06FwSbssLen = 0x1c;
+static u32 bnx2_COM_b06FwText[(0x4594/4) + 1] = {
+ 0x0a000128, 0x00000000, 0x00000000, 0x0000000d, 0x636f6d20, 0x302e362e,
+ 0x39000000, 0x00060902, 0x00000000, 0x00000003, 0x00000014, 0x00000032,
+ 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000010, 0x000003e8, 0x0000ea60, 0x00000001, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x0000ffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000002, 0x00000020, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x10000003, 0x00000000, 0x0000000d,
+ 0x0000000d, 0x3c020800, 0x244245e0, 0x3c030800, 0x24634688, 0xac400000,
+ 0x0043202b, 0x1480fffd, 0x24420004, 0x3c1d0800, 0x37bd7ffc, 0x03a0f021,
+ 0x3c100800, 0x261004a0, 0x3c1c0800, 0x279c45e0, 0x0e0001f2, 0x00000000,
+ 0x0000000d, 0x27bdffe8, 0x3c1a8000, 0x3c020008, 0x0342d825, 0x3c036010,
+ 0xafbf0010, 0x8c655000, 0x3c020800, 0x24470ac8, 0x3c040800, 0x24864600,
+ 0x2402ff7f, 0x00a22824, 0x34a5380c, 0xac655000, 0x00002821, 0x24020037,
+ 0x24030c80, 0xaf420008, 0xaf430024, 0xacc70000, 0x24a50001, 0x2ca20016,
+ 0x1440fffc, 0x24c60004, 0x24844600, 0x3c020800, 0x24420ad4, 0x3c030800,
+ 0x246309d4, 0xac820004, 0x3c020800, 0x24420618, 0x3c050800, 0x24a50ca0,
+ 0xac82000c, 0x3c020800, 0x24423100, 0xac830008, 0x3c030800, 0x246325c8,
+ 0xac820014, 0x3c020800, 0x24422b0c, 0xac830018, 0xac83001c, 0x3c030800,
+ 0x24630adc, 0xac820024, 0x3c020800, 0x24423040, 0xac83002c, 0x3c030800,
+ 0x24633060, 0xac820030, 0x3c020800, 0x24422f6c, 0xac830034, 0x3c030800,
+ 0x24632c60, 0xac82003c, 0x3c020800, 0x24420b6c, 0xac850010, 0xac850020,
+ 0xac830040, 0x0e000bd6, 0xac820050, 0x8fbf0010, 0x03e00008, 0x27bd0018,
+ 0x27bdffe0, 0xafb00010, 0x27500100, 0xafbf0018, 0xafb10014, 0x9203000b,
+ 0x24020003, 0x1462005b, 0x96110008, 0x32220001, 0x10400009, 0x27430080,
+ 0x8e020000, 0x96040014, 0x000211c2, 0x00021040, 0x00621821, 0xa4640000,
+ 0x0a0001cb, 0x3c020800, 0x3c020800, 0x8c430020, 0x1060002a, 0x3c030800,
+ 0x0e001006, 0x00000000, 0x97420108, 0x8f850018, 0x9743010c, 0x3042003e,
+ 0x00021400, 0x00621825, 0xaca30000, 0x8f840018, 0x8f420100, 0xac820004,
+ 0x97430116, 0x9742010e, 0x8f840018, 0x00031c00, 0x00431025, 0xac820008,
+ 0x97430110, 0x97440112, 0x8f850018, 0x00031c00, 0x00832025, 0xaca4000c,
+ 0x97420114, 0x8f840018, 0x3042ffff, 0xac820010, 0x8f830018, 0xac600014,
+ 0x8f820018, 0x3c030800, 0xac400018, 0x9462466e, 0x8f840018, 0x3c032000,
+ 0x00431025, 0xac82001c, 0x0e001044, 0x24040001, 0x3c030800, 0x8c620040,
+ 0x24420001, 0xac620040, 0x3c020800, 0x8c430044, 0x32240004, 0x24630001,
+ 0x10800017, 0xac430044, 0x8f4202b8, 0x04430007, 0x8e020020, 0x3c040800,
+ 0x8c830060, 0x24020001, 0x24630001, 0x0a0001ed, 0xac830060, 0x3c060800,
+ 0x8cc4005c, 0xaf420280, 0x96030016, 0x00001021, 0xa7430284, 0x8e050004,
+ 0x24840001, 0x3c031000, 0xaf450288, 0xaf4302b8, 0x0a0001ed, 0xacc4005c,
+ 0x32220002, 0x0a0001ed, 0x0002102b, 0x3c026000, 0xac400808, 0x0000000d,
+ 0x00001021, 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020,
+ 0x27bdffc8, 0xafbf0034, 0xafbe0030, 0xafb7002c, 0xafb60028, 0xafb50024,
+ 0xafb40020, 0xafb3001c, 0xafb20018, 0xafb10014, 0x0e00013f, 0xafb00010,
+ 0x24110020, 0x24150030, 0x2794000c, 0x27930008, 0x3c124000, 0x3c1e0800,
+ 0x3c170800, 0x3c160800, 0x8f820004, 0x3c040800, 0x8c830020, 0x10430004,
+ 0x00000000, 0xaf830004, 0x0e00110b, 0x00000000, 0x8f500000, 0x32020007,
+ 0x1040fff5, 0x32020001, 0x1040002b, 0x32020002, 0x8f420100, 0xaf420020,
+ 0x8f430104, 0xaf4300a8, 0x9342010b, 0x93630000, 0x306300ff, 0x10710005,
+ 0x304400ff, 0x10750006, 0x2c820016, 0x0a000227, 0x00000000, 0xaf940000,
+ 0x0a000228, 0x2c820016, 0xaf930000, 0x0a000228, 0x00000000, 0xaf800000,
+ 0x14400005, 0x00041880, 0x0e0002b2, 0x00000000, 0x0a000234, 0x00000000,
+ 0x3c020800, 0x24424600, 0x00621821, 0x8c620000, 0x0040f809, 0x00000000,
+ 0x10400005, 0x8fc20034, 0x8f420104, 0x3c016020, 0xac220014, 0x8fc20034,
+ 0xaf520138, 0x24420001, 0xafc20034, 0x32020002, 0x10400019, 0x32020004,
+ 0x8f420140, 0xaf420020, 0x93630000, 0x306300ff, 0x10710005, 0x00000000,
+ 0x10750006, 0x00000000, 0x0a000250, 0x00000000, 0xaf940000, 0x0a000251,
+ 0x00000000, 0xaf930000, 0x0a000251, 0x00000000, 0xaf800000, 0x0e0008b9,
+ 0x00000000, 0x8ee20038, 0xaf520178, 0x24420001, 0xaee20038, 0x32020004,
+ 0x1040ffad, 0x00000000, 0x8f420180, 0xaf420020, 0x93630000, 0x306300ff,
+ 0x10710005, 0x00000000, 0x10750006, 0x00000000, 0x0a00026a, 0x00000000,
+ 0xaf940000, 0x0a00026b, 0x00000000, 0xaf930000, 0x0a00026b, 0x00000000,
+ 0xaf800000, 0x93620000, 0x14510004, 0x8ec2003c, 0x0e000835, 0x00000000,
+ 0x8ec2003c, 0xaf5201b8, 0x24420001, 0x0a000206, 0xaec2003c, 0x27bdffe8,
+ 0xafbf0010, 0x97420108, 0x24033000, 0x30447000, 0x10830012, 0x28823001,
+ 0x10400007, 0x24024000, 0x1080000b, 0x24022000, 0x1082001a, 0x24020001,
+ 0x0a000299, 0x00000000, 0x1082000c, 0x24025000, 0x1082000e, 0x00000000,
+ 0x0a000299, 0x00000000, 0x0000000d, 0x0a00029b, 0x00001021, 0x0e000300,
+ 0x00000000, 0x0a00029b, 0x00001021, 0x0e00048f, 0x00000000, 0x0a00029b,
+ 0x00001021, 0x0e000fdf, 0x00000000, 0x0a00029b, 0x00001021, 0x0000000d,
+ 0x00001021, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x93620000, 0x24030020,
+ 0x304400ff, 0x10830005, 0x24020030, 0x10820007, 0x00000000, 0x0a0002af,
+ 0x00000000, 0x2782000c, 0xaf820000, 0x03e00008, 0x00000000, 0x27820008,
+ 0xaf820000, 0x03e00008, 0x00000000, 0xaf800000, 0x03e00008, 0x00000000,
+ 0x0000000d, 0x03e00008, 0x00001021, 0x03e00008, 0x00001021, 0x27440100,
+ 0x94830008, 0x30620004, 0x10400017, 0x30620002, 0x8f4202b8, 0x04430007,
+ 0x8c820020, 0x3c040800, 0x8c830060, 0x24020001, 0x24630001, 0x03e00008,
+ 0xac830060, 0xaf420280, 0x94830016, 0x3c060800, 0xa7430284, 0x8c850004,
+ 0x8cc4005c, 0x00001021, 0x3c031000, 0x24840001, 0xaf450288, 0xaf4302b8,
+ 0x03e00008, 0xacc4005c, 0x14400003, 0x3c040800, 0x03e00008, 0x00001021,
+ 0x8c830084, 0x24020001, 0x24630001, 0x03e00008, 0xac830084, 0x27450100,
+ 0x3c040800, 0x8c820088, 0x94a3000c, 0x24420001, 0x007a1821, 0xac820088,
+ 0x8ca40018, 0x90664000, 0xaf440038, 0x8ca2001c, 0x2403fff8, 0x00063600,
+ 0x00431024, 0x34420004, 0x3c030005, 0xaf42003c, 0xaf430030, 0x00000000,
+ 0x00000000, 0x00000000, 0xaf460404, 0x00000000, 0x00000000, 0x00000000,
+ 0x3c020006, 0x34420001, 0xaf420030, 0x00000000, 0x00000000, 0x00000000,
+ 0x8f420000, 0x30420010, 0x1040fffd, 0x00001021, 0x03e00008, 0x00000000,
+ 0x3c020800, 0x8c430020, 0x27bdffe8, 0xafb00010, 0x27500100, 0x1060001e,
+ 0xafbf0014, 0x0e001006, 0x00000000, 0x8f830018, 0x8e020018, 0xac620000,
+ 0x8f840018, 0x9602000c, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018,
+ 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, 0xac400014, 0x8f840018,
+ 0x3c026000, 0x8c434448, 0xac830018, 0x96020008, 0x3c030800, 0x9464466e,
+ 0x8f850018, 0x00021400, 0x00441025, 0x24040001, 0x0e001044, 0xaca2001c,
+ 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x27bdffc8, 0xafb3001c,
+ 0x00009821, 0xafb7002c, 0x0000b821, 0xafbe0030, 0x0000f021, 0xafb50024,
+ 0x27550100, 0xafbf0034, 0xafb60028, 0xafb40020, 0xafb20018, 0xafb10014,
+ 0xafb00010, 0x96a20008, 0x8f540100, 0x8eb20018, 0x30420001, 0x10400037,
+ 0x02a0b021, 0x8f630054, 0x2642ffff, 0x00431023, 0x18400006, 0x00000000,
+ 0x0000000d, 0x00000000, 0x24000128, 0x0a000372, 0x00002021, 0x8f62004c,
+ 0x02421023, 0x18400028, 0x00002021, 0x93650120, 0x93640121, 0x3c030800,
+ 0x8c62008c, 0x308400ff, 0x24420001, 0x30a500ff, 0x00803821, 0x1485000b,
+ 0xac62008c, 0x3c040800, 0x8c830090, 0x24630001, 0xac830090, 0x93620122,
+ 0x30420001, 0x00021023, 0x30420005, 0x0a000372, 0x34440004, 0x27660100,
+ 0x00041080, 0x00c21021, 0x8c430000, 0x02431823, 0x04600004, 0x24820001,
+ 0x30440007, 0x1485fff9, 0x00041080, 0x10870007, 0x3c030800, 0xa3640121,
+ 0x8c620094, 0x24040005, 0x24420001, 0x0a000372, 0xac620094, 0x24040004,
+ 0x00809821, 0x9362003f, 0x304400ff, 0x38830016, 0x2c630001, 0x38820010,
+ 0x2c420001, 0x00621825, 0x1460000c, 0x24020001, 0x38830008, 0x2c630001,
+ 0x38820014, 0x2c420001, 0x00621825, 0x14600005, 0x24020001, 0x24020012,
+ 0x14820002, 0x00001021, 0x24020001, 0x50400007, 0x8eb10020, 0x8ea20020,
+ 0x8f630040, 0x00408821, 0x00431023, 0x5c400001, 0x8f710040, 0x9343010b,
+ 0x24020004, 0x54620005, 0x36730080, 0x96a20008, 0x36730002, 0x24170001,
+ 0x305e0020, 0x2402fffb, 0x02628024, 0x1200002a, 0x3c030800, 0x8c620030,
+ 0x02021024, 0x10400026, 0x3c020800, 0x8c430020, 0x10600024, 0x32620004,
+ 0x0e001006, 0x00000000, 0x8f830018, 0x8f420100, 0xac620000, 0x8f840018,
+ 0x02201821, 0x32620002, 0xac900004, 0x8f840018, 0x50400001, 0x8ec30014,
+ 0xac830008, 0x8f830018, 0x8ec20020, 0xac62000c, 0x8f840018, 0x8f620040,
+ 0xac820010, 0x8f830018, 0x8ec20018, 0xac620014, 0x8f840018, 0x3c026000,
+ 0x8c434448, 0x3c020800, 0xac830018, 0x9443466e, 0x8f840018, 0x3c024010,
+ 0x00621825, 0xac83001c, 0x0e001044, 0x24040001, 0x32620004, 0x10400076,
+ 0x00003821, 0x3c029000, 0x34420001, 0x3c038000, 0x02821025, 0xa360007c,
+ 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620023,
+ 0x30420080, 0x10400011, 0x00000000, 0x8f65005c, 0x8f63004c, 0x9764003c,
+ 0x8f620064, 0x00a32823, 0x00852821, 0x00a2102b, 0x54400006, 0x3c023fff,
+ 0x93620023, 0x3042007f, 0xa3620023, 0xaf720064, 0x3c023fff, 0x0a0003f1,
+ 0x3442ffff, 0x8f62005c, 0x02421023, 0x04400011, 0x00000000, 0x8f65005c,
+ 0x8f630064, 0x9764003c, 0x3c023fff, 0x3442ffff, 0xaf720064, 0x00a32823,
+ 0x00852821, 0x0045102b, 0x10400004, 0x02451021, 0x3c053fff, 0x34a5ffff,
+ 0x02451021, 0xaf62005c, 0x24070001, 0xaf72004c, 0x8f620054, 0x16420005,
+ 0x00000000, 0x93620023, 0x30420040, 0x10400017, 0x24020001, 0x9762006a,
+ 0x00022880, 0x50a00001, 0x24050001, 0x97630068, 0x93640081, 0x3c020800,
+ 0x8c46004c, 0x00652821, 0x00852804, 0x00c5102b, 0x54400001, 0x00a03021,
+ 0x3c020800, 0x8c440050, 0x00c4182b, 0x54600001, 0x00c02021, 0x8f420074,
+ 0x2403fffe, 0x00832824, 0x00a21021, 0xaf62000c, 0x3c028000, 0x34420001,
+ 0x02821025, 0xa3600081, 0xaf420020, 0x9363007e, 0x9362007a, 0x10620004,
+ 0x00000000, 0x0e000f2a, 0x00000000, 0x00403821, 0x10e00017, 0x3c029000,
+ 0x34420001, 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024,
+ 0x1440fffd, 0x3c028000, 0x9363007d, 0x34420001, 0x3c048000, 0x02821025,
+ 0xa363007d, 0xaf420020, 0x8f4201f8, 0x00441024, 0x1440fffd, 0x24020002,
+ 0x3c031000, 0xaf5401c0, 0xa34201c4, 0xaf4301f8, 0x8ea30014, 0x8f620040,
+ 0x14430003, 0x00431023, 0x0a000443, 0x00001021, 0x28420001, 0x10400034,
+ 0x00000000, 0x8f620040, 0xaf630040, 0x9362003e, 0x30420001, 0x1440000b,
+ 0x3c029000, 0x93620022, 0x24420001, 0xa3620022, 0x93630022, 0x3c020800,
+ 0x8c440098, 0x0064182b, 0x1460001e, 0x3c020800, 0x3c029000, 0x34420001,
+ 0x02821025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd,
+ 0x00000000, 0x3c038000, 0x9362007d, 0x34630001, 0x3c048000, 0x02831825,
+ 0x34420001, 0xa362007d, 0xaf430020, 0x8f4201f8, 0x00441024, 0x1440fffd,
+ 0x24020002, 0x3c031000, 0xaf5401c0, 0xa34201c4, 0x24020001, 0xaf4301f8,
+ 0xa7620012, 0x0a000476, 0xa3600022, 0x9743007a, 0x9444002a, 0x00641821,
+ 0x3063fffe, 0xa7630012, 0x0e000b68, 0x00000000, 0x12e00003, 0x00000000,
+ 0x0e000f27, 0x00000000, 0x53c00004, 0x96a20008, 0x0e000c10, 0x00000000,
+ 0x96a20008, 0x8fbf0034, 0x8fbe0030, 0x8fb7002c, 0x8fb60028, 0x8fb50024,
+ 0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x00021042,
+ 0x30420001, 0x03e00008, 0x27bd0038, 0x27bdffe8, 0xafbf0010, 0x97420108,
+ 0x2403000b, 0x304400ff, 0x1083004e, 0x2882000c, 0x10400011, 0x24020006,
+ 0x1082003e, 0x28820007, 0x10400007, 0x28820008, 0x1080002b, 0x24020001,
+ 0x1082002e, 0x3c026000, 0x0a000504, 0x00000000, 0x14400061, 0x2882000a,
+ 0x1440002b, 0x00000000, 0x0a0004ec, 0x00000000, 0x2402001c, 0x1082004e,
+ 0x2882001d, 0x1040000e, 0x24020019, 0x10820041, 0x2882001a, 0x10400005,
+ 0x2402000e, 0x10820036, 0x00000000, 0x0a000504, 0x00000000, 0x2402001b,
+ 0x1082003c, 0x00000000, 0x0a000504, 0x00000000, 0x240200c1, 0x10820040,
+ 0x288200c2, 0x10400005, 0x24020080, 0x1082001f, 0x00000000, 0x0a000504,
+ 0x00000000, 0x240200c2, 0x1082003b, 0x00000000, 0x0a000504, 0x00000000,
+ 0x3c026000, 0x0e000c7d, 0xac400808, 0x0a000506, 0x8fbf0010, 0x8c444448,
+ 0x3c030800, 0xac640064, 0x0e000c7d, 0x00000000, 0x3c026000, 0x8c444448,
+ 0x3c030800, 0x0a000505, 0xac640068, 0x8f440100, 0x0e000508, 0x00000000,
+ 0x3c026000, 0x8c444448, 0x3c030800, 0x0a000505, 0xac64006c, 0x0e000cab,
+ 0x00000000, 0x0a000506, 0x8fbf0010, 0x8f440100, 0x0e000cd5, 0x00000000,
+ 0x0a000506, 0x8fbf0010, 0x0e000d1c, 0x00000000, 0x0a000506, 0x8fbf0010,
+ 0x0000000d, 0x0a000506, 0x8fbf0010, 0x0e0005d7, 0x00000000, 0x0a000506,
+ 0x8fbf0010, 0x8f440100, 0x0e000d7e, 0x00000000, 0x0a000506, 0x8fbf0010,
+ 0x0e000e95, 0x00000000, 0x0a000506, 0x8fbf0010, 0x0e000626, 0x00000000,
+ 0x0a000506, 0x8fbf0010, 0x0e000b68, 0x00000000, 0x0a000506, 0x8fbf0010,
+ 0x0000000d, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffe8, 0x3c029000,
+ 0x34420001, 0xafb00010, 0x00808021, 0x02021025, 0x3c038000, 0xafbf0014,
+ 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620005,
+ 0x34420001, 0xa3620005, 0x8f63004c, 0x8f620054, 0x10620019, 0x3c028000,
+ 0x9762006a, 0x00022880, 0x50a00001, 0x24050001, 0x97630068, 0x93640081,
+ 0x3c020800, 0x8c46004c, 0x00652821, 0x00852804, 0x00c5102b, 0x54400001,
+ 0x00a03021, 0x3c020800, 0x8c440050, 0x00c4182b, 0x54600001, 0x00c02021,
+ 0x8f420074, 0x2403fffe, 0x00832824, 0x00a21021, 0xaf62000c, 0x3c028000,
+ 0x34420001, 0x02021025, 0x0e000c7d, 0xaf420020, 0x3c029000, 0x34420001,
+ 0x3c038000, 0x02021025, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd,
+ 0x3c028000, 0x9363007d, 0x34420001, 0x3c048000, 0x02021025, 0xa363007d,
+ 0xaf420020, 0x8f4201f8, 0x00441024, 0x1440fffd, 0x8fbf0014, 0xaf5001c0,
+ 0x8fb00010, 0x24020002, 0x3c031000, 0xa34201c4, 0xaf4301f8, 0x03e00008,
+ 0x27bd0018, 0x27bdffd8, 0xafbf0020, 0xafb3001c, 0xafb20018, 0xafb10014,
+ 0xafb00010, 0x93630005, 0x00809021, 0x24020030, 0x30630030, 0x14620072,
+ 0x00a09821, 0x3c020800, 0x8c430020, 0x1060006c, 0x00000000, 0x0e001006,
+ 0x00000000, 0x8f820018, 0xac520000, 0x9363003e, 0x9362003f, 0x8f840018,
+ 0x00031a00, 0x00431025, 0xac820004, 0x93630081, 0x93620082, 0x8f850018,
+ 0x00031e00, 0x00021400, 0x00621825, 0xaca30008, 0x8f840018, 0x8f620040,
+ 0xac82000c, 0x8f830018, 0x8f620048, 0xac620010, 0x8f840018, 0x8f62004c,
+ 0x3c110800, 0xac820014, 0x8f830018, 0x8f620050, 0x26304660, 0x00002021,
+ 0xac620018, 0x9602000e, 0x8f850018, 0x3c03c00b, 0x00431025, 0x0e001044,
+ 0xaca2001c, 0x8f830018, 0x8f620054, 0xac620000, 0x8f840018, 0x8f620058,
+ 0xac820004, 0x8f830018, 0x8f62005c, 0xac620008, 0x8f840018, 0x8f620060,
+ 0xac82000c, 0x8f850018, 0x8f620064, 0xaca20010, 0x97630068, 0x9762006a,
+ 0x8f840018, 0x00031c00, 0x00431025, 0xac820014, 0x8f830018, 0x00002021,
+ 0xac600018, 0x9602000e, 0x8f850018, 0x3c03c00c, 0x00431025, 0x0e001044,
+ 0xaca2001c, 0x8f840018, 0x8f630018, 0xac830000, 0x936200c4, 0x30420002,
+ 0x10400006, 0x00000000, 0x976200c8, 0x8f830018, 0x3042ffff, 0x0a0005b5,
+ 0xac620004, 0x8f820018, 0xac400004, 0x8f830018, 0x8f62006c, 0xac620008,
+ 0x8f840018, 0x8f6200dc, 0xac82000c, 0x8f830018, 0xac600010, 0x93620005,
+ 0x8f830018, 0x00021600, 0x00531025, 0xac620014, 0x8f850018, 0x3c026000,
+ 0x8c434448, 0x24040001, 0x26224660, 0xaca30018, 0x9443000e, 0x8f850018,
+ 0x3c02400d, 0x00621825, 0x0e001044, 0xaca3001c, 0x0e000d48, 0x02402021,
+ 0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008,
+ 0x27bd0028, 0x27bdffe0, 0xafb00010, 0x27500100, 0xafbf0018, 0xafb10014,
+ 0x9603000c, 0x240200c1, 0x5462001d, 0x8e040000, 0x3c029000, 0x8f440100,
+ 0x34420001, 0x3c038000, 0x00821025, 0xaf420020, 0x8f420020, 0x00431024,
+ 0x1440fffd, 0x00000000, 0x3c038000, 0x9362007d, 0x34630001, 0x3c058000,
+ 0x00831825, 0x34420004, 0xa362007d, 0xaf430020, 0x8f4201f8, 0x00451024,
+ 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4401c0, 0xa34201c4, 0xaf4301f8,
+ 0x0a000622, 0x8fbf0018, 0x8f65004c, 0x24060001, 0x0e000db5, 0x2407049f,
+ 0x3c020800, 0x8c430020, 0x9611000c, 0x1060001d, 0x8e100000, 0x0e001006,
+ 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x00111400, 0xac820004,
+ 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010,
+ 0x8f840018, 0x240204a2, 0xac820014, 0x8f850018, 0x3c026000, 0x8c434448,
+ 0x24040001, 0x3c020800, 0xaca30018, 0x9443466e, 0x8f850018, 0x3c024019,
+ 0x00621825, 0x0e001044, 0xaca3001c, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
+ 0x03e00008, 0x27bd0020, 0x27bdffb0, 0xafb1002c, 0x27510100, 0xafbf004c,
+ 0xafbe0048, 0xafb70044, 0xafb60040, 0xafb5003c, 0xafb40038, 0xafb30034,
+ 0xafb20030, 0xafb00028, 0x8e350000, 0x9634000c, 0x3c026000, 0x8c434448,
+ 0x0000f021, 0xaf630170, 0x8f620040, 0x8e230014, 0x0000b821, 0x00431023,
+ 0x044001ec, 0x0000b021, 0x32820010, 0x1040002e, 0x3c026000, 0x9363003f,
+ 0x9222000e, 0x10430006, 0x2402000c, 0x9223000f, 0x10620003, 0x24020014,
+ 0x14620025, 0x3c026000, 0x32820004, 0x10400007, 0x241e0001, 0x8f620050,
+ 0x24420001, 0xaf620050, 0x8f630054, 0x24630001, 0xaf630054, 0x32830102,
+ 0x24020002, 0x5462000d, 0x9222000f, 0x8f620040, 0x24420001, 0xaf620040,
+ 0x8f630048, 0x8f620040, 0x24630001, 0x54620005, 0x9222000f, 0x8f620048,
+ 0x24420001, 0xaf620048, 0x9222000f, 0xa362003f, 0x9223000f, 0x24020012,
+ 0x14620007, 0x3c026000, 0x3c030800, 0x8c620074, 0x24420001, 0x0e000f6e,
+ 0xac620074, 0x3c026000, 0x8c434448, 0x32820040, 0xaf630174, 0x32830020,
+ 0xafa30010, 0x32830080, 0xafa30014, 0x32830001, 0xafa3001c, 0x32830008,
+ 0xafa30020, 0x32830100, 0x104000bb, 0xafa30018, 0x8e260010, 0x8f630054,
+ 0x24c2ffff, 0x00431023, 0x18400006, 0x00000000, 0x0000000d, 0x00000000,
+ 0x24000128, 0x0a0006b2, 0x00009021, 0x8f62004c, 0x00c21023, 0x18400028,
+ 0x00009021, 0x93650120, 0x93640121, 0x3c030800, 0x8c62008c, 0x308400ff,
+ 0x24420001, 0x30a500ff, 0x00804021, 0x1485000b, 0xac62008c, 0x3c040800,
+ 0x8c830090, 0x24630001, 0xac830090, 0x93620122, 0x30420001, 0x00021023,
+ 0x30420005, 0x0a0006b2, 0x34520004, 0x27670100, 0x00041080, 0x00e21021,
+ 0x8c430000, 0x00c31823, 0x04600004, 0x24820001, 0x30440007, 0x1485fff9,
+ 0x00041080, 0x10880007, 0x3c030800, 0xa3640121, 0x8c620094, 0x24120005,
+ 0x24420001, 0x0a0006b2, 0xac620094, 0x24120004, 0x32420001, 0x10400020,
+ 0x3c020800, 0x8c430020, 0x8e300000, 0x1060001c, 0x8e330010, 0x0e001006,
+ 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x24020001, 0xac820004,
+ 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010,
+ 0x8f820018, 0xac530014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001,
+ 0x3c020800, 0xaca30018, 0x9443466e, 0x8f850018, 0x3c024010, 0x00621825,
+ 0x0e001044, 0xaca3001c, 0x32420004, 0x10400060, 0x00003821, 0x3c029000,
+ 0x8e260010, 0x34420001, 0x3c038000, 0x02a21025, 0xa360007c, 0xaf420020,
+ 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620023, 0x30420080,
+ 0x10400011, 0x00000000, 0x8f65005c, 0x8f63004c, 0x9764003c, 0x8f620064,
+ 0x00a32823, 0x00852821, 0x00a2102b, 0x54400006, 0x3c023fff, 0x93620023,
+ 0x3042007f, 0xa3620023, 0xaf660064, 0x3c023fff, 0x0a000702, 0x3442ffff,
+ 0x8f62005c, 0x00c21023, 0x04400011, 0x00000000, 0x8f65005c, 0x8f630064,
+ 0x9764003c, 0x3c023fff, 0x3442ffff, 0xaf660064, 0x00a32823, 0x00852821,
+ 0x0045102b, 0x10400004, 0x00c51021, 0x3c053fff, 0x34a5ffff, 0x00c51021,
+ 0xaf62005c, 0x24070001, 0xaf66004c, 0x8f620054, 0x14c20005, 0x00000000,
+ 0x93620023, 0x30420040, 0x10400017, 0x24020001, 0x9762006a, 0x00022880,
+ 0x50a00001, 0x24050001, 0x97630068, 0x93640081, 0x3c020800, 0x8c46004c,
+ 0x00652821, 0x00852804, 0x00c5102b, 0x54400001, 0x00a03021, 0x3c020800,
+ 0x8c440050, 0x00c4182b, 0x54600001, 0x00c02021, 0x8f420074, 0x2403fffe,
+ 0x00832824, 0x00a21021, 0xaf62000c, 0x3c028000, 0x34420001, 0x02a21025,
+ 0xa3600081, 0xaf420020, 0x9363007e, 0x9362007a, 0x10620005, 0x00e0b021,
+ 0x0e000f2a, 0x00000000, 0x00403821, 0x00e0b021, 0x8fa20010, 0x10400008,
+ 0x00000000, 0x8e220018, 0xaf620018, 0x8e23001c, 0xaf63001c, 0x8e220020,
+ 0x24160001, 0xaf620058, 0x13c00036, 0x32820004, 0x10400035, 0x8fa30014,
+ 0x93620023, 0x30420040, 0x10400031, 0x3c020800, 0x8c430020, 0x1060001c,
+ 0x8e300000, 0x0e001006, 0x00000000, 0x8f820018, 0xac500000, 0x8f830018,
+ 0xac600004, 0x8f820018, 0xac400008, 0x8f830018, 0xac60000c, 0x8f820018,
+ 0xac400010, 0x8f830018, 0x24020587, 0xac620014, 0x8f850018, 0x3c026000,
+ 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x9443466e, 0x8f850018,
+ 0x3c024019, 0x00621825, 0x0e001044, 0xaca3001c, 0x3c029000, 0x34420001,
+ 0x02a21025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd,
+ 0x24020001, 0xaf62000c, 0x93630023, 0x3c028000, 0x34420001, 0x02a21025,
+ 0x306300bf, 0xa3630023, 0xaf420020, 0x8fa30014, 0x10600012, 0x8fa3001c,
+ 0x9362007c, 0x24420001, 0xa362007c, 0x9363007e, 0x9362007a, 0x1462000b,
+ 0x8fa3001c, 0x9362007c, 0x3c030800, 0x8c640024, 0x0044102b, 0x14400005,
+ 0x8fa3001c, 0x0e000f2a, 0x00000000, 0x02c2b025, 0x8fa3001c, 0x3062ffff,
+ 0x10400003, 0x32820200, 0x0a000793, 0x24170004, 0x10400003, 0x00000000,
+ 0x24170040, 0x24160001, 0x13c0005d, 0x32820002, 0x1040005c, 0x8fa20020,
+ 0x9222000a, 0x30420020, 0x10400033, 0x3c100800, 0x93620023, 0x30420040,
+ 0x1040002f, 0x8e020020, 0x1040001e, 0x3c029000, 0x0e001006, 0x00000000,
+ 0x8f820018, 0xac550000, 0x8f840018, 0x3c02008d, 0xac820004, 0x8f830018,
+ 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f840018,
+ 0x240205bf, 0xac820014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001,
+ 0x3c020800, 0xaca30018, 0x9443466e, 0x8f850018, 0x3c024019, 0x00621825,
+ 0x0e001044, 0xaca3001c, 0x3c029000, 0x34420001, 0x02a21025, 0xaf420020,
+ 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93630023,
+ 0x3c028000, 0x34420001, 0x02a21025, 0x306300bf, 0xa3630023, 0xaf420020,
+ 0x8e020020, 0x10400023, 0x8fa20020, 0x0e001006, 0x00000000, 0x8f840018,
+ 0x8e230000, 0xac830000, 0x9222000a, 0x8f830018, 0x00021600, 0xac620004,
+ 0x8f840018, 0x8f620040, 0xac820008, 0x8f850018, 0x8f63004c, 0xaca3000c,
+ 0x9362003f, 0x8f840018, 0x304200ff, 0xac820010, 0x8f830018, 0x3c026000,
+ 0xac600014, 0x8f850018, 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018,
+ 0x9443466e, 0x8f850018, 0x3c02401a, 0x00621825, 0x0e001044, 0xaca3001c,
+ 0x8fa20020, 0x1040000e, 0x8fa20018, 0x9222000a, 0xa3620082, 0x56e00005,
+ 0x36f70008, 0x8fa30018, 0x10600004, 0x00000000, 0x36f70008, 0x0a000801,
+ 0x24160001, 0x0e000de1, 0x02a02021, 0x8fa20018, 0x10400003, 0x00000000,
+ 0x36f70010, 0x24160001, 0x12c00019, 0x3c029000, 0x34420001, 0x02a21025,
+ 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000,
+ 0x3c038000, 0x9362007d, 0x34630001, 0x3c048000, 0x02a31825, 0x02e21025,
+ 0xa362007d, 0xaf430020, 0x8f4201f8, 0x00441024, 0x1440fffd, 0x24020002,
+ 0x3c031000, 0xaf5501c0, 0xa34201c4, 0xaf4301f8, 0x9363003f, 0x24020012,
+ 0x14620004, 0x3c026000, 0x0e000f6e, 0x00000000, 0x3c026000, 0x8c434448,
+ 0xaf630178, 0x8fbf004c, 0x8fbe0048, 0x8fb70044, 0x8fb60040, 0x8fb5003c,
+ 0x8fb40038, 0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028, 0x03e00008,
+ 0x27bd0050, 0x27bdffe8, 0xafbf0014, 0xafb00010, 0x8f500180, 0x97420184,
+ 0x30420200, 0x14400015, 0x00000000, 0x8f430188, 0x3c02ff00, 0x00621824,
+ 0x3c020200, 0x10620031, 0x0043102b, 0x14400007, 0x3c020300, 0x1060000b,
+ 0x3c020100, 0x1062000d, 0x00000000, 0x0a0008b4, 0x00000000, 0x10620027,
+ 0x3c020400, 0x1062003e, 0x02002021, 0x0a0008b4, 0x00000000, 0x0e000e1e,
+ 0x02002021, 0x0a0008b6, 0x8fbf0014, 0x93620005, 0x30420020, 0x1440005e,
+ 0x8fbf0014, 0x3c029000, 0x34420001, 0x02021025, 0xaf420020, 0x3c038000,
+ 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620005, 0x3c038000,
+ 0x34630001, 0x02031825, 0x34420020, 0xa3620005, 0xaf430020, 0x93620005,
+ 0x30420020, 0x14400003, 0x02002021, 0x0000000d, 0x02002021, 0x0e000553,
+ 0x24055854, 0x0a0008b6, 0x8fbf0014, 0x93620005, 0x30420001, 0x1040003f,
+ 0x3c029000, 0x34420001, 0x02021025, 0xaf420020, 0x3c038000, 0x8f420020,
+ 0x00431024, 0x1440fffd, 0x00000000, 0x93620005, 0x3c048000, 0x3c030800,
+ 0x304200fe, 0xa3620005, 0x8c620020, 0x34840001, 0x02042025, 0xaf440020,
+ 0x1040002d, 0x8fbf0014, 0x0a000894, 0x00000000, 0x00002821, 0x00003021,
+ 0x0e000f78, 0x240706a4, 0x3c020800, 0x8c430020, 0x10600023, 0x8fbf0014,
+ 0x0e001006, 0x00000000, 0x8f820018, 0xac500000, 0x93630082, 0x9362003f,
+ 0x8f840018, 0x00031a00, 0x00431025, 0xac820004, 0x8f830018, 0xac600008,
+ 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018, 0xac400014,
+ 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018,
+ 0x9443466e, 0x8f850018, 0x3c02400a, 0x00621825, 0x0e001044, 0xaca3001c,
+ 0x0a0008b6, 0x8fbf0014, 0x0000000d, 0x8fbf0014, 0x8fb00010, 0x03e00008,
+ 0x27bd0018, 0x27bdffe8, 0xafbf0010, 0x93420148, 0x2444ffff, 0x2c830005,
+ 0x10600047, 0x3c020800, 0x24424598, 0x00041880, 0x00621821, 0x8c640000,
+ 0x00800008, 0x00000000, 0x8f430144, 0x8f62000c, 0x14620006, 0x24020001,
+ 0xaf62000c, 0x0e000909, 0x00000000, 0x0a000907, 0x8fbf0010, 0x8f62000c,
+ 0x0a000900, 0x00000000, 0x97630010, 0x8f420144, 0x14430006, 0x24020001,
+ 0xa7620010, 0x0e000eeb, 0x00000000, 0x0a000907, 0x8fbf0010, 0x97620010,
+ 0x0a000900, 0x00000000, 0x97630012, 0x8f420144, 0x14430006, 0x24020001,
+ 0xa7620012, 0x0e000f06, 0x00000000, 0x0a000907, 0x8fbf0010, 0x97620012,
+ 0x0a000900, 0x00000000, 0x97630014, 0x8f420144, 0x14430006, 0x24020001,
+ 0xa7620014, 0x0e000f21, 0x00000000, 0x0a000907, 0x8fbf0010, 0x97620014,
+ 0x0a000900, 0x00000000, 0x97630016, 0x8f420144, 0x14430006, 0x24020001,
+ 0xa7620016, 0x0e000f24, 0x00000000, 0x0a000907, 0x8fbf0010, 0x97620016,
+ 0x14400006, 0x8fbf0010, 0x3c030800, 0x8c620070, 0x24420001, 0xac620070,
+ 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffe8, 0xafbf0010, 0x93620081,
+ 0x3c030800, 0x8c640048, 0x0044102b, 0x14400028, 0x3c029000, 0x8f460140,
+ 0x34420001, 0x3c038000, 0x00c21025, 0xaf420020, 0x8f420020, 0x00431024,
+ 0x1440fffd, 0x3c048000, 0x34840001, 0x3c059000, 0x34a50001, 0x3c078000,
+ 0x24020012, 0x24030080, 0x00c42025, 0x00c52825, 0xa362003f, 0xa3630082,
+ 0xaf440020, 0xaf450020, 0x8f420020, 0x00471024, 0x1440fffd, 0x3c038000,
+ 0x9362007d, 0x34630001, 0x3c048000, 0x00c31825, 0x34420020, 0xa362007d,
+ 0xaf430020, 0x8f4201f8, 0x00441024, 0x1440fffd, 0x24020002, 0x3c031000,
+ 0x0a00096d, 0xaf4601c0, 0x93620081, 0x24420001, 0x0e000f2a, 0xa3620081,
+ 0x9763006a, 0x00032880, 0x14a00002, 0x00403821, 0x24050001, 0x97630068,
+ 0x93640081, 0x3c020800, 0x8c46004c, 0x00652821, 0x00852804, 0x00c5102b,
+ 0x54400001, 0x00a03021, 0x3c020800, 0x8c440050, 0x00c4182b, 0x54600001,
+ 0x00c02021, 0x8f420074, 0x2403fffe, 0x00832824, 0x00a21021, 0xaf62000c,
+ 0x10e0001a, 0x3c029000, 0x8f440140, 0x34420001, 0x3c038000, 0x00821025,
+ 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x3c038000,
+ 0x9362007d, 0x34630001, 0x3c058000, 0x00831825, 0x34420004, 0xa362007d,
+ 0xaf430020, 0x8f4201f8, 0x00451024, 0x1440fffd, 0x24020002, 0x3c031000,
+ 0xaf4401c0, 0xa34201c4, 0xaf4301f8, 0x8fbf0010, 0x03e00008, 0x27bd0018,
+ 0x27bdffd8, 0xafb3001c, 0x27530100, 0xafbf0024, 0xafb40020, 0xafb20018,
+ 0xafb10014, 0xafb00010, 0x96620008, 0x3c140800, 0x8f520100, 0x30420001,
+ 0x104000cf, 0x00000000, 0x8e700018, 0x8f630054, 0x2602ffff, 0x00431023,
+ 0x18400006, 0x00000000, 0x0000000d, 0x00000000, 0x24000128, 0x0a0009b6,
+ 0x00008821, 0x8f62004c, 0x02021023, 0x18400028, 0x00008821, 0x93650120,
+ 0x93640121, 0x3c030800, 0x8c62008c, 0x308400ff, 0x24420001, 0x30a500ff,
+ 0x00803821, 0x1485000b, 0xac62008c, 0x3c040800, 0x8c830090, 0x24630001,
+ 0xac830090, 0x93620122, 0x30420001, 0x00021023, 0x30420005, 0x0a0009b6,
+ 0x34510004, 0x27660100, 0x00041080, 0x00c21021, 0x8c430000, 0x02031823,
+ 0x04600004, 0x24820001, 0x30440007, 0x1485fff9, 0x00041080, 0x10870007,
+ 0x3c030800, 0xa3640121, 0x8c620094, 0x24110005, 0x24420001, 0x0a0009b6,
+ 0xac620094, 0x24110004, 0x32220001, 0x1040001e, 0x8e820020, 0x1040001d,
+ 0x32220004, 0x0e001006, 0x00000000, 0x8f820018, 0xac520000, 0x8f840018,
+ 0x24020001, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c,
+ 0x8f830018, 0xac600010, 0x8f820018, 0xac500014, 0x8f850018, 0x3c026000,
+ 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x9443466e, 0x8f850018,
+ 0x3c024010, 0x00621825, 0x0e001044, 0xaca3001c, 0x32220004, 0x10400076,
+ 0x00003821, 0x3c029000, 0x34420001, 0x3c038000, 0x02421025, 0xa360007c,
+ 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620023,
+ 0x30420080, 0x10400011, 0x00000000, 0x8f65005c, 0x8f63004c, 0x9764003c,
+ 0x8f620064, 0x00a32823, 0x00852821, 0x00a2102b, 0x54400006, 0x3c023fff,
+ 0x93620023, 0x3042007f, 0xa3620023, 0xaf700064, 0x3c023fff, 0x0a000a03,
+ 0x3442ffff, 0x8f62005c, 0x02021023, 0x04400011, 0x00000000, 0x8f65005c,
+ 0x8f630064, 0x9764003c, 0x3c023fff, 0x3442ffff, 0xaf700064, 0x00a32823,
+ 0x00852821, 0x0045102b, 0x10400004, 0x02051021, 0x3c053fff, 0x34a5ffff,
+ 0x02051021, 0xaf62005c, 0x24070001, 0xaf70004c, 0x8f620054, 0x16020005,
+ 0x00000000, 0x93620023, 0x30420040, 0x10400017, 0x24020001, 0x9762006a,
+ 0x00022880, 0x50a00001, 0x24050001, 0x97630068, 0x93640081, 0x3c020800,
+ 0x8c46004c, 0x00652821, 0x00852804, 0x00c5102b, 0x54400001, 0x00a03021,
+ 0x3c020800, 0x8c440050, 0x00c4182b, 0x54600001, 0x00c02021, 0x8f420074,
+ 0x2403fffe, 0x00832824, 0x00a21021, 0xaf62000c, 0x3c028000, 0x34420001,
+ 0x02421025, 0xa3600081, 0xaf420020, 0x9363007e, 0x9362007a, 0x10620004,
+ 0x00000000, 0x0e000f2a, 0x00000000, 0x00403821, 0x10e00017, 0x3c029000,
+ 0x34420001, 0x02421025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024,
+ 0x1440fffd, 0x3c028000, 0x9363007d, 0x34420001, 0x3c048000, 0x02421025,
+ 0xa363007d, 0xaf420020, 0x8f4201f8, 0x00441024, 0x1440fffd, 0x24020002,
+ 0x3c031000, 0xaf5201c0, 0xa34201c4, 0xaf4301f8, 0x9342010b, 0x8e830020,
+ 0x27500100, 0x38420006, 0x10600029, 0x2c510001, 0x0e001006, 0x00000000,
+ 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018, 0x96020008, 0xac820004,
+ 0x8f830018, 0x8e020014, 0xac620008, 0x8f850018, 0x3c026000, 0x8c434448,
+ 0xaca3000c, 0x8f840018, 0x96020012, 0xac820010, 0x8f850018, 0x8e030020,
+ 0xaca30014, 0x9602000c, 0x9603000e, 0x8f840018, 0x00021400, 0x00431025,
+ 0xac820018, 0x12200005, 0x3c020800, 0x9443466e, 0x8f840018, 0x0a000a78,
+ 0x3c024013, 0x9443466e, 0x8f840018, 0x3c024014, 0x00621825, 0xac83001c,
+ 0x0e001044, 0x24040001, 0x8e630014, 0x8f620040, 0x14430003, 0x00431023,
+ 0x0a000a83, 0x00001021, 0x28420001, 0x10400034, 0x00000000, 0x8f620040,
+ 0xaf630040, 0x9362003e, 0x30420001, 0x1440000b, 0x3c029000, 0x93620022,
+ 0x24420001, 0xa3620022, 0x93630022, 0x3c020800, 0x8c440098, 0x0064182b,
+ 0x1460001e, 0x3c020800, 0x3c029000, 0x34420001, 0x02421025, 0xaf420020,
+ 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x3c038000,
+ 0x9362007d, 0x34630001, 0x3c048000, 0x02431825, 0x34420001, 0xa362007d,
+ 0xaf430020, 0x8f4201f8, 0x00441024, 0x1440fffd, 0x24020002, 0x3c031000,
+ 0xaf5201c0, 0xa34201c4, 0x24020001, 0xaf4301f8, 0xa7620012, 0x0a000ab6,
+ 0xa3600022, 0x9743007a, 0x9444002a, 0x00641821, 0x3063fffe, 0xa7630012,
+ 0x0e000b68, 0x00000000, 0x97420108, 0x8fbf0024, 0x8fb40020, 0x8fb3001c,
+ 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x00021042, 0x30420001, 0x03e00008,
+ 0x27bd0028, 0x27bdffe0, 0xafb20018, 0x3c120800, 0x8e420020, 0xafb00010,
+ 0x27500100, 0xafbf001c, 0x10400046, 0xafb10014, 0x0e001006, 0x00000000,
+ 0x8f840018, 0x8e020000, 0xac820000, 0x936300b1, 0x936200c5, 0x8f850018,
+ 0x00031e00, 0x00021400, 0x34420100, 0x00621825, 0xaca30004, 0x8f840018,
+ 0x8e02001c, 0xac820008, 0x8f830018, 0x8f620048, 0xac62000c, 0x8f840018,
+ 0x96020012, 0xac820010, 0x8f830018, 0x8f620040, 0x24040001, 0xac620014,
+ 0x8f850018, 0x3c026000, 0x8c434448, 0x3c020800, 0x24514660, 0xaca30018,
+ 0x9623000e, 0x8f850018, 0x3c024016, 0x00621825, 0x0e001044, 0xaca3001c,
+ 0x96030008, 0x30630010, 0x1060001c, 0x8e420020, 0x1040001a, 0x8e100000,
+ 0x0e001006, 0x00000000, 0x8f820018, 0xac500000, 0x8f830018, 0xac600004,
+ 0x8f820018, 0xac400008, 0x8f830018, 0xac60000c, 0x8f820018, 0xac400010,
+ 0x8f830018, 0xac600014, 0x8f850018, 0x3c036000, 0x8c634448, 0x24040001,
+ 0xaca30018, 0x9622000e, 0x8f850018, 0x3c034015, 0x00431025, 0x0e001044,
+ 0xaca2001c, 0x00001021, 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010,
+ 0x03e00008, 0x27bd0020, 0x27bdffe0, 0xafb20018, 0x3c120800, 0x8e420020,
+ 0xafb00010, 0x27500100, 0xafbf001c, 0x10400041, 0xafb10014, 0x0e001006,
+ 0x00000000, 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018, 0x24020100,
+ 0xac820004, 0x8f830018, 0x8e02001c, 0xac620008, 0x8f840018, 0x8e020018,
+ 0xac82000c, 0x8f830018, 0x96020012, 0xac620010, 0x8f840018, 0x96020008,
+ 0xac820014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800,
+ 0x24514660, 0xaca30018, 0x9623000e, 0x8f850018, 0x3c024017, 0x00621825,
+ 0x0e001044, 0xaca3001c, 0x96030008, 0x30630010, 0x1060001c, 0x8e420020,
+ 0x1040001a, 0x8e100000, 0x0e001006, 0x00000000, 0x8f820018, 0xac500000,
+ 0x8f830018, 0xac600004, 0x8f820018, 0xac400008, 0x8f830018, 0xac60000c,
+ 0x8f820018, 0xac400010, 0x8f830018, 0xac600014, 0x8f850018, 0x3c036000,
+ 0x8c634448, 0x24040001, 0xaca30018, 0x9622000e, 0x8f850018, 0x3c034015,
+ 0x00431025, 0x0e001044, 0xaca2001c, 0x00001021, 0x8fbf001c, 0x8fb20018,
+ 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0xafbf0010,
+ 0x936200c4, 0x30420002, 0x10400019, 0x00000000, 0x936200c5, 0x936300b1,
+ 0x00431023, 0x304400ff, 0x30830080, 0x10600004, 0x00000000, 0x0000000d,
+ 0x00000000, 0x24000a6a, 0x93620004, 0x00441023, 0x304400ff, 0x30830080,
+ 0x10600004, 0x2482ffff, 0x8f650024, 0x0a000b82, 0x00000000, 0x00022b00,
+ 0x8f620024, 0x0045102b, 0x10400002, 0x00000000, 0x8f650024, 0x8f620048,
+ 0x8f630040, 0x00431823, 0x0065202b, 0x10800004, 0x00000000, 0x8f620040,
+ 0x00451021, 0xaf620048, 0x9762003c, 0x0062102b, 0x10400041, 0x8fbf0010,
+ 0x10a0003f, 0x3c029000, 0x34420001, 0x3c040800, 0x8c830080, 0x8f450100,
+ 0x3c068000, 0x24630001, 0x00a21025, 0xac830080, 0xaf420020, 0x8f420020,
+ 0x00461024, 0x1440fffd, 0x3c038000, 0x9362007d, 0x34630001, 0x3c048000,
+ 0x00a31825, 0x34420004, 0xa362007d, 0xaf430020, 0x8f4201f8, 0x00441024,
+ 0x1440fffd, 0x24020002, 0x3c030800, 0xaf4501c0, 0xa34201c4, 0x8c640020,
+ 0x3c021000, 0xaf4201f8, 0x1080001f, 0x8fbf0010, 0x0e001006, 0x00000000,
+ 0x8f830018, 0x8f420100, 0xac620000, 0x8f840018, 0x8f620040, 0xac820004,
+ 0x8f850018, 0x8f620048, 0xaca20008, 0x8f830018, 0xac60000c, 0x8f820018,
+ 0xac400010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f840018, 0x8c434448,
+ 0x3c020800, 0xac830018, 0x9443466e, 0x8f840018, 0x3c0240c2, 0x00621825,
+ 0xac83001c, 0x0e001044, 0x24040001, 0x8fbf0010, 0x03e00008, 0x27bd0018,
+ 0x3c020800, 0x24423958, 0xaf82000c, 0x03e00008, 0x00000000, 0x27bdffe8,
+ 0xafb00010, 0x27500100, 0xafbf0014, 0x8e02001c, 0x14400003, 0x3c020800,
+ 0x0000000d, 0x3c020800, 0x8c430020, 0x10600026, 0x00001021, 0x0e001006,
+ 0x00000000, 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018, 0x8e02001c,
+ 0xac820004, 0x8f830018, 0xac600008, 0x8f840018, 0x8e020018, 0xac82000c,
+ 0x8f850018, 0x96020012, 0xaca20010, 0x8f830018, 0x3c106000, 0xac600014,
+ 0x8f840018, 0x8e024448, 0x3c030800, 0xac820018, 0x9462466e, 0x8f840018,
+ 0x3c034012, 0x00431025, 0xac82001c, 0x0e001044, 0x24040001, 0x8e036800,
+ 0x00001021, 0x3c040001, 0x00641825, 0xae036800, 0x0a000c0d, 0x8fbf0014,
+ 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c020800, 0x97430078,
+ 0x9444002e, 0x00001021, 0x00641821, 0x3063fffe, 0x03e00008, 0xa7630010,
+ 0x27450100, 0x8f640048, 0x8ca30018, 0x00641023, 0x18400021, 0x00000000,
+ 0xaf630048, 0x8f620040, 0x9763003c, 0x00821023, 0x0043102a, 0x1040001a,
+ 0x3c029000, 0x8ca40000, 0x34420001, 0x3c038000, 0x00821025, 0xaf420020,
+ 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x3c038000, 0x9362007d,
+ 0x34630001, 0x3c058000, 0x00831825, 0x34420004, 0xa362007d, 0xaf430020,
+ 0x8f4201f8, 0x00451024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4401c0,
+ 0xa34201c4, 0xaf4301f8, 0x03e00008, 0x00001021, 0x8f420100, 0x34420001,
+ 0xaf4200a4, 0x03e00008, 0x00001021, 0x27bdffe0, 0xafbf0018, 0xafb10014,
+ 0xafb00010, 0x9362007e, 0x30d000ff, 0x16020029, 0x00808821, 0x93620080,
+ 0x16020026, 0x00000000, 0x9362007f, 0x16020023, 0x00000000, 0x9362007a,
+ 0x16020004, 0x00000000, 0x0000000d, 0x00000000, 0x24000771, 0x0e000f49,
+ 0x00000000, 0x3c039000, 0x34630001, 0x3c048000, 0x02231825, 0xa370007a,
+ 0xaf430020, 0x8f420020, 0x00441024, 0x1440fffd, 0x3c028000, 0x9363007d,
+ 0x34420001, 0x3c048000, 0x02221025, 0xa363007d, 0xaf420020, 0x8f4201f8,
+ 0x00441024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf5101c0, 0xa34201c4,
+ 0xaf4301f8, 0x0a000c79, 0x8fbf0018, 0x0000000d, 0x00000000, 0x24000781,
+ 0x8fbf0018, 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x3c020800,
+ 0x8c430020, 0x27bdffe8, 0xafb00010, 0x27500100, 0x10600024, 0xafbf0014,
+ 0x0e001006, 0x00000000, 0x8f830018, 0x8e020000, 0xac620000, 0x8f840018,
+ 0x8e020004, 0xac820004, 0x8f830018, 0x8e020018, 0xac620008, 0x8f840018,
+ 0x8e03001c, 0xac83000c, 0x9602000c, 0x9203000a, 0x8f840018, 0x00021400,
+ 0x00431025, 0xac820010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f840018,
+ 0x8c434448, 0xac830018, 0x96020008, 0x3c030800, 0x9464466e, 0x8f850018,
+ 0x00021400, 0x00441025, 0x24040001, 0x0e001044, 0xaca2001c, 0x8fbf0014,
+ 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c020800, 0x8c430020, 0x27bdffe8,
+ 0xafb00010, 0x27500100, 0x10600020, 0xafbf0014, 0x0e001006, 0x00000000,
+ 0x8f820018, 0xac400000, 0x8f830018, 0xac600004, 0x8f820018, 0xac400008,
+ 0x8f830018, 0xac60000c, 0x9602000c, 0x9603000e, 0x8f840018, 0x00021400,
+ 0x00431025, 0xac820010, 0x8f830018, 0x3c026000, 0xac600014, 0x8f840018,
+ 0x8c434448, 0xac830018, 0x96020008, 0x3c030800, 0x9464466e, 0x8f850018,
+ 0x00021400, 0x00441025, 0x24040001, 0x0e001044, 0xaca2001c, 0x8fbf0014,
+ 0x8fb00010, 0x03e00008, 0x27bd0018, 0x27bdffe8, 0xafb00010, 0x27500100,
+ 0xafbf0014, 0x9602000c, 0x10400024, 0x00802821, 0x3c020800, 0x8c430020,
+ 0x1060003a, 0x8fbf0014, 0x0e001006, 0x00000000, 0x8f840018, 0x8e030000,
+ 0xac830000, 0x9602000c, 0x8f840018, 0x00021400, 0xac820004, 0x8f830018,
+ 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018,
+ 0xac400014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001, 0x3c020800,
+ 0xaca30018, 0x9443466e, 0x8f850018, 0x3c02400b, 0x00621825, 0x0e001044,
+ 0xaca3001c, 0x0a000d19, 0x8fbf0014, 0x93620005, 0x30420010, 0x14400015,
+ 0x3c029000, 0x34420001, 0x00a21025, 0xaf420020, 0x3c038000, 0x8f420020,
+ 0x00431024, 0x1440fffd, 0x00000000, 0x3c038000, 0x93620005, 0x34630001,
+ 0x00a02021, 0x00a31825, 0x24055852, 0x34420010, 0xa3620005, 0x0e000553,
+ 0xaf430020, 0x0a000d19, 0x8fbf0014, 0x0000000d, 0x8fbf0014, 0x8fb00010,
+ 0x03e00008, 0x27bd0018, 0x3c020800, 0x8c430020, 0x27bdffe8, 0xafb00010,
+ 0x27500100, 0x10600022, 0xafbf0014, 0x0e001006, 0x00000000, 0x8f840018,
+ 0x8e020004, 0xac820000, 0x9603000c, 0x9762002c, 0x8f840018, 0x00031c00,
+ 0x00431025, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c,
+ 0x8f830018, 0xac600010, 0x8f820018, 0xac400014, 0x8f850018, 0x3c026000,
+ 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x9443466e, 0x8f850018,
+ 0x3c02400e, 0x00621825, 0x0e001044, 0xaca3001c, 0x0e000d48, 0x8e040000,
+ 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c038000, 0x8f420278,
+ 0x00431024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf440240, 0xa3420244,
+ 0x03e00008, 0xaf430278, 0x3c020800, 0x8c430020, 0x27bdffe0, 0xafb10014,
+ 0x00808821, 0xafb20018, 0x00c09021, 0xafb00010, 0x30b0ffff, 0x1060001c,
+ 0xafbf001c, 0x0e001006, 0x00000000, 0x8f820018, 0xac510000, 0x8f840018,
+ 0x00101400, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c,
+ 0x8f830018, 0xac600010, 0x8f820018, 0xac520014, 0x8f840018, 0x3c026000,
+ 0x8c434448, 0x3c020800, 0xac830018, 0x9443466e, 0x8f840018, 0x3c024019,
+ 0x00621825, 0xac83001c, 0x0e001044, 0x24040001, 0x8fbf001c, 0x8fb20018,
+ 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x27bdffe8, 0x27450100,
+ 0xafbf0010, 0x94a3000c, 0x240200c1, 0x14620029, 0x00803021, 0x3c029000,
+ 0x34420001, 0x00c21025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024,
+ 0x1440fffd, 0x3c028000, 0x34420001, 0x3c049000, 0x34840001, 0x3c058000,
+ 0x24030012, 0x00c21025, 0x00c42025, 0xa363003f, 0xaf420020, 0xaf440020,
+ 0x8f420020, 0x00451024, 0x1440fffd, 0x3c038000, 0x9362007d, 0x34630001,
+ 0x3c048000, 0x00c31825, 0x34420020, 0xa362007d, 0xaf430020, 0x8f4201f8,
+ 0x00441024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4601c0, 0xa34201c4,
+ 0xaf4301f8, 0x0a000db3, 0x8fbf0010, 0x00c02021, 0x94a5000c, 0x24060001,
+ 0x0e000f78, 0x240706d8, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x3c020800,
+ 0x8c430020, 0x27bdffe0, 0xafb00010, 0x00808021, 0xafb20018, 0x00a09021,
+ 0xafb10014, 0x30d100ff, 0x1060001c, 0xafbf001c, 0x0e001006, 0x00000000,
+ 0x8f820018, 0xac500000, 0x8f840018, 0x24020001, 0xac820004, 0x8f830018,
+ 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010, 0x8f820018,
+ 0xac520014, 0x8f840018, 0x3c026000, 0x8c434448, 0x3c020800, 0xac830018,
+ 0x9443466e, 0x8f840018, 0x3c024010, 0x00621825, 0xac83001c, 0x0e001044,
+ 0x02202021, 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008,
+ 0x27bd0020, 0x27bdffe8, 0xafbf0014, 0xafb00010, 0x93620005, 0x30420001,
+ 0x10400033, 0x00808021, 0x3c029000, 0x34420001, 0x02021025, 0xaf420020,
+ 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93620005,
+ 0x3c048000, 0x3c030800, 0x304200fe, 0xa3620005, 0x8c620020, 0x34840001,
+ 0x02042025, 0xaf440020, 0x10400020, 0x8fbf0014, 0x0e001006, 0x00000000,
+ 0x8f820018, 0xac500000, 0x93630082, 0x9362003f, 0x8f840018, 0x00031a00,
+ 0x00431025, 0xac820004, 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c,
+ 0x8f830018, 0xac600010, 0x8f820018, 0xac400014, 0x8f840018, 0x3c026000,
+ 0x8c434448, 0x3c020800, 0xac830018, 0x9443466e, 0x8f840018, 0x3c02400a,
+ 0x00621825, 0xac83001c, 0x0e001044, 0x24040001, 0x8fbf0014, 0x8fb00010,
+ 0x03e00008, 0x27bd0018, 0x27bdffe8, 0xafbf0010, 0x8f420188, 0x00803021,
+ 0x9364003f, 0x24030012, 0x00021402, 0x1483001c, 0x304500ff, 0x3c029000,
+ 0x34420001, 0x3c038000, 0x00c21025, 0xa3650080, 0xa365007a, 0xaf420020,
+ 0x8f420020, 0x00431024, 0x1440fffd, 0x3c028000, 0x9363007d, 0x34420001,
+ 0x3c048000, 0x00c21025, 0xa363007d, 0xaf420020, 0x8f4201f8, 0x00441024,
+ 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4601c0, 0xa34201c4, 0xaf4301f8,
+ 0x0a000e54, 0x8fbf0010, 0x9362007e, 0x1445000e, 0x00000000, 0x93620080,
+ 0x1045000b, 0x00000000, 0xa3650080, 0x8f820000, 0x93660080, 0x8f440180,
+ 0x8f65004c, 0x8c430000, 0x0060f809, 0x00000000, 0x0a000e54, 0x8fbf0010,
+ 0xa3650080, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x3c020800, 0x8c430020,
+ 0x27bdffe0, 0xafb10014, 0x00808821, 0xafb20018, 0x00a09021, 0xafb00010,
+ 0x30d000ff, 0x1060002f, 0xafbf001c, 0x0e001006, 0x00000000, 0x8f820018,
+ 0xac510000, 0x8f830018, 0xac700004, 0x8f820018, 0xac520008, 0x8f830018,
+ 0xac60000c, 0x8f820018, 0xac400010, 0x9763006a, 0x00032880, 0x50a00001,
+ 0x24050001, 0x97630068, 0x93640081, 0x3c020800, 0x8c46004c, 0x00652821,
+ 0x00852804, 0x00c5102b, 0x54400001, 0x00a03021, 0x3c020800, 0x8c440050,
+ 0x00c4182b, 0x54600001, 0x00c02021, 0x8f830018, 0x2402fffe, 0x00822824,
+ 0x3c026000, 0xac650014, 0x8f840018, 0x8c434448, 0x3c020800, 0xac830018,
+ 0x9443466e, 0x8f840018, 0x3c024011, 0x00621825, 0xac83001c, 0x0e001044,
+ 0x24040001, 0x8fbf001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x03e00008,
+ 0x27bd0020, 0x27bdffe8, 0xafbf0014, 0xafb00010, 0x8f440100, 0x27500100,
+ 0x8f650050, 0x0e000c45, 0x9206001b, 0x3c020800, 0x8c430020, 0x1060001d,
+ 0x8e100018, 0x0e001006, 0x00000000, 0x8f840018, 0x8f420100, 0xac820000,
+ 0x8f830018, 0xac700004, 0x8f840018, 0x8f620050, 0xac820008, 0x8f830018,
+ 0xac60000c, 0x8f820018, 0xac400010, 0x8f830018, 0x3c026000, 0xac600014,
+ 0x8f850018, 0x8c434448, 0x24040001, 0x3c020800, 0xaca30018, 0x9443466e,
+ 0x8f850018, 0x3c02401c, 0x00621825, 0x0e001044, 0xaca3001c, 0x8fbf0014,
+ 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c029000, 0x8f460140, 0x34420001,
+ 0x3c038000, 0x00c21025, 0xaf420020, 0x8f420020, 0x00431024, 0x1440fffd,
+ 0x3c048000, 0x34840001, 0x3c059000, 0x34a50001, 0x3c078000, 0x24020012,
+ 0x24030080, 0x00c42025, 0x00c52825, 0xa362003f, 0xa3630082, 0xaf440020,
+ 0xaf450020, 0x8f420020, 0x00471024, 0x1440fffd, 0x3c038000, 0x9362007d,
+ 0x34630001, 0x3c048000, 0x00c31825, 0x34420020, 0xa362007d, 0xaf430020,
+ 0x8f4201f8, 0x00441024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4601c0,
+ 0xa34201c4, 0x03e00008, 0xaf4301f8, 0x8f430238, 0x3c020800, 0x04610013,
+ 0x8c44009c, 0x2406fffe, 0x3c050800, 0x3c038000, 0x2484ffff, 0x14800009,
+ 0x00000000, 0x97420078, 0x8ca3007c, 0x24420001, 0x00461024, 0x24630001,
+ 0xa7620010, 0x03e00008, 0xaca3007c, 0x8f420238, 0x00431024, 0x1440fff3,
+ 0x2484ffff, 0x8f420140, 0x3c031000, 0xaf420200, 0x03e00008, 0xaf430238,
+ 0x3c029000, 0x8f440140, 0x34420001, 0x3c038000, 0x00821025, 0xaf420020,
+ 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x3c038000, 0x9362007d,
+ 0x34630001, 0x3c058000, 0x00831825, 0x34420001, 0xa362007d, 0xaf430020,
+ 0x8f4201f8, 0x00451024, 0x1440fffd, 0x24020002, 0x3c031000, 0xaf4401c0,
+ 0xa34201c4, 0x03e00008, 0xaf4301f8, 0x0000000d, 0x03e00008, 0x00000000,
+ 0x0000000d, 0x03e00008, 0x00000000, 0x24020001, 0x03e00008, 0xa7620010,
+ 0x9362003f, 0x304400ff, 0x3883000e, 0x2c630001, 0x38820010, 0x2c420001,
+ 0x00621825, 0x14600003, 0x24020012, 0x14820003, 0x00000000, 0x03e00008,
+ 0x00001021, 0x9363007e, 0x9362007a, 0x14620006, 0x00000000, 0x9363007e,
+ 0x24020001, 0x24630001, 0x03e00008, 0xa363007e, 0x9363007e, 0x93620080,
+ 0x14620004, 0x24020001, 0xa362000b, 0x03e00008, 0x24020001, 0x03e00008,
+ 0x00001021, 0x9362000b, 0x10400021, 0x00001021, 0xa360000b, 0x9362003f,
+ 0x304400ff, 0x3883000e, 0x2c630001, 0x38820010, 0x2c420001, 0x00621825,
+ 0x14600015, 0x00001821, 0x24020012, 0x10820012, 0x00000000, 0x9363007e,
+ 0x9362007a, 0x14620007, 0x00000000, 0x9362007e, 0x24030001, 0x24420001,
+ 0xa362007e, 0x03e00008, 0x00601021, 0x9363007e, 0x93620080, 0x14620004,
+ 0x00001821, 0x24020001, 0xa362000b, 0x24030001, 0x03e00008, 0x00601021,
+ 0x03e00008, 0x00000000, 0x24040001, 0xaf64000c, 0x8f6300dc, 0x8f6200cc,
+ 0x50620001, 0xa7640010, 0xa7640012, 0xa7640014, 0x03e00008, 0xa7640016,
+ 0x27bdffd8, 0xafb00010, 0x00808021, 0xafb3001c, 0x00c09821, 0xafbf0020,
+ 0xafb20018, 0xafb10014, 0x93620023, 0x00e09021, 0x30420040, 0x10400020,
+ 0x30b1ffff, 0x3c020800, 0x8c430020, 0x1060001c, 0x00000000, 0x0e001006,
+ 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x3c02008d, 0xac820004,
+ 0x8f830018, 0xac600008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010,
+ 0x8f820018, 0xac520014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001,
+ 0x3c020800, 0xaca30018, 0x9443466e, 0x8f850018, 0x3c024019, 0x00621825,
+ 0x0e001044, 0xaca3001c, 0x93620023, 0x30420020, 0x14400003, 0x3c020800,
+ 0x52600020, 0x3c029000, 0x8c430020, 0x1060001d, 0x3c029000, 0x0e001006,
+ 0x00000000, 0x8f820018, 0xac500000, 0x8f840018, 0x00111400, 0xac820004,
+ 0x8f830018, 0xac720008, 0x8f820018, 0xac40000c, 0x8f830018, 0xac600010,
+ 0x8f820018, 0xac400014, 0x8f850018, 0x3c026000, 0x8c434448, 0x24040001,
+ 0x3c020800, 0xaca30018, 0x9443466e, 0x8f850018, 0x3c02401b, 0x00621825,
+ 0x0e001044, 0xaca3001c, 0x3c029000, 0x34420001, 0x02021025, 0xaf420020,
+ 0x3c038000, 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x93630023,
+ 0x3c028000, 0x34420001, 0x02021025, 0x8fbf0020, 0x8fb3001c, 0x8fb20018,
+ 0x8fb10014, 0x8fb00010, 0x3063009f, 0xa3630023, 0xaf420020, 0x03e00008,
+ 0x27bd0028, 0x3c020800, 0x8c430020, 0x27bdffe8, 0xafb00010, 0x27500100,
+ 0x1060001d, 0xafbf0014, 0x0e001006, 0x00000000, 0x8f830018, 0x8e020004,
+ 0xac620000, 0x8f840018, 0x8e020018, 0xac820004, 0x8f850018, 0x8e020000,
+ 0xaca20008, 0x8f830018, 0xac60000c, 0x8f820018, 0xac400010, 0x8f830018,
+ 0xac600014, 0x8f820018, 0xac400018, 0x96030008, 0x3c020800, 0x9444466e,
+ 0x8f850018, 0x00031c00, 0x00641825, 0x24040001, 0x0e001044, 0xaca3001c,
+ 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018, 0x3c060800, 0x24c54660,
+ 0x3c02000a, 0x03421821, 0x94640006, 0x94a2000a, 0x00441023, 0x00021400,
+ 0x00021c03, 0x04610006, 0xa4a40006, 0x0000000d, 0x00000000, 0x2400005a,
+ 0x0a00101b, 0x24020001, 0x8f820014, 0x0062102b, 0x14400002, 0x00001021,
+ 0x24020001, 0x304200ff, 0x1040001c, 0x274a0400, 0x3c07000a, 0x3c020800,
+ 0x24454660, 0x94a9000a, 0x8f880014, 0x03471021, 0x94430006, 0x00402021,
+ 0xa4a30006, 0x94820006, 0xa4a20006, 0x01221023, 0x00021400, 0x00021403,
+ 0x04410006, 0x0048102b, 0x0000000d, 0x00000000, 0x2400005a, 0x0a001036,
+ 0x24020001, 0x14400002, 0x00001021, 0x24020001, 0x304200ff, 0x1440ffec,
+ 0x03471021, 0x24c44660, 0x8c820010, 0xaf420038, 0x8c830014, 0x3c020005,
+ 0xaf43003c, 0xaf420030, 0xaf800010, 0xaf8a0018, 0x03e00008, 0x00000000,
+ 0x27bdffe0, 0x8f820010, 0x8f850018, 0x3c070800, 0x24e84660, 0xafbf001c,
+ 0xafb20018, 0xafb10014, 0xafb00010, 0x9503000a, 0x8d060014, 0x00009021,
+ 0x309000ff, 0x00e08821, 0x24420001, 0x24a50020, 0x24630001, 0xaf820010,
+ 0xaf850018, 0xa503000a, 0x24c30020, 0x3c028000, 0x04c10007, 0xad030014,
+ 0x00621024, 0x14400005, 0x26224660, 0x8d020010, 0x24420001, 0xad020010,
+ 0x26224660, 0x9444000a, 0x94450018, 0x0010102b, 0x00a41826, 0x2c630001,
+ 0x00621825, 0x1060001c, 0x3c030006, 0x8f820010, 0x24120001, 0x00021140,
+ 0x00431025, 0xaf420030, 0x00000000, 0x00000000, 0x00000000, 0x27450400,
+ 0x8f420000, 0x30420010, 0x1040fffd, 0x26224660, 0x9444000a, 0x94430018,
+ 0xaf800010, 0xaf850018, 0x14830012, 0x26274660, 0x0e0010d2, 0x00000000,
+ 0x1600000e, 0x26274660, 0x0e001006, 0x00000000, 0x0a00108f, 0x26274660,
+ 0x00041c00, 0x00031c03, 0x00051400, 0x00021403, 0x00621823, 0x18600002,
+ 0x3c026000, 0xac400808, 0x26274660, 0x94e2000e, 0x94e3000c, 0x24420001,
+ 0xa4e2000e, 0x3042ffff, 0x50430001, 0xa4e0000e, 0x12000005, 0x3c02000a,
+ 0x94e2000a, 0xa74200a2, 0x0a0010cc, 0x02401021, 0x03421821, 0x94640006,
+ 0x94e2000a, 0x00441023, 0x00021400, 0x00021c03, 0x04610006, 0xa4e40006,
+ 0x0000000d, 0x00000000, 0x2400005a, 0x0a0010ae, 0x24020001, 0x8f820014,
+ 0x0062102b, 0x14400002, 0x00001021, 0x24020001, 0x304200ff, 0x1040001b,
+ 0x3c020800, 0x3c06000a, 0x24454660, 0x94a8000a, 0x8f870014, 0x03461021,
+ 0x94430006, 0x00402021, 0xa4a30006, 0x94820006, 0xa4a20006, 0x01021023,
+ 0x00021400, 0x00021403, 0x04410006, 0x0047102b, 0x0000000d, 0x00000000,
+ 0x2400005a, 0x0a0010c8, 0x24020001, 0x14400002, 0x00001021, 0x24020001,
+ 0x304200ff, 0x1440ffec, 0x03461021, 0x02401021, 0x8fbf001c, 0x8fb20018,
+ 0x8fb10014, 0x8fb00010, 0x03e00008, 0x27bd0020, 0x3c020800, 0x24454660,
+ 0x94a3001a, 0x8ca40024, 0x00403021, 0x000318c0, 0x00832021, 0xaf44003c,
+ 0x8ca20020, 0xaf420038, 0x3c020050, 0x34420008, 0xaf420030, 0x00000000,
+ 0x00000000, 0x00000000, 0x8f420000, 0x30420020, 0x1040fffd, 0x00000000,
+ 0x8f430400, 0x24c64660, 0xacc30010, 0x8f420404, 0x3c030020, 0xacc20014,
+ 0xaf430030, 0x94c40018, 0x94c3001c, 0x94c2001a, 0x94c5001e, 0x00832021,
+ 0x24420001, 0xa4c2001a, 0x3042ffff, 0x14450002, 0xa4c40018, 0xa4c0001a,
+ 0x03e00008, 0x00000000, 0x8f820010, 0x3c030006, 0x00021140, 0x00431025,
+ 0xaf420030, 0x00000000, 0x00000000, 0x00000000, 0x27430400, 0x8f420000,
+ 0x30420010, 0x1040fffd, 0x00000000, 0xaf800010, 0xaf830018, 0x03e00008,
+ 0x00000000, 0x27bdffe8, 0xafb00010, 0x3c100800, 0x26104660, 0x3c05000a,
+ 0x02002021, 0x03452821, 0xafbf0014, 0x0e001128, 0x2406000a, 0x96020002,
+ 0x9603001e, 0x3042000f, 0x24420003, 0x00431804, 0x24027fff, 0x0043102b,
+ 0xaf830014, 0x10400004, 0x00000000, 0x0000000d, 0x00000000, 0x24000043,
+ 0x0e0010d2, 0x00000000, 0x8fbf0014, 0x8fb00010, 0x03e00008, 0x27bd0018,
+ 0x10c00007, 0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000,
+ 0x14c0fffb, 0x24840004, 0x03e00008, 0x00000000, 0x0a001137, 0x00a01021,
+ 0xac860000, 0x24840004, 0x00a01021, 0x1440fffc, 0x24a5ffff, 0x03e00008,
+ 0x00000000, 0x3c036000, 0x8c642b7c, 0x3c036010, 0x8c6553fc, 0x00041582,
+ 0x00042302, 0x308403ff, 0x00052d82, 0x00441026, 0x0002102b, 0x0005282b,
+ 0x00451025, 0x1440000d, 0x3c020050, 0x34420004, 0xaf400038, 0xaf40003c,
+ 0xaf420030, 0x00000000, 0x00000000, 0x8f420000, 0x30420020, 0x1040fffd,
+ 0x3c020020, 0xaf420030, 0x0000000d, 0x03e00008, 0x00000000, 0x3c020050,
+ 0x34420004, 0xaf440038, 0xaf45003c, 0xaf420030, 0x00000000, 0x00000000,
+ 0x8f420000, 0x30420020, 0x1040fffd, 0x3c020020, 0xaf420030, 0x03e00008,
+ 0x00000000, 0x00000000 };
+
+static u32 bnx2_COM_b06FwData[(0x0/4) + 1] = { 0x00000000 };
+static u32 bnx2_COM_b06FwRodata[(0x18/4) + 1] = {
+ 0x08002318, 0x08002348, 0x08002378, 0x080023a8, 0x080023d8, 0x00000000,
+ 0x00000000 };
+
+static u32 bnx2_COM_b06FwBss[(0x88/4) + 1] = { 0x00000000 };
+static u32 bnx2_COM_b06FwSbss[(0x1c/4) + 1] = { 0x00000000 };
+
+static int bnx2_RXP_b06FwReleaseMajor = 0x0;
+static int bnx2_RXP_b06FwReleaseMinor = 0x0;
+static int bnx2_RXP_b06FwReleaseFix = 0x0;
+static u32 bnx2_RXP_b06FwStartAddr = 0x08000060;
+static u32 bnx2_RXP_b06FwTextAddr = 0x08000000;
+static int bnx2_RXP_b06FwTextLen = 0x20b8;
+static u32 bnx2_RXP_b06FwDataAddr = 0x080020e0;
+static int bnx2_RXP_b06FwDataLen = 0x0;
+static u32 bnx2_RXP_b06FwRodataAddr = 0x00000000;
+static int bnx2_RXP_b06FwRodataLen = 0x0;
+static u32 bnx2_RXP_b06FwBssAddr = 0x08002100;
+static int bnx2_RXP_b06FwBssLen = 0x239c;
+static u32 bnx2_RXP_b06FwSbssAddr = 0x080020e0;
+static int bnx2_RXP_b06FwSbssLen = 0x14;
+
+static u32 bnx2_RXP_b06FwText[(0x20b8/4) + 1] = {
+ 0x0a000018, 0x00000000, 0x00000000, 0x0000000d, 0x72787020, 0x302e362e,
+ 0x39000000, 0x00060903, 0x00000000, 0x0000000d, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x10000003, 0x00000000, 0x0000000d, 0x0000000d, 0x3c020800,
+ 0x244220e0, 0x3c030800, 0x2463449c, 0xac400000, 0x0043202b, 0x1480fffd,
+ 0x24420004, 0x3c1d0800, 0x37bd3ffc, 0x03a0f021, 0x3c100800, 0x26100060,
+ 0x3c1c0800, 0x279c20e0, 0x0e000329, 0x00000000, 0x0000000d, 0x8f870008,
+ 0x2ce20080, 0x10400018, 0x3c030800, 0x24633490, 0x8f460100, 0x00072140,
+ 0x00831021, 0xac460000, 0x8f450104, 0x00641021, 0xac450004, 0x8f460108,
+ 0xac460008, 0x8f45010c, 0xac45000c, 0x8f460114, 0xac460010, 0x8f450118,
+ 0xac450014, 0x8f460124, 0xac460018, 0x8f450128, 0x00641821, 0x24e20001,
+ 0xaf820008, 0xac65001c, 0x03e00008, 0x00000000, 0x00804021, 0x8f830000,
+ 0x24070001, 0x3c020001, 0x00621024, 0x10400037, 0x00603021, 0x9742010e,
+ 0x3c038000, 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003,
+ 0xa342018b, 0x8f840004, 0x24020080, 0x24030002, 0xaf420180, 0xa743018c,
+ 0x10800005, 0xa745018e, 0x9743011c, 0x9742011e, 0x0a000069, 0x00021400,
+ 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f84000c,
+ 0x24020003, 0x30838000, 0x1060000d, 0xa7420188, 0x93420116, 0x304200fc,
+ 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600005, 0x00000000,
+ 0x3c02ffff, 0x34427fff, 0x00821024, 0xaf82000c, 0x9782000e, 0x9743010c,
+ 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6,
+ 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00001021, 0x30c21000,
+ 0x1040000f, 0x00000000, 0x9742010c, 0x3042fc00, 0x5440000b, 0x24070005,
+ 0x3c021000, 0x00c21024, 0x10400007, 0x3c030dff, 0x3463ffff, 0x3c020e00,
+ 0x00c21024, 0x0062182b, 0x54600001, 0x24070005, 0x8f82000c, 0x30434000,
+ 0x10600016, 0x00404821, 0x3c020f00, 0x00c21024, 0x14400012, 0x00000000,
+ 0x93420116, 0x34424000, 0x03421821, 0x94650002, 0x2ca21389, 0x1040000b,
+ 0x3c020800, 0x24422100, 0x00051942, 0x00031880, 0x00621821, 0x30a5001f,
+ 0x8c640000, 0x24020001, 0x00a21004, 0x00822024, 0x01044025, 0x11000037,
+ 0x3c021000, 0x9742010e, 0x34e60002, 0x3c038000, 0x24420004, 0x3045ffff,
+ 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x8f840004,
+ 0x24020180, 0x24030002, 0xaf420180, 0xa743018c, 0x10800005, 0xa745018e,
+ 0x9743011c, 0x9742011e, 0x0a0000cd, 0x00021400, 0x9743011e, 0x9742011c,
+ 0x00021400, 0x00621825, 0xaf4301a8, 0x8f84000c, 0x30828000, 0x1040000c,
+ 0xa7460188, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000,
+ 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00821024, 0xaf82000c,
+ 0x9782000e, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff,
+ 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x03e00008,
+ 0x00001021, 0x00c21024, 0x104000ba, 0x3c020800, 0x8c430030, 0x1060003e,
+ 0x31224000, 0x1040003c, 0x3c030f00, 0x00c31824, 0x3c020100, 0x0043102b,
+ 0x14400038, 0x3c030800, 0x9742010e, 0x34e60002, 0x3c038000, 0x24420004,
+ 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b,
+ 0x8f840004, 0x24020080, 0x24030002, 0xaf420180, 0xa743018c, 0x10800005,
+ 0xa745018e, 0x9743011c, 0x9742011e, 0x0a000110, 0x00021400, 0x9743011e,
+ 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f84000c, 0x30828000,
+ 0x1040000c, 0xa7460188, 0x93420116, 0x304200fc, 0x005a1021, 0x24424004,
+ 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff, 0x00821024,
+ 0xaf82000c, 0x9782000e, 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00,
+ 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8,
+ 0x03e00008, 0x00001021, 0x3c030800, 0x8c620024, 0x30420008, 0x1040003d,
+ 0x34e80002, 0x3c020f00, 0x00c21024, 0x5440003a, 0x3107ffff, 0x9742010c,
+ 0x30420200, 0x50400036, 0x3107ffff, 0x9742010e, 0x30e6fffb, 0x3c038000,
+ 0x24420004, 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003,
+ 0xa342018b, 0x8f840004, 0x24020180, 0x24030002, 0xaf420180, 0xa743018c,
+ 0x10800005, 0xa745018e, 0x9743011c, 0x9742011e, 0x0a000153, 0x00021400,
+ 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f84000c,
+ 0x30828000, 0x1040000c, 0xa7460188, 0x93420116, 0x304200fc, 0x005a1021,
+ 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff,
+ 0x00821024, 0xaf82000c, 0x9782000e, 0x9743010c, 0x8f440104, 0x3042bfff,
+ 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000,
+ 0xaf4201b8, 0x3107ffff, 0x8f820000, 0x3c068000, 0x9743010e, 0x00021442,
+ 0x30440780, 0x24630004, 0x3065ffff, 0x8f4201b8, 0x00461024, 0x1440fffd,
+ 0x24020003, 0xa342018b, 0x8f830004, 0x24020002, 0xaf440180, 0xa742018c,
+ 0x10600005, 0xa745018e, 0x9743011c, 0x9742011e, 0x0a000189, 0x00021400,
+ 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f84000c,
+ 0x30828000, 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, 0x005a1021,
+ 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff,
+ 0x00821024, 0xaf82000c, 0x9782000e, 0x9743010c, 0x8f440104, 0x3042bfff,
+ 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000,
+ 0xaf4201b8, 0x03e00008, 0x00001021, 0x8f424000, 0x30420100, 0x104000ef,
+ 0x3c020800, 0x8c440024, 0x24030001, 0x14830036, 0x00404021, 0x9742010e,
+ 0x34e50002, 0x3c038000, 0x24420004, 0x3044ffff, 0x8f4201b8, 0x00431024,
+ 0x1440fffd, 0x24020003, 0xa342018b, 0x8f830004, 0x24020002, 0xaf400180,
+ 0xa742018c, 0x10600005, 0xa744018e, 0x9743011c, 0x9742011e, 0x0a0001c6,
+ 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8,
+ 0x8f84000c, 0x30828000, 0x1040000c, 0xa7450188, 0x93420116, 0x304200fc,
+ 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff,
+ 0x34427fff, 0x00821024, 0xaf82000c, 0x9782000e, 0x9743010c, 0x8f440104,
+ 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac,
+ 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00001021, 0x30820001, 0x10400035,
+ 0x30e90004, 0x9742010e, 0x30e6fffb, 0x3c038000, 0x24420004, 0x3044ffff,
+ 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003, 0xa342018b, 0x8f830004,
+ 0x24020002, 0xaf400180, 0xa742018c, 0x10600005, 0xa744018e, 0x9743011c,
+ 0x9742011e, 0x0a0001fe, 0x00021400, 0x9743011e, 0x9742011c, 0x00021400,
+ 0x00621825, 0xaf4301a8, 0x8f84000c, 0x30828000, 0x1040000c, 0xa7470188,
+ 0x93420116, 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff,
+ 0x14600004, 0x3c02ffff, 0x34427fff, 0x00821024, 0xaf82000c, 0x9782000e,
+ 0x9743010c, 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825,
+ 0xa74201a6, 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x30c7ffff, 0x8d020024,
+ 0x30420004, 0x10400037, 0x8d020024, 0x9742010e, 0x30e6fffb, 0x3c038000,
+ 0x24420004, 0x3045ffff, 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020003,
+ 0xa342018b, 0x8f840004, 0x24020100, 0x24030002, 0xaf420180, 0xa743018c,
+ 0x10800005, 0xa745018e, 0x9743011c, 0x9742011e, 0x0a000237, 0x00021400,
+ 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f84000c,
+ 0x30828000, 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, 0x005a1021,
+ 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff,
+ 0x00821024, 0xaf82000c, 0x9782000e, 0x9743010c, 0x8f440104, 0x3042bfff,
+ 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000,
+ 0xaf4201b8, 0x30c7ffff, 0x8d020024, 0x30420008, 0x10400034, 0x00000000,
+ 0x9742010e, 0x3c038000, 0x24420004, 0x3045ffff, 0x8f4201b8, 0x00431024,
+ 0x1440fffd, 0x24020003, 0xa342018b, 0x8f840004, 0x24020180, 0x24030002,
+ 0xaf420180, 0xa743018c, 0x10800005, 0xa745018e, 0x9743011c, 0x9742011e,
+ 0x0a00026f, 0x00021400, 0x9743011e, 0x9742011c, 0x00021400, 0x00621825,
+ 0xaf4301a8, 0x8f84000c, 0x30828000, 0x1040000c, 0xa7470188, 0x93420116,
+ 0x304200fc, 0x005a1021, 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004,
+ 0x3c02ffff, 0x34427fff, 0x00821024, 0xaf82000c, 0x9782000e, 0x9743010c,
+ 0x8f440104, 0x3042bfff, 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6,
+ 0xaf4301ac, 0x3c021000, 0xaf4201b8, 0x15200046, 0x00001021, 0x3c038000,
+ 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, 0x24032000, 0xa342018b,
+ 0xa7430188, 0x3c021000, 0xaf4201b8, 0x03e00008, 0x00001021, 0x3c030800,
+ 0x8c620024, 0x30420001, 0x10400035, 0x00001021, 0x9742010e, 0x34e50002,
+ 0x3c038000, 0x24420004, 0x3044ffff, 0x8f4201b8, 0x00431024, 0x1440fffd,
+ 0x24020003, 0xa342018b, 0x8f830004, 0x24020002, 0xaf400180, 0xa742018c,
+ 0x10600005, 0xa744018e, 0x9743011c, 0x9742011e, 0x0a0002b5, 0x00021400,
+ 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f84000c,
+ 0x30828000, 0x1040000c, 0xa7450188, 0x93420116, 0x304200fc, 0x005a1021,
+ 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff,
+ 0x00821024, 0xaf82000c, 0x9782000e, 0x9743010c, 0x8f440104, 0x3042bfff,
+ 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000,
+ 0xaf4201b8, 0x00001021, 0x03e00008, 0x00000000, 0x27bdffe0, 0xafbf0018,
+ 0xafb10014, 0xafb00010, 0x8f420140, 0xaf420020, 0x8f430148, 0x3c027000,
+ 0x00621824, 0x3c024000, 0x1062000c, 0x0043102b, 0x14400006, 0x3c025000,
+ 0x3c023000, 0x1062000b, 0x3c024000, 0x0a00031f, 0x00000000, 0x10620034,
+ 0x3c024000, 0x0a00031f, 0x00000000, 0x0e00067c, 0x00000000, 0x0a00031f,
+ 0x3c024000, 0x8f420148, 0x24030002, 0x3044ffff, 0x00021402, 0x305000ff,
+ 0x1203000c, 0x27510180, 0x2a020003, 0x10400005, 0x24020003, 0x0600001d,
+ 0x36053000, 0x0a00030a, 0x3c038000, 0x12020007, 0x00000000, 0x0a000317,
+ 0x00000000, 0x0e000423, 0x00000000, 0x0a000308, 0x00402021, 0x0e000435,
+ 0x00000000, 0x00402021, 0x36053000, 0x3c038000, 0x8f4201b8, 0x00431024,
+ 0x1440fffd, 0x24020002, 0xa6250008, 0xa222000b, 0xa6240010, 0x8f420144,
+ 0x3c031000, 0xae220024, 0xaf4301b8, 0x0a00031f, 0x3c024000, 0x0000000d,
+ 0x00000000, 0x240001c3, 0x0a00031f, 0x3c024000, 0x0e0007f7, 0x00000000,
+ 0x3c024000, 0xaf420178, 0x00000000, 0x8fbf0018, 0x8fb10014, 0x8fb00010,
+ 0x03e00008, 0x27bd0020, 0x24020800, 0x03e00008, 0xaf4201b8, 0x27bdffe8,
+ 0x3c04600c, 0xafbf0014, 0xafb00010, 0x8c825000, 0x3c1a8000, 0x2403ff7f,
+ 0x3c106000, 0x00431024, 0x3442380c, 0x24030003, 0xac825000, 0x3c040008,
+ 0xaf430008, 0x8e020808, 0x3c030800, 0xac600020, 0x3042fff0, 0x2c420001,
+ 0xaf820004, 0x0e000819, 0x0344d825, 0x0e000781, 0x00000000, 0x3c020400,
+ 0x3442000c, 0x3c03ffff, 0x34630806, 0xae021948, 0xae03194c, 0x8e021980,
+ 0x34420200, 0xae021980, 0x8f500000, 0x32020003, 0x1040fffd, 0x32020001,
+ 0x10400004, 0x32020002, 0x0e0003bd, 0x00000000, 0x32020002, 0x1040fff6,
+ 0x00000000, 0x0e0002d4, 0x00000000, 0x0a00034a, 0x00000000, 0x27bdffe8,
+ 0x3c04600c, 0xafbf0014, 0xafb00010, 0x8c825000, 0x3c1a8000, 0x2403ff7f,
+ 0x3c106000, 0x00431024, 0x3442380c, 0x24030003, 0xac825000, 0x3c040008,
+ 0xaf430008, 0x8e020808, 0x3c030800, 0xac600020, 0x3042fff0, 0x2c420001,
+ 0xaf820004, 0x0e000819, 0x0344d825, 0x0e000781, 0x00000000, 0x3c020400,
+ 0x3442000c, 0x3c03ffff, 0x34630806, 0xae021948, 0xae03194c, 0x8e021980,
+ 0x8fbf0014, 0x34420200, 0xae021980, 0x8fb00010, 0x03e00008, 0x27bd0018,
+ 0x30a5ffff, 0x30c6ffff, 0x30e7ffff, 0x3c038000, 0x8f4201b8, 0x00431024,
+ 0x1440fffd, 0x24020003, 0xa342018b, 0x8f830004, 0xaf440180, 0xa745018c,
+ 0x10600005, 0xa746018e, 0x9743011c, 0x9742011e, 0x0a000393, 0x00021400,
+ 0x9743011e, 0x9742011c, 0x00021400, 0x00621825, 0xaf4301a8, 0x8f84000c,
+ 0x30828000, 0x1040000c, 0xa7470188, 0x93420116, 0x304200fc, 0x005a1021,
+ 0x24424004, 0x8c430000, 0x3063ffff, 0x14600004, 0x3c02ffff, 0x34427fff,
+ 0x00821024, 0xaf82000c, 0x9782000e, 0x9743010c, 0x8f440104, 0x3042bfff,
+ 0x00031c00, 0x3084ffff, 0x00641825, 0xa74201a6, 0xaf4301ac, 0x3c021000,
+ 0xaf4201b8, 0x03e00008, 0x00000000, 0x3c038000, 0x8f4201b8, 0x00431024,
+ 0x1440fffd, 0x24020002, 0x24032000, 0xa342018b, 0xa7430188, 0x3c021000,
+ 0xaf4201b8, 0x03e00008, 0x00000000, 0x27bdffe8, 0xafbf0010, 0x8f460128,
+ 0xaf460020, 0x8f420104, 0x8f450100, 0x24030800, 0x3c040010, 0xaf820000,
+ 0x00441024, 0xaf85000c, 0xaf4301b8, 0x14400005, 0x3c02001f, 0x3c030800,
+ 0x8c620020, 0x0a0003d5, 0x00002021, 0x3442ff00, 0x14c20009, 0x2402bfff,
+ 0x3c030800, 0x8c620020, 0x24040001, 0x24420001, 0x0e00004c, 0xac620020,
+ 0x0a0003e4, 0x00000000, 0x00a21024, 0x14400006, 0x00000000, 0xaf400048,
+ 0x0e000448, 0xaf400040, 0x0a0003e4, 0x00000000, 0x0e000783, 0x00000000,
+ 0x10400005, 0x3c024000, 0x8f430124, 0x3c026020, 0xac430014, 0x3c024000,
+ 0xaf420138, 0x00000000, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffe0,
+ 0xafbf0018, 0xafb10014, 0xafb00010, 0x8f420148, 0x24030002, 0x3044ffff,
+ 0x00021402, 0x305000ff, 0x1203000c, 0x27510180, 0x2a020003, 0x10400005,
+ 0x24020003, 0x0600001d, 0x36053000, 0x0a00040e, 0x3c038000, 0x12020007,
+ 0x00000000, 0x0a00041b, 0x00000000, 0x0e000423, 0x00000000, 0x0a00040c,
+ 0x00402021, 0x0e000435, 0x00000000, 0x00402021, 0x36053000, 0x3c038000,
+ 0x8f4201b8, 0x00431024, 0x1440fffd, 0x24020002, 0xa6250008, 0xa222000b,
+ 0xa6240010, 0x8f420144, 0x3c031000, 0xae220024, 0xaf4301b8, 0x0a00041f,
+ 0x8fbf0018, 0x0000000d, 0x00000000, 0x240001c3, 0x8fbf0018, 0x8fb10014,
+ 0x8fb00010, 0x03e00008, 0x27bd0020, 0x3084ffff, 0x2c821389, 0x1040000d,
+ 0x00001021, 0x3c030800, 0x24632100, 0x00042942, 0x00052880, 0x00a32821,
+ 0x3086001f, 0x8ca40000, 0x24030001, 0x00c31804, 0x00832025, 0x03e00008,
+ 0xaca40000, 0x03e00008, 0x24020091, 0x3084ffff, 0x2c821389, 0x1040000e,
+ 0x00001021, 0x3c030800, 0x24632100, 0x00042942, 0x00052880, 0x00a32821,
+ 0x3086001f, 0x24030001, 0x8ca40000, 0x00c31804, 0x00031827, 0x00832024,
+ 0x03e00008, 0xaca40000, 0x03e00008, 0x24020091, 0x27bdffb0, 0x3c026000,
+ 0xafbf0048, 0x8c434448, 0xaf630140, 0x93620005, 0x30420001, 0x14400005,
+ 0x00000000, 0x0e0007ed, 0x00000000, 0x0a00067a, 0x8fbf0048, 0x93420116,
+ 0x93430112, 0x8f430104, 0x3c040020, 0x34424000, 0x00641824, 0x1060000d,
+ 0x03426021, 0x8f430128, 0x27420180, 0xac430000, 0x8f650040, 0x24040008,
+ 0x240340c1, 0xa4430008, 0x24030002, 0xa043000b, 0x3c031000, 0x0a000563,
+ 0xa044000a, 0x8f420104, 0x3c030040, 0x00431024, 0x10400007, 0x00000000,
+ 0x8f430128, 0x27420180, 0xac430000, 0x8f650040, 0x0a00055c, 0x24040010,
+ 0xaf400048, 0xaf400054, 0xaf400040, 0x8f630048, 0x8f620040, 0x00624823,
+ 0x05210004, 0x00000000, 0x0000000d, 0x00000000, 0x24000132, 0x9742011a,
+ 0x3046ffff, 0x10c00004, 0x8d880004, 0x01061021, 0x0a000487, 0x2445ffff,
+ 0x01002821, 0x918a000d, 0xa7a00020, 0xafa00028, 0x9364003f, 0x3c026000,
+ 0x8c434448, 0x308700ff, 0x31420004, 0x10400033, 0xaf630144, 0x24090012,
+ 0x14e90006, 0x3c040800, 0x8c830028, 0x24020001, 0x24630001, 0x0a00054e,
+ 0xac830028, 0x8f620044, 0x15020012, 0x97a20020, 0x27a60010, 0x27450180,
+ 0x3442001a, 0xa7a20020, 0x8f630040, 0x3c048000, 0x24020020, 0xa3a70022,
+ 0xa3a90023, 0xa3a2001a, 0xafa30028, 0x8f4201b8, 0x00441024, 0x1440fffd,
+ 0x00000000, 0x0a000533, 0x00000000, 0x8f620044, 0x01021023, 0x0440009e,
+ 0x24020001, 0x8f620048, 0x01021023, 0x0441009a, 0x24020001, 0x97a20020,
+ 0x27a60010, 0x34420001, 0xa7a20020, 0x8f630040, 0x27450180, 0x3c048000,
+ 0xafa30028, 0x8f4201b8, 0x00441024, 0x1440fffd, 0x00000000, 0x0a000533,
+ 0x00000000, 0x3c026000, 0x8c424448, 0xaf620148, 0x8f630040, 0x00685823,
+ 0x19600013, 0x00cb102a, 0x54400007, 0x314a00fe, 0x5566000c, 0x010b4021,
+ 0x31420001, 0x54400009, 0x010b4021, 0x314a00fe, 0x24020001, 0xa7a20020,
+ 0x8f630040, 0x00c05821, 0x00003021, 0x0a0004dd, 0xafa30028, 0x00cb1023,
+ 0x0a0004dd, 0x3046ffff, 0x00005821, 0x8f620048, 0x2442ffff, 0x00a21823,
+ 0x18600019, 0x0066102a, 0x14400013, 0x24020001, 0xa7a20020, 0x8f630040,
+ 0xafa30028, 0x8f620040, 0x55020005, 0x27a60010, 0x55200003, 0x27a60010,
+ 0x0a0004f6, 0x00c01821, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024,
+ 0x1440fffd, 0x00000000, 0x0a000533, 0x00000000, 0x8f650048, 0x00c31023,
+ 0x3046ffff, 0x314a00f6, 0x3c046000, 0x8c824448, 0x31430002, 0x1060001e,
+ 0xaf62014c, 0x8f620044, 0x1502000e, 0x97a20020, 0x27a60010, 0x34420200,
+ 0xa7a20020, 0x8f630040, 0x27450180, 0x3c048000, 0xafa30028, 0x8f4201b8,
+ 0x00441024, 0x1440fffd, 0x00000000, 0x0a000533, 0x00000000, 0x27a60010,
+ 0x34420001, 0xa7a20020, 0x8f630040, 0x27450180, 0x3c048000, 0xafa30028,
+ 0x8f4201b8, 0x00441024, 0x1440fffd, 0x00000000, 0x0a000533, 0x00000000,
+ 0x3c026000, 0x8c424448, 0x31430010, 0xaf620150, 0x54600003, 0x8d890008,
+ 0x0a00054e, 0x24020001, 0x8f630054, 0x2522ffff, 0x00431023, 0x1840002a,
+ 0x24020001, 0x27a60010, 0xa7a20020, 0x8f630040, 0x27450180, 0x3c048000,
+ 0xafa30028, 0x8f4201b8, 0x00441024, 0x1440fffd, 0x00000000, 0x8f420128,
+ 0xaca20000, 0x8cc30018, 0x240240c1, 0xa4a20008, 0xaca30018, 0x90c4000a,
+ 0x24020002, 0xa0a2000b, 0xa0a4000a, 0x94c20010, 0xa4a20010, 0x90c30012,
+ 0xa0a30012, 0x90c20013, 0xa0a20013, 0x8cc30014, 0xaca30014, 0x8cc20024,
+ 0xaca20024, 0x8cc30028, 0xaca30028, 0x8cc4002c, 0x24020001, 0x3c031000,
+ 0xaca4002c, 0xaf4301b8, 0xaf400044, 0xaf400050, 0x0a00067a, 0x8fbf0048,
+ 0x3c026000, 0x8c424448, 0x31430020, 0x10600019, 0xaf620154, 0x8f430128,
+ 0x27420180, 0xac430000, 0x8f650040, 0x24040004, 0x240340c1, 0xa4430008,
+ 0x24030002, 0xa044000a, 0x24040008, 0xa043000b, 0x3c031000, 0xa4440010,
+ 0xa0400012, 0xa0400013, 0xac400014, 0xac400024, 0xac400028, 0xac40002c,
+ 0xac450018, 0x0e0007ed, 0xaf4301b8, 0x0a00067a, 0x8fbf0048, 0x8f430104,
+ 0x8c824448, 0x38e3000a, 0x2c630001, 0xaf620158, 0x38e2000c, 0x2c420001,
+ 0x00621825, 0x14600003, 0x2402000e, 0x14e2002a, 0x00000000, 0x50c00008,
+ 0x9584000e, 0x10c00004, 0xa7a60040, 0x01061021, 0x0a000583, 0x2445ffff,
+ 0x01002821, 0x9584000e, 0x93630035, 0x8f62004c, 0x00642004, 0x00892021,
+ 0x00821023, 0x1840001f, 0x3c026000, 0x8f620018, 0x01021023, 0x1c40000f,
+ 0x97a20020, 0x8f620018, 0x15020018, 0x3c026000, 0x8f62001c, 0x01221023,
+ 0x1c400008, 0x97a20020, 0x8f62001c, 0x15220011, 0x3c026000, 0x8f620058,
+ 0x00821023, 0x1840000c, 0x97a20020, 0xafa50028, 0xafa80034, 0xafa90038,
+ 0xafa4003c, 0x34420020, 0x0a0005a8, 0xa7a20020, 0x8f680040, 0x00003021,
+ 0x8f640058, 0x01002821, 0x3c026000, 0x8c434448, 0xaf63015c, 0x8f62004c,
+ 0x01221023, 0x18400009, 0x00000000, 0x8f620054, 0x01221023, 0x1c400005,
+ 0x97a20020, 0xafa50028, 0xafa90024, 0x0a0005c3, 0x34420040, 0x9742011a,
+ 0x1440000c, 0x24020014, 0x8f620058, 0x14820009, 0x24020014, 0x8f63004c,
+ 0x8f620054, 0x10620004, 0x97a20020, 0xafa50028, 0x34420080, 0xa7a20020,
+ 0x24020014, 0x10e2000a, 0x28e20015, 0x10400005, 0x2402000c, 0x10e20006,
+ 0x3c026000, 0x0a000600, 0x00000000, 0x24020016, 0x14e20031, 0x3c026000,
+ 0x8f620054, 0x24420001, 0x1522002d, 0x3c026000, 0x24020014, 0x10e2001e,
+ 0x28e20015, 0x10400005, 0x2402000c, 0x10e20008, 0x3c026000, 0x0a000600,
+ 0x00000000, 0x24020016, 0x10e2000c, 0x97a20020, 0x0a000600, 0x3c026000,
+ 0x97a30020, 0x2402000e, 0xafa50028, 0xa3a70022, 0xa3a20023, 0xafa90024,
+ 0x34630054, 0x0a0005ff, 0xa7a30020, 0x24030010, 0x24040002, 0xafa50028,
+ 0xa3a70022, 0xa3a30023, 0xa3a4001a, 0xafa90024, 0x0a0005fe, 0x3442005d,
+ 0x97a20020, 0x24030012, 0x24040002, 0xafa50028, 0xa3a70022, 0xa3a30023,
+ 0xa3a4001a, 0xafa90024, 0x3042fffe, 0x3442005c, 0xa7a20020, 0x3c026000,
+ 0x8c434448, 0x31420001, 0xaf630160, 0x1040002c, 0x2402000c, 0x10e20014,
+ 0x28e2000d, 0x10400005, 0x2402000a, 0x10e20008, 0x97a20020, 0x0a000631,
+ 0x3c026000, 0x2402000e, 0x10e20018, 0x3c026000, 0x0a000631, 0x00000000,
+ 0x24030008, 0x24040002, 0xafa50028, 0xa3a70022, 0xa3a30023, 0xa3a4001a,
+ 0x0a00062f, 0x34420013, 0x97a30020, 0x30620004, 0x1440000b, 0x97a20020,
+ 0x3462001b, 0xa7a20020, 0x24020016, 0x24030002, 0xafa50028, 0xa3a70022,
+ 0xa3a20023, 0x0a000630, 0xa3a3001a, 0x97a20020, 0x24030010, 0x24040002,
+ 0xafa50028, 0xa3a70022, 0xa3a30023, 0xa3a4001a, 0x3442001b, 0xa7a20020,
+ 0x3c026000, 0x8c434448, 0x31420009, 0x0002102b, 0x00021023, 0x30420007,
+ 0x34440003, 0xaf630164, 0x10c00016, 0x24030800, 0x8f820010, 0x27450180,
+ 0x24420001, 0xaf820010, 0x24020004, 0xaf4301b8, 0xa4a40008, 0xa0a2000b,
+ 0x93440120, 0x3c031000, 0xa4a6000e, 0xaca90024, 0xaca80028, 0x008b2021,
+ 0xa4a4000c, 0xaf4301b8, 0x97a20020, 0x00003021, 0x3042ffbf, 0x0a000650,
+ 0xa7a20020, 0x24060001, 0x3c026000, 0x8c434448, 0xaf630168, 0x97a20020,
+ 0x10400020, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd,
+ 0x00000000, 0x8f420128, 0xaca20000, 0x8fa30028, 0x240240c1, 0xa4a20008,
+ 0xaca30018, 0x93a4001a, 0x24020002, 0xa0a2000b, 0xa0a4000a, 0x97a20020,
+ 0xa4a20010, 0x93a30022, 0xa0a30012, 0x93a20023, 0xa0a20013, 0x8fa30024,
+ 0xaca30014, 0x8fa20034, 0xaca20024, 0x8fa30038, 0xaca30028, 0x8fa2003c,
+ 0x3c031000, 0xaca2002c, 0xaf4301b8, 0x3c026000, 0x8c434448, 0x00c01021,
+ 0xaf63016c, 0x8fbf0048, 0x03e00008, 0x27bd0050, 0x8f460140, 0x8f470148,
+ 0x3c028000, 0x00e24024, 0x00072c02, 0x30a300ff, 0x2402000b, 0x1062008f,
+ 0x27440180, 0x2862000c, 0x10400011, 0x24020006, 0x1062005a, 0x28620007,
+ 0x10400007, 0x24020008, 0x10600024, 0x24020001, 0x10620037, 0x00000000,
+ 0x0a00077e, 0x00000000, 0x106200a9, 0x24020009, 0x106200bb, 0x00071c02,
+ 0x0a00077e, 0x00000000, 0x2402001b, 0x106200c7, 0x2862001c, 0x10400007,
+ 0x2402000e, 0x106200b1, 0x24020019, 0x106200c2, 0x00071c02, 0x0a00077e,
+ 0x00000000, 0x24020080, 0x10620060, 0x28620081, 0x10400005, 0x2402001c,
+ 0x10620094, 0x00071c02, 0x0a00077e, 0x00000000, 0x240200c2, 0x106200c5,
+ 0x00a01821, 0x0a00077e, 0x00000000, 0x00a01821, 0x3c058000, 0x8f4201b8,
+ 0x00451024, 0x1440fffd, 0x24020001, 0xa4830008, 0x24030002, 0xac860000,
+ 0xac800004, 0xa082000a, 0xa083000b, 0xa4870010, 0x8f430144, 0x3c021000,
+ 0xac800028, 0xac830024, 0x3c036000, 0xaf4201b8, 0x03e00008, 0xac600808,
+ 0x11000009, 0x00a01821, 0x3c020800, 0x24030002, 0xa0434490, 0x24424490,
+ 0xac460008, 0x8f430144, 0x03e00008, 0xac430004, 0x3c058000, 0x8f4201b8,
+ 0x00451024, 0x1440fffd, 0x24020002, 0xac800000, 0xac860004, 0xa4830008,
+ 0xa082000a, 0xa082000b, 0xa4870010, 0xac800024, 0x8f420144, 0x3c031000,
+ 0xac820028, 0x3c026000, 0xaf4301b8, 0x03e00008, 0xac400808, 0x00a01821,
+ 0x3c080800, 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x00000000,
+ 0xac860000, 0x91024490, 0x00002821, 0x10400002, 0x25064490, 0x8cc50008,
+ 0xac850004, 0xa4830008, 0x91034490, 0x24020002, 0xa082000b, 0xa4870010,
+ 0x34630001, 0xa083000a, 0x8f420144, 0xac820024, 0x91034490, 0x10600002,
+ 0x00001021, 0x8cc20004, 0xac820028, 0x3c021000, 0xaf4201b8, 0x3c026000,
+ 0xa1004490, 0x03e00008, 0xac400808, 0x00a01821, 0x3c058000, 0x8f4201b8,
+ 0x00451024, 0x1440fffd, 0x24020002, 0xa082000b, 0xa4830008, 0xa4870010,
+ 0x8f420144, 0x3c031000, 0xa4820012, 0x03e00008, 0xaf4301b8, 0x30e2ffff,
+ 0x14400028, 0x00071c02, 0x93620005, 0x30420004, 0x14400020, 0x3c029000,
+ 0x34420001, 0x00c21025, 0xaf420020, 0x3c038000, 0x8f420020, 0x00431024,
+ 0x1440fffd, 0x00000000, 0x93620005, 0x3c038000, 0x34630001, 0x00c31825,
+ 0x34420004, 0xa3620005, 0xaf430020, 0x93620005, 0x30420004, 0x14400003,
+ 0x3c038000, 0x0000000d, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd,
+ 0x24020005, 0x3c031000, 0xac860000, 0xa082000b, 0xaf4301b8, 0x0a00073d,
+ 0x00071c02, 0x0000000d, 0x03e00008, 0x00000000, 0x00071c02, 0x3c058000,
+ 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020001, 0xa4830008, 0x24030002,
+ 0xac860000, 0xac800004, 0xa082000a, 0xa083000b, 0xa4870010, 0x8f430144,
+ 0x3c021000, 0xac800028, 0xac830024, 0x03e00008, 0xaf4201b8, 0x00071c02,
+ 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002, 0xac800000,
+ 0xac860004, 0xa4830008, 0xa082000a, 0xa082000b, 0xa4870010, 0xac800024,
+ 0x8f420144, 0x3c031000, 0xac820028, 0x03e00008, 0xaf4301b8, 0x00071c02,
+ 0x3c058000, 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020001, 0xa4830008,
+ 0x24030002, 0xa082000a, 0x3c021000, 0xac860000, 0xac800004, 0xa083000b,
+ 0xa4870010, 0xac800024, 0xac800028, 0x03e00008, 0xaf4201b8, 0x3c058000,
+ 0x8f4201b8, 0x00451024, 0x1440fffd, 0x24020002, 0xac860000, 0xac800004,
+ 0xa4830008, 0xa080000a, 0x0a000748, 0xa082000b, 0x0000000d, 0x03e00008,
+ 0x00000000, 0x03e00008, 0x00000000, 0x8f420100, 0x3042003e, 0x14400011,
+ 0x24020001, 0xaf400048, 0x8f420100, 0x304207c0, 0x10400005, 0x00000000,
+ 0xaf40004c, 0xaf400050, 0x03e00008, 0x24020001, 0xaf400054, 0xaf400040,
+ 0x8f420100, 0x30423800, 0x54400001, 0xaf400044, 0x24020001, 0x03e00008,
+ 0x00000000, 0x3c029000, 0x34420001, 0x00822025, 0xaf440020, 0x3c038000,
+ 0x8f420020, 0x00431024, 0x1440fffd, 0x00000000, 0x03e00008, 0x00000000,
+ 0x3c028000, 0x34420001, 0x00822025, 0x03e00008, 0xaf440020, 0x8f430128,
+ 0x27420180, 0xac430000, 0x8f650040, 0x240340c1, 0xa4430008, 0x24030002,
+ 0xa044000a, 0x24040008, 0xa043000b, 0x3c031000, 0xa4440010, 0xa0400012,
+ 0xa0400013, 0xac400014, 0xac400024, 0xac400028, 0xac40002c, 0xac450018,
+ 0x03e00008, 0xaf4301b8, 0x24020001, 0xacc40000, 0x03e00008, 0xa4e50000,
+ 0x03e00008, 0x24020001, 0x24020001, 0xaf400044, 0x03e00008, 0xaf400050,
+ 0x00803021, 0x27450180, 0x3c038000, 0x8f4201b8, 0x00431024, 0x1440fffd,
+ 0x00000000, 0x8f420128, 0xaca20000, 0x8cc30018, 0x240240c1, 0xa4a20008,
+ 0xaca30018, 0x90c4000a, 0x24020002, 0xa0a2000b, 0xa0a4000a, 0x94c20010,
+ 0xa4a20010, 0x90c30012, 0xa0a30012, 0x90c20013, 0xa0a20013, 0x8cc30014,
+ 0xaca30014, 0x8cc20024, 0xaca20024, 0x8cc30028, 0xaca30028, 0x8cc2002c,
+ 0x3c031000, 0xaca2002c, 0x24020001, 0xaf4301b8, 0xaf400044, 0x03e00008,
+ 0xaf400050, 0x27bdffe8, 0xafbf0010, 0x0e000326, 0x00000000, 0x00002021,
+ 0x0e00004c, 0xaf400180, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x8f460148,
+ 0x27450180, 0x3c038000, 0x00061402, 0x304700ff, 0x8f4201b8, 0x00431024,
+ 0x1440fffd, 0x00000000, 0x8f440140, 0x00061202, 0x304200ff, 0x00061c02,
+ 0xaca20004, 0x24020002, 0xa4a30008, 0x30c300ff, 0xa0a2000b, 0xaca30024,
+ 0x10e0000a, 0xaca40000, 0x28e20004, 0x14400005, 0x24020001, 0x24020005,
+ 0x54e20005, 0xa0a0000a, 0x24020001, 0x0a000816, 0xa0a2000a, 0xa0a0000a,
+ 0x3c021000, 0x03e00008, 0xaf4201b8, 0x03e00008, 0x00001021, 0x10c00007,
+ 0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000, 0x14c0fffb,
+ 0x24840004, 0x03e00008, 0x00000000, 0x0a00082a, 0x00a01021, 0xac860000,
+ 0x24840004, 0x00a01021, 0x1440fffc, 0x24a5ffff, 0x03e00008, 0x00000000,
+ 0x00000000 };
+
+static u32 bnx2_RXP_b06FwData[(0x0/4) + 1] = { 0x00000000 };
+static u32 bnx2_RXP_b06FwRodata[(0x0/4) + 1] = { 0x00000000 };
+static u32 bnx2_RXP_b06FwBss[(0x239c/4) + 1] = { 0x00000000 };
+static u32 bnx2_RXP_b06FwSbss[(0x14/4) + 1] = { 0x00000000 };
+
+static u32 bnx2_rv2p_proc1[] = {
+ 0x00000008, 0xac000001, 0x0000000c, 0x2f800001, 0x00000010, 0x213f0004,
+ 0x00000010, 0x20bf002c, 0x00000010, 0x203f0143, 0x00000018, 0x8000fffd,
+ 0x00000010, 0xb1b8b017, 0x0000000b, 0x2fdf0002, 0x00000000, 0x03d80000,
+ 0x00000000, 0x2c380000, 0x00000008, 0x2c800000, 0x00000008, 0x2d000000,
+ 0x00000010, 0x91d40000, 0x00000008, 0x2d800108, 0x00000008, 0x02000002,
+ 0x00000010, 0x91de0000, 0x0000000f, 0x42e0001c, 0x00000010, 0x91840a08,
+ 0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008, 0x00000008, 0x2d800150,
+ 0x00000000, 0x00000000, 0x00000010, 0x91de0000, 0x00000010, 0x2c620002,
+ 0x00000018, 0x80000012, 0x0000000b, 0x2fdf0002, 0x0000000c, 0x1f800002,
+ 0x00000000, 0x2c070000, 0x00000018, 0x8000ffe6, 0x00000008, 0x02000002,
+ 0x0000000f, 0x42e0001c, 0x00000010, 0x91840a08, 0x00000008, 0x2c8000b0,
+ 0x00000008, 0x2d000008, 0x00000010, 0x91d40000, 0x00000008, 0x2d800108,
+ 0x00000000, 0x00000000, 0x00000010, 0x91de0000, 0x00000018, 0x80000004,
+ 0x0000000c, 0x1f800002, 0x00000000, 0x00000000, 0x00000018, 0x8000ffd9,
+ 0x0000000c, 0x29800002, 0x0000000c, 0x1f800002, 0x00000000, 0x2adf0000,
+ 0x00000008, 0x2a000005, 0x00000018, 0x8000ffd4, 0x00000008, 0x02240030,
+ 0x00000018, 0x00040000, 0x00000018, 0x80000015, 0x00000018, 0x80000017,
+ 0x00000018, 0x8000001b, 0x00000018, 0x8000004c, 0x00000018, 0x8000008c,
+ 0x00000018, 0x8000000f, 0x00000018, 0x8000000e, 0x00000018, 0x8000000d,
+ 0x00000018, 0x8000000c, 0x00000018, 0x800000c2, 0x00000018, 0x8000000a,
+ 0x00000018, 0x80000009, 0x00000018, 0x80000008, 0x00000018, 0x800000fd,
+ 0x00000018, 0x80000006, 0x00000018, 0x80000005, 0x00000018, 0x800000ff,
+ 0x00000018, 0x80000104, 0x00000018, 0x80000002, 0x00000018, 0x80000098,
+ 0x00000018, 0x80000000, 0x0000000c, 0x1f800001, 0x00000000, 0x00000000,
+ 0x00000018, 0x8000ffba, 0x00000010, 0x91d40000, 0x0000000c, 0x29800001,
+ 0x0000000c, 0x1f800001, 0x00000008, 0x2a000002, 0x00000018, 0x8000ffb5,
+ 0x00000010, 0xb1a0b012, 0x0000000b, 0x2fdf0002, 0x00000000, 0x2c200000,
+ 0x00000008, 0x2c800000, 0x00000008, 0x2d000000, 0x00000010, 0x91d40000,
+ 0x00000008, 0x2d80011c, 0x00000000, 0x00000000, 0x00000010, 0x91de0000,
+ 0x0000000f, 0x47600008, 0x0000000f, 0x060e0001, 0x00000010, 0x001f0000,
+ 0x00000000, 0x0f580000, 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000,
+ 0x00000000, 0x0b660000, 0x00000000, 0x0d610000, 0x00000018, 0x80000013,
+ 0x0000000f, 0x47600008, 0x0000000b, 0x2fdf0002, 0x00000008, 0x2c800000,
+ 0x00000008, 0x2d000000, 0x00000010, 0x91d40000, 0x00000008, 0x2d80011c,
+ 0x0000000f, 0x060e0001, 0x00000010, 0x001f0000, 0x00000000, 0x0f580000,
+ 0x00000010, 0x91de0000, 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000,
+ 0x00000000, 0x0b660000, 0x00000000, 0x0d610000, 0x00000000, 0x02620000,
+ 0x0000000b, 0x2fdf0002, 0x00000000, 0x309a0000, 0x00000000, 0x31040000,
+ 0x00000000, 0x0c961800, 0x00000009, 0x0c99ffff, 0x00000004, 0xcc993400,
+ 0x00000010, 0xb1963202, 0x00000008, 0x0f800000, 0x0000000c, 0x29800001,
+ 0x00000010, 0x00220002, 0x0000000c, 0x29520001, 0x0000000c, 0x29520000,
+ 0x00000008, 0x22000001, 0x0000000c, 0x1f800001, 0x00000000, 0x2adf0000,
+ 0x00000008, 0x2a000003, 0x00000018, 0x8000ff83, 0x00000010, 0xb1a0b01d,
+ 0x0000000b, 0x2fdf0002, 0x00000000, 0x2c200000, 0x00000008, 0x2c8000b0,
+ 0x00000008, 0x2d000008, 0x00000010, 0x91d40000, 0x00000008, 0x2d800150,
+ 0x00000000, 0x00000000, 0x00000010, 0x205f0000, 0x00000008, 0x2c800000,
+ 0x00000008, 0x2d000000, 0x00000008, 0x2d800108, 0x00000000, 0x00000000,
+ 0x00000010, 0x91de0000, 0x0000000f, 0x47600008, 0x00000000, 0x060e0000,
+ 0x00000010, 0x001f0000, 0x00000000, 0x0f580000, 0x00000010, 0x91de0000,
+ 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000, 0x00000000, 0x0b670000,
+ 0x00000000, 0x0d620000, 0x00000000, 0x0ce71800, 0x00000009, 0x0c99ffff,
+ 0x00000004, 0xcc993400, 0x00000010, 0xb1963220, 0x00000008, 0x0f800000,
+ 0x00000018, 0x8000001e, 0x0000000f, 0x47600008, 0x0000000b, 0x2fdf0002,
+ 0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008, 0x00000010, 0x91d40000,
+ 0x00000008, 0x2d80012c, 0x0000000f, 0x060e0001, 0x00000010, 0x001f0000,
+ 0x00000000, 0x0f580000, 0x00000010, 0x91de0000, 0x00000000, 0x0a640000,
+ 0x00000000, 0x0ae50000, 0x00000000, 0x0b670000, 0x00000000, 0x0d620000,
+ 0x00000000, 0x02630000, 0x0000000f, 0x47620010, 0x00000000, 0x0ce71800,
+ 0x0000000b, 0x2fdf0002, 0x00000000, 0x311a0000, 0x00000000, 0x31840000,
+ 0x0000000b, 0xc20000ff, 0x00000002, 0x42040000, 0x00000001, 0x31620800,
+ 0x0000000f, 0x020e0010, 0x00000002, 0x31620800, 0x00000009, 0x0c99ffff,
+ 0x00000004, 0xcc993400, 0x00000010, 0xb1963202, 0x00000008, 0x0f800000,
+ 0x0000000c, 0x29800001, 0x0000000c, 0x1f800001, 0x0000000c, 0x61420006,
+ 0x00000008, 0x22000008, 0x00000000, 0x2adf0000, 0x00000008, 0x2a000004,
+ 0x00000018, 0x8000ff42, 0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008,
+ 0x00000010, 0x91a0b008, 0x00000010, 0x91d40000, 0x0000000c, 0x31620018,
+ 0x00000008, 0x2d800001, 0x00000000, 0x00000000, 0x00000010, 0x91de0000,
+ 0x00000008, 0xac000001, 0x00000018, 0x8000000e, 0x00000000, 0x0380b000,
+ 0x0000000b, 0x2fdf0002, 0x00000000, 0x2c004000, 0x00000010, 0x91d40000,
+ 0x00000008, 0x2d800101, 0x00000000, 0x00000000, 0x00000010, 0x91de0000,
+ 0x0000000c, 0x31620018, 0x00000008, 0x2d800001, 0x00000000, 0x00000000,
+ 0x00000010, 0x91de0000, 0x0000000b, 0x2fdf0002, 0x00000000, 0x2c000e00,
+ 0x0000000c, 0x29800001, 0x0000000c, 0x1f800001, 0x00000008, 0x2a000007,
+ 0x00000018, 0x8000ff27, 0x00000010, 0xb1a0b016, 0x0000000b, 0x2fdf0002,
+ 0x00000000, 0x03d80000, 0x00000000, 0x2c200000, 0x00000008, 0x2c8000b0,
+ 0x00000008, 0x2d000008, 0x00000010, 0x91d40000, 0x00000008, 0x2d800150,
+ 0x00000000, 0x00000000, 0x00000010, 0x205f0000, 0x00000008, 0x2c800000,
+ 0x00000008, 0x2d000000, 0x00000008, 0x2d800108, 0x00000008, 0x07000001,
+ 0x00000010, 0xb5de1c00, 0x00000010, 0x2c620002, 0x00000018, 0x8000000a,
+ 0x0000000b, 0x2fdf0002, 0x00000000, 0x2c070000, 0x0000000c, 0x1f800001,
+ 0x00000010, 0x91de0000, 0x00000018, 0x8000ff11, 0x00000008, 0x2c8000b0,
+ 0x00000008, 0x2d000008, 0x00000010, 0x91d40000, 0x00000008, 0x2d800108,
+ 0x0000000c, 0x29800001, 0x0000000c, 0x1f800001, 0x00000010, 0x91de0000,
+ 0x00000000, 0x2adf0000, 0x00000008, 0x2a00000a, 0x00000018, 0x8000ff07,
+ 0x00000000, 0x82265600, 0x0000000f, 0x47220008, 0x00000009, 0x070e000f,
+ 0x00000008, 0x070e0008, 0x00000008, 0x02800001, 0x00000007, 0x02851c00,
+ 0x00000008, 0x82850001, 0x00000000, 0x02840a00, 0x00000007, 0x42851c00,
+ 0x00000003, 0xc3aa5200, 0x00000000, 0x03b10e00, 0x00000010, 0x001f0000,
+ 0x0000000f, 0x0f280007, 0x00000007, 0x4b071c00, 0x00000000, 0x00000000,
+ 0x0000000f, 0x0a960003, 0x00000000, 0x0a955c00, 0x00000000, 0x4a005a00,
+ 0x00000000, 0x0c960a00, 0x00000009, 0x0c99ffff, 0x00000008, 0x0d00ffff,
+ 0x00000010, 0xb1963202, 0x00000008, 0x0f800005, 0x00000010, 0x00220020,
+ 0x00000000, 0x02a70000, 0x00000010, 0xb1850002, 0x00000008, 0x82850200,
+ 0x00000000, 0x02000000, 0x00000000, 0x03a60000, 0x00000018, 0x8000004e,
+ 0x00000000, 0x072b0000, 0x00000001, 0x878c1c00, 0x00000000, 0x870e1e00,
+ 0x00000000, 0x860c1e00, 0x00000000, 0x03061e00, 0x00000010, 0xb18e0003,
+ 0x00000018, 0x80000047, 0x00000018, 0x8000fffa, 0x00000010, 0x918c0003,
+ 0x00000010, 0xb1870002, 0x00000018, 0x80000043, 0x00000010, 0x91d40000,
+ 0x0000000c, 0x29800001, 0x00000000, 0x2a860000, 0x00000000, 0x230c0000,
+ 0x00000000, 0x2b070000, 0x00000010, 0xb187000e, 0x00000008, 0x2a000008,
+ 0x00000018, 0x8000003b, 0x00000010, 0x91d40000, 0x00000000, 0x28d18c00,
+ 0x00000000, 0x2a860000, 0x00000000, 0x230c0000, 0x00000000, 0x2b070000,
+ 0x00000018, 0x8000fff8, 0x00000010, 0x91d40000, 0x0000000c, 0x29800001,
+ 0x00000000, 0x2aab0000, 0x00000000, 0xa3265600, 0x00000000, 0x2b000000,
+ 0x0000000c, 0x1f800001, 0x00000008, 0x2a000008, 0x00000018, 0x8000fec8,
+ 0x00000010, 0x91d40000, 0x0000000c, 0x29800001, 0x0000000c, 0x1f800001,
+ 0x00000008, 0x2a000009, 0x00000018, 0x8000fec3, 0x00000010, 0x91d40000,
+ 0x0000000c, 0x29800001, 0x0000000c, 0x1f800001, 0x00000000, 0x29420000,
+ 0x00000008, 0x2a000002, 0x00000018, 0x8000febd, 0x00000018, 0x8000febc,
+ 0x00000010, 0xb1bcb016, 0x0000000b, 0x2fdf0002, 0x00000000, 0x03d80000,
+ 0x00000000, 0x2c3c0000, 0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008,
+ 0x00000010, 0x91d40000, 0x00000008, 0x2d800150, 0x00000000, 0x00000000,
+ 0x00000010, 0x205f0000, 0x00000008, 0x2c800000, 0x00000008, 0x2d000000,
+ 0x00000008, 0x2d800108, 0x00000008, 0x07000001, 0x00000010, 0xb5de1c00,
+ 0x00000010, 0x2c620002, 0x00000018, 0x8000000a, 0x0000000b, 0x2fdf0002,
+ 0x00000000, 0x2c070000, 0x0000000c, 0x1f800000, 0x00000010, 0x91de0000,
+ 0x00000018, 0x8000fea6, 0x00000008, 0x2c8000b0, 0x00000008, 0x2d000008,
+ 0x00000010, 0x91d40000, 0x00000008, 0x2d800108, 0x0000000c, 0x29800000,
+ 0x0000000c, 0x1f800000, 0x00000010, 0x91de0000, 0x00000000, 0x2adf0000,
+ 0x00000008, 0x2a000006, 0x00000018, 0x8000fe9c, 0x00000008, 0x03050004,
+ 0x00000006, 0x83040c00, 0x00000008, 0x02850200, 0x00000000, 0x86050c00,
+ 0x00000001, 0x860c0e00, 0x00000008, 0x02040004, 0x00000000, 0x02041800,
+ 0x00000000, 0x83871800, 0x00000018, 0x00020000 };
+
+static u32 bnx2_rv2p_proc2[] = {
+ 0x00000000, 0x2a000000, 0x00000010, 0xb1d40000, 0x00000008, 0x02540003,
+ 0x00000018, 0x00040000, 0x00000018, 0x8000000a, 0x00000018, 0x8000000a,
+ 0x00000018, 0x8000000e, 0x00000018, 0x80000056, 0x00000018, 0x800001b9,
+ 0x00000018, 0x800001e1, 0x00000018, 0x8000019b, 0x00000018, 0x800001f9,
+ 0x00000018, 0x8000019f, 0x00000018, 0x800001a6, 0x00000018, 0x80000000,
+ 0x0000000c, 0x29800001, 0x00000000, 0x2a000000, 0x0000000c, 0x29800000,
+ 0x00000010, 0x20530000, 0x00000018, 0x8000ffee, 0x0000000c, 0x29800001,
+ 0x00000010, 0x91de0000, 0x00000010, 0x001f0000, 0x00000000, 0x2f80aa00,
+ 0x00000000, 0x2a000000, 0x00000000, 0x0d610000, 0x00000000, 0x03620000,
+ 0x00000000, 0x2c400000, 0x00000000, 0x02638c00, 0x00000000, 0x26460000,
+ 0x00000010, 0x00420002, 0x00000008, 0x02040012, 0x00000010, 0xb9060836,
+ 0x00000000, 0x0f580000, 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000,
+ 0x00000000, 0x0b660000, 0x00000000, 0x0c000000, 0x00000000, 0x0b800000,
+ 0x00000010, 0x00420009, 0x00000008, 0x0cc60012, 0x00000008, 0x0f800003,
+ 0x00000000, 0x00000000, 0x00000010, 0x009f0000, 0x00000008, 0x27110012,
+ 0x00000000, 0x66900000, 0x00000008, 0xa31b0012, 0x00000018, 0x80000008,
+ 0x00000000, 0x0cc60000, 0x00000008, 0x0f800003, 0x00000000, 0x00000000,
+ 0x00000010, 0x009f0000, 0x00000000, 0x27110000, 0x00000000, 0x66900000,
+ 0x00000000, 0x231b0000, 0x00000010, 0xb197320e, 0x00000000, 0x25960000,
+ 0x00000000, 0x021b0000, 0x00000010, 0x001f0000, 0x00000008, 0x0f800003,
+ 0x0000000c, 0x29800000, 0x00000010, 0x20530000, 0x00000000, 0x22c50800,
+ 0x00000010, 0x009f0000, 0x00000000, 0x27002200, 0x00000000, 0x26802000,
+ 0x00000000, 0x231b0000, 0x0000000c, 0x69520001, 0x00000018, 0x8000fff3,
+ 0x00000010, 0x01130002, 0x00000010, 0xb1980003, 0x00000010, 0x001f0000,
+ 0x00000008, 0x0f800004, 0x00000008, 0x22000003, 0x00000008, 0x2c80000c,
+ 0x00000008, 0x2d00000c, 0x00000010, 0x009f0000, 0x00000000, 0x25960000,
+ 0x0000000c, 0x29800000, 0x00000000, 0x32140000, 0x00000000, 0x32950000,
+ 0x00000000, 0x33160000, 0x00000000, 0x31e32e00, 0x00000008, 0x2d800010,
+ 0x00000010, 0x20530000, 0x00000018, 0x8000ffac, 0x00000000, 0x23000000,
+ 0x00000000, 0x25e60000, 0x00000008, 0x2200000b, 0x0000000c, 0x69520000,
+ 0x0000000c, 0x29800000, 0x00000010, 0x20530000, 0x00000018, 0x8000ffa5,
+ 0x0000000c, 0x29800001, 0x00000010, 0x91de0000, 0x00000000, 0x2fd50000,
+ 0x00000010, 0x001f0000, 0x00000000, 0x02700000, 0x00000000, 0x0d620000,
+ 0x00000000, 0xbb630800, 0x00000000, 0x2a000000, 0x00000009, 0x076000ff,
+ 0x0000000f, 0x2c0e0007, 0x00000008, 0x2c800000, 0x00000008, 0x2d000064,
+ 0x00000008, 0x2d80011c, 0x00000009, 0x06420002, 0x0000000c, 0x61420001,
+ 0x00000000, 0x0f400000, 0x00000000, 0x02d08c00, 0x00000000, 0x23000000,
+ 0x00000004, 0x826da000, 0x00000000, 0x8304a000, 0x00000000, 0x22c50c00,
+ 0x00000000, 0x03760000, 0x00000004, 0x83860a00, 0x00000000, 0x83870c00,
+ 0x00000010, 0x91de0000, 0x00000000, 0x037c0000, 0x00000000, 0x837b0c00,
+ 0x00000001, 0x83060e00, 0x00000000, 0x83870c00, 0x00000000, 0x82850e00,
+ 0x00000010, 0xb1860016, 0x0000000f, 0x47610018, 0x00000000, 0x068e0000,
+ 0x0000000f, 0x47670010, 0x0000000f, 0x47e20010, 0x00000000, 0x870e1e00,
+ 0x00000010, 0xb70e1a10, 0x00000010, 0x0ce7000e, 0x00000008, 0x22000009,
+ 0x00000000, 0x286d0000, 0x0000000f, 0x65680010, 0x00000003, 0xf66c9400,
+ 0x00000010, 0xb972a003, 0x0000000c, 0x73e70019, 0x0000000c, 0x21420004,
+ 0x00000018, 0x8000023f, 0x00000000, 0x37ed0000, 0x0000000c, 0x73e7001a,
+ 0x00000010, 0x20530000, 0x00000008, 0x22000008, 0x0000000c, 0x61420004,
+ 0x00000000, 0x02f60000, 0x00000004, 0x82840a00, 0x00000010, 0xb1840a2b,
+ 0x00000010, 0x2d67000a, 0x00000010, 0xb96d0804, 0x00000004, 0xb6ed0a00,
+ 0x00000000, 0x37ed0000, 0x00000018, 0x80000029, 0x0000000c, 0x61420000,
+ 0x00000000, 0x37040000, 0x00000000, 0x37850000, 0x0000000c, 0x33e7001a,
+ 0x00000018, 0x80000024, 0x00000010, 0xb96d0809, 0x00000004, 0xb6ed0a00,
+ 0x00000000, 0x036d0000, 0x00000004, 0xb76e0c00, 0x00000010, 0x91ee0c1f,
+ 0x0000000c, 0x73e7001a, 0x00000004, 0xb6ef0c00, 0x00000000, 0x37ed0000,
+ 0x00000018, 0x8000001b, 0x0000000c, 0x61420000, 0x00000010, 0xb7ee0a05,
+ 0x00000010, 0xb96f0815, 0x00000003, 0xb76e0800, 0x00000004, 0xb7ef0a00,
+ 0x00000018, 0x80000015, 0x00000010, 0x0ce7000c, 0x00000008, 0x22000009,
+ 0x00000000, 0x286d0000, 0x0000000f, 0x65680010, 0x00000003, 0xf66c9400,
+ 0x00000010, 0xb972a003, 0x0000000c, 0x73e70019, 0x0000000c, 0x21420004,
+ 0x00000018, 0x80000215, 0x00000010, 0x20530000, 0x00000008, 0x22000008,
+ 0x0000000c, 0x61420004, 0x00000000, 0x37040000, 0x00000000, 0x37850000,
+ 0x00000000, 0x036d0000, 0x00000003, 0xb8f10c00, 0x00000018, 0x80000004,
+ 0x00000000, 0x02840000, 0x00000002, 0x21421800, 0x0000000c, 0x61420000,
+ 0x00000000, 0x286d0000, 0x0000000f, 0x65ed0010, 0x00000009, 0x266dffff,
+ 0x00000000, 0x23000000, 0x00000010, 0xb1840a3d, 0x00000010, 0x01420002,
+ 0x00000004, 0xb8f10a00, 0x00000003, 0x83760a00, 0x00000010, 0xb8040c39,
+ 0x00000010, 0xb7e6080a, 0x00000000, 0x0a640000, 0x00000000, 0x0ae50000,
+ 0x00000009, 0x0c68ffff, 0x00000009, 0x0b67ffff, 0x00000000, 0x0be60000,
+ 0x00000000, 0x0c840000, 0x00000010, 0xb197320c, 0x00000008, 0x0f800002,
+ 0x00000018, 0x8000000a, 0x00000000, 0x0a6a0000, 0x00000000, 0x0aeb0000,
+ 0x00000000, 0x0c000000, 0x00000009, 0x0b6cffff, 0x00000000, 0x0be90000,
+ 0x00000000, 0x0c840000, 0x00000010, 0xb1973203, 0x00000008, 0x0f800002,
+ 0x00000018, 0x80000001, 0x00000010, 0x001f0000, 0x00000000, 0x0c860000,
+ 0x00000000, 0x06980000, 0x00000008, 0x0f800003, 0x00000000, 0x00000000,
+ 0x00000010, 0x009f0000, 0x00000010, 0xb1973210, 0x00000000, 0x231b0000,
+ 0x00000000, 0x02043600, 0x00000003, 0x8384a000, 0x0000000f, 0x65870010,
+ 0x00000009, 0x2607ffff, 0x00000000, 0x27111a00, 0x00000000, 0x66900000,
+ 0x0000000c, 0x29000000, 0x00000018, 0x800001de, 0x00000000, 0x06980000,
+ 0x00000010, 0x20530000, 0x00000000, 0x22c58c00, 0x00000010, 0x001f0000,
+ 0x00000008, 0x0f800003, 0x00000018, 0x8000fff0, 0x00000000, 0x02043600,
+ 0x00000000, 0x231b0000, 0x00000003, 0x8384a000, 0x0000000f, 0x65870010,
+ 0x00000009, 0x2607ffff, 0x00000000, 0x27111a00, 0x00000000, 0x66900000,
+ 0x0000000c, 0x29000000, 0x00000010, 0x91840a02, 0x00000002, 0x21421800,
+ 0x00000000, 0x32140000, 0x00000000, 0x32950000, 0x00000005, 0x73e72c00,
+ 0x00000005, 0x74683000, 0x00000000, 0x33170000, 0x00000018, 0x80000138,
+ 0x00000010, 0x91c60004, 0x00000008, 0x07000004, 0x00000010, 0xb1c41c02,
+ 0x00000010, 0x91840a04, 0x00000018, 0x800001c3, 0x00000010, 0x20530000,
+ 0x00000000, 0x22c58c00, 0x00000010, 0xb1840a8e, 0x0000000c, 0x21420006,
+ 0x00000010, 0x0ce7001a, 0x0000000f, 0x43680010, 0x00000000, 0x03f30c00,
+ 0x00000010, 0x91870850, 0x0000000f, 0x46ec0010, 0x00000010, 0xb68d0c4e,
+ 0x00000000, 0x838d0c00, 0x00000000, 0xa3050800, 0x00000001, 0xa3460e00,
+ 0x00000000, 0x02048c00, 0x00000010, 0x91840a02, 0x00000002, 0x21421800,
+ 0x00000010, 0x001f0000, 0x00000008, 0x22000008, 0x00000003, 0x8384a000,
+ 0x0000000f, 0x65870010, 0x00000009, 0x2607ffff, 0x00000000, 0x27750c00,
+ 0x00000000, 0x66f40000, 0x0000000c, 0x29000000, 0x00000018, 0x800001aa,
+ 0x00000000, 0x03068c00, 0x00000003, 0xf4680c00, 0x00000010, 0x20530000,
+ 0x00000000, 0x22c58c00, 0x00000018, 0x8000ffe5, 0x00000000, 0x39760000,
+ 0x00000000, 0x39840000, 0x0000000c, 0x33e70019, 0x00000010, 0x001f0000,
+ 0x00000000, 0x031e0000, 0x00000000, 0x0760fe00, 0x0000000f, 0x0f0e0007,
+ 0x00000000, 0x83850800, 0x00000000, 0x0a7d0000, 0x00000000, 0x0afe0000,
+ 0x00000000, 0x0b7f0000, 0x00000000, 0x0d7a0000, 0x00000000, 0x0c000000,
+ 0x00000000, 0x0bfc0000, 0x00000000, 0x0c970e00, 0x00000008, 0x0f800003,
+ 0x0000000f, 0x47670010, 0x00000008, 0x070e0001, 0x0000000b, 0xc38000ff,
+ 0x00000002, 0x43870000, 0x00000001, 0x33e70e00, 0x0000000f, 0x038e0010,
+ 0x00000002, 0x33e70e00, 0x00000000, 0x28f30000, 0x00000010, 0x009f0000,
+ 0x00000000, 0x02043600, 0x00000010, 0x91840a02, 0x00000002, 0x21421800,
+ 0x00000008, 0x22000006, 0x00000000, 0x231b0000, 0x00000000, 0x23ff0000,
+ 0x00000000, 0x241b0000, 0x00000003, 0x8384a000, 0x0000000f, 0x65870010,
+ 0x00000009, 0x2607ffff, 0x00000000, 0x27110000, 0x00000000, 0x26900000,
+ 0x0000000c, 0x29000000, 0x00000018, 0x8000017e, 0x00000003, 0xf4683600,
+ 0x00000000, 0x3a100000, 0x00000000, 0x3a910000, 0x00000003, 0xf66c2400,
+ 0x00000010, 0x001f0000, 0x00000010, 0xb1923604, 0x00000008, 0x0f800004,
+ 0x00000000, 0x00000000, 0x00000010, 0x009f0000, 0x00000000, 0x3e170000,
+ 0x00000000, 0x3e940000, 0x00000000, 0x3f150000, 0x00000000, 0x3f960000,
+ 0x00000010, 0x001f0000, 0x00000000, 0x0f060000, 0x00000010, 0x20530000,
+ 0x00000000, 0x22c53600, 0x00000018, 0x8000ffac, 0x00000010, 0x001f0000,
+ 0x00000000, 0x031e0000, 0x00000000, 0x83850800, 0x00000009, 0x076000ff,
+ 0x0000000f, 0x0f0e0007, 0x00000000, 0x0c000000, 0x00000000, 0x0a7d0000,
+ 0x00000000, 0x0afe0000, 0x00000000, 0x0b7f0000, 0x00000000, 0x0d7a0000,
+ 0x00000000, 0x0bfc0000, 0x00000000, 0x0c970e00, 0x00000008, 0x0f800003,
+ 0x0000000f, 0x47670010, 0x00000008, 0x070e0001, 0x0000000b, 0xc38000ff,
+ 0x00000002, 0x43870000, 0x00000001, 0x33e70e00, 0x0000000f, 0x038e0010,
+ 0x00000002, 0x33e70e00, 0x00000000, 0x39840000, 0x00000003, 0xb9720800,
+ 0x00000000, 0x28f30000, 0x0000000f, 0x65680010, 0x00000010, 0x009f0000,
+ 0x00000000, 0x02043600, 0x00000010, 0x91840a02, 0x00000002, 0x21421800,
+ 0x00000008, 0x22000007, 0x00000000, 0x231b0000, 0x00000000, 0x23ff0000,
+ 0x00000000, 0x241b0000, 0x00000003, 0x8384a000, 0x0000000f, 0x65870010,
+ 0x00000009, 0x2607ffff, 0x00000000, 0x27110000, 0x00000000, 0x26900000,
+ 0x0000000c, 0x29000000, 0x00000018, 0x80000145, 0x00000003, 0xf4683600,
+ 0x00000000, 0x3a100000, 0x00000000, 0x3a910000, 0x00000003, 0xf66c2400,
+ 0x00000010, 0x001f0000, 0x00000010, 0xb1923604, 0x00000008, 0x0f800004,
+ 0x00000000, 0x00000000, 0x00000010, 0x009f0000, 0x00000000, 0x3e170000,
+ 0x00000000, 0x3e940000, 0x00000000, 0x3f150000, 0x00000000, 0x3f960000,
+ 0x00000010, 0x001f0000, 0x00000000, 0x0f060000, 0x00000010, 0x20530000,
+ 0x00000000, 0x22c53600, 0x00000018, 0x8000ff73, 0x00000010, 0x0ce70005,
+ 0x00000008, 0x2c80000c, 0x00000008, 0x2d000070, 0x00000008, 0x2d800010,
+ 0x00000000, 0x00000000, 0x00000010, 0x205f0000, 0x00000018, 0x8000011d,
+ 0x00000000, 0x2c1e0000, 0x00000008, 0x2c8000b8, 0x00000008, 0x2d000010,
+ 0x00000008, 0x2d800048, 0x00000000, 0x00000000, 0x00000010, 0x91de0000,
+ 0x00000018, 0x8000fe5d, 0x0000000c, 0x29800001, 0x00000000, 0x2a000000,
+ 0x00000010, 0x001f0000, 0x00000000, 0x0f008000, 0x00000008, 0x0f800007,
+ 0x00000018, 0x80000006, 0x0000000c, 0x29800001, 0x00000000, 0x2a000000,
+ 0x00000010, 0x001f0000, 0x0000000f, 0x0f470007, 0x00000008, 0x0f800008,
+ 0x00000018, 0x80000119, 0x00000010, 0x20530000, 0x00000018, 0x8000fe4f,
+ 0x0000000c, 0x29800001, 0x00000010, 0x91de0000, 0x00000000, 0x2fd50000,
+ 0x00000000, 0x2a000000, 0x00000009, 0x0261ffff, 0x0000000d, 0x70e10001,
+ 0x00000018, 0x80000101, 0x00000000, 0x2c400000, 0x00000008, 0x2c8000c4,
+ 0x00000008, 0x2d00001c, 0x00000008, 0x2d800001, 0x00000005, 0x70e10800,
+ 0x00000010, 0x91de0000, 0x00000018, 0x8000fe41, 0x0000000c, 0x29800001,
+ 0x00000010, 0x91de0000, 0x00000000, 0x2fd50000, 0x00000010, 0x001f0000,
+ 0x00000000, 0x02700000, 0x00000000, 0x0d620000, 0x00000000, 0xbb630800,
+ 0x00000000, 0x2a000000, 0x00000000, 0x0f400000, 0x00000000, 0x2c400000,
+ 0x0000000c, 0x73e7001b, 0x00000010, 0x0ce7000e, 0x00000000, 0x286d0000,
+ 0x0000000f, 0x65ed0010, 0x00000009, 0x266dffff, 0x00000018, 0x80000069,
+ 0x00000008, 0x02000004, 0x00000010, 0x91c40803, 0x00000018, 0x800000f6,
+ 0x00000010, 0x20530000, 0x00000018, 0x800000e5, 0x00000008, 0x2c8000b8,
+ 0x00000008, 0x2d000010, 0x00000008, 0x2d800048, 0x00000018, 0x80000005,
+ 0x00000008, 0x2c8000c4, 0x00000008, 0x2d00001c, 0x00000008, 0x2d800001,
+ 0x00000000, 0x00000000, 0x00000010, 0x205f0000, 0x00000008, 0x2c800048,
+ 0x00000008, 0x2d000068, 0x00000008, 0x2d800104, 0x00000000, 0x00000000,
+ 0x00000010, 0x91de0000, 0x00000000, 0x27f60000, 0x00000010, 0xb87a9e04,
+ 0x00000008, 0x2200000d, 0x00000018, 0x800000e2, 0x00000010, 0x20530000,
+ 0x00000018, 0x8000fe18, 0x0000000c, 0x29800001, 0x00000010, 0x91de0000,
+ 0x00000000, 0x2fd50000, 0x00000010, 0x001f0000, 0x00000000, 0x02700000,
+ 0x00000000, 0x0d620000, 0x00000000, 0xbb630800, 0x00000000, 0x2a000000,
+ 0x00000010, 0x0e670011, 0x00000000, 0x286d0000, 0x0000000f, 0x65ed0010,
+ 0x00000009, 0x266dffff, 0x00000004, 0xb8f1a000, 0x00000000, 0x0f400000,
+ 0x0000000c, 0x73e7001c, 0x00000018, 0x80000040, 0x00000008, 0x02000004,
+ 0x00000010, 0x91c40802, 0x00000018, 0x800000cd, 0x00000000, 0x2c1e0000,
+ 0x00000008, 0x2c8000b8, 0x00000008, 0x2d000010, 0x00000008, 0x2d800048,
+ 0x00000010, 0x20530000, 0x00000010, 0x91de0000, 0x00000018, 0x8000fdfe,
+ 0x0000000c, 0x29800001, 0x00000000, 0x03550000, 0x00000000, 0x06460000,
+ 0x00000000, 0x03d60000, 0x00000000, 0x2a000000, 0x0000000f, 0x0f480007,
+ 0x00000010, 0xb18c0027, 0x0000000f, 0x47420008, 0x00000009, 0x070e000f,
+ 0x00000008, 0x070e0008, 0x00000010, 0x001f0000, 0x00000008, 0x09000001,
+ 0x00000007, 0x09121c00, 0x00000003, 0xcbca9200, 0x00000000, 0x0b97a200,
+ 0x00000007, 0x4b171c00, 0x0000000f, 0x0a960003, 0x00000000, 0x0a959c00,
+ 0x00000000, 0x4a009a00, 0x00000008, 0x82120001, 0x00000001, 0x0c170800,
+ 0x00000000, 0x02180000, 0x00000000, 0x0c971800, 0x00000008, 0x0d00ffff,
+ 0x00000008, 0x0f800006, 0x0000000c, 0x29000000, 0x00000008, 0x22000001,
+ 0x00000000, 0x22c50c00, 0x00000010, 0x009f0000, 0x00000010, 0xb197320b,
+ 0x00000000, 0x231b0000, 0x00000000, 0x27110800, 0x00000000, 0x66900000,
+ 0x00000018, 0x800000a4, 0x00000000, 0x02180000, 0x00000010, 0x20530000,
+ 0x00000000, 0x22c53600, 0x00000010, 0x001f0000, 0x00000008, 0x0f800006,
+ 0x00000018, 0x8000fff5, 0x00000010, 0x91870002, 0x00000008, 0x2200000a,
+ 0x00000000, 0x231b0000, 0x00000000, 0x27110800, 0x00000000, 0x66900000,
+ 0x00000018, 0x80000098, 0x00000008, 0x0200000a, 0x00000010, 0x91c40804,
+ 0x00000010, 0x02c20003, 0x00000010, 0x001f0000, 0x00000008, 0x0f800008,
+ 0x00000010, 0x20530000, 0x00000018, 0x8000fdc9, 0x00000000, 0x06820000,
+ 0x00000010, 0x001f0000, 0x00000010, 0x0ce70028, 0x00000000, 0x03720000,
+ 0x00000000, 0xa8760c00, 0x00000000, 0x0cf60000, 0x00000010, 0xb8723224,
+ 0x00000000, 0x03440000, 0x00000008, 0x22000010, 0x00000000, 0x03ca0000,
+ 0x0000000f, 0x65680010, 0x00000000, 0x0bcf0000, 0x00000000, 0x27f20000,
+ 0x00000010, 0xb7ef3203, 0x0000000c, 0x21420004, 0x0000000c, 0x73e70019,
+ 0x00000000, 0x07520000, 0x00000000, 0x29000000, 0x00000018, 0x8000007e,
+ 0x00000004, 0xb9723200, 0x00000010, 0x20530000, 0x00000000, 0x22060000,
+ 0x0000000c, 0x61420004, 0x00000000, 0x25070000, 0x00000000, 0x27970000,
+ 0x00000000, 0x290e0000, 0x00000010, 0x0ce70010, 0x00000010, 0xb873320f,
+ 0x0000000f, 0x436c0010, 0x00000000, 0x03f30c00, 0x00000000, 0x03f30000,
+ 0x00000000, 0x83990e00, 0x00000001, 0x83860e00, 0x00000000, 0x83060e00,
+ 0x00000003, 0xf66c0c00, 0x00000000, 0x39f30e00, 0x00000000, 0x3af50e00,
+ 0x00000000, 0x7a740000, 0x0000000f, 0x43680010, 0x00000001, 0x83860e00,
+ 0x00000000, 0x83060e00, 0x00000003, 0xf4680c00, 0x00000000, 0x286d0000,
+ 0x00000000, 0x03690000, 0x00000010, 0xb1f60c54, 0x00000000, 0x0a6a0000,
+ 0x00000000, 0x0aeb0000, 0x00000009, 0x0b6cffff, 0x00000000, 0x0c000000,
+ 0x00000000, 0x0be90000, 0x00000003, 0x8cf6a000, 0x0000000c, 0x09800002,
+ 0x00000010, 0x009f0000, 0x00000010, 0xb8173209, 0x00000000, 0x35140000,
+ 0x00000000, 0x35950000, 0x00000005, 0x766c2c00, 0x00000000, 0x34970000,
+ 0x00000004, 0xb8f12e00, 0x00000010, 0x001f0000, 0x00000008, 0x0f800004,
+ 0x00000018, 0x8000fff7, 0x00000000, 0x03e90000, 0x00000010, 0xb8f6a01a,
+ 0x00000010, 0x20130019, 0x00000010, 0xb1f10e18, 0x00000000, 0x83973200,
+ 0x00000000, 0x38700e00, 0x00000000, 0xbb760e00, 0x00000000, 0x37d00000,
+ 0x0000000c, 0x73e7001a, 0x00000003, 0xb8f1a000, 0x00000000, 0x32140000,
+ 0x00000000, 0x32950000, 0x00000005, 0x73e72c00, 0x00000000, 0x33190000,
+ 0x00000005, 0x74680000, 0x00000010, 0x0ce7000d, 0x00000008, 0x22000009,
+ 0x00000000, 0x07520000, 0x00000000, 0x29000000, 0x0000000c, 0x73e70019,
+ 0x0000000f, 0x65680010, 0x0000000c, 0x21420004, 0x00000018, 0x8000003c,
+ 0x00000010, 0x20530000, 0x0000000c, 0x61420004, 0x00000000, 0x290e0000,
+ 0x00000018, 0x80000002, 0x00000010, 0x91973206, 0x00000000, 0x35140000,
+ 0x00000000, 0x35950000, 0x00000005, 0x766c2c00, 0x00000000, 0x34990000,
+ 0x00000004, 0xb8f13200, 0x00000000, 0x83690c00, 0x00000010, 0xb1860013,
+ 0x00000000, 0x28e90000, 0x00000008, 0x22000004, 0x00000000, 0x23ec0000,
+ 0x00000000, 0x03690000, 0x00000010, 0xb8660c07, 0x00000009, 0x036cffff,
+ 0x00000000, 0x326a0000, 0x00000000, 0x32eb0000, 0x00000005, 0x73e70c00,
+ 0x00000000, 0x33690000, 0x00000005, 0x74680000, 0x0000000c, 0x73e7001c,
+ 0x00000000, 0x03690000, 0x00000010, 0xb1f60c12, 0x00000010, 0xb1d00c11,
+ 0x0000000c, 0x21420005, 0x0000000c, 0x33e7001c, 0x00000018, 0x8000000e,
+ 0x00000010, 0x2e67000d, 0x00000000, 0x03690000, 0x00000010, 0xb1f60c0b,
+ 0x00000010, 0xb1d00c0a, 0x00000000, 0x03440000, 0x00000008, 0x2200000c,
+ 0x00000000, 0x07520000, 0x00000000, 0x29000000, 0x00000018, 0x80000015,
+ 0x0000000c, 0x33e7001c, 0x00000010, 0x20530000, 0x00000000, 0x22060000,
+ 0x00000000, 0x290e0000, 0x00000018, 0x000d0000, 0x00000000, 0x06820000,
+ 0x00000010, 0x2de7000d, 0x00000010, 0x0ce7000c, 0x00000000, 0x27f20000,
+ 0x00000010, 0xb96d9e0a, 0x00000000, 0xa86d9e00, 0x00000009, 0x0361ffff,
+ 0x00000010, 0xb7500c07, 0x00000008, 0x2200000f, 0x0000000f, 0x65680010,
+ 0x00000000, 0x29000000, 0x00000018, 0x80000004, 0x0000000c, 0x33e7001b,
+ 0x00000010, 0x20530000, 0x00000018, 0x000d0000, 0x00000000, 0x2b820000,
+ 0x00000010, 0x20d2002f, 0x00000010, 0x0052002e, 0x00000009, 0x054e0007,
+ 0x00000010, 0xb18a002c, 0x00000000, 0x050a8c00, 0x00000008, 0x850a0008,
+ 0x00000010, 0x918a0029, 0x00000003, 0xc5008800, 0x00000008, 0xa3460001,
+ 0x00000010, 0xb1c60007, 0x00000008, 0x22000001, 0x0000000c, 0x29800000,
+ 0x00000010, 0x20530000, 0x00000000, 0x274e8c00, 0x00000000, 0x66cd0000,
+ 0x00000000, 0x22c58c00, 0x00000008, 0x22000014, 0x00000003, 0x22c58e00,
+ 0x00000003, 0x23c58e00, 0x00000003, 0x22c58e00, 0x00000003, 0x26cd9e00,
+ 0x00000003, 0x27cd9e00, 0x00000003, 0x26cd9e00, 0x00000003, 0x274ea000,
+ 0x00000003, 0x284ea000, 0x00000003, 0x274ea000, 0x0000000c, 0x69520000,
+ 0x0000000c, 0x29800000, 0x00000010, 0x20530000, 0x00000003, 0x22c58e00,
+ 0x00000003, 0x23c58e00, 0x00000003, 0x22c58e00, 0x00000003, 0x26cd9e00,
+ 0x00000003, 0x27cd9e00, 0x00000003, 0x26cd9e00, 0x00000003, 0x274ea000,
+ 0x00000003, 0x284ea000, 0x00000003, 0x274ea000, 0x00000000, 0xa2c58c00,
+ 0x00000000, 0xa74e8c00, 0x00000000, 0xe6cd0000, 0x0000000f, 0x620a0010,
+ 0x00000008, 0x23460001, 0x0000000c, 0x29800000, 0x00000010, 0x20530000,
+ 0x0000000c, 0x29520000, 0x00000018, 0x80000002, 0x0000000c, 0x29800000,
+ 0x00000018, 0x00570000 };
+
+static int bnx2_TPAT_b06FwReleaseMajor = 0x0;
+static int bnx2_TPAT_b06FwReleaseMinor = 0x0;
+static int bnx2_TPAT_b06FwReleaseFix = 0x0;
+static u32 bnx2_TPAT_b06FwStartAddr = 0x08000858;
+static u32 bnx2_TPAT_b06FwTextAddr = 0x08000800;
+static int bnx2_TPAT_b06FwTextLen = 0x1314;
+static u32 bnx2_TPAT_b06FwDataAddr = 0x08001b40;
+static int bnx2_TPAT_b06FwDataLen = 0x0;
+static u32 bnx2_TPAT_b06FwRodataAddr = 0x00000000;
+static int bnx2_TPAT_b06FwRodataLen = 0x0;
+static u32 bnx2_TPAT_b06FwBssAddr = 0x08001b90;
+static int bnx2_TPAT_b06FwBssLen = 0x80;
+static u32 bnx2_TPAT_b06FwSbssAddr = 0x08001b40;
+static int bnx2_TPAT_b06FwSbssLen = 0x48;
+
+static u32 bnx2_TPAT_b06FwText[(0x1314/4) + 1] = {
+ 0x0a000216, 0x00000000, 0x00000000, 0x0000000d, 0x74706174, 0x20302e36,
+ 0x2e390000, 0x00060901, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x10000003,
+ 0x00000000, 0x0000000d, 0x0000000d, 0x3c020800, 0x24421b40, 0x3c030800,
+ 0x24631c10, 0xac400000, 0x0043202b, 0x1480fffd, 0x24420004, 0x3c1d0800,
+ 0x37bd3ffc, 0x03a0f021, 0x3c100800, 0x26100858, 0x3c1c0800, 0x279c1b40,
+ 0x0e00051f, 0x00000000, 0x0000000d, 0x8f820024, 0x27bdffe8, 0xafbf0014,
+ 0x10400004, 0xafb00010, 0x0000000d, 0x00000000, 0x2400015f, 0x8f82001c,
+ 0x8c450008, 0x24030800, 0xaf430178, 0x97430104, 0x3c020008, 0xaf420140,
+ 0x8f820034, 0x30420001, 0x10400006, 0x3070ffff, 0x24020002, 0x2603fffe,
+ 0xa7420146, 0x0a000246, 0xa7430148, 0xa7400146, 0x8f850034, 0x30a20020,
+ 0x0002102b, 0x00021023, 0x30460009, 0x30a30c00, 0x24020400, 0x14620002,
+ 0x34c40001, 0x34c40005, 0xa744014a, 0x3c020800, 0x8c440820, 0x3c030048,
+ 0x24020002, 0x00832025, 0x30a30006, 0x1062000d, 0x2c620003, 0x50400005,
+ 0x24020004, 0x10600012, 0x3c020001, 0x0a000271, 0x00000000, 0x10620007,
+ 0x24020006, 0x1462000f, 0x3c020111, 0x0a000269, 0x00821025, 0x0a000268,
+ 0x3c020101, 0x3c020011, 0x00821025, 0x24030001, 0xaf421000, 0xaf830030,
+ 0x0a000271, 0x00000000, 0x00821025, 0xaf421000, 0xaf800030, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x8f830030, 0x1060003f, 0x3c048000,
+ 0x8f421000, 0x00441024, 0x1040fffd, 0x00000000, 0x10600039, 0x00000000,
+ 0x8f421000, 0x3c030020, 0x00431024, 0x10400034, 0x00000000, 0x97421014,
+ 0x14400031, 0x00000000, 0x97421008, 0x8f84001c, 0x24420006, 0x00024082,
+ 0x00081880, 0x00643821, 0x8ce50000, 0x30430003, 0x30420001, 0x10400004,
+ 0x00000000, 0x0000000d, 0x0a0002b0, 0x00081080, 0x5460000f, 0x30a5ffff,
+ 0x3c06ffff, 0x00a62824, 0x0005182b, 0x00a61026, 0x0002102b, 0x00621824,
+ 0x10600004, 0x00000000, 0x0000000d, 0x00000000, 0x240001fc, 0x8ce20000,
+ 0x0a0002af, 0x00462825, 0x0005182b, 0x38a2ffff, 0x0002102b, 0x00621824,
+ 0x10600004, 0x00000000, 0x0000000d, 0x00000000, 0x24000206, 0x8ce20000,
+ 0x3445ffff, 0x00081080, 0x00441021, 0x3c030800, 0xac450000, 0x8c620840,
+ 0x24420001, 0xac620840, 0x8f820008, 0x10400003, 0x00000000, 0x0e000660,
+ 0x00000000, 0x8f840028, 0x02002821, 0x24820008, 0x30421fff, 0x24434000,
+ 0x0343d821, 0x30a30007, 0xaf840018, 0xaf820028, 0xaf420084, 0x10600002,
+ 0x24a20007, 0x3045fff8, 0x8f820044, 0x8f840004, 0x00451821, 0xaf82002c,
+ 0x0064102b, 0xaf830044, 0x14400002, 0x00641023, 0xaf820044, 0x8f840044,
+ 0x34028000, 0x8fbf0014, 0x8fb00010, 0x00821021, 0x03421821, 0x3c021000,
+ 0xaf83001c, 0xaf440080, 0xaf420178, 0x03e00008, 0x27bd0018, 0x8f820024,
+ 0x27bdffe8, 0xafbf0014, 0x10400004, 0xafb00010, 0x0000000d, 0x00000000,
+ 0x24000249, 0x8f85001c, 0x24020001, 0xaf820024, 0x8ca70008, 0xa3800023,
+ 0x8f620004, 0x3c100800, 0x26041b90, 0x00021402, 0xa3820010, 0x304600ff,
+ 0x24c60005, 0x0e00064a, 0x00063082, 0x8f640004, 0x8f430108, 0x3c021000,
+ 0x00621824, 0xa7840020, 0x10600008, 0x00000000, 0x97420104, 0x93830023,
+ 0x2442ffec, 0x34630002, 0xa3830023, 0x0a000304, 0x3045ffff, 0x97420104,
+ 0x2442fff0, 0x3045ffff, 0x8f620004, 0x3042ffff, 0x2c420013, 0x14400004,
+ 0x00000000, 0x93820023, 0x34420001, 0xa3820023, 0x93830023, 0x24020001,
+ 0x10620009, 0x28620002, 0x14400014, 0x24020002, 0x10620012, 0x24020003,
+ 0x1062000a, 0x00000000, 0x0a000325, 0x00000000, 0x8f82001c, 0x8c43000c,
+ 0x3c04ffff, 0x00641824, 0x00651825, 0x0a000325, 0xac43000c, 0x8f82001c,
+ 0x8c430010, 0x3c04ffff, 0x00641824, 0x00651825, 0xac430010, 0x8f620004,
+ 0x3042ffff, 0x24420002, 0x00021083, 0xa3820038, 0x304500ff, 0x8f82001c,
+ 0x3c04ffff, 0x00052880, 0x00a22821, 0x8ca70000, 0x97820020, 0x97430104,
+ 0x00e42024, 0x24420002, 0x00621823, 0x00833825, 0xaca70000, 0x93840038,
+ 0x26061b90, 0x00041080, 0x00461021, 0x90430000, 0x3063000f, 0x00832021,
+ 0xa3840022, 0x308200ff, 0x3c04fff6, 0x24420003, 0x00021080, 0x00461021,
+ 0x8c450000, 0x93830022, 0x8f82001c, 0x3484ffff, 0x00a43824, 0x00031880,
+ 0x00621821, 0xaf850000, 0xac67000c, 0x93820022, 0x93830022, 0x8f84001c,
+ 0x24420003, 0x00021080, 0x00461021, 0x24630004, 0x00031880, 0xac470000,
+ 0x93820022, 0x00661821, 0x94670002, 0x00021080, 0x00441021, 0xac670000,
+ 0x24030010, 0xac470010, 0xa7430140, 0x24030002, 0xa7400142, 0xa7400144,
+ 0xa7430146, 0x97420104, 0x8f840034, 0x24030001, 0x2442fffe, 0x30840006,
+ 0xa7420148, 0x24020002, 0xa743014a, 0x1082000d, 0x2c820003, 0x10400005,
+ 0x24020004, 0x10800011, 0x3c020009, 0x0a000383, 0x00000000, 0x10820007,
+ 0x24020006, 0x1482000d, 0x3c020119, 0x0a00037d, 0x24030001, 0x0a00037c,
+ 0x3c020109, 0x3c020019, 0x24030001, 0xaf421000, 0xaf830030, 0x0a000383,
+ 0x00000000, 0xaf421000, 0xaf800030, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x93820010, 0x24030008, 0x8f840030, 0x24420002, 0x30420007,
+ 0x00621823, 0x30630007, 0xaf83000c, 0x10800005, 0x3c038000, 0x8f421000,
+ 0x00431024, 0x1040fffd, 0x00000000, 0x8f820028, 0xaf820018, 0x24420010,
+ 0x30421fff, 0xaf820028, 0xaf420084, 0x97430104, 0x24424000, 0x0342d821,
+ 0x3063ffff, 0x30620007, 0x10400002, 0x24620007, 0x3043fff8, 0x8f820044,
+ 0x8f840004, 0x00431821, 0xaf82002c, 0x0064102b, 0xaf830044, 0x14400002,
+ 0x00641023, 0xaf820044, 0x8f840044, 0x34028000, 0x8fbf0014, 0x8fb00010,
+ 0x00821021, 0x03421821, 0x3c021000, 0xaf83001c, 0xaf440080, 0xaf420178,
+ 0x03e00008, 0x27bd0018, 0x8f820024, 0x27bdffe8, 0xafbf0014, 0x14400004,
+ 0xafb00010, 0x0000000d, 0x00000000, 0x240002db, 0x8f620004, 0x04410009,
+ 0x3c050800, 0x93820022, 0x8f830000, 0x24a41b90, 0xaf800024, 0x24420003,
+ 0x00021080, 0x00441021, 0xac430000, 0x93820038, 0x24a51b90, 0x93860010,
+ 0x3c040001, 0x27700008, 0x24420001, 0x00021080, 0x00451021, 0x8c430000,
+ 0x24c60005, 0x00063082, 0x00641821, 0x02002021, 0x0e00064a, 0xac430000,
+ 0x93840022, 0x3c057fff, 0x8f620004, 0x00042080, 0x00902021, 0x8c830004,
+ 0x34a5ffff, 0x00451024, 0x00621821, 0xac830004, 0x93850038, 0x3c07ffff,
+ 0x93840010, 0x00052880, 0x00b02821, 0x8ca30000, 0x97420104, 0x97860020,
+ 0x00671824, 0x00441021, 0x00461023, 0x3042ffff, 0x00621825, 0xaca30000,
+ 0x93830023, 0x24020001, 0x10620009, 0x28620002, 0x1440001a, 0x24020002,
+ 0x10620018, 0x24020003, 0x1062000d, 0x00000000, 0x0a000411, 0x00000000,
+ 0x93820010, 0x97430104, 0x8e04000c, 0x00621821, 0x2463fff2, 0x3063ffff,
+ 0x00872024, 0x00832025, 0x0a000411, 0xae04000c, 0x93820010, 0x97430104,
+ 0x8e040010, 0x00621821, 0x2463ffee, 0x3063ffff, 0x00872024, 0x00832025,
+ 0xae040010, 0x9783000e, 0x8f840034, 0x2402000a, 0xa7420140, 0xa7430142,
+ 0x93820010, 0xa7420144, 0xa7400146, 0x97430104, 0x30840006, 0x24020001,
+ 0xa7430148, 0xa742014a, 0x24020002, 0x1082000d, 0x2c820003, 0x10400005,
+ 0x24020004, 0x10800011, 0x3c020041, 0x0a000437, 0x00000000, 0x10820007,
+ 0x24020006, 0x1482000d, 0x3c020151, 0x0a000431, 0x24030001, 0x0a000430,
+ 0x3c020141, 0x3c020051, 0x24030001, 0xaf421000, 0xaf830030, 0x0a000437,
+ 0x00000000, 0xaf421000, 0xaf800030, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x8f820030, 0x93840010, 0x8f850028, 0x10400005, 0x3c038000,
+ 0x8f421000, 0x00431024, 0x1040fffd, 0x00000000, 0x2483000a, 0x30620007,
+ 0x10400002, 0x24620007, 0x304303f8, 0x00a31021, 0x30421fff, 0xaf850018,
+ 0xaf820028, 0xaf420084, 0x97430104, 0x24424000, 0x0342d821, 0x3063ffff,
+ 0x30620007, 0x10400002, 0x24620007, 0x3043fff8, 0x8f820044, 0x8f840004,
+ 0x00431821, 0xaf82002c, 0x0064102b, 0xaf830044, 0x14400002, 0x00641023,
+ 0xaf820044, 0x8f840044, 0x34028000, 0x8fbf0014, 0x8fb00010, 0x00821021,
+ 0x03421821, 0x3c021000, 0xaf83001c, 0xaf440080, 0xaf420178, 0x03e00008,
+ 0x27bd0018, 0x3c026000, 0x8c444448, 0x3c030800, 0xac64082c, 0x8f620000,
+ 0x97430104, 0x3c048000, 0x3046ffff, 0x3067ffff, 0x8f420178, 0x00441024,
+ 0x1440fffd, 0x2402000a, 0x30c30007, 0xa7420140, 0x24020008, 0x00431023,
+ 0x30420007, 0x24c3fffe, 0xa7420142, 0xa7430144, 0xa7400146, 0xa7470148,
+ 0x8f420108, 0x3c036000, 0x8f850034, 0x30420020, 0x0002102b, 0x00021023,
+ 0x30420009, 0x34420001, 0xa742014a, 0x8c644448, 0x3c020800, 0x30a50006,
+ 0xac440830, 0x24020002, 0x10a2000d, 0x2ca20003, 0x10400005, 0x24020004,
+ 0x10a00011, 0x3c020041, 0x0a0004a8, 0x00000000, 0x10a20007, 0x24020006,
+ 0x14a2000d, 0x3c020151, 0x0a0004a2, 0x24030001, 0x0a0004a1, 0x3c020141,
+ 0x3c020051, 0x24030001, 0xaf421000, 0xaf830030, 0x0a0004a8, 0x00000000,
+ 0xaf421000, 0xaf800030, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x8f820030, 0x24c30008, 0x10400006, 0x30e6ffff, 0x3c048000, 0x8f421000,
+ 0x00441024, 0x1040fffd, 0x00000000, 0x3c026000, 0x8c444448, 0x3065ffff,
+ 0x3c020800, 0x30a30007, 0x10600003, 0xac440834, 0x24a20007, 0x3045fff8,
+ 0x8f840028, 0x00851021, 0x30421fff, 0x24434000, 0x0343d821, 0x30c30007,
+ 0xaf840018, 0xaf820028, 0xaf420084, 0x10600002, 0x24c20007, 0x3046fff8,
+ 0x8f820044, 0x8f840004, 0x00461821, 0xaf82002c, 0x0064102b, 0xaf830044,
+ 0x14400002, 0x00641023, 0xaf820044, 0x8f840044, 0x34028000, 0x3c030800,
+ 0x8c650844, 0x00821021, 0x03421821, 0xaf83001c, 0xaf440080, 0x10a00006,
+ 0x2402000e, 0x93830043, 0x14620004, 0x3c021000, 0x2402043f, 0xa7420148,
+ 0x3c021000, 0x3c036000, 0xaf420178, 0x8c644448, 0x3c020800, 0x03e00008,
+ 0xac440838, 0x8f820034, 0x30424000, 0x10400005, 0x24020800, 0x0000000d,
+ 0x00000000, 0x24000405, 0x24020800, 0xaf420178, 0x97440104, 0x3c030008,
+ 0xaf430140, 0x8f820034, 0x30420001, 0x10400006, 0x3085ffff, 0x24020002,
+ 0x24a3fffe, 0xa7420146, 0x0a0004ff, 0xa7430148, 0xa7400146, 0x8f840028,
+ 0x2402000d, 0xa742014a, 0x24830008, 0x30631fff, 0x24624000, 0x0342d821,
+ 0x30a20007, 0xaf840018, 0xaf830028, 0xaf430084, 0x10400002, 0x24a20007,
+ 0x3045fff8, 0x8f820044, 0x8f840004, 0x00451821, 0xaf82002c, 0x0064102b,
+ 0xaf830044, 0x14400002, 0x00641023, 0xaf820044, 0x8f840044, 0x34028000,
+ 0x00821021, 0x03421821, 0x3c021000, 0xaf83001c, 0xaf440080, 0x03e00008,
+ 0xaf420178, 0x27bdffe8, 0x3c046008, 0xafbf0014, 0xafb00010, 0x8c825000,
+ 0x3c1a8000, 0x2403ff7f, 0x375b4000, 0x00431024, 0x3442380c, 0xac825000,
+ 0x8f430008, 0x3c100800, 0x37428000, 0x34630001, 0xaf430008, 0xaf82001c,
+ 0x3c02601c, 0xaf800028, 0xaf400080, 0xaf400084, 0x8c450008, 0x3c036000,
+ 0x8c620808, 0x3c040800, 0x3c030080, 0xac830820, 0x3042fff0, 0x38420010,
+ 0x2c420001, 0xaf850004, 0xaf820008, 0x0e00062f, 0x00000000, 0x8f420000,
+ 0x30420001, 0x1040fffb, 0x00000000, 0x8f440108, 0x30822000, 0xaf840034,
+ 0x10400004, 0x8e02083c, 0x24420001, 0x0a00059d, 0xae02083c, 0x30820200,
+ 0x10400027, 0x00000000, 0x97420104, 0x1040001c, 0x30824000, 0x14400005,
+ 0x00000000, 0x0e00022d, 0x00000000, 0x0a000592, 0x00000000, 0x8f620008,
+ 0x8f630000, 0x24020030, 0x00031e02, 0x306300f0, 0x10620007, 0x28620031,
+ 0x14400031, 0x24020040, 0x10620007, 0x00000000, 0x0a000592, 0x00000000,
+ 0x0e0002dd, 0x00000000, 0x0a000592, 0x00000000, 0x0e0003b8, 0x00000000,
+ 0x0a000592, 0x00000000, 0x30820040, 0x1440002d, 0x00000000, 0x0000000d,
+ 0x00000000, 0x240004a6, 0x0a00059d, 0x00000000, 0x8f430100, 0x24020d00,
+ 0x1462000f, 0x30820006, 0x97420104, 0x10400005, 0x30820040, 0x0e0004e9,
+ 0x00000000, 0x0a000592, 0x00000000, 0x1440001b, 0x00000000, 0x0000000d,
+ 0x00000000, 0x240004b8, 0x0a00059d, 0x00000000, 0x1040000e, 0x30821000,
+ 0x10400005, 0x00000000, 0x0e00065d, 0x00000000, 0x0a000592, 0x00000000,
+ 0x0e00046b, 0x00000000, 0x8f820040, 0x24420001, 0xaf820040, 0x0a00059d,
+ 0x00000000, 0x30820040, 0x14400004, 0x00000000, 0x0000000d, 0x00000000,
+ 0x240004cf, 0x8f420138, 0x3c034000, 0x00431025, 0xaf420138, 0x0a00053f,
+ 0x00000000, 0x3c046008, 0x8c835000, 0x3c1a8000, 0x2402ff7f, 0x375b4000,
+ 0x00621824, 0x3463380c, 0xac835000, 0x8f420008, 0x3c056000, 0x3c03601c,
+ 0x34420001, 0xaf420008, 0x37428000, 0xaf800028, 0xaf82001c, 0xaf400080,
+ 0xaf400084, 0x8c660008, 0x8ca20808, 0x3c040800, 0x3c030080, 0xac830820,
+ 0x3042fff0, 0x38420010, 0x2c420001, 0xaf860004, 0xaf820008, 0x03e00008,
+ 0x00000000, 0x3084ffff, 0x30820007, 0x10400002, 0x24820007, 0x3044fff8,
+ 0x8f820028, 0x00441821, 0x30631fff, 0x24644000, 0x0344d821, 0xaf820018,
+ 0xaf830028, 0x03e00008, 0xaf430084, 0x3084ffff, 0x30820007, 0x10400002,
+ 0x24820007, 0x3044fff8, 0x8f820044, 0x8f830004, 0x00442021, 0xaf82002c,
+ 0x0083102b, 0xaf840044, 0x14400002, 0x00831023, 0xaf820044, 0x8f820044,
+ 0x34038000, 0x00431821, 0x03432021, 0xaf84001c, 0x03e00008, 0xaf420080,
+ 0x8f830034, 0x24020002, 0x30630006, 0x1062000d, 0x2c620003, 0x50400005,
+ 0x24020004, 0x10600012, 0x3c020001, 0x0a000601, 0x00000000, 0x10620007,
+ 0x24020006, 0x1462000f, 0x3c020111, 0x0a0005f9, 0x00821025, 0x0a0005f8,
+ 0x3c020101, 0x3c020011, 0x00821025, 0x24030001, 0xaf421000, 0xaf830030,
+ 0x0a000601, 0x00000000, 0x00821025, 0xaf421000, 0xaf800030, 0x00000000,
+ 0x00000000, 0x00000000, 0x03e00008, 0x00000000, 0x8f820030, 0x10400005,
+ 0x3c038000, 0x8f421000, 0x00431024, 0x1040fffd, 0x00000000, 0x03e00008,
+ 0x00000000, 0x8f820034, 0x27bdffe8, 0x30424000, 0x14400005, 0xafbf0010,
+ 0x0e00022d, 0x00000000, 0x0a00062d, 0x8fbf0010, 0x8f620008, 0x8f630000,
+ 0x24020030, 0x00031e02, 0x306300f0, 0x10620008, 0x28620031, 0x1440000d,
+ 0x8fbf0010, 0x24020040, 0x10620007, 0x00000000, 0x0a00062d, 0x00000000,
+ 0x0e0002dd, 0x00000000, 0x0a00062d, 0x8fbf0010, 0x0e0003b8, 0x00000000,
+ 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x8f84003c, 0x1080000f, 0x3c026000,
+ 0x8c430c3c, 0x30630fff, 0xaf830014, 0x14600011, 0x3082000f, 0x10400005,
+ 0x308200f0, 0x10400003, 0x30820f00, 0x14400006, 0x00000000, 0x0000000d,
+ 0x00000000, 0x2400050e, 0x03e00008, 0x00000000, 0x0000000d, 0x00000000,
+ 0x24000513, 0x03e00008, 0x00000000, 0xaf83003c, 0x03e00008, 0x00000000,
+ 0x10c00007, 0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004, 0xac820000,
+ 0x14c0fffb, 0x24840004, 0x03e00008, 0x00000000, 0x0a000659, 0x00a01021,
+ 0xac860000, 0x24840004, 0x00a01021, 0x1440fffc, 0x24a5ffff, 0x03e00008,
+ 0x00000000, 0x0000000d, 0x03e00008, 0x00000000, 0x3c040800, 0x8c82084c,
+ 0x54400007, 0xac80084c, 0x8f820034, 0x24030400, 0x30420c00, 0x1443005b,
+ 0x00000000, 0xac80084c, 0x0000000d, 0x00000000, 0x2400003c, 0x3c026000,
+ 0x8c444448, 0x3c030800, 0xac640850, 0x24000043, 0x97420104, 0x3045ffff,
+ 0x000530c2, 0x24a2007f, 0x000239c2, 0x2400004e, 0x3c046020, 0x24030020,
+ 0xac830000, 0x8c820000, 0x30420020, 0x10400005, 0x3c036020, 0x8c620000,
+ 0x30420020, 0x1440fffd, 0x00000000, 0x3c026020, 0x8c430010, 0x24040001,
+ 0x0087102b, 0x30ea007f, 0x24abfffe, 0x10400010, 0x00034240, 0x3c056020,
+ 0x24090020, 0xaca90000, 0x8ca20000, 0x30420020, 0x10400006, 0x24840001,
+ 0x3c036020, 0x8c620000, 0x30420020, 0x1440fffd, 0x00000000, 0x0087102b,
+ 0x1440fff4, 0x00000000, 0x8f85001c, 0x3c026020, 0x8c430010, 0x3c046020,
+ 0x34848000, 0x006a1825, 0x01034025, 0x2400006b, 0x10c0000b, 0x00000000,
+ 0x8ca30000, 0x24a50004, 0x8ca20000, 0x24a50004, 0x24c6ffff, 0xac820000,
+ 0x24840004, 0xac830000, 0x14c0fff7, 0x24840004, 0x24000077, 0x3c020007,
+ 0x34427700, 0x3c036000, 0xac6223c8, 0xac6b23cc, 0xac6823e4, 0x24000086,
+ 0x3c046000, 0x3c038000, 0x8c8223f8, 0x00431024, 0x1440fffd, 0x3c021000,
+ 0x3c056000, 0x24030019, 0xaca223f8, 0xa743014a, 0x8ca44448, 0x3c020800,
+ 0xac440854, 0x03e00008, 0x00000000, 0x00000000 };
+
+static u32 bnx2_TPAT_b06FwData[(0x0/4) + 1] = { 0x00000000 };
+static u32 bnx2_TPAT_b06FwRodata[(0x0/4) + 1] = { 0x00000000 };
+static u32 bnx2_TPAT_b06FwBss[(0x80/4) + 1] = { 0x00000000 };
+static u32 bnx2_TPAT_b06FwSbss[(0x48/4) + 1] = { 0x00000000 };
+
+static int bnx2_TXP_b06FwReleaseMajor = 0x0;
+static int bnx2_TXP_b06FwReleaseMinor = 0x0;
+static int bnx2_TXP_b06FwReleaseFix = 0x0;
+static u32 bnx2_TXP_b06FwStartAddr = 0x08002090;
+static u32 bnx2_TXP_b06FwTextAddr = 0x08000000;
+static int bnx2_TXP_b06FwTextLen = 0x3ffc;
+static u32 bnx2_TXP_b06FwDataAddr = 0x08004020;
+static int bnx2_TXP_b06FwDataLen = 0x0;
+static u32 bnx2_TXP_b06FwRodataAddr = 0x00000000;
+static int bnx2_TXP_b06FwRodataLen = 0x0;
+static u32 bnx2_TXP_b06FwBssAddr = 0x08004060;
+static int bnx2_TXP_b06FwBssLen = 0x194;
+static u32 bnx2_TXP_b06FwSbssAddr = 0x08004020;
+static int bnx2_TXP_b06FwSbssLen = 0x34;
+static u32 bnx2_TXP_b06FwText[(0x3ffc/4) + 1] = {
+ 0x0a000824, 0x00000000, 0x00000000, 0x0000000d, 0x74787020, 0x302e362e,
+ 0x39000000, 0x00060900, 0x0000000a, 0x000003e8, 0x0000ea60, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x10000003, 0x00000000, 0x0000000d,
+ 0x0000000d, 0x3c020800, 0x24424020, 0x3c030800, 0x246341f4, 0xac400000,
+ 0x0043202b, 0x1480fffd, 0x24420004, 0x3c1d0800, 0x37bd7ffc, 0x03a0f021,
+ 0x3c100800, 0x26102090, 0x3c1c0800, 0x279c4020, 0x0e000a0e, 0x00000000,
+ 0x0000000d, 0x8f840014, 0x27bdffe8, 0xafb00010, 0x8f460104, 0x8f830008,
+ 0x8c8500ac, 0xaf430080, 0x948200a8, 0xa7420e10, 0x948300aa, 0xa7430e12,
+ 0x8c8200ac, 0xaf420e18, 0x97430e10, 0xa7430e14, 0x97420e12, 0xa7420e16,
+ 0x8f430e18, 0x00005021, 0x00c53023, 0x10c001a3, 0xaf430e1c, 0x240f0800,
+ 0x3c0e1000, 0x2419fff8, 0x24100010, 0x3c188100, 0x93620008, 0x10400009,
+ 0x00000000, 0x97620010, 0x00c2102b, 0x14400005, 0x00000000, 0x97620010,
+ 0x3042ffff, 0x0a000862, 0xaf420e00, 0xaf460e00, 0x8f420000, 0x30420008,
+ 0x1040fffd, 0x00000000, 0x97420e08, 0x8f450e04, 0x3044ffff, 0x30820001,
+ 0x14400005, 0x00000000, 0x14a00005, 0x3083a040, 0x0a0009e6, 0x00000000,
+ 0x0000000d, 0x3083a040, 0x24020040, 0x14620049, 0x3082a000, 0x8f87000c,
+ 0x30880036, 0x30890008, 0xaf4f0178, 0x00e01821, 0x9742008a, 0x00431023,
+ 0x2442ffff, 0x30421fff, 0x2c420008, 0x1440fffa, 0x00000000, 0x8f830018,
+ 0x00a05021, 0x00c53023, 0x24e24000, 0x03422821, 0x306b00ff, 0x24630001,
+ 0xaf830018, 0x93840012, 0x000b1400, 0x3c030100, 0x00431025, 0xaca20000,
+ 0x8f820018, 0x30840007, 0x00042240, 0x34870001, 0x00e83825, 0x1120000f,
+ 0xaca20004, 0x97430e0a, 0x8f84000c, 0x00ee3825, 0x2402000e, 0x00781825,
+ 0xaf430160, 0x25430006, 0x24840008, 0x30841fff, 0xa742015a, 0xa7430158,
+ 0xaf84000c, 0x0a0008a9, 0x00000000, 0x8f83000c, 0x25420002, 0xa7420158,
+ 0x24630008, 0x30631fff, 0xaf83000c, 0x54c0000c, 0x8f420e14, 0x97420e10,
+ 0x97430e12, 0x8f840014, 0x00021400, 0x00621825, 0xac8300a8, 0x8f850014,
+ 0x8f420e18, 0x34e70040, 0xaca200ac, 0x8f420e14, 0x8f430e1c, 0xaf420144,
+ 0xaf430148, 0xa34b0152, 0xaf470154, 0x0a0009f1, 0xaf4e0178, 0x10400128,
+ 0x00000000, 0x97620010, 0x00a2102b, 0x10400003, 0x30820040, 0x10400122,
+ 0x00000000, 0xafa60008, 0xa7840010, 0xaf850004, 0x93620008, 0x1440005e,
+ 0x27ac0008, 0xaf60000c, 0x97820010, 0x30424000, 0x10400002, 0x2403000e,
+ 0x24030016, 0xa363000a, 0x24034007, 0xaf630014, 0x93820012, 0x8f630014,
+ 0x30420007, 0x00021240, 0x00621825, 0xaf630014, 0x97820010, 0x8f630014,
+ 0x30420010, 0x00621825, 0xaf630014, 0x97820010, 0x30420008, 0x5040000e,
+ 0x00002821, 0x8f620014, 0x004e1025, 0xaf620014, 0x97430e0a, 0x2402000e,
+ 0x00781825, 0xaf630004, 0xa3620002, 0x9363000a, 0x3405fffc, 0x24630004,
+ 0x0a0008f2, 0xa363000a, 0xaf600004, 0xa3600002, 0x97820010, 0x9363000a,
+ 0x30421f00, 0x00021182, 0x24420028, 0x00621821, 0xa3630009, 0x97420e0c,
+ 0xa7620010, 0x93630009, 0x24020008, 0x24630002, 0x30630007, 0x00431023,
+ 0x30420007, 0xa362000b, 0x93640009, 0x97620010, 0x8f890004, 0x97830010,
+ 0x00441021, 0x00a21021, 0x30630040, 0x10600006, 0x3045ffff, 0x15250005,
+ 0x0125102b, 0x3c068000, 0x0a000925, 0x00005821, 0x0125102b, 0x144000c8,
+ 0x00005021, 0x97420e14, 0xa7420e10, 0x97430e16, 0xa7430e12, 0x8f420e1c,
+ 0xaf420e18, 0xaf450e00, 0x8f420000, 0x30420008, 0x1040fffd, 0x00000000,
+ 0x97420e08, 0x00a04821, 0xa7820010, 0x8f430e04, 0x00003021, 0x240b0001,
+ 0xaf830004, 0x97620010, 0x0a000936, 0x304dffff, 0x8f890004, 0x97820010,
+ 0x30420040, 0x10400004, 0x01206821, 0x3c068000, 0x0a000936, 0x00005821,
+ 0x97630010, 0x8f820004, 0x144300a7, 0x00005021, 0x00003021, 0x240b0001,
+ 0x8d820000, 0x00491023, 0x1440000d, 0xad820000, 0x8f620014, 0x34420040,
+ 0xaf620014, 0x97430e10, 0x97420e12, 0x8f840014, 0x00031c00, 0x00431025,
+ 0xac8200a8, 0x8f830014, 0x8f420e18, 0xac6200ac, 0x93620008, 0x1440003f,
+ 0x00000000, 0x25260002, 0x8f84000c, 0x9743008a, 0x3063ffff, 0xafa30000,
+ 0x8fa20000, 0x00441023, 0x2442ffff, 0x30421fff, 0x2c420010, 0x1440fff7,
+ 0x00000000, 0x8f82000c, 0x8f830018, 0x00021082, 0x00021080, 0x24424000,
+ 0x03422821, 0x00605021, 0x24630001, 0x314200ff, 0x00021400, 0xaf830018,
+ 0x3c033200, 0x00431025, 0xaca20000, 0x93630009, 0x9362000a, 0x00031c00,
+ 0x00431025, 0xaca20004, 0x8f830018, 0xaca30008, 0x97820010, 0x30420008,
+ 0x10400002, 0x00c04021, 0x25280006, 0x97430e14, 0x93640002, 0x8f450e1c,
+ 0x8f660004, 0x8f670014, 0xaf4f0178, 0x3063ffff, 0xa7430144, 0x97420e16,
+ 0xa7420146, 0xaf450148, 0xa34a0152, 0x8f82000c, 0x308400ff, 0xa744015a,
+ 0xaf460160, 0xa7480158, 0xaf470154, 0xaf4e0178, 0x00501021, 0x30421fff,
+ 0xaf82000c, 0x0a0009c5, 0x8d820000, 0x93620009, 0x9363000b, 0x8f85000c,
+ 0x2463000a, 0x00435021, 0x25440007, 0x00992024, 0x9743008a, 0x3063ffff,
+ 0xafa30000, 0x8fa20000, 0x00451023, 0x2442ffff, 0x30421fff, 0x0044102b,
+ 0x1440fff7, 0x00000000, 0x8f82000c, 0x8f840018, 0x00021082, 0x00021080,
+ 0x24424000, 0x03422821, 0x00804021, 0x24840001, 0xaf840018, 0x93630009,
+ 0x310200ff, 0x00022400, 0x3c024100, 0x24630002, 0x00621825, 0x00832025,
+ 0xaca40000, 0x8f62000c, 0x00461025, 0xaca20004, 0x97430e14, 0x93640002,
+ 0x8f450e1c, 0x8f660004, 0x8f670014, 0xaf4f0178, 0x3063ffff, 0xa7430144,
+ 0x97420e16, 0x308400ff, 0xa7420146, 0xaf450148, 0xa3480152, 0x8f83000c,
+ 0x25420007, 0x00591024, 0xa744015a, 0xaf460160, 0xa7490158, 0xaf470154,
+ 0xaf4e0178, 0x00621821, 0x30631fff, 0xaf83000c, 0x8d820000, 0x14400005,
+ 0x00000000, 0x8f620014, 0x2403ffbf, 0x00431024, 0xaf620014, 0x8f62000c,
+ 0x004d1021, 0xaf62000c, 0x93630008, 0x14600008, 0x00000000, 0x11600006,
+ 0x00000000, 0x8f630014, 0x3c02efff, 0x3442fffe, 0x00621824, 0xaf630014,
+ 0xa36b0008, 0x01205021, 0x15400016, 0x8fa60008, 0x97420e14, 0x97430e16,
+ 0x8f850014, 0x00021400, 0x00621825, 0xaca300a8, 0x8f840014, 0x8f420e1c,
+ 0x0a0009f3, 0xac8200ac, 0x97420e14, 0x97430e16, 0x8f840014, 0x00021400,
+ 0x00621825, 0xac8300a8, 0x8f850014, 0x8f420e1c, 0x00005021, 0x0a0009f3,
+ 0xaca200ac, 0x14c0fe64, 0x00000000, 0x55400018, 0x8fb00010, 0x3c038000,
+ 0x8f420178, 0x00431024, 0x1440fffd, 0x00000000, 0x97430e14, 0x8f440e1c,
+ 0x24020800, 0xaf420178, 0x3063ffff, 0xa7430144, 0x97420e16, 0x3c031000,
+ 0xa7420146, 0x24020240, 0xaf440148, 0xa3400152, 0xa740015a, 0xaf400160,
+ 0xa7400158, 0xaf420154, 0xaf430178, 0x8fb00010, 0x03e00008, 0x27bd0018,
+ 0x27bdffd8, 0x3c1a8000, 0x3c0420ff, 0x3484fffd, 0x3c020008, 0x03421821,
+ 0xafbf0020, 0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010, 0xaf830014,
+ 0xaf440e00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x3c0200ff, 0x3442fffd, 0x3c046004, 0xaf420e00, 0x8c835000, 0x24130d00,
+ 0x3c120800, 0x3c114000, 0x2402ff7f, 0x00621824, 0x3463380c, 0x24020009,
+ 0xac835000, 0xaf420008, 0xaf800018, 0xaf80000c, 0x0e000fa1, 0x00000000,
+ 0x0e000a96, 0x00000000, 0x3c020800, 0x24504080, 0x8f420000, 0x30420001,
+ 0x1040fffd, 0x00000000, 0x8f440100, 0xaf840008, 0xaf440020, 0x93430108,
+ 0xa3830012, 0x93820012, 0x30420001, 0x10400008, 0x00000000, 0x93820012,
+ 0x30420006, 0x00021100, 0x0e00083b, 0x0050d821, 0x0a000a52, 0x00000000,
+ 0x14930005, 0x00000000, 0x0e00083b, 0x265b4100, 0x0a000a52, 0x00000000,
+ 0x0e000ba3, 0x00000000, 0xaf510138, 0x0a000a36, 0x00000000, 0x27bdfff8,
+ 0x3084ffff, 0x24820007, 0x3044fff8, 0x8f85000c, 0x9743008a, 0x3063ffff,
+ 0xafa30000, 0x8fa20000, 0x00451023, 0x2442ffff, 0x30421fff, 0x0044102b,
+ 0x1440fff7, 0x00000000, 0x8f82000c, 0x00021082, 0x00021080, 0x24424000,
+ 0x03421021, 0x03e00008, 0x27bd0008, 0x3084ffff, 0x8f82000c, 0x24840007,
+ 0x3084fff8, 0x00441021, 0x30421fff, 0xaf82000c, 0x03e00008, 0x00000000,
+ 0x27bdffe8, 0x3c1a8000, 0x3c0420ff, 0x3484fffd, 0x3c020008, 0x03421821,
+ 0xafbf0010, 0xaf830014, 0xaf440e00, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x3c0200ff, 0x3442fffd, 0x3c046004, 0xaf420e00,
+ 0x8c825000, 0x2403ff7f, 0x00431024, 0x3442380c, 0x24030009, 0xac825000,
+ 0xaf430008, 0xaf800018, 0xaf80000c, 0x0e000fa1, 0x00000000, 0x0e000a96,
+ 0x00000000, 0x8fbf0010, 0x03e00008, 0x27bd0018, 0x27bdffe8, 0x3c02000a,
+ 0x03421821, 0x3c040800, 0x24844120, 0x24050018, 0xafbf0010, 0xaf830024,
+ 0x0e000fad, 0x00003021, 0x3c050800, 0x3c020800, 0x24423d60, 0xaca24180,
+ 0x24a54180, 0x3c020800, 0x24423e18, 0x3c030800, 0x24633e2c, 0x3c040800,
+ 0xaca20004, 0x3c020800, 0x24423d68, 0xaca30008, 0xac824190, 0x24844190,
+ 0x3c020800, 0x24423da4, 0x3c070800, 0x24e73de4, 0x3c060800, 0x24c63e40,
+ 0x3c050800, 0x24a52b28, 0x3c030800, 0xac820004, 0x3c020800, 0x24423e48,
+ 0xac870008, 0xac86000c, 0xac850010, 0xac6241b0, 0x246341b0, 0x8fbf0010,
+ 0x3c020800, 0x24423e60, 0xac620004, 0xac670008, 0xac66000c, 0xac650010,
+ 0x03e00008, 0x27bd0018, 0x27bdffc8, 0x3c020800, 0x24424120, 0xafbf0030,
+ 0xafb3002c, 0xafb20028, 0xafb10024, 0xafb00020, 0x90470021, 0x8c510008,
+ 0x8c45001c, 0x8f900020, 0x3c060800, 0x3c038000, 0x8f420178, 0x00431024,
+ 0x1440fffd, 0x8cc2414c, 0x24c3414c, 0x2473ffd4, 0xaf420144, 0x8e620030,
+ 0x30b22000, 0xaf420148, 0x3c021000, 0xaf50014c, 0xa3470152, 0xa7510158,
+ 0xaf450154, 0xaf420178, 0x12400004, 0x3c030800, 0x8c620030, 0x24420001,
+ 0xac620030, 0x93420109, 0x9344010a, 0x00111c00, 0xafa30018, 0x00071a00,
+ 0xafa50014, 0x8cc5414c, 0x00021600, 0x00042400, 0x00441025, 0x00431025,
+ 0xafa20010, 0x8f440100, 0x8e660030, 0x0e000fe1, 0x02003821, 0x1640000e,
+ 0x8fbf0030, 0x8f820000, 0x8e630030, 0x8c44017c, 0x02031823, 0x00711823,
+ 0x00641823, 0x2c630002, 0x14600006, 0x8fb3002c, 0x0000000d, 0x00000000,
+ 0x240000ca, 0x8fbf0030, 0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020,
+ 0x03e00008, 0x27bd0038, 0x974309da, 0x00804021, 0xad030000, 0x8f4209dc,
+ 0xad020004, 0x8f4309e0, 0xad030008, 0x934409d9, 0x24020001, 0x30840003,
+ 0x1082001f, 0x30a900ff, 0x28820002, 0x10400005, 0x24020002, 0x10800009,
+ 0x3c0a0800, 0x0a000b64, 0x93420934, 0x1082000b, 0x24020003, 0x10820026,
+ 0x3c0a0800, 0x0a000b64, 0x93420934, 0x974209e4, 0x00021400, 0x34420800,
+ 0xad02000c, 0x0a000b63, 0x25080010, 0x974209e4, 0x00021400, 0x34428100,
+ 0xad02000c, 0x974309e8, 0x3c0a0800, 0x00031c00, 0x34630800, 0xad030010,
+ 0x0a000b63, 0x25080014, 0x974409e4, 0x3c050800, 0x24a24120, 0x94430018,
+ 0x94460010, 0x9447000c, 0x00a05021, 0x24020800, 0xad000010, 0xad020014,
+ 0x00042400, 0x00661821, 0x00671823, 0x2463fff2, 0x00832025, 0xad04000c,
+ 0x0a000b63, 0x25080018, 0x974209e4, 0x3c050800, 0x00021400, 0x34428100,
+ 0xad02000c, 0x974409e8, 0x24a24120, 0x94430018, 0x94460010, 0x9447000c,
+ 0x00a05021, 0x24020800, 0xad000014, 0xad020018, 0x00042400, 0x00661821,
+ 0x00671823, 0x2463ffee, 0x00832025, 0xad040010, 0x2508001c, 0x93420934,
+ 0x93450921, 0x3c074000, 0x25444120, 0x94830014, 0x94860010, 0x00021082,
+ 0x00021600, 0x00052c00, 0x00a72825, 0x00451025, 0x00661821, 0x00431025,
+ 0xad020000, 0x97830028, 0x974209ea, 0x00621821, 0x00031c00, 0xad030004,
+ 0x97820028, 0x24420001, 0x30427fff, 0xa7820028, 0x93430920, 0x3c020006,
+ 0x00031e00, 0x00621825, 0xad030008, 0x8f42092c, 0xad02000c, 0x8f430930,
+ 0xad030010, 0x8f440938, 0x25080014, 0xad040000, 0x8f820020, 0x11200004,
+ 0xad020004, 0x8f420940, 0x0a000b8d, 0x2442ffff, 0x8f420940, 0xad020008,
+ 0x8f440948, 0x8f420940, 0x93430936, 0x00822823, 0x00652806, 0x3402ffff,
+ 0x0045102b, 0x54400001, 0x3405ffff, 0x93420937, 0x25444120, 0x90830020,
+ 0xad000010, 0x00021700, 0x34630010, 0x00031c00, 0x00431025, 0x00451025,
+ 0xad02000c, 0x03e00008, 0x25020014, 0x27bdffb0, 0x3c020008, 0x03421821,
+ 0xafbf004c, 0xafbe0048, 0xafb70044, 0xafb60040, 0xafb5003c, 0xafb40038,
+ 0xafb30034, 0xafb20030, 0xafb1002c, 0xafb00028, 0xaf830000, 0x24020040,
+ 0xaf420814, 0xaf400810, 0x8f420944, 0x8f430950, 0x8f440954, 0x8f45095c,
+ 0xaf820030, 0xaf830020, 0xaf84001c, 0xaf85002c, 0x93430900, 0x24020020,
+ 0x10620005, 0x24020030, 0x10620022, 0x3c030800, 0x0a000bf1, 0x8c62002c,
+ 0x24020088, 0xaf420818, 0x3c020800, 0x24424180, 0xafa20020, 0x93430109,
+ 0x3c020800, 0x10600009, 0x24574190, 0x3c026000, 0x24030100, 0xac43081c,
+ 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000, 0x2400031d, 0x9342010a,
+ 0x30420080, 0x1440001c, 0x00000000, 0x3c026000, 0x24030100, 0xac43081c,
+ 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000, 0x24000324, 0x0a000bf4,
+ 0x00000000, 0x93430109, 0x3063007f, 0x00031140, 0x000318c0, 0x00431021,
+ 0x24430088, 0xaf430818, 0x0000000d, 0x3c020800, 0x244241d0, 0x3c030800,
+ 0x247741e0, 0x0a000bf4, 0xafa20020, 0x24420001, 0x0a000f4c, 0xac62002c,
+ 0x8f840000, 0x8f850020, 0x24020800, 0xaf420178, 0x8f4209a4, 0x8c83017c,
+ 0x00a21023, 0x00431023, 0x2c420002, 0x14400004, 0x00000000, 0x0000000d,
+ 0x00000000, 0x24000349, 0x8f420104, 0x8f430988, 0x00431023, 0x58400005,
+ 0x8f4209a0, 0x0000000d, 0x00000000, 0x2400034d, 0x8f4209a0, 0x3c100800,
+ 0xae02414c, 0x8f4309a4, 0x2604414c, 0x2491ffd4, 0xae230030, 0x8f420104,
+ 0xae250024, 0x00431023, 0xac82ffd4, 0x8fa30020, 0x8c620000, 0x0040f809,
+ 0x0200b021, 0x00409021, 0x32440010, 0x32420002, 0x10400007, 0xafa40024,
+ 0x8e22001c, 0x32500040, 0x2403ffbf, 0x00431024, 0x0a000f13, 0xae22001c,
+ 0x32420020, 0x10400002, 0x3c020800, 0x245741b0, 0x32420001, 0x14400007,
+ 0x00000000, 0x8f820008, 0xaf420080, 0x8ec3414c, 0xaf430e10, 0x8e220030,
+ 0xaf420e18, 0x9343010b, 0x93420905, 0x30420008, 0x1040003c, 0x307400ff,
+ 0x8f820000, 0x8c430074, 0x0460000a, 0x00000000, 0x3c026000, 0x24030100,
+ 0xac43081c, 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000, 0x24000384,
+ 0x8f820000, 0x9044007b, 0x9343010a, 0x14830027, 0x32500040, 0x24072000,
+ 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, 0x8ec2414c,
+ 0x26c4414c, 0x2484ffd4, 0xaf420144, 0x8c820030, 0x3c030100, 0xaf420148,
+ 0x24020047, 0xaf43014c, 0x00001821, 0xa3420152, 0x3c021000, 0xa7430158,
+ 0xaf470154, 0xaf420178, 0x8ec5414c, 0x8d230030, 0x8c860030, 0x24630001,
+ 0xad230030, 0x93420109, 0x9343010a, 0xafa70014, 0xafa00018, 0x00021600,
+ 0x00031c00, 0x00431025, 0x34424700, 0xafa20010, 0x8f440100, 0x0e000fe1,
+ 0x3c070100, 0x3c030800, 0x24624120, 0x0a000d01, 0x8c43001c, 0x32820002,
+ 0x10400047, 0x3c039000, 0x34630001, 0x8f820008, 0x32500040, 0x3c048000,
+ 0x00431025, 0xaf420020, 0x8f420020, 0x00441024, 0x1440fffd, 0x00000000,
+ 0x8f830000, 0x90620005, 0x3c058000, 0x34420008, 0xa0620005, 0x8f860000,
+ 0x34a50001, 0x8f840008, 0x8cc20074, 0x3c038000, 0x00852025, 0x00431025,
+ 0xacc20074, 0xaf440020, 0x90c3007b, 0x9342010a, 0x14620028, 0x3c040800,
+ 0x24072000, 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd,
+ 0x8ec2414c, 0x26c4414c, 0x2484ffd4, 0xaf420144, 0x8c820030, 0x3c030100,
+ 0xaf420148, 0x24020046, 0xaf43014c, 0x00001821, 0xa3420152, 0x3c021000,
+ 0xa7430158, 0xaf470154, 0xaf420178, 0x8ec5414c, 0x8d230030, 0x8c860030,
+ 0x24630001, 0xad230030, 0x93420109, 0x9343010a, 0xafa70014, 0xafa00018,
+ 0x00021600, 0x00031c00, 0x00431025, 0x34424600, 0xafa20010, 0x8f440100,
+ 0x0e000fe1, 0x3c070100, 0x3c040800, 0x24824120, 0x0a000d01, 0x8c43001c,
+ 0x93420108, 0x30420010, 0x50400050, 0x9343093f, 0x8f860000, 0x90c3007f,
+ 0x90c2007e, 0x90c40080, 0x306800ff, 0x00021600, 0x00081c00, 0x00431025,
+ 0x00042200, 0x90c3007a, 0x90c5000a, 0x00441025, 0x11050028, 0x00623825,
+ 0xa0c8000a, 0x24086000, 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024,
+ 0x1440fffd, 0x8ec2414c, 0x26c4414c, 0x2484ffd4, 0xaf420144, 0x8c820030,
+ 0x00001821, 0xaf420148, 0x24020052, 0xaf47014c, 0xa3420152, 0x3c021000,
+ 0xa7430158, 0xaf480154, 0xaf420178, 0x8ec5414c, 0x8d230030, 0x8c860030,
+ 0x24630001, 0xad230030, 0x93420109, 0x9343010a, 0xafa80014, 0xafa00018,
+ 0x00021600, 0x00031c00, 0x00431025, 0x34425200, 0xafa20010, 0x0e000fe1,
+ 0x8f440100, 0x0a000cfb, 0x00000000, 0x3c026000, 0x24030100, 0xac43081c,
+ 0x3c030001, 0xac43081c, 0x0000000d, 0x00000000, 0x240003cd, 0x16800009,
+ 0x3c040800, 0x3c030800, 0x24624120, 0x8c43001c, 0x32500040, 0x2404ffbf,
+ 0x00641824, 0x0a000f13, 0xac43001c, 0x8c824120, 0x10400005, 0x3c030800,
+ 0x8c620034, 0xac804120, 0x24420001, 0xac620034, 0x9343093f, 0x24020012,
+ 0x1462000f, 0x329e0038, 0x17c0000c, 0x3c030800, 0x8f830000, 0x8c62004c,
+ 0xac62005c, 0x3c020800, 0x24444120, 0x8c82001c, 0x32500040, 0x2403ffbf,
+ 0x00431024, 0x0a000f13, 0xac82001c, 0xac604120, 0x97420908, 0x000211c0,
+ 0xaf420024, 0x97420908, 0x3c030080, 0x34630003, 0x000211c0, 0xaf42080c,
+ 0xaf43081c, 0x974209ec, 0x8f4309a4, 0xa7820028, 0x3c020800, 0x24444120,
+ 0xac830028, 0x93420937, 0x93430934, 0x00021080, 0x00621821, 0xa4830014,
+ 0x934209d8, 0x00621821, 0xa4830016, 0x934209d8, 0x93430934, 0x00809821,
+ 0x00431021, 0x24420010, 0xa4820012, 0x0000a821, 0x24020006, 0x13c00003,
+ 0xae62001c, 0x0a000d82, 0x24120008, 0x8f420958, 0x8f830020, 0x8f84002c,
+ 0x00431023, 0x00832023, 0x04800003, 0xae620004, 0x04410003, 0x0082102b,
+ 0x0a000d4e, 0xae600004, 0x54400001, 0xae640004, 0x8ee20000, 0x0040f809,
+ 0x00000000, 0x00409021, 0x32420001, 0x5440001e, 0x8ee20004, 0x8e630008,
+ 0x1060002b, 0x3c02c000, 0x00621025, 0xaf420e00, 0x8f420000, 0x30420008,
+ 0x1040fffd, 0x00000000, 0x97420e08, 0xa7820010, 0x8f430e04, 0x8e620008,
+ 0xaf830004, 0x8f840004, 0x0044102b, 0x1040000b, 0x24150001, 0x24020100,
+ 0x3c016000, 0xac22081c, 0x3c020001, 0x3c016000, 0xac22081c, 0x0000000d,
+ 0x00000000, 0x24000449, 0x24150001, 0x8ee20004, 0x0040f809, 0x00000000,
+ 0x02429025, 0x32420002, 0x5040001d, 0x8f470940, 0x12a00006, 0x8ec2414c,
+ 0x8f830000, 0xac6200a8, 0x8f840000, 0x8e620030, 0xac8200ac, 0x32420004,
+ 0x50400013, 0x8f470940, 0x3c020800, 0x3283007d, 0x106000fe, 0x245741b0,
+ 0x32820001, 0x50400006, 0x36520002, 0x8f830030, 0x8f420940, 0x106200f7,
+ 0x00000000, 0x36520002, 0x24020008, 0xa660000c, 0xa662000e, 0xae600008,
+ 0xa2600020, 0x8f470940, 0x3c030800, 0x24684120, 0x8d020028, 0x8d050008,
+ 0x9504000c, 0x9506000a, 0x95030022, 0x00451021, 0x00862021, 0x00641821,
+ 0xaf870030, 0xad020028, 0x32820030, 0x10400006, 0xa5030010, 0x91020020,
+ 0x32910040, 0x34420004, 0x0a000dd4, 0xa1020020, 0x93420923, 0x30420040,
+ 0x10400029, 0x32910040, 0x8f830000, 0x8f840020, 0x8c620084, 0x00441023,
+ 0x0442000a, 0x3c039000, 0x95020010, 0x8c630084, 0x00821021, 0x00621823,
+ 0x1c600004, 0x3c039000, 0x91020020, 0x34420001, 0xa1020020, 0x34630001,
+ 0x8f820008, 0x32910040, 0x3c048000, 0x00431025, 0xaf420020, 0x8f420020,
+ 0x00441024, 0x1440fffd, 0x00000000, 0x8f840000, 0x9083003f, 0x2402000a,
+ 0x10620005, 0x2402000c, 0x9083003f, 0x24020008, 0x14620002, 0x24020014,
+ 0xa082003f, 0x8f830008, 0x3c028000, 0x34420001, 0x00621825, 0xaf430020,
+ 0x3c040800, 0x24904120, 0x9602000c, 0x96030016, 0x9604000e, 0x00431021,
+ 0x00442021, 0x24840002, 0x3084ffff, 0x0e000a55, 0xa6020018, 0x8f850018,
+ 0x00a01821, 0xa2030021, 0x8ee60008, 0x00402021, 0x24a50001, 0xaf850018,
+ 0x00c0f809, 0x00000000, 0x00402021, 0x0e000b12, 0x02202821, 0x8ee3000c,
+ 0x0060f809, 0x00402021, 0x96040018, 0x9602000e, 0x00822021, 0x24840002,
+ 0x0e000a6b, 0x3084ffff, 0x3c030800, 0x8c624120, 0x8e030008, 0x3c040800,
+ 0x00431023, 0x14400012, 0xac824120, 0x54600006, 0x8e02001c, 0x3243004a,
+ 0x24020002, 0x14620005, 0x00000000, 0x8e02001c, 0x34420040, 0x0a000e0b,
+ 0xae02001c, 0x52a00006, 0x36520002, 0x8e02002c, 0xaf420e10, 0x8e030030,
+ 0xaf430e18, 0x36520002, 0x52a00008, 0x96670010, 0x8f830000, 0x8f420e10,
+ 0xac6200a8, 0x8f840000, 0x8f420e18, 0xac8200ac, 0x96670010, 0x92680020,
+ 0x24020040, 0xaf420814, 0x8f830020, 0x8f82001c, 0x00671821, 0x00621023,
+ 0xaf830020, 0x58400005, 0x8f42095c, 0x8f820000, 0xaf83001c, 0xac430054,
+ 0x8f42095c, 0x31030008, 0xaf82002c, 0x1060001a, 0x00000000, 0x8f840000,
+ 0x90820120, 0x90830121, 0x304600ff, 0x00c31823, 0x30630007, 0x24020007,
+ 0x1062000e, 0x00000000, 0x90820122, 0x304200fe, 0xa0820122, 0x8f850000,
+ 0x00061880, 0x8f840020, 0x24a20100, 0x00431021, 0x24c30001, 0x30630007,
+ 0xac440000, 0x0a000e40, 0xa0a30120, 0x90820122, 0x34420001, 0xa0820122,
+ 0x14e00003, 0x31020001, 0x10400031, 0x32510002, 0x8f820000, 0x8c43000c,
+ 0x30630001, 0x1060002c, 0x32510002, 0x3c029000, 0x8f830008, 0x34420001,
+ 0x3c048000, 0x00621825, 0xaf430020, 0x8f420020, 0x00441024, 0x1440fffd,
+ 0x00000000, 0x8f870000, 0x8ce2000c, 0x30420001, 0x10400018, 0x00000000,
+ 0x94e2006a, 0x00022880, 0x50a00001, 0x24050001, 0x94e30068, 0x90e40081,
+ 0x3c020800, 0x8c460024, 0x00652821, 0x00852804, 0x00c5102b, 0x54400001,
+ 0x00a03021, 0x3c020800, 0x8c440028, 0x00c4182b, 0x54600001, 0x00c02021,
+ 0x8f430074, 0x2402fffe, 0x00822824, 0x00a31821, 0xace3000c, 0x8f830008,
+ 0x3c028000, 0x34420001, 0x00621825, 0xaf430020, 0x8f830020, 0x3c020800,
+ 0x24504120, 0xae030024, 0x8ee20010, 0x0040f809, 0x00000000, 0x12a00005,
+ 0x00000000, 0x8f420e10, 0xae02002c, 0x8f430e18, 0xae030030, 0x1220feba,
+ 0x0000a821, 0x8f870024, 0x97860028, 0x8f830000, 0x8f820030, 0x8f840020,
+ 0x8f85001c, 0x32500040, 0xa4e6002c, 0xac620044, 0x32420008, 0xac640050,
+ 0xac650054, 0x1040007a, 0x32820020, 0x10400027, 0x32910010, 0x24072000,
+ 0x3c090800, 0x3c038000, 0x8f420178, 0x00431024, 0x1440fffd, 0x8ec2414c,
+ 0x26c4414c, 0x2484ffd4, 0xaf420144, 0x8c820030, 0x3c030400, 0xaf420148,
+ 0x24020041, 0xaf43014c, 0x00001821, 0xa3420152, 0x3c021000, 0xa7430158,
+ 0xaf470154, 0xaf420178, 0x8ec5414c, 0x8d230030, 0x8c860030, 0x24630001,
+ 0xad230030, 0x93420109, 0x9343010a, 0xafa70014, 0xafa00018, 0x00021600,
+ 0x00031c00, 0x00431025, 0x34424100, 0xafa20010, 0x8f440100, 0x0e000fe1,
+ 0x3c070400, 0x12200028, 0x24072000, 0x3c090800, 0x3c038000, 0x8f420178,
+ 0x00431024, 0x1440fffd, 0x8ec2414c, 0x26c4414c, 0x2484ffd4, 0xaf420144,
+ 0x8c820030, 0x3c030300, 0xaf420148, 0x2402004e, 0xaf43014c, 0x00001821,
+ 0xa3420152, 0x3c021000, 0xa7430158, 0xaf470154, 0xaf420178, 0x8ec5414c,
+ 0x8d230030, 0x8c860030, 0x24630001, 0xad230030, 0x93420109, 0x9343010a,
+ 0xafa70014, 0xafa00018, 0x00021600, 0x00031c00, 0x00431025, 0x34424e00,
+ 0xafa20010, 0x8f440100, 0x0e000fe1, 0x3c070300, 0x0a000f0b, 0x8fa30024,
+ 0x32820008, 0x10400026, 0x3c090800, 0x24072000, 0x3c038000, 0x8f420178,
+ 0x00431024, 0x1440fffd, 0x8ec2414c, 0x26c4414c, 0x2484ffd4, 0xaf420144,
+ 0x8c820030, 0x3c030200, 0xaf420148, 0x2402004b, 0xaf43014c, 0x00001821,
+ 0xa3420152, 0x3c021000, 0xa7430158, 0xaf470154, 0xaf420178, 0x8ec5414c,
+ 0x8d230030, 0x8c860030, 0x24630001, 0xad230030, 0x93420109, 0x9343010a,
+ 0xafa70014, 0xafa00018, 0x00021600, 0x00031c00, 0x00431025, 0x34424b00,
+ 0xafa20010, 0x8f440100, 0x0e000fe1, 0x3c070200, 0x8fa30024, 0x14600004,
+ 0x8fa40020, 0x32420010, 0x10400004, 0x00000000, 0x8c820004, 0x0040f809,
+ 0x00000000, 0x12000006, 0x8fa30020, 0x8c620008, 0x0040f809, 0x00000000,
+ 0x0a000f4d, 0x8fbf004c, 0x3c030800, 0x8c62413c, 0x30420040, 0x1440002f,
+ 0x8fbf004c, 0x24040040, 0x8f910020, 0x3c038000, 0x8f420178, 0x00431024,
+ 0x1440fffd, 0x8ec2414c, 0x26d0414c, 0x2610ffd4, 0xaf420144, 0x8e020030,
+ 0x00001821, 0xaf420148, 0x24020049, 0xaf51014c, 0xa3420152, 0x3c021000,
+ 0xa7430158, 0xaf440154, 0xaf420178, 0x8ec5414c, 0x8e060030, 0x93420109,
+ 0x9343010a, 0xafa40014, 0xafa00018, 0x00021600, 0x00031c00, 0x00431025,
+ 0x34424900, 0xafa20010, 0x8f440100, 0x0e000fe1, 0x02203821, 0x8f830000,
+ 0x8e020030, 0x8c64017c, 0x02221023, 0x00441023, 0x2c420002, 0x14400005,
+ 0x8fbf004c, 0x0000000d, 0x00000000, 0x240000ca, 0x8fbf004c, 0x8fbe0048,
+ 0x8fb70044, 0x8fb60040, 0x8fb5003c, 0x8fb40038, 0x8fb30034, 0x8fb20030,
+ 0x8fb1002c, 0x8fb00028, 0x03e00008, 0x27bd0050, 0x03e00008, 0x00001021,
+ 0x3c030800, 0x24654120, 0x8ca40004, 0x8c634120, 0x0064102b, 0x54400001,
+ 0x00602021, 0x9743093c, 0x0083102b, 0x54400001, 0x00801821, 0x00001021,
+ 0xaca30008, 0x03e00008, 0xa4a00022, 0x8f850004, 0x97840010, 0x3c030800,
+ 0x24634120, 0x24020008, 0xa462000e, 0x8f820004, 0xa460000c, 0x000420c2,
+ 0x30840008, 0x2c420001, 0x00021023, 0x30420006, 0xac650008, 0x03e00008,
+ 0xa0640020, 0x3c020800, 0x24424120, 0x90450021, 0x94430018, 0x3c021100,
+ 0xac800004, 0x00052c00, 0x24630002, 0x00621825, 0x00a32825, 0x24820008,
+ 0x03e00008, 0xac850000, 0x0000000d, 0x00000000, 0x2400016f, 0x03e00008,
+ 0x00000000, 0x0000000d, 0x00000000, 0x2400017b, 0x03e00008, 0x00000000,
+ 0x03e00008, 0x00000000, 0x3c020800, 0x24424120, 0xac400008, 0xa4400022,
+ 0x03e00008, 0x24020001, 0x3c020800, 0x24424120, 0x24030008, 0xac400008,
+ 0xa440000c, 0xa443000e, 0xa0400020, 0x03e00008, 0x24020004, 0x03e00008,
+ 0x00001021, 0x10c00007, 0x00000000, 0x8ca20000, 0x24c6ffff, 0x24a50004,
+ 0xac820000, 0x14c0fffb, 0x24840004, 0x03e00008, 0x00000000, 0x0a000fb2,
+ 0x00a01021, 0xac860000, 0x24840004, 0x00a01021, 0x1440fffc, 0x24a5ffff,
+ 0x03e00008, 0x00000000, 0x3c0a0800, 0x8d490068, 0x3c050800, 0x24a51090,
+ 0x00093140, 0x00c51021, 0xac440000, 0x8f440e04, 0x00a61021, 0xac440004,
+ 0x97430e08, 0x97420e0c, 0x00a62021, 0x00031c00, 0x00431025, 0xac820008,
+ 0x8f430e10, 0x00801021, 0xac43000c, 0x8f440e14, 0xac440010, 0x8f430e18,
+ 0x3c0800ff, 0xac430014, 0x8f470e1c, 0x3508ffff, 0x25290001, 0xac470018,
+ 0x3c070800, 0x8ce3006c, 0x9344010a, 0x3c026000, 0x24630001, 0xace3006c,
+ 0x8c434448, 0x3129007f, 0x00a62821, 0xad490068, 0x00042600, 0x00681824,
+ 0x00832025, 0x03e00008, 0xaca4001c, 0x8fac0010, 0x8fad0014, 0x8fae0018,
+ 0x3c0b0800, 0x8d6a0060, 0x3c080800, 0x25080078, 0x000a4940, 0x01281021,
+ 0x01091821, 0xac440000, 0x00601021, 0xac650004, 0xac460008, 0xac67000c,
+ 0xac4c0010, 0xac6d0014, 0x3c036000, 0xac4e0018, 0x8c654448, 0x3c040800,
+ 0x8c820064, 0x254a0001, 0x314a007f, 0x01094021, 0xad6a0060, 0x24420001,
+ 0xac820064, 0x03e00008, 0xad05001c, 0x00000000 };
+
+static u32 bnx2_TXP_b06FwData[(0x0/4) + 1] = { 0x00000000 };
+static u32 bnx2_TXP_b06FwRodata[(0x0/4) + 1] = { 0x00000000 };
+static u32 bnx2_TXP_b06FwBss[(0x194/4) + 1] = { 0x00000000 };
+static u32 bnx2_TXP_b06FwSbss[(0x34/4) + 1] = { 0x00000000 };
+
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 770e28f98fd..269a5e40734 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3037,7 +3037,7 @@ static void bond_activebackup_arp_mon(struct net_device *bond_dev)
bond_set_slave_inactive_flags(bond->current_arp_slave);
/* search for next candidate */
- bond_for_each_slave_from(bond, slave, i, bond->current_arp_slave) {
+ bond_for_each_slave_from(bond, slave, i, bond->current_arp_slave->next) {
if (IS_UP(slave->dev)) {
slave->link = BOND_LINK_BACK;
bond_set_slave_active_flags(slave);
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
new file mode 100644
index 00000000000..f4ba0ffb863
--- /dev/null
+++ b/drivers/net/dm9000.c
@@ -0,0 +1,1219 @@
+/*
+ * dm9000.c: Version 1.2 03/18/2003
+ *
+ * A Davicom DM9000 ISA NIC fast Ethernet driver for Linux.
+ * Copyright (C) 1997 Sten Wang
+ *
+ * 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 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.
+ *
+ * (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.
+ *
+ * V0.11 06/20/2001 REG_0A bit3=1, default enable BP with DA match
+ * 06/22/2001 Support DM9801 progrmming
+ * E3: R25 = ((R24 + NF) & 0x00ff) | 0xf000
+ * E4: R25 = ((R24 + NF) & 0x00ff) | 0xc200
+ * R17 = (R17 & 0xfff0) | NF + 3
+ * E5: R25 = ((R24 + NF - 3) & 0x00ff) | 0xc200
+ * R17 = (R17 & 0xfff0) | NF
+ *
+ * v1.00 modify by simon 2001.9.5
+ * change for kernel 2.4.x
+ *
+ * v1.1 11/09/2001 fix force mode bug
+ *
+ * v1.2 03/18/2003 Weilun Huang <weilun_huang@davicom.com.tw>:
+ * Fixed phy reset.
+ * Added tx/rx 32 bit mode.
+ * Cleaned up for kernel merge.
+ *
+ * 03/03/2004 Sascha Hauer <s.hauer@pengutronix.de>
+ * Port to 2.6 kernel
+ *
+ * 24-Sep-2004 Ben Dooks <ben@simtec.co.uk>
+ * Cleanup of code to remove ifdefs
+ * Allowed platform device data to influence access width
+ * Reformatting areas of code
+ *
+ * 17-Mar-2005 Sascha Hauer <s.hauer@pengutronix.de>
+ * * removed 2.4 style module parameters
+ * * removed removed unused stat counter and fixed
+ * net_device_stats
+ * * introduced tx_timeout function
+ * * reworked locking
+ */
+
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/version.h>
+#include <linux/spinlock.h>
+#include <linux/crc32.h>
+#include <linux/mii.h>
+#include <linux/dm9000.h>
+#include <linux/delay.h>
+
+#include <asm/delay.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include "dm9000.h"
+
+/* Board/System/Debug information/definition ---------------- */
+
+#define DM9000_PHY 0x40 /* PHY address 0x01 */
+
+#define TRUE 1
+#define FALSE 0
+
+#define CARDNAME "dm9000"
+#define PFX CARDNAME ": "
+
+#define DM9000_TIMER_WUT jiffies+(HZ*2) /* timer wakeup time : 2 second */
+
+#define DM9000_DEBUG 0
+
+#if DM9000_DEBUG > 2
+#define PRINTK3(args...) printk(CARDNAME ": " args)
+#else
+#define PRINTK3(args...) do { } while(0)
+#endif
+
+#if DM9000_DEBUG > 1
+#define PRINTK2(args...) printk(CARDNAME ": " args)
+#else
+#define PRINTK2(args...) do { } while(0)
+#endif
+
+#if DM9000_DEBUG > 0
+#define PRINTK1(args...) printk(CARDNAME ": " args)
+#define PRINTK(args...) printk(CARDNAME ": " args)
+#else
+#define PRINTK1(args...) do { } while(0)
+#define PRINTK(args...) printk(KERN_DEBUG args)
+#endif
+
+/*
+ * Transmit timeout, default 5 seconds.
+ */
+static int watchdog = 5000;
+module_param(watchdog, int, 0400);
+MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
+
+/* Structure/enum declaration ------------------------------- */
+typedef struct board_info {
+
+ void __iomem *io_addr; /* Register I/O base address */
+ void __iomem *io_data; /* Data I/O address */
+ u16 irq; /* IRQ */
+
+ u16 tx_pkt_cnt;
+ u16 queue_pkt_len;
+ u16 queue_start_addr;
+ u16 dbug_cnt;
+ u8 io_mode; /* 0:word, 2:byte */
+ u8 phy_addr;
+
+ void (*inblk)(void __iomem *port, void *data, int length);
+ void (*outblk)(void __iomem *port, void *data, int length);
+ void (*dumpblk)(void __iomem *port, int length);
+
+ struct resource *addr_res; /* resources found */
+ struct resource *data_res;
+ struct resource *addr_req; /* resources requested */
+ struct resource *data_req;
+ struct resource *irq_res;
+
+ struct timer_list timer;
+ struct net_device_stats stats;
+ unsigned char srom[128];
+ spinlock_t lock;
+
+ struct mii_if_info mii;
+ u32 msg_enable;
+} board_info_t;
+
+/* function declaration ------------------------------------- */
+static int dm9000_probe(struct device *);
+static int dm9000_open(struct net_device *);
+static int dm9000_start_xmit(struct sk_buff *, struct net_device *);
+static int dm9000_stop(struct net_device *);
+static int dm9000_do_ioctl(struct net_device *, struct ifreq *, int);
+
+
+static void dm9000_timer(unsigned long);
+static void dm9000_init_dm9000(struct net_device *);
+
+static struct net_device_stats *dm9000_get_stats(struct net_device *);
+
+static irqreturn_t dm9000_interrupt(int, void *, struct pt_regs *);
+
+static int dm9000_phy_read(struct net_device *dev, int phyaddr_unsused, int reg);
+static void dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg,
+ int value);
+static u16 read_srom_word(board_info_t *, int);
+static void dm9000_rx(struct net_device *);
+static void dm9000_hash_table(struct net_device *);
+
+//#define DM9000_PROGRAM_EEPROM
+#ifdef DM9000_PROGRAM_EEPROM
+static void program_eeprom(board_info_t * db);
+#endif
+/* DM9000 network board routine ---------------------------- */
+
+static void
+dm9000_reset(board_info_t * db)
+{
+ PRINTK1("dm9000x: resetting\n");
+ /* RESET device */
+ writeb(DM9000_NCR, db->io_addr);
+ udelay(200);
+ writeb(NCR_RST, db->io_data);
+ udelay(200);
+}
+
+/*
+ * Read a byte from I/O port
+ */
+static u8
+ior(board_info_t * db, int reg)
+{
+ writeb(reg, db->io_addr);
+ return readb(db->io_data);
+}
+
+/*
+ * Write a byte to I/O port
+ */
+
+static void
+iow(board_info_t * db, int reg, int value)
+{
+ writeb(reg, db->io_addr);
+ writeb(value, db->io_data);
+}
+
+/* routines for sending block to chip */
+
+static void dm9000_outblk_8bit(void __iomem *reg, void *data, int count)
+{
+ writesb(reg, data, count);
+}
+
+static void dm9000_outblk_16bit(void __iomem *reg, void *data, int count)
+{
+ writesw(reg, data, (count+1) >> 1);
+}
+
+static void dm9000_outblk_32bit(void __iomem *reg, void *data, int count)
+{
+ writesl(reg, data, (count+3) >> 2);
+}
+
+/* input block from chip to memory */
+
+static void dm9000_inblk_8bit(void __iomem *reg, void *data, int count)
+{
+ readsb(reg, data, count+1);
+}
+
+
+static void dm9000_inblk_16bit(void __iomem *reg, void *data, int count)
+{
+ readsw(reg, data, (count+1) >> 1);
+}
+
+static void dm9000_inblk_32bit(void __iomem *reg, void *data, int count)
+{
+ readsl(reg, data, (count+3) >> 2);
+}
+
+/* dump block from chip to null */
+
+static void dm9000_dumpblk_8bit(void __iomem *reg, int count)
+{
+ int i;
+ int tmp;
+
+ for (i = 0; i < count; i++)
+ tmp = readb(reg);
+}
+
+static void dm9000_dumpblk_16bit(void __iomem *reg, int count)
+{
+ int i;
+ int tmp;
+
+ count = (count + 1) >> 1;
+
+ for (i = 0; i < count; i++)
+ tmp = readw(reg);
+}
+
+static void dm9000_dumpblk_32bit(void __iomem *reg, int count)
+{
+ int i;
+ int tmp;
+
+ count = (count + 3) >> 2;
+
+ for (i = 0; i < count; i++)
+ tmp = readl(reg);
+}
+
+/* dm9000_set_io
+ *
+ * select the specified set of io routines to use with the
+ * device
+ */
+
+static void dm9000_set_io(struct board_info *db, int byte_width)
+{
+ /* use the size of the data resource to work out what IO
+ * routines we want to use
+ */
+
+ switch (byte_width) {
+ case 1:
+ db->dumpblk = dm9000_dumpblk_8bit;
+ db->outblk = dm9000_outblk_8bit;
+ db->inblk = dm9000_inblk_8bit;
+ break;
+
+ case 2:
+ db->dumpblk = dm9000_dumpblk_16bit;
+ db->outblk = dm9000_outblk_16bit;
+ db->inblk = dm9000_inblk_16bit;
+ break;
+
+ case 3:
+ printk(KERN_ERR PFX ": 3 byte IO, falling back to 16bit\n");
+ db->dumpblk = dm9000_dumpblk_16bit;
+ db->outblk = dm9000_outblk_16bit;
+ db->inblk = dm9000_inblk_16bit;
+ break;
+
+ case 4:
+ default:
+ db->dumpblk = dm9000_dumpblk_32bit;
+ db->outblk = dm9000_outblk_32bit;
+ db->inblk = dm9000_inblk_32bit;
+ break;
+ }
+}
+
+
+/* Our watchdog timed out. Called by the networking layer */
+static void dm9000_timeout(struct net_device *dev)
+{
+ board_info_t *db = (board_info_t *) dev->priv;
+ u8 reg_save;
+ unsigned long flags;
+
+ /* Save previous register address */
+ reg_save = readb(db->io_addr);
+ spin_lock_irqsave(db->lock,flags);
+
+ netif_stop_queue(dev);
+ dm9000_reset(db);
+ dm9000_init_dm9000(dev);
+ /* We can accept TX packets again */
+ dev->trans_start = jiffies;
+ netif_wake_queue(dev);
+
+ /* Restore previous register address */
+ writeb(reg_save, db->io_addr);
+ spin_unlock_irqrestore(db->lock,flags);
+}
+
+
+/* dm9000_release_board
+ *
+ * release a board, and any mapped resources
+ */
+
+static void
+dm9000_release_board(struct platform_device *pdev, struct board_info *db)
+{
+ if (db->data_res == NULL) {
+ if (db->addr_res != NULL)
+ release_mem_region((unsigned long)db->io_addr, 4);
+ return;
+ }
+
+ /* unmap our resources */
+
+ iounmap(db->io_addr);
+ iounmap(db->io_data);
+
+ /* release the resources */
+
+ if (db->data_req != NULL) {
+ release_resource(db->data_req);
+ kfree(db->data_req);
+ }
+
+ if (db->addr_res != NULL) {
+ release_resource(db->data_req);
+ kfree(db->addr_req);
+ }
+}
+
+#define res_size(_r) (((_r)->end - (_r)->start) + 1)
+
+/*
+ * Search DM9000 board, allocate space and register it
+ */
+static int
+dm9000_probe(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct dm9000_plat_data *pdata = pdev->dev.platform_data;
+ struct board_info *db; /* Point a board information structure */
+ struct net_device *ndev;
+ unsigned long base;
+ int ret = 0;
+ int iosize;
+ int i;
+ u32 id_val;
+
+ printk(KERN_INFO "%s Ethernet Driver\n", CARDNAME);
+
+ /* Init network device */
+ ndev = alloc_etherdev(sizeof (struct board_info));
+ if (!ndev) {
+ printk("%s: could not allocate device.\n", CARDNAME);
+ return -ENOMEM;
+ }
+
+ SET_MODULE_OWNER(ndev);
+ SET_NETDEV_DEV(ndev, dev);
+
+ PRINTK2("dm9000_probe()");
+
+ /* setup board info structure */
+ db = (struct board_info *) ndev->priv;
+ memset(db, 0, sizeof (*db));
+
+ if (pdev->num_resources < 2) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ switch (pdev->num_resources) {
+ case 2:
+ base = pdev->resource[0].start;
+
+ if (!request_mem_region(base, 4, ndev->name)) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ ndev->base_addr = base;
+ ndev->irq = pdev->resource[1].start;
+ db->io_addr = (void *)base;
+ db->io_data = (void *)(base + 4);
+
+ break;
+
+ case 3:
+ db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ db->irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+ if (db->addr_res == NULL || db->data_res == NULL) {
+ printk(KERN_ERR PFX "insufficient resources\n");
+ ret = -ENOENT;
+ goto out;
+ }
+
+ i = res_size(db->addr_res);
+ db->addr_req = request_mem_region(db->addr_res->start, i,
+ pdev->name);
+
+ if (db->addr_req == NULL) {
+ printk(KERN_ERR PFX "cannot claim address reg area\n");
+ ret = -EIO;
+ goto out;
+ }
+
+ db->io_addr = ioremap(db->addr_res->start, i);
+
+ if (db->io_addr == NULL) {
+ printk(KERN_ERR "failed to ioremap address reg\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ iosize = res_size(db->data_res);
+ db->data_req = request_mem_region(db->data_res->start, iosize,
+ pdev->name);
+
+ if (db->data_req == NULL) {
+ printk(KERN_ERR PFX "cannot claim data reg area\n");
+ ret = -EIO;
+ goto out;
+ }
+
+ db->io_data = ioremap(db->data_res->start, iosize);
+
+ if (db->io_data == NULL) {
+ printk(KERN_ERR "failed to ioremap data reg\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* fill in parameters for net-dev structure */
+
+ ndev->base_addr = (unsigned long)db->io_addr;
+ ndev->irq = db->irq_res->start;
+
+ /* ensure at least we have a default set of IO routines */
+ dm9000_set_io(db, iosize);
+
+ }
+
+ /* check to see if anything is being over-ridden */
+ if (pdata != NULL) {
+ /* check to see if the driver wants to over-ride the
+ * default IO width */
+
+ if (pdata->flags & DM9000_PLATF_8BITONLY)
+ dm9000_set_io(db, 1);
+
+ if (pdata->flags & DM9000_PLATF_16BITONLY)
+ dm9000_set_io(db, 2);
+
+ if (pdata->flags & DM9000_PLATF_32BITONLY)
+ dm9000_set_io(db, 4);
+
+ /* check to see if there are any IO routine
+ * over-rides */
+
+ if (pdata->inblk != NULL)
+ db->inblk = pdata->inblk;
+
+ if (pdata->outblk != NULL)
+ db->outblk = pdata->outblk;
+
+ if (pdata->dumpblk != NULL)
+ db->dumpblk = pdata->dumpblk;
+ }
+
+ dm9000_reset(db);
+
+ /* try two times, DM9000 sometimes gets the first read wrong */
+ for (i = 0; i < 2; i++) {
+ id_val = ior(db, DM9000_VIDL);
+ id_val |= (u32)ior(db, DM9000_VIDH) << 8;
+ id_val |= (u32)ior(db, DM9000_PIDL) << 16;
+ id_val |= (u32)ior(db, DM9000_PIDH) << 24;
+
+ if (id_val == DM9000_ID)
+ break;
+ printk("%s: read wrong id 0x%08x\n", CARDNAME, id_val);
+ }
+
+ if (id_val != DM9000_ID) {
+ printk("%s: wrong id: 0x%08x\n", CARDNAME, id_val);
+ goto release;
+ }
+
+ /* from this point we assume that we have found a DM9000 */
+
+ /* driver system function */
+ ether_setup(ndev);
+
+ ndev->open = &dm9000_open;
+ ndev->hard_start_xmit = &dm9000_start_xmit;
+ ndev->tx_timeout = &dm9000_timeout;
+ ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
+ ndev->stop = &dm9000_stop;
+ ndev->get_stats = &dm9000_get_stats;
+ ndev->set_multicast_list = &dm9000_hash_table;
+ ndev->do_ioctl = &dm9000_do_ioctl;
+
+#ifdef DM9000_PROGRAM_EEPROM
+ program_eeprom(db);
+#endif
+ db->msg_enable = NETIF_MSG_LINK;
+ db->mii.phy_id_mask = 0x1f;
+ db->mii.reg_num_mask = 0x1f;
+ db->mii.force_media = 0;
+ db->mii.full_duplex = 0;
+ db->mii.dev = ndev;
+ db->mii.mdio_read = dm9000_phy_read;
+ db->mii.mdio_write = dm9000_phy_write;
+
+ /* Read SROM content */
+ for (i = 0; i < 64; i++)
+ ((u16 *) db->srom)[i] = read_srom_word(db, i);
+
+ /* Set Node Address */
+ for (i = 0; i < 6; i++)
+ ndev->dev_addr[i] = db->srom[i];
+
+ if (!is_valid_ether_addr(ndev->dev_addr))
+ printk("%s: Invalid ethernet MAC address. Please "
+ "set using ifconfig\n", ndev->name);
+
+ dev_set_drvdata(dev, ndev);
+ ret = register_netdev(ndev);
+
+ if (ret == 0) {
+ printk("%s: dm9000 at %p,%p IRQ %d MAC: ",
+ ndev->name, db->io_addr, db->io_data, ndev->irq);
+ for (i = 0; i < 5; i++)
+ printk("%02x:", ndev->dev_addr[i]);
+ printk("%02x\n", ndev->dev_addr[5]);
+ }
+ return 0;
+
+ release:
+ out:
+ printk("%s: not found (%d).\n", CARDNAME, ret);
+
+ dm9000_release_board(pdev, db);
+ kfree(ndev);
+
+ return ret;
+}
+
+/*
+ * Open the interface.
+ * The interface is opened whenever "ifconfig" actives it.
+ */
+static int
+dm9000_open(struct net_device *dev)
+{
+ board_info_t *db = (board_info_t *) dev->priv;
+
+ PRINTK2("entering dm9000_open\n");
+
+ if (request_irq(dev->irq, &dm9000_interrupt, SA_SHIRQ, dev->name, dev))
+ return -EAGAIN;
+
+ /* Initialize DM9000 board */
+ dm9000_reset(db);
+ dm9000_init_dm9000(dev);
+
+ /* Init driver variable */
+ db->dbug_cnt = 0;
+
+ /* set and active a timer process */
+ init_timer(&db->timer);
+ db->timer.expires = DM9000_TIMER_WUT * 2;
+ db->timer.data = (unsigned long) dev;
+ db->timer.function = &dm9000_timer;
+ add_timer(&db->timer);
+
+ mii_check_media(&db->mii, netif_msg_link(db), 1);
+ netif_start_queue(dev);
+
+ return 0;
+}
+
+/*
+ * Initilize dm9000 board
+ */
+static void
+dm9000_init_dm9000(struct net_device *dev)
+{
+ board_info_t *db = (board_info_t *) dev->priv;
+
+ PRINTK1("entering %s\n",__FUNCTION__);
+
+ /* I/O mode */
+ db->io_mode = ior(db, DM9000_ISR) >> 6; /* ISR bit7:6 keeps I/O mode */
+
+ /* GPIO0 on pre-activate PHY */
+ iow(db, DM9000_GPR, 0); /* REG_1F bit0 activate phyxcer */
+ iow(db, DM9000_GPCR, GPCR_GEP_CNTL); /* Let GPIO0 output */
+ iow(db, DM9000_GPR, 0); /* Enable PHY */
+
+ /* Program operating register */
+ iow(db, DM9000_TCR, 0); /* TX Polling clear */
+ iow(db, DM9000_BPTR, 0x3f); /* Less 3Kb, 200us */
+ iow(db, DM9000_FCR, 0xff); /* Flow Control */
+ iow(db, DM9000_SMCR, 0); /* Special Mode */
+ /* clear TX status */
+ iow(db, DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
+ iow(db, DM9000_ISR, ISR_CLR_STATUS); /* Clear interrupt status */
+
+ /* Set address filter table */
+ dm9000_hash_table(dev);
+
+ /* Activate DM9000 */
+ iow(db, DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
+ /* Enable TX/RX interrupt mask */
+ iow(db, DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM);
+
+ /* Init Driver variable */
+ db->tx_pkt_cnt = 0;
+ db->queue_pkt_len = 0;
+ dev->trans_start = 0;
+ spin_lock_init(&db->lock);
+}
+
+/*
+ * Hardware start transmission.
+ * Send a packet to media from the upper layer.
+ */
+static int
+dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ board_info_t *db = (board_info_t *) dev->priv;
+
+ PRINTK3("dm9000_start_xmit\n");
+
+ if (db->tx_pkt_cnt > 1)
+ return 1;
+
+ netif_stop_queue(dev);
+
+ /* Disable all interrupts */
+ iow(db, DM9000_IMR, IMR_PAR);
+
+ /* Move data to DM9000 TX RAM */
+ writeb(DM9000_MWCMD, db->io_addr);
+
+ (db->outblk)(db->io_data, skb->data, skb->len);
+ db->stats.tx_bytes += skb->len;
+
+ /* TX control: First packet immediately send, second packet queue */
+ if (db->tx_pkt_cnt == 0) {
+
+ /* First Packet */
+ db->tx_pkt_cnt++;
+
+ /* Set TX length to DM9000 */
+ iow(db, DM9000_TXPLL, skb->len & 0xff);
+ iow(db, DM9000_TXPLH, (skb->len >> 8) & 0xff);
+
+ /* Issue TX polling command */
+ iow(db, DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */
+
+ dev->trans_start = jiffies; /* save the time stamp */
+
+ } else {
+ /* Second packet */
+ db->tx_pkt_cnt++;
+ db->queue_pkt_len = skb->len;
+ }
+
+ /* free this SKB */
+ dev_kfree_skb(skb);
+
+ /* Re-enable resource check */
+ if (db->tx_pkt_cnt == 1)
+ netif_wake_queue(dev);
+
+ /* Re-enable interrupt */
+ iow(db, DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM);
+
+ return 0;
+}
+
+static void
+dm9000_shutdown(struct net_device *dev)
+{
+ board_info_t *db = (board_info_t *) dev->priv;
+
+ /* RESET device */
+ dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */
+ iow(db, DM9000_GPR, 0x01); /* Power-Down PHY */
+ iow(db, DM9000_IMR, IMR_PAR); /* Disable all interrupt */
+ iow(db, DM9000_RCR, 0x00); /* Disable RX */
+}
+
+/*
+ * Stop the interface.
+ * The interface is stopped when it is brought.
+ */
+static int
+dm9000_stop(struct net_device *ndev)
+{
+ board_info_t *db = (board_info_t *) ndev->priv;
+
+ PRINTK1("entering %s\n",__FUNCTION__);
+
+ /* deleted timer */
+ del_timer(&db->timer);
+
+ netif_stop_queue(ndev);
+ netif_carrier_off(ndev);
+
+ /* free interrupt */
+ free_irq(ndev->irq, ndev);
+
+ dm9000_shutdown(ndev);
+
+ return 0;
+}
+
+/*
+ * DM9000 interrupt handler
+ * receive the packet to upper layer, free the transmitted packet
+ */
+
+void
+dm9000_tx_done(struct net_device *dev, board_info_t * db)
+{
+ int tx_status = ior(db, DM9000_NSR); /* Got TX status */
+
+ if (tx_status & (NSR_TX2END | NSR_TX1END)) {
+ /* One packet sent complete */
+ db->tx_pkt_cnt--;
+ db->stats.tx_packets++;
+
+ /* Queue packet check & send */
+ if (db->tx_pkt_cnt > 0) {
+ iow(db, DM9000_TXPLL, db->queue_pkt_len & 0xff);
+ iow(db, DM9000_TXPLH, (db->queue_pkt_len >> 8) & 0xff);
+ iow(db, DM9000_TCR, TCR_TXREQ);
+ dev->trans_start = jiffies;
+ }
+ netif_wake_queue(dev);
+ }
+}
+
+static irqreturn_t
+dm9000_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+ board_info_t *db;
+ int int_status;
+ u8 reg_save;
+
+ PRINTK3("entering %s\n",__FUNCTION__);
+
+ if (!dev) {
+ PRINTK1("dm9000_interrupt() without DEVICE arg\n");
+ return IRQ_HANDLED;
+ }
+
+ /* A real interrupt coming */
+ db = (board_info_t *) dev->priv;
+ spin_lock(&db->lock);
+
+ /* Save previous register address */
+ reg_save = readb(db->io_addr);
+
+ /* Disable all interrupts */
+ iow(db, DM9000_IMR, IMR_PAR);
+
+ /* Got DM9000 interrupt status */
+ int_status = ior(db, DM9000_ISR); /* Got ISR */
+ iow(db, DM9000_ISR, int_status); /* Clear ISR status */
+
+ /* Received the coming packet */
+ if (int_status & ISR_PRS)
+ dm9000_rx(dev);
+
+ /* Trnasmit Interrupt check */
+ if (int_status & ISR_PTS)
+ dm9000_tx_done(dev, db);
+
+ /* Re-enable interrupt mask */
+ iow(db, DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM);
+
+ /* Restore previous register address */
+ writeb(reg_save, db->io_addr);
+
+ spin_unlock(&db->lock);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * Get statistics from driver.
+ */
+static struct net_device_stats *
+dm9000_get_stats(struct net_device *dev)
+{
+ board_info_t *db = (board_info_t *) dev->priv;
+ return &db->stats;
+}
+
+/*
+ * Process the upper socket ioctl command
+ */
+static int
+dm9000_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ PRINTK1("entering %s\n",__FUNCTION__);
+ return 0;
+}
+
+/*
+ * A periodic timer routine
+ * Dynamic media sense, allocated Rx buffer...
+ */
+static void
+dm9000_timer(unsigned long data)
+{
+ struct net_device *dev = (struct net_device *) data;
+ board_info_t *db = (board_info_t *) dev->priv;
+ u8 reg_save;
+ unsigned long flags;
+
+ PRINTK3("dm9000_timer()\n");
+
+ spin_lock_irqsave(db->lock,flags);
+ /* Save previous register address */
+ reg_save = readb(db->io_addr);
+
+ mii_check_media(&db->mii, netif_msg_link(db), 0);
+
+ /* Restore previous register address */
+ writeb(reg_save, db->io_addr);
+ spin_unlock_irqrestore(db->lock,flags);
+
+ /* Set timer again */
+ db->timer.expires = DM9000_TIMER_WUT;
+ add_timer(&db->timer);
+}
+
+struct dm9000_rxhdr {
+ u16 RxStatus;
+ u16 RxLen;
+} __attribute__((__packed__));
+
+/*
+ * Received a packet and pass to upper layer
+ */
+static void
+dm9000_rx(struct net_device *dev)
+{
+ board_info_t *db = (board_info_t *) dev->priv;
+ struct dm9000_rxhdr rxhdr;
+ struct sk_buff *skb;
+ u8 rxbyte, *rdptr;
+ int GoodPacket;
+ int RxLen;
+
+ /* Check packet ready or not */
+ do {
+ ior(db, DM9000_MRCMDX); /* Dummy read */
+
+ /* Get most updated data */
+ rxbyte = readb(db->io_data);
+
+ /* Status check: this byte must be 0 or 1 */
+ if (rxbyte > DM9000_PKT_RDY) {
+ printk("status check failed: %d\n", rxbyte);
+ iow(db, DM9000_RCR, 0x00); /* Stop Device */
+ iow(db, DM9000_ISR, IMR_PAR); /* Stop INT request */
+ return;
+ }
+
+ if (rxbyte != DM9000_PKT_RDY)
+ return;
+
+ /* A packet ready now & Get status/length */
+ GoodPacket = TRUE;
+ writeb(DM9000_MRCMD, db->io_addr);
+
+ (db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr));
+
+ RxLen = rxhdr.RxLen;
+
+ /* Packet Status check */
+ if (RxLen < 0x40) {
+ GoodPacket = FALSE;
+ PRINTK1("Bad Packet received (runt)\n");
+ }
+
+ if (RxLen > DM9000_PKT_MAX) {
+ PRINTK1("RST: RX Len:%x\n", RxLen);
+ }
+
+ if (rxhdr.RxStatus & 0xbf00) {
+ GoodPacket = FALSE;
+ if (rxhdr.RxStatus & 0x100) {
+ PRINTK1("fifo error\n");
+ db->stats.rx_fifo_errors++;
+ }
+ if (rxhdr.RxStatus & 0x200) {
+ PRINTK1("crc error\n");
+ db->stats.rx_crc_errors++;
+ }
+ if (rxhdr.RxStatus & 0x8000) {
+ PRINTK1("length error\n");
+ db->stats.rx_length_errors++;
+ }
+ }
+
+ /* Move data from DM9000 */
+ if (GoodPacket
+ && ((skb = dev_alloc_skb(RxLen + 4)) != NULL)) {
+ skb->dev = dev;
+ skb_reserve(skb, 2);
+ rdptr = (u8 *) skb_put(skb, RxLen - 4);
+
+ /* Read received packet from RX SRAM */
+
+ (db->inblk)(db->io_data, rdptr, RxLen);
+ db->stats.rx_bytes += RxLen;
+
+ /* Pass to upper layer */
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb);
+ db->stats.rx_packets++;
+
+ } else {
+ /* need to dump the packet's data */
+
+ (db->dumpblk)(db->io_data, RxLen);
+ }
+ } while (rxbyte == DM9000_PKT_RDY);
+}
+
+/*
+ * Read a word data from SROM
+ */
+static u16
+read_srom_word(board_info_t * db, int offset)
+{
+ iow(db, DM9000_EPAR, offset);
+ iow(db, DM9000_EPCR, EPCR_ERPRR);
+ mdelay(8); /* according to the datasheet 200us should be enough,
+ but it doesn't work */
+ iow(db, DM9000_EPCR, 0x0);
+ return (ior(db, DM9000_EPDRL) + (ior(db, DM9000_EPDRH) << 8));
+}
+
+#ifdef DM9000_PROGRAM_EEPROM
+/*
+ * Write a word data to SROM
+ */
+static void
+write_srom_word(board_info_t * db, int offset, u16 val)
+{
+ iow(db, DM9000_EPAR, offset);
+ iow(db, DM9000_EPDRH, ((val >> 8) & 0xff));
+ iow(db, DM9000_EPDRL, (val & 0xff));
+ iow(db, DM9000_EPCR, EPCR_WEP | EPCR_ERPRW);
+ mdelay(8); /* same shit */
+ iow(db, DM9000_EPCR, 0);
+}
+
+/*
+ * Only for development:
+ * Here we write static data to the eeprom in case
+ * we don't have valid content on a new board
+ */
+static void
+program_eeprom(board_info_t * db)
+{
+ u16 eeprom[] = { 0x0c00, 0x007f, 0x1300, /* MAC Address */
+ 0x0000, /* Autoload: accept nothing */
+ 0x0a46, 0x9000, /* Vendor / Product ID */
+ 0x0000, /* pin control */
+ 0x0000,
+ }; /* Wake-up mode control */
+ int i;
+ for (i = 0; i < 8; i++)
+ write_srom_word(db, i, eeprom[i]);
+}
+#endif
+
+
+/*
+ * Calculate the CRC valude of the Rx packet
+ * flag = 1 : return the reverse CRC (for the received packet CRC)
+ * 0 : return the normal CRC (for Hash Table index)
+ */
+
+static unsigned long
+cal_CRC(unsigned char *Data, unsigned int Len, u8 flag)
+{
+
+ u32 crc = ether_crc_le(Len, Data);
+
+ if (flag)
+ return ~crc;
+
+ return crc;
+}
+
+/*
+ * Set DM9000 multicast address
+ */
+static void
+dm9000_hash_table(struct net_device *dev)
+{
+ board_info_t *db = (board_info_t *) dev->priv;
+ struct dev_mc_list *mcptr = dev->mc_list;
+ int mc_cnt = dev->mc_count;
+ u32 hash_val;
+ u16 i, oft, hash_table[4];
+ unsigned long flags;
+
+ PRINTK2("dm9000_hash_table()\n");
+
+ spin_lock_irqsave(&db->lock,flags);
+
+ for (i = 0, oft = 0x10; i < 6; i++, oft++)
+ iow(db, oft, dev->dev_addr[i]);
+
+ /* Clear Hash Table */
+ for (i = 0; i < 4; i++)
+ hash_table[i] = 0x0;
+
+ /* broadcast address */
+ hash_table[3] = 0x8000;
+
+ /* the multicast address in Hash Table : 64 bits */
+ for (i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
+ hash_val = cal_CRC((char *) mcptr->dmi_addr, 6, 0) & 0x3f;
+ hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16);
+ }
+
+ /* Write the hash table to MAC MD table */
+ for (i = 0, oft = 0x16; i < 4; i++) {
+ iow(db, oft++, hash_table[i] & 0xff);
+ iow(db, oft++, (hash_table[i] >> 8) & 0xff);
+ }
+
+ spin_unlock_irqrestore(&db->lock,flags);
+}
+
+
+/*
+ * Read a word from phyxcer
+ */
+static int
+dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
+{
+ board_info_t *db = (board_info_t *) dev->priv;
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&db->lock,flags);
+ /* Fill the phyxcer register into REG_0C */
+ iow(db, DM9000_EPAR, DM9000_PHY | reg);
+
+ iow(db, DM9000_EPCR, 0xc); /* Issue phyxcer read command */
+ udelay(100); /* Wait read complete */
+ iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer read command */
+
+ /* The read data keeps on REG_0D & REG_0E */
+ ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL);
+
+ spin_unlock_irqrestore(&db->lock,flags);
+
+ return ret;
+}
+
+/*
+ * Write a word to phyxcer
+ */
+static void
+dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value)
+{
+ board_info_t *db = (board_info_t *) dev->priv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&db->lock,flags);
+
+ /* Fill the phyxcer register into REG_0C */
+ iow(db, DM9000_EPAR, DM9000_PHY | reg);
+
+ /* Fill the written data into REG_0D & REG_0E */
+ iow(db, DM9000_EPDRL, (value & 0xff));
+ iow(db, DM9000_EPDRH, ((value >> 8) & 0xff));
+
+ iow(db, DM9000_EPCR, 0xa); /* Issue phyxcer write command */
+ udelay(500); /* Wait write complete */
+ iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer write command */
+
+ spin_unlock_irqrestore(&db->lock,flags);
+}
+
+static int
+dm9000_drv_suspend(struct device *dev, u32 state, u32 level)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+
+ if (ndev && level == SUSPEND_DISABLE) {
+ if (netif_running(ndev)) {
+ netif_device_detach(ndev);
+ dm9000_shutdown(ndev);
+ }
+ }
+ return 0;
+}
+
+static int
+dm9000_drv_resume(struct device *dev, u32 level)
+{
+ struct net_device *ndev = dev_get_drvdata(dev);
+ board_info_t *db = (board_info_t *) ndev->priv;
+
+ if (ndev && level == RESUME_ENABLE) {
+
+ if (netif_running(ndev)) {
+ dm9000_reset(db);
+ dm9000_init_dm9000(ndev);
+
+ netif_device_attach(ndev);
+ }
+ }
+ return 0;
+}
+
+static int
+dm9000_drv_remove(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct net_device *ndev = dev_get_drvdata(dev);
+
+ dev_set_drvdata(dev, NULL);
+
+ unregister_netdev(ndev);
+ dm9000_release_board(pdev, (board_info_t *) ndev->priv);
+ kfree(ndev); /* free device structure */
+
+ PRINTK1("clean_module() exit\n");
+
+ return 0;
+}
+
+static struct device_driver dm9000_driver = {
+ .name = "dm9000",
+ .bus = &platform_bus_type,
+ .probe = dm9000_probe,
+ .remove = dm9000_drv_remove,
+ .suspend = dm9000_drv_suspend,
+ .resume = dm9000_drv_resume,
+};
+
+static int __init
+dm9000_init(void)
+{
+ return driver_register(&dm9000_driver); /* search board and register */
+}
+
+static void __exit
+dm9000_cleanup(void)
+{
+ driver_unregister(&dm9000_driver);
+}
+
+module_init(dm9000_init);
+module_exit(dm9000_cleanup);
+
+MODULE_AUTHOR("Sascha Hauer, Ben Dooks");
+MODULE_DESCRIPTION("Davicom DM9000 network driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/dm9000.h b/drivers/net/dm9000.h
new file mode 100644
index 00000000000..82cad360baf
--- /dev/null
+++ b/drivers/net/dm9000.h
@@ -0,0 +1,135 @@
+/*
+ * dm9000 Ethernet
+ */
+
+#ifndef _DM9000X_H_
+#define _DM9000X_H_
+
+#define DM9000_ID 0x90000A46
+
+/* although the registers are 16 bit, they are 32-bit aligned.
+ */
+
+#define DM9000_NCR 0x00
+#define DM9000_NSR 0x01
+#define DM9000_TCR 0x02
+#define DM9000_TSR1 0x03
+#define DM9000_TSR2 0x04
+#define DM9000_RCR 0x05
+#define DM9000_RSR 0x06
+#define DM9000_ROCR 0x07
+#define DM9000_BPTR 0x08
+#define DM9000_FCTR 0x09
+#define DM9000_FCR 0x0A
+#define DM9000_EPCR 0x0B
+#define DM9000_EPAR 0x0C
+#define DM9000_EPDRL 0x0D
+#define DM9000_EPDRH 0x0E
+#define DM9000_WCR 0x0F
+
+#define DM9000_PAR 0x10
+#define DM9000_MAR 0x16
+
+#define DM9000_GPCR 0x1e
+#define DM9000_GPR 0x1f
+#define DM9000_TRPAL 0x22
+#define DM9000_TRPAH 0x23
+#define DM9000_RWPAL 0x24
+#define DM9000_RWPAH 0x25
+
+#define DM9000_VIDL 0x28
+#define DM9000_VIDH 0x29
+#define DM9000_PIDL 0x2A
+#define DM9000_PIDH 0x2B
+
+#define DM9000_CHIPR 0x2C
+#define DM9000_SMCR 0x2F
+
+#define DM9000_MRCMDX 0xF0
+#define DM9000_MRCMD 0xF2
+#define DM9000_MRRL 0xF4
+#define DM9000_MRRH 0xF5
+#define DM9000_MWCMDX 0xF6
+#define DM9000_MWCMD 0xF8
+#define DM9000_MWRL 0xFA
+#define DM9000_MWRH 0xFB
+#define DM9000_TXPLL 0xFC
+#define DM9000_TXPLH 0xFD
+#define DM9000_ISR 0xFE
+#define DM9000_IMR 0xFF
+
+#define NCR_EXT_PHY (1<<7)
+#define NCR_WAKEEN (1<<6)
+#define NCR_FCOL (1<<4)
+#define NCR_FDX (1<<3)
+#define NCR_LBK (3<<1)
+#define NCR_RST (1<<0)
+
+#define NSR_SPEED (1<<7)
+#define NSR_LINKST (1<<6)
+#define NSR_WAKEST (1<<5)
+#define NSR_TX2END (1<<3)
+#define NSR_TX1END (1<<2)
+#define NSR_RXOV (1<<1)
+
+#define TCR_TJDIS (1<<6)
+#define TCR_EXCECM (1<<5)
+#define TCR_PAD_DIS2 (1<<4)
+#define TCR_CRC_DIS2 (1<<3)
+#define TCR_PAD_DIS1 (1<<2)
+#define TCR_CRC_DIS1 (1<<1)
+#define TCR_TXREQ (1<<0)
+
+#define TSR_TJTO (1<<7)
+#define TSR_LC (1<<6)
+#define TSR_NC (1<<5)
+#define TSR_LCOL (1<<4)
+#define TSR_COL (1<<3)
+#define TSR_EC (1<<2)
+
+#define RCR_WTDIS (1<<6)
+#define RCR_DIS_LONG (1<<5)
+#define RCR_DIS_CRC (1<<4)
+#define RCR_ALL (1<<3)
+#define RCR_RUNT (1<<2)
+#define RCR_PRMSC (1<<1)
+#define RCR_RXEN (1<<0)
+
+#define RSR_RF (1<<7)
+#define RSR_MF (1<<6)
+#define RSR_LCS (1<<5)
+#define RSR_RWTO (1<<4)
+#define RSR_PLE (1<<3)
+#define RSR_AE (1<<2)
+#define RSR_CE (1<<1)
+#define RSR_FOE (1<<0)
+
+#define FCTR_HWOT(ot) (( ot & 0xf ) << 4 )
+#define FCTR_LWOT(ot) ( ot & 0xf )
+
+#define IMR_PAR (1<<7)
+#define IMR_ROOM (1<<3)
+#define IMR_ROM (1<<2)
+#define IMR_PTM (1<<1)
+#define IMR_PRM (1<<0)
+
+#define ISR_ROOS (1<<3)
+#define ISR_ROS (1<<2)
+#define ISR_PTS (1<<1)
+#define ISR_PRS (1<<0)
+#define ISR_CLR_STATUS (ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS)
+
+#define EPCR_REEP (1<<5)
+#define EPCR_WEP (1<<4)
+#define EPCR_EPOS (1<<3)
+#define EPCR_ERPRR (1<<2)
+#define EPCR_ERPRW (1<<1)
+#define EPCR_ERRE (1<<0)
+
+#define GPCR_GEP_CNTL (1<<0)
+
+#define DM9000_PKT_RDY 0x01 /* Packet ready to receive */
+#define DM9000_PKT_MAX 1536 /* Received packet max size */
+
+#endif /* _DM9000X_H_ */
+
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 1b68dd5a49b..4a47df5a9ff 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -155,9 +155,9 @@
#define DRV_NAME "e100"
#define DRV_EXT "-NAPI"
-#define DRV_VERSION "3.3.6-k2"DRV_EXT
+#define DRV_VERSION "3.4.8-k2"DRV_EXT
#define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver"
-#define DRV_COPYRIGHT "Copyright(c) 1999-2004 Intel Corporation"
+#define DRV_COPYRIGHT "Copyright(c) 1999-2005 Intel Corporation"
#define PFX DRV_NAME ": "
#define E100_WATCHDOG_PERIOD (2 * HZ)
@@ -210,11 +210,17 @@ static struct pci_device_id e100_id_table[] = {
INTEL_8255X_ETHERNET_DEVICE(0x1069, 6),
INTEL_8255X_ETHERNET_DEVICE(0x106A, 6),
INTEL_8255X_ETHERNET_DEVICE(0x106B, 6),
+ INTEL_8255X_ETHERNET_DEVICE(0x1091, 7),
+ INTEL_8255X_ETHERNET_DEVICE(0x1092, 7),
+ INTEL_8255X_ETHERNET_DEVICE(0x1093, 7),
+ INTEL_8255X_ETHERNET_DEVICE(0x1094, 7),
+ INTEL_8255X_ETHERNET_DEVICE(0x1095, 7),
INTEL_8255X_ETHERNET_DEVICE(0x1209, 0),
INTEL_8255X_ETHERNET_DEVICE(0x1229, 0),
INTEL_8255X_ETHERNET_DEVICE(0x2449, 2),
INTEL_8255X_ETHERNET_DEVICE(0x2459, 2),
INTEL_8255X_ETHERNET_DEVICE(0x245D, 2),
+ INTEL_8255X_ETHERNET_DEVICE(0x27DC, 7),
{ 0, }
};
MODULE_DEVICE_TABLE(pci, e100_id_table);
@@ -269,6 +275,12 @@ enum scb_status {
rus_mask = 0x3C,
};
+enum ru_state {
+ RU_SUSPENDED = 0,
+ RU_RUNNING = 1,
+ RU_UNINITIALIZED = -1,
+};
+
enum scb_stat_ack {
stat_ack_not_ours = 0x00,
stat_ack_sw_gen = 0x04,
@@ -510,7 +522,7 @@ struct nic {
struct rx *rx_to_use;
struct rx *rx_to_clean;
struct rfd blank_rfd;
- int ru_running;
+ enum ru_state ru_running;
spinlock_t cb_lock ____cacheline_aligned;
spinlock_t cmd_lock;
@@ -539,6 +551,7 @@ struct nic {
struct timer_list watchdog;
struct timer_list blink_timer;
struct mii_if_info mii;
+ struct work_struct tx_timeout_task;
enum loopback loopback;
struct mem *mem;
@@ -770,7 +783,7 @@ static int e100_eeprom_save(struct nic *nic, u16 start, u16 count)
return 0;
}
-#define E100_WAIT_SCB_TIMEOUT 40
+#define E100_WAIT_SCB_TIMEOUT 20000 /* we might have to wait 100ms!!! */
static inline int e100_exec_cmd(struct nic *nic, u8 cmd, dma_addr_t dma_addr)
{
unsigned long flags;
@@ -840,6 +853,10 @@ static inline int e100_exec_cb(struct nic *nic, struct sk_buff *skb,
* because the controller is too busy, so
* let's just queue the command and try again
* when another command is scheduled. */
+ if(err == -ENOSPC) {
+ //request a reset
+ schedule_work(&nic->tx_timeout_task);
+ }
break;
} else {
nic->cuc_cmd = cuc_resume;
@@ -884,7 +901,7 @@ static void mdio_write(struct net_device *netdev, int addr, int reg, int data)
static void e100_get_defaults(struct nic *nic)
{
- struct param_range rfds = { .min = 64, .max = 256, .count = 64 };
+ struct param_range rfds = { .min = 16, .max = 256, .count = 64 };
struct param_range cbs = { .min = 64, .max = 256, .count = 64 };
pci_read_config_byte(nic->pdev, PCI_REVISION_ID, &nic->rev_id);
@@ -899,8 +916,9 @@ static void e100_get_defaults(struct nic *nic)
/* Quadwords to DMA into FIFO before starting frame transmit */
nic->tx_threshold = 0xE0;
- nic->tx_command = cpu_to_le16(cb_tx | cb_i | cb_tx_sf |
- ((nic->mac >= mac_82558_D101_A4) ? cb_cid : 0));
+ /* no interrupt for every tx completion, delay = 256us if not 557*/
+ nic->tx_command = cpu_to_le16(cb_tx | cb_tx_sf |
+ ((nic->mac >= mac_82558_D101_A4) ? cb_cid : cb_i));
/* Template for a freshly allocated RFD */
nic->blank_rfd.command = cpu_to_le16(cb_el);
@@ -964,7 +982,8 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
if(nic->flags & multicast_all)
config->multicast_all = 0x1; /* 1=accept, 0=no */
- if(!(nic->flags & wol_magic))
+ /* disable WoL when up */
+ if(netif_running(nic->netdev) || !(nic->flags & wol_magic))
config->magic_packet_disable = 0x1; /* 1=off, 0=on */
if(nic->mac >= mac_82558_D101_A4) {
@@ -1203,7 +1222,9 @@ static void e100_update_stats(struct nic *nic)
}
}
- e100_exec_cmd(nic, cuc_dump_reset, 0);
+
+ if(e100_exec_cmd(nic, cuc_dump_reset, 0))
+ DPRINTK(TX_ERR, DEBUG, "exec cuc_dump_reset failed\n");
}
static void e100_adjust_adaptive_ifs(struct nic *nic, int speed, int duplex)
@@ -1279,12 +1300,15 @@ static inline void e100_xmit_prepare(struct nic *nic, struct cb *cb,
struct sk_buff *skb)
{
cb->command = nic->tx_command;
+ /* interrupt every 16 packets regardless of delay */
+ if((nic->cbs_avail & ~15) == nic->cbs_avail) cb->command |= cb_i;
cb->u.tcb.tbd_array = cb->dma_addr + offsetof(struct cb, u.tcb.tbd);
cb->u.tcb.tcb_byte_count = 0;
cb->u.tcb.threshold = nic->tx_threshold;
cb->u.tcb.tbd_count = 1;
cb->u.tcb.tbd.buf_addr = cpu_to_le32(pci_map_single(nic->pdev,
skb->data, skb->len, PCI_DMA_TODEVICE));
+ // check for mapping failure?
cb->u.tcb.tbd.size = cpu_to_le16(skb->len);
}
@@ -1297,7 +1321,8 @@ static int e100_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
/* SW workaround for ICH[x] 10Mbps/half duplex Tx hang.
Issue a NOP command followed by a 1us delay before
issuing the Tx command. */
- e100_exec_cmd(nic, cuc_nop, 0);
+ if(e100_exec_cmd(nic, cuc_nop, 0))
+ DPRINTK(TX_ERR, DEBUG, "exec cuc_nop failed\n");
udelay(1);
}
@@ -1415,12 +1440,18 @@ static int e100_alloc_cbs(struct nic *nic)
return 0;
}
-static inline void e100_start_receiver(struct nic *nic)
+static inline void e100_start_receiver(struct nic *nic, struct rx *rx)
{
+ if(!nic->rxs) return;
+ if(RU_SUSPENDED != nic->ru_running) return;
+
+ /* handle init time starts */
+ if(!rx) rx = nic->rxs;
+
/* (Re)start RU if suspended or idle and RFA is non-NULL */
- if(!nic->ru_running && nic->rx_to_clean->skb) {
- e100_exec_cmd(nic, ruc_start, nic->rx_to_clean->dma_addr);
- nic->ru_running = 1;
+ if(rx->skb) {
+ e100_exec_cmd(nic, ruc_start, rx->dma_addr);
+ nic->ru_running = RU_RUNNING;
}
}
@@ -1437,6 +1468,13 @@ static inline int e100_rx_alloc_skb(struct nic *nic, struct rx *rx)
rx->dma_addr = pci_map_single(nic->pdev, rx->skb->data,
RFD_BUF_LEN, PCI_DMA_BIDIRECTIONAL);
+ if(pci_dma_mapping_error(rx->dma_addr)) {
+ dev_kfree_skb_any(rx->skb);
+ rx->skb = 0;
+ rx->dma_addr = 0;
+ return -ENOMEM;
+ }
+
/* Link the RFD to end of RFA by linking previous RFD to
* this one, and clearing EL bit of previous. */
if(rx->prev->skb) {
@@ -1471,7 +1509,7 @@ static inline int e100_rx_indicate(struct nic *nic, struct rx *rx,
/* If data isn't ready, nothing to indicate */
if(unlikely(!(rfd_status & cb_complete)))
- return -EAGAIN;
+ return -ENODATA;
/* Get actual data size */
actual_size = le16_to_cpu(rfd->actual_size) & 0x3FFF;
@@ -1482,6 +1520,10 @@ static inline int e100_rx_indicate(struct nic *nic, struct rx *rx,
pci_unmap_single(nic->pdev, rx->dma_addr,
RFD_BUF_LEN, PCI_DMA_FROMDEVICE);
+ /* this allows for a fast restart without re-enabling interrupts */
+ if(le16_to_cpu(rfd->command) & cb_el)
+ nic->ru_running = RU_SUSPENDED;
+
/* Pull off the RFD and put the actual data (minus eth hdr) */
skb_reserve(skb, sizeof(struct rfd));
skb_put(skb, actual_size);
@@ -1514,20 +1556,45 @@ static inline void e100_rx_clean(struct nic *nic, unsigned int *work_done,
unsigned int work_to_do)
{
struct rx *rx;
+ int restart_required = 0;
+ struct rx *rx_to_start = NULL;
+
+ /* are we already rnr? then pay attention!!! this ensures that
+ * the state machine progression never allows a start with a
+ * partially cleaned list, avoiding a race between hardware
+ * and rx_to_clean when in NAPI mode */
+ if(RU_SUSPENDED == nic->ru_running)
+ restart_required = 1;
/* Indicate newly arrived packets */
for(rx = nic->rx_to_clean; rx->skb; rx = nic->rx_to_clean = rx->next) {
- if(e100_rx_indicate(nic, rx, work_done, work_to_do))
+ int err = e100_rx_indicate(nic, rx, work_done, work_to_do);
+ if(-EAGAIN == err) {
+ /* hit quota so have more work to do, restart once
+ * cleanup is complete */
+ restart_required = 0;
+ break;
+ } else if(-ENODATA == err)
break; /* No more to clean */
}
+ /* save our starting point as the place we'll restart the receiver */
+ if(restart_required)
+ rx_to_start = nic->rx_to_clean;
+
/* Alloc new skbs to refill list */
for(rx = nic->rx_to_use; !rx->skb; rx = nic->rx_to_use = rx->next) {
if(unlikely(e100_rx_alloc_skb(nic, rx)))
break; /* Better luck next time (see watchdog) */
}
- e100_start_receiver(nic);
+ if(restart_required) {
+ // ack the rnr?
+ writeb(stat_ack_rnr, &nic->csr->scb.stat_ack);
+ e100_start_receiver(nic, rx_to_start);
+ if(work_done)
+ (*work_done)++;
+ }
}
static void e100_rx_clean_list(struct nic *nic)
@@ -1535,6 +1602,8 @@ static void e100_rx_clean_list(struct nic *nic)
struct rx *rx;
unsigned int i, count = nic->params.rfds.count;
+ nic->ru_running = RU_UNINITIALIZED;
+
if(nic->rxs) {
for(rx = nic->rxs, i = 0; i < count; rx++, i++) {
if(rx->skb) {
@@ -1548,7 +1617,6 @@ static void e100_rx_clean_list(struct nic *nic)
}
nic->rx_to_use = nic->rx_to_clean = NULL;
- nic->ru_running = 0;
}
static int e100_rx_alloc_list(struct nic *nic)
@@ -1557,6 +1625,7 @@ static int e100_rx_alloc_list(struct nic *nic)
unsigned int i, count = nic->params.rfds.count;
nic->rx_to_use = nic->rx_to_clean = NULL;
+ nic->ru_running = RU_UNINITIALIZED;
if(!(nic->rxs = kmalloc(sizeof(struct rx) * count, GFP_ATOMIC)))
return -ENOMEM;
@@ -1572,6 +1641,7 @@ static int e100_rx_alloc_list(struct nic *nic)
}
nic->rx_to_use = nic->rx_to_clean = nic->rxs;
+ nic->ru_running = RU_SUSPENDED;
return 0;
}
@@ -1593,7 +1663,7 @@ static irqreturn_t e100_intr(int irq, void *dev_id, struct pt_regs *regs)
/* We hit Receive No Resource (RNR); restart RU after cleaning */
if(stat_ack & stat_ack_rnr)
- nic->ru_running = 0;
+ nic->ru_running = RU_SUSPENDED;
e100_disable_irq(nic);
netif_rx_schedule(netdev);
@@ -1663,6 +1733,7 @@ static int e100_change_mtu(struct net_device *netdev, int new_mtu)
return 0;
}
+#ifdef CONFIG_PM
static int e100_asf(struct nic *nic)
{
/* ASF can be enabled from eeprom */
@@ -1671,6 +1742,7 @@ static int e100_asf(struct nic *nic)
!(nic->eeprom[eeprom_config_asf] & eeprom_gcl) &&
((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE));
}
+#endif
static int e100_up(struct nic *nic)
{
@@ -1683,13 +1755,16 @@ static int e100_up(struct nic *nic)
if((err = e100_hw_init(nic)))
goto err_clean_cbs;
e100_set_multicast_list(nic->netdev);
- e100_start_receiver(nic);
+ e100_start_receiver(nic, 0);
mod_timer(&nic->watchdog, jiffies);
if((err = request_irq(nic->pdev->irq, e100_intr, SA_SHIRQ,
nic->netdev->name, nic->netdev)))
goto err_no_irq;
- e100_enable_irq(nic);
netif_wake_queue(nic->netdev);
+ netif_poll_enable(nic->netdev);
+ /* enable ints _after_ enabling poll, preventing a race between
+ * disable ints+schedule */
+ e100_enable_irq(nic);
return 0;
err_no_irq:
@@ -1703,11 +1778,13 @@ err_rx_clean_list:
static void e100_down(struct nic *nic)
{
+ /* wait here for poll to complete */
+ netif_poll_disable(nic->netdev);
+ netif_stop_queue(nic->netdev);
e100_hw_reset(nic);
free_irq(nic->pdev->irq, nic->netdev);
del_timer_sync(&nic->watchdog);
netif_carrier_off(nic->netdev);
- netif_stop_queue(nic->netdev);
e100_clean_cbs(nic);
e100_rx_clean_list(nic);
}
@@ -1716,6 +1793,15 @@ static void e100_tx_timeout(struct net_device *netdev)
{
struct nic *nic = netdev_priv(netdev);
+ /* Reset outside of interrupt context, to avoid request_irq
+ * in interrupt context */
+ schedule_work(&nic->tx_timeout_task);
+}
+
+static void e100_tx_timeout_task(struct net_device *netdev)
+{
+ struct nic *nic = netdev_priv(netdev);
+
DPRINTK(TX_ERR, DEBUG, "scb.status=0x%02X\n",
readb(&nic->csr->scb.status));
e100_down(netdev_priv(netdev));
@@ -1749,7 +1835,7 @@ static int e100_loopback_test(struct nic *nic, enum loopback loopback_mode)
mdio_write(nic->netdev, nic->mii.phy_id, MII_BMCR,
BMCR_LOOPBACK);
- e100_start_receiver(nic);
+ e100_start_receiver(nic, 0);
if(!(skb = dev_alloc_skb(ETH_DATA_LEN))) {
err = -ENOMEM;
@@ -1869,7 +1955,6 @@ static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
else
nic->flags &= ~wol_magic;
- pci_enable_wake(nic->pdev, 0, nic->flags & (wol_magic | e100_asf(nic)));
e100_exec_cb(nic, NULL, e100_configure);
return 0;
@@ -2223,6 +2308,7 @@ static int __devinit e100_probe(struct pci_dev *pdev,
e100_get_defaults(nic);
+ /* locks must be initialized before calling hw_reset */
spin_lock_init(&nic->cb_lock);
spin_lock_init(&nic->cmd_lock);
@@ -2240,6 +2326,9 @@ static int __devinit e100_probe(struct pci_dev *pdev,
nic->blink_timer.function = e100_blink_led;
nic->blink_timer.data = (unsigned long)nic;
+ INIT_WORK(&nic->tx_timeout_task,
+ (void (*)(void *))e100_tx_timeout_task, netdev);
+
if((err = e100_alloc(nic))) {
DPRINTK(PROBE, ERR, "Cannot alloc driver memory, aborting.\n");
goto err_out_iounmap;
@@ -2263,7 +2352,8 @@ static int __devinit e100_probe(struct pci_dev *pdev,
(nic->eeprom[eeprom_id] & eeprom_id_wol))
nic->flags |= wol_magic;
- pci_enable_wake(pdev, 0, nic->flags & (wol_magic | e100_asf(nic)));
+ /* ack any pending wake events, disable PME */
+ pci_enable_wake(pdev, 0, 0);
strcpy(netdev->name, "eth%d");
if((err = register_netdev(netdev))) {
@@ -2335,7 +2425,10 @@ static int e100_resume(struct pci_dev *pdev)
pci_set_power_state(pdev, PCI_D0);
pci_restore_state(pdev);
- e100_hw_init(nic);
+ /* ack any pending wake events, disable PME */
+ pci_enable_wake(pdev, 0, 0);
+ if(e100_hw_init(nic))
+ DPRINTK(HW, ERR, "e100_hw_init failed\n");
netif_device_attach(netdev);
if(netif_running(netdev))
@@ -2345,6 +2438,21 @@ static int e100_resume(struct pci_dev *pdev)
}
#endif
+
+static void e100_shutdown(struct device *dev)
+{
+ struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct nic *nic = netdev_priv(netdev);
+
+#ifdef CONFIG_PM
+ pci_enable_wake(pdev, 0, nic->flags & (wol_magic | e100_asf(nic)));
+#else
+ pci_enable_wake(pdev, 0, nic->flags & (wol_magic));
+#endif
+}
+
+
static struct pci_driver e100_driver = {
.name = DRV_NAME,
.id_table = e100_id_table,
@@ -2354,6 +2462,11 @@ static struct pci_driver e100_driver = {
.suspend = e100_suspend,
.resume = e100_resume,
#endif
+
+ .driver = {
+ .shutdown = e100_shutdown,
+ }
+
};
static int __init e100_init_module(void)
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 148930d4e9b..af1e82c5b80 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -1,7 +1,7 @@
/*******************************************************************************
- Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+ Copyright(c) 1999 - 2005 Intel Corporation. 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
@@ -112,6 +112,8 @@ struct e1000_adapter;
#define E1000_MAX_82544_RXD 4096
/* Supported Rx Buffer Sizes */
+#define E1000_RXBUFFER_128 128 /* Used for packet split */
+#define E1000_RXBUFFER_256 256 /* Used for packet split */
#define E1000_RXBUFFER_2048 2048
#define E1000_RXBUFFER_4096 4096
#define E1000_RXBUFFER_8192 8192
@@ -137,15 +139,19 @@ struct e1000_adapter;
/* How many Rx Buffers do we bundle into one write to the hardware ? */
#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */
-#define AUTO_ALL_MODES 0
-#define E1000_EEPROM_82544_APM 0x0004
-#define E1000_EEPROM_APME 0x0400
+#define AUTO_ALL_MODES 0
+#define E1000_EEPROM_82544_APM 0x0400
+#define E1000_EEPROM_APME 0x0400
#ifndef E1000_MASTER_SLAVE
/* Switch to override PHY master/slave setting */
#define E1000_MASTER_SLAVE e1000_ms_hw_default
#endif
+#define E1000_MNG_VLAN_NONE -1
+/* Number of packet split data buffers (not including the header buffer) */
+#define PS_PAGE_BUFFERS MAX_PS_BUFFERS-1
+
/* only works for sizes that are powers of 2 */
#define E1000_ROUNDUP(i, size) ((i) = (((i) + (size) - 1) & ~((size) - 1)))
@@ -159,6 +165,9 @@ struct e1000_buffer {
uint16_t next_to_watch;
};
+struct e1000_ps_page { struct page *ps_page[MAX_PS_BUFFERS]; };
+struct e1000_ps_page_dma { uint64_t ps_page_dma[MAX_PS_BUFFERS]; };
+
struct e1000_desc_ring {
/* pointer to the descriptor ring memory */
void *desc;
@@ -174,12 +183,19 @@ struct e1000_desc_ring {
unsigned int next_to_clean;
/* array of buffer information structs */
struct e1000_buffer *buffer_info;
+ /* arrays of page information for packet split */
+ struct e1000_ps_page *ps_page;
+ struct e1000_ps_page_dma *ps_page_dma;
};
#define E1000_DESC_UNUSED(R) \
((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \
(R)->next_to_clean - (R)->next_to_use - 1)
+#define E1000_RX_DESC_PS(R, i) \
+ (&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
+#define E1000_RX_DESC_EXT(R, i) \
+ (&(((union e1000_rx_desc_extended *)((R).desc))[i]))
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc)
#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc)
@@ -192,6 +208,7 @@ struct e1000_adapter {
struct timer_list watchdog_timer;
struct timer_list phy_info_timer;
struct vlan_group *vlgrp;
+ uint16_t mng_vlan_id;
uint32_t bd_number;
uint32_t rx_buffer_len;
uint32_t part_num;
@@ -228,14 +245,23 @@ struct e1000_adapter {
boolean_t detect_tx_hung;
/* RX */
+#ifdef CONFIG_E1000_NAPI
+ boolean_t (*clean_rx) (struct e1000_adapter *adapter, int *work_done,
+ int work_to_do);
+#else
+ boolean_t (*clean_rx) (struct e1000_adapter *adapter);
+#endif
+ void (*alloc_rx_buf) (struct e1000_adapter *adapter);
struct e1000_desc_ring rx_ring;
uint64_t hw_csum_err;
uint64_t hw_csum_good;
uint32_t rx_int_delay;
uint32_t rx_abs_int_delay;
boolean_t rx_csum;
+ boolean_t rx_ps;
uint32_t gorcl;
uint64_t gorcl_old;
+ uint16_t rx_ps_bsize0;
/* Interrupt Throttle Rate */
uint32_t itr;
@@ -257,5 +283,8 @@ struct e1000_adapter {
int msg_enable;
+#ifdef CONFIG_PCI_MSI
+ boolean_t have_msi;
+#endif
};
#endif /* _E1000_H_ */
diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
index 0a2ca7c73a4..237247f74df 100644
--- a/drivers/net/e1000/e1000_ethtool.c
+++ b/drivers/net/e1000/e1000_ethtool.c
@@ -1,7 +1,7 @@
/*******************************************************************************
- Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+ Copyright(c) 1999 - 2005 Intel Corporation. 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
@@ -69,6 +69,7 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
{ "rx_crc_errors", E1000_STAT(net_stats.rx_crc_errors) },
{ "rx_frame_errors", E1000_STAT(net_stats.rx_frame_errors) },
{ "rx_fifo_errors", E1000_STAT(net_stats.rx_fifo_errors) },
+ { "rx_no_buffer_count", E1000_STAT(stats.rnbc) },
{ "rx_missed_errors", E1000_STAT(net_stats.rx_missed_errors) },
{ "tx_aborted_errors", E1000_STAT(net_stats.tx_aborted_errors) },
{ "tx_carrier_errors", E1000_STAT(net_stats.tx_carrier_errors) },
@@ -593,7 +594,7 @@ e1000_set_ringparam(struct net_device *netdev,
tx_old = adapter->tx_ring;
rx_old = adapter->rx_ring;
- if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
+ if((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
return -EINVAL;
if(netif_running(adapter->netdev))
@@ -784,8 +785,8 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
/* Hook up test interrupt handler just for this test */
if(!request_irq(irq, &e1000_test_intr, 0, netdev->name, netdev)) {
shared_int = FALSE;
- } else if(request_irq(irq, &e1000_test_intr, SA_SHIRQ,
- netdev->name, netdev)){
+ } else if(request_irq(irq, &e1000_test_intr, SA_SHIRQ,
+ netdev->name, netdev)){
*data = 1;
return -1;
}
@@ -842,10 +843,8 @@ e1000_intr_test(struct e1000_adapter *adapter, uint64_t *data)
* test failed.
*/
adapter->test_icr = 0;
- E1000_WRITE_REG(&adapter->hw, IMC,
- (~mask & 0x00007FFF));
- E1000_WRITE_REG(&adapter->hw, ICS,
- (~mask & 0x00007FFF));
+ E1000_WRITE_REG(&adapter->hw, IMC, ~mask & 0x00007FFF);
+ E1000_WRITE_REG(&adapter->hw, ICS, ~mask & 0x00007FFF);
msec_delay(10);
if(adapter->test_icr) {
@@ -919,7 +918,8 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
/* Setup Tx descriptor ring and Tx buffers */
- txdr->count = 80;
+ if(!txdr->count)
+ txdr->count = E1000_DEFAULT_TXD;
size = txdr->count * sizeof(struct e1000_buffer);
if(!(txdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
@@ -974,7 +974,8 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
/* Setup Rx descriptor ring and Rx buffers */
- rxdr->count = 80;
+ if(!rxdr->count)
+ rxdr->count = E1000_DEFAULT_RXD;
size = rxdr->count * sizeof(struct e1000_buffer);
if(!(rxdr->buffer_info = kmalloc(size, GFP_KERNEL))) {
@@ -1008,7 +1009,7 @@ e1000_setup_desc_rings(struct e1000_adapter *adapter)
struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rxdr, i);
struct sk_buff *skb;
- if(!(skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN,
+ if(!(skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN,
GFP_KERNEL))) {
ret_val = 6;
goto err_nomem;
@@ -1310,31 +1311,62 @@ e1000_run_loopback_test(struct e1000_adapter *adapter)
struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
struct pci_dev *pdev = adapter->pdev;
- int i, ret_val;
+ int i, j, k, l, lc, good_cnt, ret_val=0;
+ unsigned long time;
E1000_WRITE_REG(&adapter->hw, RDT, rxdr->count - 1);
- for(i = 0; i < 64; i++) {
- e1000_create_lbtest_frame(txdr->buffer_info[i].skb, 1024);
- pci_dma_sync_single_for_device(pdev, txdr->buffer_info[i].dma,
- txdr->buffer_info[i].length,
- PCI_DMA_TODEVICE);
- }
- E1000_WRITE_REG(&adapter->hw, TDT, i);
-
- msec_delay(200);
-
- i = 0;
- do {
- pci_dma_sync_single_for_cpu(pdev, rxdr->buffer_info[i].dma,
- rxdr->buffer_info[i].length,
- PCI_DMA_FROMDEVICE);
-
- ret_val = e1000_check_lbtest_frame(rxdr->buffer_info[i].skb,
- 1024);
- i++;
- } while (ret_val != 0 && i < 64);
+ /* Calculate the loop count based on the largest descriptor ring
+ * The idea is to wrap the largest ring a number of times using 64
+ * send/receive pairs during each loop
+ */
+ if(rxdr->count <= txdr->count)
+ lc = ((txdr->count / 64) * 2) + 1;
+ else
+ lc = ((rxdr->count / 64) * 2) + 1;
+
+ k = l = 0;
+ for(j = 0; j <= lc; j++) { /* loop count loop */
+ for(i = 0; i < 64; i++) { /* send the packets */
+ e1000_create_lbtest_frame(txdr->buffer_info[i].skb,
+ 1024);
+ pci_dma_sync_single_for_device(pdev,
+ txdr->buffer_info[k].dma,
+ txdr->buffer_info[k].length,
+ PCI_DMA_TODEVICE);
+ if(unlikely(++k == txdr->count)) k = 0;
+ }
+ E1000_WRITE_REG(&adapter->hw, TDT, k);
+ msec_delay(200);
+ time = jiffies; /* set the start time for the receive */
+ good_cnt = 0;
+ do { /* receive the sent packets */
+ pci_dma_sync_single_for_cpu(pdev,
+ rxdr->buffer_info[l].dma,
+ rxdr->buffer_info[l].length,
+ PCI_DMA_FROMDEVICE);
+
+ ret_val = e1000_check_lbtest_frame(
+ rxdr->buffer_info[l].skb,
+ 1024);
+ if(!ret_val)
+ good_cnt++;
+ if(unlikely(++l == rxdr->count)) l = 0;
+ /* time + 20 msecs (200 msecs on 2.4) is more than
+ * enough time to complete the receives, if it's
+ * exceeded, break and error off
+ */
+ } while (good_cnt < 64 && jiffies < (time + 20));
+ if(good_cnt != 64) {
+ ret_val = 13; /* ret_val is the same as mis-compare */
+ break;
+ }
+ if(jiffies >= (time + 2)) {
+ ret_val = 14; /* error code for time out error */
+ break;
+ }
+ } /* end loop count loop */
return ret_val;
}
@@ -1354,13 +1386,12 @@ static int
e1000_link_test(struct e1000_adapter *adapter, uint64_t *data)
{
*data = 0;
-
if (adapter->hw.media_type == e1000_media_type_internal_serdes) {
int i = 0;
adapter->hw.serdes_link_down = TRUE;
- /* on some blade server designs link establishment */
- /* could take as long as 2-3 minutes. */
+ /* On some blade server designs, link establishment
+ * could take as long as 2-3 minutes */
do {
e1000_check_for_link(&adapter->hw);
if (adapter->hw.serdes_link_down == FALSE)
@@ -1368,9 +1399,11 @@ e1000_link_test(struct e1000_adapter *adapter, uint64_t *data)
msec_delay(20);
} while (i++ < 3750);
- *data = 1;
+ *data = 1;
} else {
e1000_check_for_link(&adapter->hw);
+ if(adapter->hw.autoneg) /* if auto_neg is set wait for it */
+ msec_delay(4000);
if(!(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_LU)) {
*data = 1;
diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
index 786a9b93565..723589b28be 100644
--- a/drivers/net/e1000/e1000_hw.c
+++ b/drivers/net/e1000/e1000_hw.c
@@ -1,7 +1,7 @@
/*******************************************************************************
- Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+ Copyright(c) 1999 - 2005 Intel Corporation. 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
@@ -63,10 +63,11 @@ static uint16_t e1000_shift_in_ee_bits(struct e1000_hw *hw, uint16_t count);
static int32_t e1000_acquire_eeprom(struct e1000_hw *hw);
static void e1000_release_eeprom(struct e1000_hw *hw);
static void e1000_standby_eeprom(struct e1000_hw *hw);
-static int32_t e1000_id_led_init(struct e1000_hw * hw);
static int32_t e1000_set_vco_speed(struct e1000_hw *hw);
static int32_t e1000_polarity_reversal_workaround(struct e1000_hw *hw);
static int32_t e1000_set_phy_mode(struct e1000_hw *hw);
+static int32_t e1000_host_if_read_cookie(struct e1000_hw *hw, uint8_t *buffer);
+static uint8_t e1000_calculate_mng_checksum(char *buffer, uint32_t length);
/* IGP cable length table */
static const
@@ -80,6 +81,17 @@ uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] =
100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120};
+static const
+uint16_t e1000_igp_2_cable_length_table[IGP02E1000_AGC_LENGTH_TABLE_SIZE] =
+ { 8, 13, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43,
+ 22, 24, 27, 30, 32, 35, 37, 40, 42, 44, 47, 49, 51, 54, 56, 58,
+ 32, 35, 38, 41, 44, 47, 50, 53, 55, 58, 61, 63, 66, 69, 71, 74,
+ 43, 47, 51, 54, 58, 61, 64, 67, 71, 74, 77, 80, 82, 85, 88, 90,
+ 57, 62, 66, 70, 74, 77, 81, 85, 88, 91, 94, 97, 100, 103, 106, 108,
+ 73, 78, 82, 87, 91, 95, 98, 102, 105, 109, 112, 114, 117, 119, 122, 124,
+ 91, 96, 101, 105, 109, 113, 116, 119, 122, 125, 127, 128, 128, 128, 128, 128,
+ 108, 113, 117, 121, 124, 127, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128};
+
/******************************************************************************
* Set the phy type member in the hw struct.
@@ -91,10 +103,14 @@ e1000_set_phy_type(struct e1000_hw *hw)
{
DEBUGFUNC("e1000_set_phy_type");
+ if(hw->mac_type == e1000_undefined)
+ return -E1000_ERR_PHY_TYPE;
+
switch(hw->phy_id) {
case M88E1000_E_PHY_ID:
case M88E1000_I_PHY_ID:
case M88E1011_I_PHY_ID:
+ case M88E1111_I_PHY_ID:
hw->phy_type = e1000_phy_m88;
break;
case IGP01E1000_I_PHY_ID:
@@ -128,7 +144,6 @@ e1000_phy_init_script(struct e1000_hw *hw)
DEBUGFUNC("e1000_phy_init_script");
-
if(hw->phy_init_script) {
msec_delay(20);
@@ -271,6 +286,7 @@ e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_82546GB_FIBER:
case E1000_DEV_ID_82546GB_SERDES:
case E1000_DEV_ID_82546GB_PCIE:
+ case E1000_DEV_ID_82546GB_QUAD_COPPER:
hw->mac_type = e1000_82546_rev_3;
break;
case E1000_DEV_ID_82541EI:
@@ -289,12 +305,19 @@ e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_82547GI:
hw->mac_type = e1000_82547_rev_2;
break;
+ case E1000_DEV_ID_82573E:
+ case E1000_DEV_ID_82573E_IAMT:
+ hw->mac_type = e1000_82573;
+ break;
default:
/* Should never have loaded on this device */
return -E1000_ERR_MAC_TYPE;
}
switch(hw->mac_type) {
+ case e1000_82573:
+ hw->eeprom_semaphore_present = TRUE;
+ /* fall through */
case e1000_82541:
case e1000_82547:
case e1000_82541_rev_2:
@@ -360,6 +383,9 @@ e1000_reset_hw(struct e1000_hw *hw)
uint32_t icr;
uint32_t manc;
uint32_t led_ctrl;
+ uint32_t timeout;
+ uint32_t extcnf_ctrl;
+ int32_t ret_val;
DEBUGFUNC("e1000_reset_hw");
@@ -369,6 +395,15 @@ e1000_reset_hw(struct e1000_hw *hw)
e1000_pci_clear_mwi(hw);
}
+ if(hw->bus_type == e1000_bus_type_pci_express) {
+ /* Prevent the PCI-E bus from sticking if there is no TLP connection
+ * on the last TLP read/write transaction when MAC is reset.
+ */
+ if(e1000_disable_pciex_master(hw) != E1000_SUCCESS) {
+ DEBUGOUT("PCI-E Master disable polling has failed.\n");
+ }
+ }
+
/* Clear interrupt mask to stop board from generating interrupts */
DEBUGOUT("Masking off all interrupts\n");
E1000_WRITE_REG(hw, IMC, 0xffffffff);
@@ -393,10 +428,32 @@ e1000_reset_hw(struct e1000_hw *hw)
/* Must reset the PHY before resetting the MAC */
if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
- E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_PHY_RST));
+ E1000_WRITE_REG(hw, CTRL, (ctrl | E1000_CTRL_PHY_RST));
msec_delay(5);
}
+ /* Must acquire the MDIO ownership before MAC reset.
+ * Ownership defaults to firmware after a reset. */
+ if(hw->mac_type == e1000_82573) {
+ timeout = 10;
+
+ extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL);
+ extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
+
+ do {
+ E1000_WRITE_REG(hw, EXTCNF_CTRL, extcnf_ctrl);
+ extcnf_ctrl = E1000_READ_REG(hw, EXTCNF_CTRL);
+
+ if(extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP)
+ break;
+ else
+ extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
+
+ msec_delay(2);
+ timeout--;
+ } while(timeout);
+ }
+
/* Issue a global reset to the MAC. This will reset the chip's
* transmit, receive, DMA, and link units. It will not effect
* the current PCI configuration. The global reset bit is self-
@@ -450,6 +507,18 @@ e1000_reset_hw(struct e1000_hw *hw)
/* Wait for EEPROM reload */
msec_delay(20);
break;
+ case e1000_82573:
+ udelay(10);
+ ctrl_ext = E1000_READ_REG(hw, CTRL_EXT);
+ ctrl_ext |= E1000_CTRL_EXT_EE_RST;
+ E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext);
+ E1000_WRITE_FLUSH(hw);
+ /* fall through */
+ ret_val = e1000_get_auto_rd_done(hw);
+ if(ret_val)
+ /* We don't want to continue accessing MAC registers. */
+ return ret_val;
+ break;
default:
/* Wait for EEPROM reload (it happens automatically) */
msec_delay(5);
@@ -457,7 +526,7 @@ e1000_reset_hw(struct e1000_hw *hw)
}
/* Disable HW ARPs on ASF enabled adapters */
- if(hw->mac_type >= e1000_82540) {
+ if(hw->mac_type >= e1000_82540 && hw->mac_type <= e1000_82547_rev_2) {
manc = E1000_READ_REG(hw, MANC);
manc &= ~(E1000_MANC_ARP_EN);
E1000_WRITE_REG(hw, MANC, manc);
@@ -510,6 +579,8 @@ e1000_init_hw(struct e1000_hw *hw)
uint16_t pcix_stat_hi_word;
uint16_t cmd_mmrbc;
uint16_t stat_mmrbc;
+ uint32_t mta_size;
+
DEBUGFUNC("e1000_init_hw");
/* Initialize Identification LED */
@@ -524,8 +595,8 @@ e1000_init_hw(struct e1000_hw *hw)
/* Disabling VLAN filtering. */
DEBUGOUT("Initializing the IEEE VLAN\n");
- E1000_WRITE_REG(hw, VET, 0);
-
+ if (hw->mac_type < e1000_82545_rev_3)
+ E1000_WRITE_REG(hw, VET, 0);
e1000_clear_vfta(hw);
/* For 82542 (rev 2.0), disable MWI and put the receiver into reset */
@@ -553,14 +624,16 @@ e1000_init_hw(struct e1000_hw *hw)
/* Zero out the Multicast HASH table */
DEBUGOUT("Zeroing the MTA\n");
- for(i = 0; i < E1000_MC_TBL_SIZE; i++)
+ mta_size = E1000_MC_TBL_SIZE;
+ for(i = 0; i < mta_size; i++)
E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
/* Set the PCI priority bit correctly in the CTRL register. This
* determines if the adapter gives priority to receives, or if it
- * gives equal priority to transmits and receives.
+ * gives equal priority to transmits and receives. Valid only on
+ * 82542 and 82543 silicon.
*/
- if(hw->dma_fairness) {
+ if(hw->dma_fairness && hw->mac_type <= e1000_82543) {
ctrl = E1000_READ_REG(hw, CTRL);
E1000_WRITE_REG(hw, CTRL, ctrl | E1000_CTRL_PRIOR);
}
@@ -598,9 +671,21 @@ e1000_init_hw(struct e1000_hw *hw)
if(hw->mac_type > e1000_82544) {
ctrl = E1000_READ_REG(hw, TXDCTL);
ctrl = (ctrl & ~E1000_TXDCTL_WTHRESH) | E1000_TXDCTL_FULL_TX_DESC_WB;
+ switch (hw->mac_type) {
+ default:
+ break;
+ case e1000_82573:
+ ctrl |= E1000_TXDCTL_COUNT_DESC;
+ break;
+ }
E1000_WRITE_REG(hw, TXDCTL, ctrl);
}
+ if (hw->mac_type == e1000_82573) {
+ e1000_enable_tx_pkt_filtering(hw);
+ }
+
+
/* Clear all of the statistics registers (clear on read). It is
* important that we do this after we have tried to establish link
* because the symbol error count will increment wildly if there
@@ -679,7 +764,7 @@ e1000_setup_link(struct e1000_hw *hw)
* control setting, then the variable hw->fc will
* be initialized based on a value in the EEPROM.
*/
- if(e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data) < 0) {
+ if(e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data)) {
DEBUGOUT("EEPROM Read Error\n");
return -E1000_ERR_EEPROM;
}
@@ -736,6 +821,7 @@ e1000_setup_link(struct e1000_hw *hw)
E1000_WRITE_REG(hw, FCAL, FLOW_CONTROL_ADDRESS_LOW);
E1000_WRITE_REG(hw, FCAH, FLOW_CONTROL_ADDRESS_HIGH);
E1000_WRITE_REG(hw, FCT, FLOW_CONTROL_TYPE);
+
E1000_WRITE_REG(hw, FCTTV, hw->fc_pause_time);
/* Set the flow control receive threshold registers. Normally,
@@ -906,20 +992,18 @@ e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
}
/******************************************************************************
-* Detects which PHY is present and the speed and duplex
+* Make sure we have a valid PHY and change PHY mode before link setup.
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
static int32_t
-e1000_setup_copper_link(struct e1000_hw *hw)
+e1000_copper_link_preconfig(struct e1000_hw *hw)
{
uint32_t ctrl;
- uint32_t led_ctrl;
int32_t ret_val;
- uint16_t i;
uint16_t phy_data;
- DEBUGFUNC("e1000_setup_copper_link");
+ DEBUGFUNC("e1000_copper_link_preconfig");
ctrl = E1000_READ_REG(hw, CTRL);
/* With 82543, we need to force speed and duplex on the MAC equal to what
@@ -933,7 +1017,9 @@ e1000_setup_copper_link(struct e1000_hw *hw)
} else {
ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU);
E1000_WRITE_REG(hw, CTRL, ctrl);
- e1000_phy_hw_reset(hw);
+ ret_val = e1000_phy_hw_reset(hw);
+ if(ret_val)
+ return ret_val;
}
/* Make sure we have a valid PHY */
@@ -961,274 +1047,398 @@ e1000_setup_copper_link(struct e1000_hw *hw)
hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2)
hw->phy_reset_disable = FALSE;
- if(!hw->phy_reset_disable) {
- if (hw->phy_type == e1000_phy_igp) {
+ return E1000_SUCCESS;
+}
- ret_val = e1000_phy_reset(hw);
- if(ret_val) {
- DEBUGOUT("Error Resetting the PHY\n");
- return ret_val;
- }
- /* Wait 10ms for MAC to configure PHY from eeprom settings */
- msec_delay(15);
+/********************************************************************
+* Copper link setup for e1000_phy_igp series.
+*
+* hw - Struct containing variables accessed by shared code
+*********************************************************************/
+static int32_t
+e1000_copper_link_igp_setup(struct e1000_hw *hw)
+{
+ uint32_t led_ctrl;
+ int32_t ret_val;
+ uint16_t phy_data;
- /* Configure activity LED after PHY reset */
- led_ctrl = E1000_READ_REG(hw, LEDCTL);
- led_ctrl &= IGP_ACTIVITY_LED_MASK;
- led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
- E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
+ DEBUGFUNC("e1000_copper_link_igp_setup");
- /* disable lplu d3 during driver init */
- ret_val = e1000_set_d3_lplu_state(hw, FALSE);
- if(ret_val) {
- DEBUGOUT("Error Disabling LPLU D3\n");
- return ret_val;
- }
+ if (hw->phy_reset_disable)
+ return E1000_SUCCESS;
+
+ ret_val = e1000_phy_reset(hw);
+ if (ret_val) {
+ DEBUGOUT("Error Resetting the PHY\n");
+ return ret_val;
+ }
- /* Configure mdi-mdix settings */
- ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL,
- &phy_data);
- if(ret_val)
- return ret_val;
+ /* Wait 10ms for MAC to configure PHY from eeprom settings */
+ msec_delay(15);
- if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
- hw->dsp_config_state = e1000_dsp_config_disabled;
- /* Force MDI for earlier revs of the IGP PHY */
- phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX |
- IGP01E1000_PSCR_FORCE_MDI_MDIX);
- hw->mdix = 1;
+ /* Configure activity LED after PHY reset */
+ led_ctrl = E1000_READ_REG(hw, LEDCTL);
+ led_ctrl &= IGP_ACTIVITY_LED_MASK;
+ led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
+ E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
- } else {
- hw->dsp_config_state = e1000_dsp_config_enabled;
- phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
-
- switch (hw->mdix) {
- case 1:
- phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
- break;
- case 2:
- phy_data |= IGP01E1000_PSCR_FORCE_MDI_MDIX;
- break;
- case 0:
- default:
- phy_data |= IGP01E1000_PSCR_AUTO_MDIX;
- break;
- }
- }
- ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL,
- phy_data);
- if(ret_val)
- return ret_val;
+ /* disable lplu d3 during driver init */
+ ret_val = e1000_set_d3_lplu_state(hw, FALSE);
+ if (ret_val) {
+ DEBUGOUT("Error Disabling LPLU D3\n");
+ return ret_val;
+ }
- /* set auto-master slave resolution settings */
- if(hw->autoneg) {
- e1000_ms_type phy_ms_setting = hw->master_slave;
+ /* disable lplu d0 during driver init */
+ ret_val = e1000_set_d0_lplu_state(hw, FALSE);
+ if (ret_val) {
+ DEBUGOUT("Error Disabling LPLU D0\n");
+ return ret_val;
+ }
+ /* Configure mdi-mdix settings */
+ ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
+ if (ret_val)
+ return ret_val;
- if(hw->ffe_config_state == e1000_ffe_config_active)
- hw->ffe_config_state = e1000_ffe_config_enabled;
+ if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) {
+ hw->dsp_config_state = e1000_dsp_config_disabled;
+ /* Force MDI for earlier revs of the IGP PHY */
+ phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX | IGP01E1000_PSCR_FORCE_MDI_MDIX);
+ hw->mdix = 1;
- if(hw->dsp_config_state == e1000_dsp_config_activated)
- hw->dsp_config_state = e1000_dsp_config_enabled;
+ } else {
+ hw->dsp_config_state = e1000_dsp_config_enabled;
+ phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
- /* when autonegotiation advertisment is only 1000Mbps then we
- * should disable SmartSpeed and enable Auto MasterSlave
- * resolution as hardware default. */
- if(hw->autoneg_advertised == ADVERTISE_1000_FULL) {
- /* Disable SmartSpeed */
- ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
- &phy_data);
- if(ret_val)
- return ret_val;
- phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
- ret_val = e1000_write_phy_reg(hw,
- IGP01E1000_PHY_PORT_CONFIG,
- phy_data);
- if(ret_val)
- return ret_val;
- /* Set auto Master/Slave resolution process */
- ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
- if(ret_val)
- return ret_val;
- phy_data &= ~CR_1000T_MS_ENABLE;
- ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
- if(ret_val)
- return ret_val;
- }
+ switch (hw->mdix) {
+ case 1:
+ phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
+ break;
+ case 2:
+ phy_data |= IGP01E1000_PSCR_FORCE_MDI_MDIX;
+ break;
+ case 0:
+ default:
+ phy_data |= IGP01E1000_PSCR_AUTO_MDIX;
+ break;
+ }
+ }
+ ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
+ if(ret_val)
+ return ret_val;
- ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
- if(ret_val)
- return ret_val;
+ /* set auto-master slave resolution settings */
+ if(hw->autoneg) {
+ e1000_ms_type phy_ms_setting = hw->master_slave;
- /* load defaults for future use */
- hw->original_master_slave = (phy_data & CR_1000T_MS_ENABLE) ?
- ((phy_data & CR_1000T_MS_VALUE) ?
- e1000_ms_force_master :
- e1000_ms_force_slave) :
- e1000_ms_auto;
-
- switch (phy_ms_setting) {
- case e1000_ms_force_master:
- phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
- break;
- case e1000_ms_force_slave:
- phy_data |= CR_1000T_MS_ENABLE;
- phy_data &= ~(CR_1000T_MS_VALUE);
- break;
- case e1000_ms_auto:
- phy_data &= ~CR_1000T_MS_ENABLE;
- default:
- break;
- }
- ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
- if(ret_val)
- return ret_val;
- }
- } else {
- /* Enable CRS on TX. This must be set for half-duplex operation. */
- ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL,
- &phy_data);
+ if(hw->ffe_config_state == e1000_ffe_config_active)
+ hw->ffe_config_state = e1000_ffe_config_enabled;
+
+ if(hw->dsp_config_state == e1000_dsp_config_activated)
+ hw->dsp_config_state = e1000_dsp_config_enabled;
+
+ /* when autonegotiation advertisment is only 1000Mbps then we
+ * should disable SmartSpeed and enable Auto MasterSlave
+ * resolution as hardware default. */
+ if(hw->autoneg_advertised == ADVERTISE_1000_FULL) {
+ /* Disable SmartSpeed */
+ ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data);
+ if(ret_val)
+ return ret_val;
+ phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val = e1000_write_phy_reg(hw,
+ IGP01E1000_PHY_PORT_CONFIG,
+ phy_data);
+ if(ret_val)
+ return ret_val;
+ /* Set auto Master/Slave resolution process */
+ ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
+ if(ret_val)
+ return ret_val;
+ phy_data &= ~CR_1000T_MS_ENABLE;
+ ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
if(ret_val)
return ret_val;
+ }
- phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
+ ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data);
+ if(ret_val)
+ return ret_val;
- /* Options:
- * MDI/MDI-X = 0 (default)
- * 0 - Auto for all speeds
- * 1 - MDI mode
- * 2 - MDI-X mode
- * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
- */
- phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
+ /* load defaults for future use */
+ hw->original_master_slave = (phy_data & CR_1000T_MS_ENABLE) ?
+ ((phy_data & CR_1000T_MS_VALUE) ?
+ e1000_ms_force_master :
+ e1000_ms_force_slave) :
+ e1000_ms_auto;
- switch (hw->mdix) {
- case 1:
- phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
- break;
- case 2:
- phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
- break;
- case 3:
- phy_data |= M88E1000_PSCR_AUTO_X_1000T;
- break;
- case 0:
+ switch (phy_ms_setting) {
+ case e1000_ms_force_master:
+ phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
+ break;
+ case e1000_ms_force_slave:
+ phy_data |= CR_1000T_MS_ENABLE;
+ phy_data &= ~(CR_1000T_MS_VALUE);
+ break;
+ case e1000_ms_auto:
+ phy_data &= ~CR_1000T_MS_ENABLE;
default:
- phy_data |= M88E1000_PSCR_AUTO_X_MODE;
- break;
- }
+ break;
+ }
+ ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data);
+ if(ret_val)
+ return ret_val;
+ }
- /* Options:
- * disable_polarity_correction = 0 (default)
- * Automatic Correction for Reversed Cable Polarity
- * 0 - Disabled
- * 1 - Enabled
- */
- phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
- if(hw->disable_polarity_correction == 1)
- phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
- ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL,
- phy_data);
- if(ret_val)
- return ret_val;
+ return E1000_SUCCESS;
+}
- /* Force TX_CLK in the Extended PHY Specific Control Register
- * to 25MHz clock.
- */
- ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
- &phy_data);
- if(ret_val)
- return ret_val;
- phy_data |= M88E1000_EPSCR_TX_CLK_25;
+/********************************************************************
+* Copper link setup for e1000_phy_m88 series.
+*
+* hw - Struct containing variables accessed by shared code
+*********************************************************************/
+static int32_t
+e1000_copper_link_mgp_setup(struct e1000_hw *hw)
+{
+ int32_t ret_val;
+ uint16_t phy_data;
+
+ DEBUGFUNC("e1000_copper_link_mgp_setup");
+
+ if(hw->phy_reset_disable)
+ return E1000_SUCCESS;
+
+ /* Enable CRS on TX. This must be set for half-duplex operation. */
+ ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
+ if(ret_val)
+ return ret_val;
+
+ phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
+
+ /* Options:
+ * MDI/MDI-X = 0 (default)
+ * 0 - Auto for all speeds
+ * 1 - MDI mode
+ * 2 - MDI-X mode
+ * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
+ */
+ phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
+
+ switch (hw->mdix) {
+ case 1:
+ phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
+ break;
+ case 2:
+ phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
+ break;
+ case 3:
+ phy_data |= M88E1000_PSCR_AUTO_X_1000T;
+ break;
+ case 0:
+ default:
+ phy_data |= M88E1000_PSCR_AUTO_X_MODE;
+ break;
+ }
+
+ /* Options:
+ * disable_polarity_correction = 0 (default)
+ * Automatic Correction for Reversed Cable Polarity
+ * 0 - Disabled
+ * 1 - Enabled
+ */
+ phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
+ if(hw->disable_polarity_correction == 1)
+ phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
+ ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
+ if(ret_val)
+ return ret_val;
- if (hw->phy_revision < M88E1011_I_REV_4) {
- /* Configure Master and Slave downshift values */
- phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK |
+ /* Force TX_CLK in the Extended PHY Specific Control Register
+ * to 25MHz clock.
+ */
+ ret_val = e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
+ if(ret_val)
+ return ret_val;
+
+ phy_data |= M88E1000_EPSCR_TX_CLK_25;
+
+ if (hw->phy_revision < M88E1011_I_REV_4) {
+ /* Configure Master and Slave downshift values */
+ phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK |
M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);
- phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
+ phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
- ret_val = e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
- phy_data);
- if(ret_val)
- return ret_val;
- }
+ ret_val = e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data);
+ if(ret_val)
+ return ret_val;
+ }
- /* SW Reset the PHY so all changes take effect */
- ret_val = e1000_phy_reset(hw);
- if(ret_val) {
- DEBUGOUT("Error Resetting the PHY\n");
- return ret_val;
- }
+ /* SW Reset the PHY so all changes take effect */
+ ret_val = e1000_phy_reset(hw);
+ if(ret_val) {
+ DEBUGOUT("Error Resetting the PHY\n");
+ return ret_val;
+ }
+
+ return E1000_SUCCESS;
+}
+
+/********************************************************************
+* Setup auto-negotiation and flow control advertisements,
+* and then perform auto-negotiation.
+*
+* hw - Struct containing variables accessed by shared code
+*********************************************************************/
+static int32_t
+e1000_copper_link_autoneg(struct e1000_hw *hw)
+{
+ int32_t ret_val;
+ uint16_t phy_data;
+
+ DEBUGFUNC("e1000_copper_link_autoneg");
+
+ /* Perform some bounds checking on the hw->autoneg_advertised
+ * parameter. If this variable is zero, then set it to the default.
+ */
+ hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT;
+
+ /* If autoneg_advertised is zero, we assume it was not defaulted
+ * by the calling code so we set to advertise full capability.
+ */
+ if(hw->autoneg_advertised == 0)
+ hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+
+ DEBUGOUT("Reconfiguring auto-neg advertisement params\n");
+ ret_val = e1000_phy_setup_autoneg(hw);
+ if(ret_val) {
+ DEBUGOUT("Error Setting up Auto-Negotiation\n");
+ return ret_val;
+ }
+ DEBUGOUT("Restarting Auto-Neg\n");
+
+ /* Restart auto-negotiation by setting the Auto Neg Enable bit and
+ * the Auto Neg Restart bit in the PHY control register.
+ */
+ ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
+ if(ret_val)
+ return ret_val;
+
+ phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
+ ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data);
+ if(ret_val)
+ return ret_val;
+
+ /* Does the user want to wait for Auto-Neg to complete here, or
+ * check at a later time (for example, callback routine).
+ */
+ if(hw->wait_autoneg_complete) {
+ ret_val = e1000_wait_autoneg(hw);
+ if(ret_val) {
+ DEBUGOUT("Error while waiting for autoneg to complete\n");
+ return ret_val;
}
+ }
- /* Options:
- * autoneg = 1 (default)
- * PHY will advertise value(s) parsed from
- * autoneg_advertised and fc
- * autoneg = 0
- * PHY will be set to 10H, 10F, 100H, or 100F
- * depending on value parsed from forced_speed_duplex.
- */
+ hw->get_link_status = TRUE;
- /* Is autoneg enabled? This is enabled by default or by software
- * override. If so, call e1000_phy_setup_autoneg routine to parse the
- * autoneg_advertised and fc options. If autoneg is NOT enabled, then
- * the user should have provided a speed/duplex override. If so, then
- * call e1000_phy_force_speed_duplex to parse and set this up.
- */
- if(hw->autoneg) {
- /* Perform some bounds checking on the hw->autoneg_advertised
- * parameter. If this variable is zero, then set it to the default.
- */
- hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT;
+ return E1000_SUCCESS;
+}
- /* If autoneg_advertised is zero, we assume it was not defaulted
- * by the calling code so we set to advertise full capability.
- */
- if(hw->autoneg_advertised == 0)
- hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT;
- DEBUGOUT("Reconfiguring auto-neg advertisement params\n");
- ret_val = e1000_phy_setup_autoneg(hw);
- if(ret_val) {
- DEBUGOUT("Error Setting up Auto-Negotiation\n");
- return ret_val;
- }
- DEBUGOUT("Restarting Auto-Neg\n");
+/******************************************************************************
+* Config the MAC and the PHY after link is up.
+* 1) Set up the MAC to the current PHY speed/duplex
+* if we are on 82543. If we
+* are on newer silicon, we only need to configure
+* collision distance in the Transmit Control Register.
+* 2) Set up flow control on the MAC to that established with
+* the link partner.
+* 3) Config DSP to improve Gigabit link quality for some PHY revisions.
+*
+* hw - Struct containing variables accessed by shared code
+******************************************************************************/
+static int32_t
+e1000_copper_link_postconfig(struct e1000_hw *hw)
+{
+ int32_t ret_val;
+ DEBUGFUNC("e1000_copper_link_postconfig");
+
+ if(hw->mac_type >= e1000_82544) {
+ e1000_config_collision_dist(hw);
+ } else {
+ ret_val = e1000_config_mac_to_phy(hw);
+ if(ret_val) {
+ DEBUGOUT("Error configuring MAC to PHY settings\n");
+ return ret_val;
+ }
+ }
+ ret_val = e1000_config_fc_after_link_up(hw);
+ if(ret_val) {
+ DEBUGOUT("Error Configuring Flow Control\n");
+ return ret_val;
+ }
- /* Restart auto-negotiation by setting the Auto Neg Enable bit and
- * the Auto Neg Restart bit in the PHY control register.
- */
- ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
- if(ret_val)
- return ret_val;
+ /* Config DSP to improve Giga link quality */
+ if(hw->phy_type == e1000_phy_igp) {
+ ret_val = e1000_config_dsp_after_link_change(hw, TRUE);
+ if(ret_val) {
+ DEBUGOUT("Error Configuring DSP after link up\n");
+ return ret_val;
+ }
+ }
+
+ return E1000_SUCCESS;
+}
- phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
- ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data);
- if(ret_val)
- return ret_val;
+/******************************************************************************
+* Detects which PHY is present and setup the speed and duplex
+*
+* hw - Struct containing variables accessed by shared code
+******************************************************************************/
+static int32_t
+e1000_setup_copper_link(struct e1000_hw *hw)
+{
+ int32_t ret_val;
+ uint16_t i;
+ uint16_t phy_data;
- /* Does the user want to wait for Auto-Neg to complete here, or
- * check at a later time (for example, callback routine).
- */
- if(hw->wait_autoneg_complete) {
- ret_val = e1000_wait_autoneg(hw);
- if(ret_val) {
- DEBUGOUT("Error while waiting for autoneg to complete\n");
- return ret_val;
- }
- }
- hw->get_link_status = TRUE;
- } else {
- DEBUGOUT("Forcing speed and duplex\n");
- ret_val = e1000_phy_force_speed_duplex(hw);
- if(ret_val) {
- DEBUGOUT("Error Forcing Speed and Duplex\n");
- return ret_val;
- }
+ DEBUGFUNC("e1000_setup_copper_link");
+
+ /* Check if it is a valid PHY and set PHY mode if necessary. */
+ ret_val = e1000_copper_link_preconfig(hw);
+ if(ret_val)
+ return ret_val;
+
+ if (hw->phy_type == e1000_phy_igp ||
+ hw->phy_type == e1000_phy_igp_2) {
+ ret_val = e1000_copper_link_igp_setup(hw);
+ if(ret_val)
+ return ret_val;
+ } else if (hw->phy_type == e1000_phy_m88) {
+ ret_val = e1000_copper_link_mgp_setup(hw);
+ if(ret_val)
+ return ret_val;
+ }
+
+ if(hw->autoneg) {
+ /* Setup autoneg and flow control advertisement
+ * and perform autonegotiation */
+ ret_val = e1000_copper_link_autoneg(hw);
+ if(ret_val)
+ return ret_val;
+ } else {
+ /* PHY will be set to 10H, 10F, 100H,or 100F
+ * depending on value from forced_speed_duplex. */
+ DEBUGOUT("Forcing speed and duplex\n");
+ ret_val = e1000_phy_force_speed_duplex(hw);
+ if(ret_val) {
+ DEBUGOUT("Error Forcing Speed and Duplex\n");
+ return ret_val;
}
- } /* !hw->phy_reset_disable */
+ }
/* Check link status. Wait up to 100 microseconds for link to become
* valid.
@@ -1242,37 +1452,11 @@ e1000_setup_copper_link(struct e1000_hw *hw)
return ret_val;
if(phy_data & MII_SR_LINK_STATUS) {
- /* We have link, so we need to finish the config process:
- * 1) Set up the MAC to the current PHY speed/duplex
- * if we are on 82543. If we
- * are on newer silicon, we only need to configure
- * collision distance in the Transmit Control Register.
- * 2) Set up flow control on the MAC to that established with
- * the link partner.
- */
- if(hw->mac_type >= e1000_82544) {
- e1000_config_collision_dist(hw);
- } else {
- ret_val = e1000_config_mac_to_phy(hw);
- if(ret_val) {
- DEBUGOUT("Error configuring MAC to PHY settings\n");
- return ret_val;
- }
- }
- ret_val = e1000_config_fc_after_link_up(hw);
- if(ret_val) {
- DEBUGOUT("Error Configuring Flow Control\n");
+ /* Config the MAC and PHY after link is up */
+ ret_val = e1000_copper_link_postconfig(hw);
+ if(ret_val)
return ret_val;
- }
- DEBUGOUT("Valid link established!!!\n");
-
- if(hw->phy_type == e1000_phy_igp) {
- ret_val = e1000_config_dsp_after_link_change(hw, TRUE);
- if(ret_val) {
- DEBUGOUT("Error Configuring DSP after link up\n");
- return ret_val;
- }
- }
+
DEBUGOUT("Valid link established!!!\n");
return E1000_SUCCESS;
}
@@ -1302,10 +1486,10 @@ e1000_phy_setup_autoneg(struct e1000_hw *hw)
if(ret_val)
return ret_val;
- /* Read the MII 1000Base-T Control Register (Address 9). */
- ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
- if(ret_val)
- return ret_val;
+ /* Read the MII 1000Base-T Control Register (Address 9). */
+ ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg);
+ if(ret_val)
+ return ret_val;
/* Need to parse both autoneg_advertised and fc and set up
* the appropriate PHY registers. First we will parse for
@@ -1417,7 +1601,7 @@ e1000_phy_setup_autoneg(struct e1000_hw *hw)
DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
- ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg);
+ ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, mii_1000t_ctrl_reg);
if(ret_val)
return ret_val;
@@ -1678,6 +1862,11 @@ e1000_config_mac_to_phy(struct e1000_hw *hw)
DEBUGFUNC("e1000_config_mac_to_phy");
+ /* 82544 or newer MAC, Auto Speed Detection takes care of
+ * MAC speed/duplex configuration.*/
+ if (hw->mac_type >= e1000_82544)
+ return E1000_SUCCESS;
+
/* Read the Device Control Register and set the bits to Force Speed
* and Duplex.
*/
@@ -1688,45 +1877,25 @@ e1000_config_mac_to_phy(struct e1000_hw *hw)
/* Set up duplex in the Device Control and Transmit Control
* registers depending on negotiated values.
*/
- if (hw->phy_type == e1000_phy_igp) {
- ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS,
- &phy_data);
- if(ret_val)
- return ret_val;
-
- if(phy_data & IGP01E1000_PSSR_FULL_DUPLEX) ctrl |= E1000_CTRL_FD;
- else ctrl &= ~E1000_CTRL_FD;
-
- e1000_config_collision_dist(hw);
+ ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
+ if(ret_val)
+ return ret_val;
- /* Set up speed in the Device Control register depending on
- * negotiated values.
- */
- if((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
- IGP01E1000_PSSR_SPEED_1000MBPS)
- ctrl |= E1000_CTRL_SPD_1000;
- else if((phy_data & IGP01E1000_PSSR_SPEED_MASK) ==
- IGP01E1000_PSSR_SPEED_100MBPS)
- ctrl |= E1000_CTRL_SPD_100;
- } else {
- ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
- &phy_data);
- if(ret_val)
- return ret_val;
+ if(phy_data & M88E1000_PSSR_DPLX)
+ ctrl |= E1000_CTRL_FD;
+ else
+ ctrl &= ~E1000_CTRL_FD;
- if(phy_data & M88E1000_PSSR_DPLX) ctrl |= E1000_CTRL_FD;
- else ctrl &= ~E1000_CTRL_FD;
+ e1000_config_collision_dist(hw);
- e1000_config_collision_dist(hw);
+ /* Set up speed in the Device Control register depending on
+ * negotiated values.
+ */
+ if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)
+ ctrl |= E1000_CTRL_SPD_1000;
+ else if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS)
+ ctrl |= E1000_CTRL_SPD_100;
- /* Set up speed in the Device Control register depending on
- * negotiated values.
- */
- if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS)
- ctrl |= E1000_CTRL_SPD_1000;
- else if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS)
- ctrl |= E1000_CTRL_SPD_100;
- }
/* Write the configured values back to the Device Control Reg. */
E1000_WRITE_REG(hw, CTRL, ctrl);
return E1000_SUCCESS;
@@ -2494,8 +2663,8 @@ e1000_read_phy_reg(struct e1000_hw *hw,
DEBUGFUNC("e1000_read_phy_reg");
-
- if(hw->phy_type == e1000_phy_igp &&
+ if((hw->phy_type == e1000_phy_igp ||
+ hw->phy_type == e1000_phy_igp_2) &&
(reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
(uint16_t)reg_addr);
@@ -2600,8 +2769,8 @@ e1000_write_phy_reg(struct e1000_hw *hw,
DEBUGFUNC("e1000_write_phy_reg");
-
- if(hw->phy_type == e1000_phy_igp &&
+ if((hw->phy_type == e1000_phy_igp ||
+ hw->phy_type == e1000_phy_igp_2) &&
(reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
(uint16_t)reg_addr);
@@ -2679,19 +2848,27 @@ e1000_write_phy_reg_ex(struct e1000_hw *hw,
return E1000_SUCCESS;
}
+
/******************************************************************************
* Returns the PHY to the power-on reset state
*
* hw - Struct containing variables accessed by shared code
******************************************************************************/
-void
+int32_t
e1000_phy_hw_reset(struct e1000_hw *hw)
{
uint32_t ctrl, ctrl_ext;
uint32_t led_ctrl;
+ int32_t ret_val;
DEBUGFUNC("e1000_phy_hw_reset");
+ /* In the case of the phy reset being blocked, it's not an error, we
+ * simply return success without performing the reset. */
+ ret_val = e1000_check_phy_reset_block(hw);
+ if (ret_val)
+ return E1000_SUCCESS;
+
DEBUGOUT("Resetting Phy...\n");
if(hw->mac_type > e1000_82543) {
@@ -2727,6 +2904,11 @@ e1000_phy_hw_reset(struct e1000_hw *hw)
led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
E1000_WRITE_REG(hw, LEDCTL, led_ctrl);
}
+
+ /* Wait for FW to finish PHY configuration. */
+ ret_val = e1000_get_phy_cfg_done(hw);
+
+ return ret_val;
}
/******************************************************************************
@@ -2744,7 +2926,19 @@ e1000_phy_reset(struct e1000_hw *hw)
DEBUGFUNC("e1000_phy_reset");
- if(hw->mac_type != e1000_82541_rev_2) {
+ /* In the case of the phy reset being blocked, it's not an error, we
+ * simply return success without performing the reset. */
+ ret_val = e1000_check_phy_reset_block(hw);
+ if (ret_val)
+ return E1000_SUCCESS;
+
+ switch (hw->mac_type) {
+ case e1000_82541_rev_2:
+ ret_val = e1000_phy_hw_reset(hw);
+ if(ret_val)
+ return ret_val;
+ break;
+ default:
ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data);
if(ret_val)
return ret_val;
@@ -2755,9 +2949,10 @@ e1000_phy_reset(struct e1000_hw *hw)
return ret_val;
udelay(1);
- } else e1000_phy_hw_reset(hw);
+ break;
+ }
- if(hw->phy_type == e1000_phy_igp)
+ if(hw->phy_type == e1000_phy_igp || hw->phy_type == e1000_phy_igp_2)
e1000_phy_init_script(hw);
return E1000_SUCCESS;
@@ -2811,6 +3006,9 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
case e1000_82547_rev_2:
if(hw->phy_id == IGP01E1000_I_PHY_ID) match = TRUE;
break;
+ case e1000_82573:
+ if(hw->phy_id == M88E1111_I_PHY_ID) match = TRUE;
+ break;
default:
DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type);
return -E1000_ERR_CONFIG;
@@ -2866,7 +3064,7 @@ e1000_phy_igp_get_info(struct e1000_hw *hw,
/* The downshift status is checked only once, after link is established,
* and it stored in the hw->speed_downgraded parameter. */
- phy_info->downshift = hw->speed_downgraded;
+ phy_info->downshift = (e1000_downshift)hw->speed_downgraded;
/* IGP01E1000 does not need to support it. */
phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_normal;
@@ -2905,7 +3103,7 @@ e1000_phy_igp_get_info(struct e1000_hw *hw,
if(ret_val)
return ret_val;
- /* transalte to old method */
+ /* Translate to old method */
average = (max_length + min_length) / 2;
if(average <= e1000_igp_cable_length_50)
@@ -2940,7 +3138,7 @@ e1000_phy_m88_get_info(struct e1000_hw *hw,
/* The downshift status is checked only once, after link is established,
* and it stored in the hw->speed_downgraded parameter. */
- phy_info->downshift = hw->speed_downgraded;
+ phy_info->downshift = (e1000_downshift)hw->speed_downgraded;
ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
if(ret_val)
@@ -3029,7 +3227,8 @@ e1000_phy_get_info(struct e1000_hw *hw,
return -E1000_ERR_CONFIG;
}
- if(hw->phy_type == e1000_phy_igp)
+ if(hw->phy_type == e1000_phy_igp ||
+ hw->phy_type == e1000_phy_igp_2)
return e1000_phy_igp_get_info(hw, phy_info);
else
return e1000_phy_m88_get_info(hw, phy_info);
@@ -3055,11 +3254,12 @@ e1000_validate_mdi_setting(struct e1000_hw *hw)
*
* hw - Struct containing variables accessed by shared code
*****************************************************************************/
-void
+int32_t
e1000_init_eeprom_params(struct e1000_hw *hw)
{
struct e1000_eeprom_info *eeprom = &hw->eeprom;
uint32_t eecd = E1000_READ_REG(hw, EECD);
+ int32_t ret_val = E1000_SUCCESS;
uint16_t eeprom_size;
DEBUGFUNC("e1000_init_eeprom_params");
@@ -3074,6 +3274,8 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
eeprom->opcode_bits = 3;
eeprom->address_bits = 6;
eeprom->delay_usec = 50;
+ eeprom->use_eerd = FALSE;
+ eeprom->use_eewr = FALSE;
break;
case e1000_82540:
case e1000_82545:
@@ -3090,6 +3292,8 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
eeprom->word_size = 64;
eeprom->address_bits = 6;
}
+ eeprom->use_eerd = FALSE;
+ eeprom->use_eewr = FALSE;
break;
case e1000_82541:
case e1000_82541_rev_2:
@@ -3118,42 +3322,60 @@ e1000_init_eeprom_params(struct e1000_hw *hw)
eeprom->address_bits = 6;
}
}
+ eeprom->use_eerd = FALSE;
+ eeprom->use_eewr = FALSE;
+ break;
+ case e1000_82573:
+ eeprom->type = e1000_eeprom_spi;
+ eeprom->opcode_bits = 8;
+ eeprom->delay_usec = 1;
+ if (eecd & E1000_EECD_ADDR_BITS) {
+ eeprom->page_size = 32;
+ eeprom->address_bits = 16;
+ } else {
+ eeprom->page_size = 8;
+ eeprom->address_bits = 8;
+ }
+ eeprom->use_eerd = TRUE;
+ eeprom->use_eewr = TRUE;
+ if(e1000_is_onboard_nvm_eeprom(hw) == FALSE) {
+ eeprom->type = e1000_eeprom_flash;
+ eeprom->word_size = 2048;
+
+ /* Ensure that the Autonomous FLASH update bit is cleared due to
+ * Flash update issue on parts which use a FLASH for NVM. */
+ eecd &= ~E1000_EECD_AUPDEN;
+ E1000_WRITE_REG(hw, EECD, eecd);
+ }
break;
default:
break;
}
if (eeprom->type == e1000_eeprom_spi) {
- eeprom->word_size = 64;
- if (e1000_read_eeprom(hw, EEPROM_CFG, 1, &eeprom_size) == 0) {
- eeprom_size &= EEPROM_SIZE_MASK;
-
- switch (eeprom_size) {
- case EEPROM_SIZE_16KB:
- eeprom->word_size = 8192;
- break;
- case EEPROM_SIZE_8KB:
- eeprom->word_size = 4096;
- break;
- case EEPROM_SIZE_4KB:
- eeprom->word_size = 2048;
- break;
- case EEPROM_SIZE_2KB:
- eeprom->word_size = 1024;
- break;
- case EEPROM_SIZE_1KB:
- eeprom->word_size = 512;
- break;
- case EEPROM_SIZE_512B:
- eeprom->word_size = 256;
- break;
- case EEPROM_SIZE_128B:
- default:
- eeprom->word_size = 64;
- break;
- }
+ /* eeprom_size will be an enum [0..8] that maps to eeprom sizes 128B to
+ * 32KB (incremented by powers of 2).
+ */
+ if(hw->mac_type <= e1000_82547_rev_2) {
+ /* Set to default value for initial eeprom read. */
+ eeprom->word_size = 64;
+ ret_val = e1000_read_eeprom(hw, EEPROM_CFG, 1, &eeprom_size);
+ if(ret_val)
+ return ret_val;
+ eeprom_size = (eeprom_size & EEPROM_SIZE_MASK) >> EEPROM_SIZE_SHIFT;
+ /* 256B eeprom size was not supported in earlier hardware, so we
+ * bump eeprom_size up one to ensure that "1" (which maps to 256B)
+ * is never the result used in the shifting logic below. */
+ if(eeprom_size)
+ eeprom_size++;
+ } else {
+ eeprom_size = (uint16_t)((eecd & E1000_EECD_SIZE_EX_MASK) >>
+ E1000_EECD_SIZE_EX_SHIFT);
}
+
+ eeprom->word_size = 1 << (eeprom_size + EEPROM_WORD_SIZE_SHIFT);
}
+ return ret_val;
}
/******************************************************************************
@@ -3306,8 +3528,12 @@ e1000_acquire_eeprom(struct e1000_hw *hw)
DEBUGFUNC("e1000_acquire_eeprom");
+ if(e1000_get_hw_eeprom_semaphore(hw))
+ return -E1000_ERR_EEPROM;
+
eecd = E1000_READ_REG(hw, EECD);
+ if (hw->mac_type != e1000_82573) {
/* Request EEPROM Access */
if(hw->mac_type > e1000_82544) {
eecd |= E1000_EECD_REQ;
@@ -3326,6 +3552,7 @@ e1000_acquire_eeprom(struct e1000_hw *hw)
return -E1000_ERR_EEPROM;
}
}
+ }
/* Setup EEPROM for Read/Write */
@@ -3443,6 +3670,8 @@ e1000_release_eeprom(struct e1000_hw *hw)
eecd &= ~E1000_EECD_REQ;
E1000_WRITE_REG(hw, EECD, eecd);
}
+
+ e1000_put_hw_eeprom_semaphore(hw);
}
/******************************************************************************
@@ -3504,8 +3733,10 @@ e1000_read_eeprom(struct e1000_hw *hw,
{
struct e1000_eeprom_info *eeprom = &hw->eeprom;
uint32_t i = 0;
+ int32_t ret_val;
DEBUGFUNC("e1000_read_eeprom");
+
/* A check for invalid values: offset too large, too many words, and not
* enough words.
*/
@@ -3515,9 +3746,23 @@ e1000_read_eeprom(struct e1000_hw *hw,
return -E1000_ERR_EEPROM;
}
- /* Prepare the EEPROM for reading */
- if(e1000_acquire_eeprom(hw) != E1000_SUCCESS)
- return -E1000_ERR_EEPROM;
+ /* FLASH reads without acquiring the semaphore are safe in 82573-based
+ * controllers.
+ */
+ if ((e1000_is_onboard_nvm_eeprom(hw) == TRUE) ||
+ (hw->mac_type != e1000_82573)) {
+ /* Prepare the EEPROM for reading */
+ if(e1000_acquire_eeprom(hw) != E1000_SUCCESS)
+ return -E1000_ERR_EEPROM;
+ }
+
+ if(eeprom->use_eerd == TRUE) {
+ ret_val = e1000_read_eeprom_eerd(hw, offset, words, data);
+ if ((e1000_is_onboard_nvm_eeprom(hw) == TRUE) ||
+ (hw->mac_type != e1000_82573))
+ e1000_release_eeprom(hw);
+ return ret_val;
+ }
if(eeprom->type == e1000_eeprom_spi) {
uint16_t word_in;
@@ -3569,6 +3814,132 @@ e1000_read_eeprom(struct e1000_hw *hw,
}
/******************************************************************************
+ * Reads a 16 bit word from the EEPROM using the EERD register.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * offset - offset of word in the EEPROM to read
+ * data - word read from the EEPROM
+ * words - number of words to read
+ *****************************************************************************/
+int32_t
+e1000_read_eeprom_eerd(struct e1000_hw *hw,
+ uint16_t offset,
+ uint16_t words,
+ uint16_t *data)
+{
+ uint32_t i, eerd = 0;
+ int32_t error = 0;
+
+ for (i = 0; i < words; i++) {
+ eerd = ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) +
+ E1000_EEPROM_RW_REG_START;
+
+ E1000_WRITE_REG(hw, EERD, eerd);
+ error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_READ);
+
+ if(error) {
+ break;
+ }
+ data[i] = (E1000_READ_REG(hw, EERD) >> E1000_EEPROM_RW_REG_DATA);
+
+ }
+
+ return error;
+}
+
+/******************************************************************************
+ * Writes a 16 bit word from the EEPROM using the EEWR register.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * offset - offset of word in the EEPROM to read
+ * data - word read from the EEPROM
+ * words - number of words to read
+ *****************************************************************************/
+int32_t
+e1000_write_eeprom_eewr(struct e1000_hw *hw,
+ uint16_t offset,
+ uint16_t words,
+ uint16_t *data)
+{
+ uint32_t register_value = 0;
+ uint32_t i = 0;
+ int32_t error = 0;
+
+ for (i = 0; i < words; i++) {
+ register_value = (data[i] << E1000_EEPROM_RW_REG_DATA) |
+ ((offset+i) << E1000_EEPROM_RW_ADDR_SHIFT) |
+ E1000_EEPROM_RW_REG_START;
+
+ error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_WRITE);
+ if(error) {
+ break;
+ }
+
+ E1000_WRITE_REG(hw, EEWR, register_value);
+
+ error = e1000_poll_eerd_eewr_done(hw, E1000_EEPROM_POLL_WRITE);
+
+ if(error) {
+ break;
+ }
+ }
+
+ return error;
+}
+
+/******************************************************************************
+ * Polls the status bit (bit 1) of the EERD to determine when the read is done.
+ *
+ * hw - Struct containing variables accessed by shared code
+ *****************************************************************************/
+int32_t
+e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd)
+{
+ uint32_t attempts = 100000;
+ uint32_t i, reg = 0;
+ int32_t done = E1000_ERR_EEPROM;
+
+ for(i = 0; i < attempts; i++) {
+ if(eerd == E1000_EEPROM_POLL_READ)
+ reg = E1000_READ_REG(hw, EERD);
+ else
+ reg = E1000_READ_REG(hw, EEWR);
+
+ if(reg & E1000_EEPROM_RW_REG_DONE) {
+ done = E1000_SUCCESS;
+ break;
+ }
+ udelay(5);
+ }
+
+ return done;
+}
+
+/***************************************************************************
+* Description: Determines if the onboard NVM is FLASH or EEPROM.
+*
+* hw - Struct containing variables accessed by shared code
+****************************************************************************/
+boolean_t
+e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw)
+{
+ uint32_t eecd = 0;
+
+ if(hw->mac_type == e1000_82573) {
+ eecd = E1000_READ_REG(hw, EECD);
+
+ /* Isolate bits 15 & 16 */
+ eecd = ((eecd >> 15) & 0x03);
+
+ /* If both bits are set, device is Flash type */
+ if(eecd == 0x03) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/******************************************************************************
* Verifies that the EEPROM has a valid checksum
*
* hw - Struct containing variables accessed by shared code
@@ -3585,6 +3956,25 @@ e1000_validate_eeprom_checksum(struct e1000_hw *hw)
DEBUGFUNC("e1000_validate_eeprom_checksum");
+ if ((hw->mac_type == e1000_82573) &&
+ (e1000_is_onboard_nvm_eeprom(hw) == FALSE)) {
+ /* Check bit 4 of word 10h. If it is 0, firmware is done updating
+ * 10h-12h. Checksum may need to be fixed. */
+ e1000_read_eeprom(hw, 0x10, 1, &eeprom_data);
+ if ((eeprom_data & 0x10) == 0) {
+ /* Read 0x23 and check bit 15. This bit is a 1 when the checksum
+ * has already been fixed. If the checksum is still wrong and this
+ * bit is a 1, we need to return bad checksum. Otherwise, we need
+ * to set this bit to a 1 and update the checksum. */
+ e1000_read_eeprom(hw, 0x23, 1, &eeprom_data);
+ if ((eeprom_data & 0x8000) == 0) {
+ eeprom_data |= 0x8000;
+ e1000_write_eeprom(hw, 0x23, 1, &eeprom_data);
+ e1000_update_eeprom_checksum(hw);
+ }
+ }
+ }
+
for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) {
if(e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) {
DEBUGOUT("EEPROM Read Error\n");
@@ -3628,6 +4018,8 @@ e1000_update_eeprom_checksum(struct e1000_hw *hw)
if(e1000_write_eeprom(hw, EEPROM_CHECKSUM_REG, 1, &checksum) < 0) {
DEBUGOUT("EEPROM Write Error\n");
return -E1000_ERR_EEPROM;
+ } else if (hw->eeprom.type == e1000_eeprom_flash) {
+ e1000_commit_shadow_ram(hw);
}
return E1000_SUCCESS;
}
@@ -3663,6 +4055,10 @@ e1000_write_eeprom(struct e1000_hw *hw,
return -E1000_ERR_EEPROM;
}
+ /* 82573 reads only through eerd */
+ if(eeprom->use_eewr == TRUE)
+ return e1000_write_eeprom_eewr(hw, offset, words, data);
+
/* Prepare the EEPROM for writing */
if (e1000_acquire_eeprom(hw) != E1000_SUCCESS)
return -E1000_ERR_EEPROM;
@@ -3833,6 +4229,65 @@ e1000_write_eeprom_microwire(struct e1000_hw *hw,
}
/******************************************************************************
+ * Flushes the cached eeprom to NVM. This is done by saving the modified values
+ * in the eeprom cache and the non modified values in the currently active bank
+ * to the new bank.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * offset - offset of word in the EEPROM to read
+ * data - word read from the EEPROM
+ * words - number of words to read
+ *****************************************************************************/
+int32_t
+e1000_commit_shadow_ram(struct e1000_hw *hw)
+{
+ uint32_t attempts = 100000;
+ uint32_t eecd = 0;
+ uint32_t flop = 0;
+ uint32_t i = 0;
+ int32_t error = E1000_SUCCESS;
+
+ /* The flop register will be used to determine if flash type is STM */
+ flop = E1000_READ_REG(hw, FLOP);
+
+ if (hw->mac_type == e1000_82573) {
+ for (i=0; i < attempts; i++) {
+ eecd = E1000_READ_REG(hw, EECD);
+ if ((eecd & E1000_EECD_FLUPD) == 0) {
+ break;
+ }
+ udelay(5);
+ }
+
+ if (i == attempts) {
+ return -E1000_ERR_EEPROM;
+ }
+
+ /* If STM opcode located in bits 15:8 of flop, reset firmware */
+ if ((flop & 0xFF00) == E1000_STM_OPCODE) {
+ E1000_WRITE_REG(hw, HICR, E1000_HICR_FW_RESET);
+ }
+
+ /* Perform the flash update */
+ E1000_WRITE_REG(hw, EECD, eecd | E1000_EECD_FLUPD);
+
+ for (i=0; i < attempts; i++) {
+ eecd = E1000_READ_REG(hw, EECD);
+ if ((eecd & E1000_EECD_FLUPD) == 0) {
+ break;
+ }
+ udelay(5);
+ }
+
+ if (i == attempts) {
+ return -E1000_ERR_EEPROM;
+ }
+ }
+
+ return error;
+}
+
+/******************************************************************************
* Reads the adapter's part number from the EEPROM
*
* hw - Struct containing variables accessed by shared code
@@ -3911,6 +4366,7 @@ void
e1000_init_rx_addrs(struct e1000_hw *hw)
{
uint32_t i;
+ uint32_t rar_num;
DEBUGFUNC("e1000_init_rx_addrs");
@@ -3919,9 +4375,10 @@ e1000_init_rx_addrs(struct e1000_hw *hw)
e1000_rar_set(hw, hw->mac_addr, 0);
+ rar_num = E1000_RAR_ENTRIES;
/* Zero out the other 15 receive addresses. */
DEBUGOUT("Clearing RAR[1-15]\n");
- for(i = 1; i < E1000_RAR_ENTRIES; i++) {
+ for(i = 1; i < rar_num; i++) {
E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
}
@@ -3950,7 +4407,9 @@ e1000_mc_addr_list_update(struct e1000_hw *hw,
{
uint32_t hash_value;
uint32_t i;
-
+ uint32_t num_rar_entry;
+ uint32_t num_mta_entry;
+
DEBUGFUNC("e1000_mc_addr_list_update");
/* Set the new number of MC addresses that we are being requested to use. */
@@ -3958,14 +4417,16 @@ e1000_mc_addr_list_update(struct e1000_hw *hw,
/* Clear RAR[1-15] */
DEBUGOUT(" Clearing RAR[1-15]\n");
- for(i = rar_used_count; i < E1000_RAR_ENTRIES; i++) {
+ num_rar_entry = E1000_RAR_ENTRIES;
+ for(i = rar_used_count; i < num_rar_entry; i++) {
E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0);
E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0);
}
/* Clear the MTA */
DEBUGOUT(" Clearing MTA\n");
- for(i = 0; i < E1000_NUM_MTA_REGISTERS; i++) {
+ num_mta_entry = E1000_NUM_MTA_REGISTERS;
+ for(i = 0; i < num_mta_entry; i++) {
E1000_WRITE_REG_ARRAY(hw, MTA, i, 0);
}
@@ -3989,7 +4450,7 @@ e1000_mc_addr_list_update(struct e1000_hw *hw,
/* Place this multicast address in the RAR if there is room, *
* else put it in the MTA
*/
- if(rar_used_count < E1000_RAR_ENTRIES) {
+ if (rar_used_count < num_rar_entry) {
e1000_rar_set(hw,
mc_addr_list + (i * (ETH_LENGTH_OF_ADDRESS + pad)),
rar_used_count);
@@ -4040,6 +4501,7 @@ e1000_hash_mc_addr(struct e1000_hw *hw,
}
hash_value &= 0xFFF;
+
return hash_value;
}
@@ -4144,12 +4606,33 @@ void
e1000_clear_vfta(struct e1000_hw *hw)
{
uint32_t offset;
-
- for(offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++)
- E1000_WRITE_REG_ARRAY(hw, VFTA, offset, 0);
+ uint32_t vfta_value = 0;
+ uint32_t vfta_offset = 0;
+ uint32_t vfta_bit_in_reg = 0;
+
+ if (hw->mac_type == e1000_82573) {
+ if (hw->mng_cookie.vlan_id != 0) {
+ /* The VFTA is a 4096b bit-field, each identifying a single VLAN
+ * ID. The following operations determine which 32b entry
+ * (i.e. offset) into the array we want to set the VLAN ID
+ * (i.e. bit) of the manageability unit. */
+ vfta_offset = (hw->mng_cookie.vlan_id >>
+ E1000_VFTA_ENTRY_SHIFT) &
+ E1000_VFTA_ENTRY_MASK;
+ vfta_bit_in_reg = 1 << (hw->mng_cookie.vlan_id &
+ E1000_VFTA_ENTRY_BIT_SHIFT_MASK);
+ }
+ }
+ for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
+ /* If the offset we want to clear is the same offset of the
+ * manageability VLAN ID, then clear all bits except that of the
+ * manageability unit */
+ vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0;
+ E1000_WRITE_REG_ARRAY(hw, VFTA, offset, vfta_value);
+ }
}
-static int32_t
+int32_t
e1000_id_led_init(struct e1000_hw * hw)
{
uint32_t ledctl;
@@ -4480,6 +4963,19 @@ e1000_clear_hw_cntrs(struct e1000_hw *hw)
temp = E1000_READ_REG(hw, MGTPRC);
temp = E1000_READ_REG(hw, MGTPDC);
temp = E1000_READ_REG(hw, MGTPTC);
+
+ if(hw->mac_type <= e1000_82547_rev_2) return;
+
+ temp = E1000_READ_REG(hw, IAC);
+ temp = E1000_READ_REG(hw, ICRXOC);
+ temp = E1000_READ_REG(hw, ICRXPTC);
+ temp = E1000_READ_REG(hw, ICRXATC);
+ temp = E1000_READ_REG(hw, ICTXPTC);
+ temp = E1000_READ_REG(hw, ICTXATC);
+ temp = E1000_READ_REG(hw, ICTXQEC);
+ temp = E1000_READ_REG(hw, ICTXQMTC);
+ temp = E1000_READ_REG(hw, ICRXDMTC);
+
}
/******************************************************************************
@@ -4646,6 +5142,11 @@ e1000_get_bus_info(struct e1000_hw *hw)
hw->bus_speed = e1000_bus_speed_unknown;
hw->bus_width = e1000_bus_width_unknown;
break;
+ case e1000_82573:
+ hw->bus_type = e1000_bus_type_pci_express;
+ hw->bus_speed = e1000_bus_speed_2500;
+ hw->bus_width = e1000_bus_width_pciex_4;
+ break;
default:
status = E1000_READ_REG(hw, STATUS);
hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ?
@@ -4749,6 +5250,7 @@ e1000_get_cable_length(struct e1000_hw *hw,
/* Use old method for Phy older than IGP */
if(hw->phy_type == e1000_phy_m88) {
+
ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
&phy_data);
if(ret_val)
@@ -4865,7 +5367,8 @@ e1000_check_polarity(struct e1000_hw *hw,
return ret_val;
*polarity = (phy_data & M88E1000_PSSR_REV_POLARITY) >>
M88E1000_PSSR_REV_POLARITY_SHIFT;
- } else if(hw->phy_type == e1000_phy_igp) {
+ } else if(hw->phy_type == e1000_phy_igp ||
+ hw->phy_type == e1000_phy_igp_2) {
/* Read the Status register to check the speed */
ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS,
&phy_data);
@@ -4917,7 +5420,8 @@ e1000_check_downshift(struct e1000_hw *hw)
DEBUGFUNC("e1000_check_downshift");
- if(hw->phy_type == e1000_phy_igp) {
+ if(hw->phy_type == e1000_phy_igp ||
+ hw->phy_type == e1000_phy_igp_2) {
ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH,
&phy_data);
if(ret_val)
@@ -4933,6 +5437,7 @@ e1000_check_downshift(struct e1000_hw *hw)
hw->speed_downgraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) >>
M88E1000_PSSR_DOWNSHIFT_SHIFT;
}
+
return E1000_SUCCESS;
}
@@ -5047,7 +5552,7 @@ e1000_config_dsp_after_link_change(struct e1000_hw *hw,
if(ret_val)
return ret_val;
- msec_delay(20);
+ msec_delay_irq(20);
ret_val = e1000_write_phy_reg(hw, 0x0000,
IGP01E1000_IEEE_FORCE_GIGA);
@@ -5071,7 +5576,7 @@ e1000_config_dsp_after_link_change(struct e1000_hw *hw,
if(ret_val)
return ret_val;
- msec_delay(20);
+ msec_delay_irq(20);
/* Now enable the transmitter */
ret_val = e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
@@ -5096,7 +5601,7 @@ e1000_config_dsp_after_link_change(struct e1000_hw *hw,
if(ret_val)
return ret_val;
- msec_delay(20);
+ msec_delay_irq(20);
ret_val = e1000_write_phy_reg(hw, 0x0000,
IGP01E1000_IEEE_FORCE_GIGA);
@@ -5112,7 +5617,7 @@ e1000_config_dsp_after_link_change(struct e1000_hw *hw,
if(ret_val)
return ret_val;
- msec_delay(20);
+ msec_delay_irq(20);
/* Now enable the transmitter */
ret_val = e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data);
@@ -5187,22 +5692,36 @@ e1000_set_d3_lplu_state(struct e1000_hw *hw,
uint16_t phy_data;
DEBUGFUNC("e1000_set_d3_lplu_state");
- if(!((hw->mac_type == e1000_82541_rev_2) ||
- (hw->mac_type == e1000_82547_rev_2)))
+ if(hw->phy_type != e1000_phy_igp && hw->phy_type != e1000_phy_igp_2)
return E1000_SUCCESS;
/* During driver activity LPLU should not be used or it will attain link
* from the lowest speeds starting from 10Mbps. The capability is used for
* Dx transitions and states */
- ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &phy_data);
- if(ret_val)
- return ret_val;
-
- if(!active) {
- phy_data &= ~IGP01E1000_GMII_FLEX_SPD;
- ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data);
+ if(hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2) {
+ ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &phy_data);
if(ret_val)
return ret_val;
+ } else {
+ ret_val = e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data);
+ if(ret_val)
+ return ret_val;
+ }
+
+ if(!active) {
+ if(hw->mac_type == e1000_82541_rev_2 ||
+ hw->mac_type == e1000_82547_rev_2) {
+ phy_data &= ~IGP01E1000_GMII_FLEX_SPD;
+ ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data);
+ if(ret_val)
+ return ret_val;
+ } else {
+ phy_data &= ~IGP02E1000_PM_D3_LPLU;
+ ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT,
+ phy_data);
+ if (ret_val)
+ return ret_val;
+ }
/* LPLU and SmartSpeed are mutually exclusive. LPLU is used during
* Dx states where the power conservation is most important. During
@@ -5236,11 +5755,105 @@ e1000_set_d3_lplu_state(struct e1000_hw *hw,
(hw->autoneg_advertised == AUTONEG_ADVERTISE_10_ALL ) ||
(hw->autoneg_advertised == AUTONEG_ADVERTISE_10_100_ALL)) {
- phy_data |= IGP01E1000_GMII_FLEX_SPD;
- ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data);
+ if(hw->mac_type == e1000_82541_rev_2 ||
+ hw->mac_type == e1000_82547_rev_2) {
+ phy_data |= IGP01E1000_GMII_FLEX_SPD;
+ ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, phy_data);
+ if(ret_val)
+ return ret_val;
+ } else {
+ phy_data |= IGP02E1000_PM_D3_LPLU;
+ ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT,
+ phy_data);
+ if (ret_val)
+ return ret_val;
+ }
+
+ /* When LPLU is enabled we should disable SmartSpeed */
+ ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data);
+ if(ret_val)
+ return ret_val;
+
+ phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, phy_data);
if(ret_val)
return ret_val;
+ }
+ return E1000_SUCCESS;
+}
+
+/*****************************************************************************
+ *
+ * This function sets the lplu d0 state according to the active flag. When
+ * activating lplu this function also disables smart speed and vise versa.
+ * lplu will not be activated unless the device autonegotiation advertisment
+ * meets standards of either 10 or 10/100 or 10/100/1000 at all duplexes.
+ * hw: Struct containing variables accessed by shared code
+ * active - true to enable lplu false to disable lplu.
+ *
+ * returns: - E1000_ERR_PHY if fail to read/write the PHY
+ * E1000_SUCCESS at any other case.
+ *
+ ****************************************************************************/
+
+int32_t
+e1000_set_d0_lplu_state(struct e1000_hw *hw,
+ boolean_t active)
+{
+ int32_t ret_val;
+ uint16_t phy_data;
+ DEBUGFUNC("e1000_set_d0_lplu_state");
+
+ if(hw->mac_type <= e1000_82547_rev_2)
+ return E1000_SUCCESS;
+
+ ret_val = e1000_read_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data);
+ if(ret_val)
+ return ret_val;
+
+ if (!active) {
+ phy_data &= ~IGP02E1000_PM_D0_LPLU;
+ ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, phy_data);
+ if (ret_val)
+ return ret_val;
+
+ /* LPLU and SmartSpeed are mutually exclusive. LPLU is used during
+ * Dx states where the power conservation is most important. During
+ * driver activity we should enable SmartSpeed, so performance is
+ * maintained. */
+ if (hw->smart_speed == e1000_smart_speed_on) {
+ ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ &phy_data);
+ if(ret_val)
+ return ret_val;
+
+ phy_data |= IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ phy_data);
+ if(ret_val)
+ return ret_val;
+ } else if (hw->smart_speed == e1000_smart_speed_off) {
+ ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ &phy_data);
+ if (ret_val)
+ return ret_val;
+
+ phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED;
+ ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
+ phy_data);
+ if(ret_val)
+ return ret_val;
+ }
+
+
+ } else {
+
+ phy_data |= IGP02E1000_PM_D0_LPLU;
+ ret_val = e1000_write_phy_reg(hw, IGP02E1000_PHY_POWER_MGMT, phy_data);
+ if (ret_val)
+ return ret_val;
+
/* When LPLU is enabled we should disable SmartSpeed */
ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data);
if(ret_val)
@@ -5318,6 +5931,338 @@ e1000_set_vco_speed(struct e1000_hw *hw)
return E1000_SUCCESS;
}
+
+/*****************************************************************************
+ * This function reads the cookie from ARC ram.
+ *
+ * returns: - E1000_SUCCESS .
+ ****************************************************************************/
+int32_t
+e1000_host_if_read_cookie(struct e1000_hw * hw, uint8_t *buffer)
+{
+ uint8_t i;
+ uint32_t offset = E1000_MNG_DHCP_COOKIE_OFFSET;
+ uint8_t length = E1000_MNG_DHCP_COOKIE_LENGTH;
+
+ length = (length >> 2);
+ offset = (offset >> 2);
+
+ for (i = 0; i < length; i++) {
+ *((uint32_t *) buffer + i) =
+ E1000_READ_REG_ARRAY_DWORD(hw, HOST_IF, offset + i);
+ }
+ return E1000_SUCCESS;
+}
+
+
+/*****************************************************************************
+ * This function checks whether the HOST IF is enabled for command operaton
+ * and also checks whether the previous command is completed.
+ * It busy waits in case of previous command is not completed.
+ *
+ * returns: - E1000_ERR_HOST_INTERFACE_COMMAND in case if is not ready or
+ * timeout
+ * - E1000_SUCCESS for success.
+ ****************************************************************************/
+int32_t
+e1000_mng_enable_host_if(struct e1000_hw * hw)
+{
+ uint32_t hicr;
+ uint8_t i;
+
+ /* Check that the host interface is enabled. */
+ hicr = E1000_READ_REG(hw, HICR);
+ if ((hicr & E1000_HICR_EN) == 0) {
+ DEBUGOUT("E1000_HOST_EN bit disabled.\n");
+ return -E1000_ERR_HOST_INTERFACE_COMMAND;
+ }
+ /* check the previous command is completed */
+ for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) {
+ hicr = E1000_READ_REG(hw, HICR);
+ if (!(hicr & E1000_HICR_C))
+ break;
+ msec_delay_irq(1);
+ }
+
+ if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) {
+ DEBUGOUT("Previous command timeout failed .\n");
+ return -E1000_ERR_HOST_INTERFACE_COMMAND;
+ }
+ return E1000_SUCCESS;
+}
+
+/*****************************************************************************
+ * This function writes the buffer content at the offset given on the host if.
+ * It also does alignment considerations to do the writes in most efficient way.
+ * Also fills up the sum of the buffer in *buffer parameter.
+ *
+ * returns - E1000_SUCCESS for success.
+ ****************************************************************************/
+int32_t
+e1000_mng_host_if_write(struct e1000_hw * hw, uint8_t *buffer,
+ uint16_t length, uint16_t offset, uint8_t *sum)
+{
+ uint8_t *tmp;
+ uint8_t *bufptr = buffer;
+ uint32_t data;
+ uint16_t remaining, i, j, prev_bytes;
+
+ /* sum = only sum of the data and it is not checksum */
+
+ if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) {
+ return -E1000_ERR_PARAM;
+ }
+
+ tmp = (uint8_t *)&data;
+ prev_bytes = offset & 0x3;
+ offset &= 0xFFFC;
+ offset >>= 2;
+
+ if (prev_bytes) {
+ data = E1000_READ_REG_ARRAY_DWORD(hw, HOST_IF, offset);
+ for (j = prev_bytes; j < sizeof(uint32_t); j++) {
+ *(tmp + j) = *bufptr++;
+ *sum += *(tmp + j);
+ }
+ E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, offset, data);
+ length -= j - prev_bytes;
+ offset++;
+ }
+
+ remaining = length & 0x3;
+ length -= remaining;
+
+ /* Calculate length in DWORDs */
+ length >>= 2;
+
+ /* The device driver writes the relevant command block into the
+ * ram area. */
+ for (i = 0; i < length; i++) {
+ for (j = 0; j < sizeof(uint32_t); j++) {
+ *(tmp + j) = *bufptr++;
+ *sum += *(tmp + j);
+ }
+
+ E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, offset + i, data);
+ }
+ if (remaining) {
+ for (j = 0; j < sizeof(uint32_t); j++) {
+ if (j < remaining)
+ *(tmp + j) = *bufptr++;
+ else
+ *(tmp + j) = 0;
+
+ *sum += *(tmp + j);
+ }
+ E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, offset + i, data);
+ }
+
+ return E1000_SUCCESS;
+}
+
+
+/*****************************************************************************
+ * This function writes the command header after does the checksum calculation.
+ *
+ * returns - E1000_SUCCESS for success.
+ ****************************************************************************/
+int32_t
+e1000_mng_write_cmd_header(struct e1000_hw * hw,
+ struct e1000_host_mng_command_header * hdr)
+{
+ uint16_t i;
+ uint8_t sum;
+ uint8_t *buffer;
+
+ /* Write the whole command header structure which includes sum of
+ * the buffer */
+
+ uint16_t length = sizeof(struct e1000_host_mng_command_header);
+
+ sum = hdr->checksum;
+ hdr->checksum = 0;
+
+ buffer = (uint8_t *) hdr;
+ i = length;
+ while(i--)
+ sum += buffer[i];
+
+ hdr->checksum = 0 - sum;
+
+ length >>= 2;
+ /* The device driver writes the relevant command block into the ram area. */
+ for (i = 0; i < length; i++)
+ E1000_WRITE_REG_ARRAY_DWORD(hw, HOST_IF, i, *((uint32_t *) hdr + i));
+
+ return E1000_SUCCESS;
+}
+
+
+/*****************************************************************************
+ * This function indicates to ARC that a new command is pending which completes
+ * one write operation by the driver.
+ *
+ * returns - E1000_SUCCESS for success.
+ ****************************************************************************/
+int32_t
+e1000_mng_write_commit(
+ struct e1000_hw * hw)
+{
+ uint32_t hicr;
+
+ hicr = E1000_READ_REG(hw, HICR);
+ /* Setting this bit tells the ARC that a new command is pending. */
+ E1000_WRITE_REG(hw, HICR, hicr | E1000_HICR_C);
+
+ return E1000_SUCCESS;
+}
+
+
+/*****************************************************************************
+ * This function checks the mode of the firmware.
+ *
+ * returns - TRUE when the mode is IAMT or FALSE.
+ ****************************************************************************/
+boolean_t
+e1000_check_mng_mode(
+ struct e1000_hw *hw)
+{
+ uint32_t fwsm;
+
+ fwsm = E1000_READ_REG(hw, FWSM);
+
+ if((fwsm & E1000_FWSM_MODE_MASK) ==
+ (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT))
+ return TRUE;
+
+ return FALSE;
+}
+
+
+/*****************************************************************************
+ * This function writes the dhcp info .
+ ****************************************************************************/
+int32_t
+e1000_mng_write_dhcp_info(struct e1000_hw * hw, uint8_t *buffer,
+ uint16_t length)
+{
+ int32_t ret_val;
+ struct e1000_host_mng_command_header hdr;
+
+ hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD;
+ hdr.command_length = length;
+ hdr.reserved1 = 0;
+ hdr.reserved2 = 0;
+ hdr.checksum = 0;
+
+ ret_val = e1000_mng_enable_host_if(hw);
+ if (ret_val == E1000_SUCCESS) {
+ ret_val = e1000_mng_host_if_write(hw, buffer, length, sizeof(hdr),
+ &(hdr.checksum));
+ if (ret_val == E1000_SUCCESS) {
+ ret_val = e1000_mng_write_cmd_header(hw, &hdr);
+ if (ret_val == E1000_SUCCESS)
+ ret_val = e1000_mng_write_commit(hw);
+ }
+ }
+ return ret_val;
+}
+
+
+/*****************************************************************************
+ * This function calculates the checksum.
+ *
+ * returns - checksum of buffer contents.
+ ****************************************************************************/
+uint8_t
+e1000_calculate_mng_checksum(char *buffer, uint32_t length)
+{
+ uint8_t sum = 0;
+ uint32_t i;
+
+ if (!buffer)
+ return 0;
+
+ for (i=0; i < length; i++)
+ sum += buffer[i];
+
+ return (uint8_t) (0 - sum);
+}
+
+/*****************************************************************************
+ * This function checks whether tx pkt filtering needs to be enabled or not.
+ *
+ * returns - TRUE for packet filtering or FALSE.
+ ****************************************************************************/
+boolean_t
+e1000_enable_tx_pkt_filtering(struct e1000_hw *hw)
+{
+ /* called in init as well as watchdog timer functions */
+
+ int32_t ret_val, checksum;
+ boolean_t tx_filter = FALSE;
+ struct e1000_host_mng_dhcp_cookie *hdr = &(hw->mng_cookie);
+ uint8_t *buffer = (uint8_t *) &(hw->mng_cookie);
+
+ if (e1000_check_mng_mode(hw)) {
+ ret_val = e1000_mng_enable_host_if(hw);
+ if (ret_val == E1000_SUCCESS) {
+ ret_val = e1000_host_if_read_cookie(hw, buffer);
+ if (ret_val == E1000_SUCCESS) {
+ checksum = hdr->checksum;
+ hdr->checksum = 0;
+ if ((hdr->signature == E1000_IAMT_SIGNATURE) &&
+ checksum == e1000_calculate_mng_checksum((char *)buffer,
+ E1000_MNG_DHCP_COOKIE_LENGTH)) {
+ if (hdr->status &
+ E1000_MNG_DHCP_COOKIE_STATUS_PARSING_SUPPORT)
+ tx_filter = TRUE;
+ } else
+ tx_filter = TRUE;
+ } else
+ tx_filter = TRUE;
+ }
+ }
+
+ hw->tx_pkt_filtering = tx_filter;
+ return tx_filter;
+}
+
+/******************************************************************************
+ * Verifies the hardware needs to allow ARPs to be processed by the host
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * returns: - TRUE/FALSE
+ *
+ *****************************************************************************/
+uint32_t
+e1000_enable_mng_pass_thru(struct e1000_hw *hw)
+{
+ uint32_t manc;
+ uint32_t fwsm, factps;
+
+ if (hw->asf_firmware_present) {
+ manc = E1000_READ_REG(hw, MANC);
+
+ if (!(manc & E1000_MANC_RCV_TCO_EN) ||
+ !(manc & E1000_MANC_EN_MAC_ADDR_FILTER))
+ return FALSE;
+ if (e1000_arc_subsystem_valid(hw) == TRUE) {
+ fwsm = E1000_READ_REG(hw, FWSM);
+ factps = E1000_READ_REG(hw, FACTPS);
+
+ if (((fwsm & E1000_FWSM_MODE_MASK) ==
+ (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT)) &&
+ (factps & E1000_FACTPS_MNGCG))
+ return TRUE;
+ } else
+ if ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN))
+ return TRUE;
+ }
+ return FALSE;
+}
+
static int32_t
e1000_polarity_reversal_workaround(struct e1000_hw *hw)
{
@@ -5403,3 +6348,265 @@ e1000_polarity_reversal_workaround(struct e1000_hw *hw)
return E1000_SUCCESS;
}
+/***************************************************************************
+ *
+ * Disables PCI-Express master access.
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ * returns: - none.
+ *
+ ***************************************************************************/
+void
+e1000_set_pci_express_master_disable(struct e1000_hw *hw)
+{
+ uint32_t ctrl;
+
+ DEBUGFUNC("e1000_set_pci_express_master_disable");
+
+ if (hw->bus_type != e1000_bus_type_pci_express)
+ return;
+
+ ctrl = E1000_READ_REG(hw, CTRL);
+ ctrl |= E1000_CTRL_GIO_MASTER_DISABLE;
+ E1000_WRITE_REG(hw, CTRL, ctrl);
+}
+
+/***************************************************************************
+ *
+ * Enables PCI-Express master access.
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ * returns: - none.
+ *
+ ***************************************************************************/
+void
+e1000_enable_pciex_master(struct e1000_hw *hw)
+{
+ uint32_t ctrl;
+
+ DEBUGFUNC("e1000_enable_pciex_master");
+
+ if (hw->bus_type != e1000_bus_type_pci_express)
+ return;
+
+ ctrl = E1000_READ_REG(hw, CTRL);
+ ctrl &= ~E1000_CTRL_GIO_MASTER_DISABLE;
+ E1000_WRITE_REG(hw, CTRL, ctrl);
+}
+
+/*******************************************************************************
+ *
+ * Disables PCI-Express master access and verifies there are no pending requests
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ * returns: - E1000_ERR_MASTER_REQUESTS_PENDING if master disable bit hasn't
+ * caused the master requests to be disabled.
+ * E1000_SUCCESS master requests disabled.
+ *
+ ******************************************************************************/
+int32_t
+e1000_disable_pciex_master(struct e1000_hw *hw)
+{
+ int32_t timeout = MASTER_DISABLE_TIMEOUT; /* 80ms */
+
+ DEBUGFUNC("e1000_disable_pciex_master");
+
+ if (hw->bus_type != e1000_bus_type_pci_express)
+ return E1000_SUCCESS;
+
+ e1000_set_pci_express_master_disable(hw);
+
+ while(timeout) {
+ if(!(E1000_READ_REG(hw, STATUS) & E1000_STATUS_GIO_MASTER_ENABLE))
+ break;
+ else
+ udelay(100);
+ timeout--;
+ }
+
+ if(!timeout) {
+ DEBUGOUT("Master requests are pending.\n");
+ return -E1000_ERR_MASTER_REQUESTS_PENDING;
+ }
+
+ return E1000_SUCCESS;
+}
+
+/*******************************************************************************
+ *
+ * Check for EEPROM Auto Read bit done.
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ * returns: - E1000_ERR_RESET if fail to reset MAC
+ * E1000_SUCCESS at any other case.
+ *
+ ******************************************************************************/
+int32_t
+e1000_get_auto_rd_done(struct e1000_hw *hw)
+{
+ int32_t timeout = AUTO_READ_DONE_TIMEOUT;
+
+ DEBUGFUNC("e1000_get_auto_rd_done");
+
+ switch (hw->mac_type) {
+ default:
+ msec_delay(5);
+ break;
+ case e1000_82573:
+ while(timeout) {
+ if (E1000_READ_REG(hw, EECD) & E1000_EECD_AUTO_RD) break;
+ else msec_delay(1);
+ timeout--;
+ }
+
+ if(!timeout) {
+ DEBUGOUT("Auto read by HW from EEPROM has not completed.\n");
+ return -E1000_ERR_RESET;
+ }
+ break;
+ }
+
+ return E1000_SUCCESS;
+}
+
+/***************************************************************************
+ * Checks if the PHY configuration is done
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ * returns: - E1000_ERR_RESET if fail to reset MAC
+ * E1000_SUCCESS at any other case.
+ *
+ ***************************************************************************/
+int32_t
+e1000_get_phy_cfg_done(struct e1000_hw *hw)
+{
+ DEBUGFUNC("e1000_get_phy_cfg_done");
+
+ /* Simply wait for 10ms */
+ msec_delay(10);
+
+ return E1000_SUCCESS;
+}
+
+/***************************************************************************
+ *
+ * Using the combination of SMBI and SWESMBI semaphore bits when resetting
+ * adapter or Eeprom access.
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ * returns: - E1000_ERR_EEPROM if fail to access EEPROM.
+ * E1000_SUCCESS at any other case.
+ *
+ ***************************************************************************/
+int32_t
+e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw)
+{
+ int32_t timeout;
+ uint32_t swsm;
+
+ DEBUGFUNC("e1000_get_hw_eeprom_semaphore");
+
+ if(!hw->eeprom_semaphore_present)
+ return E1000_SUCCESS;
+
+
+ /* Get the FW semaphore. */
+ timeout = hw->eeprom.word_size + 1;
+ while(timeout) {
+ swsm = E1000_READ_REG(hw, SWSM);
+ swsm |= E1000_SWSM_SWESMBI;
+ E1000_WRITE_REG(hw, SWSM, swsm);
+ /* if we managed to set the bit we got the semaphore. */
+ swsm = E1000_READ_REG(hw, SWSM);
+ if(swsm & E1000_SWSM_SWESMBI)
+ break;
+
+ udelay(50);
+ timeout--;
+ }
+
+ if(!timeout) {
+ /* Release semaphores */
+ e1000_put_hw_eeprom_semaphore(hw);
+ DEBUGOUT("Driver can't access the Eeprom - SWESMBI bit is set.\n");
+ return -E1000_ERR_EEPROM;
+ }
+
+ return E1000_SUCCESS;
+}
+
+/***************************************************************************
+ * This function clears HW semaphore bits.
+ *
+ * hw: Struct containing variables accessed by shared code
+ *
+ * returns: - None.
+ *
+ ***************************************************************************/
+void
+e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw)
+{
+ uint32_t swsm;
+
+ DEBUGFUNC("e1000_put_hw_eeprom_semaphore");
+
+ if(!hw->eeprom_semaphore_present)
+ return;
+
+ swsm = E1000_READ_REG(hw, SWSM);
+ /* Release both semaphores. */
+ swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI);
+ E1000_WRITE_REG(hw, SWSM, swsm);
+}
+
+/******************************************************************************
+ * Checks if PHY reset is blocked due to SOL/IDER session, for example.
+ * Returning E1000_BLK_PHY_RESET isn't necessarily an error. But it's up to
+ * the caller to figure out how to deal with it.
+ *
+ * hw - Struct containing variables accessed by shared code
+ *
+ * returns: - E1000_BLK_PHY_RESET
+ * E1000_SUCCESS
+ *
+ *****************************************************************************/
+int32_t
+e1000_check_phy_reset_block(struct e1000_hw *hw)
+{
+ uint32_t manc = 0;
+ if(hw->mac_type > e1000_82547_rev_2)
+ manc = E1000_READ_REG(hw, MANC);
+ return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ?
+ E1000_BLK_PHY_RESET : E1000_SUCCESS;
+}
+
+uint8_t
+e1000_arc_subsystem_valid(struct e1000_hw *hw)
+{
+ uint32_t fwsm;
+
+ /* On 8257x silicon, registers in the range of 0x8800 - 0x8FFC
+ * may not be provided a DMA clock when no manageability features are
+ * enabled. We do not want to perform any reads/writes to these registers
+ * if this is the case. We read FWSM to determine the manageability mode.
+ */
+ switch (hw->mac_type) {
+ case e1000_82573:
+ fwsm = E1000_READ_REG(hw, FWSM);
+ if((fwsm & E1000_FWSM_MODE_MASK) != 0)
+ return TRUE;
+ break;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+
+
diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
index f397e637a3c..a0263ee96c6 100644
--- a/drivers/net/e1000/e1000_hw.h
+++ b/drivers/net/e1000/e1000_hw.h
@@ -1,7 +1,7 @@
/*******************************************************************************
- Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+ Copyright(c) 1999 - 2005 Intel Corporation. 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
@@ -57,6 +57,7 @@ typedef enum {
e1000_82541_rev_2,
e1000_82547,
e1000_82547_rev_2,
+ e1000_82573,
e1000_num_macs
} e1000_mac_type;
@@ -64,6 +65,7 @@ typedef enum {
e1000_eeprom_uninitialized = 0,
e1000_eeprom_spi,
e1000_eeprom_microwire,
+ e1000_eeprom_flash,
e1000_num_eeprom_types
} e1000_eeprom_type;
@@ -96,6 +98,7 @@ typedef enum {
e1000_bus_type_unknown = 0,
e1000_bus_type_pci,
e1000_bus_type_pcix,
+ e1000_bus_type_pci_express,
e1000_bus_type_reserved
} e1000_bus_type;
@@ -107,6 +110,7 @@ typedef enum {
e1000_bus_speed_100,
e1000_bus_speed_120,
e1000_bus_speed_133,
+ e1000_bus_speed_2500,
e1000_bus_speed_reserved
} e1000_bus_speed;
@@ -115,6 +119,8 @@ typedef enum {
e1000_bus_width_unknown = 0,
e1000_bus_width_32,
e1000_bus_width_64,
+ e1000_bus_width_pciex_1,
+ e1000_bus_width_pciex_4,
e1000_bus_width_reserved
} e1000_bus_width;
@@ -196,6 +202,7 @@ typedef enum {
typedef enum {
e1000_phy_m88 = 0,
e1000_phy_igp,
+ e1000_phy_igp_2,
e1000_phy_undefined = 0xFF
} e1000_phy_type;
@@ -242,8 +249,19 @@ struct e1000_eeprom_info {
uint16_t address_bits;
uint16_t delay_usec;
uint16_t page_size;
+ boolean_t use_eerd;
+ boolean_t use_eewr;
};
+/* Flex ASF Information */
+#define E1000_HOST_IF_MAX_SIZE 2048
+
+typedef enum {
+ e1000_byte_align = 0,
+ e1000_word_align = 1,
+ e1000_dword_align = 2
+} e1000_align_type;
+
/* Error Codes */
@@ -254,11 +272,16 @@ struct e1000_eeprom_info {
#define E1000_ERR_PARAM 4
#define E1000_ERR_MAC_TYPE 5
#define E1000_ERR_PHY_TYPE 6
+#define E1000_ERR_RESET 9
+#define E1000_ERR_MASTER_REQUESTS_PENDING 10
+#define E1000_ERR_HOST_INTERFACE_COMMAND 11
+#define E1000_BLK_PHY_RESET 12
/* Function prototypes */
/* Initialization */
int32_t e1000_reset_hw(struct e1000_hw *hw);
int32_t e1000_init_hw(struct e1000_hw *hw);
+int32_t e1000_id_led_init(struct e1000_hw * hw);
int32_t e1000_set_mac_type(struct e1000_hw *hw);
void e1000_set_media_type(struct e1000_hw *hw);
@@ -275,7 +298,7 @@ int32_t e1000_force_mac_fc(struct e1000_hw *hw);
/* PHY */
int32_t e1000_read_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t *phy_data);
int32_t e1000_write_phy_reg(struct e1000_hw *hw, uint32_t reg_addr, uint16_t data);
-void e1000_phy_hw_reset(struct e1000_hw *hw);
+int32_t e1000_phy_hw_reset(struct e1000_hw *hw);
int32_t e1000_phy_reset(struct e1000_hw *hw);
int32_t e1000_detect_gig_phy(struct e1000_hw *hw);
int32_t e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info);
@@ -287,13 +310,86 @@ int32_t e1000_check_downshift(struct e1000_hw *hw);
int32_t e1000_validate_mdi_setting(struct e1000_hw *hw);
/* EEPROM Functions */
-void e1000_init_eeprom_params(struct e1000_hw *hw);
+int32_t e1000_init_eeprom_params(struct e1000_hw *hw);
+boolean_t e1000_is_onboard_nvm_eeprom(struct e1000_hw *hw);
+int32_t e1000_read_eeprom_eerd(struct e1000_hw *hw, uint16_t offset, uint16_t words, uint16_t *data);
+int32_t e1000_write_eeprom_eewr(struct e1000_hw *hw, uint16_t offset, uint16_t words, uint16_t *data);
+int32_t e1000_poll_eerd_eewr_done(struct e1000_hw *hw, int eerd);
+
+/* MNG HOST IF functions */
+uint32_t e1000_enable_mng_pass_thru(struct e1000_hw *hw);
+
+#define E1000_MNG_DHCP_TX_PAYLOAD_CMD 64
+#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8 /* Host Interface data length */
+
+#define E1000_MNG_DHCP_COMMAND_TIMEOUT 10 /* Time in ms to process MNG command */
+#define E1000_MNG_DHCP_COOKIE_OFFSET 0x6F0 /* Cookie offset */
+#define E1000_MNG_DHCP_COOKIE_LENGTH 0x10 /* Cookie length */
+#define E1000_MNG_IAMT_MODE 0x3
+#define E1000_IAMT_SIGNATURE 0x544D4149 /* Intel(R) Active Management Technology signature */
+
+#define E1000_MNG_DHCP_COOKIE_STATUS_PARSING_SUPPORT 0x1 /* DHCP parsing enabled */
+#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT 0x2 /* DHCP parsing enabled */
+#define E1000_VFTA_ENTRY_SHIFT 0x5
+#define E1000_VFTA_ENTRY_MASK 0x7F
+#define E1000_VFTA_ENTRY_BIT_SHIFT_MASK 0x1F
+
+struct e1000_host_mng_command_header {
+ uint8_t command_id;
+ uint8_t checksum;
+ uint16_t reserved1;
+ uint16_t reserved2;
+ uint16_t command_length;
+};
+
+struct e1000_host_mng_command_info {
+ struct e1000_host_mng_command_header command_header; /* Command Head/Command Result Head has 4 bytes */
+ uint8_t command_data[E1000_HI_MAX_MNG_DATA_LENGTH]; /* Command data can length 0..0x658*/
+};
+#ifdef __BIG_ENDIAN
+struct e1000_host_mng_dhcp_cookie{
+ uint32_t signature;
+ uint16_t vlan_id;
+ uint8_t reserved0;
+ uint8_t status;
+ uint32_t reserved1;
+ uint8_t checksum;
+ uint8_t reserved3;
+ uint16_t reserved2;
+};
+#else
+struct e1000_host_mng_dhcp_cookie{
+ uint32_t signature;
+ uint8_t status;
+ uint8_t reserved0;
+ uint16_t vlan_id;
+ uint32_t reserved1;
+ uint16_t reserved2;
+ uint8_t reserved3;
+ uint8_t checksum;
+};
+#endif
+
+int32_t e1000_mng_write_dhcp_info(struct e1000_hw *hw, uint8_t *buffer,
+ uint16_t length);
+boolean_t e1000_check_mng_mode(struct e1000_hw *hw);
+boolean_t e1000_enable_tx_pkt_filtering(struct e1000_hw *hw);
+int32_t e1000_mng_enable_host_if(struct e1000_hw *hw);
+int32_t e1000_mng_host_if_write(struct e1000_hw *hw, uint8_t *buffer,
+ uint16_t length, uint16_t offset, uint8_t *sum);
+int32_t e1000_mng_write_cmd_header(struct e1000_hw* hw,
+ struct e1000_host_mng_command_header* hdr);
+
+int32_t e1000_mng_write_commit(struct e1000_hw *hw);
+
int32_t e1000_read_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t words, uint16_t *data);
int32_t e1000_validate_eeprom_checksum(struct e1000_hw *hw);
int32_t e1000_update_eeprom_checksum(struct e1000_hw *hw);
int32_t e1000_write_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t words, uint16_t *data);
int32_t e1000_read_part_num(struct e1000_hw *hw, uint32_t * part_num);
int32_t e1000_read_mac_addr(struct e1000_hw * hw);
+int32_t e1000_swfw_sync_acquire(struct e1000_hw *hw, uint16_t mask);
+void e1000_swfw_sync_release(struct e1000_hw *hw, uint16_t mask);
/* Filters (multicast, vlan, receive) */
void e1000_init_rx_addrs(struct e1000_hw *hw);
@@ -313,7 +409,6 @@ int32_t e1000_led_off(struct e1000_hw *hw);
/* Adaptive IFS Functions */
/* Everything else */
-uint32_t e1000_enable_mng_pass_thru(struct e1000_hw *hw);
void e1000_clear_hw_cntrs(struct e1000_hw *hw);
void e1000_reset_adaptive(struct e1000_hw *hw);
void e1000_update_adaptive(struct e1000_hw *hw);
@@ -330,6 +425,19 @@ void e1000_io_write(struct e1000_hw *hw, unsigned long port, uint32_t value);
void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value);
int32_t e1000_config_dsp_after_link_change(struct e1000_hw *hw, boolean_t link_up);
int32_t e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active);
+int32_t e1000_set_d0_lplu_state(struct e1000_hw *hw, boolean_t active);
+void e1000_set_pci_express_master_disable(struct e1000_hw *hw);
+void e1000_enable_pciex_master(struct e1000_hw *hw);
+int32_t e1000_disable_pciex_master(struct e1000_hw *hw);
+int32_t e1000_get_auto_rd_done(struct e1000_hw *hw);
+int32_t e1000_get_phy_cfg_done(struct e1000_hw *hw);
+int32_t e1000_get_software_semaphore(struct e1000_hw *hw);
+void e1000_release_software_semaphore(struct e1000_hw *hw);
+int32_t e1000_check_phy_reset_block(struct e1000_hw *hw);
+int32_t e1000_get_hw_eeprom_semaphore(struct e1000_hw *hw);
+void e1000_put_hw_eeprom_semaphore(struct e1000_hw *hw);
+int32_t e1000_commit_shadow_ram(struct e1000_hw *hw);
+uint8_t e1000_arc_subsystem_valid(struct e1000_hw *hw);
#define E1000_READ_REG_IO(a, reg) \
e1000_read_reg_io((a), E1000_##reg)
@@ -369,6 +477,10 @@ int32_t e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active);
#define E1000_DEV_ID_82546GB_SERDES 0x107B
#define E1000_DEV_ID_82546GB_PCIE 0x108A
#define E1000_DEV_ID_82547EI 0x1019
+#define E1000_DEV_ID_82573E 0x108B
+#define E1000_DEV_ID_82573E_IAMT 0x108C
+
+#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099
#define NODE_ADDRESS_SIZE 6
#define ETH_LENGTH_OF_ADDRESS 6
@@ -381,6 +493,7 @@ int32_t e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active);
#define E1000_REVISION_0 0
#define E1000_REVISION_1 1
#define E1000_REVISION_2 2
+#define E1000_REVISION_3 3
#define SPEED_10 10
#define SPEED_100 100
@@ -437,6 +550,7 @@ int32_t e1000_set_d3_lplu_state(struct e1000_hw *hw, boolean_t active);
E1000_IMS_RXSEQ | \
E1000_IMS_LSC)
+
/* Number of high/low register pairs in the RAR. The RAR (Receive Address
* Registers) holds the directed and multicast addresses that we monitor. We
* reserve one of these spots for our directed address, allowing us room for
@@ -457,14 +571,74 @@ struct e1000_rx_desc {
uint16_t special;
};
+/* Receive Descriptor - Extended */
+union e1000_rx_desc_extended {
+ struct {
+ uint64_t buffer_addr;
+ uint64_t reserved;
+ } read;
+ struct {
+ struct {
+ uint32_t mrq; /* Multiple Rx Queues */
+ union {
+ uint32_t rss; /* RSS Hash */
+ struct {
+ uint16_t ip_id; /* IP id */
+ uint16_t csum; /* Packet Checksum */
+ } csum_ip;
+ } hi_dword;
+ } lower;
+ struct {
+ uint32_t status_error; /* ext status/error */
+ uint16_t length;
+ uint16_t vlan; /* VLAN tag */
+ } upper;
+ } wb; /* writeback */
+};
+
+#define MAX_PS_BUFFERS 4
+/* Receive Descriptor - Packet Split */
+union e1000_rx_desc_packet_split {
+ struct {
+ /* one buffer for protocol header(s), three data buffers */
+ uint64_t buffer_addr[MAX_PS_BUFFERS];
+ } read;
+ struct {
+ struct {
+ uint32_t mrq; /* Multiple Rx Queues */
+ union {
+ uint32_t rss; /* RSS Hash */
+ struct {
+ uint16_t ip_id; /* IP id */
+ uint16_t csum; /* Packet Checksum */
+ } csum_ip;
+ } hi_dword;
+ } lower;
+ struct {
+ uint32_t status_error; /* ext status/error */
+ uint16_t length0; /* length of buffer 0 */
+ uint16_t vlan; /* VLAN tag */
+ } middle;
+ struct {
+ uint16_t header_status;
+ uint16_t length[3]; /* length of buffers 1-3 */
+ } upper;
+ uint64_t reserved;
+ } wb; /* writeback */
+};
+
/* Receive Decriptor bit definitions */
#define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */
#define E1000_RXD_STAT_EOP 0x02 /* End of Packet */
#define E1000_RXD_STAT_IXSM 0x04 /* Ignore checksum */
#define E1000_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */
+#define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum caculated */
#define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */
#define E1000_RXD_STAT_IPCS 0x40 /* IP xsum calculated */
#define E1000_RXD_STAT_PIF 0x80 /* passed in-exact filter */
+#define E1000_RXD_STAT_IPIDV 0x200 /* IP identification valid */
+#define E1000_RXD_STAT_UDPV 0x400 /* Valid UDP checksum */
+#define E1000_RXD_STAT_ACK 0x8000 /* ACK Packet indication */
#define E1000_RXD_ERR_CE 0x01 /* CRC Error */
#define E1000_RXD_ERR_SE 0x02 /* Symbol Error */
#define E1000_RXD_ERR_SEQ 0x04 /* Sequence Error */
@@ -474,9 +648,20 @@ struct e1000_rx_desc {
#define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */
#define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */
#define E1000_RXD_SPC_PRI_MASK 0xE000 /* Priority is in upper 3 bits */
-#define E1000_RXD_SPC_PRI_SHIFT 0x000D /* Priority is in upper 3 of 16 */
+#define E1000_RXD_SPC_PRI_SHIFT 13
#define E1000_RXD_SPC_CFI_MASK 0x1000 /* CFI is bit 12 */
-#define E1000_RXD_SPC_CFI_SHIFT 0x000C /* CFI is bit 12 */
+#define E1000_RXD_SPC_CFI_SHIFT 12
+
+#define E1000_RXDEXT_STATERR_CE 0x01000000
+#define E1000_RXDEXT_STATERR_SE 0x02000000
+#define E1000_RXDEXT_STATERR_SEQ 0x04000000
+#define E1000_RXDEXT_STATERR_CXE 0x10000000
+#define E1000_RXDEXT_STATERR_TCPE 0x20000000
+#define E1000_RXDEXT_STATERR_IPE 0x40000000
+#define E1000_RXDEXT_STATERR_RXE 0x80000000
+
+#define E1000_RXDPS_HDRSTAT_HDRSP 0x00008000
+#define E1000_RXDPS_HDRSTAT_HDRLEN_MASK 0x000003FF
/* mask to determine if packets should be dropped due to frame errors */
#define E1000_RXD_ERR_FRAME_ERR_MASK ( \
@@ -486,6 +671,15 @@ struct e1000_rx_desc {
E1000_RXD_ERR_CXE | \
E1000_RXD_ERR_RXE)
+
+/* Same mask, but for extended and packet split descriptors */
+#define E1000_RXDEXT_ERR_FRAME_ERR_MASK ( \
+ E1000_RXDEXT_STATERR_CE | \
+ E1000_RXDEXT_STATERR_SE | \
+ E1000_RXDEXT_STATERR_SEQ | \
+ E1000_RXDEXT_STATERR_CXE | \
+ E1000_RXDEXT_STATERR_RXE)
+
/* Transmit Descriptor */
struct e1000_tx_desc {
uint64_t buffer_addr; /* Address of the descriptor's data buffer */
@@ -667,6 +861,7 @@ struct e1000_ffvt_entry {
#define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */
#define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */
#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */
+#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */
#define E1000_RCTL 0x00100 /* RX Control - RW */
#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */
#define E1000_TXCW 0x00178 /* TX Configuration Word - RW */
@@ -676,9 +871,23 @@ struct e1000_ffvt_entry {
#define E1000_TBT 0x00448 /* TX Burst Timer - RW */
#define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */
#define E1000_LEDCTL 0x00E00 /* LED Control - RW */
+#define E1000_EXTCNF_CTRL 0x00F00 /* Extended Configuration Control */
+#define E1000_EXTCNF_SIZE 0x00F08 /* Extended Configuration Size */
#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */
+#define E1000_PBS 0x01008 /* Packet Buffer Size */
+#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */
+#define E1000_FLASH_UPDATES 1000
+#define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */
+#define E1000_FLASHT 0x01028 /* FLASH Timer Register */
+#define E1000_EEWR 0x0102C /* EEPROM Write Register - RW */
+#define E1000_FLSWCTL 0x01030 /* FLASH control register */
+#define E1000_FLSWDATA 0x01034 /* FLASH data register */
+#define E1000_FLSWCNT 0x01038 /* FLASH Access Counter */
+#define E1000_FLOP 0x0103C /* FLASH Opcode Register */
+#define E1000_ERT 0x02008 /* Early Rx Threshold - RW */
#define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */
#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */
+#define E1000_PSRCTL 0x02170 /* Packet Split Receive Control - RW */
#define E1000_RDBAL 0x02800 /* RX Descriptor Base Address Low - RW */
#define E1000_RDBAH 0x02804 /* RX Descriptor Base Address High - RW */
#define E1000_RDLEN 0x02808 /* RX Descriptor Length - RW */
@@ -688,6 +897,7 @@ struct e1000_ffvt_entry {
#define E1000_RXDCTL 0x02828 /* RX Descriptor Control - RW */
#define E1000_RADV 0x0282C /* RX Interrupt Absolute Delay Timer - RW */
#define E1000_RSRPD 0x02C00 /* RX Small Packet Detect - RW */
+#define E1000_RAID 0x02C08 /* Receive Ack Interrupt Delay - RW */
#define E1000_TXDMAC 0x03000 /* TX DMA Control - RW */
#define E1000_TDFH 0x03410 /* TX Data FIFO Head - RW */
#define E1000_TDFT 0x03418 /* TX Data FIFO Tail - RW */
@@ -703,6 +913,14 @@ struct e1000_ffvt_entry {
#define E1000_TXDCTL 0x03828 /* TX Descriptor Control - RW */
#define E1000_TADV 0x0382C /* TX Interrupt Absolute Delay Val - RW */
#define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */
+#define E1000_TARC0 0x03840 /* TX Arbitration Count (0) */
+#define E1000_TDBAL1 0x03900 /* TX Desc Base Address Low (1) - RW */
+#define E1000_TDBAH1 0x03904 /* TX Desc Base Address High (1) - RW */
+#define E1000_TDLEN1 0x03908 /* TX Desc Length (1) - RW */
+#define E1000_TDH1 0x03910 /* TX Desc Head (1) - RW */
+#define E1000_TDT1 0x03918 /* TX Desc Tail (1) - RW */
+#define E1000_TXDCTL1 0x03928 /* TX Descriptor Control (1) - RW */
+#define E1000_TARC1 0x03940 /* TX Arbitration Count (1) */
#define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */
#define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */
#define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */
@@ -761,7 +979,17 @@ struct e1000_ffvt_entry {
#define E1000_BPTC 0x040F4 /* Broadcast Packets TX Count - R/clr */
#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context TX - R/clr */
#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context TX Fail - R/clr */
+#define E1000_IAC 0x4100 /* Interrupt Assertion Count */
+#define E1000_ICRXPTC 0x4104 /* Interrupt Cause Rx Packet Timer Expire Count */
+#define E1000_ICRXATC 0x4108 /* Interrupt Cause Rx Absolute Timer Expire Count */
+#define E1000_ICTXPTC 0x410C /* Interrupt Cause Tx Packet Timer Expire Count */
+#define E1000_ICTXATC 0x4110 /* Interrupt Cause Tx Absolute Timer Expire Count */
+#define E1000_ICTXQEC 0x4118 /* Interrupt Cause Tx Queue Empty Count */
+#define E1000_ICTXQMTC 0x411C /* Interrupt Cause Tx Queue Minimum Threshold Count */
+#define E1000_ICRXDMTC 0x4120 /* Interrupt Cause Rx Descriptor Minimum Threshold Count */
+#define E1000_ICRXOC 0x4124 /* Interrupt Cause Receiver Overrun Count */
#define E1000_RXCSUM 0x05000 /* RX Checksum Control - RW */
+#define E1000_RFCTL 0x05008 /* Receive Filter Control*/
#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */
#define E1000_RA 0x05400 /* Receive Address - RW Array */
#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */
@@ -779,6 +1007,16 @@ struct e1000_ffvt_entry {
#define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */
#define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */
+#define E1000_GCR 0x05B00 /* PCI-Ex Control */
+#define E1000_GSCL_1 0x05B10 /* PCI-Ex Statistic Control #1 */
+#define E1000_GSCL_2 0x05B14 /* PCI-Ex Statistic Control #2 */
+#define E1000_GSCL_3 0x05B18 /* PCI-Ex Statistic Control #3 */
+#define E1000_GSCL_4 0x05B1C /* PCI-Ex Statistic Control #4 */
+#define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */
+#define E1000_SWSM 0x05B50 /* SW Semaphore */
+#define E1000_FWSM 0x05B54 /* FW Semaphore */
+#define E1000_FFLT_DBG 0x05F04 /* Debug Register */
+#define E1000_HICR 0x08F00 /* Host Inteface Control */
/* Register Set (82542)
*
* Some of the 82542 registers are located at different offsets than they are
@@ -829,6 +1067,18 @@ struct e1000_ffvt_entry {
#define E1000_82542_VFTA 0x00600
#define E1000_82542_LEDCTL E1000_LEDCTL
#define E1000_82542_PBA E1000_PBA
+#define E1000_82542_PBS E1000_PBS
+#define E1000_82542_EEMNGCTL E1000_EEMNGCTL
+#define E1000_82542_EEARBC E1000_EEARBC
+#define E1000_82542_FLASHT E1000_FLASHT
+#define E1000_82542_EEWR E1000_EEWR
+#define E1000_82542_FLSWCTL E1000_FLSWCTL
+#define E1000_82542_FLSWDATA E1000_FLSWDATA
+#define E1000_82542_FLSWCNT E1000_FLSWCNT
+#define E1000_82542_FLOP E1000_FLOP
+#define E1000_82542_EXTCNF_CTRL E1000_EXTCNF_CTRL
+#define E1000_82542_EXTCNF_SIZE E1000_EXTCNF_SIZE
+#define E1000_82542_ERT E1000_ERT
#define E1000_82542_RXDCTL E1000_RXDCTL
#define E1000_82542_RADV E1000_RADV
#define E1000_82542_RSRPD E1000_RSRPD
@@ -913,6 +1163,38 @@ struct e1000_ffvt_entry {
#define E1000_82542_FFMT E1000_FFMT
#define E1000_82542_FFVT E1000_FFVT
#define E1000_82542_HOST_IF E1000_HOST_IF
+#define E1000_82542_IAM E1000_IAM
+#define E1000_82542_EEMNGCTL E1000_EEMNGCTL
+#define E1000_82542_PSRCTL E1000_PSRCTL
+#define E1000_82542_RAID E1000_RAID
+#define E1000_82542_TARC0 E1000_TARC0
+#define E1000_82542_TDBAL1 E1000_TDBAL1
+#define E1000_82542_TDBAH1 E1000_TDBAH1
+#define E1000_82542_TDLEN1 E1000_TDLEN1
+#define E1000_82542_TDH1 E1000_TDH1
+#define E1000_82542_TDT1 E1000_TDT1
+#define E1000_82542_TXDCTL1 E1000_TXDCTL1
+#define E1000_82542_TARC1 E1000_TARC1
+#define E1000_82542_RFCTL E1000_RFCTL
+#define E1000_82542_GCR E1000_GCR
+#define E1000_82542_GSCL_1 E1000_GSCL_1
+#define E1000_82542_GSCL_2 E1000_GSCL_2
+#define E1000_82542_GSCL_3 E1000_GSCL_3
+#define E1000_82542_GSCL_4 E1000_GSCL_4
+#define E1000_82542_FACTPS E1000_FACTPS
+#define E1000_82542_SWSM E1000_SWSM
+#define E1000_82542_FWSM E1000_FWSM
+#define E1000_82542_FFLT_DBG E1000_FFLT_DBG
+#define E1000_82542_IAC E1000_IAC
+#define E1000_82542_ICRXPTC E1000_ICRXPTC
+#define E1000_82542_ICRXATC E1000_ICRXATC
+#define E1000_82542_ICTXPTC E1000_ICTXPTC
+#define E1000_82542_ICTXATC E1000_ICTXATC
+#define E1000_82542_ICTXQEC E1000_ICTXQEC
+#define E1000_82542_ICTXQMTC E1000_ICTXQMTC
+#define E1000_82542_ICRXDMTC E1000_ICRXDMTC
+#define E1000_82542_ICRXOC E1000_ICRXOC
+#define E1000_82542_HICR E1000_HICR
/* Statistics counters collected by the MAC */
struct e1000_hw_stats {
@@ -974,11 +1256,21 @@ struct e1000_hw_stats {
uint64_t bptc;
uint64_t tsctc;
uint64_t tsctfc;
+ uint64_t iac;
+ uint64_t icrxptc;
+ uint64_t icrxatc;
+ uint64_t ictxptc;
+ uint64_t ictxatc;
+ uint64_t ictxqec;
+ uint64_t ictxqmtc;
+ uint64_t icrxdmtc;
+ uint64_t icrxoc;
};
/* Structure containing variables used by the shared code (e1000_hw.c) */
struct e1000_hw {
- uint8_t __iomem *hw_addr;
+ uint8_t *hw_addr;
+ uint8_t *flash_address;
e1000_mac_type mac_type;
e1000_phy_type phy_type;
uint32_t phy_init_script;
@@ -993,6 +1285,7 @@ struct e1000_hw {
e1000_ms_type original_master_slave;
e1000_ffe_config ffe_config_state;
uint32_t asf_firmware_present;
+ uint32_t eeprom_semaphore_present;
unsigned long io_base;
uint32_t phy_id;
uint32_t phy_revision;
@@ -1009,6 +1302,8 @@ struct e1000_hw {
uint32_t ledctl_default;
uint32_t ledctl_mode1;
uint32_t ledctl_mode2;
+ boolean_t tx_pkt_filtering;
+ struct e1000_host_mng_dhcp_cookie mng_cookie;
uint16_t phy_spd_default;
uint16_t autoneg_advertised;
uint16_t pci_cmd_word;
@@ -1047,16 +1342,24 @@ struct e1000_hw {
boolean_t adaptive_ifs;
boolean_t ifs_params_forced;
boolean_t in_ifs_mode;
+ boolean_t mng_reg_access_disabled;
};
#define E1000_EEPROM_SWDPIN0 0x0001 /* SWDPIN 0 EEPROM Value */
#define E1000_EEPROM_LED_LOGIC 0x0020 /* Led Logic Word */
+#define E1000_EEPROM_RW_REG_DATA 16 /* Offset to data in EEPROM read/write registers */
+#define E1000_EEPROM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */
+#define E1000_EEPROM_RW_REG_START 1 /* First bit for telling part to start operation */
+#define E1000_EEPROM_RW_ADDR_SHIFT 2 /* Shift to the address bits */
+#define E1000_EEPROM_POLL_WRITE 1 /* Flag for polling for write complete */
+#define E1000_EEPROM_POLL_READ 0 /* Flag for polling for read complete */
/* Register Bit Masks */
/* Device Control */
#define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */
#define E1000_CTRL_BEM 0x00000002 /* Endian Mode.0=little,1=big */
#define E1000_CTRL_PRIOR 0x00000004 /* Priority on PCI. 0=rx,1=fair */
+#define E1000_CTRL_GIO_MASTER_DISABLE 0x00000004 /*Blocks new Master requests */
#define E1000_CTRL_LRST 0x00000008 /* Link reset. 0=normal,1=reset */
#define E1000_CTRL_TME 0x00000010 /* Test mode. 0=normal,1=test */
#define E1000_CTRL_SLE 0x00000020 /* Serial Link on 0=dis,1=en */
@@ -1070,6 +1373,7 @@ struct e1000_hw {
#define E1000_CTRL_BEM32 0x00000400 /* Big Endian 32 mode */
#define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */
#define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */
+#define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock indication in SDP[0] */
#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */
#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */
#define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */
@@ -1089,6 +1393,7 @@ struct e1000_hw {
#define E1000_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */
#define E1000_STATUS_LU 0x00000002 /* Link up.0=no,1=link */
#define E1000_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */
+#define E1000_STATUS_FUNC_SHIFT 2
#define E1000_STATUS_FUNC_0 0x00000000 /* Function 0 */
#define E1000_STATUS_FUNC_1 0x00000004 /* Function 1 */
#define E1000_STATUS_TXOFF 0x00000010 /* transmission paused */
@@ -1098,6 +1403,8 @@ struct e1000_hw {
#define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */
#define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */
#define E1000_STATUS_ASDV 0x00000300 /* Auto speed detect value */
+#define E1000_STATUS_DOCK_CI 0x00000800 /* Change in Dock/Undock state. Clear on write '0'. */
+#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Status of Master requests. */
#define E1000_STATUS_MTXCKOK 0x00000400 /* MTX clock running OK */
#define E1000_STATUS_PCI66 0x00000800 /* In 66Mhz slot */
#define E1000_STATUS_BUS64 0x00001000 /* In 64 bit slot */
@@ -1128,6 +1435,18 @@ struct e1000_hw {
#ifndef E1000_EEPROM_GRANT_ATTEMPTS
#define E1000_EEPROM_GRANT_ATTEMPTS 1000 /* EEPROM # attempts to gain grant */
#endif
+#define E1000_EECD_AUTO_RD 0x00000200 /* EEPROM Auto Read done */
+#define E1000_EECD_SIZE_EX_MASK 0x00007800 /* EEprom Size */
+#define E1000_EECD_SIZE_EX_SHIFT 11
+#define E1000_EECD_NVADDS 0x00018000 /* NVM Address Size */
+#define E1000_EECD_SELSHAD 0x00020000 /* Select Shadow RAM */
+#define E1000_EECD_INITSRAM 0x00040000 /* Initialize Shadow RAM */
+#define E1000_EECD_FLUPD 0x00080000 /* Update FLASH */
+#define E1000_EECD_AUPDEN 0x00100000 /* Enable Autonomous FLASH update */
+#define E1000_EECD_SHADV 0x00200000 /* Shadow RAM Data Valid */
+#define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */
+#define E1000_STM_OPCODE 0xDB00
+#define E1000_HICR_FW_RESET 0xC0
/* EEPROM Read */
#define E1000_EERD_START 0x00000001 /* Start Read */
@@ -1171,6 +1490,8 @@ struct e1000_hw {
#define E1000_CTRL_EXT_WR_WMARK_320 0x01000000
#define E1000_CTRL_EXT_WR_WMARK_384 0x02000000
#define E1000_CTRL_EXT_WR_WMARK_448 0x03000000
+#define E1000_CTRL_EXT_IAME 0x08000000 /* Interrupt acknowledge Auto-mask */
+#define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers after IMS clear */
/* MDI Control */
#define E1000_MDIC_DATA_MASK 0x0000FFFF
@@ -1187,14 +1508,17 @@ struct e1000_hw {
/* LED Control */
#define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F
#define E1000_LEDCTL_LED0_MODE_SHIFT 0
+#define E1000_LEDCTL_LED0_BLINK_RATE 0x0000020
#define E1000_LEDCTL_LED0_IVRT 0x00000040
#define E1000_LEDCTL_LED0_BLINK 0x00000080
#define E1000_LEDCTL_LED1_MODE_MASK 0x00000F00
#define E1000_LEDCTL_LED1_MODE_SHIFT 8
+#define E1000_LEDCTL_LED1_BLINK_RATE 0x0002000
#define E1000_LEDCTL_LED1_IVRT 0x00004000
#define E1000_LEDCTL_LED1_BLINK 0x00008000
#define E1000_LEDCTL_LED2_MODE_MASK 0x000F0000
#define E1000_LEDCTL_LED2_MODE_SHIFT 16
+#define E1000_LEDCTL_LED2_BLINK_RATE 0x00200000
#define E1000_LEDCTL_LED2_IVRT 0x00400000
#define E1000_LEDCTL_LED2_BLINK 0x00800000
#define E1000_LEDCTL_LED3_MODE_MASK 0x0F000000
@@ -1238,6 +1562,10 @@ struct e1000_hw {
#define E1000_ICR_GPI_EN3 0x00004000 /* GP Int 3 */
#define E1000_ICR_TXD_LOW 0x00008000
#define E1000_ICR_SRPD 0x00010000
+#define E1000_ICR_ACK 0x00020000 /* Receive Ack frame */
+#define E1000_ICR_MNG 0x00040000 /* Manageability event */
+#define E1000_ICR_DOCK 0x00080000 /* Dock/Undock */
+#define E1000_ICR_INT_ASSERTED 0x80000000 /* If this bit asserted, the driver should claim the interrupt */
/* Interrupt Cause Set */
#define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written back */
@@ -1255,6 +1583,9 @@ struct e1000_hw {
#define E1000_ICS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */
#define E1000_ICS_TXD_LOW E1000_ICR_TXD_LOW
#define E1000_ICS_SRPD E1000_ICR_SRPD
+#define E1000_ICS_ACK E1000_ICR_ACK /* Receive Ack frame */
+#define E1000_ICS_MNG E1000_ICR_MNG /* Manageability event */
+#define E1000_ICS_DOCK E1000_ICR_DOCK /* Dock/Undock */
/* Interrupt Mask Set */
#define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */
@@ -1272,6 +1603,9 @@ struct e1000_hw {
#define E1000_IMS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */
#define E1000_IMS_TXD_LOW E1000_ICR_TXD_LOW
#define E1000_IMS_SRPD E1000_ICR_SRPD
+#define E1000_IMS_ACK E1000_ICR_ACK /* Receive Ack frame */
+#define E1000_IMS_MNG E1000_ICR_MNG /* Manageability event */
+#define E1000_IMS_DOCK E1000_ICR_DOCK /* Dock/Undock */
/* Interrupt Mask Clear */
#define E1000_IMC_TXDW E1000_ICR_TXDW /* Transmit desc written back */
@@ -1289,6 +1623,9 @@ struct e1000_hw {
#define E1000_IMC_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */
#define E1000_IMC_TXD_LOW E1000_ICR_TXD_LOW
#define E1000_IMC_SRPD E1000_ICR_SRPD
+#define E1000_IMC_ACK E1000_ICR_ACK /* Receive Ack frame */
+#define E1000_IMC_MNG E1000_ICR_MNG /* Manageability event */
+#define E1000_IMC_DOCK E1000_ICR_DOCK /* Dock/Undock */
/* Receive Control */
#define E1000_RCTL_RST 0x00000001 /* Software reset */
@@ -1301,6 +1638,8 @@ struct e1000_hw {
#define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */
#define E1000_RCTL_LBM_SLP 0x00000080 /* serial link loopback mode */
#define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */
+#define E1000_RCTL_DTYP_MASK 0x00000C00 /* Descriptor type mask */
+#define E1000_RCTL_DTYP_PS 0x00000400 /* Packet Split descriptor */
#define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min threshold size */
#define E1000_RCTL_RDMTS_QUAT 0x00000100 /* rx desc min threshold size */
#define E1000_RCTL_RDMTS_EIGTH 0x00000200 /* rx desc min threshold size */
@@ -1327,6 +1666,34 @@ struct e1000_hw {
#define E1000_RCTL_PMCF 0x00800000 /* pass MAC control frames */
#define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */
#define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */
+#define E1000_RCTL_FLXBUF_MASK 0x78000000 /* Flexible buffer size */
+#define E1000_RCTL_FLXBUF_SHIFT 27 /* Flexible buffer shift */
+
+/* Use byte values for the following shift parameters
+ * Usage:
+ * psrctl |= (((ROUNDUP(value0, 128) >> E1000_PSRCTL_BSIZE0_SHIFT) &
+ * E1000_PSRCTL_BSIZE0_MASK) |
+ * ((ROUNDUP(value1, 1024) >> E1000_PSRCTL_BSIZE1_SHIFT) &
+ * E1000_PSRCTL_BSIZE1_MASK) |
+ * ((ROUNDUP(value2, 1024) << E1000_PSRCTL_BSIZE2_SHIFT) &
+ * E1000_PSRCTL_BSIZE2_MASK) |
+ * ((ROUNDUP(value3, 1024) << E1000_PSRCTL_BSIZE3_SHIFT) |;
+ * E1000_PSRCTL_BSIZE3_MASK))
+ * where value0 = [128..16256], default=256
+ * value1 = [1024..64512], default=4096
+ * value2 = [0..64512], default=4096
+ * value3 = [0..64512], default=0
+ */
+
+#define E1000_PSRCTL_BSIZE0_MASK 0x0000007F
+#define E1000_PSRCTL_BSIZE1_MASK 0x00003F00
+#define E1000_PSRCTL_BSIZE2_MASK 0x003F0000
+#define E1000_PSRCTL_BSIZE3_MASK 0x3F000000
+
+#define E1000_PSRCTL_BSIZE0_SHIFT 7 /* Shift _right_ 7 */
+#define E1000_PSRCTL_BSIZE1_SHIFT 2 /* Shift _right_ 2 */
+#define E1000_PSRCTL_BSIZE2_SHIFT 6 /* Shift _left_ 6 */
+#define E1000_PSRCTL_BSIZE3_SHIFT 14 /* Shift _left_ 14 */
/* Receive Descriptor */
#define E1000_RDT_DELAY 0x0000ffff /* Delay timer (1=1024us) */
@@ -1341,6 +1708,23 @@ struct e1000_hw {
#define E1000_FCRTL_RTL 0x0000FFF8 /* Mask Bits[15:3] for RTL */
#define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */
+/* Header split receive */
+#define E1000_RFCTL_ISCSI_DIS 0x00000001
+#define E1000_RFCTL_ISCSI_DWC_MASK 0x0000003E
+#define E1000_RFCTL_ISCSI_DWC_SHIFT 1
+#define E1000_RFCTL_NFSW_DIS 0x00000040
+#define E1000_RFCTL_NFSR_DIS 0x00000080
+#define E1000_RFCTL_NFS_VER_MASK 0x00000300
+#define E1000_RFCTL_NFS_VER_SHIFT 8
+#define E1000_RFCTL_IPV6_DIS 0x00000400
+#define E1000_RFCTL_IPV6_XSUM_DIS 0x00000800
+#define E1000_RFCTL_ACK_DIS 0x00001000
+#define E1000_RFCTL_ACKD_DIS 0x00002000
+#define E1000_RFCTL_IPFRSP_DIS 0x00004000
+#define E1000_RFCTL_EXTEN 0x00008000
+#define E1000_RFCTL_IPV6_EX_DIS 0x00010000
+#define E1000_RFCTL_NEW_IPV6_EXT_DIS 0x00020000
+
/* Receive Descriptor Control */
#define E1000_RXDCTL_PTHRESH 0x0000003F /* RXDCTL Prefetch Threshold */
#define E1000_RXDCTL_HTHRESH 0x00003F00 /* RXDCTL Host Threshold */
@@ -1354,6 +1738,8 @@ struct e1000_hw {
#define E1000_TXDCTL_GRAN 0x01000000 /* TXDCTL Granularity */
#define E1000_TXDCTL_LWTHRESH 0xFE000000 /* TXDCTL Low Threshold */
#define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */
+#define E1000_TXDCTL_COUNT_DESC 0x00400000 /* Enable the counting of desc.
+ still to be processed. */
/* Transmit Configuration Word */
#define E1000_TXCW_FD 0x00000020 /* TXCW full duplex */
@@ -1387,12 +1773,16 @@ struct e1000_hw {
#define E1000_TCTL_PBE 0x00800000 /* Packet Burst Enable */
#define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */
#define E1000_TCTL_NRTU 0x02000000 /* No Re-transmit on underrun */
+#define E1000_TCTL_MULR 0x10000000 /* Multiple request support */
/* Receive Checksum Control */
#define E1000_RXCSUM_PCSS_MASK 0x000000FF /* Packet Checksum Start */
#define E1000_RXCSUM_IPOFL 0x00000100 /* IPv4 checksum offload */
#define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */
#define E1000_RXCSUM_IPV6OFL 0x00000400 /* IPv6 checksum offload */
+#define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */
+#define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */
+
/* Definitions for power management and wakeup registers */
/* Wake Up Control */
@@ -1411,6 +1801,7 @@ struct e1000_hw {
#define E1000_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */
#define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */
#define E1000_WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Enable */
+#define E1000_WUFC_IGNORE_TCO 0x00008000 /* Ignore WakeOn TCO packets */
#define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */
#define E1000_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */
#define E1000_WUFC_FLX2 0x00040000 /* Flexible Filter 2 Enable */
@@ -1446,13 +1837,19 @@ struct e1000_hw {
#define E1000_MANC_ARP_EN 0x00002000 /* Enable ARP Request Filtering */
#define E1000_MANC_NEIGHBOR_EN 0x00004000 /* Enable Neighbor Discovery
* Filtering */
+#define E1000_MANC_ARP_RES_EN 0x00008000 /* Enable ARP response Filtering */
#define E1000_MANC_TCO_RESET 0x00010000 /* TCO Reset Occurred */
#define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */
#define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */
+#define E1000_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */
#define E1000_MANC_EN_MAC_ADDR_FILTER 0x00100000 /* Enable MAC address
* filtering */
#define E1000_MANC_EN_MNG2HOST 0x00200000 /* Enable MNG packets to host
* memory */
+#define E1000_MANC_EN_IP_ADDR_FILTER 0x00400000 /* Enable IP address
+ * filtering */
+#define E1000_MANC_EN_XSUM_FILTER 0x00800000 /* Enable checksum filtering */
+#define E1000_MANC_BR_EN 0x01000000 /* Enable broadcast filtering */
#define E1000_MANC_SMB_REQ 0x01000000 /* SMBus Request */
#define E1000_MANC_SMB_GNT 0x02000000 /* SMBus Grant */
#define E1000_MANC_SMB_CLK_IN 0x04000000 /* SMBus Clock In */
@@ -1463,11 +1860,97 @@ struct e1000_hw {
#define E1000_MANC_SMB_DATA_OUT_SHIFT 28 /* SMBus Data Out Shift */
#define E1000_MANC_SMB_CLK_OUT_SHIFT 29 /* SMBus Clock Out Shift */
+/* SW Semaphore Register */
+#define E1000_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */
+#define E1000_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */
+#define E1000_SWSM_WMNG 0x00000004 /* Wake MNG Clock */
+#define E1000_SWSM_DRV_LOAD 0x00000008 /* Driver Loaded Bit */
+
+/* FW Semaphore Register */
+#define E1000_FWSM_MODE_MASK 0x0000000E /* FW mode */
+#define E1000_FWSM_MODE_SHIFT 1
+#define E1000_FWSM_FW_VALID 0x00008000 /* FW established a valid mode */
+
+/* FFLT Debug Register */
+#define E1000_FFLT_DBG_INVC 0x00100000 /* Invalid /C/ code handling */
+
+typedef enum {
+ e1000_mng_mode_none = 0,
+ e1000_mng_mode_asf,
+ e1000_mng_mode_pt,
+ e1000_mng_mode_ipmi,
+ e1000_mng_mode_host_interface_only
+} e1000_mng_mode;
+
+/* Host Inteface Control Register */
+#define E1000_HICR_EN 0x00000001 /* Enable Bit - RO */
+#define E1000_HICR_C 0x00000002 /* Driver sets this bit when done
+ * to put command in RAM */
+#define E1000_HICR_SV 0x00000004 /* Status Validity */
+#define E1000_HICR_FWR 0x00000080 /* FW reset. Set by the Host */
+
+/* Host Interface Command Interface - Address range 0x8800-0x8EFF */
+#define E1000_HI_MAX_DATA_LENGTH 252 /* Host Interface data length */
+#define E1000_HI_MAX_BLOCK_BYTE_LENGTH 1792 /* Number of bytes in range */
+#define E1000_HI_MAX_BLOCK_DWORD_LENGTH 448 /* Number of dwords in range */
+#define E1000_HI_COMMAND_TIMEOUT 500 /* Time in ms to process HI command */
+
+struct e1000_host_command_header {
+ uint8_t command_id;
+ uint8_t command_length;
+ uint8_t command_options; /* I/F bits for command, status for return */
+ uint8_t checksum;
+};
+struct e1000_host_command_info {
+ struct e1000_host_command_header command_header; /* Command Head/Command Result Head has 4 bytes */
+ uint8_t command_data[E1000_HI_MAX_DATA_LENGTH]; /* Command data can length 0..252 */
+};
+
+/* Host SMB register #0 */
+#define E1000_HSMC0R_CLKIN 0x00000001 /* SMB Clock in */
+#define E1000_HSMC0R_DATAIN 0x00000002 /* SMB Data in */
+#define E1000_HSMC0R_DATAOUT 0x00000004 /* SMB Data out */
+#define E1000_HSMC0R_CLKOUT 0x00000008 /* SMB Clock out */
+
+/* Host SMB register #1 */
+#define E1000_HSMC1R_CLKIN E1000_HSMC0R_CLKIN
+#define E1000_HSMC1R_DATAIN E1000_HSMC0R_DATAIN
+#define E1000_HSMC1R_DATAOUT E1000_HSMC0R_DATAOUT
+#define E1000_HSMC1R_CLKOUT E1000_HSMC0R_CLKOUT
+
+/* FW Status Register */
+#define E1000_FWSTS_FWS_MASK 0x000000FF /* FW Status */
+
/* Wake Up Packet Length */
#define E1000_WUPL_LENGTH_MASK 0x0FFF /* Only the lower 12 bits are valid */
#define E1000_MDALIGN 4096
+#define E1000_GCR_BEM32 0x00400000
+/* Function Active and Power State to MNG */
+#define E1000_FACTPS_FUNC0_POWER_STATE_MASK 0x00000003
+#define E1000_FACTPS_LAN0_VALID 0x00000004
+#define E1000_FACTPS_FUNC0_AUX_EN 0x00000008
+#define E1000_FACTPS_FUNC1_POWER_STATE_MASK 0x000000C0
+#define E1000_FACTPS_FUNC1_POWER_STATE_SHIFT 6
+#define E1000_FACTPS_LAN1_VALID 0x00000100
+#define E1000_FACTPS_FUNC1_AUX_EN 0x00000200
+#define E1000_FACTPS_FUNC2_POWER_STATE_MASK 0x00003000
+#define E1000_FACTPS_FUNC2_POWER_STATE_SHIFT 12
+#define E1000_FACTPS_IDE_ENABLE 0x00004000
+#define E1000_FACTPS_FUNC2_AUX_EN 0x00008000
+#define E1000_FACTPS_FUNC3_POWER_STATE_MASK 0x000C0000
+#define E1000_FACTPS_FUNC3_POWER_STATE_SHIFT 18
+#define E1000_FACTPS_SP_ENABLE 0x00100000
+#define E1000_FACTPS_FUNC3_AUX_EN 0x00200000
+#define E1000_FACTPS_FUNC4_POWER_STATE_MASK 0x03000000
+#define E1000_FACTPS_FUNC4_POWER_STATE_SHIFT 24
+#define E1000_FACTPS_IPMI_ENABLE 0x04000000
+#define E1000_FACTPS_FUNC4_AUX_EN 0x08000000
+#define E1000_FACTPS_MNGCG 0x20000000
+#define E1000_FACTPS_LAN_FUNC_SEL 0x40000000
+#define E1000_FACTPS_PM_STATE_CHANGED 0x80000000
+
/* EEPROM Commands - Microwire */
#define EEPROM_READ_OPCODE_MICROWIRE 0x6 /* EEPROM read opcode */
#define EEPROM_WRITE_OPCODE_MICROWIRE 0x5 /* EEPROM write opcode */
@@ -1477,22 +1960,20 @@ struct e1000_hw {
/* EEPROM Commands - SPI */
#define EEPROM_MAX_RETRY_SPI 5000 /* Max wait of 5ms, for RDY signal */
-#define EEPROM_READ_OPCODE_SPI 0x3 /* EEPROM read opcode */
-#define EEPROM_WRITE_OPCODE_SPI 0x2 /* EEPROM write opcode */
-#define EEPROM_A8_OPCODE_SPI 0x8 /* opcode bit-3 = address bit-8 */
-#define EEPROM_WREN_OPCODE_SPI 0x6 /* EEPROM set Write Enable latch */
-#define EEPROM_WRDI_OPCODE_SPI 0x4 /* EEPROM reset Write Enable latch */
-#define EEPROM_RDSR_OPCODE_SPI 0x5 /* EEPROM read Status register */
-#define EEPROM_WRSR_OPCODE_SPI 0x1 /* EEPROM write Status register */
+#define EEPROM_READ_OPCODE_SPI 0x03 /* EEPROM read opcode */
+#define EEPROM_WRITE_OPCODE_SPI 0x02 /* EEPROM write opcode */
+#define EEPROM_A8_OPCODE_SPI 0x08 /* opcode bit-3 = address bit-8 */
+#define EEPROM_WREN_OPCODE_SPI 0x06 /* EEPROM set Write Enable latch */
+#define EEPROM_WRDI_OPCODE_SPI 0x04 /* EEPROM reset Write Enable latch */
+#define EEPROM_RDSR_OPCODE_SPI 0x05 /* EEPROM read Status register */
+#define EEPROM_WRSR_OPCODE_SPI 0x01 /* EEPROM write Status register */
+#define EEPROM_ERASE4K_OPCODE_SPI 0x20 /* EEPROM ERASE 4KB */
+#define EEPROM_ERASE64K_OPCODE_SPI 0xD8 /* EEPROM ERASE 64KB */
+#define EEPROM_ERASE256_OPCODE_SPI 0xDB /* EEPROM ERASE 256B */
/* EEPROM Size definitions */
-#define EEPROM_SIZE_16KB 0x1800
-#define EEPROM_SIZE_8KB 0x1400
-#define EEPROM_SIZE_4KB 0x1000
-#define EEPROM_SIZE_2KB 0x0C00
-#define EEPROM_SIZE_1KB 0x0800
-#define EEPROM_SIZE_512B 0x0400
-#define EEPROM_SIZE_128B 0x0000
+#define EEPROM_WORD_SIZE_SHIFT 6
+#define EEPROM_SIZE_SHIFT 10
#define EEPROM_SIZE_MASK 0x1C00
/* EEPROM Word Offsets */
@@ -1606,7 +2087,22 @@ struct e1000_hw {
#define IFS_MIN 40
#define IFS_RATIO 4
+/* Extended Configuration Control and Size */
+#define E1000_EXTCNF_CTRL_PCIE_WRITE_ENABLE 0x00000001
+#define E1000_EXTCNF_CTRL_PHY_WRITE_ENABLE 0x00000002
+#define E1000_EXTCNF_CTRL_D_UD_ENABLE 0x00000004
+#define E1000_EXTCNF_CTRL_D_UD_LATENCY 0x00000008
+#define E1000_EXTCNF_CTRL_D_UD_OWNER 0x00000010
+#define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP 0x00000020
+#define E1000_EXTCNF_CTRL_MDIO_HW_OWNERSHIP 0x00000040
+#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER 0x1FFF0000
+
+#define E1000_EXTCNF_SIZE_EXT_PHY_LENGTH 0x000000FF
+#define E1000_EXTCNF_SIZE_EXT_DOCK_LENGTH 0x0000FF00
+#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH 0x00FF0000
+
/* PBA constants */
+#define E1000_PBA_12K 0x000C /* 12KB, default Rx allocation */
#define E1000_PBA_16K 0x0010 /* 16KB, default TX allocation */
#define E1000_PBA_22K 0x0016
#define E1000_PBA_24K 0x0018
@@ -1663,6 +2159,13 @@ struct e1000_hw {
/* Number of milliseconds we wait for auto-negotiation to complete */
#define LINK_UP_TIMEOUT 500
+/* Number of 100 microseconds we wait for PCI Express master disable */
+#define MASTER_DISABLE_TIMEOUT 800
+/* Number of milliseconds we wait for Eeprom auto read bit done after MAC reset */
+#define AUTO_READ_DONE_TIMEOUT 10
+/* Number of milliseconds we wait for PHY configuration done after MAC reset */
+#define PHY_CFG_TIMEOUT 40
+
#define E1000_TX_BUFFER_SIZE ((uint32_t)1514)
/* The carrier extension symbol, as received by the NIC. */
@@ -1763,6 +2266,7 @@ struct e1000_hw {
#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health Register */
#define IGP01E1000_GMII_FIFO 0x14 /* GMII FIFO Register */
#define IGP01E1000_PHY_CHANNEL_QUALITY 0x15 /* PHY Channel Quality Register */
+#define IGP02E1000_PHY_POWER_MGMT 0x19
#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* PHY Page Select Core Register */
/* IGP01E1000 AGC Registers - stores the cable length values*/
@@ -1771,12 +2275,20 @@ struct e1000_hw {
#define IGP01E1000_PHY_AGC_C 0x1472
#define IGP01E1000_PHY_AGC_D 0x1872
+/* IGP02E1000 AGC Registers for cable length values */
+#define IGP02E1000_PHY_AGC_A 0x11B1
+#define IGP02E1000_PHY_AGC_B 0x12B1
+#define IGP02E1000_PHY_AGC_C 0x14B1
+#define IGP02E1000_PHY_AGC_D 0x18B1
+
/* IGP01E1000 DSP Reset Register */
#define IGP01E1000_PHY_DSP_RESET 0x1F33
#define IGP01E1000_PHY_DSP_SET 0x1F71
#define IGP01E1000_PHY_DSP_FFE 0x1F35
#define IGP01E1000_PHY_CHANNEL_NUM 4
+#define IGP02E1000_PHY_CHANNEL_NUM 4
+
#define IGP01E1000_PHY_AGC_PARAM_A 0x1171
#define IGP01E1000_PHY_AGC_PARAM_B 0x1271
#define IGP01E1000_PHY_AGC_PARAM_C 0x1471
@@ -2060,20 +2572,30 @@ struct e1000_hw {
#define IGP01E1000_MSE_CHANNEL_B 0x0F00
#define IGP01E1000_MSE_CHANNEL_A 0xF000
+#define IGP02E1000_PM_SPD 0x0001 /* Smart Power Down */
+#define IGP02E1000_PM_D3_LPLU 0x0004 /* Enable LPLU in non-D0a modes */
+#define IGP02E1000_PM_D0_LPLU 0x0002 /* Enable LPLU in D0a mode */
+
/* IGP01E1000 DSP reset macros */
#define DSP_RESET_ENABLE 0x0
#define DSP_RESET_DISABLE 0x2
#define E1000_MAX_DSP_RESETS 10
-/* IGP01E1000 AGC Registers */
+/* IGP01E1000 & IGP02E1000 AGC Registers */
#define IGP01E1000_AGC_LENGTH_SHIFT 7 /* Coarse - 13:11, Fine - 10:7 */
+#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Coarse - 15:13, Fine - 12:9 */
+
+/* IGP02E1000 AGC Register Length 9-bit mask */
+#define IGP02E1000_AGC_LENGTH_MASK 0x7F
/* 7 bits (3 Coarse + 4 Fine) --> 128 optional values */
#define IGP01E1000_AGC_LENGTH_TABLE_SIZE 128
+#define IGP02E1000_AGC_LENGTH_TABLE_SIZE 128
-/* The precision of the length is +/- 10 meters */
+/* The precision error of the cable length is +/- 10 meters */
#define IGP01E1000_AGC_RANGE 10
+#define IGP02E1000_AGC_RANGE 10
/* IGP01E1000 PCS Initialization register */
/* bits 3:6 in the PCS registers stores the channels polarity */
@@ -2113,6 +2635,8 @@ struct e1000_hw {
#define M88E1000_12_PHY_ID M88E1000_E_PHY_ID
#define M88E1000_14_PHY_ID M88E1000_E_PHY_ID
#define M88E1011_I_REV_4 0x04
+#define M88E1111_I_PHY_ID 0x01410CC0
+#define L1LXT971A_PHY_ID 0x001378E0
/* Miscellaneous PHY bit definitions. */
#define PHY_PREAMBLE 0xFFFFFFFF
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 82549a6fcfb..137226d98d4 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -1,7 +1,7 @@
/*******************************************************************************
- Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+ Copyright(c) 1999 - 2005 Intel Corporation. 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
@@ -29,33 +29,9 @@
#include "e1000.h"
/* Change Log
- * 5.3.12 6/7/04
- * - kcompat NETIF_MSG for older kernels (2.4.9) <sean.p.mcdermott@intel.com>
- * - if_mii support and associated kcompat for older kernels
- * - More errlogging support from Jon Mason <jonmason@us.ibm.com>
- * - Fix TSO issues on PPC64 machines -- Jon Mason <jonmason@us.ibm.com>
- *
- * 5.7.1 12/16/04
- * - Resurrect 82547EI/GI related fix in e1000_intr to avoid deadlocks. This
- * fix was removed as it caused system instability. The suspected cause of
- * this is the called to e1000_irq_disable in e1000_intr. Inlined the
- * required piece of e1000_irq_disable into e1000_intr - Anton Blanchard
- * 5.7.0 12/10/04
- * - include fix to the condition that determines when to quit NAPI - Robert Olsson
- * - use netif_poll_{disable/enable} to synchronize between NAPI and i/f up/down
- * 5.6.5 11/01/04
- * - Enabling NETIF_F_SG without checksum offload is illegal -
- John Mason <jdmason@us.ibm.com>
- * 5.6.3 10/26/04
- * - Remove redundant initialization - Jamal Hadi
- * - Reset buffer_info->dma in tx resource cleanup logic
- * 5.6.2 10/12/04
- * - Avoid filling tx_ring completely - shemminger@osdl.org
- * - Replace schedule_timeout() with msleep()/msleep_interruptible() -
- * nacc@us.ibm.com
- * - Sparse cleanup - shemminger@osdl.org
- * - Fix tx resource cleanup logic
- * - LLTX support - ak@suse.de and hadi@cyberus.ca
+ * 6.0.44+ 2/15/05
+ * o applied Anton's patch to resolve tx hang in hardware
+ * o Applied Andrew Mortons patch - e1000 stops working after resume
*/
char e1000_driver_name[] = "e1000";
@@ -65,7 +41,7 @@ char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver";
#else
#define DRIVERNAPI "-NAPI"
#endif
-#define DRV_VERSION "5.7.6-k2"DRIVERNAPI
+#define DRV_VERSION "6.0.54-k2"DRIVERNAPI
char e1000_driver_version[] = DRV_VERSION;
char e1000_copyright[] = "Copyright (c) 1999-2004 Intel Corporation.";
@@ -96,6 +72,7 @@ static struct pci_device_id e1000_pci_tbl[] = {
INTEL_E1000_ETHERNET_DEVICE(0x1017),
INTEL_E1000_ETHERNET_DEVICE(0x1018),
INTEL_E1000_ETHERNET_DEVICE(0x1019),
+ INTEL_E1000_ETHERNET_DEVICE(0x101A),
INTEL_E1000_ETHERNET_DEVICE(0x101D),
INTEL_E1000_ETHERNET_DEVICE(0x101E),
INTEL_E1000_ETHERNET_DEVICE(0x1026),
@@ -110,6 +87,9 @@ static struct pci_device_id e1000_pci_tbl[] = {
INTEL_E1000_ETHERNET_DEVICE(0x107B),
INTEL_E1000_ETHERNET_DEVICE(0x107C),
INTEL_E1000_ETHERNET_DEVICE(0x108A),
+ INTEL_E1000_ETHERNET_DEVICE(0x108B),
+ INTEL_E1000_ETHERNET_DEVICE(0x108C),
+ INTEL_E1000_ETHERNET_DEVICE(0x1099),
/* required last entry */
{0,}
};
@@ -155,10 +135,14 @@ static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter);
static int e1000_clean(struct net_device *netdev, int *budget);
static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter,
int *work_done, int work_to_do);
+static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
+ int *work_done, int work_to_do);
#else
static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter);
+static boolean_t e1000_clean_rx_irq_ps(struct e1000_adapter *adapter);
#endif
static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter);
+static void e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter);
static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr,
int cmd);
@@ -286,7 +270,29 @@ e1000_irq_enable(struct e1000_adapter *adapter)
E1000_WRITE_FLUSH(&adapter->hw);
}
}
-
+void
+e1000_update_mng_vlan(struct e1000_adapter *adapter)
+{
+ struct net_device *netdev = adapter->netdev;
+ uint16_t vid = adapter->hw.mng_cookie.vlan_id;
+ uint16_t old_vid = adapter->mng_vlan_id;
+ if(adapter->vlgrp) {
+ if(!adapter->vlgrp->vlan_devices[vid]) {
+ if(adapter->hw.mng_cookie.status &
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) {
+ e1000_vlan_rx_add_vid(netdev, vid);
+ adapter->mng_vlan_id = vid;
+ } else
+ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
+
+ if((old_vid != (uint16_t)E1000_MNG_VLAN_NONE) &&
+ (vid != old_vid) &&
+ !adapter->vlgrp->vlan_devices[old_vid])
+ e1000_vlan_rx_kill_vid(netdev, old_vid);
+ }
+ }
+}
+
int
e1000_up(struct e1000_adapter *adapter)
{
@@ -310,19 +316,33 @@ e1000_up(struct e1000_adapter *adapter)
e1000_configure_tx(adapter);
e1000_setup_rctl(adapter);
e1000_configure_rx(adapter);
- e1000_alloc_rx_buffers(adapter);
+ adapter->alloc_rx_buf(adapter);
+#ifdef CONFIG_PCI_MSI
+ if(adapter->hw.mac_type > e1000_82547_rev_2) {
+ adapter->have_msi = TRUE;
+ if((err = pci_enable_msi(adapter->pdev))) {
+ DPRINTK(PROBE, ERR,
+ "Unable to allocate MSI interrupt Error: %d\n", err);
+ adapter->have_msi = FALSE;
+ }
+ }
+#endif
if((err = request_irq(adapter->pdev->irq, &e1000_intr,
SA_SHIRQ | SA_SAMPLE_RANDOM,
- netdev->name, netdev)))
+ netdev->name, netdev))) {
+ DPRINTK(PROBE, ERR,
+ "Unable to allocate interrupt Error: %d\n", err);
return err;
+ }
mod_timer(&adapter->watchdog_timer, jiffies);
- e1000_irq_enable(adapter);
#ifdef CONFIG_E1000_NAPI
netif_poll_enable(netdev);
#endif
+ e1000_irq_enable(adapter);
+
return 0;
}
@@ -333,6 +353,11 @@ e1000_down(struct e1000_adapter *adapter)
e1000_irq_disable(adapter);
free_irq(adapter->pdev->irq, netdev);
+#ifdef CONFIG_PCI_MSI
+ if(adapter->hw.mac_type > e1000_82547_rev_2 &&
+ adapter->have_msi == TRUE)
+ pci_disable_msi(adapter->pdev);
+#endif
del_timer_sync(&adapter->tx_fifo_stall_timer);
del_timer_sync(&adapter->watchdog_timer);
del_timer_sync(&adapter->phy_info_timer);
@@ -350,62 +375,93 @@ e1000_down(struct e1000_adapter *adapter)
e1000_clean_rx_ring(adapter);
/* If WoL is not enabled
+ * and management mode is not IAMT
* Power down the PHY so no link is implied when interface is down */
- if(!adapter->wol && adapter->hw.media_type == e1000_media_type_copper) {
+ if(!adapter->wol && adapter->hw.mac_type >= e1000_82540 &&
+ adapter->hw.media_type == e1000_media_type_copper &&
+ !e1000_check_mng_mode(&adapter->hw) &&
+ !(E1000_READ_REG(&adapter->hw, MANC) & E1000_MANC_SMBUS_EN)) {
uint16_t mii_reg;
e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &mii_reg);
mii_reg |= MII_CR_POWER_DOWN;
e1000_write_phy_reg(&adapter->hw, PHY_CTRL, mii_reg);
+ mdelay(1);
}
}
void
e1000_reset(struct e1000_adapter *adapter)
{
- uint32_t pba;
+ struct net_device *netdev = adapter->netdev;
+ uint32_t pba, manc;
+ uint16_t fc_high_water_mark = E1000_FC_HIGH_DIFF;
+ uint16_t fc_low_water_mark = E1000_FC_LOW_DIFF;
/* Repartition Pba for greater than 9k mtu
* To take effect CTRL.RST is required.
*/
- if(adapter->hw.mac_type < e1000_82547) {
- if(adapter->rx_buffer_len > E1000_RXBUFFER_8192)
- pba = E1000_PBA_40K;
- else
- pba = E1000_PBA_48K;
- } else {
- if(adapter->rx_buffer_len > E1000_RXBUFFER_8192)
- pba = E1000_PBA_22K;
- else
- pba = E1000_PBA_30K;
+ switch (adapter->hw.mac_type) {
+ case e1000_82547:
+ case e1000_82547_rev_2:
+ pba = E1000_PBA_30K;
+ break;
+ case e1000_82573:
+ pba = E1000_PBA_12K;
+ break;
+ default:
+ pba = E1000_PBA_48K;
+ break;
+ }
+
+ if((adapter->hw.mac_type != e1000_82573) &&
+ (adapter->rx_buffer_len > E1000_RXBUFFER_8192)) {
+ pba -= 8; /* allocate more FIFO for Tx */
+ /* send an XOFF when there is enough space in the
+ * Rx FIFO to hold one extra full size Rx packet
+ */
+ fc_high_water_mark = netdev->mtu + ENET_HEADER_SIZE +
+ ETHERNET_FCS_SIZE + 1;
+ fc_low_water_mark = fc_high_water_mark + 8;
+ }
+
+
+ if(adapter->hw.mac_type == e1000_82547) {
adapter->tx_fifo_head = 0;
adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT;
adapter->tx_fifo_size =
(E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT;
atomic_set(&adapter->tx_fifo_stall, 0);
}
+
E1000_WRITE_REG(&adapter->hw, PBA, pba);
/* flow control settings */
adapter->hw.fc_high_water = (pba << E1000_PBA_BYTES_SHIFT) -
- E1000_FC_HIGH_DIFF;
+ fc_high_water_mark;
adapter->hw.fc_low_water = (pba << E1000_PBA_BYTES_SHIFT) -
- E1000_FC_LOW_DIFF;
+ fc_low_water_mark;
adapter->hw.fc_pause_time = E1000_FC_PAUSE_TIME;
adapter->hw.fc_send_xon = 1;
adapter->hw.fc = adapter->hw.original_fc;
+ /* Allow time for pending master requests to run */
e1000_reset_hw(&adapter->hw);
if(adapter->hw.mac_type >= e1000_82544)
E1000_WRITE_REG(&adapter->hw, WUC, 0);
if(e1000_init_hw(&adapter->hw))
DPRINTK(PROBE, ERR, "Hardware Error\n");
-
+ e1000_update_mng_vlan(adapter);
/* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
E1000_WRITE_REG(&adapter->hw, VET, ETHERNET_IEEE_VLAN_TYPE);
e1000_reset_adaptive(&adapter->hw);
e1000_phy_get_info(&adapter->hw, &adapter->phy_info);
+ if (adapter->en_mng_pt) {
+ manc = E1000_READ_REG(&adapter->hw, MANC);
+ manc |= (E1000_MANC_ARP_EN | E1000_MANC_EN_MNG2HOST);
+ E1000_WRITE_REG(&adapter->hw, MANC, manc);
+ }
}
/**
@@ -426,15 +482,13 @@ e1000_probe(struct pci_dev *pdev,
{
struct net_device *netdev;
struct e1000_adapter *adapter;
+ unsigned long mmio_start, mmio_len;
+ uint32_t swsm;
+
static int cards_found = 0;
- unsigned long mmio_start;
- int mmio_len;
- int pci_using_dac;
- int i;
- int err;
+ int i, err, pci_using_dac;
uint16_t eeprom_data;
uint16_t eeprom_apme_mask = E1000_EEPROM_APME;
-
if((err = pci_enable_device(pdev)))
return err;
@@ -521,6 +575,9 @@ e1000_probe(struct pci_dev *pdev,
if((err = e1000_sw_init(adapter)))
goto err_sw_init;
+ if((err = e1000_check_phy_reset_block(&adapter->hw)))
+ DPRINTK(PROBE, INFO, "PHY reset is blocked due to SOL/IDER session.\n");
+
if(adapter->hw.mac_type >= e1000_82543) {
netdev->features = NETIF_F_SG |
NETIF_F_HW_CSUM |
@@ -533,6 +590,11 @@ e1000_probe(struct pci_dev *pdev,
if((adapter->hw.mac_type >= e1000_82544) &&
(adapter->hw.mac_type != e1000_82547))
netdev->features |= NETIF_F_TSO;
+
+#ifdef NETIF_F_TSO_IPV6
+ if(adapter->hw.mac_type > e1000_82547_rev_2)
+ netdev->features |= NETIF_F_TSO_IPV6;
+#endif
#endif
if(pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
@@ -540,6 +602,8 @@ e1000_probe(struct pci_dev *pdev,
/* hard_start_xmit is safe against parallel locking */
netdev->features |= NETIF_F_LLTX;
+ adapter->en_mng_pt = e1000_enable_mng_pass_thru(&adapter->hw);
+
/* before reading the EEPROM, reset the controller to
* put the device in a known good starting state */
@@ -555,7 +619,7 @@ e1000_probe(struct pci_dev *pdev,
/* copy the MAC address out of the EEPROM */
- if (e1000_read_mac_addr(&adapter->hw))
+ if(e1000_read_mac_addr(&adapter->hw))
DPRINTK(PROBE, ERR, "EEPROM Read Error\n");
memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len);
@@ -629,6 +693,17 @@ e1000_probe(struct pci_dev *pdev,
/* reset the hardware with the new settings */
e1000_reset(adapter);
+ /* Let firmware know the driver has taken over */
+ switch(adapter->hw.mac_type) {
+ case e1000_82573:
+ swsm = E1000_READ_REG(&adapter->hw, SWSM);
+ E1000_WRITE_REG(&adapter->hw, SWSM,
+ swsm | E1000_SWSM_DRV_LOAD);
+ break;
+ default:
+ break;
+ }
+
strcpy(netdev->name, "eth%d");
if((err = register_netdev(netdev)))
goto err_register;
@@ -664,7 +739,7 @@ e1000_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev->priv;
- uint32_t manc;
+ uint32_t manc, swsm;
flush_scheduled_work();
@@ -677,9 +752,21 @@ e1000_remove(struct pci_dev *pdev)
}
}
+ switch(adapter->hw.mac_type) {
+ case e1000_82573:
+ swsm = E1000_READ_REG(&adapter->hw, SWSM);
+ E1000_WRITE_REG(&adapter->hw, SWSM,
+ swsm & ~E1000_SWSM_DRV_LOAD);
+ break;
+
+ default:
+ break;
+ }
+
unregister_netdev(netdev);
- e1000_phy_hw_reset(&adapter->hw);
+ if(!e1000_check_phy_reset_block(&adapter->hw))
+ e1000_phy_hw_reset(&adapter->hw);
iounmap(adapter->hw.hw_addr);
pci_release_regions(pdev);
@@ -717,6 +804,7 @@ e1000_sw_init(struct e1000_adapter *adapter)
pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
adapter->rx_buffer_len = E1000_RXBUFFER_2048;
+ adapter->rx_ps_bsize0 = E1000_RXBUFFER_256;
hw->max_frame_size = netdev->mtu +
ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE;
@@ -730,7 +818,10 @@ e1000_sw_init(struct e1000_adapter *adapter)
/* initialize eeprom parameters */
- e1000_init_eeprom_params(hw);
+ if(e1000_init_eeprom_params(hw)) {
+ E1000_ERR("EEPROM initialization failed\n");
+ return -EIO;
+ }
switch(hw->mac_type) {
default:
@@ -795,6 +886,11 @@ e1000_open(struct net_device *netdev)
if((err = e1000_up(adapter)))
goto err_up;
+ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
+ if((adapter->hw.mng_cookie.status &
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
+ e1000_update_mng_vlan(adapter);
+ }
return E1000_SUCCESS;
@@ -830,14 +926,18 @@ e1000_close(struct net_device *netdev)
e1000_free_tx_resources(adapter);
e1000_free_rx_resources(adapter);
+ if((adapter->hw.mng_cookie.status &
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) {
+ e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
+ }
return 0;
}
/**
* e1000_check_64k_bound - check that memory doesn't cross 64kB boundary
* @adapter: address of board private structure
- * @begin: address of beginning of memory
- * @end: address of end of memory
+ * @start: address of beginning of memory
+ * @len: length of memory
**/
static inline boolean_t
e1000_check_64k_bound(struct e1000_adapter *adapter,
@@ -846,12 +946,10 @@ e1000_check_64k_bound(struct e1000_adapter *adapter,
unsigned long begin = (unsigned long) start;
unsigned long end = begin + len;
- /* first rev 82545 and 82546 need to not allow any memory
- * write location to cross a 64k boundary due to errata 23 */
+ /* First rev 82545 and 82546 need to not allow any memory
+ * write location to cross 64k boundary due to errata 23 */
if (adapter->hw.mac_type == e1000_82545 ||
- adapter->hw.mac_type == e1000_82546 ) {
-
- /* check buffer doesn't cross 64kB */
+ adapter->hw.mac_type == e1000_82546) {
return ((begin ^ (end - 1)) >> 16) != 0 ? FALSE : TRUE;
}
@@ -875,8 +973,8 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter)
size = sizeof(struct e1000_buffer) * txdr->count;
txdr->buffer_info = vmalloc(size);
if(!txdr->buffer_info) {
- DPRINTK(PROBE, ERR,
- "Unable to Allocate Memory for the Transmit descriptor ring\n");
+ DPRINTK(PROBE, ERR,
+ "Unable to allocate memory for the transmit descriptor ring\n");
return -ENOMEM;
}
memset(txdr->buffer_info, 0, size);
@@ -889,38 +987,38 @@ e1000_setup_tx_resources(struct e1000_adapter *adapter)
txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
if(!txdr->desc) {
setup_tx_desc_die:
- DPRINTK(PROBE, ERR,
- "Unable to Allocate Memory for the Transmit descriptor ring\n");
vfree(txdr->buffer_info);
+ DPRINTK(PROBE, ERR,
+ "Unable to allocate memory for the transmit descriptor ring\n");
return -ENOMEM;
}
- /* fix for errata 23, cant cross 64kB boundary */
+ /* Fix for errata 23, can't cross 64kB boundary */
if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) {
void *olddesc = txdr->desc;
dma_addr_t olddma = txdr->dma;
- DPRINTK(TX_ERR,ERR,"txdr align check failed: %u bytes at %p\n",
- txdr->size, txdr->desc);
- /* try again, without freeing the previous */
+ DPRINTK(TX_ERR, ERR, "txdr align check failed: %u bytes "
+ "at %p\n", txdr->size, txdr->desc);
+ /* Try again, without freeing the previous */
txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
- /* failed allocation, critial failure */
if(!txdr->desc) {
+ /* Failed allocation, critical failure */
pci_free_consistent(pdev, txdr->size, olddesc, olddma);
goto setup_tx_desc_die;
}
if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) {
/* give up */
- pci_free_consistent(pdev, txdr->size,
- txdr->desc, txdr->dma);
+ pci_free_consistent(pdev, txdr->size, txdr->desc,
+ txdr->dma);
pci_free_consistent(pdev, txdr->size, olddesc, olddma);
DPRINTK(PROBE, ERR,
- "Unable to Allocate aligned Memory for the Transmit"
- " descriptor ring\n");
+ "Unable to allocate aligned memory "
+ "for the transmit descriptor ring\n");
vfree(txdr->buffer_info);
return -ENOMEM;
} else {
- /* free old, move on with the new one since its okay */
+ /* Free old allocation, new allocation was successful */
pci_free_consistent(pdev, txdr->size, olddesc, olddma);
}
}
@@ -1022,59 +1120,88 @@ e1000_setup_rx_resources(struct e1000_adapter *adapter)
{
struct e1000_desc_ring *rxdr = &adapter->rx_ring;
struct pci_dev *pdev = adapter->pdev;
- int size;
+ int size, desc_len;
size = sizeof(struct e1000_buffer) * rxdr->count;
rxdr->buffer_info = vmalloc(size);
if(!rxdr->buffer_info) {
- DPRINTK(PROBE, ERR,
- "Unable to Allocate Memory for the Recieve descriptor ring\n");
+ DPRINTK(PROBE, ERR,
+ "Unable to allocate memory for the receive descriptor ring\n");
return -ENOMEM;
}
memset(rxdr->buffer_info, 0, size);
+ size = sizeof(struct e1000_ps_page) * rxdr->count;
+ rxdr->ps_page = kmalloc(size, GFP_KERNEL);
+ if(!rxdr->ps_page) {
+ vfree(rxdr->buffer_info);
+ DPRINTK(PROBE, ERR,
+ "Unable to allocate memory for the receive descriptor ring\n");
+ return -ENOMEM;
+ }
+ memset(rxdr->ps_page, 0, size);
+
+ size = sizeof(struct e1000_ps_page_dma) * rxdr->count;
+ rxdr->ps_page_dma = kmalloc(size, GFP_KERNEL);
+ if(!rxdr->ps_page_dma) {
+ vfree(rxdr->buffer_info);
+ kfree(rxdr->ps_page);
+ DPRINTK(PROBE, ERR,
+ "Unable to allocate memory for the receive descriptor ring\n");
+ return -ENOMEM;
+ }
+ memset(rxdr->ps_page_dma, 0, size);
+
+ if(adapter->hw.mac_type <= e1000_82547_rev_2)
+ desc_len = sizeof(struct e1000_rx_desc);
+ else
+ desc_len = sizeof(union e1000_rx_desc_packet_split);
+
/* Round up to nearest 4K */
- rxdr->size = rxdr->count * sizeof(struct e1000_rx_desc);
+ rxdr->size = rxdr->count * desc_len;
E1000_ROUNDUP(rxdr->size, 4096);
rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
if(!rxdr->desc) {
setup_rx_desc_die:
- DPRINTK(PROBE, ERR,
- "Unble to Allocate Memory for the Recieve descriptor ring\n");
vfree(rxdr->buffer_info);
+ kfree(rxdr->ps_page);
+ kfree(rxdr->ps_page_dma);
+ DPRINTK(PROBE, ERR,
+ "Unable to allocate memory for the receive descriptor ring\n");
return -ENOMEM;
}
- /* fix for errata 23, cant cross 64kB boundary */
+ /* Fix for errata 23, can't cross 64kB boundary */
if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) {
void *olddesc = rxdr->desc;
dma_addr_t olddma = rxdr->dma;
- DPRINTK(RX_ERR,ERR,
- "rxdr align check failed: %u bytes at %p\n",
- rxdr->size, rxdr->desc);
- /* try again, without freeing the previous */
+ DPRINTK(RX_ERR, ERR, "rxdr align check failed: %u bytes "
+ "at %p\n", rxdr->size, rxdr->desc);
+ /* Try again, without freeing the previous */
rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
- /* failed allocation, critial failure */
if(!rxdr->desc) {
+ /* Failed allocation, critical failure */
pci_free_consistent(pdev, rxdr->size, olddesc, olddma);
goto setup_rx_desc_die;
}
if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) {
/* give up */
- pci_free_consistent(pdev, rxdr->size,
- rxdr->desc, rxdr->dma);
+ pci_free_consistent(pdev, rxdr->size, rxdr->desc,
+ rxdr->dma);
pci_free_consistent(pdev, rxdr->size, olddesc, olddma);
- DPRINTK(PROBE, ERR,
- "Unable to Allocate aligned Memory for the"
- " Receive descriptor ring\n");
+ DPRINTK(PROBE, ERR,
+ "Unable to allocate aligned memory "
+ "for the receive descriptor ring\n");
vfree(rxdr->buffer_info);
+ kfree(rxdr->ps_page);
+ kfree(rxdr->ps_page_dma);
return -ENOMEM;
} else {
- /* free old, move on with the new one since its okay */
+ /* Free old allocation, new allocation was successful */
pci_free_consistent(pdev, rxdr->size, olddesc, olddma);
}
}
@@ -1087,14 +1214,15 @@ setup_rx_desc_die:
}
/**
- * e1000_setup_rctl - configure the receive control register
+ * e1000_setup_rctl - configure the receive control registers
* @adapter: Board private structure
**/
static void
e1000_setup_rctl(struct e1000_adapter *adapter)
{
- uint32_t rctl;
+ uint32_t rctl, rfctl;
+ uint32_t psrctl = 0;
rctl = E1000_READ_REG(&adapter->hw, RCTL);
@@ -1109,24 +1237,69 @@ e1000_setup_rctl(struct e1000_adapter *adapter)
else
rctl &= ~E1000_RCTL_SBP;
+ if (adapter->netdev->mtu <= ETH_DATA_LEN)
+ rctl &= ~E1000_RCTL_LPE;
+ else
+ rctl |= E1000_RCTL_LPE;
+
/* Setup buffer sizes */
- rctl &= ~(E1000_RCTL_SZ_4096);
- rctl |= (E1000_RCTL_BSEX | E1000_RCTL_LPE);
- switch (adapter->rx_buffer_len) {
- case E1000_RXBUFFER_2048:
- default:
- rctl |= E1000_RCTL_SZ_2048;
- rctl &= ~(E1000_RCTL_BSEX | E1000_RCTL_LPE);
- break;
- case E1000_RXBUFFER_4096:
- rctl |= E1000_RCTL_SZ_4096;
- break;
- case E1000_RXBUFFER_8192:
- rctl |= E1000_RCTL_SZ_8192;
- break;
- case E1000_RXBUFFER_16384:
- rctl |= E1000_RCTL_SZ_16384;
- break;
+ if(adapter->hw.mac_type == e1000_82573) {
+ /* We can now specify buffers in 1K increments.
+ * BSIZE and BSEX are ignored in this case. */
+ rctl |= adapter->rx_buffer_len << 0x11;
+ } else {
+ rctl &= ~E1000_RCTL_SZ_4096;
+ rctl |= E1000_RCTL_BSEX;
+ switch (adapter->rx_buffer_len) {
+ case E1000_RXBUFFER_2048:
+ default:
+ rctl |= E1000_RCTL_SZ_2048;
+ rctl &= ~E1000_RCTL_BSEX;
+ break;
+ case E1000_RXBUFFER_4096:
+ rctl |= E1000_RCTL_SZ_4096;
+ break;
+ case E1000_RXBUFFER_8192:
+ rctl |= E1000_RCTL_SZ_8192;
+ break;
+ case E1000_RXBUFFER_16384:
+ rctl |= E1000_RCTL_SZ_16384;
+ break;
+ }
+ }
+
+#ifdef CONFIG_E1000_PACKET_SPLIT
+ /* 82571 and greater support packet-split where the protocol
+ * header is placed in skb->data and the packet data is
+ * placed in pages hanging off of skb_shinfo(skb)->nr_frags.
+ * In the case of a non-split, skb->data is linearly filled,
+ * followed by the page buffers. Therefore, skb->data is
+ * sized to hold the largest protocol header.
+ */
+ adapter->rx_ps = (adapter->hw.mac_type > e1000_82547_rev_2)
+ && (adapter->netdev->mtu
+ < ((3 * PAGE_SIZE) + adapter->rx_ps_bsize0));
+#endif
+ if(adapter->rx_ps) {
+ /* Configure extra packet-split registers */
+ rfctl = E1000_READ_REG(&adapter->hw, RFCTL);
+ rfctl |= E1000_RFCTL_EXTEN;
+ /* disable IPv6 packet split support */
+ rfctl |= E1000_RFCTL_IPV6_DIS;
+ E1000_WRITE_REG(&adapter->hw, RFCTL, rfctl);
+
+ rctl |= E1000_RCTL_DTYP_PS | E1000_RCTL_SECRC;
+
+ psrctl |= adapter->rx_ps_bsize0 >>
+ E1000_PSRCTL_BSIZE0_SHIFT;
+ psrctl |= PAGE_SIZE >>
+ E1000_PSRCTL_BSIZE1_SHIFT;
+ psrctl |= PAGE_SIZE <<
+ E1000_PSRCTL_BSIZE2_SHIFT;
+ psrctl |= PAGE_SIZE <<
+ E1000_PSRCTL_BSIZE3_SHIFT;
+
+ E1000_WRITE_REG(&adapter->hw, PSRCTL, psrctl);
}
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
@@ -1143,9 +1316,18 @@ static void
e1000_configure_rx(struct e1000_adapter *adapter)
{
uint64_t rdba = adapter->rx_ring.dma;
- uint32_t rdlen = adapter->rx_ring.count * sizeof(struct e1000_rx_desc);
- uint32_t rctl;
- uint32_t rxcsum;
+ uint32_t rdlen, rctl, rxcsum;
+
+ if(adapter->rx_ps) {
+ rdlen = adapter->rx_ring.count *
+ sizeof(union e1000_rx_desc_packet_split);
+ adapter->clean_rx = e1000_clean_rx_irq_ps;
+ adapter->alloc_rx_buf = e1000_alloc_rx_buffers_ps;
+ } else {
+ rdlen = adapter->rx_ring.count * sizeof(struct e1000_rx_desc);
+ adapter->clean_rx = e1000_clean_rx_irq;
+ adapter->alloc_rx_buf = e1000_alloc_rx_buffers;
+ }
/* disable receives while setting up the descriptors */
rctl = E1000_READ_REG(&adapter->hw, RCTL);
@@ -1172,13 +1354,27 @@ e1000_configure_rx(struct e1000_adapter *adapter)
E1000_WRITE_REG(&adapter->hw, RDT, 0);
/* Enable 82543 Receive Checksum Offload for TCP and UDP */
- if((adapter->hw.mac_type >= e1000_82543) &&
- (adapter->rx_csum == TRUE)) {
+ if(adapter->hw.mac_type >= e1000_82543) {
rxcsum = E1000_READ_REG(&adapter->hw, RXCSUM);
- rxcsum |= E1000_RXCSUM_TUOFL;
+ if(adapter->rx_csum == TRUE) {
+ rxcsum |= E1000_RXCSUM_TUOFL;
+
+ /* Enable 82573 IPv4 payload checksum for UDP fragments
+ * Must be used in conjunction with packet-split. */
+ if((adapter->hw.mac_type > e1000_82547_rev_2) &&
+ (adapter->rx_ps)) {
+ rxcsum |= E1000_RXCSUM_IPPCSE;
+ }
+ } else {
+ rxcsum &= ~E1000_RXCSUM_TUOFL;
+ /* don't need to clear IPPCSE as it defaults to 0 */
+ }
E1000_WRITE_REG(&adapter->hw, RXCSUM, rxcsum);
}
+ if (adapter->hw.mac_type == e1000_82573)
+ E1000_WRITE_REG(&adapter->hw, ERT, 0x0100);
+
/* Enable Receives */
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
}
@@ -1210,13 +1406,11 @@ static inline void
e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter,
struct e1000_buffer *buffer_info)
{
- struct pci_dev *pdev = adapter->pdev;
-
if(buffer_info->dma) {
- pci_unmap_page(pdev,
- buffer_info->dma,
- buffer_info->length,
- PCI_DMA_TODEVICE);
+ pci_unmap_page(adapter->pdev,
+ buffer_info->dma,
+ buffer_info->length,
+ PCI_DMA_TODEVICE);
buffer_info->dma = 0;
}
if(buffer_info->skb) {
@@ -1241,7 +1435,7 @@ e1000_clean_tx_ring(struct e1000_adapter *adapter)
/* Free all the Tx ring sk_buffs */
if (likely(adapter->previous_buffer_info.skb != NULL)) {
- e1000_unmap_and_free_tx_resource(adapter,
+ e1000_unmap_and_free_tx_resource(adapter,
&adapter->previous_buffer_info);
}
@@ -1281,6 +1475,10 @@ e1000_free_rx_resources(struct e1000_adapter *adapter)
vfree(rx_ring->buffer_info);
rx_ring->buffer_info = NULL;
+ kfree(rx_ring->ps_page);
+ rx_ring->ps_page = NULL;
+ kfree(rx_ring->ps_page_dma);
+ rx_ring->ps_page_dma = NULL;
pci_free_consistent(pdev, rx_ring->size, rx_ring->desc, rx_ring->dma);
@@ -1297,16 +1495,19 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter)
{
struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
struct e1000_buffer *buffer_info;
+ struct e1000_ps_page *ps_page;
+ struct e1000_ps_page_dma *ps_page_dma;
struct pci_dev *pdev = adapter->pdev;
unsigned long size;
- unsigned int i;
+ unsigned int i, j;
/* Free all the Rx ring sk_buffs */
for(i = 0; i < rx_ring->count; i++) {
buffer_info = &rx_ring->buffer_info[i];
if(buffer_info->skb) {
-
+ ps_page = &rx_ring->ps_page[i];
+ ps_page_dma = &rx_ring->ps_page_dma[i];
pci_unmap_single(pdev,
buffer_info->dma,
buffer_info->length,
@@ -1314,11 +1515,25 @@ e1000_clean_rx_ring(struct e1000_adapter *adapter)
dev_kfree_skb(buffer_info->skb);
buffer_info->skb = NULL;
+
+ for(j = 0; j < PS_PAGE_BUFFERS; j++) {
+ if(!ps_page->ps_page[j]) break;
+ pci_unmap_single(pdev,
+ ps_page_dma->ps_page_dma[j],
+ PAGE_SIZE, PCI_DMA_FROMDEVICE);
+ ps_page_dma->ps_page_dma[j] = 0;
+ put_page(ps_page->ps_page[j]);
+ ps_page->ps_page[j] = NULL;
+ }
}
}
size = sizeof(struct e1000_buffer) * rx_ring->count;
memset(rx_ring->buffer_info, 0, size);
+ size = sizeof(struct e1000_ps_page) * rx_ring->count;
+ memset(rx_ring->ps_page, 0, size);
+ size = sizeof(struct e1000_ps_page_dma) * rx_ring->count;
+ memset(rx_ring->ps_page_dma, 0, size);
/* Zero out the descriptor ring */
@@ -1422,15 +1637,15 @@ e1000_set_multi(struct net_device *netdev)
struct e1000_adapter *adapter = netdev->priv;
struct e1000_hw *hw = &adapter->hw;
struct dev_mc_list *mc_ptr;
+ unsigned long flags;
uint32_t rctl;
uint32_t hash_value;
int i;
- unsigned long flags;
-
- /* Check for Promiscuous and All Multicast modes */
spin_lock_irqsave(&adapter->tx_lock, flags);
+ /* Check for Promiscuous and All Multicast modes */
+
rctl = E1000_READ_REG(hw, RCTL);
if(netdev->flags & IFF_PROMISC) {
@@ -1556,6 +1771,11 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
uint32_t link;
e1000_check_for_link(&adapter->hw);
+ if (adapter->hw.mac_type == e1000_82573) {
+ e1000_enable_tx_pkt_filtering(&adapter->hw);
+ if(adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id)
+ e1000_update_mng_vlan(adapter);
+ }
if((adapter->hw.media_type == e1000_media_type_internal_serdes) &&
!(E1000_READ_REG(&adapter->hw, TXCW) & E1000_TXCW_ANE))
@@ -1632,7 +1852,7 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
/* Cause software interrupt to ensure rx ring is cleaned */
E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0);
- /* Force detection of hung controller every watchdog period*/
+ /* Force detection of hung controller every watchdog period */
adapter->detect_tx_hung = TRUE;
/* Reset the timer */
@@ -1642,6 +1862,7 @@ e1000_watchdog_task(struct e1000_adapter *adapter)
#define E1000_TX_FLAGS_CSUM 0x00000001
#define E1000_TX_FLAGS_VLAN 0x00000002
#define E1000_TX_FLAGS_TSO 0x00000004
+#define E1000_TX_FLAGS_IPV4 0x00000008
#define E1000_TX_FLAGS_VLAN_MASK 0xffff0000
#define E1000_TX_FLAGS_VLAN_SHIFT 16
@@ -1652,7 +1873,7 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb)
struct e1000_context_desc *context_desc;
unsigned int i;
uint32_t cmd_length = 0;
- uint16_t ipcse, tucse, mss;
+ uint16_t ipcse = 0, tucse, mss;
uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
int err;
@@ -1665,23 +1886,37 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb)
hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
mss = skb_shinfo(skb)->tso_size;
- skb->nh.iph->tot_len = 0;
- skb->nh.iph->check = 0;
- skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr,
- skb->nh.iph->daddr,
- 0,
- IPPROTO_TCP,
- 0);
+ if(skb->protocol == ntohs(ETH_P_IP)) {
+ skb->nh.iph->tot_len = 0;
+ skb->nh.iph->check = 0;
+ skb->h.th->check =
+ ~csum_tcpudp_magic(skb->nh.iph->saddr,
+ skb->nh.iph->daddr,
+ 0,
+ IPPROTO_TCP,
+ 0);
+ cmd_length = E1000_TXD_CMD_IP;
+ ipcse = skb->h.raw - skb->data - 1;
+#ifdef NETIF_F_TSO_IPV6
+ } else if(skb->protocol == ntohs(ETH_P_IPV6)) {
+ skb->nh.ipv6h->payload_len = 0;
+ skb->h.th->check =
+ ~csum_ipv6_magic(&skb->nh.ipv6h->saddr,
+ &skb->nh.ipv6h->daddr,
+ 0,
+ IPPROTO_TCP,
+ 0);
+ ipcse = 0;
+#endif
+ }
ipcss = skb->nh.raw - skb->data;
ipcso = (void *)&(skb->nh.iph->check) - (void *)skb->data;
- ipcse = skb->h.raw - skb->data - 1;
tucss = skb->h.raw - skb->data;
tucso = (void *)&(skb->h.th->check) - (void *)skb->data;
tucse = 0;
cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE |
- E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP |
- (skb->len - (hdr_len)));
+ E1000_TXD_CMD_TCP | (skb->len - (hdr_len)));
i = adapter->tx_ring.next_to_use;
context_desc = E1000_CONTEXT_DESC(adapter->tx_ring, i);
@@ -1760,6 +1995,15 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb,
if(unlikely(mss && !nr_frags && size == len && size > 8))
size -= 4;
#endif
+ /* work-around for errata 10 and it applies
+ * to all controllers in PCI-X mode
+ * The fix is to make sure that the first descriptor of a
+ * packet is smaller than 2048 - 16 - 16 (or 2016) bytes
+ */
+ if(unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) &&
+ (size > 2015) && count == 0))
+ size = 2015;
+
/* Workaround for potential 82544 hang in PCI-X. Avoid
* terminating buffers within evenly-aligned dwords. */
if(unlikely(adapter->pcix_82544 &&
@@ -1840,7 +2084,10 @@ e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags)
if(likely(tx_flags & E1000_TX_FLAGS_TSO)) {
txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D |
E1000_TXD_CMD_TSE;
- txd_upper |= (E1000_TXD_POPTS_IXSM | E1000_TXD_POPTS_TXSM) << 8;
+ txd_upper |= E1000_TXD_POPTS_TXSM << 8;
+
+ if(likely(tx_flags & E1000_TX_FLAGS_IPV4))
+ txd_upper |= E1000_TXD_POPTS_IXSM << 8;
}
if(likely(tx_flags & E1000_TX_FLAGS_CSUM)) {
@@ -1915,6 +2162,53 @@ no_fifo_stall_required:
return 0;
}
+#define MINIMUM_DHCP_PACKET_SIZE 282
+static inline int
+e1000_transfer_dhcp_info(struct e1000_adapter *adapter, struct sk_buff *skb)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ uint16_t length, offset;
+ if(vlan_tx_tag_present(skb)) {
+ if(!((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) &&
+ ( adapter->hw.mng_cookie.status &
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) )
+ return 0;
+ }
+ if(htons(ETH_P_IP) == skb->protocol) {
+ const struct iphdr *ip = skb->nh.iph;
+ if(IPPROTO_UDP == ip->protocol) {
+ struct udphdr *udp = (struct udphdr *)(skb->h.uh);
+ if(ntohs(udp->dest) == 67) {
+ offset = (uint8_t *)udp + 8 - skb->data;
+ length = skb->len - offset;
+
+ return e1000_mng_write_dhcp_info(hw,
+ (uint8_t *)udp + 8, length);
+ }
+ }
+ } else if((skb->len > MINIMUM_DHCP_PACKET_SIZE) && (!skb->protocol)) {
+ struct ethhdr *eth = (struct ethhdr *) skb->data;
+ if((htons(ETH_P_IP) == eth->h_proto)) {
+ const struct iphdr *ip =
+ (struct iphdr *)((uint8_t *)skb->data+14);
+ if(IPPROTO_UDP == ip->protocol) {
+ struct udphdr *udp =
+ (struct udphdr *)((uint8_t *)ip +
+ (ip->ihl << 2));
+ if(ntohs(udp->dest) == 67) {
+ offset = (uint8_t *)udp + 8 - skb->data;
+ length = skb->len - offset;
+
+ return e1000_mng_write_dhcp_info(hw,
+ (uint8_t *)udp + 8,
+ length);
+ }
+ }
+ }
+ }
+ return 0;
+}
+
#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 )
static int
e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
@@ -1939,7 +2233,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
#ifdef NETIF_F_TSO
mss = skb_shinfo(skb)->tso_size;
- /* The controller does a simple calculation to
+ /* The controller does a simple calculation to
* make sure there is enough room in the FIFO before
* initiating the DMA for each buffer. The calc is:
* 4 = ceil(buffer len/mss). To make sure we don't
@@ -1952,7 +2246,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
if((mss) || (skb->ip_summed == CHECKSUM_HW))
count++;
- count++; /* for sentinel desc */
+ count++;
#else
if(skb->ip_summed == CHECKSUM_HW)
count++;
@@ -1962,6 +2256,13 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
if(adapter->pcix_82544)
count++;
+ /* work-around for errata 10 and it applies to all controllers
+ * in PCI-X mode, so add one more descriptor to the count
+ */
+ if(unlikely((adapter->hw.bus_type == e1000_bus_type_pcix) &&
+ (len > 2015)))
+ count++;
+
nr_frags = skb_shinfo(skb)->nr_frags;
for(f = 0; f < nr_frags; f++)
count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size,
@@ -1975,6 +2276,9 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
local_irq_restore(flags);
return NETDEV_TX_LOCKED;
}
+ if(adapter->hw.tx_pkt_filtering && (adapter->hw.mac_type == e1000_82573) )
+ e1000_transfer_dhcp_info(adapter, skb);
+
/* need: count + 2 desc gap to keep tail from touching
* head, otherwise try next time */
@@ -2003,6 +2307,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
tso = e1000_tso(adapter, skb);
if (tso < 0) {
dev_kfree_skb_any(skb);
+ spin_unlock_irqrestore(&adapter->tx_lock, flags);
return NETDEV_TX_OK;
}
@@ -2011,6 +2316,12 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
else if(likely(e1000_tx_csum(adapter, skb)))
tx_flags |= E1000_TX_FLAGS_CSUM;
+ /* Old method was to assume IPv4 packet by default if TSO was enabled.
+ * 82573 hardware supports TSO capabilities for IPv6 as well...
+ * no longer assume, we must. */
+ if(likely(skb->protocol == ntohs(ETH_P_IP)))
+ tx_flags |= E1000_TX_FLAGS_IPV4;
+
e1000_tx_queue(adapter,
e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss),
tx_flags);
@@ -2077,7 +2388,6 @@ static int
e1000_change_mtu(struct net_device *netdev, int new_mtu)
{
struct e1000_adapter *adapter = netdev->priv;
- int old_mtu = adapter->rx_buffer_len;
int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE;
if((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) ||
@@ -2086,29 +2396,45 @@ e1000_change_mtu(struct net_device *netdev, int new_mtu)
return -EINVAL;
}
- if(max_frame <= MAXIMUM_ETHERNET_FRAME_SIZE) {
- adapter->rx_buffer_len = E1000_RXBUFFER_2048;
-
- } else if(adapter->hw.mac_type < e1000_82543) {
- DPRINTK(PROBE, ERR, "Jumbo Frames not supported on 82542\n");
+#define MAX_STD_JUMBO_FRAME_SIZE 9216
+ /* might want this to be bigger enum check... */
+ if (adapter->hw.mac_type == e1000_82573 &&
+ max_frame > MAXIMUM_ETHERNET_FRAME_SIZE) {
+ DPRINTK(PROBE, ERR, "Jumbo Frames not supported "
+ "on 82573\n");
return -EINVAL;
+ }
- } else if(max_frame <= E1000_RXBUFFER_4096) {
- adapter->rx_buffer_len = E1000_RXBUFFER_4096;
-
- } else if(max_frame <= E1000_RXBUFFER_8192) {
- adapter->rx_buffer_len = E1000_RXBUFFER_8192;
-
+ if(adapter->hw.mac_type > e1000_82547_rev_2) {
+ adapter->rx_buffer_len = max_frame;
+ E1000_ROUNDUP(adapter->rx_buffer_len, 1024);
} else {
- adapter->rx_buffer_len = E1000_RXBUFFER_16384;
+ if(unlikely((adapter->hw.mac_type < e1000_82543) &&
+ (max_frame > MAXIMUM_ETHERNET_FRAME_SIZE))) {
+ DPRINTK(PROBE, ERR, "Jumbo Frames not supported "
+ "on 82542\n");
+ return -EINVAL;
+
+ } else {
+ if(max_frame <= E1000_RXBUFFER_2048) {
+ adapter->rx_buffer_len = E1000_RXBUFFER_2048;
+ } else if(max_frame <= E1000_RXBUFFER_4096) {
+ adapter->rx_buffer_len = E1000_RXBUFFER_4096;
+ } else if(max_frame <= E1000_RXBUFFER_8192) {
+ adapter->rx_buffer_len = E1000_RXBUFFER_8192;
+ } else if(max_frame <= E1000_RXBUFFER_16384) {
+ adapter->rx_buffer_len = E1000_RXBUFFER_16384;
+ }
+ }
}
- if(old_mtu != adapter->rx_buffer_len && netif_running(netdev)) {
+ netdev->mtu = new_mtu;
+
+ if(netif_running(netdev)) {
e1000_down(adapter);
e1000_up(adapter);
}
- netdev->mtu = new_mtu;
adapter->hw.max_frame_size = max_frame;
return 0;
@@ -2199,6 +2525,17 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->stats.tsctc += E1000_READ_REG(hw, TSCTC);
adapter->stats.tsctfc += E1000_READ_REG(hw, TSCTFC);
}
+ if(hw->mac_type > e1000_82547_rev_2) {
+ adapter->stats.iac += E1000_READ_REG(hw, IAC);
+ adapter->stats.icrxoc += E1000_READ_REG(hw, ICRXOC);
+ adapter->stats.icrxptc += E1000_READ_REG(hw, ICRXPTC);
+ adapter->stats.icrxatc += E1000_READ_REG(hw, ICRXATC);
+ adapter->stats.ictxptc += E1000_READ_REG(hw, ICTXPTC);
+ adapter->stats.ictxatc += E1000_READ_REG(hw, ICTXATC);
+ adapter->stats.ictxqec += E1000_READ_REG(hw, ICTXQEC);
+ adapter->stats.ictxqmtc += E1000_READ_REG(hw, ICTXQMTC);
+ adapter->stats.icrxdmtc += E1000_READ_REG(hw, ICRXDMTC);
+ }
/* Fill out the OS statistics structure */
@@ -2213,9 +2550,9 @@ e1000_update_stats(struct e1000_adapter *adapter)
adapter->net_stats.rx_errors = adapter->stats.rxerrc +
adapter->stats.crcerrs + adapter->stats.algnerrc +
- adapter->stats.rlec + adapter->stats.rnbc +
- adapter->stats.mpc + adapter->stats.cexterr;
- adapter->net_stats.rx_dropped = adapter->stats.rnbc;
+ adapter->stats.rlec + adapter->stats.mpc +
+ adapter->stats.cexterr;
+ adapter->net_stats.rx_dropped = adapter->stats.mpc;
adapter->net_stats.rx_length_errors = adapter->stats.rlec;
adapter->net_stats.rx_crc_errors = adapter->stats.crcerrs;
adapter->net_stats.rx_frame_errors = adapter->stats.algnerrc;
@@ -2300,11 +2637,11 @@ e1000_intr(int irq, void *data, struct pt_regs *regs)
*/
if(hw->mac_type == e1000_82547 || hw->mac_type == e1000_82547_rev_2){
atomic_inc(&adapter->irq_sem);
- E1000_WRITE_REG(&adapter->hw, IMC, ~0);
+ E1000_WRITE_REG(hw, IMC, ~0);
}
for(i = 0; i < E1000_MAX_INTR; i++)
- if(unlikely(!e1000_clean_rx_irq(adapter) &
+ if(unlikely(!adapter->clean_rx(adapter) &
!e1000_clean_tx_irq(adapter)))
break;
@@ -2328,16 +2665,15 @@ e1000_clean(struct net_device *netdev, int *budget)
int work_to_do = min(*budget, netdev->quota);
int tx_cleaned;
int work_done = 0;
-
+
tx_cleaned = e1000_clean_tx_irq(adapter);
- e1000_clean_rx_irq(adapter, &work_done, work_to_do);
+ adapter->clean_rx(adapter, &work_done, work_to_do);
*budget -= work_done;
netdev->quota -= work_done;
- /* if no Tx and not enough Rx work done, exit the polling mode */
- if((!tx_cleaned && (work_done < work_to_do)) ||
- !netif_running(netdev)) {
+ /* If no Tx and no Rx work done, exit the polling mode */
+ if ((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) {
netif_rx_complete(netdev);
e1000_irq_enable(adapter);
return 0;
@@ -2367,11 +2703,10 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
eop_desc = E1000_TX_DESC(*tx_ring, eop);
while(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
- /* pre-mature writeback of Tx descriptors */
- /* clear (free buffers and unmap pci_mapping) */
- /* previous_buffer_info */
+ /* Premature writeback of Tx descriptors clear (free buffers
+ * and unmap pci_mapping) previous_buffer_info */
if (likely(adapter->previous_buffer_info.skb != NULL)) {
- e1000_unmap_and_free_tx_resource(adapter,
+ e1000_unmap_and_free_tx_resource(adapter,
&adapter->previous_buffer_info);
}
@@ -2380,26 +2715,30 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
buffer_info = &tx_ring->buffer_info[i];
cleaned = (i == eop);
- /* pre-mature writeback of Tx descriptors */
- /* save the cleaning of the this for the */
- /* next iteration */
- if (cleaned) {
- memcpy(&adapter->previous_buffer_info,
- buffer_info,
- sizeof(struct e1000_buffer));
- memset(buffer_info,
- 0,
- sizeof(struct e1000_buffer));
+#ifdef NETIF_F_TSO
+ if (!(netdev->features & NETIF_F_TSO)) {
+#endif
+ e1000_unmap_and_free_tx_resource(adapter,
+ buffer_info);
+#ifdef NETIF_F_TSO
} else {
- e1000_unmap_and_free_tx_resource(adapter,
- buffer_info);
+ if (cleaned) {
+ memcpy(&adapter->previous_buffer_info,
+ buffer_info,
+ sizeof(struct e1000_buffer));
+ memset(buffer_info, 0,
+ sizeof(struct e1000_buffer));
+ } else {
+ e1000_unmap_and_free_tx_resource(
+ adapter, buffer_info);
+ }
}
+#endif
tx_desc->buffer_addr = 0;
tx_desc->lower.data = 0;
tx_desc->upper.data = 0;
- cleaned = (i == eop);
if(unlikely(++i == tx_ring->count)) i = 0;
}
@@ -2416,57 +2755,107 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter)
netif_wake_queue(netdev);
spin_unlock(&adapter->tx_lock);
-
if(adapter->detect_tx_hung) {
- /* detect a transmit hang in hardware, this serializes the
+
+ /* Detect a transmit hang in hardware, this serializes the
* check with the clearing of time_stamp and movement of i */
adapter->detect_tx_hung = FALSE;
- if(tx_ring->buffer_info[i].dma &&
- time_after(jiffies, tx_ring->buffer_info[i].time_stamp + HZ) &&
- !(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_TXOFF))
+ if (tx_ring->buffer_info[i].dma &&
+ time_after(jiffies, tx_ring->buffer_info[i].time_stamp + HZ)
+ && !(E1000_READ_REG(&adapter->hw, STATUS) &
+ E1000_STATUS_TXOFF)) {
+
+ /* detected Tx unit hang */
+ i = tx_ring->next_to_clean;
+ eop = tx_ring->buffer_info[i].next_to_watch;
+ eop_desc = E1000_TX_DESC(*tx_ring, eop);
+ DPRINTK(TX_ERR, ERR, "Detected Tx Unit Hang\n"
+ " TDH <%x>\n"
+ " TDT <%x>\n"
+ " next_to_use <%x>\n"
+ " next_to_clean <%x>\n"
+ "buffer_info[next_to_clean]\n"
+ " dma <%llx>\n"
+ " time_stamp <%lx>\n"
+ " next_to_watch <%x>\n"
+ " jiffies <%lx>\n"
+ " next_to_watch.status <%x>\n",
+ E1000_READ_REG(&adapter->hw, TDH),
+ E1000_READ_REG(&adapter->hw, TDT),
+ tx_ring->next_to_use,
+ i,
+ tx_ring->buffer_info[i].dma,
+ tx_ring->buffer_info[i].time_stamp,
+ eop,
+ jiffies,
+ eop_desc->upper.fields.status);
netif_stop_queue(netdev);
+ }
}
+#ifdef NETIF_F_TSO
+
+ if( unlikely(!(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) &&
+ time_after(jiffies, adapter->previous_buffer_info.time_stamp + HZ)))
+ e1000_unmap_and_free_tx_resource(
+ adapter, &adapter->previous_buffer_info);
+#endif
return cleaned;
}
/**
* e1000_rx_checksum - Receive Checksum Offload for 82543
- * @adapter: board private structure
- * @rx_desc: receive descriptor
- * @sk_buff: socket buffer with received data
+ * @adapter: board private structure
+ * @status_err: receive descriptor status and error fields
+ * @csum: receive descriptor csum field
+ * @sk_buff: socket buffer with received data
**/
static inline void
e1000_rx_checksum(struct e1000_adapter *adapter,
- struct e1000_rx_desc *rx_desc,
- struct sk_buff *skb)
+ uint32_t status_err, uint32_t csum,
+ struct sk_buff *skb)
{
+ uint16_t status = (uint16_t)status_err;
+ uint8_t errors = (uint8_t)(status_err >> 24);
+ skb->ip_summed = CHECKSUM_NONE;
+
/* 82543 or newer only */
- if(unlikely((adapter->hw.mac_type < e1000_82543) ||
+ if(unlikely(adapter->hw.mac_type < e1000_82543)) return;
/* Ignore Checksum bit is set */
- (rx_desc->status & E1000_RXD_STAT_IXSM) ||
- /* TCP Checksum has not been calculated */
- (!(rx_desc->status & E1000_RXD_STAT_TCPCS)))) {
- skb->ip_summed = CHECKSUM_NONE;
- return;
- }
-
- /* At this point we know the hardware did the TCP checksum */
- /* now look at the TCP checksum error bit */
- if(rx_desc->errors & E1000_RXD_ERR_TCPE) {
+ if(unlikely(status & E1000_RXD_STAT_IXSM)) return;
+ /* TCP/UDP checksum error bit is set */
+ if(unlikely(errors & E1000_RXD_ERR_TCPE)) {
/* let the stack verify checksum errors */
- skb->ip_summed = CHECKSUM_NONE;
adapter->hw_csum_err++;
+ return;
+ }
+ /* TCP/UDP Checksum has not been calculated */
+ if(adapter->hw.mac_type <= e1000_82547_rev_2) {
+ if(!(status & E1000_RXD_STAT_TCPCS))
+ return;
} else {
+ if(!(status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)))
+ return;
+ }
+ /* It must be a TCP or UDP packet with a valid checksum */
+ if (likely(status & E1000_RXD_STAT_TCPCS)) {
/* TCP checksum is good */
skb->ip_summed = CHECKSUM_UNNECESSARY;
- adapter->hw_csum_good++;
+ } else if (adapter->hw.mac_type > e1000_82547_rev_2) {
+ /* IP fragment with UDP payload */
+ /* Hardware complements the payload checksum, so we undo it
+ * and then put the value in host order for further stack use.
+ */
+ csum = ntohl(csum ^ 0xFFFF);
+ skb->csum = csum;
+ skb->ip_summed = CHECKSUM_HW;
}
+ adapter->hw_csum_good++;
}
/**
- * e1000_clean_rx_irq - Send received data up the network stack
+ * e1000_clean_rx_irq - Send received data up the network stack; legacy
* @adapter: board private structure
**/
@@ -2513,7 +2902,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter)
if(unlikely(!(rx_desc->status & E1000_RXD_STAT_EOP))) {
/* All receives must fit into a single buffer */
E1000_DBG("%s: Receive packet consumed multiple"
- " buffers\n", netdev->name);
+ " buffers\n", netdev->name);
dev_kfree_skb_irq(skb);
goto next_desc;
}
@@ -2539,15 +2928,17 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter)
skb_put(skb, length - ETHERNET_FCS_SIZE);
/* Receive Checksum Offload */
- e1000_rx_checksum(adapter, rx_desc, skb);
-
+ e1000_rx_checksum(adapter,
+ (uint32_t)(rx_desc->status) |
+ ((uint32_t)(rx_desc->errors) << 24),
+ rx_desc->csum, skb);
skb->protocol = eth_type_trans(skb, netdev);
#ifdef CONFIG_E1000_NAPI
if(unlikely(adapter->vlgrp &&
(rx_desc->status & E1000_RXD_STAT_VP))) {
vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
- le16_to_cpu(rx_desc->special) &
- E1000_RXD_SPC_VLAN_MASK);
+ le16_to_cpu(rx_desc->special) &
+ E1000_RXD_SPC_VLAN_MASK);
} else {
netif_receive_skb(skb);
}
@@ -2570,16 +2961,142 @@ next_desc:
rx_desc = E1000_RX_DESC(*rx_ring, i);
}
-
rx_ring->next_to_clean = i;
+ adapter->alloc_rx_buf(adapter);
+
+ return cleaned;
+}
+
+/**
+ * e1000_clean_rx_irq_ps - Send received data up the network stack; packet split
+ * @adapter: board private structure
+ **/
+
+static boolean_t
+#ifdef CONFIG_E1000_NAPI
+e1000_clean_rx_irq_ps(struct e1000_adapter *adapter, int *work_done,
+ int work_to_do)
+#else
+e1000_clean_rx_irq_ps(struct e1000_adapter *adapter)
+#endif
+{
+ struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
+ union e1000_rx_desc_packet_split *rx_desc;
+ struct net_device *netdev = adapter->netdev;
+ struct pci_dev *pdev = adapter->pdev;
+ struct e1000_buffer *buffer_info;
+ struct e1000_ps_page *ps_page;
+ struct e1000_ps_page_dma *ps_page_dma;
+ struct sk_buff *skb;
+ unsigned int i, j;
+ uint32_t length, staterr;
+ boolean_t cleaned = FALSE;
+
+ i = rx_ring->next_to_clean;
+ rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
+ staterr = rx_desc->wb.middle.status_error;
+
+ while(staterr & E1000_RXD_STAT_DD) {
+ buffer_info = &rx_ring->buffer_info[i];
+ ps_page = &rx_ring->ps_page[i];
+ ps_page_dma = &rx_ring->ps_page_dma[i];
+#ifdef CONFIG_E1000_NAPI
+ if(unlikely(*work_done >= work_to_do))
+ break;
+ (*work_done)++;
+#endif
+ cleaned = TRUE;
+ pci_unmap_single(pdev, buffer_info->dma,
+ buffer_info->length,
+ PCI_DMA_FROMDEVICE);
+
+ skb = buffer_info->skb;
+
+ if(unlikely(!(staterr & E1000_RXD_STAT_EOP))) {
+ E1000_DBG("%s: Packet Split buffers didn't pick up"
+ " the full packet\n", netdev->name);
+ dev_kfree_skb_irq(skb);
+ goto next_desc;
+ }
+
+ if(unlikely(staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)) {
+ dev_kfree_skb_irq(skb);
+ goto next_desc;
+ }
+
+ length = le16_to_cpu(rx_desc->wb.middle.length0);
+
+ if(unlikely(!length)) {
+ E1000_DBG("%s: Last part of the packet spanning"
+ " multiple descriptors\n", netdev->name);
+ dev_kfree_skb_irq(skb);
+ goto next_desc;
+ }
+
+ /* Good Receive */
+ skb_put(skb, length);
+
+ for(j = 0; j < PS_PAGE_BUFFERS; j++) {
+ if(!(length = le16_to_cpu(rx_desc->wb.upper.length[j])))
+ break;
+
+ pci_unmap_page(pdev, ps_page_dma->ps_page_dma[j],
+ PAGE_SIZE, PCI_DMA_FROMDEVICE);
+ ps_page_dma->ps_page_dma[j] = 0;
+ skb_shinfo(skb)->frags[j].page =
+ ps_page->ps_page[j];
+ ps_page->ps_page[j] = NULL;
+ skb_shinfo(skb)->frags[j].page_offset = 0;
+ skb_shinfo(skb)->frags[j].size = length;
+ skb_shinfo(skb)->nr_frags++;
+ skb->len += length;
+ skb->data_len += length;
+ }
- e1000_alloc_rx_buffers(adapter);
+ e1000_rx_checksum(adapter, staterr,
+ rx_desc->wb.lower.hi_dword.csum_ip.csum, skb);
+ skb->protocol = eth_type_trans(skb, netdev);
+
+#ifdef HAVE_RX_ZERO_COPY
+ if(likely(rx_desc->wb.upper.header_status &
+ E1000_RXDPS_HDRSTAT_HDRSP))
+ skb_shinfo(skb)->zero_copy = TRUE;
+#endif
+#ifdef CONFIG_E1000_NAPI
+ if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
+ vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
+ le16_to_cpu(rx_desc->wb.middle.vlan &
+ E1000_RXD_SPC_VLAN_MASK));
+ } else {
+ netif_receive_skb(skb);
+ }
+#else /* CONFIG_E1000_NAPI */
+ if(unlikely(adapter->vlgrp && (staterr & E1000_RXD_STAT_VP))) {
+ vlan_hwaccel_rx(skb, adapter->vlgrp,
+ le16_to_cpu(rx_desc->wb.middle.vlan &
+ E1000_RXD_SPC_VLAN_MASK));
+ } else {
+ netif_rx(skb);
+ }
+#endif /* CONFIG_E1000_NAPI */
+ netdev->last_rx = jiffies;
+
+next_desc:
+ rx_desc->wb.middle.status_error &= ~0xFF;
+ buffer_info->skb = NULL;
+ if(unlikely(++i == rx_ring->count)) i = 0;
+
+ rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
+ staterr = rx_desc->wb.middle.status_error;
+ }
+ rx_ring->next_to_clean = i;
+ adapter->alloc_rx_buf(adapter);
return cleaned;
}
/**
- * e1000_alloc_rx_buffers - Replace used receive buffers
+ * e1000_alloc_rx_buffers - Replace used receive buffers; legacy & extended
* @adapter: address of board private structure
**/
@@ -2592,43 +3109,43 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter)
struct e1000_rx_desc *rx_desc;
struct e1000_buffer *buffer_info;
struct sk_buff *skb;
- unsigned int i, bufsz;
+ unsigned int i;
+ unsigned int bufsz = adapter->rx_buffer_len + NET_IP_ALIGN;
i = rx_ring->next_to_use;
buffer_info = &rx_ring->buffer_info[i];
while(!buffer_info->skb) {
- bufsz = adapter->rx_buffer_len + NET_IP_ALIGN;
-
skb = dev_alloc_skb(bufsz);
+
if(unlikely(!skb)) {
/* Better luck next round */
break;
}
- /* fix for errata 23, cant cross 64kB boundary */
+ /* Fix for errata 23, can't cross 64kB boundary */
if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) {
struct sk_buff *oldskb = skb;
- DPRINTK(RX_ERR,ERR,
- "skb align check failed: %u bytes at %p\n",
- bufsz, skb->data);
- /* try again, without freeing the previous */
+ DPRINTK(RX_ERR, ERR, "skb align check failed: %u bytes "
+ "at %p\n", bufsz, skb->data);
+ /* Try again, without freeing the previous */
skb = dev_alloc_skb(bufsz);
+ /* Failed allocation, critical failure */
if (!skb) {
dev_kfree_skb(oldskb);
break;
}
+
if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) {
/* give up */
dev_kfree_skb(skb);
dev_kfree_skb(oldskb);
break; /* while !buffer_info->skb */
} else {
- /* move on with the new one */
+ /* Use new allocation */
dev_kfree_skb(oldskb);
}
}
-
/* Make buffer alignment 2 beyond a 16 byte boundary
* this will result in a 16 byte aligned IP header after
* the 14 byte MAC header is removed
@@ -2644,25 +3161,23 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter)
adapter->rx_buffer_len,
PCI_DMA_FROMDEVICE);
- /* fix for errata 23, cant cross 64kB boundary */
- if(!e1000_check_64k_bound(adapter,
- (void *)(unsigned long)buffer_info->dma,
- adapter->rx_buffer_len)) {
- DPRINTK(RX_ERR,ERR,
- "dma align check failed: %u bytes at %ld\n",
- adapter->rx_buffer_len, (unsigned long)buffer_info->dma);
-
+ /* Fix for errata 23, can't cross 64kB boundary */
+ if (!e1000_check_64k_bound(adapter,
+ (void *)(unsigned long)buffer_info->dma,
+ adapter->rx_buffer_len)) {
+ DPRINTK(RX_ERR, ERR,
+ "dma align check failed: %u bytes at %p\n",
+ adapter->rx_buffer_len,
+ (void *)(unsigned long)buffer_info->dma);
dev_kfree_skb(skb);
buffer_info->skb = NULL;
- pci_unmap_single(pdev,
- buffer_info->dma,
+ pci_unmap_single(pdev, buffer_info->dma,
adapter->rx_buffer_len,
PCI_DMA_FROMDEVICE);
break; /* while !buffer_info->skb */
}
-
rx_desc = E1000_RX_DESC(*rx_ring, i);
rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
@@ -2672,7 +3187,6 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter)
* applicable for weak-ordered memory model archs,
* such as IA-64). */
wmb();
-
E1000_WRITE_REG(&adapter->hw, RDT, i);
}
@@ -2684,6 +3198,95 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter)
}
/**
+ * e1000_alloc_rx_buffers_ps - Replace used receive buffers; packet split
+ * @adapter: address of board private structure
+ **/
+
+static void
+e1000_alloc_rx_buffers_ps(struct e1000_adapter *adapter)
+{
+ struct e1000_desc_ring *rx_ring = &adapter->rx_ring;
+ struct net_device *netdev = adapter->netdev;
+ struct pci_dev *pdev = adapter->pdev;
+ union e1000_rx_desc_packet_split *rx_desc;
+ struct e1000_buffer *buffer_info;
+ struct e1000_ps_page *ps_page;
+ struct e1000_ps_page_dma *ps_page_dma;
+ struct sk_buff *skb;
+ unsigned int i, j;
+
+ i = rx_ring->next_to_use;
+ buffer_info = &rx_ring->buffer_info[i];
+ ps_page = &rx_ring->ps_page[i];
+ ps_page_dma = &rx_ring->ps_page_dma[i];
+
+ while(!buffer_info->skb) {
+ rx_desc = E1000_RX_DESC_PS(*rx_ring, i);
+
+ for(j = 0; j < PS_PAGE_BUFFERS; j++) {
+ if(unlikely(!ps_page->ps_page[j])) {
+ ps_page->ps_page[j] =
+ alloc_page(GFP_ATOMIC);
+ if(unlikely(!ps_page->ps_page[j]))
+ goto no_buffers;
+ ps_page_dma->ps_page_dma[j] =
+ pci_map_page(pdev,
+ ps_page->ps_page[j],
+ 0, PAGE_SIZE,
+ PCI_DMA_FROMDEVICE);
+ }
+ /* Refresh the desc even if buffer_addrs didn't
+ * change because each write-back erases this info.
+ */
+ rx_desc->read.buffer_addr[j+1] =
+ cpu_to_le64(ps_page_dma->ps_page_dma[j]);
+ }
+
+ skb = dev_alloc_skb(adapter->rx_ps_bsize0 + NET_IP_ALIGN);
+
+ if(unlikely(!skb))
+ break;
+
+ /* Make buffer alignment 2 beyond a 16 byte boundary
+ * this will result in a 16 byte aligned IP header after
+ * the 14 byte MAC header is removed
+ */
+ skb_reserve(skb, NET_IP_ALIGN);
+
+ skb->dev = netdev;
+
+ buffer_info->skb = skb;
+ buffer_info->length = adapter->rx_ps_bsize0;
+ buffer_info->dma = pci_map_single(pdev, skb->data,
+ adapter->rx_ps_bsize0,
+ PCI_DMA_FROMDEVICE);
+
+ rx_desc->read.buffer_addr[0] = cpu_to_le64(buffer_info->dma);
+
+ if(unlikely((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i)) {
+ /* Force memory writes to complete before letting h/w
+ * know there are new descriptors to fetch. (Only
+ * applicable for weak-ordered memory model archs,
+ * such as IA-64). */
+ wmb();
+ /* Hardware increments by 16 bytes, but packet split
+ * descriptors are 32 bytes...so we increment tail
+ * twice as much.
+ */
+ E1000_WRITE_REG(&adapter->hw, RDT, i<<1);
+ }
+
+ if(unlikely(++i == rx_ring->count)) i = 0;
+ buffer_info = &rx_ring->buffer_info[i];
+ ps_page = &rx_ring->ps_page[i];
+ ps_page_dma = &rx_ring->ps_page_dma[i];
+ }
+
+no_buffers:
+ rx_ring->next_to_use = i;
+}
+
+/**
* e1000_smartspeed - Workaround for SmartSpeed on 82541 and 82547 controllers.
* @adapter:
**/
@@ -2856,9 +3459,10 @@ void
e1000_pci_set_mwi(struct e1000_hw *hw)
{
struct e1000_adapter *adapter = hw->back;
+ int ret_val = pci_set_mwi(adapter->pdev);
- int ret;
- ret = pci_set_mwi(adapter->pdev);
+ if(ret_val)
+ DPRINTK(PROBE, ERR, "Error in setting MWI\n");
}
void
@@ -2917,6 +3521,7 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
rctl |= E1000_RCTL_VFE;
rctl &= ~E1000_RCTL_CFIEN;
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ e1000_update_mng_vlan(adapter);
} else {
/* disable VLAN tag insert/strip */
ctrl = E1000_READ_REG(&adapter->hw, CTRL);
@@ -2927,6 +3532,10 @@ e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
rctl = E1000_READ_REG(&adapter->hw, RCTL);
rctl &= ~E1000_RCTL_VFE;
E1000_WRITE_REG(&adapter->hw, RCTL, rctl);
+ if(adapter->mng_vlan_id != (uint16_t)E1000_MNG_VLAN_NONE) {
+ e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
+ adapter->mng_vlan_id = E1000_MNG_VLAN_NONE;
+ }
}
e1000_irq_enable(adapter);
@@ -2937,7 +3546,10 @@ e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid)
{
struct e1000_adapter *adapter = netdev->priv;
uint32_t vfta, index;
-
+ if((adapter->hw.mng_cookie.status &
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
+ (vid == adapter->mng_vlan_id))
+ return;
/* add VID to filter table */
index = (vid >> 5) & 0x7F;
vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index);
@@ -2958,6 +3570,10 @@ e1000_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid)
e1000_irq_enable(adapter);
+ if((adapter->hw.mng_cookie.status &
+ E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) &&
+ (vid == adapter->mng_vlan_id))
+ return;
/* remove VID from filter table */
index = (vid >> 5) & 0x7F;
vfta = E1000_READ_REG_ARRAY(&adapter->hw, VFTA, index);
@@ -3004,8 +3620,7 @@ e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx)
break;
case SPEED_1000 + DUPLEX_HALF: /* not supported */
default:
- DPRINTK(PROBE, ERR,
- "Unsupported Speed/Duplexity configuration\n");
+ DPRINTK(PROBE, ERR, "Unsupported Speed/Duplex configuration\n");
return -EINVAL;
}
return 0;
@@ -3033,7 +3648,7 @@ e1000_suspend(struct pci_dev *pdev, uint32_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev->priv;
- uint32_t ctrl, ctrl_ext, rctl, manc, status;
+ uint32_t ctrl, ctrl_ext, rctl, manc, status, swsm;
uint32_t wufc = adapter->wol;
netif_device_detach(netdev);
@@ -3075,6 +3690,9 @@ e1000_suspend(struct pci_dev *pdev, uint32_t state)
E1000_WRITE_REG(&adapter->hw, CTRL_EXT, ctrl_ext);
}
+ /* Allow time for pending master requests to run */
+ e1000_disable_pciex_master(&adapter->hw);
+
E1000_WRITE_REG(&adapter->hw, WUC, E1000_WUC_PME_EN);
E1000_WRITE_REG(&adapter->hw, WUFC, wufc);
pci_enable_wake(pdev, 3, 1);
@@ -3099,6 +3717,16 @@ e1000_suspend(struct pci_dev *pdev, uint32_t state)
}
}
+ switch(adapter->hw.mac_type) {
+ case e1000_82573:
+ swsm = E1000_READ_REG(&adapter->hw, SWSM);
+ E1000_WRITE_REG(&adapter->hw, SWSM,
+ swsm & ~E1000_SWSM_DRV_LOAD);
+ break;
+ default:
+ break;
+ }
+
pci_disable_device(pdev);
state = (state > 0) ? 3 : 0;
@@ -3113,13 +3741,12 @@ e1000_resume(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev->priv;
- uint32_t manc, ret;
+ uint32_t manc, ret, swsm;
pci_set_power_state(pdev, 0);
pci_restore_state(pdev);
ret = pci_enable_device(pdev);
- if (pdev->is_busmaster)
- pci_set_master(pdev);
+ pci_set_master(pdev);
pci_enable_wake(pdev, 3, 0);
pci_enable_wake(pdev, 4, 0); /* 4 == D3 cold */
@@ -3139,10 +3766,19 @@ e1000_resume(struct pci_dev *pdev)
E1000_WRITE_REG(&adapter->hw, MANC, manc);
}
+ switch(adapter->hw.mac_type) {
+ case e1000_82573:
+ swsm = E1000_READ_REG(&adapter->hw, SWSM);
+ E1000_WRITE_REG(&adapter->hw, SWSM,
+ swsm | E1000_SWSM_DRV_LOAD);
+ break;
+ default:
+ break;
+ }
+
return 0;
}
#endif
-
#ifdef CONFIG_NET_POLL_CONTROLLER
/*
* Polling 'interrupt' - used by things like netconsole to send skbs
@@ -3150,7 +3786,7 @@ e1000_resume(struct pci_dev *pdev)
* the interrupt routine is executing.
*/
static void
-e1000_netpoll (struct net_device *netdev)
+e1000_netpoll(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev->priv;
disable_irq(adapter->pdev->irq);
diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h
index 970c656a517..aac64de6143 100644
--- a/drivers/net/e1000/e1000_osdep.h
+++ b/drivers/net/e1000/e1000_osdep.h
@@ -1,7 +1,7 @@
/*******************************************************************************
- Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+ Copyright(c) 1999 - 2005 Intel Corporation. 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
@@ -42,7 +42,12 @@
#include <linux/sched.h>
#ifndef msec_delay
-#define msec_delay(x) msleep(x)
+#define msec_delay(x) do { if(in_interrupt()) { \
+ /* Don't mdelay in interrupt context! */ \
+ BUG(); \
+ } else { \
+ msleep(x); \
+ } } while(0)
/* Some workarounds require millisecond delays and are run during interrupt
* context. Most notably, when establishing link, the phy may need tweaking
@@ -96,6 +101,29 @@ typedef enum {
(((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
((offset) << 2)))
+#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY
+#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY
+
+#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \
+ writew((value), ((a)->hw_addr + \
+ (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
+ ((offset) << 1))))
+
+#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \
+ readw((a)->hw_addr + \
+ (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
+ ((offset) << 1)))
+
+#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \
+ writeb((value), ((a)->hw_addr + \
+ (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
+ (offset))))
+
+#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \
+ readb((a)->hw_addr + \
+ (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \
+ (offset)))
+
#define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, STATUS)
#endif /* _E1000_OSDEP_H_ */
diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c
index e914d09fe6f..676247f9f1c 100644
--- a/drivers/net/e1000/e1000_param.c
+++ b/drivers/net/e1000/e1000_param.c
@@ -1,7 +1,7 @@
/*******************************************************************************
- Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+ Copyright(c) 1999 - 2005 Intel Corporation. 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
@@ -478,7 +478,6 @@ e1000_check_options(struct e1000_adapter *adapter)
DPRINTK(PROBE, INFO, "%s set to dynamic mode\n",
opt.name);
break;
- case -1:
default:
e1000_validate_option(&adapter->itr, &opt,
adapter);
diff --git a/drivers/net/fmv18x.c b/drivers/net/fmv18x.c
deleted file mode 100644
index 04c74852347..00000000000
--- a/drivers/net/fmv18x.c
+++ /dev/null
@@ -1,689 +0,0 @@
-/* fmv18x.c: A network device driver for the Fujitsu FMV-181/182/183/184.
-
- Original: at1700.c (1993-94 by Donald Becker).
- Copyright 1993 United States Government as represented by the
- Director, National Security Agency.
- The author may be reached as becker@scyld.com, or C/O
- Scyld Computing Corporation
- 410 Severn Ave., Suite 210
- Annapolis MD 21403
-
- Modified by Yutaka TAMIYA (tamy@flab.fujitsu.co.jp)
- Copyright 1994 Fujitsu Laboratories Ltd.
- Special thanks to:
- Masayoshi UTAKA (utaka@ace.yk.fujitsu.co.jp)
- for testing this driver.
- H. NEGISHI (agy, negishi@sun45.psd.cs.fujitsu.co.jp)
- for suggestion of some program modification.
- Masahiro SEKIGUCHI <seki@sysrap.cs.fujitsu.co.jp>
- for suggestion of some program modification.
- Kazutoshi MORIOKA (morioka@aurora.oaks.cs.fujitsu.co.jp)
- for testing this driver.
-
- This software may be used and distributed according to the terms
- of the GNU General Public License, incorporated herein by reference.
-
- This is a device driver for the Fujitsu FMV-181/182/183/184, which
- is a straight-forward Fujitsu MB86965 implementation.
-
- Sources:
- at1700.c
- The Fujitsu MB86965 datasheet.
- The Fujitsu FMV-181/182 user's guide
-*/
-
-static const char version[] =
- "fmv18x.c:v2.2.0 09/24/98 Yutaka TAMIYA (tamy@flab.fujitsu.co.jp)\n";
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/spinlock.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/delay.h>
-#include <linux/bitops.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-
-#define DRV_NAME "fmv18x"
-
-static unsigned fmv18x_probe_list[] __initdata = {
- 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0
-};
-
-/* use 0 for production, 1 for verification, >2 for debug */
-#ifndef NET_DEBUG
-#define NET_DEBUG 1
-#endif
-static unsigned int net_debug = NET_DEBUG;
-
-typedef unsigned char uchar;
-
-/* Information that need to be kept for each board. */
-struct net_local {
- struct net_device_stats stats;
- long open_time; /* Useless example local info. */
- uint tx_started:1; /* Number of packet on the Tx queue. */
- uint tx_queue_ready:1; /* Tx queue is ready to be sent. */
- uint rx_started:1; /* Packets are Rxing. */
- uchar tx_queue; /* Number of packet on the Tx queue. */
- ushort tx_queue_len; /* Current length of the Tx queue. */
- spinlock_t lock;
-};
-
-
-/* Offsets from the base address. */
-#define STATUS 0
-#define TX_STATUS 0
-#define RX_STATUS 1
-#define TX_INTR 2 /* Bit-mapped interrupt enable registers. */
-#define RX_INTR 3
-#define TX_MODE 4
-#define RX_MODE 5
-#define CONFIG_0 6 /* Misc. configuration settings. */
-#define CONFIG_1 7
-/* Run-time register bank 2 definitions. */
-#define DATAPORT 8 /* Word-wide DMA or programmed-I/O dataport. */
-#define TX_START 10
-#define COL16CNTL 11 /* Controll Reg for 16 collisions */
-#define MODE13 13
-/* Fujitsu FMV-18x Card Configuration */
-#define FJ_STATUS0 0x10
-#define FJ_STATUS1 0x11
-#define FJ_CONFIG0 0x12
-#define FJ_CONFIG1 0x13
-#define FJ_MACADDR 0x14 /* 0x14 - 0x19 */
-#define FJ_BUFCNTL 0x1A
-#define FJ_BUFDATA 0x1C
-#define FMV18X_IO_EXTENT 32
-
-/* Index to functions, as function prototypes. */
-
-static int fmv18x_probe1(struct net_device *dev, short ioaddr);
-static int net_open(struct net_device *dev);
-static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void net_rx(struct net_device *dev);
-static void net_timeout(struct net_device *dev);
-static int net_close(struct net_device *dev);
-static struct net_device_stats *net_get_stats(struct net_device *dev);
-static void set_multicast_list(struct net_device *dev);
-
-
-/* Check for a network adaptor of this type, and return '0' iff one exists.
- If dev->base_addr == 0, probe all likely locations.
- If dev->base_addr == 1, always return failure.
- If dev->base_addr == 2, allocate space for the device and return success
- (detachable devices only).
- */
-
-static int io = 0x220;
-static int irq;
-
-struct net_device * __init fmv18x_probe(int unit)
-{
- struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
- unsigned *port;
- int err = 0;
-
- if (!dev)
- return ERR_PTR(-ENODEV);
-
- if (unit >= 0) {
- sprintf(dev->name, "eth%d", unit);
- netdev_boot_setup_check(dev);
- io = dev->base_addr;
- irq = dev->irq;
- }
-
- SET_MODULE_OWNER(dev);
-
- if (io > 0x1ff) { /* Check a single specified location. */
- err = fmv18x_probe1(dev, io);
- } else if (io != 0) { /* Don't probe at all. */
- err = -ENXIO;
- } else {
- for (port = fmv18x_probe_list; *port; port++)
- if (fmv18x_probe1(dev, *port) == 0)
- break;
- if (!*port)
- err = -ENODEV;
- }
- if (err)
- goto out;
- err = register_netdev(dev);
- if (err)
- goto out1;
- return dev;
-out1:
- free_irq(dev->irq, dev);
- release_region(dev->base_addr, FMV18X_IO_EXTENT);
-out:
- free_netdev(dev);
- return ERR_PTR(err);
-}
-
-/* The Fujitsu datasheet suggests that the NIC be probed for by checking its
- "signature", the default bit pattern after a reset. This *doesn't* work --
- there is no way to reset the bus interface without a complete power-cycle!
-
- It turns out that ATI came to the same conclusion I did: the only thing
- that can be done is checking a few bits and then diving right into MAC
- address check. */
-
-static int __init fmv18x_probe1(struct net_device *dev, short ioaddr)
-{
- char irqmap[4] = {3, 7, 10, 15};
- char irqmap_pnp[8] = {3, 4, 5, 7, 9, 10, 11, 15};
- unsigned int i, retval;
- struct net_local *lp;
-
- /* Resetting the chip doesn't reset the ISA interface, so don't bother.
- That means we have to be careful with the register values we probe for.
- */
-
- if (!request_region(ioaddr, FMV18X_IO_EXTENT, DRV_NAME))
- return -EBUSY;
-
- dev->irq = irq;
- dev->base_addr = ioaddr;
-
- /* Check I/O address configuration and Fujitsu vendor code */
- if (inb(ioaddr+FJ_MACADDR ) != 0x00
- || inb(ioaddr+FJ_MACADDR+1) != 0x00
- || inb(ioaddr+FJ_MACADDR+2) != 0x0e) {
- retval = -ENODEV;
- goto out;
- }
-
- /* Check PnP mode for FMV-183/184/183A/184A. */
- /* This PnP routine is very poor. IO and IRQ should be known. */
- if (inb(ioaddr + FJ_STATUS1) & 0x20) {
- for (i = 0; i < 8; i++) {
- if (dev->irq == irqmap_pnp[i])
- break;
- }
- if (i == 8) {
- retval = -ENODEV;
- goto out;
- }
- } else {
- if (fmv18x_probe_list[inb(ioaddr + FJ_CONFIG0) & 0x07] != ioaddr)
- return -ENODEV;
- dev->irq = irqmap[(inb(ioaddr + FJ_CONFIG0)>>6) & 0x03];
- }
-
- /* Snarf the interrupt vector now. */
- retval = request_irq(dev->irq, &net_interrupt, 0, DRV_NAME, dev);
- if (retval) {
- printk ("FMV-18x found at %#3x, but it's unusable due to a conflict on"
- "IRQ %d.\n", ioaddr, dev->irq);
- goto out;
- }
-
- printk("%s: FMV-18x found at %#3x, IRQ %d, address ", dev->name,
- ioaddr, dev->irq);
-
- for(i = 0; i < 6; i++) {
- unsigned char val = inb(ioaddr + FJ_MACADDR + i);
- printk("%02x", val);
- dev->dev_addr[i] = val;
- }
-
- /* "FJ_STATUS0" 12 bit 0x0400 means use regular 100 ohm 10baseT signals,
- rather than 150 ohm shielded twisted pair compensation.
- 0x0000 == auto-sense the interface
- 0x0800 == use TP interface
- 0x1800 == use coax interface
- */
- {
- const char *porttype[] = {"auto-sense", "10baseT", "auto-sense", "10base2/5"};
- ushort setup_value = inb(ioaddr + FJ_STATUS0);
-
- switch( setup_value & 0x07 ){
- case 0x01 /* 10base5 */:
- case 0x02 /* 10base2 */: dev->if_port = 0x18; break;
- case 0x04 /* 10baseT */: dev->if_port = 0x08; break;
- default /* auto-sense*/: dev->if_port = 0x00; break;
- }
- printk(" %s interface.\n", porttype[(dev->if_port>>3) & 3]);
- }
-
- /* Initialize LAN Controller and LAN Card */
- outb(0xda, ioaddr + CONFIG_0); /* Initialize LAN Controller */
- outb(0x00, ioaddr + CONFIG_1); /* Stand by mode */
- outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */
- outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure (TAMIYA) */
-
- /* wait for a while */
- udelay(200);
-
- /* Set the station address in bank zero. */
- outb(0x00, ioaddr + CONFIG_1);
- for (i = 0; i < 6; i++)
- outb(dev->dev_addr[i], ioaddr + 8 + i);
-
- /* Switch to bank 1 and set the multicast table to accept none. */
- outb(0x04, ioaddr + CONFIG_1);
- for (i = 0; i < 8; i++)
- outb(0x00, ioaddr + 8 + i);
-
- /* Switch to bank 2 and lock our I/O address. */
- outb(0x08, ioaddr + CONFIG_1);
- outb(dev->if_port, ioaddr + MODE13);
- outb(0x00, ioaddr + COL16CNTL);
-
- if (net_debug)
- printk(version);
-
- /* Initialize the device structure. */
- dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
- if (!dev->priv) {
- retval = -ENOMEM;
- goto out_irq;
- }
- memset(dev->priv, 0, sizeof(struct net_local));
- lp = dev->priv;
- spin_lock_init(&lp->lock);
-
- dev->open = net_open;
- dev->stop = net_close;
- dev->hard_start_xmit = net_send_packet;
- dev->tx_timeout = net_timeout;
- dev->watchdog_timeo = HZ/10;
- dev->get_stats = net_get_stats;
- dev->set_multicast_list = set_multicast_list;
- return 0;
-
-out_irq:
- free_irq(dev->irq, dev);
-out:
- release_region(ioaddr, FMV18X_IO_EXTENT);
- return retval;
-}
-
-
-static int net_open(struct net_device *dev)
-{
- struct net_local *lp = dev->priv;
- int ioaddr = dev->base_addr;
-
- /* Set the configuration register 0 to 32K 100ns. byte-wide memory,
- 16 bit bus access, and two 4K Tx, enable the Rx and Tx. */
- outb(0x5a, ioaddr + CONFIG_0);
-
- /* Powerup and switch to register bank 2 for the run-time registers. */
- outb(0xe8, ioaddr + CONFIG_1);
-
- lp->tx_started = 0;
- lp->tx_queue_ready = 1;
- lp->rx_started = 0;
- lp->tx_queue = 0;
- lp->tx_queue_len = 0;
-
- /* Clear Tx and Rx Status */
- outb(0xff, ioaddr + TX_STATUS);
- outb(0xff, ioaddr + RX_STATUS);
- lp->open_time = jiffies;
-
- netif_start_queue(dev);
-
- /* Enable the IRQ of the LAN Card */
- outb(0x80, ioaddr + FJ_CONFIG1);
-
- /* Enable both Tx and Rx interrupts */
- outw(0x8182, ioaddr+TX_INTR);
-
- return 0;
-}
-
-static void net_timeout(struct net_device *dev)
-{
- struct net_local *lp = dev->priv;
- int ioaddr = dev->base_addr;
- unsigned long flags;
-
-
- printk(KERN_WARNING "%s: transmit timed out with status %04x, %s?\n", dev->name,
- htons(inw(ioaddr + TX_STATUS)),
- inb(ioaddr + TX_STATUS) & 0x80
- ? "IRQ conflict" : "network cable problem");
- printk(KERN_WARNING "%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n",
- dev->name, htons(inw(ioaddr + 0)),
- htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)),
- htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)),
- htons(inw(ioaddr +10)), htons(inw(ioaddr +12)),
- htons(inw(ioaddr +14)));
- printk(KERN_WARNING "eth card: %04x %04x\n",
- htons(inw(ioaddr+FJ_STATUS0)),
- htons(inw(ioaddr+FJ_CONFIG0)));
- lp->stats.tx_errors++;
- /* ToDo: We should try to restart the adaptor... */
- spin_lock_irqsave(&lp->lock, flags);
-
- /* Initialize LAN Controller and LAN Card */
- outb(0xda, ioaddr + CONFIG_0); /* Initialize LAN Controller */
- outb(0x00, ioaddr + CONFIG_1); /* Stand by mode */
- outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */
- outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure */
- net_open(dev);
- spin_unlock_irqrestore(&lp->lock, flags);
-
- netif_wake_queue(dev);
-}
-
-static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
-{
- struct net_local *lp = dev->priv;
- int ioaddr = dev->base_addr;
- short length = skb->len;
- unsigned char *buf;
- unsigned long flags;
-
- /* Block a transmit from overlapping. */
-
- if (length > ETH_FRAME_LEN) {
- if (net_debug)
- printk("%s: Attempting to send a large packet (%d bytes).\n",
- dev->name, length);
- return 1;
- }
-
- if (length < ETH_ZLEN) {
- skb = skb_padto(skb, ETH_ZLEN);
- if (skb == NULL)
- return 0;
- length = ETH_ZLEN;
- }
- buf = skb->data;
-
- if (net_debug > 4)
- printk("%s: Transmitting a packet of length %lu.\n", dev->name,
- (unsigned long)skb->len);
- /* We may not start transmitting unless we finish transferring
- a packet into the Tx queue. During executing the following
- codes we possibly catch a Tx interrupt. Thus we flag off
- tx_queue_ready, so that we prevent the interrupt routine
- (net_interrupt) to start transmitting. */
- spin_lock_irqsave(&lp->lock, flags);
- lp->tx_queue_ready = 0;
- {
- outw(length, ioaddr + DATAPORT);
- outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
- lp->tx_queue++;
- lp->tx_queue_len += length + 2;
- }
- lp->tx_queue_ready = 1;
- spin_unlock_irqrestore(&lp->lock, flags);
-
- if (lp->tx_started == 0) {
- /* If the Tx is idle, always trigger a transmit. */
- outb(0x80 | lp->tx_queue, ioaddr + TX_START);
- lp->tx_queue = 0;
- lp->tx_queue_len = 0;
- dev->trans_start = jiffies;
- lp->tx_started = 1;
- } else if (lp->tx_queue_len >= 4096 - 1502) /* No room for a packet */
- netif_stop_queue(dev);
-
- dev_kfree_skb(skb);
- return 0;
-}
-
-/* The typical workload of the driver:
- Handle the network interface interrupts. */
-static irqreturn_t
-net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct net_device *dev = dev_id;
- struct net_local *lp;
- int ioaddr, status;
-
- ioaddr = dev->base_addr;
- lp = dev->priv;
- status = inw(ioaddr + TX_STATUS);
- outw(status, ioaddr + TX_STATUS);
-
- if (net_debug > 4)
- printk("%s: Interrupt with status %04x.\n", dev->name, status);
- if (lp->rx_started == 0 &&
- (status & 0xff00 || (inb(ioaddr + RX_MODE) & 0x40) == 0)) {
- /* Got a packet(s).
- We cannot execute net_rx more than once at the same time for
- the same device. During executing net_rx, we possibly catch a
- Tx interrupt. Thus we flag on rx_started, so that we prevent
- the interrupt routine (net_interrupt) to dive into net_rx
- again. */
- lp->rx_started = 1;
- outb(0x00, ioaddr + RX_INTR); /* Disable RX intr. */
- net_rx(dev);
- outb(0x81, ioaddr + RX_INTR); /* Enable RX intr. */
- lp->rx_started = 0;
- }
- if (status & 0x00ff) {
- if (status & 0x02) {
- /* More than 16 collisions occurred */
- if (net_debug > 4)
- printk("%s: 16 Collision occur during Txing.\n", dev->name);
- /* Cancel sending a packet. */
- outb(0x03, ioaddr + COL16CNTL);
- lp->stats.collisions++;
- }
- if (status & 0x82) {
- spin_lock(&lp->lock);
- lp->stats.tx_packets++;
- if (lp->tx_queue && lp->tx_queue_ready) {
- outb(0x80 | lp->tx_queue, ioaddr + TX_START);
- lp->tx_queue = 0;
- lp->tx_queue_len = 0;
- dev->trans_start = jiffies;
- netif_wake_queue(dev); /* Inform upper layers. */
- } else {
- lp->tx_started = 0;
- netif_wake_queue(dev); /* Inform upper layers. */
- }
- spin_unlock(&lp->lock);
- }
- }
- return IRQ_RETVAL(status);
-}
-
-/* We have a good packet(s), get it/them out of the buffers. */
-static void net_rx(struct net_device *dev)
-{
- struct net_local *lp = dev->priv;
- int ioaddr = dev->base_addr;
- int boguscount = 5;
-
- while ((inb(ioaddr + RX_MODE) & 0x40) == 0) {
- /* Clear PKT_RDY bit: by agy 19940922 */
- /* outb(0x80, ioaddr + RX_STATUS); */
- ushort status = inw(ioaddr + DATAPORT);
-
- if (net_debug > 4)
- printk("%s: Rxing packet mode %02x status %04x.\n",
- dev->name, inb(ioaddr + RX_MODE), status);
-#ifndef final_version
- if (status == 0) {
- outb(0x05, ioaddr + 14);
- break;
- }
-#endif
-
- if ((status & 0xF0) != 0x20) { /* There was an error. */
- lp->stats.rx_errors++;
- if (status & 0x08) lp->stats.rx_length_errors++;
- if (status & 0x04) lp->stats.rx_frame_errors++;
- if (status & 0x02) lp->stats.rx_crc_errors++;
- if (status & 0x01) lp->stats.rx_over_errors++;
- } else {
- ushort pkt_len = inw(ioaddr + DATAPORT);
- /* Malloc up new buffer. */
- struct sk_buff *skb;
-
- if (pkt_len > 1550) {
- printk("%s: The FMV-18x claimed a very large packet, size %d.\n",
- dev->name, pkt_len);
- outb(0x05, ioaddr + 14);
- lp->stats.rx_errors++;
- break;
- }
- skb = dev_alloc_skb(pkt_len+3);
- if (skb == NULL) {
- printk("%s: Memory squeeze, dropping packet (len %d).\n",
- dev->name, pkt_len);
- outb(0x05, ioaddr + 14);
- lp->stats.rx_dropped++;
- break;
- }
- skb->dev = dev;
- skb_reserve(skb,2);
-
- insw(ioaddr + DATAPORT, skb_put(skb,pkt_len), (pkt_len + 1) >> 1);
-
- if (net_debug > 5) {
- int i;
- printk("%s: Rxed packet of length %d: ", dev->name, pkt_len);
- for (i = 0; i < 14; i++)
- printk(" %02x", skb->data[i]);
- printk(".\n");
- }
-
- skb->protocol=eth_type_trans(skb, dev);
- netif_rx(skb);
- dev->last_rx = jiffies;
- lp->stats.rx_packets++;
- lp->stats.rx_bytes += pkt_len;
- }
- if (--boguscount <= 0)
- break;
- }
-
- /* If any worth-while packets have been received, dev_rint()
- has done a mark_bh(NET_BH) for us and will work on them
- when we get to the bottom-half routine. */
- {
- int i;
- for (i = 0; i < 20; i++) {
- if ((inb(ioaddr + RX_MODE) & 0x40) == 0x40)
- break;
- (void)inw(ioaddr + DATAPORT); /* dummy status read */
- outb(0x05, ioaddr + 14);
- }
-
- if (net_debug > 5 && i > 0)
- printk("%s: Exint Rx packet with mode %02x after %d ticks.\n",
- dev->name, inb(ioaddr + RX_MODE), i);
- }
-
- return;
-}
-
-/* The inverse routine to net_open(). */
-static int net_close(struct net_device *dev)
-{
- int ioaddr = dev->base_addr;
-
- ((struct net_local *)dev->priv)->open_time = 0;
-
- netif_stop_queue(dev);
-
- /* Set configuration register 0 to disable Tx and Rx. */
- outb(0xda, ioaddr + CONFIG_0);
-
- /* Update the statistics -- ToDo. */
-
- /* Power-down the chip. Green, green, green! */
- outb(0x00, ioaddr + CONFIG_1);
-
- /* Set the ethernet adaptor disable IRQ */
- outb(0x00, ioaddr + FJ_CONFIG1);
-
- return 0;
-}
-
-/* Get the current statistics. This may be called with the card open or
- closed. */
-static struct net_device_stats *net_get_stats(struct net_device *dev)
-{
- struct net_local *lp = dev->priv;
- return &lp->stats;
-}
-
-/* Set or clear the multicast filter for this adaptor.
- num_addrs == -1 Promiscuous mode, receive all packets
- num_addrs == 0 Normal mode, clear multicast list
- num_addrs > 0 Multicast mode, receive normal and MC packets, and do
- best-effort filtering.
- */
-
-static void set_multicast_list(struct net_device *dev)
-{
- short ioaddr = dev->base_addr;
- if (dev->mc_count || dev->flags&(IFF_PROMISC|IFF_ALLMULTI))
- {
- /*
- * We must make the kernel realise we had to move
- * into promisc mode or we start all out war on
- * the cable. - AC
- */
- dev->flags|=IFF_PROMISC;
-
- outb(3, ioaddr + RX_MODE); /* Enable promiscuous mode */
- }
- else
- outb(2, ioaddr + RX_MODE); /* Disable promiscuous, use normal mode */
-}
-
-#ifdef MODULE
-static struct net_device *dev_fmv18x;
-
-MODULE_PARM(io, "i");
-MODULE_PARM(irq, "i");
-MODULE_PARM(net_debug, "i");
-MODULE_PARM_DESC(io, "FMV-18X I/O address");
-MODULE_PARM_DESC(irq, "FMV-18X IRQ number");
-MODULE_PARM_DESC(net_debug, "FMV-18X debug level (0-1,5-6)");
-MODULE_LICENSE("GPL");
-
-int init_module(void)
-{
- if (io == 0)
- printk("fmv18x: You should not use auto-probing with insmod!\n");
- dev_fmv18x = fmv18x_probe(-1);
- if (IS_ERR(dev_fmv18x))
- return PTR_ERR(dev_fmv18x);
- return 0;
-}
-
-void
-cleanup_module(void)
-{
- unregister_netdev(dev_fmv18x);
- free_irq(dev_fmv18x->irq, dev_fmv18x);
- release_region(dev_fmv18x->base_addr, FMV18X_IO_EXTENT);
- free_netdev(dev_fmv18x);
-}
-#endif /* MODULE */
-
-/*
- * Local variables:
- * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c fmv18x.c"
- * version-control: t
- * kept-new-versions: 5
- * tab-width: 4
- * c-indent-level: 4
- * End:
- */
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index cda48c5d72a..4ebcd052e15 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -81,6 +81,7 @@
* cause DMA to kfree'd memory.
* 0.31: 14 Nov 2004: ethtool support for getting/setting link
* capabilities.
+ * 0.32: 16 Apr 2005: RX_ERROR4 handling added.
*
* Known bugs:
* We suspect that on some hardware no TX done interrupts are generated.
@@ -92,7 +93,7 @@
* DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few
* superfluous timer interrupts from the nic.
*/
-#define FORCEDETH_VERSION "0.31"
+#define FORCEDETH_VERSION "0.32"
#define DRV_NAME "forcedeth"
#include <linux/module.h>
@@ -109,6 +110,7 @@
#include <linux/mii.h>
#include <linux/random.h>
#include <linux/init.h>
+#include <linux/if_vlan.h>
#include <asm/irq.h>
#include <asm/io.h>
@@ -1013,6 +1015,59 @@ static void nv_tx_timeout(struct net_device *dev)
spin_unlock_irq(&np->lock);
}
+/*
+ * Called when the nic notices a mismatch between the actual data len on the
+ * wire and the len indicated in the 802 header
+ */
+static int nv_getlen(struct net_device *dev, void *packet, int datalen)
+{
+ int hdrlen; /* length of the 802 header */
+ int protolen; /* length as stored in the proto field */
+
+ /* 1) calculate len according to header */
+ if ( ((struct vlan_ethhdr *)packet)->h_vlan_proto == __constant_htons(ETH_P_8021Q)) {
+ protolen = ntohs( ((struct vlan_ethhdr *)packet)->h_vlan_encapsulated_proto );
+ hdrlen = VLAN_HLEN;
+ } else {
+ protolen = ntohs( ((struct ethhdr *)packet)->h_proto);
+ hdrlen = ETH_HLEN;
+ }
+ dprintk(KERN_DEBUG "%s: nv_getlen: datalen %d, protolen %d, hdrlen %d\n",
+ dev->name, datalen, protolen, hdrlen);
+ if (protolen > ETH_DATA_LEN)
+ return datalen; /* Value in proto field not a len, no checks possible */
+
+ protolen += hdrlen;
+ /* consistency checks: */
+ if (datalen > ETH_ZLEN) {
+ if (datalen >= protolen) {
+ /* more data on wire than in 802 header, trim of
+ * additional data.
+ */
+ dprintk(KERN_DEBUG "%s: nv_getlen: accepting %d bytes.\n",
+ dev->name, protolen);
+ return protolen;
+ } else {
+ /* less data on wire than mentioned in header.
+ * Discard the packet.
+ */
+ dprintk(KERN_DEBUG "%s: nv_getlen: discarding long packet.\n",
+ dev->name);
+ return -1;
+ }
+ } else {
+ /* short packet. Accept only if 802 values are also short */
+ if (protolen > ETH_ZLEN) {
+ dprintk(KERN_DEBUG "%s: nv_getlen: discarding short packet.\n",
+ dev->name);
+ return -1;
+ }
+ dprintk(KERN_DEBUG "%s: nv_getlen: accepting %d bytes.\n",
+ dev->name, datalen);
+ return datalen;
+ }
+}
+
static void nv_rx_process(struct net_device *dev)
{
struct fe_priv *np = get_nvpriv(dev);
@@ -1064,7 +1119,7 @@ static void nv_rx_process(struct net_device *dev)
np->stats.rx_errors++;
goto next_pkt;
}
- if (Flags & (NV_RX_ERROR1|NV_RX_ERROR2|NV_RX_ERROR3|NV_RX_ERROR4)) {
+ if (Flags & (NV_RX_ERROR1|NV_RX_ERROR2|NV_RX_ERROR3)) {
np->stats.rx_errors++;
goto next_pkt;
}
@@ -1078,22 +1133,24 @@ static void nv_rx_process(struct net_device *dev)
np->stats.rx_errors++;
goto next_pkt;
}
- if (Flags & NV_RX_ERROR) {
- /* framing errors are soft errors, the rest is fatal. */
- if (Flags & NV_RX_FRAMINGERR) {
- if (Flags & NV_RX_SUBSTRACT1) {
- len--;
- }
- } else {
+ if (Flags & NV_RX_ERROR4) {
+ len = nv_getlen(dev, np->rx_skbuff[i]->data, len);
+ if (len < 0) {
np->stats.rx_errors++;
goto next_pkt;
}
}
+ /* framing errors are soft errors. */
+ if (Flags & NV_RX_FRAMINGERR) {
+ if (Flags & NV_RX_SUBSTRACT1) {
+ len--;
+ }
+ }
} else {
if (!(Flags & NV_RX2_DESCRIPTORVALID))
goto next_pkt;
- if (Flags & (NV_RX2_ERROR1|NV_RX2_ERROR2|NV_RX2_ERROR3|NV_RX2_ERROR4)) {
+ if (Flags & (NV_RX2_ERROR1|NV_RX2_ERROR2|NV_RX2_ERROR3)) {
np->stats.rx_errors++;
goto next_pkt;
}
@@ -1107,17 +1164,19 @@ static void nv_rx_process(struct net_device *dev)
np->stats.rx_errors++;
goto next_pkt;
}
- if (Flags & NV_RX2_ERROR) {
- /* framing errors are soft errors, the rest is fatal. */
- if (Flags & NV_RX2_FRAMINGERR) {
- if (Flags & NV_RX2_SUBSTRACT1) {
- len--;
- }
- } else {
+ if (Flags & NV_RX2_ERROR4) {
+ len = nv_getlen(dev, np->rx_skbuff[i]->data, len);
+ if (len < 0) {
np->stats.rx_errors++;
goto next_pkt;
}
}
+ /* framing errors are soft errors */
+ if (Flags & NV_RX2_FRAMINGERR) {
+ if (Flags & NV_RX2_SUBSTRACT1) {
+ len--;
+ }
+ }
Flags &= NV_RX2_CHECKSUMMASK;
if (Flags == NV_RX2_CHECKSUMOK1 ||
Flags == NV_RX2_CHECKSUMOK2 ||
@@ -1480,6 +1539,13 @@ static void nv_do_nic_poll(unsigned long data)
enable_irq(dev->irq);
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void nv_poll_controller(struct net_device *dev)
+{
+ nv_do_nic_poll((unsigned long) dev);
+}
+#endif
+
static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
struct fe_priv *np = get_nvpriv(dev);
@@ -1962,6 +2028,9 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
dev->get_stats = nv_get_stats;
dev->change_mtu = nv_change_mtu;
dev->set_multicast_list = nv_set_multicast;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = nv_poll_controller;
+#endif
SET_ETHTOOL_OPS(dev, &ops);
dev->tx_timeout = nv_tx_timeout;
dev->watchdog_timeo = NV_WATCHDOG_TIMEO;
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 89454915b85..e44f8e9055e 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -848,7 +848,7 @@ static void __exit sixpack_exit_driver(void)
{
int ret;
- if ((ret = tty_register_ldisc(N_6PACK, NULL)))
+ if ((ret = tty_unregister_ldisc(N_6PACK)))
printk(msg_unregfail, ret);
}
diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c
index 1c563f905a5..a7f15d9f13e 100644
--- a/drivers/net/hamradio/baycom_epp.c
+++ b/drivers/net/hamradio/baycom_epp.c
@@ -374,29 +374,6 @@ static inline void do_kiss_params(struct baycom_state *bc,
}
/* --------------------------------------------------------------------- */
-/*
- * high performance HDLC encoder
- * yes, it's ugly, but generates pretty good code
- */
-
-#define ENCODEITERA(j) \
-({ \
- if (!(notbitstream & (0x1f0 << j))) \
- goto stuff##j; \
- encodeend##j: ; \
-})
-
-#define ENCODEITERB(j) \
-({ \
- stuff##j: \
- bitstream &= ~(0x100 << j); \
- bitbuf = (bitbuf & (((2 << j) << numbit) - 1)) | \
- ((bitbuf & ~(((2 << j) << numbit) - 1)) << 1); \
- numbit++; \
- notbitstream = ~bitstream; \
- goto encodeend##j; \
-})
-
static void encode_hdlc(struct baycom_state *bc)
{
@@ -405,6 +382,7 @@ static void encode_hdlc(struct baycom_state *bc)
int pkt_len;
unsigned bitstream, notbitstream, bitbuf, numbit, crc;
unsigned char crcarr[2];
+ int j;
if (bc->hdlctx.bufcnt > 0)
return;
@@ -429,24 +407,14 @@ static void encode_hdlc(struct baycom_state *bc)
pkt_len--;
if (!pkt_len)
bp = crcarr;
- ENCODEITERA(0);
- ENCODEITERA(1);
- ENCODEITERA(2);
- ENCODEITERA(3);
- ENCODEITERA(4);
- ENCODEITERA(5);
- ENCODEITERA(6);
- ENCODEITERA(7);
- goto enditer;
- ENCODEITERB(0);
- ENCODEITERB(1);
- ENCODEITERB(2);
- ENCODEITERB(3);
- ENCODEITERB(4);
- ENCODEITERB(5);
- ENCODEITERB(6);
- ENCODEITERB(7);
- enditer:
+ for (j = 0; j < 8; j++)
+ if (unlikely(!(notbitstream & (0x1f0 << j)))) {
+ bitstream &= ~(0x100 << j);
+ bitbuf = (bitbuf & (((2 << j) << numbit) - 1)) |
+ ((bitbuf & ~(((2 << j) << numbit) - 1)) << 1);
+ numbit++;
+ notbitstream = ~bitstream;
+ }
numbit += 8;
while (numbit >= 8) {
*wp++ = bitbuf;
@@ -610,37 +578,6 @@ static void do_rxpacket(struct net_device *dev)
bc->stats.rx_packets++;
}
-#define DECODEITERA(j) \
-({ \
- if (!(notbitstream & (0x0fc << j))) /* flag or abort */ \
- goto flgabrt##j; \
- if ((bitstream & (0x1f8 << j)) == (0xf8 << j)) /* stuffed bit */ \
- goto stuff##j; \
- enditer##j: ; \
-})
-
-#define DECODEITERB(j) \
-({ \
- flgabrt##j: \
- if (!(notbitstream & (0x1fc << j))) { /* abort received */ \
- state = 0; \
- goto enditer##j; \
- } \
- if ((bitstream & (0x1fe << j)) != (0x0fc << j)) /* flag received */ \
- goto enditer##j; \
- if (state) \
- do_rxpacket(dev); \
- bc->hdlcrx.bufcnt = 0; \
- bc->hdlcrx.bufptr = bc->hdlcrx.buf; \
- state = 1; \
- numbits = 7-j; \
- goto enditer##j; \
- stuff##j: \
- numbits--; \
- bitbuf = (bitbuf & ((~0xff) << j)) | ((bitbuf & ~((~0xff) << j)) << 1); \
- goto enditer##j; \
-})
-
static int receive(struct net_device *dev, int cnt)
{
struct baycom_state *bc = netdev_priv(dev);
@@ -649,6 +586,7 @@ static int receive(struct net_device *dev, int cnt)
unsigned char tmp[128];
unsigned char *cp;
int cnt2, ret = 0;
+ int j;
numbits = bc->hdlcrx.numbits;
state = bc->hdlcrx.state;
@@ -669,24 +607,32 @@ static int receive(struct net_device *dev, int cnt)
bitbuf |= (*cp) << 8;
numbits += 8;
notbitstream = ~bitstream;
- DECODEITERA(0);
- DECODEITERA(1);
- DECODEITERA(2);
- DECODEITERA(3);
- DECODEITERA(4);
- DECODEITERA(5);
- DECODEITERA(6);
- DECODEITERA(7);
- goto enddec;
- DECODEITERB(0);
- DECODEITERB(1);
- DECODEITERB(2);
- DECODEITERB(3);
- DECODEITERB(4);
- DECODEITERB(5);
- DECODEITERB(6);
- DECODEITERB(7);
- enddec:
+ for (j = 0; j < 8; j++) {
+
+ /* flag or abort */
+ if (unlikely(!(notbitstream & (0x0fc << j)))) {
+
+ /* abort received */
+ if (!(notbitstream & (0x1fc << j)))
+ state = 0;
+
+ /* not flag received */
+ else if (!(bitstream & (0x1fe << j)) != (0x0fc << j)) {
+ if (state)
+ do_rxpacket(dev);
+ bc->hdlcrx.bufcnt = 0;
+ bc->hdlcrx.bufptr = bc->hdlcrx.buf;
+ state = 1;
+ numbits = 7-j;
+ }
+ }
+
+ /* stuffed bit */
+ else if (unlikely((bitstream & (0x1f8 << j)) == (0xf8 << j))) {
+ numbits--;
+ bitbuf = (bitbuf & ((~0xff) << j)) | ((bitbuf & ~((~0xff) << j)) << 1);
+ }
+ }
while (state && numbits >= 8) {
if (bc->hdlcrx.bufcnt >= TXBUFFER_SIZE) {
state = 0;
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index 62790511098..3035422f5ad 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -934,7 +934,7 @@ static void __exit mkiss_exit_driver(void)
kfree(ax25_ctrls);
ax25_ctrls = NULL;
- if ((i = tty_register_ldisc(N_AX25, NULL)))
+ if ((i = tty_unregister_ldisc(N_AX25)))
printk(KERN_ERR "mkiss: can't unregister line discipline (err = %d)\n", i);
}
diff --git a/drivers/net/ibm_emac/ibm_emac_core.c b/drivers/net/ibm_emac/ibm_emac_core.c
index ab44358ddbf..6482d994d48 100644
--- a/drivers/net/ibm_emac/ibm_emac_core.c
+++ b/drivers/net/ibm_emac/ibm_emac_core.c
@@ -1595,7 +1595,7 @@ static struct ethtool_ops emac_ethtool_ops = {
static int emac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct ocp_enet_private *fep = dev->priv;
- uint *data = (uint *) & rq->ifr_ifru;
+ uint16_t *data = (uint16_t *) & rq->ifr_ifru;
switch (cmd) {
case SIOCGMIIPHY:
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index 1c553d7efdd..ca5914091d3 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -389,7 +389,7 @@ config VIA_FIR
help
Say Y here if you want to build support for the VIA VT8231
and VIA VT1211 IrDA controllers, found on the motherboards using
- those those VIA chipsets. To use this controller, you will need
+ those VIA chipsets. To use this controller, you will need
to plug a specific 5 pins FIR IrDA dongle in the specific
motherboard connector. The driver provides support for SIR, MIR
and FIR (4Mbps) speeds.
diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c
index 7d23aa37590..b8d112348ba 100644
--- a/drivers/net/irda/irtty-sir.c
+++ b/drivers/net/irda/irtty-sir.c
@@ -626,7 +626,7 @@ static void __exit irtty_sir_cleanup(void)
{
int err;
- if ((err = tty_register_ldisc(N_IRDA, NULL))) {
+ if ((err = tty_unregister_ldisc(N_IRDA))) {
IRDA_ERROR("%s(), can't unregister line discipline (err = %d)\n",
__FUNCTION__, err);
}
diff --git a/drivers/net/irda/sir_kthread.c b/drivers/net/irda/sir_kthread.c
index 18cea109953..c65054364bc 100644
--- a/drivers/net/irda/sir_kthread.c
+++ b/drivers/net/irda/sir_kthread.c
@@ -135,8 +135,7 @@ static int irda_thread(void *startup)
remove_wait_queue(&irda_rq_queue.kick, &wait);
/* make swsusp happy with our thread */
- if (current->flags & PF_FREEZE)
- refrigerator(PF_FREEZE);
+ try_to_freeze();
run_irda_queue();
}
diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
index 66f488c1371..15f207323d9 100644
--- a/drivers/net/irda/stir4200.c
+++ b/drivers/net/irda/stir4200.c
@@ -763,7 +763,7 @@ static int stir_transmit_thread(void *arg)
{
#ifdef CONFIG_PM
/* if suspending, then power off and wait */
- if (unlikely(current->flags & PF_FREEZE)) {
+ if (unlikely(freezing(current))) {
if (stir->receiving)
receive_stop(stir);
else
@@ -771,7 +771,7 @@ static int stir_transmit_thread(void *arg)
write_reg(stir, REG_CTRL1, CTRL1_TXPWD|CTRL1_RXPWD);
- refrigerator(PF_FREEZE);
+ refrigerator();
if (change_speed(stir, stir->speed))
break;
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index 855f8b2cf13..55af32e9bf0 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -802,13 +802,14 @@ static void veth_tx_timeout(struct net_device *dev)
spin_lock_irqsave(&port->pending_gate, flags);
+ if (!port->pending_lpmask) {
+ spin_unlock_irqrestore(&port->pending_gate, flags);
+ return;
+ }
+
printk(KERN_WARNING "%s: Tx timeout! Resetting lp connections: %08x\n",
dev->name, port->pending_lpmask);
- /* If we've timed out the queue must be stopped, which should
- * only ever happen when there is a pending packet. */
- WARN_ON(! port->pending_lpmask);
-
for (i = 0; i < HVMAXARCHITECTEDLPS; i++) {
struct veth_lpar_connection *cnx = veth_cnx[i];
@@ -924,7 +925,7 @@ static int veth_transmit_to_one(struct sk_buff *skb, HvLpIndex rlp,
spin_lock_irqsave(&cnx->lock, flags);
- if (! cnx->state & VETH_STATE_READY)
+ if (! (cnx->state & VETH_STATE_READY))
goto drop;
if ((skb->len - 14) > VETH_MAX_MTU)
@@ -1023,6 +1024,8 @@ static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev)
lpmask = veth_transmit_to_many(skb, lpmask, dev);
+ dev->trans_start = jiffies;
+
if (! lpmask) {
dev_kfree_skb(skb);
} else {
@@ -1262,13 +1265,18 @@ static void veth_receive(struct veth_lpar_connection *cnx,
vlan = skb->data[9];
dev = veth_dev[vlan];
- if (! dev)
- /* Some earlier versions of the driver sent
- broadcasts down all connections, even to
- lpars that weren't on the relevant vlan.
- So ignore packets belonging to a vlan we're
- not on. */
+ if (! dev) {
+ /*
+ * Some earlier versions of the driver sent
+ * broadcasts down all connections, even to lpars
+ * that weren't on the relevant vlan. So ignore
+ * packets belonging to a vlan we're not on.
+ * We can also be here if we receive packets while
+ * the driver is going down, because then dev is NULL.
+ */
+ dev_kfree_skb_irq(skb);
continue;
+ }
port = (struct veth_port *)dev->priv;
dest = *((u64 *) skb->data) & 0xFFFFFFFFFFFF0000;
@@ -1381,18 +1389,25 @@ void __exit veth_module_cleanup(void)
{
int i;
- vio_unregister_driver(&veth_driver);
+ /* Stop the queues first to stop any new packets being sent. */
+ for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++)
+ if (veth_dev[i])
+ netif_stop_queue(veth_dev[i]);
+ /* Stop the connections before we unregister the driver. This
+ * ensures there's no skbs lying around holding the device open. */
for (i = 0; i < HVMAXARCHITECTEDLPS; ++i)
veth_stop_connection(i);
HvLpEvent_unregisterHandler(HvLpEvent_Type_VirtualLan);
/* Hypervisor callbacks may have scheduled more work while we
- * were destroying connections. Now that we've disconnected from
+ * were stoping connections. Now that we've disconnected from
* the hypervisor make sure everything's finished. */
flush_scheduled_work();
+ vio_unregister_driver(&veth_driver);
+
for (i = 0; i < HVMAXARCHITECTEDLPS; ++i)
veth_destroy_connection(i);
diff --git a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h
index 26c4f15f7fc..f8d3385c784 100644
--- a/drivers/net/ixgb/ixgb.h
+++ b/drivers/net/ixgb/ixgb.h
@@ -110,7 +110,7 @@ struct ixgb_adapter;
#define IXGB_TX_QUEUE_WAKE 16
/* How many Rx Buffers do we bundle into one write to the hardware ? */
-#define IXGB_RX_BUFFER_WRITE 16 /* Must be power of 2 */
+#define IXGB_RX_BUFFER_WRITE 4 /* Must be power of 2 */
/* only works for sizes that are powers of 2 */
#define IXGB_ROUNDUP(i, size) ((i) = (((i) + (size) - 1) & ~((size) - 1)))
diff --git a/drivers/net/ixgb/ixgb_ee.c b/drivers/net/ixgb/ixgb_ee.c
index 653e99f919c..3aae110c556 100644
--- a/drivers/net/ixgb/ixgb_ee.c
+++ b/drivers/net/ixgb/ixgb_ee.c
@@ -411,7 +411,7 @@ ixgb_write_eeprom(struct ixgb_hw *hw, uint16_t offset, uint16_t data)
ixgb_cleanup_eeprom(hw);
/* clear the init_ctrl_reg_1 to signify that the cache is invalidated */
- ee_map->init_ctrl_reg_1 = EEPROM_ICW1_SIGNATURE_CLEAR;
+ ee_map->init_ctrl_reg_1 = le16_to_cpu(EEPROM_ICW1_SIGNATURE_CLEAR);
return;
}
@@ -483,7 +483,7 @@ ixgb_get_eeprom_data(struct ixgb_hw *hw)
DEBUGOUT("ixgb_ee: Checksum invalid.\n");
/* clear the init_ctrl_reg_1 to signify that the cache is
* invalidated */
- ee_map->init_ctrl_reg_1 = EEPROM_ICW1_SIGNATURE_CLEAR;
+ ee_map->init_ctrl_reg_1 = le16_to_cpu(EEPROM_ICW1_SIGNATURE_CLEAR);
return (FALSE);
}
@@ -579,7 +579,7 @@ ixgb_get_ee_compatibility(struct ixgb_hw *hw)
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return(ee_map->compatibility);
+ return (le16_to_cpu(ee_map->compatibility));
return(0);
}
@@ -616,7 +616,7 @@ ixgb_get_ee_init_ctrl_reg_1(struct ixgb_hw *hw)
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return(ee_map->init_ctrl_reg_1);
+ return (le16_to_cpu(ee_map->init_ctrl_reg_1));
return(0);
}
@@ -635,7 +635,7 @@ ixgb_get_ee_init_ctrl_reg_2(struct ixgb_hw *hw)
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return(ee_map->init_ctrl_reg_2);
+ return (le16_to_cpu(ee_map->init_ctrl_reg_2));
return(0);
}
@@ -654,7 +654,7 @@ ixgb_get_ee_subsystem_id(struct ixgb_hw *hw)
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return(ee_map->subsystem_id);
+ return (le16_to_cpu(ee_map->subsystem_id));
return(0);
}
@@ -673,7 +673,7 @@ ixgb_get_ee_subvendor_id(struct ixgb_hw *hw)
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return(ee_map->subvendor_id);
+ return (le16_to_cpu(ee_map->subvendor_id));
return(0);
}
@@ -692,7 +692,7 @@ ixgb_get_ee_device_id(struct ixgb_hw *hw)
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return(ee_map->device_id);
+ return (le16_to_cpu(ee_map->device_id));
return(0);
}
@@ -711,7 +711,7 @@ ixgb_get_ee_vendor_id(struct ixgb_hw *hw)
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return(ee_map->vendor_id);
+ return (le16_to_cpu(ee_map->vendor_id));
return(0);
}
@@ -730,7 +730,7 @@ ixgb_get_ee_swdpins_reg(struct ixgb_hw *hw)
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return(ee_map->swdpins_reg);
+ return (le16_to_cpu(ee_map->swdpins_reg));
return(0);
}
@@ -749,7 +749,7 @@ ixgb_get_ee_d3_power(struct ixgb_hw *hw)
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return(ee_map->d3_power);
+ return (le16_to_cpu(ee_map->d3_power));
return(0);
}
@@ -768,7 +768,7 @@ ixgb_get_ee_d0_power(struct ixgb_hw *hw)
struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
if(ixgb_check_and_get_eeprom_data(hw) == TRUE)
- return(ee_map->d0_power);
+ return (le16_to_cpu(ee_map->d0_power));
return(0);
}
diff --git a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
index aea10e8aaa7..3fa113854ee 100644
--- a/drivers/net/ixgb/ixgb_ethtool.c
+++ b/drivers/net/ixgb/ixgb_ethtool.c
@@ -252,7 +252,9 @@ ixgb_get_regs(struct net_device *netdev,
uint32_t *reg_start = reg;
uint8_t i;
- regs->version = (adapter->hw.device_id << 16) | adapter->hw.subsystem_id;
+ /* the 1 (one) below indicates an attempt at versioning, if the
+ * interface in ethtool or the driver this 1 should be incremented */
+ regs->version = (1<<24) | hw->revision_id << 16 | hw->device_id;
/* General Registers */
*reg++ = IXGB_READ_REG(hw, CTRL0); /* 0 */
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index a6af9d9e340..097b90ccf57 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -47,7 +47,8 @@ char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver";
#else
#define DRIVERNAPI "-NAPI"
#endif
-#define DRV_VERSION "1.0.90-k2"DRIVERNAPI
+
+#define DRV_VERSION "1.0.95-k2"DRIVERNAPI
char ixgb_driver_version[] = DRV_VERSION;
char ixgb_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
@@ -104,6 +105,7 @@ static int ixgb_change_mtu(struct net_device *netdev, int new_mtu);
static int ixgb_set_mac(struct net_device *netdev, void *p);
static irqreturn_t ixgb_intr(int irq, void *data, struct pt_regs *regs);
static boolean_t ixgb_clean_tx_irq(struct ixgb_adapter *adapter);
+
#ifdef CONFIG_IXGB_NAPI
static int ixgb_clean(struct net_device *netdev, int *budget);
static boolean_t ixgb_clean_rx_irq(struct ixgb_adapter *adapter,
@@ -121,33 +123,20 @@ static void ixgb_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid);
static void ixgb_vlan_rx_kill_vid(struct net_device *netdev, uint16_t vid);
static void ixgb_restore_vlan(struct ixgb_adapter *adapter);
-static int ixgb_notify_reboot(struct notifier_block *, unsigned long event,
- void *ptr);
-static int ixgb_suspend(struct pci_dev *pdev, uint32_t state);
-
#ifdef CONFIG_NET_POLL_CONTROLLER
/* for netdump / net console */
static void ixgb_netpoll(struct net_device *dev);
#endif
-struct notifier_block ixgb_notifier_reboot = {
- .notifier_call = ixgb_notify_reboot,
- .next = NULL,
- .priority = 0
-};
-
/* Exported from other modules */
extern void ixgb_check_options(struct ixgb_adapter *adapter);
static struct pci_driver ixgb_driver = {
- .name = ixgb_driver_name,
+ .name = ixgb_driver_name,
.id_table = ixgb_pci_tbl,
- .probe = ixgb_probe,
- .remove = __devexit_p(ixgb_remove),
- /* Power Managment Hooks */
- .suspend = NULL,
- .resume = NULL
+ .probe = ixgb_probe,
+ .remove = __devexit_p(ixgb_remove),
};
MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
@@ -171,17 +160,12 @@ MODULE_VERSION(DRV_VERSION);
static int __init
ixgb_init_module(void)
{
- int ret;
printk(KERN_INFO "%s - version %s\n",
ixgb_driver_string, ixgb_driver_version);
printk(KERN_INFO "%s\n", ixgb_copyright);
- ret = pci_module_init(&ixgb_driver);
- if(ret >= 0) {
- register_reboot_notifier(&ixgb_notifier_reboot);
- }
- return ret;
+ return pci_module_init(&ixgb_driver);
}
module_init(ixgb_init_module);
@@ -196,7 +180,6 @@ module_init(ixgb_init_module);
static void __exit
ixgb_exit_module(void)
{
- unregister_reboot_notifier(&ixgb_notifier_reboot);
pci_unregister_driver(&ixgb_driver);
}
@@ -226,8 +209,8 @@ ixgb_irq_enable(struct ixgb_adapter *adapter)
{
if(atomic_dec_and_test(&adapter->irq_sem)) {
IXGB_WRITE_REG(&adapter->hw, IMS,
- IXGB_INT_RXT0 | IXGB_INT_RXDMT0 | IXGB_INT_TXDW |
- IXGB_INT_RXO | IXGB_INT_LSC);
+ IXGB_INT_RXT0 | IXGB_INT_RXDMT0 | IXGB_INT_TXDW |
+ IXGB_INT_LSC);
IXGB_WRITE_FLUSH(&adapter->hw);
}
}
@@ -1211,10 +1194,10 @@ ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
| IXGB_CONTEXT_DESC_CMD_TSE
| IXGB_CONTEXT_DESC_CMD_IP
| IXGB_CONTEXT_DESC_CMD_TCP
- | IXGB_CONTEXT_DESC_CMD_RS
| IXGB_CONTEXT_DESC_CMD_IDE
| (skb->len - (hdr_len)));
+
if(++i == adapter->tx_ring.count) i = 0;
adapter->tx_ring.next_to_use = i;
@@ -1249,8 +1232,7 @@ ixgb_tx_csum(struct ixgb_adapter *adapter, struct sk_buff *skb)
context_desc->mss = 0;
context_desc->cmd_type_len =
cpu_to_le32(IXGB_CONTEXT_DESC_TYPE
- | IXGB_TX_DESC_CMD_RS
- | IXGB_TX_DESC_CMD_IDE);
+ | IXGB_TX_DESC_CMD_IDE);
if(++i == adapter->tx_ring.count) i = 0;
adapter->tx_ring.next_to_use = i;
@@ -1275,6 +1257,7 @@ ixgb_tx_map(struct ixgb_adapter *adapter, struct sk_buff *skb,
unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
unsigned int f;
+
len -= skb->data_len;
i = tx_ring->next_to_use;
@@ -1528,14 +1511,33 @@ ixgb_change_mtu(struct net_device *netdev, int new_mtu)
void
ixgb_update_stats(struct ixgb_adapter *adapter)
{
+ struct net_device *netdev = adapter->netdev;
+
+ if((netdev->flags & IFF_PROMISC) || (netdev->flags & IFF_ALLMULTI) ||
+ (netdev->mc_count > IXGB_MAX_NUM_MULTICAST_ADDRESSES)) {
+ u64 multi = IXGB_READ_REG(&adapter->hw, MPRCL);
+ u32 bcast_l = IXGB_READ_REG(&adapter->hw, BPRCL);
+ u32 bcast_h = IXGB_READ_REG(&adapter->hw, BPRCH);
+ u64 bcast = ((u64)bcast_h << 32) | bcast_l;
+
+ multi |= ((u64)IXGB_READ_REG(&adapter->hw, MPRCH) << 32);
+ /* fix up multicast stats by removing broadcasts */
+ multi -= bcast;
+
+ adapter->stats.mprcl += (multi & 0xFFFFFFFF);
+ adapter->stats.mprch += (multi >> 32);
+ adapter->stats.bprcl += bcast_l;
+ adapter->stats.bprch += bcast_h;
+ } else {
+ adapter->stats.mprcl += IXGB_READ_REG(&adapter->hw, MPRCL);
+ adapter->stats.mprch += IXGB_READ_REG(&adapter->hw, MPRCH);
+ adapter->stats.bprcl += IXGB_READ_REG(&adapter->hw, BPRCL);
+ adapter->stats.bprch += IXGB_READ_REG(&adapter->hw, BPRCH);
+ }
adapter->stats.tprl += IXGB_READ_REG(&adapter->hw, TPRL);
adapter->stats.tprh += IXGB_READ_REG(&adapter->hw, TPRH);
adapter->stats.gprcl += IXGB_READ_REG(&adapter->hw, GPRCL);
adapter->stats.gprch += IXGB_READ_REG(&adapter->hw, GPRCH);
- adapter->stats.bprcl += IXGB_READ_REG(&adapter->hw, BPRCL);
- adapter->stats.bprch += IXGB_READ_REG(&adapter->hw, BPRCH);
- adapter->stats.mprcl += IXGB_READ_REG(&adapter->hw, MPRCL);
- adapter->stats.mprch += IXGB_READ_REG(&adapter->hw, MPRCH);
adapter->stats.uprcl += IXGB_READ_REG(&adapter->hw, UPRCL);
adapter->stats.uprch += IXGB_READ_REG(&adapter->hw, UPRCH);
adapter->stats.vprcl += IXGB_READ_REG(&adapter->hw, VPRCL);
@@ -1825,7 +1827,6 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
struct pci_dev *pdev = adapter->pdev;
struct ixgb_rx_desc *rx_desc, *next_rxd;
struct ixgb_buffer *buffer_info, *next_buffer, *next2_buffer;
- struct sk_buff *skb, *next_skb;
uint32_t length;
unsigned int i, j;
boolean_t cleaned = FALSE;
@@ -1835,6 +1836,8 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
buffer_info = &rx_ring->buffer_info[i];
while(rx_desc->status & IXGB_RX_DESC_STATUS_DD) {
+ struct sk_buff *skb, *next_skb;
+ u8 status;
#ifdef CONFIG_IXGB_NAPI
if(*work_done >= work_to_do)
@@ -1842,7 +1845,9 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
(*work_done)++;
#endif
+ status = rx_desc->status;
skb = buffer_info->skb;
+
prefetch(skb->data);
if(++i == rx_ring->count) i = 0;
@@ -1857,7 +1862,6 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
next_skb = next_buffer->skb;
prefetch(next_skb);
-
cleaned = TRUE;
pci_unmap_single(pdev,
@@ -1867,7 +1871,7 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
length = le16_to_cpu(rx_desc->length);
- if(unlikely(!(rx_desc->status & IXGB_RX_DESC_STATUS_EOP))) {
+ if(unlikely(!(status & IXGB_RX_DESC_STATUS_EOP))) {
/* All receives must fit into a single buffer */
@@ -1875,12 +1879,7 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
"length<%x>\n", length);
dev_kfree_skb_irq(skb);
- rx_desc->status = 0;
- buffer_info->skb = NULL;
-
- rx_desc = next_rxd;
- buffer_info = next_buffer;
- continue;
+ goto rxdesc_done;
}
if (unlikely(rx_desc->errors
@@ -1889,12 +1888,7 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
IXGB_RX_DESC_ERRORS_RXE))) {
dev_kfree_skb_irq(skb);
- rx_desc->status = 0;
- buffer_info->skb = NULL;
-
- rx_desc = next_rxd;
- buffer_info = next_buffer;
- continue;
+ goto rxdesc_done;
}
/* Good Receive */
@@ -1905,7 +1899,7 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
skb->protocol = eth_type_trans(skb, netdev);
#ifdef CONFIG_IXGB_NAPI
- if(adapter->vlgrp && (rx_desc->status & IXGB_RX_DESC_STATUS_VP)) {
+ if(adapter->vlgrp && (status & IXGB_RX_DESC_STATUS_VP)) {
vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
le16_to_cpu(rx_desc->special) &
IXGB_RX_DESC_SPECIAL_VLAN_MASK);
@@ -1913,7 +1907,7 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
netif_receive_skb(skb);
}
#else /* CONFIG_IXGB_NAPI */
- if(adapter->vlgrp && (rx_desc->status & IXGB_RX_DESC_STATUS_VP)) {
+ if(adapter->vlgrp && (status & IXGB_RX_DESC_STATUS_VP)) {
vlan_hwaccel_rx(skb, adapter->vlgrp,
le16_to_cpu(rx_desc->special) &
IXGB_RX_DESC_SPECIAL_VLAN_MASK);
@@ -1923,9 +1917,12 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter)
#endif /* CONFIG_IXGB_NAPI */
netdev->last_rx = jiffies;
+rxdesc_done:
+ /* clean up descriptor, might be written over by hw */
rx_desc->status = 0;
buffer_info->skb = NULL;
+ /* use prefetched values */
rx_desc = next_rxd;
buffer_info = next_buffer;
}
@@ -1961,8 +1958,8 @@ ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter)
num_group_tail_writes = IXGB_RX_BUFFER_WRITE;
- /* leave one descriptor unused */
- while(--cleancount > 0) {
+ /* leave three descriptors unused */
+ while(--cleancount > 2) {
rx_desc = IXGB_RX_DESC(*rx_ring, i);
skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);
@@ -1989,6 +1986,10 @@ ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter)
PCI_DMA_FROMDEVICE);
rx_desc->buff_addr = cpu_to_le64(buffer_info->dma);
+ /* guarantee DD bit not set now before h/w gets descriptor
+ * this is the rest of the workaround for h/w double
+ * writeback. */
+ rx_desc->status = 0;
if((i & ~(num_group_tail_writes- 1)) == i) {
/* Force memory writes to complete before letting h/w
@@ -2101,54 +2102,6 @@ ixgb_restore_vlan(struct ixgb_adapter *adapter)
}
}
-/**
- * ixgb_notify_reboot - handles OS notification of reboot event.
- * @param nb notifier block, unused
- * @param event Event being passed to driver to act upon
- * @param p A pointer to our net device
- **/
-static int
-ixgb_notify_reboot(struct notifier_block *nb, unsigned long event, void *p)
-{
- struct pci_dev *pdev = NULL;
-
- switch(event) {
- case SYS_DOWN:
- case SYS_HALT:
- case SYS_POWER_OFF:
- while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev))) {
- if (pci_dev_driver(pdev) == &ixgb_driver)
- ixgb_suspend(pdev, 3);
- }
- }
- return NOTIFY_DONE;
-}
-
-/**
- * ixgb_suspend - driver suspend function called from notify.
- * @param pdev pci driver structure used for passing to
- * @param state power state to enter
- **/
-static int
-ixgb_suspend(struct pci_dev *pdev, uint32_t state)
-{
- struct net_device *netdev = pci_get_drvdata(pdev);
- struct ixgb_adapter *adapter = netdev->priv;
-
- netif_device_detach(netdev);
-
- if(netif_running(netdev))
- ixgb_down(adapter, TRUE);
-
- pci_save_state(pdev);
-
- state = (state > 0) ? 3 : 0;
- pci_set_power_state(pdev, state);
- msec_delay(200);
-
- return 0;
-}
-
#ifdef CONFIG_NET_POLL_CONTROLLER
/*
* Polling 'interrupt' - used by things like netconsole to send skbs
@@ -2159,6 +2112,7 @@ ixgb_suspend(struct pci_dev *pdev, uint32_t state)
static void ixgb_netpoll(struct net_device *dev)
{
struct ixgb_adapter *adapter = dev->priv;
+
disable_irq(adapter->pdev->irq);
ixgb_intr(adapter->pdev->irq, dev, NULL);
enable_irq(adapter->pdev->irq);
diff --git a/drivers/net/ixgb/ixgb_osdep.h b/drivers/net/ixgb/ixgb_osdep.h
index 9eba9289190..dba20481ee8 100644
--- a/drivers/net/ixgb/ixgb_osdep.h
+++ b/drivers/net/ixgb/ixgb_osdep.h
@@ -45,8 +45,7 @@
/* Don't mdelay in interrupt context! */ \
BUG(); \
} else { \
- set_current_state(TASK_UNINTERRUPTIBLE); \
- schedule_timeout((x * HZ)/1000 + 2); \
+ msleep(x); \
} } while(0)
#endif
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index 223bdadd4c0..babb59e146e 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -2433,9 +2433,9 @@ static void __set_rx_mode(struct net_device *dev)
rx_mode = RxFilterEnable | AcceptBroadcast
| AcceptMulticast | AcceptMyPhys;
for (i = 0; i < 64; i += 2) {
- writew(HASH_TABLE + i, ioaddr + RxFilterAddr);
- writew((mc_filter[i+1]<<8) + mc_filter[i],
- ioaddr + RxFilterData);
+ writel(HASH_TABLE + i, ioaddr + RxFilterAddr);
+ writel((mc_filter[i + 1] << 8) + mc_filter[i],
+ ioaddr + RxFilterData);
}
}
writel(rx_mode, ioaddr + RxFilterAddr);
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index 2fcc181a862..c336b46bd33 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -1,4 +1,4 @@
-#define _VERSION "0.20"
+#define VERSION "0.22"
/* ns83820.c by Benjamin LaHaise with contributions.
*
* Questions/comments/discussion to linux-ns83820@kvack.org.
@@ -63,9 +63,11 @@
* - fix missed txok introduced during performance
* tuning
* 0.20 - fix stupid RFEN thinko. i am such a smurf.
- *
* 20040828 0.21 - add hardware vlan accleration
* by Neil Horman <nhorman@redhat.com>
+ * 20050406 0.22 - improved DAC ifdefs from Andi Kleen
+ * - removal of dead code from Adrian Bunk
+ * - fix half duplex collision behaviour
* Driver Overview
* ===============
*
@@ -129,18 +131,6 @@ static int lnksts = 0; /* CFG_LNKSTS bit polarity */
#undef Dprintk
#define Dprintk dprintk
-#if defined(CONFIG_HIGHMEM64G) || defined(__ia64__)
-#define USE_64BIT_ADDR "+"
-#endif
-
-#if defined(USE_64BIT_ADDR)
-#define VERSION _VERSION USE_64BIT_ADDR
-#define TRY_DAC 1
-#else
-#define VERSION _VERSION
-#define TRY_DAC 0
-#endif
-
/* tunables */
#define RX_BUF_SIZE 1500 /* 8192 */
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
@@ -386,22 +376,16 @@ static int lnksts = 0; /* CFG_LNKSTS bit polarity */
#define LINK_DOWN 0x02
#define LINK_UP 0x04
-#ifdef USE_64BIT_ADDR
-#define HW_ADDR_LEN 8
+#define HW_ADDR_LEN sizeof(dma_addr_t)
#define desc_addr_set(desc, addr) \
do { \
- u64 __addr = (addr); \
- (desc)[0] = cpu_to_le32(__addr); \
- (desc)[1] = cpu_to_le32(__addr >> 32); \
+ ((desc)[0] = cpu_to_le32(addr)); \
+ if (HW_ADDR_LEN == 8) \
+ (desc)[1] = cpu_to_le32(((u64)addr) >> 32); \
} while(0)
#define desc_addr_get(desc) \
- (((u64)le32_to_cpu((desc)[1]) << 32) \
- | le32_to_cpu((desc)[0]))
-#else
-#define HW_ADDR_LEN 4
-#define desc_addr_set(desc, addr) ((desc)[0] = cpu_to_le32(addr))
-#define desc_addr_get(desc) (le32_to_cpu((desc)[0]))
-#endif
+ (le32_to_cpu((desc)[0]) | \
+ (HW_ADDR_LEN == 8 ? ((dma_addr_t)le32_to_cpu((desc)[1]))<<32 : 0))
#define DESC_LINK 0
#define DESC_BUFPTR (DESC_LINK + HW_ADDR_LEN/4)
@@ -727,11 +711,23 @@ static void fastcall phy_intr(struct net_device *ndev)
speed = ((cfg / CFG_SPDSTS0) & 3);
fullduplex = (cfg & CFG_DUPSTS);
- if (fullduplex)
+ if (fullduplex) {
new_cfg |= CFG_SB;
+ writel(readl(dev->base + TXCFG)
+ | TXCFG_CSI | TXCFG_HBI,
+ dev->base + TXCFG);
+ writel(readl(dev->base + RXCFG) | RXCFG_RX_FD,
+ dev->base + RXCFG);
+ } else {
+ writel(readl(dev->base + TXCFG)
+ & ~(TXCFG_CSI | TXCFG_HBI),
+ dev->base + TXCFG);
+ writel(readl(dev->base + RXCFG) & ~(RXCFG_RX_FD),
+ dev->base + RXCFG);
+ }
if ((cfg & CFG_LNKSTS) &&
- ((new_cfg ^ dev->CFG_cache) & CFG_MODE_1000)) {
+ ((new_cfg ^ dev->CFG_cache) != 0)) {
writel(new_cfg, dev->base + CFG);
dev->CFG_cache = new_cfg;
}
@@ -1189,7 +1185,6 @@ again:
for (;;) {
volatile u32 *desc = dev->tx_descs + (free_idx * DESC_SIZE);
- u32 residue = 0;
dprintk("frag[%3u]: %4u @ 0x%08Lx\n", free_idx, len,
(unsigned long long)buf);
@@ -1199,17 +1194,11 @@ again:
desc_addr_set(desc + DESC_BUFPTR, buf);
desc[DESC_EXTSTS] = cpu_to_le32(extsts);
- cmdsts = ((nr_frags|residue) ? CMDSTS_MORE : do_intr ? CMDSTS_INTR : 0);
+ cmdsts = ((nr_frags) ? CMDSTS_MORE : do_intr ? CMDSTS_INTR : 0);
cmdsts |= (desc == first_desc) ? 0 : CMDSTS_OWN;
cmdsts |= len;
desc[DESC_CMDSTS] = cpu_to_le32(cmdsts);
- if (residue) {
- buf += len;
- len = residue;
- continue;
- }
-
if (!nr_frags)
break;
@@ -1841,7 +1830,8 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
int using_dac = 0;
/* See if we can set the dma mask early on; failure is fatal. */
- if (TRY_DAC && !pci_set_dma_mask(pci_dev, 0xffffffffffffffffULL)) {
+ if (sizeof(dma_addr_t) == 8 &&
+ !pci_set_dma_mask(pci_dev, 0xffffffffffffffffULL)) {
using_dac = 1;
} else if (!pci_set_dma_mask(pci_dev, 0xffffffff)) {
using_dac = 0;
@@ -1972,9 +1962,8 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
/* When compiled with 64 bit addressing, we must always enable
* the 64 bit descriptor format.
*/
-#ifdef USE_64BIT_ADDR
- dev->CFG_cache |= CFG_M64ADDR;
-#endif
+ if (sizeof(dma_addr_t) == 8)
+ dev->CFG_cache |= CFG_M64ADDR;
if (using_dac)
dev->CFG_cache |= CFG_T64ADDR;
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index 41e51711480..c6e8b25f968 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -1274,6 +1274,9 @@ static int el3_close(struct net_device *dev)
spin_lock_irqsave(&lp->window_lock, flags);
update_stats(dev);
spin_unlock_irqrestore(&lp->window_lock, flags);
+
+ /* force interrupts off */
+ outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
}
link->open--;
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index b0126304ca0..181b6ed5500 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -1537,20 +1537,20 @@ static void shmem_get_8390_hdr(struct net_device *dev,
static void shmem_block_input(struct net_device *dev, int count,
struct sk_buff *skb, int ring_offset)
{
- void __iomem *xfer_start = ei_status.mem + (TX_PAGES<<8)
- + ring_offset
+ void __iomem *base = ei_status.mem;
+ unsigned long offset = (TX_PAGES<<8) + ring_offset
- (ei_status.rx_start_page << 8);
char *buf = skb->data;
- if (xfer_start + count > (void __iomem *)ei_status.rmem_end) {
+ if (offset + count > ei_status.priv) {
/* We must wrap the input move. */
- int semi_count = (void __iomem *)ei_status.rmem_end - xfer_start;
- copyin(buf, xfer_start, semi_count);
+ int semi_count = ei_status.priv - offset;
+ copyin(buf, base + offset, semi_count);
buf += semi_count;
- xfer_start = ei_status.mem + (TX_PAGES<<8);
+ offset = TX_PAGES<<8;
count -= semi_count;
}
- copyin(buf, xfer_start, count);
+ copyin(buf, base + offset, count);
}
/*====================================================================*/
@@ -1611,8 +1611,9 @@ static int setup_shmem_window(dev_link_t *link, int start_pg,
}
ei_status.mem = info->base + offset;
+ ei_status.priv = req.Size;
dev->mem_start = (u_long)ei_status.mem;
- dev->mem_end = ei_status.rmem_end = (u_long)info->base + req.Size;
+ dev->mem_end = dev->mem_start + req.Size;
ei_status.tx_start_page = start_pg;
ei_status.rx_start_page = start_pg + TX_PAGES;
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index 17947e6c879..13f11487696 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -22,8 +22,8 @@
*************************************************************************/
#define DRV_NAME "pcnet32"
-#define DRV_VERSION "1.30i"
-#define DRV_RELDATE "06.28.2004"
+#define DRV_VERSION "1.30j"
+#define DRV_RELDATE "29.04.2005"
#define PFX DRV_NAME ": "
static const char *version =
@@ -256,6 +256,7 @@ static int homepna[MAX_UNITS];
* homepna for selecting HomePNA mode for PCNet/Home 79C978.
* v1.30h 24 Jun 2004 Don Fry correctly select auto, speed, duplex in bcr32.
* v1.30i 28 Jun 2004 Don Fry change to use module_param.
+ * v1.30j 29 Apr 2005 Don Fry fix skb/map leak with loopback test.
*/
@@ -395,6 +396,7 @@ static void pcnet32_led_blink_callback(struct net_device *dev);
static int pcnet32_get_regs_len(struct net_device *dev);
static void pcnet32_get_regs(struct net_device *dev, struct ethtool_regs *regs,
void *ptr);
+static void pcnet32_purge_tx_ring(struct net_device *dev);
enum pci_flags_bit {
PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
@@ -785,6 +787,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t *data1)
}
clean_up:
+ pcnet32_purge_tx_ring(dev);
x = a->read_csr(ioaddr, 15) & 0xFFFF;
a->write_csr(ioaddr, 15, (x & ~0x0044)); /* reset bits 6 and 2 */
diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c
index 33b9d79b1aa..5e48b9ab304 100644
--- a/drivers/net/ppp_async.c
+++ b/drivers/net/ppp_async.c
@@ -1025,7 +1025,7 @@ static void async_lcp_peek(struct asyncppp *ap, unsigned char *data,
static void __exit ppp_async_cleanup(void)
{
- if (tty_register_ldisc(N_PPP, NULL) != 0)
+ if (tty_unregister_ldisc(N_PPP) != 0)
printk(KERN_ERR "failed to unregister PPP line discipline\n");
}
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 3b377f6cd4a..ab726ab4379 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -273,7 +273,7 @@ static int ppp_connect_channel(struct channel *pch, int unit);
static int ppp_disconnect_channel(struct channel *pch);
static void ppp_destroy_channel(struct channel *pch);
-static struct class_simple *ppp_class;
+static struct class *ppp_class;
/* Translates a PPP protocol number to a NP index (NP == network protocol) */
static inline int proto_to_npindex(int proto)
@@ -858,12 +858,12 @@ static int __init ppp_init(void)
printk(KERN_INFO "PPP generic driver version " PPP_VERSION "\n");
err = register_chrdev(PPP_MAJOR, "ppp", &ppp_device_fops);
if (!err) {
- ppp_class = class_simple_create(THIS_MODULE, "ppp");
+ ppp_class = class_create(THIS_MODULE, "ppp");
if (IS_ERR(ppp_class)) {
err = PTR_ERR(ppp_class);
goto out_chrdev;
}
- class_simple_device_add(ppp_class, MKDEV(PPP_MAJOR, 0), NULL, "ppp");
+ class_device_create(ppp_class, MKDEV(PPP_MAJOR, 0), NULL, "ppp");
err = devfs_mk_cdev(MKDEV(PPP_MAJOR, 0),
S_IFCHR|S_IRUSR|S_IWUSR, "ppp");
if (err)
@@ -876,8 +876,8 @@ out:
return err;
out_class:
- class_simple_device_remove(MKDEV(PPP_MAJOR,0));
- class_simple_destroy(ppp_class);
+ class_device_destroy(ppp_class, MKDEV(PPP_MAJOR,0));
+ class_destroy(ppp_class);
out_chrdev:
unregister_chrdev(PPP_MAJOR, "ppp");
goto out;
@@ -1217,36 +1217,43 @@ ppp_push(struct ppp *ppp)
*/
static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
{
- int nch, len, fragsize;
+ int len, fragsize;
int i, bits, hdrlen, mtu;
- int flen, fnb;
+ int flen;
+ int navail, nfree;
+ int nbigger;
unsigned char *p, *q;
struct list_head *list;
struct channel *pch;
struct sk_buff *frag;
struct ppp_channel *chan;
- nch = 0;
+ nfree = 0; /* # channels which have no packet already queued */
+ navail = 0; /* total # of usable channels (not deregistered) */
hdrlen = (ppp->flags & SC_MP_XSHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN;
+ i = 0;
list = &ppp->channels;
while ((list = list->next) != &ppp->channels) {
pch = list_entry(list, struct channel, clist);
- nch += pch->avail = (skb_queue_len(&pch->file.xq) == 0);
- /*
- * If a channel hasn't had a fragment yet, it has to get
- * one before we send any fragments on later channels.
- * If it can't take a fragment now, don't give any
- * to subsequent channels.
- */
- if (!pch->had_frag && !pch->avail) {
- while ((list = list->next) != &ppp->channels) {
- pch = list_entry(list, struct channel, clist);
- pch->avail = 0;
+ navail += pch->avail = (pch->chan != NULL);
+ if (pch->avail) {
+ if (skb_queue_len(&pch->file.xq) == 0
+ || !pch->had_frag) {
+ pch->avail = 2;
+ ++nfree;
}
- break;
+ if (!pch->had_frag && i < ppp->nxchan)
+ ppp->nxchan = i;
}
+ ++i;
}
- if (nch == 0)
+
+ /*
+ * Don't start sending this packet unless at least half of
+ * the channels are free. This gives much better TCP
+ * performance if we have a lot of channels.
+ */
+ if (nfree == 0 || nfree < navail / 2)
return 0; /* can't take now, leave it in xmit_pending */
/* Do protocol field compression (XXX this should be optional) */
@@ -1257,14 +1264,19 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
--len;
}
- /* decide on fragment size */
+ /*
+ * Decide on fragment size.
+ * We create a fragment for each free channel regardless of
+ * how small they are (i.e. even 0 length) in order to minimize
+ * the time that it will take to detect when a channel drops
+ * a fragment.
+ */
fragsize = len;
- if (nch > 1) {
- int maxch = ROUNDUP(len, MIN_FRAG_SIZE);
- if (nch > maxch)
- nch = maxch;
- fragsize = ROUNDUP(fragsize, nch);
- }
+ if (nfree > 1)
+ fragsize = ROUNDUP(fragsize, nfree);
+ /* nbigger channels get fragsize bytes, the rest get fragsize-1,
+ except if nbigger==0, then they all get fragsize. */
+ nbigger = len % nfree;
/* skip to the channel after the one we last used
and start at that one */
@@ -1278,7 +1290,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
/* create a fragment for each channel */
bits = B;
- do {
+ while (nfree > 0 || len > 0) {
list = list->next;
if (list == &ppp->channels) {
i = 0;
@@ -1289,61 +1301,92 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
if (!pch->avail)
continue;
+ /*
+ * Skip this channel if it has a fragment pending already and
+ * we haven't given a fragment to all of the free channels.
+ */
+ if (pch->avail == 1) {
+ if (nfree > 0)
+ continue;
+ } else {
+ --nfree;
+ pch->avail = 1;
+ }
+
/* check the channel's mtu and whether it is still attached. */
spin_lock_bh(&pch->downl);
- if (pch->chan == 0 || (mtu = pch->chan->mtu) < hdrlen) {
- /* can't use this channel */
+ if (pch->chan == NULL) {
+ /* can't use this channel, it's being deregistered */
spin_unlock_bh(&pch->downl);
pch->avail = 0;
- if (--nch == 0)
+ if (--navail == 0)
break;
continue;
}
/*
- * We have to create multiple fragments for this channel
- * if fragsize is greater than the channel's mtu.
+ * Create a fragment for this channel of
+ * min(max(mtu+2-hdrlen, 4), fragsize, len) bytes.
+ * If mtu+2-hdrlen < 4, that is a ridiculously small
+ * MTU, so we use mtu = 2 + hdrlen.
*/
if (fragsize > len)
fragsize = len;
- for (flen = fragsize; flen > 0; flen -= fnb) {
- fnb = flen;
- if (fnb > mtu + 2 - hdrlen)
- fnb = mtu + 2 - hdrlen;
- if (fnb >= len)
- bits |= E;
- frag = alloc_skb(fnb + hdrlen, GFP_ATOMIC);
- if (frag == 0)
- goto noskb;
- q = skb_put(frag, fnb + hdrlen);
- /* make the MP header */
- q[0] = PPP_MP >> 8;
- q[1] = PPP_MP;
- if (ppp->flags & SC_MP_XSHORTSEQ) {
- q[2] = bits + ((ppp->nxseq >> 8) & 0xf);
- q[3] = ppp->nxseq;
- } else {
- q[2] = bits;
- q[3] = ppp->nxseq >> 16;
- q[4] = ppp->nxseq >> 8;
- q[5] = ppp->nxseq;
- }
-
- /* copy the data in */
- memcpy(q + hdrlen, p, fnb);
-
- /* try to send it down the channel */
- chan = pch->chan;
- if (!chan->ops->start_xmit(chan, frag))
- skb_queue_tail(&pch->file.xq, frag);
- pch->had_frag = 1;
- p += fnb;
- len -= fnb;
- ++ppp->nxseq;
- bits = 0;
+ flen = fragsize;
+ mtu = pch->chan->mtu + 2 - hdrlen;
+ if (mtu < 4)
+ mtu = 4;
+ if (flen > mtu)
+ flen = mtu;
+ if (flen == len && nfree == 0)
+ bits |= E;
+ frag = alloc_skb(flen + hdrlen + (flen == 0), GFP_ATOMIC);
+ if (frag == 0)
+ goto noskb;
+ q = skb_put(frag, flen + hdrlen);
+
+ /* make the MP header */
+ q[0] = PPP_MP >> 8;
+ q[1] = PPP_MP;
+ if (ppp->flags & SC_MP_XSHORTSEQ) {
+ q[2] = bits + ((ppp->nxseq >> 8) & 0xf);
+ q[3] = ppp->nxseq;
+ } else {
+ q[2] = bits;
+ q[3] = ppp->nxseq >> 16;
+ q[4] = ppp->nxseq >> 8;
+ q[5] = ppp->nxseq;
}
+
+ /*
+ * Copy the data in.
+ * Unfortunately there is a bug in older versions of
+ * the Linux PPP multilink reconstruction code where it
+ * drops 0-length fragments. Therefore we make sure the
+ * fragment has at least one byte of data. Any bytes
+ * we add in this situation will end up as padding on the
+ * end of the reconstructed packet.
+ */
+ if (flen == 0)
+ *skb_put(frag, 1) = 0;
+ else
+ memcpy(q + hdrlen, p, flen);
+
+ /* try to send it down the channel */
+ chan = pch->chan;
+ if (skb_queue_len(&pch->file.xq)
+ || !chan->ops->start_xmit(chan, frag))
+ skb_queue_tail(&pch->file.xq, frag);
+ pch->had_frag = 1;
+ p += flen;
+ len -= flen;
+ ++ppp->nxseq;
+ bits = 0;
spin_unlock_bh(&pch->downl);
- } while (len > 0);
+
+ if (--nbigger == 0 && fragsize > 0)
+ --fragsize;
+ }
ppp->nxchan = i;
return 1;
@@ -1422,7 +1465,7 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb)
kfree_skb(skb);
return;
}
-
+
proto = PPP_PROTO(skb);
read_lock_bh(&pch->upl);
if (pch->ppp == 0 || proto >= 0xc000 || proto == PPP_CCPFRAG) {
@@ -1691,7 +1734,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
struct list_head *l;
int mphdrlen = (ppp->flags & SC_MP_SHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN;
- if (!pskb_may_pull(skb, mphdrlen + 1) || ppp->mrru == 0)
+ if (!pskb_may_pull(skb, mphdrlen) || ppp->mrru == 0)
goto err; /* no good, throw it away */
/* Decode sequence number and begin/end bits */
@@ -2611,8 +2654,8 @@ static void __exit ppp_cleanup(void)
if (unregister_chrdev(PPP_MAJOR, "ppp") != 0)
printk(KERN_ERR "PPP: failed to unregister PPP device\n");
devfs_remove("ppp");
- class_simple_device_remove(MKDEV(PPP_MAJOR, 0));
- class_simple_destroy(ppp_class);
+ class_device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0));
+ class_destroy(ppp_class);
}
/*
diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c
index 7d0150b4c62..fd9f5018035 100644
--- a/drivers/net/ppp_synctty.c
+++ b/drivers/net/ppp_synctty.c
@@ -793,7 +793,7 @@ err:
static void __exit
ppp_sync_cleanup(void)
{
- if (tty_register_ldisc(N_SYNC_PPP, NULL) != 0)
+ if (tty_unregister_ldisc(N_SYNC_PPP) != 0)
printk(KERN_ERR "failed to unregister Sync PPP line discipline\n");
}
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index c59507f8a76..ce449fe90e6 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -69,7 +69,13 @@ VERSION 2.2LK <2005/01/25>
#include <asm/io.h>
#include <asm/irq.h>
-#define RTL8169_VERSION "2.2LK"
+#ifdef CONFIG_R8169_NAPI
+#define NAPI_SUFFIX "-NAPI"
+#else
+#define NAPI_SUFFIX ""
+#endif
+
+#define RTL8169_VERSION "2.2LK" NAPI_SUFFIX
#define MODULENAME "r8169"
#define PFX MODULENAME ": "
@@ -85,6 +91,10 @@ VERSION 2.2LK <2005/01/25>
#define dprintk(fmt, args...) do {} while (0)
#endif /* RTL8169_DEBUG */
+#define R8169_MSG_DEFAULT \
+ (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | NETIF_MSG_IFUP | \
+ NETIF_MSG_IFDOWN)
+
#define TX_BUFFS_AVAIL(tp) \
(tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1)
@@ -174,8 +184,9 @@ const static struct {
#undef _R
static struct pci_device_id rtl8169_pci_tbl[] = {
- {0x10ec, 0x8169, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x1186, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), },
+ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), },
+ { PCI_DEVICE(0x16ec, 0x0116), },
{0,},
};
@@ -183,10 +194,15 @@ MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
static int rx_copybreak = 200;
static int use_dac;
+static struct {
+ u32 msg_enable;
+} debug = { -1 };
enum RTL8169_registers {
MAC0 = 0, /* Ethernet hardware address. */
MAR0 = 8, /* Multicast filter. */
+ CounterAddrLow = 0x10,
+ CounterAddrHigh = 0x14,
TxDescStartAddrLow = 0x20,
TxDescStartAddrHigh = 0x24,
TxHDescStartAddrLow = 0x28,
@@ -328,6 +344,9 @@ enum RTL8169_register_content {
/* _TBICSRBit */
TBILinkOK = 0x02000000,
+
+ /* DumpCounterCommand */
+ CounterDump = 0x8,
};
enum _DescStatusBit {
@@ -385,6 +404,7 @@ struct rtl8169_private {
struct pci_dev *pci_dev; /* Index of PCI device */
struct net_device_stats stats; /* statistics of net device */
spinlock_t lock; /* spin lock flag */
+ u32 msg_enable;
int chipset;
int mac_version;
int phy_version;
@@ -415,12 +435,16 @@ struct rtl8169_private {
struct work_struct task;
};
-MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@oss.sgi.com>");
+MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
module_param_array(media, int, &num_media, 0);
+MODULE_PARM_DESC(media, "force phy operation. Deprecated by ethtool (8).");
module_param(rx_copybreak, int, 0);
+MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
module_param(use_dac, int, 0);
MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
+module_param_named(debug, debug.msg_enable, int, 0);
+MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
MODULE_LICENSE("GPL");
MODULE_VERSION(RTL8169_VERSION);
@@ -433,10 +457,10 @@ static void rtl8169_hw_start(struct net_device *dev);
static int rtl8169_close(struct net_device *dev);
static void rtl8169_set_rx_mode(struct net_device *dev);
static void rtl8169_tx_timeout(struct net_device *dev);
-static struct net_device_stats *rtl8169_get_stats(struct net_device *netdev);
+static struct net_device_stats *rtl8169_get_stats(struct net_device *dev);
static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *,
void __iomem *);
-static int rtl8169_change_mtu(struct net_device *netdev, int new_mtu);
+static int rtl8169_change_mtu(struct net_device *dev, int new_mtu);
static void rtl8169_down(struct net_device *dev);
#ifdef CONFIG_R8169_NAPI
@@ -543,9 +567,13 @@ static void rtl8169_check_link_status(struct net_device *dev,
spin_lock_irqsave(&tp->lock, flags);
if (tp->link_ok(ioaddr)) {
netif_carrier_on(dev);
- printk(KERN_INFO PFX "%s: link up\n", dev->name);
- } else
+ if (netif_msg_ifup(tp))
+ printk(KERN_INFO PFX "%s: link up\n", dev->name);
+ } else {
+ if (netif_msg_ifdown(tp))
+ printk(KERN_INFO PFX "%s: link down\n", dev->name);
netif_carrier_off(dev);
+ }
spin_unlock_irqrestore(&tp->lock, flags);
}
@@ -569,7 +597,7 @@ static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex)
option = ((idx < MAX_UNITS) && (idx >= 0)) ? media[idx] : 0xff;
- if ((option != 0xff) && !idx)
+ if ((option != 0xff) && !idx && netif_msg_drv(&debug))
printk(KERN_WARNING PFX "media option is deprecated.\n");
for (p = link_settings; p->media != 0xff; p++) {
@@ -611,9 +639,11 @@ static int rtl8169_set_speed_tbi(struct net_device *dev,
} else if (autoneg == AUTONEG_ENABLE)
RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart);
else {
- printk(KERN_WARNING PFX
- "%s: incorrect speed setting refused in TBI mode\n",
- dev->name);
+ if (netif_msg_link(tp)) {
+ printk(KERN_WARNING "%s: "
+ "incorrect speed setting refused in TBI mode\n",
+ dev->name);
+ }
ret = -EOPNOTSUPP;
}
@@ -871,12 +901,120 @@ static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs,
spin_unlock_irqrestore(&tp->lock, flags);
}
+static u32 rtl8169_get_msglevel(struct net_device *dev)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+
+ return tp->msg_enable;
+}
+
+static void rtl8169_set_msglevel(struct net_device *dev, u32 value)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+
+ tp->msg_enable = value;
+}
+
+static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = {
+ "tx_packets",
+ "rx_packets",
+ "tx_errors",
+ "rx_errors",
+ "rx_missed",
+ "align_errors",
+ "tx_single_collisions",
+ "tx_multi_collisions",
+ "unicast",
+ "broadcast",
+ "multicast",
+ "tx_aborted",
+ "tx_underrun",
+};
+
+struct rtl8169_counters {
+ u64 tx_packets;
+ u64 rx_packets;
+ u64 tx_errors;
+ u32 rx_errors;
+ u16 rx_missed;
+ u16 align_errors;
+ u32 tx_one_collision;
+ u32 tx_multi_collision;
+ u64 rx_unicast;
+ u64 rx_broadcast;
+ u32 rx_multicast;
+ u16 tx_aborted;
+ u16 tx_underun;
+};
+
+static int rtl8169_get_stats_count(struct net_device *dev)
+{
+ return ARRAY_SIZE(rtl8169_gstrings);
+}
+
+static void rtl8169_get_ethtool_stats(struct net_device *dev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ struct rtl8169_private *tp = netdev_priv(dev);
+ void __iomem *ioaddr = tp->mmio_addr;
+ struct rtl8169_counters *counters;
+ dma_addr_t paddr;
+ u32 cmd;
+
+ ASSERT_RTNL();
+
+ counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr);
+ if (!counters)
+ return;
+
+ RTL_W32(CounterAddrHigh, (u64)paddr >> 32);
+ cmd = (u64)paddr & DMA_32BIT_MASK;
+ RTL_W32(CounterAddrLow, cmd);
+ RTL_W32(CounterAddrLow, cmd | CounterDump);
+
+ while (RTL_R32(CounterAddrLow) & CounterDump) {
+ if (msleep_interruptible(1))
+ break;
+ }
+
+ RTL_W32(CounterAddrLow, 0);
+ RTL_W32(CounterAddrHigh, 0);
+
+ data[0] = le64_to_cpu(counters->tx_packets);
+ data[1] = le64_to_cpu(counters->rx_packets);
+ data[2] = le64_to_cpu(counters->tx_errors);
+ data[3] = le32_to_cpu(counters->rx_errors);
+ data[4] = le16_to_cpu(counters->rx_missed);
+ data[5] = le16_to_cpu(counters->align_errors);
+ data[6] = le32_to_cpu(counters->tx_one_collision);
+ data[7] = le32_to_cpu(counters->tx_multi_collision);
+ data[8] = le64_to_cpu(counters->rx_unicast);
+ data[9] = le64_to_cpu(counters->rx_broadcast);
+ data[10] = le32_to_cpu(counters->rx_multicast);
+ data[11] = le16_to_cpu(counters->tx_aborted);
+ data[12] = le16_to_cpu(counters->tx_underun);
+
+ pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr);
+}
+
+static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
+{
+ switch(stringset) {
+ case ETH_SS_STATS:
+ memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings));
+ break;
+ }
+}
+
+
static struct ethtool_ops rtl8169_ethtool_ops = {
.get_drvinfo = rtl8169_get_drvinfo,
.get_regs_len = rtl8169_get_regs_len,
.get_link = ethtool_op_get_link,
.get_settings = rtl8169_get_settings,
.set_settings = rtl8169_set_settings,
+ .get_msglevel = rtl8169_get_msglevel,
+ .set_msglevel = rtl8169_set_msglevel,
.get_rx_csum = rtl8169_get_rx_csum,
.set_rx_csum = rtl8169_set_rx_csum,
.get_tx_csum = ethtool_op_get_tx_csum,
@@ -886,6 +1024,9 @@ static struct ethtool_ops rtl8169_ethtool_ops = {
.get_tso = ethtool_op_get_tso,
.set_tso = ethtool_op_set_tso,
.get_regs = rtl8169_get_regs,
+ .get_strings = rtl8169_get_strings,
+ .get_stats_count = rtl8169_get_stats_count,
+ .get_ethtool_stats = rtl8169_get_ethtool_stats,
};
static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum,
@@ -1091,7 +1232,8 @@ static void rtl8169_phy_timer(unsigned long __opaque)
if (tp->link_ok(ioaddr))
goto out_unlock;
- printk(KERN_WARNING PFX "%s: PHY reset until link up\n", dev->name);
+ if (netif_msg_link(tp))
+ printk(KERN_WARNING "%s: PHY reset until link up\n", dev->name);
tp->phy_reset_enable(ioaddr);
@@ -1169,18 +1311,23 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
/* dev zeroed in alloc_etherdev */
dev = alloc_etherdev(sizeof (*tp));
if (dev == NULL) {
- printk(KERN_ERR PFX "unable to alloc new ethernet\n");
+ if (netif_msg_drv(&debug))
+ printk(KERN_ERR PFX "unable to alloc new ethernet\n");
goto err_out;
}
SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &pdev->dev);
tp = netdev_priv(dev);
+ tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT);
/* enable device (incl. PCI PM wakeup and hotplug setup) */
rc = pci_enable_device(pdev);
- if (rc) {
- printk(KERN_ERR PFX "%s: enable failure\n", pci_name(pdev));
+ if (rc < 0) {
+ if (netif_msg_probe(tp)) {
+ printk(KERN_ERR PFX "%s: enable failure\n",
+ pci_name(pdev));
+ }
goto err_out_free_dev;
}
@@ -1196,29 +1343,39 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command);
acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
} else {
- printk(KERN_ERR PFX
- "Cannot find PowerManagement capability, aborting.\n");
+ if (netif_msg_probe(tp)) {
+ printk(KERN_ERR PFX
+ "Cannot find PowerManagement capability. "
+ "Aborting.\n");
+ }
goto err_out_mwi;
}
/* make sure PCI base addr 1 is MMIO */
if (!(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
- printk(KERN_ERR PFX
- "region #1 not an MMIO resource, aborting\n");
+ if (netif_msg_probe(tp)) {
+ printk(KERN_ERR PFX
+ "region #1 not an MMIO resource, aborting\n");
+ }
rc = -ENODEV;
goto err_out_mwi;
}
/* check for weird/broken PCI region reporting */
if (pci_resource_len(pdev, 1) < R8169_REGS_SIZE) {
- printk(KERN_ERR PFX "Invalid PCI region size(s), aborting\n");
+ if (netif_msg_probe(tp)) {
+ printk(KERN_ERR PFX
+ "Invalid PCI region size(s), aborting\n");
+ }
rc = -ENODEV;
goto err_out_mwi;
}
rc = pci_request_regions(pdev, MODULENAME);
- if (rc) {
- printk(KERN_ERR PFX "%s: could not request regions.\n",
- pci_name(pdev));
+ if (rc < 0) {
+ if (netif_msg_probe(tp)) {
+ printk(KERN_ERR PFX "%s: could not request regions.\n",
+ pci_name(pdev));
+ }
goto err_out_mwi;
}
@@ -1231,7 +1388,10 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
} else {
rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (rc < 0) {
- printk(KERN_ERR PFX "DMA configuration failed.\n");
+ if (netif_msg_probe(tp)) {
+ printk(KERN_ERR PFX
+ "DMA configuration failed.\n");
+ }
goto err_out_free_res;
}
}
@@ -1241,7 +1401,8 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
/* ioremap MMIO region */
ioaddr = ioremap(pci_resource_start(pdev, 1), R8169_REGS_SIZE);
if (ioaddr == NULL) {
- printk(KERN_ERR PFX "cannot remap MMIO, aborting\n");
+ if (netif_msg_probe(tp))
+ printk(KERN_ERR PFX "cannot remap MMIO, aborting\n");
rc = -EIO;
goto err_out_free_res;
}
@@ -1272,9 +1433,11 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
}
if (i < 0) {
/* Unknown chip: assume array element #0, original RTL-8169 */
- printk(KERN_DEBUG PFX
- "PCI device %s: unknown chip version, assuming %s\n",
- pci_name(pdev), rtl_chip_info[0].name);
+ if (netif_msg_probe(tp)) {
+ printk(KERN_DEBUG PFX "PCI device %s: "
+ "unknown chip version, assuming %s\n",
+ pci_name(pdev), rtl_chip_info[0].name);
+ }
i++;
}
tp->chipset = i;
@@ -1308,7 +1471,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
struct rtl8169_private *tp;
void __iomem *ioaddr = NULL;
static int board_idx = -1;
- static int printed_version = 0;
u8 autoneg, duplex;
u16 speed;
int i, rc;
@@ -1318,10 +1480,9 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
board_idx++;
- if (!printed_version) {
+ if (netif_msg_drv(&debug)) {
printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n",
MODULENAME, RTL8169_VERSION);
- printed_version = 1;
}
rc = rtl8169_init_board(pdev, &dev, &ioaddr);
@@ -1366,7 +1527,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
#ifdef CONFIG_R8169_NAPI
dev->poll = rtl8169_poll;
dev->weight = R8169_NAPI_WEIGHT;
- printk(KERN_INFO PFX "NAPI enabled\n");
#endif
#ifdef CONFIG_R8169_VLAN
@@ -1391,20 +1551,24 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
return rc;
}
- printk(KERN_DEBUG "%s: Identified chip type is '%s'.\n", dev->name,
- rtl_chip_info[tp->chipset].name);
+ if (netif_msg_probe(tp)) {
+ printk(KERN_DEBUG "%s: Identified chip type is '%s'.\n",
+ dev->name, rtl_chip_info[tp->chipset].name);
+ }
pci_set_drvdata(pdev, dev);
- printk(KERN_INFO "%s: %s at 0x%lx, "
- "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
- "IRQ %d\n",
- dev->name,
- rtl_chip_info[ent->driver_data].name,
- dev->base_addr,
- dev->dev_addr[0], dev->dev_addr[1],
- dev->dev_addr[2], dev->dev_addr[3],
- dev->dev_addr[4], dev->dev_addr[5], dev->irq);
+ if (netif_msg_probe(tp)) {
+ printk(KERN_INFO "%s: %s at 0x%lx, "
+ "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
+ "IRQ %d\n",
+ dev->name,
+ rtl_chip_info[ent->driver_data].name,
+ dev->base_addr,
+ dev->dev_addr[0], dev->dev_addr[1],
+ dev->dev_addr[2], dev->dev_addr[3],
+ dev->dev_addr[4], dev->dev_addr[5], dev->irq);
+ }
rtl8169_hw_phy_config(dev);
@@ -1427,7 +1591,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
rtl8169_set_speed(dev, autoneg, speed, duplex);
- if (RTL_R8(PHYstatus) & TBI_Enable)
+ if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp))
printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name);
return 0;
@@ -1585,8 +1749,8 @@ rtl8169_hw_start(struct net_device *dev)
RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
RTL_W8(EarlyTxThres, EarlyTxThld);
- /* For gigabit rtl8169, MTU + header + CRC + VLAN */
- RTL_W16(RxMaxSize, tp->rx_buf_sz);
+ /* Low hurts. Let's disable the filtering. */
+ RTL_W16(RxMaxSize, 16383);
/* Set Rx Config register */
i = rtl8169_rx_config |
@@ -1860,8 +2024,13 @@ static void rtl8169_reinit_task(void *_data)
ret = rtl8169_open(dev);
if (unlikely(ret < 0)) {
if (net_ratelimit()) {
- printk(PFX KERN_ERR "%s: reinit failure (status = %d)."
- " Rescheduling.\n", dev->name, ret);
+ struct rtl8169_private *tp = netdev_priv(dev);
+
+ if (netif_msg_drv(tp)) {
+ printk(PFX KERN_ERR
+ "%s: reinit failure (status = %d)."
+ " Rescheduling.\n", dev->name, ret);
+ }
}
rtl8169_schedule_work(dev, rtl8169_reinit_task);
}
@@ -1886,8 +2055,12 @@ static void rtl8169_reset_task(void *_data)
netif_wake_queue(dev);
} else {
if (net_ratelimit()) {
- printk(PFX KERN_EMERG "%s: Rx buffers shortage\n",
- dev->name);
+ struct rtl8169_private *tp = netdev_priv(dev);
+
+ if (netif_msg_intr(tp)) {
+ printk(PFX KERN_EMERG
+ "%s: Rx buffers shortage\n", dev->name);
+ }
}
rtl8169_schedule_work(dev, rtl8169_reset_task);
}
@@ -1973,8 +2146,11 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev)
int ret = 0;
if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) {
- printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
- dev->name);
+ if (netif_msg_drv(tp)) {
+ printk(KERN_ERR
+ "%s: BUG! Tx Ring full when queue awake!\n",
+ dev->name);
+ }
goto err_stop;
}
@@ -2049,8 +2225,11 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev)
pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
pci_read_config_word(pdev, PCI_STATUS, &pci_status);
- printk(KERN_ERR PFX "%s: PCI error (cmd = 0x%04x, status = 0x%04x).\n",
- dev->name, pci_cmd, pci_status);
+ if (netif_msg_intr(tp)) {
+ printk(KERN_ERR
+ "%s: PCI error (cmd = 0x%04x, status = 0x%04x).\n",
+ dev->name, pci_cmd, pci_status);
+ }
/*
* The recovery sequence below admits a very elaborated explanation:
@@ -2069,7 +2248,8 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev)
/* The infamous DAC f*ckup only happens at boot time */
if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) {
- printk(KERN_INFO PFX "%s: disabling PCI DAC.\n", dev->name);
+ if (netif_msg_intr(tp))
+ printk(KERN_INFO "%s: disabling PCI DAC.\n", dev->name);
tp->cp_cmd &= ~PCIDAC;
RTL_W16(CPlusCmd, tp->cp_cmd);
dev->features &= ~NETIF_F_HIGHDMA;
@@ -2127,6 +2307,11 @@ rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
}
}
+static inline int rtl8169_fragmented_frame(u32 status)
+{
+ return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag);
+}
+
static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc)
{
u32 opts1 = le32_to_cpu(desc->opts1);
@@ -2175,29 +2360,46 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
rx_left = rtl8169_rx_quota(rx_left, (u32) dev->quota);
- while (rx_left > 0) {
+ for (; rx_left > 0; rx_left--, cur_rx++) {
unsigned int entry = cur_rx % NUM_RX_DESC;
+ struct RxDesc *desc = tp->RxDescArray + entry;
u32 status;
rmb();
- status = le32_to_cpu(tp->RxDescArray[entry].opts1);
+ status = le32_to_cpu(desc->opts1);
if (status & DescOwn)
break;
- if (status & RxRES) {
- printk(KERN_INFO "%s: Rx ERROR!!!\n", dev->name);
+ if (unlikely(status & RxRES)) {
+ if (netif_msg_rx_err(tp)) {
+ printk(KERN_INFO
+ "%s: Rx ERROR. status = %08x\n",
+ dev->name, status);
+ }
tp->stats.rx_errors++;
if (status & (RxRWT | RxRUNT))
tp->stats.rx_length_errors++;
if (status & RxCRC)
tp->stats.rx_crc_errors++;
+ rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
} else {
- struct RxDesc *desc = tp->RxDescArray + entry;
struct sk_buff *skb = tp->Rx_skbuff[entry];
int pkt_size = (status & 0x00001FFF) - 4;
void (*pci_action)(struct pci_dev *, dma_addr_t,
size_t, int) = pci_dma_sync_single_for_device;
+ /*
+ * The driver does not support incoming fragmented
+ * frames. They are seen as a symptom of over-mtu
+ * sized frames.
+ */
+ if (unlikely(rtl8169_fragmented_frame(status))) {
+ tp->stats.rx_dropped++;
+ tp->stats.rx_length_errors++;
+ rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
+ continue;
+ }
+
rtl8169_rx_csum(skb, desc);
pci_dma_sync_single_for_cpu(tp->pci_dev,
@@ -2224,16 +2426,13 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
tp->stats.rx_bytes += pkt_size;
tp->stats.rx_packets++;
}
-
- cur_rx++;
- rx_left--;
}
count = cur_rx - tp->cur_rx;
tp->cur_rx = cur_rx;
delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx);
- if (!delta && count)
+ if (!delta && count && netif_msg_intr(tp))
printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name);
tp->dirty_rx += delta;
@@ -2244,7 +2443,7 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
* after refill ?
* - how do others driver handle this condition (Uh oh...).
*/
- if (tp->dirty_rx + NUM_RX_DESC == tp->cur_rx)
+ if ((tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) && netif_msg_intr(tp))
printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name);
return count;
@@ -2296,7 +2495,7 @@ rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
if (likely(netif_rx_schedule_prep(dev)))
__netif_rx_schedule(dev);
- else {
+ else if (netif_msg_intr(tp)) {
printk(KERN_INFO "%s: interrupt %04x taken in poll\n",
dev->name, status);
}
@@ -2315,8 +2514,10 @@ rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
} while (boguscnt > 0);
if (boguscnt <= 0) {
- printk(KERN_WARNING "%s: Too much work at interrupt!\n",
- dev->name);
+ if (net_ratelimit() && netif_msg_intr(tp)) {
+ printk(KERN_WARNING
+ "%s: Too much work at interrupt!\n", dev->name);
+ }
/* Clear all interrupt sources. */
RTL_W16(IntrStatus, 0xffff);
}
@@ -2439,8 +2640,10 @@ rtl8169_set_rx_mode(struct net_device *dev)
if (dev->flags & IFF_PROMISC) {
/* Unconditionally log net taps. */
- printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n",
- dev->name);
+ if (netif_msg_link(tp)) {
+ printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n",
+ dev->name);
+ }
rx_mode =
AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
AcceptAllPhys;
diff --git a/drivers/net/shaper.c b/drivers/net/shaper.c
index e68cf5fb492..20edeb34579 100644
--- a/drivers/net/shaper.c
+++ b/drivers/net/shaper.c
@@ -100,35 +100,8 @@ static int sh_debug; /* Debug flag */
#define SHAPER_BANNER "CymruNet Traffic Shaper BETA 0.04 for Linux 2.1\n"
-/*
- * Locking
- */
-
-static int shaper_lock(struct shaper *sh)
-{
- /*
- * Lock in an interrupt must fail
- */
- while (test_and_set_bit(0, &sh->locked))
- {
- if (!in_interrupt())
- sleep_on(&sh->wait_queue);
- else
- return 0;
-
- }
- return 1;
-}
-
static void shaper_kick(struct shaper *sh);
-static void shaper_unlock(struct shaper *sh)
-{
- clear_bit(0, &sh->locked);
- wake_up(&sh->wait_queue);
- shaper_kick(sh);
-}
-
/*
* Compute clocks on a buffer
*/
@@ -157,17 +130,15 @@ static void shaper_setspeed(struct shaper *shaper, int bitspersec)
* Throw a frame at a shaper.
*/
-static int shaper_qframe(struct shaper *shaper, struct sk_buff *skb)
+
+static int shaper_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
+ struct shaper *shaper = dev->priv;
struct sk_buff *ptr;
- /*
- * Get ready to work on this shaper. Lock may fail if its
- * an interrupt and locked.
- */
-
- if(!shaper_lock(shaper))
- return -1;
+ if (down_trylock(&shaper->sem))
+ return -1;
+
ptr=shaper->sendq.prev;
/*
@@ -260,7 +231,8 @@ static int shaper_qframe(struct shaper *shaper, struct sk_buff *skb)
dev_kfree_skb(ptr);
shaper->stats.collisions++;
}
- shaper_unlock(shaper);
+ shaper_kick(shaper);
+ up(&shaper->sem);
return 0;
}
@@ -297,8 +269,13 @@ static void shaper_queue_xmit(struct shaper *shaper, struct sk_buff *skb)
static void shaper_timer(unsigned long data)
{
- struct shaper *sh=(struct shaper *)data;
- shaper_kick(sh);
+ struct shaper *shaper = (struct shaper *)data;
+
+ if (!down_trylock(&shaper->sem)) {
+ shaper_kick(shaper);
+ up(&shaper->sem);
+ } else
+ mod_timer(&shaper->timer, jiffies);
}
/*
@@ -311,19 +288,6 @@ static void shaper_kick(struct shaper *shaper)
struct sk_buff *skb;
/*
- * Shaper unlock will kick
- */
-
- if (test_and_set_bit(0, &shaper->locked))
- {
- if(sh_debug)
- printk("Shaper locked.\n");
- mod_timer(&shaper->timer, jiffies);
- return;
- }
-
-
- /*
* Walk the list (may be empty)
*/
@@ -364,8 +328,6 @@ static void shaper_kick(struct shaper *shaper)
if(skb!=NULL)
mod_timer(&shaper->timer, SHAPERCB(skb)->shapeclock);
-
- clear_bit(0, &shaper->locked);
}
@@ -376,14 +338,12 @@ static void shaper_kick(struct shaper *shaper)
static void shaper_flush(struct shaper *shaper)
{
struct sk_buff *skb;
- if(!shaper_lock(shaper))
- {
- printk(KERN_ERR "shaper: shaper_flush() called by an irq!\n");
- return;
- }
+
+ down(&shaper->sem);
while((skb=skb_dequeue(&shaper->sendq))!=NULL)
dev_kfree_skb(skb);
- shaper_unlock(shaper);
+ shaper_kick(shaper);
+ up(&shaper->sem);
}
/*
@@ -426,13 +386,6 @@ static int shaper_close(struct net_device *dev)
* ARP and other resolutions and not before.
*/
-
-static int shaper_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct shaper *sh=dev->priv;
- return shaper_qframe(sh, skb);
-}
-
static struct net_device_stats *shaper_get_stats(struct net_device *dev)
{
struct shaper *sh=dev->priv;
@@ -623,7 +576,6 @@ static void shaper_init_priv(struct net_device *dev)
init_timer(&sh->timer);
sh->timer.function=shaper_timer;
sh->timer.data=(unsigned long)sh;
- init_waitqueue_head(&sh->wait_queue);
}
/*
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 3e9d9aab058..3107aed0fb5 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -162,6 +162,7 @@ struct sis900_private {
struct mii_phy * mii;
struct mii_phy * first_mii; /* record the first mii structure */
unsigned int cur_phy;
+ struct mii_if_info mii_info;
struct timer_list timer; /* Link status detection timer. */
u8 autong_complete; /* 1: auto-negotiate complete */
@@ -203,7 +204,7 @@ static int sis900_open(struct net_device *net_dev);
static int sis900_mii_probe (struct net_device * net_dev);
static void sis900_init_rxfilter (struct net_device * net_dev);
static u16 read_eeprom(long ioaddr, int location);
-static u16 mdio_read(struct net_device *net_dev, int phy_id, int location);
+static int mdio_read(struct net_device *net_dev, int phy_id, int location);
static void mdio_write(struct net_device *net_dev, int phy_id, int location, int val);
static void sis900_timer(unsigned long data);
static void sis900_check_mode (struct net_device *net_dev, struct mii_phy *mii_phy);
@@ -478,7 +479,13 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
sis_priv->msg_enable = sis900_debug;
else
sis_priv->msg_enable = SIS900_DEF_MSG;
-
+
+ sis_priv->mii_info.dev = net_dev;
+ sis_priv->mii_info.mdio_read = mdio_read;
+ sis_priv->mii_info.mdio_write = mdio_write;
+ sis_priv->mii_info.phy_id_mask = 0x1f;
+ sis_priv->mii_info.reg_num_mask = 0x1f;
+
/* Get Mac address according to the chip revision */
pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &(sis_priv->chipset_rev));
if(netif_msg_probe(sis_priv))
@@ -725,6 +732,8 @@ static u16 sis900_default_phy(struct net_device * net_dev)
pci_name(sis_priv->pci_dev), sis_priv->cur_phy);
}
+ sis_priv->mii_info.phy_id = sis_priv->cur_phy;
+
status = mdio_read(net_dev, sis_priv->cur_phy, MII_CONTROL);
status &= (~MII_CNTL_ISOLATE);
@@ -852,7 +861,7 @@ static void mdio_reset(long mdio_addr)
* Please see SiS7014 or ICS spec
*/
-static u16 mdio_read(struct net_device *net_dev, int phy_id, int location)
+static int mdio_read(struct net_device *net_dev, int phy_id, int location)
{
long mdio_addr = net_dev->base_addr + mear;
int mii_cmd = MIIread|(phy_id<<MIIpmdShift)|(location<<MIIregShift);
@@ -1966,10 +1975,47 @@ static void sis900_set_msglevel(struct net_device *net_dev, u32 value)
sis_priv->msg_enable = value;
}
+static u32 sis900_get_link(struct net_device *net_dev)
+{
+ struct sis900_private *sis_priv = net_dev->priv;
+ return mii_link_ok(&sis_priv->mii_info);
+}
+
+static int sis900_get_settings(struct net_device *net_dev,
+ struct ethtool_cmd *cmd)
+{
+ struct sis900_private *sis_priv = net_dev->priv;
+ spin_lock_irq(&sis_priv->lock);
+ mii_ethtool_gset(&sis_priv->mii_info, cmd);
+ spin_unlock_irq(&sis_priv->lock);
+ return 0;
+}
+
+static int sis900_set_settings(struct net_device *net_dev,
+ struct ethtool_cmd *cmd)
+{
+ struct sis900_private *sis_priv = net_dev->priv;
+ int rt;
+ spin_lock_irq(&sis_priv->lock);
+ rt = mii_ethtool_sset(&sis_priv->mii_info, cmd);
+ spin_unlock_irq(&sis_priv->lock);
+ return rt;
+}
+
+static int sis900_nway_reset(struct net_device *net_dev)
+{
+ struct sis900_private *sis_priv = net_dev->priv;
+ return mii_nway_restart(&sis_priv->mii_info);
+}
+
static struct ethtool_ops sis900_ethtool_ops = {
.get_drvinfo = sis900_get_drvinfo,
.get_msglevel = sis900_get_msglevel,
.set_msglevel = sis900_set_msglevel,
+ .get_link = sis900_get_link,
+ .get_settings = sis900_get_settings,
+ .set_settings = sis900_set_settings,
+ .nway_reset = sis900_nway_reset,
};
/**
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
index 05b827f79f5..1ccb2989001 100644
--- a/drivers/net/sk98lin/skge.c
+++ b/drivers/net/sk98lin/skge.c
@@ -4212,7 +4212,7 @@ SK_BOOL DualNet;
Flags);
SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST);
- pAC->dev[Param.Para32[0]]->flags &= ~IFF_RUNNING;
+ netif_carrier_off(pAC->dev[Param.Para32[0]]);
spin_unlock_irqrestore(
&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
Flags);
@@ -4355,7 +4355,7 @@ SK_BOOL DualNet;
}
/* Inform the world that link protocol is up. */
- pAC->dev[Param.Para32[0]]->flags |= IFF_RUNNING;
+ netif_carrier_on(pAC->dev[Param.Para32[0]]);
break;
case SK_DRV_NET_DOWN: /* SK_U32 Reason */
@@ -4368,7 +4368,7 @@ SK_BOOL DualNet;
} else {
DoPrintInterfaceChange = SK_TRUE;
}
- pAC->dev[Param.Para32[1]]->flags &= ~IFF_RUNNING;
+ netif_carrier_off(pAC->dev[Param.Para32[1]]);
break;
case SK_DRV_SWITCH_HARD: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
@@ -4961,7 +4961,6 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = &SkGePollController;
#endif
- dev->flags &= ~IFF_RUNNING;
SET_NETDEV_DEV(dev, &pdev->dev);
SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps);
@@ -5035,7 +5034,6 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
dev->set_mac_address = &SkGeSetMacAddr;
dev->do_ioctl = &SkGeIoctl;
dev->change_mtu = &SkGeChangeMtu;
- dev->flags &= ~IFF_RUNNING;
SET_NETDEV_DEV(dev, &pdev->dev);
SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps);
diff --git a/drivers/net/sk_g16.c b/drivers/net/sk_g16.c
deleted file mode 100644
index 134ae0e6495..00000000000
--- a/drivers/net/sk_g16.c
+++ /dev/null
@@ -1,2066 +0,0 @@
-/*-
- * Copyright (C) 1994 by PJD Weichmann & SWS Bern, Switzerland
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * Module : sk_g16.c
- *
- * Version : $Revision: 1.1 $
- *
- * Author : Patrick J.D. Weichmann
- *
- * Date Created : 94/05/26
- * Last Updated : $Date: 1994/06/30 16:25:15 $
- *
- * Description : Schneider & Koch G16 Ethernet Device Driver for
- * Linux Kernel >= 1.1.22
- * Update History :
- * Paul Gortmaker, 03/97: Fix for v2.1.x to use read{b,w}
- * write{b,w} and memcpy -> memcpy_{to,from}io
- *
- * Jeff Garzik, 06/2000, Modularize
- *
--*/
-
-static const char rcsid[] = "$Id: sk_g16.c,v 1.1 1994/06/30 16:25:15 root Exp $";
-
-/*
- * The Schneider & Koch (SK) G16 Network device driver is based
- * on the 'ni6510' driver from Michael Hipp which can be found at
- * ftp://sunsite.unc.edu/pub/Linux/system/Network/drivers/nidrivers.tar.gz
- *
- * Sources: 1) ni6510.c by M. Hipp
- * 2) depca.c by D.C. Davies
- * 3) skeleton.c by D. Becker
- * 4) Am7990 Local Area Network Controller for Ethernet (LANCE),
- * AMD, Pub. #05698, June 1989
- *
- * Many Thanks for helping me to get things working to:
- *
- * A. Cox (A.Cox@swansea.ac.uk)
- * M. Hipp (mhipp@student.uni-tuebingen.de)
- * R. Bolz (Schneider & Koch, Germany)
- *
- * To Do:
- * - Support of SK_G8 and other SK Network Cards.
- * - Autoset memory mapped RAM. Check for free memory and then
- * configure RAM correctly.
- * - SK_close should really set card in to initial state.
- * - Test if IRQ 3 is not switched off. Use autoirq() functionality.
- * (as in /drivers/net/skeleton.c)
- * - Implement Multicast addressing. At minimum something like
- * in depca.c.
- * - Redo the statistics part.
- * - Try to find out if the board is in 8 Bit or 16 Bit slot.
- * If in 8 Bit mode don't use IRQ 11.
- * - (Try to make it slightly faster.)
- * - Power management support
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/fcntl.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/bitops.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-
-#include "sk_g16.h"
-
-/*
- * Schneider & Koch Card Definitions
- * =================================
- */
-
-#define SK_NAME "SK_G16"
-
-/*
- * SK_G16 Configuration
- * --------------------
- */
-
-/*
- * Abbreviations
- * -------------
- *
- * RAM - used for the 16KB shared memory
- * Boot_ROM, ROM - are used for referencing the BootEPROM
- *
- * SK_BOOT_ROM and SK_ADDR are symbolic constants used to configure
- * the behaviour of the driver and the SK_G16.
- *
- * ! See sk_g16.install on how to install and configure the driver !
- *
- * SK_BOOT_ROM defines if the Boot_ROM should be switched off or not.
- *
- * SK_ADDR defines the address where the RAM will be mapped into the real
- * host memory.
- * valid addresses are from 0xa0000 to 0xfc000 in 16Kbyte steps.
- */
-
-#define SK_BOOT_ROM 1 /* 1=BootROM on 0=off */
-
-#define SK_ADDR 0xcc000
-
-/*
- * In POS3 are bits A14-A19 of the address bus. These bits can be set
- * to choose the RAM address. That's why we only can choose the RAM address
- * in 16KB steps.
- */
-
-#define POS_ADDR (rom_addr>>14) /* Do not change this line */
-
-/*
- * SK_G16 I/O PORT's + IRQ's + Boot_ROM locations
- * ----------------------------------------------
- */
-
-/*
- * As nearly every card has also SK_G16 a specified I/O Port region and
- * only a few possible IRQ's.
- * In the Installation Guide from Schneider & Koch is listed a possible
- * Interrupt IRQ2. IRQ2 is always IRQ9 in boards with two cascaded interrupt
- * controllers. So we use in SK_IRQS IRQ9.
- */
-
-/* Don't touch any of the following #defines. */
-
-#define SK_IO_PORTS { 0x100, 0x180, 0x208, 0x220, 0x288, 0x320, 0x328, 0x390, 0 }
-
-#define SK_IRQS { 3, 5, 9, 11, 0 }
-
-#define SK_BOOT_ROM_LOCATIONS { 0xc0000, 0xc4000, 0xc8000, 0xcc000, 0xd0000, 0xd4000, 0xd8000, 0xdc000, 0 }
-
-#define SK_BOOT_ROM_ID { 0x55, 0xaa, 0x10, 0x50, 0x06, 0x33 }
-
-/*
- * SK_G16 POS REGISTERS
- * --------------------
- */
-
-/*
- * SK_G16 has a Programmable Option Select (POS) Register.
- * The POS is composed of 8 separate registers (POS0-7) which
- * are I/O mapped on an address set by the W1 switch.
- *
- */
-
-#define SK_POS_SIZE 8 /* 8 I/O Ports are used by SK_G16 */
-
-#define SK_POS0 ioaddr /* Card-ID Low (R) */
-#define SK_POS1 ioaddr+1 /* Card-ID High (R) */
-#define SK_POS2 ioaddr+2 /* Card-Enable, Boot-ROM Disable (RW) */
-#define SK_POS3 ioaddr+3 /* Base address of RAM */
-#define SK_POS4 ioaddr+4 /* IRQ */
-
-/* POS5 - POS7 are unused */
-
-/*
- * SK_G16 MAC PREFIX
- * -----------------
- */
-
-/*
- * Scheider & Koch manufacturer code (00:00:a5).
- * This must be checked, that we are sure it is a SK card.
- */
-
-#define SK_MAC0 0x00
-#define SK_MAC1 0x00
-#define SK_MAC2 0x5a
-
-/*
- * SK_G16 ID
- * ---------
- */
-
-/*
- * If POS0,POS1 contain the following ID, then we know
- * at which I/O Port Address we are.
- */
-
-#define SK_IDLOW 0xfd
-#define SK_IDHIGH 0x6a
-
-
-/*
- * LANCE POS Bit definitions
- * -------------------------
- */
-
-#define SK_ROM_RAM_ON (POS2_CARD)
-#define SK_ROM_RAM_OFF (POS2_EPROM)
-#define SK_ROM_ON (inb(SK_POS2) & POS2_CARD)
-#define SK_ROM_OFF (inb(SK_POS2) | POS2_EPROM)
-#define SK_RAM_ON (inb(SK_POS2) | POS2_CARD)
-#define SK_RAM_OFF (inb(SK_POS2) & POS2_EPROM)
-
-#define POS2_CARD 0x0001 /* 1 = SK_G16 on 0 = off */
-#define POS2_EPROM 0x0002 /* 1 = Boot EPROM off 0 = on */
-
-/*
- * SK_G16 Memory mapped Registers
- * ------------------------------
- *
- */
-
-#define SK_IOREG (&board->ioreg) /* LANCE data registers. */
-#define SK_PORT (&board->port) /* Control, Status register */
-#define SK_IOCOM (&board->iocom) /* I/O Command */
-
-/*
- * SK_G16 Status/Control Register bits
- * -----------------------------------
- *
- * (C) Controlreg (S) Statusreg
- */
-
-/*
- * Register transfer: 0 = no transfer
- * 1 = transferring data between LANCE and I/O reg
- */
-#define SK_IORUN 0x20
-
-/*
- * LANCE interrupt: 0 = LANCE interrupt occurred
- * 1 = no LANCE interrupt occurred
- */
-#define SK_IRQ 0x10
-
-#define SK_RESET 0x08 /* Reset SK_CARD: 0 = RESET 1 = normal */
-#define SK_RW 0x02 /* 0 = write to 1 = read from */
-#define SK_ADR 0x01 /* 0 = REG DataPort 1 = RAP Reg addr port */
-
-
-#define SK_RREG SK_RW /* Transferdirection to read from lance */
-#define SK_WREG 0 /* Transferdirection to write to lance */
-#define SK_RAP SK_ADR /* Destination Register RAP */
-#define SK_RDATA 0 /* Destination Register REG DataPort */
-
-/*
- * SK_G16 I/O Command
- * ------------------
- */
-
-/*
- * Any bitcombination sets the internal I/O bit (transfer will start)
- * when written to I/O Command
- */
-
-#define SK_DOIO 0x80 /* Do Transfer */
-
-/*
- * LANCE RAP (Register Address Port).
- * ---------------------------------
- */
-
-/*
- * The LANCE internal registers are selected through the RAP.
- * The Registers are:
- *
- * CSR0 - Status and Control flags
- * CSR1 - Low order bits of initialize block (bits 15:00)
- * CSR2 - High order bits of initialize block (bits 07:00, 15:08 are reserved)
- * CSR3 - Allows redefinition of the Bus Master Interface.
- * This register must be set to 0x0002, which means BSWAP = 0,
- * ACON = 1, BCON = 0;
- *
- */
-
-#define CSR0 0x00
-#define CSR1 0x01
-#define CSR2 0x02
-#define CSR3 0x03
-
-/*
- * General Definitions
- * ===================
- */
-
-/*
- * Set the number of Tx and Rx buffers, using Log_2(# buffers).
- * We have 16KB RAM which can be accessed by the LANCE. In the
- * memory are not only the buffers but also the ring descriptors and
- * the initialize block.
- * Don't change anything unless you really know what you do.
- */
-
-#define LC_LOG_TX_BUFFERS 1 /* (2 == 2^^1) 2 Transmit buffers */
-#define LC_LOG_RX_BUFFERS 3 /* (8 == 2^^3) 8 Receive buffers */
-
-/* Descriptor ring sizes */
-
-#define TMDNUM (1 << (LC_LOG_TX_BUFFERS)) /* 2 Transmit descriptor rings */
-#define RMDNUM (1 << (LC_LOG_RX_BUFFERS)) /* 8 Receive Buffers */
-
-/* Define Mask for setting RMD, TMD length in the LANCE init_block */
-
-#define TMDNUMMASK (LC_LOG_TX_BUFFERS << 29)
-#define RMDNUMMASK (LC_LOG_RX_BUFFERS << 29)
-
-/*
- * Data Buffer size is set to maximum packet length.
- */
-
-#define PKT_BUF_SZ 1518
-
-/*
- * The number of low I/O ports used by the ethercard.
- */
-
-#define ETHERCARD_TOTAL_SIZE SK_POS_SIZE
-
-/*
- * SK_DEBUG
- *
- * Here you can choose what level of debugging wanted.
- *
- * If SK_DEBUG and SK_DEBUG2 are undefined, then only the
- * necessary messages will be printed.
- *
- * If SK_DEBUG is defined, there will be many debugging prints
- * which can help to find some mistakes in configuration or even
- * in the driver code.
- *
- * If SK_DEBUG2 is defined, many many messages will be printed
- * which normally you don't need. I used this to check the interrupt
- * routine.
- *
- * (If you define only SK_DEBUG2 then only the messages for
- * checking interrupts will be printed!)
- *
- * Normal way of live is:
- *
- * For the whole thing get going let both symbolic constants
- * undefined. If you face any problems and you know what's going
- * on (you know something about the card and you can interpret some
- * hex LANCE register output) then define SK_DEBUG
- *
- */
-
-#undef SK_DEBUG /* debugging */
-#undef SK_DEBUG2 /* debugging with more verbose report */
-
-#ifdef SK_DEBUG
-#define PRINTK(x) printk x
-#else
-#define PRINTK(x) /**/
-#endif
-
-#ifdef SK_DEBUG2
-#define PRINTK2(x) printk x
-#else
-#define PRINTK2(x) /**/
-#endif
-
-/*
- * SK_G16 RAM
- *
- * The components are memory mapped and can be set in a region from
- * 0x00000 through 0xfc000 in 16KB steps.
- *
- * The Network components are: dual ported RAM, Prom, I/O Reg, Status-,
- * Controlregister and I/O Command.
- *
- * dual ported RAM: This is the only memory region which the LANCE chip
- * has access to. From the Lance it is addressed from 0x0000 to
- * 0x3fbf. The host accesses it normally.
- *
- * PROM: The PROM obtains the ETHERNET-MAC-Address. It is realised as a
- * 8-Bit PROM, this means only the 16 even addresses are used of the
- * 32 Byte Address region. Access to an odd address results in invalid
- * data.
- *
- * LANCE I/O Reg: The I/O Reg is build of 4 single Registers, Low-Byte Write,
- * Hi-Byte Write, Low-Byte Read, Hi-Byte Read.
- * Transfer from or to the LANCE is always in 16Bit so Low and High
- * registers are always relevant.
- *
- * The Data from the Readregister is not the data in the Writeregister!!
- *
- * Port: Status- and Controlregister.
- * Two different registers which share the same address, Status is
- * read-only, Control is write-only.
- *
- * I/O Command:
- * Any bitcombination written in here starts the transmission between
- * Host and LANCE.
- */
-
-typedef struct
-{
- unsigned char ram[0x3fc0]; /* 16KB dual ported ram */
- unsigned char rom[0x0020]; /* 32Byte PROM containing 6Byte MAC */
- unsigned char res1[0x0010]; /* reserved */
- unsigned volatile short ioreg;/* LANCE I/O Register */
- unsigned volatile char port; /* Statusregister and Controlregister */
- unsigned char iocom; /* I/O Command Register */
-} SK_RAM;
-
-/* struct */
-
-/*
- * This is the structure for the dual ported ram. We
- * have exactly 16 320 Bytes. In here there must be:
- *
- * - Initialize Block (starting at a word boundary)
- * - Receive and Transmit Descriptor Rings (quadword boundary)
- * - Data Buffers (arbitrary boundary)
- *
- * This is because LANCE has on SK_G16 only access to the dual ported
- * RAM and nowhere else.
- */
-
-struct SK_ram
-{
- struct init_block ib;
- struct tmd tmde[TMDNUM];
- struct rmd rmde[RMDNUM];
- char tmdbuf[TMDNUM][PKT_BUF_SZ];
- char rmdbuf[RMDNUM][PKT_BUF_SZ];
-};
-
-/*
- * Structure where all necessary information is for ring buffer
- * management and statistics.
- */
-
-struct priv
-{
- struct SK_ram *ram; /* dual ported ram structure */
- struct rmd *rmdhead; /* start of receive ring descriptors */
- struct tmd *tmdhead; /* start of transmit ring descriptors */
- int rmdnum; /* actual used ring descriptor */
- int tmdnum; /* actual transmit descriptor for transmitting data */
- int tmdlast; /* last sent descriptor used for error handling, etc */
- void *rmdbufs[RMDNUM]; /* pointer to the receive buffers */
- void *tmdbufs[TMDNUM]; /* pointer to the transmit buffers */
- struct net_device_stats stats; /* Device driver statistics */
-};
-
-/* global variable declaration */
-
-/* IRQ map used to reserve a IRQ (see SK_open()) */
-
-/* static variables */
-
-static SK_RAM *board; /* pointer to our memory mapped board components */
-static DEFINE_SPINLOCK(SK_lock);
-
-/* Macros */
-
-
-/* Function Prototypes */
-
-/*
- * Device Driver functions
- * -----------------------
- * See for short explanation of each function its definitions header.
- */
-
-static int SK_probe(struct net_device *dev, short ioaddr);
-
-static void SK_timeout(struct net_device *dev);
-static int SK_open(struct net_device *dev);
-static int SK_send_packet(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t SK_interrupt(int irq, void *dev_id, struct pt_regs * regs);
-static void SK_rxintr(struct net_device *dev);
-static void SK_txintr(struct net_device *dev);
-static int SK_close(struct net_device *dev);
-
-static struct net_device_stats *SK_get_stats(struct net_device *dev);
-
-unsigned int SK_rom_addr(void);
-
-static void set_multicast_list(struct net_device *dev);
-
-/*
- * LANCE Functions
- * ---------------
- */
-
-static int SK_lance_init(struct net_device *dev, unsigned short mode);
-void SK_reset_board(void);
-void SK_set_RAP(int reg_number);
-int SK_read_reg(int reg_number);
-int SK_rread_reg(void);
-void SK_write_reg(int reg_number, int value);
-
-/*
- * Debugging functions
- * -------------------
- */
-
-void SK_print_pos(struct net_device *dev, char *text);
-void SK_print_dev(struct net_device *dev, char *text);
-void SK_print_ram(struct net_device *dev);
-
-
-/*-
- * Function : SK_init
- * Author : Patrick J.D. Weichmann
- * Date Created : 94/05/26
- *
- * Description : Check for a SK_G16 network adaptor and initialize it.
- * This function gets called by dev_init which initializes
- * all Network devices.
- *
- * Parameters : I : struct net_device *dev - structure preconfigured
- * from Space.c
- * Return Value : 0 = Driver Found and initialized
- * Errors : ENODEV - no device found
- * ENXIO - not probed
- * Globals : None
- * Update History :
- * YY/MM/DD uid Description
--*/
-
-static int io; /* 0 == probe */
-
-/*
- * Check for a network adaptor of this type, and return '0' if one exists.
- * If dev->base_addr == 0, probe all likely locations.
- * If dev->base_addr == 1, always return failure.
- */
-
-struct net_device * __init SK_init(int unit)
-{
- int *port, ports[] = SK_IO_PORTS; /* SK_G16 supported ports */
- static unsigned version_printed;
- struct net_device *dev = alloc_etherdev(sizeof(struct priv));
- int err = -ENODEV;
-
- if (!dev)
- return ERR_PTR(-ENOMEM);
-
- if (unit >= 0) {
- sprintf(dev->name, "eth%d", unit);
- netdev_boot_setup_check(dev);
- io = dev->base_addr;
- }
-
- if (version_printed++ == 0)
- PRINTK(("%s: %s", SK_NAME, rcsid));
-
- if (io > 0xff) { /* Check a single specified address */
- err = -EBUSY;
- /* Check if on specified address is a SK_G16 */
- if (request_region(io, ETHERCARD_TOTAL_SIZE, "sk_g16")) {
- err = SK_probe(dev, io);
- if (!err)
- goto got_it;
- release_region(io, ETHERCARD_TOTAL_SIZE);
- }
- } else if (io > 0) { /* Don't probe at all */
- err = -ENXIO;
- } else {
- /* Autoprobe base_addr */
- for (port = &ports[0]; *port; port++) {
- io = *port;
-
- /* Check if I/O Port region is used by another board */
- if (!request_region(io, ETHERCARD_TOTAL_SIZE, "sk_g16"))
- continue; /* Try next Port address */
-
- /* Check if at ioaddr is a SK_G16 */
- if (SK_probe(dev, io) == 0)
- goto got_it;
-
- release_region(io, ETHERCARD_TOTAL_SIZE);
- }
- }
-err_out:
- free_netdev(dev);
- return ERR_PTR(err);
-
-got_it:
- err = register_netdev(dev);
- if (err) {
- release_region(dev->base_addr, ETHERCARD_TOTAL_SIZE);
- goto err_out;
- }
- return dev;
-
-} /* End of SK_init */
-
-
-MODULE_AUTHOR("Patrick J.D. Weichmann");
-MODULE_DESCRIPTION("Schneider & Koch G16 Ethernet Device Driver");
-MODULE_LICENSE("GPL");
-MODULE_PARM(io, "i");
-MODULE_PARM_DESC(io, "0 to probe common ports (unsafe), or the I/O base of the board");
-
-
-#ifdef MODULE
-
-static struct net_device *SK_dev;
-
-static int __init SK_init_module (void)
-{
- SK_dev = SK_init(-1);
- return IS_ERR(SK_dev) ? PTR_ERR(SK_dev) : 0;
-}
-
-static void __exit SK_cleanup_module (void)
-{
- unregister_netdev(SK_dev);
- release_region(SK_dev->base_addr, ETHERCARD_TOTAL_SIZE);
- free_netdev(SK_dev);
-}
-
-module_init(SK_init_module);
-module_exit(SK_cleanup_module);
-#endif
-
-
-/*-
- * Function : SK_probe
- * Author : Patrick J.D. Weichmann
- * Date Created : 94/05/26
- *
- * Description : This function is called by SK_init and
- * does the main part of initialization.
- *
- * Parameters : I : struct net_device *dev - SK_G16 device structure
- * I : short ioaddr - I/O Port address where POS is.
- * Return Value : 0 = Initialization done
- * Errors : ENODEV - No SK_G16 found
- * -1 - Configuration problem
- * Globals : board - pointer to SK_RAM
- * Update History :
- * YY/MM/DD uid Description
- * 94/06/30 pwe SK_ADDR now checked and at the correct place
--*/
-
-int __init SK_probe(struct net_device *dev, short ioaddr)
-{
- int i,j; /* Counters */
- int sk_addr_flag = 0; /* SK ADDR correct? 1 - no, 0 - yes */
- unsigned int rom_addr; /* used to store RAM address used for POS_ADDR */
-
- struct priv *p = netdev_priv(dev); /* SK_G16 private structure */
-
- if (inb(SK_POS0) != SK_IDLOW || inb(SK_POS1) != SK_IDHIGH)
- return -ENODEV;
- dev->base_addr = ioaddr;
-
- if (SK_ADDR & 0x3fff || SK_ADDR < 0xa0000)
- {
-
- sk_addr_flag = 1;
-
- /*
- * Now here we could use a routine which searches for a free
- * place in the ram and set SK_ADDR if found. TODO.
- */
- }
-
- if (SK_BOOT_ROM) /* Shall we keep Boot_ROM on ? */
- {
- PRINTK(("## %s: SK_BOOT_ROM is set.\n", SK_NAME));
-
- rom_addr = SK_rom_addr();
-
- if (rom_addr == 0) /* No Boot_ROM found */
- {
- if (sk_addr_flag) /* No or Invalid SK_ADDR is defined */
- {
- printk("%s: SK_ADDR %#08x is not valid. Check configuration.\n",
- dev->name, SK_ADDR);
- return -1;
- }
-
- rom_addr = SK_ADDR; /* assign predefined address */
-
- PRINTK(("## %s: NO Bootrom found \n", SK_NAME));
-
- outb(SK_ROM_RAM_OFF, SK_POS2); /* Boot_ROM + RAM off */
- outb(POS_ADDR, SK_POS3); /* Set RAM address */
- outb(SK_RAM_ON, SK_POS2); /* enable RAM */
- }
- else if (rom_addr == SK_ADDR)
- {
- printk("%s: RAM + ROM are set to the same address %#08x\n"
- " Check configuration. Now switching off Boot_ROM\n",
- SK_NAME, rom_addr);
-
- outb(SK_ROM_RAM_OFF, SK_POS2); /* Boot_ROM + RAM off*/
- outb(POS_ADDR, SK_POS3); /* Set RAM address */
- outb(SK_RAM_ON, SK_POS2); /* enable RAM */
- }
- else
- {
- PRINTK(("## %s: Found ROM at %#08x\n", SK_NAME, rom_addr));
- PRINTK(("## %s: Keeping Boot_ROM on\n", SK_NAME));
-
- if (sk_addr_flag) /* No or Invalid SK_ADDR is defined */
- {
- printk("%s: SK_ADDR %#08x is not valid. Check configuration.\n",
- dev->name, SK_ADDR);
- return -1;
- }
-
- rom_addr = SK_ADDR;
-
- outb(SK_ROM_RAM_OFF, SK_POS2); /* Boot_ROM + RAM off */
- outb(POS_ADDR, SK_POS3); /* Set RAM address */
- outb(SK_ROM_RAM_ON, SK_POS2); /* RAM on, BOOT_ROM on */
- }
- }
- else /* Don't keep Boot_ROM */
- {
- PRINTK(("## %s: SK_BOOT_ROM is not set.\n", SK_NAME));
-
- if (sk_addr_flag) /* No or Invalid SK_ADDR is defined */
- {
- printk("%s: SK_ADDR %#08x is not valid. Check configuration.\n",
- dev->name, SK_ADDR);
- return -1;
- }
-
- rom_addr = SK_rom_addr(); /* Try to find a Boot_ROM */
-
- /* IF we find a Boot_ROM disable it */
-
- outb(SK_ROM_RAM_OFF, SK_POS2); /* Boot_ROM + RAM off */
-
- /* We found a Boot_ROM and it's gone. Set RAM address on
- * Boot_ROM address.
- */
-
- if (rom_addr)
- {
- printk("%s: We found Boot_ROM at %#08x. Now setting RAM on"
- "that address\n", SK_NAME, rom_addr);
-
- outb(POS_ADDR, SK_POS3); /* Set RAM on Boot_ROM address */
- }
- else /* We did not find a Boot_ROM, use predefined SK_ADDR for ram */
- {
- if (sk_addr_flag) /* No or Invalid SK_ADDR is defined */
- {
- printk("%s: SK_ADDR %#08x is not valid. Check configuration.\n",
- dev->name, SK_ADDR);
- return -1;
- }
-
- rom_addr = SK_ADDR;
-
- outb(POS_ADDR, SK_POS3); /* Set RAM address */
- }
- outb(SK_RAM_ON, SK_POS2); /* enable RAM */
- }
-
-#ifdef SK_DEBUG
- SK_print_pos(dev, "POS registers after ROM, RAM config");
-#endif
-
- board = (SK_RAM *) isa_bus_to_virt(rom_addr);
-
- /* Read in station address */
- for (i = 0, j = 0; i < ETH_ALEN; i++, j+=2)
- {
- dev->dev_addr[i] = readb(board->rom+j);
- }
-
- /* Check for manufacturer code */
- if (!(dev->dev_addr[0] == SK_MAC0 &&
- dev->dev_addr[1] == SK_MAC1 &&
- dev->dev_addr[2] == SK_MAC2) )
- {
- PRINTK(("## %s: We did not find SK_G16 at RAM location.\n",
- SK_NAME));
- return -ENODEV; /* NO SK_G16 found */
- }
-
- printk("%s: %s found at %#3x, HW addr: %#04x:%02x:%02x:%02x:%02x:%02x\n",
- dev->name,
- "Schneider & Koch Netcard",
- (unsigned int) dev->base_addr,
- dev->dev_addr[0],
- dev->dev_addr[1],
- dev->dev_addr[2],
- dev->dev_addr[3],
- dev->dev_addr[4],
- dev->dev_addr[5]);
-
- memset((char *) dev->priv, 0, sizeof(struct priv)); /* clear memory */
-
- /* Assign our Device Driver functions */
-
- dev->open = SK_open;
- dev->stop = SK_close;
- dev->hard_start_xmit = SK_send_packet;
- dev->get_stats = SK_get_stats;
- dev->set_multicast_list = set_multicast_list;
- dev->tx_timeout = SK_timeout;
- dev->watchdog_timeo = HZ/7;
-
-
- dev->flags &= ~IFF_MULTICAST;
-
- /* Initialize private structure */
-
- p->ram = (struct SK_ram *) rom_addr; /* Set dual ported RAM addr */
- p->tmdhead = &(p->ram)->tmde[0]; /* Set TMD head */
- p->rmdhead = &(p->ram)->rmde[0]; /* Set RMD head */
-
- /* Initialize buffer pointers */
-
- for (i = 0; i < TMDNUM; i++)
- {
- p->tmdbufs[i] = &(p->ram)->tmdbuf[i];
- }
-
- for (i = 0; i < RMDNUM; i++)
- {
- p->rmdbufs[i] = &(p->ram)->rmdbuf[i];
- }
-
-#ifdef SK_DEBUG
- SK_print_pos(dev, "End of SK_probe");
- SK_print_ram(dev);
-#endif
- return 0; /* Initialization done */
-} /* End of SK_probe() */
-
-
-/*-
- * Function : SK_open
- * Author : Patrick J.D. Weichmann
- * Date Created : 94/05/26
- *
- * Description : This function is called sometimes after booting
- * when ifconfig program is run.
- *
- * This function requests an IRQ, sets the correct
- * IRQ in the card. Then calls SK_lance_init() to
- * init and start the LANCE chip. Then if everything is
- * ok returns with 0 (OK), which means SK_G16 is now
- * opened and operational.
- *
- * (Called by dev_open() /net/inet/dev.c)
- *
- * Parameters : I : struct net_device *dev - SK_G16 device structure
- * Return Value : 0 - Device opened
- * Errors : -EAGAIN - Open failed
- * Side Effects : None
- * Update History :
- * YY/MM/DD uid Description
--*/
-
-static int SK_open(struct net_device *dev)
-{
- int i = 0;
- int irqval = 0;
- int ioaddr = dev->base_addr;
-
- int irqtab[] = SK_IRQS;
-
- struct priv *p = netdev_priv(dev);
-
- PRINTK(("## %s: At beginning of SK_open(). CSR0: %#06x\n",
- SK_NAME, SK_read_reg(CSR0)));
-
- if (dev->irq == 0) /* Autoirq */
- {
- i = 0;
-
- /*
- * Check if one IRQ out of SK_IRQS is free and install
- * interrupt handler.
- * Most done by request_irq().
- * irqval: 0 - interrupt handler installed for IRQ irqtab[i]
- * -EBUSY - interrupt busy
- * -EINVAL - irq > 15 or handler = NULL
- */
-
- do
- {
- irqval = request_irq(irqtab[i], &SK_interrupt, 0, "sk_g16", dev);
- i++;
- } while (irqval && irqtab[i]);
-
- if (irqval) /* We tried every possible IRQ but no success */
- {
- printk("%s: unable to get an IRQ\n", dev->name);
- return -EAGAIN;
- }
-
- dev->irq = irqtab[--i];
-
- outb(i<<2, SK_POS4); /* Set Card on probed IRQ */
-
- }
- else if (dev->irq == 2) /* IRQ2 is always IRQ9 */
- {
- if (request_irq(9, &SK_interrupt, 0, "sk_g16", dev))
- {
- printk("%s: unable to get IRQ 9\n", dev->name);
- return -EAGAIN;
- }
- dev->irq = 9;
-
- /*
- * Now we set card on IRQ2.
- * This can be confusing, but remember that IRQ2 on the network
- * card is in reality IRQ9
- */
- outb(0x08, SK_POS4); /* set card to IRQ2 */
-
- }
- else /* Check IRQ as defined in Space.c */
- {
- int i = 0;
-
- /* check if IRQ free and valid. Then install Interrupt handler */
-
- if (request_irq(dev->irq, &SK_interrupt, 0, "sk_g16", dev))
- {
- printk("%s: unable to get selected IRQ\n", dev->name);
- return -EAGAIN;
- }
-
- switch(dev->irq)
- {
- case 3: i = 0;
- break;
- case 5: i = 1;
- break;
- case 2: i = 2;
- break;
- case 11:i = 3;
- break;
- default:
- printk("%s: Preselected IRQ %d is invalid for %s boards",
- dev->name,
- dev->irq,
- SK_NAME);
- return -EAGAIN;
- }
-
- outb(i<<2, SK_POS4); /* Set IRQ on card */
- }
-
- printk("%s: Schneider & Koch G16 at %#3x, IRQ %d, shared mem at %#08x\n",
- dev->name, (unsigned int)dev->base_addr,
- (int) dev->irq, (unsigned int) p->ram);
-
- if (!(i = SK_lance_init(dev, 0))) /* LANCE init OK? */
- {
- netif_start_queue(dev);
-
-#ifdef SK_DEBUG
-
- /*
- * This debug block tries to stop LANCE,
- * reinit LANCE with transmitter and receiver disabled,
- * then stop again and reinit with NORMAL_MODE
- */
-
- printk("## %s: After lance init. CSR0: %#06x\n",
- SK_NAME, SK_read_reg(CSR0));
- SK_write_reg(CSR0, CSR0_STOP);
- printk("## %s: LANCE stopped. CSR0: %#06x\n",
- SK_NAME, SK_read_reg(CSR0));
- SK_lance_init(dev, MODE_DTX | MODE_DRX);
- printk("## %s: Reinit with DTX + DRX off. CSR0: %#06x\n",
- SK_NAME, SK_read_reg(CSR0));
- SK_write_reg(CSR0, CSR0_STOP);
- printk("## %s: LANCE stopped. CSR0: %#06x\n",
- SK_NAME, SK_read_reg(CSR0));
- SK_lance_init(dev, MODE_NORMAL);
- printk("## %s: LANCE back to normal mode. CSR0: %#06x\n",
- SK_NAME, SK_read_reg(CSR0));
- SK_print_pos(dev, "POS regs before returning OK");
-
-#endif /* SK_DEBUG */
-
- return 0; /* SK_open() is successful */
- }
- else /* LANCE init failed */
- {
-
- PRINTK(("## %s: LANCE init failed: CSR0: %#06x\n",
- SK_NAME, SK_read_reg(CSR0)));
-
- return -EAGAIN;
- }
-
-} /* End of SK_open() */
-
-
-/*-
- * Function : SK_lance_init
- * Author : Patrick J.D. Weichmann
- * Date Created : 94/05/26
- *
- * Description : Reset LANCE chip, fill RMD, TMD structures with
- * start values and Start LANCE.
- *
- * Parameters : I : struct net_device *dev - SK_G16 device structure
- * I : int mode - put LANCE into "mode" see data-sheet for
- * more info.
- * Return Value : 0 - Init done
- * Errors : -1 - Init failed
- * Update History :
- * YY/MM/DD uid Description
--*/
-
-static int SK_lance_init(struct net_device *dev, unsigned short mode)
-{
- int i;
- unsigned long flags;
- struct priv *p = netdev_priv(dev);
- struct tmd *tmdp;
- struct rmd *rmdp;
-
- PRINTK(("## %s: At beginning of LANCE init. CSR0: %#06x\n",
- SK_NAME, SK_read_reg(CSR0)));
-
- /* Reset LANCE */
- SK_reset_board();
-
- /* Initialize TMD's with start values */
- p->tmdnum = 0; /* First descriptor for transmitting */
- p->tmdlast = 0; /* First descriptor for reading stats */
-
- for (i = 0; i < TMDNUM; i++) /* Init all TMD's */
- {
- tmdp = p->tmdhead + i;
-
- writel((unsigned long) p->tmdbufs[i], tmdp->u.buffer); /* assign buffer */
-
- /* Mark TMD as start and end of packet */
- writeb(TX_STP | TX_ENP, &tmdp->u.s.status);
- }
-
-
- /* Initialize RMD's with start values */
-
- p->rmdnum = 0; /* First RMD which will be used */
-
- for (i = 0; i < RMDNUM; i++) /* Init all RMD's */
- {
- rmdp = p->rmdhead + i;
-
-
- writel((unsigned long) p->rmdbufs[i], rmdp->u.buffer); /* assign buffer */
-
- /*
- * LANCE must be owner at beginning so that he can fill in
- * receiving packets, set status and release RMD
- */
-
- writeb(RX_OWN, &rmdp->u.s.status);
-
- writew(-PKT_BUF_SZ, &rmdp->blen); /* Buffer Size (two's complement) */
-
- writeb(0, &rmdp->mlen); /* init message length */
-
- }
-
- /* Fill LANCE Initialize Block */
-
- writew(mode, (&((p->ram)->ib.mode))); /* Set operation mode */
-
- for (i = 0; i < ETH_ALEN; i++) /* Set physical address */
- {
- writeb(dev->dev_addr[i], (&((p->ram)->ib.paddr[i])));
- }
-
- for (i = 0; i < 8; i++) /* Set multicast, logical address */
- {
- writeb(0, (&((p->ram)->ib.laddr[i]))); /* We do not use logical addressing */
- }
-
- /* Set ring descriptor pointers and set number of descriptors */
-
- writel((int)p->rmdhead | RMDNUMMASK, (&((p->ram)->ib.rdrp)));
- writel((int)p->tmdhead | TMDNUMMASK, (&((p->ram)->ib.tdrp)));
-
- /* Prepare LANCE Control and Status Registers */
-
- spin_lock_irqsave(&SK_lock, flags);
-
- SK_write_reg(CSR3, CSR3_ACON); /* Ale Control !!!THIS MUST BE SET!!!! */
-
- /*
- * LANCE addresses the RAM from 0x0000 to 0x3fbf and has no access to
- * PC Memory locations.
- *
- * In structure SK_ram is defined that the first thing in ram
- * is the initialization block. So his address is for LANCE always
- * 0x0000
- *
- * CSR1 contains low order bits 15:0 of initialization block address
- * CSR2 is built of:
- * 7:0 High order bits 23:16 of initialization block address
- * 15:8 reserved, must be 0
- */
-
- /* Set initialization block address (must be on word boundary) */
- SK_write_reg(CSR1, 0); /* Set low order bits 15:0 */
- SK_write_reg(CSR2, 0); /* Set high order bits 23:16 */
-
-
- PRINTK(("## %s: After setting CSR1-3. CSR0: %#06x\n",
- SK_NAME, SK_read_reg(CSR0)));
-
- /* Initialize LANCE */
-
- /*
- * INIT = Initialize, when set, causes the LANCE to begin the
- * initialization procedure and access the Init Block.
- */
-
- SK_write_reg(CSR0, CSR0_INIT);
-
- spin_unlock_irqrestore(&SK_lock, flags);
-
- /* Wait until LANCE finished initialization */
-
- SK_set_RAP(CSR0); /* Register Address Pointer to CSR0 */
-
- for (i = 0; (i < 100) && !(SK_rread_reg() & CSR0_IDON); i++)
- ; /* Wait until init done or go ahead if problems (i>=100) */
-
- if (i >= 100) /* Something is wrong ! */
- {
- printk("%s: can't init am7990, status: %04x "
- "init_block: %#08x\n",
- dev->name, (int) SK_read_reg(CSR0),
- (unsigned int) &(p->ram)->ib);
-
-#ifdef SK_DEBUG
- SK_print_pos(dev, "LANCE INIT failed");
- SK_print_dev(dev,"Device Structure:");
-#endif
-
- return -1; /* LANCE init failed */
- }
-
- PRINTK(("## %s: init done after %d ticks\n", SK_NAME, i));
-
- /* Clear Initialize done, enable Interrupts, start LANCE */
-
- SK_write_reg(CSR0, CSR0_IDON | CSR0_INEA | CSR0_STRT);
-
- PRINTK(("## %s: LANCE started. CSR0: %#06x\n", SK_NAME,
- SK_read_reg(CSR0)));
-
- return 0; /* LANCE is up and running */
-
-} /* End of SK_lance_init() */
-
-
-
-/*-
- * Function : SK_send_packet
- * Author : Patrick J.D. Weichmann
- * Date Created : 94/05/27
- *
- * Description : Writes an socket buffer into a transmit descriptor
- * and starts transmission.
- *
- * Parameters : I : struct sk_buff *skb - packet to transfer
- * I : struct net_device *dev - SK_G16 device structure
- * Return Value : 0 - OK
- * 1 - Could not transmit (dev_queue_xmit will queue it)
- * and try to sent it later
- * Globals : None
- * Side Effects : None
- * Update History :
- * YY/MM/DD uid Description
--*/
-
-static void SK_timeout(struct net_device *dev)
-{
- printk(KERN_WARNING "%s: xmitter timed out, try to restart!\n", dev->name);
- SK_lance_init(dev, MODE_NORMAL); /* Reinit LANCE */
- netif_wake_queue(dev); /* Clear Transmitter flag */
- dev->trans_start = jiffies; /* Mark Start of transmission */
-}
-
-static int SK_send_packet(struct sk_buff *skb, struct net_device *dev)
-{
- struct priv *p = netdev_priv(dev);
- struct tmd *tmdp;
- static char pad[64];
-
- PRINTK2(("## %s: SK_send_packet() called, CSR0 %#04x.\n",
- SK_NAME, SK_read_reg(CSR0)));
-
-
- /*
- * Block a timer-based transmit from overlapping.
- * This means check if we are already in.
- */
-
- netif_stop_queue (dev);
-
- {
-
- /* Evaluate Packet length */
- short len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
-
- tmdp = p->tmdhead + p->tmdnum; /* Which descriptor for transmitting */
-
- /* Fill in Transmit Message Descriptor */
-
- /* Copy data into dual ported ram */
-
- memcpy_toio((tmdp->u.buffer & 0x00ffffff), skb->data, skb->len);
- if (len != skb->len)
- memcpy_toio((tmdp->u.buffer & 0x00ffffff) + skb->len, pad, len-skb->len);
-
- writew(-len, &tmdp->blen); /* set length to transmit */
-
- /*
- * Packet start and end is always set because we use the maximum
- * packet length as buffer length.
- * Relinquish ownership to LANCE
- */
-
- writeb(TX_OWN | TX_STP | TX_ENP, &tmdp->u.s.status);
-
- /* Start Demand Transmission */
- SK_write_reg(CSR0, CSR0_TDMD | CSR0_INEA);
-
- dev->trans_start = jiffies; /* Mark start of transmission */
-
- /* Set pointer to next transmit buffer */
- p->tmdnum++;
- p->tmdnum &= TMDNUM-1;
-
- /* Do we own the next transmit buffer ? */
- if (! (readb(&((p->tmdhead + p->tmdnum)->u.s.status)) & TX_OWN) )
- {
- /*
- * We own next buffer and are ready to transmit, so
- * clear busy flag
- */
- netif_start_queue(dev);
- }
-
- p->stats.tx_bytes += skb->len;
-
- }
-
- dev_kfree_skb(skb);
- return 0;
-} /* End of SK_send_packet */
-
-
-/*-
- * Function : SK_interrupt
- * Author : Patrick J.D. Weichmann
- * Date Created : 94/05/27
- *
- * Description : SK_G16 interrupt handler which checks for LANCE
- * Errors, handles transmit and receive interrupts
- *
- * Parameters : I : int irq, void *dev_id, struct pt_regs * regs -
- * Return Value : None
- * Errors : None
- * Globals : None
- * Side Effects : None
- * Update History :
- * YY/MM/DD uid Description
--*/
-
-static irqreturn_t SK_interrupt(int irq, void *dev_id, struct pt_regs * regs)
-{
- int csr0;
- struct net_device *dev = dev_id;
- struct priv *p = netdev_priv(dev);
-
-
- PRINTK2(("## %s: SK_interrupt(). status: %#06x\n",
- SK_NAME, SK_read_reg(CSR0)));
-
- if (dev == NULL)
- {
- printk("SK_interrupt(): IRQ %d for unknown device.\n", irq);
- }
-
- spin_lock (&SK_lock);
-
- csr0 = SK_read_reg(CSR0); /* store register for checking */
-
- /*
- * Acknowledge all of the current interrupt sources, disable
- * Interrupts (INEA = 0)
- */
-
- SK_write_reg(CSR0, csr0 & CSR0_CLRALL);
-
- if (csr0 & CSR0_ERR) /* LANCE Error */
- {
- printk("%s: error: %04x\n", dev->name, csr0);
-
- if (csr0 & CSR0_MISS) /* No place to store packet ? */
- {
- p->stats.rx_dropped++;
- }
- }
-
- if (csr0 & CSR0_RINT) /* Receive Interrupt (packet arrived) */
- {
- SK_rxintr(dev);
- }
-
- if (csr0 & CSR0_TINT) /* Transmit interrupt (packet sent) */
- {
- SK_txintr(dev);
- }
-
- SK_write_reg(CSR0, CSR0_INEA); /* Enable Interrupts */
-
- spin_unlock (&SK_lock);
- return IRQ_HANDLED;
-} /* End of SK_interrupt() */
-
-
-/*-
- * Function : SK_txintr
- * Author : Patrick J.D. Weichmann
- * Date Created : 94/05/27
- *
- * Description : After sending a packet we check status, update
- * statistics and relinquish ownership of transmit
- * descriptor ring.
- *
- * Parameters : I : struct net_device *dev - SK_G16 device structure
- * Return Value : None
- * Errors : None
- * Globals : None
- * Update History :
- * YY/MM/DD uid Description
--*/
-
-static void SK_txintr(struct net_device *dev)
-{
- int tmdstat;
- struct tmd *tmdp;
- struct priv *p = netdev_priv(dev);
-
-
- PRINTK2(("## %s: SK_txintr() status: %#06x\n",
- SK_NAME, SK_read_reg(CSR0)));
-
- tmdp = p->tmdhead + p->tmdlast; /* Which buffer we sent at last ? */
-
- /* Set next buffer */
- p->tmdlast++;
- p->tmdlast &= TMDNUM-1;
-
- tmdstat = readb(&tmdp->u.s.status);
-
- /*
- * We check status of transmitted packet.
- * see LANCE data-sheet for error explanation
- */
- if (tmdstat & TX_ERR) /* Error occurred */
- {
- int stat2 = readw(&tmdp->status2);
-
- printk("%s: TX error: %04x %04x\n", dev->name, tmdstat, stat2);
-
- if (stat2 & TX_TDR) /* TDR problems? */
- {
- printk("%s: tdr-problems \n", dev->name);
- }
-
- if (stat2 & TX_RTRY) /* Failed in 16 attempts to transmit ? */
- p->stats.tx_aborted_errors++;
- if (stat2 & TX_LCOL) /* Late collision ? */
- p->stats.tx_window_errors++;
- if (stat2 & TX_LCAR) /* Loss of Carrier ? */
- p->stats.tx_carrier_errors++;
- if (stat2 & TX_UFLO) /* Underflow error ? */
- {
- p->stats.tx_fifo_errors++;
-
- /*
- * If UFLO error occurs it will turn transmitter of.
- * So we must reinit LANCE
- */
-
- SK_lance_init(dev, MODE_NORMAL);
- }
-
- p->stats.tx_errors++;
-
- writew(0, &tmdp->status2); /* Clear error flags */
- }
- else if (tmdstat & TX_MORE) /* Collisions occurred ? */
- {
- /*
- * Here I have a problem.
- * I only know that there must be one or up to 15 collisions.
- * That's why TX_MORE is set, because after 16 attempts TX_RTRY
- * will be set which means couldn't send packet aborted transfer.
- *
- * First I did not have this in but then I thought at minimum
- * we see that something was not ok.
- * If anyone knows something better than this to handle this
- * please report it.
- */
-
- p->stats.collisions++;
- }
- else /* Packet sent without any problems */
- {
- p->stats.tx_packets++;
- }
-
- /*
- * We mark transmitter not busy anymore, because now we have a free
- * transmit descriptor which can be filled by SK_send_packet and
- * afterwards sent by the LANCE
- *
- * The function which do handle slow IRQ parts is do_bottom_half()
- * which runs at normal kernel priority, that means all interrupt are
- * enabled. (see kernel/irq.c)
- *
- * net_bh does something like this:
- * - check if already in net_bh
- * - try to transmit something from the send queue
- * - if something is in the receive queue send it up to higher
- * levels if it is a known protocol
- * - try to transmit something from the send queue
- */
-
- netif_wake_queue(dev);
-
-} /* End of SK_txintr() */
-
-
-/*-
- * Function : SK_rxintr
- * Author : Patrick J.D. Weichmann
- * Date Created : 94/05/27
- *
- * Description : Buffer sent, check for errors, relinquish ownership
- * of the receive message descriptor.
- *
- * Parameters : I : SK_G16 device structure
- * Return Value : None
- * Globals : None
- * Update History :
- * YY/MM/DD uid Description
--*/
-
-static void SK_rxintr(struct net_device *dev)
-{
-
- struct rmd *rmdp;
- int rmdstat;
- struct priv *p = netdev_priv(dev);
-
- PRINTK2(("## %s: SK_rxintr(). CSR0: %#06x\n",
- SK_NAME, SK_read_reg(CSR0)));
-
- rmdp = p->rmdhead + p->rmdnum;
-
- /* As long as we own the next entry, check status and send
- * it up to higher layer
- */
-
- while (!( (rmdstat = readb(&rmdp->u.s.status)) & RX_OWN))
- {
- /*
- * Start and end of packet must be set, because we use
- * the ethernet maximum packet length (1518) as buffer size.
- *
- * Because our buffers are at maximum OFLO and BUFF errors are
- * not to be concerned (see Data sheet)
- */
-
- if ((rmdstat & (RX_STP | RX_ENP)) != (RX_STP | RX_ENP))
- {
- /* Start of a frame > 1518 Bytes ? */
-
- if (rmdstat & RX_STP)
- {
- p->stats.rx_errors++; /* bad packet received */
- p->stats.rx_length_errors++; /* packet too long */
-
- printk("%s: packet too long\n", dev->name);
- }
-
- /*
- * All other packets will be ignored until a new frame with
- * start (RX_STP) set follows.
- *
- * What we do is just give descriptor free for new incoming
- * packets.
- */
-
- writeb(RX_OWN, &rmdp->u.s.status); /* Relinquish ownership to LANCE */
-
- }
- else if (rmdstat & RX_ERR) /* Receive Error ? */
- {
- printk("%s: RX error: %04x\n", dev->name, (int) rmdstat);
-
- p->stats.rx_errors++;
-
- if (rmdstat & RX_FRAM) p->stats.rx_frame_errors++;
- if (rmdstat & RX_CRC) p->stats.rx_crc_errors++;
-
- writeb(RX_OWN, &rmdp->u.s.status); /* Relinquish ownership to LANCE */
-
- }
- else /* We have a packet which can be queued for the upper layers */
- {
-
- int len = readw(&rmdp->mlen) & 0x0fff; /* extract message length from receive buffer */
- struct sk_buff *skb;
-
- skb = dev_alloc_skb(len+2); /* allocate socket buffer */
-
- if (skb == NULL) /* Could not get mem ? */
- {
-
- /*
- * Couldn't allocate sk_buffer so we give descriptor back
- * to Lance, update statistics and go ahead.
- */
-
- writeb(RX_OWN, &rmdp->u.s.status); /* Relinquish ownership to LANCE */
- printk("%s: Couldn't allocate sk_buff, deferring packet.\n",
- dev->name);
- p->stats.rx_dropped++;
-
- break; /* Jump out */
- }
-
- /* Prepare sk_buff to queue for upper layers */
-
- skb->dev = dev;
- skb_reserve(skb,2); /* Align IP header on 16 byte boundary */
-
- /*
- * Copy data out of our receive descriptor into sk_buff.
- *
- * (rmdp->u.buffer & 0x00ffffff) -> get address of buffer and
- * ignore status fields)
- */
-
- memcpy_fromio(skb_put(skb,len), (rmdp->u.buffer & 0x00ffffff), len);
-
-
- /*
- * Notify the upper protocol layers that there is another packet
- * to handle
- *
- * netif_rx() always succeeds. see /net/inet/dev.c for more.
- */
-
- skb->protocol=eth_type_trans(skb,dev);
- netif_rx(skb); /* queue packet and mark it for processing */
-
- /*
- * Packet is queued and marked for processing so we
- * free our descriptor and update statistics
- */
-
- writeb(RX_OWN, &rmdp->u.s.status);
- dev->last_rx = jiffies;
- p->stats.rx_packets++;
- p->stats.rx_bytes += len;
-
-
- p->rmdnum++;
- p->rmdnum %= RMDNUM;
-
- rmdp = p->rmdhead + p->rmdnum;
- }
- }
-} /* End of SK_rxintr() */
-
-
-/*-
- * Function : SK_close
- * Author : Patrick J.D. Weichmann
- * Date Created : 94/05/26
- *
- * Description : close gets called from dev_close() and should
- * deinstall the card (free_irq, mem etc).
- *
- * Parameters : I : struct net_device *dev - our device structure
- * Return Value : 0 - closed device driver
- * Errors : None
- * Globals : None
- * Update History :
- * YY/MM/DD uid Description
--*/
-
-/* I have tried to set BOOT_ROM on and RAM off but then, after a 'ifconfig
- * down' the system stops. So I don't shut set card to init state.
- */
-
-static int SK_close(struct net_device *dev)
-{
-
- PRINTK(("## %s: SK_close(). CSR0: %#06x\n",
- SK_NAME, SK_read_reg(CSR0)));
-
- netif_stop_queue(dev); /* Transmitter busy */
-
- printk("%s: Shutting %s down CSR0 %#06x\n", dev->name, SK_NAME,
- (int) SK_read_reg(CSR0));
-
- SK_write_reg(CSR0, CSR0_STOP); /* STOP the LANCE */
-
- free_irq(dev->irq, dev); /* Free IRQ */
-
- return 0; /* always succeed */
-
-} /* End of SK_close() */
-
-
-/*-
- * Function : SK_get_stats
- * Author : Patrick J.D. Weichmann
- * Date Created : 94/05/26
- *
- * Description : Return current status structure to upper layers.
- * It is called by sprintf_stats (dev.c).
- *
- * Parameters : I : struct net_device *dev - our device structure
- * Return Value : struct net_device_stats * - our current statistics
- * Errors : None
- * Side Effects : None
- * Update History :
- * YY/MM/DD uid Description
--*/
-
-static struct net_device_stats *SK_get_stats(struct net_device *dev)
-{
-
- struct priv *p = netdev_priv(dev);
-
- PRINTK(("## %s: SK_get_stats(). CSR0: %#06x\n",
- SK_NAME, SK_read_reg(CSR0)));
-
- return &p->stats; /* Return Device status */
-
-} /* End of SK_get_stats() */
-
-
-/*-
- * Function : set_multicast_list
- * Author : Patrick J.D. Weichmann
- * Date Created : 94/05/26
- *
- * Description : This function gets called when a program performs
- * a SIOCSIFFLAGS call. Ifconfig does this if you call
- * 'ifconfig [-]allmulti' which enables or disables the
- * Promiscuous mode.
- * Promiscuous mode is when the Network card accepts all
- * packets, not only the packets which match our MAC
- * Address. It is useful for writing a network monitor,
- * but it is also a security problem. You have to remember
- * that all information on the net is not encrypted.
- *
- * Parameters : I : struct net_device *dev - SK_G16 device Structure
- * Return Value : None
- * Errors : None
- * Globals : None
- * Update History :
- * YY/MM/DD uid Description
- * 95/10/18 ACox New multicast calling scheme
--*/
-
-
-/* Set or clear the multicast filter for SK_G16.
- */
-
-static void set_multicast_list(struct net_device *dev)
-{
-
- if (dev->flags&IFF_PROMISC)
- {
- /* Reinitialize LANCE with MODE_PROM set */
- SK_lance_init(dev, MODE_PROM);
- }
- else if (dev->mc_count==0 && !(dev->flags&IFF_ALLMULTI))
- {
- /* Reinitialize LANCE without MODE_PROM */
- SK_lance_init(dev, MODE_NORMAL);
- }
- else
- {
- /* Multicast with logical address filter on */
- /* Reinitialize LANCE without MODE_PROM */
- SK_lance_init(dev, MODE_NORMAL);
-
- /* Not implemented yet. */
- }
-} /* End of set_multicast_list() */
-
-
-
-/*-
- * Function : SK_rom_addr
- * Author : Patrick J.D. Weichmann
- * Date Created : 94/06/01
- *
- * Description : Try to find a Boot_ROM at all possible locations
- *
- * Parameters : None
- * Return Value : Address where Boot_ROM is
- * Errors : 0 - Did not find Boot_ROM
- * Globals : None
- * Update History :
- * YY/MM/DD uid Description
--*/
-
-unsigned int __init SK_rom_addr(void)
-{
- int i,j;
- int rom_found = 0;
- unsigned int rom_location[] = SK_BOOT_ROM_LOCATIONS;
- unsigned char rom_id[] = SK_BOOT_ROM_ID;
- unsigned char test_byte;
-
- /* Autodetect Boot_ROM */
- PRINTK(("## %s: Autodetection of Boot_ROM\n", SK_NAME));
-
- for (i = 0; (rom_location[i] != 0) && (rom_found == 0); i++)
- {
-
- PRINTK(("## Trying ROM location %#08x", rom_location[i]));
-
- rom_found = 1;
- for (j = 0; j < 6; j++)
- {
- test_byte = readb(rom_location[i]+j);
- PRINTK((" %02x ", *test_byte));
-
- if(test_byte != rom_id[j])
- {
- rom_found = 0;
- }
- }
- PRINTK(("\n"));
- }
-
- if (rom_found == 1)
- {
- PRINTK(("## %s: Boot_ROM found at %#08x\n",
- SK_NAME, rom_location[(i-1)]));
-
- return (rom_location[--i]);
- }
- else
- {
- PRINTK(("%s: No Boot_ROM found\n", SK_NAME));
- return 0;
- }
-} /* End of SK_rom_addr() */
-
-
-
-/* LANCE access functions
- *
- * ! CSR1-3 can only be accessed when in CSR0 the STOP bit is set !
- */
-
-
-/*-
- * Function : SK_reset_board
- *
- * Author : Patrick J.D. Weichmann
- *
- * Date Created : 94/05/25
- *
- * Description : This function resets SK_G16 and all components, but
- * POS registers are not changed
- *
- * Parameters : None
- * Return Value : None
- * Errors : None
- * Globals : SK_RAM *board - SK_RAM structure pointer
- *
- * Update History :
- * YY/MM/DD uid Description
--*/
-
-void SK_reset_board(void)
-{
- writeb(0x00, SK_PORT); /* Reset active */
- mdelay(5); /* Delay min 5ms */
- writeb(SK_RESET, SK_PORT); /* Set back to normal operation */
-
-} /* End of SK_reset_board() */
-
-
-/*-
- * Function : SK_set_RAP
- * Author : Patrick J.D. Weichmann
- * Date Created : 94/05/25
- *
- * Description : Set LANCE Register Address Port to register
- * for later data transfer.
- *
- * Parameters : I : reg_number - which CSR to read/write from/to
- * Return Value : None
- * Errors : None
- * Globals : SK_RAM *board - SK_RAM structure pointer
- * Update History :
- * YY/MM/DD uid Description
--*/
-
-void SK_set_RAP(int reg_number)
-{
- writew(reg_number, SK_IOREG);
- writeb(SK_RESET | SK_RAP | SK_WREG, SK_PORT);
- writeb(SK_DOIO, SK_IOCOM);
-
- while (readb(SK_PORT) & SK_IORUN)
- barrier();
-} /* End of SK_set_RAP() */
-
-
-/*-
- * Function : SK_read_reg
- * Author : Patrick J.D. Weichmann
- * Date Created : 94/05/25
- *
- * Description : Set RAP and read data from a LANCE CSR register
- *
- * Parameters : I : reg_number - which CSR to read from
- * Return Value : Register contents
- * Errors : None
- * Globals : SK_RAM *board - SK_RAM structure pointer
- * Update History :
- * YY/MM/DD uid Description
--*/
-
-int SK_read_reg(int reg_number)
-{
- SK_set_RAP(reg_number);
-
- writeb(SK_RESET | SK_RDATA | SK_RREG, SK_PORT);
- writeb(SK_DOIO, SK_IOCOM);
-
- while (readb(SK_PORT) & SK_IORUN)
- barrier();
- return (readw(SK_IOREG));
-
-} /* End of SK_read_reg() */
-
-
-/*-
- * Function : SK_rread_reg
- * Author : Patrick J.D. Weichmann
- * Date Created : 94/05/28
- *
- * Description : Read data from preseted register.
- * This function requires that you know which
- * Register is actually set. Be aware that CSR1-3
- * can only be accessed when in CSR0 STOP is set.
- *
- * Return Value : Register contents
- * Errors : None
- * Globals : SK_RAM *board - SK_RAM structure pointer
- * Update History :
- * YY/MM/DD uid Description
--*/
-
-int SK_rread_reg(void)
-{
- writeb(SK_RESET | SK_RDATA | SK_RREG, SK_PORT);
-
- writeb(SK_DOIO, SK_IOCOM);
-
- while (readb(SK_PORT) & SK_IORUN)
- barrier();
- return (readw(SK_IOREG));
-
-} /* End of SK_rread_reg() */
-
-
-/*-
- * Function : SK_write_reg
- * Author : Patrick J.D. Weichmann
- * Date Created : 94/05/25
- *
- * Description : This function sets the RAP then fills in the
- * LANCE I/O Reg and starts Transfer to LANCE.
- * It waits until transfer has ended which is max. 7 ms
- * and then it returns.
- *
- * Parameters : I : reg_number - which CSR to write to
- * I : value - what value to fill into register
- * Return Value : None
- * Errors : None
- * Globals : SK_RAM *board - SK_RAM structure pointer
- * Update History :
- * YY/MM/DD uid Description
--*/
-
-void SK_write_reg(int reg_number, int value)
-{
- SK_set_RAP(reg_number);
-
- writew(value, SK_IOREG);
- writeb(SK_RESET | SK_RDATA | SK_WREG, SK_PORT);
- writeb(SK_DOIO, SK_IOCOM);
-
- while (readb(SK_PORT) & SK_IORUN)
- barrier();
-} /* End of SK_write_reg */
-
-
-
-/*
- * Debugging functions
- * -------------------
- */
-
-/*-
- * Function : SK_print_pos
- * Author : Patrick J.D. Weichmann
- * Date Created : 94/05/25
- *
- * Description : This function prints out the 4 POS (Programmable
- * Option Select) Registers. Used mainly to debug operation.
- *
- * Parameters : I : struct net_device *dev - SK_G16 device structure
- * I : char * - Text which will be printed as title
- * Return Value : None
- * Errors : None
- * Update History :
- * YY/MM/DD uid Description
--*/
-
-void SK_print_pos(struct net_device *dev, char *text)
-{
- int ioaddr = dev->base_addr;
-
- unsigned char pos0 = inb(SK_POS0),
- pos1 = inb(SK_POS1),
- pos2 = inb(SK_POS2),
- pos3 = inb(SK_POS3),
- pos4 = inb(SK_POS4);
-
-
- printk("## %s: %s.\n"
- "## pos0=%#4x pos1=%#4x pos2=%#04x pos3=%#08x pos4=%#04x\n",
- SK_NAME, text, pos0, pos1, pos2, (pos3<<14), pos4);
-
-} /* End of SK_print_pos() */
-
-
-
-/*-
- * Function : SK_print_dev
- * Author : Patrick J.D. Weichmann
- * Date Created : 94/05/25
- *
- * Description : This function simply prints out the important fields
- * of the device structure.
- *
- * Parameters : I : struct net_device *dev - SK_G16 device structure
- * I : char *text - Title for printing
- * Return Value : None
- * Errors : None
- * Update History :
- * YY/MM/DD uid Description
--*/
-
-void SK_print_dev(struct net_device *dev, char *text)
-{
- if (dev == NULL)
- {
- printk("## %s: Device Structure. %s\n", SK_NAME, text);
- printk("## DEVICE == NULL\n");
- }
- else
- {
- printk("## %s: Device Structure. %s\n", SK_NAME, text);
- printk("## Device Name: %s Base Address: %#06lx IRQ: %d\n",
- dev->name, dev->base_addr, dev->irq);
-
- printk("## next device: %#08x init function: %#08x\n",
- (int) dev->next, (int) dev->init);
- }
-
-} /* End of SK_print_dev() */
-
-
-
-/*-
- * Function : SK_print_ram
- * Author : Patrick J.D. Weichmann
- * Date Created : 94/06/02
- *
- * Description : This function is used to check how are things set up
- * in the 16KB RAM. Also the pointers to the receive and
- * transmit descriptor rings and rx and tx buffers locations.
- * It contains a minor bug in printing, but has no effect to the values
- * only newlines are not correct.
- *
- * Parameters : I : struct net_device *dev - SK_G16 device structure
- * Return Value : None
- * Errors : None
- * Globals : None
- * Update History :
- * YY/MM/DD uid Description
--*/
-
-void __init SK_print_ram(struct net_device *dev)
-{
-
- int i;
- struct priv *p = netdev_priv(dev);
-
- printk("## %s: RAM Details.\n"
- "## RAM at %#08x tmdhead: %#08x rmdhead: %#08x initblock: %#08x\n",
- SK_NAME,
- (unsigned int) p->ram,
- (unsigned int) p->tmdhead,
- (unsigned int) p->rmdhead,
- (unsigned int) &(p->ram)->ib);
-
- printk("## ");
-
- for(i = 0; i < TMDNUM; i++)
- {
- if (!(i % 3)) /* Every third line do a newline */
- {
- printk("\n## ");
- }
- printk("tmdbufs%d: %#08x ", (i+1), (int) p->tmdbufs[i]);
- }
- printk("## ");
-
- for(i = 0; i < RMDNUM; i++)
- {
- if (!(i % 3)) /* Every third line do a newline */
- {
- printk("\n## ");
- }
- printk("rmdbufs%d: %#08x ", (i+1), (int) p->rmdbufs[i]);
- }
- printk("\n");
-
-} /* End of SK_print_ram() */
-
diff --git a/drivers/net/sk_g16.h b/drivers/net/sk_g16.h
deleted file mode 100644
index 0a5dc0908a0..00000000000
--- a/drivers/net/sk_g16.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/*-
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * Module : sk_g16.h
- * Version : $Revision$
- *
- * Author : M.Hipp (mhipp@student.uni-tuebingen.de)
- * changes by : Patrick J.D. Weichmann
- *
- * Date Created : 94/05/25
- *
- * Description : In here are all necessary definitions of
- * the am7990 (LANCE) chip used for writing a
- * network device driver which uses this chip
- *
- * $Log$
--*/
-
-#ifndef SK_G16_H
-
-#define SK_G16_H
-
-
-/*
- * Control and Status Register 0 (CSR0) bit definitions
- *
- * (R=Readable) (W=Writeable) (S=Set on write) (C-Clear on write)
- *
- */
-
-#define CSR0_ERR 0x8000 /* Error summary (R) */
-#define CSR0_BABL 0x4000 /* Babble transmitter timeout error (RC) */
-#define CSR0_CERR 0x2000 /* Collision Error (RC) */
-#define CSR0_MISS 0x1000 /* Missed packet (RC) */
-#define CSR0_MERR 0x0800 /* Memory Error (RC) */
-#define CSR0_RINT 0x0400 /* Receiver Interrupt (RC) */
-#define CSR0_TINT 0x0200 /* Transmit Interrupt (RC) */
-#define CSR0_IDON 0x0100 /* Initialization Done (RC) */
-#define CSR0_INTR 0x0080 /* Interrupt Flag (R) */
-#define CSR0_INEA 0x0040 /* Interrupt Enable (RW) */
-#define CSR0_RXON 0x0020 /* Receiver on (R) */
-#define CSR0_TXON 0x0010 /* Transmitter on (R) */
-#define CSR0_TDMD 0x0008 /* Transmit Demand (RS) */
-#define CSR0_STOP 0x0004 /* Stop (RS) */
-#define CSR0_STRT 0x0002 /* Start (RS) */
-#define CSR0_INIT 0x0001 /* Initialize (RS) */
-
-#define CSR0_CLRALL 0x7f00 /* mask for all clearable bits */
-
-/*
- * Control and Status Register 3 (CSR3) bit definitions
- *
- */
-
-#define CSR3_BSWAP 0x0004 /* Byte Swap (RW) */
-#define CSR3_ACON 0x0002 /* ALE Control (RW) */
-#define CSR3_BCON 0x0001 /* Byte Control (RW) */
-
-/*
- * Initialization Block Mode operation Bit Definitions.
- */
-
-#define MODE_PROM 0x8000 /* Promiscuous Mode */
-#define MODE_INTL 0x0040 /* Internal Loopback */
-#define MODE_DRTY 0x0020 /* Disable Retry */
-#define MODE_COLL 0x0010 /* Force Collision */
-#define MODE_DTCR 0x0008 /* Disable Transmit CRC) */
-#define MODE_LOOP 0x0004 /* Loopback */
-#define MODE_DTX 0x0002 /* Disable the Transmitter */
-#define MODE_DRX 0x0001 /* Disable the Receiver */
-
-#define MODE_NORMAL 0x0000 /* Normal operation mode */
-
-/*
- * Receive message descriptor status bit definitions.
- */
-
-#define RX_OWN 0x80 /* Owner bit 0 = host, 1 = lance */
-#define RX_ERR 0x40 /* Error Summary */
-#define RX_FRAM 0x20 /* Framing Error */
-#define RX_OFLO 0x10 /* Overflow Error */
-#define RX_CRC 0x08 /* CRC Error */
-#define RX_BUFF 0x04 /* Buffer Error */
-#define RX_STP 0x02 /* Start of Packet */
-#define RX_ENP 0x01 /* End of Packet */
-
-
-/*
- * Transmit message descriptor status bit definitions.
- */
-
-#define TX_OWN 0x80 /* Owner bit 0 = host, 1 = lance */
-#define TX_ERR 0x40 /* Error Summary */
-#define TX_MORE 0x10 /* More the 1 retry needed to Xmit */
-#define TX_ONE 0x08 /* One retry needed to Xmit */
-#define TX_DEF 0x04 /* Deferred */
-#define TX_STP 0x02 /* Start of Packet */
-#define TX_ENP 0x01 /* End of Packet */
-
-/*
- * Transmit status (2) (valid if TX_ERR == 1)
- */
-
-#define TX_BUFF 0x8000 /* Buffering error (no ENP) */
-#define TX_UFLO 0x4000 /* Underflow (late memory) */
-#define TX_LCOL 0x1000 /* Late collision */
-#define TX_LCAR 0x0400 /* Loss of Carrier */
-#define TX_RTRY 0x0200 /* Failed after 16 retransmissions */
-#define TX_TDR 0x003f /* Time-domain-reflectometer-value */
-
-
-/*
- * Structures used for Communication with the LANCE
- */
-
-/* LANCE Initialize Block */
-
-struct init_block
-{
- unsigned short mode; /* Mode Register */
- unsigned char paddr[6]; /* Physical Address (MAC) */
- unsigned char laddr[8]; /* Logical Filter Address (not used) */
- unsigned int rdrp; /* Receive Descriptor Ring pointer */
- unsigned int tdrp; /* Transmit Descriptor Ring pointer */
-};
-
-
-/* Receive Message Descriptor Entry */
-
-struct rmd
-{
- union
- {
- unsigned long buffer; /* Address of buffer */
- struct
- {
- unsigned char unused[3];
- unsigned volatile char status; /* Status Bits */
- } s;
- } u;
- volatile short blen; /* Buffer Length (two's complement) */
- unsigned short mlen; /* Message Byte Count */
-};
-
-
-/* Transmit Message Descriptor Entry */
-
-struct tmd
-{
- union
- {
- unsigned long buffer; /* Address of buffer */
- struct
- {
- unsigned char unused[3];
- unsigned volatile char status; /* Status Bits */
- } s;
- } u;
- unsigned short blen; /* Buffer Length (two's complement) */
- unsigned volatile short status2; /* Error Status Bits */
-};
-
-#endif /* End of SK_G16_H */
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
new file mode 100644
index 00000000000..30e8d589d16
--- /dev/null
+++ b/drivers/net/skge.c
@@ -0,0 +1,3386 @@
+/*
+ * New driver for Marvell Yukon chipset and SysKonnect Gigabit
+ * Ethernet adapters. Based on earlier sk98lin, e100 and
+ * FreeBSD if_sk drivers.
+ *
+ * This driver intentionally does not support all the features
+ * of the original driver such as link fail-over and link management because
+ * those should be done at higher levels.
+ *
+ * Copyright (C) 2004, Stephen Hemminger <shemminger@osdl.org>
+ *
+ * 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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/pci.h>
+#include <linux/if_vlan.h>
+#include <linux/ip.h>
+#include <linux/delay.h>
+#include <linux/crc32.h>
+#include <linux/dma-mapping.h>
+#include <asm/irq.h>
+
+#include "skge.h"
+
+#define DRV_NAME "skge"
+#define DRV_VERSION "0.6"
+#define PFX DRV_NAME " "
+
+#define DEFAULT_TX_RING_SIZE 128
+#define DEFAULT_RX_RING_SIZE 512
+#define MAX_TX_RING_SIZE 1024
+#define MAX_RX_RING_SIZE 4096
+#define PHY_RETRIES 1000
+#define ETH_JUMBO_MTU 9000
+#define TX_WATCHDOG (5 * HZ)
+#define NAPI_WEIGHT 64
+#define BLINK_HZ (HZ/4)
+#define LINK_POLL_HZ (HZ/10)
+
+MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver");
+MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+static const u32 default_msg
+ = NETIF_MSG_DRV| NETIF_MSG_PROBE| NETIF_MSG_LINK
+ | NETIF_MSG_IFUP| NETIF_MSG_IFDOWN;
+
+static int debug = -1; /* defaults above */
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
+static const struct pci_device_id skge_id_table[] = {
+ { PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940B,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_SYSKONNECT, 0x9E00, /* SK-9Exx */
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_MARVELL, 0x4320, /* Gigabit Ethernet Controller */
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_MARVELL, 0x5005, /* Marvell (11ab), Belkin */
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_CNET, PCI_DEVICE_ID_CNET_GIGACARD,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1032,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1064,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, skge_id_table);
+
+static int skge_up(struct net_device *dev);
+static int skge_down(struct net_device *dev);
+static void skge_tx_clean(struct skge_port *skge);
+static void skge_xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val);
+static void skge_gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val);
+static void genesis_get_stats(struct skge_port *skge, u64 *data);
+static void yukon_get_stats(struct skge_port *skge, u64 *data);
+static void yukon_init(struct skge_hw *hw, int port);
+static void yukon_reset(struct skge_hw *hw, int port);
+static void genesis_mac_init(struct skge_hw *hw, int port);
+static void genesis_reset(struct skge_hw *hw, int port);
+
+static const int txqaddr[] = { Q_XA1, Q_XA2 };
+static const int rxqaddr[] = { Q_R1, Q_R2 };
+static const u32 rxirqmask[] = { IS_R1_F, IS_R2_F };
+static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F };
+
+/* Don't need to look at whole 16K.
+ * last interesting register is descriptor poll timer.
+ */
+#define SKGE_REGS_LEN (29*128)
+
+static int skge_get_regs_len(struct net_device *dev)
+{
+ return SKGE_REGS_LEN;
+}
+
+/*
+ * Returns copy of control register region
+ * I/O region is divided into banks and certain regions are unreadable
+ */
+static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs,
+ void *p)
+{
+ const struct skge_port *skge = netdev_priv(dev);
+ unsigned long offs;
+ const void __iomem *io = skge->hw->regs;
+ static const unsigned long bankmap
+ = (1<<0) | (1<<2) | (1<<8) | (1<<9)
+ | (1<<12) | (1<<13) | (1<<14) | (1<<15) | (1<<16)
+ | (1<<17) | (1<<20) | (1<<21) | (1<<22) | (1<<23)
+ | (1<<24) | (1<<25) | (1<<26) | (1<<27) | (1<<28);
+
+ regs->version = 1;
+ for (offs = 0; offs < regs->len; offs += 128) {
+ u32 len = min_t(u32, 128, regs->len - offs);
+
+ if (bankmap & (1<<(offs/128)))
+ memcpy_fromio(p + offs, io + offs, len);
+ else
+ memset(p + offs, 0, len);
+ }
+}
+
+/* Wake on Lan only supported on Yukon chps with rev 1 or above */
+static int wol_supported(const struct skge_hw *hw)
+{
+ return !((hw->chip_id == CHIP_ID_GENESIS ||
+ (hw->chip_id == CHIP_ID_YUKON && chip_rev(hw) == 0)));
+}
+
+static void skge_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct skge_port *skge = netdev_priv(dev);
+
+ wol->supported = wol_supported(skge->hw) ? WAKE_MAGIC : 0;
+ wol->wolopts = skge->wol ? WAKE_MAGIC : 0;
+}
+
+static int skge_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct skge_hw *hw = skge->hw;
+
+ if(wol->wolopts != WAKE_MAGIC && wol->wolopts != 0)
+ return -EOPNOTSUPP;
+
+ if (wol->wolopts == WAKE_MAGIC && !wol_supported(hw))
+ return -EOPNOTSUPP;
+
+ skge->wol = wol->wolopts == WAKE_MAGIC;
+
+ if (skge->wol) {
+ memcpy_toio(hw->regs + WOL_MAC_ADDR, dev->dev_addr, ETH_ALEN);
+
+ skge_write16(hw, WOL_CTRL_STAT,
+ WOL_CTL_ENA_PME_ON_MAGIC_PKT |
+ WOL_CTL_ENA_MAGIC_PKT_UNIT);
+ } else
+ skge_write16(hw, WOL_CTRL_STAT, WOL_CTL_DEFAULT);
+
+ return 0;
+}
+
+
+static int skge_get_settings(struct net_device *dev,
+ struct ethtool_cmd *ecmd)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct skge_hw *hw = skge->hw;
+
+ ecmd->transceiver = XCVR_INTERNAL;
+
+ if (iscopper(hw)) {
+ if (hw->chip_id == CHIP_ID_GENESIS)
+ ecmd->supported = SUPPORTED_1000baseT_Full
+ | SUPPORTED_1000baseT_Half
+ | SUPPORTED_Autoneg | SUPPORTED_TP;
+ else {
+ ecmd->supported = SUPPORTED_10baseT_Half
+ | SUPPORTED_10baseT_Full
+ | SUPPORTED_100baseT_Half
+ | SUPPORTED_100baseT_Full
+ | SUPPORTED_1000baseT_Half
+ | SUPPORTED_1000baseT_Full
+ | SUPPORTED_Autoneg| SUPPORTED_TP;
+
+ if (hw->chip_id == CHIP_ID_YUKON)
+ ecmd->supported &= ~SUPPORTED_1000baseT_Half;
+
+ else if (hw->chip_id == CHIP_ID_YUKON_FE)
+ ecmd->supported &= ~(SUPPORTED_1000baseT_Half
+ | SUPPORTED_1000baseT_Full);
+ }
+
+ ecmd->port = PORT_TP;
+ ecmd->phy_address = hw->phy_addr;
+ } else {
+ ecmd->supported = SUPPORTED_1000baseT_Full
+ | SUPPORTED_FIBRE
+ | SUPPORTED_Autoneg;
+
+ ecmd->port = PORT_FIBRE;
+ }
+
+ ecmd->advertising = skge->advertising;
+ ecmd->autoneg = skge->autoneg;
+ ecmd->speed = skge->speed;
+ ecmd->duplex = skge->duplex;
+ return 0;
+}
+
+static u32 skge_modes(const struct skge_hw *hw)
+{
+ u32 modes = ADVERTISED_Autoneg
+ | ADVERTISED_1000baseT_Full | ADVERTISED_1000baseT_Half
+ | ADVERTISED_100baseT_Full | ADVERTISED_100baseT_Half
+ | ADVERTISED_10baseT_Full | ADVERTISED_10baseT_Half;
+
+ if (iscopper(hw)) {
+ modes |= ADVERTISED_TP;
+ switch(hw->chip_id) {
+ case CHIP_ID_GENESIS:
+ modes &= ~(ADVERTISED_100baseT_Full
+ | ADVERTISED_100baseT_Half
+ | ADVERTISED_10baseT_Full
+ | ADVERTISED_10baseT_Half);
+ break;
+
+ case CHIP_ID_YUKON:
+ modes &= ~ADVERTISED_1000baseT_Half;
+ break;
+
+ case CHIP_ID_YUKON_FE:
+ modes &= ~(ADVERTISED_1000baseT_Half|ADVERTISED_1000baseT_Full);
+ break;
+ }
+ } else {
+ modes |= ADVERTISED_FIBRE;
+ modes &= ~ADVERTISED_1000baseT_Half;
+ }
+ return modes;
+}
+
+static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ const struct skge_hw *hw = skge->hw;
+
+ if (ecmd->autoneg == AUTONEG_ENABLE) {
+ if (ecmd->advertising & skge_modes(hw))
+ return -EINVAL;
+ } else {
+ switch(ecmd->speed) {
+ case SPEED_1000:
+ if (hw->chip_id == CHIP_ID_YUKON_FE)
+ return -EINVAL;
+ break;
+ case SPEED_100:
+ case SPEED_10:
+ if (iscopper(hw) || hw->chip_id == CHIP_ID_GENESIS)
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ skge->autoneg = ecmd->autoneg;
+ skge->speed = ecmd->speed;
+ skge->duplex = ecmd->duplex;
+ skge->advertising = ecmd->advertising;
+
+ if (netif_running(dev)) {
+ skge_down(dev);
+ skge_up(dev);
+ }
+ return (0);
+}
+
+static void skge_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ struct skge_port *skge = netdev_priv(dev);
+
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+ strcpy(info->fw_version, "N/A");
+ strcpy(info->bus_info, pci_name(skge->hw->pdev));
+}
+
+static const struct skge_stat {
+ char name[ETH_GSTRING_LEN];
+ u16 xmac_offset;
+ u16 gma_offset;
+} skge_stats[] = {
+ { "tx_bytes", XM_TXO_OK_HI, GM_TXO_OK_HI },
+ { "rx_bytes", XM_RXO_OK_HI, GM_RXO_OK_HI },
+
+ { "tx_broadcast", XM_TXF_BC_OK, GM_TXF_BC_OK },
+ { "rx_broadcast", XM_RXF_BC_OK, GM_RXF_BC_OK },
+ { "tx_multicast", XM_TXF_MC_OK, GM_TXF_MC_OK },
+ { "rx_multicast", XM_RXF_MC_OK, GM_RXF_MC_OK },
+ { "tx_unicast", XM_TXF_UC_OK, GM_TXF_UC_OK },
+ { "rx_unicast", XM_RXF_UC_OK, GM_RXF_UC_OK },
+ { "tx_mac_pause", XM_TXF_MPAUSE, GM_TXF_MPAUSE },
+ { "rx_mac_pause", XM_RXF_MPAUSE, GM_RXF_MPAUSE },
+
+ { "collisions", XM_TXF_SNG_COL, GM_TXF_SNG_COL },
+ { "multi_collisions", XM_TXF_MUL_COL, GM_TXF_MUL_COL },
+ { "aborted", XM_TXF_ABO_COL, GM_TXF_ABO_COL },
+ { "late_collision", XM_TXF_LAT_COL, GM_TXF_LAT_COL },
+ { "fifo_underrun", XM_TXE_FIFO_UR, GM_TXE_FIFO_UR },
+ { "fifo_overflow", XM_RXE_FIFO_OV, GM_RXE_FIFO_OV },
+
+ { "rx_toolong", XM_RXF_LNG_ERR, GM_RXF_LNG_ERR },
+ { "rx_jabber", XM_RXF_JAB_PKT, GM_RXF_JAB_PKT },
+ { "rx_runt", XM_RXE_RUNT, GM_RXE_FRAG },
+ { "rx_too_long", XM_RXF_LNG_ERR, GM_RXF_LNG_ERR },
+ { "rx_fcs_error", XM_RXF_FCS_ERR, GM_RXF_FCS_ERR },
+};
+
+static int skge_get_stats_count(struct net_device *dev)
+{
+ return ARRAY_SIZE(skge_stats);
+}
+
+static void skge_get_ethtool_stats(struct net_device *dev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ struct skge_port *skge = netdev_priv(dev);
+
+ if (skge->hw->chip_id == CHIP_ID_GENESIS)
+ genesis_get_stats(skge, data);
+ else
+ yukon_get_stats(skge, data);
+}
+
+/* Use hardware MIB variables for critical path statistics and
+ * transmit feedback not reported at interrupt.
+ * Other errors are accounted for in interrupt handler.
+ */
+static struct net_device_stats *skge_get_stats(struct net_device *dev)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ u64 data[ARRAY_SIZE(skge_stats)];
+
+ if (skge->hw->chip_id == CHIP_ID_GENESIS)
+ genesis_get_stats(skge, data);
+ else
+ yukon_get_stats(skge, data);
+
+ skge->net_stats.tx_bytes = data[0];
+ skge->net_stats.rx_bytes = data[1];
+ skge->net_stats.tx_packets = data[2] + data[4] + data[6];
+ skge->net_stats.rx_packets = data[3] + data[5] + data[7];
+ skge->net_stats.multicast = data[5] + data[7];
+ skge->net_stats.collisions = data[10];
+ skge->net_stats.tx_aborted_errors = data[12];
+
+ return &skge->net_stats;
+}
+
+static void skge_get_strings(struct net_device *dev, u32 stringset, u8 *data)
+{
+ int i;
+
+ switch(stringset) {
+ case ETH_SS_STATS:
+ for (i = 0; i < ARRAY_SIZE(skge_stats); i++)
+ memcpy(data + i * ETH_GSTRING_LEN,
+ skge_stats[i].name, ETH_GSTRING_LEN);
+ break;
+ }
+}
+
+static void skge_get_ring_param(struct net_device *dev,
+ struct ethtool_ringparam *p)
+{
+ struct skge_port *skge = netdev_priv(dev);
+
+ p->rx_max_pending = MAX_RX_RING_SIZE;
+ p->tx_max_pending = MAX_TX_RING_SIZE;
+ p->rx_mini_max_pending = 0;
+ p->rx_jumbo_max_pending = 0;
+
+ p->rx_pending = skge->rx_ring.count;
+ p->tx_pending = skge->tx_ring.count;
+ p->rx_mini_pending = 0;
+ p->rx_jumbo_pending = 0;
+}
+
+static int skge_set_ring_param(struct net_device *dev,
+ struct ethtool_ringparam *p)
+{
+ struct skge_port *skge = netdev_priv(dev);
+
+ if (p->rx_pending == 0 || p->rx_pending > MAX_RX_RING_SIZE ||
+ p->tx_pending == 0 || p->tx_pending > MAX_TX_RING_SIZE)
+ return -EINVAL;
+
+ skge->rx_ring.count = p->rx_pending;
+ skge->tx_ring.count = p->tx_pending;
+
+ if (netif_running(dev)) {
+ skge_down(dev);
+ skge_up(dev);
+ }
+
+ return 0;
+}
+
+static u32 skge_get_msglevel(struct net_device *netdev)
+{
+ struct skge_port *skge = netdev_priv(netdev);
+ return skge->msg_enable;
+}
+
+static void skge_set_msglevel(struct net_device *netdev, u32 value)
+{
+ struct skge_port *skge = netdev_priv(netdev);
+ skge->msg_enable = value;
+}
+
+static int skge_nway_reset(struct net_device *dev)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+
+ if (skge->autoneg != AUTONEG_ENABLE || !netif_running(dev))
+ return -EINVAL;
+
+ spin_lock_bh(&hw->phy_lock);
+ if (hw->chip_id == CHIP_ID_GENESIS) {
+ genesis_reset(hw, port);
+ genesis_mac_init(hw, port);
+ } else {
+ yukon_reset(hw, port);
+ yukon_init(hw, port);
+ }
+ spin_unlock_bh(&hw->phy_lock);
+ return 0;
+}
+
+static int skge_set_sg(struct net_device *dev, u32 data)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct skge_hw *hw = skge->hw;
+
+ if (hw->chip_id == CHIP_ID_GENESIS && data)
+ return -EOPNOTSUPP;
+ return ethtool_op_set_sg(dev, data);
+}
+
+static int skge_set_tx_csum(struct net_device *dev, u32 data)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct skge_hw *hw = skge->hw;
+
+ if (hw->chip_id == CHIP_ID_GENESIS && data)
+ return -EOPNOTSUPP;
+
+ return ethtool_op_set_tx_csum(dev, data);
+}
+
+static u32 skge_get_rx_csum(struct net_device *dev)
+{
+ struct skge_port *skge = netdev_priv(dev);
+
+ return skge->rx_csum;
+}
+
+/* Only Yukon supports checksum offload. */
+static int skge_set_rx_csum(struct net_device *dev, u32 data)
+{
+ struct skge_port *skge = netdev_priv(dev);
+
+ if (skge->hw->chip_id == CHIP_ID_GENESIS && data)
+ return -EOPNOTSUPP;
+
+ skge->rx_csum = data;
+ return 0;
+}
+
+/* Only Yukon II supports TSO (not implemented yet) */
+static int skge_set_tso(struct net_device *dev, u32 data)
+{
+ if (data)
+ return -EOPNOTSUPP;
+ return 0;
+}
+
+static void skge_get_pauseparam(struct net_device *dev,
+ struct ethtool_pauseparam *ecmd)
+{
+ struct skge_port *skge = netdev_priv(dev);
+
+ ecmd->tx_pause = (skge->flow_control == FLOW_MODE_LOC_SEND)
+ || (skge->flow_control == FLOW_MODE_SYMMETRIC);
+ ecmd->rx_pause = (skge->flow_control == FLOW_MODE_REM_SEND)
+ || (skge->flow_control == FLOW_MODE_SYMMETRIC);
+
+ ecmd->autoneg = skge->autoneg;
+}
+
+static int skge_set_pauseparam(struct net_device *dev,
+ struct ethtool_pauseparam *ecmd)
+{
+ struct skge_port *skge = netdev_priv(dev);
+
+ skge->autoneg = ecmd->autoneg;
+ if (ecmd->rx_pause && ecmd->tx_pause)
+ skge->flow_control = FLOW_MODE_SYMMETRIC;
+ else if(ecmd->rx_pause && !ecmd->tx_pause)
+ skge->flow_control = FLOW_MODE_REM_SEND;
+ else if(!ecmd->rx_pause && ecmd->tx_pause)
+ skge->flow_control = FLOW_MODE_LOC_SEND;
+ else
+ skge->flow_control = FLOW_MODE_NONE;
+
+ if (netif_running(dev)) {
+ skge_down(dev);
+ skge_up(dev);
+ }
+ return 0;
+}
+
+/* Chip internal frequency for clock calculations */
+static inline u32 hwkhz(const struct skge_hw *hw)
+{
+ if (hw->chip_id == CHIP_ID_GENESIS)
+ return 53215; /* or: 53.125 MHz */
+ else if (hw->chip_id == CHIP_ID_YUKON_EC)
+ return 125000; /* or: 125.000 MHz */
+ else
+ return 78215; /* or: 78.125 MHz */
+}
+
+/* Chip hz to microseconds */
+static inline u32 skge_clk2usec(const struct skge_hw *hw, u32 ticks)
+{
+ return (ticks * 1000) / hwkhz(hw);
+}
+
+/* Microseconds to chip hz */
+static inline u32 skge_usecs2clk(const struct skge_hw *hw, u32 usec)
+{
+ return hwkhz(hw) * usec / 1000;
+}
+
+static int skge_get_coalesce(struct net_device *dev,
+ struct ethtool_coalesce *ecmd)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+
+ ecmd->rx_coalesce_usecs = 0;
+ ecmd->tx_coalesce_usecs = 0;
+
+ if (skge_read32(hw, B2_IRQM_CTRL) & TIM_START) {
+ u32 delay = skge_clk2usec(hw, skge_read32(hw, B2_IRQM_INI));
+ u32 msk = skge_read32(hw, B2_IRQM_MSK);
+
+ if (msk & rxirqmask[port])
+ ecmd->rx_coalesce_usecs = delay;
+ if (msk & txirqmask[port])
+ ecmd->tx_coalesce_usecs = delay;
+ }
+
+ return 0;
+}
+
+/* Note: interrupt timer is per board, but can turn on/off per port */
+static int skge_set_coalesce(struct net_device *dev,
+ struct ethtool_coalesce *ecmd)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+ u32 msk = skge_read32(hw, B2_IRQM_MSK);
+ u32 delay = 25;
+
+ if (ecmd->rx_coalesce_usecs == 0)
+ msk &= ~rxirqmask[port];
+ else if (ecmd->rx_coalesce_usecs < 25 ||
+ ecmd->rx_coalesce_usecs > 33333)
+ return -EINVAL;
+ else {
+ msk |= rxirqmask[port];
+ delay = ecmd->rx_coalesce_usecs;
+ }
+
+ if (ecmd->tx_coalesce_usecs == 0)
+ msk &= ~txirqmask[port];
+ else if (ecmd->tx_coalesce_usecs < 25 ||
+ ecmd->tx_coalesce_usecs > 33333)
+ return -EINVAL;
+ else {
+ msk |= txirqmask[port];
+ delay = min(delay, ecmd->rx_coalesce_usecs);
+ }
+
+ skge_write32(hw, B2_IRQM_MSK, msk);
+ if (msk == 0)
+ skge_write32(hw, B2_IRQM_CTRL, TIM_STOP);
+ else {
+ skge_write32(hw, B2_IRQM_INI, skge_usecs2clk(hw, delay));
+ skge_write32(hw, B2_IRQM_CTRL, TIM_START);
+ }
+ return 0;
+}
+
+static void skge_led_on(struct skge_hw *hw, int port)
+{
+ if (hw->chip_id == CHIP_ID_GENESIS) {
+ skge_write8(hw, SKGEMAC_REG(port, LNK_LED_REG), LINKLED_ON);
+ skge_write8(hw, B0_LED, LED_STAT_ON);
+
+ skge_write8(hw, SKGEMAC_REG(port, RX_LED_TST), LED_T_ON);
+ skge_write32(hw, SKGEMAC_REG(port, RX_LED_VAL), 100);
+ skge_write8(hw, SKGEMAC_REG(port, RX_LED_CTRL), LED_START);
+
+ switch (hw->phy_type) {
+ case SK_PHY_BCOM:
+ skge_xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL,
+ PHY_B_PEC_LED_ON);
+ break;
+ case SK_PHY_LONE:
+ skge_xm_phy_write(hw, port, PHY_LONE_LED_CFG,
+ 0x0800);
+ break;
+ default:
+ skge_write8(hw, SKGEMAC_REG(port, TX_LED_TST), LED_T_ON);
+ skge_write32(hw, SKGEMAC_REG(port, TX_LED_VAL), 100);
+ skge_write8(hw, SKGEMAC_REG(port, TX_LED_CTRL), LED_START);
+ }
+ } else {
+ skge_gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
+ skge_gm_phy_write(hw, port, PHY_MARV_LED_OVER,
+ PHY_M_LED_MO_DUP(MO_LED_ON) |
+ PHY_M_LED_MO_10(MO_LED_ON) |
+ PHY_M_LED_MO_100(MO_LED_ON) |
+ PHY_M_LED_MO_1000(MO_LED_ON) |
+ PHY_M_LED_MO_RX(MO_LED_ON));
+ }
+}
+
+static void skge_led_off(struct skge_hw *hw, int port)
+{
+ if (hw->chip_id == CHIP_ID_GENESIS) {
+ skge_write8(hw, SKGEMAC_REG(port, LNK_LED_REG), LINKLED_OFF);
+ skge_write8(hw, B0_LED, LED_STAT_OFF);
+
+ skge_write32(hw, SKGEMAC_REG(port, RX_LED_VAL), 0);
+ skge_write8(hw, SKGEMAC_REG(port, RX_LED_CTRL), LED_T_OFF);
+
+ switch (hw->phy_type) {
+ case SK_PHY_BCOM:
+ skge_xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL,
+ PHY_B_PEC_LED_OFF);
+ break;
+ case SK_PHY_LONE:
+ skge_xm_phy_write(hw, port, PHY_LONE_LED_CFG,
+ PHY_L_LC_LEDT);
+ break;
+ default:
+ skge_write32(hw, SKGEMAC_REG(port, TX_LED_VAL), 0);
+ skge_write8(hw, SKGEMAC_REG(port, TX_LED_CTRL), LED_T_OFF);
+ }
+ } else {
+ skge_gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
+ skge_gm_phy_write(hw, port, PHY_MARV_LED_OVER,
+ PHY_M_LED_MO_DUP(MO_LED_OFF) |
+ PHY_M_LED_MO_10(MO_LED_OFF) |
+ PHY_M_LED_MO_100(MO_LED_OFF) |
+ PHY_M_LED_MO_1000(MO_LED_OFF) |
+ PHY_M_LED_MO_RX(MO_LED_OFF));
+ }
+}
+
+static void skge_blink_timer(unsigned long data)
+{
+ struct skge_port *skge = (struct skge_port *) data;
+ struct skge_hw *hw = skge->hw;
+ unsigned long flags;
+
+ spin_lock_irqsave(&hw->phy_lock, flags);
+ if (skge->blink_on)
+ skge_led_on(hw, skge->port);
+ else
+ skge_led_off(hw, skge->port);
+ spin_unlock_irqrestore(&hw->phy_lock, flags);
+
+ skge->blink_on = !skge->blink_on;
+ mod_timer(&skge->led_blink, jiffies + BLINK_HZ);
+}
+
+/* blink LED's for finding board */
+static int skge_phys_id(struct net_device *dev, u32 data)
+{
+ struct skge_port *skge = netdev_priv(dev);
+
+ if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
+ data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
+
+ /* start blinking */
+ skge->blink_on = 1;
+ mod_timer(&skge->led_blink, jiffies+1);
+
+ msleep_interruptible(data * 1000);
+ del_timer_sync(&skge->led_blink);
+
+ skge_led_off(skge->hw, skge->port);
+
+ return 0;
+}
+
+static struct ethtool_ops skge_ethtool_ops = {
+ .get_settings = skge_get_settings,
+ .set_settings = skge_set_settings,
+ .get_drvinfo = skge_get_drvinfo,
+ .get_regs_len = skge_get_regs_len,
+ .get_regs = skge_get_regs,
+ .get_wol = skge_get_wol,
+ .set_wol = skge_set_wol,
+ .get_msglevel = skge_get_msglevel,
+ .set_msglevel = skge_set_msglevel,
+ .nway_reset = skge_nway_reset,
+ .get_link = ethtool_op_get_link,
+ .get_ringparam = skge_get_ring_param,
+ .set_ringparam = skge_set_ring_param,
+ .get_pauseparam = skge_get_pauseparam,
+ .set_pauseparam = skge_set_pauseparam,
+ .get_coalesce = skge_get_coalesce,
+ .set_coalesce = skge_set_coalesce,
+ .get_tso = ethtool_op_get_tso,
+ .set_tso = skge_set_tso,
+ .get_sg = ethtool_op_get_sg,
+ .set_sg = skge_set_sg,
+ .get_tx_csum = ethtool_op_get_tx_csum,
+ .set_tx_csum = skge_set_tx_csum,
+ .get_rx_csum = skge_get_rx_csum,
+ .set_rx_csum = skge_set_rx_csum,
+ .get_strings = skge_get_strings,
+ .phys_id = skge_phys_id,
+ .get_stats_count = skge_get_stats_count,
+ .get_ethtool_stats = skge_get_ethtool_stats,
+};
+
+/*
+ * Allocate ring elements and chain them together
+ * One-to-one association of board descriptors with ring elements
+ */
+static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u64 base)
+{
+ struct skge_tx_desc *d;
+ struct skge_element *e;
+ int i;
+
+ ring->start = kmalloc(sizeof(*e)*ring->count, GFP_KERNEL);
+ if (!ring->start)
+ return -ENOMEM;
+
+ for (i = 0, e = ring->start, d = vaddr; i < ring->count; i++, e++, d++) {
+ e->desc = d;
+ if (i == ring->count - 1) {
+ e->next = ring->start;
+ d->next_offset = base;
+ } else {
+ e->next = e + 1;
+ d->next_offset = base + (i+1) * sizeof(*d);
+ }
+ }
+ ring->to_use = ring->to_clean = ring->start;
+
+ return 0;
+}
+
+/* Setup buffer for receiving */
+static inline int skge_rx_alloc(struct skge_port *skge,
+ struct skge_element *e)
+{
+ unsigned long bufsize = skge->netdev->mtu + ETH_HLEN; /* VLAN? */
+ struct skge_rx_desc *rd = e->desc;
+ struct sk_buff *skb;
+ u64 map;
+
+ skb = dev_alloc_skb(bufsize + NET_IP_ALIGN);
+ if (unlikely(!skb)) {
+ printk(KERN_DEBUG PFX "%s: out of memory for receive\n",
+ skge->netdev->name);
+ return -ENOMEM;
+ }
+
+ skb->dev = skge->netdev;
+ skb_reserve(skb, NET_IP_ALIGN);
+
+ map = pci_map_single(skge->hw->pdev, skb->data, bufsize,
+ PCI_DMA_FROMDEVICE);
+
+ rd->dma_lo = map;
+ rd->dma_hi = map >> 32;
+ e->skb = skb;
+ rd->csum1_start = ETH_HLEN;
+ rd->csum2_start = ETH_HLEN;
+ rd->csum1 = 0;
+ rd->csum2 = 0;
+
+ wmb();
+
+ rd->control = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | bufsize;
+ pci_unmap_addr_set(e, mapaddr, map);
+ pci_unmap_len_set(e, maplen, bufsize);
+ return 0;
+}
+
+/* Free all unused buffers in receive ring, assumes receiver stopped */
+static void skge_rx_clean(struct skge_port *skge)
+{
+ struct skge_hw *hw = skge->hw;
+ struct skge_ring *ring = &skge->rx_ring;
+ struct skge_element *e;
+
+ for (e = ring->to_clean; e != ring->to_use; e = e->next) {
+ struct skge_rx_desc *rd = e->desc;
+ rd->control = 0;
+
+ pci_unmap_single(hw->pdev,
+ pci_unmap_addr(e, mapaddr),
+ pci_unmap_len(e, maplen),
+ PCI_DMA_FROMDEVICE);
+ dev_kfree_skb(e->skb);
+ e->skb = NULL;
+ }
+ ring->to_clean = e;
+}
+
+/* Allocate buffers for receive ring
+ * For receive: to_use is refill location
+ * to_clean is next received frame.
+ *
+ * if (to_use == to_clean)
+ * then ring all frames in ring need buffers
+ * if (to_use->next == to_clean)
+ * then ring all frames in ring have buffers
+ */
+static int skge_rx_fill(struct skge_port *skge)
+{
+ struct skge_ring *ring = &skge->rx_ring;
+ struct skge_element *e;
+ int ret = 0;
+
+ for (e = ring->to_use; e->next != ring->to_clean; e = e->next) {
+ if (skge_rx_alloc(skge, e)) {
+ ret = 1;
+ break;
+ }
+
+ }
+ ring->to_use = e;
+
+ return ret;
+}
+
+static void skge_link_up(struct skge_port *skge)
+{
+ netif_carrier_on(skge->netdev);
+ if (skge->tx_avail > MAX_SKB_FRAGS + 1)
+ netif_wake_queue(skge->netdev);
+
+ if (netif_msg_link(skge))
+ printk(KERN_INFO PFX
+ "%s: Link is up at %d Mbps, %s duplex, flow control %s\n",
+ skge->netdev->name, skge->speed,
+ skge->duplex == DUPLEX_FULL ? "full" : "half",
+ (skge->flow_control == FLOW_MODE_NONE) ? "none" :
+ (skge->flow_control == FLOW_MODE_LOC_SEND) ? "tx only" :
+ (skge->flow_control == FLOW_MODE_REM_SEND) ? "rx only" :
+ (skge->flow_control == FLOW_MODE_SYMMETRIC) ? "tx and rx" :
+ "unknown");
+}
+
+static void skge_link_down(struct skge_port *skge)
+{
+ netif_carrier_off(skge->netdev);
+ netif_stop_queue(skge->netdev);
+
+ if (netif_msg_link(skge))
+ printk(KERN_INFO PFX "%s: Link is down.\n", skge->netdev->name);
+}
+
+static u16 skge_xm_phy_read(struct skge_hw *hw, int port, u16 reg)
+{
+ int i;
+ u16 v;
+
+ skge_xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr);
+ v = skge_xm_read16(hw, port, XM_PHY_DATA);
+ if (hw->phy_type != SK_PHY_XMAC) {
+ for (i = 0; i < PHY_RETRIES; i++) {
+ udelay(1);
+ if (skge_xm_read16(hw, port, XM_MMU_CMD)
+ & XM_MMU_PHY_RDY)
+ goto ready;
+ }
+
+ printk(KERN_WARNING PFX "%s: phy read timed out\n",
+ hw->dev[port]->name);
+ return 0;
+ ready:
+ v = skge_xm_read16(hw, port, XM_PHY_DATA);
+ }
+
+ return v;
+}
+
+static void skge_xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val)
+{
+ int i;
+
+ skge_xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr);
+ for (i = 0; i < PHY_RETRIES; i++) {
+ if (!(skge_xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_BUSY))
+ goto ready;
+ cpu_relax();
+ }
+ printk(KERN_WARNING PFX "%s: phy write failed to come ready\n",
+ hw->dev[port]->name);
+
+
+ ready:
+ skge_xm_write16(hw, port, XM_PHY_DATA, val);
+ for (i = 0; i < PHY_RETRIES; i++) {
+ udelay(1);
+ if (!(skge_xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_BUSY))
+ return;
+ }
+ printk(KERN_WARNING PFX "%s: phy write timed out\n",
+ hw->dev[port]->name);
+}
+
+static void genesis_init(struct skge_hw *hw)
+{
+ /* set blink source counter */
+ skge_write32(hw, B2_BSC_INI, (SK_BLK_DUR * SK_FACT_53) / 100);
+ skge_write8(hw, B2_BSC_CTRL, BSC_START);
+
+ /* configure mac arbiter */
+ skge_write16(hw, B3_MA_TO_CTRL, MA_RST_CLR);
+
+ /* configure mac arbiter timeout values */
+ skge_write8(hw, B3_MA_TOINI_RX1, SK_MAC_TO_53);
+ skge_write8(hw, B3_MA_TOINI_RX2, SK_MAC_TO_53);
+ skge_write8(hw, B3_MA_TOINI_TX1, SK_MAC_TO_53);
+ skge_write8(hw, B3_MA_TOINI_TX2, SK_MAC_TO_53);
+
+ skge_write8(hw, B3_MA_RCINI_RX1, 0);
+ skge_write8(hw, B3_MA_RCINI_RX2, 0);
+ skge_write8(hw, B3_MA_RCINI_TX1, 0);
+ skge_write8(hw, B3_MA_RCINI_TX2, 0);
+
+ /* configure packet arbiter timeout */
+ skge_write16(hw, B3_PA_CTRL, PA_RST_CLR);
+ skge_write16(hw, B3_PA_TOINI_RX1, SK_PKT_TO_MAX);
+ skge_write16(hw, B3_PA_TOINI_TX1, SK_PKT_TO_MAX);
+ skge_write16(hw, B3_PA_TOINI_RX2, SK_PKT_TO_MAX);
+ skge_write16(hw, B3_PA_TOINI_TX2, SK_PKT_TO_MAX);
+}
+
+static void genesis_reset(struct skge_hw *hw, int port)
+{
+ int i;
+ u64 zero = 0;
+
+ /* reset the statistics module */
+ skge_xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT);
+ skge_xm_write16(hw, port, XM_IMSK, 0xffff); /* disable XMAC IRQs */
+ skge_xm_write32(hw, port, XM_MODE, 0); /* clear Mode Reg */
+ skge_xm_write16(hw, port, XM_TX_CMD, 0); /* reset TX CMD Reg */
+ skge_xm_write16(hw, port, XM_RX_CMD, 0); /* reset RX CMD Reg */
+
+ /* disable all PHY IRQs */
+ if (hw->phy_type == SK_PHY_BCOM)
+ skge_xm_write16(hw, port, PHY_BCOM_INT_MASK, 0xffff);
+
+ skge_xm_outhash(hw, port, XM_HSM, (u8 *) &zero);
+ for (i = 0; i < 15; i++)
+ skge_xm_outaddr(hw, port, XM_EXM(i), (u8 *) &zero);
+ skge_xm_outhash(hw, port, XM_SRC_CHK, (u8 *) &zero);
+}
+
+
+static void genesis_mac_init(struct skge_hw *hw, int port)
+{
+ struct skge_port *skge = netdev_priv(hw->dev[port]);
+ int i;
+ u32 r;
+ u16 id1;
+ u16 ctrl1, ctrl2, ctrl3, ctrl4, ctrl5;
+
+ /* magic workaround patterns for Broadcom */
+ static const struct {
+ u16 reg;
+ u16 val;
+ } A1hack[] = {
+ { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 },
+ { 0x17, 0x0013 }, { 0x15, 0x0404 }, { 0x17, 0x8006 },
+ { 0x15, 0x0132 }, { 0x17, 0x8006 }, { 0x15, 0x0232 },
+ { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 },
+ }, C0hack[] = {
+ { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 },
+ { 0x17, 0x0013 }, { 0x15, 0x0A04 }, { 0x18, 0x0420 },
+ };
+
+
+ /* initialize Rx, Tx and Link LED */
+ skge_write8(hw, SKGEMAC_REG(port, LNK_LED_REG), LINKLED_ON);
+ skge_write8(hw, SKGEMAC_REG(port, LNK_LED_REG), LINKLED_LINKSYNC_ON);
+
+ skge_write8(hw, SKGEMAC_REG(port, RX_LED_CTRL), LED_START);
+ skge_write8(hw, SKGEMAC_REG(port, TX_LED_CTRL), LED_START);
+
+ /* Unreset the XMAC. */
+ skge_write16(hw, SKGEMAC_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
+
+ /*
+ * Perform additional initialization for external PHYs,
+ * namely for the 1000baseTX cards that use the XMAC's
+ * GMII mode.
+ */
+ spin_lock_bh(&hw->phy_lock);
+ if (hw->phy_type != SK_PHY_XMAC) {
+ /* Take PHY out of reset. */
+ r = skge_read32(hw, B2_GP_IO);
+ if (port == 0)
+ r |= GP_DIR_0|GP_IO_0;
+ else
+ r |= GP_DIR_2|GP_IO_2;
+
+ skge_write32(hw, B2_GP_IO, r);
+ skge_read32(hw, B2_GP_IO);
+
+ /* Enable GMII mode on the XMAC. */
+ skge_xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD);
+
+ id1 = skge_xm_phy_read(hw, port, PHY_XMAC_ID1);
+
+ /* Optimize MDIO transfer by suppressing preamble. */
+ skge_xm_write16(hw, port, XM_MMU_CMD,
+ skge_xm_read16(hw, port, XM_MMU_CMD)
+ | XM_MMU_NO_PRE);
+
+ if (id1 == PHY_BCOM_ID1_C0) {
+ /*
+ * Workaround BCOM Errata for the C0 type.
+ * Write magic patterns to reserved registers.
+ */
+ for (i = 0; i < ARRAY_SIZE(C0hack); i++)
+ skge_xm_phy_write(hw, port,
+ C0hack[i].reg, C0hack[i].val);
+
+ } else if (id1 == PHY_BCOM_ID1_A1) {
+ /*
+ * Workaround BCOM Errata for the A1 type.
+ * Write magic patterns to reserved registers.
+ */
+ for (i = 0; i < ARRAY_SIZE(A1hack); i++)
+ skge_xm_phy_write(hw, port,
+ A1hack[i].reg, A1hack[i].val);
+ }
+
+ /*
+ * Workaround BCOM Errata (#10523) for all BCom PHYs.
+ * Disable Power Management after reset.
+ */
+ r = skge_xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL);
+ skge_xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL, r | PHY_B_AC_DIS_PM);
+ }
+
+ /* Dummy read */
+ skge_xm_read16(hw, port, XM_ISRC);
+
+ r = skge_xm_read32(hw, port, XM_MODE);
+ skge_xm_write32(hw, port, XM_MODE, r|XM_MD_CSA);
+
+ /* We don't need the FCS appended to the packet. */
+ r = skge_xm_read16(hw, port, XM_RX_CMD);
+ skge_xm_write16(hw, port, XM_RX_CMD, r | XM_RX_STRIP_FCS);
+
+ /* We want short frames padded to 60 bytes. */
+ r = skge_xm_read16(hw, port, XM_TX_CMD);
+ skge_xm_write16(hw, port, XM_TX_CMD, r | XM_TX_AUTO_PAD);
+
+ /*
+ * Enable the reception of all error frames. This is is
+ * a necessary evil due to the design of the XMAC. The
+ * XMAC's receive FIFO is only 8K in size, however jumbo
+ * frames can be up to 9000 bytes in length. When bad
+ * frame filtering is enabled, the XMAC's RX FIFO operates
+ * in 'store and forward' mode. For this to work, the
+ * entire frame has to fit into the FIFO, but that means
+ * that jumbo frames larger than 8192 bytes will be
+ * truncated. Disabling all bad frame filtering causes
+ * the RX FIFO to operate in streaming mode, in which
+ * case the XMAC will start transfering frames out of the
+ * RX FIFO as soon as the FIFO threshold is reached.
+ */
+ r = skge_xm_read32(hw, port, XM_MODE);
+ skge_xm_write32(hw, port, XM_MODE,
+ XM_MD_RX_CRCE|XM_MD_RX_LONG|XM_MD_RX_RUNT|
+ XM_MD_RX_ERR|XM_MD_RX_IRLE);
+
+ skge_xm_outaddr(hw, port, XM_SA, hw->dev[port]->dev_addr);
+ skge_xm_outaddr(hw, port, XM_EXM(0), hw->dev[port]->dev_addr);
+
+ /*
+ * Bump up the transmit threshold. This helps hold off transmit
+ * underruns when we're blasting traffic from both ports at once.
+ */
+ skge_xm_write16(hw, port, XM_TX_THR, 512);
+
+ /* Configure MAC arbiter */
+ skge_write16(hw, B3_MA_TO_CTRL, MA_RST_CLR);
+
+ /* configure timeout values */
+ skge_write8(hw, B3_MA_TOINI_RX1, 72);
+ skge_write8(hw, B3_MA_TOINI_RX2, 72);
+ skge_write8(hw, B3_MA_TOINI_TX1, 72);
+ skge_write8(hw, B3_MA_TOINI_TX2, 72);
+
+ skge_write8(hw, B3_MA_RCINI_RX1, 0);
+ skge_write8(hw, B3_MA_RCINI_RX2, 0);
+ skge_write8(hw, B3_MA_RCINI_TX1, 0);
+ skge_write8(hw, B3_MA_RCINI_TX2, 0);
+
+ /* Configure Rx MAC FIFO */
+ skge_write8(hw, SKGEMAC_REG(port, RX_MFF_CTRL2), MFF_RST_CLR);
+ skge_write16(hw, SKGEMAC_REG(port, RX_MFF_CTRL1), MFF_ENA_TIM_PAT);
+ skge_write8(hw, SKGEMAC_REG(port, RX_MFF_CTRL2), MFF_ENA_OP_MD);
+
+ /* Configure Tx MAC FIFO */
+ skge_write8(hw, SKGEMAC_REG(port, TX_MFF_CTRL2), MFF_RST_CLR);
+ skge_write16(hw, SKGEMAC_REG(port, TX_MFF_CTRL1), MFF_TX_CTRL_DEF);
+ skge_write8(hw, SKGEMAC_REG(port, TX_MFF_CTRL2), MFF_ENA_OP_MD);
+
+ if (hw->dev[port]->mtu > ETH_DATA_LEN) {
+ /* Enable frame flushing if jumbo frames used */
+ skge_write16(hw, SKGEMAC_REG(port,RX_MFF_CTRL1), MFF_ENA_FLUSH);
+ } else {
+ /* enable timeout timers if normal frames */
+ skge_write16(hw, B3_PA_CTRL,
+ port == 0 ? PA_ENA_TO_TX1 : PA_ENA_TO_TX2);
+ }
+
+
+ r = skge_xm_read16(hw, port, XM_RX_CMD);
+ if (hw->dev[port]->mtu > ETH_DATA_LEN)
+ skge_xm_write16(hw, port, XM_RX_CMD, r | XM_RX_BIG_PK_OK);
+ else
+ skge_xm_write16(hw, port, XM_RX_CMD, r & ~(XM_RX_BIG_PK_OK));
+
+ switch (hw->phy_type) {
+ case SK_PHY_XMAC:
+ if (skge->autoneg == AUTONEG_ENABLE) {
+ ctrl1 = PHY_X_AN_FD | PHY_X_AN_HD;
+
+ switch (skge->flow_control) {
+ case FLOW_MODE_NONE:
+ ctrl1 |= PHY_X_P_NO_PAUSE;
+ break;
+ case FLOW_MODE_LOC_SEND:
+ ctrl1 |= PHY_X_P_ASYM_MD;
+ break;
+ case FLOW_MODE_SYMMETRIC:
+ ctrl1 |= PHY_X_P_SYM_MD;
+ break;
+ case FLOW_MODE_REM_SEND:
+ ctrl1 |= PHY_X_P_BOTH_MD;
+ break;
+ }
+
+ skge_xm_phy_write(hw, port, PHY_XMAC_AUNE_ADV, ctrl1);
+ ctrl2 = PHY_CT_ANE | PHY_CT_RE_CFG;
+ } else {
+ ctrl2 = 0;
+ if (skge->duplex == DUPLEX_FULL)
+ ctrl2 |= PHY_CT_DUP_MD;
+ }
+
+ skge_xm_phy_write(hw, port, PHY_XMAC_CTRL, ctrl2);
+ break;
+
+ case SK_PHY_BCOM:
+ ctrl1 = PHY_CT_SP1000;
+ ctrl2 = 0;
+ ctrl3 = PHY_SEL_TYPE;
+ ctrl4 = PHY_B_PEC_EN_LTR;
+ ctrl5 = PHY_B_AC_TX_TST;
+
+ if (skge->autoneg == AUTONEG_ENABLE) {
+ /*
+ * Workaround BCOM Errata #1 for the C5 type.
+ * 1000Base-T Link Acquisition Failure in Slave Mode
+ * Set Repeater/DTE bit 10 of the 1000Base-T Control Register
+ */
+ ctrl2 |= PHY_B_1000C_RD;
+ if (skge->advertising & ADVERTISED_1000baseT_Half)
+ ctrl2 |= PHY_B_1000C_AHD;
+ if (skge->advertising & ADVERTISED_1000baseT_Full)
+ ctrl2 |= PHY_B_1000C_AFD;
+
+ /* Set Flow-control capabilities */
+ switch (skge->flow_control) {
+ case FLOW_MODE_NONE:
+ ctrl3 |= PHY_B_P_NO_PAUSE;
+ break;
+ case FLOW_MODE_LOC_SEND:
+ ctrl3 |= PHY_B_P_ASYM_MD;
+ break;
+ case FLOW_MODE_SYMMETRIC:
+ ctrl3 |= PHY_B_P_SYM_MD;
+ break;
+ case FLOW_MODE_REM_SEND:
+ ctrl3 |= PHY_B_P_BOTH_MD;
+ break;
+ }
+
+ /* Restart Auto-negotiation */
+ ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG;
+ } else {
+ if (skge->duplex == DUPLEX_FULL)
+ ctrl1 |= PHY_CT_DUP_MD;
+
+ ctrl2 |= PHY_B_1000C_MSE; /* set it to Slave */
+ }
+
+ skge_xm_phy_write(hw, port, PHY_BCOM_1000T_CTRL, ctrl2);
+ skge_xm_phy_write(hw, port, PHY_BCOM_AUNE_ADV, ctrl3);
+
+ if (skge->netdev->mtu > ETH_DATA_LEN) {
+ ctrl4 |= PHY_B_PEC_HIGH_LA;
+ ctrl5 |= PHY_B_AC_LONG_PACK;
+
+ skge_xm_phy_write(hw, port,PHY_BCOM_AUX_CTRL, ctrl5);
+ }
+
+ skge_xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, ctrl4);
+ skge_xm_phy_write(hw, port, PHY_BCOM_CTRL, ctrl1);
+ break;
+ }
+ spin_unlock_bh(&hw->phy_lock);
+
+ /* Clear MIB counters */
+ skge_xm_write16(hw, port, XM_STAT_CMD,
+ XM_SC_CLR_RXC | XM_SC_CLR_TXC);
+ /* Clear two times according to Errata #3 */
+ skge_xm_write16(hw, port, XM_STAT_CMD,
+ XM_SC_CLR_RXC | XM_SC_CLR_TXC);
+
+ /* Start polling for link status */
+ mod_timer(&skge->link_check, jiffies + LINK_POLL_HZ);
+}
+
+static void genesis_stop(struct skge_port *skge)
+{
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+
+ /* Clear Tx packet arbiter timeout IRQ */
+ skge_write16(hw, B3_PA_CTRL,
+ port == 0 ? PA_CLR_TO_TX1 : PA_CLR_TO_TX2);
+
+ /*
+ * If the transfer stucks at the MAC the STOP command will not
+ * terminate if we don't flush the XMAC's transmit FIFO !
+ */
+ skge_xm_write32(hw, port, XM_MODE,
+ skge_xm_read32(hw, port, XM_MODE)|XM_MD_FTF);
+
+
+ /* Reset the MAC */
+ skge_write16(hw, SKGEMAC_REG(port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
+
+ /* For external PHYs there must be special handling */
+ if (hw->phy_type != SK_PHY_XMAC) {
+ u32 reg = skge_read32(hw, B2_GP_IO);
+
+ if (port == 0) {
+ reg |= GP_DIR_0;
+ reg &= ~GP_IO_0;
+ } else {
+ reg |= GP_DIR_2;
+ reg &= ~GP_IO_2;
+ }
+ skge_write32(hw, B2_GP_IO, reg);
+ skge_read32(hw, B2_GP_IO);
+ }
+
+ skge_xm_write16(hw, port, XM_MMU_CMD,
+ skge_xm_read16(hw, port, XM_MMU_CMD)
+ & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX));
+
+ skge_xm_read16(hw, port, XM_MMU_CMD);
+}
+
+
+static void genesis_get_stats(struct skge_port *skge, u64 *data)
+{
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+ int i;
+ unsigned long timeout = jiffies + HZ;
+
+ skge_xm_write16(hw, port,
+ XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC);
+
+ /* wait for update to complete */
+ while (skge_xm_read16(hw, port, XM_STAT_CMD)
+ & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) {
+ if (time_after(jiffies, timeout))
+ break;
+ udelay(10);
+ }
+
+ /* special case for 64 bit octet counter */
+ data[0] = (u64) skge_xm_read32(hw, port, XM_TXO_OK_HI) << 32
+ | skge_xm_read32(hw, port, XM_TXO_OK_LO);
+ data[1] = (u64) skge_xm_read32(hw, port, XM_RXO_OK_HI) << 32
+ | skge_xm_read32(hw, port, XM_RXO_OK_LO);
+
+ for (i = 2; i < ARRAY_SIZE(skge_stats); i++)
+ data[i] = skge_xm_read32(hw, port, skge_stats[i].xmac_offset);
+}
+
+static void genesis_mac_intr(struct skge_hw *hw, int port)
+{
+ struct skge_port *skge = netdev_priv(hw->dev[port]);
+ u16 status = skge_xm_read16(hw, port, XM_ISRC);
+
+ pr_debug("genesis_intr status %x\n", status);
+ if (hw->phy_type == SK_PHY_XMAC) {
+ /* LInk down, start polling for state change */
+ if (status & XM_IS_INP_ASS) {
+ skge_xm_write16(hw, port, XM_IMSK,
+ skge_xm_read16(hw, port, XM_IMSK) | XM_IS_INP_ASS);
+ mod_timer(&skge->link_check, jiffies + LINK_POLL_HZ);
+ }
+ else if (status & XM_IS_AND)
+ mod_timer(&skge->link_check, jiffies + LINK_POLL_HZ);
+ }
+
+ if (status & XM_IS_TXF_UR) {
+ skge_xm_write32(hw, port, XM_MODE, XM_MD_FTF);
+ ++skge->net_stats.tx_fifo_errors;
+ }
+ if (status & XM_IS_RXF_OV) {
+ skge_xm_write32(hw, port, XM_MODE, XM_MD_FRF);
+ ++skge->net_stats.rx_fifo_errors;
+ }
+}
+
+static void skge_gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val)
+{
+ int i;
+
+ skge_gma_write16(hw, port, GM_SMI_DATA, val);
+ skge_gma_write16(hw, port, GM_SMI_CTRL,
+ GM_SMI_CT_PHY_AD(hw->phy_addr) | GM_SMI_CT_REG_AD(reg));
+ for (i = 0; i < PHY_RETRIES; i++) {
+ udelay(1);
+
+ if (!(skge_gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_BUSY))
+ break;
+ }
+}
+
+static u16 skge_gm_phy_read(struct skge_hw *hw, int port, u16 reg)
+{
+ int i;
+
+ skge_gma_write16(hw, port, GM_SMI_CTRL,
+ GM_SMI_CT_PHY_AD(hw->phy_addr)
+ | GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD);
+
+ for (i = 0; i < PHY_RETRIES; i++) {
+ udelay(1);
+ if (skge_gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_RD_VAL)
+ goto ready;
+ }
+
+ printk(KERN_WARNING PFX "%s: phy read timeout\n",
+ hw->dev[port]->name);
+ return 0;
+ ready:
+ return skge_gma_read16(hw, port, GM_SMI_DATA);
+}
+
+static void genesis_link_down(struct skge_port *skge)
+{
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+
+ pr_debug("genesis_link_down\n");
+
+ skge_xm_write16(hw, port, XM_MMU_CMD,
+ skge_xm_read16(hw, port, XM_MMU_CMD)
+ & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX));
+
+ /* dummy read to ensure writing */
+ (void) skge_xm_read16(hw, port, XM_MMU_CMD);
+
+ skge_link_down(skge);
+}
+
+static void genesis_link_up(struct skge_port *skge)
+{
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+ u16 cmd;
+ u32 mode, msk;
+
+ pr_debug("genesis_link_up\n");
+ cmd = skge_xm_read16(hw, port, XM_MMU_CMD);
+
+ /*
+ * enabling pause frame reception is required for 1000BT
+ * because the XMAC is not reset if the link is going down
+ */
+ if (skge->flow_control == FLOW_MODE_NONE ||
+ skge->flow_control == FLOW_MODE_LOC_SEND)
+ cmd |= XM_MMU_IGN_PF;
+ else
+ /* Enable Pause Frame Reception */
+ cmd &= ~XM_MMU_IGN_PF;
+
+ skge_xm_write16(hw, port, XM_MMU_CMD, cmd);
+
+ mode = skge_xm_read32(hw, port, XM_MODE);
+ if (skge->flow_control == FLOW_MODE_SYMMETRIC ||
+ skge->flow_control == FLOW_MODE_LOC_SEND) {
+ /*
+ * Configure Pause Frame Generation
+ * Use internal and external Pause Frame Generation.
+ * Sending pause frames is edge triggered.
+ * Send a Pause frame with the maximum pause time if
+ * internal oder external FIFO full condition occurs.
+ * Send a zero pause time frame to re-start transmission.
+ */
+ /* XM_PAUSE_DA = '010000C28001' (default) */
+ /* XM_MAC_PTIME = 0xffff (maximum) */
+ /* remember this value is defined in big endian (!) */
+ skge_xm_write16(hw, port, XM_MAC_PTIME, 0xffff);
+
+ mode |= XM_PAUSE_MODE;
+ skge_write16(hw, SKGEMAC_REG(port, RX_MFF_CTRL1), MFF_ENA_PAUSE);
+ } else {
+ /*
+ * disable pause frame generation is required for 1000BT
+ * because the XMAC is not reset if the link is going down
+ */
+ /* Disable Pause Mode in Mode Register */
+ mode &= ~XM_PAUSE_MODE;
+
+ skge_write16(hw, SKGEMAC_REG(port, RX_MFF_CTRL1), MFF_DIS_PAUSE);
+ }
+
+ skge_xm_write32(hw, port, XM_MODE, mode);
+
+ msk = XM_DEF_MSK;
+ if (hw->phy_type != SK_PHY_XMAC)
+ msk |= XM_IS_INP_ASS; /* disable GP0 interrupt bit */
+
+ skge_xm_write16(hw, port, XM_IMSK, msk);
+ skge_xm_read16(hw, port, XM_ISRC);
+
+ /* get MMU Command Reg. */
+ cmd = skge_xm_read16(hw, port, XM_MMU_CMD);
+ if (hw->phy_type != SK_PHY_XMAC && skge->duplex == DUPLEX_FULL)
+ cmd |= XM_MMU_GMII_FD;
+
+ if (hw->phy_type == SK_PHY_BCOM) {
+ /*
+ * Workaround BCOM Errata (#10523) for all BCom Phys
+ * Enable Power Management after link up
+ */
+ skge_xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL,
+ skge_xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL)
+ & ~PHY_B_AC_DIS_PM);
+ skge_xm_phy_write(hw, port, PHY_BCOM_INT_MASK,
+ PHY_B_DEF_MSK);
+ }
+
+ /* enable Rx/Tx */
+ skge_xm_write16(hw, port, XM_MMU_CMD,
+ cmd | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
+ skge_link_up(skge);
+}
+
+
+static void genesis_bcom_intr(struct skge_port *skge)
+{
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+ u16 stat = skge_xm_phy_read(hw, port, PHY_BCOM_INT_STAT);
+
+ pr_debug("genesis_bcom intr stat=%x\n", stat);
+
+ /* Workaround BCom Errata:
+ * enable and disable loopback mode if "NO HCD" occurs.
+ */
+ if (stat & PHY_B_IS_NO_HDCL) {
+ u16 ctrl = skge_xm_phy_read(hw, port, PHY_BCOM_CTRL);
+ skge_xm_phy_write(hw, port, PHY_BCOM_CTRL,
+ ctrl | PHY_CT_LOOP);
+ skge_xm_phy_write(hw, port, PHY_BCOM_CTRL,
+ ctrl & ~PHY_CT_LOOP);
+ }
+
+ stat = skge_xm_phy_read(hw, port, PHY_BCOM_STAT);
+ if (stat & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) {
+ u16 aux = skge_xm_phy_read(hw, port, PHY_BCOM_AUX_STAT);
+ if ( !(aux & PHY_B_AS_LS) && netif_carrier_ok(skge->netdev))
+ genesis_link_down(skge);
+
+ else if (stat & PHY_B_IS_LST_CHANGE) {
+ if (aux & PHY_B_AS_AN_C) {
+ switch (aux & PHY_B_AS_AN_RES_MSK) {
+ case PHY_B_RES_1000FD:
+ skge->duplex = DUPLEX_FULL;
+ break;
+ case PHY_B_RES_1000HD:
+ skge->duplex = DUPLEX_HALF;
+ break;
+ }
+
+ switch (aux & PHY_B_AS_PAUSE_MSK) {
+ case PHY_B_AS_PAUSE_MSK:
+ skge->flow_control = FLOW_MODE_SYMMETRIC;
+ break;
+ case PHY_B_AS_PRR:
+ skge->flow_control = FLOW_MODE_REM_SEND;
+ break;
+ case PHY_B_AS_PRT:
+ skge->flow_control = FLOW_MODE_LOC_SEND;
+ break;
+ default:
+ skge->flow_control = FLOW_MODE_NONE;
+ }
+ skge->speed = SPEED_1000;
+ }
+ genesis_link_up(skge);
+ }
+ else
+ mod_timer(&skge->link_check, jiffies + LINK_POLL_HZ);
+ }
+}
+
+/* Perodic poll of phy status to check for link transistion */
+static void skge_link_timer(unsigned long __arg)
+{
+ struct skge_port *skge = (struct skge_port *) __arg;
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+
+ if (hw->chip_id != CHIP_ID_GENESIS || !netif_running(skge->netdev))
+ return;
+
+ spin_lock_bh(&hw->phy_lock);
+ if (hw->phy_type == SK_PHY_BCOM)
+ genesis_bcom_intr(skge);
+ else {
+ int i;
+ for (i = 0; i < 3; i++)
+ if (skge_xm_read16(hw, port, XM_ISRC) & XM_IS_INP_ASS)
+ break;
+
+ if (i == 3)
+ mod_timer(&skge->link_check, jiffies + LINK_POLL_HZ);
+ else
+ genesis_link_up(skge);
+ }
+ spin_unlock_bh(&hw->phy_lock);
+}
+
+/* Marvell Phy Initailization */
+static void yukon_init(struct skge_hw *hw, int port)
+{
+ struct skge_port *skge = netdev_priv(hw->dev[port]);
+ u16 ctrl, ct1000, adv;
+ u16 ledctrl, ledover;
+
+ pr_debug("yukon_init\n");
+ if (skge->autoneg == AUTONEG_ENABLE) {
+ u16 ectrl = skge_gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
+
+ ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
+ PHY_M_EC_MAC_S_MSK);
+ ectrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ);
+
+ /* on PHY 88E1111 there is a change for downshift control */
+ if (hw->chip_id == CHIP_ID_YUKON_EC)
+ ectrl |= PHY_M_EC_M_DSC_2(0) | PHY_M_EC_DOWN_S_ENA;
+ else
+ ectrl |= PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1);
+
+ skge_gm_phy_write(hw, port, PHY_MARV_EXT_CTRL, ectrl);
+ }
+
+ ctrl = skge_gm_phy_read(hw, port, PHY_MARV_CTRL);
+ if (skge->autoneg == AUTONEG_DISABLE)
+ ctrl &= ~PHY_CT_ANE;
+
+ ctrl |= PHY_CT_RESET;
+ skge_gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
+
+ ctrl = 0;
+ ct1000 = 0;
+ adv = PHY_SEL_TYPE;
+
+ if (skge->autoneg == AUTONEG_ENABLE) {
+ if (iscopper(hw)) {
+ if (skge->advertising & ADVERTISED_1000baseT_Full)
+ ct1000 |= PHY_M_1000C_AFD;
+ if (skge->advertising & ADVERTISED_1000baseT_Half)
+ ct1000 |= PHY_M_1000C_AHD;
+ if (skge->advertising & ADVERTISED_100baseT_Full)
+ adv |= PHY_M_AN_100_FD;
+ if (skge->advertising & ADVERTISED_100baseT_Half)
+ adv |= PHY_M_AN_100_HD;
+ if (skge->advertising & ADVERTISED_10baseT_Full)
+ adv |= PHY_M_AN_10_FD;
+ if (skge->advertising & ADVERTISED_10baseT_Half)
+ adv |= PHY_M_AN_10_HD;
+
+ /* Set Flow-control capabilities */
+ switch (skge->flow_control) {
+ case FLOW_MODE_NONE:
+ adv |= PHY_B_P_NO_PAUSE;
+ break;
+ case FLOW_MODE_LOC_SEND:
+ adv |= PHY_B_P_ASYM_MD;
+ break;
+ case FLOW_MODE_SYMMETRIC:
+ adv |= PHY_B_P_SYM_MD;
+ break;
+ case FLOW_MODE_REM_SEND:
+ adv |= PHY_B_P_BOTH_MD;
+ break;
+ }
+ } else { /* special defines for FIBER (88E1011S only) */
+ adv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD;
+
+ /* Set Flow-control capabilities */
+ switch (skge->flow_control) {
+ case FLOW_MODE_NONE:
+ adv |= PHY_M_P_NO_PAUSE_X;
+ break;
+ case FLOW_MODE_LOC_SEND:
+ adv |= PHY_M_P_ASYM_MD_X;
+ break;
+ case FLOW_MODE_SYMMETRIC:
+ adv |= PHY_M_P_SYM_MD_X;
+ break;
+ case FLOW_MODE_REM_SEND:
+ adv |= PHY_M_P_BOTH_MD_X;
+ break;
+ }
+ }
+ /* Restart Auto-negotiation */
+ ctrl |= PHY_CT_ANE | PHY_CT_RE_CFG;
+ } else {
+ /* forced speed/duplex settings */
+ ct1000 = PHY_M_1000C_MSE;
+
+ if (skge->duplex == DUPLEX_FULL)
+ ctrl |= PHY_CT_DUP_MD;
+
+ switch (skge->speed) {
+ case SPEED_1000:
+ ctrl |= PHY_CT_SP1000;
+ break;
+ case SPEED_100:
+ ctrl |= PHY_CT_SP100;
+ break;
+ }
+
+ ctrl |= PHY_CT_RESET;
+ }
+
+ if (hw->chip_id != CHIP_ID_YUKON_FE)
+ skge_gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000);
+
+ skge_gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv);
+ skge_gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
+
+ /* Setup Phy LED's */
+ ledctrl = PHY_M_LED_PULS_DUR(PULS_170MS);
+ ledover = 0;
+
+ if (hw->chip_id == CHIP_ID_YUKON_FE) {
+ /* on 88E3082 these bits are at 11..9 (shifted left) */
+ ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) << 1;
+
+ skge_gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR,
+ ((skge_gm_phy_read(hw, port, PHY_MARV_FE_LED_PAR)
+
+ & ~PHY_M_FELP_LED1_MSK)
+ | PHY_M_FELP_LED1_CTRL(LED_PAR_CTRL_ACT_BL)));
+ } else {
+ /* set Tx LED (LED_TX) to blink mode on Rx OR Tx activity */
+ ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) | PHY_M_LEDC_TX_CTRL;
+
+ /* turn off the Rx LED (LED_RX) */
+ ledover |= PHY_M_LED_MO_RX(MO_LED_OFF);
+ }
+
+ /* disable blink mode (LED_DUPLEX) on collisions */
+ ctrl |= PHY_M_LEDC_DP_CTRL;
+ skge_gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
+
+ if (skge->autoneg == AUTONEG_DISABLE || skge->speed == SPEED_100) {
+ /* turn on 100 Mbps LED (LED_LINK100) */
+ ledover |= PHY_M_LED_MO_100(MO_LED_ON);
+ }
+
+ if (ledover)
+ skge_gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover);
+
+ /* Enable phy interrupt on autonegotiation complete (or link up) */
+ if (skge->autoneg == AUTONEG_ENABLE)
+ skge_gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL);
+ else
+ skge_gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
+}
+
+static void yukon_reset(struct skge_hw *hw, int port)
+{
+ skge_gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);/* disable PHY IRQs */
+ skge_gma_write16(hw, port, GM_MC_ADDR_H1, 0); /* clear MC hash */
+ skge_gma_write16(hw, port, GM_MC_ADDR_H2, 0);
+ skge_gma_write16(hw, port, GM_MC_ADDR_H3, 0);
+ skge_gma_write16(hw, port, GM_MC_ADDR_H4, 0);
+
+ skge_gma_write16(hw, port, GM_RX_CTRL,
+ skge_gma_read16(hw, port, GM_RX_CTRL)
+ | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
+}
+
+static void yukon_mac_init(struct skge_hw *hw, int port)
+{
+ struct skge_port *skge = netdev_priv(hw->dev[port]);
+ int i;
+ u32 reg;
+ const u8 *addr = hw->dev[port]->dev_addr;
+
+ /* WA code for COMA mode -- set PHY reset */
+ if (hw->chip_id == CHIP_ID_YUKON_LITE &&
+ chip_rev(hw) == CHIP_REV_YU_LITE_A3)
+ skge_write32(hw, B2_GP_IO,
+ (skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9));
+
+ /* hard reset */
+ skge_write32(hw, SKGEMAC_REG(port, GPHY_CTRL), GPC_RST_SET);
+ skge_write32(hw, SKGEMAC_REG(port, GMAC_CTRL), GMC_RST_SET);
+
+ /* WA code for COMA mode -- clear PHY reset */
+ if (hw->chip_id == CHIP_ID_YUKON_LITE &&
+ chip_rev(hw) == CHIP_REV_YU_LITE_A3)
+ skge_write32(hw, B2_GP_IO,
+ (skge_read32(hw, B2_GP_IO) | GP_DIR_9)
+ & ~GP_IO_9);
+
+ /* Set hardware config mode */
+ reg = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
+ GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE;
+ reg |= iscopper(hw) ? GPC_HWCFG_GMII_COP : GPC_HWCFG_GMII_FIB;
+
+ /* Clear GMC reset */
+ skge_write32(hw, SKGEMAC_REG(port, GPHY_CTRL), reg | GPC_RST_SET);
+ skge_write32(hw, SKGEMAC_REG(port, GPHY_CTRL), reg | GPC_RST_CLR);
+ skge_write32(hw, SKGEMAC_REG(port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
+ if (skge->autoneg == AUTONEG_DISABLE) {
+ reg = GM_GPCR_AU_ALL_DIS;
+ skge_gma_write16(hw, port, GM_GP_CTRL,
+ skge_gma_read16(hw, port, GM_GP_CTRL) | reg);
+
+ switch (skge->speed) {
+ case SPEED_1000:
+ reg |= GM_GPCR_SPEED_1000;
+ /* fallthru */
+ case SPEED_100:
+ reg |= GM_GPCR_SPEED_100;
+ }
+
+ if (skge->duplex == DUPLEX_FULL)
+ reg |= GM_GPCR_DUP_FULL;
+ } else
+ reg = GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100 | GM_GPCR_DUP_FULL;
+ switch (skge->flow_control) {
+ case FLOW_MODE_NONE:
+ skge_write32(hw, SKGEMAC_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
+ reg |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
+ break;
+ case FLOW_MODE_LOC_SEND:
+ /* disable Rx flow-control */
+ reg |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
+ }
+
+ skge_gma_write16(hw, port, GM_GP_CTRL, reg);
+ skge_read16(hw, GMAC_IRQ_SRC);
+
+ spin_lock_bh(&hw->phy_lock);
+ yukon_init(hw, port);
+ spin_unlock_bh(&hw->phy_lock);
+
+ /* MIB clear */
+ reg = skge_gma_read16(hw, port, GM_PHY_ADDR);
+ skge_gma_write16(hw, port, GM_PHY_ADDR, reg | GM_PAR_MIB_CLR);
+
+ for (i = 0; i < GM_MIB_CNT_SIZE; i++)
+ skge_gma_read16(hw, port, GM_MIB_CNT_BASE + 8*i);
+ skge_gma_write16(hw, port, GM_PHY_ADDR, reg);
+
+ /* transmit control */
+ skge_gma_write16(hw, port, GM_TX_CTRL, TX_COL_THR(TX_COL_DEF));
+
+ /* receive control reg: unicast + multicast + no FCS */
+ skge_gma_write16(hw, port, GM_RX_CTRL,
+ GM_RXCR_UCF_ENA | GM_RXCR_CRC_DIS | GM_RXCR_MCF_ENA);
+
+ /* transmit flow control */
+ skge_gma_write16(hw, port, GM_TX_FLOW_CTRL, 0xffff);
+
+ /* transmit parameter */
+ skge_gma_write16(hw, port, GM_TX_PARAM,
+ TX_JAM_LEN_VAL(TX_JAM_LEN_DEF) |
+ TX_JAM_IPG_VAL(TX_JAM_IPG_DEF) |
+ TX_IPG_JAM_DATA(TX_IPG_JAM_DEF));
+
+ /* serial mode register */
+ reg = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF);
+ if (hw->dev[port]->mtu > 1500)
+ reg |= GM_SMOD_JUMBO_ENA;
+
+ skge_gma_write16(hw, port, GM_SERIAL_MODE, reg);
+
+ /* physical address: used for pause frames */
+ skge_gm_set_addr(hw, port, GM_SRC_ADDR_1L, addr);
+ /* virtual address for data */
+ skge_gm_set_addr(hw, port, GM_SRC_ADDR_2L, addr);
+
+ /* enable interrupt mask for counter overflows */
+ skge_gma_write16(hw, port, GM_TX_IRQ_MSK, 0);
+ skge_gma_write16(hw, port, GM_RX_IRQ_MSK, 0);
+ skge_gma_write16(hw, port, GM_TR_IRQ_MSK, 0);
+
+ /* Initialize Mac Fifo */
+
+ /* Configure Rx MAC FIFO */
+ skge_write16(hw, SKGEMAC_REG(port, RX_GMF_FL_MSK), RX_FF_FL_DEF_MSK);
+ reg = GMF_OPER_ON | GMF_RX_F_FL_ON;
+ if (hw->chip_id == CHIP_ID_YUKON_LITE &&
+ chip_rev(hw) == CHIP_REV_YU_LITE_A3)
+ reg &= ~GMF_RX_F_FL_ON;
+ skge_write8(hw, SKGEMAC_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
+ skge_write16(hw, SKGEMAC_REG(port, RX_GMF_CTRL_T), reg);
+ skge_write16(hw, SKGEMAC_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF);
+
+ /* Configure Tx MAC FIFO */
+ skge_write8(hw, SKGEMAC_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR);
+ skge_write16(hw, SKGEMAC_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON);
+}
+
+static void yukon_stop(struct skge_port *skge)
+{
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+
+ if (hw->chip_id == CHIP_ID_YUKON_LITE &&
+ chip_rev(hw) == CHIP_REV_YU_LITE_A3) {
+ skge_write32(hw, B2_GP_IO,
+ skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9);
+ }
+
+ skge_gma_write16(hw, port, GM_GP_CTRL,
+ skge_gma_read16(hw, port, GM_GP_CTRL)
+ & ~(GM_GPCR_RX_ENA|GM_GPCR_RX_ENA));
+ skge_gma_read16(hw, port, GM_GP_CTRL);
+
+ /* set GPHY Control reset */
+ skge_gma_write32(hw, port, GPHY_CTRL, GPC_RST_SET);
+ skge_gma_write32(hw, port, GMAC_CTRL, GMC_RST_SET);
+}
+
+static void yukon_get_stats(struct skge_port *skge, u64 *data)
+{
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+ int i;
+
+ data[0] = (u64) skge_gma_read32(hw, port, GM_TXO_OK_HI) << 32
+ | skge_gma_read32(hw, port, GM_TXO_OK_LO);
+ data[1] = (u64) skge_gma_read32(hw, port, GM_RXO_OK_HI) << 32
+ | skge_gma_read32(hw, port, GM_RXO_OK_LO);
+
+ for (i = 2; i < ARRAY_SIZE(skge_stats); i++)
+ data[i] = skge_gma_read32(hw, port,
+ skge_stats[i].gma_offset);
+}
+
+static void yukon_mac_intr(struct skge_hw *hw, int port)
+{
+ struct skge_port *skge = netdev_priv(hw->dev[port]);
+ u8 status = skge_read8(hw, SKGEMAC_REG(port, GMAC_IRQ_SRC));
+
+ pr_debug("yukon_intr status %x\n", status);
+ if (status & GM_IS_RX_FF_OR) {
+ ++skge->net_stats.rx_fifo_errors;
+ skge_gma_write8(hw, port, RX_GMF_CTRL_T, GMF_CLI_RX_FO);
+ }
+ if (status & GM_IS_TX_FF_UR) {
+ ++skge->net_stats.tx_fifo_errors;
+ skge_gma_write8(hw, port, TX_GMF_CTRL_T, GMF_CLI_TX_FU);
+ }
+
+}
+
+static u16 yukon_speed(const struct skge_hw *hw, u16 aux)
+{
+ if (hw->chip_id == CHIP_ID_YUKON_FE)
+ return (aux & PHY_M_PS_SPEED_100) ? SPEED_100 : SPEED_10;
+
+ switch(aux & PHY_M_PS_SPEED_MSK) {
+ case PHY_M_PS_SPEED_1000:
+ return SPEED_1000;
+ case PHY_M_PS_SPEED_100:
+ return SPEED_100;
+ default:
+ return SPEED_10;
+ }
+}
+
+static void yukon_link_up(struct skge_port *skge)
+{
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+ u16 reg;
+
+ pr_debug("yukon_link_up\n");
+
+ /* Enable Transmit FIFO Underrun */
+ skge_write8(hw, GMAC_IRQ_MSK, GMAC_DEF_MSK);
+
+ reg = skge_gma_read16(hw, port, GM_GP_CTRL);
+ if (skge->duplex == DUPLEX_FULL || skge->autoneg == AUTONEG_ENABLE)
+ reg |= GM_GPCR_DUP_FULL;
+
+ /* enable Rx/Tx */
+ reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
+ skge_gma_write16(hw, port, GM_GP_CTRL, reg);
+
+ skge_gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
+ skge_link_up(skge);
+}
+
+static void yukon_link_down(struct skge_port *skge)
+{
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+
+ pr_debug("yukon_link_down\n");
+ skge_gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
+ skge_gm_phy_write(hw, port, GM_GP_CTRL,
+ skge_gm_phy_read(hw, port, GM_GP_CTRL)
+ & ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA));
+
+ if (hw->chip_id != CHIP_ID_YUKON_FE &&
+ skge->flow_control == FLOW_MODE_REM_SEND) {
+ /* restore Asymmetric Pause bit */
+ skge_gm_phy_write(hw, port, PHY_MARV_AUNE_ADV,
+ skge_gm_phy_read(hw, port,
+ PHY_MARV_AUNE_ADV)
+ | PHY_M_AN_ASP);
+
+ }
+
+ yukon_reset(hw, port);
+ skge_link_down(skge);
+
+ yukon_init(hw, port);
+}
+
+static void yukon_phy_intr(struct skge_port *skge)
+{
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+ const char *reason = NULL;
+ u16 istatus, phystat;
+
+ istatus = skge_gm_phy_read(hw, port, PHY_MARV_INT_STAT);
+ phystat = skge_gm_phy_read(hw, port, PHY_MARV_PHY_STAT);
+ pr_debug("yukon phy intr istat=%x phy_stat=%x\n", istatus, phystat);
+
+ if (istatus & PHY_M_IS_AN_COMPL) {
+ if (skge_gm_phy_read(hw, port, PHY_MARV_AUNE_LP)
+ & PHY_M_AN_RF) {
+ reason = "remote fault";
+ goto failed;
+ }
+
+ if (!(hw->chip_id == CHIP_ID_YUKON_FE || hw->chip_id == CHIP_ID_YUKON_EC)
+ && (skge_gm_phy_read(hw, port, PHY_MARV_1000T_STAT)
+ & PHY_B_1000S_MSF)) {
+ reason = "master/slave fault";
+ goto failed;
+ }
+
+ if (!(phystat & PHY_M_PS_SPDUP_RES)) {
+ reason = "speed/duplex";
+ goto failed;
+ }
+
+ skge->duplex = (phystat & PHY_M_PS_FULL_DUP)
+ ? DUPLEX_FULL : DUPLEX_HALF;
+ skge->speed = yukon_speed(hw, phystat);
+
+ /* Tx & Rx Pause Enabled bits are at 9..8 */
+ if (hw->chip_id == CHIP_ID_YUKON_XL)
+ phystat >>= 6;
+
+ /* We are using IEEE 802.3z/D5.0 Table 37-4 */
+ switch (phystat & PHY_M_PS_PAUSE_MSK) {
+ case PHY_M_PS_PAUSE_MSK:
+ skge->flow_control = FLOW_MODE_SYMMETRIC;
+ break;
+ case PHY_M_PS_RX_P_EN:
+ skge->flow_control = FLOW_MODE_REM_SEND;
+ break;
+ case PHY_M_PS_TX_P_EN:
+ skge->flow_control = FLOW_MODE_LOC_SEND;
+ break;
+ default:
+ skge->flow_control = FLOW_MODE_NONE;
+ }
+
+ if (skge->flow_control == FLOW_MODE_NONE ||
+ (skge->speed < SPEED_1000 && skge->duplex == DUPLEX_HALF))
+ skge_write8(hw, SKGEMAC_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
+ else
+ skge_write8(hw, SKGEMAC_REG(port, GMAC_CTRL), GMC_PAUSE_ON);
+ yukon_link_up(skge);
+ return;
+ }
+
+ if (istatus & PHY_M_IS_LSP_CHANGE)
+ skge->speed = yukon_speed(hw, phystat);
+
+ if (istatus & PHY_M_IS_DUP_CHANGE)
+ skge->duplex = (phystat & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF;
+ if (istatus & PHY_M_IS_LST_CHANGE) {
+ if (phystat & PHY_M_PS_LINK_UP)
+ yukon_link_up(skge);
+ else
+ yukon_link_down(skge);
+ }
+ return;
+ failed:
+ printk(KERN_ERR PFX "%s: autonegotiation failed (%s)\n",
+ skge->netdev->name, reason);
+
+ /* XXX restart autonegotiation? */
+}
+
+static void skge_ramset(struct skge_hw *hw, u16 q, u32 start, size_t len)
+{
+ u32 end;
+
+ start /= 8;
+ len /= 8;
+ end = start + len - 1;
+
+ skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR);
+ skge_write32(hw, RB_ADDR(q, RB_START), start);
+ skge_write32(hw, RB_ADDR(q, RB_WP), start);
+ skge_write32(hw, RB_ADDR(q, RB_RP), start);
+ skge_write32(hw, RB_ADDR(q, RB_END), end);
+
+ if (q == Q_R1 || q == Q_R2) {
+ /* Set thresholds on receive queue's */
+ skge_write32(hw, RB_ADDR(q, RB_RX_UTPP),
+ start + (2*len)/3);
+ skge_write32(hw, RB_ADDR(q, RB_RX_LTPP),
+ start + (len/3));
+ } else {
+ /* Enable store & forward on Tx queue's because
+ * Tx FIFO is only 4K on Genesis and 1K on Yukon
+ */
+ skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_STFWD);
+ }
+
+ skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_OP_MD);
+}
+
+/* Setup Bus Memory Interface */
+static void skge_qset(struct skge_port *skge, u16 q,
+ const struct skge_element *e)
+{
+ struct skge_hw *hw = skge->hw;
+ u32 watermark = 0x600;
+ u64 base = skge->dma + (e->desc - skge->mem);
+
+ /* optimization to reduce window on 32bit/33mhz */
+ if ((skge_read16(hw, B0_CTST) & (CS_BUS_CLOCK | CS_BUS_SLOT_SZ)) == 0)
+ watermark /= 2;
+
+ skge_write32(hw, Q_ADDR(q, Q_CSR), CSR_CLR_RESET);
+ skge_write32(hw, Q_ADDR(q, Q_F), watermark);
+ skge_write32(hw, Q_ADDR(q, Q_DA_H), (u32)(base >> 32));
+ skge_write32(hw, Q_ADDR(q, Q_DA_L), (u32)base);
+}
+
+static int skge_up(struct net_device *dev)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+ u32 chunk, ram_addr;
+ size_t rx_size, tx_size;
+ int err;
+
+ if (netif_msg_ifup(skge))
+ printk(KERN_INFO PFX "%s: enabling interface\n", dev->name);
+
+ rx_size = skge->rx_ring.count * sizeof(struct skge_rx_desc);
+ tx_size = skge->tx_ring.count * sizeof(struct skge_tx_desc);
+ skge->mem_size = tx_size + rx_size;
+ skge->mem = pci_alloc_consistent(hw->pdev, skge->mem_size, &skge->dma);
+ if (!skge->mem)
+ return -ENOMEM;
+
+ memset(skge->mem, 0, skge->mem_size);
+
+ if ((err = skge_ring_alloc(&skge->rx_ring, skge->mem, skge->dma)))
+ goto free_pci_mem;
+
+ if (skge_rx_fill(skge))
+ goto free_rx_ring;
+
+ if ((err = skge_ring_alloc(&skge->tx_ring, skge->mem + rx_size,
+ skge->dma + rx_size)))
+ goto free_rx_ring;
+
+ skge->tx_avail = skge->tx_ring.count - 1;
+
+ /* Initialze MAC */
+ if (hw->chip_id == CHIP_ID_GENESIS)
+ genesis_mac_init(hw, port);
+ else
+ yukon_mac_init(hw, port);
+
+ /* Configure RAMbuffers */
+ chunk = hw->ram_size / (isdualport(hw) ? 4 : 2);
+ ram_addr = hw->ram_offset + 2 * chunk * port;
+
+ skge_ramset(hw, rxqaddr[port], ram_addr, chunk);
+ skge_qset(skge, rxqaddr[port], skge->rx_ring.to_clean);
+
+ BUG_ON(skge->tx_ring.to_use != skge->tx_ring.to_clean);
+ skge_ramset(hw, txqaddr[port], ram_addr+chunk, chunk);
+ skge_qset(skge, txqaddr[port], skge->tx_ring.to_use);
+
+ /* Start receiver BMU */
+ wmb();
+ skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F);
+
+ pr_debug("skge_up completed\n");
+ return 0;
+
+ free_rx_ring:
+ skge_rx_clean(skge);
+ kfree(skge->rx_ring.start);
+ free_pci_mem:
+ pci_free_consistent(hw->pdev, skge->mem_size, skge->mem, skge->dma);
+
+ return err;
+}
+
+static int skge_down(struct net_device *dev)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+
+ if (netif_msg_ifdown(skge))
+ printk(KERN_INFO PFX "%s: disabling interface\n", dev->name);
+
+ netif_stop_queue(dev);
+
+ del_timer_sync(&skge->led_blink);
+ del_timer_sync(&skge->link_check);
+
+ /* Stop transmitter */
+ skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP);
+ skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL),
+ RB_RST_SET|RB_DIS_OP_MD);
+
+ if (hw->chip_id == CHIP_ID_GENESIS)
+ genesis_stop(skge);
+ else
+ yukon_stop(skge);
+
+ /* Disable Force Sync bit and Enable Alloc bit */
+ skge_write8(hw, SKGEMAC_REG(port, TXA_CTRL),
+ TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
+
+ /* Stop Interval Timer and Limit Counter of Tx Arbiter */
+ skge_write32(hw, SKGEMAC_REG(port, TXA_ITI_INI), 0L);
+ skge_write32(hw, SKGEMAC_REG(port, TXA_LIM_INI), 0L);
+
+ /* Reset PCI FIFO */
+ skge_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_SET_RESET);
+ skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), RB_RST_SET);
+
+ /* Reset the RAM Buffer async Tx queue */
+ skge_write8(hw, RB_ADDR(port == 0 ? Q_XA1 : Q_XA2, RB_CTRL), RB_RST_SET);
+ /* stop receiver */
+ skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_STOP);
+ skge_write32(hw, RB_ADDR(port ? Q_R2 : Q_R1, RB_CTRL),
+ RB_RST_SET|RB_DIS_OP_MD);
+ skge_write32(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_SET_RESET);
+
+ if (hw->chip_id == CHIP_ID_GENESIS) {
+ skge_write8(hw, SKGEMAC_REG(port, TX_MFF_CTRL2), MFF_RST_SET);
+ skge_write8(hw, SKGEMAC_REG(port, RX_MFF_CTRL2), MFF_RST_SET);
+ skge_write8(hw, SKGEMAC_REG(port, TX_LED_CTRL), LED_STOP);
+ skge_write8(hw, SKGEMAC_REG(port, RX_LED_CTRL), LED_STOP);
+ } else {
+ skge_write8(hw, SKGEMAC_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
+ skge_write8(hw, SKGEMAC_REG(port, TX_GMF_CTRL_T), GMF_RST_SET);
+ }
+
+ /* turn off led's */
+ skge_write16(hw, B0_LED, LED_STAT_OFF);
+
+ skge_tx_clean(skge);
+ skge_rx_clean(skge);
+
+ kfree(skge->rx_ring.start);
+ kfree(skge->tx_ring.start);
+ pci_free_consistent(hw->pdev, skge->mem_size, skge->mem, skge->dma);
+ return 0;
+}
+
+static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct skge_hw *hw = skge->hw;
+ struct skge_ring *ring = &skge->tx_ring;
+ struct skge_element *e;
+ struct skge_tx_desc *td;
+ int i;
+ u32 control, len;
+ u64 map;
+ unsigned long flags;
+
+ skb = skb_padto(skb, ETH_ZLEN);
+ if (!skb)
+ return NETDEV_TX_OK;
+
+ local_irq_save(flags);
+ if (!spin_trylock(&skge->tx_lock)) {
+ /* Collision - tell upper layer to requeue */
+ local_irq_restore(flags);
+ return NETDEV_TX_LOCKED;
+ }
+
+ if (unlikely(skge->tx_avail < skb_shinfo(skb)->nr_frags +1)) {
+ netif_stop_queue(dev);
+ spin_unlock_irqrestore(&skge->tx_lock, flags);
+
+ printk(KERN_WARNING PFX "%s: ring full when queue awake!\n",
+ dev->name);
+ return NETDEV_TX_BUSY;
+ }
+
+ e = ring->to_use;
+ td = e->desc;
+ e->skb = skb;
+ len = skb_headlen(skb);
+ map = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE);
+ pci_unmap_addr_set(e, mapaddr, map);
+ pci_unmap_len_set(e, maplen, len);
+
+ td->dma_lo = map;
+ td->dma_hi = map >> 32;
+
+ if (skb->ip_summed == CHECKSUM_HW) {
+ const struct iphdr *ip
+ = (const struct iphdr *) (skb->data + ETH_HLEN);
+ int offset = skb->h.raw - skb->data;
+
+ /* This seems backwards, but it is what the sk98lin
+ * does. Looks like hardware is wrong?
+ */
+ if (ip->protocol == IPPROTO_UDP
+ && chip_rev(hw) == 0 && hw->chip_id == CHIP_ID_YUKON)
+ control = BMU_TCP_CHECK;
+ else
+ control = BMU_UDP_CHECK;
+
+ td->csum_offs = 0;
+ td->csum_start = offset;
+ td->csum_write = offset + skb->csum;
+ } else
+ control = BMU_CHECK;
+
+ if (!skb_shinfo(skb)->nr_frags) /* single buffer i.e. no fragments */
+ control |= BMU_EOF| BMU_IRQ_EOF;
+ else {
+ struct skge_tx_desc *tf = td;
+
+ control |= BMU_STFWD;
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+ map = pci_map_page(hw->pdev, frag->page, frag->page_offset,
+ frag->size, PCI_DMA_TODEVICE);
+
+ e = e->next;
+ e->skb = NULL;
+ tf = e->desc;
+ tf->dma_lo = map;
+ tf->dma_hi = (u64) map >> 32;
+ pci_unmap_addr_set(e, mapaddr, map);
+ pci_unmap_len_set(e, maplen, frag->size);
+
+ tf->control = BMU_OWN | BMU_SW | control | frag->size;
+ }
+ tf->control |= BMU_EOF | BMU_IRQ_EOF;
+ }
+ /* Make sure all the descriptors written */
+ wmb();
+ td->control = BMU_OWN | BMU_SW | BMU_STF | control | len;
+ wmb();
+
+ skge_write8(hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_START);
+
+ if (netif_msg_tx_queued(skge))
+ printk(KERN_DEBUG "%s: tx queued, slot %td, len %d\n",
+ dev->name, e - ring->start, skb->len);
+
+ ring->to_use = e->next;
+ skge->tx_avail -= skb_shinfo(skb)->nr_frags + 1;
+ if (skge->tx_avail <= MAX_SKB_FRAGS + 1) {
+ pr_debug("%s: transmit queue full\n", dev->name);
+ netif_stop_queue(dev);
+ }
+
+ dev->trans_start = jiffies;
+ spin_unlock_irqrestore(&skge->tx_lock, flags);
+
+ return NETDEV_TX_OK;
+}
+
+static inline void skge_tx_free(struct skge_hw *hw, struct skge_element *e)
+{
+ if (e->skb) {
+ pci_unmap_single(hw->pdev,
+ pci_unmap_addr(e, mapaddr),
+ pci_unmap_len(e, maplen),
+ PCI_DMA_TODEVICE);
+ dev_kfree_skb_any(e->skb);
+ e->skb = NULL;
+ } else {
+ pci_unmap_page(hw->pdev,
+ pci_unmap_addr(e, mapaddr),
+ pci_unmap_len(e, maplen),
+ PCI_DMA_TODEVICE);
+ }
+}
+
+static void skge_tx_clean(struct skge_port *skge)
+{
+ struct skge_ring *ring = &skge->tx_ring;
+ struct skge_element *e;
+ unsigned long flags;
+
+ spin_lock_irqsave(&skge->tx_lock, flags);
+ for (e = ring->to_clean; e != ring->to_use; e = e->next) {
+ ++skge->tx_avail;
+ skge_tx_free(skge->hw, e);
+ }
+ ring->to_clean = e;
+ spin_unlock_irqrestore(&skge->tx_lock, flags);
+}
+
+static void skge_tx_timeout(struct net_device *dev)
+{
+ struct skge_port *skge = netdev_priv(dev);
+
+ if (netif_msg_timer(skge))
+ printk(KERN_DEBUG PFX "%s: tx timeout\n", dev->name);
+
+ skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_STOP);
+ skge_tx_clean(skge);
+}
+
+static int skge_change_mtu(struct net_device *dev, int new_mtu)
+{
+ int err = 0;
+
+ if(new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
+ return -EINVAL;
+
+ dev->mtu = new_mtu;
+
+ if (netif_running(dev)) {
+ skge_down(dev);
+ skge_up(dev);
+ }
+
+ return err;
+}
+
+static void genesis_set_multicast(struct net_device *dev)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+ int i, count = dev->mc_count;
+ struct dev_mc_list *list = dev->mc_list;
+ u32 mode;
+ u8 filter[8];
+
+ mode = skge_xm_read32(hw, port, XM_MODE);
+ mode |= XM_MD_ENA_HASH;
+ if (dev->flags & IFF_PROMISC)
+ mode |= XM_MD_ENA_PROM;
+ else
+ mode &= ~XM_MD_ENA_PROM;
+
+ if (dev->flags & IFF_ALLMULTI)
+ memset(filter, 0xff, sizeof(filter));
+ else {
+ memset(filter, 0, sizeof(filter));
+ for(i = 0; list && i < count; i++, list = list->next) {
+ u32 crc = crc32_le(~0, list->dmi_addr, ETH_ALEN);
+ u8 bit = 63 - (crc & 63);
+
+ filter[bit/8] |= 1 << (bit%8);
+ }
+ }
+
+ skge_xm_outhash(hw, port, XM_HSM, filter);
+
+ skge_xm_write32(hw, port, XM_MODE, mode);
+}
+
+static void yukon_set_multicast(struct net_device *dev)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct skge_hw *hw = skge->hw;
+ int port = skge->port;
+ struct dev_mc_list *list = dev->mc_list;
+ u16 reg;
+ u8 filter[8];
+
+ memset(filter, 0, sizeof(filter));
+
+ reg = skge_gma_read16(hw, port, GM_RX_CTRL);
+ reg |= GM_RXCR_UCF_ENA;
+
+ if (dev->flags & IFF_PROMISC) /* promiscious */
+ reg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
+ else if (dev->flags & IFF_ALLMULTI) /* all multicast */
+ memset(filter, 0xff, sizeof(filter));
+ else if (dev->mc_count == 0) /* no multicast */
+ reg &= ~GM_RXCR_MCF_ENA;
+ else {
+ int i;
+ reg |= GM_RXCR_MCF_ENA;
+
+ for(i = 0; list && i < dev->mc_count; i++, list = list->next) {
+ u32 bit = ether_crc(ETH_ALEN, list->dmi_addr) & 0x3f;
+ filter[bit/8] |= 1 << (bit%8);
+ }
+ }
+
+
+ skge_gma_write16(hw, port, GM_MC_ADDR_H1,
+ (u16)filter[0] | ((u16)filter[1] << 8));
+ skge_gma_write16(hw, port, GM_MC_ADDR_H2,
+ (u16)filter[2] | ((u16)filter[3] << 8));
+ skge_gma_write16(hw, port, GM_MC_ADDR_H3,
+ (u16)filter[4] | ((u16)filter[5] << 8));
+ skge_gma_write16(hw, port, GM_MC_ADDR_H4,
+ (u16)filter[6] | ((u16)filter[7] << 8));
+
+ skge_gma_write16(hw, port, GM_RX_CTRL, reg);
+}
+
+static inline int bad_phy_status(const struct skge_hw *hw, u32 status)
+{
+ if (hw->chip_id == CHIP_ID_GENESIS)
+ return (status & (XMR_FS_ERR | XMR_FS_2L_VLAN)) != 0;
+ else
+ return (status & GMR_FS_ANY_ERR) ||
+ (status & GMR_FS_RX_OK) == 0;
+}
+
+static void skge_rx_error(struct skge_port *skge, int slot,
+ u32 control, u32 status)
+{
+ if (netif_msg_rx_err(skge))
+ printk(KERN_DEBUG PFX "%s: rx err, slot %d control 0x%x status 0x%x\n",
+ skge->netdev->name, slot, control, status);
+
+ if ((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF)
+ || (control & BMU_BBC) > skge->netdev->mtu + VLAN_ETH_HLEN)
+ skge->net_stats.rx_length_errors++;
+ else {
+ if (skge->hw->chip_id == CHIP_ID_GENESIS) {
+ if (status & (XMR_FS_RUNT|XMR_FS_LNG_ERR))
+ skge->net_stats.rx_length_errors++;
+ if (status & XMR_FS_FRA_ERR)
+ skge->net_stats.rx_frame_errors++;
+ if (status & XMR_FS_FCS_ERR)
+ skge->net_stats.rx_crc_errors++;
+ } else {
+ if (status & (GMR_FS_LONG_ERR|GMR_FS_UN_SIZE))
+ skge->net_stats.rx_length_errors++;
+ if (status & GMR_FS_FRAGMENT)
+ skge->net_stats.rx_frame_errors++;
+ if (status & GMR_FS_CRC_ERR)
+ skge->net_stats.rx_crc_errors++;
+ }
+ }
+}
+
+static int skge_poll(struct net_device *dev, int *budget)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct skge_hw *hw = skge->hw;
+ struct skge_ring *ring = &skge->rx_ring;
+ struct skge_element *e;
+ unsigned int to_do = min(dev->quota, *budget);
+ unsigned int work_done = 0;
+ int done;
+ static const u32 irqmask[] = { IS_PORT_1, IS_PORT_2 };
+
+ for (e = ring->to_clean; e != ring->to_use && work_done < to_do;
+ e = e->next) {
+ struct skge_rx_desc *rd = e->desc;
+ struct sk_buff *skb = e->skb;
+ u32 control, len, status;
+
+ rmb();
+ control = rd->control;
+ if (control & BMU_OWN)
+ break;
+
+ len = control & BMU_BBC;
+ e->skb = NULL;
+
+ pci_unmap_single(hw->pdev,
+ pci_unmap_addr(e, mapaddr),
+ pci_unmap_len(e, maplen),
+ PCI_DMA_FROMDEVICE);
+
+ status = rd->status;
+ if ((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF)
+ || len > dev->mtu + VLAN_ETH_HLEN
+ || bad_phy_status(hw, status)) {
+ skge_rx_error(skge, e - ring->start, control, status);
+ dev_kfree_skb(skb);
+ continue;
+ }
+
+ if (netif_msg_rx_status(skge))
+ printk(KERN_DEBUG PFX "%s: rx slot %td status 0x%x len %d\n",
+ dev->name, e - ring->start, rd->status, len);
+
+ skb_put(skb, len);
+ skb->protocol = eth_type_trans(skb, dev);
+
+ if (skge->rx_csum) {
+ skb->csum = le16_to_cpu(rd->csum2);
+ skb->ip_summed = CHECKSUM_HW;
+ }
+
+ dev->last_rx = jiffies;
+ netif_receive_skb(skb);
+
+ ++work_done;
+ }
+ ring->to_clean = e;
+
+ *budget -= work_done;
+ dev->quota -= work_done;
+ done = work_done < to_do;
+
+ if (skge_rx_fill(skge))
+ done = 0;
+
+ /* restart receiver */
+ wmb();
+ skge_write8(hw, Q_ADDR(rxqaddr[skge->port], Q_CSR),
+ CSR_START | CSR_IRQ_CL_F);
+
+ if (done) {
+ local_irq_disable();
+ hw->intr_mask |= irqmask[skge->port];
+ /* Order is important since data can get interrupted */
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
+ __netif_rx_complete(dev);
+ local_irq_enable();
+ }
+
+ return !done;
+}
+
+static inline void skge_tx_intr(struct net_device *dev)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct skge_hw *hw = skge->hw;
+ struct skge_ring *ring = &skge->tx_ring;
+ struct skge_element *e;
+
+ spin_lock(&skge->tx_lock);
+ for(e = ring->to_clean; e != ring->to_use; e = e->next) {
+ struct skge_tx_desc *td = e->desc;
+ u32 control;
+
+ rmb();
+ control = td->control;
+ if (control & BMU_OWN)
+ break;
+
+ if (unlikely(netif_msg_tx_done(skge)))
+ printk(KERN_DEBUG PFX "%s: tx done slot %td status 0x%x\n",
+ dev->name, e - ring->start, td->status);
+
+ skge_tx_free(hw, e);
+ e->skb = NULL;
+ ++skge->tx_avail;
+ }
+ ring->to_clean = e;
+ skge_write8(hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F);
+
+ if (skge->tx_avail > MAX_SKB_FRAGS + 1)
+ netif_wake_queue(dev);
+
+ spin_unlock(&skge->tx_lock);
+}
+
+static void skge_mac_parity(struct skge_hw *hw, int port)
+{
+ printk(KERN_ERR PFX "%s: mac data parity error\n",
+ hw->dev[port] ? hw->dev[port]->name
+ : (port == 0 ? "(port A)": "(port B"));
+
+ if (hw->chip_id == CHIP_ID_GENESIS)
+ skge_write16(hw, SKGEMAC_REG(port, TX_MFF_CTRL1),
+ MFF_CLR_PERR);
+ else
+ /* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */
+ skge_write8(hw, SKGEMAC_REG(port, TX_GMF_CTRL_T),
+ (hw->chip_id == CHIP_ID_YUKON && chip_rev(hw) == 0)
+ ? GMF_CLI_TX_FC : GMF_CLI_TX_PE);
+}
+
+static void skge_pci_clear(struct skge_hw *hw)
+{
+ u16 status;
+
+ status = skge_read16(hw, SKGEPCI_REG(PCI_STATUS));
+ skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+ skge_write16(hw, SKGEPCI_REG(PCI_STATUS),
+ status | PCI_STATUS_ERROR_BITS);
+ skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+}
+
+static void skge_mac_intr(struct skge_hw *hw, int port)
+{
+ if (hw->chip_id == CHIP_ID_GENESIS)
+ genesis_mac_intr(hw, port);
+ else
+ yukon_mac_intr(hw, port);
+}
+
+/* Handle device specific framing and timeout interrupts */
+static void skge_error_irq(struct skge_hw *hw)
+{
+ u32 hwstatus = skge_read32(hw, B0_HWE_ISRC);
+
+ if (hw->chip_id == CHIP_ID_GENESIS) {
+ /* clear xmac errors */
+ if (hwstatus & (IS_NO_STAT_M1|IS_NO_TIST_M1))
+ skge_write16(hw, SKGEMAC_REG(0, RX_MFF_CTRL1), MFF_CLR_INSTAT);
+ if (hwstatus & (IS_NO_STAT_M2|IS_NO_TIST_M2))
+ skge_write16(hw, SKGEMAC_REG(0, RX_MFF_CTRL2), MFF_CLR_INSTAT);
+ } else {
+ /* Timestamp (unused) overflow */
+ if (hwstatus & IS_IRQ_TIST_OV)
+ skge_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ);
+
+ if (hwstatus & IS_IRQ_SENSOR) {
+ /* no sensors on 32-bit Yukon */
+ if (!(skge_read16(hw, B0_CTST) & CS_BUS_SLOT_SZ)) {
+ printk(KERN_ERR PFX "ignoring bogus sensor interrups\n");
+ skge_write32(hw, B0_HWE_IMSK,
+ IS_ERR_MSK & ~IS_IRQ_SENSOR);
+ } else
+ printk(KERN_WARNING PFX "sensor interrupt\n");
+ }
+
+
+ }
+
+ if (hwstatus & IS_RAM_RD_PAR) {
+ printk(KERN_ERR PFX "Ram read data parity error\n");
+ skge_write16(hw, B3_RI_CTRL, RI_CLR_RD_PERR);
+ }
+
+ if (hwstatus & IS_RAM_WR_PAR) {
+ printk(KERN_ERR PFX "Ram write data parity error\n");
+ skge_write16(hw, B3_RI_CTRL, RI_CLR_WR_PERR);
+ }
+
+ if (hwstatus & IS_M1_PAR_ERR)
+ skge_mac_parity(hw, 0);
+
+ if (hwstatus & IS_M2_PAR_ERR)
+ skge_mac_parity(hw, 1);
+
+ if (hwstatus & IS_R1_PAR_ERR)
+ skge_write32(hw, B0_R1_CSR, CSR_IRQ_CL_P);
+
+ if (hwstatus & IS_R2_PAR_ERR)
+ skge_write32(hw, B0_R2_CSR, CSR_IRQ_CL_P);
+
+ if (hwstatus & (IS_IRQ_MST_ERR|IS_IRQ_STAT)) {
+ printk(KERN_ERR PFX "hardware error detected (status 0x%x)\n",
+ hwstatus);
+
+ skge_pci_clear(hw);
+
+ hwstatus = skge_read32(hw, B0_HWE_ISRC);
+ if (hwstatus & IS_IRQ_STAT) {
+ printk(KERN_WARNING PFX "IRQ status %x: still set ignoring hardware errors\n",
+ hwstatus);
+ hw->intr_mask &= ~IS_HW_ERR;
+ }
+ }
+}
+
+/*
+ * Interrrupt from PHY are handled in tasklet (soft irq)
+ * because accessing phy registers requires spin wait which might
+ * cause excess interrupt latency.
+ */
+static void skge_extirq(unsigned long data)
+{
+ struct skge_hw *hw = (struct skge_hw *) data;
+ int port;
+
+ spin_lock(&hw->phy_lock);
+ for (port = 0; port < 2; port++) {
+ struct net_device *dev = hw->dev[port];
+
+ if (dev && netif_running(dev)) {
+ struct skge_port *skge = netdev_priv(dev);
+
+ if (hw->chip_id != CHIP_ID_GENESIS)
+ yukon_phy_intr(skge);
+ else if (hw->phy_type == SK_PHY_BCOM)
+ genesis_bcom_intr(skge);
+ }
+ }
+ spin_unlock(&hw->phy_lock);
+
+ local_irq_disable();
+ hw->intr_mask |= IS_EXT_REG;
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
+ local_irq_enable();
+}
+
+static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct skge_hw *hw = dev_id;
+ u32 status = skge_read32(hw, B0_SP_ISRC);
+
+ if (status == 0 || status == ~0) /* hotplug or shared irq */
+ return IRQ_NONE;
+
+ status &= hw->intr_mask;
+
+ if ((status & IS_R1_F) && netif_rx_schedule_prep(hw->dev[0])) {
+ status &= ~IS_R1_F;
+ hw->intr_mask &= ~IS_R1_F;
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
+ __netif_rx_schedule(hw->dev[0]);
+ }
+
+ if ((status & IS_R2_F) && netif_rx_schedule_prep(hw->dev[1])) {
+ status &= ~IS_R2_F;
+ hw->intr_mask &= ~IS_R2_F;
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
+ __netif_rx_schedule(hw->dev[1]);
+ }
+
+ if (status & IS_XA1_F)
+ skge_tx_intr(hw->dev[0]);
+
+ if (status & IS_XA2_F)
+ skge_tx_intr(hw->dev[1]);
+
+ if (status & IS_MAC1)
+ skge_mac_intr(hw, 0);
+
+ if (status & IS_MAC2)
+ skge_mac_intr(hw, 1);
+
+ if (status & IS_HW_ERR)
+ skge_error_irq(hw);
+
+ if (status & IS_EXT_REG) {
+ hw->intr_mask &= ~IS_EXT_REG;
+ tasklet_schedule(&hw->ext_tasklet);
+ }
+
+ if (status)
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
+
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void skge_netpoll(struct net_device *dev)
+{
+ struct skge_port *skge = netdev_priv(dev);
+
+ disable_irq(dev->irq);
+ skge_intr(dev->irq, skge->hw, NULL);
+ enable_irq(dev->irq);
+}
+#endif
+
+static int skge_set_mac_address(struct net_device *dev, void *p)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct sockaddr *addr = p;
+ int err = 0;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ skge_down(dev);
+ memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
+ memcpy_toio(skge->hw->regs + B2_MAC_1 + skge->port*8,
+ dev->dev_addr, ETH_ALEN);
+ memcpy_toio(skge->hw->regs + B2_MAC_2 + skge->port*8,
+ dev->dev_addr, ETH_ALEN);
+ if (dev->flags & IFF_UP)
+ err = skge_up(dev);
+ return err;
+}
+
+static const struct {
+ u8 id;
+ const char *name;
+} skge_chips[] = {
+ { CHIP_ID_GENESIS, "Genesis" },
+ { CHIP_ID_YUKON, "Yukon" },
+ { CHIP_ID_YUKON_LITE, "Yukon-Lite"},
+ { CHIP_ID_YUKON_LP, "Yukon-LP"},
+ { CHIP_ID_YUKON_XL, "Yukon-2 XL"},
+ { CHIP_ID_YUKON_EC, "YUKON-2 EC"},
+ { CHIP_ID_YUKON_FE, "YUKON-2 FE"},
+};
+
+static const char *skge_board_name(const struct skge_hw *hw)
+{
+ int i;
+ static char buf[16];
+
+ for (i = 0; i < ARRAY_SIZE(skge_chips); i++)
+ if (skge_chips[i].id == hw->chip_id)
+ return skge_chips[i].name;
+
+ snprintf(buf, sizeof buf, "chipid 0x%x", hw->chip_id);
+ return buf;
+}
+
+
+/*
+ * Setup the board data structure, but don't bring up
+ * the port(s)
+ */
+static int skge_reset(struct skge_hw *hw)
+{
+ u16 ctst;
+ u8 t8;
+ int i, ports;
+
+ ctst = skge_read16(hw, B0_CTST);
+
+ /* do a SW reset */
+ skge_write8(hw, B0_CTST, CS_RST_SET);
+ skge_write8(hw, B0_CTST, CS_RST_CLR);
+
+ /* clear PCI errors, if any */
+ skge_pci_clear(hw);
+
+ skge_write8(hw, B0_CTST, CS_MRST_CLR);
+
+ /* restore CLK_RUN bits (for Yukon-Lite) */
+ skge_write16(hw, B0_CTST,
+ ctst & (CS_CLK_RUN_HOT|CS_CLK_RUN_RST|CS_CLK_RUN_ENA));
+
+ hw->chip_id = skge_read8(hw, B2_CHIP_ID);
+ hw->phy_type = skge_read8(hw, B2_E_1) & 0xf;
+ hw->pmd_type = skge_read8(hw, B2_PMD_TYP);
+
+ switch(hw->chip_id) {
+ case CHIP_ID_GENESIS:
+ switch (hw->phy_type) {
+ case SK_PHY_XMAC:
+ hw->phy_addr = PHY_ADDR_XMAC;
+ break;
+ case SK_PHY_BCOM:
+ hw->phy_addr = PHY_ADDR_BCOM;
+ break;
+ default:
+ printk(KERN_ERR PFX "%s: unsupported phy type 0x%x\n",
+ pci_name(hw->pdev), hw->phy_type);
+ return -EOPNOTSUPP;
+ }
+ break;
+
+ case CHIP_ID_YUKON:
+ case CHIP_ID_YUKON_LITE:
+ case CHIP_ID_YUKON_LP:
+ if (hw->phy_type < SK_PHY_MARV_COPPER && hw->pmd_type != 'S')
+ hw->phy_type = SK_PHY_MARV_COPPER;
+
+ hw->phy_addr = PHY_ADDR_MARV;
+ if (!iscopper(hw))
+ hw->phy_type = SK_PHY_MARV_FIBER;
+
+ break;
+
+ default:
+ printk(KERN_ERR PFX "%s: unsupported chip type 0x%x\n",
+ pci_name(hw->pdev), hw->chip_id);
+ return -EOPNOTSUPP;
+ }
+
+ hw->mac_cfg = skge_read8(hw, B2_MAC_CFG);
+ ports = isdualport(hw) ? 2 : 1;
+
+ /* read the adapters RAM size */
+ t8 = skge_read8(hw, B2_E_0);
+ if (hw->chip_id == CHIP_ID_GENESIS) {
+ if (t8 == 3) {
+ /* special case: 4 x 64k x 36, offset = 0x80000 */
+ hw->ram_size = 0x100000;
+ hw->ram_offset = 0x80000;
+ } else
+ hw->ram_size = t8 * 512;
+ }
+ else if (t8 == 0)
+ hw->ram_size = 0x20000;
+ else
+ hw->ram_size = t8 * 4096;
+
+ if (hw->chip_id == CHIP_ID_GENESIS)
+ genesis_init(hw);
+ else {
+ /* switch power to VCC (WA for VAUX problem) */
+ skge_write8(hw, B0_POWER_CTRL,
+ PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON);
+ for (i = 0; i < ports; i++) {
+ skge_write16(hw, SKGEMAC_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET);
+ skge_write16(hw, SKGEMAC_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
+ }
+ }
+
+ /* turn off hardware timer (unused) */
+ skge_write8(hw, B2_TI_CTRL, TIM_STOP);
+ skge_write8(hw, B2_TI_CTRL, TIM_CLR_IRQ);
+ skge_write8(hw, B0_LED, LED_STAT_ON);
+
+ /* enable the Tx Arbiters */
+ for (i = 0; i < ports; i++)
+ skge_write8(hw, SKGEMAC_REG(i, TXA_CTRL), TXA_ENA_ARB);
+
+ /* Initialize ram interface */
+ skge_write16(hw, B3_RI_CTRL, RI_RST_CLR);
+
+ skge_write8(hw, B3_RI_WTO_R1, SK_RI_TO_53);
+ skge_write8(hw, B3_RI_WTO_XA1, SK_RI_TO_53);
+ skge_write8(hw, B3_RI_WTO_XS1, SK_RI_TO_53);
+ skge_write8(hw, B3_RI_RTO_R1, SK_RI_TO_53);
+ skge_write8(hw, B3_RI_RTO_XA1, SK_RI_TO_53);
+ skge_write8(hw, B3_RI_RTO_XS1, SK_RI_TO_53);
+ skge_write8(hw, B3_RI_WTO_R2, SK_RI_TO_53);
+ skge_write8(hw, B3_RI_WTO_XA2, SK_RI_TO_53);
+ skge_write8(hw, B3_RI_WTO_XS2, SK_RI_TO_53);
+ skge_write8(hw, B3_RI_RTO_R2, SK_RI_TO_53);
+ skge_write8(hw, B3_RI_RTO_XA2, SK_RI_TO_53);
+ skge_write8(hw, B3_RI_RTO_XS2, SK_RI_TO_53);
+
+ skge_write32(hw, B0_HWE_IMSK, IS_ERR_MSK);
+
+ /* Set interrupt moderation for Transmit only
+ * Receive interrupts avoided by NAPI
+ */
+ skge_write32(hw, B2_IRQM_MSK, IS_XA1_F|IS_XA2_F);
+ skge_write32(hw, B2_IRQM_INI, skge_usecs2clk(hw, 100));
+ skge_write32(hw, B2_IRQM_CTRL, TIM_START);
+
+ hw->intr_mask = IS_HW_ERR | IS_EXT_REG | IS_PORT_1;
+ if (isdualport(hw))
+ hw->intr_mask |= IS_PORT_2;
+ skge_write32(hw, B0_IMSK, hw->intr_mask);
+
+ if (hw->chip_id != CHIP_ID_GENESIS)
+ skge_write8(hw, GMAC_IRQ_MSK, 0);
+
+ spin_lock_bh(&hw->phy_lock);
+ for (i = 0; i < ports; i++) {
+ if (hw->chip_id == CHIP_ID_GENESIS)
+ genesis_reset(hw, i);
+ else
+ yukon_reset(hw, i);
+ }
+ spin_unlock_bh(&hw->phy_lock);
+
+ return 0;
+}
+
+/* Initialize network device */
+static struct net_device *skge_devinit(struct skge_hw *hw, int port)
+{
+ struct skge_port *skge;
+ struct net_device *dev = alloc_etherdev(sizeof(*skge));
+
+ if (!dev) {
+ printk(KERN_ERR "skge etherdev alloc failed");
+ return NULL;
+ }
+
+ SET_MODULE_OWNER(dev);
+ SET_NETDEV_DEV(dev, &hw->pdev->dev);
+ dev->open = skge_up;
+ dev->stop = skge_down;
+ dev->hard_start_xmit = skge_xmit_frame;
+ dev->get_stats = skge_get_stats;
+ if (hw->chip_id == CHIP_ID_GENESIS)
+ dev->set_multicast_list = genesis_set_multicast;
+ else
+ dev->set_multicast_list = yukon_set_multicast;
+
+ dev->set_mac_address = skge_set_mac_address;
+ dev->change_mtu = skge_change_mtu;
+ SET_ETHTOOL_OPS(dev, &skge_ethtool_ops);
+ dev->tx_timeout = skge_tx_timeout;
+ dev->watchdog_timeo = TX_WATCHDOG;
+ dev->poll = skge_poll;
+ dev->weight = NAPI_WEIGHT;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = skge_netpoll;
+#endif
+ dev->irq = hw->pdev->irq;
+ dev->features = NETIF_F_LLTX;
+
+ skge = netdev_priv(dev);
+ skge->netdev = dev;
+ skge->hw = hw;
+ skge->msg_enable = netif_msg_init(debug, default_msg);
+ skge->tx_ring.count = DEFAULT_TX_RING_SIZE;
+ skge->rx_ring.count = DEFAULT_RX_RING_SIZE;
+
+ /* Auto speed and flow control */
+ skge->autoneg = AUTONEG_ENABLE;
+ skge->flow_control = FLOW_MODE_SYMMETRIC;
+ skge->duplex = -1;
+ skge->speed = -1;
+ skge->advertising = skge_modes(hw);
+
+ hw->dev[port] = dev;
+
+ skge->port = port;
+
+ spin_lock_init(&skge->tx_lock);
+
+ init_timer(&skge->link_check);
+ skge->link_check.function = skge_link_timer;
+ skge->link_check.data = (unsigned long) skge;
+
+ init_timer(&skge->led_blink);
+ skge->led_blink.function = skge_blink_timer;
+ skge->led_blink.data = (unsigned long) skge;
+
+ if (hw->chip_id != CHIP_ID_GENESIS) {
+ dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+ skge->rx_csum = 1;
+ }
+
+ /* read the mac address */
+ memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port*8, ETH_ALEN);
+
+ /* device is off until link detection */
+ netif_carrier_off(dev);
+ netif_stop_queue(dev);
+
+ return dev;
+}
+
+static void __devinit skge_show_addr(struct net_device *dev)
+{
+ const struct skge_port *skge = netdev_priv(dev);
+
+ if (netif_msg_probe(skge))
+ printk(KERN_INFO PFX "%s: addr %02x:%02x:%02x:%02x:%02x:%02x\n",
+ dev->name,
+ dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+ dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+}
+
+static int __devinit skge_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct net_device *dev, *dev1;
+ struct skge_hw *hw;
+ int err, using_dac = 0;
+
+ if ((err = pci_enable_device(pdev))) {
+ printk(KERN_ERR PFX "%s cannot enable PCI device\n",
+ pci_name(pdev));
+ goto err_out;
+ }
+
+ if ((err = pci_request_regions(pdev, DRV_NAME))) {
+ printk(KERN_ERR PFX "%s cannot obtain PCI resources\n",
+ pci_name(pdev));
+ goto err_out_disable_pdev;
+ }
+
+ pci_set_master(pdev);
+
+ if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)))
+ using_dac = 1;
+ else if (!(err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
+ printk(KERN_ERR PFX "%s no usable DMA configuration\n",
+ pci_name(pdev));
+ goto err_out_free_regions;
+ }
+
+#ifdef __BIG_ENDIAN
+ /* byte swap decriptors in hardware */
+ {
+ u32 reg;
+
+ pci_read_config_dword(pdev, PCI_DEV_REG2, &reg);
+ reg |= PCI_REV_DESC;
+ pci_write_config_dword(pdev, PCI_DEV_REG2, reg);
+ }
+#endif
+
+ err = -ENOMEM;
+ hw = kmalloc(sizeof(*hw), GFP_KERNEL);
+ if (!hw) {
+ printk(KERN_ERR PFX "%s: cannot allocate hardware struct\n",
+ pci_name(pdev));
+ goto err_out_free_regions;
+ }
+
+ memset(hw, 0, sizeof(*hw));
+ hw->pdev = pdev;
+ spin_lock_init(&hw->phy_lock);
+ tasklet_init(&hw->ext_tasklet, skge_extirq, (unsigned long) hw);
+
+ hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000);
+ if (!hw->regs) {
+ printk(KERN_ERR PFX "%s: cannot map device registers\n",
+ pci_name(pdev));
+ goto err_out_free_hw;
+ }
+
+ if ((err = request_irq(pdev->irq, skge_intr, SA_SHIRQ, DRV_NAME, hw))) {
+ printk(KERN_ERR PFX "%s: cannot assign irq %d\n",
+ pci_name(pdev), pdev->irq);
+ goto err_out_iounmap;
+ }
+ pci_set_drvdata(pdev, hw);
+
+ err = skge_reset(hw);
+ if (err)
+ goto err_out_free_irq;
+
+ printk(KERN_INFO PFX "addr 0x%lx irq %d chip %s rev %d\n",
+ pci_resource_start(pdev, 0), pdev->irq,
+ skge_board_name(hw), chip_rev(hw));
+
+ if ((dev = skge_devinit(hw, 0)) == NULL)
+ goto err_out_led_off;
+
+ if (using_dac)
+ dev->features |= NETIF_F_HIGHDMA;
+
+ if ((err = register_netdev(dev))) {
+ printk(KERN_ERR PFX "%s: cannot register net device\n",
+ pci_name(pdev));
+ goto err_out_free_netdev;
+ }
+
+ skge_show_addr(dev);
+
+ if (isdualport(hw) && (dev1 = skge_devinit(hw, 1))) {
+ if (using_dac)
+ dev1->features |= NETIF_F_HIGHDMA;
+
+ if (register_netdev(dev1) == 0)
+ skge_show_addr(dev1);
+ else {
+ /* Failure to register second port need not be fatal */
+ printk(KERN_WARNING PFX "register of second port failed\n");
+ hw->dev[1] = NULL;
+ free_netdev(dev1);
+ }
+ }
+
+ return 0;
+
+err_out_free_netdev:
+ free_netdev(dev);
+err_out_led_off:
+ skge_write16(hw, B0_LED, LED_STAT_OFF);
+err_out_free_irq:
+ free_irq(pdev->irq, hw);
+err_out_iounmap:
+ iounmap(hw->regs);
+err_out_free_hw:
+ kfree(hw);
+err_out_free_regions:
+ pci_release_regions(pdev);
+err_out_disable_pdev:
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+err_out:
+ return err;
+}
+
+static void __devexit skge_remove(struct pci_dev *pdev)
+{
+ struct skge_hw *hw = pci_get_drvdata(pdev);
+ struct net_device *dev0, *dev1;
+
+ if(!hw)
+ return;
+
+ if ((dev1 = hw->dev[1]))
+ unregister_netdev(dev1);
+ dev0 = hw->dev[0];
+ unregister_netdev(dev0);
+
+ tasklet_kill(&hw->ext_tasklet);
+
+ free_irq(pdev->irq, hw);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ if (dev1)
+ free_netdev(dev1);
+ free_netdev(dev0);
+ skge_write16(hw, B0_LED, LED_STAT_OFF);
+ iounmap(hw->regs);
+ kfree(hw);
+ pci_set_drvdata(pdev, NULL);
+}
+
+#ifdef CONFIG_PM
+static int skge_suspend(struct pci_dev *pdev, u32 state)
+{
+ struct skge_hw *hw = pci_get_drvdata(pdev);
+ int i, wol = 0;
+
+ for(i = 0; i < 2; i++) {
+ struct net_device *dev = hw->dev[i];
+
+ if (dev) {
+ struct skge_port *skge = netdev_priv(dev);
+ if (netif_running(dev)) {
+ netif_carrier_off(dev);
+ skge_down(dev);
+ }
+ netif_device_detach(dev);
+ wol |= skge->wol;
+ }
+ }
+
+ pci_save_state(pdev);
+ pci_enable_wake(pdev, state, wol);
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ return 0;
+}
+
+static int skge_resume(struct pci_dev *pdev)
+{
+ struct skge_hw *hw = pci_get_drvdata(pdev);
+ int i;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+ pci_enable_wake(pdev, PCI_D0, 0);
+
+ skge_reset(hw);
+
+ for(i = 0; i < 2; i++) {
+ struct net_device *dev = hw->dev[i];
+ if (dev) {
+ netif_device_attach(dev);
+ if(netif_running(dev))
+ skge_up(dev);
+ }
+ }
+ return 0;
+}
+#endif
+
+static struct pci_driver skge_driver = {
+ .name = DRV_NAME,
+ .id_table = skge_id_table,
+ .probe = skge_probe,
+ .remove = __devexit_p(skge_remove),
+#ifdef CONFIG_PM
+ .suspend = skge_suspend,
+ .resume = skge_resume,
+#endif
+};
+
+static int __init skge_init_module(void)
+{
+ return pci_module_init(&skge_driver);
+}
+
+static void __exit skge_cleanup_module(void)
+{
+ pci_unregister_driver(&skge_driver);
+}
+
+module_init(skge_init_module);
+module_exit(skge_cleanup_module);
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
new file mode 100644
index 00000000000..36c62b68fab
--- /dev/null
+++ b/drivers/net/skge.h
@@ -0,0 +1,3005 @@
+/*
+ * Definitions for the new Marvell Yukon / SysKonenct driver.
+ */
+#ifndef _SKGE_H
+#define _SKGE_H
+
+/* PCI config registers */
+#define PCI_DEV_REG1 0x40
+#define PCI_DEV_REG2 0x44
+#ifndef PCI_VPD
+#define PCI_VPD 0x50
+#endif
+
+/* PCI_OUR_REG_2 32 bit Our Register 2 */
+enum {
+ PCI_VPD_WR_THR = 0xff<<24, /* Bit 31..24: VPD Write Threshold */
+ PCI_DEV_SEL = 0x7f<<17, /* Bit 23..17: EEPROM Device Select */
+ PCI_VPD_ROM_SZ = 7 <<14, /* Bit 16..14: VPD ROM Size */
+ /* Bit 13..12: reserved */
+ PCI_EN_DUMMY_RD = 1<<3, /* Enable Dummy Read */
+ PCI_REV_DESC = 1<<2, /* Reverse Desc. Bytes */
+ PCI_USEDATA64 = 1<<0, /* Use 64Bit Data bus ext */
+};
+
+/* PCI_VPD_ADR_REG 16 bit VPD Address Register */
+enum {
+ PCI_VPD_FLAG = 1<<15, /* starts VPD rd/wr cycle */
+ PCI_VPD_ADR_MSK =0x7fffL, /* Bit 14.. 0: VPD Address Mask */
+ VPD_RES_ID = 0x82,
+ VPD_RES_READ = 0x90,
+ VPD_RES_WRITE = 0x81,
+ VPD_RES_END = 0x78,
+};
+
+
+#define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \
+ PCI_STATUS_SIG_SYSTEM_ERROR | \
+ PCI_STATUS_REC_MASTER_ABORT | \
+ PCI_STATUS_REC_TARGET_ABORT | \
+ PCI_STATUS_PARITY)
+
+
+enum csr_regs {
+ B0_RAP = 0x0000,
+ B0_CTST = 0x0004,
+ B0_LED = 0x0006,
+ B0_POWER_CTRL = 0x0007,
+ B0_ISRC = 0x0008,
+ B0_IMSK = 0x000c,
+ B0_HWE_ISRC = 0x0010,
+ B0_HWE_IMSK = 0x0014,
+ B0_SP_ISRC = 0x0018,
+ B0_XM1_IMSK = 0x0020,
+ B0_XM1_ISRC = 0x0028,
+ B0_XM1_PHY_ADDR = 0x0030,
+ B0_XM1_PHY_DATA = 0x0034,
+ B0_XM2_IMSK = 0x0040,
+ B0_XM2_ISRC = 0x0048,
+ B0_XM2_PHY_ADDR = 0x0050,
+ B0_XM2_PHY_DATA = 0x0054,
+ B0_R1_CSR = 0x0060,
+ B0_R2_CSR = 0x0064,
+ B0_XS1_CSR = 0x0068,
+ B0_XA1_CSR = 0x006c,
+ B0_XS2_CSR = 0x0070,
+ B0_XA2_CSR = 0x0074,
+
+ B2_MAC_1 = 0x0100,
+ B2_MAC_2 = 0x0108,
+ B2_MAC_3 = 0x0110,
+ B2_CONN_TYP = 0x0118,
+ B2_PMD_TYP = 0x0119,
+ B2_MAC_CFG = 0x011a,
+ B2_CHIP_ID = 0x011b,
+ B2_E_0 = 0x011c,
+ B2_E_1 = 0x011d,
+ B2_E_2 = 0x011e,
+ B2_E_3 = 0x011f,
+ B2_FAR = 0x0120,
+ B2_FDP = 0x0124,
+ B2_LD_CTRL = 0x0128,
+ B2_LD_TEST = 0x0129,
+ B2_TI_INI = 0x0130,
+ B2_TI_VAL = 0x0134,
+ B2_TI_CTRL = 0x0138,
+ B2_TI_TEST = 0x0139,
+ B2_IRQM_INI = 0x0140,
+ B2_IRQM_VAL = 0x0144,
+ B2_IRQM_CTRL = 0x0148,
+ B2_IRQM_TEST = 0x0149,
+ B2_IRQM_MSK = 0x014c,
+ B2_IRQM_HWE_MSK = 0x0150,
+ B2_TST_CTRL1 = 0x0158,
+ B2_TST_CTRL2 = 0x0159,
+ B2_GP_IO = 0x015c,
+ B2_I2C_CTRL = 0x0160,
+ B2_I2C_DATA = 0x0164,
+ B2_I2C_IRQ = 0x0168,
+ B2_I2C_SW = 0x016c,
+ B2_BSC_INI = 0x0170,
+ B2_BSC_VAL = 0x0174,
+ B2_BSC_CTRL = 0x0178,
+ B2_BSC_STAT = 0x0179,
+ B2_BSC_TST = 0x017a,
+
+ B3_RAM_ADDR = 0x0180,
+ B3_RAM_DATA_LO = 0x0184,
+ B3_RAM_DATA_HI = 0x0188,
+ B3_RI_WTO_R1 = 0x0190,
+ B3_RI_WTO_XA1 = 0x0191,
+ B3_RI_WTO_XS1 = 0x0192,
+ B3_RI_RTO_R1 = 0x0193,
+ B3_RI_RTO_XA1 = 0x0194,
+ B3_RI_RTO_XS1 = 0x0195,
+ B3_RI_WTO_R2 = 0x0196,
+ B3_RI_WTO_XA2 = 0x0197,
+ B3_RI_WTO_XS2 = 0x0198,
+ B3_RI_RTO_R2 = 0x0199,
+ B3_RI_RTO_XA2 = 0x019a,
+ B3_RI_RTO_XS2 = 0x019b,
+ B3_RI_TO_VAL = 0x019c,
+ B3_RI_CTRL = 0x01a0,
+ B3_RI_TEST = 0x01a2,
+ B3_MA_TOINI_RX1 = 0x01b0,
+ B3_MA_TOINI_RX2 = 0x01b1,
+ B3_MA_TOINI_TX1 = 0x01b2,
+ B3_MA_TOINI_TX2 = 0x01b3,
+ B3_MA_TOVAL_RX1 = 0x01b4,
+ B3_MA_TOVAL_RX2 = 0x01b5,
+ B3_MA_TOVAL_TX1 = 0x01b6,
+ B3_MA_TOVAL_TX2 = 0x01b7,
+ B3_MA_TO_CTRL = 0x01b8,
+ B3_MA_TO_TEST = 0x01ba,
+ B3_MA_RCINI_RX1 = 0x01c0,
+ B3_MA_RCINI_RX2 = 0x01c1,
+ B3_MA_RCINI_TX1 = 0x01c2,
+ B3_MA_RCINI_TX2 = 0x01c3,
+ B3_MA_RCVAL_RX1 = 0x01c4,
+ B3_MA_RCVAL_RX2 = 0x01c5,
+ B3_MA_RCVAL_TX1 = 0x01c6,
+ B3_MA_RCVAL_TX2 = 0x01c7,
+ B3_MA_RC_CTRL = 0x01c8,
+ B3_MA_RC_TEST = 0x01ca,
+ B3_PA_TOINI_RX1 = 0x01d0,
+ B3_PA_TOINI_RX2 = 0x01d4,
+ B3_PA_TOINI_TX1 = 0x01d8,
+ B3_PA_TOINI_TX2 = 0x01dc,
+ B3_PA_TOVAL_RX1 = 0x01e0,
+ B3_PA_TOVAL_RX2 = 0x01e4,
+ B3_PA_TOVAL_TX1 = 0x01e8,
+ B3_PA_TOVAL_TX2 = 0x01ec,
+ B3_PA_CTRL = 0x01f0,
+ B3_PA_TEST = 0x01f2,
+};
+
+/* B0_CTST 16 bit Control/Status register */
+enum {
+ CS_CLK_RUN_HOT = 1<<13,/* CLK_RUN hot m. (YUKON-Lite only) */
+ CS_CLK_RUN_RST = 1<<12,/* CLK_RUN reset (YUKON-Lite only) */
+ CS_CLK_RUN_ENA = 1<<11,/* CLK_RUN enable (YUKON-Lite only) */
+ CS_VAUX_AVAIL = 1<<10,/* VAUX available (YUKON only) */
+ CS_BUS_CLOCK = 1<<9, /* Bus Clock 0/1 = 33/66 MHz */
+ CS_BUS_SLOT_SZ = 1<<8, /* Slot Size 0/1 = 32/64 bit slot */
+ CS_ST_SW_IRQ = 1<<7, /* Set IRQ SW Request */
+ CS_CL_SW_IRQ = 1<<6, /* Clear IRQ SW Request */
+ CS_STOP_DONE = 1<<5, /* Stop Master is finished */
+ CS_STOP_MAST = 1<<4, /* Command Bit to stop the master */
+ CS_MRST_CLR = 1<<3, /* Clear Master reset */
+ CS_MRST_SET = 1<<2, /* Set Master reset */
+ CS_RST_CLR = 1<<1, /* Clear Software reset */
+ CS_RST_SET = 1, /* Set Software reset */
+
+/* B0_LED 8 Bit LED register */
+/* Bit 7.. 2: reserved */
+ LED_STAT_ON = 1<<1, /* Status LED on */
+ LED_STAT_OFF = 1, /* Status LED off */
+
+/* B0_POWER_CTRL 8 Bit Power Control reg (YUKON only) */
+ PC_VAUX_ENA = 1<<7, /* Switch VAUX Enable */
+ PC_VAUX_DIS = 1<<6, /* Switch VAUX Disable */
+ PC_VCC_ENA = 1<<5, /* Switch VCC Enable */
+ PC_VCC_DIS = 1<<4, /* Switch VCC Disable */
+ PC_VAUX_ON = 1<<3, /* Switch VAUX On */
+ PC_VAUX_OFF = 1<<2, /* Switch VAUX Off */
+ PC_VCC_ON = 1<<1, /* Switch VCC On */
+ PC_VCC_OFF = 1<<0, /* Switch VCC Off */
+};
+
+/* B2_IRQM_MSK 32 bit IRQ Moderation Mask */
+enum {
+ IS_ALL_MSK = 0xbffffffful, /* All Interrupt bits */
+ IS_HW_ERR = 1<<31, /* Interrupt HW Error */
+ /* Bit 30: reserved */
+ IS_PA_TO_RX1 = 1<<29, /* Packet Arb Timeout Rx1 */
+ IS_PA_TO_RX2 = 1<<28, /* Packet Arb Timeout Rx2 */
+ IS_PA_TO_TX1 = 1<<27, /* Packet Arb Timeout Tx1 */
+ IS_PA_TO_TX2 = 1<<26, /* Packet Arb Timeout Tx2 */
+ IS_I2C_READY = 1<<25, /* IRQ on end of I2C Tx */
+ IS_IRQ_SW = 1<<24, /* SW forced IRQ */
+ IS_EXT_REG = 1<<23, /* IRQ from LM80 or PHY (GENESIS only) */
+ /* IRQ from PHY (YUKON only) */
+ IS_TIMINT = 1<<22, /* IRQ from Timer */
+ IS_MAC1 = 1<<21, /* IRQ from MAC 1 */
+ IS_LNK_SYNC_M1 = 1<<20, /* Link Sync Cnt wrap MAC 1 */
+ IS_MAC2 = 1<<19, /* IRQ from MAC 2 */
+ IS_LNK_SYNC_M2 = 1<<18, /* Link Sync Cnt wrap MAC 2 */
+/* Receive Queue 1 */
+ IS_R1_B = 1<<17, /* Q_R1 End of Buffer */
+ IS_R1_F = 1<<16, /* Q_R1 End of Frame */
+ IS_R1_C = 1<<15, /* Q_R1 Encoding Error */
+/* Receive Queue 2 */
+ IS_R2_B = 1<<14, /* Q_R2 End of Buffer */
+ IS_R2_F = 1<<13, /* Q_R2 End of Frame */
+ IS_R2_C = 1<<12, /* Q_R2 Encoding Error */
+/* Synchronous Transmit Queue 1 */
+ IS_XS1_B = 1<<11, /* Q_XS1 End of Buffer */
+ IS_XS1_F = 1<<10, /* Q_XS1 End of Frame */
+ IS_XS1_C = 1<<9, /* Q_XS1 Encoding Error */
+/* Asynchronous Transmit Queue 1 */
+ IS_XA1_B = 1<<8, /* Q_XA1 End of Buffer */
+ IS_XA1_F = 1<<7, /* Q_XA1 End of Frame */
+ IS_XA1_C = 1<<6, /* Q_XA1 Encoding Error */
+/* Synchronous Transmit Queue 2 */
+ IS_XS2_B = 1<<5, /* Q_XS2 End of Buffer */
+ IS_XS2_F = 1<<4, /* Q_XS2 End of Frame */
+ IS_XS2_C = 1<<3, /* Q_XS2 Encoding Error */
+/* Asynchronous Transmit Queue 2 */
+ IS_XA2_B = 1<<2, /* Q_XA2 End of Buffer */
+ IS_XA2_F = 1<<1, /* Q_XA2 End of Frame */
+ IS_XA2_C = 1<<0, /* Q_XA2 Encoding Error */
+
+ IS_PORT_1 = IS_XA1_F| IS_R1_F| IS_MAC1,
+ IS_PORT_2 = IS_XA2_F| IS_R2_F| IS_MAC2,
+};
+
+
+/* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */
+enum {
+ IS_ERR_MSK = 0x00003fff,/* All Error bits */
+
+ IS_IRQ_TIST_OV = 1<<13, /* Time Stamp Timer Overflow (YUKON only) */
+ IS_IRQ_SENSOR = 1<<12, /* IRQ from Sensor (YUKON only) */
+ IS_IRQ_MST_ERR = 1<<11, /* IRQ master error detected */
+ IS_IRQ_STAT = 1<<10, /* IRQ status exception */
+ IS_NO_STAT_M1 = 1<<9, /* No Rx Status from MAC 1 */
+ IS_NO_STAT_M2 = 1<<8, /* No Rx Status from MAC 2 */
+ IS_NO_TIST_M1 = 1<<7, /* No Time Stamp from MAC 1 */
+ IS_NO_TIST_M2 = 1<<6, /* No Time Stamp from MAC 2 */
+ IS_RAM_RD_PAR = 1<<5, /* RAM Read Parity Error */
+ IS_RAM_WR_PAR = 1<<4, /* RAM Write Parity Error */
+ IS_M1_PAR_ERR = 1<<3, /* MAC 1 Parity Error */
+ IS_M2_PAR_ERR = 1<<2, /* MAC 2 Parity Error */
+ IS_R1_PAR_ERR = 1<<1, /* Queue R1 Parity Error */
+ IS_R2_PAR_ERR = 1<<0, /* Queue R2 Parity Error */
+};
+
+/* B2_TST_CTRL1 8 bit Test Control Register 1 */
+enum {
+ TST_FRC_DPERR_MR = 1<<7, /* force DATAPERR on MST RD */
+ TST_FRC_DPERR_MW = 1<<6, /* force DATAPERR on MST WR */
+ TST_FRC_DPERR_TR = 1<<5, /* force DATAPERR on TRG RD */
+ TST_FRC_DPERR_TW = 1<<4, /* force DATAPERR on TRG WR */
+ TST_FRC_APERR_M = 1<<3, /* force ADDRPERR on MST */
+ TST_FRC_APERR_T = 1<<2, /* force ADDRPERR on TRG */
+ TST_CFG_WRITE_ON = 1<<1, /* Enable Config Reg WR */
+ TST_CFG_WRITE_OFF= 1<<0, /* Disable Config Reg WR */
+};
+
+/* B2_MAC_CFG 8 bit MAC Configuration / Chip Revision */
+enum {
+ CFG_CHIP_R_MSK = 0xf<<4, /* Bit 7.. 4: Chip Revision */
+ /* Bit 3.. 2: reserved */
+ CFG_DIS_M2_CLK = 1<<1, /* Disable Clock for 2nd MAC */
+ CFG_SNG_MAC = 1<<0, /* MAC Config: 0=2 MACs / 1=1 MAC*/
+};
+
+/* B2_CHIP_ID 8 bit Chip Identification Number */
+enum {
+ CHIP_ID_GENESIS = 0x0a, /* Chip ID for GENESIS */
+ CHIP_ID_YUKON = 0xb0, /* Chip ID for YUKON */
+ CHIP_ID_YUKON_LITE = 0xb1, /* Chip ID for YUKON-Lite (Rev. A1-A3) */
+ CHIP_ID_YUKON_LP = 0xb2, /* Chip ID for YUKON-LP */
+ CHIP_ID_YUKON_XL = 0xb3, /* Chip ID for YUKON-2 XL */
+ CHIP_ID_YUKON_EC = 0xb6, /* Chip ID for YUKON-2 EC */
+ CHIP_ID_YUKON_FE = 0xb7, /* Chip ID for YUKON-2 FE */
+
+ CHIP_REV_YU_LITE_A1 = 3, /* Chip Rev. for YUKON-Lite A1,A2 */
+ CHIP_REV_YU_LITE_A3 = 7, /* Chip Rev. for YUKON-Lite A3 */
+};
+
+/* B2_LD_TEST 8 bit EPROM loader test register */
+enum {
+ LD_T_ON = 1<<3, /* Loader Test mode on */
+ LD_T_OFF = 1<<2, /* Loader Test mode off */
+ LD_T_STEP = 1<<1, /* Decrement FPROM addr. Counter */
+ LD_START = 1<<0, /* Start loading FPROM */
+};
+
+/* B2_TI_CTRL 8 bit Timer control */
+/* B2_IRQM_CTRL 8 bit IRQ Moderation Timer Control */
+enum {
+ TIM_START = 1<<2, /* Start Timer */
+ TIM_STOP = 1<<1, /* Stop Timer */
+ TIM_CLR_IRQ = 1<<0, /* Clear Timer IRQ (!IRQM) */
+};
+
+/* B2_TI_TEST 8 Bit Timer Test */
+/* B2_IRQM_TEST 8 bit IRQ Moderation Timer Test */
+/* B28_DPT_TST 8 bit Descriptor Poll Timer Test Reg */
+enum {
+ TIM_T_ON = 1<<2, /* Test mode on */
+ TIM_T_OFF = 1<<1, /* Test mode off */
+ TIM_T_STEP = 1<<0, /* Test step */
+};
+
+/* B28_DPT_INI 32 bit Descriptor Poll Timer Init Val */
+/* B28_DPT_VAL 32 bit Descriptor Poll Timer Curr Val */
+/* B28_DPT_CTRL 8 bit Descriptor Poll Timer Ctrl Reg */
+enum {
+ DPT_MSK = 0x00ffffffL, /* Bit 23.. 0: Desc Poll Timer Bits */
+
+ DPT_START = 1<<1, /* Start Descriptor Poll Timer */
+ DPT_STOP = 1<<0, /* Stop Descriptor Poll Timer */
+};
+
+/* B2_GP_IO 32 bit General Purpose I/O Register */
+enum {
+ GP_DIR_9 = 1<<25, /* IO_9 direct, 0=In/1=Out */
+ GP_DIR_8 = 1<<24, /* IO_8 direct, 0=In/1=Out */
+ GP_DIR_7 = 1<<23, /* IO_7 direct, 0=In/1=Out */
+ GP_DIR_6 = 1<<22, /* IO_6 direct, 0=In/1=Out */
+ GP_DIR_5 = 1<<21, /* IO_5 direct, 0=In/1=Out */
+ GP_DIR_4 = 1<<20, /* IO_4 direct, 0=In/1=Out */
+ GP_DIR_3 = 1<<19, /* IO_3 direct, 0=In/1=Out */
+ GP_DIR_2 = 1<<18, /* IO_2 direct, 0=In/1=Out */
+ GP_DIR_1 = 1<<17, /* IO_1 direct, 0=In/1=Out */
+ GP_DIR_0 = 1<<16, /* IO_0 direct, 0=In/1=Out */
+
+ GP_IO_9 = 1<<9, /* IO_9 pin */
+ GP_IO_8 = 1<<8, /* IO_8 pin */
+ GP_IO_7 = 1<<7, /* IO_7 pin */
+ GP_IO_6 = 1<<6, /* IO_6 pin */
+ GP_IO_5 = 1<<5, /* IO_5 pin */
+ GP_IO_4 = 1<<4, /* IO_4 pin */
+ GP_IO_3 = 1<<3, /* IO_3 pin */
+ GP_IO_2 = 1<<2, /* IO_2 pin */
+ GP_IO_1 = 1<<1, /* IO_1 pin */
+ GP_IO_0 = 1<<0, /* IO_0 pin */
+};
+
+/* Rx/Tx Path related Arbiter Test Registers */
+/* B3_MA_TO_TEST 16 bit MAC Arbiter Timeout Test Reg */
+/* B3_MA_RC_TEST 16 bit MAC Arbiter Recovery Test Reg */
+/* B3_PA_TEST 16 bit Packet Arbiter Test Register */
+/* Bit 15, 11, 7, and 3 are reserved in B3_PA_TEST */
+enum {
+ TX2_T_EV = 1<<15,/* TX2 Timeout/Recv Event occured */
+ TX2_T_ON = 1<<14,/* TX2 Timeout/Recv Timer Test On */
+ TX2_T_OFF = 1<<13,/* TX2 Timeout/Recv Timer Tst Off */
+ TX2_T_STEP = 1<<12,/* TX2 Timeout/Recv Timer Step */
+ TX1_T_EV = 1<<11,/* TX1 Timeout/Recv Event occured */
+ TX1_T_ON = 1<<10,/* TX1 Timeout/Recv Timer Test On */
+ TX1_T_OFF = 1<<9, /* TX1 Timeout/Recv Timer Tst Off */
+ TX1_T_STEP = 1<<8, /* TX1 Timeout/Recv Timer Step */
+ RX2_T_EV = 1<<7, /* RX2 Timeout/Recv Event occured */
+ RX2_T_ON = 1<<6, /* RX2 Timeout/Recv Timer Test On */
+ RX2_T_OFF = 1<<5, /* RX2 Timeout/Recv Timer Tst Off */
+ RX2_T_STEP = 1<<4, /* RX2 Timeout/Recv Timer Step */
+ RX1_T_EV = 1<<3, /* RX1 Timeout/Recv Event occured */
+ RX1_T_ON = 1<<2, /* RX1 Timeout/Recv Timer Test On */
+ RX1_T_OFF = 1<<1, /* RX1 Timeout/Recv Timer Tst Off */
+ RX1_T_STEP = 1<<0, /* RX1 Timeout/Recv Timer Step */
+};
+
+/* Descriptor Bit Definition */
+/* TxCtrl Transmit Buffer Control Field */
+/* RxCtrl Receive Buffer Control Field */
+enum {
+ BMU_OWN = 1<<31, /* OWN bit: 0=host/1=BMU */
+ BMU_STF = 1<<30, /* Start of Frame */
+ BMU_EOF = 1<<29, /* End of Frame */
+ BMU_IRQ_EOB = 1<<28, /* Req "End of Buffer" IRQ */
+ BMU_IRQ_EOF = 1<<27, /* Req "End of Frame" IRQ */
+ /* TxCtrl specific bits */
+ BMU_STFWD = 1<<26, /* (Tx) Store & Forward Frame */
+ BMU_NO_FCS = 1<<25, /* (Tx) Disable MAC FCS (CRC) generation */
+ BMU_SW = 1<<24, /* (Tx) 1 bit res. for SW use */
+ /* RxCtrl specific bits */
+ BMU_DEV_0 = 1<<26, /* (Rx) Transfer data to Dev0 */
+ BMU_STAT_VAL = 1<<25, /* (Rx) Rx Status Valid */
+ BMU_TIST_VAL = 1<<24, /* (Rx) Rx TimeStamp Valid */
+ /* Bit 23..16: BMU Check Opcodes */
+ BMU_CHECK = 0x55<<16, /* Default BMU check */
+ BMU_TCP_CHECK = 0x56<<16, /* Descr with TCP ext */
+ BMU_UDP_CHECK = 0x57<<16, /* Descr with UDP ext (YUKON only) */
+ BMU_BBC = 0xffffL, /* Bit 15.. 0: Buffer Byte Counter */
+};
+
+/* B2_BSC_CTRL 8 bit Blink Source Counter Control */
+enum {
+ BSC_START = 1<<1, /* Start Blink Source Counter */
+ BSC_STOP = 1<<0, /* Stop Blink Source Counter */
+};
+
+/* B2_BSC_STAT 8 bit Blink Source Counter Status */
+enum {
+ BSC_SRC = 1<<0, /* Blink Source, 0=Off / 1=On */
+};
+
+/* B2_BSC_TST 16 bit Blink Source Counter Test Reg */
+enum {
+ BSC_T_ON = 1<<2, /* Test mode on */
+ BSC_T_OFF = 1<<1, /* Test mode off */
+ BSC_T_STEP = 1<<0, /* Test step */
+};
+
+/* B3_RAM_ADDR 32 bit RAM Address, to read or write */
+ /* Bit 31..19: reserved */
+#define RAM_ADR_RAN 0x0007ffffL /* Bit 18.. 0: RAM Address Range */
+/* RAM Interface Registers */
+
+/* B3_RI_CTRL 16 bit RAM Iface Control Register */
+enum {
+ RI_CLR_RD_PERR = 1<<9, /* Clear IRQ RAM Read Parity Err */
+ RI_CLR_WR_PERR = 1<<8, /* Clear IRQ RAM Write Parity Err*/
+
+ RI_RST_CLR = 1<<1, /* Clear RAM Interface Reset */
+ RI_RST_SET = 1<<0, /* Set RAM Interface Reset */
+};
+
+/* B3_RI_TEST 8 bit RAM Iface Test Register */
+enum {
+ RI_T_EV = 1<<3, /* Timeout Event occured */
+ RI_T_ON = 1<<2, /* Timeout Timer Test On */
+ RI_T_OFF = 1<<1, /* Timeout Timer Test Off */
+ RI_T_STEP = 1<<0, /* Timeout Timer Step */
+};
+
+/* MAC Arbiter Registers */
+/* B3_MA_TO_CTRL 16 bit MAC Arbiter Timeout Ctrl Reg */
+enum {
+ MA_FOE_ON = 1<<3, /* XMAC Fast Output Enable ON */
+ MA_FOE_OFF = 1<<2, /* XMAC Fast Output Enable OFF */
+ MA_RST_CLR = 1<<1, /* Clear MAC Arbiter Reset */
+ MA_RST_SET = 1<<0, /* Set MAC Arbiter Reset */
+
+};
+
+/* Timeout values */
+#define SK_MAC_TO_53 72 /* MAC arbiter timeout */
+#define SK_PKT_TO_53 0x2000 /* Packet arbiter timeout */
+#define SK_PKT_TO_MAX 0xffff /* Maximum value */
+#define SK_RI_TO_53 36 /* RAM interface timeout */
+
+
+/* B3_MA_RC_CTRL 16 bit MAC Arbiter Recovery Ctrl Reg */
+enum {
+ MA_ENA_REC_TX2 = 1<<7, /* Enable Recovery Timer TX2 */
+ MA_DIS_REC_TX2 = 1<<6, /* Disable Recovery Timer TX2 */
+ MA_ENA_REC_TX1 = 1<<5, /* Enable Recovery Timer TX1 */
+ MA_DIS_REC_TX1 = 1<<4, /* Disable Recovery Timer TX1 */
+ MA_ENA_REC_RX2 = 1<<3, /* Enable Recovery Timer RX2 */
+ MA_DIS_REC_RX2 = 1<<2, /* Disable Recovery Timer RX2 */
+ MA_ENA_REC_RX1 = 1<<1, /* Enable Recovery Timer RX1 */
+ MA_DIS_REC_RX1 = 1<<0, /* Disable Recovery Timer RX1 */
+};
+
+/* Packet Arbiter Registers */
+/* B3_PA_CTRL 16 bit Packet Arbiter Ctrl Register */
+enum {
+ PA_CLR_TO_TX2 = 1<<13, /* Clear IRQ Packet Timeout TX2 */
+ PA_CLR_TO_TX1 = 1<<12, /* Clear IRQ Packet Timeout TX1 */
+ PA_CLR_TO_RX2 = 1<<11, /* Clear IRQ Packet Timeout RX2 */
+ PA_CLR_TO_RX1 = 1<<10, /* Clear IRQ Packet Timeout RX1 */
+ PA_ENA_TO_TX2 = 1<<9, /* Enable Timeout Timer TX2 */
+ PA_DIS_TO_TX2 = 1<<8, /* Disable Timeout Timer TX2 */
+ PA_ENA_TO_TX1 = 1<<7, /* Enable Timeout Timer TX1 */
+ PA_DIS_TO_TX1 = 1<<6, /* Disable Timeout Timer TX1 */
+ PA_ENA_TO_RX2 = 1<<5, /* Enable Timeout Timer RX2 */
+ PA_DIS_TO_RX2 = 1<<4, /* Disable Timeout Timer RX2 */
+ PA_ENA_TO_RX1 = 1<<3, /* Enable Timeout Timer RX1 */
+ PA_DIS_TO_RX1 = 1<<2, /* Disable Timeout Timer RX1 */
+ PA_RST_CLR = 1<<1, /* Clear MAC Arbiter Reset */
+ PA_RST_SET = 1<<0, /* Set MAC Arbiter Reset */
+};
+
+#define PA_ENA_TO_ALL (PA_ENA_TO_RX1 | PA_ENA_TO_RX2 |\
+ PA_ENA_TO_TX1 | PA_ENA_TO_TX2)
+
+
+/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */
+/* TXA_ITI_INI 32 bit Tx Arb Interval Timer Init Val */
+/* TXA_ITI_VAL 32 bit Tx Arb Interval Timer Value */
+/* TXA_LIM_INI 32 bit Tx Arb Limit Counter Init Val */
+/* TXA_LIM_VAL 32 bit Tx Arb Limit Counter Value */
+
+#define TXA_MAX_VAL 0x00ffffffUL /* Bit 23.. 0: Max TXA Timer/Cnt Val */
+
+/* TXA_CTRL 8 bit Tx Arbiter Control Register */
+enum {
+ TXA_ENA_FSYNC = 1<<7, /* Enable force of sync Tx queue */
+ TXA_DIS_FSYNC = 1<<6, /* Disable force of sync Tx queue */
+ TXA_ENA_ALLOC = 1<<5, /* Enable alloc of free bandwidth */
+ TXA_DIS_ALLOC = 1<<4, /* Disable alloc of free bandwidth */
+ TXA_START_RC = 1<<3, /* Start sync Rate Control */
+ TXA_STOP_RC = 1<<2, /* Stop sync Rate Control */
+ TXA_ENA_ARB = 1<<1, /* Enable Tx Arbiter */
+ TXA_DIS_ARB = 1<<0, /* Disable Tx Arbiter */
+};
+
+/*
+ * Bank 4 - 5
+ */
+/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */
+enum {
+ TXA_ITI_INI = 0x0200,/* 32 bit Tx Arb Interval Timer Init Val*/
+ TXA_ITI_VAL = 0x0204,/* 32 bit Tx Arb Interval Timer Value */
+ TXA_LIM_INI = 0x0208,/* 32 bit Tx Arb Limit Counter Init Val */
+ TXA_LIM_VAL = 0x020c,/* 32 bit Tx Arb Limit Counter Value */
+ TXA_CTRL = 0x0210,/* 8 bit Tx Arbiter Control Register */
+ TXA_TEST = 0x0211,/* 8 bit Tx Arbiter Test Register */
+ TXA_STAT = 0x0212,/* 8 bit Tx Arbiter Status Register */
+};
+
+
+enum {
+ B6_EXT_REG = 0x0300,/* External registers (GENESIS only) */
+ B7_CFG_SPC = 0x0380,/* copy of the Configuration register */
+ B8_RQ1_REGS = 0x0400,/* Receive Queue 1 */
+ B8_RQ2_REGS = 0x0480,/* Receive Queue 2 */
+ B8_TS1_REGS = 0x0600,/* Transmit sync queue 1 */
+ B8_TA1_REGS = 0x0680,/* Transmit async queue 1 */
+ B8_TS2_REGS = 0x0700,/* Transmit sync queue 2 */
+ B8_TA2_REGS = 0x0780,/* Transmit sync queue 2 */
+ B16_RAM_REGS = 0x0800,/* RAM Buffer Registers */
+};
+
+/* Queue Register Offsets, use Q_ADDR() to access */
+enum {
+ B8_Q_REGS = 0x0400, /* base of Queue registers */
+ Q_D = 0x00, /* 8*32 bit Current Descriptor */
+ Q_DA_L = 0x20, /* 32 bit Current Descriptor Address Low dWord */
+ Q_DA_H = 0x24, /* 32 bit Current Descriptor Address High dWord */
+ Q_AC_L = 0x28, /* 32 bit Current Address Counter Low dWord */
+ Q_AC_H = 0x2c, /* 32 bit Current Address Counter High dWord */
+ Q_BC = 0x30, /* 32 bit Current Byte Counter */
+ Q_CSR = 0x34, /* 32 bit BMU Control/Status Register */
+ Q_F = 0x38, /* 32 bit Flag Register */
+ Q_T1 = 0x3c, /* 32 bit Test Register 1 */
+ Q_T1_TR = 0x3c, /* 8 bit Test Register 1 Transfer SM */
+ Q_T1_WR = 0x3d, /* 8 bit Test Register 1 Write Descriptor SM */
+ Q_T1_RD = 0x3e, /* 8 bit Test Register 1 Read Descriptor SM */
+ Q_T1_SV = 0x3f, /* 8 bit Test Register 1 Supervisor SM */
+ Q_T2 = 0x40, /* 32 bit Test Register 2 */
+ Q_T3 = 0x44, /* 32 bit Test Register 3 */
+
+/* Yukon-2 */
+ Q_DONE = 0x24, /* 16 bit Done Index (Yukon-2 only) */
+ Q_WM = 0x40, /* 16 bit FIFO Watermark */
+ Q_AL = 0x42, /* 8 bit FIFO Alignment */
+ Q_RSP = 0x44, /* 16 bit FIFO Read Shadow Pointer */
+ Q_RSL = 0x46, /* 8 bit FIFO Read Shadow Level */
+ Q_RP = 0x48, /* 8 bit FIFO Read Pointer */
+ Q_RL = 0x4a, /* 8 bit FIFO Read Level */
+ Q_WP = 0x4c, /* 8 bit FIFO Write Pointer */
+ Q_WSP = 0x4d, /* 8 bit FIFO Write Shadow Pointer */
+ Q_WL = 0x4e, /* 8 bit FIFO Write Level */
+ Q_WSL = 0x4f, /* 8 bit FIFO Write Shadow Level */
+};
+#define Q_ADDR(reg, offs) (B8_Q_REGS + (reg) + (offs))
+
+/* RAM Buffer Register Offsets */
+enum {
+
+ RB_START = 0x00,/* 32 bit RAM Buffer Start Address */
+ RB_END = 0x04,/* 32 bit RAM Buffer End Address */
+ RB_WP = 0x08,/* 32 bit RAM Buffer Write Pointer */
+ RB_RP = 0x0c,/* 32 bit RAM Buffer Read Pointer */
+ RB_RX_UTPP = 0x10,/* 32 bit Rx Upper Threshold, Pause Packet */
+ RB_RX_LTPP = 0x14,/* 32 bit Rx Lower Threshold, Pause Packet */
+ RB_RX_UTHP = 0x18,/* 32 bit Rx Upper Threshold, High Prio */
+ RB_RX_LTHP = 0x1c,/* 32 bit Rx Lower Threshold, High Prio */
+ /* 0x10 - 0x1f: reserved at Tx RAM Buffer Registers */
+ RB_PC = 0x20,/* 32 bit RAM Buffer Packet Counter */
+ RB_LEV = 0x24,/* 32 bit RAM Buffer Level Register */
+ RB_CTRL = 0x28,/* 32 bit RAM Buffer Control Register */
+ RB_TST1 = 0x29,/* 8 bit RAM Buffer Test Register 1 */
+ RB_TST2 = 0x2a,/* 8 bit RAM Buffer Test Register 2 */
+};
+
+/* Receive and Transmit Queues */
+enum {
+ Q_R1 = 0x0000, /* Receive Queue 1 */
+ Q_R2 = 0x0080, /* Receive Queue 2 */
+ Q_XS1 = 0x0200, /* Synchronous Transmit Queue 1 */
+ Q_XA1 = 0x0280, /* Asynchronous Transmit Queue 1 */
+ Q_XS2 = 0x0300, /* Synchronous Transmit Queue 2 */
+ Q_XA2 = 0x0380, /* Asynchronous Transmit Queue 2 */
+};
+
+/* Different MAC Types */
+enum {
+ SK_MAC_XMAC = 0, /* Xaqti XMAC II */
+ SK_MAC_GMAC = 1, /* Marvell GMAC */
+};
+
+/* Different PHY Types */
+enum {
+ SK_PHY_XMAC = 0,/* integrated in XMAC II */
+ SK_PHY_BCOM = 1,/* Broadcom BCM5400 */
+ SK_PHY_LONE = 2,/* Level One LXT1000 [not supported]*/
+ SK_PHY_NAT = 3,/* National DP83891 [not supported] */
+ SK_PHY_MARV_COPPER= 4,/* Marvell 88E1011S */
+ SK_PHY_MARV_FIBER = 5,/* Marvell 88E1011S working on fiber */
+};
+
+/* PHY addresses (bits 12..8 of PHY address reg) */
+enum {
+ PHY_ADDR_XMAC = 0<<8,
+ PHY_ADDR_BCOM = 1<<8,
+ PHY_ADDR_LONE = 3<<8,
+ PHY_ADDR_NAT = 0<<8,
+/* GPHY address (bits 15..11 of SMI control reg) */
+ PHY_ADDR_MARV = 0,
+};
+
+#define RB_ADDR(offs, queue) (B16_RAM_REGS + (queue) + (offs))
+
+/* Receive MAC FIFO, Receive LED, and Link_Sync regs (GENESIS only) */
+enum {
+ RX_MFF_EA = 0x0c00,/* 32 bit Receive MAC FIFO End Address */
+ RX_MFF_WP = 0x0c04,/* 32 bit Receive MAC FIFO Write Pointer */
+
+ RX_MFF_RP = 0x0c0c,/* 32 bit Receive MAC FIFO Read Pointer */
+ RX_MFF_PC = 0x0c10,/* 32 bit Receive MAC FIFO Packet Cnt */
+ RX_MFF_LEV = 0x0c14,/* 32 bit Receive MAC FIFO Level */
+ RX_MFF_CTRL1 = 0x0c18,/* 16 bit Receive MAC FIFO Control Reg 1*/
+ RX_MFF_STAT_TO = 0x0c1a,/* 8 bit Receive MAC Status Timeout */
+ RX_MFF_TIST_TO = 0x0c1b,/* 8 bit Receive MAC Time Stamp Timeout */
+ RX_MFF_CTRL2 = 0x0c1c,/* 8 bit Receive MAC FIFO Control Reg 2*/
+ RX_MFF_TST1 = 0x0c1d,/* 8 bit Receive MAC FIFO Test Reg 1 */
+ RX_MFF_TST2 = 0x0c1e,/* 8 bit Receive MAC FIFO Test Reg 2 */
+
+ RX_LED_INI = 0x0c20,/* 32 bit Receive LED Cnt Init Value */
+ RX_LED_VAL = 0x0c24,/* 32 bit Receive LED Cnt Current Value */
+ RX_LED_CTRL = 0x0c28,/* 8 bit Receive LED Cnt Control Reg */
+ RX_LED_TST = 0x0c29,/* 8 bit Receive LED Cnt Test Register */
+
+ LNK_SYNC_INI = 0x0c30,/* 32 bit Link Sync Cnt Init Value */
+ LNK_SYNC_VAL = 0x0c34,/* 32 bit Link Sync Cnt Current Value */
+ LNK_SYNC_CTRL = 0x0c38,/* 8 bit Link Sync Cnt Control Register */
+ LNK_SYNC_TST = 0x0c39,/* 8 bit Link Sync Cnt Test Register */
+ LNK_LED_REG = 0x0c3c,/* 8 bit Link LED Register */
+};
+
+/* Receive and Transmit MAC FIFO Registers (GENESIS only) */
+/* RX_MFF_CTRL1 16 bit Receive MAC FIFO Control Reg 1 */
+enum {
+ MFF_ENA_RDY_PAT = 1<<13, /* Enable Ready Patch */
+ MFF_DIS_RDY_PAT = 1<<12, /* Disable Ready Patch */
+ MFF_ENA_TIM_PAT = 1<<11, /* Enable Timing Patch */
+ MFF_DIS_TIM_PAT = 1<<10, /* Disable Timing Patch */
+ MFF_ENA_ALM_FUL = 1<<9, /* Enable AlmostFull Sign */
+ MFF_DIS_ALM_FUL = 1<<8, /* Disable AlmostFull Sign */
+ MFF_ENA_PAUSE = 1<<7, /* Enable Pause Signaling */
+ MFF_DIS_PAUSE = 1<<6, /* Disable Pause Signaling */
+ MFF_ENA_FLUSH = 1<<5, /* Enable Frame Flushing */
+ MFF_DIS_FLUSH = 1<<4, /* Disable Frame Flushing */
+ MFF_ENA_TIST = 1<<3, /* Enable Time Stamp Gener */
+ MFF_DIS_TIST = 1<<2, /* Disable Time Stamp Gener */
+ MFF_CLR_INTIST = 1<<1, /* Clear IRQ No Time Stamp */
+ MFF_CLR_INSTAT = 1<<0, /* Clear IRQ No Status */
+#define MFF_RX_CTRL_DEF MFF_ENA_TIM_PAT
+};
+
+/* TX_MFF_CTRL1 16 bit Transmit MAC FIFO Control Reg 1 */
+enum {
+ MFF_CLR_PERR = 1<<15, /* Clear Parity Error IRQ */
+ /* Bit 14: reserved */
+ MFF_ENA_PKT_REC = 1<<13, /* Enable Packet Recovery */
+ MFF_DIS_PKT_REC = 1<<12, /* Disable Packet Recovery */
+
+ MFF_ENA_W4E = 1<<7, /* Enable Wait for Empty */
+ MFF_DIS_W4E = 1<<6, /* Disable Wait for Empty */
+
+ MFF_ENA_LOOPB = 1<<3, /* Enable Loopback */
+ MFF_DIS_LOOPB = 1<<2, /* Disable Loopback */
+ MFF_CLR_MAC_RST = 1<<1, /* Clear XMAC Reset */
+ MFF_SET_MAC_RST = 1<<0, /* Set XMAC Reset */
+};
+
+#define MFF_TX_CTRL_DEF (MFF_ENA_PKT_REC | MFF_ENA_TIM_PAT | MFF_ENA_FLUSH)
+
+/* RX_MFF_TST2 8 bit Receive MAC FIFO Test Register 2 */
+/* TX_MFF_TST2 8 bit Transmit MAC FIFO Test Register 2 */
+enum {
+ MFF_WSP_T_ON = 1<<6, /* Tx: Write Shadow Ptr TestOn */
+ MFF_WSP_T_OFF = 1<<5, /* Tx: Write Shadow Ptr TstOff */
+ MFF_WSP_INC = 1<<4, /* Tx: Write Shadow Ptr Increment */
+ MFF_PC_DEC = 1<<3, /* Packet Counter Decrement */
+ MFF_PC_T_ON = 1<<2, /* Packet Counter Test On */
+ MFF_PC_T_OFF = 1<<1, /* Packet Counter Test Off */
+ MFF_PC_INC = 1<<0, /* Packet Counter Increment */
+};
+
+/* RX_MFF_TST1 8 bit Receive MAC FIFO Test Register 1 */
+/* TX_MFF_TST1 8 bit Transmit MAC FIFO Test Register 1 */
+enum {
+ MFF_WP_T_ON = 1<<6, /* Write Pointer Test On */
+ MFF_WP_T_OFF = 1<<5, /* Write Pointer Test Off */
+ MFF_WP_INC = 1<<4, /* Write Pointer Increm */
+
+ MFF_RP_T_ON = 1<<2, /* Read Pointer Test On */
+ MFF_RP_T_OFF = 1<<1, /* Read Pointer Test Off */
+ MFF_RP_DEC = 1<<0, /* Read Pointer Decrement */
+};
+
+/* RX_MFF_CTRL2 8 bit Receive MAC FIFO Control Reg 2 */
+/* TX_MFF_CTRL2 8 bit Transmit MAC FIFO Control Reg 2 */
+enum {
+ MFF_ENA_OP_MD = 1<<3, /* Enable Operation Mode */
+ MFF_DIS_OP_MD = 1<<2, /* Disable Operation Mode */
+ MFF_RST_CLR = 1<<1, /* Clear MAC FIFO Reset */
+ MFF_RST_SET = 1<<0, /* Set MAC FIFO Reset */
+};
+
+
+/* Link LED Counter Registers (GENESIS only) */
+
+/* RX_LED_CTRL 8 bit Receive LED Cnt Control Reg */
+/* TX_LED_CTRL 8 bit Transmit LED Cnt Control Reg */
+/* LNK_SYNC_CTRL 8 bit Link Sync Cnt Control Register */
+enum {
+ LED_START = 1<<2, /* Start Timer */
+ LED_STOP = 1<<1, /* Stop Timer */
+ LED_STATE = 1<<0, /* Rx/Tx: LED State, 1=LED on */
+};
+
+/* RX_LED_TST 8 bit Receive LED Cnt Test Register */
+/* TX_LED_TST 8 bit Transmit LED Cnt Test Register */
+/* LNK_SYNC_TST 8 bit Link Sync Cnt Test Register */
+enum {
+ LED_T_ON = 1<<2, /* LED Counter Test mode On */
+ LED_T_OFF = 1<<1, /* LED Counter Test mode Off */
+ LED_T_STEP = 1<<0, /* LED Counter Step */
+};
+
+/* LNK_LED_REG 8 bit Link LED Register */
+enum {
+ LED_BLK_ON = 1<<5, /* Link LED Blinking On */
+ LED_BLK_OFF = 1<<4, /* Link LED Blinking Off */
+ LED_SYNC_ON = 1<<3, /* Use Sync Wire to switch LED */
+ LED_SYNC_OFF = 1<<2, /* Disable Sync Wire Input */
+ LED_ON = 1<<1, /* switch LED on */
+ LED_OFF = 1<<0, /* switch LED off */
+};
+
+/* Receive GMAC FIFO (YUKON and Yukon-2) */
+enum {
+ RX_GMF_EA = 0x0c40,/* 32 bit Rx GMAC FIFO End Address */
+ RX_GMF_AF_THR = 0x0c44,/* 32 bit Rx GMAC FIFO Almost Full Thresh. */
+ RX_GMF_CTRL_T = 0x0c48,/* 32 bit Rx GMAC FIFO Control/Test */
+ RX_GMF_FL_MSK = 0x0c4c,/* 32 bit Rx GMAC FIFO Flush Mask */
+ RX_GMF_FL_THR = 0x0c50,/* 32 bit Rx GMAC FIFO Flush Threshold */
+ RX_GMF_TR_THR = 0x0c54,/* 32 bit Rx Truncation Threshold (Yukon-2) */
+
+ RX_GMF_VLAN = 0x0c5c,/* 32 bit Rx VLAN Type Register (Yukon-2) */
+ RX_GMF_WP = 0x0c60,/* 32 bit Rx GMAC FIFO Write Pointer */
+
+ RX_GMF_WLEV = 0x0c68,/* 32 bit Rx GMAC FIFO Write Level */
+
+ RX_GMF_RP = 0x0c70,/* 32 bit Rx GMAC FIFO Read Pointer */
+
+ RX_GMF_RLEV = 0x0c78,/* 32 bit Rx GMAC FIFO Read Level */
+};
+
+
+/* TXA_TEST 8 bit Tx Arbiter Test Register */
+enum {
+ TXA_INT_T_ON = 1<<5, /* Tx Arb Interval Timer Test On */
+ TXA_INT_T_OFF = 1<<4, /* Tx Arb Interval Timer Test Off */
+ TXA_INT_T_STEP = 1<<3, /* Tx Arb Interval Timer Step */
+ TXA_LIM_T_ON = 1<<2, /* Tx Arb Limit Timer Test On */
+ TXA_LIM_T_OFF = 1<<1, /* Tx Arb Limit Timer Test Off */
+ TXA_LIM_T_STEP = 1<<0, /* Tx Arb Limit Timer Step */
+};
+
+/* TXA_STAT 8 bit Tx Arbiter Status Register */
+enum {
+ TXA_PRIO_XS = 1<<0, /* sync queue has prio to send */
+};
+
+
+/* Q_BC 32 bit Current Byte Counter */
+
+/* BMU Control Status Registers */
+/* B0_R1_CSR 32 bit BMU Ctrl/Stat Rx Queue 1 */
+/* B0_R2_CSR 32 bit BMU Ctrl/Stat Rx Queue 2 */
+/* B0_XA1_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */
+/* B0_XS1_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 1 */
+/* B0_XA2_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 2 */
+/* B0_XS2_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 2 */
+/* Q_CSR 32 bit BMU Control/Status Register */
+
+enum {
+ CSR_SV_IDLE = 1<<24, /* BMU SM Idle */
+
+ CSR_DESC_CLR = 1<<21, /* Clear Reset for Descr */
+ CSR_DESC_SET = 1<<20, /* Set Reset for Descr */
+ CSR_FIFO_CLR = 1<<19, /* Clear Reset for FIFO */
+ CSR_FIFO_SET = 1<<18, /* Set Reset for FIFO */
+ CSR_HPI_RUN = 1<<17, /* Release HPI SM */
+ CSR_HPI_RST = 1<<16, /* Reset HPI SM to Idle */
+ CSR_SV_RUN = 1<<15, /* Release Supervisor SM */
+ CSR_SV_RST = 1<<14, /* Reset Supervisor SM */
+ CSR_DREAD_RUN = 1<<13, /* Release Descr Read SM */
+ CSR_DREAD_RST = 1<<12, /* Reset Descr Read SM */
+ CSR_DWRITE_RUN = 1<<11, /* Release Descr Write SM */
+ CSR_DWRITE_RST = 1<<10, /* Reset Descr Write SM */
+ CSR_TRANS_RUN = 1<<9, /* Release Transfer SM */
+ CSR_TRANS_RST = 1<<8, /* Reset Transfer SM */
+ CSR_ENA_POL = 1<<7, /* Enable Descr Polling */
+ CSR_DIS_POL = 1<<6, /* Disable Descr Polling */
+ CSR_STOP = 1<<5, /* Stop Rx/Tx Queue */
+ CSR_START = 1<<4, /* Start Rx/Tx Queue */
+ CSR_IRQ_CL_P = 1<<3, /* (Rx) Clear Parity IRQ */
+ CSR_IRQ_CL_B = 1<<2, /* Clear EOB IRQ */
+ CSR_IRQ_CL_F = 1<<1, /* Clear EOF IRQ */
+ CSR_IRQ_CL_C = 1<<0, /* Clear ERR IRQ */
+};
+
+#define CSR_SET_RESET (CSR_DESC_SET | CSR_FIFO_SET | CSR_HPI_RST |\
+ CSR_SV_RST | CSR_DREAD_RST | CSR_DWRITE_RST |\
+ CSR_TRANS_RST)
+#define CSR_CLR_RESET (CSR_DESC_CLR | CSR_FIFO_CLR | CSR_HPI_RUN |\
+ CSR_SV_RUN | CSR_DREAD_RUN | CSR_DWRITE_RUN |\
+ CSR_TRANS_RUN)
+
+/* Q_F 32 bit Flag Register */
+enum {
+ F_ALM_FULL = 1<<27, /* Rx FIFO: almost full */
+ F_EMPTY = 1<<27, /* Tx FIFO: empty flag */
+ F_FIFO_EOF = 1<<26, /* Tag (EOF Flag) bit in FIFO */
+ F_WM_REACHED = 1<<25, /* Watermark reached */
+
+ F_FIFO_LEVEL = 0x1fL<<16, /* Bit 23..16: # of Qwords in FIFO */
+ F_WATER_MARK = 0x0007ffL, /* Bit 10.. 0: Watermark */
+};
+
+/* RAM Buffer Register Offsets, use RB_ADDR(Queue, Offs) to access */
+/* RB_START 32 bit RAM Buffer Start Address */
+/* RB_END 32 bit RAM Buffer End Address */
+/* RB_WP 32 bit RAM Buffer Write Pointer */
+/* RB_RP 32 bit RAM Buffer Read Pointer */
+/* RB_RX_UTPP 32 bit Rx Upper Threshold, Pause Pack */
+/* RB_RX_LTPP 32 bit Rx Lower Threshold, Pause Pack */
+/* RB_RX_UTHP 32 bit Rx Upper Threshold, High Prio */
+/* RB_RX_LTHP 32 bit Rx Lower Threshold, High Prio */
+/* RB_PC 32 bit RAM Buffer Packet Counter */
+/* RB_LEV 32 bit RAM Buffer Level Register */
+
+#define RB_MSK 0x0007ffff /* Bit 18.. 0: RAM Buffer Pointer Bits */
+/* RB_TST2 8 bit RAM Buffer Test Register 2 */
+/* RB_TST1 8 bit RAM Buffer Test Register 1 */
+
+/* RB_CTRL 8 bit RAM Buffer Control Register */
+enum {
+ RB_ENA_STFWD = 1<<5, /* Enable Store & Forward */
+ RB_DIS_STFWD = 1<<4, /* Disable Store & Forward */
+ RB_ENA_OP_MD = 1<<3, /* Enable Operation Mode */
+ RB_DIS_OP_MD = 1<<2, /* Disable Operation Mode */
+ RB_RST_CLR = 1<<1, /* Clear RAM Buf STM Reset */
+ RB_RST_SET = 1<<0, /* Set RAM Buf STM Reset */
+};
+
+/* Transmit MAC FIFO and Transmit LED Registers (GENESIS only), */
+enum {
+ TX_MFF_EA = 0x0d00,/* 32 bit Transmit MAC FIFO End Address */
+ TX_MFF_WP = 0x0d04,/* 32 bit Transmit MAC FIFO WR Pointer */
+ TX_MFF_WSP = 0x0d08,/* 32 bit Transmit MAC FIFO WR Shadow Ptr */
+ TX_MFF_RP = 0x0d0c,/* 32 bit Transmit MAC FIFO RD Pointer */
+ TX_MFF_PC = 0x0d10,/* 32 bit Transmit MAC FIFO Packet Cnt */
+ TX_MFF_LEV = 0x0d14,/* 32 bit Transmit MAC FIFO Level */
+ TX_MFF_CTRL1 = 0x0d18,/* 16 bit Transmit MAC FIFO Ctrl Reg 1 */
+ TX_MFF_WAF = 0x0d1a,/* 8 bit Transmit MAC Wait after flush */
+
+ TX_MFF_CTRL2 = 0x0d1c,/* 8 bit Transmit MAC FIFO Ctrl Reg 2 */
+ TX_MFF_TST1 = 0x0d1d,/* 8 bit Transmit MAC FIFO Test Reg 1 */
+ TX_MFF_TST2 = 0x0d1e,/* 8 bit Transmit MAC FIFO Test Reg 2 */
+
+ TX_LED_INI = 0x0d20,/* 32 bit Transmit LED Cnt Init Value */
+ TX_LED_VAL = 0x0d24,/* 32 bit Transmit LED Cnt Current Val */
+ TX_LED_CTRL = 0x0d28,/* 8 bit Transmit LED Cnt Control Reg */
+ TX_LED_TST = 0x0d29,/* 8 bit Transmit LED Cnt Test Reg */
+};
+
+/* Counter and Timer constants, for a host clock of 62.5 MHz */
+#define SK_XMIT_DUR 0x002faf08UL /* 50 ms */
+#define SK_BLK_DUR 0x01dcd650UL /* 500 ms */
+
+#define SK_DPOLL_DEF 0x00ee6b28UL /* 250 ms at 62.5 MHz */
+
+#define SK_DPOLL_MAX 0x00ffffffUL /* 268 ms at 62.5 MHz */
+ /* 215 ms at 78.12 MHz */
+
+#define SK_FACT_62 100 /* is given in percent */
+#define SK_FACT_53 85 /* on GENESIS: 53.12 MHz */
+#define SK_FACT_78 125 /* on YUKON: 78.12 MHz */
+
+
+/* Transmit GMAC FIFO (YUKON only) */
+enum {
+ TX_GMF_EA = 0x0d40,/* 32 bit Tx GMAC FIFO End Address */
+ TX_GMF_AE_THR = 0x0d44,/* 32 bit Tx GMAC FIFO Almost Empty Thresh.*/
+ TX_GMF_CTRL_T = 0x0d48,/* 32 bit Tx GMAC FIFO Control/Test */
+
+ TX_GMF_WP = 0x0d60,/* 32 bit Tx GMAC FIFO Write Pointer */
+ TX_GMF_WSP = 0x0d64,/* 32 bit Tx GMAC FIFO Write Shadow Ptr. */
+ TX_GMF_WLEV = 0x0d68,/* 32 bit Tx GMAC FIFO Write Level */
+
+ TX_GMF_RP = 0x0d70,/* 32 bit Tx GMAC FIFO Read Pointer */
+ TX_GMF_RSTP = 0x0d74,/* 32 bit Tx GMAC FIFO Restart Pointer */
+ TX_GMF_RLEV = 0x0d78,/* 32 bit Tx GMAC FIFO Read Level */
+
+ /* Descriptor Poll Timer Registers */
+ B28_DPT_INI = 0x0e00,/* 24 bit Descriptor Poll Timer Init Val */
+ B28_DPT_VAL = 0x0e04,/* 24 bit Descriptor Poll Timer Curr Val */
+ B28_DPT_CTRL = 0x0e08,/* 8 bit Descriptor Poll Timer Ctrl Reg */
+
+ B28_DPT_TST = 0x0e0a,/* 8 bit Descriptor Poll Timer Test Reg */
+
+ /* Time Stamp Timer Registers (YUKON only) */
+ GMAC_TI_ST_VAL = 0x0e14,/* 32 bit Time Stamp Timer Curr Val */
+ GMAC_TI_ST_CTRL = 0x0e18,/* 8 bit Time Stamp Timer Ctrl Reg */
+ GMAC_TI_ST_TST = 0x0e1a,/* 8 bit Time Stamp Timer Test Reg */
+};
+
+/* Status BMU Registers (Yukon-2 only)*/
+enum {
+ STAT_CTRL = 0x0e80,/* 32 bit Status BMU Control Reg */
+ STAT_LAST_IDX = 0x0e84,/* 16 bit Status BMU Last Index */
+ /* 0x0e85 - 0x0e86: reserved */
+ STAT_LIST_ADDR_LO = 0x0e88,/* 32 bit Status List Start Addr (low) */
+ STAT_LIST_ADDR_HI = 0x0e8c,/* 32 bit Status List Start Addr (high) */
+ STAT_TXA1_RIDX = 0x0e90,/* 16 bit Status TxA1 Report Index Reg */
+ STAT_TXS1_RIDX = 0x0e92,/* 16 bit Status TxS1 Report Index Reg */
+ STAT_TXA2_RIDX = 0x0e94,/* 16 bit Status TxA2 Report Index Reg */
+ STAT_TXS2_RIDX = 0x0e96,/* 16 bit Status TxS2 Report Index Reg */
+ STAT_TX_IDX_TH = 0x0e98,/* 16 bit Status Tx Index Threshold Reg */
+ STAT_PUT_IDX = 0x0e9c,/* 16 bit Status Put Index Reg */
+
+/* FIFO Control/Status Registers (Yukon-2 only)*/
+ STAT_FIFO_WP = 0x0ea0,/* 8 bit Status FIFO Write Pointer Reg */
+ STAT_FIFO_RP = 0x0ea4,/* 8 bit Status FIFO Read Pointer Reg */
+ STAT_FIFO_RSP = 0x0ea6,/* 8 bit Status FIFO Read Shadow Ptr */
+ STAT_FIFO_LEVEL = 0x0ea8,/* 8 bit Status FIFO Level Reg */
+ STAT_FIFO_SHLVL = 0x0eaa,/* 8 bit Status FIFO Shadow Level Reg */
+ STAT_FIFO_WM = 0x0eac,/* 8 bit Status FIFO Watermark Reg */
+ STAT_FIFO_ISR_WM = 0x0ead,/* 8 bit Status FIFO ISR Watermark Reg */
+
+/* Level and ISR Timer Registers (Yukon-2 only)*/
+ STAT_LEV_TIMER_INI = 0x0eb0,/* 32 bit Level Timer Init. Value Reg */
+ STAT_LEV_TIMER_CNT = 0x0eb4,/* 32 bit Level Timer Counter Reg */
+ STAT_LEV_TIMER_CTRL = 0x0eb8,/* 8 bit Level Timer Control Reg */
+ STAT_LEV_TIMER_TEST = 0x0eb9,/* 8 bit Level Timer Test Reg */
+ STAT_TX_TIMER_INI = 0x0ec0,/* 32 bit Tx Timer Init. Value Reg */
+ STAT_TX_TIMER_CNT = 0x0ec4,/* 32 bit Tx Timer Counter Reg */
+ STAT_TX_TIMER_CTRL = 0x0ec8,/* 8 bit Tx Timer Control Reg */
+ STAT_TX_TIMER_TEST = 0x0ec9,/* 8 bit Tx Timer Test Reg */
+ STAT_ISR_TIMER_INI = 0x0ed0,/* 32 bit ISR Timer Init. Value Reg */
+ STAT_ISR_TIMER_CNT = 0x0ed4,/* 32 bit ISR Timer Counter Reg */
+ STAT_ISR_TIMER_CTRL = 0x0ed8,/* 8 bit ISR Timer Control Reg */
+ STAT_ISR_TIMER_TEST = 0x0ed9,/* 8 bit ISR Timer Test Reg */
+
+ ST_LAST_IDX_MASK = 0x007f,/* Last Index Mask */
+ ST_TXRP_IDX_MASK = 0x0fff,/* Tx Report Index Mask */
+ ST_TXTH_IDX_MASK = 0x0fff,/* Tx Threshold Index Mask */
+ ST_WM_IDX_MASK = 0x3f,/* FIFO Watermark Index Mask */
+};
+
+enum {
+ LINKLED_OFF = 0x01,
+ LINKLED_ON = 0x02,
+ LINKLED_LINKSYNC_OFF = 0x04,
+ LINKLED_LINKSYNC_ON = 0x08,
+ LINKLED_BLINK_OFF = 0x10,
+ LINKLED_BLINK_ON = 0x20,
+};
+
+/* GMAC and GPHY Control Registers (YUKON only) */
+enum {
+ GMAC_CTRL = 0x0f00,/* 32 bit GMAC Control Reg */
+ GPHY_CTRL = 0x0f04,/* 32 bit GPHY Control Reg */
+ GMAC_IRQ_SRC = 0x0f08,/* 8 bit GMAC Interrupt Source Reg */
+ GMAC_IRQ_MSK = 0x0f0c,/* 8 bit GMAC Interrupt Mask Reg */
+ GMAC_LINK_CTRL = 0x0f10,/* 16 bit Link Control Reg */
+
+/* Wake-up Frame Pattern Match Control Registers (YUKON only) */
+
+ WOL_REG_OFFS = 0x20,/* HW-Bug: Address is + 0x20 against spec. */
+
+ WOL_CTRL_STAT = 0x0f20,/* 16 bit WOL Control/Status Reg */
+ WOL_MATCH_CTL = 0x0f22,/* 8 bit WOL Match Control Reg */
+ WOL_MATCH_RES = 0x0f23,/* 8 bit WOL Match Result Reg */
+ WOL_MAC_ADDR = 0x0f24,/* 32 bit WOL MAC Address */
+ WOL_PATT_PME = 0x0f2a,/* 8 bit WOL PME Match Enable (Yukon-2) */
+ WOL_PATT_ASFM = 0x0f2b,/* 8 bit WOL ASF Match Enable (Yukon-2) */
+ WOL_PATT_RPTR = 0x0f2c,/* 8 bit WOL Pattern Read Pointer */
+
+/* WOL Pattern Length Registers (YUKON only) */
+
+ WOL_PATT_LEN_LO = 0x0f30,/* 32 bit WOL Pattern Length 3..0 */
+ WOL_PATT_LEN_HI = 0x0f34,/* 24 bit WOL Pattern Length 6..4 */
+
+/* WOL Pattern Counter Registers (YUKON only) */
+
+ WOL_PATT_CNT_0 = 0x0f38,/* 32 bit WOL Pattern Counter 3..0 */
+ WOL_PATT_CNT_4 = 0x0f3c,/* 24 bit WOL Pattern Counter 6..4 */
+};
+
+enum {
+ WOL_PATT_RAM_1 = 0x1000,/* WOL Pattern RAM Link 1 */
+ WOL_PATT_RAM_2 = 0x1400,/* WOL Pattern RAM Link 2 */
+};
+
+enum {
+ BASE_XMAC_1 = 0x2000,/* XMAC 1 registers */
+ BASE_GMAC_1 = 0x2800,/* GMAC 1 registers */
+ BASE_XMAC_2 = 0x3000,/* XMAC 2 registers */
+ BASE_GMAC_2 = 0x3800,/* GMAC 2 registers */
+};
+
+/*
+ * Receive Frame Status Encoding
+ */
+enum {
+ XMR_FS_LEN = 0x3fff<<18, /* Bit 31..18: Rx Frame Length */
+ XMR_FS_2L_VLAN = 1<<17, /* Bit 17: tagged wh 2Lev VLAN ID*/
+ XMR_FS_1_VLAN = 1<<16, /* Bit 16: tagged wh 1ev VLAN ID*/
+ XMR_FS_BC = 1<<15, /* Bit 15: Broadcast Frame */
+ XMR_FS_MC = 1<<14, /* Bit 14: Multicast Frame */
+ XMR_FS_UC = 1<<13, /* Bit 13: Unicast Frame */
+
+ XMR_FS_BURST = 1<<11, /* Bit 11: Burst Mode */
+ XMR_FS_CEX_ERR = 1<<10, /* Bit 10: Carrier Ext. Error */
+ XMR_FS_802_3 = 1<<9, /* Bit 9: 802.3 Frame */
+ XMR_FS_COL_ERR = 1<<8, /* Bit 8: Collision Error */
+ XMR_FS_CAR_ERR = 1<<7, /* Bit 7: Carrier Event Error */
+ XMR_FS_LEN_ERR = 1<<6, /* Bit 6: In-Range Length Error */
+ XMR_FS_FRA_ERR = 1<<5, /* Bit 5: Framing Error */
+ XMR_FS_RUNT = 1<<4, /* Bit 4: Runt Frame */
+ XMR_FS_LNG_ERR = 1<<3, /* Bit 3: Giant (Jumbo) Frame */
+ XMR_FS_FCS_ERR = 1<<2, /* Bit 2: Frame Check Sequ Err */
+ XMR_FS_ERR = 1<<1, /* Bit 1: Frame Error */
+ XMR_FS_MCTRL = 1<<0, /* Bit 0: MAC Control Packet */
+
+/*
+ * XMR_FS_ERR will be set if
+ * XMR_FS_FCS_ERR, XMR_FS_LNG_ERR, XMR_FS_RUNT,
+ * XMR_FS_FRA_ERR, XMR_FS_LEN_ERR, or XMR_FS_CEX_ERR
+ * is set. XMR_FS_LNG_ERR and XMR_FS_LEN_ERR will issue
+ * XMR_FS_ERR unless the corresponding bit in the Receive Command
+ * Register is set.
+ */
+};
+
+/*
+,* XMAC-PHY Registers, indirect addressed over the XMAC
+ */
+enum {
+ PHY_XMAC_CTRL = 0x00,/* 16 bit r/w PHY Control Register */
+ PHY_XMAC_STAT = 0x01,/* 16 bit r/w PHY Status Register */
+ PHY_XMAC_ID0 = 0x02,/* 16 bit r/o PHY ID0 Register */
+ PHY_XMAC_ID1 = 0x03,/* 16 bit r/o PHY ID1 Register */
+ PHY_XMAC_AUNE_ADV = 0x04,/* 16 bit r/w Auto-Neg. Advertisement */
+ PHY_XMAC_AUNE_LP = 0x05,/* 16 bit r/o Link Partner Abi Reg */
+ PHY_XMAC_AUNE_EXP = 0x06,/* 16 bit r/o Auto-Neg. Expansion Reg */
+ PHY_XMAC_NEPG = 0x07,/* 16 bit r/w Next Page Register */
+ PHY_XMAC_NEPG_LP = 0x08,/* 16 bit r/o Next Page Link Partner */
+
+ PHY_XMAC_EXT_STAT = 0x0f,/* 16 bit r/o Ext Status Register */
+ PHY_XMAC_RES_ABI = 0x10,/* 16 bit r/o PHY Resolved Ability */
+};
+/*
+ * Broadcom-PHY Registers, indirect addressed over XMAC
+ */
+enum {
+ PHY_BCOM_CTRL = 0x00,/* 16 bit r/w PHY Control Register */
+ PHY_BCOM_STAT = 0x01,/* 16 bit r/o PHY Status Register */
+ PHY_BCOM_ID0 = 0x02,/* 16 bit r/o PHY ID0 Register */
+ PHY_BCOM_ID1 = 0x03,/* 16 bit r/o PHY ID1 Register */
+ PHY_BCOM_AUNE_ADV = 0x04,/* 16 bit r/w Auto-Neg. Advertisement */
+ PHY_BCOM_AUNE_LP = 0x05,/* 16 bit r/o Link Part Ability Reg */
+ PHY_BCOM_AUNE_EXP = 0x06,/* 16 bit r/o Auto-Neg. Expansion Reg */
+ PHY_BCOM_NEPG = 0x07,/* 16 bit r/w Next Page Register */
+ PHY_BCOM_NEPG_LP = 0x08,/* 16 bit r/o Next Page Link Partner */
+ /* Broadcom-specific registers */
+ PHY_BCOM_1000T_CTRL = 0x09,/* 16 bit r/w 1000Base-T Control Reg */
+ PHY_BCOM_1000T_STAT = 0x0a,/* 16 bit r/o 1000Base-T Status Reg */
+ PHY_BCOM_EXT_STAT = 0x0f,/* 16 bit r/o Extended Status Reg */
+ PHY_BCOM_P_EXT_CTRL = 0x10,/* 16 bit r/w PHY Extended Ctrl Reg */
+ PHY_BCOM_P_EXT_STAT = 0x11,/* 16 bit r/o PHY Extended Stat Reg */
+ PHY_BCOM_RE_CTR = 0x12,/* 16 bit r/w Receive Error Counter */
+ PHY_BCOM_FC_CTR = 0x13,/* 16 bit r/w False Carrier Sense Cnt */
+ PHY_BCOM_RNO_CTR = 0x14,/* 16 bit r/w Receiver NOT_OK Cnt */
+
+ PHY_BCOM_AUX_CTRL = 0x18,/* 16 bit r/w Auxiliary Control Reg */
+ PHY_BCOM_AUX_STAT = 0x19,/* 16 bit r/o Auxiliary Stat Summary */
+ PHY_BCOM_INT_STAT = 0x1a,/* 16 bit r/o Interrupt Status Reg */
+ PHY_BCOM_INT_MASK = 0x1b,/* 16 bit r/w Interrupt Mask Reg */
+};
+
+/*
+ * Marvel-PHY Registers, indirect addressed over GMAC
+ */
+enum {
+ PHY_MARV_CTRL = 0x00,/* 16 bit r/w PHY Control Register */
+ PHY_MARV_STAT = 0x01,/* 16 bit r/o PHY Status Register */
+ PHY_MARV_ID0 = 0x02,/* 16 bit r/o PHY ID0 Register */
+ PHY_MARV_ID1 = 0x03,/* 16 bit r/o PHY ID1 Register */
+ PHY_MARV_AUNE_ADV = 0x04,/* 16 bit r/w Auto-Neg. Advertisement */
+ PHY_MARV_AUNE_LP = 0x05,/* 16 bit r/o Link Part Ability Reg */
+ PHY_MARV_AUNE_EXP = 0x06,/* 16 bit r/o Auto-Neg. Expansion Reg */
+ PHY_MARV_NEPG = 0x07,/* 16 bit r/w Next Page Register */
+ PHY_MARV_NEPG_LP = 0x08,/* 16 bit r/o Next Page Link Partner */
+ /* Marvel-specific registers */
+ PHY_MARV_1000T_CTRL = 0x09,/* 16 bit r/w 1000Base-T Control Reg */
+ PHY_MARV_1000T_STAT = 0x0a,/* 16 bit r/o 1000Base-T Status Reg */
+ PHY_MARV_EXT_STAT = 0x0f,/* 16 bit r/o Extended Status Reg */
+ PHY_MARV_PHY_CTRL = 0x10,/* 16 bit r/w PHY Specific Ctrl Reg */
+ PHY_MARV_PHY_STAT = 0x11,/* 16 bit r/o PHY Specific Stat Reg */
+ PHY_MARV_INT_MASK = 0x12,/* 16 bit r/w Interrupt Mask Reg */
+ PHY_MARV_INT_STAT = 0x13,/* 16 bit r/o Interrupt Status Reg */
+ PHY_MARV_EXT_CTRL = 0x14,/* 16 bit r/w Ext. PHY Specific Ctrl */
+ PHY_MARV_RXE_CNT = 0x15,/* 16 bit r/w Receive Error Counter */
+ PHY_MARV_EXT_ADR = 0x16,/* 16 bit r/w Ext. Ad. for Cable Diag. */
+ PHY_MARV_PORT_IRQ = 0x17,/* 16 bit r/o Port 0 IRQ (88E1111 only) */
+ PHY_MARV_LED_CTRL = 0x18,/* 16 bit r/w LED Control Reg */
+ PHY_MARV_LED_OVER = 0x19,/* 16 bit r/w Manual LED Override Reg */
+ PHY_MARV_EXT_CTRL_2 = 0x1a,/* 16 bit r/w Ext. PHY Specific Ctrl 2 */
+ PHY_MARV_EXT_P_STAT = 0x1b,/* 16 bit r/w Ext. PHY Spec. Stat Reg */
+ PHY_MARV_CABLE_DIAG = 0x1c,/* 16 bit r/o Cable Diagnostic Reg */
+ PHY_MARV_PAGE_ADDR = 0x1d,/* 16 bit r/w Extended Page Address Reg */
+ PHY_MARV_PAGE_DATA = 0x1e,/* 16 bit r/w Extended Page Data Reg */
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+ PHY_MARV_FE_LED_PAR = 0x16,/* 16 bit r/w LED Parallel Select Reg. */
+ PHY_MARV_FE_LED_SER = 0x17,/* 16 bit r/w LED Stream Select S. LED */
+ PHY_MARV_FE_VCT_TX = 0x1a,/* 16 bit r/w VCT Reg. for TXP/N Pins */
+ PHY_MARV_FE_VCT_RX = 0x1b,/* 16 bit r/o VCT Reg. for RXP/N Pins */
+ PHY_MARV_FE_SPEC_2 = 0x1c,/* 16 bit r/w Specific Control Reg. 2 */
+};
+
+/* Level One-PHY Registers, indirect addressed over XMAC */
+enum {
+ PHY_LONE_CTRL = 0x00,/* 16 bit r/w PHY Control Register */
+ PHY_LONE_STAT = 0x01,/* 16 bit r/o PHY Status Register */
+ PHY_LONE_ID0 = 0x02,/* 16 bit r/o PHY ID0 Register */
+ PHY_LONE_ID1 = 0x03,/* 16 bit r/o PHY ID1 Register */
+ PHY_LONE_AUNE_ADV = 0x04,/* 16 bit r/w Auto-Neg. Advertisement */
+ PHY_LONE_AUNE_LP = 0x05,/* 16 bit r/o Link Part Ability Reg */
+ PHY_LONE_AUNE_EXP = 0x06,/* 16 bit r/o Auto-Neg. Expansion Reg */
+ PHY_LONE_NEPG = 0x07,/* 16 bit r/w Next Page Register */
+ PHY_LONE_NEPG_LP = 0x08,/* 16 bit r/o Next Page Link Partner */
+ /* Level One-specific registers */
+ PHY_LONE_1000T_CTRL = 0x09,/* 16 bit r/w 1000Base-T Control Reg */
+ PHY_LONE_1000T_STAT = 0x0a,/* 16 bit r/o 1000Base-T Status Reg */
+ PHY_LONE_EXT_STAT = 0x0f,/* 16 bit r/o Extended Status Reg */
+ PHY_LONE_PORT_CFG = 0x10,/* 16 bit r/w Port Configuration Reg*/
+ PHY_LONE_Q_STAT = 0x11,/* 16 bit r/o Quick Status Reg */
+ PHY_LONE_INT_ENAB = 0x12,/* 16 bit r/w Interrupt Enable Reg */
+ PHY_LONE_INT_STAT = 0x13,/* 16 bit r/o Interrupt Status Reg */
+ PHY_LONE_LED_CFG = 0x14,/* 16 bit r/w LED Configuration Reg */
+ PHY_LONE_PORT_CTRL = 0x15,/* 16 bit r/w Port Control Reg */
+ PHY_LONE_CIM = 0x16,/* 16 bit r/o CIM Reg */
+};
+
+/* National-PHY Registers, indirect addressed over XMAC */
+enum {
+ PHY_NAT_CTRL = 0x00,/* 16 bit r/w PHY Control Register */
+ PHY_NAT_STAT = 0x01,/* 16 bit r/w PHY Status Register */
+ PHY_NAT_ID0 = 0x02,/* 16 bit r/o PHY ID0 Register */
+ PHY_NAT_ID1 = 0x03,/* 16 bit r/o PHY ID1 Register */
+ PHY_NAT_AUNE_ADV = 0x04,/* 16 bit r/w Auto-Neg. Advertisement */
+ PHY_NAT_AUNE_LP = 0x05,/* 16 bit r/o Link Partner Ability Reg */
+ PHY_NAT_AUNE_EXP = 0x06,/* 16 bit r/o Auto-Neg. Expansion Reg */
+ PHY_NAT_NEPG = 0x07,/* 16 bit r/w Next Page Register */
+ PHY_NAT_NEPG_LP = 0x08,/* 16 bit r/o Next Page Link Partner Reg */
+ /* National-specific registers */
+ PHY_NAT_1000T_CTRL = 0x09,/* 16 bit r/w 1000Base-T Control Reg */
+ PHY_NAT_1000T_STAT = 0x0a,/* 16 bit r/o 1000Base-T Status Reg */
+ PHY_NAT_EXT_STAT = 0x0f,/* 16 bit r/o Extended Status Register */
+ PHY_NAT_EXT_CTRL1 = 0x10,/* 16 bit r/o Extended Control Reg1 */
+ PHY_NAT_Q_STAT1 = 0x11,/* 16 bit r/o Quick Status Reg1 */
+ PHY_NAT_10B_OP = 0x12,/* 16 bit r/o 10Base-T Operations Reg */
+ PHY_NAT_EXT_CTRL2 = 0x13,/* 16 bit r/o Extended Control Reg1 */
+ PHY_NAT_Q_STAT2 = 0x14,/* 16 bit r/o Quick Status Reg2 */
+
+ PHY_NAT_PHY_ADDR = 0x19,/* 16 bit r/o PHY Address Register */
+};
+
+enum {
+ PHY_CT_RESET = 1<<15, /* Bit 15: (sc) clear all PHY related regs */
+ PHY_CT_LOOP = 1<<14, /* Bit 14: enable Loopback over PHY */
+ PHY_CT_SPS_LSB = 1<<13, /* Bit 13: Speed select, lower bit */
+ PHY_CT_ANE = 1<<12, /* Bit 12: Auto-Negotiation Enabled */
+ PHY_CT_PDOWN = 1<<11, /* Bit 11: Power Down Mode */
+ PHY_CT_ISOL = 1<<10, /* Bit 10: Isolate Mode */
+ PHY_CT_RE_CFG = 1<<9, /* Bit 9: (sc) Restart Auto-Negotiation */
+ PHY_CT_DUP_MD = 1<<8, /* Bit 8: Duplex Mode */
+ PHY_CT_COL_TST = 1<<7, /* Bit 7: Collision Test enabled */
+ PHY_CT_SPS_MSB = 1<<6, /* Bit 6: Speed select, upper bit */
+};
+
+enum {
+ PHY_CT_SP1000 = PHY_CT_SPS_MSB, /* enable speed of 1000 Mbps */
+ PHY_CT_SP100 = PHY_CT_SPS_LSB, /* enable speed of 100 Mbps */
+ PHY_CT_SP10 = 0, /* enable speed of 10 Mbps */
+};
+
+enum {
+ PHY_ST_EXT_ST = 1<<8, /* Bit 8: Extended Status Present */
+
+ PHY_ST_PRE_SUP = 1<<6, /* Bit 6: Preamble Suppression */
+ PHY_ST_AN_OVER = 1<<5, /* Bit 5: Auto-Negotiation Over */
+ PHY_ST_REM_FLT = 1<<4, /* Bit 4: Remote Fault Condition Occured */
+ PHY_ST_AN_CAP = 1<<3, /* Bit 3: Auto-Negotiation Capability */
+ PHY_ST_LSYNC = 1<<2, /* Bit 2: Link Synchronized */
+ PHY_ST_JAB_DET = 1<<1, /* Bit 1: Jabber Detected */
+ PHY_ST_EXT_REG = 1<<0, /* Bit 0: Extended Register available */
+};
+
+enum {
+ PHY_I1_OUI_MSK = 0x3f<<10, /* Bit 15..10: Organization Unique ID */
+ PHY_I1_MOD_NUM = 0x3f<<4, /* Bit 9.. 4: Model Number */
+ PHY_I1_REV_MSK = 0xf, /* Bit 3.. 0: Revision Number */
+};
+
+/* different Broadcom PHY Ids */
+enum {
+ PHY_BCOM_ID1_A1 = 0x6041,
+ PHY_BCOM_ID1_B2 = 0x6043,
+ PHY_BCOM_ID1_C0 = 0x6044,
+ PHY_BCOM_ID1_C5 = 0x6047,
+};
+
+/* different Marvell PHY Ids */
+enum {
+ PHY_MARV_ID0_VAL= 0x0141, /* Marvell Unique Identifier */
+ PHY_MARV_ID1_B0 = 0x0C23, /* Yukon (PHY 88E1011) */
+ PHY_MARV_ID1_B2 = 0x0C25, /* Yukon-Plus (PHY 88E1011) */
+ PHY_MARV_ID1_C2 = 0x0CC2, /* Yukon-EC (PHY 88E1111) */
+ PHY_MARV_ID1_Y2 = 0x0C91, /* Yukon-2 (PHY 88E1112) */
+};
+
+enum {
+ PHY_AN_NXT_PG = 1<<15, /* Bit 15: Request Next Page */
+ PHY_X_AN_ACK = 1<<14, /* Bit 14: (ro) Acknowledge Received */
+ PHY_X_AN_RFB = 3<<12,/* Bit 13..12: Remote Fault Bits */
+
+ PHY_X_AN_PAUSE = 3<<7,/* Bit 8.. 7: Pause Bits */
+ PHY_X_AN_HD = 1<<6, /* Bit 6: Half Duplex */
+ PHY_X_AN_FD = 1<<5, /* Bit 5: Full Duplex */
+};
+
+enum {
+ PHY_B_AN_RF = 1<<13, /* Bit 13: Remote Fault */
+
+ PHY_B_AN_ASP = 1<<11, /* Bit 11: Asymmetric Pause */
+ PHY_B_AN_PC = 1<<10, /* Bit 10: Pause Capable */
+ PHY_B_AN_SEL = 0x1f, /* Bit 4..0: Selector Field, 00001=Ethernet*/
+};
+
+enum {
+ PHY_L_AN_RF = 1<<13, /* Bit 13: Remote Fault */
+ /* Bit 12: reserved */
+ PHY_L_AN_ASP = 1<<11, /* Bit 11: Asymmetric Pause */
+ PHY_L_AN_PC = 1<<10, /* Bit 10: Pause Capable */
+
+ PHY_L_AN_SEL = 0x1f, /* Bit 4..0: Selector Field, 00001=Ethernet*/
+};
+
+/* PHY_NAT_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement */
+/* PHY_NAT_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/
+/* PHY_AN_NXT_PG (see XMAC) Bit 15: Request Next Page */
+enum {
+ PHY_N_AN_RF = 1<<13, /* Bit 13: Remote Fault */
+
+ PHY_N_AN_100F = 1<<11, /* Bit 11: 100Base-T2 FD Support */
+ PHY_N_AN_100H = 1<<10, /* Bit 10: 100Base-T2 HD Support */
+
+ PHY_N_AN_SEL = 0x1f, /* Bit 4..0: Selector Field, 00001=Ethernet*/
+};
+
+/* field type definition for PHY_x_AN_SEL */
+enum {
+ PHY_SEL_TYPE = 1, /* 00001 = Ethernet */
+};
+
+enum {
+ PHY_ANE_LP_NP = 1<<3, /* Bit 3: Link Partner can Next Page */
+ PHY_ANE_LOC_NP = 1<<2, /* Bit 2: Local PHY can Next Page */
+ PHY_ANE_RX_PG = 1<<1, /* Bit 1: Page Received */
+};
+
+enum {
+ PHY_ANE_PAR_DF = 1<<4, /* Bit 4: Parallel Detection Fault */
+
+ PHY_ANE_LP_CAP = 1<<0, /* Bit 0: Link Partner Auto-Neg. Cap. */
+};
+
+enum {
+ PHY_NP_MORE = 1<<15, /* Bit 15: More, Next Pages to follow */
+ PHY_NP_ACK1 = 1<<14, /* Bit 14: (ro) Ack1, for receiving a message */
+ PHY_NP_MSG_VAL = 1<<13, /* Bit 13: Message Page valid */
+ PHY_NP_ACK2 = 1<<12, /* Bit 12: Ack2, comply with msg content */
+ PHY_NP_TOG = 1<<11, /* Bit 11: Toggle Bit, ensure sync */
+ PHY_NP_MSG = 0x07ff, /* Bit 10..0: Message from/to Link Partner */
+};
+
+enum {
+ PHY_X_EX_FD = 1<<15, /* Bit 15: Device Supports Full Duplex */
+ PHY_X_EX_HD = 1<<14, /* Bit 14: Device Supports Half Duplex */
+};
+
+enum {
+ PHY_X_RS_PAUSE = 3<<7,/* Bit 8..7: selected Pause Mode */
+ PHY_X_RS_HD = 1<<6, /* Bit 6: Half Duplex Mode selected */
+ PHY_X_RS_FD = 1<<5, /* Bit 5: Full Duplex Mode selected */
+ PHY_X_RS_ABLMIS = 1<<4, /* Bit 4: duplex or pause cap mismatch */
+ PHY_X_RS_PAUMIS = 1<<3, /* Bit 3: pause capability mismatch */
+};
+
+/** Remote Fault Bits (PHY_X_AN_RFB) encoding */
+enum {
+ X_RFB_OK = 0<<12,/* Bit 13..12 No errors, Link OK */
+ X_RFB_LF = 1<<12, /* Bit 13..12 Link Failure */
+ X_RFB_OFF = 2<<12,/* Bit 13..12 Offline */
+ X_RFB_AN_ERR = 3<<12,/* Bit 13..12 Auto-Negotiation Error */
+};
+
+/* Pause Bits (PHY_X_AN_PAUSE and PHY_X_RS_PAUSE) encoding */
+enum {
+ PHY_X_P_NO_PAUSE = 0<<7,/* Bit 8..7: no Pause Mode */
+ PHY_X_P_SYM_MD = 1<<7, /* Bit 8..7: symmetric Pause Mode */
+ PHY_X_P_ASYM_MD = 2<<7,/* Bit 8..7: asymmetric Pause Mode */
+ PHY_X_P_BOTH_MD = 3<<7,/* Bit 8..7: both Pause Mode */
+};
+
+
+/* Broadcom-Specific */
+/***** PHY_BCOM_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/
+enum {
+ PHY_B_1000C_TEST = 7<<13,/* Bit 15..13: Test Modes */
+ PHY_B_1000C_MSE = 1<<12, /* Bit 12: Master/Slave Enable */
+ PHY_B_1000C_MSC = 1<<11, /* Bit 11: M/S Configuration */
+ PHY_B_1000C_RD = 1<<10, /* Bit 10: Repeater/DTE */
+ PHY_B_1000C_AFD = 1<<9, /* Bit 9: Advertise Full Duplex */
+ PHY_B_1000C_AHD = 1<<8, /* Bit 8: Advertise Half Duplex */
+};
+
+/***** PHY_BCOM_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/
+/***** PHY_MARV_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/
+enum {
+ PHY_B_1000S_MSF = 1<<15, /* Bit 15: Master/Slave Fault */
+ PHY_B_1000S_MSR = 1<<14, /* Bit 14: Master/Slave Result */
+ PHY_B_1000S_LRS = 1<<13, /* Bit 13: Local Receiver Status */
+ PHY_B_1000S_RRS = 1<<12, /* Bit 12: Remote Receiver Status */
+ PHY_B_1000S_LP_FD = 1<<11, /* Bit 11: Link Partner can FD */
+ PHY_B_1000S_LP_HD = 1<<10, /* Bit 10: Link Partner can HD */
+ /* Bit 9..8: reserved */
+ PHY_B_1000S_IEC = 0xff, /* Bit 7..0: Idle Error Count */
+};
+
+/***** PHY_BCOM_EXT_STAT 16 bit r/o Extended Status Register *****/
+enum {
+ PHY_B_ES_X_FD_CAP = 1<<15, /* Bit 15: 1000Base-X FD capable */
+ PHY_B_ES_X_HD_CAP = 1<<14, /* Bit 14: 1000Base-X HD capable */
+ PHY_B_ES_T_FD_CAP = 1<<13, /* Bit 13: 1000Base-T FD capable */
+ PHY_B_ES_T_HD_CAP = 1<<12, /* Bit 12: 1000Base-T HD capable */
+};
+
+/***** PHY_BCOM_P_EXT_CTRL 16 bit r/w PHY Extended Control Reg *****/
+enum {
+ PHY_B_PEC_MAC_PHY = 1<<15, /* Bit 15: 10BIT/GMI-Interface */
+ PHY_B_PEC_DIS_CROSS = 1<<14, /* Bit 14: Disable MDI Crossover */
+ PHY_B_PEC_TX_DIS = 1<<13, /* Bit 13: Tx output Disabled */
+ PHY_B_PEC_INT_DIS = 1<<12, /* Bit 12: Interrupts Disabled */
+ PHY_B_PEC_F_INT = 1<<11, /* Bit 11: Force Interrupt */
+ PHY_B_PEC_BY_45 = 1<<10, /* Bit 10: Bypass 4B5B-Decoder */
+ PHY_B_PEC_BY_SCR = 1<<9, /* Bit 9: Bypass Scrambler */
+ PHY_B_PEC_BY_MLT3 = 1<<8, /* Bit 8: Bypass MLT3 Encoder */
+ PHY_B_PEC_BY_RXA = 1<<7, /* Bit 7: Bypass Rx Alignm. */
+ PHY_B_PEC_RES_SCR = 1<<6, /* Bit 6: Reset Scrambler */
+ PHY_B_PEC_EN_LTR = 1<<5, /* Bit 5: Ena LED Traffic Mode */
+ PHY_B_PEC_LED_ON = 1<<4, /* Bit 4: Force LED's on */
+ PHY_B_PEC_LED_OFF = 1<<3, /* Bit 3: Force LED's off */
+ PHY_B_PEC_EX_IPG = 1<<2, /* Bit 2: Extend Tx IPG Mode */
+ PHY_B_PEC_3_LED = 1<<1, /* Bit 1: Three Link LED mode */
+ PHY_B_PEC_HIGH_LA = 1<<0, /* Bit 0: GMII FIFO Elasticy */
+};
+
+/***** PHY_BCOM_P_EXT_STAT 16 bit r/o PHY Extended Status Reg *****/
+enum {
+ PHY_B_PES_CROSS_STAT = 1<<13, /* Bit 13: MDI Crossover Status */
+ PHY_B_PES_INT_STAT = 1<<12, /* Bit 12: Interrupt Status */
+ PHY_B_PES_RRS = 1<<11, /* Bit 11: Remote Receiver Stat. */
+ PHY_B_PES_LRS = 1<<10, /* Bit 10: Local Receiver Stat. */
+ PHY_B_PES_LOCKED = 1<<9, /* Bit 9: Locked */
+ PHY_B_PES_LS = 1<<8, /* Bit 8: Link Status */
+ PHY_B_PES_RF = 1<<7, /* Bit 7: Remote Fault */
+ PHY_B_PES_CE_ER = 1<<6, /* Bit 6: Carrier Ext Error */
+ PHY_B_PES_BAD_SSD = 1<<5, /* Bit 5: Bad SSD */
+ PHY_B_PES_BAD_ESD = 1<<4, /* Bit 4: Bad ESD */
+ PHY_B_PES_RX_ER = 1<<3, /* Bit 3: Receive Error */
+ PHY_B_PES_TX_ER = 1<<2, /* Bit 2: Transmit Error */
+ PHY_B_PES_LOCK_ER = 1<<1, /* Bit 1: Lock Error */
+ PHY_B_PES_MLT3_ER = 1<<0, /* Bit 0: MLT3 code Error */
+};
+
+/***** PHY_BCOM_FC_CTR 16 bit r/w False Carrier Counter *****/
+enum {
+ PHY_B_FC_CTR = 0xff, /* Bit 7..0: False Carrier Counter */
+
+/***** PHY_BCOM_RNO_CTR 16 bit r/w Receive NOT_OK Counter *****/
+ PHY_B_RC_LOC_MSK = 0xff00, /* Bit 15..8: Local Rx NOT_OK cnt */
+ PHY_B_RC_REM_MSK = 0x00ff, /* Bit 7..0: Remote Rx NOT_OK cnt */
+
+/***** PHY_BCOM_AUX_CTRL 16 bit r/w Auxiliary Control Reg *****/
+ PHY_B_AC_L_SQE = 1<<15, /* Bit 15: Low Squelch */
+ PHY_B_AC_LONG_PACK = 1<<14, /* Bit 14: Rx Long Packets */
+ PHY_B_AC_ER_CTRL = 3<<12,/* Bit 13..12: Edgerate Control */
+ /* Bit 11: reserved */
+ PHY_B_AC_TX_TST = 1<<10, /* Bit 10: Tx test bit, always 1 */
+ /* Bit 9.. 8: reserved */
+ PHY_B_AC_DIS_PRF = 1<<7, /* Bit 7: dis part resp filter */
+ /* Bit 6: reserved */
+ PHY_B_AC_DIS_PM = 1<<5, /* Bit 5: dis power management */
+ /* Bit 4: reserved */
+ PHY_B_AC_DIAG = 1<<3, /* Bit 3: Diagnostic Mode */
+};
+
+/***** PHY_BCOM_AUX_STAT 16 bit r/o Auxiliary Status Reg *****/
+enum {
+ PHY_B_AS_AN_C = 1<<15, /* Bit 15: AutoNeg complete */
+ PHY_B_AS_AN_CA = 1<<14, /* Bit 14: AN Complete Ack */
+ PHY_B_AS_ANACK_D = 1<<13, /* Bit 13: AN Ack Detect */
+ PHY_B_AS_ANAB_D = 1<<12, /* Bit 12: AN Ability Detect */
+ PHY_B_AS_NPW = 1<<11, /* Bit 11: AN Next Page Wait */
+ PHY_B_AS_AN_RES_MSK = 7<<8,/* Bit 10..8: AN HDC */
+ PHY_B_AS_PDF = 1<<7, /* Bit 7: Parallel Detect. Fault */
+ PHY_B_AS_RF = 1<<6, /* Bit 6: Remote Fault */
+ PHY_B_AS_ANP_R = 1<<5, /* Bit 5: AN Page Received */
+ PHY_B_AS_LP_ANAB = 1<<4, /* Bit 4: LP AN Ability */
+ PHY_B_AS_LP_NPAB = 1<<3, /* Bit 3: LP Next Page Ability */
+ PHY_B_AS_LS = 1<<2, /* Bit 2: Link Status */
+ PHY_B_AS_PRR = 1<<1, /* Bit 1: Pause Resolution-Rx */
+ PHY_B_AS_PRT = 1<<0, /* Bit 0: Pause Resolution-Tx */
+};
+#define PHY_B_AS_PAUSE_MSK (PHY_B_AS_PRR | PHY_B_AS_PRT)
+
+/***** PHY_BCOM_INT_STAT 16 bit r/o Interrupt Status Reg *****/
+/***** PHY_BCOM_INT_MASK 16 bit r/w Interrupt Mask Reg *****/
+enum {
+ PHY_B_IS_PSE = 1<<14, /* Bit 14: Pair Swap Error */
+ PHY_B_IS_MDXI_SC = 1<<13, /* Bit 13: MDIX Status Change */
+ PHY_B_IS_HCT = 1<<12, /* Bit 12: counter above 32k */
+ PHY_B_IS_LCT = 1<<11, /* Bit 11: counter above 128 */
+ PHY_B_IS_AN_PR = 1<<10, /* Bit 10: Page Received */
+ PHY_B_IS_NO_HDCL = 1<<9, /* Bit 9: No HCD Link */
+ PHY_B_IS_NO_HDC = 1<<8, /* Bit 8: No HCD */
+ PHY_B_IS_NEG_USHDC = 1<<7, /* Bit 7: Negotiated Unsup. HCD */
+ PHY_B_IS_SCR_S_ER = 1<<6, /* Bit 6: Scrambler Sync Error */
+ PHY_B_IS_RRS_CHANGE = 1<<5, /* Bit 5: Remote Rx Stat Change */
+ PHY_B_IS_LRS_CHANGE = 1<<4, /* Bit 4: Local Rx Stat Change */
+ PHY_B_IS_DUP_CHANGE = 1<<3, /* Bit 3: Duplex Mode Change */
+ PHY_B_IS_LSP_CHANGE = 1<<2, /* Bit 2: Link Speed Change */
+ PHY_B_IS_LST_CHANGE = 1<<1, /* Bit 1: Link Status Changed */
+ PHY_B_IS_CRC_ER = 1<<0, /* Bit 0: CRC Error */
+};
+#define PHY_B_DEF_MSK (~(PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE))
+
+/* Pause Bits (PHY_B_AN_ASP and PHY_B_AN_PC) encoding */
+enum {
+ PHY_B_P_NO_PAUSE = 0<<10,/* Bit 11..10: no Pause Mode */
+ PHY_B_P_SYM_MD = 1<<10, /* Bit 11..10: symmetric Pause Mode */
+ PHY_B_P_ASYM_MD = 2<<10,/* Bit 11..10: asymmetric Pause Mode */
+ PHY_B_P_BOTH_MD = 3<<10,/* Bit 11..10: both Pause Mode */
+};
+/*
+ * Resolved Duplex mode and Capabilities (Aux Status Summary Reg)
+ */
+enum {
+ PHY_B_RES_1000FD = 7<<8,/* Bit 10..8: 1000Base-T Full Dup. */
+ PHY_B_RES_1000HD = 6<<8,/* Bit 10..8: 1000Base-T Half Dup. */
+};
+
+/*
+ * Level One-Specific
+ */
+/***** PHY_LONE_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/
+enum {
+ PHY_L_1000C_TEST = 7<<13,/* Bit 15..13: Test Modes */
+ PHY_L_1000C_MSE = 1<<12, /* Bit 12: Master/Slave Enable */
+ PHY_L_1000C_MSC = 1<<11, /* Bit 11: M/S Configuration */
+ PHY_L_1000C_RD = 1<<10, /* Bit 10: Repeater/DTE */
+ PHY_L_1000C_AFD = 1<<9, /* Bit 9: Advertise Full Duplex */
+ PHY_L_1000C_AHD = 1<<8, /* Bit 8: Advertise Half Duplex */
+};
+
+/***** PHY_LONE_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/
+enum {
+ PHY_L_1000S_MSF = 1<<15, /* Bit 15: Master/Slave Fault */
+ PHY_L_1000S_MSR = 1<<14, /* Bit 14: Master/Slave Result */
+ PHY_L_1000S_LRS = 1<<13, /* Bit 13: Local Receiver Status */
+ PHY_L_1000S_RRS = 1<<12, /* Bit 12: Remote Receiver Status */
+ PHY_L_1000S_LP_FD = 1<<11, /* Bit 11: Link Partner can FD */
+ PHY_L_1000S_LP_HD = 1<<10, /* Bit 10: Link Partner can HD */
+
+ PHY_L_1000S_IEC = 0xff, /* Bit 7..0: Idle Error Count */
+
+/***** PHY_LONE_EXT_STAT 16 bit r/o Extended Status Register *****/
+ PHY_L_ES_X_FD_CAP = 1<<15, /* Bit 15: 1000Base-X FD capable */
+ PHY_L_ES_X_HD_CAP = 1<<14, /* Bit 14: 1000Base-X HD capable */
+ PHY_L_ES_T_FD_CAP = 1<<13, /* Bit 13: 1000Base-T FD capable */
+ PHY_L_ES_T_HD_CAP = 1<<12, /* Bit 12: 1000Base-T HD capable */
+};
+
+/***** PHY_LONE_PORT_CFG 16 bit r/w Port Configuration Reg *****/
+enum {
+ PHY_L_PC_REP_MODE = 1<<15, /* Bit 15: Repeater Mode */
+
+ PHY_L_PC_TX_DIS = 1<<13, /* Bit 13: Tx output Disabled */
+ PHY_L_PC_BY_SCR = 1<<12, /* Bit 12: Bypass Scrambler */
+ PHY_L_PC_BY_45 = 1<<11, /* Bit 11: Bypass 4B5B-Decoder */
+ PHY_L_PC_JAB_DIS = 1<<10, /* Bit 10: Jabber Disabled */
+ PHY_L_PC_SQE = 1<<9, /* Bit 9: Enable Heartbeat */
+ PHY_L_PC_TP_LOOP = 1<<8, /* Bit 8: TP Loopback */
+ PHY_L_PC_SSS = 1<<7, /* Bit 7: Smart Speed Selection */
+ PHY_L_PC_FIFO_SIZE = 1<<6, /* Bit 6: FIFO Size */
+ PHY_L_PC_PRE_EN = 1<<5, /* Bit 5: Preamble Enable */
+ PHY_L_PC_CIM = 1<<4, /* Bit 4: Carrier Integrity Mon */
+ PHY_L_PC_10_SER = 1<<3, /* Bit 3: Use Serial Output */
+ PHY_L_PC_ANISOL = 1<<2, /* Bit 2: Unisolate Port */
+ PHY_L_PC_TEN_BIT = 1<<1, /* Bit 1: 10bit iface mode on */
+ PHY_L_PC_ALTCLOCK = 1<<0, /* Bit 0: (ro) ALTCLOCK Mode on */
+};
+
+/***** PHY_LONE_Q_STAT 16 bit r/o Quick Status Reg *****/
+enum {
+ PHY_L_QS_D_RATE = 3<<14,/* Bit 15..14: Data Rate */
+ PHY_L_QS_TX_STAT = 1<<13, /* Bit 13: Transmitting */
+ PHY_L_QS_RX_STAT = 1<<12, /* Bit 12: Receiving */
+ PHY_L_QS_COL_STAT = 1<<11, /* Bit 11: Collision */
+ PHY_L_QS_L_STAT = 1<<10, /* Bit 10: Link is up */
+ PHY_L_QS_DUP_MOD = 1<<9, /* Bit 9: Full/Half Duplex */
+ PHY_L_QS_AN = 1<<8, /* Bit 8: AutoNeg is On */
+ PHY_L_QS_AN_C = 1<<7, /* Bit 7: AN is Complete */
+ PHY_L_QS_LLE = 7<<4,/* Bit 6..4: Line Length Estim. */
+ PHY_L_QS_PAUSE = 1<<3, /* Bit 3: LP advertised Pause */
+ PHY_L_QS_AS_PAUSE = 1<<2, /* Bit 2: LP adv. asym. Pause */
+ PHY_L_QS_ISOLATE = 1<<1, /* Bit 1: CIM Isolated */
+ PHY_L_QS_EVENT = 1<<0, /* Bit 0: Event has occurred */
+};
+
+/***** PHY_LONE_INT_ENAB 16 bit r/w Interrupt Enable Reg *****/
+/***** PHY_LONE_INT_STAT 16 bit r/o Interrupt Status Reg *****/
+enum {
+ PHY_L_IS_AN_F = 1<<13, /* Bit 13: Auto-Negotiation fault */
+ PHY_L_IS_CROSS = 1<<11, /* Bit 11: Crossover used */
+ PHY_L_IS_POL = 1<<10, /* Bit 10: Polarity correct. used */
+ PHY_L_IS_SS = 1<<9, /* Bit 9: Smart Speed Downgrade */
+ PHY_L_IS_CFULL = 1<<8, /* Bit 8: Counter Full */
+ PHY_L_IS_AN_C = 1<<7, /* Bit 7: AutoNeg Complete */
+ PHY_L_IS_SPEED = 1<<6, /* Bit 6: Speed Changed */
+ PHY_L_IS_DUP = 1<<5, /* Bit 5: Duplex Changed */
+ PHY_L_IS_LS = 1<<4, /* Bit 4: Link Status Changed */
+ PHY_L_IS_ISOL = 1<<3, /* Bit 3: Isolate Occured */
+ PHY_L_IS_MDINT = 1<<2, /* Bit 2: (ro) STAT: MII Int Pending */
+ PHY_L_IS_INTEN = 1<<1, /* Bit 1: ENAB: Enable IRQs */
+ PHY_L_IS_FORCE = 1<<0, /* Bit 0: ENAB: Force Interrupt */
+};
+
+/* int. mask */
+#define PHY_L_DEF_MSK (PHY_L_IS_LS | PHY_L_IS_ISOL | PHY_L_IS_INTEN)
+
+/***** PHY_LONE_LED_CFG 16 bit r/w LED Configuration Reg *****/
+enum {
+ PHY_L_LC_LEDC = 3<<14,/* Bit 15..14: Col/Blink/On/Off */
+ PHY_L_LC_LEDR = 3<<12,/* Bit 13..12: Rx/Blink/On/Off */
+ PHY_L_LC_LEDT = 3<<10,/* Bit 11..10: Tx/Blink/On/Off */
+ PHY_L_LC_LEDG = 3<<8,/* Bit 9..8: Giga/Blink/On/Off */
+ PHY_L_LC_LEDS = 3<<6,/* Bit 7..6: 10-100/Blink/On/Off */
+ PHY_L_LC_LEDL = 3<<4,/* Bit 5..4: Link/Blink/On/Off */
+ PHY_L_LC_LEDF = 3<<2,/* Bit 3..2: Duplex/Blink/On/Off */
+ PHY_L_LC_PSTRECH= 1<<1, /* Bit 1: Strech LED Pulses */
+ PHY_L_LC_FREQ = 1<<0, /* Bit 0: 30/100 ms */
+};
+
+/***** PHY_LONE_PORT_CTRL 16 bit r/w Port Control Reg *****/
+enum {
+ PHY_L_PC_TX_TCLK = 1<<15, /* Bit 15: Enable TX_TCLK */
+ PHY_L_PC_ALT_NP = 1<<13, /* Bit 14: Alternate Next Page */
+ PHY_L_PC_GMII_ALT= 1<<12, /* Bit 13: Alternate GMII driver */
+ PHY_L_PC_TEN_CRS = 1<<10, /* Bit 10: Extend CRS*/
+};
+
+/***** PHY_LONE_CIM 16 bit r/o CIM Reg *****/
+enum {
+ PHY_L_CIM_ISOL = 0xff<<8,/* Bit 15..8: Isolate Count */
+ PHY_L_CIM_FALSE_CAR = 0xff, /* Bit 7..0: False Carrier Count */
+};
+
+/*
+ * Pause Bits (PHY_L_AN_ASP and PHY_L_AN_PC) encoding
+ */
+enum {
+ PHY_L_P_NO_PAUSE= 0<<10,/* Bit 11..10: no Pause Mode */
+ PHY_L_P_SYM_MD = 1<<10, /* Bit 11..10: symmetric Pause Mode */
+ PHY_L_P_ASYM_MD = 2<<10,/* Bit 11..10: asymmetric Pause Mode */
+ PHY_L_P_BOTH_MD = 3<<10,/* Bit 11..10: both Pause Mode */
+};
+
+/*
+ * National-Specific
+ */
+/***** PHY_NAT_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/
+enum {
+ PHY_N_1000C_TEST= 7<<13,/* Bit 15..13: Test Modes */
+ PHY_N_1000C_MSE = 1<<12, /* Bit 12: Master/Slave Enable */
+ PHY_N_1000C_MSC = 1<<11, /* Bit 11: M/S Configuration */
+ PHY_N_1000C_RD = 1<<10, /* Bit 10: Repeater/DTE */
+ PHY_N_1000C_AFD = 1<<9, /* Bit 9: Advertise Full Duplex */
+ PHY_N_1000C_AHD = 1<<8, /* Bit 8: Advertise Half Duplex */
+ PHY_N_1000C_APC = 1<<7, /* Bit 7: Asymmetric Pause Cap. */};
+
+
+/***** PHY_NAT_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/
+enum {
+ PHY_N_1000S_MSF = 1<<15, /* Bit 15: Master/Slave Fault */
+ PHY_N_1000S_MSR = 1<<14, /* Bit 14: Master/Slave Result */
+ PHY_N_1000S_LRS = 1<<13, /* Bit 13: Local Receiver Status */
+ PHY_N_1000S_RRS = 1<<12, /* Bit 12: Remote Receiver Status*/
+ PHY_N_1000S_LP_FD= 1<<11, /* Bit 11: Link Partner can FD */
+ PHY_N_1000S_LP_HD= 1<<10, /* Bit 10: Link Partner can HD */
+ PHY_N_1000C_LP_APC= 1<<9, /* Bit 9: LP Asym. Pause Cap. */
+ PHY_N_1000S_IEC = 0xff, /* Bit 7..0: Idle Error Count */
+};
+
+/***** PHY_NAT_EXT_STAT 16 bit r/o Extended Status Register *****/
+enum {
+ PHY_N_ES_X_FD_CAP= 1<<15, /* Bit 15: 1000Base-X FD capable */
+ PHY_N_ES_X_HD_CAP= 1<<14, /* Bit 14: 1000Base-X HD capable */
+ PHY_N_ES_T_FD_CAP= 1<<13, /* Bit 13: 1000Base-T FD capable */
+ PHY_N_ES_T_HD_CAP= 1<<12, /* Bit 12: 1000Base-T HD capable */
+};
+
+/** Marvell-Specific */
+enum {
+ PHY_M_AN_NXT_PG = 1<<15, /* Request Next Page */
+ PHY_M_AN_ACK = 1<<14, /* (ro) Acknowledge Received */
+ PHY_M_AN_RF = 1<<13, /* Remote Fault */
+
+ PHY_M_AN_ASP = 1<<11, /* Asymmetric Pause */
+ PHY_M_AN_PC = 1<<10, /* MAC Pause implemented */
+ PHY_M_AN_100_T4 = 1<<9, /* Not cap. 100Base-T4 (always 0) */
+ PHY_M_AN_100_FD = 1<<8, /* Advertise 100Base-TX Full Duplex */
+ PHY_M_AN_100_HD = 1<<7, /* Advertise 100Base-TX Half Duplex */
+ PHY_M_AN_10_FD = 1<<6, /* Advertise 10Base-TX Full Duplex */
+ PHY_M_AN_10_HD = 1<<5, /* Advertise 10Base-TX Half Duplex */
+ PHY_M_AN_SEL_MSK =0x1f<<4, /* Bit 4.. 0: Selector Field Mask */
+};
+
+/* special defines for FIBER (88E1011S only) */
+enum {
+ PHY_M_AN_ASP_X = 1<<8, /* Asymmetric Pause */
+ PHY_M_AN_PC_X = 1<<7, /* MAC Pause implemented */
+ PHY_M_AN_1000X_AHD = 1<<6, /* Advertise 10000Base-X Half Duplex */
+ PHY_M_AN_1000X_AFD = 1<<5, /* Advertise 10000Base-X Full Duplex */
+};
+
+/* Pause Bits (PHY_M_AN_ASP_X and PHY_M_AN_PC_X) encoding */
+enum {
+ PHY_M_P_NO_PAUSE_X = 0<<7,/* Bit 8.. 7: no Pause Mode */
+ PHY_M_P_SYM_MD_X = 1<<7, /* Bit 8.. 7: symmetric Pause Mode */
+ PHY_M_P_ASYM_MD_X = 2<<7,/* Bit 8.. 7: asymmetric Pause Mode */
+ PHY_M_P_BOTH_MD_X = 3<<7,/* Bit 8.. 7: both Pause Mode */
+};
+
+/***** PHY_MARV_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/
+enum {
+ PHY_M_1000C_TEST = 7<<13,/* Bit 15..13: Test Modes */
+ PHY_M_1000C_MSE = 1<<12, /* Manual Master/Slave Enable */
+ PHY_M_1000C_MSC = 1<<11, /* M/S Configuration (1=Master) */
+ PHY_M_1000C_MPD = 1<<10, /* Multi-Port Device */
+ PHY_M_1000C_AFD = 1<<9, /* Advertise Full Duplex */
+ PHY_M_1000C_AHD = 1<<8, /* Advertise Half Duplex */
+};
+
+/***** PHY_MARV_PHY_CTRL 16 bit r/w PHY Specific Ctrl Reg *****/
+enum {
+ PHY_M_PC_TX_FFD_MSK = 3<<14,/* Bit 15..14: Tx FIFO Depth Mask */
+ PHY_M_PC_RX_FFD_MSK = 3<<12,/* Bit 13..12: Rx FIFO Depth Mask */
+ PHY_M_PC_ASS_CRS_TX = 1<<11, /* Assert CRS on Transmit */
+ PHY_M_PC_FL_GOOD = 1<<10, /* Force Link Good */
+ PHY_M_PC_EN_DET_MSK = 3<<8,/* Bit 9.. 8: Energy Detect Mask */
+ PHY_M_PC_ENA_EXT_D = 1<<7, /* Enable Ext. Distance (10BT) */
+ PHY_M_PC_MDIX_MSK = 3<<5,/* Bit 6.. 5: MDI/MDIX Config. Mask */
+ PHY_M_PC_DIS_125CLK = 1<<4, /* Disable 125 CLK */
+ PHY_M_PC_MAC_POW_UP = 1<<3, /* MAC Power up */
+ PHY_M_PC_SQE_T_ENA = 1<<2, /* SQE Test Enabled */
+ PHY_M_PC_POL_R_DIS = 1<<1, /* Polarity Reversal Disabled */
+ PHY_M_PC_DIS_JABBER = 1<<0, /* Disable Jabber */
+};
+
+enum {
+ PHY_M_PC_EN_DET = 2<<8, /* Energy Detect (Mode 1) */
+ PHY_M_PC_EN_DET_PLUS = 3<<8, /* Energy Detect Plus (Mode 2) */
+};
+
+#define PHY_M_PC_MDI_XMODE(x) (((x)<<5) & PHY_M_PC_MDIX_MSK)
+
+enum {
+ PHY_M_PC_MAN_MDI = 0, /* 00 = Manual MDI configuration */
+ PHY_M_PC_MAN_MDIX = 1, /* 01 = Manual MDIX configuration */
+ PHY_M_PC_ENA_AUTO = 3, /* 11 = Enable Automatic Crossover */
+};
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+enum {
+ PHY_M_PC_ENA_DTE_DT = 1<<15, /* Enable Data Terminal Equ. (DTE) Detect */
+ PHY_M_PC_ENA_ENE_DT = 1<<14, /* Enable Energy Detect (sense & pulse) */
+ PHY_M_PC_DIS_NLP_CK = 1<<13, /* Disable Normal Link Puls (NLP) Check */
+ PHY_M_PC_ENA_LIP_NP = 1<<12, /* Enable Link Partner Next Page Reg. */
+ PHY_M_PC_DIS_NLP_GN = 1<<11, /* Disable Normal Link Puls Generation */
+
+ PHY_M_PC_DIS_SCRAMB = 1<<9, /* Disable Scrambler */
+ PHY_M_PC_DIS_FEFI = 1<<8, /* Disable Far End Fault Indic. (FEFI) */
+
+ PHY_M_PC_SH_TP_SEL = 1<<6, /* Shielded Twisted Pair Select */
+ PHY_M_PC_RX_FD_MSK = 3<<2,/* Bit 3.. 2: Rx FIFO Depth Mask */
+};
+
+/***** PHY_MARV_PHY_STAT 16 bit r/o PHY Specific Status Reg *****/
+enum {
+ PHY_M_PS_SPEED_MSK = 3<<14, /* Bit 15..14: Speed Mask */
+ PHY_M_PS_SPEED_1000 = 1<<15, /* 10 = 1000 Mbps */
+ PHY_M_PS_SPEED_100 = 1<<14, /* 01 = 100 Mbps */
+ PHY_M_PS_SPEED_10 = 0, /* 00 = 10 Mbps */
+ PHY_M_PS_FULL_DUP = 1<<13, /* Full Duplex */
+ PHY_M_PS_PAGE_REC = 1<<12, /* Page Received */
+ PHY_M_PS_SPDUP_RES = 1<<11, /* Speed & Duplex Resolved */
+ PHY_M_PS_LINK_UP = 1<<10, /* Link Up */
+ PHY_M_PS_CABLE_MSK = 7<<7, /* Bit 9.. 7: Cable Length Mask */
+ PHY_M_PS_MDI_X_STAT = 1<<6, /* MDI Crossover Stat (1=MDIX) */
+ PHY_M_PS_DOWNS_STAT = 1<<5, /* Downshift Status (1=downsh.) */
+ PHY_M_PS_ENDET_STAT = 1<<4, /* Energy Detect Status (1=act) */
+ PHY_M_PS_TX_P_EN = 1<<3, /* Tx Pause Enabled */
+ PHY_M_PS_RX_P_EN = 1<<2, /* Rx Pause Enabled */
+ PHY_M_PS_POL_REV = 1<<1, /* Polarity Reversed */
+ PHY_M_PS_JABBER = 1<<0, /* Jabber */
+};
+
+#define PHY_M_PS_PAUSE_MSK (PHY_M_PS_TX_P_EN | PHY_M_PS_RX_P_EN)
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+enum {
+ PHY_M_PS_DTE_DETECT = 1<<15, /* Data Terminal Equipment (DTE) Detected */
+ PHY_M_PS_RES_SPEED = 1<<14, /* Resolved Speed (1=100 Mbps, 0=10 Mbps */
+};
+
+enum {
+ PHY_M_IS_AN_ERROR = 1<<15, /* Auto-Negotiation Error */
+ PHY_M_IS_LSP_CHANGE = 1<<14, /* Link Speed Changed */
+ PHY_M_IS_DUP_CHANGE = 1<<13, /* Duplex Mode Changed */
+ PHY_M_IS_AN_PR = 1<<12, /* Page Received */
+ PHY_M_IS_AN_COMPL = 1<<11, /* Auto-Negotiation Completed */
+ PHY_M_IS_LST_CHANGE = 1<<10, /* Link Status Changed */
+ PHY_M_IS_SYMB_ERROR = 1<<9, /* Symbol Error */
+ PHY_M_IS_FALSE_CARR = 1<<8, /* False Carrier */
+ PHY_M_IS_FIFO_ERROR = 1<<7, /* FIFO Overflow/Underrun Error */
+ PHY_M_IS_MDI_CHANGE = 1<<6, /* MDI Crossover Changed */
+ PHY_M_IS_DOWNSH_DET = 1<<5, /* Downshift Detected */
+ PHY_M_IS_END_CHANGE = 1<<4, /* Energy Detect Changed */
+
+ PHY_M_IS_DTE_CHANGE = 1<<2, /* DTE Power Det. Status Changed */
+ PHY_M_IS_POL_CHANGE = 1<<1, /* Polarity Changed */
+ PHY_M_IS_JABBER = 1<<0, /* Jabber */
+};
+
+#define PHY_M_DEF_MSK ( PHY_M_IS_AN_ERROR | PHY_M_IS_LSP_CHANGE | \
+ PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR)
+
+/***** PHY_MARV_EXT_CTRL 16 bit r/w Ext. PHY Specific Ctrl *****/
+enum {
+ PHY_M_EC_ENA_BC_EXT = 1<<15, /* Enable Block Carr. Ext. (88E1111 only) */
+ PHY_M_EC_ENA_LIN_LB = 1<<14, /* Enable Line Loopback (88E1111 only) */
+
+ PHY_M_EC_DIS_LINK_P = 1<<12, /* Disable Link Pulses (88E1111 only) */
+ PHY_M_EC_M_DSC_MSK = 3<<10, /* Bit 11..10: Master Downshift Counter */
+ /* (88E1011 only) */
+ PHY_M_EC_S_DSC_MSK = 3<<8,/* Bit 9.. 8: Slave Downshift Counter */
+ /* (88E1011 only) */
+ PHY_M_EC_M_DSC_MSK2 = 7<<9,/* Bit 11.. 9: Master Downshift Counter */
+ /* (88E1111 only) */
+ PHY_M_EC_DOWN_S_ENA = 1<<8, /* Downshift Enable (88E1111 only) */
+ /* !!! Errata in spec. (1 = disable) */
+ PHY_M_EC_RX_TIM_CT = 1<<7, /* RGMII Rx Timing Control*/
+ PHY_M_EC_MAC_S_MSK = 7<<4,/* Bit 6.. 4: Def. MAC interface speed */
+ PHY_M_EC_FIB_AN_ENA = 1<<3, /* Fiber Auto-Neg. Enable (88E1011S only) */
+ PHY_M_EC_DTE_D_ENA = 1<<2, /* DTE Detect Enable (88E1111 only) */
+ PHY_M_EC_TX_TIM_CT = 1<<1, /* RGMII Tx Timing Control */
+ PHY_M_EC_TRANS_DIS = 1<<0, /* Transmitter Disable (88E1111 only) */};
+
+#define PHY_M_EC_M_DSC(x) ((x)<<10) /* 00=1x; 01=2x; 10=3x; 11=4x */
+#define PHY_M_EC_S_DSC(x) ((x)<<8) /* 00=dis; 01=1x; 10=2x; 11=3x */
+#define PHY_M_EC_MAC_S(x) ((x)<<4) /* 01X=0; 110=2.5; 111=25 (MHz) */
+
+#define PHY_M_EC_M_DSC_2(x) ((x)<<9) /* 000=1x; 001=2x; 010=3x; 011=4x */
+ /* 100=5x; 101=6x; 110=7x; 111=8x */
+enum {
+ MAC_TX_CLK_0_MHZ = 2,
+ MAC_TX_CLK_2_5_MHZ = 6,
+ MAC_TX_CLK_25_MHZ = 7,
+};
+
+/***** PHY_MARV_LED_CTRL 16 bit r/w LED Control Reg *****/
+enum {
+ PHY_M_LEDC_DIS_LED = 1<<15, /* Disable LED */
+ PHY_M_LEDC_PULS_MSK = 7<<12,/* Bit 14..12: Pulse Stretch Mask */
+ PHY_M_LEDC_F_INT = 1<<11, /* Force Interrupt */
+ PHY_M_LEDC_BL_R_MSK = 7<<8,/* Bit 10.. 8: Blink Rate Mask */
+ PHY_M_LEDC_DP_C_LSB = 1<<7, /* Duplex Control (LSB, 88E1111 only) */
+ PHY_M_LEDC_TX_C_LSB = 1<<6, /* Tx Control (LSB, 88E1111 only) */
+ PHY_M_LEDC_LK_C_MSK = 7<<3,/* Bit 5.. 3: Link Control Mask */
+ /* (88E1111 only) */
+};
+
+enum {
+ PHY_M_LEDC_LINK_MSK = 3<<3,/* Bit 4.. 3: Link Control Mask */
+ /* (88E1011 only) */
+ PHY_M_LEDC_DP_CTRL = 1<<2, /* Duplex Control */
+ PHY_M_LEDC_DP_C_MSB = 1<<2, /* Duplex Control (MSB, 88E1111 only) */
+ PHY_M_LEDC_RX_CTRL = 1<<1, /* Rx Activity / Link */
+ PHY_M_LEDC_TX_CTRL = 1<<0, /* Tx Activity / Link */
+ PHY_M_LEDC_TX_C_MSB = 1<<0, /* Tx Control (MSB, 88E1111 only) */
+};
+
+#define PHY_M_LED_PULS_DUR(x) ( ((x)<<12) & PHY_M_LEDC_PULS_MSK)
+
+enum {
+ PULS_NO_STR = 0,/* no pulse stretching */
+ PULS_21MS = 1,/* 21 ms to 42 ms */
+ PULS_42MS = 2,/* 42 ms to 84 ms */
+ PULS_84MS = 3,/* 84 ms to 170 ms */
+ PULS_170MS = 4,/* 170 ms to 340 ms */
+ PULS_340MS = 5,/* 340 ms to 670 ms */
+ PULS_670MS = 6,/* 670 ms to 1.3 s */
+ PULS_1300MS = 7,/* 1.3 s to 2.7 s */
+};
+
+#define PHY_M_LED_BLINK_RT(x) ( ((x)<<8) & PHY_M_LEDC_BL_R_MSK)
+
+enum {
+ BLINK_42MS = 0,/* 42 ms */
+ BLINK_84MS = 1,/* 84 ms */
+ BLINK_170MS = 2,/* 170 ms */
+ BLINK_340MS = 3,/* 340 ms */
+ BLINK_670MS = 4,/* 670 ms */
+};
+
+/***** PHY_MARV_LED_OVER 16 bit r/w Manual LED Override Reg *****/
+#define PHY_M_LED_MO_SGMII(x) ((x)<<14) /* Bit 15..14: SGMII AN Timer */
+ /* Bit 13..12: reserved */
+#define PHY_M_LED_MO_DUP(x) ((x)<<10) /* Bit 11..10: Duplex */
+#define PHY_M_LED_MO_10(x) ((x)<<8) /* Bit 9.. 8: Link 10 */
+#define PHY_M_LED_MO_100(x) ((x)<<6) /* Bit 7.. 6: Link 100 */
+#define PHY_M_LED_MO_1000(x) ((x)<<4) /* Bit 5.. 4: Link 1000 */
+#define PHY_M_LED_MO_RX(x) ((x)<<2) /* Bit 3.. 2: Rx */
+#define PHY_M_LED_MO_TX(x) ((x)<<0) /* Bit 1.. 0: Tx */
+
+enum {
+ MO_LED_NORM = 0,
+ MO_LED_BLINK = 1,
+ MO_LED_OFF = 2,
+ MO_LED_ON = 3,
+};
+
+/***** PHY_MARV_EXT_CTRL_2 16 bit r/w Ext. PHY Specific Ctrl 2 *****/
+enum {
+ PHY_M_EC2_FI_IMPED = 1<<6, /* Fiber Input Impedance */
+ PHY_M_EC2_FO_IMPED = 1<<5, /* Fiber Output Impedance */
+ PHY_M_EC2_FO_M_CLK = 1<<4, /* Fiber Mode Clock Enable */
+ PHY_M_EC2_FO_BOOST = 1<<3, /* Fiber Output Boost */
+ PHY_M_EC2_FO_AM_MSK = 7,/* Bit 2.. 0: Fiber Output Amplitude */
+};
+
+/***** PHY_MARV_EXT_P_STAT 16 bit r/w Ext. PHY Specific Status *****/
+enum {
+ PHY_M_FC_AUTO_SEL = 1<<15, /* Fiber/Copper Auto Sel. Dis. */
+ PHY_M_FC_AN_REG_ACC = 1<<14, /* Fiber/Copper AN Reg. Access */
+ PHY_M_FC_RESOLUTION = 1<<13, /* Fiber/Copper Resolution */
+ PHY_M_SER_IF_AN_BP = 1<<12, /* Ser. IF AN Bypass Enable */
+ PHY_M_SER_IF_BP_ST = 1<<11, /* Ser. IF AN Bypass Status */
+ PHY_M_IRQ_POLARITY = 1<<10, /* IRQ polarity */
+ PHY_M_DIS_AUT_MED = 1<<9, /* Disable Aut. Medium Reg. Selection */
+ /* (88E1111 only) */
+ /* Bit 9.. 4: reserved (88E1011 only) */
+ PHY_M_UNDOC1 = 1<<7, /* undocumented bit !! */
+ PHY_M_DTE_POW_STAT = 1<<4, /* DTE Power Status (88E1111 only) */
+ PHY_M_MODE_MASK = 0xf, /* Bit 3.. 0: copy of HWCFG MODE[3:0] */
+};
+
+/***** PHY_MARV_CABLE_DIAG 16 bit r/o Cable Diagnostic Reg *****/
+enum {
+ PHY_M_CABD_ENA_TEST = 1<<15, /* Enable Test (Page 0) */
+ PHY_M_CABD_DIS_WAIT = 1<<15, /* Disable Waiting Period (Page 1) */
+ /* (88E1111 only) */
+ PHY_M_CABD_STAT_MSK = 3<<13, /* Bit 14..13: Status Mask */
+ PHY_M_CABD_AMPL_MSK = 0x1f<<8,/* Bit 12.. 8: Amplitude Mask */
+ /* (88E1111 only) */
+ PHY_M_CABD_DIST_MSK = 0xff, /* Bit 7.. 0: Distance Mask */
+};
+
+/* values for Cable Diagnostic Status (11=fail; 00=OK; 10=open; 01=short) */
+enum {
+ CABD_STAT_NORMAL= 0,
+ CABD_STAT_SHORT = 1,
+ CABD_STAT_OPEN = 2,
+ CABD_STAT_FAIL = 3,
+};
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+/***** PHY_MARV_FE_LED_PAR 16 bit r/w LED Parallel Select Reg. *****/
+ /* Bit 15..12: reserved (used internally) */
+enum {
+ PHY_M_FELP_LED2_MSK = 0xf<<8, /* Bit 11.. 8: LED2 Mask (LINK) */
+ PHY_M_FELP_LED1_MSK = 0xf<<4, /* Bit 7.. 4: LED1 Mask (ACT) */
+ PHY_M_FELP_LED0_MSK = 0xf, /* Bit 3.. 0: LED0 Mask (SPEED) */
+};
+
+#define PHY_M_FELP_LED2_CTRL(x) ( ((x)<<8) & PHY_M_FELP_LED2_MSK)
+#define PHY_M_FELP_LED1_CTRL(x) ( ((x)<<4) & PHY_M_FELP_LED1_MSK)
+#define PHY_M_FELP_LED0_CTRL(x) ( ((x)<<0) & PHY_M_FELP_LED0_MSK)
+
+enum {
+ LED_PAR_CTRL_COLX = 0x00,
+ LED_PAR_CTRL_ERROR = 0x01,
+ LED_PAR_CTRL_DUPLEX = 0x02,
+ LED_PAR_CTRL_DP_COL = 0x03,
+ LED_PAR_CTRL_SPEED = 0x04,
+ LED_PAR_CTRL_LINK = 0x05,
+ LED_PAR_CTRL_TX = 0x06,
+ LED_PAR_CTRL_RX = 0x07,
+ LED_PAR_CTRL_ACT = 0x08,
+ LED_PAR_CTRL_LNK_RX = 0x09,
+ LED_PAR_CTRL_LNK_AC = 0x0a,
+ LED_PAR_CTRL_ACT_BL = 0x0b,
+ LED_PAR_CTRL_TX_BL = 0x0c,
+ LED_PAR_CTRL_RX_BL = 0x0d,
+ LED_PAR_CTRL_COL_BL = 0x0e,
+ LED_PAR_CTRL_INACT = 0x0f
+};
+
+/*****,PHY_MARV_FE_SPEC_2 16 bit r/w Specific Control Reg. 2 *****/
+enum {
+ PHY_M_FESC_DIS_WAIT = 1<<2, /* Disable TDR Waiting Period */
+ PHY_M_FESC_ENA_MCLK = 1<<1, /* Enable MAC Rx Clock in sleep mode */
+ PHY_M_FESC_SEL_CL_A = 1<<0, /* Select Class A driver (100B-TX) */
+};
+
+/* for Yukon-2 Gigabit Ethernet PHY (88E1112 only) */
+/***** PHY_MARV_PHY_CTRL (page 2) 16 bit r/w MAC Specific Ctrl *****/
+enum {
+ PHY_M_MAC_MD_MSK = 7<<7, /* Bit 9.. 7: Mode Select Mask */
+ PHY_M_MAC_MD_AUTO = 3,/* Auto Copper/1000Base-X */
+ PHY_M_MAC_MD_COPPER = 5,/* Copper only */
+ PHY_M_MAC_MD_1000BX = 7,/* 1000Base-X only */
+};
+#define PHY_M_MAC_MODE_SEL(x) ( ((x)<<7) & PHY_M_MAC_MD_MSK)
+
+/***** PHY_MARV_PHY_CTRL (page 3) 16 bit r/w LED Control Reg. *****/
+enum {
+ PHY_M_LEDC_LOS_MSK = 0xf<<12,/* Bit 15..12: LOS LED Ctrl. Mask */
+ PHY_M_LEDC_INIT_MSK = 0xf<<8, /* Bit 11.. 8: INIT LED Ctrl. Mask */
+ PHY_M_LEDC_STA1_MSK = 0xf<<4,/* Bit 7.. 4: STAT1 LED Ctrl. Mask */
+ PHY_M_LEDC_STA0_MSK = 0xf, /* Bit 3.. 0: STAT0 LED Ctrl. Mask */
+};
+
+#define PHY_M_LEDC_LOS_CTRL(x) ( ((x)<<12) & PHY_M_LEDC_LOS_MSK)
+#define PHY_M_LEDC_INIT_CTRL(x) ( ((x)<<8) & PHY_M_LEDC_INIT_MSK)
+#define PHY_M_LEDC_STA1_CTRL(x) ( ((x)<<4) & PHY_M_LEDC_STA1_MSK)
+#define PHY_M_LEDC_STA0_CTRL(x) ( ((x)<<0) & PHY_M_LEDC_STA0_MSK)
+
+/* GMAC registers */
+/* Port Registers */
+enum {
+ GM_GP_STAT = 0x0000, /* 16 bit r/o General Purpose Status */
+ GM_GP_CTRL = 0x0004, /* 16 bit r/w General Purpose Control */
+ GM_TX_CTRL = 0x0008, /* 16 bit r/w Transmit Control Reg. */
+ GM_RX_CTRL = 0x000c, /* 16 bit r/w Receive Control Reg. */
+ GM_TX_FLOW_CTRL = 0x0010, /* 16 bit r/w Transmit Flow-Control */
+ GM_TX_PARAM = 0x0014, /* 16 bit r/w Transmit Parameter Reg. */
+ GM_SERIAL_MODE = 0x0018, /* 16 bit r/w Serial Mode Register */
+/* Source Address Registers */
+ GM_SRC_ADDR_1L = 0x001c, /* 16 bit r/w Source Address 1 (low) */
+ GM_SRC_ADDR_1M = 0x0020, /* 16 bit r/w Source Address 1 (middle) */
+ GM_SRC_ADDR_1H = 0x0024, /* 16 bit r/w Source Address 1 (high) */
+ GM_SRC_ADDR_2L = 0x0028, /* 16 bit r/w Source Address 2 (low) */
+ GM_SRC_ADDR_2M = 0x002c, /* 16 bit r/w Source Address 2 (middle) */
+ GM_SRC_ADDR_2H = 0x0030, /* 16 bit r/w Source Address 2 (high) */
+
+/* Multicast Address Hash Registers */
+ GM_MC_ADDR_H1 = 0x0034, /* 16 bit r/w Multicast Address Hash 1 */
+ GM_MC_ADDR_H2 = 0x0038, /* 16 bit r/w Multicast Address Hash 2 */
+ GM_MC_ADDR_H3 = 0x003c, /* 16 bit r/w Multicast Address Hash 3 */
+ GM_MC_ADDR_H4 = 0x0040, /* 16 bit r/w Multicast Address Hash 4 */
+
+/* Interrupt Source Registers */
+ GM_TX_IRQ_SRC = 0x0044, /* 16 bit r/o Tx Overflow IRQ Source */
+ GM_RX_IRQ_SRC = 0x0048, /* 16 bit r/o Rx Overflow IRQ Source */
+ GM_TR_IRQ_SRC = 0x004c, /* 16 bit r/o Tx/Rx Over. IRQ Source */
+
+/* Interrupt Mask Registers */
+ GM_TX_IRQ_MSK = 0x0050, /* 16 bit r/w Tx Overflow IRQ Mask */
+ GM_RX_IRQ_MSK = 0x0054, /* 16 bit r/w Rx Overflow IRQ Mask */
+ GM_TR_IRQ_MSK = 0x0058, /* 16 bit r/w Tx/Rx Over. IRQ Mask */
+
+/* Serial Management Interface (SMI) Registers */
+ GM_SMI_CTRL = 0x0080, /* 16 bit r/w SMI Control Register */
+ GM_SMI_DATA = 0x0084, /* 16 bit r/w SMI Data Register */
+ GM_PHY_ADDR = 0x0088, /* 16 bit r/w GPHY Address Register */
+};
+
+/* MIB Counters */
+#define GM_MIB_CNT_BASE 0x0100 /* Base Address of MIB Counters */
+#define GM_MIB_CNT_SIZE 44 /* Number of MIB Counters */
+
+/*
+ * MIB Counters base address definitions (low word) -
+ * use offset 4 for access to high word (32 bit r/o)
+ */
+enum {
+ GM_RXF_UC_OK = GM_MIB_CNT_BASE + 0, /* Unicast Frames Received OK */
+ GM_RXF_BC_OK = GM_MIB_CNT_BASE + 8, /* Broadcast Frames Received OK */
+ GM_RXF_MPAUSE = GM_MIB_CNT_BASE + 16, /* Pause MAC Ctrl Frames Received */
+ GM_RXF_MC_OK = GM_MIB_CNT_BASE + 24, /* Multicast Frames Received OK */
+ GM_RXF_FCS_ERR = GM_MIB_CNT_BASE + 32, /* Rx Frame Check Seq. Error */
+ /* GM_MIB_CNT_BASE + 40: reserved */
+ GM_RXO_OK_LO = GM_MIB_CNT_BASE + 48, /* Octets Received OK Low */
+ GM_RXO_OK_HI = GM_MIB_CNT_BASE + 56, /* Octets Received OK High */
+ GM_RXO_ERR_LO = GM_MIB_CNT_BASE + 64, /* Octets Received Invalid Low */
+ GM_RXO_ERR_HI = GM_MIB_CNT_BASE + 72, /* Octets Received Invalid High */
+ GM_RXF_SHT = GM_MIB_CNT_BASE + 80, /* Frames <64 Byte Received OK */
+ GM_RXE_FRAG = GM_MIB_CNT_BASE + 88, /* Frames <64 Byte Received with FCS Err */
+ GM_RXF_64B = GM_MIB_CNT_BASE + 96, /* 64 Byte Rx Frame */
+ GM_RXF_127B = GM_MIB_CNT_BASE + 104, /* 65-127 Byte Rx Frame */
+ GM_RXF_255B = GM_MIB_CNT_BASE + 112, /* 128-255 Byte Rx Frame */
+ GM_RXF_511B = GM_MIB_CNT_BASE + 120, /* 256-511 Byte Rx Frame */
+ GM_RXF_1023B = GM_MIB_CNT_BASE + 128, /* 512-1023 Byte Rx Frame */
+ GM_RXF_1518B = GM_MIB_CNT_BASE + 136, /* 1024-1518 Byte Rx Frame */
+ GM_RXF_MAX_SZ = GM_MIB_CNT_BASE + 144, /* 1519-MaxSize Byte Rx Frame */
+ GM_RXF_LNG_ERR = GM_MIB_CNT_BASE + 152, /* Rx Frame too Long Error */
+ GM_RXF_JAB_PKT = GM_MIB_CNT_BASE + 160, /* Rx Jabber Packet Frame */
+ /* GM_MIB_CNT_BASE + 168: reserved */
+ GM_RXE_FIFO_OV = GM_MIB_CNT_BASE + 176, /* Rx FIFO overflow Event */
+ /* GM_MIB_CNT_BASE + 184: reserved */
+ GM_TXF_UC_OK = GM_MIB_CNT_BASE + 192, /* Unicast Frames Xmitted OK */
+ GM_TXF_BC_OK = GM_MIB_CNT_BASE + 200, /* Broadcast Frames Xmitted OK */
+ GM_TXF_MPAUSE = GM_MIB_CNT_BASE + 208, /* Pause MAC Ctrl Frames Xmitted */
+ GM_TXF_MC_OK = GM_MIB_CNT_BASE + 216, /* Multicast Frames Xmitted OK */
+ GM_TXO_OK_LO = GM_MIB_CNT_BASE + 224, /* Octets Transmitted OK Low */
+ GM_TXO_OK_HI = GM_MIB_CNT_BASE + 232, /* Octets Transmitted OK High */
+ GM_TXF_64B = GM_MIB_CNT_BASE + 240, /* 64 Byte Tx Frame */
+ GM_TXF_127B = GM_MIB_CNT_BASE + 248, /* 65-127 Byte Tx Frame */
+ GM_TXF_255B = GM_MIB_CNT_BASE + 256, /* 128-255 Byte Tx Frame */
+ GM_TXF_511B = GM_MIB_CNT_BASE + 264, /* 256-511 Byte Tx Frame */
+ GM_TXF_1023B = GM_MIB_CNT_BASE + 272, /* 512-1023 Byte Tx Frame */
+ GM_TXF_1518B = GM_MIB_CNT_BASE + 280, /* 1024-1518 Byte Tx Frame */
+ GM_TXF_MAX_SZ = GM_MIB_CNT_BASE + 288, /* 1519-MaxSize Byte Tx Frame */
+
+ GM_TXF_COL = GM_MIB_CNT_BASE + 304, /* Tx Collision */
+ GM_TXF_LAT_COL = GM_MIB_CNT_BASE + 312, /* Tx Late Collision */
+ GM_TXF_ABO_COL = GM_MIB_CNT_BASE + 320, /* Tx aborted due to Exces. Col. */
+ GM_TXF_MUL_COL = GM_MIB_CNT_BASE + 328, /* Tx Multiple Collision */
+ GM_TXF_SNG_COL = GM_MIB_CNT_BASE + 336, /* Tx Single Collision */
+ GM_TXE_FIFO_UR = GM_MIB_CNT_BASE + 344, /* Tx FIFO Underrun Event */
+};
+
+/* GMAC Bit Definitions */
+/* GM_GP_STAT 16 bit r/o General Purpose Status Register */
+enum {
+ GM_GPSR_SPEED = 1<<15, /* Bit 15: Port Speed (1 = 100 Mbps) */
+ GM_GPSR_DUPLEX = 1<<14, /* Bit 14: Duplex Mode (1 = Full) */
+ GM_GPSR_FC_TX_DIS = 1<<13, /* Bit 13: Tx Flow-Control Mode Disabled */
+ GM_GPSR_LINK_UP = 1<<12, /* Bit 12: Link Up Status */
+ GM_GPSR_PAUSE = 1<<11, /* Bit 11: Pause State */
+ GM_GPSR_TX_ACTIVE = 1<<10, /* Bit 10: Tx in Progress */
+ GM_GPSR_EXC_COL = 1<<9, /* Bit 9: Excessive Collisions Occured */
+ GM_GPSR_LAT_COL = 1<<8, /* Bit 8: Late Collisions Occured */
+
+ GM_GPSR_PHY_ST_CH = 1<<5, /* Bit 5: PHY Status Change */
+ GM_GPSR_GIG_SPEED = 1<<4, /* Bit 4: Gigabit Speed (1 = 1000 Mbps) */
+ GM_GPSR_PART_MODE = 1<<3, /* Bit 3: Partition mode */
+ GM_GPSR_FC_RX_DIS = 1<<2, /* Bit 2: Rx Flow-Control Mode Disabled */
+ GM_GPSR_PROM_EN = 1<<1, /* Bit 1: Promiscuous Mode Enabled */
+};
+
+/* GM_GP_CTRL 16 bit r/w General Purpose Control Register */
+enum {
+ GM_GPCR_PROM_ENA = 1<<14, /* Bit 14: Enable Promiscuous Mode */
+ GM_GPCR_FC_TX_DIS = 1<<13, /* Bit 13: Disable Tx Flow-Control Mode */
+ GM_GPCR_TX_ENA = 1<<12, /* Bit 12: Enable Transmit */
+ GM_GPCR_RX_ENA = 1<<11, /* Bit 11: Enable Receive */
+ GM_GPCR_BURST_ENA = 1<<10, /* Bit 10: Enable Burst Mode */
+ GM_GPCR_LOOP_ENA = 1<<9, /* Bit 9: Enable MAC Loopback Mode */
+ GM_GPCR_PART_ENA = 1<<8, /* Bit 8: Enable Partition Mode */
+ GM_GPCR_GIGS_ENA = 1<<7, /* Bit 7: Gigabit Speed (1000 Mbps) */
+ GM_GPCR_FL_PASS = 1<<6, /* Bit 6: Force Link Pass */
+ GM_GPCR_DUP_FULL = 1<<5, /* Bit 5: Full Duplex Mode */
+ GM_GPCR_FC_RX_DIS = 1<<4, /* Bit 4: Disable Rx Flow-Control Mode */
+ GM_GPCR_SPEED_100 = 1<<3, /* Bit 3: Port Speed 100 Mbps */
+ GM_GPCR_AU_DUP_DIS = 1<<2, /* Bit 2: Disable Auto-Update Duplex */
+ GM_GPCR_AU_FCT_DIS = 1<<1, /* Bit 1: Disable Auto-Update Flow-C. */
+ GM_GPCR_AU_SPD_DIS = 1<<0, /* Bit 0: Disable Auto-Update Speed */
+};
+
+#define GM_GPCR_SPEED_1000 (GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100)
+#define GM_GPCR_AU_ALL_DIS (GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS|GM_GPCR_AU_SPD_DIS)
+
+/* GM_TX_CTRL 16 bit r/w Transmit Control Register */
+enum {
+ GM_TXCR_FORCE_JAM = 1<<15, /* Bit 15: Force Jam / Flow-Control */
+ GM_TXCR_CRC_DIS = 1<<14, /* Bit 14: Disable insertion of CRC */
+ GM_TXCR_PAD_DIS = 1<<13, /* Bit 13: Disable padding of packets */
+ GM_TXCR_COL_THR_MSK = 1<<10, /* Bit 12..10: Collision Threshold */
+};
+
+#define TX_COL_THR(x) (((x)<<10) & GM_TXCR_COL_THR_MSK)
+#define TX_COL_DEF 0x04
+
+/* GM_RX_CTRL 16 bit r/w Receive Control Register */
+enum {
+ GM_RXCR_UCF_ENA = 1<<15, /* Bit 15: Enable Unicast filtering */
+ GM_RXCR_MCF_ENA = 1<<14, /* Bit 14: Enable Multicast filtering */
+ GM_RXCR_CRC_DIS = 1<<13, /* Bit 13: Remove 4-byte CRC */
+ GM_RXCR_PASS_FC = 1<<12, /* Bit 12: Pass FC packets to FIFO */
+};
+
+/* GM_TX_PARAM 16 bit r/w Transmit Parameter Register */
+enum {
+ GM_TXPA_JAMLEN_MSK = 0x03<<14, /* Bit 15..14: Jam Length */
+ GM_TXPA_JAMIPG_MSK = 0x1f<<9, /* Bit 13..9: Jam IPG */
+ GM_TXPA_JAMDAT_MSK = 0x1f<<4, /* Bit 8..4: IPG Jam to Data */
+
+ TX_JAM_LEN_DEF = 0x03,
+ TX_JAM_IPG_DEF = 0x0b,
+ TX_IPG_JAM_DEF = 0x1c,
+};
+
+#define TX_JAM_LEN_VAL(x) (((x)<<14) & GM_TXPA_JAMLEN_MSK)
+#define TX_JAM_IPG_VAL(x) (((x)<<9) & GM_TXPA_JAMIPG_MSK)
+#define TX_IPG_JAM_DATA(x) (((x)<<4) & GM_TXPA_JAMDAT_MSK)
+
+
+/* GM_SERIAL_MODE 16 bit r/w Serial Mode Register */
+enum {
+ GM_SMOD_DATABL_MSK = 0x1f<<11, /* Bit 15..11: Data Blinder (r/o) */
+ GM_SMOD_LIMIT_4 = 1<<10, /* Bit 10: 4 consecutive Tx trials */
+ GM_SMOD_VLAN_ENA = 1<<9, /* Bit 9: Enable VLAN (Max. Frame Len) */
+ GM_SMOD_JUMBO_ENA = 1<<8, /* Bit 8: Enable Jumbo (Max. Frame Len) */
+ GM_SMOD_IPG_MSK = 0x1f /* Bit 4..0: Inter-Packet Gap (IPG) */
+};
+
+#define DATA_BLIND_VAL(x) (((x)<<11) & GM_SMOD_DATABL_MSK)
+#define DATA_BLIND_DEF 0x04
+
+#define IPG_DATA_VAL(x) (x & GM_SMOD_IPG_MSK)
+#define IPG_DATA_DEF 0x1e
+
+/* GM_SMI_CTRL 16 bit r/w SMI Control Register */
+enum {
+ GM_SMI_CT_PHY_A_MSK = 0x1f<<11,/* Bit 15..11: PHY Device Address */
+ GM_SMI_CT_REG_A_MSK = 0x1f<<6,/* Bit 10.. 6: PHY Register Address */
+ GM_SMI_CT_OP_RD = 1<<5, /* Bit 5: OpCode Read (0=Write)*/
+ GM_SMI_CT_RD_VAL = 1<<4, /* Bit 4: Read Valid (Read completed) */
+ GM_SMI_CT_BUSY = 1<<3, /* Bit 3: Busy (Operation in progress) */
+};
+
+#define GM_SMI_CT_PHY_AD(x) (((x)<<11) & GM_SMI_CT_PHY_A_MSK)
+#define GM_SMI_CT_REG_AD(x) (((x)<<6) & GM_SMI_CT_REG_A_MSK)
+
+/* GM_PHY_ADDR 16 bit r/w GPHY Address Register */
+enum {
+ GM_PAR_MIB_CLR = 1<<5, /* Bit 5: Set MIB Clear Counter Mode */
+ GM_PAR_MIB_TST = 1<<4, /* Bit 4: MIB Load Counter (Test Mode) */
+};
+
+/* Receive Frame Status Encoding */
+enum {
+ GMR_FS_LEN = 0xffff<<16, /* Bit 31..16: Rx Frame Length */
+ GMR_FS_VLAN = 1<<13, /* Bit 13: VLAN Packet */
+ GMR_FS_JABBER = 1<<12, /* Bit 12: Jabber Packet */
+ GMR_FS_UN_SIZE = 1<<11, /* Bit 11: Undersize Packet */
+ GMR_FS_MC = 1<<10, /* Bit 10: Multicast Packet */
+ GMR_FS_BC = 1<<9, /* Bit 9: Broadcast Packet */
+ GMR_FS_RX_OK = 1<<8, /* Bit 8: Receive OK (Good Packet) */
+ GMR_FS_GOOD_FC = 1<<7, /* Bit 7: Good Flow-Control Packet */
+ GMR_FS_BAD_FC = 1<<6, /* Bit 6: Bad Flow-Control Packet */
+ GMR_FS_MII_ERR = 1<<5, /* Bit 5: MII Error */
+ GMR_FS_LONG_ERR = 1<<4, /* Bit 4: Too Long Packet */
+ GMR_FS_FRAGMENT = 1<<3, /* Bit 3: Fragment */
+
+ GMR_FS_CRC_ERR = 1<<1, /* Bit 1: CRC Error */
+ GMR_FS_RX_FF_OV = 1<<0, /* Bit 0: Rx FIFO Overflow */
+
+/*
+ * GMR_FS_ANY_ERR (analogous to XMR_FS_ANY_ERR)
+ */
+ GMR_FS_ANY_ERR = GMR_FS_CRC_ERR | GMR_FS_LONG_ERR |
+ GMR_FS_MII_ERR | GMR_FS_BAD_FC | GMR_FS_GOOD_FC |
+ GMR_FS_JABBER,
+/* Rx GMAC FIFO Flush Mask (default) */
+ RX_FF_FL_DEF_MSK = GMR_FS_CRC_ERR | GMR_FS_RX_FF_OV |GMR_FS_MII_ERR |
+ GMR_FS_BAD_FC | GMR_FS_GOOD_FC | GMR_FS_UN_SIZE |
+ GMR_FS_JABBER,
+};
+
+/* RX_GMF_CTRL_T 32 bit Rx GMAC FIFO Control/Test */
+enum {
+ GMF_WP_TST_ON = 1<<14, /* Write Pointer Test On */
+ GMF_WP_TST_OFF = 1<<13, /* Write Pointer Test Off */
+ GMF_WP_STEP = 1<<12, /* Write Pointer Step/Increment */
+
+ GMF_RP_TST_ON = 1<<10, /* Read Pointer Test On */
+ GMF_RP_TST_OFF = 1<<9, /* Read Pointer Test Off */
+ GMF_RP_STEP = 1<<8, /* Read Pointer Step/Increment */
+ GMF_RX_F_FL_ON = 1<<7, /* Rx FIFO Flush Mode On */
+ GMF_RX_F_FL_OFF = 1<<6, /* Rx FIFO Flush Mode Off */
+ GMF_CLI_RX_FO = 1<<5, /* Clear IRQ Rx FIFO Overrun */
+ GMF_CLI_RX_FC = 1<<4, /* Clear IRQ Rx Frame Complete */
+ GMF_OPER_ON = 1<<3, /* Operational Mode On */
+ GMF_OPER_OFF = 1<<2, /* Operational Mode Off */
+ GMF_RST_CLR = 1<<1, /* Clear GMAC FIFO Reset */
+ GMF_RST_SET = 1<<0, /* Set GMAC FIFO Reset */
+
+ RX_GMF_FL_THR_DEF = 0xa, /* flush threshold (default) */
+};
+
+
+/* TX_GMF_CTRL_T 32 bit Tx GMAC FIFO Control/Test */
+enum {
+ GMF_WSP_TST_ON = 1<<18,/* Write Shadow Pointer Test On */
+ GMF_WSP_TST_OFF = 1<<17,/* Write Shadow Pointer Test Off */
+ GMF_WSP_STEP = 1<<16,/* Write Shadow Pointer Step/Increment */
+
+ GMF_CLI_TX_FU = 1<<6, /* Clear IRQ Tx FIFO Underrun */
+ GMF_CLI_TX_FC = 1<<5, /* Clear IRQ Tx Frame Complete */
+ GMF_CLI_TX_PE = 1<<4, /* Clear IRQ Tx Parity Error */
+};
+
+/* GMAC_TI_ST_CTRL 8 bit Time Stamp Timer Ctrl Reg (YUKON only) */
+enum {
+ GMT_ST_START = 1<<2, /* Start Time Stamp Timer */
+ GMT_ST_STOP = 1<<1, /* Stop Time Stamp Timer */
+ GMT_ST_CLR_IRQ = 1<<0, /* Clear Time Stamp Timer IRQ */
+};
+
+/* GMAC_CTRL 32 bit GMAC Control Reg (YUKON only) */
+enum {
+ GMC_H_BURST_ON = 1<<7, /* Half Duplex Burst Mode On */
+ GMC_H_BURST_OFF = 1<<6, /* Half Duplex Burst Mode Off */
+ GMC_F_LOOPB_ON = 1<<5, /* FIFO Loopback On */
+ GMC_F_LOOPB_OFF = 1<<4, /* FIFO Loopback Off */
+ GMC_PAUSE_ON = 1<<3, /* Pause On */
+ GMC_PAUSE_OFF = 1<<2, /* Pause Off */
+ GMC_RST_CLR = 1<<1, /* Clear GMAC Reset */
+ GMC_RST_SET = 1<<0, /* Set GMAC Reset */
+};
+
+/* GPHY_CTRL 32 bit GPHY Control Reg (YUKON only) */
+enum {
+ GPC_SEL_BDT = 1<<28, /* Select Bi-Dir. Transfer for MDC/MDIO */
+ GPC_INT_POL_HI = 1<<27, /* IRQ Polarity is Active HIGH */
+ GPC_75_OHM = 1<<26, /* Use 75 Ohm Termination instead of 50 */
+ GPC_DIS_FC = 1<<25, /* Disable Automatic Fiber/Copper Detection */
+ GPC_DIS_SLEEP = 1<<24, /* Disable Energy Detect */
+ GPC_HWCFG_M_3 = 1<<23, /* HWCFG_MODE[3] */
+ GPC_HWCFG_M_2 = 1<<22, /* HWCFG_MODE[2] */
+ GPC_HWCFG_M_1 = 1<<21, /* HWCFG_MODE[1] */
+ GPC_HWCFG_M_0 = 1<<20, /* HWCFG_MODE[0] */
+ GPC_ANEG_0 = 1<<19, /* ANEG[0] */
+ GPC_ENA_XC = 1<<18, /* Enable MDI crossover */
+ GPC_DIS_125 = 1<<17, /* Disable 125 MHz clock */
+ GPC_ANEG_3 = 1<<16, /* ANEG[3] */
+ GPC_ANEG_2 = 1<<15, /* ANEG[2] */
+ GPC_ANEG_1 = 1<<14, /* ANEG[1] */
+ GPC_ENA_PAUSE = 1<<13, /* Enable Pause (SYM_OR_REM) */
+ GPC_PHYADDR_4 = 1<<12, /* Bit 4 of Phy Addr */
+ GPC_PHYADDR_3 = 1<<11, /* Bit 3 of Phy Addr */
+ GPC_PHYADDR_2 = 1<<10, /* Bit 2 of Phy Addr */
+ GPC_PHYADDR_1 = 1<<9, /* Bit 1 of Phy Addr */
+ GPC_PHYADDR_0 = 1<<8, /* Bit 0 of Phy Addr */
+ /* Bits 7..2: reserved */
+ GPC_RST_CLR = 1<<1, /* Clear GPHY Reset */
+ GPC_RST_SET = 1<<0, /* Set GPHY Reset */
+};
+
+#define GPC_HWCFG_GMII_COP (GPC_HWCFG_M_3|GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0)
+#define GPC_HWCFG_GMII_FIB (GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0)
+#define GPC_ANEG_ADV_ALL_M (GPC_ANEG_3 | GPC_ANEG_2 | GPC_ANEG_1 | GPC_ANEG_0)
+
+/* forced speed and duplex mode (don't mix with other ANEG bits) */
+#define GPC_FRC10MBIT_HALF 0
+#define GPC_FRC10MBIT_FULL GPC_ANEG_0
+#define GPC_FRC100MBIT_HALF GPC_ANEG_1
+#define GPC_FRC100MBIT_FULL (GPC_ANEG_0 | GPC_ANEG_1)
+
+/* auto-negotiation with limited advertised speeds */
+/* mix only with master/slave settings (for copper) */
+#define GPC_ADV_1000_HALF GPC_ANEG_2
+#define GPC_ADV_1000_FULL GPC_ANEG_3
+#define GPC_ADV_ALL (GPC_ANEG_2 | GPC_ANEG_3)
+
+/* master/slave settings */
+/* only for copper with 1000 Mbps */
+#define GPC_FORCE_MASTER 0
+#define GPC_FORCE_SLAVE GPC_ANEG_0
+#define GPC_PREF_MASTER GPC_ANEG_1
+#define GPC_PREF_SLAVE (GPC_ANEG_1 | GPC_ANEG_0)
+
+/* GMAC_IRQ_SRC 8 bit GMAC Interrupt Source Reg (YUKON only) */
+/* GMAC_IRQ_MSK 8 bit GMAC Interrupt Mask Reg (YUKON only) */
+enum {
+ GM_IS_TX_CO_OV = 1<<5, /* Transmit Counter Overflow IRQ */
+ GM_IS_RX_CO_OV = 1<<4, /* Receive Counter Overflow IRQ */
+ GM_IS_TX_FF_UR = 1<<3, /* Transmit FIFO Underrun */
+ GM_IS_TX_COMPL = 1<<2, /* Frame Transmission Complete */
+ GM_IS_RX_FF_OR = 1<<1, /* Receive FIFO Overrun */
+ GM_IS_RX_COMPL = 1<<0, /* Frame Reception Complete */
+
+#define GMAC_DEF_MSK (GM_IS_TX_CO_OV | GM_IS_RX_CO_OV | GM_IS_TX_FF_UR)
+
+/* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */
+ /* Bits 15.. 2: reserved */
+ GMLC_RST_CLR = 1<<1, /* Clear GMAC Link Reset */
+ GMLC_RST_SET = 1<<0, /* Set GMAC Link Reset */
+
+
+/* WOL_CTRL_STAT 16 bit WOL Control/Status Reg */
+ WOL_CTL_LINK_CHG_OCC = 1<<15,
+ WOL_CTL_MAGIC_PKT_OCC = 1<<14,
+ WOL_CTL_PATTERN_OCC = 1<<13,
+ WOL_CTL_CLEAR_RESULT = 1<<12,
+ WOL_CTL_ENA_PME_ON_LINK_CHG = 1<<11,
+ WOL_CTL_DIS_PME_ON_LINK_CHG = 1<<10,
+ WOL_CTL_ENA_PME_ON_MAGIC_PKT = 1<<9,
+ WOL_CTL_DIS_PME_ON_MAGIC_PKT = 1<<8,
+ WOL_CTL_ENA_PME_ON_PATTERN = 1<<7,
+ WOL_CTL_DIS_PME_ON_PATTERN = 1<<6,
+ WOL_CTL_ENA_LINK_CHG_UNIT = 1<<5,
+ WOL_CTL_DIS_LINK_CHG_UNIT = 1<<4,
+ WOL_CTL_ENA_MAGIC_PKT_UNIT = 1<<3,
+ WOL_CTL_DIS_MAGIC_PKT_UNIT = 1<<2,
+ WOL_CTL_ENA_PATTERN_UNIT = 1<<1,
+ WOL_CTL_DIS_PATTERN_UNIT = 1<<0,
+};
+
+#define WOL_CTL_DEFAULT \
+ (WOL_CTL_DIS_PME_ON_LINK_CHG | \
+ WOL_CTL_DIS_PME_ON_PATTERN | \
+ WOL_CTL_DIS_PME_ON_MAGIC_PKT | \
+ WOL_CTL_DIS_LINK_CHG_UNIT | \
+ WOL_CTL_DIS_PATTERN_UNIT | \
+ WOL_CTL_DIS_MAGIC_PKT_UNIT)
+
+/* WOL_MATCH_CTL 8 bit WOL Match Control Reg */
+#define WOL_CTL_PATT_ENA(x) (1 << (x))
+
+
+/* XMAC II registers */
+enum {
+ XM_MMU_CMD = 0x0000, /* 16 bit r/w MMU Command Register */
+ XM_POFF = 0x0008, /* 32 bit r/w Packet Offset Register */
+ XM_BURST = 0x000c, /* 32 bit r/w Burst Register for half duplex*/
+ XM_1L_VLAN_TAG = 0x0010, /* 16 bit r/w One Level VLAN Tag ID */
+ XM_2L_VLAN_TAG = 0x0014, /* 16 bit r/w Two Level VLAN Tag ID */
+ XM_TX_CMD = 0x0020, /* 16 bit r/w Transmit Command Register */
+ XM_TX_RT_LIM = 0x0024, /* 16 bit r/w Transmit Retry Limit Register */
+ XM_TX_STIME = 0x0028, /* 16 bit r/w Transmit Slottime Register */
+ XM_TX_IPG = 0x002c, /* 16 bit r/w Transmit Inter Packet Gap */
+ XM_RX_CMD = 0x0030, /* 16 bit r/w Receive Command Register */
+ XM_PHY_ADDR = 0x0034, /* 16 bit r/w PHY Address Register */
+ XM_PHY_DATA = 0x0038, /* 16 bit r/w PHY Data Register */
+ XM_GP_PORT = 0x0040, /* 32 bit r/w General Purpose Port Register */
+ XM_IMSK = 0x0044, /* 16 bit r/w Interrupt Mask Register */
+ XM_ISRC = 0x0048, /* 16 bit r/o Interrupt Status Register */
+ XM_HW_CFG = 0x004c, /* 16 bit r/w Hardware Config Register */
+ XM_TX_LO_WM = 0x0060, /* 16 bit r/w Tx FIFO Low Water Mark */
+ XM_TX_HI_WM = 0x0062, /* 16 bit r/w Tx FIFO High Water Mark */
+ XM_TX_THR = 0x0064, /* 16 bit r/w Tx Request Threshold */
+ XM_HT_THR = 0x0066, /* 16 bit r/w Host Request Threshold */
+ XM_PAUSE_DA = 0x0068, /* NA reg r/w Pause Destination Address */
+ XM_CTL_PARA = 0x0070, /* 32 bit r/w Control Parameter Register */
+ XM_MAC_OPCODE = 0x0074, /* 16 bit r/w Opcode for MAC control frames */
+ XM_MAC_PTIME = 0x0076, /* 16 bit r/w Pause time for MAC ctrl frames*/
+ XM_TX_STAT = 0x0078, /* 32 bit r/o Tx Status LIFO Register */
+
+ XM_EXM_START = 0x0080, /* r/w Start Address of the EXM Regs */
+#define XM_EXM(reg) (XM_EXM_START + ((reg) << 3))
+};
+
+enum {
+ XM_SRC_CHK = 0x0100, /* NA reg r/w Source Check Address Register */
+ XM_SA = 0x0108, /* NA reg r/w Station Address Register */
+ XM_HSM = 0x0110, /* 64 bit r/w Hash Match Address Registers */
+ XM_RX_LO_WM = 0x0118, /* 16 bit r/w Receive Low Water Mark */
+ XM_RX_HI_WM = 0x011a, /* 16 bit r/w Receive High Water Mark */
+ XM_RX_THR = 0x011c, /* 32 bit r/w Receive Request Threshold */
+ XM_DEV_ID = 0x0120, /* 32 bit r/o Device ID Register */
+ XM_MODE = 0x0124, /* 32 bit r/w Mode Register */
+ XM_LSA = 0x0128, /* NA reg r/o Last Source Register */
+ XM_TS_READ = 0x0130, /* 32 bit r/o Time Stamp Read Register */
+ XM_TS_LOAD = 0x0134, /* 32 bit r/o Time Stamp Load Value */
+ XM_STAT_CMD = 0x0200, /* 16 bit r/w Statistics Command Register */
+ XM_RX_CNT_EV = 0x0204, /* 32 bit r/o Rx Counter Event Register */
+ XM_TX_CNT_EV = 0x0208, /* 32 bit r/o Tx Counter Event Register */
+ XM_RX_EV_MSK = 0x020c, /* 32 bit r/w Rx Counter Event Mask */
+ XM_TX_EV_MSK = 0x0210, /* 32 bit r/w Tx Counter Event Mask */
+ XM_TXF_OK = 0x0280, /* 32 bit r/o Frames Transmitted OK Conuter */
+ XM_TXO_OK_HI = 0x0284, /* 32 bit r/o Octets Transmitted OK High Cnt*/
+ XM_TXO_OK_LO = 0x0288, /* 32 bit r/o Octets Transmitted OK Low Cnt */
+ XM_TXF_BC_OK = 0x028c, /* 32 bit r/o Broadcast Frames Xmitted OK */
+ XM_TXF_MC_OK = 0x0290, /* 32 bit r/o Multicast Frames Xmitted OK */
+ XM_TXF_UC_OK = 0x0294, /* 32 bit r/o Unicast Frames Xmitted OK */
+ XM_TXF_LONG = 0x0298, /* 32 bit r/o Tx Long Frame Counter */
+ XM_TXE_BURST = 0x029c, /* 32 bit r/o Tx Burst Event Counter */
+ XM_TXF_MPAUSE = 0x02a0, /* 32 bit r/o Tx Pause MAC Ctrl Frame Cnt */
+ XM_TXF_MCTRL = 0x02a4, /* 32 bit r/o Tx MAC Ctrl Frame Counter */
+ XM_TXF_SNG_COL = 0x02a8, /* 32 bit r/o Tx Single Collision Counter */
+ XM_TXF_MUL_COL = 0x02ac, /* 32 bit r/o Tx Multiple Collision Counter */
+ XM_TXF_ABO_COL = 0x02b0, /* 32 bit r/o Tx aborted due to Exces. Col. */
+ XM_TXF_LAT_COL = 0x02b4, /* 32 bit r/o Tx Late Collision Counter */
+ XM_TXF_DEF = 0x02b8, /* 32 bit r/o Tx Deferred Frame Counter */
+ XM_TXF_EX_DEF = 0x02bc, /* 32 bit r/o Tx Excessive Deferall Counter */
+ XM_TXE_FIFO_UR = 0x02c0, /* 32 bit r/o Tx FIFO Underrun Event Cnt */
+ XM_TXE_CS_ERR = 0x02c4, /* 32 bit r/o Tx Carrier Sense Error Cnt */
+ XM_TXP_UTIL = 0x02c8, /* 32 bit r/o Tx Utilization in % */
+ XM_TXF_64B = 0x02d0, /* 32 bit r/o 64 Byte Tx Frame Counter */
+ XM_TXF_127B = 0x02d4, /* 32 bit r/o 65-127 Byte Tx Frame Counter */
+ XM_TXF_255B = 0x02d8, /* 32 bit r/o 128-255 Byte Tx Frame Counter */
+ XM_TXF_511B = 0x02dc, /* 32 bit r/o 256-511 Byte Tx Frame Counter */
+ XM_TXF_1023B = 0x02e0, /* 32 bit r/o 512-1023 Byte Tx Frame Counter*/
+ XM_TXF_MAX_SZ = 0x02e4, /* 32 bit r/o 1024-MaxSize Byte Tx Frame Cnt*/
+ XM_RXF_OK = 0x0300, /* 32 bit r/o Frames Received OK */
+ XM_RXO_OK_HI = 0x0304, /* 32 bit r/o Octets Received OK High Cnt */
+ XM_RXO_OK_LO = 0x0308, /* 32 bit r/o Octets Received OK Low Counter*/
+ XM_RXF_BC_OK = 0x030c, /* 32 bit r/o Broadcast Frames Received OK */
+ XM_RXF_MC_OK = 0x0310, /* 32 bit r/o Multicast Frames Received OK */
+ XM_RXF_UC_OK = 0x0314, /* 32 bit r/o Unicast Frames Received OK */
+ XM_RXF_MPAUSE = 0x0318, /* 32 bit r/o Rx Pause MAC Ctrl Frame Cnt */
+ XM_RXF_MCTRL = 0x031c, /* 32 bit r/o Rx MAC Ctrl Frame Counter */
+ XM_RXF_INV_MP = 0x0320, /* 32 bit r/o Rx invalid Pause Frame Cnt */
+ XM_RXF_INV_MOC = 0x0324, /* 32 bit r/o Rx Frames with inv. MAC Opcode*/
+ XM_RXE_BURST = 0x0328, /* 32 bit r/o Rx Burst Event Counter */
+ XM_RXE_FMISS = 0x032c, /* 32 bit r/o Rx Missed Frames Event Cnt */
+ XM_RXF_FRA_ERR = 0x0330, /* 32 bit r/o Rx Framing Error Counter */
+ XM_RXE_FIFO_OV = 0x0334, /* 32 bit r/o Rx FIFO overflow Event Cnt */
+ XM_RXF_JAB_PKT = 0x0338, /* 32 bit r/o Rx Jabber Packet Frame Cnt */
+ XM_RXE_CAR_ERR = 0x033c, /* 32 bit r/o Rx Carrier Event Error Cnt */
+ XM_RXF_LEN_ERR = 0x0340, /* 32 bit r/o Rx in Range Length Error */
+ XM_RXE_SYM_ERR = 0x0344, /* 32 bit r/o Rx Symbol Error Counter */
+ XM_RXE_SHT_ERR = 0x0348, /* 32 bit r/o Rx Short Event Error Cnt */
+ XM_RXE_RUNT = 0x034c, /* 32 bit r/o Rx Runt Event Counter */
+ XM_RXF_LNG_ERR = 0x0350, /* 32 bit r/o Rx Frame too Long Error Cnt */
+ XM_RXF_FCS_ERR = 0x0354, /* 32 bit r/o Rx Frame Check Seq. Error Cnt */
+ XM_RXF_CEX_ERR = 0x035c, /* 32 bit r/o Rx Carrier Ext Error Frame Cnt*/
+ XM_RXP_UTIL = 0x0360, /* 32 bit r/o Rx Utilization in % */
+ XM_RXF_64B = 0x0368, /* 32 bit r/o 64 Byte Rx Frame Counter */
+ XM_RXF_127B = 0x036c, /* 32 bit r/o 65-127 Byte Rx Frame Counter */
+ XM_RXF_255B = 0x0370, /* 32 bit r/o 128-255 Byte Rx Frame Counter */
+ XM_RXF_511B = 0x0374, /* 32 bit r/o 256-511 Byte Rx Frame Counter */
+ XM_RXF_1023B = 0x0378, /* 32 bit r/o 512-1023 Byte Rx Frame Counter*/
+ XM_RXF_MAX_SZ = 0x037c, /* 32 bit r/o 1024-MaxSize Byte Rx Frame Cnt*/
+};
+
+/* XM_MMU_CMD 16 bit r/w MMU Command Register */
+enum {
+ XM_MMU_PHY_RDY = 1<<12,/* Bit 12: PHY Read Ready */
+ XM_MMU_PHY_BUSY = 1<<11,/* Bit 11: PHY Busy */
+ XM_MMU_IGN_PF = 1<<10,/* Bit 10: Ignore Pause Frame */
+ XM_MMU_MAC_LB = 1<<9, /* Bit 9: Enable MAC Loopback */
+ XM_MMU_FRC_COL = 1<<7, /* Bit 7: Force Collision */
+ XM_MMU_SIM_COL = 1<<6, /* Bit 6: Simulate Collision */
+ XM_MMU_NO_PRE = 1<<5, /* Bit 5: No MDIO Preamble */
+ XM_MMU_GMII_FD = 1<<4, /* Bit 4: GMII uses Full Duplex */
+ XM_MMU_RAT_CTRL = 1<<3, /* Bit 3: Enable Rate Control */
+ XM_MMU_GMII_LOOP= 1<<2, /* Bit 2: PHY is in Loopback Mode */
+ XM_MMU_ENA_RX = 1<<1, /* Bit 1: Enable Receiver */
+ XM_MMU_ENA_TX = 1<<0, /* Bit 0: Enable Transmitter */
+};
+
+
+/* XM_TX_CMD 16 bit r/w Transmit Command Register */
+enum {
+ XM_TX_BK2BK = 1<<6, /* Bit 6: Ignor Carrier Sense (Tx Bk2Bk)*/
+ XM_TX_ENC_BYP = 1<<5, /* Bit 5: Set Encoder in Bypass Mode */
+ XM_TX_SAM_LINE = 1<<4, /* Bit 4: (sc) Start utilization calculation */
+ XM_TX_NO_GIG_MD = 1<<3, /* Bit 3: Disable Carrier Extension */
+ XM_TX_NO_PRE = 1<<2, /* Bit 2: Disable Preamble Generation */
+ XM_TX_NO_CRC = 1<<1, /* Bit 1: Disable CRC Generation */
+ XM_TX_AUTO_PAD = 1<<0, /* Bit 0: Enable Automatic Padding */
+};
+
+/* XM_TX_RT_LIM 16 bit r/w Transmit Retry Limit Register */
+#define XM_RT_LIM_MSK 0x1f /* Bit 4..0: Tx Retry Limit */
+
+
+/* XM_TX_STIME 16 bit r/w Transmit Slottime Register */
+#define XM_STIME_MSK 0x7f /* Bit 6..0: Tx Slottime bits */
+
+
+/* XM_TX_IPG 16 bit r/w Transmit Inter Packet Gap */
+#define XM_IPG_MSK 0xff /* Bit 7..0: IPG value bits */
+
+
+/* XM_RX_CMD 16 bit r/w Receive Command Register */
+enum {
+ XM_RX_LENERR_OK = 1<<8, /* Bit 8 don't set Rx Err bit for */
+ /* inrange error packets */
+ XM_RX_BIG_PK_OK = 1<<7, /* Bit 7 don't set Rx Err bit for */
+ /* jumbo packets */
+ XM_RX_IPG_CAP = 1<<6, /* Bit 6 repl. type field with IPG */
+ XM_RX_TP_MD = 1<<5, /* Bit 5: Enable transparent Mode */
+ XM_RX_STRIP_FCS = 1<<4, /* Bit 4: Enable FCS Stripping */
+ XM_RX_SELF_RX = 1<<3, /* Bit 3: Enable Rx of own packets */
+ XM_RX_SAM_LINE = 1<<2, /* Bit 2: (sc) Start utilization calculation */
+ XM_RX_STRIP_PAD = 1<<1, /* Bit 1: Strip pad bytes of Rx frames */
+ XM_RX_DIS_CEXT = 1<<0, /* Bit 0: Disable carrier ext. check */
+};
+
+
+/* XM_PHY_ADDR 16 bit r/w PHY Address Register */
+#define XM_PHY_ADDR_SZ 0x1f /* Bit 4..0: PHY Address bits */
+
+
+/* XM_GP_PORT 32 bit r/w General Purpose Port Register */
+enum {
+ XM_GP_ANIP = 1<<6, /* Bit 6: (ro) Auto-Neg. in progress */
+ XM_GP_FRC_INT = 1<<5, /* Bit 5: (sc) Force Interrupt */
+ XM_GP_RES_MAC = 1<<3, /* Bit 3: (sc) Reset MAC and FIFOs */
+ XM_GP_RES_STAT = 1<<2, /* Bit 2: (sc) Reset the statistics module */
+ XM_GP_INP_ASS = 1<<0, /* Bit 0: (ro) GP Input Pin asserted */
+};
+
+
+/* XM_IMSK 16 bit r/w Interrupt Mask Register */
+/* XM_ISRC 16 bit r/o Interrupt Status Register */
+enum {
+ XM_IS_LNK_AE = 1<<14, /* Bit 14: Link Asynchronous Event */
+ XM_IS_TX_ABORT = 1<<13, /* Bit 13: Transmit Abort, late Col. etc */
+ XM_IS_FRC_INT = 1<<12, /* Bit 12: Force INT bit set in GP */
+ XM_IS_INP_ASS = 1<<11, /* Bit 11: Input Asserted, GP bit 0 set */
+ XM_IS_LIPA_RC = 1<<10, /* Bit 10: Link Partner requests config */
+ XM_IS_RX_PAGE = 1<<9, /* Bit 9: Page Received */
+ XM_IS_TX_PAGE = 1<<8, /* Bit 8: Next Page Loaded for Transmit */
+ XM_IS_AND = 1<<7, /* Bit 7: Auto-Negotiation Done */
+ XM_IS_TSC_OV = 1<<6, /* Bit 6: Time Stamp Counter Overflow */
+ XM_IS_RXC_OV = 1<<5, /* Bit 5: Rx Counter Event Overflow */
+ XM_IS_TXC_OV = 1<<4, /* Bit 4: Tx Counter Event Overflow */
+ XM_IS_RXF_OV = 1<<3, /* Bit 3: Receive FIFO Overflow */
+ XM_IS_TXF_UR = 1<<2, /* Bit 2: Transmit FIFO Underrun */
+ XM_IS_TX_COMP = 1<<1, /* Bit 1: Frame Tx Complete */
+ XM_IS_RX_COMP = 1<<0, /* Bit 0: Frame Rx Complete */
+};
+
+#define XM_DEF_MSK (~(XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE | \
+ XM_IS_AND | XM_IS_RXC_OV | XM_IS_TXC_OV | \
+ XM_IS_RXF_OV | XM_IS_TXF_UR))
+
+
+/* XM_HW_CFG 16 bit r/w Hardware Config Register */
+enum {
+ XM_HW_GEN_EOP = 1<<3, /* Bit 3: generate End of Packet pulse */
+ XM_HW_COM4SIG = 1<<2, /* Bit 2: use Comma Detect for Sig. Det.*/
+ XM_HW_GMII_MD = 1<<0, /* Bit 0: GMII Interface selected */
+};
+
+
+/* XM_TX_LO_WM 16 bit r/w Tx FIFO Low Water Mark */
+/* XM_TX_HI_WM 16 bit r/w Tx FIFO High Water Mark */
+#define XM_TX_WM_MSK 0x01ff /* Bit 9.. 0 Tx FIFO Watermark bits */
+
+/* XM_TX_THR 16 bit r/w Tx Request Threshold */
+/* XM_HT_THR 16 bit r/w Host Request Threshold */
+/* XM_RX_THR 16 bit r/w Rx Request Threshold */
+#define XM_THR_MSK 0x03ff /* Bit 10.. 0 Rx/Tx Request Threshold bits */
+
+
+/* XM_TX_STAT 32 bit r/o Tx Status LIFO Register */
+enum {
+ XM_ST_VALID = (1UL<<31), /* Bit 31: Status Valid */
+ XM_ST_BYTE_CNT = (0x3fffL<<17), /* Bit 30..17: Tx frame Length */
+ XM_ST_RETRY_CNT = (0x1fL<<12), /* Bit 16..12: Retry Count */
+ XM_ST_EX_COL = 1<<11, /* Bit 11: Excessive Collisions */
+ XM_ST_EX_DEF = 1<<10, /* Bit 10: Excessive Deferral */
+ XM_ST_BURST = 1<<9, /* Bit 9: p. xmitted in burst md*/
+ XM_ST_DEFER = 1<<8, /* Bit 8: packet was defered */
+ XM_ST_BC = 1<<7, /* Bit 7: Broadcast packet */
+ XM_ST_MC = 1<<6, /* Bit 6: Multicast packet */
+ XM_ST_UC = 1<<5, /* Bit 5: Unicast packet */
+ XM_ST_TX_UR = 1<<4, /* Bit 4: FIFO Underrun occured */
+ XM_ST_CS_ERR = 1<<3, /* Bit 3: Carrier Sense Error */
+ XM_ST_LAT_COL = 1<<2, /* Bit 2: Late Collision Error */
+ XM_ST_MUL_COL = 1<<1, /* Bit 1: Multiple Collisions */
+ XM_ST_SGN_COL = 1<<0, /* Bit 0: Single Collision */
+};
+
+/* XM_RX_LO_WM 16 bit r/w Receive Low Water Mark */
+/* XM_RX_HI_WM 16 bit r/w Receive High Water Mark */
+#define XM_RX_WM_MSK 0x03ff /* Bit 11.. 0: Rx FIFO Watermark bits */
+
+
+/* XM_DEV_ID 32 bit r/o Device ID Register */
+#define XM_DEV_OUI (0x00ffffffUL<<8) /* Bit 31..8: Device OUI */
+#define XM_DEV_REV (0x07L << 5) /* Bit 7..5: Chip Rev Num */
+
+
+/* XM_MODE 32 bit r/w Mode Register */
+enum {
+ XM_MD_ENA_REJ = 1<<26, /* Bit 26: Enable Frame Reject */
+ XM_MD_SPOE_E = 1<<25, /* Bit 25: Send Pause on Edge */
+ /* extern generated */
+ XM_MD_TX_REP = 1<<24, /* Bit 24: Transmit Repeater Mode */
+ XM_MD_SPOFF_I = 1<<23, /* Bit 23: Send Pause on FIFO full */
+ /* intern generated */
+ XM_MD_LE_STW = 1<<22, /* Bit 22: Rx Stat Word in Little Endian */
+ XM_MD_TX_CONT = 1<<21, /* Bit 21: Send Continuous */
+ XM_MD_TX_PAUSE = 1<<20, /* Bit 20: (sc) Send Pause Frame */
+ XM_MD_ATS = 1<<19, /* Bit 19: Append Time Stamp */
+ XM_MD_SPOL_I = 1<<18, /* Bit 18: Send Pause on Low */
+ /* intern generated */
+ XM_MD_SPOH_I = 1<<17, /* Bit 17: Send Pause on High */
+ /* intern generated */
+ XM_MD_CAP = 1<<16, /* Bit 16: Check Address Pair */
+ XM_MD_ENA_HASH = 1<<15, /* Bit 15: Enable Hashing */
+ XM_MD_CSA = 1<<14, /* Bit 14: Check Station Address */
+ XM_MD_CAA = 1<<13, /* Bit 13: Check Address Array */
+ XM_MD_RX_MCTRL = 1<<12, /* Bit 12: Rx MAC Control Frame */
+ XM_MD_RX_RUNT = 1<<11, /* Bit 11: Rx Runt Frames */
+ XM_MD_RX_IRLE = 1<<10, /* Bit 10: Rx in Range Len Err Frame */
+ XM_MD_RX_LONG = 1<<9, /* Bit 9: Rx Long Frame */
+ XM_MD_RX_CRCE = 1<<8, /* Bit 8: Rx CRC Error Frame */
+ XM_MD_RX_ERR = 1<<7, /* Bit 7: Rx Error Frame */
+ XM_MD_DIS_UC = 1<<6, /* Bit 6: Disable Rx Unicast */
+ XM_MD_DIS_MC = 1<<5, /* Bit 5: Disable Rx Multicast */
+ XM_MD_DIS_BC = 1<<4, /* Bit 4: Disable Rx Broadcast */
+ XM_MD_ENA_PROM = 1<<3, /* Bit 3: Enable Promiscuous */
+ XM_MD_ENA_BE = 1<<2, /* Bit 2: Enable Big Endian */
+ XM_MD_FTF = 1<<1, /* Bit 1: (sc) Flush Tx FIFO */
+ XM_MD_FRF = 1<<0, /* Bit 0: (sc) Flush Rx FIFO */
+};
+
+#define XM_PAUSE_MODE (XM_MD_SPOE_E | XM_MD_SPOL_I | XM_MD_SPOH_I)
+#define XM_DEF_MODE (XM_MD_RX_RUNT | XM_MD_RX_IRLE | XM_MD_RX_LONG |\
+ XM_MD_RX_CRCE | XM_MD_RX_ERR | XM_MD_CSA | XM_MD_CAA)
+
+/* XM_STAT_CMD 16 bit r/w Statistics Command Register */
+enum {
+ XM_SC_SNP_RXC = 1<<5, /* Bit 5: (sc) Snap Rx Counters */
+ XM_SC_SNP_TXC = 1<<4, /* Bit 4: (sc) Snap Tx Counters */
+ XM_SC_CP_RXC = 1<<3, /* Bit 3: Copy Rx Counters Continuously */
+ XM_SC_CP_TXC = 1<<2, /* Bit 2: Copy Tx Counters Continuously */
+ XM_SC_CLR_RXC = 1<<1, /* Bit 1: (sc) Clear Rx Counters */
+ XM_SC_CLR_TXC = 1<<0, /* Bit 0: (sc) Clear Tx Counters */
+};
+
+
+/* XM_RX_CNT_EV 32 bit r/o Rx Counter Event Register */
+/* XM_RX_EV_MSK 32 bit r/w Rx Counter Event Mask */
+enum {
+ XMR_MAX_SZ_OV = 1<<31, /* Bit 31: 1024-MaxSize Rx Cnt Ov*/
+ XMR_1023B_OV = 1<<30, /* Bit 30: 512-1023Byte Rx Cnt Ov*/
+ XMR_511B_OV = 1<<29, /* Bit 29: 256-511 Byte Rx Cnt Ov*/
+ XMR_255B_OV = 1<<28, /* Bit 28: 128-255 Byte Rx Cnt Ov*/
+ XMR_127B_OV = 1<<27, /* Bit 27: 65-127 Byte Rx Cnt Ov */
+ XMR_64B_OV = 1<<26, /* Bit 26: 64 Byte Rx Cnt Ov */
+ XMR_UTIL_OV = 1<<25, /* Bit 25: Rx Util Cnt Overflow */
+ XMR_UTIL_UR = 1<<24, /* Bit 24: Rx Util Cnt Underrun */
+ XMR_CEX_ERR_OV = 1<<23, /* Bit 23: CEXT Err Cnt Ov */
+ XMR_FCS_ERR_OV = 1<<21, /* Bit 21: Rx FCS Error Cnt Ov */
+ XMR_LNG_ERR_OV = 1<<20, /* Bit 20: Rx too Long Err Cnt Ov*/
+ XMR_RUNT_OV = 1<<19, /* Bit 19: Runt Event Cnt Ov */
+ XMR_SHT_ERR_OV = 1<<18, /* Bit 18: Rx Short Ev Err Cnt Ov*/
+ XMR_SYM_ERR_OV = 1<<17, /* Bit 17: Rx Sym Err Cnt Ov */
+ XMR_CAR_ERR_OV = 1<<15, /* Bit 15: Rx Carr Ev Err Cnt Ov */
+ XMR_JAB_PKT_OV = 1<<14, /* Bit 14: Rx Jabb Packet Cnt Ov */
+ XMR_FIFO_OV = 1<<13, /* Bit 13: Rx FIFO Ov Ev Cnt Ov */
+ XMR_FRA_ERR_OV = 1<<12, /* Bit 12: Rx Framing Err Cnt Ov */
+ XMR_FMISS_OV = 1<<11, /* Bit 11: Rx Missed Ev Cnt Ov */
+ XMR_BURST = 1<<10, /* Bit 10: Rx Burst Event Cnt Ov */
+ XMR_INV_MOC = 1<<9, /* Bit 9: Rx with inv. MAC OC Ov*/
+ XMR_INV_MP = 1<<8, /* Bit 8: Rx inv Pause Frame Ov */
+ XMR_MCTRL_OV = 1<<7, /* Bit 7: Rx MAC Ctrl-F Cnt Ov */
+ XMR_MPAUSE_OV = 1<<6, /* Bit 6: Rx Pause MAC Ctrl-F Ov*/
+ XMR_UC_OK_OV = 1<<5, /* Bit 5: Rx Unicast Frame CntOv*/
+ XMR_MC_OK_OV = 1<<4, /* Bit 4: Rx Multicast Cnt Ov */
+ XMR_BC_OK_OV = 1<<3, /* Bit 3: Rx Broadcast Cnt Ov */
+ XMR_OK_LO_OV = 1<<2, /* Bit 2: Octets Rx OK Low CntOv*/
+ XMR_OK_HI_OV = 1<<1, /* Bit 1: Octets Rx OK Hi Cnt Ov*/
+ XMR_OK_OV = 1<<0, /* Bit 0: Frames Received Ok Ov */
+};
+
+#define XMR_DEF_MSK (XMR_OK_LO_OV | XMR_OK_HI_OV)
+
+/* XM_TX_CNT_EV 32 bit r/o Tx Counter Event Register */
+/* XM_TX_EV_MSK 32 bit r/w Tx Counter Event Mask */
+enum {
+ XMT_MAX_SZ_OV = 1<<25, /* Bit 25: 1024-MaxSize Tx Cnt Ov*/
+ XMT_1023B_OV = 1<<24, /* Bit 24: 512-1023Byte Tx Cnt Ov*/
+ XMT_511B_OV = 1<<23, /* Bit 23: 256-511 Byte Tx Cnt Ov*/
+ XMT_255B_OV = 1<<22, /* Bit 22: 128-255 Byte Tx Cnt Ov*/
+ XMT_127B_OV = 1<<21, /* Bit 21: 65-127 Byte Tx Cnt Ov */
+ XMT_64B_OV = 1<<20, /* Bit 20: 64 Byte Tx Cnt Ov */
+ XMT_UTIL_OV = 1<<19, /* Bit 19: Tx Util Cnt Overflow */
+ XMT_UTIL_UR = 1<<18, /* Bit 18: Tx Util Cnt Underrun */
+ XMT_CS_ERR_OV = 1<<17, /* Bit 17: Tx Carr Sen Err Cnt Ov*/
+ XMT_FIFO_UR_OV = 1<<16, /* Bit 16: Tx FIFO Ur Ev Cnt Ov */
+ XMT_EX_DEF_OV = 1<<15, /* Bit 15: Tx Ex Deferall Cnt Ov */
+ XMT_DEF = 1<<14, /* Bit 14: Tx Deferred Cnt Ov */
+ XMT_LAT_COL_OV = 1<<13, /* Bit 13: Tx Late Col Cnt Ov */
+ XMT_ABO_COL_OV = 1<<12, /* Bit 12: Tx abo dueto Ex Col Ov*/
+ XMT_MUL_COL_OV = 1<<11, /* Bit 11: Tx Mult Col Cnt Ov */
+ XMT_SNG_COL = 1<<10, /* Bit 10: Tx Single Col Cnt Ov */
+ XMT_MCTRL_OV = 1<<9, /* Bit 9: Tx MAC Ctrl Counter Ov*/
+ XMT_MPAUSE = 1<<8, /* Bit 8: Tx Pause MAC Ctrl-F Ov*/
+ XMT_BURST = 1<<7, /* Bit 7: Tx Burst Event Cnt Ov */
+ XMT_LONG = 1<<6, /* Bit 6: Tx Long Frame Cnt Ov */
+ XMT_UC_OK_OV = 1<<5, /* Bit 5: Tx Unicast Cnt Ov */
+ XMT_MC_OK_OV = 1<<4, /* Bit 4: Tx Multicast Cnt Ov */
+ XMT_BC_OK_OV = 1<<3, /* Bit 3: Tx Broadcast Cnt Ov */
+ XMT_OK_LO_OV = 1<<2, /* Bit 2: Octets Tx OK Low CntOv*/
+ XMT_OK_HI_OV = 1<<1, /* Bit 1: Octets Tx OK Hi Cnt Ov*/
+ XMT_OK_OV = 1<<0, /* Bit 0: Frames Tx Ok Ov */
+};
+
+#define XMT_DEF_MSK (XMT_OK_LO_OV | XMT_OK_HI_OV)
+
+struct skge_rx_desc {
+ u32 control;
+ u32 next_offset;
+ u32 dma_lo;
+ u32 dma_hi;
+ u32 status;
+ u32 timestamp;
+ u16 csum2;
+ u16 csum1;
+ u16 csum2_start;
+ u16 csum1_start;
+};
+
+struct skge_tx_desc {
+ u32 control;
+ u32 next_offset;
+ u32 dma_lo;
+ u32 dma_hi;
+ u32 status;
+ u32 csum_offs;
+ u16 csum_write;
+ u16 csum_start;
+ u32 rsvd;
+};
+
+struct skge_element {
+ struct skge_element *next;
+ void *desc;
+ struct sk_buff *skb;
+ DECLARE_PCI_UNMAP_ADDR(mapaddr);
+ DECLARE_PCI_UNMAP_LEN(maplen);
+};
+
+struct skge_ring {
+ struct skge_element *to_clean;
+ struct skge_element *to_use;
+ struct skge_element *start;
+ unsigned long count;
+};
+
+
+struct skge_hw {
+ void __iomem *regs;
+ struct pci_dev *pdev;
+ u32 intr_mask;
+ struct net_device *dev[2];
+
+ u8 mac_cfg;
+ u8 chip_id;
+ u8 phy_type;
+ u8 pmd_type;
+ u16 phy_addr;
+
+ u32 ram_size;
+ u32 ram_offset;
+
+ struct tasklet_struct ext_tasklet;
+ spinlock_t phy_lock;
+};
+
+static inline int isdualport(const struct skge_hw *hw)
+{
+ return !(hw->mac_cfg & CFG_SNG_MAC);
+}
+
+static inline u8 chip_rev(const struct skge_hw *hw)
+{
+ return (hw->mac_cfg & CFG_CHIP_R_MSK) >> 4;
+}
+
+static inline int iscopper(const struct skge_hw *hw)
+{
+ return (hw->pmd_type == 'T');
+}
+
+enum {
+ FLOW_MODE_NONE = 0, /* No Flow-Control */
+ FLOW_MODE_LOC_SEND = 1, /* Local station sends PAUSE */
+ FLOW_MODE_REM_SEND = 2, /* Symmetric or just remote */
+ FLOW_MODE_SYMMETRIC = 3, /* Both stations may send PAUSE */
+};
+
+struct skge_port {
+ u32 msg_enable;
+ struct skge_hw *hw;
+ struct net_device *netdev;
+ int port;
+
+ spinlock_t tx_lock;
+ u32 tx_avail;
+ struct skge_ring tx_ring;
+ struct skge_ring rx_ring;
+
+ struct net_device_stats net_stats;
+
+ u8 rx_csum;
+ u8 blink_on;
+ u8 flow_control;
+ u8 wol;
+ u8 autoneg; /* AUTONEG_ENABLE, AUTONEG_DISABLE */
+ u8 duplex; /* DUPLEX_HALF, DUPLEX_FULL */
+ u16 speed; /* SPEED_1000, SPEED_100, ... */
+ u32 advertising;
+
+ void *mem; /* PCI memory for rings */
+ dma_addr_t dma;
+ unsigned long mem_size;
+
+ struct timer_list link_check;
+ struct timer_list led_blink;
+};
+
+
+/* Register accessor for memory mapped device */
+static inline u32 skge_read32(const struct skge_hw *hw, int reg)
+{
+ return readl(hw->regs + reg);
+
+}
+
+static inline u16 skge_read16(const struct skge_hw *hw, int reg)
+{
+ return readw(hw->regs + reg);
+}
+
+static inline u8 skge_read8(const struct skge_hw *hw, int reg)
+{
+ return readb(hw->regs + reg);
+}
+
+static inline void skge_write32(const struct skge_hw *hw, int reg, u32 val)
+{
+ writel(val, hw->regs + reg);
+}
+
+static inline void skge_write16(const struct skge_hw *hw, int reg, u16 val)
+{
+ writew(val, hw->regs + reg);
+}
+
+static inline void skge_write8(const struct skge_hw *hw, int reg, u8 val)
+{
+ writeb(val, hw->regs + reg);
+}
+
+/* MAC Related Registers inside the device. */
+#define SKGEMAC_REG(port,reg) (((port)<<7)+(reg))
+
+/* PCI config space can be accessed via memory mapped space */
+#define SKGEPCI_REG(reg) ((reg)+ 0x380)
+
+#define SKGEXM_REG(port, reg) \
+ ((BASE_XMAC_1 + (port) * (BASE_XMAC_2 - BASE_XMAC_1)) | (reg) << 1)
+
+static inline u32 skge_xm_read32(const struct skge_hw *hw, int port, int reg)
+{
+ return skge_read32(hw, SKGEXM_REG(port,reg));
+}
+
+static inline u16 skge_xm_read16(const struct skge_hw *hw, int port, int reg)
+{
+ return skge_read16(hw, SKGEXM_REG(port,reg));
+}
+
+static inline u8 skge_xm_read8(const struct skge_hw *hw, int port, int reg)
+{
+ return skge_read8(hw, SKGEXM_REG(port,reg));
+}
+
+static inline void skge_xm_write32(const struct skge_hw *hw, int port, int r, u32 v)
+{
+ skge_write32(hw, SKGEXM_REG(port,r), v);
+}
+
+static inline void skge_xm_write16(const struct skge_hw *hw, int port, int r, u16 v)
+{
+ skge_write16(hw, SKGEXM_REG(port,r), v);
+}
+
+static inline void skge_xm_write8(const struct skge_hw *hw, int port, int r, u8 v)
+{
+ skge_write8(hw, SKGEXM_REG(port,r), v);
+}
+
+static inline void skge_xm_outhash(const struct skge_hw *hw, int port, int reg,
+ const u8 *hash)
+{
+ skge_xm_write16(hw, port, reg,
+ (u16)hash[0] | ((u16)hash[1] << 8));
+ skge_xm_write16(hw, port, reg+2,
+ (u16)hash[2] | ((u16)hash[3] << 8));
+ skge_xm_write16(hw, port, reg+4,
+ (u16)hash[4] | ((u16)hash[5] << 8));
+ skge_xm_write16(hw, port, reg+6,
+ (u16)hash[6] | ((u16)hash[7] << 8));
+}
+
+static inline void skge_xm_outaddr(const struct skge_hw *hw, int port, int reg,
+ const u8 *addr)
+{
+ skge_xm_write16(hw, port, reg,
+ (u16)addr[0] | ((u16)addr[1] << 8));
+ skge_xm_write16(hw, port, reg,
+ (u16)addr[2] | ((u16)addr[3] << 8));
+ skge_xm_write16(hw, port, reg,
+ (u16)addr[4] | ((u16)addr[5] << 8));
+}
+
+
+#define SKGEGMA_REG(port,reg) \
+ ((reg) + BASE_GMAC_1 + \
+ (port) * (BASE_GMAC_2-BASE_GMAC_1))
+
+static inline u16 skge_gma_read16(const struct skge_hw *hw, int port, int reg)
+{
+ return skge_read16(hw, SKGEGMA_REG(port,reg));
+}
+
+static inline u32 skge_gma_read32(const struct skge_hw *hw, int port, int reg)
+{
+ return (u32) skge_read16(hw, SKGEGMA_REG(port,reg))
+ | ((u32)skge_read16(hw, SKGEGMA_REG(port,reg+4)) << 16);
+}
+
+static inline u8 skge_gma_read8(const struct skge_hw *hw, int port, int reg)
+{
+ return skge_read8(hw, SKGEGMA_REG(port,reg));
+}
+
+static inline void skge_gma_write16(const struct skge_hw *hw, int port, int r, u16 v)
+{
+ skge_write16(hw, SKGEGMA_REG(port,r), v);
+}
+
+static inline void skge_gma_write32(const struct skge_hw *hw, int port, int r, u32 v)
+{
+ skge_write16(hw, SKGEGMA_REG(port, r), (u16) v);
+ skge_write32(hw, SKGEGMA_REG(port, r+4), (u16)(v >> 16));
+}
+
+static inline void skge_gma_write8(const struct skge_hw *hw, int port, int r, u8 v)
+{
+ skge_write8(hw, SKGEGMA_REG(port,r), v);
+}
+
+static inline void skge_gm_set_addr(struct skge_hw *hw, int port, int reg,
+ const u8 *addr)
+{
+ skge_gma_write16(hw, port, reg,
+ (u16) addr[0] | ((u16) addr[1] << 8));
+ skge_gma_write16(hw, port, reg+4,
+ (u16) addr[2] | ((u16) addr[3] << 8));
+ skge_gma_write16(hw, port, reg+8,
+ (u16) addr[4] | ((u16) addr[5] << 8));
+}
+
+#endif
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index 8f7841c0374..c79e0ad4ba0 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -198,18 +198,12 @@ err_exit:
static void
sl_free_bufs(struct slip *sl)
{
- void * tmp;
-
/* Free all SLIP frame buffers. */
- tmp = xchg(&sl->rbuff, NULL);
- kfree(tmp);
- tmp = xchg(&sl->xbuff, NULL);
- kfree(tmp);
+ kfree(xchg(&sl->rbuff, NULL));
+ kfree(xchg(&sl->xbuff, NULL));
#ifdef SL_INCLUDE_CSLIP
- tmp = xchg(&sl->cbuff, NULL);
- kfree(tmp);
- if ((tmp = xchg(&sl->slcomp, NULL)) != NULL)
- slhc_free(tmp);
+ kfree(xchg(&sl->cbuff, NULL));
+ slhc_free(xchg(&sl->slcomp, NULL));
#endif
}
@@ -1430,7 +1424,7 @@ static void __exit slip_exit(void)
kfree(slip_devs);
slip_devs = NULL;
- if ((i = tty_register_ldisc(N_SLIP, NULL)))
+ if ((i = tty_unregister_ldisc(N_SLIP)))
{
printk(KERN_ERR "SLIP: can't unregister line discipline (err = %d)\n", i);
}
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index 5e561ba4433..fd80048f7f7 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -129,7 +129,7 @@ MODULE_PARM_DESC(nowait, "set to 1 for no wait state");
/*
* Transmit timeout, default 5 seconds.
*/
-static int watchdog = 5000;
+static int watchdog = 1000;
module_param(watchdog, int, 0400);
MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
@@ -660,15 +660,14 @@ static void smc_hardware_send_pkt(unsigned long data)
SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG);
/*
- * If THROTTLE_TX_PKTS is set, we look at the TX_EMPTY flag
- * before queueing this packet for TX, and if it's clear then
- * we stop the queue here. This will have the effect of
- * having at most 2 packets queued for TX in the chip's memory
- * at all time. If THROTTLE_TX_PKTS is not set then the queue
- * is stopped only when memory allocation (MC_ALLOC) does not
- * succeed right away.
+ * If THROTTLE_TX_PKTS is set, we stop the queue here. This will
+ * have the effect of having at most one packet queued for TX
+ * in the chip's memory at all time.
+ *
+ * If THROTTLE_TX_PKTS is not set then the queue is stopped only
+ * when memory allocation (MC_ALLOC) does not succeed right away.
*/
- if (THROTTLE_TX_PKTS && !(SMC_GET_INT() & IM_TX_EMPTY_INT))
+ if (THROTTLE_TX_PKTS)
netif_stop_queue(dev);
/* queue the packet for TX */
@@ -792,17 +791,20 @@ static void smc_tx(struct net_device *dev)
DBG(2, "%s: TX STATUS 0x%04x PNR 0x%02x\n",
dev->name, tx_status, packet_no);
- if (!(tx_status & TS_SUCCESS))
+ if (!(tx_status & ES_TX_SUC))
lp->stats.tx_errors++;
- if (tx_status & TS_LOSTCAR)
+
+ if (tx_status & ES_LOSTCARR)
lp->stats.tx_carrier_errors++;
- if (tx_status & TS_LATCOL) {
- PRINTK("%s: late collision occurred on last xmit\n", dev->name);
+ if (tx_status & (ES_LATCOL | ES_16COL)) {
+ PRINTK("%s: %s occurred on last xmit\n", dev->name,
+ (tx_status & ES_LATCOL) ?
+ "late collision" : "too many collisions");
lp->stats.tx_window_errors++;
if (!(lp->stats.tx_window_errors & 63) && net_ratelimit()) {
- printk(KERN_INFO "%s: unexpectedly large numbers of "
- "late collisions. Please check duplex "
+ printk(KERN_INFO "%s: unexpectedly large number of "
+ "bad collisions. Please check duplex "
"setting.\n", dev->name);
}
}
@@ -1236,7 +1238,7 @@ static void smc_10bt_check_media(struct net_device *dev, int init)
old_carrier = netif_carrier_ok(dev) ? 1 : 0;
SMC_SELECT_BANK(0);
- new_carrier = SMC_inw(ioaddr, EPH_STATUS_REG) & ES_LINK_OK ? 1 : 0;
+ new_carrier = (SMC_GET_EPH_STATUS() & ES_LINK_OK) ? 1 : 0;
SMC_SELECT_BANK(2);
if (init || (old_carrier != new_carrier)) {
@@ -1308,15 +1310,16 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (!status)
break;
- if (status & IM_RCV_INT) {
- DBG(3, "%s: RX irq\n", dev->name);
- smc_rcv(dev);
- } else if (status & IM_TX_INT) {
+ if (status & IM_TX_INT) {
+ /* do this before RX as it will free memory quickly */
DBG(3, "%s: TX int\n", dev->name);
smc_tx(dev);
SMC_ACK_INT(IM_TX_INT);
if (THROTTLE_TX_PKTS)
netif_wake_queue(dev);
+ } else if (status & IM_RCV_INT) {
+ DBG(3, "%s: RX irq\n", dev->name);
+ smc_rcv(dev);
} else if (status & IM_ALLOC_INT) {
DBG(3, "%s: Allocation irq\n", dev->name);
tasklet_hi_schedule(&lp->tx_task);
@@ -1337,7 +1340,10 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* multiple collisions */
lp->stats.collisions += card_stats & 0xF;
} else if (status & IM_RX_OVRN_INT) {
- DBG(1, "%s: RX overrun\n", dev->name);
+ DBG(1, "%s: RX overrun (EPH_ST 0x%04x)\n", dev->name,
+ ({ int eph_st; SMC_SELECT_BANK(0);
+ eph_st = SMC_GET_EPH_STATUS();
+ SMC_SELECT_BANK(2); eph_st; }) );
SMC_ACK_INT(IM_RX_OVRN_INT);
lp->stats.rx_errors++;
lp->stats.rx_fifo_errors++;
@@ -1389,7 +1395,7 @@ static void smc_timeout(struct net_device *dev)
{
struct smc_local *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
- int status, mask, meminfo, fifo;
+ int status, mask, eph_st, meminfo, fifo;
DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
@@ -1398,11 +1404,13 @@ static void smc_timeout(struct net_device *dev)
mask = SMC_GET_INT_MASK();
fifo = SMC_GET_FIFO();
SMC_SELECT_BANK(0);
+ eph_st = SMC_GET_EPH_STATUS();
meminfo = SMC_GET_MIR();
SMC_SELECT_BANK(2);
spin_unlock_irq(&lp->lock);
- PRINTK( "%s: INT 0x%02x MASK 0x%02x MEM 0x%04x FIFO 0x%04x\n",
- dev->name, status, mask, meminfo, fifo );
+ PRINTK( "%s: TX timeout (INT 0x%02x INTMASK 0x%02x "
+ "MEM 0x%04x FIFO 0x%04x EPH_ST 0x%04x)\n",
+ dev->name, status, mask, meminfo, fifo, eph_st );
smc_reset(dev);
smc_enable(dev);
@@ -1863,7 +1871,7 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr)
SMC_SELECT_BANK(1);
val = SMC_GET_BASE();
val = ((val & 0x1F00) >> 3) << SMC_IO_SHIFT;
- if (((unsigned long)ioaddr & ((PAGE_SIZE-1)<<SMC_IO_SHIFT)) != val) { /*XXX: WTF? */
+ if (((unsigned int)ioaddr & (0x3e0 << SMC_IO_SHIFT)) != val) {
printk("%s: IOADDR %p doesn't match configuration (%x).\n",
CARDNAME, ioaddr, val);
}
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index ddd2688e7d3..946528e6b74 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -151,7 +151,7 @@
/* We actually can't write halfwords properly if not word aligned */
static inline void
-SMC_outw(u16 val, unsigned long ioaddr, int reg)
+SMC_outw(u16 val, void __iomem *ioaddr, int reg)
{
if (reg & 2) {
unsigned int v = val << 16;
@@ -317,7 +317,7 @@ static inline void SMC_outsw (unsigned long a, int r, unsigned char* p, int l)
#define SMC_insl(a, r, p, l) \
smc_pxa_dma_insl(a, lp->physaddr, r, dev->dma, p, l)
static inline void
-smc_pxa_dma_insl(u_long ioaddr, u_long physaddr, int reg, int dma,
+smc_pxa_dma_insl(void __iomem *ioaddr, u_long physaddr, int reg, int dma,
u_char *buf, int len)
{
dma_addr_t dmabuf;
@@ -355,7 +355,7 @@ smc_pxa_dma_insl(u_long ioaddr, u_long physaddr, int reg, int dma,
#define SMC_insw(a, r, p, l) \
smc_pxa_dma_insw(a, lp->physaddr, r, dev->dma, p, l)
static inline void
-smc_pxa_dma_insw(u_long ioaddr, u_long physaddr, int reg, int dma,
+smc_pxa_dma_insw(void __iomem *ioaddr, u_long physaddr, int reg, int dma,
u_char *buf, int len)
{
dma_addr_t dmabuf;
@@ -681,14 +681,6 @@ static const char * chip_ids[ 16 ] = {
/*
- . Transmit status bits
-*/
-#define TS_SUCCESS 0x0001
-#define TS_LOSTCAR 0x0400
-#define TS_LATCOL 0x0200
-#define TS_16COL 0x0010
-
-/*
. Receive status bits
*/
#define RS_ALGNERR 0x8000
@@ -845,6 +837,7 @@ static const char * chip_ids[ 16 ] = {
#define SMC_GET_FIFO() SMC_inw( ioaddr, FIFO_REG )
#define SMC_GET_PTR() SMC_inw( ioaddr, PTR_REG )
#define SMC_SET_PTR(x) SMC_outw( x, ioaddr, PTR_REG )
+#define SMC_GET_EPH_STATUS() SMC_inw( ioaddr, EPH_STATUS_REG )
#define SMC_GET_RCR() SMC_inw( ioaddr, RCR_REG )
#define SMC_SET_RCR(x) SMC_outw( x, ioaddr, RCR_REG )
#define SMC_GET_REV() SMC_inw( ioaddr, REV_REG )
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 236bdd3f6ba..12e2b6826fa 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -2,7 +2,7 @@
/*
Written 1998-2000 by Donald Becker.
- Current maintainer is Ion Badulescu <ionut@cs.columbia.edu>. Please
+ Current maintainer is Ion Badulescu <ionut ta badula tod org>. Please
send all bug reports to me, and not to Donald Becker, as this code
has been heavily modified from Donald's original version.
@@ -129,12 +129,18 @@
- put the chip to a D3 slumber on driver unload
- added config option to enable/disable NAPI
-TODO: bugfixes (no bugs known as of right now)
+ LK1.4.2 (Ion Badulescu)
+ - finally added firmware (GPL'ed by Adaptec)
+ - removed compatibility code for 2.2.x
+
+TODO: - fix forced speed/duplexing code (broken a long time ago, when
+ somebody converted the driver to use the generic MII code)
+ - fix VLAN support
*/
#define DRV_NAME "starfire"
-#define DRV_VERSION "1.03+LK1.4.1"
-#define DRV_RELDATE "February 10, 2002"
+#define DRV_VERSION "1.03+LK1.4.2"
+#define DRV_RELDATE "January 19, 2005"
#include <linux/config.h>
#include <linux/version.h>
@@ -145,25 +151,15 @@ TODO: bugfixes (no bugs known as of right now)
#include <linux/etherdevice.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/crc32.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/if_vlan.h>
#include <asm/processor.h> /* Processor type for cache alignment. */
#include <asm/uaccess.h>
#include <asm/io.h>
-/*
- * Adaptec's license for their drivers (which is where I got the
- * firmware files) does not allow one to redistribute them. Thus, we can't
- * include the firmware with this driver.
- *
- * However, should a legal-to-distribute firmware become available,
- * the driver developer would need only to obtain the firmware in the
- * form of a C header file.
- * Once that's done, the #undef below must be changed into a #define
- * for this driver to really use the firmware. Note that Rx/Tx
- * hardware TCP checksumming is not possible without the firmware.
- *
- * WANTED: legal firmware to include with this GPL'd driver.
- */
-#undef HAS_FIRMWARE
+#include "starfire_firmware.h"
/*
* The current frame processor firmware fails to checksum a fragment
* of length 1. If and when this is fixed, the #define below can be removed.
@@ -172,13 +168,7 @@ TODO: bugfixes (no bugs known as of right now)
/*
* Define this if using the driver with the zero-copy patch
*/
-#if defined(HAS_FIRMWARE) && defined(MAX_SKB_FRAGS)
#define ZEROCOPY
-#endif
-
-#ifdef HAS_FIRMWARE
-#include "starfire_firmware.h"
-#endif /* HAS_FIRMWARE */
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
#define VLAN_SUPPORT
@@ -202,11 +192,7 @@ static int mtu;
The Starfire has a 512 element hash table based on the Ethernet CRC. */
static int multicast_filter_limit = 512;
/* Whether to do TCP/UDP checksums in hardware */
-#ifdef HAS_FIRMWARE
static int enable_hw_cksum = 1;
-#else
-static int enable_hw_cksum = 0;
-#endif
#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
/*
@@ -291,43 +277,15 @@ static int full_duplex[MAX_UNITS] = {0, };
#define RX_DESC_ADDR_SIZE RxDescAddr32bit
#endif
-#ifdef MAX_SKB_FRAGS
#define skb_first_frag_len(skb) skb_headlen(skb)
#define skb_num_frags(skb) (skb_shinfo(skb)->nr_frags + 1)
-#else /* not MAX_SKB_FRAGS */
-#define skb_first_frag_len(skb) (skb->len)
-#define skb_num_frags(skb) 1
-#endif /* not MAX_SKB_FRAGS */
-
-/* 2.2.x compatibility code */
-#if LINUX_VERSION_CODE < 0x20300
-
-#include "starfire-kcomp22.h"
-
-#else /* LINUX_VERSION_CODE > 0x20300 */
-
-#include <linux/crc32.h>
-#include <linux/ethtool.h>
-#include <linux/mii.h>
-
-#include <linux/if_vlan.h>
-
-#define init_tx_timer(dev, func, timeout) \
- dev->tx_timeout = func; \
- dev->watchdog_timeo = timeout;
-#define kick_tx_timer(dev, func, timeout)
-
-#define netif_start_if(dev)
-#define netif_stop_if(dev)
-
-#define PCI_SLOT_NAME(pci_dev) pci_name(pci_dev)
-
-#endif /* LINUX_VERSION_CODE > 0x20300 */
#ifdef HAVE_NETDEV_POLL
#define init_poll(dev) \
+do { \
dev->poll = &netdev_poll; \
- dev->weight = max_interrupt_work;
+ dev->weight = max_interrupt_work; \
+} while (0)
#define netdev_rx(dev, ioaddr) \
do { \
u32 intr_enable; \
@@ -341,7 +299,7 @@ do { \
/* Paranoia check */ \
intr_enable = readl(ioaddr + IntrEnable); \
if (intr_enable & (IntrRxDone | IntrRxEmpty)) { \
- printk("%s: interrupt while in polling mode!\n", dev->name); \
+ printk(KERN_INFO "%s: interrupt while in polling mode!\n", dev->name); \
intr_enable &= ~(IntrRxDone | IntrRxEmpty); \
writel(intr_enable, ioaddr + IntrEnable); \
} \
@@ -371,6 +329,7 @@ KERN_INFO " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELD
MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver");
MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
module_param(max_interrupt_work, int, 0);
module_param(mtu, int, 0);
@@ -425,7 +384,7 @@ on the 32/64 bitness of the architecture), and relies on automatic
minimum-length padding. It does not use the completion queue
consumer index, but instead checks for non-zero status entries.
-For receive this driver uses type 0/1/2/3 receive descriptors. The driver
+For receive this driver uses type 2/3 receive descriptors. The driver
allocates full frame size skbuffs for the Rx ring buffers, so all frames
should fit in a single descriptor. The driver does not use the completion
queue consumer index, but instead checks for non-zero status entries.
@@ -476,7 +435,7 @@ IVc. Errata
*/
-
+
enum chip_capability_flags {CanHaveMII=1, };
@@ -670,7 +629,6 @@ struct full_rx_done_desc {
u32 timestamp;
};
/* XXX: this is ugly and I'm not sure it's worth the trouble -Ion */
-#ifdef HAS_FIRMWARE
#ifdef VLAN_SUPPORT
typedef struct full_rx_done_desc rx_done_desc;
#define RxComplType RxComplType3
@@ -678,15 +636,6 @@ typedef struct full_rx_done_desc rx_done_desc;
typedef struct csum_rx_done_desc rx_done_desc;
#define RxComplType RxComplType2
#endif /* not VLAN_SUPPORT */
-#else /* not HAS_FIRMWARE */
-#ifdef VLAN_SUPPORT
-typedef struct basic_rx_done_desc rx_done_desc;
-#define RxComplType RxComplType1
-#else /* not VLAN_SUPPORT */
-typedef struct short_rx_done_desc rx_done_desc;
-#define RxComplType RxComplType0
-#endif /* not VLAN_SUPPORT */
-#endif /* not HAS_FIRMWARE */
enum rx_done_bits {
RxOK=0x20000000, RxFIFOErr=0x10000000, RxBufQ2=0x08000000,
@@ -898,13 +847,10 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
/* enable MWI -- it vastly improves Rx performance on sparc64 */
pci_set_mwi(pdev);
-#ifdef MAX_SKB_FRAGS
- dev->features |= NETIF_F_SG;
-#endif /* MAX_SKB_FRAGS */
#ifdef ZEROCOPY
/* Starfire can do TCP/UDP checksumming */
if (enable_hw_cksum)
- dev->features |= NETIF_F_IP_CSUM;
+ dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
#endif /* ZEROCOPY */
#ifdef VLAN_SUPPORT
dev->features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
@@ -1008,7 +954,8 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
/* The chip-specific entries in the device structure. */
dev->open = &netdev_open;
dev->hard_start_xmit = &start_tx;
- init_tx_timer(dev, tx_timeout, TX_TIMEOUT);
+ dev->tx_timeout = tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
init_poll(dev);
dev->stop = &netdev_close;
dev->get_stats = &get_stats;
@@ -1039,7 +986,7 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
if ((mdio_read(dev, phy, MII_BMCR) & BMCR_RESET) == 0)
break;
if (boguscnt == 0) {
- printk("%s: PHY reset never completed!\n", dev->name);
+ printk("%s: PHY#%d reset never completed!\n", dev->name, phy);
continue;
}
mii_status = mdio_read(dev, phy, MII_BMSR);
@@ -1110,6 +1057,7 @@ static int netdev_open(struct net_device *dev)
size_t tx_done_q_size, rx_done_q_size, tx_ring_size, rx_ring_size;
/* Do we ever need to reset the chip??? */
+
retval = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev);
if (retval)
return retval;
@@ -1211,7 +1159,6 @@ static int netdev_open(struct net_device *dev)
writel(np->intr_timer_ctrl, ioaddr + IntrTimerCtrl);
- netif_start_if(dev);
netif_start_queue(dev);
if (debug > 1)
@@ -1238,13 +1185,11 @@ static int netdev_open(struct net_device *dev)
writel(ETH_P_8021Q, ioaddr + VlanType);
#endif /* VLAN_SUPPORT */
-#ifdef HAS_FIRMWARE
/* Load Rx/Tx firmware into the frame processors */
for (i = 0; i < FIRMWARE_RX_SIZE * 2; i++)
writel(firmware_rx[i], ioaddr + RxGfpMem + i * 4);
for (i = 0; i < FIRMWARE_TX_SIZE * 2; i++)
writel(firmware_tx[i], ioaddr + TxGfpMem + i * 4);
-#endif /* HAS_FIRMWARE */
if (enable_hw_cksum)
/* Enable the Rx and Tx units, and the Rx/Tx frame processors. */
writel(TxEnable|TxGFPEnable|RxEnable|RxGFPEnable, ioaddr + GenCtrl);
@@ -1378,8 +1323,6 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
u32 status;
int i;
- kick_tx_timer(dev, tx_timeout, TX_TIMEOUT);
-
/*
* be cautious here, wrapping the queue has weird semantics
* and we may not have enough slots even when it seems we do.
@@ -1404,7 +1347,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
}
if (has_bad_length)
- skb_checksum_help(skb);
+ skb_checksum_help(skb, 0);
}
#endif /* ZEROCOPY && HAS_BROKEN_FIRMWARE */
@@ -1433,12 +1376,10 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
np->tx_info[entry].mapping =
pci_map_single(np->pci_dev, skb->data, skb_first_frag_len(skb), PCI_DMA_TODEVICE);
} else {
-#ifdef MAX_SKB_FRAGS
skb_frag_t *this_frag = &skb_shinfo(skb)->frags[i - 1];
status |= this_frag->size;
np->tx_info[entry].mapping =
pci_map_single(np->pci_dev, page_address(this_frag->page) + this_frag->page_offset, this_frag->size, PCI_DMA_TODEVICE);
-#endif /* MAX_SKB_FRAGS */
}
np->tx_ring[entry].addr = cpu_to_dma(np->tx_info[entry].mapping);
@@ -1531,7 +1472,6 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
np->tx_info[entry].mapping = 0;
np->dirty_tx += np->tx_info[entry].used_slots;
entry = (entry + np->tx_info[entry].used_slots) % TX_RING_SIZE;
-#ifdef MAX_SKB_FRAGS
{
int i;
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
@@ -1543,7 +1483,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
entry++;
}
}
-#endif /* MAX_SKB_FRAGS */
+
dev_kfree_skb_irq(skb);
}
np->tx_done_q[np->tx_done].status = 0;
@@ -1603,7 +1543,7 @@ static int __netdev_rx(struct net_device *dev, int *quota)
if (debug > 4)
printk(KERN_DEBUG " netdev_rx() status of %d was %#8.8x.\n", np->rx_done, desc_status);
if (!(desc_status & RxOK)) {
- /* There was a error. */
+ /* There was an error. */
if (debug > 2)
printk(KERN_DEBUG " netdev_rx() Rx error was %#8.8x.\n", desc_status);
np->stats.rx_errors++;
@@ -1656,11 +1596,10 @@ static int __netdev_rx(struct net_device *dev, int *quota)
#endif
skb->protocol = eth_type_trans(skb, dev);
-#if defined(HAS_FIRMWARE) || defined(VLAN_SUPPORT)
+#ifdef VLAN_SUPPORT
if (debug > 4)
printk(KERN_DEBUG " netdev_rx() status2 of %d was %#4.4x.\n", np->rx_done, le16_to_cpu(desc->status2));
#endif
-#ifdef HAS_FIRMWARE
if (le16_to_cpu(desc->status2) & 0x0100) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
np->stats.rx_compressed++;
@@ -1679,7 +1618,6 @@ static int __netdev_rx(struct net_device *dev, int *quota)
skb->csum = le16_to_cpu(desc->csum);
printk(KERN_DEBUG "%s: checksum_hw, status2 = %#x\n", dev->name, le16_to_cpu(desc->status2));
}
-#endif /* HAS_FIRMWARE */
#ifdef VLAN_SUPPORT
if (np->vlgrp && le16_to_cpu(desc->status2) & 0x0200) {
if (debug > 4)
@@ -1900,9 +1838,6 @@ static struct net_device_stats *get_stats(struct net_device *dev)
}
-/* Chips may use the upper or lower CRC bits, and may reverse and/or invert
- them. Select the endian-ness that results in minimal calculations.
-*/
static void set_rx_mode(struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
@@ -1969,6 +1904,8 @@ static void set_rx_mode(struct net_device *dev)
memset(mc_filter, 0, sizeof(mc_filter));
for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
i++, mclist = mclist->next) {
+ /* The chip uses the upper 9 CRC bits
+ as index into the hash table */
int bit_nr = ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 23;
__u32 *fptr = (__u32 *) &mc_filter[(bit_nr >> 4) & ~1];
@@ -2001,7 +1938,7 @@ static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
struct netdev_private *np = netdev_priv(dev);
strcpy(info->driver, DRV_NAME);
strcpy(info->version, DRV_VERSION);
- strcpy(info->bus_info, PCI_SLOT_NAME(np->pci_dev));
+ strcpy(info->bus_info, pci_name(np->pci_dev));
}
static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
@@ -2083,7 +2020,6 @@ static int netdev_close(struct net_device *dev)
int i;
netif_stop_queue(dev);
- netif_stop_if(dev);
if (debug > 1) {
printk(KERN_DEBUG "%s: Shutting down ethercard, Intr status %#8.8x.\n",
@@ -2184,7 +2120,13 @@ static int __init starfire_init (void)
/* when a module, this is printed whether or not devices are found in probe */
#ifdef MODULE
printk(version);
+#ifdef HAVE_NETDEV_POLL
+ printk(KERN_INFO DRV_NAME ": polling (NAPI) enabled\n");
+#else
+ printk(KERN_INFO DRV_NAME ": polling (NAPI) disabled\n");
#endif
+#endif
+
#ifndef ADDR_64BITS
/* we can do this test only at run-time... sigh */
if (sizeof(dma_addr_t) == sizeof(u64)) {
@@ -2192,10 +2134,6 @@ static int __init starfire_init (void)
return -ENODEV;
}
#endif /* not ADDR_64BITS */
-#ifndef HAS_FIRMWARE
- /* unconditionally disable hw cksums if firmware is not present */
- enable_hw_cksum = 0;
-#endif /* not HAS_FIRMWARE */
return pci_module_init (&starfire_driver);
}
diff --git a/drivers/net/starfire_firmware.h b/drivers/net/starfire_firmware.h
new file mode 100644
index 00000000000..0a668528955
--- /dev/null
+++ b/drivers/net/starfire_firmware.h
@@ -0,0 +1,346 @@
+/*
+ * Copyright 2003 Adaptec, Inc.
+ *
+ * Please read the following license before using the Adaptec Software
+ * ("Program"). If you do not agree to the license terms, do not use the
+ * Program:
+ *
+ * You agree to be bound by version 2 of the General Public License ("GPL")
+ * dated June 1991, which can be found at http://www.fsf.org/licenses/gpl.html.
+ * If the link is broken, write to Free Software Foundation, 59 Temple Place,
+ * Boston, Massachusetts 02111-1307.
+ *
+ * BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE IT IS LICENSED "AS IS" AND
+ * THERE IS NO WARRANTY FOR THE PROGRAM, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTIBILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * (TO THE EXTENT PERMITTED BY APPLICABLE LAW). USE OF THE PROGRAM IS AT YOUR
+ * OWN RISK. IN NO EVENT WILL ADAPTEC OR ITS LICENSORS BE LIABLE TO YOU FOR
+ * DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM.
+ *
+ */
+
+static const u32 firmware_rx[] = {
+ 0x010003dc, 0x00000000,
+ 0x04000421, 0x00000086,
+ 0x80000015, 0x0000180e,
+ 0x81000015, 0x00006664,
+ 0x1a0040ab, 0x00000b06,
+ 0x14200011, 0x00000000,
+ 0x14204022, 0x0000aaaa,
+ 0x14204022, 0x00000300,
+ 0x14204022, 0x00000000,
+ 0x1a0040ab, 0x00000b14,
+ 0x14200011, 0x00000000,
+ 0x83000015, 0x00000002,
+ 0x04000021, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x04000421, 0x00000087,
+ 0x00000010, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x00008015, 0x00000000,
+ 0x0000003e, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x82000015, 0x00004000,
+ 0x009e8050, 0x00000000,
+ 0x03008015, 0x00000000,
+ 0x86008015, 0x00000000,
+ 0x82000015, 0x00008000,
+ 0x0100001c, 0x00000000,
+ 0x000050a0, 0x0000010c,
+ 0x4e20d011, 0x00006008,
+ 0x1420d012, 0x00004008,
+ 0x0000f090, 0x00007000,
+ 0x0000c8b0, 0x00003000,
+ 0x00004040, 0x00000000,
+ 0x00108015, 0x00000000,
+ 0x00a2c150, 0x00004000,
+ 0x00a400b0, 0x00000014,
+ 0x00000020, 0x00000000,
+ 0x2500400d, 0x00002525,
+ 0x00047220, 0x00003100,
+ 0x00934070, 0x00000000,
+ 0x00000020, 0x00000000,
+ 0x00924460, 0x00000184,
+ 0x2b20c011, 0x00000000,
+ 0x0000c420, 0x00000540,
+ 0x36014018, 0x0000422d,
+ 0x14200011, 0x00000000,
+ 0x00924460, 0x00000183,
+ 0x3200001f, 0x00000034,
+ 0x02ac0015, 0x00000002,
+ 0x00a60110, 0x00000008,
+ 0x42200011, 0x00000000,
+ 0x00924060, 0x00000103,
+ 0x0000001e, 0x00000000,
+ 0x00000020, 0x00000100,
+ 0x0000001e, 0x00000000,
+ 0x00924460, 0x00000086,
+ 0x00004080, 0x00000000,
+ 0x0092c070, 0x00000000,
+ 0x00924060, 0x00000100,
+ 0x0000c890, 0x00005000,
+ 0x00a6c110, 0x00000000,
+ 0x00b0c090, 0x00000012,
+ 0x021c0015, 0x00000000,
+ 0x3200001f, 0x00000034,
+ 0x00924460, 0x00000510,
+ 0x44210011, 0x00000000,
+ 0x42000011, 0x00000000,
+ 0x83000015, 0x00000040,
+ 0x00924460, 0x00000508,
+ 0x45014018, 0x00004545,
+ 0x00808050, 0x00000000,
+ 0x62208012, 0x00000000,
+ 0x82000015, 0x00000800,
+ 0x15200011, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x80000015, 0x0000eea4,
+ 0x81000015, 0x0000005f,
+ 0x00000060, 0x00000000,
+ 0x00004120, 0x00000000,
+ 0x00004a00, 0x00004000,
+ 0x00924460, 0x00000190,
+ 0x5601401a, 0x00005956,
+ 0x14000011, 0x00000000,
+ 0x00934050, 0x00000018,
+ 0x00930050, 0x00000018,
+ 0x3601403a, 0x0000002d,
+ 0x000643a9, 0x00000000,
+ 0x0000c420, 0x00000140,
+ 0x5601401a, 0x00005956,
+ 0x14000011, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x000642a9, 0x00000000,
+ 0x00024420, 0x00000183,
+ 0x5601401a, 0x00005956,
+ 0x82000015, 0x00002000,
+ 0x15200011, 0x00000000,
+ 0x82000015, 0x00000010,
+ 0x15200011, 0x00000000,
+ 0x82000015, 0x00000010,
+ 0x15200011, 0x00000000,
+}; /* 104 Rx instructions */
+#define FIRMWARE_RX_SIZE 104
+
+static const u32 firmware_tx[] = {
+ 0x010003dc, 0x00000000,
+ 0x04000421, 0x00000086,
+ 0x80000015, 0x0000180e,
+ 0x81000015, 0x00006664,
+ 0x1a0040ab, 0x00000b06,
+ 0x14200011, 0x00000000,
+ 0x14204022, 0x0000aaaa,
+ 0x14204022, 0x00000300,
+ 0x14204022, 0x00000000,
+ 0x1a0040ab, 0x00000b14,
+ 0x14200011, 0x00000000,
+ 0x83000015, 0x00000002,
+ 0x04000021, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x04000421, 0x00000087,
+ 0x00000010, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x00008015, 0x00000000,
+ 0x0000003e, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x82000015, 0x00004000,
+ 0x009e8050, 0x00000000,
+ 0x03008015, 0x00000000,
+ 0x86008015, 0x00000000,
+ 0x82000015, 0x00008000,
+ 0x0100001c, 0x00000000,
+ 0x000050a0, 0x0000010c,
+ 0x4e20d011, 0x00006008,
+ 0x1420d012, 0x00004008,
+ 0x0000f090, 0x00007000,
+ 0x0000c8b0, 0x00003000,
+ 0x00004040, 0x00000000,
+ 0x00108015, 0x00000000,
+ 0x00a2c150, 0x00004000,
+ 0x00a400b0, 0x00000014,
+ 0x00000020, 0x00000000,
+ 0x2500400d, 0x00002525,
+ 0x00047220, 0x00003100,
+ 0x00934070, 0x00000000,
+ 0x00000020, 0x00000000,
+ 0x00924460, 0x00000184,
+ 0x2b20c011, 0x00000000,
+ 0x0000c420, 0x00000540,
+ 0x36014018, 0x0000422d,
+ 0x14200011, 0x00000000,
+ 0x00924460, 0x00000183,
+ 0x3200001f, 0x00000034,
+ 0x02ac0015, 0x00000002,
+ 0x00a60110, 0x00000008,
+ 0x42200011, 0x00000000,
+ 0x00924060, 0x00000103,
+ 0x0000001e, 0x00000000,
+ 0x00000020, 0x00000100,
+ 0x0000001e, 0x00000000,
+ 0x00924460, 0x00000086,
+ 0x00004080, 0x00000000,
+ 0x0092c070, 0x00000000,
+ 0x00924060, 0x00000100,
+ 0x0000c890, 0x00005000,
+ 0x00a6c110, 0x00000000,
+ 0x00b0c090, 0x00000012,
+ 0x021c0015, 0x00000000,
+ 0x3200001f, 0x00000034,
+ 0x00924460, 0x00000510,
+ 0x44210011, 0x00000000,
+ 0x42000011, 0x00000000,
+ 0x83000015, 0x00000040,
+ 0x00924460, 0x00000508,
+ 0x45014018, 0x00004545,
+ 0x00808050, 0x00000000,
+ 0x62208012, 0x00000000,
+ 0x82000015, 0x00000800,
+ 0x15200011, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x80000015, 0x0000eea4,
+ 0x81000015, 0x0000005f,
+ 0x00000060, 0x00000000,
+ 0x00004120, 0x00000000,
+ 0x00004a00, 0x00004000,
+ 0x00924460, 0x00000190,
+ 0x5601401a, 0x00005956,
+ 0x14000011, 0x00000000,
+ 0x00934050, 0x00000018,
+ 0x00930050, 0x00000018,
+ 0x3601403a, 0x0000002d,
+ 0x000643a9, 0x00000000,
+ 0x0000c420, 0x00000140,
+ 0x5601401a, 0x00005956,
+ 0x14000011, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x000642a9, 0x00000000,
+ 0x00024420, 0x00000183,
+ 0x5601401a, 0x00005956,
+ 0x82000015, 0x00002000,
+ 0x15200011, 0x00000000,
+ 0x82000015, 0x00000010,
+ 0x15200011, 0x00000000,
+ 0x82000015, 0x00000010,
+ 0x15200011, 0x00000000,
+}; /* 104 Tx instructions */
+#define FIRMWARE_TX_SIZE 104
+#if 0
+static const u32 firmware_wol[] = {
+ 0x010003dc, 0x00000000,
+ 0x19000421, 0x00000087,
+ 0x80000015, 0x00001a1a,
+ 0x81000015, 0x00001a1a,
+ 0x1a0040ab, 0x00000b06,
+ 0x15200011, 0x00000000,
+ 0x15204022, 0x0000aaaa,
+ 0x15204022, 0x00000300,
+ 0x15204022, 0x00000000,
+ 0x1a0040ab, 0x00000b15,
+ 0x15200011, 0x00000000,
+ 0x83000015, 0x00000002,
+ 0x04000021, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x04000421, 0x00000087,
+ 0x00000010, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x00008015, 0x00000000,
+ 0x0000003e, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x82000015, 0x00004000,
+ 0x82000015, 0x00008000,
+ 0x0000000c, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x00004080, 0x00000100,
+ 0x1f20c011, 0x00001122,
+ 0x2720f011, 0x00003011,
+ 0x19200071, 0x00000000,
+ 0x1a200051, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x1d2040a4, 0x00003344,
+ 0x1d2040a2, 0x00005566,
+ 0x000040a0, 0x00000100,
+ 0x00108050, 0x00000001,
+ 0x1a208012, 0x00000006,
+ 0x82000015, 0x00008080,
+ 0x010003dc, 0x00000000,
+ 0x1d2040a4, 0x00002233,
+ 0x1d2040a4, 0x00004455,
+ 0x2d208011, 0x00000005,
+ 0x1d2040a4, 0x00006611,
+ 0x00108050, 0x00000001,
+ 0x27200011, 0x00000000,
+ 0x1d2050a4, 0x00006600,
+ 0x82000015, 0x00008080,
+ 0x010003dc, 0x00000000,
+ 0x00000050, 0x00000000,
+ 0x1b200031, 0x00000000,
+ 0x0000001e, 0x00000000,
+ 0x0000001e, 0x00000000,
+ 0x0000001e, 0x00000000,
+ 0x0000001e, 0x00000000,
+ 0x00924460, 0x00000086,
+ 0x00004080, 0x00000000,
+ 0x0092c070, 0x00000000,
+ 0x00924060, 0x00000100,
+ 0x0000c890, 0x00005000,
+ 0x00a6c110, 0x00000000,
+ 0x00b0c090, 0x00000012,
+ 0x021c0015, 0x00000000,
+ 0x3200001f, 0x00000034,
+ 0x00924460, 0x00000510,
+ 0x44210011, 0x00000000,
+ 0x42000011, 0x00000000,
+ 0x83000015, 0x00000040,
+ 0x00924460, 0x00000508,
+ 0x476a0012, 0x00000100,
+ 0x83000015, 0x00000008,
+ 0x16200011, 0x00000000,
+ 0x001e8050, 0x00000000,
+ 0x001e8050, 0x00000000,
+ 0x00808050, 0x00000000,
+ 0x03008015, 0x00000000,
+ 0x62208012, 0x00000000,
+ 0x82000015, 0x00000800,
+ 0x16200011, 0x00000000,
+ 0x80000015, 0x0000eea4,
+ 0x81000015, 0x0000005f,
+ 0x00000020, 0x00000000,
+ 0x00004120, 0x00000000,
+ 0x00004a00, 0x00004000,
+ 0x00924460, 0x00000190,
+ 0x5c01401a, 0x0000595c,
+ 0x15000011, 0x00000000,
+ 0x00934050, 0x00000018,
+ 0x00930050, 0x00000018,
+ 0x3601403a, 0x0000002d,
+ 0x00064029, 0x00000000,
+ 0x0000c420, 0x00000140,
+ 0x5c01401a, 0x0000595c,
+ 0x15000011, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x00000010, 0x00000000,
+ 0x00064029, 0x00000000,
+ 0x00024420, 0x00000183,
+ 0x5c01401a, 0x0000595c,
+ 0x82000015, 0x00002000,
+ 0x16200011, 0x00000000,
+ 0x82000015, 0x00000010,
+ 0x16200011, 0x00000000,
+ 0x82000015, 0x00000010,
+ 0x16200011, 0x00000000,
+}; /* 104 WoL instructions */
+#define FIRMWARE_WOL_SIZE 104
+#endif
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index f79b02e80e7..7e371b1209a 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -7,7 +7,12 @@
* Copyright (C) 2005 Broadcom Corporation.
*
* Firmware is:
- * Copyright (C) 2000-2003 Broadcom Corporation.
+ * Derived from proprietary unpublished source code,
+ * Copyright (C) 2000-2003 Broadcom Corporation.
+ *
+ * Permission is hereby granted for the distribution of this firmware
+ * data in hexadecimal or equivalent format, provided this copyright
+ * notice is accompanying it.
*/
#include <linux/config.h>
@@ -61,8 +66,8 @@
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.27"
-#define DRV_MODULE_RELDATE "May 5, 2005"
+#define DRV_MODULE_VERSION "3.32"
+#define DRV_MODULE_RELDATE "June 24, 2005"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -133,6 +138,8 @@
/* number of ETHTOOL_GSTATS u64's */
#define TG3_NUM_STATS (sizeof(struct tg3_ethtool_stats)/sizeof(u64))
+#define TG3_NUM_TEST 6
+
static char version[] __devinitdata =
DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
@@ -206,6 +213,8 @@ static struct pci_device_id tg3_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+ { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752M,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
{ PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M,
@@ -314,15 +323,24 @@ static struct {
{ "nic_tx_threshold_hit" }
};
+static struct {
+ const char string[ETH_GSTRING_LEN];
+} ethtool_test_keys[TG3_NUM_TEST] = {
+ { "nvram test (online) " },
+ { "link test (online) " },
+ { "register test (offline)" },
+ { "memory test (offline)" },
+ { "loopback test (offline)" },
+ { "interrupt test (offline)" },
+};
+
static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val)
{
if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0) {
- unsigned long flags;
-
- spin_lock_irqsave(&tp->indirect_lock, flags);
+ spin_lock_bh(&tp->indirect_lock);
pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
- spin_unlock_irqrestore(&tp->indirect_lock, flags);
+ spin_unlock_bh(&tp->indirect_lock);
} else {
writel(val, tp->regs + off);
if ((tp->tg3_flags & TG3_FLAG_5701_REG_WRITE_BUG) != 0)
@@ -333,12 +351,10 @@ static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val)
static void _tw32_flush(struct tg3 *tp, u32 off, u32 val)
{
if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0) {
- unsigned long flags;
-
- spin_lock_irqsave(&tp->indirect_lock, flags);
+ spin_lock_bh(&tp->indirect_lock);
pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
- spin_unlock_irqrestore(&tp->indirect_lock, flags);
+ spin_unlock_bh(&tp->indirect_lock);
} else {
void __iomem *dest = tp->regs + off;
writel(val, dest);
@@ -378,28 +394,24 @@ static inline void _tw32_tx_mbox(struct tg3 *tp, u32 off, u32 val)
static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val)
{
- unsigned long flags;
-
- spin_lock_irqsave(&tp->indirect_lock, flags);
+ spin_lock_bh(&tp->indirect_lock);
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
/* Always leave this as zero. */
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
- spin_unlock_irqrestore(&tp->indirect_lock, flags);
+ spin_unlock_bh(&tp->indirect_lock);
}
static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
{
- unsigned long flags;
-
- spin_lock_irqsave(&tp->indirect_lock, flags);
+ spin_lock_bh(&tp->indirect_lock);
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
/* Always leave this as zero. */
pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
- spin_unlock_irqrestore(&tp->indirect_lock, flags);
+ spin_unlock_bh(&tp->indirect_lock);
}
static void tg3_disable_ints(struct tg3 *tp)
@@ -418,11 +430,14 @@ static inline void tg3_cond_int(struct tg3 *tp)
static void tg3_enable_ints(struct tg3 *tp)
{
+ tp->irq_sync = 0;
+ wmb();
+
tw32(TG3PCI_MISC_HOST_CTRL,
(tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT));
- tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000000);
+ tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
+ (tp->last_tag << 24));
tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
-
tg3_cond_int(tp);
}
@@ -455,16 +470,23 @@ static void tg3_restart_ints(struct tg3 *tp)
{
tw32(TG3PCI_MISC_HOST_CTRL,
(tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT));
- tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000000);
+ tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
+ tp->last_tag << 24);
mmiowb();
- if (tg3_has_work(tp))
+ /* When doing tagged status, this work check is unnecessary.
+ * The last_tag we write above tells the chip which piece of
+ * work we've completed.
+ */
+ if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) &&
+ tg3_has_work(tp))
tw32(HOSTCC_MODE, tp->coalesce_mode |
(HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW));
}
static inline void tg3_netif_stop(struct tg3 *tp)
{
+ tp->dev->trans_start = jiffies; /* prevent tx timeout */
netif_poll_disable(tp->dev);
netif_tx_disable(tp->dev);
}
@@ -477,7 +499,8 @@ static inline void tg3_netif_start(struct tg3 *tp)
* (such as after tg3_init_hw)
*/
netif_poll_enable(tp->dev);
- tg3_cond_int(tp);
+ tp->hw_status->status |= SD_STATUS_UPDATED;
+ tg3_enable_ints(tp);
}
static void tg3_switch_clocks(struct tg3 *tp)
@@ -2500,7 +2523,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
if (netif_carrier_ok(tp->dev)) {
tw32(HOSTCC_STAT_COAL_TICKS,
- DEFAULT_STAT_COAL_TICKS);
+ tp->coal.stats_block_coalesce_usecs);
} else {
tw32(HOSTCC_STAT_COAL_TICKS, 0);
}
@@ -2551,7 +2574,7 @@ static void tg3_tx(struct tg3 *tp)
sw_idx = NEXT_TX(sw_idx);
}
- dev_kfree_skb_irq(skb);
+ dev_kfree_skb(skb);
}
tp->tx_cons = sw_idx;
@@ -2857,11 +2880,8 @@ static int tg3_poll(struct net_device *netdev, int *budget)
{
struct tg3 *tp = netdev_priv(netdev);
struct tg3_hw_status *sblk = tp->hw_status;
- unsigned long flags;
int done;
- spin_lock_irqsave(&tp->lock, flags);
-
/* handle link change and other phy events */
if (!(tp->tg3_flags &
(TG3_FLAG_USE_LINKCHG_REG |
@@ -2869,7 +2889,9 @@ static int tg3_poll(struct net_device *netdev, int *budget)
if (sblk->status & SD_STATUS_LINK_CHG) {
sblk->status = SD_STATUS_UPDATED |
(sblk->status & ~SD_STATUS_LINK_CHG);
+ spin_lock(&tp->lock);
tg3_setup_phy(tp, 0);
+ spin_unlock(&tp->lock);
}
}
@@ -2880,13 +2902,10 @@ static int tg3_poll(struct net_device *netdev, int *budget)
spin_unlock(&tp->tx_lock);
}
- spin_unlock_irqrestore(&tp->lock, flags);
-
/* run RX thread, within the bounds set by NAPI.
* All RX "locking" is done by ensuring outside
* code synchronizes with dev->poll()
*/
- done = 1;
if (sblk->idx[0].rx_producer != tp->rx_rcb_ptr) {
int orig_budget = *budget;
int work_done;
@@ -2898,22 +2917,59 @@ static int tg3_poll(struct net_device *netdev, int *budget)
*budget -= work_done;
netdev->quota -= work_done;
-
- if (work_done >= orig_budget)
- done = 0;
}
+ if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
+ tp->last_tag = sblk->status_tag;
+ rmb();
+ sblk->status &= ~SD_STATUS_UPDATED;
+
/* if no more work, tell net stack and NIC we're done */
+ done = !tg3_has_work(tp);
if (done) {
- spin_lock_irqsave(&tp->lock, flags);
- __netif_rx_complete(netdev);
+ spin_lock(&tp->lock);
+ netif_rx_complete(netdev);
tg3_restart_ints(tp);
- spin_unlock_irqrestore(&tp->lock, flags);
+ spin_unlock(&tp->lock);
}
return (done ? 0 : 1);
}
+static void tg3_irq_quiesce(struct tg3 *tp)
+{
+ BUG_ON(tp->irq_sync);
+
+ tp->irq_sync = 1;
+ smp_mb();
+
+ synchronize_irq(tp->pdev->irq);
+}
+
+static inline int tg3_irq_sync(struct tg3 *tp)
+{
+ return tp->irq_sync;
+}
+
+/* Fully shutdown all tg3 driver activity elsewhere in the system.
+ * If irq_sync is non-zero, then the IRQ handler must be synchronized
+ * with as well. Most of the time, this is not necessary except when
+ * shutting down the device.
+ */
+static inline void tg3_full_lock(struct tg3 *tp, int irq_sync)
+{
+ if (irq_sync)
+ tg3_irq_quiesce(tp);
+ spin_lock_bh(&tp->lock);
+ spin_lock(&tp->tx_lock);
+}
+
+static inline void tg3_full_unlock(struct tg3 *tp)
+{
+ spin_unlock(&tp->tx_lock);
+ spin_unlock_bh(&tp->lock);
+}
+
/* MSI ISR - No need to check for interrupt sharing and no need to
* flush status block and interrupt mailbox. PCI ordering rules
* guarantee that MSI will arrive after the status block.
@@ -2923,31 +2979,28 @@ static irqreturn_t tg3_msi(int irq, void *dev_id, struct pt_regs *regs)
struct net_device *dev = dev_id;
struct tg3 *tp = netdev_priv(dev);
struct tg3_hw_status *sblk = tp->hw_status;
- unsigned long flags;
-
- spin_lock_irqsave(&tp->lock, flags);
/*
- * writing any value to intr-mbox-0 clears PCI INTA# and
+ * Writing any value to intr-mbox-0 clears PCI INTA# and
* chip-internal interrupt pending events.
- * writing non-zero to intr-mbox-0 additional tells the
+ * Writing non-zero to intr-mbox-0 additional tells the
* NIC to stop sending us irqs, engaging "in-intr-handler"
* event coalescing.
*/
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
+ tp->last_tag = sblk->status_tag;
+ rmb();
+ if (tg3_irq_sync(tp))
+ goto out;
sblk->status &= ~SD_STATUS_UPDATED;
-
if (likely(tg3_has_work(tp)))
netif_rx_schedule(dev); /* schedule NAPI poll */
else {
- /* no work, re-enable interrupts
- */
+ /* No work, re-enable interrupts. */
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
- 0x00000000);
+ tp->last_tag << 24);
}
-
- spin_unlock_irqrestore(&tp->lock, flags);
-
+out:
return IRQ_RETVAL(1);
}
@@ -2956,10 +3009,50 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
struct net_device *dev = dev_id;
struct tg3 *tp = netdev_priv(dev);
struct tg3_hw_status *sblk = tp->hw_status;
- unsigned long flags;
unsigned int handled = 1;
- spin_lock_irqsave(&tp->lock, flags);
+ /* In INTx mode, it is possible for the interrupt to arrive at
+ * the CPU before the status block posted prior to the interrupt.
+ * Reading the PCI State register will confirm whether the
+ * interrupt is ours and will flush the status block.
+ */
+ if ((sblk->status & SD_STATUS_UPDATED) ||
+ !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) {
+ /*
+ * Writing any value to intr-mbox-0 clears PCI INTA# and
+ * chip-internal interrupt pending events.
+ * Writing non-zero to intr-mbox-0 additional tells the
+ * NIC to stop sending us irqs, engaging "in-intr-handler"
+ * event coalescing.
+ */
+ tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
+ 0x00000001);
+ if (tg3_irq_sync(tp))
+ goto out;
+ sblk->status &= ~SD_STATUS_UPDATED;
+ if (likely(tg3_has_work(tp)))
+ netif_rx_schedule(dev); /* schedule NAPI poll */
+ else {
+ /* No work, shared interrupt perhaps? re-enable
+ * interrupts, and flush that PCI write
+ */
+ tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
+ 0x00000000);
+ tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
+ }
+ } else { /* shared interrupt */
+ handled = 0;
+ }
+out:
+ return IRQ_RETVAL(handled);
+}
+
+static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+ struct tg3 *tp = netdev_priv(dev);
+ struct tg3_hw_status *sblk = tp->hw_status;
+ unsigned int handled = 1;
/* In INTx mode, it is possible for the interrupt to arrive at
* the CPU before the status block posted prior to the interrupt.
@@ -2977,13 +3070,11 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
*/
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
0x00000001);
- /*
- * Flush PCI write. This also guarantees that our
- * status block has been flushed to host memory.
- */
- tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
+ tp->last_tag = sblk->status_tag;
+ rmb();
+ if (tg3_irq_sync(tp))
+ goto out;
sblk->status &= ~SD_STATUS_UPDATED;
-
if (likely(tg3_has_work(tp)))
netif_rx_schedule(dev); /* schedule NAPI poll */
else {
@@ -2991,15 +3082,13 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
* interrupts, and flush that PCI write
*/
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
- 0x00000000);
+ tp->last_tag << 24);
tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
}
} else { /* shared interrupt */
handled = 0;
}
-
- spin_unlock_irqrestore(&tp->lock, flags);
-
+out:
return IRQ_RETVAL(handled);
}
@@ -3020,7 +3109,7 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id,
}
static int tg3_init_hw(struct tg3 *);
-static int tg3_halt(struct tg3 *, int);
+static int tg3_halt(struct tg3 *, int, int);
#ifdef CONFIG_NET_POLL_CONTROLLER
static void tg3_poll_controller(struct net_device *dev)
@@ -3038,19 +3127,17 @@ static void tg3_reset_task(void *_data)
tg3_netif_stop(tp);
- spin_lock_irq(&tp->lock);
- spin_lock(&tp->tx_lock);
+ tg3_full_lock(tp, 1);
restart_timer = tp->tg3_flags2 & TG3_FLG2_RESTART_TIMER;
tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER;
- tg3_halt(tp, 0);
+ tg3_halt(tp, RESET_KIND_SHUTDOWN, 0);
tg3_init_hw(tp);
tg3_netif_start(tp);
- spin_unlock(&tp->tx_lock);
- spin_unlock_irq(&tp->lock);
+ tg3_full_unlock(tp);
if (restart_timer)
mod_timer(&tp->timer, jiffies + 1);
@@ -3156,39 +3243,21 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
unsigned int i;
u32 len, entry, base_flags, mss;
int would_hit_hwbug;
- unsigned long flags;
len = skb_headlen(skb);
/* No BH disabling for tx_lock here. We are running in BH disabled
* context and TX reclaim runs via tp->poll inside of a software
- * interrupt. Rejoice!
- *
- * Actually, things are not so simple. If we are to take a hw
- * IRQ here, we can deadlock, consider:
- *
- * CPU1 CPU2
- * tg3_start_xmit
- * take tp->tx_lock
- * tg3_timer
- * take tp->lock
- * tg3_interrupt
- * spin on tp->lock
- * spin on tp->tx_lock
- *
- * So we really do need to disable interrupts when taking
- * tx_lock here.
+ * interrupt. Furthermore, IRQ processing runs lockless so we have
+ * no IRQ context deadlocks to worry about either. Rejoice!
*/
- local_irq_save(flags);
- if (!spin_trylock(&tp->tx_lock)) {
- local_irq_restore(flags);
+ if (!spin_trylock(&tp->tx_lock))
return NETDEV_TX_LOCKED;
- }
/* This is a hard error, log it. */
if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
netif_stop_queue(dev);
- spin_unlock_irqrestore(&tp->tx_lock, flags);
+ spin_unlock(&tp->tx_lock);
printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
dev->name);
return NETDEV_TX_BUSY;
@@ -3353,7 +3422,7 @@ static int tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
out_unlock:
mmiowb();
- spin_unlock_irqrestore(&tp->tx_lock, flags);
+ spin_unlock(&tp->tx_lock);
dev->trans_start = jiffies;
@@ -3387,10 +3456,10 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu)
}
tg3_netif_stop(tp);
- spin_lock_irq(&tp->lock);
- spin_lock(&tp->tx_lock);
- tg3_halt(tp, 1);
+ tg3_full_lock(tp, 1);
+
+ tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
tg3_set_mtu(dev, tp, new_mtu);
@@ -3398,8 +3467,7 @@ static int tg3_change_mtu(struct net_device *dev, int new_mtu)
tg3_netif_start(tp);
- spin_unlock(&tp->tx_lock);
- spin_unlock_irq(&tp->lock);
+ tg3_full_unlock(tp);
return 0;
}
@@ -4081,19 +4149,19 @@ static void tg3_stop_fw(struct tg3 *tp)
}
/* tp->lock is held. */
-static int tg3_halt(struct tg3 *tp, int silent)
+static int tg3_halt(struct tg3 *tp, int kind, int silent)
{
int err;
tg3_stop_fw(tp);
- tg3_write_sig_pre_reset(tp, RESET_KIND_SHUTDOWN);
+ tg3_write_sig_pre_reset(tp, kind);
tg3_abort_hw(tp, silent);
err = tg3_chip_reset(tp);
- tg3_write_sig_legacy(tp, RESET_KIND_SHUTDOWN);
- tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
+ tg3_write_sig_legacy(tp, kind);
+ tg3_write_sig_post_reset(tp, kind);
if (err)
return err;
@@ -4307,7 +4375,12 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_b
*/
tp->tg3_flags |= TG3_FLAG_PCIX_TARGET_HWBUG;
+ /* It is possible that bootcode is still loading at this point.
+ * Get the nvram lock first before halting the cpu.
+ */
+ tg3_nvram_lock(tp);
err = tg3_halt_cpu(tp, cpu_base);
+ tg3_nvram_unlock(tp);
if (err)
goto out;
@@ -5015,9 +5088,9 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p)
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
- spin_lock_irq(&tp->lock);
+ spin_lock_bh(&tp->lock);
__tg3_set_mac_addr(tp);
- spin_unlock_irq(&tp->lock);
+ spin_unlock_bh(&tp->lock);
return 0;
}
@@ -5044,6 +5117,27 @@ static void tg3_set_bdinfo(struct tg3 *tp, u32 bdinfo_addr,
}
static void __tg3_set_rx_mode(struct net_device *);
+static void tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec)
+{
+ tw32(HOSTCC_RXCOL_TICKS, ec->rx_coalesce_usecs);
+ tw32(HOSTCC_TXCOL_TICKS, ec->tx_coalesce_usecs);
+ tw32(HOSTCC_RXMAX_FRAMES, ec->rx_max_coalesced_frames);
+ tw32(HOSTCC_TXMAX_FRAMES, ec->tx_max_coalesced_frames);
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
+ tw32(HOSTCC_RXCOAL_TICK_INT, ec->rx_coalesce_usecs_irq);
+ tw32(HOSTCC_TXCOAL_TICK_INT, ec->tx_coalesce_usecs_irq);
+ }
+ tw32(HOSTCC_RXCOAL_MAXF_INT, ec->rx_max_coalesced_frames_irq);
+ tw32(HOSTCC_TXCOAL_MAXF_INT, ec->tx_max_coalesced_frames_irq);
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
+ u32 val = ec->stats_block_coalesce_usecs;
+
+ if (!netif_carrier_ok(tp->dev))
+ val = 0;
+
+ tw32(HOSTCC_STAT_COAL_TICKS, val);
+ }
+}
/* tp->lock is held. */
static int tg3_reset_hw(struct tg3 *tp)
@@ -5366,16 +5460,7 @@ static int tg3_reset_hw(struct tg3 *tp)
udelay(10);
}
- tw32(HOSTCC_RXCOL_TICKS, 0);
- tw32(HOSTCC_TXCOL_TICKS, LOW_TXCOL_TICKS);
- tw32(HOSTCC_RXMAX_FRAMES, 1);
- tw32(HOSTCC_TXMAX_FRAMES, LOW_RXMAX_FRAMES);
- if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
- tw32(HOSTCC_RXCOAL_TICK_INT, 0);
- tw32(HOSTCC_TXCOAL_TICK_INT, 0);
- }
- tw32(HOSTCC_RXCOAL_MAXF_INT, 1);
- tw32(HOSTCC_TXCOAL_MAXF_INT, 0);
+ tg3_set_coalesce(tp, &tp->coal);
/* set status block DMA address */
tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH,
@@ -5388,8 +5473,6 @@ static int tg3_reset_hw(struct tg3 *tp)
* the tg3_periodic_fetch_stats call there, and
* tg3_get_stats to see how this works for 5705/5750 chips.
*/
- tw32(HOSTCC_STAT_COAL_TICKS,
- DEFAULT_STAT_COAL_TICKS);
tw32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_HIGH,
((u64) tp->stats_mapping >> 32));
tw32(HOSTCC_STATS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
@@ -5445,7 +5528,8 @@ static int tg3_reset_hw(struct tg3 *tp)
udelay(100);
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0);
- tr32(MAILBOX_INTERRUPT_0);
+ tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
+ tp->last_tag = 0;
if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
tw32_f(DMAC_MODE, DMAC_MODE_ENABLE);
@@ -5643,9 +5727,6 @@ static int tg3_reset_hw(struct tg3 *tp)
tg3_write_sig_post_reset(tp, RESET_KIND_INIT);
- if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE)
- tg3_enable_ints(tp);
-
return 0;
}
@@ -5718,36 +5799,35 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp)
static void tg3_timer(unsigned long __opaque)
{
struct tg3 *tp = (struct tg3 *) __opaque;
- unsigned long flags;
- spin_lock_irqsave(&tp->lock, flags);
- spin_lock(&tp->tx_lock);
+ spin_lock(&tp->lock);
- /* All of this garbage is because when using non-tagged
- * IRQ status the mailbox/status_block protocol the chip
- * uses with the cpu is race prone.
- */
- if (tp->hw_status->status & SD_STATUS_UPDATED) {
- tw32(GRC_LOCAL_CTRL,
- tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
- } else {
- tw32(HOSTCC_MODE, tp->coalesce_mode |
- (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW));
- }
+ if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) {
+ /* All of this garbage is because when using non-tagged
+ * IRQ status the mailbox/status_block protocol the chip
+ * uses with the cpu is race prone.
+ */
+ if (tp->hw_status->status & SD_STATUS_UPDATED) {
+ tw32(GRC_LOCAL_CTRL,
+ tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
+ } else {
+ tw32(HOSTCC_MODE, tp->coalesce_mode |
+ (HOSTCC_MODE_ENABLE | HOSTCC_MODE_NOW));
+ }
- if (!(tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
- tp->tg3_flags2 |= TG3_FLG2_RESTART_TIMER;
- spin_unlock(&tp->tx_lock);
- spin_unlock_irqrestore(&tp->lock, flags);
- schedule_work(&tp->reset_task);
- return;
+ if (!(tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
+ tp->tg3_flags2 |= TG3_FLG2_RESTART_TIMER;
+ spin_unlock(&tp->lock);
+ schedule_work(&tp->reset_task);
+ return;
+ }
}
- if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
- tg3_periodic_fetch_stats(tp);
-
/* This part only runs once per second. */
if (!--tp->timer_counter) {
+ if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
+ tg3_periodic_fetch_stats(tp);
+
if (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) {
u32 mac_stat;
int phy_event;
@@ -5805,8 +5885,7 @@ static void tg3_timer(unsigned long __opaque)
tp->asf_counter = tp->asf_multiplier;
}
- spin_unlock(&tp->tx_lock);
- spin_unlock_irqrestore(&tp->lock, flags);
+ spin_unlock(&tp->lock);
tp->timer.expires = jiffies + tp->timer_offset;
add_timer(&tp->timer);
@@ -5818,6 +5897,9 @@ static int tg3_test_interrupt(struct tg3 *tp)
int err, i;
u32 int_mbox = 0;
+ if (!netif_running(dev))
+ return -ENODEV;
+
tg3_disable_ints(tp);
free_irq(tp->pdev->irq, dev);
@@ -5846,9 +5928,13 @@ static int tg3_test_interrupt(struct tg3 *tp)
if (tp->tg3_flags2 & TG3_FLG2_USING_MSI)
err = request_irq(tp->pdev->irq, tg3_msi,
SA_SAMPLE_RANDOM, dev->name, dev);
- else
- err = request_irq(tp->pdev->irq, tg3_interrupt,
+ else {
+ irqreturn_t (*fn)(int, void *, struct pt_regs *)=tg3_interrupt;
+ if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
+ fn = tg3_interrupt_tagged;
+ err = request_irq(tp->pdev->irq, fn,
SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
+ }
if (err)
return err;
@@ -5900,23 +5986,26 @@ static int tg3_test_msi(struct tg3 *tp)
tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI;
- err = request_irq(tp->pdev->irq, tg3_interrupt,
- SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
+ {
+ irqreturn_t (*fn)(int, void *, struct pt_regs *)=tg3_interrupt;
+ if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
+ fn = tg3_interrupt_tagged;
+ err = request_irq(tp->pdev->irq, fn,
+ SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
+ }
if (err)
return err;
/* Need to reset the chip because the MSI cycle may have terminated
* with Master Abort.
*/
- spin_lock_irq(&tp->lock);
- spin_lock(&tp->tx_lock);
+ tg3_full_lock(tp, 1);
- tg3_halt(tp, 1);
+ tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
err = tg3_init_hw(tp);
- spin_unlock(&tp->tx_lock);
- spin_unlock_irq(&tp->lock);
+ tg3_full_unlock(tp);
if (err)
free_irq(tp->pdev->irq, dev);
@@ -5929,14 +6018,12 @@ static int tg3_open(struct net_device *dev)
struct tg3 *tp = netdev_priv(dev);
int err;
- spin_lock_irq(&tp->lock);
- spin_lock(&tp->tx_lock);
+ tg3_full_lock(tp, 0);
tg3_disable_ints(tp);
tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE;
- spin_unlock(&tp->tx_lock);
- spin_unlock_irq(&tp->lock);
+ tg3_full_unlock(tp);
/* The placement of this call is tied
* to the setup and use of Host TX descriptors.
@@ -5948,7 +6035,13 @@ static int tg3_open(struct net_device *dev)
if ((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
(GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_AX) &&
(GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5750_BX)) {
- if (pci_enable_msi(tp->pdev) == 0) {
+ /* All MSI supporting chips should support tagged
+ * status. Assert that this is the case.
+ */
+ if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) {
+ printk(KERN_WARNING PFX "%s: MSI without TAGGED? "
+ "Not using MSI.\n", tp->dev->name);
+ } else if (pci_enable_msi(tp->pdev) == 0) {
u32 msi_mode;
msi_mode = tr32(MSGINT_MODE);
@@ -5959,9 +6052,14 @@ static int tg3_open(struct net_device *dev)
if (tp->tg3_flags2 & TG3_FLG2_USING_MSI)
err = request_irq(tp->pdev->irq, tg3_msi,
SA_SAMPLE_RANDOM, dev->name, dev);
- else
- err = request_irq(tp->pdev->irq, tg3_interrupt,
+ else {
+ irqreturn_t (*fn)(int, void *, struct pt_regs *)=tg3_interrupt;
+ if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
+ fn = tg3_interrupt_tagged;
+
+ err = request_irq(tp->pdev->irq, fn,
SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev);
+ }
if (err) {
if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
@@ -5972,17 +6070,23 @@ static int tg3_open(struct net_device *dev)
return err;
}
- spin_lock_irq(&tp->lock);
- spin_lock(&tp->tx_lock);
+ tg3_full_lock(tp, 0);
err = tg3_init_hw(tp);
if (err) {
- tg3_halt(tp, 1);
+ tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
tg3_free_rings(tp);
} else {
- tp->timer_offset = HZ / 10;
- tp->timer_counter = tp->timer_multiplier = 10;
- tp->asf_counter = tp->asf_multiplier = (10 * 120);
+ if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
+ tp->timer_offset = HZ;
+ else
+ tp->timer_offset = HZ / 10;
+
+ BUG_ON(tp->timer_offset > HZ);
+ tp->timer_counter = tp->timer_multiplier =
+ (HZ / tp->timer_offset);
+ tp->asf_counter = tp->asf_multiplier =
+ ((HZ / tp->timer_offset) * 120);
init_timer(&tp->timer);
tp->timer.expires = jiffies + tp->timer_offset;
@@ -5990,8 +6094,7 @@ static int tg3_open(struct net_device *dev)
tp->timer.function = tg3_timer;
}
- spin_unlock(&tp->tx_lock);
- spin_unlock_irq(&tp->lock);
+ tg3_full_unlock(tp);
if (err) {
free_irq(tp->pdev->irq, dev);
@@ -6005,34 +6108,31 @@ static int tg3_open(struct net_device *dev)
if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
err = tg3_test_msi(tp);
+
if (err) {
- spin_lock_irq(&tp->lock);
- spin_lock(&tp->tx_lock);
+ tg3_full_lock(tp, 0);
if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
pci_disable_msi(tp->pdev);
tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI;
}
- tg3_halt(tp, 1);
+ tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
tg3_free_rings(tp);
tg3_free_consistent(tp);
- spin_unlock(&tp->tx_lock);
- spin_unlock_irq(&tp->lock);
+ tg3_full_unlock(tp);
return err;
}
}
- spin_lock_irq(&tp->lock);
- spin_lock(&tp->tx_lock);
+ tg3_full_lock(tp, 0);
add_timer(&tp->timer);
tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
tg3_enable_ints(tp);
- spin_unlock(&tp->tx_lock);
- spin_unlock_irq(&tp->lock);
+ tg3_full_unlock(tp);
netif_start_queue(dev);
@@ -6278,23 +6378,21 @@ static int tg3_close(struct net_device *dev)
del_timer_sync(&tp->timer);
- spin_lock_irq(&tp->lock);
- spin_lock(&tp->tx_lock);
+ tg3_full_lock(tp, 1);
#if 0
tg3_dump_state(tp);
#endif
tg3_disable_ints(tp);
- tg3_halt(tp, 1);
+ tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
tg3_free_rings(tp);
tp->tg3_flags &=
~(TG3_FLAG_INIT_COMPLETE |
TG3_FLAG_GOT_SERDES_FLOWCTL);
netif_carrier_off(tp->dev);
- spin_unlock(&tp->tx_lock);
- spin_unlock_irq(&tp->lock);
+ tg3_full_unlock(tp);
free_irq(tp->pdev->irq, dev);
if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
@@ -6331,16 +6429,15 @@ static unsigned long calc_crc_errors(struct tg3 *tp)
if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) {
- unsigned long flags;
u32 val;
- spin_lock_irqsave(&tp->lock, flags);
+ spin_lock_bh(&tp->lock);
if (!tg3_readphy(tp, 0x1e, &val)) {
tg3_writephy(tp, 0x1e, val | 0x8000);
tg3_readphy(tp, 0x14, &val);
} else
val = 0;
- spin_unlock_irqrestore(&tp->lock, flags);
+ spin_unlock_bh(&tp->lock);
tp->phy_crc_errors += val;
@@ -6602,11 +6699,9 @@ static void tg3_set_rx_mode(struct net_device *dev)
{
struct tg3 *tp = netdev_priv(dev);
- spin_lock_irq(&tp->lock);
- spin_lock(&tp->tx_lock);
+ tg3_full_lock(tp, 0);
__tg3_set_rx_mode(dev);
- spin_unlock(&tp->tx_lock);
- spin_unlock_irq(&tp->lock);
+ tg3_full_unlock(tp);
}
#define TG3_REGDUMP_LEN (32 * 1024)
@@ -6628,8 +6723,7 @@ static void tg3_get_regs(struct net_device *dev,
memset(p, 0, TG3_REGDUMP_LEN);
- spin_lock_irq(&tp->lock);
- spin_lock(&tp->tx_lock);
+ tg3_full_lock(tp, 0);
#define __GET_REG32(reg) (*(p)++ = tr32(reg))
#define GET_REG32_LOOP(base,len) \
@@ -6679,8 +6773,7 @@ do { p = (u32 *)(orig_p + (reg)); \
#undef GET_REG32_LOOP
#undef GET_REG32_1
- spin_unlock(&tp->tx_lock);
- spin_unlock_irq(&tp->lock);
+ tg3_full_unlock(tp);
}
static int tg3_get_eeprom_len(struct net_device *dev)
@@ -6856,8 +6949,7 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
return -EINVAL;
}
- spin_lock_irq(&tp->lock);
- spin_lock(&tp->tx_lock);
+ tg3_full_lock(tp, 0);
tp->link_config.autoneg = cmd->autoneg;
if (cmd->autoneg == AUTONEG_ENABLE) {
@@ -6873,8 +6965,7 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
if (netif_running(dev))
tg3_setup_phy(tp, 1);
- spin_unlock(&tp->tx_lock);
- spin_unlock_irq(&tp->lock);
+ tg3_full_unlock(tp);
return 0;
}
@@ -6910,12 +7001,12 @@ static int tg3_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
!(tp->tg3_flags & TG3_FLAG_SERDES_WOL_CAP))
return -EINVAL;
- spin_lock_irq(&tp->lock);
+ spin_lock_bh(&tp->lock);
if (wol->wolopts & WAKE_MAGIC)
tp->tg3_flags |= TG3_FLAG_WOL_ENABLE;
else
tp->tg3_flags &= ~TG3_FLAG_WOL_ENABLE;
- spin_unlock_irq(&tp->lock);
+ spin_unlock_bh(&tp->lock);
return 0;
}
@@ -6955,7 +7046,7 @@ static int tg3_nway_reset(struct net_device *dev)
if (!netif_running(dev))
return -EAGAIN;
- spin_lock_irq(&tp->lock);
+ spin_lock_bh(&tp->lock);
r = -EINVAL;
tg3_readphy(tp, MII_BMCR, &bmcr);
if (!tg3_readphy(tp, MII_BMCR, &bmcr) &&
@@ -6963,7 +7054,7 @@ static int tg3_nway_reset(struct net_device *dev)
tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART);
r = 0;
}
- spin_unlock_irq(&tp->lock);
+ spin_unlock_bh(&tp->lock);
return r;
}
@@ -6985,17 +7076,19 @@ static void tg3_get_ringparam(struct net_device *dev, struct ethtool_ringparam *
static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
{
struct tg3 *tp = netdev_priv(dev);
+ int irq_sync = 0;
if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) ||
(ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) ||
(ering->tx_pending > TG3_TX_RING_SIZE - 1))
return -EINVAL;
- if (netif_running(dev))
+ if (netif_running(dev)) {
tg3_netif_stop(tp);
+ irq_sync = 1;
+ }
- spin_lock_irq(&tp->lock);
- spin_lock(&tp->tx_lock);
+ tg3_full_lock(tp, irq_sync);
tp->rx_pending = ering->rx_pending;
@@ -7006,13 +7099,12 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e
tp->tx_pending = ering->tx_pending;
if (netif_running(dev)) {
- tg3_halt(tp, 1);
+ tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
tg3_init_hw(tp);
tg3_netif_start(tp);
}
- spin_unlock(&tp->tx_lock);
- spin_unlock_irq(&tp->lock);
+ tg3_full_unlock(tp);
return 0;
}
@@ -7029,12 +7121,15 @@ static void tg3_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam
static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
{
struct tg3 *tp = netdev_priv(dev);
+ int irq_sync = 0;
- if (netif_running(dev))
+ if (netif_running(dev)) {
tg3_netif_stop(tp);
+ irq_sync = 1;
+ }
+
+ tg3_full_lock(tp, irq_sync);
- spin_lock_irq(&tp->lock);
- spin_lock(&tp->tx_lock);
if (epause->autoneg)
tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
else
@@ -7049,12 +7144,12 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
tp->tg3_flags &= ~TG3_FLAG_TX_PAUSE;
if (netif_running(dev)) {
- tg3_halt(tp, 1);
+ tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
tg3_init_hw(tp);
tg3_netif_start(tp);
}
- spin_unlock(&tp->tx_lock);
- spin_unlock_irq(&tp->lock);
+
+ tg3_full_unlock(tp);
return 0;
}
@@ -7075,12 +7170,12 @@ static int tg3_set_rx_csum(struct net_device *dev, u32 data)
return 0;
}
- spin_lock_irq(&tp->lock);
+ spin_lock_bh(&tp->lock);
if (data)
tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS;
else
tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS;
- spin_unlock_irq(&tp->lock);
+ spin_unlock_bh(&tp->lock);
return 0;
}
@@ -7108,12 +7203,20 @@ static int tg3_get_stats_count (struct net_device *dev)
return TG3_NUM_STATS;
}
+static int tg3_get_test_count (struct net_device *dev)
+{
+ return TG3_NUM_TEST;
+}
+
static void tg3_get_strings (struct net_device *dev, u32 stringset, u8 *buf)
{
switch (stringset) {
case ETH_SS_STATS:
memcpy(buf, &ethtool_stats_keys, sizeof(ethtool_stats_keys));
break;
+ case ETH_SS_TEST:
+ memcpy(buf, &ethtool_test_keys, sizeof(ethtool_test_keys));
+ break;
default:
WARN_ON(1); /* we need a WARN() */
break;
@@ -7127,6 +7230,517 @@ static void tg3_get_ethtool_stats (struct net_device *dev,
memcpy(tmp_stats, tg3_get_estats(tp), sizeof(tp->estats));
}
+#define NVRAM_TEST_SIZE 0x100
+
+static int tg3_test_nvram(struct tg3 *tp)
+{
+ u32 *buf, csum;
+ int i, j, err = 0;
+
+ buf = kmalloc(NVRAM_TEST_SIZE, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
+ for (i = 0, j = 0; i < NVRAM_TEST_SIZE; i += 4, j++) {
+ u32 val;
+
+ if ((err = tg3_nvram_read(tp, i, &val)) != 0)
+ break;
+ buf[j] = cpu_to_le32(val);
+ }
+ if (i < NVRAM_TEST_SIZE)
+ goto out;
+
+ err = -EIO;
+ if (cpu_to_be32(buf[0]) != TG3_EEPROM_MAGIC)
+ goto out;
+
+ /* Bootstrap checksum at offset 0x10 */
+ csum = calc_crc((unsigned char *) buf, 0x10);
+ if(csum != cpu_to_le32(buf[0x10/4]))
+ goto out;
+
+ /* Manufacturing block starts at offset 0x74, checksum at 0xfc */
+ csum = calc_crc((unsigned char *) &buf[0x74/4], 0x88);
+ if (csum != cpu_to_le32(buf[0xfc/4]))
+ goto out;
+
+ err = 0;
+
+out:
+ kfree(buf);
+ return err;
+}
+
+#define TG3_SERDES_TIMEOUT_SEC 2
+#define TG3_COPPER_TIMEOUT_SEC 6
+
+static int tg3_test_link(struct tg3 *tp)
+{
+ int i, max;
+
+ if (!netif_running(tp->dev))
+ return -ENODEV;
+
+ if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
+ max = TG3_SERDES_TIMEOUT_SEC;
+ else
+ max = TG3_COPPER_TIMEOUT_SEC;
+
+ for (i = 0; i < max; i++) {
+ if (netif_carrier_ok(tp->dev))
+ return 0;
+
+ if (msleep_interruptible(1000))
+ break;
+ }
+
+ return -EIO;
+}
+
+/* Only test the commonly used registers */
+static int tg3_test_registers(struct tg3 *tp)
+{
+ int i, is_5705;
+ u32 offset, read_mask, write_mask, val, save_val, read_val;
+ static struct {
+ u16 offset;
+ u16 flags;
+#define TG3_FL_5705 0x1
+#define TG3_FL_NOT_5705 0x2
+#define TG3_FL_NOT_5788 0x4
+ u32 read_mask;
+ u32 write_mask;
+ } reg_tbl[] = {
+ /* MAC Control Registers */
+ { MAC_MODE, TG3_FL_NOT_5705,
+ 0x00000000, 0x00ef6f8c },
+ { MAC_MODE, TG3_FL_5705,
+ 0x00000000, 0x01ef6b8c },
+ { MAC_STATUS, TG3_FL_NOT_5705,
+ 0x03800107, 0x00000000 },
+ { MAC_STATUS, TG3_FL_5705,
+ 0x03800100, 0x00000000 },
+ { MAC_ADDR_0_HIGH, 0x0000,
+ 0x00000000, 0x0000ffff },
+ { MAC_ADDR_0_LOW, 0x0000,
+ 0x00000000, 0xffffffff },
+ { MAC_RX_MTU_SIZE, 0x0000,
+ 0x00000000, 0x0000ffff },
+ { MAC_TX_MODE, 0x0000,
+ 0x00000000, 0x00000070 },
+ { MAC_TX_LENGTHS, 0x0000,
+ 0x00000000, 0x00003fff },
+ { MAC_RX_MODE, TG3_FL_NOT_5705,
+ 0x00000000, 0x000007fc },
+ { MAC_RX_MODE, TG3_FL_5705,
+ 0x00000000, 0x000007dc },
+ { MAC_HASH_REG_0, 0x0000,
+ 0x00000000, 0xffffffff },
+ { MAC_HASH_REG_1, 0x0000,
+ 0x00000000, 0xffffffff },
+ { MAC_HASH_REG_2, 0x0000,
+ 0x00000000, 0xffffffff },
+ { MAC_HASH_REG_3, 0x0000,
+ 0x00000000, 0xffffffff },
+
+ /* Receive Data and Receive BD Initiator Control Registers. */
+ { RCVDBDI_JUMBO_BD+0, TG3_FL_NOT_5705,
+ 0x00000000, 0xffffffff },
+ { RCVDBDI_JUMBO_BD+4, TG3_FL_NOT_5705,
+ 0x00000000, 0xffffffff },
+ { RCVDBDI_JUMBO_BD+8, TG3_FL_NOT_5705,
+ 0x00000000, 0x00000003 },
+ { RCVDBDI_JUMBO_BD+0xc, TG3_FL_NOT_5705,
+ 0x00000000, 0xffffffff },
+ { RCVDBDI_STD_BD+0, 0x0000,
+ 0x00000000, 0xffffffff },
+ { RCVDBDI_STD_BD+4, 0x0000,
+ 0x00000000, 0xffffffff },
+ { RCVDBDI_STD_BD+8, 0x0000,
+ 0x00000000, 0xffff0002 },
+ { RCVDBDI_STD_BD+0xc, 0x0000,
+ 0x00000000, 0xffffffff },
+
+ /* Receive BD Initiator Control Registers. */
+ { RCVBDI_STD_THRESH, TG3_FL_NOT_5705,
+ 0x00000000, 0xffffffff },
+ { RCVBDI_STD_THRESH, TG3_FL_5705,
+ 0x00000000, 0x000003ff },
+ { RCVBDI_JUMBO_THRESH, TG3_FL_NOT_5705,
+ 0x00000000, 0xffffffff },
+
+ /* Host Coalescing Control Registers. */
+ { HOSTCC_MODE, TG3_FL_NOT_5705,
+ 0x00000000, 0x00000004 },
+ { HOSTCC_MODE, TG3_FL_5705,
+ 0x00000000, 0x000000f6 },
+ { HOSTCC_RXCOL_TICKS, TG3_FL_NOT_5705,
+ 0x00000000, 0xffffffff },
+ { HOSTCC_RXCOL_TICKS, TG3_FL_5705,
+ 0x00000000, 0x000003ff },
+ { HOSTCC_TXCOL_TICKS, TG3_FL_NOT_5705,
+ 0x00000000, 0xffffffff },
+ { HOSTCC_TXCOL_TICKS, TG3_FL_5705,
+ 0x00000000, 0x000003ff },
+ { HOSTCC_RXMAX_FRAMES, TG3_FL_NOT_5705,
+ 0x00000000, 0xffffffff },
+ { HOSTCC_RXMAX_FRAMES, TG3_FL_5705 | TG3_FL_NOT_5788,
+ 0x00000000, 0x000000ff },
+ { HOSTCC_TXMAX_FRAMES, TG3_FL_NOT_5705,
+ 0x00000000, 0xffffffff },
+ { HOSTCC_TXMAX_FRAMES, TG3_FL_5705 | TG3_FL_NOT_5788,
+ 0x00000000, 0x000000ff },
+ { HOSTCC_RXCOAL_TICK_INT, TG3_FL_NOT_5705,
+ 0x00000000, 0xffffffff },
+ { HOSTCC_TXCOAL_TICK_INT, TG3_FL_NOT_5705,
+ 0x00000000, 0xffffffff },
+ { HOSTCC_RXCOAL_MAXF_INT, TG3_FL_NOT_5705,
+ 0x00000000, 0xffffffff },
+ { HOSTCC_RXCOAL_MAXF_INT, TG3_FL_5705 | TG3_FL_NOT_5788,
+ 0x00000000, 0x000000ff },
+ { HOSTCC_TXCOAL_MAXF_INT, TG3_FL_NOT_5705,
+ 0x00000000, 0xffffffff },
+ { HOSTCC_TXCOAL_MAXF_INT, TG3_FL_5705 | TG3_FL_NOT_5788,
+ 0x00000000, 0x000000ff },
+ { HOSTCC_STAT_COAL_TICKS, TG3_FL_NOT_5705,
+ 0x00000000, 0xffffffff },
+ { HOSTCC_STATS_BLK_HOST_ADDR, TG3_FL_NOT_5705,
+ 0x00000000, 0xffffffff },
+ { HOSTCC_STATS_BLK_HOST_ADDR+4, TG3_FL_NOT_5705,
+ 0x00000000, 0xffffffff },
+ { HOSTCC_STATUS_BLK_HOST_ADDR, 0x0000,
+ 0x00000000, 0xffffffff },
+ { HOSTCC_STATUS_BLK_HOST_ADDR+4, 0x0000,
+ 0x00000000, 0xffffffff },
+ { HOSTCC_STATS_BLK_NIC_ADDR, 0x0000,
+ 0xffffffff, 0x00000000 },
+ { HOSTCC_STATUS_BLK_NIC_ADDR, 0x0000,
+ 0xffffffff, 0x00000000 },
+
+ /* Buffer Manager Control Registers. */
+ { BUFMGR_MB_POOL_ADDR, 0x0000,
+ 0x00000000, 0x007fff80 },
+ { BUFMGR_MB_POOL_SIZE, 0x0000,
+ 0x00000000, 0x007fffff },
+ { BUFMGR_MB_RDMA_LOW_WATER, 0x0000,
+ 0x00000000, 0x0000003f },
+ { BUFMGR_MB_MACRX_LOW_WATER, 0x0000,
+ 0x00000000, 0x000001ff },
+ { BUFMGR_MB_HIGH_WATER, 0x0000,
+ 0x00000000, 0x000001ff },
+ { BUFMGR_DMA_DESC_POOL_ADDR, TG3_FL_NOT_5705,
+ 0xffffffff, 0x00000000 },
+ { BUFMGR_DMA_DESC_POOL_SIZE, TG3_FL_NOT_5705,
+ 0xffffffff, 0x00000000 },
+
+ /* Mailbox Registers */
+ { GRCMBOX_RCVSTD_PROD_IDX+4, 0x0000,
+ 0x00000000, 0x000001ff },
+ { GRCMBOX_RCVJUMBO_PROD_IDX+4, TG3_FL_NOT_5705,
+ 0x00000000, 0x000001ff },
+ { GRCMBOX_RCVRET_CON_IDX_0+4, 0x0000,
+ 0x00000000, 0x000007ff },
+ { GRCMBOX_SNDHOST_PROD_IDX_0+4, 0x0000,
+ 0x00000000, 0x000001ff },
+
+ { 0xffff, 0x0000, 0x00000000, 0x00000000 },
+ };
+
+ if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
+ is_5705 = 1;
+ else
+ is_5705 = 0;
+
+ for (i = 0; reg_tbl[i].offset != 0xffff; i++) {
+ if (is_5705 && (reg_tbl[i].flags & TG3_FL_NOT_5705))
+ continue;
+
+ if (!is_5705 && (reg_tbl[i].flags & TG3_FL_5705))
+ continue;
+
+ if ((tp->tg3_flags2 & TG3_FLG2_IS_5788) &&
+ (reg_tbl[i].flags & TG3_FL_NOT_5788))
+ continue;
+
+ offset = (u32) reg_tbl[i].offset;
+ read_mask = reg_tbl[i].read_mask;
+ write_mask = reg_tbl[i].write_mask;
+
+ /* Save the original register content */
+ save_val = tr32(offset);
+
+ /* Determine the read-only value. */
+ read_val = save_val & read_mask;
+
+ /* Write zero to the register, then make sure the read-only bits
+ * are not changed and the read/write bits are all zeros.
+ */
+ tw32(offset, 0);
+
+ val = tr32(offset);
+
+ /* Test the read-only and read/write bits. */
+ if (((val & read_mask) != read_val) || (val & write_mask))
+ goto out;
+
+ /* Write ones to all the bits defined by RdMask and WrMask, then
+ * make sure the read-only bits are not changed and the
+ * read/write bits are all ones.
+ */
+ tw32(offset, read_mask | write_mask);
+
+ val = tr32(offset);
+
+ /* Test the read-only bits. */
+ if ((val & read_mask) != read_val)
+ goto out;
+
+ /* Test the read/write bits. */
+ if ((val & write_mask) != write_mask)
+ goto out;
+
+ tw32(offset, save_val);
+ }
+
+ return 0;
+
+out:
+ printk(KERN_ERR PFX "Register test failed at offset %x\n", offset);
+ tw32(offset, save_val);
+ return -EIO;
+}
+
+static int tg3_do_mem_test(struct tg3 *tp, u32 offset, u32 len)
+{
+ static u32 test_pattern[] = { 0x00000000, 0xffffffff, 0xaa55a55a };
+ int i;
+ u32 j;
+
+ for (i = 0; i < sizeof(test_pattern)/sizeof(u32); i++) {
+ for (j = 0; j < len; j += 4) {
+ u32 val;
+
+ tg3_write_mem(tp, offset + j, test_pattern[i]);
+ tg3_read_mem(tp, offset + j, &val);
+ if (val != test_pattern[i])
+ return -EIO;
+ }
+ }
+ return 0;
+}
+
+static int tg3_test_memory(struct tg3 *tp)
+{
+ static struct mem_entry {
+ u32 offset;
+ u32 len;
+ } mem_tbl_570x[] = {
+ { 0x00000000, 0x01000},
+ { 0x00002000, 0x1c000},
+ { 0xffffffff, 0x00000}
+ }, mem_tbl_5705[] = {
+ { 0x00000100, 0x0000c},
+ { 0x00000200, 0x00008},
+ { 0x00000b50, 0x00400},
+ { 0x00004000, 0x00800},
+ { 0x00006000, 0x01000},
+ { 0x00008000, 0x02000},
+ { 0x00010000, 0x0e000},
+ { 0xffffffff, 0x00000}
+ };
+ struct mem_entry *mem_tbl;
+ int err = 0;
+ int i;
+
+ if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
+ mem_tbl = mem_tbl_5705;
+ else
+ mem_tbl = mem_tbl_570x;
+
+ for (i = 0; mem_tbl[i].offset != 0xffffffff; i++) {
+ if ((err = tg3_do_mem_test(tp, mem_tbl[i].offset,
+ mem_tbl[i].len)) != 0)
+ break;
+ }
+
+ return err;
+}
+
+static int tg3_test_loopback(struct tg3 *tp)
+{
+ u32 mac_mode, send_idx, rx_start_idx, rx_idx, tx_idx, opaque_key;
+ u32 desc_idx;
+ struct sk_buff *skb, *rx_skb;
+ u8 *tx_data;
+ dma_addr_t map;
+ int num_pkts, tx_len, rx_len, i, err;
+ struct tg3_rx_buffer_desc *desc;
+
+ if (!netif_running(tp->dev))
+ return -ENODEV;
+
+ err = -EIO;
+
+ tg3_abort_hw(tp, 1);
+
+ tg3_reset_hw(tp);
+
+ mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
+ MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY |
+ MAC_MODE_PORT_MODE_GMII;
+ tw32(MAC_MODE, mac_mode);
+
+ tx_len = 1514;
+ skb = dev_alloc_skb(tx_len);
+ tx_data = skb_put(skb, tx_len);
+ memcpy(tx_data, tp->dev->dev_addr, 6);
+ memset(tx_data + 6, 0x0, 8);
+
+ tw32(MAC_RX_MTU_SIZE, tx_len + 4);
+
+ for (i = 14; i < tx_len; i++)
+ tx_data[i] = (u8) (i & 0xff);
+
+ map = pci_map_single(tp->pdev, skb->data, tx_len, PCI_DMA_TODEVICE);
+
+ tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE |
+ HOSTCC_MODE_NOW);
+
+ udelay(10);
+
+ rx_start_idx = tp->hw_status->idx[0].rx_producer;
+
+ send_idx = 0;
+ num_pkts = 0;
+
+ tg3_set_txd(tp, send_idx, map, tx_len, 0, 1);
+
+ send_idx++;
+ num_pkts++;
+
+ tw32_tx_mbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, send_idx);
+ tr32(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW);
+
+ udelay(10);
+
+ for (i = 0; i < 10; i++) {
+ tw32_f(HOSTCC_MODE, tp->coalesce_mode | HOSTCC_MODE_ENABLE |
+ HOSTCC_MODE_NOW);
+
+ udelay(10);
+
+ tx_idx = tp->hw_status->idx[0].tx_consumer;
+ rx_idx = tp->hw_status->idx[0].rx_producer;
+ if ((tx_idx == send_idx) &&
+ (rx_idx == (rx_start_idx + num_pkts)))
+ break;
+ }
+
+ pci_unmap_single(tp->pdev, map, tx_len, PCI_DMA_TODEVICE);
+ dev_kfree_skb(skb);
+
+ if (tx_idx != send_idx)
+ goto out;
+
+ if (rx_idx != rx_start_idx + num_pkts)
+ goto out;
+
+ desc = &tp->rx_rcb[rx_start_idx];
+ desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK;
+ opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK;
+ if (opaque_key != RXD_OPAQUE_RING_STD)
+ goto out;
+
+ if ((desc->err_vlan & RXD_ERR_MASK) != 0 &&
+ (desc->err_vlan != RXD_ERR_ODD_NIBBLE_RCVD_MII))
+ goto out;
+
+ rx_len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) - 4;
+ if (rx_len != tx_len)
+ goto out;
+
+ rx_skb = tp->rx_std_buffers[desc_idx].skb;
+
+ map = pci_unmap_addr(&tp->rx_std_buffers[desc_idx], mapping);
+ pci_dma_sync_single_for_cpu(tp->pdev, map, rx_len, PCI_DMA_FROMDEVICE);
+
+ for (i = 14; i < tx_len; i++) {
+ if (*(rx_skb->data + i) != (u8) (i & 0xff))
+ goto out;
+ }
+ err = 0;
+
+ /* tg3_free_rings will unmap and free the rx_skb */
+out:
+ return err;
+}
+
+static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
+ u64 *data)
+{
+ struct tg3 *tp = netdev_priv(dev);
+
+ memset(data, 0, sizeof(u64) * TG3_NUM_TEST);
+
+ if (tg3_test_nvram(tp) != 0) {
+ etest->flags |= ETH_TEST_FL_FAILED;
+ data[0] = 1;
+ }
+ if (tg3_test_link(tp) != 0) {
+ etest->flags |= ETH_TEST_FL_FAILED;
+ data[1] = 1;
+ }
+ if (etest->flags & ETH_TEST_FL_OFFLINE) {
+ int irq_sync = 0;
+
+ if (netif_running(dev)) {
+ tg3_netif_stop(tp);
+ irq_sync = 1;
+ }
+
+ tg3_full_lock(tp, irq_sync);
+
+ tg3_halt(tp, RESET_KIND_SUSPEND, 1);
+ tg3_nvram_lock(tp);
+ tg3_halt_cpu(tp, RX_CPU_BASE);
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
+ tg3_halt_cpu(tp, TX_CPU_BASE);
+ tg3_nvram_unlock(tp);
+
+ if (tg3_test_registers(tp) != 0) {
+ etest->flags |= ETH_TEST_FL_FAILED;
+ data[2] = 1;
+ }
+ if (tg3_test_memory(tp) != 0) {
+ etest->flags |= ETH_TEST_FL_FAILED;
+ data[3] = 1;
+ }
+ if (tg3_test_loopback(tp) != 0) {
+ etest->flags |= ETH_TEST_FL_FAILED;
+ data[4] = 1;
+ }
+
+ tg3_full_unlock(tp);
+
+ if (tg3_test_interrupt(tp) != 0) {
+ etest->flags |= ETH_TEST_FL_FAILED;
+ data[5] = 1;
+ }
+
+ tg3_full_lock(tp, 0);
+
+ tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
+ if (netif_running(dev)) {
+ tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
+ tg3_init_hw(tp);
+ tg3_netif_start(tp);
+ }
+
+ tg3_full_unlock(tp);
+ }
+}
+
static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
struct mii_ioctl_data *data = if_mii(ifr);
@@ -7144,9 +7758,9 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
break; /* We have no PHY */
- spin_lock_irq(&tp->lock);
+ spin_lock_bh(&tp->lock);
err = tg3_readphy(tp, data->reg_num & 0x1f, &mii_regval);
- spin_unlock_irq(&tp->lock);
+ spin_unlock_bh(&tp->lock);
data->val_out = mii_regval;
@@ -7160,9 +7774,9 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
if (!capable(CAP_NET_ADMIN))
return -EPERM;
- spin_lock_irq(&tp->lock);
+ spin_lock_bh(&tp->lock);
err = tg3_writephy(tp, data->reg_num & 0x1f, data->val_in);
- spin_unlock_irq(&tp->lock);
+ spin_unlock_bh(&tp->lock);
return err;
@@ -7178,31 +7792,35 @@ static void tg3_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
{
struct tg3 *tp = netdev_priv(dev);
- spin_lock_irq(&tp->lock);
- spin_lock(&tp->tx_lock);
+ tg3_full_lock(tp, 0);
tp->vlgrp = grp;
/* Update RX_MODE_KEEP_VLAN_TAG bit in RX_MODE register. */
__tg3_set_rx_mode(dev);
- spin_unlock(&tp->tx_lock);
- spin_unlock_irq(&tp->lock);
+ tg3_full_unlock(tp);
}
static void tg3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
{
struct tg3 *tp = netdev_priv(dev);
- spin_lock_irq(&tp->lock);
- spin_lock(&tp->tx_lock);
+ tg3_full_lock(tp, 0);
if (tp->vlgrp)
tp->vlgrp->vlan_devices[vid] = NULL;
- spin_unlock(&tp->tx_lock);
- spin_unlock_irq(&tp->lock);
+ tg3_full_unlock(tp);
}
#endif
+static int tg3_get_coalesce(struct net_device *dev, struct ethtool_coalesce *ec)
+{
+ struct tg3 *tp = netdev_priv(dev);
+
+ memcpy(ec, &tp->coal, sizeof(*ec));
+ return 0;
+}
+
static struct ethtool_ops tg3_ethtool_ops = {
.get_settings = tg3_get_settings,
.set_settings = tg3_set_settings,
@@ -7232,9 +7850,12 @@ static struct ethtool_ops tg3_ethtool_ops = {
.get_tso = ethtool_op_get_tso,
.set_tso = tg3_set_tso,
#endif
+ .self_test_count = tg3_get_test_count,
+ .self_test = tg3_self_test,
.get_strings = tg3_get_strings,
.get_stats_count = tg3_get_stats_count,
.get_ethtool_stats = tg3_get_ethtool_stats,
+ .get_coalesce = tg3_get_coalesce,
};
static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
@@ -7914,6 +8535,16 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
case NIC_SRAM_DATA_CFG_LED_MODE_MAC:
tp->led_ctrl = LED_CTRL_MODE_MAC;
+
+ /* Default to PHY_1_MODE if 0 (MAC_MODE) is
+ * read on some older 5700/5701 bootcode.
+ */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
+ ASIC_REV_5700 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) ==
+ ASIC_REV_5701)
+ tp->led_ctrl = LED_CTRL_MODE_PHY_1;
+
break;
case SHASTA_EXT_LED_SHARED:
@@ -8422,15 +9053,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG;
- /* Only 5701 and later support tagged irq status mode.
- * Also, 5788 chips cannot use tagged irq status.
- *
- * However, since we are using NAPI avoid tagged irq status
- * because the interrupt condition is more difficult to
- * fully clear in that mode.
- */
tp->coalesce_mode = 0;
-
if (GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_AX &&
GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_BX)
tp->coalesce_mode |= HOSTCC_MODE_32BYTE;
@@ -8494,6 +9117,18 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
grc_misc_cfg == GRC_MISC_CFG_BOARD_ID_5788M))
tp->tg3_flags2 |= TG3_FLG2_IS_5788;
+ if (!(tp->tg3_flags2 & TG3_FLG2_IS_5788) &&
+ (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700))
+ tp->tg3_flags |= TG3_FLAG_TAGGED_STATUS;
+ if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS) {
+ tp->coalesce_mode |= (HOSTCC_MODE_CLRTICK_RXBD |
+ HOSTCC_MODE_CLRTICK_TXBD);
+
+ tp->misc_host_ctrl |= MISC_HOST_CTRL_TAGGED_STATUS;
+ pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+ tp->misc_host_ctrl);
+ }
+
/* these are limited to 10/100 only */
if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
(grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) ||
@@ -8671,6 +9306,146 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
return 0;
}
+#define BOUNDARY_SINGLE_CACHELINE 1
+#define BOUNDARY_MULTI_CACHELINE 2
+
+static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val)
+{
+ int cacheline_size;
+ u8 byte;
+ int goal;
+
+ pci_read_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE, &byte);
+ if (byte == 0)
+ cacheline_size = 1024;
+ else
+ cacheline_size = (int) byte * 4;
+
+ /* On 5703 and later chips, the boundary bits have no
+ * effect.
+ */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701 &&
+ !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
+ goto out;
+
+#if defined(CONFIG_PPC64) || defined(CONFIG_IA64) || defined(CONFIG_PARISC)
+ goal = BOUNDARY_MULTI_CACHELINE;
+#else
+#if defined(CONFIG_SPARC64) || defined(CONFIG_ALPHA)
+ goal = BOUNDARY_SINGLE_CACHELINE;
+#else
+ goal = 0;
+#endif
+#endif
+
+ if (!goal)
+ goto out;
+
+ /* PCI controllers on most RISC systems tend to disconnect
+ * when a device tries to burst across a cache-line boundary.
+ * Therefore, letting tg3 do so just wastes PCI bandwidth.
+ *
+ * Unfortunately, for PCI-E there are only limited
+ * write-side controls for this, and thus for reads
+ * we will still get the disconnects. We'll also waste
+ * these PCI cycles for both read and write for chips
+ * other than 5700 and 5701 which do not implement the
+ * boundary bits.
+ */
+ if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
+ !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) {
+ switch (cacheline_size) {
+ case 16:
+ case 32:
+ case 64:
+ case 128:
+ if (goal == BOUNDARY_SINGLE_CACHELINE) {
+ val |= (DMA_RWCTRL_READ_BNDRY_128_PCIX |
+ DMA_RWCTRL_WRITE_BNDRY_128_PCIX);
+ } else {
+ val |= (DMA_RWCTRL_READ_BNDRY_384_PCIX |
+ DMA_RWCTRL_WRITE_BNDRY_384_PCIX);
+ }
+ break;
+
+ case 256:
+ val |= (DMA_RWCTRL_READ_BNDRY_256_PCIX |
+ DMA_RWCTRL_WRITE_BNDRY_256_PCIX);
+ break;
+
+ default:
+ val |= (DMA_RWCTRL_READ_BNDRY_384_PCIX |
+ DMA_RWCTRL_WRITE_BNDRY_384_PCIX);
+ break;
+ };
+ } else if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
+ switch (cacheline_size) {
+ case 16:
+ case 32:
+ case 64:
+ if (goal == BOUNDARY_SINGLE_CACHELINE) {
+ val &= ~DMA_RWCTRL_WRITE_BNDRY_DISAB_PCIE;
+ val |= DMA_RWCTRL_WRITE_BNDRY_64_PCIE;
+ break;
+ }
+ /* fallthrough */
+ case 128:
+ default:
+ val &= ~DMA_RWCTRL_WRITE_BNDRY_DISAB_PCIE;
+ val |= DMA_RWCTRL_WRITE_BNDRY_128_PCIE;
+ break;
+ };
+ } else {
+ switch (cacheline_size) {
+ case 16:
+ if (goal == BOUNDARY_SINGLE_CACHELINE) {
+ val |= (DMA_RWCTRL_READ_BNDRY_16 |
+ DMA_RWCTRL_WRITE_BNDRY_16);
+ break;
+ }
+ /* fallthrough */
+ case 32:
+ if (goal == BOUNDARY_SINGLE_CACHELINE) {
+ val |= (DMA_RWCTRL_READ_BNDRY_32 |
+ DMA_RWCTRL_WRITE_BNDRY_32);
+ break;
+ }
+ /* fallthrough */
+ case 64:
+ if (goal == BOUNDARY_SINGLE_CACHELINE) {
+ val |= (DMA_RWCTRL_READ_BNDRY_64 |
+ DMA_RWCTRL_WRITE_BNDRY_64);
+ break;
+ }
+ /* fallthrough */
+ case 128:
+ if (goal == BOUNDARY_SINGLE_CACHELINE) {
+ val |= (DMA_RWCTRL_READ_BNDRY_128 |
+ DMA_RWCTRL_WRITE_BNDRY_128);
+ break;
+ }
+ /* fallthrough */
+ case 256:
+ val |= (DMA_RWCTRL_READ_BNDRY_256 |
+ DMA_RWCTRL_WRITE_BNDRY_256);
+ break;
+ case 512:
+ val |= (DMA_RWCTRL_READ_BNDRY_512 |
+ DMA_RWCTRL_WRITE_BNDRY_512);
+ break;
+ case 1024:
+ default:
+ val |= (DMA_RWCTRL_READ_BNDRY_1024 |
+ DMA_RWCTRL_WRITE_BNDRY_1024);
+ break;
+ };
+ }
+
+out:
+ return val;
+}
+
static int __devinit tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dma, int size, int to_device)
{
struct tg3_internal_buffer_desc test_desc;
@@ -8752,12 +9527,12 @@ static int __devinit tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dm
return ret;
}
-#define TEST_BUFFER_SIZE 0x400
+#define TEST_BUFFER_SIZE 0x2000
static int __devinit tg3_test_dma(struct tg3 *tp)
{
dma_addr_t buf_dma;
- u32 *buf;
+ u32 *buf, saved_dma_rwctrl;
int ret;
buf = pci_alloc_consistent(tp->pdev, TEST_BUFFER_SIZE, &buf_dma);
@@ -8769,46 +9544,7 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
tp->dma_rwctrl = ((0x7 << DMA_RWCTRL_PCI_WRITE_CMD_SHIFT) |
(0x6 << DMA_RWCTRL_PCI_READ_CMD_SHIFT));
-#ifndef CONFIG_X86
- {
- u8 byte;
- int cacheline_size;
- pci_read_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE, &byte);
-
- if (byte == 0)
- cacheline_size = 1024;
- else
- cacheline_size = (int) byte * 4;
-
- switch (cacheline_size) {
- case 16:
- case 32:
- case 64:
- case 128:
- if ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
- !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) {
- tp->dma_rwctrl |=
- DMA_RWCTRL_WRITE_BNDRY_384_PCIX;
- break;
- } else if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
- tp->dma_rwctrl &=
- ~(DMA_RWCTRL_PCI_WRITE_CMD);
- tp->dma_rwctrl |=
- DMA_RWCTRL_WRITE_BNDRY_128_PCIE;
- break;
- }
- /* fallthrough */
- case 256:
- if (!(tp->tg3_flags & TG3_FLAG_PCIX_MODE) &&
- !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
- tp->dma_rwctrl |=
- DMA_RWCTRL_WRITE_BNDRY_256;
- else if (!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
- tp->dma_rwctrl |=
- DMA_RWCTRL_WRITE_BNDRY_256_PCIX;
- };
- }
-#endif
+ tp->dma_rwctrl = tg3_calc_dma_bndry(tp, tp->dma_rwctrl);
if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
/* DMA read watermark not used on PCIE */
@@ -8827,7 +9563,7 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
if (ccval == 0x6 || ccval == 0x7)
tp->dma_rwctrl |= DMA_RWCTRL_ONE_DMA;
- /* Set bit 23 to renable PCIX hw bug fix */
+ /* Set bit 23 to enable PCIX hw bug fix */
tp->dma_rwctrl |= 0x009f0000;
} else {
tp->dma_rwctrl |= 0x001b000f;
@@ -8868,6 +9604,13 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701)
goto out;
+ /* It is best to perform DMA test with maximum write burst size
+ * to expose the 5700/5701 write DMA bug.
+ */
+ saved_dma_rwctrl = tp->dma_rwctrl;
+ tp->dma_rwctrl &= ~DMA_RWCTRL_WRITE_BNDRY_MASK;
+ tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
+
while (1) {
u32 *p = buf, i;
@@ -8906,8 +9649,9 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
if (p[i] == i)
continue;
- if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) ==
- DMA_RWCTRL_WRITE_BNDRY_DISAB) {
+ if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) !=
+ DMA_RWCTRL_WRITE_BNDRY_16) {
+ tp->dma_rwctrl &= ~DMA_RWCTRL_WRITE_BNDRY_MASK;
tp->dma_rwctrl |= DMA_RWCTRL_WRITE_BNDRY_16;
tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
break;
@@ -8924,6 +9668,28 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
break;
}
}
+ if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) !=
+ DMA_RWCTRL_WRITE_BNDRY_16) {
+ static struct pci_device_id dma_wait_state_chipsets[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_APPLE,
+ PCI_DEVICE_ID_APPLE_UNI_N_PCI15) },
+ { },
+ };
+
+ /* DMA test passed without adjusting DMA boundary,
+ * now look for chipsets that are known to expose the
+ * DMA bug without failing the test.
+ */
+ if (pci_dev_present(dma_wait_state_chipsets)) {
+ tp->dma_rwctrl &= ~DMA_RWCTRL_WRITE_BNDRY_MASK;
+ tp->dma_rwctrl |= DMA_RWCTRL_WRITE_BNDRY_16;
+ }
+ else
+ /* Safe to use the calculated DMA boundary. */
+ tp->dma_rwctrl = saved_dma_rwctrl;
+
+ tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
+ }
out:
pci_free_consistent(tp->pdev, TEST_BUFFER_SIZE, buf, buf_dma);
@@ -9011,6 +9777,31 @@ static struct pci_dev * __devinit tg3_find_5704_peer(struct tg3 *tp)
return peer;
}
+static void __devinit tg3_init_coal(struct tg3 *tp)
+{
+ struct ethtool_coalesce *ec = &tp->coal;
+
+ memset(ec, 0, sizeof(*ec));
+ ec->cmd = ETHTOOL_GCOALESCE;
+ ec->rx_coalesce_usecs = LOW_RXCOL_TICKS;
+ ec->tx_coalesce_usecs = LOW_TXCOL_TICKS;
+ ec->rx_max_coalesced_frames = LOW_RXMAX_FRAMES;
+ ec->tx_max_coalesced_frames = LOW_TXMAX_FRAMES;
+ ec->rx_coalesce_usecs_irq = DEFAULT_RXCOAL_TICK_INT;
+ ec->tx_coalesce_usecs_irq = DEFAULT_TXCOAL_TICK_INT;
+ ec->rx_max_coalesced_frames_irq = DEFAULT_RXCOAL_MAXF_INT;
+ ec->tx_max_coalesced_frames_irq = DEFAULT_TXCOAL_MAXF_INT;
+ ec->stats_block_coalesce_usecs = DEFAULT_STAT_COAL_TICKS;
+
+ if (tp->coalesce_mode & (HOSTCC_MODE_CLRTICK_RXBD |
+ HOSTCC_MODE_CLRTICK_TXBD)) {
+ ec->rx_coalesce_usecs = LOW_RXCOL_TICKS_CLRTCKS;
+ ec->rx_coalesce_usecs_irq = DEFAULT_RXCOAL_TICK_INT_CLRTCKS;
+ ec->tx_coalesce_usecs = LOW_TXCOL_TICKS_CLRTCKS;
+ ec->tx_coalesce_usecs_irq = DEFAULT_TXCOAL_TICK_INT_CLRTCKS;
+ }
+}
+
static int __devinit tg3_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -9232,7 +10023,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
(tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
pci_save_state(tp->pdev);
tw32(MEMARB_MODE, MEMARB_MODE_ENABLE);
- tg3_halt(tp, 1);
+ tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
}
err = tg3_test_dma(tp);
@@ -9256,6 +10047,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
/* flow control autonegotiation is default behavior */
tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
+ tg3_init_coal(tp);
+
err = register_netdev(dev);
if (err) {
printk(KERN_ERR PFX "Cannot register net device, "
@@ -9298,6 +10091,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
(tp->tg3_flags & TG3_FLAG_SPLIT_MODE) != 0,
(tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0,
(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0);
+ printk(KERN_INFO "%s: dma_rwctrl[%08x]\n",
+ dev->name, tp->dma_rwctrl);
return 0;
@@ -9345,24 +10140,19 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state)
del_timer_sync(&tp->timer);
- spin_lock_irq(&tp->lock);
- spin_lock(&tp->tx_lock);
+ tg3_full_lock(tp, 1);
tg3_disable_ints(tp);
- spin_unlock(&tp->tx_lock);
- spin_unlock_irq(&tp->lock);
+ tg3_full_unlock(tp);
netif_device_detach(dev);
- spin_lock_irq(&tp->lock);
- spin_lock(&tp->tx_lock);
- tg3_halt(tp, 1);
- spin_unlock(&tp->tx_lock);
- spin_unlock_irq(&tp->lock);
+ tg3_full_lock(tp, 0);
+ tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
+ tg3_full_unlock(tp);
err = tg3_set_power_state(tp, pci_choose_state(pdev, state));
if (err) {
- spin_lock_irq(&tp->lock);
- spin_lock(&tp->tx_lock);
+ tg3_full_lock(tp, 0);
tg3_init_hw(tp);
@@ -9372,8 +10162,7 @@ static int tg3_suspend(struct pci_dev *pdev, pm_message_t state)
netif_device_attach(dev);
tg3_netif_start(tp);
- spin_unlock(&tp->tx_lock);
- spin_unlock_irq(&tp->lock);
+ tg3_full_unlock(tp);
}
return err;
@@ -9396,20 +10185,16 @@ static int tg3_resume(struct pci_dev *pdev)
netif_device_attach(dev);
- spin_lock_irq(&tp->lock);
- spin_lock(&tp->tx_lock);
+ tg3_full_lock(tp, 0);
tg3_init_hw(tp);
tp->timer.expires = jiffies + tp->timer_offset;
add_timer(&tp->timer);
- tg3_enable_ints(tp);
-
tg3_netif_start(tp);
- spin_unlock(&tp->tx_lock);
- spin_unlock_irq(&tp->lock);
+ tg3_full_unlock(tp);
return 0;
}
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 8de6f21037b..99c5f9675a5 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -876,10 +876,12 @@
#define HOSTCC_STATUS_ERROR_ATTN 0x00000004
#define HOSTCC_RXCOL_TICKS 0x00003c08
#define LOW_RXCOL_TICKS 0x00000032
+#define LOW_RXCOL_TICKS_CLRTCKS 0x00000014
#define DEFAULT_RXCOL_TICKS 0x00000048
#define HIGH_RXCOL_TICKS 0x00000096
#define HOSTCC_TXCOL_TICKS 0x00003c0c
#define LOW_TXCOL_TICKS 0x00000096
+#define LOW_TXCOL_TICKS_CLRTCKS 0x00000048
#define DEFAULT_TXCOL_TICKS 0x0000012c
#define HIGH_TXCOL_TICKS 0x00000145
#define HOSTCC_RXMAX_FRAMES 0x00003c10
@@ -892,8 +894,10 @@
#define HIGH_TXMAX_FRAMES 0x00000052
#define HOSTCC_RXCOAL_TICK_INT 0x00003c18
#define DEFAULT_RXCOAL_TICK_INT 0x00000019
+#define DEFAULT_RXCOAL_TICK_INT_CLRTCKS 0x00000014
#define HOSTCC_TXCOAL_TICK_INT 0x00003c1c
#define DEFAULT_TXCOAL_TICK_INT 0x00000019
+#define DEFAULT_TXCOAL_TICK_INT_CLRTCKS 0x00000014
#define HOSTCC_RXCOAL_MAXF_INT 0x00003c20
#define DEFAULT_RXCOAL_MAXF_INT 0x00000005
#define HOSTCC_TXCOAL_MAXF_INT 0x00003c24
@@ -2002,17 +2006,31 @@ struct tg3_ethtool_stats {
struct tg3 {
/* begin "general, frequently-used members" cacheline section */
+ /* If the IRQ handler (which runs lockless) needs to be
+ * quiesced, the following bitmask state is used. The
+ * SYNC flag is set by non-IRQ context code to initiate
+ * the quiescence.
+ *
+ * When the IRQ handler notices that SYNC is set, it
+ * disables interrupts and returns.
+ *
+ * When all outstanding IRQ handlers have returned after
+ * the SYNC flag has been set, the setter can be assured
+ * that interrupts will no longer get run.
+ *
+ * In this way all SMP driver locks are never acquired
+ * in hw IRQ context, only sw IRQ context or lower.
+ */
+ unsigned int irq_sync;
+
/* SMP locking strategy:
*
* lock: Held during all operations except TX packet
* processing.
*
- * tx_lock: Held during tg3_start_xmit{,_4gbug} and tg3_tx
+ * tx_lock: Held during tg3_start_xmit and tg3_tx
*
- * If you want to shut up all asynchronous processing you must
- * acquire both locks, 'lock' taken before 'tx_lock'. IRQs must
- * be disabled to take 'lock' but only softirq disabling is
- * necessary for acquisition of 'tx_lock'.
+ * Both of these locks are to be held with BH safety.
*/
spinlock_t lock;
spinlock_t indirect_lock;
@@ -2023,6 +2041,7 @@ struct tg3 {
struct tg3_hw_status *hw_status;
dma_addr_t status_mapping;
+ u32 last_tag;
u32 msg_enable;
@@ -2068,6 +2087,7 @@ struct tg3 {
u32 rx_offset;
u32 tg3_flags;
+#define TG3_FLAG_TAGGED_STATUS 0x00000001
#define TG3_FLAG_TXD_MBOX_HWBUG 0x00000002
#define TG3_FLAG_RX_CHECKSUMS 0x00000004
#define TG3_FLAG_USE_LINKCHG_REG 0x00000008
@@ -2225,7 +2245,7 @@ struct tg3 {
#define SST_25VF0X0_PAGE_SIZE 4098
-
+ struct ethtool_coalesce coal;
};
#endif /* !(_T3_H) */
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index a7ffa64502d..cf31c062985 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -193,6 +193,12 @@ static int aui[MAX_TLAN_BOARDS];
static int duplex[MAX_TLAN_BOARDS];
static int speed[MAX_TLAN_BOARDS];
static int boards_found;
+module_param_array(aui, int, NULL, 0);
+module_param_array(duplex, int, NULL, 0);
+module_param_array(speed, int, NULL, 0);
+MODULE_PARM_DESC(aui, "ThunderLAN use AUI port(s) (0-1)");
+MODULE_PARM_DESC(duplex, "ThunderLAN duplex setting(s) (0-default, 1-half, 2-full)");
+MODULE_PARM_DESC(speed, "ThunderLAN port speen setting(s) (0,10,100)");
MODULE_AUTHOR("Maintainer: Samuel Chessman <chessman@tux.org>");
MODULE_DESCRIPTION("Driver for TI ThunderLAN based ethernet PCI adapters");
@@ -204,8 +210,13 @@ MODULE_LICENSE("GPL");
/* Turn on debugging. See Documentation/networking/tlan.txt for details */
static int debug;
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "ThunderLAN debug mask");
static int bbuf;
+module_param(bbuf, int, 0);
+MODULE_PARM_DESC(bbuf, "ThunderLAN use big buffer (0-1)");
+
static u8 *TLanPadBuffer;
static dma_addr_t TLanPadBufferDMA;
static char TLanSignature[] = "TLAN";
@@ -2381,6 +2392,7 @@ TLan_FinishReset( struct net_device *dev )
TLan_SetTimer( dev, (10*HZ), TLAN_TIMER_FINISH_RESET );
return;
}
+ TLan_SetMulticastList(dev);
} /* TLan_FinishReset */
@@ -2807,7 +2819,7 @@ void TLan_PhyMonitor( struct net_device *dev )
if (priv->link) {
priv->link = 0;
printk(KERN_DEBUG "TLAN: %s has lost link\n", dev->name);
- dev->flags &= ~IFF_RUNNING;
+ netif_carrier_off(dev);
TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_LINK_BEAT );
return;
}
@@ -2817,7 +2829,7 @@ void TLan_PhyMonitor( struct net_device *dev )
if ((phy_status & MII_GS_LINK) && !priv->link) {
priv->link = 1;
printk(KERN_DEBUG "TLAN: %s has reestablished link\n", dev->name);
- dev->flags |= IFF_RUNNING;
+ netif_carrier_on(dev);
}
/* Setup a new monitor */
diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
index c098863bdd9..3873917a9c2 100644
--- a/drivers/net/tokenring/ibmtr.c
+++ b/drivers/net/tokenring/ibmtr.c
@@ -888,11 +888,6 @@ static int tok_open(struct net_device *dev)
ti->sap_status = CLOSED; /* CLOSED or OPEN */
ti->open_failure = NO; /* NO or YES */
ti->open_mode = MANUAL; /* MANUAL or AUTOMATIC */
- /* 12/2000 not typical Linux, but we can use RUNNING to let us know when
- the network has crapped out or cables are disconnected. Useful because
- the IFF_UP flag stays up the whole time, until ifconfig tr0 down.
- */
- dev->flags &= ~IFF_RUNNING;
ti->sram_phys &= ~1; /* to reverse what we do in tok_close */
/* init the spinlock */
@@ -1242,7 +1237,7 @@ irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs)
ti->open_status = CLOSED;
ti->sap_status = CLOSED;
ti->open_mode = AUTOMATIC;
- dev->flags &= ~IFF_RUNNING;
+ netif_carrier_off(dev);
netif_stop_queue(dev);
ti->open_action = RESTART;
outb(0, dev->base_addr + ADAPTRESET);
@@ -1323,7 +1318,7 @@ irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs)
break;
}
netif_wake_queue(dev);
- dev->flags |= IFF_RUNNING;/*BMS 12/2000*/
+ netif_carrier_on(dev);
break;
case DIR_INTERRUPT:
case DIR_MOD_OPEN_PARAMS:
@@ -1427,7 +1422,7 @@ irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs)
ring_status);
if(ring_status& (REMOVE_RECV|AUTO_REMOVAL|LOBE_FAULT)){
netif_stop_queue(dev);
- dev->flags &= ~IFF_RUNNING;/*not typical Linux*/
+ netif_carrier_off(dev);
DPRINTK("Remove received, or Auto-removal error"
", or Lobe fault\n");
DPRINTK("We'll try to reopen the closed adapter"
diff --git a/drivers/net/tulip/media.c b/drivers/net/tulip/media.c
index edae09a4b02..919c40cd635 100644
--- a/drivers/net/tulip/media.c
+++ b/drivers/net/tulip/media.c
@@ -174,6 +174,7 @@ void tulip_mdio_write(struct net_device *dev, int phy_id, int location, int val)
break;
}
spin_unlock_irqrestore(&tp->mii_lock, flags);
+ return;
}
/* Establish sync by sending 32 logic ones. */
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index d098b3ba353..e0ae3ed6e57 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -1104,7 +1104,7 @@ static void set_rx_mode(struct net_device *dev)
if (entry != 0) {
/* Avoid a chip errata by prefixing a dummy entry. Don't do
this on the ULI526X as it triggers a different problem */
- if (!(tp->chip_id == ULI526X && (tp->revision = 0x40 || tp->revision == 0x50))) {
+ if (!(tp->chip_id == ULI526X && (tp->revision == 0x40 || tp->revision == 0x50))) {
tp->tx_buffers[entry].skb = NULL;
tp->tx_buffers[entry].mapping = 0;
tp->tx_ring[entry].length =
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index 66b94668ddd..18c27e1e788 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -435,7 +435,7 @@ config VENDOR_SANGOMA
the driver to support.
If you have one or more of these cards, say M to this option;
- and read <file:Documentation/networking/wanpipe.txt>.
+ and read <file:Documentation/networking/wan-router.txt>.
To compile this driver as a module, choose M here: the
module will be called wanpipe.
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index 921a573372e..7ff814fd65d 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -235,7 +235,7 @@ static int dma[MAX_CARDS+1];
static int irq[MAX_CARDS+1] = { -1, -1, -1, -1, -1, -1, 0, };
/* for class stuff*/
-static struct class_simple *cosa_class;
+static struct class *cosa_class;
#ifdef MODULE
module_param_array(io, int, NULL, 0);
@@ -394,19 +394,19 @@ static int __init cosa_init(void)
goto out;
}
devfs_mk_dir("cosa");
- cosa_class = class_simple_create(THIS_MODULE, "cosa");
+ cosa_class = class_create(THIS_MODULE, "cosa");
if (IS_ERR(cosa_class)) {
err = PTR_ERR(cosa_class);
goto out_chrdev;
}
for (i=0; i<nr_cards; i++) {
- class_simple_device_add(cosa_class, MKDEV(cosa_major, i),
+ class_device_create(cosa_class, MKDEV(cosa_major, i),
NULL, "cosa%d", i);
err = devfs_mk_cdev(MKDEV(cosa_major, i),
S_IFCHR|S_IRUSR|S_IWUSR,
"cosa/%d", i);
if (err) {
- class_simple_device_remove(MKDEV(cosa_major, i));
+ class_device_destroy(cosa_class, MKDEV(cosa_major, i));
goto out_chrdev;
}
}
@@ -427,10 +427,10 @@ static void __exit cosa_exit(void)
printk(KERN_INFO "Unloading the cosa module\n");
for (i=0; i<nr_cards; i++) {
- class_simple_device_remove(MKDEV(cosa_major, i));
+ class_device_destroy(cosa_class, MKDEV(cosa_major, i));
devfs_remove("cosa/%d", i);
}
- class_simple_destroy(cosa_class);
+ class_destroy(cosa_class);
devfs_remove("cosa");
for (cosa=cosa_cards; nr_cards--; cosa++) {
/* Clean up the per-channel data */
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
index 7f450b51a6c..a5d6891c9d4 100644
--- a/drivers/net/wan/hdlc_fr.c
+++ b/drivers/net/wan/hdlc_fr.c
@@ -2,7 +2,7 @@
* Generic HDLC support routines for Linux
* Frame Relay support
*
- * Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 1999 - 2005 Krzysztof Halasa <khc@pm.waw.pl>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
@@ -27,6 +27,10 @@
active = open and "link reliable"
exist = new = not used
+ CCITT LMI: ITU-T Q.933 Annex A
+ ANSI LMI: ANSI T1.617 Annex D
+ CISCO LMI: the original, aka "Gang of Four" LMI
+
*/
#include <linux/module.h>
@@ -49,45 +53,41 @@
#undef DEBUG_ECN
#undef DEBUG_LINK
-#define MAXLEN_LMISTAT 20 /* max size of status enquiry frame */
-
-#define PVC_STATE_NEW 0x01
-#define PVC_STATE_ACTIVE 0x02
-#define PVC_STATE_FECN 0x08 /* FECN condition */
-#define PVC_STATE_BECN 0x10 /* BECN condition */
-
-
-#define FR_UI 0x03
-#define FR_PAD 0x00
-
-#define NLPID_IP 0xCC
-#define NLPID_IPV6 0x8E
-#define NLPID_SNAP 0x80
-#define NLPID_PAD 0x00
-#define NLPID_Q933 0x08
-
-
-#define LMI_DLCI 0 /* LMI DLCI */
-#define LMI_PROTO 0x08
-#define LMI_CALLREF 0x00 /* Call Reference */
-#define LMI_ANSI_LOCKSHIFT 0x95 /* ANSI lockshift */
-#define LMI_REPTYPE 1 /* report type */
-#define LMI_CCITT_REPTYPE 0x51
-#define LMI_ALIVE 3 /* keep alive */
-#define LMI_CCITT_ALIVE 0x53
-#define LMI_PVCSTAT 7 /* pvc status */
-#define LMI_CCITT_PVCSTAT 0x57
-#define LMI_FULLREP 0 /* full report */
-#define LMI_INTEGRITY 1 /* link integrity report */
-#define LMI_SINGLE 2 /* single pvc report */
+#define FR_UI 0x03
+#define FR_PAD 0x00
+
+#define NLPID_IP 0xCC
+#define NLPID_IPV6 0x8E
+#define NLPID_SNAP 0x80
+#define NLPID_PAD 0x00
+#define NLPID_CCITT_ANSI_LMI 0x08
+#define NLPID_CISCO_LMI 0x09
+
+
+#define LMI_CCITT_ANSI_DLCI 0 /* LMI DLCI */
+#define LMI_CISCO_DLCI 1023
+
+#define LMI_CALLREF 0x00 /* Call Reference */
+#define LMI_ANSI_LOCKSHIFT 0x95 /* ANSI locking shift */
+#define LMI_ANSI_CISCO_REPTYPE 0x01 /* report type */
+#define LMI_CCITT_REPTYPE 0x51
+#define LMI_ANSI_CISCO_ALIVE 0x03 /* keep alive */
+#define LMI_CCITT_ALIVE 0x53
+#define LMI_ANSI_CISCO_PVCSTAT 0x07 /* PVC status */
+#define LMI_CCITT_PVCSTAT 0x57
+
+#define LMI_FULLREP 0x00 /* full report */
+#define LMI_INTEGRITY 0x01 /* link integrity report */
+#define LMI_SINGLE 0x02 /* single PVC report */
+
#define LMI_STATUS_ENQUIRY 0x75
#define LMI_STATUS 0x7D /* reply */
#define LMI_REPT_LEN 1 /* report type element length */
#define LMI_INTEG_LEN 2 /* link integrity element length */
-#define LMI_LENGTH 13 /* standard LMI frame length */
-#define LMI_ANSI_LENGTH 14
+#define LMI_CCITT_CISCO_LENGTH 13 /* LMI frame lengths */
+#define LMI_ANSI_LENGTH 14
typedef struct {
@@ -223,51 +223,34 @@ static inline struct net_device** get_dev_p(pvc_device *pvc, int type)
}
-static inline u16 status_to_dlci(u8 *status, int *active, int *new)
-{
- *new = (status[2] & 0x08) ? 1 : 0;
- *active = (status[2] & 0x02) ? 1 : 0;
-
- return ((status[0] & 0x3F) << 4) | ((status[1] & 0x78) >> 3);
-}
-
-
-static inline void dlci_to_status(u16 dlci, u8 *status, int active, int new)
-{
- status[0] = (dlci >> 4) & 0x3F;
- status[1] = ((dlci << 3) & 0x78) | 0x80;
- status[2] = 0x80;
-
- if (new)
- status[2] |= 0x08;
- else if (active)
- status[2] |= 0x02;
-}
-
-
-
static int fr_hard_header(struct sk_buff **skb_p, u16 dlci)
{
u16 head_len;
struct sk_buff *skb = *skb_p;
switch (skb->protocol) {
- case __constant_ntohs(ETH_P_IP):
+ case __constant_ntohs(NLPID_CCITT_ANSI_LMI):
head_len = 4;
skb_push(skb, head_len);
- skb->data[3] = NLPID_IP;
+ skb->data[3] = NLPID_CCITT_ANSI_LMI;
break;
- case __constant_ntohs(ETH_P_IPV6):
+ case __constant_ntohs(NLPID_CISCO_LMI):
head_len = 4;
skb_push(skb, head_len);
- skb->data[3] = NLPID_IPV6;
+ skb->data[3] = NLPID_CISCO_LMI;
break;
- case __constant_ntohs(LMI_PROTO):
+ case __constant_ntohs(ETH_P_IP):
+ head_len = 4;
+ skb_push(skb, head_len);
+ skb->data[3] = NLPID_IP;
+ break;
+
+ case __constant_ntohs(ETH_P_IPV6):
head_len = 4;
skb_push(skb, head_len);
- skb->data[3] = LMI_PROTO;
+ skb->data[3] = NLPID_IPV6;
break;
case __constant_ntohs(ETH_P_802_3):
@@ -461,13 +444,14 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
hdlc_device *hdlc = dev_to_hdlc(dev);
struct sk_buff *skb;
pvc_device *pvc = hdlc->state.fr.first_pvc;
- int len = (hdlc->state.fr.settings.lmi == LMI_ANSI) ? LMI_ANSI_LENGTH
- : LMI_LENGTH;
- int stat_len = 3;
+ int lmi = hdlc->state.fr.settings.lmi;
+ int dce = hdlc->state.fr.settings.dce;
+ int len = lmi == LMI_ANSI ? LMI_ANSI_LENGTH : LMI_CCITT_CISCO_LENGTH;
+ int stat_len = (lmi == LMI_CISCO) ? 6 : 3;
u8 *data;
int i = 0;
- if (hdlc->state.fr.settings.dce && fullrep) {
+ if (dce && fullrep) {
len += hdlc->state.fr.dce_pvc_count * (2 + stat_len);
if (len > HDLC_MAX_MRU) {
printk(KERN_WARNING "%s: Too many PVCs while sending "
@@ -484,29 +468,31 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
}
memset(skb->data, 0, len);
skb_reserve(skb, 4);
- skb->protocol = __constant_htons(LMI_PROTO);
- fr_hard_header(&skb, LMI_DLCI);
+ if (lmi == LMI_CISCO) {
+ skb->protocol = __constant_htons(NLPID_CISCO_LMI);
+ fr_hard_header(&skb, LMI_CISCO_DLCI);
+ } else {
+ skb->protocol = __constant_htons(NLPID_CCITT_ANSI_LMI);
+ fr_hard_header(&skb, LMI_CCITT_ANSI_DLCI);
+ }
data = skb->tail;
data[i++] = LMI_CALLREF;
- data[i++] = hdlc->state.fr.settings.dce
- ? LMI_STATUS : LMI_STATUS_ENQUIRY;
- if (hdlc->state.fr.settings.lmi == LMI_ANSI)
+ data[i++] = dce ? LMI_STATUS : LMI_STATUS_ENQUIRY;
+ if (lmi == LMI_ANSI)
data[i++] = LMI_ANSI_LOCKSHIFT;
- data[i++] = (hdlc->state.fr.settings.lmi == LMI_CCITT)
- ? LMI_CCITT_REPTYPE : LMI_REPTYPE;
+ data[i++] = lmi == LMI_CCITT ? LMI_CCITT_REPTYPE :
+ LMI_ANSI_CISCO_REPTYPE;
data[i++] = LMI_REPT_LEN;
data[i++] = fullrep ? LMI_FULLREP : LMI_INTEGRITY;
-
- data[i++] = (hdlc->state.fr.settings.lmi == LMI_CCITT)
- ? LMI_CCITT_ALIVE : LMI_ALIVE;
+ data[i++] = lmi == LMI_CCITT ? LMI_CCITT_ALIVE : LMI_ANSI_CISCO_ALIVE;
data[i++] = LMI_INTEG_LEN;
data[i++] = hdlc->state.fr.txseq =fr_lmi_nextseq(hdlc->state.fr.txseq);
data[i++] = hdlc->state.fr.rxseq;
- if (hdlc->state.fr.settings.dce && fullrep) {
+ if (dce && fullrep) {
while (pvc) {
- data[i++] = (hdlc->state.fr.settings.lmi == LMI_CCITT)
- ? LMI_CCITT_PVCSTAT : LMI_PVCSTAT;
+ data[i++] = lmi == LMI_CCITT ? LMI_CCITT_PVCSTAT :
+ LMI_ANSI_CISCO_PVCSTAT;
data[i++] = stat_len;
/* LMI start/restart */
@@ -523,8 +509,20 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
fr_log_dlci_active(pvc);
}
- dlci_to_status(pvc->dlci, data + i,
- pvc->state.active, pvc->state.new);
+ if (lmi == LMI_CISCO) {
+ data[i] = pvc->dlci >> 8;
+ data[i + 1] = pvc->dlci & 0xFF;
+ } else {
+ data[i] = (pvc->dlci >> 4) & 0x3F;
+ data[i + 1] = ((pvc->dlci << 3) & 0x78) | 0x80;
+ data[i + 2] = 0x80;
+ }
+
+ if (pvc->state.new)
+ data[i + 2] |= 0x08;
+ else if (pvc->state.active)
+ data[i + 2] |= 0x02;
+
i += stat_len;
pvc = pvc->next;
}
@@ -569,6 +567,8 @@ static void fr_set_link_state(int reliable, struct net_device *dev)
pvc_carrier(0, pvc);
pvc->state.exist = pvc->state.active = 0;
pvc->state.new = 0;
+ if (!hdlc->state.fr.settings.dce)
+ pvc->state.bandwidth = 0;
pvc = pvc->next;
}
}
@@ -583,11 +583,12 @@ static void fr_timer(unsigned long arg)
int i, cnt = 0, reliable;
u32 list;
- if (hdlc->state.fr.settings.dce)
+ if (hdlc->state.fr.settings.dce) {
reliable = hdlc->state.fr.request &&
time_before(jiffies, hdlc->state.fr.last_poll +
hdlc->state.fr.settings.t392 * HZ);
- else {
+ hdlc->state.fr.request = 0;
+ } else {
hdlc->state.fr.last_errors <<= 1; /* Shift the list */
if (hdlc->state.fr.request) {
if (hdlc->state.fr.reliable)
@@ -634,65 +635,88 @@ static void fr_timer(unsigned long arg)
static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
- int stat_len;
pvc_device *pvc;
- int reptype = -1, error, no_ram;
u8 rxseq, txseq;
- int i;
+ int lmi = hdlc->state.fr.settings.lmi;
+ int dce = hdlc->state.fr.settings.dce;
+ int stat_len = (lmi == LMI_CISCO) ? 6 : 3, reptype, error, no_ram, i;
- if (skb->len < ((hdlc->state.fr.settings.lmi == LMI_ANSI)
- ? LMI_ANSI_LENGTH : LMI_LENGTH)) {
+ if (skb->len < (lmi == LMI_ANSI ? LMI_ANSI_LENGTH :
+ LMI_CCITT_CISCO_LENGTH)) {
printk(KERN_INFO "%s: Short LMI frame\n", dev->name);
return 1;
}
- if (skb->data[5] != (!hdlc->state.fr.settings.dce ?
- LMI_STATUS : LMI_STATUS_ENQUIRY)) {
- printk(KERN_INFO "%s: LMI msgtype=%x, Not LMI status %s\n",
- dev->name, skb->data[2],
- hdlc->state.fr.settings.dce ? "enquiry" : "reply");
+ if (skb->data[3] != (lmi == LMI_CISCO ? NLPID_CISCO_LMI :
+ NLPID_CCITT_ANSI_LMI)) {
+ printk(KERN_INFO "%s: Received non-LMI frame with LMI"
+ " DLCI\n", dev->name);
+ return 1;
+ }
+
+ if (skb->data[4] != LMI_CALLREF) {
+ printk(KERN_INFO "%s: Invalid LMI Call reference (0x%02X)\n",
+ dev->name, skb->data[4]);
+ return 1;
+ }
+
+ if (skb->data[5] != (dce ? LMI_STATUS_ENQUIRY : LMI_STATUS)) {
+ printk(KERN_INFO "%s: Invalid LMI Message type (0x%02X)\n",
+ dev->name, skb->data[5]);
return 1;
}
- i = (hdlc->state.fr.settings.lmi == LMI_ANSI) ? 7 : 6;
+ if (lmi == LMI_ANSI) {
+ if (skb->data[6] != LMI_ANSI_LOCKSHIFT) {
+ printk(KERN_INFO "%s: Not ANSI locking shift in LMI"
+ " message (0x%02X)\n", dev->name, skb->data[6]);
+ return 1;
+ }
+ i = 7;
+ } else
+ i = 6;
- if (skb->data[i] !=
- ((hdlc->state.fr.settings.lmi == LMI_CCITT)
- ? LMI_CCITT_REPTYPE : LMI_REPTYPE)) {
- printk(KERN_INFO "%s: Not a report type=%x\n",
+ if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_REPTYPE :
+ LMI_ANSI_CISCO_REPTYPE)) {
+ printk(KERN_INFO "%s: Not an LMI Report type IE (0x%02X)\n",
dev->name, skb->data[i]);
return 1;
}
- i++;
- i++; /* Skip length field */
+ if (skb->data[++i] != LMI_REPT_LEN) {
+ printk(KERN_INFO "%s: Invalid LMI Report type IE length"
+ " (%u)\n", dev->name, skb->data[i]);
+ return 1;
+ }
- reptype = skb->data[i++];
+ reptype = skb->data[++i];
+ if (reptype != LMI_INTEGRITY && reptype != LMI_FULLREP) {
+ printk(KERN_INFO "%s: Unsupported LMI Report type (0x%02X)\n",
+ dev->name, reptype);
+ return 1;
+ }
- if (skb->data[i]!=
- ((hdlc->state.fr.settings.lmi == LMI_CCITT)
- ? LMI_CCITT_ALIVE : LMI_ALIVE)) {
- printk(KERN_INFO "%s: Unsupported status element=%x\n",
- dev->name, skb->data[i]);
+ if (skb->data[++i] != (lmi == LMI_CCITT ? LMI_CCITT_ALIVE :
+ LMI_ANSI_CISCO_ALIVE)) {
+ printk(KERN_INFO "%s: Not an LMI Link integrity verification"
+ " IE (0x%02X)\n", dev->name, skb->data[i]);
return 1;
}
- i++;
- i++; /* Skip length field */
+ if (skb->data[++i] != LMI_INTEG_LEN) {
+ printk(KERN_INFO "%s: Invalid LMI Link integrity verification"
+ " IE length (%u)\n", dev->name, skb->data[i]);
+ return 1;
+ }
+ i++;
hdlc->state.fr.rxseq = skb->data[i++]; /* TX sequence from peer */
rxseq = skb->data[i++]; /* Should confirm our sequence */
txseq = hdlc->state.fr.txseq;
- if (hdlc->state.fr.settings.dce) {
- if (reptype != LMI_FULLREP && reptype != LMI_INTEGRITY) {
- printk(KERN_INFO "%s: Unsupported report type=%x\n",
- dev->name, reptype);
- return 1;
- }
+ if (dce)
hdlc->state.fr.last_poll = jiffies;
- }
error = 0;
if (!hdlc->state.fr.reliable)
@@ -703,7 +727,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
error = 1;
}
- if (hdlc->state.fr.settings.dce) {
+ if (dce) {
if (hdlc->state.fr.fullrep_sent && !error) {
/* Stop sending full report - the last one has been confirmed by DTE */
hdlc->state.fr.fullrep_sent = 0;
@@ -725,6 +749,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
hdlc->state.fr.dce_changed = 0;
}
+ hdlc->state.fr.request = 1; /* got request */
fr_lmi_send(dev, reptype == LMI_FULLREP ? 1 : 0);
return 0;
}
@@ -739,7 +764,6 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
if (reptype != LMI_FULLREP)
return 0;
- stat_len = 3;
pvc = hdlc->state.fr.first_pvc;
while (pvc) {
@@ -750,24 +774,35 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
no_ram = 0;
while (skb->len >= i + 2 + stat_len) {
u16 dlci;
+ u32 bw;
unsigned int active, new;
- if (skb->data[i] != ((hdlc->state.fr.settings.lmi == LMI_CCITT)
- ? LMI_CCITT_PVCSTAT : LMI_PVCSTAT)) {
- printk(KERN_WARNING "%s: Invalid PVCSTAT ID: %x\n",
- dev->name, skb->data[i]);
+ if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_PVCSTAT :
+ LMI_ANSI_CISCO_PVCSTAT)) {
+ printk(KERN_INFO "%s: Not an LMI PVC status IE"
+ " (0x%02X)\n", dev->name, skb->data[i]);
return 1;
}
- i++;
- if (skb->data[i] != stat_len) {
- printk(KERN_WARNING "%s: Invalid PVCSTAT length: %x\n",
- dev->name, skb->data[i]);
+ if (skb->data[++i] != stat_len) {
+ printk(KERN_INFO "%s: Invalid LMI PVC status IE length"
+ " (%u)\n", dev->name, skb->data[i]);
return 1;
}
i++;
- dlci = status_to_dlci(skb->data + i, &active, &new);
+ new = !! (skb->data[i + 2] & 0x08);
+ active = !! (skb->data[i + 2] & 0x02);
+ if (lmi == LMI_CISCO) {
+ dlci = (skb->data[i] << 8) | skb->data[i + 1];
+ bw = (skb->data[i + 3] << 16) |
+ (skb->data[i + 4] << 8) |
+ (skb->data[i + 5]);
+ } else {
+ dlci = ((skb->data[i] & 0x3F) << 4) |
+ ((skb->data[i + 1] & 0x78) >> 3);
+ bw = 0;
+ }
pvc = add_pvc(dev, dlci);
@@ -783,9 +818,11 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
pvc->state.deleted = 0;
if (active != pvc->state.active ||
new != pvc->state.new ||
+ bw != pvc->state.bandwidth ||
!pvc->state.exist) {
pvc->state.new = new;
pvc->state.active = active;
+ pvc->state.bandwidth = bw;
pvc_carrier(active, pvc);
fr_log_dlci_active(pvc);
}
@@ -801,6 +838,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
pvc_carrier(0, pvc);
pvc->state.active = pvc->state.new = 0;
pvc->state.exist = 0;
+ pvc->state.bandwidth = 0;
fr_log_dlci_active(pvc);
}
pvc = pvc->next;
@@ -829,22 +867,15 @@ static int fr_rx(struct sk_buff *skb)
dlci = q922_to_dlci(skb->data);
- if (dlci == LMI_DLCI) {
- if (hdlc->state.fr.settings.lmi == LMI_NONE)
- goto rx_error; /* LMI packet with no LMI? */
-
- if (data[3] == LMI_PROTO) {
- if (fr_lmi_recv(ndev, skb))
- goto rx_error;
- else {
- dev_kfree_skb_any(skb);
- return NET_RX_SUCCESS;
- }
- }
-
- printk(KERN_INFO "%s: Received non-LMI frame with LMI DLCI\n",
- ndev->name);
- goto rx_error;
+ if ((dlci == LMI_CCITT_ANSI_DLCI &&
+ (hdlc->state.fr.settings.lmi == LMI_ANSI ||
+ hdlc->state.fr.settings.lmi == LMI_CCITT)) ||
+ (dlci == LMI_CISCO_DLCI &&
+ hdlc->state.fr.settings.lmi == LMI_CISCO)) {
+ if (fr_lmi_recv(ndev, skb))
+ goto rx_error;
+ dev_kfree_skb_any(skb);
+ return NET_RX_SUCCESS;
}
pvc = find_pvc(hdlc, dlci);
@@ -1170,7 +1201,8 @@ int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr)
if ((new_settings.lmi != LMI_NONE &&
new_settings.lmi != LMI_ANSI &&
- new_settings.lmi != LMI_CCITT) ||
+ new_settings.lmi != LMI_CCITT &&
+ new_settings.lmi != LMI_CISCO) ||
new_settings.t391 < 1 ||
new_settings.t392 < 2 ||
new_settings.n391 < 1 ||
diff --git a/drivers/net/wan/hdlc_generic.c b/drivers/net/wan/hdlc_generic.c
index 6ed064cb446..a63f6a2cc4f 100644
--- a/drivers/net/wan/hdlc_generic.c
+++ b/drivers/net/wan/hdlc_generic.c
@@ -1,7 +1,7 @@
/*
* Generic HDLC support routines for Linux
*
- * Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 1999 - 2005 Krzysztof Halasa <khc@pm.waw.pl>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
@@ -38,7 +38,7 @@
#include <linux/hdlc.h>
-static const char* version = "HDLC support module revision 1.17";
+static const char* version = "HDLC support module revision 1.18";
#undef DEBUG_LINK
@@ -126,10 +126,13 @@ void hdlc_set_carrier(int on, struct net_device *dev)
if (!hdlc->open)
goto carrier_exit;
- if (hdlc->carrier)
+ if (hdlc->carrier) {
+ printk(KERN_INFO "%s: Carrier detected\n", dev->name);
__hdlc_set_carrier_on(dev);
- else
+ } else {
+ printk(KERN_INFO "%s: Carrier lost\n", dev->name);
__hdlc_set_carrier_off(dev);
+ }
carrier_exit:
spin_unlock_irqrestore(&hdlc->state_lock, flags);
@@ -157,8 +160,11 @@ int hdlc_open(struct net_device *dev)
spin_lock_irq(&hdlc->state_lock);
- if (hdlc->carrier)
+ if (hdlc->carrier) {
+ printk(KERN_INFO "%s: Carrier detected\n", dev->name);
__hdlc_set_carrier_on(dev);
+ } else
+ printk(KERN_INFO "%s: No carrier\n", dev->name);
hdlc->open = 1;
diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c
index 15e545f66cd..2b948ea397d 100644
--- a/drivers/net/wan/lmc/lmc_main.c
+++ b/drivers/net/wan/lmc/lmc_main.c
@@ -723,7 +723,7 @@ static void lmc_watchdog (unsigned long data) /*fold00*/
/* lmc_reset (sc); Why reset??? The link can go down ok */
/* Inform the world that link has been lost */
- dev->flags &= ~IFF_RUNNING;
+ netif_carrier_off(dev);
}
/*
@@ -736,7 +736,7 @@ static void lmc_watchdog (unsigned long data) /*fold00*/
/* lmc_reset (sc); Again why reset??? */
/* Inform the world that link protocol is back up. */
- dev->flags |= IFF_RUNNING;
+ netif_carrier_on(dev);
/* Now we have to tell the syncppp that we had an outage
* and that it should deal. Calling sppp_reopen here
@@ -1168,8 +1168,6 @@ static void lmc_running_reset (struct net_device *dev) /*fold00*/
sc->lmc_media->set_link_status (sc, 1);
sc->lmc_media->set_status (sc, NULL);
- //dev->flags |= IFF_RUNNING;
-
netif_wake_queue(dev);
sc->lmc_txfull = 0;
@@ -1233,8 +1231,6 @@ static int lmc_ifdown (struct net_device *dev) /*fold00*/
csr6 &= ~LMC_DEC_SR; /* Turn off the Receive bit */
LMC_CSR_WRITE (sc, csr_command, csr6);
- dev->flags &= ~IFF_RUNNING;
-
sc->stats.rx_missed_errors +=
LMC_CSR_READ (sc, csr_missed_frames) & 0xffff;
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index 1c540d82555..bdf672c4818 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -829,7 +829,7 @@ static void __exit exit_x25_asy(void)
}
kfree(x25_asy_devs);
- tty_register_ldisc(N_X25, NULL);
+ tty_unregister_ldisc(N_X25);
}
module_init(init_x25_asy);
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 0aaa12c0c09..1d3231cc471 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -323,7 +323,7 @@ config PRISM54
For a complete list of supported cards visit <http://prism54.org>.
Here is the latest confirmed list of supported cards:
- 3com OfficeConnect 11g Cardbus Card aka 3CRWE154G72
+ 3com OfficeConnect 11g Cardbus Card aka 3CRWE154G72 (version 1)
Allnet ALL0271 PCI Card
Compex WL54G Cardbus Card
Corega CG-WLCB54GT Cardbus Card
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 463c789cdc7..d72e0385e4f 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -754,7 +754,7 @@ typedef struct {
u8 zero;
u8 ssidLen;
u8 ssid[32];
- u16 rssi;
+ u16 dBm;
#define CAP_ESS (1<<0)
#define CAP_IBSS (1<<1)
#define CAP_PRIVACY (1<<4)
@@ -1125,6 +1125,9 @@ static int micsetup(struct airo_info *ai);
static int encapsulate(struct airo_info *ai, etherHead *pPacket, MICBuffer *buffer, int len);
static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *pPacket, u16 payLen);
+static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi);
+static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm);
+
#include <linux/crypto.h>
#endif
@@ -1713,6 +1716,7 @@ static int readBSSListRid(struct airo_info *ai, int first,
list->fh.dwell = le16_to_cpu(list->fh.dwell);
list->dsChannel = le16_to_cpu(list->dsChannel);
list->atimWindow = le16_to_cpu(list->atimWindow);
+ list->dBm = le16_to_cpu(list->dBm);
return rc;
}
@@ -2914,7 +2918,7 @@ static int airo_thread(void *data) {
flush_signals(current);
/* make swsusp happy with our thread */
- try_to_freeze(PF_FREEZE);
+ try_to_freeze();
if (test_bit(JOB_DIE, &ai->flags))
break;
@@ -3245,7 +3249,10 @@ badrx:
wstats.level = 0x100 - apriv->rssi[hdr.rssi[1]].rssidBm;
else
wstats.level = (hdr.rssi[1] + 321) / 2;
- wstats.updated = 3;
+ wstats.noise = apriv->wstats.qual.noise;
+ wstats.updated = IW_QUAL_LEVEL_UPDATED
+ | IW_QUAL_QUAL_UPDATED
+ | IW_QUAL_NOISE_UPDATED;
/* Update spy records */
wireless_spy_update(dev, sa, &wstats);
}
@@ -3588,7 +3595,10 @@ void mpi_receive_802_11 (struct airo_info *ai)
wstats.level = 0x100 - ai->rssi[hdr.rssi[1]].rssidBm;
else
wstats.level = (hdr.rssi[1] + 321) / 2;
- wstats.updated = 3;
+ wstats.noise = ai->wstats.qual.noise;
+ wstats.updated = IW_QUAL_QUAL_UPDATED
+ | IW_QUAL_LEVEL_UPDATED
+ | IW_QUAL_NOISE_UPDATED;
/* Update spy records */
wireless_spy_update(ai->dev, sa, &wstats);
}
@@ -3679,7 +3689,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
status = PC4500_readrid(ai,RID_RSSI,&rssi_rid,sizeof(rssi_rid),lock);
if ( status == SUCCESS ) {
if (ai->rssi || (ai->rssi = kmalloc(512, GFP_KERNEL)) != NULL)
- memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512);
+ memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512); /* Skip RID length member */
}
else {
if (ai->rssi) {
@@ -5348,7 +5358,7 @@ static int proc_BSSList_open( struct inode *inode, struct file *file ) {
(int)BSSList_rid.bssid[5],
(int)BSSList_rid.ssidLen,
BSSList_rid.ssid,
- (int)BSSList_rid.rssi);
+ (int)BSSList_rid.dBm);
ptr += sprintf(ptr, " channel = %d %s %s %s %s\n",
(int)BSSList_rid.dsChannel,
BSSList_rid.cap & CAP_ESS ? "ESS" : "",
@@ -5593,6 +5603,29 @@ static void __exit airo_cleanup_module( void )
* would not work at all... - Jean II
*/
+static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi)
+{
+ if( !rssi_rid )
+ return 0;
+
+ return (0x100 - rssi_rid[rssi].rssidBm);
+}
+
+static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm)
+{
+ int i;
+
+ if( !rssi_rid )
+ return 0;
+
+ for( i = 0; i < 256; i++ )
+ if (rssi_rid[i].rssidBm == dbm)
+ return rssi_rid[i].rssipct;
+
+ return 0;
+}
+
+
static int airo_get_quality (StatusRid *status_rid, CapabilityRid *cap_rid)
{
int quality = 0;
@@ -6443,11 +6476,29 @@ static int airo_get_range(struct net_device *dev,
}
range->num_frequency = k;
+ range->sensitivity = 65535;
+
/* Hum... Should put the right values there */
- range->max_qual.qual = airo_get_max_quality(&cap_rid);
- range->max_qual.level = 0x100 - 120; /* -120 dBm */
+ if (local->rssi)
+ range->max_qual.qual = 100; /* % */
+ else
+ range->max_qual.qual = airo_get_max_quality(&cap_rid);
+ range->max_qual.level = 0; /* 0 means we use dBm */
range->max_qual.noise = 0;
- range->sensitivity = 65535;
+ range->max_qual.updated = 0;
+
+ /* Experimental measurements - boundary 11/5.5 Mb/s */
+ /* Note : with or without the (local->rssi), results
+ * are somewhat different. - Jean II */
+ if (local->rssi) {
+ range->avg_qual.qual = 50; /* % */
+ range->avg_qual.level = 186; /* -70 dBm */
+ } else {
+ range->avg_qual.qual = airo_get_avg_quality(&cap_rid);
+ range->avg_qual.level = 176; /* -80 dBm */
+ }
+ range->avg_qual.noise = 0;
+ range->avg_qual.updated = 0;
for(i = 0 ; i < 8 ; i++) {
range->bitrate[i] = cap_rid.supportedRates[i] * 500000;
@@ -6508,15 +6559,6 @@ static int airo_get_range(struct net_device *dev,
range->max_retry = 65535;
range->min_r_time = 1024;
range->max_r_time = 65535 * 1024;
- /* Experimental measurements - boundary 11/5.5 Mb/s */
- /* Note : with or without the (local->rssi), results
- * are somewhat different. - Jean II */
- range->avg_qual.qual = airo_get_avg_quality(&cap_rid);
- if (local->rssi)
- range->avg_qual.level = 186; /* -70 dBm */
- else
- range->avg_qual.level = 176; /* -80 dBm */
- range->avg_qual.noise = 0;
/* Event capability (kernel + driver) */
range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
@@ -6676,12 +6718,18 @@ static int airo_get_aplist(struct net_device *dev,
loseSync = 0;
memcpy(address[i].sa_data, BSSList.bssid, ETH_ALEN);
address[i].sa_family = ARPHRD_ETHER;
- if (local->rssi)
- qual[i].level = 0x100 - local->rssi[BSSList.rssi].rssidBm;
- else
- qual[i].level = (BSSList.rssi + 321) / 2;
- qual[i].qual = qual[i].noise = 0;
- qual[i].updated = 2;
+ if (local->rssi) {
+ qual[i].level = 0x100 - BSSList.dBm;
+ qual[i].qual = airo_dbm_to_pct( local->rssi, BSSList.dBm );
+ qual[i].updated = IW_QUAL_QUAL_UPDATED;
+ } else {
+ qual[i].level = (BSSList.dBm + 321) / 2;
+ qual[i].qual = 0;
+ qual[i].updated = IW_QUAL_QUAL_INVALID;
+ }
+ qual[i].noise = local->wstats.qual.noise;
+ qual[i].updated = IW_QUAL_LEVEL_UPDATED
+ | IW_QUAL_NOISE_UPDATED;
if (BSSList.index == 0xffff)
break;
}
@@ -6760,7 +6808,7 @@ static int airo_set_scan(struct net_device *dev,
static inline char *airo_translate_scan(struct net_device *dev,
char *current_ev,
char *end_buf,
- BSSListRid *list)
+ BSSListRid *bss)
{
struct airo_info *ai = dev->priv;
struct iw_event iwe; /* Temporary buffer */
@@ -6771,22 +6819,22 @@ static inline char *airo_translate_scan(struct net_device *dev,
/* First entry *MUST* be the AP MAC address */
iwe.cmd = SIOCGIWAP;
iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
- memcpy(iwe.u.ap_addr.sa_data, list->bssid, ETH_ALEN);
+ memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN);
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
/* Other entries will be displayed in the order we give them */
/* Add the ESSID */
- iwe.u.data.length = list->ssidLen;
+ iwe.u.data.length = bss->ssidLen;
if(iwe.u.data.length > 32)
iwe.u.data.length = 32;
iwe.cmd = SIOCGIWESSID;
iwe.u.data.flags = 1;
- current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, list->ssid);
+ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->ssid);
/* Add mode */
iwe.cmd = SIOCGIWMODE;
- capabilities = le16_to_cpu(list->cap);
+ capabilities = le16_to_cpu(bss->cap);
if(capabilities & (CAP_ESS | CAP_IBSS)) {
if(capabilities & CAP_ESS)
iwe.u.mode = IW_MODE_MASTER;
@@ -6797,19 +6845,25 @@ static inline char *airo_translate_scan(struct net_device *dev,
/* Add frequency */
iwe.cmd = SIOCGIWFREQ;
- iwe.u.freq.m = le16_to_cpu(list->dsChannel);
+ iwe.u.freq.m = le16_to_cpu(bss->dsChannel);
iwe.u.freq.m = frequency_list[iwe.u.freq.m] * 100000;
iwe.u.freq.e = 1;
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
/* Add quality statistics */
iwe.cmd = IWEVQUAL;
- if (ai->rssi)
- iwe.u.qual.level = 0x100 - ai->rssi[list->rssi].rssidBm;
- else
- iwe.u.qual.level = (list->rssi + 321) / 2;
- iwe.u.qual.noise = 0;
- iwe.u.qual.qual = 0;
+ if (ai->rssi) {
+ iwe.u.qual.level = 0x100 - bss->dBm;
+ iwe.u.qual.qual = airo_dbm_to_pct( ai->rssi, bss->dBm );
+ iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED;
+ } else {
+ iwe.u.qual.level = (bss->dBm + 321) / 2;
+ iwe.u.qual.qual = 0;
+ iwe.u.qual.updated = IW_QUAL_QUAL_INVALID;
+ }
+ iwe.u.qual.noise = ai->wstats.qual.noise;
+ iwe.u.qual.updated = IW_QUAL_LEVEL_UPDATED
+ | IW_QUAL_NOISE_UPDATED;
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
/* Add encryption capability */
@@ -6819,7 +6873,7 @@ static inline char *airo_translate_scan(struct net_device *dev,
else
iwe.u.data.flags = IW_ENCODE_DISABLED;
iwe.u.data.length = 0;
- current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, list->ssid);
+ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->ssid);
/* Rate : stuffing multiple values in a single event require a bit
* more of magic - Jean II */
@@ -6831,10 +6885,10 @@ static inline char *airo_translate_scan(struct net_device *dev,
/* Max 8 values */
for(i = 0 ; i < 8 ; i++) {
/* NULL terminated */
- if(list->rates[i] == 0)
+ if(bss->rates[i] == 0)
break;
/* Bit rate given in 500 kb/s units (+ 0x80) */
- iwe.u.bitrate.value = ((list->rates[i] & 0x7f) * 500000);
+ iwe.u.bitrate.value = ((bss->rates[i] & 0x7f) * 500000);
/* Add new value to event */
current_val = iwe_stream_add_value(current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
}
@@ -7153,18 +7207,22 @@ static void airo_read_wireless_stats(struct airo_info *local)
/* The status */
local->wstats.status = status_rid.mode;
- /* Signal quality and co. But where is the noise level ??? */
- local->wstats.qual.qual = airo_get_quality(&status_rid, &cap_rid);
- if (local->rssi)
- local->wstats.qual.level = 0x100 - local->rssi[status_rid.sigQuality].rssidBm;
- else
+ /* Signal quality and co */
+ if (local->rssi) {
+ local->wstats.qual.level = airo_rssi_to_dbm( local->rssi, status_rid.sigQuality );
+ /* normalizedSignalStrength appears to be a percentage */
+ local->wstats.qual.qual = status_rid.normalizedSignalStrength;
+ } else {
local->wstats.qual.level = (status_rid.normalizedSignalStrength + 321) / 2;
+ local->wstats.qual.qual = airo_get_quality(&status_rid, &cap_rid);
+ }
+ local->wstats.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED;
if (status_rid.len >= 124) {
- local->wstats.qual.noise = 256 - status_rid.noisedBm;
- local->wstats.qual.updated = 7;
+ local->wstats.qual.noise = 0x100 - status_rid.noisedBm;
+ local->wstats.qual.updated |= IW_QUAL_NOISE_UPDATED;
} else {
local->wstats.qual.noise = 0;
- local->wstats.qual.updated = 3;
+ local->wstats.qual.updated |= IW_QUAL_NOISE_INVALID;
}
/* Packets discarded in the wireless adapter due to wireless
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
index a91b507e0a7..a4ed28d9c78 100644
--- a/drivers/net/wireless/atmel_cs.c
+++ b/drivers/net/wireless/atmel_cs.c
@@ -321,6 +321,7 @@ static struct {
{ 0x01bf, 0x3302, NULL, ATMEL_FW_TYPE_502E, "Belkin F5D6020-V2" },
{ 0, 0, "BT/Voyager 1020 Laptop Adapter", ATMEL_FW_TYPE_502, "BT Voyager 1020" },
{ 0, 0, "IEEE 802.11b/Wireless LAN PC Card", ATMEL_FW_TYPE_502, "Siemens Gigaset PC Card II" },
+ { 0, 0, "IEEE 802.11b/Wireless LAN Card S", ATMEL_FW_TYPE_504_2958, "Siemens Gigaset PC Card II" },
{ 0, 0, "CNet/CNWLC 11Mbps Wireless PC Card V-5", ATMEL_FW_TYPE_502E, "CNet CNWLC-811ARL" },
{ 0, 0, "Wireless/PC_CARD", ATMEL_FW_TYPE_502D, "Planet WL-3552" },
{ 0, 0, "OEM/11Mbps Wireless LAN PC Card V-3", ATMEL_FW_TYPE_502, "OEM 11Mbps WLAN PCMCIA Card" },
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index a3a32430ae9..b1078baa1d5 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -492,6 +492,9 @@ EXPORT_SYMBOL(orinoco_debug);
static int suppress_linkstatus; /* = 0 */
module_param(suppress_linkstatus, bool, 0644);
MODULE_PARM_DESC(suppress_linkstatus, "Don't log link status changes");
+static int ignore_disconnect; /* = 0 */
+module_param(ignore_disconnect, int, 0644);
+MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer");
/********************************************************************/
/* Compile time configuration and compatibility stuff */
@@ -604,7 +607,6 @@ struct hermes_rx_descriptor {
static int orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static int __orinoco_program_rids(struct net_device *dev);
static void __orinoco_set_multicast_list(struct net_device *dev);
-static int orinoco_debug_dump_recs(struct net_device *dev);
/********************************************************************/
/* Internal helper functions */
@@ -655,7 +657,7 @@ static int orinoco_open(struct net_device *dev)
return err;
}
-int orinoco_stop(struct net_device *dev)
+static int orinoco_stop(struct net_device *dev)
{
struct orinoco_private *priv = netdev_priv(dev);
int err = 0;
@@ -686,7 +688,7 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
struct orinoco_private *priv = netdev_priv(dev);
hermes_t *hw = &priv->hw;
struct iw_statistics *wstats = &priv->wstats;
- int err = 0;
+ int err;
unsigned long flags;
if (! netif_device_present(dev)) {
@@ -695,9 +697,21 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
return NULL; /* FIXME: Can we do better than this? */
}
+ /* If busy, return the old stats. Returning NULL may cause
+ * the interface to disappear from /proc/net/wireless */
if (orinoco_lock(priv, &flags) != 0)
- return NULL; /* FIXME: Erg, we've been signalled, how
- * do we propagate this back up? */
+ return wstats;
+
+ /* We can't really wait for the tallies inquiry command to
+ * complete, so we just use the previous results and trigger
+ * a new tallies inquiry command for next time - Jean II */
+ /* FIXME: Really we should wait for the inquiry to come back -
+ * as it is the stats we give don't make a whole lot of sense.
+ * Unfortunately, it's not clear how to do that within the
+ * wireless extensions framework: I think we're in user
+ * context, but a lock seems to be held by the time we get in
+ * here so we're not safe to sleep here. */
+ hermes_inquire(hw, HERMES_INQ_TALLIES);
if (priv->iw_mode == IW_MODE_ADHOC) {
memset(&wstats->qual, 0, sizeof(wstats->qual));
@@ -716,25 +730,16 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
err = HERMES_READ_RECORD(hw, USER_BAP,
HERMES_RID_COMMSQUALITY, &cq);
-
- wstats->qual.qual = (int)le16_to_cpu(cq.qual);
- wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95;
- wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95;
- wstats->qual.updated = 7;
+
+ if (!err) {
+ wstats->qual.qual = (int)le16_to_cpu(cq.qual);
+ wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95;
+ wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95;
+ wstats->qual.updated = 7;
+ }
}
- /* We can't really wait for the tallies inquiry command to
- * complete, so we just use the previous results and trigger
- * a new tallies inquiry command for next time - Jean II */
- /* FIXME: We're in user context (I think?), so we should just
- wait for the tallies to come through */
- err = hermes_inquire(hw, HERMES_INQ_TALLIES);
-
orinoco_unlock(priv, &flags);
-
- if (err)
- return NULL;
-
return wstats;
}
@@ -1275,9 +1280,10 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
len = sizeof(tallies);
}
- /* Read directly the data (no seek) */
- hermes_read_words(hw, HERMES_DATA1, (void *) &tallies,
- len / 2); /* FIXME: blech! */
+ err = hermes_bap_pread(hw, IRQ_BAP, &tallies, len,
+ infofid, sizeof(info));
+ if (err)
+ break;
/* Increment our various counters */
/* wstats->discard.nwid - no wrong BSSID stuff */
@@ -1307,8 +1313,10 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
break;
}
- hermes_read_words(hw, HERMES_DATA1, (void *) &linkstatus,
- len / 2);
+ err = hermes_bap_pread(hw, IRQ_BAP, &linkstatus, len,
+ infofid, sizeof(info));
+ if (err)
+ break;
newstatus = le16_to_cpu(linkstatus.linkstatus);
connected = (newstatus == HERMES_LINKSTATUS_CONNECTED)
@@ -1317,7 +1325,7 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
if (connected)
netif_carrier_on(dev);
- else
+ else if (!ignore_disconnect)
netif_carrier_off(dev);
if (newstatus != priv->last_linkstatus)
@@ -1350,6 +1358,8 @@ int __orinoco_up(struct net_device *dev)
struct hermes *hw = &priv->hw;
int err;
+ netif_carrier_off(dev); /* just to make sure */
+
err = __orinoco_program_rids(dev);
if (err) {
printk(KERN_ERR "%s: Error %d configuring card\n",
@@ -1413,7 +1423,7 @@ int orinoco_reinit_firmware(struct net_device *dev)
return err;
err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
- if (err == -EIO) {
+ if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) {
/* Try workaround for old Symbol firmware bug */
printk(KERN_WARNING "%s: firmware ALLOC bug detected "
"(old Symbol firmware?). Trying to work around... ",
@@ -1610,17 +1620,15 @@ static int __orinoco_program_rids(struct net_device *dev)
return err;
}
/* Set the channel/frequency */
- if (priv->channel == 0) {
- printk(KERN_DEBUG "%s: Channel is 0 in __orinoco_program_rids()\n", dev->name);
- if (priv->createibss)
- priv->channel = 10;
- }
- err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFOWNCHANNEL,
- priv->channel);
- if (err) {
- printk(KERN_ERR "%s: Error %d setting channel\n",
- dev->name, err);
- return err;
+ if (priv->channel != 0 && priv->iw_mode != IW_MODE_INFRA) {
+ err = hermes_write_wordrec(hw, USER_BAP,
+ HERMES_RID_CNFOWNCHANNEL,
+ priv->channel);
+ if (err) {
+ printk(KERN_ERR "%s: Error %d setting channel %d\n",
+ dev->name, err, priv->channel);
+ return err;
+ }
}
if (priv->has_ibss) {
@@ -1916,7 +1924,7 @@ static void orinoco_reset(struct net_device *dev)
{
struct orinoco_private *priv = netdev_priv(dev);
struct hermes *hw = &priv->hw;
- int err = 0;
+ int err;
unsigned long flags;
if (orinoco_lock(priv, &flags) != 0)
@@ -1938,20 +1946,20 @@ static void orinoco_reset(struct net_device *dev)
orinoco_unlock(priv, &flags);
- if (priv->hard_reset)
+ if (priv->hard_reset) {
err = (*priv->hard_reset)(priv);
- if (err) {
- printk(KERN_ERR "%s: orinoco_reset: Error %d "
- "performing hard reset\n", dev->name, err);
- /* FIXME: shutdown of some sort */
- return;
+ if (err) {
+ printk(KERN_ERR "%s: orinoco_reset: Error %d "
+ "performing hard reset\n", dev->name, err);
+ goto disable;
+ }
}
err = orinoco_reinit_firmware(dev);
if (err) {
printk(KERN_ERR "%s: orinoco_reset: Error %d re-initializing firmware\n",
dev->name, err);
- return;
+ goto disable;
}
spin_lock_irq(&priv->lock); /* This has to be called from user context */
@@ -1972,6 +1980,10 @@ static void orinoco_reset(struct net_device *dev)
spin_unlock_irq(&priv->lock);
return;
+ disable:
+ hermes_set_irqmask(hw, 0);
+ netif_device_detach(dev);
+ printk(KERN_ERR "%s: Device has been disabled!\n", dev->name);
}
/********************************************************************/
@@ -2056,7 +2068,7 @@ irqreturn_t orinoco_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (events & HERMES_EV_ALLOC)
__orinoco_ev_alloc(dev, hw);
- hermes_write_regn(hw, EVACK, events);
+ hermes_write_regn(hw, EVACK, evstat);
evstat = hermes_read_regn(hw, EVSTAT);
events = evstat & hw->inten;
@@ -2215,6 +2227,8 @@ static int determine_firmware(struct net_device *dev)
firmver >= 0x31000;
priv->has_preamble = (firmver >= 0x20000);
priv->ibss_port = 4;
+ priv->broken_disableport = (firmver == 0x25013) ||
+ (firmver >= 0x30000 && firmver <= 0x31000);
/* Tested with Intel firmware : 0x20015 => Jean II */
/* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */
break;
@@ -2267,7 +2281,7 @@ static int orinoco_init(struct net_device *dev)
priv->nicbuf_size = IEEE802_11_FRAME_LEN + ETH_HLEN;
/* Initialize the firmware */
- err = hermes_init(hw);
+ err = orinoco_reinit_firmware(dev);
if (err != 0) {
printk(KERN_ERR "%s: failed to initialize firmware (err = %d)\n",
dev->name, err);
@@ -2400,31 +2414,12 @@ static int orinoco_init(struct net_device *dev)
/* By default use IEEE/IBSS ad-hoc mode if we have it */
priv->prefer_port3 = priv->has_port3 && (! priv->has_ibss);
set_port_type(priv);
- priv->channel = 10; /* default channel, more-or-less arbitrary */
+ priv->channel = 0; /* use firmware default */
priv->promiscuous = 0;
priv->wep_on = 0;
priv->tx_key = 0;
- err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
- if (err == -EIO) {
- /* Try workaround for old Symbol firmware bug */
- printk(KERN_WARNING "%s: firmware ALLOC bug detected "
- "(old Symbol firmware?). Trying to work around... ",
- dev->name);
-
- priv->nicbuf_size = TX_NICBUF_SIZE_BUG;
- err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
- if (err)
- printk("failed!\n");
- else
- printk("ok.\n");
- }
- if (err) {
- printk("%s: Error %d allocating Tx buffer\n", dev->name, err);
- goto out;
- }
-
/* Make the hardware available, as long as it hasn't been
* removed elsewhere (e.g. by PCMCIA hot unplug) */
spin_lock_irq(&priv->lock);
@@ -2450,7 +2445,7 @@ struct net_device *alloc_orinocodev(int sizeof_card,
priv = netdev_priv(dev);
priv->ndev = dev;
if (sizeof_card)
- priv->card = (void *)((unsigned long)netdev_priv(dev)
+ priv->card = (void *)((unsigned long)priv
+ sizeof(struct orinoco_private));
else
priv->card = NULL;
@@ -2555,6 +2550,7 @@ static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
}
len = le16_to_cpu(essidbuf.len);
+ BUG_ON(len > IW_ESSID_MAX_SIZE);
memset(buf, 0, IW_ESSID_MAX_SIZE+1);
memcpy(buf, p, len);
@@ -2923,13 +2919,14 @@ static int orinoco_ioctl_setessid(struct net_device *dev, struct iw_point *erq)
memset(&essidbuf, 0, sizeof(essidbuf));
if (erq->flags) {
- if (erq->length > IW_ESSID_MAX_SIZE)
+ /* iwconfig includes the NUL in the specified length */
+ if (erq->length > IW_ESSID_MAX_SIZE+1)
return -E2BIG;
if (copy_from_user(&essidbuf, erq->pointer, erq->length))
return -EFAULT;
- essidbuf[erq->length] = '\0';
+ essidbuf[IW_ESSID_MAX_SIZE] = '\0';
}
if (orinoco_lock(priv, &flags) != 0)
@@ -3855,7 +3852,6 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{ SIOCIWFIRSTPRIV + 0x7, 0,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
"get_ibssport" },
- { SIOCIWLASTPRIV, 0, 0, "dump_recs" },
};
wrq->u.data.length = sizeof(privtab) / sizeof(privtab[0]);
@@ -3943,14 +3939,6 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
err = orinoco_ioctl_getibssport(dev, wrq);
break;
- case SIOCIWLASTPRIV:
- err = orinoco_debug_dump_recs(dev);
- if (err)
- printk(KERN_ERR "%s: Unable to dump records (%d)\n",
- dev->name, err);
- break;
-
-
default:
err = -EOPNOTSUPP;
}
@@ -3964,187 +3952,6 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return err;
}
-struct {
- u16 rid;
- char *name;
- int displaytype;
-#define DISPLAY_WORDS 0
-#define DISPLAY_BYTES 1
-#define DISPLAY_STRING 2
-#define DISPLAY_XSTRING 3
-} record_table[] = {
-#define DEBUG_REC(name,type) { HERMES_RID_##name, #name, DISPLAY_##type }
- DEBUG_REC(CNFPORTTYPE,WORDS),
- DEBUG_REC(CNFOWNMACADDR,BYTES),
- DEBUG_REC(CNFDESIREDSSID,STRING),
- DEBUG_REC(CNFOWNCHANNEL,WORDS),
- DEBUG_REC(CNFOWNSSID,STRING),
- DEBUG_REC(CNFOWNATIMWINDOW,WORDS),
- DEBUG_REC(CNFSYSTEMSCALE,WORDS),
- DEBUG_REC(CNFMAXDATALEN,WORDS),
- DEBUG_REC(CNFPMENABLED,WORDS),
- DEBUG_REC(CNFPMEPS,WORDS),
- DEBUG_REC(CNFMULTICASTRECEIVE,WORDS),
- DEBUG_REC(CNFMAXSLEEPDURATION,WORDS),
- DEBUG_REC(CNFPMHOLDOVERDURATION,WORDS),
- DEBUG_REC(CNFOWNNAME,STRING),
- DEBUG_REC(CNFOWNDTIMPERIOD,WORDS),
- DEBUG_REC(CNFMULTICASTPMBUFFERING,WORDS),
- DEBUG_REC(CNFWEPENABLED_AGERE,WORDS),
- DEBUG_REC(CNFMANDATORYBSSID_SYMBOL,WORDS),
- DEBUG_REC(CNFWEPDEFAULTKEYID,WORDS),
- DEBUG_REC(CNFDEFAULTKEY0,BYTES),
- DEBUG_REC(CNFDEFAULTKEY1,BYTES),
- DEBUG_REC(CNFMWOROBUST_AGERE,WORDS),
- DEBUG_REC(CNFDEFAULTKEY2,BYTES),
- DEBUG_REC(CNFDEFAULTKEY3,BYTES),
- DEBUG_REC(CNFWEPFLAGS_INTERSIL,WORDS),
- DEBUG_REC(CNFWEPKEYMAPPINGTABLE,WORDS),
- DEBUG_REC(CNFAUTHENTICATION,WORDS),
- DEBUG_REC(CNFMAXASSOCSTA,WORDS),
- DEBUG_REC(CNFKEYLENGTH_SYMBOL,WORDS),
- DEBUG_REC(CNFTXCONTROL,WORDS),
- DEBUG_REC(CNFROAMINGMODE,WORDS),
- DEBUG_REC(CNFHOSTAUTHENTICATION,WORDS),
- DEBUG_REC(CNFRCVCRCERROR,WORDS),
- DEBUG_REC(CNFMMLIFE,WORDS),
- DEBUG_REC(CNFALTRETRYCOUNT,WORDS),
- DEBUG_REC(CNFBEACONINT,WORDS),
- DEBUG_REC(CNFAPPCFINFO,WORDS),
- DEBUG_REC(CNFSTAPCFINFO,WORDS),
- DEBUG_REC(CNFPRIORITYQUSAGE,WORDS),
- DEBUG_REC(CNFTIMCTRL,WORDS),
- DEBUG_REC(CNFTHIRTY2TALLY,WORDS),
- DEBUG_REC(CNFENHSECURITY,WORDS),
- DEBUG_REC(CNFGROUPADDRESSES,BYTES),
- DEBUG_REC(CNFCREATEIBSS,WORDS),
- DEBUG_REC(CNFFRAGMENTATIONTHRESHOLD,WORDS),
- DEBUG_REC(CNFRTSTHRESHOLD,WORDS),
- DEBUG_REC(CNFTXRATECONTROL,WORDS),
- DEBUG_REC(CNFPROMISCUOUSMODE,WORDS),
- DEBUG_REC(CNFBASICRATES_SYMBOL,WORDS),
- DEBUG_REC(CNFPREAMBLE_SYMBOL,WORDS),
- DEBUG_REC(CNFSHORTPREAMBLE,WORDS),
- DEBUG_REC(CNFWEPKEYS_AGERE,BYTES),
- DEBUG_REC(CNFEXCLUDELONGPREAMBLE,WORDS),
- DEBUG_REC(CNFTXKEY_AGERE,WORDS),
- DEBUG_REC(CNFAUTHENTICATIONRSPTO,WORDS),
- DEBUG_REC(CNFBASICRATES,WORDS),
- DEBUG_REC(CNFSUPPORTEDRATES,WORDS),
- DEBUG_REC(CNFTICKTIME,WORDS),
- DEBUG_REC(CNFSCANREQUEST,WORDS),
- DEBUG_REC(CNFJOINREQUEST,WORDS),
- DEBUG_REC(CNFAUTHENTICATESTATION,WORDS),
- DEBUG_REC(CNFCHANNELINFOREQUEST,WORDS),
- DEBUG_REC(MAXLOADTIME,WORDS),
- DEBUG_REC(DOWNLOADBUFFER,WORDS),
- DEBUG_REC(PRIID,WORDS),
- DEBUG_REC(PRISUPRANGE,WORDS),
- DEBUG_REC(CFIACTRANGES,WORDS),
- DEBUG_REC(NICSERNUM,XSTRING),
- DEBUG_REC(NICID,WORDS),
- DEBUG_REC(MFISUPRANGE,WORDS),
- DEBUG_REC(CFISUPRANGE,WORDS),
- DEBUG_REC(CHANNELLIST,WORDS),
- DEBUG_REC(REGULATORYDOMAINS,WORDS),
- DEBUG_REC(TEMPTYPE,WORDS),
-/* DEBUG_REC(CIS,BYTES), */
- DEBUG_REC(STAID,WORDS),
- DEBUG_REC(CURRENTSSID,STRING),
- DEBUG_REC(CURRENTBSSID,BYTES),
- DEBUG_REC(COMMSQUALITY,WORDS),
- DEBUG_REC(CURRENTTXRATE,WORDS),
- DEBUG_REC(CURRENTBEACONINTERVAL,WORDS),
- DEBUG_REC(CURRENTSCALETHRESHOLDS,WORDS),
- DEBUG_REC(PROTOCOLRSPTIME,WORDS),
- DEBUG_REC(SHORTRETRYLIMIT,WORDS),
- DEBUG_REC(LONGRETRYLIMIT,WORDS),
- DEBUG_REC(MAXTRANSMITLIFETIME,WORDS),
- DEBUG_REC(MAXRECEIVELIFETIME,WORDS),
- DEBUG_REC(CFPOLLABLE,WORDS),
- DEBUG_REC(AUTHENTICATIONALGORITHMS,WORDS),
- DEBUG_REC(PRIVACYOPTIONIMPLEMENTED,WORDS),
- DEBUG_REC(OWNMACADDR,BYTES),
- DEBUG_REC(SCANRESULTSTABLE,WORDS),
- DEBUG_REC(PHYTYPE,WORDS),
- DEBUG_REC(CURRENTCHANNEL,WORDS),
- DEBUG_REC(CURRENTPOWERSTATE,WORDS),
- DEBUG_REC(CCAMODE,WORDS),
- DEBUG_REC(SUPPORTEDDATARATES,WORDS),
- DEBUG_REC(BUILDSEQ,BYTES),
- DEBUG_REC(FWID,XSTRING)
-#undef DEBUG_REC
-};
-
-#define DEBUG_LTV_SIZE 128
-
-static int orinoco_debug_dump_recs(struct net_device *dev)
-{
- struct orinoco_private *priv = netdev_priv(dev);
- hermes_t *hw = &priv->hw;
- u8 *val8;
- u16 *val16;
- int i,j;
- u16 length;
- int err;
-
- /* I'm not sure: we might have a lock here, so we'd better go
- atomic, just in case. */
- val8 = kmalloc(DEBUG_LTV_SIZE + 2, GFP_ATOMIC);
- if (! val8)
- return -ENOMEM;
- val16 = (u16 *)val8;
-
- for (i = 0; i < ARRAY_SIZE(record_table); i++) {
- u16 rid = record_table[i].rid;
- int len;
-
- memset(val8, 0, DEBUG_LTV_SIZE + 2);
-
- err = hermes_read_ltv(hw, USER_BAP, rid, DEBUG_LTV_SIZE,
- &length, val8);
- if (err) {
- DEBUG(0, "Error %d reading RID 0x%04x\n", err, rid);
- continue;
- }
- val16 = (u16 *)val8;
- if (length == 0)
- continue;
-
- printk(KERN_DEBUG "%-15s (0x%04x): length=%d (%d bytes)\tvalue=",
- record_table[i].name,
- rid, length, (length-1)*2);
- len = min(((int)length-1)*2, DEBUG_LTV_SIZE);
-
- switch (record_table[i].displaytype) {
- case DISPLAY_WORDS:
- for (j = 0; j < len / 2; j++)
- printk("%04X-", le16_to_cpu(val16[j]));
- break;
-
- case DISPLAY_BYTES:
- default:
- for (j = 0; j < len; j++)
- printk("%02X:", val8[j]);
- break;
-
- case DISPLAY_STRING:
- len = min(len, le16_to_cpu(val16[0])+2);
- val8[len] = '\0';
- printk("\"%s\"", (char *)&val16[1]);
- break;
-
- case DISPLAY_XSTRING:
- printk("'%s'", (char *)val8);
- }
-
- printk("\n");
- }
-
- kfree(val8);
-
- return 0;
-}
/********************************************************************/
/* Debugging */
@@ -4218,7 +4025,6 @@ EXPORT_SYMBOL(free_orinocodev);
EXPORT_SYMBOL(__orinoco_up);
EXPORT_SYMBOL(__orinoco_down);
-EXPORT_SYMBOL(orinoco_stop);
EXPORT_SYMBOL(orinoco_reinit_firmware);
EXPORT_SYMBOL(orinoco_interrupt);
diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h
index 13e42c2afb2..f749b50d108 100644
--- a/drivers/net/wireless/orinoco.h
+++ b/drivers/net/wireless/orinoco.h
@@ -119,7 +119,6 @@ extern struct net_device *alloc_orinocodev(int sizeof_card,
extern void free_orinocodev(struct net_device *dev);
extern int __orinoco_up(struct net_device *dev);
extern int __orinoco_down(struct net_device *dev);
-extern int orinoco_stop(struct net_device *dev);
extern int orinoco_reinit_firmware(struct net_device *dev);
extern irqreturn_t orinoco_interrupt(int irq, void * dev_id, struct pt_regs *regs);
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index ec8cf29ffce..6c42b573a95 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -2828,7 +2828,7 @@ static void __exit strip_exit_driver(void)
/* Unregister with the /proc/net file here. */
proc_net_remove("strip");
- if ((i = tty_register_ldisc(N_STRIP, NULL)))
+ if ((i = tty_unregister_ldisc(N_STRIP)))
printk(KERN_ERR "STRIP: can't unregister line discipline (err = %d)\n", i);
printk(signoff);
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
index 55720dc6ec4..531b0731314 100644
--- a/drivers/oprofile/buffer_sync.c
+++ b/drivers/oprofile/buffer_sync.c
@@ -62,7 +62,7 @@ static int task_exit_notify(struct notifier_block * self, unsigned long val, voi
/* To avoid latency problems, we only process the current CPU,
* hoping that most samples for the task are on this CPU
*/
- sync_buffer(_smp_processor_id());
+ sync_buffer(raw_smp_processor_id());
return 0;
}
@@ -86,7 +86,7 @@ static int munmap_notify(struct notifier_block * self, unsigned long val, void *
/* To avoid latency problems, we only process the current CPU,
* hoping that most samples for the task are on this CPU
*/
- sync_buffer(_smp_processor_id());
+ sync_buffer(raw_smp_processor_id());
return 0;
}
@@ -206,7 +206,7 @@ static inline unsigned long fast_get_dcookie(struct dentry * dentry,
*/
static unsigned long get_exec_dcookie(struct mm_struct * mm)
{
- unsigned long cookie = 0;
+ unsigned long cookie = NO_COOKIE;
struct vm_area_struct * vma;
if (!mm)
@@ -234,35 +234,42 @@ out:
*/
static unsigned long lookup_dcookie(struct mm_struct * mm, unsigned long addr, off_t * offset)
{
- unsigned long cookie = 0;
+ unsigned long cookie = NO_COOKIE;
struct vm_area_struct * vma;
for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) {
- if (!vma->vm_file)
- continue;
-
if (addr < vma->vm_start || addr >= vma->vm_end)
continue;
- cookie = fast_get_dcookie(vma->vm_file->f_dentry,
- vma->vm_file->f_vfsmnt);
- *offset = (vma->vm_pgoff << PAGE_SHIFT) + addr - vma->vm_start;
+ if (vma->vm_file) {
+ cookie = fast_get_dcookie(vma->vm_file->f_dentry,
+ vma->vm_file->f_vfsmnt);
+ *offset = (vma->vm_pgoff << PAGE_SHIFT) + addr -
+ vma->vm_start;
+ } else {
+ /* must be an anonymous map */
+ *offset = addr;
+ }
+
break;
}
+ if (!vma)
+ cookie = INVALID_COOKIE;
+
return cookie;
}
-static unsigned long last_cookie = ~0UL;
+static unsigned long last_cookie = INVALID_COOKIE;
static void add_cpu_switch(int i)
{
add_event_entry(ESCAPE_CODE);
add_event_entry(CPU_SWITCH_CODE);
add_event_entry(i);
- last_cookie = ~0UL;
+ last_cookie = INVALID_COOKIE;
}
static void add_kernel_ctx_switch(unsigned int in_kernel)
@@ -317,7 +324,7 @@ static int add_us_sample(struct mm_struct * mm, struct op_sample * s)
cookie = lookup_dcookie(mm, s->eip, &offset);
- if (!cookie) {
+ if (cookie == INVALID_COOKIE) {
atomic_inc(&oprofile_stats.sample_lost_no_mapping);
return 0;
}
diff --git a/drivers/oprofile/event_buffer.h b/drivers/oprofile/event_buffer.h
index 442aaad391e..01802363059 100644
--- a/drivers/oprofile/event_buffer.h
+++ b/drivers/oprofile/event_buffer.h
@@ -35,6 +35,9 @@ void wake_up_buffer_waiter(void);
#define TRACE_BEGIN_CODE 8
#define TRACE_END_CODE 9
+#define INVALID_COOKIE ~0UL
+#define NO_COOKIE 0UL
+
/* add data to the event buffer */
void add_event_entry(unsigned long data);
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index e7f3bcb7900..80edfa3abd2 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -2751,7 +2751,6 @@ enum parport_pc_pci_cards {
netmos_9755,
netmos_9805,
netmos_9815,
- netmos_9855,
};
@@ -2826,7 +2825,6 @@ static struct parport_pc_pci {
/* netmos_9755 */ { 2, { { 0, 1 }, { 2, 3 },} }, /* untested */
/* netmos_9805 */ { 1, { { 0, -1 }, } }, /* untested */
/* netmos_9815 */ { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */
- /* netmos_9855 */ { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */
};
static struct pci_device_id parport_pc_pci_tbl[] = {
@@ -2907,8 +2905,6 @@ static struct pci_device_id parport_pc_pci_tbl[] = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9805 },
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9815,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 },
- { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9855 },
{ 0, } /* terminate list */
};
MODULE_DEVICE_TABLE(pci,parport_pc_pci_tbl);
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index 6715a17b5d0..00498e2f120 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -34,6 +34,7 @@ enum parport_pc_pci_cards {
titan_110l = 0,
titan_210l,
netmos_9xx5_combo,
+ netmos_9855,
avlab_1s1p,
avlab_1s1p_650,
avlab_1s1p_850,
@@ -87,6 +88,7 @@ static struct parport_pc_pci cards[] __devinitdata = {
/* titan_110l */ { 1, { { 3, -1 }, } },
/* titan_210l */ { 1, { { 3, -1 }, } },
/* netmos_9xx5_combo */ { 1, { { 2, -1 }, }, netmos_parallel_init },
+ /* netmos_9855 */ { 1, { { 0, -1 }, }, netmos_parallel_init },
/* avlab_1s1p */ { 1, { { 1, 2}, } },
/* avlab_1s1p_650 */ { 1, { { 1, 2}, } },
/* avlab_1s1p_850 */ { 1, { { 1, 2}, } },
@@ -120,7 +122,7 @@ static struct pci_device_id parport_serial_pci_tbl[] = {
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9845,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9855 },
/* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/
{ 0x14db, 0x2110, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p},
{ 0x14db, 0x2111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p_650},
@@ -207,6 +209,7 @@ static struct pci_board_no_ids pci_boards[] __devinitdata = {
/* titan_110l */ { SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 1, 921600 },
/* titan_210l */ { SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 },
/* netmos_9xx5_combo */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200, 0, 0, netmos_serial_init },
+/* netmos_9855 */ { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 1, 115200, 0, 0, netmos_serial_init },
/* avlab_1s1p (n/t) */ { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
/* avlab_1s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
/* avlab_1s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
diff --git a/drivers/parport/probe.c b/drivers/parport/probe.c
index c94963145e1..6e6f42d01e6 100644
--- a/drivers/parport/probe.c
+++ b/drivers/parport/probe.c
@@ -48,14 +48,6 @@ static void pretty_print(struct parport *port, int device)
printk("\n");
}
-static char *strdup(char *str)
-{
- int n = strlen(str)+1;
- char *s = kmalloc(n, GFP_KERNEL);
- if (!s) return NULL;
- return strcpy(s, str);
-}
-
static void parse_data(struct parport *port, int device, char *str)
{
char *txt = kmalloc(strlen(str)+1, GFP_KERNEL);
@@ -88,16 +80,16 @@ static void parse_data(struct parport *port, int device, char *str)
if (!strcmp(p, "MFG") || !strcmp(p, "MANUFACTURER")) {
if (info->mfr)
kfree (info->mfr);
- info->mfr = strdup(sep);
+ info->mfr = kstrdup(sep, GFP_KERNEL);
} else if (!strcmp(p, "MDL") || !strcmp(p, "MODEL")) {
if (info->model)
kfree (info->model);
- info->model = strdup(sep);
+ info->model = kstrdup(sep, GFP_KERNEL);
} else if (!strcmp(p, "CLS") || !strcmp(p, "CLASS")) {
int i;
if (info->class_name)
kfree (info->class_name);
- info->class_name = strdup(sep);
+ info->class_name = kstrdup(sep, GFP_KERNEL);
for (u = sep; *u; u++)
*u = toupper(*u);
for (i = 0; classes[i].token; i++) {
@@ -112,7 +104,7 @@ static void parse_data(struct parport *port, int device, char *str)
!strcmp(p, "COMMAND SET")) {
if (info->cmdset)
kfree (info->cmdset);
- info->cmdset = strdup(sep);
+ info->cmdset = kstrdup(sep, GFP_KERNEL);
/* if it speaks printer language, it's
probably a printer */
if (strstr(sep, "PJL") || strstr(sep, "PCL"))
@@ -120,7 +112,7 @@ static void parse_data(struct parport *port, int device, char *str)
} else if (!strcmp(p, "DES") || !strcmp(p, "DESCRIPTION")) {
if (info->description)
kfree (info->description);
- info->description = strdup(sep);
+ info->description = kstrdup(sep, GFP_KERNEL);
}
}
rock_on:
diff --git a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c
index 021d0f76bc4..3903f8c559b 100644
--- a/drivers/pci/hotplug.c
+++ b/drivers/pci/hotplug.c
@@ -52,116 +52,17 @@ int pci_hotplug (struct device *dev, char **envp, int num_envp,
if ((buffer_size - length <= 0) || (i >= num_envp))
return -ENOMEM;
+ envp[i++] = scratch;
+ length += scnprintf (scratch, buffer_size - length,
+ "MODALIAS=pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x\n",
+ pdev->vendor, pdev->device,
+ pdev->subsystem_vendor, pdev->subsystem_device,
+ (u8)(pdev->class >> 16), (u8)(pdev->class >> 8),
+ (u8)(pdev->class));
+ if ((buffer_size - length <= 0) || (i >= num_envp))
+ return -ENOMEM;
+
envp[i] = NULL;
return 0;
}
-
-static int pci_visit_bus (struct pci_visit * fn, struct pci_bus_wrapped *wrapped_bus, struct pci_dev_wrapped *wrapped_parent)
-{
- struct list_head *ln;
- struct pci_dev *dev;
- struct pci_dev_wrapped wrapped_dev;
- int result = 0;
-
- pr_debug("PCI: Scanning bus %04x:%02x\n", pci_domain_nr(wrapped_bus->bus),
- wrapped_bus->bus->number);
-
- if (fn->pre_visit_pci_bus) {
- result = fn->pre_visit_pci_bus(wrapped_bus, wrapped_parent);
- if (result)
- return result;
- }
-
- ln = wrapped_bus->bus->devices.next;
- while (ln != &wrapped_bus->bus->devices) {
- dev = pci_dev_b(ln);
- ln = ln->next;
-
- memset(&wrapped_dev, 0, sizeof(struct pci_dev_wrapped));
- wrapped_dev.dev = dev;
-
- result = pci_visit_dev(fn, &wrapped_dev, wrapped_bus);
- if (result)
- return result;
- }
-
- if (fn->post_visit_pci_bus)
- result = fn->post_visit_pci_bus(wrapped_bus, wrapped_parent);
-
- return result;
-}
-
-static int pci_visit_bridge (struct pci_visit * fn,
- struct pci_dev_wrapped *wrapped_dev,
- struct pci_bus_wrapped *wrapped_parent)
-{
- struct pci_bus *bus;
- struct pci_bus_wrapped wrapped_bus;
- int result = 0;
-
- pr_debug("PCI: Scanning bridge %s\n", pci_name(wrapped_dev->dev));
-
- if (fn->visit_pci_dev) {
- result = fn->visit_pci_dev(wrapped_dev, wrapped_parent);
- if (result)
- return result;
- }
-
- bus = wrapped_dev->dev->subordinate;
- if (bus) {
- memset(&wrapped_bus, 0, sizeof(struct pci_bus_wrapped));
- wrapped_bus.bus = bus;
-
- result = pci_visit_bus(fn, &wrapped_bus, wrapped_dev);
- }
- return result;
-}
-
-/**
- * pci_visit_dev - scans the pci buses.
- * @fn: callback functions that are called while visiting
- * @wrapped_dev: the device to scan
- * @wrapped_parent: the bus where @wrapped_dev is connected to
- *
- * Every bus and every function is presented to a custom
- * function that can act upon it.
- */
-int pci_visit_dev(struct pci_visit *fn, struct pci_dev_wrapped *wrapped_dev,
- struct pci_bus_wrapped *wrapped_parent)
-{
- struct pci_dev* dev = wrapped_dev ? wrapped_dev->dev : NULL;
- int result = 0;
-
- if (!dev)
- return 0;
-
- if (fn->pre_visit_pci_dev) {
- result = fn->pre_visit_pci_dev(wrapped_dev, wrapped_parent);
- if (result)
- return result;
- }
-
- switch (dev->class >> 8) {
- case PCI_CLASS_BRIDGE_PCI:
- result = pci_visit_bridge(fn, wrapped_dev,
- wrapped_parent);
- if (result)
- return result;
- break;
- default:
- pr_debug("PCI: Scanning device %s\n", pci_name(dev));
- if (fn->visit_pci_dev) {
- result = fn->visit_pci_dev (wrapped_dev,
- wrapped_parent);
- if (result)
- return result;
- }
- }
-
- if (fn->post_visit_pci_dev)
- result = fn->post_visit_pci_dev(wrapped_dev, wrapped_parent);
-
- return result;
-}
-EXPORT_SYMBOL(pci_visit_dev);
diff --git a/drivers/pci/hotplug/cpci_hotplug.h b/drivers/pci/hotplug/cpci_hotplug.h
index 3ddd75937a4..d9769b30be9 100644
--- a/drivers/pci/hotplug/cpci_hotplug.h
+++ b/drivers/pci/hotplug/cpci_hotplug.h
@@ -31,7 +31,7 @@
#include <linux/types.h>
#include <linux/pci.h>
-/* PICMG 2.12 R2.0 HS CSR bits: */
+/* PICMG 2.1 R2.0 HS CSR bits: */
#define HS_CSR_INS 0x0080
#define HS_CSR_EXT 0x0040
#define HS_CSR_PI 0x0030
diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c
index ed243605dc7..30af105271a 100644
--- a/drivers/pci/hotplug/cpci_hotplug_core.c
+++ b/drivers/pci/hotplug/cpci_hotplug_core.c
@@ -1,7 +1,7 @@
/*
* CompactPCI Hot Plug Driver
*
- * Copyright (C) 2002 SOMA Networks, Inc.
+ * Copyright (C) 2002,2005 SOMA Networks, Inc.
* Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
* Copyright (C) 2001 IBM Corp.
*
@@ -33,11 +33,11 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/smp_lock.h>
+#include <asm/atomic.h>
#include <linux/delay.h>
#include "pci_hotplug.h"
#include "cpci_hotplug.h"
-#define DRIVER_VERSION "0.2"
#define DRIVER_AUTHOR "Scott Murray <scottm@somanetworks.com>"
#define DRIVER_DESC "CompactPCI Hot Plug Core"
@@ -45,18 +45,19 @@
#define dbg(format, arg...) \
do { \
- if(cpci_debug) \
+ if (cpci_debug) \
printk (KERN_DEBUG "%s: " format "\n", \
MY_NAME , ## arg); \
- } while(0)
+ } while (0)
#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
/* local variables */
-static spinlock_t list_lock;
+static DECLARE_RWSEM(list_rwsem);
static LIST_HEAD(slot_list);
static int slots;
+static atomic_t extracting;
int cpci_debug;
static struct cpci_hp_controller *controller;
static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */
@@ -68,6 +69,8 @@ static int disable_slot(struct hotplug_slot *slot);
static int set_attention_status(struct hotplug_slot *slot, u8 value);
static int get_power_status(struct hotplug_slot *slot, u8 * value);
static int get_attention_status(struct hotplug_slot *slot, u8 * value);
+static int get_adapter_status(struct hotplug_slot *slot, u8 * value);
+static int get_latch_status(struct hotplug_slot *slot, u8 * value);
static struct hotplug_slot_ops cpci_hotplug_slot_ops = {
.owner = THIS_MODULE,
@@ -76,6 +79,8 @@ static struct hotplug_slot_ops cpci_hotplug_slot_ops = {
.set_attention_status = set_attention_status,
.get_power_status = get_power_status,
.get_attention_status = get_attention_status,
+ .get_adapter_status = get_adapter_status,
+ .get_latch_status = get_latch_status,
};
static int
@@ -106,10 +111,8 @@ enable_slot(struct hotplug_slot *hotplug_slot)
dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name);
- if(controller->ops->set_power) {
+ if (controller->ops->set_power)
retval = controller->ops->set_power(slot, 1);
- }
-
return retval;
}
@@ -121,35 +124,41 @@ disable_slot(struct hotplug_slot *hotplug_slot)
dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name);
+ down_write(&list_rwsem);
+
/* Unconfigure device */
dbg("%s - unconfiguring slot %s",
__FUNCTION__, slot->hotplug_slot->name);
- if((retval = cpci_unconfigure_slot(slot))) {
+ if ((retval = cpci_unconfigure_slot(slot))) {
err("%s - could not unconfigure slot %s",
__FUNCTION__, slot->hotplug_slot->name);
- return retval;
+ goto disable_error;
}
dbg("%s - finished unconfiguring slot %s",
__FUNCTION__, slot->hotplug_slot->name);
/* Clear EXT (by setting it) */
- if(cpci_clear_ext(slot)) {
+ if (cpci_clear_ext(slot)) {
err("%s - could not clear EXT for slot %s",
__FUNCTION__, slot->hotplug_slot->name);
retval = -ENODEV;
+ goto disable_error;
}
cpci_led_on(slot);
- if(controller->ops->set_power) {
- retval = controller->ops->set_power(slot, 0);
- }
+ if (controller->ops->set_power)
+ if ((retval = controller->ops->set_power(slot, 0)))
+ goto disable_error;
- if(update_adapter_status(slot->hotplug_slot, 0)) {
+ if (update_adapter_status(slot->hotplug_slot, 0))
warn("failure to update adapter file");
- }
-
- slot->extracting = 0;
+ if (slot->extracting) {
+ slot->extracting = 0;
+ atomic_dec(&extracting);
+ }
+disable_error:
+ up_write(&list_rwsem);
return retval;
}
@@ -158,9 +167,8 @@ cpci_get_power_status(struct slot *slot)
{
u8 power = 1;
- if(controller->ops->get_power) {
+ if (controller->ops->get_power)
power = controller->ops->get_power(slot);
- }
return power;
}
@@ -188,6 +196,20 @@ set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
return cpci_set_attention_status(hotplug_slot->private, status);
}
+static int
+get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value)
+{
+ *value = hotplug_slot->info->adapter_status;
+ return 0;
+}
+
+static int
+get_latch_status(struct hotplug_slot *hotplug_slot, u8 * value)
+{
+ *value = hotplug_slot->info->latch_status;
+ return 0;
+}
+
static void release_slot(struct hotplug_slot *hotplug_slot)
{
struct slot *slot = hotplug_slot->private;
@@ -195,6 +217,8 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
kfree(slot->hotplug_slot->info);
kfree(slot->hotplug_slot->name);
kfree(slot->hotplug_slot);
+ if (slot->dev)
+ pci_dev_put(slot->dev);
kfree(slot);
}
@@ -216,9 +240,8 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
int status = -ENOMEM;
int i;
- if(!(controller && bus)) {
+ if (!(controller && bus))
return -ENODEV;
- }
/*
* Create a structure for each slot, and register that slot
@@ -273,10 +296,10 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
}
/* Add slot to our internal list */
- spin_lock(&list_lock);
+ down_write(&list_rwsem);
list_add(&slot->slot_list, &slot_list);
slots++;
- spin_unlock(&list_lock);
+ up_write(&list_rwsem);
}
return 0;
error_name:
@@ -295,32 +318,30 @@ int
cpci_hp_unregister_bus(struct pci_bus *bus)
{
struct slot *slot;
- struct list_head *tmp;
- struct list_head *next;
- int status;
+ struct slot *tmp;
+ int status = 0;
- spin_lock(&list_lock);
- if(!slots) {
- spin_unlock(&list_lock);
+ down_write(&list_rwsem);
+ if (!slots) {
+ up_write(&list_rwsem);
return -1;
}
- list_for_each_safe(tmp, next, &slot_list) {
- slot = list_entry(tmp, struct slot, slot_list);
- if(slot->bus == bus) {
+ list_for_each_entry_safe(slot, tmp, &slot_list, slot_list) {
+ if (slot->bus == bus) {
+ list_del(&slot->slot_list);
+ slots--;
+
dbg("deregistering slot %s", slot->hotplug_slot->name);
status = pci_hp_deregister(slot->hotplug_slot);
- if(status) {
+ if (status) {
err("pci_hp_deregister failed with error %d",
status);
- return status;
+ break;
}
-
- list_del(&slot->slot_list);
- slots--;
}
}
- spin_unlock(&list_lock);
- return 0;
+ up_write(&list_rwsem);
+ return status;
}
/* This is the interrupt mode interrupt handler */
@@ -330,7 +351,7 @@ cpci_hp_intr(int irq, void *data, struct pt_regs *regs)
dbg("entered cpci_hp_intr");
/* Check to see if it was our interrupt */
- if((controller->irq_flags & SA_SHIRQ) &&
+ if ((controller->irq_flags & SA_SHIRQ) &&
!controller->ops->check_irq(controller->dev_id)) {
dbg("exited cpci_hp_intr, not our interrupt");
return IRQ_NONE;
@@ -347,46 +368,38 @@ cpci_hp_intr(int irq, void *data, struct pt_regs *regs)
}
/*
- * According to PICMG 2.12 R2.0, section 6.3.2, upon
+ * According to PICMG 2.1 R2.0, section 6.3.2, upon
* initialization, the system driver shall clear the
* INS bits of the cold-inserted devices.
*/
static int
-init_slots(void)
+init_slots(int clear_ins)
{
struct slot *slot;
- struct list_head *tmp;
struct pci_dev* dev;
dbg("%s - enter", __FUNCTION__);
- spin_lock(&list_lock);
- if(!slots) {
- spin_unlock(&list_lock);
+ down_read(&list_rwsem);
+ if (!slots) {
+ up_read(&list_rwsem);
return -1;
}
- list_for_each(tmp, &slot_list) {
- slot = list_entry(tmp, struct slot, slot_list);
+ list_for_each_entry(slot, &slot_list, slot_list) {
dbg("%s - looking at slot %s",
__FUNCTION__, slot->hotplug_slot->name);
- if(cpci_check_and_clear_ins(slot)) {
+ if (clear_ins && cpci_check_and_clear_ins(slot))
dbg("%s - cleared INS for slot %s",
__FUNCTION__, slot->hotplug_slot->name);
- dev = pci_find_slot(slot->bus->number, PCI_DEVFN(slot->number, 0));
- if(dev) {
- if(update_adapter_status(slot->hotplug_slot, 1)) {
- warn("failure to update adapter file");
- }
- if(update_latch_status(slot->hotplug_slot, 1)) {
- warn("failure to update latch file");
- }
- slot->dev = dev;
- } else {
- err("%s - no driver attached to device in slot %s",
- __FUNCTION__, slot->hotplug_slot->name);
- }
+ dev = pci_get_slot(slot->bus, PCI_DEVFN(slot->number, 0));
+ if (dev) {
+ if (update_adapter_status(slot->hotplug_slot, 1))
+ warn("failure to update adapter file");
+ if (update_latch_status(slot->hotplug_slot, 1))
+ warn("failure to update latch file");
+ slot->dev = dev;
}
}
- spin_unlock(&list_lock);
+ up_read(&list_rwsem);
dbg("%s - exit", __FUNCTION__);
return 0;
}
@@ -395,27 +408,28 @@ static int
check_slots(void)
{
struct slot *slot;
- struct list_head *tmp;
int extracted;
int inserted;
+ u16 hs_csr;
- spin_lock(&list_lock);
- if(!slots) {
- spin_unlock(&list_lock);
+ down_read(&list_rwsem);
+ if (!slots) {
+ up_read(&list_rwsem);
err("no slots registered, shutting down");
return -1;
}
extracted = inserted = 0;
- list_for_each(tmp, &slot_list) {
- slot = list_entry(tmp, struct slot, slot_list);
+ list_for_each_entry(slot, &slot_list, slot_list) {
dbg("%s - looking at slot %s",
__FUNCTION__, slot->hotplug_slot->name);
- if(cpci_check_and_clear_ins(slot)) {
- u16 hs_csr;
-
- /* Some broken hardware (e.g. PLX 9054AB) asserts ENUM# twice... */
- if(slot->dev) {
- warn("slot %s already inserted", slot->hotplug_slot->name);
+ if (cpci_check_and_clear_ins(slot)) {
+ /*
+ * Some broken hardware (e.g. PLX 9054AB) asserts
+ * ENUM# twice...
+ */
+ if (slot->dev) {
+ warn("slot %s already inserted",
+ slot->hotplug_slot->name);
inserted++;
continue;
}
@@ -432,7 +446,7 @@ check_slots(void)
/* Configure device */
dbg("%s - configuring slot %s",
__FUNCTION__, slot->hotplug_slot->name);
- if(cpci_configure_slot(slot)) {
+ if (cpci_configure_slot(slot)) {
err("%s - could not configure slot %s",
__FUNCTION__, slot->hotplug_slot->name);
continue;
@@ -445,13 +459,11 @@ check_slots(void)
dbg("%s - slot %s HS_CSR (2) = %04x",
__FUNCTION__, slot->hotplug_slot->name, hs_csr);
- if(update_latch_status(slot->hotplug_slot, 1)) {
+ if (update_latch_status(slot->hotplug_slot, 1))
warn("failure to update latch file");
- }
- if(update_adapter_status(slot->hotplug_slot, 1)) {
+ if (update_adapter_status(slot->hotplug_slot, 1))
warn("failure to update adapter file");
- }
cpci_led_off(slot);
@@ -461,9 +473,7 @@ check_slots(void)
__FUNCTION__, slot->hotplug_slot->name, hs_csr);
inserted++;
- } else if(cpci_check_ext(slot)) {
- u16 hs_csr;
-
+ } else if (cpci_check_ext(slot)) {
/* Process extraction request */
dbg("%s - slot %s extracted",
__FUNCTION__, slot->hotplug_slot->name);
@@ -473,23 +483,40 @@ check_slots(void)
dbg("%s - slot %s HS_CSR = %04x",
__FUNCTION__, slot->hotplug_slot->name, hs_csr);
- if(!slot->extracting) {
- if(update_latch_status(slot->hotplug_slot, 0)) {
+ if (!slot->extracting) {
+ if (update_latch_status(slot->hotplug_slot, 0)) {
warn("failure to update latch file");
}
slot->extracting = 1;
+ atomic_inc(&extracting);
}
extracted++;
+ } else if (slot->extracting) {
+ hs_csr = cpci_get_hs_csr(slot);
+ if (hs_csr == 0xffff) {
+ /*
+ * Hmmm, we're likely hosed at this point, should we
+ * bother trying to tell the driver or not?
+ */
+ err("card in slot %s was improperly removed",
+ slot->hotplug_slot->name);
+ if (update_adapter_status(slot->hotplug_slot, 0))
+ warn("failure to update adapter file");
+ slot->extracting = 0;
+ atomic_dec(&extracting);
+ }
}
}
- spin_unlock(&list_lock);
- if(inserted || extracted) {
+ up_read(&list_rwsem);
+ dbg("inserted=%d, extracted=%d, extracting=%d",
+ inserted, extracted, atomic_read(&extracting));
+ if (inserted || extracted)
return extracted;
- }
- else {
+ else if (!atomic_read(&extracting)) {
err("cannot find ENUM# source, shutting down");
return -1;
}
+ return 0;
}
/* This is the interrupt mode worker thread body */
@@ -497,54 +524,37 @@ static int
event_thread(void *data)
{
int rc;
- struct slot *slot;
- struct list_head *tmp;
lock_kernel();
daemonize("cpci_hp_eventd");
unlock_kernel();
dbg("%s - event thread started", __FUNCTION__);
- while(1) {
+ while (1) {
dbg("event thread sleeping");
down_interruptible(&event_semaphore);
dbg("event thread woken, thread_finished = %d",
thread_finished);
- if(thread_finished || signal_pending(current))
+ if (thread_finished || signal_pending(current))
break;
- while(controller->ops->query_enum()) {
+ do {
rc = check_slots();
- if (rc > 0)
+ if (rc > 0) {
/* Give userspace a chance to handle extraction */
msleep(500);
- else if (rc < 0) {
+ } else if (rc < 0) {
dbg("%s - error checking slots", __FUNCTION__);
thread_finished = 1;
break;
}
- }
- /* Check for someone yanking out a board */
- list_for_each(tmp, &slot_list) {
- slot = list_entry(tmp, struct slot, slot_list);
- if(slot->extracting) {
- /*
- * Hmmm, we're likely hosed at this point, should we
- * bother trying to tell the driver or not?
- */
- err("card in slot %s was improperly removed",
- slot->hotplug_slot->name);
- if(update_adapter_status(slot->hotplug_slot, 0)) {
- warn("failure to update adapter file");
- }
- slot->extracting = 0;
- }
- }
+ } while (atomic_read(&extracting) && !thread_finished);
+ if (thread_finished)
+ break;
/* Re-enable ENUM# interrupt */
dbg("%s - re-enabling irq", __FUNCTION__);
controller->ops->enable_irq();
}
-
dbg("%s - event thread signals exit", __FUNCTION__);
up(&thread_exit);
return 0;
@@ -555,45 +565,27 @@ static int
poll_thread(void *data)
{
int rc;
- struct slot *slot;
- struct list_head *tmp;
lock_kernel();
daemonize("cpci_hp_polld");
unlock_kernel();
- while(1) {
- if(thread_finished || signal_pending(current))
+ while (1) {
+ if (thread_finished || signal_pending(current))
break;
-
- while(controller->ops->query_enum()) {
- rc = check_slots();
- if(rc > 0)
- /* Give userspace a chance to handle extraction */
- msleep(500);
- else if (rc < 0) {
- dbg("%s - error checking slots", __FUNCTION__);
- thread_finished = 1;
- break;
- }
- }
- /* Check for someone yanking out a board */
- list_for_each(tmp, &slot_list) {
- slot = list_entry(tmp, struct slot, slot_list);
- if(slot->extracting) {
- /*
- * Hmmm, we're likely hosed at this point, should we
- * bother trying to tell the driver or not?
- */
- err("card in slot %s was improperly removed",
- slot->hotplug_slot->name);
- if(update_adapter_status(slot->hotplug_slot, 0)) {
- warn("failure to update adapter file");
+ if (controller->ops->query_enum()) {
+ do {
+ rc = check_slots();
+ if (rc > 0) {
+ /* Give userspace a chance to handle extraction */
+ msleep(500);
+ } else if (rc < 0) {
+ dbg("%s - error checking slots", __FUNCTION__);
+ thread_finished = 1;
+ break;
}
- slot->extracting = 0;
- }
+ } while (atomic_read(&extracting) && !thread_finished);
}
-
msleep(100);
}
dbg("poll thread signals exit");
@@ -611,12 +603,11 @@ cpci_start_thread(void)
init_MUTEX_LOCKED(&thread_exit);
thread_finished = 0;
- if(controller->irq) {
+ if (controller->irq)
pid = kernel_thread(event_thread, NULL, 0);
- } else {
+ else
pid = kernel_thread(poll_thread, NULL, 0);
- }
- if(pid < 0) {
+ if (pid < 0) {
err("Can't start up our thread");
return -1;
}
@@ -629,9 +620,8 @@ cpci_stop_thread(void)
{
thread_finished = 1;
dbg("thread finish command given");
- if(controller->irq) {
+ if (controller->irq)
up(&event_semaphore);
- }
dbg("wait for thread to exit");
down(&thread_exit);
}
@@ -641,42 +631,67 @@ cpci_hp_register_controller(struct cpci_hp_controller *new_controller)
{
int status = 0;
- if(!controller) {
- controller = new_controller;
- if(controller->irq) {
- if(request_irq(controller->irq,
- cpci_hp_intr,
- controller->irq_flags,
- MY_NAME, controller->dev_id)) {
- err("Can't get irq %d for the hotplug cPCI controller", controller->irq);
- status = -ENODEV;
- }
- dbg("%s - acquired controller irq %d", __FUNCTION__,
- controller->irq);
+ if (controller)
+ return -1;
+ if (!(new_controller && new_controller->ops))
+ return -EINVAL;
+ if (new_controller->irq) {
+ if (!(new_controller->ops->enable_irq &&
+ new_controller->ops->disable_irq))
+ status = -EINVAL;
+ if (request_irq(new_controller->irq,
+ cpci_hp_intr,
+ new_controller->irq_flags,
+ MY_NAME,
+ new_controller->dev_id)) {
+ err("Can't get irq %d for the hotplug cPCI controller",
+ new_controller->irq);
+ status = -ENODEV;
}
- } else {
- err("cPCI hotplug controller already registered");
- status = -1;
+ dbg("%s - acquired controller irq %d",
+ __FUNCTION__, new_controller->irq);
}
+ if (!status)
+ controller = new_controller;
return status;
}
+static void
+cleanup_slots(void)
+{
+ struct slot *slot;
+ struct slot *tmp;
+
+ /*
+ * Unregister all of our slots with the pci_hotplug subsystem,
+ * and free up all memory that we had allocated.
+ */
+ down_write(&list_rwsem);
+ if (!slots)
+ goto cleanup_null;
+ list_for_each_entry_safe(slot, tmp, &slot_list, slot_list) {
+ list_del(&slot->slot_list);
+ pci_hp_deregister(slot->hotplug_slot);
+ }
+cleanup_null:
+ up_write(&list_rwsem);
+ return;
+}
+
int
cpci_hp_unregister_controller(struct cpci_hp_controller *old_controller)
{
int status = 0;
- if(controller) {
- if(!thread_finished) {
+ if (controller) {
+ if (!thread_finished)
cpci_stop_thread();
- }
- if(controller->irq) {
+ if (controller->irq)
free_irq(controller->irq, controller->dev_id);
- }
controller = NULL;
- } else {
+ cleanup_slots();
+ } else
status = -ENODEV;
- }
return status;
}
@@ -687,32 +702,28 @@ cpci_hp_start(void)
int status;
dbg("%s - enter", __FUNCTION__);
- if(!controller) {
+ if (!controller)
return -ENODEV;
- }
- spin_lock(&list_lock);
- if(!slots) {
- spin_unlock(&list_lock);
+ down_read(&list_rwsem);
+ if (list_empty(&slot_list)) {
+ up_read(&list_rwsem);
return -ENODEV;
}
- spin_unlock(&list_lock);
+ up_read(&list_rwsem);
- if(first) {
- status = init_slots();
- if(status) {
- return status;
- }
+ status = init_slots(first);
+ if (first)
first = 0;
- }
+ if (status)
+ return status;
status = cpci_start_thread();
- if(status) {
+ if (status)
return status;
- }
dbg("%s - thread started", __FUNCTION__);
- if(controller->irq) {
+ if (controller->irq) {
/* Start enum interrupt processing */
dbg("%s - enabling irq", __FUNCTION__);
controller->ops->enable_irq();
@@ -724,11 +735,9 @@ cpci_hp_start(void)
int
cpci_hp_stop(void)
{
- if(!controller) {
+ if (!controller)
return -ENODEV;
- }
-
- if(controller->irq) {
+ if (controller->irq) {
/* Stop enum interrupt processing */
dbg("%s - disabling irq", __FUNCTION__);
controller->ops->disable_irq();
@@ -737,41 +746,10 @@ cpci_hp_stop(void)
return 0;
}
-static void __exit
-cleanup_slots(void)
-{
- struct list_head *tmp;
- struct slot *slot;
-
- /*
- * Unregister all of our slots with the pci_hotplug subsystem,
- * and free up all memory that we had allocated.
- */
- spin_lock(&list_lock);
- if(!slots) {
- goto null_cleanup;
- }
- list_for_each(tmp, &slot_list) {
- slot = list_entry(tmp, struct slot, slot_list);
- list_del(&slot->slot_list);
- pci_hp_deregister(slot->hotplug_slot);
- kfree(slot->hotplug_slot->info);
- kfree(slot->hotplug_slot->name);
- kfree(slot->hotplug_slot);
- kfree(slot);
- }
- null_cleanup:
- spin_unlock(&list_lock);
- return;
-}
-
int __init
cpci_hotplug_init(int debug)
{
- spin_lock_init(&list_lock);
cpci_debug = debug;
-
- info(DRIVER_DESC " version: " DRIVER_VERSION);
return 0;
}
@@ -781,7 +759,8 @@ cpci_hotplug_exit(void)
/*
* Clean everything up.
*/
- cleanup_slots();
+ cpci_hp_stop();
+ cpci_hp_unregister_controller(controller);
}
EXPORT_SYMBOL_GPL(cpci_hp_register_controller);
diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c
index 2e969616f29..225b5e551dd 100644
--- a/drivers/pci/hotplug/cpci_hotplug_pci.c
+++ b/drivers/pci/hotplug/cpci_hotplug_pci.c
@@ -1,7 +1,7 @@
/*
* CompactPCI Hot Plug Driver PCI functions
*
- * Copyright (C) 2002 by SOMA Networks, Inc.
+ * Copyright (C) 2002,2005 by SOMA Networks, Inc.
*
* All rights reserved.
*
@@ -32,20 +32,16 @@
#include "pci_hotplug.h"
#include "cpci_hotplug.h"
-#if !defined(MODULE)
#define MY_NAME "cpci_hotplug"
-#else
-#define MY_NAME THIS_MODULE->name
-#endif
extern int cpci_debug;
#define dbg(format, arg...) \
do { \
- if(cpci_debug) \
+ if (cpci_debug) \
printk (KERN_DEBUG "%s: " format "\n", \
MY_NAME , ## arg); \
- } while(0)
+ } while (0)
#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
@@ -61,16 +57,15 @@ u8 cpci_get_attention_status(struct slot* slot)
hs_cap = pci_bus_find_capability(slot->bus,
slot->devfn,
PCI_CAP_ID_CHSWP);
- if(!hs_cap) {
+ if (!hs_cap)
return 0;
- }
- if(pci_bus_read_config_word(slot->bus,
+ if (pci_bus_read_config_word(slot->bus,
slot->devfn,
hs_cap + 2,
- &hs_csr)) {
+ &hs_csr))
return 0;
- }
+
return hs_csr & 0x0008 ? 1 : 0;
}
@@ -82,27 +77,22 @@ int cpci_set_attention_status(struct slot* slot, int status)
hs_cap = pci_bus_find_capability(slot->bus,
slot->devfn,
PCI_CAP_ID_CHSWP);
- if(!hs_cap) {
+ if (!hs_cap)
return 0;
- }
-
- if(pci_bus_read_config_word(slot->bus,
+ if (pci_bus_read_config_word(slot->bus,
slot->devfn,
hs_cap + 2,
- &hs_csr)) {
+ &hs_csr))
return 0;
- }
- if(status) {
+ if (status)
hs_csr |= HS_CSR_LOO;
- } else {
+ else
hs_csr &= ~HS_CSR_LOO;
- }
- if(pci_bus_write_config_word(slot->bus,
+ if (pci_bus_write_config_word(slot->bus,
slot->devfn,
hs_cap + 2,
- hs_csr)) {
+ hs_csr))
return 0;
- }
return 1;
}
@@ -114,51 +104,16 @@ u16 cpci_get_hs_csr(struct slot* slot)
hs_cap = pci_bus_find_capability(slot->bus,
slot->devfn,
PCI_CAP_ID_CHSWP);
- if(!hs_cap) {
+ if (!hs_cap)
return 0xFFFF;
- }
-
- if(pci_bus_read_config_word(slot->bus,
+ if (pci_bus_read_config_word(slot->bus,
slot->devfn,
hs_cap + 2,
- &hs_csr)) {
+ &hs_csr))
return 0xFFFF;
- }
return hs_csr;
}
-#if 0
-u16 cpci_set_hs_csr(struct slot* slot, u16 hs_csr)
-{
- int hs_cap;
- u16 new_hs_csr;
-
- hs_cap = pci_bus_find_capability(slot->bus,
- slot->devfn,
- PCI_CAP_ID_CHSWP);
- if(!hs_cap) {
- return 0xFFFF;
- }
-
- /* Write out the new value */
- if(pci_bus_write_config_word(slot->bus,
- slot->devfn,
- hs_cap + 2,
- hs_csr)) {
- return 0xFFFF;
- }
-
- /* Read back what we just wrote out */
- if(pci_bus_read_config_word(slot->bus,
- slot->devfn,
- hs_cap + 2,
- &new_hs_csr)) {
- return 0xFFFF;
- }
- return new_hs_csr;
-}
-#endif
-
int cpci_check_and_clear_ins(struct slot* slot)
{
int hs_cap;
@@ -168,24 +123,22 @@ int cpci_check_and_clear_ins(struct slot* slot)
hs_cap = pci_bus_find_capability(slot->bus,
slot->devfn,
PCI_CAP_ID_CHSWP);
- if(!hs_cap) {
+ if (!hs_cap)
return 0;
- }
- if(pci_bus_read_config_word(slot->bus,
+ if (pci_bus_read_config_word(slot->bus,
slot->devfn,
hs_cap + 2,
- &hs_csr)) {
+ &hs_csr))
return 0;
- }
- if(hs_csr & HS_CSR_INS) {
+ if (hs_csr & HS_CSR_INS) {
/* Clear INS (by setting it) */
- if(pci_bus_write_config_word(slot->bus,
+ if (pci_bus_write_config_word(slot->bus,
slot->devfn,
hs_cap + 2,
- hs_csr)) {
+ hs_csr))
ins = 0;
- }
- ins = 1;
+ else
+ ins = 1;
}
return ins;
}
@@ -199,18 +152,15 @@ int cpci_check_ext(struct slot* slot)
hs_cap = pci_bus_find_capability(slot->bus,
slot->devfn,
PCI_CAP_ID_CHSWP);
- if(!hs_cap) {
+ if (!hs_cap)
return 0;
- }
- if(pci_bus_read_config_word(slot->bus,
+ if (pci_bus_read_config_word(slot->bus,
slot->devfn,
hs_cap + 2,
- &hs_csr)) {
+ &hs_csr))
return 0;
- }
- if(hs_csr & HS_CSR_EXT) {
+ if (hs_csr & HS_CSR_EXT)
ext = 1;
- }
return ext;
}
@@ -222,23 +172,20 @@ int cpci_clear_ext(struct slot* slot)
hs_cap = pci_bus_find_capability(slot->bus,
slot->devfn,
PCI_CAP_ID_CHSWP);
- if(!hs_cap) {
+ if (!hs_cap)
return -ENODEV;
- }
- if(pci_bus_read_config_word(slot->bus,
+ if (pci_bus_read_config_word(slot->bus,
slot->devfn,
hs_cap + 2,
- &hs_csr)) {
+ &hs_csr))
return -ENODEV;
- }
- if(hs_csr & HS_CSR_EXT) {
+ if (hs_csr & HS_CSR_EXT) {
/* Clear EXT (by setting it) */
- if(pci_bus_write_config_word(slot->bus,
+ if (pci_bus_write_config_word(slot->bus,
slot->devfn,
hs_cap + 2,
- hs_csr)) {
+ hs_csr))
return -ENODEV;
- }
}
return 0;
}
@@ -251,19 +198,16 @@ int cpci_led_on(struct slot* slot)
hs_cap = pci_bus_find_capability(slot->bus,
slot->devfn,
PCI_CAP_ID_CHSWP);
- if(!hs_cap) {
+ if (!hs_cap)
return -ENODEV;
- }
- if(pci_bus_read_config_word(slot->bus,
+ if (pci_bus_read_config_word(slot->bus,
slot->devfn,
hs_cap + 2,
- &hs_csr)) {
+ &hs_csr))
return -ENODEV;
- }
- if((hs_csr & HS_CSR_LOO) != HS_CSR_LOO) {
- /* Set LOO */
+ if ((hs_csr & HS_CSR_LOO) != HS_CSR_LOO) {
hs_csr |= HS_CSR_LOO;
- if(pci_bus_write_config_word(slot->bus,
+ if (pci_bus_write_config_word(slot->bus,
slot->devfn,
hs_cap + 2,
hs_csr)) {
@@ -283,19 +227,16 @@ int cpci_led_off(struct slot* slot)
hs_cap = pci_bus_find_capability(slot->bus,
slot->devfn,
PCI_CAP_ID_CHSWP);
- if(!hs_cap) {
+ if (!hs_cap)
return -ENODEV;
- }
- if(pci_bus_read_config_word(slot->bus,
+ if (pci_bus_read_config_word(slot->bus,
slot->devfn,
hs_cap + 2,
- &hs_csr)) {
+ &hs_csr))
return -ENODEV;
- }
- if(hs_csr & HS_CSR_LOO) {
- /* Clear LOO */
+ if (hs_csr & HS_CSR_LOO) {
hs_csr &= ~HS_CSR_LOO;
- if(pci_bus_write_config_word(slot->bus,
+ if (pci_bus_write_config_word(slot->bus,
slot->devfn,
hs_cap + 2,
hs_csr)) {
@@ -312,268 +253,21 @@ int cpci_led_off(struct slot* slot)
* Device configuration functions
*/
-static int cpci_configure_dev(struct pci_bus *bus, struct pci_dev *dev)
-{
- u8 irq_pin;
- int r;
-
- dbg("%s - enter", __FUNCTION__);
-
- /* NOTE: device already setup from prior scan */
-
- /* FIXME: How would we know if we need to enable the expansion ROM? */
- pci_write_config_word(dev, PCI_ROM_ADDRESS, 0x00L);
-
- /* Assign resources */
- dbg("assigning resources for %02x:%02x.%x",
- dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
- for (r = 0; r < 6; r++) {
- struct resource *res = dev->resource + r;
- if(res->flags)
- pci_assign_resource(dev, r);
- }
- dbg("finished assigning resources for %02x:%02x.%x",
- dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
-
- /* Does this function have an interrupt at all? */
- dbg("checking for function interrupt");
- pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq_pin);
- if(irq_pin) {
- dbg("function uses interrupt pin %d", irq_pin);
- }
-
- /*
- * Need to explicitly set irq field to 0 so that it'll get assigned
- * by the pcibios platform dependent code called by pci_enable_device.
- */
- dev->irq = 0;
-
- dbg("enabling device");
- pci_enable_device(dev); /* XXX check return */
- dbg("now dev->irq = %d", dev->irq);
- if(irq_pin && dev->irq) {
- pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
- }
-
- /* Can't use pci_insert_device at the moment, do it manually for now */
- pci_proc_attach_device(dev);
- dbg("notifying drivers");
- //pci_announce_device_to_drivers(dev);
- dbg("%s - exit", __FUNCTION__);
- return 0;
-}
-
-static int cpci_configure_bridge(struct pci_bus* bus, struct pci_dev* dev)
-{
- int rc;
- struct pci_bus* child;
- struct resource* r;
- u8 max, n;
- u16 command;
-
- dbg("%s - enter", __FUNCTION__);
-
- /* Do basic bridge initialization */
- rc = pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40);
- if(rc) {
- printk(KERN_ERR "%s - write of PCI_LATENCY_TIMER failed\n", __FUNCTION__);
- }
- rc = pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 0x40);
- if(rc) {
- printk(KERN_ERR "%s - write of PCI_SEC_LATENCY_TIMER failed\n", __FUNCTION__);
- }
- rc = pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES / 4);
- if(rc) {
- printk(KERN_ERR "%s - write of PCI_CACHE_LINE_SIZE failed\n", __FUNCTION__);
- }
-
- /*
- * Set parent bridge's subordinate field so that configuration space
- * access will work in pci_scan_bridge and friends.
- */
- max = pci_max_busnr();
- bus->subordinate = max + 1;
- pci_write_config_byte(bus->self, PCI_SUBORDINATE_BUS, max + 1);
-
- /* Scan behind bridge */
- n = pci_scan_bridge(bus, dev, max, 2);
- child = pci_find_bus(0, max + 1);
- if (!child)
- return -ENODEV;
- pci_proc_attach_bus(child);
-
- /*
- * Update parent bridge's subordinate field if there were more bridges
- * behind the bridge that was scanned.
- */
- if(n > max) {
- bus->subordinate = n;
- pci_write_config_byte(bus->self, PCI_SUBORDINATE_BUS, n);
- }
-
- /*
- * Update the bridge resources of the bridge to accommodate devices
- * behind it.
- */
- pci_bus_size_bridges(child);
- pci_bus_assign_resources(child);
-
- /* Enable resource mapping via command register */
- command = PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
- r = child->resource[0];
- if(r && r->start) {
- command |= PCI_COMMAND_IO;
- }
- r = child->resource[1];
- if(r && r->start) {
- command |= PCI_COMMAND_MEMORY;
- }
- r = child->resource[2];
- if(r && r->start) {
- command |= PCI_COMMAND_MEMORY;
- }
- rc = pci_write_config_word(dev, PCI_COMMAND, command);
- if(rc) {
- err("Error setting command register");
- return rc;
- }
-
- /* Set bridge control register */
- command = PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR | PCI_BRIDGE_CTL_NO_ISA;
- rc = pci_write_config_word(dev, PCI_BRIDGE_CONTROL, command);
- if(rc) {
- err("Error setting bridge control register");
- return rc;
- }
- dbg("%s - exit", __FUNCTION__);
- return 0;
-}
-
-static int configure_visit_pci_dev(struct pci_dev_wrapped *wrapped_dev,
- struct pci_bus_wrapped *wrapped_bus)
-{
- int rc;
- struct pci_dev *dev = wrapped_dev->dev;
- struct pci_bus *bus = wrapped_bus->bus;
- struct slot* slot;
-
- dbg("%s - enter", __FUNCTION__);
-
- /*
- * We need to fix up the hotplug representation with the Linux
- * representation.
- */
- if(wrapped_dev->data) {
- slot = (struct slot*) wrapped_dev->data;
- slot->dev = dev;
- }
-
- /* If it's a bridge, scan behind it for devices */
- if(dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
- rc = cpci_configure_bridge(bus, dev);
- if(rc)
- return rc;
- }
-
- /* Actually configure device */
- if(dev) {
- rc = cpci_configure_dev(bus, dev);
- if(rc)
- return rc;
- }
- dbg("%s - exit", __FUNCTION__);
- return 0;
-}
-
-static int unconfigure_visit_pci_dev_phase2(struct pci_dev_wrapped *wrapped_dev,
- struct pci_bus_wrapped *wrapped_bus)
-{
- struct pci_dev *dev = wrapped_dev->dev;
- struct slot* slot;
-
- dbg("%s - enter", __FUNCTION__);
- if(!dev)
- return -ENODEV;
-
- /* Remove the Linux representation */
- if(pci_remove_device_safe(dev)) {
- err("Could not remove device\n");
- return -1;
- }
-
- /*
- * Now remove the hotplug representation.
- */
- if(wrapped_dev->data) {
- slot = (struct slot*) wrapped_dev->data;
- slot->dev = NULL;
- } else {
- dbg("No hotplug representation for %02x:%02x.%x",
- dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
- }
- dbg("%s - exit", __FUNCTION__);
- return 0;
-}
-
-static int unconfigure_visit_pci_bus_phase2(struct pci_bus_wrapped *wrapped_bus,
- struct pci_dev_wrapped *wrapped_dev)
-{
- struct pci_bus *bus = wrapped_bus->bus;
- struct pci_bus *parent = bus->self->bus;
-
- dbg("%s - enter", __FUNCTION__);
-
- /* The cleanup code for proc entries regarding buses should be in the kernel... */
- if(bus->procdir)
- dbg("detach_pci_bus %s", bus->procdir->name);
- pci_proc_detach_bus(bus);
-
- /* The cleanup code should live in the kernel... */
- bus->self->subordinate = NULL;
-
- /* unlink from parent bus */
- list_del(&bus->node);
-
- /* Now, remove */
- if(bus)
- kfree(bus);
-
- /* Update parent's subordinate field */
- if(parent) {
- u8 n = pci_bus_max_busnr(parent);
- if(n < parent->subordinate) {
- parent->subordinate = n;
- pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, n);
- }
- }
- dbg("%s - exit", __FUNCTION__);
- return 0;
-}
-
-static struct pci_visit configure_functions = {
- .visit_pci_dev = configure_visit_pci_dev,
-};
-
-static struct pci_visit unconfigure_functions_phase2 = {
- .post_visit_pci_bus = unconfigure_visit_pci_bus_phase2,
- .post_visit_pci_dev = unconfigure_visit_pci_dev_phase2
-};
-
-
int cpci_configure_slot(struct slot* slot)
{
- int rc = 0;
+ unsigned char busnr;
+ struct pci_bus *child;
dbg("%s - enter", __FUNCTION__);
- if(slot->dev == NULL) {
+ if (slot->dev == NULL) {
dbg("pci_dev null, finding %02x:%02x:%x",
slot->bus->number, PCI_SLOT(slot->devfn), PCI_FUNC(slot->devfn));
- slot->dev = pci_find_slot(slot->bus->number, slot->devfn);
+ slot->dev = pci_get_slot(slot->bus, slot->devfn);
}
/* Still NULL? Well then scan for it! */
- if(slot->dev == NULL) {
+ if (slot->dev == NULL) {
int n;
dbg("pci_dev still null");
@@ -583,79 +277,50 @@ int cpci_configure_slot(struct slot* slot)
*/
n = pci_scan_slot(slot->bus, slot->devfn);
dbg("%s: pci_scan_slot returned %d", __FUNCTION__, n);
- if(n > 0)
+ if (n > 0)
pci_bus_add_devices(slot->bus);
- slot->dev = pci_find_slot(slot->bus->number, slot->devfn);
- if(slot->dev == NULL) {
+ slot->dev = pci_get_slot(slot->bus, slot->devfn);
+ if (slot->dev == NULL) {
err("Could not find PCI device for slot %02x", slot->number);
- return 0;
+ return 1;
}
}
- dbg("slot->dev = %p", slot->dev);
- if(slot->dev) {
- struct pci_dev *dev;
- struct pci_dev_wrapped wrapped_dev;
- struct pci_bus_wrapped wrapped_bus;
- int i;
-
- memset(&wrapped_dev, 0, sizeof (struct pci_dev_wrapped));
- memset(&wrapped_bus, 0, sizeof (struct pci_bus_wrapped));
-
- for (i = 0; i < 8; i++) {
- dev = pci_find_slot(slot->bus->number,
- PCI_DEVFN(PCI_SLOT(slot->dev->devfn), i));
- if(!dev)
- continue;
- wrapped_dev.dev = dev;
- wrapped_bus.bus = slot->dev->bus;
- if(i)
- wrapped_dev.data = NULL;
- else
- wrapped_dev.data = (void*) slot;
- rc = pci_visit_dev(&configure_functions, &wrapped_dev, &wrapped_bus);
- }
+
+ if (slot->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+ pci_read_config_byte(slot->dev, PCI_SECONDARY_BUS, &busnr);
+ child = pci_add_new_bus(slot->dev->bus, slot->dev, busnr);
+ pci_do_scan_bus(child);
+ pci_bus_size_bridges(child);
}
- dbg("%s - exit, rc = %d", __FUNCTION__, rc);
- return rc;
+ pci_bus_assign_resources(slot->dev->bus);
+
+ dbg("%s - exit", __FUNCTION__);
+ return 0;
}
int cpci_unconfigure_slot(struct slot* slot)
{
- int rc = 0;
int i;
- struct pci_dev_wrapped wrapped_dev;
- struct pci_bus_wrapped wrapped_bus;
struct pci_dev *dev;
dbg("%s - enter", __FUNCTION__);
-
- if(!slot->dev) {
+ if (!slot->dev) {
err("No device for slot %02x\n", slot->number);
return -ENODEV;
}
- memset(&wrapped_dev, 0, sizeof (struct pci_dev_wrapped));
- memset(&wrapped_bus, 0, sizeof (struct pci_bus_wrapped));
-
for (i = 0; i < 8; i++) {
- dev = pci_find_slot(slot->bus->number,
+ dev = pci_get_slot(slot->bus,
PCI_DEVFN(PCI_SLOT(slot->devfn), i));
- if(dev) {
- wrapped_dev.dev = dev;
- wrapped_bus.bus = dev->bus;
- if(i)
- wrapped_dev.data = NULL;
- else
- wrapped_dev.data = (void*) slot;
- dbg("%s - unconfigure phase 2", __FUNCTION__);
- rc = pci_visit_dev(&unconfigure_functions_phase2,
- &wrapped_dev,
- &wrapped_bus);
- if(rc)
- break;
+ if (dev) {
+ pci_remove_bus_device(dev);
+ pci_dev_put(dev);
}
}
- dbg("%s - exit, rc = %d", __FUNCTION__, rc);
- return rc;
+ pci_dev_put(slot->dev);
+ slot->dev = NULL;
+
+ dbg("%s - exit", __FUNCTION__);
+ return 0;
}
diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c
index 41c7971d06c..4c11048ad51 100644
--- a/drivers/pci/hotplug/cpqphp_sysfs.c
+++ b/drivers/pci/hotplug/cpqphp_sysfs.c
@@ -38,7 +38,7 @@
/* A few routines that create sysfs entries for the hot plug controller */
-static ssize_t show_ctrl (struct device *dev, char *buf)
+static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, char *buf)
{
struct pci_dev *pci_dev;
struct controller *ctrl;
@@ -82,7 +82,7 @@ static ssize_t show_ctrl (struct device *dev, char *buf)
}
static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL);
-static ssize_t show_dev (struct device *dev, char *buf)
+static ssize_t show_dev (struct device *dev, struct device_attribute *attr, char *buf)
{
struct pci_dev *pci_dev;
struct controller *ctrl;
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
index c802f6270b8..c4282902cb5 100644
--- a/drivers/pci/hotplug/pci_hotplug_core.c
+++ b/drivers/pci/hotplug/pci_hotplug_core.c
@@ -73,7 +73,7 @@ static ssize_t hotplug_slot_attr_show(struct kobject *kobj,
{
struct hotplug_slot *slot = to_hotplug_slot(kobj);
struct hotplug_slot_attribute *attribute = to_hotplug_attr(attr);
- return attribute->show ? attribute->show(slot, buf) : 0;
+ return attribute->show ? attribute->show(slot, buf) : -EIO;
}
static ssize_t hotplug_slot_attr_store(struct kobject *kobj,
@@ -81,7 +81,7 @@ static ssize_t hotplug_slot_attr_store(struct kobject *kobj,
{
struct hotplug_slot *slot = to_hotplug_slot(kobj);
struct hotplug_slot_attribute *attribute = to_hotplug_attr(attr);
- return attribute->store ? attribute->store(slot, buf, len) : 0;
+ return attribute->store ? attribute->store(slot, buf, len) : -EIO;
}
static struct sysfs_ops hotplug_slot_sysfs_ops = {
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index f313121d514..46b294a1241 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -130,6 +130,7 @@ struct controller {
u8 slot_bus; /* Bus where the slots handled by this controller sit */
u8 ctrlcap;
u16 vendor_id;
+ u8 cap_base;
};
struct irq_mapping {
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index ed1fd8d6178..df4915dbc32 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -607,7 +607,7 @@ static int pciehp_resume (struct pcie_device *dev)
static struct pcie_port_service_id port_pci_ids[] = { {
.vendor = PCI_ANY_ID,
.device = PCI_ANY_ID,
- .port_type = PCIE_RC_PORT,
+ .port_type = PCIE_ANY_PORT,
.service_type = PCIE_PORT_SERVICE_HP,
.driver_data = 0,
}, { /* end: all zeroes */ }
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 9e70c4681f7..1cda30bd6e4 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -109,20 +109,20 @@ enum ctrl_offsets {
};
static int pcie_cap_base = 0; /* Base of the PCI Express capability item structure */
-#define PCIE_CAP_ID ( pcie_cap_base + PCIECAPID )
-#define NXT_CAP_PTR ( pcie_cap_base + NXTCAPPTR )
-#define CAP_REG ( pcie_cap_base + CAPREG )
-#define DEV_CAP ( pcie_cap_base + DEVCAP )
-#define DEV_CTRL ( pcie_cap_base + DEVCTRL )
-#define DEV_STATUS ( pcie_cap_base + DEVSTATUS )
-#define LNK_CAP ( pcie_cap_base + LNKCAP )
-#define LNK_CTRL ( pcie_cap_base + LNKCTRL )
-#define LNK_STATUS ( pcie_cap_base + LNKSTATUS )
-#define SLOT_CAP ( pcie_cap_base + SLOTCAP )
-#define SLOT_CTRL ( pcie_cap_base + SLOTCTRL )
-#define SLOT_STATUS ( pcie_cap_base + SLOTSTATUS )
-#define ROOT_CTRL ( pcie_cap_base + ROOTCTRL )
-#define ROOT_STATUS ( pcie_cap_base + ROOTSTATUS )
+#define PCIE_CAP_ID(cb) ( cb + PCIECAPID )
+#define NXT_CAP_PTR(cb) ( cb + NXTCAPPTR )
+#define CAP_REG(cb) ( cb + CAPREG )
+#define DEV_CAP(cb) ( cb + DEVCAP )
+#define DEV_CTRL(cb) ( cb + DEVCTRL )
+#define DEV_STATUS(cb) ( cb + DEVSTATUS )
+#define LNK_CAP(cb) ( cb + LNKCAP )
+#define LNK_CTRL(cb) ( cb + LNKCTRL )
+#define LNK_STATUS(cb) ( cb + LNKSTATUS )
+#define SLOT_CAP(cb) ( cb + SLOTCAP )
+#define SLOT_CTRL(cb) ( cb + SLOTCTRL )
+#define SLOT_STATUS(cb) ( cb + SLOTSTATUS )
+#define ROOT_CTRL(cb) ( cb + ROOTCTRL )
+#define ROOT_STATUS(cb) ( cb + ROOTSTATUS )
#define hp_register_read_word(pdev, reg , value) \
pci_read_config_word(pdev, reg, &value)
@@ -303,7 +303,7 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd)
return -1;
}
- retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+ retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status);
if (retval) {
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
return retval;
@@ -317,7 +317,7 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd)
}
dbg("%s: Before hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, cmd);
- retval = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, cmd | CMD_CMPL_INTR_ENABLE);
+ retval = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), cmd | CMD_CMPL_INTR_ENABLE);
if (retval) {
err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
return retval;
@@ -342,7 +342,7 @@ static int hpc_check_lnk_status(struct controller *ctrl)
return -1;
}
- retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS, lnk_status);
+ retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS(ctrl->cap_base), lnk_status);
if (retval) {
err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__);
@@ -376,14 +376,14 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status)
return -1;
}
- retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+ retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
if (retval) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
return retval;
}
- dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__,SLOT_CTRL, slot_ctrl);
+ dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__,SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
atten_led_state = (slot_ctrl & ATTN_LED_CTRL) >> 6;
@@ -423,13 +423,13 @@ static int hpc_get_power_status(struct slot * slot, u8 *status)
return -1;
}
- retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+ retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
if (retval) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
return retval;
}
- dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, slot_ctrl);
+ dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
pwr_state = (slot_ctrl & PWR_CTRL) >> 10;
@@ -463,7 +463,7 @@ static int hpc_get_latch_status(struct slot *slot, u8 *status)
return -1;
}
- retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+ retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status);
if (retval) {
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
@@ -490,7 +490,7 @@ static int hpc_get_adapter_status(struct slot *slot, u8 *status)
return -1;
}
- retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+ retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status);
if (retval) {
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
@@ -518,7 +518,7 @@ static int hpc_query_power_fault(struct slot * slot)
return -1;
}
- retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+ retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status);
if (retval) {
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
@@ -549,7 +549,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
err("%s: Invalid HPC slot number!\n", __FUNCTION__);
return -1;
}
- rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
if (rc) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
@@ -574,7 +574,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
slot_cmd = slot_cmd | HP_INTR_ENABLE;
pcie_write_cmd(slot, slot_cmd);
- dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL, slot_cmd);
+ dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
return rc;
}
@@ -598,7 +598,7 @@ static void hpc_set_green_led_on(struct slot *slot)
return ;
}
- rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
if (rc) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
@@ -611,7 +611,7 @@ static void hpc_set_green_led_on(struct slot *slot)
pcie_write_cmd(slot, slot_cmd);
- dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, slot_cmd);
+ dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
return;
}
@@ -633,7 +633,7 @@ static void hpc_set_green_led_off(struct slot *slot)
return ;
}
- rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
if (rc) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
@@ -646,7 +646,7 @@ static void hpc_set_green_led_off(struct slot *slot)
if (!pciehp_poll_mode)
slot_cmd = slot_cmd | HP_INTR_ENABLE;
pcie_write_cmd(slot, slot_cmd);
- dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL, slot_cmd);
+ dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
return;
}
@@ -669,7 +669,7 @@ static void hpc_set_green_led_blink(struct slot *slot)
return ;
}
- rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
if (rc) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
@@ -683,7 +683,7 @@ static void hpc_set_green_led_blink(struct slot *slot)
slot_cmd = slot_cmd | HP_INTR_ENABLE;
pcie_write_cmd(slot, slot_cmd);
- dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, slot_cmd);
+ dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
return;
}
@@ -707,7 +707,7 @@ int pcie_get_ctlr_slot_config(struct controller *ctrl,
*first_device_num = 0;
*num_ctlr_slots = 1;
- rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP, slot_cap);
+ rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP(ctrl->cap_base), slot_cap);
if (rc) {
err("%s : hp_register_read_dword SLOT_CAP failed\n", __FUNCTION__);
@@ -793,13 +793,13 @@ static int hpc_power_on_slot(struct slot * slot)
return -1;
}
- retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+ retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
if (retval) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
return retval;
}
- dbg("%s: SLOT_CTRL %x, value read %xn", __FUNCTION__, SLOT_CTRL,
+ dbg("%s: SLOT_CTRL %x, value read %xn", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base),
slot_ctrl);
slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON;
@@ -813,7 +813,7 @@ static int hpc_power_on_slot(struct slot * slot)
err("%s: Write %x command failed!\n", __FUNCTION__, slot_cmd);
return -1;
}
- dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, slot_cmd);
+ dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
DBG_LEAVE_ROUTINE
@@ -842,13 +842,13 @@ static int hpc_power_off_slot(struct slot * slot)
err("%s: Invalid HPC slot number!\n", __FUNCTION__);
return -1;
}
- retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+ retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), slot_ctrl);
if (retval) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
return retval;
}
- dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__, SLOT_CTRL,
+ dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base),
slot_ctrl);
slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF;
@@ -862,7 +862,7 @@ static int hpc_power_off_slot(struct slot * slot)
err("%s: Write command failed!\n", __FUNCTION__);
return -1;
}
- dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL, slot_cmd);
+ dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
DBG_LEAVE_ROUTINE
@@ -900,7 +900,7 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
return IRQ_NONE;
}
- rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
if (rc) {
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
return IRQ_NONE;
@@ -918,7 +918,7 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc);
/* Mask Hot-plug Interrupt Enable */
if (!pciehp_poll_mode) {
- rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
return IRQ_NONE;
@@ -928,14 +928,14 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00;
- rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word);
+ rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
return IRQ_NONE;
}
dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
- rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
if (rc) {
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
return IRQ_NONE;
@@ -944,7 +944,7 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
/* Clear command complete interrupt caused by this write */
temp_word = 0x1f;
- rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
+ rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
return IRQ_NONE;
@@ -975,14 +975,14 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
/* Clear all events after serving them */
temp_word = 0x1F;
- rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
+ rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
return IRQ_NONE;
}
/* Unmask Hot-plug Interrupt Enable */
if (!pciehp_poll_mode) {
- rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
return IRQ_NONE;
@@ -992,14 +992,14 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
- rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL, temp_word);
+ rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
return IRQ_NONE;
}
dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
- rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
if (rc) {
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
return IRQ_NONE;
@@ -1008,7 +1008,7 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
/* Clear command complete interrupt caused by this write */
temp_word = 0x1F;
- rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
+ rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
return IRQ_NONE;
@@ -1038,7 +1038,7 @@ static int hpc_get_max_lnk_speed (struct slot *slot, enum pci_bus_speed *value)
return -1;
}
- retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP, lnk_cap);
+ retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP(slot->ctrl->cap_base), lnk_cap);
if (retval) {
err("%s : hp_register_read_dword LNK_CAP failed\n", __FUNCTION__);
@@ -1079,7 +1079,7 @@ static int hpc_get_max_lnk_width (struct slot *slot, enum pcie_link_width *value
return -1;
}
- retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP, lnk_cap);
+ retval = hp_register_read_dword(php_ctlr->pci_dev, LNK_CAP(slot->ctrl->cap_base), lnk_cap);
if (retval) {
err("%s : hp_register_read_dword LNK_CAP failed\n", __FUNCTION__);
@@ -1141,7 +1141,7 @@ static int hpc_get_cur_lnk_speed (struct slot *slot, enum pci_bus_speed *value)
return -1;
}
- retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS, lnk_status);
+ retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS(slot->ctrl->cap_base), lnk_status);
if (retval) {
err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__);
@@ -1182,7 +1182,7 @@ static int hpc_get_cur_lnk_width (struct slot *slot, enum pcie_link_width *value
return -1;
}
- retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS, lnk_status);
+ retval = hp_register_read_word(php_ctlr->pci_dev, LNK_STATUS(slot->ctrl->cap_base), lnk_status);
if (retval) {
err("%s : hp_register_read_word LNK_STATUS failed\n", __FUNCTION__);
@@ -1292,47 +1292,48 @@ int pcie_init(struct controller * ctrl,
goto abort_free_ctlr;
}
- pcie_cap_base = cap_base;
+ ctrl->cap_base = cap_base;
dbg("%s: pcie_cap_base %x\n", __FUNCTION__, pcie_cap_base);
- rc = hp_register_read_word(pdev, CAP_REG, cap_reg);
+ rc = hp_register_read_word(pdev, CAP_REG(ctrl->cap_base), cap_reg);
if (rc) {
err("%s : hp_register_read_word CAP_REG failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: CAP_REG offset %x cap_reg %x\n", __FUNCTION__, CAP_REG, cap_reg);
+ dbg("%s: CAP_REG offset %x cap_reg %x\n", __FUNCTION__, CAP_REG(ctrl->cap_base), cap_reg);
- if (((cap_reg & SLOT_IMPL) == 0) || ((cap_reg & DEV_PORT_TYPE) != 0x0040)){
+ if (((cap_reg & SLOT_IMPL) == 0) || (((cap_reg & DEV_PORT_TYPE) != 0x0040)
+ && ((cap_reg & DEV_PORT_TYPE) != 0x0060))) {
dbg("%s : This is not a root port or the port is not connected to a slot\n", __FUNCTION__);
goto abort_free_ctlr;
}
- rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP, slot_cap);
+ rc = hp_register_read_dword(php_ctlr->pci_dev, SLOT_CAP(ctrl->cap_base), slot_cap);
if (rc) {
err("%s : hp_register_read_word CAP_REG failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: SLOT_CAP offset %x slot_cap %x\n", __FUNCTION__, SLOT_CAP, slot_cap);
+ dbg("%s: SLOT_CAP offset %x slot_cap %x\n", __FUNCTION__, SLOT_CAP(ctrl->cap_base), slot_cap);
if (!(slot_cap & HP_CAP)) {
dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__);
goto abort_free_ctlr;
}
/* For debugging purpose */
- rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
if (rc) {
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: SLOT_STATUS offset %x slot_status %x\n", __FUNCTION__, SLOT_STATUS, slot_status);
+ dbg("%s: SLOT_STATUS offset %x slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), slot_status);
- rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL, slot_ctrl);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), slot_ctrl);
if (rc) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: SLOT_CTRL offset %x slot_ctrl %x\n", __FUNCTION__, SLOT_CTRL, slot_ctrl);
+ dbg("%s: SLOT_CTRL offset %x slot_ctrl %x\n", __FUNCTION__, SLOT_CTRL(ctrl->cap_base), slot_ctrl);
if (first) {
spin_lock_init(&hpc_event_lock);
@@ -1372,36 +1373,37 @@ int pcie_init(struct controller * ctrl,
php_ctlr->num_slots = 1;
/* Mask Hot-plug Interrupt Enable */
- rc = hp_register_read_word(pdev, SLOT_CTRL, temp_word);
+ rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, temp_word);
+ dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL(ctrl->cap_base), temp_word);
temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00;
- rc = hp_register_write_word(pdev, SLOT_CTRL, temp_word);
+ rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
dbg("%s : Mask HPIE hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, temp_word);
- rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
if (rc) {
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: Mask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, SLOT_STATUS, slot_status);
+ dbg("%s: Mask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base)
+ , slot_status);
temp_word = 0x1F; /* Clear all events */
- rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
+ rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS, temp_word);
+ dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), temp_word);
if (pciehp_poll_mode) {/* Install interrupt polling code */
/* Install and start the interrupt polling timer */
@@ -1417,12 +1419,12 @@ int pcie_init(struct controller * ctrl,
}
}
- rc = hp_register_read_word(pdev, SLOT_CTRL, temp_word);
+ rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, temp_word);
+ dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL(ctrl->cap_base), temp_word);
dbg("%s: slot_cap %x\n", __FUNCTION__, slot_cap);
intr_enable = intr_enable | PRSN_DETECT_ENABLE;
@@ -1446,27 +1448,27 @@ int pcie_init(struct controller * ctrl,
dbg("%s: temp_word %x\n", __FUNCTION__, temp_word);
/* Unmask Hot-plug Interrupt Enable for the interrupt notification mechanism case */
- rc = hp_register_write_word(pdev, SLOT_CTRL, temp_word);
+ rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
dbg("%s : Unmask HPIE hp_register_write_word SLOT_CTRL with %x\n", __FUNCTION__, temp_word);
- rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS, slot_status);
+ rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
if (rc) {
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
dbg("%s: Unmask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__,
- SLOT_STATUS, slot_status);
+ SLOT_STATUS(ctrl->cap_base), slot_status);
temp_word = 0x1F; /* Clear all events */
- rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS, temp_word);
+ rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS, temp_word);
+ dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), temp_word);
/* Add this HPC instance into the HPC list */
spin_lock(&list_lock);
diff --git a/drivers/pci/hotplug/rpadlpar_sysfs.c b/drivers/pci/hotplug/rpadlpar_sysfs.c
index 3285b822478..752e6513c44 100644
--- a/drivers/pci/hotplug/rpadlpar_sysfs.c
+++ b/drivers/pci/hotplug/rpadlpar_sysfs.c
@@ -48,7 +48,7 @@ dlpar_attr_store(struct kobject * kobj, struct attribute * attr,
struct dlpar_io_attr *dlpar_attr = container_of(attr,
struct dlpar_io_attr, attr);
return dlpar_attr->store ?
- dlpar_attr->store(dlpar_attr, buf, nbytes) : 0;
+ dlpar_attr->store(dlpar_attr, buf, nbytes) : -EIO;
}
static struct sysfs_ops dlpar_attr_sysfs_ops = {
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index f0c53f850ae..a70a5c5705f 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -95,7 +95,7 @@ static struct hotplug_slot_ops shpchp_hotplug_slot_ops = {
*/
static void release_slot(struct hotplug_slot *hotplug_slot)
{
- struct slot *slot = (struct slot *)hotplug_slot->private;
+ struct slot *slot = hotplug_slot->private;
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index 9f90eb8e6ec..490a9553a06 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -1885,7 +1885,7 @@ int shpchp_enable_slot (struct slot *p_slot)
func = shpchp_slot_find(p_slot->bus, p_slot->device, 0);
if (!func) {
dbg("%s: Error! slot NULL\n", __FUNCTION__);
- return 1;
+ return -ENODEV;
}
/* Check to see if (latch closed, card present, power off) */
@@ -1894,19 +1894,19 @@ int shpchp_enable_slot (struct slot *p_slot)
if (rc || !getstatus) {
info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
up(&p_slot->ctrl->crit_sect);
- return 1;
+ return -ENODEV;
}
rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
if (rc || getstatus) {
info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
up(&p_slot->ctrl->crit_sect);
- return 1;
+ return -ENODEV;
}
rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
if (rc || getstatus) {
info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number);
up(&p_slot->ctrl->crit_sect);
- return 1;
+ return -ENODEV;
}
up(&p_slot->ctrl->crit_sect);
@@ -1914,7 +1914,7 @@ int shpchp_enable_slot (struct slot *p_slot)
func = shpchp_slot_create(p_slot->bus);
if (func == NULL)
- return 1;
+ return -ENOMEM;
func->bus = p_slot->bus;
func->device = p_slot->device;
@@ -1939,7 +1939,7 @@ int shpchp_enable_slot (struct slot *p_slot)
/* Setup slot structure with entry for empty slot */
func = shpchp_slot_create(p_slot->bus);
if (func == NULL)
- return (1); /* Out of memory */
+ return -ENOMEM; /* Out of memory */
func->bus = p_slot->bus;
func->device = p_slot->device;
@@ -1972,7 +1972,7 @@ int shpchp_disable_slot (struct slot *p_slot)
struct pci_func *func;
if (!p_slot->ctrl)
- return 1;
+ return -ENODEV;
pci_bus = p_slot->ctrl->pci_dev->subordinate;
@@ -1983,19 +1983,19 @@ int shpchp_disable_slot (struct slot *p_slot)
if (ret || !getstatus) {
info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
up(&p_slot->ctrl->crit_sect);
- return 1;
+ return -ENODEV;
}
ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
if (ret || getstatus) {
info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
up(&p_slot->ctrl->crit_sect);
- return 1;
+ return -ENODEV;
}
ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
if (ret || !getstatus) {
info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number);
up(&p_slot->ctrl->crit_sect);
- return 1;
+ return -ENODEV;
}
up(&p_slot->ctrl->crit_sect);
@@ -2011,7 +2011,7 @@ int shpchp_disable_slot (struct slot *p_slot)
/* Check the Class Code */
rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
if (rc)
- return rc;
+ return -ENODEV;
if (class_code == PCI_BASE_CLASS_DISPLAY) {
/* Display/Video adapter (not supported) */
@@ -2020,13 +2020,13 @@ int shpchp_disable_slot (struct slot *p_slot)
/* See if it's a bridge */
rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
if (rc)
- return rc;
+ return -ENODEV;
/* If it's a bridge, check the VGA Enable bit */
if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR);
if (rc)
- return rc;
+ return -ENODEV;
/* If the VGA Enable bit is set, remove isn't supported */
if (BCR & PCI_BRIDGE_CTL_VGA) {
@@ -2042,12 +2042,12 @@ int shpchp_disable_slot (struct slot *p_slot)
if ((func != NULL) && !rc) {
rc = remove_board(func, p_slot->ctrl);
} else if (!rc)
- rc = 1;
+ rc = -ENODEV;
if (p_slot)
update_slot_info(p_slot);
- return(rc);
+ return rc;
}
diff --git a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c
index 9a1ee132d12..c9445ebda5c 100644
--- a/drivers/pci/hotplug/shpchp_sysfs.c
+++ b/drivers/pci/hotplug/shpchp_sysfs.c
@@ -38,7 +38,7 @@
/* A few routines that create sysfs entries for the hot plug controller */
-static ssize_t show_ctrl (struct device *dev, char *buf)
+static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, char *buf)
{
struct pci_dev *pci_dev;
struct controller *ctrl;
@@ -82,7 +82,7 @@ static ssize_t show_ctrl (struct device *dev, char *buf)
}
static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL);
-static ssize_t show_dev (struct device *dev, char *buf)
+static ssize_t show_dev (struct device *dev, struct device_attribute *attr, char *buf)
{
struct pci_dev *pci_dev;
struct controller *ctrl;
diff --git a/drivers/pci/hotplug/shpchprm_acpi.c b/drivers/pci/hotplug/shpchprm_acpi.c
index 243a51d88b8..7957cdc72cd 100644
--- a/drivers/pci/hotplug/shpchprm_acpi.c
+++ b/drivers/pci/hotplug/shpchprm_acpi.c
@@ -1626,7 +1626,7 @@ int shpchprm_set_hpp(
pci_bus->number = func->bus;
devfn = PCI_DEVFN(func->device, func->function);
- ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus);
+ ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->slot_bus);
if (ab) {
if (ab->_hpp) {
@@ -1681,7 +1681,7 @@ void shpchprm_enable_card(
| PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
bcmd = bcommand = bcommand | PCI_BRIDGE_CTL_NO_ISA;
- ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus);
+ ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->slot_bus);
if (ab) {
if (ab->_hpp) {
if (ab->_hpp->enable_perr) {
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index fe98553c978..e65bf2b395a 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -335,13 +335,14 @@ pci_driver_attr_show(struct kobject * kobj, struct attribute *attr, char *buf)
{
struct device_driver *driver = kobj_to_pci_driver(kobj);
struct driver_attribute *dattr = attr_to_driver_attribute(attr);
- ssize_t ret = 0;
+ ssize_t ret;
- if (get_driver(driver)) {
- if (dattr->show)
- ret = dattr->show(driver, buf);
- put_driver(driver);
- }
+ if (!get_driver(driver))
+ return -ENODEV;
+
+ ret = dattr->show ? dattr->show(driver, buf) : -EIO;
+
+ put_driver(driver);
return ret;
}
@@ -351,13 +352,14 @@ pci_driver_attr_store(struct kobject * kobj, struct attribute *attr,
{
struct device_driver *driver = kobj_to_pci_driver(kobj);
struct driver_attribute *dattr = attr_to_driver_attribute(attr);
- ssize_t ret = 0;
+ ssize_t ret;
- if (get_driver(driver)) {
- if (dattr->store)
- ret = dattr->store(driver, buf, count);
- put_driver(driver);
- }
+ if (!get_driver(driver))
+ return -ENODEV;
+
+ ret = dattr->store ? dattr->store(driver, buf, count) : -EIO;
+
+ put_driver(driver);
return ret;
}
@@ -393,7 +395,10 @@ int pci_register_driver(struct pci_driver *drv)
drv->driver.bus = &pci_bus_type;
drv->driver.probe = pci_device_probe;
drv->driver.remove = pci_device_remove;
- drv->driver.shutdown = pci_device_shutdown,
+ /* FIXME, once all of the existing PCI drivers have been fixed to set
+ * the pci shutdown function, this test can go away. */
+ if (!drv->driver.shutdown)
+ drv->driver.shutdown = pci_device_shutdown;
drv->driver.owner = drv->owner;
drv->driver.kobj.ktype = &pci_driver_kobj_type;
pci_init_dynids(&drv->dynids);
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 8568b207f18..a15f94072a6 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -29,7 +29,7 @@ static int sysfs_initialized; /* = 0 */
/* show configuration fields */
#define pci_config_attr(field, format_string) \
static ssize_t \
-field##_show(struct device *dev, char *buf) \
+field##_show(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct pci_dev *pdev; \
\
@@ -44,7 +44,7 @@ pci_config_attr(subsystem_device, "0x%04x\n");
pci_config_attr(class, "0x%06x\n");
pci_config_attr(irq, "%u\n");
-static ssize_t local_cpus_show(struct device *dev, char *buf)
+static ssize_t local_cpus_show(struct device *dev, struct device_attribute *attr, char *buf)
{
cpumask_t mask = pcibus_to_cpumask(to_pci_dev(dev)->bus);
int len = cpumask_scnprintf(buf, PAGE_SIZE-2, mask);
@@ -54,7 +54,7 @@ static ssize_t local_cpus_show(struct device *dev, char *buf)
/* show resources */
static ssize_t
-resource_show(struct device * dev, char * buf)
+resource_show(struct device * dev, struct device_attribute *attr, char * buf)
{
struct pci_dev * pci_dev = to_pci_dev(dev);
char * str = buf;
@@ -73,6 +73,17 @@ resource_show(struct device * dev, char * buf)
return (str - buf);
}
+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
+
+ return sprintf(buf, "pci:v%08Xd%08Xsv%08Xsd%08Xbc%02Xsc%02Xi%02x\n",
+ pci_dev->vendor, pci_dev->device,
+ pci_dev->subsystem_vendor, pci_dev->subsystem_device,
+ (u8)(pci_dev->class >> 16), (u8)(pci_dev->class >> 8),
+ (u8)(pci_dev->class));
+}
+
struct device_attribute pci_dev_attrs[] = {
__ATTR_RO(resource),
__ATTR_RO(vendor),
@@ -82,6 +93,7 @@ struct device_attribute pci_dev_attrs[] = {
__ATTR_RO(class),
__ATTR_RO(irq),
__ATTR_RO(local_cpus),
+ __ATTR_RO(modalias),
__ATTR_NULL,
};
@@ -327,16 +339,17 @@ pci_create_resource_files(struct pci_dev *pdev)
if (!pci_resource_len(pdev, i))
continue;
- res_attr = kmalloc(sizeof(*res_attr) + 10, GFP_ATOMIC);
+ /* allocate attribute structure, piggyback attribute name */
+ res_attr = kcalloc(1, sizeof(*res_attr) + 10, GFP_ATOMIC);
if (res_attr) {
- memset(res_attr, 0, sizeof(*res_attr) + 10);
+ char *res_attr_name = (char *)(res_attr + 1);
+
pdev->res_attr[i] = res_attr;
- /* Allocated above after the res_attr struct */
- res_attr->attr.name = (char *)(res_attr + 1);
- sprintf(res_attr->attr.name, "resource%d", i);
- res_attr->size = pci_resource_len(pdev, i);
+ sprintf(res_attr_name, "resource%d", i);
+ res_attr->attr.name = res_attr_name;
res_attr->attr.mode = S_IRUSR | S_IWUSR;
res_attr->attr.owner = THIS_MODULE;
+ res_attr->size = pci_resource_len(pdev, i);
res_attr->mmap = pci_mmap_resource;
res_attr->private = &pdev->resource[i];
sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 79cdc16c52c..744da0d4ae5 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -32,33 +32,6 @@ extern unsigned char pci_max_busnr(void);
extern unsigned char pci_bus_max_busnr(struct pci_bus *bus);
extern int pci_bus_find_capability (struct pci_bus *bus, unsigned int devfn, int cap);
-struct pci_dev_wrapped {
- struct pci_dev *dev;
- void *data;
-};
-
-struct pci_bus_wrapped {
- struct pci_bus *bus;
- void *data;
-};
-
-struct pci_visit {
- int (* pre_visit_pci_bus) (struct pci_bus_wrapped *,
- struct pci_dev_wrapped *);
- int (* post_visit_pci_bus) (struct pci_bus_wrapped *,
- struct pci_dev_wrapped *);
-
- int (* pre_visit_pci_dev) (struct pci_dev_wrapped *,
- struct pci_bus_wrapped *);
- int (* visit_pci_dev) (struct pci_dev_wrapped *,
- struct pci_bus_wrapped *);
- int (* post_visit_pci_dev) (struct pci_dev_wrapped *,
- struct pci_bus_wrapped *);
-};
-
-extern int pci_visit_dev(struct pci_visit *fn,
- struct pci_dev_wrapped *wrapped_dev,
- struct pci_bus_wrapped *wrapped_parent);
extern void pci_remove_legacy_files(struct pci_bus *bus);
/* Lock for read/write access to pci device and bus lists */
diff --git a/drivers/pci/pci.ids b/drivers/pci/pci.ids
index 93481b41b61..1d2ef1e2ffc 100644
--- a/drivers/pci/pci.ids
+++ b/drivers/pci/pci.ids
@@ -7173,6 +7173,7 @@
080f Sentry5 DDR/SDR RAM Controller
0811 Sentry5 External Interface Core
0816 BCM3302 Sentry5 MIPS32 CPU
+ 1600 NetXtreme BCM5752 Gigabit Ethernet PCI Express
1644 NetXtreme BCM5700 Gigabit Ethernet
1014 0277 Broadcom Vigil B5700 1000Base-T
1028 00d1 Broadcom BCM5700
diff --git a/drivers/pci/pcie/portdrv_bus.c b/drivers/pci/pcie/portdrv_bus.c
index 4037a3e568d..3e84b501e6a 100644
--- a/drivers/pci/pcie/portdrv_bus.c
+++ b/drivers/pci/pcie/portdrv_bus.c
@@ -39,7 +39,8 @@ static int pcie_port_bus_match(struct device *dev, struct device_driver *drv)
driver->id_table->vendor != pciedev->id.vendor) ||
(driver->id_table->device != PCI_ANY_ID &&
driver->id_table->device != pciedev->id.device) ||
- driver->id_table->port_type != pciedev->id.port_type ||
+ (driver->id_table->port_type != PCIE_ANY_PORT &&
+ driver->id_table->port_type != pciedev->id.port_type) ||
driver->id_table->service_type != pciedev->id.service_type )
return 0;
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index 576285765e9..f5c5f10a3d2 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -232,19 +232,16 @@ static void pcie_device_init(struct pci_dev *parent, struct pcie_device *dev,
/* Initialize generic device interface */
device = &dev->device;
memset(device, 0, sizeof(struct device));
- INIT_LIST_HEAD(&device->node);
- INIT_LIST_HEAD(&device->children);
- INIT_LIST_HEAD(&device->bus_list);
device->bus = &pcie_port_bus_type;
device->driver = NULL;
- device->driver_data = NULL;
+ device->driver_data = NULL;
device->release = release_pcie_device; /* callback to free pcie dev */
- sprintf(&device->bus_id[0], "pcie%02x",
+ sprintf(&device->bus_id[0], "pcie%02x",
get_descriptor_id(port_type, service_type));
device->parent = &parent->dev;
}
-static struct pcie_device* alloc_pcie_device(struct pci_dev *parent,
+static struct pcie_device* alloc_pcie_device(struct pci_dev *parent,
int port_type, int service_type, int irq, int irq_mode)
{
struct pcie_device *device;
@@ -270,9 +267,9 @@ int pcie_port_device_probe(struct pci_dev *dev)
pci_read_config_word(dev, pos + PCIE_CAPABILITIES_REG, &reg);
type = (reg >> 4) & PORT_TYPE_MASK;
if ( type == PCIE_RC_PORT || type == PCIE_SW_UPSTREAM_PORT ||
- type == PCIE_SW_DOWNSTREAM_PORT )
+ type == PCIE_SW_DOWNSTREAM_PORT )
return 0;
-
+
return -ENODEV;
}
@@ -283,8 +280,8 @@ int pcie_port_device_register(struct pci_dev *dev)
u16 reg16;
/* Get port type */
- pci_read_config_word(dev,
- pci_find_capability(dev, PCI_CAP_ID_EXP) +
+ pci_read_config_word(dev,
+ pci_find_capability(dev, PCI_CAP_ID_EXP) +
PCIE_CAPABILITIES_REG, &reg16);
type = (reg16 >> 4) & PORT_TYPE_MASK;
@@ -299,11 +296,11 @@ int pcie_port_device_register(struct pci_dev *dev)
if (capabilities & (1 << i)) {
child = alloc_pcie_device(
dev, /* parent */
- type, /* port type */
+ type, /* port type */
i, /* service type */
vectors[i], /* irq */
irq_mode /* interrupt mode */);
- if (child) {
+ if (child) {
status = device_register(&child->device);
if (status) {
kfree(child);
@@ -317,84 +314,78 @@ int pcie_port_device_register(struct pci_dev *dev)
}
#ifdef CONFIG_PM
-int pcie_port_device_suspend(struct pci_dev *dev, pm_message_t state)
+static int suspend_iter(struct device *dev, void *data)
{
- struct list_head *head, *tmp;
- struct device *parent, *child;
- struct device_driver *driver;
struct pcie_port_service_driver *service_driver;
+ u32 state = (u32)data;
+
+ if ((dev->bus == &pcie_port_bus_type) &&
+ (dev->driver)) {
+ service_driver = to_service_driver(dev->driver);
+ if (service_driver->suspend)
+ service_driver->suspend(to_pcie_device(dev), state);
+ }
+ return 0;
+}
- parent = &dev->dev;
- head = &parent->children;
- tmp = head->next;
- while (head != tmp) {
- child = container_of(tmp, struct device, node);
- tmp = tmp->next;
- if (child->bus != &pcie_port_bus_type)
- continue;
- driver = child->driver;
- if (!driver)
- continue;
- service_driver = to_service_driver(driver);
- if (service_driver->suspend)
- service_driver->suspend(to_pcie_device(child), state);
- }
- return 0;
+int pcie_port_device_suspend(struct pci_dev *dev, u32 state)
+{
+ device_for_each_child(&dev->dev, (void *)state, suspend_iter);
+ return 0;
}
-int pcie_port_device_resume(struct pci_dev *dev)
-{
- struct list_head *head, *tmp;
- struct device *parent, *child;
- struct device_driver *driver;
+static int resume_iter(struct device *dev, void *data)
+{
struct pcie_port_service_driver *service_driver;
- parent = &dev->dev;
- head = &parent->children;
- tmp = head->next;
- while (head != tmp) {
- child = container_of(tmp, struct device, node);
- tmp = tmp->next;
- if (child->bus != &pcie_port_bus_type)
- continue;
- driver = child->driver;
- if (!driver)
- continue;
- service_driver = to_service_driver(driver);
- if (service_driver->resume)
- service_driver->resume(to_pcie_device(child));
+ if ((dev->bus == &pcie_port_bus_type) &&
+ (dev->driver)) {
+ service_driver = to_service_driver(dev->driver);
+ if (service_driver->resume)
+ service_driver->resume(to_pcie_device(dev));
}
- return 0;
+ return 0;
+}
+int pcie_port_device_resume(struct pci_dev *dev)
+{
+ device_for_each_child(&dev->dev, NULL, resume_iter);
+ return 0;
}
#endif
-void pcie_port_device_remove(struct pci_dev *dev)
+static int remove_iter(struct device *dev, void *data)
{
- struct list_head *head, *tmp;
- struct device *parent, *child;
- struct device_driver *driver;
struct pcie_port_service_driver *service_driver;
- int interrupt_mode = PCIE_PORT_INTx_MODE;
- parent = &dev->dev;
- head = &parent->children;
- tmp = head->next;
- while (head != tmp) {
- child = container_of(tmp, struct device, node);
- tmp = tmp->next;
- if (child->bus != &pcie_port_bus_type)
- continue;
- driver = child->driver;
- if (driver) {
- service_driver = to_service_driver(driver);
- if (service_driver->remove)
- service_driver->remove(to_pcie_device(child));
+ if (dev->bus == &pcie_port_bus_type) {
+ if (dev->driver) {
+ service_driver = to_service_driver(dev->driver);
+ if (service_driver->remove)
+ service_driver->remove(to_pcie_device(dev));
}
- interrupt_mode = (to_pcie_device(child))->interrupt_mode;
- put_device(child);
- device_unregister(child);
+ *(unsigned long*)data = (unsigned long)dev;
+ return 1;
}
+ return 0;
+}
+
+void pcie_port_device_remove(struct pci_dev *dev)
+{
+ struct device *device;
+ unsigned long device_addr;
+ int interrupt_mode = PCIE_PORT_INTx_MODE;
+ int status;
+
+ do {
+ status = device_for_each_child(&dev->dev, &device_addr, remove_iter);
+ if (status) {
+ device = (struct device*)device_addr;
+ interrupt_mode = (to_pcie_device(device))->interrupt_mode;
+ put_device(device);
+ device_unregister(device);
+ }
+ } while (status);
/* Switch to INTx by default if MSI enabled */
if (interrupt_mode == PCIE_PORT_MSIX_MODE)
pci_disable_msix(dev);
@@ -423,7 +414,7 @@ int pcie_port_service_register(struct pcie_port_service_driver *new)
new->driver.resume = pcie_port_resume_service;
return driver_register(&new->driver);
-}
+}
void pcie_port_service_unregister(struct pcie_port_service_driver *new)
{
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index b7ae87823c6..fd48b201eb5 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -125,7 +125,7 @@ static inline unsigned int pci_calc_resource_flags(unsigned int flags)
/*
* Find the extent of a PCI decode..
*/
-static u32 pci_size(u32 base, u32 maxbase, unsigned long mask)
+static u32 pci_size(u32 base, u32 maxbase, u32 mask)
{
u32 size = mask & maxbase; /* Find the significant bits */
if (!size)
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 026aa04669a..968033fd29f 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -18,6 +18,7 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/acpi.h>
#include "pci.h"
/* Deal with broken BIOS'es that neglect to enable passive release,
@@ -455,24 +456,16 @@ static void __init quirk_amd_8131_ioapic(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_APIC, quirk_amd_8131_ioapic );
+static void __init quirk_svw_msi(struct pci_dev *dev)
+{
+ pci_msi_quirk = 1;
+ printk(KERN_WARNING "PCI: MSI quirk detected. pci_msi_quirk set.\n");
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCNB_LE, quirk_svw_msi );
#endif /* CONFIG_X86_IO_APIC */
/*
- * Via 686A/B: The PCI_INTERRUPT_LINE register for the on-chip
- * devices, USB0/1, AC97, MC97, and ACPI, has an unusual feature:
- * when written, it makes an internal connection to the PIC.
- * For these devices, this register is defined to be 4 bits wide.
- * Normally this is fine. However for IO-APIC motherboards, or
- * non-x86 architectures (yes Via exists on PPC among other places),
- * we must mask the PCI_INTERRUPT_LINE value versus 0xf to get
- * interrupts delivered properly.
- *
- * TODO: When we have device-specific interrupt routers,
- * quirk_via_irqpic will go away from quirks.
- */
-
-/*
* FIXME: it is questionable that quirk_via_acpi
* is needed. It shows up as an ISA bridge, and does not
* support the PCI_INTERRUPT_LINE register at all. Therefore
@@ -495,6 +488,31 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_vi
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi );
/*
+ * Via 686A/B: The PCI_INTERRUPT_LINE register for the on-chip
+ * devices, USB0/1, AC97, MC97, and ACPI, has an unusual feature:
+ * when written, it makes an internal connection to the PIC.
+ * For these devices, this register is defined to be 4 bits wide.
+ * Normally this is fine. However for IO-APIC motherboards, or
+ * non-x86 architectures (yes Via exists on PPC among other places),
+ * we must mask the PCI_INTERRUPT_LINE value versus 0xf to get
+ * interrupts delivered properly.
+ */
+static void quirk_via_irq(struct pci_dev *dev)
+{
+ u8 irq, new_irq;
+
+ new_irq = dev->irq & 0xf;
+ pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
+ if (new_irq != irq) {
+ printk(KERN_INFO "PCI: Via IRQ fixup for %s, from %d to %d\n",
+ pci_name(dev), irq, new_irq);
+ udelay(15); /* unknown if delay really needed */
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq);
+ }
+}
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irq);
+
+/*
* PIIX3 USB: We have to disable USB interrupts that are
* hardwired to PIRQD# and may be shared with an
* external device.
@@ -683,19 +701,6 @@ static void __init quirk_disable_pxb(struct pci_dev *pdev)
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb );
-/*
- * VIA northbridges care about PCI_INTERRUPT_LINE
- */
-int via_interrupt_line_quirk;
-
-static void __devinit quirk_via_bridge(struct pci_dev *pdev)
-{
- if(pdev->devfn == 0) {
- printk(KERN_INFO "PCI: Via IRQ fixup\n");
- via_interrupt_line_quirk = 1;
- }
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_bridge );
/*
* Serverworks CSB5 IDE does not fully support native mode
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 6375ebc8502..14e4124e152 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -171,19 +171,21 @@ config PCMCIA_PROBE
config M32R_PCC
bool "M32R PCMCIA I/F"
depends on M32R && CHIP_M32700 && PCMCIA
+ select PCCARD_NONSTATIC
help
Say Y here to use the M32R PCMCIA controller.
config M32R_CFC
bool "M32R CF I/F Controller"
- depends on M32R && (PLAT_USRV || PLAT_M32700UT || PLAT_MAPPI2 || PLAT_OPSPUT)
+ depends on M32R && (PLAT_USRV || PLAT_M32700UT || PLAT_MAPPI2 || PLAT_MAPPI3 || PLAT_OPSPUT)
+ select PCCARD_NONSTATIC
help
Say Y here to use the M32R CompactFlash controller.
config M32R_CFC_NUM
int "M32R CF I/F number"
depends on M32R_CFC
- default "1" if PLAT_USRV || PLAT_M32700UT || PLAT_MAPPI2 || PLAT_OPSPUT
+ default "1" if PLAT_USRV || PLAT_M32700UT || PLAT_MAPPI2 || PLAT_MAPPI3 || PLAT_OPSPUT
help
Set the number of M32R CF slots.
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 03fc885db1c..48e4f04530d 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -508,6 +508,10 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
cs_err(skt, "unsupported voltage key.\n");
return CS_BAD_TYPE;
}
+
+ if (skt->power_hook)
+ skt->power_hook(skt, HOOK_POWER_PRE);
+
skt->socket.flags = 0;
skt->ops->set_socket(skt, &skt->socket);
@@ -522,7 +526,12 @@ static int socket_setup(struct pcmcia_socket *skt, int initial_delay)
return CS_BAD_TYPE;
}
- return socket_reset(skt);
+ status = socket_reset(skt);
+
+ if (skt->power_hook)
+ skt->power_hook(skt, HOOK_POWER_POST);
+
+ return status;
}
/*
@@ -709,7 +718,7 @@ static int pccardd(void *__skt)
}
schedule();
- try_to_freeze(PF_FREEZE);
+ try_to_freeze();
if (!skt->thread)
break;
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 66150d08b5c..569e55feecf 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -604,14 +604,14 @@ static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) {
/************************ per-device sysfs output ***************************/
#define pcmcia_device_attr(field, test, format) \
-static ssize_t field##_show (struct device *dev, char *buf) \
+static ssize_t field##_show (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct pcmcia_device *p_dev = to_pcmcia_dev(dev); \
return p_dev->test ? sprintf (buf, format, p_dev->field) : -ENODEV; \
}
#define pcmcia_device_stringattr(name, field) \
-static ssize_t name##_show (struct device *dev, char *buf) \
+static ssize_t name##_show (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct pcmcia_device *p_dev = to_pcmcia_dev(dev); \
return p_dev->field ? sprintf (buf, "%s\n", p_dev->field) : -ENODEV; \
@@ -1592,9 +1592,9 @@ static int __init init_pcmcia_bus(void)
/* Set up character device for user mode clients */
i = register_chrdev(0, "pcmcia", &ds_fops);
- if (i == -EBUSY)
+ if (i < 0)
printk(KERN_NOTICE "unable to find a free device # for "
- "Driver Services\n");
+ "Driver Services (error=%d)\n", i);
else
major_dev = i;
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c
index 581bfa95429..b1111c6bf06 100644
--- a/drivers/pcmcia/m32r_cfc.c
+++ b/drivers/pcmcia/m32r_cfc.c
@@ -24,9 +24,9 @@
#include <linux/workqueue.h>
#include <linux/interrupt.h>
#include <linux/device.h>
+#include <linux/bitops.h>
#include <asm/irq.h>
#include <asm/io.h>
-#include <asm/bitops.h>
#include <asm/system.h>
#include <pcmcia/version.h>
@@ -444,7 +444,7 @@ static int _pcc_get_status(u_short sock, u_int *value)
debug(3, "m32r_cfc: _pcc_get_status: "
"power off (CPCR=0x%08x)\n", status);
}
-#elif defined(CONFIG_PLAT_MAPPI2)
+#elif defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3)
if ( status ) {
status = pcc_get(sock, (unsigned int)PLD_CPCR);
if (status == 0) { /* power off */
@@ -452,18 +452,23 @@ static int _pcc_get_status(u_short sock, u_int *value)
pcc_set(sock, (unsigned int)PLD_CFBUFCR,0); /* force buffer off for ZA-36 */
udelay(50);
}
- status = pcc_get(sock, (unsigned int)PLD_CFBUFCR);
- if (status != 0) { /* buffer off */
- pcc_set(sock, (unsigned int)PLD_CFBUFCR,0);
- udelay(50);
- pcc_set(sock, (unsigned int)PLD_CFRSTCR, 0x0101);
- udelay(25); /* for IDE reset */
- pcc_set(sock, (unsigned int)PLD_CFRSTCR, 0x0100);
- mdelay(2); /* for IDE reset */
- } else {
- *value |= SS_POWERON;
- *value |= SS_READY;
- }
+ *value |= SS_POWERON;
+
+ pcc_set(sock, (unsigned int)PLD_CFBUFCR,0);
+ udelay(50);
+ pcc_set(sock, (unsigned int)PLD_CFRSTCR, 0x0101);
+ udelay(25); /* for IDE reset */
+ pcc_set(sock, (unsigned int)PLD_CFRSTCR, 0x0100);
+ mdelay(2); /* for IDE reset */
+
+ *value |= SS_READY;
+ *value |= SS_3VCARD;
+ } else {
+ /* disable CF power */
+ pcc_set(sock, (unsigned int)PLD_CPCR, 0);
+ udelay(100);
+ debug(3, "m32r_cfc: _pcc_get_status: "
+ "power off (CPCR=0x%08x)\n", status);
}
#else
#error no platform configuration
@@ -479,14 +484,13 @@ static int _pcc_get_socket(u_short sock, socket_state_t *state)
{
// pcc_socket_t *t = &socket[sock];
-#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV) || defined(CONFIG_PLAT_OPSPUT)
state->flags = 0;
state->csc_mask = SS_DETECT;
state->csc_mask |= SS_READY;
state->io_irq = 0;
state->Vcc = 33; /* 3.3V fixed */
state->Vpp = 33;
-#endif
+
debug(3, "m32r_cfc: GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
"io_irq %d, csc_mask %#2.2x\n", sock, state->flags,
state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
@@ -497,32 +501,17 @@ static int _pcc_get_socket(u_short sock, socket_state_t *state)
static int _pcc_set_socket(u_short sock, socket_state_t *state)
{
-#if defined(CONFIG_PLAT_MAPPI2)
- u_long reg = 0;
-#endif
debug(3, "m32r_cfc: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
"io_irq %d, csc_mask %#2.2x)\n", sock, state->flags,
state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
-#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV) || defined(CONFIG_PLAT_OPSPUT)
+#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV) || defined(CONFIG_PLAT_OPSPUT) || defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3)
if (state->Vcc) {
if ((state->Vcc != 50) && (state->Vcc != 33))
return -EINVAL;
/* accept 5V and 3.3V */
}
-#elif defined(CONFIG_PLAT_MAPPI2)
- if (state->Vcc) {
- /*
- * 5V only
- */
- if (state->Vcc == 50) {
- reg |= PCCSIGCR_VEN;
- } else {
- return -EINVAL;
- }
- }
#endif
-
if (state->flags & SS_RESET) {
debug(3, ":RESET\n");
pcc_set(sock,(unsigned int)PLD_CFRSTCR,0x101);
@@ -788,7 +777,7 @@ static int __init init_m32r_pcc(void)
return ret;
}
-#if defined(CONFIG_PLAT_MAPPI2)
+#if defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3)
pcc_set(0, (unsigned int)PLD_CFCR0, 0x0f0f);
pcc_set(0, (unsigned int)PLD_CFCR1, 0x0200);
#endif
@@ -825,7 +814,7 @@ static int __init init_m32r_pcc(void)
for (i = 0 ; i < pcc_sockets ; i++) {
socket[i].socket.dev.dev = &pcc_device.dev;
socket[i].socket.ops = &pcc_operations;
- socket[i].socket.resource_ops = &pccard_static_ops;
+ socket[i].socket.resource_ops = &pccard_nonstatic_ops;
socket[i].socket.owner = THIS_MODULE;
socket[i].number = i;
ret = pcmcia_register_socket(&socket[i].socket);
diff --git a/drivers/pcmcia/m32r_cfc.h b/drivers/pcmcia/m32r_cfc.h
index 17c1db7ae15..8146e3bee2e 100644
--- a/drivers/pcmcia/m32r_cfc.h
+++ b/drivers/pcmcia/m32r_cfc.h
@@ -71,11 +71,15 @@
#define CFC_IOPORT_BASE 0x1000
-#if !defined(CONFIG_PLAT_USRV)
+#if defined(CONFIG_PLAT_MAPPI3)
+#define CFC_ATTR_MAPBASE 0x14014000
+#define CFC_IO_MAPBASE_BYTE 0xb4012000
+#define CFC_IO_MAPBASE_WORD 0xb4002000
+#elif !defined(CONFIG_PLAT_USRV)
#define CFC_ATTR_MAPBASE 0x0c014000
#define CFC_IO_MAPBASE_BYTE 0xac012000
#define CFC_IO_MAPBASE_WORD 0xac002000
-#else /* CONFIG_PLAT_USRV */
+#else
#define CFC_ATTR_MAPBASE 0x04014000
#define CFC_IO_MAPBASE_BYTE 0xa4012000
#define CFC_IO_MAPBASE_WORD 0xa4002000
diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h
index a8a1d104524..c7ba99871ac 100644
--- a/drivers/pcmcia/ti113x.h
+++ b/drivers/pcmcia/ti113x.h
@@ -611,6 +611,170 @@ out:
}
}
+
+/* Returns true value if the second slot of a two-slot controller is empty */
+static int ti12xx_2nd_slot_empty(struct yenta_socket *socket)
+{
+ struct pci_dev *func;
+ struct yenta_socket *slot2;
+ int devfn;
+ unsigned int state;
+ int ret = 1;
+
+ /* catch the two-slot controllers */
+ switch (socket->dev->device) {
+ case PCI_DEVICE_ID_TI_1220:
+ case PCI_DEVICE_ID_TI_1221:
+ case PCI_DEVICE_ID_TI_1225:
+ case PCI_DEVICE_ID_TI_1251A:
+ case PCI_DEVICE_ID_TI_1251B:
+ case PCI_DEVICE_ID_TI_1420:
+ case PCI_DEVICE_ID_TI_1450:
+ case PCI_DEVICE_ID_TI_1451A:
+ case PCI_DEVICE_ID_TI_1520:
+ case PCI_DEVICE_ID_TI_1620:
+ case PCI_DEVICE_ID_TI_4520:
+ case PCI_DEVICE_ID_TI_4450:
+ case PCI_DEVICE_ID_TI_4451:
+ /*
+ * there are way more, but they need to be added in yenta_socket.c
+ * and pci_ids.h first anyway.
+ */
+ break;
+
+ /* single-slot controllers have the 2nd slot empty always :) */
+ default:
+ return 1;
+ }
+
+ /* get other slot */
+ devfn = socket->dev->devfn & ~0x07;
+ func = pci_get_slot(socket->dev->bus,
+ (socket->dev->devfn & 0x07) ? devfn : devfn | 0x01);
+ if (!func)
+ return 1;
+
+ slot2 = pci_get_drvdata(func);
+ if (!slot2)
+ goto out;
+
+ /* check state */
+ yenta_get_status(&socket->socket, &state);
+ if (state & SS_DETECT) {
+ ret = 0;
+ goto out;
+ }
+
+out:
+ pci_dev_put(func);
+ return ret;
+}
+
+/*
+ * TI specifiy parts for the power hook.
+ *
+ * some TI's with some CB's produces interrupt storm on power on. it has been
+ * seen with atheros wlan cards on TI1225 and TI1410. solution is simply to
+ * disable any CB interrupts during this time.
+ */
+static int ti12xx_power_hook(struct pcmcia_socket *sock, int operation)
+{
+ struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+ u32 mfunc, devctl, sysctl;
+ u8 gpio3;
+
+ /* only POWER_PRE and POWER_POST are interesting */
+ if ((operation != HOOK_POWER_PRE) && (operation != HOOK_POWER_POST))
+ return 0;
+
+ devctl = config_readb(socket, TI113X_DEVICE_CONTROL);
+ sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL);
+ mfunc = config_readl(socket, TI122X_MFUNC);
+
+ /*
+ * all serial/tied: only disable when modparm set. always doing it
+ * would mean a regression for working setups 'cos it disables the
+ * interrupts for both both slots on 2-slot controllers
+ * (and users of single slot controllers where it's save have to
+ * live with setting the modparm, most don't have to anyway)
+ */
+ if (((devctl & TI113X_DCR_IMODE_MASK) == TI12XX_DCR_IMODE_ALL_SERIAL) &&
+ (pwr_irqs_off || ti12xx_2nd_slot_empty(socket))) {
+ switch (socket->dev->device) {
+ case PCI_DEVICE_ID_TI_1250:
+ case PCI_DEVICE_ID_TI_1251A:
+ case PCI_DEVICE_ID_TI_1251B:
+ case PCI_DEVICE_ID_TI_1450:
+ case PCI_DEVICE_ID_TI_1451A:
+ case PCI_DEVICE_ID_TI_4450:
+ case PCI_DEVICE_ID_TI_4451:
+ /* these chips have no IRQSER setting in MFUNC3 */
+ break;
+
+ default:
+ if (operation == HOOK_POWER_PRE)
+ mfunc = (mfunc & ~TI122X_MFUNC3_MASK);
+ else
+ mfunc = (mfunc & ~TI122X_MFUNC3_MASK) | TI122X_MFUNC3_IRQSER;
+ }
+
+ return 0;
+ }
+
+ /* do the job differently for func0/1 */
+ if ((PCI_FUNC(socket->dev->devfn) == 0) ||
+ ((sysctl & TI122X_SCR_INTRTIE) &&
+ (pwr_irqs_off || ti12xx_2nd_slot_empty(socket)))) {
+ /* some bridges are different */
+ switch (socket->dev->device) {
+ case PCI_DEVICE_ID_TI_1250:
+ case PCI_DEVICE_ID_TI_1251A:
+ case PCI_DEVICE_ID_TI_1251B:
+ case PCI_DEVICE_ID_TI_1450:
+ /* those oldies use gpio3 for INTA */
+ gpio3 = config_readb(socket, TI1250_GPIO3_CONTROL);
+ if (operation == HOOK_POWER_PRE)
+ gpio3 = (gpio3 & ~TI1250_GPIO_MODE_MASK) | 0x40;
+ else
+ gpio3 &= ~TI1250_GPIO_MODE_MASK;
+ config_writeb(socket, TI1250_GPIO3_CONTROL, gpio3);
+ break;
+
+ default:
+ /* all new bridges are the same */
+ if (operation == HOOK_POWER_PRE)
+ mfunc &= ~TI122X_MFUNC0_MASK;
+ else
+ mfunc |= TI122X_MFUNC0_INTA;
+ config_writel(socket, TI122X_MFUNC, mfunc);
+ }
+ } else {
+ switch (socket->dev->device) {
+ case PCI_DEVICE_ID_TI_1251A:
+ case PCI_DEVICE_ID_TI_1251B:
+ case PCI_DEVICE_ID_TI_1450:
+ /* those have INTA elsewhere and INTB in MFUNC0 */
+ if (operation == HOOK_POWER_PRE)
+ mfunc &= ~TI122X_MFUNC0_MASK;
+ else
+ mfunc |= TI125X_MFUNC0_INTB;
+ config_writel(socket, TI122X_MFUNC, mfunc);
+
+ break;
+
+ default:
+ /* all new bridges are the same */
+ if (operation == HOOK_POWER_PRE)
+ mfunc &= ~TI122X_MFUNC1_MASK;
+ else
+ mfunc |= TI122X_MFUNC1_INTB;
+ config_writel(socket, TI122X_MFUNC, mfunc);
+ }
+ }
+
+ return 0;
+}
+
static int ti12xx_override(struct yenta_socket *socket)
{
u32 val, val_orig;
@@ -654,6 +818,9 @@ static int ti12xx_override(struct yenta_socket *socket)
else
ti12xx_irqroute_func1(socket);
+ /* install power hook */
+ socket->socket.power_hook = ti12xx_power_hook;
+
return ti_override(socket);
}
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 6404d97a12e..bee05362fd2 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -32,6 +32,14 @@ static int disable_clkrun;
module_param(disable_clkrun, bool, 0444);
MODULE_PARM_DESC(disable_clkrun, "If PC card doesn't function properly, please try this option");
+static int isa_probe = 1;
+module_param(isa_probe, bool, 0444);
+MODULE_PARM_DESC(isa_probe, "If set ISA interrupts are probed (default). Set to N to disable probing");
+
+static int pwr_irqs_off;
+module_param(pwr_irqs_off, bool, 0644);
+MODULE_PARM_DESC(pwr_irqs_off, "Force IRQs off during power-on of slot. Use only when seeing IRQ storms!");
+
#if 0
#define debug(x,args...) printk(KERN_DEBUG "%s: " x, __func__ , ##args)
#else
@@ -150,15 +158,16 @@ static int yenta_get_status(struct pcmcia_socket *sock, unsigned int *value)
val = (state & CB_3VCARD) ? SS_3VCARD : 0;
val |= (state & CB_XVCARD) ? SS_XVCARD : 0;
- val |= (state & (CB_CDETECT1 | CB_CDETECT2 | CB_5VCARD | CB_3VCARD
- | CB_XVCARD | CB_YVCARD)) ? 0 : SS_PENDING;
+ val |= (state & (CB_5VCARD | CB_3VCARD | CB_XVCARD | CB_YVCARD)) ? 0 : SS_PENDING;
+ val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? SS_PENDING : 0;
+
if (state & CB_CBCARD) {
val |= SS_CARDBUS;
val |= (state & CB_CARDSTS) ? SS_STSCHG : 0;
val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? 0 : SS_DETECT;
val |= (state & CB_PWRCYCLE) ? SS_POWERON | SS_READY : 0;
- } else {
+ } else if (state & CB_16BITCARD) {
u8 status = exca_readb(socket, I365_STATUS);
val |= ((status & I365_CS_DETECT) == I365_CS_DETECT) ? SS_DETECT : 0;
if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) {
@@ -405,11 +414,13 @@ static int yenta_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *
}
-static unsigned int yenta_events(struct yenta_socket *socket)
+
+static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
+ unsigned int events;
+ struct yenta_socket *socket = (struct yenta_socket *) dev_id;
u8 csc;
u32 cb_event;
- unsigned int events;
/* Clear interrupt status for the event */
cb_event = cb_readl(socket, CB_SOCKET_EVENT);
@@ -426,20 +437,13 @@ static unsigned int yenta_events(struct yenta_socket *socket)
events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0;
events |= (csc & I365_CSC_READY) ? SS_READY : 0;
}
- return events;
-}
-
-
-static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- unsigned int events;
- struct yenta_socket *socket = (struct yenta_socket *) dev_id;
- events = yenta_events(socket);
- if (events) {
+ if (events)
pcmcia_parse_events(&socket->socket, events);
+
+ if (cb_event || csc)
return IRQ_HANDLED;
- }
+
return IRQ_NONE;
}
@@ -470,11 +474,22 @@ static void yenta_clear_maps(struct yenta_socket *socket)
}
}
+/* redoes voltage interrogation if required */
+static void yenta_interrogate(struct yenta_socket *socket)
+{
+ u32 state;
+
+ state = cb_readl(socket, CB_SOCKET_STATE);
+ if (!(state & (CB_5VCARD | CB_3VCARD | CB_XVCARD | CB_YVCARD)) ||
+ (state & (CB_CDETECT1 | CB_CDETECT2 | CB_NOTACARD | CB_BADVCCREQ)) ||
+ ((state & (CB_16BITCARD | CB_CBCARD)) == (CB_16BITCARD | CB_CBCARD)))
+ cb_writel(socket, CB_SOCKET_FORCE, CB_CVSTEST);
+}
+
/* Called at resume and initialization events */
static int yenta_sock_init(struct pcmcia_socket *sock)
{
struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
- u32 state;
u16 bridge;
bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~CB_BRIDGE_INTR;
@@ -486,10 +501,7 @@ static int yenta_sock_init(struct pcmcia_socket *sock)
exca_writeb(socket, I365_GENCTL, 0x00);
/* Redo card voltage interrogation */
- state = cb_readl(socket, CB_SOCKET_STATE);
- if (!(state & (CB_CDETECT1 | CB_CDETECT2 | CB_5VCARD |
- CB_3VCARD | CB_XVCARD | CB_YVCARD)))
- cb_writel(socket, CB_SOCKET_FORCE, CB_CVSTEST);
+ yenta_interrogate(socket);
yenta_clear_maps(socket);
@@ -856,7 +868,10 @@ static void yenta_get_socket_capabilities(struct yenta_socket *socket, u32 isa_i
socket->socket.features |= SS_CAP_PAGE_REGS | SS_CAP_PCCARD | SS_CAP_CARDBUS;
socket->socket.map_size = 0x1000;
socket->socket.pci_irq = socket->cb_irq;
- socket->socket.irq_mask = yenta_probe_irq(socket, isa_irq_mask);
+ if (isa_probe)
+ socket->socket.irq_mask = yenta_probe_irq(socket, isa_irq_mask);
+ else
+ socket->socket.irq_mask = 0;
socket->socket.cb_dev = socket->dev;
printk(KERN_INFO "Yenta: ISA IRQ mask 0x%04x, PCI irq %d\n",
@@ -996,6 +1011,7 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i
}
/* Figure out what the dang thing can do for the PCMCIA layer... */
+ yenta_interrogate(socket);
yenta_get_socket_capabilities(socket, isa_interrupts);
printk(KERN_INFO "Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE));
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c
index 97eeecfaef1..add12f7c489 100644
--- a/drivers/pnp/card.c
+++ b/drivers/pnp/card.c
@@ -140,7 +140,7 @@ static void pnp_release_card(struct device *dmdev)
}
-static ssize_t pnp_show_card_name(struct device *dmdev, char *buf)
+static ssize_t pnp_show_card_name(struct device *dmdev, struct device_attribute *attr, char *buf)
{
char *str = buf;
struct pnp_card *card = to_pnp_card(dmdev);
@@ -150,7 +150,7 @@ static ssize_t pnp_show_card_name(struct device *dmdev, char *buf)
static DEVICE_ATTR(name,S_IRUGO,pnp_show_card_name,NULL);
-static ssize_t pnp_show_card_ids(struct device *dmdev, char *buf)
+static ssize_t pnp_show_card_ids(struct device *dmdev, struct device_attribute *attr, char *buf)
{
char *str = buf;
struct pnp_card *card = to_pnp_card(dmdev);
@@ -259,7 +259,6 @@ int pnp_add_card_device(struct pnp_card * card, struct pnp_dev * dev)
/**
* pnp_remove_card_device- removes a device from the specified card
- * @card: pointer to the card to remove from
* @dev: pointer to the device to remove
*/
@@ -274,7 +273,7 @@ void pnp_remove_card_device(struct pnp_dev * dev)
/**
* pnp_request_card_device - Searches for a PnP device under the specified card
- * @lcard: pointer to the card link, cannot be NULL
+ * @clink: pointer to the card link, cannot be NULL
* @id: pointer to a PnP ID structure that explains the rules for finding the device
* @from: Starting place to search from. If NULL it will start from the begining.
*/
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c
index d64c1ca4fa7..1d037c2a82a 100644
--- a/drivers/pnp/driver.c
+++ b/drivers/pnp/driver.c
@@ -160,10 +160,16 @@ struct bus_type pnp_bus_type = {
};
+static int count_devices(struct device * dev, void * c)
+{
+ int * count = c;
+ (*count)++;
+ return 0;
+}
+
int pnp_register_driver(struct pnp_driver *drv)
{
int count;
- struct list_head *pos;
pnp_dbg("the driver '%s' has been registered", drv->name);
@@ -177,9 +183,7 @@ int pnp_register_driver(struct pnp_driver *drv)
/* get the number of initial matches */
if (count >= 0){
count = 0;
- list_for_each(pos,&drv->driver.devices){
- count++;
- }
+ driver_for_each_device(&drv->driver, NULL, &count, count_devices);
}
return count;
}
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c
index 53fac8ba5d5..a2d8ce7fef9 100644
--- a/drivers/pnp/interface.c
+++ b/drivers/pnp/interface.c
@@ -205,7 +205,7 @@ static void pnp_print_option(pnp_info_buffer_t *buffer, char *space,
}
-static ssize_t pnp_show_options(struct device *dmdev, char *buf)
+static ssize_t pnp_show_options(struct device *dmdev, struct device_attribute *attr, char *buf)
{
struct pnp_dev *dev = to_pnp_dev(dmdev);
struct pnp_option * independent = dev->independent;
@@ -236,7 +236,7 @@ static ssize_t pnp_show_options(struct device *dmdev, char *buf)
static DEVICE_ATTR(options,S_IRUGO,pnp_show_options,NULL);
-static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf)
+static ssize_t pnp_show_current_resources(struct device *dmdev, struct device_attribute *attr, char *buf)
{
struct pnp_dev *dev = to_pnp_dev(dmdev);
int i, ret;
@@ -308,7 +308,7 @@ static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf)
extern struct semaphore pnp_res_mutex;
static ssize_t
-pnp_set_current_resources(struct device * dmdev, const char * ubuf, size_t count)
+pnp_set_current_resources(struct device * dmdev, struct device_attribute *attr, const char * ubuf, size_t count)
{
struct pnp_dev *dev = to_pnp_dev(dmdev);
char *buf = (void *)ubuf;
@@ -444,7 +444,7 @@ pnp_set_current_resources(struct device * dmdev, const char * ubuf, size_t count
static DEVICE_ATTR(resources,S_IRUGO | S_IWUSR,
pnp_show_current_resources,pnp_set_current_resources);
-static ssize_t pnp_show_current_ids(struct device *dmdev, char *buf)
+static ssize_t pnp_show_current_ids(struct device *dmdev, struct device_attribute *attr, char *buf)
{
char *str = buf;
struct pnp_dev *dev = to_pnp_dev(dmdev);
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index 65ecef73853..6c510c19ad7 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -390,6 +390,7 @@ fail:
* pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table
* @dev: pointer to the desired device
* @res: pointer to the new resource config
+ * @mode: 0 or PNP_CONFIG_FORCE
*
* This function can be used by drivers that want to manually set thier resources.
*/
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index e939c93a931..778a324028f 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -182,7 +182,7 @@ static int pnp_dock_thread(void * unused)
msleep_interruptible(2000);
if(signal_pending(current)) {
- if (try_to_freeze(PF_FREEZE))
+ if (try_to_freeze())
continue;
break;
}
diff --git a/drivers/s390/Kconfig b/drivers/s390/Kconfig
index 96413c2cd1a..a86a650f3d6 100644
--- a/drivers/s390/Kconfig
+++ b/drivers/s390/Kconfig
@@ -187,6 +187,13 @@ config VMLOGRDR
*SYMPTOM.
This driver depends on the IUCV support driver.
+config VMCP
+ tristate "Support for the z/VM CP interface (VM only)"
+ help
+ Select this option if you want to be able to interact with the control
+ program on z/VM
+
+
config MONREADER
tristate "API for reading z/VM monitor service records"
depends on IUCV
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 02cfe244e06..6527ff6f470 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -7,7 +7,7 @@
* Bugreports.to..: <Linux390@de.ibm.com>
* (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
*
- * $Revision: 1.161 $
+ * $Revision: 1.164 $
*/
#include <linux/config.h>
@@ -176,7 +176,7 @@ dasd_state_known_to_basic(struct dasd_device * device)
return rc;
/* register 'device' debug area, used for all DBF_DEV_XXX calls */
- device->debug_area = debug_register(device->cdev->dev.bus_id, 0, 2,
+ device->debug_area = debug_register(device->cdev->dev.bus_id, 1, 2,
8 * sizeof (long));
debug_register_view(device->debug_area, &debug_sprintf_view);
debug_set_level(device->debug_area, DBF_EMERG);
@@ -1766,10 +1766,10 @@ dasd_generic_probe (struct ccw_device *cdev,
printk(KERN_WARNING
"dasd_generic_probe: could not add sysfs entries "
"for %s\n", cdev->dev.bus_id);
+ } else {
+ cdev->handler = &dasd_int_handler;
}
- cdev->handler = &dasd_int_handler;
-
return ret;
}
@@ -1780,6 +1780,8 @@ dasd_generic_remove (struct ccw_device *cdev)
{
struct dasd_device *device;
+ cdev->handler = NULL;
+
dasd_remove_sysfs_files(cdev);
device = dasd_device_from_cdev(cdev);
if (IS_ERR(device))
@@ -1810,14 +1812,14 @@ dasd_generic_set_online (struct ccw_device *cdev,
struct dasd_device *device;
int feature_diag, rc;
- feature_diag = dasd_get_feature(cdev, DASD_FEATURE_USEDIAG);
- if (feature_diag < 0)
- return feature_diag;
-
device = dasd_create_device(cdev);
if (IS_ERR(device))
return PTR_ERR(device);
+ feature_diag = dasd_get_feature(cdev, DASD_FEATURE_USEDIAG);
+ if (feature_diag < 0)
+ return feature_diag;
+
if (feature_diag) {
if (!dasd_diag_discipline_pointer) {
printk (KERN_WARNING
@@ -1950,26 +1952,24 @@ dasd_generic_notify(struct ccw_device *cdev, int event)
* Automatically online either all dasd devices (dasd_autodetect) or
* all devices specified with dasd= parameters.
*/
+static int
+__dasd_auto_online(struct device *dev, void *data)
+{
+ struct ccw_device *cdev;
+
+ cdev = to_ccwdev(dev);
+ if (dasd_autodetect || dasd_busid_known(cdev->dev.bus_id) == 0)
+ ccw_device_set_online(cdev);
+ return 0;
+}
+
void
dasd_generic_auto_online (struct ccw_driver *dasd_discipline_driver)
{
struct device_driver *drv;
- struct device *d, *dev;
- struct ccw_device *cdev;
drv = get_driver(&dasd_discipline_driver->driver);
- down_read(&drv->bus->subsys.rwsem);
- dev = NULL;
- list_for_each_entry(d, &drv->devices, driver_list) {
- dev = get_device(d);
- if (!dev)
- continue;
- cdev = to_ccwdev(dev);
- if (dasd_autodetect || dasd_busid_known(cdev->dev.bus_id) == 0)
- ccw_device_set_online(cdev);
- put_device(dev);
- }
- up_read(&drv->bus->subsys.rwsem);
+ driver_for_each_device(drv, NULL, NULL, __dasd_auto_online);
put_driver(drv);
}
@@ -1981,7 +1981,7 @@ dasd_init(void)
init_waitqueue_head(&dasd_init_waitq);
/* register 'common' DASD debug area, used for all DBF_XXX calls */
- dasd_debug_area = debug_register("dasd", 0, 2, 8 * sizeof (long));
+ dasd_debug_area = debug_register("dasd", 1, 2, 8 * sizeof (long));
if (dasd_debug_area == NULL) {
rc = -ENOMEM;
goto failed;
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index 1aedc48e5f8..d948566bb24 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -615,7 +615,7 @@ dasd_device_from_cdev(struct ccw_device *cdev)
* readonly controls the readonly status of a dasd
*/
static ssize_t
-dasd_ro_show(struct device *dev, char *buf)
+dasd_ro_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct dasd_devmap *devmap;
int ro_flag;
@@ -629,7 +629,7 @@ dasd_ro_show(struct device *dev, char *buf)
}
static ssize_t
-dasd_ro_store(struct device *dev, const char *buf, size_t count)
+dasd_ro_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct dasd_devmap *devmap;
int ro_flag;
@@ -656,7 +656,7 @@ static DEVICE_ATTR(readonly, 0644, dasd_ro_show, dasd_ro_store);
* to talk to the device
*/
static ssize_t
-dasd_use_diag_show(struct device *dev, char *buf)
+dasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct dasd_devmap *devmap;
int use_diag;
@@ -670,7 +670,7 @@ dasd_use_diag_show(struct device *dev, char *buf)
}
static ssize_t
-dasd_use_diag_store(struct device *dev, const char *buf, size_t count)
+dasd_use_diag_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct dasd_devmap *devmap;
ssize_t rc;
@@ -698,7 +698,7 @@ static
DEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store);
static ssize_t
-dasd_discipline_show(struct device *dev, char *buf)
+dasd_discipline_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct dasd_devmap *devmap;
char *dname;
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index d7f19745911..43c34f8c5e6 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -9,13 +9,14 @@
*
* /proc interface for the dasd driver.
*
- * $Revision: 1.31 $
+ * $Revision: 1.32 $
*/
#include <linux/config.h>
#include <linux/ctype.h>
#include <linux/seq_file.h>
#include <linux/vmalloc.h>
+#include <linux/proc_fs.h>
#include <asm/debug.h>
#include <asm/uaccess.h>
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index a66b17b6529..4fde4118899 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -35,26 +35,29 @@
static int dcssblk_open(struct inode *inode, struct file *filp);
static int dcssblk_release(struct inode *inode, struct file *filp);
static int dcssblk_make_request(struct request_queue *q, struct bio *bio);
+static int dcssblk_direct_access(struct block_device *bdev, sector_t secnum,
+ unsigned long *data);
static char dcssblk_segments[DCSSBLK_PARM_LEN] = "\0";
static int dcssblk_major;
static struct block_device_operations dcssblk_devops = {
- .owner = THIS_MODULE,
- .open = dcssblk_open,
- .release = dcssblk_release,
+ .owner = THIS_MODULE,
+ .open = dcssblk_open,
+ .release = dcssblk_release,
+ .direct_access = dcssblk_direct_access,
};
-static ssize_t dcssblk_add_store(struct device * dev, const char * buf,
+static ssize_t dcssblk_add_store(struct device * dev, struct device_attribute *attr, const char * buf,
size_t count);
-static ssize_t dcssblk_remove_store(struct device * dev, const char * buf,
+static ssize_t dcssblk_remove_store(struct device * dev, struct device_attribute *attr, const char * buf,
size_t count);
-static ssize_t dcssblk_save_store(struct device * dev, const char * buf,
+static ssize_t dcssblk_save_store(struct device * dev, struct device_attribute *attr, const char * buf,
size_t count);
-static ssize_t dcssblk_save_show(struct device *dev, char *buf);
-static ssize_t dcssblk_shared_store(struct device * dev, const char * buf,
+static ssize_t dcssblk_save_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t dcssblk_shared_store(struct device * dev, struct device_attribute *attr, const char * buf,
size_t count);
-static ssize_t dcssblk_shared_show(struct device *dev, char *buf);
+static ssize_t dcssblk_shared_show(struct device *dev, struct device_attribute *attr, char *buf);
static DEVICE_ATTR(add, S_IWUSR, NULL, dcssblk_add_store);
static DEVICE_ATTR(remove, S_IWUSR, NULL, dcssblk_remove_store);
@@ -195,7 +198,7 @@ dcssblk_segment_warn(int rc, char* seg_name)
* operation (show + store)
*/
static ssize_t
-dcssblk_shared_show(struct device *dev, char *buf)
+dcssblk_shared_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct dcssblk_dev_info *dev_info;
@@ -204,7 +207,7 @@ dcssblk_shared_show(struct device *dev, char *buf)
}
static ssize_t
-dcssblk_shared_store(struct device *dev, const char *inbuf, size_t count)
+dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const char *inbuf, size_t count)
{
struct dcssblk_dev_info *dev_info;
int rc;
@@ -288,7 +291,7 @@ out:
* (show + store)
*/
static ssize_t
-dcssblk_save_show(struct device *dev, char *buf)
+dcssblk_save_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct dcssblk_dev_info *dev_info;
@@ -297,7 +300,7 @@ dcssblk_save_show(struct device *dev, char *buf)
}
static ssize_t
-dcssblk_save_store(struct device *dev, const char *inbuf, size_t count)
+dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char *inbuf, size_t count)
{
struct dcssblk_dev_info *dev_info;
@@ -343,7 +346,7 @@ dcssblk_save_store(struct device *dev, const char *inbuf, size_t count)
* device attribute for adding devices
*/
static ssize_t
-dcssblk_add_store(struct device *dev, const char *buf, size_t count)
+dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int rc, i;
struct dcssblk_dev_info *dev_info;
@@ -517,7 +520,7 @@ out_nobuf:
* device attribute for removing devices
*/
static ssize_t
-dcssblk_remove_store(struct device *dev, const char *buf, size_t count)
+dcssblk_remove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct dcssblk_dev_info *dev_info;
int rc, i;
@@ -641,6 +644,20 @@ dcssblk_make_request(request_queue_t *q, struct bio *bio)
/* Request beyond end of DCSS segment. */
goto fail;
}
+ /* verify data transfer direction */
+ if (dev_info->is_shared) {
+ switch (dev_info->segment_type) {
+ case SEG_TYPE_SR:
+ case SEG_TYPE_ER:
+ case SEG_TYPE_SC:
+ /* cannot write to these segments */
+ if (bio_data_dir(bio) == WRITE) {
+ PRINT_WARN("rejecting write to ro segment %s\n", dev_info->dev.bus_id);
+ goto fail;
+ }
+ }
+ }
+
index = (bio->bi_sector >> 3);
bio_for_each_segment(bvec, bio, i) {
page_addr = (unsigned long)
@@ -661,7 +678,26 @@ dcssblk_make_request(request_queue_t *q, struct bio *bio)
bio_endio(bio, bytes_done, 0);
return 0;
fail:
- bio_io_error(bio, bytes_done);
+ bio_io_error(bio, bio->bi_size);
+ return 0;
+}
+
+static int
+dcssblk_direct_access (struct block_device *bdev, sector_t secnum,
+ unsigned long *data)
+{
+ struct dcssblk_dev_info *dev_info;
+ unsigned long pgoff;
+
+ dev_info = bdev->bd_disk->private_data;
+ if (!dev_info)
+ return -ENODEV;
+ if (secnum % (PAGE_SIZE/512))
+ return -EINVAL;
+ pgoff = secnum / (PAGE_SIZE / 512);
+ if ((pgoff+1)*PAGE_SIZE-1 > dev_info->end - dev_info->start)
+ return -ERANGE;
+ *data = (unsigned long) (dev_info->start+pgoff*PAGE_SIZE);
return 0;
}
@@ -682,7 +718,7 @@ dcssblk_check_params(void)
buf[j-i] = dcssblk_segments[j];
}
buf[j-i] = '\0';
- rc = dcssblk_add_store(dcssblk_root_dev, buf, j-i);
+ rc = dcssblk_add_store(dcssblk_root_dev, NULL, buf, j-i);
if ((rc >= 0) && (dcssblk_segments[j] == '(')) {
for (k = 0; buf[k] != '\0'; k++)
buf[k] = toupper(buf[k]);
@@ -692,7 +728,7 @@ dcssblk_check_params(void)
up_read(&dcssblk_devices_sem);
if (dev_info)
dcssblk_shared_store(&dev_info->dev,
- "0\n", 2);
+ NULL, "0\n", 2);
}
}
while ((dcssblk_segments[j] != ',') &&
diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile
index 14e8cce9f86..6377a96735d 100644
--- a/drivers/s390/char/Makefile
+++ b/drivers/s390/char/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_SCLP_CPI) += sclp_cpi.o
obj-$(CONFIG_ZVM_WATCHDOG) += vmwatchdog.o
obj-$(CONFIG_VMLOGRDR) += vmlogrdr.o
+obj-$(CONFIG_VMCP) += vmcp.o
tape-$(CONFIG_S390_TAPE_BLOCK) += tape_block.o
tape-$(CONFIG_PROC_FS) += tape_proc.o
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 022f17bff73..f11a67fda40 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -860,8 +860,8 @@ con3215_init(void)
/* Set the console mode for VM */
if (MACHINE_IS_VM) {
- cpcmd("TERM CONMODE 3215", NULL, 0);
- cpcmd("TERM AUTOCR OFF", NULL, 0);
+ cpcmd("TERM CONMODE 3215", NULL, 0, NULL);
+ cpcmd("TERM AUTOCR OFF", NULL, 0, NULL);
}
/* allocate 3215 request structures */
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c
index d52fb57a6b1..fc7a213e591 100644
--- a/drivers/s390/char/con3270.c
+++ b/drivers/s390/char/con3270.c
@@ -591,8 +591,8 @@ con3270_init(void)
/* Set the console mode for VM */
if (MACHINE_IS_VM) {
- cpcmd("TERM CONMODE 3270", 0, 0);
- cpcmd("TERM AUTOCR OFF", 0, 0);
+ cpcmd("TERM CONMODE 3270", NULL, 0, NULL);
+ cpcmd("TERM AUTOCR OFF", NULL, 0, NULL);
}
cdev = ccw_device_probe_console();
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 8e16a971668..d5eefeaba50 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -1084,7 +1084,7 @@ raw3270_probe (struct ccw_device *cdev)
* Additional attributes for a 3270 device
*/
static ssize_t
-raw3270_model_show(struct device *dev, char *buf)
+raw3270_model_show(struct device *dev, struct device_attribute *attr, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%i\n",
((struct raw3270 *) dev->driver_data)->model);
@@ -1092,7 +1092,7 @@ raw3270_model_show(struct device *dev, char *buf)
static DEVICE_ATTR(model, 0444, raw3270_model_show, 0);
static ssize_t
-raw3270_rows_show(struct device *dev, char *buf)
+raw3270_rows_show(struct device *dev, struct device_attribute *attr, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%i\n",
((struct raw3270 *) dev->driver_data)->rows);
@@ -1100,7 +1100,7 @@ raw3270_rows_show(struct device *dev, char *buf)
static DEVICE_ATTR(rows, 0444, raw3270_rows_show, 0);
static ssize_t
-raw3270_columns_show(struct device *dev, char *buf)
+raw3270_columns_show(struct device *dev, struct device_attribute *attr, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%i\n",
((struct raw3270 *) dev->driver_data)->cols);
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c
index 480ec87976f..20be88e91fa 100644
--- a/drivers/s390/char/tape_34xx.c
+++ b/drivers/s390/char/tape_34xx.c
@@ -1351,13 +1351,13 @@ tape_34xx_init (void)
{
int rc;
- TAPE_DBF_AREA = debug_register ( "tape_34xx", 1, 2, 4*sizeof(long));
+ TAPE_DBF_AREA = debug_register ( "tape_34xx", 2, 2, 4*sizeof(long));
debug_register_view(TAPE_DBF_AREA, &debug_sprintf_view);
#ifdef DBF_LIKE_HELL
debug_set_level(TAPE_DBF_AREA, 6);
#endif
- DBF_EVENT(3, "34xx init: $Revision: 1.21 $\n");
+ DBF_EVENT(3, "34xx init: $Revision: 1.23 $\n");
/* Register driver for 3480/3490 tapes. */
rc = ccw_driver_register(&tape_34xx_driver);
if (rc)
@@ -1378,7 +1378,7 @@ tape_34xx_exit(void)
MODULE_DEVICE_TABLE(ccw, tape_34xx_ids);
MODULE_AUTHOR("(C) 2001-2002 IBM Deutschland Entwicklung GmbH");
MODULE_DESCRIPTION("Linux on zSeries channel attached 3480 tape "
- "device driver ($Revision: 1.21 $)");
+ "device driver ($Revision: 1.23 $)");
MODULE_LICENSE("GPL");
module_init(tape_34xx_init);
diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
index 0f8ffd4167c..ed0cb1f15b4 100644
--- a/drivers/s390/char/tape_class.c
+++ b/drivers/s390/char/tape_class.c
@@ -16,7 +16,7 @@ MODULE_DESCRIPTION(
);
MODULE_LICENSE("GPL");
-struct class_simple *tape_class;
+static struct class *tape_class;
/*
* Register a tape device and return a pointer to the cdev structure.
@@ -70,7 +70,7 @@ struct tape_class_device *register_tape_dev(
if (rc)
goto fail_with_cdev;
- tcd->class_device = class_simple_device_add(
+ tcd->class_device = class_device_create(
tape_class,
tcd->char_device->dev,
device,
@@ -101,7 +101,7 @@ void unregister_tape_dev(struct tape_class_device *tcd)
&tcd->class_device->dev->kobj,
tcd->mode_name
);
- class_simple_device_remove(tcd->char_device->dev);
+ class_device_destroy(tape_class, tcd->char_device->dev);
cdev_del(tcd->char_device);
kfree(tcd);
}
@@ -111,14 +111,14 @@ EXPORT_SYMBOL(unregister_tape_dev);
static int __init tape_init(void)
{
- tape_class = class_simple_create(THIS_MODULE, "tape390");
+ tape_class = class_create(THIS_MODULE, "tape390");
return 0;
}
static void __exit tape_exit(void)
{
- class_simple_destroy(tape_class);
+ class_destroy(tape_class);
tape_class = NULL;
}
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index e51046ab8ad..0597aa0e27e 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -107,7 +107,7 @@ busid_to_int(char *bus_id)
* replaced by a link to the cdev tree.
*/
static ssize_t
-tape_medium_state_show(struct device *dev, char *buf)
+tape_medium_state_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct tape_device *tdev;
@@ -119,7 +119,7 @@ static
DEVICE_ATTR(medium_state, 0444, tape_medium_state_show, NULL);
static ssize_t
-tape_first_minor_show(struct device *dev, char *buf)
+tape_first_minor_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct tape_device *tdev;
@@ -131,7 +131,7 @@ static
DEVICE_ATTR(first_minor, 0444, tape_first_minor_show, NULL);
static ssize_t
-tape_state_show(struct device *dev, char *buf)
+tape_state_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct tape_device *tdev;
@@ -144,7 +144,7 @@ static
DEVICE_ATTR(state, 0444, tape_state_show, NULL);
static ssize_t
-tape_operation_show(struct device *dev, char *buf)
+tape_operation_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct tape_device *tdev;
ssize_t rc;
@@ -171,7 +171,7 @@ static
DEVICE_ATTR(operation, 0444, tape_operation_show, NULL);
static ssize_t
-tape_blocksize_show(struct device *dev, char *buf)
+tape_blocksize_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct tape_device *tdev;
@@ -1186,7 +1186,7 @@ tape_mtop(struct tape_device *device, int mt_op, int mt_count)
static int
tape_init (void)
{
- TAPE_DBF_AREA = debug_register ( "tape", 1, 2, 4*sizeof(long));
+ TAPE_DBF_AREA = debug_register ( "tape", 2, 2, 4*sizeof(long));
debug_register_view(TAPE_DBF_AREA, &debug_sprintf_view);
#ifdef DBF_LIKE_HELL
debug_set_level(TAPE_DBF_AREA, 6);
diff --git a/drivers/s390/char/tape_proc.c b/drivers/s390/char/tape_proc.c
index 801d17cca34..5fec0a10cc3 100644
--- a/drivers/s390/char/tape_proc.c
+++ b/drivers/s390/char/tape_proc.c
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/vmalloc.h>
#include <linux/seq_file.h>
+#include <linux/proc_fs.h>
#define TAPE_DBF_AREA tape_core_dbf
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c
new file mode 100644
index 00000000000..7f11a608a63
--- /dev/null
+++ b/drivers/s390/char/vmcp.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2004,2005 IBM Corporation
+ * Interface implementation for communication with the v/VM control program
+ * Author(s): Christian Borntraeger <cborntra@de.ibm.com>
+ *
+ *
+ * z/VMs CP offers the possibility to issue commands via the diagnose code 8
+ * this driver implements a character device that issues these commands and
+ * returns the answer of CP.
+
+ * The idea of this driver is based on cpint from Neale Ferguson and #CP in CMS
+ */
+
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <asm/cpcmd.h>
+#include <asm/debug.h>
+#include <asm/uaccess.h>
+#include "vmcp.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Borntraeger <cborntra@de.ibm.com>");
+MODULE_DESCRIPTION("z/VM CP interface");
+
+static debug_info_t *vmcp_debug;
+
+static int vmcp_open(struct inode *inode, struct file *file)
+{
+ struct vmcp_session *session;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ session = kmalloc(sizeof(*session), GFP_KERNEL);
+ if (!session)
+ return -ENOMEM;
+ session->bufsize = PAGE_SIZE;
+ session->response = NULL;
+ session->resp_size = 0;
+ init_MUTEX(&session->mutex);
+ file->private_data = session;
+ return nonseekable_open(inode, file);
+}
+
+static int vmcp_release(struct inode *inode, struct file *file)
+{
+ struct vmcp_session *session;
+
+ session = (struct vmcp_session *)file->private_data;
+ file->private_data = NULL;
+ free_pages((unsigned long)session->response, get_order(session->bufsize));
+ kfree(session);
+ return 0;
+}
+
+static ssize_t
+vmcp_read(struct file *file, char __user * buff, size_t count, loff_t * ppos)
+{
+ size_t tocopy;
+ struct vmcp_session *session;
+
+ session = (struct vmcp_session *)file->private_data;
+ if (down_interruptible(&session->mutex))
+ return -ERESTARTSYS;
+ if (!session->response) {
+ up(&session->mutex);
+ return 0;
+ }
+ if (*ppos > session->resp_size) {
+ up(&session->mutex);
+ return 0;
+ }
+ tocopy = min(session->resp_size - (size_t) (*ppos), count);
+ tocopy = min(tocopy,session->bufsize - (size_t) (*ppos));
+
+ if (copy_to_user(buff, session->response + (*ppos), tocopy)) {
+ up(&session->mutex);
+ return -EFAULT;
+ }
+ up(&session->mutex);
+ *ppos += tocopy;
+ return tocopy;
+}
+
+static ssize_t
+vmcp_write(struct file *file, const char __user * buff, size_t count,
+ loff_t * ppos)
+{
+ char *cmd;
+ struct vmcp_session *session;
+
+ if (count > 240)
+ return -EINVAL;
+ cmd = kmalloc(count + 1, GFP_KERNEL);
+ if (!cmd)
+ return -ENOMEM;
+ if (copy_from_user(cmd, buff, count)) {
+ kfree(cmd);
+ return -EFAULT;
+ }
+ cmd[count] = '\0';
+ session = (struct vmcp_session *)file->private_data;
+ if (down_interruptible(&session->mutex))
+ return -ERESTARTSYS;
+ if (!session->response)
+ session->response = (char *)__get_free_pages(GFP_KERNEL
+ | __GFP_REPEAT | GFP_DMA,
+ get_order(session->bufsize));
+ if (!session->response) {
+ up(&session->mutex);
+ kfree(cmd);
+ return -ENOMEM;
+ }
+ debug_text_event(vmcp_debug, 1, cmd);
+ session->resp_size = cpcmd(cmd, session->response,
+ session->bufsize,
+ &session->resp_code);
+ up(&session->mutex);
+ kfree(cmd);
+ *ppos = 0; /* reset the file pointer after a command */
+ return count;
+}
+
+
+/*
+ * These ioctls are available, as the semantics of the diagnose 8 call
+ * does not fit very well into a Linux call. Diagnose X'08' is described in
+ * CP Programming Services SC24-6084-00
+ *
+ * VMCP_GETCODE: gives the CP return code back to user space
+ * VMCP_SETBUF: sets the response buffer for the next write call. diagnose 8
+ * expects adjacent pages in real storage and to make matters worse, we
+ * dont know the size of the response. Therefore we default to PAGESIZE and
+ * let userspace to change the response size, if userspace expects a bigger
+ * response
+ */
+static long vmcp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct vmcp_session *session;
+ int temp;
+
+ session = (struct vmcp_session *)file->private_data;
+ if (down_interruptible(&session->mutex))
+ return -ERESTARTSYS;
+ switch (cmd) {
+ case VMCP_GETCODE:
+ temp = session->resp_code;
+ up(&session->mutex);
+ return put_user(temp, (int __user *)arg);
+ case VMCP_SETBUF:
+ free_pages((unsigned long)session->response,
+ get_order(session->bufsize));
+ session->response=NULL;
+ temp = get_user(session->bufsize, (int __user *)arg);
+ if (get_order(session->bufsize) > 8) {
+ session->bufsize = PAGE_SIZE;
+ temp = -EINVAL;
+ }
+ up(&session->mutex);
+ return temp;
+ case VMCP_GETSIZE:
+ temp = session->resp_size;
+ up(&session->mutex);
+ return put_user(temp, (int __user *)arg);
+ default:
+ up(&session->mutex);
+ return -ENOIOCTLCMD;
+ }
+}
+
+static struct file_operations vmcp_fops = {
+ .owner = THIS_MODULE,
+ .open = &vmcp_open,
+ .release = &vmcp_release,
+ .read = &vmcp_read,
+ .llseek = &no_llseek,
+ .write = &vmcp_write,
+ .unlocked_ioctl = &vmcp_ioctl,
+ .compat_ioctl = &vmcp_ioctl
+};
+
+static struct miscdevice vmcp_dev = {
+ .name = "vmcp",
+ .minor = MISC_DYNAMIC_MINOR,
+ .fops = &vmcp_fops,
+};
+
+static int __init vmcp_init(void)
+{
+ int ret;
+
+ if (!MACHINE_IS_VM) {
+ printk(KERN_WARNING
+ "z/VM CP interface is only available under z/VM\n");
+ return -ENODEV;
+ }
+ ret = misc_register(&vmcp_dev);
+ if (!ret)
+ printk(KERN_INFO "z/VM CP interface loaded\n");
+ else
+ printk(KERN_WARNING
+ "z/VM CP interface not loaded. Could not register misc device.\n");
+ vmcp_debug = debug_register("vmcp", 1, 1, 240);
+ debug_register_view(vmcp_debug, &debug_hex_ascii_view);
+ return ret;
+}
+
+static void __exit vmcp_exit(void)
+{
+ WARN_ON(misc_deregister(&vmcp_dev) != 0);
+ debug_unregister(vmcp_debug);
+ printk(KERN_INFO "z/VM CP interface unloaded.\n");
+}
+
+module_init(vmcp_init);
+module_exit(vmcp_exit);
diff --git a/drivers/s390/char/vmcp.h b/drivers/s390/char/vmcp.h
new file mode 100644
index 00000000000..87389e73046
--- /dev/null
+++ b/drivers/s390/char/vmcp.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2004, 2005 IBM Corporation
+ * Interface implementation for communication with the v/VM control program
+ * Version 1.0
+ * Author(s): Christian Borntraeger <cborntra@de.ibm.com>
+ *
+ *
+ * z/VMs CP offers the possibility to issue commands via the diagnose code 8
+ * this driver implements a character device that issues these commands and
+ * returns the answer of CP.
+ *
+ * The idea of this driver is based on cpint from Neale Ferguson
+ */
+
+#include <asm/semaphore.h>
+#include <linux/ioctl.h>
+
+#define VMCP_GETCODE _IOR(0x10, 1, int)
+#define VMCP_SETBUF _IOW(0x10, 2, int)
+#define VMCP_GETSIZE _IOR(0x10, 3, int)
+
+struct vmcp_session {
+ unsigned int bufsize;
+ char *response;
+ int resp_size;
+ int resp_code;
+ /* As we use copy_from/to_user, which might *
+ * sleep and cannot use a spinlock */
+ struct semaphore mutex;
+};
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index edf50d2bd10..491f00c032e 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -236,7 +236,7 @@ vmlogrdr_get_recording_class_AB(void) {
int len,i;
printk (KERN_DEBUG "vmlogrdr: query command: %s\n", cp_command);
- cpcmd(cp_command, cp_response, sizeof(cp_response));
+ cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
printk (KERN_DEBUG "vmlogrdr: response: %s", cp_response);
len = strnlen(cp_response,sizeof(cp_response));
// now the parsing
@@ -288,7 +288,7 @@ vmlogrdr_recording(struct vmlogrdr_priv_t * logptr, int action, int purge) {
printk (KERN_DEBUG "vmlogrdr: recording command: %s\n",
cp_command);
- cpcmd(cp_command, cp_response, sizeof(cp_response));
+ cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
printk (KERN_DEBUG "vmlogrdr: recording response: %s",
cp_response);
}
@@ -301,7 +301,7 @@ vmlogrdr_recording(struct vmlogrdr_priv_t * logptr, int action, int purge) {
qid_string);
printk (KERN_DEBUG "vmlogrdr: recording command: %s\n", cp_command);
- cpcmd(cp_command, cp_response, sizeof(cp_response));
+ cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
printk (KERN_DEBUG "vmlogrdr: recording response: %s",
cp_response);
/* The recording command will usually answer with 'Command complete'
@@ -548,7 +548,7 @@ vmlogrdr_read (struct file *filp, char *data, size_t count, loff_t * ppos)
}
static ssize_t
-vmlogrdr_autopurge_store(struct device * dev, const char * buf, size_t count) {
+vmlogrdr_autopurge_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) {
struct vmlogrdr_priv_t *priv = dev->driver_data;
ssize_t ret = count;
@@ -567,7 +567,7 @@ vmlogrdr_autopurge_store(struct device * dev, const char * buf, size_t count) {
static ssize_t
-vmlogrdr_autopurge_show(struct device *dev, char *buf) {
+vmlogrdr_autopurge_show(struct device *dev, struct device_attribute *attr, char *buf) {
struct vmlogrdr_priv_t *priv = dev->driver_data;
return sprintf(buf, "%u\n", priv->autopurge);
}
@@ -578,7 +578,7 @@ static DEVICE_ATTR(autopurge, 0644, vmlogrdr_autopurge_show,
static ssize_t
-vmlogrdr_purge_store(struct device * dev, const char * buf, size_t count) {
+vmlogrdr_purge_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) {
char cp_command[80];
char cp_response[80];
@@ -607,7 +607,7 @@ vmlogrdr_purge_store(struct device * dev, const char * buf, size_t count) {
priv->recording_name);
printk (KERN_DEBUG "vmlogrdr: recording command: %s\n", cp_command);
- cpcmd(cp_command, cp_response, sizeof(cp_response));
+ cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
printk (KERN_DEBUG "vmlogrdr: recording response: %s",
cp_response);
@@ -619,7 +619,7 @@ static DEVICE_ATTR(purge, 0200, NULL, vmlogrdr_purge_store);
static ssize_t
-vmlogrdr_autorecording_store(struct device *dev, const char *buf,
+vmlogrdr_autorecording_store(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count) {
struct vmlogrdr_priv_t *priv = dev->driver_data;
ssize_t ret = count;
@@ -639,7 +639,7 @@ vmlogrdr_autorecording_store(struct device *dev, const char *buf,
static ssize_t
-vmlogrdr_autorecording_show(struct device *dev, char *buf) {
+vmlogrdr_autorecording_show(struct device *dev, struct device_attribute *attr, char *buf) {
struct vmlogrdr_priv_t *priv = dev->driver_data;
return sprintf(buf, "%u\n", priv->autorecording);
}
@@ -650,7 +650,7 @@ static DEVICE_ATTR(autorecording, 0644, vmlogrdr_autorecording_show,
static ssize_t
-vmlogrdr_recording_store(struct device * dev, const char * buf, size_t count) {
+vmlogrdr_recording_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) {
struct vmlogrdr_priv_t *priv = dev->driver_data;
ssize_t ret;
@@ -682,7 +682,7 @@ vmlogrdr_recording_status_show(struct device_driver *driver, char *buf) {
char cp_command[] = "QUERY RECORDING ";
int len;
- cpcmd(cp_command, buf, 4096);
+ cpcmd(cp_command, buf, 4096, NULL);
len = strlen(buf);
return len;
}
@@ -703,7 +703,7 @@ static struct attribute_group vmlogrdr_attr_group = {
.attrs = vmlogrdr_attrs,
};
-static struct class_simple *vmlogrdr_class;
+static struct class *vmlogrdr_class;
static struct device_driver vmlogrdr_driver = {
.name = "vmlogrdr",
.bus = &iucv_bus,
@@ -727,7 +727,7 @@ vmlogrdr_register_driver(void) {
goto unregdriver;
}
- vmlogrdr_class = class_simple_create(THIS_MODULE, "vmlogrdr");
+ vmlogrdr_class = class_create(THIS_MODULE, "vmlogrdr");
if (IS_ERR(vmlogrdr_class)) {
printk(KERN_ERR "vmlogrdr: failed to create class.\n");
ret=PTR_ERR(vmlogrdr_class);
@@ -746,7 +746,7 @@ unregdriver:
static void
vmlogrdr_unregister_driver(void) {
- class_simple_destroy(vmlogrdr_class);
+ class_destroy(vmlogrdr_class);
vmlogrdr_class = NULL;
driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status);
driver_unregister(&vmlogrdr_driver);
@@ -786,7 +786,7 @@ vmlogrdr_register_device(struct vmlogrdr_priv_t *priv) {
device_unregister(dev);
return ret;
}
- priv->class_device = class_simple_device_add(
+ priv->class_device = class_device_create(
vmlogrdr_class,
MKDEV(vmlogrdr_major, priv->minor_num),
dev,
@@ -806,7 +806,7 @@ vmlogrdr_register_device(struct vmlogrdr_priv_t *priv) {
static int
vmlogrdr_unregister_device(struct vmlogrdr_priv_t *priv ) {
- class_simple_device_remove(MKDEV(vmlogrdr_major, priv->minor_num));
+ class_device_destroy(vmlogrdr_class, MKDEV(vmlogrdr_major, priv->minor_num));
if (priv->device != NULL) {
sysfs_remove_group(&priv->device->kobj, &vmlogrdr_attr_group);
device_unregister(priv->device);
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index 4a06c7d0e5e..aac83ce6469 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/blacklist.c
* S/390 common I/O routines -- blacklisting of specific devices
- * $Revision: 1.33 $
+ * $Revision: 1.34 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -289,7 +289,7 @@ static int cio_ignore_read (char *page, char **start, off_t off,
len = 0;
for (devno = off; /* abuse the page variable
* as counter, see fs/proc/generic.c */
- devno <= __MAX_SUBCHANNELS && len + entry_size < count; devno++) {
+ devno < __MAX_SUBCHANNELS && len + entry_size < count; devno++) {
if (!test_bit(devno, bl_dev))
continue;
len += sprintf(page + len, "0.0.%04lx", devno);
@@ -302,7 +302,7 @@ static int cio_ignore_read (char *page, char **start, off_t off,
len += sprintf(page + len, "\n");
}
- if (devno <= __MAX_SUBCHANNELS)
+ if (devno < __MAX_SUBCHANNELS)
*eof = 1;
*start = (char *) (devno - off); /* number of checked entries */
return len;
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index 21a75ee28b8..91ea8e4777f 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -77,7 +77,7 @@ __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
* longer needed or accidentially created. Saves memory :)
*/
static ssize_t
-ccwgroup_ungroup_store(struct device *dev, const char *buf, size_t count)
+ccwgroup_ungroup_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct ccwgroup_device *gdev;
@@ -310,7 +310,7 @@ ccwgroup_set_offline(struct ccwgroup_device *gdev)
}
static ssize_t
-ccwgroup_online_store (struct device *dev, const char *buf, size_t count)
+ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct ccwgroup_device *gdev;
struct ccwgroup_driver *gdrv;
@@ -338,7 +338,7 @@ ccwgroup_online_store (struct device *dev, const char *buf, size_t count)
}
static ssize_t
-ccwgroup_online_show (struct device *dev, char *buf)
+ccwgroup_online_show (struct device *dev, struct device_attribute *attr, char *buf)
{
int online;
@@ -403,34 +403,22 @@ ccwgroup_driver_register (struct ccwgroup_driver *cdriver)
return driver_register(&cdriver->driver);
}
-static inline struct device *
-__get_next_ccwgroup_device(struct device_driver *drv)
+static int
+__ccwgroup_driver_unregister_device(struct device *dev, void *data)
{
- struct device *dev, *d;
-
- down_read(&drv->bus->subsys.rwsem);
- dev = NULL;
- list_for_each_entry(d, &drv->devices, driver_list) {
- dev = get_device(d);
- if (dev)
- break;
- }
- up_read(&drv->bus->subsys.rwsem);
- return dev;
+ __ccwgroup_remove_symlinks(to_ccwgroupdev(dev));
+ device_unregister(dev);
+ put_device(dev);
+ return 0;
}
void
ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver)
{
- struct device *dev;
-
/* We don't want ccwgroup devices to live longer than their driver. */
get_driver(&cdriver->driver);
- while ((dev = __get_next_ccwgroup_device(&cdriver->driver))) {
- __ccwgroup_remove_symlinks(to_ccwgroupdev(dev));
- device_unregister(dev);
- put_device(dev);
- };
+ driver_for_each_device(&cdriver->driver, NULL, NULL,
+ __ccwgroup_driver_unregister_device);
put_driver(&cdriver->driver);
driver_unregister(&cdriver->driver);
}
@@ -449,7 +437,7 @@ __ccwgroup_get_gdev_by_cdev(struct ccw_device *cdev)
if (cdev->dev.driver_data) {
gdev = (struct ccwgroup_device *)cdev->dev.driver_data;
if (get_device(&gdev->dev)) {
- if (!list_empty(&gdev->dev.node))
+ if (klist_node_attached(&gdev->dev.knode_bus))
return gdev;
put_device(&gdev->dev);
}
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index b35fe12e6bf..b86f94ecd87 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -852,7 +852,7 @@ out:
* Files for the channel path entries.
*/
static ssize_t
-chp_status_show(struct device *dev, char *buf)
+chp_status_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct channel_path *chp = container_of(dev, struct channel_path, dev);
@@ -863,7 +863,7 @@ chp_status_show(struct device *dev, char *buf)
}
static ssize_t
-chp_status_write(struct device *dev, const char *buf, size_t count)
+chp_status_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct channel_path *cp = container_of(dev, struct channel_path, dev);
char cmd[10];
@@ -888,7 +888,7 @@ chp_status_write(struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(status, 0644, chp_status_show, chp_status_write);
static ssize_t
-chp_type_show(struct device *dev, char *buf)
+chp_type_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct channel_path *chp = container_of(dev, struct channel_path, dev);
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 1d9b3f18d8d..ea813bdce1d 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -1,7 +1,7 @@
/*
* drivers/s390/cio/cio.c
* S/390 common I/O routines -- low level i/o calls
- * $Revision: 1.133 $
+ * $Revision: 1.134 $
*
* Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
* IBM Corporation
@@ -63,17 +63,17 @@ __setup ("cio_msg=", cio_setup);
static int __init
cio_debug_init (void)
{
- cio_debug_msg_id = debug_register ("cio_msg", 4, 4, 16*sizeof (long));
+ cio_debug_msg_id = debug_register ("cio_msg", 16, 4, 16*sizeof (long));
if (!cio_debug_msg_id)
goto out_unregister;
debug_register_view (cio_debug_msg_id, &debug_sprintf_view);
debug_set_level (cio_debug_msg_id, 2);
- cio_debug_trace_id = debug_register ("cio_trace", 4, 4, 8);
+ cio_debug_trace_id = debug_register ("cio_trace", 16, 4, 8);
if (!cio_debug_trace_id)
goto out_unregister;
debug_register_view (cio_debug_trace_id, &debug_hex_ascii_view);
debug_set_level (cio_debug_trace_id, 2);
- cio_debug_crw_id = debug_register ("cio_crw", 2, 4, 16*sizeof (long));
+ cio_debug_crw_id = debug_register ("cio_crw", 4, 4, 16*sizeof (long));
if (!cio_debug_crw_id)
goto out_unregister;
debug_register_view (cio_debug_crw_id, &debug_sprintf_view);
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index 49def26ba38..8cc4f1a940d 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -796,7 +796,7 @@ cmb_show_attr(struct device *dev, char *buf, enum cmb_index idx)
}
static ssize_t
-cmb_show_avg_sample_interval(struct device *dev, char *buf)
+cmb_show_avg_sample_interval(struct device *dev, struct device_attribute *attr, char *buf)
{
struct ccw_device *cdev;
long interval;
@@ -813,7 +813,7 @@ cmb_show_avg_sample_interval(struct device *dev, char *buf)
}
static ssize_t
-cmb_show_avg_utilization(struct device *dev, char *buf)
+cmb_show_avg_utilization(struct device *dev, struct device_attribute *attr, char *buf)
{
struct cmbdata data;
u64 utilization;
@@ -842,12 +842,12 @@ cmb_show_avg_utilization(struct device *dev, char *buf)
}
#define cmf_attr(name) \
-static ssize_t show_ ## name (struct device * dev, char * buf) \
+static ssize_t show_ ## name (struct device * dev, struct device_attribute *attr, char * buf) \
{ return cmb_show_attr((dev), buf, cmb_ ## name); } \
static DEVICE_ATTR(name, 0444, show_ ## name, NULL);
#define cmf_attr_avg(name) \
-static ssize_t show_avg_ ## name (struct device * dev, char * buf) \
+static ssize_t show_avg_ ## name (struct device * dev, struct device_attribute *attr, char * buf) \
{ return cmb_show_attr((dev), buf, cmb_ ## name); } \
static DEVICE_ATTR(avg_ ## name, 0444, show_avg_ ## name, NULL);
@@ -902,12 +902,12 @@ static struct attribute_group cmf_attr_group_ext = {
.attrs = cmf_attributes_ext,
};
-static ssize_t cmb_enable_show(struct device *dev, char *buf)
+static ssize_t cmb_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", to_ccwdev(dev)->private->cmb ? 1 : 0);
}
-static ssize_t cmb_enable_store(struct device *dev, const char *buf, size_t c)
+static ssize_t cmb_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t c)
{
struct ccw_device *cdev;
int ret;
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 87bd70eeabe..555119cacc2 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -128,34 +128,28 @@ css_probe_device(int irq)
return ret;
}
+static int
+check_subchannel(struct device * dev, void * data)
+{
+ struct subchannel *sch;
+ int irq = (unsigned long)data;
+
+ sch = to_subchannel(dev);
+ return (sch->irq == irq);
+}
+
struct subchannel *
get_subchannel_by_schid(int irq)
{
- struct subchannel *sch;
- struct list_head *entry;
struct device *dev;
- if (!get_bus(&css_bus_type))
- return NULL;
- down_read(&css_bus_type.subsys.rwsem);
- sch = NULL;
- list_for_each(entry, &css_bus_type.devices.list) {
- dev = get_device(container_of(entry,
- struct device, bus_list));
- if (!dev)
- continue;
- sch = to_subchannel(dev);
- if (sch->irq == irq)
- break;
- put_device(dev);
- sch = NULL;
- }
- up_read(&css_bus_type.subsys.rwsem);
- put_bus(&css_bus_type);
+ dev = bus_find_device(&css_bus_type, NULL,
+ (void *)(unsigned long)irq, check_subchannel);
- return sch;
+ return dev ? to_subchannel(dev) : NULL;
}
+
static inline int
css_get_subchannel_status(struct subchannel *sch, int schid)
{
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index df0325505e4..14c76f5e417 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -204,7 +204,7 @@ module_exit(cleanup_ccw_bus_type);
* TODO: Split chpids and pimpampom up? Where is "in use" in the tree?
*/
static ssize_t
-chpids_show (struct device * dev, char * buf)
+chpids_show (struct device * dev, struct device_attribute *attr, char * buf)
{
struct subchannel *sch = to_subchannel(dev);
struct ssd_info *ssd = &sch->ssd_info;
@@ -219,7 +219,7 @@ chpids_show (struct device * dev, char * buf)
}
static ssize_t
-pimpampom_show (struct device * dev, char * buf)
+pimpampom_show (struct device * dev, struct device_attribute *attr, char * buf)
{
struct subchannel *sch = to_subchannel(dev);
struct pmcw *pmcw = &sch->schib.pmcw;
@@ -229,7 +229,7 @@ pimpampom_show (struct device * dev, char * buf)
}
static ssize_t
-devtype_show (struct device *dev, char *buf)
+devtype_show (struct device *dev, struct device_attribute *attr, char *buf)
{
struct ccw_device *cdev = to_ccwdev(dev);
struct ccw_device_id *id = &(cdev->id);
@@ -242,7 +242,7 @@ devtype_show (struct device *dev, char *buf)
}
static ssize_t
-cutype_show (struct device *dev, char *buf)
+cutype_show (struct device *dev, struct device_attribute *attr, char *buf)
{
struct ccw_device *cdev = to_ccwdev(dev);
struct ccw_device_id *id = &(cdev->id);
@@ -252,7 +252,7 @@ cutype_show (struct device *dev, char *buf)
}
static ssize_t
-online_show (struct device *dev, char *buf)
+online_show (struct device *dev, struct device_attribute *attr, char *buf)
{
struct ccw_device *cdev = to_ccwdev(dev);
@@ -350,7 +350,7 @@ ccw_device_set_online(struct ccw_device *cdev)
}
static ssize_t
-online_store (struct device *dev, const char *buf, size_t count)
+online_store (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct ccw_device *cdev = to_ccwdev(dev);
int i, force, ret;
@@ -422,7 +422,7 @@ online_store (struct device *dev, const char *buf, size_t count)
}
static ssize_t
-available_show (struct device *dev, char *buf)
+available_show (struct device *dev, struct device_attribute *attr, char *buf)
{
struct ccw_device *cdev = to_ccwdev(dev);
struct subchannel *sch;
@@ -514,36 +514,39 @@ ccw_device_register(struct ccw_device *cdev)
return ret;
}
+struct match_data {
+ unsigned int devno;
+ struct ccw_device * sibling;
+};
+
+static int
+match_devno(struct device * dev, void * data)
+{
+ struct match_data * d = (struct match_data *)data;
+ struct ccw_device * cdev;
+
+ cdev = to_ccwdev(dev);
+ if ((cdev->private->state == DEV_STATE_DISCONNECTED) &&
+ (cdev->private->devno == d->devno) &&
+ (cdev != d->sibling)) {
+ cdev->private->state = DEV_STATE_NOT_OPER;
+ return 1;
+ }
+ return 0;
+}
+
static struct ccw_device *
get_disc_ccwdev_by_devno(unsigned int devno, struct ccw_device *sibling)
{
- struct ccw_device *cdev;
- struct list_head *entry;
struct device *dev;
+ struct match_data data = {
+ .devno = devno,
+ .sibling = sibling,
+ };
- if (!get_bus(&ccw_bus_type))
- return NULL;
- down_read(&ccw_bus_type.subsys.rwsem);
- cdev = NULL;
- list_for_each(entry, &ccw_bus_type.devices.list) {
- dev = get_device(container_of(entry,
- struct device, bus_list));
- if (!dev)
- continue;
- cdev = to_ccwdev(dev);
- if ((cdev->private->state == DEV_STATE_DISCONNECTED) &&
- (cdev->private->devno == devno) &&
- (cdev != sibling)) {
- cdev->private->state = DEV_STATE_NOT_OPER;
- break;
- }
- put_device(dev);
- cdev = NULL;
- }
- up_read(&ccw_bus_type.subsys.rwsem);
- put_bus(&ccw_bus_type);
+ dev = bus_find_device(&css_bus_type, NULL, &data, match_devno);
- return cdev;
+ return dev ? to_ccwdev(dev) : NULL;
}
static void
@@ -647,7 +650,7 @@ io_subchannel_register(void *data)
cdev = (struct ccw_device *) data;
sch = to_subchannel(cdev->dev.parent);
- if (!list_empty(&sch->dev.children)) {
+ if (klist_node_attached(&cdev->dev.knode_parent)) {
bus_rescan_devices(&ccw_bus_type);
goto out;
}
@@ -1019,30 +1022,29 @@ ccw_device_probe_console(void)
/*
* get ccw_device matching the busid, but only if owned by cdrv
*/
+static int
+__ccwdev_check_busid(struct device *dev, void *id)
+{
+ char *bus_id;
+
+ bus_id = (char *)id;
+
+ return (strncmp(bus_id, dev->bus_id, BUS_ID_SIZE) == 0);
+}
+
+
struct ccw_device *
get_ccwdev_by_busid(struct ccw_driver *cdrv, const char *bus_id)
{
- struct device *d, *dev;
+ struct device *dev;
struct device_driver *drv;
drv = get_driver(&cdrv->driver);
if (!drv)
- return 0;
-
- down_read(&drv->bus->subsys.rwsem);
-
- dev = NULL;
- list_for_each_entry(d, &drv->devices, driver_list) {
- dev = get_device(d);
+ return NULL;
- if (dev && !strncmp(bus_id, dev->bus_id, BUS_ID_SIZE))
- break;
- else if (dev) {
- put_device(dev);
- dev = NULL;
- }
- }
- up_read(&drv->bus->subsys.rwsem);
+ dev = driver_find_device(drv, NULL, (void *)bus_id,
+ __ccwdev_check_busid);
put_driver(drv);
return dev ? to_ccwdev(dev) : 0;
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index bbe9f45d143..82194c4eadf 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -56,7 +56,7 @@
#include "ioasm.h"
#include "chsc.h"
-#define VERSION_QDIO_C "$Revision: 1.98 $"
+#define VERSION_QDIO_C "$Revision: 1.101 $"
/****************** MODULE PARAMETER VARIABLES ********************/
MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
@@ -3342,7 +3342,7 @@ static int
qdio_register_dbf_views(void)
{
qdio_dbf_setup=debug_register(QDIO_DBF_SETUP_NAME,
- QDIO_DBF_SETUP_INDEX,
+ QDIO_DBF_SETUP_PAGES,
QDIO_DBF_SETUP_NR_AREAS,
QDIO_DBF_SETUP_LEN);
if (!qdio_dbf_setup)
@@ -3351,7 +3351,7 @@ qdio_register_dbf_views(void)
debug_set_level(qdio_dbf_setup,QDIO_DBF_SETUP_LEVEL);
qdio_dbf_sbal=debug_register(QDIO_DBF_SBAL_NAME,
- QDIO_DBF_SBAL_INDEX,
+ QDIO_DBF_SBAL_PAGES,
QDIO_DBF_SBAL_NR_AREAS,
QDIO_DBF_SBAL_LEN);
if (!qdio_dbf_sbal)
@@ -3361,7 +3361,7 @@ qdio_register_dbf_views(void)
debug_set_level(qdio_dbf_sbal,QDIO_DBF_SBAL_LEVEL);
qdio_dbf_sense=debug_register(QDIO_DBF_SENSE_NAME,
- QDIO_DBF_SENSE_INDEX,
+ QDIO_DBF_SENSE_PAGES,
QDIO_DBF_SENSE_NR_AREAS,
QDIO_DBF_SENSE_LEN);
if (!qdio_dbf_sense)
@@ -3371,7 +3371,7 @@ qdio_register_dbf_views(void)
debug_set_level(qdio_dbf_sense,QDIO_DBF_SENSE_LEVEL);
qdio_dbf_trace=debug_register(QDIO_DBF_TRACE_NAME,
- QDIO_DBF_TRACE_INDEX,
+ QDIO_DBF_TRACE_PAGES,
QDIO_DBF_TRACE_NR_AREAS,
QDIO_DBF_TRACE_LEN);
if (!qdio_dbf_trace)
@@ -3382,7 +3382,7 @@ qdio_register_dbf_views(void)
#ifdef CONFIG_QDIO_DEBUG
qdio_dbf_slsb_out=debug_register(QDIO_DBF_SLSB_OUT_NAME,
- QDIO_DBF_SLSB_OUT_INDEX,
+ QDIO_DBF_SLSB_OUT_PAGES,
QDIO_DBF_SLSB_OUT_NR_AREAS,
QDIO_DBF_SLSB_OUT_LEN);
if (!qdio_dbf_slsb_out)
@@ -3391,7 +3391,7 @@ qdio_register_dbf_views(void)
debug_set_level(qdio_dbf_slsb_out,QDIO_DBF_SLSB_OUT_LEVEL);
qdio_dbf_slsb_in=debug_register(QDIO_DBF_SLSB_IN_NAME,
- QDIO_DBF_SLSB_IN_INDEX,
+ QDIO_DBF_SLSB_IN_PAGES,
QDIO_DBF_SLSB_IN_NR_AREAS,
QDIO_DBF_SLSB_IN_LEN);
if (!qdio_dbf_slsb_in)
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index b6daadac4e8..6b8aa6a852b 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -3,7 +3,7 @@
#include <asm/page.h>
-#define VERSION_CIO_QDIO_H "$Revision: 1.32 $"
+#define VERSION_CIO_QDIO_H "$Revision: 1.33 $"
#ifdef CONFIG_QDIO_DEBUG
#define QDIO_VERBOSE_LEVEL 9
@@ -132,7 +132,7 @@ enum qdio_irq_states {
#define QDIO_DBF_SETUP_NAME "qdio_setup"
#define QDIO_DBF_SETUP_LEN 8
-#define QDIO_DBF_SETUP_INDEX 2
+#define QDIO_DBF_SETUP_PAGES 4
#define QDIO_DBF_SETUP_NR_AREAS 1
#ifdef CONFIG_QDIO_DEBUG
#define QDIO_DBF_SETUP_LEVEL 6
@@ -142,7 +142,7 @@ enum qdio_irq_states {
#define QDIO_DBF_SBAL_NAME "qdio_labs" /* sbal */
#define QDIO_DBF_SBAL_LEN 256
-#define QDIO_DBF_SBAL_INDEX 2
+#define QDIO_DBF_SBAL_PAGES 4
#define QDIO_DBF_SBAL_NR_AREAS 2
#ifdef CONFIG_QDIO_DEBUG
#define QDIO_DBF_SBAL_LEVEL 6
@@ -154,16 +154,16 @@ enum qdio_irq_states {
#define QDIO_DBF_TRACE_LEN 8
#define QDIO_DBF_TRACE_NR_AREAS 2
#ifdef CONFIG_QDIO_DEBUG
-#define QDIO_DBF_TRACE_INDEX 4
+#define QDIO_DBF_TRACE_PAGES 16
#define QDIO_DBF_TRACE_LEVEL 4 /* -------- could be even more verbose here */
#else /* CONFIG_QDIO_DEBUG */
-#define QDIO_DBF_TRACE_INDEX 2
+#define QDIO_DBF_TRACE_PAGES 4
#define QDIO_DBF_TRACE_LEVEL 2
#endif /* CONFIG_QDIO_DEBUG */
#define QDIO_DBF_SENSE_NAME "qdio_sense"
#define QDIO_DBF_SENSE_LEN 64
-#define QDIO_DBF_SENSE_INDEX 1
+#define QDIO_DBF_SENSE_PAGES 2
#define QDIO_DBF_SENSE_NR_AREAS 1
#ifdef CONFIG_QDIO_DEBUG
#define QDIO_DBF_SENSE_LEVEL 6
@@ -176,13 +176,13 @@ enum qdio_irq_states {
#define QDIO_DBF_SLSB_OUT_NAME "qdio_slsb_out"
#define QDIO_DBF_SLSB_OUT_LEN QDIO_MAX_BUFFERS_PER_Q
-#define QDIO_DBF_SLSB_OUT_INDEX 8
+#define QDIO_DBF_SLSB_OUT_PAGES 256
#define QDIO_DBF_SLSB_OUT_NR_AREAS 1
#define QDIO_DBF_SLSB_OUT_LEVEL 6
#define QDIO_DBF_SLSB_IN_NAME "qdio_slsb_in"
#define QDIO_DBF_SLSB_IN_LEN QDIO_MAX_BUFFERS_PER_Q
-#define QDIO_DBF_SLSB_IN_INDEX 8
+#define QDIO_DBF_SLSB_IN_PAGES 256
#define QDIO_DBF_SLSB_IN_NR_AREAS 1
#define QDIO_DBF_SLSB_IN_LEVEL 6
#endif /* CONFIG_QDIO_DEBUG */
diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile
index 7cabb80a2e4..90d4d0ef3dd 100644
--- a/drivers/s390/net/Makefile
+++ b/drivers/s390/net/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o
obj-$(CONFIG_LCS) += lcs.o cu3088.o
-qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o qeth_tso.o
+obj-$(CONFIG_CLAW) += claw.o cu3088.o
+qeth-y := qeth_main.o qeth_mpc.o qeth_sys.o qeth_eddp.o
qeth-$(CONFIG_PROC_FS) += qeth_proc.o
obj-$(CONFIG_QETH) += qeth.o
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index 06804d39a9c..60440dbe3a2 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -146,8 +146,8 @@ claw_unregister_debug_facility(void)
static int
claw_register_debug_facility(void)
{
- claw_dbf_setup = debug_register("claw_setup", 1, 1, 8);
- claw_dbf_trace = debug_register("claw_trace", 1, 2, 8);
+ claw_dbf_setup = debug_register("claw_setup", 2, 1, 8);
+ claw_dbf_trace = debug_register("claw_trace", 2, 2, 8);
if (claw_dbf_setup == NULL || claw_dbf_trace == NULL) {
printk(KERN_WARNING "Not enough memory for debug facility.\n");
claw_unregister_debug_facility();
@@ -241,20 +241,20 @@ static struct sk_buff *claw_pack_skb(struct claw_privbk *privptr);
static void dumpit (char *buf, int len);
#endif
/* sysfs Functions */
-static ssize_t claw_hname_show(struct device *dev, char *buf);
-static ssize_t claw_hname_write(struct device *dev,
+static ssize_t claw_hname_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t claw_hname_write(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count);
-static ssize_t claw_adname_show(struct device *dev, char *buf);
-static ssize_t claw_adname_write(struct device *dev,
+static ssize_t claw_adname_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t claw_adname_write(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count);
-static ssize_t claw_apname_show(struct device *dev, char *buf);
-static ssize_t claw_apname_write(struct device *dev,
+static ssize_t claw_apname_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t claw_apname_write(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count);
-static ssize_t claw_wbuff_show(struct device *dev, char *buf);
-static ssize_t claw_wbuff_write(struct device *dev,
+static ssize_t claw_wbuff_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t claw_wbuff_write(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count);
-static ssize_t claw_rbuff_show(struct device *dev, char *buf);
-static ssize_t claw_rbuff_write(struct device *dev,
+static ssize_t claw_rbuff_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t claw_rbuff_write(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count);
static int claw_add_files(struct device *dev);
static void claw_remove_files(struct device *dev);
@@ -4149,7 +4149,7 @@ claw_remove_device(struct ccwgroup_device *cgdev)
* sysfs attributes
*/
static ssize_t
-claw_hname_show(struct device *dev, char *buf)
+claw_hname_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct claw_privbk *priv;
struct claw_env * p_env;
@@ -4162,7 +4162,7 @@ claw_hname_show(struct device *dev, char *buf)
}
static ssize_t
-claw_hname_write(struct device *dev, const char *buf, size_t count)
+claw_hname_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct claw_privbk *priv;
struct claw_env * p_env;
@@ -4186,7 +4186,7 @@ claw_hname_write(struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(host_name, 0644, claw_hname_show, claw_hname_write);
static ssize_t
-claw_adname_show(struct device *dev, char *buf)
+claw_adname_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct claw_privbk *priv;
struct claw_env * p_env;
@@ -4199,7 +4199,7 @@ claw_adname_show(struct device *dev, char *buf)
}
static ssize_t
-claw_adname_write(struct device *dev, const char *buf, size_t count)
+claw_adname_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct claw_privbk *priv;
struct claw_env * p_env;
@@ -4223,7 +4223,7 @@ claw_adname_write(struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(adapter_name, 0644, claw_adname_show, claw_adname_write);
static ssize_t
-claw_apname_show(struct device *dev, char *buf)
+claw_apname_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct claw_privbk *priv;
struct claw_env * p_env;
@@ -4237,7 +4237,7 @@ claw_apname_show(struct device *dev, char *buf)
}
static ssize_t
-claw_apname_write(struct device *dev, const char *buf, size_t count)
+claw_apname_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct claw_privbk *priv;
struct claw_env * p_env;
@@ -4271,7 +4271,7 @@ claw_apname_write(struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(api_type, 0644, claw_apname_show, claw_apname_write);
static ssize_t
-claw_wbuff_show(struct device *dev, char *buf)
+claw_wbuff_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct claw_privbk *priv;
struct claw_env * p_env;
@@ -4284,7 +4284,7 @@ claw_wbuff_show(struct device *dev, char *buf)
}
static ssize_t
-claw_wbuff_write(struct device *dev, const char *buf, size_t count)
+claw_wbuff_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct claw_privbk *priv;
struct claw_env * p_env;
@@ -4312,7 +4312,7 @@ claw_wbuff_write(struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(write_buffer, 0644, claw_wbuff_show, claw_wbuff_write);
static ssize_t
-claw_rbuff_show(struct device *dev, char *buf)
+claw_rbuff_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct claw_privbk *priv;
struct claw_env * p_env;
@@ -4325,7 +4325,7 @@ claw_rbuff_show(struct device *dev, char *buf)
}
static ssize_t
-claw_rbuff_write(struct device *dev, const char *buf, size_t count)
+claw_rbuff_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct claw_privbk *priv;
struct claw_env *p_env;
diff --git a/drivers/s390/net/ctcdbug.c b/drivers/s390/net/ctcdbug.c
index 2c86bfa11b2..0e2a8bb9303 100644
--- a/drivers/s390/net/ctcdbug.c
+++ b/drivers/s390/net/ctcdbug.c
@@ -1,6 +1,6 @@
/*
*
- * linux/drivers/s390/net/ctcdbug.c ($Revision: 1.4 $)
+ * linux/drivers/s390/net/ctcdbug.c ($Revision: 1.6 $)
*
* CTC / ESCON network driver - s390 dbf exploit.
*
@@ -9,7 +9,7 @@
* Author(s): Original Code written by
* Peter Tiedemann (ptiedem@de.ibm.com)
*
- * $Revision: 1.4 $ $Date: 2004/08/04 10:11:59 $
+ * $Revision: 1.6 $ $Date: 2005/05/11 08:10:17 $
*
* 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
@@ -51,15 +51,15 @@ int
ctc_register_dbf_views(void)
{
ctc_dbf_setup = debug_register(CTC_DBF_SETUP_NAME,
- CTC_DBF_SETUP_INDEX,
+ CTC_DBF_SETUP_PAGES,
CTC_DBF_SETUP_NR_AREAS,
CTC_DBF_SETUP_LEN);
ctc_dbf_data = debug_register(CTC_DBF_DATA_NAME,
- CTC_DBF_DATA_INDEX,
+ CTC_DBF_DATA_PAGES,
CTC_DBF_DATA_NR_AREAS,
CTC_DBF_DATA_LEN);
ctc_dbf_trace = debug_register(CTC_DBF_TRACE_NAME,
- CTC_DBF_TRACE_INDEX,
+ CTC_DBF_TRACE_PAGES,
CTC_DBF_TRACE_NR_AREAS,
CTC_DBF_TRACE_LEN);
diff --git a/drivers/s390/net/ctcdbug.h b/drivers/s390/net/ctcdbug.h
index ef888395172..7d6afa1627c 100644
--- a/drivers/s390/net/ctcdbug.h
+++ b/drivers/s390/net/ctcdbug.h
@@ -1,6 +1,6 @@
/*
*
- * linux/drivers/s390/net/ctcdbug.h ($Revision: 1.4 $)
+ * linux/drivers/s390/net/ctcdbug.h ($Revision: 1.6 $)
*
* CTC / ESCON network driver - s390 dbf exploit.
*
@@ -9,7 +9,7 @@
* Author(s): Original Code written by
* Peter Tiedemann (ptiedem@de.ibm.com)
*
- * $Revision: 1.4 $ $Date: 2004/10/15 09:26:58 $
+ * $Revision: 1.6 $ $Date: 2005/05/11 08:10:17 $
*
* 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
@@ -25,27 +25,29 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
+#ifndef _CTCDBUG_H_
+#define _CTCDBUG_H_
#include <asm/debug.h>
+#include "ctcmain.h"
/**
* Debug Facility stuff
*/
#define CTC_DBF_SETUP_NAME "ctc_setup"
#define CTC_DBF_SETUP_LEN 16
-#define CTC_DBF_SETUP_INDEX 3
+#define CTC_DBF_SETUP_PAGES 8
#define CTC_DBF_SETUP_NR_AREAS 1
#define CTC_DBF_SETUP_LEVEL 3
#define CTC_DBF_DATA_NAME "ctc_data"
#define CTC_DBF_DATA_LEN 128
-#define CTC_DBF_DATA_INDEX 3
+#define CTC_DBF_DATA_PAGES 8
#define CTC_DBF_DATA_NR_AREAS 1
-#define CTC_DBF_DATA_LEVEL 2
+#define CTC_DBF_DATA_LEVEL 3
#define CTC_DBF_TRACE_NAME "ctc_trace"
#define CTC_DBF_TRACE_LEN 16
-#define CTC_DBF_TRACE_INDEX 2
+#define CTC_DBF_TRACE_PAGES 4
#define CTC_DBF_TRACE_NR_AREAS 2
#define CTC_DBF_TRACE_LEVEL 3
@@ -121,3 +123,5 @@ hex_dump(unsigned char *buf, size_t len)
printk("\n");
}
+
+#endif
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
index 7266bf5ea65..96ca863eaff 100644
--- a/drivers/s390/net/ctcmain.c
+++ b/drivers/s390/net/ctcmain.c
@@ -1,5 +1,5 @@
/*
- * $Id: ctcmain.c,v 1.72 2005/03/17 10:51:52 ptiedem Exp $
+ * $Id: ctcmain.c,v 1.74 2005/03/24 09:04:17 mschwide Exp $
*
* CTC / ESCON network driver
*
@@ -37,12 +37,11 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.72 $
+ * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.74 $
*
*/
#undef DEBUG
-
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -74,288 +73,13 @@
#include "ctctty.h"
#include "fsm.h"
#include "cu3088.h"
+
#include "ctcdbug.h"
+#include "ctcmain.h"
MODULE_AUTHOR("(C) 2000 IBM Corp. by Fritz Elfert (felfert@millenux.com)");
MODULE_DESCRIPTION("Linux for S/390 CTC/Escon Driver");
MODULE_LICENSE("GPL");
-
-/**
- * CCW commands, used in this driver.
- */
-#define CCW_CMD_WRITE 0x01
-#define CCW_CMD_READ 0x02
-#define CCW_CMD_SET_EXTENDED 0xc3
-#define CCW_CMD_PREPARE 0xe3
-
-#define CTC_PROTO_S390 0
-#define CTC_PROTO_LINUX 1
-#define CTC_PROTO_LINUX_TTY 2
-#define CTC_PROTO_OS390 3
-#define CTC_PROTO_MAX 3
-
-#define CTC_BUFSIZE_LIMIT 65535
-#define CTC_BUFSIZE_DEFAULT 32768
-
-#define CTC_TIMEOUT_5SEC 5000
-
-#define CTC_INITIAL_BLOCKLEN 2
-
-#define READ 0
-#define WRITE 1
-
-#define CTC_ID_SIZE BUS_ID_SIZE+3
-
-
-struct ctc_profile {
- unsigned long maxmulti;
- unsigned long maxcqueue;
- unsigned long doios_single;
- unsigned long doios_multi;
- unsigned long txlen;
- unsigned long tx_time;
- struct timespec send_stamp;
-};
-
-/**
- * Definition of one channel
- */
-struct channel {
-
- /**
- * Pointer to next channel in list.
- */
- struct channel *next;
- char id[CTC_ID_SIZE];
- struct ccw_device *cdev;
-
- /**
- * Type of this channel.
- * CTC/A or Escon for valid channels.
- */
- enum channel_types type;
-
- /**
- * Misc. flags. See CHANNEL_FLAGS_... below
- */
- __u32 flags;
-
- /**
- * The protocol of this channel
- */
- __u16 protocol;
-
- /**
- * I/O and irq related stuff
- */
- struct ccw1 *ccw;
- struct irb *irb;
-
- /**
- * RX/TX buffer size
- */
- int max_bufsize;
-
- /**
- * Transmit/Receive buffer.
- */
- struct sk_buff *trans_skb;
-
- /**
- * Universal I/O queue.
- */
- struct sk_buff_head io_queue;
-
- /**
- * TX queue for collecting skb's during busy.
- */
- struct sk_buff_head collect_queue;
-
- /**
- * Amount of data in collect_queue.
- */
- int collect_len;
-
- /**
- * spinlock for collect_queue and collect_len
- */
- spinlock_t collect_lock;
-
- /**
- * Timer for detecting unresposive
- * I/O operations.
- */
- fsm_timer timer;
-
- /**
- * Retry counter for misc. operations.
- */
- int retry;
-
- /**
- * The finite state machine of this channel
- */
- fsm_instance *fsm;
-
- /**
- * The corresponding net_device this channel
- * belongs to.
- */
- struct net_device *netdev;
-
- struct ctc_profile prof;
-
- unsigned char *trans_skb_data;
-
- __u16 logflags;
-};
-
-#define CHANNEL_FLAGS_READ 0
-#define CHANNEL_FLAGS_WRITE 1
-#define CHANNEL_FLAGS_INUSE 2
-#define CHANNEL_FLAGS_BUFSIZE_CHANGED 4
-#define CHANNEL_FLAGS_FAILED 8
-#define CHANNEL_FLAGS_WAITIRQ 16
-#define CHANNEL_FLAGS_RWMASK 1
-#define CHANNEL_DIRECTION(f) (f & CHANNEL_FLAGS_RWMASK)
-
-#define LOG_FLAG_ILLEGALPKT 1
-#define LOG_FLAG_ILLEGALSIZE 2
-#define LOG_FLAG_OVERRUN 4
-#define LOG_FLAG_NOMEM 8
-
-#define CTC_LOGLEVEL_INFO 1
-#define CTC_LOGLEVEL_NOTICE 2
-#define CTC_LOGLEVEL_WARN 4
-#define CTC_LOGLEVEL_EMERG 8
-#define CTC_LOGLEVEL_ERR 16
-#define CTC_LOGLEVEL_DEBUG 32
-#define CTC_LOGLEVEL_CRIT 64
-
-#define CTC_LOGLEVEL_DEFAULT \
-(CTC_LOGLEVEL_INFO | CTC_LOGLEVEL_NOTICE | CTC_LOGLEVEL_WARN | CTC_LOGLEVEL_CRIT)
-
-#define CTC_LOGLEVEL_MAX ((CTC_LOGLEVEL_CRIT<<1)-1)
-
-static int loglevel = CTC_LOGLEVEL_DEFAULT;
-
-#define ctc_pr_debug(fmt, arg...) \
-do { if (loglevel & CTC_LOGLEVEL_DEBUG) printk(KERN_DEBUG fmt,##arg); } while (0)
-
-#define ctc_pr_info(fmt, arg...) \
-do { if (loglevel & CTC_LOGLEVEL_INFO) printk(KERN_INFO fmt,##arg); } while (0)
-
-#define ctc_pr_notice(fmt, arg...) \
-do { if (loglevel & CTC_LOGLEVEL_NOTICE) printk(KERN_NOTICE fmt,##arg); } while (0)
-
-#define ctc_pr_warn(fmt, arg...) \
-do { if (loglevel & CTC_LOGLEVEL_WARN) printk(KERN_WARNING fmt,##arg); } while (0)
-
-#define ctc_pr_emerg(fmt, arg...) \
-do { if (loglevel & CTC_LOGLEVEL_EMERG) printk(KERN_EMERG fmt,##arg); } while (0)
-
-#define ctc_pr_err(fmt, arg...) \
-do { if (loglevel & CTC_LOGLEVEL_ERR) printk(KERN_ERR fmt,##arg); } while (0)
-
-#define ctc_pr_crit(fmt, arg...) \
-do { if (loglevel & CTC_LOGLEVEL_CRIT) printk(KERN_CRIT fmt,##arg); } while (0)
-
-/**
- * Linked list of all detected channels.
- */
-static struct channel *channels = NULL;
-
-struct ctc_priv {
- struct net_device_stats stats;
- unsigned long tbusy;
- /**
- * The finite state machine of this interface.
- */
- fsm_instance *fsm;
- /**
- * The protocol of this device
- */
- __u16 protocol;
- /**
- * Timer for restarting after I/O Errors
- */
- fsm_timer restart_timer;
-
- int buffer_size;
-
- struct channel *channel[2];
-};
-
-/**
- * Definition of our link level header.
- */
-struct ll_header {
- __u16 length;
- __u16 type;
- __u16 unused;
-};
-#define LL_HEADER_LENGTH (sizeof(struct ll_header))
-
-/**
- * Compatibility macros for busy handling
- * of network devices.
- */
-static __inline__ void
-ctc_clear_busy(struct net_device * dev)
-{
- clear_bit(0, &(((struct ctc_priv *) dev->priv)->tbusy));
- if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY)
- netif_wake_queue(dev);
-}
-
-static __inline__ int
-ctc_test_and_set_busy(struct net_device * dev)
-{
- if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY)
- netif_stop_queue(dev);
- return test_and_set_bit(0, &((struct ctc_priv *) dev->priv)->tbusy);
-}
-
-/**
- * Print Banner.
- */
-static void
-print_banner(void)
-{
- static int printed = 0;
- char vbuf[] = "$Revision: 1.72 $";
- char *version = vbuf;
-
- if (printed)
- return;
- if ((version = strchr(version, ':'))) {
- char *p = strchr(version + 1, '$');
- if (p)
- *p = '\0';
- } else
- version = " ??? ";
- printk(KERN_INFO "CTC driver Version%s"
-#ifdef DEBUG
- " (DEBUG-VERSION, " __DATE__ __TIME__ ")"
-#endif
- " initialized\n", version);
- printed = 1;
-}
-
-/**
- * Return type of a detected device.
- */
-static enum channel_types
-get_channel_type(struct ccw_device_id *id)
-{
- enum channel_types type = (enum channel_types) id->driver_info;
-
- if (type == channel_type_ficon)
- type = channel_type_escon;
-
- return type;
-}
-
/**
* States of the interface statemachine.
*/
@@ -371,7 +95,7 @@ enum dev_states {
/**
* MUST be always the last element!!
*/
- NR_DEV_STATES
+ CTC_NR_DEV_STATES
};
static const char *dev_state_names[] = {
@@ -399,7 +123,7 @@ enum dev_events {
/**
* MUST be always the last element!!
*/
- NR_DEV_EVENTS
+ CTC_NR_DEV_EVENTS
};
static const char *dev_event_names[] = {
@@ -476,40 +200,6 @@ enum ch_events {
NR_CH_EVENTS,
};
-static const char *ch_event_names[] = {
- "ccw_device success",
- "ccw_device busy",
- "ccw_device enodev",
- "ccw_device ioerr",
- "ccw_device unknown",
-
- "Status ATTN & BUSY",
- "Status ATTN",
- "Status BUSY",
-
- "Unit check remote reset",
- "Unit check remote system reset",
- "Unit check TX timeout",
- "Unit check TX parity",
- "Unit check Hardware failure",
- "Unit check RX parity",
- "Unit check ZERO",
- "Unit check Unknown",
-
- "SubChannel check Unknown",
-
- "Machine check failure",
- "Machine check operational",
-
- "IRQ normal",
- "IRQ final",
-
- "Timer",
-
- "Start",
- "Stop",
-};
-
/**
* States of the channel statemachine.
*/
@@ -545,6 +235,87 @@ enum ch_states {
NR_CH_STATES,
};
+static int loglevel = CTC_LOGLEVEL_DEFAULT;
+
+/**
+ * Linked list of all detected channels.
+ */
+static struct channel *channels = NULL;
+
+/**
+ * Print Banner.
+ */
+static void
+print_banner(void)
+{
+ static int printed = 0;
+ char vbuf[] = "$Revision: 1.74 $";
+ char *version = vbuf;
+
+ if (printed)
+ return;
+ if ((version = strchr(version, ':'))) {
+ char *p = strchr(version + 1, '$');
+ if (p)
+ *p = '\0';
+ } else
+ version = " ??? ";
+ printk(KERN_INFO "CTC driver Version%s"
+#ifdef DEBUG
+ " (DEBUG-VERSION, " __DATE__ __TIME__ ")"
+#endif
+ " initialized\n", version);
+ printed = 1;
+}
+
+/**
+ * Return type of a detected device.
+ */
+static enum channel_types
+get_channel_type(struct ccw_device_id *id)
+{
+ enum channel_types type = (enum channel_types) id->driver_info;
+
+ if (type == channel_type_ficon)
+ type = channel_type_escon;
+
+ return type;
+}
+
+static const char *ch_event_names[] = {
+ "ccw_device success",
+ "ccw_device busy",
+ "ccw_device enodev",
+ "ccw_device ioerr",
+ "ccw_device unknown",
+
+ "Status ATTN & BUSY",
+ "Status ATTN",
+ "Status BUSY",
+
+ "Unit check remote reset",
+ "Unit check remote system reset",
+ "Unit check TX timeout",
+ "Unit check TX parity",
+ "Unit check Hardware failure",
+ "Unit check RX parity",
+ "Unit check ZERO",
+ "Unit check Unknown",
+
+ "SubChannel check Unknown",
+
+ "Machine check failure",
+ "Machine check operational",
+
+ "IRQ normal",
+ "IRQ final",
+
+ "Timer",
+
+ "Start",
+ "Stop",
+};
+
static const char *ch_state_names[] = {
"Idle",
"Stopped",
@@ -1934,7 +1705,6 @@ add_channel(struct ccw_device *cdev, enum channel_types type)
ch->cdev = cdev;
snprintf(ch->id, CTC_ID_SIZE, "ch-%s", cdev->dev.bus_id);
ch->type = type;
- loglevel = CTC_LOGLEVEL_DEFAULT;
ch->fsm = init_fsm(ch->id, ch_state_names,
ch_event_names, NR_CH_STATES, NR_CH_EVENTS,
ch_fsm, CH_FSM_LEN, GFP_KERNEL);
@@ -2697,8 +2467,9 @@ ctc_stats(struct net_device * dev)
/*
* sysfs attributes
*/
+
static ssize_t
-buffer_show(struct device *dev, char *buf)
+buffer_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct ctc_priv *priv;
@@ -2710,62 +2481,66 @@ buffer_show(struct device *dev, char *buf)
}
static ssize_t
-buffer_write(struct device *dev, const char *buf, size_t count)
+buffer_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct ctc_priv *priv;
struct net_device *ndev;
int bs1;
+ char buffer[16];
DBF_TEXT(trace, 3, __FUNCTION__);
+ DBF_TEXT(trace, 3, buf);
priv = dev->driver_data;
- if (!priv)
+ if (!priv) {
+ DBF_TEXT(trace, 3, "bfnopriv");
return -ENODEV;
+ }
+
+ sscanf(buf, "%u", &bs1);
+ if (bs1 > CTC_BUFSIZE_LIMIT)
+ goto einval;
+ if (bs1 < (576 + LL_HEADER_LENGTH + 2))
+ goto einval;
+ priv->buffer_size = bs1; // just to overwrite the default
+
ndev = priv->channel[READ]->netdev;
- if (!ndev)
+ if (!ndev) {
+ DBF_TEXT(trace, 3, "bfnondev");
return -ENODEV;
- sscanf(buf, "%u", &bs1);
+ }
- if (bs1 > CTC_BUFSIZE_LIMIT)
- return -EINVAL;
if ((ndev->flags & IFF_RUNNING) &&
(bs1 < (ndev->mtu + LL_HEADER_LENGTH + 2)))
- return -EINVAL;
- if (bs1 < (576 + LL_HEADER_LENGTH + 2))
- return -EINVAL;
+ goto einval;
- priv->buffer_size = bs1;
- priv->channel[READ]->max_bufsize =
- priv->channel[WRITE]->max_bufsize = bs1;
+ priv->channel[READ]->max_bufsize = bs1;
+ priv->channel[WRITE]->max_bufsize = bs1;
if (!(ndev->flags & IFF_RUNNING))
ndev->mtu = bs1 - LL_HEADER_LENGTH - 2;
priv->channel[READ]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
priv->channel[WRITE]->flags |= CHANNEL_FLAGS_BUFSIZE_CHANGED;
+ sprintf(buffer, "%d",priv->buffer_size);
+ DBF_TEXT(trace, 3, buffer);
return count;
+einval:
+ DBF_TEXT(trace, 3, "buff_err");
+ return -EINVAL;
}
static ssize_t
-loglevel_show(struct device *dev, char *buf)
+loglevel_show(struct device *dev, struct device_attribute *attr, char *buf)
{
- struct ctc_priv *priv;
-
- priv = dev->driver_data;
- if (!priv)
- return -ENODEV;
return sprintf(buf, "%d\n", loglevel);
}
static ssize_t
-loglevel_write(struct device *dev, const char *buf, size_t count)
+loglevel_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
- struct ctc_priv *priv;
int ll1;
DBF_TEXT(trace, 5, __FUNCTION__);
- priv = dev->driver_data;
- if (!priv)
- return -ENODEV;
sscanf(buf, "%i", &ll1);
if ((ll1 > CTC_LOGLEVEL_MAX) || (ll1 < 0))
@@ -2814,7 +2589,7 @@ ctc_print_statistics(struct ctc_priv *priv)
}
static ssize_t
-stats_show(struct device *dev, char *buf)
+stats_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct ctc_priv *priv = dev->driver_data;
if (!priv)
@@ -2824,7 +2599,7 @@ stats_show(struct device *dev, char *buf)
}
static ssize_t
-stats_write(struct device *dev, const char *buf, size_t count)
+stats_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct ctc_priv *priv = dev->driver_data;
if (!priv)
@@ -2835,27 +2610,6 @@ stats_write(struct device *dev, const char *buf, size_t count)
return count;
}
-static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write);
-static DEVICE_ATTR(loglevel, 0644, loglevel_show, loglevel_write);
-static DEVICE_ATTR(stats, 0644, stats_show, stats_write);
-
-static int
-ctc_add_attributes(struct device *dev)
-{
-// device_create_file(dev, &dev_attr_buffer);
- device_create_file(dev, &dev_attr_loglevel);
- device_create_file(dev, &dev_attr_stats);
- return 0;
-}
-
-static void
-ctc_remove_attributes(struct device *dev)
-{
- device_remove_file(dev, &dev_attr_stats);
- device_remove_file(dev, &dev_attr_loglevel);
-// device_remove_file(dev, &dev_attr_buffer);
-}
-
static void
ctc_netdev_unregister(struct net_device * dev)
@@ -2899,54 +2653,8 @@ ctc_free_netdevice(struct net_device * dev, int free_dev)
#endif
}
-/**
- * Initialize everything of the net device except the name and the
- * channel structs.
- */
-static struct net_device *
-ctc_init_netdevice(struct net_device * dev, int alloc_device,
- struct ctc_priv *privptr)
-{
- if (!privptr)
- return NULL;
-
- DBF_TEXT(setup, 3, __FUNCTION__);
- if (alloc_device) {
- dev = kmalloc(sizeof (struct net_device), GFP_KERNEL);
- if (!dev)
- return NULL;
- memset(dev, 0, sizeof (struct net_device));
- }
-
- dev->priv = privptr;
- privptr->fsm = init_fsm("ctcdev", dev_state_names,
- dev_event_names, NR_DEV_STATES, NR_DEV_EVENTS,
- dev_fsm, DEV_FSM_LEN, GFP_KERNEL);
- if (privptr->fsm == NULL) {
- if (alloc_device)
- kfree(dev);
- return NULL;
- }
- fsm_newstate(privptr->fsm, DEV_STATE_STOPPED);
- fsm_settimer(privptr->fsm, &privptr->restart_timer);
- if (dev->mtu == 0)
- dev->mtu = CTC_BUFSIZE_DEFAULT - LL_HEADER_LENGTH - 2;
- dev->hard_start_xmit = ctc_tx;
- dev->open = ctc_open;
- dev->stop = ctc_close;
- dev->get_stats = ctc_stats;
- dev->change_mtu = ctc_change_mtu;
- dev->hard_header_len = LL_HEADER_LENGTH + 2;
- dev->addr_len = 0;
- dev->type = ARPHRD_SLIP;
- dev->tx_queue_len = 100;
- dev->flags = IFF_POINTOPOINT | IFF_NOARP;
- SET_MODULE_OWNER(dev);
- return dev;
-}
-
static ssize_t
-ctc_proto_show(struct device *dev, char *buf)
+ctc_proto_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct ctc_priv *priv;
@@ -2958,7 +2666,7 @@ ctc_proto_show(struct device *dev, char *buf)
}
static ssize_t
-ctc_proto_store(struct device *dev, const char *buf, size_t count)
+ctc_proto_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct ctc_priv *priv;
int value;
@@ -2977,10 +2685,9 @@ ctc_proto_store(struct device *dev, const char *buf, size_t count)
return count;
}
-static DEVICE_ATTR(protocol, 0644, ctc_proto_show, ctc_proto_store);
static ssize_t
-ctc_type_show(struct device *dev, char *buf)
+ctc_type_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct ccwgroup_device *cgdev;
@@ -2991,8 +2698,13 @@ ctc_type_show(struct device *dev, char *buf)
return sprintf(buf, "%s\n", cu3088_type[cgdev->cdev[0]->id.driver_info]);
}
+static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write);
+static DEVICE_ATTR(protocol, 0644, ctc_proto_show, ctc_proto_store);
static DEVICE_ATTR(type, 0444, ctc_type_show, NULL);
+static DEVICE_ATTR(loglevel, 0644, loglevel_show, loglevel_write);
+static DEVICE_ATTR(stats, 0644, stats_show, stats_write);
+
static struct attribute *ctc_attr[] = {
&dev_attr_protocol.attr,
&dev_attr_type.attr,
@@ -3005,6 +2717,21 @@ static struct attribute_group ctc_attr_group = {
};
static int
+ctc_add_attributes(struct device *dev)
+{
+ device_create_file(dev, &dev_attr_loglevel);
+ device_create_file(dev, &dev_attr_stats);
+ return 0;
+}
+
+static void
+ctc_remove_attributes(struct device *dev)
+{
+ device_remove_file(dev, &dev_attr_stats);
+ device_remove_file(dev, &dev_attr_loglevel);
+}
+
+static int
ctc_add_files(struct device *dev)
{
pr_debug("%s() called\n", __FUNCTION__);
@@ -3028,15 +2755,15 @@ ctc_remove_files(struct device *dev)
*
* @returns 0 on success, !0 on failure.
*/
-
static int
ctc_probe_device(struct ccwgroup_device *cgdev)
{
struct ctc_priv *priv;
int rc;
+ char buffer[16];
pr_debug("%s() called\n", __FUNCTION__);
- DBF_TEXT(trace, 3, __FUNCTION__);
+ DBF_TEXT(setup, 3, __FUNCTION__);
if (!get_device(&cgdev->dev))
return -ENODEV;
@@ -3060,10 +2787,70 @@ ctc_probe_device(struct ccwgroup_device *cgdev)
cgdev->cdev[1]->handler = ctc_irq_handler;
cgdev->dev.driver_data = priv;
+ sprintf(buffer, "%p", priv);
+ DBF_TEXT(data, 3, buffer);
+
+ sprintf(buffer, "%u", (unsigned int)sizeof(struct ctc_priv));
+ DBF_TEXT(data, 3, buffer);
+
+ sprintf(buffer, "%p", &channels);
+ DBF_TEXT(data, 3, buffer);
+
+ sprintf(buffer, "%u", (unsigned int)sizeof(struct channel));
+ DBF_TEXT(data, 3, buffer);
+
return 0;
}
/**
+ * Initialize everything of the net device except the name and the
+ * channel structs.
+ */
+static struct net_device *
+ctc_init_netdevice(struct net_device * dev, int alloc_device,
+ struct ctc_priv *privptr)
+{
+ if (!privptr)
+ return NULL;
+
+ DBF_TEXT(setup, 3, __FUNCTION__);
+
+ if (alloc_device) {
+ dev = kmalloc(sizeof (struct net_device), GFP_KERNEL);
+ if (!dev)
+ return NULL;
+ memset(dev, 0, sizeof (struct net_device));
+ }
+
+ dev->priv = privptr;
+ privptr->fsm = init_fsm("ctcdev", dev_state_names,
+ dev_event_names, CTC_NR_DEV_STATES, CTC_NR_DEV_EVENTS,
+ dev_fsm, DEV_FSM_LEN, GFP_KERNEL);
+ if (privptr->fsm == NULL) {
+ if (alloc_device)
+ kfree(dev);
+ return NULL;
+ }
+ fsm_newstate(privptr->fsm, DEV_STATE_STOPPED);
+ fsm_settimer(privptr->fsm, &privptr->restart_timer);
+ if (dev->mtu == 0)
+ dev->mtu = CTC_BUFSIZE_DEFAULT - LL_HEADER_LENGTH - 2;
+ dev->hard_start_xmit = ctc_tx;
+ dev->open = ctc_open;
+ dev->stop = ctc_close;
+ dev->get_stats = ctc_stats;
+ dev->change_mtu = ctc_change_mtu;
+ dev->hard_header_len = LL_HEADER_LENGTH + 2;
+ dev->addr_len = 0;
+ dev->type = ARPHRD_SLIP;
+ dev->tx_queue_len = 100;
+ dev->flags = IFF_POINTOPOINT | IFF_NOARP;
+ SET_MODULE_OWNER(dev);
+ return dev;
+}
+
+
+/**
*
* Setup an interface.
*
@@ -3081,6 +2868,7 @@ ctc_new_device(struct ccwgroup_device *cgdev)
struct ctc_priv *privptr;
struct net_device *dev;
int ret;
+ char buffer[16];
pr_debug("%s() called\n", __FUNCTION__);
DBF_TEXT(setup, 3, __FUNCTION__);
@@ -3089,6 +2877,9 @@ ctc_new_device(struct ccwgroup_device *cgdev)
if (!privptr)
return -ENODEV;
+ sprintf(buffer, "%d", privptr->buffer_size);
+ DBF_TEXT(setup, 3, buffer);
+
type = get_channel_type(&cgdev->cdev[0]->id);
snprintf(read_id, CTC_ID_SIZE, "ch-%s", cgdev->cdev[0]->dev.bus_id);
@@ -3177,9 +2968,10 @@ ctc_shutdown_device(struct ccwgroup_device *cgdev)
struct ctc_priv *priv;
struct net_device *ndev;
- DBF_TEXT(trace, 3, __FUNCTION__);
+ DBF_TEXT(setup, 3, __FUNCTION__);
pr_debug("%s() called\n", __FUNCTION__);
+
priv = cgdev->dev.driver_data;
ndev = NULL;
if (!priv)
@@ -3215,7 +3007,6 @@ ctc_shutdown_device(struct ccwgroup_device *cgdev)
channel_remove(priv->channel[READ]);
if (priv->channel[WRITE])
channel_remove(priv->channel[WRITE]);
-
priv->channel[READ] = priv->channel[WRITE] = NULL;
return 0;
@@ -3228,7 +3019,7 @@ ctc_remove_device(struct ccwgroup_device *cgdev)
struct ctc_priv *priv;
pr_debug("%s() called\n", __FUNCTION__);
- DBF_TEXT(trace, 3, __FUNCTION__);
+ DBF_TEXT(setup, 3, __FUNCTION__);
priv = cgdev->dev.driver_data;
if (!priv)
@@ -3265,6 +3056,7 @@ static struct ccwgroup_driver ctc_group_driver = {
static void __exit
ctc_exit(void)
{
+ DBF_TEXT(setup, 3, __FUNCTION__);
unregister_cu3088_discipline(&ctc_group_driver);
ctc_tty_cleanup();
ctc_unregister_dbf_views();
@@ -3282,6 +3074,10 @@ ctc_init(void)
{
int ret = 0;
+ loglevel = CTC_LOGLEVEL_DEFAULT;
+
+ DBF_TEXT(setup, 3, __FUNCTION__);
+
print_banner();
ret = ctc_register_dbf_views();
diff --git a/drivers/s390/net/ctcmain.h b/drivers/s390/net/ctcmain.h
new file mode 100644
index 00000000000..ba3605f1633
--- /dev/null
+++ b/drivers/s390/net/ctcmain.h
@@ -0,0 +1,276 @@
+/*
+ * $Id: ctcmain.h,v 1.4 2005/03/24 09:04:17 mschwide Exp $
+ *
+ * CTC / ESCON network driver
+ *
+ * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
+ Peter Tiedemann (ptiedem@de.ibm.com)
+ *
+ *
+ * Documentation used:
+ * - Principles of Operation (IBM doc#: SA22-7201-06)
+ * - Common IO/-Device Commands and Self Description (IBM doc#: SA22-7204-02)
+ * - Common IO/-Device Commands and Self Description (IBM doc#: SN22-5535)
+ * - ESCON Channel-to-Channel Adapter (IBM doc#: SA22-7203-00)
+ * - ESCON I/O Interface (IBM doc#: SA22-7202-029
+ *
+ * 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; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.4 $
+ *
+ */
+
+#ifndef _CTCMAIN_H_
+#define _CTCMAIN_H_
+
+#include <asm/ccwdev.h>
+#include <asm/ccwgroup.h>
+
+#include "ctctty.h"
+#include "fsm.h"
+#include "cu3088.h"
+
+
+/**
+ * CCW commands, used in this driver.
+ */
+#define CCW_CMD_WRITE 0x01
+#define CCW_CMD_READ 0x02
+#define CCW_CMD_SET_EXTENDED 0xc3
+#define CCW_CMD_PREPARE 0xe3
+
+#define CTC_PROTO_S390 0
+#define CTC_PROTO_LINUX 1
+#define CTC_PROTO_LINUX_TTY 2
+#define CTC_PROTO_OS390 3
+#define CTC_PROTO_MAX 3
+
+#define CTC_BUFSIZE_LIMIT 65535
+#define CTC_BUFSIZE_DEFAULT 32768
+
+#define CTC_TIMEOUT_5SEC 5000
+
+#define CTC_INITIAL_BLOCKLEN 2
+
+#define READ 0
+#define WRITE 1
+
+#define CTC_ID_SIZE BUS_ID_SIZE+3
+
+
+struct ctc_profile {
+ unsigned long maxmulti;
+ unsigned long maxcqueue;
+ unsigned long doios_single;
+ unsigned long doios_multi;
+ unsigned long txlen;
+ unsigned long tx_time;
+ struct timespec send_stamp;
+};
+
+/**
+ * Definition of one channel
+ */
+struct channel {
+
+ /**
+ * Pointer to next channel in list.
+ */
+ struct channel *next;
+ char id[CTC_ID_SIZE];
+ struct ccw_device *cdev;
+
+ /**
+ * Type of this channel.
+ * CTC/A or Escon for valid channels.
+ */
+ enum channel_types type;
+
+ /**
+ * Misc. flags. See CHANNEL_FLAGS_... below
+ */
+ __u32 flags;
+
+ /**
+ * The protocol of this channel
+ */
+ __u16 protocol;
+
+ /**
+ * I/O and irq related stuff
+ */
+ struct ccw1 *ccw;
+ struct irb *irb;
+
+ /**
+ * RX/TX buffer size
+ */
+ int max_bufsize;
+
+ /**
+ * Transmit/Receive buffer.
+ */
+ struct sk_buff *trans_skb;
+
+ /**
+ * Universal I/O queue.
+ */
+ struct sk_buff_head io_queue;
+
+ /**
+ * TX queue for collecting skb's during busy.
+ */
+ struct sk_buff_head collect_queue;
+
+ /**
+ * Amount of data in collect_queue.
+ */
+ int collect_len;
+
+ /**
+ * spinlock for collect_queue and collect_len
+ */
+ spinlock_t collect_lock;
+
+ /**
+ * Timer for detecting unresposive
+ * I/O operations.
+ */
+ fsm_timer timer;
+
+ /**
+ * Retry counter for misc. operations.
+ */
+ int retry;
+
+ /**
+ * The finite state machine of this channel
+ */
+ fsm_instance *fsm;
+
+ /**
+ * The corresponding net_device this channel
+ * belongs to.
+ */
+ struct net_device *netdev;
+
+ struct ctc_profile prof;
+
+ unsigned char *trans_skb_data;
+
+ __u16 logflags;
+};
+
+#define CHANNEL_FLAGS_READ 0
+#define CHANNEL_FLAGS_WRITE 1
+#define CHANNEL_FLAGS_INUSE 2
+#define CHANNEL_FLAGS_BUFSIZE_CHANGED 4
+#define CHANNEL_FLAGS_FAILED 8
+#define CHANNEL_FLAGS_WAITIRQ 16
+#define CHANNEL_FLAGS_RWMASK 1
+#define CHANNEL_DIRECTION(f) (f & CHANNEL_FLAGS_RWMASK)
+
+#define LOG_FLAG_ILLEGALPKT 1
+#define LOG_FLAG_ILLEGALSIZE 2
+#define LOG_FLAG_OVERRUN 4
+#define LOG_FLAG_NOMEM 8
+
+#define CTC_LOGLEVEL_INFO 1
+#define CTC_LOGLEVEL_NOTICE 2
+#define CTC_LOGLEVEL_WARN 4
+#define CTC_LOGLEVEL_EMERG 8
+#define CTC_LOGLEVEL_ERR 16
+#define CTC_LOGLEVEL_DEBUG 32
+#define CTC_LOGLEVEL_CRIT 64
+
+#define CTC_LOGLEVEL_DEFAULT \
+(CTC_LOGLEVEL_INFO | CTC_LOGLEVEL_NOTICE | CTC_LOGLEVEL_WARN | CTC_LOGLEVEL_CRIT)
+
+#define CTC_LOGLEVEL_MAX ((CTC_LOGLEVEL_CRIT<<1)-1)
+
+#define ctc_pr_debug(fmt, arg...) \
+do { if (loglevel & CTC_LOGLEVEL_DEBUG) printk(KERN_DEBUG fmt,##arg); } while (0)
+
+#define ctc_pr_info(fmt, arg...) \
+do { if (loglevel & CTC_LOGLEVEL_INFO) printk(KERN_INFO fmt,##arg); } while (0)
+
+#define ctc_pr_notice(fmt, arg...) \
+do { if (loglevel & CTC_LOGLEVEL_NOTICE) printk(KERN_NOTICE fmt,##arg); } while (0)
+
+#define ctc_pr_warn(fmt, arg...) \
+do { if (loglevel & CTC_LOGLEVEL_WARN) printk(KERN_WARNING fmt,##arg); } while (0)
+
+#define ctc_pr_emerg(fmt, arg...) \
+do { if (loglevel & CTC_LOGLEVEL_EMERG) printk(KERN_EMERG fmt,##arg); } while (0)
+
+#define ctc_pr_err(fmt, arg...) \
+do { if (loglevel & CTC_LOGLEVEL_ERR) printk(KERN_ERR fmt,##arg); } while (0)
+
+#define ctc_pr_crit(fmt, arg...) \
+do { if (loglevel & CTC_LOGLEVEL_CRIT) printk(KERN_CRIT fmt,##arg); } while (0)
+
+struct ctc_priv {
+ struct net_device_stats stats;
+ unsigned long tbusy;
+ /**
+ * The finite state machine of this interface.
+ */
+ fsm_instance *fsm;
+ /**
+ * The protocol of this device
+ */
+ __u16 protocol;
+ /**
+ * Timer for restarting after I/O Errors
+ */
+ fsm_timer restart_timer;
+
+ int buffer_size;
+
+ struct channel *channel[2];
+};
+
+/**
+ * Definition of our link level header.
+ */
+struct ll_header {
+ __u16 length;
+ __u16 type;
+ __u16 unused;
+};
+#define LL_HEADER_LENGTH (sizeof(struct ll_header))
+
+/**
+ * Compatibility macros for busy handling
+ * of network devices.
+ */
+static __inline__ void
+ctc_clear_busy(struct net_device * dev)
+{
+ clear_bit(0, &(((struct ctc_priv *) dev->priv)->tbusy));
+ if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY)
+ netif_wake_queue(dev);
+}
+
+static __inline__ int
+ctc_test_and_set_busy(struct net_device * dev)
+{
+ if (((struct ctc_priv *)dev->priv)->protocol != CTC_PROTO_LINUX_TTY)
+ netif_stop_queue(dev);
+ return test_and_set_bit(0, &((struct ctc_priv *) dev->priv)->tbusy);
+}
+
+#endif
diff --git a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c
index 9257d60c783..3080393e823 100644
--- a/drivers/s390/net/ctctty.c
+++ b/drivers/s390/net/ctctty.c
@@ -1,5 +1,5 @@
/*
- * $Id: ctctty.c,v 1.26 2004/08/04 11:06:55 mschwide Exp $
+ * $Id: ctctty.c,v 1.29 2005/04/05 08:50:44 mschwide Exp $
*
* CTC / ESCON network driver, tty interface.
*
@@ -1056,8 +1056,7 @@ ctc_tty_close(struct tty_struct *tty, struct file *filp)
info->tty = 0;
tty->closing = 0;
if (info->blocked_open) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(HZ/2);
+ msleep_interruptible(500);
wake_up_interruptible(&info->open_wait);
}
info->flags &= ~(CTC_ASYNC_NORMAL_ACTIVE | CTC_ASYNC_CLOSING);
diff --git a/drivers/s390/net/cu3088.c b/drivers/s390/net/cu3088.c
index 1b0a9f16024..0075894c71d 100644
--- a/drivers/s390/net/cu3088.c
+++ b/drivers/s390/net/cu3088.c
@@ -1,5 +1,5 @@
/*
- * $Id: cu3088.c,v 1.34 2004/06/15 13:16:27 pavlic Exp $
+ * $Id: cu3088.c,v 1.35 2005/03/30 19:28:52 richtera Exp $
*
* CTC / LCS ccw_device driver
*
@@ -39,6 +39,7 @@ const char *cu3088_type[] = {
"FICON channel",
"P390 LCS card",
"OSA LCS card",
+ "CLAW channel device",
"unknown channel type",
"unsupported channel type",
};
@@ -51,6 +52,7 @@ static struct ccw_device_id cu3088_ids[] = {
{ CCW_DEVICE(0x3088, 0x1e), .driver_info = channel_type_ficon },
{ CCW_DEVICE(0x3088, 0x01), .driver_info = channel_type_p390 },
{ CCW_DEVICE(0x3088, 0x60), .driver_info = channel_type_osa2 },
+ { CCW_DEVICE(0x3088, 0x61), .driver_info = channel_type_claw },
{ /* end of list */ }
};
diff --git a/drivers/s390/net/cu3088.h b/drivers/s390/net/cu3088.h
index 0ec49a8b3ad..1753661f702 100644
--- a/drivers/s390/net/cu3088.h
+++ b/drivers/s390/net/cu3088.h
@@ -23,6 +23,9 @@ enum channel_types {
/* Device is a OSA2 card */
channel_type_osa2,
+ /* Device is a CLAW channel device */
+ channel_type_claw,
+
/* Device is a channel, but we don't know
* anything about it */
channel_type_unknown,
diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c
index 1ac6563ee3e..e08e74e1612 100644
--- a/drivers/s390/net/iucv.c
+++ b/drivers/s390/net/iucv.c
@@ -1,5 +1,5 @@
/*
- * $Id: iucv.c,v 1.43 2005/02/09 14:47:43 braunu Exp $
+ * $Id: iucv.c,v 1.45 2005/04/26 22:59:06 braunu Exp $
*
* IUCV network driver
*
@@ -29,7 +29,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.43 $
+ * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.45 $
*
*/
@@ -355,7 +355,7 @@ do { \
static void
iucv_banner(void)
{
- char vbuf[] = "$Revision: 1.43 $";
+ char vbuf[] = "$Revision: 1.45 $";
char *version = vbuf;
if ((version = strchr(version, ':'))) {
@@ -2553,12 +2553,12 @@ EXPORT_SYMBOL (iucv_resume);
#endif
EXPORT_SYMBOL (iucv_reply_prmmsg);
EXPORT_SYMBOL (iucv_send);
-#if 0
EXPORT_SYMBOL (iucv_send2way);
EXPORT_SYMBOL (iucv_send2way_array);
-EXPORT_SYMBOL (iucv_send_array);
EXPORT_SYMBOL (iucv_send2way_prmmsg);
EXPORT_SYMBOL (iucv_send2way_prmmsg_array);
+#if 0
+EXPORT_SYMBOL (iucv_send_array);
EXPORT_SYMBOL (iucv_send_prmmsg);
EXPORT_SYMBOL (iucv_setmask);
#endif
diff --git a/drivers/s390/net/iucv.h b/drivers/s390/net/iucv.h
index 198330217ef..0c4644d3d2f 100644
--- a/drivers/s390/net/iucv.h
+++ b/drivers/s390/net/iucv.h
@@ -37,19 +37,19 @@
*/
#define IUCV_DBF_SETUP_NAME "iucv_setup"
#define IUCV_DBF_SETUP_LEN 32
-#define IUCV_DBF_SETUP_INDEX 1
+#define IUCV_DBF_SETUP_PAGES 2
#define IUCV_DBF_SETUP_NR_AREAS 1
#define IUCV_DBF_SETUP_LEVEL 3
#define IUCV_DBF_DATA_NAME "iucv_data"
#define IUCV_DBF_DATA_LEN 128
-#define IUCV_DBF_DATA_INDEX 1
+#define IUCV_DBF_DATA_PAGES 2
#define IUCV_DBF_DATA_NR_AREAS 1
#define IUCV_DBF_DATA_LEVEL 2
#define IUCV_DBF_TRACE_NAME "iucv_trace"
#define IUCV_DBF_TRACE_LEN 16
-#define IUCV_DBF_TRACE_INDEX 2
+#define IUCV_DBF_TRACE_PAGES 4
#define IUCV_DBF_TRACE_NR_AREAS 1
#define IUCV_DBF_TRACE_LEVEL 3
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index 0f76e945b98..46f34ba93ac 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -11,7 +11,7 @@
* Frank Pavlic (pavlic@de.ibm.com) and
* Martin Schwidefsky <schwidefsky@de.ibm.com>
*
- * $Revision: 1.96 $ $Date: 2004/11/11 13:42:33 $
+ * $Revision: 1.99 $ $Date: 2005/05/11 08:10:17 $
*
* 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
@@ -59,7 +59,7 @@
/**
* initialization string for output
*/
-#define VERSION_LCS_C "$Revision: 1.96 $"
+#define VERSION_LCS_C "$Revision: 1.99 $"
static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")";
static char debug_buffer[255];
@@ -93,8 +93,8 @@ lcs_unregister_debug_facility(void)
static int
lcs_register_debug_facility(void)
{
- lcs_dbf_setup = debug_register("lcs_setup", 1, 1, 8);
- lcs_dbf_trace = debug_register("lcs_trace", 1, 2, 8);
+ lcs_dbf_setup = debug_register("lcs_setup", 2, 1, 8);
+ lcs_dbf_trace = debug_register("lcs_trace", 2, 2, 8);
if (lcs_dbf_setup == NULL || lcs_dbf_trace == NULL) {
PRINT_ERR("Not enough memory for debug facility.\n");
lcs_unregister_debug_facility();
@@ -1098,14 +1098,6 @@ lcs_check_multicast_support(struct lcs_card *card)
PRINT_ERR("Query IPAssist failed. Assuming unsupported!\n");
return -EOPNOTSUPP;
}
- /* Print out supported assists: IPv6 */
- PRINT_INFO("LCS device %s %s IPv6 support\n", card->dev->name,
- (card->ip_assists_supported & LCS_IPASS_IPV6_SUPPORT) ?
- "with" : "without");
- /* Print out supported assist: Multicast */
- PRINT_INFO("LCS device %s %s Multicast support\n", card->dev->name,
- (card->ip_assists_supported & LCS_IPASS_MULTICAST_SUPPORT) ?
- "with" : "without");
if (card->ip_assists_supported & LCS_IPASS_MULTICAST_SUPPORT)
return 0;
return -EOPNOTSUPP;
@@ -1160,7 +1152,7 @@ list_modified:
}
}
/* re-insert all entries from the failed_list into ipm_list */
- list_for_each_entry(ipm, &failed_list, list) {
+ list_for_each_entry_safe(ipm, tmp, &failed_list, list) {
list_del_init(&ipm->list);
list_add_tail(&ipm->list, &card->ipm_list);
}
@@ -1992,7 +1984,7 @@ lcs_open_device(struct net_device *dev)
* show function for portno called by cat or similar things
*/
static ssize_t
-lcs_portno_show (struct device *dev, char *buf)
+lcs_portno_show (struct device *dev, struct device_attribute *attr, char *buf)
{
struct lcs_card *card;
@@ -2008,7 +2000,7 @@ lcs_portno_show (struct device *dev, char *buf)
* store the value which is piped to file portno
*/
static ssize_t
-lcs_portno_store (struct device *dev, const char *buf, size_t count)
+lcs_portno_store (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct lcs_card *card;
int value;
@@ -2029,7 +2021,7 @@ lcs_portno_store (struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(portno, 0644, lcs_portno_show, lcs_portno_store);
static ssize_t
-lcs_type_show(struct device *dev, char *buf)
+lcs_type_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct ccwgroup_device *cgdev;
@@ -2043,7 +2035,7 @@ lcs_type_show(struct device *dev, char *buf)
static DEVICE_ATTR(type, 0444, lcs_type_show, NULL);
static ssize_t
-lcs_timeout_show(struct device *dev, char *buf)
+lcs_timeout_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lcs_card *card;
@@ -2053,7 +2045,7 @@ lcs_timeout_show(struct device *dev, char *buf)
}
static ssize_t
-lcs_timeout_store (struct device *dev, const char *buf, size_t count)
+lcs_timeout_store (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct lcs_card *card;
int value;
@@ -2198,30 +2190,39 @@ lcs_new_device(struct ccwgroup_device *ccwgdev)
if (!dev)
goto out;
card->dev = dev;
-netdev_out:
card->dev->priv = card;
card->dev->open = lcs_open_device;
card->dev->stop = lcs_stop_device;
card->dev->hard_start_xmit = lcs_start_xmit;
card->dev->get_stats = lcs_getstats;
SET_MODULE_OWNER(dev);
- if (lcs_register_netdev(ccwgdev) != 0)
- goto out;
memcpy(card->dev->dev_addr, card->mac, LCS_MAC_LENGTH);
#ifdef CONFIG_IP_MULTICAST
if (!lcs_check_multicast_support(card))
card->dev->set_multicast_list = lcs_set_multicast_list;
#endif
- netif_stop_queue(card->dev);
+netdev_out:
lcs_set_allowed_threads(card,0xffffffff);
if (recover_state == DEV_STATE_RECOVER) {
lcs_set_multicast_list(card->dev);
card->dev->flags |= IFF_UP;
netif_wake_queue(card->dev);
card->state = DEV_STATE_UP;
- } else
+ } else {
lcs_stopcard(card);
+ }
+ if (lcs_register_netdev(ccwgdev) != 0)
+ goto out;
+
+ /* Print out supported assists: IPv6 */
+ PRINT_INFO("LCS device %s %s IPv6 support\n", card->dev->name,
+ (card->ip_assists_supported & LCS_IPASS_IPV6_SUPPORT) ?
+ "with" : "without");
+ /* Print out supported assist: Multicast */
+ PRINT_INFO("LCS device %s %s Multicast support\n", card->dev->name,
+ (card->ip_assists_supported & LCS_IPASS_MULTICAST_SUPPORT) ?
+ "with" : "without");
return 0;
out:
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index 16e8e69afb1..69425a7a6e9 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -1,5 +1,5 @@
/*
- * $Id: netiucv.c,v 1.63 2004/07/27 13:36:05 mschwide Exp $
+ * $Id: netiucv.c,v 1.66 2005/05/11 08:10:17 holzheu Exp $
*
* IUCV network driver
*
@@ -30,7 +30,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
- * RELEASE-TAG: IUCV network driver $Revision: 1.63 $
+ * RELEASE-TAG: IUCV network driver $Revision: 1.66 $
*
*/
@@ -391,15 +391,15 @@ static int
iucv_register_dbf_views(void)
{
iucv_dbf_setup = debug_register(IUCV_DBF_SETUP_NAME,
- IUCV_DBF_SETUP_INDEX,
+ IUCV_DBF_SETUP_PAGES,
IUCV_DBF_SETUP_NR_AREAS,
IUCV_DBF_SETUP_LEN);
iucv_dbf_data = debug_register(IUCV_DBF_DATA_NAME,
- IUCV_DBF_DATA_INDEX,
+ IUCV_DBF_DATA_PAGES,
IUCV_DBF_DATA_NR_AREAS,
IUCV_DBF_DATA_LEN);
iucv_dbf_trace = debug_register(IUCV_DBF_TRACE_NAME,
- IUCV_DBF_TRACE_INDEX,
+ IUCV_DBF_TRACE_PAGES,
IUCV_DBF_TRACE_NR_AREAS,
IUCV_DBF_TRACE_LEN);
@@ -1356,7 +1356,7 @@ netiucv_change_mtu (struct net_device * dev, int new_mtu)
*****************************************************************************/
static ssize_t
-user_show (struct device *dev, char *buf)
+user_show (struct device *dev, struct device_attribute *attr, char *buf)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1365,7 +1365,7 @@ user_show (struct device *dev, char *buf)
}
static ssize_t
-user_write (struct device *dev, const char *buf, size_t count)
+user_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct netiucv_priv *priv = dev->driver_data;
struct net_device *ndev = priv->conn->netdev;
@@ -1422,7 +1422,7 @@ user_write (struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(user, 0644, user_show, user_write);
static ssize_t
-buffer_show (struct device *dev, char *buf)
+buffer_show (struct device *dev, struct device_attribute *attr, char *buf)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1431,7 +1431,7 @@ buffer_show (struct device *dev, char *buf)
}
static ssize_t
-buffer_write (struct device *dev, const char *buf, size_t count)
+buffer_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct netiucv_priv *priv = dev->driver_data;
struct net_device *ndev = priv->conn->netdev;
@@ -1486,7 +1486,7 @@ buffer_write (struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write);
static ssize_t
-dev_fsm_show (struct device *dev, char *buf)
+dev_fsm_show (struct device *dev, struct device_attribute *attr, char *buf)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1497,7 +1497,7 @@ dev_fsm_show (struct device *dev, char *buf)
static DEVICE_ATTR(device_fsm_state, 0444, dev_fsm_show, NULL);
static ssize_t
-conn_fsm_show (struct device *dev, char *buf)
+conn_fsm_show (struct device *dev, struct device_attribute *attr, char *buf)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1508,7 +1508,7 @@ conn_fsm_show (struct device *dev, char *buf)
static DEVICE_ATTR(connection_fsm_state, 0444, conn_fsm_show, NULL);
static ssize_t
-maxmulti_show (struct device *dev, char *buf)
+maxmulti_show (struct device *dev, struct device_attribute *attr, char *buf)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1517,7 +1517,7 @@ maxmulti_show (struct device *dev, char *buf)
}
static ssize_t
-maxmulti_write (struct device *dev, const char *buf, size_t count)
+maxmulti_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1529,7 +1529,7 @@ maxmulti_write (struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(max_tx_buffer_used, 0644, maxmulti_show, maxmulti_write);
static ssize_t
-maxcq_show (struct device *dev, char *buf)
+maxcq_show (struct device *dev, struct device_attribute *attr, char *buf)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1538,7 +1538,7 @@ maxcq_show (struct device *dev, char *buf)
}
static ssize_t
-maxcq_write (struct device *dev, const char *buf, size_t count)
+maxcq_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1550,7 +1550,7 @@ maxcq_write (struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(max_chained_skbs, 0644, maxcq_show, maxcq_write);
static ssize_t
-sdoio_show (struct device *dev, char *buf)
+sdoio_show (struct device *dev, struct device_attribute *attr, char *buf)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1559,7 +1559,7 @@ sdoio_show (struct device *dev, char *buf)
}
static ssize_t
-sdoio_write (struct device *dev, const char *buf, size_t count)
+sdoio_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1571,7 +1571,7 @@ sdoio_write (struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(tx_single_write_ops, 0644, sdoio_show, sdoio_write);
static ssize_t
-mdoio_show (struct device *dev, char *buf)
+mdoio_show (struct device *dev, struct device_attribute *attr, char *buf)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1580,7 +1580,7 @@ mdoio_show (struct device *dev, char *buf)
}
static ssize_t
-mdoio_write (struct device *dev, const char *buf, size_t count)
+mdoio_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1592,7 +1592,7 @@ mdoio_write (struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(tx_multi_write_ops, 0644, mdoio_show, mdoio_write);
static ssize_t
-txlen_show (struct device *dev, char *buf)
+txlen_show (struct device *dev, struct device_attribute *attr, char *buf)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1601,7 +1601,7 @@ txlen_show (struct device *dev, char *buf)
}
static ssize_t
-txlen_write (struct device *dev, const char *buf, size_t count)
+txlen_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1613,7 +1613,7 @@ txlen_write (struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(netto_bytes, 0644, txlen_show, txlen_write);
static ssize_t
-txtime_show (struct device *dev, char *buf)
+txtime_show (struct device *dev, struct device_attribute *attr, char *buf)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1622,7 +1622,7 @@ txtime_show (struct device *dev, char *buf)
}
static ssize_t
-txtime_write (struct device *dev, const char *buf, size_t count)
+txtime_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1634,7 +1634,7 @@ txtime_write (struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(max_tx_io_time, 0644, txtime_show, txtime_write);
static ssize_t
-txpend_show (struct device *dev, char *buf)
+txpend_show (struct device *dev, struct device_attribute *attr, char *buf)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1643,7 +1643,7 @@ txpend_show (struct device *dev, char *buf)
}
static ssize_t
-txpend_write (struct device *dev, const char *buf, size_t count)
+txpend_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1655,7 +1655,7 @@ txpend_write (struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(tx_pending, 0644, txpend_show, txpend_write);
static ssize_t
-txmpnd_show (struct device *dev, char *buf)
+txmpnd_show (struct device *dev, struct device_attribute *attr, char *buf)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -1664,7 +1664,7 @@ txmpnd_show (struct device *dev, char *buf)
}
static ssize_t
-txmpnd_write (struct device *dev, const char *buf, size_t count)
+txmpnd_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct netiucv_priv *priv = dev->driver_data;
@@ -2076,7 +2076,7 @@ DRIVER_ATTR(remove, 0200, NULL, remove_write);
static void
netiucv_banner(void)
{
- char vbuf[] = "$Revision: 1.63 $";
+ char vbuf[] = "$Revision: 1.66 $";
char *version = vbuf;
if ((version = strchr(version, ':'))) {
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index a341041a6cf..008e0a5d2eb 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -24,7 +24,7 @@
#include "qeth_mpc.h"
-#define VERSION_QETH_H "$Revision: 1.135 $"
+#define VERSION_QETH_H "$Revision: 1.139 $"
#ifdef CONFIG_QETH_IPV6
#define QETH_VERSION_IPV6 ":IPv6"
@@ -42,44 +42,44 @@
*/
#define QETH_DBF_SETUP_NAME "qeth_setup"
#define QETH_DBF_SETUP_LEN 8
-#define QETH_DBF_SETUP_INDEX 3
+#define QETH_DBF_SETUP_PAGES 8
#define QETH_DBF_SETUP_NR_AREAS 1
#define QETH_DBF_SETUP_LEVEL 5
#define QETH_DBF_MISC_NAME "qeth_misc"
#define QETH_DBF_MISC_LEN 128
-#define QETH_DBF_MISC_INDEX 1
+#define QETH_DBF_MISC_PAGES 2
#define QETH_DBF_MISC_NR_AREAS 1
#define QETH_DBF_MISC_LEVEL 2
#define QETH_DBF_DATA_NAME "qeth_data"
#define QETH_DBF_DATA_LEN 96
-#define QETH_DBF_DATA_INDEX 3
+#define QETH_DBF_DATA_PAGES 8
#define QETH_DBF_DATA_NR_AREAS 1
#define QETH_DBF_DATA_LEVEL 2
#define QETH_DBF_CONTROL_NAME "qeth_control"
#define QETH_DBF_CONTROL_LEN 256
-#define QETH_DBF_CONTROL_INDEX 3
+#define QETH_DBF_CONTROL_PAGES 8
#define QETH_DBF_CONTROL_NR_AREAS 2
#define QETH_DBF_CONTROL_LEVEL 5
#define QETH_DBF_TRACE_NAME "qeth_trace"
#define QETH_DBF_TRACE_LEN 8
-#define QETH_DBF_TRACE_INDEX 2
+#define QETH_DBF_TRACE_PAGES 4
#define QETH_DBF_TRACE_NR_AREAS 2
#define QETH_DBF_TRACE_LEVEL 3
extern debug_info_t *qeth_dbf_trace;
#define QETH_DBF_SENSE_NAME "qeth_sense"
#define QETH_DBF_SENSE_LEN 64
-#define QETH_DBF_SENSE_INDEX 1
+#define QETH_DBF_SENSE_PAGES 2
#define QETH_DBF_SENSE_NR_AREAS 1
#define QETH_DBF_SENSE_LEVEL 2
#define QETH_DBF_QERR_NAME "qeth_qerr"
#define QETH_DBF_QERR_LEN 8
-#define QETH_DBF_QERR_INDEX 1
+#define QETH_DBF_QERR_PAGES 2
#define QETH_DBF_QERR_NR_AREAS 2
#define QETH_DBF_QERR_LEVEL 2
@@ -288,7 +288,8 @@ qeth_is_ipa_enabled(struct qeth_ipa_info *ipa, enum qeth_ipa_funcs func)
#define QETH_TX_TIMEOUT 100 * HZ
#define QETH_HEADER_SIZE 32
#define MAX_PORTNO 15
-#define QETH_FAKE_LL_LEN ETH_HLEN
+#define QETH_FAKE_LL_LEN_ETH ETH_HLEN
+#define QETH_FAKE_LL_LEN_TR (sizeof(struct trh_hdr)-TR_MAXRIFLEN+sizeof(struct trllc))
#define QETH_FAKE_LL_V6_ADDR_POS 24
/*IPv6 address autoconfiguration stuff*/
@@ -369,6 +370,25 @@ struct qeth_hdr {
} hdr;
} __attribute__ ((packed));
+/*TCP Segmentation Offload header*/
+struct qeth_hdr_ext_tso {
+ __u16 hdr_tot_len;
+ __u8 imb_hdr_no;
+ __u8 reserved;
+ __u8 hdr_type;
+ __u8 hdr_version;
+ __u16 hdr_len;
+ __u32 payload_len;
+ __u16 mss;
+ __u16 dg_hdr_len;
+ __u8 padding[16];
+} __attribute__ ((packed));
+
+struct qeth_hdr_tso {
+ struct qeth_hdr hdr; /*hdr->hdr.l3.xxx*/
+ struct qeth_hdr_ext_tso ext;
+} __attribute__ ((packed));
+
/* flags for qeth_hdr.flags */
#define QETH_HDR_PASSTHRU 0x10
@@ -866,6 +886,7 @@ qeth_push_skb(struct qeth_card *card, struct sk_buff **skb, int size)
return hdr;
}
+
inline static int
qeth_get_hlen(__u8 link_type)
{
@@ -873,19 +894,19 @@ qeth_get_hlen(__u8 link_type)
switch (link_type) {
case QETH_LINK_TYPE_HSTR:
case QETH_LINK_TYPE_LANE_TR:
- return sizeof(struct qeth_hdr) + TR_HLEN;
+ return sizeof(struct qeth_hdr_tso) + TR_HLEN;
default:
#ifdef CONFIG_QETH_VLAN
- return sizeof(struct qeth_hdr) + VLAN_ETH_HLEN;
+ return sizeof(struct qeth_hdr_tso) + VLAN_ETH_HLEN;
#else
- return sizeof(struct qeth_hdr) + ETH_HLEN;
+ return sizeof(struct qeth_hdr_tso) + ETH_HLEN;
#endif
}
#else /* CONFIG_QETH_IPV6 */
#ifdef CONFIG_QETH_VLAN
- return sizeof(struct qeth_hdr) + VLAN_HLEN;
+ return sizeof(struct qeth_hdr_tso) + VLAN_HLEN;
#else
- return sizeof(struct qeth_hdr);
+ return sizeof(struct qeth_hdr_tso);
#endif
#endif /* CONFIG_QETH_IPV6 */
}
diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c
index 7ee1c06ed68..f94f1f25eec 100644
--- a/drivers/s390/net/qeth_eddp.c
+++ b/drivers/s390/net/qeth_eddp.c
@@ -1,6 +1,6 @@
/*
*
- * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.11 $)
+ * linux/drivers/s390/net/qeth_eddp.c ($Revision: 1.13 $)
*
* Enhanced Device Driver Packing (EDDP) support for the qeth driver.
*
@@ -8,7 +8,7 @@
*
* Author(s): Thomas Spatzier <tspat@de.ibm.com>
*
- * $Revision: 1.11 $ $Date: 2005/03/24 09:04:18 $
+ * $Revision: 1.13 $ $Date: 2005/05/04 20:19:18 $
*
*/
#include <linux/config.h>
@@ -85,7 +85,7 @@ void
qeth_eddp_buf_release_contexts(struct qeth_qdio_out_buffer *buf)
{
struct qeth_eddp_context_reference *ref;
-
+
QETH_DBF_TEXT(trace, 6, "eddprctx");
while (!list_empty(&buf->ctx_list)){
ref = list_entry(buf->ctx_list.next,
@@ -139,7 +139,7 @@ qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue,
"buffer!\n");
goto out;
}
- }
+ }
/* check if the whole next skb fits into current buffer */
if ((QETH_MAX_BUFFER_ELEMENTS(queue->card) -
buf->next_element_to_fill)
@@ -152,7 +152,7 @@ qeth_eddp_fill_buffer(struct qeth_qdio_out_q *queue,
* and increment ctx's refcnt */
must_refcnt = 1;
continue;
- }
+ }
if (must_refcnt){
must_refcnt = 0;
if (qeth_eddp_buf_ref_context(buf, ctx)){
@@ -202,40 +202,29 @@ out:
return flush_cnt;
}
-static inline int
-qeth_get_skb_data_len(struct sk_buff *skb)
-{
- int len = skb->len;
- int i;
-
- for (i = 0; i < skb_shinfo(skb)->nr_frags; ++i)
- len -= skb_shinfo(skb)->frags[i].size;
- return len;
-}
-
static inline void
qeth_eddp_create_segment_hdrs(struct qeth_eddp_context *ctx,
- struct qeth_eddp_data *eddp)
+ struct qeth_eddp_data *eddp, int data_len)
{
u8 *page;
int page_remainder;
int page_offset;
- int hdr_len;
+ int pkt_len;
struct qeth_eddp_element *element;
QETH_DBF_TEXT(trace, 5, "eddpcrsh");
page = ctx->pages[ctx->offset >> PAGE_SHIFT];
page_offset = ctx->offset % PAGE_SIZE;
element = &ctx->elements[ctx->num_elements];
- hdr_len = eddp->nhl + eddp->thl;
+ pkt_len = eddp->nhl + eddp->thl + data_len;
/* FIXME: layer2 and VLAN !!! */
if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2)
- hdr_len += ETH_HLEN;
+ pkt_len += ETH_HLEN;
if (eddp->mac.h_proto == __constant_htons(ETH_P_8021Q))
- hdr_len += VLAN_HLEN;
- /* does complete header fit in current page ? */
+ pkt_len += VLAN_HLEN;
+ /* does complete packet fit in current page ? */
page_remainder = PAGE_SIZE - page_offset;
- if (page_remainder < (sizeof(struct qeth_hdr) + hdr_len)){
+ if (page_remainder < (sizeof(struct qeth_hdr) + pkt_len)){
/* no -> go to start of next page */
ctx->offset += page_remainder;
page = ctx->pages[ctx->offset >> PAGE_SHIFT];
@@ -281,7 +270,7 @@ qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len,
int left_in_frag;
int copy_len;
u8 *src;
-
+
QETH_DBF_TEXT(trace, 5, "eddpcdtc");
if (skb_shinfo(eddp->skb)->nr_frags == 0) {
memcpy(dst, eddp->skb->data + eddp->skb_offset, len);
@@ -292,7 +281,7 @@ qeth_eddp_copy_data_tcp(char *dst, struct qeth_eddp_data *eddp, int len,
while (len > 0) {
if (eddp->frag < 0) {
/* we're in skb->data */
- left_in_frag = qeth_get_skb_data_len(eddp->skb)
+ left_in_frag = (eddp->skb->len - eddp->skb->data_len)
- eddp->skb_offset;
src = eddp->skb->data + eddp->skb_offset;
} else {
@@ -424,7 +413,7 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
struct tcphdr *tcph;
int data_len;
u32 hcsum;
-
+
QETH_DBF_TEXT(trace, 5, "eddpftcp");
eddp->skb_offset = sizeof(struct qeth_hdr) + eddp->nhl + eddp->thl;
tcph = eddp->skb->h.th;
@@ -464,7 +453,7 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
else
hcsum = qeth_eddp_check_tcp6_hdr(eddp, data_len);
/* fill the next segment into the context */
- qeth_eddp_create_segment_hdrs(ctx, eddp);
+ qeth_eddp_create_segment_hdrs(ctx, eddp, data_len);
qeth_eddp_create_segment_data_tcp(ctx, eddp, data_len, hcsum);
if (eddp->skb_offset >= eddp->skb->len)
break;
@@ -474,13 +463,13 @@ __qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
eddp->th.tcp.h.seq += data_len;
}
}
-
+
static inline int
qeth_eddp_fill_context_tcp(struct qeth_eddp_context *ctx,
struct sk_buff *skb, struct qeth_hdr *qhdr)
{
struct qeth_eddp_data *eddp = NULL;
-
+
QETH_DBF_TEXT(trace, 5, "eddpficx");
/* create our segmentation headers and copy original headers */
if (skb->protocol == ETH_P_IP)
@@ -520,7 +509,7 @@ qeth_eddp_calc_num_pages(struct qeth_eddp_context *ctx, struct sk_buff *skb,
int hdr_len)
{
int skbs_per_page;
-
+
QETH_DBF_TEXT(trace, 5, "eddpcanp");
/* can we put multiple skbs in one page? */
skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->tso_size + hdr_len);
@@ -600,7 +589,7 @@ qeth_eddp_create_context_tcp(struct qeth_card *card, struct sk_buff *skb,
struct qeth_hdr *qhdr)
{
struct qeth_eddp_context *ctx = NULL;
-
+
QETH_DBF_TEXT(trace, 5, "creddpct");
if (skb->protocol == ETH_P_IP)
ctx = qeth_eddp_create_context_generic(card, skb,
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 607b92542df..3cb88c77003 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -1,6 +1,6 @@
/*
*
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.206 $)
+ * linux/drivers/s390/net/qeth_main.c ($Revision: 1.214 $)
*
* Linux on zSeries OSA Express and HiperSockets support
*
@@ -12,7 +12,7 @@
* Frank Pavlic (pavlic@de.ibm.com) and
* Thomas Spatzier <tspat@de.ibm.com>
*
- * $Revision: 1.206 $ $Date: 2005/03/24 09:04:18 $
+ * $Revision: 1.214 $ $Date: 2005/05/04 20:19:18 $
*
* 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
@@ -80,7 +80,7 @@ qeth_eyecatcher(void)
#include "qeth_eddp.h"
#include "qeth_tso.h"
-#define VERSION_QETH_C "$Revision: 1.206 $"
+#define VERSION_QETH_C "$Revision: 1.214 $"
static const char *version = "qeth S/390 OSA-Express driver";
/**
@@ -158,6 +158,9 @@ qeth_irq_tasklet(unsigned long);
static int
qeth_set_online(struct ccwgroup_device *);
+static int
+__qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode);
+
static struct qeth_ipaddr *
qeth_get_addr_buffer(enum qeth_prot_versions);
@@ -510,10 +513,10 @@ qeth_irq_tasklet(unsigned long data)
wake_up(&card->wait_q);
}
-static int qeth_stop_card(struct qeth_card *);
+static int qeth_stop_card(struct qeth_card *, int);
static int
-qeth_set_offline(struct ccwgroup_device *cgdev)
+__qeth_set_offline(struct ccwgroup_device *cgdev, int recovery_mode)
{
struct qeth_card *card = (struct qeth_card *) cgdev->dev.driver_data;
int rc = 0;
@@ -523,7 +526,7 @@ qeth_set_offline(struct ccwgroup_device *cgdev)
QETH_DBF_HEX(setup, 3, &card, sizeof(void *));
recover_flag = card->state;
- if (qeth_stop_card(card) == -ERESTARTSYS){
+ if (qeth_stop_card(card, recovery_mode) == -ERESTARTSYS){
PRINT_WARN("Stopping card %s interrupted by user!\n",
CARD_BUS_ID(card));
return -ERESTARTSYS;
@@ -540,6 +543,12 @@ qeth_set_offline(struct ccwgroup_device *cgdev)
}
static int
+qeth_set_offline(struct ccwgroup_device *cgdev)
+{
+ return __qeth_set_offline(cgdev, 0);
+}
+
+static int
qeth_wait_for_threads(struct qeth_card *card, unsigned long threads);
@@ -953,8 +962,8 @@ qeth_recover(void *ptr)
PRINT_WARN("Recovery of device %s started ...\n",
CARD_BUS_ID(card));
card->use_hard_stop = 1;
- qeth_set_offline(card->gdev);
- rc = qeth_set_online(card->gdev);
+ __qeth_set_offline(card->gdev,1);
+ rc = __qeth_set_online(card->gdev,1);
if (!rc)
PRINT_INFO("Device %s successfully recovered!\n",
CARD_BUS_ID(card));
@@ -2152,9 +2161,15 @@ qeth_get_next_skb(struct qeth_card *card, struct qdio_buffer *buffer,
if (!skb_len)
return NULL;
if (card->options.fake_ll){
- if (!(skb = qeth_get_skb(skb_len + QETH_FAKE_LL_LEN)))
- goto no_mem;
- skb_pull(skb, QETH_FAKE_LL_LEN);
+ if(card->dev->type == ARPHRD_IEEE802_TR){
+ if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_TR)))
+ goto no_mem;
+ skb_reserve(skb,QETH_FAKE_LL_LEN_TR);
+ } else {
+ if (!(skb = qeth_get_skb(skb_len+QETH_FAKE_LL_LEN_ETH)))
+ goto no_mem;
+ skb_reserve(skb,QETH_FAKE_LL_LEN_ETH);
+ }
} else if (!(skb = qeth_get_skb(skb_len)))
goto no_mem;
data_ptr = element->addr + offset;
@@ -2229,14 +2244,68 @@ qeth_type_trans(struct sk_buff *skb, struct net_device *dev)
}
static inline void
-qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb,
+qeth_rebuild_skb_fake_ll_tr(struct qeth_card *card, struct sk_buff *skb,
+ struct qeth_hdr *hdr)
+{
+ struct trh_hdr *fake_hdr;
+ struct trllc *fake_llc;
+ struct iphdr *ip_hdr;
+
+ QETH_DBF_TEXT(trace,5,"skbfktr");
+ skb->mac.raw = skb->data - QETH_FAKE_LL_LEN_TR;
+ /* this is a fake ethernet header */
+ fake_hdr = (struct trh_hdr *) skb->mac.raw;
+
+ /* the destination MAC address */
+ switch (skb->pkt_type){
+ case PACKET_MULTICAST:
+ switch (skb->protocol){
+#ifdef CONFIG_QETH_IPV6
+ case __constant_htons(ETH_P_IPV6):
+ ndisc_mc_map((struct in6_addr *)
+ skb->data + QETH_FAKE_LL_V6_ADDR_POS,
+ fake_hdr->daddr, card->dev, 0);
+ break;
+#endif /* CONFIG_QETH_IPV6 */
+ case __constant_htons(ETH_P_IP):
+ ip_hdr = (struct iphdr *)skb->data;
+ ip_tr_mc_map(ip_hdr->daddr, fake_hdr->daddr);
+ break;
+ default:
+ memcpy(fake_hdr->daddr, card->dev->dev_addr, TR_ALEN);
+ }
+ break;
+ case PACKET_BROADCAST:
+ memset(fake_hdr->daddr, 0xff, TR_ALEN);
+ break;
+ default:
+ memcpy(fake_hdr->daddr, card->dev->dev_addr, TR_ALEN);
+ }
+ /* the source MAC address */
+ if (hdr->hdr.l3.ext_flags & QETH_HDR_EXT_SRC_MAC_ADDR)
+ memcpy(fake_hdr->saddr, &hdr->hdr.l3.dest_addr[2], TR_ALEN);
+ else
+ memset(fake_hdr->saddr, 0, TR_ALEN);
+ fake_hdr->rcf=0;
+ fake_llc = (struct trllc*)&(fake_hdr->rcf);
+ fake_llc->dsap = EXTENDED_SAP;
+ fake_llc->ssap = EXTENDED_SAP;
+ fake_llc->llc = UI_CMD;
+ fake_llc->protid[0] = 0;
+ fake_llc->protid[1] = 0;
+ fake_llc->protid[2] = 0;
+ fake_llc->ethertype = ETH_P_IP;
+}
+
+static inline void
+qeth_rebuild_skb_fake_ll_eth(struct qeth_card *card, struct sk_buff *skb,
struct qeth_hdr *hdr)
{
struct ethhdr *fake_hdr;
struct iphdr *ip_hdr;
- QETH_DBF_TEXT(trace,5,"skbfake");
- skb->mac.raw = skb->data - QETH_FAKE_LL_LEN;
+ QETH_DBF_TEXT(trace,5,"skbfketh");
+ skb->mac.raw = skb->data - QETH_FAKE_LL_LEN_ETH;
/* this is a fake ethernet header */
fake_hdr = (struct ethhdr *) skb->mac.raw;
@@ -2253,10 +2322,7 @@ qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb,
#endif /* CONFIG_QETH_IPV6 */
case __constant_htons(ETH_P_IP):
ip_hdr = (struct iphdr *)skb->data;
- if (card->dev->type == ARPHRD_IEEE802_TR)
- ip_tr_mc_map(ip_hdr->daddr, fake_hdr->h_dest);
- else
- ip_eth_mc_map(ip_hdr->daddr, fake_hdr->h_dest);
+ ip_eth_mc_map(ip_hdr->daddr, fake_hdr->h_dest);
break;
default:
memcpy(fake_hdr->h_dest, card->dev->dev_addr, ETH_ALEN);
@@ -2278,6 +2344,16 @@ qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb,
}
static inline void
+qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb,
+ struct qeth_hdr *hdr)
+{
+ if (card->dev->type == ARPHRD_IEEE802_TR)
+ qeth_rebuild_skb_fake_ll_tr(card, skb, hdr);
+ else
+ qeth_rebuild_skb_fake_ll_eth(card, skb, hdr);
+}
+
+static inline void
qeth_rebuild_skb_vlan(struct qeth_card *card, struct sk_buff *skb,
struct qeth_hdr *hdr)
{
@@ -3440,16 +3516,25 @@ qeth_fake_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, void *daddr, void *saddr,
unsigned len)
{
- struct ethhdr *hdr;
+ if(dev->type == ARPHRD_IEEE802_TR){
+ struct trh_hdr *hdr;
+ hdr = (struct trh_hdr *)skb_push(skb, QETH_FAKE_LL_LEN_TR);
+ memcpy(hdr->saddr, dev->dev_addr, TR_ALEN);
+ memcpy(hdr->daddr, "FAKELL", TR_ALEN);
+ return QETH_FAKE_LL_LEN_TR;
+
+ } else {
+ struct ethhdr *hdr;
+ hdr = (struct ethhdr *)skb_push(skb, QETH_FAKE_LL_LEN_ETH);
+ memcpy(hdr->h_source, dev->dev_addr, ETH_ALEN);
+ memcpy(hdr->h_dest, "FAKELL", ETH_ALEN);
+ if (type != ETH_P_802_3)
+ hdr->h_proto = htons(type);
+ else
+ hdr->h_proto = htons(len);
+ return QETH_FAKE_LL_LEN_ETH;
- hdr = (struct ethhdr *)skb_push(skb, QETH_FAKE_LL_LEN);
- memcpy(hdr->h_source, dev->dev_addr, ETH_ALEN);
- memcpy(hdr->h_dest, "FAKELL", ETH_ALEN);
- if (type != ETH_P_802_3)
- hdr->h_proto = htons(type);
- else
- hdr->h_proto = htons(len);
- return QETH_FAKE_LL_LEN;
+ }
}
static inline int
@@ -3710,16 +3795,12 @@ static inline int
qeth_prepare_skb(struct qeth_card *card, struct sk_buff **skb,
struct qeth_hdr **hdr, int ipv)
{
- int rc = 0;
#ifdef CONFIG_QETH_VLAN
u16 *tag;
#endif
QETH_DBF_TEXT(trace, 6, "prepskb");
- rc = qeth_realloc_headroom(card, skb, sizeof(struct qeth_hdr));
- if (rc)
- return rc;
#ifdef CONFIG_QETH_VLAN
if (card->vlangrp && vlan_tx_tag_present(*skb) &&
((ipv == 6) || card->options.layer2) ) {
@@ -3882,9 +3963,15 @@ qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
memcpy(hdr->hdr.l3.dest_addr, &skb->nh.ipv6h->daddr, 16);
}
} else { /* passthrough */
- if (!memcmp(skb->data + sizeof(struct qeth_hdr),
+ if((skb->dev->type == ARPHRD_IEEE802_TR) &&
+ !memcmp(skb->data + sizeof(struct qeth_hdr) +
+ sizeof(__u16), skb->dev->broadcast, 6)) {
+ hdr->hdr.l3.flags = QETH_CAST_BROADCAST |
+ QETH_HDR_PASSTHRU;
+ } else if (!memcmp(skb->data + sizeof(struct qeth_hdr),
skb->dev->broadcast, 6)) { /* broadcast? */
- hdr->hdr.l3.flags = QETH_CAST_BROADCAST | QETH_HDR_PASSTHRU;
+ hdr->hdr.l3.flags = QETH_CAST_BROADCAST |
+ QETH_HDR_PASSTHRU;
} else {
hdr->hdr.l3.flags = (cast_type == RTN_MULTICAST) ?
QETH_CAST_MULTICAST | QETH_HDR_PASSTHRU :
@@ -3894,67 +3981,29 @@ qeth_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
}
static inline void
-__qeth_fill_buffer_frag(struct sk_buff *skb, struct qdio_buffer *buffer,
- int *next_element_to_fill)
-{
- int length = skb->len;
- struct skb_frag_struct *frag;
- int fragno;
- unsigned long addr;
- int element;
- int first_lap = 1;
-
- fragno = skb_shinfo(skb)->nr_frags; /* start with last frag */
- element = *next_element_to_fill + fragno;
- while (length > 0) {
- if (fragno > 0) {
- frag = &skb_shinfo(skb)->frags[fragno - 1];
- addr = (page_to_pfn(frag->page) << PAGE_SHIFT) +
- frag->page_offset;
- buffer->element[element].addr = (char *)addr;
- buffer->element[element].length = frag->size;
- length -= frag->size;
- if (first_lap)
- buffer->element[element].flags =
- SBAL_FLAGS_LAST_FRAG;
- else
- buffer->element[element].flags =
- SBAL_FLAGS_MIDDLE_FRAG;
- } else {
- buffer->element[element].addr = skb->data;
- buffer->element[element].length = length;
- length = 0;
- buffer->element[element].flags =
- SBAL_FLAGS_FIRST_FRAG;
- }
- element--;
- fragno--;
- first_lap = 0;
- }
- *next_element_to_fill += skb_shinfo(skb)->nr_frags + 1;
-}
-
-static inline void
__qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer,
- int *next_element_to_fill)
+ int is_tso, int *next_element_to_fill)
{
int length = skb->len;
int length_here;
int element;
char *data;
- int first_lap = 1;
+ int first_lap ;
element = *next_element_to_fill;
data = skb->data;
+ first_lap = (is_tso == 0 ? 1 : 0);
+
while (length > 0) {
/* length_here is the remaining amount of data in this page */
length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE);
if (length < length_here)
length_here = length;
+
buffer->element[element].addr = data;
buffer->element[element].length = length_here;
length -= length_here;
- if (!length){
+ if (!length) {
if (first_lap)
buffer->element[element].flags = 0;
else
@@ -3981,17 +4030,35 @@ qeth_fill_buffer(struct qeth_qdio_out_q *queue,
struct sk_buff *skb)
{
struct qdio_buffer *buffer;
- int flush_cnt = 0;
+ struct qeth_hdr_tso *hdr;
+ int flush_cnt = 0, hdr_len, large_send = 0;
QETH_DBF_TEXT(trace, 6, "qdfillbf");
+
buffer = buf->buffer;
atomic_inc(&skb->users);
skb_queue_tail(&buf->skb_list, skb);
+
+ hdr = (struct qeth_hdr_tso *) skb->data;
+ /*check first on TSO ....*/
+ if (hdr->hdr.hdr.l3.id == QETH_HEADER_TYPE_TSO) {
+ int element = buf->next_element_to_fill;
+
+ hdr_len = sizeof(struct qeth_hdr_tso) + hdr->ext.dg_hdr_len;
+ /*fill first buffer entry only with header information */
+ buffer->element[element].addr = skb->data;
+ buffer->element[element].length = hdr_len;
+ buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG;
+ buf->next_element_to_fill++;
+ skb->data += hdr_len;
+ skb->len -= hdr_len;
+ large_send = 1;
+ }
if (skb_shinfo(skb)->nr_frags == 0)
- __qeth_fill_buffer(skb, buffer,
+ __qeth_fill_buffer(skb, buffer, large_send,
(int *)&buf->next_element_to_fill);
else
- __qeth_fill_buffer_frag(skb, buffer,
+ __qeth_fill_buffer_frag(skb, buffer, large_send,
(int *)&buf->next_element_to_fill);
if (!queue->do_pack) {
@@ -4184,6 +4251,25 @@ out:
}
static inline int
+qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb)
+{
+ int elements_needed = 0;
+
+ if (skb_shinfo(skb)->nr_frags > 0) {
+ elements_needed = (skb_shinfo(skb)->nr_frags + 1);
+ }
+ if (elements_needed == 0 )
+ elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE)
+ + skb->len) >> PAGE_SHIFT);
+ if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){
+ PRINT_ERR("qeth_do_send_packet: invalid size of "
+ "IP packet. Discarded.");
+ return 0;
+ }
+ return elements_needed;
+}
+
+static inline int
qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
{
int ipv = 0;
@@ -4205,7 +4291,11 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
dev_kfree_skb_irq(skb);
return 0;
}
- skb_pull(skb, QETH_FAKE_LL_LEN);
+ if(card->dev->type == ARPHRD_IEEE802_TR){
+ skb_pull(skb, QETH_FAKE_LL_LEN_TR);
+ } else {
+ skb_pull(skb, QETH_FAKE_LL_LEN_ETH);
+ }
}
}
cast_type = qeth_get_cast_type(card, skb);
@@ -4221,19 +4311,25 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
if (skb_shinfo(skb)->tso_size)
large_send = card->options.large_send;
- if ((rc = qeth_prepare_skb(card, &skb, &hdr, ipv))){
- QETH_DBF_TEXT_(trace, 4, "pskbe%d", rc);
- return rc;
- }
/*are we able to do TSO ? If so ,prepare and send it from here */
if ((large_send == QETH_LARGE_SEND_TSO) &&
(cast_type == RTN_UNSPEC)) {
- rc = qeth_tso_send_packet(card, skb, queue,
- ipv, cast_type);
- goto do_statistics;
+ rc = qeth_tso_prepare_packet(card, skb, ipv, cast_type);
+ if (rc) {
+ card->stats.tx_dropped++;
+ card->stats.tx_errors++;
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+ }
+ elements_needed++;
+ } else {
+ if ((rc = qeth_prepare_skb(card, &skb, &hdr, ipv))) {
+ QETH_DBF_TEXT_(trace, 4, "pskbe%d", rc);
+ return rc;
+ }
+ qeth_fill_header(card, hdr, skb, ipv, cast_type);
}
- qeth_fill_header(card, hdr, skb, ipv, cast_type);
if (large_send == QETH_LARGE_SEND_EDDP) {
ctx = qeth_eddp_create_context(card, skb, hdr);
if (ctx == NULL) {
@@ -4241,7 +4337,7 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
return -EINVAL;
}
} else {
- elements_needed = qeth_get_elements_no(card,(void*) hdr, skb);
+ elements_needed += qeth_get_elements_no(card,(void*) hdr, skb);
if (!elements_needed)
return -EINVAL;
}
@@ -4252,12 +4348,12 @@ qeth_send_packet(struct qeth_card *card, struct sk_buff *skb)
else
rc = qeth_do_send_packet_fast(card, queue, skb, hdr,
elements_needed, ctx);
-do_statistics:
if (!rc){
card->stats.tx_packets++;
card->stats.tx_bytes += skb->len;
#ifdef CONFIG_QETH_PERF_STATS
- if (skb_shinfo(skb)->tso_size) {
+ if (skb_shinfo(skb)->tso_size &&
+ !(large_send == QETH_LARGE_SEND_NO)) {
card->perf_stats.large_send_bytes += skb->len;
card->perf_stats.large_send_cnt++;
}
@@ -7154,7 +7250,7 @@ qeth_wait_for_threads(struct qeth_card *card, unsigned long threads)
}
static int
-qeth_stop_card(struct qeth_card *card)
+qeth_stop_card(struct qeth_card *card, int recovery_mode)
{
int rc = 0;
@@ -7167,9 +7263,13 @@ qeth_stop_card(struct qeth_card *card)
if (card->read.state == CH_STATE_UP &&
card->write.state == CH_STATE_UP &&
(card->state == CARD_STATE_UP)) {
- rtnl_lock();
- dev_close(card->dev);
- rtnl_unlock();
+ if(recovery_mode) {
+ qeth_stop(card->dev);
+ } else {
+ rtnl_lock();
+ dev_close(card->dev);
+ rtnl_unlock();
+ }
if (!card->use_hard_stop) {
__u8 *mac = &card->dev->dev_addr[0];
rc = qeth_layer2_send_delmac(card, mac);
@@ -7341,13 +7441,17 @@ qeth_register_netdev(struct qeth_card *card)
}
static void
-qeth_start_again(struct qeth_card *card)
+qeth_start_again(struct qeth_card *card, int recovery_mode)
{
QETH_DBF_TEXT(setup ,2, "startag");
- rtnl_lock();
- dev_open(card->dev);
- rtnl_unlock();
+ if(recovery_mode) {
+ qeth_open(card->dev);
+ } else {
+ rtnl_lock();
+ dev_open(card->dev);
+ rtnl_unlock();
+ }
/* this also sets saved unicast addresses */
qeth_set_multicast_list(card->dev);
}
@@ -7404,7 +7508,7 @@ static void qeth_make_parameters_consistent(struct qeth_card *card)
static int
-qeth_set_online(struct ccwgroup_device *gdev)
+__qeth_set_online(struct ccwgroup_device *gdev, int recovery_mode)
{
struct qeth_card *card = gdev->dev.driver_data;
int rc = 0;
@@ -7464,12 +7568,12 @@ qeth_set_online(struct ccwgroup_device *gdev)
* we can also use this state for recovery purposes*/
qeth_set_allowed_threads(card, 0xffffffff, 0);
if (recover_flag == CARD_STATE_RECOVER)
- qeth_start_again(card);
+ qeth_start_again(card, recovery_mode);
qeth_notify_processes();
return 0;
out_remove:
card->use_hard_stop = 1;
- qeth_stop_card(card);
+ qeth_stop_card(card, 0);
ccw_device_set_offline(CARD_DDEV(card));
ccw_device_set_offline(CARD_WDEV(card));
ccw_device_set_offline(CARD_RDEV(card));
@@ -7480,6 +7584,12 @@ out_remove:
return -ENODEV;
}
+static int
+qeth_set_online(struct ccwgroup_device *gdev)
+{
+ return __qeth_set_online(gdev, 0);
+}
+
static struct ccw_device_id qeth_ids[] = {
{CCW_DEVICE(0x1731, 0x01), driver_info:QETH_CARD_TYPE_OSAE},
{CCW_DEVICE(0x1731, 0x05), driver_info:QETH_CARD_TYPE_IQD},
@@ -7529,31 +7639,31 @@ static int
qeth_register_dbf_views(void)
{
qeth_dbf_setup = debug_register(QETH_DBF_SETUP_NAME,
- QETH_DBF_SETUP_INDEX,
+ QETH_DBF_SETUP_PAGES,
QETH_DBF_SETUP_NR_AREAS,
QETH_DBF_SETUP_LEN);
qeth_dbf_misc = debug_register(QETH_DBF_MISC_NAME,
- QETH_DBF_MISC_INDEX,
+ QETH_DBF_MISC_PAGES,
QETH_DBF_MISC_NR_AREAS,
QETH_DBF_MISC_LEN);
qeth_dbf_data = debug_register(QETH_DBF_DATA_NAME,
- QETH_DBF_DATA_INDEX,
+ QETH_DBF_DATA_PAGES,
QETH_DBF_DATA_NR_AREAS,
QETH_DBF_DATA_LEN);
qeth_dbf_control = debug_register(QETH_DBF_CONTROL_NAME,
- QETH_DBF_CONTROL_INDEX,
+ QETH_DBF_CONTROL_PAGES,
QETH_DBF_CONTROL_NR_AREAS,
QETH_DBF_CONTROL_LEN);
qeth_dbf_sense = debug_register(QETH_DBF_SENSE_NAME,
- QETH_DBF_SENSE_INDEX,
+ QETH_DBF_SENSE_PAGES,
QETH_DBF_SENSE_NR_AREAS,
QETH_DBF_SENSE_LEN);
qeth_dbf_qerr = debug_register(QETH_DBF_QERR_NAME,
- QETH_DBF_QERR_INDEX,
+ QETH_DBF_QERR_PAGES,
QETH_DBF_QERR_NR_AREAS,
QETH_DBF_QERR_LEN);
qeth_dbf_trace = debug_register(QETH_DBF_TRACE_NAME,
- QETH_DBF_TRACE_INDEX,
+ QETH_DBF_TRACE_PAGES,
QETH_DBF_TRACE_NR_AREAS,
QETH_DBF_TRACE_LEN);
diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c
index 24034839821..98bedb0cb38 100644
--- a/drivers/s390/net/qeth_sys.c
+++ b/drivers/s390/net/qeth_sys.c
@@ -30,7 +30,7 @@ const char *VERSION_QETH_SYS_C = "$Revision: 1.51 $";
//low/high watermark
static ssize_t
-qeth_dev_state_show(struct device *dev, char *buf)
+qeth_dev_state_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
if (!card)
@@ -58,7 +58,7 @@ qeth_dev_state_show(struct device *dev, char *buf)
static DEVICE_ATTR(state, 0444, qeth_dev_state_show, NULL);
static ssize_t
-qeth_dev_chpid_show(struct device *dev, char *buf)
+qeth_dev_chpid_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
if (!card)
@@ -70,7 +70,7 @@ qeth_dev_chpid_show(struct device *dev, char *buf)
static DEVICE_ATTR(chpid, 0444, qeth_dev_chpid_show, NULL);
static ssize_t
-qeth_dev_if_name_show(struct device *dev, char *buf)
+qeth_dev_if_name_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
if (!card)
@@ -81,7 +81,7 @@ qeth_dev_if_name_show(struct device *dev, char *buf)
static DEVICE_ATTR(if_name, 0444, qeth_dev_if_name_show, NULL);
static ssize_t
-qeth_dev_card_type_show(struct device *dev, char *buf)
+qeth_dev_card_type_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
if (!card)
@@ -93,7 +93,7 @@ qeth_dev_card_type_show(struct device *dev, char *buf)
static DEVICE_ATTR(card_type, 0444, qeth_dev_card_type_show, NULL);
static ssize_t
-qeth_dev_portno_show(struct device *dev, char *buf)
+qeth_dev_portno_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
if (!card)
@@ -103,7 +103,7 @@ qeth_dev_portno_show(struct device *dev, char *buf)
}
static ssize_t
-qeth_dev_portno_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_portno_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
char *tmp;
@@ -129,7 +129,7 @@ qeth_dev_portno_store(struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(portno, 0644, qeth_dev_portno_show, qeth_dev_portno_store);
static ssize_t
-qeth_dev_portname_show(struct device *dev, char *buf)
+qeth_dev_portname_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
char portname[9] = {0, };
@@ -146,7 +146,7 @@ qeth_dev_portname_show(struct device *dev, char *buf)
}
static ssize_t
-qeth_dev_portname_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_portname_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
char *tmp;
@@ -177,7 +177,7 @@ static DEVICE_ATTR(portname, 0644, qeth_dev_portname_show,
qeth_dev_portname_store);
static ssize_t
-qeth_dev_checksum_show(struct device *dev, char *buf)
+qeth_dev_checksum_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
@@ -188,7 +188,7 @@ qeth_dev_checksum_show(struct device *dev, char *buf)
}
static ssize_t
-qeth_dev_checksum_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_checksum_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
char *tmp;
@@ -218,7 +218,7 @@ static DEVICE_ATTR(checksumming, 0644, qeth_dev_checksum_show,
qeth_dev_checksum_store);
static ssize_t
-qeth_dev_prioqing_show(struct device *dev, char *buf)
+qeth_dev_prioqing_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
@@ -237,7 +237,7 @@ qeth_dev_prioqing_show(struct device *dev, char *buf)
}
static ssize_t
-qeth_dev_prioqing_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_prioqing_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
char *tmp;
@@ -290,7 +290,7 @@ static DEVICE_ATTR(priority_queueing, 0644, qeth_dev_prioqing_show,
qeth_dev_prioqing_store);
static ssize_t
-qeth_dev_bufcnt_show(struct device *dev, char *buf)
+qeth_dev_bufcnt_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
@@ -301,7 +301,7 @@ qeth_dev_bufcnt_show(struct device *dev, char *buf)
}
static ssize_t
-qeth_dev_bufcnt_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_bufcnt_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
char *tmp;
@@ -360,7 +360,7 @@ qeth_dev_route_show(struct qeth_card *card, struct qeth_routing_info *route,
}
static ssize_t
-qeth_dev_route4_show(struct device *dev, char *buf)
+qeth_dev_route4_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
@@ -410,7 +410,7 @@ qeth_dev_route_store(struct qeth_card *card, struct qeth_routing_info *route,
}
static ssize_t
-qeth_dev_route4_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_route4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
@@ -425,7 +425,7 @@ static DEVICE_ATTR(route4, 0644, qeth_dev_route4_show, qeth_dev_route4_store);
#ifdef CONFIG_QETH_IPV6
static ssize_t
-qeth_dev_route6_show(struct device *dev, char *buf)
+qeth_dev_route6_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
@@ -439,7 +439,7 @@ qeth_dev_route6_show(struct device *dev, char *buf)
}
static ssize_t
-qeth_dev_route6_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_route6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
@@ -461,7 +461,7 @@ static DEVICE_ATTR(route6, 0644, qeth_dev_route6_show, qeth_dev_route6_store);
#endif
static ssize_t
-qeth_dev_add_hhlen_show(struct device *dev, char *buf)
+qeth_dev_add_hhlen_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
@@ -472,7 +472,7 @@ qeth_dev_add_hhlen_show(struct device *dev, char *buf)
}
static ssize_t
-qeth_dev_add_hhlen_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_add_hhlen_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
char *tmp;
@@ -499,7 +499,7 @@ static DEVICE_ATTR(add_hhlen, 0644, qeth_dev_add_hhlen_show,
qeth_dev_add_hhlen_store);
static ssize_t
-qeth_dev_fake_ll_show(struct device *dev, char *buf)
+qeth_dev_fake_ll_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
@@ -510,7 +510,7 @@ qeth_dev_fake_ll_show(struct device *dev, char *buf)
}
static ssize_t
-qeth_dev_fake_ll_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_fake_ll_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
char *tmp;
@@ -536,7 +536,7 @@ static DEVICE_ATTR(fake_ll, 0644, qeth_dev_fake_ll_show,
qeth_dev_fake_ll_store);
static ssize_t
-qeth_dev_fake_broadcast_show(struct device *dev, char *buf)
+qeth_dev_fake_broadcast_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
@@ -547,7 +547,7 @@ qeth_dev_fake_broadcast_show(struct device *dev, char *buf)
}
static ssize_t
-qeth_dev_fake_broadcast_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_fake_broadcast_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
char *tmp;
@@ -574,7 +574,7 @@ static DEVICE_ATTR(fake_broadcast, 0644, qeth_dev_fake_broadcast_show,
qeth_dev_fake_broadcast_store);
static ssize_t
-qeth_dev_recover_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_recover_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
char *tmp;
@@ -596,7 +596,7 @@ qeth_dev_recover_store(struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(recover, 0200, NULL, qeth_dev_recover_store);
static ssize_t
-qeth_dev_broadcast_mode_show(struct device *dev, char *buf)
+qeth_dev_broadcast_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
@@ -613,7 +613,7 @@ qeth_dev_broadcast_mode_show(struct device *dev, char *buf)
}
static ssize_t
-qeth_dev_broadcast_mode_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_broadcast_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
char *tmp;
@@ -651,7 +651,7 @@ static DEVICE_ATTR(broadcast_mode, 0644, qeth_dev_broadcast_mode_show,
qeth_dev_broadcast_mode_store);
static ssize_t
-qeth_dev_canonical_macaddr_show(struct device *dev, char *buf)
+qeth_dev_canonical_macaddr_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
@@ -667,7 +667,7 @@ qeth_dev_canonical_macaddr_show(struct device *dev, char *buf)
}
static ssize_t
-qeth_dev_canonical_macaddr_store(struct device *dev, const char *buf,
+qeth_dev_canonical_macaddr_store(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
struct qeth_card *card = dev->driver_data;
@@ -703,7 +703,7 @@ static DEVICE_ATTR(canonical_macaddr, 0644, qeth_dev_canonical_macaddr_show,
qeth_dev_canonical_macaddr_store);
static ssize_t
-qeth_dev_layer2_show(struct device *dev, char *buf)
+qeth_dev_layer2_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
@@ -714,7 +714,7 @@ qeth_dev_layer2_show(struct device *dev, char *buf)
}
static ssize_t
-qeth_dev_layer2_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_layer2_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
char *tmp;
@@ -742,7 +742,7 @@ static DEVICE_ATTR(layer2, 0644, qeth_dev_layer2_show,
qeth_dev_layer2_store);
static ssize_t
-qeth_dev_large_send_show(struct device *dev, char *buf)
+qeth_dev_large_send_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
@@ -762,7 +762,7 @@ qeth_dev_large_send_show(struct device *dev, char *buf)
}
static ssize_t
-qeth_dev_large_send_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
enum qeth_large_send_types type;
@@ -832,7 +832,7 @@ qeth_dev_blkt_store(struct qeth_card *card, const char *buf, size_t count,
}
static ssize_t
-qeth_dev_blkt_total_show(struct device *dev, char *buf)
+qeth_dev_blkt_total_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
@@ -841,7 +841,7 @@ qeth_dev_blkt_total_show(struct device *dev, char *buf)
static ssize_t
-qeth_dev_blkt_total_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_blkt_total_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
@@ -855,7 +855,7 @@ static DEVICE_ATTR(total, 0644, qeth_dev_blkt_total_show,
qeth_dev_blkt_total_store);
static ssize_t
-qeth_dev_blkt_inter_show(struct device *dev, char *buf)
+qeth_dev_blkt_inter_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
@@ -864,7 +864,7 @@ qeth_dev_blkt_inter_show(struct device *dev, char *buf)
static ssize_t
-qeth_dev_blkt_inter_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_blkt_inter_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
@@ -876,7 +876,7 @@ static DEVICE_ATTR(inter, 0644, qeth_dev_blkt_inter_show,
qeth_dev_blkt_inter_store);
static ssize_t
-qeth_dev_blkt_inter_jumbo_show(struct device *dev, char *buf)
+qeth_dev_blkt_inter_jumbo_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
@@ -886,7 +886,7 @@ qeth_dev_blkt_inter_jumbo_show(struct device *dev, char *buf)
static ssize_t
-qeth_dev_blkt_inter_jumbo_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_blkt_inter_jumbo_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
@@ -956,7 +956,7 @@ qeth_check_layer2(struct qeth_card *card)
static ssize_t
-qeth_dev_ipato_enable_show(struct device *dev, char *buf)
+qeth_dev_ipato_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
@@ -969,7 +969,7 @@ qeth_dev_ipato_enable_show(struct device *dev, char *buf)
}
static ssize_t
-qeth_dev_ipato_enable_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_ipato_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
char *tmp;
@@ -1004,7 +1004,7 @@ static QETH_DEVICE_ATTR(ipato_enable, enable, 0644,
qeth_dev_ipato_enable_store);
static ssize_t
-qeth_dev_ipato_invert4_show(struct device *dev, char *buf)
+qeth_dev_ipato_invert4_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
@@ -1018,7 +1018,7 @@ qeth_dev_ipato_invert4_show(struct device *dev, char *buf)
}
static ssize_t
-qeth_dev_ipato_invert4_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_ipato_invert4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
char *tmp;
@@ -1084,7 +1084,7 @@ qeth_dev_ipato_add_show(char *buf, struct qeth_card *card,
}
static ssize_t
-qeth_dev_ipato_add4_show(struct device *dev, char *buf)
+qeth_dev_ipato_add4_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
@@ -1153,7 +1153,7 @@ qeth_dev_ipato_add_store(const char *buf, size_t count,
}
static ssize_t
-qeth_dev_ipato_add4_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_ipato_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
@@ -1186,7 +1186,7 @@ qeth_dev_ipato_del_store(const char *buf, size_t count,
}
static ssize_t
-qeth_dev_ipato_del4_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_ipato_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
@@ -1201,7 +1201,7 @@ static QETH_DEVICE_ATTR(ipato_del4, del4, 0200, NULL,
#ifdef CONFIG_QETH_IPV6
static ssize_t
-qeth_dev_ipato_invert6_show(struct device *dev, char *buf)
+qeth_dev_ipato_invert6_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
@@ -1215,7 +1215,7 @@ qeth_dev_ipato_invert6_show(struct device *dev, char *buf)
}
static ssize_t
-qeth_dev_ipato_invert6_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_ipato_invert6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
char *tmp;
@@ -1247,7 +1247,7 @@ static QETH_DEVICE_ATTR(ipato_invert6, invert6, 0644,
static ssize_t
-qeth_dev_ipato_add6_show(struct device *dev, char *buf)
+qeth_dev_ipato_add6_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
@@ -1258,7 +1258,7 @@ qeth_dev_ipato_add6_show(struct device *dev, char *buf)
}
static ssize_t
-qeth_dev_ipato_add6_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_ipato_add6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
@@ -1273,7 +1273,7 @@ static QETH_DEVICE_ATTR(ipato_add6, add6, 0644,
qeth_dev_ipato_add6_store);
static ssize_t
-qeth_dev_ipato_del6_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_ipato_del6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
@@ -1341,7 +1341,7 @@ qeth_dev_vipa_add_show(char *buf, struct qeth_card *card,
}
static ssize_t
-qeth_dev_vipa_add4_show(struct device *dev, char *buf)
+qeth_dev_vipa_add4_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
@@ -1381,7 +1381,7 @@ qeth_dev_vipa_add_store(const char *buf, size_t count,
}
static ssize_t
-qeth_dev_vipa_add4_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_vipa_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
@@ -1413,7 +1413,7 @@ qeth_dev_vipa_del_store(const char *buf, size_t count,
}
static ssize_t
-qeth_dev_vipa_del4_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_vipa_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
@@ -1428,7 +1428,7 @@ static QETH_DEVICE_ATTR(vipa_del4, del4, 0200, NULL,
#ifdef CONFIG_QETH_IPV6
static ssize_t
-qeth_dev_vipa_add6_show(struct device *dev, char *buf)
+qeth_dev_vipa_add6_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
@@ -1439,7 +1439,7 @@ qeth_dev_vipa_add6_show(struct device *dev, char *buf)
}
static ssize_t
-qeth_dev_vipa_add6_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_vipa_add6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
@@ -1454,7 +1454,7 @@ static QETH_DEVICE_ATTR(vipa_add6, add6, 0644,
qeth_dev_vipa_add6_store);
static ssize_t
-qeth_dev_vipa_del6_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_vipa_del6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
@@ -1522,7 +1522,7 @@ qeth_dev_rxip_add_show(char *buf, struct qeth_card *card,
}
static ssize_t
-qeth_dev_rxip_add4_show(struct device *dev, char *buf)
+qeth_dev_rxip_add4_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
@@ -1562,7 +1562,7 @@ qeth_dev_rxip_add_store(const char *buf, size_t count,
}
static ssize_t
-qeth_dev_rxip_add4_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_rxip_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
@@ -1594,7 +1594,7 @@ qeth_dev_rxip_del_store(const char *buf, size_t count,
}
static ssize_t
-qeth_dev_rxip_del4_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_rxip_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
@@ -1609,7 +1609,7 @@ static QETH_DEVICE_ATTR(rxip_del4, del4, 0200, NULL,
#ifdef CONFIG_QETH_IPV6
static ssize_t
-qeth_dev_rxip_add6_show(struct device *dev, char *buf)
+qeth_dev_rxip_add6_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct qeth_card *card = dev->driver_data;
@@ -1620,7 +1620,7 @@ qeth_dev_rxip_add6_show(struct device *dev, char *buf)
}
static ssize_t
-qeth_dev_rxip_add6_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_rxip_add6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
@@ -1635,7 +1635,7 @@ static QETH_DEVICE_ATTR(rxip_add6, add6, 0644,
qeth_dev_rxip_add6_store);
static ssize_t
-qeth_dev_rxip_del6_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_rxip_del6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct qeth_card *card = dev->driver_data;
diff --git a/drivers/s390/net/qeth_tso.c b/drivers/s390/net/qeth_tso.c
deleted file mode 100644
index c91976274e7..00000000000
--- a/drivers/s390/net/qeth_tso.c
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * linux/drivers/s390/net/qeth_tso.c ($Revision: 1.6 $)
- *
- * Header file for qeth TCP Segmentation Offload support.
- *
- * Copyright 2004 IBM Corporation
- *
- * Author(s): Frank Pavlic <pavlic@de.ibm.com>
- *
- * $Revision: 1.6 $ $Date: 2005/03/24 09:04:18 $
- *
- */
-
-#include <linux/skbuff.h>
-#include <linux/tcp.h>
-#include <linux/ip.h>
-#include <linux/ipv6.h>
-#include <net/ip6_checksum.h>
-#include "qeth.h"
-#include "qeth_mpc.h"
-#include "qeth_tso.h"
-
-/**
- * skb already partially prepared
- * classic qdio header in skb->data
- * */
-static inline struct qeth_hdr_tso *
-qeth_tso_prepare_skb(struct qeth_card *card, struct sk_buff **skb)
-{
- int rc = 0;
-
- QETH_DBF_TEXT(trace, 5, "tsoprsk");
- rc = qeth_realloc_headroom(card, skb,sizeof(struct qeth_hdr_ext_tso));
- if (rc)
- return NULL;
-
- return qeth_push_skb(card, skb, sizeof(struct qeth_hdr_ext_tso));
-}
-
-/**
- * fill header for a TSO packet
- */
-static inline void
-qeth_tso_fill_header(struct qeth_card *card, struct sk_buff *skb)
-{
- struct qeth_hdr_tso *hdr;
- struct tcphdr *tcph;
- struct iphdr *iph;
-
- QETH_DBF_TEXT(trace, 5, "tsofhdr");
-
- hdr = (struct qeth_hdr_tso *) skb->data;
- iph = skb->nh.iph;
- tcph = skb->h.th;
- /*fix header to TSO values ...*/
- hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO;
- /*set values which are fix for the first approach ...*/
- hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso);
- hdr->ext.imb_hdr_no = 1;
- hdr->ext.hdr_type = 1;
- hdr->ext.hdr_version = 1;
- hdr->ext.hdr_len = 28;
- /*insert non-fix values */
- hdr->ext.mss = skb_shinfo(skb)->tso_size;
- hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4);
- hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len -
- sizeof(struct qeth_hdr_tso));
-}
-
-/**
- * change some header values as requested by hardware
- */
-static inline void
-qeth_tso_set_tcpip_header(struct qeth_card *card, struct sk_buff *skb)
-{
- struct iphdr *iph;
- struct ipv6hdr *ip6h;
- struct tcphdr *tcph;
-
- iph = skb->nh.iph;
- ip6h = skb->nh.ipv6h;
- tcph = skb->h.th;
-
- tcph->check = 0;
- if (skb->protocol == ETH_P_IPV6) {
- ip6h->payload_len = 0;
- tcph->check = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
- 0, IPPROTO_TCP, 0);
- return;
- }
- /*OSA want us to set these values ...*/
- tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
- 0, IPPROTO_TCP, 0);
- iph->tot_len = 0;
- iph->check = 0;
-}
-
-static inline struct qeth_hdr_tso *
-qeth_tso_prepare_packet(struct qeth_card *card, struct sk_buff *skb,
- int ipv, int cast_type)
-{
- struct qeth_hdr_tso *hdr;
- int rc = 0;
-
- QETH_DBF_TEXT(trace, 5, "tsoprep");
-
- /*get headroom for tso qdio header */
- hdr = (struct qeth_hdr_tso *) qeth_tso_prepare_skb(card, &skb);
- if (hdr == NULL) {
- QETH_DBF_TEXT_(trace, 4, "2err%d", rc);
- return NULL;
- }
- memset(hdr, 0, sizeof(struct qeth_hdr_tso));
- /*fill first 32 bytes of qdio header as used
- *FIXME: TSO has two struct members
- * with different names but same size
- * */
- qeth_fill_header(card, &hdr->hdr, skb, ipv, cast_type);
- qeth_tso_fill_header(card, skb);
- qeth_tso_set_tcpip_header(card, skb);
- return hdr;
-}
-
-static inline int
-qeth_tso_get_queue_buffer(struct qeth_qdio_out_q *queue)
-{
- struct qeth_qdio_out_buffer *buffer;
- int flush_cnt = 0;
-
- QETH_DBF_TEXT(trace, 5, "tsobuf");
-
- /* force to non-packing*/
- if (queue->do_pack)
- queue->do_pack = 0;
- buffer = &queue->bufs[queue->next_buf_to_fill];
- /* get a new buffer if current is already in use*/
- if ((atomic_read(&buffer->state) == QETH_QDIO_BUF_EMPTY) &&
- (buffer->next_element_to_fill > 0)) {
- atomic_set(&buffer->state, QETH_QDIO_BUF_PRIMED);
- queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) %
- QDIO_MAX_BUFFERS_PER_Q;
- flush_cnt++;
- }
- return flush_cnt;
-}
-
-static inline void
-__qeth_tso_fill_buffer_frag(struct qeth_qdio_out_buffer *buf,
- struct sk_buff *skb)
-{
- struct skb_frag_struct *frag;
- struct qdio_buffer *buffer;
- int fragno, cnt, element;
- unsigned long addr;
-
- QETH_DBF_TEXT(trace, 6, "tsfilfrg");
-
- /*initialize variables ...*/
- fragno = skb_shinfo(skb)->nr_frags;
- buffer = buf->buffer;
- element = buf->next_element_to_fill;
- /*fill buffer elements .....*/
- for (cnt = 0; cnt < fragno; cnt++) {
- frag = &skb_shinfo(skb)->frags[cnt];
- addr = (page_to_pfn(frag->page) << PAGE_SHIFT) +
- frag->page_offset;
- buffer->element[element].addr = (char *)addr;
- buffer->element[element].length = frag->size;
- if (cnt < (fragno - 1))
- buffer->element[element].flags =
- SBAL_FLAGS_MIDDLE_FRAG;
- else
- buffer->element[element].flags =
- SBAL_FLAGS_LAST_FRAG;
- element++;
- }
- buf->next_element_to_fill = element;
-}
-
-static inline int
-qeth_tso_fill_buffer(struct qeth_qdio_out_buffer *buf,
- struct sk_buff *skb)
-{
- int length, length_here, element;
- int hdr_len;
- struct qdio_buffer *buffer;
- struct qeth_hdr_tso *hdr;
- char *data;
-
- QETH_DBF_TEXT(trace, 3, "tsfilbuf");
-
- /*increment user count and queue skb ...*/
- atomic_inc(&skb->users);
- skb_queue_tail(&buf->skb_list, skb);
-
- /*initialize all variables...*/
- buffer = buf->buffer;
- hdr = (struct qeth_hdr_tso *)skb->data;
- hdr_len = sizeof(struct qeth_hdr_tso) + hdr->ext.dg_hdr_len;
- data = skb->data + hdr_len;
- length = skb->len - hdr_len;
- element = buf->next_element_to_fill;
- /*fill first buffer entry only with header information */
- buffer->element[element].addr = skb->data;
- buffer->element[element].length = hdr_len;
- buffer->element[element].flags = SBAL_FLAGS_FIRST_FRAG;
- buf->next_element_to_fill++;
-
- if (skb_shinfo(skb)->nr_frags > 0) {
- __qeth_tso_fill_buffer_frag(buf, skb);
- goto out;
- }
-
- /*start filling buffer entries ...*/
- element++;
- while (length > 0) {
- /* length_here is the remaining amount of data in this page */
- length_here = PAGE_SIZE - ((unsigned long) data % PAGE_SIZE);
- if (length < length_here)
- length_here = length;
- buffer->element[element].addr = data;
- buffer->element[element].length = length_here;
- length -= length_here;
- if (!length)
- buffer->element[element].flags =
- SBAL_FLAGS_LAST_FRAG;
- else
- buffer->element[element].flags =
- SBAL_FLAGS_MIDDLE_FRAG;
- data += length_here;
- element++;
- }
- /*set the buffer to primed ...*/
- buf->next_element_to_fill = element;
-out:
- atomic_set(&buf->state, QETH_QDIO_BUF_PRIMED);
- return 1;
-}
-
-int
-qeth_tso_send_packet(struct qeth_card *card, struct sk_buff *skb,
- struct qeth_qdio_out_q *queue, int ipv, int cast_type)
-{
- int flush_cnt = 0;
- struct qeth_hdr_tso *hdr;
- struct qeth_qdio_out_buffer *buffer;
- int start_index;
-
- QETH_DBF_TEXT(trace, 3, "tsosend");
-
- if (!(hdr = qeth_tso_prepare_packet(card, skb, ipv, cast_type)))
- return -ENOMEM;
- /*check if skb fits in one SBAL ...*/
- if (!(qeth_get_elements_no(card, (void*)hdr, skb)))
- return -EINVAL;
- /*lock queue, force switching to non-packing and send it ...*/
- while (atomic_compare_and_swap(QETH_OUT_Q_UNLOCKED,
- QETH_OUT_Q_LOCKED,
- &queue->state));
- start_index = queue->next_buf_to_fill;
- buffer = &queue->bufs[queue->next_buf_to_fill];
- /*check if card is too busy ...*/
- if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY){
- card->stats.tx_dropped++;
- goto out;
- }
- /*let's force to non-packing and get a new SBAL*/
- flush_cnt += qeth_tso_get_queue_buffer(queue);
- buffer = &queue->bufs[queue->next_buf_to_fill];
- if (atomic_read(&buffer->state) != QETH_QDIO_BUF_EMPTY) {
- card->stats.tx_dropped++;
- goto out;
- }
- flush_cnt += qeth_tso_fill_buffer(buffer, skb);
- queue->next_buf_to_fill = (queue->next_buf_to_fill + 1) %
- QDIO_MAX_BUFFERS_PER_Q;
-out:
- atomic_set(&queue->state, QETH_OUT_Q_UNLOCKED);
- if (flush_cnt)
- qeth_flush_buffers(queue, 0, start_index, flush_cnt);
- /*do some statistics */
- card->stats.tx_packets++;
- card->stats.tx_bytes += skb->len;
- return 0;
-}
diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h
index 83504dee3f5..ad33e6f466f 100644
--- a/drivers/s390/net/qeth_tso.h
+++ b/drivers/s390/net/qeth_tso.h
@@ -1,5 +1,5 @@
/*
- * linux/drivers/s390/net/qeth_tso.h ($Revision: 1.4 $)
+ * linux/drivers/s390/net/qeth_tso.h ($Revision: 1.7 $)
*
* Header file for qeth TCP Segmentation Offload support.
*
@@ -7,52 +7,148 @@
*
* Author(s): Frank Pavlic <pavlic@de.ibm.com>
*
- * $Revision: 1.4 $ $Date: 2005/03/24 09:04:18 $
+ * $Revision: 1.7 $ $Date: 2005/05/04 20:19:18 $
*
*/
#ifndef __QETH_TSO_H__
#define __QETH_TSO_H__
+#include <linux/skbuff.h>
+#include <linux/tcp.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <net/ip6_checksum.h>
+#include "qeth.h"
+#include "qeth_mpc.h"
-extern int
-qeth_tso_send_packet(struct qeth_card *, struct sk_buff *,
- struct qeth_qdio_out_q *, int , int);
-struct qeth_hdr_ext_tso {
- __u16 hdr_tot_len;
- __u8 imb_hdr_no;
- __u8 reserved;
- __u8 hdr_type;
- __u8 hdr_version;
- __u16 hdr_len;
- __u32 payload_len;
- __u16 mss;
- __u16 dg_hdr_len;
- __u8 padding[16];
-} __attribute__ ((packed));
+static inline struct qeth_hdr_tso *
+qeth_tso_prepare_skb(struct qeth_card *card, struct sk_buff **skb)
+{
+ QETH_DBF_TEXT(trace, 5, "tsoprsk");
+ return qeth_push_skb(card, skb, sizeof(struct qeth_hdr_tso));
+}
+
+/**
+ * fill header for a TSO packet
+ */
+static inline void
+qeth_tso_fill_header(struct qeth_card *card, struct sk_buff *skb)
+{
+ struct qeth_hdr_tso *hdr;
+ struct tcphdr *tcph;
+ struct iphdr *iph;
+
+ QETH_DBF_TEXT(trace, 5, "tsofhdr");
+
+ hdr = (struct qeth_hdr_tso *) skb->data;
+ iph = skb->nh.iph;
+ tcph = skb->h.th;
+ /*fix header to TSO values ...*/
+ hdr->hdr.hdr.l3.id = QETH_HEADER_TYPE_TSO;
+ /*set values which are fix for the first approach ...*/
+ hdr->ext.hdr_tot_len = (__u16) sizeof(struct qeth_hdr_ext_tso);
+ hdr->ext.imb_hdr_no = 1;
+ hdr->ext.hdr_type = 1;
+ hdr->ext.hdr_version = 1;
+ hdr->ext.hdr_len = 28;
+ /*insert non-fix values */
+ hdr->ext.mss = skb_shinfo(skb)->tso_size;
+ hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4);
+ hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len -
+ sizeof(struct qeth_hdr_tso));
+}
+
+/**
+ * change some header values as requested by hardware
+ */
+static inline void
+qeth_tso_set_tcpip_header(struct qeth_card *card, struct sk_buff *skb)
+{
+ struct iphdr *iph;
+ struct ipv6hdr *ip6h;
+ struct tcphdr *tcph;
-struct qeth_hdr_tso {
- struct qeth_hdr hdr; /*hdr->hdr.l3.xxx*/
- struct qeth_hdr_ext_tso ext;
-} __attribute__ ((packed));
+ iph = skb->nh.iph;
+ ip6h = skb->nh.ipv6h;
+ tcph = skb->h.th;
-/*some helper functions*/
+ tcph->check = 0;
+ if (skb->protocol == ETH_P_IPV6) {
+ ip6h->payload_len = 0;
+ tcph->check = ~csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
+ 0, IPPROTO_TCP, 0);
+ return;
+ }
+ /*OSA want us to set these values ...*/
+ tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
+ 0, IPPROTO_TCP, 0);
+ iph->tot_len = 0;
+ iph->check = 0;
+}
static inline int
-qeth_get_elements_no(struct qeth_card *card, void *hdr, struct sk_buff *skb)
+qeth_tso_prepare_packet(struct qeth_card *card, struct sk_buff *skb,
+ int ipv, int cast_type)
+{
+ struct qeth_hdr_tso *hdr;
+
+ QETH_DBF_TEXT(trace, 5, "tsoprep");
+
+ hdr = (struct qeth_hdr_tso *) qeth_tso_prepare_skb(card, &skb);
+ if (hdr == NULL) {
+ QETH_DBF_TEXT(trace, 4, "tsoperr");
+ return -ENOMEM;
+ }
+ memset(hdr, 0, sizeof(struct qeth_hdr_tso));
+ /*fill first 32 bytes of qdio header as used
+ *FIXME: TSO has two struct members
+ * with different names but same size
+ * */
+ qeth_fill_header(card, &hdr->hdr, skb, ipv, cast_type);
+ qeth_tso_fill_header(card, skb);
+ qeth_tso_set_tcpip_header(card, skb);
+ return 0;
+}
+
+static inline void
+__qeth_fill_buffer_frag(struct sk_buff *skb, struct qdio_buffer *buffer,
+ int is_tso, int *next_element_to_fill)
{
- int elements_needed = 0;
-
- if (skb_shinfo(skb)->nr_frags > 0)
- elements_needed = (skb_shinfo(skb)->nr_frags + 1);
- if (elements_needed == 0 )
- elements_needed = 1 + (((((unsigned long) hdr) % PAGE_SIZE)
- + skb->len) >> PAGE_SHIFT);
- if (elements_needed > QETH_MAX_BUFFER_ELEMENTS(card)){
- PRINT_ERR("qeth_do_send_packet: invalid size of "
- "IP packet. Discarded.");
- return 0;
+ struct skb_frag_struct *frag;
+ int fragno;
+ unsigned long addr;
+ int element, cnt, dlen;
+
+ fragno = skb_shinfo(skb)->nr_frags;
+ element = *next_element_to_fill;
+ dlen = 0;
+
+ if (is_tso)
+ buffer->element[element].flags =
+ SBAL_FLAGS_MIDDLE_FRAG;
+ else
+ buffer->element[element].flags =
+ SBAL_FLAGS_FIRST_FRAG;
+ if ( (dlen = (skb->len - skb->data_len)) ) {
+ buffer->element[element].addr = skb->data;
+ buffer->element[element].length = dlen;
+ element++;
+ }
+ for (cnt = 0; cnt < fragno; cnt++) {
+ frag = &skb_shinfo(skb)->frags[cnt];
+ addr = (page_to_pfn(frag->page) << PAGE_SHIFT) +
+ frag->page_offset;
+ buffer->element[element].addr = (char *)addr;
+ buffer->element[element].length = frag->size;
+ if (cnt < (fragno - 1))
+ buffer->element[element].flags =
+ SBAL_FLAGS_MIDDLE_FRAG;
+ else
+ buffer->element[element].flags =
+ SBAL_FLAGS_LAST_FRAG;
+ element++;
}
- return elements_needed;
+ *next_element_to_fill = element;
}
#endif /* __QETH_TSO_H__ */
diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c
index 1e3f7f3c662..d6469baa7e1 100644
--- a/drivers/s390/net/smsgiucv.c
+++ b/drivers/s390/net/smsgiucv.c
@@ -138,7 +138,7 @@ static void __exit
smsg_exit(void)
{
if (smsg_handle > 0) {
- cpcmd("SET SMSG OFF", 0, 0);
+ cpcmd("SET SMSG OFF", NULL, 0, NULL);
iucv_sever(smsg_pathid, 0);
iucv_unregister_program(smsg_handle);
driver_unregister(&smsg_driver);
@@ -177,7 +177,7 @@ smsg_init(void)
smsg_handle = 0;
return -EIO;
}
- cpcmd("SET SMSG IUCV", 0, 0);
+ cpcmd("SET SMSG IUCV", NULL, 0, NULL);
return 0;
}
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
index ffa996c8a90..5bb255e02ac 100644
--- a/drivers/s390/s390mach.c
+++ b/drivers/s390/s390mach.c
@@ -31,14 +31,14 @@ extern void css_reiterate_subchannels(void);
extern struct workqueue_struct *slow_path_wq;
extern struct work_struct slow_path_work;
-static void
+static NORET_TYPE void
s390_handle_damage(char *msg)
{
- printk(KERN_EMERG "%s\n", msg);
#ifdef CONFIG_SMP
smp_send_stop();
#endif
disabled_wait((unsigned long) __builtin_return_address(0));
+ for(;;);
}
/*
@@ -122,40 +122,39 @@ repeat:
return 0;
}
+struct mcck_struct {
+ int kill_task;
+ int channel_report;
+ int warning;
+ unsigned long long mcck_code;
+};
+
+static DEFINE_PER_CPU(struct mcck_struct, cpu_mcck);
+
/*
- * machine check handler.
+ * Main machine check handler function. Will be called with interrupts enabled
+ * or disabled and machine checks enabled or disabled.
*/
void
-s390_do_machine_check(void)
+s390_handle_mcck(void)
{
- struct mci *mci;
-
- mci = (struct mci *) &S390_lowcore.mcck_interruption_code;
+ unsigned long flags;
+ struct mcck_struct mcck;
- if (mci->sd) /* system damage */
- s390_handle_damage("received system damage machine check\n");
+ /*
+ * Disable machine checks and get the current state of accumulated
+ * machine checks. Afterwards delete the old state and enable machine
+ * checks again.
+ */
+ local_irq_save(flags);
+ local_mcck_disable();
+ mcck = __get_cpu_var(cpu_mcck);
+ memset(&__get_cpu_var(cpu_mcck), 0, sizeof(struct mcck_struct));
+ clear_thread_flag(TIF_MCCK_PENDING);
+ local_mcck_enable();
+ local_irq_restore(flags);
- if (mci->pd) /* instruction processing damage */
- s390_handle_damage("received instruction processing "
- "damage machine check\n");
-
- if (mci->se) /* storage error uncorrected */
- s390_handle_damage("received storage error uncorrected "
- "machine check\n");
-
- if (mci->sc) /* storage error corrected */
- printk(KERN_WARNING
- "received storage error corrected machine check\n");
-
- if (mci->ke) /* storage key-error uncorrected */
- s390_handle_damage("received storage key-error uncorrected "
- "machine check\n");
-
- if (mci->ds && mci->fa) /* storage degradation */
- s390_handle_damage("received storage degradation machine "
- "check\n");
-
- if (mci->cp) /* channel report word pending */
+ if (mcck.channel_report)
up(&m_sem);
#ifdef CONFIG_MACHCHK_WARNING
@@ -168,7 +167,7 @@ s390_do_machine_check(void)
* On VM we only get one interrupt per virtally presented machinecheck.
* Though one suffices, we may get one interrupt per (virtual) processor.
*/
- if (mci->w) { /* WARNING pending ? */
+ if (mcck.warning) { /* WARNING pending ? */
static int mchchk_wng_posted = 0;
/*
* Use single machine clear, as we cannot handle smp right now
@@ -178,6 +177,261 @@ s390_do_machine_check(void)
kill_proc(1, SIGPWR, 1);
}
#endif
+
+ if (mcck.kill_task) {
+ local_irq_enable();
+ printk(KERN_EMERG "mcck: Terminating task because of machine "
+ "malfunction (code 0x%016llx).\n", mcck.mcck_code);
+ printk(KERN_EMERG "mcck: task: %s, pid: %d.\n",
+ current->comm, current->pid);
+ do_exit(SIGSEGV);
+ }
+}
+
+/*
+ * returns 0 if all registers could be validated
+ * returns 1 otherwise
+ */
+static int
+s390_revalidate_registers(struct mci *mci)
+{
+ int kill_task;
+ u64 tmpclock;
+ u64 zero;
+ void *fpt_save_area, *fpt_creg_save_area;
+
+ kill_task = 0;
+ zero = 0;
+ /* General purpose registers */
+ if (!mci->gr)
+ /*
+ * General purpose registers couldn't be restored and have
+ * unknown contents. Process needs to be terminated.
+ */
+ kill_task = 1;
+
+ /* Revalidate floating point registers */
+ if (!mci->fp)
+ /*
+ * Floating point registers can't be restored and
+ * therefore the process needs to be terminated.
+ */
+ kill_task = 1;
+
+#ifndef __s390x__
+ asm volatile("ld 0,0(%0)\n"
+ "ld 2,8(%0)\n"
+ "ld 4,16(%0)\n"
+ "ld 6,24(%0)"
+ : : "a" (&S390_lowcore.floating_pt_save_area));
+#endif
+
+ if (MACHINE_HAS_IEEE) {
+#ifdef __s390x__
+ fpt_save_area = &S390_lowcore.floating_pt_save_area;
+ fpt_creg_save_area = &S390_lowcore.fpt_creg_save_area;
+#else
+ fpt_save_area = (void *) S390_lowcore.extended_save_area_addr;
+ fpt_creg_save_area = fpt_save_area+128;
+#endif
+ /* Floating point control register */
+ if (!mci->fc) {
+ /*
+ * Floating point control register can't be restored.
+ * Task will be terminated.
+ */
+ asm volatile ("lfpc 0(%0)" : : "a" (&zero));
+ kill_task = 1;
+
+ }
+ else
+ asm volatile (
+ "lfpc 0(%0)"
+ : : "a" (fpt_creg_save_area));
+
+ asm volatile("ld 0,0(%0)\n"
+ "ld 1,8(%0)\n"
+ "ld 2,16(%0)\n"
+ "ld 3,24(%0)\n"
+ "ld 4,32(%0)\n"
+ "ld 5,40(%0)\n"
+ "ld 6,48(%0)\n"
+ "ld 7,56(%0)\n"
+ "ld 8,64(%0)\n"
+ "ld 9,72(%0)\n"
+ "ld 10,80(%0)\n"
+ "ld 11,88(%0)\n"
+ "ld 12,96(%0)\n"
+ "ld 13,104(%0)\n"
+ "ld 14,112(%0)\n"
+ "ld 15,120(%0)\n"
+ : : "a" (fpt_save_area));
+ }
+
+ /* Revalidate access registers */
+ asm volatile("lam 0,15,0(%0)"
+ : : "a" (&S390_lowcore.access_regs_save_area));
+ if (!mci->ar)
+ /*
+ * Access registers have unknown contents.
+ * Terminating task.
+ */
+ kill_task = 1;
+
+ /* Revalidate control registers */
+ if (!mci->cr)
+ /*
+ * Control registers have unknown contents.
+ * Can't recover and therefore stopping machine.
+ */
+ s390_handle_damage("invalid control registers.");
+ else
+#ifdef __s390x__
+ asm volatile("lctlg 0,15,0(%0)"
+ : : "a" (&S390_lowcore.cregs_save_area));
+#else
+ asm volatile("lctl 0,15,0(%0)"
+ : : "a" (&S390_lowcore.cregs_save_area));
+#endif
+
+ /*
+ * We don't even try to revalidate the TOD register, since we simply
+ * can't write something sensible into that register.
+ */
+
+#ifdef __s390x__
+ /*
+ * See if we can revalidate the TOD programmable register with its
+ * old contents (should be zero) otherwise set it to zero.
+ */
+ if (!mci->pr)
+ asm volatile("sr 0,0\n"
+ "sckpf"
+ : : : "0", "cc");
+ else
+ asm volatile(
+ "l 0,0(%0)\n"
+ "sckpf"
+ : : "a" (&S390_lowcore.tod_progreg_save_area) : "0", "cc");
+#endif
+
+ /* Revalidate clock comparator register */
+ asm volatile ("stck 0(%1)\n"
+ "sckc 0(%1)"
+ : "=m" (tmpclock) : "a" (&(tmpclock)) : "cc", "memory");
+
+ /* Check if old PSW is valid */
+ if (!mci->wp)
+ /*
+ * Can't tell if we come from user or kernel mode
+ * -> stopping machine.
+ */
+ s390_handle_damage("old psw invalid.");
+
+ if (!mci->ms || !mci->pm || !mci->ia)
+ kill_task = 1;
+
+ return kill_task;
+}
+
+/*
+ * machine check handler.
+ */
+void
+s390_do_machine_check(struct pt_regs *regs)
+{
+ struct mci *mci;
+ struct mcck_struct *mcck;
+ int umode;
+
+ mci = (struct mci *) &S390_lowcore.mcck_interruption_code;
+ mcck = &__get_cpu_var(cpu_mcck);
+ umode = user_mode(regs);
+
+ if (mci->sd)
+ /* System damage -> stopping machine */
+ s390_handle_damage("received system damage machine check.");
+
+ if (mci->pd) {
+ if (mci->b) {
+ /* Processing backup -> verify if we can survive this */
+ u64 z_mcic, o_mcic, t_mcic;
+#ifdef __s390x__
+ z_mcic = (1ULL<<63 | 1ULL<<59 | 1ULL<<29);
+ o_mcic = (1ULL<<43 | 1ULL<<42 | 1ULL<<41 | 1ULL<<40 |
+ 1ULL<<36 | 1ULL<<35 | 1ULL<<34 | 1ULL<<32 |
+ 1ULL<<30 | 1ULL<<21 | 1ULL<<20 | 1ULL<<17 |
+ 1ULL<<16);
+#else
+ z_mcic = (1ULL<<63 | 1ULL<<59 | 1ULL<<57 | 1ULL<<50 |
+ 1ULL<<29);
+ o_mcic = (1ULL<<43 | 1ULL<<42 | 1ULL<<41 | 1ULL<<40 |
+ 1ULL<<36 | 1ULL<<35 | 1ULL<<34 | 1ULL<<32 |
+ 1ULL<<30 | 1ULL<<20 | 1ULL<<17 | 1ULL<<16);
+#endif
+ t_mcic = *(u64 *)mci;
+
+ if (((t_mcic & z_mcic) != 0) ||
+ ((t_mcic & o_mcic) != o_mcic)) {
+ s390_handle_damage("processing backup machine "
+ "check with damage.");
+ }
+ if (!umode)
+ s390_handle_damage("processing backup machine "
+ "check in kernel mode.");
+ mcck->kill_task = 1;
+ mcck->mcck_code = *(unsigned long long *) mci;
+ }
+ else {
+ /* Processing damage -> stopping machine */
+ s390_handle_damage("received instruction processing "
+ "damage machine check.");
+ }
+ }
+ if (s390_revalidate_registers(mci)) {
+ if (umode) {
+ /*
+ * Couldn't restore all register contents while in
+ * user mode -> mark task for termination.
+ */
+ mcck->kill_task = 1;
+ mcck->mcck_code = *(unsigned long long *) mci;
+ set_thread_flag(TIF_MCCK_PENDING);
+ }
+ else
+ /*
+ * Couldn't restore all register contents while in
+ * kernel mode -> stopping machine.
+ */
+ s390_handle_damage("unable to revalidate registers.");
+ }
+
+ if (mci->se)
+ /* Storage error uncorrected */
+ s390_handle_damage("received storage error uncorrected "
+ "machine check.");
+
+ if (mci->ke)
+ /* Storage key-error uncorrected */
+ s390_handle_damage("received storage key-error uncorrected "
+ "machine check.");
+
+ if (mci->ds && mci->fa)
+ /* Storage degradation */
+ s390_handle_damage("received storage degradation machine "
+ "check.");
+
+ if (mci->cp) {
+ /* Channel report word pending */
+ mcck->channel_report = 1;
+ set_thread_flag(TIF_MCCK_PENDING);
+ }
+
+ if (mci->w) {
+ /* Warning pending */
+ mcck->warning = 1;
+ set_thread_flag(TIF_MCCK_PENDING);
+ }
}
/*
@@ -189,9 +443,8 @@ static int
machine_check_init(void)
{
init_MUTEX_LOCKED(&m_sem);
- ctl_clear_bit(14, 25); /* disable damage MCH */
- ctl_set_bit(14, 26); /* enable degradation MCH */
- ctl_set_bit(14, 27); /* enable system recovery MCH */
+ ctl_clear_bit(14, 25); /* disable external damage MCH */
+ ctl_set_bit(14, 27); /* enable system recovery MCH */
#ifdef CONFIG_MACHCHK_WARNING
ctl_set_bit(14, 24); /* enable warning MCH */
#endif
diff --git a/drivers/s390/s390mach.h b/drivers/s390/s390mach.h
index 7e26f0f1b0d..4eaa7017918 100644
--- a/drivers/s390/s390mach.h
+++ b/drivers/s390/s390mach.h
@@ -16,20 +16,45 @@ struct mci {
__u32 sd : 1; /* 00 system damage */
__u32 pd : 1; /* 01 instruction-processing damage */
__u32 sr : 1; /* 02 system recovery */
- __u32 to_be_defined_1 : 4; /* 03-06 */
+ __u32 to_be_defined_1 : 1; /* 03 */
+ __u32 cd : 1; /* 04 timing-facility damage */
+ __u32 ed : 1; /* 05 external damage */
+ __u32 to_be_defined_2 : 1; /* 06 */
__u32 dg : 1; /* 07 degradation */
__u32 w : 1; /* 08 warning pending */
__u32 cp : 1; /* 09 channel-report pending */
- __u32 to_be_defined_2 : 6; /* 10-15 */
+ __u32 sp : 1; /* 10 service-processor damage */
+ __u32 ck : 1; /* 11 channel-subsystem damage */
+ __u32 to_be_defined_3 : 2; /* 12-13 */
+ __u32 b : 1; /* 14 backed up */
+ __u32 to_be_defined_4 : 1; /* 15 */
__u32 se : 1; /* 16 storage error uncorrected */
__u32 sc : 1; /* 17 storage error corrected */
__u32 ke : 1; /* 18 storage-key error uncorrected */
__u32 ds : 1; /* 19 storage degradation */
- __u32 to_be_defined_3 : 4; /* 20-23 */
+ __u32 wp : 1; /* 20 psw mwp validity */
+ __u32 ms : 1; /* 21 psw mask and key validity */
+ __u32 pm : 1; /* 22 psw program mask and cc validity */
+ __u32 ia : 1; /* 23 psw instruction address validity */
__u32 fa : 1; /* 24 failing storage address validity */
- __u32 to_be_defined_4 : 7; /* 25-31 */
+ __u32 to_be_defined_5 : 1; /* 25 */
+ __u32 ec : 1; /* 26 external damage code validity */
+ __u32 fp : 1; /* 27 floating point register validity */
+ __u32 gr : 1; /* 28 general register validity */
+ __u32 cr : 1; /* 29 control register validity */
+ __u32 to_be_defined_6 : 1; /* 30 */
+ __u32 st : 1; /* 31 storage logical validity */
__u32 ie : 1; /* 32 indirect storage error */
- __u32 to_be_defined_5 : 31; /* 33-63 */
+ __u32 ar : 1; /* 33 access register validity */
+ __u32 da : 1; /* 34 delayed access exception */
+ __u32 to_be_defined_7 : 7; /* 35-41 */
+ __u32 pr : 1; /* 42 tod programmable register validity */
+ __u32 fc : 1; /* 43 fp control register validity */
+ __u32 ap : 1; /* 44 ancillary report */
+ __u32 to_be_defined_8 : 1; /* 45 */
+ __u32 ct : 1; /* 46 cpu timer validity */
+ __u32 cc : 1; /* 47 clock comparator validity */
+ __u32 to_be_defined_9 : 16; /* 47-63 */
};
/*
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 68d151aaa47..e17b4d58a9f 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -97,11 +97,6 @@ MODULE_PARM_DESC(loglevel,
"FC ERP QDIO CIO Config FSF SCSI Other, "
"levels: 0=none 1=normal 2=devel 3=trace");
-#ifdef ZFCP_PRINT_FLAGS
-u32 flags_dump = 0;
-module_param(flags_dump, uint, 0);
-#endif
-
/****************************************************************/
/************** Functions without logging ***********************/
/****************************************************************/
@@ -223,13 +218,20 @@ zfcp_in_els_dbf_event(struct zfcp_adapter *adapter, const char *text,
* Parse "device=..." parameter string.
*/
static int __init
-zfcp_device_setup(char *str)
+zfcp_device_setup(char *devstr)
{
- char *tmp;
+ char *tmp, *str;
+ size_t len;
- if (!str)
+ if (!devstr)
return 0;
+ len = strlen(devstr) + 1;
+ str = (char *) kmalloc(len, GFP_KERNEL);
+ if (!str)
+ goto err_out;
+ memcpy(str, devstr, len);
+
tmp = strchr(str, ',');
if (!tmp)
goto err_out;
@@ -246,10 +248,12 @@ zfcp_device_setup(char *str)
zfcp_data.init_fcp_lun = simple_strtoull(tmp, &tmp, 0);
if (*tmp != '\0')
goto err_out;
+ kfree(str);
return 1;
err_out:
ZFCP_LOG_NORMAL("Parse error for device parameter string %s\n", str);
+ kfree(str);
return 0;
}
@@ -525,7 +529,7 @@ zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command,
out:
if (fsf_req != NULL)
- zfcp_fsf_req_cleanup(fsf_req);
+ zfcp_fsf_req_free(fsf_req);
if ((adapter != NULL) && (retval != -ENXIO))
zfcp_adapter_put(adapter);
@@ -1154,7 +1158,7 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
INIT_LIST_HEAD(&adapter->port_remove_lh);
/* initialize list of fsf requests */
- rwlock_init(&adapter->fsf_req_list_lock);
+ spin_lock_init(&adapter->fsf_req_list_lock);
INIT_LIST_HEAD(&adapter->fsf_req_list_head);
/* initialize abort lock */
@@ -1239,9 +1243,9 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev);
dev_set_drvdata(&adapter->ccw_device->dev, NULL);
/* sanity check: no pending FSF requests */
- read_lock_irqsave(&adapter->fsf_req_list_lock, flags);
+ spin_lock_irqsave(&adapter->fsf_req_list_lock, flags);
retval = !list_empty(&adapter->fsf_req_list_head);
- read_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
+ spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
if (retval) {
ZFCP_LOG_NORMAL("bug: adapter %s (%p) still in use, "
"%i requests outstanding\n",
@@ -1483,19 +1487,15 @@ zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter,
fcp_rscn_element++;
switch (fcp_rscn_element->addr_format) {
case ZFCP_PORT_ADDRESS:
- ZFCP_LOG_FLAGS(1, "ZFCP_PORT_ADDRESS\n");
range_mask = ZFCP_PORTS_RANGE_PORT;
break;
case ZFCP_AREA_ADDRESS:
- ZFCP_LOG_FLAGS(1, "ZFCP_AREA_ADDRESS\n");
range_mask = ZFCP_PORTS_RANGE_AREA;
break;
case ZFCP_DOMAIN_ADDRESS:
- ZFCP_LOG_FLAGS(1, "ZFCP_DOMAIN_ADDRESS\n");
range_mask = ZFCP_PORTS_RANGE_DOMAIN;
break;
case ZFCP_FABRIC_ADDRESS:
- ZFCP_LOG_FLAGS(1, "ZFCP_FABRIC_ADDRESS\n");
range_mask = ZFCP_PORTS_RANGE_FABRIC;
break;
default:
@@ -1762,7 +1762,10 @@ static void zfcp_ns_gid_pn_handler(unsigned long data)
ct_iu_req = zfcp_sg_to_address(ct->req);
ct_iu_resp = zfcp_sg_to_address(ct->resp);
- if ((ct->status != 0) || zfcp_check_ct_response(&ct_iu_resp->header)) {
+ if (ct->status != 0)
+ goto failed;
+
+ if (zfcp_check_ct_response(&ct_iu_resp->header)) {
/* FIXME: do we need some specific erp entry points */
atomic_set_mask(ZFCP_STATUS_PORT_INVALID_WWPN, &port->status);
goto failed;
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index c5daf372f85..4103b5be768 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -62,9 +62,6 @@
#include <linux/syscalls.h>
#include <linux/ioctl.h>
-/************************ DEBUG FLAGS *****************************************/
-
-#define ZFCP_PRINT_FLAGS
/********************* GENERAL DEFINES *********************************/
@@ -152,8 +149,10 @@ typedef u32 scsi_lun_t;
#define FSF_QTCB_UNSOLICITED_STATUS 0x6305
#define ZFCP_STATUS_READ_FAILED_THRESHOLD 3
#define ZFCP_STATUS_READS_RECOM FSF_STATUS_READS_RECOM
-#define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES 6
-#define ZFCP_EXCHANGE_CONFIG_DATA_SLEEP 50
+
+/* Do 1st retry in 1 second, then double the timeout for each following retry */
+#define ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP 100
+#define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES 7
/* timeout value for "default timer" for fsf requests */
#define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ);
@@ -472,17 +471,6 @@ do { \
ZFCP_LOG(ZFCP_LOG_LEVEL_TRACE, fmt , ##args)
#endif
-#ifndef ZFCP_PRINT_FLAGS
-# define ZFCP_LOG_FLAGS(level, fmt, args...)
-#else
-extern u32 flags_dump;
-# define ZFCP_LOG_FLAGS(level, fmt, args...) \
-do { \
- if (level <= flags_dump) \
- _ZFCP_LOG(fmt, ##args); \
-} while (0)
-#endif
-
/*************** ADAPTER/PORT/UNIT AND FSF_REQ STATUS FLAGS ******************/
/*
@@ -502,6 +490,7 @@ do { \
#define ZFCP_STATUS_COMMON_CLOSING 0x02000000
#define ZFCP_STATUS_COMMON_ERP_INUSE 0x01000000
#define ZFCP_STATUS_COMMON_ACCESS_DENIED 0x00800000
+#define ZFCP_STATUS_COMMON_ACCESS_BOXED 0x00400000
/* adapter status */
#define ZFCP_STATUS_ADAPTER_QDIOUP 0x00000002
@@ -763,6 +752,7 @@ typedef void (*zfcp_send_els_handler_t)(unsigned long);
/**
* struct zfcp_send_els - used to pass parameters to function zfcp_fsf_send_els
* @adapter: adapter where request is sent from
+ * @port: port where ELS is destinated (port reference count has to be increased)
* @d_id: destiniation id of port where request is sent to
* @req: scatter-gather list for request
* @resp: scatter-gather list for response
@@ -777,6 +767,7 @@ typedef void (*zfcp_send_els_handler_t)(unsigned long);
*/
struct zfcp_send_els {
struct zfcp_adapter *adapter;
+ struct zfcp_port *port;
fc_id_t d_id;
struct scatterlist *req;
struct scatterlist *resp;
@@ -871,7 +862,7 @@ struct zfcp_adapter {
u32 ports; /* number of remote ports */
struct timer_list scsi_er_timer; /* SCSI err recovery watch */
struct list_head fsf_req_list_head; /* head of FSF req list */
- rwlock_t fsf_req_list_lock; /* lock for ops on list of
+ spinlock_t fsf_req_list_lock; /* lock for ops on list of
FSF requests */
atomic_t fsf_reqs_active; /* # active FSF reqs */
struct zfcp_qdio_queue request_queue; /* request queue */
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 53ebc1cdfe2..0cf31f7d1c0 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -35,7 +35,7 @@
#include "zfcp_ext.h"
-static int zfcp_erp_adisc(struct zfcp_adapter *, fc_id_t);
+static int zfcp_erp_adisc(struct zfcp_port *);
static void zfcp_erp_adisc_handler(unsigned long);
static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int);
@@ -295,12 +295,12 @@ zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear_mask)
/**
* zfcp_erp_adisc - send ADISC ELS command
- * @adapter: adapter structure
- * @d_id: d_id of port where ADISC is sent to
+ * @port: port structure
*/
int
-zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id)
+zfcp_erp_adisc(struct zfcp_port *port)
{
+ struct zfcp_adapter *adapter = port->adapter;
struct zfcp_send_els *send_els;
struct zfcp_ls_adisc *adisc;
void *address = NULL;
@@ -332,7 +332,8 @@ zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id)
send_els->req_count = send_els->resp_count = 1;
send_els->adapter = adapter;
- send_els->d_id = d_id;
+ send_els->port = port;
+ send_els->d_id = port->d_id;
send_els->handler = zfcp_erp_adisc_handler;
send_els->handler_data = (unsigned long) send_els;
@@ -350,7 +351,7 @@ zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id)
ZFCP_LOG_INFO("ADISC request from s_id 0x%08x to d_id 0x%08x "
"(wwpn=0x%016Lx, wwnn=0x%016Lx, "
"hard_nport_id=0x%08x, nport_id=0x%08x)\n",
- adapter->s_id, d_id, (wwn_t) adisc->wwpn,
+ adapter->s_id, send_els->d_id, (wwn_t) adisc->wwpn,
(wwn_t) adisc->wwnn, adisc->hard_nport_id,
adisc->nport_id);
@@ -367,7 +368,7 @@ zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id)
retval = zfcp_fsf_send_els(send_els);
if (retval != 0) {
ZFCP_LOG_NORMAL("error: initiation of Send ELS failed for port "
- "0x%08x on adapter %s\n", d_id,
+ "0x%08x on adapter %s\n", send_els->d_id,
zfcp_get_busid_by_adapter(adapter));
del_timer(send_els->timer);
goto freemem;
@@ -411,14 +412,9 @@ zfcp_erp_adisc_handler(unsigned long data)
del_timer(send_els->timer);
adapter = send_els->adapter;
+ port = send_els->port;
d_id = send_els->d_id;
- read_lock(&zfcp_data.config_lock);
- port = zfcp_get_port_by_did(send_els->adapter, send_els->d_id);
- read_unlock(&zfcp_data.config_lock);
-
- BUG_ON(port == NULL);
-
/* request rejected or timed out */
if (send_els->status != 0) {
ZFCP_LOG_NORMAL("ELS request rejected/timed out, "
@@ -482,7 +478,7 @@ zfcp_test_link(struct zfcp_port *port)
int retval;
zfcp_port_get(port);
- retval = zfcp_erp_adisc(port->adapter, port->d_id);
+ retval = zfcp_erp_adisc(port);
if (retval != 0) {
zfcp_port_put(port);
ZFCP_LOG_NORMAL("reopen needed for port 0x%016Lx "
@@ -895,7 +891,7 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
if (erp_action->fsf_req) {
/* take lock to ensure that request is not being deleted meanwhile */
- write_lock(&adapter->fsf_req_list_lock);
+ spin_lock(&adapter->fsf_req_list_lock);
/* check whether fsf req does still exist */
list_for_each_entry(fsf_req, &adapter->fsf_req_list_head, list)
if (fsf_req == erp_action->fsf_req)
@@ -938,7 +934,7 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
*/
erp_action->fsf_req = NULL;
}
- write_unlock(&adapter->fsf_req_list_lock);
+ spin_unlock(&adapter->fsf_req_list_lock);
} else
debug_text_event(adapter->erp_dbf, 3, "a_ca_noreq");
@@ -2286,12 +2282,12 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
{
int retval = ZFCP_ERP_SUCCEEDED;
int retries;
+ int sleep = ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP;
struct zfcp_adapter *adapter = erp_action->adapter;
atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status);
- retries = ZFCP_EXCHANGE_CONFIG_DATA_RETRIES;
- do {
+ for (retries = ZFCP_EXCHANGE_CONFIG_DATA_RETRIES; retries; retries--) {
atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
&adapter->status);
ZFCP_LOG_DEBUG("Doing exchange config data\n");
@@ -2329,16 +2325,17 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
zfcp_get_busid_by_adapter(adapter));
break;
}
- if (atomic_test_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
- &adapter->status)) {
- ZFCP_LOG_DEBUG("host connection still initialising... "
- "waiting and retrying...\n");
- /* sleep a little bit before retry */
- msleep(jiffies_to_msecs(ZFCP_EXCHANGE_CONFIG_DATA_SLEEP));
- }
- } while ((retries--) &&
- atomic_test_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
- &adapter->status));
+
+ if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
+ &adapter->status))
+ break;
+
+ ZFCP_LOG_DEBUG("host connection still initialising... "
+ "waiting and retrying...\n");
+ /* sleep a little bit before retry */
+ msleep(jiffies_to_msecs(sleep));
+ sleep *= 2;
+ }
if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
&adapter->status)) {
@@ -3485,6 +3482,45 @@ zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action)
}
/*
+ * function: zfcp_erp_port_boxed
+ *
+ * purpose:
+ */
+void
+zfcp_erp_port_boxed(struct zfcp_port *port)
+{
+ struct zfcp_adapter *adapter = port->adapter;
+ unsigned long flags;
+
+ debug_text_event(adapter->erp_dbf, 3, "p_access_boxed");
+ debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t));
+ read_lock_irqsave(&zfcp_data.config_lock, flags);
+ zfcp_erp_modify_port_status(port,
+ ZFCP_STATUS_COMMON_ACCESS_BOXED,
+ ZFCP_SET);
+ read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+ zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED);
+}
+
+/*
+ * function: zfcp_erp_unit_boxed
+ *
+ * purpose:
+ */
+void
+zfcp_erp_unit_boxed(struct zfcp_unit *unit)
+{
+ struct zfcp_adapter *adapter = unit->port->adapter;
+
+ debug_text_event(adapter->erp_dbf, 3, "u_access_boxed");
+ debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t));
+ zfcp_erp_modify_unit_status(unit,
+ ZFCP_STATUS_COMMON_ACCESS_BOXED,
+ ZFCP_SET);
+ zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED);
+}
+
+/*
* function: zfcp_erp_port_access_denied
*
* purpose:
@@ -3495,11 +3531,13 @@ zfcp_erp_port_access_denied(struct zfcp_port *port)
struct zfcp_adapter *adapter = port->adapter;
unsigned long flags;
- debug_text_event(adapter->erp_dbf, 3, "p_access_block");
+ debug_text_event(adapter->erp_dbf, 3, "p_access_denied");
debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t));
read_lock_irqsave(&zfcp_data.config_lock, flags);
- zfcp_erp_modify_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED |
- ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET);
+ zfcp_erp_modify_port_status(port,
+ ZFCP_STATUS_COMMON_ERP_FAILED |
+ ZFCP_STATUS_COMMON_ACCESS_DENIED,
+ ZFCP_SET);
read_unlock_irqrestore(&zfcp_data.config_lock, flags);
}
@@ -3513,10 +3551,12 @@ zfcp_erp_unit_access_denied(struct zfcp_unit *unit)
{
struct zfcp_adapter *adapter = unit->port->adapter;
- debug_text_event(adapter->erp_dbf, 3, "u_access_block");
+ debug_text_event(adapter->erp_dbf, 3, "u_access_denied");
debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t));
- zfcp_erp_modify_unit_status(unit, ZFCP_STATUS_COMMON_ERP_FAILED |
- ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET);
+ zfcp_erp_modify_unit_status(unit,
+ ZFCP_STATUS_COMMON_ERP_FAILED |
+ ZFCP_STATUS_COMMON_ACCESS_DENIED,
+ ZFCP_SET);
}
/*
@@ -3530,7 +3570,7 @@ zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter)
struct zfcp_port *port;
unsigned long flags;
- debug_text_event(adapter->erp_dbf, 3, "a_access_unblock");
+ debug_text_event(adapter->erp_dbf, 3, "a_access_recover");
debug_event(adapter->erp_dbf, 3, &adapter->name, 8);
read_lock_irqsave(&zfcp_data.config_lock, flags);
@@ -3553,10 +3593,12 @@ zfcp_erp_port_access_changed(struct zfcp_port *port)
struct zfcp_adapter *adapter = port->adapter;
struct zfcp_unit *unit;
- debug_text_event(adapter->erp_dbf, 3, "p_access_unblock");
+ debug_text_event(adapter->erp_dbf, 3, "p_access_recover");
debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t));
if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED,
+ &port->status) &&
+ !atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED,
&port->status)) {
if (!atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status))
list_for_each_entry(unit, &port->unit_list_head, list)
@@ -3583,10 +3625,13 @@ zfcp_erp_unit_access_changed(struct zfcp_unit *unit)
{
struct zfcp_adapter *adapter = unit->port->adapter;
- debug_text_event(adapter->erp_dbf, 3, "u_access_unblock");
+ debug_text_event(adapter->erp_dbf, 3, "u_access_recover");
debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t));
- if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, &unit->status))
+ if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED,
+ &unit->status) &&
+ !atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED,
+ &unit->status))
return;
ZFCP_LOG_NORMAL("reopen of unit 0x%016Lx on port 0x%016Lx "
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index d5fd4335207..42df7e57eea 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -116,7 +116,7 @@ extern int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *,
struct timer_list*, int);
extern int zfcp_fsf_req_complete(struct zfcp_fsf_req *);
extern void zfcp_fsf_incoming_els(struct zfcp_fsf_req *);
-extern void zfcp_fsf_req_cleanup(struct zfcp_fsf_req *);
+extern void zfcp_fsf_req_free(struct zfcp_fsf_req *);
extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_command_task_management(
struct zfcp_adapter *, struct zfcp_unit *, u8, int);
extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(
@@ -171,6 +171,8 @@ extern int zfcp_erp_async_handler(struct zfcp_erp_action *, unsigned long);
extern int zfcp_test_link(struct zfcp_port *);
+extern void zfcp_erp_port_boxed(struct zfcp_port *);
+extern void zfcp_erp_unit_boxed(struct zfcp_unit *);
extern void zfcp_erp_port_access_denied(struct zfcp_port *);
extern void zfcp_erp_unit_access_denied(struct zfcp_unit *);
extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *);
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 148b11c822b..0d9f20edc49 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -61,7 +61,6 @@ static int zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *);
static int zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *);
static int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *);
static void zfcp_fsf_req_dismiss(struct zfcp_fsf_req *);
-static void zfcp_fsf_req_free(struct zfcp_fsf_req *);
/* association between FSF command and FSF QTCB type */
static u32 fsf_qtcb_type[] = {
@@ -149,13 +148,13 @@ zfcp_fsf_req_alloc(mempool_t *pool, int req_flags)
*
* locks: none
*/
-static void
+void
zfcp_fsf_req_free(struct zfcp_fsf_req *fsf_req)
{
if (likely(fsf_req->pool != NULL))
mempool_free(fsf_req, fsf_req->pool);
- else
- kfree(fsf_req);
+ else
+ kfree(fsf_req);
}
/*
@@ -170,30 +169,21 @@ zfcp_fsf_req_free(struct zfcp_fsf_req *fsf_req)
int
zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
{
- int retval = 0;
struct zfcp_fsf_req *fsf_req, *tmp;
+ unsigned long flags;
+ LIST_HEAD(remove_queue);
- list_for_each_entry_safe(fsf_req, tmp, &adapter->fsf_req_list_head,
- list)
- zfcp_fsf_req_dismiss(fsf_req);
- /* wait_event_timeout? */
- while (!list_empty(&adapter->fsf_req_list_head)) {
- ZFCP_LOG_DEBUG("fsf req list of adapter %s not yet empty\n",
- zfcp_get_busid_by_adapter(adapter));
- /* wait for woken intiators to clean up their requests */
- msleep(jiffies_to_msecs(ZFCP_FSFREQ_CLEANUP_TIMEOUT));
- }
+ spin_lock_irqsave(&adapter->fsf_req_list_lock, flags);
+ list_splice_init(&adapter->fsf_req_list_head, &remove_queue);
+ atomic_set(&adapter->fsf_reqs_active, 0);
+ spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
- /* consistency check */
- if (atomic_read(&adapter->fsf_reqs_active)) {
- ZFCP_LOG_NORMAL("bug: There are still %d FSF requests pending "
- "on adapter %s after cleanup.\n",
- atomic_read(&adapter->fsf_reqs_active),
- zfcp_get_busid_by_adapter(adapter));
- atomic_set(&adapter->fsf_reqs_active, 0);
+ list_for_each_entry_safe(fsf_req, tmp, &remove_queue, list) {
+ list_del(&fsf_req->list);
+ zfcp_fsf_req_dismiss(fsf_req);
}
- return retval;
+ return 0;
}
/*
@@ -226,10 +216,6 @@ zfcp_fsf_req_complete(struct zfcp_fsf_req *fsf_req)
{
int retval = 0;
int cleanup;
- struct zfcp_adapter *adapter = fsf_req->adapter;
-
- /* do some statistics */
- atomic_dec(&adapter->fsf_reqs_active);
if (unlikely(fsf_req->fsf_command == FSF_QTCB_UNSOLICITED_STATUS)) {
ZFCP_LOG_DEBUG("Status read response received\n");
@@ -260,7 +246,7 @@ zfcp_fsf_req_complete(struct zfcp_fsf_req *fsf_req)
* lock must not be held here since it will be
* grabed by the called routine, too
*/
- zfcp_fsf_req_cleanup(fsf_req);
+ zfcp_fsf_req_free(fsf_req);
} else {
/* notify initiator waiting for the requests completion */
ZFCP_LOG_TRACE("waking initiator of FSF request %p\n",fsf_req);
@@ -346,15 +332,10 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
switch (fsf_req->qtcb->prefix.prot_status) {
case FSF_PROT_GOOD:
- ZFCP_LOG_TRACE("FSF_PROT_GOOD\n");
- break;
-
case FSF_PROT_FSF_STATUS_PRESENTED:
- ZFCP_LOG_TRACE("FSF_PROT_FSF_STATUS_PRESENTED\n");
break;
case FSF_PROT_QTCB_VERSION_ERROR:
- ZFCP_LOG_FLAGS(0, "FSF_PROT_QTCB_VERSION_ERROR\n");
ZFCP_LOG_NORMAL("error: The adapter %s contains "
"microcode of version 0x%x, the device driver "
"only supports 0x%x. Aborting.\n",
@@ -371,7 +352,6 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
break;
case FSF_PROT_SEQ_NUMB_ERROR:
- ZFCP_LOG_FLAGS(0, "FSF_PROT_SEQ_NUMB_ERROR\n");
ZFCP_LOG_NORMAL("bug: Sequence number mismatch between "
"driver (0x%x) and adapter %s (0x%x). "
"Restarting all operations on this adapter.\n",
@@ -390,7 +370,6 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
break;
case FSF_PROT_UNSUPP_QTCB_TYPE:
- ZFCP_LOG_FLAGS(0, "FSF_PROT_UNSUP_QTCB_TYPE\n");
ZFCP_LOG_NORMAL("error: Packet header type used by the "
"device driver is incompatible with "
"that used on adapter %s. "
@@ -405,7 +384,6 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
break;
case FSF_PROT_HOST_CONNECTION_INITIALIZING:
- ZFCP_LOG_FLAGS(1, "FSF_PROT_HOST_CONNECTION_INITIALIZING\n");
zfcp_cmd_dbf_event_fsf("hconinit", fsf_req,
&fsf_req->qtcb->prefix.prot_status_qual,
sizeof (union fsf_prot_status_qual));
@@ -416,7 +394,6 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
break;
case FSF_PROT_DUPLICATE_REQUEST_ID:
- ZFCP_LOG_FLAGS(0, "FSF_PROT_DUPLICATE_REQUEST_IDS\n");
if (fsf_req->qtcb) {
ZFCP_LOG_NORMAL("bug: The request identifier 0x%Lx "
"to the adapter %s is ambiguous. "
@@ -445,7 +422,6 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
break;
case FSF_PROT_LINK_DOWN:
- ZFCP_LOG_FLAGS(1, "FSF_PROT_LINK_DOWN\n");
/*
* 'test and set' is not atomic here -
* it's ok as long as calls to our response queue handler
@@ -502,13 +478,11 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
ZFCP_STATUS_COMMON_ERP_FAILED,
&adapter->status);
zfcp_erp_adapter_reopen(adapter, 0);
- debug_text_event(adapter->erp_dbf, 1, "prot_link_down");
}
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_PROT_REEST_QUEUE:
- ZFCP_LOG_FLAGS(1, "FSF_PROT_REEST_QUEUE\n");
debug_text_event(adapter->erp_dbf, 1, "prot_reest_queue");
ZFCP_LOG_INFO("The local link to adapter with "
"%s was re-plugged. "
@@ -528,7 +502,6 @@ zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *fsf_req)
break;
case FSF_PROT_ERROR_STATE:
- ZFCP_LOG_FLAGS(0, "FSF_PROT_ERROR_STATE\n");
ZFCP_LOG_NORMAL("error: The adapter %s "
"has entered the error state. "
"Restarting all operations on this "
@@ -589,7 +562,6 @@ zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *fsf_req)
/* evaluate FSF Status */
switch (fsf_req->qtcb->header.fsf_status) {
case FSF_UNKNOWN_COMMAND:
- ZFCP_LOG_FLAGS(0, "FSF_UNKNOWN_COMMAND\n");
ZFCP_LOG_NORMAL("bug: Command issued by the device driver is "
"not known by the adapter %s "
"Stopping all operations on this adapter. "
@@ -606,14 +578,12 @@ zfcp_fsf_fsfstatus_eval(struct zfcp_fsf_req *fsf_req)
break;
case FSF_FCP_RSP_AVAILABLE:
- ZFCP_LOG_FLAGS(2, "FSF_FCP_RSP_AVAILABLE\n");
ZFCP_LOG_DEBUG("FCP Sense data will be presented to the "
"SCSI stack.\n");
debug_text_event(fsf_req->adapter->erp_dbf, 3, "fsf_s_rsp");
break;
case FSF_ADAPTER_STATUS_AVAILABLE:
- ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_astatus");
zfcp_fsf_fsfstatus_qual_eval(fsf_req);
break;
@@ -647,11 +617,9 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req)
switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) {
case FSF_SQ_FCP_RSP_AVAILABLE:
- ZFCP_LOG_FLAGS(2, "FSF_SQ_FCP_RSP_AVAILABLE\n");
debug_text_event(fsf_req->adapter->erp_dbf, 4, "fsf_sq_rsp");
break;
case FSF_SQ_RETRY_IF_POSSIBLE:
- ZFCP_LOG_FLAGS(2, "FSF_SQ_RETRY_IF_POSSIBLE\n");
/* The SCSI-stack may now issue retries or escalate */
debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_sq_retry");
zfcp_cmd_dbf_event_fsf("sqretry", fsf_req,
@@ -660,7 +628,6 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req)
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_SQ_COMMAND_ABORTED:
- ZFCP_LOG_FLAGS(2, "FSF_SQ_COMMAND_ABORTED\n");
/* Carry the aborted state on to upper layer */
debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_sq_abort");
zfcp_cmd_dbf_event_fsf("sqabort", fsf_req,
@@ -670,7 +637,6 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req)
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_SQ_NO_RECOM:
- ZFCP_LOG_FLAGS(0, "FSF_SQ_NO_RECOM\n");
debug_text_exception(fsf_req->adapter->erp_dbf, 0,
"fsf_sq_no_rec");
ZFCP_LOG_NORMAL("bug: No recommendation could be given for a"
@@ -684,7 +650,6 @@ zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *fsf_req)
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_SQ_ULP_PROGRAMMING_ERROR:
- ZFCP_LOG_FLAGS(0, "FSF_SQ_ULP_PROGRAMMING_ERROR\n");
ZFCP_LOG_NORMAL("error: not enough SBALs for data transfer "
"(adapter %s)\n",
zfcp_get_busid_by_adapter(fsf_req->adapter));
@@ -740,72 +705,58 @@ zfcp_fsf_req_dispatch(struct zfcp_fsf_req *fsf_req)
switch (fsf_req->fsf_command) {
case FSF_QTCB_FCP_CMND:
- ZFCP_LOG_FLAGS(3, "FSF_QTCB_FCP_CMND\n");
zfcp_fsf_send_fcp_command_handler(fsf_req);
break;
case FSF_QTCB_ABORT_FCP_CMND:
- ZFCP_LOG_FLAGS(2, "FSF_QTCB_ABORT_FCP_CMND\n");
zfcp_fsf_abort_fcp_command_handler(fsf_req);
break;
case FSF_QTCB_SEND_GENERIC:
- ZFCP_LOG_FLAGS(2, "FSF_QTCB_SEND_GENERIC\n");
zfcp_fsf_send_ct_handler(fsf_req);
break;
case FSF_QTCB_OPEN_PORT_WITH_DID:
- ZFCP_LOG_FLAGS(2, "FSF_QTCB_OPEN_PORT_WITH_DID\n");
zfcp_fsf_open_port_handler(fsf_req);
break;
case FSF_QTCB_OPEN_LUN:
- ZFCP_LOG_FLAGS(2, "FSF_QTCB_OPEN_LUN\n");
zfcp_fsf_open_unit_handler(fsf_req);
break;
case FSF_QTCB_CLOSE_LUN:
- ZFCP_LOG_FLAGS(2, "FSF_QTCB_CLOSE_LUN\n");
zfcp_fsf_close_unit_handler(fsf_req);
break;
case FSF_QTCB_CLOSE_PORT:
- ZFCP_LOG_FLAGS(2, "FSF_QTCB_CLOSE_PORT\n");
zfcp_fsf_close_port_handler(fsf_req);
break;
case FSF_QTCB_CLOSE_PHYSICAL_PORT:
- ZFCP_LOG_FLAGS(2, "FSF_QTCB_CLOSE_PHYSICAL_PORT\n");
zfcp_fsf_close_physical_port_handler(fsf_req);
break;
case FSF_QTCB_EXCHANGE_CONFIG_DATA:
- ZFCP_LOG_FLAGS(2, "FSF_QTCB_EXCHANGE_CONFIG_DATA\n");
zfcp_fsf_exchange_config_data_handler(fsf_req);
break;
case FSF_QTCB_EXCHANGE_PORT_DATA:
- ZFCP_LOG_FLAGS(2, "FSF_QTCB_EXCHANGE_PORT_DATA\n");
zfcp_fsf_exchange_port_data_handler(fsf_req);
break;
case FSF_QTCB_SEND_ELS:
- ZFCP_LOG_FLAGS(2, "FSF_QTCB_SEND_ELS\n");
zfcp_fsf_send_els_handler(fsf_req);
break;
case FSF_QTCB_DOWNLOAD_CONTROL_FILE:
- ZFCP_LOG_FLAGS(2, "FSF_QTCB_DOWNLOAD_CONTROL_FILE\n");
zfcp_fsf_control_file_handler(fsf_req);
break;
case FSF_QTCB_UPLOAD_CONTROL_FILE:
- ZFCP_LOG_FLAGS(2, "FSF_QTCB_UPLOAD_CONTROL_FILE\n");
zfcp_fsf_control_file_handler(fsf_req);
break;
default:
- ZFCP_LOG_FLAGS(2, "FSF_QTCB_UNKNOWN\n");
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
ZFCP_LOG_NORMAL("bug: Command issued by the device driver is "
"not supported by the adapter %s\n",
@@ -929,13 +880,11 @@ zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *fsf_req)
switch (status_buffer->status_subtype) {
case FSF_STATUS_READ_SUB_CLOSE_PHYS_PORT:
- ZFCP_LOG_FLAGS(2, "FSF_STATUS_READ_SUB_CLOSE_PHYS_PORT\n");
debug_text_event(adapter->erp_dbf, 3, "unsol_pc_phys:");
zfcp_erp_port_reopen(port, 0);
break;
case FSF_STATUS_READ_SUB_ERROR_PORT:
- ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_SUB_ERROR_PORT\n");
debug_text_event(adapter->erp_dbf, 1, "unsol_pc_err:");
zfcp_erp_port_shutdown(port, 0);
break;
@@ -973,14 +922,13 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
mempool_free(status_buffer, adapter->pool.data_status_read);
- zfcp_fsf_req_cleanup(fsf_req);
+ zfcp_fsf_req_free(fsf_req);
goto out;
}
switch (status_buffer->status_type) {
case FSF_STATUS_READ_PORT_CLOSED:
- ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_PORT_CLOSED\n");
debug_text_event(adapter->erp_dbf, 3, "unsol_pclosed:");
debug_event(adapter->erp_dbf, 3,
&status_buffer->d_id, sizeof (u32));
@@ -988,13 +936,11 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_STATUS_READ_INCOMING_ELS:
- ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_INCOMING_ELS\n");
debug_text_event(adapter->erp_dbf, 3, "unsol_els:");
zfcp_fsf_incoming_els(fsf_req);
break;
case FSF_STATUS_READ_SENSE_DATA_AVAIL:
- ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_SENSE_DATA_AVAIL\n");
debug_text_event(adapter->erp_dbf, 3, "unsol_sense:");
ZFCP_LOG_INFO("unsolicited sense data received (adapter %s)\n",
zfcp_get_busid_by_adapter(adapter));
@@ -1003,7 +949,6 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_STATUS_READ_BIT_ERROR_THRESHOLD:
- ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_BIT_ERROR_THRESHOLD\n");
debug_text_event(adapter->erp_dbf, 3, "unsol_bit_err:");
ZFCP_LOG_NORMAL("Bit error threshold data received:\n");
ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL,
@@ -1012,7 +957,6 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_STATUS_READ_LINK_DOWN:
- ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_LINK_DOWN\n");
debug_text_event(adapter->erp_dbf, 0, "unsol_link_down:");
ZFCP_LOG_INFO("Local link to adapter %s is down\n",
zfcp_get_busid_by_adapter(adapter));
@@ -1022,7 +966,6 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_STATUS_READ_LINK_UP:
- ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_LINK_UP\n");
debug_text_event(adapter->erp_dbf, 2, "unsol_link_up:");
ZFCP_LOG_INFO("Local link to adapter %s was replugged. "
"Restarting operations on this adapter\n",
@@ -1037,7 +980,6 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_STATUS_READ_CFDC_UPDATED:
- ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_CFDC_UPDATED\n");
debug_text_event(adapter->erp_dbf, 2, "unsol_cfdc_update:");
ZFCP_LOG_INFO("CFDC has been updated on the adapter %s\n",
zfcp_get_busid_by_adapter(adapter));
@@ -1045,7 +987,6 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_STATUS_READ_CFDC_HARDENED:
- ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_CFDC_HARDENED\n");
debug_text_event(adapter->erp_dbf, 2, "unsol_cfdc_harden:");
switch (status_buffer->status_subtype) {
case FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE:
@@ -1078,7 +1019,7 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
break;
}
mempool_free(status_buffer, adapter->pool.data_status_read);
- zfcp_fsf_req_cleanup(fsf_req);
+ zfcp_fsf_req_free(fsf_req);
/*
* recycle buffer and start new request repeat until outbound
* queue is empty or adapter shutdown is requested
@@ -1214,7 +1155,6 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
case FSF_PORT_HANDLE_NOT_VALID:
if (status_qual >> 4 != status_qual % 0xf) {
- ZFCP_LOG_FLAGS(2, "FSF_PORT_HANDLE_NOT_VALID\n");
debug_text_event(new_fsf_req->adapter->erp_dbf, 3,
"fsf_s_phand_nv0");
/*
@@ -1223,7 +1163,6 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
* fine.
*/
} else {
- ZFCP_LOG_FLAGS(1, "FSF_PORT_HANDLE_NOT_VALID\n");
ZFCP_LOG_INFO("Temporary port identifier 0x%x for "
"port 0x%016Lx on adapter %s invalid. "
"This may happen occasionally.\n",
@@ -1246,7 +1185,6 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
case FSF_LUN_HANDLE_NOT_VALID:
if (status_qual >> 4 != status_qual % 0xf) {
/* 2 */
- ZFCP_LOG_FLAGS(0, "FSF_LUN_HANDLE_NOT_VALID\n");
debug_text_event(new_fsf_req->adapter->erp_dbf, 3,
"fsf_s_lhand_nv0");
/*
@@ -1255,7 +1193,6 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
* This is fine.
*/
} else {
- ZFCP_LOG_FLAGS(1, "FSF_LUN_HANDLE_NOT_VALID\n");
ZFCP_LOG_INFO
("Warning: Temporary LUN identifier 0x%x of LUN "
"0x%016Lx on port 0x%016Lx on adapter %s is "
@@ -1279,7 +1216,6 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
break;
case FSF_FCP_COMMAND_DOES_NOT_EXIST:
- ZFCP_LOG_FLAGS(2, "FSF_FCP_COMMAND_DOES_NOT_EXIST\n");
retval = 0;
debug_text_event(new_fsf_req->adapter->erp_dbf, 3,
"fsf_s_no_exist");
@@ -1287,50 +1223,37 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
break;
case FSF_PORT_BOXED:
- /* 2 */
- ZFCP_LOG_FLAGS(0, "FSF_PORT_BOXED\n");
ZFCP_LOG_INFO("Remote port 0x%016Lx on adapter %s needs to "
"be reopened\n", unit->port->wwpn,
zfcp_get_busid_by_unit(unit));
debug_text_event(new_fsf_req->adapter->erp_dbf, 2,
"fsf_s_pboxed");
- zfcp_erp_port_reopen(unit->port, 0);
+ zfcp_erp_port_boxed(unit->port);
new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR
| ZFCP_STATUS_FSFREQ_RETRY;
break;
case FSF_LUN_BOXED:
- ZFCP_LOG_FLAGS(0, "FSF_LUN_BOXED\n");
ZFCP_LOG_INFO(
"unit 0x%016Lx on port 0x%016Lx on adapter %s needs "
"to be reopened\n",
unit->fcp_lun, unit->port->wwpn,
zfcp_get_busid_by_unit(unit));
debug_text_event(new_fsf_req->adapter->erp_dbf, 1, "fsf_s_lboxed");
- zfcp_erp_unit_reopen(unit, 0);
- zfcp_cmd_dbf_event_fsf("unitbox", new_fsf_req,
- &new_fsf_req->qtcb->header.fsf_status_qual,
- sizeof(union fsf_status_qual));
+ zfcp_erp_unit_boxed(unit);
new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR
| ZFCP_STATUS_FSFREQ_RETRY;
break;
case FSF_ADAPTER_STATUS_AVAILABLE:
- /* 2 */
- ZFCP_LOG_FLAGS(0, "FSF_ADAPTER_STATUS_AVAILABLE\n");
switch (new_fsf_req->qtcb->header.fsf_status_qual.word[0]) {
case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
- ZFCP_LOG_FLAGS(2,
- "FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
debug_text_event(new_fsf_req->adapter->erp_dbf, 1,
"fsf_sq_ltest");
- /* reopening link to port */
- zfcp_erp_port_reopen(unit->port, 0);
+ zfcp_test_link(unit->port);
new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
- ZFCP_LOG_FLAGS(2,
- "FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED\n");
/* SCSI stack will escalate */
debug_text_event(new_fsf_req->adapter->erp_dbf, 1,
"fsf_sq_ulp");
@@ -1350,8 +1273,6 @@ zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req)
break;
case FSF_GOOD:
- /* 3 */
- ZFCP_LOG_FLAGS(0, "FSF_GOOD\n");
retval = 0;
new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED;
break;
@@ -1553,12 +1474,10 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
switch (header->fsf_status) {
case FSF_GOOD:
- ZFCP_LOG_FLAGS(2,"FSF_GOOD\n");
retval = 0;
break;
case FSF_SERVICE_CLASS_NOT_SUPPORTED:
- ZFCP_LOG_FLAGS(2, "FSF_SERVICE_CLASS_NOT_SUPPORTED\n");
if (adapter->fc_service_class <= 3) {
ZFCP_LOG_INFO("error: adapter %s does not support fc "
"class %d.\n",
@@ -1578,17 +1497,14 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_ADAPTER_STATUS_AVAILABLE:
- ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
switch (header->fsf_status_qual.word[0]){
case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
- ZFCP_LOG_FLAGS(2,"FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
/* reopening link to port */
debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest");
zfcp_test_link(port);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
- ZFCP_LOG_FLAGS(2,"FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED\n");
/* ERP strategy will escalate */
debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp");
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -1602,7 +1518,6 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_ACCESS_DENIED:
- ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n");
ZFCP_LOG_NORMAL("access denied, cannot send generic service "
"command (adapter %s, port d_id=0x%08x)\n",
zfcp_get_busid_by_port(port), port->d_id);
@@ -1625,7 +1540,6 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_GENERIC_COMMAND_REJECTED:
- ZFCP_LOG_FLAGS(2, "FSF_GENERIC_COMMAND_REJECTED\n");
ZFCP_LOG_INFO("generic service command rejected "
"(adapter %s, port d_id=0x%08x)\n",
zfcp_get_busid_by_port(port), port->d_id);
@@ -1638,7 +1552,6 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_PORT_HANDLE_NOT_VALID:
- ZFCP_LOG_FLAGS(2, "FSF_PORT_HANDLE_NOT_VALID\n");
ZFCP_LOG_DEBUG("Temporary port identifier 0x%x for port "
"0x%016Lx on adapter %s invalid. This may "
"happen occasionally.\n", port->handle,
@@ -1653,12 +1566,11 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_PORT_BOXED:
- ZFCP_LOG_FLAGS(2, "FSF_PORT_BOXED\n");
ZFCP_LOG_INFO("port needs to be reopened "
"(adapter %s, port d_id=0x%08x)\n",
zfcp_get_busid_by_port(port), port->d_id);
debug_text_event(adapter->erp_dbf, 2, "fsf_s_pboxed");
- zfcp_erp_port_reopen(port, 0);
+ zfcp_erp_port_boxed(port);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR
| ZFCP_STATUS_FSFREQ_RETRY;
break;
@@ -1666,7 +1578,6 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
/* following states should never occure, all cases avoided
in zfcp_fsf_send_ct - but who knows ... */
case FSF_PAYLOAD_SIZE_MISMATCH:
- ZFCP_LOG_FLAGS(2, "FSF_PAYLOAD_SIZE_MISMATCH\n");
ZFCP_LOG_INFO("payload size mismatch (adapter: %s, "
"req_buf_length=%d, resp_buf_length=%d)\n",
zfcp_get_busid_by_adapter(adapter),
@@ -1674,7 +1585,6 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_REQUEST_SIZE_TOO_LARGE:
- ZFCP_LOG_FLAGS(2, "FSF_REQUEST_SIZE_TOO_LARGE\n");
ZFCP_LOG_INFO("request size too large (adapter: %s, "
"req_buf_length=%d)\n",
zfcp_get_busid_by_adapter(adapter),
@@ -1682,7 +1592,6 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_RESPONSE_SIZE_TOO_LARGE:
- ZFCP_LOG_FLAGS(2, "FSF_RESPONSE_SIZE_TOO_LARGE\n");
ZFCP_LOG_INFO("response size too large (adapter: %s, "
"resp_buf_length=%d)\n",
zfcp_get_busid_by_adapter(adapter),
@@ -1690,7 +1599,6 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_SBAL_MISMATCH:
- ZFCP_LOG_FLAGS(2, "FSF_SBAL_MISMATCH\n");
ZFCP_LOG_INFO("SBAL mismatch (adapter: %s, req_buf_length=%d, "
"resp_buf_length=%d)\n",
zfcp_get_busid_by_adapter(adapter),
@@ -1846,8 +1754,8 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
{
struct zfcp_adapter *adapter;
- fc_id_t d_id;
struct zfcp_port *port;
+ fc_id_t d_id;
struct fsf_qtcb_header *header;
struct fsf_qtcb_bottom_support *bottom;
struct zfcp_send_els *send_els;
@@ -1856,6 +1764,7 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
send_els = fsf_req->data.send_els;
adapter = send_els->adapter;
+ port = send_els->port;
d_id = send_els->d_id;
header = &fsf_req->qtcb->header;
bottom = &fsf_req->qtcb->bottom.support;
@@ -1866,12 +1775,10 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
switch (header->fsf_status) {
case FSF_GOOD:
- ZFCP_LOG_FLAGS(2, "FSF_GOOD\n");
retval = 0;
break;
case FSF_SERVICE_CLASS_NOT_SUPPORTED:
- ZFCP_LOG_FLAGS(2, "FSF_SERVICE_CLASS_NOT_SUPPORTED\n");
if (adapter->fc_service_class <= 3) {
ZFCP_LOG_INFO("error: adapter %s does "
"not support fibrechannel class %d.\n",
@@ -1891,22 +1798,14 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_ADAPTER_STATUS_AVAILABLE:
- ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
switch (header->fsf_status_qual.word[0]){
case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
- ZFCP_LOG_FLAGS(2,"FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest");
- if (send_els->ls_code != ZFCP_LS_ADISC) {
- read_lock(&zfcp_data.config_lock);
- port = zfcp_get_port_by_did(adapter, d_id);
- if (port)
- zfcp_test_link(port);
- read_unlock(&zfcp_data.config_lock);
- }
+ if (port && (send_els->ls_code != ZFCP_LS_ADISC))
+ zfcp_test_link(port);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
- ZFCP_LOG_FLAGS(2,"FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED\n");
debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp");
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
retval =
@@ -1915,7 +1814,6 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
&header->fsf_status_qual.word[2]);
break;
case FSF_SQ_RETRY_IF_POSSIBLE:
- ZFCP_LOG_FLAGS(2, "FSF_SQ_RETRY_IF_POSSIBLE\n");
debug_text_event(adapter->erp_dbf, 1, "fsf_sq_retry");
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -1928,7 +1826,6 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_ELS_COMMAND_REJECTED:
- ZFCP_LOG_FLAGS(2, "FSF_ELS_COMMAND_REJECTED\n");
ZFCP_LOG_INFO("ELS has been rejected because command filter "
"prohibited sending "
"(adapter: %s, port d_id: 0x%08x)\n",
@@ -1937,7 +1834,6 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_PAYLOAD_SIZE_MISMATCH:
- ZFCP_LOG_FLAGS(2, "FSF_PAYLOAD_SIZE_MISMATCH\n");
ZFCP_LOG_INFO(
"ELS request size and ELS response size must be either "
"both 0, or both greater than 0 "
@@ -1948,7 +1844,6 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_REQUEST_SIZE_TOO_LARGE:
- ZFCP_LOG_FLAGS(2, "FSF_REQUEST_SIZE_TOO_LARGE\n");
ZFCP_LOG_INFO(
"Length of the ELS request buffer, "
"specified in QTCB bottom, "
@@ -1960,7 +1855,6 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_RESPONSE_SIZE_TOO_LARGE:
- ZFCP_LOG_FLAGS(2, "FSF_RESPONSE_SIZE_TOO_LARGE\n");
ZFCP_LOG_INFO(
"Length of the ELS response buffer, "
"specified in QTCB bottom, "
@@ -1973,7 +1867,6 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
case FSF_SBAL_MISMATCH:
/* should never occure, avoided in zfcp_fsf_send_els */
- ZFCP_LOG_FLAGS(2, "FSF_SBAL_MISMATCH\n");
ZFCP_LOG_INFO("SBAL mismatch (adapter: %s, req_buf_length=%d, "
"resp_buf_length=%d)\n",
zfcp_get_busid_by_adapter(adapter),
@@ -1982,7 +1875,6 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_ACCESS_DENIED:
- ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n");
ZFCP_LOG_NORMAL("access denied, cannot send ELS command "
"(adapter %s, port d_id=0x%08x)\n",
zfcp_get_busid_by_adapter(adapter), d_id);
@@ -2000,11 +1892,8 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
}
}
debug_text_event(adapter->erp_dbf, 1, "fsf_s_access");
- read_lock(&zfcp_data.config_lock);
- port = zfcp_get_port_by_did(adapter, d_id);
if (port != NULL)
zfcp_erp_port_access_denied(port);
- read_unlock(&zfcp_data.config_lock);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
@@ -2195,14 +2084,11 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
switch (fsf_req->qtcb->header.fsf_status) {
case FSF_GOOD:
- ZFCP_LOG_FLAGS(2, "FSF_GOOD\n");
-
if (zfcp_fsf_exchange_config_evaluate(fsf_req, 1))
return -EIO;
switch (adapter->fc_topology) {
case FSF_TOPO_P2P:
- ZFCP_LOG_FLAGS(1, "FSF_TOPO_P2P\n");
ZFCP_LOG_NORMAL("Point-to-Point fibrechannel "
"configuration detected at adapter %s\n"
"Peer WWNN 0x%016llx, "
@@ -2216,7 +2102,6 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
"top-p-to-p");
break;
case FSF_TOPO_AL:
- ZFCP_LOG_FLAGS(1, "FSF_TOPO_AL\n");
ZFCP_LOG_NORMAL("error: Arbitrated loop fibrechannel "
"topology detected at adapter %s "
"unsupported, shutting down adapter\n",
@@ -2226,7 +2111,6 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
zfcp_erp_adapter_shutdown(adapter, 0);
return -EIO;
case FSF_TOPO_FABRIC:
- ZFCP_LOG_FLAGS(1, "FSF_TOPO_FABRIC\n");
ZFCP_LOG_INFO("Switched fabric fibrechannel "
"network detected at adapter %s.\n",
zfcp_get_busid_by_adapter(adapter));
@@ -2357,7 +2241,7 @@ zfcp_fsf_exchange_port_data(struct zfcp_adapter *adapter,
wait_event(fsf_req->completion_wq,
fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
del_timer_sync(timer);
- zfcp_fsf_req_cleanup(fsf_req);
+ zfcp_fsf_req_free(fsf_req);
out:
kfree(timer);
return retval;
@@ -2379,7 +2263,6 @@ zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req)
switch (fsf_req->qtcb->header.fsf_status) {
case FSF_GOOD:
- ZFCP_LOG_FLAGS(2,"FSF_GOOD\n");
bottom = &fsf_req->qtcb->bottom.port;
memcpy(data, bottom, sizeof(*data));
break;
@@ -2481,7 +2364,6 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
switch (header->fsf_status) {
case FSF_PORT_ALREADY_OPEN:
- ZFCP_LOG_FLAGS(0, "FSF_PORT_ALREADY_OPEN\n");
ZFCP_LOG_NORMAL("bug: remote port 0x%016Lx on adapter %s "
"is already open.\n",
port->wwpn, zfcp_get_busid_by_port(port));
@@ -2494,7 +2376,6 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_ACCESS_DENIED:
- ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n");
ZFCP_LOG_NORMAL("Access denied, cannot open port 0x%016Lx "
"on adapter %s\n",
port->wwpn, zfcp_get_busid_by_port(port));
@@ -2517,7 +2398,6 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED:
- ZFCP_LOG_FLAGS(1, "FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED\n");
ZFCP_LOG_INFO("error: The FSF adapter is out of resources. "
"The remote port 0x%016Lx on adapter %s "
"could not be opened. Disabling it.\n",
@@ -2529,11 +2409,8 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_ADAPTER_STATUS_AVAILABLE:
- ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
switch (header->fsf_status_qual.word[0]) {
case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
- ZFCP_LOG_FLAGS(2,
- "FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
debug_text_event(fsf_req->adapter->erp_dbf, 1,
"fsf_sq_ltest");
/* ERP strategy will escalate */
@@ -2546,7 +2423,6 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_SQ_NO_RETRY_POSSIBLE:
- ZFCP_LOG_FLAGS(0, "FSF_SQ_NO_RETRY_POSSIBLE\n");
ZFCP_LOG_NORMAL("The remote port 0x%016Lx on "
"adapter %s could not be opened. "
"Disabling it.\n",
@@ -2572,7 +2448,6 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_GOOD:
- ZFCP_LOG_FLAGS(3, "FSF_GOOD\n");
/* save port handle assigned by FSF */
port->handle = header->port_handle;
ZFCP_LOG_INFO("The remote port 0x%016Lx via adapter %s "
@@ -2582,6 +2457,9 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
/* mark port as open */
atomic_set_mask(ZFCP_STATUS_COMMON_OPEN |
ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
+ atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
+ ZFCP_STATUS_COMMON_ACCESS_BOXED,
+ &port->status);
retval = 0;
/* check whether D_ID has changed during open */
/*
@@ -2630,7 +2508,6 @@ zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req)
case FSF_UNKNOWN_OP_SUBTYPE:
/* should never occure, subtype not set in zfcp_fsf_open_port */
- ZFCP_LOG_FLAGS(2, "FSF_UNKNOWN_OP_SUBTYPE\n");
ZFCP_LOG_INFO("unknown operation subtype (adapter: %s, "
"op_subtype=0x%x)\n",
zfcp_get_busid_by_port(port),
@@ -2739,7 +2616,6 @@ zfcp_fsf_close_port_handler(struct zfcp_fsf_req *fsf_req)
switch (fsf_req->qtcb->header.fsf_status) {
case FSF_PORT_HANDLE_NOT_VALID:
- ZFCP_LOG_FLAGS(1, "FSF_PORT_HANDLE_NOT_VALID\n");
ZFCP_LOG_INFO("Temporary port identifier 0x%x for port "
"0x%016Lx on adapter %s invalid. This may happen "
"occasionally.\n", port->handle,
@@ -2755,7 +2631,6 @@ zfcp_fsf_close_port_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_ADAPTER_STATUS_AVAILABLE:
- ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
/* Note: FSF has actually closed the port in this case.
* The status code is just daft. Fingers crossed for a change
*/
@@ -2763,7 +2638,6 @@ zfcp_fsf_close_port_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_GOOD:
- ZFCP_LOG_FLAGS(3, "FSF_GOOD\n");
ZFCP_LOG_TRACE("remote port 0x016%Lx on adapter %s closed, "
"port handle 0x%x\n", port->wwpn,
zfcp_get_busid_by_port(port), port->handle);
@@ -2884,7 +2758,6 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req)
switch (header->fsf_status) {
case FSF_PORT_HANDLE_NOT_VALID:
- ZFCP_LOG_FLAGS(1, "FSF_PORT_HANDLE_NOT_VALID\n");
ZFCP_LOG_INFO("Temporary port identifier 0x%x invalid"
"(adapter %s, port 0x%016Lx). "
"This may happen occasionally.\n",
@@ -2902,7 +2775,6 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_ACCESS_DENIED:
- ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n");
ZFCP_LOG_NORMAL("Access denied, cannot close "
"physical port 0x%016Lx on adapter %s\n",
port->wwpn, zfcp_get_busid_by_port(port));
@@ -2925,32 +2797,26 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_PORT_BOXED:
- ZFCP_LOG_FLAGS(2, "FSF_PORT_BOXED\n");
ZFCP_LOG_DEBUG("The remote port 0x%016Lx on adapter "
"%s needs to be reopened but it was attempted "
"to close it physically.\n",
port->wwpn,
zfcp_get_busid_by_port(port));
debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_pboxed");
- zfcp_erp_port_reopen(port, 0);
+ zfcp_erp_port_boxed(port);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR |
ZFCP_STATUS_FSFREQ_RETRY;
break;
case FSF_ADAPTER_STATUS_AVAILABLE:
- ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
switch (header->fsf_status_qual.word[0]) {
case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
- ZFCP_LOG_FLAGS(2,
- "FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
debug_text_event(fsf_req->adapter->erp_dbf, 1,
"fsf_sq_ltest");
/* This will now be escalated by ERP */
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
- ZFCP_LOG_FLAGS(2,
- "FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED\n");
/* ERP strategy will escalate */
debug_text_event(fsf_req->adapter->erp_dbf, 1,
"fsf_sq_ulp");
@@ -2970,7 +2836,6 @@ zfcp_fsf_close_physical_port_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_GOOD:
- ZFCP_LOG_FLAGS(3, "FSF_GOOD\n");
ZFCP_LOG_DEBUG("Remote port 0x%016Lx via adapter %s "
"physically closed, port handle 0x%x\n",
port->wwpn,
@@ -3116,7 +2981,6 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
switch (header->fsf_status) {
case FSF_PORT_HANDLE_NOT_VALID:
- ZFCP_LOG_FLAGS(1, "FSF_PORT_HANDLE_NOT_VALID\n");
ZFCP_LOG_INFO("Temporary port identifier 0x%x "
"for port 0x%016Lx on adapter %s invalid "
"This may happen occasionally\n",
@@ -3132,7 +2996,6 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_LUN_ALREADY_OPEN:
- ZFCP_LOG_FLAGS(0, "FSF_LUN_ALREADY_OPEN\n");
ZFCP_LOG_NORMAL("bug: Attempted to open unit 0x%016Lx on "
"remote port 0x%016Lx on adapter %s twice.\n",
unit->fcp_lun,
@@ -3143,7 +3006,6 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_ACCESS_DENIED:
- ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n");
ZFCP_LOG_NORMAL("Access denied, cannot open unit 0x%016Lx on "
"remote port 0x%016Lx on adapter %s\n",
unit->fcp_lun, unit->port->wwpn,
@@ -3169,18 +3031,16 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_PORT_BOXED:
- ZFCP_LOG_FLAGS(2, "FSF_PORT_BOXED\n");
ZFCP_LOG_DEBUG("The remote port 0x%016Lx on adapter %s "
"needs to be reopened\n",
unit->port->wwpn, zfcp_get_busid_by_unit(unit));
debug_text_event(adapter->erp_dbf, 2, "fsf_s_pboxed");
- zfcp_erp_port_reopen(unit->port, 0);
+ zfcp_erp_port_boxed(unit->port);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR |
ZFCP_STATUS_FSFREQ_RETRY;
break;
case FSF_LUN_SHARING_VIOLATION:
- ZFCP_LOG_FLAGS(2, "FSF_LUN_SHARING_VIOLATION\n");
if (header->fsf_status_qual.word[0] != 0) {
ZFCP_LOG_NORMAL("FCP-LUN 0x%Lx at the remote port "
"with WWPN 0x%Lx "
@@ -3224,7 +3084,6 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED:
- ZFCP_LOG_FLAGS(1, "FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED\n");
ZFCP_LOG_INFO("error: The adapter ran out of resources. "
"There is no handle (temporary port identifier) "
"available for unit 0x%016Lx on port 0x%016Lx "
@@ -3239,20 +3098,15 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_ADAPTER_STATUS_AVAILABLE:
- ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
switch (header->fsf_status_qual.word[0]) {
case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
- ZFCP_LOG_FLAGS(2,
- "FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
/* Re-establish link to port */
debug_text_event(adapter->erp_dbf, 1,
"fsf_sq_ltest");
- zfcp_erp_port_reopen(unit->port, 0);
+ zfcp_test_link(unit->port);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
- ZFCP_LOG_FLAGS(2,
- "FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED\n");
/* ERP strategy will escalate */
debug_text_event(adapter->erp_dbf, 1,
"fsf_sq_ulp");
@@ -3271,7 +3125,6 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_INVALID_COMMAND_OPTION:
- ZFCP_LOG_FLAGS(2, "FSF_INVALID_COMMAND_OPTION\n");
ZFCP_LOG_NORMAL(
"Invalid option 0x%x has been specified "
"in QTCB bottom sent to the adapter %s\n",
@@ -3282,7 +3135,6 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_GOOD:
- ZFCP_LOG_FLAGS(3, "FSF_GOOD\n");
/* save LUN handle assigned by FSF */
unit->handle = header->lun_handle;
ZFCP_LOG_TRACE("unit 0x%016Lx on remote port 0x%016Lx on "
@@ -3293,7 +3145,9 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
unit->handle);
/* mark unit as open */
atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status);
-
+ atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
+ ZFCP_STATUS_COMMON_ACCESS_BOXED,
+ &unit->status);
if (adapter->supported_features & FSF_FEATURE_LUN_SHARING){
if (!exclusive)
atomic_set_mask(ZFCP_STATUS_UNIT_SHARED,
@@ -3437,7 +3291,6 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req)
switch (fsf_req->qtcb->header.fsf_status) {
case FSF_PORT_HANDLE_NOT_VALID:
- ZFCP_LOG_FLAGS(1, "FSF_PORT_HANDLE_NOT_VALID\n");
ZFCP_LOG_INFO("Temporary port identifier 0x%x for port "
"0x%016Lx on adapter %s invalid. This may "
"happen in rare circumstances\n",
@@ -3458,7 +3311,6 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_LUN_HANDLE_NOT_VALID:
- ZFCP_LOG_FLAGS(1, "FSF_LUN_HANDLE_NOT_VALID\n");
ZFCP_LOG_INFO("Temporary LUN identifier 0x%x of unit "
"0x%016Lx on port 0x%016Lx on adapter %s is "
"invalid. This may happen occasionally.\n",
@@ -3480,32 +3332,26 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_PORT_BOXED:
- ZFCP_LOG_FLAGS(2, "FSF_PORT_BOXED\n");
ZFCP_LOG_DEBUG("The remote port 0x%016Lx on adapter %s "
"needs to be reopened\n",
unit->port->wwpn,
zfcp_get_busid_by_unit(unit));
debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_pboxed");
- zfcp_erp_port_reopen(unit->port, 0);
+ zfcp_erp_port_boxed(unit->port);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR |
ZFCP_STATUS_FSFREQ_RETRY;
break;
case FSF_ADAPTER_STATUS_AVAILABLE:
- ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) {
case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
- ZFCP_LOG_FLAGS(2,
- "FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
/* re-establish link to port */
debug_text_event(fsf_req->adapter->erp_dbf, 1,
"fsf_sq_ltest");
- zfcp_erp_port_reopen(unit->port, 0);
+ zfcp_test_link(unit->port);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
- ZFCP_LOG_FLAGS(2,
- "FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED\n");
/* ERP strategy will escalate */
debug_text_event(fsf_req->adapter->erp_dbf, 1,
"fsf_sq_ulp");
@@ -3526,7 +3372,6 @@ zfcp_fsf_close_unit_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_GOOD:
- ZFCP_LOG_FLAGS(3, "FSF_GOOD\n");
ZFCP_LOG_TRACE("unit 0x%016Lx on port 0x%016Lx on adapter %s "
"closed, port handle 0x%x\n",
unit->fcp_lun,
@@ -3622,7 +3467,6 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
*/
switch (scsi_cmnd->sc_data_direction) {
case DMA_NONE:
- ZFCP_LOG_FLAGS(3, "DMA_NONE\n");
fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
/*
* FIXME(qdio):
@@ -3632,19 +3476,16 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter,
sbtype = SBAL_FLAGS0_TYPE_READ;
break;
case DMA_FROM_DEVICE:
- ZFCP_LOG_FLAGS(3, "DMA_FROM_DEVICE\n");
fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_READ;
sbtype = SBAL_FLAGS0_TYPE_READ;
fcp_cmnd_iu->rddata = 1;
break;
case DMA_TO_DEVICE:
- ZFCP_LOG_FLAGS(3, "DMA_TO_DEVICE\n");
fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_WRITE;
sbtype = SBAL_FLAGS0_TYPE_WRITE;
fcp_cmnd_iu->wddata = 1;
break;
case DMA_BIDIRECTIONAL:
- ZFCP_LOG_FLAGS(0, "DMA_BIDIRECTIONAL not supported\n");
default:
/*
* dummy, catch this condition earlier
@@ -3877,7 +3718,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
switch (header->fsf_status) {
case FSF_PORT_HANDLE_NOT_VALID:
- ZFCP_LOG_FLAGS(1, "FSF_PORT_HANDLE_NOT_VALID\n");
ZFCP_LOG_INFO("Temporary port identifier 0x%x for port "
"0x%016Lx on adapter %s invalid\n",
unit->port->handle,
@@ -3892,7 +3732,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_LUN_HANDLE_NOT_VALID:
- ZFCP_LOG_FLAGS(1, "FSF_LUN_HANDLE_NOT_VALID\n");
ZFCP_LOG_INFO("Temporary LUN identifier 0x%x for unit "
"0x%016Lx on port 0x%016Lx on adapter %s is "
"invalid. This may happen occasionally.\n",
@@ -3911,7 +3750,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_HANDLE_MISMATCH:
- ZFCP_LOG_FLAGS(0, "FSF_HANDLE_MISMATCH\n");
ZFCP_LOG_NORMAL("bug: The port handle 0x%x has changed "
"unexpectedly. (adapter %s, port 0x%016Lx, "
"unit 0x%016Lx)\n",
@@ -3934,7 +3772,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_SERVICE_CLASS_NOT_SUPPORTED:
- ZFCP_LOG_FLAGS(0, "FSF_SERVICE_CLASS_NOT_SUPPORTED\n");
if (fsf_req->adapter->fc_service_class <= 3) {
ZFCP_LOG_NORMAL("error: The adapter %s does "
"not support fibrechannel class %d.\n",
@@ -3959,7 +3796,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_FCPLUN_NOT_VALID:
- ZFCP_LOG_FLAGS(0, "FSF_FCPLUN_NOT_VALID\n");
ZFCP_LOG_NORMAL("bug: unit 0x%016Lx on port 0x%016Lx on "
"adapter %s does not have correct unit "
"handle 0x%x\n",
@@ -3982,7 +3818,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_ACCESS_DENIED:
- ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n");
ZFCP_LOG_NORMAL("Access denied, cannot send FCP command to "
"unit 0x%016Lx on port 0x%016Lx on "
"adapter %s\n", unit->fcp_lun, unit->port->wwpn,
@@ -4006,7 +3841,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_DIRECTION_INDICATOR_NOT_VALID:
- ZFCP_LOG_FLAGS(0, "FSF_DIRECTION_INDICATOR_NOT_VALID\n");
ZFCP_LOG_INFO("bug: Invalid data direction given for unit "
"0x%016Lx on port 0x%016Lx on adapter %s "
"(debug info %d)\n",
@@ -4026,7 +3860,6 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_CMND_LENGTH_NOT_VALID:
- ZFCP_LOG_FLAGS(0, "FSF_CMND_LENGTH_NOT_VALID\n");
ZFCP_LOG_NORMAL
("bug: An invalid control-data-block length field "
"was found in a command for unit 0x%016Lx on port "
@@ -4046,69 +3879,43 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_PORT_BOXED:
- ZFCP_LOG_FLAGS(2, "FSF_PORT_BOXED\n");
ZFCP_LOG_DEBUG("The remote port 0x%016Lx on adapter %s "
"needs to be reopened\n",
unit->port->wwpn, zfcp_get_busid_by_unit(unit));
debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_pboxed");
- zfcp_erp_port_reopen(unit->port, 0);
- zfcp_cmd_dbf_event_fsf("portbox", fsf_req,
- &header->fsf_status_qual,
- sizeof (union fsf_status_qual));
+ zfcp_erp_port_boxed(unit->port);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR |
ZFCP_STATUS_FSFREQ_RETRY;
break;
case FSF_LUN_BOXED:
- ZFCP_LOG_FLAGS(0, "FSF_LUN_BOXED\n");
ZFCP_LOG_NORMAL("unit needs to be reopened (adapter %s, "
"wwpn=0x%016Lx, fcp_lun=0x%016Lx)\n",
zfcp_get_busid_by_unit(unit),
unit->port->wwpn, unit->fcp_lun);
debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_lboxed");
- zfcp_erp_unit_reopen(unit, 0);
- zfcp_cmd_dbf_event_fsf("unitbox", fsf_req,
- &header->fsf_status_qual,
- sizeof(union fsf_status_qual));
+ zfcp_erp_unit_boxed(unit);
fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR
| ZFCP_STATUS_FSFREQ_RETRY;
break;
case FSF_ADAPTER_STATUS_AVAILABLE:
- ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
switch (header->fsf_status_qual.word[0]) {
case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
- ZFCP_LOG_FLAGS(2,
- "FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
/* re-establish link to port */
debug_text_event(fsf_req->adapter->erp_dbf, 1,
"fsf_sq_ltest");
- zfcp_erp_port_reopen(unit->port, 0);
- zfcp_cmd_dbf_event_fsf(
- "sqltest",
- fsf_req,
- &header->fsf_status_qual,
- sizeof (union fsf_status_qual));
- fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ zfcp_test_link(unit->port);
break;
case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
- ZFCP_LOG_FLAGS(3,
- "FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED\n");
/* FIXME(hw) need proper specs for proper action */
/* let scsi stack deal with retries and escalation */
debug_text_event(fsf_req->adapter->erp_dbf, 1,
"fsf_sq_ulp");
- zfcp_cmd_dbf_event_fsf(
- "sqdeperp",
- fsf_req,
- &header->fsf_status_qual,
- sizeof (union fsf_status_qual));
- fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
default:
- /* FIXME: shall we consider this a successful transfer? */
ZFCP_LOG_NORMAL
- ("bug: Wrong status qualifier 0x%x arrived.\n",
+ ("Unknown status qualifier 0x%x arrived.\n",
header->fsf_status_qual.word[0]);
debug_text_event(fsf_req->adapter->erp_dbf, 0,
"fsf_sq_inval:");
@@ -4117,14 +3924,13 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req)
sizeof(u32));
break;
}
+ fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_GOOD:
- ZFCP_LOG_FLAGS(3, "FSF_GOOD\n");
break;
case FSF_FCP_RSP_AVAILABLE:
- ZFCP_LOG_FLAGS(2, "FSF_FCP_RSP_AVAILABLE\n");
break;
default:
@@ -4217,14 +4023,12 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
ZFCP_LOG_DEBUG("rsp_len is valid\n");
switch (fcp_rsp_info[3]) {
case RSP_CODE_GOOD:
- ZFCP_LOG_FLAGS(3, "RSP_CODE_GOOD\n");
/* ok, continue */
ZFCP_LOG_TRACE("no failure or Task Management "
"Function complete\n");
set_host_byte(&scpnt->result, DID_OK);
break;
case RSP_CODE_LENGTH_MISMATCH:
- ZFCP_LOG_FLAGS(0, "RSP_CODE_LENGTH_MISMATCH\n");
/* hardware bug */
ZFCP_LOG_NORMAL("bug: FCP response code indictates "
"that the fibrechannel protocol data "
@@ -4242,7 +4046,6 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
set_host_byte(&scpnt->result, DID_ERROR);
goto skip_fsfstatus;
case RSP_CODE_FIELD_INVALID:
- ZFCP_LOG_FLAGS(0, "RSP_CODE_FIELD_INVALID\n");
/* driver or hardware bug */
ZFCP_LOG_NORMAL("bug: FCP response code indictates "
"that the fibrechannel protocol data "
@@ -4261,7 +4064,6 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
zfcp_cmd_dbf_event_fsf("codeinv", fsf_req, NULL, 0);
goto skip_fsfstatus;
case RSP_CODE_RO_MISMATCH:
- ZFCP_LOG_FLAGS(0, "RSP_CODE_RO_MISMATCH\n");
/* hardware bug */
ZFCP_LOG_NORMAL("bug: The FCP response code indicates "
"that conflicting values for the "
@@ -4407,13 +4209,11 @@ zfcp_fsf_send_fcp_command_task_management_handler(struct zfcp_fsf_req *fsf_req)
/* check FCP_RSP_INFO */
switch (fcp_rsp_info[3]) {
case RSP_CODE_GOOD:
- ZFCP_LOG_FLAGS(3, "RSP_CODE_GOOD\n");
/* ok, continue */
ZFCP_LOG_DEBUG("no failure or Task Management "
"Function complete\n");
break;
case RSP_CODE_TASKMAN_UNSUPP:
- ZFCP_LOG_FLAGS(0, "RSP_CODE_TASKMAN_UNSUPP\n");
ZFCP_LOG_NORMAL("bug: A reuested task management function "
"is not supported on the target device "
"unit 0x%016Lx, port 0x%016Lx, adapter %s\n ",
@@ -4423,7 +4223,6 @@ zfcp_fsf_send_fcp_command_task_management_handler(struct zfcp_fsf_req *fsf_req)
fsf_req->status |= ZFCP_STATUS_FSFREQ_TMFUNCNOTSUPP;
break;
case RSP_CODE_TASKMAN_FAILED:
- ZFCP_LOG_FLAGS(0, "RSP_CODE_TASKMAN_FAILED\n");
ZFCP_LOG_NORMAL("bug: A reuested task management function "
"failed to complete successfully. "
"unit 0x%016Lx, port 0x%016Lx, adapter %s.\n",
@@ -4610,7 +4409,6 @@ zfcp_fsf_control_file_handler(struct zfcp_fsf_req *fsf_req)
switch (header->fsf_status) {
case FSF_GOOD:
- ZFCP_LOG_FLAGS(2, "FSF_GOOD\n");
ZFCP_LOG_NORMAL(
"The FSF request has been successfully completed "
"on the adapter %s\n",
@@ -4618,7 +4416,6 @@ zfcp_fsf_control_file_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_OPERATION_PARTIALLY_SUCCESSFUL:
- ZFCP_LOG_FLAGS(2, "FSF_OPERATION_PARTIALLY_SUCCESSFUL\n");
if (bottom->operation_subtype == FSF_CFDC_OPERATION_SUBTYPE) {
switch (header->fsf_status_qual.word[0]) {
@@ -4655,7 +4452,6 @@ zfcp_fsf_control_file_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_AUTHORIZATION_FAILURE:
- ZFCP_LOG_FLAGS(2, "FSF_AUTHORIZATION_FAILURE\n");
ZFCP_LOG_NORMAL(
"Adapter %s does not accept privileged commands\n",
zfcp_get_busid_by_adapter(adapter));
@@ -4664,7 +4460,6 @@ zfcp_fsf_control_file_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_CFDC_ERROR_DETECTED:
- ZFCP_LOG_FLAGS(2, "FSF_CFDC_ERROR_DETECTED\n");
ZFCP_LOG_NORMAL(
"Error at position %d in the CFDC, "
"CFDC is discarded by the adapter %s\n",
@@ -4675,7 +4470,6 @@ zfcp_fsf_control_file_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_CONTROL_FILE_UPDATE_ERROR:
- ZFCP_LOG_FLAGS(2, "FSF_CONTROL_FILE_UPDATE_ERROR\n");
ZFCP_LOG_NORMAL(
"Adapter %s cannot harden the control file, "
"file is discarded\n",
@@ -4685,7 +4479,6 @@ zfcp_fsf_control_file_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_CONTROL_FILE_TOO_LARGE:
- ZFCP_LOG_FLAGS(2, "FSF_CONTROL_FILE_TOO_LARGE\n");
ZFCP_LOG_NORMAL(
"Control file is too large, file is discarded "
"by the adapter %s\n",
@@ -4695,7 +4488,6 @@ zfcp_fsf_control_file_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_ACCESS_CONFLICT_DETECTED:
- ZFCP_LOG_FLAGS(2, "FSF_ACCESS_CONFLICT_DETECTED\n");
if (bottom->operation_subtype == FSF_CFDC_OPERATION_SUBTYPE)
ZFCP_LOG_NORMAL(
"CFDC has been discarded by the adapter %s, "
@@ -4708,7 +4500,6 @@ zfcp_fsf_control_file_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_CONFLICTS_OVERRULED:
- ZFCP_LOG_FLAGS(2, "FSF_CONFLICTS_OVERRULED\n");
if (bottom->operation_subtype == FSF_CFDC_OPERATION_SUBTYPE)
ZFCP_LOG_NORMAL(
"CFDC has been activated on the adapter %s, "
@@ -4721,7 +4512,6 @@ zfcp_fsf_control_file_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_UNKNOWN_OP_SUBTYPE:
- ZFCP_LOG_FLAGS(2, "FSF_UNKNOWN_OP_SUBTYPE\n");
ZFCP_LOG_NORMAL("unknown operation subtype (adapter: %s, "
"op_subtype=0x%x)\n",
zfcp_get_busid_by_adapter(adapter),
@@ -4731,7 +4521,6 @@ zfcp_fsf_control_file_handler(struct zfcp_fsf_req *fsf_req)
break;
case FSF_INVALID_COMMAND_OPTION:
- ZFCP_LOG_FLAGS(2, "FSF_INVALID_COMMAND_OPTION\n");
ZFCP_LOG_NORMAL(
"Invalid option 0x%x has been specified "
"in QTCB bottom sent to the adapter %s\n",
@@ -4800,7 +4589,7 @@ zfcp_fsf_req_wait_and_cleanup(struct zfcp_fsf_req *fsf_req,
*status = fsf_req->status;
/* cleanup request */
- zfcp_fsf_req_cleanup(fsf_req);
+ zfcp_fsf_req_free(fsf_req);
out:
return retval;
}
@@ -4999,9 +4788,9 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
inc_seq_no = 0;
/* put allocated FSF request at list tail */
- write_lock_irqsave(&adapter->fsf_req_list_lock, flags);
+ spin_lock_irqsave(&adapter->fsf_req_list_lock, flags);
list_add_tail(&fsf_req->list, &adapter->fsf_req_list_head);
- write_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
+ spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
/* figure out expiration time of timeout and start timeout */
if (unlikely(timer)) {
@@ -5045,9 +4834,9 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
*/
if (timer)
del_timer(timer);
- write_lock_irqsave(&adapter->fsf_req_list_lock, flags);
+ spin_lock_irqsave(&adapter->fsf_req_list_lock, flags);
list_del(&fsf_req->list);
- write_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
+ spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
/*
* adjust the number of free SBALs in request queue as well as
* position of first one
@@ -5085,25 +4874,4 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
return retval;
}
-/*
- * function: zfcp_fsf_req_cleanup
- *
- * purpose: cleans up an FSF request and removes it from the specified list
- *
- * returns:
- *
- * assumption: no pending SB in SBALEs other than QTCB
- */
-void
-zfcp_fsf_req_cleanup(struct zfcp_fsf_req *fsf_req)
-{
- struct zfcp_adapter *adapter = fsf_req->adapter;
- unsigned long flags;
-
- write_lock_irqsave(&adapter->fsf_req_list_lock, flags);
- list_del(&fsf_req->list);
- write_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
- zfcp_fsf_req_free(fsf_req);
-}
-
#undef ZFCP_LOG_AREA
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index 06e862d7bc9..24e16ec331d 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -229,52 +229,14 @@ zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter,
ZFCP_LOG_TRACE("status is"
" QDIO_STATUS_OUTBOUND_INT \n");
}
- } // if (ZFCP_LOG_CHECK(ZFCP_LOG_LEVEL_TRACE))
+ }
if (unlikely(status & QDIO_STATUS_LOOK_FOR_ERROR)) {
retval = -EIO;
- ZFCP_LOG_FLAGS(1, "QDIO_STATUS_LOOK_FOR_ERROR \n");
-
ZFCP_LOG_INFO("QDIO problem occurred (status=0x%x, "
"qdio_error=0x%x, siga_error=0x%x)\n",
status, qdio_error, siga_error);
- if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION) {
- ZFCP_LOG_FLAGS(2,
- "QDIO_STATUS_ACTIVATE_CHECK_CONDITION\n");
- }
- if (status & QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR) {
- ZFCP_LOG_FLAGS(2,
- "QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR\n");
- }
- if (status & QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR) {
- ZFCP_LOG_FLAGS(2,
- "QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR\n");
- }
-
- if (siga_error & QDIO_SIGA_ERROR_ACCESS_EXCEPTION) {
- ZFCP_LOG_FLAGS(2, "QDIO_SIGA_ERROR_ACCESS_EXCEPTION\n");
- }
-
- if (siga_error & QDIO_SIGA_ERROR_B_BIT_SET) {
- ZFCP_LOG_FLAGS(2, "QDIO_SIGA_ERROR_B_BIT_SET\n");
- }
-
- switch (qdio_error) {
- case 0:
- ZFCP_LOG_FLAGS(3, "QDIO_OK");
- break;
- case SLSB_P_INPUT_ERROR:
- ZFCP_LOG_FLAGS(1, "SLSB_P_INPUT_ERROR\n");
- break;
- case SLSB_P_OUTPUT_ERROR:
- ZFCP_LOG_FLAGS(1, "SLSB_P_OUTPUT_ERROR\n");
- break;
- default:
- ZFCP_LOG_NORMAL("bug: unknown QDIO error 0x%x\n",
- qdio_error);
- break;
- }
/* Restarting IO on the failed adapter from scratch */
debug_text_event(adapter->erp_dbf, 1, "qdio_err");
/*
@@ -484,37 +446,37 @@ int
zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, void *sbale_addr)
{
struct zfcp_fsf_req *fsf_req;
- int retval = 0;
/* invalid (per convention used in this driver) */
if (unlikely(!sbale_addr)) {
ZFCP_LOG_NORMAL("bug: invalid reqid\n");
- retval = -EINVAL;
- goto out;
+ return -EINVAL;
}
/* valid request id and thus (hopefully :) valid fsf_req address */
fsf_req = (struct zfcp_fsf_req *) sbale_addr;
+ /* serialize with zfcp_fsf_req_dismiss_all */
+ spin_lock(&adapter->fsf_req_list_lock);
+ if (list_empty(&adapter->fsf_req_list_head)) {
+ spin_unlock(&adapter->fsf_req_list_lock);
+ return 0;
+ }
+ list_del(&fsf_req->list);
+ atomic_dec(&adapter->fsf_reqs_active);
+ spin_unlock(&adapter->fsf_req_list_lock);
+
if (unlikely(adapter != fsf_req->adapter)) {
ZFCP_LOG_NORMAL("bug: invalid reqid (fsf_req=%p, "
"fsf_req->adapter=%p, adapter=%p)\n",
fsf_req, fsf_req->adapter, adapter);
- retval = -EINVAL;
- goto out;
- }
-
- ZFCP_LOG_TRACE("fsf_req at %p, QTCB at %p\n", fsf_req, fsf_req->qtcb);
- if (likely(fsf_req->qtcb)) {
- ZFCP_LOG_TRACE("hex dump of QTCB:\n");
- ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) fsf_req->qtcb,
- sizeof(struct fsf_qtcb));
+ return -EINVAL;
}
/* finish the FSF request */
zfcp_fsf_req_complete(fsf_req);
- out:
- return retval;
+
+ return 0;
}
/**
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index e21b547fd42..b61d309352c 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -433,7 +433,7 @@ zfcp_port_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id)
* FAILED - otherwise
*/
int
-zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
+__zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
{
int retval = SUCCESS;
struct zfcp_fsf_req *new_fsf_req, *old_fsf_req;
@@ -575,7 +575,7 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
*(u64 *) & new_fsf_req->qtcb->header.fsf_status_qual.word[0];
dbf_fsf_qual[1] =
*(u64 *) & new_fsf_req->qtcb->header.fsf_status_qual.word[2];
- zfcp_fsf_req_cleanup(new_fsf_req);
+ zfcp_fsf_req_free(new_fsf_req);
#else
retval = zfcp_fsf_req_wait_and_cleanup(new_fsf_req,
ZFCP_UNINTERRUPTIBLE, &status);
@@ -611,6 +611,17 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
return retval;
}
+int
+zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
+{
+ int rc;
+ struct Scsi_Host *scsi_host = scpnt->device->host;
+ spin_lock_irq(scsi_host->host_lock);
+ rc = __zfcp_scsi_eh_abort_handler(scpnt);
+ spin_unlock_irq(scsi_host->host_lock);
+ return rc;
+}
+
/*
* function: zfcp_scsi_eh_device_reset_handler
*
@@ -625,8 +636,6 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata;
struct Scsi_Host *scsi_host = scpnt->device->host;
- spin_unlock_irq(scsi_host->host_lock);
-
if (!unit) {
ZFCP_LOG_NORMAL("bug: Tried reset for nonexistent unit\n");
retval = SUCCESS;
@@ -669,7 +678,6 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
retval = SUCCESS;
}
out:
- spin_lock_irq(scsi_host->host_lock);
return retval;
}
@@ -723,8 +731,6 @@ zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *scpnt)
struct zfcp_unit *unit;
struct Scsi_Host *scsi_host = scpnt->device->host;
- spin_unlock_irq(scsi_host->host_lock);
-
unit = (struct zfcp_unit *) scpnt->device->hostdata;
ZFCP_LOG_NORMAL("bus reset because of problems with "
"unit 0x%016Lx\n", unit->fcp_lun);
@@ -732,7 +738,6 @@ zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *scpnt)
zfcp_erp_wait(unit->port->adapter);
retval = SUCCESS;
- spin_lock_irq(scsi_host->host_lock);
return retval;
}
@@ -750,8 +755,6 @@ zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
struct zfcp_unit *unit;
struct Scsi_Host *scsi_host = scpnt->device->host;
- spin_unlock_irq(scsi_host->host_lock);
-
unit = (struct zfcp_unit *) scpnt->device->hostdata;
ZFCP_LOG_NORMAL("host reset because of problems with "
"unit 0x%016Lx\n", unit->fcp_lun);
@@ -759,7 +762,6 @@ zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
zfcp_erp_wait(unit->port->adapter);
retval = SUCCESS;
- spin_lock_irq(scsi_host->host_lock);
return retval;
}
@@ -922,7 +924,7 @@ struct fc_function_template zfcp_transport_functions = {
* Generates attribute for a unit.
*/
#define ZFCP_DEFINE_SCSI_ATTR(_name, _format, _value) \
-static ssize_t zfcp_sysfs_scsi_##_name##_show(struct device *dev, \
+static ssize_t zfcp_sysfs_scsi_##_name##_show(struct device *dev, struct device_attribute *attr, \
char *buf) \
{ \
struct scsi_device *sdev; \
diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c
index 23e2dca55bb..e7345a74800 100644
--- a/drivers/s390/scsi/zfcp_sysfs_adapter.c
+++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c
@@ -50,7 +50,7 @@ static const char fc_topologies[5][25] = {
* Generates attributes for an adapter.
*/
#define ZFCP_DEFINE_ADAPTER_ATTR(_name, _format, _value) \
-static ssize_t zfcp_sysfs_adapter_##_name##_show(struct device *dev, \
+static ssize_t zfcp_sysfs_adapter_##_name##_show(struct device *dev, struct device_attribute *attr, \
char *buf) \
{ \
struct zfcp_adapter *adapter; \
@@ -90,7 +90,7 @@ ZFCP_DEFINE_ADAPTER_ATTR(in_recovery, "%d\n", atomic_test_mask
* Store function of the "port_add" attribute of an adapter.
*/
static ssize_t
-zfcp_sysfs_port_add_store(struct device *dev, const char *buf, size_t count)
+zfcp_sysfs_port_add_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
wwn_t wwpn;
char *endp;
@@ -135,7 +135,7 @@ static DEVICE_ATTR(port_add, S_IWUSR, NULL, zfcp_sysfs_port_add_store);
* Store function of the "port_remove" attribute of an adapter.
*/
static ssize_t
-zfcp_sysfs_port_remove_store(struct device *dev, const char *buf, size_t count)
+zfcp_sysfs_port_remove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct zfcp_adapter *adapter;
struct zfcp_port *port;
@@ -196,7 +196,7 @@ static DEVICE_ATTR(port_remove, S_IWUSR, NULL, zfcp_sysfs_port_remove_store);
* started for the belonging adapter.
*/
static ssize_t
-zfcp_sysfs_adapter_failed_store(struct device *dev,
+zfcp_sysfs_adapter_failed_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct zfcp_adapter *adapter;
@@ -236,7 +236,7 @@ zfcp_sysfs_adapter_failed_store(struct device *dev,
* "0" if adapter is working, otherwise "1".
*/
static ssize_t
-zfcp_sysfs_adapter_failed_show(struct device *dev, char *buf)
+zfcp_sysfs_adapter_failed_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct zfcp_adapter *adapter;
diff --git a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c
index 6aafb2abb4b..7a84c7d474d 100644
--- a/drivers/s390/scsi/zfcp_sysfs_port.c
+++ b/drivers/s390/scsi/zfcp_sysfs_port.c
@@ -53,7 +53,7 @@ zfcp_sysfs_port_release(struct device *dev)
* Generates attributes for a port.
*/
#define ZFCP_DEFINE_PORT_ATTR(_name, _format, _value) \
-static ssize_t zfcp_sysfs_port_##_name##_show(struct device *dev, \
+static ssize_t zfcp_sysfs_port_##_name##_show(struct device *dev, struct device_attribute *attr, \
char *buf) \
{ \
struct zfcp_port *port; \
@@ -82,7 +82,7 @@ ZFCP_DEFINE_PORT_ATTR(access_denied, "%d\n", atomic_test_mask
* Store function of the "unit_add" attribute of a port.
*/
static ssize_t
-zfcp_sysfs_unit_add_store(struct device *dev, const char *buf, size_t count)
+zfcp_sysfs_unit_add_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
fcp_lun_t fcp_lun;
char *endp;
@@ -125,7 +125,7 @@ static DEVICE_ATTR(unit_add, S_IWUSR, NULL, zfcp_sysfs_unit_add_store);
* @count: number of bytes in buffer
*/
static ssize_t
-zfcp_sysfs_unit_remove_store(struct device *dev, const char *buf, size_t count)
+zfcp_sysfs_unit_remove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct zfcp_port *port;
struct zfcp_unit *unit;
@@ -186,7 +186,7 @@ static DEVICE_ATTR(unit_remove, S_IWUSR, NULL, zfcp_sysfs_unit_remove_store);
* started for the belonging port.
*/
static ssize_t
-zfcp_sysfs_port_failed_store(struct device *dev, const char *buf, size_t count)
+zfcp_sysfs_port_failed_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct zfcp_port *port;
unsigned int val;
@@ -224,7 +224,7 @@ zfcp_sysfs_port_failed_store(struct device *dev, const char *buf, size_t count)
* "0" if port is working, otherwise "1".
*/
static ssize_t
-zfcp_sysfs_port_failed_show(struct device *dev, char *buf)
+zfcp_sysfs_port_failed_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct zfcp_port *port;
diff --git a/drivers/s390/scsi/zfcp_sysfs_unit.c b/drivers/s390/scsi/zfcp_sysfs_unit.c
index 87c0b461831..0556642c9e1 100644
--- a/drivers/s390/scsi/zfcp_sysfs_unit.c
+++ b/drivers/s390/scsi/zfcp_sysfs_unit.c
@@ -53,7 +53,7 @@ zfcp_sysfs_unit_release(struct device *dev)
* Generates attribute for a unit.
*/
#define ZFCP_DEFINE_UNIT_ATTR(_name, _format, _value) \
-static ssize_t zfcp_sysfs_unit_##_name##_show(struct device *dev, \
+static ssize_t zfcp_sysfs_unit_##_name##_show(struct device *dev, struct device_attribute *attr, \
char *buf) \
{ \
struct zfcp_unit *unit; \
@@ -86,7 +86,7 @@ ZFCP_DEFINE_UNIT_ATTR(access_readonly, "%d\n", atomic_test_mask
* started for the belonging unit.
*/
static ssize_t
-zfcp_sysfs_unit_failed_store(struct device *dev, const char *buf, size_t count)
+zfcp_sysfs_unit_failed_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct zfcp_unit *unit;
unsigned int val;
@@ -123,7 +123,7 @@ zfcp_sysfs_unit_failed_store(struct device *dev, const char *buf, size_t count)
* "0" if unit is working, otherwise "1".
*/
static ssize_t
-zfcp_sysfs_unit_failed_show(struct device *dev, char *buf)
+zfcp_sysfs_unit_failed_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct zfcp_unit *unit;
diff --git a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c
index e5fa1703856..650d5e924f4 100644
--- a/drivers/sbus/char/aurora.c
+++ b/drivers/sbus/char/aurora.c
@@ -81,10 +81,6 @@ unsigned char irqs[4] = {
int irqhit=0;
#endif
-#ifndef MIN
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
static struct tty_driver *aurora_driver;
static struct Aurora_board aurora_board[AURORA_NBOARD] = {
{0,},
@@ -594,7 +590,7 @@ static void aurora_transmit(struct Aurora_board const * bp, int chip)
&bp->r[chip]->r[CD180_TDR]);
port->COR2 &= ~COR2_ETC;
}
- count = MIN(port->break_length, 0xff);
+ count = min(port->break_length, 0xff);
sbus_writeb(CD180_C_ESC,
&bp->r[chip]->r[CD180_TDR]);
sbus_writeb(CD180_C_DELAY,
@@ -1575,7 +1571,7 @@ static int aurora_write(struct tty_struct * tty,
save_flags(flags);
while (1) {
cli();
- c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+ c = min(count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
SERIAL_XMIT_SIZE - port->xmit_head));
if (c <= 0) {
restore_flags(flags);
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index a2b18f5a4f9..34dbc37a79d 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -1695,8 +1695,6 @@ static int twa_scsi_eh_reset(struct scsi_cmnd *SCpnt)
tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
- spin_unlock_irq(tw_dev->host->host_lock);
-
tw_dev->num_resets++;
printk(KERN_WARNING "3w-9xxx: scsi%d: WARNING: (0x%02X:0x%04X): Unit #%d: Command (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, TW_DRIVER, 0x2c, SCpnt->device->id, SCpnt->cmnd[0]);
@@ -1709,7 +1707,6 @@ static int twa_scsi_eh_reset(struct scsi_cmnd *SCpnt)
retval = SUCCESS;
out:
- spin_lock_irq(tw_dev->host->host_lock);
return retval;
} /* End twa_scsi_eh_reset() */
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 48f9ece1cbd..b6dc576da43 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -1430,8 +1430,6 @@ static int tw_scsi_eh_reset(struct scsi_cmnd *SCpnt)
tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
- spin_unlock_irq(tw_dev->host->host_lock);
-
tw_dev->num_resets++;
printk(KERN_WARNING "3w-xxxx: scsi%d: WARNING: Unit #%d: Command (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, SCpnt->device->id, SCpnt->cmnd[0]);
@@ -1444,7 +1442,6 @@ static int tw_scsi_eh_reset(struct scsi_cmnd *SCpnt)
retval = SUCCESS;
out:
- spin_lock_irq(tw_dev->host->host_lock);
return retval;
} /* End tw_scsi_eh_reset() */
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index 4b1bb529f67..a7620fc368e 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -170,7 +170,6 @@ MODULE_LICENSE("GPL");
STATIC int NCR_700_queuecommand(struct scsi_cmnd *, void (*done)(struct scsi_cmnd *));
STATIC int NCR_700_abort(struct scsi_cmnd * SCpnt);
STATIC int NCR_700_bus_reset(struct scsi_cmnd * SCpnt);
-STATIC int NCR_700_dev_reset(struct scsi_cmnd * SCpnt);
STATIC int NCR_700_host_reset(struct scsi_cmnd * SCpnt);
STATIC void NCR_700_chip_setup(struct Scsi_Host *host);
STATIC void NCR_700_chip_reset(struct Scsi_Host *host);
@@ -330,7 +329,6 @@ NCR_700_detect(struct scsi_host_template *tpnt,
/* Fill in the missing routines from the host template */
tpnt->queuecommand = NCR_700_queuecommand;
tpnt->eh_abort_handler = NCR_700_abort;
- tpnt->eh_device_reset_handler = NCR_700_dev_reset;
tpnt->eh_bus_reset_handler = NCR_700_bus_reset;
tpnt->eh_host_reset_handler = NCR_700_host_reset;
tpnt->can_queue = NCR_700_COMMAND_SLOTS_PER_HOST;
@@ -1959,34 +1957,31 @@ NCR_700_bus_reset(struct scsi_cmnd * SCp)
printk(KERN_INFO "scsi%d (%d:%d) New error handler wants BUS reset, cmd %p\n\t",
SCp->device->host->host_no, SCp->device->id, SCp->device->lun, SCp);
scsi_print_command(SCp);
+
/* In theory, eh_complete should always be null because the
* eh is single threaded, but just in case we're handling a
* reset via sg or something */
- while(hostdata->eh_complete != NULL) {
+ spin_lock_irq(SCp->device->host->host_lock);
+ while (hostdata->eh_complete != NULL) {
spin_unlock_irq(SCp->device->host->host_lock);
msleep_interruptible(100);
spin_lock_irq(SCp->device->host->host_lock);
}
+
hostdata->eh_complete = &complete;
NCR_700_internal_bus_reset(SCp->device->host);
+
spin_unlock_irq(SCp->device->host->host_lock);
wait_for_completion(&complete);
spin_lock_irq(SCp->device->host->host_lock);
+
hostdata->eh_complete = NULL;
/* Revalidate the transport parameters of the failing device */
if(hostdata->fast)
spi_schedule_dv_device(SCp->device);
- return SUCCESS;
-}
-STATIC int
-NCR_700_dev_reset(struct scsi_cmnd * SCp)
-{
- printk(KERN_INFO "scsi%d (%d:%d) New error handler wants device reset\n\t",
- SCp->device->host->host_no, SCp->device->id, SCp->device->lun);
- scsi_print_command(SCp);
-
- return FAILED;
+ spin_unlock_irq(SCp->device->host->host_lock);
+ return SUCCESS;
}
STATIC int
@@ -1996,8 +1991,13 @@ NCR_700_host_reset(struct scsi_cmnd * SCp)
SCp->device->host->host_no, SCp->device->id, SCp->device->lun);
scsi_print_command(SCp);
+ spin_lock_irq(SCp->device->host->host_lock);
+
NCR_700_internal_bus_reset(SCp->device->host);
NCR_700_chip_reset(SCp->device->host);
+
+ spin_unlock_irq(SCp->device->host->host_lock);
+
return SUCCESS;
}
@@ -2125,7 +2125,7 @@ static int NCR_700_change_queue_type(struct scsi_device *SDp, int tag_type)
}
static ssize_t
-NCR_700_show_active_tags(struct device *dev, char *buf)
+NCR_700_show_active_tags(struct device *dev, struct device_attribute *attr, char *buf)
{
struct scsi_device *SDp = to_scsi_device(dev);
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index 15e4b122d56..9d6040bfa06 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -2746,9 +2746,15 @@ static int BusLogic_host_reset(struct scsi_cmnd * SCpnt)
unsigned int id = SCpnt->device->id;
struct BusLogic_TargetStatistics *stats = &HostAdapter->TargetStatistics[id];
+ int rc;
+
+ spin_lock_irq(SCpnt->device->host->host_lock);
+
BusLogic_IncrementErrorCounter(&stats->HostAdapterResetsRequested);
- return BusLogic_ResetHostAdapter(HostAdapter, false);
+ rc = BusLogic_ResetHostAdapter(HostAdapter, false);
+ spin_unlock_irq(SCpnt->device->host->host_lock);
+ return rc;
}
/*
diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c
index 56a695c6ab5..5beed4f6d98 100644
--- a/drivers/scsi/FlashPoint.c
+++ b/drivers/scsi/FlashPoint.c
@@ -22,8 +22,6 @@
#ifndef CONFIG_SCSI_OMIT_FLASHPOINT
-#define UNIX
-#define FW_TYPE _SCCB_MGR_
#define MAX_CARDS 8
#undef BUSTYPE_PCI
@@ -34,8 +32,6 @@
#define OS_OutPortByte(port, value) outb(value, port)
#define OS_OutPortWord(port, value) outw(value, port)
#define OS_OutPortLong(port, value) outl(value, port)
-#define OS_Lock(x)
-#define OS_UnLock(x)
/*
@@ -51,164 +47,17 @@
#define SccbMgr_isr FlashPoint_HandleInterrupt
-/*
- Define name replacements to avoid kernel namespace pollution.
-*/
-
-#define BL_Card FPT_BL_Card
-#define BusMasterInit FPT_BusMasterInit
-#define CalcCrc16 FPT_CalcCrc16
-#define CalcLrc FPT_CalcLrc
-#define ChkIfChipInitialized FPT_ChkIfChipInitialized
-#define DiagBusMaster FPT_DiagBusMaster
-#define DiagEEPROM FPT_DiagEEPROM
-#define DiagXbow FPT_DiagXbow
-#define GetTarLun FPT_GetTarLun
-#define RNVRamData FPT_RNVRamData
-#define RdStack FPT_RdStack
-#define SccbMgrTableInitAll FPT_SccbMgrTableInitAll
-#define SccbMgrTableInitCard FPT_SccbMgrTableInitCard
-#define SccbMgrTableInitTarget FPT_SccbMgrTableInitTarget
-#define SccbMgr_bad_isr FPT_SccbMgr_bad_isr
-#define SccbMgr_scsi_reset FPT_SccbMgr_scsi_reset
-#define SccbMgr_timer_expired FPT_SccbMgr_timer_expired
-#define SendMsg FPT_SendMsg
-#define Wait FPT_Wait
-#define Wait1Second FPT_Wait1Second
-#define WrStack FPT_WrStack
-#define XbowInit FPT_XbowInit
-#define autoCmdCmplt FPT_autoCmdCmplt
-#define autoLoadDefaultMap FPT_autoLoadDefaultMap
-#define busMstrDataXferStart FPT_busMstrDataXferStart
-#define busMstrSGDataXferStart FPT_busMstrSGDataXferStart
-#define busMstrTimeOut FPT_busMstrTimeOut
-#define dataXferProcessor FPT_dataXferProcessor
-#define default_intena FPT_default_intena
-#define hostDataXferAbort FPT_hostDataXferAbort
-#define hostDataXferRestart FPT_hostDataXferRestart
-#define inisci FPT_inisci
-#define mbCards FPT_mbCards
-#define nvRamInfo FPT_nvRamInfo
-#define phaseBusFree FPT_phaseBusFree
-#define phaseChkFifo FPT_phaseChkFifo
-#define phaseCommand FPT_phaseCommand
-#define phaseDataIn FPT_phaseDataIn
-#define phaseDataOut FPT_phaseDataOut
-#define phaseDecode FPT_phaseDecode
-#define phaseIllegal FPT_phaseIllegal
-#define phaseMsgIn FPT_phaseMsgIn
-#define phaseMsgOut FPT_phaseMsgOut
-#define phaseStatus FPT_phaseStatus
-#define queueAddSccb FPT_queueAddSccb
-#define queueCmdComplete FPT_queueCmdComplete
-#define queueDisconnect FPT_queueDisconnect
-#define queueFindSccb FPT_queueFindSccb
-#define queueFlushSccb FPT_queueFlushSccb
-#define queueFlushTargSccb FPT_queueFlushTargSccb
-#define queueSearchSelect FPT_queueSearchSelect
-#define queueSelectFail FPT_queueSelectFail
-#define s_PhaseTbl FPT_s_PhaseTbl
-#define scamHAString FPT_scamHAString
-#define scamInfo FPT_scamInfo
-#define scarb FPT_scarb
-#define scasid FPT_scasid
-#define scbusf FPT_scbusf
-#define sccbMgrTbl FPT_sccbMgrTbl
-#define schkdd FPT_schkdd
-#define scini FPT_scini
-#define sciso FPT_sciso
-#define scmachid FPT_scmachid
-#define scsavdi FPT_scsavdi
-#define scsel FPT_scsel
-#define scsell FPT_scsell
-#define scsendi FPT_scsendi
-#define scvalq FPT_scvalq
-#define scwirod FPT_scwirod
-#define scwiros FPT_scwiros
-#define scwtsel FPT_scwtsel
-#define scxferc FPT_scxferc
-#define sdecm FPT_sdecm
-#define sfm FPT_sfm
-#define shandem FPT_shandem
-#define sinits FPT_sinits
-#define sisyncn FPT_sisyncn
-#define sisyncr FPT_sisyncr
-#define siwidn FPT_siwidn
-#define siwidr FPT_siwidr
-#define sres FPT_sres
-#define sresb FPT_sresb
-#define ssel FPT_ssel
-#define ssenss FPT_ssenss
-#define sssyncv FPT_sssyncv
-#define stsyncn FPT_stsyncn
-#define stwidn FPT_stwidn
-#define sxfrp FPT_sxfrp
-#define utilEERead FPT_utilEERead
-#define utilEEReadOrg FPT_utilEEReadOrg
-#define utilEESendCmdAddr FPT_utilEESendCmdAddr
-#define utilEEWrite FPT_utilEEWrite
-#define utilEEWriteOnOff FPT_utilEEWriteOnOff
-#define utilUpdateResidual FPT_utilUpdateResidual
-
-
-/*----------------------------------------------------------------------
- *
- *
- * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved
- *
- * This file is available under both the GNU General Public License
- * and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- * $Workfile: globals.h $
- *
- * Description: Common shared global defines.
- *
- * $Date: 1996/09/04 01:26:13 $
- *
- * $Revision: 1.11 $
- *
- *----------------------------------------------------------------------*/
-#ifndef __GLOBALS_H__
-#define __GLOBALS_H__
-
-#define _UCB_MGR_ 1
-#define _SCCB_MGR_ 2
-
-/*#include <osflags.h>*/
-
#define MAX_CDBLEN 12
#define SCAM_LEV_2 1
#define CRCMASK 0xA001
-/* In your osflags.h file, please ENSURE that only ONE OS FLAG
- is on at a time !!! Also, please make sure you turn set the
- variable FW_TYPE to either _UCB_MGR_ or _SCCB_MGR_ !!! */
-
-#if defined(DOS) || defined(WIN95_16) || defined(OS2) || defined(OTHER_16)
- #define COMPILER_16_BIT 1
-#elif defined(NETWARE) || defined(NT) || defined(WIN95_32) || defined(UNIX) || defined(OTHER_32) || defined(SOLARIS_REAL_MODE)
- #define COMPILER_32_BIT 1
-#endif
-
-
#define BL_VENDOR_ID 0x104B
#define FP_DEVICE_ID 0x8130
#define MM_DEVICE_ID 0x1040
-#ifndef FALSE
-#define FALSE 0
-#endif
-#ifndef TRUE
-#define TRUE (!(FALSE))
-#endif
-
-#ifndef NULL
-#define NULL 0
-#endif
-
#define FAILURE 0xFFFFFFFFL
@@ -222,27 +71,11 @@ typedef unsigned long * PULONG;
typedef void * PVOID;
-#if defined(COMPILER_16_BIT)
-typedef unsigned char far * uchar_ptr;
-typedef unsigned short far * ushort_ptr;
-typedef unsigned long far * ulong_ptr;
-#endif /* 16_BIT_COMPILER */
-
-#if defined(COMPILER_32_BIT)
typedef unsigned char * uchar_ptr;
typedef unsigned short * ushort_ptr;
typedef unsigned long * ulong_ptr;
-#endif /* 32_BIT_COMPILER */
-/* NEW TYPE DEFINITIONS (shared with Mylex North)
-
-** Use following type defines to avoid confusion in 16 and 32-bit
-** environments. Avoid using 'int' as it denotes 16 bits in 16-bit
-** environment and 32 in 32-bit environments.
-
-*/
-
#define s08bits char
#define s16bits short
#define s32bits long
@@ -251,195 +84,19 @@ typedef unsigned long * ulong_ptr;
#define u16bits unsigned s16bits
#define u32bits unsigned s32bits
-#if defined(COMPILER_16_BIT)
-
-typedef u08bits far * pu08bits;
-typedef u16bits far * pu16bits;
-typedef u32bits far * pu32bits;
-
-#endif /* COMPILER_16_BIT */
-
-#if defined(COMPILER_32_BIT)
-
typedef u08bits * pu08bits;
typedef u16bits * pu16bits;
typedef u32bits * pu32bits;
-#endif /* COMPILER_32_BIT */
-
#define BIT(x) ((UCHAR)(1<<(x))) /* single-bit mask in bit position x */
#define BITW(x) ((USHORT)(1<<(x))) /* single-bit mask in bit position x */
-#if defined(DOS)
-/*#include <dos.h>*/
- #undef inportb /* undefine for Borland Lib */
- #undef inport /* they may have define I/O function in LIB */
- #undef outportb
- #undef outport
-
- #define OS_InPortByte(ioport) inportb(ioport)
- #define OS_InPortWord(ioport) inport(ioport)
- #define OS_InPortLong(ioport) inportq(ioport, val)
- #define OS_OutPortByte(ioport, val) outportb(ioport, val)
- #define OS_OutPortWord(ioport, val) outport(ioport, val)
- #define OS_OutPortLong(ioport) outportq(ioport, val)
-#endif /* DOS */
-
-#if defined(NETWARE) || defined(OTHER_32) || defined(OTHER_16)
- extern u08bits OS_InPortByte(u32bits ioport);
- extern u16bits OS_InPortWord(u32bits ioport);
- extern u32bits OS_InPortLong(u32bits ioport);
-
- extern OS_InPortByteBuffer(u32bits ioport, pu08bits buffer, u32bits count);
- extern OS_InPortWordBuffer(u32bits ioport, pu16bits buffer, u32bits count);
- extern OS_OutPortByte(u32bits ioport, u08bits val);
- extern OS_OutPortWord(u32bits ioport, u16bits val);
- extern OS_OutPortLong(u32bits ioport, u32bits val);
- extern OS_OutPortByteBuffer(u32bits ioport, pu08bits buffer, u32bits count);
- extern OS_OutPortWordBuffer(u32bits ioport, pu16bits buffer, u32bits count);
-#endif /* NETWARE || OTHER_32 || OTHER_16 */
-
-#if defined (NT) || defined(WIN95_32) || defined(WIN95_16)
- #if defined(NT)
-
- extern __declspec(dllimport) u08bits ScsiPortReadPortUchar(pu08bits ioport);
- extern __declspec(dllimport) u16bits ScsiPortReadPortUshort(pu16bits ioport);
- extern __declspec(dllimport) u32bits ScsiPortReadPortUlong(pu32bits ioport);
- extern __declspec(dllimport) void ScsiPortWritePortUchar(pu08bits ioport, u08bits val);
- extern __declspec(dllimport) void ScsiPortWritePortUshort(pu16bits port, u16bits val);
- extern __declspec(dllimport) void ScsiPortWritePortUlong(pu32bits port, u32bits val);
-
- #else
-
- extern u08bits ScsiPortReadPortUchar(pu08bits ioport);
- extern u16bits ScsiPortReadPortUshort(pu16bits ioport);
- extern u32bits ScsiPortReadPortUlong(pu32bits ioport);
- extern void ScsiPortWritePortUchar(pu08bits ioport, u08bits val);
- extern void ScsiPortWritePortUshort(pu16bits port, u16bits val);
- extern void ScsiPortWritePortUlong(pu32bits port, u32bits val);
- #endif
-
- #define OS_InPortByte(ioport) ScsiPortReadPortUchar((pu08bits) ioport)
- #define OS_InPortWord(ioport) ScsiPortReadPortUshort((pu16bits) ioport)
- #define OS_InPortLong(ioport) ScsiPortReadPortUlong((pu32bits) ioport)
-
- #define OS_OutPortByte(ioport, val) ScsiPortWritePortUchar((pu08bits) ioport, (u08bits) val)
- #define OS_OutPortWord(ioport, val) ScsiPortWritePortUshort((pu16bits) ioport, (u16bits) val)
- #define OS_OutPortLong(ioport, val) ScsiPortWritePortUlong((pu32bits) ioport, (u32bits) val)
- #define OS_OutPortByteBuffer(ioport, buffer, count) \
- ScsiPortWritePortBufferUchar((pu08bits)&port, (pu08bits) buffer, (u32bits) count)
- #define OS_OutPortWordBuffer(ioport, buffer, count) \
- ScsiPortWritePortBufferUshort((pu16bits)&port, (pu16bits) buffer, (u32bits) count)
-
- #define OS_Lock(x)
- #define OS_UnLock(x)
-#endif /* NT || WIN95_32 || WIN95_16 */
-
-#if defined (UNIX) && !defined(OS_InPortByte)
- #define OS_InPortByte(ioport) inb((u16bits)ioport)
- #define OS_InPortWord(ioport) inw((u16bits)ioport)
- #define OS_InPortLong(ioport) inl((u16bits)ioport)
- #define OS_OutPortByte(ioport,val) outb((u16bits)ioport, (u08bits)val)
- #define OS_OutPortWord(ioport,val) outw((u16bits)ioport, (u16bits)val)
- #define OS_OutPortLong(ioport,val) outl((u16bits)ioport, (u32bits)val)
-
- #define OS_Lock(x)
- #define OS_UnLock(x)
-#endif /* UNIX */
-
-
-#if defined(OS2)
- extern u08bits inb(u32bits ioport);
- extern u16bits inw(u32bits ioport);
- extern void outb(u32bits ioport, u08bits val);
- extern void outw(u32bits ioport, u16bits val);
-
- #define OS_InPortByte(ioport) inb(ioport)
- #define OS_InPortWord(ioport) inw(ioport)
- #define OS_OutPortByte(ioport, val) outb(ioport, val)
- #define OS_OutPortWord(ioport, val) outw(ioport, val)
- extern u32bits OS_InPortLong(u32bits ioport);
- extern void OS_OutPortLong(u32bits ioport, u32bits val);
-
- #define OS_Lock(x)
- #define OS_UnLock(x)
-#endif /* OS2 */
-
-#if defined(SOLARIS_REAL_MODE)
-
-extern unsigned char inb(unsigned long ioport);
-extern unsigned short inw(unsigned long ioport);
-
-#define OS_InPortByte(ioport) inb(ioport)
-#define OS_InPortWord(ioport) inw(ioport)
-
-extern void OS_OutPortByte(unsigned long ioport, unsigned char val);
-extern void OS_OutPortWord(unsigned long ioport, unsigned short val);
-extern unsigned long OS_InPortLong(unsigned long ioport);
-extern void OS_OutPortLong(unsigned long ioport, unsigned long val);
-
-#define OS_Lock(x)
-#define OS_UnLock(x)
-
-#endif /* SOLARIS_REAL_MODE */
-
-#endif /* __GLOBALS_H__ */
-
-/*----------------------------------------------------------------------
- *
- *
- * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved
- *
- * This file is available under both the GNU General Public License
- * and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- * $Workfile: sccbmgr.h $
- *
- * Description: Common shared SCCB Interface defines and SCCB
- * Manager specifics defines.
- *
- * $Date: 1996/10/24 23:09:33 $
- *
- * $Revision: 1.14 $
- *
- *----------------------------------------------------------------------*/
-
-#ifndef __SCCB_H__
-#define __SCCB_H__
-
-/*#include <osflags.h>*/
-/*#include <globals.h>*/
-
-#if defined(BUGBUG)
-#define debug_size 32
-#endif
-
-#if defined(DOS)
-
- typedef struct _SCCB near *PSCCB;
- #if (FW_TYPE == _SCCB_MGR_)
- typedef void (*CALL_BK_FN)(PSCCB);
- #endif
-
-#elif defined(OS2)
-
- typedef struct _SCCB far *PSCCB;
- #if (FW_TYPE == _SCCB_MGR_)
- typedef void (far *CALL_BK_FN)(PSCCB);
- #endif
-
-#else
-
- typedef struct _SCCB *PSCCB;
- #if (FW_TYPE == _SCCB_MGR_)
- typedef void (*CALL_BK_FN)(PSCCB);
- #endif
-
-#endif
+typedef struct _SCCB *PSCCB;
+typedef void (*CALL_BK_FN)(PSCCB);
typedef struct SCCBMgr_info {
@@ -466,25 +123,13 @@ typedef struct SCCBMgr_info {
ULONG si_secondary_range;
} SCCBMGR_INFO;
-#if defined(DOS)
- typedef SCCBMGR_INFO * PSCCBMGR_INFO;
-#else
- #if defined (COMPILER_16_BIT)
- typedef SCCBMGR_INFO far * PSCCBMGR_INFO;
- #else
- typedef SCCBMGR_INFO * PSCCBMGR_INFO;
- #endif
-#endif // defined(DOS)
+typedef SCCBMGR_INFO * PSCCBMGR_INFO;
-
-
-#if (FW_TYPE==_SCCB_MGR_)
- #define SCSI_PARITY_ENA 0x0001
- #define LOW_BYTE_TERM 0x0010
- #define HIGH_BYTE_TERM 0x0020
- #define BUSTYPE_PCI 0x3
-#endif
+#define SCSI_PARITY_ENA 0x0001
+#define LOW_BYTE_TERM 0x0010
+#define HIGH_BYTE_TERM 0x0020
+#define BUSTYPE_PCI 0x3
#define SUPPORT_16TAR_32LUN 0x0002
#define SOFT_RESET 0x0004
@@ -553,9 +198,6 @@ typedef struct _SCCB {
UCHAR Save_CdbLen;
UCHAR Sccb_XferState;
ULONG Sccb_SGoffset;
-#if (FW_TYPE == _UCB_MGR_)
- PUCB Sccb_ucb_ptr;
-#endif
} SCCB;
#define SCCB_SIZE sizeof(SCCB)
@@ -626,25 +268,9 @@ typedef struct _SCCB {
-#if (FW_TYPE==_UCB_MGR_)
- #define HBA_AUTO_SENSE_FAIL 0x1B
- #define HBA_TQ_REJECTED 0x1C
- #define HBA_UNSUPPORTED_MSG 0x1D
- #define HBA_HW_ERROR 0x20
- #define HBA_ATN_NOT_RESPONDED 0x21
- #define HBA_SCSI_RESET_BY_ADAPTER 0x22
- #define HBA_SCSI_RESET_BY_TARGET 0x23
- #define HBA_WRONG_CONNECTION 0x24
- #define HBA_BUS_DEVICE_RESET 0x25
- #define HBA_ABORT_QUEUE 0x26
-
-#else // these are not defined in BUDI/UCB
-
- #define SCCB_INVALID_DIRECTION 0x18 /* Invalid target direction */
- #define SCCB_DUPLICATE_SCCB 0x19 /* Duplicate SCCB */
- #define SCCB_SCSI_RST 0x35 /* SCSI RESET detected. */
-
-#endif // (FW_TYPE==_UCB_MGR_)
+#define SCCB_INVALID_DIRECTION 0x18 /* Invalid target direction */
+#define SCCB_DUPLICATE_SCCB 0x19 /* Duplicate SCCB */
+#define SCCB_SCSI_RST 0x35 /* SCSI RESET detected. */
#define SCCB_IN_PROCESS 0x00
@@ -657,115 +283,20 @@ typedef struct _SCCB {
#define SCCB_SIZE sizeof(SCCB)
-
-
-#if (FW_TYPE == _UCB_MGR_)
- void SccbMgr_start_sccb(CARD_HANDLE pCurrCard, PUCB p_ucb);
- s32bits SccbMgr_abort_sccb(CARD_HANDLE pCurrCard, PUCB p_ucb);
- u08bits SccbMgr_my_int(CARD_HANDLE pCurrCard);
- s32bits SccbMgr_isr(CARD_HANDLE pCurrCard);
- void SccbMgr_scsi_reset(CARD_HANDLE pCurrCard);
- void SccbMgr_timer_expired(CARD_HANDLE pCurrCard);
- void SccbMgr_unload_card(CARD_HANDLE pCurrCard);
- void SccbMgr_restore_foreign_state(CARD_HANDLE pCurrCard);
- void SccbMgr_restore_native_state(CARD_HANDLE pCurrCard);
- void SccbMgr_save_foreign_state(PADAPTER_INFO pAdapterInfo);
-
-#endif
-
-
-#if (FW_TYPE == _SCCB_MGR_)
-
- #if defined (DOS)
- int SccbMgr_sense_adapter(PSCCBMGR_INFO pCardInfo);
- USHORT SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo);
- void SccbMgr_start_sccb(USHORT pCurrCard, PSCCB p_SCCB);
- int SccbMgr_abort_sccb(USHORT pCurrCard, PSCCB p_SCCB);
- UCHAR SccbMgr_my_int(USHORT pCurrCard);
- int SccbMgr_isr(USHORT pCurrCard);
- void SccbMgr_scsi_reset(USHORT pCurrCard);
- void SccbMgr_timer_expired(USHORT pCurrCard);
- USHORT SccbMgr_status(USHORT pCurrCard);
- void SccbMgr_unload_card(USHORT pCurrCard);
-
- #else //non-DOS
-
- int SccbMgr_sense_adapter(PSCCBMGR_INFO pCardInfo);
- ULONG SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo);
- void SccbMgr_start_sccb(ULONG pCurrCard, PSCCB p_SCCB);
- int SccbMgr_abort_sccb(ULONG pCurrCard, PSCCB p_SCCB);
- UCHAR SccbMgr_my_int(ULONG pCurrCard);
- int SccbMgr_isr(ULONG pCurrCard);
- void SccbMgr_scsi_reset(ULONG pCurrCard);
- void SccbMgr_enable_int(ULONG pCurrCard);
- void SccbMgr_disable_int(ULONG pCurrCard);
- void SccbMgr_timer_expired(ULONG pCurrCard);
- void SccbMgr_unload_card(ULONG pCurrCard);
-
- #endif
-#endif // (FW_TYPE == _SCCB_MGR_)
-
-#endif /* __SCCB_H__ */
-
-/*----------------------------------------------------------------------
- *
- *
- * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved
- *
- * This file is available under both the GNU General Public License
- * and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- * $Workfile: blx30.h $
- *
- * Description: This module contains SCCB/UCB Manager implementation
- * specific stuff.
- *
- * $Date: 1996/11/13 18:34:22 $
- *
- * $Revision: 1.10 $
- *
- *----------------------------------------------------------------------*/
-
-
-#ifndef __blx30_H__
-#define __blx30_H__
-
-/*#include <globals.h>*/
-
#define ORION_FW_REV 3110
-
-
-
#define HARP_REVD 1
-#if defined(DOS)
-#define QUEUE_DEPTH 8+1 /*1 for Normal disconnect 0 for Q'ing. */
-#else
#define QUEUE_DEPTH 254+1 /*1 for Normal disconnect 32 for Q'ing. */
-#endif // defined(DOS)
#define MAX_MB_CARDS 4 /* Max. no of cards suppoerted on Mother Board */
#define WIDE_SCSI 1
-#if defined(WIDE_SCSI)
- #if defined(DOS)
- #define MAX_SCSI_TAR 16
- #define MAX_LUN 8
- #define LUN_MASK 0x07
- #else
- #define MAX_SCSI_TAR 16
- #define MAX_LUN 32
- #define LUN_MASK 0x1f
-
- #endif
-#else
- #define MAX_SCSI_TAR 8
- #define MAX_LUN 8
- #define LUN_MASK 0x07
-#endif
+#define MAX_SCSI_TAR 16
+#define MAX_LUN 32
+#define LUN_MASK 0x1f
#if defined(HARP_REVA)
#define SG_BUF_CNT 15 /*Number of prefetched elements. */
@@ -778,116 +309,12 @@ typedef struct _SCCB {
#define SG_ELEMENT_MASK 0xFFFFFFFFL
-#if (FW_TYPE == _UCB_MGR_)
- #define OPC_DECODE_NORMAL 0x0f7f
-#endif // _UCB_MGR_
-
-
-
-#if defined(DOS)
-
-/*#include <dos.h>*/
- #define RD_HARPOON(ioport) (OS_InPortByte(ioport))
- #define RDW_HARPOON(ioport) (OS_InPortWord(ioport))
- #define WR_HARPOON(ioport,val) (OS_OutPortByte(ioport,val))
- #define WRW_HARPOON(ioport,val) (OS_OutPortWord(ioport,val))
-
- #define RD_HARP32(port,offset,data) asm{db 66h; \
- push ax; \
- mov dx,port; \
- add dx, offset; \
- db 66h; \
- in ax,dx; \
- db 66h; \
- mov word ptr data,ax;\
- db 66h; \
- pop ax}
-
- #define WR_HARP32(port,offset,data) asm{db 66h; \
- push ax; \
- mov dx,port; \
- add dx, offset; \
- db 66h; \
- mov ax,word ptr data;\
- db 66h; \
- out dx,ax; \
- db 66h; \
- pop ax}
-#endif /* DOS */
-
-#if defined(NETWARE) || defined(OTHER_32) || defined(OTHER_16)
- #define RD_HARPOON(ioport) OS_InPortByte((unsigned long)ioport)
- #define RDW_HARPOON(ioport) OS_InPortWord((unsigned long)ioport)
- #define RD_HARP32(ioport,offset,data) (data = OS_InPortLong(ioport + offset))
- #define WR_HARPOON(ioport,val) OS_OutPortByte((ULONG)ioport,(UCHAR) val)
- #define WRW_HARPOON(ioport,val) OS_OutPortWord((ULONG)ioport,(USHORT)val)
- #define WR_HARP32(ioport,offset,data) OS_OutPortLong((ioport + offset), data)
-#endif /* NETWARE || OTHER_32 || OTHER_16 */
-
-#if defined(NT) || defined(WIN95_32) || defined(WIN95_16)
- #define RD_HARPOON(ioport) OS_InPortByte((ULONG)ioport)
- #define RDW_HARPOON(ioport) OS_InPortWord((ULONG)ioport)
- #define RD_HARP32(ioport,offset,data) (data = OS_InPortLong((ULONG)(ioport + offset)))
- #define WR_HARPOON(ioport,val) OS_OutPortByte((ULONG)ioport,(UCHAR) val)
- #define WRW_HARPOON(ioport,val) OS_OutPortWord((ULONG)ioport,(USHORT)val)
- #define WR_HARP32(ioport,offset,data) OS_OutPortLong((ULONG)(ioport + offset), data)
-#endif /* NT || WIN95_32 || WIN95_16 */
-
-#if defined (UNIX)
- #define RD_HARPOON(ioport) OS_InPortByte((u32bits)ioport)
- #define RDW_HARPOON(ioport) OS_InPortWord((u32bits)ioport)
- #define RD_HARP32(ioport,offset,data) (data = OS_InPortLong((u32bits)(ioport + offset)))
- #define WR_HARPOON(ioport,val) OS_OutPortByte((u32bits)ioport,(u08bits) val)
- #define WRW_HARPOON(ioport,val) OS_OutPortWord((u32bits)ioport,(u16bits)val)
- #define WR_HARP32(ioport,offset,data) OS_OutPortLong((u32bits)(ioport + offset), data)
-#endif /* UNIX */
-
-#if defined(OS2)
- #define RD_HARPOON(ioport) OS_InPortByte((unsigned long)ioport)
- #define RDW_HARPOON(ioport) OS_InPortWord((unsigned long)ioport)
- #define RD_HARP32(ioport,offset,data) (data = OS_InPortLong((ULONG)(ioport + offset)))
- #define WR_HARPOON(ioport,val) OS_OutPortByte((ULONG)ioport,(UCHAR) val)
- #define WRW_HARPOON(ioport,val) OS_OutPortWord((ULONG)ioport,(USHORT)val)
- #define WR_HARP32(ioport,offset,data) OS_OutPortLong(((ULONG)(ioport + offset)), data)
-#endif /* OS2 */
-
-#if defined(SOLARIS_REAL_MODE)
-
- #define RD_HARPOON(ioport) OS_InPortByte((unsigned long)ioport)
- #define RDW_HARPOON(ioport) OS_InPortWord((unsigned long)ioport)
- #define RD_HARP32(ioport,offset,data) (data = OS_InPortLong((ULONG)(ioport + offset)))
- #define WR_HARPOON(ioport,val) OS_OutPortByte((ULONG)ioport,(UCHAR) val)
- #define WRW_HARPOON(ioport,val) OS_OutPortWord((ULONG)ioport,(USHORT)val)
- #define WR_HARP32(ioport,offset,data) OS_OutPortLong((ULONG)(ioport + offset), (ULONG)data)
-
-#endif /* SOLARIS_REAL_MODE */
-
-#endif /* __BLX30_H__ */
-
-
-/*----------------------------------------------------------------------
- *
- *
- * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved
- *
- * This file is available under both the GNU General Public License
- * and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- * $Workfile: target.h $
- *
- * Description: Definitions for Target related structures
- *
- * $Date: 1996/12/11 22:06:20 $
- *
- * $Revision: 1.9 $
- *
- *----------------------------------------------------------------------*/
-
-#ifndef __TARGET__
-#define __TARGET__
-
-/*#include <globals.h>*/
-/*#include <blx30.h>*/
+#define RD_HARPOON(ioport) OS_InPortByte((u32bits)ioport)
+#define RDW_HARPOON(ioport) OS_InPortWord((u32bits)ioport)
+#define RD_HARP32(ioport,offset,data) (data = OS_InPortLong((u32bits)(ioport + offset)))
+#define WR_HARPOON(ioport,val) OS_OutPortByte((u32bits)ioport,(u08bits) val)
+#define WRW_HARPOON(ioport,val) OS_OutPortWord((u32bits)ioport,(u16bits)val)
+#define WR_HARP32(ioport,offset,data) OS_OutPortLong((u32bits)(ioport + offset), data)
#define TAR_SYNC_MASK (BIT(7)+BIT(6))
@@ -919,16 +346,7 @@ typedef struct _SCCB {
#define EE_WIDE_SCSI BIT(7)
-#if defined(DOS)
- typedef struct SCCBMgr_tar_info near *PSCCBMgr_tar_info;
-
-#elif defined(OS2)
- typedef struct SCCBMgr_tar_info far *PSCCBMgr_tar_info;
-
-#else
- typedef struct SCCBMgr_tar_info *PSCCBMgr_tar_info;
-
-#endif
+typedef struct SCCBMgr_tar_info *PSCCBMgr_tar_info;
typedef struct SCCBMgr_tar_info {
@@ -949,11 +367,7 @@ typedef struct SCCBMgr_tar_info {
typedef struct NVRAMInfo {
UCHAR niModel; /* Model No. of card */
UCHAR niCardNo; /* Card no. */
-#if defined(DOS)
- USHORT niBaseAddr; /* Port Address of card */
-#else
ULONG niBaseAddr; /* Port Address of card */
-#endif
UCHAR niSysConf; /* Adapter Configuration byte - Byte 16 of eeprom map */
UCHAR niScsiConf; /* SCSI Configuration byte - Byte 17 of eeprom map */
UCHAR niScamConf; /* SCAM Configuration byte - Byte 20 of eeprom map */
@@ -962,13 +376,7 @@ typedef struct NVRAMInfo {
UCHAR niScamTbl[MAX_SCSI_TAR][4]; /* Compressed Scam name string of Targets */
}NVRAMINFO;
-#if defined(DOS)
-typedef NVRAMINFO near *PNVRamInfo;
-#elif defined (OS2)
-typedef NVRAMINFO far *PNVRamInfo;
-#else
typedef NVRAMINFO *PNVRamInfo;
-#endif
#define MODEL_LT 1
#define MODEL_DL 2
@@ -978,17 +386,9 @@ typedef NVRAMINFO *PNVRamInfo;
typedef struct SCCBcard {
PSCCB currentSCCB;
-#if (FW_TYPE==_SCCB_MGR_)
PSCCBMGR_INFO cardInfo;
-#else
- PADAPTER_INFO cardInfo;
-#endif
-#if defined(DOS)
- USHORT ioPort;
-#else
ULONG ioPort;
-#endif
USHORT cmdCounter;
UCHAR discQCount;
@@ -1002,13 +402,7 @@ typedef struct SCCBcard {
}SCCBCARD;
-#if defined(DOS)
-typedef struct SCCBcard near *PSCCBcard;
-#elif defined (OS2)
-typedef struct SCCBcard far *PSCCBcard;
-#else
typedef struct SCCBcard *PSCCBcard;
-#endif
#define F_TAG_STARTED 0x01
@@ -1063,29 +457,6 @@ typedef struct SCCBscam_info {
} SCCBSCAM_INFO, *PSCCBSCAM_INFO;
-#endif
-/*----------------------------------------------------------------------
- *
- *
- * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved
- *
- * This file is available under both the GNU General Public License
- * and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- * $Workfile: scsi2.h $
- *
- * Description: Register definitions for HARPOON ASIC.
- *
- * $Date: 1996/11/13 18:32:57 $
- *
- * $Revision: 1.4 $
- *
- *----------------------------------------------------------------------*/
-
-#ifndef __SCSI_H__
-#define __SCSI_H__
-
-
#define SCSI_TEST_UNIT_READY 0x00
#define SCSI_REZERO_UNIT 0x01
@@ -1195,29 +566,6 @@ typedef struct SCCBscam_info {
#define SYNC5MBS 0x32
#define MAX_OFFSET 0x0F /* Maxbyteoffset for Sync Xfers */
-#endif
-/*----------------------------------------------------------------------
- *
- *
- * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved
- *
- * This file is available under both the GNU General Public License
- * and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- * $Workfile: eeprom.h $
- *
- * Description: Definitions for EEPROM related structures
- *
- * $Date: 1996/11/13 18:28:39 $
- *
- * $Revision: 1.4 $
- *
- *----------------------------------------------------------------------*/
-
-#ifndef __EEPROM__
-#define __EEPROM__
-
-/*#include <globals.h>*/
#define EEPROM_WD_CNT 256
@@ -1280,31 +628,6 @@ typedef struct SCCBscam_info {
#define DISC_ENABLE_BIT BIT(6)
-#endif
-/*----------------------------------------------------------------------
- *
- *
- * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved
- *
- * This file is available under both the GNU General Public License
- * and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- * $Workfile: harpoon.h $
- *
- * Description: Register definitions for HARPOON ASIC.
- *
- * $Date: 1997/07/09 21:44:36 $
- *
- * $Revision: 1.9 $
- *
- *----------------------------------------------------------------------*/
-
-
-/*#include <globals.h>*/
-
-#ifndef __HARPOON__
-#define __HARPOON__
-
#define hp_vendor_id_0 0x00 /* LSB */
#define ORION_VEND_0 0x4B
@@ -1578,8 +901,6 @@ typedef struct SCCBscam_info {
- extern USHORT default_intena;
-
#define hp_intena 0x40
#define RESET BITW(7)
@@ -1972,15 +1293,6 @@ typedef struct SCCBscam_info {
xfercnt <<= 16,\
xfercnt |= RDW_HARPOON((USHORT)(port+hp_xfercnt_0)))
*/
-#if defined(DOS)
-#define HP_SETUP_ADDR_CNT(port,addr,count) (WRW_HARPOON((USHORT)(port+hp_host_addr_lo), (USHORT)(addr & 0x0000FFFFL)),\
- addr >>= 16,\
- WRW_HARPOON((USHORT)(port+hp_host_addr_hmi), (USHORT)(addr & 0x0000FFFFL)),\
- WR_HARP32(port,hp_xfercnt_0,count),\
- WRW_HARPOON((USHORT)(port+hp_xfer_cnt_lo), (USHORT)(count & 0x0000FFFFL)),\
- count >>= 16,\
- WR_HARPOON(port+hp_xfer_cnt_hi, (count & 0xFF)))
-#else
#define HP_SETUP_ADDR_CNT(port,addr,count) (WRW_HARPOON((port+hp_host_addr_lo), (USHORT)(addr & 0x0000FFFFL)),\
addr >>= 16,\
WRW_HARPOON((port+hp_host_addr_hmi), (USHORT)(addr & 0x0000FFFFL)),\
@@ -1988,7 +1300,6 @@ typedef struct SCCBscam_info {
WRW_HARPOON((port+hp_xfer_cnt_lo), (USHORT)(count & 0x0000FFFFL)),\
count >>= 16,\
WR_HARPOON(port+hp_xfer_cnt_hi, (count & 0xFF)))
-#endif
#define ACCEPT_MSG(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
WR_HARPOON(port+hp_scsisig, S_ILL_PH);}
@@ -2020,383 +1331,145 @@ typedef struct SCCBscam_info {
-#endif
-
-#if (FW_TYPE==_UCB_MGR_)
-void ReadNVRam(PSCCBcard pCurrCard,PUCB p_ucb);
-void WriteNVRam(PSCCBcard pCurrCard,PUCB p_ucb);
-void UpdateCheckSum(u32bits baseport);
-#endif // (FW_TYPE==_UCB_MGR_)
-
-#if defined(DOS)
-UCHAR sfm(USHORT port, PSCCB pcurrSCCB);
-void scsiStartAuto(USHORT port);
-UCHAR sisyncn(USHORT port, UCHAR p_card, UCHAR syncFlag);
-void ssel(USHORT port, UCHAR p_card);
-void sres(USHORT port, UCHAR p_card, PSCCBcard pCurrCard);
-void sdecm(UCHAR message, USHORT port, UCHAR p_card);
-void shandem(USHORT port, UCHAR p_card,PSCCB pCurrSCCB);
-void stsyncn(USHORT port, UCHAR p_card);
-void sisyncr(USHORT port,UCHAR sync_pulse, UCHAR offset);
-void sssyncv(USHORT p_port, UCHAR p_id, UCHAR p_sync_value, PSCCBMgr_tar_info currTar_Info);
-void sresb(USHORT port, UCHAR p_card);
-void sxfrp(USHORT p_port, UCHAR p_card);
-void schkdd(USHORT port, UCHAR p_card);
-UCHAR RdStack(USHORT port, UCHAR index);
-void WrStack(USHORT portBase, UCHAR index, UCHAR data);
-UCHAR ChkIfChipInitialized(USHORT ioPort);
-
-#if defined(V302)
-UCHAR GetTarLun(USHORT port, UCHAR p_card, UCHAR our_target, PSCCBcard pCurrCard, PUCHAR tag, PUCHAR lun);
-#endif
-
-void SendMsg(USHORT port, UCHAR message);
-void queueFlushTargSccb(UCHAR p_card, UCHAR thisTarg, UCHAR error_code);
-UCHAR scsellDOS(USHORT p_port, UCHAR targ_id);
-#else
-UCHAR sfm(ULONG port, PSCCB pcurrSCCB);
void scsiStartAuto(ULONG port);
-UCHAR sisyncn(ULONG port, UCHAR p_card, UCHAR syncFlag);
-void ssel(ULONG port, UCHAR p_card);
-void sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard);
-void sdecm(UCHAR message, ULONG port, UCHAR p_card);
-void shandem(ULONG port, UCHAR p_card,PSCCB pCurrSCCB);
-void stsyncn(ULONG port, UCHAR p_card);
-void sisyncr(ULONG port,UCHAR sync_pulse, UCHAR offset);
-void sssyncv(ULONG p_port, UCHAR p_id, UCHAR p_sync_value, PSCCBMgr_tar_info currTar_Info);
-void sresb(ULONG port, UCHAR p_card);
-void sxfrp(ULONG p_port, UCHAR p_card);
-void schkdd(ULONG port, UCHAR p_card);
-UCHAR RdStack(ULONG port, UCHAR index);
-void WrStack(ULONG portBase, UCHAR index, UCHAR data);
-UCHAR ChkIfChipInitialized(ULONG ioPort);
-
-#if defined(V302)
-UCHAR GetTarLun(ULONG port, UCHAR p_card, UCHAR our_target, PSCCBcard pCurrCard, PUCHAR tar, PUCHAR lun);
-#endif
+static UCHAR FPT_sisyncn(ULONG port, UCHAR p_card, UCHAR syncFlag);
+static void FPT_ssel(ULONG port, UCHAR p_card);
+static void FPT_sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard);
+static void FPT_shandem(ULONG port, UCHAR p_card,PSCCB pCurrSCCB);
+static void FPT_stsyncn(ULONG port, UCHAR p_card);
+static void FPT_sisyncr(ULONG port,UCHAR sync_pulse, UCHAR offset);
+static void FPT_sssyncv(ULONG p_port, UCHAR p_id, UCHAR p_sync_value,
+ PSCCBMgr_tar_info currTar_Info);
+static void FPT_sresb(ULONG port, UCHAR p_card);
+static void FPT_sxfrp(ULONG p_port, UCHAR p_card);
+static void FPT_schkdd(ULONG port, UCHAR p_card);
+static UCHAR FPT_RdStack(ULONG port, UCHAR index);
+static void FPT_WrStack(ULONG portBase, UCHAR index, UCHAR data);
+static UCHAR FPT_ChkIfChipInitialized(ULONG ioPort);
-void SendMsg(ULONG port, UCHAR message);
-void queueFlushTargSccb(UCHAR p_card, UCHAR thisTarg, UCHAR error_code);
-#endif
+static void FPT_SendMsg(ULONG port, UCHAR message);
+static void FPT_queueFlushTargSccb(UCHAR p_card, UCHAR thisTarg,
+ UCHAR error_code);
-void ssenss(PSCCBcard pCurrCard);
-void sinits(PSCCB p_sccb, UCHAR p_card);
-void RNVRamData(PNVRamInfo pNvRamInfo);
-
-#if defined(WIDE_SCSI)
- #if defined(DOS)
- UCHAR siwidn(USHORT port, UCHAR p_card);
- void stwidn(USHORT port, UCHAR p_card);
- void siwidr(USHORT port, UCHAR width);
- #else
- UCHAR siwidn(ULONG port, UCHAR p_card);
- void stwidn(ULONG port, UCHAR p_card);
- void siwidr(ULONG port, UCHAR width);
- #endif
-#endif
+static void FPT_sinits(PSCCB p_sccb, UCHAR p_card);
+static void FPT_RNVRamData(PNVRamInfo pNvRamInfo);
+static UCHAR FPT_siwidn(ULONG port, UCHAR p_card);
+static void FPT_stwidn(ULONG port, UCHAR p_card);
+static void FPT_siwidr(ULONG port, UCHAR width);
-void queueSelectFail(PSCCBcard pCurrCard, UCHAR p_card);
-void queueDisconnect(PSCCB p_SCCB, UCHAR p_card);
-void queueCmdComplete(PSCCBcard pCurrCard, PSCCB p_SCCB, UCHAR p_card);
-void queueSearchSelect(PSCCBcard pCurrCard, UCHAR p_card);
-void queueFlushSccb(UCHAR p_card, UCHAR error_code);
-void queueAddSccb(PSCCB p_SCCB, UCHAR card);
-UCHAR queueFindSccb(PSCCB p_SCCB, UCHAR p_card);
-void utilUpdateResidual(PSCCB p_SCCB);
-USHORT CalcCrc16(UCHAR buffer[]);
-UCHAR CalcLrc(UCHAR buffer[]);
-
-
-#if defined(DOS)
-void Wait1Second(USHORT p_port);
-void Wait(USHORT p_port, UCHAR p_delay);
-void utilEEWriteOnOff(USHORT p_port,UCHAR p_mode);
-void utilEEWrite(USHORT p_port, USHORT ee_data, USHORT ee_addr);
-USHORT utilEERead(USHORT p_port, USHORT ee_addr);
-USHORT utilEEReadOrg(USHORT p_port, USHORT ee_addr);
-void utilEESendCmdAddr(USHORT p_port, UCHAR ee_cmd, USHORT ee_addr);
-#else
-void Wait1Second(ULONG p_port);
-void Wait(ULONG p_port, UCHAR p_delay);
-void utilEEWriteOnOff(ULONG p_port,UCHAR p_mode);
-void utilEEWrite(ULONG p_port, USHORT ee_data, USHORT ee_addr);
-USHORT utilEERead(ULONG p_port, USHORT ee_addr);
-USHORT utilEEReadOrg(ULONG p_port, USHORT ee_addr);
-void utilEESendCmdAddr(ULONG p_port, UCHAR ee_cmd, USHORT ee_addr);
-#endif
+static void FPT_queueSelectFail(PSCCBcard pCurrCard, UCHAR p_card);
+static void FPT_queueDisconnect(PSCCB p_SCCB, UCHAR p_card);
+static void FPT_queueCmdComplete(PSCCBcard pCurrCard, PSCCB p_SCCB,
+ UCHAR p_card);
+static void FPT_queueSearchSelect(PSCCBcard pCurrCard, UCHAR p_card);
+static void FPT_queueFlushSccb(UCHAR p_card, UCHAR error_code);
+static void FPT_queueAddSccb(PSCCB p_SCCB, UCHAR card);
+static UCHAR FPT_queueFindSccb(PSCCB p_SCCB, UCHAR p_card);
+static void FPT_utilUpdateResidual(PSCCB p_SCCB);
+static USHORT FPT_CalcCrc16(UCHAR buffer[]);
+static UCHAR FPT_CalcLrc(UCHAR buffer[]);
-#if defined(OS2)
- void far phaseDataOut(ULONG port, UCHAR p_card);
- void far phaseDataIn(ULONG port, UCHAR p_card);
- void far phaseCommand(ULONG port, UCHAR p_card);
- void far phaseStatus(ULONG port, UCHAR p_card);
- void far phaseMsgOut(ULONG port, UCHAR p_card);
- void far phaseMsgIn(ULONG port, UCHAR p_card);
- void far phaseIllegal(ULONG port, UCHAR p_card);
-#else
- #if defined(DOS)
- void phaseDataOut(USHORT port, UCHAR p_card);
- void phaseDataIn(USHORT port, UCHAR p_card);
- void phaseCommand(USHORT port, UCHAR p_card);
- void phaseStatus(USHORT port, UCHAR p_card);
- void phaseMsgOut(USHORT port, UCHAR p_card);
- void phaseMsgIn(USHORT port, UCHAR p_card);
- void phaseIllegal(USHORT port, UCHAR p_card);
- #else
- void phaseDataOut(ULONG port, UCHAR p_card);
- void phaseDataIn(ULONG port, UCHAR p_card);
- void phaseCommand(ULONG port, UCHAR p_card);
- void phaseStatus(ULONG port, UCHAR p_card);
- void phaseMsgOut(ULONG port, UCHAR p_card);
- void phaseMsgIn(ULONG port, UCHAR p_card);
- void phaseIllegal(ULONG port, UCHAR p_card);
- #endif
-#endif
+static void FPT_Wait1Second(ULONG p_port);
+static void FPT_Wait(ULONG p_port, UCHAR p_delay);
+static void FPT_utilEEWriteOnOff(ULONG p_port,UCHAR p_mode);
+static void FPT_utilEEWrite(ULONG p_port, USHORT ee_data, USHORT ee_addr);
+static USHORT FPT_utilEERead(ULONG p_port, USHORT ee_addr);
+static USHORT FPT_utilEEReadOrg(ULONG p_port, USHORT ee_addr);
+static void FPT_utilEESendCmdAddr(ULONG p_port, UCHAR ee_cmd, USHORT ee_addr);
-#if defined(DOS)
-void phaseDecode(USHORT port, UCHAR p_card);
-void phaseChkFifo(USHORT port, UCHAR p_card);
-void phaseBusFree(USHORT p_port, UCHAR p_card);
-#else
-void phaseDecode(ULONG port, UCHAR p_card);
-void phaseChkFifo(ULONG port, UCHAR p_card);
-void phaseBusFree(ULONG p_port, UCHAR p_card);
-#endif
-
-
-
-
-#if defined(DOS)
-void XbowInit(USHORT port, UCHAR scamFlg);
-void BusMasterInit(USHORT p_port);
-int DiagXbow(USHORT port);
-int DiagBusMaster(USHORT port);
-void DiagEEPROM(USHORT p_port);
-#else
-void XbowInit(ULONG port, UCHAR scamFlg);
-void BusMasterInit(ULONG p_port);
-int DiagXbow(ULONG port);
-int DiagBusMaster(ULONG port);
-void DiagEEPROM(ULONG p_port);
-#endif
+static void FPT_phaseDataOut(ULONG port, UCHAR p_card);
+static void FPT_phaseDataIn(ULONG port, UCHAR p_card);
+static void FPT_phaseCommand(ULONG port, UCHAR p_card);
+static void FPT_phaseStatus(ULONG port, UCHAR p_card);
+static void FPT_phaseMsgOut(ULONG port, UCHAR p_card);
+static void FPT_phaseMsgIn(ULONG port, UCHAR p_card);
+static void FPT_phaseIllegal(ULONG port, UCHAR p_card);
+static void FPT_phaseDecode(ULONG port, UCHAR p_card);
+static void FPT_phaseChkFifo(ULONG port, UCHAR p_card);
+static void FPT_phaseBusFree(ULONG p_port, UCHAR p_card);
-#if defined(DOS)
-void busMstrAbort(USHORT port);
-UCHAR busMstrTimeOut(USHORT port);
-void dataXferProcessor(USHORT port, PSCCBcard pCurrCard);
-void busMstrSGDataXferStart(USHORT port, PSCCB pCurrSCCB);
-void busMstrDataXferStart(USHORT port, PSCCB pCurrSCCB);
-void hostDataXferAbort(USHORT port, UCHAR p_card, PSCCB pCurrSCCB);
-#else
-void busMstrAbort(ULONG port);
-UCHAR busMstrTimeOut(ULONG port);
-void dataXferProcessor(ULONG port, PSCCBcard pCurrCard);
-void busMstrSGDataXferStart(ULONG port, PSCCB pCurrSCCB);
-void busMstrDataXferStart(ULONG port, PSCCB pCurrSCCB);
-void hostDataXferAbort(ULONG port, UCHAR p_card, PSCCB pCurrSCCB);
-#endif
-void hostDataXferRestart(PSCCB currSCCB);
-#if defined (DOS)
-UCHAR SccbMgr_bad_isr(USHORT p_port, UCHAR p_card, PSCCBcard pCurrCard, USHORT p_int);
-#else
-UCHAR SccbMgr_bad_isr(ULONG p_port, UCHAR p_card, PSCCBcard pCurrCard, USHORT p_int);
-#endif
+static void FPT_XbowInit(ULONG port, UCHAR scamFlg);
+static void FPT_BusMasterInit(ULONG p_port);
+static void FPT_DiagEEPROM(ULONG p_port);
-void SccbMgrTableInitAll(void);
-void SccbMgrTableInitCard(PSCCBcard pCurrCard, UCHAR p_card);
-void SccbMgrTableInitTarget(UCHAR p_card, UCHAR target);
-
-
-
-void scini(UCHAR p_card, UCHAR p_our_id, UCHAR p_power_up);
-
-#if defined(DOS)
-int scarb(USHORT p_port, UCHAR p_sel_type);
-void scbusf(USHORT p_port);
-void scsel(USHORT p_port);
-void scasid(UCHAR p_card, USHORT p_port);
-UCHAR scxferc(USHORT p_port, UCHAR p_data);
-UCHAR scsendi(USHORT p_port, UCHAR p_id_string[]);
-UCHAR sciso(USHORT p_port, UCHAR p_id_string[]);
-void scwirod(USHORT p_port, UCHAR p_data_bit);
-void scwiros(USHORT p_port, UCHAR p_data_bit);
-UCHAR scvalq(UCHAR p_quintet);
-UCHAR scsell(USHORT p_port, UCHAR targ_id);
-void scwtsel(USHORT p_port);
-void inisci(UCHAR p_card, USHORT p_port, UCHAR p_our_id);
-void scsavdi(UCHAR p_card, USHORT p_port);
-#else
-int scarb(ULONG p_port, UCHAR p_sel_type);
-void scbusf(ULONG p_port);
-void scsel(ULONG p_port);
-void scasid(UCHAR p_card, ULONG p_port);
-UCHAR scxferc(ULONG p_port, UCHAR p_data);
-UCHAR scsendi(ULONG p_port, UCHAR p_id_string[]);
-UCHAR sciso(ULONG p_port, UCHAR p_id_string[]);
-void scwirod(ULONG p_port, UCHAR p_data_bit);
-void scwiros(ULONG p_port, UCHAR p_data_bit);
-UCHAR scvalq(UCHAR p_quintet);
-UCHAR scsell(ULONG p_port, UCHAR targ_id);
-void scwtsel(ULONG p_port);
-void inisci(UCHAR p_card, ULONG p_port, UCHAR p_our_id);
-void scsavdi(UCHAR p_card, ULONG p_port);
-#endif
-UCHAR scmachid(UCHAR p_card, UCHAR p_id_string[]);
-
-
-#if defined(DOS)
-void autoCmdCmplt(USHORT p_port, UCHAR p_card);
-void autoLoadDefaultMap(USHORT p_port);
-#else
-void autoCmdCmplt(ULONG p_port, UCHAR p_card);
-void autoLoadDefaultMap(ULONG p_port);
-#endif
-
-
-
-#if (FW_TYPE==_SCCB_MGR_)
- void OS_start_timer(unsigned long ioport, unsigned long timeout);
- void OS_stop_timer(unsigned long ioport, unsigned long timeout);
- void OS_disable_int(unsigned char intvec);
- void OS_enable_int(unsigned char intvec);
- void OS_delay(unsigned long count);
- int OS_VirtToPhys(u32bits CardHandle, u32bits *physaddr, u32bits *virtaddr);
- #if !(defined(UNIX) || defined(OS2) || defined(SOLARIS_REAL_MODE))
- void OS_Lock(PSCCBMGR_INFO pCardInfo);
- void OS_UnLock(PSCCBMGR_INFO pCardInfo);
-#endif // if FW_TYPE == ...
-
-#endif
-
-extern SCCBCARD BL_Card[MAX_CARDS];
-extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR];
-
-
-#if defined(OS2)
- extern void (far *s_PhaseTbl[8]) (ULONG, UCHAR);
-#else
- #if defined(DOS)
- extern void (*s_PhaseTbl[8]) (USHORT, UCHAR);
- #else
- extern void (*s_PhaseTbl[8]) (ULONG, UCHAR);
- #endif
-#endif
-extern SCCBSCAM_INFO scamInfo[MAX_SCSI_TAR];
-extern NVRAMINFO nvRamInfo[MAX_MB_CARDS];
-#if defined(DOS) || defined(OS2)
-extern UCHAR temp_id_string[ID_STRING_LENGTH];
-#endif
-extern UCHAR scamHAString[];
-extern UCHAR mbCards;
-#if defined(BUGBUG)
-extern UCHAR debug_int[MAX_CARDS][debug_size];
-extern UCHAR debug_index[MAX_CARDS];
-void Debug_Load(UCHAR p_card, UCHAR p_bug_data);
-#endif
+void busMstrAbort(ULONG port);
+static void FPT_dataXferProcessor(ULONG port, PSCCBcard pCurrCard);
+static void FPT_busMstrSGDataXferStart(ULONG port, PSCCB pCurrSCCB);
+static void FPT_busMstrDataXferStart(ULONG port, PSCCB pCurrSCCB);
+static void FPT_hostDataXferAbort(ULONG port, UCHAR p_card, PSCCB pCurrSCCB);
+static void FPT_hostDataXferRestart(PSCCB currSCCB);
-#if (FW_TYPE==_SCCB_MGR_)
-#if defined(DOS)
- extern UCHAR first_time;
-#endif
-#endif /* (FW_TYPE==_SCCB_MGR_) */
-#if (FW_TYPE==_UCB_MGR_)
-#if defined(DOS)
- extern u08bits first_time;
-#endif
-#endif /* (FW_TYPE==_UCB_MGR_) */
+static UCHAR FPT_SccbMgr_bad_isr(ULONG p_port, UCHAR p_card,
+ PSCCBcard pCurrCard, USHORT p_int);
-#if defined(BUGBUG)
-void Debug_Load(UCHAR p_card, UCHAR p_bug_data);
-#endif
+static void FPT_SccbMgrTableInitAll(void);
+static void FPT_SccbMgrTableInitCard(PSCCBcard pCurrCard, UCHAR p_card);
+static void FPT_SccbMgrTableInitTarget(UCHAR p_card, UCHAR target);
-extern unsigned int SccbGlobalFlags;
-#ident "$Id: sccb.c 1.18 1997/06/10 16:47:04 mohan Exp $"
-/*----------------------------------------------------------------------
- *
- *
- * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved
- *
- * This file is available under both the GNU General Public License
- * and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- * $Workfile: sccb.c $
- *
- * Description: Functions relating to handling of the SCCB interface
- * between the device driver and the HARPOON.
- *
- * $Date: 1997/06/10 16:47:04 $
- *
- * $Revision: 1.18 $
- *
- *----------------------------------------------------------------------*/
+static void FPT_scini(UCHAR p_card, UCHAR p_our_id, UCHAR p_power_up);
-/*#include <globals.h>*/
+static int FPT_scarb(ULONG p_port, UCHAR p_sel_type);
+static void FPT_scbusf(ULONG p_port);
+static void FPT_scsel(ULONG p_port);
+static void FPT_scasid(UCHAR p_card, ULONG p_port);
+static UCHAR FPT_scxferc(ULONG p_port, UCHAR p_data);
+static UCHAR FPT_scsendi(ULONG p_port, UCHAR p_id_string[]);
+static UCHAR FPT_sciso(ULONG p_port, UCHAR p_id_string[]);
+static void FPT_scwirod(ULONG p_port, UCHAR p_data_bit);
+static void FPT_scwiros(ULONG p_port, UCHAR p_data_bit);
+static UCHAR FPT_scvalq(UCHAR p_quintet);
+static UCHAR FPT_scsell(ULONG p_port, UCHAR targ_id);
+static void FPT_scwtsel(ULONG p_port);
+static void FPT_inisci(UCHAR p_card, ULONG p_port, UCHAR p_our_id);
+static void FPT_scsavdi(UCHAR p_card, ULONG p_port);
+static UCHAR FPT_scmachid(UCHAR p_card, UCHAR p_id_string[]);
-#if (FW_TYPE==_UCB_MGR_)
- /*#include <budi.h>*/
- /*#include <budioctl.h>*/
-#endif
-/*#include <sccbmgr.h>*/
-/*#include <blx30.h>*/
-/*#include <target.h>*/
-/*#include <eeprom.h>*/
-/*#include <scsi2.h>*/
-/*#include <harpoon.h>*/
+static void FPT_autoCmdCmplt(ULONG p_port, UCHAR p_card);
+static void FPT_autoLoadDefaultMap(ULONG p_port);
-#if (FW_TYPE==_SCCB_MGR_)
-#define mOS_Lock(card) OS_Lock((PSCCBMGR_INFO)(((PSCCBcard)card)->cardInfo))
-#define mOS_UnLock(card) OS_UnLock((PSCCBMGR_INFO)(((PSCCBcard)card)->cardInfo))
-#else /* FW_TYPE==_UCB_MGR_ */
-#define mOS_Lock(card) OS_Lock((u32bits)(((PSCCBcard)card)->ioPort))
-#define mOS_UnLock(card) OS_UnLock((u32bits)(((PSCCBcard)card)->ioPort))
-#endif
+void OS_start_timer(unsigned long ioport, unsigned long timeout);
+void OS_stop_timer(unsigned long ioport, unsigned long timeout);
+void OS_disable_int(unsigned char intvec);
+void OS_enable_int(unsigned char intvec);
+void OS_delay(unsigned long count);
+int OS_VirtToPhys(u32bits CardHandle, u32bits *physaddr, u32bits *virtaddr);
+static SCCBMGR_TAR_INFO FPT_sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] = { { { 0 } } };
+static SCCBCARD FPT_BL_Card[MAX_CARDS] = { { 0 } };
+static SCCBSCAM_INFO FPT_scamInfo[MAX_SCSI_TAR] = { { { 0 } } };
+static NVRAMINFO FPT_nvRamInfo[MAX_MB_CARDS] = { { 0 } };
-/*
-extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR];
-extern SCCBCARD BL_Card[MAX_CARDS];
-extern NVRAMINFO nvRamInfo[MAX_MB_CARDS];
-extern UCHAR mbCards;
+static UCHAR FPT_mbCards = 0;
+static UCHAR FPT_scamHAString[] = {0x63, 0x07, 'B', 'U', 'S', 'L', 'O', 'G', 'I', 'C', \
+ ' ', 'B', 'T', '-', '9', '3', '0', \
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, \
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
-#if defined (OS2)
- extern void (far *s_PhaseTbl[8]) (ULONG, UCHAR);
-#else
- #if defined(DOS)
- extern void (*s_PhaseTbl[8]) (USHORT, UCHAR);
- #else
- extern void (*s_PhaseTbl[8]) (ULONG, UCHAR);
- #endif
-#endif
+static USHORT FPT_default_intena = 0;
-#if defined(BUGBUG)
-extern UCHAR debug_int[MAX_CARDS][debug_size];
-extern UCHAR debug_index[MAX_CARDS];
-void Debug_Load(UCHAR p_card, UCHAR p_bug_data);
-#endif
-*/
+static void (*FPT_s_PhaseTbl[8]) (ULONG, UCHAR)= { 0 };
-#if (FW_TYPE==_SCCB_MGR_)
/*---------------------------------------------------------------------
*
@@ -2406,27 +1479,16 @@ void Debug_Load(UCHAR p_card, UCHAR p_bug_data);
*
*---------------------------------------------------------------------*/
-int SccbMgr_sense_adapter(PSCCBMGR_INFO pCardInfo)
+static int SccbMgr_sense_adapter(PSCCBMGR_INFO pCardInfo)
{
-#if defined(DOS)
-#else
static UCHAR first_time = 1;
-#endif
UCHAR i,j,id,ScamFlg;
USHORT temp,temp2,temp3,temp4,temp5,temp6;
-#if defined(DOS)
- USHORT ioport;
-#else
ULONG ioport;
-#endif
PNVRamInfo pCurrNvRam;
-#if defined(DOS)
- ioport = (USHORT)pCardInfo->si_baseaddr;
-#else
ioport = pCardInfo->si_baseaddr;
-#endif
if (RD_HARPOON(ioport+hp_vendor_id_0) != ORION_VEND_0)
@@ -2455,36 +1517,31 @@ int SccbMgr_sense_adapter(PSCCBMGR_INFO pCardInfo)
if (first_time)
{
- SccbMgrTableInitAll();
+ FPT_SccbMgrTableInitAll();
first_time = 0;
- mbCards = 0;
+ FPT_mbCards = 0;
}
- if(RdStack(ioport, 0) != 0x00) {
- if(ChkIfChipInitialized(ioport) == FALSE)
+ if(FPT_RdStack(ioport, 0) != 0x00) {
+ if(FPT_ChkIfChipInitialized(ioport) == 0)
{
pCurrNvRam = NULL;
WR_HARPOON(ioport+hp_semaphore, 0x00);
- XbowInit(ioport, 0); /*Must Init the SCSI before attempting */
- DiagEEPROM(ioport);
+ FPT_XbowInit(ioport, 0); /*Must Init the SCSI before attempting */
+ FPT_DiagEEPROM(ioport);
}
else
{
- if(mbCards < MAX_MB_CARDS) {
- pCurrNvRam = &nvRamInfo[mbCards];
- mbCards++;
+ if(FPT_mbCards < MAX_MB_CARDS) {
+ pCurrNvRam = &FPT_nvRamInfo[FPT_mbCards];
+ FPT_mbCards++;
pCurrNvRam->niBaseAddr = ioport;
- RNVRamData(pCurrNvRam);
+ FPT_RNVRamData(pCurrNvRam);
}else
return((int) FAILURE);
}
}else
pCurrNvRam = NULL;
-#if defined (NO_BIOS_OPTION)
- pCurrNvRam = NULL;
- XbowInit(ioport, 0); /*Must Init the SCSI before attempting */
- DiagEEPROM(ioport);
-#endif /* No BIOS Option */
WR_HARPOON(ioport+hp_clkctrl_0, CLKCTRL_DEFAULT);
WR_HARPOON(ioport+hp_sys_ctrl, 0x00);
@@ -2492,7 +1549,7 @@ int SccbMgr_sense_adapter(PSCCBMGR_INFO pCardInfo)
if(pCurrNvRam)
pCardInfo->si_id = pCurrNvRam->niAdapId;
else
- pCardInfo->si_id = (UCHAR)(utilEERead(ioport, (ADAPTER_SCSI_ID/2)) &
+ pCardInfo->si_id = (UCHAR)(FPT_utilEERead(ioport, (ADAPTER_SCSI_ID/2)) &
(UCHAR)0x0FF);
pCardInfo->si_lun = 0x00;
@@ -2510,7 +1567,7 @@ int SccbMgr_sense_adapter(PSCCBMGR_INFO pCardInfo)
temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
(((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
}else
- temp = utilEERead(ioport, (USHORT)((SYNC_RATE_TBL/2)+id));
+ temp = FPT_utilEERead(ioport, (USHORT)((SYNC_RATE_TBL/2)+id));
for (i = 0; i < 2; temp >>=8,i++) {
@@ -2549,12 +1606,12 @@ int SccbMgr_sense_adapter(PSCCBMGR_INFO pCardInfo)
if(pCurrNvRam)
i = pCurrNvRam->niSysConf;
else
- i = (UCHAR)(utilEERead(ioport, (SYSTEM_CONFIG/2)));
+ i = (UCHAR)(FPT_utilEERead(ioport, (SYSTEM_CONFIG/2)));
if(pCurrNvRam)
ScamFlg = pCurrNvRam->niScamConf;
else
- ScamFlg = (UCHAR) utilEERead(ioport, SCAM_CONFIG/2);
+ ScamFlg = (UCHAR) FPT_utilEERead(ioport, SCAM_CONFIG/2);
pCardInfo->si_flags = 0x0000;
@@ -2613,9 +1670,9 @@ int SccbMgr_sense_adapter(PSCCBMGR_INFO pCardInfo)
break;
}
}else{
- temp = utilEERead(ioport, (MODEL_NUMB_0/2));
+ temp = FPT_utilEERead(ioport, (MODEL_NUMB_0/2));
pCardInfo->si_card_model[0] = (UCHAR)(temp >> 8);
- temp = utilEERead(ioport, (MODEL_NUMB_2/2));
+ temp = FPT_utilEERead(ioport, (MODEL_NUMB_2/2));
pCardInfo->si_card_model[1] = (UCHAR)(temp & 0x00FF);
pCardInfo->si_card_model[2] = (UCHAR)(temp >> 8);
@@ -2677,29 +1734,17 @@ int SccbMgr_sense_adapter(PSCCBMGR_INFO pCardInfo)
SGRAM_ACCESS(ioport);
- s_PhaseTbl[0] = phaseDataOut;
- s_PhaseTbl[1] = phaseDataIn;
- s_PhaseTbl[2] = phaseIllegal;
- s_PhaseTbl[3] = phaseIllegal;
- s_PhaseTbl[4] = phaseCommand;
- s_PhaseTbl[5] = phaseStatus;
- s_PhaseTbl[6] = phaseMsgOut;
- s_PhaseTbl[7] = phaseMsgIn;
+ FPT_s_PhaseTbl[0] = FPT_phaseDataOut;
+ FPT_s_PhaseTbl[1] = FPT_phaseDataIn;
+ FPT_s_PhaseTbl[2] = FPT_phaseIllegal;
+ FPT_s_PhaseTbl[3] = FPT_phaseIllegal;
+ FPT_s_PhaseTbl[4] = FPT_phaseCommand;
+ FPT_s_PhaseTbl[5] = FPT_phaseStatus;
+ FPT_s_PhaseTbl[6] = FPT_phaseMsgOut;
+ FPT_s_PhaseTbl[7] = FPT_phaseMsgIn;
pCardInfo->si_present = 0x01;
-#if defined(BUGBUG)
-
-
- for (i = 0; i < MAX_CARDS; i++) {
-
- for (id=0; id<debug_size; id++)
- debug_int[i][id] = (UCHAR)0x00;
- debug_index[i] = 0;
- }
-
-#endif
-
return(0);
}
@@ -2712,27 +1757,15 @@ int SccbMgr_sense_adapter(PSCCBMGR_INFO pCardInfo)
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-USHORT SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo)
-#else
-ULONG SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo)
-#endif
+static ULONG SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo)
{
PSCCBcard CurrCard = NULL;
PNVRamInfo pCurrNvRam;
UCHAR i,j,thisCard, ScamFlg;
USHORT temp,sync_bit_map,id;
-#if defined(DOS)
- USHORT ioport;
-#else
ULONG ioport;
-#endif
-#if defined(DOS)
- ioport = (USHORT)pCardInfo->si_baseaddr;
-#else
ioport = pCardInfo->si_baseaddr;
-#endif
for(thisCard =0; thisCard <= MAX_CARDS; thisCard++) {
@@ -2741,24 +1774,24 @@ ULONG SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo)
return(FAILURE);
}
- if (BL_Card[thisCard].ioPort == ioport) {
+ if (FPT_BL_Card[thisCard].ioPort == ioport) {
- CurrCard = &BL_Card[thisCard];
- SccbMgrTableInitCard(CurrCard,thisCard);
+ CurrCard = &FPT_BL_Card[thisCard];
+ FPT_SccbMgrTableInitCard(CurrCard,thisCard);
break;
}
- else if (BL_Card[thisCard].ioPort == 0x00) {
+ else if (FPT_BL_Card[thisCard].ioPort == 0x00) {
- BL_Card[thisCard].ioPort = ioport;
- CurrCard = &BL_Card[thisCard];
+ FPT_BL_Card[thisCard].ioPort = ioport;
+ CurrCard = &FPT_BL_Card[thisCard];
- if(mbCards)
- for(i = 0; i < mbCards; i++){
- if(CurrCard->ioPort == nvRamInfo[i].niBaseAddr)
- CurrCard->pNvRamInfo = &nvRamInfo[i];
+ if(FPT_mbCards)
+ for(i = 0; i < FPT_mbCards; i++){
+ if(CurrCard->ioPort == FPT_nvRamInfo[i].niBaseAddr)
+ CurrCard->pNvRamInfo = &FPT_nvRamInfo[i];
}
- SccbMgrTableInitCard(CurrCard,thisCard);
+ FPT_SccbMgrTableInitCard(CurrCard,thisCard);
CurrCard->cardIndex = thisCard;
CurrCard->cardInfo = pCardInfo;
@@ -2772,22 +1805,14 @@ ULONG SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo)
ScamFlg = pCurrNvRam->niScamConf;
}
else{
- ScamFlg = (UCHAR) utilEERead(ioport, SCAM_CONFIG/2);
+ ScamFlg = (UCHAR) FPT_utilEERead(ioport, SCAM_CONFIG/2);
}
- BusMasterInit(ioport);
- XbowInit(ioport, ScamFlg);
-
-#if defined (NO_BIOS_OPTION)
+ FPT_BusMasterInit(ioport);
+ FPT_XbowInit(ioport, ScamFlg);
-
- if (DiagXbow(ioport)) return(FAILURE);
- if (DiagBusMaster(ioport)) return(FAILURE);
-
-#endif /* No BIOS Option */
-
- autoLoadDefaultMap(ioport);
+ FPT_autoLoadDefaultMap(ioport);
for (i = 0,id = 0x01; i != pCardInfo->si_id; i++,id <<= 1){}
@@ -2814,9 +1839,9 @@ ULONG SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo)
if (!(pCardInfo->si_flags & SOFT_RESET)) {
- sresb(ioport,thisCard);
+ FPT_sresb(ioport,thisCard);
- scini(thisCard, pCardInfo->si_id, 0);
+ FPT_scini(thisCard, pCardInfo->si_id, 0);
}
@@ -2829,7 +1854,7 @@ ULONG SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo)
CurrCard->globalFlags |= F_GREEN_PC;
}
else{
- if (utilEERead(ioport, (SYSTEM_CONFIG/2)) & GREEN_PC_ENA)
+ if (FPT_utilEERead(ioport, (SYSTEM_CONFIG/2)) & GREEN_PC_ENA)
CurrCard->globalFlags |= F_GREEN_PC;
}
@@ -2840,7 +1865,7 @@ ULONG SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo)
CurrCard->globalFlags |= F_DO_RENEGO;
}
else{
- if (utilEERead(ioport, (SCSI_CONFIG/2)) & RENEGO_ENA)
+ if (FPT_utilEERead(ioport, (SCSI_CONFIG/2)) & RENEGO_ENA)
CurrCard->globalFlags |= F_DO_RENEGO;
}
@@ -2849,7 +1874,7 @@ ULONG SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo)
CurrCard->globalFlags |= F_CONLUN_IO;
}
else{
- if (utilEERead(ioport, (SCSI_CONFIG/2)) & CONNIO_ENA)
+ if (FPT_utilEERead(ioport, (SCSI_CONFIG/2)) & CONNIO_ENA)
CurrCard->globalFlags |= F_CONLUN_IO;
}
@@ -2859,7 +1884,7 @@ ULONG SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo)
for (i = 0,id = 1; i < MAX_SCSI_TAR; i++, id <<= 1) {
if (temp & id)
- sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC;
+ FPT_sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC;
}
sync_bit_map = 0x0001;
@@ -2871,39 +1896,34 @@ ULONG SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo)
temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
(((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
}else
- temp = utilEERead(ioport, (USHORT)((SYNC_RATE_TBL/2)+id));
+ temp = FPT_utilEERead(ioport, (USHORT)((SYNC_RATE_TBL/2)+id));
for (i = 0; i < 2; temp >>=8,i++) {
if (pCardInfo->si_per_targ_init_sync & sync_bit_map) {
- sccbMgrTbl[thisCard][id*2+i].TarEEValue = (UCHAR)temp;
+ FPT_sccbMgrTbl[thisCard][id*2+i].TarEEValue = (UCHAR)temp;
}
else {
- sccbMgrTbl[thisCard][id*2+i].TarStatus |= SYNC_SUPPORTED;
- sccbMgrTbl[thisCard][id*2+i].TarEEValue =
+ FPT_sccbMgrTbl[thisCard][id*2+i].TarStatus |= SYNC_SUPPORTED;
+ FPT_sccbMgrTbl[thisCard][id*2+i].TarEEValue =
(UCHAR)(temp & ~EE_SYNC_MASK);
}
-#if defined(WIDE_SCSI)
/* if ((pCardInfo->si_per_targ_wide_nego & sync_bit_map) ||
(id*2+i >= 8)){
*/
if (pCardInfo->si_per_targ_wide_nego & sync_bit_map){
- sccbMgrTbl[thisCard][id*2+i].TarEEValue |= EE_WIDE_SCSI;
+ FPT_sccbMgrTbl[thisCard][id*2+i].TarEEValue |= EE_WIDE_SCSI;
}
else { /* NARROW SCSI */
- sccbMgrTbl[thisCard][id*2+i].TarStatus |= WIDE_NEGOCIATED;
+ FPT_sccbMgrTbl[thisCard][id*2+i].TarStatus |= WIDE_NEGOCIATED;
}
-#else
- sccbMgrTbl[thisCard][id*2+i].TarStatus |= WIDE_NEGOCIATED;
-#endif
-
sync_bit_map <<= 1;
@@ -2915,1285 +1935,97 @@ ULONG SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo)
WR_HARPOON((ioport+hp_semaphore),
(UCHAR)(RD_HARPOON((ioport+hp_semaphore)) | SCCB_MGR_PRESENT));
-#if defined(DOS)
- return((USHORT)CurrCard);
-#else
return((ULONG)CurrCard);
-#endif
}
-#else /* end (FW_TYPE==_SCCB_MGR_) */
-
-
-
-STATIC s16bits FP_PresenceCheck(PMGR_INFO pMgrInfo)
-{
- PMGR_ENTRYPNTS pMgr_EntryPnts = &pMgrInfo->mi_Functions;
-
- pMgr_EntryPnts->UCBMgr_probe_adapter = probe_adapter;
- pMgr_EntryPnts->UCBMgr_init_adapter = init_adapter;
- pMgr_EntryPnts->UCBMgr_start_UCB = SccbMgr_start_sccb;
- pMgr_EntryPnts->UCBMgr_build_UCB = build_UCB;
- pMgr_EntryPnts->UCBMgr_abort_UCB = SccbMgr_abort_sccb;
- pMgr_EntryPnts->UCBMgr_my_int = SccbMgr_my_int;
- pMgr_EntryPnts->UCBMgr_isr = SccbMgr_isr;
- pMgr_EntryPnts->UCBMgr_scsi_reset = SccbMgr_scsi_reset;
- pMgr_EntryPnts->UCBMgr_timer_expired = SccbMgr_timer_expired;
-#ifndef NO_IOCTLS
- pMgr_EntryPnts->UCBMgr_unload_card = SccbMgr_unload_card;
- pMgr_EntryPnts->UCBMgr_save_foreign_state =
- SccbMgr_save_foreign_state;
- pMgr_EntryPnts->UCBMgr_restore_foreign_state =
- SccbMgr_restore_foreign_state;
- pMgr_EntryPnts->UCBMgr_restore_native_state =
- SccbMgr_restore_native_state;
-#endif /*NO_IOCTLS*/
-
- pMgrInfo->mi_SGListFormat=0x01;
- pMgrInfo->mi_DataPtrFormat=0x01;
- pMgrInfo->mi_MaxSGElements= (u16bits) 0xffffffff;
- pMgrInfo->mi_MgrPrivateLen=sizeof(SCCB);
- pMgrInfo->mi_PCIVendorID=BL_VENDOR_ID;
- pMgrInfo->mi_PCIDeviceID=FP_DEVICE_ID;
- pMgrInfo->mi_MgrAttributes= ATTR_IO_MAPPED +
- ATTR_PHYSICAL_ADDRESS +
- ATTR_VIRTUAL_ADDRESS +
- ATTR_OVERLAPPED_IO_IOCTLS_OK;
- pMgrInfo->mi_IoRangeLen = 256;
- return(0);
-}
-
-
-
-/*---------------------------------------------------------------------
- *
- * Function: probe_adapter
- *
- * Description: Setup and/or Search for cards and return info to caller.
- *
- *---------------------------------------------------------------------*/
-STATIC s32bits probe_adapter(PADAPTER_INFO pAdapterInfo)
-{
- u16bits temp,temp2,temp3,temp4;
- u08bits i,j,id;
-
-#if defined(DOS)
-#else
- static u08bits first_time = 1;
-#endif
- BASE_PORT ioport;
- PNVRamInfo pCurrNvRam;
-
- ioport = (BASE_PORT)pAdapterInfo->ai_baseaddr;
-
-
-
- if (RD_HARPOON(ioport+hp_vendor_id_0) != ORION_VEND_0)
- return(1);
-
- if ((RD_HARPOON(ioport+hp_vendor_id_1) != ORION_VEND_1))
- return(2);
-
- if ((RD_HARPOON(ioport+hp_device_id_0) != ORION_DEV_0))
- return(3);
-
- if ((RD_HARPOON(ioport+hp_device_id_1) != ORION_DEV_1))
- return(4);
-
-
- if (RD_HARPOON(ioport+hp_rev_num) != 0x0f){
-
-
-/* For new Harpoon then check for sub_device ID LSB
- the bits(0-3) must be all ZERO for compatible with
- current version of SCCBMgr, else skip this Harpoon
- device. */
-
- if (RD_HARPOON(ioport+hp_sub_device_id_0) & 0x0f)
- return(5);
- }
-
- if (first_time) {
-
- SccbMgrTableInitAll();
- first_time = 0;
- mbCards = 0;
- }
-
- if(RdStack(ioport, 0) != 0x00) {
- if(ChkIfChipInitialized(ioport) == FALSE)
- {
- pCurrNvRam = NULL;
- WR_HARPOON(ioport+hp_semaphore, 0x00);
- XbowInit(ioport, 0); /*Must Init the SCSI before attempting */
- DiagEEPROM(ioport);
- }
- else
- {
- if(mbCards < MAX_MB_CARDS) {
- pCurrNvRam = &nvRamInfo[mbCards];
- mbCards++;
- pCurrNvRam->niBaseAddr = ioport;
- RNVRamData(pCurrNvRam);
- }else
- return((int) FAILURE);
- }
- }else
- pCurrNvRam = NULL;
-
-#if defined (NO_BIOS_OPTION)
- pCurrNvRam = NULL;
- XbowInit(ioport, 0); /*Must Init the SCSI before attempting */
- DiagEEPROM(ioport);
-#endif /* No BIOS Option */
-
- WR_HARPOON(ioport+hp_clkctrl_0, CLKCTRL_DEFAULT);
- WR_HARPOON(ioport+hp_sys_ctrl, 0x00);
-
- if(pCurrNvRam)
- pAdapterInfo->ai_id = pCurrNvRam->niAdapId;
- else
- pAdapterInfo->ai_id = (u08bits)(utilEERead(ioport, (ADAPTER_SCSI_ID/2)) &
- (u08bits)0x0FF);
-
- pAdapterInfo->ai_lun = 0x00;
- pAdapterInfo->ai_fw_revision[0] = '3';
- pAdapterInfo->ai_fw_revision[1] = '1';
- pAdapterInfo->ai_fw_revision[2] = '1';
- pAdapterInfo->ai_fw_revision[3] = ' ';
- pAdapterInfo->ai_NumChannels = 1;
-
- temp2 = 0x0000;
- temp3 = 0x0000;
- temp4 = 0x0000;
-
- for (id = 0; id < (16/2); id++) {
-
- if(pCurrNvRam){
- temp = (USHORT) pCurrNvRam->niSyncTbl[id];
- temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
- (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
- }else
- temp = utilEERead(ioport, (u16bits)((SYNC_RATE_TBL/2)+id));
-
- for (i = 0; i < 2; temp >>=8,i++) {
-
- if ((temp & 0x03) != AUTO_RATE_00) {
-
- temp2 >>= 0x01;
- temp2 |= 0x8000;
- }
-
- else {
- temp2 >>= 0x01;
- }
-
- if (temp & DISC_ENABLE_BIT) {
-
- temp3 >>= 0x01;
- temp3 |= 0x8000;
- }
-
- else {
- temp3 >>= 0x01;
- }
-
- if (temp & WIDE_NEGO_BIT) {
-
- temp4 >>= 0x01;
- temp4 |= 0x8000;
- }
-
- else {
- temp4 >>= 0x01;
- }
-
- }
- }
-
- pAdapterInfo->ai_per_targ_init_sync = temp2;
- pAdapterInfo->ai_per_targ_no_disc = temp3;
- pAdapterInfo->ai_per_targ_wide_nego = temp4;
- if(pCurrNvRam)
- i = pCurrNvRam->niSysConf;
- else
- i = (u08bits)(utilEERead(ioport, (SYSTEM_CONFIG/2)));
-
- /*
- ** interrupts always level-triggered for FlashPoint
- */
- pAdapterInfo->ai_stateinfo |= LEVEL_TRIG;
-
- if (i & 0x01)
- pAdapterInfo->ai_stateinfo |= SCSI_PARITY_ENA;
-
- if (i & 0x02) /* SCSI Bus reset in AutoSCSI Set ? */
- {
- if(pCurrNvRam)
- {
- j = pCurrNvRam->niScamConf;
- }
- else
- {
- j = (u08bits) utilEERead(ioport, SCAM_CONFIG/2);
- }
- if(j & SCAM_ENABLED)
- {
- if(j & SCAM_LEVEL2)
- {
- pAdapterInfo->ai_stateinfo |= SCAM2_ENA;
- }
- else
- {
- pAdapterInfo->ai_stateinfo |= SCAM1_ENA;
- }
- }
- }
- j = (RD_HARPOON(ioport+hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
- if (i & 0x04) {
- j |= SCSI_TERM_ENA_L;
- pAdapterInfo->ai_stateinfo |= LOW_BYTE_TERM_ENA;
- }
- WR_HARPOON(ioport+hp_bm_ctrl, j );
-
- j = (RD_HARPOON(ioport+hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
- if (i & 0x08) {
- j |= SCSI_TERM_ENA_H;
- pAdapterInfo->ai_stateinfo |= HIGH_BYTE_TERM_ENA;
- }
- WR_HARPOON(ioport+hp_ee_ctrl, j );
-
- if(RD_HARPOON(ioport + hp_page_ctrl) & BIOS_SHADOW)
- {
- pAdapterInfo->ai_FlashRomSize = 64 * 1024; /* 64k ROM */
- }
- else
- {
- pAdapterInfo->ai_FlashRomSize = 32 * 1024; /* 32k ROM */
- }
-
- pAdapterInfo->ai_stateinfo |= (FAST20_ENA | TAG_QUEUE_ENA);
- if (!(RD_HARPOON(ioport+hp_page_ctrl) & NARROW_SCSI_CARD))
- {
- pAdapterInfo->ai_attributes |= (WIDE_CAPABLE | FAST20_CAPABLE
- | SCAM2_CAPABLE
- | TAG_QUEUE_CAPABLE
- | SUPRESS_UNDERRRUNS_CAPABLE
- | SCSI_PARITY_CAPABLE);
- pAdapterInfo->ai_MaxTarg = 16;
- pAdapterInfo->ai_MaxLun = 32;
- }
- else
- {
- pAdapterInfo->ai_attributes |= (FAST20_CAPABLE | SCAM2_CAPABLE
- | TAG_QUEUE_CAPABLE
- | SUPRESS_UNDERRRUNS_CAPABLE
- | SCSI_PARITY_CAPABLE);
- pAdapterInfo->ai_MaxTarg = 8;
- pAdapterInfo->ai_MaxLun = 8;
- }
-
- pAdapterInfo->ai_product_family = HARPOON_FAMILY;
- pAdapterInfo->ai_HBAbustype = BUSTYPE_PCI;
-
- for (i=0;i<CARD_MODEL_NAMELEN;i++)
- {
- pAdapterInfo->ai_card_model[i]=' '; /* initialize the ai_card_model */
- }
-
- if(pCurrNvRam){
- pAdapterInfo->ai_card_model[0] = '9';
- switch(pCurrNvRam->niModel & 0x0f){
- case MODEL_LT:
- pAdapterInfo->ai_card_model[1] = '3';
- pAdapterInfo->ai_card_model[2] = '0';
- break;
- case MODEL_LW:
- pAdapterInfo->ai_card_model[1] = '5';
- pAdapterInfo->ai_card_model[2] = '0';
- break;
- case MODEL_DL:
- pAdapterInfo->ai_card_model[1] = '3';
- pAdapterInfo->ai_card_model[2] = '2';
- break;
- case MODEL_DW:
- pAdapterInfo->ai_card_model[1] = '5';
- pAdapterInfo->ai_card_model[2] = '2';
- break;
- }
- }else{
- temp = utilEERead(ioport, (MODEL_NUMB_0/2));
- pAdapterInfo->ai_card_model[0] = (u08bits)(temp >> 8);
- temp = utilEERead(ioport, (MODEL_NUMB_2/2));
-
- pAdapterInfo->ai_card_model[1] = (u08bits)(temp & 0x00FF);
- pAdapterInfo->ai_card_model[2] = (u08bits)(temp >> 8);
- }
-
-
-
- pAdapterInfo->ai_FiberProductType = 0;
-
- pAdapterInfo->ai_secondary_range = 0;
-
- for (i=0;i<WORLD_WIDE_NAMELEN;i++)
- {
- pAdapterInfo->ai_worldwidename[i]='\0';
- }
-
- for (i=0;i<VENDOR_NAMELEN;i++)
- {
- pAdapterInfo->ai_vendorstring[i]='\0';
- }
- pAdapterInfo->ai_vendorstring[0]='B';
- pAdapterInfo->ai_vendorstring[1]='U';
- pAdapterInfo->ai_vendorstring[2]='S';
- pAdapterInfo->ai_vendorstring[3]='L';
- pAdapterInfo->ai_vendorstring[4]='O';
- pAdapterInfo->ai_vendorstring[5]='G';
- pAdapterInfo->ai_vendorstring[6]='I';
- pAdapterInfo->ai_vendorstring[7]='C';
-
- for (i=0;i<FAMILY_NAMELEN;i++)
- {
- pAdapterInfo->ai_AdapterFamilyString[i]='\0';
- }
- pAdapterInfo->ai_AdapterFamilyString[0]='F';
- pAdapterInfo->ai_AdapterFamilyString[1]='L';
- pAdapterInfo->ai_AdapterFamilyString[2]='A';
- pAdapterInfo->ai_AdapterFamilyString[3]='S';
- pAdapterInfo->ai_AdapterFamilyString[4]='H';
- pAdapterInfo->ai_AdapterFamilyString[5]='P';
- pAdapterInfo->ai_AdapterFamilyString[6]='O';
- pAdapterInfo->ai_AdapterFamilyString[7]='I';
- pAdapterInfo->ai_AdapterFamilyString[8]='N';
- pAdapterInfo->ai_AdapterFamilyString[9]='T';
-
- ARAM_ACCESS(ioport);
-
- for ( i = 0; i < 4; i++ ) {
-
- pAdapterInfo->ai_XlatInfo[i] =
- RD_HARPOON(ioport+hp_aramBase+BIOS_DATA_OFFSET+i);
- }
-
- /* return with -1 if no sort, else return with
- logical card number sorted by BIOS (zero-based) */
-
-
- pAdapterInfo->ai_relative_cardnum =
- (u08bits)(RD_HARPOON(ioport+hp_aramBase+BIOS_RELATIVE_CARD)-1);
-
- SGRAM_ACCESS(ioport);
-
- s_PhaseTbl[0] = phaseDataOut;
- s_PhaseTbl[1] = phaseDataIn;
- s_PhaseTbl[2] = phaseIllegal;
- s_PhaseTbl[3] = phaseIllegal;
- s_PhaseTbl[4] = phaseCommand;
- s_PhaseTbl[5] = phaseStatus;
- s_PhaseTbl[6] = phaseMsgOut;
- s_PhaseTbl[7] = phaseMsgIn;
-
- pAdapterInfo->ai_present = 0x01;
-
-#if defined(BUGBUG)
-
-
- for (i = 0; i < MAX_CARDS; i++) {
-
- for (id=0; id<debug_size; id++)
- debug_int[i][id] = (u08bits)0x00;
- debug_index[i] = 0;
- }
-
-#endif
-
- return(0);
-}
-
-
-
-
-
-/*---------------------------------------------------------------------
- *
- * Function: init_adapter, exported to BUDI via UCBMgr_init_adapter entry
- *
- *
- * Description: Setup adapter for normal operation (hard reset).
- *
- *---------------------------------------------------------------------*/
-STATIC CARD_HANDLE init_adapter(PADAPTER_INFO pCardInfo)
-{
- PSCCBcard CurrCard;
- PNVRamInfo pCurrNvRam;
- u08bits i,j,thisCard, ScamFlg;
- u16bits temp,sync_bit_map,id;
- BASE_PORT ioport;
-
- ioport = (BASE_PORT)pCardInfo->ai_baseaddr;
-
- for(thisCard =0; thisCard <= MAX_CARDS; thisCard++) {
-
- if (thisCard == MAX_CARDS) {
-
- return(FAILURE);
- }
-
- if (BL_Card[thisCard].ioPort == ioport) {
-
- CurrCard = &BL_Card[thisCard];
- SccbMgrTableInitCard(CurrCard,thisCard);
- break;
- }
-
- else if (BL_Card[thisCard].ioPort == 0x00) {
-
- BL_Card[thisCard].ioPort = ioport;
- CurrCard = &BL_Card[thisCard];
-
- if(mbCards)
- for(i = 0; i < mbCards; i++){
- if(CurrCard->ioPort == nvRamInfo[i].niBaseAddr)
- CurrCard->pNvRamInfo = &nvRamInfo[i];
- }
- SccbMgrTableInitCard(CurrCard,thisCard);
- CurrCard->cardIndex = thisCard;
- CurrCard->cardInfo = pCardInfo;
-
- break;
- }
- }
-
- pCurrNvRam = CurrCard->pNvRamInfo;
-
-
- if(pCurrNvRam){
- ScamFlg = pCurrNvRam->niScamConf;
- }
- else{
- ScamFlg = (UCHAR) utilEERead(ioport, SCAM_CONFIG/2);
- }
-
-
- BusMasterInit(ioport);
- XbowInit(ioport, ScamFlg);
-
-#if defined (NO_BIOS_OPTION)
-
-
- if (DiagXbow(ioport)) return(FAILURE);
- if (DiagBusMaster(ioport)) return(FAILURE);
-
-#endif /* No BIOS Option */
-
- autoLoadDefaultMap(ioport);
-
-
- for (i = 0,id = 0x01; i != pCardInfo->ai_id; i++,id <<= 1){}
-
- WR_HARPOON(ioport+hp_selfid_0, id);
- WR_HARPOON(ioport+hp_selfid_1, 0x00);
- WR_HARPOON(ioport+hp_arb_id, pCardInfo->ai_id);
- CurrCard->ourId = (unsigned char) pCardInfo->ai_id;
-
- i = (u08bits) pCardInfo->ai_stateinfo;
- if (i & SCSI_PARITY_ENA)
- WR_HARPOON(ioport+hp_portctrl_1,(HOST_MODE8 | CHK_SCSI_P));
-
- j = (RD_HARPOON(ioport+hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
- if (i & LOW_BYTE_TERM_ENA)
- j |= SCSI_TERM_ENA_L;
- WR_HARPOON(ioport+hp_bm_ctrl, j);
-
- j = (RD_HARPOON(ioport+hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
- if (i & HIGH_BYTE_TERM_ENA)
- j |= SCSI_TERM_ENA_H;
- WR_HARPOON(ioport+hp_ee_ctrl, j );
-
-
- if (!(pCardInfo->ai_stateinfo & NO_RESET_IN_INIT)) {
-
- sresb(ioport,thisCard);
-
- scini(thisCard, (u08bits) pCardInfo->ai_id, 0);
- }
-
-
-
- if (pCardInfo->ai_stateinfo & SUPRESS_UNDERRRUNS_ENA)
- CurrCard->globalFlags |= F_NO_FILTER;
-
- if(pCurrNvRam){
- if(pCurrNvRam->niSysConf & 0x10)
- CurrCard->globalFlags |= F_GREEN_PC;
- }
- else{
- if (utilEERead(ioport, (SYSTEM_CONFIG/2)) & GREEN_PC_ENA)
- CurrCard->globalFlags |= F_GREEN_PC;
- }
-
- /* Set global flag to indicate Re-Negotiation to be done on all
- ckeck condition */
- if(pCurrNvRam){
- if(pCurrNvRam->niScsiConf & 0x04)
- CurrCard->globalFlags |= F_DO_RENEGO;
- }
- else{
- if (utilEERead(ioport, (SCSI_CONFIG/2)) & RENEGO_ENA)
- CurrCard->globalFlags |= F_DO_RENEGO;
- }
-
- if(pCurrNvRam){
- if(pCurrNvRam->niScsiConf & 0x08)
- CurrCard->globalFlags |= F_CONLUN_IO;
- }
- else{
- if (utilEERead(ioport, (SCSI_CONFIG/2)) & CONNIO_ENA)
- CurrCard->globalFlags |= F_CONLUN_IO;
- }
-
- temp = pCardInfo->ai_per_targ_no_disc;
-
- for (i = 0,id = 1; i < MAX_SCSI_TAR; i++, id <<= 1) {
-
- if (temp & id)
- sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC;
- }
-
- sync_bit_map = 0x0001;
-
- for (id = 0; id < (MAX_SCSI_TAR/2); id++){
-
- if(pCurrNvRam){
- temp = (USHORT) pCurrNvRam->niSyncTbl[id];
- temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
- (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
- }else
- temp = utilEERead(ioport, (u16bits)((SYNC_RATE_TBL/2)+id));
-
- for (i = 0; i < 2; temp >>=8,i++){
-
- if (pCardInfo->ai_per_targ_init_sync & sync_bit_map){
-
- sccbMgrTbl[thisCard][id*2+i].TarEEValue = (u08bits)temp;
- }
-
- else {
- sccbMgrTbl[thisCard][id*2+i].TarStatus |= SYNC_SUPPORTED;
- sccbMgrTbl[thisCard][id*2+i].TarEEValue =
- (u08bits)(temp & ~EE_SYNC_MASK);
- }
-
-#if defined(WIDE_SCSI)
-/* if ((pCardInfo->ai_per_targ_wide_nego & sync_bit_map) ||
- (id*2+i >= 8)){
-*/
- if (pCardInfo->ai_per_targ_wide_nego & sync_bit_map){
-
- sccbMgrTbl[thisCard][id*2+i].TarEEValue |= EE_WIDE_SCSI;
-
- }
-
- else { /* NARROW SCSI */
- sccbMgrTbl[thisCard][id*2+i].TarStatus |= WIDE_NEGOCIATED;
- }
-
-#else
- sccbMgrTbl[thisCard][id*2+i].TarStatus |= WIDE_NEGOCIATED;
-#endif
-
-
- sync_bit_map <<= 1;
- }
- }
-
-
- pCardInfo->ai_SGListFormat=0x01;
- pCardInfo->ai_DataPtrFormat=0x01;
- pCardInfo->ai_AEN_mask &= SCSI_RESET_COMPLETE;
-
- WR_HARPOON((ioport+hp_semaphore),
- (u08bits)(RD_HARPOON((ioport+hp_semaphore)) | SCCB_MGR_PRESENT));
-
- return((u32bits)CurrCard);
-
-}
-
-
-/*---------------------------------------------------------------------
- *
- * Function: build_ucb, exported to BUDI via UCBMgr_build_ucb entry
- *
- * Description: prepare fw portion of ucb. do not start, resource not guaranteed
- * so don't manipulate anything that's derived from states which
- * may change
- *
- *---------------------------------------------------------------------*/
-void build_UCB(CARD_HANDLE pCurrCard, PUCB p_ucb)
-{
-
- u08bits thisCard;
- u08bits i,j;
-
- PSCCB p_sccb;
-
-
- thisCard = ((PSCCBcard) pCurrCard)->cardIndex;
-
-
- p_sccb=(PSCCB)p_ucb->UCB_MgrPrivatePtr;
-
-
- p_sccb->Sccb_ucb_ptr=p_ucb;
-
- switch (p_ucb->UCB_opcode & (OPC_DEVICE_RESET+OPC_XFER_SG+OPC_CHK_RESIDUAL))
- {
- case OPC_DEVICE_RESET:
- p_sccb->OperationCode=RESET_COMMAND;
- break;
- case OPC_XFER_SG:
- p_sccb->OperationCode=SCATTER_GATHER_COMMAND;
- break;
- case OPC_XFER_SG+OPC_CHK_RESIDUAL:
- p_sccb->OperationCode=RESIDUAL_SG_COMMAND;
- break;
- case OPC_CHK_RESIDUAL:
-
- p_sccb->OperationCode=RESIDUAL_COMMAND;
- break;
- default:
- p_sccb->OperationCode=SCSI_INITIATOR_COMMAND;
- break;
- }
-
- if (p_ucb->UCB_opcode & OPC_TQ_ENABLE)
- {
- p_sccb->ControlByte = (u08bits)((p_ucb->UCB_opcode & OPC_TQ_MASK)>>2) | F_USE_CMD_Q;
- }
- else
- {
- p_sccb->ControlByte = 0;
- }
-
-
- p_sccb->CdbLength = (u08bits)p_ucb->UCB_cdblen;
-
- if (p_ucb->UCB_opcode & OPC_NO_AUTO_SENSE)
- {
- p_sccb->RequestSenseLength = 0;
- }
- else
- {
- p_sccb->RequestSenseLength = (unsigned char) p_ucb->UCB_senselen;
- }
-
-
- if (p_ucb->UCB_opcode & OPC_XFER_SG)
- {
- p_sccb->DataPointer=p_ucb->UCB_virt_dataptr;
- p_sccb->DataLength = (((u32bits)p_ucb->UCB_NumSgElements)<<3);
- }
- else
- {
- p_sccb->DataPointer=p_ucb->UCB_phys_dataptr;
- p_sccb->DataLength=p_ucb->UCB_datalen;
- };
-
- p_sccb->HostStatus=0;
- p_sccb->TargetStatus=0;
- p_sccb->TargID=(unsigned char)p_ucb->UCB_targid;
- p_sccb->Lun=(unsigned char) p_ucb->UCB_lun;
- p_sccb->SccbIOPort=((PSCCBcard)pCurrCard)->ioPort;
-
- j=p_ucb->UCB_cdblen;
- for (i=0;i<j;i++)
- {
- p_sccb->Cdb[i] = p_ucb->UCB_cdb[i];
- }
-
- p_sccb->SensePointer=p_ucb->UCB_phys_senseptr;
-
- sinits(p_sccb,thisCard);
-
-}
-#ifndef NO_IOCTLS
-
-/*---------------------------------------------------------------------
- *
- * Function: GetDevSyncRate
- *
- *---------------------------------------------------------------------*/
-STATIC int GetDevSyncRate(PSCCBcard pCurrCard,PUCB p_ucb)
-{
- struct _SYNC_RATE_INFO * pSyncStr;
- PSCCBMgr_tar_info currTar_Info;
- BASE_PORT ioport;
- u08bits scsiID, j;
-
-#if (FW_TYPE != _SCCB_MGR_)
- if( p_ucb->UCB_targid >= pCurrCard->cardInfo->ai_MaxTarg )
- {
- return(1);
- }
-#endif
-
- ioport = pCurrCard->ioPort;
- pSyncStr = (struct _SYNC_RATE_INFO *) p_ucb->UCB_virt_dataptr;
- scsiID = (u08bits) p_ucb->UCB_targid;
- currTar_Info = &sccbMgrTbl[pCurrCard->cardIndex][scsiID];
- j = currTar_Info->TarSyncCtrl;
-
- switch (currTar_Info->TarEEValue & EE_SYNC_MASK)
- {
- case EE_SYNC_ASYNC:
- pSyncStr->RequestMegaXferRate = 0x00;
- break;
- case EE_SYNC_5MB:
- pSyncStr->RequestMegaXferRate = (j & NARROW_SCSI) ? 50 : 100;
- break;
- case EE_SYNC_10MB:
- pSyncStr->RequestMegaXferRate = (j & NARROW_SCSI) ? 100 : 200;
- break;
- case EE_SYNC_20MB:
- pSyncStr->RequestMegaXferRate = (j & NARROW_SCSI) ? 200 : 400;
- break;
- }
-
- switch ((j >> 5) & 0x07)
- {
- case 0x00:
- if((j & 0x07) == 0x00)
- {
- pSyncStr->ActualMegaXferRate = 0x00; /* Async Mode */
- }
- else
- {
- pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 200 : 400;
- }
- break;
- case 0x01:
- pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 100 : 200;
- break;
- case 0x02:
- pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 66 : 122;
- break;
- case 0x03:
- pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 50 : 100;
- break;
- case 0x04:
- pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 40 : 80;
- break;
- case 0x05:
- pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 33 : 66;
- break;
- case 0x06:
- pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 28 : 56;
- break;
- case 0x07:
- pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 25 : 50;
- break;
- }
- pSyncStr->NegotiatedOffset = j & 0x0f;
-
- return(0);
-}
-
-/*---------------------------------------------------------------------
- *
- * Function: SetDevSyncRate
- *
- *---------------------------------------------------------------------*/
-STATIC int SetDevSyncRate(PSCCBcard pCurrCard, PUCB p_ucb)
-{
- struct _SYNC_RATE_INFO * pSyncStr;
- PSCCBMgr_tar_info currTar_Info;
- BASE_PORT ioPort;
- u08bits scsiID, i, j, syncVal;
- u16bits syncOffset, actualXferRate;
- union {
- u08bits tempb[2];
- u16bits tempw;
- }temp2;
-
-#if (FW_TYPE != _SCCB_MGR_)
- if( p_ucb->UCB_targid >= pCurrCard->cardInfo->ai_MaxTarg )
- {
- return(1);
- }
-#endif
-
- ioPort = pCurrCard->ioPort;
- pSyncStr = (struct _SYNC_RATE_INFO *) p_ucb->UCB_virt_dataptr;
- scsiID = (u08bits) p_ucb->UCB_targid;
- currTar_Info = &sccbMgrTbl[pCurrCard->cardIndex][scsiID];
- i = RD_HARPOON(ioPort+hp_xfer_pad); /* Save current value */
- WR_HARPOON(ioPort+hp_xfer_pad, (i | ID_UNLOCK));
- WR_HARPOON(ioPort+hp_select_id, ((scsiID << 4) | scsiID));
- j = RD_HARPOON(ioPort+hp_synctarg_0);
- WR_HARPOON(ioPort+hp_xfer_pad, i); /* restore value */
-
- actualXferRate = pSyncStr->ActualMegaXferRate;
- if(!(j & NARROW_SCSI))
- {
- actualXferRate <<= 1;
- }
- if(actualXferRate == 0x00)
- {
- syncVal = EE_SYNC_ASYNC; /* Async Mode */
- }
- if(actualXferRate == 0x0200)
- {
- syncVal = EE_SYNC_20MB; /* 20/40 MB Mode */
- }
- if(actualXferRate > 0x0050 && actualXferRate < 0x0200 )
- {
- syncVal = EE_SYNC_10MB; /* 10/20 MB Mode */
- }
- else
- {
- syncVal = EE_SYNC_5MB; /* 5/10 MB Mode */
- }
- if(currTar_Info->TarEEValue && EE_SYNC_MASK == syncVal)
- return(0);
- currTar_Info->TarEEValue = (currTar_Info->TarEEValue & !EE_SYNC_MASK)
- | syncVal;
- syncOffset = (SYNC_RATE_TBL + scsiID) / 2;
- temp2.tempw = utilEERead(ioPort, syncOffset);
- if(scsiID & 0x01)
- {
- temp2.tempb[0] = (temp2.tempb[0] & !EE_SYNC_MASK) | syncVal;
- }
- else
- {
- temp2.tempb[1] = (temp2.tempb[1] & !EE_SYNC_MASK) | syncVal;
- }
- utilEEWriteOnOff(ioPort, 1);
- utilEEWrite(ioPort, temp2.tempw, syncOffset);
- utilEEWriteOnOff(ioPort, 0);
- UpdateCheckSum(ioPort);
-
- return(0);
-}
-/*---------------------------------------------------------------------
- *
- * Function: GetDevWideMode
- *
- *---------------------------------------------------------------------*/
-int GetDevWideMode(PSCCBcard pCurrCard,PUCB p_ucb)
-{
- u08bits *pData;
-
- pData = (u08bits *)p_ucb->UCB_virt_dataptr;
- if(sccbMgrTbl[pCurrCard->cardIndex][p_ucb->UCB_targid].TarEEValue
- & EE_WIDE_SCSI)
- {
- *pData = 1;
- }
- else
- {
- *pData = 0;
- }
-
- return(0);
-}
-
-/*---------------------------------------------------------------------
- *
- * Function: SetDevWideMode
- *
- *---------------------------------------------------------------------*/
-int SetDevWideMode(PSCCBcard pCurrCard,PUCB p_ucb)
-{
- u08bits *pData;
- PSCCBMgr_tar_info currTar_Info;
- BASE_PORT ioPort;
- u08bits scsiID, scsiWideMode;
- u16bits syncOffset;
- union {
- u08bits tempb[2];
- u16bits tempw;
- }temp2;
-
-#if (FW_TYPE != _SCCB_MGR_)
- if( !(pCurrCard->cardInfo->ai_attributes & WIDE_CAPABLE) )
- {
- return(1);
- }
-
- if( p_ucb->UCB_targid >= pCurrCard->cardInfo->ai_MaxTarg )
- {
- return(1);
- }
-#endif
-
- ioPort = pCurrCard->ioPort;
- pData = (u08bits *)p_ucb->UCB_virt_dataptr;
- scsiID = (u08bits) p_ucb->UCB_targid;
- currTar_Info = &sccbMgrTbl[pCurrCard->cardIndex][scsiID];
-
- if(*pData)
- {
- if(currTar_Info->TarEEValue & EE_WIDE_SCSI)
- {
- return(0);
- }
- else
- {
- scsiWideMode = EE_WIDE_SCSI;
- }
- }
- else
- {
- if(!(currTar_Info->TarEEValue & EE_WIDE_SCSI))
- {
- return(0);
- }
- else
- {
- scsiWideMode = 0;
- }
- }
- currTar_Info->TarEEValue = (currTar_Info->TarEEValue & !EE_WIDE_SCSI)
- | scsiWideMode;
-
- syncOffset = (SYNC_RATE_TBL + scsiID) / 2;
- temp2.tempw = utilEERead(ioPort, syncOffset);
- if(scsiID & 0x01)
- {
- temp2.tempb[0] = (temp2.tempb[0] & !EE_WIDE_SCSI) | scsiWideMode;
- }
- else
- {
- temp2.tempb[1] = (temp2.tempb[1] & !EE_WIDE_SCSI) | scsiWideMode;
- }
- utilEEWriteOnOff(ioPort, 1);
- utilEEWrite(ioPort, temp2.tempw, syncOffset);
- utilEEWriteOnOff(ioPort, 0);
- UpdateCheckSum(ioPort);
-
- return(0);
-}
-
-/*---------------------------------------------------------------------
- *
- * Function: ReadNVRam
- *
- *---------------------------------------------------------------------*/
-void ReadNVRam(PSCCBcard pCurrCard,PUCB p_ucb)
-{
- u08bits *pdata;
- u16bits i,numwrds,numbytes,offset,temp;
- u08bits OneMore = FALSE;
-#if defined(DOS)
- u16bits ioport;
-#else
- u32bits ioport;
-#endif
-
- numbytes = (u16bits) p_ucb->UCB_datalen;
- ioport = pCurrCard->ioPort;
- pdata = (u08bits *) p_ucb->UCB_virt_dataptr;
- offset = (u16bits) (p_ucb->UCB_IOCTLParams[0]);
-
-
-
- if (offset & 0x1)
- {
- *((u16bits*) pdata) = utilEERead(ioport,(u16bits)((offset - 1) / 2)); /* 16 bit read */
- *pdata = *(pdata + 1);
- ++offset;
- ++pdata;
- --numbytes;
- }
-
- numwrds = numbytes / 2;
- if (numbytes & 1)
- OneMore = TRUE;
-
- for (i = 0; i < numwrds; i++)
- {
- *((u16bits*) pdata) = utilEERead(ioport,(u16bits)(offset / 2));
- pdata += 2;
- offset += 2;
- }
- if (OneMore)
- {
- --pdata;
- -- offset;
- temp = utilEERead(ioport,(u16bits)(offset / 2));
- *pdata = (u08bits) (temp);
- }
-
-} /* end proc ReadNVRam */
-
-
-/*---------------------------------------------------------------------
- *
- * Function: WriteNVRam
- *
- *---------------------------------------------------------------------*/
-void WriteNVRam(PSCCBcard pCurrCard,PUCB p_ucb)
-{
- u08bits *pdata;
- u16bits i,numwrds,numbytes,offset, eeprom_end;
- u08bits OneMore = FALSE;
- union {
- u08bits tempb[2];
- u16bits tempw;
- } temp2;
-
-#if defined(DOS)
- u16bits ioport;
-#else
- u32bits ioport;
-#endif
-
- numbytes = (u16bits) p_ucb->UCB_datalen;
- ioport = pCurrCard->ioPort;
- pdata = (u08bits *) p_ucb->UCB_virt_dataptr;
- offset = (u16bits) (p_ucb->UCB_IOCTLParams[0]);
-
- if (RD_HARPOON(ioport+hp_page_ctrl) & NARROW_SCSI_CARD)
- eeprom_end = 512;
- else
- eeprom_end = 768;
-
- if(offset > eeprom_end)
- return;
-
- if((offset + numbytes) > eeprom_end)
- numbytes = eeprom_end - offset;
-
- utilEEWriteOnOff(ioport,1); /* Enable write access to the EEPROM */
-
-
-
- if (offset & 0x1)
- {
- temp2.tempw = utilEERead(ioport,(u16bits)((offset - 1) / 2)); /* 16 bit read */
- temp2.tempb[1] = *pdata;
- utilEEWrite(ioport, temp2.tempw, (u16bits)((offset -1) / 2));
- *pdata = *(pdata + 1);
- ++offset;
- ++pdata;
- --numbytes;
- }
-
- numwrds = numbytes / 2;
- if (numbytes & 1)
- OneMore = TRUE;
-
- for (i = 0; i < numwrds; i++)
- {
- utilEEWrite(ioport, *((pu16bits)pdata),(u16bits)(offset / 2));
- pdata += 2;
- offset += 2;
- }
- if (OneMore)
- {
-
- temp2.tempw = utilEERead(ioport,(u16bits)(offset / 2));
- temp2.tempb[0] = *pdata;
- utilEEWrite(ioport, temp2.tempw, (u16bits)(offset / 2));
- }
- utilEEWriteOnOff(ioport,0); /* Turn off write access */
- UpdateCheckSum((u32bits)ioport);
-
-} /* end proc WriteNVRam */
-
-
-
-/*---------------------------------------------------------------------
- *
- * Function: UpdateCheckSum
- *
- * Description: Update Check Sum in EEPROM
- *
- *---------------------------------------------------------------------*/
-
-
-void UpdateCheckSum(u32bits baseport)
-{
- USHORT i,sum_data, eeprom_end;
-
- sum_data = 0x0000;
-
-
- if (RD_HARPOON(baseport+hp_page_ctrl) & NARROW_SCSI_CARD)
- eeprom_end = 512;
- else
- eeprom_end = 768;
-
- for (i = 1; i < eeprom_end/2; i++)
- {
- sum_data += utilEERead(baseport, i);
- }
-
- utilEEWriteOnOff(baseport,1); /* Enable write access to the EEPROM */
-
- utilEEWrite(baseport, sum_data, EEPROM_CHECK_SUM/2);
- utilEEWriteOnOff(baseport,0); /* Turn off write access */
-}
-
-void SccbMgr_save_foreign_state(PADAPTER_INFO pAdapterInfo)
-{
-}
-
-
-void SccbMgr_restore_foreign_state(CARD_HANDLE pCurrCard)
-{
-}
-
-void SccbMgr_restore_native_state(CARD_HANDLE pCurrCard)
-{
-}
-
-#endif /* NO_IOCTLS */
-
-#endif /* (FW_TYPE==_UCB_MGR_) */
-
-#ifndef NO_IOCTLS
-#if (FW_TYPE==_UCB_MGR_)
-void SccbMgr_unload_card(CARD_HANDLE pCurrCard)
-#else
-#if defined(DOS)
-void SccbMgr_unload_card(USHORT pCurrCard)
-#else
-void SccbMgr_unload_card(ULONG pCurrCard)
-#endif
-#endif
+static void SccbMgr_unload_card(ULONG pCurrCard)
{
UCHAR i;
-#if defined(DOS)
- USHORT portBase;
- USHORT regOffset;
-#else
ULONG portBase;
ULONG regOffset;
-#endif
ULONG scamData;
-#if defined(OS2)
- ULONG far *pScamTbl;
-#else
ULONG *pScamTbl;
-#endif
PNVRamInfo pCurrNvRam;
pCurrNvRam = ((PSCCBcard)pCurrCard)->pNvRamInfo;
if(pCurrNvRam){
- WrStack(pCurrNvRam->niBaseAddr, 0, pCurrNvRam->niModel);
- WrStack(pCurrNvRam->niBaseAddr, 1, pCurrNvRam->niSysConf);
- WrStack(pCurrNvRam->niBaseAddr, 2, pCurrNvRam->niScsiConf);
- WrStack(pCurrNvRam->niBaseAddr, 3, pCurrNvRam->niScamConf);
- WrStack(pCurrNvRam->niBaseAddr, 4, pCurrNvRam->niAdapId);
+ FPT_WrStack(pCurrNvRam->niBaseAddr, 0, pCurrNvRam->niModel);
+ FPT_WrStack(pCurrNvRam->niBaseAddr, 1, pCurrNvRam->niSysConf);
+ FPT_WrStack(pCurrNvRam->niBaseAddr, 2, pCurrNvRam->niScsiConf);
+ FPT_WrStack(pCurrNvRam->niBaseAddr, 3, pCurrNvRam->niScamConf);
+ FPT_WrStack(pCurrNvRam->niBaseAddr, 4, pCurrNvRam->niAdapId);
for(i = 0; i < MAX_SCSI_TAR / 2; i++)
- WrStack(pCurrNvRam->niBaseAddr, (UCHAR)(i+5), pCurrNvRam->niSyncTbl[i]);
+ FPT_WrStack(pCurrNvRam->niBaseAddr, (UCHAR)(i+5), pCurrNvRam->niSyncTbl[i]);
portBase = pCurrNvRam->niBaseAddr;
for(i = 0; i < MAX_SCSI_TAR; i++){
regOffset = hp_aramBase + 64 + i*4;
-#if defined(OS2)
- pScamTbl = (ULONG far *) &pCurrNvRam->niScamTbl[i];
-#else
pScamTbl = (ULONG *) &pCurrNvRam->niScamTbl[i];
-#endif
scamData = *pScamTbl;
WR_HARP32(portBase, regOffset, scamData);
}
}else{
- WrStack(((PSCCBcard)pCurrCard)->ioPort, 0, 0);
+ FPT_WrStack(((PSCCBcard)pCurrCard)->ioPort, 0, 0);
}
}
-#endif /* NO_IOCTLS */
-void RNVRamData(PNVRamInfo pNvRamInfo)
+static void FPT_RNVRamData(PNVRamInfo pNvRamInfo)
{
UCHAR i;
-#if defined(DOS)
- USHORT portBase;
- USHORT regOffset;
-#else
ULONG portBase;
ULONG regOffset;
-#endif
ULONG scamData;
-#if defined (OS2)
- ULONG far *pScamTbl;
-#else
ULONG *pScamTbl;
-#endif
- pNvRamInfo->niModel = RdStack(pNvRamInfo->niBaseAddr, 0);
- pNvRamInfo->niSysConf = RdStack(pNvRamInfo->niBaseAddr, 1);
- pNvRamInfo->niScsiConf = RdStack(pNvRamInfo->niBaseAddr, 2);
- pNvRamInfo->niScamConf = RdStack(pNvRamInfo->niBaseAddr, 3);
- pNvRamInfo->niAdapId = RdStack(pNvRamInfo->niBaseAddr, 4);
+ pNvRamInfo->niModel = FPT_RdStack(pNvRamInfo->niBaseAddr, 0);
+ pNvRamInfo->niSysConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 1);
+ pNvRamInfo->niScsiConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 2);
+ pNvRamInfo->niScamConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 3);
+ pNvRamInfo->niAdapId = FPT_RdStack(pNvRamInfo->niBaseAddr, 4);
for(i = 0; i < MAX_SCSI_TAR / 2; i++)
- pNvRamInfo->niSyncTbl[i] = RdStack(pNvRamInfo->niBaseAddr, (UCHAR)(i+5));
+ pNvRamInfo->niSyncTbl[i] = FPT_RdStack(pNvRamInfo->niBaseAddr, (UCHAR)(i+5));
portBase = pNvRamInfo->niBaseAddr;
for(i = 0; i < MAX_SCSI_TAR; i++){
regOffset = hp_aramBase + 64 + i*4;
RD_HARP32(portBase, regOffset, scamData);
-#if defined(OS2)
- pScamTbl = (ULONG far *) &pNvRamInfo->niScamTbl[i];
-#else
pScamTbl = (ULONG *) &pNvRamInfo->niScamTbl[i];
-#endif
*pScamTbl = scamData;
}
}
-#if defined(DOS)
-UCHAR RdStack(USHORT portBase, UCHAR index)
-#else
-UCHAR RdStack(ULONG portBase, UCHAR index)
-#endif
+static UCHAR FPT_RdStack(ULONG portBase, UCHAR index)
{
WR_HARPOON(portBase + hp_stack_addr, index);
return(RD_HARPOON(portBase + hp_stack_data));
}
-#if defined(DOS)
-void WrStack(USHORT portBase, UCHAR index, UCHAR data)
-#else
-void WrStack(ULONG portBase, UCHAR index, UCHAR data)
-#endif
+static void FPT_WrStack(ULONG portBase, UCHAR index, UCHAR data)
{
WR_HARPOON(portBase + hp_stack_addr, index);
WR_HARPOON(portBase + hp_stack_data, data);
}
-#if (FW_TYPE==_UCB_MGR_)
-u08bits ChkIfChipInitialized(BASE_PORT ioPort)
-#else
-#if defined(DOS)
-UCHAR ChkIfChipInitialized(USHORT ioPort)
-#else
-UCHAR ChkIfChipInitialized(ULONG ioPort)
-#endif
-#endif
+static UCHAR FPT_ChkIfChipInitialized(ULONG ioPort)
{
- if((RD_HARPOON(ioPort + hp_arb_id) & 0x0f) != RdStack(ioPort, 4))
- return(FALSE);
+ if((RD_HARPOON(ioPort + hp_arb_id) & 0x0f) != FPT_RdStack(ioPort, 4))
+ return(0);
if((RD_HARPOON(ioPort + hp_clkctrl_0) & CLKCTRL_DEFAULT)
!= CLKCTRL_DEFAULT)
- return(FALSE);
+ return(0);
if((RD_HARPOON(ioPort + hp_seltimeout) == TO_250ms) ||
(RD_HARPOON(ioPort + hp_seltimeout) == TO_290ms))
- return(TRUE);
- return(FALSE);
+ return(1);
+ return(0);
}
/*---------------------------------------------------------------------
@@ -4205,185 +2037,29 @@ UCHAR ChkIfChipInitialized(ULONG ioPort)
* callback function.
*
*---------------------------------------------------------------------*/
-#if (FW_TYPE==_UCB_MGR_)
-void SccbMgr_start_sccb(CARD_HANDLE pCurrCard, PUCB p_ucb)
-#else
-#if defined(DOS)
-void SccbMgr_start_sccb(USHORT pCurrCard, PSCCB p_Sccb)
-#else
-void SccbMgr_start_sccb(ULONG pCurrCard, PSCCB p_Sccb)
-#endif
-#endif
+static void SccbMgr_start_sccb(ULONG pCurrCard, PSCCB p_Sccb)
{
-#if defined(DOS)
- USHORT ioport;
-#else
ULONG ioport;
-#endif
UCHAR thisCard, lun;
PSCCB pSaveSccb;
CALL_BK_FN callback;
-#if (FW_TYPE==_UCB_MGR_)
- PSCCB p_Sccb;
-#endif
-
- mOS_Lock((PSCCBcard)pCurrCard);
thisCard = ((PSCCBcard) pCurrCard)->cardIndex;
ioport = ((PSCCBcard) pCurrCard)->ioPort;
-#if (FW_TYPE==_UCB_MGR_)
- p_Sccb = (PSCCB)p_ucb->UCB_MgrPrivatePtr;
-#endif
-
if((p_Sccb->TargID > MAX_SCSI_TAR) || (p_Sccb->Lun > MAX_LUN))
{
-#if (FW_TYPE==_UCB_MGR_)
- p_ucb->UCB_hbastat = SCCB_COMPLETE;
- p_ucb->UCB_status=SCCB_ERROR;
- callback = (CALL_BK_FN)p_ucb->UCB_callback;
- if (callback)
- callback(p_ucb);
-#endif
-
-#if (FW_TYPE==_SCCB_MGR_)
p_Sccb->HostStatus = SCCB_COMPLETE;
p_Sccb->SccbStatus = SCCB_ERROR;
callback = (CALL_BK_FN)p_Sccb->SccbCallback;
if (callback)
callback(p_Sccb);
-#endif
- mOS_UnLock((PSCCBcard)pCurrCard);
return;
}
-#if (FW_TYPE==_SCCB_MGR_)
- sinits(p_Sccb,thisCard);
-#endif
-
-
-#if (FW_TYPE==_UCB_MGR_)
-#ifndef NO_IOCTLS
-
- if (p_ucb->UCB_opcode & OPC_IOCTL)
- {
-
- switch (p_ucb->UCB_IOCTLCommand)
- {
- case READ_NVRAM:
- ReadNVRam((PSCCBcard)pCurrCard,p_ucb);
- p_ucb->UCB_status=UCB_SUCCESS;
- callback = (CALL_BK_FN)p_ucb->UCB_callback;
- if (callback)
- callback(p_ucb);
- mOS_UnLock((PSCCBcard)pCurrCard);
- return;
-
- case WRITE_NVRAM:
- WriteNVRam((PSCCBcard)pCurrCard,p_ucb);
- p_ucb->UCB_status=UCB_SUCCESS;
- callback = (CALL_BK_FN)p_ucb->UCB_callback;
- if (callback)
- callback(p_ucb);
- mOS_UnLock((PSCCBcard)pCurrCard);
- return;
-
- case SEND_SCSI_PASSTHRU:
-#if (FW_TYPE != _SCCB_MGR_)
- if( p_ucb->UCB_targid >=
- ((PSCCBcard)pCurrCard)->cardInfo->ai_MaxTarg )
- {
- p_ucb->UCB_status = UCB_ERROR;
- p_ucb->UCB_hbastat = HASTAT_HW_ERROR;
- callback = (CALL_BK_FN)p_ucb->UCB_callback;
- if (callback)
- callback(p_ucb);
- mOS_UnLock((PSCCBcard)pCurrCard);
- return;
- }
-#endif
- break;
-
- case HARD_RESET:
- p_ucb->UCB_status = UCB_INVALID;
- callback = (CALL_BK_FN)p_ucb->UCB_callback;
- if (callback)
- callback(p_ucb);
- mOS_UnLock((PSCCBcard)pCurrCard);
- return;
- case GET_DEVICE_SYNCRATE:
- if( !GetDevSyncRate((PSCCBcard)pCurrCard,p_ucb) )
- {
- p_ucb->UCB_status = UCB_SUCCESS;
- }
- else
- {
- p_ucb->UCB_status = UCB_ERROR;
- p_ucb->UCB_hbastat = HASTAT_HW_ERROR;
- }
- callback = (CALL_BK_FN)p_ucb->UCB_callback;
- if (callback)
- callback(p_ucb);
- mOS_UnLock((PSCCBcard)pCurrCard);
- return;
- case SET_DEVICE_SYNCRATE:
- if( !SetDevSyncRate((PSCCBcard)pCurrCard,p_ucb) )
- {
- p_ucb->UCB_status = UCB_SUCCESS;
- }
- else
- {
- p_ucb->UCB_status = UCB_ERROR;
- p_ucb->UCB_hbastat = HASTAT_HW_ERROR;
- }
- callback = (CALL_BK_FN)p_ucb->UCB_callback;
- if (callback)
- callback(p_ucb);
- mOS_UnLock((PSCCBcard)pCurrCard);
- return;
- case GET_WIDE_MODE:
- if( !GetDevWideMode((PSCCBcard)pCurrCard,p_ucb) )
- {
- p_ucb->UCB_status = UCB_SUCCESS;
- }
- else
- {
- p_ucb->UCB_status = UCB_ERROR;
- p_ucb->UCB_hbastat = HASTAT_HW_ERROR;
- }
- callback = (CALL_BK_FN)p_ucb->UCB_callback;
- if (callback)
- callback(p_ucb);
- mOS_UnLock((PSCCBcard)pCurrCard);
- return;
- case SET_WIDE_MODE:
- if( !SetDevWideMode((PSCCBcard)pCurrCard,p_ucb) )
- {
- p_ucb->UCB_status = UCB_SUCCESS;
- }
- else
- {
- p_ucb->UCB_status = UCB_ERROR;
- p_ucb->UCB_hbastat = HASTAT_HW_ERROR;
- }
- callback = (CALL_BK_FN)p_ucb->UCB_callback;
- if (callback)
- callback(p_ucb);
- mOS_UnLock((PSCCBcard)pCurrCard);
- return;
- default:
- p_ucb->UCB_status=UCB_INVALID;
- callback = (CALL_BK_FN)p_ucb->UCB_callback;
- if (callback)
- callback(p_ucb);
- mOS_UnLock((PSCCBcard)pCurrCard);
- return;
- }
- }
-#endif /* NO_IOCTLS */
-#endif /* (FW_TYPE==_UCB_MGR_) */
+ FPT_sinits(p_Sccb,thisCard);
if (!((PSCCBcard) pCurrCard)->cmdCounter)
@@ -4408,12 +2084,12 @@ void SccbMgr_start_sccb(ULONG pCurrCard, PSCCB p_Sccb)
{
pSaveSccb = ((PSCCBcard) pCurrCard)->currentSCCB;
((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb;
- queueSelectFail(&BL_Card[thisCard], thisCard);
+ FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
((PSCCBcard) pCurrCard)->currentSCCB = pSaveSccb;
}
else
{
- queueAddSccb(p_Sccb,thisCard);
+ FPT_queueAddSccb(p_Sccb,thisCard);
}
}
@@ -4423,12 +2099,12 @@ void SccbMgr_start_sccb(ULONG pCurrCard, PSCCB p_Sccb)
{
pSaveSccb = ((PSCCBcard) pCurrCard)->currentSCCB;
((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb;
- queueSelectFail(&BL_Card[thisCard], thisCard);
+ FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
((PSCCBcard) pCurrCard)->currentSCCB = pSaveSccb;
}
else
{
- queueAddSccb(p_Sccb,thisCard);
+ FPT_queueAddSccb(p_Sccb,thisCard);
}
}
@@ -4437,23 +2113,17 @@ void SccbMgr_start_sccb(ULONG pCurrCard, PSCCB p_Sccb)
MDISABLE_INT(ioport);
if((((PSCCBcard) pCurrCard)->globalFlags & F_CONLUN_IO) &&
- ((sccbMgrTbl[thisCard][p_Sccb->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
+ ((FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
lun = p_Sccb->Lun;
else
lun = 0;
if ((((PSCCBcard) pCurrCard)->currentSCCB == NULL) &&
- (sccbMgrTbl[thisCard][p_Sccb->TargID].TarSelQ_Cnt == 0) &&
- (sccbMgrTbl[thisCard][p_Sccb->TargID].TarLUNBusy[lun]
- == FALSE)) {
+ (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarSelQ_Cnt == 0) &&
+ (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarLUNBusy[lun]
+ == 0)) {
((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb;
- mOS_UnLock((PSCCBcard)pCurrCard);
-#if defined(DOS)
- ssel((USHORT)p_Sccb->SccbIOPort,thisCard);
-#else
- ssel(p_Sccb->SccbIOPort,thisCard);
-#endif
- mOS_Lock((PSCCBcard)pCurrCard);
+ FPT_ssel(p_Sccb->SccbIOPort,thisCard);
}
else {
@@ -4462,12 +2132,12 @@ void SccbMgr_start_sccb(ULONG pCurrCard, PSCCB p_Sccb)
{
pSaveSccb = ((PSCCBcard) pCurrCard)->currentSCCB;
((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb;
- queueSelectFail(&BL_Card[thisCard], thisCard);
+ FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
((PSCCBcard) pCurrCard)->currentSCCB = pSaveSccb;
}
else
{
- queueAddSccb(p_Sccb,thisCard);
+ FPT_queueAddSccb(p_Sccb,thisCard);
}
}
@@ -4475,7 +2145,6 @@ void SccbMgr_start_sccb(ULONG pCurrCard, PSCCB p_Sccb)
MENABLE_INT(ioport);
}
- mOS_UnLock((PSCCBcard)pCurrCard);
}
@@ -4488,22 +2157,9 @@ void SccbMgr_start_sccb(ULONG pCurrCard, PSCCB p_Sccb)
* callback function.
*
*---------------------------------------------------------------------*/
-#if (FW_TYPE==_UCB_MGR_)
-s32bits SccbMgr_abort_sccb(CARD_HANDLE pCurrCard, PUCB p_ucb)
-#else
-#if defined(DOS)
-int SccbMgr_abort_sccb(USHORT pCurrCard, PSCCB p_Sccb)
-#else
-int SccbMgr_abort_sccb(ULONG pCurrCard, PSCCB p_Sccb)
-#endif
-#endif
-
+static int SccbMgr_abort_sccb(ULONG pCurrCard, PSCCB p_Sccb)
{
-#if defined(DOS)
- USHORT ioport;
-#else
ULONG ioport;
-#endif
UCHAR thisCard;
CALL_BK_FN callback;
@@ -4512,53 +2168,31 @@ int SccbMgr_abort_sccb(ULONG pCurrCard, PSCCB p_Sccb)
PSCCBMgr_tar_info currTar_Info;
-#if (FW_TYPE==_UCB_MGR_)
- PSCCB p_Sccb;
- p_Sccb=(PSCCB)p_ucb->UCB_MgrPrivatePtr;
-#endif
-
ioport = ((PSCCBcard) pCurrCard)->ioPort;
thisCard = ((PSCCBcard)pCurrCard)->cardIndex;
- mOS_Lock((PSCCBcard)pCurrCard);
-
- if (RD_HARPOON(ioport+hp_page_ctrl) & G_INT_DISABLE)
+ if (!(RD_HARPOON(ioport+hp_page_ctrl) & G_INT_DISABLE))
{
- mOS_UnLock((PSCCBcard)pCurrCard);
- }
- else
- {
-
- if (queueFindSccb(p_Sccb,thisCard))
+ if (FPT_queueFindSccb(p_Sccb,thisCard))
{
- mOS_UnLock((PSCCBcard)pCurrCard);
-
((PSCCBcard)pCurrCard)->cmdCounter--;
if (!((PSCCBcard)pCurrCard)->cmdCounter)
WR_HARPOON(ioport+hp_semaphore,(RD_HARPOON(ioport+hp_semaphore)
& (UCHAR)(~(SCCB_MGR_ACTIVE | TICKLE_ME)) ));
-#if (FW_TYPE==_SCCB_MGR_)
p_Sccb->SccbStatus = SCCB_ABORT;
callback = p_Sccb->SccbCallback;
callback(p_Sccb);
-#else
- p_ucb->UCB_status=SCCB_ABORT;
- callback = (CALL_BK_FN)p_ucb->UCB_callback;
- callback(p_ucb);
-#endif
return(0);
}
else
{
- mOS_UnLock((PSCCBcard)pCurrCard);
-
if (((PSCCBcard)pCurrCard)->currentSCCB == p_Sccb)
{
p_Sccb->SccbStatus = SCCB_ABORT;
@@ -4579,21 +2213,18 @@ int SccbMgr_abort_sccb(ULONG pCurrCard, PSCCB p_Sccb)
{
p_Sccb->SccbStatus = SCCB_ABORT;
p_Sccb->Sccb_scsistat = ABORT_ST;
-#if (FW_TYPE==_UCB_MGR_)
- p_ucb->UCB_status=SCCB_ABORT;
-#endif
p_Sccb->Sccb_scsimsg = SMABORT_TAG;
if(((PSCCBcard) pCurrCard)->currentSCCB == NULL)
{
((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb;
- ssel(ioport, thisCard);
+ FPT_ssel(ioport, thisCard);
}
else
{
pSaveSCCB = ((PSCCBcard) pCurrCard)->currentSCCB;
((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb;
- queueSelectFail((PSCCBcard) pCurrCard, thisCard);
+ FPT_queueSelectFail((PSCCBcard) pCurrCard, thisCard);
((PSCCBcard) pCurrCard)->currentSCCB = pSaveSCCB;
}
}
@@ -4602,9 +2233,9 @@ int SccbMgr_abort_sccb(ULONG pCurrCard, PSCCB p_Sccb)
}
else
{
- currTar_Info = &sccbMgrTbl[thisCard][p_Sccb->TargID];
+ currTar_Info = &FPT_sccbMgrTbl[thisCard][p_Sccb->TargID];
- if(BL_Card[thisCard].discQ_Tbl[currTar_Info->LunDiscQ_Idx[p_Sccb->Lun]]
+ if(FPT_BL_Card[thisCard].discQ_Tbl[currTar_Info->LunDiscQ_Idx[p_Sccb->Lun]]
== p_Sccb)
{
p_Sccb->SccbStatus = SCCB_ABORT;
@@ -4626,37 +2257,20 @@ int SccbMgr_abort_sccb(ULONG pCurrCard, PSCCB p_Sccb)
* interrupt for this card and disable the IRQ Pin if so.
*
*---------------------------------------------------------------------*/
-#if (FW_TYPE==_UCB_MGR_)
-u08bits SccbMgr_my_int(CARD_HANDLE pCurrCard)
-#else
-#if defined(DOS)
-UCHAR SccbMgr_my_int(USHORT pCurrCard)
-#else
-UCHAR SccbMgr_my_int(ULONG pCurrCard)
-#endif
-#endif
+static UCHAR SccbMgr_my_int(ULONG pCurrCard)
{
-#if defined(DOS)
- USHORT ioport;
-#else
ULONG ioport;
-#endif
ioport = ((PSCCBcard)pCurrCard)->ioPort;
if (RD_HARPOON(ioport+hp_int_status) & INT_ASSERTED)
{
-
-#if defined(DOS)
- MDISABLE_INT(ioport);
-#endif
-
- return(TRUE);
+ return(1);
}
else
- return(FALSE);
+ return(0);
}
@@ -4670,37 +2284,19 @@ UCHAR SccbMgr_my_int(ULONG pCurrCard)
* us.
*
*---------------------------------------------------------------------*/
-#if (FW_TYPE==_UCB_MGR_)
-s32bits SccbMgr_isr(CARD_HANDLE pCurrCard)
-#else
-#if defined(DOS)
-int SccbMgr_isr(USHORT pCurrCard)
-#else
-int SccbMgr_isr(ULONG pCurrCard)
-#endif
-#endif
+static int SccbMgr_isr(ULONG pCurrCard)
{
PSCCB currSCCB;
UCHAR thisCard,result,bm_status, bm_int_st;
USHORT hp_int;
UCHAR i, target;
-#if defined(DOS)
- USHORT ioport;
-#else
ULONG ioport;
-#endif
-
- mOS_Lock((PSCCBcard)pCurrCard);
thisCard = ((PSCCBcard)pCurrCard)->cardIndex;
ioport = ((PSCCBcard)pCurrCard)->ioPort;
MDISABLE_INT(ioport);
-#if defined(BUGBUG)
- WR_HARPOON(ioport+hp_user_defined_D, RD_HARPOON(ioport+hp_int_status));
-#endif
-
if ((bm_int_st=RD_HARPOON(ioport+hp_int_status)) & EXT_STATUS_ON)
bm_status = RD_HARPOON(ioport+hp_ext_status) & (UCHAR)BAD_EXT_STATUS;
else
@@ -4708,33 +2304,20 @@ int SccbMgr_isr(ULONG pCurrCard)
WR_HARPOON(ioport+hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
- mOS_UnLock((PSCCBcard)pCurrCard);
-
- while ((hp_int = RDW_HARPOON((ioport+hp_intstat)) & default_intena) |
+ while ((hp_int = RDW_HARPOON((ioport+hp_intstat)) & FPT_default_intena) |
bm_status)
{
currSCCB = ((PSCCBcard)pCurrCard)->currentSCCB;
-#if defined(BUGBUG)
- Debug_Load(thisCard,(UCHAR) 0XFF);
- Debug_Load(thisCard,bm_int_st);
-
- Debug_Load(thisCard,hp_int_0);
- Debug_Load(thisCard,hp_int_1);
-#endif
-
-
if (hp_int & (FIFO | TIMEOUT | RESET | SCAM_SEL) || bm_status) {
- result = SccbMgr_bad_isr(ioport,thisCard,((PSCCBcard)pCurrCard),hp_int);
+ result = FPT_SccbMgr_bad_isr(ioport,thisCard,((PSCCBcard)pCurrCard),hp_int);
WRW_HARPOON((ioport+hp_intstat), (FIFO | TIMEOUT | RESET | SCAM_SEL));
bm_status = 0;
if (result) {
- mOS_Lock((PSCCBcard)pCurrCard);
MENABLE_INT(ioport);
- mOS_UnLock((PSCCBcard)pCurrCard);
return(result);
}
}
@@ -4753,7 +2336,7 @@ int SccbMgr_isr(ULONG pCurrCard)
if (((PSCCBcard)pCurrCard)->globalFlags & F_HOST_XFER_ACT)
- phaseChkFifo(ioport, thisCard);
+ FPT_phaseChkFifo(ioport, thisCard);
/* WRW_HARPOON((ioport+hp_intstat),
(BUS_FREE | ICMD_COMP | ITAR_DISC | XFER_CNT_0));
@@ -4761,7 +2344,7 @@ int SccbMgr_isr(ULONG pCurrCard)
WRW_HARPOON((ioport+hp_intstat), CLR_ALL_INT_1);
- autoCmdCmplt(ioport,thisCard);
+ FPT_autoCmdCmplt(ioport,thisCard);
}
@@ -4771,7 +2354,7 @@ int SccbMgr_isr(ULONG pCurrCard)
if (((PSCCBcard)pCurrCard)->globalFlags & F_HOST_XFER_ACT) {
- phaseChkFifo(ioport, thisCard);
+ FPT_phaseChkFifo(ioport, thisCard);
}
@@ -4784,7 +2367,7 @@ int SccbMgr_isr(ULONG pCurrCard)
}
currSCCB->Sccb_scsistat = DISCONNECT_ST;
- queueDisconnect(currSCCB,thisCard);
+ FPT_queueDisconnect(currSCCB,thisCard);
/* Wait for the BusFree before starting a new command. We
must also check for being reselected since the BusFree
@@ -4803,9 +2386,7 @@ int SccbMgr_isr(ULONG pCurrCard)
*/
if (!(RDW_HARPOON((ioport+hp_intstat)) & (BUS_FREE | RSEL)))
{
- mOS_Lock((PSCCBcard)pCurrCard);
MENABLE_INT(ioport);
- mOS_UnLock((PSCCBcard)pCurrCard);
return 0xFE;
}
@@ -4825,7 +2406,7 @@ int SccbMgr_isr(ULONG pCurrCard)
{
if (((PSCCBcard)pCurrCard)->globalFlags & F_HOST_XFER_ACT)
{
- phaseChkFifo(ioport, thisCard);
+ FPT_phaseChkFifo(ioport, thisCard);
}
if (RD_HARPOON(ioport+hp_gp_reg_1) == SMSAVE_DATA_PTR)
@@ -4837,11 +2418,11 @@ int SccbMgr_isr(ULONG pCurrCard)
WRW_HARPOON((ioport+hp_intstat), (BUS_FREE | ITAR_DISC));
currSCCB->Sccb_scsistat = DISCONNECT_ST;
- queueDisconnect(currSCCB,thisCard);
+ FPT_queueDisconnect(currSCCB,thisCard);
}
- sres(ioport,thisCard,((PSCCBcard)pCurrCard));
- phaseDecode(ioport,thisCard);
+ FPT_sres(ioport,thisCard,((PSCCBcard)pCurrCard));
+ FPT_phaseDecode(ioport,thisCard);
}
@@ -4850,7 +2431,7 @@ int SccbMgr_isr(ULONG pCurrCard)
{
WRW_HARPOON((ioport+hp_intstat), (IDO_STRT | XFER_CNT_0));
- phaseDecode(ioport,thisCard);
+ FPT_phaseDecode(ioport,thisCard);
}
@@ -4860,7 +2441,7 @@ int SccbMgr_isr(ULONG pCurrCard)
WRW_HARPOON((ioport+hp_intstat), (PHASE | IUNKWN | PROG_HLT));
if ((RD_HARPOON(ioport+hp_prgmcnt_0) & (UCHAR)0x3f)< (UCHAR)SELCHK)
{
- phaseDecode(ioport,thisCard);
+ FPT_phaseDecode(ioport,thisCard);
}
else
{
@@ -4885,7 +2466,7 @@ int SccbMgr_isr(ULONG pCurrCard)
WRW_HARPOON((ioport+hp_intstat), XFER_CNT_0);
- schkdd(ioport,thisCard);
+ FPT_schkdd(ioport,thisCard);
}
@@ -4896,10 +2477,10 @@ int SccbMgr_isr(ULONG pCurrCard)
if (((PSCCBcard)pCurrCard)->globalFlags & F_HOST_XFER_ACT) {
- hostDataXferAbort(ioport,thisCard,currSCCB);
+ FPT_hostDataXferAbort(ioport,thisCard,currSCCB);
}
- phaseBusFree(ioport,thisCard);
+ FPT_phaseBusFree(ioport,thisCard);
}
@@ -4919,12 +2500,12 @@ int SccbMgr_isr(ULONG pCurrCard)
if (((PSCCBcard)pCurrCard)->currentSCCB == NULL) {
- queueSearchSelect(((PSCCBcard)pCurrCard),thisCard);
+ FPT_queueSearchSelect(((PSCCBcard)pCurrCard),thisCard);
}
if (((PSCCBcard)pCurrCard)->currentSCCB != NULL) {
((PSCCBcard)pCurrCard)->globalFlags &= ~F_NEW_SCCB_CMD;
- ssel(ioport,thisCard);
+ FPT_ssel(ioport,thisCard);
}
break;
@@ -4933,9 +2514,7 @@ int SccbMgr_isr(ULONG pCurrCard)
} /*end while */
- mOS_Lock((PSCCBcard)pCurrCard);
MENABLE_INT(ioport);
- mOS_UnLock((PSCCBcard)pCurrCard);
return(0);
}
@@ -4950,18 +2529,12 @@ int SccbMgr_isr(ULONG pCurrCard)
* processing time.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-UCHAR SccbMgr_bad_isr(USHORT p_port, UCHAR p_card, PSCCBcard pCurrCard, USHORT p_int)
-#else
-UCHAR SccbMgr_bad_isr(ULONG p_port, UCHAR p_card, PSCCBcard pCurrCard, USHORT p_int)
-#endif
+static UCHAR FPT_SccbMgr_bad_isr(ULONG p_port, UCHAR p_card,
+ PSCCBcard pCurrCard, USHORT p_int)
{
-#if defined(HARP_REVX)
- ULONG timer;
-#endif
-UCHAR temp, ScamFlg;
-PSCCBMgr_tar_info currTar_Info;
-PNVRamInfo pCurrNvRam;
+ UCHAR temp, ScamFlg;
+ PSCCBMgr_tar_info currTar_Info;
+ PNVRamInfo pCurrNvRam;
if (RD_HARPOON(p_port+hp_ext_status) &
@@ -4971,7 +2544,7 @@ PNVRamInfo pCurrNvRam;
if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
{
- hostDataXferAbort(p_port,p_card, pCurrCard->currentSCCB);
+ FPT_hostDataXferAbort(p_port,p_card, pCurrCard->currentSCCB);
}
if (RD_HARPOON(p_port+hp_pci_stat_cfg) & REC_MASTER_ABORT)
@@ -4990,7 +2563,7 @@ PNVRamInfo pCurrNvRam;
if (!pCurrCard->currentSCCB->HostStatus)
pCurrCard->currentSCCB->HostStatus = SCCB_BM_ERR;
- sxfrp(p_port,p_card);
+ FPT_sxfrp(p_port,p_card);
temp = (UCHAR)(RD_HARPOON(p_port+hp_ee_ctrl) &
(EXT_ARB_ACK | SCSI_TERM_ENA_H));
@@ -4999,7 +2572,7 @@ PNVRamInfo pCurrNvRam;
if (!(RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | RESET)))
{
- phaseDecode(p_port,p_card);
+ FPT_phaseDecode(p_port,p_card);
}
}
}
@@ -5014,13 +2587,13 @@ PNVRamInfo pCurrNvRam;
if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
- hostDataXferAbort(p_port,p_card, pCurrCard->currentSCCB);
+ FPT_hostDataXferAbort(p_port,p_card, pCurrCard->currentSCCB);
}
DISABLE_AUTO(p_port);
- sresb(p_port,p_card);
+ FPT_sresb(p_port,p_card);
while(RD_HARPOON(p_port+hp_scsictrl_0) & SCSI_RST) {}
@@ -5029,12 +2602,12 @@ PNVRamInfo pCurrNvRam;
ScamFlg = pCurrNvRam->niScamConf;
}
else{
- ScamFlg = (UCHAR) utilEERead(p_port, SCAM_CONFIG/2);
+ ScamFlg = (UCHAR) FPT_utilEERead(p_port, SCAM_CONFIG/2);
}
- XbowInit(p_port, ScamFlg);
+ FPT_XbowInit(p_port, ScamFlg);
- scini(p_card, pCurrCard->ourId, 0);
+ FPT_scini(p_card, pCurrCard->ourId, 0);
return(0xFF);
}
@@ -5044,34 +2617,8 @@ PNVRamInfo pCurrNvRam;
WRW_HARPOON((p_port+hp_intstat), FIFO);
-#if defined(HARP_REVX)
-
- for (timer=0x00FFFFFFL; timer != 0x00000000L; timer--) {
-
- if (RD_HARPOON(p_port+hp_xferstat) & FIFO_EMPTY)
- break;
-
- if (RDW_HARPOON((p_port+hp_intstat)) & BUS_FREE)
- break;
- }
-
-
- if ( (RD_HARPOON(p_port+hp_xferstat) & FIFO_EMPTY) &&
- (RD_HARPOON(p_port+hp_fiforead) !=
- RD_HARPOON(p_port+hp_fifowrite)) &&
- (RD_HARPOON(p_port+hp_xfercnt_0))
- )
-
- WR_HARPOON((p_port+hp_xferstat), 0x01);
-
-/* else
- */
-/* sxfrp(p_port,p_card);
- */
-#else
if (pCurrCard->currentSCCB != NULL)
- sxfrp(p_port,p_card);
-#endif
+ FPT_sxfrp(p_port,p_card);
}
else if (p_int & TIMEOUT)
@@ -5085,12 +2632,12 @@ PNVRamInfo pCurrNvRam;
pCurrCard->currentSCCB->HostStatus = SCCB_SELECTION_TIMEOUT;
- currTar_Info = &sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
+ currTar_Info = &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
if((pCurrCard->globalFlags & F_CONLUN_IO) &&
((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
- currTar_Info->TarLUNBusy[pCurrCard->currentSCCB->Lun] = FALSE;
+ currTar_Info->TarLUNBusy[pCurrCard->currentSCCB->Lun] = 0;
else
- currTar_Info->TarLUNBusy[0] = FALSE;
+ currTar_Info->TarLUNBusy[0] = 0;
if (currTar_Info->TarEEValue & EE_SYNC_MASK)
@@ -5104,26 +2651,23 @@ PNVRamInfo pCurrNvRam;
currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
}
- sssyncv(p_port, pCurrCard->currentSCCB->TargID, NARROW_SCSI,currTar_Info);
+ FPT_sssyncv(p_port, pCurrCard->currentSCCB->TargID, NARROW_SCSI,currTar_Info);
- queueCmdComplete(pCurrCard, pCurrCard->currentSCCB, p_card);
+ FPT_queueCmdComplete(pCurrCard, pCurrCard->currentSCCB, p_card);
}
-#if defined(SCAM_LEV_2)
-
else if (p_int & SCAM_SEL)
{
- scarb(p_port,LEVEL2_TAR);
- scsel(p_port);
- scasid(p_card, p_port);
+ FPT_scarb(p_port,LEVEL2_TAR);
+ FPT_scsel(p_port);
+ FPT_scasid(p_card, p_port);
- scbusf(p_port);
+ FPT_scbusf(p_port);
WRW_HARPOON((p_port+hp_intstat), SCAM_SEL);
}
-#endif
return(0x00);
}
@@ -5131,126 +2675,25 @@ PNVRamInfo pCurrNvRam;
/*---------------------------------------------------------------------
*
- * Function: SccbMgr_scsi_reset
- *
- * Description: A SCSI bus reset will be generated and all outstanding
- * Sccbs will be returned via the callback.
- *
- *---------------------------------------------------------------------*/
-#if (FW_TYPE==_UCB_MGR_)
-void SccbMgr_scsi_reset(CARD_HANDLE pCurrCard)
-#else
-#if defined(DOS)
-void SccbMgr_scsi_reset(USHORT pCurrCard)
-#else
-void SccbMgr_scsi_reset(ULONG pCurrCard)
-#endif
-#endif
-{
- UCHAR thisCard;
-
- thisCard = ((PSCCBcard)pCurrCard)->cardIndex;
-
- mOS_Lock((PSCCBcard)pCurrCard);
-
- if (((PSCCBcard) pCurrCard)->globalFlags & F_GREEN_PC)
- {
- WR_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_clkctrl_0, CLKCTRL_DEFAULT);
- WR_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_sys_ctrl, 0x00);
- }
-
- sresb(((PSCCBcard)pCurrCard)->ioPort,thisCard);
-
- if (RD_HARPOON(((PSCCBcard)pCurrCard)->ioPort+hp_ext_status) & BM_CMD_BUSY)
- {
- WR_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_page_ctrl,
- (RD_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_page_ctrl)
- & ~SCATTER_EN));
-
- WR_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_sg_addr,0x00);
-
- ((PSCCBcard) pCurrCard)->globalFlags &= ~F_HOST_XFER_ACT;
- busMstrTimeOut(((PSCCBcard) pCurrCard)->ioPort);
-
- WR_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_int_mask,
- (INT_CMD_COMPL | SCSI_INTERRUPT));
- }
-
-/*
- if (utilEERead(((PSCCBcard)pCurrCard)->ioPort, (SCAM_CONFIG/2))
- & SCAM_ENABLED)
-*/
- scini(thisCard, ((PSCCBcard)pCurrCard)->ourId, 0);
-
-#if (FW_TYPE==_UCB_MGR_)
- ((PSCCBcard)pCurrCard)->cardInfo->ai_AEN_routine(0x01,pCurrCard,0,0,0,0);
-#endif
-
- mOS_UnLock((PSCCBcard)pCurrCard);
-}
-
-
-/*---------------------------------------------------------------------
- *
- * Function: SccbMgr_timer_expired
- *
- * Description: This function allow me to kill my own job that has not
- * yet completed, and has cause a timeout to occur. This
- * timeout has caused the upper level driver to call this
- * function.
- *
- *---------------------------------------------------------------------*/
-
-#if (FW_TYPE==_UCB_MGR_)
-void SccbMgr_timer_expired(CARD_HANDLE pCurrCard)
-#else
-#if defined(DOS)
-void SccbMgr_timer_expired(USHORT pCurrCard)
-#else
-void SccbMgr_timer_expired(ULONG pCurrCard)
-#endif
-#endif
-{
-}
-
-#if defined(DOS)
-/*---------------------------------------------------------------------
- *
- * Function: SccbMgr_status
- *
- * Description: This function returns the number of outstanding SCCB's.
- * This is specific to the DOS enviroment, which needs this
- * to help them keep protected and real mode commands staight.
- *
- *---------------------------------------------------------------------*/
-
-USHORT SccbMgr_status(USHORT pCurrCard)
-{
- return(BL_Card[pCurrCard].cmdCounter);
-}
-#endif
-
-/*---------------------------------------------------------------------
- *
* Function: SccbMgrTableInit
*
* Description: Initialize all Sccb manager data structures.
*
*---------------------------------------------------------------------*/
-void SccbMgrTableInitAll()
+static void FPT_SccbMgrTableInitAll()
{
UCHAR thisCard;
for (thisCard = 0; thisCard < MAX_CARDS; thisCard++)
{
- SccbMgrTableInitCard(&BL_Card[thisCard],thisCard);
+ FPT_SccbMgrTableInitCard(&FPT_BL_Card[thisCard],thisCard);
- BL_Card[thisCard].ioPort = 0x00;
- BL_Card[thisCard].cardInfo = NULL;
- BL_Card[thisCard].cardIndex = 0xFF;
- BL_Card[thisCard].ourId = 0x00;
- BL_Card[thisCard].pNvRamInfo = NULL;
+ FPT_BL_Card[thisCard].ioPort = 0x00;
+ FPT_BL_Card[thisCard].cardInfo = NULL;
+ FPT_BL_Card[thisCard].cardIndex = 0xFF;
+ FPT_BL_Card[thisCard].ourId = 0x00;
+ FPT_BL_Card[thisCard].pNvRamInfo = NULL;
}
}
@@ -5263,20 +2706,20 @@ void SccbMgrTableInitAll()
*
*---------------------------------------------------------------------*/
-void SccbMgrTableInitCard(PSCCBcard pCurrCard, UCHAR p_card)
+static void FPT_SccbMgrTableInitCard(PSCCBcard pCurrCard, UCHAR p_card)
{
UCHAR scsiID, qtag;
for (qtag = 0; qtag < QUEUE_DEPTH; qtag++)
{
- BL_Card[p_card].discQ_Tbl[qtag] = NULL;
+ FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
}
for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++)
{
- sccbMgrTbl[p_card][scsiID].TarStatus = 0;
- sccbMgrTbl[p_card][scsiID].TarEEValue = 0;
- SccbMgrTableInitTarget(p_card, scsiID);
+ FPT_sccbMgrTbl[p_card][scsiID].TarStatus = 0;
+ FPT_sccbMgrTbl[p_card][scsiID].TarEEValue = 0;
+ FPT_SccbMgrTableInitTarget(p_card, scsiID);
}
pCurrCard->scanIndex = 0x00;
@@ -5298,13 +2741,13 @@ void SccbMgrTableInitCard(PSCCBcard pCurrCard, UCHAR p_card)
*
*---------------------------------------------------------------------*/
-void SccbMgrTableInitTarget(UCHAR p_card, UCHAR target)
+static void FPT_SccbMgrTableInitTarget(UCHAR p_card, UCHAR target)
{
UCHAR lun, qtag;
PSCCBMgr_tar_info currTar_Info;
- currTar_Info = &sccbMgrTbl[p_card][target];
+ currTar_Info = &FPT_sccbMgrTbl[p_card][target];
currTar_Info->TarSelQ_Cnt = 0;
currTar_Info->TarSyncCtrl = 0;
@@ -5312,160 +2755,28 @@ void SccbMgrTableInitTarget(UCHAR p_card, UCHAR target)
currTar_Info->TarSelQ_Head = NULL;
currTar_Info->TarSelQ_Tail = NULL;
currTar_Info->TarTagQ_Cnt = 0;
- currTar_Info->TarLUN_CA = FALSE;
+ currTar_Info->TarLUN_CA = 0;
for (lun = 0; lun < MAX_LUN; lun++)
{
- currTar_Info->TarLUNBusy[lun] = FALSE;
+ currTar_Info->TarLUNBusy[lun] = 0;
currTar_Info->LunDiscQ_Idx[lun] = 0;
}
for (qtag = 0; qtag < QUEUE_DEPTH; qtag++)
{
- if(BL_Card[p_card].discQ_Tbl[qtag] != NULL)
+ if(FPT_BL_Card[p_card].discQ_Tbl[qtag] != NULL)
{
- if(BL_Card[p_card].discQ_Tbl[qtag]->TargID == target)
+ if(FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == target)
{
- BL_Card[p_card].discQ_Tbl[qtag] = NULL;
- BL_Card[p_card].discQCount--;
+ FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
+ FPT_BL_Card[p_card].discQCount--;
}
}
}
}
-#if defined(BUGBUG)
-
-/*****************************************************************
- * Save the current byte in the debug array
- *****************************************************************/
-
-
-void Debug_Load(UCHAR p_card, UCHAR p_bug_data)
-{
- debug_int[p_card][debug_index[p_card]] = p_bug_data;
- debug_index[p_card]++;
-
- if (debug_index[p_card] == debug_size)
-
- debug_index[p_card] = 0;
-}
-
-#endif
-#ident "$Id: sccb_dat.c 1.10 1997/02/22 03:16:02 awin Exp $"
-/*----------------------------------------------------------------------
- *
- *
- * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved
- *
- * This file is available under both the GNU General Public License
- * and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- * $Workfile: sccb_dat.c $
- *
- * Description: Functions relating to handling of the SCCB interface
- * between the device driver and the HARPOON.
- *
- * $Date: 1997/02/22 03:16:02 $
- *
- * $Revision: 1.10 $
- *
- *----------------------------------------------------------------------*/
-
-/*#include <globals.h>*/
-
-#if (FW_TYPE==_UCB_MGR_)
- /*#include <budi.h>*/
-#endif
-
-/*#include <sccbmgr.h>*/
-/*#include <blx30.h>*/
-/*#include <target.h>*/
-/*#include <harpoon.h>*/
-
-/*
-** IMPORTANT NOTE!!!
-**
-** You MUST preassign all data to a valid value or zero. This is
-** required due to the MS compiler bug under OS/2 and Solaris Real-Mode
-** driver environment.
-*/
-
-
-SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] = { { { 0 } } };
-SCCBCARD BL_Card[MAX_CARDS] = { { 0 } };
-SCCBSCAM_INFO scamInfo[MAX_SCSI_TAR] = { { { 0 } } };
-NVRAMINFO nvRamInfo[MAX_MB_CARDS] = { { 0 } };
-
-
-#if defined(OS2)
-void (far *s_PhaseTbl[8]) (ULONG, UCHAR) = { 0 };
-UCHAR temp_id_string[ID_STRING_LENGTH] = { 0 };
-#elif defined(SOLARIS_REAL_MODE) || defined(__STDC__)
-void (*s_PhaseTbl[8]) (ULONG, UCHAR) = { 0 };
-#else
-void (*s_PhaseTbl[8]) ();
-#endif
-
-#if defined(DOS)
-UCHAR first_time = 0;
-#endif
-
-UCHAR mbCards = 0;
-UCHAR scamHAString[] = {0x63, 0x07, 'B', 'U', 'S', 'L', 'O', 'G', 'I', 'C', \
- ' ', 'B', 'T', '-', '9', '3', '0', \
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, \
- 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
-
-USHORT default_intena = 0;
-
-#if defined(BUGBUG)
-UCHAR debug_int[MAX_CARDS][debug_size] = { 0 };
-UCHAR debug_index[MAX_CARDS] = { 0 };
-UCHAR reserved_1[3] = { 0 };
-#endif
-#ident "$Id: scsi.c 1.23 1997/07/09 21:42:54 mohan Exp $"
-/*----------------------------------------------------------------------
- *
- *
- * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved
- *
- * This file is available under both the GNU General Public License
- * and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- * $Workfile: scsi.c $
- *
- * Description: Functions for handling SCSI bus functions such as
- * selection/reselection, sync negotiation, message-in
- * decoding.
- *
- * $Date: 1997/07/09 21:42:54 $
- *
- * $Revision: 1.23 $
- *
- *----------------------------------------------------------------------*/
-
-/*#include <globals.h>*/
-
-#if (FW_TYPE==_UCB_MGR_)
- /*#include <budi.h>*/
-#endif
-
-/*#include <sccbmgr.h>*/
-/*#include <blx30.h>*/
-/*#include <target.h>*/
-/*#include <scsi2.h>*/
-/*#include <eeprom.h>*/
-/*#include <harpoon.h>*/
-
-
-/*
-extern SCCBCARD BL_Card[MAX_CARDS];
-extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR];
-#if defined(BUGBUG)
-void Debug_Load(UCHAR p_card, UCHAR p_bug_data);
-#endif
-*/
/*---------------------------------------------------------------------
*
@@ -5476,11 +2787,7 @@ void Debug_Load(UCHAR p_card, UCHAR p_bug_data);
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-UCHAR sfm(USHORT port, PSCCB pCurrSCCB)
-#else
-UCHAR sfm(ULONG port, PSCCB pCurrSCCB)
-#endif
+static UCHAR FPT_sfm(ULONG port, PSCCB pCurrSCCB)
{
UCHAR message;
USHORT TimeOutLoop;
@@ -5547,42 +2854,27 @@ UCHAR sfm(ULONG port, PSCCB pCurrSCCB)
/*---------------------------------------------------------------------
*
- * Function: ssel
+ * Function: FPT_ssel
*
* Description: Load up automation and select target device.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void ssel(USHORT port, UCHAR p_card)
-#else
-void ssel(ULONG port, UCHAR p_card)
-#endif
+static void FPT_ssel(ULONG port, UCHAR p_card)
{
-#if defined(DOS)
UCHAR auto_loaded, i, target, *theCCB;
-#elif defined(OS2)
- UCHAR auto_loaded, i, target;
- UCHAR far *theCCB;
-#else
- UCHAR auto_loaded, i, target, *theCCB;
-#endif
-#if defined(DOS)
- USHORT cdb_reg;
-#else
ULONG cdb_reg;
-#endif
PSCCBcard CurrCard;
PSCCB currSCCB;
PSCCBMgr_tar_info currTar_Info;
UCHAR lastTag, lun;
- CurrCard = &BL_Card[p_card];
+ CurrCard = &FPT_BL_Card[p_card];
currSCCB = CurrCard->currentSCCB;
target = currSCCB->TargID;
- currTar_Info = &sccbMgrTbl[p_card][target];
+ currTar_Info = &FPT_sccbMgrTbl[p_card][target];
lastTag = CurrCard->tagQ_Lst;
ARAM_ACCESS(port);
@@ -5599,60 +2891,53 @@ void ssel(ULONG port, UCHAR p_card)
lun = 0;
-#if defined(DOS)
- currTar_Info->TarLUNBusy[lun] = TRUE;
-
-#else
-
if (CurrCard->globalFlags & F_TAG_STARTED)
{
if (!(currSCCB->ControlByte & F_USE_CMD_Q))
{
- if ((currTar_Info->TarLUN_CA == FALSE)
+ if ((currTar_Info->TarLUN_CA == 0)
&& ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
== TAG_Q_TRYING))
{
if (currTar_Info->TarTagQ_Cnt !=0)
{
- currTar_Info->TarLUNBusy[lun] = TRUE;
- queueSelectFail(CurrCard,p_card);
+ currTar_Info->TarLUNBusy[lun] = 1;
+ FPT_queueSelectFail(CurrCard,p_card);
SGRAM_ACCESS(port);
return;
}
else {
- currTar_Info->TarLUNBusy[lun] = TRUE;
+ currTar_Info->TarLUNBusy[lun] = 1;
}
} /*End non-tagged */
else {
- currTar_Info->TarLUNBusy[lun] = TRUE;
+ currTar_Info->TarLUNBusy[lun] = 1;
}
} /*!Use cmd Q Tagged */
else {
- if (currTar_Info->TarLUN_CA == TRUE)
+ if (currTar_Info->TarLUN_CA == 1)
{
- queueSelectFail(CurrCard,p_card);
+ FPT_queueSelectFail(CurrCard,p_card);
SGRAM_ACCESS(port);
return;
}
- currTar_Info->TarLUNBusy[lun] = TRUE;
+ currTar_Info->TarLUNBusy[lun] = 1;
} /*else use cmd Q tagged */
} /*if glob tagged started */
else {
- currTar_Info->TarLUNBusy[lun] = TRUE;
+ currTar_Info->TarLUNBusy[lun] = 1;
}
-#endif /* DOS */
-
if((((CurrCard->globalFlags & F_CONLUN_IO) &&
@@ -5661,8 +2946,8 @@ void ssel(ULONG port, UCHAR p_card)
{
if(CurrCard->discQCount >= QUEUE_DEPTH)
{
- currTar_Info->TarLUNBusy[lun] = TRUE;
- queueSelectFail(CurrCard,p_card);
+ currTar_Info->TarLUNBusy[lun] = 1;
+ FPT_queueSelectFail(CurrCard,p_card);
SGRAM_ACCESS(port);
return;
}
@@ -5680,8 +2965,8 @@ void ssel(ULONG port, UCHAR p_card)
}
if(i == QUEUE_DEPTH)
{
- currTar_Info->TarLUNBusy[lun] = TRUE;
- queueSelectFail(CurrCard,p_card);
+ currTar_Info->TarLUNBusy[lun] = 1;
+ FPT_queueSelectFail(CurrCard,p_card);
SGRAM_ACCESS(port);
return;
}
@@ -5689,7 +2974,7 @@ void ssel(ULONG port, UCHAR p_card)
- auto_loaded = FALSE;
+ auto_loaded = 0;
WR_HARPOON(port+hp_select_id, target);
WR_HARPOON(port+hp_gp_reg_3, target); /* Use by new automation logic */
@@ -5703,7 +2988,7 @@ void ssel(ULONG port, UCHAR p_card)
currSCCB->Sccb_scsimsg = SMDEV_RESET;
WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT));
- auto_loaded = TRUE;
+ auto_loaded = 1;
currSCCB->Sccb_scsistat = SELECT_BDR_ST;
if (currTar_Info->TarEEValue & EE_SYNC_MASK)
@@ -5712,16 +2997,13 @@ void ssel(ULONG port, UCHAR p_card)
currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
}
-#if defined(WIDE_SCSI)
-
if (currTar_Info->TarEEValue & EE_WIDE_SCSI)
{
currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
}
-#endif
- sssyncv(port, target, NARROW_SCSI,currTar_Info);
- SccbMgrTableInitTarget(p_card, target);
+ FPT_sssyncv(port, target, NARROW_SCSI,currTar_Info);
+ FPT_SccbMgrTableInitTarget(p_card, target);
}
@@ -5740,24 +3022,18 @@ void ssel(ULONG port, UCHAR p_card)
WRW_HARPOON((port+SYNC_MSGS+4), (BRH_OP+ALWAYS+NP ));
WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT));
- auto_loaded = TRUE;
+ auto_loaded = 1;
}
-#if defined(WIDE_SCSI)
-
-
else if (!(currTar_Info->TarStatus & WIDE_NEGOCIATED)) {
- auto_loaded = siwidn(port,p_card);
+ auto_loaded = FPT_siwidn(port,p_card);
currSCCB->Sccb_scsistat = SELECT_WN_ST;
}
-#endif
-
-
else if (!((currTar_Info->TarStatus & TAR_SYNC_MASK)
== SYNC_SUPPORTED)) {
- auto_loaded = sisyncn(port,p_card, FALSE);
+ auto_loaded = FPT_sisyncn(port,p_card, 0);
currSCCB->Sccb_scsistat = SELECT_SN_ST;
}
@@ -5765,7 +3041,6 @@ void ssel(ULONG port, UCHAR p_card)
if (!auto_loaded)
{
-#if !defined(DOS)
if (currSCCB->ControlByte & F_USE_CMD_Q)
{
@@ -5789,7 +3064,7 @@ void ssel(ULONG port, UCHAR p_card)
the wheels fall off. */
currSCCB->Sccb_scsistat = SELECT_ST;
- currTar_Info->TarLUNBusy[lun] = TRUE;
+ currTar_Info->TarLUNBusy[lun] = 1;
}
else
@@ -5818,8 +3093,8 @@ void ssel(ULONG port, UCHAR p_card)
if ( i == QUEUE_DEPTH )
{
- currTar_Info->TarLUNBusy[lun] = TRUE;
- queueSelectFail(CurrCard,p_card);
+ currTar_Info->TarLUNBusy[lun] = 1;
+ FPT_queueSelectFail(CurrCard,p_card);
SGRAM_ACCESS(port);
return;
}
@@ -5832,7 +3107,6 @@ void ssel(ULONG port, UCHAR p_card)
else
{
-#endif /* !DOS */
WRW_HARPOON((port+ID_MSG_STRT),BRH_OP+ALWAYS+NTCMD);
@@ -5842,16 +3116,10 @@ void ssel(ULONG port, UCHAR p_card)
currSCCB->Sccb_scsistat = SELECT_ST;
WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT));
-#if !defined(DOS)
}
-#endif
-#if defined(OS2)
- theCCB = (UCHAR far *)&currSCCB->Cdb[0];
-#else
theCCB = (UCHAR *)&currSCCB->Cdb[0];
-#endif
cdb_reg = port + CMD_STRT;
@@ -5867,10 +3135,8 @@ void ssel(ULONG port, UCHAR p_card)
} /* auto_loaded */
-#if defined(WIDE_SCSI)
WRW_HARPOON((port+hp_fiforead), (USHORT) 0x00);
WR_HARPOON(port+hp_xferstat, 0x00);
-#endif
WRW_HARPOON((port+hp_intstat), (PROG_HLT | TIMEOUT | SEL | BUS_FREE));
@@ -5899,30 +3165,16 @@ void ssel(ULONG port, UCHAR p_card)
/*---------------------------------------------------------------------
*
- * Function: sres
+ * Function: FPT_sres
*
* Description: Hookup the correct CCB and handle the incoming messages.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void sres(USHORT port, UCHAR p_card, PSCCBcard pCurrCard)
-#else
-void sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard)
-#endif
+static void FPT_sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard)
{
-#if defined(V302)
-#ifdef DOS
- UCHAR our_target,message, msgRetryCount;
- extern UCHAR lun, tag;
-#else
- UCHAR our_target,message,lun,tag, msgRetryCount;
-#endif
-
-#else /* V302 */
UCHAR our_target, message, lun = 0, tag, msgRetryCount;
-#endif /* V302 */
PSCCBMgr_tar_info currTar_Info;
@@ -5933,7 +3185,7 @@ void sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard)
if(pCurrCard->currentSCCB != NULL)
{
- currTar_Info = &sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
+ currTar_Info = &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
DISABLE_AUTO(port);
@@ -5954,7 +3206,7 @@ void sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard)
if(((pCurrCard->globalFlags & F_CONLUN_IO) &&
((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
{
- currTar_Info->TarLUNBusy[currSCCB->Lun] = FALSE;
+ currTar_Info->TarLUNBusy[currSCCB->Lun] = 0;
if(currSCCB->Sccb_scsistat != ABORT_ST)
{
pCurrCard->discQCount--;
@@ -5964,7 +3216,7 @@ void sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard)
}
else
{
- currTar_Info->TarLUNBusy[0] = FALSE;
+ currTar_Info->TarLUNBusy[0] = 0;
if(currSCCB->Sccb_tag)
{
if(currSCCB->Sccb_scsistat != ABORT_ST)
@@ -5982,29 +3234,21 @@ void sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard)
}
}
- queueSelectFail(&BL_Card[p_card],p_card);
+ FPT_queueSelectFail(&FPT_BL_Card[p_card],p_card);
}
-#if defined(WIDE_SCSI)
WRW_HARPOON((port+hp_fiforead), (USHORT) 0x00);
-#endif
our_target = (UCHAR)(RD_HARPOON(port+hp_select_id) >> 4);
- currTar_Info = &sccbMgrTbl[p_card][our_target];
+ currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
msgRetryCount = 0;
do
{
-#if defined(V302)
-
- message = GetTarLun(port, p_card, our_target, pCurrCard, &tag, &lun);
-
-#else /* V302 */
-
- currTar_Info = &sccbMgrTbl[p_card][our_target];
+ currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
tag = 0;
@@ -6022,7 +3266,7 @@ void sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard)
if ((RD_HARPOON(port+hp_scsisig) & S_SCSI_PHZ) == S_MSGI_PH)
{
- message = sfm(port,pCurrCard->currentSCCB);
+ message = FPT_sfm(port,pCurrCard->currentSCCB);
if (message)
{
@@ -6030,7 +3274,6 @@ void sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard)
{
lun = message & (UCHAR)LUN_MASK;
-#if !defined(DOS)
if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_TRYING)
{
if (currTar_Info->TarTagQ_Cnt != 0)
@@ -6041,21 +3284,21 @@ void sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard)
ACCEPT_MSG(port); /*Release the ACK for ID msg. */
- message = sfm(port,pCurrCard->currentSCCB);
+ message = FPT_sfm(port,pCurrCard->currentSCCB);
if (message)
{
ACCEPT_MSG(port);
}
else
- message = FALSE;
+ message = 0;
- if(message != FALSE)
+ if(message != 0)
{
- tag = sfm(port,pCurrCard->currentSCCB);
+ tag = FPT_sfm(port,pCurrCard->currentSCCB);
if (!(tag))
- message = FALSE;
+ message = 0;
}
} /*C.A. exists! */
@@ -6063,7 +3306,6 @@ void sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard)
} /*End Q cnt != 0 */
} /*End Tag cmds supported! */
-#endif /* !DOS */
} /*End valid ID message. */
@@ -6078,7 +3320,7 @@ void sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard)
else
{
- message = FALSE;
+ message = 0;
}
}
else
@@ -6091,49 +3333,47 @@ void sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard)
return;
}
-
-#endif /* V302 */
- if(message == FALSE)
+ if(message == 0)
{
msgRetryCount++;
if(msgRetryCount == 1)
{
- SendMsg(port, SMPARITY);
+ FPT_SendMsg(port, SMPARITY);
}
else
{
- SendMsg(port, SMDEV_RESET);
+ FPT_SendMsg(port, SMDEV_RESET);
- sssyncv(port, our_target, NARROW_SCSI,currTar_Info);
+ FPT_sssyncv(port, our_target, NARROW_SCSI,currTar_Info);
- if (sccbMgrTbl[p_card][our_target].TarEEValue & EE_SYNC_MASK)
+ if (FPT_sccbMgrTbl[p_card][our_target].TarEEValue & EE_SYNC_MASK)
{
- sccbMgrTbl[p_card][our_target].TarStatus &= ~TAR_SYNC_MASK;
+ FPT_sccbMgrTbl[p_card][our_target].TarStatus &= ~TAR_SYNC_MASK;
}
- if (sccbMgrTbl[p_card][our_target].TarEEValue & EE_WIDE_SCSI)
+ if (FPT_sccbMgrTbl[p_card][our_target].TarEEValue & EE_WIDE_SCSI)
{
- sccbMgrTbl[p_card][our_target].TarStatus &= ~TAR_WIDE_MASK;
+ FPT_sccbMgrTbl[p_card][our_target].TarStatus &= ~TAR_WIDE_MASK;
}
- queueFlushTargSccb(p_card, our_target, SCCB_COMPLETE);
- SccbMgrTableInitTarget(p_card,our_target);
+ FPT_queueFlushTargSccb(p_card, our_target, SCCB_COMPLETE);
+ FPT_SccbMgrTableInitTarget(p_card,our_target);
return;
}
}
- }while(message == FALSE);
+ }while(message == 0);
if(((pCurrCard->globalFlags & F_CONLUN_IO) &&
((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
{
- currTar_Info->TarLUNBusy[lun] = TRUE;
+ currTar_Info->TarLUNBusy[lun] = 1;
pCurrCard->currentSCCB = pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[lun]];
if(pCurrCard->currentSCCB != NULL)
{
@@ -6146,7 +3386,7 @@ void sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard)
}
else
{
- currTar_Info->TarLUNBusy[0] = TRUE;
+ currTar_Info->TarLUNBusy[0] = 1;
if (tag)
@@ -6182,7 +3422,7 @@ void sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard)
/* During Abort Tag command, the target could have got re-selected
and completed the command. Check the select Q and remove the CCB
if it is in the Select Q */
- queueFindSccb(pCurrCard->currentSCCB, p_card);
+ FPT_queueFindSccb(pCurrCard->currentSCCB, p_card);
}
}
@@ -6192,106 +3432,7 @@ void sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard)
(RD_HARPOON(port+hp_scsisig) & SCSI_BSY)) ;
}
-#if defined(V302)
-
-#if defined(DOS)
-UCHAR GetTarLun(USHORT port, UCHAR p_card, UCHAR our_target, PSCCBcard pCurrCard, PUCHAR tag, PUCHAR lun)
-#else
-UCHAR GetTarLun(ULONG port, UCHAR p_card, UCHAR our_target, PSCCBcard pCurrCard, PUCHAR tag, PUCHAR lun)
-#endif
-{
- UCHAR message;
- PSCCBMgr_tar_info currTar_Info;
-
-
- currTar_Info = &sccbMgrTbl[p_card][our_target];
- *tag = 0;
-
-
- while(!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ))
- {
- if (! (RD_HARPOON(port+hp_scsisig) & SCSI_BSY))
- {
-
- WRW_HARPOON((port+hp_intstat), PHASE);
- return(TRUE);
- }
- }
-
- WRW_HARPOON((port+hp_intstat), PHASE);
- if ((RD_HARPOON(port+hp_scsisig) & S_SCSI_PHZ) == S_MSGI_PH)
- {
-
- message = sfm(port,pCurrCard->currentSCCB);
- if (message)
- {
-
- if (message <= (0x80 | LUN_MASK))
- {
- *lun = message & (UCHAR)LUN_MASK;
-
-#if !defined(DOS)
- if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_TRYING)
- {
- if (currTar_Info->TarTagQ_Cnt != 0)
- {
-
- if (!(currTar_Info->TarLUN_CA))
- {
- ACCEPT_MSG(port); /*Release the ACK for ID msg. */
-
-
- message = sfm(port,pCurrCard->currentSCCB);
- if (message)
- {
- ACCEPT_MSG(port);
- }
-
- else
- return(FALSE);
-
- *tag = sfm(port,pCurrCard->currentSCCB);
-
- if (!(*tag)) return(FALSE);
-
- } /*C.A. exists! */
-
- } /*End Q cnt != 0 */
-
- } /*End Tag cmds supported! */
-#endif /* !DOS */
-
- } /*End valid ID message. */
-
- else
- {
-
- ACCEPT_MSG_ATN(port);
- }
-
- } /* End good id message. */
-
- else
- {
-
- return(FALSE);
- }
- }
- else
- {
- ACCEPT_MSG_ATN(port);
- return(TRUE);
- }
- return(TRUE);
-}
-
-#endif /* V302 */
-
-#if defined(DOS)
-void SendMsg(USHORT port, UCHAR message)
-#else
-void SendMsg(ULONG port, UCHAR message)
-#endif
+static void FPT_SendMsg(ULONG port, UCHAR message)
{
while(!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ))
{
@@ -6334,26 +3475,22 @@ void SendMsg(ULONG port, UCHAR message)
/*---------------------------------------------------------------------
*
- * Function: sdecm
+ * Function: FPT_sdecm
*
* Description: Determine the proper responce to the message from the
* target device.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void sdecm(UCHAR message, USHORT port, UCHAR p_card)
-#else
-void sdecm(UCHAR message, ULONG port, UCHAR p_card)
-#endif
+static void FPT_sdecm(UCHAR message, ULONG port, UCHAR p_card)
{
PSCCB currSCCB;
PSCCBcard CurrCard;
PSCCBMgr_tar_info currTar_Info;
- CurrCard = &BL_Card[p_card];
+ CurrCard = &FPT_BL_Card[p_card];
currSCCB = CurrCard->currentSCCB;
- currTar_Info = &sccbMgrTbl[p_card][currSCCB->TargID];
+ currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
if (message == SMREST_DATA_PTR)
{
@@ -6361,7 +3498,7 @@ void sdecm(UCHAR message, ULONG port, UCHAR p_card)
{
currSCCB->Sccb_ATC = currSCCB->Sccb_savedATC;
- hostDataXferRestart(currSCCB);
+ FPT_hostDataXferRestart(currSCCB);
}
ACCEPT_MSG(port);
@@ -6417,7 +3554,6 @@ void sdecm(UCHAR message, ULONG port, UCHAR p_card)
currTar_Info->TarEEValue &= ~EE_SYNC_MASK;
}
-#if defined(WIDE_SCSI)
else if ((currSCCB->Sccb_scsistat == SELECT_WN_ST))
{
@@ -6428,7 +3564,6 @@ void sdecm(UCHAR message, ULONG port, UCHAR p_card)
currTar_Info->TarEEValue &= ~EE_WIDE_SCSI;
}
-#endif
else if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_TRYING )
{
@@ -6460,9 +3595,9 @@ void sdecm(UCHAR message, ULONG port, UCHAR p_card)
if((CurrCard->globalFlags & F_CONLUN_IO) &&
((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
- currTar_Info->TarLUNBusy[currSCCB->Lun] = TRUE;
+ currTar_Info->TarLUNBusy[currSCCB->Lun] = 1;
else
- currTar_Info->TarLUNBusy[0] = TRUE;
+ currTar_Info->TarLUNBusy[0] = 1;
currSCCB->ControlByte &= ~(UCHAR)F_USE_CMD_Q;
@@ -6490,7 +3625,7 @@ void sdecm(UCHAR message, ULONG port, UCHAR p_card)
{
ACCEPT_MSG(port);
- shandem(port,p_card,currSCCB);
+ FPT_shandem(port,p_card,currSCCB);
}
else if (message == SMIGNORWR)
@@ -6498,7 +3633,7 @@ void sdecm(UCHAR message, ULONG port, UCHAR p_card)
ACCEPT_MSG(port); /* ACK the RESIDUE MSG */
- message = sfm(port,currSCCB);
+ message = FPT_sfm(port,currSCCB);
if(currSCCB->Sccb_scsimsg != SMPARITY)
ACCEPT_MSG(port);
@@ -6520,25 +3655,21 @@ void sdecm(UCHAR message, ULONG port, UCHAR p_card)
/*---------------------------------------------------------------------
*
- * Function: shandem
+ * Function: FPT_shandem
*
* Description: Decide what to do with the extended message.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void shandem(USHORT port, UCHAR p_card, PSCCB pCurrSCCB)
-#else
-void shandem(ULONG port, UCHAR p_card, PSCCB pCurrSCCB)
-#endif
+static void FPT_shandem(ULONG port, UCHAR p_card, PSCCB pCurrSCCB)
{
UCHAR length,message;
- length = sfm(port,pCurrSCCB);
+ length = FPT_sfm(port,pCurrSCCB);
if (length)
{
ACCEPT_MSG(port);
- message = sfm(port,pCurrSCCB);
+ message = FPT_sfm(port,pCurrSCCB);
if (message)
{
@@ -6549,7 +3680,7 @@ void shandem(ULONG port, UCHAR p_card, PSCCB pCurrSCCB)
{
ACCEPT_MSG(port);
- stsyncn(port,p_card);
+ FPT_stsyncn(port,p_card);
}
else
{
@@ -6558,7 +3689,6 @@ void shandem(ULONG port, UCHAR p_card, PSCCB pCurrSCCB)
ACCEPT_MSG_ATN(port);
}
}
-#if defined(WIDE_SCSI)
else if (message == SMWDTR)
{
@@ -6566,7 +3696,7 @@ void shandem(ULONG port, UCHAR p_card, PSCCB pCurrSCCB)
{
ACCEPT_MSG(port);
- stwidn(port,p_card);
+ FPT_stwidn(port,p_card);
}
else
{
@@ -6577,7 +3707,6 @@ void shandem(ULONG port, UCHAR p_card, PSCCB pCurrSCCB)
WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START));
}
}
-#endif
else
{
@@ -6603,24 +3732,20 @@ void shandem(ULONG port, UCHAR p_card, PSCCB pCurrSCCB)
/*---------------------------------------------------------------------
*
- * Function: sisyncn
+ * Function: FPT_sisyncn
*
* Description: Read in a message byte from the SCSI bus, and check
* for a parity error.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-UCHAR sisyncn(USHORT port, UCHAR p_card, UCHAR syncFlag)
-#else
-UCHAR sisyncn(ULONG port, UCHAR p_card, UCHAR syncFlag)
-#endif
+static UCHAR FPT_sisyncn(ULONG port, UCHAR p_card, UCHAR syncFlag)
{
PSCCB currSCCB;
PSCCBMgr_tar_info currTar_Info;
- currSCCB = BL_Card[p_card].currentSCCB;
- currTar_Info = &sccbMgrTbl[p_card][currSCCB->TargID];
+ currSCCB = FPT_BL_Card[p_card].currentSCCB;
+ currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)) {
@@ -6656,7 +3781,7 @@ UCHAR sisyncn(ULONG port, UCHAR p_card, UCHAR syncFlag)
WRW_HARPOON((port+SYNC_MSGS+12),(BRH_OP+ALWAYS+NP ));
- if(syncFlag == FALSE)
+ if(syncFlag == 0)
{
WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT));
currTar_Info->TarStatus = ((currTar_Info->TarStatus &
@@ -6668,14 +3793,14 @@ UCHAR sisyncn(ULONG port, UCHAR p_card, UCHAR syncFlag)
}
- return(TRUE);
+ return(1);
}
else {
currTar_Info->TarStatus |= (UCHAR)SYNC_SUPPORTED;
currTar_Info->TarEEValue &= ~EE_SYNC_MASK;
- return(FALSE);
+ return(0);
}
}
@@ -6683,26 +3808,22 @@ UCHAR sisyncn(ULONG port, UCHAR p_card, UCHAR syncFlag)
/*---------------------------------------------------------------------
*
- * Function: stsyncn
+ * Function: FPT_stsyncn
*
* Description: The has sent us a Sync Nego message so handle it as
* necessary.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void stsyncn(USHORT port, UCHAR p_card)
-#else
-void stsyncn(ULONG port, UCHAR p_card)
-#endif
+static void FPT_stsyncn(ULONG port, UCHAR p_card)
{
UCHAR sync_msg,offset,sync_reg,our_sync_msg;
PSCCB currSCCB;
PSCCBMgr_tar_info currTar_Info;
- currSCCB = BL_Card[p_card].currentSCCB;
- currTar_Info = &sccbMgrTbl[p_card][currSCCB->TargID];
+ currSCCB = FPT_BL_Card[p_card].currentSCCB;
+ currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
- sync_msg = sfm(port,currSCCB);
+ sync_msg = FPT_sfm(port,currSCCB);
if((sync_msg == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY))
{
@@ -6713,7 +3834,7 @@ void stsyncn(ULONG port, UCHAR p_card)
ACCEPT_MSG(port);
- offset = sfm(port,currSCCB);
+ offset = FPT_sfm(port,currSCCB);
if((offset == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY))
{
@@ -6783,7 +3904,6 @@ void stsyncn(ULONG port, UCHAR p_card)
}
-#if defined(WIDE_SCSI)
if (currTar_Info->TarStatus & WIDE_ENABLED)
sync_reg |= offset;
@@ -6792,11 +3912,7 @@ void stsyncn(ULONG port, UCHAR p_card)
sync_reg |= (offset | NARROW_SCSI);
-#else
- sync_reg |= (offset | NARROW_SCSI);
-#endif
-
- sssyncv(port,currSCCB->TargID,sync_reg,currTar_Info);
+ FPT_sssyncv(port,currSCCB->TargID,sync_reg,currTar_Info);
if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
@@ -6815,7 +3931,7 @@ void stsyncn(ULONG port, UCHAR p_card)
ACCEPT_MSG_ATN(port);
- sisyncr(port,sync_msg,offset);
+ FPT_sisyncr(port,sync_msg,offset);
currTar_Info->TarStatus = ((currTar_Info->TarStatus &
~(UCHAR)TAR_SYNC_MASK) | (UCHAR)SYNC_SUPPORTED);
@@ -6825,16 +3941,12 @@ void stsyncn(ULONG port, UCHAR p_card)
/*---------------------------------------------------------------------
*
- * Function: sisyncr
+ * Function: FPT_sisyncr
*
* Description: Answer the targets sync message.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void sisyncr(USHORT port,UCHAR sync_pulse, UCHAR offset)
-#else
-void sisyncr(ULONG port,UCHAR sync_pulse, UCHAR offset)
-#endif
+static void FPT_sisyncr(ULONG port,UCHAR sync_pulse, UCHAR offset)
{
ARAM_ACCESS(port);
WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+SMEXT ));
@@ -6856,28 +3968,22 @@ void sisyncr(ULONG port,UCHAR sync_pulse, UCHAR offset)
-#if defined(WIDE_SCSI)
-
/*---------------------------------------------------------------------
*
- * Function: siwidn
+ * Function: FPT_siwidn
*
* Description: Read in a message byte from the SCSI bus, and check
* for a parity error.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-UCHAR siwidn(USHORT port, UCHAR p_card)
-#else
-UCHAR siwidn(ULONG port, UCHAR p_card)
-#endif
+static UCHAR FPT_siwidn(ULONG port, UCHAR p_card)
{
PSCCB currSCCB;
PSCCBMgr_tar_info currTar_Info;
- currSCCB = BL_Card[p_card].currentSCCB;
- currTar_Info = &sccbMgrTbl[p_card][currSCCB->TargID];
+ currSCCB = FPT_BL_Card[p_card].currentSCCB;
+ currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
if (!((currTar_Info->TarStatus & TAR_WIDE_MASK) == WIDE_NEGOCIATED)) {
@@ -6900,7 +4006,7 @@ UCHAR siwidn(ULONG port, UCHAR p_card)
currTar_Info->TarStatus = ((currTar_Info->TarStatus &
~(UCHAR)TAR_WIDE_MASK) | (UCHAR)WIDE_ENABLED);
- return(TRUE);
+ return(1);
}
else {
@@ -6909,7 +4015,7 @@ UCHAR siwidn(ULONG port, UCHAR p_card)
~(UCHAR)TAR_WIDE_MASK) | WIDE_NEGOCIATED);
currTar_Info->TarEEValue &= ~EE_WIDE_SCSI;
- return(FALSE);
+ return(0);
}
}
@@ -6917,26 +4023,22 @@ UCHAR siwidn(ULONG port, UCHAR p_card)
/*---------------------------------------------------------------------
*
- * Function: stwidn
+ * Function: FPT_stwidn
*
* Description: The has sent us a Wide Nego message so handle it as
* necessary.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void stwidn(USHORT port, UCHAR p_card)
-#else
-void stwidn(ULONG port, UCHAR p_card)
-#endif
+static void FPT_stwidn(ULONG port, UCHAR p_card)
{
UCHAR width;
PSCCB currSCCB;
PSCCBMgr_tar_info currTar_Info;
- currSCCB = BL_Card[p_card].currentSCCB;
- currTar_Info = &sccbMgrTbl[p_card][currSCCB->TargID];
+ currSCCB = FPT_BL_Card[p_card].currentSCCB;
+ currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
- width = sfm(port,currSCCB);
+ width = FPT_sfm(port,currSCCB);
if((width == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY))
{
@@ -6958,7 +4060,7 @@ void stwidn(ULONG port, UCHAR p_card)
}
- sssyncv(port,currSCCB->TargID,width,currTar_Info);
+ FPT_sssyncv(port,currSCCB->TargID,width,currTar_Info);
if (currSCCB->Sccb_scsistat == SELECT_WN_ST)
@@ -6972,7 +4074,7 @@ void stwidn(ULONG port, UCHAR p_card)
{
ACCEPT_MSG_ATN(port);
ARAM_ACCESS(port);
- sisyncn(port,p_card, TRUE);
+ FPT_sisyncn(port,p_card, 1);
currSCCB->Sccb_scsistat = SELECT_SN_ST;
SGRAM_ACCESS(port);
}
@@ -6993,7 +4095,7 @@ void stwidn(ULONG port, UCHAR p_card)
else
width = SM8BIT;
- siwidr(port,width);
+ FPT_siwidr(port,width);
currTar_Info->TarStatus |= (WIDE_NEGOCIATED | WIDE_ENABLED);
}
@@ -7002,16 +4104,12 @@ void stwidn(ULONG port, UCHAR p_card)
/*---------------------------------------------------------------------
*
- * Function: siwidr
+ * Function: FPT_siwidr
*
* Description: Answer the targets Wide nego message.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void siwidr(USHORT port, UCHAR width)
-#else
-void siwidr(ULONG port, UCHAR width)
-#endif
+static void FPT_siwidr(ULONG port, UCHAR width)
{
ARAM_ACCESS(port);
WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+SMEXT ));
@@ -7030,23 +4128,18 @@ void siwidr(ULONG port, UCHAR width)
while (!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | AUTO_INT))) {}
}
-#endif
-
/*---------------------------------------------------------------------
*
- * Function: sssyncv
+ * Function: FPT_sssyncv
*
* Description: Write the desired value to the Sync Register for the
* ID specified.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void sssyncv(USHORT p_port, UCHAR p_id, UCHAR p_sync_value,PSCCBMgr_tar_info currTar_Info)
-#else
-void sssyncv(ULONG p_port, UCHAR p_id, UCHAR p_sync_value,PSCCBMgr_tar_info currTar_Info)
-#endif
+static void FPT_sssyncv(ULONG p_port, UCHAR p_id, UCHAR p_sync_value,
+ PSCCBMgr_tar_info currTar_Info)
{
UCHAR index;
@@ -7112,16 +4205,12 @@ void sssyncv(ULONG p_port, UCHAR p_id, UCHAR p_sync_value,PSCCBMgr_tar_info curr
/*---------------------------------------------------------------------
*
- * Function: sresb
+ * Function: FPT_sresb
*
* Description: Reset the desired card's SCSI bus.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void sresb(USHORT port, UCHAR p_card)
-#else
-void sresb(ULONG port, UCHAR p_card)
-#endif
+static void FPT_sresb(ULONG port, UCHAR p_card)
{
UCHAR scsiID, i;
@@ -7145,7 +4234,7 @@ void sresb(ULONG port, UCHAR p_card)
WR_HARPOON(port+hp_scsictrl_0, ENA_SCAM_SEL);
- Wait(port, TO_5ms);
+ FPT_Wait(port, TO_5ms);
WRW_HARPOON((port+hp_intstat), CLR_ALL_INT);
@@ -7153,7 +4242,7 @@ void sresb(ULONG port, UCHAR p_card)
for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++)
{
- currTar_Info = &sccbMgrTbl[p_card][scsiID];
+ currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
if (currTar_Info->TarEEValue & EE_SYNC_MASK)
{
@@ -7166,21 +4255,21 @@ void sresb(ULONG port, UCHAR p_card)
currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
}
- sssyncv(port, scsiID, NARROW_SCSI,currTar_Info);
+ FPT_sssyncv(port, scsiID, NARROW_SCSI,currTar_Info);
- SccbMgrTableInitTarget(p_card, scsiID);
+ FPT_SccbMgrTableInitTarget(p_card, scsiID);
}
- BL_Card[p_card].scanIndex = 0x00;
- BL_Card[p_card].currentSCCB = NULL;
- BL_Card[p_card].globalFlags &= ~(F_TAG_STARTED | F_HOST_XFER_ACT
+ FPT_BL_Card[p_card].scanIndex = 0x00;
+ FPT_BL_Card[p_card].currentSCCB = NULL;
+ FPT_BL_Card[p_card].globalFlags &= ~(F_TAG_STARTED | F_HOST_XFER_ACT
| F_NEW_SCCB_CMD);
- BL_Card[p_card].cmdCounter = 0x00;
- BL_Card[p_card].discQCount = 0x00;
- BL_Card[p_card].tagQ_Lst = 0x01;
+ FPT_BL_Card[p_card].cmdCounter = 0x00;
+ FPT_BL_Card[p_card].discQCount = 0x00;
+ FPT_BL_Card[p_card].tagQ_Lst = 0x01;
for(i = 0; i < QUEUE_DEPTH; i++)
- BL_Card[p_card].discQ_Tbl[i] = NULL;
+ FPT_BL_Card[p_card].discQ_Tbl[i] = NULL;
WR_HARPOON(port+hp_page_ctrl,
(RD_HARPOON(port+hp_page_ctrl) & ~G_INT_DISABLE));
@@ -7189,12 +4278,12 @@ void sresb(ULONG port, UCHAR p_card)
/*---------------------------------------------------------------------
*
- * Function: ssenss
+ * Function: FPT_ssenss
*
* Description: Setup for the Auto Sense command.
*
*---------------------------------------------------------------------*/
-void ssenss(PSCCBcard pCurrCard)
+static void FPT_ssenss(PSCCBcard pCurrCard)
{
UCHAR i;
PSCCB currSCCB;
@@ -7236,27 +4325,23 @@ void ssenss(PSCCBcard pCurrCard)
/*---------------------------------------------------------------------
*
- * Function: sxfrp
+ * Function: FPT_sxfrp
*
* Description: Transfer data into the bit bucket until the device
* decides to switch phase.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void sxfrp(USHORT p_port, UCHAR p_card)
-#else
-void sxfrp(ULONG p_port, UCHAR p_card)
-#endif
+static void FPT_sxfrp(ULONG p_port, UCHAR p_card)
{
UCHAR curr_phz;
DISABLE_AUTO(p_port);
- if (BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
+ if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
- hostDataXferAbort(p_port,p_card,BL_Card[p_card].currentSCCB);
+ FPT_hostDataXferAbort(p_port,p_card,FPT_BL_Card[p_card].currentSCCB);
}
@@ -7322,25 +4407,21 @@ void sxfrp(ULONG p_port, UCHAR p_card)
/*---------------------------------------------------------------------
*
- * Function: schkdd
+ * Function: FPT_schkdd
*
* Description: Make sure data has been flushed from both FIFOs and abort
* the operations if necessary.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void schkdd(USHORT port, UCHAR p_card)
-#else
-void schkdd(ULONG port, UCHAR p_card)
-#endif
+static void FPT_schkdd(ULONG port, UCHAR p_card)
{
USHORT TimeOutLoop;
UCHAR sPhase;
PSCCB currSCCB;
- currSCCB = BL_Card[p_card].currentSCCB;
+ currSCCB = FPT_BL_Card[p_card].currentSCCB;
if ((currSCCB->Sccb_scsistat != DATA_OUT_ST) &&
@@ -7378,7 +4459,7 @@ void schkdd(ULONG port, UCHAR p_card)
}
- hostDataXferAbort(port,p_card,currSCCB);
+ FPT_hostDataXferAbort(port,p_card,currSCCB);
while (RD_HARPOON(port+hp_scsisig) & SCSI_ACK) {}
@@ -7412,21 +4493,21 @@ void schkdd(ULONG port, UCHAR p_card)
if (!(currSCCB->Sccb_XferState & F_ALL_XFERRED))
{
if (currSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
- phaseDataIn(port,p_card);
+ FPT_phaseDataIn(port,p_card);
}
else {
- phaseDataOut(port,p_card);
+ FPT_phaseDataOut(port,p_card);
}
}
else
{
- sxfrp(port,p_card);
+ FPT_sxfrp(port,p_card);
if (!(RDW_HARPOON((port+hp_intstat)) &
(BUS_FREE | ICMD_COMP | ITAR_DISC | RESET)))
{
WRW_HARPOON((port+hp_intstat), AUTO_INT);
- phaseDecode(port,p_card);
+ FPT_phaseDecode(port,p_card);
}
}
@@ -7440,13 +4521,13 @@ void schkdd(ULONG port, UCHAR p_card)
/*---------------------------------------------------------------------
*
- * Function: sinits
+ * Function: FPT_sinits
*
* Description: Setup SCCB manager fields in this SCCB.
*
*---------------------------------------------------------------------*/
-void sinits(PSCCB p_sccb, UCHAR p_card)
+static void FPT_sinits(PSCCB p_sccb, UCHAR p_card)
{
PSCCBMgr_tar_info currTar_Info;
@@ -7454,7 +4535,7 @@ void sinits(PSCCB p_sccb, UCHAR p_card)
{
return;
}
- currTar_Info = &sccbMgrTbl[p_card][p_sccb->TargID];
+ currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
p_sccb->Sccb_XferState = 0x00;
p_sccb->Sccb_XferCnt = p_sccb->DataLength;
@@ -7485,7 +4566,7 @@ void sinits(PSCCB p_sccb, UCHAR p_card)
else send Cmd with Disconnect Disable */
/*
- if (((!(BL_Card[p_card].globalFlags & F_SINGLE_DEVICE)) &&
+ if (((!(FPT_BL_Card[p_card].globalFlags & F_SINGLE_DEVICE)) &&
(currTar_Info->TarStatus & TAR_ALLOW_DISC)) ||
(currTar_Info->TarStatus & TAG_Q_TRYING)) {
*/
@@ -7518,55 +4599,6 @@ void sinits(PSCCB p_sccb, UCHAR p_card)
}
-#ident "$Id: phase.c 1.11 1997/01/31 02:08:49 mohan Exp $"
-/*----------------------------------------------------------------------
- *
- *
- * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved
- *
- * This file is available under both the GNU General Public License
- * and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- * $Workfile: phase.c $
- *
- * Description: Functions to initially handle the SCSI bus phase when
- * the target asserts request (and the automation is not
- * enabled to handle the situation).
- *
- * $Date: 1997/01/31 02:08:49 $
- *
- * $Revision: 1.11 $
- *
- *----------------------------------------------------------------------*/
-
-/*#include <globals.h>*/
-
-#if (FW_TYPE==_UCB_MGR_)
- /*#include <budi.h>*/
-#endif
-
-/*#include <sccbmgr.h>*/
-/*#include <blx30.h>*/
-/*#include <target.h>*/
-/*#include <scsi2.h>*/
-/*#include <harpoon.h>*/
-
-
-/*
-extern SCCBCARD BL_Card[MAX_CARDS];
-extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR];
-
-#if defined(OS2)
- extern void (far *s_PhaseTbl[8]) (ULONG, UCHAR);
-#else
- #if defined(DOS)
- extern void (*s_PhaseTbl[8]) (USHORT, UCHAR);
- #else
- extern void (*s_PhaseTbl[8]) (ULONG, UCHAR);
- #endif
-#endif
-*/
-
/*---------------------------------------------------------------------
*
* Function: Phase Decode
@@ -7575,29 +4607,17 @@ extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR];
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void phaseDecode(USHORT p_port, UCHAR p_card)
-#else
-void phaseDecode(ULONG p_port, UCHAR p_card)
-#endif
+static void FPT_phaseDecode(ULONG p_port, UCHAR p_card)
{
unsigned char phase_ref;
-#if defined(OS2)
- void (far *phase) (ULONG, UCHAR);
-#else
- #if defined(DOS)
- void (*phase) (USHORT, UCHAR);
- #else
- void (*phase) (ULONG, UCHAR);
- #endif
-#endif
+ void (*phase) (ULONG, UCHAR);
DISABLE_AUTO(p_port);
phase_ref = (UCHAR) (RD_HARPOON(p_port+hp_scsisig) & S_SCSI_PHZ);
- phase = s_PhaseTbl[phase_ref];
+ phase = FPT_s_PhaseTbl[phase_ref];
(*phase)(p_port, p_card); /* Call the correct phase func */
}
@@ -7612,20 +4632,12 @@ void phaseDecode(ULONG p_port, UCHAR p_card)
*
*---------------------------------------------------------------------*/
-#if defined(OS2)
-void far phaseDataOut(ULONG port, UCHAR p_card)
-#else
-#if defined(DOS)
-void phaseDataOut(USHORT port, UCHAR p_card)
-#else
-void phaseDataOut(ULONG port, UCHAR p_card)
-#endif
-#endif
+static void FPT_phaseDataOut(ULONG port, UCHAR p_card)
{
PSCCB currSCCB;
- currSCCB = BL_Card[p_card].currentSCCB;
+ currSCCB = FPT_BL_Card[p_card].currentSCCB;
if (currSCCB == NULL)
{
return; /* Exit if No SCCB record */
@@ -7640,14 +4652,7 @@ void phaseDataOut(ULONG port, UCHAR p_card)
WR_HARPOON(port+hp_autostart_0, (END_DATA+END_DATA_START));
- dataXferProcessor(port, &BL_Card[p_card]);
-
-#if defined(NOBUGBUG)
- if (RDW_HARPOON((port+hp_intstat)) & XFER_CNT_0)
- WRW_HARPOON((port+hp_intstat), XFER_CNT_0);
-
-#endif
-
+ FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
if (currSCCB->Sccb_XferCnt == 0) {
@@ -7656,9 +4661,9 @@ void phaseDataOut(ULONG port, UCHAR p_card)
(currSCCB->HostStatus == SCCB_COMPLETE))
currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
- sxfrp(port,p_card);
+ FPT_sxfrp(port,p_card);
if (!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | RESET)))
- phaseDecode(port,p_card);
+ FPT_phaseDecode(port,p_card);
}
}
@@ -7671,20 +4676,12 @@ void phaseDataOut(ULONG port, UCHAR p_card)
*
*---------------------------------------------------------------------*/
-#if defined(OS2)
-void far phaseDataIn(ULONG port, UCHAR p_card)
-#else
-#if defined(DOS)
-void phaseDataIn(USHORT port, UCHAR p_card)
-#else
-void phaseDataIn(ULONG port, UCHAR p_card)
-#endif
-#endif
+static void FPT_phaseDataIn(ULONG port, UCHAR p_card)
{
PSCCB currSCCB;
- currSCCB = BL_Card[p_card].currentSCCB;
+ currSCCB = FPT_BL_Card[p_card].currentSCCB;
if (currSCCB == NULL)
{
@@ -7702,7 +4699,7 @@ void phaseDataIn(ULONG port, UCHAR p_card)
WR_HARPOON(port+hp_autostart_0, (END_DATA+END_DATA_START));
- dataXferProcessor(port, &BL_Card[p_card]);
+ FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
if (currSCCB->Sccb_XferCnt == 0) {
@@ -7711,9 +4708,9 @@ void phaseDataIn(ULONG port, UCHAR p_card)
(currSCCB->HostStatus == SCCB_COMPLETE))
currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
- sxfrp(port,p_card);
+ FPT_sxfrp(port,p_card);
if (!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | RESET)))
- phaseDecode(port,p_card);
+ FPT_phaseDecode(port,p_card);
}
}
@@ -7726,25 +4723,13 @@ void phaseDataIn(ULONG port, UCHAR p_card)
*
*---------------------------------------------------------------------*/
-#if defined(OS2)
-void far phaseCommand(ULONG p_port, UCHAR p_card)
-#else
-#if defined(DOS)
-void phaseCommand(USHORT p_port, UCHAR p_card)
-#else
-void phaseCommand(ULONG p_port, UCHAR p_card)
-#endif
-#endif
+static void FPT_phaseCommand(ULONG p_port, UCHAR p_card)
{
PSCCB currSCCB;
-#if defined(DOS)
- USHORT cdb_reg;
-#else
ULONG cdb_reg;
-#endif
UCHAR i;
- currSCCB = BL_Card[p_card].currentSCCB;
+ currSCCB = FPT_BL_Card[p_card].currentSCCB;
if (currSCCB->OperationCode == RESET_COMMAND) {
@@ -7790,15 +4775,7 @@ void phaseCommand(ULONG p_port, UCHAR p_card)
*
*---------------------------------------------------------------------*/
-#if defined(OS2)
-void far phaseStatus(ULONG port, UCHAR p_card)
-#else
-#if defined(DOS)
-void phaseStatus(USHORT port, UCHAR p_card)
-#else
-void phaseStatus(ULONG port, UCHAR p_card)
-#endif
-#endif
+static void FPT_phaseStatus(ULONG port, UCHAR p_card)
{
/* Start-up the automation to finish off this command and let the
isr handle the interrupt for command complete when it comes in.
@@ -7820,21 +4797,13 @@ void phaseStatus(ULONG port, UCHAR p_card)
*
*---------------------------------------------------------------------*/
-#if defined(OS2)
-void far phaseMsgOut(ULONG port, UCHAR p_card)
-#else
-#if defined(DOS)
-void phaseMsgOut(USHORT port, UCHAR p_card)
-#else
-void phaseMsgOut(ULONG port, UCHAR p_card)
-#endif
-#endif
+static void FPT_phaseMsgOut(ULONG port, UCHAR p_card)
{
UCHAR message,scsiID;
PSCCB currSCCB;
PSCCBMgr_tar_info currTar_Info;
- currSCCB = BL_Card[p_card].currentSCCB;
+ currSCCB = FPT_BL_Card[p_card].currentSCCB;
if (currSCCB != NULL) {
@@ -7845,34 +4814,34 @@ void phaseMsgOut(ULONG port, UCHAR p_card)
{
- currTar_Info = &sccbMgrTbl[p_card][scsiID];
+ currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
currTar_Info->TarSyncCtrl = 0;
- sssyncv(port, scsiID, NARROW_SCSI,currTar_Info);
+ FPT_sssyncv(port, scsiID, NARROW_SCSI,currTar_Info);
- if (sccbMgrTbl[p_card][scsiID].TarEEValue & EE_SYNC_MASK)
+ if (FPT_sccbMgrTbl[p_card][scsiID].TarEEValue & EE_SYNC_MASK)
{
- sccbMgrTbl[p_card][scsiID].TarStatus &= ~TAR_SYNC_MASK;
+ FPT_sccbMgrTbl[p_card][scsiID].TarStatus &= ~TAR_SYNC_MASK;
}
- if (sccbMgrTbl[p_card][scsiID].TarEEValue & EE_WIDE_SCSI)
+ if (FPT_sccbMgrTbl[p_card][scsiID].TarEEValue & EE_WIDE_SCSI)
{
- sccbMgrTbl[p_card][scsiID].TarStatus &= ~TAR_WIDE_MASK;
+ FPT_sccbMgrTbl[p_card][scsiID].TarStatus &= ~TAR_WIDE_MASK;
}
- queueFlushSccb(p_card,SCCB_COMPLETE);
- SccbMgrTableInitTarget(p_card,scsiID);
+ FPT_queueFlushSccb(p_card,SCCB_COMPLETE);
+ FPT_SccbMgrTableInitTarget(p_card,scsiID);
}
else if (currSCCB->Sccb_scsistat == ABORT_ST)
{
currSCCB->HostStatus = SCCB_COMPLETE;
- if(BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] != NULL)
+ if(FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] != NULL)
{
- BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
- sccbMgrTbl[p_card][scsiID].TarTagQ_Cnt--;
+ FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
+ FPT_sccbMgrTbl[p_card][scsiID].TarTagQ_Cnt--;
}
}
@@ -7885,7 +4854,7 @@ void phaseMsgOut(ULONG port, UCHAR p_card)
{
currSCCB->Sccb_MGRFlags |= F_DEV_SELECTED;
- ssel(port,p_card);
+ FPT_ssel(port,p_card);
return;
}
}
@@ -7895,7 +4864,7 @@ void phaseMsgOut(ULONG port, UCHAR p_card)
if (message == SMABORT)
- queueFlushSccb(p_card,SCCB_COMPLETE);
+ FPT_queueFlushSccb(p_card,SCCB_COMPLETE);
}
}
@@ -7930,25 +4899,25 @@ void phaseMsgOut(ULONG port, UCHAR p_card)
if (currSCCB != NULL)
{
- if((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
- ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
- sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = FALSE;
+ if((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
+ ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = 0;
else
- sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = FALSE;
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0;
- queueCmdComplete(&BL_Card[p_card],currSCCB, p_card);
+ FPT_queueCmdComplete(&FPT_BL_Card[p_card],currSCCB, p_card);
}
else
{
- BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
+ FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
}
}
else
{
- sxfrp(port,p_card);
+ FPT_sxfrp(port,p_card);
}
}
@@ -7962,7 +4931,7 @@ void phaseMsgOut(ULONG port, UCHAR p_card)
}
else
{
- sxfrp(port,p_card);
+ FPT_sxfrp(port,p_card);
}
}
}
@@ -7976,25 +4945,17 @@ void phaseMsgOut(ULONG port, UCHAR p_card)
*
*---------------------------------------------------------------------*/
-#if defined(OS2)
-void far phaseMsgIn(ULONG port, UCHAR p_card)
-#else
-#if defined(DOS)
-void phaseMsgIn(USHORT port, UCHAR p_card)
-#else
-void phaseMsgIn(ULONG port, UCHAR p_card)
-#endif
-#endif
+static void FPT_phaseMsgIn(ULONG port, UCHAR p_card)
{
UCHAR message;
PSCCB currSCCB;
- currSCCB = BL_Card[p_card].currentSCCB;
+ currSCCB = FPT_BL_Card[p_card].currentSCCB;
- if (BL_Card[p_card].globalFlags & F_HOST_XFER_ACT)
+ if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT)
{
- phaseChkFifo(port, p_card);
+ FPT_phaseChkFifo(port, p_card);
}
message = RD_HARPOON(port+hp_scsidata_0);
@@ -8008,12 +4969,12 @@ void phaseMsgIn(ULONG port, UCHAR p_card)
else
{
- message = sfm(port,currSCCB);
+ message = FPT_sfm(port,currSCCB);
if (message)
{
- sdecm(message,port,p_card);
+ FPT_sdecm(message,port,p_card);
}
else
@@ -8037,19 +4998,11 @@ void phaseMsgIn(ULONG port, UCHAR p_card)
*
*---------------------------------------------------------------------*/
-#if defined(OS2)
-void far phaseIllegal(ULONG port, UCHAR p_card)
-#else
-#if defined(DOS)
-void phaseIllegal(USHORT port, UCHAR p_card)
-#else
-void phaseIllegal(ULONG port, UCHAR p_card)
-#endif
-#endif
+static void FPT_phaseIllegal(ULONG port, UCHAR p_card)
{
PSCCB currSCCB;
- currSCCB = BL_Card[p_card].currentSCCB;
+ currSCCB = FPT_BL_Card[p_card].currentSCCB;
WR_HARPOON(port+hp_scsisig, RD_HARPOON(port+hp_scsisig));
if (currSCCB != NULL) {
@@ -8073,16 +5026,12 @@ void phaseIllegal(ULONG port, UCHAR p_card)
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void phaseChkFifo(USHORT port, UCHAR p_card)
-#else
-void phaseChkFifo(ULONG port, UCHAR p_card)
-#endif
+static void FPT_phaseChkFifo(ULONG port, UCHAR p_card)
{
ULONG xfercnt;
PSCCB currSCCB;
- currSCCB = BL_Card[p_card].currentSCCB;
+ currSCCB = FPT_BL_Card[p_card].currentSCCB;
if (currSCCB->Sccb_scsistat == DATA_IN_ST)
{
@@ -8104,9 +5053,9 @@ void phaseChkFifo(ULONG port, UCHAR p_card)
WRW_HARPOON((port+hp_intstat), PARITY);
}
- hostDataXferAbort(port,p_card,currSCCB);
+ FPT_hostDataXferAbort(port,p_card,currSCCB);
- dataXferProcessor(port, &BL_Card[p_card]);
+ FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
while((!(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY)) &&
(RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY)) {}
@@ -8116,22 +5065,7 @@ void phaseChkFifo(ULONG port, UCHAR p_card)
-#if defined(DOS)
- asm { mov dx,port;
- add dx,hp_xfercnt_2;
- in al,dx;
- dec dx;
- xor ah,ah;
- mov word ptr xfercnt+2,ax;
- in al,dx;
- dec dx;
- mov ah,al;
- in al,dx;
- mov word ptr xfercnt,ax;
- }
-#else
GET_XFER_CNT(port,xfercnt);
-#endif
WR_HARPOON(port+hp_xfercnt_0, 0x00);
@@ -8151,7 +5085,7 @@ void phaseChkFifo(ULONG port, UCHAR p_card)
}
- hostDataXferAbort(port,p_card,currSCCB);
+ FPT_hostDataXferAbort(port,p_card,currSCCB);
WR_HARPOON(port+hp_fifowrite, 0x00);
@@ -8170,15 +5104,11 @@ void phaseChkFifo(ULONG port, UCHAR p_card)
* because of command complete or from a disconnect.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void phaseBusFree(USHORT port, UCHAR p_card)
-#else
-void phaseBusFree(ULONG port, UCHAR p_card)
-#endif
+static void FPT_phaseBusFree(ULONG port, UCHAR p_card)
{
PSCCB currSCCB;
- currSCCB = BL_Card[p_card].currentSCCB;
+ currSCCB = FPT_BL_Card[p_card].currentSCCB;
if (currSCCB != NULL)
{
@@ -8189,35 +5119,34 @@ void phaseBusFree(ULONG port, UCHAR p_card)
if (currSCCB->OperationCode == RESET_COMMAND)
{
- if((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
- ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
- sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = FALSE;
+ if((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
+ ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = 0;
else
- sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = FALSE;
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0;
- queueCmdComplete(&BL_Card[p_card], currSCCB, p_card);
+ FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, p_card);
- queueSearchSelect(&BL_Card[p_card],p_card);
+ FPT_queueSearchSelect(&FPT_BL_Card[p_card],p_card);
}
else if(currSCCB->Sccb_scsistat == SELECT_SN_ST)
{
- sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
(UCHAR)SYNC_SUPPORTED;
- sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_SYNC_MASK;
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_SYNC_MASK;
}
else if(currSCCB->Sccb_scsistat == SELECT_WN_ST)
{
- sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
- (sccbMgrTbl[p_card][currSCCB->TargID].
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
+ (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
- sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_WIDE_SCSI;
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_WIDE_SCSI;
}
-#if !defined(DOS)
else if(currSCCB->Sccb_scsistat == SELECT_Q_ST)
{
/* Make sure this is not a phony BUS_FREE. If we were
@@ -8227,8 +5156,8 @@ void phaseBusFree(ULONG port, UCHAR p_card)
if ((!(RD_HARPOON(port+hp_scsisig) & SCSI_BSY)) ||
(RDW_HARPOON((port+hp_intstat)) & RSEL))
{
- sccbMgrTbl[p_card][currSCCB->TargID].TarStatus &= ~TAR_TAG_Q_MASK;
- sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |= TAG_Q_REJECT;
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus &= ~TAR_TAG_Q_MASK;
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |= TAG_Q_REJECT;
}
else
@@ -8236,7 +5165,6 @@ void phaseBusFree(ULONG port, UCHAR p_card)
return;
}
}
-#endif
else
{
@@ -8248,18 +5176,18 @@ void phaseBusFree(ULONG port, UCHAR p_card)
currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
}
- if((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
- ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
- sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = FALSE;
+ if((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
+ ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = 0;
else
- sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = FALSE;
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0;
- queueCmdComplete(&BL_Card[p_card], currSCCB, p_card);
+ FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, p_card);
return;
}
- BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
+ FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
} /*end if !=null */
}
@@ -8267,44 +5195,6 @@ void phaseBusFree(ULONG port, UCHAR p_card)
-#ident "$Id: automate.c 1.14 1997/01/31 02:11:46 mohan Exp $"
-/*----------------------------------------------------------------------
- *
- *
- * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved
- *
- * This file is available under both the GNU General Public License
- * and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- * $Workfile: automate.c $
- *
- * Description: Functions relating to programming the automation of
- * the HARPOON.
- *
- * $Date: 1997/01/31 02:11:46 $
- *
- * $Revision: 1.14 $
- *
- *----------------------------------------------------------------------*/
-
-/*#include <globals.h>*/
-
-#if (FW_TYPE==_UCB_MGR_)
- /*#include <budi.h>*/
-#endif
-
-/*#include <sccbmgr.h>*/
-/*#include <blx30.h>*/
-/*#include <target.h>*/
-/*#include <scsi2.h>*/
-/*#include <harpoon.h>*/
-
-/*
-extern SCCBCARD BL_Card[MAX_CARDS];
-extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR];
-extern SCCBCARD BL_Card[MAX_CARDS];
-*/
-
/*---------------------------------------------------------------------
*
* Function: Auto Load Default Map
@@ -8312,17 +5202,9 @@ extern SCCBCARD BL_Card[MAX_CARDS];
* Description: Load the Automation RAM with the defualt map values.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void autoLoadDefaultMap(USHORT p_port)
-#else
-void autoLoadDefaultMap(ULONG p_port)
-#endif
+static void FPT_autoLoadDefaultMap(ULONG p_port)
{
-#if defined(DOS)
- USHORT map_addr;
-#else
ULONG map_addr;
-#endif
ARAM_ACCESS(p_port);
map_addr = p_port + hp_aramBase;
@@ -8428,86 +5310,82 @@ void autoLoadDefaultMap(ULONG p_port)
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void autoCmdCmplt(USHORT p_port, UCHAR p_card)
-#else
-void autoCmdCmplt(ULONG p_port, UCHAR p_card)
-#endif
+static void FPT_autoCmdCmplt(ULONG p_port, UCHAR p_card)
{
PSCCB currSCCB;
UCHAR status_byte;
- currSCCB = BL_Card[p_card].currentSCCB;
+ currSCCB = FPT_BL_Card[p_card].currentSCCB;
status_byte = RD_HARPOON(p_port+hp_gp_reg_0);
- sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA = FALSE;
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA = 0;
if (status_byte != SSGOOD) {
if (status_byte == SSQ_FULL) {
- if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
- ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
+ if(((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
+ ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
{
- sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = TRUE;
- if(BL_Card[p_card].discQCount != 0)
- BL_Card[p_card].discQCount--;
- BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL;
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = 1;
+ if(FPT_BL_Card[p_card].discQCount != 0)
+ FPT_BL_Card[p_card].discQCount--;
+ FPT_BL_Card[p_card].discQ_Tbl[FPT_sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL;
}
else
{
- sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = TRUE;
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 1;
if(currSCCB->Sccb_tag)
{
- if(BL_Card[p_card].discQCount != 0)
- BL_Card[p_card].discQCount--;
- BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
+ if(FPT_BL_Card[p_card].discQCount != 0)
+ FPT_BL_Card[p_card].discQCount--;
+ FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
}else
{
- if(BL_Card[p_card].discQCount != 0)
- BL_Card[p_card].discQCount--;
- BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL;
+ if(FPT_BL_Card[p_card].discQCount != 0)
+ FPT_BL_Card[p_card].discQCount--;
+ FPT_BL_Card[p_card].discQ_Tbl[FPT_sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL;
}
}
currSCCB->Sccb_MGRFlags |= F_STATUSLOADED;
- queueSelectFail(&BL_Card[p_card],p_card);
+ FPT_queueSelectFail(&FPT_BL_Card[p_card],p_card);
return;
}
if(currSCCB->Sccb_scsistat == SELECT_SN_ST)
{
- sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
(UCHAR)SYNC_SUPPORTED;
- sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_SYNC_MASK;
- BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_SYNC_MASK;
+ FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
- if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
- ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
+ if(((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
+ ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
{
- sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = TRUE;
- if(BL_Card[p_card].discQCount != 0)
- BL_Card[p_card].discQCount--;
- BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL;
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = 1;
+ if(FPT_BL_Card[p_card].discQCount != 0)
+ FPT_BL_Card[p_card].discQCount--;
+ FPT_BL_Card[p_card].discQ_Tbl[FPT_sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL;
}
else
{
- sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = TRUE;
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 1;
if(currSCCB->Sccb_tag)
{
- if(BL_Card[p_card].discQCount != 0)
- BL_Card[p_card].discQCount--;
- BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
+ if(FPT_BL_Card[p_card].discQCount != 0)
+ FPT_BL_Card[p_card].discQCount--;
+ FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
}else
{
- if(BL_Card[p_card].discQCount != 0)
- BL_Card[p_card].discQCount--;
- BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL;
+ if(FPT_BL_Card[p_card].discQCount != 0)
+ FPT_BL_Card[p_card].discQCount--;
+ FPT_BL_Card[p_card].discQ_Tbl[FPT_sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL;
}
}
return;
@@ -8517,34 +5395,34 @@ void autoCmdCmplt(ULONG p_port, UCHAR p_card)
if(currSCCB->Sccb_scsistat == SELECT_WN_ST)
{
- sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
- (sccbMgrTbl[p_card][currSCCB->TargID].
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
+ (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
- sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_WIDE_SCSI;
- BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_WIDE_SCSI;
+ FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
- if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
- ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
+ if(((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
+ ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
{
- sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = TRUE;
- if(BL_Card[p_card].discQCount != 0)
- BL_Card[p_card].discQCount--;
- BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL;
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = 1;
+ if(FPT_BL_Card[p_card].discQCount != 0)
+ FPT_BL_Card[p_card].discQCount--;
+ FPT_BL_Card[p_card].discQ_Tbl[FPT_sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL;
}
else
{
- sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = TRUE;
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 1;
if(currSCCB->Sccb_tag)
{
- if(BL_Card[p_card].discQCount != 0)
- BL_Card[p_card].discQCount--;
- BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
+ if(FPT_BL_Card[p_card].discQCount != 0)
+ FPT_BL_Card[p_card].discQCount--;
+ FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
}else
{
- if(BL_Card[p_card].discQCount != 0)
- BL_Card[p_card].discQCount--;
- BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL;
+ if(FPT_BL_Card[p_card].discQCount != 0)
+ FPT_BL_Card[p_card].discQCount--;
+ FPT_BL_Card[p_card].discQ_Tbl[FPT_sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL;
}
}
return;
@@ -8553,15 +5431,15 @@ void autoCmdCmplt(ULONG p_port, UCHAR p_card)
if (status_byte == SSCHECK)
{
- if(BL_Card[p_card].globalFlags & F_DO_RENEGO)
+ if(FPT_BL_Card[p_card].globalFlags & F_DO_RENEGO)
{
- if (sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue & EE_SYNC_MASK)
+ if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue & EE_SYNC_MASK)
{
- sccbMgrTbl[p_card][currSCCB->TargID].TarStatus &= ~TAR_SYNC_MASK;
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus &= ~TAR_SYNC_MASK;
}
- if (sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue & EE_WIDE_SCSI)
+ if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue & EE_WIDE_SCSI)
{
- sccbMgrTbl[p_card][currSCCB->TargID].TarStatus &= ~TAR_WIDE_MASK;
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus &= ~TAR_WIDE_MASK;
}
}
}
@@ -8573,135 +5451,61 @@ void autoCmdCmplt(ULONG p_port, UCHAR p_card)
if (status_byte == SSCHECK) {
- sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA
- = TRUE;
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA
+ = 1;
-#if (FW_TYPE==_SCCB_MGR_)
if (currSCCB->RequestSenseLength != NO_AUTO_REQUEST_SENSE) {
if (currSCCB->RequestSenseLength == 0)
currSCCB->RequestSenseLength = 14;
- ssenss(&BL_Card[p_card]);
- BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
+ FPT_ssenss(&FPT_BL_Card[p_card]);
+ FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
- if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
- ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
+ if(((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
+ ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
{
- sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = TRUE;
- if(BL_Card[p_card].discQCount != 0)
- BL_Card[p_card].discQCount--;
- BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL;
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = 1;
+ if(FPT_BL_Card[p_card].discQCount != 0)
+ FPT_BL_Card[p_card].discQCount--;
+ FPT_BL_Card[p_card].discQ_Tbl[FPT_sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL;
}
else
{
- sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = TRUE;
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 1;
if(currSCCB->Sccb_tag)
{
- if(BL_Card[p_card].discQCount != 0)
- BL_Card[p_card].discQCount--;
- BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
+ if(FPT_BL_Card[p_card].discQCount != 0)
+ FPT_BL_Card[p_card].discQCount--;
+ FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
}else
{
- if(BL_Card[p_card].discQCount != 0)
- BL_Card[p_card].discQCount--;
- BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL;
+ if(FPT_BL_Card[p_card].discQCount != 0)
+ FPT_BL_Card[p_card].discQCount--;
+ FPT_BL_Card[p_card].discQ_Tbl[FPT_sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL;
}
}
return;
}
-#else
- if ((!(currSCCB->Sccb_ucb_ptr->UCB_opcode & OPC_NO_AUTO_SENSE)) &&
- (currSCCB->RequestSenseLength))
- {
- ssenss(&BL_Card[p_card]);
- BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
-
- if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
- ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
- {
- sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = TRUE;
- if(BL_Card[p_card].discQCount != 0)
- BL_Card[p_card].discQCount--;
- BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL;
- }
- else
- {
- sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = TRUE;
- if(currSCCB->Sccb_tag)
- {
- if(BL_Card[p_card].discQCount != 0)
- BL_Card[p_card].discQCount--;
- BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
- }else
- {
- if(BL_Card[p_card].discQCount != 0)
- BL_Card[p_card].discQCount--;
- BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL;
- }
- }
- return;
- }
-
-#endif
}
}
}
- if((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
- ((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
- sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = FALSE;
+ if((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
+ ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = 0;
else
- sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = FALSE;
+ FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0;
- queueCmdComplete(&BL_Card[p_card], currSCCB, p_card);
+ FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, p_card);
}
-#ident "$Id: busmstr.c 1.8 1997/01/31 02:10:27 mohan Exp $"
-/*----------------------------------------------------------------------
- *
- *
- * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved
- *
- * This file is available under both the GNU General Public License
- * and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- * $Workfile: busmstr.c $
- *
- * Description: Functions to start, stop, and abort BusMaster operations.
- *
- * $Date: 1997/01/31 02:10:27 $
- *
- * $Revision: 1.8 $
- *
- *----------------------------------------------------------------------*/
-
-/*#include <globals.h>*/
-
-#if (FW_TYPE==_UCB_MGR_)
- /*#include <budi.h>*/
-#endif
-
-/*#include <sccbmgr.h>*/
-/*#include <blx30.h>*/
-/*#include <target.h>*/
-/*#include <scsi2.h>*/
-/*#include <harpoon.h>*/
-
-
-/*
-extern SCCBCARD BL_Card[MAX_CARDS];
-extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR];
-*/
#define SHORT_WAIT 0x0000000F
#define LONG_WAIT 0x0000FFFFL
-#if defined(BUGBUG)
-void Debug_Load(UCHAR p_card, UCHAR p_bug_data);
-#endif
/*---------------------------------------------------------------------
*
@@ -8721,11 +5525,7 @@ void Debug_Load(UCHAR p_card, UCHAR p_bug_data);
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void dataXferProcessor(USHORT port, PSCCBcard pCurrCard)
-#else
-void dataXferProcessor(ULONG port, PSCCBcard pCurrCard)
-#endif
+static void FPT_dataXferProcessor(ULONG port, PSCCBcard pCurrCard)
{
PSCCB currSCCB;
@@ -8741,7 +5541,7 @@ void dataXferProcessor(ULONG port, PSCCBcard pCurrCard)
}
pCurrCard->globalFlags |= F_HOST_XFER_ACT;
- busMstrSGDataXferStart(port, currSCCB);
+ FPT_busMstrSGDataXferStart(port, currSCCB);
}
else
@@ -8750,7 +5550,7 @@ void dataXferProcessor(ULONG port, PSCCBcard pCurrCard)
{
pCurrCard->globalFlags |= F_HOST_XFER_ACT;
- busMstrDataXferStart(port, currSCCB);
+ FPT_busMstrDataXferStart(port, currSCCB);
}
}
}
@@ -8763,20 +5563,12 @@ void dataXferProcessor(ULONG port, PSCCBcard pCurrCard)
* Description:
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void busMstrSGDataXferStart(USHORT p_port, PSCCB pcurrSCCB)
-#else
-void busMstrSGDataXferStart(ULONG p_port, PSCCB pcurrSCCB)
-#endif
+static void FPT_busMstrSGDataXferStart(ULONG p_port, PSCCB pcurrSCCB)
{
ULONG count,addr,tmpSGCnt;
UINT sg_index;
UCHAR sg_count, i;
-#if defined(DOS)
- USHORT reg_offset;
-#else
ULONG reg_offset;
-#endif
if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
@@ -8802,17 +5594,6 @@ void busMstrSGDataXferStart(ULONG p_port, PSCCB pcurrSCCB)
while ((sg_count < (UCHAR)SG_BUF_CNT) &&
((ULONG)(sg_index * (UINT)SG_ELEMENT_SIZE) < pcurrSCCB->DataLength) ) {
-#if defined(COMPILER_16_BIT) && !defined(DOS)
- tmpSGCnt += *(((ULONG far *)pcurrSCCB->DataPointer)+
- (sg_index * 2));
-
- count |= *(((ULONG far *)pcurrSCCB->DataPointer)+
- (sg_index * 2));
-
- addr = *(((ULONG far *)pcurrSCCB->DataPointer)+
- ((sg_index * 2) + 1));
-
-#else
tmpSGCnt += *(((ULONG *)pcurrSCCB->DataPointer)+
(sg_index * 2));
@@ -8821,7 +5602,6 @@ void busMstrSGDataXferStart(ULONG p_port, PSCCB pcurrSCCB)
addr = *(((ULONG *)pcurrSCCB->DataPointer)+
((sg_index * 2) + 1));
-#endif
if ((!sg_count) && (pcurrSCCB->Sccb_SGoffset)) {
@@ -8888,11 +5668,7 @@ void busMstrSGDataXferStart(ULONG p_port, PSCCB pcurrSCCB)
* Description:
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void busMstrDataXferStart(USHORT p_port, PSCCB pcurrSCCB)
-#else
-void busMstrDataXferStart(ULONG p_port, PSCCB pcurrSCCB)
-#endif
+static void FPT_busMstrDataXferStart(ULONG p_port, PSCCB pcurrSCCB)
{
ULONG addr,count;
@@ -8909,37 +5685,7 @@ void busMstrDataXferStart(ULONG p_port, PSCCB pcurrSCCB)
}
-#if defined(DOS)
- asm { mov dx,p_port;
- mov ax,word ptr count;
- add dx,hp_xfer_cnt_lo;
- out dx,al;
- inc dx;
- xchg ah,al
- out dx,al;
- inc dx;
- mov ax,word ptr count+2;
- out dx,al;
- inc dx;
- inc dx;
- mov ax,word ptr addr;
- out dx,al;
- inc dx;
- xchg ah,al
- out dx,al;
- inc dx;
- mov ax,word ptr addr+2;
- out dx,al;
- inc dx;
- xchg ah,al
- out dx,al;
- }
-
- WR_HARP32(p_port,hp_xfercnt_0,count);
-
-#else
HP_SETUP_ADDR_CNT(p_port,addr,count);
-#endif
if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
@@ -8975,11 +5721,7 @@ void busMstrDataXferStart(ULONG p_port, PSCCB pcurrSCCB)
* command busy is also time out, it'll just give up.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-UCHAR busMstrTimeOut(USHORT p_port)
-#else
-UCHAR busMstrTimeOut(ULONG p_port)
-#endif
+static UCHAR FPT_busMstrTimeOut(ULONG p_port)
{
ULONG timeout;
@@ -9001,11 +5743,11 @@ UCHAR busMstrTimeOut(ULONG p_port)
RD_HARPOON(p_port+hp_int_status); /*Clear command complete */
if (RD_HARPOON(p_port+hp_ext_status) & BM_CMD_BUSY) {
- return(TRUE);
+ return(1);
}
else {
- return(FALSE);
+ return(0);
}
}
@@ -9017,18 +5759,14 @@ UCHAR busMstrTimeOut(ULONG p_port)
* Description: Abort any in progress transfer.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void hostDataXferAbort(USHORT port, UCHAR p_card, PSCCB pCurrSCCB)
-#else
-void hostDataXferAbort(ULONG port, UCHAR p_card, PSCCB pCurrSCCB)
-#endif
+static void FPT_hostDataXferAbort(ULONG port, UCHAR p_card, PSCCB pCurrSCCB)
{
ULONG timeout;
ULONG remain_cnt;
UINT sg_ptr;
- BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT;
+ FPT_BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT;
if (pCurrSCCB->Sccb_XferState & F_AUTO_SENSE) {
@@ -9044,7 +5782,7 @@ void hostDataXferAbort(ULONG port, UCHAR p_card, PSCCB pCurrSCCB)
if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) {
- if (busMstrTimeOut(port)) {
+ if (FPT_busMstrTimeOut(port)) {
if (pCurrSCCB->HostStatus == 0x00)
@@ -9060,10 +5798,6 @@ void hostDataXferAbort(ULONG port, UCHAR p_card, PSCCB pCurrSCCB)
{
pCurrSCCB->HostStatus = SCCB_BM_ERR;
-#if defined(BUGBUG)
- WR_HARPOON(port+hp_dual_addr_lo,
- RD_HARPOON(port+hp_ext_status));
-#endif
}
}
}
@@ -9092,22 +5826,12 @@ void hostDataXferAbort(ULONG port, UCHAR p_card, PSCCB pCurrSCCB)
sg_ptr--;
-#if defined(COMPILER_16_BIT) && !defined(DOS)
- if (remain_cnt > (ULONG)(*(((ULONG far *)pCurrSCCB->
- DataPointer) + (sg_ptr * 2)))) {
-
- remain_cnt -= (ULONG)(*(((ULONG far *)pCurrSCCB->
- DataPointer) + (sg_ptr * 2)));
- }
-
-#else
if (remain_cnt > (ULONG)(*(((ULONG *)pCurrSCCB->
DataPointer) + (sg_ptr * 2)))) {
remain_cnt -= (ULONG)(*(((ULONG *)pCurrSCCB->
DataPointer) + (sg_ptr * 2)));
}
-#endif
else {
@@ -9147,7 +5871,7 @@ void hostDataXferAbort(ULONG port, UCHAR p_card, PSCCB pCurrSCCB)
if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) {
- busMstrTimeOut(port);
+ FPT_busMstrTimeOut(port);
}
else {
@@ -9159,10 +5883,6 @@ void hostDataXferAbort(ULONG port, UCHAR p_card, PSCCB pCurrSCCB)
if (pCurrSCCB->HostStatus == 0x00) {
pCurrSCCB->HostStatus = SCCB_BM_ERR;
-#if defined(BUGBUG)
- WR_HARPOON(port+hp_dual_addr_lo,
- RD_HARPOON(port+hp_ext_status));
-#endif
}
}
}
@@ -9203,7 +5923,7 @@ void hostDataXferAbort(ULONG port, UCHAR p_card, PSCCB pCurrSCCB)
pCurrSCCB->HostStatus = SCCB_BM_ERR;
}
- busMstrTimeOut(port);
+ FPT_busMstrTimeOut(port);
}
}
@@ -9214,10 +5934,6 @@ void hostDataXferAbort(ULONG port, UCHAR p_card, PSCCB pCurrSCCB)
if (pCurrSCCB->HostStatus == 0x00) {
pCurrSCCB->HostStatus = SCCB_BM_ERR;
-#if defined(BUGBUG)
- WR_HARPOON(port+hp_dual_addr_lo,
- RD_HARPOON(port+hp_ext_status));
-#endif
}
}
}
@@ -9241,7 +5957,7 @@ void hostDataXferAbort(ULONG port, UCHAR p_card, PSCCB pCurrSCCB)
pCurrSCCB->HostStatus = SCCB_BM_ERR;
}
- busMstrTimeOut(port);
+ FPT_busMstrTimeOut(port);
}
}
@@ -9253,10 +5969,6 @@ void hostDataXferAbort(ULONG port, UCHAR p_card, PSCCB pCurrSCCB)
if (pCurrSCCB->HostStatus == 0x00) {
pCurrSCCB->HostStatus = SCCB_BM_ERR;
-#if defined(BUGBUG)
- WR_HARPOON(port+hp_dual_addr_lo,
- RD_HARPOON(port+hp_ext_status));
-#endif
}
}
@@ -9305,15 +6017,11 @@ void hostDataXferAbort(ULONG port, UCHAR p_card, PSCCB pCurrSCCB)
* pointers message.
*
*---------------------------------------------------------------------*/
-void hostDataXferRestart(PSCCB currSCCB)
+static void FPT_hostDataXferRestart(PSCCB currSCCB)
{
ULONG data_count;
UINT sg_index;
-#if defined(COMPILER_16_BIT) && !defined(DOS)
- ULONG far *sg_ptr;
-#else
ULONG *sg_ptr;
-#endif
if (currSCCB->Sccb_XferState & F_SG_XFER) {
@@ -9322,11 +6030,7 @@ void hostDataXferRestart(PSCCB currSCCB)
sg_index = 0xffff; /*Index by long words into sg list. */
data_count = 0; /*Running count of SG xfer counts. */
-#if defined(COMPILER_16_BIT) && !defined(DOS)
- sg_ptr = (ULONG far *)currSCCB->DataPointer;
-#else
sg_ptr = (ULONG *)currSCCB->DataPointer;
-#endif
while (data_count < currSCCB->Sccb_ATC) {
@@ -9351,78 +6055,28 @@ void hostDataXferRestart(PSCCB currSCCB)
currSCCB->Sccb_XferCnt = currSCCB->DataLength - currSCCB->Sccb_ATC;
}
}
-#ident "$Id: scam.c 1.17 1997/03/20 23:49:37 mohan Exp $"
-/*----------------------------------------------------------------------
- *
- *
- * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved
- *
- * This file is available under both the GNU General Public License
- * and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- * $Workfile: scam.c $
- *
- * Description: Functions relating to handling of the SCAM selection
- * and the determination of the SCSI IDs to be assigned
- * to all perspective SCSI targets.
- *
- * $Date: 1997/03/20 23:49:37 $
- *
- * $Revision: 1.17 $
- *
- *----------------------------------------------------------------------*/
-/*#include <globals.h>*/
-
-#if (FW_TYPE==_UCB_MGR_)
- /*#include <budi.h>*/
-#endif
-/*#include <sccbmgr.h>*/
-/*#include <blx30.h>*/
-/*#include <target.h>*/
-/*#include <scsi2.h>*/
-/*#include <eeprom.h>*/
-/*#include <harpoon.h>*/
-
-
-/*
-extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR];
-extern SCCBCARD BL_Card[MAX_CARDS];
-extern SCCBSCAM_INFO scamInfo[MAX_SCSI_TAR];
-extern NVRAMINFO nvRamInfo[MAX_MB_CARDS];
-#if defined(DOS) || defined(OS2)
-extern UCHAR temp_id_string[ID_STRING_LENGTH];
-#endif
-extern UCHAR scamHAString[];
-*/
/*---------------------------------------------------------------------
*
- * Function: scini
+ * Function: FPT_scini
*
* Description: Setup all data structures necessary for SCAM selection.
*
*---------------------------------------------------------------------*/
-void scini(UCHAR p_card, UCHAR p_our_id, UCHAR p_power_up)
+static void FPT_scini(UCHAR p_card, UCHAR p_our_id, UCHAR p_power_up)
{
-#if defined(SCAM_LEV_2)
UCHAR loser,assigned_id;
-#endif
-#if defined(DOS)
-
- USHORT p_port;
-#else
ULONG p_port;
-#endif
UCHAR i,k,ScamFlg ;
PSCCBcard currCard;
PNVRamInfo pCurrNvRam;
- currCard = &BL_Card[p_card];
+ currCard = &FPT_BL_Card[p_card];
p_port = currCard->ioPort;
pCurrNvRam = currCard->pNvRamInfo;
@@ -9432,72 +6086,68 @@ void scini(UCHAR p_card, UCHAR p_our_id, UCHAR p_power_up)
i = pCurrNvRam->niSysConf;
}
else{
- ScamFlg = (UCHAR) utilEERead(p_port, SCAM_CONFIG/2);
- i = (UCHAR)(utilEERead(p_port, (SYSTEM_CONFIG/2)));
+ ScamFlg = (UCHAR) FPT_utilEERead(p_port, SCAM_CONFIG/2);
+ i = (UCHAR)(FPT_utilEERead(p_port, (SYSTEM_CONFIG/2)));
}
if(!(i & 0x02)) /* check if reset bus in AutoSCSI parameter set */
return;
- inisci(p_card,p_port, p_our_id);
+ FPT_inisci(p_card,p_port, p_our_id);
/* Force to wait 1 sec after SCSI bus reset. Some SCAM device FW
too slow to return to SCAM selection */
/* if (p_power_up)
- Wait1Second(p_port);
+ FPT_Wait1Second(p_port);
else
- Wait(p_port, TO_250ms); */
-
- Wait1Second(p_port);
+ FPT_Wait(p_port, TO_250ms); */
-#if defined(SCAM_LEV_2)
+ FPT_Wait1Second(p_port);
if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2))
{
- while (!(scarb(p_port,INIT_SELTD))) {}
+ while (!(FPT_scarb(p_port,INIT_SELTD))) {}
- scsel(p_port);
+ FPT_scsel(p_port);
do {
- scxferc(p_port,SYNC_PTRN);
- scxferc(p_port,DOM_MSTR);
- loser = scsendi(p_port,&scamInfo[p_our_id].id_string[0]);
+ FPT_scxferc(p_port,SYNC_PTRN);
+ FPT_scxferc(p_port,DOM_MSTR);
+ loser = FPT_scsendi(p_port,&FPT_scamInfo[p_our_id].id_string[0]);
} while ( loser == 0xFF );
- scbusf(p_port);
+ FPT_scbusf(p_port);
if ((p_power_up) && (!loser))
{
- sresb(p_port,p_card);
- Wait(p_port, TO_250ms);
+ FPT_sresb(p_port,p_card);
+ FPT_Wait(p_port, TO_250ms);
- while (!(scarb(p_port,INIT_SELTD))) {}
+ while (!(FPT_scarb(p_port,INIT_SELTD))) {}
- scsel(p_port);
+ FPT_scsel(p_port);
do {
- scxferc(p_port, SYNC_PTRN);
- scxferc(p_port, DOM_MSTR);
- loser = scsendi(p_port,&scamInfo[p_our_id].
+ FPT_scxferc(p_port, SYNC_PTRN);
+ FPT_scxferc(p_port, DOM_MSTR);
+ loser = FPT_scsendi(p_port,&FPT_scamInfo[p_our_id].
id_string[0]);
} while ( loser == 0xFF );
- scbusf(p_port);
+ FPT_scbusf(p_port);
}
}
else
{
- loser = FALSE;
+ loser = 0;
}
if (!loser)
{
-#endif /* SCAM_LEV_2 */
-
- scamInfo[p_our_id].state = ID_ASSIGNED;
+ FPT_scamInfo[p_our_id].state = ID_ASSIGNED;
if (ScamFlg & SCAM_ENABLED)
@@ -9505,18 +6155,18 @@ void scini(UCHAR p_card, UCHAR p_our_id, UCHAR p_power_up)
for (i=0; i < MAX_SCSI_TAR; i++)
{
- if ((scamInfo[i].state == ID_UNASSIGNED) ||
- (scamInfo[i].state == ID_UNUSED))
+ if ((FPT_scamInfo[i].state == ID_UNASSIGNED) ||
+ (FPT_scamInfo[i].state == ID_UNUSED))
{
- if (scsell(p_port,i))
+ if (FPT_scsell(p_port,i))
{
- scamInfo[i].state = LEGACY;
- if ((scamInfo[i].id_string[0] != 0xFF) ||
- (scamInfo[i].id_string[1] != 0xFA))
+ FPT_scamInfo[i].state = LEGACY;
+ if ((FPT_scamInfo[i].id_string[0] != 0xFF) ||
+ (FPT_scamInfo[i].id_string[1] != 0xFA))
{
- scamInfo[i].id_string[0] = 0xFF;
- scamInfo[i].id_string[1] = 0xFA;
+ FPT_scamInfo[i].id_string[0] = 0xFF;
+ FPT_scamInfo[i].id_string[1] = 0xFA;
if(pCurrNvRam == NULL)
currCard->globalFlags |= F_UPDATE_EEPROM;
}
@@ -9524,45 +6174,43 @@ void scini(UCHAR p_card, UCHAR p_our_id, UCHAR p_power_up)
}
}
- sresb(p_port,p_card);
- Wait1Second(p_port);
- while (!(scarb(p_port,INIT_SELTD))) {}
- scsel(p_port);
- scasid(p_card, p_port);
+ FPT_sresb(p_port,p_card);
+ FPT_Wait1Second(p_port);
+ while (!(FPT_scarb(p_port,INIT_SELTD))) {}
+ FPT_scsel(p_port);
+ FPT_scasid(p_card, p_port);
}
-#if defined(SCAM_LEV_2)
-
}
else if ((loser) && (ScamFlg & SCAM_ENABLED))
{
- scamInfo[p_our_id].id_string[0] = SLV_TYPE_CODE0;
- assigned_id = FALSE;
- scwtsel(p_port);
+ FPT_scamInfo[p_our_id].id_string[0] = SLV_TYPE_CODE0;
+ assigned_id = 0;
+ FPT_scwtsel(p_port);
do {
- while (scxferc(p_port,0x00) != SYNC_PTRN) {}
+ while (FPT_scxferc(p_port,0x00) != SYNC_PTRN) {}
- i = scxferc(p_port,0x00);
+ i = FPT_scxferc(p_port,0x00);
if (i == ASSIGN_ID)
{
- if (!(scsendi(p_port,&scamInfo[p_our_id].id_string[0])))
+ if (!(FPT_scsendi(p_port,&FPT_scamInfo[p_our_id].id_string[0])))
{
- i = scxferc(p_port,0x00);
- if (scvalq(i))
+ i = FPT_scxferc(p_port,0x00);
+ if (FPT_scvalq(i))
{
- k = scxferc(p_port,0x00);
+ k = FPT_scxferc(p_port,0x00);
- if (scvalq(k))
+ if (FPT_scvalq(k))
{
currCard->ourId =
((UCHAR)(i<<3)+(k & (UCHAR)7)) & (UCHAR) 0x3F;
- inisci(p_card, p_port, p_our_id);
- scamInfo[currCard->ourId].state = ID_ASSIGNED;
- scamInfo[currCard->ourId].id_string[0]
+ FPT_inisci(p_card, p_port, p_our_id);
+ FPT_scamInfo[currCard->ourId].state = ID_ASSIGNED;
+ FPT_scamInfo[currCard->ourId].id_string[0]
= SLV_TYPE_CODE0;
- assigned_id = TRUE;
+ assigned_id = 1;
}
}
}
@@ -9570,43 +6218,31 @@ void scini(UCHAR p_card, UCHAR p_our_id, UCHAR p_power_up)
else if (i == SET_P_FLAG)
{
- if (!(scsendi(p_port,
- &scamInfo[p_our_id].id_string[0])))
- scamInfo[p_our_id].id_string[0] |= 0x80;
+ if (!(FPT_scsendi(p_port,
+ &FPT_scamInfo[p_our_id].id_string[0])))
+ FPT_scamInfo[p_our_id].id_string[0] |= 0x80;
}
}while (!assigned_id);
- while (scxferc(p_port,0x00) != CFG_CMPLT) {}
+ while (FPT_scxferc(p_port,0x00) != CFG_CMPLT) {}
}
-#endif /* SCAM_LEV_2 */
if (ScamFlg & SCAM_ENABLED)
{
- scbusf(p_port);
+ FPT_scbusf(p_port);
if (currCard->globalFlags & F_UPDATE_EEPROM)
{
- scsavdi(p_card, p_port);
+ FPT_scsavdi(p_card, p_port);
currCard->globalFlags &= ~F_UPDATE_EEPROM;
}
}
-#if defined(DOS)
- for (i=0; i < MAX_SCSI_TAR; i++)
- {
- if (((ScamFlg & SCAM_ENABLED) && (scamInfo[i].state == LEGACY))
- || (i != p_our_id))
- {
- scsellDOS(p_port,i);
- }
- }
-#endif
-
/*
for (i=0,k=0; i < MAX_SCSI_TAR; i++)
{
- if ((scamInfo[i].state == ID_ASSIGNED) ||
- (scamInfo[i].state == LEGACY))
+ if ((FPT_scamInfo[i].state == ID_ASSIGNED) ||
+ (FPT_scamInfo[i].state == LEGACY))
k++;
}
@@ -9620,17 +6256,13 @@ void scini(UCHAR p_card, UCHAR p_our_id, UCHAR p_power_up)
/*---------------------------------------------------------------------
*
- * Function: scarb
+ * Function: FPT_scarb
*
* Description: Gain control of the bus and wait SCAM select time (250ms)
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-int scarb(USHORT p_port, UCHAR p_sel_type)
-#else
-int scarb(ULONG p_port, UCHAR p_sel_type)
-#endif
+static int FPT_scarb(ULONG p_port, UCHAR p_sel_type)
{
if (p_sel_type == INIT_SELTD)
{
@@ -9639,10 +6271,10 @@ int scarb(ULONG p_port, UCHAR p_sel_type)
if (RD_HARPOON(p_port+hp_scsisig) & SCSI_SEL)
- return(FALSE);
+ return(0);
if (RD_HARPOON(p_port+hp_scsidata_0) != 00)
- return(FALSE);
+ return(0);
WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) | SCSI_BSY));
@@ -9650,7 +6282,7 @@ int scarb(ULONG p_port, UCHAR p_sel_type)
WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) &
~SCSI_BSY));
- return(FALSE);
+ return(0);
}
@@ -9660,7 +6292,7 @@ int scarb(ULONG p_port, UCHAR p_sel_type)
WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) &
~(SCSI_BSY | SCSI_SEL)));
- return(FALSE);
+ return(0);
}
}
@@ -9669,9 +6301,7 @@ int scarb(ULONG p_port, UCHAR p_sel_type)
& ~ACTdeassert));
WR_HARPOON(p_port+hp_scsireset, SCAM_EN);
WR_HARPOON(p_port+hp_scsidata_0, 0x00);
-#if defined(WIDE_SCSI)
WR_HARPOON(p_port+hp_scsidata_1, 0x00);
-#endif
WR_HARPOON(p_port+hp_portctrl_0, SCSI_BUS_EN);
WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) | SCSI_MSG));
@@ -9679,25 +6309,21 @@ int scarb(ULONG p_port, UCHAR p_sel_type)
WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig)
& ~SCSI_BSY));
- Wait(p_port,TO_250ms);
+ FPT_Wait(p_port,TO_250ms);
- return(TRUE);
+ return(1);
}
/*---------------------------------------------------------------------
*
- * Function: scbusf
+ * Function: FPT_scbusf
*
* Description: Release the SCSI bus and disable SCAM selection.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void scbusf(USHORT p_port)
-#else
-void scbusf(ULONG p_port)
-#endif
+static void FPT_scbusf(ULONG p_port)
{
WR_HARPOON(p_port+hp_page_ctrl,
(RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE));
@@ -9717,11 +6343,7 @@ void scbusf(ULONG p_port)
WR_HARPOON(p_port+hp_clkctrl_0, (RD_HARPOON(p_port+hp_clkctrl_0)
| ACTdeassert));
-#if defined(SCAM_LEV_2)
WRW_HARPOON((p_port+hp_intstat), (BUS_FREE | AUTO_INT | SCAM_SEL));
-#else
- WRW_HARPOON((p_port+hp_intstat), (BUS_FREE | AUTO_INT));
-#endif
WR_HARPOON(p_port+hp_page_ctrl,
(RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE));
@@ -9731,35 +6353,24 @@ void scbusf(ULONG p_port)
/*---------------------------------------------------------------------
*
- * Function: scasid
+ * Function: FPT_scasid
*
* Description: Assign an ID to all the SCAM devices.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void scasid(UCHAR p_card, USHORT p_port)
-#else
-void scasid(UCHAR p_card, ULONG p_port)
-#endif
+static void FPT_scasid(UCHAR p_card, ULONG p_port)
{
-#if defined(DOS) || defined(OS2)
- /* Use external defined in global space area, instead of Stack
- space. WIN/95 DOS doesnot work TINY mode. The OS doesnot intialize
- SS equal to DS. Thus the array allocated on stack doesnot get
- access correctly */
-#else
UCHAR temp_id_string[ID_STRING_LENGTH];
-#endif
UCHAR i,k,scam_id;
UCHAR crcBytes[3];
PNVRamInfo pCurrNvRam;
ushort_ptr pCrcBytes;
- pCurrNvRam = BL_Card[p_card].pNvRamInfo;
+ pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
- i=FALSE;
+ i=0;
while (!i)
{
@@ -9769,36 +6380,36 @@ void scasid(UCHAR p_card, ULONG p_port)
temp_id_string[k] = (UCHAR) 0x00;
}
- scxferc(p_port,SYNC_PTRN);
- scxferc(p_port,ASSIGN_ID);
+ FPT_scxferc(p_port,SYNC_PTRN);
+ FPT_scxferc(p_port,ASSIGN_ID);
- if (!(sciso(p_port,&temp_id_string[0])))
+ if (!(FPT_sciso(p_port,&temp_id_string[0])))
{
if(pCurrNvRam){
pCrcBytes = (ushort_ptr)&crcBytes[0];
- *pCrcBytes = CalcCrc16(&temp_id_string[0]);
- crcBytes[2] = CalcLrc(&temp_id_string[0]);
+ *pCrcBytes = FPT_CalcCrc16(&temp_id_string[0]);
+ crcBytes[2] = FPT_CalcLrc(&temp_id_string[0]);
temp_id_string[1] = crcBytes[2];
temp_id_string[2] = crcBytes[0];
temp_id_string[3] = crcBytes[1];
for(k = 4; k < ID_STRING_LENGTH; k++)
temp_id_string[k] = (UCHAR) 0x00;
}
- i = scmachid(p_card,temp_id_string);
+ i = FPT_scmachid(p_card,temp_id_string);
if (i == CLR_PRIORITY)
{
- scxferc(p_port,MISC_CODE);
- scxferc(p_port,CLR_P_FLAG);
- i = FALSE; /*Not the last ID yet. */
+ FPT_scxferc(p_port,MISC_CODE);
+ FPT_scxferc(p_port,CLR_P_FLAG);
+ i = 0; /*Not the last ID yet. */
}
else if (i != NO_ID_AVAIL)
{
if (i < 8 )
- scxferc(p_port,ID_0_7);
+ FPT_scxferc(p_port,ID_0_7);
else
- scxferc(p_port,ID_8_F);
+ FPT_scxferc(p_port,ID_8_F);
scam_id = (i & (UCHAR) 0x07);
@@ -9807,21 +6418,21 @@ void scasid(UCHAR p_card, ULONG p_port)
if (!( k & i ))
scam_id += 0x08; /*Count number of zeros in DB0-3. */
- scxferc(p_port,scam_id);
+ FPT_scxferc(p_port,scam_id);
- i = FALSE; /*Not the last ID yet. */
+ i = 0; /*Not the last ID yet. */
}
}
else
{
- i = TRUE;
+ i = 1;
}
} /*End while */
- scxferc(p_port,SYNC_PTRN);
- scxferc(p_port,CFG_CMPLT);
+ FPT_scxferc(p_port,SYNC_PTRN);
+ FPT_scxferc(p_port,CFG_CMPLT);
}
@@ -9830,21 +6441,17 @@ void scasid(UCHAR p_card, ULONG p_port)
/*---------------------------------------------------------------------
*
- * Function: scsel
+ * Function: FPT_scsel
*
* Description: Select all the SCAM devices.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void scsel(USHORT p_port)
-#else
-void scsel(ULONG p_port)
-#endif
+static void FPT_scsel(ULONG p_port)
{
WR_HARPOON(p_port+hp_scsisig, SCSI_SEL);
- scwiros(p_port, SCSI_MSG);
+ FPT_scwiros(p_port, SCSI_MSG);
WR_HARPOON(p_port+hp_scsisig, (SCSI_SEL | SCSI_BSY));
@@ -9855,11 +6462,11 @@ void scsel(ULONG p_port)
WR_HARPOON(p_port+hp_scsisig, (SCSI_BSY | SCSI_IOBIT | SCSI_CD));
- scwiros(p_port, SCSI_SEL);
+ FPT_scwiros(p_port, SCSI_SEL);
WR_HARPOON(p_port+hp_scsidata_0, (UCHAR)(RD_HARPOON(p_port+hp_scsidata_0) &
~(UCHAR)BIT(6)));
- scwirod(p_port, BIT(6));
+ FPT_scwirod(p_port, BIT(6));
WR_HARPOON(p_port+hp_scsisig, (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
}
@@ -9868,17 +6475,13 @@ void scsel(ULONG p_port)
/*---------------------------------------------------------------------
*
- * Function: scxferc
+ * Function: FPT_scxferc
*
* Description: Handshake the p_data (DB4-0) across the bus.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-UCHAR scxferc(USHORT p_port, UCHAR p_data)
-#else
-UCHAR scxferc(ULONG p_port, UCHAR p_data)
-#endif
+static UCHAR FPT_scxferc(ULONG p_port, UCHAR p_data)
{
UCHAR curr_data, ret_data;
@@ -9890,7 +6493,7 @@ UCHAR scxferc(ULONG p_port, UCHAR p_data)
WR_HARPOON(p_port+hp_scsidata_0, curr_data);
- scwirod(p_port,BIT(7)); /*Wait for DB7 to be released. */
+ FPT_scwirod(p_port,BIT(7)); /*Wait for DB7 to be released. */
while (!(RD_HARPOON(p_port+hp_scsidata_0) & BIT(5)));
ret_data = (RD_HARPOON(p_port+hp_scsidata_0) & (UCHAR) 0x1F);
@@ -9903,7 +6506,7 @@ UCHAR scxferc(ULONG p_port, UCHAR p_data)
WR_HARPOON(p_port+hp_scsidata_0, curr_data);
- scwirod(p_port,BIT(5)); /*Wait for DB5 to be released. */
+ FPT_scwirod(p_port,BIT(5)); /*Wait for DB5 to be released. */
curr_data &= ~(BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0)); /*Release data bits */
curr_data |= BIT(7);
@@ -9914,7 +6517,7 @@ UCHAR scxferc(ULONG p_port, UCHAR p_data)
WR_HARPOON(p_port+hp_scsidata_0, curr_data);
- scwirod(p_port,BIT(6)); /*Wait for DB6 to be released. */
+ FPT_scwirod(p_port,BIT(6)); /*Wait for DB6 to be released. */
return(ret_data);
}
@@ -9922,39 +6525,35 @@ UCHAR scxferc(ULONG p_port, UCHAR p_data)
/*---------------------------------------------------------------------
*
- * Function: scsendi
+ * Function: FPT_scsendi
*
* Description: Transfer our Identification string to determine if we
* will be the dominant master.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-UCHAR scsendi(USHORT p_port, UCHAR p_id_string[])
-#else
-UCHAR scsendi(ULONG p_port, UCHAR p_id_string[])
-#endif
+static UCHAR FPT_scsendi(ULONG p_port, UCHAR p_id_string[])
{
UCHAR ret_data,byte_cnt,bit_cnt,defer;
- defer = FALSE;
+ defer = 0;
for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
for (bit_cnt = 0x80; bit_cnt != 0 ; bit_cnt >>= 1) {
if (defer)
- ret_data = scxferc(p_port,00);
+ ret_data = FPT_scxferc(p_port,00);
else if (p_id_string[byte_cnt] & bit_cnt)
- ret_data = scxferc(p_port,02);
+ ret_data = FPT_scxferc(p_port,02);
else {
- ret_data = scxferc(p_port,01);
+ ret_data = FPT_scxferc(p_port,01);
if (ret_data & 02)
- defer = TRUE;
+ defer = 1;
}
if ((ret_data & 0x1C) == 0x10)
@@ -9980,17 +6579,13 @@ UCHAR scsendi(ULONG p_port, UCHAR p_id_string[])
/*---------------------------------------------------------------------
*
- * Function: sciso
+ * Function: FPT_sciso
*
* Description: Transfer the Identification string.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-UCHAR sciso(USHORT p_port, UCHAR p_id_string[])
-#else
-UCHAR sciso(ULONG p_port, UCHAR p_id_string[])
-#endif
+static UCHAR FPT_sciso(ULONG p_port, UCHAR p_id_string[])
{
UCHAR ret_data,the_data,byte_cnt,bit_cnt;
@@ -10000,7 +6595,7 @@ UCHAR sciso(ULONG p_port, UCHAR p_id_string[])
for (bit_cnt = 0; bit_cnt < 8; bit_cnt++) {
- ret_data = scxferc(p_port,0);
+ ret_data = FPT_scxferc(p_port,0);
if (ret_data & 0xFC)
return(0xFF);
@@ -10020,8 +6615,8 @@ UCHAR sciso(ULONG p_port, UCHAR p_id_string[])
{
byte_cnt = 0;
bit_cnt = 0;
- scxferc(p_port, SYNC_PTRN);
- scxferc(p_port, ASSIGN_ID);
+ FPT_scxferc(p_port, SYNC_PTRN);
+ FPT_scxferc(p_port, ASSIGN_ID);
continue;
}
*/
@@ -10044,18 +6639,14 @@ UCHAR sciso(ULONG p_port, UCHAR p_id_string[])
/*---------------------------------------------------------------------
*
- * Function: scwirod
+ * Function: FPT_scwirod
*
* Description: Sample the SCSI data bus making sure the signal has been
* deasserted for the correct number of consecutive samples.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void scwirod(USHORT p_port, UCHAR p_data_bit)
-#else
-void scwirod(ULONG p_port, UCHAR p_data_bit)
-#endif
+static void FPT_scwirod(ULONG p_port, UCHAR p_data_bit)
{
UCHAR i;
@@ -10077,18 +6668,14 @@ void scwirod(ULONG p_port, UCHAR p_data_bit)
/*---------------------------------------------------------------------
*
- * Function: scwiros
+ * Function: FPT_scwiros
*
* Description: Sample the SCSI Signal lines making sure the signal has been
* deasserted for the correct number of consecutive samples.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void scwiros(USHORT p_port, UCHAR p_data_bit)
-#else
-void scwiros(ULONG p_port, UCHAR p_data_bit)
-#endif
+static void FPT_scwiros(ULONG p_port, UCHAR p_data_bit)
{
UCHAR i;
@@ -10109,13 +6696,13 @@ void scwiros(ULONG p_port, UCHAR p_data_bit)
/*---------------------------------------------------------------------
*
- * Function: scvalq
+ * Function: FPT_scvalq
*
* Description: Make sure we received a valid data byte.
*
*---------------------------------------------------------------------*/
-UCHAR scvalq(UCHAR p_quintet)
+static UCHAR FPT_scvalq(UCHAR p_quintet)
{
UCHAR count;
@@ -10125,16 +6712,16 @@ UCHAR scvalq(UCHAR p_quintet)
}
if (p_quintet & 0x18)
- return(FALSE);
+ return(0);
else
- return(TRUE);
+ return(1);
}
/*---------------------------------------------------------------------
*
- * Function: scsell
+ * Function: FPT_scsell
*
* Description: Select the specified device ID using a selection timeout
* less than 4ms. If somebody responds then it is a legacy
@@ -10142,17 +6729,9 @@ UCHAR scvalq(UCHAR p_quintet)
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-UCHAR scsell(USHORT p_port, UCHAR targ_id)
-#else
-UCHAR scsell(ULONG p_port, UCHAR targ_id)
-#endif
+static UCHAR FPT_scsell(ULONG p_port, UCHAR targ_id)
{
-#if defined(DOS)
- USHORT i;
-#else
ULONG i;
-#endif
WR_HARPOON(p_port+hp_page_ctrl,
(RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE));
@@ -10182,7 +6761,7 @@ UCHAR scsell(ULONG p_port, UCHAR targ_id)
(RESET | PROG_HLT | TIMEOUT | AUTO_INT))) {}
if (RDW_HARPOON((p_port+hp_intstat)) & RESET)
- Wait(p_port, TO_250ms);
+ FPT_Wait(p_port, TO_250ms);
DISABLE_AUTO(p_port);
@@ -10199,7 +6778,7 @@ UCHAR scsell(ULONG p_port, UCHAR targ_id)
WR_HARPOON(p_port+hp_page_ctrl,
(RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE));
- return(FALSE); /*No legacy device */
+ return(0); /*No legacy device */
}
else {
@@ -10217,108 +6796,19 @@ UCHAR scsell(ULONG p_port, UCHAR targ_id)
WR_HARPOON(p_port+hp_page_ctrl,
(RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE));
- return(TRUE); /*Found one of them oldies! */
+ return(1); /*Found one of them oldies! */
}
}
-#if defined(DOS)
/*---------------------------------------------------------------------
*
- * Function: scsell for DOS
- *
- * Description: Select the specified device ID using a selection timeout
- * less than 2ms. This was specially required to solve
- * the problem with Plextor 12X CD-ROM drive. This drive
- * was responding the Selection at the end of 4ms and
- * hanging the system.
- *
- *---------------------------------------------------------------------*/
-
-UCHAR scsellDOS(USHORT p_port, UCHAR targ_id)
-{
- USHORT i;
-
- WR_HARPOON(p_port+hp_page_ctrl,
- (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE));
-
- ARAM_ACCESS(p_port);
-
- WR_HARPOON(p_port+hp_addstat,(RD_HARPOON(p_port+hp_addstat) | SCAM_TIMER));
- WR_HARPOON(p_port+hp_seltimeout,TO_2ms);
-
-
- for (i = p_port+CMD_STRT; i < p_port+CMD_STRT+12; i+=2) {
- WRW_HARPOON(i, (MPM_OP+ACOMMAND));
- }
- WRW_HARPOON(i, (BRH_OP+ALWAYS+ NP));
-
- WRW_HARPOON((p_port+hp_intstat),
- (RESET | TIMEOUT | SEL | BUS_FREE | AUTO_INT));
-
- WR_HARPOON(p_port+hp_select_id, targ_id);
-
- WR_HARPOON(p_port+hp_portctrl_0, SCSI_PORT);
- WR_HARPOON(p_port+hp_autostart_3, (SELECT | CMD_ONLY_STRT));
- WR_HARPOON(p_port+hp_scsictrl_0, (SEL_TAR | ENA_RESEL));
-
-
- while (!(RDW_HARPOON((p_port+hp_intstat)) &
- (RESET | PROG_HLT | TIMEOUT | AUTO_INT))) {}
-
- if (RDW_HARPOON((p_port+hp_intstat)) & RESET)
- Wait(p_port, TO_250ms);
-
- DISABLE_AUTO(p_port);
-
- WR_HARPOON(p_port+hp_addstat,(RD_HARPOON(p_port+hp_addstat) & ~SCAM_TIMER));
- WR_HARPOON(p_port+hp_seltimeout,TO_290ms);
-
- SGRAM_ACCESS(p_port);
-
- if (RDW_HARPOON((p_port+hp_intstat)) & (RESET | TIMEOUT) ) {
-
- WRW_HARPOON((p_port+hp_intstat),
- (RESET | TIMEOUT | SEL | BUS_FREE | PHASE));
-
- WR_HARPOON(p_port+hp_page_ctrl,
- (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE));
-
- return(FALSE); /*No legacy device */
- }
-
- else {
-
- while(!(RDW_HARPOON((p_port+hp_intstat)) & BUS_FREE)) {
- if (RD_HARPOON(p_port+hp_scsisig) & SCSI_REQ)
- {
- WR_HARPOON(p_port+hp_scsisig, (SCSI_ACK + S_ILL_PH));
- ACCEPT_MSG(p_port);
- }
- }
-
- WRW_HARPOON((p_port+hp_intstat), CLR_ALL_INT_1);
-
- WR_HARPOON(p_port+hp_page_ctrl,
- (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE));
-
- return(TRUE); /*Found one of them oldies! */
- }
-}
-#endif /* DOS */
-
-/*---------------------------------------------------------------------
- *
- * Function: scwtsel
+ * Function: FPT_scwtsel
*
* Description: Wait to be selected by another SCAM initiator.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void scwtsel(USHORT p_port)
-#else
-void scwtsel(ULONG p_port)
-#endif
+static void FPT_scwtsel(ULONG p_port)
{
while(!(RDW_HARPOON((p_port+hp_intstat)) & SCAM_SEL)) {}
}
@@ -10326,23 +6816,19 @@ void scwtsel(ULONG p_port)
/*---------------------------------------------------------------------
*
- * Function: inisci
+ * Function: FPT_inisci
*
* Description: Setup the data Structure with the info from the EEPROM.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void inisci(UCHAR p_card, USHORT p_port, UCHAR p_our_id)
-#else
-void inisci(UCHAR p_card, ULONG p_port, UCHAR p_our_id)
-#endif
+static void FPT_inisci(UCHAR p_card, ULONG p_port, UCHAR p_our_id)
{
UCHAR i,k,max_id;
USHORT ee_data;
PNVRamInfo pCurrNvRam;
- pCurrNvRam = BL_Card[p_card].pNvRamInfo;
+ pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
if (RD_HARPOON(p_port+hp_page_ctrl) & NARROW_SCSI_CARD)
max_id = 0x08;
@@ -10354,14 +6840,14 @@ void inisci(UCHAR p_card, ULONG p_port, UCHAR p_our_id)
for(i = 0; i < max_id; i++){
for(k = 0; k < 4; k++)
- scamInfo[i].id_string[k] = pCurrNvRam->niScamTbl[i][k];
+ FPT_scamInfo[i].id_string[k] = pCurrNvRam->niScamTbl[i][k];
for(k = 4; k < ID_STRING_LENGTH; k++)
- scamInfo[i].id_string[k] = (UCHAR) 0x00;
+ FPT_scamInfo[i].id_string[k] = (UCHAR) 0x00;
- if(scamInfo[i].id_string[0] == 0x00)
- scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */
+ if(FPT_scamInfo[i].id_string[0] == 0x00)
+ FPT_scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */
else
- scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */
+ FPT_scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */
}
}else {
@@ -10369,38 +6855,38 @@ void inisci(UCHAR p_card, ULONG p_port, UCHAR p_our_id)
{
for (k=0; k < ID_STRING_LENGTH; k+=2)
{
- ee_data = utilEERead(p_port, (USHORT)((EE_SCAMBASE/2) +
+ ee_data = FPT_utilEERead(p_port, (USHORT)((EE_SCAMBASE/2) +
(USHORT) (i*((USHORT)ID_STRING_LENGTH/2)) + (USHORT)(k/2)));
- scamInfo[i].id_string[k] = (UCHAR) ee_data;
+ FPT_scamInfo[i].id_string[k] = (UCHAR) ee_data;
ee_data >>= 8;
- scamInfo[i].id_string[k+1] = (UCHAR) ee_data;
+ FPT_scamInfo[i].id_string[k+1] = (UCHAR) ee_data;
}
- if ((scamInfo[i].id_string[0] == 0x00) ||
- (scamInfo[i].id_string[0] == 0xFF))
+ if ((FPT_scamInfo[i].id_string[0] == 0x00) ||
+ (FPT_scamInfo[i].id_string[0] == 0xFF))
- scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */
+ FPT_scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */
else
- scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */
+ FPT_scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */
}
}
for(k = 0; k < ID_STRING_LENGTH; k++)
- scamInfo[p_our_id].id_string[k] = scamHAString[k];
+ FPT_scamInfo[p_our_id].id_string[k] = FPT_scamHAString[k];
}
/*---------------------------------------------------------------------
*
- * Function: scmachid
+ * Function: FPT_scmachid
*
* Description: Match the Device ID string with our values stored in
* the EEPROM.
*
*---------------------------------------------------------------------*/
-UCHAR scmachid(UCHAR p_card, UCHAR p_id_string[])
+static UCHAR FPT_scmachid(UCHAR p_card, UCHAR p_id_string[])
{
UCHAR i,k,match;
@@ -10408,28 +6894,20 @@ UCHAR scmachid(UCHAR p_card, UCHAR p_id_string[])
for (i=0; i < MAX_SCSI_TAR; i++) {
-#if !defined(SCAM_LEV_2)
- if (scamInfo[i].state == ID_UNASSIGNED)
- {
-#endif
- match = TRUE;
+ match = 1;
for (k=0; k < ID_STRING_LENGTH; k++)
{
- if (p_id_string[k] != scamInfo[i].id_string[k])
- match = FALSE;
+ if (p_id_string[k] != FPT_scamInfo[i].id_string[k])
+ match = 0;
}
if (match)
{
- scamInfo[i].state = ID_ASSIGNED;
+ FPT_scamInfo[i].state = ID_ASSIGNED;
return(i);
}
-#if !defined(SCAM_LEV_2)
- }
-#endif
-
}
@@ -10448,17 +6926,17 @@ UCHAR scmachid(UCHAR p_card, UCHAR p_id_string[])
{
i--;
- if (scamInfo[match].state == ID_UNUSED)
+ if (FPT_scamInfo[match].state == ID_UNUSED)
{
for (k=0; k < ID_STRING_LENGTH; k++)
{
- scamInfo[match].id_string[k] = p_id_string[k];
+ FPT_scamInfo[match].id_string[k] = p_id_string[k];
}
- scamInfo[match].state = ID_ASSIGNED;
+ FPT_scamInfo[match].state = ID_ASSIGNED;
- if(BL_Card[p_card].pNvRamInfo == NULL)
- BL_Card[p_card].globalFlags |= F_UPDATE_EEPROM;
+ if(FPT_BL_Card[p_card].pNvRamInfo == NULL)
+ FPT_BL_Card[p_card].globalFlags |= F_UPDATE_EEPROM;
return(match);
}
@@ -10498,17 +6976,17 @@ UCHAR scmachid(UCHAR p_card, UCHAR p_id_string[])
i--;
- if (scamInfo[match].state == ID_UNASSIGNED)
+ if (FPT_scamInfo[match].state == ID_UNASSIGNED)
{
for (k=0; k < ID_STRING_LENGTH; k++)
{
- scamInfo[match].id_string[k] = p_id_string[k];
+ FPT_scamInfo[match].id_string[k] = p_id_string[k];
}
- scamInfo[match].id_string[0] |= BIT(7);
- scamInfo[match].state = ID_ASSIGNED;
- if(BL_Card[p_card].pNvRamInfo == NULL)
- BL_Card[p_card].globalFlags |= F_UPDATE_EEPROM;
+ FPT_scamInfo[match].id_string[0] |= BIT(7);
+ FPT_scamInfo[match].state = ID_ASSIGNED;
+ if(FPT_BL_Card[p_card].pNvRamInfo == NULL)
+ FPT_BL_Card[p_card].globalFlags |= F_UPDATE_EEPROM;
return(match);
}
@@ -10531,17 +7009,13 @@ UCHAR scmachid(UCHAR p_card, UCHAR p_id_string[])
/*---------------------------------------------------------------------
*
- * Function: scsavdi
+ * Function: FPT_scsavdi
*
* Description: Save off the device SCAM ID strings.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void scsavdi(UCHAR p_card, USHORT p_port)
-#else
-void scsavdi(UCHAR p_card, ULONG p_port)
-#endif
+static void FPT_scsavdi(UCHAR p_card, ULONG p_port)
{
UCHAR i,k,max_id;
USHORT ee_data,sum_data;
@@ -10551,11 +7025,11 @@ void scsavdi(UCHAR p_card, ULONG p_port)
for (i = 1; i < EE_SCAMBASE/2; i++)
{
- sum_data += utilEERead(p_port, i);
+ sum_data += FPT_utilEERead(p_port, i);
}
- utilEEWriteOnOff(p_port,1); /* Enable write access to the EEPROM */
+ FPT_utilEEWriteOnOff(p_port,1); /* Enable write access to the EEPROM */
if (RD_HARPOON(p_port+hp_page_ctrl) & NARROW_SCSI_CARD)
max_id = 0x08;
@@ -10568,64 +7042,29 @@ void scsavdi(UCHAR p_card, ULONG p_port)
for (k=0; k < ID_STRING_LENGTH; k+=2)
{
- ee_data = scamInfo[i].id_string[k+1];
+ ee_data = FPT_scamInfo[i].id_string[k+1];
ee_data <<= 8;
- ee_data |= scamInfo[i].id_string[k];
+ ee_data |= FPT_scamInfo[i].id_string[k];
sum_data += ee_data;
- utilEEWrite(p_port, ee_data, (USHORT)((EE_SCAMBASE/2) +
+ FPT_utilEEWrite(p_port, ee_data, (USHORT)((EE_SCAMBASE/2) +
(USHORT)(i*((USHORT)ID_STRING_LENGTH/2)) + (USHORT)(k/2)));
}
}
- utilEEWrite(p_port, sum_data, EEPROM_CHECK_SUM/2);
- utilEEWriteOnOff(p_port,0); /* Turn off write access */
+ FPT_utilEEWrite(p_port, sum_data, EEPROM_CHECK_SUM/2);
+ FPT_utilEEWriteOnOff(p_port,0); /* Turn off write access */
}
-#ident "$Id: diagnose.c 1.10 1997/06/10 16:51:47 mohan Exp $"
-/*----------------------------------------------------------------------
- *
- *
- * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved
- *
- * This file is available under both the GNU General Public License
- * and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- * $Workfile: diagnose.c $
- *
- * Description: Diagnostic funtions for testing the integrity of
- * the HARPOON.
- *
- * $Date: 1997/06/10 16:51:47 $
- *
- * $Revision: 1.10 $
- *
- *----------------------------------------------------------------------*/
-
-/*#include <globals.h>*/
-
-#if (FW_TYPE==_UCB_MGR_)
- /*#include <budi.h>*/
-#endif
-
-/*#include <sccbmgr.h>*/
-/*#include <blx30.h>*/
-/*#include <target.h>*/
-/*#include <eeprom.h>*/
-/*#include <harpoon.h>*/
/*---------------------------------------------------------------------
*
- * Function: XbowInit
+ * Function: FPT_XbowInit
*
* Description: Setup the Xbow for normal operation.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void XbowInit(USHORT port, UCHAR ScamFlg)
-#else
-void XbowInit(ULONG port, UCHAR ScamFlg)
-#endif
+static void FPT_XbowInit(ULONG port, UCHAR ScamFlg)
{
UCHAR i;
@@ -10647,18 +7086,13 @@ UCHAR i;
WRW_HARPOON((port+hp_intstat), CLR_ALL_INT);
-#if defined(SCAM_LEV_2)
- default_intena = RESET | RSEL | PROG_HLT | TIMEOUT |
+ FPT_default_intena = RESET | RSEL | PROG_HLT | TIMEOUT |
BUS_FREE | XFER_CNT_0 | AUTO_INT;
if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2))
- default_intena |= SCAM_SEL;
+ FPT_default_intena |= SCAM_SEL;
-#else
- default_intena = RESET | RSEL | PROG_HLT | TIMEOUT |
- BUS_FREE | XFER_CNT_0 | AUTO_INT;
-#endif
- WRW_HARPOON((port+hp_intena), default_intena);
+ WRW_HARPOON((port+hp_intena), FPT_default_intena);
WR_HARPOON(port+hp_seltimeout,TO_290ms);
@@ -10667,26 +7101,6 @@ UCHAR i;
if (RD_HARPOON(port+hp_page_ctrl) & NARROW_SCSI_CARD)
WR_HARPOON(port+hp_addstat,SCSI_MODE8);
-#if defined(NO_BIOS_OPTION)
-
- WR_HARPOON(port+hp_synctarg_0,NARROW_SCSI);
- WR_HARPOON(port+hp_synctarg_1,NARROW_SCSI);
- WR_HARPOON(port+hp_synctarg_2,NARROW_SCSI);
- WR_HARPOON(port+hp_synctarg_3,NARROW_SCSI);
- WR_HARPOON(port+hp_synctarg_4,NARROW_SCSI);
- WR_HARPOON(port+hp_synctarg_5,NARROW_SCSI);
- WR_HARPOON(port+hp_synctarg_6,NARROW_SCSI);
- WR_HARPOON(port+hp_synctarg_7,NARROW_SCSI);
- WR_HARPOON(port+hp_synctarg_8,NARROW_SCSI);
- WR_HARPOON(port+hp_synctarg_9,NARROW_SCSI);
- WR_HARPOON(port+hp_synctarg_10,NARROW_SCSI);
- WR_HARPOON(port+hp_synctarg_11,NARROW_SCSI);
- WR_HARPOON(port+hp_synctarg_12,NARROW_SCSI);
- WR_HARPOON(port+hp_synctarg_13,NARROW_SCSI);
- WR_HARPOON(port+hp_synctarg_14,NARROW_SCSI);
- WR_HARPOON(port+hp_synctarg_15,NARROW_SCSI);
-
-#endif
WR_HARPOON(port+hp_page_ctrl, i);
}
@@ -10694,17 +7108,13 @@ UCHAR i;
/*---------------------------------------------------------------------
*
- * Function: BusMasterInit
+ * Function: FPT_BusMasterInit
*
* Description: Initialize the BusMaster for normal operations.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void BusMasterInit(USHORT p_port)
-#else
-void BusMasterInit(ULONG p_port)
-#endif
+static void FPT_BusMasterInit(ULONG p_port)
{
@@ -10719,13 +7129,6 @@ void BusMasterInit(ULONG p_port)
WR_HARPOON(p_port+hp_ee_ctrl, (SCSI_TERM_ENA_H));
-#if defined(NT)
-
- WR_HARPOON(p_port+hp_pci_cmd_cfg, (RD_HARPOON(p_port+hp_pci_cmd_cfg)
- & ~MEM_SPACE_ENA));
-
-#endif
-
RD_HARPOON(p_port+hp_int_status); /*Clear interrupts. */
WR_HARPOON(p_port+hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
WR_HARPOON(p_port+hp_page_ctrl, (RD_HARPOON(p_port+hp_page_ctrl) &
@@ -10735,147 +7138,14 @@ void BusMasterInit(ULONG p_port)
/*---------------------------------------------------------------------
*
- * Function: DiagXbow
- *
- * Description: Test Xbow integrity. Non-zero return indicates an error.
- *
- *---------------------------------------------------------------------*/
-
-#if defined(DOS)
-int DiagXbow(USHORT port)
-#else
-int DiagXbow(ULONG port)
-#endif
-{
- unsigned char fifo_cnt,loop_cnt;
-
- unsigned char fifodata[5];
- fifodata[0] = 0x00;
- fifodata[1] = 0xFF;
- fifodata[2] = 0x55;
- fifodata[3] = 0xAA;
- fifodata[4] = 0x00;
-
-
- WRW_HARPOON((port+hp_intstat), CLR_ALL_INT);
- WRW_HARPOON((port+hp_intena), 0x0000);
-
- WR_HARPOON(port+hp_seltimeout,TO_5ms);
-
- WR_HARPOON(port+hp_portctrl_0,START_TO);
-
-
- for(fifodata[4] = 0x01; fifodata[4] != (UCHAR) 0; fifodata[4] = fifodata[4] << 1) {
-
- WR_HARPOON(port+hp_selfid_0,fifodata[4]);
- WR_HARPOON(port+hp_selfid_1,fifodata[4]);
-
- if ((RD_HARPOON(port+hp_selfid_0) != fifodata[4]) ||
- (RD_HARPOON(port+hp_selfid_1) != fifodata[4]))
- return(1);
- }
-
-
- for(loop_cnt = 0; loop_cnt < 4; loop_cnt++) {
-
- WR_HARPOON(port+hp_portctrl_0,(HOST_PORT | HOST_WRT | START_TO));
-
-
- for (fifo_cnt = 0; fifo_cnt < FIFO_LEN; fifo_cnt++) {
-
- WR_HARPOON(port+hp_fifodata_0, fifodata[loop_cnt]);
- }
-
-
- if (!(RD_HARPOON(port+hp_xferstat) & FIFO_FULL))
- return(1);
-
-
- WR_HARPOON(port+hp_portctrl_0,(HOST_PORT | START_TO));
-
- for (fifo_cnt = 0; fifo_cnt < FIFO_LEN; fifo_cnt++) {
-
- if (RD_HARPOON(port+hp_fifodata_0) != fifodata[loop_cnt])
- return(1);
- }
-
-
- if (!(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY))
- return(1);
- }
-
-
- while(!(RDW_HARPOON((port+hp_intstat)) & TIMEOUT)) {}
-
-
- WR_HARPOON(port+hp_seltimeout,TO_290ms);
-
- WRW_HARPOON((port+hp_intstat), CLR_ALL_INT);
-
- WRW_HARPOON((port+hp_intena), default_intena);
-
- return(0);
-}
-
-
-/*---------------------------------------------------------------------
- *
- * Function: DiagBusMaster
- *
- * Description: Test BusMaster integrity. Non-zero return indicates an
- * error.
- *
- *---------------------------------------------------------------------*/
-
-#if defined(DOS)
-int DiagBusMaster(USHORT port)
-#else
-int DiagBusMaster(ULONG port)
-#endif
-{
- UCHAR testdata;
-
- for(testdata = (UCHAR) 1; testdata != (UCHAR)0; testdata = testdata << 1) {
-
- WR_HARPOON(port+hp_xfer_cnt_lo,testdata);
- WR_HARPOON(port+hp_xfer_cnt_mi,testdata);
- WR_HARPOON(port+hp_xfer_cnt_hi,testdata);
- WR_HARPOON(port+hp_host_addr_lo,testdata);
- WR_HARPOON(port+hp_host_addr_lmi,testdata);
- WR_HARPOON(port+hp_host_addr_hmi,testdata);
- WR_HARPOON(port+hp_host_addr_hi,testdata);
-
- if ((RD_HARPOON(port+hp_xfer_cnt_lo) != testdata) ||
- (RD_HARPOON(port+hp_xfer_cnt_mi) != testdata) ||
- (RD_HARPOON(port+hp_xfer_cnt_hi) != testdata) ||
- (RD_HARPOON(port+hp_host_addr_lo) != testdata) ||
- (RD_HARPOON(port+hp_host_addr_lmi) != testdata) ||
- (RD_HARPOON(port+hp_host_addr_hmi) != testdata) ||
- (RD_HARPOON(port+hp_host_addr_hi) != testdata))
-
- return(1);
- }
- RD_HARPOON(port+hp_int_status); /*Clear interrupts. */
- return(0);
-}
-
-
-
-/*---------------------------------------------------------------------
- *
- * Function: DiagEEPROM
+ * Function: FPT_DiagEEPROM
*
* Description: Verfiy checksum and 'Key' and initialize the EEPROM if
* necessary.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void DiagEEPROM(USHORT p_port)
-#else
-void DiagEEPROM(ULONG p_port)
-#endif
-
+static void FPT_DiagEEPROM(ULONG p_port)
{
USHORT index,temp,max_wd_cnt;
@@ -10884,185 +7154,148 @@ void DiagEEPROM(ULONG p_port)
else
max_wd_cnt = EEPROM_WD_CNT * 2;
- temp = utilEERead(p_port, FW_SIGNATURE/2);
+ temp = FPT_utilEERead(p_port, FW_SIGNATURE/2);
if (temp == 0x4641) {
for (index = 2; index < max_wd_cnt; index++) {
- temp += utilEERead(p_port, index);
+ temp += FPT_utilEERead(p_port, index);
}
- if (temp == utilEERead(p_port, EEPROM_CHECK_SUM/2)) {
+ if (temp == FPT_utilEERead(p_port, EEPROM_CHECK_SUM/2)) {
return; /*EEPROM is Okay so return now! */
}
}
- utilEEWriteOnOff(p_port,(UCHAR)1);
+ FPT_utilEEWriteOnOff(p_port,(UCHAR)1);
for (index = 0; index < max_wd_cnt; index++) {
- utilEEWrite(p_port, 0x0000, index);
+ FPT_utilEEWrite(p_port, 0x0000, index);
}
temp = 0;
- utilEEWrite(p_port, 0x4641, FW_SIGNATURE/2);
+ FPT_utilEEWrite(p_port, 0x4641, FW_SIGNATURE/2);
temp += 0x4641;
- utilEEWrite(p_port, 0x3920, MODEL_NUMB_0/2);
+ FPT_utilEEWrite(p_port, 0x3920, MODEL_NUMB_0/2);
temp += 0x3920;
- utilEEWrite(p_port, 0x3033, MODEL_NUMB_2/2);
+ FPT_utilEEWrite(p_port, 0x3033, MODEL_NUMB_2/2);
temp += 0x3033;
- utilEEWrite(p_port, 0x2020, MODEL_NUMB_4/2);
+ FPT_utilEEWrite(p_port, 0x2020, MODEL_NUMB_4/2);
temp += 0x2020;
- utilEEWrite(p_port, 0x70D3, SYSTEM_CONFIG/2);
+ FPT_utilEEWrite(p_port, 0x70D3, SYSTEM_CONFIG/2);
temp += 0x70D3;
- utilEEWrite(p_port, 0x0010, BIOS_CONFIG/2);
+ FPT_utilEEWrite(p_port, 0x0010, BIOS_CONFIG/2);
temp += 0x0010;
- utilEEWrite(p_port, 0x0003, SCAM_CONFIG/2);
+ FPT_utilEEWrite(p_port, 0x0003, SCAM_CONFIG/2);
temp += 0x0003;
- utilEEWrite(p_port, 0x0007, ADAPTER_SCSI_ID/2);
+ FPT_utilEEWrite(p_port, 0x0007, ADAPTER_SCSI_ID/2);
temp += 0x0007;
- utilEEWrite(p_port, 0x0000, IGNORE_B_SCAN/2);
+ FPT_utilEEWrite(p_port, 0x0000, IGNORE_B_SCAN/2);
temp += 0x0000;
- utilEEWrite(p_port, 0x0000, SEND_START_ENA/2);
+ FPT_utilEEWrite(p_port, 0x0000, SEND_START_ENA/2);
temp += 0x0000;
- utilEEWrite(p_port, 0x0000, DEVICE_ENABLE/2);
+ FPT_utilEEWrite(p_port, 0x0000, DEVICE_ENABLE/2);
temp += 0x0000;
- utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL01/2);
+ FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL01/2);
temp += 0x4242;
- utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL23/2);
+ FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL23/2);
temp += 0x4242;
- utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL45/2);
+ FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL45/2);
temp += 0x4242;
- utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL67/2);
+ FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL67/2);
temp += 0x4242;
- utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL89/2);
+ FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL89/2);
temp += 0x4242;
- utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLab/2);
+ FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLab/2);
temp += 0x4242;
- utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLcd/2);
+ FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLcd/2);
temp += 0x4242;
- utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLef/2);
+ FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLef/2);
temp += 0x4242;
- utilEEWrite(p_port, 0x6C46, 64/2); /*PRODUCT ID */
+ FPT_utilEEWrite(p_port, 0x6C46, 64/2); /*PRODUCT ID */
temp += 0x6C46;
- utilEEWrite(p_port, 0x7361, 66/2); /* FlashPoint LT */
+ FPT_utilEEWrite(p_port, 0x7361, 66/2); /* FlashPoint LT */
temp += 0x7361;
- utilEEWrite(p_port, 0x5068, 68/2);
+ FPT_utilEEWrite(p_port, 0x5068, 68/2);
temp += 0x5068;
- utilEEWrite(p_port, 0x696F, 70/2);
+ FPT_utilEEWrite(p_port, 0x696F, 70/2);
temp += 0x696F;
- utilEEWrite(p_port, 0x746E, 72/2);
+ FPT_utilEEWrite(p_port, 0x746E, 72/2);
temp += 0x746E;
- utilEEWrite(p_port, 0x4C20, 74/2);
+ FPT_utilEEWrite(p_port, 0x4C20, 74/2);
temp += 0x4C20;
- utilEEWrite(p_port, 0x2054, 76/2);
+ FPT_utilEEWrite(p_port, 0x2054, 76/2);
temp += 0x2054;
- utilEEWrite(p_port, 0x2020, 78/2);
+ FPT_utilEEWrite(p_port, 0x2020, 78/2);
temp += 0x2020;
index = ((EE_SCAMBASE/2)+(7*16));
- utilEEWrite(p_port, (0x0700+TYPE_CODE0), index);
+ FPT_utilEEWrite(p_port, (0x0700+TYPE_CODE0), index);
temp += (0x0700+TYPE_CODE0);
index++;
- utilEEWrite(p_port, 0x5542, index); /*Vendor ID code */
+ FPT_utilEEWrite(p_port, 0x5542, index); /*Vendor ID code */
temp += 0x5542; /* BUSLOGIC */
index++;
- utilEEWrite(p_port, 0x4C53, index);
+ FPT_utilEEWrite(p_port, 0x4C53, index);
temp += 0x4C53;
index++;
- utilEEWrite(p_port, 0x474F, index);
+ FPT_utilEEWrite(p_port, 0x474F, index);
temp += 0x474F;
index++;
- utilEEWrite(p_port, 0x4349, index);
+ FPT_utilEEWrite(p_port, 0x4349, index);
temp += 0x4349;
index++;
- utilEEWrite(p_port, 0x5442, index); /*Vendor unique code */
+ FPT_utilEEWrite(p_port, 0x5442, index); /*Vendor unique code */
temp += 0x5442; /* BT- 930 */
index++;
- utilEEWrite(p_port, 0x202D, index);
+ FPT_utilEEWrite(p_port, 0x202D, index);
temp += 0x202D;
index++;
- utilEEWrite(p_port, 0x3339, index);
+ FPT_utilEEWrite(p_port, 0x3339, index);
temp += 0x3339;
index++; /*Serial # */
- utilEEWrite(p_port, 0x2030, index); /* 01234567 */
+ FPT_utilEEWrite(p_port, 0x2030, index); /* 01234567 */
temp += 0x2030;
index++;
- utilEEWrite(p_port, 0x5453, index);
+ FPT_utilEEWrite(p_port, 0x5453, index);
temp += 0x5453;
index++;
- utilEEWrite(p_port, 0x5645, index);
+ FPT_utilEEWrite(p_port, 0x5645, index);
temp += 0x5645;
index++;
- utilEEWrite(p_port, 0x2045, index);
+ FPT_utilEEWrite(p_port, 0x2045, index);
temp += 0x2045;
index++;
- utilEEWrite(p_port, 0x202F, index);
+ FPT_utilEEWrite(p_port, 0x202F, index);
temp += 0x202F;
index++;
- utilEEWrite(p_port, 0x4F4A, index);
+ FPT_utilEEWrite(p_port, 0x4F4A, index);
temp += 0x4F4A;
index++;
- utilEEWrite(p_port, 0x204E, index);
+ FPT_utilEEWrite(p_port, 0x204E, index);
temp += 0x204E;
index++;
- utilEEWrite(p_port, 0x3539, index);
+ FPT_utilEEWrite(p_port, 0x3539, index);
temp += 0x3539;
- utilEEWrite(p_port, temp, EEPROM_CHECK_SUM/2);
+ FPT_utilEEWrite(p_port, temp, EEPROM_CHECK_SUM/2);
- utilEEWriteOnOff(p_port,(UCHAR)0);
+ FPT_utilEEWriteOnOff(p_port,(UCHAR)0);
}
-#ident "$Id: utility.c 1.23 1997/06/10 16:55:06 mohan Exp $"
-/*----------------------------------------------------------------------
- *
- *
- * Copyright 1995-1996 by Mylex Corporation. All Rights Reserved
- *
- * This file is available under both the GNU General Public License
- * and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- * $Workfile: utility.c $
- *
- * Description: Utility functions relating to queueing and EEPROM
- * manipulation and any other garbage functions.
- *
- * $Date: 1997/06/10 16:55:06 $
- *
- * $Revision: 1.23 $
- *
- *----------------------------------------------------------------------*/
-/*#include <globals.h>*/
-
-#if (FW_TYPE==_UCB_MGR_)
- /*#include <budi.h>*/
-#endif
-
-/*#include <sccbmgr.h>*/
-/*#include <blx30.h>*/
-/*#include <target.h>*/
-/*#include <scsi2.h>*/
-/*#include <harpoon.h>*/
-
-
-/*
-extern SCCBCARD BL_Card[MAX_CARDS];
-extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR];
-extern unsigned int SccbGlobalFlags;
-*/
/*---------------------------------------------------------------------
*
@@ -11072,7 +7305,7 @@ extern unsigned int SccbGlobalFlags;
*
*---------------------------------------------------------------------*/
-void queueSearchSelect(PSCCBcard pCurrCard, UCHAR p_card)
+static void FPT_queueSearchSelect(PSCCBcard pCurrCard, UCHAR p_card)
{
UCHAR scan_ptr, lun;
PSCCBMgr_tar_info currTar_Info;
@@ -11081,7 +7314,7 @@ void queueSearchSelect(PSCCBcard pCurrCard, UCHAR p_card)
scan_ptr = pCurrCard->scanIndex;
do
{
- currTar_Info = &sccbMgrTbl[p_card][scan_ptr];
+ currTar_Info = &FPT_sccbMgrTbl[p_card][scan_ptr];
if((pCurrCard->globalFlags & F_CONLUN_IO) &&
((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
{
@@ -11094,7 +7327,7 @@ void queueSearchSelect(PSCCBcard pCurrCard, UCHAR p_card)
for(lun=0; lun < MAX_LUN; lun++)
{
- if(currTar_Info->TarLUNBusy[lun] == FALSE)
+ if(currTar_Info->TarLUNBusy[lun] == 0)
{
pCurrCard->currentSCCB = currTar_Info->TarSelQ_Head;
@@ -11153,7 +7386,7 @@ void queueSearchSelect(PSCCBcard pCurrCard, UCHAR p_card)
else
{
if ((currTar_Info->TarSelQ_Cnt != 0) &&
- (currTar_Info->TarLUNBusy[0] == FALSE))
+ (currTar_Info->TarLUNBusy[0] == 0))
{
pCurrCard->currentSCCB = currTar_Info->TarSelQ_Head;
@@ -11203,7 +7436,7 @@ void queueSearchSelect(PSCCBcard pCurrCard, UCHAR p_card)
*
*---------------------------------------------------------------------*/
-void queueSelectFail(PSCCBcard pCurrCard, UCHAR p_card)
+static void FPT_queueSelectFail(PSCCBcard pCurrCard, UCHAR p_card)
{
UCHAR thisTarg;
PSCCBMgr_tar_info currTar_Info;
@@ -11211,7 +7444,7 @@ void queueSelectFail(PSCCBcard pCurrCard, UCHAR p_card)
if (pCurrCard->currentSCCB != NULL)
{
thisTarg = (UCHAR)(((PSCCB)(pCurrCard->currentSCCB))->TargID);
- currTar_Info = &sccbMgrTbl[p_card][thisTarg];
+ currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
pCurrCard->currentSCCB->Sccb_backlink = (PSCCB)NULL;
@@ -11242,103 +7475,10 @@ void queueSelectFail(PSCCBcard pCurrCard, UCHAR p_card)
*
*---------------------------------------------------------------------*/
-void queueCmdComplete(PSCCBcard pCurrCard, PSCCB p_sccb, UCHAR p_card)
+static void FPT_queueCmdComplete(PSCCBcard pCurrCard, PSCCB p_sccb,
+ UCHAR p_card)
{
-#if (FW_TYPE==_UCB_MGR_)
-
- u08bits SCSIcmd;
- CALL_BK_FN callback;
- PSCCBMgr_tar_info currTar_Info;
-
- PUCB p_ucb;
- p_ucb=p_sccb->Sccb_ucb_ptr;
-
- SCSIcmd = p_sccb->Cdb[0];
-
-
- if (!(p_sccb->Sccb_XferState & F_ALL_XFERRED))
- {
-
- if ((p_ucb->UCB_opcode & OPC_CHK_UNDER_OVER_RUN) &&
- (p_sccb->HostStatus == SCCB_COMPLETE) &&
- (p_sccb->TargetStatus != SSCHECK))
-
- if ((SCSIcmd == SCSI_READ) ||
- (SCSIcmd == SCSI_WRITE) ||
- (SCSIcmd == SCSI_READ_EXTENDED) ||
- (SCSIcmd == SCSI_WRITE_EXTENDED) ||
- (SCSIcmd == SCSI_WRITE_AND_VERIFY) ||
- (SCSIcmd == SCSI_START_STOP_UNIT) ||
- (pCurrCard->globalFlags & F_NO_FILTER)
- )
- p_sccb->HostStatus = SCCB_DATA_UNDER_RUN;
- }
-
- p_ucb->UCB_status=SCCB_SUCCESS;
-
- if ((p_ucb->UCB_hbastat=p_sccb->HostStatus) || (p_ucb->UCB_scsistat=p_sccb->TargetStatus))
- {
- p_ucb->UCB_status=SCCB_ERROR;
- }
-
- if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) ||
- (p_sccb->OperationCode == RESIDUAL_COMMAND))
- {
-
- utilUpdateResidual(p_sccb);
-
- p_ucb->UCB_datalen=p_sccb->DataLength;
- }
-
- pCurrCard->cmdCounter--;
- if (!pCurrCard->cmdCounter)
- {
-
- if (pCurrCard->globalFlags & F_GREEN_PC)
- {
- WR_HARPOON(pCurrCard->ioPort+hp_clkctrl_0,(PWR_DWN | CLKCTRL_DEFAULT));
- WR_HARPOON(pCurrCard->ioPort+hp_sys_ctrl, STOP_CLK);
- }
-
- WR_HARPOON(pCurrCard->ioPort+hp_semaphore,
- (RD_HARPOON(pCurrCard->ioPort+hp_semaphore) & ~SCCB_MGR_ACTIVE));
- }
-
- if(pCurrCard->discQCount != 0)
- {
- currTar_Info = &sccbMgrTbl[p_card][p_sccb->TargID];
- if(((pCurrCard->globalFlags & F_CONLUN_IO) &&
- ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
- {
- pCurrCard->discQCount--;
- pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[p_sccb->Lun]] = NULL;
- }
- else
- {
- if(p_sccb->Sccb_tag)
- {
- pCurrCard->discQCount--;
- pCurrCard->discQ_Tbl[p_sccb->Sccb_tag] = NULL;
- }else
- {
- pCurrCard->discQCount--;
- pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]] = NULL;
- }
- }
-
- }
- callback = (CALL_BK_FN)p_ucb->UCB_callback;
- callback(p_ucb);
- pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
- pCurrCard->currentSCCB = NULL;
-}
-
-
-
-
-#else
-
UCHAR i, SCSIcmd;
CALL_BK_FN callback;
PSCCBMgr_tar_info currTar_Info;
@@ -11383,7 +7523,7 @@ void queueCmdComplete(PSCCBcard pCurrCard, PSCCB p_sccb, UCHAR p_card)
if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) ||
(p_sccb->OperationCode == RESIDUAL_COMMAND)) {
- utilUpdateResidual(p_sccb);
+ FPT_utilUpdateResidual(p_sccb);
}
pCurrCard->cmdCounter--;
@@ -11401,7 +7541,7 @@ void queueCmdComplete(PSCCBcard pCurrCard, PSCCB p_sccb, UCHAR p_card)
if(pCurrCard->discQCount != 0)
{
- currTar_Info = &sccbMgrTbl[p_card][p_sccb->TargID];
+ currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
if(((pCurrCard->globalFlags & F_CONLUN_IO) &&
((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
{
@@ -11428,7 +7568,6 @@ void queueCmdComplete(PSCCBcard pCurrCard, PSCCB p_sccb, UCHAR p_card)
pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
pCurrCard->currentSCCB = NULL;
}
-#endif /* ( if FW_TYPE==...) */
/*---------------------------------------------------------------------
@@ -11438,30 +7577,30 @@ void queueCmdComplete(PSCCBcard pCurrCard, PSCCB p_sccb, UCHAR p_card)
* Description: Add SCCB to our disconnect array.
*
*---------------------------------------------------------------------*/
-void queueDisconnect(PSCCB p_sccb, UCHAR p_card)
+static void FPT_queueDisconnect(PSCCB p_sccb, UCHAR p_card)
{
PSCCBMgr_tar_info currTar_Info;
- currTar_Info = &sccbMgrTbl[p_card][p_sccb->TargID];
+ currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
- if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
+ if(((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
{
- BL_Card[p_card].discQ_Tbl[currTar_Info->LunDiscQ_Idx[p_sccb->Lun]] = p_sccb;
+ FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->LunDiscQ_Idx[p_sccb->Lun]] = p_sccb;
}
else
{
if (p_sccb->Sccb_tag)
{
- BL_Card[p_card].discQ_Tbl[p_sccb->Sccb_tag] = p_sccb;
- sccbMgrTbl[p_card][p_sccb->TargID].TarLUNBusy[0] = FALSE;
- sccbMgrTbl[p_card][p_sccb->TargID].TarTagQ_Cnt++;
+ FPT_BL_Card[p_card].discQ_Tbl[p_sccb->Sccb_tag] = p_sccb;
+ FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarLUNBusy[0] = 0;
+ FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarTagQ_Cnt++;
}else
{
- BL_Card[p_card].discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]] = p_sccb;
+ FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]] = p_sccb;
}
}
- BL_Card[p_card].currentSCCB = NULL;
+ FPT_BL_Card[p_card].currentSCCB = NULL;
}
@@ -11473,29 +7612,29 @@ void queueDisconnect(PSCCB p_sccb, UCHAR p_card)
*
*---------------------------------------------------------------------*/
-void queueFlushSccb(UCHAR p_card, UCHAR error_code)
+static void FPT_queueFlushSccb(UCHAR p_card, UCHAR error_code)
{
UCHAR qtag,thisTarg;
PSCCB currSCCB;
PSCCBMgr_tar_info currTar_Info;
- currSCCB = BL_Card[p_card].currentSCCB;
+ currSCCB = FPT_BL_Card[p_card].currentSCCB;
if(currSCCB != NULL)
{
thisTarg = (UCHAR)currSCCB->TargID;
- currTar_Info = &sccbMgrTbl[p_card][thisTarg];
+ currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
for (qtag=0; qtag<QUEUE_DEPTH; qtag++) {
- if (BL_Card[p_card].discQ_Tbl[qtag] &&
- (BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg))
+ if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
+ (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg))
{
- BL_Card[p_card].discQ_Tbl[qtag]->HostStatus = (UCHAR)error_code;
+ FPT_BL_Card[p_card].discQ_Tbl[qtag]->HostStatus = (UCHAR)error_code;
- queueCmdComplete(&BL_Card[p_card],BL_Card[p_card].discQ_Tbl[qtag], p_card);
+ FPT_queueCmdComplete(&FPT_BL_Card[p_card],FPT_BL_Card[p_card].discQ_Tbl[qtag], p_card);
- BL_Card[p_card].discQ_Tbl[qtag] = NULL;
+ FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
currTar_Info->TarTagQ_Cnt--;
}
@@ -11512,24 +7651,25 @@ void queueFlushSccb(UCHAR p_card, UCHAR error_code)
*
*---------------------------------------------------------------------*/
-void queueFlushTargSccb(UCHAR p_card, UCHAR thisTarg, UCHAR error_code)
+static void FPT_queueFlushTargSccb(UCHAR p_card, UCHAR thisTarg,
+ UCHAR error_code)
{
UCHAR qtag;
PSCCBMgr_tar_info currTar_Info;
- currTar_Info = &sccbMgrTbl[p_card][thisTarg];
+ currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
for (qtag=0; qtag<QUEUE_DEPTH; qtag++) {
- if (BL_Card[p_card].discQ_Tbl[qtag] &&
- (BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg))
+ if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
+ (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg))
{
- BL_Card[p_card].discQ_Tbl[qtag]->HostStatus = (UCHAR)error_code;
+ FPT_BL_Card[p_card].discQ_Tbl[qtag]->HostStatus = (UCHAR)error_code;
- queueCmdComplete(&BL_Card[p_card],BL_Card[p_card].discQ_Tbl[qtag], p_card);
+ FPT_queueCmdComplete(&FPT_BL_Card[p_card],FPT_BL_Card[p_card].discQ_Tbl[qtag], p_card);
- BL_Card[p_card].discQ_Tbl[qtag] = NULL;
+ FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
currTar_Info->TarTagQ_Cnt--;
}
@@ -11541,10 +7681,10 @@ void queueFlushTargSccb(UCHAR p_card, UCHAR thisTarg, UCHAR error_code)
-void queueAddSccb(PSCCB p_SCCB, UCHAR p_card)
+static void FPT_queueAddSccb(PSCCB p_SCCB, UCHAR p_card)
{
PSCCBMgr_tar_info currTar_Info;
- currTar_Info = &sccbMgrTbl[p_card][p_SCCB->TargID];
+ currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
p_SCCB->Sccb_forwardlink = NULL;
@@ -11575,12 +7715,12 @@ void queueAddSccb(PSCCB p_SCCB, UCHAR p_card)
*
*---------------------------------------------------------------------*/
-UCHAR queueFindSccb(PSCCB p_SCCB, UCHAR p_card)
+static UCHAR FPT_queueFindSccb(PSCCB p_SCCB, UCHAR p_card)
{
PSCCB q_ptr;
PSCCBMgr_tar_info currTar_Info;
- currTar_Info = &sccbMgrTbl[p_card][p_SCCB->TargID];
+ currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
q_ptr = currTar_Info->TarSelQ_Head;
@@ -11609,7 +7749,7 @@ UCHAR queueFindSccb(PSCCB p_SCCB, UCHAR p_card)
currTar_Info->TarSelQ_Cnt--;
- return(TRUE);
+ return(1);
}
else {
@@ -11618,7 +7758,7 @@ UCHAR queueFindSccb(PSCCB p_SCCB, UCHAR p_card)
}
- return(FALSE);
+ return(0);
}
@@ -11636,15 +7776,11 @@ UCHAR queueFindSccb(PSCCB p_SCCB, UCHAR p_card)
*
*---------------------------------------------------------------------*/
-void utilUpdateResidual(PSCCB p_SCCB)
+static void FPT_utilUpdateResidual(PSCCB p_SCCB)
{
ULONG partial_cnt;
UINT sg_index;
-#if defined(COMPILER_16_BIT) && !defined(DOS)
- ULONG far *sg_ptr;
-#else
ULONG *sg_ptr;
-#endif
if (p_SCCB->Sccb_XferState & F_ALL_XFERRED) {
@@ -11657,11 +7793,7 @@ void utilUpdateResidual(PSCCB p_SCCB)
sg_index = p_SCCB->Sccb_sgseg;
-#if defined(COMPILER_16_BIT) && !defined(DOS)
- sg_ptr = (ULONG far *)p_SCCB->DataPointer;
-#else
sg_ptr = (ULONG *)p_SCCB->DataPointer;
-#endif
if (p_SCCB->Sccb_SGoffset) {
@@ -11694,17 +7826,13 @@ void utilUpdateResidual(PSCCB p_SCCB)
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void Wait1Second(USHORT p_port)
-#else
-void Wait1Second(ULONG p_port)
-#endif
+static void FPT_Wait1Second(ULONG p_port)
{
UCHAR i;
for(i=0; i < 4; i++) {
- Wait(p_port, TO_250ms);
+ FPT_Wait(p_port, TO_250ms);
if ((RD_HARPOON(p_port+hp_scsictrl_0) & SCSI_RST))
break;
@@ -11717,17 +7845,13 @@ void Wait1Second(ULONG p_port)
/*---------------------------------------------------------------------
*
- * Function: Wait
+ * Function: FPT_Wait
*
* Description: Wait the desired delay.
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void Wait(USHORT p_port, UCHAR p_delay)
-#else
-void Wait(ULONG p_port, UCHAR p_delay)
-#endif
+static void FPT_Wait(ULONG p_port, UCHAR p_delay)
{
UCHAR old_timer;
UCHAR green_flag;
@@ -11739,7 +7863,7 @@ void Wait(ULONG p_port, UCHAR p_delay)
WR_HARPOON(p_port+hp_seltimeout,p_delay);
WRW_HARPOON((p_port+hp_intstat), TIMEOUT);
- WRW_HARPOON((p_port+hp_intena), (default_intena & ~TIMEOUT));
+ WRW_HARPOON((p_port+hp_intena), (FPT_default_intena & ~TIMEOUT));
WR_HARPOON(p_port+hp_portctrl_0,
@@ -11758,7 +7882,7 @@ void Wait(ULONG p_port, UCHAR p_delay)
(RD_HARPOON(p_port+hp_portctrl_0) & ~START_TO));
WRW_HARPOON((p_port+hp_intstat), TIMEOUT);
- WRW_HARPOON((p_port+hp_intena), default_intena);
+ WRW_HARPOON((p_port+hp_intena), FPT_default_intena);
WR_HARPOON(p_port+hp_clkctrl_0,green_flag);
@@ -11775,11 +7899,7 @@ void Wait(ULONG p_port, UCHAR p_delay)
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void utilEEWriteOnOff(USHORT p_port,UCHAR p_mode)
-#else
-void utilEEWriteOnOff(ULONG p_port,UCHAR p_mode)
-#endif
+static void FPT_utilEEWriteOnOff(ULONG p_port,UCHAR p_mode)
{
UCHAR ee_value;
@@ -11787,12 +7907,12 @@ void utilEEWriteOnOff(ULONG p_port,UCHAR p_mode)
if (p_mode)
- utilEESendCmdAddr(p_port, EWEN, EWEN_ADDR);
+ FPT_utilEESendCmdAddr(p_port, EWEN, EWEN_ADDR);
else
- utilEESendCmdAddr(p_port, EWDS, EWDS_ADDR);
+ FPT_utilEESendCmdAddr(p_port, EWDS, EWDS_ADDR);
WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */
WR_HARPOON(p_port+hp_ee_ctrl, ee_value); /*Turn off Master Select */
@@ -11808,11 +7928,7 @@ void utilEEWriteOnOff(ULONG p_port,UCHAR p_mode)
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void utilEEWrite(USHORT p_port, USHORT ee_data, USHORT ee_addr)
-#else
-void utilEEWrite(ULONG p_port, USHORT ee_data, USHORT ee_addr)
-#endif
+static void FPT_utilEEWrite(ULONG p_port, USHORT ee_data, USHORT ee_addr)
{
UCHAR ee_value;
@@ -11823,7 +7939,7 @@ void utilEEWrite(ULONG p_port, USHORT ee_data, USHORT ee_addr)
- utilEESendCmdAddr(p_port, EE_WRITE, ee_addr);
+ FPT_utilEESendCmdAddr(p_port, EE_WRITE, ee_addr);
ee_value |= (SEE_MS + SEE_CS);
@@ -11847,7 +7963,7 @@ void utilEEWrite(ULONG p_port, USHORT ee_data, USHORT ee_addr)
ee_value &= (EXT_ARB_ACK | SCSI_TERM_ENA_H);
WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS));
- Wait(p_port, TO_10ms);
+ FPT_Wait(p_port, TO_10ms);
WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS | SEE_CS)); /* Set CS to EEPROM */
WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS)); /* Turn off CS */
@@ -11863,19 +7979,15 @@ void utilEEWrite(ULONG p_port, USHORT ee_data, USHORT ee_addr)
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-USHORT utilEERead(USHORT p_port, USHORT ee_addr)
-#else
-USHORT utilEERead(ULONG p_port, USHORT ee_addr)
-#endif
+static USHORT FPT_utilEERead(ULONG p_port, USHORT ee_addr)
{
USHORT i, ee_data1, ee_data2;
i = 0;
- ee_data1 = utilEEReadOrg(p_port, ee_addr);
+ ee_data1 = FPT_utilEEReadOrg(p_port, ee_addr);
do
{
- ee_data2 = utilEEReadOrg(p_port, ee_addr);
+ ee_data2 = FPT_utilEEReadOrg(p_port, ee_addr);
if(ee_data1 == ee_data2)
return(ee_data1);
@@ -11897,11 +8009,7 @@ USHORT utilEERead(ULONG p_port, USHORT ee_addr)
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-USHORT utilEEReadOrg(USHORT p_port, USHORT ee_addr)
-#else
-USHORT utilEEReadOrg(ULONG p_port, USHORT ee_addr)
-#endif
+static USHORT FPT_utilEEReadOrg(ULONG p_port, USHORT ee_addr)
{
UCHAR ee_value;
@@ -11911,7 +8019,7 @@ USHORT utilEEReadOrg(ULONG p_port, USHORT ee_addr)
(SEE_MS | SEE_CS));
- utilEESendCmdAddr(p_port, EE_READ, ee_addr);
+ FPT_utilEESendCmdAddr(p_port, EE_READ, ee_addr);
ee_value |= (SEE_MS + SEE_CS);
@@ -11949,11 +8057,7 @@ USHORT utilEEReadOrg(ULONG p_port, USHORT ee_addr)
*
*---------------------------------------------------------------------*/
-#if defined(DOS)
-void utilEESendCmdAddr(USHORT p_port, UCHAR ee_cmd, USHORT ee_addr)
-#else
-void utilEESendCmdAddr(ULONG p_port, UCHAR ee_cmd, USHORT ee_addr)
-#endif
+static void FPT_utilEESendCmdAddr(ULONG p_port, UCHAR ee_cmd, USHORT ee_addr)
{
UCHAR ee_value;
UCHAR narrow_flg;
@@ -12016,7 +8120,7 @@ void utilEESendCmdAddr(ULONG p_port, UCHAR ee_cmd, USHORT ee_addr)
}
}
-USHORT CalcCrc16(UCHAR buffer[])
+static USHORT FPT_CalcCrc16(UCHAR buffer[])
{
USHORT crc=0;
int i,j;
@@ -12036,7 +8140,7 @@ USHORT CalcCrc16(UCHAR buffer[])
return(crc);
}
-UCHAR CalcLrc(UCHAR buffer[])
+static UCHAR FPT_CalcLrc(UCHAR buffer[])
{
int i;
UCHAR lrc;
@@ -12109,33 +8213,6 @@ FlashPoint__HandleInterrupt(FlashPoint_CardHandle_T CardHandle)
#define FlashPoint_HandleInterrupt FlashPoint__HandleInterrupt
-/*
- FlashPoint_InquireTargetInfo returns the Synchronous Period, Synchronous
- Offset, and Wide Transfers Active information for TargetID on CardHandle.
-*/
-
-void FlashPoint_InquireTargetInfo(FlashPoint_CardHandle_T CardHandle,
- int TargetID,
- unsigned char *SynchronousPeriod,
- unsigned char *SynchronousOffset,
- unsigned char *WideTransfersActive)
-{
- SCCBMGR_TAR_INFO *TargetInfo =
- &sccbMgrTbl[((SCCBCARD *)CardHandle)->cardIndex][TargetID];
- if ((TargetInfo->TarSyncCtrl & SYNC_OFFSET) > 0)
- {
- *SynchronousPeriod = 5 * ((TargetInfo->TarSyncCtrl >> 5) + 1);
- *SynchronousOffset = TargetInfo->TarSyncCtrl & SYNC_OFFSET;
- }
- else
- {
- *SynchronousPeriod = 0;
- *SynchronousOffset = 0;
- }
- *WideTransfersActive = (TargetInfo->TarSyncCtrl & NARROW_SCSI ? 0 : 1);
-}
-
-
#else /* CONFIG_SCSI_OMIT_FLASHPOINT */
@@ -12151,9 +8228,6 @@ extern int FlashPoint_AbortCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *);
extern boolean FlashPoint_InterruptPending(FlashPoint_CardHandle_T);
extern int FlashPoint_HandleInterrupt(FlashPoint_CardHandle_T);
extern void FlashPoint_ReleaseHostAdapter(FlashPoint_CardHandle_T);
-extern void FlashPoint_InquireTargetInfo(FlashPoint_CardHandle_T,
- int, unsigned char *,
- unsigned char *, unsigned char *);
#endif /* CONFIG_SCSI_OMIT_FLASHPOINT */
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 1811cb24031..96df148ed96 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -137,6 +137,24 @@ config CHR_DEV_SG
If unsure, say N.
+config CHR_DEV_SCH
+ tristate "SCSI media changer support"
+ depends on SCSI
+ ---help---
+ This is a driver for SCSI media changers. Most common devices are
+ tape libraries and MOD/CDROM jukeboxes. *Real* jukeboxes, you
+ don't need this for those tiny 6-slot cdrom changers. Media
+ changers are listed as "Type: Medium Changer" in /proc/scsi/scsi.
+ If you have such hardware and want to use it with linux, say Y
+ here. Check <file:Documentation/scsi-changer.txt> for details.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read <file:Documentation/modules.txt> and
+ <file:Documentation/scsi.txt>. The module will be called ch.o.
+ If unsure, say N.
+
+
comment "Some SCSI devices (e.g. CD jukebox) support multiple LUNs"
depends on SCSI
@@ -1192,28 +1210,6 @@ config SCSI_PAS16
To compile this driver as a module, choose M here: the
module will be called pas16.
-config SCSI_PCI2000
- tristate "PCI2000 support"
- depends on PCI && SCSI && BROKEN
- help
- This is support for the PCI2000I EIDE interface card which acts as a
- SCSI host adapter. Please read the SCSI-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here: the
- module will be called pci2000.
-
-config SCSI_PCI2220I
- tristate "PCI2220i support"
- depends on PCI && SCSI && BROKEN
- help
- This is support for the PCI2220i EIDE interface card which acts as a
- SCSI host adapter. Please read the SCSI-HOWTO, available from
- <http://www.tldp.org/docs.html#howto>.
-
- To compile this driver as a module, choose M here: the
- module will be called pci2220i.
-
config SCSI_PSI240I
tristate "PSI240i support"
depends on ISA && SCSI
@@ -1752,7 +1748,7 @@ config SCSI_NCR53C7xx_FAST
config SUN3_SCSI
tristate "Sun3 NCR5380 SCSI"
- depends on SUN3 && SCSI
+ depends on SUN3 && SCSI && BROKEN
help
This option will enable support for the OBIO (onboard io) NCR5380
SCSI controller found in the Sun 3/50 and 3/60, as well as for
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 9cb9fe7d623..3746fb9fa2f 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -50,8 +50,6 @@ obj-$(CONFIG_MVME16x_SCSI) += mvme16x.o 53c7xx.o
obj-$(CONFIG_BVME6000_SCSI) += bvme6000.o 53c7xx.o
obj-$(CONFIG_SCSI_SIM710) += 53c700.o sim710.o
obj-$(CONFIG_SCSI_ADVANSYS) += advansys.o
-obj-$(CONFIG_SCSI_PCI2000) += pci2000.o
-obj-$(CONFIG_SCSI_PCI2220I) += pci2220i.o
obj-$(CONFIG_SCSI_PSI240I) += psi240i.o
obj-$(CONFIG_SCSI_BUSLOGIC) += BusLogic.o
obj-$(CONFIG_SCSI_DPT_I2O) += dpt_i2o.o
@@ -142,6 +140,7 @@ obj-$(CONFIG_CHR_DEV_OSST) += osst.o
obj-$(CONFIG_BLK_DEV_SD) += sd_mod.o
obj-$(CONFIG_BLK_DEV_SR) += sr_mod.o
obj-$(CONFIG_CHR_DEV_SG) += sg.o
+obj-$(CONFIG_CHR_DEV_SCH) += ch.o
scsi_mod-y += scsi.o hosts.o scsi_ioctl.o constants.o \
scsicam.o scsi_error.o scsi_lib.o \
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index 770fa841e38..f8ec6fe7d85 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -2825,39 +2825,17 @@ static int NCR5380_abort(Scsi_Cmnd * cmd) {
* Locks: host lock taken by caller
*/
-static int NCR5380_bus_reset(Scsi_Cmnd * cmd) {
- NCR5380_local_declare();
- NCR5380_setup(cmd->device->host);
-
- NCR5380_print_status(cmd->device->host);
- do_reset(cmd->device->host);
- return SUCCESS;
-}
-
-/*
- * Function : int NCR5380_device_reset (Scsi_Cmnd *cmd)
- *
- * Purpose : reset a SCSI device
- *
- * Returns : FAILED
- *
- * Locks: io_request_lock held by caller
- */
+static int NCR5380_bus_reset(Scsi_Cmnd * cmd)
+{
+ struct Scsi_Host *instance = cmd->device->host;
-static int NCR5380_device_reset(Scsi_Cmnd * cmd) {
- return FAILED;
-}
+ NCR5380_local_declare();
+ NCR5380_setup(instance);
+ NCR5380_print_status(instance);
-/*
- * Function : int NCR5380_host_reset (Scsi_Cmnd *cmd)
- *
- * Purpose : reset a SCSI device
- *
- * Returns : FAILED
- *
- * Locks: io_request_lock held by caller
- */
+ spin_lock_irq(instance->host_lock);
+ do_reset(instance);
+ spin_unlock_irq(instance->host_lock);
-static int NCR5380_host_reset(Scsi_Cmnd * cmd) {
- return FAILED;
+ return SUCCESS;
}
diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h
index b5103f94d62..c3462e358d1 100644
--- a/drivers/scsi/NCR5380.h
+++ b/drivers/scsi/NCR5380.h
@@ -306,8 +306,6 @@ static void NCR5380_print(struct Scsi_Host *instance);
#endif
static int NCR5380_abort(Scsi_Cmnd * cmd);
static int NCR5380_bus_reset(Scsi_Cmnd * cmd);
-static int NCR5380_host_reset(Scsi_Cmnd * cmd);
-static int NCR5380_device_reset(Scsi_Cmnd * cmd);
static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *));
static int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, char **start,
off_t offset, int length, int inout);
diff --git a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c
index 74b93564a25..6ceabbd42a3 100644
--- a/drivers/scsi/NCR53C9x.c
+++ b/drivers/scsi/NCR53C9x.c
@@ -94,7 +94,7 @@ enum {
};
/* The master ring of all esp hosts we are managing in this driver. */
-struct NCR_ESP *espchain;
+static struct NCR_ESP *espchain;
int nesps = 0, esps_in_use = 0, esps_running = 0;
irqreturn_t esp_intr(int irq, void *dev_id, struct pt_regs *pregs);
@@ -1467,14 +1467,12 @@ int esp_reset(Scsi_Cmnd *SCptr)
{
struct NCR_ESP *esp = (struct NCR_ESP *) SCptr->device->host->hostdata;
+ spin_lock_irq(esp->ehost->host_lock);
(void) esp_do_resetbus(esp, esp->eregs);
-
spin_unlock_irq(esp->ehost->host_lock);
wait_event(esp->reset_queue, (esp->resetting_bus == 0));
- spin_lock_irq(esp->ehost->host_lock);
-
return SUCCESS;
}
diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c
index c685d546f83..b2002ba6e2a 100644
--- a/drivers/scsi/NCR53c406a.c
+++ b/drivers/scsi/NCR53c406a.c
@@ -722,15 +722,12 @@ static int NCR53c406a_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
return 0;
}
-static int NCR53c406a_abort(Scsi_Cmnd * SCpnt)
-{
- DEB(printk("NCR53c406a_abort called\n"));
- return FAILED; /* Don't know how to abort */
-}
-
static int NCR53c406a_host_reset(Scsi_Cmnd * SCpnt)
{
DEB(printk("NCR53c406a_reset called\n"));
+
+ spin_lock_irq(SCpnt->device->host->host_lock);
+
outb(C4_IMG, CONFIG4); /* Select reg set 0 */
outb(CHIP_RESET, CMD_REG);
outb(SCSI_NOP, CMD_REG); /* required after reset */
@@ -738,17 +735,10 @@ static int NCR53c406a_host_reset(Scsi_Cmnd * SCpnt)
chip_init();
rtrc(2);
- return SUCCESS;
-}
-static int NCR53c406a_device_reset(Scsi_Cmnd * SCpnt)
-{
- return FAILED;
-}
+ spin_unlock_irq(SCpnt->device->host->host_lock);
-static int NCR53c406a_bus_reset(Scsi_Cmnd * SCpnt)
-{
- return FAILED;
+ return SUCCESS;
}
static int NCR53c406a_biosparm(struct scsi_device *disk,
@@ -1075,9 +1065,6 @@ static Scsi_Host_Template driver_template =
.release = NCR53c406a_release,
.info = NCR53c406a_info /* info */,
.queuecommand = NCR53c406a_queue /* queuecommand */,
- .eh_abort_handler = NCR53c406a_abort /* abort */,
- .eh_bus_reset_handler = NCR53c406a_bus_reset /* reset */,
- .eh_device_reset_handler = NCR53c406a_device_reset /* reset */,
.eh_host_reset_handler = NCR53c406a_host_reset /* reset */,
.bios_param = NCR53c406a_biosparm /* biosparm */,
.can_queue = 1 /* can_queue */,
diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c
index 9928a2fbce0..f7a1751e892 100644
--- a/drivers/scsi/a2091.c
+++ b/drivers/scsi/a2091.c
@@ -221,7 +221,14 @@ int __init a2091_detect(Scsi_Host_Template *tpnt)
static int a2091_bus_reset(Scsi_Cmnd *cmd)
{
/* FIXME perform bus-specific reset */
+
+ /* FIXME 2: kill this function, and let midlayer fall back
+ to the same action, calling wd33c93_host_reset() */
+
+ spin_lock_irq(cmd->device->host->host_lock);
wd33c93_host_reset(cmd);
+ spin_unlock_irq(cmd->device->host->host_lock);
+
return SUCCESS;
}
diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c
index f8a89ec2504..306caf56f3d 100644
--- a/drivers/scsi/a3000.c
+++ b/drivers/scsi/a3000.c
@@ -208,7 +208,14 @@ fail_register:
static int a3000_bus_reset(Scsi_Cmnd *cmd)
{
/* FIXME perform bus-specific reset */
+
+ /* FIXME 2: kill this entire function, which should
+ cause mid-layer to call wd33c93_host_reset anyway? */
+
+ spin_lock_irq(cmd->device->host->host_lock);
wd33c93_host_reset(cmd);
+ spin_unlock_irq(cmd->device->host->host_lock);
+
return SUCCESS;
}
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index f3fc3538606..f02c9964146 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -53,10 +53,6 @@
#define INQD_PDT_DMASK 0x1F /* Peripheral Device Type Mask */
#define INQD_PDT_QMASK 0xE0 /* Peripheral Device Qualifer Mask */
-#define MAX_FIB_DATA (sizeof(struct hw_fib) - sizeof(FIB_HEADER))
-
-#define MAX_DRIVER_SG_SEGMENT_COUNT 17
-
/*
* Sense codes
*/
@@ -158,6 +154,13 @@ MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC. 0
module_param(commit, int, 0);
MODULE_PARM_DESC(commit, "Control whether a COMMIT_CONFIG is issued to the adapter for foreign arrays.\nThis is typically needed in systems that do not have a BIOS. 0=off, 1=on");
+int numacb = -1;
+module_param(numacb, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(numacb, "Request a limit to the number of adapter control blocks (FIB) allocated. Valid\nvalues are 512 and down. Default is to use suggestion from Firmware.");
+
+int acbsize = -1;
+module_param(acbsize, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. Valid values are 512,\n2048, 4096 and 8192. Default is to use suggestion from Firmware.");
/**
* aac_get_config_status - check the adapter configuration
* @common: adapter to query
@@ -462,7 +465,7 @@ static int probe_container(struct aac_dev *dev, int cid)
1, 1,
NULL, NULL);
if (status < 0) {
- printk(KERN_WARNING "aacraid: probe_containers query failed.\n");
+ printk(KERN_WARNING "aacraid: probe_container query failed.\n");
goto error;
}
@@ -562,10 +565,10 @@ static void setinqstr(int devtype, void *data, int tindex)
inqstrcpy ("V1.0", str->prl);
}
-void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code,
- u8 a_sense_code, u8 incorrect_length,
- u8 bit_pointer, u16 field_pointer,
- u32 residue)
+static void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code,
+ u8 a_sense_code, u8 incorrect_length,
+ u8 bit_pointer, u16 field_pointer,
+ u32 residue)
{
sense_buf[0] = 0xF0; /* Sense data valid, err code 70h (current error) */
sense_buf[1] = 0; /* Segment number, always zero */
@@ -605,35 +608,63 @@ void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code,
int aac_get_adapter_info(struct aac_dev* dev)
{
struct fib* fibptr;
- struct aac_adapter_info* info;
int rcode;
u32 tmp;
+ struct aac_adapter_info * info;
+
if (!(fibptr = fib_alloc(dev)))
return -ENOMEM;
fib_init(fibptr);
- info = (struct aac_adapter_info*) fib_data(fibptr);
-
- memset(info,0,sizeof(struct aac_adapter_info));
+ info = (struct aac_adapter_info *) fib_data(fibptr);
+ memset(info,0,sizeof(*info));
rcode = fib_send(RequestAdapterInfo,
- fibptr,
- sizeof(struct aac_adapter_info),
- FsaNormal,
- 1, 1,
- NULL,
- NULL);
+ fibptr,
+ sizeof(*info),
+ FsaNormal,
+ 1, 1,
+ NULL,
+ NULL);
+
+ if (rcode < 0) {
+ fib_complete(fibptr);
+ fib_free(fibptr);
+ return rcode;
+ }
+ memcpy(&dev->adapter_info, info, sizeof(*info));
+
+ if (dev->adapter_info.options & AAC_OPT_SUPPLEMENT_ADAPTER_INFO) {
+ struct aac_supplement_adapter_info * info;
- memcpy(&dev->adapter_info, info, sizeof(struct aac_adapter_info));
+ fib_init(fibptr);
+
+ info = (struct aac_supplement_adapter_info *) fib_data(fibptr);
+
+ memset(info,0,sizeof(*info));
+
+ rcode = fib_send(RequestSupplementAdapterInfo,
+ fibptr,
+ sizeof(*info),
+ FsaNormal,
+ 1, 1,
+ NULL,
+ NULL);
+
+ if (rcode >= 0)
+ memcpy(&dev->supplement_adapter_info, info, sizeof(*info));
+ }
tmp = le32_to_cpu(dev->adapter_info.kernelrev);
- printk(KERN_INFO "%s%d: kernel %d.%d-%d[%d]\n",
+ printk(KERN_INFO "%s%d: kernel %d.%d-%d[%d] %.*s\n",
dev->name,
dev->id,
tmp>>24,
(tmp>>16)&0xff,
tmp&0xff,
- le32_to_cpu(dev->adapter_info.kernelbuild));
+ le32_to_cpu(dev->adapter_info.kernelbuild),
+ (int)sizeof(dev->supplement_adapter_info.BuildDate),
+ dev->supplement_adapter_info.BuildDate);
tmp = le32_to_cpu(dev->adapter_info.monitorrev);
printk(KERN_INFO "%s%d: monitor %d.%d-%d[%d]\n",
dev->name, dev->id,
@@ -707,6 +738,38 @@ int aac_get_adapter_info(struct aac_dev* dev)
rcode = -ENOMEM;
}
}
+ /*
+ * 57 scatter gather elements
+ */
+ dev->scsi_host_ptr->sg_tablesize = (dev->max_fib_size -
+ sizeof(struct aac_fibhdr) -
+ sizeof(struct aac_write) + sizeof(struct sgmap)) /
+ sizeof(struct sgmap);
+ if (dev->dac_support) {
+ /*
+ * 38 scatter gather elements
+ */
+ dev->scsi_host_ptr->sg_tablesize =
+ (dev->max_fib_size -
+ sizeof(struct aac_fibhdr) -
+ sizeof(struct aac_write64) +
+ sizeof(struct sgmap64)) /
+ sizeof(struct sgmap64);
+ }
+ dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT;
+ if(!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) {
+ /*
+ * Worst case size that could cause sg overflow when
+ * we break up SG elements that are larger than 64KB.
+ * Would be nice if we could tell the SCSI layer what
+ * the maximum SG element size can be. Worst case is
+ * (sg_tablesize-1) 4KB elements with one 64KB
+ * element.
+ * 32bit -> 468 or 238KB 64bit -> 424 or 212KB
+ */
+ dev->scsi_host_ptr->max_sectors =
+ (dev->scsi_host_ptr->sg_tablesize * 8) + 112;
+ }
fib_complete(fibptr);
fib_free(fibptr);
@@ -747,8 +810,10 @@ static void read_callback(void *context, struct fib * fibptr)
if (le32_to_cpu(readreply->status) == ST_OK)
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
else {
- printk(KERN_WARNING "read_callback: read failed, status = %d\n",
- le32_to_cpu(readreply->status));
+#ifdef AAC_DETAILED_STATUS_INFO
+ printk(KERN_WARNING "read_callback: io failed, status = %d\n",
+ le32_to_cpu(readreply->status));
+#endif
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
HARDWARE_ERROR,
@@ -813,7 +878,7 @@ static void write_callback(void *context, struct fib * fibptr)
aac_io_done(scsicmd);
}
-int aac_read(struct scsi_cmnd * scsicmd, int cid)
+static int aac_read(struct scsi_cmnd * scsicmd, int cid)
{
u32 lba;
u32 count;
@@ -842,7 +907,8 @@ int aac_read(struct scsi_cmnd * scsicmd, int cid)
lba = (scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
}
- dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies));
+ dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %u, t = %ld.\n",
+ smp_processor_id(), (unsigned long long)lba, jiffies));
/*
* Alocate and initialize a Fib
*/
@@ -852,7 +918,7 @@ int aac_read(struct scsi_cmnd * scsicmd, int cid)
fib_init(cmd_fibcontext);
- if(dev->dac_support == 1) {
+ if (dev->dac_support == 1) {
struct aac_read64 *readcmd;
readcmd = (struct aac_read64 *) fib_data(cmd_fibcontext);
readcmd->command = cpu_to_le32(VM_CtHostRead64);
@@ -886,14 +952,11 @@ int aac_read(struct scsi_cmnd * scsicmd, int cid)
readcmd->block = cpu_to_le32(lba);
readcmd->count = cpu_to_le32(count * 512);
- if (count * 512 > (64 * 1024))
- BUG();
-
aac_build_sg(scsicmd, &readcmd->sg);
fibsize = sizeof(struct aac_read) +
((le32_to_cpu(readcmd->sg.count) - 1) *
sizeof (struct sgentry));
- BUG_ON (fibsize > (sizeof(struct hw_fib) -
+ BUG_ON (fibsize > (dev->max_fib_size -
sizeof(struct aac_fibhdr)));
/*
* Now send the Fib to the adapter
@@ -976,7 +1039,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
fibsize = sizeof(struct aac_write64) +
((le32_to_cpu(writecmd->sg.count) - 1) *
sizeof (struct sgentry64));
- BUG_ON (fibsize > (sizeof(struct hw_fib) -
+ BUG_ON (fibsize > (dev->max_fib_size -
sizeof(struct aac_fibhdr)));
/*
* Now send the Fib to the adapter
@@ -998,15 +1061,11 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
writecmd->sg.count = cpu_to_le32(1);
/* ->stable is not used - it did mean which type of write */
- if (count * 512 > (64 * 1024)) {
- BUG();
- }
-
aac_build_sg(scsicmd, &writecmd->sg);
fibsize = sizeof(struct aac_write) +
((le32_to_cpu(writecmd->sg.count) - 1) *
sizeof (struct sgentry));
- BUG_ON (fibsize > (sizeof(struct hw_fib) -
+ BUG_ON (fibsize > (dev->max_fib_size -
sizeof(struct aac_fibhdr)));
/*
* Now send the Fib to the adapter
@@ -1025,7 +1084,6 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
*/
if (status == -EINPROGRESS)
{
- dprintk("write queued.\n");
return 0;
}
@@ -1111,7 +1169,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
return SCSI_MLQUEUE_DEVICE_BUSY;
/*
- * Alocate and initialize a Fib
+ * Allocate and initialize a Fib
*/
if (!(cmd_fibcontext =
fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata)))
@@ -1403,7 +1461,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
/*
* Unhandled commands
*/
- printk(KERN_WARNING "Unhandled SCSI Command: 0x%x.\n", scsicmd->cmnd[0]);
+ dprintk((KERN_WARNING "Unhandled SCSI Command: 0x%x.\n", scsicmd->cmnd[0]));
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
ILLEGAL_REQUEST, SENCODE_INVALID_COMMAND,
@@ -1818,7 +1876,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
fibsize = sizeof (struct aac_srb) - sizeof (struct sgentry) +
((le32_to_cpu(srbcmd->sg.count) & 0xff) *
sizeof (struct sgentry64));
- BUG_ON (fibsize > (sizeof(struct hw_fib) -
+ BUG_ON (fibsize > (dev->max_fib_size -
sizeof(struct aac_fibhdr)));
/*
@@ -1840,7 +1898,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
fibsize = sizeof (struct aac_srb) +
(((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) *
sizeof (struct sgentry));
- BUG_ON (fibsize > (sizeof(struct hw_fib) -
+ BUG_ON (fibsize > (dev->max_fib_size -
sizeof(struct aac_fibhdr)));
/*
@@ -1893,7 +1951,9 @@ static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* psg)
}
/* hba wants the size to be exact */
if(byte_count > scsicmd->request_bufflen){
- psg->sg[i-1].count -= (byte_count - scsicmd->request_bufflen);
+ u32 temp = le32_to_cpu(psg->sg[i-1].count) -
+ (byte_count - scsicmd->request_bufflen);
+ psg->sg[i-1].count = cpu_to_le32(temp);
byte_count = scsicmd->request_bufflen;
}
/* Check for command underflow */
@@ -1922,7 +1982,7 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p
{
struct aac_dev *dev;
unsigned long byte_count = 0;
- u64 le_addr;
+ u64 addr;
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
// Get rid of old data
@@ -1943,16 +2003,18 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p
byte_count = 0;
for (i = 0; i < sg_count; i++) {
- le_addr = cpu_to_le64(sg_dma_address(sg));
- psg->sg[i].addr[1] = (u32)(le_addr>>32);
- psg->sg[i].addr[0] = (u32)(le_addr & 0xffffffff);
+ addr = sg_dma_address(sg);
+ psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
+ psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
psg->sg[i].count = cpu_to_le32(sg_dma_len(sg));
byte_count += sg_dma_len(sg);
sg++;
}
/* hba wants the size to be exact */
if(byte_count > scsicmd->request_bufflen){
- psg->sg[i-1].count -= (byte_count - scsicmd->request_bufflen);
+ u32 temp = le32_to_cpu(psg->sg[i-1].count) -
+ (byte_count - scsicmd->request_bufflen);
+ psg->sg[i-1].count = cpu_to_le32(temp);
byte_count = scsicmd->request_bufflen;
}
/* Check for command underflow */
@@ -1962,15 +2024,14 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p
}
}
else if(scsicmd->request_bufflen) {
- dma_addr_t addr;
+ u64 addr;
addr = pci_map_single(dev->pdev,
scsicmd->request_buffer,
scsicmd->request_bufflen,
scsicmd->sc_data_direction);
psg->count = cpu_to_le32(1);
- le_addr = cpu_to_le64(addr);
- psg->sg[0].addr[1] = (u32)(le_addr>>32);
- psg->sg[0].addr[0] = (u32)(le_addr & 0xffffffff);
+ psg->sg[0].addr[0] = cpu_to_le32(addr & 0xffffffff);
+ psg->sg[0].addr[1] = cpu_to_le32(addr >> 32);
psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen);
scsicmd->SCp.dma_handle = addr;
byte_count = scsicmd->request_bufflen;
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 700d90331c1..42484417cef 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -8,12 +8,18 @@
#define MAXIMUM_NUM_CONTAINERS 32
-#define AAC_NUM_FIB (256 + 64)
-#define AAC_NUM_IO_FIB 100
+#define AAC_NUM_MGT_FIB 8
+#define AAC_NUM_IO_FIB (512 - AAC_NUM_MGT_FIB)
+#define AAC_NUM_FIB (AAC_NUM_IO_FIB + AAC_NUM_MGT_FIB)
#define AAC_MAX_LUN (8)
#define AAC_MAX_HOSTPHYSMEMPAGES (0xfffff)
+/*
+ * max_sectors is an unsigned short, otherwise limit is 0x100000000 / 512
+ * Linux has starvation problems if we permit larger than 4MB I/O ...
+ */
+#define AAC_MAX_32BIT_SGBCOUNT ((unsigned short)8192)
/*
* These macros convert from physical channels to virtual channels
@@ -89,11 +95,21 @@ struct diskparm
* on 64 bit systems not all cards support the 64 bit version
*/
struct sgentry {
+ __le32 addr; /* 32-bit address. */
+ __le32 count; /* Length. */
+};
+
+struct user_sgentry {
u32 addr; /* 32-bit address. */
u32 count; /* Length. */
};
struct sgentry64 {
+ __le32 addr[2]; /* 64-bit addr. 2 pieces for data alignment */
+ __le32 count; /* Length. */
+};
+
+struct user_sgentry64 {
u32 addr[2]; /* 64-bit addr. 2 pieces for data alignment */
u32 count; /* Length. */
};
@@ -106,15 +122,25 @@ struct sgentry64 {
*/
struct sgmap {
- u32 count;
+ __le32 count;
struct sgentry sg[1];
};
-struct sgmap64 {
+struct user_sgmap {
u32 count;
+ struct user_sgentry sg[1];
+};
+
+struct sgmap64 {
+ __le32 count;
struct sgentry64 sg[1];
};
+struct user_sgmap64 {
+ u32 count;
+ struct user_sgentry64 sg[1];
+};
+
struct creation_info
{
u8 buildnum; /* e.g., 588 */
@@ -123,14 +149,14 @@ struct creation_info
* 2 = API
*/
u8 year; /* e.g., 1997 = 97 */
- u32 date; /*
+ __le32 date; /*
* unsigned Month :4; // 1 - 12
* unsigned Day :6; // 1 - 32
* unsigned Hour :6; // 0 - 23
* unsigned Minute :6; // 0 - 60
* unsigned Second :6; // 0 - 60
*/
- u32 serial[2]; /* e.g., 0x1DEADB0BFAFAF001 */
+ __le32 serial[2]; /* e.g., 0x1DEADB0BFAFAF001 */
};
@@ -175,8 +201,8 @@ struct creation_info
*/
struct aac_entry {
- u32 size; /* Size in bytes of Fib which this QE points to */
- u32 addr; /* Receiver address of the FIB */
+ __le32 size; /* Size in bytes of Fib which this QE points to */
+ __le32 addr; /* Receiver address of the FIB */
};
/*
@@ -185,9 +211,10 @@ struct aac_entry {
*/
struct aac_qhdr {
- u64 header_addr; /* Address to hand the adapter to access to this queue head */
- u32 *producer; /* The producer index for this queue (host address) */
- u32 *consumer; /* The consumer index for this queue (host address) */
+ __le64 header_addr;/* Address to hand the adapter to access
+ to this queue head */
+ __le32 *producer; /* The producer index for this queue (host address) */
+ __le32 *consumer; /* The consumer index for this queue (host address) */
};
/*
@@ -261,29 +288,30 @@ enum aac_queue_types {
*/
struct aac_fibhdr {
- u32 XferState; // Current transfer state for this CCB
- u16 Command; // Routing information for the destination
- u8 StructType; // Type FIB
- u8 Flags; // Flags for FIB
- u16 Size; // Size of this FIB in bytes
- u16 SenderSize; // Size of the FIB in the sender (for response sizing)
- u32 SenderFibAddress; // Host defined data in the FIB
- u32 ReceiverFibAddress; // Logical address of this FIB for the adapter
- u32 SenderData; // Place holder for the sender to store data
+ __le32 XferState; /* Current transfer state for this CCB */
+ __le16 Command; /* Routing information for the destination */
+ u8 StructType; /* Type FIB */
+ u8 Flags; /* Flags for FIB */
+ __le16 Size; /* Size of this FIB in bytes */
+ __le16 SenderSize; /* Size of the FIB in the sender
+ (for response sizing) */
+ __le32 SenderFibAddress; /* Host defined data in the FIB */
+ __le32 ReceiverFibAddress;/* Logical address of this FIB for
+ the adapter */
+ u32 SenderData; /* Place holder for the sender to store data */
union {
struct {
- u32 _ReceiverTimeStart; // Timestamp for receipt of fib
- u32 _ReceiverTimeDone; // Timestamp for completion of fib
+ __le32 _ReceiverTimeStart; /* Timestamp for
+ receipt of fib */
+ __le32 _ReceiverTimeDone; /* Timestamp for
+ completion of fib */
} _s;
} _u;
};
-#define FIB_DATA_SIZE_IN_BYTES (512 - sizeof(struct aac_fibhdr))
-
-
struct hw_fib {
struct aac_fibhdr header;
- u8 data[FIB_DATA_SIZE_IN_BYTES]; // Command specific data
+ u8 data[512-sizeof(struct aac_fibhdr)]; // Command specific data
};
/*
@@ -345,11 +373,12 @@ struct hw_fib {
#define RequestAdapterInfo 703
#define IsAdapterPaused 704
#define SendHostTime 705
-#define LastMiscCommand 706
+#define RequestSupplementAdapterInfo 706
+#define LastMiscCommand 707
-//
-// Commands that will target the failover level on the FSA adapter
-//
+/*
+ * Commands that will target the failover level on the FSA adapter
+ */
enum fib_xfer_state {
HostOwned = (1<<0),
@@ -382,22 +411,32 @@ enum fib_xfer_state {
*/
#define ADAPTER_INIT_STRUCT_REVISION 3
+#define ADAPTER_INIT_STRUCT_REVISION_4 4 // rocket science
struct aac_init
{
- u32 InitStructRevision;
- u32 MiniPortRevision;
- u32 fsrev;
- u32 CommHeaderAddress;
- u32 FastIoCommAreaAddress;
- u32 AdapterFibsPhysicalAddress;
- u32 AdapterFibsVirtualAddress;
- u32 AdapterFibsSize;
- u32 AdapterFibAlign;
- u32 printfbuf;
- u32 printfbufsiz;
- u32 HostPhysMemPages; // number of 4k pages of host physical memory
- u32 HostElapsedSeconds; // number of seconds since 1970.
+ __le32 InitStructRevision;
+ __le32 MiniPortRevision;
+ __le32 fsrev;
+ __le32 CommHeaderAddress;
+ __le32 FastIoCommAreaAddress;
+ __le32 AdapterFibsPhysicalAddress;
+ __le32 AdapterFibsVirtualAddress;
+ __le32 AdapterFibsSize;
+ __le32 AdapterFibAlign;
+ __le32 printfbuf;
+ __le32 printfbufsiz;
+ __le32 HostPhysMemPages; /* number of 4k pages of host
+ physical memory */
+ __le32 HostElapsedSeconds; /* number of seconds since 1970. */
+ /*
+ * ADAPTER_INIT_STRUCT_REVISION_4 begins here
+ */
+ __le32 InitFlags; /* flags for supported features */
+#define INITFLAGS_NEW_COMM_SUPPORTED 0x00000001
+ __le32 MaxIoCommands; /* max outstanding commands */
+ __le32 MaxIoSize; /* largest I/O command */
+ __le32 MaxFibSize; /* largest FIB to adapter */
};
enum aac_log_level {
@@ -421,7 +460,7 @@ struct adapter_ops
{
void (*adapter_interrupt)(struct aac_dev *dev);
void (*adapter_notify)(struct aac_dev *dev, u32 event);
- int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 *status);
+ int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4);
int (*adapter_check_health)(struct aac_dev *dev);
};
@@ -541,6 +580,7 @@ struct sa_drawbridge_CSR {
#define Mailbox3 SaDbCSR.MAILBOX3
#define Mailbox4 SaDbCSR.MAILBOX4
#define Mailbox5 SaDbCSR.MAILBOX5
+#define Mailbox6 SaDbCSR.MAILBOX6
#define Mailbox7 SaDbCSR.MAILBOX7
#define DoorbellReg_p SaDbCSR.PRISETIRQ
@@ -763,29 +803,48 @@ struct fib {
struct aac_adapter_info
{
- u32 platform;
- u32 cpu;
- u32 subcpu;
- u32 clock;
- u32 execmem;
- u32 buffermem;
- u32 totalmem;
- u32 kernelrev;
- u32 kernelbuild;
- u32 monitorrev;
- u32 monitorbuild;
- u32 hwrev;
- u32 hwbuild;
- u32 biosrev;
- u32 biosbuild;
- u32 cluster;
- u32 clusterchannelmask;
- u32 serial[2];
- u32 battery;
- u32 options;
- u32 OEM;
+ __le32 platform;
+ __le32 cpu;
+ __le32 subcpu;
+ __le32 clock;
+ __le32 execmem;
+ __le32 buffermem;
+ __le32 totalmem;
+ __le32 kernelrev;
+ __le32 kernelbuild;
+ __le32 monitorrev;
+ __le32 monitorbuild;
+ __le32 hwrev;
+ __le32 hwbuild;
+ __le32 biosrev;
+ __le32 biosbuild;
+ __le32 cluster;
+ __le32 clusterchannelmask;
+ __le32 serial[2];
+ __le32 battery;
+ __le32 options;
+ __le32 OEM;
};
+struct aac_supplement_adapter_info
+{
+ u8 AdapterTypeText[17+1];
+ u8 Pad[2];
+ __le32 FlashMemoryByteSize;
+ __le32 FlashImageId;
+ __le32 MaxNumberPorts;
+ __le32 Version;
+ __le32 FeatureBits;
+ u8 SlotNumber;
+ u8 ReservedPad0[0];
+ u8 BuildDate[12];
+ __le32 CurrentNumberPorts;
+ __le32 ReservedGrowth[24];
+};
+#define AAC_FEATURE_FALCON 0x00000010
+#define AAC_SIS_VERSION_V3 3
+#define AAC_SIS_SLOT_UNKNOWN 0xFF
+
/*
* Battery platforms
*/
@@ -831,6 +890,12 @@ struct aac_dev
u16 irq_mask;
/*
+ * negotiated FIB settings
+ */
+ unsigned max_fib_size;
+ unsigned sg_tablesize;
+
+ /*
* Map for 128 fib objects (64k)
*/
dma_addr_t hw_fib_pa;
@@ -889,12 +954,14 @@ struct aac_dev
u32 aif_thread;
struct completion aif_completion;
struct aac_adapter_info adapter_info;
+ struct aac_supplement_adapter_info supplement_adapter_info;
/* These are in adapter info but they are in the io flow so
* lets break them out so we don't have to do an AND to check them
*/
u8 nondasd_support;
u8 dac_support;
u8 raid_scsi_mode;
+ u8 printf_enabled;
};
#define aac_adapter_interrupt(dev) \
@@ -903,6 +970,8 @@ struct aac_dev
#define aac_adapter_notify(dev, event) \
(dev)->a_ops.adapter_notify(dev, event)
+#define aac_adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4) \
+ (dev)->a_ops.adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4)
#define aac_adapter_check_health(dev) \
(dev)->a_ops.adapter_check_health(dev)
@@ -1016,83 +1085,102 @@ struct aac_dev
struct aac_read
{
- u32 command;
- u32 cid;
- u32 block;
- u32 count;
+ __le32 command;
+ __le32 cid;
+ __le32 block;
+ __le32 count;
struct sgmap sg; // Must be last in struct because it is variable
};
struct aac_read64
{
- u32 command;
- u16 cid;
- u16 sector_count;
- u32 block;
- u16 pad;
- u16 flags;
+ __le32 command;
+ __le16 cid;
+ __le16 sector_count;
+ __le32 block;
+ __le16 pad;
+ __le16 flags;
struct sgmap64 sg; // Must be last in struct because it is variable
};
struct aac_read_reply
{
- u32 status;
- u32 count;
+ __le32 status;
+ __le32 count;
};
struct aac_write
{
- u32 command;
- u32 cid;
- u32 block;
- u32 count;
- u32 stable; // Not used
+ __le32 command;
+ __le32 cid;
+ __le32 block;
+ __le32 count;
+ __le32 stable; // Not used
struct sgmap sg; // Must be last in struct because it is variable
};
struct aac_write64
{
- u32 command;
- u16 cid;
- u16 sector_count;
- u32 block;
- u16 pad;
- u16 flags;
+ __le32 command;
+ __le16 cid;
+ __le16 sector_count;
+ __le32 block;
+ __le16 pad;
+ __le16 flags;
struct sgmap64 sg; // Must be last in struct because it is variable
};
struct aac_write_reply
{
- u32 status;
- u32 count;
- u32 committed;
+ __le32 status;
+ __le32 count;
+ __le32 committed;
};
#define CT_FLUSH_CACHE 129
struct aac_synchronize {
- u32 command; /* VM_ContainerConfig */
- u32 type; /* CT_FLUSH_CACHE */
- u32 cid;
- u32 parm1;
- u32 parm2;
- u32 parm3;
- u32 parm4;
- u32 count; /* sizeof(((struct aac_synchronize_reply *)NULL)->data) */
+ __le32 command; /* VM_ContainerConfig */
+ __le32 type; /* CT_FLUSH_CACHE */
+ __le32 cid;
+ __le32 parm1;
+ __le32 parm2;
+ __le32 parm3;
+ __le32 parm4;
+ __le32 count; /* sizeof(((struct aac_synchronize_reply *)NULL)->data) */
};
struct aac_synchronize_reply {
- u32 dummy0;
- u32 dummy1;
- u32 status; /* CT_OK */
- u32 parm1;
- u32 parm2;
- u32 parm3;
- u32 parm4;
- u32 parm5;
+ __le32 dummy0;
+ __le32 dummy1;
+ __le32 status; /* CT_OK */
+ __le32 parm1;
+ __le32 parm2;
+ __le32 parm3;
+ __le32 parm4;
+ __le32 parm5;
u8 data[16];
};
struct aac_srb
{
+ __le32 function;
+ __le32 channel;
+ __le32 id;
+ __le32 lun;
+ __le32 timeout;
+ __le32 flags;
+ __le32 count; // Data xfer size
+ __le32 retry_limit;
+ __le32 cdb_size;
+ u8 cdb[16];
+ struct sgmap sg;
+};
+
+/*
+ * This and assocated data structs are used by the
+ * ioctl caller and are in cpu order.
+ */
+struct user_aac_srb
+{
u32 function;
u32 channel;
u32 id;
@@ -1103,20 +1191,18 @@ struct aac_srb
u32 retry_limit;
u32 cdb_size;
u8 cdb[16];
- struct sgmap sg;
+ struct user_sgmap sg;
};
-
-
#define AAC_SENSE_BUFFERSIZE 30
struct aac_srb_reply
{
- u32 status;
- u32 srb_status;
- u32 scsi_status;
- u32 data_xfer_length;
- u32 sense_data_size;
+ __le32 status;
+ __le32 srb_status;
+ __le32 scsi_status;
+ __le32 data_xfer_length;
+ __le32 sense_data_size;
u8 sense_data[AAC_SENSE_BUFFERSIZE]; // Can this be SCSI_SENSE_BUFFERSIZE
};
/*
@@ -1223,14 +1309,14 @@ struct aac_srb_reply
*/
struct aac_fsinfo {
- u32 fsTotalSize; /* Consumed by fs, incl. metadata */
- u32 fsBlockSize;
- u32 fsFragSize;
- u32 fsMaxExtendSize;
- u32 fsSpaceUnits;
- u32 fsMaxNumFiles;
- u32 fsNumFreeFiles;
- u32 fsInodeDensity;
+ __le32 fsTotalSize; /* Consumed by fs, incl. metadata */
+ __le32 fsBlockSize;
+ __le32 fsFragSize;
+ __le32 fsMaxExtendSize;
+ __le32 fsSpaceUnits;
+ __le32 fsMaxNumFiles;
+ __le32 fsNumFreeFiles;
+ __le32 fsInodeDensity;
}; /* valid iff ObjType == FT_FILESYS && !(ContentState & FSCS_NOTCLEAN) */
union aac_contentinfo {
@@ -1243,32 +1329,32 @@ union aac_contentinfo {
#define CT_GET_CONFIG_STATUS 147
struct aac_get_config_status {
- u32 command; /* VM_ContainerConfig */
- u32 type; /* CT_GET_CONFIG_STATUS */
- u32 parm1;
- u32 parm2;
- u32 parm3;
- u32 parm4;
- u32 parm5;
- u32 count; /* sizeof(((struct aac_get_config_status_resp *)NULL)->data) */
+ __le32 command; /* VM_ContainerConfig */
+ __le32 type; /* CT_GET_CONFIG_STATUS */
+ __le32 parm1;
+ __le32 parm2;
+ __le32 parm3;
+ __le32 parm4;
+ __le32 parm5;
+ __le32 count; /* sizeof(((struct aac_get_config_status_resp *)NULL)->data) */
};
#define CFACT_CONTINUE 0
#define CFACT_PAUSE 1
#define CFACT_ABORT 2
struct aac_get_config_status_resp {
- u32 response; /* ST_OK */
- u32 dummy0;
- u32 status; /* CT_OK */
- u32 parm1;
- u32 parm2;
- u32 parm3;
- u32 parm4;
- u32 parm5;
+ __le32 response; /* ST_OK */
+ __le32 dummy0;
+ __le32 status; /* CT_OK */
+ __le32 parm1;
+ __le32 parm2;
+ __le32 parm3;
+ __le32 parm4;
+ __le32 parm5;
struct {
- u32 action; /* CFACT_CONTINUE, CFACT_PAUSE or CFACT_ABORT */
- u16 flags;
- s16 count;
+ __le32 action; /* CFACT_CONTINUE, CFACT_PAUSE or CFACT_ABORT */
+ __le16 flags;
+ __le16 count;
} data;
};
@@ -1279,26 +1365,26 @@ struct aac_get_config_status_resp {
#define CT_COMMIT_CONFIG 152
struct aac_commit_config {
- u32 command; /* VM_ContainerConfig */
- u32 type; /* CT_COMMIT_CONFIG */
+ __le32 command; /* VM_ContainerConfig */
+ __le32 type; /* CT_COMMIT_CONFIG */
};
/*
- * Query for Container Configuration Count
+ * Query for Container Configuration Status
*/
#define CT_GET_CONTAINER_COUNT 4
struct aac_get_container_count {
- u32 command; /* VM_ContainerConfig */
- u32 type; /* CT_GET_CONTAINER_COUNT */
+ __le32 command; /* VM_ContainerConfig */
+ __le32 type; /* CT_GET_CONTAINER_COUNT */
};
struct aac_get_container_count_resp {
- u32 response; /* ST_OK */
- u32 dummy0;
- u32 MaxContainers;
- u32 ContainerSwitchEntries;
- u32 MaxPartitions;
+ __le32 response; /* ST_OK */
+ __le32 dummy0;
+ __le32 MaxContainers;
+ __le32 ContainerSwitchEntries;
+ __le32 MaxPartitions;
};
@@ -1308,15 +1394,19 @@ struct aac_get_container_count_resp {
*/
struct aac_mntent {
- u32 oid;
- u8 name[16]; // if applicable
- struct creation_info create_info; // if applicable
- u32 capacity;
- u32 vol; // substrate structure
- u32 obj; // FT_FILESYS, FT_DATABASE, etc.
- u32 state; // unready for mounting, readonly, etc.
- union aac_contentinfo fileinfo; // Info specific to content manager (eg, filesystem)
- u32 altoid; // != oid <==> snapshot or broken mirror exists
+ __le32 oid;
+ u8 name[16]; /* if applicable */
+ struct creation_info create_info; /* if applicable */
+ __le32 capacity;
+ __le32 vol; /* substrate structure */
+ __le32 obj; /* FT_FILESYS,
+ FT_DATABASE, etc. */
+ __le32 state; /* unready for mounting,
+ readonly, etc. */
+ union aac_contentinfo fileinfo; /* Info specific to content
+ manager (eg, filesystem) */
+ __le32 altoid; /* != oid <==> snapshot or
+ broken mirror exists */
};
#define FSCS_NOTCLEAN 0x0001 /* fsck is neccessary before mounting */
@@ -1324,40 +1414,40 @@ struct aac_mntent {
#define FSCS_HIDDEN 0x0004 /* should be ignored - set during a clear */
struct aac_query_mount {
- u32 command;
- u32 type;
- u32 count;
+ __le32 command;
+ __le32 type;
+ __le32 count;
};
struct aac_mount {
- u32 status;
- u32 type; /* should be same as that requested */
- u32 count;
+ __le32 status;
+ __le32 type; /* should be same as that requested */
+ __le32 count;
struct aac_mntent mnt[1];
};
#define CT_READ_NAME 130
struct aac_get_name {
- u32 command; /* VM_ContainerConfig */
- u32 type; /* CT_READ_NAME */
- u32 cid;
- u32 parm1;
- u32 parm2;
- u32 parm3;
- u32 parm4;
- u32 count; /* sizeof(((struct aac_get_name_resp *)NULL)->data) */
+ __le32 command; /* VM_ContainerConfig */
+ __le32 type; /* CT_READ_NAME */
+ __le32 cid;
+ __le32 parm1;
+ __le32 parm2;
+ __le32 parm3;
+ __le32 parm4;
+ __le32 count; /* sizeof(((struct aac_get_name_resp *)NULL)->data) */
};
#define CT_OK 218
struct aac_get_name_resp {
- u32 dummy0;
- u32 dummy1;
- u32 status; /* CT_OK */
- u32 parm1;
- u32 parm2;
- u32 parm3;
- u32 parm4;
- u32 parm5;
+ __le32 dummy0;
+ __le32 dummy1;
+ __le32 status; /* CT_OK */
+ __le32 parm1;
+ __le32 parm2;
+ __le32 parm3;
+ __le32 parm4;
+ __le32 parm5;
u8 data[16];
};
@@ -1366,8 +1456,8 @@ struct aac_get_name_resp {
*/
struct aac_close {
- u32 command;
- u32 cid;
+ __le32 command;
+ __le32 cid;
};
struct aac_query_disk
@@ -1434,6 +1524,7 @@ struct revision
#define FSACTL_GET_PCI_INFO CTL_CODE(2119, METHOD_BUFFERED)
#define FSACTL_FORCE_DELETE_DISK CTL_CODE(2120, METHOD_NEITHER)
#define FSACTL_GET_CONTAINERS 2131
+#define FSACTL_SEND_LARGE_FIB CTL_CODE(2138, METHOD_BUFFERED)
struct aac_common
@@ -1573,8 +1664,8 @@ extern struct aac_common aac_config;
*/
struct aac_aifcmd {
- u32 command; /* Tell host what type of notify this is */
- u32 seqnum; /* To allow ordering of reports (if necessary) */
+ __le32 command; /* Tell host what type of notify this is */
+ __le32 seqnum; /* To allow ordering of reports (if necessary) */
u8 data[1]; /* Undefined length (from kernel viewpoint) */
};
@@ -1597,7 +1688,6 @@ int fib_setup(struct aac_dev *dev);
void fib_map_free(struct aac_dev *dev);
void fib_free(struct fib * context);
void fib_init(struct fib * context);
-void fib_dealloc(struct fib * context);
void aac_printf(struct aac_dev *dev, u32 val);
int fib_send(u16 command, struct fib * context, unsigned long size, int priority, int wait, int reply, fib_callback callback, void *ctxt);
int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry);
@@ -1621,3 +1711,5 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size);
struct aac_driver_ident* aac_get_driver_ident(int devtype);
int aac_get_adapter_info(struct aac_dev* dev);
int aac_send_shutdown(struct aac_dev *dev);
+extern int numacb;
+extern int acbsize;
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index 30dd1f7120f..1fef92d55de 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -51,15 +51,22 @@
* This routine sends a fib to the adapter on behalf of a user level
* program.
*/
+# define AAC_DEBUG_PREAMBLE KERN_INFO
+# define AAC_DEBUG_POSTAMBLE
static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
{
struct hw_fib * kfib;
struct fib *fibptr;
+ struct hw_fib * hw_fib = (struct hw_fib *)0;
+ dma_addr_t hw_fib_pa = (dma_addr_t)0LL;
+ unsigned size;
+ int retval;
fibptr = fib_alloc(dev);
- if(fibptr == NULL)
+ if(fibptr == NULL) {
return -ENOMEM;
+ }
kfib = fibptr->hw_fib;
/*
@@ -74,19 +81,24 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
* will not overrun the buffer when we copy the memory. Return
* an error if we would.
*/
- if (le16_to_cpu(kfib->header.Size) >
- sizeof(struct hw_fib) - sizeof(struct aac_fibhdr)) {
- fib_free(fibptr);
- return -EINVAL;
+ size = le16_to_cpu(kfib->header.Size) + sizeof(struct aac_fibhdr);
+ if (size < le16_to_cpu(kfib->header.SenderSize))
+ size = le16_to_cpu(kfib->header.SenderSize);
+ if (size > dev->max_fib_size) {
+ /* Highjack the hw_fib */
+ hw_fib = fibptr->hw_fib;
+ hw_fib_pa = fibptr->hw_fib_pa;
+ fibptr->hw_fib = kfib = pci_alloc_consistent(dev->pdev, size, &fibptr->hw_fib_pa);
+ memset(((char *)kfib) + dev->max_fib_size, 0, size - dev->max_fib_size);
+ memcpy(kfib, hw_fib, dev->max_fib_size);
}
- if (copy_from_user(kfib, arg, le16_to_cpu(kfib->header.Size) +
- sizeof(struct aac_fibhdr))) {
- fib_free(fibptr);
- return -EFAULT;
+ if (copy_from_user(kfib, arg, size)) {
+ retval = -EFAULT;
+ goto cleanup;
}
- if (kfib->header.Command == cpu_to_le32(TakeABreakPt)) {
+ if (kfib->header.Command == cpu_to_le16(TakeABreakPt)) {
aac_adapter_interrupt(dev);
/*
* Since we didn't really send a fib, zero out the state to allow
@@ -94,16 +106,15 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
*/
kfib->header.XferState = 0;
} else {
- int retval = fib_send(kfib->header.Command, fibptr,
+ retval = fib_send(le16_to_cpu(kfib->header.Command), fibptr,
le16_to_cpu(kfib->header.Size) , FsaNormal,
1, 1, NULL, NULL);
if (retval) {
- fib_free(fibptr);
- return retval;
+ goto cleanup;
}
if (fib_complete(fibptr) != 0) {
- fib_free(fibptr);
- return -EINVAL;
+ retval = -EINVAL;
+ goto cleanup;
}
}
/*
@@ -114,12 +125,17 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
* was already included by the adapter.)
*/
- if (copy_to_user(arg, (void *)kfib, kfib->header.Size)) {
- fib_free(fibptr);
- return -EFAULT;
+ retval = 0;
+ if (copy_to_user(arg, (void *)kfib, size))
+ retval = -EFAULT;
+cleanup:
+ if (hw_fib) {
+ pci_free_consistent(dev->pdev, size, kfib, fibptr->hw_fib_pa);
+ fibptr->hw_fib_pa = hw_fib_pa;
+ fibptr->hw_fib = hw_fib;
}
fib_free(fibptr);
- return 0;
+ return retval;
}
/**
@@ -391,26 +407,28 @@ static int check_revision(struct aac_dev *dev, void __user *arg)
struct revision response;
response.compat = 1;
- response.version = dev->adapter_info.kernelrev;
- response.build = dev->adapter_info.kernelbuild;
+ response.version = le32_to_cpu(dev->adapter_info.kernelrev);
+ response.build = le32_to_cpu(dev->adapter_info.kernelbuild);
if (copy_to_user(arg, &response, sizeof(response)))
return -EFAULT;
return 0;
}
+
/**
*
* aac_send_raw_scb
*
*/
-int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
+static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
{
struct fib* srbfib;
int status;
- struct aac_srb *srbcmd;
- struct aac_srb __user *user_srb = arg;
+ struct aac_srb *srbcmd = NULL;
+ struct user_aac_srb *user_srbcmd = NULL;
+ struct user_aac_srb __user *user_srb = arg;
struct aac_srb_reply __user *user_reply;
struct aac_srb_reply* reply;
u32 fibsize = 0;
@@ -426,50 +444,59 @@ int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
if (!capable(CAP_SYS_ADMIN)){
- printk(KERN_DEBUG"aacraid: No permission to send raw srb\n");
+ dprintk((KERN_DEBUG"aacraid: No permission to send raw srb\n"));
return -EPERM;
}
/*
* Allocate and initialize a Fib then setup a BlockWrite command
*/
if (!(srbfib = fib_alloc(dev))) {
- return -1;
+ return -ENOMEM;
}
fib_init(srbfib);
srbcmd = (struct aac_srb*) fib_data(srbfib);
+ memset(sg_list, 0, sizeof(sg_list)); /* cleanup may take issue */
if(copy_from_user(&fibsize, &user_srb->count,sizeof(u32))){
- printk(KERN_DEBUG"aacraid: Could not copy data size from user\n");
+ dprintk((KERN_DEBUG"aacraid: Could not copy data size from user\n"));
rcode = -EFAULT;
goto cleanup;
}
- if (fibsize > FIB_DATA_SIZE_IN_BYTES) {
+ if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))) {
rcode = -EINVAL;
goto cleanup;
}
- if(copy_from_user(srbcmd, user_srb,fibsize)){
- printk(KERN_DEBUG"aacraid: Could not copy srb from user\n");
+ user_srbcmd = kmalloc(GFP_KERNEL, fibsize);
+ if (!user_srbcmd) {
+ dprintk((KERN_DEBUG"aacraid: Could not make a copy of the srb\n"));
+ rcode = -ENOMEM;
+ goto cleanup;
+ }
+ if(copy_from_user(user_srbcmd, user_srb,fibsize)){
+ dprintk((KERN_DEBUG"aacraid: Could not copy srb from user\n"));
rcode = -EFAULT;
goto cleanup;
}
user_reply = arg+fibsize;
- flags = srbcmd->flags;
+ flags = user_srbcmd->flags; /* from user in cpu order */
// Fix up srb for endian and force some values
+
srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); // Force this
- srbcmd->channel = cpu_to_le32(srbcmd->channel);
- srbcmd->id = cpu_to_le32(srbcmd->id);
- srbcmd->lun = cpu_to_le32(srbcmd->lun);
- srbcmd->flags = cpu_to_le32(srbcmd->flags);
- srbcmd->timeout = cpu_to_le32(srbcmd->timeout);
- srbcmd->retry_limit =cpu_to_le32(0); // Obsolete parameter
- srbcmd->cdb_size = cpu_to_le32(srbcmd->cdb_size);
+ srbcmd->channel = cpu_to_le32(user_srbcmd->channel);
+ srbcmd->id = cpu_to_le32(user_srbcmd->id);
+ srbcmd->lun = cpu_to_le32(user_srbcmd->lun);
+ srbcmd->timeout = cpu_to_le32(user_srbcmd->timeout);
+ srbcmd->flags = cpu_to_le32(flags);
+ srbcmd->retry_limit = 0; // Obsolete parameter
+ srbcmd->cdb_size = cpu_to_le32(user_srbcmd->cdb_size);
+ memcpy(srbcmd->cdb, user_srbcmd->cdb, sizeof(srbcmd->cdb));
- switch (srbcmd->flags & (SRB_DataIn | SRB_DataOut)) {
+ switch (flags & (SRB_DataIn | SRB_DataOut)) {
case SRB_DataOut:
data_dir = DMA_TO_DEVICE;
break;
@@ -482,118 +509,148 @@ int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
default:
data_dir = DMA_NONE;
}
+ if (user_srbcmd->sg.count > (sizeof(sg_list)/sizeof(sg_list[0]))) {
+ dprintk((KERN_DEBUG"aacraid: too many sg entries %d\n",
+ le32_to_cpu(srbcmd->sg.count)));
+ rcode = -EINVAL;
+ goto cleanup;
+ }
if (dev->dac_support == 1) {
- struct sgmap64* psg = (struct sgmap64*)&srbcmd->sg;
+ struct user_sgmap64* upsg = (struct user_sgmap64*)&user_srbcmd->sg;
+ struct sgmap64* psg = (struct sgmap64*)&user_srbcmd->sg;
+ struct user_sgmap* usg;
byte_count = 0;
/*
* This should also catch if user used the 32 bit sgmap
*/
actual_fibsize = sizeof(struct aac_srb) -
- sizeof(struct sgentry) + ((srbcmd->sg.count & 0xff) *
- sizeof(struct sgentry64));
+ sizeof(struct sgentry) +
+ ((upsg->count & 0xff) *
+ sizeof(struct sgentry));
if(actual_fibsize != fibsize){ // User made a mistake - should not continue
- printk(KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n");
+ dprintk((KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n"));
rcode = -EINVAL;
goto cleanup;
}
- if ((data_dir == DMA_NONE) && psg->count) {
- printk(KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n");
+ usg = kmalloc(actual_fibsize - sizeof(struct aac_srb)
+ + sizeof(struct sgmap), GFP_KERNEL);
+ if (!usg) {
+ dprintk((KERN_DEBUG"aacraid: Allocation error in Raw SRB command\n"));
+ rcode = -ENOMEM;
+ goto cleanup;
+ }
+ memcpy (usg, upsg, actual_fibsize - sizeof(struct aac_srb)
+ + sizeof(struct sgmap));
+ actual_fibsize = sizeof(struct aac_srb) -
+ sizeof(struct sgentry) + ((usg->count & 0xff) *
+ sizeof(struct sgentry64));
+ if ((data_dir == DMA_NONE) && upsg->count) {
+ kfree (usg);
+ dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"));
rcode = -EINVAL;
goto cleanup;
}
- for (i = 0; i < psg->count; i++) {
- dma_addr_t addr;
- u64 le_addr;
+ for (i = 0; i < usg->count; i++) {
+ u64 addr;
void* p;
- p = kmalloc(psg->sg[i].count,GFP_KERNEL|__GFP_DMA);
+ /* Does this really need to be GFP_DMA? */
+ p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA);
if(p == 0) {
- printk(KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
- psg->sg[i].count,i,psg->count);
+ kfree (usg);
+ dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
+ usg->sg[i].count,i,usg->count));
rcode = -ENOMEM;
goto cleanup;
}
- sg_user[i] = (void __user *)psg->sg[i].addr;
+ sg_user[i] = (void __user *)usg->sg[i].addr;
sg_list[i] = p; // save so we can clean up later
sg_indx = i;
if( flags & SRB_DataOut ){
- if(copy_from_user(p,sg_user[i],psg->sg[i].count)){
- printk(KERN_DEBUG"aacraid: Could not copy sg data from user\n");
+ if(copy_from_user(p,sg_user[i],upsg->sg[i].count)){
+ kfree (usg);
+ dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
rcode = -EFAULT;
goto cleanup;
}
}
- addr = pci_map_single(dev->pdev, p, psg->sg[i].count, data_dir);
+ addr = pci_map_single(dev->pdev, p, usg->sg[i].count, data_dir);
- le_addr = cpu_to_le64(addr);
- psg->sg[i].addr[1] = (u32)(le_addr>>32);
- psg->sg[i].addr[0] = (u32)(le_addr & 0xffffffff);
- psg->sg[i].count = cpu_to_le32(psg->sg[i].count);
- byte_count += psg->sg[i].count;
+ psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
+ psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
+ psg->sg[i].count = cpu_to_le32(usg->sg[i].count);
+ byte_count += usg->sg[i].count;
}
+ kfree (usg);
srbcmd->count = cpu_to_le32(byte_count);
+ psg->count = cpu_to_le32(sg_indx+1);
status = fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL);
} else {
+ struct user_sgmap* upsg = &user_srbcmd->sg;
struct sgmap* psg = &srbcmd->sg;
byte_count = 0;
- actual_fibsize = sizeof (struct aac_srb) +
- (((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) *
- sizeof (struct sgentry));
+ actual_fibsize = sizeof (struct aac_srb) + (((user_srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry));
if(actual_fibsize != fibsize){ // User made a mistake - should not continue
- printk(KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n");
+ dprintk((KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n"));
rcode = -EINVAL;
goto cleanup;
}
- if ((data_dir == DMA_NONE) && psg->count) {
- printk(KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n");
+ if ((data_dir == DMA_NONE) && upsg->count) {
+ dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"));
rcode = -EINVAL;
goto cleanup;
}
- for (i = 0; i < psg->count; i++) {
+ for (i = 0; i < upsg->count; i++) {
dma_addr_t addr;
void* p;
- p = kmalloc(psg->sg[i].count,GFP_KERNEL);
+ p = kmalloc(upsg->sg[i].count, GFP_KERNEL);
if(p == 0) {
- printk(KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
- psg->sg[i].count,i,psg->count);
+ dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
+ upsg->sg[i].count, i, upsg->count));
rcode = -ENOMEM;
goto cleanup;
}
- sg_user[i] = (void __user *)(psg->sg[i].addr);
+ sg_user[i] = (void __user *)upsg->sg[i].addr;
sg_list[i] = p; // save so we can clean up later
sg_indx = i;
if( flags & SRB_DataOut ){
- if(copy_from_user(p,sg_user[i],psg->sg[i].count)){
- printk(KERN_DEBUG"aacraid: Could not copy sg data from user\n");
+ if(copy_from_user(p, sg_user[i],
+ upsg->sg[i].count)) {
+ dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
rcode = -EFAULT;
goto cleanup;
}
}
- addr = pci_map_single(dev->pdev, p, psg->sg[i].count, data_dir);
+ addr = pci_map_single(dev->pdev, p,
+ upsg->sg[i].count, data_dir);
psg->sg[i].addr = cpu_to_le32(addr);
- psg->sg[i].count = cpu_to_le32(psg->sg[i].count);
- byte_count += psg->sg[i].count;
+ psg->sg[i].count = cpu_to_le32(upsg->sg[i].count);
+ byte_count += upsg->sg[i].count;
}
srbcmd->count = cpu_to_le32(byte_count);
+ psg->count = cpu_to_le32(sg_indx+1);
status = fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL);
}
if (status != 0){
- printk(KERN_DEBUG"aacraid: Could not send raw srb fib to hba\n");
- rcode = -1;
+ dprintk((KERN_DEBUG"aacraid: Could not send raw srb fib to hba\n"));
+ rcode = -ENXIO;
goto cleanup;
}
if( flags & SRB_DataIn ) {
for(i = 0 ; i <= sg_indx; i++){
- if(copy_to_user(sg_user[i],sg_list[i],le32_to_cpu(srbcmd->sg.sg[i].count))){
- printk(KERN_DEBUG"aacraid: Could not copy sg data to user\n");
+ byte_count = le32_to_cpu((dev->dac_support == 1)
+ ? ((struct sgmap64*)&srbcmd->sg)->sg[i].count
+ : srbcmd->sg.sg[i].count);
+ if(copy_to_user(sg_user[i], sg_list[i], byte_count)){
+ dprintk((KERN_DEBUG"aacraid: Could not copy sg data to user\n"));
rcode = -EFAULT;
goto cleanup;
@@ -603,12 +660,13 @@ int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
reply = (struct aac_srb_reply *) fib_data(srbfib);
if(copy_to_user(user_reply,reply,sizeof(struct aac_srb_reply))){
- printk(KERN_DEBUG"aacraid: Could not copy reply to user\n");
+ dprintk((KERN_DEBUG"aacraid: Could not copy reply to user\n"));
rcode = -EFAULT;
goto cleanup;
}
cleanup:
+ kfree(user_srbcmd);
for(i=0; i <= sg_indx; i++){
kfree(sg_list[i]);
}
@@ -618,14 +676,13 @@ cleanup:
return rcode;
}
-
struct aac_pci_info {
u32 bus;
u32 slot;
};
-int aac_get_pci_info(struct aac_dev* dev, void __user *arg)
+static int aac_get_pci_info(struct aac_dev* dev, void __user *arg)
{
struct aac_pci_info pci_info;
@@ -633,11 +690,11 @@ int aac_get_pci_info(struct aac_dev* dev, void __user *arg)
pci_info.slot = PCI_SLOT(dev->pdev->devfn);
if (copy_to_user(arg, &pci_info, sizeof(struct aac_pci_info))) {
- printk(KERN_DEBUG "aacraid: Could not copy pci info\n");
+ dprintk((KERN_DEBUG "aacraid: Could not copy pci info\n"));
return -EFAULT;
}
return 0;
- }
+}
int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg)
@@ -656,6 +713,7 @@ int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg)
case FSACTL_MINIPORT_REV_CHECK:
status = check_revision(dev, arg);
break;
+ case FSACTL_SEND_LARGE_FIB:
case FSACTL_SENDFIB:
status = ioctl_send_fib(dev, arg);
break;
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index 6832a55ca90..43557bf661f 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -39,6 +39,7 @@
#include <linux/blkdev.h>
#include <linux/completion.h>
#include <linux/mm.h>
+#include <scsi/scsi_host.h>
#include <asm/semaphore.h>
#include "aacraid.h"
@@ -49,8 +50,8 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
{
unsigned char *base;
unsigned long size, align;
- unsigned long fibsize = 4096;
- unsigned long printfbufsiz = 256;
+ const unsigned long fibsize = 4096;
+ const unsigned long printfbufsiz = 256;
struct aac_init *init;
dma_addr_t phys;
@@ -74,6 +75,8 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
init = dev->init;
init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION);
+ if (dev->max_fib_size != sizeof(struct hw_fib))
+ init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4);
init->MiniPortRevision = cpu_to_le32(Sa_MINIPORT_REVISION);
init->fsrev = cpu_to_le32(dev->fsrev);
@@ -110,6 +113,10 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
init->HostPhysMemPages = cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES);
}
+ init->InitFlags = 0;
+ init->MaxIoCommands = cpu_to_le32(dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB);
+ init->MaxIoSize = cpu_to_le32(dev->scsi_host_ptr->max_sectors << 9);
+ init->MaxFibSize = cpu_to_le32(dev->max_fib_size);
/*
* Increment the base address by the amount already used
@@ -152,8 +159,8 @@ static void aac_queue_init(struct aac_dev * dev, struct aac_queue * q, u32 *mem,
init_waitqueue_head(&q->qfull);
spin_lock_init(&q->lockdata);
q->lock = &q->lockdata;
- q->headers.producer = mem;
- q->headers.consumer = mem+1;
+ q->headers.producer = (__le32 *)mem;
+ q->headers.consumer = (__le32 *)(mem+1);
*(q->headers.producer) = cpu_to_le32(qsize);
*(q->headers.consumer) = cpu_to_le32(qsize);
q->entries = qsize;
@@ -173,6 +180,8 @@ int aac_send_shutdown(struct aac_dev * dev)
int status;
fibctx = fib_alloc(dev);
+ if (!fibctx)
+ return -ENOMEM;
fib_init(fibctx);
cmd = (struct aac_close *) fib_data(fibctx);
@@ -204,7 +213,7 @@ int aac_send_shutdown(struct aac_dev * dev)
* 0 - If there were errors initing. This is a fatal error.
*/
-int aac_comm_init(struct aac_dev * dev)
+static int aac_comm_init(struct aac_dev * dev)
{
unsigned long hdrsize = (sizeof(u32) * NUMBER_OF_COMM_QUEUES) * 2;
unsigned long queuesize = sizeof(struct aac_entry) * TOTAL_QUEUE_ENTRIES;
@@ -293,6 +302,79 @@ int aac_comm_init(struct aac_dev * dev)
struct aac_dev *aac_init_adapter(struct aac_dev *dev)
{
+ u32 status[5];
+ struct Scsi_Host * host = dev->scsi_host_ptr;
+
+ /*
+ * Check the preferred comm settings, defaults from template.
+ */
+ dev->max_fib_size = sizeof(struct hw_fib);
+ dev->sg_tablesize = host->sg_tablesize = (dev->max_fib_size
+ - sizeof(struct aac_fibhdr)
+ - sizeof(struct aac_write) + sizeof(struct sgmap))
+ / sizeof(struct sgmap);
+ if ((!aac_adapter_sync_cmd(dev, GET_COMM_PREFERRED_SETTINGS,
+ 0, 0, 0, 0, 0, 0,
+ status+0, status+1, status+2, status+3, status+4))
+ && (status[0] == 0x00000001)) {
+ /*
+ * status[1] >> 16 maximum command size in KB
+ * status[1] & 0xFFFF maximum FIB size
+ * status[2] >> 16 maximum SG elements to driver
+ * status[2] & 0xFFFF maximum SG elements from driver
+ * status[3] & 0xFFFF maximum number FIBs outstanding
+ */
+ host->max_sectors = (status[1] >> 16) << 1;
+ dev->max_fib_size = status[1] & 0xFFFF;
+ host->sg_tablesize = status[2] >> 16;
+ dev->sg_tablesize = status[2] & 0xFFFF;
+ host->can_queue = (status[3] & 0xFFFF) - AAC_NUM_MGT_FIB;
+ /*
+ * NOTE:
+ * All these overrides are based on a fixed internal
+ * knowledge and understanding of existing adapters,
+ * acbsize should be set with caution.
+ */
+ if (acbsize == 512) {
+ host->max_sectors = AAC_MAX_32BIT_SGBCOUNT;
+ dev->max_fib_size = 512;
+ dev->sg_tablesize = host->sg_tablesize
+ = (512 - sizeof(struct aac_fibhdr)
+ - sizeof(struct aac_write) + sizeof(struct sgmap))
+ / sizeof(struct sgmap);
+ host->can_queue = AAC_NUM_IO_FIB;
+ } else if (acbsize == 2048) {
+ host->max_sectors = 512;
+ dev->max_fib_size = 2048;
+ host->sg_tablesize = 65;
+ dev->sg_tablesize = 81;
+ host->can_queue = 512 - AAC_NUM_MGT_FIB;
+ } else if (acbsize == 4096) {
+ host->max_sectors = 1024;
+ dev->max_fib_size = 4096;
+ host->sg_tablesize = 129;
+ dev->sg_tablesize = 166;
+ host->can_queue = 256 - AAC_NUM_MGT_FIB;
+ } else if (acbsize == 8192) {
+ host->max_sectors = 2048;
+ dev->max_fib_size = 8192;
+ host->sg_tablesize = 257;
+ dev->sg_tablesize = 337;
+ host->can_queue = 128 - AAC_NUM_MGT_FIB;
+ } else if (acbsize > 0) {
+ printk("Illegal acbsize=%d ignored\n", acbsize);
+ }
+ }
+ {
+
+ if (numacb > 0) {
+ if (numacb < host->can_queue)
+ host->can_queue = numacb;
+ else
+ printk("numacb=%d ignored\n", numacb);
+ }
+ }
+
/*
* Ok now init the communication subsystem
*/
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 3f36dbaa2bb..5322865942e 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -25,7 +25,7 @@
* commsup.c
*
* Abstract: Contain all routines that are required for FSA host/adapter
- * commuication.
+ * communication.
*
*/
@@ -38,6 +38,7 @@
#include <linux/slab.h>
#include <linux/completion.h>
#include <linux/blkdev.h>
+#include <scsi/scsi_host.h>
#include <asm/semaphore.h>
#include "aacraid.h"
@@ -52,7 +53,13 @@
static int fib_map_alloc(struct aac_dev *dev)
{
- if((dev->hw_fib_va = pci_alloc_consistent(dev->pdev, sizeof(struct hw_fib) * AAC_NUM_FIB, &dev->hw_fib_pa))==NULL)
+ dprintk((KERN_INFO
+ "allocate hardware fibs pci_alloc_consistent(%p, %d * (%d + %d), %p)\n",
+ dev->pdev, dev->max_fib_size, dev->scsi_host_ptr->can_queue,
+ AAC_NUM_MGT_FIB, &dev->hw_fib_pa));
+ if((dev->hw_fib_va = pci_alloc_consistent(dev->pdev, dev->max_fib_size
+ * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB),
+ &dev->hw_fib_pa))==NULL)
return -ENOMEM;
return 0;
}
@@ -67,7 +74,7 @@ static int fib_map_alloc(struct aac_dev *dev)
void fib_map_free(struct aac_dev *dev)
{
- pci_free_consistent(dev->pdev, sizeof(struct hw_fib) * AAC_NUM_FIB, dev->hw_fib_va, dev->hw_fib_pa);
+ pci_free_consistent(dev->pdev, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB), dev->hw_fib_va, dev->hw_fib_pa);
}
/**
@@ -84,17 +91,22 @@ int fib_setup(struct aac_dev * dev)
struct hw_fib *hw_fib_va;
dma_addr_t hw_fib_pa;
int i;
-
- if(fib_map_alloc(dev)<0)
+
+ while (((i = fib_map_alloc(dev)) == -ENOMEM)
+ && (dev->scsi_host_ptr->can_queue > (64 - AAC_NUM_MGT_FIB))) {
+ dev->init->MaxIoCommands = cpu_to_le32((dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) >> 1);
+ dev->scsi_host_ptr->can_queue = le32_to_cpu(dev->init->MaxIoCommands) - AAC_NUM_MGT_FIB;
+ }
+ if (i<0)
return -ENOMEM;
hw_fib_va = dev->hw_fib_va;
hw_fib_pa = dev->hw_fib_pa;
- memset(hw_fib_va, 0, sizeof(struct hw_fib) * AAC_NUM_FIB);
+ memset(hw_fib_va, 0, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB));
/*
* Initialise the fibs
*/
- for (i = 0, fibptr = &dev->fibs[i]; i < AAC_NUM_FIB; i++, fibptr++)
+ for (i = 0, fibptr = &dev->fibs[i]; i < (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); i++, fibptr++)
{
fibptr->dev = dev;
fibptr->hw_fib = hw_fib_va;
@@ -102,16 +114,16 @@ int fib_setup(struct aac_dev * dev)
fibptr->next = fibptr+1; /* Forward chain the fibs */
init_MUTEX_LOCKED(&fibptr->event_wait);
spin_lock_init(&fibptr->event_lock);
- hw_fib_va->header.XferState = 0xffffffff;
- hw_fib_va->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib));
+ hw_fib_va->header.XferState = cpu_to_le32(0xffffffff);
+ hw_fib_va->header.SenderSize = cpu_to_le16(dev->max_fib_size);
fibptr->hw_fib_pa = hw_fib_pa;
- hw_fib_va = (struct hw_fib *)((unsigned char *)hw_fib_va + sizeof(struct hw_fib));
- hw_fib_pa = hw_fib_pa + sizeof(struct hw_fib);
+ hw_fib_va = (struct hw_fib *)((unsigned char *)hw_fib_va + dev->max_fib_size);
+ hw_fib_pa = hw_fib_pa + dev->max_fib_size;
}
/*
* Add the fib chain to the free list
*/
- dev->fibs[AAC_NUM_FIB-1].next = NULL;
+ dev->fibs[dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB - 1].next = NULL;
/*
* Enable this to debug out of queue space
*/
@@ -124,7 +136,7 @@ int fib_setup(struct aac_dev * dev)
* @dev: Adapter to allocate the fib for
*
* Allocate a fib from the adapter fib pool. If the pool is empty we
- * wait for fibs to become free.
+ * return NULL.
*/
struct fib * fib_alloc(struct aac_dev *dev)
@@ -133,10 +145,10 @@ struct fib * fib_alloc(struct aac_dev *dev)
unsigned long flags;
spin_lock_irqsave(&dev->fib_lock, flags);
fibptr = dev->free_fib;
- /* Cannot sleep here or you get hangs. Instead we did the
- maths at compile time. */
- if(!fibptr)
- BUG();
+ if(!fibptr){
+ spin_unlock_irqrestore(&dev->fib_lock, flags);
+ return fibptr;
+ }
dev->free_fib = fibptr->next;
spin_unlock_irqrestore(&dev->fib_lock, flags);
/*
@@ -196,11 +208,11 @@ void fib_init(struct fib *fibptr)
struct hw_fib *hw_fib = fibptr->hw_fib;
hw_fib->header.StructType = FIB_MAGIC;
- hw_fib->header.Size = cpu_to_le16(sizeof(struct hw_fib));
- hw_fib->header.XferState = cpu_to_le32(HostOwned | FibInitialized | FibEmpty | FastResponseCapable);
+ hw_fib->header.Size = cpu_to_le16(fibptr->dev->max_fib_size);
+ hw_fib->header.XferState = cpu_to_le32(HostOwned | FibInitialized | FibEmpty | FastResponseCapable);
hw_fib->header.SenderFibAddress = cpu_to_le32(fibptr->hw_fib_pa);
hw_fib->header.ReceiverFibAddress = cpu_to_le32(fibptr->hw_fib_pa);
- hw_fib->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib));
+ hw_fib->header.SenderSize = cpu_to_le16(fibptr->dev->max_fib_size);
}
/**
@@ -211,7 +223,7 @@ void fib_init(struct fib *fibptr)
* caller.
*/
-void fib_dealloc(struct fib * fibptr)
+static void fib_dealloc(struct fib * fibptr)
{
struct hw_fib *hw_fib = fibptr->hw_fib;
if(hw_fib->header.StructType != FIB_MAGIC)
@@ -279,7 +291,7 @@ static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entr
}
if ((*index + 1) == le32_to_cpu(*(q->headers.consumer))) { /* Queue is full */
- printk(KERN_WARNING "Queue %d full, %d outstanding.\n",
+ printk(KERN_WARNING "Queue %d full, %u outstanding.\n",
qid, q->numpending);
return 0;
} else {
@@ -658,9 +670,8 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size)
}
if (aac_insert_entry(dev, index, AdapHighRespQueue, (nointr & (int)aac_config.irq_mod)) != 0) {
}
- }
- else if (hw_fib->header.XferState & NormalPriority)
- {
+ } else if (hw_fib->header.XferState &
+ cpu_to_le32(NormalPriority)) {
u32 index;
if (size) {
@@ -744,22 +755,25 @@ int fib_complete(struct fib * fibptr)
void aac_printf(struct aac_dev *dev, u32 val)
{
- int length = val & 0xffff;
- int level = (val >> 16) & 0xffff;
char *cp = dev->printfbuf;
-
- /*
- * The size of the printfbuf is set in port.c
- * There is no variable or define for it
- */
- if (length > 255)
- length = 255;
- if (cp[length] != 0)
- cp[length] = 0;
- if (level == LOG_AAC_HIGH_ERROR)
- printk(KERN_WARNING "aacraid:%s", cp);
- else
- printk(KERN_INFO "aacraid:%s", cp);
+ if (dev->printf_enabled)
+ {
+ int length = val & 0xffff;
+ int level = (val >> 16) & 0xffff;
+
+ /*
+ * The size of the printfbuf is set in port.c
+ * There is no variable or define for it
+ */
+ if (length > 255)
+ length = 255;
+ if (cp[length] != 0)
+ cp[length] = 0;
+ if (level == LOG_AAC_HIGH_ERROR)
+ printk(KERN_WARNING "aacraid:%s", cp);
+ else
+ printk(KERN_INFO "aacraid:%s", cp);
+ }
memset(cp, 0, 256);
}
@@ -832,8 +846,8 @@ int aac_command_thread(struct aac_dev * dev)
aifcmd = (struct aac_aifcmd *) hw_fib->data;
if (aifcmd->command == cpu_to_le32(AifCmdDriverNotify)) {
/* Handle Driver Notify Events */
- *(u32 *)hw_fib->data = cpu_to_le32(ST_OK);
- fib_adapter_complete(fib, sizeof(u32));
+ *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
+ fib_adapter_complete(fib, (u16)sizeof(u32));
} else {
struct list_head *entry;
/* The u32 here is important and intended. We are using
@@ -916,7 +930,7 @@ int aac_command_thread(struct aac_dev * dev)
/*
* Set the status of this FIB
*/
- *(u32 *)hw_fib->data = cpu_to_le32(ST_OK);
+ *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
fib_adapter_complete(fib, sizeof(u32));
spin_unlock_irqrestore(&dev->fib_lock, flagv);
}
diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c
index 8480b427a6d..be2e98de9fa 100644
--- a/drivers/scsi/aacraid/dpcsup.c
+++ b/drivers/scsi/aacraid/dpcsup.c
@@ -99,7 +99,7 @@ unsigned int aac_response_normal(struct aac_queue * q)
/*
* Doctor the fib
*/
- *(u32 *)hwfib->data = cpu_to_le32(ST_OK);
+ *(__le32 *)hwfib->data = cpu_to_le32(ST_OK);
hwfib->header.XferState |= cpu_to_le32(AdapterProcessed);
}
@@ -107,7 +107,7 @@ unsigned int aac_response_normal(struct aac_queue * q)
if (hwfib->header.Command == cpu_to_le16(NuFileSystem))
{
- u32 *pstatus = (u32 *)hwfib->data;
+ __le32 *pstatus = (__le32 *)hwfib->data;
if (*pstatus & cpu_to_le32(0xffff0000))
*pstatus = cpu_to_le32(ST_OK);
}
@@ -205,7 +205,7 @@ unsigned int aac_command_normal(struct aac_queue *q)
/*
* Set the status of this FIB
*/
- *(u32 *)hw_fib->data = cpu_to_le32(ST_OK);
+ *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
fib_adapter_complete(fib, sizeof(u32));
spin_lock_irqsave(q->lock, flags);
}
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 242fa77513f..f7e9c89c491 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -215,7 +215,7 @@ static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd
* Returns a static string describing the device in question
*/
-const char *aac_info(struct Scsi_Host *shost)
+static const char *aac_info(struct Scsi_Host *shost)
{
struct aac_dev *dev = (struct aac_dev *)shost->hostdata;
return aac_drivers[dev->cardtype].name;
@@ -288,7 +288,7 @@ static int aac_biosparm(struct scsi_device *sdev, struct block_device *bdev,
* translations ( 64/32, 128/32, 255/63 ).
*/
buf = scsi_bios_ptable(bdev);
- if(*(unsigned short *)(buf + 0x40) == cpu_to_le16(0xaa55)) {
+ if(*(__le16 *)(buf + 0x40) == cpu_to_le16(0xaa55)) {
struct partition *first = (struct partition * )buf;
struct partition *entry = first;
int saved_cylinders = param->cylinders;
@@ -347,10 +347,16 @@ static int aac_biosparm(struct scsi_device *sdev, struct block_device *bdev,
static int aac_slave_configure(struct scsi_device *sdev)
{
+ struct Scsi_Host *host = sdev->host;
+
if (sdev->tagged_supported)
scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, 128);
else
scsi_adjust_queue_depth(sdev, 0, 1);
+
+ if (host->max_sectors < AAC_MAX_32BIT_SGBCOUNT)
+ blk_queue_max_segment_size(sdev->request_queue, 65536);
+
return 0;
}
@@ -361,14 +367,6 @@ static int aac_ioctl(struct scsi_device *sdev, int cmd, void __user * arg)
}
/*
- * XXX: does aac really need no error handling??
- */
-static int aac_eh_abort(struct scsi_cmnd *cmd)
-{
- return FAILED;
-}
-
-/*
* aac_eh_reset - Reset command handling
* @scsi_cmd: SCSI command block causing the reset
*
@@ -386,10 +384,13 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
AAC_DRIVERNAME);
+ spin_lock_irq(host->host_lock);
+
aac = (struct aac_dev *)host->hostdata;
if (aac_adapter_check_health(aac)) {
printk(KERN_ERR "%s: Host adapter appears dead\n",
AAC_DRIVERNAME);
+ spin_unlock_irq(host->host_lock);
return -ENODEV;
}
/*
@@ -420,6 +421,7 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
ssleep(1);
spin_lock_irq(host->host_lock);
}
+ spin_unlock_irq(host->host_lock);
printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME);
return -ETIMEDOUT;
}
@@ -439,11 +441,11 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
static int aac_cfg_open(struct inode *inode, struct file *file)
{
struct aac_dev *aac;
- unsigned minor = iminor(inode);
+ unsigned minor_number = iminor(inode);
int err = -ENODEV;
list_for_each_entry(aac, &aac_devices, entry) {
- if (aac->id == minor) {
+ if (aac->id == minor_number) {
file->private_data = aac;
err = 0;
break;
@@ -489,6 +491,7 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long
case FSACTL_DELETE_DISK:
case FSACTL_FORCE_DELETE_DISK:
case FSACTL_GET_CONTAINERS:
+ case FSACTL_SEND_LARGE_FIB:
ret = aac_do_ioctl(dev, cmd, (void __user *)arg);
break;
@@ -526,6 +529,134 @@ static long aac_compat_cfg_ioctl(struct file *file, unsigned cmd, unsigned long
}
#endif
+static ssize_t aac_show_model(struct class_device *class_dev,
+ char *buf)
+{
+ struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
+ int len;
+
+ len = snprintf(buf, PAGE_SIZE, "%s\n",
+ aac_drivers[dev->cardtype].model);
+ return len;
+}
+
+static ssize_t aac_show_vendor(struct class_device *class_dev,
+ char *buf)
+{
+ struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
+ int len;
+
+ len = snprintf(buf, PAGE_SIZE, "%s\n",
+ aac_drivers[dev->cardtype].vname);
+ return len;
+}
+
+static ssize_t aac_show_kernel_version(struct class_device *class_dev,
+ char *buf)
+{
+ struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
+ int len, tmp;
+
+ tmp = le32_to_cpu(dev->adapter_info.kernelrev);
+ len = snprintf(buf, PAGE_SIZE, "%d.%d-%d[%d]\n",
+ tmp >> 24, (tmp >> 16) & 0xff, tmp & 0xff,
+ le32_to_cpu(dev->adapter_info.kernelbuild));
+ return len;
+}
+
+static ssize_t aac_show_monitor_version(struct class_device *class_dev,
+ char *buf)
+{
+ struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
+ int len, tmp;
+
+ tmp = le32_to_cpu(dev->adapter_info.monitorrev);
+ len = snprintf(buf, PAGE_SIZE, "%d.%d-%d[%d]\n",
+ tmp >> 24, (tmp >> 16) & 0xff, tmp & 0xff,
+ le32_to_cpu(dev->adapter_info.monitorbuild));
+ return len;
+}
+
+static ssize_t aac_show_bios_version(struct class_device *class_dev,
+ char *buf)
+{
+ struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
+ int len, tmp;
+
+ tmp = le32_to_cpu(dev->adapter_info.biosrev);
+ len = snprintf(buf, PAGE_SIZE, "%d.%d-%d[%d]\n",
+ tmp >> 24, (tmp >> 16) & 0xff, tmp & 0xff,
+ le32_to_cpu(dev->adapter_info.biosbuild));
+ return len;
+}
+
+static ssize_t aac_show_serial_number(struct class_device *class_dev,
+ char *buf)
+{
+ struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
+ int len = 0;
+
+ if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0)
+ len = snprintf(buf, PAGE_SIZE, "%x\n",
+ le32_to_cpu(dev->adapter_info.serial[0]));
+ return len;
+}
+
+
+static struct class_device_attribute aac_model = {
+ .attr = {
+ .name = "model",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_model,
+};
+static struct class_device_attribute aac_vendor = {
+ .attr = {
+ .name = "vendor",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_vendor,
+};
+static struct class_device_attribute aac_kernel_version = {
+ .attr = {
+ .name = "hba_kernel_version",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_kernel_version,
+};
+static struct class_device_attribute aac_monitor_version = {
+ .attr = {
+ .name = "hba_monitor_version",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_monitor_version,
+};
+static struct class_device_attribute aac_bios_version = {
+ .attr = {
+ .name = "hba_bios_version",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_bios_version,
+};
+static struct class_device_attribute aac_serial_number = {
+ .attr = {
+ .name = "serial_number",
+ .mode = S_IRUGO,
+ },
+ .show = aac_show_serial_number,
+};
+
+static struct class_device_attribute *aac_attrs[] = {
+ &aac_model,
+ &aac_vendor,
+ &aac_kernel_version,
+ &aac_monitor_version,
+ &aac_bios_version,
+ &aac_serial_number,
+ NULL
+};
+
+
static struct file_operations aac_cfg_fops = {
.owner = THIS_MODULE,
.ioctl = aac_cfg_ioctl,
@@ -538,7 +669,7 @@ static struct file_operations aac_cfg_fops = {
static struct scsi_host_template aac_driver_template = {
.module = THIS_MODULE,
.name = "AAC",
- .proc_name = "aacraid",
+ .proc_name = AAC_DRIVERNAME,
.info = aac_info,
.ioctl = aac_ioctl,
#ifdef CONFIG_COMPAT
@@ -546,8 +677,8 @@ static struct scsi_host_template aac_driver_template = {
#endif
.queuecommand = aac_queuecommand,
.bios_param = aac_biosparm,
+ .shost_attrs = aac_attrs,
.slave_configure = aac_slave_configure,
- .eh_abort_handler = aac_eh_abort,
.eh_host_reset_handler = aac_eh_reset,
.can_queue = AAC_NUM_IO_FIB,
.this_id = 16,
@@ -612,7 +743,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
aac->cardtype = index;
INIT_LIST_HEAD(&aac->entry);
- aac->fibs = kmalloc(sizeof(struct fib) * AAC_NUM_FIB, GFP_KERNEL);
+ aac->fibs = kmalloc(sizeof(struct fib) * (shost->can_queue + AAC_NUM_MGT_FIB), GFP_KERNEL);
if (!aac->fibs)
goto out_free_host;
spin_lock_init(&aac->fib_lock);
@@ -632,6 +763,24 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
aac_get_adapter_info(aac);
/*
+ * Lets override negotiations and drop the maximum SG limit to 34
+ */
+ if ((aac_drivers[index].quirks & AAC_QUIRK_34SG) &&
+ (aac->scsi_host_ptr->sg_tablesize > 34)) {
+ aac->scsi_host_ptr->sg_tablesize = 34;
+ aac->scsi_host_ptr->max_sectors
+ = (aac->scsi_host_ptr->sg_tablesize * 8) + 112;
+ }
+
+ /*
+ * Firware printf works only with older firmware.
+ */
+ if (aac_drivers[index].quirks & AAC_QUIRK_34SG)
+ aac->printf_enabled = 1;
+ else
+ aac->printf_enabled = 0;
+
+ /*
* max channel will be the physical channels plus 1 virtual channel
* all containers are on the virtual channel 0
* physical channels are address by their actual physical number+1
diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c
index 1b8ed47cfe3..7d68b782513 100644
--- a/drivers/scsi/aacraid/rkt.c
+++ b/drivers/scsi/aacraid/rkt.c
@@ -98,7 +98,9 @@ static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs)
* for its completion.
*/
-static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
+static int rkt_sync_cmd(struct aac_dev *dev, u32 command,
+ u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
+ u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4)
{
unsigned long start;
int ok;
@@ -107,12 +109,12 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
*/
rkt_writel(dev, InboundMailbox0, command);
/*
- * Write the parameters into Mailboxes 1 - 4
+ * Write the parameters into Mailboxes 1 - 6
*/
rkt_writel(dev, InboundMailbox1, p1);
- rkt_writel(dev, InboundMailbox2, 0);
- rkt_writel(dev, InboundMailbox3, 0);
- rkt_writel(dev, InboundMailbox4, 0);
+ rkt_writel(dev, InboundMailbox2, p2);
+ rkt_writel(dev, InboundMailbox3, p3);
+ rkt_writel(dev, InboundMailbox4, p4);
/*
* Clear the synch command doorbell to start on a clean slate.
*/
@@ -169,6 +171,14 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
*/
if (status)
*status = rkt_readl(dev, IndexRegs.Mailbox[0]);
+ if (r1)
+ *r1 = rkt_readl(dev, IndexRegs.Mailbox[1]);
+ if (r2)
+ *r2 = rkt_readl(dev, IndexRegs.Mailbox[2]);
+ if (r3)
+ *r3 = rkt_readl(dev, IndexRegs.Mailbox[3]);
+ if (r4)
+ *r4 = rkt_readl(dev, IndexRegs.Mailbox[4]);
/*
* Clear the synch command doorbell.
*/
@@ -190,8 +200,8 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
static void aac_rkt_interrupt_adapter(struct aac_dev *dev)
{
- u32 ret;
- rkt_sync_cmd(dev, BREAKPOINT_REQUEST, 0, &ret);
+ rkt_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0,
+ NULL, NULL, NULL, NULL, NULL);
}
/**
@@ -220,7 +230,8 @@ static void aac_rkt_notify_adapter(struct aac_dev *dev, u32 event)
rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_3);
break;
case HostShutdown:
-// rkt_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, &ret);
+// rkt_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, 0, 0,
+// NULL, NULL, NULL, NULL, NULL);
break;
case FastIo:
rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_6);
@@ -243,17 +254,11 @@ static void aac_rkt_notify_adapter(struct aac_dev *dev, u32 event)
static void aac_rkt_start_adapter(struct aac_dev *dev)
{
- u32 status;
struct aac_init *init;
init = dev->init;
init->HostElapsedSeconds = cpu_to_le32(get_seconds());
/*
- * Tell the adapter we are back and up and running so it will scan
- * its command queues and enable our interrupts
- */
- dev->irq_mask = (DoorBellPrintfReady | OUTBOUNDDOORBELL_1 | OUTBOUNDDOORBELL_2 | OUTBOUNDDOORBELL_3 | OUTBOUNDDOORBELL_4);
- /*
* First clear out all interrupts. Then enable the one's that we
* can handle.
*/
@@ -263,7 +268,8 @@ static void aac_rkt_start_adapter(struct aac_dev *dev)
rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
// We can only use a 32 bit address here
- rkt_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, &status);
+ rkt_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa,
+ 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
}
/**
@@ -288,8 +294,8 @@ static int aac_rkt_check_health(struct aac_dev *dev)
if (status & KERNEL_PANIC) {
char * buffer;
struct POSTSTATUS {
- u32 Post_Command;
- u32 Post_Address;
+ __le32 Post_Command;
+ __le32 Post_Address;
} * post;
dma_addr_t paddr, baddr;
int ret;
@@ -310,7 +316,8 @@ static int aac_rkt_check_health(struct aac_dev *dev)
post->Post_Command = cpu_to_le32(COMMAND_POST_RESULTS);
post->Post_Address = cpu_to_le32(baddr);
rkt_writel(dev, MUnit.IMRx[0], paddr);
- rkt_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, &status);
+ rkt_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, 0, 0, 0, 0, 0,
+ NULL, NULL, NULL, NULL, NULL);
pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS),
post, paddr);
if ((buffer[0] == '0') && (buffer[1] == 'x')) {
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
index 630b99e1fe8..1ff25f49fad 100644
--- a/drivers/scsi/aacraid/rx.c
+++ b/drivers/scsi/aacraid/rx.c
@@ -63,7 +63,7 @@ static irqreturn_t aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs)
{
bellbits = rx_readl(dev, OutboundDoorbellReg);
if (bellbits & DoorBellPrintfReady) {
- aac_printf(dev, le32_to_cpu(rx_readl (dev, IndexRegs.Mailbox[5])));
+ aac_printf(dev, rx_readl(dev, IndexRegs.Mailbox[5]));
rx_writel(dev, MUnit.ODR,DoorBellPrintfReady);
rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
}
@@ -98,7 +98,9 @@ static irqreturn_t aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs)
* for its completion.
*/
-static int rx_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
+static int rx_sync_cmd(struct aac_dev *dev, u32 command,
+ u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
+ u32 *status, u32 * r1, u32 * r2, u32 * r3, u32 * r4)
{
unsigned long start;
int ok;
@@ -107,12 +109,12 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
*/
rx_writel(dev, InboundMailbox0, command);
/*
- * Write the parameters into Mailboxes 1 - 4
+ * Write the parameters into Mailboxes 1 - 6
*/
rx_writel(dev, InboundMailbox1, p1);
- rx_writel(dev, InboundMailbox2, 0);
- rx_writel(dev, InboundMailbox3, 0);
- rx_writel(dev, InboundMailbox4, 0);
+ rx_writel(dev, InboundMailbox2, p2);
+ rx_writel(dev, InboundMailbox3, p3);
+ rx_writel(dev, InboundMailbox4, p4);
/*
* Clear the synch command doorbell to start on a clean slate.
*/
@@ -120,7 +122,7 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
/*
* Disable doorbell interrupts
*/
- rx_writeb(dev, MUnit.OIMR, dev->OIMR |= 0x04);
+ rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
/*
* Force the completion of the mask register write before issuing
* the interrupt.
@@ -169,6 +171,14 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
*/
if (status)
*status = rx_readl(dev, IndexRegs.Mailbox[0]);
+ if (r1)
+ *r1 = rx_readl(dev, IndexRegs.Mailbox[1]);
+ if (r2)
+ *r2 = rx_readl(dev, IndexRegs.Mailbox[2]);
+ if (r3)
+ *r3 = rx_readl(dev, IndexRegs.Mailbox[3]);
+ if (r4)
+ *r4 = rx_readl(dev, IndexRegs.Mailbox[4]);
/*
* Clear the synch command doorbell.
*/
@@ -190,8 +200,7 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
static void aac_rx_interrupt_adapter(struct aac_dev *dev)
{
- u32 ret;
- rx_sync_cmd(dev, BREAKPOINT_REQUEST, 0, &ret);
+ rx_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
}
/**
@@ -220,7 +229,8 @@ static void aac_rx_notify_adapter(struct aac_dev *dev, u32 event)
rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_3);
break;
case HostShutdown:
-// rx_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, &ret);
+// rx_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, 0, 0,
+// NULL, NULL, NULL, NULL, NULL);
break;
case FastIo:
rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_6);
@@ -243,17 +253,11 @@ static void aac_rx_notify_adapter(struct aac_dev *dev, u32 event)
static void aac_rx_start_adapter(struct aac_dev *dev)
{
- u32 status;
struct aac_init *init;
init = dev->init;
init->HostElapsedSeconds = cpu_to_le32(get_seconds());
/*
- * Tell the adapter we are back and up and running so it will scan
- * its command queues and enable our interrupts
- */
- dev->irq_mask = (DoorBellPrintfReady | OUTBOUNDDOORBELL_1 | OUTBOUNDDOORBELL_2 | OUTBOUNDDOORBELL_3 | OUTBOUNDDOORBELL_4);
- /*
* First clear out all interrupts. Then enable the one's that we
* can handle.
*/
@@ -263,7 +267,8 @@ static void aac_rx_start_adapter(struct aac_dev *dev)
rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
// We can only use a 32 bit address here
- rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, &status);
+ rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa,
+ 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
}
/**
@@ -288,8 +293,8 @@ static int aac_rx_check_health(struct aac_dev *dev)
if (status & KERNEL_PANIC) {
char * buffer;
struct POSTSTATUS {
- u32 Post_Command;
- u32 Post_Address;
+ __le32 Post_Command;
+ __le32 Post_Address;
} * post;
dma_addr_t paddr, baddr;
int ret;
@@ -310,7 +315,8 @@ static int aac_rx_check_health(struct aac_dev *dev)
post->Post_Command = cpu_to_le32(COMMAND_POST_RESULTS);
post->Post_Address = cpu_to_le32(baddr);
rx_writel(dev, MUnit.IMRx[0], paddr);
- rx_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, &status);
+ rx_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, 0, 0, 0, 0, 0,
+ NULL, NULL, NULL, NULL, NULL);
pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS),
post, paddr);
if ((buffer[0] == '0') && (buffer[1] == 'x')) {
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
index bd6c30723fb..0680249ab86 100644
--- a/drivers/scsi/aacraid/sa.c
+++ b/drivers/scsi/aacraid/sa.c
@@ -89,7 +89,7 @@ static irqreturn_t aac_sa_intr(int irq, void *dev_id, struct pt_regs *regs)
* Notify the adapter of an event
*/
-void aac_sa_notify_adapter(struct aac_dev *dev, u32 event)
+static void aac_sa_notify_adapter(struct aac_dev *dev, u32 event)
{
switch (event) {
@@ -106,7 +106,10 @@ void aac_sa_notify_adapter(struct aac_dev *dev, u32 event)
sa_writew(dev, DoorbellReg_s,DOORBELL_3);
break;
case HostShutdown:
- //sa_sync_cmd(dev, HOST_CRASHING, 0, &ret);
+ /*
+ sa_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, 0, 0,
+ NULL, NULL, NULL, NULL, NULL);
+ */
break;
case FastIo:
sa_writew(dev, DoorbellReg_s,DOORBELL_6);
@@ -132,7 +135,9 @@ void aac_sa_notify_adapter(struct aac_dev *dev, u32 event)
* for its completion.
*/
-static int sa_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *ret)
+static int sa_sync_cmd(struct aac_dev *dev, u32 command,
+ u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
+ u32 *ret, u32 *r1, u32 *r2, u32 *r3, u32 *r4)
{
unsigned long start;
int ok;
@@ -144,9 +149,10 @@ static int sa_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *ret)
* Write the parameters into Mailboxes 1 - 4
*/
sa_writel(dev, Mailbox1, p1);
- sa_writel(dev, Mailbox2, 0);
- sa_writel(dev, Mailbox3, 0);
- sa_writel(dev, Mailbox4, 0);
+ sa_writel(dev, Mailbox2, p2);
+ sa_writel(dev, Mailbox3, p3);
+ sa_writel(dev, Mailbox4, p4);
+
/*
* Clear the synch command doorbell to start on a clean slate.
*/
@@ -188,6 +194,14 @@ static int sa_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *ret)
*/
if (ret)
*ret = sa_readl(dev, Mailbox0);
+ if (r1)
+ *r1 = sa_readl(dev, Mailbox1);
+ if (r2)
+ *r2 = sa_readl(dev, Mailbox2);
+ if (r3)
+ *r3 = sa_readl(dev, Mailbox3);
+ if (r4)
+ *r4 = sa_readl(dev, Mailbox4);
return 0;
}
@@ -201,7 +215,8 @@ static int sa_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *ret)
static void aac_sa_interrupt_adapter (struct aac_dev *dev)
{
u32 ret;
- sa_sync_cmd(dev, BREAKPOINT_REQUEST, 0, &ret);
+ sa_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0,
+ &ret, NULL, NULL, NULL, NULL);
}
/**
@@ -230,10 +245,12 @@ static void aac_sa_start_adapter(struct aac_dev *dev)
* First clear out all interrupts. Then enable the one's that
* we can handle.
*/
- sa_writew(dev, SaDbCSR.PRISETIRQMASK, cpu_to_le16(0xffff));
+ sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 | DOORBELL_2 | DOORBELL_3 | DOORBELL_4));
/* We can only use a 32 bit address here */
- sa_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, &ret);
+ sa_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS,
+ (u32)(ulong)dev->init_pa, 0, 0, 0, 0, 0,
+ &ret, NULL, NULL, NULL, NULL);
}
/**
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index 88d119f4b97..630b1157523 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -1225,8 +1225,6 @@ static int aha152x_device_reset(Scsi_Cmnd * SCpnt)
}
DO_UNLOCK(flags);
-
- spin_lock_irq(shpnt->host_lock);
return ret;
}
diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
index e9920a00959..9ec4641a634 100644
--- a/drivers/scsi/aha1542.c
+++ b/drivers/scsi/aha1542.c
@@ -1348,20 +1348,6 @@ static int aha1542_restart(struct Scsi_Host *shost)
return 0;
}
-static int aha1542_abort(Scsi_Cmnd * SCpnt)
-{
-
- /*
- * The abort command does not leave the device in a clean state where
- * it is available to be used again. Until this gets worked out, we
- * will leave it commented out.
- */
-
- printk(KERN_ERR "aha1542.c: Unable to abort command for target %d\n",
- SCpnt->device->id);
- return FAILED;
-}
-
/*
* This is a device reset. This is handled by sending a special command
* to the device.
@@ -1478,8 +1464,8 @@ static int aha1542_bus_reset(Scsi_Cmnd * SCpnt)
* check for timeout, and if we are doing something like this
* we are pretty desperate anyways.
*/
- spin_unlock_irq(SCpnt->device->host->host_lock);
ssleep(4);
+
spin_lock_irq(SCpnt->device->host->host_lock);
WAIT(STATUS(SCpnt->device->host->io_port),
@@ -1517,9 +1503,11 @@ static int aha1542_bus_reset(Scsi_Cmnd * SCpnt)
}
}
+ spin_unlock_irq(SCpnt->device->host->host_lock);
return SUCCESS;
fail:
+ spin_unlock_irq(SCpnt->device->host->host_lock);
return FAILED;
}
@@ -1542,7 +1530,6 @@ static int aha1542_host_reset(Scsi_Cmnd * SCpnt)
* check for timeout, and if we are doing something like this
* we are pretty desperate anyways.
*/
- spin_unlock_irq(SCpnt->device->host->host_lock);
ssleep(4);
spin_lock_irq(SCpnt->device->host->host_lock);
@@ -1586,9 +1573,11 @@ static int aha1542_host_reset(Scsi_Cmnd * SCpnt)
}
}
+ spin_unlock_irq(SCpnt->device->host->host_lock);
return SUCCESS;
fail:
+ spin_unlock_irq(SCpnt->device->host->host_lock);
return FAILED;
}
@@ -1817,7 +1806,6 @@ static Scsi_Host_Template driver_template = {
.detect = aha1542_detect,
.release = aha1542_release,
.queuecommand = aha1542_queuecommand,
- .eh_abort_handler = aha1542_abort,
.eh_device_reset_handler= aha1542_dev_reset,
.eh_bus_reset_handler = aha1542_bus_reset,
.eh_host_reset_handler = aha1542_host_reset,
diff --git a/drivers/scsi/aha1542.h b/drivers/scsi/aha1542.h
index c402351dc79..3821ee17f47 100644
--- a/drivers/scsi/aha1542.h
+++ b/drivers/scsi/aha1542.h
@@ -133,7 +133,6 @@ struct ccb { /* Command Control Block 5.3 */
static int aha1542_detect(Scsi_Host_Template *);
static int aha1542_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-static int aha1542_abort(Scsi_Cmnd * SCpnt);
static int aha1542_bus_reset(Scsi_Cmnd * SCpnt);
static int aha1542_dev_reset(Scsi_Cmnd * SCpnt);
static int aha1542_host_reset(Scsi_Cmnd * SCpnt);
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index da5bd33d982..9a547ca9c86 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -32,13 +32,14 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
+#include <linux/dma-mapping.h>
#include "scsi.h"
#include <scsi/scsi_host.h>
#include <linux/libata.h>
#include <asm/io.h>
#define DRV_NAME "ahci"
-#define DRV_VERSION "1.00"
+#define DRV_VERSION "1.01"
enum {
@@ -49,6 +50,7 @@ enum {
AHCI_CMD_SLOT_SZ = 32 * 32,
AHCI_RX_FIS_SZ = 256,
AHCI_CMD_TBL_HDR = 0x80,
+ AHCI_CMD_TBL_CDB = 0x40,
AHCI_CMD_TBL_SZ = AHCI_CMD_TBL_HDR + (AHCI_MAX_SG * 16),
AHCI_PORT_PRIV_DMA_SZ = AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_SZ +
AHCI_RX_FIS_SZ,
@@ -133,6 +135,9 @@ enum {
PORT_CMD_ICC_ACTIVE = (0x1 << 28), /* Put i/f in active state */
PORT_CMD_ICC_PARTIAL = (0x2 << 28), /* Put i/f in partial state */
PORT_CMD_ICC_SLUMBER = (0x6 << 28), /* Put i/f in slumber state */
+
+ /* hpriv->flags bits */
+ AHCI_FLAG_MSI = (1 << 0),
};
struct ahci_cmd_hdr {
@@ -182,6 +187,7 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc);
static u8 ahci_check_status(struct ata_port *ap);
static u8 ahci_check_err(struct ata_port *ap);
static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
+static void ahci_remove_one (struct pci_dev *pdev);
static Scsi_Host_Template ahci_sht = {
.module = THIS_MODULE,
@@ -271,7 +277,7 @@ static struct pci_driver ahci_pci_driver = {
.name = DRV_NAME,
.id_table = ahci_pci_tbl,
.probe = ahci_init_one,
- .remove = ata_pci_remove_one,
+ .remove = ahci_remove_one,
};
@@ -289,6 +295,8 @@ static void ahci_host_stop(struct ata_host_set *host_set)
{
struct ahci_host_priv *hpriv = host_set->private_data;
kfree(hpriv);
+
+ ata_host_stop(host_set);
}
static int ahci_port_start(struct ata_port *ap)
@@ -503,7 +511,8 @@ static void ahci_fill_sg(struct ata_queued_cmd *qc)
static void ahci_qc_prep(struct ata_queued_cmd *qc)
{
- struct ahci_port_priv *pp = qc->ap->private_data;
+ struct ata_port *ap = qc->ap;
+ struct ahci_port_priv *pp = ap->private_data;
u32 opts;
const u32 cmd_fis_len = 5; /* five dwords */
@@ -515,18 +524,8 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
opts = (qc->n_elem << 16) | cmd_fis_len;
if (qc->tf.flags & ATA_TFLAG_WRITE)
opts |= AHCI_CMD_WRITE;
-
- switch (qc->tf.protocol) {
- case ATA_PROT_ATAPI:
- case ATA_PROT_ATAPI_NODATA:
- case ATA_PROT_ATAPI_DMA:
+ if (is_atapi_taskfile(&qc->tf))
opts |= AHCI_CMD_ATAPI;
- break;
-
- default:
- /* do nothing */
- break;
- }
pp->cmd_slot[0].opts = cpu_to_le32(opts);
pp->cmd_slot[0].status = 0;
@@ -538,6 +537,10 @@ static void ahci_qc_prep(struct ata_queued_cmd *qc)
* a SATA Register - Host to Device command FIS.
*/
ata_tf_to_fis(&qc->tf, pp->cmd_tbl, 0);
+ if (opts & AHCI_CMD_ATAPI) {
+ memset(pp->cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32);
+ memcpy(pp->cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, ap->cdb_len);
+ }
if (!(qc->flags & ATA_QCFLAG_DMAMAP))
return;
@@ -792,8 +795,6 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
return rc;
}
}
-
- hpriv->flags |= HOST_CAP_64;
} else {
rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (rc) {
@@ -876,15 +877,19 @@ static int ahci_host_init(struct ata_probe_ent *probe_ent)
}
/* move to PCI layer, integrate w/ MSI stuff */
-static void pci_enable_intx(struct pci_dev *pdev)
+static void pci_intx(struct pci_dev *pdev, int enable)
{
- u16 pci_command;
+ u16 pci_command, new;
pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
- if (pci_command & PCI_COMMAND_INTX_DISABLE) {
- pci_command &= ~PCI_COMMAND_INTX_DISABLE;
+
+ if (enable)
+ new = pci_command & ~PCI_COMMAND_INTX_DISABLE;
+ else
+ new = pci_command | PCI_COMMAND_INTX_DISABLE;
+
+ if (new != pci_command)
pci_write_config_word(pdev, PCI_COMMAND, pci_command);
- }
}
static void ahci_print_info(struct ata_probe_ent *probe_ent)
@@ -966,7 +971,7 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
unsigned long base;
void *mmio_base;
unsigned int board_idx = (unsigned int) ent->driver_data;
- int pci_dev_busy = 0;
+ int have_msi, pci_dev_busy = 0;
int rc;
VPRINTK("ENTER\n");
@@ -984,12 +989,17 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out;
}
- pci_enable_intx(pdev);
+ if (pci_enable_msi(pdev) == 0)
+ have_msi = 1;
+ else {
+ pci_intx(pdev, 1);
+ have_msi = 0;
+ }
probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
if (probe_ent == NULL) {
rc = -ENOMEM;
- goto err_out_regions;
+ goto err_out_msi;
}
memset(probe_ent, 0, sizeof(*probe_ent));
@@ -1022,6 +1032,9 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
probe_ent->mmio_base = mmio_base;
probe_ent->private_data = hpriv;
+ if (have_msi)
+ hpriv->flags |= AHCI_FLAG_MSI;
+
/* initialize adapter */
rc = ahci_host_init(probe_ent);
if (rc)
@@ -1041,7 +1054,11 @@ err_out_iounmap:
iounmap(mmio_base);
err_out_free_ent:
kfree(probe_ent);
-err_out_regions:
+err_out_msi:
+ if (have_msi)
+ pci_disable_msi(pdev);
+ else
+ pci_intx(pdev, 0);
pci_release_regions(pdev);
err_out:
if (!pci_dev_busy)
@@ -1049,6 +1066,42 @@ err_out:
return rc;
}
+static void ahci_remove_one (struct pci_dev *pdev)
+{
+ struct device *dev = pci_dev_to_dev(pdev);
+ struct ata_host_set *host_set = dev_get_drvdata(dev);
+ struct ahci_host_priv *hpriv = host_set->private_data;
+ struct ata_port *ap;
+ unsigned int i;
+ int have_msi;
+
+ for (i = 0; i < host_set->n_ports; i++) {
+ ap = host_set->ports[i];
+
+ scsi_remove_host(ap->host);
+ }
+
+ have_msi = hpriv->flags & AHCI_FLAG_MSI;
+ free_irq(host_set->irq, host_set);
+
+ for (i = 0; i < host_set->n_ports; i++) {
+ ap = host_set->ports[i];
+
+ ata_scsi_release(ap->host);
+ scsi_host_put(ap->host);
+ }
+
+ host_set->ops->host_stop(host_set);
+ kfree(host_set);
+
+ if (have_msi)
+ pci_disable_msi(pdev);
+ else
+ pci_intx(pdev, 0);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ dev_set_drvdata(dev, NULL);
+}
static int __init ahci_init(void)
{
diff --git a/drivers/scsi/aic7xxx/aic7770_osm.c b/drivers/scsi/aic7xxx/aic7770_osm.c
index c2b47f2bdff..d4ed5e9f830 100644
--- a/drivers/scsi/aic7xxx/aic7770_osm.c
+++ b/drivers/scsi/aic7xxx/aic7770_osm.c
@@ -41,138 +41,49 @@
#include "aic7xxx_osm.h"
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
#include <linux/device.h>
#include <linux/eisa.h>
-#define EISA_MFCTR_CHAR0(ID) (char)(((ID>>26) & 0x1F) | '@') /* Bits 26-30 */
-#define EISA_MFCTR_CHAR1(ID) (char)(((ID>>21) & 0x1F) | '@') /* Bits 21-25 */
-#define EISA_MFCTR_CHAR2(ID) (char)(((ID>>16) & 0x1F) | '@') /* Bits 16-20 */
-#define EISA_PRODUCT_ID(ID) (short)((ID>>4) & 0xFFF) /* Bits 4-15 */
-#define EISA_REVISION_ID(ID) (uint8_t)(ID & 0x0F) /* Bits 0-3 */
-
-static int aic7770_eisa_dev_probe(struct device *dev);
-static int aic7770_eisa_dev_remove(struct device *dev);
-static struct eisa_driver aic7770_driver = {
- .driver = {
- .name = "aic7xxx",
- .probe = aic7770_eisa_dev_probe,
- .remove = aic7770_eisa_dev_remove,
- }
-};
-
-typedef struct device *aic7770_dev_t;
-#else
-#define MINSLOT 1
-#define NUMSLOTS 16
-#define IDOFFSET 0x80
-
-typedef void *aic7770_dev_t;
-#endif
-
-static int aic7770_linux_config(struct aic7770_identity *entry,
- aic7770_dev_t dev, u_int eisaBase);
-
int
-ahc_linux_eisa_init(void)
+aic7770_map_registers(struct ahc_softc *ahc, u_int port)
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- struct eisa_device_id *eid;
- struct aic7770_identity *id;
- int i;
-
- if (aic7xxx_probe_eisa_vl == 0)
- return -ENODEV;
-
/*
- * Linux requires the EISA IDs to be specified in
- * the EISA ID string format. Perform the conversion
- * and setup a table with a NUL terminal entry.
+ * Lock out other contenders for our i/o space.
*/
- aic7770_driver.id_table = malloc(sizeof(struct eisa_device_id) *
- (ahc_num_aic7770_devs + 1),
- M_DEVBUF, M_NOWAIT);
- if (aic7770_driver.id_table == NULL)
- return -ENOMEM;
-
- for (eid = (struct eisa_device_id *)aic7770_driver.id_table,
- id = aic7770_ident_table, i = 0;
- i < ahc_num_aic7770_devs; eid++, id++, i++) {
-
- sprintf(eid->sig, "%c%c%c%03X%01X",
- EISA_MFCTR_CHAR0(id->full_id),
- EISA_MFCTR_CHAR1(id->full_id),
- EISA_MFCTR_CHAR2(id->full_id),
- EISA_PRODUCT_ID(id->full_id),
- EISA_REVISION_ID(id->full_id));
- eid->driver_data = i;
- }
- eid->sig[0] = 0;
-
- return eisa_driver_register(&aic7770_driver);
-#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) */
- struct aic7770_identity *entry;
- u_int slot;
- u_int eisaBase;
- u_int i;
- int ret = -ENODEV;
-
- if (aic7xxx_probe_eisa_vl == 0)
- return ret;
-
- eisaBase = 0x1000 + AHC_EISA_SLOT_OFFSET;
- for (slot = 1; slot < NUMSLOTS; eisaBase+=0x1000, slot++) {
- uint32_t eisa_id;
- size_t id_size;
-
- if (request_region(eisaBase, AHC_EISA_IOSIZE, "aic7xxx") == 0)
- continue;
-
- eisa_id = 0;
- id_size = sizeof(eisa_id);
- for (i = 0; i < 4; i++) {
- /* VLcards require priming*/
- outb(0x80 + i, eisaBase + IDOFFSET);
- eisa_id |= inb(eisaBase + IDOFFSET + i)
- << ((id_size-i-1) * 8);
- }
- release_region(eisaBase, AHC_EISA_IOSIZE);
- if (eisa_id & 0x80000000)
- continue; /* no EISA card in slot */
-
- entry = aic7770_find_device(eisa_id);
- if (entry != NULL) {
- aic7770_linux_config(entry, NULL, eisaBase);
- ret = 0;
- }
- }
- return ret;
-#endif
+ if (request_region(port, AHC_EISA_IOSIZE, "aic7xxx") == 0)
+ return (ENOMEM);
+ ahc->tag = BUS_SPACE_PIO;
+ ahc->bsh.ioport = port;
+ return (0);
}
-void
-ahc_linux_eisa_exit(void)
+int
+aic7770_map_int(struct ahc_softc *ahc, u_int irq)
{
- if(aic7xxx_probe_eisa_vl != 0 && aic7770_driver.id_table != NULL) {
- eisa_driver_unregister(&aic7770_driver);
- free(aic7770_driver.id_table, M_DEVBUF);
- }
+ int error;
+ int shared;
+
+ shared = 0;
+ if ((ahc->flags & AHC_EDGE_INTERRUPT) == 0)
+ shared = SA_SHIRQ;
+
+ error = request_irq(irq, ahc_linux_isr, shared, "aic7xxx", ahc);
+ if (error == 0)
+ ahc->platform_data->irq = irq;
+
+ return (-error);
}
static int
-aic7770_linux_config(struct aic7770_identity *entry, aic7770_dev_t dev,
- u_int eisaBase)
+aic7770_probe(struct device *dev)
{
+ struct eisa_device *edev = to_eisa_device(dev);
+ u_int eisaBase = edev->base_addr+AHC_EISA_SLOT_OFFSET;
struct ahc_softc *ahc;
char buf[80];
char *name;
int error;
- /*
- * Allocate a softc for this card and
- * set it up for attachment by our
- * common detect routine.
- */
sprintf(buf, "ahc_eisa:%d", eisaBase >> 12);
name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
if (name == NULL)
@@ -181,84 +92,62 @@ aic7770_linux_config(struct aic7770_identity *entry, aic7770_dev_t dev,
ahc = ahc_alloc(&aic7xxx_driver_template, name);
if (ahc == NULL)
return (ENOMEM);
- error = aic7770_config(ahc, entry, eisaBase);
+ error = aic7770_config(ahc, aic7770_ident_table + edev->id.driver_data,
+ eisaBase);
if (error != 0) {
ahc->bsh.ioport = 0;
ahc_free(ahc);
return (error);
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- dev->driver_data = (void *)ahc;
+
+ dev_set_drvdata(dev, ahc);
+
if (aic7xxx_detect_complete)
error = ahc_linux_register_host(ahc, &aic7xxx_driver_template);
-#endif
return (error);
}
-int
-aic7770_map_registers(struct ahc_softc *ahc, u_int port)
-{
- /*
- * Lock out other contenders for our i/o space.
- */
- if (request_region(port, AHC_EISA_IOSIZE, "aic7xxx") == 0)
- return (ENOMEM);
- ahc->tag = BUS_SPACE_PIO;
- ahc->bsh.ioport = port;
- return (0);
-}
-
-int
-aic7770_map_int(struct ahc_softc *ahc, u_int irq)
+static int
+aic7770_remove(struct device *dev)
{
- int error;
- int shared;
+ struct ahc_softc *ahc = dev_get_drvdata(dev);
+ u_long s;
- shared = 0;
- if ((ahc->flags & AHC_EDGE_INTERRUPT) == 0)
- shared = SA_SHIRQ;
+ ahc_lock(ahc, &s);
+ ahc_intr_enable(ahc, FALSE);
+ ahc_unlock(ahc, &s);
- error = request_irq(irq, ahc_linux_isr, shared, "aic7xxx", ahc);
- if (error == 0)
- ahc->platform_data->irq = irq;
-
- return (-error);
+ ahc_free(ahc);
+ return 0;
}
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-static int
-aic7770_eisa_dev_probe(struct device *dev)
+
+static struct eisa_device_id aic7770_ids[] = {
+ { "ADP7771", 0 }, /* AHA 274x */
+ { "ADP7756", 1 }, /* AHA 284x BIOS enabled */
+ { "ADP7757", 2 }, /* AHA 284x BIOS disabled */
+ { "ADP7782", 3 }, /* AHA 274x Olivetti OEM */
+ { "ADP7783", 4 }, /* AHA 274x Olivetti OEM (Differential) */
+ { "ADP7770", 5 }, /* AIC7770 generic */
+ { "" }
+};
+
+static struct eisa_driver aic7770_driver = {
+ .id_table = aic7770_ids,
+ .driver = {
+ .name = "aic7xxx",
+ .probe = aic7770_probe,
+ .remove = aic7770_remove,
+ }
+};
+
+int
+ahc_linux_eisa_init(void)
{
- struct eisa_device *edev;
-
- edev = to_eisa_device(dev);
- return (aic7770_linux_config(aic7770_ident_table + edev->id.driver_data,
- dev, edev->base_addr+AHC_EISA_SLOT_OFFSET));
+ return eisa_driver_register(&aic7770_driver);
}
-
-static int
-aic7770_eisa_dev_remove(struct device *dev)
+
+void
+ahc_linux_eisa_exit(void)
{
- struct ahc_softc *ahc;
- u_long l;
-
- /*
- * We should be able to just perform
- * the free directly, but check our
- * list for extra sanity.
- */
- ahc_list_lock(&l);
- ahc = ahc_find_softc((struct ahc_softc *)dev->driver_data);
- if (ahc != NULL) {
- u_long s;
-
- ahc_lock(ahc, &s);
- ahc_intr_enable(ahc, FALSE);
- ahc_unlock(ahc, &s);
- ahc_free(ahc);
- }
- ahc_list_unlock(&l);
-
- return (0);
+ eisa_driver_unregister(&aic7770_driver);
}
-#endif
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 550c9921691..5f526dd0aaa 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -1511,17 +1511,17 @@ ahd_linux_dev_reset(Scsi_Cmnd *cmd)
ahd_name(ahd), cmd->device->channel, cmd->device->id,
cmd->device->lun, cmd);
#endif
- ahd_midlayer_entrypoint_lock(ahd, &s);
+ ahd_lock(ahd, &s);
dev = ahd_linux_get_device(ahd, cmd->device->channel, cmd->device->id,
cmd->device->lun, /*alloc*/FALSE);
if (dev == NULL) {
- ahd_midlayer_entrypoint_unlock(ahd, &s);
+ ahd_unlock(ahd, &s);
kfree(recovery_cmd);
return (FAILED);
}
if ((scb = ahd_get_scb(ahd, AHD_NEVER_COL_IDX)) == NULL) {
- ahd_midlayer_entrypoint_unlock(ahd, &s);
+ ahd_unlock(ahd, &s);
kfree(recovery_cmd);
return (FAILED);
}
@@ -1570,7 +1570,7 @@ ahd_linux_dev_reset(Scsi_Cmnd *cmd)
spin_lock_irq(&ahd->platform_data->spin_lock);
ahd_schedule_runq(ahd);
ahd_linux_run_complete_queue(ahd);
- ahd_midlayer_entrypoint_unlock(ahd, &s);
+ ahd_unlock(ahd, &s);
printf("%s: Device reset returning 0x%x\n", ahd_name(ahd), retval);
return (retval);
}
@@ -1591,11 +1591,11 @@ ahd_linux_bus_reset(Scsi_Cmnd *cmd)
printf("%s: Bus reset called for cmd %p\n",
ahd_name(ahd), cmd);
#endif
- ahd_midlayer_entrypoint_lock(ahd, &s);
+ ahd_lock(ahd, &s);
found = ahd_reset_channel(ahd, cmd->device->channel + 'A',
/*initiate reset*/TRUE);
ahd_linux_run_complete_queue(ahd);
- ahd_midlayer_entrypoint_unlock(ahd, &s);
+ ahd_unlock(ahd, &s);
if (bootverbose)
printf("%s: SCSI bus reset delivered. "
@@ -2488,7 +2488,7 @@ ahd_linux_dv_thread(void *data)
sprintf(current->comm, "ahd_dv_%d", ahd->unit);
#else
daemonize("ahd_dv_%d", ahd->unit);
- current->flags |= PF_FREEZE;
+ current->flags |= PF_NOFREEZE;
#endif
unlock_kernel();
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index 605f92b6c5c..7823e52e99a 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -112,23 +112,6 @@ typedef Scsi_Cmnd *ahd_io_ctx_t;
#define ahd_le32toh(x) le32_to_cpu(x)
#define ahd_le64toh(x) le64_to_cpu(x)
-#ifndef LITTLE_ENDIAN
-#define LITTLE_ENDIAN 1234
-#endif
-
-#ifndef BIG_ENDIAN
-#define BIG_ENDIAN 4321
-#endif
-
-#ifndef BYTE_ORDER
-#if defined(__BIG_ENDIAN)
-#define BYTE_ORDER BIG_ENDIAN
-#endif
-#if defined(__LITTLE_ENDIAN)
-#define BYTE_ORDER LITTLE_ENDIAN
-#endif
-#endif /* BYTE_ORDER */
-
/************************* Configuration Data *********************************/
extern uint32_t aic79xx_allow_memio;
extern int aic79xx_detect_complete;
diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h
index 8ff16fd8ed4..0948d50ae75 100644
--- a/drivers/scsi/aic7xxx/aic7xxx.h
+++ b/drivers/scsi/aic7xxx/aic7xxx.h
@@ -346,7 +346,6 @@ typedef enum {
* controller.
*/
AHC_NEWEEPROM_FMT = 0x4000,
- AHC_RESOURCE_SHORTAGE = 0x8000,
AHC_TQINFIFO_BLOCKED = 0x10000, /* Blocked waiting for ATIOs */
AHC_INT50_SPEEDFLEX = 0x20000, /*
* Internal 50pin connector
@@ -1200,7 +1199,6 @@ void ahc_pause_and_flushwork(struct ahc_softc *ahc);
int ahc_suspend(struct ahc_softc *ahc);
int ahc_resume(struct ahc_softc *ahc);
void ahc_softc_insert(struct ahc_softc *);
-struct ahc_softc *ahc_find_softc(struct ahc_softc *ahc);
void ahc_set_unit(struct ahc_softc *, int);
void ahc_set_name(struct ahc_softc *, char *);
void ahc_alloc_scbs(struct ahc_softc *ahc);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c
index 9a6b4a570aa..8a2bb6f8d77 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_core.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_core.c
@@ -3934,22 +3934,6 @@ ahc_softc_insert(struct ahc_softc *ahc)
ahc->init_level++;
}
-/*
- * Verify that the passed in softc pointer is for a
- * controller that is still configured.
- */
-struct ahc_softc *
-ahc_find_softc(struct ahc_softc *ahc)
-{
- struct ahc_softc *list_ahc;
-
- TAILQ_FOREACH(list_ahc, &ahc_tailq, links) {
- if (list_ahc == ahc)
- return (ahc);
- }
- return (NULL);
-}
-
void
ahc_set_unit(struct ahc_softc *ahc, int unit)
{
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index d978e4a3e97..b89094db14c 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -122,8 +122,6 @@
#include "aic7xxx_osm.h"
#include "aic7xxx_inline.h"
#include <scsi/scsicam.h>
-#include <scsi/scsi_transport.h>
-#include <scsi/scsi_transport_spi.h>
static struct scsi_transport_template *ahc_linux_transport_template = NULL;
@@ -134,11 +132,6 @@ static struct scsi_transport_template *ahc_linux_transport_template = NULL;
#include "aiclib.c"
#include <linux/init.h> /* __setup */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-#include "sd.h" /* For geometry detection */
-#endif
-
#include <linux/mm.h> /* For fetching system memory size */
#include <linux/blkdev.h> /* For block_size() */
#include <linux/delay.h> /* For ssleep/msleep */
@@ -148,11 +141,6 @@ static struct scsi_transport_template *ahc_linux_transport_template = NULL;
*/
spinlock_t ahc_list_spinlock;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-/* For dynamic sglist size calculation. */
-u_int ahc_linux_nseg;
-#endif
-
/*
* Set this to the delay in seconds after SCSI bus reset.
* Note, we honor this only for the initial bus reset.
@@ -342,22 +330,6 @@ static uint32_t aic7xxx_extended;
static uint32_t aic7xxx_pci_parity = ~0;
/*
- * Certain newer motherboards have put new PCI based devices into the
- * IO spaces that used to typically be occupied by VLB or EISA cards.
- * This overlap can cause these newer motherboards to lock up when scanned
- * for older EISA and VLB devices. Setting this option to non-0 will
- * cause the driver to skip scanning for any VLB or EISA controllers and
- * only support the PCI controllers. NOTE: this means that if the kernel
- * os compiled with PCI support disabled, then setting this to non-0
- * would result in never finding any devices :)
- */
-#ifndef CONFIG_AIC7XXX_PROBE_EISA_VL
-uint32_t aic7xxx_probe_eisa_vl;
-#else
-uint32_t aic7xxx_probe_eisa_vl = ~0;
-#endif
-
-/*
* There are lots of broken chipsets in the world. Some of them will
* violate the PCI spec when we issue byte sized memory writes to our
* controller. I/O mapped register access, if allowed by the given
@@ -433,51 +405,27 @@ MODULE_PARM_DESC(aic7xxx,
);
static void ahc_linux_handle_scsi_status(struct ahc_softc *,
- struct ahc_linux_device *,
+ struct scsi_device *,
struct scb *);
static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc,
- Scsi_Cmnd *cmd);
+ struct scsi_cmnd *cmd);
static void ahc_linux_sem_timeout(u_long arg);
static void ahc_linux_freeze_simq(struct ahc_softc *ahc);
static void ahc_linux_release_simq(u_long arg);
-static void ahc_linux_dev_timed_unfreeze(u_long arg);
-static int ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag);
+static int ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag);
static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc);
-static void ahc_linux_size_nseg(void);
-static void ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc);
static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc,
struct ahc_devinfo *devinfo);
-static void ahc_linux_device_queue_depth(struct ahc_softc *ahc,
- struct ahc_linux_device *dev);
-static struct ahc_linux_target* ahc_linux_alloc_target(struct ahc_softc*,
- u_int, u_int);
-static void ahc_linux_free_target(struct ahc_softc*,
- struct ahc_linux_target*);
-static struct ahc_linux_device* ahc_linux_alloc_device(struct ahc_softc*,
- struct ahc_linux_target*,
- u_int);
-static void ahc_linux_free_device(struct ahc_softc*,
- struct ahc_linux_device*);
-static void ahc_linux_run_device_queue(struct ahc_softc*,
- struct ahc_linux_device*);
+static void ahc_linux_device_queue_depth(struct scsi_device *);
+static int ahc_linux_run_command(struct ahc_softc*,
+ struct ahc_linux_device *,
+ struct scsi_cmnd *);
static void ahc_linux_setup_tag_info_global(char *p);
static aic_option_callback_t ahc_linux_setup_tag_info;
static int aic7xxx_setup(char *s);
static int ahc_linux_next_unit(void);
-static void ahc_runq_tasklet(unsigned long data);
-static struct ahc_cmd *ahc_linux_run_complete_queue(struct ahc_softc *ahc);
/********************************* Inlines ************************************/
-static __inline void ahc_schedule_runq(struct ahc_softc *ahc);
-static __inline struct ahc_linux_device*
- ahc_linux_get_device(struct ahc_softc *ahc, u_int channel,
- u_int target, u_int lun, int alloc);
-static __inline void ahc_schedule_completeq(struct ahc_softc *ahc);
-static __inline void ahc_linux_check_device_queue(struct ahc_softc *ahc,
- struct ahc_linux_device *dev);
-static __inline struct ahc_linux_device *
- ahc_linux_next_device_to_run(struct ahc_softc *ahc);
-static __inline void ahc_linux_run_device_queues(struct ahc_softc *ahc);
static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*);
static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb,
@@ -485,132 +433,9 @@ static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb,
dma_addr_t addr, bus_size_t len);
static __inline void
-ahc_schedule_completeq(struct ahc_softc *ahc)
-{
- if ((ahc->platform_data->flags & AHC_RUN_CMPLT_Q_TIMER) == 0) {
- ahc->platform_data->flags |= AHC_RUN_CMPLT_Q_TIMER;
- ahc->platform_data->completeq_timer.expires = jiffies;
- add_timer(&ahc->platform_data->completeq_timer);
- }
-}
-
-/*
- * Must be called with our lock held.
- */
-static __inline void
-ahc_schedule_runq(struct ahc_softc *ahc)
-{
- tasklet_schedule(&ahc->platform_data->runq_tasklet);
-}
-
-static __inline struct ahc_linux_device*
-ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target,
- u_int lun, int alloc)
-{
- struct ahc_linux_target *targ;
- struct ahc_linux_device *dev;
- u_int target_offset;
-
- target_offset = target;
- if (channel != 0)
- target_offset += 8;
- targ = ahc->platform_data->targets[target_offset];
- if (targ == NULL) {
- if (alloc != 0) {
- targ = ahc_linux_alloc_target(ahc, channel, target);
- if (targ == NULL)
- return (NULL);
- } else
- return (NULL);
- }
- dev = targ->devices[lun];
- if (dev == NULL && alloc != 0)
- dev = ahc_linux_alloc_device(ahc, targ, lun);
- return (dev);
-}
-
-#define AHC_LINUX_MAX_RETURNED_ERRORS 4
-static struct ahc_cmd *
-ahc_linux_run_complete_queue(struct ahc_softc *ahc)
-{
- struct ahc_cmd *acmd;
- u_long done_flags;
- int with_errors;
-
- with_errors = 0;
- ahc_done_lock(ahc, &done_flags);
- while ((acmd = TAILQ_FIRST(&ahc->platform_data->completeq)) != NULL) {
- Scsi_Cmnd *cmd;
-
- if (with_errors > AHC_LINUX_MAX_RETURNED_ERRORS) {
- /*
- * Linux uses stack recursion to requeue
- * commands that need to be retried. Avoid
- * blowing out the stack by "spoon feeding"
- * commands that completed with error back
- * the operating system in case they are going
- * to be retried. "ick"
- */
- ahc_schedule_completeq(ahc);
- break;
- }
- TAILQ_REMOVE(&ahc->platform_data->completeq,
- acmd, acmd_links.tqe);
- cmd = &acmd_scsi_cmd(acmd);
- cmd->host_scribble = NULL;
- if (ahc_cmd_get_transaction_status(cmd) != DID_OK
- || (cmd->result & 0xFF) != SCSI_STATUS_OK)
- with_errors++;
-
- cmd->scsi_done(cmd);
- }
- ahc_done_unlock(ahc, &done_flags);
- return (acmd);
-}
-
-static __inline void
-ahc_linux_check_device_queue(struct ahc_softc *ahc,
- struct ahc_linux_device *dev)
-{
- if ((dev->flags & AHC_DEV_FREEZE_TIL_EMPTY) != 0
- && dev->active == 0) {
- dev->flags &= ~AHC_DEV_FREEZE_TIL_EMPTY;
- dev->qfrozen--;
- }
-
- if (TAILQ_FIRST(&dev->busyq) == NULL
- || dev->openings == 0 || dev->qfrozen != 0)
- return;
-
- ahc_linux_run_device_queue(ahc, dev);
-}
-
-static __inline struct ahc_linux_device *
-ahc_linux_next_device_to_run(struct ahc_softc *ahc)
-{
-
- if ((ahc->flags & AHC_RESOURCE_SHORTAGE) != 0
- || (ahc->platform_data->qfrozen != 0))
- return (NULL);
- return (TAILQ_FIRST(&ahc->platform_data->device_runq));
-}
-
-static __inline void
-ahc_linux_run_device_queues(struct ahc_softc *ahc)
-{
- struct ahc_linux_device *dev;
-
- while ((dev = ahc_linux_next_device_to_run(ahc)) != NULL) {
- TAILQ_REMOVE(&ahc->platform_data->device_runq, dev, links);
- dev->flags &= ~AHC_DEV_ON_RUN_LIST;
- ahc_linux_check_device_queue(ahc, dev);
- }
-}
-
-static __inline void
ahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb)
{
- Scsi_Cmnd *cmd;
+ struct scsi_cmnd *cmd;
cmd = scb->io_ctx;
ahc_sync_sglist(ahc, scb, BUS_DMASYNC_POSTWRITE);
@@ -650,121 +475,15 @@ ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb,
return (consumed);
}
-/************************ Host template entry points *************************/
-static int ahc_linux_detect(Scsi_Host_Template *);
-static int ahc_linux_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *));
-static const char *ahc_linux_info(struct Scsi_Host *);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
-static int ahc_linux_slave_alloc(Scsi_Device *);
-static int ahc_linux_slave_configure(Scsi_Device *);
-static void ahc_linux_slave_destroy(Scsi_Device *);
-#if defined(__i386__)
-static int ahc_linux_biosparam(struct scsi_device*,
- struct block_device*,
- sector_t, int[]);
-#endif
-#else
-static int ahc_linux_release(struct Scsi_Host *);
-static void ahc_linux_select_queue_depth(struct Scsi_Host *host,
- Scsi_Device *scsi_devs);
-#if defined(__i386__)
-static int ahc_linux_biosparam(Disk *, kdev_t, int[]);
-#endif
-#endif
-static int ahc_linux_bus_reset(Scsi_Cmnd *);
-static int ahc_linux_dev_reset(Scsi_Cmnd *);
-static int ahc_linux_abort(Scsi_Cmnd *);
-
-/*
- * Calculate a safe value for AHC_NSEG (as expressed through ahc_linux_nseg).
- *
- * In pre-2.5.X...
- * The midlayer allocates an S/G array dynamically when a command is issued
- * using SCSI malloc. This array, which is in an OS dependent format that
- * must later be copied to our private S/G list, is sized to house just the
- * number of segments needed for the current transfer. Since the code that
- * sizes the SCSI malloc pool does not take into consideration fragmentation
- * of the pool, executing transactions numbering just a fraction of our
- * concurrent transaction limit with list lengths aproaching AHC_NSEG will
- * quickly depleat the SCSI malloc pool of usable space. Unfortunately, the
- * mid-layer does not properly handle this scsi malloc failures for the S/G
- * array and the result can be a lockup of the I/O subsystem. We try to size
- * our S/G list so that it satisfies our drivers allocation requirements in
- * addition to avoiding fragmentation of the SCSI malloc pool.
- */
-static void
-ahc_linux_size_nseg(void)
-{
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- u_int cur_size;
- u_int best_size;
-
- /*
- * The SCSI allocator rounds to the nearest 512 bytes
- * an cannot allocate across a page boundary. Our algorithm
- * is to start at 1K of scsi malloc space per-command and
- * loop through all factors of the PAGE_SIZE and pick the best.
- */
- best_size = 0;
- for (cur_size = 1024; cur_size <= PAGE_SIZE; cur_size *= 2) {
- u_int nseg;
-
- nseg = cur_size / sizeof(struct scatterlist);
- if (nseg < AHC_LINUX_MIN_NSEG)
- continue;
-
- if (best_size == 0) {
- best_size = cur_size;
- ahc_linux_nseg = nseg;
- } else {
- u_int best_rem;
- u_int cur_rem;
-
- /*
- * Compare the traits of the current "best_size"
- * with the current size to determine if the
- * current size is a better size.
- */
- best_rem = best_size % sizeof(struct scatterlist);
- cur_rem = cur_size % sizeof(struct scatterlist);
- if (cur_rem < best_rem) {
- best_size = cur_size;
- ahc_linux_nseg = nseg;
- }
- }
- }
-#endif
-}
-
/*
* Try to detect an Adaptec 7XXX controller.
*/
static int
-ahc_linux_detect(Scsi_Host_Template *template)
+ahc_linux_detect(struct scsi_host_template *template)
{
struct ahc_softc *ahc;
int found = 0;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- /*
- * It is a bug that the upper layer takes
- * this lock just prior to calling us.
- */
- spin_unlock_irq(&io_request_lock);
-#endif
-
- /*
- * Sanity checking of Linux SCSI data structures so
- * that some of our hacks^H^H^H^H^Hassumptions aren't
- * violated.
- */
- if (offsetof(struct ahc_cmd_internal, end)
- > offsetof(struct scsi_cmnd, host_scribble)) {
- printf("ahc_linux_detect: SCSI data structures changed.\n");
- printf("ahc_linux_detect: Unable to attach\n");
- return (0);
- }
- ahc_linux_size_nseg();
/*
* If we've been passed any parameters, process them now.
*/
@@ -793,48 +512,11 @@ ahc_linux_detect(Scsi_Host_Template *template)
found++;
}
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- spin_lock_irq(&io_request_lock);
-#endif
aic7xxx_detect_complete++;
return (found);
}
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-/*
- * Free the passed in Scsi_Host memory structures prior to unloading the
- * module.
- */
-int
-ahc_linux_release(struct Scsi_Host * host)
-{
- struct ahc_softc *ahc;
- u_long l;
-
- ahc_list_lock(&l);
- if (host != NULL) {
-
- /*
- * We should be able to just perform
- * the free directly, but check our
- * list for extra sanity.
- */
- ahc = ahc_find_softc(*(struct ahc_softc **)host->hostdata);
- if (ahc != NULL) {
- u_long s;
-
- ahc_lock(ahc, &s);
- ahc_intr_enable(ahc, FALSE);
- ahc_unlock(ahc, &s);
- ahc_free(ahc);
- }
- }
- ahc_list_unlock(&l);
- return (0);
-}
-#endif
-
/*
* Return a string describing the driver.
*/
@@ -867,11 +549,10 @@ ahc_linux_info(struct Scsi_Host *host)
* Queue an SCB to the controller.
*/
static int
-ahc_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
+ahc_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
{
struct ahc_softc *ahc;
- struct ahc_linux_device *dev;
- u_long flags;
+ struct ahc_linux_device *dev = scsi_transport_device_data(cmd->device);
ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
@@ -880,205 +561,197 @@ ahc_linux_queue(Scsi_Cmnd * cmd, void (*scsi_done) (Scsi_Cmnd *))
*/
cmd->scsi_done = scsi_done;
- ahc_midlayer_entrypoint_lock(ahc, &flags);
-
/*
* Close the race of a command that was in the process of
* being queued to us just as our simq was frozen. Let
* DV commands through so long as we are only frozen to
* perform DV.
*/
- if (ahc->platform_data->qfrozen != 0) {
+ if (ahc->platform_data->qfrozen != 0)
+ return SCSI_MLQUEUE_HOST_BUSY;
- ahc_cmd_set_transaction_status(cmd, CAM_REQUEUE_REQ);
- ahc_linux_queue_cmd_complete(ahc, cmd);
- ahc_schedule_completeq(ahc);
- ahc_midlayer_entrypoint_unlock(ahc, &flags);
- return (0);
- }
- dev = ahc_linux_get_device(ahc, cmd->device->channel, cmd->device->id,
- cmd->device->lun, /*alloc*/TRUE);
- if (dev == NULL) {
- ahc_cmd_set_transaction_status(cmd, CAM_RESRC_UNAVAIL);
- ahc_linux_queue_cmd_complete(ahc, cmd);
- ahc_schedule_completeq(ahc);
- ahc_midlayer_entrypoint_unlock(ahc, &flags);
- printf("%s: aic7xxx_linux_queue - Unable to allocate device!\n",
- ahc_name(ahc));
- return (0);
- }
cmd->result = CAM_REQ_INPROG << 16;
- TAILQ_INSERT_TAIL(&dev->busyq, (struct ahc_cmd *)cmd, acmd_links.tqe);
- if ((dev->flags & AHC_DEV_ON_RUN_LIST) == 0) {
- TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links);
- dev->flags |= AHC_DEV_ON_RUN_LIST;
- ahc_linux_run_device_queues(ahc);
- }
- ahc_midlayer_entrypoint_unlock(ahc, &flags);
- return (0);
+
+ return ahc_linux_run_command(ahc, dev, cmd);
+}
+
+static inline struct scsi_target **
+ahc_linux_target_in_softc(struct scsi_target *starget)
+{
+ struct ahc_softc *ahc =
+ *((struct ahc_softc **)dev_to_shost(&starget->dev)->hostdata);
+ unsigned int target_offset;
+
+ target_offset = starget->id;
+ if (starget->channel != 0)
+ target_offset += 8;
+
+ return &ahc->platform_data->starget[target_offset];
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
static int
-ahc_linux_slave_alloc(Scsi_Device *device)
+ahc_linux_target_alloc(struct scsi_target *starget)
{
- struct ahc_softc *ahc;
+ struct ahc_softc *ahc =
+ *((struct ahc_softc **)dev_to_shost(&starget->dev)->hostdata);
+ struct seeprom_config *sc = ahc->seep_config;
+ unsigned long flags;
+ struct scsi_target **ahc_targp = ahc_linux_target_in_softc(starget);
+ struct ahc_linux_target *targ = scsi_transport_target_data(starget);
+ unsigned short scsirate;
+ struct ahc_devinfo devinfo;
+ struct ahc_initiator_tinfo *tinfo;
+ struct ahc_tmode_tstate *tstate;
+ char channel = starget->channel + 'A';
+ unsigned int our_id = ahc->our_id;
+ unsigned int target_offset;
- ahc = *((struct ahc_softc **)device->host->hostdata);
- if (bootverbose)
- printf("%s: Slave Alloc %d\n", ahc_name(ahc), device->id);
- return (0);
+ target_offset = starget->id;
+ if (starget->channel != 0)
+ target_offset += 8;
+
+ if (starget->channel)
+ our_id = ahc->our_id_b;
+
+ ahc_lock(ahc, &flags);
+
+ BUG_ON(*ahc_targp != NULL);
+
+ *ahc_targp = starget;
+ memset(targ, 0, sizeof(*targ));
+
+ if (sc) {
+ int maxsync = AHC_SYNCRATE_DT;
+ int ultra = 0;
+ int flags = sc->device_flags[target_offset];
+
+ if (ahc->flags & AHC_NEWEEPROM_FMT) {
+ if (flags & CFSYNCHISULTRA)
+ ultra = 1;
+ } else if (flags & CFULTRAEN)
+ ultra = 1;
+ /* AIC nutcase; 10MHz appears as ultra = 1, CFXFER = 0x04
+ * change it to ultra=0, CFXFER = 0 */
+ if(ultra && (flags & CFXFER) == 0x04) {
+ ultra = 0;
+ flags &= ~CFXFER;
+ }
+
+ if ((ahc->features & AHC_ULTRA2) != 0) {
+ scsirate = (flags & CFXFER) | (ultra ? 0x8 : 0);
+ } else {
+ scsirate = (flags & CFXFER) << 4;
+ maxsync = ultra ? AHC_SYNCRATE_ULTRA :
+ AHC_SYNCRATE_FAST;
+ }
+ spi_max_width(starget) = (flags & CFWIDEB) ? 1 : 0;
+ if (!(flags & CFSYNCH))
+ spi_max_offset(starget) = 0;
+ spi_min_period(starget) =
+ ahc_find_period(ahc, scsirate, maxsync);
+
+ tinfo = ahc_fetch_transinfo(ahc, channel, ahc->our_id,
+ starget->id, &tstate);
+ }
+ ahc_compile_devinfo(&devinfo, our_id, starget->id,
+ CAM_LUN_WILDCARD, channel,
+ ROLE_INITIATOR);
+ ahc_set_syncrate(ahc, &devinfo, NULL, 0, 0, 0,
+ AHC_TRANS_GOAL, /*paused*/FALSE);
+ ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
+ AHC_TRANS_GOAL, /*paused*/FALSE);
+ ahc_unlock(ahc, &flags);
+
+ return 0;
+}
+
+static void
+ahc_linux_target_destroy(struct scsi_target *starget)
+{
+ struct scsi_target **ahc_targp = ahc_linux_target_in_softc(starget);
+
+ *ahc_targp = NULL;
}
static int
-ahc_linux_slave_configure(Scsi_Device *device)
+ahc_linux_slave_alloc(struct scsi_device *sdev)
{
- struct ahc_softc *ahc;
- struct ahc_linux_device *dev;
- u_long flags;
+ struct ahc_softc *ahc =
+ *((struct ahc_softc **)sdev->host->hostdata);
+ struct scsi_target *starget = sdev->sdev_target;
+ struct ahc_linux_target *targ = scsi_transport_target_data(starget);
+ struct ahc_linux_device *dev;
- ahc = *((struct ahc_softc **)device->host->hostdata);
if (bootverbose)
- printf("%s: Slave Configure %d\n", ahc_name(ahc), device->id);
- ahc_midlayer_entrypoint_lock(ahc, &flags);
+ printf("%s: Slave Alloc %d\n", ahc_name(ahc), sdev->id);
+
+ BUG_ON(targ->sdev[sdev->lun] != NULL);
+
+ dev = scsi_transport_device_data(sdev);
+ memset(dev, 0, sizeof(*dev));
+
/*
- * Since Linux has attached to the device, configure
- * it so we don't free and allocate the device
- * structure on every command.
+ * We start out life using untagged
+ * transactions of which we allow one.
*/
- dev = ahc_linux_get_device(ahc, device->channel,
- device->id, device->lun,
- /*alloc*/TRUE);
- if (dev != NULL) {
- dev->flags &= ~AHC_DEV_UNCONFIGURED;
- dev->scsi_device = device;
- ahc_linux_device_queue_depth(ahc, dev);
- }
- ahc_midlayer_entrypoint_unlock(ahc, &flags);
+ dev->openings = 1;
- /* Initial Domain Validation */
- if (!spi_initial_dv(device->sdev_target))
- spi_dv_device(device);
+ /*
+ * Set maxtags to 0. This will be changed if we
+ * later determine that we are dealing with
+ * a tagged queuing capable device.
+ */
+ dev->maxtags = 0;
+
+ targ->sdev[sdev->lun] = sdev;
- return (0);
+ return 0;
}
-static void
-ahc_linux_slave_destroy(Scsi_Device *device)
+static int
+ahc_linux_slave_configure(struct scsi_device *sdev)
{
struct ahc_softc *ahc;
- struct ahc_linux_device *dev;
- u_long flags;
- ahc = *((struct ahc_softc **)device->host->hostdata);
+ ahc = *((struct ahc_softc **)sdev->host->hostdata);
+
if (bootverbose)
- printf("%s: Slave Destroy %d\n", ahc_name(ahc), device->id);
- ahc_midlayer_entrypoint_lock(ahc, &flags);
- dev = ahc_linux_get_device(ahc, device->channel,
- device->id, device->lun,
- /*alloc*/FALSE);
- /*
- * Filter out "silly" deletions of real devices by only
- * deleting devices that have had slave_configure()
- * called on them. All other devices that have not
- * been configured will automatically be deleted by
- * the refcounting process.
- */
- if (dev != NULL
- && (dev->flags & AHC_DEV_SLAVE_CONFIGURED) != 0) {
- dev->flags |= AHC_DEV_UNCONFIGURED;
- if (TAILQ_EMPTY(&dev->busyq)
- && dev->active == 0
- && (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0)
- ahc_linux_free_device(ahc, dev);
- }
- ahc_midlayer_entrypoint_unlock(ahc, &flags);
+ printf("%s: Slave Configure %d\n", ahc_name(ahc), sdev->id);
+
+ ahc_linux_device_queue_depth(sdev);
+
+ /* Initial Domain Validation */
+ if (!spi_initial_dv(sdev->sdev_target))
+ spi_dv_device(sdev);
+
+ return 0;
}
-#else
-/*
- * Sets the queue depth for each SCSI device hanging
- * off the input host adapter.
- */
+
static void
-ahc_linux_select_queue_depth(struct Scsi_Host *host, Scsi_Device *scsi_devs)
+ahc_linux_slave_destroy(struct scsi_device *sdev)
{
- Scsi_Device *device;
- Scsi_Device *ldev;
struct ahc_softc *ahc;
- u_long flags;
-
- ahc = *((struct ahc_softc **)host->hostdata);
- ahc_lock(ahc, &flags);
- for (device = scsi_devs; device != NULL; device = device->next) {
+ struct ahc_linux_device *dev = scsi_transport_device_data(sdev);
+ struct ahc_linux_target *targ = scsi_transport_target_data(sdev->sdev_target);
- /*
- * Watch out for duplicate devices. This works around
- * some quirks in how the SCSI scanning code does its
- * device management.
- */
- for (ldev = scsi_devs; ldev != device; ldev = ldev->next) {
- if (ldev->host == device->host
- && ldev->channel == device->channel
- && ldev->id == device->id
- && ldev->lun == device->lun)
- break;
- }
- /* Skip duplicate. */
- if (ldev != device)
- continue;
+ ahc = *((struct ahc_softc **)sdev->host->hostdata);
+ if (bootverbose)
+ printf("%s: Slave Destroy %d\n", ahc_name(ahc), sdev->id);
- if (device->host == host) {
- struct ahc_linux_device *dev;
+ BUG_ON(dev->active);
- /*
- * Since Linux has attached to the device, configure
- * it so we don't free and allocate the device
- * structure on every command.
- */
- dev = ahc_linux_get_device(ahc, device->channel,
- device->id, device->lun,
- /*alloc*/TRUE);
- if (dev != NULL) {
- dev->flags &= ~AHC_DEV_UNCONFIGURED;
- dev->scsi_device = device;
- ahc_linux_device_queue_depth(ahc, dev);
- device->queue_depth = dev->openings
- + dev->active;
- if ((dev->flags & (AHC_DEV_Q_BASIC
- | AHC_DEV_Q_TAGGED)) == 0) {
- /*
- * We allow the OS to queue 2 untagged
- * transactions to us at any time even
- * though we can only execute them
- * serially on the controller/device.
- * This should remove some latency.
- */
- device->queue_depth = 2;
- }
- }
- }
- }
- ahc_unlock(ahc, &flags);
+ targ->sdev[sdev->lun] = NULL;
}
-#endif
#if defined(__i386__)
/*
* Return the disk geometry for the given SCSI device.
*/
static int
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
ahc_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev,
sector_t capacity, int geom[])
{
uint8_t *bh;
-#else
-ahc_linux_biosparam(Disk *disk, kdev_t dev, int geom[])
-{
- struct scsi_device *sdev = disk->device;
- u_long capacity = disk->capacity;
- struct buffer_head *bh;
-#endif
int heads;
int sectors;
int cylinders;
@@ -1090,22 +763,11 @@ ahc_linux_biosparam(Disk *disk, kdev_t dev, int geom[])
ahc = *((struct ahc_softc **)sdev->host->hostdata);
channel = sdev->channel;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
bh = scsi_bios_ptable(bdev);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,17)
- bh = bread(MKDEV(MAJOR(dev), MINOR(dev) & ~0xf), 0, block_size(dev));
-#else
- bh = bread(MKDEV(MAJOR(dev), MINOR(dev) & ~0xf), 0, 1024);
-#endif
-
if (bh) {
ret = scsi_partsize(bh, capacity,
&geom[2], &geom[0], &geom[1]);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
kfree(bh);
-#else
- brelse(bh);
-#endif
if (ret != -1)
return (ret);
}
@@ -1135,7 +797,7 @@ ahc_linux_biosparam(Disk *disk, kdev_t dev, int geom[])
* Abort the current SCSI command(s).
*/
static int
-ahc_linux_abort(Scsi_Cmnd *cmd)
+ahc_linux_abort(struct scsi_cmnd *cmd)
{
int error;
@@ -1149,7 +811,7 @@ ahc_linux_abort(Scsi_Cmnd *cmd)
* Attempt to send a target reset message to the device that timed out.
*/
static int
-ahc_linux_dev_reset(Scsi_Cmnd *cmd)
+ahc_linux_dev_reset(struct scsi_cmnd *cmd)
{
int error;
@@ -1163,18 +825,18 @@ ahc_linux_dev_reset(Scsi_Cmnd *cmd)
* Reset the SCSI bus.
*/
static int
-ahc_linux_bus_reset(Scsi_Cmnd *cmd)
+ahc_linux_bus_reset(struct scsi_cmnd *cmd)
{
struct ahc_softc *ahc;
- u_long s;
int found;
+ unsigned long flags;
ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
- ahc_midlayer_entrypoint_lock(ahc, &s);
+
+ ahc_lock(ahc, &flags);
found = ahc_reset_channel(ahc, cmd->device->channel + 'A',
/*initiate reset*/TRUE);
- ahc_linux_run_complete_queue(ahc);
- ahc_midlayer_entrypoint_unlock(ahc, &s);
+ ahc_unlock(ahc, &flags);
if (bootverbose)
printf("%s: SCSI bus reset delivered. "
@@ -1183,7 +845,7 @@ ahc_linux_bus_reset(Scsi_Cmnd *cmd)
return SUCCESS;
}
-Scsi_Host_Template aic7xxx_driver_template = {
+struct scsi_host_template aic7xxx_driver_template = {
.module = THIS_MODULE,
.name = "aic7xxx",
.proc_info = ahc_linux_proc_info,
@@ -1202,37 +864,12 @@ Scsi_Host_Template aic7xxx_driver_template = {
.slave_alloc = ahc_linux_slave_alloc,
.slave_configure = ahc_linux_slave_configure,
.slave_destroy = ahc_linux_slave_destroy,
+ .target_alloc = ahc_linux_target_alloc,
+ .target_destroy = ahc_linux_target_destroy,
};
/**************************** Tasklet Handler *********************************/
-/*
- * In 2.4.X and above, this routine is called from a tasklet,
- * so we must re-acquire our lock prior to executing this code.
- * In all prior kernels, ahc_schedule_runq() calls this routine
- * directly and ahc_schedule_runq() is called with our lock held.
- */
-static void
-ahc_runq_tasklet(unsigned long data)
-{
- struct ahc_softc* ahc;
- struct ahc_linux_device *dev;
- u_long flags;
-
- ahc = (struct ahc_softc *)data;
- ahc_lock(ahc, &flags);
- while ((dev = ahc_linux_next_device_to_run(ahc)) != NULL) {
-
- TAILQ_REMOVE(&ahc->platform_data->device_runq, dev, links);
- dev->flags &= ~AHC_DEV_ON_RUN_LIST;
- ahc_linux_check_device_queue(ahc, dev);
- /* Yeild to our interrupt handler */
- ahc_unlock(ahc, &flags);
- ahc_lock(ahc, &flags);
- }
- ahc_unlock(ahc, &flags);
-}
-
/******************************** Macros **************************************/
#define BUILD_SCSIID(ahc, cmd) \
((((cmd)->device->id << TID_SHIFT) & TID) \
@@ -1278,37 +915,11 @@ int
ahc_dmamem_alloc(struct ahc_softc *ahc, bus_dma_tag_t dmat, void** vaddr,
int flags, bus_dmamap_t *mapp)
{
- bus_dmamap_t map;
-
- map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT);
- if (map == NULL)
- return (ENOMEM);
- /*
- * Although we can dma data above 4GB, our
- * "consistent" memory is below 4GB for
- * space efficiency reasons (only need a 4byte
- * address). For this reason, we have to reset
- * our dma mask when doing allocations.
- */
- if (ahc->dev_softc != NULL)
- if (pci_set_dma_mask(ahc->dev_softc, 0xFFFFFFFF)) {
- printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n");
- kfree(map);
- return (ENODEV);
- }
*vaddr = pci_alloc_consistent(ahc->dev_softc,
- dmat->maxsize, &map->bus_addr);
- if (ahc->dev_softc != NULL)
- if (pci_set_dma_mask(ahc->dev_softc,
- ahc->platform_data->hw_dma_mask)) {
- printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n");
- kfree(map);
- return (ENODEV);
- }
+ dmat->maxsize, mapp);
if (*vaddr == NULL)
- return (ENOMEM);
- *mapp = map;
- return(0);
+ return ENOMEM;
+ return 0;
}
void
@@ -1316,7 +927,7 @@ ahc_dmamem_free(struct ahc_softc *ahc, bus_dma_tag_t dmat,
void* vaddr, bus_dmamap_t map)
{
pci_free_consistent(ahc->dev_softc, dmat->maxsize,
- vaddr, map->bus_addr);
+ vaddr, map);
}
int
@@ -1330,7 +941,7 @@ ahc_dmamap_load(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map,
*/
bus_dma_segment_t stack_sg;
- stack_sg.ds_addr = map->bus_addr;
+ stack_sg.ds_addr = map;
stack_sg.ds_len = dmat->maxsize;
cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0);
return (0);
@@ -1339,12 +950,6 @@ ahc_dmamap_load(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map,
void
ahc_dmamap_destroy(struct ahc_softc *ahc, bus_dma_tag_t dmat, bus_dmamap_t map)
{
- /*
- * The map may is NULL in our < 2.3.X implementation.
- * Now it's 2.6.5, but just in case...
- */
- BUG_ON(map == NULL);
- free(map, M_DEVBUF);
}
int
@@ -1499,8 +1104,6 @@ aic7xxx_setup(char *s)
{ "debug", &ahc_debug },
#endif
{ "reverse_scan", &aic7xxx_reverse_scan },
- { "no_probe", &aic7xxx_probe_eisa_vl },
- { "probe_eisa_vl", &aic7xxx_probe_eisa_vl },
{ "periodic_otag", &aic7xxx_periodic_otag },
{ "pci_parity", &aic7xxx_pci_parity },
{ "seltime", &aic7xxx_seltime },
@@ -1550,7 +1153,7 @@ __setup("aic7xxx=", aic7xxx_setup);
uint32_t aic7xxx_verbose;
int
-ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template)
+ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *template)
{
char buf[80];
struct Scsi_Host *host;
@@ -1564,11 +1167,7 @@ ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template)
*((struct ahc_softc **)host->hostdata) = ahc;
ahc_lock(ahc, &s);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
scsi_assign_lock(host, &ahc->platform_data->spin_lock);
-#elif AHC_SCSI_HAS_HOST_LOCK != 0
- host->lock = &ahc->platform_data->spin_lock;
-#endif
ahc->platform_data->host = host;
host->can_queue = AHC_MAX_QUEUE;
host->cmd_per_lun = 2;
@@ -1587,19 +1186,14 @@ ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template)
ahc_set_name(ahc, new_name);
}
host->unique_id = ahc->unit;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- scsi_set_pci_device(host, ahc->dev_softc);
-#endif
ahc_linux_initialize_scsi_bus(ahc);
ahc_intr_enable(ahc, TRUE);
ahc_unlock(ahc, &s);
host->transportt = ahc_linux_transport_template;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
scsi_add_host(host, (ahc->dev_softc ? &ahc->dev_softc->dev : NULL)); /* XXX handle failure */
scsi_scan_host(host);
-#endif
return (0);
}
@@ -1717,19 +1311,9 @@ ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg)
if (ahc->platform_data == NULL)
return (ENOMEM);
memset(ahc->platform_data, 0, sizeof(struct ahc_platform_data));
- TAILQ_INIT(&ahc->platform_data->completeq);
- TAILQ_INIT(&ahc->platform_data->device_runq);
ahc->platform_data->irq = AHC_LINUX_NOIRQ;
- ahc->platform_data->hw_dma_mask = 0xFFFFFFFF;
ahc_lockinit(ahc);
- ahc_done_lockinit(ahc);
- init_timer(&ahc->platform_data->completeq_timer);
- ahc->platform_data->completeq_timer.data = (u_long)ahc;
- ahc->platform_data->completeq_timer.function =
- (ahc_linux_callback_t *)ahc_linux_thread_run_complete_queue;
init_MUTEX_LOCKED(&ahc->platform_data->eh_sem);
- tasklet_init(&ahc->platform_data->runq_tasklet, ahc_runq_tasklet,
- (unsigned long)ahc);
ahc->seltime = (aic7xxx_seltime & 0x3) << 4;
ahc->seltime_b = (aic7xxx_seltime & 0x3) << 4;
if (aic7xxx_pci_parity == 0)
@@ -1741,38 +1325,28 @@ ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg)
void
ahc_platform_free(struct ahc_softc *ahc)
{
- struct ahc_linux_target *targ;
- struct ahc_linux_device *dev;
+ struct scsi_target *starget;
int i, j;
if (ahc->platform_data != NULL) {
- del_timer_sync(&ahc->platform_data->completeq_timer);
- tasklet_kill(&ahc->platform_data->runq_tasklet);
if (ahc->platform_data->host != NULL) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
scsi_remove_host(ahc->platform_data->host);
-#endif
scsi_host_put(ahc->platform_data->host);
}
/* destroy all of the device and target objects */
for (i = 0; i < AHC_NUM_TARGETS; i++) {
- targ = ahc->platform_data->targets[i];
- if (targ != NULL) {
- /* Keep target around through the loop. */
- targ->refcount++;
+ starget = ahc->platform_data->starget[i];
+ if (starget != NULL) {
for (j = 0; j < AHC_NUM_LUNS; j++) {
+ struct ahc_linux_target *targ =
+ scsi_transport_target_data(starget);
- if (targ->devices[j] == NULL)
+ if (targ->sdev[j] == NULL)
continue;
- dev = targ->devices[j];
- ahc_linux_free_device(ahc, dev);
+ targ->sdev[j] = NULL;
}
- /*
- * Forcibly free the target now that
- * all devices are gone.
- */
- ahc_linux_free_target(ahc, targ);
+ ahc->platform_data->starget[i] = NULL;
}
}
@@ -1787,16 +1361,7 @@ ahc_platform_free(struct ahc_softc *ahc)
release_mem_region(ahc->platform_data->mem_busaddr,
0x1000);
}
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- /*
- * In 2.4 we detach from the scsi midlayer before the PCI
- * layer invokes our remove callback. No per-instance
- * detach is provided, so we must reach inside the PCI
- * subsystem's internals and detach our driver manually.
- */
- if (ahc->dev_softc != NULL)
- ahc->dev_softc->driver = NULL;
-#endif
+
free(ahc->platform_data, M_DEVBUF);
}
}
@@ -1814,15 +1379,25 @@ void
ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
ahc_queue_alg alg)
{
+ struct scsi_target *starget;
+ struct ahc_linux_target *targ;
struct ahc_linux_device *dev;
+ struct scsi_device *sdev;
+ u_int target_offset;
int was_queuing;
int now_queuing;
- dev = ahc_linux_get_device(ahc, devinfo->channel - 'A',
- devinfo->target,
- devinfo->lun, /*alloc*/FALSE);
- if (dev == NULL)
+ target_offset = devinfo->target;
+ if (devinfo->channel != 'A')
+ target_offset += 8;
+ starget = ahc->platform_data->starget[target_offset];
+ targ = scsi_transport_target_data(starget);
+ BUG_ON(targ == NULL);
+ sdev = targ->sdev[devinfo->lun];
+ if (sdev == NULL)
return;
+ dev = scsi_transport_device_data(sdev);
+
was_queuing = dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED);
switch (alg) {
default:
@@ -1873,116 +1448,36 @@ ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
dev->maxtags = 0;
dev->openings = 1 - dev->active;
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- if (dev->scsi_device != NULL) {
- switch ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED))) {
- case AHC_DEV_Q_BASIC:
- scsi_adjust_queue_depth(dev->scsi_device,
- MSG_SIMPLE_TASK,
- dev->openings + dev->active);
- break;
- case AHC_DEV_Q_TAGGED:
- scsi_adjust_queue_depth(dev->scsi_device,
- MSG_ORDERED_TASK,
- dev->openings + dev->active);
- break;
- default:
- /*
- * We allow the OS to queue 2 untagged transactions to
- * us at any time even though we can only execute them
- * serially on the controller/device. This should
- * remove some latency.
- */
- scsi_adjust_queue_depth(dev->scsi_device,
- /*NON-TAGGED*/0,
- /*queue depth*/2);
- break;
- }
+ switch ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED))) {
+ case AHC_DEV_Q_BASIC:
+ scsi_adjust_queue_depth(sdev,
+ MSG_SIMPLE_TASK,
+ dev->openings + dev->active);
+ break;
+ case AHC_DEV_Q_TAGGED:
+ scsi_adjust_queue_depth(sdev,
+ MSG_ORDERED_TASK,
+ dev->openings + dev->active);
+ break;
+ default:
+ /*
+ * We allow the OS to queue 2 untagged transactions to
+ * us at any time even though we can only execute them
+ * serially on the controller/device. This should
+ * remove some latency.
+ */
+ scsi_adjust_queue_depth(sdev,
+ /*NON-TAGGED*/0,
+ /*queue depth*/2);
+ break;
}
-#endif
}
int
ahc_platform_abort_scbs(struct ahc_softc *ahc, int target, char channel,
int lun, u_int tag, role_t role, uint32_t status)
{
- int chan;
- int maxchan;
- int targ;
- int maxtarg;
- int clun;
- int maxlun;
- int count;
-
- if (tag != SCB_LIST_NULL)
- return (0);
-
- chan = 0;
- if (channel != ALL_CHANNELS) {
- chan = channel - 'A';
- maxchan = chan + 1;
- } else {
- maxchan = (ahc->features & AHC_TWIN) ? 2 : 1;
- }
- targ = 0;
- if (target != CAM_TARGET_WILDCARD) {
- targ = target;
- maxtarg = targ + 1;
- } else {
- maxtarg = (ahc->features & AHC_WIDE) ? 16 : 8;
- }
- clun = 0;
- if (lun != CAM_LUN_WILDCARD) {
- clun = lun;
- maxlun = clun + 1;
- } else {
- maxlun = AHC_NUM_LUNS;
- }
-
- count = 0;
- for (; chan < maxchan; chan++) {
-
- for (; targ < maxtarg; targ++) {
-
- for (; clun < maxlun; clun++) {
- struct ahc_linux_device *dev;
- struct ahc_busyq *busyq;
- struct ahc_cmd *acmd;
-
- dev = ahc_linux_get_device(ahc, chan,
- targ, clun,
- /*alloc*/FALSE);
- if (dev == NULL)
- continue;
-
- busyq = &dev->busyq;
- while ((acmd = TAILQ_FIRST(busyq)) != NULL) {
- Scsi_Cmnd *cmd;
-
- cmd = &acmd_scsi_cmd(acmd);
- TAILQ_REMOVE(busyq, acmd,
- acmd_links.tqe);
- count++;
- cmd->result = status << 16;
- ahc_linux_queue_cmd_complete(ahc, cmd);
- }
- }
- }
- }
-
- return (count);
-}
-
-static void
-ahc_linux_thread_run_complete_queue(struct ahc_softc *ahc)
-{
- u_long flags;
-
- ahc_lock(ahc, &flags);
- del_timer(&ahc->platform_data->completeq_timer);
- ahc->platform_data->flags &= ~AHC_RUN_CMPLT_Q_TIMER;
- ahc_linux_run_complete_queue(ahc);
- ahc_unlock(ahc, &flags);
+ return 0;
}
static u_int
@@ -2020,22 +1515,20 @@ ahc_linux_user_tagdepth(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
* Determines the queue depth for a given device.
*/
static void
-ahc_linux_device_queue_depth(struct ahc_softc *ahc,
- struct ahc_linux_device *dev)
+ahc_linux_device_queue_depth(struct scsi_device *sdev)
{
struct ahc_devinfo devinfo;
u_int tags;
+ struct ahc_softc *ahc = *((struct ahc_softc **)sdev->host->hostdata);
ahc_compile_devinfo(&devinfo,
- dev->target->channel == 0
+ sdev->sdev_target->channel == 0
? ahc->our_id : ahc->our_id_b,
- dev->target->target, dev->lun,
- dev->target->channel == 0 ? 'A' : 'B',
+ sdev->sdev_target->id, sdev->lun,
+ sdev->sdev_target->channel == 0 ? 'A' : 'B',
ROLE_INITIATOR);
tags = ahc_linux_user_tagdepth(ahc, &devinfo);
- if (tags != 0
- && dev->scsi_device != NULL
- && dev->scsi_device->tagged_supported != 0) {
+ if (tags != 0 && sdev->tagged_supported != 0) {
ahc_set_tags(ahc, &devinfo, AHC_QUEUE_TAGGED);
ahc_print_devinfo(ahc, &devinfo);
@@ -2045,213 +1538,199 @@ ahc_linux_device_queue_depth(struct ahc_softc *ahc,
}
}
-static void
-ahc_linux_run_device_queue(struct ahc_softc *ahc, struct ahc_linux_device *dev)
+static int
+ahc_linux_run_command(struct ahc_softc *ahc, struct ahc_linux_device *dev,
+ struct scsi_cmnd *cmd)
{
- struct ahc_cmd *acmd;
- struct scsi_cmnd *cmd;
struct scb *scb;
struct hardware_scb *hscb;
struct ahc_initiator_tinfo *tinfo;
struct ahc_tmode_tstate *tstate;
uint16_t mask;
+ struct scb_tailq *untagged_q = NULL;
- if ((dev->flags & AHC_DEV_ON_RUN_LIST) != 0)
- panic("running device on run list");
+ /*
+ * Schedule us to run later. The only reason we are not
+ * running is because the whole controller Q is frozen.
+ */
+ if (ahc->platform_data->qfrozen != 0)
+ return SCSI_MLQUEUE_HOST_BUSY;
- while ((acmd = TAILQ_FIRST(&dev->busyq)) != NULL
- && dev->openings > 0 && dev->qfrozen == 0) {
+ /*
+ * We only allow one untagged transaction
+ * per target in the initiator role unless
+ * we are storing a full busy target *lun*
+ * table in SCB space.
+ */
+ if (!blk_rq_tagged(cmd->request)
+ && (ahc->features & AHC_SCB_BTT) == 0) {
+ int target_offset;
- /*
- * Schedule us to run later. The only reason we are not
- * running is because the whole controller Q is frozen.
- */
- if (ahc->platform_data->qfrozen != 0) {
- TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq,
- dev, links);
- dev->flags |= AHC_DEV_ON_RUN_LIST;
- return;
- }
- /*
- * Get an scb to use.
- */
- if ((scb = ahc_get_scb(ahc)) == NULL) {
- TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq,
- dev, links);
- dev->flags |= AHC_DEV_ON_RUN_LIST;
- ahc->flags |= AHC_RESOURCE_SHORTAGE;
- return;
- }
- TAILQ_REMOVE(&dev->busyq, acmd, acmd_links.tqe);
- cmd = &acmd_scsi_cmd(acmd);
- scb->io_ctx = cmd;
- scb->platform_data->dev = dev;
- hscb = scb->hscb;
- cmd->host_scribble = (char *)scb;
+ target_offset = cmd->device->id + cmd->device->channel * 8;
+ untagged_q = &(ahc->untagged_queues[target_offset]);
+ if (!TAILQ_EMPTY(untagged_q))
+ /* if we're already executing an untagged command
+ * we're busy to another */
+ return SCSI_MLQUEUE_DEVICE_BUSY;
+ }
- /*
- * Fill out basics of the HSCB.
- */
- hscb->control = 0;
- hscb->scsiid = BUILD_SCSIID(ahc, cmd);
- hscb->lun = cmd->device->lun;
- mask = SCB_GET_TARGET_MASK(ahc, scb);
- tinfo = ahc_fetch_transinfo(ahc, SCB_GET_CHANNEL(ahc, scb),
- SCB_GET_OUR_ID(scb),
- SCB_GET_TARGET(ahc, scb), &tstate);
- hscb->scsirate = tinfo->scsirate;
- hscb->scsioffset = tinfo->curr.offset;
- if ((tstate->ultraenb & mask) != 0)
- hscb->control |= ULTRAENB;
-
- if ((ahc->user_discenable & mask) != 0)
- hscb->control |= DISCENB;
-
- if ((tstate->auto_negotiate & mask) != 0) {
- scb->flags |= SCB_AUTO_NEGOTIATE;
- scb->hscb->control |= MK_MESSAGE;
- }
+ /*
+ * Get an scb to use.
+ */
+ scb = ahc_get_scb(ahc);
+ if (!scb)
+ return SCSI_MLQUEUE_HOST_BUSY;
- if ((dev->flags & (AHC_DEV_Q_TAGGED|AHC_DEV_Q_BASIC)) != 0) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- int msg_bytes;
- uint8_t tag_msgs[2];
-
- msg_bytes = scsi_populate_tag_msg(cmd, tag_msgs);
- if (msg_bytes && tag_msgs[0] != MSG_SIMPLE_TASK) {
- hscb->control |= tag_msgs[0];
- if (tag_msgs[0] == MSG_ORDERED_TASK)
- dev->commands_since_idle_or_otag = 0;
- } else
-#endif
- if (dev->commands_since_idle_or_otag == AHC_OTAG_THRESH
- && (dev->flags & AHC_DEV_Q_TAGGED) != 0) {
- hscb->control |= MSG_ORDERED_TASK;
- dev->commands_since_idle_or_otag = 0;
- } else {
- hscb->control |= MSG_SIMPLE_TASK;
- }
- }
+ scb->io_ctx = cmd;
+ scb->platform_data->dev = dev;
+ hscb = scb->hscb;
+ cmd->host_scribble = (char *)scb;
- hscb->cdb_len = cmd->cmd_len;
- if (hscb->cdb_len <= 12) {
- memcpy(hscb->shared_data.cdb, cmd->cmnd, hscb->cdb_len);
+ /*
+ * Fill out basics of the HSCB.
+ */
+ hscb->control = 0;
+ hscb->scsiid = BUILD_SCSIID(ahc, cmd);
+ hscb->lun = cmd->device->lun;
+ mask = SCB_GET_TARGET_MASK(ahc, scb);
+ tinfo = ahc_fetch_transinfo(ahc, SCB_GET_CHANNEL(ahc, scb),
+ SCB_GET_OUR_ID(scb),
+ SCB_GET_TARGET(ahc, scb), &tstate);
+ hscb->scsirate = tinfo->scsirate;
+ hscb->scsioffset = tinfo->curr.offset;
+ if ((tstate->ultraenb & mask) != 0)
+ hscb->control |= ULTRAENB;
+
+ if ((ahc->user_discenable & mask) != 0)
+ hscb->control |= DISCENB;
+
+ if ((tstate->auto_negotiate & mask) != 0) {
+ scb->flags |= SCB_AUTO_NEGOTIATE;
+ scb->hscb->control |= MK_MESSAGE;
+ }
+
+ if ((dev->flags & (AHC_DEV_Q_TAGGED|AHC_DEV_Q_BASIC)) != 0) {
+ int msg_bytes;
+ uint8_t tag_msgs[2];
+
+ msg_bytes = scsi_populate_tag_msg(cmd, tag_msgs);
+ if (msg_bytes && tag_msgs[0] != MSG_SIMPLE_TASK) {
+ hscb->control |= tag_msgs[0];
+ if (tag_msgs[0] == MSG_ORDERED_TASK)
+ dev->commands_since_idle_or_otag = 0;
+ } else if (dev->commands_since_idle_or_otag == AHC_OTAG_THRESH
+ && (dev->flags & AHC_DEV_Q_TAGGED) != 0) {
+ hscb->control |= MSG_ORDERED_TASK;
+ dev->commands_since_idle_or_otag = 0;
} else {
- memcpy(hscb->cdb32, cmd->cmnd, hscb->cdb_len);
- scb->flags |= SCB_CDB32_PTR;
+ hscb->control |= MSG_SIMPLE_TASK;
}
+ }
- scb->platform_data->xfer_len = 0;
- ahc_set_residual(scb, 0);
- ahc_set_sense_residual(scb, 0);
- scb->sg_count = 0;
- if (cmd->use_sg != 0) {
- struct ahc_dma_seg *sg;
- struct scatterlist *cur_seg;
- struct scatterlist *end_seg;
- int nseg;
-
- cur_seg = (struct scatterlist *)cmd->request_buffer;
- nseg = pci_map_sg(ahc->dev_softc, cur_seg, cmd->use_sg,
- cmd->sc_data_direction);
- end_seg = cur_seg + nseg;
- /* Copy the segments into the SG list. */
- sg = scb->sg_list;
- /*
- * The sg_count may be larger than nseg if
- * a transfer crosses a 32bit page.
- */
- while (cur_seg < end_seg) {
- dma_addr_t addr;
- bus_size_t len;
- int consumed;
-
- addr = sg_dma_address(cur_seg);
- len = sg_dma_len(cur_seg);
- consumed = ahc_linux_map_seg(ahc, scb,
- sg, addr, len);
- sg += consumed;
- scb->sg_count += consumed;
- cur_seg++;
- }
- sg--;
- sg->len |= ahc_htole32(AHC_DMA_LAST_SEG);
-
- /*
- * Reset the sg list pointer.
- */
- scb->hscb->sgptr =
- ahc_htole32(scb->sg_list_phys | SG_FULL_RESID);
+ hscb->cdb_len = cmd->cmd_len;
+ if (hscb->cdb_len <= 12) {
+ memcpy(hscb->shared_data.cdb, cmd->cmnd, hscb->cdb_len);
+ } else {
+ memcpy(hscb->cdb32, cmd->cmnd, hscb->cdb_len);
+ scb->flags |= SCB_CDB32_PTR;
+ }
- /*
- * Copy the first SG into the "current"
- * data pointer area.
- */
- scb->hscb->dataptr = scb->sg_list->addr;
- scb->hscb->datacnt = scb->sg_list->len;
- } else if (cmd->request_bufflen != 0) {
- struct ahc_dma_seg *sg;
+ scb->platform_data->xfer_len = 0;
+ ahc_set_residual(scb, 0);
+ ahc_set_sense_residual(scb, 0);
+ scb->sg_count = 0;
+ if (cmd->use_sg != 0) {
+ struct ahc_dma_seg *sg;
+ struct scatterlist *cur_seg;
+ struct scatterlist *end_seg;
+ int nseg;
+
+ cur_seg = (struct scatterlist *)cmd->request_buffer;
+ nseg = pci_map_sg(ahc->dev_softc, cur_seg, cmd->use_sg,
+ cmd->sc_data_direction);
+ end_seg = cur_seg + nseg;
+ /* Copy the segments into the SG list. */
+ sg = scb->sg_list;
+ /*
+ * The sg_count may be larger than nseg if
+ * a transfer crosses a 32bit page.
+ */
+ while (cur_seg < end_seg) {
dma_addr_t addr;
-
- sg = scb->sg_list;
- addr = pci_map_single(ahc->dev_softc,
- cmd->request_buffer,
- cmd->request_bufflen,
- cmd->sc_data_direction);
- scb->platform_data->buf_busaddr = addr;
- scb->sg_count = ahc_linux_map_seg(ahc, scb,
- sg, addr,
- cmd->request_bufflen);
- sg->len |= ahc_htole32(AHC_DMA_LAST_SEG);
-
- /*
- * Reset the sg list pointer.
- */
- scb->hscb->sgptr =
- ahc_htole32(scb->sg_list_phys | SG_FULL_RESID);
-
- /*
- * Copy the first SG into the "current"
- * data pointer area.
- */
- scb->hscb->dataptr = sg->addr;
- scb->hscb->datacnt = sg->len;
- } else {
- scb->hscb->sgptr = ahc_htole32(SG_LIST_NULL);
- scb->hscb->dataptr = 0;
- scb->hscb->datacnt = 0;
- scb->sg_count = 0;
+ bus_size_t len;
+ int consumed;
+
+ addr = sg_dma_address(cur_seg);
+ len = sg_dma_len(cur_seg);
+ consumed = ahc_linux_map_seg(ahc, scb,
+ sg, addr, len);
+ sg += consumed;
+ scb->sg_count += consumed;
+ cur_seg++;
}
+ sg--;
+ sg->len |= ahc_htole32(AHC_DMA_LAST_SEG);
+
+ /*
+ * Reset the sg list pointer.
+ */
+ scb->hscb->sgptr =
+ ahc_htole32(scb->sg_list_phys | SG_FULL_RESID);
+
+ /*
+ * Copy the first SG into the "current"
+ * data pointer area.
+ */
+ scb->hscb->dataptr = scb->sg_list->addr;
+ scb->hscb->datacnt = scb->sg_list->len;
+ } else if (cmd->request_bufflen != 0) {
+ struct ahc_dma_seg *sg;
+ dma_addr_t addr;
+
+ sg = scb->sg_list;
+ addr = pci_map_single(ahc->dev_softc,
+ cmd->request_buffer,
+ cmd->request_bufflen,
+ cmd->sc_data_direction);
+ scb->platform_data->buf_busaddr = addr;
+ scb->sg_count = ahc_linux_map_seg(ahc, scb,
+ sg, addr,
+ cmd->request_bufflen);
+ sg->len |= ahc_htole32(AHC_DMA_LAST_SEG);
- ahc_sync_sglist(ahc, scb, BUS_DMASYNC_PREWRITE);
- LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links);
- dev->openings--;
- dev->active++;
- dev->commands_issued++;
- if ((dev->flags & AHC_DEV_PERIODIC_OTAG) != 0)
- dev->commands_since_idle_or_otag++;
+ /*
+ * Reset the sg list pointer.
+ */
+ scb->hscb->sgptr =
+ ahc_htole32(scb->sg_list_phys | SG_FULL_RESID);
/*
- * We only allow one untagged transaction
- * per target in the initiator role unless
- * we are storing a full busy target *lun*
- * table in SCB space.
+ * Copy the first SG into the "current"
+ * data pointer area.
*/
- if ((scb->hscb->control & (TARGET_SCB|TAG_ENB)) == 0
- && (ahc->features & AHC_SCB_BTT) == 0) {
- struct scb_tailq *untagged_q;
- int target_offset;
-
- target_offset = SCB_GET_TARGET_OFFSET(ahc, scb);
- untagged_q = &(ahc->untagged_queues[target_offset]);
- TAILQ_INSERT_TAIL(untagged_q, scb, links.tqe);
- scb->flags |= SCB_UNTAGGEDQ;
- if (TAILQ_FIRST(untagged_q) != scb)
- continue;
- }
- scb->flags |= SCB_ACTIVE;
- ahc_queue_scb(ahc, scb);
+ scb->hscb->dataptr = sg->addr;
+ scb->hscb->datacnt = sg->len;
+ } else {
+ scb->hscb->sgptr = ahc_htole32(SG_LIST_NULL);
+ scb->hscb->dataptr = 0;
+ scb->hscb->datacnt = 0;
+ scb->sg_count = 0;
}
+
+ LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links);
+ dev->openings--;
+ dev->active++;
+ dev->commands_issued++;
+ if ((dev->flags & AHC_DEV_PERIODIC_OTAG) != 0)
+ dev->commands_since_idle_or_otag++;
+
+ scb->flags |= SCB_ACTIVE;
+ if (untagged_q) {
+ TAILQ_INSERT_TAIL(untagged_q, scb, links.tqe);
+ scb->flags |= SCB_UNTAGGEDQ;
+ }
+ ahc_queue_scb(ahc, scb);
+ return 0;
}
/*
@@ -2267,9 +1746,6 @@ ahc_linux_isr(int irq, void *dev_id, struct pt_regs * regs)
ahc = (struct ahc_softc *) dev_id;
ahc_lock(ahc, &flags);
ours = ahc_intr(ahc);
- if (ahc_linux_next_device_to_run(ahc) != NULL)
- ahc_schedule_runq(ahc);
- ahc_linux_run_complete_queue(ahc);
ahc_unlock(ahc, &flags);
return IRQ_RETVAL(ours);
}
@@ -2278,118 +1754,6 @@ void
ahc_platform_flushwork(struct ahc_softc *ahc)
{
- while (ahc_linux_run_complete_queue(ahc) != NULL)
- ;
-}
-
-static struct ahc_linux_target*
-ahc_linux_alloc_target(struct ahc_softc *ahc, u_int channel, u_int target)
-{
- struct ahc_linux_target *targ;
- u_int target_offset;
-
- target_offset = target;
- if (channel != 0)
- target_offset += 8;
-
- targ = malloc(sizeof(*targ), M_DEVBUG, M_NOWAIT);
- if (targ == NULL)
- return (NULL);
- memset(targ, 0, sizeof(*targ));
- targ->channel = channel;
- targ->target = target;
- targ->ahc = ahc;
- ahc->platform_data->targets[target_offset] = targ;
- return (targ);
-}
-
-static void
-ahc_linux_free_target(struct ahc_softc *ahc, struct ahc_linux_target *targ)
-{
- struct ahc_devinfo devinfo;
- struct ahc_initiator_tinfo *tinfo;
- struct ahc_tmode_tstate *tstate;
- u_int our_id;
- u_int target_offset;
- char channel;
-
- /*
- * Force a negotiation to async/narrow on any
- * future command to this device unless a bus
- * reset occurs between now and that command.
- */
- channel = 'A' + targ->channel;
- our_id = ahc->our_id;
- target_offset = targ->target;
- if (targ->channel != 0) {
- target_offset += 8;
- our_id = ahc->our_id_b;
- }
- tinfo = ahc_fetch_transinfo(ahc, channel, our_id,
- targ->target, &tstate);
- ahc_compile_devinfo(&devinfo, our_id, targ->target, CAM_LUN_WILDCARD,
- channel, ROLE_INITIATOR);
- ahc_set_syncrate(ahc, &devinfo, NULL, 0, 0, 0,
- AHC_TRANS_GOAL, /*paused*/FALSE);
- ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
- AHC_TRANS_GOAL, /*paused*/FALSE);
- ahc_update_neg_request(ahc, &devinfo, tstate, tinfo, AHC_NEG_ALWAYS);
- ahc->platform_data->targets[target_offset] = NULL;
- free(targ, M_DEVBUF);
-}
-
-static struct ahc_linux_device*
-ahc_linux_alloc_device(struct ahc_softc *ahc,
- struct ahc_linux_target *targ, u_int lun)
-{
- struct ahc_linux_device *dev;
-
- dev = malloc(sizeof(*dev), M_DEVBUG, M_NOWAIT);
- if (dev == NULL)
- return (NULL);
- memset(dev, 0, sizeof(*dev));
- init_timer(&dev->timer);
- TAILQ_INIT(&dev->busyq);
- dev->flags = AHC_DEV_UNCONFIGURED;
- dev->lun = lun;
- dev->target = targ;
-
- /*
- * We start out life using untagged
- * transactions of which we allow one.
- */
- dev->openings = 1;
-
- /*
- * Set maxtags to 0. This will be changed if we
- * later determine that we are dealing with
- * a tagged queuing capable device.
- */
- dev->maxtags = 0;
-
- targ->refcount++;
- targ->devices[lun] = dev;
- return (dev);
-}
-
-static void
-__ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev)
-{
- struct ahc_linux_target *targ;
-
- targ = dev->target;
- targ->devices[dev->lun] = NULL;
- free(dev, M_DEVBUF);
- targ->refcount--;
- if (targ->refcount == 0)
- ahc_linux_free_target(ahc, targ);
-}
-
-static void
-ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev)
-{
- del_timer_sync(&dev->timer);
- __ahc_linux_free_device(ahc, dev);
}
void
@@ -2400,11 +1764,15 @@ ahc_send_async(struct ahc_softc *ahc, char channel,
case AC_TRANSFER_NEG:
{
char buf[80];
+ struct scsi_target *starget;
struct ahc_linux_target *targ;
struct info_str info;
struct ahc_initiator_tinfo *tinfo;
struct ahc_tmode_tstate *tstate;
int target_offset;
+ unsigned int target_ppr_options;
+
+ BUG_ON(target == CAM_TARGET_WILDCARD);
info.buffer = buf;
info.length = sizeof(buf);
@@ -2433,58 +1801,37 @@ ahc_send_async(struct ahc_softc *ahc, char channel,
target_offset = target;
if (channel == 'B')
target_offset += 8;
- targ = ahc->platform_data->targets[target_offset];
+ starget = ahc->platform_data->starget[target_offset];
+ targ = scsi_transport_target_data(starget);
if (targ == NULL)
break;
- if (tinfo->curr.period == targ->last_tinfo.period
- && tinfo->curr.width == targ->last_tinfo.width
- && tinfo->curr.offset == targ->last_tinfo.offset
- && tinfo->curr.ppr_options == targ->last_tinfo.ppr_options)
+
+ target_ppr_options =
+ (spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0)
+ + (spi_qas(starget) ? MSG_EXT_PPR_QAS_REQ : 0)
+ + (spi_iu(starget) ? MSG_EXT_PPR_IU_REQ : 0);
+
+ if (tinfo->curr.period == spi_period(starget)
+ && tinfo->curr.width == spi_width(starget)
+ && tinfo->curr.offset == spi_offset(starget)
+ && tinfo->curr.ppr_options == target_ppr_options)
if (bootverbose == 0)
break;
- targ->last_tinfo.period = tinfo->curr.period;
- targ->last_tinfo.width = tinfo->curr.width;
- targ->last_tinfo.offset = tinfo->curr.offset;
- targ->last_tinfo.ppr_options = tinfo->curr.ppr_options;
-
- printf("(%s:%c:", ahc_name(ahc), channel);
- if (target == CAM_TARGET_WILDCARD)
- printf("*): ");
- else
- printf("%d): ", target);
- ahc_format_transinfo(&info, &tinfo->curr);
- if (info.pos < info.length)
- *info.buffer = '\0';
- else
- buf[info.length - 1] = '\0';
- printf("%s", buf);
+ spi_period(starget) = tinfo->curr.period;
+ spi_width(starget) = tinfo->curr.width;
+ spi_offset(starget) = tinfo->curr.offset;
+ spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ;
+ spi_qas(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ;
+ spi_iu(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ;
+ spi_display_xfer_agreement(starget);
break;
}
case AC_SENT_BDR:
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
WARN_ON(lun != CAM_LUN_WILDCARD);
scsi_report_device_reset(ahc->platform_data->host,
channel - 'A', target);
-#else
- Scsi_Device *scsi_dev;
-
- /*
- * Find the SCSI device associated with this
- * request and indicate that a UA is expected.
- */
- for (scsi_dev = ahc->platform_data->host->host_queue;
- scsi_dev != NULL; scsi_dev = scsi_dev->next) {
- if (channel - 'A' == scsi_dev->channel
- && target == scsi_dev->id
- && (lun == CAM_LUN_WILDCARD
- || lun == scsi_dev->lun)) {
- scsi_dev->was_reset = 1;
- scsi_dev->expecting_cc_ua = 1;
- }
- }
-#endif
break;
}
case AC_BUS_RESET:
@@ -2504,7 +1851,7 @@ ahc_send_async(struct ahc_softc *ahc, char channel,
void
ahc_done(struct ahc_softc *ahc, struct scb *scb)
{
- Scsi_Cmnd *cmd;
+ struct scsi_cmnd *cmd;
struct ahc_linux_device *dev;
LIST_REMOVE(scb, pending_links);
@@ -2515,7 +1862,7 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
target_offset = SCB_GET_TARGET_OFFSET(ahc, scb);
untagged_q = &(ahc->untagged_queues[target_offset]);
TAILQ_REMOVE(untagged_q, scb, links.tqe);
- ahc_run_untagged_queue(ahc, untagged_q);
+ BUG_ON(!TAILQ_EMPTY(untagged_q));
}
if ((scb->flags & SCB_ACTIVE) == 0) {
@@ -2582,9 +1929,7 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
ahc_set_transaction_status(scb, CAM_REQ_CMP);
}
} else if (ahc_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) {
- ahc_linux_handle_scsi_status(ahc, dev, scb);
- } else if (ahc_get_transaction_status(scb) == CAM_SEL_TIMEOUT) {
- dev->flags |= AHC_DEV_UNCONFIGURED;
+ ahc_linux_handle_scsi_status(ahc, cmd->device, scb);
}
if (dev->openings == 1
@@ -2606,16 +1951,6 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
if (dev->active == 0)
dev->commands_since_idle_or_otag = 0;
- if (TAILQ_EMPTY(&dev->busyq)) {
- if ((dev->flags & AHC_DEV_UNCONFIGURED) != 0
- && dev->active == 0
- && (dev->flags & AHC_DEV_TIMER_ACTIVE) == 0)
- ahc_linux_free_device(ahc, dev);
- } else if ((dev->flags & AHC_DEV_ON_RUN_LIST) == 0) {
- TAILQ_INSERT_TAIL(&ahc->platform_data->device_runq, dev, links);
- dev->flags |= AHC_DEV_ON_RUN_LIST;
- }
-
if ((scb->flags & SCB_RECOVERY_SCB) != 0) {
printf("Recovery SCB completes\n");
if (ahc_get_transaction_status(scb) == CAM_BDR_SENT
@@ -2633,14 +1968,15 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
static void
ahc_linux_handle_scsi_status(struct ahc_softc *ahc,
- struct ahc_linux_device *dev, struct scb *scb)
+ struct scsi_device *sdev, struct scb *scb)
{
struct ahc_devinfo devinfo;
+ struct ahc_linux_device *dev = scsi_transport_device_data(sdev);
ahc_compile_devinfo(&devinfo,
ahc->our_id,
- dev->target->target, dev->lun,
- dev->target->channel == 0 ? 'A' : 'B',
+ sdev->sdev_target->id, sdev->lun,
+ sdev->sdev_target->channel == 0 ? 'A' : 'B',
ROLE_INITIATOR);
/*
@@ -2659,7 +1995,7 @@ ahc_linux_handle_scsi_status(struct ahc_softc *ahc,
case SCSI_STATUS_CHECK_COND:
case SCSI_STATUS_CMD_TERMINATED:
{
- Scsi_Cmnd *cmd;
+ struct scsi_cmnd *cmd;
/*
* Copy sense information to the OS's cmd
@@ -2754,52 +2090,15 @@ ahc_linux_handle_scsi_status(struct ahc_softc *ahc,
ahc_platform_set_tags(ahc, &devinfo,
(dev->flags & AHC_DEV_Q_BASIC)
? AHC_QUEUE_BASIC : AHC_QUEUE_TAGGED);
- /* FALLTHROUGH */
- }
- case SCSI_STATUS_BUSY:
- {
- /*
- * Set a short timer to defer sending commands for
- * a bit since Linux will not delay in this case.
- */
- if ((dev->flags & AHC_DEV_TIMER_ACTIVE) != 0) {
- printf("%s:%c:%d: Device Timer still active during "
- "busy processing\n", ahc_name(ahc),
- dev->target->channel, dev->target->target);
- break;
- }
- dev->flags |= AHC_DEV_TIMER_ACTIVE;
- dev->qfrozen++;
- init_timer(&dev->timer);
- dev->timer.data = (u_long)dev;
- dev->timer.expires = jiffies + (HZ/2);
- dev->timer.function = ahc_linux_dev_timed_unfreeze;
- add_timer(&dev->timer);
break;
}
}
}
static void
-ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, Scsi_Cmnd *cmd)
+ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, struct scsi_cmnd *cmd)
{
/*
- * Typically, the complete queue has very few entries
- * queued to it before the queue is emptied by
- * ahc_linux_run_complete_queue, so sorting the entries
- * by generation number should be inexpensive.
- * We perform the sort so that commands that complete
- * with an error are retuned in the order origionally
- * queued to the controller so that any subsequent retries
- * are performed in order. The underlying ahc routines do
- * not guarantee the order that aborted commands will be
- * returned to us.
- */
- struct ahc_completeq *completeq;
- struct ahc_cmd *list_cmd;
- struct ahc_cmd *acmd;
-
- /*
* Map CAM error codes into Linux Error codes. We
* avoid the conversion so that the DV code has the
* full error information available when making
@@ -2852,26 +2151,7 @@ ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, Scsi_Cmnd *cmd)
new_status = DID_ERROR;
break;
case CAM_REQUEUE_REQ:
- /*
- * If we want the request requeued, make sure there
- * are sufficent retries. In the old scsi error code,
- * we used to be able to specify a result code that
- * bypassed the retry count. Now we must use this
- * hack. We also "fake" a check condition with
- * a sense code of ABORTED COMMAND. This seems to
- * evoke a retry even if this command is being sent
- * via the eh thread. Ick! Ick! Ick!
- */
- if (cmd->retries > 0)
- cmd->retries--;
- new_status = DID_OK;
- ahc_cmd_set_scsi_status(cmd, SCSI_STATUS_CHECK_COND);
- cmd->result |= (DRIVER_SENSE << 24);
- memset(cmd->sense_buffer, 0,
- sizeof(cmd->sense_buffer));
- cmd->sense_buffer[0] = SSD_ERRCODE_VALID
- | SSD_CURRENT_ERROR;
- cmd->sense_buffer[2] = SSD_KEY_ABORTED_COMMAND;
+ new_status = DID_REQUEUE;
break;
default:
/* We should never get here */
@@ -2882,17 +2162,7 @@ ahc_linux_queue_cmd_complete(struct ahc_softc *ahc, Scsi_Cmnd *cmd)
ahc_cmd_set_transaction_status(cmd, new_status);
}
- completeq = &ahc->platform_data->completeq;
- list_cmd = TAILQ_FIRST(completeq);
- acmd = (struct ahc_cmd *)cmd;
- while (list_cmd != NULL
- && acmd_scsi_cmd(list_cmd).serial_number
- < acmd_scsi_cmd(acmd).serial_number)
- list_cmd = TAILQ_NEXT(list_cmd, acmd_links.tqe);
- if (list_cmd != NULL)
- TAILQ_INSERT_BEFORE(list_cmd, acmd, acmd_links.tqe);
- else
- TAILQ_INSERT_TAIL(completeq, acmd, acmd_links.tqe);
+ cmd->scsi_done(cmd);
}
static void
@@ -2940,7 +2210,6 @@ ahc_linux_release_simq(u_long arg)
ahc->platform_data->qfrozen--;
if (ahc->platform_data->qfrozen == 0)
unblock_reqs = 1;
- ahc_schedule_runq(ahc);
ahc_unlock(ahc, &s);
/*
* There is still a race here. The mid-layer
@@ -2952,37 +2221,12 @@ ahc_linux_release_simq(u_long arg)
scsi_unblock_requests(ahc->platform_data->host);
}
-static void
-ahc_linux_dev_timed_unfreeze(u_long arg)
-{
- struct ahc_linux_device *dev;
- struct ahc_softc *ahc;
- u_long s;
-
- dev = (struct ahc_linux_device *)arg;
- ahc = dev->target->ahc;
- ahc_lock(ahc, &s);
- dev->flags &= ~AHC_DEV_TIMER_ACTIVE;
- if (dev->qfrozen > 0)
- dev->qfrozen--;
- if (dev->qfrozen == 0
- && (dev->flags & AHC_DEV_ON_RUN_LIST) == 0)
- ahc_linux_run_device_queue(ahc, dev);
- if (TAILQ_EMPTY(&dev->busyq)
- && dev->active == 0)
- __ahc_linux_free_device(ahc, dev);
- ahc_unlock(ahc, &s);
-}
-
static int
-ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag)
+ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag)
{
struct ahc_softc *ahc;
- struct ahc_cmd *acmd;
- struct ahc_cmd *list_acmd;
struct ahc_linux_device *dev;
struct scb *pending_scb;
- u_long s;
u_int saved_scbptr;
u_int active_scb_index;
u_int last_phase;
@@ -2998,7 +2242,6 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag)
paused = FALSE;
wait = FALSE;
ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
- acmd = (struct ahc_cmd *)cmd;
printf("%s:%d:%d:%d: Attempting to queue a%s message\n",
ahc_name(ahc), cmd->device->channel,
@@ -3010,21 +2253,7 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag)
printf(" 0x%x", cmd->cmnd[cdb_byte]);
printf("\n");
- /*
- * In all versions of Linux, we have to work around
- * a major flaw in how the mid-layer is locked down
- * if we are to sleep successfully in our error handler
- * while allowing our interrupt handler to run. Since
- * the midlayer acquires either the io_request_lock or
- * our lock prior to calling us, we must use the
- * spin_unlock_irq() method for unlocking our lock.
- * This will force interrupts to be enabled on the
- * current CPU. Since the EH thread should not have
- * been running with CPU interrupts disabled other than
- * by acquiring either the io_request_lock or our own
- * lock, this *should* be safe.
- */
- ahc_midlayer_entrypoint_lock(ahc, &s);
+ spin_lock_irq(&ahc->platform_data->spin_lock);
/*
* First determine if we currently own this command.
@@ -3033,8 +2262,7 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag)
* at all, and the system wanted us to just abort the
* command, return success.
*/
- dev = ahc_linux_get_device(ahc, cmd->device->channel, cmd->device->id,
- cmd->device->lun, /*alloc*/FALSE);
+ dev = scsi_transport_device_data(cmd->device);
if (dev == NULL) {
/*
@@ -3048,24 +2276,6 @@ ahc_linux_queue_recovery_cmd(Scsi_Cmnd *cmd, scb_flag flag)
goto no_cmd;
}
- TAILQ_FOREACH(list_acmd, &dev->busyq, acmd_links.tqe) {
- if (list_acmd == acmd)
- break;
- }
-
- if (list_acmd != NULL) {
- printf("%s:%d:%d:%d: Command found on device queue\n",
- ahc_name(ahc), cmd->device->channel, cmd->device->id,
- cmd->device->lun);
- if (flag == SCB_ABORT) {
- TAILQ_REMOVE(&dev->busyq, list_acmd, acmd_links.tqe);
- cmd->result = DID_ABORT << 16;
- ahc_linux_queue_cmd_complete(ahc, cmd);
- retval = SUCCESS;
- goto done;
- }
- }
-
if ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED)) == 0
&& ahc_search_untagged_queues(ahc, cmd, cmd->device->id,
cmd->device->channel + 'A',
@@ -3299,63 +2509,30 @@ done:
}
spin_lock_irq(&ahc->platform_data->spin_lock);
}
- ahc_schedule_runq(ahc);
- ahc_linux_run_complete_queue(ahc);
- ahc_midlayer_entrypoint_unlock(ahc, &s);
+
+ spin_unlock_irq(&ahc->platform_data->spin_lock);
return (retval);
}
void
ahc_platform_dump_card_state(struct ahc_softc *ahc)
{
- struct ahc_linux_device *dev;
- int channel;
- int maxchannel;
- int target;
- int maxtarget;
- int lun;
- int i;
-
- maxchannel = (ahc->features & AHC_TWIN) ? 1 : 0;
- maxtarget = (ahc->features & AHC_WIDE) ? 15 : 7;
- for (channel = 0; channel <= maxchannel; channel++) {
-
- for (target = 0; target <=maxtarget; target++) {
-
- for (lun = 0; lun < AHC_NUM_LUNS; lun++) {
- struct ahc_cmd *acmd;
-
- dev = ahc_linux_get_device(ahc, channel, target,
- lun, /*alloc*/FALSE);
- if (dev == NULL)
- continue;
-
- printf("DevQ(%d:%d:%d): ",
- channel, target, lun);
- i = 0;
- TAILQ_FOREACH(acmd, &dev->busyq,
- acmd_links.tqe) {
- if (i++ > AHC_SCB_MAX)
- break;
- }
- printf("%d waiting\n", i);
- }
- }
- }
}
static void ahc_linux_exit(void);
-static void ahc_linux_get_period(struct scsi_target *starget)
+static void ahc_linux_set_width(struct scsi_target *starget, int width)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
- struct ahc_tmode_tstate *tstate;
- struct ahc_initiator_tinfo *tinfo
- = ahc_fetch_transinfo(ahc,
- starget->channel + 'A',
- shost->this_id, starget->id, &tstate);
- spi_period(starget) = tinfo->curr.period;
+ struct ahc_devinfo devinfo;
+ unsigned long flags;
+
+ ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
+ starget->channel + 'A', ROLE_INITIATOR);
+ ahc_lock(ahc, &flags);
+ ahc_set_width(ahc, &devinfo, width, AHC_TRANS_GOAL, FALSE);
+ ahc_unlock(ahc, &flags);
}
static void ahc_linux_set_period(struct scsi_target *starget, int period)
@@ -3368,16 +2545,28 @@ static void ahc_linux_set_period(struct scsi_target *starget, int period)
starget->channel + 'A',
shost->this_id, starget->id, &tstate);
struct ahc_devinfo devinfo;
- unsigned int ppr_options = tinfo->curr.ppr_options;
+ unsigned int ppr_options = tinfo->goal.ppr_options;
unsigned long flags;
- unsigned long offset = tinfo->curr.offset;
+ unsigned long offset = tinfo->goal.offset;
struct ahc_syncrate *syncrate;
if (offset == 0)
offset = MAX_OFFSET;
+ if (period < 9)
+ period = 9; /* 12.5ns is our minimum */
+ if (period == 9)
+ ppr_options |= MSG_EXT_PPR_DT_REQ;
+
ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
starget->channel + 'A', ROLE_INITIATOR);
+
+ /* all PPR requests apart from QAS require wide transfers */
+ if (ppr_options & ~MSG_EXT_PPR_QAS_REQ) {
+ if (spi_width(starget) == 0)
+ ppr_options &= MSG_EXT_PPR_QAS_REQ;
+ }
+
syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, AHC_SYNCRATE_DT);
ahc_lock(ahc, &flags);
ahc_set_syncrate(ahc, &devinfo, syncrate, period, offset,
@@ -3385,18 +2574,6 @@ static void ahc_linux_set_period(struct scsi_target *starget, int period)
ahc_unlock(ahc, &flags);
}
-static void ahc_linux_get_offset(struct scsi_target *starget)
-{
- struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
- struct ahc_tmode_tstate *tstate;
- struct ahc_initiator_tinfo *tinfo
- = ahc_fetch_transinfo(ahc,
- starget->channel + 'A',
- shost->this_id, starget->id, &tstate);
- spi_offset(starget) = tinfo->curr.offset;
-}
-
static void ahc_linux_set_offset(struct scsi_target *starget, int offset)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
@@ -3416,8 +2593,8 @@ static void ahc_linux_set_offset(struct scsi_target *starget, int offset)
starget->channel + 'A', ROLE_INITIATOR);
if (offset != 0) {
syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, AHC_SYNCRATE_DT);
- period = tinfo->curr.period;
- ppr_options = tinfo->curr.ppr_options;
+ period = tinfo->goal.period;
+ ppr_options = tinfo->goal.ppr_options;
}
ahc_lock(ahc, &flags);
ahc_set_syncrate(ahc, &devinfo, syncrate, period, offset,
@@ -3425,44 +2602,6 @@ static void ahc_linux_set_offset(struct scsi_target *starget, int offset)
ahc_unlock(ahc, &flags);
}
-static void ahc_linux_get_width(struct scsi_target *starget)
-{
- struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
- struct ahc_tmode_tstate *tstate;
- struct ahc_initiator_tinfo *tinfo
- = ahc_fetch_transinfo(ahc,
- starget->channel + 'A',
- shost->this_id, starget->id, &tstate);
- spi_width(starget) = tinfo->curr.width;
-}
-
-static void ahc_linux_set_width(struct scsi_target *starget, int width)
-{
- struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
- struct ahc_devinfo devinfo;
- unsigned long flags;
-
- ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
- starget->channel + 'A', ROLE_INITIATOR);
- ahc_lock(ahc, &flags);
- ahc_set_width(ahc, &devinfo, width, AHC_TRANS_GOAL, FALSE);
- ahc_unlock(ahc, &flags);
-}
-
-static void ahc_linux_get_dt(struct scsi_target *starget)
-{
- struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
- struct ahc_tmode_tstate *tstate;
- struct ahc_initiator_tinfo *tinfo
- = ahc_fetch_transinfo(ahc,
- starget->channel + 'A',
- shost->this_id, starget->id, &tstate);
- spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ;
-}
-
static void ahc_linux_set_dt(struct scsi_target *starget, int dt)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
@@ -3473,34 +2612,27 @@ static void ahc_linux_set_dt(struct scsi_target *starget, int dt)
starget->channel + 'A',
shost->this_id, starget->id, &tstate);
struct ahc_devinfo devinfo;
- unsigned int ppr_options = tinfo->curr.ppr_options
+ unsigned int ppr_options = tinfo->goal.ppr_options
& ~MSG_EXT_PPR_DT_REQ;
- unsigned int period = tinfo->curr.period;
+ unsigned int period = tinfo->goal.period;
unsigned long flags;
struct ahc_syncrate *syncrate;
+ if (dt) {
+ period = 9; /* 12.5ns is the only period valid for DT */
+ ppr_options |= MSG_EXT_PPR_DT_REQ;
+ } else if (period == 9)
+ period = 10; /* if resetting DT, period must be >= 25ns */
+
ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
starget->channel + 'A', ROLE_INITIATOR);
- syncrate = ahc_find_syncrate(ahc, &period, &ppr_options,
- dt ? AHC_SYNCRATE_DT : AHC_SYNCRATE_ULTRA2);
+ syncrate = ahc_find_syncrate(ahc, &period, &ppr_options,AHC_SYNCRATE_DT);
ahc_lock(ahc, &flags);
- ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->curr.offset,
+ ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->goal.offset,
ppr_options, AHC_TRANS_GOAL, FALSE);
ahc_unlock(ahc, &flags);
}
-static void ahc_linux_get_qas(struct scsi_target *starget)
-{
- struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
- struct ahc_tmode_tstate *tstate;
- struct ahc_initiator_tinfo *tinfo
- = ahc_fetch_transinfo(ahc,
- starget->channel + 'A',
- shost->this_id, starget->id, &tstate);
- spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ;
-}
-
static void ahc_linux_set_qas(struct scsi_target *starget, int qas)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
@@ -3511,10 +2643,9 @@ static void ahc_linux_set_qas(struct scsi_target *starget, int qas)
starget->channel + 'A',
shost->this_id, starget->id, &tstate);
struct ahc_devinfo devinfo;
- unsigned int ppr_options = tinfo->curr.ppr_options
+ unsigned int ppr_options = tinfo->goal.ppr_options
& ~MSG_EXT_PPR_QAS_REQ;
- unsigned int period = tinfo->curr.period;
- unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+ unsigned int period = tinfo->goal.period;
unsigned long flags;
struct ahc_syncrate *syncrate;
@@ -3523,26 +2654,13 @@ static void ahc_linux_set_qas(struct scsi_target *starget, int qas)
ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
starget->channel + 'A', ROLE_INITIATOR);
- syncrate = ahc_find_syncrate(ahc, &period, &ppr_options,
- dt ? AHC_SYNCRATE_DT : AHC_SYNCRATE_ULTRA2);
+ syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, AHC_SYNCRATE_DT);
ahc_lock(ahc, &flags);
- ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->curr.offset,
+ ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->goal.offset,
ppr_options, AHC_TRANS_GOAL, FALSE);
ahc_unlock(ahc, &flags);
}
-static void ahc_linux_get_iu(struct scsi_target *starget)
-{
- struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
- struct ahc_tmode_tstate *tstate;
- struct ahc_initiator_tinfo *tinfo
- = ahc_fetch_transinfo(ahc,
- starget->channel + 'A',
- shost->this_id, starget->id, &tstate);
- spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ;
-}
-
static void ahc_linux_set_iu(struct scsi_target *starget, int iu)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
@@ -3553,10 +2671,9 @@ static void ahc_linux_set_iu(struct scsi_target *starget, int iu)
starget->channel + 'A',
shost->this_id, starget->id, &tstate);
struct ahc_devinfo devinfo;
- unsigned int ppr_options = tinfo->curr.ppr_options
+ unsigned int ppr_options = tinfo->goal.ppr_options
& ~MSG_EXT_PPR_IU_REQ;
- unsigned int period = tinfo->curr.period;
- unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
+ unsigned int period = tinfo->goal.period;
unsigned long flags;
struct ahc_syncrate *syncrate;
@@ -3565,31 +2682,24 @@ static void ahc_linux_set_iu(struct scsi_target *starget, int iu)
ahc_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
starget->channel + 'A', ROLE_INITIATOR);
- syncrate = ahc_find_syncrate(ahc, &period, &ppr_options,
- dt ? AHC_SYNCRATE_DT : AHC_SYNCRATE_ULTRA2);
+ syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, AHC_SYNCRATE_DT);
ahc_lock(ahc, &flags);
- ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->curr.offset,
+ ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->goal.offset,
ppr_options, AHC_TRANS_GOAL, FALSE);
ahc_unlock(ahc, &flags);
}
static struct spi_function_template ahc_linux_transport_functions = {
- .get_offset = ahc_linux_get_offset,
.set_offset = ahc_linux_set_offset,
.show_offset = 1,
- .get_period = ahc_linux_get_period,
.set_period = ahc_linux_set_period,
.show_period = 1,
- .get_width = ahc_linux_get_width,
.set_width = ahc_linux_set_width,
.show_width = 1,
- .get_dt = ahc_linux_get_dt,
.set_dt = ahc_linux_set_dt,
.show_dt = 1,
- .get_iu = ahc_linux_get_iu,
.set_iu = ahc_linux_set_iu,
.show_iu = 1,
- .get_qas = ahc_linux_get_qas,
.set_qas = ahc_linux_set_qas,
.show_qas = 1,
};
@@ -3599,38 +2709,23 @@ static struct spi_function_template ahc_linux_transport_functions = {
static int __init
ahc_linux_init(void)
{
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
ahc_linux_transport_template = spi_attach_transport(&ahc_linux_transport_functions);
if (!ahc_linux_transport_template)
return -ENODEV;
+ scsi_transport_reserve_target(ahc_linux_transport_template,
+ sizeof(struct ahc_linux_target));
+ scsi_transport_reserve_device(ahc_linux_transport_template,
+ sizeof(struct ahc_linux_device));
if (ahc_linux_detect(&aic7xxx_driver_template))
return 0;
spi_release_transport(ahc_linux_transport_template);
ahc_linux_exit();
return -ENODEV;
-#else
- scsi_register_module(MODULE_SCSI_HA, &aic7xxx_driver_template);
- if (aic7xxx_driver_template.present == 0) {
- scsi_unregister_module(MODULE_SCSI_HA,
- &aic7xxx_driver_template);
- return (-ENODEV);
- }
-
- return (0);
-#endif
}
static void
ahc_linux_exit(void)
{
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- /*
- * In 2.4 we have to unregister from the PCI core _after_
- * unregistering from the scsi midlayer to avoid dangling
- * references.
- */
- scsi_unregister_module(MODULE_SCSI_HA, &aic7xxx_driver_template);
-#endif
ahc_linux_pci_exit();
ahc_linux_eisa_exit();
spi_release_transport(ahc_linux_transport_template);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
index ed9027bd8a4..8ffe2d3e1d9 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h
@@ -59,6 +59,7 @@
#ifndef _AIC7XXX_LINUX_H_
#define _AIC7XXX_LINUX_H_
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/blkdev.h>
#include <linux/delay.h>
@@ -66,18 +67,23 @@
#include <linux/pci.h>
#include <linux/smp_lock.h>
#include <linux/version.h>
+#include <linux/interrupt.h>
#include <linux/module.h>
+#include <linux/slab.h>
#include <asm/byteorder.h>
#include <asm/io.h>
-#include <linux/interrupt.h> /* For tasklet support. */
-#include <linux/config.h>
-#include <linux/slab.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_spi.h>
/* Core SCSI definitions */
#define AIC_LIB_PREFIX ahc
-#include "scsi.h"
-#include <scsi/scsi_host.h>
/* Name space conflict with BSD queue macros */
#ifdef LIST_HEAD
@@ -106,7 +112,7 @@
/************************* Forward Declarations *******************************/
struct ahc_softc;
typedef struct pci_dev *ahc_dev_softc_t;
-typedef Scsi_Cmnd *ahc_io_ctx_t;
+typedef struct scsi_cmnd *ahc_io_ctx_t;
/******************************* Byte Order ***********************************/
#define ahc_htobe16(x) cpu_to_be16(x)
@@ -123,28 +129,11 @@ typedef Scsi_Cmnd *ahc_io_ctx_t;
#define ahc_le32toh(x) le32_to_cpu(x)
#define ahc_le64toh(x) le64_to_cpu(x)
-#ifndef LITTLE_ENDIAN
-#define LITTLE_ENDIAN 1234
-#endif
-
-#ifndef BIG_ENDIAN
-#define BIG_ENDIAN 4321
-#endif
-
-#ifndef BYTE_ORDER
-#if defined(__BIG_ENDIAN)
-#define BYTE_ORDER BIG_ENDIAN
-#endif
-#if defined(__LITTLE_ENDIAN)
-#define BYTE_ORDER LITTLE_ENDIAN
-#endif
-#endif /* BYTE_ORDER */
-
/************************* Configuration Data *********************************/
extern u_int aic7xxx_no_probe;
extern u_int aic7xxx_allow_memio;
extern int aic7xxx_detect_complete;
-extern Scsi_Host_Template aic7xxx_driver_template;
+extern struct scsi_host_template aic7xxx_driver_template;
/***************************** Bus Space/DMA **********************************/
@@ -174,11 +163,7 @@ struct ahc_linux_dma_tag
};
typedef struct ahc_linux_dma_tag* bus_dma_tag_t;
-struct ahc_linux_dmamap
-{
- dma_addr_t bus_addr;
-};
-typedef struct ahc_linux_dmamap* bus_dmamap_t;
+typedef dma_addr_t bus_dmamap_t;
typedef int bus_dma_filter_t(void*, dma_addr_t);
typedef void bus_dmamap_callback_t(void *, bus_dma_segment_t *, int, int);
@@ -281,43 +266,8 @@ ahc_scb_timer_reset(struct scb *scb, u_int usec)
/***************************** SMP support ************************************/
#include <linux/spinlock.h>
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) || defined(SCSI_HAS_HOST_LOCK))
-#define AHC_SCSI_HAS_HOST_LOCK 1
-#else
-#define AHC_SCSI_HAS_HOST_LOCK 0
-#endif
-
#define AIC7XXX_DRIVER_VERSION "6.2.36"
-/**************************** Front End Queues ********************************/
-/*
- * Data structure used to cast the Linux struct scsi_cmnd to something
- * that allows us to use the queue macros. The linux structure has
- * plenty of space to hold the links fields as required by the queue
- * macros, but the queue macors require them to have the correct type.
- */
-struct ahc_cmd_internal {
- /* Area owned by the Linux scsi layer. */
- uint8_t private[offsetof(struct scsi_cmnd, SCp.Status)];
- union {
- STAILQ_ENTRY(ahc_cmd) ste;
- LIST_ENTRY(ahc_cmd) le;
- TAILQ_ENTRY(ahc_cmd) tqe;
- } links;
- uint32_t end;
-};
-
-struct ahc_cmd {
- union {
- struct ahc_cmd_internal icmd;
- struct scsi_cmnd scsi_cmd;
- } un;
-};
-
-#define acmd_icmd(cmd) ((cmd)->un.icmd)
-#define acmd_scsi_cmd(cmd) ((cmd)->un.scsi_cmd)
-#define acmd_links un.icmd.links
-
/*************************** Device Data Structures ***************************/
/*
* A per probed device structure used to deal with some error recovery
@@ -326,23 +276,15 @@ struct ahc_cmd {
* after a successfully completed inquiry command to the target when
* that inquiry data indicates a lun is present.
*/
-TAILQ_HEAD(ahc_busyq, ahc_cmd);
typedef enum {
- AHC_DEV_UNCONFIGURED = 0x01,
AHC_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */
- AHC_DEV_TIMER_ACTIVE = 0x04, /* Our timer is active */
- AHC_DEV_ON_RUN_LIST = 0x08, /* Queued to be run later */
AHC_DEV_Q_BASIC = 0x10, /* Allow basic device queuing */
AHC_DEV_Q_TAGGED = 0x20, /* Allow full SCSI2 command queueing */
AHC_DEV_PERIODIC_OTAG = 0x40, /* Send OTAG to prevent starvation */
- AHC_DEV_SLAVE_CONFIGURED = 0x80 /* slave_configure() has been called */
} ahc_linux_dev_flags;
struct ahc_linux_target;
struct ahc_linux_device {
- TAILQ_ENTRY(ahc_linux_device) links;
- struct ahc_busyq busyq;
-
/*
* The number of transactions currently
* queued to the device.
@@ -382,11 +324,6 @@ struct ahc_linux_device {
ahc_linux_dev_flags flags;
/*
- * Per device timer.
- */
- struct timer_list timer;
-
- /*
* The high limit for the tags variable.
*/
u_int maxtags;
@@ -417,17 +354,10 @@ struct ahc_linux_device {
*/
u_int commands_since_idle_or_otag;
#define AHC_OTAG_THRESH 500
-
- int lun;
- Scsi_Device *scsi_device;
- struct ahc_linux_target *target;
};
struct ahc_linux_target {
- struct ahc_linux_device *devices[AHC_NUM_LUNS];
- int channel;
- int target;
- int refcount;
+ struct scsi_device *sdev[AHC_NUM_LUNS];
struct ahc_transinfo last_tinfo;
struct ahc_softc *ahc;
};
@@ -439,32 +369,16 @@ struct ahc_linux_target {
* manner and are allocated below 4GB, the number of S/G segments is
* unrestricted.
*/
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-/*
- * We dynamically adjust the number of segments in pre-2.5 kernels to
- * avoid fragmentation issues in the SCSI mid-layer's private memory
- * allocator. See aic7xxx_osm.c ahc_linux_size_nseg() for details.
- */
-extern u_int ahc_linux_nseg;
-#define AHC_NSEG ahc_linux_nseg
-#define AHC_LINUX_MIN_NSEG 64
-#else
#define AHC_NSEG 128
-#endif
/*
* Per-SCB OSM storage.
*/
-typedef enum {
- AHC_UP_EH_SEMAPHORE = 0x1
-} ahc_linux_scb_flags;
-
struct scb_platform_data {
struct ahc_linux_device *dev;
dma_addr_t buf_busaddr;
uint32_t xfer_len;
uint32_t sense_resid; /* Auto-Sense residual */
- ahc_linux_scb_flags flags;
};
/*
@@ -473,39 +387,24 @@ struct scb_platform_data {
* alignment restrictions of the various platforms supported by
* this driver.
*/
-typedef enum {
- AHC_RUN_CMPLT_Q_TIMER = 0x10
-} ahc_linux_softc_flags;
-
-TAILQ_HEAD(ahc_completeq, ahc_cmd);
-
struct ahc_platform_data {
/*
* Fields accessed from interrupt context.
*/
- struct ahc_linux_target *targets[AHC_NUM_TARGETS];
- TAILQ_HEAD(, ahc_linux_device) device_runq;
- struct ahc_completeq completeq;
+ struct scsi_target *starget[AHC_NUM_TARGETS];
spinlock_t spin_lock;
- struct tasklet_struct runq_tasklet;
u_int qfrozen;
- pid_t dv_pid;
- struct timer_list completeq_timer;
struct timer_list reset_timer;
struct semaphore eh_sem;
- struct semaphore dv_sem;
- struct semaphore dv_cmd_sem; /* XXX This needs to be in
- * the target struct
- */
- struct scsi_device *dv_scsi_dev;
struct Scsi_Host *host; /* pointer to scsi host */
#define AHC_LINUX_NOIRQ ((uint32_t)~0)
uint32_t irq; /* IRQ for this adapter */
uint32_t bios_address;
uint32_t mem_busaddr; /* Mem Base Addr */
- uint64_t hw_dma_mask;
- ahc_linux_softc_flags flags;
+
+#define AHC_UP_EH_SEMAPHORE 0x1
+ uint32_t flags;
};
/************************** OS Utility Wrappers *******************************/
@@ -594,7 +493,7 @@ ahc_insb(struct ahc_softc * ahc, long port, uint8_t *array, int count)
/**************************** Initialization **********************************/
int ahc_linux_register_host(struct ahc_softc *,
- Scsi_Host_Template *);
+ struct scsi_host_template *);
uint64_t ahc_linux_get_memsize(void);
@@ -615,17 +514,6 @@ static __inline void ahc_lockinit(struct ahc_softc *);
static __inline void ahc_lock(struct ahc_softc *, unsigned long *flags);
static __inline void ahc_unlock(struct ahc_softc *, unsigned long *flags);
-/* Lock acquisition and release of the above lock in midlayer entry points. */
-static __inline void ahc_midlayer_entrypoint_lock(struct ahc_softc *,
- unsigned long *flags);
-static __inline void ahc_midlayer_entrypoint_unlock(struct ahc_softc *,
- unsigned long *flags);
-
-/* Lock held during command compeletion to the upper layer */
-static __inline void ahc_done_lockinit(struct ahc_softc *);
-static __inline void ahc_done_lock(struct ahc_softc *, unsigned long *flags);
-static __inline void ahc_done_unlock(struct ahc_softc *, unsigned long *flags);
-
/* Lock held during ahc_list manipulation and ahc softc frees */
extern spinlock_t ahc_list_spinlock;
static __inline void ahc_list_lockinit(void);
@@ -651,57 +539,6 @@ ahc_unlock(struct ahc_softc *ahc, unsigned long *flags)
}
static __inline void
-ahc_midlayer_entrypoint_lock(struct ahc_softc *ahc, unsigned long *flags)
-{
- /*
- * In 2.5.X and some 2.4.X versions, the midlayer takes our
- * lock just before calling us, so we avoid locking again.
- * For other kernel versions, the io_request_lock is taken
- * just before our entry point is called. In this case, we
- * trade the io_request_lock for our per-softc lock.
- */
-#if AHC_SCSI_HAS_HOST_LOCK == 0
- spin_unlock(&io_request_lock);
- spin_lock(&ahc->platform_data->spin_lock);
-#endif
-}
-
-static __inline void
-ahc_midlayer_entrypoint_unlock(struct ahc_softc *ahc, unsigned long *flags)
-{
-#if AHC_SCSI_HAS_HOST_LOCK == 0
- spin_unlock(&ahc->platform_data->spin_lock);
- spin_lock(&io_request_lock);
-#endif
-}
-
-static __inline void
-ahc_done_lockinit(struct ahc_softc *ahc)
-{
- /*
- * In 2.5.X, our own lock is held during completions.
- * In previous versions, the io_request_lock is used.
- * In either case, we can't initialize this lock again.
- */
-}
-
-static __inline void
-ahc_done_lock(struct ahc_softc *ahc, unsigned long *flags)
-{
-#if AHC_SCSI_HAS_HOST_LOCK == 0
- spin_lock_irqsave(&io_request_lock, *flags);
-#endif
-}
-
-static __inline void
-ahc_done_unlock(struct ahc_softc *ahc, unsigned long *flags)
-{
-#if AHC_SCSI_HAS_HOST_LOCK == 0
- spin_unlock_irqrestore(&io_request_lock, *flags);
-#endif
-}
-
-static __inline void
ahc_list_lockinit(void)
{
spin_lock_init(&ahc_list_spinlock);
@@ -767,14 +604,7 @@ typedef enum
} ahc_power_state;
/**************************** VL/EISA Routines ********************************/
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) \
- && (defined(__i386__) || defined(__alpha__)) \
- && (!defined(CONFIG_EISA)))
-#define CONFIG_EISA
-#endif
-
#ifdef CONFIG_EISA
-extern uint32_t aic7xxx_probe_eisa_vl;
int ahc_linux_eisa_init(void);
void ahc_linux_eisa_exit(void);
int aic7770_map_registers(struct ahc_softc *ahc,
@@ -888,22 +718,18 @@ ahc_flush_device_writes(struct ahc_softc *ahc)
}
/**************************** Proc FS Support *********************************/
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-int ahc_linux_proc_info(char *, char **, off_t, int, int, int);
-#else
int ahc_linux_proc_info(struct Scsi_Host *, char *, char **,
off_t, int, int);
-#endif
/*************************** Domain Validation ********************************/
/*********************** Transaction Access Wrappers *************************/
-static __inline void ahc_cmd_set_transaction_status(Scsi_Cmnd *, uint32_t);
+static __inline void ahc_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t);
static __inline void ahc_set_transaction_status(struct scb *, uint32_t);
-static __inline void ahc_cmd_set_scsi_status(Scsi_Cmnd *, uint32_t);
+static __inline void ahc_cmd_set_scsi_status(struct scsi_cmnd *, uint32_t);
static __inline void ahc_set_scsi_status(struct scb *, uint32_t);
-static __inline uint32_t ahc_cmd_get_transaction_status(Scsi_Cmnd *cmd);
+static __inline uint32_t ahc_cmd_get_transaction_status(struct scsi_cmnd *cmd);
static __inline uint32_t ahc_get_transaction_status(struct scb *);
-static __inline uint32_t ahc_cmd_get_scsi_status(Scsi_Cmnd *cmd);
+static __inline uint32_t ahc_cmd_get_scsi_status(struct scsi_cmnd *cmd);
static __inline uint32_t ahc_get_scsi_status(struct scb *);
static __inline void ahc_set_transaction_tag(struct scb *, int, u_int);
static __inline u_long ahc_get_transfer_length(struct scb *);
@@ -922,7 +748,7 @@ static __inline void ahc_platform_scb_free(struct ahc_softc *ahc,
static __inline void ahc_freeze_scb(struct scb *scb);
static __inline
-void ahc_cmd_set_transaction_status(Scsi_Cmnd *cmd, uint32_t status)
+void ahc_cmd_set_transaction_status(struct scsi_cmnd *cmd, uint32_t status)
{
cmd->result &= ~(CAM_STATUS_MASK << 16);
cmd->result |= status << 16;
@@ -935,7 +761,7 @@ void ahc_set_transaction_status(struct scb *scb, uint32_t status)
}
static __inline
-void ahc_cmd_set_scsi_status(Scsi_Cmnd *cmd, uint32_t status)
+void ahc_cmd_set_scsi_status(struct scsi_cmnd *cmd, uint32_t status)
{
cmd->result &= ~0xFFFF;
cmd->result |= status;
@@ -948,7 +774,7 @@ void ahc_set_scsi_status(struct scb *scb, uint32_t status)
}
static __inline
-uint32_t ahc_cmd_get_transaction_status(Scsi_Cmnd *cmd)
+uint32_t ahc_cmd_get_transaction_status(struct scsi_cmnd *cmd)
{
return ((cmd->result >> 16) & CAM_STATUS_MASK);
}
@@ -960,7 +786,7 @@ uint32_t ahc_get_transaction_status(struct scb *scb)
}
static __inline
-uint32_t ahc_cmd_get_scsi_status(Scsi_Cmnd *cmd)
+uint32_t ahc_cmd_get_scsi_status(struct scsi_cmnd *cmd)
{
return (cmd->result & 0xFFFF);
}
@@ -1043,7 +869,6 @@ ahc_notify_xfer_settings_change(struct ahc_softc *ahc,
static __inline void
ahc_platform_scb_free(struct ahc_softc *ahc, struct scb *scb)
{
- ahc->flags &= ~AHC_RESOURCE_SHORTAGE;
}
int ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
index 6f6674aa31e..89d737ee551 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
@@ -140,27 +140,17 @@ struct pci_driver aic7xxx_pci_driver = {
static void
ahc_linux_pci_dev_remove(struct pci_dev *pdev)
{
- struct ahc_softc *ahc;
- u_long l;
+ struct ahc_softc *ahc = pci_get_drvdata(pdev);
+ u_long s;
- /*
- * We should be able to just perform
- * the free directly, but check our
- * list for extra sanity.
- */
- ahc_list_lock(&l);
- ahc = ahc_find_softc((struct ahc_softc *)pci_get_drvdata(pdev));
- if (ahc != NULL) {
- u_long s;
+ ahc_list_lock(&s);
+ TAILQ_REMOVE(&ahc_tailq, ahc, links);
+ ahc_list_unlock(&s);
- TAILQ_REMOVE(&ahc_tailq, ahc, links);
- ahc_list_unlock(&l);
- ahc_lock(ahc, &s);
- ahc_intr_enable(ahc, FALSE);
- ahc_unlock(ahc, &s);
- ahc_free(ahc);
- } else
- ahc_list_unlock(&l);
+ ahc_lock(ahc, &s);
+ ahc_intr_enable(ahc, FALSE);
+ ahc_unlock(ahc, &s);
+ ahc_free(ahc);
}
static int
@@ -174,22 +164,6 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
char *name;
int error;
- /*
- * Some BIOSen report the same device multiple times.
- */
- TAILQ_FOREACH(ahc, &ahc_tailq, links) {
- struct pci_dev *probed_pdev;
-
- probed_pdev = ahc->dev_softc;
- if (probed_pdev->bus->number == pdev->bus->number
- && probed_pdev->devfn == pdev->devfn)
- break;
- }
- if (ahc != NULL) {
- /* Skip duplicate. */
- return (-ENODEV);
- }
-
pci = pdev;
entry = ahc_find_pci_device(pci);
if (entry == NULL)
@@ -221,13 +195,11 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
&& ahc_linux_get_memsize() > 0x80000000
&& pci_set_dma_mask(pdev, mask_39bit) == 0) {
ahc->flags |= AHC_39BIT_ADDRESSING;
- ahc->platform_data->hw_dma_mask = mask_39bit;
} else {
if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n");
return (-ENODEV);
}
- ahc->platform_data->hw_dma_mask = DMA_32BIT_MASK;
}
ahc->dev_softc = pci;
error = ahc_pci_config(ahc, entry);
@@ -236,15 +208,8 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return (-error);
}
pci_set_drvdata(pdev, ahc);
- if (aic7xxx_detect_complete) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
+ if (aic7xxx_detect_complete)
ahc_linux_register_host(ahc, &aic7xxx_driver_template);
-#else
- printf("aic7xxx: ignoring PCI device found after "
- "initialization\n");
- return (-ENODEV);
-#endif
- }
return (0);
}
diff --git a/drivers/scsi/aic7xxx/aic7xxx_proc.c b/drivers/scsi/aic7xxx/aic7xxx_proc.c
index 85e80eecc9d..ab4469d83fb 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_proc.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_proc.c
@@ -50,7 +50,7 @@ static void ahc_dump_target_state(struct ahc_softc *ahc,
u_int our_id, char channel,
u_int target_id, u_int target_offset);
static void ahc_dump_device_state(struct info_str *info,
- struct ahc_linux_device *dev);
+ struct scsi_device *dev);
static int ahc_proc_write_seeprom(struct ahc_softc *ahc,
char *buffer, int length);
@@ -142,6 +142,7 @@ ahc_dump_target_state(struct ahc_softc *ahc, struct info_str *info,
u_int target_offset)
{
struct ahc_linux_target *targ;
+ struct scsi_target *starget;
struct ahc_initiator_tinfo *tinfo;
struct ahc_tmode_tstate *tstate;
int lun;
@@ -153,7 +154,8 @@ ahc_dump_target_state(struct ahc_softc *ahc, struct info_str *info,
copy_info(info, "Target %d Negotiation Settings\n", target_id);
copy_info(info, "\tUser: ");
ahc_format_transinfo(info, &tinfo->user);
- targ = ahc->platform_data->targets[target_offset];
+ starget = ahc->platform_data->starget[target_offset];
+ targ = scsi_transport_target_data(starget);
if (targ == NULL)
return;
@@ -163,22 +165,25 @@ ahc_dump_target_state(struct ahc_softc *ahc, struct info_str *info,
ahc_format_transinfo(info, &tinfo->curr);
for (lun = 0; lun < AHC_NUM_LUNS; lun++) {
- struct ahc_linux_device *dev;
+ struct scsi_device *sdev;
- dev = targ->devices[lun];
+ sdev = targ->sdev[lun];
- if (dev == NULL)
+ if (sdev == NULL)
continue;
- ahc_dump_device_state(info, dev);
+ ahc_dump_device_state(info, sdev);
}
}
static void
-ahc_dump_device_state(struct info_str *info, struct ahc_linux_device *dev)
+ahc_dump_device_state(struct info_str *info, struct scsi_device *sdev)
{
+ struct ahc_linux_device *dev = scsi_transport_device_data(sdev);
+
copy_info(info, "\tChannel %c Target %d Lun %d Settings\n",
- dev->target->channel + 'A', dev->target->target, dev->lun);
+ sdev->sdev_target->channel + 'A',
+ sdev->sdev_target->id, sdev->lun);
copy_info(info, "\t\tCommands Queued %ld\n", dev->commands_issued);
copy_info(info, "\t\tCommands Active %d\n", dev->active);
@@ -289,36 +294,16 @@ done:
* Return information to handle /proc support for the driver.
*/
int
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-ahc_linux_proc_info(char *buffer, char **start, off_t offset,
- int length, int hostno, int inout)
-#else
ahc_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
off_t offset, int length, int inout)
-#endif
{
- struct ahc_softc *ahc;
+ struct ahc_softc *ahc = *(struct ahc_softc **)shost->hostdata;
struct info_str info;
char ahc_info[256];
- u_long s;
u_int max_targ;
u_int i;
int retval;
- retval = -EINVAL;
- ahc_list_lock(&s);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
- TAILQ_FOREACH(ahc, &ahc_tailq, links) {
- if (ahc->platform_data->host->host_no == hostno)
- break;
- }
-#else
- ahc = ahc_find_softc(*(struct ahc_softc **)shost->hostdata);
-#endif
-
- if (ahc == NULL)
- goto done;
-
/* Has data been written to the file? */
if (inout == TRUE) {
retval = ahc_proc_write_seeprom(ahc, buffer, length);
@@ -380,6 +365,5 @@ ahc_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
}
retval = info.pos > info.offset ? info.pos - info.offset : 0;
done:
- ahc_list_unlock(&s);
return (retval);
}
diff --git a/drivers/scsi/aic7xxx/aiclib.c b/drivers/scsi/aic7xxx/aiclib.c
index 79bfd9efd8e..7c5a6db0e67 100644
--- a/drivers/scsi/aic7xxx/aiclib.c
+++ b/drivers/scsi/aic7xxx/aiclib.c
@@ -35,7 +35,6 @@
#include <linux/version.h>
/* Core SCSI definitions */
-#include "scsi.h"
#include <scsi/scsi_host.h>
#include "aiclib.h"
#include "cam.h"
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index 9e9d0c40187..fac091e7093 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -10358,7 +10358,7 @@ aic7xxx_queue(Scsi_Cmnd *cmd, void (*fn)(Scsi_Cmnd *))
* Returns an enumerated type that indicates the status of the operation.
*-F*************************************************************************/
static int
-aic7xxx_bus_device_reset(Scsi_Cmnd *cmd)
+__aic7xxx_bus_device_reset(Scsi_Cmnd *cmd)
{
struct aic7xxx_host *p;
struct aic7xxx_scb *scb;
@@ -10551,6 +10551,18 @@ aic7xxx_bus_device_reset(Scsi_Cmnd *cmd)
return SUCCESS;
}
+static int
+aic7xxx_bus_device_reset(Scsi_Cmnd *cmd)
+{
+ int rc;
+
+ spin_lock_irq(cmd->device->host->host_lock);
+ rc = __aic7xxx_bus_device_reset(cmd);
+ spin_unlock_irq(cmd->device->host->host_lock);
+
+ return rc;
+}
+
/*+F*************************************************************************
* Function:
@@ -10585,7 +10597,7 @@ aic7xxx_panic_abort(struct aic7xxx_host *p, Scsi_Cmnd *cmd)
* Abort the current SCSI command(s).
*-F*************************************************************************/
static int
-aic7xxx_abort(Scsi_Cmnd *cmd)
+__aic7xxx_abort(Scsi_Cmnd *cmd)
{
struct aic7xxx_scb *scb = NULL;
struct aic7xxx_host *p;
@@ -10802,6 +10814,19 @@ success:
return SUCCESS;
}
+static int
+aic7xxx_abort(Scsi_Cmnd *cmd)
+{
+ int rc;
+
+ spin_lock_irq(cmd->device->host->host_lock);
+ rc = __aic7xxx_abort(cmd);
+ spin_unlock_irq(cmd->device->host->host_lock);
+
+ return rc;
+}
+
+
/*+F*************************************************************************
* Function:
* aic7xxx_reset
@@ -10820,6 +10845,8 @@ aic7xxx_reset(Scsi_Cmnd *cmd)
struct aic_dev_data *aic_dev;
p = (struct aic7xxx_host *) cmd->device->host->hostdata;
+ spin_lock_irq(p->host->host_lock);
+
aic_dev = AIC_DEV(cmd);
if(aic7xxx_position(cmd) < p->scb_data->numscbs)
{
@@ -10859,6 +10886,7 @@ aic7xxx_reset(Scsi_Cmnd *cmd)
* longer have it.
*/
unpause_sequencer(p, FALSE);
+ spin_unlock_irq(p->host->host_lock);
return SUCCESS;
}
@@ -10882,7 +10910,6 @@ aic7xxx_reset(Scsi_Cmnd *cmd)
unpause_sequencer(p, FALSE);
spin_unlock_irq(p->host->host_lock);
ssleep(2);
- spin_lock_irq(p->host->host_lock);
return SUCCESS;
}
diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c
index 27271bfc01d..26498553a7c 100644
--- a/drivers/scsi/arm/cumana_1.c
+++ b/drivers/scsi/arm/cumana_1.c
@@ -244,9 +244,7 @@ static Scsi_Host_Template cumanascsi_template = {
.info = cumanascsi_info,
.queuecommand = cumanascsi_queue_command,
.eh_abort_handler = NCR5380_abort,
- .eh_device_reset_handler= NCR5380_device_reset,
.eh_bus_reset_handler = NCR5380_bus_reset,
- .eh_host_reset_handler = NCR5380_host_reset,
.can_queue = 16,
.this_id = 7,
.sg_tablesize = SG_ALL,
diff --git a/drivers/scsi/arm/ecoscsi.c b/drivers/scsi/arm/ecoscsi.c
index 303648a8470..f8a7fdd3c46 100644
--- a/drivers/scsi/arm/ecoscsi.c
+++ b/drivers/scsi/arm/ecoscsi.c
@@ -162,9 +162,7 @@ static Scsi_Host_Template ecoscsi_template = {
.info = ecoscsi_info,
.queuecommand = ecoscsi_queue_command,
.eh_abort_handler = NCR5380_abort,
- .eh_device_reset_handler= NCR5380_device_reset,
.eh_bus_reset_handler = NCR5380_bus_reset,
- .eh_host_reset_handler = NCR5380_host_reset,
.can_queue = 16,
.this_id = 7,
.sg_tablesize = SG_ALL,
diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c
index 78b7e543471..ce711f166cf 100644
--- a/drivers/scsi/arm/eesox.c
+++ b/drivers/scsi/arm/eesox.c
@@ -466,7 +466,7 @@ int eesoxscsi_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_
return pos;
}
-static ssize_t eesoxscsi_show_term(struct device *dev, char *buf)
+static ssize_t eesoxscsi_show_term(struct device *dev, struct device_attribute *attr, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
struct Scsi_Host *host = ecard_get_drvdata(ec);
@@ -475,7 +475,7 @@ static ssize_t eesoxscsi_show_term(struct device *dev, char *buf)
return sprintf(buf, "%d\n", info->control & EESOX_TERM_ENABLE ? 1 : 0);
}
-static ssize_t eesoxscsi_store_term(struct device *dev, const char *buf, size_t len)
+static ssize_t eesoxscsi_store_term(struct device *dev, struct device_attribute *attr, const char *buf, size_t len)
{
struct expansion_card *ec = ECARD_DEV(dev);
struct Scsi_Host *host = ecard_get_drvdata(ec);
diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c
index 3838f88e1fe..4772fb317f3 100644
--- a/drivers/scsi/arm/fas216.c
+++ b/drivers/scsi/arm/fas216.c
@@ -2659,6 +2659,8 @@ int fas216_eh_host_reset(Scsi_Cmnd *SCpnt)
{
FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
+ spin_lock_irq(info->host->host_lock);
+
fas216_checkmagic(info);
printk("scsi%d.%c: %s: resetting host\n",
@@ -2686,6 +2688,7 @@ int fas216_eh_host_reset(Scsi_Cmnd *SCpnt)
fas216_init_chip(info);
+ spin_unlock_irq(info->host->host_lock);
return SUCCESS;
}
diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c
index ff2554f4cb8..de24bb991f1 100644
--- a/drivers/scsi/arm/oak.c
+++ b/drivers/scsi/arm/oak.c
@@ -118,9 +118,7 @@ static Scsi_Host_Template oakscsi_template = {
.info = oakscsi_info,
.queuecommand = oakscsi_queue_command,
.eh_abort_handler = NCR5380_abort,
- .eh_device_reset_handler= NCR5380_device_reset,
.eh_bus_reset_handler = NCR5380_bus_reset,
- .eh_host_reset_handler = NCR5380_host_reset,
.can_queue = 16,
.this_id = 7,
.sg_tablesize = SG_ALL,
diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c
index 54f23be6460..abda216113f 100644
--- a/drivers/scsi/arm/powertec.c
+++ b/drivers/scsi/arm/powertec.c
@@ -269,7 +269,7 @@ int powertecscsi_proc_info(struct Scsi_Host *host, char *buffer, char **start, o
return pos;
}
-static ssize_t powertecscsi_show_term(struct device *dev, char *buf)
+static ssize_t powertecscsi_show_term(struct device *dev, struct device_attribute *attr, char *buf)
{
struct expansion_card *ec = ECARD_DEV(dev);
struct Scsi_Host *host = ecard_get_drvdata(ec);
@@ -279,7 +279,7 @@ static ssize_t powertecscsi_show_term(struct device *dev, char *buf)
}
static ssize_t
-powertecscsi_store_term(struct device *dev, const char *buf, size_t len)
+powertecscsi_store_term(struct device *dev, struct device_attribute *attr, const char *buf, size_t len)
{
struct expansion_card *ec = ECARD_DEV(dev);
struct Scsi_Host *host = ecard_get_drvdata(ec);
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index 3867f91ef8c..3be54643925 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -153,6 +153,7 @@ static struct ata_port_operations piix_pata_ops = {
.port_start = ata_port_start,
.port_stop = ata_port_stop,
+ .host_stop = ata_host_stop,
};
static struct ata_port_operations piix_sata_ops = {
@@ -180,6 +181,7 @@ static struct ata_port_operations piix_sata_ops = {
.port_start = ata_port_start,
.port_stop = ata_port_stop,
+ .host_stop = ata_host_stop,
};
static struct ata_port_info piix_port_info[] = {
@@ -663,15 +665,6 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
return ata_pci_init_one(pdev, port_info, n_ports);
}
-/**
- * piix_init -
- *
- * LOCKING:
- *
- * RETURNS:
- *
- */
-
static int __init piix_init(void)
{
int rc;
@@ -687,13 +680,6 @@ static int __init piix_init(void)
return 0;
}
-/**
- * piix_exit -
- *
- * LOCKING:
- *
- */
-
static void __exit piix_exit(void)
{
pci_unregister_driver(&piix_pci_driver);
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 45b75ddacaa..e6153fe5842 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -3146,8 +3146,8 @@ static const char *atp870u_info(struct Scsi_Host *notused)
}
#define BLS buffer + len + size
-int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer,
- char **start, off_t offset, int length, int inout)
+static int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer,
+ char **start, off_t offset, int length, int inout)
{
static u8 buff[512];
int size = 0;
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
new file mode 100644
index 00000000000..3900e28ac7d
--- /dev/null
+++ b/drivers/scsi/ch.c
@@ -0,0 +1,1026 @@
+/*
+ * SCSI Media Changer device driver for Linux 2.6
+ *
+ * (c) 1996-2003 Gerd Knorr <kraxel@bytesex.org>
+ *
+ */
+
+#define VERSION "0.25"
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/completion.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/ioctl32.h>
+#include <linux/compat.h>
+#include <linux/chio.h> /* here are all the ioctls */
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_ioctl.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_request.h>
+#include <scsi/scsi_dbg.h>
+
+#define CH_DT_MAX 16
+#define CH_TYPES 8
+
+MODULE_DESCRIPTION("device driver for scsi media changer devices");
+MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org>");
+MODULE_LICENSE("GPL");
+
+static int init = 1;
+module_param(init, int, 0444);
+MODULE_PARM_DESC(init, \
+ "initialize element status on driver load (default: on)");
+
+static int timeout_move = 300;
+module_param(timeout_move, int, 0644);
+MODULE_PARM_DESC(timeout_move,"timeout for move commands "
+ "(default: 300 seconds)");
+
+static int timeout_init = 3600;
+module_param(timeout_init, int, 0644);
+MODULE_PARM_DESC(timeout_init,"timeout for INITIALIZE ELEMENT STATUS "
+ "(default: 3600 seconds)");
+
+static int verbose = 1;
+module_param(verbose, int, 0644);
+MODULE_PARM_DESC(verbose,"be verbose (default: on)");
+
+static int debug = 0;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug,"enable/disable debug messages, also prints more "
+ "detailed sense codes on scsi errors (default: off)");
+
+static int dt_id[CH_DT_MAX] = { [ 0 ... (CH_DT_MAX-1) ] = -1 };
+static int dt_lun[CH_DT_MAX];
+module_param_array(dt_id, int, NULL, 0444);
+module_param_array(dt_lun, int, NULL, 0444);
+
+/* tell the driver about vendor-specific slots */
+static int vendor_firsts[CH_TYPES-4];
+static int vendor_counts[CH_TYPES-4];
+module_param_array(vendor_firsts, int, NULL, 0444);
+module_param_array(vendor_counts, int, NULL, 0444);
+
+static char *vendor_labels[CH_TYPES-4] = {
+ "v0", "v1", "v2", "v3"
+};
+// module_param_string_array(vendor_labels, NULL, 0444);
+
+#define dprintk(fmt, arg...) if (debug) \
+ printk(KERN_DEBUG "%s: " fmt, ch->name , ## arg)
+#define vprintk(fmt, arg...) if (verbose) \
+ printk(KERN_INFO "%s: " fmt, ch->name , ## arg)
+
+/* ------------------------------------------------------------------- */
+
+#define MAX_RETRIES 1
+
+static int ch_probe(struct device *);
+static int ch_remove(struct device *);
+static int ch_open(struct inode * inode, struct file * filp);
+static int ch_release(struct inode * inode, struct file * filp);
+static int ch_ioctl(struct inode * inode, struct file * filp,
+ unsigned int cmd, unsigned long arg);
+#ifdef CONFIG_COMPAT
+static long ch_ioctl_compat(struct file * filp,
+ unsigned int cmd, unsigned long arg);
+#endif
+
+static struct class * ch_sysfs_class;
+
+typedef struct {
+ struct list_head list;
+ int minor;
+ char name[8];
+ struct scsi_device *device;
+ struct scsi_device **dt; /* ptrs to data transfer elements */
+ u_int firsts[CH_TYPES];
+ u_int counts[CH_TYPES];
+ u_int unit_attention;
+ u_int voltags;
+ struct semaphore lock;
+} scsi_changer;
+
+static LIST_HEAD(ch_devlist);
+static spinlock_t ch_devlist_lock = SPIN_LOCK_UNLOCKED;
+static int ch_devcount;
+
+static struct scsi_driver ch_template =
+{
+ .owner = THIS_MODULE,
+ .gendrv = {
+ .name = "ch",
+ .probe = ch_probe,
+ .remove = ch_remove,
+ },
+};
+
+static struct file_operations changer_fops =
+{
+ .owner = THIS_MODULE,
+ .open = ch_open,
+ .release = ch_release,
+ .ioctl = ch_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = ch_ioctl_compat,
+#endif
+};
+
+static struct {
+ unsigned char sense;
+ unsigned char asc;
+ unsigned char ascq;
+ int errno;
+} err[] = {
+/* Just filled in what looks right. Hav'nt checked any standard paper for
+ these errno assignments, so they may be wrong... */
+ {
+ .sense = ILLEGAL_REQUEST,
+ .asc = 0x21,
+ .ascq = 0x01,
+ .errno = EBADSLT, /* Invalid element address */
+ },{
+ .sense = ILLEGAL_REQUEST,
+ .asc = 0x28,
+ .ascq = 0x01,
+ .errno = EBADE, /* Import or export element accessed */
+ },{
+ .sense = ILLEGAL_REQUEST,
+ .asc = 0x3B,
+ .ascq = 0x0D,
+ .errno = EXFULL, /* Medium destination element full */
+ },{
+ .sense = ILLEGAL_REQUEST,
+ .asc = 0x3B,
+ .ascq = 0x0E,
+ .errno = EBADE, /* Medium source element empty */
+ },{
+ .sense = ILLEGAL_REQUEST,
+ .asc = 0x20,
+ .ascq = 0x00,
+ .errno = EBADRQC, /* Invalid command operation code */
+ },{
+ /* end of list */
+ }
+};
+
+/* ------------------------------------------------------------------- */
+
+static int ch_find_errno(unsigned char *sense_buffer)
+{
+ int i,errno = 0;
+
+ /* Check to see if additional sense information is available */
+ if (sense_buffer[7] > 5 &&
+ sense_buffer[12] != 0) {
+ for (i = 0; err[i].errno != 0; i++) {
+ if (err[i].sense == sense_buffer[ 2] &&
+ err[i].asc == sense_buffer[12] &&
+ err[i].ascq == sense_buffer[13]) {
+ errno = -err[i].errno;
+ break;
+ }
+ }
+ }
+ if (errno == 0)
+ errno = -EIO;
+ return errno;
+}
+
+static int
+ch_do_scsi(scsi_changer *ch, unsigned char *cmd,
+ void *buffer, unsigned buflength,
+ enum dma_data_direction direction)
+{
+ int errno, retries = 0, timeout;
+ struct scsi_request *sr;
+
+ sr = scsi_allocate_request(ch->device, GFP_KERNEL);
+ if (NULL == sr)
+ return -ENOMEM;
+
+ timeout = (cmd[0] == INITIALIZE_ELEMENT_STATUS)
+ ? timeout_init : timeout_move;
+
+ retry:
+ errno = 0;
+ if (debug) {
+ dprintk("command: ");
+ __scsi_print_command(cmd);
+ }
+
+ scsi_wait_req(sr, cmd, buffer, buflength,
+ timeout * HZ, MAX_RETRIES);
+
+ dprintk("result: 0x%x\n",sr->sr_result);
+ if (driver_byte(sr->sr_result) & DRIVER_SENSE) {
+ if (debug)
+ scsi_print_req_sense(ch->name, sr);
+ errno = ch_find_errno(sr->sr_sense_buffer);
+
+ switch(sr->sr_sense_buffer[2] & 0xf) {
+ case UNIT_ATTENTION:
+ ch->unit_attention = 1;
+ if (retries++ < 3)
+ goto retry;
+ break;
+ }
+ }
+ scsi_release_request(sr);
+ return errno;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int
+ch_elem_to_typecode(scsi_changer *ch, u_int elem)
+{
+ int i;
+
+ for (i = 0; i < CH_TYPES; i++) {
+ if (elem >= ch->firsts[i] &&
+ elem < ch->firsts[i] +
+ ch->counts[i])
+ return i+1;
+ }
+ return 0;
+}
+
+static int
+ch_read_element_status(scsi_changer *ch, u_int elem, char *data)
+{
+ u_char cmd[12];
+ u_char *buffer;
+ int result;
+
+ buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
+ if(!buffer)
+ return -ENOMEM;
+
+ retry:
+ memset(cmd,0,sizeof(cmd));
+ cmd[0] = READ_ELEMENT_STATUS;
+ cmd[1] = (ch->device->lun << 5) |
+ (ch->voltags ? 0x10 : 0) |
+ ch_elem_to_typecode(ch,elem);
+ cmd[2] = (elem >> 8) & 0xff;
+ cmd[3] = elem & 0xff;
+ cmd[5] = 1;
+ cmd[9] = 255;
+ if (0 == (result = ch_do_scsi(ch, cmd, buffer, 256, DMA_FROM_DEVICE))) {
+ if (((buffer[16] << 8) | buffer[17]) != elem) {
+ dprintk("asked for element 0x%02x, got 0x%02x\n",
+ elem,(buffer[16] << 8) | buffer[17]);
+ kfree(buffer);
+ return -EIO;
+ }
+ memcpy(data,buffer+16,16);
+ } else {
+ if (ch->voltags) {
+ ch->voltags = 0;
+ vprintk("device has no volume tag support\n");
+ goto retry;
+ }
+ dprintk("READ ELEMENT STATUS for element 0x%x failed\n",elem);
+ }
+ kfree(buffer);
+ return result;
+}
+
+static int
+ch_init_elem(scsi_changer *ch)
+{
+ int err;
+ u_char cmd[6];
+
+ vprintk("INITIALIZE ELEMENT STATUS, may take some time ...\n");
+ memset(cmd,0,sizeof(cmd));
+ cmd[0] = INITIALIZE_ELEMENT_STATUS;
+ cmd[1] = ch->device->lun << 5;
+ err = ch_do_scsi(ch, cmd, NULL, 0, DMA_NONE);
+ vprintk("... finished\n");
+ return err;
+}
+
+static int
+ch_readconfig(scsi_changer *ch)
+{
+ u_char cmd[10], data[16];
+ u_char *buffer;
+ int result,id,lun,i;
+ u_int elem;
+
+ buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
+ if (!buffer)
+ return -ENOMEM;
+ memset(buffer,0,512);
+
+ memset(cmd,0,sizeof(cmd));
+ cmd[0] = MODE_SENSE;
+ cmd[1] = ch->device->lun << 5;
+ cmd[2] = 0x1d;
+ cmd[4] = 255;
+ result = ch_do_scsi(ch, cmd, buffer, 255, DMA_FROM_DEVICE);
+ if (0 != result) {
+ cmd[1] |= (1<<3);
+ result = ch_do_scsi(ch, cmd, buffer, 255, DMA_FROM_DEVICE);
+ }
+ if (0 == result) {
+ ch->firsts[CHET_MT] =
+ (buffer[buffer[3]+ 6] << 8) | buffer[buffer[3]+ 7];
+ ch->counts[CHET_MT] =
+ (buffer[buffer[3]+ 8] << 8) | buffer[buffer[3]+ 9];
+ ch->firsts[CHET_ST] =
+ (buffer[buffer[3]+10] << 8) | buffer[buffer[3]+11];
+ ch->counts[CHET_ST] =
+ (buffer[buffer[3]+12] << 8) | buffer[buffer[3]+13];
+ ch->firsts[CHET_IE] =
+ (buffer[buffer[3]+14] << 8) | buffer[buffer[3]+15];
+ ch->counts[CHET_IE] =
+ (buffer[buffer[3]+16] << 8) | buffer[buffer[3]+17];
+ ch->firsts[CHET_DT] =
+ (buffer[buffer[3]+18] << 8) | buffer[buffer[3]+19];
+ ch->counts[CHET_DT] =
+ (buffer[buffer[3]+20] << 8) | buffer[buffer[3]+21];
+ vprintk("type #1 (mt): 0x%x+%d [medium transport]\n",
+ ch->firsts[CHET_MT],
+ ch->counts[CHET_MT]);
+ vprintk("type #2 (st): 0x%x+%d [storage]\n",
+ ch->firsts[CHET_ST],
+ ch->counts[CHET_ST]);
+ vprintk("type #3 (ie): 0x%x+%d [import/export]\n",
+ ch->firsts[CHET_IE],
+ ch->counts[CHET_IE]);
+ vprintk("type #4 (dt): 0x%x+%d [data transfer]\n",
+ ch->firsts[CHET_DT],
+ ch->counts[CHET_DT]);
+ } else {
+ vprintk("reading element address assigment page failed!\n");
+ }
+
+ /* vendor specific element types */
+ for (i = 0; i < 4; i++) {
+ if (0 == vendor_counts[i])
+ continue;
+ if (NULL == vendor_labels[i])
+ continue;
+ ch->firsts[CHET_V1+i] = vendor_firsts[i];
+ ch->counts[CHET_V1+i] = vendor_counts[i];
+ vprintk("type #%d (v%d): 0x%x+%d [%s, vendor specific]\n",
+ i+5,i+1,vendor_firsts[i],vendor_counts[i],
+ vendor_labels[i]);
+ }
+
+ /* look up the devices of the data transfer elements */
+ ch->dt = kmalloc(ch->counts[CHET_DT]*sizeof(struct scsi_device),
+ GFP_KERNEL);
+ for (elem = 0; elem < ch->counts[CHET_DT]; elem++) {
+ id = -1;
+ lun = 0;
+ if (elem < CH_DT_MAX && -1 != dt_id[elem]) {
+ id = dt_id[elem];
+ lun = dt_lun[elem];
+ vprintk("dt 0x%x: [insmod option] ",
+ elem+ch->firsts[CHET_DT]);
+ } else if (0 != ch_read_element_status
+ (ch,elem+ch->firsts[CHET_DT],data)) {
+ vprintk("dt 0x%x: READ ELEMENT STATUS failed\n",
+ elem+ch->firsts[CHET_DT]);
+ } else {
+ vprintk("dt 0x%x: ",elem+ch->firsts[CHET_DT]);
+ if (data[6] & 0x80) {
+ if (verbose)
+ printk("not this SCSI bus\n");
+ ch->dt[elem] = NULL;
+ } else if (0 == (data[6] & 0x30)) {
+ if (verbose)
+ printk("ID/LUN unknown\n");
+ ch->dt[elem] = NULL;
+ } else {
+ id = ch->device->id;
+ lun = 0;
+ if (data[6] & 0x20) id = data[7];
+ if (data[6] & 0x10) lun = data[6] & 7;
+ }
+ }
+ if (-1 != id) {
+ if (verbose)
+ printk("ID %i, LUN %i, ",id,lun);
+ ch->dt[elem] =
+ scsi_device_lookup(ch->device->host,
+ ch->device->channel,
+ id,lun);
+ if (!ch->dt[elem]) {
+ /* should not happen */
+ if (verbose)
+ printk("Huh? device not found!\n");
+ } else {
+ if (verbose)
+ printk("name: %8.8s %16.16s %4.4s\n",
+ ch->dt[elem]->vendor,
+ ch->dt[elem]->model,
+ ch->dt[elem]->rev);
+ }
+ }
+ }
+ ch->voltags = 1;
+ kfree(buffer);
+
+ return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int
+ch_position(scsi_changer *ch, u_int trans, u_int elem, int rotate)
+{
+ u_char cmd[10];
+
+ dprintk("position: 0x%x\n",elem);
+ if (0 == trans)
+ trans = ch->firsts[CHET_MT];
+ memset(cmd,0,sizeof(cmd));
+ cmd[0] = POSITION_TO_ELEMENT;
+ cmd[1] = ch->device->lun << 5;
+ cmd[2] = (trans >> 8) & 0xff;
+ cmd[3] = trans & 0xff;
+ cmd[4] = (elem >> 8) & 0xff;
+ cmd[5] = elem & 0xff;
+ cmd[8] = rotate ? 1 : 0;
+ return ch_do_scsi(ch, cmd, NULL, 0, DMA_NONE);
+}
+
+static int
+ch_move(scsi_changer *ch, u_int trans, u_int src, u_int dest, int rotate)
+{
+ u_char cmd[12];
+
+ dprintk("move: 0x%x => 0x%x\n",src,dest);
+ if (0 == trans)
+ trans = ch->firsts[CHET_MT];
+ memset(cmd,0,sizeof(cmd));
+ cmd[0] = MOVE_MEDIUM;
+ cmd[1] = ch->device->lun << 5;
+ cmd[2] = (trans >> 8) & 0xff;
+ cmd[3] = trans & 0xff;
+ cmd[4] = (src >> 8) & 0xff;
+ cmd[5] = src & 0xff;
+ cmd[6] = (dest >> 8) & 0xff;
+ cmd[7] = dest & 0xff;
+ cmd[10] = rotate ? 1 : 0;
+ return ch_do_scsi(ch, cmd, NULL,0, DMA_NONE);
+}
+
+static int
+ch_exchange(scsi_changer *ch, u_int trans, u_int src,
+ u_int dest1, u_int dest2, int rotate1, int rotate2)
+{
+ u_char cmd[12];
+
+ dprintk("exchange: 0x%x => 0x%x => 0x%x\n",
+ src,dest1,dest2);
+ if (0 == trans)
+ trans = ch->firsts[CHET_MT];
+ memset(cmd,0,sizeof(cmd));
+ cmd[0] = EXCHANGE_MEDIUM;
+ cmd[1] = ch->device->lun << 5;
+ cmd[2] = (trans >> 8) & 0xff;
+ cmd[3] = trans & 0xff;
+ cmd[4] = (src >> 8) & 0xff;
+ cmd[5] = src & 0xff;
+ cmd[6] = (dest1 >> 8) & 0xff;
+ cmd[7] = dest1 & 0xff;
+ cmd[8] = (dest2 >> 8) & 0xff;
+ cmd[9] = dest2 & 0xff;
+ cmd[10] = (rotate1 ? 1 : 0) | (rotate2 ? 2 : 0);
+
+ return ch_do_scsi(ch, cmd, NULL,0, DMA_NONE);
+}
+
+static void
+ch_check_voltag(char *tag)
+{
+ int i;
+
+ for (i = 0; i < 32; i++) {
+ /* restrict to ascii */
+ if (tag[i] >= 0x7f || tag[i] < 0x20)
+ tag[i] = ' ';
+ /* don't allow search wildcards */
+ if (tag[i] == '?' ||
+ tag[i] == '*')
+ tag[i] = ' ';
+ }
+}
+
+static int
+ch_set_voltag(scsi_changer *ch, u_int elem,
+ int alternate, int clear, u_char *tag)
+{
+ u_char cmd[12];
+ u_char *buffer;
+ int result;
+
+ buffer = kmalloc(512, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+ memset(buffer,0,512);
+
+ dprintk("%s %s voltag: 0x%x => \"%s\"\n",
+ clear ? "clear" : "set",
+ alternate ? "alternate" : "primary",
+ elem, tag);
+ memset(cmd,0,sizeof(cmd));
+ cmd[0] = SEND_VOLUME_TAG;
+ cmd[1] = (ch->device->lun << 5) |
+ ch_elem_to_typecode(ch,elem);
+ cmd[2] = (elem >> 8) & 0xff;
+ cmd[3] = elem & 0xff;
+ cmd[5] = clear
+ ? (alternate ? 0x0d : 0x0c)
+ : (alternate ? 0x0b : 0x0a);
+
+ cmd[9] = 255;
+
+ memcpy(buffer,tag,32);
+ ch_check_voltag(buffer);
+
+ result = ch_do_scsi(ch, cmd, buffer, 256, DMA_TO_DEVICE);
+ kfree(buffer);
+ return result;
+}
+
+static int ch_gstatus(scsi_changer *ch, int type, unsigned char *dest)
+{
+ int retval = 0;
+ u_char data[16];
+ unsigned int i;
+
+ down(&ch->lock);
+ for (i = 0; i < ch->counts[type]; i++) {
+ if (0 != ch_read_element_status
+ (ch, ch->firsts[type]+i,data)) {
+ retval = -EIO;
+ break;
+ }
+ put_user(data[2], dest+i);
+ if (data[2] & CESTATUS_EXCEPT)
+ vprintk("element 0x%x: asc=0x%x, ascq=0x%x\n",
+ ch->firsts[type]+i,
+ (int)data[4],(int)data[5]);
+ retval = ch_read_element_status
+ (ch, ch->firsts[type]+i,data);
+ if (0 != retval)
+ break;
+ }
+ up(&ch->lock);
+ return retval;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int
+ch_release(struct inode *inode, struct file *file)
+{
+ scsi_changer *ch = file->private_data;
+
+ scsi_device_put(ch->device);
+ file->private_data = NULL;
+ return 0;
+}
+
+static int
+ch_open(struct inode *inode, struct file *file)
+{
+ scsi_changer *tmp, *ch;
+ int minor = iminor(inode);
+
+ spin_lock(&ch_devlist_lock);
+ ch = NULL;
+ list_for_each_entry(tmp,&ch_devlist,list) {
+ if (tmp->minor == minor)
+ ch = tmp;
+ }
+ if (NULL == ch || scsi_device_get(ch->device)) {
+ spin_unlock(&ch_devlist_lock);
+ return -ENXIO;
+ }
+ spin_unlock(&ch_devlist_lock);
+
+ file->private_data = ch;
+ return 0;
+}
+
+static int
+ch_checkrange(scsi_changer *ch, unsigned int type, unsigned int unit)
+{
+ if (type >= CH_TYPES || unit >= ch->counts[type])
+ return -1;
+ return 0;
+}
+
+static int ch_ioctl(struct inode * inode, struct file * file,
+ unsigned int cmd, unsigned long arg)
+{
+ scsi_changer *ch = file->private_data;
+ int retval;
+
+ switch (cmd) {
+ case CHIOGPARAMS:
+ {
+ struct changer_params params;
+
+ params.cp_curpicker = 0;
+ params.cp_npickers = ch->counts[CHET_MT];
+ params.cp_nslots = ch->counts[CHET_ST];
+ params.cp_nportals = ch->counts[CHET_IE];
+ params.cp_ndrives = ch->counts[CHET_DT];
+
+ if (copy_to_user((void *) arg, &params, sizeof(params)))
+ return -EFAULT;
+ return 0;
+ }
+ case CHIOGVPARAMS:
+ {
+ struct changer_vendor_params vparams;
+
+ memset(&vparams,0,sizeof(vparams));
+ if (ch->counts[CHET_V1]) {
+ vparams.cvp_n1 = ch->counts[CHET_V1];
+ strncpy(vparams.cvp_label1,vendor_labels[0],16);
+ }
+ if (ch->counts[CHET_V2]) {
+ vparams.cvp_n2 = ch->counts[CHET_V2];
+ strncpy(vparams.cvp_label2,vendor_labels[1],16);
+ }
+ if (ch->counts[CHET_V3]) {
+ vparams.cvp_n3 = ch->counts[CHET_V3];
+ strncpy(vparams.cvp_label3,vendor_labels[2],16);
+ }
+ if (ch->counts[CHET_V4]) {
+ vparams.cvp_n4 = ch->counts[CHET_V4];
+ strncpy(vparams.cvp_label4,vendor_labels[3],16);
+ }
+ if (copy_to_user((void *) arg, &vparams, sizeof(vparams)))
+ return -EFAULT;
+ return 0;
+ }
+
+ case CHIOPOSITION:
+ {
+ struct changer_position pos;
+
+ if (copy_from_user(&pos, (void*)arg, sizeof (pos)))
+ return -EFAULT;
+
+ if (0 != ch_checkrange(ch, pos.cp_type, pos.cp_unit)) {
+ dprintk("CHIOPOSITION: invalid parameter\n");
+ return -EBADSLT;
+ }
+ down(&ch->lock);
+ retval = ch_position(ch,0,
+ ch->firsts[pos.cp_type] + pos.cp_unit,
+ pos.cp_flags & CP_INVERT);
+ up(&ch->lock);
+ return retval;
+ }
+
+ case CHIOMOVE:
+ {
+ struct changer_move mv;
+
+ if (copy_from_user(&mv, (void*)arg, sizeof (mv)))
+ return -EFAULT;
+
+ if (0 != ch_checkrange(ch, mv.cm_fromtype, mv.cm_fromunit) ||
+ 0 != ch_checkrange(ch, mv.cm_totype, mv.cm_tounit )) {
+ dprintk("CHIOMOVE: invalid parameter\n");
+ return -EBADSLT;
+ }
+
+ down(&ch->lock);
+ retval = ch_move(ch,0,
+ ch->firsts[mv.cm_fromtype] + mv.cm_fromunit,
+ ch->firsts[mv.cm_totype] + mv.cm_tounit,
+ mv.cm_flags & CM_INVERT);
+ up(&ch->lock);
+ return retval;
+ }
+
+ case CHIOEXCHANGE:
+ {
+ struct changer_exchange mv;
+
+ if (copy_from_user(&mv, (void*)arg, sizeof (mv)))
+ return -EFAULT;
+
+ if (0 != ch_checkrange(ch, mv.ce_srctype, mv.ce_srcunit ) ||
+ 0 != ch_checkrange(ch, mv.ce_fdsttype, mv.ce_fdstunit) ||
+ 0 != ch_checkrange(ch, mv.ce_sdsttype, mv.ce_sdstunit)) {
+ dprintk("CHIOEXCHANGE: invalid parameter\n");
+ return -EBADSLT;
+ }
+
+ down(&ch->lock);
+ retval = ch_exchange
+ (ch,0,
+ ch->firsts[mv.ce_srctype] + mv.ce_srcunit,
+ ch->firsts[mv.ce_fdsttype] + mv.ce_fdstunit,
+ ch->firsts[mv.ce_sdsttype] + mv.ce_sdstunit,
+ mv.ce_flags & CE_INVERT1, mv.ce_flags & CE_INVERT2);
+ up(&ch->lock);
+ return retval;
+ }
+
+ case CHIOGSTATUS:
+ {
+ struct changer_element_status ces;
+
+ if (copy_from_user(&ces, (void*)arg, sizeof (ces)))
+ return -EFAULT;
+ if (ces.ces_type < 0 || ces.ces_type >= CH_TYPES)
+ return -EINVAL;
+
+ return ch_gstatus(ch, ces.ces_type, ces.ces_data);
+ }
+
+ case CHIOGELEM:
+ {
+ struct changer_get_element cge;
+ u_char cmd[12];
+ u_char *buffer;
+ unsigned int elem;
+ int result,i;
+
+ if (copy_from_user(&cge, (void*)arg, sizeof (cge)))
+ return -EFAULT;
+
+ if (0 != ch_checkrange(ch, cge.cge_type, cge.cge_unit))
+ return -EINVAL;
+ elem = ch->firsts[cge.cge_type] + cge.cge_unit;
+
+ buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
+ if (!buffer)
+ return -ENOMEM;
+ down(&ch->lock);
+
+ voltag_retry:
+ memset(cmd,0,sizeof(cmd));
+ cmd[0] = READ_ELEMENT_STATUS;
+ cmd[1] = (ch->device->lun << 5) |
+ (ch->voltags ? 0x10 : 0) |
+ ch_elem_to_typecode(ch,elem);
+ cmd[2] = (elem >> 8) & 0xff;
+ cmd[3] = elem & 0xff;
+ cmd[5] = 1;
+ cmd[9] = 255;
+
+ if (0 == (result = ch_do_scsi(ch, cmd, buffer, 256, DMA_FROM_DEVICE))) {
+ cge.cge_status = buffer[18];
+ cge.cge_flags = 0;
+ if (buffer[18] & CESTATUS_EXCEPT) {
+ cge.cge_errno = EIO;
+ }
+ if (buffer[25] & 0x80) {
+ cge.cge_flags |= CGE_SRC;
+ if (buffer[25] & 0x40)
+ cge.cge_flags |= CGE_INVERT;
+ elem = (buffer[26]<<8) | buffer[27];
+ for (i = 0; i < 4; i++) {
+ if (elem >= ch->firsts[i] &&
+ elem < ch->firsts[i] + ch->counts[i]) {
+ cge.cge_srctype = i;
+ cge.cge_srcunit = elem-ch->firsts[i];
+ }
+ }
+ }
+ if ((buffer[22] & 0x30) == 0x30) {
+ cge.cge_flags |= CGE_IDLUN;
+ cge.cge_id = buffer[23];
+ cge.cge_lun = buffer[22] & 7;
+ }
+ if (buffer[9] & 0x80) {
+ cge.cge_flags |= CGE_PVOLTAG;
+ memcpy(cge.cge_pvoltag,buffer+28,36);
+ }
+ if (buffer[9] & 0x40) {
+ cge.cge_flags |= CGE_AVOLTAG;
+ memcpy(cge.cge_avoltag,buffer+64,36);
+ }
+ } else if (ch->voltags) {
+ ch->voltags = 0;
+ vprintk("device has no volume tag support\n");
+ goto voltag_retry;
+ }
+ kfree(buffer);
+ up(&ch->lock);
+
+ if (copy_to_user((void*)arg, &cge, sizeof (cge)))
+ return -EFAULT;
+ return result;
+ }
+
+ case CHIOINITELEM:
+ {
+ down(&ch->lock);
+ retval = ch_init_elem(ch);
+ up(&ch->lock);
+ return retval;
+ }
+
+ case CHIOSVOLTAG:
+ {
+ struct changer_set_voltag csv;
+ int elem;
+
+ if (copy_from_user(&csv, (void*)arg, sizeof(csv)))
+ return -EFAULT;
+
+ if (0 != ch_checkrange(ch, csv.csv_type, csv.csv_unit)) {
+ dprintk("CHIOSVOLTAG: invalid parameter\n");
+ return -EBADSLT;
+ }
+ elem = ch->firsts[csv.csv_type] + csv.csv_unit;
+ down(&ch->lock);
+ retval = ch_set_voltag(ch, elem,
+ csv.csv_flags & CSV_AVOLTAG,
+ csv.csv_flags & CSV_CLEARTAG,
+ csv.csv_voltag);
+ up(&ch->lock);
+ return retval;
+ }
+
+ default:
+ return scsi_ioctl(ch->device, cmd, (void*)arg);
+
+ }
+}
+
+#ifdef CONFIG_COMPAT
+
+struct changer_element_status32 {
+ int ces_type;
+ compat_uptr_t ces_data;
+};
+#define CHIOGSTATUS32 _IOW('c', 8,struct changer_element_status32)
+
+static long ch_ioctl_compat(struct file * file,
+ unsigned int cmd, unsigned long arg)
+{
+ scsi_changer *ch = file->private_data;
+
+ switch (cmd) {
+ case CHIOGPARAMS:
+ case CHIOGVPARAMS:
+ case CHIOPOSITION:
+ case CHIOMOVE:
+ case CHIOEXCHANGE:
+ case CHIOGELEM:
+ case CHIOINITELEM:
+ case CHIOSVOLTAG:
+ /* compatible */
+ return ch_ioctl(NULL /* inode, unused */,
+ file, cmd, arg);
+ case CHIOGSTATUS32:
+ {
+ struct changer_element_status32 ces32;
+ unsigned char *data;
+
+ if (copy_from_user(&ces32, (void*)arg, sizeof (ces32)))
+ return -EFAULT;
+ if (ces32.ces_type < 0 || ces32.ces_type >= CH_TYPES)
+ return -EINVAL;
+
+ data = compat_ptr(ces32.ces_data);
+ return ch_gstatus(ch, ces32.ces_type, data);
+ }
+ default:
+ // return scsi_ioctl_compat(ch->device, cmd, (void*)arg);
+ return -ENOIOCTLCMD;
+
+ }
+}
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static int ch_probe(struct device *dev)
+{
+ struct scsi_device *sd = to_scsi_device(dev);
+ scsi_changer *ch;
+
+ if (sd->type != TYPE_MEDIUM_CHANGER)
+ return -ENODEV;
+
+ ch = kmalloc(sizeof(*ch), GFP_KERNEL);
+ if (NULL == ch)
+ return -ENOMEM;
+
+ memset(ch,0,sizeof(*ch));
+ ch->minor = ch_devcount;
+ sprintf(ch->name,"ch%d",ch->minor);
+ init_MUTEX(&ch->lock);
+ ch->device = sd;
+ ch_readconfig(ch);
+ if (init)
+ ch_init_elem(ch);
+
+ devfs_mk_cdev(MKDEV(SCSI_CHANGER_MAJOR,ch->minor),
+ S_IFCHR | S_IRUGO | S_IWUGO, ch->name);
+ class_device_create(ch_sysfs_class,
+ MKDEV(SCSI_CHANGER_MAJOR,ch->minor),
+ dev, "s%s", ch->name);
+
+ printk(KERN_INFO "Attached scsi changer %s "
+ "at scsi%d, channel %d, id %d, lun %d\n",
+ ch->name, sd->host->host_no, sd->channel, sd->id, sd->lun);
+
+ spin_lock(&ch_devlist_lock);
+ list_add_tail(&ch->list,&ch_devlist);
+ ch_devcount++;
+ spin_unlock(&ch_devlist_lock);
+ return 0;
+}
+
+static int ch_remove(struct device *dev)
+{
+ struct scsi_device *sd = to_scsi_device(dev);
+ scsi_changer *tmp, *ch;
+
+ spin_lock(&ch_devlist_lock);
+ ch = NULL;
+ list_for_each_entry(tmp,&ch_devlist,list) {
+ if (tmp->device == sd)
+ ch = tmp;
+ }
+ BUG_ON(NULL == ch);
+ list_del(&ch->list);
+ spin_unlock(&ch_devlist_lock);
+
+ class_device_destroy(ch_sysfs_class,
+ MKDEV(SCSI_CHANGER_MAJOR,ch->minor));
+ devfs_remove(ch->name);
+ kfree(ch->dt);
+ kfree(ch);
+ ch_devcount--;
+ return 0;
+}
+
+static int __init init_ch_module(void)
+{
+ int rc;
+
+ printk(KERN_INFO "SCSI Media Changer driver v" VERSION " \n");
+ ch_sysfs_class = class_create(THIS_MODULE, "scsi_changer");
+ if (IS_ERR(ch_sysfs_class)) {
+ rc = PTR_ERR(ch_sysfs_class);
+ return rc;
+ }
+ rc = register_chrdev(SCSI_CHANGER_MAJOR,"ch",&changer_fops);
+ if (rc < 0) {
+ printk("Unable to get major %d for SCSI-Changer\n",
+ SCSI_CHANGER_MAJOR);
+ goto fail1;
+ }
+ rc = scsi_register_driver(&ch_template.gendrv);
+ if (rc < 0)
+ goto fail2;
+ return 0;
+
+ fail2:
+ unregister_chrdev(SCSI_CHANGER_MAJOR, "ch");
+ fail1:
+ class_destroy(ch_sysfs_class);
+ return rc;
+}
+
+static void __exit exit_ch_module(void)
+{
+ scsi_unregister_driver(&ch_template.gendrv);
+ unregister_chrdev(SCSI_CHANGER_MAJOR, "ch");
+ class_destroy(ch_sysfs_class);
+}
+
+module_init(init_ch_module);
+module_exit(exit_ch_module);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index cca41cf8d3e..ae13c002f60 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -1310,7 +1310,7 @@ static void reset_dev_param(struct AdapterCtlBlk *acb)
* @cmd - some command for this host (for fetching hooks)
* Returns: SUCCESS (0x2002) on success, else FAILED (0x2003).
*/
-static int dc395x_eh_bus_reset(struct scsi_cmnd *cmd)
+static int __dc395x_eh_bus_reset(struct scsi_cmnd *cmd)
{
struct AdapterCtlBlk *acb =
(struct AdapterCtlBlk *)cmd->device->host->hostdata;
@@ -1356,6 +1356,16 @@ static int dc395x_eh_bus_reset(struct scsi_cmnd *cmd)
return SUCCESS;
}
+static int dc395x_eh_bus_reset(struct scsi_cmnd *cmd)
+{
+ int rc;
+
+ spin_lock_irq(cmd->device->host->host_lock);
+ rc = __dc395x_eh_bus_reset(cmd);
+ spin_unlock_irq(cmd->device->host->host_lock);
+
+ return rc;
+}
/*
* abort an errant SCSI command
diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c
index 1d2242403db..7905b904e01 100644
--- a/drivers/scsi/dmx3191d.c
+++ b/drivers/scsi/dmx3191d.c
@@ -61,8 +61,6 @@ static struct scsi_host_template dmx3191d_driver_template = {
.queuecommand = NCR5380_queue_command,
.eh_abort_handler = NCR5380_abort,
.eh_bus_reset_handler = NCR5380_bus_reset,
- .eh_device_reset_handler= NCR5380_device_reset,
- .eh_host_reset_handler = NCR5380_host_reset,
.can_queue = 32,
.this_id = 7,
.sg_tablesize = SG_ALL,
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 53c9b93013f..bbe346bd3cb 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -34,7 +34,6 @@
#define ADDR32 (0)
-#include <linux/version.h>
#include <linux/module.h>
MODULE_AUTHOR("Deanna Bonds, with _lots_ of help from Mark Salyzyn");
@@ -113,7 +112,6 @@ static struct i2o_sys_tbl *sys_tbl = NULL;
static int sys_tbl_ind = 0;
static int sys_tbl_len = 0;
-static adpt_hba* hbas[DPTI_MAX_HBA];
static adpt_hba* hba_chain = NULL;
static int hba_count = 0;
@@ -691,7 +689,7 @@ static int adpt_device_reset(struct scsi_cmnd* cmd)
u32 msg[4];
u32 rcode;
int old_state;
- struct adpt_device* d = (void*) cmd->device->hostdata;
+ struct adpt_device* d = cmd->device->hostdata;
pHba = (void*) cmd->device->host->hostdata[0];
printk(KERN_INFO"%s: Trying to reset device\n",pHba->name);
@@ -707,7 +705,7 @@ static int adpt_device_reset(struct scsi_cmnd* cmd)
old_state = d->state;
d->state |= DPTI_DEV_RESET;
- if( (rcode = adpt_i2o_post_wait(pHba, (void*)msg,sizeof(msg), FOREVER)) ){
+ if( (rcode = adpt_i2o_post_wait(pHba, msg,sizeof(msg), FOREVER)) ){
d->state = old_state;
if(rcode == -EOPNOTSUPP ){
printk(KERN_INFO"%s: Device reset not supported\n",pHba->name);
@@ -737,7 +735,7 @@ static int adpt_bus_reset(struct scsi_cmnd* cmd)
msg[1] = (I2O_HBA_BUS_RESET<<24|HOST_TID<<12|pHba->channel[cmd->device->channel].tid);
msg[2] = 0;
msg[3] = 0;
- if(adpt_i2o_post_wait(pHba, (void*)msg,sizeof(msg), FOREVER) ){
+ if(adpt_i2o_post_wait(pHba, msg,sizeof(msg), FOREVER) ){
printk(KERN_WARNING"%s: Bus reset failed.\n",pHba->name);
return FAILED;
} else {
@@ -747,7 +745,7 @@ static int adpt_bus_reset(struct scsi_cmnd* cmd)
}
// This version of reset is called by the eh_error_handler
-static int adpt_reset(struct scsi_cmnd* cmd)
+static int __adpt_reset(struct scsi_cmnd* cmd)
{
adpt_hba* pHba;
int rcode;
@@ -763,6 +761,17 @@ static int adpt_reset(struct scsi_cmnd* cmd)
}
}
+static int adpt_reset(struct scsi_cmnd* cmd)
+{
+ int rc;
+
+ spin_lock_irq(cmd->device->host->host_lock);
+ rc = __adpt_reset(cmd);
+ spin_unlock_irq(cmd->device->host->host_lock);
+
+ return rc;
+}
+
// This version of reset is called by the ioctls and indirectly from eh_error_handler via adpt_reset
static int adpt_hba_reset(adpt_hba* pHba)
{
@@ -875,7 +884,6 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
void __iomem *msg_addr_virt = NULL;
int raptorFlag = FALSE;
- int i;
if(pci_enable_device(pDev)) {
return -EINVAL;
@@ -935,12 +943,6 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
memset(pHba, 0, sizeof(adpt_hba));
down(&adpt_configuration_lock);
- for(i=0;i<DPTI_MAX_HBA;i++) {
- if(hbas[i]==NULL) {
- hbas[i]=pHba;
- break;
- }
- }
if(hba_chain != NULL){
for(p = hba_chain; p->next; p = p->next);
@@ -950,7 +952,7 @@ static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev
}
pHba->next = NULL;
pHba->unit = hba_count;
- sprintf(pHba->name, "dpti%d", i);
+ sprintf(pHba->name, "dpti%d", hba_count);
hba_count++;
up(&adpt_configuration_lock);
@@ -1015,11 +1017,6 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba)
if(pHba->host){
free_irq(pHba->host->irq, pHba);
}
- for(i=0;i<DPTI_MAX_HBA;i++) {
- if(hbas[i]==pHba) {
- hbas[i] = NULL;
- }
- }
p2 = NULL;
for( p1 = hba_chain; p1; p2 = p1,p1=p1->next){
if(p1 == pHba) {
@@ -1076,12 +1073,7 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba)
static int adpt_init(void)
{
- int i;
-
printk("Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n");
- for (i = 0; i < DPTI_MAX_HBA; i++) {
- hbas[i] = NULL;
- }
#ifdef REBOOT_NOTIFIER
register_reboot_notifier(&adpt_reboot_notifier);
#endif
@@ -1133,11 +1125,11 @@ static int adpt_i2o_post_wait(adpt_hba* pHba, u32* msg, int len, int timeout)
struct adpt_i2o_post_wait_data *p1, *p2;
struct adpt_i2o_post_wait_data *wait_data =
kmalloc(sizeof(struct adpt_i2o_post_wait_data),GFP_KERNEL);
- adpt_wait_queue_t wait;
+ DECLARE_WAITQUEUE(wait, current);
- if(!wait_data){
+ if (!wait_data)
return -ENOMEM;
- }
+
/*
* The spin locking is needed to keep anyone from playing
* with the queue pointers and id while we do the same
@@ -1155,12 +1147,7 @@ static int adpt_i2o_post_wait(adpt_hba* pHba, u32* msg, int len, int timeout)
wait_data->wq = &adpt_wq_i2o_post;
wait_data->status = -ETIMEDOUT;
- // this code is taken from kernel/sched.c:interruptible_sleep_on_timeout
- wait.task = current;
- init_waitqueue_entry(&wait, current);
- spin_lock_irqsave(&adpt_wq_i2o_post.lock, flags);
- __add_wait_queue(&adpt_wq_i2o_post, &wait);
- spin_unlock(&adpt_wq_i2o_post.lock);
+ add_wait_queue(&adpt_wq_i2o_post, &wait);
msg[2] |= 0x80000000 | ((u32)wait_data->id);
timeout *= HZ;
@@ -1182,9 +1169,7 @@ static int adpt_i2o_post_wait(adpt_hba* pHba, u32* msg, int len, int timeout)
if(pHba->host)
spin_lock_irq(pHba->host->host_lock);
}
- spin_lock_irq(&adpt_wq_i2o_post.lock);
- __remove_wait_queue(&adpt_wq_i2o_post, &wait);
- spin_unlock_irqrestore(&adpt_wq_i2o_post.lock, flags);
+ remove_wait_queue(&adpt_wq_i2o_post, &wait);
if(status == -ETIMEDOUT){
printk(KERN_INFO"dpti%d: POST WAIT TIMEOUT\n",pHba->unit);
@@ -1454,7 +1439,7 @@ static int adpt_i2o_parse_lct(adpt_hba* pHba)
return -ENOMEM;
}
- d->controller = (void*)pHba;
+ d->controller = pHba;
d->next = NULL;
memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry));
@@ -1825,9 +1810,9 @@ static int adpt_system_info(void __user *buffer)
memset(&si, 0, sizeof(si));
si.osType = OS_LINUX;
- si.osMajorVersion = (u8) (LINUX_VERSION_CODE >> 16);
- si.osMinorVersion = (u8) (LINUX_VERSION_CODE >> 8 & 0x0ff);
- si.osRevision = (u8) (LINUX_VERSION_CODE & 0x0ff);
+ si.osMajorVersion = 0;
+ si.osMinorVersion = 0;
+ si.osRevision = 0;
si.busType = SI_PCI_BUS;
si.processorFamily = DPTI_sig.dsProcessorFamily;
@@ -2000,7 +1985,7 @@ static irqreturn_t adpt_isr(int irq, void *dev_id, struct pt_regs *regs)
struct scsi_cmnd* cmd;
adpt_hba* pHba = dev_id;
u32 m;
- ulong reply;
+ void __iomem *reply;
u32 status=0;
u32 context;
ulong flags = 0;
@@ -2025,11 +2010,11 @@ static irqreturn_t adpt_isr(int irq, void *dev_id, struct pt_regs *regs)
goto out;
}
}
- reply = (ulong)bus_to_virt(m);
+ reply = bus_to_virt(m);
if (readl(reply) & MSG_FAIL) {
u32 old_m = readl(reply+28);
- ulong msg;
+ void __iomem *msg;
u32 old_context;
PDEBUG("%s: Failed message\n",pHba->name);
if(old_m >= 0x100000){
@@ -2038,16 +2023,16 @@ static irqreturn_t adpt_isr(int irq, void *dev_id, struct pt_regs *regs)
continue;
}
// Transaction context is 0 in failed reply frame
- msg = (ulong)(pHba->msg_addr_virt + old_m);
+ msg = pHba->msg_addr_virt + old_m;
old_context = readl(msg+12);
writel(old_context, reply+12);
adpt_send_nop(pHba, old_m);
}
context = readl(reply+8);
if(context & 0x40000000){ // IOCTL
- ulong p = (ulong)(readl(reply+12));
- if( p != 0) {
- memcpy((void*)p, (void*)reply, REPLY_FRAME_SIZE * 4);
+ void *p = (void *)readl(reply+12);
+ if( p != NULL) {
+ memcpy_fromio(p, reply, REPLY_FRAME_SIZE * 4);
}
// All IOCTLs will also be post wait
}
@@ -2231,7 +2216,7 @@ static s32 adpt_scsi_register(adpt_hba* pHba,struct scsi_host_template * sht)
}
-static s32 adpt_i2o_to_scsi(ulong reply, struct scsi_cmnd* cmd)
+static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd)
{
adpt_hba* pHba;
u32 hba_status;
@@ -2323,7 +2308,7 @@ static s32 adpt_i2o_to_scsi(ulong reply, struct scsi_cmnd* cmd)
u32 len = sizeof(cmd->sense_buffer);
len = (len > 40) ? 40 : len;
// Copy over the sense data
- memcpy(cmd->sense_buffer, (void*)(reply+28) , len);
+ memcpy_fromio(cmd->sense_buffer, (reply+28) , len);
if(cmd->sense_buffer[0] == 0x70 /* class 7 */ &&
cmd->sense_buffer[2] == DATA_PROTECT ){
/* This is to handle an array failed */
@@ -2438,7 +2423,7 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba)
return -ENOMEM;
}
- d->controller = (void*)pHba;
+ d->controller = pHba;
d->next = NULL;
memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry));
@@ -2985,8 +2970,8 @@ static int adpt_i2o_build_sys_table(void)
sys_tbl->iops[count].frame_size = pHba->status_block->inbound_frame_size;
sys_tbl->iops[count].last_changed = sys_tbl_ind - 1; // ??
sys_tbl->iops[count].iop_capabilities = pHba->status_block->iop_capabilities;
- sys_tbl->iops[count].inbound_low = (u32)virt_to_bus((void*)pHba->post_port);
- sys_tbl->iops[count].inbound_high = (u32)((u64)virt_to_bus((void*)pHba->post_port)>>32);
+ sys_tbl->iops[count].inbound_low = (u32)virt_to_bus(pHba->post_port);
+ sys_tbl->iops[count].inbound_high = (u32)((u64)virt_to_bus(pHba->post_port)>>32);
count++;
}
diff --git a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h
index 426e15dd490..489194af43d 100644
--- a/drivers/scsi/dpti.h
+++ b/drivers/scsi/dpti.h
@@ -20,15 +20,7 @@
#ifndef _DPT_H
#define _DPT_H
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h>
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,00)
-#define MAX_TO_IOP_MESSAGES (210)
-#else
#define MAX_TO_IOP_MESSAGES (255)
-#endif
#define MAX_FROM_IOP_MESSAGES (255)
@@ -296,7 +288,7 @@ static s32 adpt_i2o_status_get(adpt_hba* pHba);
static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba);
static s32 adpt_i2o_hrt_get(adpt_hba* pHba);
static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_device* dptdevice);
-static s32 adpt_i2o_to_scsi(ulong reply, struct scsi_cmnd* cmd);
+static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd);
static s32 adpt_scsi_register(adpt_hba* pHba,struct scsi_host_template * sht);
static s32 adpt_hba_reset(adpt_hba* pHba);
static s32 adpt_i2o_reset_hba(adpt_hba* pHba);
@@ -321,10 +313,6 @@ static int adpt_close(struct inode *inode, struct file *file);
static void adpt_delay(int millisec);
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
-static struct pci_dev* adpt_pci_find_device(uint vendor, struct pci_dev* from);
-#endif
-
#if defined __ia64__
static void adpt_ia64_info(sysInfo_S* si);
#endif
diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c
index da1aaa413fe..ab9de39bb50 100644
--- a/drivers/scsi/dtc.c
+++ b/drivers/scsi/dtc.c
@@ -482,8 +482,6 @@ static Scsi_Host_Template driver_template = {
.queuecommand = dtc_queue_command,
.eh_abort_handler = dtc_abort,
.eh_bus_reset_handler = dtc_bus_reset,
- .eh_device_reset_handler = dtc_device_reset,
- .eh_host_reset_handler = dtc_host_reset,
.bios_param = dtc_biosparam,
.can_queue = CAN_QUEUE,
.this_id = 7,
diff --git a/drivers/scsi/dtc.h b/drivers/scsi/dtc.h
index c4bcdbf338a..ed73629eb2f 100644
--- a/drivers/scsi/dtc.h
+++ b/drivers/scsi/dtc.h
@@ -34,8 +34,6 @@ static int dtc_biosparam(struct scsi_device *, struct block_device *,
static int dtc_detect(Scsi_Host_Template *);
static int dtc_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
static int dtc_bus_reset(Scsi_Cmnd *);
-static int dtc_device_reset(Scsi_Cmnd *);
-static int dtc_host_reset(Scsi_Cmnd *);
#ifndef CMD_PER_LUN
#define CMD_PER_LUN 2
@@ -86,8 +84,6 @@ static int dtc_host_reset(Scsi_Cmnd *);
#define NCR5380_queue_command dtc_queue_command
#define NCR5380_abort dtc_abort
#define NCR5380_bus_reset dtc_bus_reset
-#define NCR5380_device_reset dtc_device_reset
-#define NCR5380_host_reset dtc_host_reset
#define NCR5380_proc_info dtc_proc_info
/* 15 12 11 10
diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c
index 81d16cfbe69..1bb8727eea3 100644
--- a/drivers/scsi/eata.c
+++ b/drivers/scsi/eata.c
@@ -518,8 +518,6 @@ static struct scsi_host_template driver_template = {
.release = eata2x_release,
.queuecommand = eata2x_queuecommand,
.eh_abort_handler = eata2x_eh_abort,
- .eh_device_reset_handler = NULL,
- .eh_bus_reset_handler = NULL,
.eh_host_reset_handler = eata2x_eh_host_reset,
.bios_param = eata2x_bios_param,
.slave_configure = eata2x_slave_configure,
@@ -1950,16 +1948,20 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg)
ha->board_name, SCarg->device->channel, SCarg->device->id,
SCarg->device->lun, SCarg->pid);
+ spin_lock_irq(shost->host_lock);
+
if (SCarg->host_scribble == NULL)
printk("%s: reset, pid %ld inactive.\n", ha->board_name, SCarg->pid);
if (ha->in_reset) {
printk("%s: reset, exit, already in reset.\n", ha->board_name);
+ spin_unlock_irq(shost->host_lock);
return FAILED;
}
if (wait_on_busy(shost->io_port, MAXLOOP)) {
printk("%s: reset, exit, timeout error.\n", ha->board_name);
+ spin_unlock_irq(shost->host_lock);
return FAILED;
}
@@ -2014,6 +2016,7 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg)
if (do_dma(shost->io_port, 0, RESET_PIO)) {
printk("%s: reset, cannot reset, timeout error.\n", ha->board_name);
+ spin_unlock_irq(shost->host_lock);
return FAILED;
}
@@ -2026,9 +2029,12 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg)
ha->in_reset = 1;
spin_unlock_irq(shost->host_lock);
+
+ /* FIXME: use a sleep instead */
time = jiffies;
while ((jiffies - time) < (10 * HZ) && limit++ < 200000)
udelay(100L);
+
spin_lock_irq(shost->host_lock);
printk("%s: reset, interrupts disabled, loops %d.\n", ha->board_name, limit);
@@ -2078,6 +2084,7 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg)
else
printk("%s: reset, exit.\n", ha->board_name);
+ spin_unlock_irq(shost->host_lock);
return SUCCESS;
}
diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c
index 0ee49dc50b8..04a06b71a5e 100644
--- a/drivers/scsi/eata_pio.c
+++ b/drivers/scsi/eata_pio.c
@@ -486,8 +486,11 @@ static int eata_pio_host_reset(struct scsi_cmnd *cmd)
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset called pid:%ld target:" " %x lun: %x reason %x\n", cmd->pid, cmd->device->id, cmd->device->lun, cmd->abort_reason));
+ spin_lock_irq(host->host_lock);
+
if (HD(cmd)->state == RESET) {
printk(KERN_WARNING "eata_pio_reset: exit, already in reset.\n");
+ spin_unlock_irq(host->host_lock);
return FAILED;
}
@@ -536,6 +539,8 @@ static int eata_pio_host_reset(struct scsi_cmnd *cmd)
HD(cmd)->state = 0;
+ spin_unlock_irq(host->host_lock);
+
if (success) { /* hmmm... */
DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: exit, success.\n"));
return SUCCESS;
diff --git a/drivers/scsi/fcal.c b/drivers/scsi/fcal.c
index 0dad89d4cb3..a6f120dcdfc 100644
--- a/drivers/scsi/fcal.c
+++ b/drivers/scsi/fcal.c
@@ -311,7 +311,6 @@ static Scsi_Host_Template driver_template = {
.use_clustering = ENABLE_CLUSTERING,
.eh_abort_handler = fcp_scsi_abort,
.eh_device_reset_handler = fcp_scsi_dev_reset,
- .eh_bus_reset_handler = fcp_scsi_bus_reset,
.eh_host_reset_handler = fcp_scsi_host_reset,
};
#include "scsi_module.c"
diff --git a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c
index 770930e2aec..fa652f8aa64 100644
--- a/drivers/scsi/fd_mcs.c
+++ b/drivers/scsi/fd_mcs.c
@@ -1241,18 +1241,9 @@ static int fd_mcs_abort(Scsi_Cmnd * SCpnt)
return SUCCESS;
}
-static int fd_mcs_host_reset(Scsi_Cmnd * SCpnt)
-{
- return FAILED;
-}
-
-static int fd_mcs_device_reset(Scsi_Cmnd * SCpnt)
-{
- return FAILED;
-}
-
static int fd_mcs_bus_reset(Scsi_Cmnd * SCpnt) {
struct Scsi_Host *shpnt = SCpnt->device->host;
+ unsigned long flags;
#if DEBUG_RESET
static int called_once = 0;
@@ -1269,6 +1260,8 @@ static int fd_mcs_bus_reset(Scsi_Cmnd * SCpnt) {
called_once = 1;
#endif
+ spin_lock_irqsave(shpnt->host_lock, flags);
+
outb(1, SCSI_Cntl_port);
do_pause(2);
outb(0, SCSI_Cntl_port);
@@ -1276,6 +1269,8 @@ static int fd_mcs_bus_reset(Scsi_Cmnd * SCpnt) {
outb(0, SCSI_Mode_Cntl_port);
outb(PARITY_MASK, TMC_Cntl_port);
+ spin_unlock_irqrestore(shpnt->host_lock, flags);
+
/* Unless this is the very first call (i.e., SCPnt == NULL), everything
is probably hosed at this point. We will, however, try to keep
things going by informing the high-level code that we need help. */
@@ -1357,8 +1352,6 @@ static Scsi_Host_Template driver_template = {
.queuecommand = fd_mcs_queue,
.eh_abort_handler = fd_mcs_abort,
.eh_bus_reset_handler = fd_mcs_bus_reset,
- .eh_host_reset_handler = fd_mcs_host_reset,
- .eh_device_reset_handler = fd_mcs_device_reset,
.bios_param = fd_mcs_biosparam,
.can_queue = 1,
.this_id = 7,
diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c
index a843c080c1d..4ba6a15cf43 100644
--- a/drivers/scsi/fdomain.c
+++ b/drivers/scsi/fdomain.c
@@ -1543,12 +1543,18 @@ static int fdomain_16x0_abort(struct scsi_cmnd *SCpnt)
int fdomain_16x0_bus_reset(struct scsi_cmnd *SCpnt)
{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
outb(1, port_base + SCSI_Cntl);
do_pause( 2 );
outb(0, port_base + SCSI_Cntl);
do_pause( 115 );
outb(0, port_base + SCSI_Mode_Cntl);
outb(PARITY_MASK, port_base + TMC_Cntl);
+
+ local_irq_restore(flags);
return SUCCESS;
}
diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index ca9d5bd26ca..a3aa729b9d3 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -908,8 +908,6 @@ static Scsi_Host_Template driver_template = {
.queuecommand = generic_NCR5380_queue_command,
.eh_abort_handler = generic_NCR5380_abort,
.eh_bus_reset_handler = generic_NCR5380_bus_reset,
- .eh_device_reset_handler = generic_NCR5380_device_reset,
- .eh_host_reset_handler = generic_NCR5380_host_reset,
.bios_param = NCR5380_BIOSPARAM,
.can_queue = CAN_QUEUE,
.this_id = 7,
diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h
index 0c04cefb2a8..c8adc5a9488 100644
--- a/drivers/scsi/g_NCR5380.h
+++ b/drivers/scsi/g_NCR5380.h
@@ -49,8 +49,6 @@ static int generic_NCR5380_detect(Scsi_Host_Template *);
static int generic_NCR5380_release_resources(struct Scsi_Host *);
static int generic_NCR5380_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
static int generic_NCR5380_bus_reset(Scsi_Cmnd *);
-static int generic_NCR5380_host_reset(Scsi_Cmnd *);
-static int generic_NCR5380_device_reset(Scsi_Cmnd *);
static const char* generic_NCR5380_info(struct Scsi_Host *);
#ifndef CMD_PER_LUN
@@ -114,8 +112,6 @@ static const char* generic_NCR5380_info(struct Scsi_Host *);
#define NCR5380_queue_command generic_NCR5380_queue_command
#define NCR5380_abort generic_NCR5380_abort
#define NCR5380_bus_reset generic_NCR5380_bus_reset
-#define NCR5380_device_reset generic_NCR5380_device_reset
-#define NCR5380_host_reset generic_NCR5380_host_reset
#define NCR5380_pread generic_NCR5380_pread
#define NCR5380_pwrite generic_NCR5380_pwrite
#define NCR5380_proc_info notyet_generic_proc_info
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index a9eaab9fbd5..4552cccd283 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -4703,19 +4703,6 @@ static const char *gdth_info(struct Scsi_Host *shp)
return ((const char *)ha->binfo.type_string);
}
-/* new error handling */
-static int gdth_eh_abort(Scsi_Cmnd *scp)
-{
- TRACE2(("gdth_eh_abort()\n"));
- return FAILED;
-}
-
-static int gdth_eh_device_reset(Scsi_Cmnd *scp)
-{
- TRACE2(("gdth_eh_device_reset()\n"));
- return FAILED;
-}
-
static int gdth_eh_bus_reset(Scsi_Cmnd *scp)
{
int i, hanum;
@@ -4770,13 +4757,6 @@ static int gdth_eh_bus_reset(Scsi_Cmnd *scp)
return SUCCESS;
}
-static int gdth_eh_host_reset(Scsi_Cmnd *scp)
-{
- TRACE2(("gdth_eh_host_reset()\n"));
- return FAILED;
-}
-
-
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
static int gdth_bios_param(struct scsi_device *sdev,struct block_device *bdev,sector_t cap,int *ip)
#else
@@ -5713,10 +5693,7 @@ static Scsi_Host_Template driver_template = {
.release = gdth_release,
.info = gdth_info,
.queuecommand = gdth_queuecommand,
- .eh_abort_handler = gdth_eh_abort,
- .eh_device_reset_handler = gdth_eh_device_reset,
.eh_bus_reset_handler = gdth_eh_bus_reset,
- .eh_host_reset_handler = gdth_eh_host_reset,
.bios_param = gdth_bios_param,
.can_queue = GDTH_MAXCMDS,
.this_id = -1,
diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c
index 30cbf73c743..d12342fa819 100644
--- a/drivers/scsi/gvp11.c
+++ b/drivers/scsi/gvp11.c
@@ -345,7 +345,15 @@ release:
static int gvp11_bus_reset(Scsi_Cmnd *cmd)
{
/* FIXME perform bus-specific reset */
+
+ /* FIXME 2: shouldn't we no-op this function (return
+ FAILED), and fall back to host reset function,
+ wd33c93_host_reset ? */
+
+ spin_lock_irq(cmd->device->host->host_lock);
wd33c93_host_reset(cmd);
+ spin_unlock_irq(cmd->device->host->host_lock);
+
return SUCCESS;
}
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index ba347576d99..d7a38b6713f 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -56,7 +56,7 @@ static struct class shost_class = {
* @shost: pointer to struct Scsi_Host
* recovery: recovery requested to run.
**/
-void scsi_host_cancel(struct Scsi_Host *shost, int recovery)
+static void scsi_host_cancel(struct Scsi_Host *shost, int recovery)
{
struct scsi_device *sdev;
diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c
index a3fdead9bce..b5dc3535557 100644
--- a/drivers/scsi/ibmmca.c
+++ b/drivers/scsi/ibmmca.c
@@ -2118,7 +2118,7 @@ static int ibmmca_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
return 0;
}
-static int ibmmca_abort(Scsi_Cmnd * cmd)
+static int __ibmmca_abort(Scsi_Cmnd * cmd)
{
/* Abort does not work, as the adapter never generates an interrupt on
* whatever situation is simulated, even when really pending commands
@@ -2225,7 +2225,19 @@ static int ibmmca_abort(Scsi_Cmnd * cmd)
}
}
-static int ibmmca_host_reset(Scsi_Cmnd * cmd)
+static int ibmmca_abort(Scsi_Cmnd * cmd)
+{
+ struct Scsi_Host *shpnt = cmd->device->host;
+ int rc;
+
+ spin_lock_irq(shpnt->host_lock);
+ rc = __ibmmca_abort(cmd);
+ spin_unlock_irq(shpnt->host_lock);
+
+ return rc;
+}
+
+static int __ibmmca_host_reset(Scsi_Cmnd * cmd)
{
struct Scsi_Host *shpnt;
Scsi_Cmnd *cmd_aid;
@@ -2312,6 +2324,18 @@ static int ibmmca_host_reset(Scsi_Cmnd * cmd)
return SUCCESS;
}
+static int ibmmca_host_reset(Scsi_Cmnd * cmd)
+{
+ struct Scsi_Host *shpnt = cmd->device->host;
+ int rc;
+
+ spin_lock_irq(shpnt->host_lock);
+ rc = __ibmmca_host_reset(cmd);
+ spin_unlock_irq(shpnt->host_lock);
+
+ return rc;
+}
+
static int ibmmca_biosparam(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int *info)
{
int size = capacity;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index e89f76e5dd5..d89b8eb3cdf 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -874,9 +874,7 @@ static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
return FAILED;
}
- spin_unlock_irq(hostdata->host->host_lock);
wait_for_completion(&evt->comp);
- spin_lock_irq(hostdata->host->host_lock);
/* make sure we got a good response */
if (unlikely(srp_rsp.srp.generic.type != SRP_RSP_TYPE)) {
@@ -978,9 +976,7 @@ static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
return FAILED;
}
- spin_unlock_irq(hostdata->host->host_lock);
wait_for_completion(&evt->comp);
- spin_lock_irq(hostdata->host->host_lock);
/* make sure we got a good response */
if (unlikely(srp_rsp.srp.generic.type != SRP_RSP_TYPE)) {
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 2e2486b035d..3d62c9bcbff 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -46,6 +46,7 @@
#include <linux/slab.h>
#include <linux/ide.h>
#include <linux/scatterlist.h>
+#include <linux/delay.h>
#include <asm/io.h>
#include <asm/bitops.h>
@@ -179,8 +180,18 @@ static void idescsi_input_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigne
return;
}
count = min(pc->sg->length - pc->b_count, bcount);
- buf = page_address(pc->sg->page) + pc->sg->offset;
- drive->hwif->atapi_input_bytes(drive, buf + pc->b_count, count);
+ if (PageHighMem(pc->sg->page)) {
+ unsigned long flags;
+
+ local_irq_save(flags);
+ buf = kmap_atomic(pc->sg->page, KM_IRQ0) + pc->sg->offset;
+ drive->hwif->atapi_input_bytes(drive, buf + pc->b_count, count);
+ kunmap_atomic(buf - pc->sg->offset, KM_IRQ0);
+ local_irq_restore(flags);
+ } else {
+ buf = page_address(pc->sg->page) + pc->sg->offset;
+ drive->hwif->atapi_input_bytes(drive, buf + pc->b_count, count);
+ }
bcount -= count; pc->b_count += count;
if (pc->b_count == pc->sg->length) {
pc->sg++;
@@ -201,8 +212,18 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign
return;
}
count = min(pc->sg->length - pc->b_count, bcount);
- buf = page_address(pc->sg->page) + pc->sg->offset;
- drive->hwif->atapi_output_bytes(drive, buf + pc->b_count, count);
+ if (PageHighMem(pc->sg->page)) {
+ unsigned long flags;
+
+ local_irq_save(flags);
+ buf = kmap_atomic(pc->sg->page, KM_IRQ0) + pc->sg->offset;
+ drive->hwif->atapi_output_bytes(drive, buf + pc->b_count, count);
+ kunmap_atomic(buf - pc->sg->offset, KM_IRQ0);
+ local_irq_restore(flags);
+ } else {
+ buf = page_address(pc->sg->page) + pc->sg->offset;
+ drive->hwif->atapi_output_bytes(drive, buf + pc->b_count, count);
+ }
bcount -= count; pc->b_count += count;
if (pc->b_count == pc->sg->length) {
pc->sg++;
@@ -713,7 +734,6 @@ static void idescsi_add_settings(ide_drive_t *drive)
*/
static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi)
{
- DRIVER(drive)->busy++;
if (drive->id && (drive->id->config & 0x0060) == 0x20)
set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags);
set_bit(IDESCSI_TRANSFORM, &scsi->transform);
@@ -722,17 +742,16 @@ static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi)
set_bit(IDESCSI_LOG_CMD, &scsi->log);
#endif /* IDESCSI_DEBUG_LOG */
idescsi_add_settings(drive);
- DRIVER(drive)->busy--;
}
-static int idescsi_cleanup (ide_drive_t *drive)
+static int ide_scsi_remove(struct device *dev)
{
+ ide_drive_t *drive = to_ide_device(dev);
struct Scsi_Host *scsihost = drive->driver_data;
struct ide_scsi_obj *scsi = scsihost_to_idescsi(scsihost);
struct gendisk *g = scsi->disk;
- if (ide_unregister_subdriver(drive))
- return 1;
+ ide_unregister_subdriver(drive, scsi->driver);
ide_unregister_region(g);
@@ -746,7 +765,7 @@ static int idescsi_cleanup (ide_drive_t *drive)
return 0;
}
-static int idescsi_attach(ide_drive_t *drive);
+static int ide_scsi_probe(struct device *);
#ifdef CONFIG_PROC_FS
static ide_proc_entry_t idescsi_proc[] = {
@@ -757,24 +776,22 @@ static ide_proc_entry_t idescsi_proc[] = {
# define idescsi_proc NULL
#endif
-/*
- * IDE subdriver functions, registered with ide.c
- */
static ide_driver_t idescsi_driver = {
.owner = THIS_MODULE,
- .name = "ide-scsi",
+ .gen_driver = {
+ .name = "ide-scsi",
+ .bus = &ide_bus_type,
+ .probe = ide_scsi_probe,
+ .remove = ide_scsi_remove,
+ },
.version = IDESCSI_VERSION,
.media = ide_scsi,
- .busy = 0,
.supports_dsc_overlap = 0,
.proc = idescsi_proc,
- .attach = idescsi_attach,
- .cleanup = idescsi_cleanup,
.do_request = idescsi_do_request,
.end_request = idescsi_end_request,
.error = idescsi_atapi_error,
.abort = idescsi_atapi_abort,
- .drives = LIST_HEAD_INIT(idescsi_driver.drives),
};
static int idescsi_ide_open(struct inode *inode, struct file *filp)
@@ -821,8 +838,6 @@ static struct block_device_operations idescsi_ops = {
.ioctl = idescsi_ide_ioctl,
};
-static int idescsi_attach(ide_drive_t *drive);
-
static int idescsi_slave_configure(struct scsi_device * sdp)
{
/* Configure detected device */
@@ -1012,11 +1027,13 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
return FAILED;
}
- spin_lock_irq(&ide_lock);
+ spin_lock_irq(cmd->device->host->host_lock);
+ spin_lock(&ide_lock);
if (!scsi->pc || (req = scsi->pc->rq) != HWGROUP(drive)->rq || !HWGROUP(drive)->handler) {
printk (KERN_WARNING "ide-scsi: No active request in idescsi_eh_reset\n");
spin_unlock(&ide_lock);
+ spin_unlock_irq(cmd->device->host->host_lock);
return FAILED;
}
@@ -1038,16 +1055,15 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
HWGROUP(drive)->rq = NULL;
HWGROUP(drive)->handler = NULL;
HWGROUP(drive)->busy = 1; /* will set this to zero when ide reset finished */
- spin_unlock_irq(&ide_lock);
+ spin_unlock(&ide_lock);
ide_do_reset(drive);
/* ide_do_reset starts a polling handler which restarts itself every 50ms until the reset finishes */
do {
- set_current_state(TASK_UNINTERRUPTIBLE);
spin_unlock_irq(cmd->device->host->host_lock);
- schedule_timeout(HZ/20);
+ msleep(50);
spin_lock_irq(cmd->device->host->host_lock);
} while ( HWGROUP(drive)->handler );
@@ -1058,6 +1074,7 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
ret = FAILED;
}
+ spin_unlock_irq(cmd->device->host->host_lock);
return ret;
}
@@ -1095,8 +1112,9 @@ static struct scsi_host_template idescsi_template = {
.proc_name = "ide-scsi",
};
-static int idescsi_attach(ide_drive_t *drive)
+static int ide_scsi_probe(struct device *dev)
{
+ ide_drive_t *drive = to_ide_device(dev);
idescsi_scsi_t *idescsi;
struct Scsi_Host *host;
struct gendisk *g;
@@ -1112,7 +1130,7 @@ static int idescsi_attach(ide_drive_t *drive)
!drive->present ||
drive->media == ide_disk ||
!(host = scsi_host_alloc(&idescsi_template,sizeof(idescsi_scsi_t))))
- return 1;
+ return -ENODEV;
g = alloc_disk(1 << PARTN_BITS);
if (!g)
@@ -1138,20 +1156,19 @@ static int idescsi_attach(ide_drive_t *drive)
idescsi->host = host;
idescsi->disk = g;
g->private_data = &idescsi->driver;
- err = ide_register_subdriver(drive, &idescsi_driver);
+ ide_register_subdriver(drive, &idescsi_driver);
+ err = 0;
+ idescsi_setup(drive, idescsi);
+ g->fops = &idescsi_ops;
+ ide_register_region(g);
+ err = scsi_add_host(host, &drive->gendev);
if (!err) {
- idescsi_setup (drive, idescsi);
- g->fops = &idescsi_ops;
- ide_register_region(g);
- err = scsi_add_host(host, &drive->gendev);
- if (!err) {
- scsi_scan_host(host);
- return 0;
- }
- /* fall through on error */
- ide_unregister_region(g);
- ide_unregister_subdriver(drive);
+ scsi_scan_host(host);
+ return 0;
}
+ /* fall through on error */
+ ide_unregister_region(g);
+ ide_unregister_subdriver(drive, &idescsi_driver);
put_disk(g);
out_host_put:
@@ -1161,12 +1178,12 @@ out_host_put:
static int __init init_idescsi_module(void)
{
- return ide_register_driver(&idescsi_driver);
+ return driver_register(&idescsi_driver.gen_driver);
}
static void __exit exit_idescsi_module(void)
{
- ide_unregister_driver(&idescsi_driver);
+ driver_unregister(&idescsi_driver.gen_driver);
}
module_init(init_idescsi_module);
diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c
index be7f2ca0183..65e845665b8 100644
--- a/drivers/scsi/imm.c
+++ b/drivers/scsi/imm.c
@@ -18,6 +18,7 @@
#include <linux/blkdev.h>
#include <linux/parport.h>
#include <linux/workqueue.h>
+#include <linux/delay.h>
#include <asm/io.h>
#include <scsi/scsi.h>
@@ -610,9 +611,9 @@ static int imm_init(imm_struct *dev)
if (imm_connect(dev, 0) != 1)
return -EIO;
imm_reset_pulse(dev->base);
- udelay(1000); /* Delay to allow devices to settle */
+ mdelay(1); /* Delay to allow devices to settle */
imm_disconnect(dev);
- udelay(1000); /* Another delay to allow devices to settle */
+ mdelay(1); /* Another delay to allow devices to settle */
return device_check(dev);
}
@@ -1026,9 +1027,9 @@ static int imm_reset(struct scsi_cmnd *cmd)
imm_connect(dev, CONNECT_NORMAL);
imm_reset_pulse(dev->base);
- udelay(1000); /* device settle delay */
+ mdelay(1); /* device settle delay */
imm_disconnect(dev);
- udelay(1000); /* device settle delay */
+ mdelay(1); /* device settle delay */
return SUCCESS;
}
diff --git a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c
index 0bb0369efb2..aed7e64865f 100644
--- a/drivers/scsi/in2000.c
+++ b/drivers/scsi/in2000.c
@@ -1644,14 +1644,16 @@ static int in2000_bus_reset(Scsi_Cmnd * cmd)
struct Scsi_Host *instance;
struct IN2000_hostdata *hostdata;
int x;
+ unsigned long flags;
instance = cmd->device->host;
hostdata = (struct IN2000_hostdata *) instance->hostdata;
printk(KERN_WARNING "scsi%d: Reset. ", instance->host_no);
- /* do scsi-reset here */
+ spin_lock_irqsave(instance->host_lock, flags);
+ /* do scsi-reset here */
reset_hardware(instance, RESET_CARD_AND_BUS);
for (x = 0; x < 8; x++) {
hostdata->busy[x] = 0;
@@ -1668,21 +1670,12 @@ static int in2000_bus_reset(Scsi_Cmnd * cmd)
hostdata->outgoing_len = 0;
cmd->result = DID_RESET << 16;
- return SUCCESS;
-}
-static int in2000_host_reset(Scsi_Cmnd * cmd)
-{
- return FAILED;
-}
-
-static int in2000_device_reset(Scsi_Cmnd * cmd)
-{
- return FAILED;
+ spin_unlock_irqrestore(instance->host_lock, flags);
+ return SUCCESS;
}
-
-static int in2000_abort(Scsi_Cmnd * cmd)
+static int __in2000_abort(Scsi_Cmnd * cmd)
{
struct Scsi_Host *instance;
struct IN2000_hostdata *hostdata;
@@ -1803,6 +1796,16 @@ static int in2000_abort(Scsi_Cmnd * cmd)
return SUCCESS;
}
+static int in2000_abort(Scsi_Cmnd * cmd)
+{
+ int rc;
+
+ spin_lock_irq(cmd->device->host->host_lock);
+ rc = __in2000_abort(cmd);
+ spin_unlock_irq(cmd->device->host->host_lock);
+
+ return rc;
+}
#define MAX_IN2000_HOSTS 3
@@ -2311,8 +2314,6 @@ static Scsi_Host_Template driver_template = {
.queuecommand = in2000_queuecommand,
.eh_abort_handler = in2000_abort,
.eh_bus_reset_handler = in2000_bus_reset,
- .eh_device_reset_handler = in2000_device_reset,
- .eh_host_reset_handler = in2000_host_reset,
.bios_param = in2000_biosparam,
.can_queue = IN2000_CAN_Q,
.this_id = IN2000_HOST_ID,
diff --git a/drivers/scsi/in2000.h b/drivers/scsi/in2000.h
index 019e45df301..a240b52554d 100644
--- a/drivers/scsi/in2000.h
+++ b/drivers/scsi/in2000.h
@@ -401,9 +401,7 @@ static int in2000_abort(Scsi_Cmnd *);
static void in2000_setup(char *, int *) in2000__INIT;
static int in2000_biosparam(struct scsi_device *, struct block_device *,
sector_t, int *);
-static int in2000_host_reset(Scsi_Cmnd *);
static int in2000_bus_reset(Scsi_Cmnd *);
-static int in2000_device_reset(Scsi_Cmnd *);
#define IN2000_CAN_Q 16
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index a7b74d8c53b..2094d4811d6 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -223,7 +223,7 @@ static void tul_select_atn(HCS * pCurHcb, SCB * pCurScb);
static void tul_select_atn3(HCS * pCurHcb, SCB * pCurScb);
static void tul_select_atn_stop(HCS * pCurHcb, SCB * pCurScb);
static int int_tul_busfree(HCS * pCurHcb);
-int int_tul_scsi_rst(HCS * pCurHcb);
+static int int_tul_scsi_rst(HCS * pCurHcb);
static int int_tul_bad_seq(HCS * pCurHcb);
static int int_tul_resel(HCS * pCurHcb);
static int tul_sync_done(HCS * pCurHcb);
@@ -240,9 +240,8 @@ static int tul_se2_rd_all(WORD CurBase);
static void tul_se2_update_all(WORD CurBase); /* setup default pattern */
static void tul_read_eeprom(WORD CurBase);
- /* ---- EXTERNAL VARIABLES ---- */
-HCS tul_hcs[MAX_SUPPORTED_ADAPTERS];
/* ---- INTERNAL VARIABLES ---- */
+static HCS tul_hcs[MAX_SUPPORTED_ADAPTERS];
static INI_ADPT_STRUCT i91u_adpt[MAX_SUPPORTED_ADAPTERS];
/*NVRAM nvram, *nvramp = &nvram; */
@@ -381,7 +380,7 @@ void tul_se2_wait(void)
******************************************************************/
-void tul_se2_instr(WORD CurBase, UCHAR instr)
+static void tul_se2_instr(WORD CurBase, UCHAR instr)
{
int i;
UCHAR b;
@@ -437,7 +436,7 @@ void tul_se2_ew_ds(WORD CurBase)
Input :address of Serial E2PROM
Output :value stored in Serial E2PROM
*******************************************************************/
-USHORT tul_se2_rd(WORD CurBase, ULONG adr)
+static USHORT tul_se2_rd(WORD CurBase, ULONG adr)
{
UCHAR instr, readByte;
USHORT readWord;
@@ -468,7 +467,7 @@ USHORT tul_se2_rd(WORD CurBase, ULONG adr)
/******************************************************************
Input: new value in Serial E2PROM, address of Serial E2PROM
*******************************************************************/
-void tul_se2_wr(WORD CurBase, UCHAR adr, USHORT writeWord)
+static void tul_se2_wr(WORD CurBase, UCHAR adr, USHORT writeWord)
{
UCHAR readByte;
UCHAR instr;
@@ -584,8 +583,8 @@ void tul_read_eeprom(WORD CurBase)
TUL_WR(CurBase + TUL_GCTRL, gctrl & ~TUL_GCTRL_EEPROM_BIT);
} /* read_eeprom */
-int Addi91u_into_Adapter_table(WORD wBIOS, WORD wBASE, BYTE bInterrupt,
- BYTE bBus, BYTE bDevice)
+static int Addi91u_into_Adapter_table(WORD wBIOS, WORD wBASE, BYTE bInterrupt,
+ BYTE bBus, BYTE bDevice)
{
int i, j;
@@ -616,7 +615,7 @@ int Addi91u_into_Adapter_table(WORD wBIOS, WORD wBASE, BYTE bInterrupt,
return 1;
}
-void init_i91uAdapter_table(void)
+static void init_i91uAdapter_table(void)
{
int i;
@@ -630,7 +629,7 @@ void init_i91uAdapter_table(void)
return;
}
-void tul_stop_bm(HCS * pCurHcb)
+static void tul_stop_bm(HCS * pCurHcb)
{
if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) { /* if DMA xfer is pending, abort DMA xfer */
@@ -642,7 +641,7 @@ void tul_stop_bm(HCS * pCurHcb)
}
/***************************************************************************/
-void get_tulipPCIConfig(HCS * pCurHcb, int ch_idx)
+static void get_tulipPCIConfig(HCS * pCurHcb, int ch_idx)
{
pCurHcb->HCS_Base = i91u_adpt[ch_idx].ADPT_BASE; /* Supply base address */
pCurHcb->HCS_BIOS = i91u_adpt[ch_idx].ADPT_BIOS; /* Supply BIOS address */
@@ -651,7 +650,7 @@ void get_tulipPCIConfig(HCS * pCurHcb, int ch_idx)
}
/***************************************************************************/
-int tul_reset_scsi(HCS * pCurHcb, int seconds)
+static int tul_reset_scsi(HCS * pCurHcb, int seconds)
{
TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_BUS);
@@ -670,7 +669,8 @@ int tul_reset_scsi(HCS * pCurHcb, int seconds)
}
/***************************************************************************/
-int init_tulip(HCS * pCurHcb, SCB * scbp, int tul_num_scb, BYTE * pbBiosAdr, int seconds)
+static int init_tulip(HCS * pCurHcb, SCB * scbp, int tul_num_scb,
+ BYTE * pbBiosAdr, int seconds)
{
int i;
BYTE *pwFlags;
@@ -788,7 +788,7 @@ int init_tulip(HCS * pCurHcb, SCB * scbp, int tul_num_scb, BYTE * pbBiosAdr, int
}
/***************************************************************************/
-SCB *tul_alloc_scb(HCS * hcsp)
+static SCB *tul_alloc_scb(HCS * hcsp)
{
SCB *pTmpScb;
ULONG flags;
@@ -807,7 +807,7 @@ SCB *tul_alloc_scb(HCS * hcsp)
}
/***************************************************************************/
-void tul_release_scb(HCS * hcsp, SCB * scbp)
+static void tul_release_scb(HCS * hcsp, SCB * scbp)
{
ULONG flags;
@@ -829,7 +829,7 @@ void tul_release_scb(HCS * hcsp, SCB * scbp)
}
/***************************************************************************/
-void tul_append_pend_scb(HCS * pCurHcb, SCB * scbp)
+static void tul_append_pend_scb(HCS * pCurHcb, SCB * scbp)
{
#if DEBUG_QUEUE
@@ -847,7 +847,7 @@ void tul_append_pend_scb(HCS * pCurHcb, SCB * scbp)
}
/***************************************************************************/
-void tul_push_pend_scb(HCS * pCurHcb, SCB * scbp)
+static void tul_push_pend_scb(HCS * pCurHcb, SCB * scbp)
{
#if DEBUG_QUEUE
@@ -863,7 +863,7 @@ void tul_push_pend_scb(HCS * pCurHcb, SCB * scbp)
}
/***************************************************************************/
-SCB *tul_find_first_pend_scb(HCS * pCurHcb)
+static SCB *tul_find_first_pend_scb(HCS * pCurHcb)
{
SCB *pFirstPend;
@@ -894,24 +894,7 @@ SCB *tul_find_first_pend_scb(HCS * pCurHcb)
return (pFirstPend);
}
/***************************************************************************/
-SCB *tul_pop_pend_scb(HCS * pCurHcb)
-{
- SCB *pTmpScb;
-
- if ((pTmpScb = pCurHcb->HCS_FirstPend) != NULL) {
- if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL)
- pCurHcb->HCS_LastPend = NULL;
- pTmpScb->SCB_NxtScb = NULL;
- }
-#if DEBUG_QUEUE
- printk("Pop pend SCB %lx; ", (ULONG) pTmpScb);
-#endif
- return (pTmpScb);
-}
-
-
-/***************************************************************************/
-void tul_unlink_pend_scb(HCS * pCurHcb, SCB * pCurScb)
+static void tul_unlink_pend_scb(HCS * pCurHcb, SCB * pCurScb)
{
SCB *pTmpScb, *pPrevScb;
@@ -939,7 +922,7 @@ void tul_unlink_pend_scb(HCS * pCurHcb, SCB * pCurScb)
return;
}
/***************************************************************************/
-void tul_append_busy_scb(HCS * pCurHcb, SCB * scbp)
+static void tul_append_busy_scb(HCS * pCurHcb, SCB * scbp)
{
#if DEBUG_QUEUE
@@ -961,7 +944,7 @@ void tul_append_busy_scb(HCS * pCurHcb, SCB * scbp)
}
/***************************************************************************/
-SCB *tul_pop_busy_scb(HCS * pCurHcb)
+static SCB *tul_pop_busy_scb(HCS * pCurHcb)
{
SCB *pTmpScb;
@@ -982,7 +965,7 @@ SCB *tul_pop_busy_scb(HCS * pCurHcb)
}
/***************************************************************************/
-void tul_unlink_busy_scb(HCS * pCurHcb, SCB * pCurScb)
+static void tul_unlink_busy_scb(HCS * pCurHcb, SCB * pCurScb)
{
SCB *pTmpScb, *pPrevScb;
@@ -1037,7 +1020,7 @@ SCB *tul_find_busy_scb(HCS * pCurHcb, WORD tarlun)
}
/***************************************************************************/
-void tul_append_done_scb(HCS * pCurHcb, SCB * scbp)
+static void tul_append_done_scb(HCS * pCurHcb, SCB * scbp)
{
#if DEBUG_QUEUE
@@ -1073,7 +1056,7 @@ SCB *tul_find_done_scb(HCS * pCurHcb)
}
/***************************************************************************/
-int tul_abort_srb(HCS * pCurHcb, struct scsi_cmnd *srbp)
+static int tul_abort_srb(HCS * pCurHcb, struct scsi_cmnd *srbp)
{
ULONG flags;
SCB *pTmpScb, *pPrevScb;
@@ -1163,7 +1146,7 @@ int tul_abort_srb(HCS * pCurHcb, struct scsi_cmnd *srbp)
}
/***************************************************************************/
-int tul_bad_seq(HCS * pCurHcb)
+static int tul_bad_seq(HCS * pCurHcb)
{
SCB *pCurScb;
@@ -1182,9 +1165,11 @@ int tul_bad_seq(HCS * pCurHcb)
return (tul_post_scsi_rst(pCurHcb));
}
+#if 0
+
/************************************************************************/
-int tul_device_reset(HCS * pCurHcb, struct scsi_cmnd *pSrb,
- unsigned int target, unsigned int ResetFlags)
+static int tul_device_reset(HCS * pCurHcb, struct scsi_cmnd *pSrb,
+ unsigned int target, unsigned int ResetFlags)
{
ULONG flags;
SCB *pScb;
@@ -1255,7 +1240,7 @@ int tul_device_reset(HCS * pCurHcb, struct scsi_cmnd *pSrb,
return SCSI_RESET_PENDING;
}
-int tul_reset_scsi_bus(HCS * pCurHcb)
+static int tul_reset_scsi_bus(HCS * pCurHcb)
{
ULONG flags;
@@ -1284,8 +1269,10 @@ int tul_reset_scsi_bus(HCS * pCurHcb)
return (SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET);
}
+#endif /* 0 */
+
/************************************************************************/
-void tul_exec_scb(HCS * pCurHcb, SCB * pCurScb)
+static void tul_exec_scb(HCS * pCurHcb, SCB * pCurScb)
{
ULONG flags;
@@ -1318,7 +1305,7 @@ void tul_exec_scb(HCS * pCurHcb, SCB * pCurScb)
}
/***************************************************************************/
-int tul_isr(HCS * pCurHcb)
+static int tul_isr(HCS * pCurHcb)
{
/* Enter critical section */
@@ -2108,7 +2095,7 @@ int int_tul_busfree(HCS * pCurHcb)
/***************************************************************************/
/* scsi bus reset */
-int int_tul_scsi_rst(HCS * pCurHcb)
+static int int_tul_scsi_rst(HCS * pCurHcb)
{
SCB *pCurScb;
int i;
@@ -2214,7 +2201,7 @@ int int_tul_resel(HCS * pCurHcb)
/***************************************************************************/
-int int_tul_bad_seq(HCS * pCurHcb)
+static int int_tul_bad_seq(HCS * pCurHcb)
{ /* target wrong phase */
SCB *pCurScb;
int i;
@@ -3014,7 +3001,11 @@ static int i91u_bus_reset(struct scsi_cmnd * SCpnt)
HCS *pHCB;
pHCB = (HCS *) SCpnt->device->host->base;
+
+ spin_lock_irq(SCpnt->device->host->host_lock);
tul_reset_scsi(pHCB, 0);
+ spin_unlock_irq(SCpnt->device->host->host_lock);
+
return SUCCESS;
}
diff --git a/drivers/scsi/initio.h b/drivers/scsi/initio.h
index df3ed7c1cee..3efb1184fc3 100644
--- a/drivers/scsi/initio.h
+++ b/drivers/scsi/initio.h
@@ -719,21 +719,3 @@ typedef struct _HCSinfo {
#define SCSI_RESET_HOST_RESET 0x200
#define SCSI_RESET_ACTION 0xff
-extern void init_i91uAdapter_table(void);
-extern int Addi91u_into_Adapter_table(WORD, WORD, BYTE, BYTE, BYTE);
-extern int tul_ReturnNumberOfAdapters(void);
-extern void get_tulipPCIConfig(HCS * pHCB, int iChannel_index);
-extern int init_tulip(HCS * pHCB, SCB * pSCB, int tul_num_scb, BYTE * pbBiosAdr, int reset_time);
-extern SCB *tul_alloc_scb(HCS * pHCB);
-extern int tul_abort_srb(HCS * pHCB, struct scsi_cmnd * pSRB);
-extern void tul_exec_scb(HCS * pHCB, SCB * pSCB);
-extern void tul_release_scb(HCS * pHCB, SCB * pSCB);
-extern void tul_stop_bm(HCS * pHCB);
-extern int tul_reset_scsi(HCS * pCurHcb, int seconds);
-extern int tul_isr(HCS * pHCB);
-extern int tul_reset(HCS * pHCB, struct scsi_cmnd * pSRB, unsigned char target);
-extern int tul_reset_scsi_bus(HCS * pCurHcb);
-extern int tul_device_reset(HCS * pCurHcb, struct scsi_cmnd *pSrb,
- unsigned int target, unsigned int ResetFlags);
- /* ---- EXTERNAL VARIABLES ---- */
-extern HCS tul_hcs[];
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 5441531c0d8..80d022625c8 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -1053,7 +1053,7 @@ static void ipr_log_array_error(struct ipr_ioa_cfg *ioa_cfg,
array_entry->dev_res_addr.lun);
}
- if (array_entry->dev_res_addr.bus >= IPR_MAX_NUM_BUSES) {
+ if (array_entry->expected_dev_res_addr.bus >= IPR_MAX_NUM_BUSES) {
ipr_err("Expected Location: unknown\n");
} else {
ipr_err("Expected Location: %d:%d:%d:%d\n",
@@ -2716,7 +2716,7 @@ static int ipr_change_queue_type(struct scsi_device *sdev, int tag_type)
* Return value:
* number of bytes printed to buffer
**/
-static ssize_t ipr_show_adapter_handle(struct device *dev, char *buf)
+static ssize_t ipr_show_adapter_handle(struct device *dev, struct device_attribute *attr, char *buf)
{
struct scsi_device *sdev = to_scsi_device(dev);
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata;
@@ -2885,7 +2885,7 @@ static int ipr_slave_alloc(struct scsi_device *sdev)
* Return value:
* SUCCESS / FAILED
**/
-static int ipr_eh_host_reset(struct scsi_cmnd * scsi_cmd)
+static int __ipr_eh_host_reset(struct scsi_cmnd * scsi_cmd)
{
struct ipr_ioa_cfg *ioa_cfg;
int rc;
@@ -2905,6 +2905,17 @@ static int ipr_eh_host_reset(struct scsi_cmnd * scsi_cmd)
return rc;
}
+static int ipr_eh_host_reset(struct scsi_cmnd * cmd)
+{
+ int rc;
+
+ spin_lock_irq(cmd->device->host->host_lock);
+ rc = __ipr_eh_host_reset(cmd);
+ spin_unlock_irq(cmd->device->host->host_lock);
+
+ return rc;
+}
+
/**
* ipr_eh_dev_reset - Reset the device
* @scsi_cmd: scsi command struct
@@ -2916,7 +2927,7 @@ static int ipr_eh_host_reset(struct scsi_cmnd * scsi_cmd)
* Return value:
* SUCCESS / FAILED
**/
-static int ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd)
+static int __ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd)
{
struct ipr_cmnd *ipr_cmd;
struct ipr_ioa_cfg *ioa_cfg;
@@ -2970,6 +2981,17 @@ static int ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd)
return (IPR_IOASC_SENSE_KEY(ioasc) ? FAILED : SUCCESS);
}
+static int ipr_eh_dev_reset(struct scsi_cmnd * cmd)
+{
+ int rc;
+
+ spin_lock_irq(cmd->device->host->host_lock);
+ rc = __ipr_eh_dev_reset(cmd);
+ spin_unlock_irq(cmd->device->host->host_lock);
+
+ return rc;
+}
+
/**
* ipr_bus_reset_done - Op done function for bus reset.
* @ipr_cmd: ipr command struct
@@ -3068,6 +3090,12 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd)
ioa_cfg = (struct ipr_ioa_cfg *)scsi_cmd->device->host->hostdata;
res = scsi_cmd->device->hostdata;
+ /* If we are currently going through reset/reload, return failed.
+ * This will force the mid-layer to call ipr_eh_host_reset,
+ * which will then go to sleep and wait for the reset to complete
+ */
+ if (ioa_cfg->in_reset_reload || ioa_cfg->ioa_is_dead)
+ return FAILED;
if (!res || (!ipr_is_gscsi(res) && !ipr_is_vset_device(res)))
return FAILED;
@@ -3118,23 +3146,17 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd)
**/
static int ipr_eh_abort(struct scsi_cmnd * scsi_cmd)
{
- struct ipr_ioa_cfg *ioa_cfg;
+ unsigned long flags;
+ int rc;
ENTER;
- ioa_cfg = (struct ipr_ioa_cfg *) scsi_cmd->device->host->hostdata;
- /* If we are currently going through reset/reload, return failed. This will force the
- mid-layer to call ipr_eh_host_reset, which will then go to sleep and wait for the
- reset to complete */
- if (ioa_cfg->in_reset_reload)
- return FAILED;
- if (ioa_cfg->ioa_is_dead)
- return FAILED;
- if (!scsi_cmd->device->hostdata)
- return FAILED;
+ spin_lock_irqsave(scsi_cmd->device->host->host_lock, flags);
+ rc = ipr_cancel_op(scsi_cmd);
+ spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, flags);
LEAVE;
- return ipr_cancel_op(scsi_cmd);
+ return rc;
}
/**
@@ -5886,6 +5908,7 @@ static void __ipr_remove(struct pci_dev *pdev)
spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags);
wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
+ flush_scheduled_work();
spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags);
spin_lock(&ipr_driver_lock);
@@ -5916,8 +5939,6 @@ static void ipr_remove(struct pci_dev *pdev)
ENTER;
- ioa_cfg->allow_cmds = 0;
- flush_scheduled_work();
ipr_remove_trace_file(&ioa_cfg->host->shost_classdev.kobj,
&ipr_trace_attr);
ipr_remove_dump_file(&ioa_cfg->host->shost_classdev.kobj,
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index 446f4259285..cbff3ea3cd8 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -36,8 +36,8 @@
/*
* Literals
*/
-#define IPR_DRIVER_VERSION "2.0.13"
-#define IPR_DRIVER_DATE "(February 21, 2005)"
+#define IPR_DRIVER_VERSION "2.0.14"
+#define IPR_DRIVER_DATE "(May 2, 2005)"
/*
* IPR_DBG_TRACE: Setting this to 1 will turn on some general function tracing
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index fbc2cb6667a..6dfcb4fbccd 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -819,12 +819,15 @@ ips_eh_abort(Scsi_Cmnd * SC)
ips_ha_t *ha;
ips_copp_wait_item_t *item;
int ret;
+ unsigned long cpu_flags;
+ struct Scsi_Host *host;
METHOD_TRACE("ips_eh_abort", 1);
if (!SC)
return (FAILED);
+ host = SC->device->host;
ha = (ips_ha_t *) SC->device->host->hostdata;
if (!ha)
@@ -833,6 +836,8 @@ ips_eh_abort(Scsi_Cmnd * SC)
if (!ha->active)
return (FAILED);
+ IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+
/* See if the command is on the copp queue */
item = ha->copp_waitlist.head;
while ((item) && (item->scsi_cmd != SC))
@@ -851,6 +856,8 @@ ips_eh_abort(Scsi_Cmnd * SC)
/* command must have already been sent */
ret = (FAILED);
}
+
+ IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
return ret;
}
@@ -866,7 +873,7 @@ ips_eh_abort(Scsi_Cmnd * SC)
/* */
/****************************************************************************/
static int
-ips_eh_reset(Scsi_Cmnd * SC)
+__ips_eh_reset(Scsi_Cmnd * SC)
{
int ret;
int i;
@@ -1053,6 +1060,18 @@ ips_eh_reset(Scsi_Cmnd * SC)
}
+static int
+ips_eh_reset(Scsi_Cmnd * SC)
+{
+ int rc;
+
+ spin_lock_irq(SC->device->host->host_lock);
+ rc = __ips_eh_reset(SC);
+ spin_unlock_irq(SC->device->host->host_lock);
+
+ return rc;
+}
+
/****************************************************************************/
/* */
/* Routine Name: ips_queue */
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 0b5d3a5b7ed..36b401fee1f 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -186,6 +186,28 @@ static void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
ata_wait_idle(ap);
}
+
+/**
+ * ata_tf_load - send taskfile registers to host controller
+ * @ap: Port to which output is sent
+ * @tf: ATA taskfile register set
+ *
+ * Outputs ATA taskfile to standard ATA host controller using MMIO
+ * or PIO as indicated by the ATA_FLAG_MMIO flag.
+ * Writes the control, feature, nsect, lbal, lbam, and lbah registers.
+ * Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect,
+ * hob_lbal, hob_lbam, and hob_lbah.
+ *
+ * This function waits for idle (!BUSY and !DRQ) after writing
+ * registers. If the control register has a new value, this
+ * function also waits for idle after writing control and before
+ * writing the remaining registers.
+ *
+ * May be used as the tf_load() entry in ata_port_operations.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
{
if (ap->flags & ATA_FLAG_MMIO)
@@ -195,11 +217,11 @@ void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
}
/**
- * ata_exec_command - issue ATA command to host controller
+ * ata_exec_command_pio - issue ATA command to host controller
* @ap: port to which command is being issued
* @tf: ATA taskfile register set
*
- * Issues PIO/MMIO write to ATA command register, with proper
+ * Issues PIO write to ATA command register, with proper
* synchronization with interrupt handler / other threads.
*
* LOCKING:
@@ -235,6 +257,18 @@ static void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
ata_pause(ap);
}
+
+/**
+ * ata_exec_command - issue ATA command to host controller
+ * @ap: port to which command is being issued
+ * @tf: ATA taskfile register set
+ *
+ * Issues PIO/MMIO write to ATA command register, with proper
+ * synchronization with interrupt handler / other threads.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host_set lock)
+ */
void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf)
{
if (ap->flags & ATA_FLAG_MMIO)
@@ -305,7 +339,7 @@ void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf)
}
/**
- * ata_tf_read - input device's ATA taskfile shadow registers
+ * ata_tf_read_pio - input device's ATA taskfile shadow registers
* @ap: Port from which input is read
* @tf: ATA taskfile register set for storing input
*
@@ -368,6 +402,23 @@ static void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf)
}
}
+
+/**
+ * ata_tf_read - input device's ATA taskfile shadow registers
+ * @ap: Port from which input is read
+ * @tf: ATA taskfile register set for storing input
+ *
+ * Reads ATA taskfile registers for currently-selected device
+ * into @tf.
+ *
+ * Reads nsect, lbal, lbam, lbah, and device. If ATA_TFLAG_LBA48
+ * is set, also reads the hob registers.
+ *
+ * May be used as the tf_read() entry in ata_port_operations.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
{
if (ap->flags & ATA_FLAG_MMIO)
@@ -381,7 +432,7 @@ void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
* @ap: port where the device is
*
* Reads ATA taskfile status register for currently-selected device
- * and return it's value. This also clears pending interrupts
+ * and return its value. This also clears pending interrupts
* from this device
*
* LOCKING:
@@ -397,7 +448,7 @@ static u8 ata_check_status_pio(struct ata_port *ap)
* @ap: port where the device is
*
* Reads ATA taskfile status register for currently-selected device
- * via MMIO and return it's value. This also clears pending interrupts
+ * via MMIO and return its value. This also clears pending interrupts
* from this device
*
* LOCKING:
@@ -408,6 +459,20 @@ static u8 ata_check_status_mmio(struct ata_port *ap)
return readb((void __iomem *) ap->ioaddr.status_addr);
}
+
+/**
+ * ata_check_status - Read device status reg & clear interrupt
+ * @ap: port where the device is
+ *
+ * Reads ATA taskfile status register for currently-selected device
+ * and return its value. This also clears pending interrupts
+ * from this device
+ *
+ * May be used as the check_status() entry in ata_port_operations.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
u8 ata_check_status(struct ata_port *ap)
{
if (ap->flags & ATA_FLAG_MMIO)
@@ -415,6 +480,20 @@ u8 ata_check_status(struct ata_port *ap)
return ata_check_status_pio(ap);
}
+
+/**
+ * ata_altstatus - Read device alternate status reg
+ * @ap: port where the device is
+ *
+ * Reads ATA taskfile alternate status register for
+ * currently-selected device and return its value.
+ *
+ * Note: may NOT be used as the check_altstatus() entry in
+ * ata_port_operations.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
u8 ata_altstatus(struct ata_port *ap)
{
if (ap->ops->check_altstatus)
@@ -425,6 +504,20 @@ u8 ata_altstatus(struct ata_port *ap)
return inb(ap->ioaddr.altstatus_addr);
}
+
+/**
+ * ata_chk_err - Read device error reg
+ * @ap: port where the device is
+ *
+ * Reads ATA taskfile error register for
+ * currently-selected device and return its value.
+ *
+ * Note: may NOT be used as the check_err() entry in
+ * ata_port_operations.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
u8 ata_chk_err(struct ata_port *ap)
{
if (ap->ops->check_err)
@@ -873,10 +966,24 @@ void ata_dev_id_string(u16 *id, unsigned char *s,
}
}
+
+/**
+ * ata_noop_dev_select - Select device 0/1 on ATA bus
+ * @ap: ATA channel to manipulate
+ * @device: ATA device (numbered from zero) to select
+ *
+ * This function performs no actual function.
+ *
+ * May be used as the dev_select() entry in ata_port_operations.
+ *
+ * LOCKING:
+ * caller.
+ */
void ata_noop_dev_select (struct ata_port *ap, unsigned int device)
{
}
+
/**
* ata_std_dev_select - Select device 0/1 on ATA bus
* @ap: ATA channel to manipulate
@@ -884,7 +991,9 @@ void ata_noop_dev_select (struct ata_port *ap, unsigned int device)
*
* Use the method defined in the ATA specification to
* make either device 0, or device 1, active on the
- * ATA channel.
+ * ATA channel. Works with both PIO and MMIO.
+ *
+ * May be used as the dev_select() entry in ata_port_operations.
*
* LOCKING:
* caller.
@@ -1186,11 +1295,47 @@ err_out:
DPRINTK("EXIT, err\n");
}
+
+static inline u8 ata_dev_knobble(struct ata_port *ap)
+{
+ return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(ap->device->id)));
+}
+
+/**
+ * ata_dev_config - Run device specific handlers and check for
+ * SATA->PATA bridges
+ * @ap: Bus
+ * @i: Device
+ *
+ * LOCKING:
+ */
+
+void ata_dev_config(struct ata_port *ap, unsigned int i)
+{
+ /* limit bridge transfers to udma5, 200 sectors */
+ if (ata_dev_knobble(ap)) {
+ printk(KERN_INFO "ata%u(%u): applying bridge limits\n",
+ ap->id, ap->device->devno);
+ ap->udma_mask &= ATA_UDMA5;
+ ap->host->max_sectors = ATA_MAX_SECTORS;
+ ap->host->hostt->max_sectors = ATA_MAX_SECTORS;
+ ap->device->flags |= ATA_DFLAG_LOCK_SECTORS;
+ }
+
+ if (ap->ops->dev_config)
+ ap->ops->dev_config(ap, &ap->device[i]);
+}
+
/**
* ata_bus_probe - Reset and probe ATA bus
* @ap: Bus to probe
*
+ * Master ATA bus probing function. Initiates a hardware-dependent
+ * bus reset, then attempts to identify any devices found on
+ * the bus.
+ *
* LOCKING:
+ * PCI/etc. bus probe sem.
*
* RETURNS:
* Zero on success, non-zero on error.
@@ -1208,8 +1353,7 @@ static int ata_bus_probe(struct ata_port *ap)
ata_dev_identify(ap, i);
if (ata_dev_present(&ap->device[i])) {
found = 1;
- if (ap->ops->dev_config)
- ap->ops->dev_config(ap, &ap->device[i]);
+ ata_dev_config(ap,i);
}
}
@@ -1229,10 +1373,14 @@ err_out:
}
/**
- * ata_port_probe -
- * @ap:
+ * ata_port_probe - Mark port as enabled
+ * @ap: Port for which we indicate enablement
*
- * LOCKING:
+ * Modify @ap data structure such that the system
+ * thinks that the entire port is enabled.
+ *
+ * LOCKING: host_set lock, or some other form of
+ * serialization.
*/
void ata_port_probe(struct ata_port *ap)
@@ -1241,10 +1389,15 @@ void ata_port_probe(struct ata_port *ap)
}
/**
- * __sata_phy_reset -
- * @ap:
+ * __sata_phy_reset - Wake/reset a low-level SATA PHY
+ * @ap: SATA port associated with target SATA PHY.
+ *
+ * This function issues commands to standard SATA Sxxx
+ * PHY registers, to wake up the phy (and device), and
+ * clear any reset condition.
*
* LOCKING:
+ * PCI/etc. bus probe sem.
*
*/
void __sata_phy_reset(struct ata_port *ap)
@@ -1253,11 +1406,11 @@ void __sata_phy_reset(struct ata_port *ap)
unsigned long timeout = jiffies + (HZ * 5);
if (ap->flags & ATA_FLAG_SATA_RESET) {
- scr_write(ap, SCR_CONTROL, 0x301); /* issue phy wake/reset */
- scr_read(ap, SCR_STATUS); /* dummy read; flush */
+ /* issue phy wake/reset */
+ scr_write_flush(ap, SCR_CONTROL, 0x301);
udelay(400); /* FIXME: a guess */
}
- scr_write(ap, SCR_CONTROL, 0x300); /* issue phy wake/clear reset */
+ scr_write_flush(ap, SCR_CONTROL, 0x300); /* phy wake/clear reset */
/* wait for phy to become ready, if necessary */
do {
@@ -1289,10 +1442,14 @@ void __sata_phy_reset(struct ata_port *ap)
}
/**
- * __sata_phy_reset -
- * @ap:
+ * sata_phy_reset - Reset SATA bus.
+ * @ap: SATA port associated with target SATA PHY.
+ *
+ * This function resets the SATA bus, and then probes
+ * the bus for devices.
*
* LOCKING:
+ * PCI/etc. bus probe sem.
*
*/
void sata_phy_reset(struct ata_port *ap)
@@ -1304,10 +1461,16 @@ void sata_phy_reset(struct ata_port *ap)
}
/**
- * ata_port_disable -
- * @ap:
+ * ata_port_disable - Disable port.
+ * @ap: Port to be disabled.
*
- * LOCKING:
+ * Modify @ap data structure such that the system
+ * thinks that the entire port is disabled, and should
+ * never attempt to probe or communicate with devices
+ * on this port.
+ *
+ * LOCKING: host_set lock, or some other form of
+ * serialization.
*/
void ata_port_disable(struct ata_port *ap)
@@ -1416,7 +1579,10 @@ static void ata_host_set_dma(struct ata_port *ap, u8 xfer_mode,
* ata_set_mode - Program timings and issue SET FEATURES - XFER
* @ap: port on which timings will be programmed
*
+ * Set ATA device disk transfer mode (PIO3, UDMA6, etc.).
+ *
* LOCKING:
+ * PCI/etc. bus probe sem.
*
*/
static void ata_set_mode(struct ata_port *ap)
@@ -1467,7 +1633,10 @@ err_out:
* @tmout_pat: impatience timeout
* @tmout: overall timeout
*
- * LOCKING:
+ * Sleep until ATA Status register bit BSY clears,
+ * or a timeout occurs.
+ *
+ * LOCKING: None.
*
*/
@@ -1553,10 +1722,14 @@ static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask)
}
/**
- * ata_bus_edd -
- * @ap:
+ * ata_bus_edd - Issue EXECUTE DEVICE DIAGNOSTIC command.
+ * @ap: Port to reset and probe
+ *
+ * Use the EXECUTE DEVICE DIAGNOSTIC command to reset and
+ * probe the bus. Not often used these days.
*
* LOCKING:
+ * PCI/etc. bus probe sem.
*
*/
@@ -1633,8 +1806,8 @@ static unsigned int ata_bus_softreset(struct ata_port *ap,
* the device is ATA or ATAPI.
*
* LOCKING:
- * Inherited from caller. Some functions called by this function
- * obtain the host_set lock.
+ * PCI/etc. bus probe sem.
+ * Obtains host_set lock.
*
* SIDE EFFECTS:
* Sets ATA_FLAG_PORT_DISABLED if bus reset fails.
@@ -1876,7 +2049,11 @@ static int fgb(u32 bitmap)
* @xfer_mode_out: (output) SET FEATURES - XFER MODE code
* @xfer_shift_out: (output) bit shift that selects this mode
*
+ * Based on host and device capabilities, determine the
+ * maximum transfer mode that is amenable to all.
+ *
* LOCKING:
+ * PCI/etc. bus probe sem.
*
* RETURNS:
* Zero on success, negative on error.
@@ -1909,7 +2086,11 @@ static int ata_choose_xfer_mode(struct ata_port *ap,
* @ap: Port associated with device @dev
* @dev: Device to which command will be sent
*
+ * Issue SET FEATURES - XFER MODE command to device @dev
+ * on port @ap.
+ *
* LOCKING:
+ * PCI/etc. bus probe sem.
*/
static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
@@ -1947,10 +2128,13 @@ static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
}
/**
- * ata_sg_clean -
- * @qc:
+ * ata_sg_clean - Unmap DMA memory associated with command
+ * @qc: Command containing DMA memory to be released
+ *
+ * Unmap all mapped DMA memory associated with this command.
*
* LOCKING:
+ * spin_lock_irqsave(host_set lock)
*/
static void ata_sg_clean(struct ata_queued_cmd *qc)
@@ -1981,7 +2165,11 @@ static void ata_sg_clean(struct ata_queued_cmd *qc)
* ata_fill_sg - Fill PCI IDE PRD table
* @qc: Metadata associated with taskfile to be transferred
*
+ * Fill PCI IDE PRD (scatter-gather) table with segments
+ * associated with the current disk command.
+ *
* LOCKING:
+ * spin_lock_irqsave(host_set lock)
*
*/
static void ata_fill_sg(struct ata_queued_cmd *qc)
@@ -2028,7 +2216,13 @@ static void ata_fill_sg(struct ata_queued_cmd *qc)
* ata_check_atapi_dma - Check whether ATAPI DMA can be supported
* @qc: Metadata associated with taskfile to check
*
+ * Allow low-level driver to filter ATA PACKET commands, returning
+ * a status indicating whether or not it is OK to use DMA for the
+ * supplied PACKET command.
+ *
* LOCKING:
+ * spin_lock_irqsave(host_set lock)
+ *
* RETURNS: 0 when ATAPI DMA can be used
* nonzero otherwise
*/
@@ -2046,6 +2240,8 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc)
* ata_qc_prep - Prepare taskfile for submission
* @qc: Metadata associated with taskfile to be prepared
*
+ * Prepare ATA taskfile for submission.
+ *
* LOCKING:
* spin_lock_irqsave(host_set lock)
*/
@@ -2057,6 +2253,32 @@ void ata_qc_prep(struct ata_queued_cmd *qc)
ata_fill_sg(qc);
}
+/**
+ * ata_sg_init_one - Associate command with memory buffer
+ * @qc: Command to be associated
+ * @buf: Memory buffer
+ * @buflen: Length of memory buffer, in bytes.
+ *
+ * Initialize the data-related elements of queued_cmd @qc
+ * to point to a single memory buffer, @buf of byte length @buflen.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host_set lock)
+ */
+
+
+
+/**
+ * ata_sg_init_one - Prepare a one-entry scatter-gather list.
+ * @qc: Queued command
+ * @buf: transfer buffer
+ * @buflen: length of buf
+ *
+ * Builds a single-entry scatter-gather list to initiate a
+ * transfer utilizing the specified buffer.
+ *
+ * LOCKING:
+ */
void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
{
struct scatterlist *sg;
@@ -2071,9 +2293,35 @@ void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
sg = qc->sg;
sg->page = virt_to_page(buf);
sg->offset = (unsigned long) buf & ~PAGE_MASK;
- sg_dma_len(sg) = buflen;
+ sg->length = buflen;
}
+/**
+ * ata_sg_init - Associate command with scatter-gather table.
+ * @qc: Command to be associated
+ * @sg: Scatter-gather table.
+ * @n_elem: Number of elements in s/g table.
+ *
+ * Initialize the data-related elements of queued_cmd @qc
+ * to point to a scatter-gather table @sg, containing @n_elem
+ * elements.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host_set lock)
+ */
+
+
+/**
+ * ata_sg_init - Assign a scatter gather list to a queued command
+ * @qc: Queued command
+ * @sg: Scatter-gather list
+ * @n_elem: length of sg list
+ *
+ * Attaches a scatter-gather list to a queued command.
+ *
+ * LOCKING:
+ */
+
void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
unsigned int n_elem)
{
@@ -2083,14 +2331,16 @@ void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
}
/**
- * ata_sg_setup_one -
- * @qc:
+ * ata_sg_setup_one - DMA-map the memory buffer associated with a command.
+ * @qc: Command with memory buffer to be mapped.
+ *
+ * DMA-map the memory buffer associated with queued_cmd @qc.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*
* RETURNS:
- *
+ * Zero on success, negative on error.
*/
static int ata_sg_setup_one(struct ata_queued_cmd *qc)
@@ -2101,11 +2351,12 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc)
dma_addr_t dma_address;
dma_address = dma_map_single(ap->host_set->dev, qc->buf_virt,
- sg_dma_len(sg), dir);
+ sg->length, dir);
if (dma_mapping_error(dma_address))
return -1;
sg_dma_address(sg) = dma_address;
+ sg_dma_len(sg) = sg->length;
DPRINTK("mapped buffer of %d bytes for %s\n", sg_dma_len(sg),
qc->tf.flags & ATA_TFLAG_WRITE ? "write" : "read");
@@ -2114,13 +2365,16 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc)
}
/**
- * ata_sg_setup -
- * @qc:
+ * ata_sg_setup - DMA-map the scatter-gather table associated with a command.
+ * @qc: Command with scatter-gather table to be mapped.
+ *
+ * DMA-map the scatter-gather table associated with queued_cmd @qc.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*
* RETURNS:
+ * Zero on success, negative on error.
*
*/
@@ -2150,6 +2404,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
* @ap:
*
* LOCKING:
+ * None. (executing in kernel thread context)
*
* RETURNS:
*
@@ -2197,6 +2452,7 @@ static unsigned long ata_pio_poll(struct ata_port *ap)
* @ap:
*
* LOCKING:
+ * None. (executing in kernel thread context)
*/
static void ata_pio_complete (struct ata_port *ap)
@@ -2239,6 +2495,18 @@ static void ata_pio_complete (struct ata_port *ap)
ata_qc_complete(qc, drv_stat);
}
+
+/**
+ * swap_buf_le16 -
+ * @buf: Buffer to swap
+ * @buf_words: Number of 16-bit words in buffer.
+ *
+ * Swap halves of 16-bit words if needed to convert from
+ * little-endian byte order to native cpu byte order, or
+ * vice-versa.
+ *
+ * LOCKING:
+ */
void swap_buf_le16(u16 *buf, unsigned int buf_words)
{
#ifdef __BIG_ENDIAN
@@ -2310,7 +2578,7 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
qc->cursect++;
qc->cursg_ofs++;
- if ((qc->cursg_ofs * ATA_SECT_SIZE) == sg_dma_len(&sg[qc->cursg])) {
+ if ((qc->cursg_ofs * ATA_SECT_SIZE) == (&sg[qc->cursg])->length) {
qc->cursg++;
qc->cursg_ofs = 0;
}
@@ -2339,7 +2607,6 @@ static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
next_sg:
sg = &qc->sg[qc->cursg];
-next_page:
page = sg->page;
offset = sg->offset + qc->cursg_ofs;
@@ -2347,7 +2614,8 @@ next_page:
page = nth_page(page, (offset >> PAGE_SHIFT));
offset %= PAGE_SIZE;
- count = min(sg_dma_len(sg) - qc->cursg_ofs, bytes);
+ /* don't overrun current sg */
+ count = min(sg->length - qc->cursg_ofs, bytes);
/* don't cross page boundaries */
count = min(count, (unsigned int)PAGE_SIZE - offset);
@@ -2358,7 +2626,7 @@ next_page:
qc->curbytes += count;
qc->cursg_ofs += count;
- if (qc->cursg_ofs == sg_dma_len(sg)) {
+ if (qc->cursg_ofs == sg->length) {
qc->cursg++;
qc->cursg_ofs = 0;
}
@@ -2371,8 +2639,6 @@ next_page:
kunmap(page);
if (bytes) {
- if (qc->cursg_ofs < sg_dma_len(sg))
- goto next_page;
goto next_sg;
}
}
@@ -2414,6 +2680,7 @@ err_out:
* @ap:
*
* LOCKING:
+ * None. (executing in kernel thread context)
*/
static void ata_pio_block(struct ata_port *ap)
@@ -2539,7 +2806,7 @@ static void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer));
qc->dma_dir = DMA_FROM_DEVICE;
- memset(&qc->cdb, 0, sizeof(ap->cdb_len));
+ memset(&qc->cdb, 0, ap->cdb_len);
qc->cdb[0] = REQUEST_SENSE;
qc->cdb[4] = SCSI_SENSE_BUFFERSIZE;
@@ -2582,6 +2849,7 @@ static void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
* transaction completed successfully.
*
* LOCKING:
+ * Inherited from SCSI layer (none, can sleep)
*/
static void ata_qc_timeout(struct ata_queued_cmd *qc)
@@ -2691,6 +2959,7 @@ out:
* @dev: Device from whom we request an available command structure
*
* LOCKING:
+ * None.
*/
static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
@@ -2716,6 +2985,7 @@ static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
* @dev: Device from whom we request an available command structure
*
* LOCKING:
+ * None.
*/
struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
@@ -2780,6 +3050,7 @@ static void __ata_qc_complete(struct ata_queued_cmd *qc)
* in case something prevents using it.
*
* LOCKING:
+ * spin_lock_irqsave(host_set lock)
*
*/
void ata_qc_free(struct ata_queued_cmd *qc)
@@ -2793,9 +3064,13 @@ void ata_qc_free(struct ata_queued_cmd *qc)
/**
* ata_qc_complete - Complete an active ATA command
* @qc: Command to complete
- * @drv_stat: ATA status register contents
+ * @drv_stat: ATA Status register contents
+ *
+ * Indicate to the mid and upper layers that an ATA
+ * command has completed, with either an ok or not-ok status.
*
* LOCKING:
+ * spin_lock_irqsave(host_set lock)
*
*/
@@ -2811,6 +3086,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
/* call completion callback */
rc = qc->complete_fn(qc, drv_stat);
+ qc->flags &= ~ATA_QCFLAG_ACTIVE;
/* if callback indicates not to complete command (non-zero),
* return immediately
@@ -2890,6 +3166,7 @@ err_out:
return -1;
}
+
/**
* ata_qc_issue_prot - issue taskfile to device in proto-dependent manner
* @qc: command to issue to device
@@ -2899,6 +3176,8 @@ err_out:
* classes called "protocols", and issuing each type of protocol
* is slightly different.
*
+ * May be used as the qc_issue() entry in ata_port_operations.
+ *
* LOCKING:
* spin_lock_irqsave(host_set lock)
*
@@ -2956,7 +3235,7 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc)
}
/**
- * ata_bmdma_setup - Set up PCI IDE BMDMA transaction
+ * ata_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction
* @qc: Info associated with this ATA transaction.
*
* LOCKING:
@@ -3063,6 +3342,18 @@ static void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
}
+
+/**
+ * ata_bmdma_start - Start a PCI IDE BMDMA transaction
+ * @qc: Info associated with this ATA transaction.
+ *
+ * Writes the ATA_DMA_START flag to the DMA command register.
+ *
+ * May be used as the bmdma_start() entry in ata_port_operations.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host_set lock)
+ */
void ata_bmdma_start(struct ata_queued_cmd *qc)
{
if (qc->ap->flags & ATA_FLAG_MMIO)
@@ -3071,6 +3362,20 @@ void ata_bmdma_start(struct ata_queued_cmd *qc)
ata_bmdma_start_pio(qc);
}
+
+/**
+ * ata_bmdma_setup - Set up PCI IDE BMDMA transaction
+ * @qc: Info associated with this ATA transaction.
+ *
+ * Writes address of PRD table to device's PRD Table Address
+ * register, sets the DMA control register, and calls
+ * ops->exec_command() to start the transfer.
+ *
+ * May be used as the bmdma_setup() entry in ata_port_operations.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host_set lock)
+ */
void ata_bmdma_setup(struct ata_queued_cmd *qc)
{
if (qc->ap->flags & ATA_FLAG_MMIO)
@@ -3079,6 +3384,19 @@ void ata_bmdma_setup(struct ata_queued_cmd *qc)
ata_bmdma_setup_pio(qc);
}
+
+/**
+ * ata_bmdma_irq_clear - Clear PCI IDE BMDMA interrupt.
+ * @ap: Port associated with this ATA transaction.
+ *
+ * Clear interrupt and error flags in DMA status register.
+ *
+ * May be used as the irq_clear() entry in ata_port_operations.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host_set lock)
+ */
+
void ata_bmdma_irq_clear(struct ata_port *ap)
{
if (ap->flags & ATA_FLAG_MMIO) {
@@ -3091,6 +3409,19 @@ void ata_bmdma_irq_clear(struct ata_port *ap)
}
+
+/**
+ * ata_bmdma_status - Read PCI IDE BMDMA status
+ * @ap: Port associated with this ATA transaction.
+ *
+ * Read and return BMDMA status register.
+ *
+ * May be used as the bmdma_status() entry in ata_port_operations.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host_set lock)
+ */
+
u8 ata_bmdma_status(struct ata_port *ap)
{
u8 host_stat;
@@ -3102,6 +3433,19 @@ u8 ata_bmdma_status(struct ata_port *ap)
return host_stat;
}
+
+/**
+ * ata_bmdma_stop - Stop PCI IDE BMDMA transfer
+ * @ap: Port associated with this ATA transaction.
+ *
+ * Clears the ATA_DMA_START flag in the dma control register
+ *
+ * May be used as the bmdma_stop() entry in ata_port_operations.
+ *
+ * LOCKING:
+ * spin_lock_irqsave(host_set lock)
+ */
+
void ata_bmdma_stop(struct ata_port *ap)
{
if (ap->flags & ATA_FLAG_MMIO) {
@@ -3201,13 +3545,18 @@ idle_irq:
/**
* ata_interrupt - Default ATA host interrupt handler
- * @irq: irq line
- * @dev_instance: pointer to our host information structure
+ * @irq: irq line (unused)
+ * @dev_instance: pointer to our ata_host_set information structure
* @regs: unused
*
+ * Default interrupt handler for PCI IDE devices. Calls
+ * ata_host_intr() for each port that is not disabled.
+ *
* LOCKING:
+ * Obtains host_set lock during operation.
*
* RETURNS:
+ * IRQ_NONE or IRQ_HANDLED.
*
*/
@@ -3229,7 +3578,8 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
struct ata_queued_cmd *qc;
qc = ata_qc_from_tag(ap, ap->active_tag);
- if (qc && (!(qc->tf.ctl & ATA_NIEN)))
+ if (qc && (!(qc->tf.ctl & ATA_NIEN)) &&
+ (qc->flags & ATA_QCFLAG_ACTIVE))
handled |= ata_host_intr(ap, qc);
}
}
@@ -3299,6 +3649,19 @@ err_out:
ata_qc_complete(qc, ATA_ERR);
}
+
+/**
+ * ata_port_start - Set port up for dma.
+ * @ap: Port to initialize
+ *
+ * Called just after data structures for each port are
+ * initialized. Allocates space for PRD table.
+ *
+ * May be used as the port_start() entry in ata_port_operations.
+ *
+ * LOCKING:
+ */
+
int ata_port_start (struct ata_port *ap)
{
struct device *dev = ap->host_set->dev;
@@ -3312,6 +3675,18 @@ int ata_port_start (struct ata_port *ap)
return 0;
}
+
+/**
+ * ata_port_stop - Undo ata_port_start()
+ * @ap: Port to shut down
+ *
+ * Frees the PRD table.
+ *
+ * May be used as the port_stop() entry in ata_port_operations.
+ *
+ * LOCKING:
+ */
+
void ata_port_stop (struct ata_port *ap)
{
struct device *dev = ap->host_set->dev;
@@ -3319,6 +3694,13 @@ void ata_port_stop (struct ata_port *ap)
dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma);
}
+void ata_host_stop (struct ata_host_set *host_set)
+{
+ if (host_set->mmio_base)
+ iounmap(host_set->mmio_base);
+}
+
+
/**
* ata_host_remove - Unregister SCSI host structure with upper layers
* @ap: Port to unregister
@@ -3347,7 +3729,11 @@ static void ata_host_remove(struct ata_port *ap, unsigned int do_unregister)
* @ent: Probe information provided by low-level driver
* @port_no: Port number associated with this ata_port
*
+ * Initialize a new ata_port structure, and its associated
+ * scsi_host.
+ *
* LOCKING:
+ * Inherited from caller.
*
*/
@@ -3402,9 +3788,13 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
* @host_set: Collections of ports to which we add
* @port_no: Port number associated with this host
*
+ * Attach low-level ATA driver to system.
+ *
* LOCKING:
+ * PCI/etc. bus probe sem.
*
* RETURNS:
+ * New ata_port on success, for NULL on error.
*
*/
@@ -3437,12 +3827,22 @@ err_out:
}
/**
- * ata_device_add -
- * @ent:
+ * ata_device_add - Register hardware device with ATA and SCSI layers
+ * @ent: Probe information describing hardware device to be registered
+ *
+ * This function processes the information provided in the probe
+ * information struct @ent, allocates the necessary ATA and SCSI
+ * host information structures, initializes them, and registers
+ * everything with requisite kernel subsystems.
+ *
+ * This function requests irqs, probes the ATA bus, and probes
+ * the SCSI bus.
*
* LOCKING:
+ * PCI/etc. bus probe sem.
*
* RETURNS:
+ * Number of ports registered. Zero on error (no ports registered).
*
*/
@@ -3594,7 +3994,15 @@ int ata_scsi_release(struct Scsi_Host *host)
/**
* ata_std_ports - initialize ioaddr with standard port offsets.
* @ioaddr: IO address structure to be initialized
+ *
+ * Utility function which initializes data_addr, error_addr,
+ * feature_addr, nsect_addr, lbal_addr, lbam_addr, lbah_addr,
+ * device_addr, status_addr, and command_addr to standard offsets
+ * relative to cmd_addr.
+ *
+ * Does not set ctl_addr, altstatus_addr, bmdma_addr, or scr_addr.
*/
+
void ata_std_ports(struct ata_ioports *ioaddr)
{
ioaddr->data_addr = ioaddr->cmd_addr + ATA_REG_DATA;
@@ -3636,6 +4044,20 @@ ata_probe_ent_alloc(struct device *dev, struct ata_port_info *port)
return probe_ent;
}
+
+
+/**
+ * ata_pci_init_native_mode - Initialize native-mode driver
+ * @pdev: pci device to be initialized
+ * @port: array[2] of pointers to port info structures.
+ *
+ * Utility function which allocates and initializes an
+ * ata_probe_ent structure for a standard dual-port
+ * PIO-based IDE controller. The returned ata_probe_ent
+ * structure can be passed to ata_device_add(). The returned
+ * ata_probe_ent structure should then be freed with kfree().
+ */
+
#ifdef CONFIG_PCI
struct ata_probe_ent *
ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port)
@@ -3717,10 +4139,19 @@ ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port,
* @port_info: Information from low-level host driver
* @n_ports: Number of ports attached to host controller
*
+ * This is a helper function which can be called from a driver's
+ * xxx_init_one() probe function if the hardware uses traditional
+ * IDE taskfile registers.
+ *
+ * This function calls pci_enable_device(), reserves its register
+ * regions, sets the dma mask, enables bus master mode, and calls
+ * ata_device_add()
+ *
* LOCKING:
* Inherited from PCI layer (may sleep).
*
* RETURNS:
+ * Zero on success, negative on errno-based value on error.
*
*/
@@ -3875,10 +4306,6 @@ void ata_pci_remove_one (struct pci_dev *pdev)
}
free_irq(host_set->irq, host_set);
- if (host_set->ops->host_stop)
- host_set->ops->host_stop(host_set);
- if (host_set->mmio_base)
- iounmap(host_set->mmio_base);
for (i = 0; i < host_set->n_ports; i++) {
ap = host_set->ports[i];
@@ -3897,6 +4324,9 @@ void ata_pci_remove_one (struct pci_dev *pdev)
scsi_host_put(ap->host);
}
+ if (host_set->ops->host_stop)
+ host_set->ops->host_stop(host_set);
+
kfree(host_set);
pci_release_regions(pdev);
@@ -3940,15 +4370,6 @@ int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits)
#endif /* CONFIG_PCI */
-/**
- * ata_init -
- *
- * LOCKING:
- *
- * RETURNS:
- *
- */
-
static int __init ata_init(void)
{
ata_wq = create_workqueue("ata");
@@ -3994,6 +4415,7 @@ EXPORT_SYMBOL_GPL(ata_chk_err);
EXPORT_SYMBOL_GPL(ata_exec_command);
EXPORT_SYMBOL_GPL(ata_port_start);
EXPORT_SYMBOL_GPL(ata_port_stop);
+EXPORT_SYMBOL_GPL(ata_host_stop);
EXPORT_SYMBOL_GPL(ata_interrupt);
EXPORT_SYMBOL_GPL(ata_qc_prep);
EXPORT_SYMBOL_GPL(ata_bmdma_setup);
@@ -4014,6 +4436,7 @@ EXPORT_SYMBOL_GPL(ata_scsi_release);
EXPORT_SYMBOL_GPL(ata_host_intr);
EXPORT_SYMBOL_GPL(ata_dev_classify);
EXPORT_SYMBOL_GPL(ata_dev_id_string);
+EXPORT_SYMBOL_GPL(ata_dev_config);
EXPORT_SYMBOL_GPL(ata_scsi_simulate);
#ifdef CONFIG_PCI
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 4c96df060c3..7a4adc4c8f0 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -347,7 +347,10 @@ int ata_scsi_slave_config(struct scsi_device *sdev)
*/
if ((dev->flags & ATA_DFLAG_LBA48) &&
((dev->flags & ATA_DFLAG_LOCK_SECTORS) == 0)) {
- sdev->host->max_sectors = 2048;
+ /*
+ * do not overwrite sdev->host->max_sectors, since
+ * other drives on this host may not support LBA48
+ */
blk_queue_max_sectors(sdev->request_queue, 2048);
}
}
@@ -944,7 +947,7 @@ unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
}
/**
- * ata_scsiop_noop -
+ * ata_scsiop_noop - Command handler that simply returns success.
* @args: device IDENTIFY data / SCSI command of interest.
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
* @buflen: Response buffer length.
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index 6518226b8f8..d90430bbb0d 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -26,7 +26,7 @@
#define __LIBATA_H__
#define DRV_NAME "libata"
-#define DRV_VERSION "1.10" /* must be exactly four chars */
+#define DRV_VERSION "1.11" /* must be exactly four chars */
struct ata_scsi_args {
u16 *id;
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 42fab03ad2b..f2aff3f4042 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -798,7 +798,7 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
}
static int
-lpfc_abort_handler(struct scsi_cmnd *cmnd)
+__lpfc_abort_handler(struct scsi_cmnd *cmnd)
{
struct lpfc_hba *phba =
(struct lpfc_hba *)cmnd->device->host->hostdata[0];
@@ -918,7 +918,17 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
}
static int
-lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
+lpfc_abort_handler(struct scsi_cmnd *cmnd)
+{
+ int rc;
+ spin_lock_irq(cmnd->device->host->host_lock);
+ rc = __lpfc_abort_handler(cmnd);
+ spin_unlock_irq(cmnd->device->host->host_lock);
+ return rc;
+}
+
+static int
+__lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
{
struct Scsi_Host *shost = cmnd->device->host;
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0];
@@ -1030,11 +1040,21 @@ out:
return ret;
}
+static int
+lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
+{
+ int rc;
+ spin_lock_irq(cmnd->device->host->host_lock);
+ rc = __lpfc_reset_lun_handler(cmnd);
+ spin_unlock_irq(cmnd->device->host->host_lock);
+ return rc;
+}
+
/*
* Note: midlayer calls this function with the host_lock held
*/
static int
-lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
+__lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
{
struct Scsi_Host *shost = cmnd->device->host;
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0];
@@ -1124,6 +1144,16 @@ out:
}
static int
+lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
+{
+ int rc;
+ spin_lock_irq(cmnd->device->host->host_lock);
+ rc = __lpfc_reset_bus_handler(cmnd);
+ spin_unlock_irq(cmnd->device->host->host_lock);
+ return rc;
+}
+
+static int
lpfc_slave_alloc(struct scsi_device *sdev)
{
struct lpfc_hba *phba = (struct lpfc_hba *)sdev->host->hostdata[0];
diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c
index 3ef2a144399..edd47d1f0b1 100644
--- a/drivers/scsi/mac53c94.c
+++ b/drivers/scsi/mac53c94.c
@@ -98,16 +98,14 @@ static int mac53c94_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *
return 0;
}
-static int mac53c94_abort(struct scsi_cmnd *cmd)
-{
- return FAILED;
-}
-
static int mac53c94_host_reset(struct scsi_cmnd *cmd)
{
struct fsc_state *state = (struct fsc_state *) cmd->device->host->hostdata;
struct mac53c94_regs __iomem *regs = state->regs;
struct dbdma_regs __iomem *dma = state->dma;
+ unsigned long flags;
+
+ spin_lock_irqsave(cmd->device->host->host_lock, flags);
writel((RUN|PAUSE|FLUSH|WAKE) << 16, &dma->control);
writeb(CMD_SCSI_RESET, &regs->command); /* assert RST */
@@ -116,6 +114,8 @@ static int mac53c94_host_reset(struct scsi_cmnd *cmd)
udelay(20);
mac53c94_init(state);
writeb(CMD_NOP, &regs->command);
+
+ spin_unlock_irqrestore(cmd->device->host->host_lock, flags);
return SUCCESS;
}
@@ -416,7 +416,6 @@ static struct scsi_host_template mac53c94_template = {
.proc_name = "53c94",
.name = "53C94",
.queuecommand = mac53c94_queue,
- .eh_abort_handler = mac53c94_abort,
.eh_host_reset_handler = mac53c94_host_reset,
.can_queue = 1,
.this_id = 7,
diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
index d5fd17ef74d..92d2c8379ab 100644
--- a/drivers/scsi/mac_scsi.c
+++ b/drivers/scsi/mac_scsi.c
@@ -591,8 +591,6 @@ static Scsi_Host_Template driver_template = {
.queuecommand = macscsi_queue_command,
.eh_abort_handler = macscsi_abort,
.eh_bus_reset_handler = macscsi_bus_reset,
- .eh_device_reset_handler = macscsi_device_reset,
- .eh_host_reset_handler = macscsi_host_reset,
.can_queue = CAN_QUEUE,
.this_id = 7,
.sg_tablesize = SG_ALL,
diff --git a/drivers/scsi/mac_scsi.h b/drivers/scsi/mac_scsi.h
index 23ab2c18a01..d26e331c6c1 100644
--- a/drivers/scsi/mac_scsi.h
+++ b/drivers/scsi/mac_scsi.h
@@ -72,8 +72,6 @@
#define NCR5380_queue_command macscsi_queue_command
#define NCR5380_abort macscsi_abort
#define NCR5380_bus_reset macscsi_bus_reset
-#define NCR5380_device_reset macscsi_device_reset
-#define NCR5380_host_reset macscsi_host_reset
#define NCR5380_proc_info macscsi_proc_info
#define BOARD_NORMAL 0
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 8d707b29027..ec81532eb84 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -1938,7 +1938,7 @@ megaraid_abort(Scsi_Cmnd *cmd)
static int
-megaraid_reset(Scsi_Cmnd *cmd)
+__megaraid_reset(Scsi_Cmnd *cmd)
{
adapter_t *adapter;
megacmd_t mc;
@@ -1972,6 +1972,18 @@ megaraid_reset(Scsi_Cmnd *cmd)
return rval;
}
+static int
+megaraid_reset(Scsi_Cmnd *cmd)
+{
+ adapter_t *adapter = (adapter_t *)cmd->device->host->hostdata;
+ int rc;
+
+ spin_lock_irq(&adapter->lock);
+ rc = __megaraid_reset(cmd);
+ spin_unlock_irq(&adapter->lock);
+
+ return rc;
+}
/**
diff --git a/drivers/scsi/megaraid/mega_common.h b/drivers/scsi/megaraid/mega_common.h
index 18969a4946b..69df1a9b935 100644
--- a/drivers/scsi/megaraid/mega_common.h
+++ b/drivers/scsi/megaraid/mega_common.h
@@ -27,6 +27,7 @@
#include <linux/list.h>
#include <linux/version.h>
#include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
#include <asm/semaphore.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index 138fa481583..cbe43024627 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -10,7 +10,7 @@
* 2 of the License, or (at your option) any later version.
*
* FILE : megaraid_mbox.c
- * Version : v2.20.4.5 (Feb 03 2005)
+ * Version : v2.20.4.6 (Mar 07 2005)
*
* Authors:
* Atul Mukker <Atul.Mukker@lsil.com>
@@ -124,7 +124,7 @@ static irqreturn_t megaraid_isr(int, void *, struct pt_regs *);
static void megaraid_mbox_dpc(unsigned long);
static ssize_t megaraid_sysfs_show_app_hndl(struct class_device *, char *);
-static ssize_t megaraid_sysfs_show_ldnum(struct device *, char *);
+static ssize_t megaraid_sysfs_show_ldnum(struct device *, struct device_attribute *attr, char *);
static int megaraid_cmm_register(adapter_t *);
static int megaraid_cmm_unregister(adapter_t *);
@@ -202,7 +202,7 @@ MODULE_PARM_DESC(debug_level, "Debug level for driver (default=0)");
* ### global data ###
*/
static uint8_t megaraid_mbox_version[8] =
- { 0x02, 0x20, 0x04, 0x05, 2, 3, 20, 5 };
+ { 0x02, 0x20, 0x04, 0x06, 3, 7, 20, 5 };
/*
@@ -229,9 +229,9 @@ static struct pci_device_id pci_id_table_g[] = {
},
{
PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_PERC4_QC,
- PCI_VENDOR_ID_DELL,
- PCI_SUBSYS_ID_PERC4_QC,
+ PCI_DEVICE_ID_VERDE,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
},
{
PCI_VENDOR_ID_DELL,
@@ -271,15 +271,9 @@ static struct pci_device_id pci_id_table_g[] = {
},
{
PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_PERC4E_DC_320_2E,
- PCI_VENDOR_ID_DELL,
- PCI_SUBSYS_ID_PERC4E_DC_320_2E,
- },
- {
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_PERC4E_SC_320_1E,
- PCI_VENDOR_ID_DELL,
- PCI_SUBSYS_ID_PERC4E_SC_320_1E,
+ PCI_DEVICE_ID_DOBSON,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
},
{
PCI_VENDOR_ID_AMI,
@@ -331,36 +325,6 @@ static struct pci_device_id pci_id_table_g[] = {
},
{
PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_MEGARAID_SCSI_320_0x,
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_SUBSYS_ID_MEGARAID_SCSI_320_0x,
- },
- {
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_MEGARAID_SCSI_320_2x,
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_SUBSYS_ID_MEGARAID_SCSI_320_2x,
- },
- {
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_MEGARAID_SCSI_320_4x,
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_SUBSYS_ID_MEGARAID_SCSI_320_4x,
- },
- {
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_MEGARAID_SCSI_320_1E,
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_SUBSYS_ID_MEGARAID_SCSI_320_1E,
- },
- {
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_MEGARAID_SCSI_320_2E,
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_SUBSYS_ID_MEGARAID_SCSI_320_2E,
- },
- {
- PCI_VENDOR_ID_LSI_LOGIC,
PCI_DEVICE_ID_MEGARAID_I4_133_RAID,
PCI_VENDOR_ID_LSI_LOGIC,
PCI_SUBSYS_ID_MEGARAID_I4_133_RAID,
@@ -379,21 +343,9 @@ static struct pci_device_id pci_id_table_g[] = {
},
{
PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_MEGARAID_SATA_300_4x,
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_SUBSYS_ID_MEGARAID_SATA_300_4x,
- },
- {
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_MEGARAID_SATA_300_8x,
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_SUBSYS_ID_MEGARAID_SATA_300_8x,
- },
- {
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_INTEL_RAID_SRCU42X,
- PCI_VENDOR_ID_INTEL,
- PCI_SUBSYS_ID_INTEL_RAID_SRCU42X,
+ PCI_DEVICE_ID_LINDSAY,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
},
{
PCI_VENDOR_ID_LSI_LOGIC,
@@ -403,58 +355,10 @@ static struct pci_device_id pci_id_table_g[] = {
},
{
PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_INTEL_RAID_SRCU42E,
- PCI_VENDOR_ID_INTEL,
- PCI_SUBSYS_ID_INTEL_RAID_SRCU42E,
- },
- {
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_INTEL_RAID_SRCZCRX,
- PCI_VENDOR_ID_INTEL,
- PCI_SUBSYS_ID_INTEL_RAID_SRCZCRX,
- },
- {
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_INTEL_RAID_SRCS28X,
- PCI_VENDOR_ID_INTEL,
- PCI_SUBSYS_ID_INTEL_RAID_SRCS28X,
- },
- {
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_INTEL_RAID_SROMBU42E_ALIEF,
- PCI_VENDOR_ID_INTEL,
- PCI_SUBSYS_ID_INTEL_RAID_SROMBU42E_ALIEF,
- },
- {
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_INTEL_RAID_SROMBU42E_HARWICH,
- PCI_VENDOR_ID_INTEL,
- PCI_SUBSYS_ID_INTEL_RAID_SROMBU42E_HARWICH,
- },
- {
- PCI_VENDOR_ID_LSI_LOGIC,
PCI_DEVICE_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK,
PCI_VENDOR_ID_INTEL,
PCI_SUBSYS_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK,
},
- {
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_FSC_MEGARAID_PCI_EXPRESS_ROMB,
- PCI_SUBSYS_ID_FSC,
- PCI_SUBSYS_ID_FSC_MEGARAID_PCI_EXPRESS_ROMB,
- },
- {
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_MEGARAID_ACER_ROMB_2E,
- PCI_VENDOR_ID_AI,
- PCI_SUBSYS_ID_MEGARAID_ACER_ROMB_2E,
- },
- {
- PCI_VENDOR_ID_LSI_LOGIC,
- PCI_DEVICE_ID_MEGARAID_NEC_ROMB_2E,
- PCI_VENDOR_ID_NEC,
- PCI_SUBSYS_ID_MEGARAID_NEC_ROMB_2E,
- },
{0} /* Terminating entry */
};
MODULE_DEVICE_TABLE(pci, pci_id_table_g);
@@ -539,7 +443,8 @@ megaraid_init(void)
// register as a PCI hot-plug driver module
- if ((rval = pci_module_init(&megaraid_pci_driver_g))) {
+ rval = pci_register_driver(&megaraid_pci_driver_g);
+ if (rval < 0) {
con_log(CL_ANN, (KERN_WARNING
"megaraid: could not register hotplug support.\n"));
}
@@ -619,7 +524,7 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
// Setup the default DMA mask. This would be changed later on
// depending on hardware capabilities
- if (pci_set_dma_mask(adapter->pdev, 0xFFFFFFFF) != 0) {
+ if (pci_set_dma_mask(adapter->pdev, DMA_32BIT_MASK) != 0) {
con_log(CL_ANN, (KERN_WARNING
"megaraid: pci_set_dma_mask failed:%d\n", __LINE__));
@@ -1031,7 +936,7 @@ megaraid_init_mbox(adapter_t *adapter)
// Set the DMA mask to 64-bit. All supported controllers as capable of
// DMA in this range
- if (pci_set_dma_mask(adapter->pdev, 0xFFFFFFFFFFFFFFFFULL) != 0) {
+ if (pci_set_dma_mask(adapter->pdev, DMA_64BIT_MASK) != 0) {
con_log(CL_ANN, (KERN_WARNING
"megaraid: could not set DMA mask for 64-bit.\n"));
@@ -2661,7 +2566,7 @@ megaraid_mbox_dpc(unsigned long devp)
* aborted. All the commands issued to the F/W must complete.
**/
static int
-megaraid_abort_handler(struct scsi_cmnd *scp)
+__megaraid_abort_handler(struct scsi_cmnd *scp)
{
adapter_t *adapter;
mraid_device_t *raid_dev;
@@ -2794,6 +2699,21 @@ megaraid_abort_handler(struct scsi_cmnd *scp)
return FAILED;
}
+static int
+megaraid_abort_handler(struct scsi_cmnd *scp)
+{
+ adapter_t *adapter;
+ int rc;
+
+ adapter = SCP2ADAPTER(scp);
+
+ spin_lock_irq(adapter->host_lock);
+ rc = __megaraid_abort_handler(scp);
+ spin_unlock_irq(adapter->host_lock);
+
+ return rc;
+}
+
/**
* megaraid_reset_handler - device reset hadler for mailbox based driver
@@ -2806,7 +2726,7 @@ megaraid_abort_handler(struct scsi_cmnd *scp)
* host
**/
static int
-megaraid_reset_handler(struct scsi_cmnd *scp)
+__megaraid_reset_handler(struct scsi_cmnd *scp)
{
adapter_t *adapter;
scb_t *scb;
@@ -2927,6 +2847,18 @@ megaraid_reset_handler(struct scsi_cmnd *scp)
return rval;
}
+static int
+megaraid_reset_handler(struct scsi_cmnd *cmd)
+{
+ int rc;
+
+ spin_lock_irq(cmd->device->host->host_lock);
+ rc = __megaraid_reset_handler(cmd);
+ spin_unlock_irq(cmd->device->host->host_lock);
+
+ return rc;
+}
+
/*
* START: internal commands library
@@ -4213,7 +4145,7 @@ megaraid_sysfs_show_app_hndl(struct class_device *cdev, char *buf)
* @param buf : buffer to send data to
*/
static ssize_t
-megaraid_sysfs_show_ldnum(struct device *dev, char *buf)
+megaraid_sysfs_show_ldnum(struct device *dev, struct device_attribute *attr, char *buf)
{
struct scsi_device *sdev = to_scsi_device(dev);
adapter_t *adapter = (adapter_t *)SCSIHOST2ADAP(sdev->host);
diff --git a/drivers/scsi/megaraid/megaraid_mbox.h b/drivers/scsi/megaraid/megaraid_mbox.h
index 07510009d11..644b91bdb02 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.h
+++ b/drivers/scsi/megaraid/megaraid_mbox.h
@@ -21,8 +21,8 @@
#include "megaraid_ioctl.h"
-#define MEGARAID_VERSION "2.20.4.5"
-#define MEGARAID_EXT_VERSION "(Release Date: Thu Feb 03 12:27:22 EST 2005)"
+#define MEGARAID_VERSION "2.20.4.6"
+#define MEGARAID_EXT_VERSION "(Release Date: Mon Mar 07 12:27:22 EST 2005)"
/*
@@ -37,8 +37,7 @@
#define PCI_DEVICE_ID_PERC4_DC 0x1960
#define PCI_SUBSYS_ID_PERC4_DC 0x0518
-#define PCI_DEVICE_ID_PERC4_QC 0x0407
-#define PCI_SUBSYS_ID_PERC4_QC 0x0531
+#define PCI_DEVICE_ID_VERDE 0x0407
#define PCI_DEVICE_ID_PERC4_DI_EVERGLADES 0x000F
#define PCI_SUBSYS_ID_PERC4_DI_EVERGLADES 0x014A
@@ -58,11 +57,7 @@
#define PCI_DEVICE_ID_PERC4E_DI_GUADALUPE 0x0013
#define PCI_SUBSYS_ID_PERC4E_DI_GUADALUPE 0x0170
-#define PCI_DEVICE_ID_PERC4E_DC_320_2E 0x0408
-#define PCI_SUBSYS_ID_PERC4E_DC_320_2E 0x0002
-
-#define PCI_DEVICE_ID_PERC4E_SC_320_1E 0x0408
-#define PCI_SUBSYS_ID_PERC4E_SC_320_1E 0x0001
+#define PCI_DEVICE_ID_DOBSON 0x0408
#define PCI_DEVICE_ID_MEGARAID_SCSI_320_0 0x1960
#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_0 0xA520
@@ -73,21 +68,6 @@
#define PCI_DEVICE_ID_MEGARAID_SCSI_320_2 0x1960
#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_2 0x0518
-#define PCI_DEVICE_ID_MEGARAID_SCSI_320_0x 0x0407
-#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_0x 0x0530
-
-#define PCI_DEVICE_ID_MEGARAID_SCSI_320_2x 0x0407
-#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_2x 0x0532
-
-#define PCI_DEVICE_ID_MEGARAID_SCSI_320_4x 0x0407
-#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_4x 0x0531
-
-#define PCI_DEVICE_ID_MEGARAID_SCSI_320_1E 0x0408
-#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_1E 0x0001
-
-#define PCI_DEVICE_ID_MEGARAID_SCSI_320_2E 0x0408
-#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_2E 0x0002
-
#define PCI_DEVICE_ID_MEGARAID_I4_133_RAID 0x1960
#define PCI_SUBSYS_ID_MEGARAID_I4_133_RAID 0x0522
@@ -97,52 +77,18 @@
#define PCI_DEVICE_ID_MEGARAID_SATA_150_6 0x1960
#define PCI_SUBSYS_ID_MEGARAID_SATA_150_6 0x0523
-#define PCI_DEVICE_ID_MEGARAID_SATA_300_4x 0x0409
-#define PCI_SUBSYS_ID_MEGARAID_SATA_300_4x 0x3004
-
-#define PCI_DEVICE_ID_MEGARAID_SATA_300_8x 0x0409
-#define PCI_SUBSYS_ID_MEGARAID_SATA_300_8x 0x3008
-
-#define PCI_DEVICE_ID_INTEL_RAID_SRCU42X 0x0407
-#define PCI_SUBSYS_ID_INTEL_RAID_SRCU42X 0x0532
+#define PCI_DEVICE_ID_LINDSAY 0x0409
#define PCI_DEVICE_ID_INTEL_RAID_SRCS16 0x1960
#define PCI_SUBSYS_ID_INTEL_RAID_SRCS16 0x0523
-#define PCI_DEVICE_ID_INTEL_RAID_SRCU42E 0x0408
-#define PCI_SUBSYS_ID_INTEL_RAID_SRCU42E 0x0002
-
-#define PCI_DEVICE_ID_INTEL_RAID_SRCZCRX 0x0407
-#define PCI_SUBSYS_ID_INTEL_RAID_SRCZCRX 0x0530
-
-#define PCI_DEVICE_ID_INTEL_RAID_SRCS28X 0x0409
-#define PCI_SUBSYS_ID_INTEL_RAID_SRCS28X 0x3008
-
-#define PCI_DEVICE_ID_INTEL_RAID_SROMBU42E_ALIEF 0x0408
-#define PCI_SUBSYS_ID_INTEL_RAID_SROMBU42E_ALIEF 0x3431
-
-#define PCI_DEVICE_ID_INTEL_RAID_SROMBU42E_HARWICH 0x0408
-#define PCI_SUBSYS_ID_INTEL_RAID_SROMBU42E_HARWICH 0x3499
-
#define PCI_DEVICE_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK 0x1960
#define PCI_SUBSYS_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK 0x0520
-#define PCI_DEVICE_ID_FSC_MEGARAID_PCI_EXPRESS_ROMB 0x0408
-#define PCI_SUBSYS_ID_FSC_MEGARAID_PCI_EXPRESS_ROMB 0x1065
-
-#define PCI_DEVICE_ID_MEGARAID_ACER_ROMB_2E 0x0408
-#define PCI_SUBSYS_ID_MEGARAID_ACER_ROMB_2E 0x004D
-
#define PCI_SUBSYS_ID_PERC3_QC 0x0471
#define PCI_SUBSYS_ID_PERC3_DC 0x0493
#define PCI_SUBSYS_ID_PERC3_SC 0x0475
-#define PCI_DEVICE_ID_MEGARAID_NEC_ROMB_2E 0x0408
-#define PCI_SUBSYS_ID_MEGARAID_NEC_ROMB_2E 0x8287
-
-#ifndef PCI_SUBSYS_ID_FSC
-#define PCI_SUBSYS_ID_FSC 0x1734
-#endif
#define MBOX_MAX_SCSI_CMDS 128 // number of cmds reserved for kernel
#define MBOX_MAX_USER_CMDS 32 // number of cmds for applications
diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c
index 9f1b550713e..37d110e864c 100644
--- a/drivers/scsi/megaraid/megaraid_mm.c
+++ b/drivers/scsi/megaraid/megaraid_mm.c
@@ -10,13 +10,12 @@
* 2 of the License, or (at your option) any later version.
*
* FILE : megaraid_mm.c
- * Version : v2.20.2.5 (Jan 21 2005)
+ * Version : v2.20.2.6 (Mar 7 2005)
*
* Common management module
*/
#include "megaraid_mm.h"
-#include <linux/smp_lock.h>
// Entry points for char node driver
@@ -61,7 +60,7 @@ EXPORT_SYMBOL(mraid_mm_unregister_adp);
EXPORT_SYMBOL(mraid_mm_adapter_app_handle);
static int majorno;
-static uint32_t drvr_ver = 0x02200201;
+static uint32_t drvr_ver = 0x02200206;
static int adapters_count_g;
static struct list_head adapters_list_g;
@@ -1231,9 +1230,9 @@ mraid_mm_compat_ioctl(struct file *filep, unsigned int cmd,
unsigned long arg)
{
int err;
- lock_kernel();
+
err = mraid_mm_ioctl(NULL, filep, cmd, arg);
- unlock_kernel();
+
return err;
}
#endif
diff --git a/drivers/scsi/megaraid/megaraid_mm.h b/drivers/scsi/megaraid/megaraid_mm.h
index 948a0012ab8..7e36c46e7c4 100644
--- a/drivers/scsi/megaraid/megaraid_mm.h
+++ b/drivers/scsi/megaraid/megaraid_mm.h
@@ -29,9 +29,9 @@
#include "megaraid_ioctl.h"
-#define LSI_COMMON_MOD_VERSION "2.20.2.5"
+#define LSI_COMMON_MOD_VERSION "2.20.2.6"
#define LSI_COMMON_MOD_EXT_VERSION \
- "(Release Date: Fri Jan 21 00:01:03 EST 2005)"
+ "(Release Date: Mon Mar 7 00:01:03 EST 2005)"
#define LSI_DBGLVL dbglevel
diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c
index f6da46d672f..b05737ae5ef 100644
--- a/drivers/scsi/mesh.c
+++ b/drivers/scsi/mesh.c
@@ -1715,9 +1715,12 @@ static int mesh_host_reset(struct scsi_cmnd *cmd)
struct mesh_state *ms = (struct mesh_state *) cmd->device->host->hostdata;
volatile struct mesh_regs __iomem *mr = ms->mesh;
volatile struct dbdma_regs __iomem *md = ms->dma;
+ unsigned long flags;
printk(KERN_DEBUG "mesh_host_reset\n");
+ spin_lock_irqsave(ms->host->host_lock, flags);
+
/* Reset the controller & dbdma channel */
out_le32(&md->control, (RUN|PAUSE|FLUSH|WAKE) << 16); /* stop dma */
out_8(&mr->exception, 0xff); /* clear all exception bits */
@@ -1739,6 +1742,7 @@ static int mesh_host_reset(struct scsi_cmnd *cmd)
/* Complete pending commands */
handle_reset(ms);
+ spin_unlock_irqrestore(ms->host->host_lock, flags);
return SUCCESS;
}
diff --git a/drivers/scsi/mvme147.c b/drivers/scsi/mvme147.c
index e73b33f293a..2fb31ee6d9f 100644
--- a/drivers/scsi/mvme147.c
+++ b/drivers/scsi/mvme147.c
@@ -116,7 +116,14 @@ int mvme147_detect(Scsi_Host_Template *tpnt)
static int mvme147_bus_reset(Scsi_Cmnd *cmd)
{
/* FIXME perform bus-specific reset */
+
+ /* FIXME 2: kill this function, and let midlayer fallback to
+ the same result, calling wd33c93_host_reset() */
+
+ spin_lock_irq(cmd->device->host->host_lock);
wd33c93_host_reset(cmd);
+ spin_unlock_irq(cmd->device->host->host_lock);
+
return SUCCESS;
}
diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
index d28c0d99c34..5159ceea319 100644
--- a/drivers/scsi/nsp32.c
+++ b/drivers/scsi/nsp32.c
@@ -294,7 +294,6 @@ static struct scsi_host_template nsp32_template = {
.this_id = NSP32_HOST_SCSIID,
.use_clustering = DISABLE_CLUSTERING,
.eh_abort_handler = nsp32_eh_abort,
-/* .eh_device_reset_handler = NULL, */
.eh_bus_reset_handler = nsp32_eh_bus_reset,
.eh_host_reset_handler = nsp32_eh_host_reset,
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74))
@@ -2988,6 +2987,8 @@ static int nsp32_eh_bus_reset(struct scsi_cmnd *SCpnt)
nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
unsigned int base = SCpnt->device->host->io_port;
+ spin_lock_irq(SCpnt->device->host->host_lock);
+
nsp32_msg(KERN_INFO, "Bus Reset");
nsp32_dbg(NSP32_DEBUG_BUSRESET, "SCpnt=0x%x", SCpnt);
@@ -2995,6 +2996,7 @@ static int nsp32_eh_bus_reset(struct scsi_cmnd *SCpnt)
nsp32_do_bus_reset(data);
nsp32_write2(base, IRQ_CONTROL, 0);
+ spin_unlock_irq(SCpnt->device->host->host_lock);
return SUCCESS; /* SCSI bus reset is succeeded at any time. */
}
@@ -3049,11 +3051,14 @@ static int nsp32_eh_host_reset(struct scsi_cmnd *SCpnt)
nsp32_msg(KERN_INFO, "Host Reset");
nsp32_dbg(NSP32_DEBUG_BUSRESET, "SCpnt=0x%x", SCpnt);
+ spin_lock_irq(SCpnt->device->host->host_lock);
+
nsp32hw_init(data);
nsp32_write2(base, IRQ_CONTROL, IRQ_CONTROL_ALL_IRQ_MASK);
nsp32_do_bus_reset(data);
nsp32_write2(base, IRQ_CONTROL, 0);
+ spin_unlock_irq(SCpnt->device->host->host_lock);
return SUCCESS; /* Host reset is succeeded at any time. */
}
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index c585c7bef24..89a4a0615c2 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -5608,13 +5608,13 @@ static ssize_t osst_filemark_cnt_show(struct class_device *class_dev, char *buf)
CLASS_DEVICE_ATTR(file_count, S_IRUGO, osst_filemark_cnt_show, NULL);
-static struct class_simple * osst_sysfs_class;
+static struct class *osst_sysfs_class;
static int osst_sysfs_valid = 0;
static void osst_sysfs_init(void)
{
- osst_sysfs_class = class_simple_create(THIS_MODULE, "onstream_tape");
+ osst_sysfs_class = class_create(THIS_MODULE, "onstream_tape");
if ( IS_ERR(osst_sysfs_class) )
printk(KERN_WARNING "osst :W: Unable to register sysfs class\n");
else
@@ -5627,7 +5627,7 @@ static void osst_sysfs_add(dev_t dev, struct device *device, struct osst_tape *
if (!osst_sysfs_valid) return;
- osst_class_member = class_simple_device_add(osst_sysfs_class, dev, device, "%s", name);
+ osst_class_member = class_device_create(osst_sysfs_class, dev, device, "%s", name);
if (IS_ERR(osst_class_member)) {
printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
return;
@@ -5645,13 +5645,13 @@ static void osst_sysfs_destroy(dev_t dev)
{
if (!osst_sysfs_valid) return;
- class_simple_device_remove(dev);
+ class_device_destroy(osst_sysfs_class, dev);
}
static void osst_sysfs_cleanup(void)
{
if (osst_sysfs_valid) {
- class_simple_destroy(osst_sysfs_class);
+ class_destroy(osst_sysfs_class);
osst_sysfs_valid = 0;
}
}
diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c
index 7976947c032..363e0ebd4a3 100644
--- a/drivers/scsi/pas16.c
+++ b/drivers/scsi/pas16.c
@@ -621,8 +621,6 @@ static Scsi_Host_Template driver_template = {
.queuecommand = pas16_queue_command,
.eh_abort_handler = pas16_abort,
.eh_bus_reset_handler = pas16_bus_reset,
- .eh_device_reset_handler = pas16_device_reset,
- .eh_host_reset_handler = pas16_host_reset,
.bios_param = pas16_biosparam,
.can_queue = CAN_QUEUE,
.this_id = 7,
diff --git a/drivers/scsi/pas16.h b/drivers/scsi/pas16.h
index 58d4d67aed2..65ce1cc40d9 100644
--- a/drivers/scsi/pas16.h
+++ b/drivers/scsi/pas16.h
@@ -120,8 +120,6 @@ static int pas16_biosparam(struct scsi_device *, struct block_device *,
static int pas16_detect(Scsi_Host_Template *);
static int pas16_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
static int pas16_bus_reset(Scsi_Cmnd *);
-static int pas16_host_reset(Scsi_Cmnd *);
-static int pas16_device_reset(Scsi_Cmnd *);
#ifndef CMD_PER_LUN
#define CMD_PER_LUN 2
@@ -164,9 +162,7 @@ static int pas16_device_reset(Scsi_Cmnd *);
#define do_NCR5380_intr do_pas16_intr
#define NCR5380_queue_command pas16_queue_command
#define NCR5380_abort pas16_abort
-#define NCR5380_device_reset pas16_device_reset
#define NCR5380_bus_reset pas16_bus_reset
-#define NCR5380_host_reset pas16_host_reset
#define NCR5380_proc_info pas16_proc_info
/* 15 14 12 10 7 5 3
diff --git a/drivers/scsi/pci2000.c b/drivers/scsi/pci2000.c
deleted file mode 100644
index 377a4666b56..00000000000
--- a/drivers/scsi/pci2000.c
+++ /dev/null
@@ -1,836 +0,0 @@
-/****************************************************************************
- * Perceptive Solutions, Inc. PCI-2000 device driver for Linux.
- *
- * pci2000.c - Linux Host Driver for PCI-2000 IntelliCache SCSI Adapters
- *
- * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
- * All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that redistributions of source
- * code retain the above copyright notice and this comment without
- * modification.
- *
- * Technical updates and product information at:
- * http://www.psidisk.com
- *
- * Please send questions, comments, bug reports to:
- * tech@psidisk.com Technical Support
- *
- *
- * Revisions 1.10 Jan-21-1999
- * - Fixed sign on message to reflect proper controller name.
- * - Added support for RAID status monitoring and control.
- *
- * Revisions 1.11 Mar-22-1999
- * - Fixed control timeout to not lock up the entire system if
- * controller goes offline completely.
- *
- * Revisions 1.12 Mar-26-1999
- * - Fixed spinlock and PCI configuration.
- *
- * Revisions 1.20 Mar-27-2000
- * - Added support for dynamic DMA
- *
- ****************************************************************************/
-#define PCI2000_VERSION "1.20"
-
-#include <linux/blkdev.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/pci.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/spinlock.h>
-
-#include <asm/dma.h>
-#include <asm/system.h>
-#include <asm/io.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "pci2000.h"
-#include "psi_roy.h"
-
-
-//#define DEBUG 1
-
-#ifdef DEBUG
-#define DEB(x) x
-#define STOP_HERE {int st;for(st=0;st<100;st++){st=1;}}
-#else
-#define DEB(x)
-#define STOP_HERE
-#endif
-
-typedef struct
- {
- unsigned int address;
- unsigned int length;
- } SCATGATH, *PSCATGATH;
-
-typedef struct
- {
- Scsi_Cmnd *SCpnt;
- PSCATGATH scatGath;
- dma_addr_t scatGathDma;
- UCHAR *cdb;
- dma_addr_t cdbDma;
- UCHAR tag;
- } DEV2000, *PDEV2000;
-
-typedef struct
- {
- ULONG basePort;
- ULONG mb0;
- ULONG mb1;
- ULONG mb2;
- ULONG mb3;
- ULONG mb4;
- ULONG cmd;
- ULONG tag;
- ULONG irqOwned;
- struct pci_dev *pdev;
- DEV2000 dev[MAX_BUS][MAX_UNITS];
- } ADAPTER2000, *PADAPTER2000;
-
-#define HOSTDATA(host) ((PADAPTER2000)&host->hostdata)
-#define consistentLen (MAX_BUS * MAX_UNITS * (16 * sizeof (SCATGATH) + MAX_COMMAND_SIZE))
-
-
-static struct Scsi_Host *PsiHost[MAXADAPTER] = {NULL,}; // One for each adapter
-static int NumAdapters = 0;
-/****************************************************************
- * Name: WaitReady :LOCAL
- *
- * Description: Wait for controller ready.
- *
- * Parameters: padapter - Pointer adapter data structure.
- *
- * Returns: TRUE on not ready.
- *
- ****************************************************************/
-static int WaitReady (PADAPTER2000 padapter)
- {
- ULONG z;
-
- for ( z = 0; z < (TIMEOUT_COMMAND * 4); z++ )
- {
- if ( !inb_p (padapter->cmd) )
- return FALSE;
- udelay (250);
- };
- return TRUE;
- }
-/****************************************************************
- * Name: WaitReadyLong :LOCAL
- *
- * Description: Wait for controller ready.
- *
- * Parameters: padapter - Pointer adapter data structure.
- *
- * Returns: TRUE on not ready.
- *
- ****************************************************************/
-static int WaitReadyLong (PADAPTER2000 padapter)
- {
- ULONG z;
-
- for ( z = 0; z < (5000 * 4); z++ )
- {
- if ( !inb_p (padapter->cmd) )
- return FALSE;
- udelay (250);
- };
- return TRUE;
- }
-/****************************************************************
- * Name: OpDone :LOCAL
- *
- * Description: Clean up operation and issue done to caller.
- *
- * Parameters: SCpnt - Pointer to SCSI command structure.
- * status - Caller status.
- *
- * Returns: Nothing.
- *
- ****************************************************************/
-static void OpDone (Scsi_Cmnd *SCpnt, ULONG status)
- {
- SCpnt->result = status;
- SCpnt->scsi_done (SCpnt);
- }
-/****************************************************************
- * Name: Command :LOCAL
- *
- * Description: Issue queued command to the PCI-2000.
- *
- * Parameters: padapter - Pointer to adapter information structure.
- * cmd - PCI-2000 command byte.
- *
- * Returns: Non-zero command tag if operation is accepted.
- *
- ****************************************************************/
-static UCHAR Command (PADAPTER2000 padapter, UCHAR cmd)
- {
- outb_p (cmd, padapter->cmd);
- if ( WaitReady (padapter) )
- return 0;
-
- if ( inw_p (padapter->mb0) )
- return 0;
-
- return inb_p (padapter->mb1);
- }
-/****************************************************************
- * Name: BuildSgList :LOCAL
- *
- * Description: Build the scatter gather list for controller.
- *
- * Parameters: SCpnt - Pointer to SCSI command structure.
- * padapter - Pointer to adapter information structure.
- * pdev - Pointer to adapter device structure.
- *
- * Returns: Non-zero in not scatter gather.
- *
- ****************************************************************/
-static int BuildSgList (Scsi_Cmnd *SCpnt, PADAPTER2000 padapter, PDEV2000 pdev)
- {
- int z;
- int zc;
- struct scatterlist *sg;
-
- if ( SCpnt->use_sg )
- {
- sg = (struct scatterlist *)SCpnt->request_buffer;
- zc = pci_map_sg (padapter->pdev, sg, SCpnt->use_sg, SCpnt->sc_data_direction);
- for ( z = 0; z < zc; z++ )
- {
- pdev->scatGath[z].address = cpu_to_le32 (sg_dma_address (sg));
- pdev->scatGath[z].length = cpu_to_le32 (sg_dma_len (sg++));
- }
- outl (pdev->scatGathDma, padapter->mb2);
- outl ((zc << 24) | SCpnt->request_bufflen, padapter->mb3);
- return FALSE;
- }
- if ( !SCpnt->request_bufflen)
- {
- outl (0, padapter->mb2);
- outl (0, padapter->mb3);
- return TRUE;
- }
- SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev,
- SCpnt->request_buffer, SCpnt->request_bufflen,
- SCpnt->sc_data_direction);
- outl (SCpnt->SCp.have_data_in, padapter->mb2);
- outl (SCpnt->request_bufflen, padapter->mb3);
- return TRUE;
- }
-/*********************************************************************
- * Name: PsiRaidCmd
- *
- * Description: Execute a simple command.
- *
- * Parameters: padapter - Pointer to adapter control structure.
- * cmd - Roy command byte.
- *
- * Returns: Return error status.
- *
- ********************************************************************/
-static int PsiRaidCmd (PADAPTER2000 padapter, char cmd)
- {
- if ( WaitReady (padapter) ) // test for command register ready
- return DID_TIME_OUT;
- outb_p (cmd, padapter->cmd); // issue command
- if ( WaitReadyLong (padapter) ) // wait for adapter ready
- return DID_TIME_OUT;
- return DID_OK;
- }
-/****************************************************************
- * Name: Irq_Handler :LOCAL
- *
- * Description: Interrupt handler.
- *
- * Parameters: irq - Hardware IRQ number.
- * dev_id -
- * regs -
- *
- * Returns: TRUE if drive is not ready in time.
- *
- ****************************************************************/
-static irqreturn_t Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
- {
- struct Scsi_Host *shost = NULL; // Pointer to host data block
- PADAPTER2000 padapter; // Pointer to adapter control structure
- PDEV2000 pdev;
- Scsi_Cmnd *SCpnt;
- UCHAR tag = 0;
- UCHAR tag0;
- ULONG error;
- int pun;
- int bus;
- int z;
- unsigned long flags;
- int handled = 0;
-
- DEB(printk ("\npci2000 received interrupt "));
- for ( z = 0; z < NumAdapters; z++ ) // scan for interrupt to process
- {
- if ( PsiHost[z]->irq == (UCHAR)(irq & 0xFF) )
- {
- tag = inb_p (HOSTDATA(PsiHost[z])->tag);
- if ( tag )
- {
- shost = PsiHost[z];
- break;
- }
- }
- }
-
- if ( !shost )
- {
- DEB (printk ("\npci2000: not my interrupt"));
- goto out;
- }
-
- handled = 1;
- spin_lock_irqsave(shost->host_lock, flags);
- padapter = HOSTDATA(shost);
-
- tag0 = tag & 0x7F; // mask off the error bit
- for ( bus = 0; bus < MAX_BUS; bus++ ) // scan the busses
- {
- for ( pun = 0; pun < MAX_UNITS; pun++ ) // scan the targets
- {
- pdev = &padapter->dev[bus][pun];
- if ( !pdev->tag )
- continue;
- if ( pdev->tag == tag0 ) // is this it?
- {
- pdev->tag = 0;
- SCpnt = pdev->SCpnt;
- goto unmapProceed;
- }
- }
- }
-
- outb_p (0xFF, padapter->tag); // clear the op interrupt
- outb_p (CMD_DONE, padapter->cmd); // complete the op
- goto irq_return; // done, but, with what?
-
-unmapProceed:;
- if ( !bus )
- {
- switch ( SCpnt->cmnd[0] )
- {
- case SCSIOP_TEST_UNIT_READY:
- pci_unmap_single (padapter->pdev, SCpnt->SCp.have_data_in, sizeof (SCpnt->sense_buffer), PCI_DMA_FROMDEVICE);
- goto irqProceed;
- case SCSIOP_READ_CAPACITY:
- pci_unmap_single (padapter->pdev, SCpnt->SCp.have_data_in, 8, PCI_DMA_FROMDEVICE);
- goto irqProceed;
- case SCSIOP_VERIFY:
- case SCSIOP_START_STOP_UNIT:
- case SCSIOP_MEDIUM_REMOVAL:
- goto irqProceed;
- }
- }
- if ( SCpnt->SCp.have_data_in )
- pci_unmap_single (padapter->pdev, SCpnt->SCp.have_data_in, SCpnt->request_bufflen, SCpnt->sc_data_direction);
- else
- {
- if ( SCpnt->use_sg )
- pci_unmap_sg (padapter->pdev, (struct scatterlist *)SCpnt->request_buffer, SCpnt->use_sg, SCpnt->sc_data_direction);
- }
-
-irqProceed:;
- if ( tag & ERR08_TAGGED ) // is there an error here?
- {
- if ( WaitReady (padapter) )
- {
- OpDone (SCpnt, DID_TIME_OUT << 16);
- goto irq_return;
- }
-
- outb_p (tag0, padapter->mb0); // get real error code
- outb_p (CMD_ERROR, padapter->cmd);
- if ( WaitReady (padapter) ) // wait for controller to suck up the op
- {
- OpDone (SCpnt, DID_TIME_OUT << 16);
- goto irq_return;
- }
-
- error = inl (padapter->mb0); // get error data
- outb_p (0xFF, padapter->tag); // clear the op interrupt
- outb_p (CMD_DONE, padapter->cmd); // complete the op
-
- DEB (printk ("status: %lX ", error));
- if ( error == 0x00020002 ) // is this error a check condition?
- {
- if ( bus ) // are we doint SCSI commands?
- {
- OpDone (SCpnt, (DID_OK << 16) | 2);
- goto irq_return;
- }
- if ( *SCpnt->cmnd == SCSIOP_TEST_UNIT_READY )
- OpDone (SCpnt, (DRIVER_SENSE << 24) | (DID_OK << 16) | 2); // test caller we have sense data too
- else
- OpDone (SCpnt, DID_ERROR << 16);
- goto irq_return;
- }
- OpDone (SCpnt, DID_ERROR << 16);
- goto irq_return;
- }
-
- outb_p (0xFF, padapter->tag); // clear the op interrupt
- outb_p (CMD_DONE, padapter->cmd); // complete the op
- OpDone (SCpnt, DID_OK << 16);
-
-irq_return:
- spin_unlock_irqrestore(shost->host_lock, flags);
-out:
- return IRQ_RETVAL(handled);
-}
-/****************************************************************
- * Name: Pci2000_QueueCommand
- *
- * Description: Process a queued command from the SCSI manager.
- *
- * Parameters: SCpnt - Pointer to SCSI command structure.
- * done - Pointer to done function to call.
- *
- * Returns: Status code.
- *
- ****************************************************************/
-int Pci2000_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
- {
- UCHAR *cdb = (UCHAR *)SCpnt->cmnd; // Pointer to SCSI CDB
- PADAPTER2000 padapter = HOSTDATA(SCpnt->device->host); // Pointer to adapter control structure
- int rc = -1; // command return code
- UCHAR bus = SCpnt->device->channel;
- UCHAR pun = SCpnt->device->id;
- UCHAR lun = SCpnt->device->lun;
- UCHAR cmd;
- PDEV2000 pdev = &padapter->dev[bus][pun];
-
- if ( !done )
- {
- printk("pci2000_queuecommand: %02X: done can't be NULL\n", *cdb);
- return 0;
- }
-
- SCpnt->scsi_done = done;
- SCpnt->SCp.have_data_in = 0;
- pdev->SCpnt = SCpnt; // Save this command data
-
- if ( WaitReady (padapter) )
- {
- rc = DID_ERROR;
- goto finished;
- }
-
- outw_p (pun | (lun << 8), padapter->mb0);
-
- if ( bus )
- {
- DEB (if(*cdb) printk ("\nCDB: %X- %X %X %X %X %X %X %X %X %X %X ", SCpnt->cmd_len, cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9]));
- DEB (if(*cdb) printk ("\ntimeout_per_command: %d, timeout_total: %d, timeout: %d", SCpnt->timeout_per_command,
- SCpnt->timeout_total, SCpnt->timeout));
- outl (SCpnt->timeout_per_command, padapter->mb1);
- outb_p (CMD_SCSI_TIMEOUT, padapter->cmd);
- if ( WaitReady (padapter) )
- {
- rc = DID_ERROR;
- goto finished;
- }
-
- outw_p (pun | (lun << 8), padapter->mb0);
- outw_p (SCpnt->cmd_len << 8, padapter->mb0 + 2);
- memcpy (pdev->cdb, cdb, MAX_COMMAND_SIZE);
-
- outl (pdev->cdbDma, padapter->mb1);
- if ( BuildSgList (SCpnt, padapter, pdev) )
- cmd = CMD_SCSI_THRU;
- else
- cmd = CMD_SCSI_THRU_SG;
- if ( (pdev->tag = Command (padapter, cmd)) == 0 )
- rc = DID_TIME_OUT;
- goto finished;
- }
- else
- {
- if ( lun )
- {
- rc = DID_BAD_TARGET;
- goto finished;
- }
- }
-
- switch ( *cdb )
- {
- case SCSIOP_INQUIRY: // inquiry CDB
- if ( cdb[2] == SC_MY_RAID )
- {
- switch ( cdb[3] )
- {
- case MY_SCSI_REBUILD:
- OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_REBUILD) << 16);
- return 0;
- case MY_SCSI_ALARMMUTE:
- OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_MUTE) << 16);
- return 0;
- case MY_SCSI_DEMOFAIL:
- OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_FAIL) << 16);
- return 0;
- default:
- if ( SCpnt->use_sg )
- {
- rc = DID_ERROR;
- goto finished;
- }
- else
- {
- SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer, SCpnt->request_bufflen,
- SCpnt->sc_data_direction);
- outl (SCpnt->SCp.have_data_in, padapter->mb2);
- }
- outl (cdb[5], padapter->mb0);
- outl (cdb[3], padapter->mb3);
- cmd = CMD_DASD_RAID_RQ;
- break;
- }
- break;
- }
-
- if ( SCpnt->use_sg )
- {
- SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev,
- ((struct scatterlist *)SCpnt->request_buffer)->address,
- SCpnt->request_bufflen,
- SCpnt->sc_data_direction);
- }
- else
- {
- SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer,
- SCpnt->request_bufflen,
- SCpnt->sc_data_direction);
- }
- outl (SCpnt->SCp.have_data_in, padapter->mb2);
- outl (SCpnt->request_bufflen, padapter->mb3);
- cmd = CMD_DASD_SCSI_INQ;
- break;
-
- case SCSIOP_TEST_UNIT_READY: // test unit ready CDB
- SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->sense_buffer, sizeof (SCpnt->sense_buffer), PCI_DMA_FROMDEVICE);
- outl (SCpnt->SCp.have_data_in, padapter->mb2);
- outl (sizeof (SCpnt->sense_buffer), padapter->mb3);
- cmd = CMD_TEST_READY;
- break;
-
- case SCSIOP_READ_CAPACITY: // read capacity CDB
- if ( SCpnt->use_sg )
- {
- SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, ((struct scatterlist *)(SCpnt->request_buffer))->address,
- 8, PCI_DMA_FROMDEVICE);
- }
- else
- SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer, 8, PCI_DMA_FROMDEVICE);
- outl (SCpnt->SCp.have_data_in, padapter->mb2);
- outl (8, padapter->mb3);
- cmd = CMD_DASD_CAP;
- break;
- case SCSIOP_VERIFY: // verify CDB
- outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2);
- outl (XSCSI2LONG (&cdb[2]), padapter->mb1);
- cmd = CMD_READ_SG;
- break;
- case SCSIOP_READ: // read10 CDB
- outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2);
- outl (XSCSI2LONG (&cdb[2]), padapter->mb1);
- if ( BuildSgList (SCpnt, padapter, pdev) )
- cmd = CMD_READ;
- else
- cmd = CMD_READ_SG;
- break;
- case SCSIOP_READ6: // read6 CDB
- outw_p (cdb[4], padapter->mb0 + 2);
- outl ((SCSI2LONG (&cdb[1])) & 0x001FFFFF, padapter->mb1);
- if ( BuildSgList (SCpnt, padapter, pdev) )
- cmd = CMD_READ;
- else
- cmd = CMD_READ_SG;
- break;
- case SCSIOP_WRITE: // write10 CDB
- outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2);
- outl (XSCSI2LONG (&cdb[2]), padapter->mb1);
- if ( BuildSgList (SCpnt, padapter, pdev) )
- cmd = CMD_WRITE;
- else
- cmd = CMD_WRITE_SG;
- break;
- case SCSIOP_WRITE6: // write6 CDB
- outw_p (cdb[4], padapter->mb0 + 2);
- outl ((SCSI2LONG (&cdb[1])) & 0x001FFFFF, padapter->mb1);
- if ( BuildSgList (SCpnt, padapter, pdev) )
- cmd = CMD_WRITE;
- else
- cmd = CMD_WRITE_SG;
- break;
- case SCSIOP_START_STOP_UNIT:
- cmd = CMD_EJECT_MEDIA;
- break;
- case SCSIOP_MEDIUM_REMOVAL:
- switch ( cdb[4] )
- {
- case 0:
- cmd = CMD_UNLOCK_DOOR;
- break;
- case 1:
- cmd = CMD_LOCK_DOOR;
- break;
- default:
- cmd = 0;
- break;
- }
- if ( cmd )
- break;
- default:
- DEB (printk ("pci2000_queuecommand: Unsupported command %02X\n", *cdb));
- OpDone (SCpnt, DID_ERROR << 16);
- return 0;
- }
-
- if ( (pdev->tag = Command (padapter, cmd)) == 0 )
- rc = DID_TIME_OUT;
-finished:;
- if ( rc != -1 )
- OpDone (SCpnt, rc << 16);
- return 0;
- }
-/****************************************************************
- * Name: Pci2000_Detect
- *
- * Description: Detect and initialize our boards.
- *
- * Parameters: tpnt - Pointer to SCSI host template structure.
- *
- * Returns: Number of adapters installed.
- *
- ****************************************************************/
-int Pci2000_Detect (Scsi_Host_Template *tpnt)
- {
- int found = 0;
- int installed = 0;
- struct Scsi_Host *pshost;
- PADAPTER2000 padapter;
- int z, zz;
- int setirq;
- struct pci_dev *pdev = NULL;
- UCHAR *consistent;
- dma_addr_t consistentDma;
-
- while ( (pdev = pci_find_device (VENDOR_PSI, DEVICE_ROY_1, pdev)) != NULL )
- {
- if (pci_enable_device(pdev))
- continue;
- pshost = scsi_register (tpnt, sizeof(ADAPTER2000));
- if(pshost == NULL)
- continue;
- padapter = HOSTDATA(pshost);
-
- padapter->basePort = pci_resource_start (pdev, 1);
- DEB (printk ("\nBase Regs = %#04X", padapter->basePort)); // get the base I/O port address
- padapter->mb0 = padapter->basePort + RTR_MAILBOX; // get the 32 bit mail boxes
- padapter->mb1 = padapter->basePort + RTR_MAILBOX + 4;
- padapter->mb2 = padapter->basePort + RTR_MAILBOX + 8;
- padapter->mb3 = padapter->basePort + RTR_MAILBOX + 12;
- padapter->mb4 = padapter->basePort + RTR_MAILBOX + 16;
- padapter->cmd = padapter->basePort + RTR_LOCAL_DOORBELL; // command register
- padapter->tag = padapter->basePort + RTR_PCI_DOORBELL; // tag/response register
- padapter->pdev = pdev;
-
- if ( WaitReady (padapter) )
- goto unregister;
- outb_p (0x84, padapter->mb0);
- outb_p (CMD_SPECIFY, padapter->cmd);
- if ( WaitReady (padapter) )
- goto unregister;
-
- consistent = pci_alloc_consistent (pdev, consistentLen, &consistentDma);
- if ( !consistent )
- {
- printk ("Unable to allocate DMA memory for PCI-2000 controller.\n");
- goto unregister;
- }
-
- scsi_set_device(pshost, &pdev->dev);
- pshost->irq = pdev->irq;
- setirq = 1;
- padapter->irqOwned = 0;
- for ( z = 0; z < installed; z++ ) // scan for shared interrupts
- {
- if ( PsiHost[z]->irq == pshost->irq ) // if shared then, don't posses
- setirq = 0;
- }
- if ( setirq ) // if not shared, posses
- {
- if ( request_irq (pshost->irq, Irq_Handler, SA_SHIRQ, "pci2000", padapter) < 0 )
- {
- if ( request_irq (pshost->irq, Irq_Handler, SA_INTERRUPT | SA_SHIRQ, "pci2000", padapter) < 0 )
- {
- printk ("Unable to allocate IRQ for PCI-2000 controller.\n");
- pci_free_consistent (pdev, consistentLen, consistent, consistentDma);
- goto unregister;
- }
- }
- padapter->irqOwned = pshost->irq; // set IRQ as owned
- }
- PsiHost[installed] = pshost; // save SCSI_HOST pointer
-
- pshost->io_port = padapter->basePort;
- pshost->n_io_port = 0xFF;
- pshost->unique_id = padapter->basePort;
- pshost->max_id = 16;
- pshost->max_channel = 1;
-
- for ( zz = 0; zz < MAX_BUS; zz++ )
- for ( z = 0; z < MAX_UNITS; z++ )
- {
- padapter->dev[zz][z].tag = 0;
- padapter->dev[zz][z].scatGath = (PSCATGATH)consistent;
- padapter->dev[zz][z].scatGathDma = consistentDma;
- consistent += 16 * sizeof (SCATGATH);
- consistentDma += 16 * sizeof (SCATGATH);
- padapter->dev[zz][z].cdb = (UCHAR *)consistent;
- padapter->dev[zz][z].cdbDma = consistentDma;
- consistent += MAX_COMMAND_SIZE;
- consistentDma += MAX_COMMAND_SIZE;
- }
-
- printk("\nPSI-2000 Intelligent Storage SCSI CONTROLLER: at I/O = %lX IRQ = %d\n", padapter->basePort, pshost->irq);
- printk("Version %s, Compiled %s %s\n\n", PCI2000_VERSION, __DATE__, __TIME__);
- found++;
- if ( ++installed < MAXADAPTER )
- continue;
- break;
-unregister:;
- scsi_unregister (pshost);
- found++;
- }
- NumAdapters = installed;
- return installed;
- }
-/****************************************************************
- * Name: Pci2000_Abort
- *
- * Description: Process the Abort command from the SCSI manager.
- *
- * Parameters: SCpnt - Pointer to SCSI command structure.
- *
- * Returns: Allways snooze.
- *
- ****************************************************************/
-int Pci2000_Abort (Scsi_Cmnd *SCpnt)
- {
- DEB (printk ("pci2000_abort\n"));
- return SCSI_ABORT_SNOOZE;
- }
-/****************************************************************
- * Name: Pci2000_Reset
- *
- * Description: Process the Reset command from the SCSI manager.
- *
- * Parameters: SCpnt - Pointer to SCSI command structure.
- * flags - Flags about the reset command
- *
- * Returns: No active command at this time, so this means
- * that each time we got some kind of response the
- * last time through. Tell the mid-level code to
- * request sense information in order to decide what
- * to do next.
- *
- ****************************************************************/
-int Pci2000_Reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
- {
- return SCSI_RESET_PUNT;
- }
-/****************************************************************
- * Name: Pci2000_Release
- *
- * Description: Release resources allocated for a single each adapter.
- *
- * Parameters: pshost - Pointer to SCSI command structure.
- *
- * Returns: zero.
- *
- ****************************************************************/
-int Pci2000_Release (struct Scsi_Host *pshost)
- {
- PADAPTER2000 padapter = HOSTDATA (pshost);
-
- if ( padapter->irqOwned )
- free_irq (pshost->irq, padapter);
- pci_free_consistent (padapter->pdev, consistentLen, padapter->dev[0][0].scatGath, padapter->dev[0][0].scatGathDma);
- release_region (pshost->io_port, pshost->n_io_port);
- scsi_unregister(pshost);
- return 0;
- }
-
-/****************************************************************
- * Name: Pci2000_BiosParam
- *
- * Description: Process the biosparam request from the SCSI manager to
- * return C/H/S data.
- *
- * Parameters: disk - Pointer to SCSI disk structure.
- * dev - Major/minor number from kernel.
- * geom - Pointer to integer array to place geometry data.
- *
- * Returns: zero.
- *
- ****************************************************************/
-int Pci2000_BiosParam (struct scsi_device *sdev, struct block_device *dev,
- sector_t capacity, int geom[])
- {
- PADAPTER2000 padapter;
-
- padapter = HOSTDATA(sdev->host);
-
- if ( WaitReady (padapter) )
- return 0;
- outb_p (sdev->id, padapter->mb0);
- outb_p (CMD_GET_PARMS, padapter->cmd);
- if ( WaitReady (padapter) )
- return 0;
-
- geom[0] = inb_p (padapter->mb2 + 3);
- geom[1] = inb_p (padapter->mb2 + 2);
- geom[2] = inw_p (padapter->mb2);
- return 0;
- }
-
-
-MODULE_LICENSE("Dual BSD/GPL");
-
-static Scsi_Host_Template driver_template = {
- .proc_name = "pci2000",
- .name = "PCI-2000 SCSI Intelligent Disk Controller",
- .detect = Pci2000_Detect,
- .release = Pci2000_Release,
- .queuecommand = Pci2000_QueueCommand,
- .abort = Pci2000_Abort,
- .reset = Pci2000_Reset,
- .bios_param = Pci2000_BiosParam,
- .can_queue = 16,
- .this_id = -1,
- .sg_tablesize = 16,
- .cmd_per_lun = 1,
- .use_clustering = DISABLE_CLUSTERING,
-};
-#include "scsi_module.c"
diff --git a/drivers/scsi/pci2220i.c b/drivers/scsi/pci2220i.c
deleted file mode 100644
index e395e420315..00000000000
--- a/drivers/scsi/pci2220i.c
+++ /dev/null
@@ -1,2915 +0,0 @@
-/****************************************************************************
- * Perceptive Solutions, Inc. PCI-2220I device driver for Linux.
- *
- * pci2220i.c - Linux Host Driver for PCI-2220I EIDE RAID Adapters
- *
- * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
- * All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that redistributions of source
- * code retain the above copyright notice and this comment without
- * modification.
- *
- * Technical updates and product information at:
- * http://www.psidisk.com
- *
- * Please send questions, comments, bug reports to:
- * tech@psidisk.com Technical Support
- *
- *
- * Revisions 1.10 Mar-26-1999
- * - Updated driver for RAID and hot reconstruct support.
- *
- * Revisions 1.11 Mar-26-1999
- * - Fixed spinlock and PCI configuration.
- *
- * Revision 2.00 December-1-1999
- * - Added code for the PCI-2240I controller
- * - Added code for ATAPI devices.
- * - Double buffer for scatter/gather support
- *
- * Revision 2.10 March-27-2000
- * - Added support for dynamic DMA
- *
- ****************************************************************************/
-
-#error Convert me to understand page+offset based scatterlists
-
-//#define DEBUG 1
-
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/blkdev.h>
-#include <linux/timer.h>
-#include <linux/spinlock.h>
-
-#include <asm/dma.h>
-#include <asm/system.h>
-#include <asm/io.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "pci2220i.h"
-#include "psi_dale.h"
-
-
-#define PCI2220I_VERSION "2.10"
-#define READ_CMD IDE_CMD_READ_MULTIPLE
-#define WRITE_CMD IDE_CMD_WRITE_MULTIPLE
-#define MAX_BUS_MASTER_BLOCKS SECTORSXFER // This is the maximum we can bus master
-
-#ifdef DEBUG
-#define DEB(x) x
-#define STOP_HERE() {int st;for(st=0;st<100;st++){st=1;}}
-#else
-#define DEB(x)
-#define STOP_HERE()
-#endif
-
-#define MAXADAPTER 4 // Increase this and the sizes of the arrays below, if you need more.
-
-
-typedef struct
- {
- UCHAR byte6; // device select register image
- UCHAR spigot; // spigot number
- UCHAR spigots[2]; // RAID spigots
- UCHAR deviceID[2]; // device ID codes
- USHORT sectors; // number of sectors per track
- USHORT heads; // number of heads
- USHORT cylinders; // number of cylinders for this device
- USHORT spareword; // placeholder
- ULONG blocks; // number of blocks on device
- DISK_MIRROR DiskMirror[2]; // RAID status and control
- ULONG lastsectorlba[2]; // last addressable sector on the drive
- USHORT raid; // RAID active flag
- USHORT mirrorRecon;
- UCHAR reconOn;
- USHORT reconCount;
- USHORT reconIsStarting; // indicate hot reconstruct is starting
- UCHAR cmdDrqInt; // flag for command interrupt
- UCHAR packet; // command packet size in bytes
- } OUR_DEVICE, *POUR_DEVICE;
-
-typedef struct
- {
- USHORT bigD; // identity is a PCI-2240I if true, otherwise a PCI-2220I
- USHORT atapi; // this interface is for ATAPI devices only
- ULONG regDmaDesc; // address of the DMA discriptor register for direction of transfer
- ULONG regDmaCmdStat; // Byte #1 of DMA command status register
- ULONG regDmaAddrPci; // 32 bit register for PCI address of DMA
- ULONG regDmaAddrLoc; // 32 bit register for local bus address of DMA
- ULONG regDmaCount; // 32 bit register for DMA transfer count
- ULONG regDmaMode; // 32 bit register for DMA mode control
- ULONG regRemap; // 32 bit local space remap
- ULONG regDesc; // 32 bit local region descriptor
- ULONG regRange; // 32 bit local range
- ULONG regIrqControl; // 16 bit Interrupt enable/disable and status
- ULONG regScratchPad; // scratch pad I/O base address
- ULONG regBase; // Base I/O register for data space
- ULONG regData; // data register I/O address
- ULONG regError; // error register I/O address
- ULONG regSectCount; // sector count register I/O address
- ULONG regLba0; // least significant byte of LBA
- ULONG regLba8; // next least significant byte of LBA
- ULONG regLba16; // next most significan byte of LBA
- ULONG regLba24; // head and most 4 significant bits of LBA
- ULONG regStatCmd; // status on read and command on write register
- ULONG regStatSel; // board status on read and spigot select on write register
- ULONG regFail; // fail bits control register
- ULONG regAltStat; // alternate status and drive control register
- ULONG basePort; // PLX base I/O port
- USHORT timingMode; // timing mode currently set for adapter
- USHORT timingPIO; // TRUE if PIO timing is active
- struct pci_dev *pcidev;
- ULONG timingAddress; // address to use on adapter for current timing mode
- ULONG irqOwned; // owned IRQ or zero if shared
- UCHAR numberOfDrives; // saved number of drives on this controller
- UCHAR failRegister; // current inverted data in fail register
- OUR_DEVICE device[BIGD_MAXDRIVES];
- DISK_MIRROR *raidData[BIGD_MAXDRIVES];
- ULONG startSector;
- USHORT sectorCount;
- ULONG readCount;
- UCHAR *currentSgBuffer;
- ULONG currentSgCount;
- USHORT nextSg;
- UCHAR cmd;
- Scsi_Cmnd *SCpnt;
- POUR_DEVICE pdev; // current device opearating on
- USHORT devInReconIndex;
- USHORT expectingIRQ;
- USHORT reconOn; // Hot reconstruct is to be done.
- USHORT reconPhase; // Hot reconstruct operation is in progress.
- ULONG reconSize;
- USHORT demoFail; // flag for RAID failure demonstration
- USHORT survivor;
- USHORT failinprog;
- struct timer_list reconTimer;
- struct timer_list timer;
- UCHAR *kBuffer;
- dma_addr_t kBufferDma;
- UCHAR reqSense;
- UCHAR atapiCdb[16];
- UCHAR atapiSpecial;
- } ADAPTER2220I, *PADAPTER2220I;
-
-#define HOSTDATA(host) ((PADAPTER2220I)&host->hostdata)
-
-#define RECON_PHASE_READY 0x01
-#define RECON_PHASE_COPY 0x02
-#define RECON_PHASE_UPDATE 0x03
-#define RECON_PHASE_LAST 0x04
-#define RECON_PHASE_END 0x07
-#define RECON_PHASE_MARKING 0x80
-#define RECON_PHASE_FAILOVER 0xFF
-
-static struct Scsi_Host *PsiHost[MAXADAPTER] = {NULL,}; // One for each adapter
-static int NumAdapters = 0;
-static int Installed = 0;
-static SETUP DaleSetup;
-static DISK_MIRROR DiskMirror[BIGD_MAXDRIVES];
-static ULONG ModeArray[] = {DALE_DATA_MODE2, DALE_DATA_MODE3, DALE_DATA_MODE4, DALE_DATA_MODE5};
-static ULONG ModeArray2[] = {BIGD_DATA_MODE2, BIGD_DATA_MODE3, BIGD_DATA_MODE4, BIGD_DATA_MODE5};
-
-static void ReconTimerExpiry (unsigned long data);
-
-/*******************************************************************************************************
- * Name: Alarm
- *
- * Description: Sound the for the given device
- *
- * Parameters: padapter - Pointer adapter data structure.
- * device - Device number.
- *
- * Returns: Nothing.
- *
- ******************************************************************************************************/
-static void Alarm (PADAPTER2220I padapter, UCHAR device)
- {
- UCHAR zc;
-
- if ( padapter->bigD )
- {
- zc = device | (FAIL_ANY | FAIL_AUDIBLE);
- if ( padapter->failRegister & FAIL_ANY )
- zc |= FAIL_MULTIPLE;
-
- padapter->failRegister = zc;
- outb_p (~zc, padapter->regFail);
- }
- else
- outb_p (0x3C | (1 << device), padapter->regFail); // sound alarm and set fail light
- }
-/****************************************************************
- * Name: MuteAlarm :LOCAL
- *
- * Description: Mute the audible alarm.
- *
- * Parameters: padapter - Pointer adapter data structure.
- *
- * Returns: TRUE if drive does not assert DRQ in time.
- *
- ****************************************************************/
-static void MuteAlarm (PADAPTER2220I padapter)
- {
- UCHAR old;
-
- if ( padapter->bigD )
- {
- padapter->failRegister &= ~FAIL_AUDIBLE;
- outb_p (~padapter->failRegister, padapter->regFail);
- }
- else
- {
- old = (inb_p (padapter->regStatSel) >> 3) | (inb_p (padapter->regStatSel) & 0x83);
- outb_p (old | 0x40, padapter->regFail);
- }
- }
-/****************************************************************
- * Name: WaitReady :LOCAL
- *
- * Description: Wait for device ready.
- *
- * Parameters: padapter - Pointer adapter data structure.
- *
- * Returns: TRUE if drive does not assert DRQ in time.
- *
- ****************************************************************/
-static int WaitReady (PADAPTER2220I padapter)
- {
- ULONG z;
- UCHAR status;
-
- for ( z = 0; z < (TIMEOUT_READY * 4); z++ )
- {
- status = inb_p (padapter->regStatCmd);
- if ( (status & (IDE_STATUS_DRDY | IDE_STATUS_BUSY)) == IDE_STATUS_DRDY )
- return 0;
- udelay (250);
- }
- return status;
- }
-/****************************************************************
- * Name: WaitReadyReset :LOCAL
- *
- * Description: Wait for device ready.
- *
- * Parameters: padapter - Pointer adapter data structure.
- *
- * Returns: TRUE if drive does not assert DRQ in time.
- *
- ****************************************************************/
-static int WaitReadyReset (PADAPTER2220I padapter)
- {
- ULONG z;
- UCHAR status;
-
- for ( z = 0; z < (125 * 16); z++ ) // wait up to 1/4 second
- {
- status = inb_p (padapter->regStatCmd);
- if ( (status & (IDE_STATUS_DRDY | IDE_STATUS_BUSY)) == IDE_STATUS_DRDY )
- {
- DEB (printk ("\nPCI2220I: Reset took %ld mSec to be ready", z / 8));
- return 0;
- }
- udelay (125);
- }
- DEB (printk ("\nPCI2220I: Reset took more than 2 Seconds to come ready, Disk Failure"));
- return status;
- }
-/****************************************************************
- * Name: WaitDrq :LOCAL
- *
- * Description: Wait for device ready for data transfer.
- *
- * Parameters: padapter - Pointer adapter data structure.
- *
- * Returns: TRUE if drive does not assert DRQ in time.
- *
- ****************************************************************/
-static int WaitDrq (PADAPTER2220I padapter)
- {
- ULONG z;
- UCHAR status;
-
- for ( z = 0; z < (TIMEOUT_DRQ * 4); z++ )
- {
- status = inb_p (padapter->regStatCmd);
- if ( status & IDE_STATUS_DRQ )
- return 0;
- udelay (250);
- }
- return status;
- }
-/****************************************************************
- * Name: AtapiWaitReady :LOCAL
- *
- * Description: Wait for device busy and DRQ to be cleared.
- *
- * Parameters: padapter - Pointer adapter data structure.
- * msec - Number of milliseconds to wait.
- *
- * Returns: TRUE if drive does not clear busy in time.
- *
- ****************************************************************/
-static int AtapiWaitReady (PADAPTER2220I padapter, int msec)
- {
- int z;
-
- for ( z = 0; z < (msec * 16); z++ )
- {
- if ( !(inb_p (padapter->regStatCmd) & (IDE_STATUS_BUSY | IDE_STATUS_DRQ)) )
- return FALSE;
- udelay (125);
- }
- return TRUE;
- }
-/****************************************************************
- * Name: AtapiWaitDrq :LOCAL
- *
- * Description: Wait for device ready for data transfer.
- *
- * Parameters: padapter - Pointer adapter data structure.
- * msec - Number of milliseconds to wait.
- *
- * Returns: TRUE if drive does not assert DRQ in time.
- *
- ****************************************************************/
-static int AtapiWaitDrq (PADAPTER2220I padapter, int msec)
- {
- ULONG z;
-
- for ( z = 0; z < (msec * 16); z++ )
- {
- if ( inb_p (padapter->regStatCmd) & IDE_STATUS_DRQ )
- return 0;
- udelay (128);
- }
- return TRUE;
- }
-/****************************************************************
- * Name: HardReset :LOCAL
- *
- * Description: Wait for device ready for data transfer.
- *
- * Parameters: padapter - Pointer adapter data structure.
- * pdev - Pointer to device.
- * spigot - Spigot number.
- *
- * Returns: TRUE if drive does not assert DRQ in time.
- *
- ****************************************************************/
-static int HardReset (PADAPTER2220I padapter, POUR_DEVICE pdev, UCHAR spigot)
- {
- DEB (printk ("\npci2220i:RESET spigot = %X devices = %d, %d", spigot, pdev->deviceID[0], pdev->deviceID[1]));
- mdelay (100); // just wait 100 mSec to let drives flush
- SelectSpigot (padapter, spigot | SEL_IRQ_OFF);
-
- outb_p (0x0E, padapter->regAltStat); // reset the suvivor
- udelay (100); // wait a little
- outb_p (0x08, padapter->regAltStat); // clear the reset
- udelay (100);
-
- outb_p (0xA0, padapter->regLba24); // select the master drive
- if ( WaitReadyReset (padapter) )
- {
- DEB (printk ("\npci2220i: master not ready after reset"));
- return TRUE;
- }
- outb_p (0xB0, padapter->regLba24); // try the slave drive
- if ( (inb_p (padapter->regStatCmd) & (IDE_STATUS_DRDY | IDE_STATUS_BUSY)) == IDE_STATUS_DRDY )
- {
- DEB (printk ("\nPCI2220I: initializing slave drive on spigot %X", spigot));
- outb_p (SECTORSXFER, padapter->regSectCount);
- WriteCommand (padapter, IDE_CMD_SET_MULTIPLE);
- if ( WaitReady (padapter) )
- {
- DEB (printk ("\npci2220i: slave not ready after set multiple"));
- return TRUE;
- }
- }
-
- outb_p (0xA0, padapter->regLba24); // select the drive
- outb_p (SECTORSXFER, padapter->regSectCount);
- WriteCommand (padapter, IDE_CMD_SET_MULTIPLE);
- if ( WaitReady (padapter) )
- {
- DEB (printk ("\npci2220i: master not ready after set multiple"));
- return TRUE;
- }
- return FALSE;
- }
-/****************************************************************
- * Name: AtapiReset :LOCAL
- *
- * Description: Wait for device ready for data transfer.
- *
- * Parameters: padapter - Pointer adapter data structure.
- * pdev - Pointer to device.
- *
- * Returns: TRUE if drive does not come ready.
- *
- ****************************************************************/
-static int AtapiReset (PADAPTER2220I padapter, POUR_DEVICE pdev)
- {
- SelectSpigot (padapter, pdev->spigot);
- AtapiDevice (padapter, pdev->byte6);
- AtapiCountLo (padapter, 0);
- AtapiCountHi (padapter, 0);
- WriteCommand (padapter, IDE_COMMAND_ATAPI_RESET);
- udelay (125);
- if ( AtapiWaitReady (padapter, 1000) )
- return TRUE;
- if ( inb_p (padapter->regStatCmd) || (inb_p (padapter->regLba8) != 0x14) || (inb_p (padapter->regLba16) != 0xEB) )
- return TRUE;
- return FALSE;
- }
-/****************************************************************
- * Name: WalkScatGath :LOCAL
- *
- * Description: Transfer data to/from scatter/gather buffers.
- *
- * Parameters: padapter - Pointer adapter data structure.
- * datain - TRUE if data read.
- * length - Number of bytes to transfer.
- *
- * Returns: Nothing.
- *
- ****************************************************************/
-static void WalkScatGath (PADAPTER2220I padapter, UCHAR datain, ULONG length)
- {
- ULONG count;
- UCHAR *buffer = padapter->kBuffer;
-
- while ( length )
- {
- count = ( length > padapter->currentSgCount ) ? padapter->currentSgCount : length;
-
- if ( datain )
- memcpy (padapter->currentSgBuffer, buffer, count);
- else
- memcpy (buffer, padapter->currentSgBuffer, count);
-
- padapter->currentSgCount -= count;
- if ( !padapter->currentSgCount )
- {
- if ( padapter->nextSg < padapter->SCpnt->use_sg )
- {
- padapter->currentSgBuffer = ((struct scatterlist *)padapter->SCpnt->request_buffer)[padapter->nextSg].address;
- padapter->currentSgCount = ((struct scatterlist *)padapter->SCpnt->request_buffer)[padapter->nextSg].length;
- padapter->nextSg++;
- }
- }
- else
- padapter->currentSgBuffer += count;
-
- length -= count;
- buffer += count;
- }
- }
-/****************************************************************
- * Name: BusMaster :LOCAL
- *
- * Description: Do a bus master I/O.
- *
- * Parameters: padapter - Pointer adapter data structure.
- * datain - TRUE if data read.
- * irq - TRUE if bus master interrupt expected.
- *
- * Returns: Nothing.
- *
- ****************************************************************/
-static void BusMaster (PADAPTER2220I padapter, UCHAR datain, UCHAR irq)
- {
- ULONG zl;
-
- zl = ( padapter->sectorCount > MAX_BUS_MASTER_BLOCKS ) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
- padapter->sectorCount -= zl;
- zl *= (ULONG)BYTES_PER_SECTOR;
-
- if ( datain )
- {
- padapter->readCount = zl;
- outb_p (8, padapter->regDmaDesc); // read operation
- if ( padapter->bigD )
- {
- if ( irq && !padapter->sectorCount )
- outb_p (0x0C, padapter->regDmaMode); // interrupt on
- else
- outb_p (0x08, padapter->regDmaMode); // no interrupt
- }
- else
- {
- if ( irq && !padapter->sectorCount )
- outb_p (0x05, padapter->regDmaMode); // interrupt on
- else
- outb_p (0x01, padapter->regDmaMode); // no interrupt
- }
- }
- else
- {
- outb_p (0x00, padapter->regDmaDesc); // write operation
- if ( padapter->bigD )
- outb_p (0x08, padapter->regDmaMode); // no interrupt
- else
- outb_p (0x01, padapter->regDmaMode); // no interrupt
- WalkScatGath (padapter, FALSE, zl);
- }
-
- outl (padapter->timingAddress, padapter->regDmaAddrLoc);
- outl (padapter->kBufferDma, padapter->regDmaAddrPci);
- outl (zl, padapter->regDmaCount);
- outb_p (0x03, padapter->regDmaCmdStat); // kick the DMA engine in gear
- }
-/****************************************************************
- * Name: AtapiBusMaster :LOCAL
- *
- * Description: Do a bus master I/O.
- *
- * Parameters: padapter - Pointer adapter data structure.
- * datain - TRUE if data read.
- * length - Number of bytes to transfer.
- *
- * Returns: Nothing.
- *
- ****************************************************************/
-static void AtapiBusMaster (PADAPTER2220I padapter, UCHAR datain, ULONG length)
- {
- outl (padapter->timingAddress, padapter->regDmaAddrLoc);
- outl (padapter->kBufferDma, padapter->regDmaAddrPci);
- outl (length, padapter->regDmaCount);
- if ( datain )
- {
- if ( padapter->readCount )
- WalkScatGath (padapter, TRUE, padapter->readCount);
- outb_p (0x08, padapter->regDmaDesc); // read operation
- outb_p (0x08, padapter->regDmaMode); // no interrupt
- padapter->readCount = length;
- }
- else
- {
- outb_p (0x00, padapter->regDmaDesc); // write operation
- outb_p (0x08, padapter->regDmaMode); // no interrupt
- if ( !padapter->atapiSpecial )
- WalkScatGath (padapter, FALSE, length);
- }
- outb_p (0x03, padapter->regDmaCmdStat); // kick the DMA engine in gear
- }
-/****************************************************************
- * Name: WriteData :LOCAL
- *
- * Description: Write data to device.
- *
- * Parameters: padapter - Pointer adapter data structure.
- *
- * Returns: TRUE if drive does not assert DRQ in time.
- *
- ****************************************************************/
-static int WriteData (PADAPTER2220I padapter)
- {
- ULONG zl;
-
- if ( !WaitDrq (padapter) )
- {
- if ( padapter->timingPIO )
- {
- zl = (padapter->sectorCount > MAX_BUS_MASTER_BLOCKS) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
- WalkScatGath (padapter, FALSE, zl * BYTES_PER_SECTOR);
- outsw (padapter->regData, padapter->kBuffer, zl * (BYTES_PER_SECTOR / 2));
- padapter->sectorCount -= zl;
- }
- else
- BusMaster (padapter, 0, 0);
- return 0;
- }
- padapter->cmd = 0; // null out the command byte
- return 1;
- }
-/****************************************************************
- * Name: WriteDataBoth :LOCAL
- *
- * Description: Write data to device.
- *
- * Parameters: padapter - Pointer to adapter structure.
- * pdev - Pointer to device structure
- *
- * Returns: Index + 1 of drive not failed or zero for OK.
- *
- ****************************************************************/
-static int WriteDataBoth (PADAPTER2220I padapter, POUR_DEVICE pdev)
- {
- ULONG zl;
- UCHAR status0, status1;
-
- SelectSpigot (padapter, pdev->spigots[0]);
- status0 = WaitDrq (padapter);
- if ( !status0 )
- {
- SelectSpigot (padapter, pdev->spigots[1]);
- status1 = WaitDrq (padapter);
- if ( !status1 )
- {
- SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1] | padapter->bigD);
- if ( padapter->timingPIO )
- {
- zl = (padapter->sectorCount > MAX_BUS_MASTER_BLOCKS) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
- WalkScatGath (padapter, FALSE, zl * BYTES_PER_SECTOR);
- outsw (padapter->regData, padapter->kBuffer, zl * (BYTES_PER_SECTOR / 2));
- padapter->sectorCount -= zl;
- }
- else
- BusMaster (padapter, 0, 0);
- return 0;
- }
- }
- padapter->cmd = 0; // null out the command byte
- if ( status0 )
- return 2;
- return 1;
- }
-/****************************************************************
- * Name: IdeCmd :LOCAL
- *
- * Description: Process an IDE command.
- *
- * Parameters: padapter - Pointer adapter data structure.
- * pdev - Pointer to device.
- *
- * Returns: Zero if no error or status register contents on error.
- *
- ****************************************************************/
-static UCHAR IdeCmd (PADAPTER2220I padapter, POUR_DEVICE pdev)
- {
- UCHAR status;
-
- SelectSpigot (padapter, pdev->spigot | padapter->bigD); // select the spigot
- outb_p (pdev->byte6 | ((UCHAR *)(&padapter->startSector))[3], padapter->regLba24); // select the drive
- status = WaitReady (padapter);
- if ( !status )
- {
- outb_p (padapter->sectorCount, padapter->regSectCount);
- outb_p (((UCHAR *)(&padapter->startSector))[0], padapter->regLba0);
- outb_p (((UCHAR *)(&padapter->startSector))[1], padapter->regLba8);
- outb_p (((UCHAR *)(&padapter->startSector))[2], padapter->regLba16);
- padapter->expectingIRQ = TRUE;
- WriteCommand (padapter, padapter->cmd);
- return 0;
- }
-
- padapter->cmd = 0; // null out the command byte
- return status;
- }
-/****************************************************************
- * Name: IdeCmdBoth :LOCAL
- *
- * Description: Process an IDE command to both drivers.
- *
- * Parameters: padapter - Pointer adapter data structure.
- * pdev - Pointer to device structure
- *
- * Returns: Index + 1 of drive not failed or zero for OK.
- *
- ****************************************************************/
-static UCHAR IdeCmdBoth (PADAPTER2220I padapter, POUR_DEVICE pdev)
- {
- UCHAR status0;
- UCHAR status1;
-
- SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1]); // select the spigots
- outb_p (padapter->pdev->byte6 | ((UCHAR *)(&padapter->startSector))[3], padapter->regLba24);// select the drive
- SelectSpigot (padapter, pdev->spigots[0]);
- status0 = WaitReady (padapter);
- if ( !status0 )
- {
- SelectSpigot (padapter, pdev->spigots[1]);
- status1 = WaitReady (padapter);
- if ( !status1 )
- {
- SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1] | padapter->bigD);
- outb_p (padapter->sectorCount, padapter->regSectCount);
- outb_p (((UCHAR *)(&padapter->startSector))[0], padapter->regLba0);
- outb_p (((UCHAR *)(&padapter->startSector))[1], padapter->regLba8);
- outb_p (((UCHAR *)(&padapter->startSector))[2], padapter->regLba16);
- padapter->expectingIRQ = TRUE;
- WriteCommand (padapter, padapter->cmd);
- return 0;
- }
- }
- padapter->cmd = 0; // null out the command byte
- if ( status0 )
- return 2;
- return 1;
- }
-/****************************************************************
- * Name: OpDone :LOCAL
- *
- * Description: Complete an operatoin done sequence.
- *
- * Parameters: padapter - Pointer to host data block.
- * spigot - Spigot select code.
- * device - Device byte code.
- *
- * Returns: Nothing.
- *
- ****************************************************************/
-static void OpDone (PADAPTER2220I padapter, ULONG result)
- {
- Scsi_Cmnd *SCpnt = padapter->SCpnt;
-
- if ( padapter->reconPhase )
- {
- padapter->reconPhase = 0;
- if ( padapter->SCpnt )
- {
- Pci2220i_QueueCommand (SCpnt, SCpnt->scsi_done);
- }
- else
- {
- if ( padapter->reconOn )
- {
- ReconTimerExpiry ((unsigned long)padapter);
- }
- }
- }
- else
- {
- padapter->cmd = 0;
- padapter->SCpnt = NULL;
- padapter->pdev = NULL;
- SCpnt->result = result;
- SCpnt->scsi_done (SCpnt);
- if ( padapter->reconOn && !padapter->reconTimer.data )
- {
- padapter->reconTimer.expires = jiffies + (HZ / 4); // start in 1/4 second
- padapter->reconTimer.data = (unsigned long)padapter;
- add_timer (&padapter->reconTimer);
- }
- }
- }
-/****************************************************************
- * Name: InlineIdentify :LOCAL
- *
- * Description: Do an intline inquiry on a drive.
- *
- * Parameters: padapter - Pointer to host data block.
- * spigot - Spigot select code.
- * device - Device byte code.
- *
- * Returns: Last addressable sector or zero if none.
- *
- ****************************************************************/
-static ULONG InlineIdentify (PADAPTER2220I padapter, UCHAR spigot, UCHAR device)
- {
- PIDENTIFY_DATA pid = (PIDENTIFY_DATA)padapter->kBuffer;
-
- SelectSpigot (padapter, spigot | SEL_IRQ_OFF); // select the spigot
- outb_p ((device << 4) | 0xA0, padapter->regLba24); // select the drive
- if ( WaitReady (padapter) )
- return 0;
- WriteCommand (padapter, IDE_COMMAND_IDENTIFY);
- if ( WaitDrq (padapter) )
- return 0;
- insw (padapter->regData, padapter->kBuffer, sizeof (IDENTIFY_DATA) >> 1);
- return (pid->LBATotalSectors - 1);
- }
-/****************************************************************
- * Name: AtapiIdentify :LOCAL
- *
- * Description: Do an intline inquiry on a drive.
- *
- * Parameters: padapter - Pointer to host data block.
- * pdev - Pointer to device table.
- *
- * Returns: TRUE on error.
- *
- ****************************************************************/
-static ULONG AtapiIdentify (PADAPTER2220I padapter, POUR_DEVICE pdev)
- {
- ATAPI_GENERAL_0 ag0;
- USHORT zs;
- int z;
-
- AtapiDevice (padapter, pdev->byte6);
- WriteCommand (padapter, IDE_COMMAND_ATAPI_IDENTIFY);
- if ( AtapiWaitDrq (padapter, 3000) )
- return TRUE;
-
- *(USHORT *)&ag0 = inw_p (padapter->regData);
- for ( z = 0; z < 255; z++ )
- zs = inw_p (padapter->regData);
-
- if ( ag0.ProtocolType == 2 )
- {
- if ( ag0.CmdDrqType == 1 )
- pdev->cmdDrqInt = TRUE;
- switch ( ag0.CmdPacketSize )
- {
- case 0:
- pdev->packet = 6;
- break;
- case 1:
- pdev->packet = 8;
- break;
- default:
- pdev->packet = 6;
- break;
- }
- return FALSE;
- }
- return TRUE;
- }
-/****************************************************************
- * Name: Atapi2Scsi
- *
- * Description: Convert ATAPI data to SCSI data.
- *
- * Parameters: padapter - Pointer adapter data structure.
- * SCpnt - Pointer to SCSI command structure.
- *
- * Returns: Nothing.
- *
- ****************************************************************/
-void Atapi2Scsi (PADAPTER2220I padapter, Scsi_Cmnd *SCpnt)
- {
- UCHAR *buff = padapter->currentSgBuffer;
-
- switch ( SCpnt->cmnd[0] )
- {
- case SCSIOP_MODE_SENSE:
- buff[0] = padapter->kBuffer[1];
- buff[1] = padapter->kBuffer[2];
- buff[2] = padapter->kBuffer[3];
- buff[3] = padapter->kBuffer[7];
- memcpy (&buff[4], &padapter->kBuffer[8], padapter->atapiCdb[8] - 8);
- break;
- case SCSIOP_INQUIRY:
- padapter->kBuffer[2] = 2;
- memcpy (buff, padapter->kBuffer, padapter->currentSgCount);
- break;
- default:
- if ( padapter->readCount )
- WalkScatGath (padapter, TRUE, padapter->readCount);
- break;
- }
- }
-/****************************************************************
- * Name: Scsi2Atapi
- *
- * Description: Convert SCSI packet command to Atapi packet command.
- *
- * Parameters: padapter - Pointer adapter data structure.
- * SCpnt - Pointer to SCSI command structure.
- *
- * Returns: Nothing.
- *
- ****************************************************************/
-static void Scsi2Atapi (PADAPTER2220I padapter, Scsi_Cmnd *SCpnt)
- {
- UCHAR *cdb = SCpnt->cmnd;
- UCHAR *buff = padapter->currentSgBuffer;
-
- switch (cdb[0])
- {
- case SCSIOP_READ6:
- padapter->atapiCdb[0] = SCSIOP_READ;
- padapter->atapiCdb[1] = cdb[1] & 0xE0;
- padapter->atapiCdb[3] = cdb[1] & 0x1F;
- padapter->atapiCdb[4] = cdb[2];
- padapter->atapiCdb[5] = cdb[3];
- padapter->atapiCdb[8] = cdb[4];
- padapter->atapiCdb[9] = cdb[5];
- break;
- case SCSIOP_WRITE6:
- padapter->atapiCdb[0] = SCSIOP_WRITE;
- padapter->atapiCdb[1] = cdb[1] & 0xE0;
- padapter->atapiCdb[3] = cdb[1] & 0x1F;
- padapter->atapiCdb[4] = cdb[2];
- padapter->atapiCdb[5] = cdb[3];
- padapter->atapiCdb[8] = cdb[4];
- padapter->atapiCdb[9] = cdb[5];
- break;
- case SCSIOP_MODE_SENSE:
- padapter->atapiCdb[0] = SCSIOP_MODE_SENSE10;
- padapter->atapiCdb[2] = cdb[2];
- padapter->atapiCdb[8] = cdb[4] + 4;
- break;
-
- case SCSIOP_MODE_SELECT:
- padapter->atapiSpecial = TRUE;
- padapter->atapiCdb[0] = SCSIOP_MODE_SELECT10;
- padapter->atapiCdb[1] = cdb[1] | 0x10;
- memcpy (padapter->kBuffer, buff, 4);
- padapter->kBuffer[4] = padapter->kBuffer[5] = 0;
- padapter->kBuffer[6] = padapter->kBuffer[7] = 0;
- memcpy (&padapter->kBuffer[8], &buff[4], cdb[4] - 4);
- padapter->atapiCdb[8] = cdb[4] + 4;
- break;
- }
- }
-/****************************************************************
- * Name: AtapiSendCdb
- *
- * Description: Send the CDB packet to the device.
- *
- * Parameters: padapter - Pointer adapter data structure.
- * pdev - Pointer to device.
- * cdb - Pointer to 16 byte SCSI cdb.
- *
- * Returns: Nothing.
- *
- ****************************************************************/
-static void AtapiSendCdb (PADAPTER2220I padapter, POUR_DEVICE pdev, CHAR *cdb)
- {
- DEB (printk ("\nPCI2242I: CDB: %X %X %X %X %X %X %X %X %X %X %X %X", cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11]));
- outsw (padapter->regData, cdb, pdev->packet);
- }
-/****************************************************************
- * Name: AtapiRequestSense
- *
- * Description: Send the CDB packet to the device.
- *
- * Parameters: padapter - Pointer adapter data structure.
- * pdev - Pointer to device.
- * SCpnt - Pointer to SCSI command structure.
- * pass - If true then this is the second pass to send cdb.
- *
- * Returns: TRUE on error.
- *
- ****************************************************************/
-static int AtapiRequestSense (PADAPTER2220I padapter, POUR_DEVICE pdev, Scsi_Cmnd *SCpnt, UCHAR pass)
- {
- UCHAR cdb[16] = {SCSIOP_REQUEST_SENSE,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0};
-
- DEB (printk ("\nPCI2242I: AUTO REQUEST SENSE"));
- cdb[4] = (UCHAR)(sizeof (SCpnt->sense_buffer));
- if ( !pass )
- {
- padapter->reqSense = TRUE;
- AtapiCountLo (padapter, cdb[4]);
- AtapiCountHi (padapter, 0);
- outb_p (0, padapter->regError);
- WriteCommand (padapter, IDE_COMMAND_ATAPI_PACKET);
- if ( pdev->cmdDrqInt )
- return FALSE;
-
- if ( AtapiWaitDrq (padapter, 500) )
- return TRUE;
- }
- AtapiSendCdb (padapter, pdev, cdb);
- return FALSE;
- }
-/****************************************************************
- * Name: InlineReadSignature :LOCAL
- *
- * Description: Do an inline read RAID sigature.
- *
- * Parameters: padapter - Pointer adapter data structure.
- * pdev - Pointer to device.
- * index - index of data to read.
- *
- * Returns: Zero if no error or status register contents on error.
- *
- ****************************************************************/
-static UCHAR InlineReadSignature (PADAPTER2220I padapter, POUR_DEVICE pdev, int index)
- {
- UCHAR status;
- ULONG zl = pdev->lastsectorlba[index];
-
- SelectSpigot (padapter, pdev->spigots[index] | SEL_IRQ_OFF); // select the spigot without interrupts
- outb_p (pdev->byte6 | ((UCHAR *)&zl)[3], padapter->regLba24);
- status = WaitReady (padapter);
- if ( !status )
- {
- outb_p (((UCHAR *)&zl)[2], padapter->regLba16);
- outb_p (((UCHAR *)&zl)[1], padapter->regLba8);
- outb_p (((UCHAR *)&zl)[0], padapter->regLba0);
- outb_p (1, padapter->regSectCount);
- WriteCommand (padapter, IDE_COMMAND_READ);
- status = WaitDrq (padapter);
- if ( !status )
- {
- insw (padapter->regData, padapter->kBuffer, BYTES_PER_SECTOR / 2);
- ((ULONG *)(&pdev->DiskMirror[index]))[0] = ((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[0];
- ((ULONG *)(&pdev->DiskMirror[index]))[1] = ((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[1];
- // some drives assert DRQ before IRQ so let's make sure we clear the IRQ
- WaitReady (padapter);
- return 0;
- }
- }
- return status;
- }
-/****************************************************************
- * Name: DecodeError :LOCAL
- *
- * Description: Decode and process device errors.
- *
- * Parameters: padapter - Pointer to adapter data.
- * status - Status register code.
- *
- * Returns: The driver status code.
- *
- ****************************************************************/
-static ULONG DecodeError (PADAPTER2220I padapter, UCHAR status)
- {
- UCHAR error;
-
- padapter->expectingIRQ = 0;
- if ( status & IDE_STATUS_WRITE_FAULT )
- {
- return DID_PARITY << 16;
- }
- if ( status & IDE_STATUS_BUSY )
- return DID_BUS_BUSY << 16;
-
- error = inb_p (padapter->regError);
- DEB(printk ("\npci2220i error register: %x", error));
- switch ( error )
- {
- case IDE_ERROR_AMNF:
- case IDE_ERROR_TKONF:
- case IDE_ERROR_ABRT:
- case IDE_ERROR_IDFN:
- case IDE_ERROR_UNC:
- case IDE_ERROR_BBK:
- default:
- return DID_ERROR << 16;
- }
- return DID_ERROR << 16;
- }
-/****************************************************************
- * Name: StartTimer :LOCAL
- *
- * Description: Start the timer.
- *
- * Parameters: ipadapter - Pointer adapter data structure.
- *
- * Returns: Nothing.
- *
- ****************************************************************/
-static void StartTimer (PADAPTER2220I padapter)
- {
- padapter->timer.expires = jiffies + TIMEOUT_DATA;
- add_timer (&padapter->timer);
- }
-/****************************************************************
- * Name: WriteSignature :LOCAL
- *
- * Description: Start the timer.
- *
- * Parameters: padapter - Pointer adapter data structure.
- * pdev - Pointer to our device.
- * spigot - Selected spigot.
- * index - index of mirror signature on device.
- *
- * Returns: TRUE on any error.
- *
- ****************************************************************/
-static int WriteSignature (PADAPTER2220I padapter, POUR_DEVICE pdev, UCHAR spigot, int index)
- {
- ULONG zl;
-
- SelectSpigot (padapter, spigot);
- zl = pdev->lastsectorlba[index];
- outb_p (pdev->byte6 | ((UCHAR *)&zl)[3], padapter->regLba24);
- outb_p (((UCHAR *)&zl)[2], padapter->regLba16);
- outb_p (((UCHAR *)&zl)[1], padapter->regLba8);
- outb_p (((UCHAR *)&zl)[0], padapter->regLba0);
- outb_p (1, padapter->regSectCount);
-
- WriteCommand (padapter, IDE_COMMAND_WRITE);
- if ( WaitDrq (padapter) )
- return TRUE;
- StartTimer (padapter);
- padapter->expectingIRQ = TRUE;
-
- ((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[0] = ((ULONG *)(&pdev->DiskMirror[index]))[0];
- ((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[1] = ((ULONG *)(&pdev->DiskMirror[index]))[1];
- outsw (padapter->regData, padapter->kBuffer, BYTES_PER_SECTOR / 2);
- return FALSE;
- }
-/*******************************************************************************************************
- * Name: InitFailover
- *
- * Description: This is the beginning of the failover routine
- *
- * Parameters: SCpnt - Pointer to SCSI command structure.
- * padapter - Pointer adapter data structure.
- * pdev - Pointer to our device.
- *
- * Returns: TRUE on error.
- *
- ******************************************************************************************************/
-static int InitFailover (PADAPTER2220I padapter, POUR_DEVICE pdev)
- {
- UCHAR spigot;
-
- DEB (printk ("\npci2220i: Initialize failover process - survivor = %d", pdev->deviceID[padapter->survivor]));
- pdev->raid = FALSE; //initializes system for non raid mode
- pdev->reconOn = FALSE;
- spigot = pdev->spigots[padapter->survivor];
-
- if ( pdev->DiskMirror[padapter->survivor].status & UCBF_REBUILD )
- {
- DEB (printk ("\n failed, is survivor"));
- return (TRUE);
- }
-
- if ( HardReset (padapter, pdev, spigot) )
- {
- DEB (printk ("\n failed, reset"));
- return TRUE;
- }
-
- Alarm (padapter, pdev->deviceID[padapter->survivor ^ 1]);
- pdev->DiskMirror[padapter->survivor].status = UCBF_MIRRORED | UCBF_SURVIVOR; //clear present status
-
- if ( WriteSignature (padapter, pdev, spigot, padapter->survivor) )
- {
- DEB (printk ("\n failed, write signature"));
- return TRUE;
- }
- padapter->failinprog = TRUE;
- return FALSE;
- }
-/****************************************************************
- * Name: TimerExpiry :LOCAL
- *
- * Description: Timer expiry routine.
- *
- * Parameters: data - Pointer adapter data structure.
- *
- * Returns: Nothing.
- *
- ****************************************************************/
-static void TimerExpiry (unsigned long data)
- {
- PADAPTER2220I padapter = (PADAPTER2220I)data;
- struct Scsi_Host *host = padapter->SCpnt->device->host;
- POUR_DEVICE pdev = padapter->pdev;
- UCHAR status = IDE_STATUS_BUSY;
- UCHAR temp, temp1;
- unsigned long flags;
-
- /*
- * Disable interrupts, if they aren't already disabled and acquire
- * the I/O spinlock.
- */
- spin_lock_irqsave (host->host_lock, flags);
- DEB (printk ("\nPCI2220I: Timeout expired "));
-
- if ( padapter->failinprog )
- {
- DEB (printk ("in failover process"));
- OpDone (padapter, DecodeError (padapter, inb_p (padapter->regStatCmd)));
- goto timerExpiryDone;
- }
-
- while ( padapter->reconPhase )
- {
- DEB (printk ("in recon phase %X", padapter->reconPhase));
- switch ( padapter->reconPhase )
- {
- case RECON_PHASE_MARKING:
- case RECON_PHASE_LAST:
- padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 1 : 0;
- DEB (printk ("\npci2220i: FAILURE 1"));
- if ( InitFailover (padapter, pdev) )
- OpDone (padapter, DID_ERROR << 16);
- goto timerExpiryDone;
-
- case RECON_PHASE_READY:
- OpDone (padapter, DID_ERROR << 16);
- goto timerExpiryDone;
-
- case RECON_PHASE_COPY:
- padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
- DEB (printk ("\npci2220i: FAILURE 2"));
- DEB (printk ("\n spig/stat = %X", inb_p (padapter->regStatSel));
- if ( InitFailover (padapter, pdev) )
- OpDone (padapter, DID_ERROR << 16);
- goto timerExpiryDone;
-
- case RECON_PHASE_UPDATE:
- padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
- DEB (printk ("\npci2220i: FAILURE 3")));
- if ( InitFailover (padapter, pdev) )
- OpDone (padapter, DID_ERROR << 16);
- goto timerExpiryDone;
-
- case RECON_PHASE_END:
- padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
- DEB (printk ("\npci2220i: FAILURE 4"));
- if ( InitFailover (padapter, pdev) )
- OpDone (padapter, DID_ERROR << 16);
- goto timerExpiryDone;
-
- default:
- goto timerExpiryDone;
- }
- }
-
- while ( padapter->cmd )
- {
- outb_p (0x08, padapter->regDmaCmdStat); // cancel interrupt from DMA engine
- if ( pdev->raid )
- {
- if ( padapter->cmd == WRITE_CMD )
- {
- DEB (printk ("in RAID write operation"));
- temp = ( pdev->spigot & (SEL_1 | SEL_2) ) ? SEL_1 : SEL_3;
- if ( inb_p (padapter->regStatSel) & temp )
- {
- DEB (printk ("\npci2220i: Determined A OK"));
- SelectSpigot (padapter, temp | SEL_IRQ_OFF); // Masking the interrupt during spigot select
- temp = inb_p (padapter->regStatCmd);
- }
- else
- temp = IDE_STATUS_BUSY;
-
- temp1 = ( pdev->spigot & (SEL_1 | SEL_2) ) ? SEL_2 : SEL_4;
- if ( inb (padapter->regStatSel) & temp1 )
- {
- DEB (printk ("\npci2220i: Determined B OK"));
- SelectSpigot (padapter, temp1 | SEL_IRQ_OFF); // Masking the interrupt during spigot select
- temp1 = inb_p (padapter->regStatCmd);
- }
- else
- temp1 = IDE_STATUS_BUSY;
-
- if ( (temp & IDE_STATUS_BUSY) || (temp1 & IDE_STATUS_BUSY) )
- {
- DEB (printk ("\npci2220i: Status A: %X B: %X", temp & 0xFF, temp1 & 0xFF));
- if ( (temp & IDE_STATUS_BUSY) && (temp1 & IDE_STATUS_BUSY) )
- {
- status = temp;
- break;
- }
- else
- {
- if ( temp & IDE_STATUS_BUSY )
- padapter->survivor = 1;
- else
- padapter->survivor = 0;
- if ( InitFailover (padapter, pdev) )
- {
- status = inb_p (padapter->regStatCmd);
- break;
- }
- goto timerExpiryDone;
- }
- }
- }
- else
- {
- DEB (printk ("in RAID read operation"));
- padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
- DEB (printk ("\npci2220i: FAILURE 6"));
- if ( InitFailover (padapter, pdev) )
- {
- status = inb_p (padapter->regStatCmd);
- break;
- }
- goto timerExpiryDone;
- }
- }
- else
- {
- DEB (printk ("in I/O operation"));
- status = inb_p (padapter->regStatCmd);
- }
- break;
- }
-
- OpDone (padapter, DecodeError (padapter, status));
-
-timerExpiryDone:;
- /*
- * Release the I/O spinlock and restore the original flags
- * which will enable interrupts if and only if they were
- * enabled on entry.
- */
- spin_unlock_irqrestore (host->host_lock, flags);
- }
-/****************************************************************
- * Name: SetReconstruct :LOCAL
- *
- * Description: Set the reconstruct up.
- *
- * Parameters: pdev - Pointer to device structure.
- * index - Mirror index number.
- *
- * Returns: Number of sectors on new disk required.
- *
- ****************************************************************/
-static LONG SetReconstruct (POUR_DEVICE pdev, int index)
- {
- pdev->DiskMirror[index].status = UCBF_MIRRORED; // setup the flags
- pdev->DiskMirror[index ^ 1].status = UCBF_MIRRORED | UCBF_REBUILD;
- pdev->DiskMirror[index ^ 1].reconstructPoint = 0; // start the reconstruct
- pdev->reconCount = 1990; // mark target drive early
- return pdev->DiskMirror[index].reconstructPoint;
- }
-/****************************************************************
- * Name: ReconTimerExpiry :LOCAL
- *
- * Description: Reconstruct timer expiry routine.
- *
- * Parameters: data - Pointer adapter data structure.
- *
- * Returns: Nothing.
- *
- ****************************************************************/
-static void ReconTimerExpiry (unsigned long data)
- {
- PADAPTER2220I padapter = (PADAPTER2220I)data;
- struct Scsi_Host *host = padapter->SCpnt->device->host;
- POUR_DEVICE pdev;
- ULONG testsize = 0;
- PIDENTIFY_DATA pid;
- USHORT minmode;
- ULONG zl;
- UCHAR zc;
- USHORT z;
- unsigned long flags;
-
- /*
- * Disable interrupts, if they aren't already disabled and acquire
- * the I/O spinlock.
- */
- spin_lock_irqsave(host->host_lock, flags);
-
- if ( padapter->SCpnt )
- goto reconTimerExpiry;
-
- padapter->reconTimer.data = 0;
- for ( z = padapter->devInReconIndex + 1; z < BIGD_MAXDRIVES; z++ )
- {
- if ( padapter->device[z].reconOn )
- break;
- }
- if ( z < BIGD_MAXDRIVES )
- pdev = &padapter->device[z];
- else
- {
- for ( z = 0; z < BIGD_MAXDRIVES; z++ )
- {
- if ( padapter->device[z].reconOn )
- break;
- }
- if ( z < BIGD_MAXDRIVES )
- pdev = &padapter->device[z];
- else
- {
- padapter->reconOn = FALSE;
- goto reconTimerExpiry;
- }
- }
-
- padapter->devInReconIndex = z;
- pid = (PIDENTIFY_DATA)padapter->kBuffer;
- padapter->pdev = pdev;
- if ( pdev->reconIsStarting )
- {
- pdev->reconIsStarting = FALSE;
- pdev->reconOn = FALSE;
-
- while ( (pdev->DiskMirror[0].signature == SIGNATURE) && (pdev->DiskMirror[1].signature == SIGNATURE) &&
- (pdev->DiskMirror[0].pairIdentifier == (pdev->DiskMirror[1].pairIdentifier ^ 1)) )
- {
- if ( (pdev->DiskMirror[0].status & UCBF_MATCHED) && (pdev->DiskMirror[1].status & UCBF_MATCHED) )
- break;
-
- if ( pdev->DiskMirror[0].status & UCBF_SURVIVOR ) // is first drive survivor?
- testsize = SetReconstruct (pdev, 0);
- else
- if ( pdev->DiskMirror[1].status & UCBF_SURVIVOR ) // is second drive survivor?
- testsize = SetReconstruct (pdev, 1);
-
- if ( (pdev->DiskMirror[0].status & UCBF_REBUILD) || (pdev->DiskMirror[1].status & UCBF_REBUILD) )
- {
- if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
- pdev->mirrorRecon = 0;
- else
- pdev->mirrorRecon = 1;
- pdev->reconOn = TRUE;
- }
- break;
- }
-
- if ( !pdev->reconOn )
- goto reconTimerExpiry;
-
- if ( padapter->bigD )
- {
- padapter->failRegister = 0;
- outb_p (~padapter->failRegister, padapter->regFail);
- }
- else
- {
- zc = ((inb_p (padapter->regStatSel) >> 3) | inb_p (padapter->regStatSel)) & 0x83; // mute the alarm
- outb_p (0xFF, padapter->regFail);
- }
-
- while ( 1 )
- {
- DEB (printk ("\npci2220i: hard reset issue"));
- if ( HardReset (padapter, pdev, pdev->spigots[pdev->mirrorRecon]) )
- {
- DEB (printk ("\npci2220i: sub 1"));
- break;
- }
-
- pdev->lastsectorlba[pdev->mirrorRecon] = InlineIdentify (padapter, pdev->spigots[pdev->mirrorRecon], pdev->deviceID[pdev->mirrorRecon] & 1);
-
- if ( pdev->lastsectorlba[pdev->mirrorRecon] < testsize )
- {
- DEB (printk ("\npci2220i: sub 2 %ld %ld", pdev->lastsectorlba[pdev->mirrorRecon], testsize));
- break;
- }
-
- // test LBA and multiper sector transfer compatibility
- if (!pid->SupportLBA || (pid->NumSectorsPerInt < SECTORSXFER) || !pid->Valid_64_70 )
- {
- DEB (printk ("\npci2220i: sub 3"));
- break;
- }
-
- // test PIO/bus matering mode compatibility
- if ( (pid->MinPIOCycleWithoutFlow > 240) && !pid->SupportIORDYDisable && !padapter->timingPIO )
- {
- DEB (printk ("\npci2220i: sub 4"));
- break;
- }
-
- if ( pid->MinPIOCycleWithoutFlow <= 120 ) // setup timing mode of drive
- minmode = 5;
- else
- {
- if ( pid->MinPIOCylceWithFlow <= 150 )
- minmode = 4;
- else
- {
- if ( pid->MinPIOCylceWithFlow <= 180 )
- minmode = 3;
- else
- {
- if ( pid->MinPIOCylceWithFlow <= 240 )
- minmode = 2;
- else
- {
- DEB (printk ("\npci2220i: sub 5"));
- break;
- }
- }
- }
- }
-
- if ( padapter->timingMode > minmode ) // set minimum timing mode
- padapter->timingMode = minmode;
- if ( padapter->timingMode >= 2 )
- padapter->timingAddress = ModeArray[padapter->timingMode - 2];
- else
- padapter->timingPIO = TRUE;
-
- padapter->reconOn = TRUE;
- break;
- }
-
- if ( !pdev->reconOn )
- {
- padapter->survivor = pdev->mirrorRecon ^ 1;
- padapter->reconPhase = RECON_PHASE_FAILOVER;
- DEB (printk ("\npci2220i: FAILURE 7"));
- InitFailover (padapter, pdev);
- goto reconTimerExpiry;
- }
-
- pdev->raid = TRUE;
-
- if ( WriteSignature (padapter, pdev, pdev->spigot, pdev->mirrorRecon ^ 1) )
- goto reconTimerExpiry;
- padapter->reconPhase = RECON_PHASE_MARKING;
- goto reconTimerExpiry;
- }
-
- //**********************************
- // reconstruct copy starts here
- //**********************************
- if ( pdev->reconCount++ > 2000 )
- {
- pdev->reconCount = 0;
- if ( WriteSignature (padapter, pdev, pdev->spigots[pdev->mirrorRecon], pdev->mirrorRecon) )
- {
- padapter->survivor = pdev->mirrorRecon ^ 1;
- padapter->reconPhase = RECON_PHASE_FAILOVER;
- DEB (printk ("\npci2220i: FAILURE 8"));
- InitFailover (padapter, pdev);
- goto reconTimerExpiry;
- }
- padapter->reconPhase = RECON_PHASE_UPDATE;
- goto reconTimerExpiry;
- }
-
- zl = pdev->DiskMirror[pdev->mirrorRecon].reconstructPoint;
- padapter->reconSize = pdev->DiskMirror[pdev->mirrorRecon ^ 1].reconstructPoint - zl;
- if ( padapter->reconSize > MAX_BUS_MASTER_BLOCKS )
- padapter->reconSize = MAX_BUS_MASTER_BLOCKS;
-
- if ( padapter->reconSize )
- {
- SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1]); // select the spigots
- outb_p (pdev->byte6 | ((UCHAR *)(&zl))[3], padapter->regLba24); // select the drive
- SelectSpigot (padapter, pdev->spigot);
- if ( WaitReady (padapter) )
- goto reconTimerExpiry;
-
- SelectSpigot (padapter, pdev->spigots[pdev->mirrorRecon]);
- if ( WaitReady (padapter) )
- {
- padapter->survivor = pdev->mirrorRecon ^ 1;
- padapter->reconPhase = RECON_PHASE_FAILOVER;
- DEB (printk ("\npci2220i: FAILURE 9"));
- InitFailover (padapter, pdev);
- goto reconTimerExpiry;
- }
-
- SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1]);
- outb_p (padapter->reconSize & 0xFF, padapter->regSectCount);
- outb_p (((UCHAR *)(&zl))[0], padapter->regLba0);
- outb_p (((UCHAR *)(&zl))[1], padapter->regLba8);
- outb_p (((UCHAR *)(&zl))[2], padapter->regLba16);
- padapter->expectingIRQ = TRUE;
- padapter->reconPhase = RECON_PHASE_READY;
- SelectSpigot (padapter, pdev->spigots[pdev->mirrorRecon]);
- WriteCommand (padapter, WRITE_CMD);
- StartTimer (padapter);
- SelectSpigot (padapter, pdev->spigot);
- WriteCommand (padapter, READ_CMD);
- goto reconTimerExpiry;
- }
-
- pdev->DiskMirror[pdev->mirrorRecon].status = UCBF_MIRRORED | UCBF_MATCHED;
- pdev->DiskMirror[pdev->mirrorRecon ^ 1].status = UCBF_MIRRORED | UCBF_MATCHED;
- if ( WriteSignature (padapter, pdev, pdev->spigot, pdev->mirrorRecon ^ 1) )
- goto reconTimerExpiry;
- padapter->reconPhase = RECON_PHASE_LAST;
-
-reconTimerExpiry:;
- /*
- * Release the I/O spinlock and restore the original flags
- * which will enable interrupts if and only if they were
- * enabled on entry.
- */
- spin_unlock_irqrestore(host->host_lock, flags);
- }
-/****************************************************************
- * Name: Irq_Handler :LOCAL
- *
- * Description: Interrupt handler.
- *
- * Parameters: irq - Hardware IRQ number.
- * dev_id -
- * regs -
- *
- * Returns: TRUE if drive is not ready in time.
- *
- ****************************************************************/
-static irqreturn_t Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
- {
- struct Scsi_Host *shost = NULL; // Pointer to host data block
- PADAPTER2220I padapter; // Pointer to adapter control structure
- POUR_DEVICE pdev;
- Scsi_Cmnd *SCpnt;
- UCHAR status;
- UCHAR status1;
- ATAPI_STATUS statusa;
- ATAPI_REASON reasona;
- ATAPI_ERROR errora;
- int z;
- ULONG zl;
- unsigned long flags;
- int handled = 0;
-
-// DEB (printk ("\npci2220i received interrupt\n"));
-
- for ( z = 0; z < NumAdapters; z++ ) // scan for interrupt to process
- {
- if ( PsiHost[z]->irq == (UCHAR)(irq & 0xFF) )
- {
- if ( inw_p (HOSTDATA(PsiHost[z])->regIrqControl) & 0x8000 )
- {
- shost = PsiHost[z];
- break;
- }
- }
- }
-
- if ( !shost )
- {
- DEB (printk ("\npci2220i: not my interrupt"));
- goto out;
- }
-
- handled = 1;
- spin_lock_irqsave(shost->host_lock, flags);
- padapter = HOSTDATA(shost);
- pdev = padapter->pdev;
- SCpnt = padapter->SCpnt;
- outb_p (0x08, padapter->regDmaCmdStat); // cancel interrupt from DMA engine
-
- if ( padapter->atapi && SCpnt )
- {
- *(char *)&statusa = inb_p (padapter->regStatCmd); // read the device status
- *(char *)&reasona = inb_p (padapter->regSectCount); // read the device interrupt reason
-
- if ( !statusa.bsy )
- {
- if ( statusa.drq ) // test for transfer phase
- {
- if ( !reasona.cod ) // test for data phase
- {
- z = (ULONG)inb_p (padapter->regLba8) | (ULONG)(inb_p (padapter->regLba16) << 8);
- if ( padapter->reqSense )
- insw (padapter->regData, SCpnt->sense_buffer, z / 2);
- else
- AtapiBusMaster (padapter, reasona.io, z);
- goto irq_return;
- }
- if ( reasona.cod && !reasona.io ) // test for command packet phase
- {
- if ( padapter->reqSense )
- AtapiRequestSense (padapter, pdev, SCpnt, TRUE);
- else
- AtapiSendCdb (padapter, pdev, padapter->atapiCdb);
- goto irq_return;
- }
- }
- else
- {
- if ( reasona.io && statusa.drdy ) // test for status phase
- {
- Atapi2Scsi (padapter, SCpnt);
- if ( statusa.check )
- {
- *(UCHAR *)&errora = inb_p (padapter->regError); // read the device error
- if ( errora.senseKey )
- {
- if ( padapter->reqSense || AtapiRequestSense (padapter, pdev, SCpnt, FALSE) )
- OpDone (padapter, DID_ERROR << 16);
- }
- else
- {
- if ( errora.ili || errora.abort )
- OpDone (padapter, DID_ERROR << 16);
- else
- OpDone (padapter, DID_OK << 16);
- }
- }
- else
- if ( padapter->reqSense )
- {
- DEB (printk ("PCI2242I: Sense codes - %X %X %X ", ((UCHAR *)SCpnt->sense_buffer)[0], ((UCHAR *)SCpnt->sense_buffer)[12], ((UCHAR *)SCpnt->sense_buffer)[13]));
- OpDone (padapter, (DRIVER_SENSE << 24) | (DID_OK << 16) | 2);
- }
- else
- OpDone (padapter, DID_OK << 16);
- }
- }
- }
- goto irq_return;
- }
-
- if ( !padapter->expectingIRQ || !(SCpnt || padapter->reconPhase) )
- {
- DEB(printk ("\npci2220i Unsolicited interrupt\n"));
- STOP_HERE ();
- goto irq_return;
- }
- padapter->expectingIRQ = 0;
-
- if ( padapter->failinprog )
- {
- DEB (printk ("\npci2220i interrupt failover complete"));
- padapter->failinprog = FALSE;
- status = inb_p (padapter->regStatCmd); // read the device status
- if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
- {
- DEB (printk ("\npci2220i: interrupt failover error from drive %X", status));
- padapter->cmd = 0;
- }
- else
- {
- DEB (printk ("\npci2220i: restarting failed opertation."));
- pdev->spigot = (padapter->survivor) ? pdev->spigots[1] : pdev->spigots[0];
- del_timer (&padapter->timer);
- if ( padapter->reconPhase )
- OpDone (padapter, DID_OK << 16);
- else
- Pci2220i_QueueCommand (SCpnt, SCpnt->scsi_done);
- goto irq_return;
- }
- }
-
- if ( padapter->reconPhase )
- {
- switch ( padapter->reconPhase )
- {
- case RECON_PHASE_MARKING:
- case RECON_PHASE_LAST:
- status = inb_p (padapter->regStatCmd); // read the device status
- del_timer (&padapter->timer);
- if ( padapter->reconPhase == RECON_PHASE_LAST )
- {
- if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
- {
- padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 1 : 0;
- DEB (printk ("\npci2220i: FAILURE 10"));
- if ( InitFailover (padapter, pdev) )
- OpDone (padapter, DecodeError (padapter, status));
- goto irq_return;
- }
- if ( WriteSignature (padapter, pdev, pdev->spigots[pdev->mirrorRecon], pdev->mirrorRecon) )
- {
- padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
- DEB (printk ("\npci2220i: FAILURE 11"));
- if ( InitFailover (padapter, pdev) )
- OpDone (padapter, DecodeError (padapter, status));
- goto irq_return;
- }
- padapter->reconPhase = RECON_PHASE_END;
- goto irq_return;
- }
- OpDone (padapter, DID_OK << 16);
- goto irq_return;
-
- case RECON_PHASE_READY:
- status = inb_p (padapter->regStatCmd); // read the device status
- if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
- {
- del_timer (&padapter->timer);
- OpDone (padapter, DecodeError (padapter, status));
- goto irq_return;
- }
- SelectSpigot (padapter, pdev->spigots[pdev->mirrorRecon]);
- if ( WaitDrq (padapter) )
- {
- del_timer (&padapter->timer);
- padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
- DEB (printk ("\npci2220i: FAILURE 12"));
- if ( InitFailover (padapter, pdev) )
- OpDone (padapter, DecodeError (padapter, status));
- goto irq_return;
- }
- SelectSpigot (padapter, pdev->spigot | SEL_COPY | padapter->bigD);
- padapter->reconPhase = RECON_PHASE_COPY;
- padapter->expectingIRQ = TRUE;
- if ( padapter->timingPIO )
- {
- insw (padapter->regData, padapter->kBuffer, padapter->reconSize * (BYTES_PER_SECTOR / 2));
- }
- else
- {
- if ( (padapter->timingMode > 3) )
- {
- if ( padapter->bigD )
- outl (BIGD_DATA_MODE3, padapter->regDmaAddrLoc);
- else
- outl (DALE_DATA_MODE3, padapter->regDmaAddrLoc);
- }
- else
- outl (padapter->timingAddress, padapter->regDmaAddrLoc);
- outl (padapter->kBufferDma, padapter->regDmaAddrPci);
- outl (padapter->reconSize * BYTES_PER_SECTOR, padapter->regDmaCount);
- outb_p (8, padapter->regDmaDesc); // read operation
- if ( padapter->bigD )
- outb_p (8, padapter->regDmaMode); // no interrupt
- else
- outb_p (1, padapter->regDmaMode); // no interrupt
- outb_p (0x03, padapter->regDmaCmdStat); // kick the DMA engine in gear
- }
- goto irq_return;
-
- case RECON_PHASE_COPY:
- pdev->DiskMirror[pdev->mirrorRecon].reconstructPoint += padapter->reconSize;
-
- case RECON_PHASE_UPDATE:
- SelectSpigot (padapter, pdev->spigots[pdev->mirrorRecon] | SEL_IRQ_OFF);
- status = inb_p (padapter->regStatCmd); // read the device status
- del_timer (&padapter->timer);
- if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
- {
- padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
- DEB (printk ("\npci2220i: FAILURE 13"));
- DEB (printk ("\n status register = %X error = %X", status, inb_p (padapter->regError)));
- if ( InitFailover (padapter, pdev) )
- OpDone (padapter, DecodeError (padapter, status));
- goto irq_return;
- }
- OpDone (padapter, DID_OK << 16);
- goto irq_return;
-
- case RECON_PHASE_END:
- status = inb_p (padapter->regStatCmd); // read the device status
- del_timer (&padapter->timer);
- if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
- {
- padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
- DEB (printk ("\npci2220i: FAILURE 14"));
- if ( InitFailover (padapter, pdev) )
- OpDone (padapter, DecodeError (padapter, status));
- goto irq_return;
- }
- pdev->reconOn = 0;
- if ( padapter->bigD )
- {
- for ( z = 0; z < padapter->numberOfDrives; z++ )
- {
- if ( padapter->device[z].DiskMirror[0].status & UCBF_SURVIVOR )
- {
- Alarm (padapter, padapter->device[z].deviceID[0] ^ 2);
- MuteAlarm (padapter);
- }
- if ( padapter->device[z].DiskMirror[1].status & UCBF_SURVIVOR )
- {
- Alarm (padapter, padapter->device[z].deviceID[1] ^ 2);
- MuteAlarm (padapter);
- }
- }
- }
- OpDone (padapter, DID_OK << 16);
- goto irq_return;
-
- default:
- goto irq_return;
- }
- }
-
- switch ( padapter->cmd ) // decide how to handle the interrupt
- {
- case READ_CMD:
- if ( padapter->sectorCount )
- {
- status = inb_p (padapter->regStatCmd); // read the device status
- if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
- {
- if ( pdev->raid )
- {
- padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 1 : 0;
- del_timer (&padapter->timer);
- DEB (printk ("\npci2220i: FAILURE 15"));
- if ( !InitFailover (padapter, pdev) )
- goto irq_return;
- }
- break;
- }
- if ( padapter->timingPIO )
- {
- insw (padapter->regData, padapter->kBuffer, padapter->readCount / 2);
- padapter->sectorCount -= padapter->readCount / BYTES_PER_SECTOR;
- WalkScatGath (padapter, TRUE, padapter->readCount);
- if ( !padapter->sectorCount )
- {
- status = 0;
- break;
- }
- }
- else
- {
- if ( padapter->readCount )
- WalkScatGath (padapter, TRUE, padapter->readCount);
- BusMaster (padapter, 1, 1);
- }
- padapter->expectingIRQ = TRUE;
- goto irq_return;
- }
- if ( padapter->readCount && !padapter->timingPIO )
- WalkScatGath (padapter, TRUE, padapter->readCount);
- status = 0;
- break;
-
- case WRITE_CMD:
- if ( pdev->raid )
- {
- SelectSpigot (padapter, pdev->spigots[0] | SEL_IRQ_OFF);
- status = inb_p (padapter->regStatCmd); // read the device status
- SelectSpigot (padapter, pdev->spigots[1] | SEL_IRQ_OFF);
- status1 = inb_p (padapter->regStatCmd); // read the device status
- }
- else
- SelectSpigot (padapter, pdev->spigot | SEL_IRQ_OFF);
- status = inb_p (padapter->regStatCmd); // read the device status
- status1 = 0;
-
- if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
- {
- if ( pdev->raid && !(status1 & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT)) )
- {
- padapter->survivor = 1;
- del_timer (&padapter->timer);
- SelectSpigot (padapter, pdev->spigot | SEL_IRQ_OFF);
- DEB (printk ("\npci2220i: FAILURE 16 status = %X error = %X", status, inb_p (padapter->regError)));
- if ( !InitFailover (padapter, pdev) )
- goto irq_return;
- }
- break;
- }
- if ( pdev->raid )
- {
- if ( status1 & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
- {
- padapter->survivor = 0;
- del_timer (&padapter->timer);
- DEB (printk ("\npci2220i: FAILURE 17 status = %X error = %X", status1, inb_p (padapter->regError)));
- if ( !InitFailover (padapter, pdev) )
- goto irq_return;
- status = status1;
- break;
- }
- if ( padapter->sectorCount )
- {
- status = WriteDataBoth (padapter, pdev);
- if ( status )
- {
- padapter->survivor = status >> 1;
- del_timer (&padapter->timer);
- DEB (printk ("\npci2220i: FAILURE 18"));
- if ( !InitFailover (padapter, pdev) )
- goto irq_return;
- SelectSpigot (padapter, pdev->spigots[status] | SEL_IRQ_OFF);
- status = inb_p (padapter->regStatCmd); // read the device status
- break;
- }
- padapter->expectingIRQ = TRUE;
- goto irq_return;
- }
- status = 0;
- break;
- }
- if ( padapter->sectorCount )
- {
- SelectSpigot (padapter, pdev->spigot | padapter->bigD);
- status = WriteData (padapter);
- if ( status )
- break;
- padapter->expectingIRQ = TRUE;
- goto irq_return;
- }
- status = 0;
- break;
-
- case IDE_COMMAND_IDENTIFY:
- {
- PINQUIRYDATA pinquiryData = SCpnt->request_buffer;
- PIDENTIFY_DATA pid = (PIDENTIFY_DATA)padapter->kBuffer;
-
- status = inb_p (padapter->regStatCmd);
- if ( status & IDE_STATUS_DRQ )
- {
- insw (padapter->regData, pid, sizeof (IDENTIFY_DATA) >> 1);
-
- memset (pinquiryData, 0, SCpnt->request_bufflen); // Zero INQUIRY data structure.
- pinquiryData->DeviceType = 0;
- pinquiryData->Versions = 2;
- pinquiryData->AdditionalLength = 35 - 4;
-
- // Fill in vendor identification fields.
- for ( z = 0; z < 20; z += 2 )
- {
- pinquiryData->VendorId[z] = ((UCHAR *)pid->ModelNumber)[z + 1];
- pinquiryData->VendorId[z + 1] = ((UCHAR *)pid->ModelNumber)[z];
- }
-
- // Initialize unused portion of product id.
- for ( z = 0; z < 4; z++ )
- pinquiryData->ProductId[12 + z] = ' ';
-
- // Move firmware revision from IDENTIFY data to
- // product revision in INQUIRY data.
- for ( z = 0; z < 4; z += 2 )
- {
- pinquiryData->ProductRevisionLevel[z] = ((UCHAR *)pid->FirmwareRevision)[z + 1];
- pinquiryData->ProductRevisionLevel[z + 1] = ((UCHAR *)pid->FirmwareRevision)[z];
- }
- if ( pdev == padapter->device )
- *((USHORT *)(&pinquiryData->VendorSpecific)) = DEVICE_DALE_1;
-
- status = 0;
- }
- break;
- }
-
- default:
- status = 0;
- break;
- }
-
- del_timer (&padapter->timer);
- if ( status )
- {
- DEB (printk ("\npci2220i Interrupt handler return error"));
- zl = DecodeError (padapter, status);
- }
- else
- zl = DID_OK << 16;
-
- OpDone (padapter, zl);
-irq_return:
- spin_unlock_irqrestore(shost->host_lock, flags);
-out:
- return IRQ_RETVAL(handled);
-}
-
-/****************************************************************
- * Name: Pci2220i_QueueCommand
- *
- * Description: Process a queued command from the SCSI manager.
- *
- * Parameters: SCpnt - Pointer to SCSI command structure.
- * done - Pointer to done function to call.
- *
- * Returns: Status code.
- *
- ****************************************************************/
-int Pci2220i_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
- {
- UCHAR *cdb = (UCHAR *)SCpnt->cmnd; // Pointer to SCSI CDB
- PADAPTER2220I padapter = HOSTDATA(SCpnt->device->host); // Pointer to adapter control structure
- POUR_DEVICE pdev = &padapter->device[SCpnt->device->id];// Pointer to device information
- UCHAR rc; // command return code
- int z;
- PDEVICE_RAID1 pdr;
-
- SCpnt->scsi_done = done;
- padapter->SCpnt = SCpnt; // Save this command data
- padapter->readCount = 0;
-
- if ( SCpnt->use_sg )
- {
- padapter->currentSgBuffer = ((struct scatterlist *)SCpnt->request_buffer)[0].address;
- padapter->currentSgCount = ((struct scatterlist *)SCpnt->request_buffer)[0].length;
- }
- else
- {
- padapter->currentSgBuffer = SCpnt->request_buffer;
- padapter->currentSgCount = SCpnt->request_bufflen;
- }
- padapter->nextSg = 1;
-
- if ( !done )
- {
- printk("pci2220i_queuecommand: %02X: done can't be NULL\n", *cdb);
- return 0;
- }
-
- if ( padapter->atapi )
- {
- UCHAR zlo, zhi;
-
- DEB (printk ("\nPCI2242I: ID %d, LUN %d opcode %X ", SCpnt->device->id, SCpnt->device->lun, *cdb));
- padapter->pdev = pdev;
- if ( !pdev->byte6 || SCpnt->device->lun )
- {
- OpDone (padapter, DID_BAD_TARGET << 16);
- return 0;
- }
-
- padapter->atapiSpecial = FALSE;
- padapter->reqSense = FALSE;
- memset (padapter->atapiCdb, 0, 16);
- SelectSpigot (padapter, pdev->spigot); // select the spigot
- AtapiDevice (padapter, pdev->byte6); // select the drive
- if ( AtapiWaitReady (padapter, 100) )
- {
- OpDone (padapter, DID_NO_CONNECT << 16);
- return 0;
- }
-
- switch ( cdb[0] )
- {
- case SCSIOP_MODE_SENSE:
- case SCSIOP_MODE_SELECT:
- Scsi2Atapi (padapter, SCpnt);
- z = SCpnt->request_bufflen + 4;
- break;
- case SCSIOP_READ6:
- case SCSIOP_WRITE6:
- Scsi2Atapi (padapter, SCpnt);
- z = SCpnt->request_bufflen;
- break;
- default:
- memcpy (padapter->atapiCdb, cdb, SCpnt->cmd_len);
- z = SCpnt->request_bufflen;
- break;
- }
- if ( z > ATAPI_TRANSFER )
- z = ATAPI_TRANSFER;
- zlo = (UCHAR)(z & 0xFF);
- zhi = (UCHAR)(z >> 8);
-
- AtapiCountLo (padapter, zlo);
- AtapiCountHi (padapter, zhi);
- outb_p (0, padapter->regError);
- WriteCommand (padapter, IDE_COMMAND_ATAPI_PACKET);
- if ( pdev->cmdDrqInt )
- return 0;
-
- if ( AtapiWaitDrq (padapter, 500) )
- {
- OpDone (padapter, DID_ERROR << 16);
- return 0;
- }
- AtapiSendCdb (padapter, pdev, padapter->atapiCdb);
- return 0;
- }
-
- if ( padapter->reconPhase )
- return 0;
- if ( padapter->reconTimer.data )
- {
- del_timer (&padapter->reconTimer);
- padapter->reconTimer.data = 0;
- }
-
- if ( (SCpnt->device->id >= padapter->numberOfDrives) || SCpnt->device->lun )
- {
- OpDone (padapter, DID_BAD_TARGET << 16);
- return 0;
- }
-
- switch ( *cdb )
- {
- case SCSIOP_INQUIRY: // inquiry CDB
- {
- if ( cdb[2] == SC_MY_RAID )
- {
- switch ( cdb[3] )
- {
- case MY_SCSI_REBUILD:
- for ( z = 0; z < padapter->numberOfDrives; z++ )
- {
- pdev = &padapter->device[z];
- if ( ((pdev->DiskMirror[0].status & UCBF_SURVIVOR) && (pdev->DiskMirror[1].status & UCBF_MIRRORED)) ||
- ((pdev->DiskMirror[1].status & UCBF_SURVIVOR) && (pdev->DiskMirror[0].status & UCBF_MIRRORED)) )
- {
- padapter->reconOn = pdev->reconOn = pdev->reconIsStarting = TRUE;
- }
- }
- OpDone (padapter, DID_OK << 16);
- break;
- case MY_SCSI_ALARMMUTE:
- MuteAlarm (padapter);
- OpDone (padapter, DID_OK << 16);
- break;
- case MY_SCSI_DEMOFAIL:
- padapter->demoFail = TRUE;
- OpDone (padapter, DID_OK << 16);
- break;
- default:
- z = cdb[5]; // get index
- pdr = (PDEVICE_RAID1)SCpnt->request_buffer;
- if ( padapter->raidData[z] )
- {
- memcpy (&pdr->DiskRaid1, padapter->raidData[z], sizeof (DISK_MIRROR));
- if ( padapter->raidData[z]->reconstructPoint > padapter->raidData[z ^ 2]->reconstructPoint )
- pdr->TotalSectors = padapter->raidData[z]->reconstructPoint;
- else
- pdr->TotalSectors = padapter->raidData[z ^ 2]->reconstructPoint;
- }
- else
- memset (pdr, 0, sizeof (DEVICE_RAID1));
- OpDone (padapter, DID_OK << 16);
- break;
- }
- return 0;
- }
- padapter->cmd = IDE_COMMAND_IDENTIFY;
- break;
- }
-
- case SCSIOP_TEST_UNIT_READY: // test unit ready CDB
- OpDone (padapter, DID_OK << 16);
- return 0;
- case SCSIOP_READ_CAPACITY: // read capctiy CDB
- {
- PREAD_CAPACITY_DATA pdata = (PREAD_CAPACITY_DATA)SCpnt->request_buffer;
-
- pdata->blksiz = 0x20000;
- XANY2SCSI ((UCHAR *)&pdata->blks, pdev->blocks);
- OpDone (padapter, DID_OK << 16);
- return 0;
- }
- case SCSIOP_VERIFY: // verify CDB
- padapter->startSector = XSCSI2LONG (&cdb[2]);
- padapter->sectorCount = (UCHAR)((USHORT)cdb[8] | ((USHORT)cdb[7] << 8));
- padapter->cmd = IDE_COMMAND_VERIFY;
- break;
- case SCSIOP_READ: // read10 CDB
- padapter->startSector = XSCSI2LONG (&cdb[2]);
- padapter->sectorCount = (USHORT)cdb[8] | ((USHORT)cdb[7] << 8);
- padapter->cmd = READ_CMD;
- break;
- case SCSIOP_READ6: // read6 CDB
- padapter->startSector = SCSI2LONG (&cdb[1]);
- padapter->sectorCount = cdb[4];
- padapter->cmd = READ_CMD;
- break;
- case SCSIOP_WRITE: // write10 CDB
- padapter->startSector = XSCSI2LONG (&cdb[2]);
- padapter->sectorCount = (USHORT)cdb[8] | ((USHORT)cdb[7] << 8);
- padapter->cmd = WRITE_CMD;
- break;
- case SCSIOP_WRITE6: // write6 CDB
- padapter->startSector = SCSI2LONG (&cdb[1]);
- padapter->sectorCount = cdb[4];
- padapter->cmd = WRITE_CMD;
- break;
- default:
- DEB (printk ("pci2220i_queuecommand: Unsupported command %02X\n", *cdb));
- OpDone (padapter, DID_ERROR << 16);
- return 0;
- }
-
- if ( padapter->reconPhase )
- return 0;
-
- padapter->pdev = pdev;
-
- while ( padapter->demoFail )
- {
- pdev = padapter->pdev = &padapter->device[0];
- padapter->demoFail = FALSE;
- if ( !pdev->raid ||
- (pdev->DiskMirror[0].status & UCBF_SURVIVOR) ||
- (pdev->DiskMirror[1].status & UCBF_SURVIVOR) )
- {
- break;
- }
- if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
- padapter->survivor = 1;
- else
- padapter->survivor = 0;
- DEB (printk ("\npci2220i: FAILURE 19"));
- if ( InitFailover (padapter, pdev) )
- break;
- return 0;
- }
-
- StartTimer (padapter);
- if ( pdev->raid && (padapter->cmd == WRITE_CMD) )
- {
- rc = IdeCmdBoth (padapter, pdev);
- if ( !rc )
- rc = WriteDataBoth (padapter, pdev);
- if ( rc )
- {
- del_timer (&padapter->timer);
- padapter->expectingIRQ = 0;
- padapter->survivor = rc >> 1;
- DEB (printk ("\npci2220i: FAILURE 20"));
- if ( InitFailover (padapter, pdev) )
- {
- OpDone (padapter, DID_ERROR << 16);
- return 0;
- }
- }
- }
- else
- {
- rc = IdeCmd (padapter, pdev);
- if ( (padapter->cmd == WRITE_CMD) && !rc )
- rc = WriteData (padapter);
- if ( rc )
- {
- del_timer (&padapter->timer);
- padapter->expectingIRQ = 0;
- if ( pdev->raid )
- {
- padapter->survivor = (pdev->spigot ^ 3) >> 1;
- DEB (printk ("\npci2220i: FAILURE 21"));
- if ( !InitFailover (padapter, pdev) )
- return 0;
- }
- OpDone (padapter, DID_ERROR << 16);
- return 0;
- }
- }
- return 0;
- }
-/****************************************************************
- * Name: ReadFlash
- *
- * Description: Read information from controller Flash memory.
- *
- * Parameters: padapter - Pointer to host interface data structure.
- * pdata - Pointer to data structures.
- * base - base address in Flash.
- * length - lenght of data space in bytes.
- *
- * Returns: Nothing.
- *
- ****************************************************************/
-static VOID ReadFlash (PADAPTER2220I padapter, VOID *pdata, ULONG base, ULONG length)
- {
- ULONG oldremap;
- UCHAR olddesc;
- ULONG z;
- UCHAR *pd = (UCHAR *)pdata;
-
- oldremap = inl (padapter->regRemap); // save values to restore later
- olddesc = inb_p (padapter->regDesc);
-
- outl (base | 1, padapter->regRemap); // remap to Flash space as specified
- outb_p (0x40, padapter->regDesc); // describe remap region as 8 bit
- for ( z = 0; z < length; z++) // get "length" data count
- *pd++ = inb_p (padapter->regBase + z); // read in the data
-
- outl (oldremap, padapter->regRemap); // restore remap register values
- outb_p (olddesc, padapter->regDesc);
- }
-/****************************************************************
- * Name: GetRegs
- *
- * Description: Initialize the regester information.
- *
- * Parameters: pshost - Pointer to SCSI host data structure.
- * bigd - PCI-2240I identifier
- * pcidev - Pointer to device data structure.
- *
- * Returns: TRUE if failure to install.
- *
- ****************************************************************/
-static USHORT GetRegs (struct Scsi_Host *pshost, BOOL bigd, struct pci_dev *pcidev)
- {
- PADAPTER2220I padapter;
- int setirq;
- int z;
- USHORT zr, zl;
- UCHAR *consistent;
- dma_addr_t consistentDma;
-
- padapter = HOSTDATA(pshost);
- memset (padapter, 0, sizeof (ADAPTER2220I));
- memset (&DaleSetup, 0, sizeof (DaleSetup));
- memset (DiskMirror, 0, sizeof (DiskMirror));
-
- zr = pci_resource_start (pcidev, 1);
- zl = pci_resource_start (pcidev, 2);
-
- padapter->basePort = zr;
- padapter->regRemap = zr + RTR_LOCAL_REMAP; // 32 bit local space remap
- padapter->regDesc = zr + RTR_REGIONS; // 32 bit local region descriptor
- padapter->regRange = zr + RTR_LOCAL_RANGE; // 32 bit local range
- padapter->regIrqControl = zr + RTR_INT_CONTROL_STATUS; // 16 bit interrupt control and status
- padapter->regScratchPad = zr + RTR_MAILBOX; // 16 byte scratchpad I/O base address
-
- padapter->regBase = zl;
- padapter->regData = zl + REG_DATA; // data register I/O address
- padapter->regError = zl + REG_ERROR; // error register I/O address
- padapter->regSectCount = zl + REG_SECTOR_COUNT; // sector count register I/O address
- padapter->regLba0 = zl + REG_LBA_0; // least significant byte of LBA
- padapter->regLba8 = zl + REG_LBA_8; // next least significant byte of LBA
- padapter->regLba16 = zl + REG_LBA_16; // next most significan byte of LBA
- padapter->regLba24 = zl + REG_LBA_24; // head and most 4 significant bits of LBA
- padapter->regStatCmd = zl + REG_STAT_CMD; // status on read and command on write register
- padapter->regStatSel = zl + REG_STAT_SEL; // board status on read and spigot select on write register
- padapter->regFail = zl + REG_FAIL;
- padapter->regAltStat = zl + REG_ALT_STAT;
- padapter->pcidev = pcidev;
-
- if ( bigd )
- {
- padapter->regDmaDesc = zr + RTR_DMA0_DESC_PTR; // address of the DMA discriptor register for direction of transfer
- padapter->regDmaCmdStat = zr + RTR_DMA_COMMAND_STATUS; // Byte #0 of DMA command status register
- padapter->regDmaAddrPci = zr + RTR_DMA0_PCI_ADDR; // 32 bit register for PCI address of DMA
- padapter->regDmaAddrLoc = zr + RTR_DMA0_LOCAL_ADDR; // 32 bit register for local bus address of DMA
- padapter->regDmaCount = zr + RTR_DMA0_COUNT; // 32 bit register for DMA transfer count
- padapter->regDmaMode = zr + RTR_DMA0_MODE + 1; // 32 bit register for DMA mode control
- padapter->bigD = SEL_NEW_SPEED_1; // set spigot speed control bit
- }
- else
- {
- padapter->regDmaDesc = zl + RTL_DMA1_DESC_PTR; // address of the DMA discriptor register for direction of transfer
- padapter->regDmaCmdStat = zl + RTL_DMA_COMMAND_STATUS + 1; // Byte #1 of DMA command status register
- padapter->regDmaAddrPci = zl + RTL_DMA1_PCI_ADDR; // 32 bit register for PCI address of DMA
- padapter->regDmaAddrLoc = zl + RTL_DMA1_LOCAL_ADDR; // 32 bit register for local bus address of DMA
- padapter->regDmaCount = zl + RTL_DMA1_COUNT; // 32 bit register for DMA transfer count
- padapter->regDmaMode = zl + RTL_DMA1_MODE + 1; // 32 bit register for DMA mode control
- }
-
- padapter->numberOfDrives = inb_p (padapter->regScratchPad + BIGD_NUM_DRIVES);
- if ( !bigd && !padapter->numberOfDrives ) // if no devices on this board
- return TRUE;
-
- pshost->irq = pcidev->irq;
- setirq = 1;
- for ( z = 0; z < Installed; z++ ) // scan for shared interrupts
- {
- if ( PsiHost[z]->irq == pshost->irq ) // if shared then, don't posses
- setirq = 0;
- }
- if ( setirq ) // if not shared, posses
- {
- if ( request_irq (pshost->irq, Irq_Handler, SA_SHIRQ, "pci2220i", padapter) < 0 )
- {
- if ( request_irq (pshost->irq, Irq_Handler, SA_INTERRUPT | SA_SHIRQ, "pci2220i", padapter) < 0 )
- {
- printk ("Unable to allocate IRQ for PCI-2220I controller.\n");
- return TRUE;
- }
- }
- padapter->irqOwned = pshost->irq; // set IRQ as owned
- }
-
- if ( padapter->numberOfDrives )
- consistent = pci_alloc_consistent (pcidev, SECTORSXFER * BYTES_PER_SECTOR, &consistentDma);
- else
- consistent = pci_alloc_consistent (pcidev, ATAPI_TRANSFER, &consistentDma);
- if ( !consistent )
- {
- printk ("Unable to allocate DMA buffer for PCI-2220I controller.\n");
- free_irq (pshost->irq, padapter);
- return TRUE;
- }
- padapter->kBuffer = consistent;
- padapter->kBufferDma = consistentDma;
-
- PsiHost[Installed] = pshost; // save SCSI_HOST pointer
- pshost->io_port = padapter->basePort;
- pshost->n_io_port = 0xFF;
- pshost->unique_id = padapter->regBase;
-
- outb_p (0x01, padapter->regRange); // fix our range register because other drivers want to tromp on it
-
- padapter->timingMode = inb_p (padapter->regScratchPad + DALE_TIMING_MODE);
- if ( padapter->timingMode >= 2 )
- {
- if ( bigd )
- padapter->timingAddress = ModeArray2[padapter->timingMode - 2];
- else
- padapter->timingAddress = ModeArray[padapter->timingMode - 2];
- }
- else
- padapter->timingPIO = TRUE;
-
- ReadFlash (padapter, &DaleSetup, DALE_FLASH_SETUP, sizeof (SETUP));
- ReadFlash (padapter, &DiskMirror, DALE_FLASH_RAID, sizeof (DiskMirror));
-
- return FALSE;
- }
-/****************************************************************
- * Name: SetupFinish
- *
- * Description: Complete the driver initialization process for a card
- *
- * Parameters: padapter - Pointer to SCSI host data structure.
- * str - Pointer to board type string.
- *
- * Returns: Nothing.
- *
- ****************************************************************/
-VOID SetupFinish (PADAPTER2220I padapter, char *str, int irq)
- {
- init_timer (&padapter->timer);
- padapter->timer.function = TimerExpiry;
- padapter->timer.data = (unsigned long)padapter;
- init_timer (&padapter->reconTimer);
- padapter->reconTimer.function = ReconTimerExpiry;
- padapter->reconTimer.data = (unsigned long)padapter;
- printk("\nPCI-%sI EIDE CONTROLLER: at I/O = %lX/%lX IRQ = %d\n", str, padapter->basePort, padapter->regBase, irq);
- printk("Version %s, Compiled %s %s\n\n", PCI2220I_VERSION, __DATE__, __TIME__);
- }
-/****************************************************************
- * Name: Pci2220i_Detect
- *
- * Description: Detect and initialize our boards.
- *
- * Parameters: tpnt - Pointer to SCSI host template structure.
- *
- * Returns: Number of adapters installed.
- *
- ****************************************************************/
-int Pci2220i_Detect (Scsi_Host_Template *tpnt)
- {
- struct Scsi_Host *pshost;
- PADAPTER2220I padapter;
- POUR_DEVICE pdev;
- int unit;
- int z;
- USHORT raidon;
- UCHAR spigot1, spigot2;
- UCHAR device;
- struct pci_dev *pcidev = NULL;
-
- while ( (pcidev = pci_find_device (VENDOR_PSI, DEVICE_DALE_1, pcidev)) != NULL )
- {
- if (pci_enable_device(pcidev))
- continue;
- pshost = scsi_register (tpnt, sizeof(ADAPTER2220I));
- if(pshost==NULL)
- continue;
-
- padapter = HOSTDATA(pshost);
-
- if ( GetRegs (pshost, FALSE, pcidev) )
- goto unregister;
-
- scsi_set_device(pshost, &pcidev->dev);
- pshost->max_id = padapter->numberOfDrives;
- for ( z = 0; z < padapter->numberOfDrives; z++ )
- {
- unit = inb_p (padapter->regScratchPad + DALE_CHANNEL_DEVICE_0 + z) & 0x0F;
- pdev = &padapter->device[z];
- pdev->byte6 = (UCHAR)(((unit & 1) << 4) | 0xE0);
- pdev->spigot = (UCHAR)(1 << (unit >> 1));
- pdev->sectors = DaleSetup.setupDevice[unit].sectors;
- pdev->heads = DaleSetup.setupDevice[unit].heads;
- pdev->cylinders = DaleSetup.setupDevice[unit].cylinders;
- pdev->blocks = DaleSetup.setupDevice[unit].blocks;
-
- if ( !z )
- {
- DiskMirror[0].status = inb_p (padapter->regScratchPad + DALE_RAID_0_STATUS);
- DiskMirror[1].status = inb_p (padapter->regScratchPad + DALE_RAID_1_STATUS);
- if ( (DiskMirror[0].signature == SIGNATURE) && (DiskMirror[1].signature == SIGNATURE) &&
- (DiskMirror[0].pairIdentifier == (DiskMirror[1].pairIdentifier ^ 1)) )
- {
- raidon = TRUE;
- if ( unit > (unit ^ 2) )
- unit = unit ^ 2;
- }
- else
- raidon = FALSE;
-
- memcpy (pdev->DiskMirror, DiskMirror, sizeof (DiskMirror));
- padapter->raidData[0] = &pdev->DiskMirror[0];
- padapter->raidData[2] = &pdev->DiskMirror[1];
-
- spigot1 = spigot2 = FALSE;
- pdev->spigots[0] = 1;
- pdev->spigots[1] = 2;
- pdev->lastsectorlba[0] = InlineIdentify (padapter, 1, 0);
- pdev->lastsectorlba[1] = InlineIdentify (padapter, 2, 0);
-
- if ( !(pdev->DiskMirror[1].status & UCBF_SURVIVOR) && pdev->lastsectorlba[0] )
- spigot1 = TRUE;
- if ( !(pdev->DiskMirror[0].status & UCBF_SURVIVOR) && pdev->lastsectorlba[1] )
- spigot2 = TRUE;
- if ( pdev->DiskMirror[0].status & DiskMirror[1].status & UCBF_SURVIVOR )
- spigot1 = TRUE;
-
- if ( spigot1 && (pdev->DiskMirror[0].status & UCBF_REBUILD) )
- InlineReadSignature (padapter, pdev, 0);
- if ( spigot2 && (pdev->DiskMirror[1].status & UCBF_REBUILD) )
- InlineReadSignature (padapter, pdev, 1);
-
- if ( spigot1 && spigot2 && raidon )
- {
- pdev->raid = 1;
- if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
- pdev->spigot = 2;
- else
- pdev->spigot = 1;
- if ( (pdev->DiskMirror[0].status & UCBF_REBUILD) || (pdev->DiskMirror[1].status & UCBF_REBUILD) )
- padapter->reconOn = pdev->reconOn = pdev->reconIsStarting = TRUE;
- }
- else
- {
- if ( spigot1 )
- {
- if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
- goto unregister;
- pdev->DiskMirror[0].status = UCBF_MIRRORED | UCBF_SURVIVOR;
- pdev->spigot = 1;
- }
- else
- {
- if ( pdev->DiskMirror[1].status & UCBF_REBUILD )
- goto unregister;
- pdev->DiskMirror[1].status = UCBF_MIRRORED | UCBF_SURVIVOR;
- pdev->spigot = 2;
- }
- if ( DaleSetup.rebootRebuild && raidon )
- padapter->reconOn = pdev->reconOn = pdev->reconIsStarting = TRUE;
- }
-
- if ( raidon )
- break;
- }
- }
-
- SetupFinish (padapter, "2220", pshost->irq);
-
- if ( ++Installed < MAXADAPTER )
- continue;
- break;
-unregister:;
- scsi_unregister (pshost);
- }
-
- while ( (pcidev = pci_find_device (VENDOR_PSI, DEVICE_BIGD_1, pcidev)) != NULL )
- {
- pshost = scsi_register (tpnt, sizeof(ADAPTER2220I));
- padapter = HOSTDATA(pshost);
-
- if ( GetRegs (pshost, TRUE, pcidev) )
- goto unregister1;
-
- for ( z = 0; z < BIGD_MAXDRIVES; z++ )
- DiskMirror[z].status = inb_p (padapter->regScratchPad + BIGD_RAID_0_STATUS + z);
-
- scsi_set_pci_device(pshost, pcidev);
- pshost->max_id = padapter->numberOfDrives;
- padapter->failRegister = inb_p (padapter->regScratchPad + BIGD_ALARM_IMAGE);
- for ( z = 0; z < padapter->numberOfDrives; z++ )
- {
- unit = inb_p (padapter->regScratchPad + BIGD_DEVICE_0 + z);
- pdev = &padapter->device[z];
- pdev->byte6 = (UCHAR)(((unit & 1) << 4) | 0xE0);
- pdev->spigot = (UCHAR)(1 << (unit >> 1));
- pdev->sectors = DaleSetup.setupDevice[unit].sectors;
- pdev->heads = DaleSetup.setupDevice[unit].heads;
- pdev->cylinders = DaleSetup.setupDevice[unit].cylinders;
- pdev->blocks = DaleSetup.setupDevice[unit].blocks;
-
- if ( (DiskMirror[unit].signature == SIGNATURE) && (DiskMirror[unit ^ 2].signature == SIGNATURE) &&
- (DiskMirror[unit].pairIdentifier == (DiskMirror[unit ^ 2].pairIdentifier ^ 1)) )
- {
- raidon = TRUE;
- if ( unit > (unit ^ 2) )
- unit = unit ^ 2;
- }
- else
- raidon = FALSE;
-
- spigot1 = spigot2 = FALSE;
- memcpy (&pdev->DiskMirror[0], &DiskMirror[unit], sizeof (DISK_MIRROR));
- memcpy (&pdev->DiskMirror[1], &DiskMirror[unit ^ 2], sizeof (DISK_MIRROR));
- padapter->raidData[unit] = &pdev->DiskMirror[0];
- padapter->raidData[unit ^ 2] = &pdev->DiskMirror[1];
- pdev->spigots[0] = 1 << (unit >> 1);
- pdev->spigots[1] = 1 << ((unit ^ 2) >> 1);
- pdev->deviceID[0] = unit;
- pdev->deviceID[1] = unit ^ 2;
- pdev->lastsectorlba[0] = InlineIdentify (padapter, pdev->spigots[0], unit & 1);
- pdev->lastsectorlba[1] = InlineIdentify (padapter, pdev->spigots[1], unit & 1);
-
- if ( !(pdev->DiskMirror[1].status & UCBF_SURVIVOR) && pdev->lastsectorlba[0] )
- spigot1 = TRUE;
- if ( !(pdev->DiskMirror[0].status & UCBF_SURVIVOR) && pdev->lastsectorlba[1] )
- spigot2 = TRUE;
- if ( pdev->DiskMirror[0].status & pdev->DiskMirror[1].status & UCBF_SURVIVOR )
- spigot1 = TRUE;
-
- if ( spigot1 && (pdev->DiskMirror[0].status & UCBF_REBUILD) )
- InlineReadSignature (padapter, pdev, 0);
- if ( spigot2 && (pdev->DiskMirror[1].status & UCBF_REBUILD) )
- InlineReadSignature (padapter, pdev, 1);
-
- if ( spigot1 && spigot2 && raidon )
- {
- pdev->raid = 1;
- if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
- pdev->spigot = pdev->spigots[1];
- else
- pdev->spigot = pdev->spigots[0];
- if ( (pdev->DiskMirror[0].status & UCBF_REBUILD) || (pdev->DiskMirror[1].status & UCBF_REBUILD) )
- padapter->reconOn = pdev->reconOn = pdev->reconIsStarting = TRUE;
- }
- else
- {
- if ( spigot1 )
- {
- if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
- goto unregister1;
- pdev->DiskMirror[0].status = UCBF_MIRRORED | UCBF_SURVIVOR;
- pdev->spigot = pdev->spigots[0];
- }
- else
- {
- if ( pdev->DiskMirror[1].status & UCBF_REBUILD )
- goto unregister;
- pdev->DiskMirror[1].status = UCBF_MIRRORED | UCBF_SURVIVOR;
- pdev->spigot = pdev->spigots[1];
- }
- if ( DaleSetup.rebootRebuild && raidon )
- padapter->reconOn = pdev->reconOn = pdev->reconIsStarting = TRUE;
- }
- }
-
- if ( !padapter->numberOfDrives ) // If no ATA devices then scan ATAPI
- {
- unit = 0;
- for ( spigot1 = 0; spigot1 < 4; spigot1++ )
- {
- for ( device = 0; device < 2; device++ )
- {
- DEB (printk ("\nPCI2242I: scanning for ID %d ", (spigot1 * 2) + device));
- pdev = &(padapter->device[(spigot1 * 2) + device]);
- pdev->byte6 = 0x0A | (device << 4);
- pdev->spigot = 1 << spigot1;
- if ( !AtapiReset (padapter, pdev) )
- {
- DEB (printk (" Device found "));
- if ( !AtapiIdentify (padapter, pdev) )
- {
- DEB (printk (" Device verified"));
- unit++;
- continue;
- }
- }
- pdev->spigot = pdev->byte6 = 0;
- }
- }
-
- if ( unit )
- {
- padapter->atapi = TRUE;
- padapter->timingAddress = DALE_DATA_MODE3;
- outw_p (0x0900, padapter->regIrqControl); // Turn our interrupts on
- outw_p (0x0C41, padapter->regDmaMode - 1); // setup for 16 bits, ready enabled, done IRQ enabled, no incriment
- outb_p (0xFF, padapter->regFail); // all fail lights and alarm off
- pshost->max_id = 8;
- }
- }
- SetupFinish (padapter, "2240", pshost->irq);
-
- if ( ++Installed < MAXADAPTER )
- continue;
- break;
-unregister1:;
- scsi_unregister (pshost);
- }
-
- NumAdapters = Installed;
- return Installed;
- }
-/****************************************************************
- * Name: Pci2220i_Abort
- *
- * Description: Process the Abort command from the SCSI manager.
- *
- * Parameters: SCpnt - Pointer to SCSI command structure.
- *
- * Returns: Allways snooze.
- *
- ****************************************************************/
-int Pci2220i_Abort (Scsi_Cmnd *SCpnt)
- {
- PADAPTER2220I padapter = HOSTDATA(SCpnt->device->host); // Pointer to adapter control structure
- POUR_DEVICE pdev = &padapter->device[SCpnt->device->id];// Pointer to device information
-
- if ( !padapter->SCpnt )
- return SCSI_ABORT_NOT_RUNNING;
-
- if ( padapter->atapi )
- {
- if ( AtapiReset (padapter, pdev) )
- return SCSI_ABORT_ERROR;
- OpDone (padapter, DID_ABORT << 16);
- return SCSI_ABORT_SUCCESS;
- }
- return SCSI_ABORT_SNOOZE;
- }
-/****************************************************************
- * Name: Pci2220i_Reset
- *
- * Description: Process the Reset command from the SCSI manager.
- *
- * Parameters: SCpnt - Pointer to SCSI command structure.
- * flags - Flags about the reset command
- *
- * Returns: No active command at this time, so this means
- * that each time we got some kind of response the
- * last time through. Tell the mid-level code to
- * request sense information in order to decide what
- * to do next.
- *
- ****************************************************************/
-int Pci2220i_Reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
- {
- PADAPTER2220I padapter = HOSTDATA(SCpnt->device->host); // Pointer to adapter control structure
- POUR_DEVICE pdev = &padapter->device[SCpnt->device->id];// Pointer to device information
-
- if ( padapter->atapi )
- {
- if ( AtapiReset (padapter, pdev) )
- return SCSI_RESET_ERROR;
- return SCSI_RESET_SUCCESS;
- }
- return SCSI_RESET_PUNT;
- }
-/****************************************************************
- * Name: Pci2220i_Release
- *
- * Description: Release resources allocated for a single each adapter.
- *
- * Parameters: pshost - Pointer to SCSI command structure.
- *
- * Returns: zero.
- *
- ****************************************************************/
-int Pci2220i_Release (struct Scsi_Host *pshost)
- {
- PADAPTER2220I padapter = HOSTDATA (pshost);
- USHORT z;
-
- if ( padapter->reconOn )
- {
- padapter->reconOn = FALSE; // shut down the hot reconstruct
- if ( padapter->reconPhase )
- mdelay (300);
- if ( padapter->reconTimer.data ) // is the timer running?
- {
- del_timer (&padapter->reconTimer);
- padapter->reconTimer.data = 0;
- }
- }
-
- // save RAID status on the board
- if ( padapter->bigD )
- {
- outb_p (padapter->failRegister, padapter->regScratchPad + BIGD_ALARM_IMAGE);
- for ( z = 0; z < BIGD_MAXDRIVES; z++ )
- {
- if ( padapter->raidData )
- outb_p (padapter->raidData[z]->status, padapter->regScratchPad + BIGD_RAID_0_STATUS + z);
- else
- outb_p (0, padapter->regScratchPad + BIGD_RAID_0_STATUS);
- }
- }
- else
- {
- outb_p (padapter->device[0].DiskMirror[0].status, padapter->regScratchPad + DALE_RAID_0_STATUS);
- outb_p (padapter->device[0].DiskMirror[1].status, padapter->regScratchPad + DALE_RAID_1_STATUS);
- }
-
- if ( padapter->irqOwned )
- free_irq (pshost->irq, padapter);
- release_region (pshost->io_port, pshost->n_io_port);
- if ( padapter->numberOfDrives )
- pci_free_consistent (padapter->pcidev, SECTORSXFER * BYTES_PER_SECTOR, padapter->kBuffer, padapter->kBufferDma);
- else
- pci_free_consistent (padapter->pcidev, ATAPI_TRANSFER, padapter->kBuffer, padapter->kBufferDma);
- scsi_unregister(pshost);
- return 0;
- }
-
-/****************************************************************
- * Name: Pci2220i_BiosParam
- *
- * Description: Process the biosparam request from the SCSI manager to
- * return C/H/S data.
- *
- * Parameters: disk - Pointer to SCSI disk structure.
- * dev - Major/minor number from kernel.
- * geom - Pointer to integer array to place geometry data.
- *
- * Returns: zero.
- *
- ****************************************************************/
-int Pci2220i_BiosParam (struct scsi_device *sdev, struct block_device *dev,
- sector_t capacity, int geom[])
- {
- POUR_DEVICE pdev;
-
- if ( !(HOSTDATA(sdev->host))->atapi )
- {
- pdev = &(HOSTDATA(sdev->host)->device[sdev->id]);
-
- geom[0] = pdev->heads;
- geom[1] = pdev->sectors;
- geom[2] = pdev->cylinders;
- }
- return 0;
- }
-
-MODULE_LICENSE("Dual BSD/GPL");
-
-static Scsi_Host_Template driver_template = {
- .proc_name = "pci2220i",
- .name = "PCI-2220I/PCI-2240I",
- .detect = Pci2220i_Detect,
- .release = Pci2220i_Release,
- .queuecommand = Pci2220i_QueueCommand,
- .abort = Pci2220i_Abort,
- .reset = Pci2220i_Reset,
- .bios_param = Pci2220i_BiosParam,
- .can_queue = 1,
- .this_id = -1,
- .sg_tablesize = SG_ALL,
- .cmd_per_lun = 1,
- .use_clustering = DISABLE_CLUSTERING,
-};
-#include "scsi_module.c"
diff --git a/drivers/scsi/pci2220i.h b/drivers/scsi/pci2220i.h
deleted file mode 100644
index 6926056c2ae..00000000000
--- a/drivers/scsi/pci2220i.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/****************************************************************************
- * Perceptive Solutions, Inc. PCI-2220I device driver for Linux.
- *
- * pci2220i.h - Linux Host Driver for PCI-2220i EIDE Adapters
- *
- * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
- * All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that redistributions of source
- * code retain the above copyright notice and this comment without
- * modification.
- *
- * Technical updates and product information at:
- * http://www.psidisk.com
- *
- * Please send questions, comments, bug reports to:
- * tech@psidisk.com Technical Support
- *
- ****************************************************************************/
-#ifndef _PCI2220I_H
-#define _PCI2220I_H
-
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h>
-#endif
-#define LINUXVERSION(v,p,s) (((v)<<16) + ((p)<<8) + (s))
-
-// function prototypes
-int Pci2220i_Detect (Scsi_Host_Template *tpnt);
-int Pci2220i_Command (Scsi_Cmnd *SCpnt);
-int Pci2220i_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *));
-int Pci2220i_Abort (Scsi_Cmnd *SCpnt);
-int Pci2220i_Reset (Scsi_Cmnd *SCpnt, unsigned int flags);
-int Pci2220i_Release (struct Scsi_Host *pshost);
-int Pci2220i_BiosParam (struct scsi_device *sdev,
- struct block_device *dev,
- sector_t capacity, int geom[]);
-#endif
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index 496c412c885..3dddb323e71 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -92,9 +92,7 @@ static Scsi_Host_Template nsp_driver_template = {
#endif
.info = nsp_info,
.queuecommand = nsp_queuecommand,
-/* .eh_strategy_handler = nsp_eh_strategy,*/
/* .eh_abort_handler = nsp_eh_abort,*/
-/* .eh_device_reset_handler = nsp_eh_device_reset,*/
.eh_bus_reset_handler = nsp_eh_bus_reset,
.eh_host_reset_handler = nsp_eh_host_reset,
.can_queue = 1,
@@ -1536,11 +1534,6 @@ nsp_proc_info(
/* error handler */
/*---------------------------------------------------------------*/
-/*static int nsp_eh_strategy(struct Scsi_Host *Shost)
-{
- return FAILED;
-}*/
-
/*
static int nsp_eh_abort(Scsi_Cmnd *SCpnt)
{
@@ -1549,14 +1542,6 @@ static int nsp_eh_abort(Scsi_Cmnd *SCpnt)
return nsp_eh_bus_reset(SCpnt);
}*/
-/*
-static int nsp_eh_device_reset(Scsi_Cmnd *SCpnt)
-{
- nsp_dbg(NSP_DEBUG_BUSRESET, "%s: SCpnt=0x%p", SCpnt);
-
- return FAILED;
-}*/
-
static int nsp_bus_reset(nsp_hw_data *data)
{
unsigned int base = data->BaseAddress;
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
index 4766bcd6369..a0175f5d11c 100644
--- a/drivers/scsi/pcmcia/qlogic_stub.c
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -81,8 +81,6 @@ static Scsi_Host_Template qlogicfas_driver_template = {
.queuecommand = qlogicfas408_queuecommand,
.eh_abort_handler = qlogicfas408_abort,
.eh_bus_reset_handler = qlogicfas408_bus_reset,
- .eh_device_reset_handler= qlogicfas408_device_reset,
- .eh_host_reset_handler = qlogicfas408_host_reset,
.bios_param = qlogicfas408_biosparam,
.can_queue = 1,
.this_id = -1,
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index 8457d0d7748..1667da9508b 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -627,7 +627,9 @@ SYM53C500_host_reset(struct scsi_cmnd *SCpnt)
int port_base = SCpnt->device->host->io_port;
DEB(printk("SYM53C500_host_reset called\n"));
+ spin_lock_irq(SCpnt->device->host->host_lock);
SYM53C500_int_host_reset(port_base);
+ spin_unlock_irq(SCpnt->device->host->host_lock);
return SUCCESS;
}
diff --git a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c
index c01b7191fcf..623082d3a83 100644
--- a/drivers/scsi/pluto.c
+++ b/drivers/scsi/pluto.c
@@ -354,7 +354,6 @@ static Scsi_Host_Template driver_template = {
.use_clustering = ENABLE_CLUSTERING,
.eh_abort_handler = fcp_scsi_abort,
.eh_device_reset_handler = fcp_scsi_dev_reset,
- .eh_bus_reset_handler = fcp_scsi_bus_reset,
.eh_host_reset_handler = fcp_scsi_host_reset,
};
diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c
index 96b4522523d..fafcf5d185e 100644
--- a/drivers/scsi/ppa.c
+++ b/drivers/scsi/ppa.c
@@ -17,6 +17,7 @@
#include <linux/blkdev.h>
#include <linux/parport.h>
#include <linux/workqueue.h>
+#include <linux/delay.h>
#include <asm/io.h>
#include <scsi/scsi.h>
@@ -891,9 +892,9 @@ static int ppa_reset(struct scsi_cmnd *cmd)
ppa_connect(dev, CONNECT_NORMAL);
ppa_reset_pulse(dev->base);
- udelay(1000); /* device settle delay */
+ mdelay(1); /* device settle delay */
ppa_disconnect(dev);
- udelay(1000); /* device settle delay */
+ mdelay(1); /* device settle delay */
return SUCCESS;
}
diff --git a/drivers/scsi/psi_dale.h b/drivers/scsi/psi_dale.h
deleted file mode 100644
index d672e3b0198..00000000000
--- a/drivers/scsi/psi_dale.h
+++ /dev/null
@@ -1,564 +0,0 @@
-/****************************************************************************
- * Perceptive Solutions, Inc. PCI-2220I device driver for Linux.
- *
- * psi_dalei.h - Linux Host Driver for PCI-2220i EIDE Adapters
- *
- * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
- * All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that redistributions of source
- * code retain the above copyright notice and this comment without
- * modification.
- *
- * Technical updates and product information at:
- * http://www.psidisk.com
- *
- * Please send questions, comments, bug reports to:
- * tech@psidisk.com Technical Support
- *
- ****************************************************************************/
-
-/************************************************/
-/* Some defines that we like */
-/************************************************/
-#define CHAR char
-#define UCHAR unsigned char
-#define SHORT short
-#define USHORT unsigned short
-#define BOOL unsigned short
-#define LONG long
-#define ULONG unsigned long
-#define VOID void
-
-/************************************************/
-/* Dale PCI setup */
-/************************************************/
-#define VENDOR_PSI 0x1256
-#define DEVICE_DALE_1 0x4401 /* 'D1' */
-#define DEVICE_BIGD_1 0x4201 /* 'B1' */
-#define DEVICE_BIGD_2 0x4202 /* 'B2' */
-
-/************************************************/
-/* Misc konstants */
-/************************************************/
-#define DALE_MAXDRIVES 4
-#define BIGD_MAXDRIVES 8
-#define SECTORSXFER 8
-#define ATAPI_TRANSFER 8192
-#define BYTES_PER_SECTOR 512
-#define DEFAULT_TIMING_MODE 5
-
-/************************************************/
-/* EEPROM locations */
-/************************************************/
-#define DALE_FLASH_PAGE_SIZE 128 // number of bytes per page
-#define DALE_FLASH_SIZE 65536L
-
-#define DALE_FLASH_BIOS 0x00080000L // BIOS base address
-#define DALE_FLASH_SETUP 0x00088000L // SETUP PROGRAM base address offset from BIOS
-#define DALE_FLASH_RAID 0x00088400L // RAID signature storage
-#define DALE_FLASH_FACTORY 0x00089000L // FACTORY data base address offset from BIOS
-
-#define DALE_FLASH_BIOS_SIZE 32768U // size of FLASH BIOS REGION
-
-/************************************************/
-/* DALE Register address offsets */
-/************************************************/
-#define REG_DATA 0x80
-#define REG_ERROR 0x84
-#define REG_SECTOR_COUNT 0x88
-#define REG_LBA_0 0x8C
-#define REG_LBA_8 0x90
-#define REG_LBA_16 0x94
-#define REG_LBA_24 0x98
-#define REG_STAT_CMD 0x9C
-#define REG_STAT_SEL 0xA0
-#define REG_FAIL 0xB0
-#define REG_ALT_STAT 0xB8
-#define REG_DRIVE_ADRS 0xBC
-
-#define DALE_DATA_SLOW 0x00040000L
-#define DALE_DATA_MODE2 0x00040000L
-#define DALE_DATA_MODE3 0x00050000L
-#define DALE_DATA_MODE4 0x00060000L
-#define DALE_DATA_MODE5 0x00070000L
-
-#define BIGD_DATA_SLOW 0x00000000L
-#define BIGD_DATA_MODE0 0x00000000L
-#define BIGD_DATA_MODE2 0x00000000L
-#define BIGD_DATA_MODE3 0x00000008L
-#define BIGD_DATA_MODE4 0x00000010L
-#define BIGD_DATA_MODE5 0x00000020L
-
-#define RTR_LOCAL_RANGE 0x000
-#define RTR_LOCAL_REMAP 0x004
-#define RTR_EXP_RANGE 0x010
-#define RTR_EXP_REMAP 0x014
-#define RTR_REGIONS 0x018
-#define RTR_DM_MASK 0x01C
-#define RTR_DM_LOCAL_BASE 0x020
-#define RTR_DM_IO_BASE 0x024
-#define RTR_DM_PCI_REMAP 0x028
-#define RTR_DM_IO_CONFIG 0x02C
-#define RTR_MAILBOX 0x040
-#define RTR_LOCAL_DOORBELL 0x060
-#define RTR_PCI_DOORBELL 0x064
-#define RTR_INT_CONTROL_STATUS 0x068
-#define RTR_EEPROM_CONTROL_STATUS 0x06C
-
-#define RTR_DMA0_MODE 0x0080
-#define RTR_DMA0_PCI_ADDR 0x0084
-#define RTR_DMA0_LOCAL_ADDR 0x0088
-#define RTR_DMA0_COUNT 0x008C
-#define RTR_DMA0_DESC_PTR 0x0090
-#define RTR_DMA1_MODE 0x0094
-#define RTR_DMA1_PCI_ADDR 0x0098
-#define RTR_DMA1_LOCAL_ADDR 0x009C
-#define RTR_DMA1_COUNT 0x00A0
-#define RTR_DMA1_DESC_PTR 0x00A4
-#define RTR_DMA_COMMAND_STATUS 0x00A8
-#define RTR_DMA_ARB0 0x00AC
-#define RTR_DMA_ARB1 0x00B0
-
-#define RTL_DMA0_MODE 0x00
-#define RTL_DMA0_PCI_ADDR 0x04
-#define RTL_DMA0_LOCAL_ADDR 0x08
-#define RTL_DMA0_COUNT 0x0C
-#define RTL_DMA0_DESC_PTR 0x10
-#define RTL_DMA1_MODE 0x14
-#define RTL_DMA1_PCI_ADDR 0x18
-#define RTL_DMA1_LOCAL_ADDR 0x1C
-#define RTL_DMA1_COUNT 0x20
-#define RTL_DMA1_DESC_PTR 0x24
-#define RTL_DMA_COMMAND_STATUS 0x28
-#define RTL_DMA_ARB0 0x2C
-#define RTL_DMA_ARB1 0x30
-
-/************************************************/
-/* Dale Scratchpad locations */
-/************************************************/
-#define DALE_CHANNEL_DEVICE_0 0 // device channel locations
-#define DALE_CHANNEL_DEVICE_1 1
-#define DALE_CHANNEL_DEVICE_2 2
-#define DALE_CHANNEL_DEVICE_3 3
-
-#define DALE_SCRATCH_DEVICE_0 4 // device type codes
-#define DALE_SCRATCH_DEVICE_1 5
-#define DALE_SCRATCH_DEVICE_2 6
-#define DALE_SCRATCH_DEVICE_3 7
-
-#define DALE_RAID_0_STATUS 8
-#define DALE_RAID_1_STATUS 9
-
-#define DALE_TIMING_MODE 12 // bus master timing mode (2, 3, 4, 5)
-#define DALE_NUM_DRIVES 13 // number of addressable drives on this board
-#define DALE_RAID_ON 14 // RAID status On
-#define DALE_LAST_ERROR 15 // Last error code from BIOS
-
-/************************************************/
-/* BigD Scratchpad locations */
-/************************************************/
-#define BIGD_DEVICE_0 0 // device channel locations
-#define BIGD_DEVICE_1 1
-#define BIGD_DEVICE_2 2
-#define BIGD_DEVICE_3 3
-
-#define BIGD_DEVICE_4 4 // device type codes
-#define BIGD_DEVICE_5 5
-#define BIGD_DEVICE_6 6
-#define BIGD_DEVICE_7 7
-
-#define BIGD_ALARM_IMAGE 11 // ~image of alarm fail register
-#define BIGD_TIMING_MODE 12 // bus master timing mode (2, 3, 4, 5)
-#define BIGD_NUM_DRIVES 13 // number of addressable drives on this board
-#define BIGD_RAID_ON 14 // RAID status is on for the whole board
-#define BIGD_LAST_ERROR 15 // Last error code from BIOS
-
-#define BIGD_RAID_0_STATUS 16
-#define BIGD_RAID_1_STATUS 17
-#define BIGD_RAID_2_STATUS 18
-#define BIGD_RAID_3_STATUS 19
-#define BIGD_RAID_4_STATUS 20
-#define BIGD_RAID_5_STATUS 21
-#define BIGD_RAID_6_STATUS 22
-#define BIGD_RAID_7_STATUS 23
-
-/************************************************/
-/* Dale cable select bits */
-/************************************************/
-#define SEL_NONE 0x00
-#define SEL_1 0x01
-#define SEL_2 0x02
-#define SEL_3 0x04
-#define SEL_4 0x08
-#define SEL_NEW_SPEED_1 0x20
-#define SEL_COPY 0x40
-#define SEL_IRQ_OFF 0x80
-
-/************************************************/
-/* Device/Geometry controls */
-/************************************************/
-#define GEOMETRY_NONE 0x0 // No device
-#define GEOMETRY_SET 0x1 // Geometry set
-#define GEOMETRY_LBA 0x2 // Geometry set in default LBA mode
-#define GEOMETRY_PHOENIX 0x3 // Geometry set in Pheonix BIOS compatibility mode
-
-#define DEVICE_NONE 0x0 // No device present
-#define DEVICE_INACTIVE 0x1 // device present but not registered active
-#define DEVICE_ATAPI 0x2 // ATAPI device (CD_ROM, Tape, Etc...)
-#define DEVICE_DASD_NONLBA 0x3 // Non LBA incompatible device
-#define DEVICE_DASD_LBA 0x4 // LBA compatible device
-
-/************************************************/
-/* BigD fail register bits */
-/************************************************/
-#define FAIL_NONE 0x00
-#define FAIL_0 0x01
-#define FAIL_1 0x02
-#define FAIL_2 0x04
-#define FAIL_MULTIPLE 0x08
-#define FAIL_GOOD 0x20
-#define FAIL_AUDIBLE 0x40
-#define FAIL_ANY 0x80
-
-/************************************************/
-/* Setup Structure Definitions */
-/************************************************/
-typedef struct // device setup parameters
- {
- UCHAR geometryControl; // geometry control flags
- UCHAR device; // device code
- USHORT sectors; // number of sectors per track
- USHORT heads; // number of heads
- USHORT cylinders; // number of cylinders for this device
- ULONG blocks; // number of blocks on device
- ULONG realCapacity; // number of real blocks on this device for drive changed testing
- } SETUP_DEVICE, *PSETUP_DEVICE;
-
-typedef struct // master setup structure
- {
- USHORT startupDelay;
- BOOL promptBIOS;
- BOOL fastFormat;
- BOOL shareInterrupt;
- BOOL rebootRebuild;
- USHORT timingMode;
- USHORT spare5;
- USHORT spare6;
- SETUP_DEVICE setupDevice[BIGD_MAXDRIVES];
- } SETUP, *PSETUP;
-
-/************************************************/
-/* RAID Structure Definitions */
-/************************************************/
-typedef struct
- {
- UCHAR signature; // 0x55 our mirror signature
- UCHAR status; // current status bits
- UCHAR pairIdentifier; // unique identifier for pair
- ULONG reconstructPoint; // recontruction point for hot reconstruct
- } DISK_MIRROR;
-
-typedef struct DEVICE_RAID1
- {
- long TotalSectors;
- DISK_MIRROR DiskRaid1;
- } DEVICE_RAID1, *PDEVICE_RAID1;
-
-#define DISK_MIRROR_POSITION 0x01A8
-#define SIGNATURE 0x55
-
-#define MASK_SERIAL_NUMBER 0x0FFE // mask for serial number matching
-#define MASK_SERIAL_UNIT 0x0001 // mask for unit portion of serial number
-
-// Status bits
-#define UCBF_MIRRORED 0x0010 // drive has a pair
-#define UCBF_MATCHED 0x0020 // drive pair is matched
-#define UCBF_SURVIVOR 0x0040 // this unit is a survivor of a pair
-#define UCBF_REBUILD 0x0080 // rebuild in progress on this device
-
-// SCSI controls for RAID
-#define SC_MY_RAID 0xBF // our special CDB command byte for Win95... interface
-#define MY_SCSI_QUERY1 0x32 // byte 1 subcommand to query driver for RAID 1 informatation
-#define MY_SCSI_REBUILD 0x40 // byte 1 subcommand to reconstruct a mirrored pair
-#define MY_SCSI_DEMOFAIL 0x54 // byte 1 subcommand for RAID failure demonstration
-#define MY_SCSI_ALARMMUTE 0x60 // byte 1 subcommand to mute any alarm currently on
-
-/************************************************/
-/* Timeout konstants */
-/************************************************/
-#define TIMEOUT_READY 100 // 100 mSec
-#define TIMEOUT_DRQ 300 // 300 mSec
-#define TIMEOUT_DATA (3 * HZ) // 3 seconds
-
-/************************************************/
-/* Misc. macros */
-/************************************************/
-#define ANY2SCSI(up, p) \
-((UCHAR *)up)[0] = (((ULONG)(p)) >> 8); \
-((UCHAR *)up)[1] = ((ULONG)(p));
-
-#define SCSI2LONG(up) \
-( (((long)*(((UCHAR *)up))) << 16) \
-+ (((long)(((UCHAR *)up)[1])) << 8) \
-+ ((long)(((UCHAR *)up)[2])) )
-
-#define XANY2SCSI(up, p) \
-((UCHAR *)up)[0] = ((long)(p)) >> 24; \
-((UCHAR *)up)[1] = ((long)(p)) >> 16; \
-((UCHAR *)up)[2] = ((long)(p)) >> 8; \
-((UCHAR *)up)[3] = ((long)(p));
-
-#define XSCSI2LONG(up) \
-( (((long)(((UCHAR *)up)[0])) << 24) \
-+ (((long)(((UCHAR *)up)[1])) << 16) \
-+ (((long)(((UCHAR *)up)[2])) << 8) \
-+ ((long)(((UCHAR *)up)[3])) )
-
-#define SelectSpigot(padapter,spigot) outb_p (spigot, padapter->regStatSel)
-#define WriteCommand(padapter,cmd) outb_p (cmd, padapter->regStatCmd)
-#define AtapiDevice(padapter,b) outb_p (b, padapter->regLba24);
-#define AtapiCountLo(padapter,b) outb_p (b, padapter->regLba8)
-#define AtapiCountHi(padapter,b) outb_p (b, padapter->regLba16)
-
-/************************************************/
-/* SCSI CDB operation codes */
-/************************************************/
-#define SCSIOP_TEST_UNIT_READY 0x00
-#define SCSIOP_REZERO_UNIT 0x01
-#define SCSIOP_REWIND 0x01
-#define SCSIOP_REQUEST_BLOCK_ADDR 0x02
-#define SCSIOP_REQUEST_SENSE 0x03
-#define SCSIOP_FORMAT_UNIT 0x04
-#define SCSIOP_READ_BLOCK_LIMITS 0x05
-#define SCSIOP_REASSIGN_BLOCKS 0x07
-#define SCSIOP_READ6 0x08
-#define SCSIOP_RECEIVE 0x08
-#define SCSIOP_WRITE6 0x0A
-#define SCSIOP_PRINT 0x0A
-#define SCSIOP_SEND 0x0A
-#define SCSIOP_SEEK6 0x0B
-#define SCSIOP_TRACK_SELECT 0x0B
-#define SCSIOP_SLEW_PRINT 0x0B
-#define SCSIOP_SEEK_BLOCK 0x0C
-#define SCSIOP_PARTITION 0x0D
-#define SCSIOP_READ_REVERSE 0x0F
-#define SCSIOP_WRITE_FILEMARKS 0x10
-#define SCSIOP_FLUSH_BUFFER 0x10
-#define SCSIOP_SPACE 0x11
-#define SCSIOP_INQUIRY 0x12
-#define SCSIOP_VERIFY6 0x13
-#define SCSIOP_RECOVER_BUF_DATA 0x14
-#define SCSIOP_MODE_SELECT 0x15
-#define SCSIOP_RESERVE_UNIT 0x16
-#define SCSIOP_RELEASE_UNIT 0x17
-#define SCSIOP_COPY 0x18
-#define SCSIOP_ERASE 0x19
-#define SCSIOP_MODE_SENSE 0x1A
-#define SCSIOP_START_STOP_UNIT 0x1B
-#define SCSIOP_STOP_PRINT 0x1B
-#define SCSIOP_LOAD_UNLOAD 0x1B
-#define SCSIOP_RECEIVE_DIAGNOSTIC 0x1C
-#define SCSIOP_SEND_DIAGNOSTIC 0x1D
-#define SCSIOP_MEDIUM_REMOVAL 0x1E
-#define SCSIOP_READ_CAPACITY 0x25
-#define SCSIOP_READ 0x28
-#define SCSIOP_WRITE 0x2A
-#define SCSIOP_SEEK 0x2B
-#define SCSIOP_LOCATE 0x2B
-#define SCSIOP_WRITE_VERIFY 0x2E
-#define SCSIOP_VERIFY 0x2F
-#define SCSIOP_SEARCH_DATA_HIGH 0x30
-#define SCSIOP_SEARCH_DATA_EQUAL 0x31
-#define SCSIOP_SEARCH_DATA_LOW 0x32
-#define SCSIOP_SET_LIMITS 0x33
-#define SCSIOP_READ_POSITION 0x34
-#define SCSIOP_SYNCHRONIZE_CACHE 0x35
-#define SCSIOP_COMPARE 0x39
-#define SCSIOP_COPY_COMPARE 0x3A
-#define SCSIOP_WRITE_DATA_BUFF 0x3B
-#define SCSIOP_READ_DATA_BUFF 0x3C
-#define SCSIOP_CHANGE_DEFINITION 0x40
-#define SCSIOP_READ_SUB_CHANNEL 0x42
-#define SCSIOP_READ_TOC 0x43
-#define SCSIOP_READ_HEADER 0x44
-#define SCSIOP_PLAY_AUDIO 0x45
-#define SCSIOP_PLAY_AUDIO_MSF 0x47
-#define SCSIOP_PLAY_TRACK_INDEX 0x48
-#define SCSIOP_PLAY_TRACK_RELATIVE 0x49
-#define SCSIOP_PAUSE_RESUME 0x4B
-#define SCSIOP_LOG_SELECT 0x4C
-#define SCSIOP_LOG_SENSE 0x4D
-#define SCSIOP_MODE_SELECT10 0x55
-#define SCSIOP_MODE_SENSE10 0x5A
-#define SCSIOP_LOAD_UNLOAD_SLOT 0xA6
-#define SCSIOP_MECHANISM_STATUS 0xBD
-#define SCSIOP_READ_CD 0xBE
-
-// IDE command definitions
-#define IDE_COMMAND_ATAPI_RESET 0x08
-#define IDE_COMMAND_READ 0x20
-#define IDE_COMMAND_WRITE 0x30
-#define IDE_COMMAND_RECALIBRATE 0x10
-#define IDE_COMMAND_SEEK 0x70
-#define IDE_COMMAND_SET_PARAMETERS 0x91
-#define IDE_COMMAND_VERIFY 0x40
-#define IDE_COMMAND_ATAPI_PACKET 0xA0
-#define IDE_COMMAND_ATAPI_IDENTIFY 0xA1
-#define IDE_CMD_READ_MULTIPLE 0xC4
-#define IDE_CMD_WRITE_MULTIPLE 0xC5
-#define IDE_CMD_SET_MULTIPLE 0xC6
-#define IDE_COMMAND_IDENTIFY 0xEC
-
-// IDE status definitions
-#define IDE_STATUS_ERROR 0x01
-#define IDE_STATUS_INDEX 0x02
-#define IDE_STATUS_CORRECTED_ERROR 0x04
-#define IDE_STATUS_DRQ 0x08
-#define IDE_STATUS_DSC 0x10
-#define IDE_STATUS_WRITE_FAULT 0x20
-#define IDE_STATUS_DRDY 0x40
-#define IDE_STATUS_BUSY 0x80
-
-typedef struct _ATAPI_STATUS
- {
- CHAR check :1;
- CHAR reserved1 :1;
- CHAR corr :1;
- CHAR drq :1;
- CHAR dsc :1;
- CHAR reserved2 :1;
- CHAR drdy :1;
- CHAR bsy :1;
- } ATAPI_STATUS;
-
-typedef struct _ATAPI_REASON
- {
- CHAR cod :1;
- CHAR io :1;
- CHAR reserved1 :6;
- } ATAPI_REASON;
-
-typedef struct _ATAPI_ERROR
- {
- CHAR ili :1;
- CHAR eom :1;
- CHAR abort :1;
- CHAR mcr :1;
- CHAR senseKey :4;
- } ATAPI_ERROR;
-
-// IDE error definitions
-#define IDE_ERROR_AMNF 0x01
-#define IDE_ERROR_TKONF 0x02
-#define IDE_ERROR_ABRT 0x04
-#define IDE_ERROR_MCR 0x08
-#define IDE_ERROR_IDFN 0x10
-#define IDE_ERROR_MC 0x20
-#define IDE_ERROR_UNC 0x40
-#define IDE_ERROR_BBK 0x80
-
-// SCSI read capacity structure
-typedef struct _READ_CAPACITY_DATA
- {
- ULONG blks; /* total blocks (converted to little endian) */
- ULONG blksiz; /* size of each (converted to little endian) */
- } READ_CAPACITY_DATA, *PREAD_CAPACITY_DATA;
-
-// SCSI inquiry data
-typedef struct _INQUIRYDATA
- {
- UCHAR DeviceType :5;
- UCHAR DeviceTypeQualifier :3;
- UCHAR DeviceTypeModifier :7;
- UCHAR RemovableMedia :1;
- UCHAR Versions;
- UCHAR ResponseDataFormat;
- UCHAR AdditionalLength;
- UCHAR Reserved[2];
- UCHAR SoftReset :1;
- UCHAR CommandQueue :1;
- UCHAR Reserved2 :1;
- UCHAR LinkedCommands :1;
- UCHAR Synchronous :1;
- UCHAR Wide16Bit :1;
- UCHAR Wide32Bit :1;
- UCHAR RelativeAddressing :1;
- UCHAR VendorId[8];
- UCHAR ProductId[16];
- UCHAR ProductRevisionLevel[4];
- UCHAR VendorSpecific[20];
- UCHAR Reserved3[40];
- } INQUIRYDATA, *PINQUIRYDATA;
-
-// IDE IDENTIFY data
-#pragma pack (1)
-typedef struct _IDENTIFY_DATA
- {
- USHORT GeneralConfiguration; // 0
- USHORT NumberOfCylinders; // 1
- USHORT Reserved1; // 2
- USHORT NumberOfHeads; // 3
- USHORT UnformattedBytesPerTrack; // 4
- USHORT UnformattedBytesPerSector; // 5
- USHORT SectorsPerTrack; // 6
- USHORT NumBytesISG; // 7 Byte Len - inter-sector gap
- USHORT NumBytesSync; // 8 - sync field
- USHORT NumWordsVUS; // 9 Len - Vendor Unique Info
- USHORT SerialNumber[10]; // 10
- USHORT BufferType; // 20
- USHORT BufferSectorSize; // 21
- USHORT NumberOfEccBytes; // 22
- USHORT FirmwareRevision[4]; // 23
- USHORT ModelNumber[20]; // 27
- USHORT NumSectorsPerInt :8; // 47 Multiple Mode - Sec/Blk
- USHORT Reserved2 :8; // 47
- USHORT DoubleWordMode; // 48 flag for double word mode capable
- USHORT VendorUnique1 :8; // 49
- USHORT SupportDMA :1; // 49 DMA supported
- USHORT SupportLBA :1; // 49 LBA supported
- USHORT SupportIORDYDisable :1; // 49 IORDY can be disabled
- USHORT SupportIORDY :1; // 49 IORDY supported
- USHORT ReservedPsuedoDMA :1; // 49 reserved for pseudo DMA mode support
- USHORT Reserved3 :3; // 49
- USHORT Reserved4; // 50
- USHORT Reserved5 :8; // 51 Transfer Cycle Timing - PIO
- USHORT PIOCycleTime :8; // 51 Transfer Cycle Timing - PIO
- USHORT Reserved6 :8; // 52 - DMA
- USHORT DMACycleTime :8; // 52 - DMA
- USHORT Valid_54_58 :1; // 53 words 54 - 58 are valid
- USHORT Valid_64_70 :1; // 53 words 64 - 70 are valid
- USHORT Reserved7 :14; // 53
- USHORT LogNumCyl; // 54 Current Translation - Num Cyl
- USHORT LogNumHeads; // 55 Num Heads
- USHORT LogSectorsPerTrack; // 56 Sec/Trk
- ULONG LogTotalSectors; // 57 Total Sec
- USHORT CurrentNumSecPerInt :8; // 59 current setting for number of sectors per interrupt
- USHORT ValidNumSecPerInt :1; // 59 Current setting is valid for number of sectors per interrupt
- USHORT Reserved8 :7; // 59
- ULONG LBATotalSectors; // 60 LBA Mode - Sectors
- USHORT DMASWordFlags; // 62
- USHORT DMAMWordFlags; // 63
- USHORT AdvancedPIOSupport :8; // 64 Flow control PIO transfer modes supported
- USHORT Reserved9 :8; // 64
- USHORT MinMultiDMACycle; // 65 minimum multiword DMA transfer cycle time per word
- USHORT RecomendDMACycle; // 66 Manufacturer's recommende multiword DMA transfer cycle time
- USHORT MinPIOCycleWithoutFlow; // 67 Minimum PIO transfer cycle time without flow control
- USHORT MinPIOCylceWithFlow; // 68 Minimum PIO transfer cycle time with IORDY flow control
- USHORT ReservedSpace[256-69]; // 69
- } IDENTIFY_DATA, *PIDENTIFY_DATA;
-
-// ATAPI configuration bits
-typedef struct _ATAPI_GENERAL_0
- {
- USHORT CmdPacketSize :2; // Command packet size
- USHORT Reserved1 :3;
- USHORT CmdDrqType :2;
- USHORT Removable :1;
- USHORT DeviceType :5;
- USHORT Reserved2 :1;
- USHORT ProtocolType :2;
- } ATAPI_GENERAL_0;
-
-#pragma pack ()
diff --git a/drivers/scsi/psi_roy.h b/drivers/scsi/psi_roy.h
deleted file mode 100644
index c55b9c04c32..00000000000
--- a/drivers/scsi/psi_roy.h
+++ /dev/null
@@ -1,331 +0,0 @@
-/****************************************************************************
- * Perceptive Solutions, Inc. PCI-2000 device driver for Linux.
- *
- * psi_roy.h - Linux Host Driver for PCI-2000 IntelliCache SCSI Adapters
- *
- * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
- * All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that redistributions of source
- * code retain the above copyright notice and this comment without
- * modification.
- *
- * Technical updates and product information at:
- * http://www.psidisk.com
- *
- * Please send questions, comments, bug reports to:
- * tech@psidisk.com Technical Support
- *
- ****************************************************************************/
-
-#ifndef ROY_HOST
-#define ROY_HOST
-
-/************************************************/
-/* PCI setup */
-/************************************************/
-#define VENDOR_PSI 0x1256
-#define DEVICE_ROY_1 0x5201 /* 'R1' */
-
-/************************************************/
-/* controller constants */
-/************************************************/
-#define MAXADAPTER 4 // Increase this and the sizes of the arrays below, if you need more.
-#define MAX_BUS 2
-#define MAX_UNITS 16
-#define TIMEOUT_COMMAND 400 // number of milliSecondos for command busy timeout
-
-/************************************************/
-/* I/O address offsets */
-/************************************************/
-#define RTR_MAILBOX 0x040
-#define RTR_LOCAL_DOORBELL 0x060
-#define RTR_PCI_DOORBELL 0x064
-
-/************************************************/
-/* */
-/* Host command codes */
-/* */
-/************************************************/
-#define CMD_READ_CHS 0x01 /* read sectors as specified (CHS mode) */
-#define CMD_READ 0x02 /* read sectors as specified (RBA mode) */
-#define CMD_READ_SG 0x03 /* read sectors using scatter/gather list */
-#define CMD_WRITE_CHS 0x04 /* write sectors as specified (CHS mode) */
-#define CMD_WRITE 0x05 /* write sectors as specified (RBA mode) */
-#define CMD_WRITE_SG 0x06 /* write sectors using scatter/gather list (LBA mode) */
-#define CMD_READ_CHS_SG 0x07 /* read sectors using scatter/gather list (CHS mode) */
-#define CMD_WRITE_CHS_SG 0x08 /* write sectors using scatter/gather list (CHS mode) */
-#define CMD_VERIFY_CHS 0x09 /* verify data on sectors as specified (CHS mode) */
-#define CMD_VERIFY 0x0A /* verify data on sectors as specified (RBA mode) */
-#define CMD_DASD_CDB 0x0B /* process CDB for a DASD device */
-#define CMD_DASD_CDB_SG 0x0C /* process CDB for a DASD device with scatter/gather */
-
-#define CMD_READ_ABS 0x10 /* read absolute disk */
-#define CMD_WRITE_ABS 0x11 /* write absolute disk */
-#define CMD_VERIFY_ABS 0x12 /* verify absolute disk */
-#define CMD_TEST_READY 0x13 /* test unit ready and return status code */
-#define CMD_LOCK_DOOR 0x14 /* lock device door */
-#define CMD_UNLOCK_DOOR 0x15 /* unlock device door */
-#define CMD_EJECT_MEDIA 0x16 /* eject the media */
-#define CMD_UPDATE_CAP 0x17 /* update capacity information */
-#define CMD_TEST_PRIV 0x18 /* test and setup private format media */
-
-
-#define CMD_SCSI_THRU 0x30 /* SCSI pass through CDB */
-#define CMD_SCSI_THRU_SG 0x31 /* SCSI pass through CDB with scatter/gather */
-#define CMD_SCSI_REQ_SENSE 0x32 /* SCSI pass through request sense after check condition */
-
-#define CMD_DASD_RAID_RQ 0x35 /* request DASD RAID drive data */
-#define CMD_DASD_RAID_RQ0 0x31 /* byte 1 subcommand to query for RAID 0 informatation */
-#define CMD_DASD_RAID_RQ1 0x32 /* byte 1 subcommand to query for RAID 1 informatation */
-#define CMD_DASD_RAID_RQ5 0x33 /* byte 1 subcommand to query for RAID 5 informatation */
-
-#define CMD_DASD_SCSI_INQ 0x36 /* do DASD inquire and return in SCSI format */
-#define CMD_DASD_CAP 0x37 /* read DASD capacity */
-#define CMD_DASD_INQ 0x38 /* do DASD inquire for type data and return SCSI/EIDE inquiry */
-#define CMD_SCSI_INQ 0x39 /* do SCSI inquire */
-#define CMD_READ_SETUP 0x3A /* Get setup structures from controller */
-#define CMD_WRITE_SETUP 0x3B /* Put setup structures in controller and burn in flash */
-#define CMD_READ_CONFIG 0x3C /* Get the entire configuration and setup structures */
-#define CMD_WRITE_CONFIG 0x3D /* Put the entire configuration and setup structures in flash */
-
-#define CMD_TEXT_DEVICE 0x3E /* obtain device text */
-#define CMD_TEXT_SIGNON 0x3F /* get sign on banner */
-
-#define CMD_QUEUE 0x40 /* any command below this generates a queue tag interrupt to host*/
-
-#define CMD_PREFETCH 0x40 /* prefetch sectors as specified */
-#define CMD_TEST_WRITE 0x41 /* Test a device for write protect */
-#define CMD_LAST_STATUS 0x42 /* get last command status and error data*/
-#define CMD_ABORT 0x43 /* abort command as specified */
-#define CMD_ERROR 0x44 /* fetch error code from a tagged op */
-#define CMD_DONE 0x45 /* done with operation */
-#define CMD_DIAGNOSTICS 0x46 /* execute controller diagnostics and wait for results */
-#define CMD_FEATURE_MODE 0x47 /* feature mode control word */
-#define CMD_DASD_INQUIRE 0x48 /* inquire as to DASD SCSI device (32 possible) */
-#define CMD_FEATURE_QUERY 0x49 /* query the feature control word */
-#define CMD_DASD_EJECT 0x4A /* Eject removable media for DASD type */
-#define CMD_DASD_LOCK 0x4B /* Lock removable media for DASD type */
-#define CMD_DASD_TYPE 0x4C /* obtain DASD device type */
-#define CMD_NUM_DEV 0x4D /* obtain the number of devices connected to the controller */
-#define CMD_GET_PARMS 0x4E /* obtain device parameters */
-#define CMD_SPECIFY 0x4F /* specify operating system for scatter/gather operations */
-
-#define CMD_RAID_GET_DEV 0x50 /* read RAID device geometry */
-#define CMD_RAID_READ 0x51 /* read RAID 1 parameter block */
-#define CMD_RAID_WRITE 0x52 /* write RAID 1 parameter block */
-#define CMD_RAID_LITEUP 0x53 /* Light up the drive light for identification */
-#define CMD_RAID_REBUILD 0x54 /* issue a RAID 1 pair rebuild */
-#define CMD_RAID_MUTE 0x55 /* mute RAID failure alarm */
-#define CMD_RAID_FAIL 0x56 /* induce a RAID failure */
-#define CMD_RAID_STATUS 0x57 /* get status of RAID pair */
-#define CMD_RAID_STOP 0x58 /* stop any reconstruct in progress */
-#define CMD_RAID_START 0x59 /* start reconstruct */
-#define CMD_RAID0_READ 0x5A /* read RAID 0 parameter block */
-#define CMD_RAID0_WRITE 0x5B /* write RAID 0 parameter block */
-#define CMD_RAID5_READ 0x5C /* read RAID 5 parameter block */
-#define CMD_RAID5_WRITE 0x5D /* write RAID 5 parameter block */
-
-#define CMD_ERASE_TABLES 0x5F /* erase partition table and RAID signatutures */
-
-#define CMD_SCSI_GET 0x60 /* get SCSI pass through devices */
-#define CMD_SCSI_TIMEOUT 0x61 /* set SCSI pass through timeout */
-#define CMD_SCSI_ERROR 0x62 /* get SCSI pass through request sense length and residual data count */
-#define CMD_GET_SPARMS 0x63 /* get SCSI bus and user parms */
-#define CMD_SCSI_ABORT 0x64 /* abort by setting time-out to zero */
-
-#define CMD_CHIRP_CHIRP 0x77 /* make a chirp chirp sound */
-#define CMD_GET_LAST_DONE 0x78 /* get tag of last done in progress */
-#define CMD_GET_FEATURES 0x79 /* get feature code and ESN */
-#define CMD_CLEAR_CACHE 0x7A /* Clear cache on specified device */
-#define CMD_BIOS_TEST 0x7B /* Test whether or not to load BIOS */
-#define CMD_WAIT_FLUSH 0x7C /* wait for cache flushed and invalidate read cache */
-#define CMD_RESET_BUS 0x7D /* reset the SCSI bus */
-#define CMD_STARTUP_QRY 0x7E /* startup in progress query */
-#define CMD_RESET 0x7F /* reset the controller */
-
-#define CMD_RESTART_RESET 0x80 /* reload and restart the controller at any reset issued */
-#define CMD_SOFT_RESET 0x81 /* do a soft reset NOW! */
-
-/************************************************/
-/* */
-/* Host return errors */
-/* */
-/************************************************/
-#define ERR08_TAGGED 0x80 /* doorbell error ored with tag */
-
-#define ERR16_NONE 0x0000 /* no errors */
-#define ERR16_SC_COND_MET 0x0004 /* SCSI status - Condition Met */
-#define ERR16_CMD 0x0101 /* command error */
-#define ERR16_SC_CHECK_COND 0x0002 /* SCSI status - Check Condition */
-#define ERR16_CMD_NOT 0x0201 /* command not supported */
-#define ERR16_NO_DEVICE 0x0301 /* invalid device selection */
-#define ERR16_SECTOR 0x0202 /* bad sector */
-#define ERR16_PROTECT 0x0303 /* write protected */
-#define ERR16_NOSECTOR 0x0404 /* sector not found */
-#define ERR16_MEDIA 0x0C0C /* invalid media */
-#define ERR16_CONTROL 0x2020 /* controller error */
-#define ERR16_CONTROL_DMA 0x2120 /* controller DMA engine error */
-#define ERR16_NO_ALARM 0x2220 /* alarm is not active */
-#define ERR16_OP_BUSY 0x2320 /* operation busy */
-#define ERR16_SEEK 0x4040 /* seek failure */
-#define ERR16_DEVICE_FAIL 0x4140 /* device has failed */
-#define ERR16_TIMEOUT 0x8080 /* timeout error */
-#define ERR16_DEV_NOT_READY 0xAAAA /* drive not ready */
-#define ERR16_UNDEFINED 0xBBBB /* undefined error */
-#define ERR16_WRITE_FAULT 0xCCCC /* write fault */
-#define ERR16_INVALID_DEV 0x4001 /* invalid device access */
-#define ERR16_DEVICE_BUSY 0x4002 /* device is busy */
-#define ERR16_MEMORY 0x4003 /* device pass thru requires too much memory */
-#define ERR16_NO_FEATURE 0x40FA /* feature no implemented */
-#define ERR16_NOTAG 0x40FD /* no tag space available */
-#define ERR16_NOT_READY 0x40FE /* controller not ready error */
-#define ERR16_SETUP_FLASH 0x5050 /* error when writing setup to flash memory */
-#define ERR16_SETUP_SIZE 0x5051 /* setup block size error */
-#define ERR16_SENSE 0xFFFF /* sense opereration failed */
-#define ERR16_SC_BUSY 0x0008 /* SCSI status - Busy */
-#define ERR16_SC_RES_CONFL 0x0018 /* SCSI status - Reservation Conflict */
-#define ERR16_SC_CMD_TERM 0x0022 /* SCSI status - Command Terminated */
-#define ERR16_SC_OTHER 0x00FF /* SCSI status - not recognized (any value masked) */
-#define ERR16_MEDIA_CHANGED 0x8001 /* devices media has been changed */
-
-#define ERR32_NONE 0x00000000 /* no errors */
-#define ERR32_SC_COND_MET 0x00000004 /* SCSI status - Condition Met */
-#define ERR32_CMD 0x00010101 /* command error */
-#define ERR32_SC_CHECK_COND 0x00020002 /* SCSI status - Check Condition */
-#define ERR32_CMD_NOT 0x00030201 /* command not supported */
-#define ERR32_NO_DEVICE 0x00040301 /* invalid device selection */
-#define ERR32_SECTOR 0x00050202 /* bad sector */
-#define ERR32_PROTECT 0x00060303 /* write protected */
-#define ERR32_NOSECTOR 0x00070404 /* sector not found */
-#define ERR32_MEDIA 0x00080C0C /* invalid media */
-#define ERR32_CONTROL 0x00092020 /* controller error */
-#define ERR32_CONTROL_DMA 0x000A2120 /* Controller DMA error */
-#define ERR32_NO_ALARM 0x000B2220 /* alarm is not active */
-#define ERR32_OP_BUSY 0x000C2320 /* operation busy */
-#define ERR32_SEEK 0x000D4040 /* seek failure */
-#define ERR32_DEVICE_FAIL 0x000E4140 /* device has failed */
-#define ERR32_TIMEOUT 0x000F8080 /* timeout error */
-#define ERR32_DEV_NOT_READY 0x0010AAAA /* drive not ready */
-#define ERR32_UNDEFINED 0x0011BBBB /* undefined error */
-#define ERR32_WRITE_FAULT 0x0012CCCC /* write fault */
-#define ERR32_INVALID_DEV 0x00134001 /* invalid device access */
-#define ERR32_DEVICE_BUSY 0x00144002 /* device is busy */
-#define ERR32_MEMORY 0x00154003 /* device pass thru requires too much memory */
-#define ERR32_NO_FEATURE 0x001640FA /* feature no implemented */
-#define ERR32_NOTAG 0x001740FD /* no tag space available */
-#define ERR32_NOT_READY 0x001840FE /* controller not ready error */
-#define ERR32_SETUP_FLASH 0x00195050 /* error when writing setup to flash memory */
-#define ERR32_SETUP_SIZE 0x001A5051 /* setup block size error */
-#define ERR32_SENSE 0x001BFFFF /* sense opereration failed */
-#define ERR32_SC_BUSY 0x001C0008 /* SCSI status - Busy */
-#define ERR32_SC_RES_CONFL 0x001D0018 /* SCSI status - Reservation Conflict */
-#define ERR32_SC_CMD_TERM 0x001E0022 /* SCSI status - Command Terminated */
-#define ERR32_SC_OTHER 0x001F00FF /* SCSI status - not recognized (any value masked) */
-#define ERR32_MEDIA_CHANGED 0x00208001 /* devices media has been changed */
-
-/************************************************/
-/* */
-/* Host Operating System specification codes */
-/* */
-/************************************************/
-#define SPEC_INTERRUPT 0x80 /* specification requires host interrupt */
-#define SPEC_BACKWARD_SG 0x40 /* specification requires scatter/gather items reversed */
-#define SPEC_DOS_BLOCK 0x01 /* DOS DASD blocking on pass through */
-#define SPEC_OS2_V3 0x02 /* OS/2 Warp */
-#define SPCE_SCO_3242 0x04 /* SCO 3.4.2.2 */
-#define SPEC_QNX_4X 0x05 /* QNX 4.XX */
-#define SPEC_NOVELL_NWPA 0x08 /* Novell NWPA scatter/gather support */
-
-/************************************************/
-/* */
-/* Inquire structures */
-/* */
-/************************************************/
-typedef struct _CNT_SCSI_INQ
- {
- UCHAR devt; /* 00: device type */
- UCHAR devtm; /* 01: device type modifier */
- UCHAR svers; /* 02: SCSI version */
- UCHAR rfmt; /* 03: response data format */
- UCHAR adlen; /* 04: additional length of data */
- UCHAR res1; /* 05: */
- UCHAR res2; /* 06: */
- UCHAR fncs; /* 07: functional capabilities */
- UCHAR vid[8]; /* 08: vendor ID */
- UCHAR pid[16]; /* 10: product ID */
- UCHAR rev[4]; /* 20: product revision */
- } CNT_SCSI_INQ;
-
-typedef struct _CNT_IDE_INQ
- {
- USHORT GeneralConfiguration; /* 00 */
- USHORT NumberOfCylinders; /* 02 */
- USHORT Reserved1; /* 04 */
- USHORT NumberOfHeads; /* 06 */
- USHORT UnformattedBytesPerTrack; /* 08 */
- USHORT UnformattedBytesPerSector; /* 0A */
- USHORT SectorsPerTrack; /* 0C */
- USHORT VendorUnique1[3]; /* 0E */
- USHORT SerialNumber[10]; /* 14 */
- USHORT BufferType; /* 28 */
- USHORT BufferSectorSize; /* 2A */
- USHORT NumberOfEccBytes; /* 2C */
- USHORT FirmwareRevision[4]; /* 2E */
- USHORT ModelNumber[20]; /* 36 */
- UCHAR MaximumBlockTransfer; /* 5E */
- UCHAR VendorUnique2; /* 5F */
- USHORT DoubleWordIo; /* 60 */
- USHORT Capabilities; /* 62 */
- USHORT Reserved2; /* 64 */
- UCHAR VendorUnique3; /* 66 */
- UCHAR PioCycleTimingMode; /* 67 */
- UCHAR VendorUnique4; /* 68 */
- UCHAR DmaCycleTimingMode; /* 69 */
- USHORT TranslationFieldsValid; /* 6A */
- USHORT NumberOfCurrentCylinders; /* 6C */
- USHORT NumberOfCurrentHeads; /* 6E */
- USHORT CurrentSectorsPerTrack; /* 70 */
- ULONG CurrentSectorCapacity; /* 72 */
- } CNT_IDE_INQ;
-
-typedef struct _DASD_INQUIRE
- {
- ULONG type; /* 0 = SCSI, 1 = IDE */
- union
- {
- CNT_SCSI_INQ scsi; /* SCSI inquire data */
- CNT_IDE_INQ ide; /* IDE inquire data */
- } inq;
- } DASD_INQUIRE;
-
-/************************************************/
-/* */
-/* Device Codes */
-/* */
-/************************************************/
-#define DEVC_DASD 0x00 /* Direct-access Storage Device */
-#define DEVC_SEQACESS 0x01 /* Sequential-access device */
-#define DEVC_PRINTER 0x02 /* Printer device */
-#define DEVC_PROCESSOR 0x03 /* Processor device */
-#define DEVC_WRITEONCE 0x04 /* Write-once device */
-#define DEVC_CDROM 0x05 /* CD-ROM device */
-#define DEVC_SCANNER 0x06 /* Scanner device */
-#define DEVC_OPTICAL 0x07 /* Optical memory device */
-#define DEVC_MEDCHGR 0x08 /* Medium changer device */
-#define DEVC_DASD_REMOVABLE 0x80 /* Direct-access storage device, Removable */
-#define DEVC_NONE 0xFF /* no device */
-
-// SCSI controls for RAID
-#define SC_MY_RAID 0xBF // our special CDB command byte for Win95... interface
-#define MY_SCSI_QUERY0 0x31 // byte 1 subcommand to query driver for RAID 0 informatation
-#define MY_SCSI_QUERY1 0x32 // byte 1 subcommand to query driver for RAID 1 informatation
-#define MY_SCSI_QUERY5 0x33 // byte 1 subcommand to query driver for RAID 5 informatation
-#define MY_SCSI_REBUILD 0x40 // byte 1 subcommand to reconstruct a mirrored pair
-#define MY_SCSI_DEMOFAIL 0x54 // byte 1 subcommand for RAID failure demonstration
-#define MY_SCSI_ALARMMUTE 0x60 // byte 1 subcommand to mute any alarm currently on
-
-
-#endif
-
diff --git a/drivers/scsi/ql1040_fw.h b/drivers/scsi/ql1040_fw.h
index 89d8e09ec38..aaf9284a8b7 100644
--- a/drivers/scsi/ql1040_fw.h
+++ b/drivers/scsi/ql1040_fw.h
@@ -25,17 +25,17 @@
*/
/*
- * Firmware Version 7.65.00 (14:17 Jul 20, 1999)
+ * Firmware Version 7.65.06 (14:38 Jan 07, 2002)
*/
-static unsigned char firmware_version[] = {7,65,0};
+static unsigned char firmware_version[] = {7,65,6};
-#define FW_VERSION_STRING "7.65.0"
+#define FW_VERSION_STRING "7.65.06"
static unsigned short risc_code_addr01 = 0x1000 ;
static unsigned short risc_code01[] = {
- 0x0078, 0x103a, 0x0000, 0x4057, 0x0000, 0x2043, 0x4f50, 0x5952,
+ 0x0078, 0x103a, 0x0000, 0x4158, 0x0000, 0x2043, 0x4f50, 0x5952,
0x4947, 0x4854, 0x2031, 0x3939, 0x3520, 0x514c, 0x4f47, 0x4943,
0x2043, 0x4f52, 0x504f, 0x5241, 0x5449, 0x4f4e, 0x2049, 0x5350,
0x3130, 0x3230, 0x2049, 0x2f54, 0x2046, 0x6972, 0x6d77, 0x6172,
@@ -45,7 +45,7 @@ static unsigned short risc_code01[] = {
0x3031, 0x2024, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x0048,
0x1045, 0x0038, 0x104b, 0x0078, 0x1047, 0x0028, 0x104b, 0x20b9,
0x1212, 0x0078, 0x104d, 0x20b9, 0x2222, 0x20c1, 0x0008, 0x2071,
- 0x0010, 0x70c3, 0x0004, 0x20c9, 0x77ff, 0x2089, 0x1186, 0x70c7,
+ 0x0010, 0x70c3, 0x0004, 0x20c9, 0x78ff, 0x2089, 0x1186, 0x70c7,
0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3, 0x0007, 0x3f00,
0x70d6, 0x20c1, 0x0008, 0x2019, 0x0000, 0x2009, 0xfeff, 0x2100,
0x200b, 0xa5a5, 0xa1ec, 0x7fff, 0x2d64, 0x206b, 0x0a0a, 0xaddc,
@@ -59,62 +59,62 @@ static unsigned short risc_code01[] = {
0x118e, 0x284a, 0x263a, 0x98c0, 0xa188, 0x1000, 0x212c, 0x200b,
0xa5a5, 0x2114, 0xa286, 0xa5a5, 0x0040, 0x10bc, 0x250a, 0xa18a,
0x1000, 0x98c1, 0x0078, 0x10c1, 0x250a, 0x0078, 0x10c1, 0x2c6a,
- 0x2a5a, 0x2130, 0xa18a, 0x0040, 0x2128, 0xa1a2, 0x5100, 0x8424,
- 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0xa192, 0x7800, 0x2009,
- 0x0000, 0x2001, 0x0031, 0x1078, 0x1cba, 0x2218, 0x2079, 0x5100,
+ 0x2a5a, 0x2130, 0xa18a, 0x0040, 0x2128, 0xa1a2, 0x5200, 0x8424,
+ 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0xa192, 0x7900, 0x2009,
+ 0x0000, 0x2001, 0x0031, 0x1078, 0x1d26, 0x2218, 0x2079, 0x5200,
0x2fa0, 0x2408, 0x2011, 0x0000, 0x20a9, 0x0040, 0x42a4, 0x8109,
0x00c0, 0x10dc, 0x7ef2, 0x8528, 0x7de6, 0x7cea, 0x7bee, 0x7883,
0x0000, 0x2031, 0x0030, 0x78cf, 0x0101, 0x780b, 0x0002, 0x780f,
- 0x0002, 0x784f, 0x0003, 0x2069, 0x5140, 0x2001, 0x04fd, 0x2004,
+ 0x0002, 0x784f, 0x0003, 0x2069, 0x5240, 0x2001, 0x04fd, 0x2004,
0xa082, 0x0005, 0x0048, 0x1104, 0x0038, 0x1100, 0x0078, 0x1108,
0x681b, 0x003c, 0x0078, 0x110a, 0x00a8, 0x1108, 0x681b, 0x003c,
0x681b, 0x0028, 0x6807, 0x0007, 0x680b, 0x00fa, 0x680f, 0x0008,
0x6813, 0x0005, 0x6823, 0x0000, 0x6827, 0x0006, 0x6817, 0x0008,
- 0x682b, 0x0000, 0x681f, 0x0019, 0x2069, 0x5380, 0x2011, 0x0020,
+ 0x682b, 0x0000, 0x681f, 0x0019, 0x2069, 0x5480, 0x2011, 0x0020,
0x2009, 0x0010, 0x680b, 0x080c, 0x680f, 0x0019, 0x6803, 0xfd00,
0x6807, 0x0018, 0x6a1a, 0x2d00, 0xa0e8, 0x0008, 0xa290, 0x0004,
- 0x8109, 0x00c0, 0x1122, 0x2069, 0x5400, 0x2009, 0x0002, 0x20a9,
+ 0x8109, 0x00c0, 0x1122, 0x2069, 0x5500, 0x2009, 0x0002, 0x20a9,
0x0100, 0x6837, 0x0000, 0x680b, 0x0040, 0x7bf0, 0xa386, 0xfeff,
0x00c0, 0x1148, 0x6817, 0x0100, 0x681f, 0x0064, 0x0078, 0x114c,
0x6817, 0x0064, 0x681f, 0x0002, 0xade8, 0x0010, 0x0070, 0x1152,
- 0x0078, 0x1139, 0x8109, 0x00c0, 0x1137, 0x1078, 0x220a, 0x1078,
- 0x482c, 0x1078, 0x1963, 0x1078, 0x4d22, 0x3200, 0xa085, 0x000d,
+ 0x0078, 0x1139, 0x8109, 0x00c0, 0x1137, 0x1078, 0x22a7, 0x1078,
+ 0x493d, 0x1078, 0x19b5, 0x1078, 0x4e33, 0x3200, 0xa085, 0x000d,
0x2090, 0x70c3, 0x0000, 0x0090, 0x116c, 0x70c0, 0xa086, 0x0002,
0x00c0, 0x116c, 0x1078, 0x1284, 0x1078, 0x1196, 0x78cc, 0xa005,
- 0x00c0, 0x117a, 0x1078, 0x1ce3, 0x0010, 0x1180, 0x0068, 0x1180,
- 0x1078, 0x20e9, 0x0010, 0x1180, 0x0068, 0x1180, 0x1078, 0x1a48,
- 0x00e0, 0x116c, 0x1078, 0x4ba9, 0x0078, 0x116c, 0x118e, 0x1190,
- 0x240b, 0x240b, 0x48ad, 0x48ad, 0x240b, 0x240b, 0x0078, 0x118e,
+ 0x00c0, 0x117a, 0x1078, 0x1d4f, 0x0010, 0x1180, 0x0068, 0x1180,
+ 0x1078, 0x2186, 0x0010, 0x1180, 0x0068, 0x1180, 0x1078, 0x1ab9,
+ 0x00e0, 0x116c, 0x1078, 0x4cba, 0x0078, 0x116c, 0x118e, 0x1190,
+ 0x24ac, 0x24ac, 0x49be, 0x49be, 0x24ac, 0x24ac, 0x0078, 0x118e,
0x0078, 0x1190, 0x0078, 0x1192, 0x0078, 0x1194, 0x0068, 0x1201,
0x2061, 0x0000, 0x6018, 0xa084, 0x0001, 0x00c0, 0x1201, 0x7814,
0xa005, 0x00c0, 0x11a7, 0x0010, 0x1202, 0x0078, 0x1201, 0x2009,
- 0x515b, 0x2104, 0xa005, 0x00c0, 0x1201, 0x2009, 0x5164, 0x200b,
+ 0x525b, 0x2104, 0xa005, 0x00c0, 0x1201, 0x2009, 0x5264, 0x200b,
0x0000, 0x7914, 0xa186, 0x0042, 0x00c0, 0x11cc, 0x7816, 0x2009,
- 0x5162, 0x2164, 0x200b, 0x0000, 0x6018, 0x70c6, 0x6014, 0x70ca,
+ 0x5262, 0x2164, 0x200b, 0x0000, 0x6018, 0x70c6, 0x6014, 0x70ca,
0x611c, 0xa18c, 0xff00, 0x6020, 0xa084, 0x00ff, 0xa105, 0x70ce,
- 0x1078, 0x1948, 0x0078, 0x11ff, 0x7814, 0xa086, 0x0018, 0x00c0,
- 0x11d3, 0x1078, 0x165a, 0x7817, 0x0000, 0x2009, 0x5162, 0x2104,
- 0xa065, 0x0040, 0x11ef, 0x0c7e, 0x609c, 0x2060, 0x1078, 0x19b3,
- 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1730, 0x2009, 0x000c, 0x6007,
- 0x0103, 0x1078, 0x1924, 0x00c0, 0x11fb, 0x1078, 0x1948, 0x2009,
- 0x5162, 0x200b, 0x0000, 0x2009, 0x515c, 0x2104, 0x200b, 0x0000,
+ 0x1078, 0x199a, 0x0078, 0x11ff, 0x7814, 0xa086, 0x0018, 0x00c0,
+ 0x11d3, 0x1078, 0x1678, 0x7817, 0x0000, 0x2009, 0x5262, 0x2104,
+ 0xa065, 0x0040, 0x11ef, 0x0c7e, 0x609c, 0x2060, 0x1078, 0x1a17,
+ 0x0c7f, 0x609f, 0x0000, 0x1078, 0x174e, 0x2009, 0x000c, 0x6007,
+ 0x0103, 0x1078, 0x1976, 0x00c0, 0x11fb, 0x1078, 0x199a, 0x2009,
+ 0x5262, 0x200b, 0x0000, 0x2009, 0x525c, 0x2104, 0x200b, 0x0000,
0xa005, 0x0040, 0x11ff, 0x2001, 0x4005, 0x0078, 0x1286, 0x0078,
0x1284, 0x007c, 0x70c3, 0x0000, 0x70c7, 0x0000, 0x70cb, 0x0000,
0x70cf, 0x0000, 0x70c0, 0xa0bc, 0xffc0, 0x00c0, 0x1252, 0x2038,
0x0079, 0x1212, 0x1284, 0x12e5, 0x12a9, 0x12fe, 0x130d, 0x1313,
- 0x12a0, 0x1748, 0x1317, 0x1298, 0x12ad, 0x12af, 0x12b1, 0x12b3,
- 0x174d, 0x1298, 0x1329, 0x1360, 0x1672, 0x1742, 0x12b5, 0x1591,
- 0x15ad, 0x15c9, 0x15f4, 0x154a, 0x1558, 0x156c, 0x1580, 0x13df,
- 0x1298, 0x138d, 0x1393, 0x1398, 0x139d, 0x13a3, 0x13a8, 0x13ad,
- 0x13b2, 0x13b7, 0x13bb, 0x13d0, 0x13dc, 0x1298, 0x1298, 0x1298,
- 0x1298, 0x13eb, 0x13f4, 0x1403, 0x1429, 0x1433, 0x143a, 0x1480,
- 0x148f, 0x149e, 0x14b0, 0x152a, 0x153a, 0x1298, 0x1298, 0x1298,
- 0x1298, 0x153f, 0xa0bc, 0xffa0, 0x00c0, 0x1298, 0x2038, 0xa084,
- 0x001f, 0x0079, 0x125b, 0x1786, 0x1789, 0x1799, 0x1298, 0x1298,
- 0x18df, 0x18fc, 0x1298, 0x1298, 0x1298, 0x1900, 0x1908, 0x1298,
- 0x1298, 0x1298, 0x1298, 0x12db, 0x12f4, 0x131f, 0x1356, 0x1668,
- 0x1764, 0x1778, 0x1298, 0x1829, 0x190e, 0x18bb, 0x18c5, 0x18c9,
- 0x18d7, 0x1298, 0x1298, 0x72ca, 0x71c6, 0x2001, 0x4006, 0x0078,
+ 0x12a0, 0x1766, 0x1317, 0x1298, 0x12ad, 0x12af, 0x12b1, 0x12b3,
+ 0x176b, 0x1298, 0x1329, 0x1365, 0x1690, 0x1760, 0x12b5, 0x15af,
+ 0x15cb, 0x15e7, 0x1612, 0x1568, 0x1576, 0x158a, 0x159e, 0x13e9,
+ 0x1298, 0x1397, 0x139d, 0x13a2, 0x13a7, 0x13ad, 0x13b2, 0x13b7,
+ 0x13bc, 0x13c1, 0x13c5, 0x13da, 0x13e6, 0x1298, 0x1298, 0x1298,
+ 0x1298, 0x13f5, 0x13fe, 0x140d, 0x1451, 0x145b, 0x1462, 0x14a8,
+ 0x14b7, 0x14c6, 0x14d8, 0x1548, 0x1558, 0x1298, 0x1298, 0x1298,
+ 0x1298, 0x155d, 0xa0bc, 0xffa0, 0x00c0, 0x1298, 0x2038, 0xa084,
+ 0x001f, 0x0079, 0x125b, 0x17a4, 0x17a7, 0x17b7, 0x1298, 0x1298,
+ 0x1931, 0x194e, 0x1298, 0x1298, 0x1298, 0x1952, 0x195a, 0x1298,
+ 0x1298, 0x1298, 0x1298, 0x12db, 0x12f4, 0x131f, 0x135b, 0x1686,
+ 0x1782, 0x1796, 0x1298, 0x1847, 0x1960, 0x190d, 0x1917, 0x191b,
+ 0x1929, 0x1298, 0x1298, 0x72ca, 0x71c6, 0x2001, 0x4006, 0x0078,
0x1286, 0x73ce, 0x72ca, 0x71c6, 0x2001, 0x4000, 0x70c2, 0x0068,
0x1287, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x5000, 0x00e0,
0x128f, 0x00e0, 0x1291, 0x0068, 0x1291, 0x2091, 0x4080, 0x007c,
@@ -126,1974 +126,2005 @@ static unsigned short risc_code01[] = {
0x0007, 0x3f00, 0x70d6, 0x2079, 0x0000, 0x781b, 0x0001, 0x2031,
0x0030, 0x2059, 0x1000, 0x2029, 0x0457, 0x2051, 0x0470, 0x2061,
0x0472, 0x20b9, 0xffff, 0x20c1, 0x0000, 0x2091, 0x5000, 0x2091,
- 0x4080, 0x0078, 0x0455, 0x1078, 0x1b53, 0x00c0, 0x129c, 0x75d8,
+ 0x4080, 0x0078, 0x0455, 0x1078, 0x1bc4, 0x00c0, 0x129c, 0x75d8,
0x74dc, 0x75da, 0x74de, 0x0078, 0x12e8, 0x2029, 0x0000, 0x2520,
- 0x71d0, 0x73c8, 0x72cc, 0x70c4, 0x1078, 0x1a8d, 0x0040, 0x1284,
- 0x70c3, 0x4002, 0x0078, 0x1284, 0x1078, 0x1b53, 0x00c0, 0x129c,
+ 0x71d0, 0x73c8, 0x72cc, 0x70c4, 0x1078, 0x1afe, 0x0040, 0x1284,
+ 0x70c3, 0x4002, 0x0078, 0x1284, 0x1078, 0x1bc4, 0x00c0, 0x129c,
0x75d8, 0x74dc, 0x75da, 0x74de, 0x0078, 0x1301, 0x2029, 0x0000,
- 0x2520, 0x71d0, 0x73c8, 0x72cc, 0x70c4, 0x1078, 0x1aed, 0x0040,
+ 0x2520, 0x71d0, 0x73c8, 0x72cc, 0x70c4, 0x1078, 0x1b5e, 0x0040,
0x1284, 0x70c3, 0x4002, 0x0078, 0x1284, 0x71c4, 0x70c8, 0x2114,
0x200a, 0x0078, 0x1282, 0x71c4, 0x2114, 0x0078, 0x1282, 0x70c7,
- 0x0007, 0x70cb, 0x0041, 0x70cf, 0x0000, 0x0078, 0x1284, 0x1078,
- 0x1b53, 0x00c0, 0x129c, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0078,
+ 0x0007, 0x70cb, 0x0041, 0x70cf, 0x0006, 0x0078, 0x1284, 0x1078,
+ 0x1bc4, 0x00c0, 0x129c, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0078,
0x132c, 0x2029, 0x0000, 0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d0,
- 0x70c6, 0x72ca, 0x73ce, 0x74d2, 0xa005, 0x0040, 0x1350, 0x8001,
- 0x7892, 0xa084, 0xfc00, 0x0040, 0x1345, 0x78cc, 0xa085, 0x0001,
- 0x78ce, 0x2001, 0x4005, 0x0078, 0x1286, 0x7a9a, 0x7b9e, 0x7da2,
- 0x7ea6, 0x7c96, 0x78cc, 0xa084, 0xfffc, 0x78ce, 0x0078, 0x1354,
- 0x78cc, 0xa085, 0x0001, 0x78ce, 0x0078, 0x1284, 0x1078, 0x1b53,
- 0x00c0, 0x129c, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0078, 0x1363,
- 0x2029, 0x0000, 0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d4, 0x70c6,
- 0x72ca, 0x73ce, 0x74d6, 0xa005, 0x0040, 0x1387, 0x8001, 0x78ae,
- 0xa084, 0xfc00, 0x0040, 0x137c, 0x78cc, 0xa085, 0x0100, 0x78ce,
- 0x2001, 0x4005, 0x0078, 0x1286, 0x7ab6, 0x7bba, 0x7dbe, 0x7ec2,
- 0x7cb2, 0x78cc, 0xa084, 0xfcff, 0x78ce, 0x0078, 0x138b, 0x78cc,
- 0xa085, 0x0100, 0x78ce, 0x0078, 0x1284, 0x2009, 0x5161, 0x210c,
- 0x7aec, 0x0078, 0x1282, 0x2009, 0x5141, 0x210c, 0x0078, 0x1283,
- 0x2009, 0x5142, 0x210c, 0x0078, 0x1283, 0x2061, 0x5140, 0x610c,
- 0x6210, 0x0078, 0x1282, 0x2009, 0x5145, 0x210c, 0x0078, 0x1283,
- 0x2009, 0x5146, 0x210c, 0x0078, 0x1283, 0x2009, 0x5148, 0x210c,
- 0x0078, 0x1283, 0x2009, 0x5149, 0x210c, 0x0078, 0x1283, 0x7908,
- 0x7a0c, 0x0078, 0x1282, 0x71c4, 0x8107, 0xa084, 0x000f, 0x8003,
- 0x8003, 0x8003, 0xa0e8, 0x5380, 0x6a00, 0x6804, 0xa084, 0x0008,
- 0x0040, 0x13cd, 0x6b08, 0x0078, 0x13ce, 0x6b0c, 0x0078, 0x1281,
- 0x77c4, 0x1078, 0x1973, 0x2091, 0x8000, 0x6b1c, 0x6a14, 0x2091,
- 0x8001, 0x2708, 0x0078, 0x1281, 0x794c, 0x0078, 0x1283, 0x77c4,
- 0x1078, 0x1973, 0x2091, 0x8000, 0x6908, 0x6a18, 0x6b10, 0x2091,
- 0x8001, 0x0078, 0x1281, 0x71c4, 0xa182, 0x0010, 0x00c8, 0x127c,
- 0x1078, 0x22e2, 0x0078, 0x1281, 0x71c4, 0xa182, 0x0010, 0x00c8,
- 0x127c, 0x2011, 0x5141, 0x2204, 0x007e, 0x2112, 0x1078, 0x229b,
- 0x017f, 0x0078, 0x1283, 0x71c4, 0x2011, 0x1421, 0x20a9, 0x0008,
- 0x2204, 0xa106, 0x0040, 0x1413, 0x8210, 0x0070, 0x1411, 0x0078,
- 0x1408, 0x0078, 0x127c, 0xa292, 0x1421, 0x027e, 0x2011, 0x5142,
- 0x2204, 0x2112, 0x017f, 0x007e, 0x1078, 0x22a7, 0x017f, 0x0078,
+ 0x70c6, 0x72ca, 0x73ce, 0x74d2, 0xa005, 0x0040, 0x1355, 0xa40a,
+ 0x0040, 0x133c, 0x00c8, 0x1346, 0x8001, 0x7892, 0xa084, 0xfc00,
+ 0x0040, 0x134a, 0x78cc, 0xa085, 0x0001, 0x78ce, 0x2001, 0x4005,
+ 0x0078, 0x1286, 0x7a9a, 0x7b9e, 0x7da2, 0x7ea6, 0x7c96, 0x78cc,
+ 0xa084, 0xfffc, 0x78ce, 0x0078, 0x1359, 0x78cc, 0xa085, 0x0001,
+ 0x78ce, 0x0078, 0x1284, 0x1078, 0x1bc4, 0x00c0, 0x129c, 0x75d8,
+ 0x76dc, 0x75da, 0x76de, 0x0078, 0x1368, 0x2029, 0x0000, 0x2530,
+ 0x70c4, 0x72c8, 0x73cc, 0x74d4, 0x70c6, 0x72ca, 0x73ce, 0x74d6,
+ 0xa005, 0x0040, 0x1391, 0xa40a, 0x0040, 0x1378, 0x00c8, 0x1382,
+ 0x8001, 0x78ae, 0xa084, 0xfc00, 0x0040, 0x1386, 0x78cc, 0xa085,
+ 0x0100, 0x78ce, 0x2001, 0x4005, 0x0078, 0x1286, 0x7ab6, 0x7bba,
+ 0x7dbe, 0x7ec2, 0x7cb2, 0x78cc, 0xa084, 0xfcff, 0x78ce, 0x0078,
+ 0x1395, 0x78cc, 0xa085, 0x0100, 0x78ce, 0x0078, 0x1284, 0x2009,
+ 0x5261, 0x210c, 0x7aec, 0x0078, 0x1282, 0x2009, 0x5241, 0x210c,
+ 0x0078, 0x1283, 0x2009, 0x5242, 0x210c, 0x0078, 0x1283, 0x2061,
+ 0x5240, 0x610c, 0x6210, 0x0078, 0x1282, 0x2009, 0x5245, 0x210c,
+ 0x0078, 0x1283, 0x2009, 0x5246, 0x210c, 0x0078, 0x1283, 0x2009,
+ 0x5248, 0x210c, 0x0078, 0x1283, 0x2009, 0x5249, 0x210c, 0x0078,
+ 0x1283, 0x7908, 0x7a0c, 0x0078, 0x1282, 0x71c4, 0x8107, 0xa084,
+ 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e8, 0x5480, 0x6a00, 0x6804,
+ 0xa084, 0x0008, 0x0040, 0x13d7, 0x6b08, 0x0078, 0x13d8, 0x6b0c,
+ 0x0078, 0x1281, 0x77c4, 0x1078, 0x19c5, 0x2091, 0x8000, 0x6b1c,
+ 0x6a14, 0x2091, 0x8001, 0x2708, 0x0078, 0x1281, 0x794c, 0x0078,
+ 0x1283, 0x77c4, 0x1078, 0x19c5, 0x2091, 0x8000, 0x6908, 0x6a18,
+ 0x6b10, 0x2091, 0x8001, 0x0078, 0x1281, 0x71c4, 0xa182, 0x0010,
+ 0x00c8, 0x127c, 0x1078, 0x237f, 0x0078, 0x1281, 0x71c4, 0xa182,
+ 0x0010, 0x00c8, 0x127c, 0x2011, 0x5241, 0x2204, 0x007e, 0x2112,
+ 0x1078, 0x2338, 0x017f, 0x0078, 0x1283, 0x71c4, 0x2019, 0x0100,
+ 0x2304, 0xa082, 0x0006, 0x0048, 0x141b, 0x2011, 0x1449, 0x20a9,
+ 0x0008, 0x0078, 0x141f, 0x2011, 0x1441, 0x20a9, 0x0008, 0x2204,
+ 0xa106, 0x0040, 0x142a, 0x8210, 0x0070, 0x1428, 0x0078, 0x141f,
+ 0x0078, 0x127c, 0x2304, 0xa082, 0x0006, 0x0048, 0x1433, 0xa292,
+ 0x1449, 0x0078, 0x1435, 0xa292, 0x1441, 0x027e, 0x2011, 0x5242,
+ 0x2204, 0x2112, 0x017f, 0x007e, 0x1078, 0x2344, 0x017f, 0x0078,
0x1283, 0x03e8, 0x00fa, 0x01f4, 0x02ee, 0x0064, 0x0019, 0x0032,
- 0x004b, 0x2061, 0x5140, 0x610c, 0x6210, 0x70c4, 0x600e, 0x70c8,
- 0x6012, 0x0078, 0x1282, 0x2061, 0x5140, 0x6114, 0x70c4, 0x6016,
- 0x0078, 0x1283, 0x2061, 0x5140, 0x71c4, 0x2011, 0x0004, 0x601f,
- 0x0019, 0x2019, 0x1212, 0xa186, 0x0028, 0x0040, 0x145b, 0x2011,
+ 0x004b, 0x03e8, 0x00fa, 0x01f4, 0x02ee, 0x0004, 0x0001, 0x0002,
+ 0x0003, 0x2061, 0x5240, 0x610c, 0x6210, 0x70c4, 0x600e, 0x70c8,
+ 0x6012, 0x0078, 0x1282, 0x2061, 0x5240, 0x6114, 0x70c4, 0x6016,
+ 0x0078, 0x1283, 0x2061, 0x5240, 0x71c4, 0x2011, 0x0004, 0x601f,
+ 0x0019, 0x2019, 0x1212, 0xa186, 0x0028, 0x0040, 0x1483, 0x2011,
0x0005, 0x601f, 0x0019, 0x2019, 0x1212, 0xa186, 0x0032, 0x0040,
- 0x145b, 0x2011, 0x0006, 0x601f, 0x000c, 0x2019, 0x2222, 0xa186,
+ 0x1483, 0x2011, 0x0006, 0x601f, 0x000c, 0x2019, 0x2222, 0xa186,
0x003c, 0x00c0, 0x127c, 0x6018, 0x007e, 0x611a, 0x7800, 0xa084,
- 0x0001, 0x00c0, 0x1476, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005,
- 0x0048, 0x146e, 0x0038, 0x1472, 0x0078, 0x1476, 0x0028, 0x1472,
- 0x0078, 0x1476, 0x2019, 0x2222, 0x0078, 0x1478, 0x2019, 0x1212,
- 0x23b8, 0x1078, 0x22b8, 0x1078, 0x4d22, 0x017f, 0x0078, 0x1283,
- 0x71c4, 0xa184, 0xffcf, 0x00c0, 0x127c, 0x2011, 0x5148, 0x2204,
- 0x2112, 0x007e, 0x1078, 0x22da, 0x017f, 0x0078, 0x1283, 0x71c4,
- 0xa182, 0x0010, 0x00c8, 0x127c, 0x2011, 0x5149, 0x2204, 0x007e,
- 0x2112, 0x1078, 0x22c9, 0x017f, 0x0078, 0x1283, 0x71c4, 0x72c8,
+ 0x0001, 0x00c0, 0x149e, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005,
+ 0x0048, 0x1496, 0x0038, 0x149a, 0x0078, 0x149e, 0x0028, 0x149a,
+ 0x0078, 0x149e, 0x2019, 0x2222, 0x0078, 0x14a0, 0x2019, 0x1212,
+ 0x23b8, 0x1078, 0x2355, 0x1078, 0x4e33, 0x017f, 0x0078, 0x1283,
+ 0x71c4, 0xa184, 0xffcf, 0x00c0, 0x127c, 0x2011, 0x5248, 0x2204,
+ 0x2112, 0x007e, 0x1078, 0x2377, 0x017f, 0x0078, 0x1283, 0x71c4,
+ 0xa182, 0x0010, 0x00c8, 0x127c, 0x2011, 0x5249, 0x2204, 0x007e,
+ 0x2112, 0x1078, 0x2366, 0x017f, 0x0078, 0x1283, 0x71c4, 0x72c8,
0xa184, 0xfffd, 0x00c0, 0x127b, 0xa284, 0xfffd, 0x00c0, 0x127b,
0x2100, 0x7908, 0x780a, 0x2200, 0x7a0c, 0x780e, 0x0078, 0x1282,
0x71c4, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e8,
- 0x5380, 0x2019, 0x0000, 0x72c8, 0xa284, 0x0080, 0x0040, 0x14c6,
- 0x6c14, 0x84ff, 0x00c0, 0x14c6, 0x6817, 0x0040, 0xa284, 0x0040,
- 0x0040, 0x14d0, 0x6c10, 0x84ff, 0x00c0, 0x14d0, 0x6813, 0x0001,
- 0x6800, 0x007e, 0xa226, 0x0040, 0x14f3, 0x6a02, 0xa484, 0x2000,
- 0x0040, 0x14dc, 0xa39d, 0x0010, 0xa484, 0x1000, 0x0040, 0x14e2,
- 0xa39d, 0x0008, 0xa484, 0x4000, 0x0040, 0x14f3, 0x810f, 0xa284,
- 0x4000, 0x0040, 0x14ef, 0x1078, 0x22fc, 0x0078, 0x14f3, 0x1078,
- 0x22ee, 0x0078, 0x14f3, 0x72cc, 0x6808, 0xa206, 0x0040, 0x1522,
- 0xa2a4, 0x00ff, 0x2061, 0x5140, 0x6118, 0xa186, 0x0028, 0x0040,
- 0x1509, 0xa186, 0x0032, 0x0040, 0x150f, 0xa186, 0x003c, 0x0040,
- 0x1515, 0xa482, 0x0064, 0x0048, 0x151f, 0x0078, 0x1519, 0xa482,
- 0x0050, 0x0048, 0x151f, 0x0078, 0x1519, 0xa482, 0x0043, 0x0048,
- 0x151f, 0x71c4, 0x71c6, 0x027f, 0x72ca, 0x0078, 0x127d, 0x6a0a,
- 0xa39d, 0x000a, 0x6804, 0xa305, 0x6806, 0x027f, 0x6b0c, 0x71c4,
- 0x0078, 0x1281, 0x77c4, 0x1078, 0x1973, 0x2091, 0x8000, 0x6a14,
- 0x6b1c, 0x2091, 0x8001, 0x70c8, 0x6816, 0x70cc, 0x681e, 0x2708,
- 0x0078, 0x1281, 0x70c4, 0x794c, 0x784e, 0x0078, 0x1283, 0x71c4,
- 0x72c8, 0x73cc, 0xa182, 0x0010, 0x00c8, 0x127c, 0x1078, 0x230a,
- 0x0078, 0x1281, 0x77c4, 0x1078, 0x1973, 0x2091, 0x8000, 0x6a08,
- 0xa295, 0x0002, 0x6a0a, 0x2091, 0x8001, 0x2708, 0x0078, 0x1282,
- 0x77c4, 0x1078, 0x1973, 0x2091, 0x8000, 0x6a08, 0xa294, 0xfff9,
- 0x6a0a, 0x6804, 0xa005, 0x0040, 0x1567, 0x1078, 0x21d2, 0x2091,
- 0x8001, 0x2708, 0x0078, 0x1282, 0x77c4, 0x1078, 0x1973, 0x2091,
- 0x8000, 0x6a08, 0xa295, 0x0004, 0x6a0a, 0x6804, 0xa005, 0x0040,
- 0x157b, 0x1078, 0x21d2, 0x2091, 0x8001, 0x2708, 0x0078, 0x1282,
- 0x77c4, 0x2041, 0x0001, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091,
- 0x8000, 0x1078, 0x1980, 0x2091, 0x8001, 0x2708, 0x6a08, 0x0078,
- 0x1282, 0x77c4, 0x72c8, 0x73cc, 0x77c6, 0x72ca, 0x73ce, 0x1078,
- 0x19e1, 0x00c0, 0x15a9, 0x6818, 0xa005, 0x0040, 0x15a9, 0x2708,
- 0x1078, 0x231a, 0x00c0, 0x15a9, 0x7817, 0x0015, 0x2091, 0x8001,
- 0x007c, 0x2091, 0x8001, 0x0078, 0x1284, 0x77c4, 0x77c6, 0x2041,
- 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x1078,
- 0x1980, 0x2061, 0x5140, 0x606f, 0x0003, 0x6782, 0x6093, 0x000f,
- 0x6073, 0x0000, 0x7817, 0x0016, 0x1078, 0x21d2, 0x2091, 0x8001,
- 0x007c, 0x77c8, 0x77ca, 0x77c4, 0x77c6, 0xa7bc, 0xff00, 0x2091,
- 0x8000, 0x2061, 0x5140, 0x606f, 0x0002, 0x6073, 0x0000, 0x6782,
- 0x6093, 0x000f, 0x7817, 0x0017, 0x1078, 0x21d2, 0x2091, 0x8001,
- 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0010, 0x2091, 0x8000,
- 0x1078, 0x1980, 0x70c8, 0x6836, 0x8738, 0xa784, 0x001f, 0x00c0,
- 0x15e8, 0x2091, 0x8001, 0x007c, 0x78cc, 0xa084, 0x0003, 0x00c0,
- 0x1618, 0x2039, 0x0000, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051,
- 0x0008, 0x1078, 0x1973, 0x2091, 0x8000, 0x6808, 0xa80d, 0x690a,
- 0x2091, 0x8001, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1601, 0xa7bc,
- 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0, 0x1601,
- 0x2091, 0x8000, 0x2069, 0x0100, 0x6830, 0xa084, 0x0040, 0x0040,
- 0x1641, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0004,
- 0x0040, 0x162e, 0x0070, 0x162e, 0x0078, 0x1625, 0x684b, 0x0009,
- 0x20a9, 0x0014, 0x6848, 0xa084, 0x0001, 0x0040, 0x163b, 0x0070,
- 0x163b, 0x0078, 0x1632, 0x20a9, 0x00fa, 0x0070, 0x1641, 0x0078,
- 0x163d, 0x2079, 0x5100, 0x7817, 0x0018, 0x2061, 0x5140, 0x606f,
- 0x0001, 0x6073, 0x0000, 0x6093, 0x000f, 0x78cc, 0xa085, 0x0002,
- 0x78ce, 0x6808, 0xa084, 0xfffd, 0x680a, 0x681b, 0x0048, 0x2091,
- 0x8001, 0x007c, 0x78cc, 0xa084, 0xfffd, 0x78ce, 0xa084, 0x0001,
- 0x00c0, 0x1664, 0x1078, 0x1a2b, 0x71c4, 0x71c6, 0x794a, 0x007c,
- 0x1078, 0x1b53, 0x00c0, 0x129c, 0x75d8, 0x74dc, 0x75da, 0x74de,
- 0x0078, 0x1675, 0x2029, 0x0000, 0x2520, 0x71c4, 0x73c8, 0x72cc,
- 0x71c6, 0x73ca, 0x72ce, 0x2079, 0x5100, 0x2091, 0x8000, 0x1078,
- 0x192e, 0x2091, 0x8001, 0x0040, 0x172c, 0x20a9, 0x0005, 0x20a1,
- 0x5118, 0x2091, 0x8000, 0x41a1, 0x2091, 0x8001, 0x2009, 0x0020,
- 0x1078, 0x1929, 0x0040, 0x1698, 0x1078, 0x1948, 0x0078, 0x172c,
- 0x6004, 0xa084, 0xff00, 0x8007, 0x8009, 0x0040, 0x16fb, 0x0c7e,
- 0x2c68, 0x2091, 0x8000, 0x1078, 0x192e, 0x2091, 0x8001, 0x0040,
- 0x16cc, 0x2c00, 0x689e, 0x8109, 0x00c0, 0x16a0, 0x609f, 0x0000,
- 0x0c7f, 0x0c7e, 0x7218, 0x731c, 0x7420, 0x7524, 0x2c68, 0x689c,
- 0xa065, 0x0040, 0x16fa, 0x2009, 0x0020, 0x1078, 0x1929, 0x00c0,
- 0x16e3, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0002, 0x00c0, 0x16cc,
- 0x2d00, 0x6002, 0x0078, 0x16b2, 0x0c7f, 0x0c7e, 0x609c, 0x2060,
- 0x1078, 0x19b3, 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1730, 0x2009,
- 0x000c, 0x6008, 0xa085, 0x0200, 0x600a, 0x1078, 0x1924, 0x1078,
- 0x1948, 0x0078, 0x172c, 0x0c7f, 0x0c7e, 0x609c, 0x2060, 0x1078,
- 0x19b3, 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1730, 0x2009, 0x000c,
- 0x6007, 0x0103, 0x601b, 0x0003, 0x1078, 0x1924, 0x1078, 0x1948,
- 0x0078, 0x172c, 0x0c7f, 0x74c4, 0x73c8, 0x72cc, 0x6014, 0x2091,
- 0x8000, 0x7817, 0x0012, 0x0e7e, 0x2071, 0x5140, 0x706f, 0x0005,
- 0x7073, 0x0000, 0x7376, 0x727a, 0x747e, 0x7082, 0x7087, 0x0000,
- 0x2c00, 0x708a, 0x708f, 0x0000, 0xa02e, 0x2530, 0x611c, 0x61a2,
- 0xa184, 0x0060, 0x0040, 0x171e, 0x1078, 0x47c2, 0x0e7f, 0x6596,
- 0x65a6, 0x669a, 0x66aa, 0x60af, 0x0000, 0x60b3, 0x0000, 0x1078,
- 0x21d2, 0x2091, 0x8001, 0x007c, 0x70c3, 0x4005, 0x0078, 0x1287,
- 0x20a9, 0x0005, 0x2099, 0x5118, 0x2091, 0x8000, 0x530a, 0x2091,
- 0x8001, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9,
- 0x0000, 0x007c, 0x71c4, 0x70c7, 0x0000, 0x7906, 0x0078, 0x1284,
- 0x71c4, 0x71c6, 0x2168, 0x0078, 0x174f, 0x2069, 0x1000, 0x690c,
- 0xa016, 0x2d04, 0xa210, 0x8d68, 0x8109, 0x00c0, 0x1751, 0xa285,
- 0x0000, 0x00c0, 0x175f, 0x70c3, 0x4000, 0x0078, 0x1761, 0x70c3,
- 0x4003, 0x70ca, 0x0078, 0x1287, 0x2011, 0x5167, 0x220c, 0x70c4,
- 0x8003, 0x0048, 0x1771, 0x1078, 0x3b7f, 0xa184, 0x7fff, 0x0078,
- 0x1775, 0x1078, 0x3b72, 0xa185, 0x8000, 0x2012, 0x0078, 0x1283,
- 0x71c4, 0x1078, 0x3b69, 0x6100, 0x2001, 0x5167, 0x2004, 0xa084,
- 0x8000, 0xa10d, 0x6204, 0x6308, 0x0078, 0x1281, 0x79e4, 0x0078,
- 0x1283, 0x71c4, 0x71c6, 0x2198, 0x20a1, 0x0042, 0x20a9, 0x0004,
- 0x53a3, 0x21a0, 0x2099, 0x0042, 0x20a9, 0x0004, 0x53a3, 0x0078,
- 0x1284, 0x70c4, 0x2068, 0x2079, 0x5100, 0x2091, 0x8000, 0x1078,
- 0x192e, 0x2091, 0x8001, 0x0040, 0x1825, 0x6007, 0x0001, 0x600b,
- 0x0000, 0x602b, 0x0000, 0x601b, 0x0006, 0x6a10, 0xa28c, 0x000f,
- 0xa284, 0x00f0, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0x6016,
- 0xa284, 0x0800, 0x0040, 0x17c0, 0x601b, 0x000a, 0x0078, 0x17c6,
- 0xa284, 0x1000, 0x0040, 0x17c6, 0x601b, 0x000c, 0xa284, 0x0300,
- 0x0040, 0x17cf, 0x602b, 0x0001, 0x8004, 0x8004, 0x8004, 0xa085,
- 0x0001, 0x601e, 0x6023, 0x0000, 0x6027, 0x0000, 0xa284, 0x0400,
- 0x0040, 0x17dc, 0x602b, 0x0000, 0x20a9, 0x0006, 0xac80, 0x000b,
- 0x20a0, 0xad80, 0x0005, 0x2098, 0x53a3, 0xa284, 0x0300, 0x00c0,
- 0x17f1, 0x6046, 0x604a, 0x604e, 0x6052, 0x6096, 0x609a, 0x0078,
- 0x17fb, 0x6800, 0x6046, 0x6804, 0x604a, 0x6e08, 0x664e, 0x6d0c,
- 0x6552, 0x6596, 0x669a, 0x6014, 0x2091, 0x8000, 0x7817, 0x0042,
- 0x2c08, 0x2061, 0x5140, 0x606f, 0x0005, 0x6073, 0x0000, 0x6077,
- 0x0000, 0x607b, 0x0000, 0x607f, 0x0000, 0x6082, 0x618a, 0xa284,
- 0x0400, 0x608e, 0x2091, 0x8001, 0x0e7e, 0x2071, 0x0020, 0x7007,
- 0x000a, 0x7007, 0x0002, 0x7003, 0x0000, 0x0e7f, 0x2091, 0x8000,
- 0x1078, 0x21d2, 0x2091, 0x8001, 0x007c, 0x70c3, 0x4005, 0x0078,
- 0x1287, 0x0c7e, 0x0d7e, 0x0e7e, 0x0f7e, 0x2091, 0x8000, 0x2071,
- 0x5140, 0x2079, 0x0100, 0x2061, 0x0010, 0x70a0, 0xa06d, 0x0040,
- 0x18b1, 0x6a04, 0xa294, 0x00ff, 0xa286, 0x0007, 0x0040, 0x1844,
- 0xa286, 0x000f, 0x00c0, 0x18b1, 0x691c, 0xa184, 0x0080, 0x00c0,
- 0x18b1, 0x6824, 0xa18c, 0xff00, 0xa085, 0x0019, 0x6826, 0x71b0,
- 0x81ff, 0x0040, 0x1867, 0x0d7e, 0x2069, 0x0020, 0x6807, 0x0010,
- 0x6908, 0x6808, 0xa106, 0x00c0, 0x1858, 0x690c, 0x680c, 0xa106,
- 0x00c0, 0x185d, 0xa184, 0x00ff, 0x00c0, 0x185d, 0x0d7f, 0x78b8,
- 0xa084, 0x801f, 0x00c0, 0x1867, 0x7848, 0xa085, 0x000c, 0x784a,
- 0x71b0, 0x81ff, 0x0040, 0x188a, 0x70b3, 0x0000, 0x0d7e, 0x2069,
- 0x0020, 0x6807, 0x0018, 0x6804, 0xa084, 0x0008, 0x00c0, 0x187b,
- 0x6807, 0x0008, 0x6804, 0xa084, 0x0008, 0x00c0, 0x1882, 0x6807,
- 0x0002, 0x0d7f, 0x61c4, 0x62c8, 0x63cc, 0x61c6, 0x62ca, 0x63ce,
- 0x0e7e, 0x2071, 0x5100, 0x7266, 0x736a, 0xae80, 0x0019, 0x0e7f,
- 0x7848, 0xa084, 0x000c, 0x00c0, 0x1898, 0x1078, 0x46db, 0x78a3,
- 0x0000, 0x7858, 0xa084, 0xedff, 0x785a, 0x70b4, 0xa080, 0x00df,
- 0x781a, 0x0f7f, 0x0e7f, 0x0d7f, 0x0c7f, 0x2091, 0x8001, 0x0078,
- 0x1284, 0x0f7f, 0x0e7f, 0x0d7f, 0x0c7f, 0x2091, 0x8001, 0x2001,
- 0x4005, 0x0078, 0x1286, 0x7980, 0x71c6, 0x71c4, 0xa182, 0x0003,
- 0x00c8, 0x127c, 0x7982, 0x0078, 0x1284, 0x7980, 0x71c6, 0x0078,
- 0x1284, 0x7974, 0x71c6, 0x71c4, 0x7976, 0x7978, 0x71ca, 0x71c8,
- 0x797a, 0x797c, 0x71ce, 0x71cc, 0x797e, 0x0078, 0x1284, 0x7974,
- 0x71c6, 0x7978, 0x71ca, 0x797c, 0x71ce, 0x0078, 0x1284, 0x7900,
- 0x71c6, 0x71c4, 0x7902, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005,
- 0x0048, 0x18ee, 0x0038, 0x18f0, 0x0078, 0x18fa, 0x00a8, 0x18fa,
- 0xa18c, 0x0001, 0x00c0, 0x18f8, 0x20b9, 0x2222, 0x0078, 0x18fa,
- 0x20b9, 0x1212, 0x0078, 0x1284, 0x7900, 0x71c6, 0x0078, 0x1284,
- 0x2009, 0x5174, 0x2104, 0x70c6, 0x70c4, 0x200a, 0x0078, 0x1284,
- 0x2009, 0x5174, 0x2104, 0x70c6, 0x0078, 0x1284, 0x71c4, 0x8107,
- 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e8, 0x5380, 0x6a14,
- 0xd2b4, 0x0040, 0x191f, 0x2011, 0x0001, 0x0078, 0x1921, 0x2011,
- 0x0000, 0x6b0c, 0x0078, 0x1281, 0xac80, 0x0001, 0x1078, 0x1b0f,
- 0x007c, 0xac80, 0x0001, 0x1078, 0x1aaf, 0x007c, 0x7850, 0xa065,
- 0x0040, 0x1936, 0x2c04, 0x7852, 0x2063, 0x0000, 0x007c, 0x0f7e,
- 0x2079, 0x5100, 0x7850, 0xa06d, 0x0040, 0x1946, 0x2d04, 0x7852,
- 0x6803, 0x0000, 0x6807, 0x0000, 0x680b, 0x0000, 0x0f7f, 0x007c,
- 0x2091, 0x8000, 0x0f7e, 0x2079, 0x5100, 0x7850, 0x2062, 0x2c00,
- 0xa005, 0x00c0, 0x1955, 0x1078, 0x23eb, 0x7852, 0x0f7f, 0x2091,
- 0x8001, 0x007c, 0x0f7e, 0x2079, 0x5100, 0x7850, 0x206a, 0x2d00,
- 0x7852, 0x0f7f, 0x007c, 0x2011, 0x7800, 0x7a52, 0x7bec, 0x8319,
- 0x0040, 0x1970, 0xa280, 0x0031, 0x2012, 0x2010, 0x0078, 0x1967,
- 0x2013, 0x0000, 0x007c, 0xa784, 0x0f00, 0x800b, 0xa784, 0x001f,
- 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xa0e8, 0x5400, 0x007c,
- 0x1078, 0x1973, 0x2900, 0x682a, 0x2a00, 0x682e, 0x6808, 0xa084,
- 0xffef, 0xa80d, 0x690a, 0x2009, 0x5152, 0x210c, 0x6804, 0xa005,
- 0x0040, 0x19b2, 0xa116, 0x00c0, 0x199d, 0x2060, 0x6000, 0x6806,
- 0x017e, 0x200b, 0x0000, 0x0078, 0x19a0, 0x2009, 0x0000, 0x017e,
- 0x6804, 0xa065, 0x0040, 0x19af, 0x6000, 0x6806, 0x1078, 0x19c0,
- 0x1078, 0x1c5f, 0x6810, 0x8001, 0x6812, 0x00c0, 0x19a0, 0x017f,
- 0x6902, 0x6906, 0x007c, 0xa065, 0x0040, 0x19bf, 0x609c, 0x609f,
- 0x0000, 0x2008, 0x1078, 0x1948, 0x2100, 0x0078, 0x19b3, 0x007c,
- 0x6007, 0x0103, 0x608f, 0x0000, 0x20a9, 0x001c, 0xac80, 0x0005,
- 0x20a0, 0x2001, 0x0000, 0x40a4, 0x6828, 0x601a, 0x682c, 0x6022,
- 0x007c, 0x0e7e, 0x2071, 0x5140, 0x704c, 0xa08c, 0x0200, 0x00c0,
- 0x19df, 0xa088, 0x5180, 0x2d0a, 0x8000, 0x704e, 0xa006, 0x0e7f,
- 0x007c, 0x1078, 0x1973, 0x2091, 0x8000, 0x6804, 0x781e, 0xa065,
- 0x0040, 0x1a2a, 0x0078, 0x19f2, 0x2c00, 0x781e, 0x6000, 0xa065,
- 0x0040, 0x1a2a, 0x600c, 0xa306, 0x00c0, 0x19ec, 0x6010, 0xa206,
- 0x00c0, 0x19ec, 0x2c28, 0x2001, 0x5152, 0x2004, 0xac06, 0x00c0,
- 0x1a03, 0x0078, 0x1a28, 0x6804, 0xac06, 0x00c0, 0x1a10, 0x6000,
- 0xa065, 0x6806, 0x00c0, 0x1a1a, 0x6803, 0x0000, 0x0078, 0x1a1a,
- 0x6400, 0x781c, 0x2060, 0x6402, 0xa486, 0x0000, 0x00c0, 0x1a1a,
- 0x2c00, 0x6802, 0x2560, 0x1078, 0x19c0, 0x601b, 0x0005, 0x6023,
- 0x0020, 0x1078, 0x1c5f, 0x6810, 0x8001, 0x1050, 0x23eb, 0x6812,
- 0xa085, 0xffff, 0x007c, 0x2039, 0x0000, 0x2041, 0x0021, 0x2049,
- 0x0004, 0x2051, 0x0008, 0x2091, 0x8000, 0x1078, 0x1980, 0x8738,
- 0xa784, 0x001f, 0x00c0, 0x1a35, 0xa7bc, 0xff00, 0x873f, 0x8738,
- 0x873f, 0xa784, 0x0f00, 0x00c0, 0x1a35, 0x2091, 0x8001, 0x007c,
- 0x2061, 0x0000, 0x6018, 0xa084, 0x0001, 0x00c0, 0x1a59, 0x2091,
- 0x8000, 0x78e0, 0x78e3, 0x0000, 0x2091, 0x8001, 0xa005, 0x00c0,
- 0x1a5a, 0x007c, 0xa08c, 0xfff0, 0x0040, 0x1a60, 0x1078, 0x23eb,
- 0x0079, 0x1a62, 0x1a72, 0x1a75, 0x1a7b, 0x1a7f, 0x1a73, 0x1a83,
- 0x1a89, 0x1a73, 0x1a73, 0x1c29, 0x1c4d, 0x1c51, 0x1a73, 0x1a73,
- 0x1a73, 0x1a73, 0x007c, 0x1078, 0x23eb, 0x1078, 0x1a2b, 0x2001,
- 0x8001, 0x0078, 0x1c57, 0x2001, 0x8003, 0x0078, 0x1c57, 0x2001,
- 0x8004, 0x0078, 0x1c57, 0x1078, 0x1a2b, 0x2001, 0x8006, 0x0078,
- 0x1c57, 0x2001, 0x8007, 0x0078, 0x1c57, 0x2030, 0x2138, 0xa782,
- 0x0021, 0x0048, 0x1a95, 0x2009, 0x0020, 0x2600, 0x1078, 0x1aaf,
- 0x00c0, 0x1aae, 0xa7ba, 0x0020, 0x0048, 0x1aad, 0x0040, 0x1aad,
- 0x2708, 0xa6b0, 0x0020, 0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1,
- 0x0000, 0xa5a9, 0x0000, 0x0078, 0x1a8f, 0xa006, 0x007c, 0x81ff,
- 0x0040, 0x1aea, 0x2099, 0x0030, 0x20a0, 0x700c, 0xa084, 0x00ff,
- 0x0040, 0x1ac1, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0,
- 0x1abc, 0x21a8, 0x7017, 0x0000, 0x810b, 0x7112, 0x721a, 0x731e,
- 0x7422, 0x7526, 0x780c, 0xa085, 0x0001, 0x7002, 0x7007, 0x0001,
- 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x00c8, 0x1ade, 0x2009,
- 0x0022, 0x2104, 0xa084, 0x4000, 0x00c0, 0x1ad0, 0x7008, 0x800b,
- 0x00c8, 0x1ad0, 0x7007, 0x0002, 0xa08c, 0x01e0, 0x00c0, 0x1aea,
- 0x53a5, 0xa006, 0x7003, 0x0000, 0x007c, 0x2030, 0x2138, 0xa782,
- 0x0021, 0x0048, 0x1af5, 0x2009, 0x0020, 0x2600, 0x1078, 0x1b0f,
- 0x00c0, 0x1b0e, 0xa7ba, 0x0020, 0x0048, 0x1b0d, 0x0040, 0x1b0d,
- 0x2708, 0xa6b0, 0x0020, 0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1,
- 0x0000, 0xa5a9, 0x0000, 0x0078, 0x1aef, 0xa006, 0x007c, 0x81ff,
- 0x0040, 0x1b50, 0x2098, 0x20a1, 0x0030, 0x700c, 0xa084, 0x00ff,
- 0x0040, 0x1b21, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0,
- 0x1b1c, 0x21a8, 0x7017, 0x0000, 0x810b, 0x7112, 0x721a, 0x731e,
- 0x7422, 0x7526, 0x780c, 0xa085, 0x0000, 0x7002, 0x53a6, 0x7007,
- 0x0001, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x00c8, 0x1b3f,
- 0x2009, 0x0022, 0x2104, 0xa084, 0x4000, 0x00c0, 0x1b31, 0x7010,
- 0xa084, 0xf000, 0x0040, 0x1b48, 0x7007, 0x0008, 0x0078, 0x1b4c,
- 0x7108, 0x8103, 0x00c8, 0x1b31, 0x7007, 0x0002, 0xa184, 0x01e0,
- 0x7003, 0x0000, 0x007c, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0004,
- 0x00c8, 0x1b5c, 0x0078, 0x1b5f, 0xa006, 0x0078, 0x1b61, 0xa085,
- 0x0001, 0x007c, 0x0e7e, 0x2071, 0x5100, 0x2d08, 0x7058, 0x6802,
- 0xa005, 0x00c0, 0x1b6c, 0x715e, 0x715a, 0x0e7f, 0x007c, 0x2c08,
- 0x7858, 0x6002, 0xa005, 0x00c0, 0x1b76, 0x795e, 0x795a, 0x007c,
- 0x2091, 0x8000, 0x6003, 0x0000, 0x2c08, 0x785c, 0xa065, 0x00c0,
- 0x1b84, 0x795a, 0x0078, 0x1b85, 0x6102, 0x795e, 0x2091, 0x8001,
- 0x1078, 0x21ef, 0x007c, 0x0e7e, 0x2071, 0x5100, 0x7058, 0xa06d,
- 0x0040, 0x1b99, 0x6800, 0x705a, 0xa005, 0x00c0, 0x1b98, 0x705e,
- 0x8dff, 0x0e7f, 0x007c, 0x0d7e, 0x0c7e, 0x0f7e, 0x2079, 0x5100,
- 0xaf80, 0x0016, 0x2060, 0x6000, 0xa005, 0x0040, 0x1bc9, 0x2068,
- 0x6814, 0xa306, 0x00c0, 0x1bb2, 0x6828, 0xa084, 0x00ff, 0xa406,
- 0x0040, 0x1bb5, 0x2d60, 0x0078, 0x1ba3, 0x6800, 0xa005, 0x6002,
- 0x00c0, 0x1bc1, 0xaf80, 0x0016, 0xac06, 0x0040, 0x1bc0, 0x2c00,
- 0x785e, 0x0d7e, 0x689c, 0xa005, 0x0040, 0x1bc8, 0x1078, 0x19b3,
- 0x007f, 0x0f7f, 0x0c7f, 0x0d7f, 0xa005, 0x007c, 0x0d7e, 0x0c7e,
- 0x0f7e, 0x2079, 0x5100, 0xaf80, 0x0016, 0x2060, 0x6000, 0xa005,
- 0x0040, 0x1bf8, 0x2068, 0x6814, 0xa084, 0x00ff, 0xa306, 0x0040,
- 0x1be4, 0x2d60, 0x0078, 0x1bd6, 0x6800, 0xa005, 0x6002, 0x00c0,
- 0x1bf0, 0xaf80, 0x0016, 0xac06, 0x0040, 0x1bef, 0x2c00, 0x785e,
- 0x0d7e, 0x689c, 0xa005, 0x0040, 0x1bf7, 0x1078, 0x19b3, 0x007f,
- 0x0f7f, 0x0c7f, 0x0d7f, 0xa005, 0x007c, 0x0d7e, 0x0c7e, 0x0f7e,
- 0x2079, 0x5100, 0xaf80, 0x0016, 0x2060, 0x6000, 0xa06d, 0x0040,
- 0x1c24, 0x6814, 0xa306, 0x0040, 0x1c10, 0x2d60, 0x0078, 0x1c05,
- 0x6800, 0xa005, 0x6002, 0x00c0, 0x1c1c, 0xaf80, 0x0016, 0xac06,
- 0x0040, 0x1c1b, 0x2c00, 0x785e, 0x0d7e, 0x689c, 0xa005, 0x0040,
- 0x1c23, 0x1078, 0x19b3, 0x007f, 0x0f7f, 0x0c7f, 0x0d7f, 0xa005,
- 0x007c, 0x2091, 0x8000, 0x2069, 0x5140, 0x6800, 0xa086, 0x0000,
- 0x0040, 0x1c37, 0x2091, 0x8001, 0x78e3, 0x0009, 0x007c, 0x6880,
- 0xa0bc, 0xff00, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0010,
- 0x1078, 0x1980, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1c40, 0x2091,
- 0x8001, 0x2001, 0x800a, 0x0078, 0x1c57, 0x2001, 0x800c, 0x0078,
- 0x1c57, 0x1078, 0x1a2b, 0x2001, 0x800d, 0x0078, 0x1c57, 0x70c2,
- 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x4080, 0x007c, 0x6004,
- 0x2c08, 0x2063, 0x0000, 0x7884, 0x8000, 0x7886, 0x7888, 0xa005,
- 0x798a, 0x0040, 0x1c6e, 0x2c02, 0x0078, 0x1c6f, 0x798e, 0x007c,
- 0x6807, 0x0103, 0x0c7e, 0x2061, 0x5100, 0x2d08, 0x206b, 0x0000,
- 0x6084, 0x8000, 0x6086, 0x6088, 0xa005, 0x618a, 0x0040, 0x1c83,
- 0x2d02, 0x0078, 0x1c84, 0x618e, 0x0c7f, 0x007c, 0x1078, 0x1c97,
- 0x0040, 0x1c96, 0x0c7e, 0x609c, 0xa065, 0x0040, 0x1c91, 0x1078,
- 0x19b3, 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1948, 0x007c, 0x788c,
- 0xa065, 0x0040, 0x1ca9, 0x2091, 0x8000, 0x7884, 0x8001, 0x7886,
- 0x2c04, 0x788e, 0xa005, 0x00c0, 0x1ca7, 0x788a, 0x8000, 0x2091,
- 0x8001, 0x007c, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e,
- 0x00c8, 0x1cb3, 0xa200, 0x0070, 0x1cb7, 0x0078, 0x1cae, 0x8086,
- 0x818e, 0x007c, 0x157e, 0x20a9, 0x0010, 0xa005, 0x0040, 0x1cdd,
- 0xa11a, 0x00c8, 0x1cdd, 0x8213, 0x818d, 0x0048, 0x1cce, 0xa11a,
- 0x00c8, 0x1ccf, 0x0070, 0x1cd5, 0x0078, 0x1cc3, 0xa11a, 0x2308,
- 0x8210, 0x0070, 0x1cd5, 0x0078, 0x1cc3, 0x007e, 0x3200, 0xa084,
- 0xf7ff, 0x2080, 0x007f, 0x157f, 0x007c, 0x007e, 0x3200, 0xa085,
- 0x0800, 0x0078, 0x1cd9, 0x7994, 0x70d0, 0xa106, 0x0040, 0x1d51,
- 0x2091, 0x8000, 0x2071, 0x0020, 0x7004, 0xa005, 0x00c0, 0x1d51,
- 0x7008, 0x7208, 0xa206, 0x00c0, 0x1d51, 0xa286, 0x0008, 0x00c0,
- 0x1d51, 0x2071, 0x0010, 0x1078, 0x192e, 0x0040, 0x1d51, 0x7a9c,
- 0x7b98, 0x7ca4, 0x7da0, 0xa184, 0xff00, 0x0040, 0x1d1f, 0x2031,
- 0x0000, 0x810b, 0x86b5, 0x810b, 0x86b5, 0x810b, 0x86b5, 0x810b,
- 0x86b5, 0x810b, 0x86b5, 0x810b, 0x86b5, 0x2100, 0xa210, 0x2600,
- 0xa319, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x0078, 0x1d29, 0x8107,
- 0x8004, 0x8004, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9,
- 0x0000, 0x2009, 0x0020, 0x1078, 0x1929, 0x2091, 0x8001, 0x0040,
- 0x1d48, 0x1078, 0x1948, 0x78a8, 0x8000, 0x78aa, 0xa086, 0x0002,
- 0x00c0, 0x1d51, 0x2091, 0x8000, 0x78e3, 0x0002, 0x78ab, 0x0000,
- 0x78cc, 0xa085, 0x0003, 0x78ce, 0x2091, 0x8001, 0x0078, 0x1d51,
- 0x78ab, 0x0000, 0x1078, 0x20ac, 0x6004, 0xa084, 0x000f, 0x0079,
- 0x1d56, 0x2071, 0x0010, 0x2091, 0x8001, 0x007c, 0x1d66, 0x1d88,
- 0x1dae, 0x1d66, 0x1dcb, 0x1d75, 0x1f2c, 0x1f47, 0x1d66, 0x1d82,
- 0x1da8, 0x1e13, 0x1e82, 0x1ed2, 0x1ee4, 0x1f43, 0x2039, 0x0400,
- 0x78dc, 0xa705, 0x78de, 0x6008, 0xa705, 0x600a, 0x1078, 0x1fc7,
- 0x609c, 0x78da, 0x1078, 0x2094, 0x007c, 0x78dc, 0xa084, 0x0100,
- 0x0040, 0x1d7c, 0x0078, 0x1d66, 0x601c, 0xa085, 0x0080, 0x601e,
- 0x0078, 0x1d8f, 0x1078, 0x1b53, 0x00c0, 0x1d66, 0x1078, 0x20c6,
- 0x78dc, 0xa084, 0x0100, 0x0040, 0x1d8f, 0x0078, 0x1d66, 0x78df,
- 0x0000, 0x6004, 0x8007, 0xa084, 0x00ff, 0x78d2, 0x8001, 0x609f,
- 0x0000, 0x0040, 0x1da5, 0x1078, 0x1fc7, 0x0040, 0x1da5, 0x78dc,
- 0xa085, 0x0100, 0x78de, 0x0078, 0x1da7, 0x1078, 0x1feb, 0x007c,
- 0x1078, 0x1b53, 0x00c0, 0x1d66, 0x1078, 0x20c2, 0x78dc, 0xa08c,
- 0x0e00, 0x00c0, 0x1db7, 0xa084, 0x0100, 0x00c0, 0x1db9, 0x0078,
- 0x1d66, 0x1078, 0x1fc7, 0x00c0, 0x1dca, 0x6104, 0xa18c, 0x00ff,
- 0xa186, 0x0007, 0x0040, 0x1f84, 0xa186, 0x000f, 0x0040, 0x1f84,
- 0x1078, 0x1feb, 0x007c, 0x78dc, 0xa084, 0x0100, 0x0040, 0x1dd2,
- 0x0078, 0x1d66, 0x78df, 0x0000, 0x6714, 0x2011, 0x0001, 0x20a9,
- 0x0001, 0x6018, 0xa084, 0x00ff, 0xa005, 0x0040, 0x1df5, 0x2011,
- 0x0001, 0xa7bc, 0xff00, 0x20a9, 0x0020, 0xa08e, 0x0001, 0x0040,
- 0x1df5, 0x2039, 0x0000, 0x2011, 0x0002, 0x20a9, 0x0100, 0xa08e,
- 0x0002, 0x0040, 0x1df5, 0x0078, 0x1e10, 0x1078, 0x1973, 0x2091,
- 0x8000, 0x682b, 0x0000, 0x682f, 0x0000, 0x6808, 0xa084, 0xffde,
- 0x680a, 0xade8, 0x0010, 0x2091, 0x8001, 0x0070, 0x1e09, 0x0078,
- 0x1df7, 0x8211, 0x0040, 0x1e10, 0x20a9, 0x0100, 0x0078, 0x1df7,
- 0x1078, 0x1948, 0x007c, 0x2001, 0x5167, 0x2004, 0xa084, 0x8000,
- 0x0040, 0x1fac, 0x6114, 0x1078, 0x20e3, 0x6900, 0xa184, 0x0001,
- 0x0040, 0x1e34, 0x6028, 0xa084, 0x00ff, 0x00c0, 0x1fa4, 0x6800,
- 0xa084, 0x0001, 0x0040, 0x1fac, 0x6803, 0x0000, 0x680b, 0x0000,
- 0x6807, 0x0000, 0x0078, 0x1fb4, 0x2011, 0x0001, 0x6020, 0xd0f4,
- 0x0040, 0x1e3c, 0xa295, 0x0002, 0xd0c4, 0x0040, 0x1e41, 0xa295,
- 0x0008, 0xd0cc, 0x0040, 0x1e46, 0xa295, 0x0400, 0x601c, 0xa084,
- 0x0002, 0x0040, 0x1e4d, 0xa295, 0x0004, 0x602c, 0xa08c, 0x00ff,
- 0xa182, 0x0002, 0x0048, 0x1fb0, 0xa182, 0x001b, 0x00c8, 0x1fb0,
- 0x0040, 0x1fb0, 0x690e, 0x602c, 0x8007, 0xa08c, 0x00ff, 0xa182,
- 0x0002, 0x0048, 0x1fb0, 0xa182, 0x001b, 0x00c8, 0x1fb0, 0x0040,
- 0x1fb0, 0x6912, 0x6030, 0xa005, 0x00c0, 0x1e70, 0x2001, 0x001e,
- 0x8000, 0x6816, 0x6028, 0xa084, 0x00ff, 0x0040, 0x1fac, 0x6806,
- 0x6028, 0x8007, 0xa084, 0x00ff, 0x0040, 0x1fac, 0x680a, 0x6a02,
- 0x0078, 0x1fb4, 0x2001, 0x5167, 0x2004, 0xa084, 0x8000, 0x0040,
- 0x1fac, 0x6114, 0x1078, 0x20e3, 0x2091, 0x8000, 0x6a04, 0x6b08,
- 0x6418, 0xa484, 0x0003, 0x0040, 0x1ea8, 0x6128, 0xa18c, 0x00ff,
- 0x8001, 0x00c0, 0x1ea1, 0x2100, 0xa210, 0x0048, 0x1ece, 0x0078,
- 0x1ea8, 0x8001, 0x00c0, 0x1ece, 0x2100, 0xa212, 0x0048, 0x1ece,
- 0xa484, 0x000c, 0x0040, 0x1ec2, 0x6128, 0x810f, 0xa18c, 0x00ff,
- 0xa082, 0x0004, 0x00c0, 0x1eba, 0x2100, 0xa318, 0x0048, 0x1ece,
- 0x0078, 0x1ec2, 0xa082, 0x0004, 0x00c0, 0x1ece, 0x2100, 0xa31a,
- 0x0048, 0x1ece, 0x6030, 0xa005, 0x0040, 0x1ec8, 0x8000, 0x6816,
- 0x6a06, 0x6b0a, 0x2091, 0x8001, 0x0078, 0x1fb4, 0x2091, 0x8001,
- 0x0078, 0x1fb0, 0x6114, 0x1078, 0x20e3, 0x2091, 0x8000, 0x6b08,
- 0x8318, 0x0048, 0x1ee0, 0x6b0a, 0x2091, 0x8001, 0x0078, 0x1fc3,
- 0x2091, 0x8001, 0x0078, 0x1fb0, 0x6024, 0x8007, 0xa084, 0x00ff,
- 0x0040, 0x1f02, 0xa086, 0x0080, 0x00c0, 0x1f2a, 0x20a9, 0x0008,
- 0x2069, 0x7510, 0x2091, 0x8000, 0x6800, 0xa084, 0xfcff, 0x6802,
- 0xade8, 0x0008, 0x0070, 0x1efe, 0x0078, 0x1ef4, 0x2091, 0x8001,
- 0x0078, 0x1fb4, 0x6028, 0xa015, 0x0040, 0x1f2a, 0x6114, 0x1078,
- 0x20e3, 0x0d7e, 0xade8, 0x0007, 0x2091, 0x8000, 0x6800, 0xa00d,
- 0x0040, 0x1f27, 0xa206, 0x0040, 0x1f18, 0x2168, 0x0078, 0x1f0e,
- 0x0c7e, 0x2160, 0x6000, 0x6802, 0x1078, 0x1948, 0x0c7f, 0x0d7f,
- 0x6808, 0x8000, 0x680a, 0x2091, 0x8001, 0x0078, 0x1fc3, 0x2091,
- 0x8001, 0x0d7f, 0x0078, 0x1fac, 0x6114, 0x1078, 0x20e3, 0x6800,
- 0xa084, 0x0001, 0x0040, 0x1f9c, 0x2091, 0x8000, 0x6a04, 0x8210,
- 0x0048, 0x1f3f, 0x6a06, 0x2091, 0x8001, 0x0078, 0x1fc3, 0x2091,
- 0x8001, 0x0078, 0x1fb0, 0x1078, 0x1b53, 0x00c0, 0x1d66, 0x6114,
- 0x1078, 0x20e3, 0x60be, 0x60bb, 0x0000, 0x6900, 0xa184, 0x0008,
- 0x0040, 0x1f56, 0x6020, 0xa085, 0x0100, 0x6022, 0xa184, 0x0001,
- 0x0040, 0x1fac, 0xa184, 0x0100, 0x00c0, 0x1f98, 0xa184, 0x0200,
- 0x00c0, 0x1f94, 0x681c, 0xa005, 0x00c0, 0x1fa0, 0x6004, 0xa084,
- 0x00ff, 0xa086, 0x000f, 0x00c0, 0x1f6f, 0x1078, 0x20c6, 0x78df,
- 0x0000, 0x6004, 0x8007, 0xa084, 0x00ff, 0x78d2, 0x8001, 0x609f,
- 0x0000, 0x0040, 0x1f84, 0x1078, 0x1fc7, 0x0040, 0x1f84, 0x78dc,
- 0xa085, 0x0100, 0x78de, 0x007c, 0x78d7, 0x0000, 0x78db, 0x0000,
- 0x6024, 0xa084, 0xff00, 0x6026, 0x1078, 0x39de, 0x0040, 0x1ce3,
- 0x1078, 0x1b78, 0x0078, 0x1ce3, 0x2009, 0x0017, 0x0078, 0x1fb6,
- 0x2009, 0x000e, 0x0078, 0x1fb6, 0x2009, 0x0007, 0x0078, 0x1fb6,
- 0x2009, 0x0035, 0x0078, 0x1fb6, 0x2009, 0x003e, 0x0078, 0x1fb6,
- 0x2009, 0x0004, 0x0078, 0x1fb6, 0x2009, 0x0006, 0x0078, 0x1fb6,
- 0x2009, 0x0016, 0x0078, 0x1fb6, 0x2009, 0x0001, 0x6024, 0xa084,
- 0xff00, 0xa105, 0x6026, 0x2091, 0x8000, 0x1078, 0x1c5f, 0x2091,
- 0x8001, 0x0078, 0x1ce3, 0x1078, 0x1948, 0x0078, 0x1ce3, 0x78d4,
- 0xa06d, 0x00c0, 0x1fd2, 0x2c00, 0x78d6, 0x78da, 0x609f, 0x0000,
- 0x0078, 0x1fde, 0x2c00, 0x689e, 0x609f, 0x0000, 0x78d6, 0x2d00,
- 0x6002, 0x78d8, 0xad06, 0x00c0, 0x1fde, 0x6002, 0x78d0, 0x8001,
- 0x78d2, 0x00c0, 0x1fea, 0x78dc, 0xa084, 0xfeff, 0x78de, 0x78d8,
- 0x2060, 0xa006, 0x007c, 0xa02e, 0x2530, 0x611c, 0x61a2, 0xa184,
- 0xe1ff, 0x601e, 0xa184, 0x0060, 0x0040, 0x1ffa, 0x0e7e, 0x1078,
- 0x47c2, 0x0e7f, 0x6596, 0x65a6, 0x669a, 0x66aa, 0x60af, 0x0000,
- 0x60b3, 0x0000, 0x6714, 0x1078, 0x1973, 0x2091, 0x8000, 0x60a0,
- 0xa084, 0x8000, 0x00c0, 0x2021, 0x6808, 0xa084, 0x0001, 0x0040,
- 0x2021, 0x2091, 0x8001, 0x1078, 0x19c0, 0x2091, 0x8000, 0x1078,
- 0x1c5f, 0x2091, 0x8001, 0x78d7, 0x0000, 0x78db, 0x0000, 0x0078,
- 0x2093, 0x6024, 0xa096, 0x0001, 0x00c0, 0x2028, 0x8000, 0x6026,
- 0x6a10, 0x6814, 0x2091, 0x8001, 0xa202, 0x0048, 0x2037, 0x0040,
- 0x2037, 0x2039, 0x0200, 0x1078, 0x2094, 0x0078, 0x2093, 0x2c08,
- 0x2091, 0x8000, 0x60a0, 0xa084, 0x8000, 0x0040, 0x2064, 0x6800,
- 0xa065, 0x0040, 0x2069, 0x6a04, 0x0e7e, 0x2071, 0x5140, 0x7000,
- 0xa084, 0x0001, 0x0040, 0x205e, 0x7048, 0xa206, 0x00c0, 0x205e,
- 0x6b04, 0x231c, 0x2160, 0x6302, 0x2300, 0xa005, 0x00c0, 0x2059,
- 0x6902, 0x2260, 0x6102, 0x0e7f, 0x0078, 0x2070, 0x2160, 0x6202,
- 0x6906, 0x0e7f, 0x0078, 0x2070, 0x6800, 0xa065, 0x0040, 0x2069,
- 0x6102, 0x6902, 0x00c0, 0x206d, 0x6906, 0x2160, 0x6003, 0x0000,
- 0x2160, 0x60a0, 0xa084, 0x8000, 0x0040, 0x207a, 0x6808, 0xa084,
- 0xfffc, 0x680a, 0x6810, 0x8000, 0x6812, 0x2091, 0x8001, 0x6808,
- 0xa08c, 0x0040, 0x0040, 0x2089, 0xa086, 0x0040, 0x680a, 0x1078,
- 0x19d1, 0x2091, 0x8000, 0x1078, 0x21d2, 0x2091, 0x8001, 0x78db,
- 0x0000, 0x78d7, 0x0000, 0x007c, 0x6008, 0xa705, 0x600a, 0x2091,
- 0x8000, 0x1078, 0x1c5f, 0x2091, 0x8001, 0x78d8, 0xa065, 0x0040,
- 0x20a7, 0x609c, 0x78da, 0x609f, 0x0000, 0x0078, 0x2097, 0x78d7,
- 0x0000, 0x78db, 0x0000, 0x007c, 0x7990, 0x7894, 0x8000, 0xa10a,
- 0x00c8, 0x20b3, 0xa006, 0x7896, 0x70d2, 0x7804, 0xa005, 0x0040,
- 0x20c1, 0x8001, 0x7806, 0x00c0, 0x20c1, 0x0068, 0x20c1, 0x2091,
- 0x4080, 0x007c, 0x2039, 0x20da, 0x0078, 0x20c8, 0x2039, 0x20e0,
- 0x2704, 0xa005, 0x0040, 0x20d9, 0xac00, 0x2068, 0x6b08, 0x6c0c,
- 0x6910, 0x6a14, 0x690a, 0x6a0e, 0x6b12, 0x6c16, 0x8738, 0x0078,
- 0x20c8, 0x007c, 0x0003, 0x0009, 0x000f, 0x0015, 0x001b, 0x0000,
- 0x0015, 0x001b, 0x0000, 0x0c7e, 0x1078, 0x3b69, 0x2c68, 0x0c7f,
- 0x007c, 0x0010, 0x215a, 0x0068, 0x215a, 0x2029, 0x0000, 0x78cb,
- 0x0000, 0x788c, 0xa065, 0x0040, 0x2153, 0x2009, 0x5174, 0x2104,
- 0xa084, 0x0001, 0x0040, 0x2121, 0x6004, 0xa086, 0x0103, 0x00c0,
- 0x2121, 0x6018, 0xa005, 0x00c0, 0x2121, 0x6014, 0xa005, 0x00c0,
- 0x2121, 0x0d7e, 0x2069, 0x0000, 0x6818, 0xa084, 0x0001, 0x00c0,
- 0x2120, 0x600c, 0x70c6, 0x6010, 0x70ca, 0x70c3, 0x8020, 0x681b,
- 0x0001, 0x2091, 0x4080, 0x0d7f, 0x1078, 0x1c86, 0x0078, 0x2158,
- 0x0d7f, 0x1078, 0x215b, 0x0040, 0x2153, 0x6204, 0xa294, 0x00ff,
- 0xa296, 0x0003, 0x0040, 0x2133, 0x6204, 0xa296, 0x0110, 0x00c0,
- 0x2141, 0x78cb, 0x0001, 0x6204, 0xa294, 0xff00, 0x8217, 0x8211,
- 0x0040, 0x2141, 0x85ff, 0x00c0, 0x2153, 0x8210, 0xa202, 0x00c8,
- 0x2153, 0x057e, 0x1078, 0x216a, 0x057f, 0x0040, 0x214e, 0x78e0,
- 0xa086, 0x0003, 0x0040, 0x2153, 0x0078, 0x2141, 0x8528, 0x78c8,
- 0xa005, 0x0040, 0x20f1, 0x85ff, 0x0040, 0x215a, 0x2091, 0x4080,
- 0x78b0, 0x70d6, 0x007c, 0x7bac, 0x79b0, 0x70d4, 0xa102, 0x00c0,
- 0x2164, 0x2300, 0xa005, 0x007c, 0x0048, 0x2168, 0xa302, 0x007c,
- 0x8002, 0x007c, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x00c8,
- 0x2184, 0x2091, 0x8000, 0x2071, 0x0020, 0x7004, 0xa005, 0x00c0,
- 0x21b9, 0x7008, 0x7208, 0xa206, 0x00c0, 0x21b9, 0xa286, 0x0008,
- 0x00c0, 0x21b9, 0x2071, 0x0010, 0x1078, 0x21be, 0x2009, 0x0020,
- 0x6004, 0xa086, 0x0103, 0x00c0, 0x2193, 0x6028, 0xa005, 0x00c0,
- 0x2193, 0x2009, 0x000c, 0x1078, 0x1924, 0x0040, 0x21ac, 0x78c4,
- 0x8000, 0x78c6, 0xa086, 0x0002, 0x00c0, 0x21b9, 0x2091, 0x8000,
- 0x78e3, 0x0003, 0x78c7, 0x0000, 0x78cc, 0xa085, 0x0300, 0x78ce,
- 0x2091, 0x8001, 0x0078, 0x21b9, 0x78c7, 0x0000, 0x1078, 0x1c86,
- 0x79ac, 0x78b0, 0x8000, 0xa10a, 0x00c8, 0x21b7, 0xa006, 0x78b2,
- 0xa006, 0x2071, 0x0010, 0x2091, 0x8001, 0x007c, 0x8107, 0x8004,
- 0x8004, 0x7ab8, 0x7bb4, 0x7cc0, 0x7dbc, 0xa210, 0xa399, 0x0000,
- 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x007c, 0x2009, 0x515b, 0x2091,
- 0x8000, 0x200a, 0x0f7e, 0x0e7e, 0x2071, 0x5140, 0x7000, 0xa086,
- 0x0000, 0x00c0, 0x21ec, 0x2009, 0x5112, 0x2104, 0xa005, 0x00c0,
- 0x21ec, 0x2079, 0x0100, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x21ec,
- 0x0018, 0x21ec, 0x781b, 0x004b, 0x0e7f, 0x0f7f, 0x007c, 0x0f7e,
- 0x0e7e, 0x2071, 0x5140, 0x2091, 0x8000, 0x7000, 0xa086, 0x0000,
- 0x00c0, 0x2205, 0x2079, 0x0100, 0x7830, 0xa084, 0x00c0, 0x00c0,
- 0x2205, 0x0018, 0x2205, 0x781b, 0x004d, 0x2091, 0x8001, 0x0e7f,
- 0x0f7f, 0x007c, 0x127e, 0x2091, 0x2300, 0x2071, 0x5140, 0x2079,
- 0x0100, 0x784b, 0x000f, 0x0098, 0x2218, 0x7838, 0x0078, 0x2211,
- 0x20a9, 0x0040, 0x7800, 0xa082, 0x0004, 0x0048, 0x2221, 0x20a9,
- 0x0060, 0x789b, 0x0000, 0x78af, 0x0000, 0x78af, 0x0000, 0x0070,
- 0x222b, 0x0078, 0x2223, 0x7800, 0xa082, 0x0004, 0x0048, 0x223a,
- 0x70b7, 0x0096, 0x2019, 0x4ee7, 0x1078, 0x2276, 0x702f, 0x8001,
- 0x0078, 0x2246, 0x70b7, 0x0000, 0x2019, 0x4d5f, 0x1078, 0x2276,
- 0x2019, 0x4d9e, 0x1078, 0x2276, 0x702f, 0x8000, 0x7003, 0x0000,
- 0x1078, 0x237f, 0x7004, 0xa084, 0x000f, 0x017e, 0x2009, 0x04fd,
- 0x210c, 0xa18a, 0x0005, 0x0048, 0x225b, 0x0038, 0x2261, 0xa085,
- 0x6280, 0x0078, 0x2263, 0x0028, 0x2261, 0xa085, 0x6280, 0x0078,
- 0x2263, 0xa085, 0x62c0, 0x017f, 0x7806, 0x780f, 0xb204, 0x7843,
- 0x00d8, 0x7853, 0x0080, 0x780b, 0x0008, 0x7047, 0x0008, 0x7053,
- 0x517f, 0x704f, 0x0000, 0x127f, 0x2000, 0x007c, 0x137e, 0x147e,
- 0x157e, 0x047e, 0x20a1, 0x012b, 0x2304, 0xa005, 0x789a, 0x0040,
- 0x2296, 0x8318, 0x2324, 0x8318, 0x2398, 0x24a8, 0xa484, 0xff00,
- 0x0040, 0x228e, 0xa482, 0x0100, 0x20a9, 0x0100, 0x2020, 0x53a6,
- 0xa005, 0x00c0, 0x2285, 0x3318, 0x0078, 0x227c, 0x047f, 0x157f,
- 0x147f, 0x137f, 0x007c, 0xa18c, 0x000f, 0x2011, 0x0101, 0x2204,
- 0xa084, 0xfff0, 0xa105, 0x2012, 0x1078, 0x237f, 0x007c, 0x2011,
- 0x0101, 0x20a9, 0x0009, 0x810b, 0x0070, 0x22b0, 0x0078, 0x22ab,
- 0xa18c, 0x0e00, 0x2204, 0xa084, 0xf1ff, 0xa105, 0x2012, 0x007c,
- 0x2009, 0x0101, 0x20a9, 0x0005, 0x8213, 0x0070, 0x22c1, 0x0078,
- 0x22bc, 0xa294, 0x00e0, 0x2104, 0xa084, 0xff1f, 0xa205, 0x200a,
- 0x007c, 0x2011, 0x0101, 0x20a9, 0x000c, 0x810b, 0x0070, 0x22d2,
- 0x0078, 0x22cd, 0xa18c, 0xf000, 0x2204, 0xa084, 0x0fff, 0xa105,
- 0x2012, 0x007c, 0x2011, 0x0102, 0x2204, 0xa084, 0xffcf, 0xa105,
- 0x2012, 0x007c, 0x8103, 0x8003, 0xa080, 0x0020, 0x0c7e, 0x2061,
- 0x0100, 0x609a, 0x62ac, 0x63ac, 0x0c7f, 0x007c, 0x8103, 0x8003,
- 0xa080, 0x0022, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x60a4, 0xa084,
- 0xffdf, 0x60ae, 0x0c7f, 0x007c, 0x8103, 0x8003, 0xa080, 0x0022,
- 0x0c7e, 0x2061, 0x0100, 0x609a, 0x60a4, 0xa085, 0x0020, 0x60ae,
- 0x0c7f, 0x007c, 0x8103, 0x8003, 0xa080, 0x0020, 0x0c7e, 0x2061,
- 0x0100, 0x609a, 0x60a4, 0x62ae, 0x2010, 0x60a4, 0x63ae, 0x2018,
- 0x0c7f, 0x007c, 0x2091, 0x8000, 0x0c7e, 0x0e7e, 0x6818, 0xa005,
- 0x0040, 0x235d, 0x2061, 0x7500, 0x1078, 0x2365, 0x0040, 0x2349,
- 0x20a9, 0x0000, 0x2061, 0x7400, 0x0c7e, 0x1078, 0x2365, 0x0040,
- 0x2339, 0x0c7f, 0x8c60, 0x0070, 0x2337, 0x0078, 0x232c, 0x0078,
- 0x235d, 0x007f, 0xa082, 0x7400, 0x2071, 0x5140, 0x7086, 0x7182,
- 0x2001, 0x0004, 0x706e, 0x7093, 0x000f, 0x1078, 0x21cd, 0x0078,
- 0x2359, 0x60c0, 0xa005, 0x00c0, 0x235d, 0x2071, 0x5140, 0x7182,
- 0x2c00, 0x708a, 0x2001, 0x0006, 0x706e, 0x7093, 0x000f, 0x1078,
- 0x21cd, 0x2001, 0x0000, 0x0078, 0x235f, 0x2001, 0x0001, 0x2091,
- 0x8001, 0xa005, 0x0e7f, 0x0c7f, 0x007c, 0x2c04, 0xa005, 0x0040,
- 0x237c, 0x2060, 0x600c, 0xa306, 0x00c0, 0x2379, 0x6010, 0xa206,
- 0x00c0, 0x2379, 0x6014, 0xa106, 0x00c0, 0x2379, 0xa006, 0x0078,
- 0x237e, 0x6000, 0x0078, 0x2366, 0xa085, 0x0001, 0x007c, 0x2011,
- 0x5141, 0x220c, 0xa18c, 0x000f, 0x2011, 0x013b, 0x2204, 0xa084,
- 0x0100, 0x0040, 0x2395, 0x2021, 0xff04, 0x2122, 0x810b, 0x810b,
- 0x810b, 0x810b, 0xa18d, 0x0f00, 0x2104, 0x007c, 0x0e7e, 0x68e4,
- 0xa08c, 0x0020, 0x0040, 0x23e9, 0xa084, 0x0006, 0x00c0, 0x23e9,
- 0x6014, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0f0,
- 0x5380, 0x7004, 0xa084, 0x000a, 0x00c0, 0x23e9, 0x7108, 0xa194,
- 0xff00, 0x0040, 0x23e9, 0xa18c, 0x00ff, 0x2001, 0x000c, 0xa106,
- 0x0040, 0x23d0, 0x2001, 0x0012, 0xa106, 0x0040, 0x23d4, 0x2001,
- 0x0014, 0xa106, 0x0040, 0x23d8, 0x2001, 0x0019, 0xa106, 0x0040,
- 0x23dc, 0x2001, 0x0032, 0xa106, 0x0040, 0x23e0, 0x0078, 0x23e4,
- 0x2009, 0x0012, 0x0078, 0x23e6, 0x2009, 0x0014, 0x0078, 0x23e6,
- 0x2009, 0x0019, 0x0078, 0x23e6, 0x2009, 0x0020, 0x0078, 0x23e6,
- 0x2009, 0x003f, 0x0078, 0x23e6, 0x2011, 0x0000, 0x2100, 0xa205,
- 0x700a, 0x0e7f, 0x007c, 0x0068, 0x23eb, 0x2091, 0x8000, 0x2071,
- 0x0000, 0x007e, 0x7018, 0xa084, 0x0001, 0x00c0, 0x23f2, 0x007f,
- 0x2071, 0x0010, 0x70ca, 0x007f, 0x70c6, 0x70c3, 0x8002, 0x70db,
- 0x0741, 0x70df, 0x0000, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091,
- 0x4080, 0x0078, 0x2409, 0x107e, 0x007e, 0x127e, 0x2091, 0x2300,
- 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x77c2, 0x74c6, 0x76ca, 0x75ce,
- 0xa594, 0x003f, 0xa49c, 0x0003, 0xa484, 0x000f, 0x0079, 0x2420,
- 0x2432, 0x2432, 0x2432, 0x276c, 0x393b, 0x2430, 0x2461, 0x246b,
- 0x2430, 0x2430, 0x2430, 0x2430, 0x2430, 0x2430, 0x2430, 0x2430,
- 0x1078, 0x23eb, 0x8507, 0xa084, 0x001f, 0x0079, 0x2437, 0x2475,
- 0x276c, 0x2926, 0x2a23, 0x2a4b, 0x2ced, 0x2f98, 0x2fdb, 0x3026,
- 0x30ab, 0x3163, 0x320c, 0x2461, 0x2848, 0x2f6d, 0x2457, 0x3cc8,
- 0x3ce8, 0x3eae, 0x3eba, 0x3f8f, 0x2457, 0x2457, 0x4062, 0x4066,
- 0x3cc6, 0x2457, 0x3e19, 0x2457, 0x3b8c, 0x246b, 0x2457, 0x1078,
- 0x23eb, 0x0018, 0x2410, 0x127f, 0x2091, 0x8001, 0x007f, 0x107f,
- 0x007c, 0x2019, 0x4e3b, 0x1078, 0x2276, 0x702f, 0x0001, 0x781b,
- 0x004f, 0x0078, 0x2459, 0x2019, 0x4d9e, 0x1078, 0x2276, 0x702f,
- 0x8000, 0x781b, 0x00d0, 0x0078, 0x2459, 0x7242, 0x2009, 0x510f,
- 0x200b, 0x0000, 0xa584, 0x0001, 0x00c0, 0x3ba0, 0x0040, 0x2492,
- 0x1078, 0x23eb, 0x7003, 0x0000, 0x704b, 0x0000, 0x7043, 0x0000,
- 0x7037, 0x0000, 0x1078, 0x3912, 0x0018, 0x2410, 0x2009, 0x510f,
- 0x200b, 0x0000, 0x7068, 0xa005, 0x00c0, 0x255d, 0x706c, 0xa084,
- 0x0007, 0x0079, 0x249b, 0x2594, 0x24a3, 0x24af, 0x24cc, 0x24ee,
- 0x253b, 0x2514, 0x24a3, 0x1078, 0x38fa, 0x2009, 0x0048, 0x1078,
- 0x2e39, 0x00c0, 0x24ad, 0x7003, 0x0004, 0x0078, 0x2459, 0x1078,
- 0x38fa, 0x00c0, 0x24ca, 0x7080, 0x8007, 0x7882, 0x789b, 0x0010,
- 0x78ab, 0x000c, 0x789b, 0x0060, 0x78ab, 0x0001, 0x785b, 0x0004,
- 0x2009, 0x00e0, 0x1078, 0x2e2d, 0x00c0, 0x24ca, 0x7003, 0x0004,
- 0x7093, 0x000f, 0x0078, 0x2459, 0x1078, 0x38fa, 0x00c0, 0x24ec,
- 0x7180, 0x8107, 0x7882, 0x789b, 0x0010, 0xa18c, 0x001f, 0xa18d,
- 0x00c0, 0x79aa, 0x78ab, 0x0006, 0x789b, 0x0060, 0x78ab, 0x0002,
- 0x785b, 0x0004, 0x2009, 0x00e0, 0x1078, 0x2e2d, 0x00c0, 0x24ec,
- 0x7003, 0x0004, 0x7093, 0x000f, 0x0078, 0x2459, 0x1078, 0x38fa,
- 0x00c0, 0x2512, 0x7180, 0x8107, 0x7882, 0x789b, 0x0010, 0xa18c,
- 0x001f, 0xa18d, 0x00c0, 0x79aa, 0x78ab, 0x0020, 0x7184, 0x79aa,
- 0x78ab, 0x000d, 0x789b, 0x0060, 0x78ab, 0x0004, 0x785b, 0x0004,
- 0x2009, 0x00e0, 0x1078, 0x2e2d, 0x00c0, 0x2512, 0x7003, 0x0004,
- 0x7093, 0x000f, 0x0078, 0x2459, 0x1078, 0x38fa, 0x00c0, 0x2539,
- 0x7180, 0x8107, 0x7882, 0x789b, 0x0010, 0xa18c, 0x001f, 0xa18d,
- 0x00c0, 0x79aa, 0x78ab, 0x0006, 0x789b, 0x0060, 0x78ab, 0x0002,
- 0x785b, 0x0004, 0x2009, 0x00e0, 0x1078, 0x2e2d, 0x00c0, 0x2539,
- 0x7088, 0x708b, 0x0000, 0x2068, 0x704a, 0x7003, 0x0002, 0x7093,
- 0x000f, 0x0078, 0x2459, 0x1078, 0x38fa, 0x00c0, 0x2459, 0x7088,
- 0x2068, 0x6f14, 0x1078, 0x37ef, 0x2c50, 0x1078, 0x39ac, 0x789b,
- 0x0010, 0x6814, 0xa084, 0x001f, 0xa085, 0x0080, 0x78aa, 0x6e1c,
- 0x2041, 0x0001, 0x708c, 0xa084, 0x0400, 0x2001, 0x0004, 0x0040,
- 0x255b, 0x2001, 0x0006, 0x0078, 0x267c, 0x1078, 0x38fa, 0x00c0,
- 0x2459, 0x789b, 0x0010, 0x7068, 0x2068, 0x6f14, 0x1078, 0x37ef,
- 0x2c50, 0x1078, 0x39ac, 0x6008, 0xa085, 0x0010, 0x600a, 0x6824,
- 0xa005, 0x0040, 0x257b, 0xa082, 0x0006, 0x0048, 0x2579, 0x0078,
- 0x257b, 0x6827, 0x0005, 0x6b14, 0xa39c, 0x001f, 0xa39d, 0x00c0,
- 0x7058, 0xa084, 0x8000, 0x0040, 0x2589, 0xa684, 0x0001, 0x0040,
- 0x258b, 0xa39c, 0xffbf, 0x7baa, 0x2031, 0x0020, 0x2041, 0x0001,
- 0x2001, 0x0003, 0x0078, 0x267c, 0x0018, 0x2410, 0x744c, 0xa485,
- 0x0000, 0x0040, 0x25ae, 0xa080, 0x5180, 0x2030, 0x7150, 0x8108,
- 0xa12a, 0x0048, 0x25a5, 0x2009, 0x5180, 0x2164, 0x6504, 0x85ff,
- 0x00c0, 0x25bf, 0x8421, 0x00c0, 0x259f, 0x7152, 0x7003, 0x0000,
- 0x704b, 0x0000, 0x7040, 0xa005, 0x0040, 0x3ba0, 0x0078, 0x2459,
- 0x764c, 0xa6b0, 0x5180, 0x7150, 0x2600, 0x0078, 0x25aa, 0x7152,
- 0x2568, 0x2558, 0x754a, 0x2c50, 0x6034, 0xa085, 0x0000, 0x00c0,
- 0x25bc, 0x6708, 0x773a, 0xa784, 0x033f, 0x0040, 0x25f5, 0xa784,
- 0x0021, 0x00c0, 0x25bc, 0xa784, 0x0002, 0x0040, 0x25de, 0xa784,
- 0x0004, 0x0040, 0x25bc, 0xa7bc, 0xfffb, 0x670a, 0xa784, 0x0008,
- 0x00c0, 0x25bc, 0xa784, 0x0010, 0x00c0, 0x25bc, 0xa784, 0x0200,
- 0x00c0, 0x25bc, 0xa784, 0x0100, 0x0040, 0x25f5, 0x6018, 0xa005,
- 0x00c0, 0x25bc, 0xa7bc, 0xfeff, 0x670a, 0x6823, 0x0000, 0x6e1c,
- 0xa684, 0x000e, 0x6118, 0x0040, 0x2605, 0x601c, 0xa102, 0x0048,
- 0x2608, 0x0040, 0x2608, 0x0078, 0x25b8, 0x81ff, 0x00c0, 0x25b8,
- 0x68c3, 0x0000, 0xa784, 0x0080, 0x00c0, 0x2610, 0x700c, 0x6022,
- 0xa7bc, 0xff7f, 0x670a, 0x1078, 0x39ac, 0x0018, 0x2410, 0x789b,
- 0x0010, 0xa046, 0x1078, 0x38fa, 0x00c0, 0x2459, 0x6b14, 0xa39c,
- 0x001f, 0xa39d, 0x00c0, 0x7058, 0xa084, 0x8000, 0x0040, 0x262c,
- 0xa684, 0x0001, 0x0040, 0x262e, 0xa39c, 0xffbf, 0xa684, 0x0010,
- 0x0040, 0x2634, 0xa39d, 0x0020, 0x7baa, 0x8840, 0xa684, 0x000e,
- 0x00c0, 0x263f, 0xa7bd, 0x0010, 0x670a, 0x0078, 0x267a, 0x7158,
- 0xa18c, 0x0800, 0x0040, 0x3401, 0x2011, 0x0020, 0xa684, 0x0008,
- 0x00c0, 0x2650, 0x8210, 0xa684, 0x0002, 0x00c0, 0x2650, 0x8210,
- 0x7aaa, 0x8840, 0x1078, 0x3912, 0x6a14, 0x610c, 0x8108, 0xa18c,
- 0x00ff, 0xa1e0, 0x7400, 0x2c64, 0x8cff, 0x0040, 0x2671, 0x6014,
- 0xa206, 0x00c0, 0x265b, 0x60b8, 0x8001, 0x60ba, 0x00c0, 0x2656,
- 0x0c7e, 0x2a60, 0x6008, 0xa085, 0x0100, 0x600a, 0x0c7f, 0x0078,
- 0x2594, 0x1078, 0x38fa, 0x00c0, 0x2459, 0x2a60, 0x610e, 0x79aa,
- 0x8840, 0x7132, 0x2001, 0x0001, 0x007e, 0x715c, 0xa184, 0x0018,
- 0x0040, 0x2697, 0xa184, 0x0010, 0x0040, 0x268a, 0x1078, 0x3604,
- 0x00c0, 0x26ba, 0xa184, 0x0008, 0x0040, 0x2697, 0x69a0, 0xa184,
- 0x0600, 0x00c0, 0x2697, 0x1078, 0x34f1, 0x0078, 0x26ba, 0x69a0,
- 0xa184, 0x0800, 0x0040, 0x26ae, 0x0c7e, 0x027e, 0x2960, 0x6000,
- 0xa085, 0x2000, 0x6002, 0x6104, 0xa18d, 0x0010, 0x6106, 0x027f,
- 0x0c7f, 0x1078, 0x3604, 0x00c0, 0x26ba, 0x69a0, 0xa184, 0x0200,
- 0x0040, 0x26b6, 0x1078, 0x3540, 0x0078, 0x26ba, 0xa184, 0x0400,
- 0x00c0, 0x2693, 0x69a0, 0xa184, 0x1000, 0x0040, 0x26c5, 0x6914,
- 0xa18c, 0xff00, 0x810f, 0x1078, 0x22ee, 0x007f, 0x7002, 0xa68c,
- 0x00e0, 0xa684, 0x0060, 0x0040, 0x26d3, 0xa086, 0x0060, 0x00c0,
- 0x26d3, 0xa18d, 0x4000, 0x88ff, 0x0040, 0x26d8, 0xa18d, 0x0004,
- 0x795a, 0x69b6, 0x789b, 0x0060, 0x2800, 0x78aa, 0x789b, 0x0061,
- 0x6818, 0xa08d, 0x8000, 0xa084, 0x7fff, 0x691a, 0xa68c, 0x0080,
- 0x0040, 0x26f7, 0x7097, 0x0000, 0xa08a, 0x000d, 0x0050, 0x26f5,
- 0xa08a, 0x000c, 0x7196, 0x2001, 0x000c, 0x800c, 0x719a, 0x78aa,
- 0x8008, 0x810c, 0x0040, 0x3407, 0xa18c, 0x00f8, 0x00c0, 0x3407,
- 0x157e, 0x137e, 0x147e, 0x20a1, 0x012b, 0x789b, 0x0000, 0x8000,
- 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f,
- 0x6814, 0x8007, 0x7882, 0x6d94, 0x7dd6, 0x7dde, 0x6e98, 0x7ed2,
- 0x7eda, 0x1078, 0x38fa, 0x00c0, 0x272e, 0x702c, 0x8003, 0x0048,
- 0x2727, 0x2019, 0x4d9e, 0x1078, 0x2276, 0x702f, 0x8000, 0x7830,
- 0xa084, 0x00c0, 0x00c0, 0x272e, 0x0098, 0x2736, 0x6008, 0xa084,
- 0xffef, 0x600a, 0x1078, 0x3912, 0x0078, 0x2482, 0x7200, 0xa284,
- 0x0007, 0xa086, 0x0001, 0x00c0, 0x2743, 0x781b, 0x004f, 0x1078,
- 0x3912, 0x0078, 0x2754, 0x6ab4, 0xa295, 0x2000, 0x7a5a, 0x781b,
- 0x004f, 0x1078, 0x3912, 0x7200, 0x2500, 0xa605, 0x0040, 0x2754,
- 0xa284, 0x0007, 0x1079, 0x2762, 0xad80, 0x0009, 0x7036, 0xa284,
- 0x0007, 0xa086, 0x0001, 0x00c0, 0x2459, 0x6018, 0x8000, 0x601a,
- 0x0078, 0x2459, 0x276a, 0x4a3a, 0x4a3a, 0x4a29, 0x4a3a, 0x276a,
- 0x4a29, 0x276a, 0x1078, 0x23eb, 0x1078, 0x38fa, 0x0f7e, 0x2079,
- 0x5100, 0x78cc, 0x0f7f, 0xa084, 0x0001, 0x0040, 0x2790, 0x706c,
- 0xa086, 0x0001, 0x00c0, 0x277f, 0x706e, 0x0078, 0x2823, 0x706c,
- 0xa086, 0x0005, 0x00c0, 0x278e, 0x7088, 0x2068, 0x681b, 0x0004,
- 0x6817, 0x0000, 0x6820, 0xa085, 0x0008, 0x6822, 0x706f, 0x0000,
- 0x2011, 0x0004, 0x716c, 0xa186, 0x0001, 0x0040, 0x27b1, 0xa186,
- 0x0007, 0x00c0, 0x27a1, 0x2009, 0x5138, 0x200b, 0x0005, 0x0078,
- 0x27b1, 0x2009, 0x5113, 0x2104, 0x2009, 0x5112, 0x200a, 0x2009,
- 0x5138, 0x200b, 0x0001, 0x706f, 0x0000, 0x7073, 0x0001, 0x0078,
- 0x27b3, 0x706f, 0x0000, 0x1078, 0x4776, 0x157e, 0x20a9, 0x0010,
- 0x2039, 0x0000, 0x1078, 0x36e2, 0xa7b8, 0x0100, 0x0070, 0x27c2,
- 0x0078, 0x27ba, 0x157f, 0x7000, 0x0079, 0x27c6, 0x27f4, 0x27db,
- 0x27db, 0x27ce, 0x27f4, 0x27f4, 0x27f4, 0x27f4, 0x2021, 0x515a,
- 0x2404, 0xa005, 0x0040, 0x27f4, 0xad06, 0x00c0, 0x27db, 0x6800,
- 0x2022, 0x0078, 0x27eb, 0x6820, 0xa084, 0x0001, 0x00c0, 0x27e7,
- 0x6f14, 0x1078, 0x37ef, 0x1078, 0x33d8, 0x0078, 0x27eb, 0x7060,
- 0x2060, 0x6800, 0x6002, 0x6a1a, 0x6817, 0x0000, 0x6820, 0xa085,
- 0x0008, 0x6822, 0x1078, 0x1c70, 0x2021, 0x7500, 0x1078, 0x2830,
- 0x2021, 0x515a, 0x1078, 0x2830, 0x157e, 0x20a9, 0x0000, 0x2021,
- 0x7400, 0x1078, 0x2830, 0x8420, 0x0070, 0x2808, 0x0078, 0x2801,
- 0x2061, 0x5400, 0x2021, 0x0002, 0x20a9, 0x0100, 0x6018, 0x6110,
- 0x81ff, 0x0040, 0x2817, 0xa102, 0x0050, 0x2817, 0x6012, 0x601b,
- 0x0000, 0xace0, 0x0010, 0x0070, 0x281f, 0x0078, 0x280e, 0x8421,
- 0x00c0, 0x280c, 0x157f, 0x709c, 0xa084, 0x8000, 0x0040, 0x282a,
- 0x1078, 0x3a00, 0x7003, 0x0000, 0x704b, 0x0000, 0x0078, 0x2459,
- 0x047e, 0x2404, 0xa005, 0x0040, 0x2844, 0x2068, 0x6800, 0x007e,
- 0x6a1a, 0x6817, 0x0000, 0x6820, 0xa085, 0x0008, 0x6822, 0x1078,
- 0x1c70, 0x007f, 0x0078, 0x2832, 0x047f, 0x2023, 0x0000, 0x007c,
- 0xa282, 0x0003, 0x0050, 0x284e, 0x1078, 0x23eb, 0x2300, 0x0079,
- 0x2851, 0x2854, 0x28c7, 0x28e4, 0xa282, 0x0002, 0x0040, 0x285a,
- 0x1078, 0x23eb, 0x706c, 0x706f, 0x0000, 0x7093, 0x0000, 0x0079,
- 0x2861, 0x2869, 0x2869, 0x286b, 0x289f, 0x340d, 0x2869, 0x289f,
- 0x2869, 0x1078, 0x23eb, 0x7780, 0x1078, 0x36e2, 0x7780, 0xa7bc,
- 0x0f00, 0x1078, 0x37ef, 0x6018, 0xa005, 0x0040, 0x2896, 0x2021,
- 0x7500, 0x2009, 0x0004, 0x2011, 0x0010, 0x1078, 0x28ff, 0x0040,
- 0x2896, 0x157e, 0x20a9, 0x0000, 0x2021, 0x7400, 0x047e, 0x2009,
- 0x0004, 0x2011, 0x0010, 0x1078, 0x28ff, 0x047f, 0x0040, 0x2895,
- 0x8420, 0x0070, 0x2895, 0x0078, 0x2886, 0x157f, 0x8738, 0xa784,
- 0x001f, 0x00c0, 0x2871, 0x0078, 0x2482, 0x0078, 0x2482, 0x7780,
- 0x1078, 0x37ef, 0x6018, 0xa005, 0x0040, 0x28c5, 0x2021, 0x7500,
- 0x2009, 0x0005, 0x2011, 0x0020, 0x1078, 0x28ff, 0x0040, 0x28c5,
- 0x157e, 0x20a9, 0x0000, 0x2021, 0x7400, 0x047e, 0x2009, 0x0005,
- 0x2011, 0x0020, 0x1078, 0x28ff, 0x047f, 0x0040, 0x28c4, 0x8420,
- 0x0070, 0x28c4, 0x0078, 0x28b5, 0x157f, 0x0078, 0x2482, 0x2200,
- 0x0079, 0x28ca, 0x28cd, 0x28cf, 0x28cf, 0x1078, 0x23eb, 0x2009,
- 0x0012, 0x706c, 0xa086, 0x0002, 0x0040, 0x28d8, 0x2009, 0x000e,
- 0x6818, 0xa084, 0x8000, 0x0040, 0x28de, 0x691a, 0x706f, 0x0000,
- 0x7073, 0x0001, 0x0078, 0x3888, 0x2200, 0x0079, 0x28e7, 0x28ec,
- 0x28cf, 0x28ea, 0x1078, 0x23eb, 0x1078, 0x4776, 0x7000, 0xa086,
- 0x0001, 0x00c0, 0x339d, 0x1078, 0x33ee, 0x6008, 0xa084, 0xffef,
- 0x600a, 0x1078, 0x3390, 0x0040, 0x339d, 0x0078, 0x2594, 0x2404,
- 0xa005, 0x0040, 0x2922, 0x2068, 0x2d04, 0x007e, 0x6814, 0xa706,
- 0x0040, 0x290e, 0x2d20, 0x007f, 0x0078, 0x2900, 0x007f, 0x2022,
- 0x691a, 0x6817, 0x0000, 0x6820, 0xa205, 0x6822, 0x1078, 0x1c70,
- 0x6010, 0x8001, 0x6012, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078,
- 0x33ee, 0x007c, 0xa085, 0x0001, 0x0078, 0x2921, 0x2300, 0x0079,
- 0x2929, 0x292e, 0x292c, 0x29c7, 0x1078, 0x23eb, 0x78ec, 0xa084,
- 0x0001, 0x00c0, 0x2942, 0x7000, 0xa086, 0x0004, 0x00c0, 0x293a,
- 0x0078, 0x2965, 0x1078, 0x33ee, 0x6008, 0xa084, 0xffef, 0x600a,
- 0x0078, 0x339d, 0x78e4, 0xa005, 0x00d0, 0x2965, 0x0018, 0x2459,
- 0x2008, 0xa084, 0x0030, 0x00c0, 0x2951, 0x781b, 0x004f, 0x0078,
- 0x2459, 0x78ec, 0xa084, 0x0003, 0x0040, 0x294d, 0x2100, 0xa084,
- 0x0007, 0x0079, 0x295b, 0x299e, 0x29a9, 0x298f, 0x2963, 0x38ed,
- 0x38ed, 0x2963, 0x29b8, 0x1078, 0x23eb, 0x7000, 0xa086, 0x0004,
- 0x00c0, 0x297f, 0x706c, 0xa086, 0x0002, 0x00c0, 0x2975, 0x2011,
- 0x0002, 0x2019, 0x0000, 0x0078, 0x2848, 0x706c, 0xa086, 0x0006,
- 0x0040, 0x296f, 0x706c, 0xa086, 0x0004, 0x0040, 0x296f, 0x79e4,
- 0xa184, 0x0030, 0x0040, 0x2989, 0x78ec, 0xa084, 0x0003, 0x00c0,
- 0x298b, 0x0078, 0x2f6d, 0x2001, 0x0003, 0x0078, 0x2d01, 0x6818,
- 0xa084, 0x8000, 0x0040, 0x2996, 0x681b, 0x001d, 0x1078, 0x36c1,
- 0x782b, 0x3008, 0x781b, 0x0056, 0x0078, 0x2459, 0x6818, 0xa084,
- 0x8000, 0x0040, 0x29a5, 0x681b, 0x001d, 0x1078, 0x36c1, 0x0078,
- 0x38b8, 0x6818, 0xa084, 0x8000, 0x0040, 0x29b0, 0x681b, 0x001d,
- 0x1078, 0x36c1, 0x782b, 0x3008, 0x781b, 0x00cd, 0x0078, 0x2459,
- 0x6818, 0xa084, 0x8000, 0x0040, 0x29bf, 0x681b, 0x001d, 0x1078,
- 0x36c1, 0x782b, 0x3008, 0x781b, 0x008e, 0x0078, 0x2459, 0xa584,
- 0x000f, 0x00c0, 0x29e4, 0x7000, 0x0079, 0x29ce, 0x2482, 0x29d8,
- 0x29d6, 0x339d, 0x339d, 0x339d, 0x339d, 0x29d6, 0x1078, 0x23eb,
- 0x1078, 0x33ee, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078, 0x3390,
- 0x0040, 0x339d, 0x0078, 0x2594, 0x78e4, 0xa005, 0x00d0, 0x2965,
- 0x0018, 0x2965, 0x2008, 0xa084, 0x0030, 0x00c0, 0x29f3, 0x781b,
- 0x004f, 0x0078, 0x2459, 0x78ec, 0xa084, 0x0003, 0x0040, 0x29ef,
- 0x2100, 0xa184, 0x0007, 0x0079, 0x29fd, 0x2a0f, 0x2a13, 0x2a07,
- 0x2a05, 0x38ed, 0x38ed, 0x2a05, 0x38e3, 0x1078, 0x23eb, 0x1078,
- 0x36c9, 0x782b, 0x3008, 0x781b, 0x0056, 0x0078, 0x2459, 0x1078,
- 0x36c9, 0x0078, 0x38b8, 0x1078, 0x36c9, 0x782b, 0x3008, 0x781b,
- 0x00cd, 0x0078, 0x2459, 0x1078, 0x36c9, 0x782b, 0x3008, 0x781b,
- 0x008e, 0x0078, 0x2459, 0x2300, 0x0079, 0x2a26, 0x2a2b, 0x2a29,
- 0x2a2d, 0x1078, 0x23eb, 0x0078, 0x30ab, 0x681b, 0x0008, 0x78a3,
- 0x0000, 0x79e4, 0xa184, 0x0030, 0x0040, 0x30ab, 0x78ec, 0xa084,
- 0x0003, 0x0040, 0x30ab, 0xa184, 0x0007, 0x0079, 0x2a3f, 0x2a47,
- 0x2a13, 0x298f, 0x3888, 0x38ed, 0x38ed, 0x2a47, 0x38e3, 0x1078,
- 0x389c, 0x0078, 0x2459, 0xa282, 0x0005, 0x0050, 0x2a51, 0x1078,
- 0x23eb, 0x2300, 0x0079, 0x2a54, 0x2a57, 0x2cae, 0x2cbc, 0x2200,
- 0x0079, 0x2a5a, 0x2a74, 0x2a61, 0x2a74, 0x2a5f, 0x2c93, 0x1078,
- 0x23eb, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff, 0xa082, 0x0020,
- 0x0048, 0x369d, 0xa08a, 0x0004, 0x00c8, 0x369d, 0x0079, 0x2a70,
- 0x369d, 0x369d, 0x369d, 0x364b, 0x789b, 0x0018, 0x79a8, 0xa184,
- 0x0080, 0x0040, 0x2a85, 0x0078, 0x369d, 0x7000, 0xa005, 0x00c0,
- 0x2a7b, 0x2011, 0x0004, 0x0078, 0x321f, 0xa184, 0x00ff, 0xa08a,
- 0x0010, 0x00c8, 0x369d, 0x0079, 0x2a8d, 0x2a9f, 0x2a9d, 0x2ab7,
- 0x2abb, 0x2b78, 0x369d, 0x369d, 0x2b7a, 0x369d, 0x369d, 0x2c8f,
- 0x2c8f, 0x369d, 0x369d, 0x369d, 0x2c91, 0x1078, 0x23eb, 0xa684,
- 0x1000, 0x0040, 0x2aac, 0x2001, 0x0500, 0x8000, 0x8000, 0x783a,
- 0x781b, 0x008c, 0x0078, 0x2459, 0x6818, 0xa084, 0x8000, 0x0040,
- 0x2ab5, 0x681b, 0x001d, 0x0078, 0x2aa3, 0x0078, 0x3888, 0x681b,
- 0x001d, 0x0078, 0x36ad, 0x6920, 0x6922, 0xa684, 0x1800, 0x00c0,
- 0x2afc, 0x6820, 0xa084, 0x0001, 0x00c0, 0x2b04, 0x6818, 0xa086,
- 0x0008, 0x00c0, 0x2acd, 0x681b, 0x0000, 0xa684, 0x0400, 0x0040,
- 0x2b74, 0xa684, 0x0080, 0x0040, 0x2af8, 0x7097, 0x0000, 0x6818,
- 0xa084, 0x003f, 0xa08a, 0x000d, 0x0050, 0x2af8, 0xa08a, 0x000c,
- 0x7196, 0x2001, 0x000c, 0x800c, 0x719a, 0x789b, 0x0061, 0x78aa,
+ 0x5480, 0x2019, 0x0000, 0x72c8, 0xd2bc, 0x0040, 0x14e9, 0xa39d,
+ 0x0010, 0xd2b4, 0x0040, 0x14ee, 0xa39d, 0x0008, 0x6800, 0x007e,
+ 0xa226, 0x0040, 0x1511, 0x6a02, 0xa484, 0x2000, 0x0040, 0x14fa,
+ 0xa39d, 0x0010, 0xa484, 0x1000, 0x0040, 0x1500, 0xa39d, 0x0008,
+ 0xa484, 0x4000, 0x0040, 0x1511, 0x810f, 0xa284, 0x4000, 0x0040,
+ 0x150d, 0x1078, 0x2399, 0x0078, 0x1511, 0x1078, 0x238b, 0x0078,
+ 0x1511, 0x72cc, 0x6808, 0xa206, 0x0040, 0x1540, 0xa2a4, 0x00ff,
+ 0x2061, 0x5240, 0x6118, 0xa186, 0x0028, 0x0040, 0x1527, 0xa186,
+ 0x0032, 0x0040, 0x152d, 0xa186, 0x003c, 0x0040, 0x1533, 0xa482,
+ 0x0064, 0x0048, 0x153d, 0x0078, 0x1537, 0xa482, 0x0050, 0x0048,
+ 0x153d, 0x0078, 0x1537, 0xa482, 0x0043, 0x0048, 0x153d, 0x71c4,
+ 0x71c6, 0x027f, 0x72ca, 0x0078, 0x127d, 0x6a0a, 0xa39d, 0x000a,
+ 0x6804, 0xa305, 0x6806, 0x027f, 0x6b0c, 0x71c4, 0x0078, 0x1281,
+ 0x77c4, 0x1078, 0x19c5, 0x2091, 0x8000, 0x6a14, 0x6b1c, 0x2091,
+ 0x8001, 0x70c8, 0x6816, 0x70cc, 0x681e, 0x2708, 0x0078, 0x1281,
+ 0x70c4, 0x794c, 0x784e, 0x0078, 0x1283, 0x71c4, 0x72c8, 0x73cc,
+ 0xa182, 0x0010, 0x00c8, 0x127c, 0x1078, 0x23a7, 0x0078, 0x1281,
+ 0x77c4, 0x1078, 0x19c5, 0x2091, 0x8000, 0x6a08, 0xa295, 0x0002,
+ 0x6a0a, 0x2091, 0x8001, 0x2708, 0x0078, 0x1282, 0x77c4, 0x1078,
+ 0x19c5, 0x2091, 0x8000, 0x6a08, 0xa294, 0xfff9, 0x6a0a, 0x6804,
+ 0xa005, 0x0040, 0x1585, 0x1078, 0x226f, 0x2091, 0x8001, 0x2708,
+ 0x0078, 0x1282, 0x77c4, 0x1078, 0x19c5, 0x2091, 0x8000, 0x6a08,
+ 0xa295, 0x0004, 0x6a0a, 0x6804, 0xa005, 0x0040, 0x1599, 0x1078,
+ 0x226f, 0x2091, 0x8001, 0x2708, 0x0078, 0x1282, 0x77c4, 0x2041,
+ 0x0001, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x1078,
+ 0x19d2, 0x2091, 0x8001, 0x2708, 0x6a08, 0x0078, 0x1282, 0x77c4,
+ 0x72c8, 0x73cc, 0x77c6, 0x72ca, 0x73ce, 0x1078, 0x1a52, 0x00c0,
+ 0x15c7, 0x6818, 0xa005, 0x0040, 0x15c7, 0x2708, 0x1078, 0x23b7,
+ 0x00c0, 0x15c7, 0x7817, 0x0015, 0x2091, 0x8001, 0x007c, 0x2091,
+ 0x8001, 0x0078, 0x1284, 0x77c4, 0x77c6, 0x2041, 0x0021, 0x2049,
+ 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x1078, 0x19d2, 0x2061,
+ 0x5240, 0x606f, 0x0003, 0x6782, 0x6093, 0x000f, 0x6073, 0x0000,
+ 0x7817, 0x0016, 0x1078, 0x226f, 0x2091, 0x8001, 0x007c, 0x77c8,
+ 0x77ca, 0x77c4, 0x77c6, 0xa7bc, 0xff00, 0x2091, 0x8000, 0x2061,
+ 0x5240, 0x606f, 0x0002, 0x6073, 0x0000, 0x6782, 0x6093, 0x000f,
+ 0x7817, 0x0017, 0x1078, 0x226f, 0x2091, 0x8001, 0x2041, 0x0021,
+ 0x2049, 0x0004, 0x2051, 0x0010, 0x2091, 0x8000, 0x1078, 0x19d2,
+ 0x70c8, 0x6836, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1606, 0x2091,
+ 0x8001, 0x007c, 0x78cc, 0xa084, 0x0003, 0x00c0, 0x1636, 0x2039,
+ 0x0000, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008, 0x1078,
+ 0x19c5, 0x2091, 0x8000, 0x6808, 0xa80d, 0x690a, 0x2091, 0x8001,
+ 0x8738, 0xa784, 0x001f, 0x00c0, 0x161f, 0xa7bc, 0xff00, 0x873f,
+ 0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0, 0x161f, 0x2091, 0x8000,
+ 0x2069, 0x0100, 0x6830, 0xa084, 0x0040, 0x0040, 0x165f, 0x684b,
+ 0x0004, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0004, 0x0040, 0x164c,
+ 0x0070, 0x164c, 0x0078, 0x1643, 0x684b, 0x0009, 0x20a9, 0x0014,
+ 0x6848, 0xa084, 0x0001, 0x0040, 0x1659, 0x0070, 0x1659, 0x0078,
+ 0x1650, 0x20a9, 0x00fa, 0x0070, 0x165f, 0x0078, 0x165b, 0x2079,
+ 0x5200, 0x7817, 0x0018, 0x2061, 0x5240, 0x606f, 0x0001, 0x6073,
+ 0x0000, 0x6093, 0x000f, 0x78cc, 0xa085, 0x0002, 0x78ce, 0x6808,
+ 0xa084, 0xfffd, 0x680a, 0x681b, 0x0048, 0x2091, 0x8001, 0x007c,
+ 0x78cc, 0xa084, 0xfffd, 0x78ce, 0xa084, 0x0001, 0x00c0, 0x1682,
+ 0x1078, 0x1a9c, 0x71c4, 0x71c6, 0x794a, 0x007c, 0x1078, 0x1bc4,
+ 0x00c0, 0x129c, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0078, 0x1693,
+ 0x2029, 0x0000, 0x2520, 0x71c4, 0x73c8, 0x72cc, 0x71c6, 0x73ca,
+ 0x72ce, 0x2079, 0x5200, 0x2091, 0x8000, 0x1078, 0x1980, 0x2091,
+ 0x8001, 0x0040, 0x174a, 0x20a9, 0x0005, 0x20a1, 0x5218, 0x2091,
+ 0x8000, 0x41a1, 0x2091, 0x8001, 0x2009, 0x0020, 0x1078, 0x197b,
+ 0x0040, 0x16b6, 0x1078, 0x199a, 0x0078, 0x174a, 0x6004, 0xa084,
+ 0xff00, 0x8007, 0x8009, 0x0040, 0x1719, 0x0c7e, 0x2c68, 0x2091,
+ 0x8000, 0x1078, 0x1980, 0x2091, 0x8001, 0x0040, 0x16ea, 0x2c00,
+ 0x689e, 0x8109, 0x00c0, 0x16be, 0x609f, 0x0000, 0x0c7f, 0x0c7e,
+ 0x7218, 0x731c, 0x7420, 0x7524, 0x2c68, 0x689c, 0xa065, 0x0040,
+ 0x1718, 0x2009, 0x0020, 0x1078, 0x197b, 0x00c0, 0x1701, 0x6004,
+ 0xa084, 0x00ff, 0xa086, 0x0002, 0x00c0, 0x16ea, 0x2d00, 0x6002,
+ 0x0078, 0x16d0, 0x0c7f, 0x0c7e, 0x609c, 0x2060, 0x1078, 0x1a17,
+ 0x0c7f, 0x609f, 0x0000, 0x1078, 0x174e, 0x2009, 0x000c, 0x6008,
+ 0xa085, 0x0200, 0x600a, 0x1078, 0x1976, 0x1078, 0x199a, 0x0078,
+ 0x174a, 0x0c7f, 0x0c7e, 0x609c, 0x2060, 0x1078, 0x1a17, 0x0c7f,
+ 0x609f, 0x0000, 0x1078, 0x174e, 0x2009, 0x000c, 0x6007, 0x0103,
+ 0x601b, 0x0003, 0x1078, 0x1976, 0x1078, 0x199a, 0x0078, 0x174a,
+ 0x0c7f, 0x74c4, 0x73c8, 0x72cc, 0x6014, 0x2091, 0x8000, 0x7817,
+ 0x0012, 0x0e7e, 0x2071, 0x5240, 0x706f, 0x0005, 0x7073, 0x0000,
+ 0x7376, 0x727a, 0x747e, 0x7082, 0x7087, 0x0000, 0x2c00, 0x708a,
+ 0x708f, 0x0000, 0xa02e, 0x2530, 0x611c, 0x61a2, 0xa184, 0x0060,
+ 0x0040, 0x173c, 0x1078, 0x48d3, 0x0e7f, 0x6596, 0x65a6, 0x669a,
+ 0x66aa, 0x60af, 0x0000, 0x60b3, 0x0000, 0x1078, 0x226f, 0x2091,
+ 0x8001, 0x007c, 0x70c3, 0x4005, 0x0078, 0x1287, 0x20a9, 0x0005,
+ 0x2099, 0x5218, 0x2091, 0x8000, 0x530a, 0x2091, 0x8001, 0x2100,
+ 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x007c,
+ 0x71c4, 0x70c7, 0x0000, 0x7906, 0x0078, 0x1284, 0x71c4, 0x71c6,
+ 0x2168, 0x0078, 0x176d, 0x2069, 0x1000, 0x690c, 0xa016, 0x2d04,
+ 0xa210, 0x8d68, 0x8109, 0x00c0, 0x176f, 0xa285, 0x0000, 0x00c0,
+ 0x177d, 0x70c3, 0x4000, 0x0078, 0x177f, 0x70c3, 0x4003, 0x70ca,
+ 0x0078, 0x1287, 0x2011, 0x5267, 0x220c, 0x70c4, 0x8003, 0x0048,
+ 0x178f, 0x1078, 0x3c51, 0xa184, 0x7fff, 0x0078, 0x1793, 0x1078,
+ 0x3c44, 0xa185, 0x8000, 0x2012, 0x0078, 0x1283, 0x71c4, 0x1078,
+ 0x3c3b, 0x6100, 0x2001, 0x5267, 0x2004, 0xa084, 0x8000, 0xa10d,
+ 0x6204, 0x6308, 0x0078, 0x1281, 0x79e4, 0x0078, 0x1283, 0x71c4,
+ 0x71c6, 0x2198, 0x20a1, 0x0042, 0x20a9, 0x0004, 0x53a3, 0x21a0,
+ 0x2099, 0x0042, 0x20a9, 0x0004, 0x53a3, 0x0078, 0x1284, 0x70c4,
+ 0x2068, 0x2079, 0x5200, 0x2091, 0x8000, 0x1078, 0x1980, 0x2091,
+ 0x8001, 0x0040, 0x1843, 0x6007, 0x0001, 0x600b, 0x0000, 0x602b,
+ 0x0000, 0x601b, 0x0006, 0x6a10, 0xa28c, 0x000f, 0xa284, 0x00f0,
+ 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0x6016, 0xa284, 0x0800,
+ 0x0040, 0x17de, 0x601b, 0x000a, 0x0078, 0x17e4, 0xa284, 0x1000,
+ 0x0040, 0x17e4, 0x601b, 0x000c, 0xa284, 0x0300, 0x0040, 0x17ed,
+ 0x602b, 0x0001, 0x8004, 0x8004, 0x8004, 0xa085, 0x0001, 0x601e,
+ 0x6023, 0x0000, 0x6027, 0x0000, 0xa284, 0x0400, 0x0040, 0x17fa,
+ 0x602b, 0x0000, 0x20a9, 0x0006, 0xac80, 0x000b, 0x20a0, 0xad80,
+ 0x0005, 0x2098, 0x53a3, 0xa284, 0x0300, 0x00c0, 0x180f, 0x6046,
+ 0x604a, 0x604e, 0x6052, 0x6096, 0x609a, 0x0078, 0x1819, 0x6800,
+ 0x6046, 0x6804, 0x604a, 0x6e08, 0x664e, 0x6d0c, 0x6552, 0x6596,
+ 0x669a, 0x6014, 0x2091, 0x8000, 0x7817, 0x0042, 0x2c08, 0x2061,
+ 0x5240, 0x606f, 0x0005, 0x6073, 0x0000, 0x6077, 0x0000, 0x607b,
+ 0x0000, 0x607f, 0x0000, 0x6082, 0x618a, 0xa284, 0x0400, 0x608e,
+ 0x2091, 0x8001, 0x0e7e, 0x2071, 0x0020, 0x7007, 0x000a, 0x7007,
+ 0x0002, 0x7003, 0x0000, 0x0e7f, 0x2091, 0x8000, 0x1078, 0x226f,
+ 0x2091, 0x8001, 0x007c, 0x70c3, 0x4005, 0x0078, 0x1287, 0x0c7e,
+ 0x0d7e, 0x0e7e, 0x0f7e, 0x2091, 0x8000, 0x2071, 0x5240, 0x2079,
+ 0x0100, 0x2061, 0x0010, 0x70a0, 0xa06d, 0x0040, 0x1903, 0x6a04,
+ 0xa294, 0x00ff, 0xa286, 0x0007, 0x0040, 0x1862, 0xa286, 0x000f,
+ 0x00c0, 0x1903, 0x691c, 0xa184, 0x00c0, 0x0040, 0x1903, 0xa184,
+ 0x0080, 0x00c0, 0x18d3, 0x6824, 0xa084, 0xff00, 0xa085, 0x0019,
+ 0x6826, 0x71b0, 0x81ff, 0x0040, 0x1889, 0x0d7e, 0x2069, 0x0020,
+ 0x6807, 0x0010, 0x6908, 0x6808, 0xa106, 0x00c0, 0x187a, 0x690c,
+ 0x680c, 0xa106, 0x00c0, 0x187f, 0xa184, 0x00ff, 0x00c0, 0x187f,
+ 0x0d7f, 0x78b8, 0xa084, 0x801f, 0x00c0, 0x1889, 0x7848, 0xa085,
+ 0x000c, 0x784a, 0x71b0, 0x81ff, 0x0040, 0x18ac, 0x70b3, 0x0000,
+ 0x0d7e, 0x2069, 0x0020, 0x6807, 0x0018, 0x6804, 0xa084, 0x0008,
+ 0x00c0, 0x189d, 0x6807, 0x0008, 0x6804, 0xa084, 0x0008, 0x00c0,
+ 0x18a4, 0x6807, 0x0002, 0x0d7f, 0x61c4, 0x62c8, 0x63cc, 0x61c6,
+ 0x62ca, 0x63ce, 0x0e7e, 0x2071, 0x5200, 0x7266, 0x736a, 0xae80,
+ 0x0019, 0x0e7f, 0x7848, 0xa084, 0x000c, 0x00c0, 0x18ba, 0x1078,
+ 0x47e1, 0x78a3, 0x0000, 0x7858, 0xa084, 0xedff, 0x785a, 0x70b4,
+ 0xa080, 0x00da, 0x781a, 0x0f7f, 0x0e7f, 0x0d7f, 0x0c7f, 0x2091,
+ 0x8001, 0x0078, 0x1284, 0x6824, 0xa084, 0xff00, 0xa085, 0x0019,
+ 0x6826, 0x78b8, 0xa084, 0x801f, 0x00c0, 0x18d9, 0x7848, 0xa085,
+ 0x000c, 0x784a, 0x7848, 0xa084, 0x000c, 0x00c0, 0x18e2, 0x71b0,
+ 0x81ff, 0x0040, 0x1901, 0x70b3, 0x0000, 0x0d7e, 0x2069, 0x0020,
+ 0x6807, 0x0018, 0x6804, 0xa084, 0x0008, 0x00c0, 0x18f2, 0x6807,
+ 0x0008, 0x6804, 0xa084, 0x0008, 0x00c0, 0x18f9, 0x6807, 0x0002,
+ 0x0d7f, 0x0078, 0x18cb, 0x0f7f, 0x0e7f, 0x0d7f, 0x0c7f, 0x2091,
+ 0x8001, 0x2001, 0x4005, 0x0078, 0x1286, 0x7980, 0x71c6, 0x71c4,
+ 0xa182, 0x0003, 0x00c8, 0x127c, 0x7982, 0x0078, 0x1284, 0x7980,
+ 0x71c6, 0x0078, 0x1284, 0x7974, 0x71c6, 0x71c4, 0x7976, 0x7978,
+ 0x71ca, 0x71c8, 0x797a, 0x797c, 0x71ce, 0x71cc, 0x797e, 0x0078,
+ 0x1284, 0x7974, 0x71c6, 0x7978, 0x71ca, 0x797c, 0x71ce, 0x0078,
+ 0x1284, 0x7900, 0x71c6, 0x71c4, 0x7902, 0x2001, 0x04fd, 0x2004,
+ 0xa082, 0x0005, 0x0048, 0x1940, 0x0038, 0x1942, 0x0078, 0x194c,
+ 0x00a8, 0x194c, 0xa18c, 0x0001, 0x00c0, 0x194a, 0x20b9, 0x2222,
+ 0x0078, 0x194c, 0x20b9, 0x1212, 0x0078, 0x1284, 0x7900, 0x71c6,
+ 0x0078, 0x1284, 0x2009, 0x5274, 0x2104, 0x70c6, 0x70c4, 0x200a,
+ 0x0078, 0x1284, 0x2009, 0x5274, 0x2104, 0x70c6, 0x0078, 0x1284,
+ 0x71c4, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e8,
+ 0x5480, 0x6a14, 0xd2b4, 0x0040, 0x1971, 0x2011, 0x0001, 0x0078,
+ 0x1973, 0x2011, 0x0000, 0x6b0c, 0x0078, 0x1281, 0xac80, 0x0001,
+ 0x1078, 0x1b80, 0x007c, 0xac80, 0x0001, 0x1078, 0x1b20, 0x007c,
+ 0x7850, 0xa065, 0x0040, 0x1988, 0x2c04, 0x7852, 0x2063, 0x0000,
+ 0x007c, 0x0f7e, 0x2079, 0x5200, 0x7850, 0xa06d, 0x0040, 0x1998,
+ 0x2d04, 0x7852, 0x6803, 0x0000, 0x6807, 0x0000, 0x680b, 0x0000,
+ 0x0f7f, 0x007c, 0x2091, 0x8000, 0x0f7e, 0x2079, 0x5200, 0x7850,
+ 0x2062, 0x2c00, 0xa005, 0x00c0, 0x19a7, 0x1078, 0x248c, 0x7852,
+ 0x0f7f, 0x2091, 0x8001, 0x007c, 0x0f7e, 0x2079, 0x5200, 0x7850,
+ 0x206a, 0x2d00, 0x7852, 0x0f7f, 0x007c, 0x2011, 0x7900, 0x7a52,
+ 0x7bec, 0x8319, 0x0040, 0x19c2, 0xa280, 0x0031, 0x2012, 0x2010,
+ 0x0078, 0x19b9, 0x2013, 0x0000, 0x007c, 0xa784, 0x0f00, 0x800b,
+ 0xa784, 0x001f, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xa0e8,
+ 0x5500, 0x007c, 0x1078, 0x19c5, 0x2900, 0x682a, 0x2a00, 0x682e,
+ 0x6808, 0xa084, 0xffef, 0xa80d, 0x690a, 0x2009, 0x5252, 0x210c,
+ 0x6804, 0xa005, 0x0040, 0x1a04, 0xa116, 0x00c0, 0x19ef, 0x2060,
+ 0x6000, 0x6806, 0x017e, 0x200b, 0x0000, 0x0078, 0x19f2, 0x2009,
+ 0x0000, 0x017e, 0x6804, 0xa065, 0x0040, 0x1a01, 0x6000, 0x6806,
+ 0x1078, 0x1a31, 0x1078, 0x1ccb, 0x6810, 0x8001, 0x6812, 0x00c0,
+ 0x19f2, 0x017f, 0x6902, 0x6906, 0x007c, 0xa065, 0x0040, 0x1a16,
+ 0x2008, 0x609c, 0xa005, 0x0040, 0x1a13, 0x2062, 0x609f, 0x0000,
+ 0xa065, 0x0078, 0x1a09, 0x7850, 0x7952, 0x2062, 0x007c, 0xa065,
+ 0x0040, 0x1a30, 0x2008, 0x609c, 0xa005, 0x0040, 0x1a25, 0x2062,
+ 0x609f, 0x0000, 0xa065, 0x0078, 0x1a1b, 0x0f7e, 0x2079, 0x5200,
+ 0x2091, 0x8000, 0x7850, 0x7952, 0x0f7f, 0x2062, 0x2091, 0x8001,
+ 0x007c, 0x6007, 0x0103, 0x608f, 0x0000, 0x20a9, 0x001c, 0xac80,
+ 0x0005, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x6828, 0x601a, 0x682c,
+ 0x6022, 0x007c, 0x0e7e, 0x2071, 0x5240, 0x704c, 0xa08c, 0x0200,
+ 0x00c0, 0x1a50, 0xa088, 0x5280, 0x2d0a, 0x8000, 0x704e, 0xa006,
+ 0x0e7f, 0x007c, 0x1078, 0x19c5, 0x2091, 0x8000, 0x6804, 0x781e,
+ 0xa065, 0x0040, 0x1a9b, 0x0078, 0x1a63, 0x2c00, 0x781e, 0x6000,
+ 0xa065, 0x0040, 0x1a9b, 0x600c, 0xa306, 0x00c0, 0x1a5d, 0x6010,
+ 0xa206, 0x00c0, 0x1a5d, 0x2c28, 0x2001, 0x5252, 0x2004, 0xac06,
+ 0x00c0, 0x1a74, 0x0078, 0x1a99, 0x6804, 0xac06, 0x00c0, 0x1a81,
+ 0x6000, 0xa065, 0x6806, 0x00c0, 0x1a8b, 0x6803, 0x0000, 0x0078,
+ 0x1a8b, 0x6400, 0x781c, 0x2060, 0x6402, 0xa486, 0x0000, 0x00c0,
+ 0x1a8b, 0x2c00, 0x6802, 0x2560, 0x1078, 0x1a31, 0x601b, 0x0005,
+ 0x6023, 0x0020, 0x1078, 0x1ccb, 0x6810, 0x8001, 0x1050, 0x248c,
+ 0x6812, 0xa085, 0xffff, 0x007c, 0x2039, 0x0000, 0x2041, 0x0021,
+ 0x2049, 0x0004, 0x2051, 0x0008, 0x2091, 0x8000, 0x1078, 0x19d2,
+ 0x8738, 0xa784, 0x001f, 0x00c0, 0x1aa6, 0xa7bc, 0xff00, 0x873f,
+ 0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0, 0x1aa6, 0x2091, 0x8001,
+ 0x007c, 0x2061, 0x0000, 0x6018, 0xa084, 0x0001, 0x00c0, 0x1aca,
+ 0x2091, 0x8000, 0x78e0, 0x78e3, 0x0000, 0x2091, 0x8001, 0xa005,
+ 0x00c0, 0x1acb, 0x007c, 0xa08c, 0xfff0, 0x0040, 0x1ad1, 0x1078,
+ 0x248c, 0x0079, 0x1ad3, 0x1ae3, 0x1ae6, 0x1aec, 0x1af0, 0x1ae4,
+ 0x1af4, 0x1afa, 0x1ae4, 0x1ae4, 0x1c95, 0x1cb9, 0x1cbd, 0x1ae4,
+ 0x1ae4, 0x1ae4, 0x1ae4, 0x007c, 0x1078, 0x248c, 0x1078, 0x1a9c,
+ 0x2001, 0x8001, 0x0078, 0x1cc3, 0x2001, 0x8003, 0x0078, 0x1cc3,
+ 0x2001, 0x8004, 0x0078, 0x1cc3, 0x1078, 0x1a9c, 0x2001, 0x8006,
+ 0x0078, 0x1cc3, 0x2001, 0x8007, 0x0078, 0x1cc3, 0x2030, 0x2138,
+ 0xa782, 0x0021, 0x0048, 0x1b06, 0x2009, 0x0020, 0x2600, 0x1078,
+ 0x1b20, 0x00c0, 0x1b1f, 0xa7ba, 0x0020, 0x0048, 0x1b1e, 0x0040,
+ 0x1b1e, 0x2708, 0xa6b0, 0x0020, 0xa290, 0x0040, 0xa399, 0x0000,
+ 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x0078, 0x1b00, 0xa006, 0x007c,
+ 0x81ff, 0x0040, 0x1b5b, 0x2099, 0x0030, 0x20a0, 0x700c, 0xa084,
+ 0x00ff, 0x0040, 0x1b32, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004,
+ 0x00c0, 0x1b2d, 0x21a8, 0x7017, 0x0000, 0x810b, 0x7112, 0x721a,
+ 0x731e, 0x7422, 0x7526, 0x780c, 0xa085, 0x0001, 0x7002, 0x7007,
+ 0x0001, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x00c8, 0x1b4f,
+ 0x2009, 0x0022, 0x2104, 0xa084, 0x4000, 0x00c0, 0x1b41, 0x7008,
+ 0x800b, 0x00c8, 0x1b41, 0x7007, 0x0002, 0xa08c, 0x01e0, 0x00c0,
+ 0x1b5b, 0x53a5, 0xa006, 0x7003, 0x0000, 0x007c, 0x2030, 0x2138,
+ 0xa782, 0x0021, 0x0048, 0x1b66, 0x2009, 0x0020, 0x2600, 0x1078,
+ 0x1b80, 0x00c0, 0x1b7f, 0xa7ba, 0x0020, 0x0048, 0x1b7e, 0x0040,
+ 0x1b7e, 0x2708, 0xa6b0, 0x0020, 0xa290, 0x0040, 0xa399, 0x0000,
+ 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x0078, 0x1b60, 0xa006, 0x007c,
+ 0x81ff, 0x0040, 0x1bc1, 0x2098, 0x20a1, 0x0030, 0x700c, 0xa084,
+ 0x00ff, 0x0040, 0x1b92, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004,
+ 0x00c0, 0x1b8d, 0x21a8, 0x7017, 0x0000, 0x810b, 0x7112, 0x721a,
+ 0x731e, 0x7422, 0x7526, 0x780c, 0xa085, 0x0000, 0x7002, 0x53a6,
+ 0x7007, 0x0001, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x00c8,
+ 0x1bb0, 0x2009, 0x0022, 0x2104, 0xa084, 0x4000, 0x00c0, 0x1ba2,
+ 0x7010, 0xa084, 0xf000, 0x0040, 0x1bb9, 0x7007, 0x0008, 0x0078,
+ 0x1bbd, 0x7108, 0x8103, 0x00c8, 0x1ba2, 0x7007, 0x0002, 0xa184,
+ 0x01e0, 0x7003, 0x0000, 0x007c, 0x2001, 0x04fd, 0x2004, 0xa082,
+ 0x0004, 0x00c8, 0x1bcd, 0x0078, 0x1bd0, 0xa006, 0x0078, 0x1bd2,
+ 0xa085, 0x0001, 0x007c, 0x0e7e, 0x2071, 0x5200, 0x2d08, 0x7058,
+ 0x6802, 0xa005, 0x00c0, 0x1bdd, 0x715e, 0x715a, 0x0e7f, 0x007c,
+ 0x2c08, 0x7858, 0x6002, 0xa005, 0x00c0, 0x1be7, 0x795e, 0x795a,
+ 0x007c, 0x2091, 0x8000, 0x6114, 0x1078, 0x2180, 0x6900, 0xa184,
+ 0x0100, 0x00c0, 0x2035, 0xa184, 0x0200, 0x00c0, 0x2031, 0x681c,
+ 0xa005, 0x00c0, 0x203d, 0x6003, 0x0000, 0x2c08, 0x785c, 0xa065,
+ 0x00c0, 0x1c05, 0x795a, 0x0078, 0x1c06, 0x6102, 0x795e, 0x2091,
+ 0x8001, 0x1078, 0x228c, 0x007c, 0x0e7e, 0x2071, 0x5200, 0x7058,
+ 0xa06d, 0x0040, 0x1c1a, 0x6800, 0x705a, 0xa005, 0x00c0, 0x1c19,
+ 0x705e, 0x8dff, 0x0e7f, 0x007c, 0x0d7e, 0x0c7e, 0x0f7e, 0x2079,
+ 0x5200, 0xaf80, 0x0016, 0x2060, 0x6000, 0xa005, 0x0040, 0x1c43,
+ 0x2068, 0x6814, 0xa306, 0x00c0, 0x1c33, 0x6828, 0xa084, 0x00ff,
+ 0xa406, 0x0040, 0x1c36, 0x2d60, 0x0078, 0x1c24, 0x6800, 0xa005,
+ 0x6002, 0x00c0, 0x1c42, 0xaf80, 0x0016, 0xac06, 0x0040, 0x1c41,
+ 0x2c00, 0x785e, 0x2d00, 0x0f7f, 0x0c7f, 0x0d7f, 0xa005, 0x007c,
+ 0x0d7e, 0x0c7e, 0x0f7e, 0x2079, 0x5200, 0xaf80, 0x0016, 0x2060,
+ 0x6000, 0xa005, 0x0040, 0x1c6b, 0x2068, 0x6814, 0xa084, 0x00ff,
+ 0xa306, 0x0040, 0x1c5e, 0x2d60, 0x0078, 0x1c50, 0x6800, 0xa005,
+ 0x6002, 0x00c0, 0x1c6a, 0xaf80, 0x0016, 0xac06, 0x0040, 0x1c69,
+ 0x2c00, 0x785e, 0x2d00, 0x0f7f, 0x0c7f, 0x0d7f, 0xa005, 0x007c,
+ 0x0d7e, 0x0c7e, 0x0f7e, 0x2079, 0x5200, 0xaf80, 0x0016, 0x2060,
+ 0x6000, 0xa06d, 0x0040, 0x1c90, 0x6814, 0xa306, 0x0040, 0x1c83,
+ 0x2d60, 0x0078, 0x1c78, 0x6800, 0xa005, 0x6002, 0x00c0, 0x1c8f,
+ 0xaf80, 0x0016, 0xac06, 0x0040, 0x1c8e, 0x2c00, 0x785e, 0x2d00,
+ 0x0f7f, 0x0c7f, 0x0d7f, 0xa005, 0x007c, 0x2091, 0x8000, 0x2069,
+ 0x5240, 0x6800, 0xa086, 0x0000, 0x0040, 0x1ca3, 0x2091, 0x8001,
+ 0x78e3, 0x0009, 0x007c, 0x6880, 0xa0bc, 0xff00, 0x2041, 0x0021,
+ 0x2049, 0x0004, 0x2051, 0x0010, 0x1078, 0x19d2, 0x8738, 0xa784,
+ 0x001f, 0x00c0, 0x1cac, 0x2091, 0x8001, 0x2001, 0x800a, 0x0078,
+ 0x1cc3, 0x2001, 0x800c, 0x0078, 0x1cc3, 0x1078, 0x1a9c, 0x2001,
+ 0x800d, 0x0078, 0x1cc3, 0x70c2, 0x2061, 0x0000, 0x601b, 0x0001,
+ 0x2091, 0x4080, 0x007c, 0x6004, 0x2c08, 0x2063, 0x0000, 0x7884,
+ 0x8000, 0x7886, 0x7888, 0xa005, 0x798a, 0x0040, 0x1cda, 0x2c02,
+ 0x0078, 0x1cdb, 0x798e, 0x007c, 0x6807, 0x0103, 0x0c7e, 0x2061,
+ 0x5200, 0x2d08, 0x206b, 0x0000, 0x6084, 0x8000, 0x6086, 0x6088,
+ 0xa005, 0x618a, 0x0040, 0x1cef, 0x2d02, 0x0078, 0x1cf0, 0x618e,
+ 0x0c7f, 0x007c, 0x1078, 0x1d03, 0x0040, 0x1d02, 0x0c7e, 0x609c,
+ 0xa065, 0x0040, 0x1cfd, 0x1078, 0x1a17, 0x0c7f, 0x609f, 0x0000,
+ 0x1078, 0x199a, 0x007c, 0x788c, 0xa065, 0x0040, 0x1d15, 0x2091,
+ 0x8000, 0x7884, 0x8001, 0x7886, 0x2c04, 0x788e, 0xa005, 0x00c0,
+ 0x1d13, 0x788a, 0x8000, 0x2091, 0x8001, 0x007c, 0x20a9, 0x0010,
+ 0xa006, 0x8004, 0x8086, 0x818e, 0x00c8, 0x1d1f, 0xa200, 0x0070,
+ 0x1d23, 0x0078, 0x1d1a, 0x8086, 0x818e, 0x007c, 0x157e, 0x20a9,
+ 0x0010, 0xa005, 0x0040, 0x1d49, 0xa11a, 0x00c8, 0x1d49, 0x8213,
+ 0x818d, 0x0048, 0x1d3a, 0xa11a, 0x00c8, 0x1d3b, 0x0070, 0x1d41,
+ 0x0078, 0x1d2f, 0xa11a, 0x2308, 0x8210, 0x0070, 0x1d41, 0x0078,
+ 0x1d2f, 0x007e, 0x3200, 0xa084, 0xf7ff, 0x2080, 0x007f, 0x157f,
+ 0x007c, 0x007e, 0x3200, 0xa085, 0x0800, 0x0078, 0x1d45, 0x7994,
+ 0x70d0, 0xa106, 0x0040, 0x1dbd, 0x2091, 0x8000, 0x2071, 0x0020,
+ 0x7004, 0xa005, 0x00c0, 0x1dbd, 0x7008, 0x7208, 0xa206, 0x00c0,
+ 0x1dbd, 0xa286, 0x0008, 0x00c0, 0x1dbd, 0x2071, 0x0010, 0x1078,
+ 0x1980, 0x0040, 0x1dbd, 0x7a9c, 0x7b98, 0x7ca4, 0x7da0, 0xa184,
+ 0xff00, 0x0040, 0x1d8b, 0x2031, 0x0000, 0x810b, 0x86b5, 0x810b,
+ 0x86b5, 0x810b, 0x86b5, 0x810b, 0x86b5, 0x810b, 0x86b5, 0x810b,
+ 0x86b5, 0x2100, 0xa210, 0x2600, 0xa319, 0xa4a1, 0x0000, 0xa5a9,
+ 0x0000, 0x0078, 0x1d95, 0x8107, 0x8004, 0x8004, 0xa210, 0xa399,
+ 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x2009, 0x0020, 0x1078,
+ 0x197b, 0x2091, 0x8001, 0x0040, 0x1db4, 0x1078, 0x199a, 0x78a8,
+ 0x8000, 0x78aa, 0xa086, 0x0002, 0x00c0, 0x1dbd, 0x2091, 0x8000,
+ 0x78e3, 0x0002, 0x78ab, 0x0000, 0x78cc, 0xa085, 0x0003, 0x78ce,
+ 0x2091, 0x8001, 0x0078, 0x1dbd, 0x78ab, 0x0000, 0x1078, 0x2149,
+ 0x6004, 0xa084, 0x000f, 0x0079, 0x1dc2, 0x2071, 0x0010, 0x2091,
+ 0x8001, 0x007c, 0x1dd2, 0x1df4, 0x1e1a, 0x1dd2, 0x1e37, 0x1de1,
+ 0x1fc9, 0x1fe4, 0x1dd2, 0x1dee, 0x1e14, 0x1e7f, 0x1eee, 0x1f57,
+ 0x1f69, 0x1fe0, 0x2039, 0x0400, 0x78dc, 0xa705, 0x78de, 0x6008,
+ 0xa705, 0x600a, 0x1078, 0x2064, 0x609c, 0x78da, 0x1078, 0x2131,
+ 0x007c, 0x78dc, 0xa084, 0x0100, 0x0040, 0x1de8, 0x0078, 0x1dd2,
+ 0x601c, 0xa085, 0x0080, 0x601e, 0x0078, 0x1dfb, 0x1078, 0x1bc4,
+ 0x00c0, 0x1dd2, 0x1078, 0x2163, 0x78dc, 0xa084, 0x0100, 0x0040,
+ 0x1dfb, 0x0078, 0x1dd2, 0x78df, 0x0000, 0x6004, 0x8007, 0xa084,
+ 0x00ff, 0x78d2, 0x8001, 0x609f, 0x0000, 0x0040, 0x1e11, 0x1078,
+ 0x2064, 0x0040, 0x1e11, 0x78dc, 0xa085, 0x0100, 0x78de, 0x0078,
+ 0x1e13, 0x1078, 0x2088, 0x007c, 0x1078, 0x1bc4, 0x00c0, 0x1dd2,
+ 0x1078, 0x215f, 0x78dc, 0xa08c, 0x0e00, 0x00c0, 0x1e23, 0xa084,
+ 0x0100, 0x00c0, 0x1e25, 0x0078, 0x1dd2, 0x1078, 0x2064, 0x00c0,
+ 0x1e36, 0x6104, 0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040, 0x2021,
+ 0xa186, 0x000f, 0x0040, 0x2021, 0x1078, 0x2088, 0x007c, 0x78dc,
+ 0xa084, 0x0100, 0x0040, 0x1e3e, 0x0078, 0x1dd2, 0x78df, 0x0000,
+ 0x6714, 0x2011, 0x0001, 0x20a9, 0x0001, 0x6018, 0xa084, 0x00ff,
+ 0xa005, 0x0040, 0x1e61, 0x2011, 0x0001, 0xa7bc, 0xff00, 0x20a9,
+ 0x0020, 0xa08e, 0x0001, 0x0040, 0x1e61, 0x2039, 0x0000, 0x2011,
+ 0x0002, 0x20a9, 0x0100, 0xa08e, 0x0002, 0x0040, 0x1e61, 0x0078,
+ 0x1e7c, 0x1078, 0x19c5, 0x2091, 0x8000, 0x682b, 0x0000, 0x682f,
+ 0x0000, 0x6808, 0xa084, 0xffde, 0x680a, 0xade8, 0x0010, 0x2091,
+ 0x8001, 0x0070, 0x1e75, 0x0078, 0x1e63, 0x8211, 0x0040, 0x1e7c,
+ 0x20a9, 0x0100, 0x0078, 0x1e63, 0x1078, 0x199a, 0x007c, 0x2001,
+ 0x5267, 0x2004, 0xa084, 0x8000, 0x0040, 0x2049, 0x6114, 0x1078,
+ 0x2180, 0x6900, 0xa184, 0x0001, 0x0040, 0x1ea0, 0x6028, 0xa084,
+ 0x00ff, 0x00c0, 0x2041, 0x6800, 0xa084, 0x0001, 0x0040, 0x2049,
+ 0x6803, 0x0000, 0x680b, 0x0000, 0x6807, 0x0000, 0x0078, 0x2051,
+ 0x2011, 0x0001, 0x6020, 0xd0f4, 0x0040, 0x1ea8, 0xa295, 0x0002,
+ 0xd0c4, 0x0040, 0x1ead, 0xa295, 0x0008, 0xd0cc, 0x0040, 0x1eb2,
+ 0xa295, 0x0400, 0x601c, 0xa084, 0x0002, 0x0040, 0x1eb9, 0xa295,
+ 0x0004, 0x602c, 0xa08c, 0x00ff, 0xa182, 0x0002, 0x0048, 0x204d,
+ 0xa182, 0x001b, 0x00c8, 0x204d, 0x0040, 0x204d, 0x690e, 0x602c,
+ 0x8007, 0xa08c, 0x00ff, 0xa182, 0x0002, 0x0048, 0x204d, 0xa182,
+ 0x001b, 0x00c8, 0x204d, 0x0040, 0x204d, 0x6912, 0x6030, 0xa005,
+ 0x00c0, 0x1edc, 0x2001, 0x001e, 0x8000, 0x6816, 0x6028, 0xa084,
+ 0x00ff, 0x0040, 0x2049, 0x6806, 0x6028, 0x8007, 0xa084, 0x00ff,
+ 0x0040, 0x2049, 0x680a, 0x6a02, 0x0078, 0x2051, 0x2001, 0x5240,
+ 0x2004, 0xa086, 0x0007, 0x00c0, 0x1f53, 0x2001, 0x5267, 0x2004,
+ 0xa084, 0x8000, 0x0040, 0x2049, 0x6114, 0x1078, 0x2180, 0x2001,
+ 0x5252, 0x2004, 0x2010, 0x82ff, 0x0040, 0x1f0e, 0xa080, 0x0005,
+ 0x2004, 0xa084, 0x00ff, 0xa106, 0x00c0, 0x1f53, 0x2091, 0x8000,
+ 0x6a04, 0x6b08, 0x6418, 0xa484, 0x0003, 0x0040, 0x1f2d, 0x6128,
+ 0xa18c, 0x00ff, 0x8001, 0x00c0, 0x1f23, 0x2100, 0xa210, 0x0048,
+ 0x1f53, 0x0078, 0x1f2d, 0x8001, 0x00c0, 0x1f53, 0x2100, 0xa212,
+ 0x0048, 0x1f53, 0x82ff, 0x0040, 0x1f53, 0xa484, 0x000c, 0x0040,
+ 0x1f47, 0x6128, 0x810f, 0xa18c, 0x00ff, 0xa082, 0x0004, 0x00c0,
+ 0x1f3f, 0x2100, 0xa318, 0x0048, 0x1f53, 0x0078, 0x1f47, 0xa082,
+ 0x0004, 0x00c0, 0x1f53, 0x2100, 0xa31a, 0x0048, 0x1f53, 0x6030,
+ 0xa005, 0x0040, 0x1f4d, 0x8000, 0x6816, 0x6a06, 0x6b0a, 0x2091,
+ 0x8001, 0x0078, 0x2051, 0x2091, 0x8001, 0x0078, 0x204d, 0x6114,
+ 0x1078, 0x2180, 0x2091, 0x8000, 0x6b08, 0x8318, 0x0048, 0x1f65,
+ 0x6b0a, 0x2091, 0x8001, 0x0078, 0x2060, 0x2091, 0x8001, 0x0078,
+ 0x204d, 0x6024, 0x8007, 0xa084, 0x00ff, 0x0040, 0x1f87, 0xa086,
+ 0x0080, 0x00c0, 0x1fc7, 0x20a9, 0x0008, 0x2069, 0x7610, 0x2091,
+ 0x8000, 0x6800, 0xa084, 0xfcff, 0x6802, 0xade8, 0x0008, 0x0070,
+ 0x1f83, 0x0078, 0x1f79, 0x2091, 0x8001, 0x0078, 0x2051, 0x6028,
+ 0xa015, 0x0040, 0x1fc7, 0x6114, 0x1078, 0x2180, 0x0c7e, 0x0d7e,
+ 0xade8, 0x0007, 0x2091, 0x8000, 0x6800, 0xa00d, 0x0040, 0x1fc3,
+ 0xa206, 0x0040, 0x1f9e, 0x2168, 0x0078, 0x1f94, 0x2160, 0x6000,
+ 0x6802, 0x2c68, 0x1078, 0x19ac, 0x0d7f, 0x6818, 0xa00d, 0x0040,
+ 0x1fbb, 0x2060, 0x6200, 0x6a1a, 0x6a1c, 0x6202, 0x681e, 0x1078,
+ 0x1989, 0x2da0, 0x2198, 0x20a9, 0x0031, 0x53a3, 0x2d60, 0x1078,
+ 0x1ccb, 0x0078, 0x1fbe, 0x6808, 0x8000, 0x680a, 0x2091, 0x8001,
+ 0x0c7f, 0x0078, 0x2060, 0x2091, 0x8001, 0x0d7f, 0x0c7f, 0x0078,
+ 0x2049, 0x6114, 0x1078, 0x2180, 0x6800, 0xa084, 0x0001, 0x0040,
+ 0x2039, 0x2091, 0x8000, 0x6a04, 0x8210, 0x0048, 0x1fdc, 0x6a06,
+ 0x2091, 0x8001, 0x0078, 0x2060, 0x2091, 0x8001, 0x0078, 0x204d,
+ 0x1078, 0x1bc4, 0x00c0, 0x1dd2, 0x6114, 0x1078, 0x2180, 0x60be,
+ 0x60bb, 0x0000, 0x6900, 0xa184, 0x0008, 0x0040, 0x1ff3, 0x6020,
+ 0xa085, 0x0100, 0x6022, 0xa184, 0x0001, 0x0040, 0x2049, 0xa184,
+ 0x0100, 0x00c0, 0x2035, 0xa184, 0x0200, 0x00c0, 0x2031, 0x681c,
+ 0xa005, 0x00c0, 0x203d, 0x6004, 0xa084, 0x00ff, 0xa086, 0x000f,
+ 0x00c0, 0x200c, 0x1078, 0x2163, 0x78df, 0x0000, 0x6004, 0x8007,
+ 0xa084, 0x00ff, 0x78d2, 0x8001, 0x609f, 0x0000, 0x0040, 0x2021,
+ 0x1078, 0x2064, 0x0040, 0x2021, 0x78dc, 0xa085, 0x0100, 0x78de,
+ 0x007c, 0x78d7, 0x0000, 0x78db, 0x0000, 0x6024, 0xa084, 0xff00,
+ 0x6026, 0x1078, 0x3aac, 0x0040, 0x1d4f, 0x1078, 0x1be9, 0x0078,
+ 0x1d4f, 0x2009, 0x0017, 0x0078, 0x2053, 0x2009, 0x000e, 0x0078,
+ 0x2053, 0x2009, 0x0007, 0x0078, 0x2053, 0x2009, 0x0035, 0x0078,
+ 0x2053, 0x2009, 0x003e, 0x0078, 0x2053, 0x2009, 0x0004, 0x0078,
+ 0x2053, 0x2009, 0x0006, 0x0078, 0x2053, 0x2009, 0x0016, 0x0078,
+ 0x2053, 0x2009, 0x0001, 0x6024, 0xa084, 0xff00, 0xa105, 0x6026,
+ 0x2091, 0x8000, 0x1078, 0x1ccb, 0x2091, 0x8001, 0x0078, 0x1d4f,
+ 0x1078, 0x199a, 0x0078, 0x1d4f, 0x78d4, 0xa06d, 0x00c0, 0x206f,
+ 0x2c00, 0x78d6, 0x78da, 0x609f, 0x0000, 0x0078, 0x207b, 0x2c00,
+ 0x689e, 0x609f, 0x0000, 0x78d6, 0x2d00, 0x6002, 0x78d8, 0xad06,
+ 0x00c0, 0x207b, 0x6002, 0x78d0, 0x8001, 0x78d2, 0x00c0, 0x2087,
+ 0x78dc, 0xa084, 0xfeff, 0x78de, 0x78d8, 0x2060, 0xa006, 0x007c,
+ 0xa02e, 0x2530, 0x611c, 0x61a2, 0xa184, 0xe1ff, 0x601e, 0xa184,
+ 0x0060, 0x0040, 0x2097, 0x0e7e, 0x1078, 0x48d3, 0x0e7f, 0x6596,
+ 0x65a6, 0x669a, 0x66aa, 0x60af, 0x0000, 0x60b3, 0x0000, 0x6714,
+ 0x1078, 0x19c5, 0x2091, 0x8000, 0x60a0, 0xa084, 0x8000, 0x00c0,
+ 0x20be, 0x6808, 0xa084, 0x0001, 0x0040, 0x20be, 0x2091, 0x8001,
+ 0x1078, 0x1a31, 0x2091, 0x8000, 0x1078, 0x1ccb, 0x2091, 0x8001,
+ 0x78d7, 0x0000, 0x78db, 0x0000, 0x0078, 0x2130, 0x6024, 0xa096,
+ 0x0001, 0x00c0, 0x20c5, 0x8000, 0x6026, 0x6a10, 0x6814, 0x2091,
+ 0x8001, 0xa202, 0x0048, 0x20d4, 0x0040, 0x20d4, 0x2039, 0x0200,
+ 0x1078, 0x2131, 0x0078, 0x2130, 0x2c08, 0x2091, 0x8000, 0x60a0,
+ 0xa084, 0x8000, 0x0040, 0x2101, 0x6800, 0xa065, 0x0040, 0x2106,
+ 0x6a04, 0x0e7e, 0x2071, 0x5240, 0x7000, 0xa084, 0x0001, 0x0040,
+ 0x20fb, 0x7048, 0xa206, 0x00c0, 0x20fb, 0x6b04, 0x231c, 0x2160,
+ 0x6302, 0x2300, 0xa005, 0x00c0, 0x20f6, 0x6902, 0x2260, 0x6102,
+ 0x0e7f, 0x0078, 0x210d, 0x2160, 0x6202, 0x6906, 0x0e7f, 0x0078,
+ 0x210d, 0x6800, 0xa065, 0x0040, 0x2106, 0x6102, 0x6902, 0x00c0,
+ 0x210a, 0x6906, 0x2160, 0x6003, 0x0000, 0x2160, 0x60a0, 0xa084,
+ 0x8000, 0x0040, 0x2117, 0x6808, 0xa084, 0xfffc, 0x680a, 0x6810,
+ 0x8000, 0x6812, 0x2091, 0x8001, 0x6808, 0xa08c, 0x0040, 0x0040,
+ 0x2126, 0xa086, 0x0040, 0x680a, 0x1078, 0x1a42, 0x2091, 0x8000,
+ 0x1078, 0x226f, 0x2091, 0x8001, 0x78db, 0x0000, 0x78d7, 0x0000,
+ 0x007c, 0x6008, 0xa705, 0x600a, 0x2091, 0x8000, 0x1078, 0x1ccb,
+ 0x2091, 0x8001, 0x78d8, 0xa065, 0x0040, 0x2144, 0x609c, 0x78da,
+ 0x609f, 0x0000, 0x0078, 0x2134, 0x78d7, 0x0000, 0x78db, 0x0000,
+ 0x007c, 0x7990, 0x7894, 0x8000, 0xa10a, 0x00c8, 0x2150, 0xa006,
+ 0x7896, 0x70d2, 0x7804, 0xa005, 0x0040, 0x215e, 0x8001, 0x7806,
+ 0x00c0, 0x215e, 0x0068, 0x215e, 0x2091, 0x4080, 0x007c, 0x2039,
+ 0x2177, 0x0078, 0x2165, 0x2039, 0x217d, 0x2704, 0xa005, 0x0040,
+ 0x2176, 0xac00, 0x2068, 0x6b08, 0x6c0c, 0x6910, 0x6a14, 0x690a,
+ 0x6a0e, 0x6b12, 0x6c16, 0x8738, 0x0078, 0x2165, 0x007c, 0x0003,
+ 0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0015, 0x001b, 0x0000,
+ 0x0c7e, 0x1078, 0x3c3b, 0x2c68, 0x0c7f, 0x007c, 0x0010, 0x21f7,
+ 0x0068, 0x21f7, 0x2029, 0x0000, 0x78cb, 0x0000, 0x788c, 0xa065,
+ 0x0040, 0x21f0, 0x2009, 0x5274, 0x2104, 0xa084, 0x0001, 0x0040,
+ 0x21be, 0x6004, 0xa086, 0x0103, 0x00c0, 0x21be, 0x6018, 0xa005,
+ 0x00c0, 0x21be, 0x6014, 0xa005, 0x00c0, 0x21be, 0x0d7e, 0x2069,
+ 0x0000, 0x6818, 0xa084, 0x0001, 0x00c0, 0x21bd, 0x600c, 0x70c6,
+ 0x6010, 0x70ca, 0x70c3, 0x8020, 0x681b, 0x0001, 0x2091, 0x4080,
+ 0x0d7f, 0x1078, 0x1cf2, 0x0078, 0x21f5, 0x0d7f, 0x1078, 0x21f8,
+ 0x0040, 0x21f0, 0x6204, 0xa294, 0x00ff, 0xa296, 0x0003, 0x0040,
+ 0x21d0, 0x6204, 0xa296, 0x0110, 0x00c0, 0x21de, 0x78cb, 0x0001,
+ 0x6204, 0xa294, 0xff00, 0x8217, 0x8211, 0x0040, 0x21de, 0x85ff,
+ 0x00c0, 0x21f0, 0x8210, 0xa202, 0x00c8, 0x21f0, 0x057e, 0x1078,
+ 0x2207, 0x057f, 0x0040, 0x21eb, 0x78e0, 0xa086, 0x0003, 0x0040,
+ 0x21f0, 0x0078, 0x21de, 0x8528, 0x78c8, 0xa005, 0x0040, 0x218e,
+ 0x85ff, 0x0040, 0x21f7, 0x2091, 0x4080, 0x78b0, 0x70d6, 0x007c,
+ 0x7bac, 0x79b0, 0x70d4, 0xa102, 0x00c0, 0x2201, 0x2300, 0xa005,
+ 0x007c, 0x0048, 0x2205, 0xa302, 0x007c, 0x8002, 0x007c, 0x2001,
+ 0x04fd, 0x2004, 0xa082, 0x0005, 0x00c8, 0x2221, 0x2091, 0x8000,
+ 0x2071, 0x0020, 0x7004, 0xa005, 0x00c0, 0x2256, 0x7008, 0x7208,
+ 0xa206, 0x00c0, 0x2256, 0xa286, 0x0008, 0x00c0, 0x2256, 0x2071,
+ 0x0010, 0x1078, 0x225b, 0x2009, 0x0020, 0x6004, 0xa086, 0x0103,
+ 0x00c0, 0x2230, 0x6028, 0xa005, 0x00c0, 0x2230, 0x2009, 0x000c,
+ 0x1078, 0x1976, 0x0040, 0x2249, 0x78c4, 0x8000, 0x78c6, 0xa086,
+ 0x0002, 0x00c0, 0x2256, 0x2091, 0x8000, 0x78e3, 0x0003, 0x78c7,
+ 0x0000, 0x78cc, 0xa085, 0x0300, 0x78ce, 0x2091, 0x8001, 0x0078,
+ 0x2256, 0x78c7, 0x0000, 0x1078, 0x1cf2, 0x79ac, 0x78b0, 0x8000,
+ 0xa10a, 0x00c8, 0x2254, 0xa006, 0x78b2, 0xa006, 0x2071, 0x0010,
+ 0x2091, 0x8001, 0x007c, 0x8107, 0x8004, 0x8004, 0x7ab8, 0x7bb4,
+ 0x7cc0, 0x7dbc, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9,
+ 0x0000, 0x007c, 0x2009, 0x525b, 0x2091, 0x8000, 0x200a, 0x0f7e,
+ 0x0e7e, 0x2071, 0x5240, 0x7000, 0xa086, 0x0000, 0x00c0, 0x2289,
+ 0x2009, 0x5212, 0x2104, 0xa005, 0x00c0, 0x2289, 0x2079, 0x0100,
+ 0x7830, 0xa084, 0x00c0, 0x00c0, 0x2289, 0x0018, 0x2289, 0x781b,
+ 0x004b, 0x0e7f, 0x0f7f, 0x007c, 0x0f7e, 0x0e7e, 0x2071, 0x5240,
+ 0x2091, 0x8000, 0x7000, 0xa086, 0x0000, 0x00c0, 0x22a2, 0x2079,
+ 0x0100, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x22a2, 0x0018, 0x22a2,
+ 0x781b, 0x004d, 0x2091, 0x8001, 0x0e7f, 0x0f7f, 0x007c, 0x127e,
+ 0x2091, 0x2300, 0x2071, 0x5240, 0x2079, 0x0100, 0x784b, 0x000f,
+ 0x0098, 0x22b5, 0x7838, 0x0078, 0x22ae, 0x20a9, 0x0040, 0x7800,
+ 0xa082, 0x0004, 0x0048, 0x22be, 0x20a9, 0x0060, 0x789b, 0x0000,
+ 0x78af, 0x0000, 0x78af, 0x0000, 0x0070, 0x22c8, 0x0078, 0x22c0,
+ 0x7800, 0xa082, 0x0004, 0x0048, 0x22d7, 0x70b7, 0x0093, 0x2019,
+ 0x4ff0, 0x1078, 0x2313, 0x702f, 0x8001, 0x0078, 0x22e3, 0x70b7,
+ 0x0000, 0x2019, 0x4e70, 0x1078, 0x2313, 0x2019, 0x4eaf, 0x1078,
+ 0x2313, 0x702f, 0x8000, 0x7003, 0x0000, 0x1078, 0x2420, 0x7004,
+ 0xa084, 0x000f, 0x017e, 0x2009, 0x04fd, 0x210c, 0xa18a, 0x0005,
+ 0x0048, 0x22f8, 0x0038, 0x22fe, 0xa085, 0x6280, 0x0078, 0x2300,
+ 0x0028, 0x22fe, 0xa085, 0x6280, 0x0078, 0x2300, 0xa085, 0x62c0,
+ 0x017f, 0x7806, 0x780f, 0xb204, 0x7843, 0x00d8, 0x7853, 0x0080,
+ 0x780b, 0x0008, 0x7047, 0x0008, 0x7053, 0x527f, 0x704f, 0x0000,
+ 0x127f, 0x2000, 0x007c, 0x137e, 0x147e, 0x157e, 0x047e, 0x20a1,
+ 0x012b, 0x2304, 0xa005, 0x789a, 0x0040, 0x2333, 0x8318, 0x2324,
+ 0x8318, 0x2398, 0x24a8, 0xa484, 0xff00, 0x0040, 0x232b, 0xa482,
+ 0x0100, 0x20a9, 0x0100, 0x2020, 0x53a6, 0xa005, 0x00c0, 0x2322,
+ 0x3318, 0x0078, 0x2319, 0x047f, 0x157f, 0x147f, 0x137f, 0x007c,
+ 0xa18c, 0x000f, 0x2011, 0x0101, 0x2204, 0xa084, 0xfff0, 0xa105,
+ 0x2012, 0x1078, 0x2420, 0x007c, 0x2011, 0x0101, 0x20a9, 0x0009,
+ 0x810b, 0x0070, 0x234d, 0x0078, 0x2348, 0xa18c, 0x0e00, 0x2204,
+ 0xa084, 0xf1ff, 0xa105, 0x2012, 0x007c, 0x2009, 0x0101, 0x20a9,
+ 0x0005, 0x8213, 0x0070, 0x235e, 0x0078, 0x2359, 0xa294, 0x00e0,
+ 0x2104, 0xa084, 0xff1f, 0xa205, 0x200a, 0x007c, 0x2011, 0x0101,
+ 0x20a9, 0x000c, 0x810b, 0x0070, 0x236f, 0x0078, 0x236a, 0xa18c,
+ 0xf000, 0x2204, 0xa084, 0x0fff, 0xa105, 0x2012, 0x007c, 0x2011,
+ 0x0102, 0x2204, 0xa084, 0xffcf, 0xa105, 0x2012, 0x007c, 0x8103,
+ 0x8003, 0xa080, 0x0020, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x62ac,
+ 0x63ac, 0x0c7f, 0x007c, 0x8103, 0x8003, 0xa080, 0x0022, 0x0c7e,
+ 0x2061, 0x0100, 0x609a, 0x60a4, 0xa084, 0xffdf, 0x60ae, 0x0c7f,
+ 0x007c, 0x8103, 0x8003, 0xa080, 0x0022, 0x0c7e, 0x2061, 0x0100,
+ 0x609a, 0x60a4, 0xa085, 0x0020, 0x60ae, 0x0c7f, 0x007c, 0x8103,
+ 0x8003, 0xa080, 0x0020, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x60a4,
+ 0x62ae, 0x2010, 0x60a4, 0x63ae, 0x2018, 0x0c7f, 0x007c, 0x2091,
+ 0x8000, 0x0c7e, 0x0e7e, 0x6818, 0xa005, 0x0040, 0x23fe, 0x2061,
+ 0x7600, 0x1078, 0x2406, 0x0040, 0x23e8, 0x20a9, 0x0000, 0x2061,
+ 0x7500, 0x0c7e, 0x1078, 0x2406, 0x0040, 0x23d6, 0x0c7f, 0x8c60,
+ 0x0070, 0x23d4, 0x0078, 0x23c9, 0x0078, 0x23fe, 0x007f, 0xa082,
+ 0x7500, 0x2071, 0x5240, 0x7086, 0x7182, 0x2001, 0x0004, 0x706e,
+ 0x7093, 0x000f, 0x7073, 0x0000, 0x1078, 0x226a, 0x0078, 0x23fa,
+ 0x60c0, 0xa005, 0x00c0, 0x23fe, 0x2071, 0x5240, 0x7182, 0x2c00,
+ 0x708a, 0x2001, 0x0006, 0x706e, 0x7093, 0x000f, 0x7073, 0x0000,
+ 0x1078, 0x226a, 0x2001, 0x0000, 0x0078, 0x2400, 0x2001, 0x0001,
+ 0x2091, 0x8001, 0xa005, 0x0e7f, 0x0c7f, 0x007c, 0x2c04, 0xa005,
+ 0x0040, 0x241d, 0x2060, 0x600c, 0xa306, 0x00c0, 0x241a, 0x6010,
+ 0xa206, 0x00c0, 0x241a, 0x6014, 0xa106, 0x00c0, 0x241a, 0xa006,
+ 0x0078, 0x241f, 0x6000, 0x0078, 0x2407, 0xa085, 0x0001, 0x007c,
+ 0x2011, 0x5241, 0x220c, 0xa18c, 0x000f, 0x2011, 0x013b, 0x2204,
+ 0xa084, 0x0100, 0x0040, 0x2436, 0x2021, 0xff04, 0x2122, 0x810b,
+ 0x810b, 0x810b, 0x810b, 0xa18d, 0x0f00, 0x2104, 0x007c, 0x0e7e,
+ 0x68e4, 0xa08c, 0x0020, 0x0040, 0x248a, 0xa084, 0x0006, 0x00c0,
+ 0x248a, 0x6014, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
+ 0xa0f0, 0x5480, 0x7004, 0xa084, 0x000a, 0x00c0, 0x248a, 0x7108,
+ 0xa194, 0xff00, 0x0040, 0x248a, 0xa18c, 0x00ff, 0x2001, 0x000c,
+ 0xa106, 0x0040, 0x2471, 0x2001, 0x0012, 0xa106, 0x0040, 0x2475,
+ 0x2001, 0x0014, 0xa106, 0x0040, 0x2479, 0x2001, 0x0019, 0xa106,
+ 0x0040, 0x247d, 0x2001, 0x0032, 0xa106, 0x0040, 0x2481, 0x0078,
+ 0x2485, 0x2009, 0x0012, 0x0078, 0x2487, 0x2009, 0x0014, 0x0078,
+ 0x2487, 0x2009, 0x0019, 0x0078, 0x2487, 0x2009, 0x0020, 0x0078,
+ 0x2487, 0x2009, 0x003f, 0x0078, 0x2487, 0x2011, 0x0000, 0x2100,
+ 0xa205, 0x700a, 0x0e7f, 0x007c, 0x0068, 0x248c, 0x2091, 0x8000,
+ 0x2071, 0x0000, 0x007e, 0x7018, 0xa084, 0x0001, 0x00c0, 0x2493,
+ 0x007f, 0x2071, 0x0010, 0x70ca, 0x007f, 0x70c6, 0x70c3, 0x8002,
+ 0x70db, 0x0741, 0x70df, 0x0006, 0x2071, 0x0000, 0x701b, 0x0001,
+ 0x2091, 0x4080, 0x0078, 0x24aa, 0x107e, 0x007e, 0x127e, 0x2091,
+ 0x2300, 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x77c2, 0x74c6, 0x76ca,
+ 0x75ce, 0xa594, 0x003f, 0xa49c, 0x0003, 0xa484, 0x000f, 0x0079,
+ 0x24c1, 0x24d3, 0x24d3, 0x24d3, 0x280d, 0x3a09, 0x24d1, 0x2502,
+ 0x250c, 0x24d1, 0x24d1, 0x24d1, 0x24d1, 0x24d1, 0x24d1, 0x24d1,
+ 0x24d1, 0x1078, 0x248c, 0x8507, 0xa084, 0x001f, 0x0079, 0x24d8,
+ 0x2516, 0x280d, 0x29c7, 0x2ac4, 0x2aec, 0x2d8c, 0x3037, 0x309a,
+ 0x30fb, 0x3180, 0x3238, 0x32d6, 0x2502, 0x28e9, 0x300c, 0x24f8,
+ 0x3dac, 0x3dcc, 0x3f8f, 0x3f9b, 0x4074, 0x24f8, 0x24f8, 0x4149,
+ 0x414d, 0x3daa, 0x24f8, 0x3efa, 0x24f8, 0x3c5e, 0x250c, 0x24f8,
+ 0x1078, 0x248c, 0x0018, 0x24b1, 0x127f, 0x2091, 0x8001, 0x007f,
+ 0x107f, 0x007c, 0x2019, 0x4f49, 0x1078, 0x2313, 0x702f, 0x0001,
+ 0x781b, 0x004f, 0x0078, 0x24fa, 0x2019, 0x4eaf, 0x1078, 0x2313,
+ 0x702f, 0x8000, 0x781b, 0x00cd, 0x0078, 0x24fa, 0x7242, 0x2009,
+ 0x520f, 0x200b, 0x0000, 0xa584, 0x0001, 0x00c0, 0x3c72, 0x0040,
+ 0x2533, 0x1078, 0x248c, 0x7003, 0x0000, 0x704b, 0x0000, 0x7043,
+ 0x0000, 0x7037, 0x0000, 0x1078, 0x39e0, 0x0018, 0x24b1, 0x2009,
+ 0x520f, 0x200b, 0x0000, 0x7068, 0xa005, 0x00c0, 0x25fe, 0x706c,
+ 0xa084, 0x0007, 0x0079, 0x253c, 0x2635, 0x2544, 0x2550, 0x256d,
+ 0x258f, 0x25dc, 0x25b5, 0x2544, 0x1078, 0x39c8, 0x2009, 0x0048,
+ 0x1078, 0x2ed8, 0x00c0, 0x254e, 0x7003, 0x0004, 0x0078, 0x24fa,
+ 0x1078, 0x39c8, 0x00c0, 0x256b, 0x7080, 0x8007, 0x7882, 0x789b,
+ 0x0010, 0x78ab, 0x000c, 0x789b, 0x0060, 0x78ab, 0x0001, 0x785b,
+ 0x0004, 0x2009, 0x00dd, 0x1078, 0x2ecc, 0x00c0, 0x256b, 0x7003,
+ 0x0004, 0x7093, 0x000f, 0x0078, 0x24fa, 0x1078, 0x39c8, 0x00c0,
+ 0x258d, 0x7180, 0x8107, 0x7882, 0x789b, 0x0010, 0xa18c, 0x001f,
+ 0xa18d, 0x00c0, 0x79aa, 0x78ab, 0x0006, 0x789b, 0x0060, 0x78ab,
+ 0x0002, 0x785b, 0x0004, 0x2009, 0x00dd, 0x1078, 0x2ecc, 0x00c0,
+ 0x258d, 0x7003, 0x0004, 0x7093, 0x000f, 0x0078, 0x24fa, 0x1078,
+ 0x39c8, 0x00c0, 0x25b3, 0x7180, 0x8107, 0x7882, 0x789b, 0x0010,
+ 0xa18c, 0x001f, 0xa18d, 0x00c0, 0x79aa, 0x78ab, 0x0020, 0x7184,
+ 0x79aa, 0x78ab, 0x000d, 0x789b, 0x0060, 0x78ab, 0x0004, 0x785b,
+ 0x0004, 0x2009, 0x00dd, 0x1078, 0x2ecc, 0x00c0, 0x25b3, 0x7003,
+ 0x0004, 0x7093, 0x000f, 0x0078, 0x24fa, 0x1078, 0x39c8, 0x00c0,
+ 0x25da, 0x7180, 0x8107, 0x7882, 0x789b, 0x0010, 0xa18c, 0x001f,
+ 0xa18d, 0x00c0, 0x79aa, 0x78ab, 0x0006, 0x789b, 0x0060, 0x78ab,
+ 0x0002, 0x785b, 0x0004, 0x2009, 0x00dd, 0x1078, 0x2ecc, 0x00c0,
+ 0x25da, 0x7088, 0x708b, 0x0000, 0x2068, 0x704a, 0x7003, 0x0002,
+ 0x7093, 0x000f, 0x0078, 0x24fa, 0x1078, 0x39c8, 0x00c0, 0x24fa,
+ 0x7088, 0x2068, 0x6f14, 0x1078, 0x38bd, 0x2c50, 0x1078, 0x3a7a,
+ 0x789b, 0x0010, 0x6814, 0xa084, 0x001f, 0xa085, 0x0080, 0x78aa,
+ 0x6e1c, 0x2041, 0x0001, 0x708c, 0xa084, 0x0400, 0x2001, 0x0004,
+ 0x0040, 0x25fc, 0x2001, 0x0006, 0x0078, 0x271d, 0x1078, 0x39c8,
+ 0x00c0, 0x24fa, 0x789b, 0x0010, 0x7068, 0x2068, 0x6f14, 0x1078,
+ 0x38bd, 0x2c50, 0x1078, 0x3a7a, 0x6008, 0xa085, 0x0010, 0x600a,
+ 0x6824, 0xa005, 0x0040, 0x261c, 0xa082, 0x0006, 0x0048, 0x261a,
+ 0x0078, 0x261c, 0x6827, 0x0005, 0x6b14, 0xa39c, 0x001f, 0xa39d,
+ 0x00c0, 0x7058, 0xa084, 0x8000, 0x0040, 0x262a, 0xa684, 0x0001,
+ 0x0040, 0x262c, 0xa39c, 0xffbf, 0x7baa, 0x2031, 0x0020, 0x2041,
+ 0x0001, 0x2001, 0x0003, 0x0078, 0x271d, 0x0018, 0x24b1, 0x744c,
+ 0xa485, 0x0000, 0x0040, 0x264f, 0xa080, 0x5280, 0x2030, 0x7150,
+ 0x8108, 0xa12a, 0x0048, 0x2646, 0x2009, 0x5280, 0x2164, 0x6504,
+ 0x85ff, 0x00c0, 0x2660, 0x8421, 0x00c0, 0x2640, 0x7152, 0x7003,
+ 0x0000, 0x704b, 0x0000, 0x7040, 0xa005, 0x0040, 0x3c72, 0x0078,
+ 0x24fa, 0x764c, 0xa6b0, 0x5280, 0x7150, 0x2600, 0x0078, 0x264b,
+ 0x7152, 0x2568, 0x2558, 0x754a, 0x2c50, 0x6034, 0xa085, 0x0000,
+ 0x00c0, 0x265d, 0x6708, 0x773a, 0xa784, 0x033f, 0x0040, 0x2696,
+ 0xa784, 0x0021, 0x00c0, 0x265d, 0xa784, 0x0002, 0x0040, 0x267f,
+ 0xa784, 0x0004, 0x0040, 0x265d, 0xa7bc, 0xfffb, 0x670a, 0xa784,
+ 0x0008, 0x00c0, 0x265d, 0xa784, 0x0010, 0x00c0, 0x265d, 0xa784,
+ 0x0200, 0x00c0, 0x265d, 0xa784, 0x0100, 0x0040, 0x2696, 0x6018,
+ 0xa005, 0x00c0, 0x265d, 0xa7bc, 0xfeff, 0x670a, 0x6823, 0x0000,
+ 0x6e1c, 0xa684, 0x000e, 0x6118, 0x0040, 0x26a6, 0x601c, 0xa102,
+ 0x0048, 0x26a9, 0x0040, 0x26a9, 0x0078, 0x2659, 0x81ff, 0x00c0,
+ 0x2659, 0x68c3, 0x0000, 0xa784, 0x0080, 0x00c0, 0x26b1, 0x700c,
+ 0x6022, 0xa7bc, 0xff7f, 0x670a, 0x1078, 0x3a7a, 0x0018, 0x24b1,
+ 0x789b, 0x0010, 0xa046, 0x1078, 0x39c8, 0x00c0, 0x24fa, 0x6b14,
+ 0xa39c, 0x001f, 0xa39d, 0x00c0, 0x7058, 0xa084, 0x8000, 0x0040,
+ 0x26cd, 0xa684, 0x0001, 0x0040, 0x26cf, 0xa39c, 0xffbf, 0xa684,
+ 0x0010, 0x0040, 0x26d5, 0xa39d, 0x0020, 0x7baa, 0x8840, 0xa684,
+ 0x000e, 0x00c0, 0x26e0, 0xa7bd, 0x0010, 0x670a, 0x0078, 0x271b,
+ 0x7158, 0xa18c, 0x0800, 0x0040, 0x34cb, 0x2011, 0x0020, 0xa684,
+ 0x0008, 0x00c0, 0x26f1, 0x8210, 0xa684, 0x0002, 0x00c0, 0x26f1,
+ 0x8210, 0x7aaa, 0x8840, 0x1078, 0x39e0, 0x6a14, 0x610c, 0x8108,
+ 0xa18c, 0x00ff, 0xa1e0, 0x7500, 0x2c64, 0x8cff, 0x0040, 0x2712,
+ 0x6014, 0xa206, 0x00c0, 0x26fc, 0x60b8, 0x8001, 0x60ba, 0x00c0,
+ 0x26f7, 0x0c7e, 0x2a60, 0x6008, 0xa085, 0x0100, 0x600a, 0x0c7f,
+ 0x0078, 0x2635, 0x1078, 0x39c8, 0x00c0, 0x24fa, 0x2a60, 0x610e,
+ 0x79aa, 0x8840, 0x7132, 0x2001, 0x0001, 0x007e, 0x715c, 0xa184,
+ 0x0018, 0x0040, 0x2738, 0xa184, 0x0010, 0x0040, 0x272b, 0x1078,
+ 0x36d0, 0x00c0, 0x275b, 0xa184, 0x0008, 0x0040, 0x2738, 0x69a0,
+ 0xa184, 0x0600, 0x00c0, 0x2738, 0x1078, 0x35bb, 0x0078, 0x275b,
+ 0x69a0, 0xa184, 0x0800, 0x0040, 0x274f, 0x0c7e, 0x027e, 0x2960,
+ 0x6000, 0xa085, 0x2000, 0x6002, 0x6104, 0xa18d, 0x0010, 0x6106,
+ 0x027f, 0x0c7f, 0x1078, 0x36d0, 0x00c0, 0x275b, 0x69a0, 0xa184,
+ 0x0200, 0x0040, 0x2757, 0x1078, 0x360c, 0x0078, 0x275b, 0xa184,
+ 0x0400, 0x00c0, 0x2734, 0x69a0, 0xa184, 0x1000, 0x0040, 0x2766,
+ 0x6914, 0xa18c, 0xff00, 0x810f, 0x1078, 0x238b, 0x007f, 0x7002,
+ 0xa68c, 0x00e0, 0xa684, 0x0060, 0x0040, 0x2774, 0xa086, 0x0060,
+ 0x00c0, 0x2774, 0xa18d, 0x4000, 0x88ff, 0x0040, 0x2779, 0xa18d,
+ 0x0004, 0x795a, 0x69b6, 0x789b, 0x0060, 0x2800, 0x78aa, 0x789b,
+ 0x0061, 0x6818, 0xa08d, 0x8000, 0xa084, 0x7fff, 0x691a, 0xa68c,
+ 0x0080, 0x0040, 0x2798, 0x7097, 0x0000, 0xa08a, 0x000d, 0x0050,
+ 0x2796, 0xa08a, 0x000c, 0x7196, 0x2001, 0x000c, 0x800c, 0x719a,
+ 0x78aa, 0x8008, 0x810c, 0x0040, 0x34d1, 0xa18c, 0x00f8, 0x00c0,
+ 0x34d1, 0x157e, 0x137e, 0x147e, 0x20a1, 0x012b, 0x789b, 0x0000,
+ 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f, 0x137f,
+ 0x157f, 0x6814, 0x8007, 0x7882, 0x6d94, 0x7dd6, 0x7dde, 0x6e98,
+ 0x7ed2, 0x7eda, 0x1078, 0x39c8, 0x00c0, 0x27cf, 0x702c, 0x8003,
+ 0x0048, 0x27c8, 0x2019, 0x4eaf, 0x1078, 0x2313, 0x702f, 0x8000,
+ 0x7830, 0xa084, 0x00c0, 0x00c0, 0x27cf, 0x0098, 0x27d7, 0x6008,
+ 0xa084, 0xffef, 0x600a, 0x1078, 0x39e0, 0x0078, 0x2523, 0x7200,
+ 0xa284, 0x0007, 0xa086, 0x0001, 0x00c0, 0x27e4, 0x781b, 0x004f,
+ 0x1078, 0x39e0, 0x0078, 0x27f5, 0x6ab4, 0xa295, 0x2000, 0x7a5a,
+ 0x781b, 0x004f, 0x1078, 0x39e0, 0x7200, 0x2500, 0xa605, 0x0040,
+ 0x27f5, 0xa284, 0x0007, 0x1079, 0x2803, 0xad80, 0x0009, 0x7036,
+ 0xa284, 0x0007, 0xa086, 0x0001, 0x00c0, 0x24fa, 0x6018, 0x8000,
+ 0x601a, 0x0078, 0x24fa, 0x280b, 0x4b4b, 0x4b4b, 0x4b3a, 0x4b4b,
+ 0x280b, 0x4b3a, 0x280b, 0x1078, 0x248c, 0x1078, 0x39c8, 0x0f7e,
+ 0x2079, 0x5200, 0x78cc, 0x0f7f, 0xa084, 0x0001, 0x0040, 0x2831,
+ 0x706c, 0xa086, 0x0001, 0x00c0, 0x2820, 0x706e, 0x0078, 0x28c4,
+ 0x706c, 0xa086, 0x0005, 0x00c0, 0x282f, 0x7088, 0x2068, 0x681b,
+ 0x0004, 0x6817, 0x0000, 0x6820, 0xa085, 0x0008, 0x6822, 0x706f,
+ 0x0000, 0x2011, 0x0004, 0x716c, 0xa186, 0x0001, 0x0040, 0x2852,
+ 0xa186, 0x0007, 0x00c0, 0x2842, 0x2009, 0x5238, 0x200b, 0x0005,
+ 0x0078, 0x2852, 0x2009, 0x5213, 0x2104, 0x2009, 0x5212, 0x200a,
+ 0x2009, 0x5238, 0x200b, 0x0001, 0x706f, 0x0000, 0x7073, 0x0001,
+ 0x0078, 0x2854, 0x706f, 0x0000, 0x1078, 0x4887, 0x157e, 0x20a9,
+ 0x0010, 0x2039, 0x0000, 0x1078, 0x37b0, 0xa7b8, 0x0100, 0x0070,
+ 0x2863, 0x0078, 0x285b, 0x157f, 0x7000, 0x0079, 0x2867, 0x2895,
+ 0x287c, 0x287c, 0x286f, 0x2895, 0x2895, 0x2895, 0x2895, 0x2021,
+ 0x525a, 0x2404, 0xa005, 0x0040, 0x2895, 0xad06, 0x00c0, 0x287c,
+ 0x6800, 0x2022, 0x0078, 0x288c, 0x6820, 0xa084, 0x0001, 0x00c0,
+ 0x2888, 0x6f14, 0x1078, 0x38bd, 0x1078, 0x34a2, 0x0078, 0x288c,
+ 0x7060, 0x2060, 0x6800, 0x6002, 0x6a1a, 0x6817, 0x0000, 0x6820,
+ 0xa085, 0x0008, 0x6822, 0x1078, 0x1cdc, 0x2021, 0x7600, 0x1078,
+ 0x28d1, 0x2021, 0x525a, 0x1078, 0x28d1, 0x157e, 0x20a9, 0x0000,
+ 0x2021, 0x7500, 0x1078, 0x28d1, 0x8420, 0x0070, 0x28a9, 0x0078,
+ 0x28a2, 0x2061, 0x5500, 0x2021, 0x0002, 0x20a9, 0x0100, 0x6018,
+ 0x6110, 0x81ff, 0x0040, 0x28b8, 0xa102, 0x0050, 0x28b8, 0x6012,
+ 0x601b, 0x0000, 0xace0, 0x0010, 0x0070, 0x28c0, 0x0078, 0x28af,
+ 0x8421, 0x00c0, 0x28ad, 0x157f, 0x709c, 0xa084, 0x8000, 0x0040,
+ 0x28cb, 0x1078, 0x3ace, 0x7003, 0x0000, 0x704b, 0x0000, 0x0078,
+ 0x24fa, 0x047e, 0x2404, 0xa005, 0x0040, 0x28e5, 0x2068, 0x6800,
+ 0x007e, 0x6a1a, 0x6817, 0x0000, 0x6820, 0xa085, 0x0008, 0x6822,
+ 0x1078, 0x1cdc, 0x007f, 0x0078, 0x28d3, 0x047f, 0x2023, 0x0000,
+ 0x007c, 0xa282, 0x0003, 0x0050, 0x28ef, 0x1078, 0x248c, 0x2300,
+ 0x0079, 0x28f2, 0x28f5, 0x2968, 0x2985, 0xa282, 0x0002, 0x0040,
+ 0x28fb, 0x1078, 0x248c, 0x706c, 0x706f, 0x0000, 0x7093, 0x0000,
+ 0x0079, 0x2902, 0x290a, 0x290a, 0x290c, 0x2940, 0x34d7, 0x290a,
+ 0x2940, 0x290a, 0x1078, 0x248c, 0x7780, 0x1078, 0x37b0, 0x7780,
+ 0xa7bc, 0x0f00, 0x1078, 0x38bd, 0x6018, 0xa005, 0x0040, 0x2937,
+ 0x2021, 0x7600, 0x2009, 0x0004, 0x2011, 0x0010, 0x1078, 0x29a0,
+ 0x0040, 0x2937, 0x157e, 0x20a9, 0x0000, 0x2021, 0x7500, 0x047e,
+ 0x2009, 0x0004, 0x2011, 0x0010, 0x1078, 0x29a0, 0x047f, 0x0040,
+ 0x2936, 0x8420, 0x0070, 0x2936, 0x0078, 0x2927, 0x157f, 0x8738,
+ 0xa784, 0x001f, 0x00c0, 0x2912, 0x0078, 0x2523, 0x0078, 0x2523,
+ 0x7780, 0x1078, 0x38bd, 0x6018, 0xa005, 0x0040, 0x2966, 0x2021,
+ 0x7600, 0x2009, 0x0005, 0x2011, 0x0020, 0x1078, 0x29a0, 0x0040,
+ 0x2966, 0x157e, 0x20a9, 0x0000, 0x2021, 0x7500, 0x047e, 0x2009,
+ 0x0005, 0x2011, 0x0020, 0x1078, 0x29a0, 0x047f, 0x0040, 0x2965,
+ 0x8420, 0x0070, 0x2965, 0x0078, 0x2956, 0x157f, 0x0078, 0x2523,
+ 0x2200, 0x0079, 0x296b, 0x296e, 0x2970, 0x2970, 0x1078, 0x248c,
+ 0x2009, 0x0012, 0x706c, 0xa086, 0x0002, 0x0040, 0x2979, 0x2009,
+ 0x000e, 0x6818, 0xa084, 0x8000, 0x0040, 0x297f, 0x691a, 0x706f,
+ 0x0000, 0x7073, 0x0001, 0x0078, 0x3956, 0x2200, 0x0079, 0x2988,
+ 0x298d, 0x2970, 0x298b, 0x1078, 0x248c, 0x1078, 0x4887, 0x7000,
+ 0xa086, 0x0001, 0x00c0, 0x3467, 0x1078, 0x34b8, 0x6008, 0xa084,
+ 0xffef, 0x600a, 0x1078, 0x345a, 0x0040, 0x3467, 0x0078, 0x2635,
+ 0x2404, 0xa005, 0x0040, 0x29c3, 0x2068, 0x2d04, 0x007e, 0x6814,
+ 0xa706, 0x0040, 0x29af, 0x2d20, 0x007f, 0x0078, 0x29a1, 0x007f,
+ 0x2022, 0x691a, 0x6817, 0x0000, 0x6820, 0xa205, 0x6822, 0x1078,
+ 0x1cdc, 0x6010, 0x8001, 0x6012, 0x6008, 0xa084, 0xffef, 0x600a,
+ 0x1078, 0x34b8, 0x007c, 0xa085, 0x0001, 0x0078, 0x29c2, 0x2300,
+ 0x0079, 0x29ca, 0x29cf, 0x29cd, 0x2a68, 0x1078, 0x248c, 0x78ec,
+ 0xa084, 0x0001, 0x00c0, 0x29e3, 0x7000, 0xa086, 0x0004, 0x00c0,
+ 0x29db, 0x0078, 0x2a06, 0x1078, 0x34b8, 0x6008, 0xa084, 0xffef,
+ 0x600a, 0x0078, 0x3467, 0x78e4, 0xa005, 0x00d0, 0x2a06, 0x0018,
+ 0x24fa, 0x2008, 0xa084, 0x0030, 0x00c0, 0x29f2, 0x781b, 0x004f,
+ 0x0078, 0x24fa, 0x78ec, 0xa084, 0x0003, 0x0040, 0x29ee, 0x2100,
+ 0xa084, 0x0007, 0x0079, 0x29fc, 0x2a3f, 0x2a4a, 0x2a30, 0x2a04,
+ 0x39bb, 0x39bb, 0x2a04, 0x2a59, 0x1078, 0x248c, 0x7000, 0xa086,
+ 0x0004, 0x00c0, 0x2a20, 0x706c, 0xa086, 0x0002, 0x00c0, 0x2a16,
+ 0x2011, 0x0002, 0x2019, 0x0000, 0x0078, 0x28e9, 0x706c, 0xa086,
+ 0x0006, 0x0040, 0x2a10, 0x706c, 0xa086, 0x0004, 0x0040, 0x2a10,
+ 0x79e4, 0xa184, 0x0030, 0x0040, 0x2a2a, 0x78ec, 0xa084, 0x0003,
+ 0x00c0, 0x2a2c, 0x0078, 0x300c, 0x2001, 0x0003, 0x0078, 0x2da0,
+ 0x6818, 0xa084, 0x8000, 0x0040, 0x2a37, 0x681b, 0x001d, 0x1078,
+ 0x378f, 0x782b, 0x3008, 0x781b, 0x0056, 0x0078, 0x24fa, 0x6818,
+ 0xa084, 0x8000, 0x0040, 0x2a46, 0x681b, 0x001d, 0x1078, 0x378f,
+ 0x0078, 0x3986, 0x6818, 0xa084, 0x8000, 0x0040, 0x2a51, 0x681b,
+ 0x001d, 0x1078, 0x378f, 0x782b, 0x3008, 0x781b, 0x00ca, 0x0078,
+ 0x24fa, 0x6818, 0xa084, 0x8000, 0x0040, 0x2a60, 0x681b, 0x001d,
+ 0x1078, 0x378f, 0x782b, 0x3008, 0x781b, 0x008f, 0x0078, 0x24fa,
+ 0xa584, 0x000f, 0x00c0, 0x2a85, 0x7000, 0x0079, 0x2a6f, 0x2523,
+ 0x2a79, 0x2a77, 0x3467, 0x3467, 0x3467, 0x3467, 0x2a77, 0x1078,
+ 0x248c, 0x1078, 0x34b8, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078,
+ 0x345a, 0x0040, 0x3467, 0x0078, 0x2635, 0x78e4, 0xa005, 0x00d0,
+ 0x2a06, 0x0018, 0x2a06, 0x2008, 0xa084, 0x0030, 0x00c0, 0x2a94,
+ 0x781b, 0x004f, 0x0078, 0x24fa, 0x78ec, 0xa084, 0x0003, 0x0040,
+ 0x2a90, 0x2100, 0xa184, 0x0007, 0x0079, 0x2a9e, 0x2ab0, 0x2ab4,
+ 0x2aa8, 0x2aa6, 0x39bb, 0x39bb, 0x2aa6, 0x39b1, 0x1078, 0x248c,
+ 0x1078, 0x3797, 0x782b, 0x3008, 0x781b, 0x0056, 0x0078, 0x24fa,
+ 0x1078, 0x3797, 0x0078, 0x3986, 0x1078, 0x3797, 0x782b, 0x3008,
+ 0x781b, 0x00ca, 0x0078, 0x24fa, 0x1078, 0x3797, 0x782b, 0x3008,
+ 0x781b, 0x008f, 0x0078, 0x24fa, 0x2300, 0x0079, 0x2ac7, 0x2acc,
+ 0x2aca, 0x2ace, 0x1078, 0x248c, 0x0078, 0x3180, 0x681b, 0x0008,
+ 0x78a3, 0x0000, 0x79e4, 0xa184, 0x0030, 0x0040, 0x3180, 0x78ec,
+ 0xa084, 0x0003, 0x0040, 0x3180, 0xa184, 0x0007, 0x0079, 0x2ae0,
+ 0x2ae8, 0x2ab4, 0x2a30, 0x3956, 0x39bb, 0x39bb, 0x2ae8, 0x39b1,
+ 0x1078, 0x396a, 0x0078, 0x24fa, 0xa282, 0x0005, 0x0050, 0x2af2,
+ 0x1078, 0x248c, 0x2300, 0x0079, 0x2af5, 0x2af8, 0x2d4d, 0x2d5b,
+ 0x2200, 0x0079, 0x2afb, 0x2b15, 0x2b02, 0x2b15, 0x2b00, 0x2d32,
+ 0x1078, 0x248c, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff, 0xa082,
+ 0x0020, 0x0048, 0x376b, 0xa08a, 0x0004, 0x00c8, 0x376b, 0x0079,
+ 0x2b11, 0x376b, 0x376b, 0x376b, 0x3719, 0x789b, 0x0018, 0x79a8,
+ 0xa184, 0x0080, 0x0040, 0x2b26, 0x0078, 0x376b, 0x7000, 0xa005,
+ 0x00c0, 0x2b1c, 0x2011, 0x0004, 0x0078, 0x32e9, 0xa184, 0x00ff,
+ 0xa08a, 0x0010, 0x00c8, 0x376b, 0x0079, 0x2b2e, 0x2b40, 0x2b3e,
+ 0x2b58, 0x2b5c, 0x2c17, 0x376b, 0x376b, 0x2c19, 0x376b, 0x376b,
+ 0x2d2e, 0x2d2e, 0x376b, 0x376b, 0x376b, 0x2d30, 0x1078, 0x248c,
+ 0xa684, 0x1000, 0x0040, 0x2b4d, 0x2001, 0x0500, 0x8000, 0x8000,
+ 0x783a, 0x781b, 0x008d, 0x0078, 0x24fa, 0x6818, 0xa084, 0x8000,
+ 0x0040, 0x2b56, 0x681b, 0x001d, 0x0078, 0x2b44, 0x0078, 0x3956,
+ 0x681b, 0x001d, 0x0078, 0x377b, 0x6920, 0x6922, 0xa684, 0x1800,
+ 0x00c0, 0x2b9d, 0x6820, 0xa084, 0x0001, 0x00c0, 0x2ba5, 0x6818,
+ 0xa086, 0x0008, 0x00c0, 0x2b6e, 0x681b, 0x0000, 0xa684, 0x0400,
+ 0x0040, 0x2c13, 0xa684, 0x0080, 0x0040, 0x2b99, 0x7097, 0x0000,
+ 0x6818, 0xa084, 0x003f, 0xa08a, 0x000d, 0x0050, 0x2b99, 0xa08a,
+ 0x000c, 0x7196, 0x2001, 0x000c, 0x800c, 0x719a, 0x789b, 0x0061,
+ 0x78aa, 0x157e, 0x137e, 0x147e, 0x20a1, 0x012b, 0x789b, 0x0000,
+ 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f, 0x137f,
+ 0x157f, 0x781b, 0x0058, 0x0078, 0x24fa, 0xa684, 0x1000, 0x0040,
+ 0x2ba5, 0x781b, 0x0065, 0x0078, 0x24fa, 0xa684, 0x0060, 0x0040,
+ 0x2c0f, 0xa684, 0x0800, 0x0040, 0x2c0f, 0xa684, 0x8000, 0x00c0,
+ 0x2bb3, 0x0078, 0x2bcb, 0xa6b4, 0x7fff, 0x7e5a, 0x6eb6, 0x7adc,
+ 0x79d8, 0x78d0, 0x801b, 0x00c8, 0x2bbe, 0x8000, 0xa084, 0x003f,
+ 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94,
+ 0x2200, 0xa303, 0x68ae, 0xa684, 0x4000, 0x0040, 0x2bd3, 0xa6b4,
+ 0xbfff, 0x7e5a, 0x6eb6, 0x7000, 0xa086, 0x0003, 0x00c0, 0x2be0,
+ 0x1078, 0x493d, 0x1078, 0x4b3a, 0x781b, 0x0064, 0x0078, 0x24fa,
+ 0xa006, 0x1078, 0x4c41, 0x6ab0, 0x69ac, 0x6c98, 0x6b94, 0x2200,
+ 0xa105, 0x0040, 0x2bef, 0x2200, 0xa422, 0x2100, 0xa31b, 0x6caa,
+ 0x7cd2, 0x7cda, 0x6ba6, 0x7bd6, 0x7bde, 0x2300, 0xa405, 0x00c0,
+ 0x2c01, 0xa6b5, 0x4000, 0x7e5a, 0x6eb6, 0x781b, 0x0064, 0x0078,
+ 0x24fa, 0x781b, 0x0064, 0x2200, 0xa115, 0x00c0, 0x2c0b, 0x1078,
+ 0x4b4b, 0x0078, 0x24fa, 0x1078, 0x4b96, 0x0078, 0x24fa, 0x781b,
+ 0x0065, 0x0078, 0x24fa, 0x781b, 0x0058, 0x0078, 0x24fa, 0x1078,
+ 0x248c, 0x0078, 0x2c7a, 0x6920, 0xa184, 0x0100, 0x0040, 0x2c31,
+ 0xa18c, 0xfeff, 0x6922, 0x0c7e, 0x7054, 0x2060, 0x6000, 0xa084,
+ 0xefff, 0x6002, 0x6004, 0xa084, 0xfff5, 0x6006, 0x0c7f, 0x0078,
+ 0x2c69, 0xa184, 0x0200, 0x0040, 0x2c69, 0xa18c, 0xfdff, 0x6922,
+ 0x0c7e, 0x7054, 0x2060, 0x6000, 0xa084, 0xdfff, 0x6002, 0x6004,
+ 0xa084, 0xffef, 0x6006, 0x2008, 0x2c48, 0x0c7f, 0xa184, 0x0008,
+ 0x0040, 0x2c69, 0x1078, 0x38b9, 0x1078, 0x35bb, 0x88ff, 0x0040,
+ 0x2c69, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xa6b5, 0x0004,
+ 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x2c63, 0x782b, 0x3008, 0x781b,
+ 0x0056, 0x0078, 0x24fa, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078,
+ 0x24fa, 0x7e58, 0xa684, 0x0400, 0x00c0, 0x2c72, 0x781b, 0x0058,
+ 0x0078, 0x24fa, 0x781b, 0x0065, 0x0078, 0x24fa, 0x0078, 0x3773,
+ 0x0078, 0x3773, 0x2019, 0x0000, 0x7990, 0xa18c, 0x0007, 0x00c0,
+ 0x2c88, 0x6820, 0xa084, 0x0100, 0x0040, 0x2c78, 0x2009, 0x0008,
+ 0x789b, 0x0010, 0x78a8, 0xa094, 0x00ff, 0xa286, 0x0001, 0x00c0,
+ 0x2cbf, 0x2300, 0x7ca8, 0xa400, 0x2018, 0xa102, 0x0040, 0x2cb7,
+ 0x0048, 0x2c9c, 0x0078, 0x2cb9, 0xa380, 0x0002, 0xa102, 0x00c8,
+ 0x2cb7, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0c7e, 0x7054, 0x2060,
+ 0x6000, 0xa084, 0xefef, 0x6002, 0x6004, 0xa084, 0xffe5, 0x6006,
+ 0x0c7f, 0x7e58, 0xa6b4, 0xfffb, 0x7e5a, 0x0078, 0x2c6a, 0x0078,
+ 0x2c1b, 0x24a8, 0x7aa8, 0x00f0, 0x2cb9, 0x0078, 0x2c8a, 0xa284,
+ 0x00f0, 0xa086, 0x0020, 0x00c0, 0x2d1f, 0x8318, 0x8318, 0x2300,
+ 0xa102, 0x0040, 0x2ccf, 0x0048, 0x2ccf, 0x0078, 0x2d1c, 0xa286,
+ 0x0023, 0x0040, 0x2c78, 0x681c, 0xa084, 0xfff1, 0x681e, 0x7e58,
+ 0xa684, 0xfff1, 0xa085, 0x0010, 0x2030, 0x7e5a, 0x6008, 0xa085,
+ 0x0010, 0x600a, 0x0c7e, 0x7054, 0x2060, 0x6004, 0x2008, 0x2c48,
+ 0x0c7f, 0xa184, 0x0010, 0x0040, 0x2cf3, 0x1078, 0x38b9, 0x1078,
+ 0x36d0, 0x0078, 0x2d02, 0x0c7e, 0x7054, 0x2060, 0x6004, 0x2008,
+ 0x2c48, 0x0c7f, 0xa184, 0x0008, 0x0040, 0x2c69, 0x1078, 0x38b9,
+ 0x1078, 0x35bb, 0x88ff, 0x0040, 0x2c69, 0x789b, 0x0060, 0x2800,
+ 0x78aa, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x2d16,
+ 0x782b, 0x3008, 0x781b, 0x0056, 0x0078, 0x24fa, 0x782b, 0x3008,
+ 0x781b, 0x0065, 0x0078, 0x24fa, 0x7aa8, 0x0078, 0x2c8a, 0x8318,
+ 0x2300, 0xa102, 0x0040, 0x2d28, 0x0048, 0x2d28, 0x0078, 0x2c8a,
+ 0xa284, 0x0080, 0x00c0, 0x377b, 0x0078, 0x3773, 0x0078, 0x377b,
+ 0x0078, 0x376b, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff, 0xa08e,
+ 0x0001, 0x0040, 0x2d3d, 0x1078, 0x248c, 0x7aa8, 0xa294, 0x00ff,
+ 0x78a8, 0xa084, 0x00ff, 0xa08a, 0x0004, 0x00c8, 0x376b, 0x0079,
+ 0x2d49, 0x376b, 0x3508, 0x376b, 0x3665, 0xa282, 0x0000, 0x00c0,
+ 0x2d53, 0x1078, 0x248c, 0x1078, 0x378f, 0x782b, 0x3008, 0x781b,
+ 0x0065, 0x0078, 0x24fa, 0xa282, 0x0003, 0x00c0, 0x2d61, 0x1078,
+ 0x248c, 0xa484, 0x8000, 0x00c0, 0x2d84, 0x706c, 0xa005, 0x0040,
+ 0x2d6b, 0x1078, 0x248c, 0x6f14, 0x7782, 0xa7bc, 0x0f00, 0x1078,
+ 0x38bd, 0x6008, 0xa085, 0x0021, 0x600a, 0x8738, 0xa784, 0x001f,
+ 0x00c0, 0x2d6f, 0x1078, 0x3793, 0x706f, 0x0002, 0x2009, 0x5238,
+ 0x200b, 0x0009, 0x0078, 0x2d86, 0x1078, 0x379f, 0x782b, 0x3008,
+ 0x781b, 0x0065, 0x0078, 0x24fa, 0xa282, 0x0004, 0x0050, 0x2d92,
+ 0x1078, 0x248c, 0x2300, 0x0079, 0x2d95, 0x2d98, 0x2e81, 0x2eb4,
+ 0xa286, 0x0003, 0x0040, 0x2d9e, 0x1078, 0x248c, 0x2001, 0x0000,
+ 0x007e, 0x68c0, 0xa005, 0x0040, 0x2da7, 0x7003, 0x0003, 0x68a0,
+ 0xa084, 0x2000, 0x0040, 0x2db0, 0x6008, 0xa085, 0x0002, 0x600a,
+ 0x007f, 0x703e, 0x7000, 0xa084, 0x0007, 0x0079, 0x2db7, 0x2523,
+ 0x2dc1, 0x2dc1, 0x2fb6, 0x2ff2, 0x2523, 0x2ff2, 0x2dbf, 0x1078,
+ 0x248c, 0xa684, 0x1000, 0x00c0, 0x2dc9, 0x1078, 0x4887, 0x0040,
+ 0x2e5b, 0x7868, 0xa08c, 0x00ff, 0x0040, 0x2e11, 0xa186, 0x0008,
+ 0x00c0, 0x2de0, 0x1078, 0x34b8, 0x6008, 0xa084, 0xffef, 0x600a,
+ 0x1078, 0x345a, 0x0040, 0x2e11, 0x1078, 0x4887, 0x0078, 0x2df8,
+ 0xa186, 0x0028, 0x00c0, 0x2e11, 0x1078, 0x4887, 0x6008, 0xa084,
+ 0xffef, 0x600a, 0x6018, 0xa005, 0x0040, 0x2df8, 0x8001, 0x601a,
+ 0xa005, 0x0040, 0x2df8, 0x8001, 0xa005, 0x0040, 0x2df8, 0x601e,
+ 0x6820, 0xa084, 0x0001, 0x0040, 0x2523, 0x6820, 0xa084, 0xfffe,
+ 0x6822, 0x7060, 0x0c7e, 0x2060, 0x6800, 0x6002, 0x0c7f, 0x6004,
+ 0x6802, 0xa005, 0x2d00, 0x00c0, 0x2e0e, 0x6002, 0x6006, 0x0078,
+ 0x2523, 0x017e, 0x1078, 0x2ee5, 0x017f, 0xa684, 0xdf00, 0x681e,
+ 0x682b, 0x0000, 0x6f14, 0x81ff, 0x0040, 0x2e5b, 0xa186, 0x0002,
+ 0x00c0, 0x2e5b, 0xa684, 0x0800, 0x00c0, 0x2e2e, 0xa684, 0x0060,
+ 0x0040, 0x2e2e, 0x78d8, 0x7adc, 0x682e, 0x6a32, 0x6820, 0xa084,
+ 0x0800, 0x00c0, 0x2e5b, 0x8717, 0xa294, 0x000f, 0x8213, 0x8213,
+ 0x8213, 0xa290, 0x5480, 0xa290, 0x0000, 0x221c, 0xa384, 0x0100,
+ 0x00c0, 0x2e44, 0x0078, 0x2e4a, 0x8210, 0x2204, 0xa085, 0x0018,
+ 0x2012, 0x8211, 0xa384, 0x0400, 0x0040, 0x2e57, 0x68a0, 0xa084,
+ 0x0100, 0x00c0, 0x2e57, 0x1078, 0x2f69, 0x0078, 0x2523, 0x6008,
+ 0xa085, 0x0002, 0x600a, 0x6916, 0x6818, 0xa084, 0x8000, 0x0040,
+ 0x2e63, 0x703c, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x1078, 0x34a9,
+ 0x1078, 0x34b8, 0x00c0, 0x2e70, 0x6008, 0xa084, 0xffef, 0x600a,
+ 0x6820, 0xa084, 0x0001, 0x00c0, 0x2e79, 0x1078, 0x34a2, 0x0078,
+ 0x2e7d, 0x7060, 0x2060, 0x6800, 0x6002, 0x1078, 0x1cdc, 0x0078,
+ 0x2523, 0xa282, 0x0004, 0x0048, 0x2e87, 0x1078, 0x248c, 0x2200,
+ 0x0079, 0x2e8a, 0x2e85, 0x2e8e, 0x2e9b, 0x2e8e, 0x7000, 0xa086,
+ 0x0005, 0x0040, 0x2e97, 0x1078, 0x378f, 0x782b, 0x3008, 0x781b,
+ 0x0065, 0x0078, 0x24fa, 0x7890, 0x8007, 0x8001, 0xa084, 0x0007,
+ 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c, 0x00ff, 0xa186, 0x0003,
+ 0x0040, 0x2eb0, 0xa186, 0x0000, 0x0040, 0x2eb0, 0x0078, 0x376b,
+ 0x781b, 0x0065, 0x0078, 0x24fa, 0x6820, 0xa085, 0x0004, 0x6822,
+ 0x82ff, 0x00c0, 0x2ebf, 0x1078, 0x378f, 0x0078, 0x2ec6, 0x8211,
+ 0x0040, 0x2ec4, 0x1078, 0x248c, 0x1078, 0x379f, 0x782b, 0x3008,
+ 0x781b, 0x0065, 0x0078, 0x24fa, 0x702c, 0x8003, 0x0048, 0x2ed6,
+ 0x2019, 0x4eaf, 0x1078, 0x2313, 0x702f, 0x8000, 0x1078, 0x39e0,
+ 0x7830, 0xa084, 0x00c0, 0x00c0, 0x2ee2, 0x0018, 0x2ee2, 0x791a,
+ 0xa006, 0x007c, 0xa085, 0x0001, 0x007c, 0xa684, 0x0060, 0x00c0,
+ 0x2eef, 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x2f68, 0xa684,
+ 0x0800, 0x00c0, 0x2f11, 0x68b4, 0xa084, 0x4800, 0xa635, 0xa684,
+ 0x0800, 0x00c0, 0x2f11, 0x6998, 0x6a94, 0x692e, 0x6a32, 0x703c,
+ 0xa005, 0x00c0, 0x2f09, 0x2200, 0xa105, 0x0040, 0x2f10, 0x703f,
+ 0x0015, 0x7000, 0xa086, 0x0006, 0x0040, 0x2f10, 0x1078, 0x4887,
+ 0x007c, 0xa684, 0x0020, 0x0040, 0x2f33, 0xa684, 0x4000, 0x0040,
+ 0x2f1f, 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x2f09, 0x68b4,
+ 0xa084, 0x4800, 0xa635, 0xa684, 0x4000, 0x00c0, 0x2f19, 0x703c,
+ 0xa005, 0x00c0, 0x2f2d, 0x703f, 0x0015, 0x79d8, 0x7adc, 0x692e,
+ 0x6a32, 0x0078, 0x2f09, 0xa684, 0x4000, 0x0040, 0x2f3d, 0x682f,
+ 0x0000, 0x6833, 0x0000, 0x0078, 0x2f09, 0x68b4, 0xa084, 0x4800,
+ 0xa635, 0xa684, 0x4000, 0x00c0, 0x2f37, 0x703c, 0xa005, 0x00c0,
+ 0x2f4b, 0x703f, 0x0015, 0x79d8, 0x7adc, 0x78d0, 0x80fb, 0x00c8,
+ 0x2f52, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x692e,
+ 0x6a32, 0x2100, 0xa205, 0x00c0, 0x2f5f, 0x0078, 0x2f09, 0x7000,
+ 0xa086, 0x0006, 0x0040, 0x2f68, 0x1078, 0x4c41, 0x0078, 0x2f09,
+ 0x007c, 0x6008, 0xa085, 0x0200, 0x600a, 0xa384, 0x0200, 0x0040,
+ 0x2f75, 0x6008, 0xa085, 0x0002, 0x600a, 0x681b, 0x0006, 0x688f,
+ 0x0000, 0x6893, 0x0000, 0x6a30, 0x692c, 0x6a3e, 0x6942, 0x682f,
+ 0x0003, 0x6833, 0x0000, 0x6837, 0x0020, 0x6897, 0x0000, 0x689b,
+ 0x0020, 0x68b3, 0x0000, 0x68af, 0x0000, 0x7000, 0x0079, 0x2f90,
+ 0x2523, 0x2f9a, 0x2fa3, 0x2f98, 0x2f98, 0x2f98, 0x2f98, 0x2f98,
+ 0x1078, 0x248c, 0x6820, 0xa084, 0x0001, 0x00c0, 0x2fa3, 0x1078,
+ 0x34a2, 0x0078, 0x2fa9, 0x7060, 0x2c50, 0x2060, 0x6800, 0x6002,
+ 0x2a60, 0x2021, 0x525a, 0x2404, 0xa005, 0x0040, 0x2fb2, 0x2020,
+ 0x0078, 0x2fab, 0x2d22, 0x206b, 0x0000, 0x007c, 0x1078, 0x34a9,
+ 0x1078, 0x34b8, 0x6008, 0xa084, 0xfdff, 0x600a, 0x682b, 0x0000,
+ 0x789b, 0x000e, 0x6f14, 0x6817, 0x0002, 0x1078, 0x4c89, 0xa684,
+ 0x0800, 0x0040, 0x2fcf, 0x691c, 0xa18d, 0x2000, 0x691e, 0x6818,
+ 0xa084, 0x8000, 0x0040, 0x2fdf, 0x7868, 0xa08c, 0x00ff, 0x0040,
+ 0x2fdd, 0x681b, 0x001e, 0x0078, 0x2fdf, 0x681b, 0x0000, 0x2021,
+ 0x525a, 0x2404, 0xad06, 0x0040, 0x2fe6, 0x7460, 0x6800, 0x2022,
+ 0x68c3, 0x0000, 0x6a3c, 0x6940, 0x6a32, 0x692e, 0x1078, 0x1cdc,
+ 0x0078, 0x2523, 0x1078, 0x2ee5, 0x682b, 0x0000, 0x2001, 0x000e,
+ 0x6f14, 0x1078, 0x39e6, 0xa08c, 0x00ff, 0x6916, 0x6818, 0xa084,
+ 0x8000, 0x0040, 0x3005, 0x703c, 0x681a, 0xa68c, 0xdf00, 0x691e,
+ 0x706f, 0x0000, 0x0078, 0x2523, 0x7000, 0xa005, 0x00c0, 0x3012,
+ 0x0078, 0x2523, 0xa006, 0x1078, 0x4887, 0x6817, 0x0000, 0x681b,
+ 0x0014, 0xa68c, 0xdf00, 0x691e, 0x682b, 0x0000, 0x6820, 0xa085,
+ 0x00ff, 0x6822, 0x7000, 0x0079, 0x3025, 0x2523, 0x302f, 0x302f,
+ 0x3031, 0x3031, 0x3031, 0x3031, 0x302d, 0x1078, 0x248c, 0x1078,
+ 0x34b8, 0x6008, 0xa084, 0xffef, 0x600a, 0x0078, 0x3472, 0x2300,
+ 0x0079, 0x303a, 0x303d, 0x303f, 0x3098, 0x1078, 0x248c, 0xa684,
+ 0x8000, 0x00c0, 0x307d, 0x7000, 0x0079, 0x3046, 0x2523, 0x3050,
+ 0x3050, 0x306c, 0x3050, 0x3079, 0x306c, 0x304e, 0x1078, 0x248c,
+ 0xa684, 0x0060, 0xa086, 0x0060, 0x00c0, 0x3068, 0xa6b4, 0xffdf,
+ 0xa6b4, 0xbfff, 0xa6b5, 0x2000, 0x7e5a, 0x6eb6, 0x681c, 0xa084,
+ 0xffdf, 0x681e, 0x1078, 0x4887, 0x1078, 0x4b4b, 0x0078, 0x3956,
+ 0xa684, 0x2000, 0x0040, 0x305a, 0x6818, 0xa084, 0x8000, 0x0040,
+ 0x3079, 0x681b, 0x0015, 0xa684, 0x4000, 0x0040, 0x3079, 0x681b,
+ 0x0007, 0x1078, 0x396a, 0x0078, 0x24fa, 0xa6b4, 0x7fff, 0x7e5a,
+ 0x7adc, 0x79d8, 0x78d0, 0x79d2, 0x801b, 0x00c8, 0x3088, 0x8000,
+ 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302,
+ 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x781b, 0x0065, 0x007c,
+ 0x1078, 0x248c, 0x2300, 0x0079, 0x309d, 0x30a0, 0x30a2, 0x30eb,
+ 0x1078, 0x248c, 0xa684, 0x8000, 0x00c0, 0x30da, 0x7000, 0x0079,
+ 0x30a9, 0x2523, 0x30b3, 0x30b3, 0x30cf, 0x30b3, 0x30d6, 0x30cf,
+ 0x30b1, 0x1078, 0x248c, 0xa684, 0x0060, 0xa086, 0x0060, 0x00c0,
+ 0x30cb, 0xa6b4, 0xffbf, 0xa6b4, 0xbfff, 0xa6b5, 0x2000, 0x7e5a,
+ 0x6eb6, 0x681c, 0xa084, 0xffbf, 0x681e, 0x1078, 0x4887, 0x1078,
+ 0x4b4b, 0x0078, 0x3956, 0xa684, 0x2000, 0x0040, 0x30bd, 0x6818,
+ 0xa084, 0x8000, 0x0040, 0x30d6, 0x681b, 0x0007, 0x781b, 0x00ca,
+ 0x0078, 0x24fa, 0xa6b4, 0x7fff, 0x7e5a, 0x7adc, 0x79d8, 0x6b98,
+ 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x79d2,
+ 0x781b, 0x0065, 0x007c, 0x6820, 0xa085, 0x0004, 0x6822, 0x1078,
+ 0x3921, 0xa6b5, 0x0800, 0x1078, 0x378f, 0x782b, 0x3008, 0x781b,
+ 0x0065, 0x0078, 0x24fa, 0x2300, 0x0079, 0x30fe, 0x3101, 0x3103,
+ 0x3105, 0x1078, 0x248c, 0x0078, 0x377b, 0xa684, 0x0400, 0x00c0,
+ 0x312e, 0x79e4, 0xa184, 0x0020, 0x0040, 0x3115, 0x78ec, 0xa084,
+ 0x0003, 0x0040, 0x3115, 0x782b, 0x3009, 0x789b, 0x0060, 0x78ab,
+ 0x0000, 0xa684, 0xfffb, 0x785a, 0x79e4, 0xa184, 0x0020, 0x0040,
+ 0x3126, 0x78ec, 0xa084, 0x0003, 0x00c0, 0x312a, 0x2001, 0x0014,
+ 0x0078, 0x2da0, 0xa184, 0x0007, 0x0079, 0x3166, 0x7a90, 0xa294,
+ 0x0007, 0x789b, 0x0060, 0x79a8, 0x81ff, 0x0040, 0x3164, 0x789b,
+ 0x0010, 0x7ba8, 0xa384, 0x0001, 0x00c0, 0x3155, 0x7ba8, 0x7ba8,
+ 0xa386, 0x0001, 0x00c0, 0x3148, 0x2009, 0xfff7, 0x0078, 0x314e,
+ 0xa386, 0x0003, 0x00c0, 0x3155, 0x2009, 0xffef, 0x0c7e, 0x7054,
+ 0x2060, 0x6004, 0xa104, 0x6006, 0x0c7f, 0x789b, 0x0060, 0x78ab,
+ 0x0000, 0xa684, 0xfffb, 0x785a, 0x782b, 0x3009, 0x6920, 0xa18c,
+ 0xfdff, 0xa18c, 0xfeff, 0x6922, 0x0078, 0x3956, 0x2a3f, 0x2a4a,
+ 0x3170, 0x3178, 0x316e, 0x316e, 0x3956, 0x3956, 0x1078, 0x248c,
+ 0x6920, 0xa18c, 0xfdff, 0xa18c, 0xfeff, 0x6922, 0x0078, 0x3960,
+ 0x6920, 0xa18c, 0xfdff, 0xa18c, 0xfeff, 0x6922, 0x0078, 0x3956,
+ 0x79e4, 0xa184, 0x0030, 0x0040, 0x318a, 0x78ec, 0xa084, 0x0003,
+ 0x00c0, 0x31b1, 0x7000, 0xa086, 0x0004, 0x00c0, 0x31a4, 0x706c,
+ 0xa086, 0x0002, 0x00c0, 0x319a, 0x2011, 0x0002, 0x2019, 0x0000,
+ 0x0078, 0x28e9, 0x706c, 0xa086, 0x0006, 0x0040, 0x3194, 0x706c,
+ 0xa086, 0x0004, 0x0040, 0x3194, 0x7000, 0xa086, 0x0000, 0x0040,
+ 0x24fa, 0x6818, 0xa085, 0x8000, 0x681a, 0x2001, 0x0014, 0x0078,
+ 0x2da0, 0xa184, 0x0007, 0x0079, 0x31b5, 0x3956, 0x3956, 0x31bd,
+ 0x3956, 0x39bb, 0x39bb, 0x3956, 0x3956, 0xa684, 0x0080, 0x0040,
+ 0x31ec, 0x7194, 0x81ff, 0x0040, 0x31ec, 0xa182, 0x000d, 0x00d0,
+ 0x31cd, 0x7097, 0x0000, 0x0078, 0x31d2, 0xa182, 0x000c, 0x7096,
+ 0x2009, 0x000c, 0x789b, 0x0061, 0x79aa, 0x157e, 0x137e, 0x147e,
+ 0x7098, 0x8114, 0xa210, 0x729a, 0xa080, 0x000b, 0xad00, 0x2098,
+ 0x20a1, 0x012b, 0x789b, 0x0000, 0x8108, 0x81ac, 0x53a6, 0x147f,
+ 0x137f, 0x157f, 0x0078, 0x3960, 0xa684, 0x0400, 0x00c0, 0x322d,
+ 0x6820, 0xa084, 0x0001, 0x0040, 0x3960, 0xa68c, 0x0060, 0xa684,
+ 0x0060, 0x0040, 0x3201, 0xa086, 0x0060, 0x00c0, 0x3201, 0xa18d,
+ 0x4000, 0xa18c, 0xfffb, 0x795a, 0x69b6, 0x789b, 0x0060, 0x78ab,
+ 0x0000, 0x789b, 0x0061, 0x6818, 0xa085, 0x8000, 0x681a, 0x78aa,
+ 0x8008, 0x810c, 0x0040, 0x34d1, 0xa18c, 0x00f8, 0x00c0, 0x34d1,
0x157e, 0x137e, 0x147e, 0x20a1, 0x012b, 0x789b, 0x0000, 0x8000,
0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f,
- 0x781b, 0x0058, 0x0078, 0x2459, 0xa684, 0x1000, 0x0040, 0x2b04,
- 0x781b, 0x0065, 0x0078, 0x2459, 0xa684, 0x0060, 0x0040, 0x2b70,
- 0xa684, 0x0800, 0x0040, 0x2b70, 0xa684, 0x8000, 0x00c0, 0x2b12,
- 0x0078, 0x2b2c, 0xa6b4, 0x7fff, 0x7e5a, 0x6eb6, 0x789b, 0x0076,
- 0x7aac, 0x79ac, 0x78ac, 0x801b, 0x00c8, 0x2b1f, 0x8000, 0xa084,
- 0x003f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2,
- 0x6b94, 0x2200, 0xa303, 0x68ae, 0xa684, 0x4000, 0x0040, 0x2b34,
- 0xa6b4, 0xbfff, 0x7e5a, 0x6eb6, 0x7000, 0xa086, 0x0003, 0x00c0,
- 0x2b41, 0x1078, 0x482c, 0x1078, 0x4a29, 0x781b, 0x0064, 0x0078,
- 0x2459, 0xa006, 0x1078, 0x4b30, 0x6ab0, 0x69ac, 0x6c98, 0x6b94,
- 0x2200, 0xa105, 0x0040, 0x2b50, 0x2200, 0xa422, 0x2100, 0xa31b,
- 0x6caa, 0x7cd2, 0x7cda, 0x6ba6, 0x7bd6, 0x7bde, 0x2300, 0xa405,
- 0x00c0, 0x2b62, 0xa6b5, 0x4000, 0x7e5a, 0x6eb6, 0x781b, 0x0064,
- 0x0078, 0x2459, 0x781b, 0x0064, 0x2200, 0xa115, 0x00c0, 0x2b6c,
- 0x1078, 0x4a3a, 0x0078, 0x2459, 0x1078, 0x4a85, 0x0078, 0x2459,
- 0x781b, 0x0065, 0x0078, 0x2459, 0x781b, 0x0058, 0x0078, 0x2459,
- 0x1078, 0x23eb, 0x0078, 0x2bdb, 0x6920, 0xa184, 0x0100, 0x0040,
- 0x2b92, 0xa18c, 0xfeff, 0x6922, 0x0c7e, 0x7054, 0x2060, 0x6000,
- 0xa084, 0xefff, 0x6002, 0x6004, 0xa084, 0xfff5, 0x6006, 0x0c7f,
- 0x0078, 0x2bca, 0xa184, 0x0200, 0x0040, 0x2bca, 0xa18c, 0xfdff,
- 0x6922, 0x0c7e, 0x7054, 0x2060, 0x6000, 0xa084, 0xdfff, 0x6002,
- 0x6004, 0xa084, 0xffef, 0x6006, 0x2008, 0x2c48, 0x0c7f, 0xa184,
- 0x0008, 0x0040, 0x2bca, 0x1078, 0x37eb, 0x1078, 0x34f1, 0x88ff,
- 0x0040, 0x2bca, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xa6b5,
- 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x2bc4, 0x782b, 0x3008,
- 0x781b, 0x0056, 0x0078, 0x2459, 0x782b, 0x3008, 0x781b, 0x0065,
- 0x0078, 0x2459, 0x7e58, 0xa684, 0x0400, 0x00c0, 0x2bd3, 0x781b,
- 0x0058, 0x0078, 0x2459, 0x781b, 0x0065, 0x0078, 0x2459, 0x0078,
- 0x36a5, 0x0078, 0x36a5, 0x2019, 0x0000, 0x7990, 0xa18c, 0x0007,
- 0x00c0, 0x2be9, 0x6820, 0xa084, 0x0100, 0x0040, 0x2bd9, 0x2009,
- 0x0008, 0x789b, 0x0010, 0x78a8, 0xa094, 0x00ff, 0xa286, 0x0001,
- 0x00c0, 0x2c20, 0x2300, 0x7ca8, 0xa400, 0x2018, 0xa102, 0x0040,
- 0x2c18, 0x0048, 0x2bfd, 0x0078, 0x2c1a, 0xa380, 0x0002, 0xa102,
- 0x00c8, 0x2c18, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0c7e, 0x7054,
- 0x2060, 0x6000, 0xa084, 0xefef, 0x6002, 0x6004, 0xa084, 0xffe5,
- 0x6006, 0x0c7f, 0x7e58, 0xa6b4, 0xfffb, 0x7e5a, 0x0078, 0x2bcb,
- 0x0078, 0x2b7c, 0x24a8, 0x7aa8, 0x00f0, 0x2c1a, 0x0078, 0x2beb,
- 0xa284, 0x00f0, 0xa086, 0x0020, 0x00c0, 0x2c80, 0x8318, 0x8318,
- 0x2300, 0xa102, 0x0040, 0x2c30, 0x0048, 0x2c30, 0x0078, 0x2c7d,
- 0xa286, 0x0023, 0x0040, 0x2bd9, 0x681c, 0xa084, 0xfff1, 0x681e,
- 0x7e58, 0xa684, 0xfff1, 0xa085, 0x0010, 0x2030, 0x7e5a, 0x6008,
- 0xa085, 0x0010, 0x600a, 0x0c7e, 0x7054, 0x2060, 0x6004, 0x2008,
- 0x2c48, 0x0c7f, 0xa184, 0x0010, 0x0040, 0x2c54, 0x1078, 0x37eb,
- 0x1078, 0x3604, 0x0078, 0x2c63, 0x0c7e, 0x7054, 0x2060, 0x6004,
- 0x2008, 0x2c48, 0x0c7f, 0xa184, 0x0008, 0x0040, 0x2bca, 0x1078,
- 0x37eb, 0x1078, 0x34f1, 0x88ff, 0x0040, 0x2bca, 0x789b, 0x0060,
- 0x2800, 0x78aa, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0,
- 0x2c77, 0x782b, 0x3008, 0x781b, 0x0056, 0x0078, 0x2459, 0x782b,
- 0x3008, 0x781b, 0x0065, 0x0078, 0x2459, 0x7aa8, 0x0078, 0x2beb,
- 0x8318, 0x2300, 0xa102, 0x0040, 0x2c89, 0x0048, 0x2c89, 0x0078,
- 0x2beb, 0xa284, 0x0080, 0x00c0, 0x36ad, 0x0078, 0x36a5, 0x0078,
- 0x36ad, 0x0078, 0x369d, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff,
- 0xa08e, 0x0001, 0x0040, 0x2c9e, 0x1078, 0x23eb, 0x7aa8, 0xa294,
- 0x00ff, 0x78a8, 0xa084, 0x00ff, 0xa08a, 0x0004, 0x00c8, 0x369d,
- 0x0079, 0x2caa, 0x369d, 0x343e, 0x369d, 0x3599, 0xa282, 0x0000,
- 0x00c0, 0x2cb4, 0x1078, 0x23eb, 0x1078, 0x36c1, 0x782b, 0x3008,
- 0x781b, 0x0065, 0x0078, 0x2459, 0xa282, 0x0003, 0x00c0, 0x2cc2,
- 0x1078, 0x23eb, 0xa484, 0x8000, 0x00c0, 0x2ce5, 0x706c, 0xa005,
- 0x0040, 0x2ccc, 0x1078, 0x23eb, 0x6f14, 0x7782, 0xa7bc, 0x0f00,
- 0x1078, 0x37ef, 0x6008, 0xa085, 0x0021, 0x600a, 0x8738, 0xa784,
- 0x001f, 0x00c0, 0x2cd0, 0x1078, 0x36c5, 0x706f, 0x0002, 0x2009,
- 0x5138, 0x200b, 0x0009, 0x0078, 0x2ce7, 0x1078, 0x36d1, 0x782b,
- 0x3008, 0x781b, 0x0065, 0x0078, 0x2459, 0xa282, 0x0004, 0x0050,
- 0x2cf3, 0x1078, 0x23eb, 0x2300, 0x0079, 0x2cf6, 0x2cf9, 0x2de2,
- 0x2e15, 0xa286, 0x0003, 0x0040, 0x2cff, 0x1078, 0x23eb, 0x2001,
- 0x0000, 0x007e, 0x68c0, 0xa005, 0x0040, 0x2d08, 0x7003, 0x0003,
- 0x68a0, 0xa084, 0x2000, 0x0040, 0x2d11, 0x6008, 0xa085, 0x0002,
- 0x600a, 0x007f, 0x703e, 0x7000, 0xa084, 0x0007, 0x0079, 0x2d18,
- 0x2482, 0x2d22, 0x2d22, 0x2f17, 0x2f53, 0x2482, 0x2f53, 0x2d20,
- 0x1078, 0x23eb, 0xa684, 0x1000, 0x00c0, 0x2d2a, 0x1078, 0x4776,
- 0x0040, 0x2dbc, 0x7868, 0xa08c, 0x00ff, 0x0040, 0x2d72, 0xa186,
- 0x0008, 0x00c0, 0x2d41, 0x1078, 0x33ee, 0x6008, 0xa084, 0xffef,
- 0x600a, 0x1078, 0x3390, 0x0040, 0x2d72, 0x1078, 0x4776, 0x0078,
- 0x2d59, 0xa186, 0x0028, 0x00c0, 0x2d72, 0x1078, 0x4776, 0x6008,
- 0xa084, 0xffef, 0x600a, 0x6018, 0xa005, 0x0040, 0x2d59, 0x8001,
- 0x601a, 0xa005, 0x0040, 0x2d59, 0x8001, 0xa005, 0x0040, 0x2d59,
- 0x601e, 0x6820, 0xa084, 0x0001, 0x0040, 0x2482, 0x6820, 0xa084,
- 0xfffe, 0x6822, 0x7060, 0x0c7e, 0x2060, 0x6800, 0x6002, 0x0c7f,
- 0x6004, 0x6802, 0xa005, 0x2d00, 0x00c0, 0x2d6f, 0x6002, 0x6006,
- 0x0078, 0x2482, 0x017e, 0x1078, 0x2e46, 0x017f, 0xa684, 0xdf00,
- 0x681e, 0x682b, 0x0000, 0x6f14, 0x81ff, 0x0040, 0x2dbc, 0xa186,
- 0x0002, 0x00c0, 0x2dbc, 0xa684, 0x0800, 0x00c0, 0x2d8f, 0xa684,
- 0x0060, 0x0040, 0x2d8f, 0x78d8, 0x7adc, 0x682e, 0x6a32, 0x6820,
- 0xa084, 0x0800, 0x00c0, 0x2dbc, 0x8717, 0xa294, 0x000f, 0x8213,
- 0x8213, 0x8213, 0xa290, 0x5380, 0xa290, 0x0000, 0x221c, 0xa384,
- 0x0100, 0x00c0, 0x2da5, 0x0078, 0x2dab, 0x8210, 0x2204, 0xa085,
- 0x0018, 0x2012, 0x8211, 0xa384, 0x0400, 0x0040, 0x2db8, 0x68a0,
- 0xa084, 0x0100, 0x00c0, 0x2db8, 0x1078, 0x2eca, 0x0078, 0x2482,
- 0x6008, 0xa085, 0x0002, 0x600a, 0x6916, 0x6818, 0xa084, 0x8000,
- 0x0040, 0x2dc4, 0x703c, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x1078,
- 0x33df, 0x1078, 0x33ee, 0x00c0, 0x2dd1, 0x6008, 0xa084, 0xffef,
- 0x600a, 0x6820, 0xa084, 0x0001, 0x00c0, 0x2dda, 0x1078, 0x33d8,
- 0x0078, 0x2dde, 0x7060, 0x2060, 0x6800, 0x6002, 0x1078, 0x1c70,
- 0x0078, 0x2482, 0xa282, 0x0004, 0x0048, 0x2de8, 0x1078, 0x23eb,
- 0x2200, 0x0079, 0x2deb, 0x2de6, 0x2def, 0x2dfc, 0x2def, 0x7000,
- 0xa086, 0x0005, 0x0040, 0x2df8, 0x1078, 0x36c1, 0x782b, 0x3008,
- 0x781b, 0x0065, 0x0078, 0x2459, 0x7890, 0x8007, 0x8001, 0xa084,
- 0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c, 0x00ff, 0xa186,
- 0x0003, 0x0040, 0x2e11, 0xa186, 0x0000, 0x0040, 0x2e11, 0x0078,
- 0x369d, 0x781b, 0x0065, 0x0078, 0x2459, 0x6820, 0xa085, 0x0004,
- 0x6822, 0x82ff, 0x00c0, 0x2e20, 0x1078, 0x36c1, 0x0078, 0x2e27,
- 0x8211, 0x0040, 0x2e25, 0x1078, 0x23eb, 0x1078, 0x36d1, 0x782b,
- 0x3008, 0x781b, 0x0065, 0x0078, 0x2459, 0x702c, 0x8003, 0x0048,
- 0x2e37, 0x2019, 0x4d9e, 0x1078, 0x2276, 0x702f, 0x8000, 0x1078,
- 0x3912, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x2e43, 0x0018, 0x2e43,
- 0x791a, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c, 0xa684, 0x0060,
- 0x00c0, 0x2e50, 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x2ec9,
- 0xa684, 0x0800, 0x00c0, 0x2e72, 0x68b4, 0xa084, 0x4800, 0xa635,
- 0xa684, 0x0800, 0x00c0, 0x2e72, 0x6998, 0x6a94, 0x692e, 0x6a32,
- 0x703c, 0xa005, 0x00c0, 0x2e6a, 0x2200, 0xa105, 0x0040, 0x2e71,
- 0x703f, 0x0015, 0x7000, 0xa086, 0x0006, 0x0040, 0x2e71, 0x1078,
- 0x4776, 0x007c, 0xa684, 0x0020, 0x0040, 0x2e94, 0xa684, 0x4000,
- 0x0040, 0x2e80, 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x2e6a,
- 0x68b4, 0xa084, 0x4800, 0xa635, 0xa684, 0x4000, 0x00c0, 0x2e7a,
- 0x703c, 0xa005, 0x00c0, 0x2e8e, 0x703f, 0x0015, 0x79d8, 0x7adc,
- 0x692e, 0x6a32, 0x0078, 0x2e6a, 0xa684, 0x4000, 0x0040, 0x2e9e,
- 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x2e6a, 0x68b4, 0xa084,
- 0x4800, 0xa635, 0xa684, 0x4000, 0x00c0, 0x2e98, 0x703c, 0xa005,
- 0x00c0, 0x2eac, 0x703f, 0x0015, 0x79d8, 0x7adc, 0x78d0, 0x80fb,
- 0x00c8, 0x2eb3, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000,
- 0x692e, 0x6a32, 0x2100, 0xa205, 0x00c0, 0x2ec0, 0x0078, 0x2e6a,
- 0x7000, 0xa086, 0x0006, 0x0040, 0x2ec9, 0x1078, 0x4b30, 0x0078,
- 0x2e6a, 0x007c, 0x6008, 0xa085, 0x0200, 0x600a, 0xa384, 0x0200,
- 0x0040, 0x2ed6, 0x6008, 0xa085, 0x0002, 0x600a, 0x681b, 0x0006,
- 0x688f, 0x0000, 0x6893, 0x0000, 0x6a30, 0x692c, 0x6a3e, 0x6942,
- 0x682f, 0x0003, 0x6833, 0x0000, 0x6837, 0x0020, 0x6897, 0x0000,
- 0x689b, 0x0020, 0x68b3, 0x0000, 0x68af, 0x0000, 0x7000, 0x0079,
- 0x2ef1, 0x2482, 0x2efb, 0x2f04, 0x2ef9, 0x2ef9, 0x2ef9, 0x2ef9,
- 0x2ef9, 0x1078, 0x23eb, 0x6820, 0xa084, 0x0001, 0x00c0, 0x2f04,
- 0x1078, 0x33d8, 0x0078, 0x2f0a, 0x7060, 0x2c50, 0x2060, 0x6800,
- 0x6002, 0x2a60, 0x2021, 0x515a, 0x2404, 0xa005, 0x0040, 0x2f13,
- 0x2020, 0x0078, 0x2f0c, 0x2d22, 0x206b, 0x0000, 0x007c, 0x1078,
- 0x33df, 0x1078, 0x33ee, 0x6008, 0xa084, 0xfdff, 0x600a, 0x682b,
- 0x0000, 0x789b, 0x000e, 0x6f14, 0x6817, 0x0002, 0x1078, 0x4b78,
- 0xa684, 0x0800, 0x0040, 0x2f30, 0x691c, 0xa18d, 0x2000, 0x691e,
- 0x6818, 0xa084, 0x8000, 0x0040, 0x2f40, 0x7868, 0xa08c, 0x00ff,
- 0x0040, 0x2f3e, 0x681b, 0x001e, 0x0078, 0x2f40, 0x681b, 0x0000,
- 0x2021, 0x515a, 0x2404, 0xad06, 0x0040, 0x2f47, 0x7460, 0x6800,
- 0x2022, 0x68c3, 0x0000, 0x6a3c, 0x6940, 0x6a32, 0x692e, 0x1078,
- 0x1c70, 0x0078, 0x2482, 0x1078, 0x2e46, 0x682b, 0x0000, 0x2001,
- 0x000e, 0x6f14, 0x1078, 0x3918, 0xa08c, 0x00ff, 0x6916, 0x6818,
- 0xa084, 0x8000, 0x0040, 0x2f66, 0x703c, 0x681a, 0xa68c, 0xdf00,
- 0x691e, 0x706f, 0x0000, 0x0078, 0x2482, 0x7000, 0xa005, 0x00c0,
- 0x2f73, 0x0078, 0x2482, 0xa006, 0x1078, 0x4776, 0x6817, 0x0000,
- 0x681b, 0x0014, 0xa68c, 0xdf00, 0x691e, 0x682b, 0x0000, 0x6820,
- 0xa085, 0x00ff, 0x6822, 0x7000, 0x0079, 0x2f86, 0x2482, 0x2f90,
- 0x2f90, 0x2f92, 0x2f92, 0x2f92, 0x2f92, 0x2f8e, 0x1078, 0x23eb,
- 0x1078, 0x33ee, 0x6008, 0xa084, 0xffef, 0x600a, 0x0078, 0x33a8,
- 0x2300, 0x0079, 0x2f9b, 0x2f9e, 0x2fa0, 0x2fd9, 0x1078, 0x23eb,
- 0x7000, 0x0079, 0x2fa3, 0x2482, 0x2fad, 0x2fad, 0x2fc8, 0x2fad,
- 0x2fd5, 0x2fc8, 0x2fab, 0x1078, 0x23eb, 0xa684, 0x0060, 0xa086,
- 0x0060, 0x00c0, 0x2fc4, 0xa6b4, 0xffdf, 0xa6b4, 0xbfff, 0xa6b5,
- 0x2000, 0x7e5a, 0x681c, 0xa084, 0xffdf, 0x681e, 0x1078, 0x4776,
- 0x1078, 0x4a3a, 0x0078, 0x3888, 0xa684, 0x2000, 0x0040, 0x2fb7,
- 0x6818, 0xa084, 0x8000, 0x0040, 0x2fd5, 0x681b, 0x0015, 0xa684,
- 0x4000, 0x0040, 0x2fd5, 0x681b, 0x0007, 0x1078, 0x389c, 0x0078,
- 0x2459, 0x1078, 0x23eb, 0x2300, 0x0079, 0x2fde, 0x2fe1, 0x2fe3,
- 0x3016, 0x1078, 0x23eb, 0x7000, 0x0079, 0x2fe6, 0x2482, 0x2ff0,
- 0x2ff0, 0x300b, 0x2ff0, 0x3012, 0x300b, 0x2fee, 0x1078, 0x23eb,
- 0xa684, 0x0060, 0xa086, 0x0060, 0x00c0, 0x3007, 0xa6b4, 0xffbf,
- 0xa6b4, 0xbfff, 0xa6b5, 0x2000, 0x7e5a, 0x681c, 0xa084, 0xffbf,
- 0x681e, 0x1078, 0x4776, 0x1078, 0x4a3a, 0x0078, 0x3888, 0xa684,
- 0x2000, 0x0040, 0x2ffa, 0x6818, 0xa084, 0x8000, 0x0040, 0x3012,
- 0x681b, 0x0007, 0x781b, 0x00cd, 0x0078, 0x2459, 0x6820, 0xa085,
- 0x0004, 0x6822, 0x1078, 0x3853, 0xa6b5, 0x0800, 0x1078, 0x36c1,
- 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x2459, 0x2300, 0x0079,
- 0x3029, 0x302c, 0x302e, 0x3030, 0x1078, 0x23eb, 0x0078, 0x36ad,
- 0xa684, 0x0400, 0x00c0, 0x3059, 0x79e4, 0xa184, 0x0020, 0x0040,
- 0x3040, 0x78ec, 0xa084, 0x0003, 0x0040, 0x3040, 0x782b, 0x3009,
- 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb, 0x785a, 0x79e4,
- 0xa184, 0x0020, 0x0040, 0x3051, 0x78ec, 0xa084, 0x0003, 0x00c0,
- 0x3055, 0x2001, 0x0014, 0x0078, 0x2d01, 0xa184, 0x0007, 0x0079,
- 0x3091, 0x7a90, 0xa294, 0x0007, 0x789b, 0x0060, 0x79a8, 0x81ff,
- 0x0040, 0x308f, 0x789b, 0x0010, 0x7ba8, 0xa384, 0x0001, 0x00c0,
- 0x3080, 0x7ba8, 0x7ba8, 0xa386, 0x0001, 0x00c0, 0x3073, 0x2009,
- 0xfff7, 0x0078, 0x3079, 0xa386, 0x0003, 0x00c0, 0x3080, 0x2009,
- 0xffef, 0x0c7e, 0x7054, 0x2060, 0x6004, 0xa104, 0x6006, 0x0c7f,
- 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb, 0x785a, 0x782b,
- 0x3009, 0x6920, 0xa18c, 0xfdff, 0xa18c, 0xfeff, 0x6922, 0x0078,
- 0x3888, 0x299e, 0x29a9, 0x309b, 0x30a3, 0x3099, 0x3099, 0x3888,
- 0x3888, 0x1078, 0x23eb, 0x6920, 0xa18c, 0xfdff, 0xa18c, 0xfeff,
- 0x6922, 0x0078, 0x3892, 0x6920, 0xa18c, 0xfdff, 0xa18c, 0xfeff,
- 0x6922, 0x0078, 0x3888, 0x79e4, 0xa184, 0x0030, 0x0040, 0x30b5,
- 0x78ec, 0xa084, 0x0003, 0x00c0, 0x30dc, 0x7000, 0xa086, 0x0004,
- 0x00c0, 0x30cf, 0x706c, 0xa086, 0x0002, 0x00c0, 0x30c5, 0x2011,
- 0x0002, 0x2019, 0x0000, 0x0078, 0x2848, 0x706c, 0xa086, 0x0006,
- 0x0040, 0x30bf, 0x706c, 0xa086, 0x0004, 0x0040, 0x30bf, 0x7000,
- 0xa086, 0x0000, 0x0040, 0x2459, 0x6818, 0xa085, 0x8000, 0x681a,
- 0x2001, 0x0014, 0x0078, 0x2d01, 0xa184, 0x0007, 0x0079, 0x30e0,
- 0x3888, 0x3888, 0x30e8, 0x3888, 0x38ed, 0x38ed, 0x3888, 0x3888,
- 0xa684, 0x0080, 0x0040, 0x3117, 0x7194, 0x81ff, 0x0040, 0x3117,
- 0xa182, 0x000d, 0x00d0, 0x30f8, 0x7097, 0x0000, 0x0078, 0x30fd,
- 0xa182, 0x000c, 0x7096, 0x2009, 0x000c, 0x789b, 0x0061, 0x79aa,
- 0x157e, 0x137e, 0x147e, 0x7098, 0x8114, 0xa210, 0x729a, 0xa080,
- 0x000b, 0xad00, 0x2098, 0x20a1, 0x012b, 0x789b, 0x0000, 0x8108,
- 0x81ac, 0x53a6, 0x147f, 0x137f, 0x157f, 0x0078, 0x3892, 0xa684,
- 0x0400, 0x00c0, 0x3158, 0x6820, 0xa084, 0x0001, 0x0040, 0x3892,
- 0xa68c, 0x0060, 0xa684, 0x0060, 0x0040, 0x312c, 0xa086, 0x0060,
- 0x00c0, 0x312c, 0xa18d, 0x4000, 0xa18c, 0xfffb, 0x795a, 0x69b6,
- 0x789b, 0x0060, 0x78ab, 0x0000, 0x789b, 0x0061, 0x6818, 0xa085,
- 0x8000, 0x681a, 0x78aa, 0x8008, 0x810c, 0x0040, 0x3407, 0xa18c,
- 0x00f8, 0x00c0, 0x3407, 0x157e, 0x137e, 0x147e, 0x20a1, 0x012b,
- 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6,
- 0x147f, 0x137f, 0x157f, 0x6814, 0x8007, 0x7882, 0x0078, 0x3892,
- 0x6818, 0xa084, 0x8000, 0x0040, 0x315f, 0x681b, 0x0008, 0x781b,
- 0x00c3, 0x0078, 0x2459, 0x2300, 0x0079, 0x3166, 0x316b, 0x320a,
- 0x3169, 0x1078, 0x23eb, 0x7000, 0xa084, 0x0007, 0x0079, 0x3170,
- 0x2482, 0x317a, 0x31af, 0x3185, 0x3178, 0x2482, 0x3178, 0x3178,
- 0x1078, 0x23eb, 0x681c, 0xa084, 0x2000, 0x0040, 0x3193, 0x6008,
- 0xa085, 0x0002, 0x600a, 0x0078, 0x3193, 0x68c0, 0xa005, 0x00c0,
- 0x31af, 0x6920, 0xa18d, 0x0001, 0x6922, 0x68c3, 0x0001, 0x6800,
- 0x706a, 0x0078, 0x31a9, 0x6920, 0xa18d, 0x0001, 0x6922, 0x6800,
- 0x6006, 0xa005, 0x00c0, 0x319d, 0x6002, 0x681c, 0xa084, 0x000e,
- 0x0040, 0x31a9, 0x7014, 0x68ba, 0x7130, 0xa188, 0x7400, 0x0078,
- 0x31ab, 0x2009, 0x7500, 0x2104, 0x6802, 0x2d0a, 0x7162, 0x6eb6,
- 0xa684, 0x0060, 0x0040, 0x3208, 0xa684, 0x0800, 0x00c0, 0x31c3,
- 0xa684, 0x7fff, 0x68b6, 0x6894, 0x68a6, 0x6898, 0x68aa, 0x1078,
- 0x4776, 0x0078, 0x3208, 0xa684, 0x0020, 0x0040, 0x31d8, 0x68c0,
- 0xa005, 0x0040, 0x31cf, 0x1078, 0x4b78, 0x0078, 0x31d2, 0xa006,
- 0x1078, 0x4b30, 0x79d8, 0x7adc, 0x69aa, 0x6aa6, 0x0078, 0x31de,
- 0x1078, 0x37fc, 0x69aa, 0x6aa6, 0x1078, 0x4b30, 0xa684, 0x8000,
- 0x0040, 0x3208, 0xa684, 0x7fff, 0x68b6, 0x2001, 0x0076, 0x1078,
- 0x3918, 0x2010, 0x2001, 0x0078, 0x1078, 0x3918, 0x2008, 0xa684,
- 0x0020, 0x00c0, 0x3200, 0x2001, 0x007a, 0x1078, 0x3918, 0x801b,
- 0x00c8, 0x31fb, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000,
- 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae,
- 0x0078, 0x2482, 0x0078, 0x36ad, 0x7037, 0x0000, 0xa282, 0x0006,
- 0x0050, 0x3214, 0x1078, 0x23eb, 0x7000, 0xa084, 0x0007, 0x10c0,
- 0x39be, 0x2300, 0x0079, 0x321c, 0x321f, 0x3248, 0x325c, 0x2200,
- 0x0079, 0x3222, 0x3246, 0x36ad, 0x3228, 0x3246, 0x3278, 0x32ba,
- 0x7003, 0x0005, 0x2001, 0x7610, 0x2068, 0x704a, 0x157e, 0x20a9,
- 0x0031, 0x2003, 0x0000, 0x8000, 0x0070, 0x3238, 0x0078, 0x3231,
- 0x157f, 0xad80, 0x0009, 0x7036, 0x6817, 0x0000, 0x68b7, 0x0700,
- 0x6823, 0x0800, 0x6827, 0x0003, 0x0078, 0x369d, 0x1078, 0x23eb,
- 0x7003, 0x0005, 0x2001, 0x7610, 0x2068, 0x704a, 0xad80, 0x0009,
- 0x7036, 0x2200, 0x0079, 0x3254, 0x36ad, 0x325a, 0x325a, 0x3278,
- 0x325a, 0x36ad, 0x1078, 0x23eb, 0x7003, 0x0005, 0x2001, 0x7610,
- 0x2068, 0x704a, 0xad80, 0x0009, 0x7036, 0x2200, 0x0079, 0x3268,
- 0x3270, 0x326e, 0x326e, 0x3270, 0x326e, 0x3270, 0x1078, 0x23eb,
- 0x1078, 0x36d1, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x2459,
- 0x7003, 0x0002, 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8,
- 0xa484, 0x001f, 0xa215, 0x2069, 0x7500, 0x2d04, 0x2d08, 0x7162,
- 0x2068, 0xa005, 0x0040, 0x3293, 0x6814, 0xa206, 0x0040, 0x32af,
- 0x6800, 0x0078, 0x3286, 0x7003, 0x0005, 0x2001, 0x7610, 0x2068,
- 0x704a, 0x7036, 0x157e, 0x20a9, 0x0031, 0x2003, 0x0000, 0x8000,
- 0x0070, 0x32a4, 0x0078, 0x329d, 0x157f, 0xad80, 0x0009, 0x7036,
- 0x6a16, 0x68b7, 0x0700, 0x6823, 0x0800, 0x6827, 0x0003, 0x6eb4,
- 0x7e5a, 0x6820, 0xa084, 0x0c00, 0x0040, 0x3309, 0x1078, 0x36c9,
- 0x0078, 0x3309, 0x7003, 0x0002, 0x7a80, 0xa294, 0x0f00, 0x789b,
- 0x0018, 0x7ca8, 0xa484, 0x001f, 0xa215, 0x79a8, 0x79a8, 0xa18c,
- 0x00ff, 0xa1e8, 0x7400, 0x2d04, 0x2d08, 0x7162, 0x2068, 0xa005,
- 0x0040, 0x32d9, 0x6814, 0xa206, 0x0040, 0x32f4, 0x6800, 0x0078,
- 0x32cc, 0x7003, 0x0005, 0x2001, 0x7610, 0x2068, 0x704a, 0x157e,
- 0x20a9, 0x0031, 0x2003, 0x0000, 0x8000, 0x0070, 0x32e9, 0x0078,
- 0x32e2, 0x157f, 0xad80, 0x0009, 0x7036, 0x6a16, 0x68b7, 0x0700,
- 0x6823, 0x0800, 0x6827, 0x0003, 0x6eb4, 0x7e5a, 0x6820, 0xa084,
- 0x0c00, 0x0040, 0x3309, 0xa084, 0x0800, 0x0040, 0x3303, 0x1078,
- 0x36cd, 0x0078, 0x3309, 0x1078, 0x36c9, 0x708b, 0x0000, 0x0078,
- 0x3309, 0x027e, 0x8207, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
- 0xa080, 0x5380, 0x2060, 0x7056, 0x6000, 0x705a, 0x6004, 0x705e,
- 0xa684, 0x0060, 0x0040, 0x3361, 0x6b98, 0x6c94, 0x69ac, 0x68b0,
- 0xa105, 0x00c0, 0x3343, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0xa6b4,
- 0xb7ff, 0x7e5a, 0xa684, 0x0060, 0xa086, 0x0060, 0x0040, 0x3361,
- 0x68c0, 0xa005, 0x0040, 0x333c, 0x7003, 0x0003, 0x682b, 0x0000,
- 0x1078, 0x4a29, 0x0078, 0x333e, 0x1078, 0x4a3a, 0xa6b5, 0x2000,
- 0x7e5a, 0x0078, 0x3361, 0x68b0, 0xa31a, 0x2100, 0xa423, 0x2400,
- 0xa305, 0x0040, 0x3361, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0x68b0,
- 0xa6b4, 0xbfff, 0x7e5a, 0x007e, 0x68c0, 0xa005, 0x007f, 0x0040,
- 0x335f, 0x7003, 0x0003, 0x1078, 0x4a29, 0x0078, 0x3361, 0x1078,
- 0x4a85, 0x077f, 0x1078, 0x37ef, 0x2009, 0x0065, 0xa684, 0x0004,
- 0x0040, 0x3382, 0x78e4, 0xa084, 0x0030, 0x0040, 0x337a, 0x78ec,
- 0xa084, 0x0003, 0x0040, 0x337a, 0x782b, 0x3008, 0x2009, 0x0065,
- 0x0078, 0x3382, 0x0f7e, 0x2079, 0x5100, 0x1078, 0x4776, 0x0f7f,
- 0x0040, 0x2482, 0x791a, 0x2d00, 0x704a, 0x8207, 0xa084, 0x000f,
- 0x8003, 0x8003, 0x8003, 0xa080, 0x5380, 0x2048, 0x0078, 0x2459,
- 0x6020, 0xa005, 0x0040, 0x339c, 0x8001, 0x6022, 0x6008, 0xa085,
- 0x0008, 0x600a, 0x7010, 0x6026, 0x007c, 0xa006, 0x1078, 0x4776,
- 0x6817, 0x0000, 0x681b, 0x0001, 0x6823, 0x0040, 0x681f, 0x0100,
- 0x7000, 0xa084, 0x0007, 0x0079, 0x33ad, 0x2482, 0x33b7, 0x33b7,
- 0x33d4, 0x33bf, 0x33bd, 0x33bf, 0x33b5, 0x1078, 0x23eb, 0x1078,
- 0x33df, 0x1078, 0x33d8, 0x1078, 0x1c70, 0x0078, 0x2482, 0x706c,
- 0x706f, 0x0000, 0x7093, 0x0000, 0x0079, 0x33c6, 0x33d0, 0x33d0,
- 0x33ce, 0x33ce, 0x33ce, 0x33d0, 0x33ce, 0x33d0, 0x0079, 0x2861,
- 0x706f, 0x0000, 0x0078, 0x2482, 0x681b, 0x0000, 0x0078, 0x2f17,
- 0x6800, 0xa005, 0x00c0, 0x33dd, 0x6002, 0x6006, 0x007c, 0x6010,
- 0xa005, 0x0040, 0x33e8, 0x8001, 0x00d0, 0x33e8, 0x1078, 0x23eb,
- 0x6012, 0x6008, 0xa084, 0xffef, 0x600a, 0x007c, 0x6018, 0xa005,
- 0x0040, 0x33f4, 0x8001, 0x601a, 0x007c, 0x1078, 0x3912, 0x681b,
- 0x0018, 0x0078, 0x342b, 0x1078, 0x3912, 0x681b, 0x0019, 0x0078,
- 0x342b, 0x1078, 0x3912, 0x681b, 0x001a, 0x0078, 0x342b, 0x1078,
- 0x3912, 0x681b, 0x0003, 0x0078, 0x342b, 0x7780, 0x1078, 0x37ef,
- 0x7184, 0xa18c, 0x00ff, 0xa1e8, 0x7400, 0x2d04, 0x2d08, 0x2068,
- 0xa005, 0x00c0, 0x341d, 0x0078, 0x2482, 0x6814, 0x7280, 0xa206,
- 0x0040, 0x3425, 0x6800, 0x0078, 0x3416, 0x6800, 0x200a, 0x681b,
- 0x0005, 0x708b, 0x0000, 0x1078, 0x33df, 0x6820, 0xa084, 0x0001,
- 0x00c0, 0x3434, 0x1078, 0x33d8, 0x1078, 0x33ee, 0x681f, 0x0000,
- 0x6823, 0x0020, 0x1078, 0x1c70, 0x0078, 0x2482, 0xa282, 0x0003,
- 0x00c0, 0x369d, 0x7da8, 0xa5ac, 0x00ff, 0x7ca8, 0xa4a4, 0x00ff,
- 0x6920, 0xa18d, 0x0080, 0x6922, 0xa184, 0x0100, 0x0040, 0x34a2,
- 0xa18c, 0xfeff, 0x6922, 0xa4a4, 0x00ff, 0x0040, 0x348c, 0xa482,
- 0x000c, 0x0048, 0x345f, 0x0040, 0x345f, 0x2021, 0x000c, 0x852b,
- 0x852b, 0x1078, 0x3760, 0x0040, 0x3469, 0x1078, 0x355b, 0x0078,
- 0x3495, 0x1078, 0x371b, 0x0c7e, 0x2960, 0x6004, 0xa084, 0xfff5,
- 0x6006, 0x1078, 0x3586, 0x0c7f, 0x6920, 0xa18d, 0x0100, 0x6922,
- 0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x3486,
- 0x782b, 0x3008, 0x781b, 0x0056, 0x0078, 0x2459, 0x782b, 0x3008,
- 0x781b, 0x0065, 0x0078, 0x2459, 0x0c7e, 0x2960, 0x6004, 0xa084,
- 0xfff5, 0x6006, 0x1078, 0x3586, 0x0c7f, 0x7e58, 0xa684, 0x0400,
- 0x00c0, 0x349e, 0x781b, 0x0058, 0x0078, 0x2459, 0x781b, 0x0065,
- 0x0078, 0x2459, 0x0c7e, 0x7054, 0x2060, 0x6100, 0xa18c, 0x1000,
- 0x0040, 0x34e2, 0x6208, 0x8217, 0xa294, 0x00ff, 0xa282, 0x000c,
- 0x0048, 0x34b6, 0x0040, 0x34b6, 0x2011, 0x000c, 0x2400, 0xa202,
- 0x00c8, 0x34bb, 0x2220, 0x6208, 0xa294, 0x00ff, 0x7018, 0xa086,
- 0x0028, 0x00c0, 0x34cb, 0xa282, 0x0019, 0x00c8, 0x34d1, 0x2011,
- 0x0019, 0x0078, 0x34d1, 0xa282, 0x000c, 0x00c8, 0x34d1, 0x2011,
- 0x000c, 0x2200, 0xa502, 0x00c8, 0x34d6, 0x2228, 0x1078, 0x371f,
- 0x852b, 0x852b, 0x1078, 0x3760, 0x0040, 0x34e2, 0x1078, 0x355b,
- 0x0078, 0x34e6, 0x1078, 0x371b, 0x1078, 0x3586, 0x7858, 0xa085,
- 0x0004, 0x785a, 0x0c7f, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078,
- 0x2459, 0x0c7e, 0x2960, 0x6000, 0xa084, 0x1000, 0x00c0, 0x3509,
- 0x6010, 0xa084, 0x000f, 0x00c0, 0x3503, 0x6104, 0xa18c, 0xfff5,
- 0x6106, 0x0c7f, 0x007c, 0x2011, 0x0032, 0x2019, 0x0000, 0x0078,
- 0x3530, 0x68a0, 0xa084, 0x0200, 0x00c0, 0x3503, 0x6208, 0xa294,
- 0x00ff, 0x7018, 0xa086, 0x0028, 0x00c0, 0x351e, 0xa282, 0x0019,
- 0x00c8, 0x3524, 0x2011, 0x0019, 0x0078, 0x3524, 0xa282, 0x000c,
- 0x00c8, 0x3524, 0x2011, 0x000c, 0x6308, 0x831f, 0xa39c, 0x00ff,
- 0xa382, 0x000c, 0x0048, 0x3530, 0x0040, 0x3530, 0x2019, 0x000c,
- 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa,
- 0xa8c0, 0x0005, 0x6820, 0xa085, 0x0100, 0x6822, 0x0c7f, 0x007c,
- 0x0c7e, 0x2960, 0xa18c, 0xfff5, 0x6106, 0x2011, 0x0032, 0x2019,
- 0x0000, 0x0078, 0x354b, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab,
- 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820, 0xa085, 0x0100,
- 0x6822, 0x0c7f, 0x007c, 0x0c7e, 0x7154, 0x2160, 0x1078, 0x3562,
- 0x0c7f, 0x007c, 0x2008, 0xa084, 0xfff0, 0xa425, 0x7c86, 0x6018,
- 0x789a, 0x7cae, 0x6412, 0x78a4, 0xa084, 0xfff8, 0xa18c, 0x0007,
- 0xa105, 0x78a6, 0x6016, 0x788a, 0xa4a4, 0x000f, 0x8427, 0x8204,
- 0x8004, 0xa084, 0x00ff, 0xa405, 0x600e, 0x78ec, 0xd08c, 0x00c0,
- 0x3585, 0x6004, 0xa084, 0xfff5, 0x6006, 0x007c, 0x0c7e, 0x7054,
- 0x2060, 0x1078, 0x358d, 0x0c7f, 0x007c, 0x6018, 0x789a, 0x78a4,
- 0xa084, 0xfff0, 0x78a6, 0x6012, 0x7884, 0xa084, 0xfff0, 0x7886,
- 0x007c, 0xa282, 0x0002, 0x00c0, 0x369d, 0x7aa8, 0x6920, 0xa18d,
- 0x0080, 0x6922, 0xa184, 0x0200, 0x0040, 0x35e2, 0xa18c, 0xfdff,
- 0x6922, 0xa294, 0x00ff, 0xa282, 0x0002, 0x00c8, 0x369d, 0x1078,
- 0x362b, 0x1078, 0x3586, 0xa980, 0x0001, 0x200c, 0x1078, 0x37eb,
- 0x1078, 0x34f1, 0x88ff, 0x0040, 0x35d5, 0x789b, 0x0060, 0x2800,
- 0x78aa, 0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0,
- 0x35cf, 0x782b, 0x3008, 0x781b, 0x0056, 0x0078, 0x2459, 0x782b,
- 0x3008, 0x781b, 0x0065, 0x0078, 0x2459, 0x7e58, 0xa684, 0x0400,
- 0x00c0, 0x35de, 0x781b, 0x0058, 0x0078, 0x2459, 0x781b, 0x0065,
- 0x0078, 0x2459, 0xa282, 0x0002, 0x00c8, 0x35ea, 0xa284, 0x0001,
- 0x0040, 0x35f4, 0x7154, 0xa188, 0x0000, 0x210c, 0xa18c, 0x2000,
- 0x00c0, 0x35f4, 0x2011, 0x0000, 0x1078, 0x370d, 0x1078, 0x362b,
- 0x1078, 0x3586, 0x7858, 0xa085, 0x0004, 0x785a, 0x782b, 0x3008,
- 0x781b, 0x0065, 0x0078, 0x2459, 0x0c7e, 0x027e, 0x2960, 0x6000,
- 0x2011, 0x0001, 0xa084, 0x2000, 0x00c0, 0x361b, 0x6014, 0xa084,
- 0x0040, 0x00c0, 0x3619, 0xa18c, 0xffef, 0x6106, 0xa006, 0x0078,
- 0x3628, 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab,
- 0x0003, 0x7aaa, 0xa8c0, 0x0004, 0x6820, 0xa085, 0x0200, 0x6822,
- 0x027f, 0x0c7f, 0x007c, 0x0c7e, 0x7054, 0x2060, 0x1078, 0x3632,
- 0x0c7f, 0x007c, 0x82ff, 0x0040, 0x3637, 0x2011, 0x0040, 0x6018,
- 0xa080, 0x0002, 0x789a, 0x78a4, 0xa084, 0xffbf, 0xa205, 0x78a6,
- 0x788a, 0x6016, 0x78ec, 0xd08c, 0x00c0, 0x364a, 0x6004, 0xa084,
- 0xffef, 0x6006, 0x007c, 0x007e, 0x7000, 0xa086, 0x0003, 0x0040,
- 0x3654, 0x007f, 0x0078, 0x3657, 0x007f, 0x0078, 0x3699, 0xa684,
- 0x0020, 0x0040, 0x3699, 0x7888, 0xa084, 0x0040, 0x0040, 0x3699,
- 0x7bb8, 0xa384, 0x003f, 0x831b, 0x00c8, 0x3667, 0x8000, 0xa005,
- 0x0040, 0x367d, 0x831b, 0x00c8, 0x3670, 0x8001, 0x0040, 0x3695,
- 0xa684, 0x4000, 0x0040, 0x367d, 0x78b8, 0x801b, 0x00c8, 0x3679,
- 0x8000, 0xa084, 0x003f, 0x00c0, 0x3695, 0xa6b4, 0xbfff, 0x7e5a,
- 0x79d8, 0x7adc, 0x2001, 0x0001, 0xa108, 0x00c8, 0x3689, 0xa291,
- 0x0000, 0x79d2, 0x79da, 0x7ad6, 0x7ade, 0x1078, 0x4b30, 0x781b,
- 0x0064, 0x1078, 0x49b5, 0x0078, 0x2459, 0x781b, 0x0064, 0x0078,
- 0x2459, 0x781b, 0x0065, 0x0078, 0x2459, 0x1078, 0x36d5, 0x782b,
- 0x3008, 0x781b, 0x0065, 0x0078, 0x2459, 0x1078, 0x36c1, 0x782b,
- 0x3008, 0x781b, 0x0065, 0x0078, 0x2459, 0x6827, 0x0002, 0x1078,
- 0x36c9, 0x78e4, 0xa084, 0x0030, 0x0040, 0x2482, 0x78ec, 0xa084,
- 0x0003, 0x0040, 0x2482, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078,
- 0x2459, 0x2001, 0x0005, 0x0078, 0x36d7, 0x2001, 0x000c, 0x0078,
- 0x36d7, 0x2001, 0x0006, 0x0078, 0x36d7, 0x2001, 0x000d, 0x0078,
- 0x36d7, 0x2001, 0x0009, 0x0078, 0x36d7, 0x2001, 0x0007, 0x789b,
- 0x0010, 0x78aa, 0x789b, 0x0060, 0x78ab, 0x0001, 0xa6b5, 0x0004,
- 0x7e5a, 0x007c, 0x077e, 0x873f, 0xa7bc, 0x000f, 0x873b, 0x873b,
- 0x8703, 0xa0e0, 0x5380, 0xa7b8, 0x0020, 0x7f9a, 0x79a4, 0xa184,
- 0x000f, 0x0040, 0x36fb, 0xa184, 0xfff0, 0x78a6, 0x6012, 0x6004,
- 0xa085, 0x0008, 0x6006, 0x8738, 0x8738, 0x7f9a, 0x79a4, 0xa184,
- 0x0040, 0x0040, 0x370b, 0xa184, 0xffbf, 0x78a6, 0x6016, 0x6004,
- 0xa085, 0x0010, 0x6006, 0x077f, 0x007c, 0x789b, 0x0010, 0x78ab,
- 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0060,
- 0x78ab, 0x0004, 0x007c, 0x2021, 0x0000, 0x2029, 0x0032, 0x789b,
- 0x0010, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa,
- 0x7caa, 0x789b, 0x0060, 0x78ab, 0x0005, 0x007c, 0x157e, 0x8007,
- 0xa084, 0x00ff, 0x8003, 0x8003, 0xa080, 0x0020, 0x789a, 0x79a4,
- 0xa18c, 0xfff0, 0x2001, 0x5146, 0x2004, 0xa082, 0x0028, 0x0040,
- 0x3749, 0x2021, 0x37d2, 0x2019, 0x0014, 0x20a9, 0x000c, 0x0078,
- 0x374f, 0x2021, 0x37de, 0x2019, 0x0019, 0x20a9, 0x000d, 0x2011,
- 0x0064, 0x2404, 0xa084, 0xfff0, 0xa106, 0x0040, 0x375e, 0x8420,
- 0x2300, 0xa210, 0x0070, 0x375e, 0x0078, 0x3751, 0x157f, 0x007c,
- 0x157e, 0x2009, 0x5146, 0x210c, 0xa182, 0x0032, 0x0048, 0x3774,
- 0x0040, 0x3778, 0x2009, 0x37c4, 0x2019, 0x0011, 0x20a9, 0x000e,
- 0x2011, 0x0032, 0x0078, 0x378a, 0xa182, 0x0028, 0x0040, 0x3782,
- 0x2009, 0x37d2, 0x2019, 0x0014, 0x20a9, 0x000c, 0x2011, 0x0064,
- 0x0078, 0x378a, 0x2009, 0x37de, 0x2019, 0x0019, 0x20a9, 0x000d,
- 0x2011, 0x0064, 0x2200, 0xa502, 0x0040, 0x379a, 0x0048, 0x379a,
- 0x8108, 0x2300, 0xa210, 0x0070, 0x3797, 0x0078, 0x378a, 0x157f,
- 0xa006, 0x007c, 0x157f, 0xa582, 0x0064, 0x00c8, 0x37a9, 0x7808,
- 0xa085, 0x0070, 0x780a, 0x7044, 0xa085, 0x0070, 0x7046, 0x0078,
- 0x37a9, 0x78ec, 0xa084, 0x0300, 0x0040, 0x37b1, 0x2104, 0x0078,
- 0x37c2, 0x2104, 0xa09e, 0x1102, 0x00c0, 0x37c2, 0x2001, 0x04fd,
- 0x2004, 0xa082, 0x0005, 0x0048, 0x37c1, 0x2001, 0x1201, 0x0078,
- 0x37c2, 0x2104, 0xa005, 0x007c, 0x1102, 0x3002, 0x3202, 0x4203,
- 0x4403, 0x5404, 0x5604, 0x6605, 0x6805, 0x7806, 0x7a06, 0x0c07,
- 0x0c07, 0x0e07, 0x3202, 0x4202, 0x5202, 0x6202, 0x7202, 0x6605,
- 0x7605, 0x7805, 0x7a05, 0x7c05, 0x7e05, 0x7f05, 0x2202, 0x3202,
- 0x4202, 0x5202, 0x5404, 0x6404, 0x7404, 0x7604, 0x7804, 0x7a04,
- 0x7c04, 0x7e04, 0x7f04, 0x789b, 0x0010, 0xa046, 0x007c, 0xa784,
- 0x0f00, 0x800b, 0xa784, 0x001f, 0x8003, 0x8003, 0x8003, 0x8003,
- 0xa105, 0xa0e0, 0x5400, 0x007c, 0x79d8, 0x7adc, 0x78d0, 0x801b,
- 0x00c8, 0x3803, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000,
- 0x007c, 0x0f7e, 0x2079, 0x0100, 0x2009, 0x5140, 0x2091, 0x8000,
- 0x2104, 0x0079, 0x3813, 0x3849, 0x381d, 0x381d, 0x381d, 0x381d,
- 0x381d, 0x381d, 0x384d, 0x1078, 0x23eb, 0x784b, 0x0004, 0x7848,
- 0xa084, 0x0004, 0x00c0, 0x381f, 0x784b, 0x0008, 0x7848, 0xa084,
- 0x0008, 0x00c0, 0x3826, 0x68b4, 0xa085, 0x4000, 0x68b6, 0x7858,
- 0xa085, 0x4000, 0x785a, 0x7830, 0xa084, 0x0080, 0x00c0, 0x3849,
- 0x0018, 0x3849, 0x681c, 0xa084, 0x0020, 0x00c0, 0x3847, 0x0e7e,
- 0x2071, 0x5140, 0x1078, 0x389c, 0x0e7f, 0x0078, 0x3849, 0x781b,
- 0x00cd, 0x2091, 0x8001, 0x0f7f, 0x007c, 0x70b3, 0x0000, 0x1078,
- 0x3a76, 0x0078, 0x3849, 0x0c7e, 0x6814, 0x8007, 0xa084, 0x000f,
- 0x8003, 0x8003, 0x8003, 0xa0e0, 0x5380, 0x6004, 0xa084, 0x000a,
- 0x00c0, 0x3886, 0x6108, 0xa194, 0xff00, 0x0040, 0x3886, 0xa18c,
- 0x00ff, 0x2001, 0x0019, 0xa106, 0x0040, 0x3875, 0x2001, 0x0032,
- 0xa106, 0x0040, 0x3879, 0x0078, 0x387d, 0x2009, 0x0020, 0x0078,
- 0x387f, 0x2009, 0x003f, 0x0078, 0x387f, 0x2011, 0x0000, 0x2100,
- 0xa205, 0x600a, 0x6004, 0xa085, 0x0002, 0x6006, 0x0c7f, 0x007c,
- 0x781b, 0x0065, 0x0078, 0x2459, 0x782b, 0x3008, 0x781b, 0x0065,
- 0x0078, 0x2459, 0x781b, 0x0058, 0x0078, 0x2459, 0x782b, 0x3008,
- 0x781b, 0x0056, 0x0078, 0x2459, 0x2009, 0x5120, 0x210c, 0xa186,
- 0x0000, 0x0040, 0x38b0, 0xa186, 0x0001, 0x0040, 0x38b3, 0x2009,
- 0x5138, 0x200b, 0x000b, 0x706f, 0x0001, 0x781b, 0x0048, 0x007c,
- 0x781b, 0x00c7, 0x007c, 0x2009, 0x5138, 0x200b, 0x000a, 0x007c,
- 0x2009, 0x5120, 0x210c, 0xa186, 0x0000, 0x0040, 0x38d3, 0xa186,
- 0x0001, 0x0040, 0x38cd, 0x2009, 0x5138, 0x200b, 0x000b, 0x706f,
- 0x0001, 0x781b, 0x0048, 0x0078, 0x2459, 0x2009, 0x5138, 0x200b,
- 0x000a, 0x0078, 0x2459, 0x782b, 0x3008, 0x781b, 0x00c7, 0x0078,
- 0x2459, 0x781b, 0x00cd, 0x0078, 0x2459, 0x782b, 0x3008, 0x781b,
- 0x00cd, 0x0078, 0x2459, 0x781b, 0x008e, 0x0078, 0x2459, 0x782b,
- 0x3008, 0x781b, 0x008e, 0x0078, 0x2459, 0x6818, 0xa084, 0x8000,
- 0x0040, 0x38f4, 0x681b, 0x001d, 0x706f, 0x0001, 0x781b, 0x0048,
- 0x0078, 0x2459, 0x007e, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x3910,
- 0x7808, 0xa084, 0xfffc, 0x780a, 0x0005, 0x0005, 0x0005, 0x0005,
- 0x78ec, 0xa084, 0x0021, 0x0040, 0x3910, 0x7044, 0x780a, 0xa005,
- 0x007f, 0x007c, 0x7044, 0xa085, 0x0002, 0x7046, 0x780a, 0x007c,
- 0x007e, 0x7830, 0xa084, 0x0040, 0x00c0, 0x3919, 0x0098, 0x3924,
- 0x007f, 0x789a, 0x78ac, 0x007c, 0x7808, 0xa084, 0xfffd, 0x780a,
- 0x0005, 0x0005, 0x0005, 0x0005, 0x78ec, 0xa084, 0x0021, 0x0040,
- 0x3933, 0x0098, 0x3931, 0x007f, 0x789a, 0x78ac, 0x007e, 0x7044,
- 0x780a, 0x007f, 0x007c, 0x78ec, 0xa084, 0x0002, 0x00c0, 0x4760,
- 0xa784, 0x007d, 0x00c0, 0x3947, 0x2700, 0x1078, 0x23eb, 0xa784,
- 0x0001, 0x00c0, 0x2f6d, 0xa784, 0x0070, 0x0040, 0x3957, 0x0c7e,
- 0x2d60, 0x2f68, 0x1078, 0x2396, 0x2d78, 0x2c68, 0x0c7f, 0xa784,
- 0x0008, 0x0040, 0x3964, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003,
- 0x0040, 0x2482, 0x0078, 0x3888, 0xa784, 0x0004, 0x0040, 0x3997,
- 0x78b8, 0xa084, 0x4001, 0x0040, 0x3997, 0x784b, 0x0008, 0x78ec,
- 0xa084, 0x0003, 0x0040, 0x2482, 0x78e4, 0xa084, 0x0007, 0xa086,
- 0x0001, 0x00c0, 0x3997, 0x78c0, 0xa085, 0x4800, 0x2030, 0x7e5a,
- 0x781b, 0x00cd, 0x0078, 0x2459, 0x784b, 0x0008, 0x6818, 0xa084,
- 0x8000, 0x0040, 0x3993, 0x681b, 0x0015, 0xa684, 0x4000, 0x0040,
- 0x3993, 0x681b, 0x0007, 0x1078, 0x389c, 0x0078, 0x2459, 0x681b,
- 0x0003, 0x7858, 0xa084, 0x3f00, 0x681e, 0x682f, 0x0000, 0x6833,
- 0x0000, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x2965,
- 0x0018, 0x2459, 0x0078, 0x36a5, 0x6b14, 0x8307, 0xa084, 0x000f,
- 0x8003, 0x8003, 0x8003, 0xa080, 0x5380, 0x2060, 0x2048, 0x7056,
- 0x6000, 0x705a, 0x6004, 0x705e, 0x2a60, 0x007c, 0x0079, 0x39c0,
- 0x39c8, 0x39c9, 0x39c8, 0x39cb, 0x39c8, 0x39c8, 0x39c8, 0x39d0,
- 0x007c, 0x1078, 0x33ee, 0x1078, 0x4776, 0x7038, 0x600a, 0x007c,
- 0x70a0, 0xa005, 0x0040, 0x39dd, 0x2068, 0x1078, 0x1b62, 0x1078,
- 0x46f8, 0x1078, 0x46ff, 0x70a3, 0x0000, 0x007c, 0x0e7e, 0x2091,
- 0x8000, 0x2071, 0x5140, 0x7000, 0xa086, 0x0007, 0x00c0, 0x39f4,
- 0x6110, 0x70bc, 0xa106, 0x00c0, 0x39f4, 0x0e7f, 0x1078, 0x1b6f,
- 0x1078, 0x39fa, 0xa006, 0x007c, 0x2091, 0x8001, 0x0e7f, 0xa085,
- 0x0001, 0x007c, 0x0f7e, 0x0e7e, 0x2071, 0x5140, 0x0078, 0x21fa,
- 0x785b, 0x0000, 0x70af, 0x000e, 0x2009, 0x0100, 0x017e, 0x70a0,
- 0xa06d, 0x0040, 0x3a0f, 0x70a3, 0x0000, 0x0078, 0x3a15, 0x70b3,
- 0x0000, 0x1078, 0x1b8b, 0x0040, 0x3a1b, 0x70ac, 0x6826, 0x1078,
- 0x3af8, 0x0078, 0x3a0f, 0x017f, 0x157e, 0x0c7e, 0x0d7e, 0x20a9,
- 0x0008, 0x2061, 0x7510, 0x6000, 0xa105, 0x6002, 0x601c, 0xa06d,
- 0x0040, 0x3a33, 0x6800, 0x601e, 0x1078, 0x195a, 0x6008, 0x8000,
- 0x600a, 0x0078, 0x3a26, 0x6018, 0xa06d, 0x0040, 0x3a3d, 0x6800,
- 0x601a, 0x1078, 0x195a, 0x0078, 0x3a33, 0xace0, 0x0008, 0x0070,
- 0x3a43, 0x0078, 0x3a23, 0x709c, 0xa084, 0x8000, 0x0040, 0x3a4a,
- 0x1078, 0x3b72, 0x0d7f, 0x0c7f, 0x157f, 0x007c, 0x127e, 0x2091,
- 0x2300, 0x6804, 0xa084, 0x000f, 0x0079, 0x3a56, 0x3a66, 0x3a66,
- 0x3a66, 0x3a66, 0x3a66, 0x3a66, 0x3a68, 0x3a6e, 0x3a66, 0x3a66,
- 0x3a66, 0x3a66, 0x3a66, 0x3a70, 0x3a66, 0x3a68, 0x1078, 0x23eb,
- 0x1078, 0x44d0, 0x1078, 0x195a, 0x0078, 0x3a74, 0x6827, 0x000b,
- 0x1078, 0x44d0, 0x1078, 0x3af8, 0x127f, 0x007c, 0x127e, 0x2091,
- 0x2300, 0x0098, 0x3a92, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x3a92,
- 0x0d7e, 0x1078, 0x4708, 0x2d00, 0x682e, 0x2009, 0x0004, 0x2001,
- 0x0000, 0x6827, 0x0084, 0x1078, 0x46c1, 0x1078, 0x3af8, 0x0d7f,
- 0x0078, 0x3ac6, 0x7948, 0xa185, 0x4000, 0x784a, 0x0098, 0x3a9b,
- 0x794a, 0x0078, 0x3a80, 0x7828, 0xa086, 0x1834, 0x00c0, 0x3aa4,
- 0xa185, 0x0004, 0x0078, 0x3aab, 0x7828, 0xa086, 0x1814, 0x00c0,
- 0x3a98, 0xa185, 0x000c, 0x784a, 0x789b, 0x000e, 0x78ab, 0x0002,
- 0x7858, 0xa084, 0x00ff, 0xa085, 0x0400, 0x785a, 0x70b4, 0xa080,
- 0x0091, 0x781a, 0x6827, 0x0284, 0x682c, 0x6836, 0x6830, 0x683a,
- 0x2009, 0x0004, 0x2001, 0x0000, 0x1078, 0x46c1, 0x127f, 0x007c,
- 0x0d7e, 0x6b14, 0x1078, 0x1bfd, 0x0040, 0x3ad5, 0x2068, 0x6827,
- 0x0002, 0x1078, 0x3af8, 0x0078, 0x3aca, 0x0d7f, 0x007c, 0x0d7e,
- 0x6b14, 0x6c28, 0xa4a4, 0x00ff, 0x1078, 0x1b9b, 0x0040, 0x3ae5,
- 0x2068, 0x6827, 0x0002, 0x1078, 0x3af8, 0x0d7f, 0x007c, 0x0d7e,
- 0x6b14, 0xa39c, 0x00ff, 0x1078, 0x1bce, 0x0040, 0x3af6, 0x2068,
- 0x6827, 0x0002, 0x1078, 0x3af8, 0x0078, 0x3aeb, 0x0d7f, 0x007c,
- 0x0c7e, 0x6914, 0x1078, 0x3b69, 0x6904, 0xa18c, 0x00ff, 0xa186,
- 0x0006, 0x0040, 0x3b13, 0xa186, 0x000d, 0x0040, 0x3b32, 0xa186,
- 0x0017, 0x00c0, 0x3b0f, 0x1078, 0x195a, 0x0078, 0x3b11, 0x1078,
- 0x1c72, 0x0c7f, 0x007c, 0x6004, 0x8001, 0x0048, 0x3b30, 0x6006,
- 0x2009, 0x0000, 0xa684, 0x0001, 0x00c0, 0x3b20, 0xa18d, 0x8000,
- 0xa684, 0x0004, 0x0040, 0x3b26, 0xa18d, 0x0002, 0x691e, 0x6823,
- 0x0000, 0x7104, 0x810f, 0x6818, 0xa105, 0x681a, 0x0078, 0x3b0f,
- 0x1078, 0x23eb, 0x6018, 0xa005, 0x00c0, 0x3b41, 0x6008, 0x8001,
- 0x0048, 0x3b41, 0x600a, 0x601c, 0x6802, 0x2d00, 0x601e, 0x0078,
- 0x3b57, 0xac88, 0x0006, 0x2104, 0xa005, 0x0040, 0x3b4a, 0x2008,
- 0x0078, 0x3b43, 0x6802, 0x2d0a, 0x6008, 0x8001, 0x0048, 0x3b11,
- 0x600a, 0x6018, 0x2068, 0x6800, 0x601a, 0x0078, 0x3b3b, 0x157e,
- 0x137e, 0x147e, 0x0c7e, 0x0d7e, 0x1078, 0x1937, 0x2da0, 0x137f,
- 0x20a9, 0x0031, 0x53a3, 0x0c7f, 0x147f, 0x137f, 0x157f, 0x0078,
- 0x3b0f, 0xa184, 0x001f, 0x8003, 0x8003, 0x8003, 0xa080, 0x7510,
- 0x2060, 0x007c, 0x2019, 0x5151, 0x2304, 0xa085, 0x0001, 0x201a,
- 0x2019, 0x0102, 0x2304, 0xa085, 0x0001, 0x201a, 0x007c, 0x2019,
- 0x5151, 0x2304, 0xa084, 0xfffe, 0x201a, 0x2019, 0x0102, 0x2304,
- 0xa084, 0xfffe, 0x201a, 0x007c, 0x7990, 0xa18c, 0xfff8, 0x7992,
- 0x70b4, 0xa080, 0x00dd, 0x781a, 0x0078, 0x2459, 0x70a3, 0x0000,
- 0x7003, 0x0000, 0x7043, 0x0001, 0x7037, 0x0000, 0x0018, 0x2410,
- 0x1078, 0x1b8b, 0x0040, 0x3bc7, 0x2009, 0x510f, 0x200b, 0x0000,
- 0x68bc, 0x2060, 0x6100, 0xa184, 0x0300, 0x0040, 0x3bbb, 0x6827,
- 0x000e, 0xa084, 0x0200, 0x0040, 0x3bb7, 0x6827, 0x0017, 0x1078,
- 0x3af8, 0x0078, 0x3b96, 0x7000, 0xa086, 0x0007, 0x00c0, 0x3c29,
- 0x2d00, 0x70a2, 0xad80, 0x000f, 0x7036, 0x0078, 0x3bce, 0x7040,
- 0xa086, 0x0001, 0x0040, 0x2492, 0x0078, 0x2459, 0x2031, 0x0000,
- 0x691c, 0xa184, 0x0002, 0x0040, 0x3bd7, 0xa6b5, 0x0004, 0xa184,
- 0x00c0, 0x8003, 0x8003, 0x8007, 0xa080, 0x3cc2, 0x2004, 0xa635,
- 0x6820, 0xa084, 0x0400, 0x0040, 0x3bef, 0x789b, 0x0018, 0x78ab,
- 0x0003, 0x789b, 0x0081, 0x78ab, 0x0001, 0xa6b5, 0x1000, 0x6820,
- 0xa084, 0x8000, 0x00c0, 0x3bfd, 0x681c, 0xa084, 0x8000, 0x00c0,
- 0x3c04, 0xa6b5, 0x0800, 0x0078, 0x3c04, 0xa6b5, 0x0400, 0x789b,
- 0x000e, 0x6824, 0x8007, 0x78aa, 0x6820, 0xa084, 0x0100, 0x0040,
- 0x3c0b, 0xa6b5, 0x4000, 0xa684, 0x0200, 0x0040, 0x3c25, 0x682c,
- 0x78d2, 0x6830, 0x78d6, 0xa684, 0x0100, 0x0040, 0x3c23, 0x682c,
- 0xa084, 0x0001, 0x0040, 0x3c23, 0x7888, 0xa084, 0x0040, 0x0040,
- 0x3c23, 0xa6b5, 0x8000, 0x1078, 0x46f0, 0x7e5a, 0x6eb6, 0x0078,
- 0x4727, 0x1078, 0x38fa, 0x00c0, 0x3cbc, 0x702c, 0x8004, 0x0048,
- 0x3c37, 0x2019, 0x4e3b, 0x1078, 0x2276, 0x702f, 0x0001, 0x2041,
- 0x0001, 0x2031, 0x1000, 0x789b, 0x0018, 0x6814, 0xa084, 0x001f,
- 0xa085, 0x0080, 0x78aa, 0x691c, 0xa184, 0x0002, 0x0040, 0x3c50,
- 0xa6b5, 0x0004, 0x78ab, 0x0020, 0x6828, 0x78aa, 0xa8c0, 0x0002,
- 0x681c, 0xd0f4, 0x0040, 0x3c59, 0x2c50, 0x1078, 0x39ac, 0x1078,
- 0x45ff, 0x6820, 0xa084, 0x8000, 0x0040, 0x3c67, 0xa6b5, 0x0400,
- 0x789b, 0x000e, 0x6824, 0x8007, 0x78aa, 0x0078, 0x3c6e, 0x681c,
- 0xa084, 0x8000, 0x00c0, 0x3c6e, 0xa6b5, 0x0800, 0x6820, 0xa084,
- 0x0100, 0x0040, 0x3c75, 0xa6b5, 0x4000, 0x681c, 0xa084, 0x00c0,
- 0x8003, 0x8003, 0x8007, 0xa080, 0x3cc2, 0x2004, 0xa635, 0xa684,
- 0x0100, 0x0040, 0x3c8f, 0x682c, 0xa084, 0x0001, 0x0040, 0x3c8f,
- 0x7888, 0xa084, 0x0040, 0x0040, 0x3c8f, 0xa6b5, 0x8000, 0x789b,
- 0x007e, 0x7eae, 0x6eb6, 0x6814, 0x8007, 0x78aa, 0x7882, 0x2810,
- 0x7aaa, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x3cbc, 0x0018, 0x3cbc,
- 0x70b4, 0xa080, 0x00e2, 0x781a, 0x1078, 0x3912, 0xa684, 0x0200,
- 0x0040, 0x3cb0, 0x682c, 0x78d2, 0x6830, 0x78d6, 0x1078, 0x46f0,
- 0x2d00, 0x70a2, 0x704a, 0x6810, 0x70be, 0x7003, 0x0007, 0xad80,
- 0x000f, 0x7036, 0x0078, 0x2459, 0x1078, 0x1b62, 0x1078, 0x3912,
- 0x0078, 0x2459, 0x0000, 0x0300, 0x0200, 0x0000, 0x1078, 0x23eb,
- 0x2300, 0x0079, 0x3ccb, 0x3cce, 0x3cce, 0x3cd0, 0x1078, 0x23eb,
- 0x1078, 0x46ff, 0x6924, 0xa184, 0x00ff, 0xa086, 0x000a, 0x0040,
- 0x3ce2, 0xa184, 0xff00, 0xa085, 0x000a, 0x6826, 0x1078, 0x1b62,
- 0x0078, 0x3b96, 0x2001, 0x000a, 0x1078, 0x4691, 0x0078, 0x3b96,
- 0xa282, 0x0005, 0x0050, 0x3cee, 0x1078, 0x23eb, 0x7000, 0xa084,
- 0x0007, 0x10c0, 0x39be, 0x1078, 0x1937, 0x00c0, 0x3d0d, 0xa684,
- 0x0004, 0x0040, 0x3cff, 0x2001, 0x2800, 0x0078, 0x3d01, 0x2001,
- 0x0800, 0x71b4, 0xa188, 0x0091, 0x789b, 0x000e, 0x78aa, 0x2031,
- 0x0400, 0x7e5a, 0x791a, 0x0078, 0x2459, 0x6807, 0x0106, 0x680b,
- 0x0000, 0x689f, 0x0000, 0x6827, 0x0000, 0xa386, 0x0002, 0x00c0,
- 0x3d2e, 0xa286, 0x0002, 0x00c0, 0x3d2e, 0x78a0, 0xa005, 0x00c0,
- 0x3d2e, 0xa484, 0x8000, 0x00c0, 0x3d2e, 0x78e4, 0xa084, 0x0008,
- 0x0040, 0x3d2e, 0xa6b5, 0x0008, 0x2019, 0x0000, 0x1078, 0x411e,
- 0x2d00, 0x70a2, 0x704a, 0x7003, 0x0007, 0x7037, 0x0000, 0x6824,
- 0xa084, 0x0080, 0x0040, 0x3d40, 0x1078, 0x41d0, 0x0078, 0x2459,
- 0x2300, 0x0079, 0x3d43, 0x3d46, 0x3dc7, 0x3de6, 0x2200, 0x0079,
- 0x3d49, 0x3d4e, 0x3d5e, 0x3d84, 0x3d90, 0x3db3, 0x2029, 0x0001,
- 0xa026, 0x2011, 0x0000, 0x1078, 0x42f1, 0x0079, 0x3d57, 0x3d5c,
- 0x2459, 0x3b96, 0x3d5c, 0x3d5c, 0x1078, 0x23eb, 0x7990, 0xa18c,
- 0x0007, 0x00c0, 0x3d65, 0x2009, 0x0008, 0x2011, 0x0001, 0xa684,
- 0x0004, 0x0040, 0x3d6d, 0x2011, 0x0003, 0x2220, 0xa12a, 0x2011,
- 0x0001, 0x1078, 0x42f1, 0x0079, 0x3d75, 0x3d7a, 0x2459, 0x3b96,
- 0x3d82, 0x3d7c, 0x0078, 0x472d, 0x70ab, 0x3d80, 0x0078, 0x2459,
- 0x0078, 0x3d7a, 0x1078, 0x23eb, 0xa684, 0x0010, 0x0040, 0x3d8e,
- 0x1078, 0x419f, 0x0040, 0x3d8e, 0x0078, 0x2459, 0x0078, 0x420c,
- 0x6000, 0xa084, 0x0002, 0x0040, 0x3dad, 0x70b4, 0xa080, 0x00d2,
- 0x781a, 0x0d7e, 0x1078, 0x4708, 0x2d00, 0x682e, 0x6827, 0x0000,
- 0x1078, 0x3af8, 0x0d7f, 0x1078, 0x195a, 0x7003, 0x0000, 0x7037,
- 0x0000, 0x704b, 0x0000, 0x0078, 0x3b96, 0xa684, 0x0004, 0x00c0,
- 0x3db3, 0x0078, 0x472d, 0x6000, 0xa084, 0x0004, 0x00c0, 0x3dc5,
- 0x6000, 0xa084, 0x0001, 0x0040, 0x3dc5, 0x70ab, 0x3dc5, 0x2001,
- 0x0007, 0x1078, 0x4689, 0x0078, 0x4733, 0x0078, 0x472d, 0x2200,
- 0x0079, 0x3dca, 0x3dcf, 0x3dcf, 0x3dcf, 0x3dd1, 0x3dcf, 0x1078,
- 0x23eb, 0x70a7, 0x3dd5, 0x0078, 0x4739, 0x2011, 0x0018, 0x1078,
- 0x42eb, 0x0079, 0x3ddb, 0x3de0, 0x2459, 0x3b96, 0x3de2, 0x3de4,
- 0x1078, 0x23eb, 0x1078, 0x23eb, 0x1078, 0x23eb, 0x2200, 0x0079,
- 0x3de9, 0x3dee, 0x3df0, 0x3df0, 0x3dee, 0x3dee, 0x1078, 0x23eb,
- 0x78e4, 0xa084, 0x0008, 0x0040, 0x3e05, 0x70a7, 0x3df9, 0x0078,
- 0x4739, 0x2011, 0x0004, 0x1078, 0x42eb, 0x0079, 0x3dff, 0x3e05,
- 0x2459, 0x3b96, 0x3e05, 0x3e0f, 0x3e13, 0x70ab, 0x3e0d, 0x2001,
- 0x0003, 0x1078, 0x4689, 0x0078, 0x4733, 0x0078, 0x472d, 0x70ab,
- 0x3e05, 0x0078, 0x2459, 0x70ab, 0x3e17, 0x0078, 0x2459, 0x0078,
- 0x3e0d, 0xa282, 0x0003, 0x0050, 0x3e1f, 0x1078, 0x23eb, 0xa386,
- 0x0002, 0x00c0, 0x3e38, 0xa286, 0x0002, 0x00c0, 0x3e3e, 0x78a0,
- 0xa005, 0x00c0, 0x3e3e, 0xa484, 0x8000, 0x00c0, 0x3e3e, 0x78e4,
- 0xa084, 0x0008, 0x0040, 0x3e38, 0xa6b5, 0x0008, 0x2019, 0x0000,
- 0xa684, 0x0008, 0x0040, 0x3e3e, 0x1078, 0x417c, 0x6810, 0x70be,
- 0x7003, 0x0007, 0x2300, 0x0079, 0x3e45, 0x3e48, 0x3e75, 0x3e7d,
- 0x2200, 0x0079, 0x3e4b, 0x3e50, 0x3e4e, 0x3e69, 0x1078, 0x23eb,
- 0x7990, 0xa1ac, 0x0007, 0xa026, 0x2011, 0x0001, 0x1078, 0x42f1,
- 0x0079, 0x3e5a, 0x3e5f, 0x2459, 0x3b96, 0x3e67, 0x3e61, 0x0078,
- 0x472d, 0x70ab, 0x3e65, 0x0078, 0x2459, 0x0078, 0x3e5f, 0x1078,
- 0x23eb, 0xa684, 0x0010, 0x0040, 0x3e73, 0x1078, 0x419f, 0x0040,
- 0x3e73, 0x0078, 0x2459, 0x0078, 0x420c, 0x2200, 0x0079, 0x3e78,
- 0x3e7b, 0x3e7b, 0x3e7b, 0x1078, 0x23eb, 0x2200, 0x0079, 0x3e80,
- 0x3e83, 0x3e85, 0x3e85, 0x1078, 0x23eb, 0x78e4, 0xa084, 0x0008,
- 0x0040, 0x3e9a, 0x70a7, 0x3e8e, 0x0078, 0x4739, 0x2011, 0x0004,
- 0x1078, 0x42eb, 0x0079, 0x3e94, 0x3e9a, 0x2459, 0x3b96, 0x3e9a,
- 0x3ea4, 0x3ea8, 0x70ab, 0x3ea2, 0x2001, 0x0003, 0x1078, 0x4689,
- 0x0078, 0x4733, 0x0078, 0x472d, 0x70ab, 0x3e9a, 0x0078, 0x2459,
- 0x70ab, 0x3eac, 0x0078, 0x2459, 0x0078, 0x3ea2, 0x2300, 0x0079,
- 0x3eb1, 0x3eb6, 0x3eb8, 0x3eb4, 0x1078, 0x23eb, 0x70a4, 0x007a,
- 0x70a4, 0x007a, 0xa282, 0x0002, 0x0050, 0x3ec0, 0x1078, 0x23eb,
- 0xa684, 0x0200, 0x0040, 0x3eca, 0x1078, 0x46f8, 0x1078, 0x42d3,
- 0x1078, 0x46ff, 0x2300, 0x0079, 0x3ecd, 0x3ed0, 0x3ef4, 0x3f5a,
- 0xa286, 0x0001, 0x0040, 0x3ed6, 0x1078, 0x23eb, 0xa684, 0x0200,
- 0x0040, 0x3ede, 0x1078, 0x46f8, 0x1078, 0x46ff, 0x2001, 0x0001,
- 0x1078, 0x4691, 0x78b8, 0xa084, 0xc001, 0x0040, 0x3ef0, 0x7848,
- 0xa085, 0x0008, 0x784a, 0x7848, 0xa084, 0x0008, 0x00c0, 0x3eeb,
- 0x7003, 0x0000, 0x0078, 0x3b96, 0x2200, 0x0079, 0x3ef7, 0x3ef9,
- 0x3f2a, 0x70a7, 0x3efd, 0x0078, 0x4739, 0x2011, 0x000d, 0x1078,
- 0x42eb, 0x0079, 0x3f03, 0x3f0a, 0x2459, 0x3b96, 0x3f12, 0x3f1a,
- 0x3f20, 0x3f22, 0xa6b4, 0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a,
- 0x0078, 0x4727, 0xa6b4, 0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a,
- 0x0078, 0x4727, 0x70ab, 0x3f1e, 0x0078, 0x2459, 0x0078, 0x3f0a,
- 0x1078, 0x23eb, 0x70ab, 0x3f26, 0x0078, 0x2459, 0x1078, 0x473f,
- 0x0078, 0x2459, 0x70a7, 0x3f2e, 0x0078, 0x4739, 0x2011, 0x0012,
- 0x1078, 0x42eb, 0x0079, 0x3f34, 0x3f3a, 0x2459, 0x3b96, 0x3f46,
- 0x3f4e, 0x3f54, 0xa6b4, 0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a,
- 0x70b4, 0xa080, 0x00a6, 0x781a, 0x0078, 0x2459, 0xa6b4, 0x00ff,
- 0xa6b5, 0x0400, 0x6eb6, 0x7e5a, 0x0078, 0x4727, 0x70ab, 0x3f52,
- 0x0078, 0x2459, 0x0078, 0x3f3a, 0x70ab, 0x3f58, 0x0078, 0x2459,
- 0x0078, 0x3f46, 0xa286, 0x0001, 0x0040, 0x3f60, 0x1078, 0x23eb,
- 0x70a7, 0x3f64, 0x0078, 0x4739, 0x2011, 0x0015, 0x1078, 0x42eb,
- 0x0079, 0x3f6a, 0x3f6f, 0x2459, 0x3b96, 0x3f7d, 0x3f89, 0xa6b4,
- 0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a, 0x783b, 0x1301, 0x70b4,
- 0xa080, 0x00b4, 0x781a, 0x0078, 0x2459, 0xa6b4, 0x00ff, 0xa6b5,
- 0x0400, 0x6eb6, 0x7e5a, 0x70b4, 0xa080, 0x00a6, 0x781a, 0x0078,
- 0x2459, 0x70ab, 0x3f8d, 0x0078, 0x2459, 0x0078, 0x3f6f, 0xa282,
- 0x0003, 0x0050, 0x3f95, 0x1078, 0x23eb, 0x2300, 0x0079, 0x3f98,
- 0x3f9b, 0x3fd2, 0x402d, 0xa286, 0x0001, 0x0040, 0x3fa1, 0x1078,
- 0x23eb, 0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x3fae,
- 0x1078, 0x3af8, 0x7003, 0x0000, 0x0078, 0x3b96, 0x683b, 0x0000,
- 0x6837, 0x0000, 0xa684, 0x0200, 0x0040, 0x3fbc, 0x1078, 0x46f8,
- 0x1078, 0x42d3, 0x1078, 0x46ff, 0x2001, 0x0001, 0x1078, 0x4691,
- 0x78b8, 0xa084, 0xc001, 0x0040, 0x3fce, 0x7848, 0xa085, 0x0008,
- 0x784a, 0x7848, 0xa084, 0x0008, 0x00c0, 0x3fc9, 0x7003, 0x0000,
- 0x0078, 0x3b96, 0x2200, 0x0079, 0x3fd5, 0x3fd7, 0x4008, 0x70a7,
- 0x3fdb, 0x0078, 0x4739, 0x2011, 0x000d, 0x1078, 0x42eb, 0x0079,
- 0x3fe1, 0x3fe8, 0x2459, 0x3b96, 0x3ff0, 0x3ff8, 0x3ffe, 0x4000,
- 0xa6b4, 0x00ff, 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x4727,
- 0xa6b4, 0x00ff, 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x4727,
- 0x70ab, 0x3ffc, 0x0078, 0x2459, 0x0078, 0x3fe8, 0x1078, 0x23eb,
- 0x70ab, 0x4004, 0x0078, 0x2459, 0x1078, 0x473f, 0x0078, 0x2459,
- 0x70a7, 0x400c, 0x0078, 0x4739, 0x2011, 0x0005, 0x1078, 0x42eb,
- 0x0079, 0x4012, 0x4017, 0x2459, 0x3b96, 0x401f, 0x4027, 0xa6b4,
- 0x00ff, 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x4727, 0xa6b4,
- 0x00ff, 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x4727, 0x70ab,
- 0x402b, 0x0078, 0x2459, 0x0078, 0x4017, 0xa286, 0x0001, 0x0040,
- 0x4033, 0x1078, 0x23eb, 0x70a7, 0x4037, 0x0078, 0x4739, 0x2011,
- 0x0006, 0x1078, 0x42eb, 0x0079, 0x403d, 0x4042, 0x2459, 0x3b96,
- 0x4048, 0x4052, 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x4727,
- 0xa6b4, 0x00ff, 0xa6b5, 0x0800, 0x6eb6, 0xa6b5, 0x4000, 0x7e5a,
- 0x0078, 0x4727, 0x70ab, 0x4056, 0x0078, 0x2459, 0x0078, 0x4042,
- 0x2300, 0x0079, 0x405b, 0x4060, 0x405e, 0x405e, 0x1078, 0x23eb,
- 0x1078, 0x23eb, 0x2300, 0x71a8, 0xa005, 0x017a, 0x6810, 0x70be,
- 0xa282, 0x0003, 0x0050, 0x406e, 0x1078, 0x23eb, 0x2300, 0x0079,
- 0x4071, 0x4074, 0x4082, 0x40a4, 0xa684, 0x0200, 0x0040, 0x407c,
- 0x1078, 0x46f8, 0x1078, 0x46ff, 0x2001, 0x0001, 0x1078, 0x4691,
- 0x0078, 0x2459, 0xa296, 0x0002, 0x0040, 0x408b, 0x82ff, 0x0040,
- 0x408b, 0x1078, 0x23eb, 0x70a7, 0x408f, 0x0078, 0x4739, 0x2011,
- 0x0018, 0x1078, 0x42eb, 0x0079, 0x4095, 0x409a, 0x2459, 0x3b96,
- 0x409c, 0x409e, 0x0078, 0x4727, 0x0078, 0x4727, 0x70ab, 0x40a2,
- 0x0078, 0x2459, 0x0078, 0x409a, 0x2200, 0x0079, 0x40a7, 0x40a9,
- 0x40c2, 0x70a7, 0x40ad, 0x0078, 0x4739, 0x2011, 0x0017, 0x1078,
- 0x42eb, 0x0079, 0x40b3, 0x40b8, 0x2459, 0x3b96, 0x40ba, 0x40bc,
- 0x0078, 0x4727, 0x0078, 0x4727, 0x70ab, 0x40c0, 0x0078, 0x2459,
- 0x0078, 0x40b8, 0xa484, 0x8000, 0x00c0, 0x410c, 0xa684, 0x0100,
- 0x0040, 0x40d6, 0x1078, 0x46f8, 0x1078, 0x42d3, 0x1078, 0x46ff,
- 0x7848, 0xa085, 0x000c, 0x784a, 0x0078, 0x40da, 0x78d8, 0x78d2,
- 0x78dc, 0x78d6, 0xa6b4, 0xefff, 0x7e5a, 0x70a7, 0x40e1, 0x0078,
- 0x4739, 0x2011, 0x000d, 0x1078, 0x42eb, 0x0079, 0x40e7, 0x40ee,
- 0x2459, 0x3b96, 0x40ee, 0x40fc, 0x4102, 0x4104, 0xa684, 0x0100,
- 0x0040, 0x40fa, 0x1078, 0x46b6, 0x682c, 0x78d2, 0x6830, 0x78d6,
- 0x1078, 0x46f0, 0x0078, 0x4727, 0x70ab, 0x4100, 0x0078, 0x2459,
- 0x0078, 0x40ee, 0x1078, 0x23eb, 0x70ab, 0x4108, 0x0078, 0x2459,
- 0x1078, 0x473f, 0x0078, 0x2459, 0x1078, 0x46ff, 0x70ab, 0x4116,
- 0x2001, 0x0003, 0x1078, 0x4689, 0x0078, 0x4733, 0x1078, 0x46f0,
- 0x682c, 0x78d2, 0x6830, 0x78d6, 0x0078, 0x4727, 0x70b8, 0x6812,
- 0x70be, 0x8000, 0x70ba, 0x681b, 0x0000, 0xa684, 0x0008, 0x0040,
- 0x4141, 0x157e, 0x137e, 0x147e, 0x7890, 0x8004, 0x8004, 0x8004,
- 0x8004, 0xa084, 0x000f, 0x681a, 0x80ac, 0x789b, 0x0000, 0xaf80,
- 0x002b, 0x2098, 0xad80, 0x000b, 0x20a0, 0x53a5, 0x147f, 0x137f,
- 0x157f, 0xa6c4, 0x0f00, 0xa684, 0x0002, 0x00c0, 0x4150, 0x692c,
- 0x810d, 0x810d, 0x810d, 0xa184, 0x0007, 0x2008, 0x0078, 0x415f,
- 0x789b, 0x0010, 0x79ac, 0xa184, 0x0020, 0x0040, 0x415f, 0x017e,
- 0x2009, 0x0005, 0x2001, 0x3d00, 0x1078, 0x46c1, 0x017f, 0xa184,
- 0x001f, 0xa805, 0x6816, 0x1078, 0x3b69, 0x68be, 0xa684, 0x0004,
- 0x0040, 0x4170, 0xa18c, 0xff00, 0x78a8, 0xa084, 0x00ff, 0xa105,
- 0x682a, 0xa6b4, 0x00ff, 0x6000, 0xa084, 0x0008, 0x0040, 0x417a,
- 0xa6b5, 0x4000, 0x6eb6, 0x007c, 0x157e, 0x137e, 0x147e, 0x6918,
- 0x7890, 0x8004, 0x8004, 0x8004, 0x8004, 0xa084, 0x000f, 0x007e,
- 0xa100, 0x681a, 0x007f, 0x8000, 0x8004, 0x0040, 0x419b, 0x20a8,
- 0x8104, 0xa080, 0x000b, 0xad00, 0x20a0, 0x789b, 0x0000, 0xaf80,
- 0x002b, 0x2098, 0x53a5, 0x147f, 0x137f, 0x157f, 0x007c, 0x682c,
- 0xa084, 0x0020, 0x00c0, 0x41a7, 0x620c, 0x0078, 0x41a8, 0x6210,
- 0x6b18, 0x2300, 0xa202, 0x0040, 0x41c8, 0x2018, 0xa382, 0x000e,
- 0x0048, 0x41b8, 0x0040, 0x41b8, 0x2019, 0x000e, 0x0078, 0x41bc,
- 0x7858, 0xa084, 0xffef, 0x785a, 0x783b, 0x1b01, 0x7893, 0x0000,
- 0x7ba2, 0x70b4, 0xa080, 0x008e, 0x781a, 0xa085, 0x0001, 0x007c,
- 0x7858, 0xa084, 0xffef, 0x785a, 0x7893, 0x0000, 0xa006, 0x007c,
- 0x6904, 0xa18c, 0x00ff, 0xa196, 0x0007, 0x0040, 0x41dd, 0xa196,
- 0x000f, 0x0040, 0x41dd, 0x6807, 0x0117, 0x6914, 0x1078, 0x3b69,
- 0x6100, 0x8104, 0x00c8, 0x41f8, 0x601c, 0xa005, 0x0040, 0x41ec,
- 0x2001, 0x0800, 0x0078, 0x41fa, 0x0d7e, 0x6824, 0x007e, 0x1078,
- 0x4708, 0x007f, 0x6826, 0x2d00, 0x682e, 0x1078, 0x3af8, 0x0d7f,
- 0x2001, 0x0200, 0x6826, 0x8007, 0x789b, 0x000e, 0x78aa, 0x6820,
- 0xa085, 0x8000, 0x6822, 0x2031, 0x0400, 0x6eb6, 0x7e5a, 0x71b4,
- 0xa188, 0x0091, 0x791a, 0x007c, 0xa6c4, 0x0f00, 0xa684, 0x0002,
- 0x00c0, 0x4220, 0x692c, 0x810d, 0x810d, 0x810d, 0xa184, 0x0007,
- 0x2008, 0xa805, 0x6816, 0x1078, 0x3b69, 0x68be, 0x0078, 0x4223,
- 0x6914, 0x1078, 0x3b69, 0x6100, 0x8104, 0x00c8, 0x4280, 0xa184,
- 0x0300, 0x0040, 0x422f, 0x6807, 0x0117, 0x0078, 0x424d, 0x6004,
- 0xa005, 0x00c0, 0x4256, 0x6807, 0x0117, 0x601c, 0xa005, 0x00c0,
- 0x4243, 0x0d7e, 0x1078, 0x4708, 0x6827, 0x0034, 0x2d00, 0x682e,
- 0x1078, 0x3af8, 0x0d7f, 0xa684, 0x0004, 0x0040, 0x424d, 0x2031,
- 0x0400, 0x2001, 0x2800, 0x0078, 0x4251, 0x2031, 0x0400, 0x2001,
- 0x0800, 0x71b4, 0xa188, 0x0091, 0x0078, 0x42ae, 0x6018, 0xa005,
- 0x00c0, 0x4243, 0x601c, 0xa005, 0x00c0, 0x4243, 0x689f, 0x0000,
- 0x6827, 0x003d, 0xa684, 0x0001, 0x0040, 0x42bc, 0xd694, 0x00c0,
- 0x4279, 0x6100, 0xd1d4, 0x0040, 0x4279, 0x692c, 0x81ff, 0x0040,
- 0x42bc, 0xa186, 0x0003, 0x0040, 0x42bc, 0xa186, 0x0012, 0x0040,
- 0x42bc, 0xa6b5, 0x0800, 0x71b4, 0xa188, 0x00af, 0x0078, 0x42b7,
- 0x6807, 0x0117, 0x2031, 0x0400, 0x692c, 0xa18c, 0x00ff, 0xa186,
- 0x0012, 0x00c0, 0x4291, 0x2001, 0x42c9, 0x2009, 0x0001, 0x0078,
- 0x42a2, 0xa186, 0x0003, 0x00c0, 0x429b, 0x2001, 0x42ca, 0x2009,
- 0x0012, 0x0078, 0x42a2, 0x2001, 0x0200, 0x71b4, 0xa188, 0x0091,
- 0x0078, 0x42ae, 0x1078, 0x46db, 0x78a3, 0x0000, 0x681c, 0xa085,
- 0x0040, 0x681e, 0x71b4, 0xa188, 0x00df, 0xa006, 0x6826, 0x8007,
- 0x789b, 0x000e, 0x78aa, 0x6820, 0xa085, 0x8000, 0x6822, 0x6eb6,
- 0x7e5a, 0x791a, 0x0078, 0x2459, 0x6eb6, 0x1078, 0x3af8, 0x6810,
- 0x70be, 0x7003, 0x0007, 0x70a3, 0x0000, 0x704b, 0x0000, 0x0078,
- 0x2459, 0x0023, 0x0070, 0x0005, 0x0000, 0x0a00, 0x0000, 0x0000,
- 0x0025, 0x0000, 0x0000, 0x683b, 0x0000, 0x6837, 0x0000, 0xa684,
- 0x0200, 0x0040, 0x42ea, 0x78b8, 0xa08c, 0x001f, 0xa084, 0x8000,
- 0x0040, 0x42e3, 0x8108, 0x78d8, 0xa100, 0x6836, 0x78dc, 0xa081,
- 0x0000, 0x683a, 0x007c, 0x7990, 0x810f, 0xa5ac, 0x0007, 0x2021,
- 0x0000, 0xa480, 0x0010, 0x789a, 0x79a8, 0xa18c, 0x00ff, 0xa184,
- 0x0080, 0x00c0, 0x4319, 0xa182, 0x0020, 0x00c8, 0x4337, 0xa182,
- 0x0012, 0x00c8, 0x467b, 0x2100, 0x1079, 0x4307, 0x007c, 0x467b,
- 0x44e8, 0x467b, 0x467b, 0x4344, 0x4347, 0x4381, 0x43b7, 0x43eb,
- 0x43ee, 0x467b, 0x467b, 0x43a2, 0x4412, 0x444c, 0x467b, 0x467b,
- 0x4473, 0xa184, 0x0020, 0x00c0, 0x44a7, 0xa18c, 0x001f, 0x6814,
- 0xa084, 0x001f, 0xa106, 0x0040, 0x4334, 0x70b4, 0xa080, 0x00d2,
- 0x781a, 0x2001, 0x0014, 0x1078, 0x4691, 0x1078, 0x46ff, 0x7003,
- 0x0000, 0x2001, 0x0002, 0x007c, 0x2001, 0x0000, 0x007c, 0xa182,
- 0x0024, 0x00c8, 0x467b, 0xa184, 0x0003, 0x1079, 0x4307, 0x007c,
- 0x467b, 0x467b, 0x467b, 0x467b, 0x1078, 0x467b, 0x007c, 0x2200,
- 0x0079, 0x434a, 0x4476, 0x4476, 0x436e, 0x436e, 0x436e, 0x436e,
- 0x436e, 0x436e, 0x436e, 0x436e, 0x436c, 0x436e, 0x4363, 0x436e,
- 0x436e, 0x436e, 0x436e, 0x436e, 0x4376, 0x4379, 0x4476, 0x4379,
- 0x436e, 0x436e, 0x436e, 0x0c7e, 0x077e, 0x6f14, 0x1078, 0x36e2,
- 0x077f, 0x0c7f, 0x0078, 0x436e, 0x1078, 0x458b, 0x6827, 0x02b3,
- 0x2009, 0x000b, 0x2001, 0x4800, 0x0078, 0x44aa, 0x1078, 0x4670,
- 0x007c, 0x6827, 0x0093, 0x2009, 0x000b, 0x2001, 0x4800, 0x0078,
- 0x4492, 0x2d58, 0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0,
- 0x438b, 0x6807, 0x0117, 0x6827, 0x0002, 0x1078, 0x4708, 0x6827,
- 0x0036, 0x6932, 0x2d00, 0x682e, 0x0d7e, 0x1078, 0x3ac8, 0x1078,
- 0x44d0, 0x2b68, 0x1078, 0x3af8, 0x0d7f, 0x1078, 0x3af8, 0x2001,
- 0x0002, 0x007c, 0x1078, 0x44d0, 0x2001, 0x0017, 0x1078, 0x4691,
- 0x70a3, 0x0000, 0x2009, 0x5138, 0x200b, 0x0006, 0x70af, 0x0017,
- 0x2009, 0x0200, 0x1078, 0x3a06, 0x2001, 0x0001, 0x007c, 0x2200,
- 0x0079, 0x43ba, 0x4476, 0x44a7, 0x44a7, 0x44a7, 0x43db, 0x44b7,
- 0x43e3, 0x44b7, 0x44b7, 0x44ba, 0x44ba, 0x44bf, 0x44bf, 0x43d3,
- 0x43d3, 0x44a7, 0x44a7, 0x44b7, 0x44a7, 0x43e3, 0x4476, 0x43e3,
- 0x43e3, 0x43e3, 0x43e3, 0x6827, 0x0084, 0x2009, 0x000b, 0x2001,
- 0x4300, 0x0078, 0x44c9, 0x6827, 0x000d, 0x2009, 0x000b, 0x2001,
- 0x4300, 0x0078, 0x44aa, 0x6827, 0x0093, 0x2009, 0x000b, 0x2001,
- 0x4300, 0x0078, 0x4492, 0x2001, 0x0000, 0x007c, 0x2200, 0x0079,
- 0x43f1, 0x4476, 0x440a, 0x440a, 0x440a, 0x440a, 0x44b7, 0x44b7,
- 0x44b7, 0x44b7, 0x44b7, 0x44b7, 0x44b7, 0x44b7, 0x440a, 0x440a,
- 0x440a, 0x440a, 0x44b7, 0x440a, 0x440a, 0x44b7, 0x44b7, 0x44b7,
- 0x44b7, 0x4476, 0x6827, 0x0093, 0x2009, 0x000b, 0x2001, 0x4300,
- 0x0078, 0x4492, 0xa684, 0x0004, 0x00c0, 0x4426, 0x6804, 0xa084,
- 0x00ff, 0xa086, 0x0006, 0x00c0, 0x467b, 0x1078, 0x44d0, 0x6807,
- 0x0117, 0x1078, 0x3af8, 0x2001, 0x0002, 0x007c, 0x6000, 0xa084,
- 0x0004, 0x0040, 0x467b, 0x2d58, 0x6804, 0xa084, 0x00ff, 0xa086,
- 0x0006, 0x00c0, 0x4435, 0x6807, 0x0117, 0x6827, 0x0002, 0x1078,
- 0x4708, 0x6827, 0x0036, 0x6932, 0x2d00, 0x682e, 0x0d7e, 0x1078,
- 0x3ad7, 0x1078, 0x44d0, 0x2b68, 0x1078, 0x3af8, 0x0d7f, 0x1078,
- 0x3af8, 0x2001, 0x0002, 0x007c, 0x6000, 0xa084, 0x0004, 0x0040,
- 0x467b, 0x2d58, 0x6a04, 0xa294, 0x00ff, 0xa286, 0x0006, 0x00c0,
- 0x445b, 0x6807, 0x0117, 0x6827, 0x0002, 0x2d58, 0x1078, 0x4708,
- 0x6827, 0x0036, 0x6932, 0x2d00, 0x682e, 0x0d7e, 0x1078, 0x3ae7,
- 0x1078, 0x44d0, 0x2b68, 0x1078, 0x3af8, 0x0d7f, 0x1078, 0x3af8,
- 0x2001, 0x0002, 0x007c, 0x1078, 0x467b, 0x007c, 0x70b4, 0xa080,
- 0x00d2, 0x781a, 0x2001, 0x0001, 0x1078, 0x4691, 0x1078, 0x46ff,
- 0x7003, 0x0000, 0x2001, 0x0002, 0x007c, 0x1078, 0x46c1, 0x1078,
- 0x46f8, 0x1078, 0x42d3, 0x1078, 0x41d0, 0x1078, 0x46ff, 0x2001,
- 0x0001, 0x007c, 0x1078, 0x46c1, 0x1078, 0x46f8, 0x1078, 0x42d3,
- 0x70b4, 0xa080, 0x00d2, 0x781a, 0x2001, 0x0013, 0x1078, 0x4691,
- 0x1078, 0x46ff, 0x7003, 0x0000, 0x2001, 0x0002, 0x007c, 0x1078,
- 0x467b, 0x007c, 0x1078, 0x46c1, 0x1078, 0x46f8, 0x1078, 0x42d3,
- 0x1078, 0x41d0, 0x1078, 0x46ff, 0x2001, 0x0001, 0x007c, 0x2001,
- 0x0003, 0x007c, 0x1078, 0x458b, 0x2001, 0x0000, 0x007c, 0x0c7e,
- 0x077e, 0x6f14, 0x1078, 0x36e2, 0x077f, 0x0c7f, 0x2001, 0x0000,
- 0x007c, 0x1078, 0x46c1, 0x1078, 0x467b, 0x2001, 0x0006, 0x007c,
- 0x6904, 0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040, 0x44db, 0xa186,
- 0x000f, 0x00c0, 0x44df, 0x1078, 0x46f8, 0x1078, 0x42d3, 0x70b4,
- 0xa080, 0x00d2, 0x781a, 0x1078, 0x46ff, 0x7003, 0x0000, 0x007c,
- 0x7aa8, 0xa294, 0x00ff, 0x78a8, 0xa084, 0x00ff, 0xa08a, 0x0004,
- 0x00c8, 0x467b, 0x1079, 0x44f5, 0x007c, 0x467b, 0x44f9, 0x467b,
- 0x4592, 0xa282, 0x0003, 0x0040, 0x4500, 0x1078, 0x467b, 0x007c,
- 0x7da8, 0xa5ac, 0x00ff, 0x7ca8, 0xa4a4, 0x00ff, 0x69b8, 0xa184,
- 0x0100, 0x0040, 0x453f, 0xa18c, 0xfeff, 0x69ba, 0x78a0, 0xa005,
- 0x00c0, 0x453f, 0xa4a4, 0x00ff, 0x0040, 0x4533, 0xa482, 0x000c,
- 0x0040, 0x451c, 0x00c8, 0x4526, 0x852b, 0x852b, 0x1078, 0x3760,
- 0x0040, 0x4526, 0x1078, 0x355b, 0x0078, 0x4535, 0x1078, 0x465d,
- 0x1078, 0x3586, 0x69b8, 0xa18d, 0x0100, 0x69ba, 0xa6b5, 0x1000,
- 0x7e5a, 0x0078, 0x4538, 0x1078, 0x3586, 0xa6b4, 0xefff, 0x7e5a,
- 0x70b4, 0xa080, 0x0091, 0x781a, 0x2001, 0x0001, 0x007c, 0x0c7e,
- 0x1078, 0x457f, 0x6200, 0xd2e4, 0x0040, 0x4570, 0x6208, 0x8217,
- 0xa294, 0x00ff, 0xa282, 0x000c, 0x0048, 0x4552, 0x0040, 0x4552,
- 0x2011, 0x000c, 0x2400, 0xa202, 0x00c8, 0x4557, 0x2220, 0x6208,
- 0xa294, 0x00ff, 0x701c, 0xa202, 0x00c8, 0x455f, 0x721c, 0x2200,
- 0xa502, 0x00c8, 0x4564, 0x2228, 0x1078, 0x4661, 0x852b, 0x852b,
- 0x1078, 0x3760, 0x0040, 0x4570, 0x1078, 0x3562, 0x0078, 0x4574,
- 0x1078, 0x465d, 0x1078, 0x358d, 0xa6b5, 0x1000, 0x7e5a, 0x70b4,
- 0xa080, 0x00be, 0x781a, 0x2001, 0x0004, 0x0c7f, 0x007c, 0x007e,
- 0x6814, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e0,
- 0x5380, 0x007f, 0x007c, 0x0c7e, 0x1078, 0x457f, 0x1078, 0x358d,
- 0x0c7f, 0x007c, 0xa282, 0x0002, 0x00c0, 0x467b, 0x7aa8, 0xa294,
- 0x00ff, 0x69b8, 0xa184, 0x0200, 0x0040, 0x45c9, 0xa18c, 0xfdff,
- 0x69ba, 0x78a0, 0xa005, 0x00c0, 0x45c9, 0xa282, 0x0002, 0x00c8,
- 0x369d, 0x1078, 0x4627, 0x1078, 0x362b, 0x1078, 0x3586, 0xa684,
- 0x0100, 0x0040, 0x45bf, 0x682c, 0xa084, 0x0001, 0x0040, 0x45bf,
- 0xc6fc, 0x7888, 0xa084, 0x0040, 0x0040, 0x45bf, 0xc6fd, 0xa6b5,
- 0x1000, 0x7e5a, 0x70b4, 0xa080, 0x0091, 0x781a, 0x2001, 0x0001,
- 0x007c, 0x0c7e, 0x1078, 0x457f, 0xa284, 0xfffe, 0x0040, 0x45d4,
- 0x2011, 0x0001, 0x0078, 0x45d8, 0xa284, 0x0001, 0x0040, 0x45de,
- 0x6100, 0xd1ec, 0x00c0, 0x45de, 0x2011, 0x0000, 0x1078, 0x4619,
- 0x1078, 0x3632, 0x1078, 0x358d, 0xa684, 0x0100, 0x0040, 0x45f4,
- 0x682c, 0xa084, 0x0001, 0x0040, 0x45f4, 0xc6fc, 0x7888, 0xa084,
- 0x0040, 0x0040, 0x45f4, 0xc6fd, 0xa6b5, 0x1000, 0x7e5a, 0x70b4,
- 0xa080, 0x00be, 0x781a, 0x2001, 0x0004, 0x0c7f, 0x007c, 0x0c7e,
- 0x2960, 0x6000, 0x2011, 0x0001, 0xa084, 0x2000, 0x00c0, 0x460a,
- 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003,
- 0x7aaa, 0xa8c0, 0x0004, 0x68b8, 0xa085, 0x0200, 0x68ba, 0x0c7f,
- 0x007c, 0x789b, 0x0018, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab,
- 0x0003, 0x7aaa, 0x789b, 0x0081, 0x78ab, 0x0004, 0x007c, 0x0c7e,
- 0x7054, 0x2060, 0x6000, 0xa084, 0x1000, 0x00c0, 0x4635, 0x2029,
- 0x0032, 0x2021, 0x0000, 0x0078, 0x4655, 0x6508, 0xa5ac, 0x00ff,
- 0x7018, 0xa086, 0x0028, 0x00c0, 0x4645, 0xa582, 0x0019, 0x00c8,
- 0x464b, 0x2029, 0x0019, 0x0078, 0x464b, 0xa582, 0x000c, 0x00c8,
- 0x464b, 0x2029, 0x000c, 0x6408, 0x8427, 0xa4a4, 0x00ff, 0xa482,
- 0x000c, 0x0048, 0x4655, 0x2021, 0x000c, 0x1078, 0x4661, 0x68b8,
- 0xa085, 0x0100, 0x68ba, 0x0c7f, 0x007c, 0x2021, 0x0000, 0x2029,
- 0x0032, 0x789b, 0x0018, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab,
- 0x0001, 0x7daa, 0x7caa, 0x789b, 0x0081, 0x78ab, 0x0005, 0x007c,
- 0x2001, 0x0003, 0x1078, 0x4689, 0x70b4, 0xa080, 0x00be, 0x781a,
- 0x2001, 0x0005, 0x007c, 0x2001, 0x0007, 0x1078, 0x4689, 0xa6b5,
- 0x1000, 0x7e5a, 0x70b4, 0xa080, 0x00be, 0x781a, 0x2001, 0x0004,
- 0x007c, 0x789b, 0x0018, 0x78aa, 0x789b, 0x0081, 0x78ab, 0x0001,
- 0x007c, 0x6904, 0xa18c, 0x00ff, 0xa196, 0x0007, 0x0040, 0x469f,
- 0xa196, 0x000f, 0x0040, 0x469f, 0x1078, 0x195a, 0x007c, 0x6924,
- 0xa194, 0x003f, 0x00c0, 0x46a8, 0xa18c, 0xffc0, 0xa105, 0x6826,
- 0x1078, 0x3af8, 0x691c, 0xa184, 0x0100, 0x0040, 0x46b5, 0x6914,
- 0x1078, 0x3b69, 0x6204, 0x8210, 0x6206, 0x007c, 0x692c, 0x6834,
- 0x682e, 0xa112, 0x6930, 0x6838, 0x6832, 0xa11b, 0xa200, 0xa301,
- 0x007c, 0x0c7e, 0xade0, 0x0018, 0x6003, 0x0070, 0x6106, 0x600b,
- 0x0000, 0x600f, 0x0a00, 0x6013, 0x0000, 0x6017, 0x0000, 0x8007,
- 0x601a, 0x601f, 0x0000, 0x6023, 0x0000, 0x0c7f, 0x6824, 0xa085,
- 0x0080, 0x6826, 0x007c, 0x157e, 0x137e, 0x147e, 0x2098, 0xaf80,
- 0x002d, 0x20a0, 0x81ac, 0x0040, 0x46e6, 0x53a6, 0xa184, 0x0001,
- 0x0040, 0x46ec, 0x3304, 0x78be, 0x147f, 0x137f, 0x157f, 0x007c,
- 0x70b0, 0xa005, 0x10c0, 0x23eb, 0x70b3, 0x8000, 0x0078, 0x4a3a,
- 0x71b0, 0x81ff, 0x0040, 0x46fe, 0x1078, 0x4b30, 0x007c, 0x71b0,
- 0x81ff, 0x0040, 0x4707, 0x70b3, 0x0000, 0x1078, 0x4776, 0x007c,
- 0x0c7e, 0x0d7e, 0x1078, 0x1937, 0x0c7f, 0x157e, 0x137e, 0x147e,
- 0x2da0, 0x2c98, 0x20a9, 0x0031, 0x53a3, 0x147f, 0x137f, 0x157f,
- 0x6807, 0x010d, 0x680b, 0x0000, 0x7004, 0x8007, 0x681a, 0x6823,
- 0x0000, 0x681f, 0x0000, 0x689f, 0x0000, 0x0c7f, 0x007c, 0x70b4,
- 0xa080, 0x0091, 0x781a, 0x0078, 0x2459, 0x70b4, 0xa080, 0x0081,
- 0x781a, 0x0078, 0x2459, 0x70b4, 0xa080, 0x00be, 0x781a, 0x0078,
- 0x2459, 0x70b4, 0xa080, 0x00c8, 0x781a, 0x0078, 0x2459, 0x6904,
- 0xa18c, 0x00ff, 0xa196, 0x0007, 0x0040, 0x474c, 0xa196, 0x000f,
- 0x0040, 0x474c, 0x6807, 0x0117, 0x2001, 0x0200, 0x6826, 0x8007,
- 0x789b, 0x000e, 0x78aa, 0x6820, 0xa085, 0x8000, 0x6822, 0x2031,
- 0x0400, 0x6eb6, 0x7e5a, 0x71b4, 0xa188, 0x0091, 0x791a, 0x007c,
- 0x1078, 0x46ff, 0x7848, 0xa085, 0x000c, 0x784a, 0x70b4, 0xa080,
- 0x00d2, 0x781a, 0x2009, 0x000b, 0x2001, 0x4400, 0x1078, 0x46c1,
- 0x2001, 0x0013, 0x1078, 0x4691, 0x0078, 0x3b96, 0x127e, 0x2091,
- 0x2200, 0x2049, 0x4776, 0x7000, 0x7204, 0xa205, 0x720c, 0xa215,
- 0x7008, 0xa084, 0xfff7, 0xa205, 0x0040, 0x4788, 0x0078, 0x478d,
- 0x7003, 0x0000, 0x127f, 0x2000, 0x007c, 0x7000, 0xa084, 0x0001,
- 0x00c0, 0x47bb, 0x7108, 0x8103, 0x00c8, 0x479a, 0x1078, 0x48bd,
- 0x0078, 0x4792, 0x700c, 0xa08c, 0x00ff, 0x0040, 0x47bb, 0x7004,
- 0x8004, 0x00c8, 0x47b2, 0x7014, 0xa005, 0x00c0, 0x47ae, 0x7010,
- 0xa005, 0x0040, 0x47b2, 0xa102, 0x00c8, 0x4792, 0x7007, 0x0010,
- 0x0078, 0x47bb, 0x8aff, 0x0040, 0x47bb, 0x1078, 0x4b07, 0x00c0,
- 0x47b5, 0x0040, 0x4792, 0x1078, 0x4846, 0x7003, 0x0000, 0x127f,
- 0x2000, 0x007c, 0x017e, 0x6104, 0xa18c, 0x00ff, 0xa186, 0x0007,
- 0x0040, 0x47ce, 0xa18e, 0x000f, 0x00c0, 0x47d1, 0x6040, 0x0078,
- 0x47d2, 0x6428, 0x017f, 0x84ff, 0x0040, 0x47fc, 0x2c70, 0x7004,
- 0xa0bc, 0x000f, 0xa7b8, 0x480c, 0x273c, 0x87fb, 0x00c0, 0x47ea,
- 0x0048, 0x47e4, 0x1078, 0x23eb, 0x609c, 0xa075, 0x0040, 0x47fc,
- 0x0078, 0x47d7, 0x2704, 0xae68, 0x6808, 0xa630, 0x680c, 0xa529,
- 0x8421, 0x0040, 0x47fc, 0x8738, 0x2704, 0xa005, 0x00c0, 0x47eb,
- 0x709c, 0xa075, 0x00c0, 0x47d7, 0x007c, 0x0000, 0x0005, 0x0009,
- 0x000d, 0x0011, 0x0015, 0x0019, 0x001d, 0x0000, 0x0003, 0x0009,
- 0x000f, 0x0015, 0x001b, 0x0000, 0x0000, 0x4801, 0x47fe, 0x0000,
- 0x0000, 0x8000, 0x0000, 0x4801, 0x0000, 0x4809, 0x4806, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x4809, 0x0000, 0x4804, 0x4804, 0x0000,
- 0x0000, 0x8000, 0x0000, 0x4804, 0x0000, 0x480a, 0x480a, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x480a, 0x127e, 0x2091, 0x2200, 0x2079,
- 0x5100, 0x2071, 0x0010, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003,
- 0x0000, 0x2071, 0x0020, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003,
- 0x0000, 0x2049, 0x0000, 0x127f, 0x2000, 0x007c, 0x2049, 0x4846,
- 0x2019, 0x0000, 0x7004, 0x8004, 0x00c8, 0x4899, 0x7007, 0x0012,
- 0x7108, 0x7008, 0xa106, 0x00c0, 0x4850, 0xa184, 0x01e0, 0x0040,
- 0x485b, 0x1078, 0x23eb, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005,
- 0x00c8, 0x4866, 0xa184, 0x4000, 0x00c0, 0x4850, 0xa19c, 0x300c,
- 0xa386, 0x2004, 0x0040, 0x4874, 0xa386, 0x0008, 0x0040, 0x487f,
- 0xa386, 0x200c, 0x00c0, 0x4850, 0x7200, 0x8204, 0x0048, 0x487f,
- 0x730c, 0xa384, 0x00ff, 0x0040, 0x487f, 0x1078, 0x23eb, 0x7007,
- 0x0012, 0x7000, 0xa084, 0x0001, 0x00c0, 0x4899, 0x7008, 0xa084,
- 0x01e0, 0x00c0, 0x4899, 0x7310, 0x7014, 0xa305, 0x0040, 0x4899,
- 0x710c, 0xa184, 0x0300, 0x00c0, 0x4899, 0xa184, 0x00ff, 0x00c0,
- 0x4846, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004, 0xa084, 0x0008,
- 0x00c0, 0x489d, 0x7007, 0x0012, 0x7108, 0x8103, 0x0048, 0x48a2,
- 0x7003, 0x0000, 0x2049, 0x0000, 0x007c, 0x107e, 0x007e, 0x127e,
- 0x157e, 0x2091, 0x2200, 0x7108, 0x1078, 0x48bd, 0x157f, 0x127f,
- 0x2091, 0x8001, 0x007f, 0x107f, 0x007c, 0x7204, 0x7500, 0x730c,
- 0xa384, 0x0300, 0x00c0, 0x48e4, 0xa184, 0x01e0, 0x00c0, 0x4908,
- 0x7108, 0xa184, 0x01e0, 0x00c0, 0x4908, 0x2001, 0x04fd, 0x2004,
- 0xa082, 0x0005, 0x00c8, 0x48d8, 0xa184, 0x4000, 0x00c0, 0x48c8,
- 0xa184, 0x0007, 0x0079, 0x48dc, 0x48e6, 0x48f8, 0x48e4, 0x48f8,
- 0x48e4, 0x4944, 0x48e4, 0x4942, 0x1078, 0x23eb, 0x7004, 0xa084,
- 0x0010, 0xa085, 0x0002, 0x7006, 0x8aff, 0x00c0, 0x48f3, 0x2049,
- 0x0000, 0x0078, 0x48f7, 0x1078, 0x4b07, 0x00c0, 0x48f3, 0x007c,
- 0x7004, 0xa084, 0x0010, 0xa085, 0x0002, 0x7006, 0x8aff, 0x00c0,
- 0x4903, 0x0078, 0x4907, 0x1078, 0x4b07, 0x00c0, 0x4903, 0x007c,
- 0x7007, 0x0012, 0x7108, 0x00e0, 0x490b, 0x2091, 0x6000, 0x00e0,
- 0x490f, 0x2091, 0x6000, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004,
- 0xa084, 0x0008, 0x00c0, 0x4917, 0x7007, 0x0012, 0x7108, 0x8103,
- 0x0048, 0x491c, 0x7003, 0x0000, 0x7000, 0xa005, 0x00c0, 0x4930,
- 0x7004, 0xa005, 0x00c0, 0x4930, 0x700c, 0xa005, 0x0040, 0x4932,
- 0x0078, 0x4913, 0x2049, 0x0000, 0x1078, 0x3809, 0x6818, 0xa084,
- 0x8000, 0x0040, 0x493d, 0x681b, 0x0002, 0x007c, 0x1078, 0x23eb,
- 0x1078, 0x23eb, 0x1078, 0x49a0, 0x7210, 0x7114, 0x700c, 0xa09c,
- 0x00ff, 0x2800, 0xa300, 0xa211, 0xa189, 0x0000, 0x1078, 0x49a0,
- 0x2704, 0x2c58, 0xac60, 0x6308, 0x2200, 0xa322, 0x630c, 0x2100,
- 0xa31b, 0x2400, 0xa305, 0x0040, 0x4967, 0x00c8, 0x4967, 0x8412,
- 0x8210, 0x830a, 0xa189, 0x0000, 0x2b60, 0x0078, 0x494e, 0x2b60,
- 0x8a07, 0x007e, 0x6004, 0xa084, 0x0008, 0x0040, 0x4973, 0xa7ba,
- 0x4806, 0x0078, 0x4975, 0xa7ba, 0x47fe, 0x007f, 0xa73d, 0x2c00,
- 0x6886, 0x6f8a, 0x6c92, 0x6b8e, 0x7007, 0x0012, 0x1078, 0x4846,
- 0x007c, 0x8738, 0x2704, 0xa005, 0x00c0, 0x4994, 0x609c, 0xa005,
- 0x0040, 0x499d, 0x2060, 0x6004, 0xa084, 0x000f, 0xa080, 0x480c,
- 0x203c, 0x87fb, 0x1040, 0x23eb, 0x8a51, 0x0040, 0x499c, 0x7008,
- 0xa084, 0x0003, 0xa086, 0x0003, 0x007c, 0x2051, 0x0000, 0x007c,
- 0x8a50, 0x8739, 0x2704, 0xa004, 0x00c0, 0x49b4, 0x6000, 0xa064,
- 0x00c0, 0x49ab, 0x2d60, 0x6004, 0xa084, 0x000f, 0xa080, 0x481c,
- 0x203c, 0x87fb, 0x1040, 0x23eb, 0x007c, 0x127e, 0x0d7e, 0x2091,
- 0x2200, 0x0d7f, 0x6884, 0x2060, 0x6888, 0x6b8c, 0x6c90, 0x8057,
- 0xaad4, 0x00ff, 0xa084, 0x00ff, 0x007e, 0x6804, 0xa084, 0x0008,
- 0x007f, 0x0040, 0x49cf, 0xa0b8, 0x4806, 0x0078, 0x49d1, 0xa0b8,
- 0x47fe, 0x7e08, 0xa6b5, 0x000c, 0x6904, 0xa18c, 0x00ff, 0xa186,
- 0x0007, 0x0040, 0x49df, 0xa18e, 0x000f, 0x00c0, 0x49e8, 0x681c,
- 0xa084, 0x0040, 0x0040, 0x49ef, 0xa6b5, 0x0001, 0x0078, 0x49ef,
- 0x681c, 0xa084, 0x0040, 0x0040, 0x49ef, 0xa6b5, 0x0001, 0x7007,
- 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x49f1, 0x2400, 0xa305,
- 0x00c0, 0x49fc, 0x0078, 0x4a22, 0x2c58, 0x2704, 0x6104, 0xac60,
- 0x6000, 0xa400, 0x701a, 0x6004, 0xa301, 0x701e, 0xa184, 0x0008,
- 0x0040, 0x4a12, 0x6010, 0xa081, 0x0000, 0x7022, 0x6014, 0xa081,
- 0x0000, 0x7026, 0x6208, 0x2400, 0xa202, 0x7012, 0x620c, 0x2300,
- 0xa203, 0x7016, 0x7602, 0x7007, 0x0001, 0x2b60, 0x1078, 0x4981,
- 0x0078, 0x4a24, 0x1078, 0x4b07, 0x00c0, 0x4a22, 0x127f, 0x2000,
- 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x7007, 0x0004,
- 0x7004, 0xa084, 0x0004, 0x00c0, 0x4a30, 0x7003, 0x0008, 0x127f,
- 0x2000, 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x2049,
- 0x4a3a, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x4a43,
- 0x7e08, 0xa6b5, 0x000c, 0x6904, 0xa18c, 0x00ff, 0xa186, 0x0007,
- 0x0040, 0x4a56, 0xa18e, 0x000f, 0x00c0, 0x4a61, 0x681c, 0xa084,
- 0x0040, 0x0040, 0x4a5d, 0xa6b5, 0x0001, 0x6840, 0x2050, 0x0078,
- 0x4a6a, 0x681c, 0xa084, 0x0020, 0x00c0, 0x4a68, 0xa6b5, 0x0001,
- 0x6828, 0x2050, 0x2d60, 0x6004, 0xa0bc, 0x000f, 0xa7b8, 0x480c,
- 0x273c, 0x87fb, 0x00c0, 0x4a7e, 0x0048, 0x4a78, 0x1078, 0x23eb,
- 0x689c, 0xa065, 0x0040, 0x4a82, 0x0078, 0x4a6b, 0x1078, 0x4b07,
- 0x00c0, 0x4a7e, 0x127f, 0x2000, 0x007c, 0x127e, 0x007e, 0x017e,
- 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x037f, 0x047f, 0x7e08, 0xa6b5,
- 0x000c, 0x6904, 0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040, 0x4a9c,
- 0xa18e, 0x000f, 0x00c0, 0x4aa5, 0x681c, 0xa084, 0x0040, 0x0040,
- 0x4aac, 0xa6b5, 0x0001, 0x0078, 0x4aac, 0x681c, 0xa084, 0x0040,
- 0x0040, 0x4aac, 0xa6b5, 0x0001, 0x2049, 0x4a85, 0x017e, 0x6904,
- 0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040, 0x4aba, 0xa18e, 0x000f,
- 0x00c0, 0x4abd, 0x6840, 0x0078, 0x4abe, 0x6828, 0x017f, 0xa055,
- 0x0040, 0x4b04, 0x2d70, 0x2e60, 0x7004, 0xa0bc, 0x000f, 0xa7b8,
- 0x480c, 0x273c, 0x87fb, 0x00c0, 0x4ad8, 0x0048, 0x4ad1, 0x1078,
- 0x23eb, 0x709c, 0xa075, 0x2060, 0x0040, 0x4b04, 0x0078, 0x4ac4,
- 0x2704, 0xae68, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0048, 0x4af1,
- 0x8a51, 0x00c0, 0x4ae5, 0x1078, 0x23eb, 0x8738, 0x2704, 0xa005,
- 0x00c0, 0x4ad9, 0x709c, 0xa075, 0x2060, 0x0040, 0x4b04, 0x0078,
- 0x4ac4, 0x8422, 0x8420, 0x831a, 0xa399, 0x0000, 0x6908, 0x2400,
- 0xa122, 0x690c, 0x2300, 0xa11b, 0x00c8, 0x4b00, 0x1078, 0x23eb,
- 0x2071, 0x0020, 0x0078, 0x49ef, 0x127f, 0x2000, 0x007c, 0x7008,
- 0xa084, 0x0003, 0xa086, 0x0003, 0x0040, 0x4b2f, 0x2704, 0xac08,
- 0x2104, 0x701a, 0x8108, 0x2104, 0x701e, 0x8108, 0x2104, 0x7012,
- 0x8108, 0x2104, 0x7016, 0x6004, 0xa084, 0x0008, 0x0040, 0x4b26,
- 0x8108, 0x2104, 0x7022, 0x8108, 0x2104, 0x7026, 0x7602, 0x7004,
- 0xa084, 0x0010, 0xa085, 0x0001, 0x7006, 0x1078, 0x4981, 0x007c,
- 0x127e, 0x007e, 0x0d7e, 0x2091, 0x2200, 0x2049, 0x4b30, 0x0d7f,
- 0x087f, 0x7108, 0xa184, 0x0003, 0x00c0, 0x4b5a, 0x017e, 0x6904,
- 0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040, 0x4b4a, 0xa18e, 0x000f,
- 0x00c0, 0x4b4d, 0x6840, 0x0078, 0x4b4e, 0x6828, 0x017f, 0xa005,
- 0x0040, 0x4b68, 0x0078, 0x478d, 0x0020, 0x4b5a, 0x1078, 0x4944,
- 0x0078, 0x4b68, 0x00a0, 0x4b61, 0x7108, 0x1078, 0x48bd, 0x0078,
- 0x4b39, 0x7007, 0x0010, 0x00a0, 0x4b63, 0x7108, 0x1078, 0x48bd,
- 0x7008, 0xa086, 0x0008, 0x00c0, 0x4b39, 0x7000, 0xa005, 0x00c0,
- 0x4b39, 0x7003, 0x0000, 0x2049, 0x0000, 0x127f, 0x2000, 0x007c,
- 0x127e, 0x147e, 0x137e, 0x157e, 0x0c7e, 0x0d7e, 0x2091, 0x2200,
- 0x0d7f, 0x2049, 0x4b78, 0xad80, 0x0011, 0x20a0, 0x2099, 0x0031,
- 0x700c, 0xa084, 0x00ff, 0x682a, 0x7007, 0x0008, 0x7007, 0x0002,
- 0x7003, 0x0001, 0x0040, 0x4b97, 0x8000, 0x80ac, 0x53a5, 0x7007,
- 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x4b99, 0x0c7f, 0x2049,
- 0x0000, 0x7003, 0x0000, 0x157f, 0x137f, 0x147f, 0x127f, 0x2000,
- 0x007c, 0x2091, 0x6000, 0x2091, 0x8000, 0x78cc, 0xa005, 0x0040,
- 0x4bc0, 0x7994, 0x70d0, 0xa106, 0x00c0, 0x4bc0, 0x7804, 0xa005,
- 0x0040, 0x4bc0, 0x7807, 0x0000, 0x0068, 0x4bc0, 0x2091, 0x4080,
- 0x7820, 0x8001, 0x7822, 0x00c0, 0x4c1b, 0x7824, 0x7822, 0x2069,
- 0x5140, 0x6800, 0xa084, 0x0007, 0x0040, 0x4bde, 0xa086, 0x0002,
- 0x0040, 0x4bde, 0x6834, 0xa00d, 0x0040, 0x4bde, 0x2104, 0xa005,
- 0x0040, 0x4bde, 0x8001, 0x200a, 0x0040, 0x4cc3, 0x7848, 0xa005,
- 0x0040, 0x4bec, 0x8001, 0x784a, 0x00c0, 0x4bec, 0x2009, 0x0102,
- 0x6844, 0x200a, 0x1078, 0x21d2, 0x6890, 0xa005, 0x0040, 0x4bf8,
- 0x8001, 0x6892, 0x00c0, 0x4bf8, 0x686f, 0x0000, 0x6873, 0x0001,
- 0x2061, 0x5400, 0x20a9, 0x0100, 0x2009, 0x0002, 0x6034, 0xa005,
- 0x0040, 0x4c0e, 0x8001, 0x6036, 0x00c0, 0x4c0e, 0x6010, 0xa005,
- 0x0040, 0x4c0e, 0x017e, 0x1078, 0x21d2, 0x017f, 0xace0, 0x0010,
- 0x0070, 0x4c14, 0x0078, 0x4bfe, 0x8109, 0x0040, 0x4c1b, 0x20a9,
- 0x0100, 0x0078, 0x4bfe, 0x1078, 0x4c28, 0x1078, 0x4c4d, 0x2009,
- 0x5151, 0x2104, 0x2009, 0x0102, 0x200a, 0x2091, 0x8001, 0x007c,
- 0x7834, 0x8001, 0x7836, 0x00c0, 0x4c4c, 0x7838, 0x7836, 0x2091,
- 0x8000, 0x7844, 0xa005, 0x00c0, 0x4c37, 0x2001, 0x0101, 0x8001,
- 0x7846, 0xa080, 0x7400, 0x2040, 0x2004, 0xa065, 0x0040, 0x4c4c,
- 0x6024, 0xa005, 0x0040, 0x4c48, 0x8001, 0x6026, 0x0040, 0x4c7c,
- 0x6000, 0x2c40, 0x0078, 0x4c3d, 0x007c, 0x7828, 0x8001, 0x782a,
- 0x00c0, 0x4c7b, 0x782c, 0x782a, 0x7830, 0xa005, 0x00c0, 0x4c5a,
- 0x2001, 0x0200, 0x8001, 0x7832, 0x8003, 0x8003, 0x8003, 0x8003,
- 0xa090, 0x5400, 0xa298, 0x0002, 0x2304, 0xa084, 0x0008, 0x0040,
- 0x4c7b, 0xa290, 0x0009, 0x2204, 0xa005, 0x0040, 0x4c73, 0x8001,
- 0x2012, 0x00c0, 0x4c7b, 0x2304, 0xa084, 0xfff7, 0xa085, 0x0080,
- 0x201a, 0x1078, 0x21d2, 0x007c, 0x2069, 0x5140, 0x6800, 0xa005,
- 0x0040, 0x4c86, 0x6848, 0xac06, 0x0040, 0x4cc3, 0x601b, 0x0006,
- 0x60b4, 0xa084, 0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff, 0xa085,
- 0x0060, 0x6022, 0x6000, 0x2042, 0x6714, 0x6f82, 0x1078, 0x1973,
- 0x6818, 0xa005, 0x0040, 0x4c9e, 0x8001, 0x681a, 0x6808, 0xa084,
- 0xffef, 0x680a, 0x6810, 0x8001, 0x00d0, 0x4ca8, 0x1078, 0x23eb,
- 0x6812, 0x602f, 0x0000, 0x6033, 0x0000, 0x2c68, 0x1078, 0x1c70,
- 0x2069, 0x5140, 0x7944, 0xa184, 0x0100, 0x2001, 0x0006, 0x686e,
- 0x00c0, 0x4cbe, 0x6986, 0x2001, 0x0004, 0x686e, 0x1078, 0x21cd,
- 0x2091, 0x8001, 0x007c, 0x2069, 0x0100, 0x2009, 0x5140, 0x2104,
- 0xa084, 0x0007, 0x0040, 0x4d1f, 0xa086, 0x0007, 0x00c0, 0x4cd9,
- 0x0d7e, 0x2009, 0x5152, 0x216c, 0x1078, 0x3a4e, 0x0d7f, 0x0078,
- 0x4d1f, 0x2009, 0x5152, 0x2164, 0x1078, 0x2396, 0x601b, 0x0006,
- 0x6858, 0xa084, 0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff, 0xa085,
- 0x0048, 0x6022, 0x602f, 0x0000, 0x6033, 0x0000, 0x6830, 0xa084,
- 0x0040, 0x0040, 0x4d13, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848,
- 0xa084, 0x0004, 0x0040, 0x4d00, 0x0070, 0x4d00, 0x0078, 0x4cf7,
- 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0001, 0x0040,
- 0x4d0d, 0x0070, 0x4d0d, 0x0078, 0x4d04, 0x20a9, 0x00fa, 0x0070,
- 0x4d13, 0x0078, 0x4d0f, 0x6808, 0xa084, 0xfffd, 0x680a, 0x681b,
- 0x0048, 0x2009, 0x515b, 0x200b, 0x0007, 0x784c, 0x784a, 0x2091,
- 0x8001, 0x007c, 0x2079, 0x5100, 0x1078, 0x4d4d, 0x1078, 0x4d31,
- 0x1078, 0x4d3f, 0x7833, 0x0000, 0x7847, 0x0000, 0x784b, 0x0000,
- 0x007c, 0x2019, 0x0003, 0x2011, 0x5146, 0x2204, 0xa086, 0x003c,
- 0x0040, 0x4d3c, 0x2019, 0x0002, 0x7b2a, 0x7b2e, 0x007c, 0x2019,
- 0x0039, 0x2011, 0x5146, 0x2204, 0xa086, 0x003c, 0x0040, 0x4d4a,
- 0x2019, 0x0027, 0x7b36, 0x7b3a, 0x007c, 0x2019, 0x3971, 0x2011,
- 0x5146, 0x2204, 0xa086, 0x003c, 0x0040, 0x4d58, 0x2019, 0x2626,
- 0x7b22, 0x7b26, 0x783f, 0x0000, 0x7843, 0x000a, 0x007c, 0x0020,
- 0x002b, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
- 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
- 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
- 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
- 0x0020, 0x0000, 0x0014, 0x0014, 0x9849, 0x0014, 0x0014, 0x0014,
- 0x0014, 0x0014, 0x0014, 0x0014, 0x0080, 0x000f, 0x0000, 0x0201,
- 0x0604, 0x0c08, 0x2120, 0x4022, 0xf880, 0x0018, 0x300b, 0xa201,
- 0x0014, 0xa200, 0x0014, 0xa200, 0x0214, 0x0000, 0x006c, 0x0002,
- 0x0014, 0x98d0, 0x009e, 0x0096, 0xa202, 0x8838, 0x3806, 0x8839,
- 0x20c3, 0x0864, 0x9884, 0x28c1, 0x9cb1, 0xa203, 0x300c, 0x2846,
- 0x8161, 0x846a, 0x8300, 0x1856, 0x883a, 0x9865, 0x28f2, 0x9c90,
- 0x9858, 0x300c, 0x28e1, 0x9c90, 0x2802, 0xa206, 0x64c3, 0x282d,
- 0xa207, 0x64a0, 0x67a0, 0x6fc0, 0x1814, 0x883b, 0x7824, 0x68c1,
- 0x7864, 0x883e, 0x9878, 0x8576, 0x8677, 0x206b, 0x28c1, 0x9cb1,
- 0x2044, 0x2103, 0x20a2, 0x2081, 0x9865, 0xa209, 0x2901, 0x988c,
- 0x0014, 0xa205, 0xa300, 0x1872, 0x879a, 0x883c, 0x1fe2, 0xc601,
- 0xa20a, 0x856e, 0x0704, 0x9c90, 0x0014, 0xa204, 0xa300, 0x3009,
- 0x19e2, 0xf868, 0x8176, 0x86eb, 0x85eb, 0x872e, 0x87a9, 0x883f,
- 0x08e6, 0x9890, 0xf881, 0x988b, 0xc801, 0x0014, 0xf8c1, 0x0016,
- 0x85b2, 0x80f0, 0x9532, 0xfb02, 0x1de2, 0x0014, 0x8532, 0xf241,
- 0x0014, 0x1de2, 0x84a8, 0xd7a0, 0x1fe6, 0x0014, 0xa208, 0x6043,
- 0x8008, 0x1dc1, 0x0016, 0x8300, 0x8160, 0x842a, 0xf041, 0x3008,
- 0x84a8, 0x11d6, 0x7042, 0x20dd, 0x0011, 0x20d5, 0x8822, 0x0016,
- 0x8000, 0x2847, 0x1011, 0x98c3, 0x8000, 0xa000, 0x2802, 0x1011,
- 0x98c9, 0x9865, 0x283e, 0x1011, 0x98cd, 0xa20b, 0x0017, 0x300c,
- 0xa300, 0x1de2, 0xdb81, 0x0014, 0x0210, 0x98da, 0x0014, 0x26e0,
- 0x873a, 0xfb02, 0x19f2, 0x1fe2, 0x0014, 0xa20d, 0x3806, 0x0210,
- 0x9cb6, 0x0704, 0x0000, 0x006c, 0x0002, 0x984f, 0x0014, 0x009e,
- 0x00a5, 0x0017, 0x60ff, 0x300c, 0x8720, 0xa211, 0x9cd5, 0x8772,
- 0x8837, 0x2101, 0x987a, 0x10d2, 0x78e2, 0x9cd8, 0x9859, 0xd984,
- 0xf0e2, 0xf0a1, 0x98d2, 0x0014, 0x8831, 0xd166, 0x8830, 0x800f,
- 0x9401, 0xb520, 0xc802, 0x8820, 0x987a, 0x2301, 0x987a, 0x10d2,
- 0x78e4, 0x9cd8, 0x8821, 0x8820, 0x9859, 0xf123, 0xf142, 0xf101,
- 0x98cb, 0x10d2, 0x70f6, 0x8832, 0x8203, 0x870c, 0xd99e, 0x6001,
- 0x0014, 0x6845, 0x0214, 0xa21b, 0x9cd5, 0x2001, 0x98ca, 0x8201,
- 0x1852, 0xd184, 0xd163, 0x8834, 0x8001, 0x988d, 0x3027, 0x84a8,
- 0x1a56, 0x8833, 0x0014, 0xa218, 0x6981, 0x9cc1, 0x692a, 0x6902,
- 0x1834, 0x989d, 0x1a14, 0x8010, 0x8592, 0x8026, 0x84b9, 0x7021,
- 0x0014, 0xa300, 0x69e1, 0x9caa, 0x694c, 0xa213, 0x9cba, 0x1462,
- 0xa213, 0x8000, 0x16e1, 0x98b4, 0x8023, 0x16e1, 0x8001, 0x10f1,
- 0x0016, 0x6968, 0xa214, 0x9cba, 0x8004, 0x16e1, 0x0101, 0x300a,
- 0x8827, 0x0014, 0x9cba, 0x0014, 0x61c2, 0x8002, 0x14e1, 0x0016,
- 0xa217, 0x9cc1, 0x0014, 0xa300, 0x8181, 0x842a, 0x84a8, 0x1ce6,
- 0x882c, 0x0016, 0xa212, 0x9cd5, 0x10d2, 0x70e4, 0x0004, 0x8007,
- 0x9424, 0xcc1a, 0x9cd8, 0x98ca, 0x8827, 0x300a, 0x0013, 0x8000,
- 0x84a4, 0x0016, 0x11c2, 0x211e, 0x870e, 0xa21d, 0x0014, 0x878e,
- 0x0016, 0xa21c, 0x1035, 0x9891, 0xa210, 0xa000, 0x8010, 0x8592,
- 0x853b, 0xd044, 0x8022, 0x3807, 0x84bb, 0x98ef, 0x8021, 0x3807,
- 0x84b9, 0x300c, 0x817e, 0x872b, 0x8772, 0x9891, 0x0000, 0x0020,
- 0x002b, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
- 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
- 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
- 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
- 0x0020, 0x0000, 0x0014, 0x0014, 0x9849, 0x0014, 0x0014, 0x98e5,
- 0x98d0, 0x0014, 0x0014, 0x0014, 0x0080, 0x013f, 0x0000, 0x0201,
- 0x0604, 0x0c08, 0x2120, 0x4022, 0xf880, 0x0018, 0x300b, 0xa201,
- 0x0014, 0xa200, 0x0014, 0xa200, 0x0214, 0xa202, 0x8838, 0x3806,
- 0x8839, 0x20c3, 0x0864, 0xa82e, 0x28c1, 0x9cb1, 0xa203, 0x300c,
- 0x2846, 0x8161, 0x846a, 0x8300, 0x1856, 0x883a, 0xa804, 0x28f2,
- 0x9c90, 0xa8f4, 0x300c, 0x28e1, 0x9c90, 0x2802, 0xa206, 0x64c3,
- 0x282d, 0xa207, 0x64a0, 0x67a0, 0x6fc0, 0x1814, 0x883b, 0x7824,
- 0x68c1, 0x7864, 0x883e, 0xa802, 0x8576, 0x8677, 0x206b, 0x28c1,
- 0x9cb1, 0x2044, 0x2103, 0x20a2, 0x2081, 0xa8e5, 0xa209, 0x2901,
- 0xa809, 0x0014, 0xa205, 0xa300, 0x1872, 0x879a, 0x883c, 0x1fe2,
- 0xc601, 0xa20a, 0x856e, 0x0704, 0x9c90, 0x0014, 0xa204, 0xa300,
- 0x3009, 0x19e2, 0xf868, 0x8176, 0x86eb, 0x85eb, 0x872e, 0x87a9,
- 0x883f, 0x08e6, 0xa8f3, 0xf881, 0xa8ec, 0xc801, 0x0014, 0xf8c1,
- 0x0016, 0x85b2, 0x80f0, 0x9532, 0xfb02, 0x1de2, 0x0014, 0x8532,
- 0xf241, 0x0014, 0x1de2, 0x84a8, 0xd7a0, 0x1fe6, 0x0014, 0xa208,
- 0x6043, 0x8008, 0x1dc1, 0x0016, 0x8300, 0x8160, 0x842a, 0xf041,
- 0x3008, 0x84a8, 0x11d6, 0x7042, 0x20dd, 0x0011, 0x20d5, 0x8822,
- 0x0016, 0x8000, 0x2847, 0x1011, 0xa8fc, 0x8000, 0xa000, 0x2802,
- 0x1011, 0xa8fd, 0xa898, 0x283e, 0x1011, 0xa8fd, 0xa20b, 0x0017,
- 0x300c, 0xa300, 0x1de2, 0xdb81, 0x0014, 0x0210, 0xa801, 0x0014,
- 0x26e0, 0x873a, 0xfb02, 0x19f2, 0x1fe2, 0x0014, 0xa20d, 0x3806,
- 0x0210, 0x9cb6, 0x0704, 0x0017, 0x60ff, 0x300c, 0x8720, 0xa211,
- 0x9d6b, 0x8772, 0x8837, 0x2101, 0xa821, 0x10d2, 0x78e2, 0x9d6e,
- 0xa8fc, 0xd984, 0xf0e2, 0xf0a1, 0xa871, 0x0014, 0x8831, 0xd166,
- 0x8830, 0x800f, 0x9401, 0xb520, 0xc802, 0x8820, 0xa80f, 0x2301,
- 0xa80d, 0x10d2, 0x78e4, 0x9d6e, 0x8821, 0x8820, 0xa8e6, 0xf123,
- 0xf142, 0xf101, 0xa854, 0x10d2, 0x70f6, 0x8832, 0x8203, 0x870c,
- 0xd99e, 0x6001, 0x0014, 0x6845, 0x0214, 0xa21b, 0x9d6b, 0x2001,
- 0xa845, 0x8201, 0x1852, 0xd184, 0xd163, 0x8834, 0x8001, 0xa801,
- 0x3027, 0x84a8, 0x1a56, 0x8833, 0x0014, 0xa218, 0x6981, 0x9d57,
- 0x692a, 0x6902, 0x1834, 0xa805, 0x1a14, 0x8010, 0x8592, 0x8026,
- 0x84b9, 0x7021, 0x0014, 0xa300, 0x69e1, 0x9d40, 0x694c, 0xa213,
- 0x9d50, 0x1462, 0xa213, 0x8000, 0x16e1, 0xa80a, 0x8023, 0x16e1,
- 0x8001, 0x10f1, 0x0016, 0x6968, 0xa214, 0x9d50, 0x8004, 0x16e1,
- 0x0101, 0x300a, 0x8827, 0x0014, 0x9d50, 0x0014, 0x61c2, 0x8002,
- 0x14e1, 0x0016, 0xa217, 0x9d57, 0x0014, 0xa300, 0x8181, 0x842a,
- 0x84a8, 0x1ce6, 0x882c, 0x0016, 0xa212, 0x9d6b, 0x10d2, 0x70e4,
- 0x0004, 0x8007, 0x9424, 0xcc1a, 0x9d6e, 0xa8f8, 0x8827, 0x300a,
- 0x0013, 0x8000, 0x84a4, 0x0016, 0x11c2, 0x211e, 0x870e, 0xa21d,
- 0x0014, 0x878e, 0x0016, 0xa21c, 0x1035, 0xa8af, 0xa210, 0x3807,
- 0x300c, 0x817e, 0x872b, 0x8772, 0xa8a8, 0x0000, 0xdf21
+ 0x6814, 0x8007, 0x7882, 0x0078, 0x3960, 0x6818, 0xa084, 0x8000,
+ 0x0040, 0x3234, 0x681b, 0x0008, 0x781b, 0x00c0, 0x0078, 0x24fa,
+ 0x2300, 0x0079, 0x323b, 0x3240, 0x32d4, 0x323e, 0x1078, 0x248c,
+ 0x7000, 0xa084, 0x0007, 0x0079, 0x3245, 0x2523, 0x324f, 0x3284,
+ 0x325a, 0x324d, 0x2523, 0x324d, 0x324d, 0x1078, 0x248c, 0x681c,
+ 0xa084, 0x2000, 0x0040, 0x3268, 0x6008, 0xa085, 0x0002, 0x600a,
+ 0x0078, 0x3268, 0x68c0, 0xa005, 0x00c0, 0x3284, 0x6920, 0xa18d,
+ 0x0001, 0x6922, 0x68c3, 0x0001, 0x6800, 0x706a, 0x0078, 0x327e,
+ 0x6920, 0xa18d, 0x0001, 0x6922, 0x6800, 0x6006, 0xa005, 0x00c0,
+ 0x3272, 0x6002, 0x681c, 0xa084, 0x000e, 0x0040, 0x327e, 0x7014,
+ 0x68ba, 0x7130, 0xa188, 0x7500, 0x0078, 0x3280, 0x2009, 0x7600,
+ 0x2104, 0x6802, 0x2d0a, 0x7162, 0x6eb6, 0xa684, 0x0060, 0x0040,
+ 0x32d2, 0xa684, 0x0800, 0x00c0, 0x3298, 0xa684, 0x7fff, 0x68b6,
+ 0x6894, 0x68a6, 0x6898, 0x68aa, 0x1078, 0x4887, 0x0078, 0x32d2,
+ 0xa684, 0x0020, 0x0040, 0x32ad, 0x68c0, 0xa005, 0x0040, 0x32a4,
+ 0x1078, 0x4c89, 0x0078, 0x32a7, 0xa006, 0x1078, 0x4c41, 0x79d8,
+ 0x7adc, 0x69aa, 0x6aa6, 0x0078, 0x32b3, 0x1078, 0x38ca, 0x69aa,
+ 0x6aa6, 0x1078, 0x4c41, 0xa684, 0x8000, 0x0040, 0x32d2, 0xa684,
+ 0x7fff, 0x68b6, 0x7adc, 0x79d8, 0xa684, 0x0020, 0x00c0, 0x32ca,
+ 0x78d0, 0x801b, 0x00c8, 0x32c5, 0x8000, 0xa084, 0x003f, 0xa108,
+ 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200,
+ 0xa303, 0x68ae, 0x0078, 0x2523, 0x0078, 0x377b, 0x7037, 0x0000,
+ 0xa282, 0x0006, 0x0050, 0x32de, 0x1078, 0x248c, 0x7000, 0xa084,
+ 0x0007, 0x10c0, 0x3a8c, 0x2300, 0x0079, 0x32e6, 0x32e9, 0x3312,
+ 0x3326, 0x2200, 0x0079, 0x32ec, 0x3310, 0x377b, 0x32f2, 0x3310,
+ 0x3342, 0x3384, 0x7003, 0x0005, 0x2001, 0x7710, 0x2068, 0x704a,
+ 0x157e, 0x20a9, 0x0031, 0x2003, 0x0000, 0x8000, 0x0070, 0x3302,
+ 0x0078, 0x32fb, 0x157f, 0xad80, 0x0009, 0x7036, 0x6817, 0x0000,
+ 0x68b7, 0x0700, 0x6823, 0x0800, 0x6827, 0x0003, 0x0078, 0x376b,
+ 0x1078, 0x248c, 0x7003, 0x0005, 0x2001, 0x7710, 0x2068, 0x704a,
+ 0xad80, 0x0009, 0x7036, 0x2200, 0x0079, 0x331e, 0x377b, 0x3324,
+ 0x3324, 0x3342, 0x3324, 0x377b, 0x1078, 0x248c, 0x7003, 0x0005,
+ 0x2001, 0x7710, 0x2068, 0x704a, 0xad80, 0x0009, 0x7036, 0x2200,
+ 0x0079, 0x3332, 0x333a, 0x3338, 0x3338, 0x333a, 0x3338, 0x333a,
+ 0x1078, 0x248c, 0x1078, 0x379f, 0x782b, 0x3008, 0x781b, 0x0065,
+ 0x0078, 0x24fa, 0x7003, 0x0002, 0x7a80, 0xa294, 0x0f00, 0x789b,
+ 0x0018, 0x7ca8, 0xa484, 0x001f, 0xa215, 0x2069, 0x7600, 0x2d04,
+ 0x2d08, 0x7162, 0x2068, 0xa005, 0x0040, 0x335d, 0x6814, 0xa206,
+ 0x0040, 0x3379, 0x6800, 0x0078, 0x3350, 0x7003, 0x0005, 0x2001,
+ 0x7710, 0x2068, 0x704a, 0x7036, 0x157e, 0x20a9, 0x0031, 0x2003,
+ 0x0000, 0x8000, 0x0070, 0x336e, 0x0078, 0x3367, 0x157f, 0xad80,
+ 0x0009, 0x7036, 0x6a16, 0x68b7, 0x0700, 0x6823, 0x0800, 0x6827,
+ 0x0003, 0x6eb4, 0x7e5a, 0x6820, 0xa084, 0x0c00, 0x0040, 0x33d3,
+ 0x1078, 0x3797, 0x0078, 0x33d3, 0x7003, 0x0002, 0x7a80, 0xa294,
+ 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, 0x001f, 0xa215, 0x79a8,
+ 0x79a8, 0xa18c, 0x00ff, 0xa1e8, 0x7500, 0x2d04, 0x2d08, 0x7162,
+ 0x2068, 0xa005, 0x0040, 0x33a3, 0x6814, 0xa206, 0x0040, 0x33be,
+ 0x6800, 0x0078, 0x3396, 0x7003, 0x0005, 0x2001, 0x7710, 0x2068,
+ 0x704a, 0x157e, 0x20a9, 0x0031, 0x2003, 0x0000, 0x8000, 0x0070,
+ 0x33b3, 0x0078, 0x33ac, 0x157f, 0xad80, 0x0009, 0x7036, 0x6a16,
+ 0x68b7, 0x0700, 0x6823, 0x0800, 0x6827, 0x0003, 0x6eb4, 0x7e5a,
+ 0x6820, 0xa084, 0x0c00, 0x0040, 0x33d3, 0xa084, 0x0800, 0x0040,
+ 0x33cd, 0x1078, 0x379b, 0x0078, 0x33d3, 0x1078, 0x3797, 0x708b,
+ 0x0000, 0x0078, 0x33d3, 0x027e, 0x8207, 0xa084, 0x000f, 0x8003,
+ 0x8003, 0x8003, 0xa080, 0x5480, 0x2060, 0x7056, 0x6000, 0x705a,
+ 0x6004, 0x705e, 0xa684, 0x0060, 0x0040, 0x342b, 0x6b98, 0x6c94,
+ 0x69ac, 0x68b0, 0xa105, 0x00c0, 0x340d, 0x7bd2, 0x7bda, 0x7cd6,
+ 0x7cde, 0xa6b4, 0xb7ff, 0x7e5a, 0xa684, 0x0060, 0xa086, 0x0060,
+ 0x0040, 0x342b, 0x68c0, 0xa005, 0x0040, 0x3406, 0x7003, 0x0003,
+ 0x682b, 0x0000, 0x1078, 0x4b3a, 0x0078, 0x3408, 0x1078, 0x4b4b,
+ 0xa6b5, 0x2000, 0x7e5a, 0x0078, 0x342b, 0x68b0, 0xa31a, 0x2100,
+ 0xa423, 0x2400, 0xa305, 0x0040, 0x342b, 0x7bd2, 0x7bda, 0x7cd6,
+ 0x7cde, 0x68b0, 0xa6b4, 0xbfff, 0x7e5a, 0x007e, 0x68c0, 0xa005,
+ 0x007f, 0x0040, 0x3429, 0x7003, 0x0003, 0x1078, 0x4b3a, 0x0078,
+ 0x342b, 0x1078, 0x4b96, 0x077f, 0x1078, 0x38bd, 0x2009, 0x0065,
+ 0xa684, 0x0004, 0x0040, 0x344c, 0x78e4, 0xa084, 0x0030, 0x0040,
+ 0x3444, 0x78ec, 0xa084, 0x0003, 0x0040, 0x3444, 0x782b, 0x3008,
+ 0x2009, 0x0065, 0x0078, 0x344c, 0x0f7e, 0x2079, 0x5200, 0x1078,
+ 0x4887, 0x0f7f, 0x0040, 0x2523, 0x791a, 0x2d00, 0x704a, 0x8207,
+ 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x5480, 0x2048,
+ 0x0078, 0x24fa, 0x6020, 0xa005, 0x0040, 0x3466, 0x8001, 0x6022,
+ 0x6008, 0xa085, 0x0008, 0x600a, 0x7010, 0x6026, 0x007c, 0xa006,
+ 0x1078, 0x4887, 0x6817, 0x0000, 0x681b, 0x0001, 0x6823, 0x0040,
+ 0x681f, 0x0100, 0x7000, 0xa084, 0x0007, 0x0079, 0x3477, 0x2523,
+ 0x3481, 0x3481, 0x349e, 0x3489, 0x3487, 0x3489, 0x347f, 0x1078,
+ 0x248c, 0x1078, 0x34a9, 0x1078, 0x34a2, 0x1078, 0x1cdc, 0x0078,
+ 0x2523, 0x706c, 0x706f, 0x0000, 0x7093, 0x0000, 0x0079, 0x3490,
+ 0x349a, 0x349a, 0x3498, 0x3498, 0x3498, 0x349a, 0x3498, 0x349a,
+ 0x0079, 0x2902, 0x706f, 0x0000, 0x0078, 0x2523, 0x681b, 0x0000,
+ 0x0078, 0x2fb6, 0x6800, 0xa005, 0x00c0, 0x34a7, 0x6002, 0x6006,
+ 0x007c, 0x6010, 0xa005, 0x0040, 0x34b2, 0x8001, 0x00d0, 0x34b2,
+ 0x1078, 0x248c, 0x6012, 0x6008, 0xa084, 0xffef, 0x600a, 0x007c,
+ 0x6018, 0xa005, 0x0040, 0x34be, 0x8001, 0x601a, 0x007c, 0x1078,
+ 0x39e0, 0x681b, 0x0018, 0x0078, 0x34f5, 0x1078, 0x39e0, 0x681b,
+ 0x0019, 0x0078, 0x34f5, 0x1078, 0x39e0, 0x681b, 0x001a, 0x0078,
+ 0x34f5, 0x1078, 0x39e0, 0x681b, 0x0003, 0x0078, 0x34f5, 0x7780,
+ 0x1078, 0x38bd, 0x7184, 0xa18c, 0x00ff, 0xa1e8, 0x7500, 0x2d04,
+ 0x2d08, 0x2068, 0xa005, 0x00c0, 0x34e7, 0x0078, 0x2523, 0x6814,
+ 0x7280, 0xa206, 0x0040, 0x34ef, 0x6800, 0x0078, 0x34e0, 0x6800,
+ 0x200a, 0x681b, 0x0005, 0x708b, 0x0000, 0x1078, 0x34a9, 0x6820,
+ 0xa084, 0x0001, 0x00c0, 0x34fe, 0x1078, 0x34a2, 0x1078, 0x34b8,
+ 0x681f, 0x0000, 0x6823, 0x0020, 0x1078, 0x1cdc, 0x0078, 0x2523,
+ 0xa282, 0x0003, 0x00c0, 0x376b, 0x7da8, 0xa5ac, 0x00ff, 0x7ca8,
+ 0xa4a4, 0x00ff, 0x6920, 0xa18d, 0x0080, 0x6922, 0xa184, 0x0100,
+ 0x0040, 0x356c, 0xa18c, 0xfeff, 0x6922, 0xa4a4, 0x00ff, 0x0040,
+ 0x3556, 0xa482, 0x000c, 0x0048, 0x3529, 0x0040, 0x3529, 0x2021,
+ 0x000c, 0x852b, 0x852b, 0x1078, 0x382e, 0x0040, 0x3533, 0x1078,
+ 0x3627, 0x0078, 0x355f, 0x1078, 0x37e9, 0x0c7e, 0x2960, 0x6004,
+ 0xa084, 0xfff5, 0x6006, 0x1078, 0x3652, 0x0c7f, 0x6920, 0xa18d,
+ 0x0100, 0x6922, 0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400,
+ 0x00c0, 0x3550, 0x782b, 0x3008, 0x781b, 0x0056, 0x0078, 0x24fa,
+ 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x24fa, 0x0c7e, 0x2960,
+ 0x6004, 0xa084, 0xfff5, 0x6006, 0x1078, 0x3652, 0x0c7f, 0x7e58,
+ 0xa684, 0x0400, 0x00c0, 0x3568, 0x781b, 0x0058, 0x0078, 0x24fa,
+ 0x781b, 0x0065, 0x0078, 0x24fa, 0x0c7e, 0x7054, 0x2060, 0x6100,
+ 0xa18c, 0x1000, 0x0040, 0x35ac, 0x6208, 0x8217, 0xa294, 0x00ff,
+ 0xa282, 0x000c, 0x0048, 0x3580, 0x0040, 0x3580, 0x2011, 0x000c,
+ 0x2400, 0xa202, 0x00c8, 0x3585, 0x2220, 0x6208, 0xa294, 0x00ff,
+ 0x7018, 0xa086, 0x0028, 0x00c0, 0x3595, 0xa282, 0x0019, 0x00c8,
+ 0x359b, 0x2011, 0x0019, 0x0078, 0x359b, 0xa282, 0x000c, 0x00c8,
+ 0x359b, 0x2011, 0x000c, 0x2200, 0xa502, 0x00c8, 0x35a0, 0x2228,
+ 0x1078, 0x37ed, 0x852b, 0x852b, 0x1078, 0x382e, 0x0040, 0x35ac,
+ 0x1078, 0x3627, 0x0078, 0x35b0, 0x1078, 0x37e9, 0x1078, 0x3652,
+ 0x7858, 0xa085, 0x0004, 0x785a, 0x0c7f, 0x782b, 0x3008, 0x781b,
+ 0x0065, 0x0078, 0x24fa, 0x0c7e, 0x2960, 0x6000, 0xd0e4, 0x00c0,
+ 0x35d5, 0xd0b4, 0x00c0, 0x35cf, 0x6010, 0xa084, 0x000f, 0x00c0,
+ 0x35cf, 0x6104, 0xa18c, 0xfff5, 0x6106, 0x0c7f, 0x007c, 0x2011,
+ 0x0032, 0x2019, 0x0000, 0x0078, 0x35fc, 0x68a0, 0xa084, 0x0200,
+ 0x00c0, 0x35cf, 0x6208, 0xa294, 0x00ff, 0x7018, 0xa086, 0x0028,
+ 0x00c0, 0x35ea, 0xa282, 0x0019, 0x00c8, 0x35f0, 0x2011, 0x0019,
+ 0x0078, 0x35f0, 0xa282, 0x000c, 0x00c8, 0x35f0, 0x2011, 0x000c,
+ 0x6308, 0x831f, 0xa39c, 0x00ff, 0xa382, 0x000c, 0x0048, 0x35fc,
+ 0x0040, 0x35fc, 0x2019, 0x000c, 0x78ab, 0x0001, 0x78ab, 0x0003,
+ 0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820, 0xa085,
+ 0x0100, 0x6822, 0x0c7f, 0x007c, 0x0c7e, 0x2960, 0xa18c, 0xfff5,
+ 0x6106, 0x2011, 0x0032, 0x2019, 0x0000, 0x0078, 0x3617, 0x78ab,
+ 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0,
+ 0x0005, 0x6820, 0xa085, 0x0100, 0x6822, 0x0c7f, 0x007c, 0x0c7e,
+ 0x7154, 0x2160, 0x1078, 0x362e, 0x0c7f, 0x007c, 0x2008, 0xa084,
+ 0xfff0, 0xa425, 0x7c86, 0x6018, 0x789a, 0x7cae, 0x6412, 0x78a4,
+ 0xa084, 0xfff8, 0xa18c, 0x0007, 0xa105, 0x78a6, 0x6016, 0x788a,
+ 0xa4a4, 0x000f, 0x8427, 0x8204, 0x8004, 0xa084, 0x00ff, 0xa405,
+ 0x600e, 0x78ec, 0xd08c, 0x00c0, 0x3651, 0x6004, 0xa084, 0xfff5,
+ 0x6006, 0x007c, 0x0c7e, 0x7054, 0x2060, 0x1078, 0x3659, 0x0c7f,
+ 0x007c, 0x6018, 0x789a, 0x78a4, 0xa084, 0xfff0, 0x78a6, 0x6012,
+ 0x7884, 0xa084, 0xfff0, 0x7886, 0x007c, 0xa282, 0x0002, 0x00c0,
+ 0x376b, 0x7aa8, 0x6920, 0xa18d, 0x0080, 0x6922, 0xa184, 0x0200,
+ 0x0040, 0x36ae, 0xa18c, 0xfdff, 0x6922, 0xa294, 0x00ff, 0xa282,
+ 0x0002, 0x00c8, 0x376b, 0x1078, 0x36f9, 0x1078, 0x3652, 0xa980,
+ 0x0001, 0x200c, 0x1078, 0x38b9, 0x1078, 0x35bb, 0x88ff, 0x0040,
+ 0x36a1, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xa6b5, 0x0004,
+ 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x369b, 0x782b, 0x3008, 0x781b,
+ 0x0056, 0x0078, 0x24fa, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078,
+ 0x24fa, 0x7e58, 0xa684, 0x0400, 0x00c0, 0x36aa, 0x781b, 0x0058,
+ 0x0078, 0x24fa, 0x781b, 0x0065, 0x0078, 0x24fa, 0xa282, 0x0002,
+ 0x00c8, 0x36b6, 0xa284, 0x0001, 0x0040, 0x36c0, 0x7154, 0xa188,
+ 0x0000, 0x210c, 0xa18c, 0x2000, 0x00c0, 0x36c0, 0x2011, 0x0000,
+ 0x1078, 0x37db, 0x1078, 0x36f9, 0x1078, 0x3652, 0x7858, 0xa085,
+ 0x0004, 0x785a, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x24fa,
+ 0x0c7e, 0x027e, 0x2960, 0x6000, 0x2011, 0x0001, 0xd0ec, 0x00c0,
+ 0x36e9, 0xd0bc, 0x00c0, 0x36e7, 0x6014, 0xa084, 0x0040, 0x00c0,
+ 0x36e7, 0xa18c, 0xffef, 0x6106, 0xa006, 0x0078, 0x36f6, 0x2011,
+ 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa,
+ 0xa8c0, 0x0004, 0x6820, 0xa085, 0x0200, 0x6822, 0x027f, 0x0c7f,
+ 0x007c, 0x0c7e, 0x7054, 0x2060, 0x1078, 0x3700, 0x0c7f, 0x007c,
+ 0x82ff, 0x0040, 0x3705, 0x2011, 0x0040, 0x6018, 0xa080, 0x0002,
+ 0x789a, 0x78a4, 0xa084, 0xffbf, 0xa205, 0x78a6, 0x788a, 0x6016,
+ 0x78ec, 0xd08c, 0x00c0, 0x3718, 0x6004, 0xa084, 0xffef, 0x6006,
+ 0x007c, 0x007e, 0x7000, 0xa086, 0x0003, 0x0040, 0x3722, 0x007f,
+ 0x0078, 0x3725, 0x007f, 0x0078, 0x3767, 0xa684, 0x0020, 0x0040,
+ 0x3767, 0x7888, 0xa084, 0x0040, 0x0040, 0x3767, 0x7bb8, 0xa384,
+ 0x003f, 0x831b, 0x00c8, 0x3735, 0x8000, 0xa005, 0x0040, 0x374b,
+ 0x831b, 0x00c8, 0x373e, 0x8001, 0x0040, 0x3763, 0xa684, 0x4000,
+ 0x0040, 0x374b, 0x78b8, 0x801b, 0x00c8, 0x3747, 0x8000, 0xa084,
+ 0x003f, 0x00c0, 0x3763, 0xa6b4, 0xbfff, 0x7e5a, 0x79d8, 0x7adc,
+ 0x2001, 0x0001, 0xa108, 0x00c8, 0x3757, 0xa291, 0x0000, 0x79d2,
+ 0x79da, 0x7ad6, 0x7ade, 0x1078, 0x4c41, 0x781b, 0x0064, 0x1078,
+ 0x4ac6, 0x0078, 0x24fa, 0x781b, 0x0064, 0x0078, 0x24fa, 0x781b,
+ 0x0065, 0x0078, 0x24fa, 0x1078, 0x37a3, 0x782b, 0x3008, 0x781b,
+ 0x0065, 0x0078, 0x24fa, 0x1078, 0x378f, 0x782b, 0x3008, 0x781b,
+ 0x0065, 0x0078, 0x24fa, 0x6827, 0x0002, 0x1078, 0x3797, 0x78e4,
+ 0xa084, 0x0030, 0x0040, 0x2523, 0x78ec, 0xa084, 0x0003, 0x0040,
+ 0x2523, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x24fa, 0x2001,
+ 0x0005, 0x0078, 0x37a5, 0x2001, 0x000c, 0x0078, 0x37a5, 0x2001,
+ 0x0006, 0x0078, 0x37a5, 0x2001, 0x000d, 0x0078, 0x37a5, 0x2001,
+ 0x0009, 0x0078, 0x37a5, 0x2001, 0x0007, 0x789b, 0x0010, 0x78aa,
+ 0x789b, 0x0060, 0x78ab, 0x0001, 0xa6b5, 0x0004, 0x7e5a, 0x007c,
+ 0x077e, 0x873f, 0xa7bc, 0x000f, 0x873b, 0x873b, 0x8703, 0xa0e0,
+ 0x5480, 0xa7b8, 0x0020, 0x7f9a, 0x79a4, 0xa184, 0x000f, 0x0040,
+ 0x37c9, 0xa184, 0xfff0, 0x78a6, 0x6012, 0x6004, 0xa085, 0x0008,
+ 0x6006, 0x8738, 0x8738, 0x7f9a, 0x79a4, 0xa184, 0x0040, 0x0040,
+ 0x37d9, 0xa184, 0xffbf, 0x78a6, 0x6016, 0x6004, 0xa085, 0x0010,
+ 0x6006, 0x077f, 0x007c, 0x789b, 0x0010, 0x78ab, 0x0001, 0x78ab,
+ 0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0060, 0x78ab, 0x0004,
+ 0x007c, 0x2021, 0x0000, 0x2029, 0x0032, 0x789b, 0x0010, 0x78ab,
+ 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa, 0x7caa, 0x789b,
+ 0x0060, 0x78ab, 0x0005, 0x007c, 0x157e, 0x8007, 0xa084, 0x00ff,
+ 0x8003, 0x8003, 0xa080, 0x0020, 0x789a, 0x79a4, 0xa18c, 0xfff0,
+ 0x2001, 0x5246, 0x2004, 0xa082, 0x0028, 0x0040, 0x3817, 0x2021,
+ 0x38a0, 0x2019, 0x0014, 0x20a9, 0x000c, 0x0078, 0x381d, 0x2021,
+ 0x38ac, 0x2019, 0x0019, 0x20a9, 0x000d, 0x2011, 0x0064, 0x2404,
+ 0xa084, 0xfff0, 0xa106, 0x0040, 0x382c, 0x8420, 0x2300, 0xa210,
+ 0x0070, 0x382c, 0x0078, 0x381f, 0x157f, 0x007c, 0x157e, 0x2009,
+ 0x5246, 0x210c, 0xa182, 0x0032, 0x0048, 0x3842, 0x0040, 0x3846,
+ 0x2009, 0x3892, 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011, 0x0032,
+ 0x0078, 0x3858, 0xa182, 0x0028, 0x0040, 0x3850, 0x2009, 0x38a0,
+ 0x2019, 0x0014, 0x20a9, 0x000c, 0x2011, 0x0064, 0x0078, 0x3858,
+ 0x2009, 0x38ac, 0x2019, 0x0019, 0x20a9, 0x000d, 0x2011, 0x0064,
+ 0x2200, 0xa502, 0x0040, 0x3868, 0x0048, 0x3868, 0x8108, 0x2300,
+ 0xa210, 0x0070, 0x3865, 0x0078, 0x3858, 0x157f, 0xa006, 0x007c,
+ 0x157f, 0xa582, 0x0064, 0x00c8, 0x3877, 0x7808, 0xa085, 0x0070,
+ 0x780a, 0x7044, 0xa085, 0x0070, 0x7046, 0x0078, 0x3877, 0x78ec,
+ 0xa084, 0x0300, 0x0040, 0x387f, 0x2104, 0x0078, 0x3890, 0x2104,
+ 0xa09e, 0x1102, 0x00c0, 0x3890, 0x2001, 0x04fd, 0x2004, 0xa082,
+ 0x0005, 0x0048, 0x388f, 0x2001, 0x1201, 0x0078, 0x3890, 0x2104,
+ 0xa005, 0x007c, 0x1102, 0x3002, 0x3202, 0x4203, 0x4403, 0x5404,
+ 0x5604, 0x6605, 0x6805, 0x7806, 0x7a06, 0x0c07, 0x0c07, 0x0e07,
+ 0x3202, 0x4202, 0x5202, 0x6202, 0x7202, 0x6605, 0x7605, 0x7805,
+ 0x7a05, 0x7c05, 0x7e05, 0x7f05, 0x2202, 0x3202, 0x4202, 0x5202,
+ 0x5404, 0x6404, 0x7404, 0x7604, 0x7804, 0x7a04, 0x7c04, 0x7e04,
+ 0x7f04, 0x789b, 0x0010, 0xa046, 0x007c, 0xa784, 0x0f00, 0x800b,
+ 0xa784, 0x001f, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xa0e0,
+ 0x5500, 0x007c, 0x79d8, 0x7adc, 0x78d0, 0x801b, 0x00c8, 0x38d1,
+ 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x007c, 0x0f7e,
+ 0x2079, 0x0100, 0x2009, 0x5240, 0x2091, 0x8000, 0x2104, 0x0079,
+ 0x38e1, 0x3917, 0x38eb, 0x38eb, 0x38eb, 0x38eb, 0x38eb, 0x38eb,
+ 0x391b, 0x1078, 0x248c, 0x784b, 0x0004, 0x7848, 0xa084, 0x0004,
+ 0x00c0, 0x38ed, 0x784b, 0x0008, 0x7848, 0xa084, 0x0008, 0x00c0,
+ 0x38f4, 0x68b4, 0xa085, 0x4000, 0x68b6, 0x7858, 0xa085, 0x4000,
+ 0x785a, 0x7830, 0xa084, 0x0080, 0x00c0, 0x3917, 0x0018, 0x3917,
+ 0x681c, 0xa084, 0x0020, 0x00c0, 0x3915, 0x0e7e, 0x2071, 0x5240,
+ 0x1078, 0x396a, 0x0e7f, 0x0078, 0x3917, 0x781b, 0x00ca, 0x2091,
+ 0x8001, 0x0f7f, 0x007c, 0x70b3, 0x0000, 0x1078, 0x3b44, 0x0078,
+ 0x3917, 0x0c7e, 0x6814, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003,
+ 0x8003, 0xa0e0, 0x5480, 0x6004, 0xa084, 0x000a, 0x00c0, 0x3954,
+ 0x6108, 0xa194, 0xff00, 0x0040, 0x3954, 0xa18c, 0x00ff, 0x2001,
+ 0x0019, 0xa106, 0x0040, 0x3943, 0x2001, 0x0032, 0xa106, 0x0040,
+ 0x3947, 0x0078, 0x394b, 0x2009, 0x0020, 0x0078, 0x394d, 0x2009,
+ 0x003f, 0x0078, 0x394d, 0x2011, 0x0000, 0x2100, 0xa205, 0x600a,
+ 0x6004, 0xa085, 0x0002, 0x6006, 0x0c7f, 0x007c, 0x781b, 0x0065,
+ 0x0078, 0x24fa, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x24fa,
+ 0x781b, 0x0058, 0x0078, 0x24fa, 0x782b, 0x3008, 0x781b, 0x0056,
+ 0x0078, 0x24fa, 0x2009, 0x5220, 0x210c, 0xa186, 0x0000, 0x0040,
+ 0x397e, 0xa186, 0x0001, 0x0040, 0x3981, 0x2009, 0x5238, 0x200b,
+ 0x000b, 0x706f, 0x0001, 0x781b, 0x0048, 0x007c, 0x781b, 0x00c4,
+ 0x007c, 0x2009, 0x5238, 0x200b, 0x000a, 0x007c, 0x2009, 0x5220,
+ 0x210c, 0xa186, 0x0000, 0x0040, 0x39a1, 0xa186, 0x0001, 0x0040,
+ 0x399b, 0x2009, 0x5238, 0x200b, 0x000b, 0x706f, 0x0001, 0x781b,
+ 0x0048, 0x0078, 0x24fa, 0x2009, 0x5238, 0x200b, 0x000a, 0x0078,
+ 0x24fa, 0x782b, 0x3008, 0x781b, 0x00c4, 0x0078, 0x24fa, 0x781b,
+ 0x00ca, 0x0078, 0x24fa, 0x782b, 0x3008, 0x781b, 0x00ca, 0x0078,
+ 0x24fa, 0x781b, 0x008f, 0x0078, 0x24fa, 0x782b, 0x3008, 0x781b,
+ 0x008f, 0x0078, 0x24fa, 0x6818, 0xa084, 0x8000, 0x0040, 0x39c2,
+ 0x681b, 0x001d, 0x706f, 0x0001, 0x781b, 0x0048, 0x0078, 0x24fa,
+ 0x007e, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x39de, 0x7808, 0xa084,
+ 0xfffc, 0x780a, 0x0005, 0x0005, 0x0005, 0x0005, 0x78ec, 0xa084,
+ 0x0021, 0x0040, 0x39de, 0x7044, 0x780a, 0xa005, 0x007f, 0x007c,
+ 0x7044, 0xa085, 0x0002, 0x7046, 0x780a, 0x007c, 0x007e, 0x7830,
+ 0xa084, 0x0040, 0x00c0, 0x39e7, 0x0098, 0x39f2, 0x007f, 0x789a,
+ 0x78ac, 0x007c, 0x7808, 0xa084, 0xfffd, 0x780a, 0x0005, 0x0005,
+ 0x0005, 0x0005, 0x78ec, 0xa084, 0x0021, 0x0040, 0x3a01, 0x0098,
+ 0x39ff, 0x007f, 0x789a, 0x78ac, 0x007e, 0x7044, 0x780a, 0x007f,
+ 0x007c, 0x78ec, 0xa084, 0x0002, 0x00c0, 0x4871, 0xa784, 0x007d,
+ 0x00c0, 0x3a15, 0x2700, 0x1078, 0x248c, 0xa784, 0x0001, 0x00c0,
+ 0x300c, 0xa784, 0x0070, 0x0040, 0x3a25, 0x0c7e, 0x2d60, 0x2f68,
+ 0x1078, 0x2437, 0x2d78, 0x2c68, 0x0c7f, 0xa784, 0x0008, 0x0040,
+ 0x3a32, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x2523,
+ 0x0078, 0x3956, 0xa784, 0x0004, 0x0040, 0x3a65, 0x78b8, 0xa084,
+ 0x4001, 0x0040, 0x3a65, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003,
+ 0x0040, 0x2523, 0x78e4, 0xa084, 0x0007, 0xa086, 0x0001, 0x00c0,
+ 0x3a65, 0x78c0, 0xa085, 0x4800, 0x2030, 0x7e5a, 0x781b, 0x00ca,
+ 0x0078, 0x24fa, 0x784b, 0x0008, 0x6818, 0xa084, 0x8000, 0x0040,
+ 0x3a61, 0x681b, 0x0015, 0xa684, 0x4000, 0x0040, 0x3a61, 0x681b,
+ 0x0007, 0x1078, 0x396a, 0x0078, 0x24fa, 0x681b, 0x0003, 0x7858,
+ 0xa084, 0x3f00, 0x681e, 0x682f, 0x0000, 0x6833, 0x0000, 0x784b,
+ 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x2a06, 0x0018, 0x24fa,
+ 0x0078, 0x3773, 0x6b14, 0x8307, 0xa084, 0x000f, 0x8003, 0x8003,
+ 0x8003, 0xa080, 0x5480, 0x2060, 0x2048, 0x7056, 0x6000, 0x705a,
+ 0x6004, 0x705e, 0x2a60, 0x007c, 0x0079, 0x3a8e, 0x3a96, 0x3a97,
+ 0x3a96, 0x3a99, 0x3a96, 0x3a96, 0x3a96, 0x3a9e, 0x007c, 0x1078,
+ 0x34b8, 0x1078, 0x4887, 0x7038, 0x600a, 0x007c, 0x70a0, 0xa005,
+ 0x0040, 0x3aab, 0x2068, 0x1078, 0x1bd3, 0x1078, 0x47fe, 0x1078,
+ 0x4805, 0x70a3, 0x0000, 0x007c, 0x0e7e, 0x2091, 0x8000, 0x2071,
+ 0x5240, 0x7000, 0xa086, 0x0007, 0x00c0, 0x3ac2, 0x6110, 0x70bc,
+ 0xa106, 0x00c0, 0x3ac2, 0x0e7f, 0x1078, 0x1be0, 0x1078, 0x3ac8,
+ 0xa006, 0x007c, 0x2091, 0x8001, 0x0e7f, 0xa085, 0x0001, 0x007c,
+ 0x0f7e, 0x0e7e, 0x2071, 0x5240, 0x0078, 0x2297, 0x785b, 0x0000,
+ 0x70af, 0x000e, 0x2009, 0x0100, 0x017e, 0x70a0, 0xa06d, 0x0040,
+ 0x3add, 0x70a3, 0x0000, 0x0078, 0x3ae3, 0x70b3, 0x0000, 0x1078,
+ 0x1c0c, 0x0040, 0x3ae9, 0x70ac, 0x6826, 0x1078, 0x3bc6, 0x0078,
+ 0x3add, 0x017f, 0x157e, 0x0c7e, 0x0d7e, 0x20a9, 0x0008, 0x2061,
+ 0x7610, 0x6000, 0xa105, 0x6002, 0x601c, 0xa06d, 0x0040, 0x3b01,
+ 0x6800, 0x601e, 0x1078, 0x19ac, 0x6008, 0x8000, 0x600a, 0x0078,
+ 0x3af4, 0x6018, 0xa06d, 0x0040, 0x3b0b, 0x6800, 0x601a, 0x1078,
+ 0x19ac, 0x0078, 0x3b01, 0xace0, 0x0008, 0x0070, 0x3b11, 0x0078,
+ 0x3af1, 0x709c, 0xa084, 0x8000, 0x0040, 0x3b18, 0x1078, 0x3c44,
+ 0x0d7f, 0x0c7f, 0x157f, 0x007c, 0x127e, 0x2091, 0x2300, 0x6804,
+ 0xa084, 0x000f, 0x0079, 0x3b24, 0x3b34, 0x3b34, 0x3b34, 0x3b34,
+ 0x3b34, 0x3b34, 0x3b36, 0x3b3c, 0x3b34, 0x3b34, 0x3b34, 0x3b34,
+ 0x3b34, 0x3b3e, 0x3b34, 0x3b36, 0x1078, 0x248c, 0x1078, 0x45d3,
+ 0x1078, 0x19ac, 0x0078, 0x3b42, 0x6827, 0x000b, 0x1078, 0x45d3,
+ 0x1078, 0x3bc6, 0x127f, 0x007c, 0x127e, 0x2091, 0x2300, 0x0098,
+ 0x3b60, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x3b60, 0x0d7e, 0x1078,
+ 0x4812, 0x2d00, 0x682e, 0x2009, 0x0004, 0x2001, 0x0000, 0x6827,
+ 0x0084, 0x1078, 0x47c7, 0x1078, 0x3bc6, 0x0d7f, 0x0078, 0x3b94,
+ 0x7948, 0xa185, 0x4000, 0x784a, 0x0098, 0x3b69, 0x794a, 0x0078,
+ 0x3b4e, 0x7828, 0xa086, 0x1834, 0x00c0, 0x3b72, 0xa185, 0x0004,
+ 0x0078, 0x3b79, 0x7828, 0xa086, 0x1814, 0x00c0, 0x3b66, 0xa185,
+ 0x000c, 0x784a, 0x789b, 0x000e, 0x78ab, 0x0002, 0x7858, 0xa084,
+ 0x00ff, 0xa085, 0x0400, 0x785a, 0x70b4, 0xa080, 0x0091, 0x781a,
+ 0x6827, 0x0284, 0x682c, 0x6836, 0x6830, 0x683a, 0x2009, 0x0004,
+ 0x2001, 0x0000, 0x1078, 0x47c7, 0x127f, 0x007c, 0x0d7e, 0x6b14,
+ 0x1078, 0x1c70, 0x0040, 0x3ba3, 0x2068, 0x6827, 0x0002, 0x1078,
+ 0x3bc6, 0x0078, 0x3b98, 0x0d7f, 0x007c, 0x0d7e, 0x6b14, 0x6c28,
+ 0xa4a4, 0x00ff, 0x1078, 0x1c1c, 0x0040, 0x3bb3, 0x2068, 0x6827,
+ 0x0002, 0x1078, 0x3bc6, 0x0d7f, 0x007c, 0x0d7e, 0x6b14, 0xa39c,
+ 0x00ff, 0x1078, 0x1c48, 0x0040, 0x3bc4, 0x2068, 0x6827, 0x0002,
+ 0x1078, 0x3bc6, 0x0078, 0x3bb9, 0x0d7f, 0x007c, 0x0c7e, 0x6914,
+ 0x1078, 0x3c3b, 0x6904, 0xa18c, 0x00ff, 0xa186, 0x0006, 0x0040,
+ 0x3be1, 0xa186, 0x000d, 0x0040, 0x3c00, 0xa186, 0x0017, 0x00c0,
+ 0x3bdd, 0x1078, 0x19ac, 0x0078, 0x3bdf, 0x1078, 0x1cde, 0x0c7f,
+ 0x007c, 0x6004, 0x8001, 0x0048, 0x3bfe, 0x6006, 0x2009, 0x0000,
+ 0xa684, 0x0001, 0x00c0, 0x3bee, 0xa18d, 0x8000, 0xa684, 0x0004,
+ 0x0040, 0x3bf4, 0xa18d, 0x0002, 0x691e, 0x6823, 0x0000, 0x7104,
+ 0x810f, 0x6818, 0xa105, 0x681a, 0x0078, 0x3bdd, 0x1078, 0x248c,
+ 0x6018, 0xa005, 0x00c0, 0x3c0f, 0x6008, 0x8001, 0x0048, 0x3c0f,
+ 0x600a, 0x601c, 0x6802, 0x2d00, 0x601e, 0x0078, 0x3c25, 0xac88,
+ 0x0006, 0x2104, 0xa005, 0x0040, 0x3c18, 0x2008, 0x0078, 0x3c11,
+ 0x6802, 0x2d0a, 0x6008, 0x8001, 0x0048, 0x3bdf, 0x600a, 0x6018,
+ 0x2068, 0x6800, 0x601a, 0x0078, 0x3c09, 0x157e, 0x137e, 0x147e,
+ 0x0c7e, 0x0d7e, 0x1078, 0x1989, 0x00c0, 0x3c30, 0x1078, 0x248c,
+ 0x2da0, 0x137f, 0x20a9, 0x0031, 0x53a3, 0x0c7f, 0x147f, 0x137f,
+ 0x157f, 0x0078, 0x3bdd, 0xa184, 0x001f, 0x8003, 0x8003, 0x8003,
+ 0xa080, 0x7610, 0x2060, 0x007c, 0x2019, 0x5251, 0x2304, 0xa085,
+ 0x0001, 0x201a, 0x2019, 0x0102, 0x2304, 0xa085, 0x0001, 0x201a,
+ 0x007c, 0x2019, 0x5251, 0x2304, 0xa084, 0xfffe, 0x201a, 0x2019,
+ 0x0102, 0x2304, 0xa084, 0xfffe, 0x201a, 0x007c, 0x7990, 0xa18c,
+ 0xfff8, 0x7992, 0x70b4, 0xa080, 0x00d8, 0x781a, 0x0078, 0x24fa,
+ 0x70a3, 0x0000, 0x7003, 0x0000, 0x7043, 0x0001, 0x7037, 0x0000,
+ 0x0018, 0x24b1, 0x1078, 0x1c0c, 0x0040, 0x3c99, 0x2009, 0x520f,
+ 0x200b, 0x0000, 0x68bc, 0x2060, 0x6100, 0xa184, 0x0300, 0x0040,
+ 0x3c8d, 0x6827, 0x000e, 0xa084, 0x0200, 0x0040, 0x3c89, 0x6827,
+ 0x0017, 0x1078, 0x3bc6, 0x0078, 0x3c68, 0x7000, 0xa086, 0x0007,
+ 0x00c0, 0x3d0d, 0x2d00, 0x70a2, 0xad80, 0x000f, 0x7036, 0x0078,
+ 0x3ca0, 0x7040, 0xa086, 0x0001, 0x0040, 0x2533, 0x0078, 0x24fa,
+ 0x2031, 0x0000, 0x691c, 0xa184, 0x0002, 0x0040, 0x3ca9, 0xa6b5,
+ 0x0004, 0xa184, 0x00c0, 0x8003, 0x8003, 0x8007, 0xa080, 0x3da6,
+ 0x2004, 0xa635, 0x6820, 0xa084, 0x0400, 0x0040, 0x3cc1, 0x789b,
+ 0x0018, 0x78ab, 0x0003, 0x789b, 0x0081, 0x78ab, 0x0001, 0xa6b5,
+ 0x5000, 0x6820, 0xa084, 0x8000, 0x0040, 0x3ccf, 0xa6b5, 0x0400,
+ 0x789b, 0x000e, 0x6824, 0x8007, 0x78aa, 0x0078, 0x3cef, 0x681c,
+ 0xd0fc, 0x00c0, 0x3cdd, 0xa6b5, 0x0800, 0x6820, 0xd0c4, 0x0040,
+ 0x3cef, 0xa6b5, 0x4000, 0x0078, 0x3cef, 0x6820, 0xd0c4, 0x0040,
+ 0x3ce5, 0xa6b5, 0x4000, 0x0078, 0x3cef, 0x789b, 0x0018, 0x78ab,
+ 0x0002, 0x789b, 0x0081, 0x78ab, 0x0001, 0xa6b5, 0x1000, 0xa684,
+ 0x0200, 0x0040, 0x3d09, 0x682c, 0x78d2, 0x6830, 0x78d6, 0xa684,
+ 0x0100, 0x0040, 0x3d07, 0x682c, 0xa084, 0x0001, 0x0040, 0x3d07,
+ 0x7888, 0xa084, 0x0040, 0x0040, 0x3d07, 0xa6b5, 0x8000, 0x1078,
+ 0x47f6, 0x7e5a, 0x6eb6, 0x0078, 0x4835, 0x1078, 0x39c8, 0x00c0,
+ 0x3da0, 0x702c, 0x8004, 0x0048, 0x3d1b, 0x2019, 0x4f49, 0x1078,
+ 0x2313, 0x702f, 0x0001, 0x2041, 0x0001, 0x2031, 0x1000, 0x789b,
+ 0x0018, 0x6814, 0xa084, 0x001f, 0xa085, 0x0080, 0x78aa, 0x691c,
+ 0xa184, 0x0002, 0x0040, 0x3d34, 0xa6b5, 0x0004, 0x78ab, 0x0020,
+ 0x6828, 0x78aa, 0xa8c0, 0x0002, 0x681c, 0xd0f4, 0x0040, 0x3d3d,
+ 0x2c50, 0x1078, 0x3a7a, 0x1078, 0x4702, 0x6820, 0xa084, 0x8000,
+ 0x0040, 0x3d4b, 0xa6b5, 0x0400, 0x789b, 0x000e, 0x6824, 0x8007,
+ 0x78aa, 0x0078, 0x3d52, 0x681c, 0xa084, 0x8000, 0x00c0, 0x3d52,
+ 0xa6b5, 0x0800, 0x6820, 0xa084, 0x0100, 0x0040, 0x3d59, 0xa6b5,
+ 0x4000, 0x681c, 0xa084, 0x00c0, 0x8003, 0x8003, 0x8007, 0xa080,
+ 0x3da6, 0x2004, 0xa635, 0xa684, 0x0100, 0x0040, 0x3d73, 0x682c,
+ 0xa084, 0x0001, 0x0040, 0x3d73, 0x7888, 0xa084, 0x0040, 0x0040,
+ 0x3d73, 0xa6b5, 0x8000, 0x789b, 0x007e, 0x7eae, 0x6eb6, 0x6814,
+ 0x8007, 0x78aa, 0x7882, 0x2810, 0x7aaa, 0x7830, 0xa084, 0x00c0,
+ 0x00c0, 0x3da0, 0x0018, 0x3da0, 0x70b4, 0xa080, 0x00dd, 0x781a,
+ 0x1078, 0x39e0, 0xa684, 0x0200, 0x0040, 0x3d94, 0x682c, 0x78d2,
+ 0x6830, 0x78d6, 0x1078, 0x47f6, 0x2d00, 0x70a2, 0x704a, 0x6810,
+ 0x70be, 0x7003, 0x0007, 0xad80, 0x000f, 0x7036, 0x0078, 0x24fa,
+ 0x1078, 0x1bd3, 0x1078, 0x39e0, 0x0078, 0x24fa, 0x0000, 0x0300,
+ 0x0200, 0x0000, 0x1078, 0x248c, 0x2300, 0x0079, 0x3daf, 0x3db2,
+ 0x3db2, 0x3db4, 0x1078, 0x248c, 0x1078, 0x4805, 0x6924, 0xa184,
+ 0x00ff, 0xa086, 0x000a, 0x0040, 0x3dc6, 0xa184, 0xff00, 0xa085,
+ 0x000a, 0x6826, 0x1078, 0x1bd3, 0x0078, 0x3c68, 0x2001, 0x000a,
+ 0x1078, 0x4797, 0x0078, 0x3c68, 0xa282, 0x0005, 0x0050, 0x3dd2,
+ 0x1078, 0x248c, 0x7000, 0xa084, 0x0007, 0x10c0, 0x3a8c, 0x1078,
+ 0x1989, 0x00c0, 0x3df4, 0x2069, 0xffff, 0xa684, 0x0004, 0x0040,
+ 0x3de5, 0x2001, 0x2800, 0x0078, 0x3de7, 0x2001, 0x0800, 0x71b4,
+ 0xa188, 0x0091, 0x789b, 0x000e, 0x8007, 0x78aa, 0x2031, 0x0400,
+ 0x7e5a, 0x791a, 0x0078, 0x24fa, 0x6807, 0x0106, 0x680b, 0x0000,
+ 0x689f, 0x0000, 0x6827, 0x0000, 0xa386, 0x0002, 0x00c0, 0x3e15,
+ 0xa286, 0x0002, 0x00c0, 0x3e15, 0x78a0, 0xa005, 0x00c0, 0x3e15,
+ 0xa484, 0x8000, 0x00c0, 0x3e15, 0x78e4, 0xa084, 0x0008, 0x0040,
+ 0x3e15, 0xa6b5, 0x0008, 0x2019, 0x0000, 0x1078, 0x4217, 0x2d00,
+ 0x70a2, 0x704a, 0x7003, 0x0007, 0x7037, 0x0000, 0x6824, 0xa084,
+ 0x0080, 0x0040, 0x3e27, 0x1078, 0x42cd, 0x0078, 0x24fa, 0x2300,
+ 0x0079, 0x3e2a, 0x3e2d, 0x3eae, 0x3ec7, 0x2200, 0x0079, 0x3e30,
+ 0x3e35, 0x3e45, 0x3e6b, 0x3e77, 0x3e9a, 0x2029, 0x0001, 0xa026,
+ 0x2011, 0x0000, 0x1078, 0x43f3, 0x0079, 0x3e3e, 0x3e43, 0x24fa,
+ 0x3c68, 0x3e43, 0x3e43, 0x1078, 0x248c, 0x7990, 0xa18c, 0x0007,
+ 0x00c0, 0x3e4c, 0x2009, 0x0008, 0x2011, 0x0001, 0xa684, 0x0004,
+ 0x0040, 0x3e54, 0x2011, 0x0003, 0x2220, 0xa12a, 0x2011, 0x0001,
+ 0x1078, 0x43f3, 0x0079, 0x3e5c, 0x3e61, 0x24fa, 0x3c68, 0x3e69,
+ 0x3e63, 0x0078, 0x483b, 0x70ab, 0x3e67, 0x0078, 0x24fa, 0x0078,
+ 0x3e61, 0x1078, 0x248c, 0xa684, 0x0010, 0x0040, 0x3e75, 0x1078,
+ 0x429c, 0x0040, 0x3e75, 0x0078, 0x24fa, 0x0078, 0x430d, 0x6000,
+ 0xa084, 0x0002, 0x0040, 0x3e94, 0x70b4, 0xa080, 0x00cd, 0x781a,
+ 0x0d7e, 0x1078, 0x4812, 0x2d00, 0x682e, 0x6827, 0x0000, 0x1078,
+ 0x3bc6, 0x0d7f, 0x1078, 0x19ac, 0x7003, 0x0000, 0x7037, 0x0000,
+ 0x704b, 0x0000, 0x0078, 0x3c68, 0xa684, 0x0004, 0x00c0, 0x3e9a,
+ 0x0078, 0x483b, 0x6000, 0xa084, 0x0004, 0x00c0, 0x3eac, 0x6000,
+ 0xa084, 0x0001, 0x0040, 0x3eac, 0x70ab, 0x3eac, 0x2001, 0x0007,
+ 0x1078, 0x478f, 0x0078, 0x4841, 0x0078, 0x483b, 0x2200, 0x0079,
+ 0x3eb1, 0x3eb6, 0x3eb8, 0x3eb6, 0x3eb6, 0x3eb6, 0x1078, 0x248c,
+ 0x70a7, 0x3ebc, 0x0078, 0x4847, 0x78e4, 0xa084, 0x0008, 0x00c0,
+ 0x3eb8, 0x1078, 0x4781, 0x70ab, 0x3ec5, 0x0078, 0x483b, 0x2200,
+ 0x0079, 0x3eca, 0x3ecf, 0x3ed1, 0x3ed1, 0x3ecf, 0x3ecf, 0x1078,
+ 0x248c, 0x78e4, 0xa084, 0x0008, 0x0040, 0x3ee6, 0x70a7, 0x3eda,
+ 0x0078, 0x4847, 0x2011, 0x0004, 0x1078, 0x43ed, 0x0079, 0x3ee0,
+ 0x3ee6, 0x24fa, 0x3c68, 0x3ee6, 0x3ef0, 0x3ef4, 0x70ab, 0x3eee,
+ 0x2001, 0x0003, 0x1078, 0x478f, 0x0078, 0x4841, 0x0078, 0x483b,
+ 0x70ab, 0x3ee6, 0x0078, 0x24fa, 0x70ab, 0x3ef8, 0x0078, 0x24fa,
+ 0x0078, 0x3eee, 0xa282, 0x0003, 0x0050, 0x3f00, 0x1078, 0x248c,
+ 0xa386, 0x0002, 0x00c0, 0x3f19, 0xa286, 0x0002, 0x00c0, 0x3f1f,
+ 0x78a0, 0xa005, 0x00c0, 0x3f1f, 0xa484, 0x8000, 0x00c0, 0x3f1f,
+ 0x78e4, 0xa084, 0x0008, 0x0040, 0x3f19, 0xa6b5, 0x0008, 0x2019,
+ 0x0000, 0xa684, 0x0008, 0x0040, 0x3f1f, 0x1078, 0x4279, 0x6810,
+ 0x70be, 0x7003, 0x0007, 0x2300, 0x0079, 0x3f26, 0x3f29, 0x3f56,
+ 0x3f5e, 0x2200, 0x0079, 0x3f2c, 0x3f31, 0x3f2f, 0x3f4a, 0x1078,
+ 0x248c, 0x7990, 0xa1ac, 0x0007, 0xa026, 0x2011, 0x0001, 0x1078,
+ 0x43f3, 0x0079, 0x3f3b, 0x3f40, 0x24fa, 0x3c68, 0x3f48, 0x3f42,
+ 0x0078, 0x483b, 0x70ab, 0x3f46, 0x0078, 0x24fa, 0x0078, 0x3f40,
+ 0x1078, 0x248c, 0xa684, 0x0010, 0x0040, 0x3f54, 0x1078, 0x429c,
+ 0x0040, 0x3f54, 0x0078, 0x24fa, 0x0078, 0x430d, 0x2200, 0x0079,
+ 0x3f59, 0x3f5c, 0x3f5c, 0x3f5c, 0x1078, 0x248c, 0x2200, 0x0079,
+ 0x3f61, 0x3f64, 0x3f66, 0x3f66, 0x1078, 0x248c, 0x78e4, 0xa084,
+ 0x0008, 0x0040, 0x3f7b, 0x70a7, 0x3f6f, 0x0078, 0x4847, 0x2011,
+ 0x0004, 0x1078, 0x43ed, 0x0079, 0x3f75, 0x3f7b, 0x24fa, 0x3c68,
+ 0x3f7b, 0x3f85, 0x3f89, 0x70ab, 0x3f83, 0x2001, 0x0003, 0x1078,
+ 0x478f, 0x0078, 0x4841, 0x0078, 0x483b, 0x70ab, 0x3f7b, 0x0078,
+ 0x24fa, 0x70ab, 0x3f8d, 0x0078, 0x24fa, 0x0078, 0x3f83, 0x2300,
+ 0x0079, 0x3f92, 0x3f97, 0x3f99, 0x3f95, 0x1078, 0x248c, 0x70a4,
+ 0x007a, 0x70a4, 0x007a, 0xa282, 0x0002, 0x0050, 0x3fa1, 0x1078,
+ 0x248c, 0xa684, 0x0200, 0x0040, 0x3fab, 0x1078, 0x47fe, 0x1078,
+ 0x43d5, 0x1078, 0x4805, 0x2300, 0x0079, 0x3fae, 0x3fb1, 0x3fd9,
+ 0x403f, 0xad86, 0xffff, 0x0040, 0x3c68, 0xa286, 0x0001, 0x0040,
+ 0x3fbb, 0x1078, 0x248c, 0xa684, 0x0200, 0x0040, 0x3fc3, 0x1078,
+ 0x47fe, 0x1078, 0x4805, 0x2001, 0x0001, 0x1078, 0x4797, 0x78b8,
+ 0xa084, 0xc001, 0x0040, 0x3fd5, 0x7848, 0xa085, 0x0008, 0x784a,
+ 0x7848, 0xa084, 0x0008, 0x00c0, 0x3fd0, 0x7003, 0x0000, 0x0078,
+ 0x3c68, 0x2200, 0x0079, 0x3fdc, 0x3fde, 0x400f, 0x70a7, 0x3fe2,
+ 0x0078, 0x4847, 0x2011, 0x000d, 0x1078, 0x43ed, 0x0079, 0x3fe8,
+ 0x3fef, 0x24fa, 0x3c68, 0x3ff7, 0x3fff, 0x4005, 0x4007, 0xa6b4,
+ 0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a, 0x0078, 0x4835, 0xa6b4,
+ 0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a, 0x0078, 0x4835, 0x70ab,
+ 0x4003, 0x0078, 0x24fa, 0x0078, 0x3fef, 0x1078, 0x248c, 0x70ab,
+ 0x400b, 0x0078, 0x24fa, 0x1078, 0x484d, 0x0078, 0x24fa, 0x70a7,
+ 0x4013, 0x0078, 0x4847, 0x2011, 0x0012, 0x1078, 0x43ed, 0x0079,
+ 0x4019, 0x401f, 0x24fa, 0x3c68, 0x402b, 0x4033, 0x4039, 0xa6b4,
+ 0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a, 0x70b4, 0xa080, 0x00aa,
+ 0x781a, 0x0078, 0x24fa, 0xa6b4, 0x00ff, 0xa6b5, 0x0400, 0x6eb6,
+ 0x7e5a, 0x0078, 0x4835, 0x70ab, 0x4037, 0x0078, 0x24fa, 0x0078,
+ 0x401f, 0x70ab, 0x403d, 0x0078, 0x24fa, 0x0078, 0x402b, 0xa286,
+ 0x0001, 0x0040, 0x4045, 0x1078, 0x248c, 0x70a7, 0x4049, 0x0078,
+ 0x4847, 0x2011, 0x0015, 0x1078, 0x43ed, 0x0079, 0x404f, 0x4054,
+ 0x24fa, 0x3c68, 0x4062, 0x406e, 0xa6b4, 0x00ff, 0xa6b5, 0x0400,
+ 0x6eb6, 0x7e5a, 0x783b, 0x1301, 0x70b4, 0xa080, 0x00b5, 0x781a,
+ 0x0078, 0x24fa, 0xa6b4, 0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a,
+ 0x70b4, 0xa080, 0x00aa, 0x781a, 0x0078, 0x24fa, 0x70ab, 0x4072,
+ 0x0078, 0x24fa, 0x0078, 0x4054, 0xa282, 0x0003, 0x0050, 0x407a,
+ 0x1078, 0x248c, 0x2300, 0x0079, 0x407d, 0x4080, 0x40b7, 0x4114,
+ 0xa286, 0x0001, 0x0040, 0x4086, 0x1078, 0x248c, 0x6804, 0xa084,
+ 0x00ff, 0xa086, 0x0006, 0x00c0, 0x4093, 0x1078, 0x3bc6, 0x7003,
+ 0x0000, 0x0078, 0x3c68, 0x683b, 0x0000, 0x6837, 0x0000, 0xa684,
+ 0x0200, 0x0040, 0x40a1, 0x1078, 0x47fe, 0x1078, 0x43d5, 0x1078,
+ 0x4805, 0x2001, 0x0001, 0x1078, 0x4797, 0x78b8, 0xa084, 0xc001,
+ 0x0040, 0x40b3, 0x7848, 0xa085, 0x0008, 0x784a, 0x7848, 0xa084,
+ 0x0008, 0x00c0, 0x40ae, 0x7003, 0x0000, 0x0078, 0x3c68, 0x2200,
+ 0x0079, 0x40ba, 0x40bc, 0x40ef, 0x70a7, 0x40c0, 0x0078, 0x4847,
+ 0x2011, 0x000d, 0x1078, 0x43ed, 0x0079, 0x40c6, 0x40cd, 0x24fa,
+ 0x3c68, 0x40d5, 0x40dd, 0x40e3, 0x40e5, 0xa6b4, 0x00ff, 0xa6b5,
+ 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x4835, 0xa6b4, 0x00ff, 0xa6b5,
+ 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x4835, 0x70ab, 0x40e1, 0x0078,
+ 0x24fa, 0x0078, 0x40cd, 0x1078, 0x248c, 0x70ab, 0x40eb, 0x1078,
+ 0x4805, 0x0078, 0x24fa, 0x1078, 0x484d, 0x0078, 0x24fa, 0x70a7,
+ 0x40f3, 0x0078, 0x4847, 0x2011, 0x0005, 0x1078, 0x43ed, 0x0079,
+ 0x40f9, 0x40fe, 0x24fa, 0x3c68, 0x4106, 0x410e, 0xa6b4, 0x00ff,
+ 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x4835, 0xa6b4, 0x00ff,
+ 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x4835, 0x70ab, 0x4112,
+ 0x0078, 0x24fa, 0x0078, 0x40fe, 0xa286, 0x0001, 0x0040, 0x411a,
+ 0x1078, 0x248c, 0x70a7, 0x411e, 0x0078, 0x4847, 0x2011, 0x0006,
+ 0x1078, 0x43ed, 0x0079, 0x4124, 0x4129, 0x24fa, 0x3c68, 0x412f,
+ 0x4139, 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x4835, 0xa6b4,
+ 0x00ff, 0xa6b5, 0x0800, 0x6eb6, 0xa6b5, 0x4000, 0x7e5a, 0x0078,
+ 0x4835, 0x70ab, 0x413d, 0x0078, 0x24fa, 0x0078, 0x4129, 0x2300,
+ 0x0079, 0x4142, 0x4147, 0x4145, 0x4145, 0x1078, 0x248c, 0x1078,
+ 0x248c, 0x2300, 0x71a8, 0xa005, 0x017a, 0x6810, 0x70be, 0xa282,
+ 0x0003, 0x0050, 0x4155, 0x1078, 0x248c, 0x2300, 0x0079, 0x4158,
+ 0x415b, 0x4169, 0x418b, 0xa684, 0x0200, 0x0040, 0x4163, 0x1078,
+ 0x47fe, 0x1078, 0x4805, 0x2001, 0x0001, 0x1078, 0x4797, 0x0078,
+ 0x24fa, 0xa296, 0x0002, 0x0040, 0x4172, 0x82ff, 0x0040, 0x4172,
+ 0x1078, 0x248c, 0x70a7, 0x4176, 0x0078, 0x4847, 0x2011, 0x0018,
+ 0x1078, 0x43ed, 0x0079, 0x417c, 0x4181, 0x24fa, 0x3c68, 0x4183,
+ 0x4185, 0x0078, 0x4835, 0x0078, 0x4835, 0x70ab, 0x4189, 0x0078,
+ 0x24fa, 0x0078, 0x4181, 0x2200, 0x0079, 0x418e, 0x4190, 0x41a9,
+ 0x70a7, 0x4194, 0x0078, 0x4847, 0x2011, 0x0017, 0x1078, 0x43ed,
+ 0x0079, 0x419a, 0x419f, 0x24fa, 0x3c68, 0x41a1, 0x41a3, 0x0078,
+ 0x4835, 0x0078, 0x4835, 0x70ab, 0x41a7, 0x0078, 0x24fa, 0x0078,
+ 0x419f, 0xa484, 0x8000, 0x00c0, 0x4205, 0xa684, 0x0100, 0x0040,
+ 0x41b5, 0x1078, 0x47fe, 0x1078, 0x43d5, 0x78d8, 0x78d2, 0x78dc,
+ 0x78d6, 0xa6b4, 0xefff, 0x7e5a, 0x70a7, 0x41c0, 0x0078, 0x4847,
+ 0x2011, 0x000d, 0x1078, 0x43ed, 0x0079, 0x41c6, 0x41cd, 0x24fa,
+ 0x3c68, 0x41cd, 0x41f3, 0x41f9, 0x41fb, 0x78d8, 0x79dc, 0xa105,
+ 0x00c0, 0x41df, 0x78b8, 0xa084, 0x001f, 0x00c0, 0x41df, 0x70b3,
+ 0x0000, 0x7858, 0xa084, 0xfdff, 0x785a, 0x0078, 0x4835, 0xa684,
+ 0x0100, 0x0040, 0x41f1, 0x7848, 0xa085, 0x0008, 0x784a, 0x1078,
+ 0x47bc, 0x682c, 0x78d2, 0x6830, 0x78d6, 0x70b3, 0x0000, 0x1078,
+ 0x47f6, 0x0078, 0x4835, 0x70ab, 0x41f7, 0x0078, 0x24fa, 0x0078,
+ 0x41cd, 0x1078, 0x248c, 0x70ab, 0x4201, 0x1078, 0x4805, 0x0078,
+ 0x24fa, 0x1078, 0x484d, 0x0078, 0x24fa, 0x1078, 0x4805, 0x70ab,
+ 0x420f, 0x2001, 0x0003, 0x1078, 0x478f, 0x0078, 0x4841, 0x1078,
+ 0x47f6, 0x682c, 0x78d2, 0x6830, 0x78d6, 0x0078, 0x4835, 0x70b8,
+ 0x6812, 0x70be, 0x8000, 0x70ba, 0x681b, 0x0000, 0xa684, 0x0008,
+ 0x0040, 0x423a, 0x157e, 0x137e, 0x147e, 0x7890, 0x8004, 0x8004,
+ 0x8004, 0x8004, 0xa084, 0x000f, 0x681a, 0x80ac, 0x789b, 0x0000,
+ 0xaf80, 0x002b, 0x2098, 0xad80, 0x000b, 0x20a0, 0x53a5, 0x147f,
+ 0x137f, 0x157f, 0xa6c4, 0x0f00, 0xa684, 0x0002, 0x00c0, 0x4249,
+ 0x692c, 0x810d, 0x810d, 0x810d, 0xa184, 0x0007, 0x2008, 0x0078,
+ 0x425c, 0x789b, 0x0010, 0x79ac, 0xa184, 0x0020, 0x0040, 0x425c,
+ 0x017e, 0x2009, 0x0005, 0x2001, 0x3d00, 0x1078, 0x47c7, 0x6824,
+ 0xa085, 0x003b, 0x6826, 0x017f, 0xa184, 0x001f, 0xa805, 0x6816,
+ 0x1078, 0x3c3b, 0x68be, 0xa684, 0x0004, 0x0040, 0x426d, 0xa18c,
+ 0xff00, 0x78a8, 0xa084, 0x00ff, 0xa105, 0x682a, 0xa6b4, 0x00ff,
+ 0x6000, 0xa084, 0x0008, 0x0040, 0x4277, 0xa6b5, 0x4000, 0x6eb6,
+ 0x007c, 0x157e, 0x137e, 0x147e, 0x6918, 0x7890, 0x8004, 0x8004,
+ 0x8004, 0x8004, 0xa084, 0x000f, 0x007e, 0xa100, 0x681a, 0x007f,
+ 0x8000, 0x8004, 0x0040, 0x4298, 0x20a8, 0x8104, 0xa080, 0x000b,
+ 0xad00, 0x20a0, 0x789b, 0x0000, 0xaf80, 0x002b, 0x2098, 0x53a5,
+ 0x147f, 0x137f, 0x157f, 0x007c, 0x682c, 0xa084, 0x0020, 0x00c0,
+ 0x42a4, 0x620c, 0x0078, 0x42a5, 0x6210, 0x6b18, 0x2300, 0xa202,
+ 0x0040, 0x42c5, 0x2018, 0xa382, 0x000e, 0x0048, 0x42b5, 0x0040,
+ 0x42b5, 0x2019, 0x000e, 0x0078, 0x42b9, 0x7858, 0xa084, 0xffef,
+ 0x785a, 0x783b, 0x1b01, 0x7893, 0x0000, 0x7ba2, 0x70b4, 0xa080,
+ 0x008e, 0x781a, 0xa085, 0x0001, 0x007c, 0x7858, 0xa084, 0xffef,
+ 0x785a, 0x7893, 0x0000, 0xa006, 0x007c, 0x6904, 0xa18c, 0x00ff,
+ 0xa196, 0x0007, 0x0040, 0x42da, 0xa196, 0x000f, 0x0040, 0x42da,
+ 0x6807, 0x0117, 0x6914, 0x1078, 0x3c3b, 0x6100, 0x8104, 0x00c8,
+ 0x42f5, 0x601c, 0xa005, 0x0040, 0x42e9, 0x2001, 0x0800, 0x0078,
+ 0x42f7, 0x0d7e, 0x6824, 0x007e, 0x1078, 0x4812, 0x007f, 0x6826,
+ 0x2d00, 0x682e, 0x1078, 0x3bc6, 0x0d7f, 0x2001, 0x0200, 0x6924,
+ 0xa18c, 0x00ff, 0xa10d, 0x6926, 0x8007, 0x789b, 0x000e, 0x78aa,
+ 0x6820, 0xa085, 0x8000, 0x6822, 0x2031, 0x0400, 0x6eb6, 0x7e5a,
+ 0x71b4, 0xa188, 0x0091, 0x791a, 0x007c, 0xa6c4, 0x0f00, 0xa684,
+ 0x0002, 0x00c0, 0x4321, 0x692c, 0x810d, 0x810d, 0x810d, 0xa184,
+ 0x0007, 0x2008, 0xa805, 0x6816, 0x1078, 0x3c3b, 0x68be, 0x0078,
+ 0x4324, 0x6914, 0x1078, 0x3c3b, 0x6100, 0x8104, 0x00c8, 0x4382,
+ 0xa184, 0x0300, 0x0040, 0x4330, 0x6807, 0x0117, 0x0078, 0x434e,
+ 0x6004, 0xa005, 0x00c0, 0x4357, 0x6807, 0x0117, 0x601c, 0xa005,
+ 0x00c0, 0x4344, 0x0d7e, 0x1078, 0x4812, 0x6827, 0x0034, 0x2d00,
+ 0x682e, 0x1078, 0x3bc6, 0x0d7f, 0xa684, 0x0004, 0x0040, 0x434e,
+ 0x2031, 0x0400, 0x2001, 0x2800, 0x0078, 0x4352, 0x2031, 0x0400,
+ 0x2001, 0x0800, 0x71b4, 0xa188, 0x0091, 0x0078, 0x43b0, 0x6018,
+ 0xa005, 0x00c0, 0x4344, 0x601c, 0xa005, 0x00c0, 0x4344, 0x689f,
+ 0x0000, 0x6827, 0x003d, 0xa684, 0x0001, 0x0040, 0x43be, 0xd694,
+ 0x00c0, 0x437b, 0x6100, 0xd1d4, 0x0040, 0x437b, 0x692c, 0xa18c,
+ 0x00ff, 0x0040, 0x43be, 0xa186, 0x0003, 0x0040, 0x43be, 0xa186,
+ 0x0012, 0x0040, 0x43be, 0xa6b5, 0x0800, 0x71b4, 0xa188, 0x00ae,
+ 0x0078, 0x43b9, 0x6807, 0x0117, 0x2031, 0x0400, 0x692c, 0xa18c,
+ 0x00ff, 0xa186, 0x0012, 0x00c0, 0x4393, 0x2001, 0x43cb, 0x2009,
+ 0x0001, 0x0078, 0x43a4, 0xa186, 0x0003, 0x00c0, 0x439d, 0x2001,
+ 0x43cc, 0x2009, 0x0012, 0x0078, 0x43a4, 0x2001, 0x0200, 0x71b4,
+ 0xa188, 0x0091, 0x0078, 0x43b0, 0x1078, 0x47e1, 0x78a3, 0x0000,
+ 0x681c, 0xa085, 0x0040, 0x681e, 0x71b4, 0xa188, 0x00da, 0xa006,
+ 0x6826, 0x8007, 0x789b, 0x000e, 0x78aa, 0x6820, 0xa085, 0x8000,
+ 0x6822, 0x6eb6, 0x7e5a, 0x791a, 0x0078, 0x24fa, 0x6eb6, 0x1078,
+ 0x3bc6, 0x6810, 0x70be, 0x7003, 0x0007, 0x70a3, 0x0000, 0x704b,
+ 0x0000, 0x0078, 0x24fa, 0x0023, 0x0070, 0x0005, 0x0000, 0x0a00,
+ 0x0000, 0x0000, 0x0025, 0x0000, 0x0000, 0x683b, 0x0000, 0x6837,
+ 0x0000, 0xa684, 0x0200, 0x0040, 0x43ec, 0x78b8, 0xa08c, 0x001f,
+ 0xa084, 0x8000, 0x0040, 0x43e5, 0x8108, 0x78d8, 0xa100, 0x6836,
+ 0x78dc, 0xa081, 0x0000, 0x683a, 0x007c, 0x7990, 0x810f, 0xa5ac,
+ 0x0007, 0x2021, 0x0000, 0xa480, 0x0010, 0x789a, 0x79a8, 0xa18c,
+ 0x00ff, 0xa184, 0x0080, 0x00c0, 0x441b, 0xa182, 0x0020, 0x00c8,
+ 0x4439, 0xa182, 0x0012, 0x00c8, 0x4781, 0x2100, 0x1079, 0x4409,
+ 0x007c, 0x4781, 0x45eb, 0x4781, 0x4781, 0x4446, 0x4449, 0x4483,
+ 0x44b9, 0x44ed, 0x44f0, 0x4781, 0x4781, 0x44a4, 0x4514, 0x454e,
+ 0x4781, 0x4781, 0x4574, 0xa184, 0x0020, 0x00c0, 0x45a8, 0xa18c,
+ 0x001f, 0x6814, 0xa084, 0x001f, 0xa106, 0x0040, 0x4436, 0x70b4,
+ 0xa080, 0x00cd, 0x781a, 0x2001, 0x0014, 0x1078, 0x4797, 0x1078,
+ 0x4805, 0x7003, 0x0000, 0x2001, 0x0002, 0x007c, 0x2001, 0x0000,
+ 0x007c, 0xa182, 0x0024, 0x00c8, 0x4781, 0xa184, 0x0003, 0x1079,
+ 0x4409, 0x007c, 0x4781, 0x4781, 0x4781, 0x4781, 0x1078, 0x4781,
+ 0x007c, 0x2200, 0x0079, 0x444c, 0x4577, 0x4577, 0x4470, 0x4470,
+ 0x4470, 0x4470, 0x4470, 0x4470, 0x4470, 0x4470, 0x446e, 0x4470,
+ 0x4465, 0x4470, 0x4470, 0x4470, 0x4470, 0x4470, 0x4478, 0x447b,
+ 0x4577, 0x447b, 0x4470, 0x4470, 0x4470, 0x0c7e, 0x077e, 0x6f14,
+ 0x1078, 0x37b0, 0x077f, 0x0c7f, 0x0078, 0x4470, 0x1078, 0x468e,
+ 0x6827, 0x02b3, 0x2009, 0x000b, 0x2001, 0x4800, 0x0078, 0x45ab,
+ 0x1078, 0x4773, 0x007c, 0x6827, 0x0093, 0x2009, 0x000b, 0x2001,
+ 0x4800, 0x0078, 0x4593, 0x2d58, 0x6804, 0xa084, 0x00ff, 0xa086,
+ 0x0006, 0x00c0, 0x448d, 0x6807, 0x0117, 0x6827, 0x0002, 0x1078,
+ 0x4812, 0x6827, 0x0036, 0x6932, 0x2d00, 0x682e, 0x0d7e, 0x1078,
+ 0x3b96, 0x1078, 0x45d3, 0x2b68, 0x1078, 0x3bc6, 0x0d7f, 0x1078,
+ 0x3bc6, 0x2001, 0x0002, 0x007c, 0x1078, 0x45d3, 0x2001, 0x0017,
+ 0x1078, 0x4797, 0x70a3, 0x0000, 0x2009, 0x5238, 0x200b, 0x0006,
+ 0x70af, 0x0017, 0x2009, 0x0200, 0x1078, 0x3ad4, 0x2001, 0x0001,
+ 0x007c, 0x2200, 0x0079, 0x44bc, 0x4577, 0x45a8, 0x45a8, 0x45a8,
+ 0x44dd, 0x45ba, 0x44e5, 0x45ba, 0x45ba, 0x45bd, 0x45bd, 0x45c2,
+ 0x45c2, 0x44d5, 0x44d5, 0x45a8, 0x45a8, 0x45ba, 0x45a8, 0x44e5,
+ 0x4577, 0x44e5, 0x44e5, 0x44e5, 0x44e5, 0x6827, 0x0084, 0x2009,
+ 0x000b, 0x2001, 0x4300, 0x0078, 0x45cc, 0x6827, 0x000d, 0x2009,
+ 0x000b, 0x2001, 0x4300, 0x0078, 0x45ab, 0x6827, 0x0093, 0x2009,
+ 0x000b, 0x2001, 0x4300, 0x0078, 0x4593, 0x2001, 0x0000, 0x007c,
+ 0x2200, 0x0079, 0x44f3, 0x4577, 0x450c, 0x450c, 0x450c, 0x450c,
+ 0x45ba, 0x45ba, 0x45ba, 0x45ba, 0x45ba, 0x45ba, 0x45ba, 0x45ba,
+ 0x450c, 0x450c, 0x450c, 0x450c, 0x45ba, 0x450c, 0x450c, 0x45ba,
+ 0x45ba, 0x45ba, 0x45ba, 0x4577, 0x6827, 0x0093, 0x2009, 0x000b,
+ 0x2001, 0x4300, 0x0078, 0x4593, 0xa684, 0x0004, 0x00c0, 0x4528,
+ 0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x4781, 0x1078,
+ 0x45d3, 0x6807, 0x0117, 0x1078, 0x3bc6, 0x2001, 0x0002, 0x007c,
+ 0x6000, 0xa084, 0x0004, 0x0040, 0x4781, 0x2d58, 0x6804, 0xa084,
+ 0x00ff, 0xa086, 0x0006, 0x00c0, 0x4537, 0x6807, 0x0117, 0x6827,
+ 0x0002, 0x1078, 0x4812, 0x6827, 0x0036, 0x6932, 0x2d00, 0x682e,
+ 0x0d7e, 0x1078, 0x3ba5, 0x1078, 0x45d3, 0x2b68, 0x1078, 0x3bc6,
+ 0x0d7f, 0x1078, 0x3bc6, 0x2001, 0x0002, 0x007c, 0x6000, 0xa084,
+ 0x0004, 0x0040, 0x4781, 0x6a04, 0xa294, 0x00ff, 0xa286, 0x0006,
+ 0x00c0, 0x455c, 0x6807, 0x0117, 0x6827, 0x0002, 0x2d58, 0x1078,
+ 0x4812, 0x6827, 0x0036, 0x6932, 0x2d00, 0x682e, 0x0d7e, 0x1078,
+ 0x3bb5, 0x1078, 0x45d3, 0x2b68, 0x1078, 0x3bc6, 0x0d7f, 0x1078,
+ 0x3bc6, 0x2001, 0x0002, 0x007c, 0x1078, 0x4781, 0x007c, 0x70b4,
+ 0xa080, 0x00cd, 0x781a, 0x2001, 0x0001, 0x1078, 0x4797, 0x1078,
+ 0x4805, 0x7003, 0x0000, 0x2001, 0x0002, 0x007c, 0x1078, 0x47c7,
+ 0x1078, 0x47fe, 0x1078, 0x43d5, 0x1078, 0x42cd, 0x1078, 0x4805,
+ 0x2001, 0x0001, 0x007c, 0x1078, 0x47c7, 0x1078, 0x47fe, 0x1078,
+ 0x43d5, 0x70b4, 0xa080, 0x00cd, 0x781a, 0x2001, 0x0013, 0x1078,
+ 0x4797, 0x1078, 0x4805, 0x7003, 0x0000, 0x2001, 0x0002, 0x007c,
+ 0x1078, 0x4781, 0x007c, 0x1078, 0x47c7, 0x1078, 0x47fe, 0x1078,
+ 0x43d5, 0x1078, 0x42cd, 0x1078, 0x4805, 0x1078, 0x484d, 0x2001,
+ 0x0001, 0x007c, 0x2001, 0x0003, 0x007c, 0x1078, 0x468e, 0x2001,
+ 0x0000, 0x007c, 0x0c7e, 0x077e, 0x6f14, 0x1078, 0x37b0, 0x077f,
+ 0x0c7f, 0x2001, 0x0000, 0x007c, 0x1078, 0x47c7, 0x1078, 0x4781,
+ 0x2001, 0x0006, 0x007c, 0x6904, 0xa18c, 0x00ff, 0xa186, 0x0007,
+ 0x0040, 0x45de, 0xa186, 0x000f, 0x00c0, 0x45e2, 0x1078, 0x47fe,
+ 0x1078, 0x43d5, 0x70b4, 0xa080, 0x00cd, 0x781a, 0x1078, 0x4805,
+ 0x7003, 0x0000, 0x007c, 0x7aa8, 0xa294, 0x00ff, 0x78a8, 0xa084,
+ 0x00ff, 0xa08a, 0x0004, 0x00c8, 0x4781, 0x1079, 0x45f8, 0x007c,
+ 0x4781, 0x45fc, 0x4781, 0x4695, 0xa282, 0x0003, 0x0040, 0x4603,
+ 0x1078, 0x4781, 0x007c, 0x7da8, 0xa5ac, 0x00ff, 0x7ca8, 0xa4a4,
+ 0x00ff, 0x69b8, 0xa184, 0x0100, 0x0040, 0x4642, 0xa18c, 0xfeff,
+ 0x69ba, 0x78a0, 0xa005, 0x00c0, 0x4642, 0xa4a4, 0x00ff, 0x0040,
+ 0x4636, 0xa482, 0x000c, 0x0040, 0x461f, 0x00c8, 0x4629, 0x852b,
+ 0x852b, 0x1078, 0x382e, 0x0040, 0x4629, 0x1078, 0x3627, 0x0078,
+ 0x4638, 0x1078, 0x4760, 0x1078, 0x3652, 0x69b8, 0xa18d, 0x0100,
+ 0x69ba, 0xa6b5, 0x1000, 0x7e5a, 0x0078, 0x463b, 0x1078, 0x3652,
+ 0xa6b4, 0xefff, 0x7e5a, 0x70b4, 0xa080, 0x0091, 0x781a, 0x2001,
+ 0x0001, 0x007c, 0x0c7e, 0x1078, 0x4682, 0x6200, 0xd2e4, 0x0040,
+ 0x4673, 0x6208, 0x8217, 0xa294, 0x00ff, 0xa282, 0x000c, 0x0048,
+ 0x4655, 0x0040, 0x4655, 0x2011, 0x000c, 0x2400, 0xa202, 0x00c8,
+ 0x465a, 0x2220, 0x6208, 0xa294, 0x00ff, 0x701c, 0xa202, 0x00c8,
+ 0x4662, 0x721c, 0x2200, 0xa502, 0x00c8, 0x4667, 0x2228, 0x1078,
+ 0x4764, 0x852b, 0x852b, 0x1078, 0x382e, 0x0040, 0x4673, 0x1078,
+ 0x362e, 0x0078, 0x4677, 0x1078, 0x4760, 0x1078, 0x3659, 0xa6b5,
+ 0x1000, 0x7e5a, 0x70b4, 0xa080, 0x00b9, 0x781a, 0x2001, 0x0004,
+ 0x0c7f, 0x007c, 0x007e, 0x6814, 0x8007, 0xa084, 0x000f, 0x8003,
+ 0x8003, 0x8003, 0xa0e0, 0x5480, 0x007f, 0x007c, 0x0c7e, 0x1078,
+ 0x4682, 0x1078, 0x3659, 0x0c7f, 0x007c, 0xa282, 0x0002, 0x00c0,
+ 0x4781, 0x7aa8, 0xa294, 0x00ff, 0x69b8, 0xa184, 0x0200, 0x0040,
+ 0x46cc, 0xa18c, 0xfdff, 0x69ba, 0x78a0, 0xa005, 0x00c0, 0x46cc,
+ 0xa282, 0x0002, 0x00c8, 0x376b, 0x1078, 0x472a, 0x1078, 0x36f9,
+ 0x1078, 0x3652, 0xa684, 0x0100, 0x0040, 0x46c2, 0x682c, 0xa084,
+ 0x0001, 0x0040, 0x46c2, 0xc6fc, 0x7888, 0xa084, 0x0040, 0x0040,
+ 0x46c2, 0xc6fd, 0xa6b5, 0x1000, 0x7e5a, 0x70b4, 0xa080, 0x0091,
+ 0x781a, 0x2001, 0x0001, 0x007c, 0x0c7e, 0x1078, 0x4682, 0xa284,
+ 0xfffe, 0x0040, 0x46d7, 0x2011, 0x0001, 0x0078, 0x46db, 0xa284,
+ 0x0001, 0x0040, 0x46e1, 0x6100, 0xd1ec, 0x00c0, 0x46e1, 0x2011,
+ 0x0000, 0x1078, 0x471c, 0x1078, 0x3700, 0x1078, 0x3659, 0xa684,
+ 0x0100, 0x0040, 0x46f7, 0x682c, 0xa084, 0x0001, 0x0040, 0x46f7,
+ 0xc6fc, 0x7888, 0xa084, 0x0040, 0x0040, 0x46f7, 0xc6fd, 0xa6b5,
+ 0x1000, 0x7e5a, 0x70b4, 0xa080, 0x00b9, 0x781a, 0x2001, 0x0004,
+ 0x0c7f, 0x007c, 0x0c7e, 0x2960, 0x6000, 0x2011, 0x0001, 0xa084,
+ 0x2000, 0x00c0, 0x470d, 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab,
+ 0x0002, 0x78ab, 0x0003, 0x7aaa, 0xa8c0, 0x0004, 0x68b8, 0xa085,
+ 0x0200, 0x68ba, 0x0c7f, 0x007c, 0x789b, 0x0018, 0x78ab, 0x0001,
+ 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0081, 0x78ab,
+ 0x0004, 0x007c, 0x0c7e, 0x7054, 0x2060, 0x6000, 0xa084, 0x1000,
+ 0x00c0, 0x4738, 0x2029, 0x0032, 0x2021, 0x0000, 0x0078, 0x4758,
+ 0x6508, 0xa5ac, 0x00ff, 0x7018, 0xa086, 0x0028, 0x00c0, 0x4748,
+ 0xa582, 0x0019, 0x00c8, 0x474e, 0x2029, 0x0019, 0x0078, 0x474e,
+ 0xa582, 0x000c, 0x00c8, 0x474e, 0x2029, 0x000c, 0x6408, 0x8427,
+ 0xa4a4, 0x00ff, 0xa482, 0x000c, 0x0048, 0x4758, 0x2021, 0x000c,
+ 0x1078, 0x4764, 0x68b8, 0xa085, 0x0100, 0x68ba, 0x0c7f, 0x007c,
+ 0x2021, 0x0000, 0x2029, 0x0032, 0x789b, 0x0018, 0x78ab, 0x0001,
+ 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa, 0x7caa, 0x789b, 0x0081,
+ 0x78ab, 0x0005, 0x007c, 0x2001, 0x0003, 0x1078, 0x478f, 0xa6b5,
+ 0x1000, 0x7e5a, 0x70b4, 0xa080, 0x00b9, 0x781a, 0x2001, 0x0005,
+ 0x007c, 0x2001, 0x0007, 0x1078, 0x478f, 0xa6b5, 0x1000, 0x7e5a,
+ 0x70b4, 0xa080, 0x00b9, 0x781a, 0x2001, 0x0004, 0x007c, 0x789b,
+ 0x0018, 0x78aa, 0x789b, 0x0081, 0x78ab, 0x0001, 0x007c, 0x6904,
+ 0xa18c, 0x00ff, 0xa196, 0x0007, 0x0040, 0x47a5, 0xa196, 0x000f,
+ 0x0040, 0x47a5, 0x1078, 0x19ac, 0x007c, 0x6924, 0xa194, 0x003f,
+ 0x00c0, 0x47ae, 0xa18c, 0xffc0, 0xa105, 0x6826, 0x1078, 0x3bc6,
+ 0x691c, 0xa184, 0x0100, 0x0040, 0x47bb, 0x6914, 0x1078, 0x3c3b,
+ 0x6204, 0x8210, 0x6206, 0x007c, 0x692c, 0x6834, 0x682e, 0xa112,
+ 0x6930, 0x6838, 0x6832, 0xa11b, 0xa200, 0xa301, 0x007c, 0x0c7e,
+ 0xade0, 0x0018, 0x6003, 0x0070, 0x6106, 0x600b, 0x0000, 0x600f,
+ 0x0a00, 0x6013, 0x0000, 0x6017, 0x0000, 0x8007, 0x601a, 0x601f,
+ 0x0000, 0x6023, 0x0000, 0x0c7f, 0x6824, 0xa085, 0x0080, 0x6826,
+ 0x007c, 0x157e, 0x137e, 0x147e, 0x2098, 0xaf80, 0x002d, 0x20a0,
+ 0x81ac, 0x0040, 0x47ec, 0x53a6, 0xa184, 0x0001, 0x0040, 0x47f2,
+ 0x3304, 0x78be, 0x147f, 0x137f, 0x157f, 0x007c, 0x70b0, 0xa005,
+ 0x10c0, 0x248c, 0x70b3, 0x8000, 0x0078, 0x4b4b, 0x71b0, 0x81ff,
+ 0x0040, 0x4804, 0x1078, 0x4c41, 0x007c, 0x71b0, 0x81ff, 0x0040,
+ 0x4811, 0x7848, 0xa085, 0x0008, 0x784a, 0x70b3, 0x0000, 0x1078,
+ 0x4887, 0x007c, 0x0c7e, 0x0d7e, 0x1078, 0x1989, 0x00c0, 0x481a,
+ 0x1078, 0x248c, 0x0c7f, 0x157e, 0x137e, 0x147e, 0x2da0, 0x2c98,
+ 0x20a9, 0x0031, 0x53a3, 0x147f, 0x137f, 0x157f, 0x6807, 0x010d,
+ 0x680b, 0x0000, 0x7004, 0x8007, 0x681a, 0x6823, 0x0000, 0x681f,
+ 0x0000, 0x689f, 0x0000, 0x0c7f, 0x007c, 0x70b4, 0xa080, 0x0091,
+ 0x781a, 0x0078, 0x24fa, 0x70b4, 0xa080, 0x0081, 0x781a, 0x0078,
+ 0x24fa, 0x70b4, 0xa080, 0x00b9, 0x781a, 0x0078, 0x24fa, 0x70b4,
+ 0xa080, 0x00c3, 0x781a, 0x0078, 0x24fa, 0x6904, 0xa18c, 0x00ff,
+ 0xa196, 0x0007, 0x0040, 0x485a, 0xa196, 0x000f, 0x0040, 0x485a,
+ 0x6807, 0x0117, 0x6824, 0xa084, 0x00ff, 0xa085, 0x0200, 0x6826,
+ 0x8007, 0x789b, 0x000e, 0x78aa, 0x6820, 0xa085, 0x8000, 0x6822,
+ 0x2031, 0x0400, 0x6eb6, 0x7e5a, 0x71b4, 0xa188, 0x0091, 0x791a,
+ 0x007c, 0x1078, 0x4805, 0x7848, 0xa085, 0x000c, 0x784a, 0x70b4,
+ 0xa080, 0x00cd, 0x781a, 0x2009, 0x000b, 0x2001, 0x4400, 0x1078,
+ 0x47c7, 0x2001, 0x0013, 0x1078, 0x4797, 0x0078, 0x3c68, 0x127e,
+ 0x2091, 0x2200, 0x2049, 0x4887, 0x7000, 0x7204, 0xa205, 0x720c,
+ 0xa215, 0x7008, 0xa084, 0xfff7, 0xa205, 0x0040, 0x4899, 0x0078,
+ 0x489e, 0x7003, 0x0000, 0x127f, 0x2000, 0x007c, 0x7000, 0xa084,
+ 0x0001, 0x00c0, 0x48cc, 0x7108, 0x8103, 0x00c8, 0x48ab, 0x1078,
+ 0x49ce, 0x0078, 0x48a3, 0x700c, 0xa08c, 0x00ff, 0x0040, 0x48cc,
+ 0x7004, 0x8004, 0x00c8, 0x48c3, 0x7014, 0xa005, 0x00c0, 0x48bf,
+ 0x7010, 0xa005, 0x0040, 0x48c3, 0xa102, 0x00c8, 0x48a3, 0x7007,
+ 0x0010, 0x0078, 0x48cc, 0x8aff, 0x0040, 0x48cc, 0x1078, 0x4c18,
+ 0x00c0, 0x48c6, 0x0040, 0x48a3, 0x1078, 0x4957, 0x7003, 0x0000,
+ 0x127f, 0x2000, 0x007c, 0x017e, 0x6104, 0xa18c, 0x00ff, 0xa186,
+ 0x0007, 0x0040, 0x48df, 0xa18e, 0x000f, 0x00c0, 0x48e2, 0x6040,
+ 0x0078, 0x48e3, 0x6428, 0x017f, 0x84ff, 0x0040, 0x490d, 0x2c70,
+ 0x7004, 0xa0bc, 0x000f, 0xa7b8, 0x491d, 0x273c, 0x87fb, 0x00c0,
+ 0x48fb, 0x0048, 0x48f5, 0x1078, 0x248c, 0x609c, 0xa075, 0x0040,
+ 0x490d, 0x0078, 0x48e8, 0x2704, 0xae68, 0x6808, 0xa630, 0x680c,
+ 0xa529, 0x8421, 0x0040, 0x490d, 0x8738, 0x2704, 0xa005, 0x00c0,
+ 0x48fc, 0x709c, 0xa075, 0x00c0, 0x48e8, 0x007c, 0x0000, 0x0005,
+ 0x0009, 0x000d, 0x0011, 0x0015, 0x0019, 0x001d, 0x0000, 0x0003,
+ 0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0000, 0x4912, 0x490f,
+ 0x0000, 0x0000, 0x8000, 0x0000, 0x4912, 0x0000, 0x491a, 0x4917,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x491a, 0x0000, 0x4915, 0x4915,
+ 0x0000, 0x0000, 0x8000, 0x0000, 0x4915, 0x0000, 0x491b, 0x491b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x491b, 0x127e, 0x2091, 0x2200,
+ 0x2079, 0x5200, 0x2071, 0x0010, 0x7007, 0x000a, 0x7007, 0x0002,
+ 0x7003, 0x0000, 0x2071, 0x0020, 0x7007, 0x000a, 0x7007, 0x0002,
+ 0x7003, 0x0000, 0x2049, 0x0000, 0x127f, 0x2000, 0x007c, 0x2049,
+ 0x4957, 0x2019, 0x0000, 0x7004, 0x8004, 0x00c8, 0x49aa, 0x7007,
+ 0x0012, 0x7108, 0x7008, 0xa106, 0x00c0, 0x4961, 0xa184, 0x01e0,
+ 0x0040, 0x496c, 0x1078, 0x248c, 0x2001, 0x04fd, 0x2004, 0xa082,
+ 0x0005, 0x00c8, 0x4977, 0xa184, 0x4000, 0x00c0, 0x4961, 0xa19c,
+ 0x300c, 0xa386, 0x2004, 0x0040, 0x4985, 0xa386, 0x0008, 0x0040,
+ 0x4990, 0xa386, 0x200c, 0x00c0, 0x4961, 0x7200, 0x8204, 0x0048,
+ 0x4990, 0x730c, 0xa384, 0x00ff, 0x0040, 0x4990, 0x1078, 0x248c,
+ 0x7007, 0x0012, 0x7000, 0xa084, 0x0001, 0x00c0, 0x49aa, 0x7008,
+ 0xa084, 0x01e0, 0x00c0, 0x49aa, 0x7310, 0x7014, 0xa305, 0x0040,
+ 0x49aa, 0x710c, 0xa184, 0x0300, 0x00c0, 0x49aa, 0xa184, 0x00ff,
+ 0x00c0, 0x4957, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004, 0xa084,
+ 0x0008, 0x00c0, 0x49ae, 0x7007, 0x0012, 0x7108, 0x8103, 0x0048,
+ 0x49b3, 0x7003, 0x0000, 0x2049, 0x0000, 0x007c, 0x107e, 0x007e,
+ 0x127e, 0x157e, 0x2091, 0x2200, 0x7108, 0x1078, 0x49ce, 0x157f,
+ 0x127f, 0x2091, 0x8001, 0x007f, 0x107f, 0x007c, 0x7204, 0x7500,
+ 0x730c, 0xa384, 0x0300, 0x00c0, 0x49f5, 0xa184, 0x01e0, 0x00c0,
+ 0x4a19, 0x7108, 0xa184, 0x01e0, 0x00c0, 0x4a19, 0x2001, 0x04fd,
+ 0x2004, 0xa082, 0x0005, 0x00c8, 0x49e9, 0xa184, 0x4000, 0x00c0,
+ 0x49d9, 0xa184, 0x0007, 0x0079, 0x49ed, 0x49f7, 0x4a09, 0x49f5,
+ 0x4a09, 0x49f5, 0x4a55, 0x49f5, 0x4a53, 0x1078, 0x248c, 0x7004,
+ 0xa084, 0x0010, 0xa085, 0x0002, 0x7006, 0x8aff, 0x00c0, 0x4a04,
+ 0x2049, 0x0000, 0x0078, 0x4a08, 0x1078, 0x4c18, 0x00c0, 0x4a04,
+ 0x007c, 0x7004, 0xa084, 0x0010, 0xa085, 0x0002, 0x7006, 0x8aff,
+ 0x00c0, 0x4a14, 0x0078, 0x4a18, 0x1078, 0x4c18, 0x00c0, 0x4a14,
+ 0x007c, 0x7007, 0x0012, 0x7108, 0x00e0, 0x4a1c, 0x2091, 0x6000,
+ 0x00e0, 0x4a20, 0x2091, 0x6000, 0x7007, 0x0012, 0x7007, 0x0008,
+ 0x7004, 0xa084, 0x0008, 0x00c0, 0x4a28, 0x7007, 0x0012, 0x7108,
+ 0x8103, 0x0048, 0x4a2d, 0x7003, 0x0000, 0x7000, 0xa005, 0x00c0,
+ 0x4a41, 0x7004, 0xa005, 0x00c0, 0x4a41, 0x700c, 0xa005, 0x0040,
+ 0x4a43, 0x0078, 0x4a24, 0x2049, 0x0000, 0x1078, 0x38d7, 0x6818,
+ 0xa084, 0x8000, 0x0040, 0x4a4e, 0x681b, 0x0002, 0x007c, 0x1078,
+ 0x248c, 0x1078, 0x248c, 0x1078, 0x4ab1, 0x7210, 0x7114, 0x700c,
+ 0xa09c, 0x00ff, 0x2800, 0xa300, 0xa211, 0xa189, 0x0000, 0x1078,
+ 0x4ab1, 0x2704, 0x2c58, 0xac60, 0x6308, 0x2200, 0xa322, 0x630c,
+ 0x2100, 0xa31b, 0x2400, 0xa305, 0x0040, 0x4a78, 0x00c8, 0x4a78,
+ 0x8412, 0x8210, 0x830a, 0xa189, 0x0000, 0x2b60, 0x0078, 0x4a5f,
+ 0x2b60, 0x8a07, 0x007e, 0x6004, 0xa084, 0x0008, 0x0040, 0x4a84,
+ 0xa7ba, 0x4917, 0x0078, 0x4a86, 0xa7ba, 0x490f, 0x007f, 0xa73d,
+ 0x2c00, 0x6886, 0x6f8a, 0x6c92, 0x6b8e, 0x7007, 0x0012, 0x1078,
+ 0x4957, 0x007c, 0x8738, 0x2704, 0xa005, 0x00c0, 0x4aa5, 0x609c,
+ 0xa005, 0x0040, 0x4aae, 0x2060, 0x6004, 0xa084, 0x000f, 0xa080,
+ 0x491d, 0x203c, 0x87fb, 0x1040, 0x248c, 0x8a51, 0x0040, 0x4aad,
+ 0x7008, 0xa084, 0x0003, 0xa086, 0x0003, 0x007c, 0x2051, 0x0000,
+ 0x007c, 0x8a50, 0x8739, 0x2704, 0xa004, 0x00c0, 0x4ac5, 0x6000,
+ 0xa064, 0x00c0, 0x4abc, 0x2d60, 0x6004, 0xa084, 0x000f, 0xa080,
+ 0x492d, 0x203c, 0x87fb, 0x1040, 0x248c, 0x007c, 0x127e, 0x0d7e,
+ 0x2091, 0x2200, 0x0d7f, 0x6884, 0x2060, 0x6888, 0x6b8c, 0x6c90,
+ 0x8057, 0xaad4, 0x00ff, 0xa084, 0x00ff, 0x007e, 0x6804, 0xa084,
+ 0x0008, 0x007f, 0x0040, 0x4ae0, 0xa0b8, 0x4917, 0x0078, 0x4ae2,
+ 0xa0b8, 0x490f, 0x7e08, 0xa6b5, 0x000c, 0x6904, 0xa18c, 0x00ff,
+ 0xa186, 0x0007, 0x0040, 0x4af0, 0xa18e, 0x000f, 0x00c0, 0x4af9,
+ 0x681c, 0xa084, 0x0040, 0x0040, 0x4b00, 0xa6b5, 0x0001, 0x0078,
+ 0x4b00, 0x681c, 0xa084, 0x0040, 0x0040, 0x4b00, 0xa6b5, 0x0001,
+ 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x4b02, 0x2400,
+ 0xa305, 0x00c0, 0x4b0d, 0x0078, 0x4b33, 0x2c58, 0x2704, 0x6104,
+ 0xac60, 0x6000, 0xa400, 0x701a, 0x6004, 0xa301, 0x701e, 0xa184,
+ 0x0008, 0x0040, 0x4b23, 0x6010, 0xa081, 0x0000, 0x7022, 0x6014,
+ 0xa081, 0x0000, 0x7026, 0x6208, 0x2400, 0xa202, 0x7012, 0x620c,
+ 0x2300, 0xa203, 0x7016, 0x7602, 0x7007, 0x0001, 0x2b60, 0x1078,
+ 0x4a92, 0x0078, 0x4b35, 0x1078, 0x4c18, 0x00c0, 0x4b33, 0x127f,
+ 0x2000, 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x7007,
+ 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x4b41, 0x7003, 0x0008,
+ 0x127f, 0x2000, 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f,
+ 0x2049, 0x4b4b, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0,
+ 0x4b54, 0x7e08, 0xa6b5, 0x000c, 0x6904, 0xa18c, 0x00ff, 0xa186,
+ 0x0007, 0x0040, 0x4b67, 0xa18e, 0x000f, 0x00c0, 0x4b72, 0x681c,
+ 0xa084, 0x0040, 0x0040, 0x4b6e, 0xa6b5, 0x0001, 0x6840, 0x2050,
+ 0x0078, 0x4b7b, 0x681c, 0xa084, 0x0020, 0x00c0, 0x4b79, 0xa6b5,
+ 0x0001, 0x6828, 0x2050, 0x2d60, 0x6004, 0xa0bc, 0x000f, 0xa7b8,
+ 0x491d, 0x273c, 0x87fb, 0x00c0, 0x4b8f, 0x0048, 0x4b89, 0x1078,
+ 0x248c, 0x689c, 0xa065, 0x0040, 0x4b93, 0x0078, 0x4b7c, 0x1078,
+ 0x4c18, 0x00c0, 0x4b8f, 0x127f, 0x2000, 0x007c, 0x127e, 0x007e,
+ 0x017e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x037f, 0x047f, 0x7e08,
+ 0xa6b5, 0x000c, 0x6904, 0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040,
+ 0x4bad, 0xa18e, 0x000f, 0x00c0, 0x4bb6, 0x681c, 0xa084, 0x0040,
+ 0x0040, 0x4bbd, 0xa6b5, 0x0001, 0x0078, 0x4bbd, 0x681c, 0xa084,
+ 0x0040, 0x0040, 0x4bbd, 0xa6b5, 0x0001, 0x2049, 0x4b96, 0x017e,
+ 0x6904, 0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040, 0x4bcb, 0xa18e,
+ 0x000f, 0x00c0, 0x4bce, 0x6840, 0x0078, 0x4bcf, 0x6828, 0x017f,
+ 0xa055, 0x0040, 0x4c15, 0x2d70, 0x2e60, 0x7004, 0xa0bc, 0x000f,
+ 0xa7b8, 0x491d, 0x273c, 0x87fb, 0x00c0, 0x4be9, 0x0048, 0x4be2,
+ 0x1078, 0x248c, 0x709c, 0xa075, 0x2060, 0x0040, 0x4c15, 0x0078,
+ 0x4bd5, 0x2704, 0xae68, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0048,
+ 0x4c02, 0x8a51, 0x00c0, 0x4bf6, 0x1078, 0x248c, 0x8738, 0x2704,
+ 0xa005, 0x00c0, 0x4bea, 0x709c, 0xa075, 0x2060, 0x0040, 0x4c15,
+ 0x0078, 0x4bd5, 0x8422, 0x8420, 0x831a, 0xa399, 0x0000, 0x6908,
+ 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, 0x00c8, 0x4c11, 0x1078,
+ 0x248c, 0x2071, 0x0020, 0x0078, 0x4b00, 0x127f, 0x2000, 0x007c,
+ 0x7008, 0xa084, 0x0003, 0xa086, 0x0003, 0x0040, 0x4c40, 0x2704,
+ 0xac08, 0x2104, 0x701a, 0x8108, 0x2104, 0x701e, 0x8108, 0x2104,
+ 0x7012, 0x8108, 0x2104, 0x7016, 0x6004, 0xa084, 0x0008, 0x0040,
+ 0x4c37, 0x8108, 0x2104, 0x7022, 0x8108, 0x2104, 0x7026, 0x7602,
+ 0x7004, 0xa084, 0x0010, 0xa085, 0x0001, 0x7006, 0x1078, 0x4a92,
+ 0x007c, 0x127e, 0x007e, 0x0d7e, 0x2091, 0x2200, 0x2049, 0x4c41,
+ 0x0d7f, 0x087f, 0x7108, 0xa184, 0x0003, 0x00c0, 0x4c6b, 0x017e,
+ 0x6904, 0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040, 0x4c5b, 0xa18e,
+ 0x000f, 0x00c0, 0x4c5e, 0x6840, 0x0078, 0x4c5f, 0x6828, 0x017f,
+ 0xa005, 0x0040, 0x4c79, 0x0078, 0x489e, 0x0020, 0x4c6b, 0x1078,
+ 0x4a55, 0x0078, 0x4c79, 0x00a0, 0x4c72, 0x7108, 0x1078, 0x49ce,
+ 0x0078, 0x4c4a, 0x7007, 0x0010, 0x00a0, 0x4c74, 0x7108, 0x1078,
+ 0x49ce, 0x7008, 0xa086, 0x0008, 0x00c0, 0x4c4a, 0x7000, 0xa005,
+ 0x00c0, 0x4c4a, 0x7003, 0x0000, 0x2049, 0x0000, 0x127f, 0x2000,
+ 0x007c, 0x127e, 0x147e, 0x137e, 0x157e, 0x0c7e, 0x0d7e, 0x2091,
+ 0x2200, 0x0d7f, 0x2049, 0x4c89, 0xad80, 0x0011, 0x20a0, 0x2099,
+ 0x0031, 0x700c, 0xa084, 0x00ff, 0x682a, 0x7007, 0x0008, 0x7007,
+ 0x0002, 0x7003, 0x0001, 0x0040, 0x4ca8, 0x8000, 0x80ac, 0x53a5,
+ 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x4caa, 0x0c7f,
+ 0x2049, 0x0000, 0x7003, 0x0000, 0x157f, 0x137f, 0x147f, 0x127f,
+ 0x2000, 0x007c, 0x2091, 0x6000, 0x2091, 0x8000, 0x78cc, 0xa005,
+ 0x0040, 0x4cd1, 0x7994, 0x70d0, 0xa106, 0x00c0, 0x4cd1, 0x7804,
+ 0xa005, 0x0040, 0x4cd1, 0x7807, 0x0000, 0x0068, 0x4cd1, 0x2091,
+ 0x4080, 0x7820, 0x8001, 0x7822, 0x00c0, 0x4d2c, 0x7824, 0x7822,
+ 0x2069, 0x5240, 0x6800, 0xa084, 0x0007, 0x0040, 0x4cef, 0xa086,
+ 0x0002, 0x0040, 0x4cef, 0x6834, 0xa00d, 0x0040, 0x4cef, 0x2104,
+ 0xa005, 0x0040, 0x4cef, 0x8001, 0x200a, 0x0040, 0x4dd4, 0x7848,
+ 0xa005, 0x0040, 0x4cfd, 0x8001, 0x784a, 0x00c0, 0x4cfd, 0x2009,
+ 0x0102, 0x6844, 0x200a, 0x1078, 0x226f, 0x6890, 0xa005, 0x0040,
+ 0x4d09, 0x8001, 0x6892, 0x00c0, 0x4d09, 0x686f, 0x0000, 0x6873,
+ 0x0001, 0x2061, 0x5500, 0x20a9, 0x0100, 0x2009, 0x0002, 0x6034,
+ 0xa005, 0x0040, 0x4d1f, 0x8001, 0x6036, 0x00c0, 0x4d1f, 0x6010,
+ 0xa005, 0x0040, 0x4d1f, 0x017e, 0x1078, 0x226f, 0x017f, 0xace0,
+ 0x0010, 0x0070, 0x4d25, 0x0078, 0x4d0f, 0x8109, 0x0040, 0x4d2c,
+ 0x20a9, 0x0100, 0x0078, 0x4d0f, 0x1078, 0x4d39, 0x1078, 0x4d5e,
+ 0x2009, 0x5251, 0x2104, 0x2009, 0x0102, 0x200a, 0x2091, 0x8001,
+ 0x007c, 0x7834, 0x8001, 0x7836, 0x00c0, 0x4d5d, 0x7838, 0x7836,
+ 0x2091, 0x8000, 0x7844, 0xa005, 0x00c0, 0x4d48, 0x2001, 0x0101,
+ 0x8001, 0x7846, 0xa080, 0x7500, 0x2040, 0x2004, 0xa065, 0x0040,
+ 0x4d5d, 0x6024, 0xa005, 0x0040, 0x4d59, 0x8001, 0x6026, 0x0040,
+ 0x4d8d, 0x6000, 0x2c40, 0x0078, 0x4d4e, 0x007c, 0x7828, 0x8001,
+ 0x782a, 0x00c0, 0x4d8c, 0x782c, 0x782a, 0x7830, 0xa005, 0x00c0,
+ 0x4d6b, 0x2001, 0x0200, 0x8001, 0x7832, 0x8003, 0x8003, 0x8003,
+ 0x8003, 0xa090, 0x5500, 0xa298, 0x0002, 0x2304, 0xa084, 0x0008,
+ 0x0040, 0x4d8c, 0xa290, 0x0009, 0x2204, 0xa005, 0x0040, 0x4d84,
+ 0x8001, 0x2012, 0x00c0, 0x4d8c, 0x2304, 0xa084, 0xfff7, 0xa085,
+ 0x0080, 0x201a, 0x1078, 0x226f, 0x007c, 0x2069, 0x5240, 0x6800,
+ 0xa005, 0x0040, 0x4d97, 0x6848, 0xac06, 0x0040, 0x4dd4, 0x601b,
+ 0x0006, 0x60b4, 0xa084, 0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff,
+ 0xa085, 0x0060, 0x6022, 0x6000, 0x2042, 0x6714, 0x6f82, 0x1078,
+ 0x19c5, 0x6818, 0xa005, 0x0040, 0x4daf, 0x8001, 0x681a, 0x6808,
+ 0xa084, 0xffef, 0x680a, 0x6810, 0x8001, 0x00d0, 0x4db9, 0x1078,
+ 0x248c, 0x6812, 0x602f, 0x0000, 0x6033, 0x0000, 0x2c68, 0x1078,
+ 0x1cdc, 0x2069, 0x5240, 0x7944, 0xa184, 0x0100, 0x2001, 0x0006,
+ 0x686e, 0x00c0, 0x4dcf, 0x6986, 0x2001, 0x0004, 0x686e, 0x1078,
+ 0x226a, 0x2091, 0x8001, 0x007c, 0x2069, 0x0100, 0x2009, 0x5240,
+ 0x2104, 0xa084, 0x0007, 0x0040, 0x4e30, 0xa086, 0x0007, 0x00c0,
+ 0x4dea, 0x0d7e, 0x2009, 0x5252, 0x216c, 0x1078, 0x3b1c, 0x0d7f,
+ 0x0078, 0x4e30, 0x2009, 0x5252, 0x2164, 0x1078, 0x2437, 0x601b,
+ 0x0006, 0x6858, 0xa084, 0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff,
+ 0xa085, 0x0048, 0x6022, 0x602f, 0x0000, 0x6033, 0x0000, 0x6830,
+ 0xa084, 0x0040, 0x0040, 0x4e24, 0x684b, 0x0004, 0x20a9, 0x0014,
+ 0x6848, 0xa084, 0x0004, 0x0040, 0x4e11, 0x0070, 0x4e11, 0x0078,
+ 0x4e08, 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0001,
+ 0x0040, 0x4e1e, 0x0070, 0x4e1e, 0x0078, 0x4e15, 0x20a9, 0x00fa,
+ 0x0070, 0x4e24, 0x0078, 0x4e20, 0x6808, 0xa084, 0xfffd, 0x680a,
+ 0x681b, 0x0048, 0x2009, 0x525b, 0x200b, 0x0007, 0x784c, 0x784a,
+ 0x2091, 0x8001, 0x007c, 0x2079, 0x5200, 0x1078, 0x4e5e, 0x1078,
+ 0x4e42, 0x1078, 0x4e50, 0x7833, 0x0000, 0x7847, 0x0000, 0x784b,
+ 0x0000, 0x007c, 0x2019, 0x0003, 0x2011, 0x5246, 0x2204, 0xa086,
+ 0x003c, 0x0040, 0x4e4d, 0x2019, 0x0002, 0x7b2a, 0x7b2e, 0x007c,
+ 0x2019, 0x0039, 0x2011, 0x5246, 0x2204, 0xa086, 0x003c, 0x0040,
+ 0x4e5b, 0x2019, 0x0027, 0x7b36, 0x7b3a, 0x007c, 0x2019, 0x3971,
+ 0x2011, 0x5246, 0x2204, 0xa086, 0x003c, 0x0040, 0x4e69, 0x2019,
+ 0x2626, 0x7b22, 0x7b26, 0x783f, 0x0000, 0x7843, 0x000a, 0x007c,
+ 0x0020, 0x002b, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
+ 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
+ 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
+ 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
+ 0x0000, 0x0020, 0x0000, 0x0014, 0x0014, 0x9849, 0x0014, 0x0014,
+ 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0080, 0x000f, 0x0000,
+ 0x0201, 0x0604, 0x0c08, 0x2120, 0x4022, 0xf880, 0x0018, 0x300b,
+ 0xa201, 0x0014, 0xa200, 0x0014, 0xa200, 0x0214, 0x0000, 0x006c,
+ 0x0002, 0x0014, 0x98cd, 0x009e, 0x0093, 0xa202, 0x8838, 0x3806,
+ 0x8839, 0x20c3, 0x0864, 0x9885, 0x28c1, 0x9cae, 0xa203, 0x300c,
+ 0x2846, 0x8161, 0x846a, 0x8300, 0x1856, 0x883a, 0x9865, 0x28f2,
+ 0x9c91, 0x9858, 0x300c, 0x28e1, 0x9c91, 0x2802, 0xa206, 0x64c3,
+ 0x282e, 0xa207, 0x64a0, 0x6de0, 0x67a0, 0x6fc0, 0x1814, 0x883b,
+ 0x7824, 0x68c1, 0x7864, 0x883e, 0x9879, 0x8576, 0x8677, 0x206b,
+ 0x28c1, 0x9cae, 0x2044, 0x2103, 0x20a2, 0x2081, 0x9865, 0xa209,
+ 0x2901, 0x988d, 0x0014, 0xa205, 0xa300, 0x1872, 0x879a, 0x883c,
+ 0x1fe2, 0xc601, 0xa20a, 0x856e, 0x0704, 0x9c91, 0x0014, 0xa204,
+ 0xa300, 0x3009, 0x19e2, 0xf864, 0x856e, 0x883f, 0x08e6, 0x9891,
+ 0xf881, 0x988c, 0xc801, 0x0014, 0xf8c1, 0x0016, 0x85b2, 0x80f0,
+ 0x9532, 0xfb02, 0x1de2, 0x0014, 0x8532, 0xf241, 0x0014, 0x1de2,
+ 0x84a8, 0xd7a0, 0x1fe6, 0x0014, 0xa208, 0x6043, 0x8008, 0x1dc1,
+ 0x0016, 0x8300, 0x8160, 0x842a, 0xf041, 0x3008, 0x84a8, 0x11d6,
+ 0x7042, 0x20dd, 0x0011, 0x20d5, 0x8822, 0x0016, 0x8000, 0x2847,
+ 0x1011, 0x98c0, 0x8000, 0xa000, 0x2802, 0x1011, 0x98c6, 0x9865,
+ 0x283e, 0x1011, 0x98ca, 0xa20b, 0x0017, 0x300c, 0xa300, 0x1de2,
+ 0xdb81, 0x0014, 0x0210, 0x98d7, 0x0014, 0x26e0, 0x873a, 0xfb02,
+ 0x19f2, 0x1fe2, 0x0014, 0xa20d, 0x3806, 0x0210, 0x9cb3, 0x0704,
+ 0x0000, 0x006c, 0x0002, 0x984f, 0x0014, 0x009e, 0x00a0, 0x0017,
+ 0x60ff, 0x300c, 0x8720, 0xa211, 0x9cd0, 0x8772, 0x8837, 0x2101,
+ 0x987a, 0x10d2, 0x78e2, 0x9cd3, 0x9859, 0xd984, 0xf0e2, 0xf0a1,
+ 0x98cd, 0x0014, 0x8831, 0xd166, 0x8830, 0x800f, 0x9401, 0xb520,
+ 0xc802, 0x8820, 0x987a, 0x2301, 0x987a, 0x10d2, 0x78e4, 0x9cd3,
+ 0x8821, 0x8820, 0x9859, 0xf123, 0xf142, 0xf101, 0x98c6, 0x10d2,
+ 0x70f6, 0x8832, 0x8203, 0x870c, 0xd99e, 0x6001, 0x0014, 0x6845,
+ 0x0214, 0xa21b, 0x9cd0, 0x2001, 0x98c5, 0x8201, 0x1852, 0xd184,
+ 0xd163, 0x8834, 0x8001, 0x988d, 0x3027, 0x84a8, 0x1a56, 0x8833,
+ 0x0014, 0xa218, 0x6981, 0x9cbc, 0x6926, 0x6902, 0x1a34, 0x9899,
+ 0x1a14, 0x7021, 0x0014, 0xa300, 0x6141, 0x6964, 0x8010, 0x8592,
+ 0x8026, 0x84b9, 0x69e4, 0x8023, 0x16e1, 0x8001, 0x10f1, 0x6946,
+ 0xa213, 0x1462, 0xa213, 0x8000, 0x16e1, 0x98b5, 0x6969, 0xa214,
+ 0x61c2, 0x8002, 0x14e1, 0x8004, 0x16e1, 0x0101, 0x300a, 0x8827,
+ 0x0014, 0xa217, 0x9cbc, 0x0014, 0xa300, 0x8181, 0x842a, 0x84a8,
+ 0x1ce6, 0x882c, 0x0016, 0xa212, 0x9cd0, 0x10d2, 0x70e4, 0x0004,
+ 0x8007, 0x9424, 0xcc1a, 0x9cd3, 0x98c5, 0x8827, 0x300a, 0x0013,
+ 0x8000, 0x84a4, 0x0016, 0x11c2, 0x211e, 0x870e, 0xa21d, 0x0014,
+ 0x878e, 0x0016, 0xa21c, 0x1035, 0x9891, 0xa210, 0xa000, 0x8010,
+ 0x8592, 0x853b, 0xd044, 0x8022, 0x3807, 0x84bb, 0x98ea, 0x8021,
+ 0x3807, 0x84b9, 0x300c, 0x817e, 0x872b, 0x8772, 0x9891, 0x0000,
+ 0x0020, 0x002b, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
+ 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
+ 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
+ 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
+ 0x0000, 0x0020, 0x0000, 0x0014, 0x0014, 0x9849, 0x0014, 0x0014,
+ 0x98e2, 0x98cd, 0x0014, 0x0014, 0x0014, 0x0080, 0x0137, 0x0000,
+ 0x0201, 0x0604, 0x0c08, 0x2120, 0x4022, 0xf880, 0x0018, 0x300b,
+ 0xa201, 0x0014, 0xa200, 0x0014, 0xa200, 0x0214, 0xa202, 0x8838,
+ 0x3806, 0x8839, 0x20c3, 0x0864, 0xa82f, 0x28c1, 0x9cae, 0xa203,
+ 0x300c, 0x2846, 0x8161, 0x846a, 0x8300, 0x1856, 0x883a, 0xa804,
+ 0x28f2, 0x9c91, 0xa8f4, 0x300c, 0x28e1, 0x9c91, 0x2802, 0xa206,
+ 0x64c3, 0x282e, 0xa207, 0x64a0, 0x6de0, 0x67a0, 0x6fc0, 0x1814,
+ 0x883b, 0x7824, 0x68c1, 0x7864, 0x883e, 0xa802, 0x8576, 0x8677,
+ 0x206b, 0x28c1, 0x9cae, 0x2044, 0x2103, 0x20a2, 0x2081, 0xa8e4,
+ 0xa209, 0x2901, 0xa809, 0x0014, 0xa205, 0xa300, 0x1872, 0x879a,
+ 0x883c, 0x1fe2, 0xc601, 0xa20a, 0x856e, 0x0704, 0x9c91, 0x0014,
+ 0xa204, 0xa300, 0x3009, 0x19e2, 0xf864, 0x856e, 0x883f, 0x08e6,
+ 0xa8f7, 0xf881, 0xa8f0, 0xc801, 0x0014, 0xf8c1, 0x0016, 0x85b2,
+ 0x80f0, 0x9532, 0xfb02, 0x1de2, 0x0014, 0x8532, 0xf241, 0x0014,
+ 0x1de2, 0x84a8, 0xd7a0, 0x1fe6, 0x0014, 0xa208, 0x6043, 0x8008,
+ 0x1dc1, 0x0016, 0x8300, 0x8160, 0x842a, 0xf041, 0x3008, 0x84a8,
+ 0x11d6, 0x7042, 0x20dd, 0x0011, 0x20d5, 0x8822, 0x0016, 0x8000,
+ 0x2847, 0x1011, 0xa8fc, 0x8000, 0xa000, 0x2802, 0x1011, 0xa8fd,
+ 0xa89b, 0x283e, 0x1011, 0xa8fd, 0xa20b, 0x0017, 0x300c, 0xa300,
+ 0x1de2, 0xdb81, 0x0014, 0x0210, 0xa801, 0x0014, 0x26e0, 0x873a,
+ 0xfb02, 0x19f2, 0x1fe2, 0x0014, 0xa20d, 0x3806, 0x0210, 0x9cb3,
+ 0x0704, 0x0017, 0x60ff, 0x300c, 0x8720, 0xa211, 0x9d63, 0x8772,
+ 0x8837, 0x2101, 0xa821, 0x10d2, 0x78e2, 0x9d66, 0xa8fc, 0xd984,
+ 0xf0e2, 0xf0a1, 0xa86c, 0x0014, 0x8831, 0xd166, 0x8830, 0x800f,
+ 0x9401, 0xb520, 0xc802, 0x8820, 0xa80f, 0x2301, 0xa80d, 0x10d2,
+ 0x78e4, 0x9d66, 0x8821, 0x8820, 0xa8e6, 0xf123, 0xf142, 0xf101,
+ 0xa84f, 0x10d2, 0x70f6, 0x8832, 0x8203, 0x870c, 0xd99e, 0x6001,
+ 0x0014, 0x6845, 0x0214, 0xa21b, 0x9d63, 0x2001, 0xa840, 0x8201,
+ 0x1852, 0xd184, 0xd163, 0x8834, 0x8001, 0xa801, 0x3027, 0x84a8,
+ 0x1a56, 0x8833, 0x0014, 0xa218, 0x6981, 0x9d4f, 0x6926, 0x6902,
+ 0x1a34, 0xa801, 0x1a14, 0x7021, 0x0014, 0xa300, 0x6141, 0x6964,
+ 0x8010, 0x8592, 0x8026, 0x84b9, 0x69e4, 0x8023, 0x16e1, 0x8001,
+ 0x10f1, 0x6946, 0xa213, 0x1462, 0xa213, 0x8000, 0x16e1, 0xa807,
+ 0x6969, 0xa214, 0x61c2, 0x8002, 0x14e1, 0x8004, 0x16e1, 0x0101,
+ 0x300a, 0x8827, 0x0014, 0xa217, 0x9d4f, 0x0014, 0xa300, 0x8181,
+ 0x842a, 0x84a8, 0x1ce6, 0x882c, 0x0016, 0xa212, 0x9d63, 0x10d2,
+ 0x70e4, 0x0004, 0x8007, 0x9424, 0xcc1a, 0x9d66, 0xa8f8, 0x8827,
+ 0x300a, 0x0013, 0x8000, 0x84a4, 0x0016, 0x11c2, 0x211e, 0x870e,
+ 0xa21d, 0x0014, 0x878e, 0x0016, 0xa21c, 0x1035, 0xa8b4, 0xa210,
+ 0x3807, 0x300c, 0x817e, 0x872b, 0x8772, 0xa8ad, 0x0000, 0x0d0c
};
-static unsigned short risc_code_length01 = 0x4057;
-
+static unsigned short risc_code_length01 = 0x4158;
diff --git a/drivers/scsi/ql12160_fw.h b/drivers/scsi/ql12160_fw.h
index 9db6a208c9f..d89dac0cc9d 100644
--- a/drivers/scsi/ql12160_fw.h
+++ b/drivers/scsi/ql12160_fw.h
@@ -22,19 +22,19 @@
************************************************************************/
/*
- * Firmware Version 10.04.32 (12:03 May 09, 2001)
+ * Firmware Version 10.04.42 (15:44 Apr 18, 2003)
*/
#ifdef UNIQUE_FW_NAME
-static unsigned char fw12160i_version_str[] = {10,4,32};
+static unsigned char fw12160i_version_str[] = {10,4,42};
#else
-static unsigned char firmware_version[] = {10,4,32};
+static unsigned char firmware_version[] = {10,4,42};
#endif
#ifdef UNIQUE_FW_NAME
-#define fw12160i_VERSION_STRING "10.04.32"
+#define fw12160i_VERSION_STRING "10.04.42"
#else
-#define FW_VERSION_STRING "10.04.32"
+#define FW_VERSION_STRING "10.04.42"
#endif
#ifdef UNIQUE_FW_NAME
@@ -48,7 +48,7 @@ static unsigned short fw12160i_code01[] = {
#else
static unsigned short risc_code01[] = {
#endif
- 0x0804, 0x1041, 0x0000, 0x35e6, 0x0000, 0x2043, 0x4f50, 0x5952,
+ 0x0804, 0x1041, 0x0000, 0x36c9, 0x0000, 0x2043, 0x4f50, 0x5952,
0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932, 0x2c31,
0x3939, 0x332c, 0x3139, 0x3934, 0x2051, 0x4c4f, 0x4749, 0x4320,
0x434f, 0x5250, 0x4f52, 0x4154, 0x494f, 0x4e00, 0x2049, 0x5350,
@@ -56,112 +56,112 @@ static unsigned short risc_code01[] = {
0x6572, 0x7369, 0x6f6e, 0x2031, 0x302e, 0x3034, 0x2020, 0x2043,
0x7573, 0x746f, 0x6d65, 0x7220, 0x4e6f, 0x2e20, 0x3030, 0x2050,
0x726f, 0x6475, 0x6374, 0x204e, 0x6f2e, 0x2020, 0x3030, 0x2020,
- 0x2400, 0x20c9, 0x8fff, 0x2071, 0x0200, 0x70a0, 0x70a2, 0x2001,
+ 0x2400, 0x20c9, 0x90ff, 0x2071, 0x0200, 0x70a0, 0x70a2, 0x2001,
0x01ff, 0x2004, 0xd0fc, 0x1120, 0x2071, 0x0100, 0x70a0, 0x70a2,
0x20c1, 0x0020, 0x2089, 0x1221, 0x2071, 0x0010, 0x70c3, 0x0004,
0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3, 0x000a,
0x2001, 0x04fd, 0x2004, 0x70d6, 0x2009, 0xfeff, 0x2130, 0x2128,
- 0xa1a2, 0x4600, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424,
- 0xa192, 0x9000, 0x2009, 0x0000, 0x2001, 0x0032, 0x080c, 0x1de8,
- 0x2218, 0x2079, 0x4600, 0x2fa0, 0x2408, 0x2011, 0x0000, 0x20a9,
+ 0xa1a2, 0x4700, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424,
+ 0xa192, 0x9100, 0x2009, 0x0000, 0x2001, 0x0032, 0x080c, 0x1e05,
+ 0x2218, 0x2079, 0x4700, 0x2fa0, 0x2408, 0x2011, 0x0000, 0x20a9,
0x0040, 0x42a4, 0x8109, 0x1dd8, 0x2009, 0xff00, 0x3400, 0xa102,
0x0218, 0x0110, 0x20a8, 0x42a4, 0x781b, 0x0064, 0x7814, 0xc0cd,
- 0xc0d5, 0x7816, 0x2071, 0x0200, 0x00d6, 0x2069, 0x4640, 0x080c,
- 0x459a, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1130, 0x2069, 0x4680,
- 0x2071, 0x0100, 0x080c, 0x459a, 0x7814, 0xc0d4, 0x7816, 0x00de,
+ 0xc0d5, 0x7816, 0x2071, 0x0200, 0x00d6, 0x2069, 0x4740, 0x080c,
+ 0x465c, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1130, 0x2069, 0x4780,
+ 0x2071, 0x0100, 0x080c, 0x465c, 0x7814, 0xc0d4, 0x7816, 0x00de,
0x7eca, 0x7cc2, 0x7bc6, 0x7867, 0x0000, 0x7800, 0xc08d, 0x7802,
0x2031, 0x0030, 0x78af, 0x0101, 0x7823, 0x0002, 0x7827, 0x0002,
- 0x2009, 0x0002, 0x2069, 0x4640, 0x681b, 0x0003, 0x6823, 0x0007,
+ 0x2009, 0x0002, 0x2069, 0x4740, 0x681b, 0x0003, 0x6823, 0x0007,
0x6827, 0x00fa, 0x682b, 0x0008, 0x682f, 0x0028, 0x6837, 0x0006,
0x6833, 0x0008, 0x683b, 0x0000, 0x8109, 0x0500, 0x68cf, 0x000a,
- 0x68bf, 0x46c0, 0x2079, 0x4600, 0x68d3, 0x762d, 0x68c3, 0x4bc0,
- 0x68c7, 0x4ac0, 0x68cb, 0x8bc0, 0x68a7, 0x8e44, 0x68ab, 0x8e49,
- 0x68af, 0x8e44, 0x68b3, 0x8e44, 0x68a3, 0x0001, 0x2001, 0x01ff,
- 0x2004, 0xd0fc, 0x11c8, 0x2069, 0x4680, 0x0870, 0x68cf, 0x000a,
- 0x68bf, 0x48c0, 0x68d3, 0x7839, 0x68c3, 0x6bc0, 0x68c7, 0x4b40,
- 0x68cb, 0x8cd0, 0x68a7, 0x8e49, 0x68ab, 0x8e4e, 0x68af, 0x8e49,
- 0x68b3, 0x8e49, 0x68a3, 0x0001, 0x00e6, 0x2069, 0x4ac0, 0x2071,
+ 0x68bf, 0x47c0, 0x2079, 0x4700, 0x68d3, 0x762d, 0x68c3, 0x4cc0,
+ 0x68c7, 0x4bc0, 0x68cb, 0x8cc0, 0x68a7, 0x8f44, 0x68ab, 0x8f49,
+ 0x68af, 0x8f44, 0x68b3, 0x8f44, 0x68a3, 0x0001, 0x2001, 0x01ff,
+ 0x2004, 0xd0fc, 0x11c8, 0x2069, 0x4780, 0x0870, 0x68cf, 0x000a,
+ 0x68bf, 0x49c0, 0x68d3, 0x7839, 0x68c3, 0x6cc0, 0x68c7, 0x4c40,
+ 0x68cb, 0x8dd0, 0x68a7, 0x8f49, 0x68ab, 0x8f4e, 0x68af, 0x8f49,
+ 0x68b3, 0x8f49, 0x68a3, 0x0001, 0x00e6, 0x2069, 0x4bc0, 0x2071,
0x0200, 0x70ec, 0xd0e4, 0x2019, 0x1809, 0x2021, 0x0009, 0x1120,
- 0x2019, 0x180c, 0x2021, 0x000c, 0x080c, 0x1d58, 0x2001, 0x01ff,
- 0x2004, 0xd0fc, 0x1188, 0x2069, 0x4b40, 0x2071, 0x0100, 0x70ec,
+ 0x2019, 0x180c, 0x2021, 0x000c, 0x080c, 0x1d75, 0x2001, 0x01ff,
+ 0x2004, 0xd0fc, 0x1188, 0x2069, 0x4c40, 0x2071, 0x0100, 0x70ec,
0xd0e4, 0x2019, 0x1809, 0x2021, 0x0009, 0x1120, 0x2019, 0x180c,
- 0x2021, 0x000c, 0x080c, 0x1d58, 0x00ee, 0x2011, 0x0002, 0x2069,
- 0x4bc0, 0x2009, 0x0002, 0x20a9, 0x0100, 0x6837, 0x0000, 0x680b,
+ 0x2021, 0x000c, 0x080c, 0x1d75, 0x00ee, 0x2011, 0x0002, 0x2069,
+ 0x4cc0, 0x2009, 0x0002, 0x20a9, 0x0100, 0x6837, 0x0000, 0x680b,
0x0040, 0x7bc8, 0xa386, 0xfeff, 0x1128, 0x6817, 0x0100, 0x681f,
0x0064, 0x0020, 0x6817, 0x0064, 0x681f, 0x0002, 0xade8, 0x0010,
0x1f04, 0x1135, 0x8109, 0x1d38, 0x2001, 0x01ff, 0x2004, 0xd0fc,
- 0x1128, 0x8211, 0x0118, 0x2069, 0x6bc0, 0x08d8, 0x080c, 0x22cf,
- 0x080c, 0x4015, 0x080c, 0x1b6d, 0x080c, 0x4553, 0x2091, 0x2200,
- 0x2079, 0x4600, 0x2071, 0x0050, 0x2091, 0x2400, 0x2079, 0x4600,
- 0x2071, 0x0020, 0x2091, 0x2600, 0x2079, 0x0200, 0x2071, 0x4640,
- 0x2091, 0x2800, 0x2079, 0x0100, 0x2071, 0x4680, 0x2091, 0x2000,
- 0x2079, 0x4600, 0x2071, 0x0010, 0x3200, 0xa085, 0x303d, 0x2090,
+ 0x1128, 0x8211, 0x0118, 0x2069, 0x6cc0, 0x08d8, 0x080c, 0x22f6,
+ 0x080c, 0x403d, 0x080c, 0x1b8c, 0x080c, 0x4615, 0x2091, 0x2200,
+ 0x2079, 0x4700, 0x2071, 0x0050, 0x2091, 0x2400, 0x2079, 0x4700,
+ 0x2071, 0x0020, 0x2091, 0x2600, 0x2079, 0x0200, 0x2071, 0x4740,
+ 0x2091, 0x2800, 0x2079, 0x0100, 0x2071, 0x4780, 0x2091, 0x2000,
+ 0x2079, 0x4700, 0x2071, 0x0010, 0x3200, 0xa085, 0x303d, 0x2090,
0x2071, 0x0010, 0x70c3, 0x0000, 0x1004, 0x118c, 0x70c0, 0xa086,
0x0002, 0x1110, 0x080c, 0x13ba, 0x2039, 0x0000, 0x080c, 0x12ab,
0x78ac, 0xa005, 0x1180, 0x0e04, 0x119a, 0x786c, 0xa065, 0x0110,
- 0x080c, 0x207a, 0x080c, 0x1e09, 0x0e04, 0x11af, 0x786c, 0xa065,
- 0x0110, 0x080c, 0x207a, 0x0e04, 0x11af, 0x2009, 0x4647, 0x2011,
- 0x4687, 0x2104, 0x220c, 0xa105, 0x0110, 0x080c, 0x1c7c, 0x2071,
- 0x4640, 0x70a0, 0xa005, 0x01e8, 0x744c, 0xa485, 0x0000, 0x01c8,
+ 0x080c, 0x20a1, 0x080c, 0x1e26, 0x0e04, 0x11af, 0x786c, 0xa065,
+ 0x0110, 0x080c, 0x20a1, 0x0e04, 0x11af, 0x2009, 0x4747, 0x2011,
+ 0x4787, 0x2104, 0x220c, 0xa105, 0x0110, 0x080c, 0x1c9b, 0x2071,
+ 0x4740, 0x70a0, 0xa005, 0x01e8, 0x744c, 0xa485, 0x0000, 0x01c8,
0x2079, 0x0200, 0x2091, 0x8000, 0x72d0, 0xa28c, 0x303d, 0x2190,
- 0x080c, 0x2720, 0x2091, 0x8000, 0x2091, 0x303d, 0x0e04, 0x11d1,
- 0x2079, 0x4600, 0x786c, 0xa065, 0x0120, 0x2071, 0x0010, 0x080c,
- 0x207a, 0x1d04, 0x11d9, 0x2079, 0x4600, 0x2071, 0x0010, 0x080c,
- 0x4370, 0x2071, 0x4680, 0x70a0, 0xa005, 0x0188, 0x704c, 0xa025,
+ 0x080c, 0x274c, 0x2091, 0x8000, 0x2091, 0x303d, 0x0e04, 0x11d1,
+ 0x2079, 0x4700, 0x786c, 0xa065, 0x0120, 0x2071, 0x0010, 0x080c,
+ 0x20a1, 0x1d04, 0x11d9, 0x2079, 0x4700, 0x2071, 0x0010, 0x080c,
+ 0x4429, 0x2071, 0x4780, 0x70a0, 0xa005, 0x0188, 0x704c, 0xa025,
0x0170, 0x2079, 0x0100, 0x2091, 0x8000, 0x72d0, 0xa28c, 0x303d,
- 0x2190, 0x080c, 0x2720, 0x2091, 0x8000, 0x2091, 0x303d, 0x2079,
- 0x4600, 0x2071, 0x0010, 0x0e04, 0x11fa, 0x786c, 0xa065, 0x0110,
- 0x080c, 0x207a, 0x1d04, 0x118e, 0x080c, 0x4370, 0x0804, 0x118e,
+ 0x2190, 0x080c, 0x274c, 0x2091, 0x8000, 0x2091, 0x303d, 0x2079,
+ 0x4700, 0x2071, 0x0010, 0x0e04, 0x11fa, 0x786c, 0xa065, 0x0110,
+ 0x080c, 0x20a1, 0x1d04, 0x118e, 0x080c, 0x4429, 0x0804, 0x118e,
0x3c00, 0xa084, 0x0007, 0x0002, 0x120c, 0x120c, 0x120e, 0x120e,
- 0x1213, 0x1213, 0x1218, 0x1218, 0x080c, 0x254c, 0x2091, 0x2400,
- 0x080c, 0x40ad, 0x0005, 0x2091, 0x2200, 0x080c, 0x40ad, 0x0005,
- 0x2091, 0x2200, 0x080c, 0x40ad, 0x2091, 0x2400, 0x080c, 0x40ad,
+ 0x1213, 0x1213, 0x1218, 0x1218, 0x080c, 0x2575, 0x2091, 0x2400,
+ 0x080c, 0x40d5, 0x0005, 0x2091, 0x2200, 0x080c, 0x40d5, 0x0005,
+ 0x2091, 0x2200, 0x080c, 0x40d5, 0x2091, 0x2400, 0x080c, 0x40d5,
0x0005, 0x1241, 0x1241, 0x1242, 0x1242, 0x124d, 0x124d, 0x124d,
0x124d, 0x1256, 0x1256, 0x1261, 0x1261, 0x124d, 0x124d, 0x124d,
0x124d, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270,
0x1270, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270,
0x1270, 0x0cf8, 0x0006, 0x0106, 0x0126, 0x2091, 0x2800, 0x080c,
- 0x2569, 0x012e, 0x010e, 0x000e, 0x000d, 0x0006, 0x0106, 0x0126,
+ 0x2592, 0x012e, 0x010e, 0x000e, 0x000d, 0x0006, 0x0106, 0x0126,
0x080c, 0x1200, 0x012e, 0x010e, 0x000e, 0x000d, 0x0006, 0x0106,
- 0x0126, 0x2091, 0x2600, 0x080c, 0x2569, 0x012e, 0x010e, 0x000e,
- 0x000d, 0x0006, 0x0106, 0x0126, 0x2091, 0x2600, 0x080c, 0x2569,
- 0x2091, 0x2800, 0x080c, 0x2569, 0x012e, 0x010e, 0x000e, 0x000d,
- 0x0006, 0x0106, 0x0126, 0x00d6, 0x00e6, 0x00f6, 0x2079, 0x4600,
- 0x2071, 0x0200, 0x2069, 0x4640, 0x3d00, 0xd08c, 0x0130, 0x70ec,
- 0xa084, 0x1c00, 0x78e2, 0x080c, 0x459a, 0x3d00, 0xd084, 0x0150,
- 0x2069, 0x4680, 0x2071, 0x0100, 0x70ec, 0xa084, 0x1c00, 0x78e6,
- 0x080c, 0x459a, 0x080c, 0x24fd, 0x00fe, 0x00ee, 0x00de, 0x012e,
+ 0x0126, 0x2091, 0x2600, 0x080c, 0x2592, 0x012e, 0x010e, 0x000e,
+ 0x000d, 0x0006, 0x0106, 0x0126, 0x2091, 0x2600, 0x080c, 0x2592,
+ 0x2091, 0x2800, 0x080c, 0x2592, 0x012e, 0x010e, 0x000e, 0x000d,
+ 0x0006, 0x0106, 0x0126, 0x00d6, 0x00e6, 0x00f6, 0x2079, 0x4700,
+ 0x2071, 0x0200, 0x2069, 0x4740, 0x3d00, 0xd08c, 0x0130, 0x70ec,
+ 0xa084, 0x1c00, 0x78e2, 0x080c, 0x465c, 0x3d00, 0xd084, 0x0150,
+ 0x2069, 0x4780, 0x2071, 0x0100, 0x70ec, 0xa084, 0x1c00, 0x78e6,
+ 0x080c, 0x465c, 0x080c, 0x2526, 0x00fe, 0x00ee, 0x00de, 0x012e,
0x010e, 0x000e, 0x000d, 0x7008, 0x800b, 0x1240, 0x7007, 0x0002,
0xa08c, 0x01e0, 0x1120, 0xd09c, 0x0108, 0x0887, 0x0897, 0x70c3,
0x4002, 0x0804, 0x13bd, 0x0e04, 0x131e, 0x2061, 0x0000, 0x6018,
0xd084, 0x1904, 0x131e, 0x7828, 0xa005, 0x1120, 0x0004, 0x131f,
- 0x0804, 0x131e, 0xd0fc, 0x0130, 0x0006, 0x080c, 0x1b0a, 0x000e,
- 0x0150, 0x0028, 0x0006, 0x080c, 0x1aff, 0x000e, 0x0120, 0x2001,
- 0x4007, 0x0804, 0x13bc, 0x7910, 0xd0fc, 0x1128, 0x2061, 0x4640,
- 0xc19c, 0xc7fc, 0x0020, 0x2061, 0x4680, 0xc19d, 0xc7fd, 0x6060,
+ 0x0804, 0x131e, 0xd0fc, 0x0130, 0x0006, 0x080c, 0x1b29, 0x000e,
+ 0x0150, 0x0028, 0x0006, 0x080c, 0x1b1e, 0x000e, 0x0120, 0x2001,
+ 0x4007, 0x0804, 0x13bc, 0x7910, 0xd0fc, 0x1128, 0x2061, 0x4740,
+ 0xc19c, 0xc7fc, 0x0020, 0x2061, 0x4780, 0xc19d, 0xc7fd, 0x6060,
0xa005, 0x1904, 0x131e, 0x7912, 0x607e, 0x7828, 0xc0fc, 0xa086,
- 0x0018, 0x1120, 0x00c6, 0x080c, 0x1916, 0x00ce, 0x782b, 0x0000,
- 0x6078, 0xa065, 0x01e0, 0x00c6, 0x609c, 0x080c, 0x1bd4, 0x00ce,
- 0x609f, 0x0000, 0x080c, 0x1a41, 0x2009, 0x0018, 0x6087, 0x0103,
+ 0x0018, 0x1120, 0x00c6, 0x080c, 0x1926, 0x00ce, 0x782b, 0x0000,
+ 0x6078, 0xa065, 0x01e0, 0x00c6, 0x609c, 0x080c, 0x1bf3, 0x00ce,
+ 0x609f, 0x0000, 0x080c, 0x1a60, 0x2009, 0x0018, 0x6087, 0x0103,
0x7810, 0x0006, 0x84ff, 0x1110, 0x85ff, 0x0110, 0xc0c5, 0x7812,
- 0x080c, 0x1b15, 0x000e, 0x7812, 0x1198, 0x080c, 0x1b60, 0x7810,
- 0xd09c, 0x1118, 0x2061, 0x4640, 0x0020, 0x2061, 0x4680, 0xc09c,
+ 0x080c, 0x1b34, 0x000e, 0x7812, 0x1198, 0x080c, 0x1b7f, 0x7810,
+ 0xd09c, 0x1118, 0x2061, 0x4740, 0x0020, 0x2061, 0x4780, 0xc09c,
0x7812, 0x607b, 0x0000, 0x60d0, 0xd0c4, 0x0130, 0xc0c4, 0x60d2,
0x2001, 0x4005, 0x0804, 0x13bc, 0x0804, 0x13ba, 0x0005, 0xa006,
0x70c2, 0x70c6, 0x70ca, 0x70ce, 0x70da, 0x70c0, 0xa03d, 0xa08a,
0x0040, 0x1a04, 0x136c, 0x0002, 0x13ba, 0x1408, 0x13d6, 0x143c,
- 0x1470, 0x1470, 0x13ce, 0x1a59, 0x147a, 0x13c8, 0x13da, 0x13db,
- 0x13dc, 0x13dd, 0x1a5d, 0x13c8, 0x1487, 0x14db, 0x1931, 0x1a53,
- 0x13de, 0x17ba, 0x17f0, 0x1822, 0x1868, 0x1777, 0x1784, 0x1797,
- 0x17a9, 0x15b0, 0x13c8, 0x150d, 0x1518, 0x1526, 0x1534, 0x154b,
- 0x1559, 0x155c, 0x156a, 0x1578, 0x1582, 0x1596, 0x15a2, 0x13c8,
- 0x13c8, 0x13c8, 0x13c8, 0x15bd, 0x15ce, 0x15e8, 0x161c, 0x1645,
- 0x1657, 0x165a, 0x1685, 0x16be, 0x16d0, 0x1745, 0x1755, 0x13c8,
- 0x13c8, 0x13c8, 0x13c8, 0x1767, 0x2100, 0xa08a, 0x0040, 0x1a04,
- 0x13c8, 0x0002, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x1a7f,
- 0x1a85, 0x13c8, 0x13c8, 0x13c8, 0x1a89, 0x1ac9, 0x13c8, 0x13c8,
- 0x13c8, 0x13c8, 0x1403, 0x146b, 0x1482, 0x14d6, 0x192c, 0x13c8,
- 0x13c8, 0x18fb, 0x13c8, 0x1acd, 0x1a71, 0x1a7b, 0x13c8, 0x13c8,
+ 0x1470, 0x1470, 0x13ce, 0x1a78, 0x147a, 0x13c8, 0x13da, 0x13db,
+ 0x13dc, 0x13dd, 0x1a7c, 0x13c8, 0x1487, 0x14db, 0x1941, 0x1a72,
+ 0x13de, 0x17c8, 0x17fe, 0x1830, 0x1876, 0x1785, 0x1792, 0x17a5,
+ 0x17b7, 0x15bf, 0x13c8, 0x150d, 0x1518, 0x1526, 0x1534, 0x154b,
+ 0x1559, 0x155c, 0x156e, 0x157c, 0x1586, 0x15a5, 0x15b1, 0x13c8,
+ 0x13c8, 0x13c8, 0x13c8, 0x15cc, 0x15dd, 0x15f7, 0x162b, 0x1654,
+ 0x1666, 0x1669, 0x1693, 0x16cc, 0x16de, 0x1753, 0x1763, 0x13c8,
+ 0x13c8, 0x13c8, 0x13c8, 0x1775, 0x2100, 0xa08a, 0x0040, 0x1a04,
+ 0x13c8, 0x0002, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x1a9e,
+ 0x1aa4, 0x13c8, 0x13c8, 0x13c8, 0x1aa8, 0x1ae8, 0x13c8, 0x13c8,
+ 0x13c8, 0x13c8, 0x1403, 0x146b, 0x1482, 0x14d6, 0x193c, 0x13c8,
+ 0x13c8, 0x190b, 0x13c8, 0x1aec, 0x1a90, 0x1a9a, 0x13c8, 0x13c8,
0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8,
0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8,
0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8,
@@ -191,7 +191,7 @@ static unsigned short risc_code01[] = {
0x0001, 0x7008, 0xd0fc, 0x0de8, 0xa084, 0x01e0, 0x0d48, 0x70c3,
0x4002, 0x0804, 0x13bd, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0878,
0x71c4, 0x70c8, 0x2114, 0xa79e, 0x0004, 0x1108, 0x200a, 0x72ca,
- 0x0804, 0x13b9, 0x70c7, 0x000a, 0x70cb, 0x0004, 0x70cf, 0x0020,
+ 0x0804, 0x13b9, 0x70c7, 0x000a, 0x70cb, 0x0004, 0x70cf, 0x002a,
0x0804, 0x13ba, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0018, 0x2029,
0x0000, 0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d0, 0x70c6, 0x72ca,
0x73ce, 0x74d2, 0xa005, 0x05e8, 0xa40a, 0x0108, 0x1240, 0x8001,
@@ -211,1281 +211,1286 @@ static unsigned short risc_code01[] = {
0xc2c5, 0x7a12, 0x7c96, 0x78ac, 0xa084, 0xfcff, 0x78ae, 0x0018,
0x78ac, 0xc0c5, 0x78ae, 0x0804, 0x13ba, 0x2009, 0x0000, 0x786c,
0xa065, 0x0118, 0x8108, 0x6000, 0x0cd8, 0x7ac4, 0x0804, 0x13b8,
- 0x2009, 0x4648, 0x210c, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904,
- 0x13b9, 0x2011, 0x4688, 0x2214, 0x0804, 0x13b8, 0x2009, 0x4649,
+ 0x2009, 0x4748, 0x210c, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904,
+ 0x13b9, 0x2011, 0x4788, 0x2214, 0x0804, 0x13b8, 0x2009, 0x4749,
0x210c, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9, 0x2011,
- 0x4689, 0x2214, 0x0804, 0x13b8, 0x2061, 0x4640, 0x6128, 0x622c,
+ 0x4789, 0x2214, 0x0804, 0x13b8, 0x2061, 0x4740, 0x6128, 0x622c,
0x8214, 0x8214, 0x8214, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1148,
- 0x2061, 0x4680, 0x6328, 0x73da, 0x632c, 0x831c, 0x831c, 0x831c,
- 0x73de, 0x0804, 0x13b8, 0x2009, 0x464c, 0x210c, 0x2001, 0x01ff,
- 0x2004, 0xd0fc, 0x1904, 0x13b9, 0x2011, 0x468c, 0x2214, 0x0804,
- 0x13b8, 0x7918, 0x0804, 0x13b9, 0x2009, 0x0202, 0x210c, 0x2001,
- 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9, 0x2011, 0x0102, 0x2214,
- 0x0804, 0x13b8, 0x2009, 0x464d, 0x210c, 0x2001, 0x01ff, 0x2004,
- 0xd0fc, 0x1904, 0x13b9, 0x2011, 0x468d, 0x2214, 0x0804, 0x13b8,
- 0x7920, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9, 0x7a24,
- 0x0804, 0x13b8, 0x2011, 0x4b40, 0x71c4, 0xd1fc, 0x1110, 0x2011,
- 0x4ac0, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa268,
- 0x6a00, 0x6b08, 0x6c1c, 0x74da, 0x0804, 0x13b7, 0x77c4, 0x080c,
- 0x1b7b, 0x2091, 0x8000, 0x6b1c, 0x6a14, 0x2091, 0x8001, 0x2708,
- 0x0804, 0x13b7, 0x2061, 0x4640, 0x6118, 0x2001, 0x01ff, 0x2004,
- 0xd0fc, 0x1904, 0x13b9, 0x2061, 0x4680, 0x6218, 0x0804, 0x13b8,
- 0x77c4, 0x080c, 0x1b7b, 0x2091, 0x8000, 0x6908, 0x6a18, 0x6b10,
- 0x77da, 0x2091, 0x8001, 0x0804, 0x13b7, 0x71c4, 0x2110, 0xa294,
- 0x000f, 0xa282, 0x0010, 0x1a04, 0x13b3, 0x080c, 0x238b, 0xa384,
- 0x4000, 0x0110, 0xa295, 0x0020, 0x0804, 0x13b7, 0x71c4, 0x2100,
- 0xc0bc, 0xa082, 0x0010, 0x1a04, 0x13b3, 0xd1bc, 0x1120, 0x2011,
- 0x4648, 0x2204, 0x0020, 0x2011, 0x4688, 0x2204, 0xc0bd, 0x0006,
- 0x2100, 0xc0bc, 0x2012, 0x080c, 0x2331, 0x001e, 0x0804, 0x13b9,
- 0x71c4, 0x2021, 0x4649, 0x2404, 0x70c6, 0x2019, 0x0000, 0x0030,
- 0x71c8, 0x2021, 0x4689, 0x2404, 0x70ca, 0xc3fd, 0x2011, 0x1614,
- 0x20a9, 0x0008, 0x2204, 0xa106, 0x0138, 0x8210, 0x1f04, 0x15fa,
- 0x71c4, 0x72c8, 0x0804, 0x13b2, 0xa292, 0x1614, 0x0026, 0x2122,
- 0x001e, 0x080c, 0x2343, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1110,
- 0xd3fc, 0x09f0, 0x0804, 0x13ba, 0x03e8, 0x00fa, 0x01f4, 0x02ee,
- 0x0004, 0x0001, 0x0002, 0x0003, 0x2061, 0x4640, 0x6128, 0x622c,
- 0x8214, 0x8214, 0x8214, 0x70c4, 0x602a, 0x70c8, 0x8003, 0x8003,
- 0x8003, 0x602e, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x11a0, 0x0026,
- 0x0016, 0x2061, 0x4680, 0x6128, 0x622c, 0x8214, 0x8214, 0x8214,
- 0x70d8, 0x602a, 0x70dc, 0x8003, 0x8003, 0x8003, 0x602e, 0x71da,
- 0x72de, 0x001e, 0x002e, 0x0804, 0x13b8, 0x2061, 0x4640, 0x6130,
- 0x70c4, 0x6032, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9,
- 0x2061, 0x4680, 0x6230, 0x70c8, 0x6032, 0x0804, 0x13b8, 0x7918,
- 0x0804, 0x13b9, 0x71c4, 0xa184, 0xf0cf, 0x0148, 0x2001, 0x01ff,
- 0x2004, 0xd0fc, 0x1904, 0x13b3, 0x72c8, 0x0804, 0x13b2, 0x0006,
- 0x2019, 0x0000, 0x080c, 0x237f, 0x2001, 0x01ff, 0x2004, 0xd0fc,
- 0x0118, 0x001e, 0x0804, 0x13b9, 0x71c8, 0xa184, 0xf0cf, 0x0128,
- 0x0006, 0x2110, 0x71c4, 0x0804, 0x13b2, 0x0006, 0xc3fd, 0x080c,
- 0x237f, 0x002e, 0x001e, 0x0804, 0x13b8, 0x71c4, 0xa182, 0x0010,
- 0x0248, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b3, 0x72c8,
- 0x0804, 0x13b2, 0x2011, 0x464d, 0x2204, 0x0006, 0x8104, 0x1208,
- 0x8108, 0x2112, 0x2019, 0x0000, 0x080c, 0x236c, 0x2001, 0x01ff,
- 0x2004, 0xd0fc, 0x0118, 0x001e, 0x0804, 0x13b9, 0x71c8, 0xa182,
- 0x0010, 0x0228, 0x0006, 0x2110, 0x71c4, 0x0804, 0x13b2, 0x2011,
- 0x468d, 0x2204, 0x0006, 0x8104, 0x1208, 0x8108, 0x2112, 0xc3fd,
- 0x080c, 0x236c, 0x002e, 0x001e, 0x0804, 0x13b8, 0x71c4, 0x72c8,
- 0xa184, 0xfffd, 0x1904, 0x13b2, 0xa284, 0xfffd, 0x1904, 0x13b2,
- 0x2100, 0x7920, 0x7822, 0x2200, 0x7a24, 0x7826, 0x0804, 0x13b8,
- 0x2011, 0x4b40, 0x71c4, 0xd1fc, 0x1110, 0x2011, 0x4ac0, 0x8107,
- 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa268, 0x72c8, 0x73cc,
- 0x74d8, 0x71c6, 0x6800, 0x70ca, 0x73ce, 0x74da, 0x2091, 0x8000,
- 0x6a02, 0xd2ac, 0x1118, 0x2021, 0x0000, 0x0090, 0xa484, 0x00ff,
- 0xa082, 0x0002, 0x1a04, 0x1741, 0x843f, 0xa7bc, 0x00ff, 0x0140,
- 0xa786, 0x0002, 0x1904, 0x1741, 0xa484, 0x00ff, 0x0904, 0x1741,
- 0x2061, 0x0200, 0xd1fc, 0x0110, 0x2061, 0x0100, 0x2029, 0x0009,
- 0x2031, 0x0062, 0x843f, 0xa7bc, 0x00ff, 0x0130, 0x8307, 0xa084,
- 0x00ff, 0x1110, 0xa73d, 0x1138, 0x2041, 0x0019, 0xa384, 0x00ff,
- 0xa082, 0x001a, 0x0210, 0xa4a4, 0x00ff, 0x8307, 0xa084, 0x00ff,
- 0x0188, 0xa842, 0x02f0, 0xa086, 0x0010, 0x1120, 0xa39c, 0x00ff,
- 0xa39d, 0x0f00, 0xa3bc, 0x00ff, 0x2500, 0xa702, 0x0290, 0x2600,
- 0xa702, 0x1278, 0x2039, 0x003a, 0x6804, 0xa705, 0x6806, 0x6b0a,
- 0x6b0c, 0x73ce, 0x681c, 0x70da, 0x6c1e, 0x2091, 0x8001, 0x0804,
- 0x13ba, 0x2091, 0x8001, 0x0804, 0x13b4, 0x77c4, 0x080c, 0x1b7b,
- 0x2091, 0x8000, 0x6a14, 0x6b1c, 0x2091, 0x8001, 0x70c8, 0x6816,
- 0x70cc, 0x681e, 0x2708, 0x0804, 0x13b7, 0x70c4, 0x2061, 0x4640,
- 0x6118, 0x601a, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9,
- 0x70c8, 0x2061, 0x4680, 0x6218, 0x601a, 0x0804, 0x13b8, 0x71c4,
- 0x72c8, 0x73cc, 0xa182, 0x0010, 0x1a04, 0x13b3, 0x080c, 0x23af,
- 0xa384, 0x4000, 0x0110, 0xa295, 0x0020, 0x0804, 0x13b7, 0x77c4,
- 0x080c, 0x1b7b, 0x2091, 0x8000, 0x6a08, 0xc28d, 0x6a0a, 0x2091,
- 0x8001, 0x2708, 0x0804, 0x13b8, 0x77c4, 0x080c, 0x1b7b, 0x2091,
- 0x8000, 0x6a08, 0xa294, 0xfff9, 0x6a0a, 0x6804, 0xa005, 0x0110,
- 0x080c, 0x22ae, 0x2091, 0x8001, 0x2708, 0x0804, 0x13b8, 0x77c4,
- 0x080c, 0x1b7b, 0x2091, 0x8000, 0x6a08, 0xc295, 0x6a0a, 0x6804,
- 0xa005, 0x0110, 0x080c, 0x22ae, 0x2091, 0x8001, 0x2708, 0x0804,
- 0x13b8, 0x77c4, 0x2041, 0x0001, 0x2049, 0x0005, 0x2051, 0x0020,
- 0x2091, 0x8000, 0x080c, 0x1b93, 0x2091, 0x8001, 0x2708, 0x6a08,
- 0x0804, 0x13b8, 0x77c4, 0xd7fc, 0x0128, 0x080c, 0x1b0a, 0x0138,
- 0x0804, 0x13bc, 0x080c, 0x1aff, 0x0110, 0x0804, 0x13bc, 0x73c8,
- 0x72cc, 0x77c6, 0x73ca, 0x72ce, 0x080c, 0x1c0b, 0x11e8, 0x6818,
- 0xa005, 0x01a0, 0x2708, 0x0076, 0x080c, 0x23ce, 0x007e, 0x1170,
- 0x2001, 0x0015, 0xd7fc, 0x1118, 0x2061, 0x4640, 0x0018, 0xc0fd,
- 0x2061, 0x4680, 0x782a, 0x2091, 0x8001, 0x0005, 0x2091, 0x8001,
- 0x2001, 0x4005, 0x0804, 0x13bc, 0x2091, 0x8001, 0x0804, 0x13ba,
- 0x77c4, 0xd7fc, 0x0128, 0x080c, 0x1b0a, 0x0138, 0x0804, 0x13bc,
- 0x080c, 0x1aff, 0x0110, 0x0804, 0x13bc, 0x77c6, 0x2041, 0x0021,
- 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x080c, 0x1b93,
- 0x2009, 0x0016, 0xd7fc, 0x1118, 0x2061, 0x4640, 0x0018, 0x2061,
- 0x4680, 0xc1fd, 0x6063, 0x0003, 0x607b, 0x0000, 0x6772, 0x607f,
- 0x000f, 0x792a, 0x61d0, 0xc1c4, 0x61d2, 0x080c, 0x22ae, 0x2091,
- 0x8001, 0x0005, 0x77c8, 0x77ca, 0x77c4, 0x77c6, 0xd7fc, 0x0128,
- 0x080c, 0x1b0a, 0x0138, 0x0804, 0x13bc, 0x080c, 0x1aff, 0x0110,
- 0x0804, 0x13bc, 0xa7bc, 0xff00, 0x2091, 0x8000, 0x2009, 0x0017,
- 0xd7fc, 0x1118, 0x2061, 0x4640, 0x0018, 0x2061, 0x4680, 0xc1fd,
- 0x607b, 0x0000, 0x6063, 0x0002, 0x6772, 0x607f, 0x000f, 0x792a,
- 0x61d0, 0xc1c4, 0x61d2, 0x080c, 0x22ae, 0x2091, 0x8001, 0x2041,
- 0x0021, 0x2049, 0x0005, 0x2051, 0x0030, 0x2091, 0x8000, 0x70c8,
- 0xa005, 0x0118, 0x60d0, 0xc0fd, 0x60d2, 0x080c, 0x1b93, 0x70c8,
- 0x6836, 0x8738, 0xa784, 0x001f, 0x1dc0, 0x2091, 0x8001, 0x0005,
- 0x2019, 0x0000, 0x72c8, 0xd284, 0x0128, 0x080c, 0x1b0a, 0x0138,
- 0x0804, 0x13bc, 0x080c, 0x1aff, 0x0110, 0x0804, 0x13bc, 0x72c8,
- 0x72ca, 0x78ac, 0xa084, 0x0003, 0x1508, 0x2039, 0x0000, 0xd284,
- 0x0108, 0xc7fd, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008,
- 0x080c, 0x1b7b, 0x2091, 0x8000, 0x6808, 0xc0d4, 0xa80d, 0x690a,
- 0x2091, 0x8001, 0x8738, 0xa784, 0x001f, 0x1d90, 0xa7bc, 0xff00,
- 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x1d50, 0x2091, 0x8000,
+ 0x2061, 0x4780, 0x6328, 0x73da, 0x632c, 0x831c, 0x831c, 0x831c,
+ 0x73de, 0x0804, 0x13b8, 0x2009, 0x474c, 0x210c, 0x2001, 0x01ff,
+ 0x2004, 0xd0fc, 0x1904, 0x13b9, 0x2011, 0x478c, 0x2214, 0x0804,
+ 0x13b8, 0x7918, 0x0804, 0x13b9, 0x2009, 0x0202, 0x210c, 0xa18c,
+ 0x0f30, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9, 0x2011,
+ 0x0102, 0x2214, 0xa294, 0x0f30, 0x0804, 0x13b8, 0x2009, 0x474d,
+ 0x210c, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9, 0x2011,
+ 0x478d, 0x2214, 0x0804, 0x13b8, 0x7920, 0x2001, 0x01ff, 0x2004,
+ 0xd0fc, 0x1904, 0x13b9, 0x7a24, 0x0804, 0x13b8, 0x2011, 0x4c40,
+ 0x71c4, 0xd1fc, 0x1110, 0x2011, 0x4bc0, 0x8107, 0xa084, 0x000f,
+ 0x8003, 0x8003, 0x8003, 0xa268, 0x6a00, 0x6b08, 0x6c1c, 0x74da,
+ 0xd1fc, 0x1118, 0x2021, 0x023b, 0x0010, 0x2021, 0x013b, 0x2424,
+ 0xa4a4, 0x1c00, 0x74de, 0x0804, 0x13b7, 0x77c4, 0x080c, 0x1b9a,
+ 0x2091, 0x8000, 0x6b1c, 0x6a14, 0x2091, 0x8001, 0x2708, 0x0804,
+ 0x13b7, 0x2061, 0x4740, 0x6118, 0x2001, 0x01ff, 0x2004, 0xd0fc,
+ 0x1904, 0x13b9, 0x2061, 0x4780, 0x6218, 0x0804, 0x13b8, 0x77c4,
+ 0x080c, 0x1b9a, 0x2091, 0x8000, 0x6908, 0x6a18, 0x6b10, 0x77da,
+ 0x2091, 0x8001, 0x0804, 0x13b7, 0x71c4, 0x2110, 0xa294, 0x000f,
+ 0xa282, 0x0010, 0x1a04, 0x13b3, 0x080c, 0x23b4, 0xa384, 0x4000,
+ 0x0110, 0xa295, 0x0020, 0x0804, 0x13b7, 0x71c4, 0x2100, 0xc0bc,
+ 0xa082, 0x0010, 0x1a04, 0x13b3, 0xd1bc, 0x1120, 0x2011, 0x4748,
+ 0x2204, 0x0020, 0x2011, 0x4788, 0x2204, 0xc0bd, 0x0006, 0x2100,
+ 0xc0bc, 0x2012, 0x080c, 0x2358, 0x001e, 0x0804, 0x13b9, 0x71c4,
+ 0x2021, 0x4749, 0x2404, 0x70c6, 0x2019, 0x0000, 0x0030, 0x71c8,
+ 0x2021, 0x4789, 0x2404, 0x70ca, 0xc3fd, 0x2011, 0x1623, 0x20a9,
+ 0x0008, 0x2204, 0xa106, 0x0138, 0x8210, 0x1f04, 0x1609, 0x71c4,
+ 0x72c8, 0x0804, 0x13b2, 0xa292, 0x1623, 0x0026, 0x2122, 0x001e,
+ 0x080c, 0x236a, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1110, 0xd3fc,
+ 0x09f0, 0x0804, 0x13ba, 0x03e8, 0x00fa, 0x01f4, 0x02ee, 0x0004,
+ 0x0001, 0x0002, 0x0003, 0x2061, 0x4740, 0x6128, 0x622c, 0x8214,
+ 0x8214, 0x8214, 0x70c4, 0x602a, 0x70c8, 0x8003, 0x8003, 0x8003,
+ 0x602e, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x11a0, 0x0026, 0x0016,
+ 0x2061, 0x4780, 0x6128, 0x622c, 0x8214, 0x8214, 0x8214, 0x70d8,
+ 0x602a, 0x70dc, 0x8003, 0x8003, 0x8003, 0x602e, 0x71da, 0x72de,
+ 0x001e, 0x002e, 0x0804, 0x13b8, 0x2061, 0x4740, 0x6130, 0x70c4,
+ 0x6032, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9, 0x2061,
+ 0x4780, 0x6230, 0x70c8, 0x6032, 0x0804, 0x13b8, 0x7918, 0x0804,
+ 0x13b9, 0x71c4, 0xa184, 0xf0cf, 0x0148, 0x2001, 0x01ff, 0x2004,
+ 0xd0fc, 0x1904, 0x13b3, 0x72c8, 0x0804, 0x13b2, 0x2019, 0x0000,
+ 0x080c, 0x23a6, 0x0036, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x0118,
+ 0x001e, 0x0804, 0x13b9, 0x71c8, 0xa184, 0xf0cf, 0x0128, 0x000e,
+ 0x2110, 0x71c4, 0x0804, 0x13b2, 0xc3fd, 0x080c, 0x23a6, 0x2310,
+ 0x001e, 0x0804, 0x13b8, 0x71c4, 0xa182, 0x0010, 0x0248, 0x2001,
+ 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b3, 0x72c8, 0x0804, 0x13b2,
+ 0x2011, 0x474d, 0x2204, 0x0006, 0x8104, 0x1208, 0x8108, 0x2112,
+ 0x2019, 0x0000, 0x080c, 0x2393, 0x2001, 0x01ff, 0x2004, 0xd0fc,
+ 0x0118, 0x001e, 0x0804, 0x13b9, 0x71c8, 0xa182, 0x0010, 0x0228,
+ 0x0006, 0x2110, 0x71c4, 0x0804, 0x13b2, 0x2011, 0x478d, 0x2204,
+ 0x0006, 0x8104, 0x1208, 0x8108, 0x2112, 0xc3fd, 0x080c, 0x2393,
+ 0x002e, 0x001e, 0x0804, 0x13b8, 0x71c4, 0x72c8, 0xa184, 0xfffd,
+ 0x1904, 0x13b2, 0xa284, 0xfffd, 0x1904, 0x13b2, 0x2100, 0x7920,
+ 0x7822, 0x2200, 0x7a24, 0x7826, 0x0804, 0x13b8, 0x2011, 0x4c40,
+ 0x71c4, 0xd1fc, 0x1110, 0x2011, 0x4bc0, 0x8107, 0xa084, 0x000f,
+ 0x8003, 0x8003, 0x8003, 0xa268, 0x72c8, 0x73cc, 0x74d8, 0x71c6,
+ 0x6800, 0x70ca, 0x73ce, 0x74da, 0x2091, 0x8000, 0x6a02, 0xd2ac,
+ 0x1118, 0x2021, 0x0000, 0x0090, 0xa484, 0x00ff, 0xa082, 0x0002,
+ 0x1a04, 0x174f, 0x843f, 0xa7bc, 0x00ff, 0x0140, 0xa786, 0x0002,
+ 0x1904, 0x174f, 0xa484, 0x00ff, 0x0904, 0x174f, 0x2061, 0x0200,
+ 0xd1fc, 0x0110, 0x2061, 0x0100, 0x2029, 0x0009, 0x2031, 0x0062,
+ 0x843f, 0xa7bc, 0x00ff, 0x0130, 0x8307, 0xa084, 0x00ff, 0x1110,
+ 0xa73d, 0x1138, 0x2041, 0x0019, 0xa384, 0x00ff, 0xa082, 0x001a,
+ 0x0210, 0xa4a4, 0x00ff, 0x8307, 0xa084, 0x00ff, 0x0188, 0xa842,
+ 0x02f0, 0xa086, 0x0010, 0x1120, 0xa39c, 0x00ff, 0xa39d, 0x0f00,
+ 0xa3bc, 0x00ff, 0x2500, 0xa702, 0x0290, 0x2600, 0xa702, 0x1278,
+ 0x2039, 0x003a, 0x6804, 0xa705, 0x6806, 0x6b0a, 0x6b0c, 0x73ce,
+ 0x681c, 0x70da, 0x6c1e, 0x2091, 0x8001, 0x0804, 0x13ba, 0x2091,
+ 0x8001, 0x0804, 0x13b4, 0x77c4, 0x080c, 0x1b9a, 0x2091, 0x8000,
+ 0x6a14, 0x6b1c, 0x2091, 0x8001, 0x70c8, 0x6816, 0x70cc, 0x681e,
+ 0x2708, 0x0804, 0x13b7, 0x70c4, 0x2061, 0x4740, 0x6118, 0x601a,
+ 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9, 0x70c8, 0x2061,
+ 0x4780, 0x6218, 0x601a, 0x0804, 0x13b8, 0x71c4, 0x72c8, 0x73cc,
+ 0xa182, 0x0010, 0x1a04, 0x13b3, 0x080c, 0x23d8, 0xa384, 0x4000,
+ 0x0110, 0xa295, 0x0020, 0x0804, 0x13b7, 0x77c4, 0x080c, 0x1b9a,
+ 0x2091, 0x8000, 0x6a08, 0xc28d, 0x6a0a, 0x2091, 0x8001, 0x2708,
+ 0x0804, 0x13b8, 0x77c4, 0x080c, 0x1b9a, 0x2091, 0x8000, 0x6a08,
+ 0xa294, 0xfff9, 0x6a0a, 0x6804, 0xa005, 0x0110, 0x080c, 0x22d5,
+ 0x2091, 0x8001, 0x2708, 0x0804, 0x13b8, 0x77c4, 0x080c, 0x1b9a,
+ 0x2091, 0x8000, 0x6a08, 0xc295, 0x6a0a, 0x6804, 0xa005, 0x0110,
+ 0x080c, 0x22d5, 0x2091, 0x8001, 0x2708, 0x0804, 0x13b8, 0x77c4,
+ 0x2041, 0x0001, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000,
+ 0x080c, 0x1bb2, 0x2091, 0x8001, 0x2708, 0x6a08, 0x0804, 0x13b8,
+ 0x77c4, 0xd7fc, 0x0128, 0x080c, 0x1b29, 0x0138, 0x0804, 0x13bc,
+ 0x080c, 0x1b1e, 0x0110, 0x0804, 0x13bc, 0x73c8, 0x72cc, 0x77c6,
+ 0x73ca, 0x72ce, 0x080c, 0x1c2a, 0x11e8, 0x6818, 0xa005, 0x01a0,
+ 0x2708, 0x0076, 0x080c, 0x23f7, 0x007e, 0x1170, 0x2001, 0x0015,
+ 0xd7fc, 0x1118, 0x2061, 0x4740, 0x0018, 0xc0fd, 0x2061, 0x4780,
+ 0x782a, 0x2091, 0x8001, 0x0005, 0x2091, 0x8001, 0x2001, 0x4005,
+ 0x0804, 0x13bc, 0x2091, 0x8001, 0x0804, 0x13ba, 0x77c4, 0xd7fc,
+ 0x0128, 0x080c, 0x1b29, 0x0138, 0x0804, 0x13bc, 0x080c, 0x1b1e,
+ 0x0110, 0x0804, 0x13bc, 0x77c6, 0x2041, 0x0021, 0x2049, 0x0005,
+ 0x2051, 0x0020, 0x2091, 0x8000, 0x080c, 0x1bb2, 0x2009, 0x0016,
+ 0xd7fc, 0x1118, 0x2061, 0x4740, 0x0018, 0x2061, 0x4780, 0xc1fd,
+ 0x6063, 0x0003, 0x607b, 0x0000, 0x6772, 0x607f, 0x000f, 0x792a,
+ 0x61d0, 0xc1c4, 0x61d2, 0x080c, 0x22d5, 0x2091, 0x8001, 0x0005,
+ 0x77c8, 0x77ca, 0x77c4, 0x77c6, 0xd7fc, 0x0128, 0x080c, 0x1b29,
+ 0x0138, 0x0804, 0x13bc, 0x080c, 0x1b1e, 0x0110, 0x0804, 0x13bc,
+ 0xa7bc, 0xff00, 0x2091, 0x8000, 0x2009, 0x0017, 0xd7fc, 0x1118,
+ 0x2061, 0x4740, 0x0018, 0x2061, 0x4780, 0xc1fd, 0x607b, 0x0000,
+ 0x6063, 0x0002, 0x6772, 0x607f, 0x000f, 0x792a, 0x61d0, 0xc1c4,
+ 0x61d2, 0x080c, 0x22d5, 0x2091, 0x8001, 0x2041, 0x0021, 0x2049,
+ 0x0005, 0x2051, 0x0010, 0x2091, 0x8000, 0x70c8, 0xa005, 0x0118,
+ 0x60d0, 0xc0fd, 0x60d2, 0x080c, 0x1bb2, 0x70c8, 0x6836, 0x8738,
+ 0xa784, 0x001f, 0x1dc0, 0x2091, 0x8001, 0x0005, 0x2019, 0x0000,
+ 0x72c8, 0xd284, 0x0128, 0x080c, 0x1b29, 0x0138, 0x0804, 0x13bc,
+ 0x080c, 0x1b1e, 0x0110, 0x0804, 0x13bc, 0x72c8, 0x72ca, 0x78ac,
+ 0xa084, 0x0003, 0x1518, 0x2039, 0x0000, 0xd284, 0x0108, 0xc7fd,
+ 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008, 0x080c, 0x1b9a,
+ 0x2091, 0x8000, 0x6808, 0xc0d4, 0xa80d, 0x690a, 0x6837, 0x0000,
+ 0x2091, 0x8001, 0x8738, 0xa784, 0x001f, 0x1d80, 0xa7bc, 0xff00,
+ 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x1d40, 0x2091, 0x8000,
0x72c8, 0x2069, 0x0100, 0xd284, 0x1110, 0x2069, 0x0200, 0x6808,
0xa084, 0xfffd, 0x680a, 0x6830, 0xd0b4, 0x01b0, 0x684b, 0x0004,
- 0x20a9, 0x0014, 0x6848, 0xd094, 0x0110, 0x1f04, 0x18b2, 0x684b,
- 0x0009, 0x20a9, 0x0014, 0x6848, 0xd084, 0x0110, 0x1f04, 0x18bb,
- 0x20a9, 0x00fa, 0x1f04, 0x18c2, 0x2079, 0x4600, 0x2009, 0x0018,
- 0x72c8, 0xd284, 0x1118, 0x2061, 0x4640, 0x0018, 0x2061, 0x4680,
+ 0x20a9, 0x0014, 0x6848, 0xd094, 0x0110, 0x1f04, 0x18c2, 0x684b,
+ 0x0009, 0x20a9, 0x0014, 0x6848, 0xd084, 0x0110, 0x1f04, 0x18cb,
+ 0x20a9, 0x00fa, 0x1f04, 0x18d2, 0x2079, 0x4700, 0x2009, 0x0018,
+ 0x72c8, 0xd284, 0x1118, 0x2061, 0x4740, 0x0018, 0x2061, 0x4780,
0xc1fd, 0x607b, 0x0000, 0x792a, 0x6063, 0x0001, 0x607f, 0x000f,
0x60a3, 0x0000, 0x60a4, 0x60ae, 0x60b2, 0x60d0, 0xd0b4, 0x0160,
0xc0b4, 0x60d2, 0x00c6, 0x60b4, 0xa065, 0x6008, 0xc0d4, 0x600a,
0x6018, 0x8001, 0x601a, 0x00ce, 0x60d0, 0xa084, 0x7eff, 0x60d2,
0x78ac, 0xc08d, 0x78ae, 0x83ff, 0x0108, 0x0005, 0x681b, 0x0054,
- 0x2091, 0x8001, 0x0005, 0x73cc, 0x080c, 0x186a, 0x69ec, 0x6a48,
+ 0x2091, 0x8001, 0x0005, 0x73cc, 0x080c, 0x1878, 0x69ec, 0x6a48,
0xa185, 0x1800, 0x684a, 0xa185, 0x0040, 0x68ee, 0x73cc, 0x2021,
- 0x0004, 0x20a9, 0x09ff, 0x1f04, 0x190b, 0x8421, 0x1dd0, 0x8319,
+ 0x0004, 0x20a9, 0x09ff, 0x1f04, 0x191b, 0x8421, 0x1dd0, 0x8319,
0x1db0, 0x69ee, 0x6a4a, 0x2091, 0x8001, 0x0005, 0xd7fc, 0x1118,
- 0x2069, 0x4640, 0x0010, 0x2069, 0x4680, 0x71c4, 0x71c6, 0x6916,
+ 0x2069, 0x4740, 0x0010, 0x2069, 0x4780, 0x71c4, 0x71c6, 0x6916,
0x81ff, 0x1110, 0x68a3, 0x0001, 0x78ac, 0xc08c, 0x78ae, 0xd084,
- 0x1110, 0x080c, 0x1c5b, 0x0005, 0x75d8, 0x74dc, 0x75da, 0x74de,
+ 0x1110, 0x080c, 0x1c7a, 0x0005, 0x75d8, 0x74dc, 0x75da, 0x74de,
0x0010, 0xa02e, 0x2520, 0x71c4, 0x73c8, 0x72cc, 0x71c6, 0x73ca,
- 0x72ce, 0x2079, 0x4600, 0x7dde, 0x7cda, 0x7bd6, 0x7ad2, 0x080c,
- 0x1b58, 0x0904, 0x1a3d, 0x20a9, 0x0005, 0x20a1, 0x4614, 0x2091,
- 0x8000, 0x41a1, 0x2091, 0x8001, 0x2009, 0x0040, 0x080c, 0x1d24,
- 0x0120, 0x080c, 0x1b60, 0x0804, 0x1a3d, 0x6004, 0xa08c, 0x00ff,
- 0xa18e, 0x0009, 0x1120, 0x0006, 0x080c, 0x205f, 0x000e, 0xa084,
- 0xff00, 0x8007, 0x8009, 0x0904, 0x19e1, 0x00c6, 0x2c68, 0x080c,
- 0x1b58, 0x05a8, 0x2c00, 0x689e, 0x8109, 0x1dc0, 0x609f, 0x0000,
+ 0x72ce, 0x2079, 0x4700, 0x7dde, 0x7cda, 0x7bd6, 0x7ad2, 0x080c,
+ 0x1b77, 0x0904, 0x1a5c, 0x20a9, 0x0005, 0x20a1, 0x4714, 0x2091,
+ 0x8000, 0x41a1, 0x2091, 0x8001, 0x2009, 0x0040, 0x080c, 0x1d41,
+ 0x0120, 0x080c, 0x1b7f, 0x0804, 0x1a5c, 0x6004, 0xa08c, 0x00ff,
+ 0xa18e, 0x0009, 0x1120, 0x0006, 0x080c, 0x2086, 0x000e, 0xa084,
+ 0xff00, 0x8007, 0x8009, 0x0904, 0x19f1, 0x00c6, 0x2c68, 0x080c,
+ 0x1b77, 0x05a8, 0x2c00, 0x689e, 0x8109, 0x1dc0, 0x609f, 0x0000,
0x00ce, 0x00c6, 0x7ddc, 0x7cd8, 0x7bd4, 0x7ad0, 0xa290, 0x0040,
0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x7dde, 0x7cda,
- 0x7bd6, 0x7ad2, 0x2c68, 0x689c, 0xa065, 0x0904, 0x19e0, 0x2009,
- 0x0040, 0x080c, 0x1d24, 0x15a0, 0x6004, 0xa084, 0x00ff, 0xa086,
- 0x0002, 0x1168, 0x6004, 0xa084, 0x00ff, 0xa086, 0x000a, 0x1120,
- 0x0016, 0x080c, 0x205c, 0x001e, 0x2d00, 0x6002, 0x0898, 0x00ce,
- 0x00c6, 0x609c, 0x080c, 0x1bd4, 0x00ce, 0x609f, 0x0000, 0x080c,
- 0x1a41, 0x2009, 0x0018, 0x6008, 0xc0cd, 0x600a, 0x6004, 0x6086,
+ 0x7bd6, 0x7ad2, 0x2c68, 0x689c, 0xa065, 0x0904, 0x19f0, 0x2009,
+ 0x0040, 0x080c, 0x1d41, 0x15a0, 0x6004, 0xa084, 0x00ff, 0xa086,
+ 0x0002, 0x0150, 0x6004, 0xa084, 0x00ff, 0xa086, 0x000a, 0x1138,
+ 0x0016, 0x080c, 0x2083, 0x001e, 0x2d00, 0x6002, 0x0898, 0x00ce,
+ 0x00c6, 0x609c, 0x080c, 0x1bf3, 0x00ce, 0x609f, 0x0000, 0x080c,
+ 0x1a60, 0x2009, 0x0018, 0x6008, 0xc0cd, 0x600a, 0x6004, 0x6086,
0x7810, 0x0006, 0x84ff, 0x1110, 0x85ff, 0x0110, 0xc0c5, 0x7812,
- 0x080c, 0x1b15, 0x000e, 0x7812, 0x080c, 0x1b60, 0x0804, 0x1a3d,
- 0x00ce, 0x00c6, 0x609c, 0x080c, 0x1bd4, 0x00ce, 0x609f, 0x0000,
- 0x080c, 0x1a41, 0x2009, 0x0018, 0x6087, 0x0103, 0x601b, 0x0003,
+ 0x080c, 0x1b34, 0x000e, 0x7812, 0x080c, 0x1b7f, 0x0804, 0x1a5c,
+ 0x00ce, 0x00c6, 0x609c, 0x080c, 0x1bf3, 0x00ce, 0x609f, 0x0000,
+ 0x080c, 0x1a60, 0x2009, 0x0018, 0x6087, 0x0103, 0x601b, 0x0003,
0x7810, 0x0006, 0x84ff, 0x1110, 0x85ff, 0x0110, 0xc0c5, 0x7812,
- 0x080c, 0x1b15, 0x000e, 0x7812, 0x080c, 0x1b60, 0x0804, 0x1a3d,
- 0x00ce, 0x6114, 0xd1fc, 0x0120, 0x080c, 0x1b0a, 0x01f0, 0x0018,
- 0x080c, 0x1aff, 0x01d0, 0x080c, 0x1a41, 0x2009, 0x0018, 0x6087,
+ 0x080c, 0x1b34, 0x000e, 0x7812, 0x080c, 0x1b7f, 0x0804, 0x1a5c,
+ 0x00ce, 0x6114, 0xd1fc, 0x0120, 0x080c, 0x1b29, 0x01f0, 0x0018,
+ 0x080c, 0x1b1e, 0x01d0, 0x080c, 0x1a60, 0x2009, 0x0018, 0x6087,
0x0103, 0x601b, 0x0021, 0x7810, 0x0006, 0x84ff, 0x1110, 0x85ff,
- 0x0110, 0xc0c5, 0x7812, 0x080c, 0x1b15, 0x000e, 0x7812, 0x080c,
- 0x1b60, 0x2001, 0x4007, 0x0804, 0x13bc, 0x74c4, 0x73c8, 0x72cc,
- 0x6014, 0x2091, 0x8000, 0x00e6, 0x2009, 0x0012, 0xd0fc, 0x1118,
- 0x2071, 0x4640, 0x0018, 0x2071, 0x4680, 0xc1fd, 0x792a, 0x7063,
- 0x0005, 0x71d0, 0xc1c4, 0x71d2, 0x7366, 0x726a, 0x746e, 0x7072,
- 0x7077, 0x0000, 0x2c00, 0x707a, 0xa02e, 0x2530, 0x611c, 0xa184,
- 0x0060, 0x0110, 0x080c, 0x3fc1, 0x00ee, 0x6596, 0x65a6, 0x669a,
- 0x66aa, 0x60af, 0x0000, 0x60b3, 0x0000, 0x6714, 0x6023, 0x0000,
- 0x080c, 0x22ae, 0x2091, 0x8001, 0x0005, 0x70c3, 0x4005, 0x0804,
- 0x13bd, 0x20a9, 0x0005, 0x2099, 0x4614, 0x2091, 0x8000, 0x530a,
- 0x2091, 0x8001, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000,
- 0xa5a9, 0x0000, 0x0005, 0x71c4, 0x70c7, 0x0000, 0x791e, 0x0804,
- 0x13ba, 0x71c4, 0x71c6, 0x2168, 0x0010, 0x2069, 0x1000, 0x690c,
- 0xa016, 0x2d04, 0xa210, 0x8d68, 0x8109, 0x1dd8, 0xa285, 0x0000,
- 0x1118, 0x70c3, 0x4000, 0x0010, 0x70c3, 0x4003, 0x70ca, 0x0804,
- 0x13bd, 0x7964, 0x71c6, 0x71c4, 0xa182, 0x0003, 0x1a04, 0x13b3,
- 0x7966, 0x0804, 0x13ba, 0x7964, 0x71c6, 0x0804, 0x13ba, 0x7900,
- 0x71c6, 0x71c4, 0x7902, 0x0804, 0x13ba, 0x7900, 0x71c6, 0x0804,
- 0x13ba, 0x70c4, 0x2011, 0x0000, 0xa08c, 0x000d, 0x0160, 0x810c,
- 0x0230, 0x8210, 0x810c, 0x810c, 0x0210, 0x8210, 0x810c, 0x81ff,
- 0x1904, 0x13b4, 0x8210, 0x7a0e, 0xd28c, 0x0538, 0x7910, 0xc1cd,
- 0x7912, 0x2009, 0x0021, 0x2019, 0x0003, 0xd284, 0x01c0, 0x8108,
- 0x2019, 0x0041, 0x2011, 0x8e4e, 0x2312, 0x2019, 0x0042, 0x8210,
- 0x2312, 0x2019, 0x0043, 0x8210, 0x2312, 0x2019, 0x0046, 0x8210,
- 0x2312, 0x2019, 0x0047, 0x8210, 0x2312, 0x2019, 0x0006, 0x2011,
- 0x8e53, 0x2112, 0x2011, 0x8e73, 0x2312, 0x7904, 0x7806, 0x0804,
- 0x13b9, 0x7804, 0x70c6, 0x0804, 0x13ba, 0x71c4, 0xd1fc, 0x1118,
- 0x2011, 0x4ac0, 0x0010, 0x2011, 0x4b40, 0x8107, 0xa084, 0x000f,
- 0x8003, 0x8003, 0x8003, 0xa268, 0x2011, 0x0000, 0x6814, 0xd0fc,
- 0x0110, 0xa295, 0x0200, 0xd0b4, 0x0110, 0xa295, 0x0001, 0x6b0c,
- 0x6800, 0x70da, 0x0804, 0x13b7, 0x7814, 0xd0f4, 0x0130, 0x2001,
- 0x4007, 0x70db, 0x0000, 0xa005, 0x0048, 0xd0fc, 0x0130, 0x2001,
- 0x4007, 0x70db, 0x0001, 0xa005, 0x0008, 0xa006, 0x0005, 0x7814,
- 0xd0f4, 0x0130, 0x2001, 0x4007, 0x70db, 0x0000, 0xa005, 0x0008,
- 0xa006, 0x0005, 0x7814, 0xd0fc, 0x0130, 0x2001, 0x4007, 0x70db,
- 0x0001, 0xa005, 0x0008, 0xa006, 0x0005, 0x7112, 0x721a, 0x731e,
- 0x7810, 0xd0c4, 0x0110, 0x7422, 0x7526, 0xac80, 0x0001, 0x8108,
- 0x810c, 0x81a9, 0x8098, 0x20a1, 0x0030, 0x7003, 0x0000, 0x6084,
- 0x20a2, 0x53a6, 0x7007, 0x0001, 0x7974, 0xa184, 0xff00, 0x0140,
- 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0018,
- 0x8107, 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78, 0xa006, 0xa211,
- 0x7d10, 0xd5c4, 0x0120, 0x7b84, 0xa319, 0x7c80, 0xa421, 0x7008,
- 0xd0fc, 0x0de8, 0x7003, 0x0001, 0x7007, 0x0006, 0x711a, 0x721e,
- 0x7d10, 0xd5c4, 0x0110, 0x7322, 0x7426, 0xa084, 0x01e0, 0x0005,
- 0x7848, 0xa065, 0x0120, 0x2c04, 0x784a, 0x2063, 0x0000, 0x0005,
- 0x00f6, 0x2079, 0x4600, 0x7848, 0x2062, 0x2c00, 0xa005, 0x1110,
- 0x080c, 0x254c, 0x784a, 0x00fe, 0x0005, 0x2011, 0x9000, 0x7a4a,
- 0x7bc4, 0x8319, 0x0128, 0xa280, 0x0032, 0x2012, 0x2010, 0x0cc8,
- 0x2013, 0x0000, 0x0005, 0x0016, 0x0026, 0xd7fc, 0x1118, 0x2011,
- 0x4bc0, 0x0010, 0x2011, 0x6bc0, 0xa784, 0x0f00, 0x800b, 0xa784,
- 0x001f, 0x0120, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xa268,
- 0x002e, 0x001e, 0x0005, 0x0c39, 0x2900, 0x682a, 0x2a00, 0x682e,
- 0x6808, 0xa084, 0xf9ef, 0xa80d, 0x690a, 0x00e6, 0xd7fc, 0x1128,
- 0x2009, 0x4652, 0x2071, 0x4640, 0x0020, 0x2009, 0x4692, 0x2071,
- 0x4680, 0x210c, 0x6804, 0xa005, 0x0148, 0xa116, 0x1138, 0x2060,
- 0x6000, 0x6806, 0x0016, 0x200b, 0x0000, 0x0018, 0x2009, 0x0000,
- 0x0016, 0x6804, 0xa065, 0x0178, 0x6000, 0x6806, 0x0421, 0x080c,
- 0x1d95, 0x6810, 0x7908, 0x8109, 0x790a, 0x8001, 0x6812, 0x1d88,
- 0x7910, 0xc1a5, 0x7912, 0x001e, 0x6902, 0x6906, 0x2d00, 0x2060,
- 0x080c, 0x2693, 0x00ee, 0x0005, 0xa065, 0x0160, 0x2008, 0x609c,
- 0xa005, 0x0128, 0x2062, 0x609f, 0x0000, 0xa065, 0x0cc0, 0x7848,
- 0x794a, 0x2062, 0x0005, 0x6007, 0x0103, 0x608f, 0x0000, 0x20a9,
- 0x001c, 0xac80, 0x0005, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x6828,
- 0x601a, 0x682c, 0x6022, 0x0005, 0x00e6, 0xd7fc, 0x1128, 0x2071,
- 0x4640, 0x2031, 0x46c0, 0x0020, 0x2071, 0x4680, 0x2031, 0x48c0,
- 0x704c, 0xa08c, 0x0200, 0x1128, 0xa608, 0x2d0a, 0x8000, 0x704e,
- 0xa006, 0x00ee, 0x0005, 0x00f6, 0xd7fc, 0x1118, 0x2079, 0x4640,
- 0x0010, 0x2079, 0x4680, 0x080c, 0x1b7b, 0x2091, 0x8000, 0x6804,
- 0x780a, 0xa065, 0x05f0, 0x0030, 0x2c00, 0x780a, 0x2060, 0x6000,
- 0xa065, 0x05b8, 0x6010, 0xa306, 0x1db8, 0x600c, 0xa206, 0x1da0,
- 0x2c28, 0x7848, 0xac06, 0x1108, 0x0448, 0x6804, 0xac06, 0x1140,
- 0x6000, 0x2060, 0x6806, 0xa005, 0x1118, 0x6803, 0x0000, 0x0048,
- 0x6400, 0x7808, 0x2060, 0x6402, 0xa486, 0x0000, 0x1110, 0x2c00,
- 0x6802, 0x2560, 0x080c, 0x1be3, 0x601b, 0x0005, 0x6023, 0x0020,
- 0x00fe, 0x080c, 0x1d95, 0x00f6, 0x7908, 0x8109, 0x790a, 0x6810,
- 0x8001, 0x6812, 0x1118, 0x7810, 0xc0a5, 0x7812, 0x2001, 0xffff,
- 0xa005, 0x00fe, 0x0005, 0x0076, 0x2700, 0x2039, 0x0000, 0xd0fc,
- 0x0108, 0xc7fd, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008,
- 0x2091, 0x8000, 0x080c, 0x1b93, 0x8738, 0xa784, 0x001f, 0x1dd0,
- 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x1d90,
- 0x2091, 0x8001, 0x007e, 0x0005, 0x786c, 0x2009, 0x8e74, 0x210c,
- 0xa10d, 0x0118, 0xa065, 0x0804, 0x207a, 0x2061, 0x0000, 0x6018,
- 0xd084, 0x11b8, 0x7810, 0xd08c, 0x0130, 0xc08c, 0x7812, 0xc7fc,
- 0x2069, 0x4640, 0x0028, 0xc08d, 0x7812, 0x2069, 0x4680, 0xc7fd,
- 0x2091, 0x8000, 0x681c, 0x681f, 0x0000, 0x2091, 0x8001, 0xa005,
- 0x1108, 0x0005, 0xa08c, 0xfff0, 0x0110, 0x080c, 0x254c, 0x0002,
- 0x1cb8, 0x1cbb, 0x1cc1, 0x1cc5, 0x1cb9, 0x1cc9, 0x1cb9, 0x1cb9,
- 0x1cb9, 0x1ccf, 0x1cfb, 0x1cfe, 0x1d03, 0x1d0c, 0x1cb9, 0x1cb9,
- 0x0005, 0x080c, 0x254c, 0x080c, 0x1c5b, 0x2001, 0x8001, 0x0804,
- 0x1d15, 0x2001, 0x8003, 0x0804, 0x1d15, 0x2001, 0x8004, 0x0804,
- 0x1d15, 0x080c, 0x1c5b, 0x2001, 0x8006, 0x0804, 0x1d15, 0x2091,
- 0x8000, 0x0076, 0xd7fc, 0x1128, 0x2069, 0x4640, 0x2039, 0x0009,
- 0x0020, 0x2069, 0x4680, 0x2039, 0x0009, 0x6800, 0xa086, 0x0000,
- 0x0128, 0x000e, 0x6f1e, 0x2091, 0x8001, 0x0005, 0x6870, 0x007e,
- 0xa0bc, 0xff00, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0010,
- 0x080c, 0x1b93, 0x8738, 0xa784, 0x001f, 0x1dd0, 0x2091, 0x8001,
- 0x2001, 0x800a, 0x00d0, 0x2001, 0x800c, 0x00b8, 0x080c, 0x1c5b,
- 0x2001, 0x800d, 0x0090, 0xd7fc, 0x0110, 0x78e4, 0x0008, 0x78e0,
- 0x70c6, 0x2001, 0x800e, 0x0048, 0xd7fc, 0x0110, 0x78ec, 0x0008,
- 0x78e8, 0x70c6, 0x2001, 0x800f, 0x0000, 0x70c2, 0xd7fc, 0x1118,
- 0x70db, 0x0000, 0x0010, 0x70db, 0x0001, 0x2061, 0x0000, 0x601b,
- 0x0001, 0x2091, 0x4080, 0x0005, 0xac80, 0x0001, 0x81ff, 0x0518,
- 0x2099, 0x0030, 0x20a0, 0x700c, 0xa084, 0x07ff, 0x0100, 0x7018,
- 0x0006, 0x701c, 0x0006, 0x7020, 0x0006, 0x7024, 0x0006, 0x7112,
- 0x81ac, 0x721a, 0x731e, 0x7422, 0x7526, 0x7003, 0x0001, 0x7007,
- 0x0001, 0x7008, 0x800b, 0x1ee8, 0x7007, 0x0002, 0xa08c, 0x01e0,
- 0x1110, 0x53a5, 0xa006, 0x7003, 0x0000, 0x7007, 0x0004, 0x000e,
- 0x7026, 0x000e, 0x7022, 0x000e, 0x701e, 0x000e, 0x701a, 0x0005,
- 0x2011, 0x0020, 0x2009, 0x0010, 0x6b0a, 0x6c0e, 0x681f, 0x0201,
- 0x6803, 0xfd20, 0x6807, 0x0038, 0x6a1a, 0x2d00, 0xa0e8, 0x0008,
- 0xa290, 0x0004, 0x8109, 0x1d80, 0x0005, 0x70ec, 0xd0dc, 0x1520,
- 0x2029, 0x0001, 0x7814, 0xd0cc, 0x1160, 0x70ec, 0xd0e4, 0x2019,
- 0x0c0a, 0x2021, 0x000a, 0x1120, 0x2019, 0x0c0c, 0x2021, 0x000c,
- 0x0070, 0x70ec, 0xd0e4, 0x1128, 0x2019, 0x180c, 0x2021, 0x000c,
- 0x0030, 0x2019, 0x1809, 0x2021, 0x0009, 0xa5ad, 0x0200, 0x6b0a,
- 0x6c0e, 0x6d1e, 0x6807, 0x0038, 0x0005, 0x6004, 0x6086, 0x2c08,
- 0x2063, 0x0000, 0x7868, 0xa005, 0x796a, 0x0110, 0x2c02, 0x0008,
- 0x796e, 0x0005, 0x00c6, 0x2061, 0x4600, 0x6887, 0x0103, 0x2d08,
- 0x206b, 0x0000, 0x6068, 0xa005, 0x616a, 0x0110, 0x2d02, 0x0008,
- 0x616e, 0x00ce, 0x0005, 0x2091, 0x8000, 0x2c04, 0x786e, 0xa005,
- 0x1108, 0x786a, 0x2091, 0x8001, 0x609c, 0xa005, 0x0188, 0x00c6,
- 0x2060, 0x2008, 0x609c, 0xa005, 0x0138, 0x2062, 0x609f, 0x0000,
- 0xa065, 0x609c, 0xa005, 0x1dc8, 0x7848, 0x794a, 0x2062, 0x00ce,
- 0x7848, 0x2062, 0x609f, 0x0000, 0xac85, 0x0000, 0x1110, 0x080c,
- 0x254c, 0x784a, 0x0005, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086,
- 0x818e, 0x1208, 0xa200, 0x1f04, 0x1ddf, 0x8086, 0x818e, 0x0005,
- 0x0156, 0x20a9, 0x0010, 0xa005, 0x01b8, 0xa11a, 0x12a8, 0x8213,
- 0x818d, 0x0228, 0xa11a, 0x1220, 0x1f04, 0x1def, 0x0028, 0xa11a,
- 0x2308, 0x8210, 0x1f04, 0x1def, 0x0006, 0x3200, 0xa084, 0xefff,
- 0x2080, 0x000e, 0x015e, 0x0005, 0x0006, 0x3200, 0xa085, 0x1000,
- 0x0cb8, 0x7d74, 0x70d0, 0xa506, 0x0904, 0x1ebd, 0x7810, 0x2050,
- 0x080c, 0x1b58, 0x0904, 0x1ebd, 0xa046, 0x7970, 0x2500, 0x8000,
- 0xa112, 0x2009, 0x0040, 0x1208, 0x0030, 0x72d0, 0xa206, 0x0118,
- 0x8840, 0x2009, 0x0080, 0x00c6, 0x7112, 0x7007, 0x0001, 0x2099,
- 0x0030, 0x20a9, 0x0020, 0xac80, 0x0001, 0x20a0, 0x2061, 0x0000,
- 0x88ff, 0x0110, 0x080c, 0x1b58, 0x7008, 0xd0fc, 0x0de8, 0x7007,
- 0x0002, 0x2091, 0x8001, 0xa08c, 0x01e0, 0x1538, 0x53a5, 0x8cff,
- 0x1120, 0x88ff, 0x0904, 0x1eaa, 0x0050, 0x2c00, 0x788e, 0x20a9,
- 0x0020, 0xac80, 0x0001, 0x20a0, 0x53a5, 0x0804, 0x1eaa, 0xa046,
- 0x7218, 0x731c, 0xdac4, 0x0110, 0x7420, 0x7524, 0xa292, 0x0040,
- 0xa39b, 0x0000, 0xa4a3, 0x0000, 0xa5ab, 0x0000, 0x721a, 0x731e,
- 0xdac4, 0x0118, 0x7422, 0x7526, 0xa006, 0x7007, 0x0004, 0x0904,
- 0x1eaa, 0x8cff, 0x0110, 0x080c, 0x1b60, 0x00ce, 0x080c, 0x1b60,
- 0xa046, 0x7888, 0x8000, 0x788a, 0xa086, 0x0002, 0x01c0, 0x7a7c,
- 0x7b78, 0xdac4, 0x0110, 0x7c84, 0x7d80, 0x7974, 0x8107, 0x8004,
- 0x8004, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000,
- 0x721a, 0x731e, 0xdac4, 0x0588, 0x7422, 0x7526, 0x0470, 0x6014,
- 0xd0fc, 0x1118, 0x2069, 0x4640, 0x0010, 0x2069, 0x4680, 0x2091,
- 0x8000, 0x681f, 0x0002, 0x88ff, 0x0120, 0xa046, 0x788c, 0x2060,
- 0x0c70, 0x788b, 0x0000, 0x78ac, 0xa085, 0x0003, 0x78ae, 0x2091,
- 0x8001, 0x0098, 0x00ce, 0x788b, 0x0000, 0x080c, 0x2035, 0x6004,
- 0xa084, 0x000f, 0x0059, 0x88ff, 0x0130, 0x788c, 0x2060, 0x6004,
- 0xa084, 0x000f, 0x0019, 0x0804, 0x1e09, 0x0005, 0x0002, 0x1ecf,
- 0x1eea, 0x1f03, 0x1ecf, 0x1f10, 0x1ee0, 0x1ecf, 0x1ecf, 0x1ecf,
- 0x1ee8, 0x1f01, 0x1ecf, 0x1ecf, 0x1ecf, 0x1ecf, 0x1ecf, 0x2039,
- 0x0400, 0x78bc, 0xa705, 0x78be, 0x6008, 0xa705, 0x600a, 0x080c,
- 0x1f4c, 0x609c, 0x78ba, 0x609f, 0x0000, 0x080c, 0x2021, 0x0005,
- 0x78bc, 0xd0c4, 0x0108, 0x0c58, 0x601c, 0xc0bd, 0x601e, 0x0030,
- 0x080c, 0x205f, 0x78bc, 0xd0c4, 0x0108, 0x0c08, 0x78bf, 0x0000,
- 0x6004, 0x8007, 0xa084, 0x00ff, 0x78b2, 0x8001, 0x0138, 0x080c,
- 0x1f4c, 0x0120, 0x78bc, 0xc0c5, 0x78be, 0x0010, 0x0804, 0x1f67,
- 0x0005, 0x080c, 0x205c, 0x78bc, 0xa08c, 0x0e00, 0x1110, 0xd0c4,
- 0x1108, 0x0828, 0x080c, 0x1f4c, 0x1110, 0x0804, 0x1f67, 0x0005,
- 0x78bc, 0xd0c4, 0x0110, 0x0804, 0x1ecf, 0x78bf, 0x0000, 0x6714,
- 0x2011, 0x0001, 0x22a8, 0x6018, 0xa084, 0x00ff, 0xa005, 0x0188,
- 0xa7bc, 0xff00, 0x20a9, 0x0020, 0xa08e, 0x0001, 0x0150, 0xa7bc,
- 0x8000, 0x2011, 0x0002, 0x20a9, 0x0100, 0xa08e, 0x0002, 0x0108,
- 0x00c0, 0x080c, 0x1b7b, 0x2d00, 0x2091, 0x8000, 0x682b, 0x0000,
- 0x682f, 0x0000, 0x6808, 0xa084, 0xffde, 0x680a, 0xade8, 0x0010,
- 0x2091, 0x8001, 0x1f04, 0x1f34, 0x8211, 0x0118, 0x20a9, 0x0100,
- 0x0c58, 0x080c, 0x1b60, 0x0005, 0x609f, 0x0000, 0x78b4, 0xa06d,
- 0x2c00, 0x78b6, 0x1110, 0x78ba, 0x0038, 0x689e, 0x2d00, 0x6002,
- 0x78b8, 0xad06, 0x1108, 0x6002, 0x78b0, 0x8001, 0x78b2, 0x1130,
- 0x78bc, 0xc0c4, 0x78be, 0x78b8, 0x2060, 0xa006, 0x0005, 0x00e6,
- 0xa02e, 0x2530, 0x7dba, 0x7db6, 0x65ae, 0x65b2, 0x601c, 0x60a2,
- 0x2048, 0xa984, 0xe1ff, 0x601e, 0xa984, 0x0060, 0x0110, 0x080c,
- 0x3fc1, 0x6596, 0x65a6, 0x669a, 0x66aa, 0x6714, 0x2071, 0x4680,
- 0xd7fc, 0x1110, 0x2071, 0x4640, 0xa784, 0x0f00, 0x800b, 0xa784,
- 0x001f, 0x0120, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0x71c0,
- 0xa168, 0x2700, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
- 0x71c4, 0xa100, 0x60c2, 0x2091, 0x8000, 0x7814, 0xd0c4, 0x0138,
- 0xd7fc, 0x1118, 0xd0f4, 0x1140, 0x0010, 0xd0fc, 0x1128, 0x6e08,
- 0xd684, 0x01f0, 0xd9fc, 0x11e0, 0x2091, 0x8001, 0x080c, 0x1be3,
- 0x2091, 0x8000, 0x080c, 0x1d95, 0x2091, 0x8001, 0x7814, 0xd0c4,
- 0x0904, 0x201f, 0xd7fc, 0x1120, 0xd0f4, 0x1130, 0x0804, 0x201f,
- 0xd0fc, 0x1110, 0x0804, 0x201f, 0x601b, 0x0021, 0x0804, 0x201f,
- 0x6024, 0xa096, 0x0001, 0x1110, 0x8000, 0x6026, 0x6a10, 0x6814,
- 0xa202, 0x0268, 0x0160, 0x2091, 0x8001, 0x2039, 0x0200, 0x609c,
- 0x78ba, 0x609f, 0x0000, 0x080c, 0x2021, 0x0804, 0x201f, 0x2c08,
- 0xd9fc, 0x01f0, 0x6800, 0xa065, 0x01d8, 0x6a04, 0x7000, 0xa084,
- 0x0002, 0x0168, 0x7048, 0xa206, 0x1150, 0x6b04, 0x2160, 0x2304,
- 0x6002, 0xa005, 0x1108, 0x6902, 0x2260, 0x6102, 0x0098, 0x2d00,
- 0x2060, 0x080c, 0x2693, 0x6e08, 0x2160, 0x6202, 0x6906, 0x0050,
- 0x6800, 0x6902, 0xa065, 0x0110, 0x6102, 0x0008, 0x6906, 0x2160,
- 0x6003, 0x0000, 0x2160, 0xd9fc, 0x0118, 0xa6b4, 0xfffc, 0x6e0a,
- 0x6810, 0x7d08, 0x8528, 0x7d0a, 0x8000, 0x6812, 0x2091, 0x8001,
- 0xd6b4, 0x0128, 0xa6b6, 0x0040, 0x6e0a, 0x080c, 0x1bf4, 0x00ee,
- 0x0005, 0x6008, 0xa705, 0x600a, 0x2091, 0x8000, 0x080c, 0x1d95,
- 0x2091, 0x8001, 0x78b8, 0xa065, 0x0128, 0x609c, 0x78ba, 0x609f,
- 0x0000, 0x0c78, 0x78b6, 0x78ba, 0x0005, 0x7970, 0x7874, 0x2818,
- 0xd384, 0x0118, 0x8000, 0xa112, 0x0220, 0x8000, 0xa112, 0x1278,
- 0xc384, 0x7a7c, 0x721a, 0x7a78, 0x721e, 0xdac4, 0x0120, 0x7a84,
- 0x7222, 0x7a80, 0x7226, 0xa006, 0xd384, 0x0108, 0x8000, 0x7876,
- 0x70d2, 0x781c, 0xa005, 0x0138, 0x8001, 0x781e, 0x1120, 0x0e04,
- 0x205b, 0x2091, 0x4080, 0x0005, 0x2039, 0x2071, 0x0010, 0x2039,
- 0x2077, 0x2704, 0xa005, 0x0160, 0xac00, 0x2068, 0x6908, 0x6810,
- 0x6912, 0x680a, 0x690c, 0x6814, 0x6916, 0x680e, 0x8738, 0x0c88,
- 0x0005, 0x0003, 0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0015,
- 0x001b, 0x0000, 0x2041, 0x0000, 0x780c, 0x0002, 0x2223, 0x21fe,
- 0x2082, 0x20f2, 0x2039, 0x8e74, 0x2734, 0x7d10, 0x00c0, 0x6084,
- 0xa086, 0x0103, 0x1904, 0x20dc, 0x6114, 0x6018, 0xa105, 0x0120,
- 0x86ff, 0x11d8, 0x0804, 0x20dc, 0x8603, 0xa080, 0x8e55, 0x620c,
- 0x2202, 0x8000, 0x6210, 0x2202, 0x080c, 0x1db3, 0x8630, 0xa68e,
- 0x000f, 0x0904, 0x215d, 0x786c, 0xa065, 0x1d08, 0x7808, 0xa602,
- 0x1220, 0xd5ac, 0x1110, 0x263a, 0x0005, 0xa682, 0x0003, 0x1a04,
- 0x215d, 0x2091, 0x8000, 0x2069, 0x0000, 0x6818, 0xd084, 0x11f8,
- 0x2011, 0x8e55, 0x2204, 0x70c6, 0x8210, 0x2204, 0x70ca, 0xd684,
- 0x1130, 0x8210, 0x2204, 0x70da, 0x8210, 0x2204, 0x70de, 0xa685,
- 0x8020, 0x70c2, 0x681b, 0x0001, 0x2091, 0x4080, 0x7810, 0xa084,
- 0xffcf, 0x7812, 0x2091, 0x8001, 0x203b, 0x0000, 0x0005, 0x7810,
- 0xc0ad, 0x7812, 0x0804, 0x215d, 0x263a, 0x080c, 0x2229, 0x1904,
- 0x2245, 0x786c, 0xa065, 0x1904, 0x2087, 0x2091, 0x8000, 0x7810,
- 0xa084, 0xffcf, 0x86ff, 0x0108, 0xc0ad, 0x7812, 0x2091, 0x8001,
- 0x0804, 0x2245, 0x2039, 0x8e74, 0x2734, 0x7d10, 0x00a0, 0x6084,
- 0xa086, 0x0103, 0x1904, 0x2147, 0x6114, 0x6018, 0xa105, 0x0120,
- 0x86ff, 0x11b8, 0x0804, 0x2147, 0xa680, 0x8e55, 0x620c, 0x2202,
- 0x080c, 0x1db3, 0x8630, 0xa68e, 0x001e, 0x0904, 0x215d, 0x786c,
- 0xa065, 0x1d28, 0x7808, 0xa602, 0x1220, 0xd5ac, 0x1110, 0x263a,
- 0x0005, 0xa682, 0x0006, 0x1a04, 0x215d, 0x2091, 0x8000, 0x2069,
- 0x0000, 0x6818, 0xd084, 0x11f8, 0x2011, 0x8e55, 0x2009, 0x8e4e,
- 0x26a8, 0x211c, 0x2204, 0x201a, 0x8108, 0x8210, 0x1f04, 0x2129,
- 0xa685, 0x8030, 0x70c2, 0x681b, 0x0001, 0x2091, 0x4080, 0x7810,
- 0xa084, 0xffcf, 0x7812, 0x2091, 0x8001, 0xa006, 0x2009, 0x8e75,
- 0x200a, 0x203a, 0x0005, 0x7810, 0xc0ad, 0x7812, 0x00b0, 0x263a,
- 0x080c, 0x2229, 0x1904, 0x2245, 0x786c, 0xa065, 0x1904, 0x20f7,
- 0x2091, 0x8000, 0x7810, 0xa084, 0xffcf, 0x86ff, 0x0108, 0xc0ad,
- 0x7812, 0x2091, 0x8001, 0x0804, 0x2245, 0x2091, 0x8000, 0x7007,
- 0x0004, 0x7994, 0x70d4, 0xa102, 0x0228, 0x0168, 0x7b90, 0xa302,
- 0x1150, 0x0010, 0x8002, 0x1138, 0x263a, 0x7810, 0xc0ad, 0x7812,
- 0x2091, 0x8001, 0x0005, 0xa184, 0xff00, 0x0140, 0x810f, 0x810c,
- 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0018, 0x8107, 0x8004,
- 0x8004, 0x7a9c, 0xa210, 0x721a, 0x7a98, 0xa006, 0xa211, 0x721e,
- 0xd4c4, 0x0130, 0x7aa4, 0xa211, 0x7222, 0x7aa0, 0xa211, 0x7226,
- 0x20a1, 0x0030, 0x7003, 0x0000, 0x2009, 0x8e54, 0x260a, 0x8109,
- 0x2198, 0x2104, 0xd084, 0x0108, 0x8633, 0xa6b0, 0x0002, 0x26a8,
- 0x53a6, 0x8603, 0x7012, 0x7007, 0x0001, 0x7990, 0x7894, 0x8000,
- 0xa10a, 0x1208, 0xa006, 0x2028, 0x7974, 0xa184, 0xff00, 0x0140,
- 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0018,
- 0x8107, 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78, 0xa006, 0xa211,
- 0xd4c4, 0x0120, 0x7b84, 0xa319, 0x7c80, 0xa421, 0x7008, 0xd0fc,
- 0x0de8, 0xa084, 0x01e0, 0x01d0, 0x7d10, 0x2031, 0x8e54, 0x2634,
- 0x78a8, 0x8000, 0x78aa, 0xd08c, 0x1138, 0x7007, 0x0006, 0x7004,
- 0xd094, 0x1de8, 0x0804, 0x215f, 0x2069, 0x4647, 0x206b, 0x0003,
- 0x78ac, 0xa085, 0x0300, 0x78ae, 0xa006, 0x0048, 0x2030, 0x75d6,
- 0x2091, 0x4080, 0x7d96, 0x7d10, 0xa5ac, 0xffcf, 0x7d12, 0x2091,
- 0x8001, 0x78aa, 0x7007, 0x0006, 0x263a, 0x7003, 0x0001, 0x711a,
- 0x721e, 0xd5c4, 0x0110, 0x7322, 0x7426, 0x0005, 0x6084, 0xa086,
- 0x0103, 0x11d8, 0x6114, 0x6018, 0xa105, 0x11b8, 0x2069, 0x0000,
- 0x6818, 0xd084, 0x1190, 0x600c, 0x70c6, 0x6010, 0x70ca, 0x70c3,
- 0x8020, 0x681b, 0x0001, 0x2091, 0x4080, 0x080c, 0x1db3, 0x0e04,
- 0x221c, 0x786c, 0xa065, 0x1d10, 0x0005, 0x0059, 0x1530, 0x786c,
- 0xa065, 0x19e0, 0x0410, 0x0029, 0x1500, 0x786c, 0xa065, 0x1dd8,
- 0x00e0, 0x6084, 0xa086, 0x0103, 0x1168, 0x6018, 0xc0fc, 0x601a,
- 0xa086, 0x0004, 0x1138, 0x7804, 0xd0a4, 0x0120, 0x080c, 0x1db3,
- 0xa006, 0x0005, 0x0079, 0x1118, 0xa085, 0x0001, 0x0005, 0x00b9,
- 0x1110, 0x2041, 0x0001, 0x7d10, 0x0005, 0x88ff, 0x0110, 0x2091,
- 0x4080, 0x0005, 0x7b90, 0x7994, 0x70d4, 0xa102, 0x1118, 0xa385,
- 0x0000, 0x0005, 0x0210, 0xa302, 0x0005, 0x8002, 0x0005, 0xa184,
- 0xff00, 0x0140, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007,
- 0xa100, 0x0018, 0x8107, 0x8004, 0x8004, 0x7a9c, 0x7b98, 0x7ca4,
- 0x7da0, 0xa210, 0xa006, 0xa319, 0xa421, 0xa529, 0x2009, 0x0018,
- 0x6028, 0xa005, 0x0110, 0x2009, 0x0040, 0x080c, 0x1b15, 0x01d0,
- 0x78a8, 0x8000, 0x78aa, 0xd08c, 0x1510, 0x6014, 0xd0fc, 0x1118,
- 0x2069, 0x4640, 0x0010, 0x2069, 0x4680, 0x2091, 0x8000, 0x681f,
- 0x0003, 0x78ab, 0x0000, 0x78ac, 0xa085, 0x0300, 0x78ae, 0x2091,
- 0x8001, 0x0068, 0x78ab, 0x0000, 0x080c, 0x1db3, 0x7990, 0x7894,
- 0x8000, 0xa10a, 0x1208, 0xa006, 0x7896, 0x70d6, 0xa006, 0x2071,
- 0x0010, 0x2091, 0x8001, 0x0005, 0xd7fc, 0x1118, 0x2009, 0x4658,
- 0x0010, 0x2009, 0x4698, 0x2091, 0x8000, 0x200a, 0x00f6, 0x2009,
- 0x4680, 0x2079, 0x0100, 0xd7fc, 0x1120, 0x2009, 0x4640, 0x2079,
- 0x0200, 0x2104, 0xa086, 0x0000, 0x1180, 0xd7fc, 0x1118, 0x2009,
- 0x4645, 0x0010, 0x2009, 0x4685, 0x2104, 0xa005, 0x1130, 0x7830,
- 0xa084, 0x00c0, 0x1110, 0x781b, 0x0052, 0x00fe, 0x0005, 0x2009,
- 0x0002, 0x2069, 0x4600, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904,
- 0x2324, 0x2071, 0x4680, 0x2079, 0x0100, 0x2021, 0x48bf, 0x784b,
- 0x000f, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x0118, 0x2019, 0x3e0f,
- 0x0030, 0x20a1, 0x012b, 0x2019, 0x3e0f, 0xd184, 0x0110, 0x20a1,
- 0x022b, 0x2304, 0xa005, 0x0140, 0x789a, 0x8318, 0x23ac, 0x8318,
- 0x2398, 0x53a6, 0x3318, 0x0ca8, 0x789b, 0x0000, 0x789b, 0x0020,
- 0x20a9, 0x0010, 0x78af, 0x0000, 0x78af, 0x2020, 0x1f04, 0x2302,
- 0x7003, 0x0000, 0x0016, 0xd18c, 0x2009, 0x0000, 0x0108, 0xc1bd,
- 0x080c, 0x2443, 0x001e, 0x7020, 0xa084, 0x000f, 0xa085, 0x6300,
- 0x7806, 0x780f, 0x9000, 0x7843, 0x00d8, 0x7853, 0x0090, 0x780b,
- 0x2f08, 0x7452, 0x704f, 0x0000, 0x8109, 0x0140, 0x2071, 0x4640,
- 0x2079, 0x0200, 0x2021, 0x46bf, 0x0804, 0x22df, 0x080c, 0x24fd,
- 0x0005, 0x0016, 0x2011, 0x0101, 0xd1bc, 0x1110, 0x2011, 0x0201,
- 0xa18c, 0x000f, 0x2204, 0xa084, 0xfff0, 0xa105, 0x2012, 0x001e,
- 0x080c, 0x2443, 0x0005, 0x2011, 0x0101, 0xd3fc, 0x1110, 0x2011,
- 0x0201, 0x20a9, 0x0009, 0x810b, 0x1f04, 0x234b, 0xa18c, 0x0e00,
- 0x2204, 0xa084, 0xf1ff, 0xa105, 0x2012, 0x0005, 0x2019, 0x0002,
- 0x2009, 0x0101, 0x20a9, 0x0005, 0x8213, 0x1f04, 0x235c, 0xa294,
- 0x00e0, 0x2104, 0xa084, 0xff1f, 0xa205, 0x200a, 0x8319, 0x0118,
- 0x2009, 0x0201, 0x0c78, 0x0005, 0x2011, 0x0101, 0xd3fc, 0x1110,
- 0x2011, 0x0201, 0x20a9, 0x000c, 0x810b, 0x1f04, 0x2374, 0xa18c,
- 0xf000, 0x2204, 0xa084, 0x0fff, 0xa105, 0x2012, 0x0005, 0x2011,
- 0x0102, 0xd3fc, 0x1110, 0x2011, 0x0202, 0x2204, 0xa084, 0xf0cf,
- 0xa105, 0x2012, 0x0005, 0x00c6, 0x2061, 0x0100, 0xd1bc, 0x1110,
- 0x2061, 0x0200, 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0020, 0x609a,
- 0x62ac, 0x63ac, 0x00ce, 0x0005, 0x00c6, 0x2061, 0x0100, 0xd1bc,
- 0x1110, 0x2061, 0x0200, 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0022,
- 0x609a, 0x60a4, 0xa084, 0xffdf, 0x60ae, 0x00ce, 0x0005, 0x00c6,
- 0x2061, 0x0100, 0xd1bc, 0x1110, 0x2061, 0x0200, 0xc1bc, 0x8103,
- 0x8003, 0xa080, 0x0020, 0x609a, 0x60a4, 0xa28c, 0x0020, 0x0118,
- 0xc2ac, 0xa39d, 0x4000, 0xc3ec, 0xd3b4, 0x1108, 0xc3ed, 0x62ae,
- 0x2010, 0x60a4, 0x63ae, 0x2018, 0x00ce, 0x0005, 0x2091, 0x8000,
- 0x00c6, 0x00e6, 0x6818, 0xa005, 0x0904, 0x2427, 0xd1fc, 0x0118,
- 0x2061, 0x8dd0, 0x0010, 0x2061, 0x8cc0, 0x080c, 0x242f, 0x0560,
- 0x20a9, 0x0101, 0xd1fc, 0x0118, 0x2061, 0x8cd0, 0x0010, 0x2061,
- 0x8bc0, 0x00c6, 0x080c, 0x242f, 0x0128, 0x00ce, 0x8c60, 0x1f04,
- 0x23e9, 0x04a8, 0x000e, 0xd1fc, 0x0128, 0xa082, 0x8cd0, 0x2071,
- 0x4680, 0x0020, 0xa082, 0x8bc0, 0x2071, 0x4640, 0x7076, 0x7172,
- 0x2138, 0x2001, 0x0004, 0x7062, 0x707f, 0x000f, 0x71d0, 0xc1c4,
- 0x71d2, 0x080c, 0x22a4, 0x00c0, 0xd1fc, 0x1118, 0x2071, 0x4640,
- 0x0010, 0x2071, 0x4680, 0x6020, 0xc0dd, 0x6022, 0x7172, 0x2138,
- 0x2c00, 0x707a, 0x2001, 0x0006, 0x7062, 0x707f, 0x000f, 0x71d0,
- 0xc1c4, 0x71d2, 0x080c, 0x22a4, 0x2001, 0x0000, 0x0010, 0x2001,
- 0x0001, 0x2091, 0x8001, 0xa005, 0x00ee, 0x00ce, 0x0005, 0x2c04,
- 0xa005, 0x0170, 0x2060, 0x6010, 0xa306, 0x1140, 0x600c, 0xa206,
- 0x1128, 0x6014, 0xa106, 0x1110, 0xa006, 0x0020, 0x6000, 0x0c80,
- 0xa085, 0x0001, 0x0005, 0x00f6, 0x00e6, 0x0016, 0x2079, 0x4680,
- 0x2071, 0x0100, 0xd1bc, 0x1120, 0x2079, 0x4640, 0x2071, 0x0200,
- 0x7920, 0xa18c, 0x000f, 0x70ec, 0xd0c4, 0x1110, 0x001e, 0x0060,
- 0x810b, 0x810b, 0x810b, 0x810b, 0x000e, 0xa18d, 0x0800, 0xd0bc,
- 0x1110, 0xa18d, 0x0f00, 0x2104, 0x00ee, 0x00fe, 0x0005, 0x2001,
- 0x4601, 0x2004, 0xd0ac, 0x1138, 0x68e4, 0xd0ac, 0x0120, 0xa084,
- 0x0006, 0x1108, 0x0009, 0x0005, 0x6014, 0x00e6, 0x0036, 0x2018,
- 0x2071, 0x4b40, 0xd0fc, 0x1110, 0x2071, 0x4ac0, 0x8007, 0xa084,
- 0x000f, 0x8003, 0x8003, 0x8003, 0xae70, 0x7004, 0xa084, 0x000a,
- 0x1904, 0x24fa, 0x7108, 0xa194, 0xff00, 0x0904, 0x24fa, 0xa18c,
- 0x00ff, 0x701c, 0xa084, 0xff00, 0x01c0, 0x7004, 0xa085, 0x003a,
- 0x7006, 0x2001, 0x0009, 0xa102, 0x16d8, 0x2001, 0x000a, 0xa102,
- 0x16d0, 0x2001, 0x000c, 0xa102, 0x16c8, 0x701c, 0xa084, 0x00ff,
- 0x701e, 0x7004, 0xa084, 0xffdf, 0x7006, 0x2001, 0x000a, 0xa106,
- 0x01a8, 0x2001, 0x000c, 0xa106, 0x01a0, 0x2001, 0x0012, 0xa106,
- 0x0198, 0x2001, 0x0014, 0xa106, 0x0190, 0x2001, 0x0019, 0xa106,
- 0x0188, 0x2001, 0x0032, 0xa106, 0x0180, 0x00d8, 0x2009, 0x000c,
- 0x00d0, 0x2009, 0x0012, 0x00b8, 0x2009, 0x0014, 0x00a0, 0x2009,
- 0x0019, 0x0088, 0x2009, 0x0020, 0x0070, 0x2009, 0x003f, 0x0058,
- 0x2009, 0x000a, 0x0040, 0x2009, 0x000c, 0x0028, 0x2009, 0x0019,
- 0x0010, 0x2011, 0x0000, 0x2100, 0xa205, 0x700a, 0x7004, 0xa085,
- 0x000a, 0x7006, 0x2071, 0x4600, 0x7004, 0xd0bc, 0x0158, 0xd3fc,
- 0x1120, 0x73ea, 0x2071, 0x4640, 0x0018, 0x73ee, 0x2071, 0x4680,
- 0x701f, 0x000d, 0x003e, 0x00ee, 0x0005, 0x2001, 0x01ff, 0x2004,
- 0xd0fc, 0x11d0, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x12a0,
- 0x2071, 0x0200, 0x71ec, 0xa18c, 0x1c00, 0x810f, 0x810c, 0x810c,
- 0x2079, 0x0100, 0x78ec, 0xa084, 0x1c00, 0x8007, 0x8004, 0x8004,
- 0xa105, 0xa08a, 0x0007, 0x0208, 0x0005, 0x0002, 0x254b, 0x2532,
- 0x254b, 0x2532, 0x2525, 0x253f, 0x2525, 0x7008, 0xa084, 0xc3ff,
- 0xa085, 0x3000, 0x700a, 0x7808, 0xa084, 0xc3ff, 0xa085, 0x3000,
- 0x780a, 0x0005, 0x7008, 0xa084, 0xc3ff, 0xa085, 0x2000, 0x700a,
- 0x7808, 0xa084, 0xc3ff, 0xa085, 0x2000, 0x780a, 0x0005, 0x7008,
- 0xa084, 0xc3ff, 0xa085, 0x0c00, 0x700a, 0x7808, 0xa084, 0xc3ff,
- 0xa085, 0x0c00, 0x780a, 0x0005, 0x0e04, 0x254c, 0x2091, 0x8000,
- 0x2071, 0x0000, 0x0006, 0x7018, 0xd084, 0x1de8, 0x000e, 0x2071,
- 0x0010, 0x70ca, 0x000e, 0x70c6, 0x70c3, 0x8002, 0x70db, 0x0a04,
- 0x70df, 0x0020, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080,
- 0x0cf8, 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x78a0, 0x708a, 0x758e,
- 0x7492, 0x7696, 0x779a, 0xa594, 0x003f, 0xd4f4, 0x0138, 0xd7bc,
- 0x1128, 0xa784, 0x007d, 0x1904, 0x3c74, 0x0871, 0xa49c, 0x000f,
- 0xa382, 0x0004, 0x0320, 0xa3a6, 0x0007, 0x1930, 0x2418, 0x8507,
- 0xa084, 0x000f, 0x0002, 0x2b49, 0x2c34, 0x2c72, 0x2ed8, 0x3256,
- 0x32ad, 0x3353, 0x33e2, 0x34b6, 0x3588, 0x259e, 0x259b, 0x2970,
- 0x2a56, 0x322a, 0x259b, 0x080c, 0x254c, 0x0005, 0xa006, 0x0038,
- 0x7808, 0xc08d, 0x780a, 0xa006, 0x7002, 0x704a, 0x7042, 0x70ce,
- 0x705c, 0xa005, 0x1904, 0x26ec, 0x7060, 0xa084, 0x0007, 0x0002,
- 0x25b8, 0x2626, 0x262e, 0x2637, 0x2640, 0x26d2, 0x2649, 0x2626,
- 0x7830, 0xd0bc, 0x1d10, 0x71d0, 0xd1bc, 0x19f8, 0xd1b4, 0x1904,
- 0x2603, 0x70a0, 0xa086, 0x0001, 0x09c0, 0x70b0, 0xa06d, 0x6800,
- 0xa065, 0xa055, 0x789b, 0x0080, 0x6b0c, 0x7baa, 0x6808, 0xa045,
- 0x6d10, 0x6804, 0xa06d, 0xa05d, 0xa886, 0x0001, 0x0118, 0x69bc,
- 0x7daa, 0x79aa, 0x68c0, 0xa04d, 0x6e1c, 0x2001, 0x0010, 0x0804,
- 0x281f, 0x705c, 0xa005, 0x1904, 0x259d, 0x00c6, 0x00d6, 0x70b0,
- 0xa06d, 0x6800, 0xa065, 0xa055, 0x789b, 0x0080, 0x6b0c, 0x7baa,
- 0x6808, 0xa045, 0x6d10, 0x6804, 0xa06d, 0xa05d, 0xa886, 0x0001,
- 0x0118, 0x69bc, 0x7daa, 0x79aa, 0x68c0, 0xa04d, 0x6e1c, 0x2001,
- 0x0020, 0x0804, 0x281f, 0x080c, 0x3c33, 0x1904, 0x259d, 0x781b,
- 0x0068, 0x70b8, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de,
- 0x6898, 0x78d2, 0x78da, 0x7808, 0xc08d, 0x780a, 0x68bc, 0x703e,
- 0xc1b4, 0x71d2, 0x70b4, 0xa065, 0x68c0, 0x7056, 0x7003, 0x0002,
- 0x2d00, 0x704a, 0xad80, 0x0009, 0x7042, 0x0005, 0x080c, 0x3c33,
- 0x1120, 0x781b, 0x0054, 0x7003, 0x0004, 0x0005, 0x080c, 0x3c33,
- 0x1128, 0x2011, 0x000c, 0x0419, 0x7003, 0x0004, 0x0005, 0x080c,
- 0x3c33, 0x1128, 0x2011, 0x0006, 0x00d1, 0x7003, 0x0004, 0x0005,
- 0x080c, 0x3c33, 0x1128, 0x2011, 0x000d, 0x0089, 0x7003, 0x0004,
- 0x0005, 0x080c, 0x3c33, 0x1150, 0x2011, 0x0006, 0x0041, 0x7078,
- 0x707b, 0x0000, 0x2068, 0x704a, 0x7003, 0x0004, 0x0005, 0x7170,
- 0xc1fc, 0x8107, 0x7882, 0x789b, 0x0080, 0xa286, 0x000c, 0x1120,
- 0x7aaa, 0x2001, 0x0001, 0x0098, 0xa18c, 0x001f, 0xa18d, 0x00c0,
- 0x79aa, 0xa286, 0x000d, 0x0120, 0x7aaa, 0x2001, 0x0002, 0x0038,
- 0x78ab, 0x0020, 0x7174, 0x79aa, 0x7aaa, 0x2001, 0x0004, 0x789b,
- 0x0060, 0x78aa, 0x785b, 0x0004, 0x781b, 0x0113, 0x080c, 0x3c46,
- 0x707f, 0x000f, 0x70d0, 0xd0b4, 0x0168, 0xc0b4, 0x70d2, 0x00c6,
- 0x70b4, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001,
- 0x601a, 0x00ce, 0x0005, 0x7014, 0xa005, 0x1138, 0x70d0, 0xd0b4,
- 0x0128, 0x70b4, 0xac06, 0x1110, 0x0c29, 0x0005, 0x0016, 0x71a0,
- 0xa186, 0x0001, 0x0528, 0x00d6, 0x0026, 0x2100, 0x2011, 0x0001,
- 0xa212, 0x70b0, 0x2068, 0x6800, 0xac06, 0x0120, 0x8211, 0x01b0,
- 0x00c9, 0x0cc8, 0x00c6, 0x2100, 0x2011, 0x0001, 0xa212, 0x70b0,
- 0x2068, 0x6800, 0x2060, 0x6008, 0xa084, 0xfbef, 0x600a, 0x8211,
- 0x0110, 0x0041, 0x0cb0, 0x70a3, 0x0001, 0x00ce, 0x002e, 0x00de,
- 0x001e, 0x0005, 0xade8, 0x0005, 0x70a8, 0xad06, 0x1110, 0x70a4,
- 0x2068, 0x0005, 0x080c, 0x3c33, 0x1904, 0x259d, 0x7078, 0x2068,
- 0x7770, 0x080c, 0x3b6f, 0x2c50, 0x080c, 0x3cce, 0x789b, 0x0080,
- 0x6814, 0xa084, 0x001f, 0xc0bd, 0x78aa, 0x6e1c, 0x2041, 0x0001,
- 0x2001, 0x0004, 0x0804, 0x2824, 0x080c, 0x3c33, 0x1904, 0x259d,
- 0x789b, 0x0080, 0x705c, 0x2068, 0x6f14, 0x70d0, 0xd0b4, 0x0168,
- 0xc0b4, 0x70d2, 0x00c6, 0x70b4, 0xa065, 0x6008, 0xa084, 0xfbef,
- 0x600a, 0x6018, 0x8001, 0x601a, 0x00ce, 0x080c, 0x3b6f, 0x2c50,
- 0x080c, 0x3cce, 0x6824, 0xa005, 0x0130, 0xa082, 0x0006, 0x0208,
- 0x0010, 0x6827, 0x0005, 0x6814, 0xa084, 0x001f, 0xc0bd, 0x78aa,
- 0x2031, 0x0020, 0x2041, 0x0001, 0x2001, 0x0003, 0x0804, 0x2824,
- 0xc28d, 0x72d2, 0x72bc, 0xa200, 0xa015, 0x7150, 0x8108, 0xa12a,
- 0x0208, 0x71bc, 0x2164, 0x6504, 0x85ff, 0x1170, 0x7152, 0x8421,
- 0x1da8, 0x70d0, 0xd08c, 0x0128, 0x70cc, 0xa005, 0x1110, 0x70cf,
- 0x000a, 0x0005, 0x2200, 0x0c90, 0x70d0, 0xc08c, 0x70d2, 0x70cf,
- 0x0000, 0x6034, 0xa005, 0x1db0, 0x6708, 0xa784, 0x073f, 0x01d0,
- 0xd7d4, 0x1d80, 0xa784, 0x0021, 0x1d68, 0xa784, 0x0002, 0x0130,
- 0xa784, 0x0004, 0x0d38, 0xa7bc, 0xfffb, 0x670a, 0xa784, 0x0218,
- 0x1d08, 0xa784, 0x0100, 0x0130, 0x6018, 0xa005, 0x19d8, 0xa7bc,
- 0xfeff, 0x670a, 0x2568, 0x6823, 0x0000, 0x6e1c, 0xa684, 0x000e,
- 0x6318, 0x0128, 0x601c, 0xa302, 0x0220, 0x0118, 0x0858, 0x83ff,
- 0x1948, 0x2d58, 0x2c50, 0x7152, 0xd7bc, 0x1120, 0x7028, 0x6022,
- 0x603a, 0x0010, 0xc7bc, 0x670a, 0x68c0, 0xa065, 0xa04d, 0x6100,
- 0x2a60, 0x2041, 0x0001, 0x6b14, 0xa39c, 0x001f, 0xa39d, 0x00c0,
- 0xd1fc, 0x0110, 0xd684, 0x0110, 0xa39c, 0xffbf, 0xd6a4, 0x0110,
- 0xa39d, 0x0020, 0xa684, 0x000e, 0x1904, 0x27d6, 0xc7a5, 0x670a,
- 0x2c00, 0x68c6, 0x77a0, 0xa786, 0x0001, 0x1178, 0x70d0, 0xd0b4,
- 0x1160, 0x7000, 0xa082, 0x0002, 0x1240, 0x7830, 0xd0bc, 0x1128,
- 0x789b, 0x0080, 0x7baa, 0x0804, 0x281d, 0x8739, 0x77a2, 0x2750,
- 0x77ac, 0xa7b0, 0x0005, 0x70a8, 0xa606, 0x1108, 0x76a4, 0x76ae,
- 0x2c3a, 0x8738, 0x2d3a, 0x8738, 0x283a, 0x8738, 0x233a, 0x8738,
- 0x253a, 0x7830, 0xd0bc, 0x0150, 0x2091, 0x8000, 0x2091, 0x303d,
- 0x70d0, 0xa084, 0x303d, 0x2091, 0x8000, 0x2090, 0xaad5, 0x0000,
- 0x0120, 0x8421, 0x2200, 0x1904, 0x2725, 0x0005, 0xd1dc, 0x0904,
- 0x37ce, 0x2029, 0x0020, 0xd69c, 0x1120, 0x8528, 0xd68c, 0x1108,
- 0x8528, 0x8840, 0x6f14, 0x610c, 0x8108, 0xa18c, 0x00ff, 0x70c8,
- 0xa160, 0x2c64, 0x8cff, 0x0188, 0x6014, 0xa706, 0x1dd0, 0x60b8,
- 0x8001, 0x60ba, 0x1d88, 0x2a60, 0x6008, 0xa085, 0x0100, 0x600a,
- 0x2200, 0x8421, 0x1904, 0x2725, 0x0005, 0x2a60, 0x610e, 0x69be,
- 0x2c00, 0x68c6, 0x8840, 0x6008, 0xc0d5, 0x600a, 0x77a0, 0xa786,
- 0x0001, 0x1904, 0x27ad, 0x70d0, 0xd0b4, 0x1904, 0x27ad, 0x7000,
- 0xa082, 0x0002, 0x1a04, 0x27ad, 0x7830, 0xd0bc, 0x1904, 0x27ad,
- 0x789b, 0x0080, 0x7baa, 0x7daa, 0x79aa, 0x2001, 0x0002, 0x0006,
- 0x6018, 0x8000, 0x601a, 0x0008, 0x0006, 0x2960, 0x6104, 0x2a60,
- 0x080c, 0x3ce1, 0x1590, 0xa184, 0x0018, 0x0180, 0xa184, 0x0010,
- 0x0118, 0x080c, 0x3977, 0x1548, 0xa184, 0x0008, 0x0138, 0x69a0,
- 0xa184, 0x0600, 0x1118, 0x080c, 0x3895, 0x00f8, 0x69a0, 0xa184,
- 0x1e00, 0x0528, 0xa184, 0x0800, 0x0178, 0x00c6, 0x2960, 0x6000,
- 0xa085, 0x2000, 0x6002, 0x6104, 0xa18d, 0x0010, 0x6106, 0x00ce,
- 0x080c, 0x3977, 0x1150, 0x69a0, 0xa184, 0x0200, 0x0118, 0x080c,
- 0x38da, 0x0018, 0xa184, 0x0400, 0x19f0, 0x69a0, 0xa184, 0x1000,
- 0x0130, 0x6914, 0xa18c, 0xff00, 0x810f, 0x080c, 0x239c, 0x002e,
- 0xa68c, 0x00e0, 0xa684, 0x0060, 0x0128, 0xa086, 0x0060, 0x1110,
- 0xa18d, 0x4000, 0xa18d, 0x0104, 0x69b6, 0x789b, 0x0060, 0x2800,
- 0x78aa, 0x6818, 0xc0fd, 0x681a, 0xd6bc, 0x0168, 0xc0fc, 0x7083,
- 0x0000, 0xa08a, 0x000d, 0x0328, 0xa08a, 0x000c, 0x7182, 0x2001,
- 0x000c, 0x800c, 0x7186, 0x78aa, 0x3518, 0x3340, 0x3428, 0x8000,
- 0x80ac, 0xaf80, 0x002b, 0x20a0, 0x789b, 0x0000, 0xad80, 0x000b,
- 0x2098, 0x53a6, 0x23a8, 0x2898, 0x25a0, 0xa286, 0x0020, 0x1508,
- 0x70d0, 0xc0b5, 0x70d2, 0x2c00, 0x70b6, 0x2d00, 0x70ba, 0x6814,
- 0xc0fc, 0x8007, 0x7882, 0xa286, 0x0002, 0x0904, 0x28f5, 0x70a0,
- 0x8000, 0x70a2, 0x74b0, 0xa498, 0x0005, 0x70a8, 0xa306, 0x1108,
- 0x73a4, 0x73b2, 0xa286, 0x0010, 0x0904, 0x259d, 0x00de, 0x00ce,
- 0x0005, 0x7000, 0xa005, 0x19e0, 0xa286, 0x0002, 0x1904, 0x290c,
- 0x080c, 0x3c33, 0x19a8, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x2091,
- 0x8000, 0x781b, 0x0068, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de,
- 0x6898, 0x78d2, 0x78da, 0x2091, 0x8001, 0x7808, 0xc08d, 0x780a,
- 0x0126, 0x00d6, 0x00c6, 0x70d0, 0xa084, 0x2e00, 0x2090, 0x00ce,
- 0x00de, 0x012e, 0x2900, 0x7056, 0x68bc, 0x703e, 0x7003, 0x0002,
- 0x2d00, 0x704a, 0xad80, 0x0009, 0x7042, 0x7830, 0xd0bc, 0x0140,
- 0x2091, 0x303d, 0x70d0, 0xa084, 0x303d, 0x2091, 0x8000, 0x2090,
- 0x70a0, 0xa005, 0x1108, 0x0005, 0x8421, 0x0de8, 0x724c, 0x70bc,
- 0xa200, 0xa015, 0x0804, 0x2725, 0xa286, 0x0010, 0x1560, 0x080c,
- 0x3c33, 0x1904, 0x28a0, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x781b,
- 0x0068, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2,
- 0x78da, 0x7808, 0xc08d, 0x780a, 0x70a0, 0x8000, 0x70a2, 0x74b0,
- 0xa490, 0x0005, 0x70a8, 0xa206, 0x1108, 0x72a4, 0x72b2, 0x2900,
- 0x7056, 0x68bc, 0x703e, 0x7003, 0x0002, 0x2d00, 0x704a, 0xad80,
- 0x0009, 0x7042, 0x0005, 0x6bb4, 0xa39d, 0x2000, 0x7b5a, 0x6814,
- 0xc0fc, 0x8007, 0x7882, 0x6b94, 0x7bd6, 0x7bde, 0x6e98, 0x7ed2,
- 0x7eda, 0x781b, 0x0068, 0x2900, 0x7056, 0x7202, 0x7808, 0xc08d,
- 0x780a, 0x2300, 0xa605, 0x0170, 0x70d0, 0xa084, 0x2e00, 0xa086,
- 0x2600, 0x1118, 0x2009, 0x0000, 0x0010, 0x2009, 0x0001, 0xa284,
- 0x000f, 0x0023, 0xad80, 0x0009, 0x7042, 0x0005, 0x296e, 0x41d9,
- 0x41d9, 0x41c7, 0x41d9, 0x296e, 0x296e, 0x296e, 0x080c, 0x254c,
- 0x7808, 0xa084, 0xfffd, 0x780a, 0x00f6, 0x2079, 0x4600, 0x78ac,
- 0x00fe, 0xd084, 0x01b0, 0x7060, 0xa086, 0x0001, 0x0904, 0x2a32,
- 0x7060, 0xa086, 0x0005, 0x1158, 0x7078, 0x2068, 0x681b, 0x0004,
+ 0x0110, 0xc0c5, 0x7812, 0x080c, 0x1b34, 0x000e, 0x7812, 0x080c,
+ 0x1b7f, 0x2001, 0x4007, 0x0804, 0x13bc, 0x6104, 0xa18c, 0x00ff,
+ 0xa186, 0x0005, 0x1118, 0x601c, 0xc0bd, 0x601e, 0x74c4, 0x73c8,
+ 0x72cc, 0x6014, 0x2091, 0x8000, 0x00e6, 0x2009, 0x0012, 0xd0fc,
+ 0x1118, 0x2071, 0x4740, 0x0018, 0x2071, 0x4780, 0xc1fd, 0x792a,
+ 0x7063, 0x0005, 0x71d0, 0xc1c4, 0x71d2, 0x7366, 0x726a, 0x746e,
+ 0x7072, 0x7077, 0x0000, 0x2c00, 0x707a, 0xa02e, 0x2530, 0x611c,
+ 0xa184, 0x0060, 0x0110, 0x080c, 0x3fe9, 0x00ee, 0x6596, 0x65a6,
+ 0x669a, 0x66aa, 0x60af, 0x0000, 0x60b3, 0x0000, 0x6714, 0x6023,
+ 0x0000, 0x6024, 0xa096, 0x0001, 0x1110, 0x8000, 0x6026, 0x080c,
+ 0x22d5, 0x2091, 0x8001, 0x0005, 0x70c3, 0x4005, 0x0804, 0x13bd,
+ 0x20a9, 0x0005, 0x2099, 0x4714, 0x2091, 0x8000, 0x530a, 0x2091,
+ 0x8001, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9,
+ 0x0000, 0x0005, 0x71c4, 0x70c7, 0x0000, 0x791e, 0x0804, 0x13ba,
+ 0x71c4, 0x71c6, 0x2168, 0x0010, 0x2069, 0x1000, 0x690c, 0xa016,
+ 0x2d04, 0xa210, 0x8d68, 0x8109, 0x1dd8, 0xa285, 0x0000, 0x1118,
+ 0x70c3, 0x4000, 0x0010, 0x70c3, 0x4003, 0x70ca, 0x0804, 0x13bd,
+ 0x7964, 0x71c6, 0x71c4, 0xa182, 0x0003, 0x1a04, 0x13b3, 0x7966,
+ 0x0804, 0x13ba, 0x7964, 0x71c6, 0x0804, 0x13ba, 0x7900, 0x71c6,
+ 0x71c4, 0x7902, 0x0804, 0x13ba, 0x7900, 0x71c6, 0x0804, 0x13ba,
+ 0x70c4, 0x2011, 0x0000, 0xa08c, 0x000d, 0x0160, 0x810c, 0x0230,
+ 0x8210, 0x810c, 0x810c, 0x0210, 0x8210, 0x810c, 0x81ff, 0x1904,
+ 0x13b4, 0x8210, 0x7a0e, 0xd28c, 0x0538, 0x7910, 0xc1cd, 0x7912,
+ 0x2009, 0x0021, 0x2019, 0x0003, 0xd284, 0x01c0, 0x8108, 0x2019,
+ 0x0041, 0x2011, 0x8f4e, 0x2312, 0x2019, 0x0042, 0x8210, 0x2312,
+ 0x2019, 0x0043, 0x8210, 0x2312, 0x2019, 0x0046, 0x8210, 0x2312,
+ 0x2019, 0x0047, 0x8210, 0x2312, 0x2019, 0x0006, 0x2011, 0x8f53,
+ 0x2112, 0x2011, 0x8f73, 0x2312, 0x7904, 0x7806, 0x0804, 0x13b9,
+ 0x7804, 0x70c6, 0x0804, 0x13ba, 0x71c4, 0xd1fc, 0x1118, 0x2011,
+ 0x4bc0, 0x0010, 0x2011, 0x4c40, 0x8107, 0xa084, 0x000f, 0x8003,
+ 0x8003, 0x8003, 0xa268, 0x2011, 0x0000, 0x6814, 0xd0fc, 0x0110,
+ 0xa295, 0x0200, 0xd0b4, 0x0110, 0xa295, 0x0001, 0x6b0c, 0x6800,
+ 0x70da, 0x0804, 0x13b7, 0x7814, 0xd0f4, 0x0130, 0x2001, 0x4007,
+ 0x70db, 0x0000, 0xa005, 0x0048, 0xd0fc, 0x0130, 0x2001, 0x4007,
+ 0x70db, 0x0001, 0xa005, 0x0008, 0xa006, 0x0005, 0x7814, 0xd0f4,
+ 0x0130, 0x2001, 0x4007, 0x70db, 0x0000, 0xa005, 0x0008, 0xa006,
+ 0x0005, 0x7814, 0xd0fc, 0x0130, 0x2001, 0x4007, 0x70db, 0x0001,
+ 0xa005, 0x0008, 0xa006, 0x0005, 0x7112, 0x721a, 0x731e, 0x7810,
+ 0xd0c4, 0x0110, 0x7422, 0x7526, 0xac80, 0x0001, 0x8108, 0x810c,
+ 0x81a9, 0x8098, 0x20a1, 0x0030, 0x7003, 0x0000, 0x6084, 0x20a2,
+ 0x53a6, 0x7007, 0x0001, 0x7974, 0xa184, 0xff00, 0x0140, 0x810f,
+ 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0018, 0x8107,
+ 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78, 0xa006, 0xa211, 0x7d10,
+ 0xd5c4, 0x0120, 0x7b84, 0xa319, 0x7c80, 0xa421, 0x7008, 0xd0fc,
+ 0x0de8, 0x7003, 0x0001, 0x7007, 0x0006, 0x711a, 0x721e, 0x7d10,
+ 0xd5c4, 0x0110, 0x7322, 0x7426, 0xa084, 0x01e0, 0x0005, 0x7848,
+ 0xa065, 0x0120, 0x2c04, 0x784a, 0x2063, 0x0000, 0x0005, 0x00f6,
+ 0x2079, 0x4700, 0x7848, 0x2062, 0x2c00, 0xa005, 0x1110, 0x080c,
+ 0x2575, 0x784a, 0x00fe, 0x0005, 0x2011, 0x9100, 0x7a4a, 0x7bc4,
+ 0x8319, 0x0128, 0xa280, 0x0032, 0x2012, 0x2010, 0x0cc8, 0x2013,
+ 0x0000, 0x0005, 0x0016, 0x0026, 0xd7fc, 0x1118, 0x2011, 0x4cc0,
+ 0x0010, 0x2011, 0x6cc0, 0xa784, 0x0f00, 0x800b, 0xa784, 0x001f,
+ 0x0120, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xa268, 0x002e,
+ 0x001e, 0x0005, 0x0c39, 0x2900, 0x682a, 0x2a00, 0x682e, 0x6808,
+ 0xa084, 0xf9ef, 0xa80d, 0x690a, 0x00e6, 0xd7fc, 0x1128, 0x2009,
+ 0x4752, 0x2071, 0x4740, 0x0020, 0x2009, 0x4792, 0x2071, 0x4780,
+ 0x210c, 0x6804, 0xa005, 0x0148, 0xa116, 0x1138, 0x2060, 0x6000,
+ 0x6806, 0x0016, 0x200b, 0x0000, 0x0018, 0x2009, 0x0000, 0x0016,
+ 0x6804, 0xa065, 0x0178, 0x6000, 0x6806, 0x0421, 0x080c, 0x1db2,
+ 0x6810, 0x7908, 0x8109, 0x790a, 0x8001, 0x6812, 0x1d88, 0x7910,
+ 0xc1a5, 0x7912, 0x001e, 0x6902, 0x6906, 0x2d00, 0x2060, 0x080c,
+ 0x26bf, 0x00ee, 0x0005, 0xa065, 0x0160, 0x2008, 0x609c, 0xa005,
+ 0x0128, 0x2062, 0x609f, 0x0000, 0xa065, 0x0cc0, 0x7848, 0x794a,
+ 0x2062, 0x0005, 0x6007, 0x0103, 0x608f, 0x0000, 0x20a9, 0x001c,
+ 0xac80, 0x0005, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x6828, 0x601a,
+ 0x682c, 0x6022, 0x0005, 0x00e6, 0xd7fc, 0x1128, 0x2071, 0x4740,
+ 0x2031, 0x47c0, 0x0020, 0x2071, 0x4780, 0x2031, 0x49c0, 0x704c,
+ 0xa08c, 0x0200, 0x1128, 0xa608, 0x2d0a, 0x8000, 0x704e, 0xa006,
+ 0x00ee, 0x0005, 0x00f6, 0xd7fc, 0x1118, 0x2079, 0x4740, 0x0010,
+ 0x2079, 0x4780, 0x080c, 0x1b9a, 0x2091, 0x8000, 0x6804, 0x780a,
+ 0xa065, 0x05f0, 0x0030, 0x2c00, 0x780a, 0x2060, 0x6000, 0xa065,
+ 0x05b8, 0x6010, 0xa306, 0x1db8, 0x600c, 0xa206, 0x1da0, 0x2c28,
+ 0x7848, 0xac06, 0x1108, 0x0448, 0x6804, 0xac06, 0x1140, 0x6000,
+ 0x2060, 0x6806, 0xa005, 0x1118, 0x6803, 0x0000, 0x0048, 0x6400,
+ 0x7808, 0x2060, 0x6402, 0xa486, 0x0000, 0x1110, 0x2c00, 0x6802,
+ 0x2560, 0x080c, 0x1c02, 0x601b, 0x0005, 0x6023, 0x0020, 0x00fe,
+ 0x080c, 0x1db2, 0x00f6, 0x7908, 0x8109, 0x790a, 0x6810, 0x8001,
+ 0x6812, 0x1118, 0x7810, 0xc0a5, 0x7812, 0x2001, 0xffff, 0xa005,
+ 0x00fe, 0x0005, 0x0076, 0x2700, 0x2039, 0x0000, 0xd0fc, 0x0108,
+ 0xc7fd, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008, 0x2091,
+ 0x8000, 0x080c, 0x1bb2, 0x8738, 0xa784, 0x001f, 0x1dd0, 0xa7bc,
+ 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x1d90, 0x2091,
+ 0x8001, 0x007e, 0x0005, 0x786c, 0x2009, 0x8f74, 0x210c, 0xa10d,
+ 0x0118, 0xa065, 0x0804, 0x20a1, 0x2061, 0x0000, 0x6018, 0xd084,
+ 0x11b8, 0x7810, 0xd08c, 0x0130, 0xc08c, 0x7812, 0xc7fc, 0x2069,
+ 0x4740, 0x0028, 0xc08d, 0x7812, 0x2069, 0x4780, 0xc7fd, 0x2091,
+ 0x8000, 0x681c, 0x681f, 0x0000, 0x2091, 0x8001, 0xa005, 0x1108,
+ 0x0005, 0xa08c, 0xfff0, 0x0110, 0x080c, 0x2575, 0x0002, 0x1cd7,
+ 0x1cda, 0x1ce0, 0x1ce4, 0x1cd8, 0x1ce8, 0x1cd8, 0x1cd8, 0x1cd8,
+ 0x1cee, 0x1d18, 0x1d1b, 0x1d20, 0x1d29, 0x1cd8, 0x1cd8, 0x0005,
+ 0x080c, 0x2575, 0x080c, 0x1c7a, 0x2001, 0x8001, 0x0804, 0x1d32,
+ 0x2001, 0x8003, 0x0804, 0x1d32, 0x2001, 0x8004, 0x0804, 0x1d32,
+ 0x080c, 0x1c7a, 0x2001, 0x8006, 0x0804, 0x1d32, 0x2011, 0x800a,
+ 0x2091, 0x8000, 0xd7fc, 0x1118, 0x2069, 0x4740, 0x0010, 0x2069,
+ 0x4780, 0x2038, 0x6800, 0xa086, 0x0000, 0x0120, 0x6f1e, 0x2091,
+ 0x8001, 0x0005, 0x0026, 0x6870, 0xa0bc, 0xff00, 0x2041, 0x0021,
+ 0x2049, 0x0004, 0x2051, 0x0010, 0x080c, 0x1bb2, 0x8738, 0xa784,
+ 0x001f, 0x1dd0, 0x2091, 0x8001, 0x000e, 0x6970, 0x71c6, 0x00d0,
+ 0x2001, 0x800c, 0x00b8, 0x080c, 0x1c7a, 0x2001, 0x800d, 0x0090,
+ 0xd7fc, 0x0110, 0x78e4, 0x0008, 0x78e0, 0x70c6, 0x2001, 0x800e,
+ 0x0048, 0xd7fc, 0x0110, 0x78ec, 0x0008, 0x78e8, 0x70c6, 0x2001,
+ 0x800f, 0x0000, 0x70c2, 0xd7fc, 0x1118, 0x70db, 0x0000, 0x0010,
+ 0x70db, 0x0001, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x4080,
+ 0x0005, 0xac80, 0x0001, 0x81ff, 0x0518, 0x2099, 0x0030, 0x20a0,
+ 0x700c, 0xa084, 0x07ff, 0x0100, 0x7018, 0x0006, 0x701c, 0x0006,
+ 0x7020, 0x0006, 0x7024, 0x0006, 0x7112, 0x81ac, 0x721a, 0x731e,
+ 0x7422, 0x7526, 0x7003, 0x0001, 0x7007, 0x0001, 0x7008, 0x800b,
+ 0x1ee8, 0x7007, 0x0002, 0xa08c, 0x01e0, 0x1110, 0x53a5, 0xa006,
+ 0x7003, 0x0000, 0x7007, 0x0004, 0x000e, 0x7026, 0x000e, 0x7022,
+ 0x000e, 0x701e, 0x000e, 0x701a, 0x0005, 0x2011, 0x0020, 0x2009,
+ 0x0010, 0x6b0a, 0x6c0e, 0x681f, 0x0201, 0x6803, 0xfd20, 0x6807,
+ 0x0038, 0x6a1a, 0x2d00, 0xa0e8, 0x0008, 0xa290, 0x0004, 0x8109,
+ 0x1d80, 0x0005, 0x70ec, 0xd0dc, 0x1520, 0x2029, 0x0001, 0x7814,
+ 0xd0cc, 0x1160, 0x70ec, 0xd0e4, 0x2019, 0x0c0a, 0x2021, 0x000a,
+ 0x1120, 0x2019, 0x0c0c, 0x2021, 0x000c, 0x0070, 0x70ec, 0xd0e4,
+ 0x1128, 0x2019, 0x180c, 0x2021, 0x000c, 0x0030, 0x2019, 0x1809,
+ 0x2021, 0x0009, 0xa5ad, 0x0200, 0x6b0a, 0x6c0e, 0x6d1e, 0x6807,
+ 0x0038, 0x0005, 0x6004, 0x6086, 0x2c08, 0x2063, 0x0000, 0x7868,
+ 0xa005, 0x796a, 0x0110, 0x2c02, 0x0008, 0x796e, 0x0005, 0x00c6,
+ 0x2061, 0x4700, 0x6887, 0x0103, 0x2d08, 0x206b, 0x0000, 0x6068,
+ 0xa005, 0x616a, 0x0110, 0x2d02, 0x0008, 0x616e, 0x00ce, 0x0005,
+ 0x2091, 0x8000, 0x2c04, 0x786e, 0xa005, 0x1108, 0x786a, 0x2091,
+ 0x8001, 0x609c, 0xa005, 0x0188, 0x00c6, 0x2060, 0x2008, 0x609c,
+ 0xa005, 0x0138, 0x2062, 0x609f, 0x0000, 0xa065, 0x609c, 0xa005,
+ 0x1dc8, 0x7848, 0x794a, 0x2062, 0x00ce, 0x7848, 0x2062, 0x609f,
+ 0x0000, 0xac85, 0x0000, 0x1110, 0x080c, 0x2575, 0x784a, 0x0005,
+ 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e, 0x1208, 0xa200,
+ 0x1f04, 0x1dfc, 0x8086, 0x818e, 0x0005, 0x0156, 0x20a9, 0x0010,
+ 0xa005, 0x01b8, 0xa11a, 0x12a8, 0x8213, 0x818d, 0x0228, 0xa11a,
+ 0x1220, 0x1f04, 0x1e0c, 0x0028, 0xa11a, 0x2308, 0x8210, 0x1f04,
+ 0x1e0c, 0x0006, 0x3200, 0xa084, 0xefff, 0x2080, 0x000e, 0x015e,
+ 0x0005, 0x0006, 0x3200, 0xa085, 0x1000, 0x0cb8, 0x7d74, 0x70d0,
+ 0xa506, 0x0904, 0x1eda, 0x7810, 0x2050, 0x080c, 0x1b77, 0x0904,
+ 0x1eda, 0xa046, 0x7970, 0x2500, 0x8000, 0xa112, 0x2009, 0x0040,
+ 0x1208, 0x0030, 0x72d0, 0xa206, 0x0118, 0x8840, 0x2009, 0x0080,
+ 0x00c6, 0x7112, 0x7007, 0x0001, 0x2099, 0x0030, 0x20a9, 0x0020,
+ 0xac80, 0x0001, 0x20a0, 0x2061, 0x0000, 0x88ff, 0x0110, 0x080c,
+ 0x1b77, 0x7008, 0xd0fc, 0x0de8, 0x7007, 0x0002, 0x2091, 0x8001,
+ 0xa08c, 0x01e0, 0x1538, 0x53a5, 0x8cff, 0x1120, 0x88ff, 0x0904,
+ 0x1ec7, 0x0050, 0x2c00, 0x788e, 0x20a9, 0x0020, 0xac80, 0x0001,
+ 0x20a0, 0x53a5, 0x0804, 0x1ec7, 0xa046, 0x7218, 0x731c, 0xdac4,
+ 0x0110, 0x7420, 0x7524, 0xa292, 0x0040, 0xa39b, 0x0000, 0xa4a3,
+ 0x0000, 0xa5ab, 0x0000, 0x721a, 0x731e, 0xdac4, 0x0118, 0x7422,
+ 0x7526, 0xa006, 0x7007, 0x0004, 0x0904, 0x1ec7, 0x8cff, 0x0110,
+ 0x080c, 0x1b7f, 0x00ce, 0x080c, 0x1b7f, 0xa046, 0x7888, 0x8000,
+ 0x788a, 0xa086, 0x0002, 0x01c0, 0x7a7c, 0x7b78, 0xdac4, 0x0110,
+ 0x7c84, 0x7d80, 0x7974, 0x8107, 0x8004, 0x8004, 0xa210, 0xa399,
+ 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x721a, 0x731e, 0xdac4,
+ 0x0588, 0x7422, 0x7526, 0x0470, 0x6014, 0xd0fc, 0x1118, 0x2069,
+ 0x4740, 0x0010, 0x2069, 0x4780, 0x2091, 0x8000, 0x681f, 0x0002,
+ 0x88ff, 0x0120, 0xa046, 0x788c, 0x2060, 0x0c70, 0x788b, 0x0000,
+ 0x78ac, 0xa085, 0x0003, 0x78ae, 0x2091, 0x8001, 0x0098, 0x00ce,
+ 0x788b, 0x0000, 0x080c, 0x205c, 0x6004, 0xa084, 0x000f, 0x0059,
+ 0x88ff, 0x0130, 0x788c, 0x2060, 0x6004, 0xa084, 0x000f, 0x0019,
+ 0x0804, 0x1e26, 0x0005, 0x0002, 0x1eec, 0x1f07, 0x1f20, 0x1eec,
+ 0x1f2d, 0x1efd, 0x1eec, 0x1eec, 0x1eec, 0x1f05, 0x1f1e, 0x1eec,
+ 0x1eec, 0x1eec, 0x1eec, 0x1eec, 0x2039, 0x0400, 0x78bc, 0xa705,
+ 0x78be, 0x6008, 0xa705, 0x600a, 0x080c, 0x1f69, 0x609c, 0x78ba,
+ 0x609f, 0x0000, 0x080c, 0x2048, 0x0005, 0x78bc, 0xd0c4, 0x0108,
+ 0x0c58, 0x601c, 0xc0bd, 0x601e, 0x0030, 0x080c, 0x2086, 0x78bc,
+ 0xd0c4, 0x0108, 0x0c08, 0x78bf, 0x0000, 0x6004, 0x8007, 0xa084,
+ 0x00ff, 0x78b2, 0x8001, 0x0138, 0x080c, 0x1f69, 0x0120, 0x78bc,
+ 0xc0c5, 0x78be, 0x0010, 0x0804, 0x1f84, 0x0005, 0x080c, 0x2083,
+ 0x78bc, 0xa08c, 0x0e00, 0x1110, 0xd0c4, 0x1108, 0x0828, 0x080c,
+ 0x1f69, 0x1110, 0x0804, 0x1f84, 0x0005, 0x78bc, 0xd0c4, 0x0110,
+ 0x0804, 0x1eec, 0x78bf, 0x0000, 0x6714, 0x2011, 0x0001, 0x22a8,
+ 0x6018, 0xa084, 0x00ff, 0xa005, 0x0188, 0xa7bc, 0xff00, 0x20a9,
+ 0x0020, 0xa08e, 0x0001, 0x0150, 0xa7bc, 0x8000, 0x2011, 0x0002,
+ 0x20a9, 0x0100, 0xa08e, 0x0002, 0x0108, 0x00c0, 0x080c, 0x1b9a,
+ 0x2d00, 0x2091, 0x8000, 0x682b, 0x0000, 0x682f, 0x0000, 0x6808,
+ 0xa084, 0xffde, 0x680a, 0xade8, 0x0010, 0x2091, 0x8001, 0x1f04,
+ 0x1f51, 0x8211, 0x0118, 0x20a9, 0x0100, 0x0c58, 0x080c, 0x1b7f,
+ 0x0005, 0x609f, 0x0000, 0x78b4, 0xa06d, 0x2c00, 0x78b6, 0x1110,
+ 0x78ba, 0x0038, 0x689e, 0x2d00, 0x6002, 0x78b8, 0xad06, 0x1108,
+ 0x6002, 0x78b0, 0x8001, 0x78b2, 0x1130, 0x78bc, 0xc0c4, 0x78be,
+ 0x78b8, 0x2060, 0xa006, 0x0005, 0x00e6, 0xa02e, 0x2530, 0x7dba,
+ 0x7db6, 0x65ae, 0x65b2, 0x601c, 0x60a2, 0x2048, 0xa984, 0xe1ff,
+ 0x601e, 0xa984, 0x0060, 0x0160, 0x080c, 0x3fe9, 0x86ff, 0x1140,
+ 0x85ff, 0x1130, 0x2039, 0x0800, 0x080c, 0x2048, 0x0804, 0x2046,
+ 0x6596, 0x65a6, 0x669a, 0x66aa, 0x6714, 0x2071, 0x4780, 0xd7fc,
+ 0x1110, 0x2071, 0x4740, 0xa784, 0x0f00, 0x800b, 0xa784, 0x001f,
+ 0x0120, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0x71c0, 0xa168,
+ 0x2700, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0x71c4,
+ 0xa100, 0x60c2, 0x2091, 0x8000, 0x7814, 0xd0c4, 0x0138, 0xd7fc,
+ 0x1118, 0xd0f4, 0x1140, 0x0010, 0xd0fc, 0x1128, 0x6e08, 0xd684,
+ 0x01f0, 0xd9fc, 0x11e0, 0x2091, 0x8001, 0x080c, 0x1c02, 0x2091,
+ 0x8000, 0x080c, 0x1db2, 0x2091, 0x8001, 0x7814, 0xd0c4, 0x0904,
+ 0x2046, 0xd7fc, 0x1120, 0xd0f4, 0x1130, 0x0804, 0x2046, 0xd0fc,
+ 0x1110, 0x0804, 0x2046, 0x601b, 0x0021, 0x0804, 0x2046, 0x6024,
+ 0xa096, 0x0001, 0x1110, 0x8000, 0x6026, 0x6a10, 0x6814, 0xa202,
+ 0x0268, 0x0160, 0x2091, 0x8001, 0x2039, 0x0200, 0x609c, 0x78ba,
+ 0x609f, 0x0000, 0x080c, 0x2048, 0x0804, 0x2046, 0x2c08, 0xd9fc,
+ 0x01f0, 0x6800, 0xa065, 0x01d8, 0x6a04, 0x7000, 0xa084, 0x0002,
+ 0x0168, 0x7048, 0xa206, 0x1150, 0x6b04, 0x2160, 0x2304, 0x6002,
+ 0xa005, 0x1108, 0x6902, 0x2260, 0x6102, 0x0098, 0x2d00, 0x2060,
+ 0x080c, 0x26bf, 0x6e08, 0x2160, 0x6202, 0x6906, 0x0050, 0x6800,
+ 0x6902, 0xa065, 0x0110, 0x6102, 0x0008, 0x6906, 0x2160, 0x6003,
+ 0x0000, 0x2160, 0xd9fc, 0x0118, 0xa6b4, 0xfffc, 0x6e0a, 0x6810,
+ 0x7d08, 0x8528, 0x7d0a, 0x8000, 0x6812, 0x2091, 0x8001, 0xd6b4,
+ 0x0128, 0xa6b6, 0x0040, 0x6e0a, 0x080c, 0x1c13, 0x00ee, 0x0005,
+ 0x6008, 0xa705, 0x600a, 0x2091, 0x8000, 0x080c, 0x1db2, 0x2091,
+ 0x8001, 0x78b8, 0xa065, 0x0128, 0x609c, 0x78ba, 0x609f, 0x0000,
+ 0x0c78, 0x78b6, 0x78ba, 0x0005, 0x7970, 0x7874, 0x2818, 0xd384,
+ 0x0118, 0x8000, 0xa112, 0x0220, 0x8000, 0xa112, 0x1278, 0xc384,
+ 0x7a7c, 0x721a, 0x7a78, 0x721e, 0xdac4, 0x0120, 0x7a84, 0x7222,
+ 0x7a80, 0x7226, 0xa006, 0xd384, 0x0108, 0x8000, 0x7876, 0x70d2,
+ 0x781c, 0xa005, 0x0138, 0x8001, 0x781e, 0x1120, 0x0e04, 0x2082,
+ 0x2091, 0x4080, 0x0005, 0x2039, 0x2098, 0x0010, 0x2039, 0x209e,
+ 0x2704, 0xa005, 0x0160, 0xac00, 0x2068, 0x6908, 0x6810, 0x6912,
+ 0x680a, 0x690c, 0x6814, 0x6916, 0x680e, 0x8738, 0x0c88, 0x0005,
+ 0x0003, 0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0015, 0x001b,
+ 0x0000, 0x2041, 0x0000, 0x780c, 0x0002, 0x224a, 0x2225, 0x20a9,
+ 0x2119, 0x2039, 0x8f74, 0x2734, 0x7d10, 0x00c0, 0x6084, 0xa086,
+ 0x0103, 0x1904, 0x2103, 0x6114, 0x6018, 0xa105, 0x0120, 0x86ff,
+ 0x11d8, 0x0804, 0x2103, 0x8603, 0xa080, 0x8f55, 0x620c, 0x2202,
+ 0x8000, 0x6210, 0x2202, 0x080c, 0x1dd0, 0x8630, 0xa68e, 0x000f,
+ 0x0904, 0x2184, 0x786c, 0xa065, 0x1d08, 0x7808, 0xa602, 0x1220,
+ 0xd5ac, 0x1110, 0x263a, 0x0005, 0xa682, 0x0003, 0x1a04, 0x2184,
+ 0x2091, 0x8000, 0x2069, 0x0000, 0x6818, 0xd084, 0x11f8, 0x2011,
+ 0x8f55, 0x2204, 0x70c6, 0x8210, 0x2204, 0x70ca, 0xd684, 0x1130,
+ 0x8210, 0x2204, 0x70da, 0x8210, 0x2204, 0x70de, 0xa685, 0x8020,
+ 0x70c2, 0x681b, 0x0001, 0x2091, 0x4080, 0x7810, 0xa084, 0xffcf,
+ 0x7812, 0x2091, 0x8001, 0x203b, 0x0000, 0x0005, 0x7810, 0xc0ad,
+ 0x7812, 0x0804, 0x2184, 0x263a, 0x080c, 0x2250, 0x1904, 0x226c,
+ 0x786c, 0xa065, 0x1904, 0x20ae, 0x2091, 0x8000, 0x7810, 0xa084,
+ 0xffcf, 0x86ff, 0x0108, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x0804,
+ 0x226c, 0x2039, 0x8f74, 0x2734, 0x7d10, 0x00a0, 0x6084, 0xa086,
+ 0x0103, 0x1904, 0x216e, 0x6114, 0x6018, 0xa105, 0x0120, 0x86ff,
+ 0x11b8, 0x0804, 0x216e, 0xa680, 0x8f55, 0x620c, 0x2202, 0x080c,
+ 0x1dd0, 0x8630, 0xa68e, 0x001e, 0x0904, 0x2184, 0x786c, 0xa065,
+ 0x1d28, 0x7808, 0xa602, 0x1220, 0xd5ac, 0x1110, 0x263a, 0x0005,
+ 0xa682, 0x0006, 0x1a04, 0x2184, 0x2091, 0x8000, 0x2069, 0x0000,
+ 0x6818, 0xd084, 0x11f8, 0x2011, 0x8f55, 0x2009, 0x8f4e, 0x26a8,
+ 0x211c, 0x2204, 0x201a, 0x8108, 0x8210, 0x1f04, 0x2150, 0xa685,
+ 0x8030, 0x70c2, 0x681b, 0x0001, 0x2091, 0x4080, 0x7810, 0xa084,
+ 0xffcf, 0x7812, 0x2091, 0x8001, 0xa006, 0x2009, 0x8f75, 0x200a,
+ 0x203a, 0x0005, 0x7810, 0xc0ad, 0x7812, 0x00b0, 0x263a, 0x080c,
+ 0x2250, 0x1904, 0x226c, 0x786c, 0xa065, 0x1904, 0x211e, 0x2091,
+ 0x8000, 0x7810, 0xa084, 0xffcf, 0x86ff, 0x0108, 0xc0ad, 0x7812,
+ 0x2091, 0x8001, 0x0804, 0x226c, 0x2091, 0x8000, 0x7007, 0x0004,
+ 0x7994, 0x70d4, 0xa102, 0x0228, 0x0168, 0x7b90, 0xa302, 0x1150,
+ 0x0010, 0x8002, 0x1138, 0x263a, 0x7810, 0xc0ad, 0x7812, 0x2091,
+ 0x8001, 0x0005, 0xa184, 0xff00, 0x0140, 0x810f, 0x810c, 0x810c,
+ 0x8004, 0x8004, 0x8007, 0xa100, 0x0018, 0x8107, 0x8004, 0x8004,
+ 0x7a9c, 0xa210, 0x721a, 0x7a98, 0xa006, 0xa211, 0x721e, 0xd4c4,
+ 0x0130, 0x7aa4, 0xa211, 0x7222, 0x7aa0, 0xa211, 0x7226, 0x20a1,
+ 0x0030, 0x7003, 0x0000, 0x2009, 0x8f54, 0x260a, 0x8109, 0x2198,
+ 0x2104, 0xd084, 0x0108, 0x8633, 0xa6b0, 0x0002, 0x26a8, 0x53a6,
+ 0x8603, 0x7012, 0x7007, 0x0001, 0x7990, 0x7894, 0x8000, 0xa10a,
+ 0x1208, 0xa006, 0x2028, 0x7974, 0xa184, 0xff00, 0x0140, 0x810f,
+ 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0018, 0x8107,
+ 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78, 0xa006, 0xa211, 0xd4c4,
+ 0x0120, 0x7b84, 0xa319, 0x7c80, 0xa421, 0x7008, 0xd0fc, 0x0de8,
+ 0xa084, 0x01e0, 0x01d0, 0x7d10, 0x2031, 0x8f54, 0x2634, 0x78a8,
+ 0x8000, 0x78aa, 0xd08c, 0x1138, 0x7007, 0x0006, 0x7004, 0xd094,
+ 0x1de8, 0x0804, 0x2186, 0x2069, 0x4747, 0x206b, 0x0003, 0x78ac,
+ 0xa085, 0x0300, 0x78ae, 0xa006, 0x0048, 0x2030, 0x75d6, 0x2091,
+ 0x4080, 0x7d96, 0x7d10, 0xa5ac, 0xffcf, 0x7d12, 0x2091, 0x8001,
+ 0x78aa, 0x7007, 0x0006, 0x263a, 0x7003, 0x0001, 0x711a, 0x721e,
+ 0xd5c4, 0x0110, 0x7322, 0x7426, 0x0005, 0x6084, 0xa086, 0x0103,
+ 0x11d8, 0x6114, 0x6018, 0xa105, 0x11b8, 0x2069, 0x0000, 0x6818,
+ 0xd084, 0x1190, 0x600c, 0x70c6, 0x6010, 0x70ca, 0x70c3, 0x8020,
+ 0x681b, 0x0001, 0x2091, 0x4080, 0x080c, 0x1dd0, 0x0e04, 0x2243,
+ 0x786c, 0xa065, 0x1d10, 0x0005, 0x0059, 0x1530, 0x786c, 0xa065,
+ 0x19e0, 0x0410, 0x0029, 0x1500, 0x786c, 0xa065, 0x1dd8, 0x00e0,
+ 0x6084, 0xa086, 0x0103, 0x1168, 0x6018, 0xc0fc, 0x601a, 0xa086,
+ 0x0004, 0x1138, 0x7804, 0xd0a4, 0x0120, 0x080c, 0x1dd0, 0xa006,
+ 0x0005, 0x0079, 0x1118, 0xa085, 0x0001, 0x0005, 0x00b9, 0x1110,
+ 0x2041, 0x0001, 0x7d10, 0x0005, 0x88ff, 0x0110, 0x2091, 0x4080,
+ 0x0005, 0x7b90, 0x7994, 0x70d4, 0xa102, 0x1118, 0xa385, 0x0000,
+ 0x0005, 0x0210, 0xa302, 0x0005, 0x8002, 0x0005, 0xa184, 0xff00,
+ 0x0140, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100,
+ 0x0018, 0x8107, 0x8004, 0x8004, 0x7a9c, 0x7b98, 0x7ca4, 0x7da0,
+ 0xa210, 0xa006, 0xa319, 0xa421, 0xa529, 0x2009, 0x0018, 0x6028,
+ 0xa005, 0x0110, 0x2009, 0x0040, 0x080c, 0x1b34, 0x01d0, 0x78a8,
+ 0x8000, 0x78aa, 0xd08c, 0x1510, 0x6014, 0xd0fc, 0x1118, 0x2069,
+ 0x4740, 0x0010, 0x2069, 0x4780, 0x2091, 0x8000, 0x681f, 0x0003,
+ 0x78ab, 0x0000, 0x78ac, 0xa085, 0x0300, 0x78ae, 0x2091, 0x8001,
+ 0x0068, 0x78ab, 0x0000, 0x080c, 0x1dd0, 0x7990, 0x7894, 0x8000,
+ 0xa10a, 0x1208, 0xa006, 0x7896, 0x70d6, 0xa006, 0x2071, 0x0010,
+ 0x2091, 0x8001, 0x0005, 0xd7fc, 0x1118, 0x2009, 0x4758, 0x0010,
+ 0x2009, 0x4798, 0x2091, 0x8000, 0x200a, 0x00f6, 0x2009, 0x4780,
+ 0x2079, 0x0100, 0xd7fc, 0x1120, 0x2009, 0x4740, 0x2079, 0x0200,
+ 0x2104, 0xa086, 0x0000, 0x1180, 0xd7fc, 0x1118, 0x2009, 0x4745,
+ 0x0010, 0x2009, 0x4785, 0x2104, 0xa005, 0x1130, 0x7830, 0xa084,
+ 0x00c0, 0x1110, 0x781b, 0x0052, 0x00fe, 0x0005, 0x2009, 0x0002,
+ 0x2069, 0x4700, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x234b,
+ 0x2071, 0x4780, 0x2079, 0x0100, 0x2021, 0x49bf, 0x784b, 0x000f,
+ 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x0118, 0x2019, 0x3e37, 0x0030,
+ 0x20a1, 0x012b, 0x2019, 0x3e37, 0xd184, 0x0110, 0x20a1, 0x022b,
+ 0x2304, 0xa005, 0x0140, 0x789a, 0x8318, 0x23ac, 0x8318, 0x2398,
+ 0x53a6, 0x3318, 0x0ca8, 0x789b, 0x0000, 0x789b, 0x0020, 0x20a9,
+ 0x0010, 0x78af, 0x0000, 0x78af, 0x2020, 0x1f04, 0x2329, 0x7003,
+ 0x0000, 0x0016, 0xd18c, 0x2009, 0x0000, 0x0108, 0xc1bd, 0x080c,
+ 0x246c, 0x001e, 0x7020, 0xa084, 0x000f, 0xa085, 0x6300, 0x7806,
+ 0x780f, 0x9000, 0x7843, 0x00d8, 0x7853, 0x0090, 0x780b, 0x2f08,
+ 0x7452, 0x704f, 0x0000, 0x8109, 0x0140, 0x2071, 0x4740, 0x2079,
+ 0x0200, 0x2021, 0x47bf, 0x0804, 0x2306, 0x080c, 0x2526, 0x0005,
+ 0x0016, 0x2011, 0x0101, 0xd1bc, 0x1110, 0x2011, 0x0201, 0xa18c,
+ 0x000f, 0x2204, 0xa084, 0xfff0, 0xa105, 0x2012, 0x001e, 0x080c,
+ 0x246c, 0x0005, 0x2011, 0x0101, 0xd3fc, 0x1110, 0x2011, 0x0201,
+ 0x20a9, 0x0009, 0x810b, 0x1f04, 0x2372, 0xa18c, 0x0e00, 0x2204,
+ 0xa084, 0xf1ff, 0xa105, 0x2012, 0x0005, 0x2019, 0x0002, 0x2009,
+ 0x0101, 0x20a9, 0x0005, 0x8213, 0x1f04, 0x2383, 0xa294, 0x00e0,
+ 0x2104, 0xa084, 0xff1f, 0xa205, 0x200a, 0x8319, 0x0118, 0x2009,
+ 0x0201, 0x0c78, 0x0005, 0x2011, 0x0101, 0xd3fc, 0x1110, 0x2011,
+ 0x0201, 0x20a9, 0x000c, 0x810b, 0x1f04, 0x239b, 0xa18c, 0xf000,
+ 0x2204, 0xa084, 0x0fff, 0xa105, 0x2012, 0x0005, 0x2011, 0x0102,
+ 0xd3fc, 0x1110, 0x2011, 0x0202, 0x2204, 0xa09c, 0x0f30, 0xa084,
+ 0xf0cf, 0xa105, 0x2012, 0x0005, 0x00c6, 0x2061, 0x0100, 0xd1bc,
+ 0x1110, 0x2061, 0x0200, 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0020,
+ 0x609a, 0x62ac, 0x63ac, 0x00ce, 0x0005, 0x00c6, 0x2061, 0x0100,
+ 0xd1bc, 0x1110, 0x2061, 0x0200, 0xc1bc, 0x8103, 0x8003, 0xa080,
+ 0x0022, 0x609a, 0x60a4, 0xa084, 0xffdf, 0x60ae, 0x00ce, 0x0005,
+ 0x00c6, 0x2061, 0x0100, 0xd1bc, 0x1110, 0x2061, 0x0200, 0xc1bc,
+ 0x8103, 0x8003, 0xa080, 0x0020, 0x609a, 0x60a4, 0xa28c, 0x0020,
+ 0x0118, 0xc2ac, 0xa39d, 0x4000, 0xc3ec, 0xd3b4, 0x1108, 0xc3ed,
+ 0x62ae, 0x2010, 0x60a4, 0x63ae, 0x2018, 0x00ce, 0x0005, 0x2091,
+ 0x8000, 0x00c6, 0x00e6, 0x6818, 0xa005, 0x0904, 0x2450, 0xd1fc,
+ 0x0118, 0x2061, 0x8ed0, 0x0010, 0x2061, 0x8dc0, 0x080c, 0x2458,
+ 0x0560, 0x20a9, 0x0101, 0xd1fc, 0x0118, 0x2061, 0x8dd0, 0x0010,
+ 0x2061, 0x8cc0, 0x00c6, 0x080c, 0x2458, 0x0128, 0x00ce, 0x8c60,
+ 0x1f04, 0x2412, 0x04a8, 0x000e, 0xd1fc, 0x0128, 0xa082, 0x8dd0,
+ 0x2071, 0x4780, 0x0020, 0xa082, 0x8cc0, 0x2071, 0x4740, 0x7076,
+ 0x7172, 0x2138, 0x2001, 0x0004, 0x7062, 0x707f, 0x000f, 0x71d0,
+ 0xc1c4, 0x71d2, 0x080c, 0x22cb, 0x00c0, 0xd1fc, 0x1118, 0x2071,
+ 0x4740, 0x0010, 0x2071, 0x4780, 0x6020, 0xc0dd, 0x6022, 0x7172,
+ 0x2138, 0x2c00, 0x707a, 0x2001, 0x0006, 0x7062, 0x707f, 0x000f,
+ 0x71d0, 0xc1c4, 0x71d2, 0x080c, 0x22cb, 0x2001, 0x0000, 0x0010,
+ 0x2001, 0x0001, 0x2091, 0x8001, 0xa005, 0x00ee, 0x00ce, 0x0005,
+ 0x2c04, 0xa005, 0x0170, 0x2060, 0x6010, 0xa306, 0x1140, 0x600c,
+ 0xa206, 0x1128, 0x6014, 0xa106, 0x1110, 0xa006, 0x0020, 0x6000,
+ 0x0c80, 0xa085, 0x0001, 0x0005, 0x00f6, 0x00e6, 0x0016, 0x2079,
+ 0x4780, 0x2071, 0x0100, 0xd1bc, 0x1120, 0x2079, 0x4740, 0x2071,
+ 0x0200, 0x7920, 0xa18c, 0x000f, 0x70ec, 0xd0c4, 0x1110, 0x001e,
+ 0x0060, 0x810b, 0x810b, 0x810b, 0x810b, 0x000e, 0xa18d, 0x0800,
+ 0xd0bc, 0x1110, 0xa18d, 0x0f00, 0x2104, 0x00ee, 0x00fe, 0x0005,
+ 0x2001, 0x4701, 0x2004, 0xd0ac, 0x1138, 0x68e4, 0xd0ac, 0x0120,
+ 0xa084, 0x0006, 0x1108, 0x0009, 0x0005, 0x6014, 0x00e6, 0x0036,
+ 0x2018, 0x2071, 0x4c40, 0xd0fc, 0x1110, 0x2071, 0x4bc0, 0x8007,
+ 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xae70, 0x7004, 0xa084,
+ 0x000a, 0x1904, 0x2523, 0x7108, 0xa194, 0xff00, 0x0904, 0x2523,
+ 0xa18c, 0x00ff, 0x701c, 0xa084, 0xff00, 0x01c0, 0x7004, 0xa085,
+ 0x003a, 0x7006, 0x2001, 0x0009, 0xa102, 0x16d8, 0x2001, 0x000a,
+ 0xa102, 0x16d0, 0x2001, 0x000c, 0xa102, 0x16c8, 0x701c, 0xa084,
+ 0x00ff, 0x701e, 0x7004, 0xa084, 0xffdf, 0x7006, 0x2001, 0x000a,
+ 0xa106, 0x01a8, 0x2001, 0x000c, 0xa106, 0x01a0, 0x2001, 0x0012,
+ 0xa106, 0x0198, 0x2001, 0x0014, 0xa106, 0x0190, 0x2001, 0x0019,
+ 0xa106, 0x0188, 0x2001, 0x0032, 0xa106, 0x0180, 0x00d8, 0x2009,
+ 0x000c, 0x00d0, 0x2009, 0x0012, 0x00b8, 0x2009, 0x0014, 0x00a0,
+ 0x2009, 0x0019, 0x0088, 0x2009, 0x0020, 0x0070, 0x2009, 0x003f,
+ 0x0058, 0x2009, 0x000a, 0x0040, 0x2009, 0x000c, 0x0028, 0x2009,
+ 0x0019, 0x0010, 0x2011, 0x0000, 0x2100, 0xa205, 0x700a, 0x7004,
+ 0xa085, 0x000a, 0x7006, 0x2071, 0x4700, 0x7004, 0xd0bc, 0x0158,
+ 0xd3fc, 0x1120, 0x73ea, 0x2071, 0x4740, 0x0018, 0x73ee, 0x2071,
+ 0x4780, 0x701f, 0x000d, 0x003e, 0x00ee, 0x0005, 0x2001, 0x01ff,
+ 0x2004, 0xd0fc, 0x11d0, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005,
+ 0x12a0, 0x2071, 0x0200, 0x71ec, 0xa18c, 0x1c00, 0x810f, 0x810c,
+ 0x810c, 0x2079, 0x0100, 0x78ec, 0xa084, 0x1c00, 0x8007, 0x8004,
+ 0x8004, 0xa105, 0xa08a, 0x0007, 0x0208, 0x0005, 0x0002, 0x2574,
+ 0x255b, 0x2574, 0x255b, 0x254e, 0x2568, 0x254e, 0x7008, 0xa084,
+ 0xc3ff, 0xa085, 0x3000, 0x700a, 0x7808, 0xa084, 0xc3ff, 0xa085,
+ 0x3000, 0x780a, 0x0005, 0x7008, 0xa084, 0xc3ff, 0xa085, 0x2000,
+ 0x700a, 0x7808, 0xa084, 0xc3ff, 0xa085, 0x2000, 0x780a, 0x0005,
+ 0x7008, 0xa084, 0xc3ff, 0xa085, 0x0c00, 0x700a, 0x7808, 0xa084,
+ 0xc3ff, 0xa085, 0x0c00, 0x780a, 0x0005, 0x0e04, 0x2575, 0x2091,
+ 0x8000, 0x2071, 0x0000, 0x0006, 0x7018, 0xd084, 0x1de8, 0x000e,
+ 0x2071, 0x0010, 0x70ca, 0x000e, 0x70c6, 0x70c3, 0x8002, 0x70db,
+ 0x0a04, 0x70df, 0x002a, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091,
+ 0x4080, 0x0cf8, 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x78a0, 0x708a,
+ 0x758e, 0x7492, 0x7696, 0x779a, 0xa594, 0x003f, 0xd4f4, 0x0138,
+ 0xd7bc, 0x1128, 0xa784, 0x007d, 0x1904, 0x3c9c, 0x0871, 0xa49c,
+ 0x000f, 0xa382, 0x0004, 0x0320, 0xa3a6, 0x0007, 0x1930, 0x2418,
+ 0x8507, 0xa084, 0x000f, 0x0002, 0x2b6c, 0x2c57, 0x2c95, 0x2efb,
+ 0x3279, 0x32d0, 0x3376, 0x3405, 0x34d9, 0x35ab, 0x25c7, 0x25c4,
+ 0x299e, 0x2a85, 0x324d, 0x25c4, 0x080c, 0x2575, 0x0005, 0xa006,
+ 0x0038, 0x7808, 0xc08d, 0x780a, 0xa006, 0x7002, 0x704a, 0x7042,
+ 0x70ce, 0x705c, 0xa005, 0x1904, 0x2718, 0x7060, 0xa084, 0x0007,
+ 0x0002, 0x25e1, 0x2652, 0x265a, 0x2663, 0x266c, 0x26fe, 0x2675,
+ 0x2652, 0x7830, 0xd0bc, 0x1d10, 0x71d0, 0xd1bc, 0x19f8, 0xd1b4,
+ 0x1904, 0x262f, 0x70a0, 0xa086, 0x0001, 0x09c0, 0x7014, 0xa005,
+ 0x19a8, 0x70b0, 0xa06d, 0x6800, 0xa065, 0xa055, 0x789b, 0x0080,
+ 0x6b0c, 0x7baa, 0x6808, 0xa045, 0x6d10, 0x6804, 0xa06d, 0xa05d,
+ 0xa886, 0x0001, 0x0118, 0x69bc, 0x7daa, 0x79aa, 0x68c0, 0xa04d,
+ 0x6e1c, 0x2001, 0x0010, 0x0804, 0x284b, 0x705c, 0xa005, 0x1904,
+ 0x25c6, 0x00c6, 0x00d6, 0x70b0, 0xa06d, 0x6800, 0xa065, 0xa055,
+ 0x789b, 0x0080, 0x6b0c, 0x7baa, 0x6808, 0xa045, 0x6d10, 0x6804,
+ 0xa06d, 0xa05d, 0xa886, 0x0001, 0x0118, 0x69bc, 0x7daa, 0x79aa,
+ 0x68c0, 0xa04d, 0x6e1c, 0x2001, 0x0020, 0x0804, 0x284b, 0x080c,
+ 0x3c5b, 0x1904, 0x25c6, 0x781b, 0x0068, 0x70b8, 0xa06d, 0x68b4,
+ 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0x7808,
+ 0xc08d, 0x780a, 0x68bc, 0x703e, 0xc1b4, 0x71d2, 0x70b4, 0xa065,
+ 0x68c0, 0x7056, 0x7003, 0x0002, 0x2d00, 0x704a, 0xad80, 0x0009,
+ 0x7042, 0x0005, 0x080c, 0x3c5b, 0x1120, 0x781b, 0x0054, 0x7003,
+ 0x0004, 0x0005, 0x080c, 0x3c5b, 0x1128, 0x2011, 0x000c, 0x0419,
+ 0x7003, 0x0004, 0x0005, 0x080c, 0x3c5b, 0x1128, 0x2011, 0x0006,
+ 0x00d1, 0x7003, 0x0004, 0x0005, 0x080c, 0x3c5b, 0x1128, 0x2011,
+ 0x000d, 0x0089, 0x7003, 0x0004, 0x0005, 0x080c, 0x3c5b, 0x1150,
+ 0x2011, 0x0006, 0x0041, 0x7078, 0x707b, 0x0000, 0x2068, 0x704a,
+ 0x7003, 0x0004, 0x0005, 0x7170, 0xc1fc, 0x8107, 0x7882, 0x789b,
+ 0x0080, 0xa286, 0x000c, 0x1120, 0x7aaa, 0x2001, 0x0001, 0x0098,
+ 0xa18c, 0x001f, 0xa18d, 0x00c0, 0x79aa, 0xa286, 0x000d, 0x0120,
+ 0x7aaa, 0x2001, 0x0002, 0x0038, 0x78ab, 0x0020, 0x7174, 0x79aa,
+ 0x7aaa, 0x2001, 0x0004, 0x789b, 0x0060, 0x78aa, 0x785b, 0x0004,
+ 0x781b, 0x0113, 0x080c, 0x3c6e, 0x707f, 0x000f, 0x70d0, 0xd0b4,
+ 0x0168, 0xc0b4, 0x70d2, 0x00c6, 0x70b4, 0xa065, 0x6008, 0xa084,
+ 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x00ce, 0x0005, 0x7014,
+ 0xa005, 0x1138, 0x70d0, 0xd0b4, 0x0128, 0x70b4, 0xac06, 0x1110,
+ 0x0c29, 0x0005, 0x0016, 0x71a0, 0xa186, 0x0001, 0x0528, 0x00d6,
+ 0x0026, 0x2100, 0x2011, 0x0001, 0xa212, 0x70b0, 0x2068, 0x6800,
+ 0xac06, 0x0120, 0x8211, 0x01b0, 0x00c9, 0x0cc8, 0x00c6, 0x2100,
+ 0x2011, 0x0001, 0xa212, 0x70b0, 0x2068, 0x6800, 0x2060, 0x6008,
+ 0xa084, 0xfbef, 0x600a, 0x8211, 0x0110, 0x0041, 0x0cb0, 0x70a3,
+ 0x0001, 0x00ce, 0x002e, 0x00de, 0x001e, 0x0005, 0xade8, 0x0005,
+ 0x70a8, 0xad06, 0x1110, 0x70a4, 0x2068, 0x0005, 0x080c, 0x3c5b,
+ 0x1904, 0x25c6, 0x7078, 0x2068, 0x7770, 0x080c, 0x3b95, 0x2c50,
+ 0x080c, 0x3cf6, 0x789b, 0x0080, 0x6814, 0xa084, 0x001f, 0xc0bd,
+ 0x78aa, 0x6e1c, 0x2041, 0x0001, 0x2001, 0x0004, 0x0804, 0x2850,
+ 0x080c, 0x3c5b, 0x1904, 0x25c6, 0x789b, 0x0080, 0x705c, 0x2068,
+ 0x6f14, 0x70d0, 0xd0b4, 0x0168, 0xc0b4, 0x70d2, 0x00c6, 0x70b4,
+ 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a,
+ 0x00ce, 0x080c, 0x3b95, 0x2c50, 0x080c, 0x3cf6, 0x6824, 0xa005,
+ 0x0130, 0xa082, 0x0006, 0x0208, 0x0010, 0x6827, 0x0005, 0x6814,
+ 0xa084, 0x001f, 0xc0bd, 0x78aa, 0x2031, 0x0020, 0x2041, 0x0001,
+ 0x2001, 0x0003, 0x0804, 0x2850, 0xc28d, 0x72d2, 0x72bc, 0xa200,
+ 0xa015, 0x7150, 0x8108, 0xa12a, 0x0208, 0x71bc, 0x2164, 0x6504,
+ 0x85ff, 0x1170, 0x7152, 0x8421, 0x1da8, 0x70d0, 0xd08c, 0x0128,
+ 0x70cc, 0xa005, 0x1110, 0x70cf, 0x000a, 0x0005, 0x2200, 0x0c90,
+ 0x70d0, 0xc08c, 0x70d2, 0x70cf, 0x0000, 0x6034, 0xa005, 0x1db0,
+ 0x6708, 0xa784, 0x073f, 0x01d0, 0xd7d4, 0x1d80, 0xa784, 0x0021,
+ 0x1d68, 0xa784, 0x0002, 0x0130, 0xa784, 0x0004, 0x0d38, 0xa7bc,
+ 0xfffb, 0x670a, 0xa784, 0x0218, 0x1d08, 0xa784, 0x0100, 0x0130,
+ 0x6018, 0xa005, 0x19d8, 0xa7bc, 0xfeff, 0x670a, 0x2568, 0x6823,
+ 0x0000, 0x6e1c, 0xa684, 0x000e, 0x6318, 0x0128, 0x601c, 0xa302,
+ 0x0220, 0x0118, 0x0858, 0x83ff, 0x1948, 0x2d58, 0x2c50, 0x7152,
+ 0xd7bc, 0x1120, 0x7028, 0x6022, 0x603a, 0x0010, 0xc7bc, 0x670a,
+ 0x68c0, 0xa065, 0xa04d, 0x6100, 0x2a60, 0x2041, 0x0001, 0x6b14,
+ 0xa39c, 0x001f, 0xa39d, 0x00c0, 0xd1fc, 0x0110, 0xd684, 0x0110,
+ 0xa39c, 0xffbf, 0xd6a4, 0x0110, 0xa39d, 0x0020, 0xa684, 0x000e,
+ 0x1904, 0x2802, 0xc7a5, 0x670a, 0x2c00, 0x68c6, 0x77a0, 0xa786,
+ 0x0001, 0x1178, 0x70d0, 0xd0b4, 0x1160, 0x7000, 0xa082, 0x0002,
+ 0x1240, 0x7830, 0xd0bc, 0x1128, 0x789b, 0x0080, 0x7baa, 0x0804,
+ 0x2849, 0x8739, 0x77a2, 0x2750, 0x77ac, 0xa7b0, 0x0005, 0x70a8,
+ 0xa606, 0x1108, 0x76a4, 0x76ae, 0x2c3a, 0x8738, 0x2d3a, 0x8738,
+ 0x283a, 0x8738, 0x233a, 0x8738, 0x253a, 0x7830, 0xd0bc, 0x0150,
+ 0x2091, 0x8000, 0x2091, 0x303d, 0x70d0, 0xa084, 0x303d, 0x2091,
+ 0x8000, 0x2090, 0xaad5, 0x0000, 0x0120, 0x8421, 0x2200, 0x1904,
+ 0x2751, 0x0005, 0xd1dc, 0x0904, 0x37f1, 0x2029, 0x0020, 0xd69c,
+ 0x1120, 0x8528, 0xd68c, 0x1108, 0x8528, 0x8840, 0x6f14, 0x610c,
+ 0x8108, 0xa18c, 0x00ff, 0x70c8, 0xa160, 0x2c64, 0x8cff, 0x0188,
+ 0x6014, 0xa706, 0x1dd0, 0x60b8, 0x8001, 0x60ba, 0x1d88, 0x2a60,
+ 0x6008, 0xa085, 0x0100, 0x600a, 0x2200, 0x8421, 0x1904, 0x2751,
+ 0x0005, 0x2a60, 0x610e, 0x69be, 0x2c00, 0x68c6, 0x8840, 0x6008,
+ 0xc0d5, 0x600a, 0x77a0, 0xa786, 0x0001, 0x1904, 0x27d9, 0x70d0,
+ 0xd0b4, 0x1904, 0x27d9, 0x7000, 0xa082, 0x0002, 0x1a04, 0x27d9,
+ 0x7830, 0xd0bc, 0x1904, 0x27d9, 0x789b, 0x0080, 0x7baa, 0x7daa,
+ 0x79aa, 0x2001, 0x0002, 0x0006, 0x6018, 0x8000, 0x601a, 0x0008,
+ 0x0006, 0x2960, 0x6104, 0x2a60, 0x080c, 0x3d09, 0x1590, 0xa184,
+ 0x0018, 0x0180, 0xa184, 0x0010, 0x0118, 0x080c, 0x399a, 0x1548,
+ 0xa184, 0x0008, 0x0138, 0x69a0, 0xa184, 0x0600, 0x1118, 0x080c,
+ 0x38b8, 0x00f8, 0x69a0, 0xa184, 0x1e00, 0x0528, 0xa184, 0x0800,
+ 0x0178, 0x00c6, 0x2960, 0x6000, 0xa085, 0x2000, 0x6002, 0x6104,
+ 0xa18d, 0x0010, 0x6106, 0x00ce, 0x080c, 0x399a, 0x1150, 0x69a0,
+ 0xa184, 0x0200, 0x0118, 0x080c, 0x38fd, 0x0018, 0xa184, 0x0400,
+ 0x19f0, 0x69a0, 0xa184, 0x1000, 0x0130, 0x6914, 0xa18c, 0xff00,
+ 0x810f, 0x080c, 0x23c5, 0x002e, 0xa68c, 0x00e0, 0xa684, 0x0060,
+ 0x0128, 0xa086, 0x0060, 0x1110, 0xa18d, 0x4000, 0xa18d, 0x0104,
+ 0x69b6, 0x789b, 0x0060, 0x2800, 0x78aa, 0x6818, 0xc0fd, 0x681a,
+ 0xd6bc, 0x0168, 0xc0fc, 0x7083, 0x0000, 0xa08a, 0x000d, 0x0328,
+ 0xa08a, 0x000c, 0x7182, 0x2001, 0x000c, 0x800c, 0x7186, 0x78aa,
+ 0x3518, 0x3340, 0x3428, 0x8000, 0x80ac, 0xaf80, 0x002b, 0x20a0,
+ 0x789b, 0x0000, 0xad80, 0x000b, 0x2098, 0x53a6, 0x23a8, 0x2898,
+ 0x25a0, 0xa286, 0x0020, 0x1508, 0x70d0, 0xc0b5, 0x70d2, 0x2c00,
+ 0x70b6, 0x2d00, 0x70ba, 0x6814, 0xc0fc, 0x8007, 0x7882, 0xa286,
+ 0x0002, 0x0904, 0x2921, 0x70a0, 0x8000, 0x70a2, 0x74b0, 0xa498,
+ 0x0005, 0x70a8, 0xa306, 0x1108, 0x73a4, 0x73b2, 0xa286, 0x0010,
+ 0x0904, 0x25c6, 0x00de, 0x00ce, 0x0005, 0x7000, 0xa005, 0x19e0,
+ 0xa286, 0x0002, 0x1904, 0x2938, 0x080c, 0x3c5b, 0x19a8, 0x6814,
+ 0xc0fc, 0x8007, 0x7882, 0x2091, 0x8000, 0x781b, 0x0068, 0x68b4,
+ 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0x2091,
+ 0x8001, 0x7808, 0xc08d, 0x780a, 0x0126, 0x00d6, 0x00c6, 0x70d0,
+ 0xa084, 0x2e00, 0x2090, 0x00ce, 0x00de, 0x012e, 0x2900, 0x7056,
+ 0x68bc, 0x703e, 0x7003, 0x0002, 0x2d00, 0x704a, 0xad80, 0x0009,
+ 0x7042, 0x7830, 0xd0bc, 0x0140, 0x2091, 0x303d, 0x70d0, 0xa084,
+ 0x303d, 0x2091, 0x8000, 0x2090, 0x70a0, 0xa005, 0x1108, 0x0005,
+ 0x8421, 0x0de8, 0x724c, 0x70bc, 0xa200, 0xa015, 0x0804, 0x2751,
+ 0xa286, 0x0010, 0x1560, 0x080c, 0x3c5b, 0x1904, 0x28cc, 0x6814,
+ 0xc0fc, 0x8007, 0x7882, 0x781b, 0x0068, 0x68b4, 0x785a, 0x6894,
+ 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0x7808, 0xc08d, 0x780a,
+ 0x70a0, 0x8000, 0x70a2, 0x74b0, 0xa490, 0x0005, 0x70a8, 0xa206,
+ 0x1108, 0x72a4, 0x72b2, 0x2900, 0x7056, 0x68bc, 0x703e, 0x7003,
+ 0x0002, 0x2d00, 0x704a, 0xad80, 0x0009, 0x7042, 0x0005, 0x6bb4,
+ 0xa39d, 0x2000, 0x7b5a, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x6b94,
+ 0x7bd6, 0x7bde, 0x6e98, 0x7ed2, 0x7eda, 0x781b, 0x0068, 0x2900,
+ 0x7056, 0x7202, 0x7808, 0xc08d, 0x780a, 0x2300, 0xa605, 0x0170,
+ 0x70d0, 0xa084, 0x2e00, 0xa086, 0x2600, 0x1118, 0x2009, 0x0000,
+ 0x0010, 0x2009, 0x0001, 0xa284, 0x000f, 0x0033, 0xad80, 0x0009,
+ 0x7042, 0x2d00, 0x704a, 0x0005, 0x299c, 0x4208, 0x4208, 0x41f6,
+ 0x4208, 0x299c, 0x299c, 0x299c, 0x080c, 0x2575, 0x7808, 0xa084,
+ 0xfffd, 0x780a, 0x00f6, 0x2079, 0x4700, 0x78ac, 0x00fe, 0xd084,
+ 0x01c0, 0x7160, 0xa186, 0x0001, 0x0904, 0x2a61, 0xa186, 0x0007,
+ 0x0170, 0xa186, 0x0005, 0x1158, 0x7078, 0x2068, 0x681b, 0x0004,
0x6817, 0x0000, 0x6820, 0xa084, 0x00ff, 0xc09d, 0x6822, 0x7063,
- 0x0000, 0x70a3, 0x0000, 0x70a4, 0x70ae, 0x70b2, 0x080c, 0x2682,
- 0x0156, 0x2011, 0x0004, 0x7160, 0xa186, 0x0001, 0x0160, 0xa186,
- 0x0007, 0x1118, 0x701f, 0x0005, 0x0030, 0x701f, 0x0001, 0x70d0,
- 0xc0c5, 0x70d2, 0x0000, 0x2001, 0x460a, 0x2004, 0xa084, 0x00ff,
- 0xa086, 0x0018, 0x0130, 0x7018, 0x7016, 0xa005, 0x1110, 0x70a3,
- 0x0001, 0x0066, 0x080c, 0x3f26, 0x20a9, 0x0010, 0x2039, 0x0000,
- 0x080c, 0x3a66, 0xa7b8, 0x0100, 0x1f04, 0x29c0, 0x006e, 0x7000,
- 0x0002, 0x29fd, 0x29db, 0x29db, 0x29d3, 0x29fd, 0x29fd, 0x29fd,
- 0x29d1, 0x080c, 0x254c, 0x705c, 0xa005, 0x0538, 0xad06, 0x1118,
- 0x6800, 0x705e, 0x0080, 0x6820, 0xd084, 0x1148, 0x6f14, 0x080c,
- 0x3b6f, 0x6008, 0xc0d4, 0x600a, 0x080c, 0x37a4, 0x0020, 0x7058,
- 0x2060, 0x6800, 0x6002, 0xa684, 0x5f00, 0x681e, 0x6818, 0xd0fc,
- 0x0108, 0x6a1a, 0x6817, 0x0000, 0x682b, 0x0000, 0x6820, 0xa084,
- 0x00ff, 0xc09d, 0x6822, 0x080c, 0x1da2, 0x2011, 0x0004, 0x74c8,
- 0xa4a0, 0x0100, 0x04b1, 0xaea0, 0x0017, 0x0499, 0x20a9, 0x0101,
- 0x74c8, 0x0479, 0x8420, 0x1f04, 0x2a09, 0x70c0, 0x2060, 0x2021,
- 0x0002, 0x20a9, 0x0100, 0x6110, 0x81ff, 0x0198, 0x6018, 0x0016,
- 0x0006, 0x2011, 0x4602, 0x220c, 0xa102, 0x2012, 0x000e, 0x001e,
- 0xa102, 0x0338, 0x6012, 0x1128, 0x2011, 0x4604, 0x2204, 0xc0a5,
- 0x2012, 0x601b, 0x0000, 0xace0, 0x0010, 0x1f04, 0x2a13, 0x8421,
- 0x1d00, 0x015e, 0x7063, 0x0000, 0x7003, 0x0000, 0x704b, 0x0000,
- 0x0005, 0x0046, 0x2404, 0xa005, 0x01a8, 0x2068, 0x6800, 0x0006,
- 0x6a1a, 0x6817, 0x0000, 0x682b, 0x0000, 0x68b4, 0xa084, 0x5f00,
- 0x681e, 0x6820, 0xa084, 0x00ff, 0xc09d, 0x6822, 0x080c, 0x1da2,
- 0x000e, 0x0c48, 0x004e, 0x2023, 0x0000, 0x0005, 0xa282, 0x0003,
- 0x0310, 0x080c, 0x254c, 0x2300, 0x0002, 0x2a60, 0x2add, 0x2af7,
- 0xa282, 0x0002, 0x0110, 0x080c, 0x254c, 0x7060, 0x7063, 0x0000,
- 0x707f, 0x0000, 0x0022, 0x77d0, 0xc7c5, 0x77d2, 0x0002, 0x2a77,
- 0x2a77, 0x2a79, 0x2ab1, 0x37d8, 0x2a77, 0x2ab1, 0x2a77, 0x080c,
- 0x254c, 0x7770, 0x080c, 0x3a66, 0x7770, 0xa7bc, 0x8f00, 0x080c,
- 0x3b6f, 0x6018, 0xa005, 0x0528, 0xd7fc, 0x1118, 0x2021, 0x8cc0,
- 0x0010, 0x2021, 0x8dd0, 0x2009, 0x0005, 0x2011, 0x0010, 0x080c,
- 0x2b11, 0x01b8, 0x0156, 0x20a9, 0x0101, 0xd7fc, 0x1118, 0x2021,
- 0x8bc0, 0x0010, 0x2021, 0x8cd0, 0x0046, 0x2009, 0x0005, 0x2011,
- 0x0010, 0x080c, 0x2b11, 0x004e, 0x0118, 0x8420, 0x1f04, 0x2a9c,
- 0x015e, 0x8738, 0xa784, 0x001f, 0x1990, 0x0804, 0x25a0, 0x0804,
- 0x25a0, 0x7770, 0x080c, 0x3b6f, 0x6018, 0xa005, 0x0520, 0xd7fc,
- 0x1118, 0x2021, 0x8cc0, 0x0010, 0x2021, 0x8dd0, 0x2009, 0x0005,
- 0x2011, 0x0020, 0x080c, 0x2b11, 0x01b0, 0x0156, 0x20a9, 0x0101,
- 0xd7fc, 0x1118, 0x2021, 0x8bc0, 0x0010, 0x2021, 0x8cd0, 0x0046,
- 0x2009, 0x0005, 0x2011, 0x0020, 0x04e1, 0x004e, 0x0118, 0x8420,
- 0x1f04, 0x2acf, 0x015e, 0x0804, 0x25a0, 0x2200, 0x0002, 0x2ae2,
- 0x2ae4, 0x2ae4, 0x080c, 0x254c, 0x2009, 0x0012, 0x7060, 0xa086,
- 0x0002, 0x0110, 0x2009, 0x000e, 0x6818, 0xd0fc, 0x0108, 0x691a,
- 0x7063, 0x0000, 0x70d0, 0xc0c5, 0x70d2, 0x0804, 0x3be5, 0x2200,
- 0x0002, 0x2afe, 0x2ae4, 0x2afc, 0x080c, 0x254c, 0x080c, 0x3f26,
- 0x7000, 0xa086, 0x0002, 0x1904, 0x375d, 0x080c, 0x37be, 0x6008,
- 0xa084, 0xfbef, 0x600a, 0x080c, 0x374f, 0x0904, 0x375d, 0x0804,
- 0x25a0, 0x2404, 0xa005, 0x0590, 0x2068, 0x2d04, 0x0006, 0x6814,
- 0xa706, 0x0118, 0x2d20, 0x000e, 0x0ca8, 0x000e, 0x2022, 0x691a,
+ 0x0000, 0x70a3, 0x0000, 0x70a4, 0x70ae, 0x70b2, 0x080c, 0x26ae,
+ 0x0156, 0x2011, 0x0004, 0x7160, 0xa186, 0x0001, 0x0158, 0xa186,
+ 0x0007, 0x1118, 0x701f, 0x0005, 0x0010, 0x701f, 0x0001, 0x70d0,
+ 0xc0c5, 0x70d2, 0x2001, 0x470a, 0x2004, 0xa084, 0x00ff, 0xa086,
+ 0x0018, 0x0130, 0x7018, 0x7016, 0xa005, 0x1110, 0x70a3, 0x0001,
+ 0x0066, 0x080c, 0x3f4e, 0x20a9, 0x0010, 0x2039, 0x0000, 0x080c,
+ 0x3a8b, 0xa7b8, 0x0100, 0x1f04, 0x29ef, 0x006e, 0x7000, 0x0002,
+ 0x2a2c, 0x2a0a, 0x2a0a, 0x2a02, 0x2a2c, 0x2a2c, 0x2a2c, 0x2a00,
+ 0x080c, 0x2575, 0x705c, 0xa005, 0x0538, 0xad06, 0x1118, 0x6800,
+ 0x705e, 0x0080, 0x6820, 0xd084, 0x1148, 0x6f14, 0x080c, 0x3b95,
+ 0x6008, 0xc0d4, 0x600a, 0x080c, 0x37c7, 0x0020, 0x7058, 0x2060,
+ 0x6800, 0x6002, 0xa684, 0x5f00, 0x681e, 0x6818, 0xd0fc, 0x0108,
+ 0x6a1a, 0x6817, 0x0000, 0x682b, 0x0000, 0x6820, 0xa084, 0x00ff,
+ 0xc09d, 0x6822, 0x080c, 0x1dbf, 0x2011, 0x0004, 0x74c8, 0xa4a0,
+ 0x0100, 0x04b1, 0xaea0, 0x0017, 0x0499, 0x20a9, 0x0101, 0x74c8,
+ 0x0479, 0x8420, 0x1f04, 0x2a38, 0x70c0, 0x2060, 0x2021, 0x0002,
+ 0x20a9, 0x0100, 0x6110, 0x81ff, 0x0198, 0x6018, 0x0016, 0x0006,
+ 0x2011, 0x4702, 0x220c, 0xa102, 0x2012, 0x000e, 0x001e, 0xa102,
+ 0x0338, 0x6012, 0x1128, 0x2011, 0x4704, 0x2204, 0xc0a5, 0x2012,
+ 0x601b, 0x0000, 0xace0, 0x0010, 0x1f04, 0x2a42, 0x8421, 0x1d00,
+ 0x015e, 0x7063, 0x0000, 0x7003, 0x0000, 0x704b, 0x0000, 0x0005,
+ 0x0046, 0x2404, 0xa005, 0x01a8, 0x2068, 0x6800, 0x0006, 0x6a1a,
0x6817, 0x0000, 0x682b, 0x0000, 0x68b4, 0xa084, 0x5f00, 0x681e,
- 0x6820, 0xa084, 0x00ff, 0xa205, 0x6822, 0x080c, 0x1da2, 0x2021,
- 0x4602, 0x241c, 0x8319, 0x2322, 0x6010, 0x8001, 0x6012, 0x1128,
- 0x2021, 0x4604, 0x2404, 0xc0a5, 0x2022, 0x6008, 0xa084, 0xf9ef,
- 0x600a, 0x080c, 0x269e, 0x080c, 0x37be, 0x0005, 0xa085, 0x0001,
- 0x0ce0, 0x2300, 0x0002, 0x2b50, 0x2b4e, 0x2bcb, 0x080c, 0x254c,
- 0x78e4, 0xa005, 0x17b0, 0x3208, 0xa18c, 0x0800, 0x0118, 0x0104,
- 0x259d, 0x0010, 0x0304, 0x259d, 0x2008, 0xa084, 0x0030, 0x1110,
- 0x0804, 0x322a, 0x78ec, 0xa084, 0x0003, 0x0dd0, 0x7884, 0xd0fc,
- 0x1118, 0xa184, 0x0007, 0x0090, 0xa184, 0x0007, 0xa086, 0x0004,
- 0x1118, 0x2001, 0x0000, 0x0050, 0xa184, 0x0007, 0xa086, 0x0005,
- 0x0118, 0xa184, 0x0007, 0x0010, 0x2001, 0x0001, 0x0002, 0x2bae,
- 0x2bb7, 0x2ba4, 0x2b87, 0x3c29, 0x3c29, 0x2b87, 0x2bc1, 0x080c,
- 0x254c, 0x7000, 0xa086, 0x0004, 0x1190, 0x7060, 0xa086, 0x0002,
- 0x1130, 0x2011, 0x0002, 0x2019, 0x0000, 0x0804, 0x2a56, 0x7060,
- 0xa086, 0x0006, 0x0db0, 0x7060, 0xa086, 0x0004, 0x0d90, 0x79e4,
- 0x2001, 0x0003, 0x0804, 0x2f18, 0x6818, 0xd0fc, 0x0110, 0x681b,
- 0x001d, 0x080c, 0x3a3c, 0x781b, 0x006e, 0x0005, 0x6818, 0xd0fc,
- 0x0110, 0x681b, 0x001d, 0x080c, 0x3a3c, 0x0804, 0x3c07, 0x6818,
- 0xd0fc, 0x0110, 0x681b, 0x001d, 0x080c, 0x3a3c, 0x781b, 0x00fa,
- 0x0005, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x001d, 0x080c, 0x3a3c,
- 0x781b, 0x00cb, 0x0005, 0xa584, 0x000f, 0x11c0, 0x7000, 0x0002,
- 0x25a0, 0x2bd8, 0x2bda, 0x375d, 0x375d, 0x375d, 0x2bd8, 0x2bd8,
- 0x080c, 0x254c, 0x080c, 0x37be, 0x6008, 0xa084, 0xfbef, 0x600a,
- 0x080c, 0x374f, 0x0904, 0x375d, 0x0804, 0x25a0, 0x78e4, 0xa005,
- 0x1b04, 0x2b89, 0x3208, 0xa18c, 0x0800, 0x0118, 0x0104, 0x2b89,
- 0x0010, 0x0304, 0x2b89, 0x2008, 0xa084, 0x0030, 0x1118, 0x781b,
- 0x0068, 0x0005, 0x78ec, 0xa084, 0x0003, 0x0dc8, 0x7884, 0xd0fc,
- 0x1118, 0xa184, 0x0007, 0x0090, 0xa184, 0x0007, 0xa086, 0x0004,
- 0x1118, 0x2001, 0x0000, 0x0050, 0xa184, 0x0007, 0xa086, 0x0005,
- 0x0118, 0xa184, 0x0007, 0x0010, 0x2001, 0x0001, 0x0002, 0x2c26,
- 0x2c2a, 0x2c21, 0x2c1f, 0x3c29, 0x3c29, 0x2c1f, 0x3c23, 0x080c,
- 0x254c, 0x080c, 0x3a42, 0x781b, 0x006e, 0x0005, 0x080c, 0x3a42,
- 0x0804, 0x3c07, 0x080c, 0x3a42, 0x781b, 0x00fa, 0x0005, 0x080c,
- 0x3a42, 0x781b, 0x00cb, 0x0005, 0x2300, 0x0002, 0x2c3b, 0x2c39,
- 0x2c3d, 0x080c, 0x254c, 0x0804, 0x33e2, 0x681b, 0x0016, 0x78a3,
- 0x0000, 0x79e4, 0xa184, 0x0030, 0x0904, 0x33e2, 0x78ec, 0xa084,
- 0x0003, 0x0904, 0x33e2, 0xa184, 0x0100, 0x0d98, 0x7884, 0xd0fc,
+ 0x6820, 0xa084, 0x00ff, 0xc09d, 0x6822, 0x080c, 0x1dbf, 0x000e,
+ 0x0c48, 0x004e, 0x2023, 0x0000, 0x0005, 0xa282, 0x0003, 0x0310,
+ 0x080c, 0x2575, 0x2300, 0x0002, 0x2a8f, 0x2b0c, 0x2b1a, 0xa282,
+ 0x0002, 0x0110, 0x080c, 0x2575, 0x7060, 0x7063, 0x0000, 0x707f,
+ 0x0000, 0x0022, 0x77d0, 0xc7c5, 0x77d2, 0x0002, 0x2aa6, 0x2aa6,
+ 0x2aa8, 0x2ae0, 0x37fb, 0x2aa6, 0x2ae0, 0x2aa6, 0x080c, 0x2575,
+ 0x7770, 0x080c, 0x3a8b, 0x7770, 0xa7bc, 0x8f00, 0x080c, 0x3b95,
+ 0x6018, 0xa005, 0x0528, 0xd7fc, 0x1118, 0x2021, 0x8dc0, 0x0010,
+ 0x2021, 0x8ed0, 0x2009, 0x0005, 0x2011, 0x0010, 0x080c, 0x2b34,
+ 0x01b8, 0x0156, 0x20a9, 0x0101, 0xd7fc, 0x1118, 0x2021, 0x8cc0,
+ 0x0010, 0x2021, 0x8dd0, 0x0046, 0x2009, 0x0005, 0x2011, 0x0010,
+ 0x080c, 0x2b34, 0x004e, 0x0118, 0x8420, 0x1f04, 0x2acb, 0x015e,
+ 0x8738, 0xa784, 0x001f, 0x1990, 0x0804, 0x25c9, 0x0804, 0x25c9,
+ 0x7770, 0x080c, 0x3b95, 0x6018, 0xa005, 0x0520, 0xd7fc, 0x1118,
+ 0x2021, 0x8dc0, 0x0010, 0x2021, 0x8ed0, 0x2009, 0x0005, 0x2011,
+ 0x0020, 0x080c, 0x2b34, 0x01b0, 0x0156, 0x20a9, 0x0101, 0xd7fc,
+ 0x1118, 0x2021, 0x8cc0, 0x0010, 0x2021, 0x8dd0, 0x0046, 0x2009,
+ 0x0005, 0x2011, 0x0020, 0x0481, 0x004e, 0x0118, 0x8420, 0x1f04,
+ 0x2afe, 0x015e, 0x0804, 0x25c9, 0x2200, 0x0002, 0x2b11, 0x2b13,
+ 0x2b13, 0x080c, 0x2575, 0x7063, 0x0000, 0x70d0, 0xc0c5, 0x70d2,
+ 0x0804, 0x25c9, 0x2200, 0x0002, 0x2b21, 0x2b13, 0x2b1f, 0x080c,
+ 0x2575, 0x080c, 0x3f4e, 0x7000, 0xa086, 0x0002, 0x1904, 0x3780,
+ 0x080c, 0x37e1, 0x6008, 0xa084, 0xfbef, 0x600a, 0x080c, 0x3772,
+ 0x0904, 0x3780, 0x0804, 0x25c9, 0x2404, 0xa005, 0x0590, 0x2068,
+ 0x2d04, 0x0006, 0x6814, 0xa706, 0x0118, 0x2d20, 0x000e, 0x0ca8,
+ 0x000e, 0x2022, 0x691a, 0x6817, 0x0000, 0x682b, 0x0000, 0x68b4,
+ 0xa084, 0x5f00, 0x681e, 0x6820, 0xa084, 0x00ff, 0xa205, 0x6822,
+ 0x080c, 0x1dbf, 0x2021, 0x4702, 0x241c, 0x8319, 0x2322, 0x6010,
+ 0x8001, 0x6012, 0x1128, 0x2021, 0x4704, 0x2404, 0xc0a5, 0x2022,
+ 0x6008, 0xa084, 0xf9ef, 0x600a, 0x080c, 0x26ca, 0x080c, 0x37e1,
+ 0x0005, 0xa085, 0x0001, 0x0ce0, 0x2300, 0x0002, 0x2b73, 0x2b71,
+ 0x2bee, 0x080c, 0x2575, 0x78e4, 0xa005, 0x17b0, 0x3208, 0xa18c,
+ 0x0800, 0x0118, 0x0104, 0x25c6, 0x0010, 0x0304, 0x25c6, 0x2008,
+ 0xa084, 0x0030, 0x1110, 0x0804, 0x324d, 0x78ec, 0xa084, 0x0003,
+ 0x0dd0, 0x7884, 0xd0fc, 0x1118, 0xa184, 0x0007, 0x0090, 0xa184,
+ 0x0007, 0xa086, 0x0004, 0x1118, 0x2001, 0x0000, 0x0050, 0xa184,
+ 0x0007, 0xa086, 0x0005, 0x0118, 0xa184, 0x0007, 0x0010, 0x2001,
+ 0x0001, 0x0002, 0x2bd1, 0x2bda, 0x2bc7, 0x2baa, 0x3c4f, 0x3c4f,
+ 0x2baa, 0x2be4, 0x080c, 0x2575, 0x7000, 0xa086, 0x0004, 0x1190,
+ 0x7060, 0xa086, 0x0002, 0x1130, 0x2011, 0x0002, 0x2019, 0x0000,
+ 0x0804, 0x2a85, 0x7060, 0xa086, 0x0006, 0x0db0, 0x7060, 0xa086,
+ 0x0004, 0x0d90, 0x79e4, 0x2001, 0x0003, 0x0804, 0x2f3b, 0x6818,
+ 0xd0fc, 0x0110, 0x681b, 0x001d, 0x080c, 0x3a61, 0x781b, 0x006e,
+ 0x0005, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x001d, 0x080c, 0x3a61,
+ 0x0804, 0x3c2d, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x001d, 0x080c,
+ 0x3a61, 0x781b, 0x00fa, 0x0005, 0x6818, 0xd0fc, 0x0110, 0x681b,
+ 0x001d, 0x080c, 0x3a61, 0x781b, 0x00cb, 0x0005, 0xa584, 0x000f,
+ 0x11c0, 0x7000, 0x0002, 0x25c9, 0x2bfb, 0x2bfd, 0x3780, 0x3780,
+ 0x3780, 0x2bfb, 0x2bfb, 0x080c, 0x2575, 0x080c, 0x37e1, 0x6008,
+ 0xa084, 0xfbef, 0x600a, 0x080c, 0x3772, 0x0904, 0x3780, 0x0804,
+ 0x25c9, 0x78e4, 0xa005, 0x1b04, 0x2bac, 0x3208, 0xa18c, 0x0800,
+ 0x0118, 0x0104, 0x2bac, 0x0010, 0x0304, 0x2bac, 0x2008, 0xa084,
+ 0x0030, 0x1118, 0x781b, 0x0068, 0x0005, 0x78ec, 0xa084, 0x0003,
+ 0x0dc8, 0x7884, 0xd0fc, 0x1118, 0xa184, 0x0007, 0x0090, 0xa184,
+ 0x0007, 0xa086, 0x0004, 0x1118, 0x2001, 0x0000, 0x0050, 0xa184,
+ 0x0007, 0xa086, 0x0005, 0x0118, 0xa184, 0x0007, 0x0010, 0x2001,
+ 0x0001, 0x0002, 0x2c49, 0x2c4d, 0x2c44, 0x2c42, 0x3c4f, 0x3c4f,
+ 0x2c42, 0x3c49, 0x080c, 0x2575, 0x080c, 0x3a67, 0x781b, 0x006e,
+ 0x0005, 0x080c, 0x3a67, 0x0804, 0x3c2d, 0x080c, 0x3a67, 0x781b,
+ 0x00fa, 0x0005, 0x080c, 0x3a67, 0x781b, 0x00cb, 0x0005, 0x2300,
+ 0x0002, 0x2c5e, 0x2c5c, 0x2c60, 0x080c, 0x2575, 0x0804, 0x3405,
+ 0x681b, 0x0016, 0x78a3, 0x0000, 0x79e4, 0xa184, 0x0030, 0x0904,
+ 0x3405, 0x78ec, 0xa084, 0x0003, 0x0904, 0x3405, 0xa184, 0x0100,
+ 0x0d98, 0x7884, 0xd0fc, 0x1118, 0xa184, 0x0007, 0x0090, 0xa184,
+ 0x0007, 0xa086, 0x0004, 0x1118, 0x2001, 0x0000, 0x0050, 0xa184,
+ 0x0007, 0xa086, 0x0005, 0x0118, 0xa184, 0x0007, 0x0010, 0x2001,
+ 0x0001, 0x0002, 0x2c92, 0x2c4d, 0x2bc7, 0x3c0b, 0x3c4f, 0x3c4f,
+ 0x3c0b, 0x3c49, 0x080c, 0x3c17, 0x0005, 0xa282, 0x0005, 0x0310,
+ 0x080c, 0x2575, 0x7898, 0x2040, 0x2300, 0x0002, 0x2ca1, 0x2ecb,
+ 0x2ed5, 0x2200, 0x0002, 0x2cbd, 0x2caa, 0x2cbd, 0x2ca8, 0x2ead,
+ 0x080c, 0x2575, 0x789b, 0x0018, 0x78a8, 0x2010, 0xa084, 0x00ff,
+ 0xa082, 0x0020, 0x0a04, 0x3a30, 0xa08a, 0x0004, 0x1a04, 0x3a30,
+ 0x0002, 0x3a30, 0x3a30, 0x3a30, 0x39e4, 0x789b, 0x0018, 0x79a8,
+ 0xa184, 0x0080, 0x0148, 0x0804, 0x3a30, 0x7000, 0xa005, 0x1dd8,
+ 0x2011, 0x0004, 0x0804, 0x35b7, 0xa184, 0x00ff, 0xa08a, 0x0010,
+ 0x1a04, 0x3a30, 0x0002, 0x2ce5, 0x2ce3, 0x2cf7, 0x2cfb, 0x2da9,
+ 0x3a30, 0x3a30, 0x2dab, 0x3a30, 0x3a30, 0x2ea9, 0x2ea9, 0x3a30,
+ 0x3a30, 0x3a30, 0x2eab, 0x080c, 0x2575, 0xd6e4, 0x0140, 0x2001,
+ 0x0300, 0x8000, 0x8000, 0x783a, 0x781b, 0x00c7, 0x0005, 0x6818,
+ 0xd0fc, 0x0118, 0x681b, 0x001d, 0x0c90, 0x0804, 0x3c0b, 0x681b,
+ 0x001d, 0x0804, 0x3a5b, 0x6920, 0x6922, 0xa684, 0x1800, 0x1904,
+ 0x2d4c, 0x6820, 0xd084, 0x1904, 0x2d54, 0x6818, 0xa086, 0x0008,
+ 0x1110, 0x681b, 0x0000, 0xd6d4, 0x0568, 0xd6bc, 0x0558, 0x7083,
+ 0x0000, 0x6818, 0xa084, 0x003f, 0xa08a, 0x000d, 0x0718, 0xa08a,
+ 0x000c, 0x7182, 0x2001, 0x000c, 0x800c, 0x7186, 0x789b, 0x0061,
+ 0x78aa, 0x0156, 0x0136, 0x0146, 0x0016, 0x3208, 0xa18c, 0x0600,
+ 0x0118, 0x20a1, 0x022b, 0x0010, 0x20a1, 0x012b, 0x001e, 0x789b,
+ 0x0000, 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x014e,
+ 0x013e, 0x015e, 0x6038, 0xa005, 0x1150, 0x681c, 0xa084, 0x000e,
+ 0x0904, 0x3a5b, 0x080c, 0x3a6d, 0x782b, 0x3008, 0x0010, 0x8001,
+ 0x603a, 0x781b, 0x0071, 0x0005, 0xd6e4, 0x0130, 0x781b, 0x0083,
+ 0x0005, 0x781b, 0x0083, 0x0005, 0xa684, 0x0060, 0x0dd0, 0xd6dc,
+ 0x0dc0, 0xd6fc, 0x01a0, 0xc6fc, 0x7e5a, 0x6eb6, 0x7adc, 0x79d8,
+ 0x78d0, 0x8007, 0xa084, 0x007f, 0xa108, 0xa291, 0x0000, 0x6b98,
+ 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0xd6f4,
+ 0x0118, 0xc6f4, 0x7e5a, 0x6eb6, 0x7000, 0xa086, 0x0003, 0x1148,
+ 0x0006, 0x080c, 0x3f4e, 0x080c, 0x4208, 0x000e, 0x781b, 0x0080,
+ 0x0005, 0xa006, 0x080c, 0x42e8, 0x6ab0, 0x69ac, 0x6c98, 0x6b94,
+ 0x2200, 0xa105, 0x0120, 0x2200, 0xa422, 0x2100, 0xa31b, 0x6caa,
+ 0x7cd2, 0x7cda, 0x6ba6, 0x7bd6, 0x7bde, 0x2300, 0xa405, 0x1130,
+ 0xc6f5, 0x7e5a, 0x6eb6, 0x781b, 0x0080, 0x0005, 0x781b, 0x0080,
+ 0x2200, 0xa115, 0x1118, 0x080c, 0x4208, 0x0005, 0x080c, 0x4235,
+ 0x0005, 0x080c, 0x2575, 0x0804, 0x2e3f, 0x00c6, 0x7054, 0x2060,
+ 0x6920, 0xa18c, 0xecff, 0x6922, 0x6000, 0xa084, 0xcfdf, 0x6002,
+ 0x080c, 0x3917, 0xa006, 0x2040, 0x2038, 0x080c, 0x39bf, 0x0804,
+ 0x2e33, 0x00c6, 0x7054, 0x2060, 0x2c48, 0x7aa8, 0xa294, 0x00ff,
+ 0xa286, 0x0004, 0x11d8, 0x6920, 0xd1e4, 0x1170, 0x2039, 0x0000,
+ 0x2041, 0x0000, 0x2031, 0x0000, 0xa006, 0x2010, 0x080c, 0x391a,
+ 0x080c, 0x39bf, 0x0804, 0x2e33, 0xa18c, 0xecff, 0x6922, 0x6104,
+ 0xa18c, 0xffdd, 0x6106, 0x6000, 0xc0ac, 0x6002, 0xa286, 0x0003,
+ 0x01d0, 0x6104, 0xa184, 0x0010, 0x0548, 0x080c, 0x3b91, 0x080c,
+ 0x399a, 0x88ff, 0x0518, 0x00ce, 0x789b, 0x0060, 0x2800, 0x78aa,
+ 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x1118, 0x781b, 0x006e, 0x0005,
+ 0x781b, 0x0082, 0x0005, 0x6920, 0xd1cc, 0x0130, 0xa18c, 0xfdff,
+ 0x6922, 0x6000, 0xc0ec, 0x6002, 0x2039, 0x0000, 0x2041, 0x0000,
+ 0x2031, 0x0000, 0xa006, 0x2010, 0x080c, 0x39bf, 0xa286, 0x0001,
+ 0x0158, 0x6104, 0xa184, 0x0008, 0x01b0, 0x080c, 0x3b91, 0x080c,
+ 0x38b8, 0x88ff, 0x1980, 0x0078, 0x6920, 0xd1c4, 0x0130, 0xa18c,
+ 0xfeff, 0x6922, 0x6000, 0xc0e4, 0x6002, 0x2031, 0x0000, 0xa006,
+ 0x2010, 0x080c, 0x391a, 0x00ce, 0x7e58, 0xd6d4, 0x1118, 0x781b,
+ 0x0071, 0x0005, 0x781b, 0x0083, 0x0005, 0x0804, 0x3a57, 0x2808,
+ 0x789b, 0x0080, 0x2019, 0x0080, 0x78a8, 0xa094, 0x00ff, 0xa286,
+ 0x0001, 0x11b8, 0x2300, 0xa102, 0xa086, 0x0001, 0x0904, 0x2dad,
+ 0x7ca8, 0xa4a4, 0x00ff, 0xa480, 0x0002, 0xa300, 0x2018, 0xa102,
+ 0x0a04, 0x2dc1, 0x0904, 0x2dc1, 0x24a8, 0x7aa8, 0x1f04, 0x2e5d,
+ 0x0c18, 0xa284, 0x00f0, 0xa082, 0x0020, 0x06b8, 0x2200, 0xa082,
+ 0x0021, 0x1698, 0x7aa8, 0x8318, 0x8318, 0x2100, 0xa302, 0x0aa0,
+ 0xa286, 0x0023, 0x0950, 0x681c, 0xa084, 0xfff1, 0x681e, 0x7e58,
+ 0xa684, 0xfff1, 0xc0a5, 0x2030, 0x7e5a, 0x6008, 0xc0a5, 0x600a,
+ 0x78a0, 0xa005, 0x0904, 0x2e34, 0x20a8, 0x7998, 0x789b, 0x0060,
+ 0x78aa, 0x2011, 0x0080, 0x799a, 0x78a8, 0x7998, 0x7a9a, 0x78aa,
+ 0x7a98, 0x1f04, 0x2e8b, 0xc695, 0x7e5a, 0xd6d4, 0x1118, 0x781b,
+ 0x006e, 0x0005, 0x781b, 0x0082, 0x0005, 0x8318, 0x2100, 0xa302,
+ 0x0a04, 0x2e44, 0xa284, 0x0080, 0x1904, 0x3a5b, 0x78a0, 0xa005,
+ 0x08c8, 0x0804, 0x3a5b, 0x0804, 0x3a30, 0x7054, 0xa04d, 0x789b,
+ 0x0018, 0x78a8, 0xa084, 0x00ff, 0xa08e, 0x0001, 0x0110, 0x080c,
+ 0x2575, 0x7aa8, 0xa294, 0x00ff, 0x784b, 0x0008, 0x78a8, 0xa084,
+ 0x00ff, 0xa08a, 0x0005, 0x1a04, 0x3a30, 0x0002, 0x3a30, 0x382f,
+ 0x3a30, 0x394a, 0x3d59, 0xa282, 0x0000, 0x1110, 0x080c, 0x2575,
+ 0x080c, 0x3a61, 0x781b, 0x0082, 0x0005, 0xa282, 0x0003, 0x1110,
+ 0x080c, 0x2575, 0xd4fc, 0x11d0, 0x7060, 0xa005, 0x0110, 0x080c,
+ 0x2575, 0x6f14, 0x7772, 0xa7bc, 0x8f00, 0x080c, 0x3b95, 0x6008,
+ 0xa085, 0x0021, 0x600a, 0x8738, 0xa784, 0x001f, 0x1db0, 0x080c,
+ 0x3a64, 0x7063, 0x0002, 0x701f, 0x0009, 0x0010, 0x080c, 0x3a70,
+ 0x781b, 0x0082, 0x0005, 0xa282, 0x0004, 0x0310, 0x080c, 0x2575,
+ 0x2300, 0x0002, 0x2f05, 0x309b, 0x30d7, 0xa286, 0x0003, 0x0598,
+ 0x7200, 0x7cd8, 0x7ddc, 0x7fd0, 0x71d0, 0xd1b4, 0x0528, 0xd1bc,
+ 0x1518, 0x2001, 0x4701, 0x2004, 0xd0c4, 0x11f0, 0x7868, 0xa084,
+ 0x00ff, 0x11d0, 0xa282, 0x0002, 0x12b8, 0x00d6, 0x783b, 0x8300,
+ 0x781b, 0x0059, 0x70b8, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6,
+ 0x78de, 0x6898, 0x78d2, 0x78da, 0xc1b4, 0x71d2, 0x7003, 0x0030,
+ 0x00de, 0x2001, 0x0000, 0x0058, 0x783b, 0x1300, 0x781b, 0x0057,
+ 0x2001, 0x0000, 0x0020, 0x7200, 0x7cd8, 0x7ddc, 0x7fd0, 0x7046,
+ 0x68a0, 0xd0ec, 0x0118, 0x6008, 0xc08d, 0x600a, 0xa284, 0x000f,
+ 0x0002, 0x307c, 0x2f56, 0x2f53, 0x31a7, 0x3232, 0x25c9, 0x2f51,
+ 0x2f51, 0x080c, 0x2575, 0x6008, 0xc0d4, 0x600a, 0xd6e4, 0x0120,
+ 0x7044, 0xa086, 0x0014, 0x11e8, 0x080c, 0x3f4e, 0x2009, 0x0000,
+ 0x6818, 0xd0fc, 0x0108, 0x7044, 0xa086, 0x0014, 0x0168, 0x6818,
+ 0xa086, 0x0008, 0x1904, 0x303e, 0x7858, 0xd09c, 0x0904, 0x303e,
+ 0x6820, 0xd0ac, 0x0904, 0x303e, 0x681b, 0x0014, 0x2009, 0x0002,
+ 0x04a8, 0x7868, 0xa08c, 0x00ff, 0x0588, 0xa186, 0x0008, 0x1158,
+ 0x6008, 0xc0a4, 0x600a, 0x080c, 0x3772, 0x0540, 0x080c, 0x37e1,
+ 0x080c, 0x3f4e, 0x0060, 0xa186, 0x0028, 0x1500, 0x6018, 0xa005,
+ 0x0d78, 0x8001, 0x0d68, 0x8001, 0x0d58, 0x601e, 0x0c48, 0x6820,
+ 0xd084, 0x0904, 0x25c9, 0xc084, 0x6822, 0x080c, 0x26bf, 0x7058,
+ 0x00c6, 0x2060, 0x6800, 0x6002, 0x00ce, 0x6004, 0x6802, 0xa005,
+ 0x2d00, 0x1108, 0x6002, 0x6006, 0x0804, 0x25c9, 0x0016, 0x81ff,
+ 0x15f0, 0x7000, 0xa086, 0x0030, 0x05d0, 0x71d0, 0xd1bc, 0x15b8,
+ 0xd1b4, 0x11e8, 0x705c, 0xa005, 0x1590, 0x70a0, 0xa086, 0x0001,
+ 0x0570, 0x7003, 0x0000, 0x0046, 0x0056, 0x0076, 0x0066, 0x00c6,
+ 0x00d6, 0x080c, 0x25f1, 0x00de, 0x00ce, 0x006e, 0x007e, 0x005e,
+ 0x004e, 0x71d0, 0xd1b4, 0x11d8, 0x7003, 0x0040, 0x00c0, 0x080c,
+ 0x3c5b, 0x11a8, 0x781b, 0x0068, 0x00d6, 0x70b8, 0xa06d, 0x68b4,
+ 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0xc1b4,
+ 0x71d2, 0x7003, 0x0030, 0x7808, 0xc08d, 0x780a, 0x00de, 0x080c,
+ 0x30ff, 0x001e, 0x81ff, 0x0904, 0x303e, 0xa684, 0xdf00, 0x681e,
+ 0x682b, 0x0000, 0x6f14, 0xa186, 0x0002, 0x1904, 0x303f, 0x6818,
+ 0xa086, 0x0014, 0x1130, 0x2008, 0xd6e4, 0x0118, 0x7868, 0xa08c,
+ 0x00ff, 0x080c, 0x3a7a, 0x080c, 0x26ca, 0x6820, 0xd0dc, 0x1578,
+ 0x8717, 0xa294, 0x000f, 0x8213, 0x8213, 0x8213, 0xb284, 0x0600,
+ 0x0118, 0xa290, 0x4bc0, 0x0010, 0xa290, 0x4c40, 0xa290, 0x0000,
+ 0x221c, 0xd3c4, 0x0170, 0x6820, 0xd0e4, 0x0128, 0xa084, 0xefff,
+ 0x6822, 0xc3ac, 0x2312, 0x8210, 0x2204, 0xa085, 0x0038, 0x2012,
+ 0x8211, 0xd3d4, 0x0138, 0x68a0, 0xd0c4, 0x1120, 0x080c, 0x3167,
+ 0x0804, 0x25c9, 0x6008, 0xc08d, 0x600a, 0x0008, 0x692a, 0x6916,
+ 0x6818, 0xd0fc, 0x0110, 0x7044, 0x681a, 0xa68c, 0xdf00, 0x691e,
+ 0x6410, 0x84ff, 0x0168, 0x2009, 0x4702, 0x2104, 0x8001, 0x200a,
+ 0x8421, 0x6412, 0x1128, 0x2021, 0x4704, 0x2404, 0xc0a5, 0x2022,
+ 0x6018, 0xa005, 0x0118, 0x8001, 0x601a, 0x1118, 0x6008, 0xc0a4,
+ 0x600a, 0x6820, 0xd084, 0x1130, 0x6800, 0xa005, 0x1108, 0x6002,
+ 0x6006, 0x0020, 0x7058, 0x2060, 0x6800, 0x6002, 0x2061, 0x4700,
+ 0x6887, 0x0103, 0x2d08, 0x206b, 0x0000, 0x6068, 0xa005, 0x616a,
+ 0x0110, 0x2d02, 0x0008, 0x616e, 0x7200, 0xa286, 0x0030, 0x0158,
+ 0xa286, 0x0040, 0x1904, 0x25c9, 0x7003, 0x0002, 0x7048, 0x2068,
+ 0x68c4, 0x2060, 0x0005, 0x7003, 0x0002, 0x70b8, 0xa06d, 0x68bc,
+ 0x703e, 0x70b4, 0xa065, 0x68c0, 0x7056, 0x2d00, 0x704a, 0xad80,
+ 0x0009, 0x7042, 0x0005, 0xa282, 0x0004, 0x0210, 0x080c, 0x2575,
+ 0x2200, 0x0002, 0x30a6, 0x30b5, 0x30c1, 0x30b5, 0xa586, 0x1300,
+ 0x0160, 0xa586, 0x8300, 0x1d90, 0x7003, 0x0000, 0x6018, 0x8001,
+ 0x601a, 0x6008, 0xa084, 0xfbef, 0x600a, 0x7000, 0xa086, 0x0005,
+ 0x0128, 0x080c, 0x3a61, 0x781b, 0x0082, 0x0005, 0x781b, 0x0083,
+ 0x0005, 0x7890, 0x8007, 0x8001, 0xa084, 0x0007, 0xa080, 0x0018,
+ 0x789a, 0x79a8, 0xa18c, 0x00ff, 0xa186, 0x0003, 0x0128, 0xa186,
+ 0x0000, 0x0110, 0x0804, 0x3a30, 0x781b, 0x0083, 0x0005, 0x6820,
+ 0xc095, 0x6822, 0x82ff, 0x1118, 0x080c, 0x3a61, 0x0030, 0x8211,
+ 0x0110, 0x080c, 0x2575, 0x080c, 0x3a70, 0x781b, 0x0082, 0x0005,
+ 0x080c, 0x3c6e, 0x7830, 0xa084, 0x00c0, 0x1170, 0x0016, 0x3208,
+ 0xa18c, 0x0800, 0x001e, 0x0118, 0x0104, 0x30fc, 0x0010, 0x0304,
+ 0x30fc, 0x791a, 0xa006, 0x0005, 0xa085, 0x0001, 0x0005, 0xa684,
+ 0x0060, 0x1130, 0x682f, 0x0000, 0x6833, 0x0000, 0x0804, 0x3166,
+ 0xd6dc, 0x1198, 0x68b4, 0xd0dc, 0x1180, 0x6998, 0x6a94, 0x692e,
+ 0x6a32, 0x7044, 0xa005, 0x1130, 0x2200, 0xa105, 0x0904, 0x3f4e,
+ 0x7047, 0x0015, 0x0804, 0x3f4e, 0x0005, 0xd6ac, 0x01f0, 0xd6f4,
+ 0x0130, 0x682f, 0x0000, 0x6833, 0x0000, 0x0804, 0x3f4e, 0x68b4,
+ 0xa084, 0x4000, 0xa635, 0xd6f4, 0x1da0, 0x7044, 0xa005, 0x1110,
+ 0x7047, 0x0015, 0xd6dc, 0x1128, 0x68b4, 0xd0dc, 0x0110, 0x6ca8,
+ 0x6da4, 0x6c2e, 0x6d32, 0x0804, 0x3f4e, 0xd6f4, 0x0130, 0x682f,
+ 0x0000, 0x6833, 0x0000, 0x0804, 0x3f4e, 0x68b4, 0xa084, 0x4800,
+ 0xa635, 0xd6f4, 0x1da0, 0x7044, 0xa005, 0x1110, 0x7047, 0x0015,
+ 0x2408, 0x2510, 0x2700, 0x8007, 0xa084, 0x007f, 0xa108, 0xa291,
+ 0x0000, 0x692e, 0x6a32, 0x2100, 0xa205, 0x1110, 0x0804, 0x3f4e,
+ 0x7000, 0xa086, 0x0006, 0x0110, 0x0804, 0x3f4e, 0x0005, 0x6946,
+ 0x6008, 0xc0cd, 0xd3cc, 0x0108, 0xc08d, 0x600a, 0x6818, 0x683a,
+ 0x681b, 0x0006, 0x688f, 0x0000, 0x6893, 0x0000, 0x6a30, 0x692c,
+ 0x6a3e, 0x6942, 0x682f, 0x0003, 0x6833, 0x0000, 0x6837, 0x0020,
+ 0x6897, 0x0000, 0x689b, 0x0020, 0x7000, 0x0002, 0x25c9, 0x3196,
+ 0x3190, 0x318e, 0x318e, 0x318e, 0x318e, 0x318e, 0x080c, 0x2575,
+ 0x6820, 0xd084, 0x1118, 0x080c, 0x37c7, 0x0030, 0x7058, 0x2c50,
+ 0x2060, 0x6800, 0x6002, 0x2a60, 0xaea0, 0x0017, 0x2404, 0xa005,
+ 0x0110, 0x2020, 0x0cd8, 0x2d22, 0x206b, 0x0000, 0x0005, 0x080c,
+ 0x37cd, 0x080c, 0x37e1, 0x6008, 0xc0cc, 0x600a, 0x682b, 0x0000,
+ 0x789b, 0x000e, 0x6f14, 0x6938, 0x691a, 0x6944, 0x6916, 0x2009,
+ 0x0000, 0xae86, 0x4740, 0x0110, 0x2009, 0x0001, 0x080c, 0x431f,
+ 0xd6dc, 0x01c8, 0x691c, 0xc1ed, 0x691e, 0x6828, 0xa082, 0x000e,
+ 0x0290, 0x6848, 0xa084, 0x000f, 0xa086, 0x000b, 0x1160, 0x685c,
+ 0xa086, 0x0047, 0x1140, 0x2001, 0x4701, 0x2004, 0xd0ac, 0x1118,
+ 0x2700, 0x080c, 0x249e, 0x6818, 0xd0fc, 0x0140, 0x681b, 0x0000,
+ 0x7868, 0xa08c, 0x00ff, 0x0110, 0x681b, 0x001e, 0xaea0, 0x0017,
+ 0x6800, 0x2022, 0x6a3c, 0x6940, 0x6a32, 0x692e, 0x68c0, 0x2060,
+ 0x6000, 0xd0a4, 0x0580, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051,
+ 0x0020, 0x00d6, 0x00f6, 0x0156, 0x0146, 0x2079, 0x4700, 0x080c,
+ 0x1bb2, 0x014e, 0x015e, 0x00fe, 0x70c8, 0x2010, 0x2009, 0x0101,
+ 0x0026, 0x2204, 0xa06d, 0x0140, 0x6814, 0xa706, 0x0110, 0x6800,
+ 0x0cc8, 0x6820, 0xc0d5, 0x6822, 0x002e, 0x8210, 0x8109, 0x1d80,
+ 0x00de, 0x7063, 0x0003, 0x707b, 0x0000, 0x7772, 0x707f, 0x000f,
+ 0x71d0, 0xc1c4, 0x71d2, 0x6818, 0xa086, 0x0002, 0x1138, 0x6817,
+ 0x0000, 0x682b, 0x0000, 0x681c, 0xc0ec, 0x681e, 0x080c, 0x1dbf,
+ 0x0804, 0x25c9, 0x7cd8, 0x7ddc, 0x7fd0, 0x080c, 0x30ff, 0x682b,
+ 0x0000, 0x789b, 0x000e, 0x6f14, 0x080c, 0x3c72, 0xa08c, 0x00ff,
+ 0x6916, 0x6818, 0xd0fc, 0x0110, 0x7044, 0x681a, 0xa68c, 0xdf00,
+ 0x691e, 0x7063, 0x0000, 0x0804, 0x25c9, 0x7000, 0xa005, 0x1110,
+ 0x0804, 0x25c9, 0xa006, 0x080c, 0x3f4e, 0x6920, 0xd1ac, 0x1110,
+ 0x681b, 0x0014, 0xa68c, 0xdf00, 0x691e, 0x682b, 0x0000, 0x6820,
+ 0xa084, 0x00ff, 0x6822, 0x7000, 0x0002, 0x25c9, 0x326f, 0x326f,
+ 0x3272, 0x3272, 0x3272, 0x326d, 0x326d, 0x080c, 0x2575, 0x6818,
+ 0x0804, 0x2f3b, 0x6008, 0xc0a4, 0x600a, 0x6817, 0x0000, 0x0804,
+ 0x3795, 0x2300, 0x0002, 0x327e, 0x3280, 0x32ce, 0x080c, 0x2575,
+ 0xd6fc, 0x1904, 0x2d5b, 0x7000, 0xa00d, 0x0002, 0x25c9, 0x3290,
+ 0x3290, 0x32ba, 0x3290, 0x32cb, 0x328e, 0x328e, 0x080c, 0x2575,
+ 0xa684, 0x0060, 0x0538, 0xa086, 0x0060, 0x1510, 0xc6ac, 0xc6f4,
+ 0xc6ed, 0x7e5a, 0x6eb6, 0x681c, 0xc0ac, 0x681e, 0xa186, 0x0002,
+ 0x0148, 0x080c, 0x3f4e, 0x69ac, 0x68b0, 0xa115, 0x0118, 0x080c,
+ 0x4235, 0x0010, 0x080c, 0x4208, 0x781b, 0x0083, 0x71d0, 0xd1b4,
+ 0x1904, 0x25c6, 0x70a0, 0xa086, 0x0001, 0x1904, 0x260d, 0x0005,
+ 0xd6ec, 0x09f0, 0x6818, 0xd0fc, 0x0170, 0xd6f4, 0x1130, 0x681b,
+ 0x0015, 0x781b, 0x0083, 0x0804, 0x25c6, 0x681b, 0x0007, 0x682f,
+ 0x0000, 0x6833, 0x0000, 0x080c, 0x3c17, 0x0005, 0x080c, 0x2575,
+ 0x2300, 0x0002, 0x32d7, 0x32f9, 0x3351, 0x080c, 0x2575, 0x7000,
+ 0x0002, 0x32e1, 0x32e3, 0x32ea, 0x32e1, 0x32e1, 0x32e1, 0x32e1,
+ 0x32e1, 0x080c, 0x2575, 0x69ac, 0x68b0, 0xa115, 0x0118, 0x080c,
+ 0x4235, 0x0010, 0x080c, 0x4208, 0x681c, 0xc0b4, 0x681e, 0x70d0,
+ 0xd0b4, 0x1904, 0x25c6, 0x70a0, 0xa086, 0x0001, 0x1904, 0x260d,
+ 0x0005, 0xd6fc, 0x1904, 0x3341, 0x7000, 0xa00d, 0x0002, 0x25c9,
+ 0x330f, 0x3309, 0x3339, 0x330f, 0x333e, 0x3307, 0x3307, 0x080c,
+ 0x2575, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0xa684,
+ 0x0060, 0x0538, 0xa086, 0x0060, 0x1510, 0xa6b4, 0xbfbf, 0xc6ed,
+ 0x7e5a, 0x6eb6, 0xa186, 0x0002, 0x0148, 0x080c, 0x3f4e, 0x69ac,
+ 0x68b0, 0xa115, 0x0118, 0x080c, 0x4235, 0x0010, 0x080c, 0x4208,
+ 0x781b, 0x0083, 0x681c, 0xc0b4, 0x681e, 0x71d0, 0xd1b4, 0x1904,
+ 0x25c6, 0x70a0, 0xa086, 0x0001, 0x1904, 0x260d, 0x0005, 0xd6ec,
+ 0x09f0, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x0007, 0x781b, 0x00fb,
+ 0x0005, 0xc6fc, 0x7e5a, 0x7adc, 0x79d8, 0x6b98, 0x2100, 0xa302,
+ 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x79d2, 0x781b, 0x0083,
+ 0x0005, 0xd6dc, 0x0130, 0x782b, 0x3009, 0x781b, 0x0083, 0x0804,
+ 0x25c6, 0x7884, 0xc0ac, 0x7886, 0x78e4, 0xa084, 0x0008, 0x1150,
+ 0xa484, 0x0200, 0x0108, 0xc6f5, 0xc6dd, 0x7e5a, 0x781b, 0x0083,
+ 0x0804, 0x25c6, 0x6820, 0xc095, 0x6822, 0x080c, 0x3c02, 0xc6dd,
+ 0x080c, 0x3a61, 0x781b, 0x0082, 0x0804, 0x25c6, 0x2300, 0x0002,
+ 0x337b, 0x337d, 0x337f, 0x080c, 0x2575, 0x0804, 0x3a5b, 0x7d98,
+ 0xd6d4, 0x15a8, 0x79e4, 0xd1ac, 0x0130, 0x78ec, 0xa084, 0x0003,
+ 0x0110, 0x782b, 0x3009, 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684,
+ 0xfffb, 0x785a, 0x7d9a, 0x79e4, 0xd1ac, 0x0120, 0x78ec, 0xa084,
+ 0x0003, 0x1120, 0x2001, 0x0014, 0x0804, 0x2f3b, 0x7884, 0xd0fc,
0x1118, 0xa184, 0x0007, 0x0090, 0xa184, 0x0007, 0xa086, 0x0004,
0x1118, 0x2001, 0x0000, 0x0050, 0xa184, 0x0007, 0xa086, 0x0005,
- 0x0118, 0xa184, 0x0007, 0x0010, 0x2001, 0x0001, 0x0002, 0x2c6f,
- 0x2c2a, 0x2ba4, 0x3be5, 0x3c29, 0x3c29, 0x3be5, 0x3c23, 0x080c,
- 0x3bf1, 0x0005, 0xa282, 0x0005, 0x0310, 0x080c, 0x254c, 0x7898,
- 0x2040, 0x2300, 0x0002, 0x2c7e, 0x2ea8, 0x2eb2, 0x2200, 0x0002,
- 0x2c9a, 0x2c87, 0x2c9a, 0x2c85, 0x2e8a, 0x080c, 0x254c, 0x789b,
- 0x0018, 0x78a8, 0x2010, 0xa084, 0x00ff, 0xa082, 0x0020, 0x0a04,
- 0x3a0b, 0xa08a, 0x0004, 0x1a04, 0x3a0b, 0x0002, 0x3a0b, 0x3a0b,
- 0x3a0b, 0x39c1, 0x789b, 0x0018, 0x79a8, 0xa184, 0x0080, 0x0148,
- 0x0804, 0x3a0b, 0x7000, 0xa005, 0x1dd8, 0x2011, 0x0004, 0x0804,
- 0x3594, 0xa184, 0x00ff, 0xa08a, 0x0010, 0x1a04, 0x3a0b, 0x0002,
- 0x2cc2, 0x2cc0, 0x2cd4, 0x2cd8, 0x2d86, 0x3a0b, 0x3a0b, 0x2d88,
- 0x3a0b, 0x3a0b, 0x2e86, 0x2e86, 0x3a0b, 0x3a0b, 0x3a0b, 0x2e88,
- 0x080c, 0x254c, 0xd6e4, 0x0140, 0x2001, 0x0300, 0x8000, 0x8000,
- 0x783a, 0x781b, 0x00c7, 0x0005, 0x6818, 0xd0fc, 0x0118, 0x681b,
- 0x001d, 0x0c90, 0x0804, 0x3be5, 0x681b, 0x001d, 0x0804, 0x3a36,
- 0x6920, 0x6922, 0xa684, 0x1800, 0x1904, 0x2d29, 0x6820, 0xd084,
- 0x1904, 0x2d31, 0x6818, 0xa086, 0x0008, 0x1110, 0x681b, 0x0000,
- 0xd6d4, 0x0568, 0xd6bc, 0x0558, 0x7083, 0x0000, 0x6818, 0xa084,
- 0x003f, 0xa08a, 0x000d, 0x0718, 0xa08a, 0x000c, 0x7182, 0x2001,
- 0x000c, 0x800c, 0x7186, 0x789b, 0x0061, 0x78aa, 0x0156, 0x0136,
- 0x0146, 0x0016, 0x3208, 0xa18c, 0x0600, 0x0118, 0x20a1, 0x022b,
- 0x0010, 0x20a1, 0x012b, 0x001e, 0x789b, 0x0000, 0x8000, 0x80ac,
- 0xad80, 0x000b, 0x2098, 0x53a6, 0x014e, 0x013e, 0x015e, 0x6038,
- 0xa005, 0x1150, 0x681c, 0xa084, 0x000e, 0x0904, 0x3a36, 0x080c,
- 0x3a48, 0x782b, 0x3008, 0x0010, 0x8001, 0x603a, 0x781b, 0x0071,
- 0x0005, 0xd6e4, 0x0130, 0x781b, 0x0083, 0x0005, 0x781b, 0x0083,
- 0x0005, 0xa684, 0x0060, 0x0dd0, 0xd6dc, 0x0dc0, 0xd6fc, 0x01a0,
- 0xc6fc, 0x7e5a, 0x6eb6, 0x7adc, 0x79d8, 0x78d0, 0x8007, 0xa084,
- 0x007f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2,
- 0x6b94, 0x2200, 0xa303, 0x68ae, 0xd6f4, 0x0118, 0xc6f4, 0x7e5a,
- 0x6eb6, 0x7000, 0xa086, 0x0003, 0x1148, 0x0006, 0x080c, 0x3f26,
- 0x080c, 0x41d9, 0x000e, 0x781b, 0x0080, 0x0005, 0xa006, 0x080c,
- 0x42b5, 0x6ab0, 0x69ac, 0x6c98, 0x6b94, 0x2200, 0xa105, 0x0120,
- 0x2200, 0xa422, 0x2100, 0xa31b, 0x6caa, 0x7cd2, 0x7cda, 0x6ba6,
- 0x7bd6, 0x7bde, 0x2300, 0xa405, 0x1130, 0xc6f5, 0x7e5a, 0x6eb6,
- 0x781b, 0x0080, 0x0005, 0x781b, 0x0080, 0x2200, 0xa115, 0x1118,
- 0x080c, 0x41d9, 0x0005, 0x080c, 0x4206, 0x0005, 0x080c, 0x254c,
- 0x0804, 0x2e1c, 0x00c6, 0x7054, 0x2060, 0x6920, 0xa18c, 0xecff,
- 0x6922, 0x6000, 0xa084, 0xcfdf, 0x6002, 0x080c, 0x38f4, 0xa006,
- 0x2040, 0x2038, 0x080c, 0x399c, 0x0804, 0x2e10, 0x00c6, 0x7054,
- 0x2060, 0x2c48, 0x7aa8, 0xa294, 0x00ff, 0xa286, 0x0004, 0x11d8,
- 0x6920, 0xd1e4, 0x1170, 0x2039, 0x0000, 0x2041, 0x0000, 0x2031,
- 0x0000, 0xa006, 0x2010, 0x080c, 0x38f7, 0x080c, 0x399c, 0x0804,
- 0x2e10, 0xa18c, 0xecff, 0x6922, 0x6104, 0xa18c, 0xffdd, 0x6106,
- 0x6000, 0xc0ac, 0x6002, 0xa286, 0x0003, 0x01d0, 0x6104, 0xa184,
- 0x0010, 0x0548, 0x080c, 0x3b6b, 0x080c, 0x3977, 0x88ff, 0x0518,
- 0x00ce, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695, 0x7e5a,
- 0xd6d4, 0x1118, 0x781b, 0x006e, 0x0005, 0x781b, 0x0082, 0x0005,
- 0x6920, 0xd1cc, 0x0130, 0xa18c, 0xfdff, 0x6922, 0x6000, 0xc0ec,
- 0x6002, 0x2039, 0x0000, 0x2041, 0x0000, 0x2031, 0x0000, 0xa006,
- 0x2010, 0x080c, 0x399c, 0xa286, 0x0001, 0x0158, 0x6104, 0xa184,
- 0x0008, 0x01b0, 0x080c, 0x3b6b, 0x080c, 0x3895, 0x88ff, 0x1980,
- 0x0078, 0x6920, 0xd1c4, 0x0130, 0xa18c, 0xfeff, 0x6922, 0x6000,
- 0xc0e4, 0x6002, 0x2031, 0x0000, 0xa006, 0x2010, 0x080c, 0x38f7,
- 0x00ce, 0x7e58, 0xd6d4, 0x1118, 0x781b, 0x0071, 0x0005, 0x781b,
- 0x0083, 0x0005, 0x0804, 0x3a32, 0x2808, 0x789b, 0x0080, 0x2019,
- 0x0080, 0x78a8, 0xa094, 0x00ff, 0xa286, 0x0001, 0x11b8, 0x2300,
- 0xa102, 0xa086, 0x0001, 0x0904, 0x2d8a, 0x7ca8, 0xa4a4, 0x00ff,
- 0xa480, 0x0002, 0xa300, 0x2018, 0xa102, 0x0a04, 0x2d9e, 0x0904,
- 0x2d9e, 0x24a8, 0x7aa8, 0x1f04, 0x2e3a, 0x0c18, 0xa284, 0x00f0,
- 0xa082, 0x0020, 0x06b8, 0x2200, 0xa082, 0x0021, 0x1698, 0x7aa8,
- 0x8318, 0x8318, 0x2100, 0xa302, 0x0aa0, 0xa286, 0x0023, 0x0950,
- 0x681c, 0xa084, 0xfff1, 0x681e, 0x7e58, 0xa684, 0xfff1, 0xc0a5,
- 0x2030, 0x7e5a, 0x6008, 0xc0a5, 0x600a, 0x78a0, 0x8001, 0x0904,
- 0x2e10, 0x20a8, 0x7998, 0x789b, 0x0060, 0x78aa, 0x2011, 0x0080,
- 0x799a, 0x78a8, 0x7998, 0x7a9a, 0x78aa, 0x7a98, 0x1f04, 0x2e68,
- 0xc695, 0x7e5a, 0xd6d4, 0x1118, 0x781b, 0x006e, 0x0005, 0x781b,
- 0x0082, 0x0005, 0x8318, 0x2100, 0xa302, 0x0a04, 0x2e21, 0xa284,
- 0x0080, 0x1904, 0x3a36, 0x78a0, 0xa005, 0x08c8, 0x0804, 0x3a36,
- 0x0804, 0x3a0b, 0x7054, 0xa04d, 0x789b, 0x0018, 0x78a8, 0xa084,
- 0x00ff, 0xa08e, 0x0001, 0x0110, 0x080c, 0x254c, 0x7aa8, 0xa294,
- 0x00ff, 0x784b, 0x0008, 0x78a8, 0xa084, 0x00ff, 0xa08a, 0x0005,
- 0x1a04, 0x3a0b, 0x0002, 0x3a0b, 0x380c, 0x3a0b, 0x3927, 0x3d31,
- 0xa282, 0x0000, 0x1110, 0x080c, 0x254c, 0x080c, 0x3a3c, 0x781b,
- 0x0082, 0x0005, 0xa282, 0x0003, 0x1110, 0x080c, 0x254c, 0xd4fc,
- 0x11d0, 0x7060, 0xa005, 0x0110, 0x080c, 0x254c, 0x6f14, 0x7772,
- 0xa7bc, 0x8f00, 0x080c, 0x3b6f, 0x6008, 0xa085, 0x0021, 0x600a,
- 0x8738, 0xa784, 0x001f, 0x1db0, 0x080c, 0x3a3f, 0x7063, 0x0002,
- 0x701f, 0x0009, 0x0010, 0x080c, 0x3a4b, 0x781b, 0x0082, 0x0005,
- 0xa282, 0x0004, 0x0310, 0x080c, 0x254c, 0x2300, 0x0002, 0x2ee2,
- 0x3078, 0x30b4, 0xa286, 0x0003, 0x0598, 0x7200, 0x7cd8, 0x7ddc,
- 0x7fd0, 0x71d0, 0xd1b4, 0x0528, 0xd1bc, 0x1518, 0x2001, 0x4601,
- 0x2004, 0xd0c4, 0x11f0, 0x7868, 0xa084, 0x00ff, 0x11d0, 0xa282,
- 0x0002, 0x12b8, 0x00d6, 0x783b, 0x8300, 0x781b, 0x0059, 0x70b8,
- 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2,
- 0x78da, 0xc1b4, 0x71d2, 0x7003, 0x0030, 0x00de, 0x2001, 0x0000,
- 0x0058, 0x783b, 0x1300, 0x781b, 0x0057, 0x2001, 0x0000, 0x0020,
- 0x7200, 0x7cd8, 0x7ddc, 0x7fd0, 0x7046, 0x68a0, 0xd0ec, 0x0118,
- 0x6008, 0xc08d, 0x600a, 0xa284, 0x000f, 0x0002, 0x3059, 0x2f33,
- 0x2f30, 0x3184, 0x320f, 0x25a0, 0x2f2e, 0x2f2e, 0x080c, 0x254c,
- 0x6008, 0xc0d4, 0x600a, 0xd6e4, 0x0120, 0x7044, 0xa086, 0x0014,
- 0x11e8, 0x080c, 0x3f26, 0x2009, 0x0000, 0x6818, 0xd0fc, 0x0108,
- 0x7044, 0xa086, 0x0014, 0x0168, 0x6818, 0xa086, 0x0008, 0x1904,
- 0x301b, 0x7858, 0xd09c, 0x0904, 0x301b, 0x6820, 0xd0ac, 0x0904,
- 0x301b, 0x681b, 0x0014, 0x2009, 0x0002, 0x04a8, 0x7868, 0xa08c,
- 0x00ff, 0x0588, 0xa186, 0x0008, 0x1158, 0x6008, 0xc0a4, 0x600a,
- 0x080c, 0x374f, 0x0540, 0x080c, 0x37be, 0x080c, 0x3f26, 0x0060,
- 0xa186, 0x0028, 0x1500, 0x6018, 0xa005, 0x0d78, 0x8001, 0x0d68,
- 0x8001, 0x0d58, 0x601e, 0x0c48, 0x6820, 0xd084, 0x0904, 0x25a0,
- 0xc084, 0x6822, 0x080c, 0x2693, 0x7058, 0x00c6, 0x2060, 0x6800,
- 0x6002, 0x00ce, 0x6004, 0x6802, 0xa005, 0x2d00, 0x1108, 0x6002,
- 0x6006, 0x0804, 0x25a0, 0x0016, 0x81ff, 0x15f0, 0x7000, 0xa086,
- 0x0030, 0x05d0, 0x71d0, 0xd1bc, 0x15b8, 0xd1b4, 0x11e8, 0x705c,
- 0xa005, 0x1590, 0x70a0, 0xa086, 0x0001, 0x0570, 0x7003, 0x0000,
- 0x0046, 0x0056, 0x0076, 0x0066, 0x00c6, 0x00d6, 0x080c, 0x25c5,
- 0x00de, 0x00ce, 0x006e, 0x007e, 0x005e, 0x004e, 0x71d0, 0xd1b4,
- 0x11d8, 0x7003, 0x0040, 0x00c0, 0x080c, 0x3c33, 0x11a8, 0x781b,
- 0x0068, 0x00d6, 0x70b8, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6,
- 0x78de, 0x6898, 0x78d2, 0x78da, 0xc1b4, 0x71d2, 0x7003, 0x0030,
- 0x7808, 0xc08d, 0x780a, 0x00de, 0x080c, 0x30dc, 0x001e, 0x81ff,
- 0x0904, 0x301b, 0xa684, 0xdf00, 0x681e, 0x682b, 0x0000, 0x6f14,
- 0xa186, 0x0002, 0x1904, 0x301c, 0x6818, 0xa086, 0x0014, 0x1130,
- 0x2008, 0xd6e4, 0x0118, 0x7868, 0xa08c, 0x00ff, 0x080c, 0x3a55,
- 0x080c, 0x269e, 0x6820, 0xd0dc, 0x1578, 0x8717, 0xa294, 0x000f,
- 0x8213, 0x8213, 0x8213, 0xb284, 0x0600, 0x0118, 0xa290, 0x4ac0,
- 0x0010, 0xa290, 0x4b40, 0xa290, 0x0000, 0x221c, 0xd3c4, 0x0170,
- 0x6820, 0xd0e4, 0x0128, 0xa084, 0xefff, 0x6822, 0xc3ac, 0x2312,
- 0x8210, 0x2204, 0xa085, 0x0038, 0x2012, 0x8211, 0xd3d4, 0x0138,
- 0x68a0, 0xd0c4, 0x1120, 0x080c, 0x3144, 0x0804, 0x25a0, 0x6008,
- 0xc08d, 0x600a, 0x0008, 0x692a, 0x6916, 0x6818, 0xd0fc, 0x0110,
- 0x7044, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x6410, 0x84ff, 0x0168,
- 0x2009, 0x4602, 0x2104, 0x8001, 0x200a, 0x8421, 0x6412, 0x1128,
- 0x2021, 0x4604, 0x2404, 0xc0a5, 0x2022, 0x6018, 0xa005, 0x0118,
- 0x8001, 0x601a, 0x1118, 0x6008, 0xc0a4, 0x600a, 0x6820, 0xd084,
- 0x1130, 0x6800, 0xa005, 0x1108, 0x6002, 0x6006, 0x0020, 0x7058,
- 0x2060, 0x6800, 0x6002, 0x2061, 0x4600, 0x6887, 0x0103, 0x2d08,
- 0x206b, 0x0000, 0x6068, 0xa005, 0x616a, 0x0110, 0x2d02, 0x0008,
- 0x616e, 0x7200, 0xa286, 0x0030, 0x0158, 0xa286, 0x0040, 0x1904,
- 0x25a0, 0x7003, 0x0002, 0x7048, 0x2068, 0x68c4, 0x2060, 0x0005,
- 0x7003, 0x0002, 0x70b8, 0xa06d, 0x68bc, 0x703e, 0x70b4, 0xa065,
- 0x68c0, 0x7056, 0x2d00, 0x704a, 0xad80, 0x0009, 0x7042, 0x0005,
- 0xa282, 0x0004, 0x0210, 0x080c, 0x254c, 0x2200, 0x0002, 0x3083,
- 0x3092, 0x309e, 0x3092, 0xa586, 0x1300, 0x0160, 0xa586, 0x8300,
- 0x1d90, 0x7003, 0x0000, 0x6018, 0x8001, 0x601a, 0x6008, 0xa084,
- 0xfbef, 0x600a, 0x7000, 0xa086, 0x0005, 0x0128, 0x080c, 0x3a3c,
- 0x781b, 0x0082, 0x0005, 0x781b, 0x0083, 0x0005, 0x7890, 0x8007,
- 0x8001, 0xa084, 0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c,
- 0x00ff, 0xa186, 0x0003, 0x0128, 0xa186, 0x0000, 0x0110, 0x0804,
- 0x3a0b, 0x781b, 0x0083, 0x0005, 0x6820, 0xc095, 0x6822, 0x82ff,
- 0x1118, 0x080c, 0x3a3c, 0x0030, 0x8211, 0x0110, 0x080c, 0x254c,
- 0x080c, 0x3a4b, 0x781b, 0x0082, 0x0005, 0x080c, 0x3c46, 0x7830,
- 0xa084, 0x00c0, 0x1170, 0x0016, 0x3208, 0xa18c, 0x0800, 0x001e,
- 0x0118, 0x0104, 0x30d9, 0x0010, 0x0304, 0x30d9, 0x791a, 0xa006,
- 0x0005, 0xa085, 0x0001, 0x0005, 0xa684, 0x0060, 0x1130, 0x682f,
- 0x0000, 0x6833, 0x0000, 0x0804, 0x3143, 0xd6dc, 0x1198, 0x68b4,
- 0xd0dc, 0x1180, 0x6998, 0x6a94, 0x692e, 0x6a32, 0x7044, 0xa005,
- 0x1130, 0x2200, 0xa105, 0x0904, 0x3f26, 0x7047, 0x0015, 0x0804,
- 0x3f26, 0x0005, 0xd6ac, 0x01f0, 0xd6f4, 0x0130, 0x682f, 0x0000,
- 0x6833, 0x0000, 0x0804, 0x3f26, 0x68b4, 0xa084, 0x4000, 0xa635,
- 0xd6f4, 0x1da0, 0x7044, 0xa005, 0x1110, 0x7047, 0x0015, 0xd6dc,
- 0x1128, 0x68b4, 0xd0dc, 0x0110, 0x6ca8, 0x6da4, 0x6c2e, 0x6d32,
- 0x0804, 0x3f26, 0xd6f4, 0x0130, 0x682f, 0x0000, 0x6833, 0x0000,
- 0x0804, 0x3f26, 0x68b4, 0xa084, 0x4800, 0xa635, 0xd6f4, 0x1da0,
- 0x7044, 0xa005, 0x1110, 0x7047, 0x0015, 0x2408, 0x2510, 0x2700,
- 0x8007, 0xa084, 0x007f, 0xa108, 0xa291, 0x0000, 0x692e, 0x6a32,
- 0x2100, 0xa205, 0x1110, 0x0804, 0x3f26, 0x7000, 0xa086, 0x0006,
- 0x0110, 0x0804, 0x3f26, 0x0005, 0x6946, 0x6008, 0xc0cd, 0xd3cc,
- 0x0108, 0xc08d, 0x600a, 0x6818, 0x683a, 0x681b, 0x0006, 0x688f,
- 0x0000, 0x6893, 0x0000, 0x6a30, 0x692c, 0x6a3e, 0x6942, 0x682f,
- 0x0003, 0x6833, 0x0000, 0x6837, 0x0020, 0x6897, 0x0000, 0x689b,
- 0x0020, 0x7000, 0x0002, 0x25a0, 0x3173, 0x316d, 0x316b, 0x316b,
- 0x316b, 0x316b, 0x316b, 0x080c, 0x254c, 0x6820, 0xd084, 0x1118,
- 0x080c, 0x37a4, 0x0030, 0x7058, 0x2c50, 0x2060, 0x6800, 0x6002,
- 0x2a60, 0xaea0, 0x0017, 0x2404, 0xa005, 0x0110, 0x2020, 0x0cd8,
- 0x2d22, 0x206b, 0x0000, 0x0005, 0x080c, 0x37aa, 0x080c, 0x37be,
- 0x6008, 0xc0cc, 0x600a, 0x682b, 0x0000, 0x789b, 0x000e, 0x6f14,
- 0x6938, 0x691a, 0x6944, 0x6916, 0x2009, 0x0000, 0xae86, 0x4640,
- 0x0110, 0x2009, 0x0001, 0x080c, 0x42ec, 0xd6dc, 0x01c8, 0x691c,
- 0xc1ed, 0x691e, 0x6828, 0xa082, 0x000e, 0x0290, 0x6848, 0xa084,
- 0x000f, 0xa086, 0x000b, 0x1160, 0x685c, 0xa086, 0x0047, 0x1140,
- 0x2001, 0x4601, 0x2004, 0xd0ac, 0x1118, 0x2700, 0x080c, 0x2475,
- 0x6818, 0xd0fc, 0x0140, 0x681b, 0x0000, 0x7868, 0xa08c, 0x00ff,
- 0x0110, 0x681b, 0x001e, 0xaea0, 0x0017, 0x6800, 0x2022, 0x6a3c,
- 0x6940, 0x6a32, 0x692e, 0x68c0, 0x2060, 0x6000, 0xd0a4, 0x0580,
- 0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x00d6, 0x00f6,
- 0x0156, 0x0146, 0x2079, 0x4600, 0x080c, 0x1b93, 0x014e, 0x015e,
- 0x00fe, 0x70c8, 0x2010, 0x2009, 0x0101, 0x0026, 0x2204, 0xa06d,
- 0x0140, 0x6814, 0xa706, 0x0110, 0x6800, 0x0cc8, 0x6820, 0xc0d5,
- 0x6822, 0x002e, 0x8210, 0x8109, 0x1d80, 0x00de, 0x7063, 0x0003,
- 0x707b, 0x0000, 0x7772, 0x707f, 0x000f, 0x71d0, 0xc1c4, 0x71d2,
- 0x6818, 0xa086, 0x0002, 0x1138, 0x6817, 0x0000, 0x682b, 0x0000,
- 0x681c, 0xc0ec, 0x681e, 0x080c, 0x1da2, 0x0804, 0x25a0, 0x7cd8,
- 0x7ddc, 0x7fd0, 0x080c, 0x30dc, 0x682b, 0x0000, 0x789b, 0x000e,
- 0x6f14, 0x080c, 0x3c4a, 0xa08c, 0x00ff, 0x6916, 0x6818, 0xd0fc,
- 0x0110, 0x7044, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x7063, 0x0000,
- 0x0804, 0x25a0, 0x7000, 0xa005, 0x1110, 0x0804, 0x25a0, 0xa006,
- 0x080c, 0x3f26, 0x6920, 0xd1ac, 0x1110, 0x681b, 0x0014, 0xa68c,
- 0xdf00, 0x691e, 0x682b, 0x0000, 0x6820, 0xa084, 0x00ff, 0x6822,
- 0x7000, 0x0002, 0x25a0, 0x324c, 0x324c, 0x324f, 0x324f, 0x324f,
- 0x324a, 0x324a, 0x080c, 0x254c, 0x6818, 0x0804, 0x2f18, 0x6008,
- 0xc0a4, 0x600a, 0x6817, 0x0000, 0x0804, 0x3772, 0x2300, 0x0002,
- 0x325b, 0x325d, 0x32ab, 0x080c, 0x254c, 0xd6fc, 0x1904, 0x2d38,
- 0x7000, 0xa00d, 0x0002, 0x25a0, 0x326d, 0x326d, 0x3297, 0x326d,
- 0x32a8, 0x326b, 0x326b, 0x080c, 0x254c, 0xa684, 0x0060, 0x0538,
- 0xa086, 0x0060, 0x1510, 0xc6ac, 0xc6f4, 0xc6ed, 0x7e5a, 0x6eb6,
- 0x681c, 0xc0ac, 0x681e, 0xa186, 0x0002, 0x0148, 0x080c, 0x3f26,
- 0x69ac, 0x68b0, 0xa115, 0x0118, 0x080c, 0x4206, 0x0010, 0x080c,
- 0x41d9, 0x781b, 0x0083, 0x71d0, 0xd1b4, 0x1904, 0x259d, 0x70a0,
- 0xa086, 0x0001, 0x1904, 0x25e1, 0x0005, 0xd6ec, 0x09f0, 0x6818,
- 0xd0fc, 0x0170, 0xd6f4, 0x1130, 0x681b, 0x0015, 0x781b, 0x0083,
- 0x0804, 0x259d, 0x681b, 0x0007, 0x682f, 0x0000, 0x6833, 0x0000,
- 0x080c, 0x3bf1, 0x0005, 0x080c, 0x254c, 0x2300, 0x0002, 0x32b4,
- 0x32d6, 0x332e, 0x080c, 0x254c, 0x7000, 0x0002, 0x32be, 0x32c0,
- 0x32c7, 0x32be, 0x32be, 0x32be, 0x32be, 0x32be, 0x080c, 0x254c,
- 0x69ac, 0x68b0, 0xa115, 0x0118, 0x080c, 0x4206, 0x0010, 0x080c,
- 0x41d9, 0x681c, 0xc0b4, 0x681e, 0x70d0, 0xd0b4, 0x1904, 0x259d,
- 0x70a0, 0xa086, 0x0001, 0x1904, 0x25e1, 0x0005, 0xd6fc, 0x1904,
- 0x331e, 0x7000, 0xa00d, 0x0002, 0x25a0, 0x32ec, 0x32e6, 0x3316,
- 0x32ec, 0x331b, 0x32e4, 0x32e4, 0x080c, 0x254c, 0x6894, 0x78d6,
- 0x78de, 0x6898, 0x78d2, 0x78da, 0xa684, 0x0060, 0x0538, 0xa086,
- 0x0060, 0x1510, 0xa6b4, 0xbfbf, 0xc6ed, 0x7e5a, 0x6eb6, 0xa186,
- 0x0002, 0x0148, 0x080c, 0x3f26, 0x69ac, 0x68b0, 0xa115, 0x0118,
- 0x080c, 0x4206, 0x0010, 0x080c, 0x41d9, 0x781b, 0x0083, 0x681c,
- 0xc0b4, 0x681e, 0x71d0, 0xd1b4, 0x1904, 0x259d, 0x70a0, 0xa086,
- 0x0001, 0x1904, 0x25e1, 0x0005, 0xd6ec, 0x09f0, 0x6818, 0xd0fc,
- 0x0110, 0x681b, 0x0007, 0x781b, 0x00fb, 0x0005, 0xc6fc, 0x7e5a,
- 0x7adc, 0x79d8, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200,
- 0xa303, 0x68ae, 0x79d2, 0x781b, 0x0083, 0x0005, 0xd6dc, 0x0130,
- 0x782b, 0x3009, 0x781b, 0x0083, 0x0804, 0x259d, 0x7884, 0xc0ac,
- 0x7886, 0x78e4, 0xa084, 0x0008, 0x1150, 0xa484, 0x0200, 0x0108,
- 0xc6f5, 0xc6dd, 0x7e5a, 0x781b, 0x0083, 0x0804, 0x259d, 0x6820,
- 0xc095, 0x6822, 0x080c, 0x3bdc, 0xc6dd, 0x080c, 0x3a3c, 0x781b,
- 0x0082, 0x0804, 0x259d, 0x2300, 0x0002, 0x3358, 0x335a, 0x335c,
- 0x080c, 0x254c, 0x0804, 0x3a36, 0x7d98, 0xd6d4, 0x15a8, 0x79e4,
- 0xd1ac, 0x0130, 0x78ec, 0xa084, 0x0003, 0x0110, 0x782b, 0x3009,
- 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb, 0x785a, 0x7d9a,
- 0x79e4, 0xd1ac, 0x0120, 0x78ec, 0xa084, 0x0003, 0x1120, 0x2001,
- 0x0014, 0x0804, 0x2f18, 0x7884, 0xd0fc, 0x1118, 0xa184, 0x0007,
+ 0x0118, 0xa184, 0x0007, 0x0010, 0x2001, 0x0001, 0x04c2, 0x7a90,
+ 0xa294, 0x0007, 0x789b, 0x0060, 0x79a8, 0x81ff, 0x0568, 0x789b,
+ 0x0080, 0x7ba8, 0xa384, 0x0001, 0x11d0, 0x7ba8, 0x7ba8, 0xa386,
+ 0x0004, 0x1118, 0x2009, 0xffdf, 0x0058, 0xa386, 0x0001, 0x1118,
+ 0x2009, 0xfff7, 0x0028, 0xa386, 0x0003, 0x1148, 0x2009, 0xffef,
+ 0x00c6, 0x7054, 0x2060, 0x6004, 0xa104, 0x6006, 0x00ce, 0x789b,
+ 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb, 0x785a, 0x782b, 0x3009,
+ 0x6920, 0xa18c, 0xecff, 0x6922, 0x7d9a, 0x0804, 0x3c0b, 0x2bd1,
+ 0x2bda, 0x33f9, 0x33ff, 0x33f7, 0x33f7, 0x3c0b, 0x3c0b, 0x080c,
+ 0x2575, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0804, 0x3c11, 0x6920,
+ 0xa18c, 0xfcff, 0x6922, 0x0804, 0x3c0b, 0x79e4, 0xa184, 0x0030,
+ 0x0120, 0x78ec, 0xa084, 0x0003, 0x1570, 0x7000, 0xa086, 0x0004,
+ 0x1190, 0x7060, 0xa086, 0x0002, 0x1130, 0x2011, 0x0002, 0x2019,
+ 0x0000, 0x0804, 0x2a85, 0x7060, 0xa086, 0x0006, 0x0db0, 0x7060,
+ 0xa086, 0x0004, 0x0d90, 0x7000, 0xa086, 0x0000, 0x0904, 0x25c6,
+ 0x6920, 0xa184, 0x0420, 0x0128, 0xc1d4, 0x6922, 0x6818, 0x0804,
+ 0x2f3b, 0x6818, 0xa08e, 0x0002, 0x0120, 0xc0fd, 0x681a, 0x2001,
+ 0x0014, 0x0804, 0x2f3b, 0x7884, 0xd0fc, 0x1118, 0xa184, 0x0007,
0x0090, 0xa184, 0x0007, 0xa086, 0x0004, 0x1118, 0x2001, 0x0000,
0x0050, 0xa184, 0x0007, 0xa086, 0x0005, 0x0118, 0xa184, 0x0007,
- 0x0010, 0x2001, 0x0001, 0x04c2, 0x7a90, 0xa294, 0x0007, 0x789b,
- 0x0060, 0x79a8, 0x81ff, 0x0568, 0x789b, 0x0080, 0x7ba8, 0xa384,
- 0x0001, 0x11d0, 0x7ba8, 0x7ba8, 0xa386, 0x0004, 0x1118, 0x2009,
- 0xffdf, 0x0058, 0xa386, 0x0001, 0x1118, 0x2009, 0xfff7, 0x0028,
- 0xa386, 0x0003, 0x1148, 0x2009, 0xffef, 0x00c6, 0x7054, 0x2060,
- 0x6004, 0xa104, 0x6006, 0x00ce, 0x789b, 0x0060, 0x78ab, 0x0000,
- 0xa684, 0xfffb, 0x785a, 0x782b, 0x3009, 0x6920, 0xa18c, 0xecff,
- 0x6922, 0x7d9a, 0x0804, 0x3be5, 0x2bae, 0x2bb7, 0x33d6, 0x33dc,
- 0x33d4, 0x33d4, 0x3be5, 0x3be5, 0x080c, 0x254c, 0x6920, 0xa18c,
- 0xfcff, 0x6922, 0x0804, 0x3beb, 0x6920, 0xa18c, 0xfcff, 0x6922,
- 0x0804, 0x3be5, 0x79e4, 0xa184, 0x0030, 0x0120, 0x78ec, 0xa084,
- 0x0003, 0x1570, 0x7000, 0xa086, 0x0004, 0x1190, 0x7060, 0xa086,
- 0x0002, 0x1130, 0x2011, 0x0002, 0x2019, 0x0000, 0x0804, 0x2a56,
- 0x7060, 0xa086, 0x0006, 0x0db0, 0x7060, 0xa086, 0x0004, 0x0d90,
- 0x7000, 0xa086, 0x0000, 0x0904, 0x259d, 0x6920, 0xa184, 0x0420,
- 0x0128, 0xc1d4, 0x6922, 0x6818, 0x0804, 0x2f18, 0x6818, 0xa08e,
- 0x0002, 0x0120, 0xc0fd, 0x681a, 0x2001, 0x0014, 0x0804, 0x2f18,
- 0x7884, 0xd0fc, 0x1118, 0xa184, 0x0007, 0x0090, 0xa184, 0x0007,
- 0xa086, 0x0004, 0x1118, 0x2001, 0x0000, 0x0050, 0xa184, 0x0007,
- 0xa086, 0x0005, 0x0118, 0xa184, 0x0007, 0x0010, 0x2001, 0x0001,
- 0x0002, 0x3be5, 0x3be5, 0x3439, 0x3be5, 0x3c29, 0x3c29, 0x3be5,
- 0x3be5, 0xd6bc, 0x0570, 0x7180, 0x81ff, 0x0558, 0xa182, 0x000d,
- 0x1318, 0x7083, 0x0000, 0x0028, 0xa182, 0x000c, 0x7082, 0x2009,
- 0x000c, 0x789b, 0x0061, 0x79aa, 0x0156, 0x0136, 0x0146, 0x7084,
- 0x8114, 0xa210, 0x7286, 0xa080, 0x000b, 0xad00, 0x2098, 0xb284,
- 0x0600, 0x0118, 0x20a1, 0x022b, 0x0010, 0x20a1, 0x012b, 0x789b,
- 0x0000, 0x8108, 0x81ac, 0x53a6, 0x014e, 0x013e, 0x015e, 0x0804,
- 0x3beb, 0xd6d4, 0x1904, 0x34ac, 0x6820, 0xd084, 0x0904, 0x3beb,
- 0xa68c, 0x0060, 0xa684, 0x0060, 0x0120, 0xa086, 0x0060, 0x1108,
- 0xc1f5, 0xc194, 0x795a, 0x69b6, 0x789b, 0x0060, 0x78ab, 0x0000,
- 0x789b, 0x0061, 0x6818, 0xc0fd, 0x681a, 0x78aa, 0x8008, 0x810c,
- 0x0904, 0x37d3, 0xa18c, 0x00f8, 0x1904, 0x37d3, 0x0156, 0x0136,
- 0x0146, 0x0016, 0x20a1, 0x012b, 0x3208, 0xa18c, 0x0600, 0x0110,
- 0x20a1, 0x022b, 0x001e, 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80,
- 0x000b, 0x2098, 0x53a6, 0x014e, 0x013e, 0x015e, 0x6814, 0xc0fc,
- 0x8007, 0x7882, 0x0804, 0x3beb, 0x6818, 0xd0fc, 0x0110, 0x681b,
- 0x0008, 0x080c, 0x3a3c, 0x781b, 0x00ed, 0x0005, 0x2300, 0x0002,
- 0x34bd, 0x357a, 0x34bb, 0x080c, 0x254c, 0x7cd8, 0x7ddc, 0x7fd0,
- 0x82ff, 0x1528, 0x7200, 0xa286, 0x0003, 0x0904, 0x2ee6, 0x71d0,
- 0xd1bc, 0x11f8, 0xd1b4, 0x01e8, 0x2001, 0x4601, 0x2004, 0xd0c4,
- 0x11c0, 0x00d6, 0x783b, 0x8800, 0x781b, 0x0059, 0x70b8, 0xa06d,
- 0x68b4, 0xc0a5, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2,
- 0x78da, 0xc1b4, 0x71d2, 0x7003, 0x0030, 0x00de, 0x0030, 0x7200,
- 0x0020, 0x783b, 0x1800, 0x781b, 0x0057, 0xa284, 0x000f, 0x0002,
- 0x3565, 0x3522, 0x34fa, 0x2f15, 0x34f8, 0x3565, 0x34f8, 0x34f8,
- 0x080c, 0x254c, 0x681c, 0xd0ec, 0x0118, 0x6008, 0xc08d, 0x600a,
- 0x6920, 0xc185, 0x6922, 0x6800, 0x6006, 0xa005, 0x1108, 0x6002,
- 0x6008, 0xc0d4, 0x600a, 0x681c, 0xa084, 0x000e, 0x1120, 0x71c8,
- 0xa188, 0x0100, 0x0028, 0x7030, 0x68ba, 0x713c, 0x70c8, 0xa108,
- 0x2104, 0x6802, 0x2d0a, 0x715a, 0xd6dc, 0x1120, 0xc6fc, 0x6eb6,
- 0x0804, 0x3565, 0x6eb6, 0xa684, 0x0060, 0x1120, 0xa684, 0x7fff,
- 0x68b6, 0x04d8, 0xd6dc, 0x1150, 0xa684, 0x7fff, 0x68b6, 0x6894,
- 0x68a6, 0x6898, 0x68aa, 0x080c, 0x3f26, 0x0478, 0xd6ac, 0x0140,
- 0xa006, 0x080c, 0x3f26, 0x2408, 0x2510, 0x69aa, 0x6aa6, 0x0068,
- 0x2408, 0x2510, 0x2700, 0x8007, 0xa084, 0x007f, 0xa108, 0xa291,
- 0x0000, 0x69aa, 0x6aa6, 0x080c, 0x3f26, 0xd6fc, 0x01b0, 0xa684,
- 0x7fff, 0x68b6, 0x2510, 0x2408, 0xd6ac, 0x1138, 0x2700, 0x8007,
- 0xa084, 0x007f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302,
- 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x7000, 0xa086, 0x0030,
- 0x1904, 0x25a0, 0x7003, 0x0002, 0x70b8, 0xa06d, 0x68bc, 0x703e,
- 0x70b4, 0xa065, 0x68c0, 0x7056, 0x2d00, 0x704a, 0xad80, 0x0009,
- 0x7042, 0x0005, 0xa586, 0x8800, 0x1148, 0x7003, 0x0000, 0x6018,
- 0x8001, 0x601a, 0x6008, 0xa084, 0xfbef, 0x600a, 0x0804, 0x3a36,
- 0x7043, 0x0000, 0xa282, 0x0006, 0x0310, 0x080c, 0x254c, 0x2300,
- 0x0002, 0x3594, 0x35a5, 0x35af, 0x2200, 0x0002, 0x359c, 0x3a36,
- 0x359e, 0x359c, 0x35e0, 0x362e, 0x080c, 0x254c, 0x7a80, 0xa294,
- 0x0f00, 0x080c, 0x3682, 0x0804, 0x3a0b, 0x00c1, 0x0002, 0x3a36,
- 0x35ad, 0x35ad, 0x35e0, 0x35ad, 0x3a36, 0x080c, 0x254c, 0x0071,
- 0x0002, 0x35b9, 0x35b7, 0x35b7, 0x35b9, 0x35b7, 0x35b9, 0x080c,
- 0x254c, 0x080c, 0x3a4b, 0x781b, 0x0082, 0x0005, 0x7000, 0xa086,
- 0x0002, 0x1150, 0x080c, 0x37be, 0x0010, 0x080c, 0x3f26, 0x6008,
- 0xa084, 0xfbef, 0x600a, 0x0020, 0x7000, 0xa086, 0x0003, 0x0da8,
- 0x7003, 0x0005, 0x2001, 0x8de0, 0xae8e, 0x4640, 0x0110, 0x2001,
- 0x8e12, 0x2068, 0x704a, 0xad80, 0x0009, 0x7042, 0x2200, 0x0005,
- 0x7000, 0xa086, 0x0002, 0x1158, 0x70d0, 0xc0b5, 0x70d2, 0x2c00,
- 0x70b6, 0x2d00, 0x70ba, 0x0038, 0x080c, 0x3f26, 0x0020, 0x7000,
- 0xa086, 0x0003, 0x0dc8, 0x7003, 0x0001, 0x7a80, 0xa294, 0x0f00,
- 0x789b, 0x0018, 0x7ca8, 0xa484, 0x001f, 0xa215, 0x2069, 0x8cc0,
- 0xb284, 0x0600, 0x1118, 0xc2fd, 0x2069, 0x8dd0, 0x2d04, 0x2d08,
- 0x715a, 0xa06d, 0x0128, 0x6814, 0xa206, 0x0120, 0x6800, 0x0cb8,
- 0x080c, 0x3682, 0x6eb4, 0x7e5a, 0x6920, 0xa184, 0x0c00, 0x0904,
- 0x36a8, 0x7060, 0xa086, 0x0006, 0x1128, 0x7070, 0xa206, 0x1110,
- 0x7062, 0x707a, 0x681b, 0x0005, 0xc1ad, 0x681b, 0x0005, 0xc1ad,
- 0xc1d4, 0x6922, 0x080c, 0x3a42, 0x0804, 0x36a8, 0x7200, 0xa286,
- 0x0002, 0x1158, 0x70d0, 0xc0b5, 0x70d2, 0x2c00, 0x70b6, 0x2d00,
- 0x70ba, 0x0030, 0x080c, 0x3f26, 0x0018, 0xa286, 0x0003, 0x0dd0,
- 0x7003, 0x0001, 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8,
- 0xa484, 0x001f, 0xa215, 0xae86, 0x4640, 0x0108, 0xc2fd, 0x79a8,
- 0x79a8, 0xa18c, 0x00ff, 0x2118, 0x70c8, 0xa168, 0x2d04, 0x2d08,
- 0x715a, 0xa06d, 0x0128, 0x6814, 0xa206, 0x0118, 0x6800, 0x0cb8,
- 0x0409, 0x6eb4, 0x6920, 0xa184, 0x0c00, 0x0904, 0x36a8, 0xd0dc,
- 0x0178, 0x7060, 0xa086, 0x0004, 0x1140, 0x7070, 0xa206, 0x1128,
- 0x7074, 0xa306, 0x1110, 0x7062, 0x707a, 0x080c, 0x3a48, 0x0480,
- 0x681b, 0x0005, 0xc1ad, 0xc1d4, 0x6922, 0x080c, 0x3a42, 0x707b,
- 0x0000, 0x0430, 0x7003, 0x0005, 0xb284, 0x0600, 0x0118, 0x2001,
- 0x8de0, 0x0010, 0x2001, 0x8e12, 0x2068, 0x704a, 0x0156, 0x20a9,
- 0x0032, 0x2003, 0x0000, 0x8000, 0x1f04, 0x3691, 0x015e, 0xb284,
- 0x0600, 0x0110, 0xc2fc, 0x0008, 0xc2fd, 0x6a16, 0xad80, 0x0009,
- 0x7042, 0x68b7, 0x0700, 0x6823, 0x0800, 0x6827, 0x0003, 0x0005,
- 0xc6ec, 0xa6ac, 0x0060, 0x0904, 0x36ef, 0x6b98, 0x6c94, 0x69ac,
- 0x68b0, 0xa105, 0x11e0, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0xa586,
- 0x0060, 0x05c8, 0xd6f4, 0x1108, 0xc6ed, 0xa6b4, 0xb7ff, 0x7e5a,
- 0x2009, 0x0083, 0xd69c, 0x0128, 0x2009, 0x0082, 0x2019, 0x0000,
- 0x2320, 0x791a, 0xd6ec, 0x0588, 0x080c, 0x41d9, 0x0470, 0x68b0,
- 0xa31a, 0x2100, 0xa423, 0x2400, 0xa305, 0x01f8, 0x7bd2, 0x7bda,
- 0x7cd6, 0x7cde, 0x68b0, 0xd6f4, 0x1108, 0xc6ed, 0xc6f4, 0x7e5a,
- 0x2011, 0x0083, 0xd69c, 0x0128, 0x2011, 0x0082, 0x2019, 0x0000,
- 0x2320, 0x7a1a, 0xd6ec, 0x0188, 0x080c, 0x4206, 0x0070, 0x2019,
- 0x0000, 0x2320, 0x0010, 0xa6b4, 0xb7ff, 0x7e5a, 0x2009, 0x0083,
- 0xd69c, 0x0110, 0x2009, 0x0082, 0x791a, 0x68c0, 0x7056, 0x2d00,
- 0x704a, 0x68c4, 0x2060, 0x71d0, 0x2001, 0x4601, 0x2004, 0xd0c4,
- 0x15c8, 0x70d4, 0xa02d, 0x01b8, 0xd1bc, 0x0548, 0x7a80, 0xa294,
- 0x0f00, 0x70d8, 0xa206, 0x0118, 0x78e0, 0xa504, 0x1558, 0x70d6,
- 0xc1bc, 0x71d2, 0x0438, 0x2031, 0x0001, 0x852c, 0x0218, 0x8633,
- 0x8210, 0x0cd8, 0x0005, 0x7de0, 0xa594, 0xff00, 0x0130, 0x2011,
- 0x0008, 0x852f, 0x0c81, 0x8637, 0x0008, 0x0c69, 0x8217, 0x7880,
- 0xa084, 0x0f00, 0xa206, 0x0170, 0x72da, 0x76d6, 0x0058, 0x7a80,
- 0xa294, 0x0f00, 0x70d8, 0xa236, 0x0dc0, 0x78e0, 0xa534, 0x0da8,
- 0xc1bd, 0x71d2, 0xd1b4, 0x1904, 0x259d, 0x2300, 0xa405, 0x0904,
- 0x259d, 0x70a0, 0xa086, 0x0001, 0x1904, 0x25e1, 0x0005, 0x6020,
- 0xa005, 0x0150, 0x8001, 0x6022, 0x6008, 0xa085, 0x0008, 0x600a,
- 0x700f, 0x0100, 0x702c, 0x6026, 0x0005, 0xa006, 0x080c, 0x3f26,
- 0x7000, 0xa086, 0x0002, 0x0120, 0x7060, 0xa086, 0x0005, 0x1150,
- 0x682b, 0x0000, 0x6817, 0x0000, 0x681b, 0x0001, 0x6823, 0x0040,
- 0x681f, 0x0100, 0x7000, 0xa084, 0x000f, 0x0002, 0x25a0, 0x3783,
- 0x3780, 0x37a0, 0x378c, 0x25a0, 0x377e, 0x377e, 0x080c, 0x254c,
- 0x0449, 0x0411, 0x0028, 0x0431, 0x7058, 0x2060, 0x6800, 0x6002,
- 0x080c, 0x1da2, 0x0804, 0x25a0, 0x7060, 0x7063, 0x0000, 0x707f,
- 0x0000, 0x0002, 0x379c, 0x379c, 0x379a, 0x379a, 0x379a, 0x379c,
- 0x379a, 0x379c, 0x0804, 0x2a6b, 0x7063, 0x0000, 0x0804, 0x25a0,
- 0x681b, 0x0000, 0x0804, 0x3184, 0x6800, 0xa005, 0x1108, 0x6002,
- 0x6006, 0x0005, 0x6410, 0x84ff, 0x0168, 0x2009, 0x4602, 0x2104,
- 0x8001, 0x200a, 0x8421, 0x6412, 0x1128, 0x2021, 0x4604, 0x2404,
- 0xc0a5, 0x2022, 0x6008, 0xc0a4, 0x600a, 0x0005, 0x6018, 0xa005,
- 0x0110, 0x8001, 0x601a, 0x0005, 0x080c, 0x3c46, 0x681b, 0x0018,
- 0x0490, 0x080c, 0x3c46, 0x681b, 0x0019, 0x0468, 0x080c, 0x3c46,
- 0x681b, 0x001a, 0x0440, 0x080c, 0x3c46, 0x681b, 0x0003, 0x0418,
- 0x7770, 0x080c, 0x3b6f, 0x7174, 0xa18c, 0x00ff, 0x3210, 0xa294,
- 0x0600, 0x0118, 0xa1e8, 0x8bc0, 0x0010, 0xa1e8, 0x8cd0, 0x2d04,
- 0x2d08, 0x2068, 0xa005, 0x1118, 0x707a, 0x0804, 0x25a0, 0x6814,
- 0x7270, 0xa206, 0x0110, 0x6800, 0x0c98, 0x6800, 0x200a, 0x681b,
- 0x0005, 0x707b, 0x0000, 0x080c, 0x37aa, 0x6820, 0xd084, 0x1110,
- 0x080c, 0x37a4, 0x080c, 0x37be, 0x681f, 0x0000, 0x6823, 0x0020,
- 0x080c, 0x1da2, 0x0804, 0x25a0, 0xa282, 0x0003, 0x1904, 0x3a10,
- 0x7da8, 0xa5ac, 0x00ff, 0x7ea8, 0xa6b4, 0x00ff, 0x6920, 0xc1bd,
- 0x6922, 0xd1c4, 0x05b0, 0xc1c4, 0x6922, 0xa6b4, 0x00ff, 0x0530,
- 0xa682, 0x0018, 0x0218, 0x0110, 0x2031, 0x0018, 0xa686, 0x0010,
- 0x1108, 0x8630, 0x852b, 0x852b, 0x2041, 0x0000, 0x080c, 0x3ac9,
- 0x0118, 0x080c, 0x38f7, 0x00a0, 0x080c, 0x3a95, 0x080c, 0x38f4,
- 0x6920, 0xc1c5, 0x6922, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x1118,
- 0x781b, 0x006e, 0x0005, 0x781b, 0x0082, 0x0005, 0x080c, 0x38f4,
+ 0x0010, 0x2001, 0x0001, 0x0002, 0x3c0b, 0x3c0b, 0x345c, 0x3c0b,
+ 0x3c4f, 0x3c4f, 0x3c0b, 0x3c0b, 0xd6bc, 0x0570, 0x7180, 0x81ff,
+ 0x0558, 0xa182, 0x000d, 0x1318, 0x7083, 0x0000, 0x0028, 0xa182,
+ 0x000c, 0x7082, 0x2009, 0x000c, 0x789b, 0x0061, 0x79aa, 0x0156,
+ 0x0136, 0x0146, 0x7084, 0x8114, 0xa210, 0x7286, 0xa080, 0x000b,
+ 0xad00, 0x2098, 0xb284, 0x0600, 0x0118, 0x20a1, 0x022b, 0x0010,
+ 0x20a1, 0x012b, 0x789b, 0x0000, 0x8108, 0x81ac, 0x53a6, 0x014e,
+ 0x013e, 0x015e, 0x0804, 0x3c11, 0xd6d4, 0x1904, 0x34cf, 0x6820,
+ 0xd084, 0x0904, 0x3c11, 0xa68c, 0x0060, 0xa684, 0x0060, 0x0120,
+ 0xa086, 0x0060, 0x1108, 0xc1f5, 0xc194, 0x795a, 0x69b6, 0x789b,
+ 0x0060, 0x78ab, 0x0000, 0x789b, 0x0061, 0x6818, 0xc0fd, 0x681a,
+ 0x78aa, 0x8008, 0x810c, 0x0904, 0x37f6, 0xa18c, 0x00f8, 0x1904,
+ 0x37f6, 0x0156, 0x0136, 0x0146, 0x0016, 0x20a1, 0x012b, 0x3208,
+ 0xa18c, 0x0600, 0x0110, 0x20a1, 0x022b, 0x001e, 0x789b, 0x0000,
+ 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x014e, 0x013e,
+ 0x015e, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x0804, 0x3c11, 0x6818,
+ 0xd0fc, 0x0110, 0x681b, 0x0008, 0x080c, 0x3a61, 0x781b, 0x00ed,
+ 0x0005, 0x2300, 0x0002, 0x34e0, 0x359d, 0x34de, 0x080c, 0x2575,
+ 0x7cd8, 0x7ddc, 0x7fd0, 0x82ff, 0x1528, 0x7200, 0xa286, 0x0003,
+ 0x0904, 0x2f09, 0x71d0, 0xd1bc, 0x11f8, 0xd1b4, 0x01e8, 0x2001,
+ 0x4701, 0x2004, 0xd0c4, 0x11c0, 0x00d6, 0x783b, 0x8800, 0x781b,
+ 0x0059, 0x70b8, 0xa06d, 0x68b4, 0xc0a5, 0x785a, 0x6894, 0x78d6,
+ 0x78de, 0x6898, 0x78d2, 0x78da, 0xc1b4, 0x71d2, 0x7003, 0x0030,
+ 0x00de, 0x0030, 0x7200, 0x0020, 0x783b, 0x1800, 0x781b, 0x0057,
+ 0xa284, 0x000f, 0x0002, 0x3588, 0x3545, 0x351d, 0x2f38, 0x351b,
+ 0x3588, 0x351b, 0x351b, 0x080c, 0x2575, 0x681c, 0xd0ec, 0x0118,
+ 0x6008, 0xc08d, 0x600a, 0x6920, 0xc185, 0x6922, 0x6800, 0x6006,
+ 0xa005, 0x1108, 0x6002, 0x6008, 0xc0d4, 0x600a, 0x681c, 0xa084,
+ 0x000e, 0x1120, 0x71c8, 0xa188, 0x0100, 0x0028, 0x7030, 0x68ba,
+ 0x713c, 0x70c8, 0xa108, 0x2104, 0x6802, 0x2d0a, 0x715a, 0xd6dc,
+ 0x1120, 0xc6fc, 0x6eb6, 0x0804, 0x3588, 0x6eb6, 0xa684, 0x0060,
+ 0x1120, 0xa684, 0x7fff, 0x68b6, 0x04d8, 0xd6dc, 0x1150, 0xa684,
+ 0x7fff, 0x68b6, 0x6894, 0x68a6, 0x6898, 0x68aa, 0x080c, 0x3f4e,
+ 0x0478, 0xd6ac, 0x0140, 0xa006, 0x080c, 0x3f4e, 0x2408, 0x2510,
+ 0x69aa, 0x6aa6, 0x0068, 0x2408, 0x2510, 0x2700, 0x8007, 0xa084,
+ 0x007f, 0xa108, 0xa291, 0x0000, 0x69aa, 0x6aa6, 0x080c, 0x3f4e,
+ 0xd6fc, 0x01b0, 0xa684, 0x7fff, 0x68b6, 0x2510, 0x2408, 0xd6ac,
+ 0x1138, 0x2700, 0x8007, 0xa084, 0x007f, 0xa108, 0xa291, 0x0000,
+ 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae,
+ 0x7000, 0xa086, 0x0030, 0x1904, 0x25c9, 0x7003, 0x0002, 0x70b8,
+ 0xa06d, 0x68bc, 0x703e, 0x70b4, 0xa065, 0x68c0, 0x7056, 0x2d00,
+ 0x704a, 0xad80, 0x0009, 0x7042, 0x0005, 0xa586, 0x8800, 0x1148,
+ 0x7003, 0x0000, 0x6018, 0x8001, 0x601a, 0x6008, 0xa084, 0xfbef,
+ 0x600a, 0x0804, 0x3a5b, 0x7043, 0x0000, 0xa282, 0x0006, 0x0310,
+ 0x080c, 0x2575, 0x2300, 0x0002, 0x35b7, 0x35c8, 0x35d2, 0x2200,
+ 0x0002, 0x35bf, 0x3a5b, 0x35c1, 0x35bf, 0x3603, 0x3651, 0x080c,
+ 0x2575, 0x7a80, 0xa294, 0x0f00, 0x080c, 0x36a5, 0x0804, 0x3a30,
+ 0x00c1, 0x0002, 0x3a5b, 0x35d0, 0x35d0, 0x3603, 0x35d0, 0x3a5b,
+ 0x080c, 0x2575, 0x0071, 0x0002, 0x35dc, 0x35da, 0x35da, 0x35dc,
+ 0x35da, 0x35dc, 0x080c, 0x2575, 0x080c, 0x3a70, 0x781b, 0x0082,
+ 0x0005, 0x7000, 0xa086, 0x0002, 0x1150, 0x080c, 0x37e1, 0x0010,
+ 0x080c, 0x3f4e, 0x6008, 0xa084, 0xfbef, 0x600a, 0x0020, 0x7000,
+ 0xa086, 0x0003, 0x0da8, 0x7003, 0x0005, 0x2001, 0x8ee0, 0xae8e,
+ 0x4740, 0x0110, 0x2001, 0x8f12, 0x2068, 0x704a, 0xad80, 0x0009,
+ 0x7042, 0x2200, 0x0005, 0x7000, 0xa086, 0x0002, 0x1158, 0x70d0,
+ 0xc0b5, 0x70d2, 0x2c00, 0x70b6, 0x2d00, 0x70ba, 0x0038, 0x080c,
+ 0x3f4e, 0x0020, 0x7000, 0xa086, 0x0003, 0x0dc8, 0x7003, 0x0001,
+ 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, 0x001f,
+ 0xa215, 0x2069, 0x8dc0, 0xb284, 0x0600, 0x1118, 0xc2fd, 0x2069,
+ 0x8ed0, 0x2d04, 0x2d08, 0x715a, 0xa06d, 0x0128, 0x6814, 0xa206,
+ 0x0120, 0x6800, 0x0cb8, 0x080c, 0x36a5, 0x6eb4, 0x7e5a, 0x6920,
+ 0xa184, 0x0c00, 0x0904, 0x36cb, 0x7060, 0xa086, 0x0006, 0x1128,
+ 0x7070, 0xa206, 0x1110, 0x7062, 0x707a, 0x681b, 0x0005, 0xc1ad,
+ 0x681b, 0x0005, 0xc1ad, 0xc1d4, 0x6922, 0x080c, 0x3a67, 0x0804,
+ 0x36cb, 0x7200, 0xa286, 0x0002, 0x1158, 0x70d0, 0xc0b5, 0x70d2,
+ 0x2c00, 0x70b6, 0x2d00, 0x70ba, 0x0030, 0x080c, 0x3f4e, 0x0018,
+ 0xa286, 0x0003, 0x0dd0, 0x7003, 0x0001, 0x7a80, 0xa294, 0x0f00,
+ 0x789b, 0x0018, 0x7ca8, 0xa484, 0x001f, 0xa215, 0xae86, 0x4740,
+ 0x0108, 0xc2fd, 0x79a8, 0x79a8, 0xa18c, 0x00ff, 0x2118, 0x70c8,
+ 0xa168, 0x2d04, 0x2d08, 0x715a, 0xa06d, 0x0128, 0x6814, 0xa206,
+ 0x0118, 0x6800, 0x0cb8, 0x0409, 0x6eb4, 0x6920, 0xa184, 0x0c00,
+ 0x0904, 0x36cb, 0xd0dc, 0x0178, 0x7060, 0xa086, 0x0004, 0x1140,
+ 0x7070, 0xa206, 0x1128, 0x7074, 0xa306, 0x1110, 0x7062, 0x707a,
+ 0x080c, 0x3a6d, 0x0480, 0x681b, 0x0005, 0xc1ad, 0xc1d4, 0x6922,
+ 0x080c, 0x3a67, 0x707b, 0x0000, 0x0430, 0x7003, 0x0005, 0xb284,
+ 0x0600, 0x0118, 0x2001, 0x8ee0, 0x0010, 0x2001, 0x8f12, 0x2068,
+ 0x704a, 0x0156, 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, 0x1f04,
+ 0x36b4, 0x015e, 0xb284, 0x0600, 0x0110, 0xc2fc, 0x0008, 0xc2fd,
+ 0x6a16, 0xad80, 0x0009, 0x7042, 0x68b7, 0x0700, 0x6823, 0x0800,
+ 0x6827, 0x0003, 0x0005, 0xc6ec, 0xa6ac, 0x0060, 0x0904, 0x3712,
+ 0x6b98, 0x6c94, 0x69ac, 0x68b0, 0xa105, 0x11e0, 0x7bd2, 0x7bda,
+ 0x7cd6, 0x7cde, 0xa586, 0x0060, 0x05c8, 0xd6f4, 0x1108, 0xc6ed,
+ 0xa6b4, 0xb7ff, 0x7e5a, 0x2009, 0x0083, 0xd69c, 0x0128, 0x2009,
+ 0x0082, 0x2019, 0x0000, 0x2320, 0x791a, 0xd6ec, 0x0588, 0x080c,
+ 0x4208, 0x0470, 0x68b0, 0xa31a, 0x2100, 0xa423, 0x2400, 0xa305,
+ 0x01f8, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0x68b0, 0xd6f4, 0x1108,
+ 0xc6ed, 0xc6f4, 0x7e5a, 0x2011, 0x0083, 0xd69c, 0x0128, 0x2011,
+ 0x0082, 0x2019, 0x0000, 0x2320, 0x7a1a, 0xd6ec, 0x0188, 0x080c,
+ 0x4235, 0x0070, 0x2019, 0x0000, 0x2320, 0x0010, 0xa6b4, 0xb7ff,
+ 0x7e5a, 0x2009, 0x0083, 0xd69c, 0x0110, 0x2009, 0x0082, 0x791a,
+ 0x68c0, 0x7056, 0x2d00, 0x704a, 0x68c4, 0x2060, 0x71d0, 0x2001,
+ 0x4701, 0x2004, 0xd0c4, 0x15c8, 0x70d4, 0xa02d, 0x01b8, 0xd1bc,
+ 0x0548, 0x7a80, 0xa294, 0x0f00, 0x70d8, 0xa206, 0x0118, 0x78e0,
+ 0xa504, 0x1558, 0x70d6, 0xc1bc, 0x71d2, 0x0438, 0x2031, 0x0001,
+ 0x852c, 0x0218, 0x8633, 0x8210, 0x0cd8, 0x0005, 0x7de0, 0xa594,
+ 0xff00, 0x0130, 0x2011, 0x0008, 0x852f, 0x0c81, 0x8637, 0x0008,
+ 0x0c69, 0x8217, 0x7880, 0xa084, 0x0f00, 0xa206, 0x0170, 0x72da,
+ 0x76d6, 0x0058, 0x7a80, 0xa294, 0x0f00, 0x70d8, 0xa236, 0x0dc0,
+ 0x78e0, 0xa534, 0x0da8, 0xc1bd, 0x71d2, 0xd1b4, 0x1904, 0x25c6,
+ 0x2300, 0xa405, 0x0904, 0x25c6, 0x70a0, 0xa086, 0x0001, 0x1904,
+ 0x260d, 0x0005, 0x6020, 0xa005, 0x0150, 0x8001, 0x6022, 0x6008,
+ 0xa085, 0x0008, 0x600a, 0x700f, 0x0100, 0x702c, 0x6026, 0x0005,
+ 0xa006, 0x080c, 0x3f4e, 0x7000, 0xa086, 0x0002, 0x0120, 0x7060,
+ 0xa086, 0x0005, 0x1150, 0x682b, 0x0000, 0x6817, 0x0000, 0x681b,
+ 0x0001, 0x6823, 0x0040, 0x681f, 0x0100, 0x7000, 0xa084, 0x000f,
+ 0x0002, 0x25c9, 0x37a6, 0x37a3, 0x37c3, 0x37af, 0x25c9, 0x37a1,
+ 0x37a1, 0x080c, 0x2575, 0x0449, 0x0411, 0x0028, 0x0431, 0x7058,
+ 0x2060, 0x6800, 0x6002, 0x080c, 0x1dbf, 0x0804, 0x25c9, 0x7060,
+ 0x7063, 0x0000, 0x707f, 0x0000, 0x0002, 0x37bf, 0x37bf, 0x37bd,
+ 0x37bd, 0x37bd, 0x37bf, 0x37bd, 0x37bf, 0x0804, 0x2a9a, 0x7063,
+ 0x0000, 0x0804, 0x25c9, 0x681b, 0x0000, 0x0804, 0x31a7, 0x6800,
+ 0xa005, 0x1108, 0x6002, 0x6006, 0x0005, 0x6410, 0x84ff, 0x0168,
+ 0x2009, 0x4702, 0x2104, 0x8001, 0x200a, 0x8421, 0x6412, 0x1128,
+ 0x2021, 0x4704, 0x2404, 0xc0a5, 0x2022, 0x6008, 0xc0a4, 0x600a,
+ 0x0005, 0x6018, 0xa005, 0x0110, 0x8001, 0x601a, 0x0005, 0x080c,
+ 0x3c6e, 0x681b, 0x0018, 0x0490, 0x080c, 0x3c6e, 0x681b, 0x0019,
+ 0x0468, 0x080c, 0x3c6e, 0x681b, 0x001a, 0x0440, 0x080c, 0x3c6e,
+ 0x681b, 0x0003, 0x0418, 0x7770, 0x080c, 0x3b95, 0x7174, 0xa18c,
+ 0x00ff, 0x3210, 0xa294, 0x0600, 0x0118, 0xa1e8, 0x8cc0, 0x0010,
+ 0xa1e8, 0x8dd0, 0x2d04, 0x2d08, 0x2068, 0xa005, 0x1118, 0x707a,
+ 0x0804, 0x25c9, 0x6814, 0x7270, 0xa206, 0x0110, 0x6800, 0x0c98,
+ 0x6800, 0x200a, 0x681b, 0x0005, 0x707b, 0x0000, 0x080c, 0x37cd,
+ 0x6820, 0xd084, 0x1110, 0x080c, 0x37c7, 0x080c, 0x37e1, 0x681f,
+ 0x0000, 0x6823, 0x0020, 0x080c, 0x1dbf, 0x0804, 0x25c9, 0xa282,
+ 0x0003, 0x1904, 0x3a35, 0x7da8, 0xa5ac, 0x00ff, 0x7ea8, 0xa6b4,
+ 0x00ff, 0x6920, 0xc1bd, 0x6922, 0xd1c4, 0x05b0, 0xc1c4, 0x6922,
+ 0xa6b4, 0x00ff, 0x0530, 0xa682, 0x0018, 0x0218, 0x0110, 0x2031,
+ 0x0018, 0xa686, 0x0010, 0x1108, 0x8630, 0x852b, 0x852b, 0x2041,
+ 0x0000, 0x080c, 0x3aee, 0x0118, 0x080c, 0x391a, 0x00a0, 0x080c,
+ 0x3aba, 0x080c, 0x3917, 0x6920, 0xc1c5, 0x6922, 0x7e58, 0xc695,
+ 0x7e5a, 0xd6d4, 0x1118, 0x781b, 0x006e, 0x0005, 0x781b, 0x0082,
+ 0x0005, 0x080c, 0x3917, 0x7e58, 0xd6d4, 0x1118, 0x781b, 0x0071,
+ 0x0005, 0x781b, 0x0083, 0x0005, 0x00c6, 0x7054, 0x2060, 0x6100,
+ 0xd1e4, 0x0598, 0x6208, 0x8217, 0xa294, 0x00ff, 0xa282, 0x0018,
+ 0x0218, 0x0110, 0x2011, 0x0018, 0x2600, 0xa202, 0x1208, 0x2230,
+ 0xa686, 0x0010, 0x1108, 0x8630, 0x6208, 0xa294, 0x00ff, 0x78ec,
+ 0xd0e4, 0x0130, 0xa282, 0x000a, 0x1240, 0x2011, 0x000a, 0x0028,
+ 0xa282, 0x000c, 0x1210, 0x2011, 0x000c, 0x2200, 0xa502, 0x1208,
+ 0x2228, 0x080c, 0x3abe, 0x852b, 0x852b, 0x2041, 0x0000, 0x080c,
+ 0x3aee, 0x0118, 0x080c, 0x391a, 0x0020, 0x080c, 0x3aba, 0x080c,
+ 0x3917, 0x7858, 0xc095, 0x785a, 0x00ce, 0x781b, 0x0082, 0x0005,
+ 0x00c6, 0x2960, 0x6000, 0xd0e4, 0x1188, 0xd0b4, 0x1150, 0x6010,
+ 0xa084, 0x000f, 0x1130, 0x6104, 0xa18c, 0xfff5, 0x6106, 0x00ce,
+ 0x0005, 0x2011, 0x0032, 0x2019, 0x0000, 0x00f0, 0x68a0, 0xd0cc,
+ 0x1dc0, 0x6208, 0xa294, 0x00ff, 0x78ec, 0xd0e4, 0x0130, 0xa282,
+ 0x000b, 0x1218, 0x2011, 0x000a, 0x0028, 0xa282, 0x000c, 0x1210,
+ 0x2011, 0x000c, 0x6308, 0x831f, 0xa39c, 0x00ff, 0xa382, 0x0018,
+ 0x0218, 0x0110, 0x2019, 0x0018, 0x78ab, 0x0001, 0x78ab, 0x0003,
+ 0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820, 0xc0c5,
+ 0x6822, 0x080c, 0x3a7a, 0x00ce, 0x0005, 0x00c6, 0x2960, 0x6104,
+ 0xa18c, 0xfff5, 0x6106, 0x2011, 0x0032, 0x2019, 0x0000, 0x0000,
+ 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa,
+ 0xa8c0, 0x0005, 0x6820, 0xc0c5, 0x6822, 0x00ce, 0x0005, 0xa006,
+ 0x2030, 0x2010, 0x00c6, 0x7154, 0x2160, 0x2018, 0x2008, 0xa084,
+ 0xffe0, 0xa635, 0x7e86, 0x6018, 0x789a, 0x7eae, 0x6612, 0x78a4,
+ 0xa084, 0x7770, 0xa18c, 0x000f, 0xa105, 0x2029, 0x4705, 0x252c,
+ 0xd5cc, 0x0140, 0xd3a4, 0x0110, 0xa085, 0x0800, 0xd3fc, 0x0110,
+ 0xa085, 0x8080, 0x78a6, 0x6016, 0x788a, 0xa6b4, 0x001f, 0x8637,
+ 0x8204, 0x8004, 0xa605, 0x600e, 0x6004, 0xa084, 0xffd5, 0x6006,
+ 0x00ce, 0x0005, 0xa282, 0x0002, 0x1904, 0x3a3f, 0x7aa8, 0x6920,
+ 0xc1bd, 0x6922, 0xd1cc, 0x0568, 0xc1cc, 0x6922, 0xa294, 0x00ff,
+ 0xa282, 0x0002, 0x1a04, 0x3a30, 0x080c, 0x39c1, 0x080c, 0x3917,
+ 0xa980, 0x0001, 0x200c, 0x080c, 0x3b91, 0x080c, 0x38b8, 0x88ff,
+ 0x0178, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695, 0x7e5a,
+ 0xd6d4, 0x1118, 0x781b, 0x006e, 0x0005, 0x781b, 0x0082, 0x0005,
0x7e58, 0xd6d4, 0x1118, 0x781b, 0x0071, 0x0005, 0x781b, 0x0083,
- 0x0005, 0x00c6, 0x7054, 0x2060, 0x6100, 0xd1e4, 0x0598, 0x6208,
- 0x8217, 0xa294, 0x00ff, 0xa282, 0x0018, 0x0218, 0x0110, 0x2011,
- 0x0018, 0x2600, 0xa202, 0x1208, 0x2230, 0xa686, 0x0010, 0x1108,
- 0x8630, 0x6208, 0xa294, 0x00ff, 0x78ec, 0xd0e4, 0x0130, 0xa282,
- 0x000a, 0x1240, 0x2011, 0x000a, 0x0028, 0xa282, 0x000c, 0x1210,
- 0x2011, 0x000c, 0x2200, 0xa502, 0x1208, 0x2228, 0x080c, 0x3a99,
- 0x852b, 0x852b, 0x2041, 0x0000, 0x080c, 0x3ac9, 0x0118, 0x080c,
- 0x38f7, 0x0020, 0x080c, 0x3a95, 0x080c, 0x38f4, 0x7858, 0xc095,
- 0x785a, 0x00ce, 0x781b, 0x0082, 0x0005, 0x00c6, 0x2960, 0x6000,
- 0xd0e4, 0x1188, 0xd0b4, 0x1150, 0x6010, 0xa084, 0x000f, 0x1130,
- 0x6104, 0xa18c, 0xfff5, 0x6106, 0x00ce, 0x0005, 0x2011, 0x0032,
- 0x2019, 0x0000, 0x00f0, 0x68a0, 0xd0cc, 0x1dc0, 0x6208, 0xa294,
- 0x00ff, 0x78ec, 0xd0e4, 0x0130, 0xa282, 0x000b, 0x1218, 0x2011,
- 0x000a, 0x0028, 0xa282, 0x000c, 0x1210, 0x2011, 0x000c, 0x6308,
- 0x831f, 0xa39c, 0x00ff, 0xa382, 0x0018, 0x0218, 0x0110, 0x2019,
- 0x0018, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa,
- 0x7baa, 0xa8c0, 0x0005, 0x6820, 0xc0c5, 0x6822, 0x080c, 0x3a55,
- 0x00ce, 0x0005, 0x00c6, 0x2960, 0x6104, 0xa18c, 0xfff5, 0x6106,
- 0x2011, 0x0032, 0x2019, 0x0000, 0x0000, 0x78ab, 0x0001, 0x78ab,
- 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820,
- 0xc0c5, 0x6822, 0x00ce, 0x0005, 0xa006, 0x2030, 0x2010, 0x00c6,
- 0x7154, 0x2160, 0x2018, 0x2008, 0xa084, 0xffe0, 0xa635, 0x7e86,
- 0x6018, 0x789a, 0x7eae, 0x6612, 0x78a4, 0xa084, 0x7770, 0xa18c,
- 0x000f, 0xa105, 0x2029, 0x4605, 0x252c, 0xd5cc, 0x0140, 0xd3a4,
- 0x0110, 0xa085, 0x0800, 0xd3fc, 0x0110, 0xa085, 0x8080, 0x78a6,
- 0x6016, 0x788a, 0xa6b4, 0x001f, 0x8637, 0x8204, 0x8004, 0xa605,
- 0x600e, 0x6004, 0xa084, 0xffd5, 0x6006, 0x00ce, 0x0005, 0xa282,
- 0x0002, 0x1904, 0x3a1a, 0x7aa8, 0x6920, 0xc1bd, 0x6922, 0xd1cc,
- 0x0568, 0xc1cc, 0x6922, 0xa294, 0x00ff, 0xa282, 0x0002, 0x1a04,
- 0x3a0b, 0x080c, 0x399e, 0x080c, 0x38f4, 0xa980, 0x0001, 0x200c,
- 0x080c, 0x3b6b, 0x080c, 0x3895, 0x88ff, 0x0178, 0x789b, 0x0060,
- 0x2800, 0x78aa, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x1118, 0x781b,
- 0x006e, 0x0005, 0x781b, 0x0082, 0x0005, 0x7e58, 0xd6d4, 0x1118,
- 0x781b, 0x0071, 0x0005, 0x781b, 0x0083, 0x0005, 0xa282, 0x0002,
- 0x1218, 0xa284, 0x0001, 0x0140, 0x7154, 0xa188, 0x0000, 0x210c,
- 0xd1ec, 0x1110, 0x2011, 0x0000, 0x080c, 0x3a87, 0x0479, 0x080c,
- 0x38f4, 0x7858, 0xc095, 0x785a, 0x781b, 0x0082, 0x0005, 0x00c6,
- 0x0026, 0x2960, 0x6000, 0x2011, 0x0001, 0xd0ec, 0x1158, 0xd0bc,
- 0x1138, 0x6014, 0xd0b4, 0x1120, 0xc1a4, 0x6106, 0xa006, 0x0088,
- 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003,
- 0x7aaa, 0xa8c0, 0x0004, 0x080c, 0x3a55, 0x6820, 0xa085, 0x0200,
- 0x6822, 0x002e, 0x00ce, 0x0005, 0x8807, 0xa715, 0x00c6, 0x2009,
- 0x0000, 0x7054, 0x2060, 0x82ff, 0x0110, 0x2009, 0x0040, 0x6018,
- 0xa080, 0x0002, 0x789a, 0x78a4, 0xa084, 0xff9f, 0xa105, 0xc0ec,
- 0xd0b4, 0x1108, 0xc0ed, 0x6100, 0xd1f4, 0x0110, 0xa085, 0x0020,
- 0x78a6, 0x6016, 0x788a, 0x6004, 0xa084, 0xffef, 0x6006, 0x00ce,
- 0x0005, 0x0006, 0x7000, 0xa086, 0x0003, 0x0110, 0x000e, 0x0010,
- 0x000e, 0x0488, 0xd6ac, 0x0578, 0x7888, 0xa084, 0x0040, 0x0558,
- 0x7bb8, 0x8307, 0xa084, 0x007f, 0x1508, 0x8207, 0xa084, 0x00ff,
- 0xa09e, 0x0001, 0x1904, 0x3a32, 0xd6f4, 0x11d0, 0x79d8, 0x7adc,
- 0xa108, 0xa291, 0x0000, 0x79d2, 0x79da, 0x7ad6, 0x7ade, 0x080c,
- 0x42b5, 0x781b, 0x0080, 0xb284, 0x0600, 0x0118, 0x2001, 0x0000,
- 0x0010, 0x2001, 0x0001, 0x080c, 0x4172, 0x0005, 0x080c, 0x254c,
- 0x781b, 0x0080, 0x0005, 0x781b, 0x0083, 0x0005, 0x2039, 0x0000,
- 0x2041, 0x0000, 0x2031, 0x0000, 0xa006, 0x2010, 0x080c, 0x38f7,
- 0x080c, 0x399c, 0x7e58, 0x080c, 0x3a4e, 0x781b, 0x0082, 0x0005,
- 0x0cd1, 0x6820, 0xc0c4, 0x6822, 0x00c6, 0x7054, 0x2060, 0x080c,
- 0x3921, 0x00b0, 0x0c81, 0x6820, 0xc0cc, 0x6822, 0x00c6, 0x7054,
- 0x2060, 0x080c, 0x39bb, 0x0060, 0x0c31, 0x6820, 0xa084, 0xecff,
- 0x6822, 0x00c6, 0x7054, 0x2060, 0x6004, 0xa084, 0xffc5, 0x6006,
- 0x00ce, 0x0005, 0x0049, 0x781b, 0x0082, 0x0005, 0x6827, 0x0002,
- 0x0049, 0x781b, 0x0082, 0x0005, 0x2001, 0x0005, 0x0088, 0x2001,
- 0x000c, 0x0070, 0x6820, 0xc0d5, 0x6822, 0x2001, 0x0006, 0x0040,
- 0x2001, 0x000d, 0x0028, 0x2001, 0x0009, 0x0010, 0x2001, 0x0007,
- 0x789b, 0x007e, 0x78aa, 0xc69d, 0x7e5a, 0x70d0, 0xd0b4, 0x0168,
- 0xc0b4, 0x70d2, 0x00c6, 0x70b4, 0xa065, 0x6008, 0xa084, 0xfbef,
- 0x600a, 0x6018, 0x8001, 0x601a, 0x00ce, 0x0005, 0x0076, 0x873f,
- 0xa7bc, 0x000f, 0x873b, 0x873b, 0x8703, 0xa0e0, 0x4ac0, 0xae8e,
- 0x4640, 0x0110, 0xa0e0, 0x4b40, 0xa7b8, 0x0020, 0x7f9a, 0x79a4,
- 0xa184, 0x7fe0, 0x78ae, 0x6012, 0x79a4, 0xa184, 0x773f, 0x78a6,
- 0x6016, 0x6004, 0xa085, 0x0038, 0x6006, 0x007e, 0x0005, 0x789b,
- 0x0080, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa,
- 0x789b, 0x0060, 0x78ab, 0x0004, 0x0800, 0x2031, 0x0000, 0x2029,
- 0x0032, 0x789b, 0x0080, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab,
- 0x0001, 0x7daa, 0x7eaa, 0x789b, 0x0060, 0x78ab, 0x0005, 0x0804,
- 0x3a55, 0x0156, 0x8007, 0xa084, 0x00ff, 0x8003, 0x8003, 0xa080,
- 0x0020, 0x789a, 0x79a4, 0xa18c, 0xffe0, 0x2021, 0x3b54, 0x2019,
- 0x0011, 0x20a9, 0x000e, 0x2011, 0x0032, 0x2404, 0xa084, 0xffe0,
- 0xa106, 0x0128, 0x8420, 0x2300, 0xa210, 0x1f04, 0x3abd, 0x015e,
- 0x0005, 0x0156, 0x04f8, 0x2021, 0x3b62, 0x20a9, 0x0009, 0x2011,
- 0x0029, 0xa582, 0x0028, 0x0550, 0x8420, 0x95a9, 0x2011, 0x0033,
- 0xa582, 0x0033, 0x0618, 0x8420, 0x95a9, 0x2019, 0x000a, 0x2011,
- 0x0065, 0x2200, 0xa502, 0x02d0, 0x8420, 0x2300, 0xa210, 0x1f04,
- 0x3ae1, 0x015e, 0x0088, 0x2021, 0x3b54, 0x2019, 0x0011, 0x20a9,
- 0x000e, 0x2011, 0x0033, 0x2200, 0xa502, 0x0240, 0x8420, 0x2300,
- 0xa210, 0x1f04, 0x3af3, 0x015e, 0xa006, 0x0005, 0x8211, 0x015e,
- 0xa582, 0x0064, 0x1220, 0x7808, 0xa085, 0x0070, 0x780a, 0x2404,
- 0xa005, 0x0005, 0xa886, 0x0002, 0x01e8, 0x2021, 0x3b40, 0x20a9,
- 0x000d, 0x2011, 0x0028, 0xa582, 0x0028, 0x0d48, 0x8420, 0x2019,
- 0x0019, 0x2011, 0x0033, 0x2200, 0xa502, 0x0e00, 0x8420, 0x2300,
- 0xa210, 0x1f04, 0x3b1b, 0x015e, 0x2011, 0x0184, 0xa582, 0x0185,
- 0x0ab0, 0x0890, 0x2021, 0x3b4f, 0x20a9, 0x0003, 0x2011, 0x0024,
- 0xa586, 0x0024, 0x0960, 0x8420, 0x2011, 0x0028, 0xa586, 0x0028,
- 0x0930, 0x8420, 0x2019, 0x0019, 0x2011, 0x0033, 0x0804, 0x3af3,
- 0x1021, 0x2202, 0x3403, 0x4604, 0x5805, 0x6a06, 0x7c07, 0x4610,
- 0x4612, 0x5812, 0x5a12, 0x6a14, 0x6c14, 0x6e14, 0x7e17, 0x9021,
- 0xb002, 0xe204, 0xe210, 0xe210, 0x1209, 0x3002, 0x3202, 0x4203,
- 0x4403, 0x5404, 0x5604, 0x6605, 0x6805, 0x7806, 0x7a06, 0x0c07,
- 0x0c07, 0x0e07, 0x10e1, 0x330a, 0x5805, 0x5a05, 0x6a06, 0x6c06,
- 0x7c07, 0x7e07, 0x0e00, 0x789b, 0x0080, 0xa046, 0x0005, 0xa784,
- 0x0f00, 0x800b, 0xa784, 0x001f, 0x8003, 0x8003, 0x8003, 0x8003,
- 0xa105, 0xd7fc, 0x0118, 0xa0e0, 0x6bc0, 0x0010, 0xa0e0, 0x4bc0,
- 0x0005, 0x00e6, 0x00f6, 0xd084, 0x0138, 0x2079, 0x0100, 0x2009,
- 0x4680, 0x2071, 0x4680, 0x0030, 0x2009, 0x4640, 0x2079, 0x0200,
- 0x2071, 0x4640, 0x2091, 0x8000, 0x2104, 0xa084, 0x000f, 0x0002,
- 0x3ba2, 0x3ba2, 0x3ba2, 0x3ba2, 0x3ba2, 0x3ba2, 0x3ba0, 0x3ba0,
- 0x080c, 0x254c, 0x69b4, 0xc1f5, 0xa18c, 0xff9f, 0x69b6, 0xa005,
- 0x0580, 0x7858, 0xa084, 0xff9f, 0xa085, 0x6000, 0x785a, 0x7828,
- 0xa086, 0x1814, 0x1530, 0x784b, 0x0004, 0x7848, 0xa084, 0x0004,
- 0x1de0, 0x784b, 0x0008, 0x7848, 0xa084, 0x0008, 0x1de0, 0x7830,
- 0xd0bc, 0x11b8, 0xb284, 0x0800, 0x0118, 0x0104, 0x3bd9, 0x0010,
- 0x0304, 0x3bd9, 0x79e4, 0xa184, 0x0030, 0x0158, 0x78ec, 0xa084,
- 0x0003, 0x0138, 0x681c, 0xd0ac, 0x1110, 0x00d9, 0x0010, 0x781b,
- 0x00fb, 0x00fe, 0x00ee, 0x0005, 0x2001, 0x4601, 0x2004, 0xd0ac,
- 0x1118, 0x6814, 0x080c, 0x2475, 0x0005, 0x781b, 0x0083, 0x0005,
- 0x781b, 0x0082, 0x0005, 0x781b, 0x0071, 0x0005, 0x781b, 0x006e,
- 0x0005, 0x2009, 0x4619, 0x210c, 0xa186, 0x0000, 0x0150, 0xa186,
- 0x0001, 0x0150, 0x701f, 0x000b, 0x7063, 0x0001, 0x781b, 0x0054,
- 0x0005, 0x781b, 0x00f3, 0x0005, 0x701f, 0x000a, 0x0005, 0x2009,
- 0x4619, 0x210c, 0xa186, 0x0000, 0x0168, 0xa186, 0x0001, 0x0138,
- 0x701f, 0x000b, 0x7063, 0x0001, 0x781b, 0x0054, 0x0005, 0x701f,
- 0x000a, 0x0005, 0x781b, 0x00f2, 0x0005, 0x781b, 0x00fb, 0x0005,
- 0x781b, 0x00fa, 0x0005, 0x781b, 0x00cc, 0x0005, 0x781b, 0x00cb,
- 0x0005, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x001d, 0x7063, 0x0001,
+ 0x0005, 0xa282, 0x0002, 0x1218, 0xa284, 0x0001, 0x0140, 0x7154,
+ 0xa188, 0x0000, 0x210c, 0xd1ec, 0x1110, 0x2011, 0x0000, 0x080c,
+ 0x3aac, 0x0479, 0x080c, 0x3917, 0x7858, 0xc095, 0x785a, 0x781b,
+ 0x0082, 0x0005, 0x00c6, 0x0026, 0x2960, 0x6000, 0x2011, 0x0001,
+ 0xd0ec, 0x1158, 0xd0bc, 0x1138, 0x6014, 0xd0b4, 0x1120, 0xc1a4,
+ 0x6106, 0xa006, 0x0088, 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab,
+ 0x0002, 0x78ab, 0x0003, 0x7aaa, 0xa8c0, 0x0004, 0x080c, 0x3a7a,
+ 0x6820, 0xa085, 0x0200, 0x6822, 0x002e, 0x00ce, 0x0005, 0x8807,
+ 0xa715, 0x00c6, 0x2009, 0x0000, 0x7054, 0x2060, 0x82ff, 0x0110,
+ 0x2009, 0x0040, 0x6018, 0xa080, 0x0002, 0x789a, 0x78a4, 0xa084,
+ 0xff9f, 0xa105, 0xc0ec, 0xd0b4, 0x1108, 0xc0ed, 0x6100, 0xd1f4,
+ 0x0110, 0xa085, 0x0020, 0x78a6, 0x6016, 0x788a, 0x6004, 0xa084,
+ 0xffef, 0x6006, 0x00ce, 0x0005, 0x0006, 0x7000, 0xa086, 0x0003,
+ 0x0110, 0x000e, 0x0010, 0x000e, 0x0498, 0xd6ac, 0x0588, 0x7888,
+ 0xa084, 0x0040, 0x0568, 0x7bb8, 0x8307, 0xa084, 0x007f, 0x1518,
+ 0x8207, 0xa084, 0x00ff, 0x0904, 0x3a57, 0xa09a, 0x0004, 0x1a04,
+ 0x3a57, 0xd6f4, 0x11d0, 0x79d8, 0x7adc, 0xa108, 0xa291, 0x0000,
+ 0x79d2, 0x79da, 0x7ad6, 0x7ade, 0x080c, 0x42e8, 0x781b, 0x0080,
+ 0xb284, 0x0600, 0x0118, 0x2001, 0x0000, 0x0010, 0x2001, 0x0001,
+ 0x080c, 0x419a, 0x0005, 0x080c, 0x2575, 0x781b, 0x0080, 0x0005,
+ 0x781b, 0x0083, 0x0005, 0x2039, 0x0000, 0x2041, 0x0000, 0x2031,
+ 0x0000, 0xa006, 0x2010, 0x080c, 0x391a, 0x080c, 0x39bf, 0x7e58,
+ 0x080c, 0x3a73, 0x781b, 0x0082, 0x0005, 0x0cd1, 0x6820, 0xc0c4,
+ 0x6822, 0x00c6, 0x7054, 0x2060, 0x080c, 0x3944, 0x00b0, 0x0c81,
+ 0x6820, 0xc0cc, 0x6822, 0x00c6, 0x7054, 0x2060, 0x080c, 0x39de,
+ 0x0060, 0x0c31, 0x6820, 0xa084, 0xecff, 0x6822, 0x00c6, 0x7054,
+ 0x2060, 0x6004, 0xa084, 0xffc5, 0x6006, 0x00ce, 0x0005, 0x0049,
+ 0x781b, 0x0082, 0x0005, 0x6827, 0x0002, 0x0049, 0x781b, 0x0082,
+ 0x0005, 0x2001, 0x0005, 0x0088, 0x2001, 0x000c, 0x0070, 0x6820,
+ 0xc0d5, 0x6822, 0x2001, 0x0006, 0x0040, 0x2001, 0x000d, 0x0028,
+ 0x2001, 0x0009, 0x0010, 0x2001, 0x0007, 0x789b, 0x007e, 0x78aa,
+ 0xc69d, 0x7e5a, 0x70d0, 0xd0b4, 0x0168, 0xc0b4, 0x70d2, 0x00c6,
+ 0x70b4, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001,
+ 0x601a, 0x00ce, 0x0005, 0x0076, 0x873f, 0xa7bc, 0x000f, 0x873b,
+ 0x873b, 0x8703, 0xa0e0, 0x4bc0, 0xae8e, 0x4740, 0x0110, 0xa0e0,
+ 0x4c40, 0xa7b8, 0x0020, 0x7f9a, 0x79a4, 0xa184, 0x7fe0, 0x78ae,
+ 0x6012, 0x79a4, 0xa184, 0x773f, 0x78a6, 0x6016, 0x6004, 0xa085,
+ 0x0038, 0x6006, 0x007e, 0x0005, 0x789b, 0x0080, 0x78ab, 0x0001,
+ 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0060, 0x78ab,
+ 0x0004, 0x0800, 0x2031, 0x0000, 0x2029, 0x0032, 0x789b, 0x0080,
+ 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa, 0x7eaa,
+ 0x789b, 0x0060, 0x78ab, 0x0005, 0x0804, 0x3a7a, 0x0156, 0x8007,
+ 0xa084, 0x00ff, 0x8003, 0x8003, 0xa080, 0x0020, 0x789a, 0x79a4,
+ 0xa18c, 0xffe0, 0x2021, 0x3b7a, 0x2019, 0x0011, 0x20a9, 0x000e,
+ 0x2011, 0x0032, 0x2404, 0xa084, 0xffe0, 0xa106, 0x0128, 0x8420,
+ 0x2300, 0xa210, 0x1f04, 0x3ae2, 0x015e, 0x0005, 0x0156, 0x0804,
+ 0x3b30, 0x2021, 0x3b88, 0x20a9, 0x0009, 0x2011, 0x0029, 0xa582,
+ 0x0028, 0x0550, 0x8420, 0x95a9, 0x2011, 0x0033, 0xa582, 0x0033,
+ 0x0618, 0x8420, 0x95a9, 0x2019, 0x000a, 0x2011, 0x0065, 0x2200,
+ 0xa502, 0x02d0, 0x8420, 0x2300, 0xa210, 0x1f04, 0x3b07, 0x015e,
+ 0x0088, 0x2021, 0x3b7a, 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011,
+ 0x0033, 0x2200, 0xa502, 0x0240, 0x8420, 0x2300, 0xa210, 0x1f04,
+ 0x3b19, 0x015e, 0xa006, 0x0005, 0x8211, 0x015e, 0xa582, 0x0064,
+ 0x1220, 0x7808, 0xa085, 0x0070, 0x780a, 0x2404, 0xa005, 0x0005,
+ 0xa886, 0x0002, 0x01e8, 0x2021, 0x3b66, 0x20a9, 0x000d, 0x2011,
+ 0x0028, 0xa582, 0x0028, 0x0d48, 0x8420, 0x2019, 0x0019, 0x2011,
+ 0x0033, 0x2200, 0xa502, 0x0e00, 0x8420, 0x2300, 0xa210, 0x1f04,
+ 0x3b41, 0x015e, 0x2011, 0x0184, 0xa582, 0x0185, 0x0ab0, 0x0890,
+ 0x2021, 0x3b75, 0x20a9, 0x0003, 0x2011, 0x0024, 0xa586, 0x0024,
+ 0x0960, 0x8420, 0x2011, 0x0028, 0xa586, 0x0028, 0x0930, 0x8420,
+ 0x2019, 0x0019, 0x2011, 0x0033, 0x0804, 0x3b19, 0x1021, 0x2202,
+ 0x3403, 0x4604, 0x5805, 0x6a06, 0x7c07, 0x4610, 0x4612, 0x5812,
+ 0x5a12, 0x6a14, 0x6c14, 0x6e14, 0x7e17, 0x9021, 0xb002, 0xe204,
+ 0xe210, 0xe210, 0x1209, 0x3002, 0x3202, 0x4203, 0x4403, 0x5404,
+ 0x5604, 0x6605, 0x6805, 0x7806, 0x7a06, 0x0c07, 0x0c07, 0x0e07,
+ 0x10e1, 0x330a, 0x5805, 0x5a05, 0x6a06, 0x6c06, 0x7c07, 0x7e07,
+ 0x0e00, 0x789b, 0x0080, 0xa046, 0x0005, 0xa784, 0x0f00, 0x800b,
+ 0xa784, 0x001f, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xd7fc,
+ 0x0118, 0xa0e0, 0x6cc0, 0x0010, 0xa0e0, 0x4cc0, 0x0005, 0x00e6,
+ 0x00f6, 0xd084, 0x0138, 0x2079, 0x0100, 0x2009, 0x4780, 0x2071,
+ 0x4780, 0x0030, 0x2009, 0x4740, 0x2079, 0x0200, 0x2071, 0x4740,
+ 0x2091, 0x8000, 0x2104, 0xa084, 0x000f, 0x0002, 0x3bc8, 0x3bc8,
+ 0x3bc8, 0x3bc8, 0x3bc8, 0x3bc8, 0x3bc6, 0x3bc6, 0x080c, 0x2575,
+ 0x69b4, 0xc1f5, 0xa18c, 0xff9f, 0x69b6, 0xa005, 0x0580, 0x7858,
+ 0xa084, 0xff9f, 0xa085, 0x6000, 0x785a, 0x7828, 0xa086, 0x1814,
+ 0x1530, 0x784b, 0x0004, 0x7848, 0xa084, 0x0004, 0x1de0, 0x784b,
+ 0x0008, 0x7848, 0xa084, 0x0008, 0x1de0, 0x7830, 0xd0bc, 0x11b8,
+ 0xb284, 0x0800, 0x0118, 0x0104, 0x3bff, 0x0010, 0x0304, 0x3bff,
+ 0x79e4, 0xa184, 0x0030, 0x0158, 0x78ec, 0xa084, 0x0003, 0x0138,
+ 0x681c, 0xd0ac, 0x1110, 0x00d9, 0x0010, 0x781b, 0x00fb, 0x00fe,
+ 0x00ee, 0x0005, 0x2001, 0x4701, 0x2004, 0xd0ac, 0x1118, 0x6814,
+ 0x080c, 0x249e, 0x0005, 0x781b, 0x0083, 0x0005, 0x781b, 0x0082,
+ 0x0005, 0x781b, 0x0071, 0x0005, 0x781b, 0x006e, 0x0005, 0x2009,
+ 0x4719, 0x210c, 0xa186, 0x0000, 0x0150, 0xa186, 0x0001, 0x0150,
+ 0x701f, 0x000b, 0x7063, 0x0001, 0x781b, 0x0054, 0x0005, 0x781b,
+ 0x00f3, 0x0005, 0x701f, 0x000a, 0x0005, 0x2009, 0x4719, 0x210c,
+ 0xa186, 0x0000, 0x0168, 0xa186, 0x0001, 0x0138, 0x701f, 0x000b,
+ 0x7063, 0x0001, 0x781b, 0x0054, 0x0005, 0x701f, 0x000a, 0x0005,
+ 0x781b, 0x00f2, 0x0005, 0x781b, 0x00fb, 0x0005, 0x781b, 0x00fa,
+ 0x0005, 0x781b, 0x00cc, 0x0005, 0x781b, 0x00cb, 0x0005, 0x6818,
+ 0xd0fc, 0x0110, 0x681b, 0x001d, 0x701f, 0x000b, 0x7063, 0x0001,
0x781b, 0x0054, 0x0005, 0x7830, 0xa084, 0x00c0, 0x1170, 0x7808,
0xc08c, 0x780a, 0xe000, 0xe000, 0xe000, 0xe000, 0x78ec, 0xa084,
0x0021, 0x0118, 0x7808, 0xc08d, 0x780a, 0x0005, 0x7808, 0xc08d,
0x780a, 0x0005, 0x7830, 0xa084, 0x0040, 0x1de0, 0xb284, 0x0800,
- 0x0118, 0x1104, 0x3c58, 0x0010, 0x1304, 0x3c58, 0x78ac, 0x0005,
+ 0x0118, 0x1104, 0x3c80, 0x0010, 0x1304, 0x3c80, 0x78ac, 0x0005,
0x7808, 0xa084, 0xfffd, 0x780a, 0xe000, 0xe000, 0xe000, 0xe000,
0x78ec, 0xa084, 0x0021, 0x0140, 0xb284, 0x0800, 0x0118, 0x1104,
- 0x3c67, 0x0010, 0x1304, 0x3c6a, 0x78ac, 0x0006, 0x7808, 0xa085,
- 0x0002, 0x780a, 0x000e, 0x0005, 0xa784, 0x0001, 0x1904, 0x322a,
- 0xa784, 0x0070, 0x0140, 0x00c6, 0x2d60, 0x2f68, 0x080c, 0x2467,
+ 0x3c8f, 0x0010, 0x1304, 0x3c92, 0x78ac, 0x0006, 0x7808, 0xa085,
+ 0x0002, 0x780a, 0x000e, 0x0005, 0xa784, 0x0001, 0x1904, 0x324d,
+ 0xa784, 0x0070, 0x0140, 0x00c6, 0x2d60, 0x2f68, 0x080c, 0x2490,
0x2d78, 0x2c68, 0x00ce, 0xa784, 0x0008, 0x0148, 0x784b, 0x0008,
- 0x78ec, 0xa084, 0x0003, 0x0904, 0x322a, 0x0804, 0x3be5, 0xa784,
+ 0x78ec, 0xa084, 0x0003, 0x0904, 0x324d, 0x0804, 0x3c0b, 0xa784,
0x0004, 0x01c8, 0x78b8, 0xa084, 0x8000, 0x01a8, 0x784b, 0x0008,
- 0x78ec, 0xa084, 0x0003, 0x0904, 0x322a, 0x78e4, 0xa084, 0x0007,
+ 0x78ec, 0xa084, 0x0003, 0x0904, 0x324d, 0x78e4, 0xa084, 0x0007,
0xa086, 0x0001, 0x1140, 0x78c0, 0xa685, 0x4800, 0x2030, 0x7e5a,
0x781b, 0x00fb, 0x0005, 0xa784, 0x0080, 0x0140, 0x7884, 0xd0fc,
- 0x0128, 0x080c, 0x3a32, 0x681b, 0x0022, 0x0005, 0x681b, 0x0003,
+ 0x0128, 0x080c, 0x3a57, 0x681b, 0x0022, 0x0005, 0x681b, 0x0003,
0x7858, 0xa084, 0x5f00, 0x681e, 0x682f, 0x0000, 0x6833, 0x0000,
- 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0904, 0x2b89, 0xb284,
- 0x0800, 0x0110, 0x0104, 0x259d, 0x0304, 0x259d, 0x6b14, 0x8307,
+ 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0904, 0x2bac, 0xb284,
+ 0x0800, 0x0110, 0x0104, 0x25c6, 0x0304, 0x25c6, 0x6b14, 0x8307,
0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xd3fc, 0x0118, 0xa080,
- 0x4b40, 0x0010, 0xa080, 0x4ac0, 0x2060, 0x2048, 0x7056, 0x2a60,
- 0x0005, 0x00c6, 0x2960, 0x6000, 0xd0ac, 0x0904, 0x3d2f, 0x68a0,
- 0xd1ac, 0x1120, 0xa084, 0x0e00, 0x0904, 0x3d2d, 0x6108, 0x8117,
+ 0x4c40, 0x0010, 0xa080, 0x4bc0, 0x2060, 0x2048, 0x7056, 0x2a60,
+ 0x0005, 0x00c6, 0x2960, 0x6000, 0xd0ac, 0x0904, 0x3d57, 0x68a0,
+ 0xd1ac, 0x1120, 0xa084, 0x0e00, 0x0904, 0x3d55, 0x6108, 0x8117,
0xa18c, 0x00ff, 0x631c, 0x832f, 0xd0dc, 0x0110, 0xa39d, 0x0001,
0xd0cc, 0x11c8, 0xa584, 0x00ff, 0x0138, 0x78ec, 0xd0e4, 0x0110,
0x8213, 0x00b8, 0x2029, 0x0000, 0xa182, 0x000c, 0x1290, 0x78ec,
@@ -1493,23 +1498,23 @@ static unsigned short risc_code01[] = {
0x2009, 0x000a, 0x0030, 0x2009, 0x0032, 0x2011, 0x0000, 0x2029,
0x0000, 0x78ab, 0x0001, 0x78ab, 0x0006, 0x78ab, 0x0004, 0x79aa,
0x78ab, 0x0000, 0x7aaa, 0x7baa, 0x7daa, 0xa8c0, 0x0008, 0x6820,
- 0xa085, 0x1000, 0x6822, 0x080c, 0x3a55, 0xa085, 0x0001, 0x00ce,
- 0x0005, 0xa282, 0x0006, 0x1904, 0x3a24, 0x7da8, 0x7eac, 0x8637,
+ 0xa085, 0x1000, 0x6822, 0x080c, 0x3a7a, 0xa085, 0x0001, 0x00ce,
+ 0x0005, 0xa282, 0x0006, 0x1904, 0x3a49, 0x7da8, 0x7eac, 0x8637,
0xa5ac, 0x00ff, 0xa6b4, 0x00ff, 0x7fac, 0x8747, 0xa7bc, 0x00ff,
- 0xa8c4, 0x00ff, 0x6920, 0xc1bd, 0x6922, 0xd1e4, 0x0904, 0x3da3,
- 0xa18c, 0xecff, 0x6922, 0xa782, 0x0002, 0x1a04, 0x39fe, 0xa6b4,
- 0x00ff, 0x0904, 0x3da0, 0xa682, 0x0031, 0x1a04, 0x39fe, 0xa582,
- 0x0009, 0x0a04, 0x39fe, 0xa882, 0x0003, 0x1a04, 0x39fe, 0xa886,
- 0x0002, 0x01d0, 0xa886, 0x0000, 0x1904, 0x39fe, 0x2001, 0x000c,
+ 0xa8c4, 0x00ff, 0x6920, 0xc1bd, 0x6922, 0xd1e4, 0x0904, 0x3dcb,
+ 0xa18c, 0xecff, 0x6922, 0xa782, 0x0002, 0x1a04, 0x3a23, 0xa6b4,
+ 0x00ff, 0x0904, 0x3dc8, 0xa682, 0x0031, 0x1a04, 0x3a23, 0xa582,
+ 0x0009, 0x0a04, 0x3a23, 0xa882, 0x0003, 0x1a04, 0x3a23, 0xa886,
+ 0x0002, 0x01d0, 0xa886, 0x0000, 0x1904, 0x3a23, 0x2001, 0x000c,
0x79ec, 0xd1e4, 0x0110, 0x2001, 0x000a, 0xa502, 0x1290, 0x080c,
- 0x39fe, 0x00c6, 0x2960, 0x6004, 0xa085, 0x001a, 0x6006, 0x6000,
- 0xc0ac, 0x6002, 0x00ce, 0x0005, 0xa786, 0x0000, 0x0904, 0x39fe,
+ 0x3a23, 0x00c6, 0x2960, 0x6004, 0xa085, 0x001a, 0x6006, 0x6000,
+ 0xc0ac, 0x6002, 0x00ce, 0x0005, 0xa786, 0x0000, 0x0904, 0x3a23,
0x8634, 0xa682, 0x0018, 0x0228, 0x0120, 0x2031, 0x0018, 0x0804,
- 0x3df1, 0xa686, 0x0010, 0x1108, 0x8630, 0x852b, 0x852b, 0x080c,
- 0x3ac9, 0x0904, 0x39fe, 0x080c, 0x38f7, 0x080c, 0x399c, 0x7e58,
+ 0x3e19, 0xa686, 0x0010, 0x1108, 0x8630, 0x852b, 0x852b, 0x080c,
+ 0x3aee, 0x0904, 0x3a23, 0x080c, 0x391a, 0x080c, 0x39bf, 0x7e58,
0xd6d4, 0x1118, 0x781b, 0x0071, 0x0005, 0x781b, 0x0083, 0x0005,
- 0x080c, 0x38f4, 0x0c90, 0xa886, 0x0002, 0x1108, 0x8634, 0x7154,
- 0xa188, 0x0000, 0x210c, 0xd1ac, 0x0904, 0x39fe, 0xd1ec, 0x1120,
+ 0x080c, 0x3917, 0x0c90, 0xa886, 0x0002, 0x1108, 0x8634, 0x7154,
+ 0xa188, 0x0000, 0x210c, 0xd1ac, 0x0904, 0x3a23, 0xd1ec, 0x1120,
0x2039, 0x0000, 0x2041, 0x0000, 0xd1e4, 0x1120, 0x2031, 0x0000,
0x2041, 0x0000, 0xa782, 0x0002, 0x12c8, 0x621c, 0xa284, 0x00ff,
0xa706, 0x0110, 0x2039, 0x0000, 0xa605, 0x0190, 0x6108, 0x811f,
@@ -1517,11 +1522,11 @@ static unsigned short risc_code01[] = {
0xa086, 0x0201, 0x0160, 0xa886, 0x0000, 0x0168, 0x2039, 0x0000,
0x2041, 0x0000, 0x2031, 0x0000, 0xa006, 0x2010, 0x0070, 0xa284,
0xff00, 0x1108, 0x2040, 0xa184, 0x00ff, 0xa502, 0x0108, 0x2128,
- 0x852b, 0x852b, 0x080c, 0x3ac9, 0x0d58, 0x080c, 0x38f7, 0x080c,
- 0x399c, 0x789b, 0x0080, 0x78ab, 0x0001, 0x78ab, 0x0006, 0x78ab,
+ 0x852b, 0x852b, 0x080c, 0x3aee, 0x0d58, 0x080c, 0x391a, 0x080c,
+ 0x39bf, 0x789b, 0x0080, 0x78ab, 0x0001, 0x78ab, 0x0006, 0x78ab,
0x0004, 0x7daa, 0x78ab, 0x0000, 0x7eaa, 0x7faa, 0x2800, 0x78aa,
0x789b, 0x0060, 0x78ab, 0x0008, 0x6820, 0xc0e5, 0x6822, 0x080c,
- 0x3a55, 0x7858, 0xc095, 0x785a, 0x781b, 0x0082, 0x0005, 0x0020,
+ 0x3a7a, 0x7858, 0xc095, 0x785a, 0x781b, 0x0082, 0x0005, 0x0020,
0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
@@ -1559,223 +1564,248 @@ static unsigned short risc_code01[] = {
0x20dd, 0x0011, 0x20d5, 0x8822, 0x0016, 0x0000, 0x0126, 0x70d0,
0xa084, 0x4c00, 0x8004, 0x2090, 0x7204, 0x7008, 0xc09c, 0xa205,
0x11a0, 0x720c, 0x82ff, 0x0128, 0x8aff, 0x1178, 0x7200, 0xd284,
- 0x1160, 0x7804, 0xd0cc, 0x0110, 0x080c, 0x4328, 0x7007, 0x0008,
+ 0x1160, 0x7804, 0xd0cc, 0x0110, 0x080c, 0x435b, 0x7007, 0x0008,
0x7003, 0x0008, 0x012e, 0x2000, 0x0005, 0x7000, 0xa084, 0x0003,
0x7002, 0xc69c, 0xd084, 0x0588, 0x7108, 0xe000, 0x7008, 0xa106,
- 0x1dd8, 0xa184, 0x0003, 0x0904, 0x3fa2, 0xa184, 0x01e0, 0x1904,
- 0x3fa2, 0xd1f4, 0x1d88, 0xa184, 0x3000, 0xa086, 0x1000, 0x0d60,
+ 0x1dd8, 0xa184, 0x0003, 0x0904, 0x3fca, 0xa184, 0x01e0, 0x1904,
+ 0x3fca, 0xd1f4, 0x1d88, 0xa184, 0x3000, 0xa086, 0x1000, 0x0d60,
0x2011, 0x0180, 0x710c, 0x8211, 0x0130, 0x7008, 0xd0f4, 0x1d20,
0x700c, 0xa106, 0x0dc0, 0x7007, 0x0012, 0x7108, 0xe000, 0x7008,
0xa106, 0x1dd8, 0xa184, 0x0003, 0x0568, 0xd194, 0x0db0, 0xd1f4,
0x0548, 0x7007, 0x0002, 0x0880, 0x0428, 0x7108, 0xd1fc, 0x0130,
- 0x080c, 0x40ae, 0x8aff, 0x0904, 0x3f2c, 0x0cb8, 0x700c, 0xa08c,
+ 0x080c, 0x40d6, 0x8aff, 0x0904, 0x3f54, 0x0cb8, 0x700c, 0xa08c,
0x07ff, 0x01e8, 0x7004, 0xd084, 0x0178, 0x7014, 0xa005, 0x1148,
0x7010, 0x7310, 0xa306, 0x1de0, 0x2300, 0xa005, 0x0128, 0xa102,
- 0x1e20, 0x7007, 0x0010, 0x0030, 0x8aff, 0x0148, 0x080c, 0x426b,
- 0x1de8, 0x09d8, 0x080c, 0x4034, 0x012e, 0x2000, 0x0005, 0x7204,
+ 0x1e20, 0x7007, 0x0010, 0x0030, 0x8aff, 0x0148, 0x080c, 0x429a,
+ 0x1de8, 0x09d8, 0x080c, 0x405c, 0x012e, 0x2000, 0x0005, 0x7204,
0x7108, 0xc19c, 0x8103, 0x1218, 0x7007, 0x0002, 0x0cc0, 0xa205,
- 0x1d88, 0x7007, 0x0008, 0x7003, 0x0008, 0x0006, 0x2001, 0x4601,
- 0x2004, 0xd0cc, 0x0110, 0x080c, 0x4328, 0x000e, 0x012e, 0x2000,
+ 0x1d88, 0x7007, 0x0008, 0x7003, 0x0008, 0x0006, 0x2001, 0x4701,
+ 0x2004, 0xd0cc, 0x0110, 0x080c, 0x435b, 0x000e, 0x012e, 0x2000,
0x0005, 0x6428, 0x84ff, 0x0508, 0x2c70, 0x7004, 0xa0bc, 0x000f,
- 0xa7b8, 0x3ff5, 0x273c, 0x87fb, 0x1148, 0x0210, 0x080c, 0x254c,
- 0x609c, 0xa075, 0x0190, 0x0c88, 0x2039, 0x3fea, 0x2704, 0xae68,
+ 0xa7b8, 0x401d, 0x273c, 0x87fb, 0x1148, 0x0210, 0x080c, 0x2575,
+ 0x609c, 0xa075, 0x0190, 0x0c88, 0x2039, 0x4012, 0x2704, 0xae68,
0x6808, 0xa630, 0x680c, 0xa529, 0x8421, 0x0138, 0x8738, 0x2704,
0xa005, 0x1da8, 0x709c, 0xa075, 0x1d00, 0x0005, 0x0000, 0x0005,
0x0009, 0x000d, 0x0011, 0x0015, 0x0019, 0x001d, 0x0000, 0x0003,
- 0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0000, 0x3fea, 0x3fe7,
- 0x0000, 0x0000, 0x8000, 0x0000, 0x3fea, 0x0000, 0x3ff2, 0x3fef,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x3ff2, 0x0000, 0x3fed, 0x3fed,
- 0x0000, 0x0000, 0x8000, 0x0000, 0x3fed, 0x0000, 0x3ff3, 0x3ff3,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x3ff3, 0x2079, 0x4600, 0x2071,
+ 0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0000, 0x4012, 0x400f,
+ 0x0000, 0x0000, 0x8000, 0x0000, 0x4012, 0x0000, 0x401a, 0x4017,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x401a, 0x0000, 0x4015, 0x4015,
+ 0x0000, 0x0000, 0x8000, 0x0000, 0x4015, 0x0000, 0x401b, 0x401b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x401b, 0x2079, 0x4700, 0x2071,
0x0010, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, 0x0001, 0x2009,
0x0002, 0x2071, 0x0050, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003,
0x0000, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1128, 0x8109, 0x0118,
- 0x2071, 0x0020, 0x0c80, 0x0005, 0x7004, 0x8004, 0x1a04, 0x408a,
+ 0x2071, 0x0020, 0x0c80, 0x0005, 0x7004, 0x8004, 0x1a04, 0x40b2,
0x7108, 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0, 0x0120, 0x080c,
- 0x40e6, 0x0804, 0x40aa, 0x7007, 0x0012, 0x2019, 0x0000, 0x7108,
- 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0, 0x0120, 0x080c, 0x40e6,
- 0x0804, 0x40aa, 0xa19c, 0x300c, 0xa386, 0x2004, 0x0190, 0xa386,
+ 0x410e, 0x0804, 0x40d2, 0x7007, 0x0012, 0x2019, 0x0000, 0x7108,
+ 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0, 0x0120, 0x080c, 0x410e,
+ 0x0804, 0x40d2, 0xa19c, 0x300c, 0xa386, 0x2004, 0x0190, 0xa386,
0x0008, 0x01c0, 0x7004, 0xd084, 0x1148, 0x7108, 0x7008, 0xa106,
- 0x1de0, 0xa184, 0x0003, 0x0110, 0x0804, 0x40e6, 0xa386, 0x200c,
+ 0x1de0, 0xa184, 0x0003, 0x0110, 0x0804, 0x410e, 0xa386, 0x200c,
0x19f0, 0x7200, 0x8204, 0x0230, 0x730c, 0xa384, 0x07ff, 0x0110,
- 0x080c, 0x254c, 0x7108, 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0,
- 0x0118, 0x080c, 0x40e6, 0x0470, 0x7007, 0x0012, 0x7000, 0xd084,
+ 0x080c, 0x2575, 0x7108, 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0,
+ 0x0118, 0x080c, 0x410e, 0x0470, 0x7007, 0x0012, 0x7000, 0xd084,
0x1148, 0x7310, 0x7014, 0xa305, 0x0128, 0x710c, 0xa184, 0x07ff,
- 0x1904, 0x4034, 0x7108, 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0,
- 0x0118, 0x080c, 0x40e6, 0x00b0, 0x7007, 0x0012, 0x7007, 0x0008,
+ 0x1904, 0x405c, 0x7108, 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0,
+ 0x0118, 0x080c, 0x410e, 0x00b0, 0x7007, 0x0012, 0x7007, 0x0008,
0x7004, 0xd09c, 0x1de8, 0x7108, 0x7008, 0xa106, 0x1de0, 0xa184,
- 0x01e0, 0x0118, 0x080c, 0x40e6, 0x0028, 0x7007, 0x0012, 0x7108,
+ 0x01e0, 0x0118, 0x080c, 0x410e, 0x0028, 0x7007, 0x0012, 0x7108,
0x8103, 0x0e88, 0x7003, 0x0008, 0x0005, 0x7108, 0xa184, 0x01e0,
0x15a8, 0x7108, 0xa184, 0x01e0, 0x1588, 0xa184, 0x0007, 0x0002,
- 0x40c2, 0x40d0, 0x40c0, 0x40d0, 0x40c0, 0x4120, 0x40c0, 0x411e,
- 0x080c, 0x254c, 0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x8aff,
- 0x1118, 0x2049, 0x0000, 0x0005, 0x080c, 0x426b, 0x1de8, 0x0005,
+ 0x40ea, 0x40f8, 0x40e8, 0x40f8, 0x40e8, 0x4148, 0x40e8, 0x4146,
+ 0x080c, 0x2575, 0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x8aff,
+ 0x1118, 0x2049, 0x0000, 0x0005, 0x080c, 0x429a, 0x1de8, 0x0005,
0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x7004, 0xd084, 0x1140,
0x7108, 0x7008, 0xa106, 0x1de0, 0xa184, 0x0003, 0x0108, 0x0030,
- 0x8aff, 0x0118, 0x080c, 0x426b, 0x1de8, 0x0005, 0x7007, 0x0012,
- 0x7108, 0x1d04, 0x40e9, 0x2091, 0x6000, 0x1d04, 0x40ed, 0x2091,
+ 0x8aff, 0x0118, 0x080c, 0x429a, 0x1de8, 0x0005, 0x7007, 0x0012,
+ 0x7108, 0x1d04, 0x4111, 0x2091, 0x6000, 0x1d04, 0x4115, 0x2091,
0x6000, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004, 0xd09c, 0x1de8,
0x7007, 0x0012, 0x7108, 0xd1fc, 0x1dd8, 0x7003, 0x0000, 0x7000,
0xa005, 0x1130, 0x7004, 0xa005, 0x1118, 0x700c, 0xa005, 0x0108,
0x0c40, 0x2049, 0x0000, 0xb284, 0x0200, 0x0118, 0x2001, 0x0000,
- 0x0010, 0x2001, 0x0001, 0x080c, 0x3b81, 0x681b, 0x0002, 0x2051,
- 0x0000, 0x0005, 0x080c, 0x254c, 0x080c, 0x254c, 0x080c, 0x415f,
+ 0x0010, 0x2001, 0x0001, 0x080c, 0x3ba7, 0x681b, 0x0002, 0x2051,
+ 0x0000, 0x0005, 0x080c, 0x2575, 0x080c, 0x2575, 0x080c, 0x4187,
0x7210, 0x7114, 0x700c, 0xa09c, 0x07ff, 0x2800, 0xa300, 0xa211,
0xa189, 0x0000, 0x04a1, 0x2704, 0x2c58, 0xac60, 0x6308, 0x2200,
0xa322, 0x630c, 0x2100, 0xa31b, 0x2400, 0xa305, 0x0140, 0x1238,
0x8412, 0x8210, 0x830a, 0xa189, 0x0000, 0x2b60, 0x0c58, 0x2b60,
- 0x8a07, 0x0006, 0x6004, 0xd09c, 0x0118, 0xa7ba, 0x3fef, 0x0010,
- 0xa7ba, 0x3fe7, 0x000e, 0xa73d, 0x2c00, 0x6886, 0x6f8a, 0x6c92,
+ 0x8a07, 0x0006, 0x6004, 0xd09c, 0x0118, 0xa7ba, 0x4017, 0x0010,
+ 0xa7ba, 0x400f, 0x000e, 0xa73d, 0x2c00, 0x6886, 0x6f8a, 0x6c92,
0x6b8e, 0x7108, 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0, 0x0110,
- 0x080c, 0x40e6, 0x7007, 0x0012, 0x080c, 0x4034, 0x0005, 0x8a50,
+ 0x080c, 0x410e, 0x7007, 0x0012, 0x080c, 0x405c, 0x0005, 0x8a50,
0x8739, 0x2704, 0xa004, 0x1168, 0x6000, 0xa064, 0x1108, 0x2d60,
- 0x6004, 0xa084, 0x000f, 0xa080, 0x4005, 0x203c, 0x87fb, 0x090c,
- 0x254c, 0x0005, 0x0126, 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004,
+ 0x6004, 0xa084, 0x000f, 0xa080, 0x402d, 0x203c, 0x87fb, 0x090c,
+ 0x2575, 0x0005, 0x0126, 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004,
0x2090, 0x00de, 0x6884, 0x2060, 0x6888, 0x6b8c, 0x6c90, 0x8057,
0xaad4, 0x00ff, 0xa084, 0x00ff, 0x0006, 0x6804, 0xa084, 0x0008,
- 0x000e, 0x0118, 0xa0b8, 0x3fef, 0x0010, 0xa0b8, 0x3fe7, 0xb284,
+ 0x000e, 0x0118, 0xa0b8, 0x4017, 0x0010, 0xa0b8, 0x400f, 0xb284,
0x0200, 0x0110, 0x7e20, 0x0008, 0x7e24, 0xa6b5, 0x000c, 0x681c,
- 0xd0b4, 0x0108, 0xc685, 0x2400, 0xa305, 0x0518, 0x2c58, 0x2704,
- 0x6104, 0xac60, 0x6000, 0xa400, 0x701a, 0x6004, 0xa301, 0x701e,
- 0xd19c, 0x0140, 0x6010, 0xa081, 0x0000, 0x7022, 0x6014, 0xa081,
- 0x0000, 0x7026, 0x6208, 0x2400, 0xa202, 0x7012, 0x620c, 0x2300,
- 0xa203, 0x7016, 0x7602, 0x7007, 0x0001, 0x2b60, 0x080c, 0x4292,
- 0x0010, 0x080c, 0x426b, 0x1de8, 0x012e, 0x2000, 0x0005, 0x0126,
- 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de, 0x7007,
- 0x0004, 0x7004, 0xd094, 0x1de8, 0x7003, 0x0008, 0x012e, 0x2000,
- 0x0005, 0x0126, 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090,
- 0x00de, 0x7e20, 0xb284, 0x0200, 0x1108, 0x7e24, 0xa6b5, 0x000c,
- 0x681c, 0xd0ac, 0x1118, 0xc685, 0x7003, 0x0000, 0x6828, 0x2050,
- 0x2d60, 0x6004, 0xa0bc, 0x000f, 0xa7b8, 0x3ff5, 0x273c, 0x87fb,
- 0x1138, 0x0210, 0x080c, 0x254c, 0x689c, 0xa065, 0x0120, 0x0c88,
- 0x080c, 0x426b, 0x1de8, 0x012e, 0x2000, 0x0005, 0x0126, 0x0006,
- 0x0016, 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x7e20,
- 0xb284, 0x0200, 0x1108, 0x7e24, 0x00de, 0x003e, 0x004e, 0xa6b5,
- 0x000c, 0x681c, 0xd0b4, 0x0128, 0xc685, 0x7003, 0x0000, 0x7007,
- 0x0004, 0x2049, 0x4206, 0x6828, 0xa055, 0x00d6, 0x0904, 0x4267,
- 0x2d70, 0x2e60, 0x7004, 0xa0bc, 0x000f, 0xa7b8, 0x3ff5, 0x273c,
- 0x87fb, 0x1140, 0x0210, 0x080c, 0x254c, 0x709c, 0xa075, 0x2060,
- 0x0570, 0x0c80, 0x2704, 0xae68, 0x6808, 0xa422, 0x680c, 0xa31b,
- 0x0268, 0x8a51, 0x1110, 0x080c, 0x254c, 0x8738, 0x2704, 0xa005,
- 0x1d90, 0x709c, 0xa075, 0x2060, 0x01d0, 0x08e0, 0x8422, 0x8420,
- 0x831a, 0xa399, 0x0000, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300,
- 0xa11b, 0x1210, 0x080c, 0x254c, 0xb284, 0x0200, 0x0118, 0x2071,
- 0x0050, 0x0010, 0x2071, 0x0020, 0x00de, 0x0804, 0x419b, 0x00de,
- 0x012e, 0x2000, 0x0005, 0x7008, 0x0006, 0xa084, 0x01e0, 0x000e,
- 0x0110, 0xa006, 0x0005, 0xa084, 0x0003, 0xa086, 0x0003, 0x1108,
- 0x0005, 0x2704, 0xac78, 0x7800, 0x701a, 0x7804, 0x701e, 0x7808,
- 0x7012, 0x780c, 0x7016, 0x6004, 0xd09c, 0x0120, 0x7810, 0x7022,
- 0x7814, 0x7026, 0x7602, 0x7004, 0xa084, 0x0010, 0xc085, 0x7006,
- 0x2079, 0x4600, 0x8a51, 0x01e8, 0x8738, 0x2704, 0xa005, 0x1168,
- 0x609c, 0xa005, 0x01b8, 0x2060, 0x6004, 0xa084, 0x000f, 0xa080,
- 0x3ff5, 0x203c, 0x87fb, 0x090c, 0x254c, 0x7008, 0x0006, 0xa084,
- 0x01e0, 0x000e, 0x0110, 0xa006, 0x0028, 0xa084, 0x0003, 0xa086,
- 0x0003, 0x0005, 0x2051, 0x0000, 0x0005, 0x0126, 0x0006, 0x00d6,
- 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de, 0x008e, 0x7108,
- 0xa184, 0x0003, 0x1128, 0x6828, 0xa005, 0x0178, 0x0804, 0x3f45,
- 0x7108, 0xd1fc, 0x0118, 0x080c, 0x40ae, 0x0c88, 0x7007, 0x0010,
- 0x7108, 0xd1fc, 0x0de8, 0x080c, 0x40ae, 0x7008, 0xa086, 0x0008,
- 0x1d30, 0x7000, 0xa005, 0x1d18, 0x7003, 0x0000, 0x2049, 0x0000,
- 0x0006, 0x2001, 0x4601, 0x2004, 0xd0cc, 0x0110, 0x080c, 0x4328,
- 0x000e, 0x012e, 0x2000, 0x0005, 0x0126, 0x0146, 0x0136, 0x0156,
- 0x00c6, 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de,
- 0x2049, 0x42ec, 0xad80, 0x0011, 0x20a0, 0xb284, 0x0200, 0x0118,
- 0x2099, 0x0032, 0x0010, 0x2099, 0x0031, 0x700c, 0xa084, 0x07ff,
- 0x682a, 0x7007, 0x0008, 0x7007, 0x0002, 0x7003, 0x0001, 0x0118,
- 0x8000, 0x80ac, 0x53a5, 0x700c, 0xa084, 0x07ff, 0x0130, 0x7007,
- 0x0004, 0x7004, 0xa084, 0x0004, 0x1de0, 0x00ce, 0x2049, 0x0000,
- 0x7003, 0x0000, 0x015e, 0x013e, 0x014e, 0x012e, 0x2000, 0x0005,
- 0x6814, 0xd0fc, 0x0904, 0x436b, 0x7000, 0xd084, 0x05e0, 0x7e24,
- 0xa6b5, 0x0004, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x1de0,
- 0x7118, 0x0016, 0x711c, 0x0016, 0x7120, 0x0016, 0x7124, 0x0016,
- 0x701b, 0x0000, 0x701f, 0x3fff, 0x7023, 0x0000, 0x7027, 0x0000,
- 0x7013, 0x0004, 0x7017, 0x0000, 0x7602, 0x7007, 0x0001, 0x2001,
- 0xffff, 0x2009, 0x0031, 0x200a, 0x200a, 0x7108, 0x7008, 0xa106,
- 0x1de0, 0xd1fc, 0x0dd0, 0x002e, 0x7226, 0x002e, 0x7222, 0x002e,
- 0x721e, 0x002e, 0x721a, 0x7007, 0x0002, 0x7008, 0xa086, 0x0008,
- 0x0110, 0x0804, 0x40e6, 0x7007, 0x0004, 0x7003, 0x0000, 0x0005,
- 0x2091, 0x8000, 0x2091, 0x6000, 0x78ac, 0xa005, 0x1168, 0x7974,
- 0x70d0, 0xa106, 0x1148, 0x781c, 0xa005, 0x0130, 0x781f, 0x0000,
- 0x0e04, 0x4384, 0x2091, 0x4080, 0x2069, 0x4680, 0xd7fc, 0x1110,
- 0x2069, 0x4640, 0x6800, 0xa084, 0x000f, 0x1198, 0x68d0, 0xd0b4,
- 0x0180, 0xd0bc, 0x1170, 0x00f6, 0x2079, 0x0100, 0xd7fc, 0x1110,
- 0x2079, 0x0200, 0x7830, 0xa084, 0x00c0, 0x1110, 0x080c, 0x22ae,
- 0x00fe, 0x7830, 0x8001, 0x7832, 0x1904, 0x440b, 0x7834, 0x7832,
- 0x2061, 0x6bc0, 0x2069, 0x4680, 0xc7fd, 0x68cc, 0xa005, 0x0128,
- 0x8001, 0x68ce, 0x1110, 0x080c, 0x4577, 0x6800, 0xa084, 0x000f,
- 0x0168, 0xa086, 0x0001, 0x0150, 0x6840, 0xa00d, 0x0138, 0x2104,
- 0xa005, 0x0120, 0x8001, 0x200a, 0x0904, 0x4514, 0x6814, 0xa005,
- 0x01a8, 0x8001, 0x6816, 0x1190, 0x68a3, 0x0001, 0x00f6, 0xd7fc,
- 0x1118, 0x2079, 0x0200, 0x0010, 0x2079, 0x0100, 0x080c, 0x3c46,
- 0x00fe, 0x6860, 0xa005, 0x0110, 0x080c, 0x22ae, 0x687c, 0xa005,
- 0x0140, 0x8001, 0x687e, 0x1128, 0x6863, 0x0000, 0x68d0, 0xc0c5,
- 0x68d2, 0x68d0, 0xd0fc, 0x01b0, 0xc0fc, 0x68d2, 0x20a9, 0x0200,
- 0x6034, 0xa005, 0x0158, 0x8001, 0x6036, 0x68d0, 0xc0fd, 0x68d2,
- 0x1128, 0x6010, 0xa005, 0x0110, 0x080c, 0x22ae, 0xace0, 0x0010,
- 0x1f04, 0x43f0, 0xd7fc, 0x0138, 0x2061, 0x4bc0, 0x2069, 0x4640,
- 0xc7fc, 0x0804, 0x43ad, 0x0459, 0x7838, 0x8001, 0x783a, 0x11a0,
- 0x783c, 0x783a, 0x2061, 0x4bc0, 0x2069, 0x4640, 0xc7fc, 0x680c,
- 0xa005, 0x0110, 0x080c, 0x4487, 0xd7fc, 0x1130, 0x2061, 0x6bc0,
- 0x2069, 0x4680, 0xc7fd, 0x0c98, 0x7810, 0xd0cc, 0x0168, 0xd0ac,
- 0x1120, 0xd0a4, 0x0148, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x0e04,
- 0x4433, 0x080c, 0x207a, 0x0005, 0x2091, 0x8001, 0x0005, 0x7840,
- 0x8001, 0x7842, 0x1904, 0x4486, 0x7844, 0x7842, 0x2069, 0x4640,
- 0xc7fc, 0x2079, 0x0200, 0x68d4, 0xa005, 0x0138, 0x7de0, 0xa504,
- 0x1120, 0x68d6, 0x68d0, 0xc0bc, 0x68d2, 0x2079, 0x4600, 0x6810,
- 0xa005, 0x1110, 0x2001, 0x0101, 0x8001, 0x6812, 0xd7fc, 0x0118,
- 0xa080, 0x8cd0, 0x0010, 0xa080, 0x8bc0, 0x2040, 0x2004, 0xa065,
- 0x01e0, 0x6024, 0xa005, 0x01b0, 0x8001, 0x6026, 0x1198, 0x6800,
- 0xa005, 0x0130, 0x6848, 0xac06, 0x1118, 0x080c, 0x4514, 0x0068,
- 0x6860, 0xa005, 0x0118, 0x6027, 0x0001, 0x0020, 0x080c, 0x44c8,
- 0x2804, 0x0c28, 0x6000, 0x2c40, 0x0c10, 0xd7fc, 0x1138, 0x2069,
- 0x4680, 0xc7fd, 0x2079, 0x0100, 0x0804, 0x4443, 0x0005, 0x2009,
- 0x0000, 0x20a9, 0x0200, 0x6008, 0xd09c, 0x0558, 0x6024, 0xa005,
- 0x0118, 0x8001, 0x6026, 0x0418, 0x6008, 0xc09c, 0xd084, 0x1110,
- 0xd0ac, 0x01c0, 0x600a, 0x6004, 0xa005, 0x01d8, 0x00d6, 0x00c6,
- 0x0016, 0x2068, 0x6010, 0x8001, 0x6012, 0x080c, 0x37a4, 0x2d00,
- 0x2c68, 0x2060, 0x080c, 0x1be3, 0x080c, 0x1d95, 0x001e, 0x00ce,
- 0x00de, 0x0038, 0xc0bd, 0x600a, 0xa18d, 0x0001, 0x0010, 0xa18d,
- 0x0100, 0xace0, 0x0010, 0x1f04, 0x448b, 0xa184, 0x0001, 0x0130,
- 0xa18c, 0xfffe, 0x690e, 0x080c, 0x22ae, 0x0008, 0x690e, 0x0005,
- 0x2c00, 0x687a, 0x6714, 0x6f72, 0x6017, 0x0000, 0x602b, 0x0000,
- 0x601b, 0x0006, 0x60b4, 0xa084, 0x5f00, 0x601e, 0x6020, 0xa084,
- 0x00ff, 0xa085, 0x0060, 0x6022, 0x6000, 0x2042, 0x6858, 0xac06,
- 0x1110, 0x2800, 0x685a, 0x080c, 0x1b7b, 0x6818, 0xa005, 0x0110,
- 0x8001, 0x681a, 0x6808, 0xc0a4, 0x680a, 0x6810, 0x7908, 0x8109,
- 0x790a, 0x8001, 0x1310, 0x080c, 0x254c, 0x6812, 0x1118, 0x7910,
- 0xc1a5, 0x7912, 0x602f, 0x0000, 0x6033, 0x0000, 0x2c68, 0x080c,
- 0x1da2, 0xd7fc, 0x1118, 0x2069, 0x4640, 0x0010, 0x2069, 0x4680,
- 0x6910, 0xa184, 0x0100, 0x2001, 0x0006, 0x1118, 0x6976, 0x2001,
- 0x0004, 0x080c, 0x22a4, 0x0005, 0x00d6, 0x6948, 0x2160, 0xd7fc,
- 0x1118, 0x2069, 0x0200, 0x0010, 0x2069, 0x0100, 0x080c, 0x2467,
- 0x601b, 0x0006, 0x6858, 0xa084, 0x5f00, 0x601e, 0x6020, 0xa084,
- 0x00ff, 0xa085, 0x0048, 0x6022, 0x602f, 0x0000, 0x6033, 0x0000,
- 0x6808, 0xa084, 0xfffd, 0x680a, 0x6830, 0xd0b4, 0x01b0, 0x684b,
- 0x0004, 0x20a9, 0x0014, 0x6848, 0xd094, 0x0110, 0x1f04, 0x453b,
- 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xd084, 0x0110, 0x1f04,
- 0x4544, 0x20a9, 0x00fa, 0x1f04, 0x454b, 0x681b, 0x0054, 0x00de,
- 0x6863, 0x0007, 0x0005, 0x2079, 0x4600, 0x00e1, 0x0089, 0x00a9,
- 0x2009, 0x0002, 0x2069, 0x4680, 0x680f, 0x0000, 0x6813, 0x0000,
- 0x6817, 0x0000, 0x8109, 0x0118, 0x2069, 0x4640, 0x0ca8, 0x0005,
- 0x2019, 0x00a3, 0x7b3a, 0x7b3e, 0x0005, 0x2019, 0x0033, 0x7b42,
- 0x7b46, 0x0005, 0x2019, 0x32dd, 0x7b32, 0x7b36, 0x0005, 0x6a4c,
- 0xa285, 0x0000, 0x01f0, 0x6950, 0x6bbc, 0xa300, 0x00c6, 0x2164,
- 0x6304, 0x83ff, 0x1138, 0x8211, 0x0148, 0x8108, 0xa11a, 0x0eb8,
- 0x69bc, 0x0ca8, 0x68cf, 0x000a, 0x00ce, 0x0005, 0x694c, 0x6abc,
- 0x2264, 0x6008, 0xc0b5, 0x600a, 0x8210, 0x8109, 0x1dc8, 0x694e,
- 0x00ce, 0x0005, 0x1d04, 0x459a, 0x2091, 0x6000, 0x1d04, 0x459e,
- 0x2091, 0x6000, 0x70ec, 0xd0dc, 0x1118, 0xd0d4, 0x0190, 0x0098,
- 0xae8e, 0x0100, 0x0138, 0x7814, 0xc0f5, 0xc0c5, 0x7816, 0xd0d4,
- 0x1578, 0x0458, 0x7814, 0xc0fd, 0xc0c5, 0x7816, 0xd0d4, 0x1540,
- 0x0420, 0xd0e4, 0x0538, 0x1d04, 0x45bb, 0x2091, 0x6000, 0x2009,
- 0x000c, 0x1d04, 0x45c1, 0x2091, 0x6000, 0x8109, 0x1dd0, 0x70e4,
- 0xa084, 0x01ff, 0xa086, 0x01ff, 0x1110, 0x70ec, 0x08c8, 0xae8e,
- 0x0100, 0x0128, 0x7814, 0xc0f4, 0xd0fc, 0x1130, 0x0020, 0x7814,
- 0xc0fc, 0xd0f4, 0x1108, 0xc0c4, 0x7816, 0x7804, 0xd08c, 0x0110,
- 0x681f, 0x000c, 0x70a0, 0x70a2, 0x0005, 0x7c12
+ 0xd0b4, 0x0108, 0xc685, 0x2400, 0xa305, 0x0550, 0x2c58, 0x2704,
+ 0x6104, 0xac60, 0x6000, 0xa400, 0x2048, 0xa9cc, 0x0004, 0x0118,
+ 0x080c, 0x43a3, 0x0400, 0x701a, 0x6004, 0xa301, 0x701e, 0xd19c,
+ 0x0140, 0x6010, 0xa081, 0x0000, 0x7022, 0x6014, 0xa081, 0x0000,
+ 0x7026, 0x6208, 0x2400, 0xa202, 0x7012, 0x620c, 0x2300, 0xa203,
+ 0x7016, 0x7602, 0x7007, 0x0001, 0x2b60, 0x080c, 0x42c5, 0x0010,
+ 0x080c, 0x429a, 0x1de8, 0x012e, 0x2000, 0x0005, 0x0126, 0x00d6,
+ 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de, 0x7007, 0x0004,
+ 0x7004, 0xd094, 0x1de8, 0x7003, 0x0008, 0x012e, 0x2000, 0x0005,
+ 0x0126, 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de,
+ 0x7e20, 0xb284, 0x0200, 0x1108, 0x7e24, 0xa6b5, 0x000c, 0x681c,
+ 0xd0ac, 0x1118, 0xc685, 0x7003, 0x0000, 0x6828, 0x2050, 0x2d60,
+ 0x6004, 0xa0bc, 0x000f, 0xa7b8, 0x401d, 0x273c, 0x87fb, 0x1138,
+ 0x0210, 0x080c, 0x2575, 0x689c, 0xa065, 0x0120, 0x0c88, 0x080c,
+ 0x429a, 0x1de8, 0x012e, 0x2000, 0x0005, 0x0126, 0x0006, 0x0016,
+ 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x7e20, 0xb284,
+ 0x0200, 0x1108, 0x7e24, 0x00de, 0x003e, 0x004e, 0xa6b5, 0x000c,
+ 0x681c, 0xd0b4, 0x0128, 0xc685, 0x7003, 0x0000, 0x7007, 0x0004,
+ 0x2049, 0x4235, 0x6828, 0xa055, 0x00d6, 0x0904, 0x4296, 0x2d70,
+ 0x2e60, 0x7004, 0xa0bc, 0x000f, 0xa7b8, 0x401d, 0x273c, 0x87fb,
+ 0x1140, 0x0210, 0x080c, 0x2575, 0x709c, 0xa075, 0x2060, 0x0570,
+ 0x0c80, 0x2704, 0xae68, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0268,
+ 0x8a51, 0x1110, 0x080c, 0x2575, 0x8738, 0x2704, 0xa005, 0x1d90,
+ 0x709c, 0xa075, 0x2060, 0x01d0, 0x08e0, 0x8422, 0x8420, 0x831a,
+ 0xa399, 0x0000, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b,
+ 0x1210, 0x080c, 0x2575, 0xb284, 0x0200, 0x0118, 0x2071, 0x0050,
+ 0x0010, 0x2071, 0x0020, 0x00de, 0x0804, 0x41c3, 0x00de, 0x012e,
+ 0x2000, 0x0005, 0x7008, 0x0006, 0xa084, 0x01e0, 0x000e, 0x0110,
+ 0xa006, 0x0005, 0xa084, 0x0003, 0xa086, 0x0003, 0x1108, 0x0005,
+ 0x2704, 0xac78, 0x7800, 0x2f08, 0xd094, 0x1904, 0x43a6, 0x701a,
+ 0x7804, 0x701e, 0x7808, 0x7012, 0x780c, 0x7016, 0x6004, 0xd09c,
+ 0x0120, 0x7810, 0x7022, 0x7814, 0x7026, 0x7602, 0x7004, 0xa084,
+ 0x0010, 0xc085, 0x7006, 0x2079, 0x4700, 0x8a51, 0x01e8, 0x8738,
+ 0x2704, 0xa005, 0x1168, 0x609c, 0xa005, 0x01b8, 0x2060, 0x6004,
+ 0xa084, 0x000f, 0xa080, 0x401d, 0x203c, 0x87fb, 0x090c, 0x2575,
+ 0x7008, 0x0006, 0xa084, 0x01e0, 0x000e, 0x0110, 0xa006, 0x0028,
+ 0xa084, 0x0003, 0xa086, 0x0003, 0x0005, 0x2051, 0x0000, 0x0005,
+ 0x0126, 0x0006, 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090,
+ 0x00de, 0x008e, 0x7108, 0xa184, 0x0003, 0x1128, 0x6828, 0xa005,
+ 0x0178, 0x0804, 0x3f6d, 0x7108, 0xd1fc, 0x0118, 0x080c, 0x40d6,
+ 0x0c88, 0x7007, 0x0010, 0x7108, 0xd1fc, 0x0de8, 0x080c, 0x40d6,
+ 0x7008, 0xa086, 0x0008, 0x1d30, 0x7000, 0xa005, 0x1d18, 0x7003,
+ 0x0000, 0x2049, 0x0000, 0x0006, 0x2001, 0x4701, 0x2004, 0xd0cc,
+ 0x0110, 0x080c, 0x435b, 0x000e, 0x012e, 0x2000, 0x0005, 0x0126,
+ 0x0146, 0x0136, 0x0156, 0x00c6, 0x00d6, 0x70d0, 0xa084, 0x4c00,
+ 0x8004, 0x2090, 0x00de, 0x2049, 0x431f, 0xad80, 0x0011, 0x20a0,
+ 0xb284, 0x0200, 0x0118, 0x2099, 0x0032, 0x0010, 0x2099, 0x0031,
+ 0x700c, 0xa084, 0x07ff, 0x682a, 0x7007, 0x0008, 0x7007, 0x0002,
+ 0x7003, 0x0001, 0x0118, 0x8000, 0x80ac, 0x53a5, 0x700c, 0xa084,
+ 0x07ff, 0x0130, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x1de0,
+ 0x00ce, 0x2049, 0x0000, 0x7003, 0x0000, 0x015e, 0x013e, 0x014e,
+ 0x012e, 0x2000, 0x0005, 0x6814, 0xd0fc, 0x0904, 0x439e, 0x7000,
+ 0xd084, 0x05e0, 0x7e24, 0xa6b5, 0x0004, 0x7007, 0x0004, 0x7004,
+ 0xa084, 0x0004, 0x1de0, 0x7118, 0x0016, 0x711c, 0x0016, 0x7120,
+ 0x0016, 0x7124, 0x0016, 0x701b, 0x0000, 0x701f, 0x3fff, 0x7023,
+ 0x0000, 0x7027, 0x0000, 0x7013, 0x0004, 0x7017, 0x0000, 0x7602,
+ 0x7007, 0x0001, 0x2001, 0xffff, 0x2009, 0x0031, 0x200a, 0x200a,
+ 0x7108, 0x7008, 0xa106, 0x1de0, 0xd1fc, 0x0dd0, 0x002e, 0x7226,
+ 0x002e, 0x7222, 0x002e, 0x721e, 0x002e, 0x721a, 0x7007, 0x0002,
+ 0x7008, 0xa086, 0x0008, 0x0110, 0x0804, 0x410e, 0x7007, 0x0004,
+ 0x7003, 0x0000, 0x0005, 0x2049, 0x41c3, 0x0068, 0x7008, 0xa084,
+ 0x0003, 0x0110, 0xa006, 0x0005, 0xa006, 0x2020, 0x2018, 0x2c58,
+ 0x2160, 0x2049, 0x0000, 0x8b58, 0x6100, 0x2100, 0xa408, 0x711a,
+ 0x6004, 0xa301, 0x701e, 0x0006, 0x2b04, 0xa084, 0x0008, 0x0150,
+ 0x6010, 0xa081, 0x0000, 0x7022, 0x0006, 0x6014, 0xa081, 0x0000,
+ 0x7026, 0x0006, 0xa184, 0x0007, 0x2011, 0x0008, 0xa22a, 0x6208,
+ 0x2400, 0xa212, 0x0026, 0x620c, 0x2240, 0x2300, 0xa843, 0x002e,
+ 0x88ff, 0x1170, 0x2500, 0xa202, 0x0108, 0x1250, 0x2220, 0x2041,
+ 0x0000, 0x2b04, 0xd09c, 0x0110, 0x000e, 0x000e, 0x000e, 0x0450,
+ 0x7512, 0x7017, 0x0000, 0x7602, 0xa986, 0x41c3, 0x1118, 0x7007,
+ 0x0001, 0x0028, 0x7004, 0xa084, 0x0010, 0xc085, 0x7006, 0x2500,
+ 0xa100, 0x701a, 0x2b04, 0xa084, 0x0008, 0x0110, 0x000e, 0x004e,
+ 0x001e, 0xa189, 0x0000, 0x711e, 0x2b0c, 0xa18c, 0x0008, 0x0130,
+ 0xa4a1, 0x0000, 0x7422, 0xa081, 0x0000, 0x7026, 0x2500, 0xa222,
+ 0xa8c3, 0x0000, 0x7412, 0x2820, 0x7416, 0x7602, 0xa986, 0x41c3,
+ 0x1118, 0x7007, 0x0001, 0x0028, 0x7004, 0xa084, 0x0010, 0xc085,
+ 0x7006, 0x8b59, 0x2b60, 0x2079, 0x4700, 0x080c, 0x42c5, 0xa006,
+ 0x0005, 0x2091, 0x8000, 0x2091, 0x6000, 0x78ac, 0xa005, 0x1168,
+ 0x7974, 0x70d0, 0xa106, 0x1148, 0x781c, 0xa005, 0x0130, 0x781f,
+ 0x0000, 0x0e04, 0x443d, 0x2091, 0x4080, 0x2069, 0x4780, 0xc7fd,
+ 0x6800, 0xa084, 0x000f, 0x1198, 0x68d0, 0xd0b4, 0x0180, 0xd0bc,
+ 0x1170, 0x00f6, 0x2079, 0x0100, 0xd7fc, 0x1110, 0x2079, 0x0200,
+ 0x7830, 0xa084, 0x00c0, 0x1110, 0x080c, 0x22d5, 0x00fe, 0xd7fc,
+ 0x0120, 0x2069, 0x4740, 0xc7fc, 0x0c18, 0x7830, 0x8001, 0x7832,
+ 0x1904, 0x44c7, 0x7834, 0x7832, 0x2061, 0x6cc0, 0x2069, 0x4780,
+ 0xc7fd, 0x68cc, 0xa005, 0x0128, 0x8001, 0x68ce, 0x1110, 0x080c,
+ 0x4639, 0x6800, 0xa084, 0x000f, 0x0168, 0xa086, 0x0001, 0x0150,
+ 0x6840, 0xa00d, 0x0138, 0x2104, 0xa005, 0x0120, 0x8001, 0x200a,
+ 0x0904, 0x45d6, 0x6814, 0xa005, 0x01a8, 0x8001, 0x6816, 0x1190,
+ 0x68a3, 0x0001, 0x00f6, 0xd7fc, 0x1118, 0x2079, 0x0200, 0x0010,
+ 0x2079, 0x0100, 0x080c, 0x3c6e, 0x00fe, 0x6860, 0xa005, 0x0110,
+ 0x080c, 0x22d5, 0x687c, 0xa005, 0x0140, 0x8001, 0x687e, 0x1128,
+ 0x6863, 0x0000, 0x68d0, 0xc0c5, 0x68d2, 0x68d0, 0xd0fc, 0x01b0,
+ 0xc0fc, 0x68d2, 0x20a9, 0x0200, 0x6034, 0xa005, 0x0158, 0x8001,
+ 0x6036, 0x68d0, 0xc0fd, 0x68d2, 0x1128, 0x6010, 0xa005, 0x0110,
+ 0x080c, 0x22d5, 0xace0, 0x0010, 0x1f04, 0x44ac, 0xd7fc, 0x0138,
+ 0x2061, 0x4cc0, 0x2069, 0x4740, 0xc7fc, 0x0804, 0x4469, 0x0459,
+ 0x7838, 0x8001, 0x783a, 0x11a0, 0x783c, 0x783a, 0x2061, 0x4cc0,
+ 0x2069, 0x4740, 0xc7fc, 0x680c, 0xa005, 0x0110, 0x080c, 0x4543,
+ 0xd7fc, 0x1130, 0x2061, 0x6cc0, 0x2069, 0x4780, 0xc7fd, 0x0c98,
+ 0x7810, 0xd0cc, 0x0168, 0xd0ac, 0x1120, 0xd0a4, 0x0148, 0xc0ad,
+ 0x7812, 0x2091, 0x8001, 0x0e04, 0x44ef, 0x080c, 0x20a1, 0x0005,
+ 0x2091, 0x8001, 0x0005, 0x7840, 0x8001, 0x7842, 0x1904, 0x4542,
+ 0x7844, 0x7842, 0x2069, 0x4740, 0xc7fc, 0x2079, 0x0200, 0x68d4,
+ 0xa005, 0x0138, 0x7de0, 0xa504, 0x1120, 0x68d6, 0x68d0, 0xc0bc,
+ 0x68d2, 0x2079, 0x4700, 0x6810, 0xa005, 0x1110, 0x2001, 0x0101,
+ 0x8001, 0x6812, 0xd7fc, 0x0118, 0xa080, 0x8dd0, 0x0010, 0xa080,
+ 0x8cc0, 0x2040, 0x2004, 0xa065, 0x01e0, 0x6024, 0xa005, 0x01b0,
+ 0x8001, 0x6026, 0x1198, 0x6800, 0xa005, 0x0130, 0x6848, 0xac06,
+ 0x1118, 0x080c, 0x45d6, 0x0068, 0x6860, 0xa005, 0x0118, 0x6027,
+ 0x0001, 0x0020, 0x080c, 0x4584, 0x2804, 0x0c28, 0x6000, 0x2c40,
+ 0x0c10, 0xd7fc, 0x1138, 0x2069, 0x4780, 0xc7fd, 0x2079, 0x0100,
+ 0x0804, 0x44ff, 0x0005, 0x2009, 0x0000, 0x20a9, 0x0200, 0x6008,
+ 0xd09c, 0x0558, 0x6024, 0xa005, 0x0118, 0x8001, 0x6026, 0x0418,
+ 0x6008, 0xc09c, 0xd084, 0x1110, 0xd0ac, 0x01c0, 0x600a, 0x6004,
+ 0xa005, 0x01d8, 0x00d6, 0x00c6, 0x0016, 0x2068, 0x6010, 0x8001,
+ 0x6012, 0x080c, 0x37c7, 0x2d00, 0x2c68, 0x2060, 0x080c, 0x1c02,
+ 0x080c, 0x1db2, 0x001e, 0x00ce, 0x00de, 0x0038, 0xc0bd, 0x600a,
+ 0xa18d, 0x0001, 0x0010, 0xa18d, 0x0100, 0xace0, 0x0010, 0x1f04,
+ 0x4547, 0xa184, 0x0001, 0x0130, 0xa18c, 0xfffe, 0x690e, 0x080c,
+ 0x22d5, 0x0008, 0x690e, 0x0005, 0x2c00, 0x687a, 0x6714, 0x6f72,
+ 0x6017, 0x0000, 0x602b, 0x0000, 0x601b, 0x0006, 0x60b4, 0xa084,
+ 0x5f00, 0x601e, 0x6020, 0xa084, 0x00ff, 0xa085, 0x0060, 0x6022,
+ 0x6000, 0x2042, 0x2069, 0x4780, 0xd7fc, 0x1110, 0x2069, 0x4740,
+ 0x6858, 0xac06, 0x1110, 0x2800, 0x685a, 0x080c, 0x1b9a, 0x6818,
+ 0xa005, 0x0110, 0x8001, 0x681a, 0x6808, 0xc0a4, 0x680a, 0x6810,
+ 0x7908, 0x8109, 0x790a, 0x8001, 0x1310, 0x080c, 0x2575, 0x6812,
+ 0x1118, 0x7910, 0xc1a5, 0x7912, 0x602f, 0x0000, 0x6033, 0x0000,
+ 0x2c68, 0x080c, 0x1dbf, 0xd7fc, 0x1118, 0x2069, 0x4740, 0x0010,
+ 0x2069, 0x4780, 0x6910, 0xa184, 0x0100, 0x2001, 0x0006, 0x1118,
+ 0x6976, 0x2001, 0x0004, 0x080c, 0x22cb, 0x0005, 0x00d6, 0x6948,
+ 0x2160, 0xd7fc, 0x1118, 0x2069, 0x0200, 0x0010, 0x2069, 0x0100,
+ 0x080c, 0x2490, 0x601b, 0x0006, 0x6858, 0xa084, 0x5f00, 0x601e,
+ 0x6020, 0xa084, 0x00ff, 0xa085, 0x0048, 0x6022, 0x602f, 0x0000,
+ 0x6033, 0x0000, 0x6808, 0xa084, 0xfffd, 0x680a, 0x6830, 0xd0b4,
+ 0x01b0, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, 0xd094, 0x0110,
+ 0x1f04, 0x45fd, 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xd084,
+ 0x0110, 0x1f04, 0x4606, 0x20a9, 0x00fa, 0x1f04, 0x460d, 0x681b,
+ 0x0054, 0x00de, 0x6863, 0x0007, 0x0005, 0x2079, 0x4700, 0x00e1,
+ 0x0089, 0x00a9, 0x2009, 0x0002, 0x2069, 0x4780, 0x680f, 0x0000,
+ 0x6813, 0x0000, 0x6817, 0x0000, 0x8109, 0x0118, 0x2069, 0x4740,
+ 0x0ca8, 0x0005, 0x2019, 0x00a3, 0x7b3a, 0x7b3e, 0x0005, 0x2019,
+ 0x0033, 0x7b42, 0x7b46, 0x0005, 0x2019, 0x32dd, 0x7b32, 0x7b36,
+ 0x0005, 0x6a4c, 0xa285, 0x0000, 0x01f0, 0x6950, 0x6bbc, 0xa300,
+ 0x00c6, 0x2164, 0x6304, 0x83ff, 0x1138, 0x8211, 0x0148, 0x8108,
+ 0xa11a, 0x0eb8, 0x69bc, 0x0ca8, 0x68cf, 0x000a, 0x00ce, 0x0005,
+ 0x694c, 0x6abc, 0x2264, 0x6008, 0xc0b5, 0x600a, 0x8210, 0x8109,
+ 0x1dc8, 0x694e, 0x00ce, 0x0005, 0x0016, 0x1d04, 0x465d, 0x2091,
+ 0x6000, 0x1d04, 0x4661, 0x2091, 0x6000, 0x70ec, 0xd0dc, 0x1118,
+ 0xd0d4, 0x0190, 0x00a0, 0xae8e, 0x0100, 0x0138, 0x7814, 0xc0f5,
+ 0xc0c5, 0x7816, 0xd0d4, 0x1580, 0x0460, 0x7814, 0xc0fd, 0xc0c5,
+ 0x7816, 0xd0d4, 0x1548, 0x0428, 0xd0e4, 0x0904, 0x46c4, 0x1d04,
+ 0x467f, 0x2091, 0x6000, 0x2009, 0x000c, 0x1d04, 0x4685, 0x2091,
+ 0x6000, 0x8109, 0x1dd0, 0x70e4, 0xa084, 0x01ff, 0xa086, 0x01ff,
+ 0x1110, 0x70ec, 0x08c0, 0xae8e, 0x0100, 0x0128, 0x7814, 0xc0f4,
+ 0xd0fc, 0x1130, 0x0020, 0x7814, 0xc0fc, 0xd0f4, 0x1108, 0xc0c4,
+ 0x7816, 0x7804, 0xd08c, 0x0500, 0x00c6, 0x2061, 0x0000, 0x6018,
+ 0xd084, 0x11b8, 0xae86, 0x0200, 0x00e6, 0x2071, 0x0010, 0x0120,
+ 0x70db, 0x0001, 0x78e4, 0x0018, 0x70db, 0x0000, 0x78e0, 0x70c6,
+ 0x70c3, 0x800e, 0x601b, 0x0001, 0x2091, 0x4080, 0x00ee, 0x00ce,
+ 0x0018, 0x00ce, 0x681f, 0x000c, 0x001e, 0x70a0, 0x70a2, 0x0005,
+ 0x0c26
};
#ifdef UNIQUE_FW_NAME
-static unsigned short fw12160i_length01 = 0x35e6;
+static unsigned short fw12160i_length01 = 0x36c9;
#else
-static unsigned short risc_code_length01 = 0x35e6;
+static unsigned short risc_code_length01 = 0x36c9;
#endif
+
diff --git a/drivers/scsi/ql1280_fw.h b/drivers/scsi/ql1280_fw.h
index 2621e99a431..784f2a04bf2 100644
--- a/drivers/scsi/ql1280_fw.h
+++ b/drivers/scsi/ql1280_fw.h
@@ -23,25 +23,25 @@
/*
- * Firmware Version 8.15.00 (14:35 Aug 22, 2000)
+ * Firmware Version 8.15.11 (10:20 Jan 02, 2002)
*/
#ifdef UNIQUE_FW_NAME
-static unsigned char fw1280ei_version_str[] = {8,15,0};
+static unsigned char fw1280ei_version_str[] = {8,15,11};
#else
-static unsigned char firmware_version[] = {8,15,0};
+static unsigned char firmware_version[] = {8,15,11};
#endif
#ifdef UNIQUE_FW_NAME
-#define fw1280ei_VERSION_STRING "8.15.00"
+#define fw1280ei_VERSION_STRING "8.15.11"
#else
-#define FW_VERSION_STRING "8.15.00"
+#define FW_VERSION_STRING "8.15.11"
#endif
#ifdef UNIQUE_FW_NAME
-static unsigned short fw1280ei_addr01 = 0x1000;
+static unsigned short fw1280ei_addr01 = 0x1000 ;
#else
-static unsigned short risc_code_addr01 = 0x1000;
+static unsigned short risc_code_addr01 = 0x1000 ;
#endif
#ifdef UNIQUE_FW_NAME
@@ -49,7 +49,7 @@ static unsigned short fw1280ei_code01[] = {
#else
static unsigned short risc_code01[] = {
#endif
- 0x0078, 0x1041, 0x0000, 0x3d3b, 0x0000, 0x2043, 0x4f50, 0x5952,
+ 0x0078, 0x1041, 0x0000, 0x3e2e, 0x0000, 0x2043, 0x4f50, 0x5952,
0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932, 0x2c31,
0x3939, 0x332c, 0x3139, 0x3934, 0x2051, 0x4c4f, 0x4749, 0x4320,
0x434f, 0x5250, 0x4f52, 0x4154, 0x494f, 0x4e00, 0x2049, 0x5350,
@@ -57,7 +57,7 @@ static unsigned short risc_code01[] = {
0x6572, 0x7369, 0x6f6e, 0x2030, 0x382e, 0x3135, 0x2020, 0x2043,
0x7573, 0x746f, 0x6d65, 0x7220, 0x4e6f, 0x2e20, 0x3030, 0x2050,
0x726f, 0x6475, 0x6374, 0x204e, 0x6f2e, 0x2020, 0x3030, 0x2020,
- 0x2400, 0x20c9, 0x97ff, 0x2001, 0x04fc, 0x2004, 0xa086, 0x1080,
+ 0x2400, 0x20c9, 0x98ff, 0x2001, 0x04fc, 0x2004, 0xa086, 0x1080,
0x00c0, 0x1054, 0x2071, 0x0100, 0x70a0, 0x70a2, 0x20c1, 0x0010,
0x2089, 0x1374, 0x0078, 0x106d, 0x2001, 0x04fc, 0x2004, 0xa086,
0x1280, 0x00c0, 0x1069, 0x2071, 0x0200, 0x70a0, 0x70a2, 0x2071,
@@ -70,1660 +70,1670 @@ static unsigned short risc_code01[] = {
0xa286, 0xa5a5, 0x0040, 0x10a4, 0xa386, 0x000f, 0x0040, 0x10a0,
0x2c6a, 0x2a5a, 0x20c1, 0x0020, 0x2019, 0x000f, 0x0078, 0x1080,
0x2c6a, 0x2a5a, 0x0078, 0x10a2, 0x2c6a, 0x2a5a, 0x2130, 0x2128,
- 0xa1a2, 0x4e00, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424,
- 0xa192, 0x9800, 0x2009, 0x0000, 0x2001, 0x0032, 0x1078, 0x207a,
- 0x2218, 0x2079, 0x4e00, 0x2fa0, 0x2408, 0x2011, 0x0000, 0x20a9,
+ 0xa1a2, 0x4f00, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424,
+ 0xa192, 0x9900, 0x2009, 0x0000, 0x2001, 0x0032, 0x1078, 0x20c1,
+ 0x2218, 0x2079, 0x4f00, 0x2fa0, 0x2408, 0x2011, 0x0000, 0x20a9,
0x0040, 0x42a4, 0x8109, 0x00c0, 0x10bf, 0x2009, 0xff00, 0x3400,
0xa102, 0x0048, 0x10cf, 0x0040, 0x10cf, 0x20a8, 0x42a4, 0x2001,
0x04fc, 0x2004, 0xa086, 0x1080, 0x00c0, 0x10e5, 0x2071, 0x0100,
- 0x0d7e, 0x2069, 0x4e40, 0x1078, 0x4cdd, 0x0d7f, 0x7810, 0xc0ed,
+ 0x0d7e, 0x2069, 0x4f40, 0x1078, 0x4db0, 0x0d7f, 0x7810, 0xc0ed,
0x7812, 0x781b, 0x0064, 0x0078, 0x110a, 0x2001, 0x04fc, 0x2004,
0xa086, 0x1280, 0x00c0, 0x1105, 0x7814, 0xc0ed, 0xc0d5, 0x7816,
- 0x781b, 0x0064, 0x2071, 0x0200, 0x0d7e, 0x2069, 0x4e40, 0x1078,
- 0x4cdd, 0x2069, 0x4e80, 0x2071, 0x0100, 0x1078, 0x4cdd, 0x7814,
+ 0x781b, 0x0064, 0x2071, 0x0200, 0x0d7e, 0x2069, 0x4f40, 0x1078,
+ 0x4db0, 0x2069, 0x4f80, 0x2071, 0x0100, 0x1078, 0x4db0, 0x7814,
0xc0d4, 0x7816, 0x0d7f, 0x0078, 0x110a, 0x7814, 0xc0e5, 0x7816,
0x781b, 0x003c, 0x7eca, 0x7cc2, 0x7bc6, 0x7867, 0x0000, 0x7800,
0xc08d, 0x7802, 0x2031, 0x0030, 0x78af, 0x0101, 0x7823, 0x0002,
- 0x7827, 0x0002, 0x2009, 0x0002, 0x2069, 0x4e40, 0x681b, 0x0003,
+ 0x7827, 0x0002, 0x2009, 0x0002, 0x2069, 0x4f40, 0x681b, 0x0003,
0x6823, 0x0007, 0x6827, 0x00fa, 0x682b, 0x0008, 0x682f, 0x0028,
0x6837, 0x0000, 0x683b, 0x0006, 0x6833, 0x0008, 0x683f, 0x0000,
- 0x8109, 0x0040, 0x115e, 0x68d3, 0x000a, 0x68c3, 0x4ec0, 0x2079,
- 0x4e00, 0x7814, 0xd0e4, 0x00c0, 0x1144, 0xd0ec, 0x00c0, 0x1148,
+ 0x8109, 0x0040, 0x115e, 0x68d3, 0x000a, 0x68c3, 0x4fc0, 0x2079,
+ 0x4f00, 0x7814, 0xd0e4, 0x00c0, 0x1144, 0xd0ec, 0x00c0, 0x1148,
0x68d7, 0x7329, 0x0078, 0x114a, 0x68d7, 0x730d, 0x0078, 0x114a,
- 0x68d7, 0x732d, 0x68c7, 0x53c0, 0x68cb, 0x52c0, 0x68cf, 0x93c0,
- 0x68ab, 0x9644, 0x68af, 0x9649, 0x68b3, 0x9644, 0x68b7, 0x9644,
- 0x68a7, 0x0001, 0x2069, 0x4e80, 0x0078, 0x111e, 0x68d3, 0x000a,
- 0x68c3, 0x50c0, 0x7814, 0xd0e4, 0x00c0, 0x116a, 0x68d7, 0x7439,
- 0x0078, 0x116c, 0x68d7, 0x7419, 0x68c7, 0x73c0, 0x68cb, 0x5340,
- 0x68cf, 0x94d0, 0x68ab, 0x9649, 0x68af, 0x964e, 0x68b3, 0x9649,
- 0x68b7, 0x9649, 0x68a7, 0x0001, 0x7810, 0xd0ec, 0x00c0, 0x11c2,
- 0x7814, 0xd0e4, 0x00c0, 0x11b4, 0x0e7e, 0x2069, 0x52c0, 0x2071,
+ 0x68d7, 0x732d, 0x68c7, 0x54c0, 0x68cb, 0x53c0, 0x68cf, 0x94c0,
+ 0x68ab, 0x9744, 0x68af, 0x9749, 0x68b3, 0x9744, 0x68b7, 0x9744,
+ 0x68a7, 0x0001, 0x2069, 0x4f80, 0x0078, 0x111e, 0x68d3, 0x000a,
+ 0x68c3, 0x51c0, 0x7814, 0xd0e4, 0x00c0, 0x116a, 0x68d7, 0x7439,
+ 0x0078, 0x116c, 0x68d7, 0x7419, 0x68c7, 0x74c0, 0x68cb, 0x5440,
+ 0x68cf, 0x95d0, 0x68ab, 0x9749, 0x68af, 0x974e, 0x68b3, 0x9749,
+ 0x68b7, 0x9749, 0x68a7, 0x0001, 0x7810, 0xd0ec, 0x00c0, 0x11c2,
+ 0x7814, 0xd0e4, 0x00c0, 0x11b4, 0x0e7e, 0x2069, 0x53c0, 0x2071,
0x0200, 0x70ec, 0xd0e4, 0x00c0, 0x1195, 0x2019, 0x0c0c, 0x2021,
- 0x000c, 0x1078, 0x2009, 0x0078, 0x119b, 0x2019, 0x0c0a, 0x2021,
- 0x000a, 0x1078, 0x2009, 0x2069, 0x5340, 0x2071, 0x0100, 0x70ec,
+ 0x000c, 0x1078, 0x2050, 0x0078, 0x119b, 0x2019, 0x0c0a, 0x2021,
+ 0x000a, 0x1078, 0x2050, 0x2069, 0x5440, 0x2071, 0x0100, 0x70ec,
0xd0e4, 0x00c0, 0x11ab, 0x2019, 0x0c0c, 0x2021, 0x000c, 0x1078,
- 0x2009, 0x0078, 0x11b1, 0x2019, 0x0c0a, 0x2021, 0x000a, 0x1078,
- 0x2009, 0x0e7f, 0x0078, 0x11db, 0x2019, 0x0c0c, 0x2021, 0x000c,
- 0x2069, 0x52c0, 0x1078, 0x2009, 0x2069, 0x5340, 0x1078, 0x2009,
- 0x0078, 0x11db, 0x2069, 0x52c0, 0x0e7e, 0x2071, 0x0100, 0x70ec,
+ 0x2050, 0x0078, 0x11b1, 0x2019, 0x0c0a, 0x2021, 0x000a, 0x1078,
+ 0x2050, 0x0e7f, 0x0078, 0x11db, 0x2019, 0x0c0c, 0x2021, 0x000c,
+ 0x2069, 0x53c0, 0x1078, 0x2050, 0x2069, 0x5440, 0x1078, 0x2050,
+ 0x0078, 0x11db, 0x2069, 0x53c0, 0x0e7e, 0x2071, 0x0100, 0x70ec,
0xd0e4, 0x00c0, 0x11d4, 0x2019, 0x0c0c, 0x2021, 0x000c, 0x1078,
- 0x2009, 0x0e7f, 0x0078, 0x11db, 0x2019, 0x0c0a, 0x2021, 0x000a,
- 0x1078, 0x2009, 0x0e7f, 0x2011, 0x0002, 0x2069, 0x53c0, 0x2009,
+ 0x2050, 0x0e7f, 0x0078, 0x11db, 0x2019, 0x0c0a, 0x2021, 0x000a,
+ 0x1078, 0x2050, 0x0e7f, 0x2011, 0x0002, 0x2069, 0x54c0, 0x2009,
0x0002, 0x20a9, 0x0100, 0x6837, 0x0000, 0x680b, 0x0040, 0x7bc8,
0xa386, 0xfeff, 0x00c0, 0x11f2, 0x6817, 0x0100, 0x681f, 0x0064,
0x0078, 0x11f6, 0x6817, 0x0064, 0x681f, 0x0002, 0xade8, 0x0010,
0x00f0, 0x11e3, 0x8109, 0x00c0, 0x11e1, 0x8211, 0x0040, 0x1204,
- 0x2069, 0x73c0, 0x0078, 0x11df, 0x1078, 0x265b, 0x1078, 0x468e,
- 0x1078, 0x1dd4, 0x1078, 0x4c6f, 0x2091, 0x2100, 0x2079, 0x4e00,
+ 0x2069, 0x74c0, 0x0078, 0x11df, 0x1078, 0x26a2, 0x1078, 0x4712,
+ 0x1078, 0x1e1b, 0x1078, 0x4d42, 0x2091, 0x2100, 0x2079, 0x4f00,
0x7810, 0xd0ec, 0x0040, 0x1218, 0x2071, 0x0020, 0x0078, 0x121a,
- 0x2071, 0x0050, 0x2091, 0x2200, 0x2079, 0x4e00, 0x2071, 0x0020,
- 0x2091, 0x2300, 0x2079, 0x4e00, 0x7810, 0xd0ec, 0x0040, 0x122c,
- 0x2079, 0x0100, 0x0078, 0x122e, 0x2079, 0x0200, 0x2071, 0x4e40,
- 0x2091, 0x2400, 0x2079, 0x0100, 0x2071, 0x4e80, 0x2091, 0x2000,
- 0x2079, 0x4e00, 0x2071, 0x0010, 0x3200, 0xa085, 0x303d, 0x2090,
+ 0x2071, 0x0050, 0x2091, 0x2200, 0x2079, 0x4f00, 0x2071, 0x0020,
+ 0x2091, 0x2300, 0x2079, 0x4f00, 0x7810, 0xd0ec, 0x0040, 0x122c,
+ 0x2079, 0x0100, 0x0078, 0x122e, 0x2079, 0x0200, 0x2071, 0x4f40,
+ 0x2091, 0x2400, 0x2079, 0x0100, 0x2071, 0x4f80, 0x2091, 0x2000,
+ 0x2079, 0x4f00, 0x2071, 0x0010, 0x3200, 0xa085, 0x303d, 0x2090,
0x2071, 0x0010, 0x70c3, 0x0000, 0x0090, 0x124d, 0x70c0, 0xa086,
- 0x0002, 0x00c0, 0x124d, 0x1078, 0x15ba, 0x2039, 0x0000, 0x7810,
+ 0x0002, 0x00c0, 0x124d, 0x1078, 0x15c1, 0x2039, 0x0000, 0x7810,
0xd0ec, 0x00c0, 0x12cf, 0x1078, 0x148e, 0x78ac, 0xa005, 0x00c0,
0x126b, 0x0068, 0x1261, 0x786c, 0xa065, 0x0040, 0x1261, 0x1078,
- 0x2395, 0x1078, 0x20a1, 0x0068, 0x1278, 0x786c, 0xa065, 0x0040,
- 0x126b, 0x1078, 0x2395, 0x0068, 0x1278, 0x2009, 0x4e47, 0x2011,
- 0x4e87, 0x2104, 0x220c, 0xa105, 0x0040, 0x1278, 0x1078, 0x1f0a,
- 0x2071, 0x4e40, 0x70a4, 0xa005, 0x0040, 0x129d, 0x7450, 0xa485,
+ 0x23dc, 0x1078, 0x20e8, 0x0068, 0x1278, 0x786c, 0xa065, 0x0040,
+ 0x126b, 0x1078, 0x23dc, 0x0068, 0x1278, 0x2009, 0x4f47, 0x2011,
+ 0x4f87, 0x2104, 0x220c, 0xa105, 0x0040, 0x1278, 0x1078, 0x1f51,
+ 0x2071, 0x4f40, 0x70a4, 0xa005, 0x0040, 0x129d, 0x7450, 0xa485,
0x0000, 0x0040, 0x129d, 0x2079, 0x0200, 0x2091, 0x8000, 0x72d4,
- 0xa28c, 0x303d, 0x2190, 0x1078, 0x2b6a, 0x2091, 0x8000, 0x2091,
- 0x303d, 0x0068, 0x129d, 0x2079, 0x4e00, 0x786c, 0xa065, 0x0040,
- 0x129d, 0x2071, 0x0010, 0x1078, 0x2395, 0x00e0, 0x12a5, 0x2079,
- 0x4e00, 0x2071, 0x0010, 0x1078, 0x4a43, 0x2071, 0x4e80, 0x70a4,
+ 0xa28c, 0x303d, 0x2190, 0x1078, 0x2bb1, 0x2091, 0x8000, 0x2091,
+ 0x303d, 0x0068, 0x129d, 0x2079, 0x4f00, 0x786c, 0xa065, 0x0040,
+ 0x129d, 0x2071, 0x0010, 0x1078, 0x23dc, 0x00e0, 0x12a5, 0x2079,
+ 0x4f00, 0x2071, 0x0010, 0x1078, 0x4b16, 0x2071, 0x4f80, 0x70a4,
0xa005, 0x0040, 0x12bd, 0x7050, 0xa025, 0x0040, 0x12bd, 0x2079,
0x0100, 0x2091, 0x8000, 0x72d4, 0xa28c, 0x303d, 0x2190, 0x1078,
- 0x2b6a, 0x2091, 0x8000, 0x2091, 0x303d, 0x2079, 0x4e00, 0x2071,
+ 0x2bb1, 0x2091, 0x8000, 0x2091, 0x303d, 0x2079, 0x4f00, 0x2071,
0x0010, 0x0068, 0x12c9, 0x786c, 0xa065, 0x0040, 0x12c9, 0x1078,
- 0x2395, 0x00e0, 0x1253, 0x1078, 0x4a43, 0x0078, 0x1253, 0x1078,
+ 0x23dc, 0x00e0, 0x1253, 0x1078, 0x4b16, 0x0078, 0x1253, 0x1078,
0x148e, 0x78ac, 0xa005, 0x00c0, 0x12e7, 0x0068, 0x12dd, 0x786c,
- 0xa065, 0x0040, 0x12dd, 0x1078, 0x2395, 0x1078, 0x20a1, 0x0068,
- 0x12f1, 0x786c, 0xa065, 0x0040, 0x12e7, 0x1078, 0x2395, 0x0068,
- 0x12f1, 0x2009, 0x4e47, 0x2104, 0xa005, 0x0040, 0x12f1, 0x1078,
- 0x1f0a, 0x2071, 0x4e40, 0x70a4, 0xa005, 0x0040, 0x130c, 0x7450,
+ 0xa065, 0x0040, 0x12dd, 0x1078, 0x23dc, 0x1078, 0x20e8, 0x0068,
+ 0x12f1, 0x786c, 0xa065, 0x0040, 0x12e7, 0x1078, 0x23dc, 0x0068,
+ 0x12f1, 0x2009, 0x4f47, 0x2104, 0xa005, 0x0040, 0x12f1, 0x1078,
+ 0x1f51, 0x2071, 0x4f40, 0x70a4, 0xa005, 0x0040, 0x130c, 0x7450,
0xa485, 0x0000, 0x0040, 0x130c, 0x2079, 0x0100, 0x2091, 0x8000,
- 0x72d4, 0xa28c, 0x303d, 0x2190, 0x1078, 0x2b6a, 0x2091, 0x8000,
- 0x2091, 0x303d, 0x2079, 0x4e00, 0x2071, 0x0010, 0x0068, 0x1316,
- 0x786c, 0xa065, 0x0040, 0x1316, 0x1078, 0x2395, 0x00e0, 0x12cf,
- 0x1078, 0x4a43, 0x0078, 0x12cf, 0x133c, 0x133c, 0x133e, 0x133e,
+ 0x72d4, 0xa28c, 0x303d, 0x2190, 0x1078, 0x2bb1, 0x2091, 0x8000,
+ 0x2091, 0x303d, 0x2079, 0x4f00, 0x2071, 0x0010, 0x0068, 0x1316,
+ 0x786c, 0xa065, 0x0040, 0x1316, 0x1078, 0x23dc, 0x00e0, 0x12cf,
+ 0x1078, 0x4b16, 0x0078, 0x12cf, 0x133c, 0x133c, 0x133e, 0x133e,
0x134b, 0x134b, 0x134b, 0x134b, 0x1356, 0x1356, 0x1363, 0x1363,
0x134b, 0x134b, 0x134b, 0x134b, 0x133c, 0x133c, 0x133e, 0x133e,
0x134b, 0x134b, 0x134b, 0x134b, 0x1356, 0x1356, 0x1363, 0x1363,
0x134b, 0x134b, 0x134b, 0x134b, 0x0078, 0x133c, 0x007e, 0x107e,
- 0x127e, 0x2091, 0x2400, 0x1078, 0x298a, 0x127f, 0x107f, 0x007f,
+ 0x127e, 0x2091, 0x2400, 0x1078, 0x29d1, 0x127f, 0x107f, 0x007f,
0x2091, 0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x1078, 0x13c8,
0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c, 0x007e, 0x107e,
- 0x127e, 0x2091, 0x2300, 0x1078, 0x298a, 0x127f, 0x107f, 0x007f,
+ 0x127e, 0x2091, 0x2300, 0x1078, 0x29d1, 0x127f, 0x107f, 0x007f,
0x2091, 0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x2091, 0x2300,
- 0x1078, 0x298a, 0x2091, 0x2400, 0x1078, 0x298a, 0x127f, 0x107f,
+ 0x1078, 0x29d1, 0x2091, 0x2400, 0x1078, 0x29d1, 0x127f, 0x107f,
0x007f, 0x2091, 0x8001, 0x007c, 0x1394, 0x1394, 0x1396, 0x1396,
0x13a3, 0x13a3, 0x13a3, 0x13a3, 0x13ae, 0x13ae, 0x1396, 0x1396,
0x13a3, 0x13a3, 0x13a3, 0x13a3, 0x13af, 0x13af, 0x13af, 0x13af,
0x13af, 0x13af, 0x13af, 0x13af, 0x13af, 0x13af, 0x13af, 0x13af,
0x13af, 0x13af, 0x13af, 0x13af, 0x0078, 0x1394, 0x007e, 0x107e,
- 0x127e, 0x2091, 0x2300, 0x1078, 0x298a, 0x127f, 0x107f, 0x007f,
+ 0x127e, 0x2091, 0x2300, 0x1078, 0x29d1, 0x127f, 0x107f, 0x007f,
0x2091, 0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x1078, 0x13d5,
0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c, 0x007c, 0x107e,
0x127e, 0x0d7e, 0x0e7e, 0x0f7e, 0x007e, 0x2071, 0x0100, 0x2069,
- 0x4e40, 0x2079, 0x4e00, 0x70ec, 0xa084, 0x1c00, 0x78e2, 0x1078,
- 0x4cdd, 0x007f, 0x0f7f, 0x0e7f, 0x0d7f, 0x127f, 0x107f, 0x007c,
+ 0x4f40, 0x2079, 0x4f00, 0x70ec, 0xa084, 0x1c00, 0x78e2, 0x1078,
+ 0x4db0, 0x007f, 0x0f7f, 0x0e7f, 0x0d7f, 0x127f, 0x107f, 0x007c,
0x3c00, 0xa084, 0x0007, 0x0079, 0x13cd, 0x13de, 0x13de, 0x13e0,
0x13e0, 0x13e5, 0x13e5, 0x13ea, 0x13ea, 0x3c00, 0xa084, 0x0003,
- 0x0079, 0x13da, 0x13de, 0x13de, 0x13f3, 0x13f3, 0x1078, 0x296b,
- 0x2091, 0x2200, 0x1078, 0x4768, 0x007c, 0x2091, 0x2100, 0x1078,
- 0x4768, 0x007c, 0x2091, 0x2100, 0x1078, 0x4768, 0x2091, 0x2200,
- 0x1078, 0x4768, 0x007c, 0x2091, 0x2100, 0x1078, 0x4768, 0x007c,
+ 0x0079, 0x13da, 0x13de, 0x13de, 0x13f3, 0x13f3, 0x1078, 0x29b2,
+ 0x2091, 0x2200, 0x1078, 0x47ec, 0x007c, 0x2091, 0x2100, 0x1078,
+ 0x47ec, 0x007c, 0x2091, 0x2100, 0x1078, 0x47ec, 0x2091, 0x2200,
+ 0x1078, 0x47ec, 0x007c, 0x2091, 0x2100, 0x1078, 0x47ec, 0x007c,
0x1418, 0x1418, 0x141a, 0x141a, 0x1427, 0x1427, 0x1427, 0x1427,
0x1432, 0x1432, 0x143f, 0x143f, 0x1427, 0x1427, 0x1427, 0x1427,
0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450,
0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450,
0x0078, 0x1418, 0x007e, 0x107e, 0x127e, 0x2091, 0x2400, 0x1078,
- 0x298a, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c, 0x007e,
+ 0x29d1, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c, 0x007e,
0x107e, 0x127e, 0x1078, 0x13c8, 0x127f, 0x107f, 0x007f, 0x2091,
0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x2091, 0x2300, 0x1078,
- 0x298a, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c, 0x007e,
- 0x107e, 0x127e, 0x2091, 0x2300, 0x1078, 0x298a, 0x2091, 0x2400,
- 0x1078, 0x298a, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c,
- 0x007e, 0x107e, 0x127e, 0x0d7e, 0x0e7e, 0x0f7e, 0x2079, 0x4e00,
- 0x2071, 0x0200, 0x2069, 0x4e40, 0x3d00, 0xd08c, 0x0040, 0x1466,
- 0x70ec, 0xa084, 0x1c00, 0x78e2, 0x1078, 0x4cdd, 0x3d00, 0xd084,
- 0x0040, 0x1474, 0x2069, 0x4e80, 0x2071, 0x0100, 0x70ec, 0xa084,
- 0x1c00, 0x78e6, 0x1078, 0x4cdd, 0x0f7f, 0x0e7f, 0x0d7f, 0x127f,
+ 0x29d1, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c, 0x007e,
+ 0x107e, 0x127e, 0x2091, 0x2300, 0x1078, 0x29d1, 0x2091, 0x2400,
+ 0x1078, 0x29d1, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c,
+ 0x007e, 0x107e, 0x127e, 0x0d7e, 0x0e7e, 0x0f7e, 0x2079, 0x4f00,
+ 0x2071, 0x0200, 0x2069, 0x4f40, 0x3d00, 0xd08c, 0x0040, 0x1466,
+ 0x70ec, 0xa084, 0x1c00, 0x78e2, 0x1078, 0x4db0, 0x3d00, 0xd084,
+ 0x0040, 0x1474, 0x2069, 0x4f80, 0x2071, 0x0100, 0x70ec, 0xa084,
+ 0x1c00, 0x78e6, 0x1078, 0x4db0, 0x0f7f, 0x0e7f, 0x0d7f, 0x127f,
0x107f, 0x007f, 0x007c, 0x7008, 0x800b, 0x00c8, 0x1489, 0x7007,
0x0002, 0xa08c, 0x01e0, 0x00c0, 0x148a, 0xd09c, 0x0040, 0x1489,
- 0x087a, 0x097a, 0x70c3, 0x4002, 0x0078, 0x15bd, 0x0068, 0x1513,
- 0x2061, 0x0000, 0x6018, 0xd084, 0x00c0, 0x1513, 0x7828, 0xa005,
- 0x00c0, 0x149e, 0x0010, 0x1514, 0x0078, 0x1513, 0x7910, 0xd1f4,
- 0x0040, 0x14a6, 0x2001, 0x4007, 0x0078, 0x15bc, 0x7914, 0xd1ec,
- 0x0040, 0x14c1, 0xd0fc, 0x0040, 0x14b7, 0x007e, 0x1078, 0x1d64,
- 0x007f, 0x0040, 0x14c1, 0x2001, 0x4007, 0x0078, 0x15bc, 0x007e,
- 0x1078, 0x1d54, 0x007f, 0x0040, 0x14c1, 0x2001, 0x4007, 0x0078,
- 0x15bc, 0x7910, 0xd0fc, 0x00c0, 0x14cb, 0x2061, 0x4e40, 0xc19c,
- 0xc7fc, 0x0078, 0x14cf, 0x2061, 0x4e80, 0xc19d, 0xc7fd, 0x6064,
- 0xa005, 0x00c0, 0x1513, 0x7912, 0x6083, 0x0000, 0x7828, 0xc0fc,
- 0xa086, 0x0018, 0x00c0, 0x14e0, 0x0c7e, 0x1078, 0x1b5b, 0x0c7f,
- 0x782b, 0x0000, 0x607c, 0xa065, 0x0040, 0x14f9, 0x0c7e, 0x609c,
- 0x1078, 0x1e49, 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1c84, 0x2009,
- 0x0018, 0x6087, 0x0103, 0x1078, 0x1d74, 0x00c0, 0x150d, 0x1078,
- 0x1dc6, 0x7810, 0xd09c, 0x00c0, 0x1501, 0x2061, 0x4e40, 0x0078,
- 0x1505, 0x2061, 0x4e80, 0xc09c, 0x7812, 0x607f, 0x0000, 0x60d4,
- 0xd0dc, 0x0040, 0x1511, 0xc0dc, 0x60d6, 0x2001, 0x4005, 0x0078,
- 0x15bc, 0x0078, 0x15ba, 0x007c, 0x7810, 0xd0f4, 0x0040, 0x151c,
- 0x2001, 0x4007, 0x0078, 0x15bc, 0xa006, 0x70c2, 0x70c6, 0x70ca,
- 0x70ce, 0x70da, 0x70c0, 0xa03d, 0xa08a, 0x0040, 0x00c8, 0x152a,
- 0x0079, 0x1531, 0x2100, 0xa08a, 0x0040, 0x00c8, 0x15c8, 0x0079,
- 0x1571, 0x15ba, 0x1610, 0x15d9, 0x1648, 0x1680, 0x1680, 0x15d0,
- 0x1c9c, 0x168b, 0x15c8, 0x15dd, 0x15df, 0x15e1, 0x15e3, 0x1ca1,
- 0x15c8, 0x1699, 0x16f6, 0x1b7b, 0x1c96, 0x15e5, 0x19c0, 0x1a02,
- 0x1a3d, 0x1a8e, 0x197b, 0x1988, 0x199c, 0x19af, 0x17cb, 0x15c8,
- 0x172d, 0x173a, 0x1746, 0x1752, 0x1768, 0x1774, 0x1777, 0x1783,
- 0x178f, 0x1797, 0x17b3, 0x17bf, 0x15c8, 0x15c8, 0x15c8, 0x15c8,
- 0x17d8, 0x17ea, 0x1806, 0x183c, 0x1864, 0x1874, 0x1877, 0x18a8,
- 0x18d9, 0x18eb, 0x194a, 0x195a, 0x15c8, 0x15c8, 0x15c8, 0x15c8,
- 0x196a, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x1cc6, 0x1ccc,
- 0x15c8, 0x15c8, 0x15c8, 0x1cd0, 0x1d15, 0x15c8, 0x15c8, 0x15c8,
- 0x15c8, 0x160a, 0x167a, 0x1693, 0x16f0, 0x1b75, 0x15c8, 0x15c8,
- 0x1b3e, 0x15c8, 0x1d19, 0x1cb8, 0x1cc2, 0x15c8, 0x15c8, 0x15c8,
- 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8,
- 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8,
- 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8,
- 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8,
- 0x15c8, 0x72ca, 0x71c6, 0x2001, 0x4006, 0x0078, 0x15bc, 0x73ce,
- 0x72ca, 0x71c6, 0x2001, 0x4000, 0x70c2, 0x0068, 0x15bd, 0x2061,
- 0x0000, 0x601b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x007c,
- 0x70c3, 0x4001, 0x0078, 0x15bd, 0x70c3, 0x4006, 0x0078, 0x15bd,
- 0x2099, 0x0041, 0x20a1, 0x0041, 0x20a9, 0x0005, 0x53a3, 0x0078,
- 0x15ba, 0x70c4, 0x70c3, 0x0004, 0x007a, 0x0078, 0x15ba, 0x0078,
- 0x15ba, 0x0078, 0x15ba, 0x0078, 0x15ba, 0x2091, 0x8000, 0x70c3,
- 0x0004, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3,
- 0x0008, 0x2001, 0x000f, 0x70d6, 0x2079, 0x0000, 0x781b, 0x0001,
- 0x2031, 0x0030, 0x2059, 0x1000, 0x2029, 0x041a, 0x2051, 0x0445,
- 0x2061, 0x0447, 0x20c1, 0x0020, 0x2091, 0x5000, 0x2091, 0x4080,
- 0x0078, 0x0418, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0078, 0x1613,
- 0x2029, 0x0000, 0x2520, 0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x20a0,
- 0x2099, 0x0030, 0x7003, 0x0001, 0x7007, 0x0006, 0x731a, 0x721e,
- 0x7422, 0x7526, 0x2021, 0x0040, 0x81ff, 0x0040, 0x15ba, 0xa182,
- 0x0040, 0x00c8, 0x162d, 0x2120, 0xa006, 0x2008, 0x8403, 0x7012,
- 0x7007, 0x0004, 0x7007, 0x0001, 0x7008, 0xd0fc, 0x0040, 0x1634,
- 0x7007, 0x0002, 0xa084, 0x01e0, 0x0040, 0x1642, 0x70c3, 0x4002,
- 0x0078, 0x15bd, 0x24a8, 0x53a5, 0x0078, 0x1624, 0x0078, 0x15ba,
- 0x2029, 0x0000, 0x2520, 0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x2098,
- 0x20a1, 0x0030, 0x7003, 0x0000, 0x7007, 0x0006, 0x731a, 0x721e,
- 0x7422, 0x7526, 0x2021, 0x0040, 0x7007, 0x0006, 0x81ff, 0x0040,
- 0x15ba, 0xa182, 0x0040, 0x00c8, 0x1667, 0x2120, 0xa006, 0x2008,
- 0x8403, 0x7012, 0x24a8, 0x53a6, 0x7007, 0x0001, 0x7008, 0xd0fc,
- 0x0040, 0x166e, 0xa084, 0x01e0, 0x0040, 0x165c, 0x70c3, 0x4002,
- 0x0078, 0x15bd, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0078, 0x164b,
- 0x71c4, 0x70c8, 0x2114, 0xa79e, 0x0004, 0x00c0, 0x1688, 0x200a,
- 0x72ca, 0x0078, 0x15b9, 0x70c7, 0x0008, 0x70cb, 0x000f, 0x70cf,
- 0x0000, 0x0078, 0x15ba, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0078,
- 0x169c, 0x2029, 0x0000, 0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d0,
- 0x70c6, 0x72ca, 0x73ce, 0x74d2, 0xa005, 0x0040, 0x16eb, 0xa40a,
- 0x0040, 0x16ac, 0x00c8, 0x16b5, 0x8001, 0x7872, 0xa084, 0xfc00,
- 0x0040, 0x16b9, 0x78ac, 0xc085, 0x78ae, 0x2001, 0x4005, 0x0078,
- 0x15bc, 0x7b7e, 0x7a7a, 0x7e86, 0x7d82, 0x7c76, 0xa48c, 0xff00,
- 0x0040, 0x16d1, 0x8407, 0x8004, 0x8004, 0x810c, 0x810c, 0x810f,
- 0xa118, 0xa291, 0x0000, 0xa6b1, 0x0000, 0xa581, 0x0000, 0x0078,
- 0x16db, 0x8407, 0x8004, 0x8004, 0xa318, 0xa291, 0x0000, 0xa6b1,
- 0x0000, 0xa581, 0x0000, 0x731a, 0x721e, 0x7622, 0x7026, 0xa605,
- 0x0040, 0x16e5, 0x7a10, 0xc2c5, 0x7a12, 0x78ac, 0xa084, 0xfffc,
- 0x78ae, 0x0078, 0x16ee, 0x78ac, 0xc085, 0x78ae, 0x0078, 0x15ba,
- 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0078, 0x16f9, 0x2029, 0x0000,
- 0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d4, 0x70c6, 0x72ca, 0x73ce,
- 0x74d6, 0xa005, 0x0040, 0x1728, 0xa40a, 0x0040, 0x1709, 0x00c8,
- 0x15bc, 0x8001, 0x7892, 0xa084, 0xfc00, 0x0040, 0x1716, 0x78ac,
- 0xc0c5, 0x78ae, 0x2001, 0x4005, 0x0078, 0x15bc, 0x7a9a, 0x7b9e,
- 0x7da2, 0x7ea6, 0x2600, 0xa505, 0x0040, 0x1721, 0x7a10, 0xc2c5,
- 0x7a12, 0x7c96, 0x78ac, 0xa084, 0xfcff, 0x78ae, 0x0078, 0x172b,
- 0x78ac, 0xc0c5, 0x78ae, 0x0078, 0x15ba, 0x2009, 0x0000, 0x786c,
- 0xa065, 0x0040, 0x1737, 0x8108, 0x6000, 0x0078, 0x1730, 0x7ac4,
- 0x0078, 0x15b8, 0x2009, 0x4e48, 0x210c, 0x7810, 0xd0ec, 0x00c0,
- 0x15b9, 0x2011, 0x4e88, 0x2214, 0x0078, 0x15b8, 0x2009, 0x4e49,
- 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x15b9, 0x2011, 0x4e89, 0x2214,
- 0x0078, 0x15b8, 0x2061, 0x4e40, 0x6128, 0x622c, 0x8214, 0x8214,
- 0x8214, 0x7810, 0xd0ec, 0x00c0, 0x1766, 0x2061, 0x4e80, 0x6328,
- 0x73da, 0x632c, 0x831c, 0x831c, 0x831c, 0x73de, 0x0078, 0x15b8,
- 0x2009, 0x4e4c, 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x15b9, 0x2011,
- 0x4e8c, 0x2214, 0x0078, 0x15b8, 0x7918, 0x0078, 0x15b9, 0x2009,
- 0x4e4d, 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x15b9, 0x2011, 0x4e8d,
- 0x2214, 0x0078, 0x15b8, 0x2009, 0x4e4e, 0x210c, 0x7810, 0xd0ec,
- 0x00c0, 0x15b9, 0x2011, 0x4e8e, 0x2214, 0x0078, 0x15b8, 0x7920,
- 0x7810, 0xd0ec, 0x00c0, 0x15b9, 0x7a24, 0x0078, 0x15b8, 0x71c4,
- 0xd1fc, 0x00c0, 0x179f, 0x2011, 0x52c0, 0x0078, 0x17a1, 0x2011,
- 0x5340, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa268,
- 0x6a00, 0x6804, 0xd09c, 0x0040, 0x17b0, 0x6b08, 0x0078, 0x17b1,
- 0x6b0c, 0x0078, 0x15b7, 0x77c4, 0x1078, 0x1de4, 0x2091, 0x8000,
- 0x6b1c, 0x6a14, 0x2091, 0x8001, 0x2708, 0x0078, 0x15b7, 0x2061,
- 0x4e40, 0x6118, 0x7810, 0xd0ec, 0x00c0, 0x15b9, 0x2061, 0x4e80,
- 0x6218, 0x0078, 0x15b8, 0x77c4, 0x1078, 0x1de4, 0x2091, 0x8000,
- 0x6908, 0x6a18, 0x6b10, 0x77da, 0x2091, 0x8001, 0x0078, 0x15b7,
- 0x71c4, 0x2110, 0xa294, 0x000f, 0xa282, 0x0010, 0x00c8, 0x15b2,
- 0x1078, 0x277f, 0xa384, 0x4000, 0x0040, 0x17e8, 0xa295, 0x0020,
- 0x0078, 0x15b7, 0x71c4, 0x2100, 0xc0bc, 0xa082, 0x0010, 0x00c8,
- 0x15b2, 0xd1bc, 0x00c0, 0x17f9, 0x2011, 0x4e48, 0x2204, 0x0078,
- 0x17fd, 0x2011, 0x4e88, 0x2204, 0xc0bd, 0x007e, 0x2100, 0xc0bc,
- 0x2012, 0x1078, 0x26dc, 0x017f, 0x0078, 0x15b9, 0x71c4, 0x2021,
- 0x4e49, 0x2404, 0x70c6, 0x2019, 0x0000, 0x0078, 0x1815, 0x71c8,
- 0x2021, 0x4e89, 0x2404, 0x70ca, 0xc3fd, 0x2011, 0x1834, 0x20a9,
- 0x0008, 0x2204, 0xa106, 0x0040, 0x1824, 0x8210, 0x00f0, 0x1819,
- 0x71c4, 0x72c8, 0x0078, 0x15b1, 0xa292, 0x1834, 0x027e, 0x2122,
- 0x017f, 0x1078, 0x26fd, 0x7810, 0xd0ec, 0x00c0, 0x1832, 0xd3fc,
- 0x0040, 0x180f, 0x0078, 0x15ba, 0x03e8, 0x00fa, 0x01f4, 0x02ee,
- 0x0004, 0x0001, 0x0002, 0x0003, 0x2061, 0x4e40, 0x6128, 0x622c,
+ 0x087a, 0x097a, 0x70c3, 0x4002, 0x0078, 0x15c4, 0x0068, 0x151a,
+ 0x2061, 0x0000, 0x6018, 0xd084, 0x00c0, 0x151a, 0x7828, 0xa005,
+ 0x00c0, 0x149e, 0x0010, 0x151b, 0x0078, 0x151a, 0x7910, 0xd1f4,
+ 0x0040, 0x14a4, 0x0078, 0x14b9, 0x7914, 0xd1ec, 0x0040, 0x14bd,
+ 0xd0fc, 0x0040, 0x14b3, 0x007e, 0x1078, 0x1dae, 0x007f, 0x0040,
+ 0x14bd, 0x0078, 0x14b9, 0x007e, 0x1078, 0x1da1, 0x007f, 0x0040,
+ 0x14bd, 0x2001, 0x4007, 0x0078, 0x15c3, 0x7910, 0xd0fc, 0x00c0,
+ 0x14c7, 0x2061, 0x4f40, 0xc19c, 0xc7fc, 0x0078, 0x14cb, 0x2061,
+ 0x4f80, 0xc19d, 0xc7fd, 0x6064, 0xa005, 0x00c0, 0x151a, 0x7912,
+ 0x6082, 0x7828, 0xc0fc, 0xa086, 0x0018, 0x00c0, 0x14db, 0x0c7e,
+ 0x1078, 0x1b85, 0x0c7f, 0x782b, 0x0000, 0x607c, 0xa065, 0x0040,
+ 0x1500, 0x0c7e, 0x609c, 0x1078, 0x1e90, 0x0c7f, 0x609f, 0x0000,
+ 0x1078, 0x1cd5, 0x2009, 0x0018, 0x6087, 0x0103, 0x7810, 0x007e,
+ 0x84ff, 0x00c0, 0x14f6, 0x85ff, 0x0040, 0x14f8, 0xc0c5, 0x7812,
+ 0x1078, 0x1dbb, 0x007f, 0x7812, 0x00c0, 0x1514, 0x1078, 0x1e0d,
+ 0x7810, 0xd09c, 0x00c0, 0x1508, 0x2061, 0x4f40, 0x0078, 0x150c,
+ 0x2061, 0x4f80, 0xc09c, 0x7812, 0x607f, 0x0000, 0x60d4, 0xd0dc,
+ 0x0040, 0x1518, 0xc0dc, 0x60d6, 0x2001, 0x4005, 0x0078, 0x15c3,
+ 0x0078, 0x15c1, 0x007c, 0x7810, 0xd0f4, 0x0040, 0x1523, 0x2001,
+ 0x4007, 0x0078, 0x15c3, 0xa006, 0x70c2, 0x70c6, 0x70ca, 0x70ce,
+ 0x70da, 0x70c0, 0xa03d, 0xa08a, 0x0040, 0x00c8, 0x1531, 0x0079,
+ 0x1538, 0x2100, 0xa08a, 0x0040, 0x00c8, 0x15cf, 0x0079, 0x1578,
+ 0x15c1, 0x1617, 0x15e0, 0x164f, 0x1687, 0x1687, 0x15d7, 0x1ced,
+ 0x1692, 0x15cf, 0x15e4, 0x15e6, 0x15e8, 0x15ea, 0x1cf2, 0x15cf,
+ 0x16a0, 0x16fd, 0x1ba5, 0x1ce7, 0x15ec, 0x19ea, 0x1a2c, 0x1a67,
+ 0x1ab8, 0x19a5, 0x19b2, 0x19c6, 0x19d9, 0x17eb, 0x15cf, 0x1734,
+ 0x1741, 0x174d, 0x1759, 0x176f, 0x177b, 0x177e, 0x178a, 0x1796,
+ 0x179e, 0x17d3, 0x17df, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x17f8,
+ 0x180a, 0x1826, 0x185c, 0x1884, 0x1894, 0x1897, 0x18c8, 0x18f9,
+ 0x190b, 0x1974, 0x1984, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x1994,
+ 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x1d17, 0x1d1d, 0x15cf,
+ 0x15cf, 0x15cf, 0x1d21, 0x1d66, 0x15cf, 0x15cf, 0x15cf, 0x15cf,
+ 0x1611, 0x1681, 0x169a, 0x16f7, 0x1b9f, 0x15cf, 0x15cf, 0x1b68,
+ 0x15cf, 0x1d6a, 0x1d09, 0x1d13, 0x15cf, 0x15cf, 0x15cf, 0x15cf,
+ 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf,
+ 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf,
+ 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf,
+ 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf,
+ 0x72ca, 0x71c6, 0x2001, 0x4006, 0x0078, 0x15c3, 0x73ce, 0x72ca,
+ 0x71c6, 0x2001, 0x4000, 0x70c2, 0x0068, 0x15c4, 0x2061, 0x0000,
+ 0x601b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x007c, 0x70c3,
+ 0x4001, 0x0078, 0x15c4, 0x70c3, 0x4006, 0x0078, 0x15c4, 0x2099,
+ 0x0041, 0x20a1, 0x0041, 0x20a9, 0x0005, 0x53a3, 0x0078, 0x15c1,
+ 0x70c4, 0x70c3, 0x0004, 0x007a, 0x0078, 0x15c1, 0x0078, 0x15c1,
+ 0x0078, 0x15c1, 0x0078, 0x15c1, 0x2091, 0x8000, 0x70c3, 0x0004,
+ 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3, 0x0008,
+ 0x2001, 0x000f, 0x70d6, 0x2079, 0x0000, 0x781b, 0x0001, 0x2031,
+ 0x0030, 0x2059, 0x1000, 0x2029, 0x041a, 0x2051, 0x0445, 0x2061,
+ 0x0447, 0x20c1, 0x0020, 0x2091, 0x5000, 0x2091, 0x4080, 0x0078,
+ 0x0418, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0078, 0x161a, 0x2029,
+ 0x0000, 0x2520, 0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x20a0, 0x2099,
+ 0x0030, 0x7003, 0x0001, 0x7007, 0x0006, 0x731a, 0x721e, 0x7422,
+ 0x7526, 0x2021, 0x0040, 0x81ff, 0x0040, 0x15c1, 0xa182, 0x0040,
+ 0x00c8, 0x1634, 0x2120, 0xa006, 0x2008, 0x8403, 0x7012, 0x7007,
+ 0x0004, 0x7007, 0x0001, 0x7008, 0xd0fc, 0x0040, 0x163b, 0x7007,
+ 0x0002, 0xa084, 0x01e0, 0x0040, 0x1649, 0x70c3, 0x4002, 0x0078,
+ 0x15c4, 0x24a8, 0x53a5, 0x0078, 0x162b, 0x0078, 0x15c1, 0x2029,
+ 0x0000, 0x2520, 0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x2098, 0x20a1,
+ 0x0030, 0x7003, 0x0000, 0x7007, 0x0006, 0x731a, 0x721e, 0x7422,
+ 0x7526, 0x2021, 0x0040, 0x7007, 0x0006, 0x81ff, 0x0040, 0x15c1,
+ 0xa182, 0x0040, 0x00c8, 0x166e, 0x2120, 0xa006, 0x2008, 0x8403,
+ 0x7012, 0x24a8, 0x53a6, 0x7007, 0x0001, 0x7008, 0xd0fc, 0x0040,
+ 0x1675, 0xa084, 0x01e0, 0x0040, 0x1663, 0x70c3, 0x4002, 0x0078,
+ 0x15c4, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0078, 0x1652, 0x71c4,
+ 0x70c8, 0x2114, 0xa79e, 0x0004, 0x00c0, 0x168f, 0x200a, 0x72ca,
+ 0x0078, 0x15c0, 0x70c7, 0x0008, 0x70cb, 0x000f, 0x70cf, 0x000b,
+ 0x0078, 0x15c1, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0078, 0x16a3,
+ 0x2029, 0x0000, 0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d0, 0x70c6,
+ 0x72ca, 0x73ce, 0x74d2, 0xa005, 0x0040, 0x16f2, 0xa40a, 0x0040,
+ 0x16b3, 0x00c8, 0x16bc, 0x8001, 0x7872, 0xa084, 0xfc00, 0x0040,
+ 0x16c0, 0x78ac, 0xc085, 0x78ae, 0x2001, 0x4005, 0x0078, 0x15c3,
+ 0x7b7e, 0x7a7a, 0x7e86, 0x7d82, 0x7c76, 0xa48c, 0xff00, 0x0040,
+ 0x16d8, 0x8407, 0x8004, 0x8004, 0x810c, 0x810c, 0x810f, 0xa118,
+ 0xa291, 0x0000, 0xa6b1, 0x0000, 0xa581, 0x0000, 0x0078, 0x16e2,
+ 0x8407, 0x8004, 0x8004, 0xa318, 0xa291, 0x0000, 0xa6b1, 0x0000,
+ 0xa581, 0x0000, 0x731a, 0x721e, 0x7622, 0x7026, 0xa605, 0x0040,
+ 0x16ec, 0x7a10, 0xc2c5, 0x7a12, 0x78ac, 0xa084, 0xfffc, 0x78ae,
+ 0x0078, 0x16f5, 0x78ac, 0xc085, 0x78ae, 0x0078, 0x15c1, 0x75d8,
+ 0x76dc, 0x75da, 0x76de, 0x0078, 0x1700, 0x2029, 0x0000, 0x2530,
+ 0x70c4, 0x72c8, 0x73cc, 0x74d4, 0x70c6, 0x72ca, 0x73ce, 0x74d6,
+ 0xa005, 0x0040, 0x172f, 0xa40a, 0x0040, 0x1710, 0x00c8, 0x1719,
+ 0x8001, 0x7892, 0xa084, 0xfc00, 0x0040, 0x171d, 0x78ac, 0xc0c5,
+ 0x78ae, 0x2001, 0x4005, 0x0078, 0x15c3, 0x7a9a, 0x7b9e, 0x7da2,
+ 0x7ea6, 0x2600, 0xa505, 0x0040, 0x1728, 0x7a10, 0xc2c5, 0x7a12,
+ 0x7c96, 0x78ac, 0xa084, 0xfcff, 0x78ae, 0x0078, 0x1732, 0x78ac,
+ 0xc0c5, 0x78ae, 0x0078, 0x15c1, 0x2009, 0x0000, 0x786c, 0xa065,
+ 0x0040, 0x173e, 0x8108, 0x6000, 0x0078, 0x1737, 0x7ac4, 0x0078,
+ 0x15bf, 0x2009, 0x4f48, 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x15c0,
+ 0x2011, 0x4f88, 0x2214, 0x0078, 0x15bf, 0x2009, 0x4f49, 0x210c,
+ 0x7810, 0xd0ec, 0x00c0, 0x15c0, 0x2011, 0x4f89, 0x2214, 0x0078,
+ 0x15bf, 0x2061, 0x4f40, 0x6128, 0x622c, 0x8214, 0x8214, 0x8214,
+ 0x7810, 0xd0ec, 0x00c0, 0x176d, 0x2061, 0x4f80, 0x6328, 0x73da,
+ 0x632c, 0x831c, 0x831c, 0x831c, 0x73de, 0x0078, 0x15bf, 0x2009,
+ 0x4f4c, 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x15c0, 0x2011, 0x4f8c,
+ 0x2214, 0x0078, 0x15bf, 0x7918, 0x0078, 0x15c0, 0x2009, 0x4f4d,
+ 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x15c0, 0x2011, 0x4f8d, 0x2214,
+ 0x0078, 0x15bf, 0x2009, 0x4f4e, 0x210c, 0x7810, 0xd0ec, 0x00c0,
+ 0x15c0, 0x2011, 0x4f8e, 0x2214, 0x0078, 0x15bf, 0x7920, 0x7810,
+ 0xd0ec, 0x00c0, 0x15c0, 0x7a24, 0x0078, 0x15bf, 0x71c4, 0xd1fc,
+ 0x00c0, 0x17a6, 0x2011, 0x53c0, 0x0078, 0x17a8, 0x2011, 0x5440,
+ 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa268, 0x6a00,
+ 0x6804, 0xd09c, 0x0040, 0x17b7, 0x6b08, 0x0078, 0x17b8, 0x6b0c,
+ 0xd1fc, 0x00c0, 0x17bf, 0x2021, 0x023b, 0x0078, 0x17c1, 0x2021,
+ 0x013b, 0x2424, 0x7914, 0xd1e4, 0x0040, 0x17cd, 0xd4c4, 0x00c0,
+ 0x17cc, 0xc4d5, 0x0078, 0x17cd, 0xc4dd, 0xa4a4, 0x1c00, 0x74de,
+ 0x71c4, 0x0078, 0x15be, 0x77c4, 0x1078, 0x1e2b, 0x2091, 0x8000,
+ 0x6b1c, 0x6a14, 0x2091, 0x8001, 0x2708, 0x0078, 0x15be, 0x2061,
+ 0x4f40, 0x6118, 0x7810, 0xd0ec, 0x00c0, 0x15c0, 0x2061, 0x4f80,
+ 0x6218, 0x0078, 0x15bf, 0x77c4, 0x1078, 0x1e2b, 0x2091, 0x8000,
+ 0x6908, 0x6a18, 0x6b10, 0x77da, 0x2091, 0x8001, 0x0078, 0x15be,
+ 0x71c4, 0x2110, 0xa294, 0x000f, 0xa282, 0x0010, 0x00c8, 0x15b9,
+ 0x1078, 0x27c6, 0xa384, 0x4000, 0x0040, 0x1808, 0xa295, 0x0020,
+ 0x0078, 0x15be, 0x71c4, 0x2100, 0xc0bc, 0xa082, 0x0010, 0x00c8,
+ 0x15b9, 0xd1bc, 0x00c0, 0x1819, 0x2011, 0x4f48, 0x2204, 0x0078,
+ 0x181d, 0x2011, 0x4f88, 0x2204, 0xc0bd, 0x007e, 0x2100, 0xc0bc,
+ 0x2012, 0x1078, 0x2723, 0x017f, 0x0078, 0x15c0, 0x71c4, 0x2021,
+ 0x4f49, 0x2404, 0x70c6, 0x2019, 0x0000, 0x0078, 0x1835, 0x71c8,
+ 0x2021, 0x4f89, 0x2404, 0x70ca, 0xc3fd, 0x2011, 0x1854, 0x20a9,
+ 0x0008, 0x2204, 0xa106, 0x0040, 0x1844, 0x8210, 0x00f0, 0x1839,
+ 0x71c4, 0x72c8, 0x0078, 0x15b8, 0xa292, 0x1854, 0x027e, 0x2122,
+ 0x017f, 0x1078, 0x2744, 0x7810, 0xd0ec, 0x00c0, 0x1852, 0xd3fc,
+ 0x0040, 0x182f, 0x0078, 0x15c1, 0x03e8, 0x00fa, 0x01f4, 0x02ee,
+ 0x0004, 0x0001, 0x0002, 0x0003, 0x2061, 0x4f40, 0x6128, 0x622c,
0x8214, 0x8214, 0x8214, 0x70c4, 0x602a, 0x70c8, 0x8003, 0x8003,
- 0x8003, 0x602e, 0x7810, 0xd0ec, 0x00c0, 0x1862, 0x027e, 0x017e,
- 0x2061, 0x4e80, 0x6128, 0x622c, 0x8214, 0x8214, 0x8214, 0x70d8,
+ 0x8003, 0x602e, 0x7810, 0xd0ec, 0x00c0, 0x1882, 0x027e, 0x017e,
+ 0x2061, 0x4f80, 0x6128, 0x622c, 0x8214, 0x8214, 0x8214, 0x70d8,
0x602a, 0x70dc, 0x8003, 0x8003, 0x8003, 0x602e, 0x71da, 0x72de,
- 0x017f, 0x027f, 0x0078, 0x15b8, 0x2061, 0x4e40, 0x6130, 0x70c4,
- 0x6032, 0x7810, 0xd0ec, 0x00c0, 0x15b9, 0x2061, 0x4e80, 0x6230,
- 0x70c8, 0x6032, 0x0078, 0x15b8, 0x7918, 0x0078, 0x15b9, 0x71c4,
- 0xa184, 0xffcf, 0x0040, 0x1883, 0x7810, 0xd0ec, 0x00c0, 0x15b2,
- 0x72c8, 0x0078, 0x15b1, 0x2011, 0x4e4d, 0x2204, 0x2112, 0x007e,
- 0x2019, 0x0000, 0x1078, 0x2764, 0x7810, 0xd0ec, 0x0040, 0x1893,
- 0x017f, 0x0078, 0x15b9, 0x71c8, 0xa184, 0xffcf, 0x0040, 0x189c,
- 0x2110, 0x71c4, 0x0078, 0x15b1, 0x2011, 0x4e8d, 0x2204, 0x2112,
- 0x007e, 0xc3fd, 0x1078, 0x2764, 0x027f, 0x017f, 0x0078, 0x15b8,
- 0x71c4, 0xa182, 0x0010, 0x0048, 0x18b4, 0x7810, 0xd0ec, 0x00c0,
- 0x15b2, 0x72c8, 0x0078, 0x15b1, 0x2011, 0x4e4e, 0x2204, 0x007e,
- 0x2112, 0x2019, 0x0000, 0x1078, 0x2742, 0x7810, 0xd0ec, 0x0040,
- 0x18c4, 0x017f, 0x0078, 0x15b9, 0x71c8, 0xa182, 0x0010, 0x0048,
- 0x18cd, 0x2110, 0x71c4, 0x0078, 0x15b1, 0x2011, 0x4e8e, 0x2204,
- 0x007e, 0x2112, 0xc3fd, 0x1078, 0x2742, 0x027f, 0x017f, 0x0078,
- 0x15b8, 0x71c4, 0x72c8, 0xa184, 0xfffd, 0x00c0, 0x15b1, 0xa284,
- 0xfffd, 0x00c0, 0x15b1, 0x2100, 0x7920, 0x7822, 0x2200, 0x7a24,
- 0x7826, 0x0078, 0x15b8, 0x71c4, 0xd1fc, 0x00c0, 0x18f3, 0x2011,
- 0x52c0, 0x0078, 0x18f5, 0x2011, 0x5340, 0x8107, 0xa084, 0x000f,
- 0x8003, 0x8003, 0x8003, 0xa268, 0x2019, 0x0000, 0x72c8, 0x2091,
- 0x8000, 0x6800, 0x007e, 0xa226, 0x0040, 0x191e, 0x6a02, 0xd4ec,
- 0x0040, 0x190b, 0xc3a5, 0xd4e4, 0x0040, 0x190f, 0xc39d, 0xd4f4,
- 0x0040, 0x191e, 0x810f, 0xd2f4, 0x0040, 0x191a, 0x1078, 0x27c1,
- 0x0078, 0x191e, 0x1078, 0x279f, 0x0078, 0x191e, 0x72cc, 0x6808,
- 0xa206, 0x0040, 0x1940, 0xa2a4, 0x00ff, 0x7814, 0xd0e4, 0x00c0,
- 0x1931, 0xa482, 0x0028, 0x0048, 0x193d, 0x0040, 0x193d, 0x0078,
- 0x1935, 0xa482, 0x0043, 0x0048, 0x193d, 0x71c4, 0x71c6, 0x027f,
- 0x72ca, 0x2091, 0x8001, 0x0078, 0x15b3, 0x6a0a, 0xa39d, 0x000a,
- 0x6804, 0xa305, 0x6806, 0x027f, 0x6b0c, 0x71c4, 0x2091, 0x8001,
- 0x0078, 0x15b7, 0x77c4, 0x1078, 0x1de4, 0x2091, 0x8000, 0x6a14,
- 0x6b1c, 0x2091, 0x8001, 0x70c8, 0x6816, 0x70cc, 0x681e, 0x2708,
- 0x0078, 0x15b7, 0x70c4, 0x2061, 0x4e40, 0x6118, 0x601a, 0x7810,
- 0xd0ec, 0x00c0, 0x15b9, 0x70c8, 0x2061, 0x4e80, 0x6218, 0x601a,
- 0x0078, 0x15b8, 0x71c4, 0x72c8, 0x73cc, 0xa182, 0x0010, 0x00c8,
- 0x15b2, 0x1078, 0x27e3, 0xa384, 0x4000, 0x0040, 0x1979, 0xa295,
- 0x0020, 0x0078, 0x15b7, 0x77c4, 0x1078, 0x1de4, 0x2091, 0x8000,
- 0x6a08, 0xc28d, 0x6a0a, 0x2091, 0x8001, 0x2708, 0x0078, 0x15b8,
- 0x77c4, 0x1078, 0x1de4, 0x2091, 0x8000, 0x6a08, 0xa294, 0xfff9,
- 0x6a0a, 0x6804, 0xa005, 0x0040, 0x1997, 0x1078, 0x2628, 0x2091,
- 0x8001, 0x2708, 0x0078, 0x15b8, 0x77c4, 0x1078, 0x1de4, 0x2091,
- 0x8000, 0x6a08, 0xc295, 0x6a0a, 0x6804, 0xa005, 0x0040, 0x19aa,
- 0x1078, 0x2628, 0x2091, 0x8001, 0x2708, 0x0078, 0x15b8, 0x77c4,
- 0x2041, 0x0001, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000,
- 0x1078, 0x1dff, 0x2091, 0x8001, 0x2708, 0x6a08, 0x0078, 0x15b8,
- 0x77c4, 0x7814, 0xd0e4, 0x00c0, 0x19d4, 0xd7fc, 0x0040, 0x19ce,
- 0x1078, 0x1d64, 0x0040, 0x19d4, 0x0078, 0x15bc, 0x1078, 0x1d54,
- 0x0040, 0x19d4, 0x0078, 0x15bc, 0x73c8, 0x72cc, 0x77c6, 0x73ca,
- 0x72ce, 0x1078, 0x1e86, 0x00c0, 0x19fe, 0x6818, 0xa005, 0x0040,
- 0x19f8, 0x2708, 0x077e, 0x1078, 0x2813, 0x077f, 0x00c0, 0x19f8,
- 0x2001, 0x0015, 0xd7fc, 0x00c0, 0x19f1, 0x2061, 0x4e40, 0x0078,
- 0x19f4, 0xc0fd, 0x2061, 0x4e80, 0x782a, 0x2091, 0x8001, 0x007c,
- 0x2091, 0x8001, 0x2001, 0x4005, 0x0078, 0x15bc, 0x2091, 0x8001,
- 0x0078, 0x15ba, 0x77c4, 0x7814, 0xd0e4, 0x00c0, 0x1a16, 0xd7fc,
- 0x0040, 0x1a10, 0x1078, 0x1d64, 0x0040, 0x1a16, 0x0078, 0x15bc,
- 0x1078, 0x1d54, 0x0040, 0x1a16, 0x0078, 0x15bc, 0x77c6, 0x2041,
- 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x1078,
- 0x1dff, 0x2009, 0x0016, 0xd7fc, 0x00c0, 0x1a2a, 0x2061, 0x4e40,
- 0x0078, 0x1a2d, 0x2061, 0x4e80, 0xc1fd, 0x6067, 0x0003, 0x607f,
- 0x0000, 0x6776, 0x6083, 0x000f, 0x792a, 0x61d4, 0xc1dc, 0x61d6,
- 0x1078, 0x2628, 0x2091, 0x8001, 0x007c, 0x77c8, 0x77ca, 0x77c4,
- 0x77c6, 0x7814, 0xd0e4, 0x00c0, 0x1a54, 0xd7fc, 0x0040, 0x1a4e,
- 0x1078, 0x1d64, 0x0040, 0x1a54, 0x0078, 0x15bc, 0x1078, 0x1d54,
- 0x0040, 0x1a54, 0x0078, 0x15bc, 0xa7bc, 0xff00, 0x2091, 0x8000,
- 0x2009, 0x0017, 0xd7fc, 0x00c0, 0x1a61, 0x2061, 0x4e40, 0x0078,
- 0x1a64, 0x2061, 0x4e80, 0xc1fd, 0x607f, 0x0000, 0x6067, 0x0002,
- 0x6776, 0x6083, 0x000f, 0x792a, 0x61d4, 0xc1dc, 0x61d6, 0x1078,
- 0x2628, 0x2091, 0x8001, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051,
- 0x0010, 0x2091, 0x8000, 0x70c8, 0xa005, 0x0040, 0x1a82, 0x60d4,
- 0xc0fd, 0x60d6, 0x1078, 0x1dff, 0x70c8, 0x6836, 0x8738, 0xa784,
- 0x001f, 0x00c0, 0x1a82, 0x2091, 0x8001, 0x007c, 0x2019, 0x0000,
- 0x7814, 0xd0e4, 0x00c0, 0x1aa4, 0x72c8, 0xd284, 0x0040, 0x1a9e,
- 0x1078, 0x1d64, 0x0040, 0x1aa4, 0x0078, 0x15bc, 0x1078, 0x1d54,
- 0x0040, 0x1aa4, 0x0078, 0x15bc, 0x72c8, 0x72ca, 0x78ac, 0xa084,
- 0x0003, 0x00c0, 0x1acf, 0x2039, 0x0000, 0xd284, 0x0040, 0x1ab1,
- 0xc7fd, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008, 0x1078,
- 0x1de4, 0x2091, 0x8000, 0x6808, 0xc0d4, 0xa80d, 0x690a, 0x2091,
- 0x8001, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1ab7, 0xa7bc, 0xff00,
- 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0, 0x1ab7, 0x2091,
- 0x8000, 0x72c8, 0xd284, 0x00c0, 0x1ae1, 0x7810, 0xd0ec, 0x0040,
- 0x1add, 0x2069, 0x0100, 0x0078, 0x1ae3, 0x2069, 0x0200, 0x0078,
- 0x1ae3, 0x2069, 0x0100, 0x6808, 0xa084, 0xfffd, 0x680a, 0x6830,
- 0xd0b4, 0x0040, 0x1b03, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848,
- 0xd094, 0x0040, 0x1af5, 0x00f0, 0x1aef, 0x684b, 0x0009, 0x20a9,
- 0x0014, 0x6848, 0xd084, 0x0040, 0x1aff, 0x00f0, 0x1af9, 0x20a9,
- 0x00fa, 0x00f0, 0x1b01, 0x2079, 0x4e00, 0x2009, 0x0018, 0x72c8,
- 0xd284, 0x00c0, 0x1b0f, 0x2061, 0x4e40, 0x0078, 0x1b12, 0x2061,
- 0x4e80, 0xc1fd, 0x607f, 0x0000, 0x792a, 0x6067, 0x0001, 0x6083,
- 0x000f, 0x60a7, 0x0000, 0x60a8, 0x60b2, 0x60b6, 0x60d4, 0xd0b4,
- 0x0040, 0x1b2e, 0xc0b4, 0x60d6, 0x0c7e, 0x60b8, 0xa065, 0x6008,
- 0xc0d4, 0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f, 0x60d4, 0xa084,
- 0x77ff, 0x60d6, 0x78ac, 0xc08d, 0x78ae, 0x83ff, 0x0040, 0x1b39,
- 0x007c, 0x681b, 0x0047, 0x2091, 0x8001, 0x007c, 0x73cc, 0x1078,
- 0x1a90, 0x69ec, 0x6a48, 0xa185, 0x1800, 0x684a, 0xa185, 0x0040,
- 0x68ee, 0x73cc, 0x2021, 0x0004, 0x20a9, 0x09ff, 0x00f0, 0x1b4e,
- 0x8421, 0x00c0, 0x1b4c, 0x8319, 0x00c0, 0x1b4a, 0x69ee, 0x6a4a,
- 0x2091, 0x8001, 0x007c, 0xd7fc, 0x00c0, 0x1b62, 0x2069, 0x4e40,
- 0x0078, 0x1b64, 0x2069, 0x4e80, 0x71c4, 0x71c6, 0x6916, 0x81ff,
- 0x00c0, 0x1b6c, 0x68a7, 0x0001, 0x78ac, 0xc08c, 0x78ae, 0xd084,
- 0x00c0, 0x1b74, 0x1078, 0x1ee6, 0x007c, 0x75d8, 0x74dc, 0x75da,
- 0x74de, 0x0078, 0x1b7e, 0x2029, 0x0000, 0x2520, 0x71c4, 0x73c8,
- 0x72cc, 0x71c6, 0x73ca, 0x72ce, 0x2079, 0x4e00, 0x7dde, 0x7cda,
- 0x7bd6, 0x7ad2, 0x1078, 0x1dbd, 0x0040, 0x1c80, 0x20a9, 0x0005,
- 0x20a1, 0x4e14, 0x2091, 0x8000, 0x41a1, 0x2091, 0x8001, 0x2009,
- 0x0040, 0x1078, 0x1fd1, 0x0040, 0x1ba1, 0x1078, 0x1dc6, 0x0078,
- 0x1c80, 0x6004, 0xa08c, 0x00ff, 0xa18e, 0x0009, 0x00c0, 0x1bac,
- 0x007e, 0x1078, 0x2378, 0x007f, 0xa084, 0xff00, 0x8007, 0x8009,
- 0x0040, 0x1c20, 0x0c7e, 0x2c68, 0x1078, 0x1dbd, 0x0040, 0x1bf2,
- 0x2c00, 0x689e, 0x8109, 0x00c0, 0x1bb3, 0x609f, 0x0000, 0x0c7f,
- 0x0c7e, 0x7ddc, 0x7cd8, 0x7bd4, 0x7ad0, 0xa290, 0x0040, 0xa399,
- 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x7dde, 0x7cda, 0x7bd6,
- 0x7ad2, 0x2c68, 0x689c, 0xa065, 0x0040, 0x1c1f, 0x2009, 0x0040,
- 0x1078, 0x1fd1, 0x00c0, 0x1c09, 0x6004, 0xa084, 0x00ff, 0xa086,
- 0x0002, 0x00c0, 0x1bf2, 0x6004, 0xa084, 0x00ff, 0xa086, 0x000a,
- 0x00c0, 0x1bee, 0x017e, 0x1078, 0x2374, 0x017f, 0x2d00, 0x6002,
- 0x0078, 0x1bc1, 0x0c7f, 0x0c7e, 0x609c, 0x1078, 0x1e49, 0x0c7f,
- 0x609f, 0x0000, 0x1078, 0x1c84, 0x2009, 0x0018, 0x6008, 0xc0cd,
- 0x600a, 0x6004, 0x6086, 0x1078, 0x1d74, 0x1078, 0x1dc6, 0x0078,
- 0x1c80, 0x0c7f, 0x0c7e, 0x609c, 0x1078, 0x1e49, 0x0c7f, 0x609f,
- 0x0000, 0x1078, 0x1c84, 0x2009, 0x0018, 0x6087, 0x0103, 0x601b,
- 0x0003, 0x1078, 0x1d74, 0x1078, 0x1dc6, 0x0078, 0x1c80, 0x0c7f,
- 0x7814, 0xd0e4, 0x00c0, 0x1c45, 0x6114, 0xd1fc, 0x0040, 0x1c2e,
- 0x1078, 0x1d64, 0x0040, 0x1c45, 0x0078, 0x1c32, 0x1078, 0x1d54,
- 0x0040, 0x1c45, 0x2029, 0x0000, 0x2520, 0x2009, 0x0018, 0x73c8,
- 0x72cc, 0x6087, 0x0103, 0x601b, 0x0021, 0x1078, 0x1d74, 0x1078,
- 0x1dc6, 0x2001, 0x4007, 0x0078, 0x15bc, 0x74c4, 0x73c8, 0x72cc,
- 0x6014, 0x2091, 0x8000, 0x0e7e, 0x2009, 0x0012, 0xd0fc, 0x00c0,
- 0x1c55, 0x2071, 0x4e40, 0x0078, 0x1c58, 0x2071, 0x4e80, 0xc1fd,
- 0x792a, 0x7067, 0x0005, 0x71d4, 0xc1dc, 0x71d6, 0x736a, 0x726e,
- 0x7472, 0x7076, 0x707b, 0x0000, 0x2c00, 0x707e, 0xa02e, 0x2530,
- 0x611c, 0xa184, 0x0060, 0x0040, 0x1c6f, 0x1078, 0x4632, 0x0e7f,
- 0x6596, 0x65a6, 0x669a, 0x66aa, 0x60af, 0x0000, 0x60b3, 0x0000,
- 0x6714, 0x6023, 0x0000, 0x1078, 0x2628, 0x2091, 0x8001, 0x007c,
- 0x70c3, 0x4005, 0x0078, 0x15bd, 0x20a9, 0x0005, 0x2099, 0x4e14,
- 0x2091, 0x8000, 0x530a, 0x2091, 0x8001, 0x2100, 0xa210, 0xa399,
- 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x007c, 0x71c4, 0x70c7,
- 0x0000, 0x791e, 0x0078, 0x15ba, 0x71c4, 0x71c6, 0x2168, 0x0078,
- 0x1ca3, 0x2069, 0x1000, 0x690c, 0xa016, 0x2d04, 0xa210, 0x8d68,
- 0x8109, 0x00c0, 0x1ca5, 0xa285, 0x0000, 0x00c0, 0x1cb3, 0x70c3,
- 0x4000, 0x0078, 0x1cb5, 0x70c3, 0x4003, 0x70ca, 0x0078, 0x15bd,
- 0x7964, 0x71c6, 0x71c4, 0xa182, 0x0003, 0x00c8, 0x15b2, 0x7966,
- 0x0078, 0x15ba, 0x7964, 0x71c6, 0x0078, 0x15ba, 0x7900, 0x71c6,
- 0x71c4, 0x7902, 0x0078, 0x15ba, 0x7900, 0x71c6, 0x0078, 0x15ba,
- 0x70c4, 0x2011, 0x0000, 0xa08c, 0x000d, 0x0040, 0x1ce5, 0x810c,
- 0x0048, 0x1ce1, 0x8210, 0x810c, 0x810c, 0x0048, 0x1ce1, 0x8210,
- 0x810c, 0x81ff, 0x00c0, 0x15b3, 0x8210, 0x7a0e, 0xd28c, 0x0040,
- 0x1d11, 0x7910, 0xc1cd, 0x7912, 0x2009, 0x0021, 0x2019, 0x0003,
- 0xd284, 0x0040, 0x1d0b, 0x8108, 0x2019, 0x0041, 0x2011, 0x964e,
- 0x2312, 0x2019, 0x0042, 0x8210, 0x2312, 0x2019, 0x0043, 0x8210,
- 0x2312, 0x2019, 0x0046, 0x8210, 0x2312, 0x2019, 0x0047, 0x8210,
- 0x2312, 0x2019, 0x0006, 0x2011, 0x9653, 0x2112, 0x2011, 0x9673,
- 0x2312, 0x7904, 0x7806, 0x0078, 0x15b9, 0x7804, 0x70c6, 0x0078,
- 0x15ba, 0x71c4, 0xd1fc, 0x00c0, 0x1d21, 0x2011, 0x52c0, 0x0078,
- 0x1d23, 0x2011, 0x5340, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003,
- 0x8003, 0xa268, 0x6a14, 0xd2b4, 0x0040, 0x1d32, 0x2011, 0x0001,
- 0x0078, 0x1d34, 0x2011, 0x0000, 0x6b0c, 0x6800, 0x70da, 0x0078,
- 0x15b7, 0x017e, 0x7814, 0xd0f4, 0x0040, 0x1d46, 0x2001, 0x4007,
- 0x70db, 0x0000, 0xa18d, 0x0001, 0x0078, 0x1d52, 0xd0fc, 0x0040,
- 0x1d51, 0x2001, 0x4007, 0x70db, 0x0001, 0xa18d, 0x0001, 0x0078,
- 0x1d52, 0xa006, 0x017f, 0x007c, 0x017e, 0x7814, 0xd0f4, 0x0040,
- 0x1d61, 0x2001, 0x4007, 0x70db, 0x0000, 0xa18d, 0x0001, 0x0078,
- 0x1d62, 0xa006, 0x017f, 0x007c, 0x017e, 0x7814, 0xd0fc, 0x0040,
- 0x1d71, 0x2001, 0x4007, 0x70db, 0x0001, 0xa18d, 0x0001, 0x0078,
- 0x1d72, 0xa006, 0x017f, 0x007c, 0x7112, 0x721a, 0x731e, 0x7810,
- 0xd0c4, 0x0040, 0x1d7d, 0x7422, 0x7526, 0xac80, 0x0001, 0x8108,
- 0x810c, 0x81a9, 0x8098, 0x20a1, 0x0030, 0x7003, 0x0000, 0x6084,
- 0x20a2, 0x53a6, 0x7007, 0x0001, 0x7974, 0xa184, 0xff00, 0x0040,
- 0x1d9a, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100,
- 0x0078, 0x1d9d, 0x8107, 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78,
- 0xa006, 0xa211, 0x7d10, 0xd5c4, 0x0040, 0x1daa, 0x7b84, 0xa319,
- 0x7c80, 0xa421, 0x7008, 0xd0fc, 0x0040, 0x1daa, 0x7003, 0x0001,
- 0x7007, 0x0006, 0x711a, 0x721e, 0x7d10, 0xd5c4, 0x0040, 0x1dba,
- 0x7322, 0x7426, 0xa084, 0x01e0, 0x007c, 0x7848, 0xa065, 0x0040,
- 0x1dc5, 0x2c04, 0x784a, 0x2063, 0x0000, 0x007c, 0x0f7e, 0x2079,
- 0x4e00, 0x7848, 0x2062, 0x2c00, 0xa005, 0x00c0, 0x1dd1, 0x1078,
- 0x296b, 0x784a, 0x0f7f, 0x007c, 0x2011, 0x9800, 0x7a4a, 0x7bc4,
- 0x8319, 0x0040, 0x1de1, 0xa280, 0x0032, 0x2012, 0x2010, 0x0078,
- 0x1dd8, 0x2013, 0x0000, 0x007c, 0x017e, 0x027e, 0xd7fc, 0x00c0,
- 0x1ded, 0x2011, 0x53c0, 0x0078, 0x1def, 0x2011, 0x73c0, 0xa784,
- 0x0f00, 0x800b, 0xa784, 0x001f, 0x0040, 0x1dfa, 0x8003, 0x8003,
- 0x8003, 0x8003, 0xa105, 0xa268, 0x027f, 0x017f, 0x007c, 0x1078,
- 0x1de4, 0x2900, 0x682a, 0x2a00, 0x682e, 0x6808, 0xa084, 0xf9ef,
- 0xa80d, 0x690a, 0x0e7e, 0xd7fc, 0x00c0, 0x1e14, 0x2009, 0x4e53,
- 0x2071, 0x4e40, 0x0078, 0x1e18, 0x2009, 0x4e93, 0x2071, 0x4e80,
- 0x210c, 0x6804, 0xa005, 0x0040, 0x1e28, 0xa116, 0x00c0, 0x1e28,
- 0x2060, 0x6000, 0x6806, 0x017e, 0x200b, 0x0000, 0x0078, 0x1e2b,
- 0x2009, 0x0000, 0x017e, 0x6804, 0xa065, 0x0040, 0x1e40, 0x6000,
- 0x6806, 0x1078, 0x1e5b, 0x1078, 0x201d, 0x6810, 0x7908, 0x8109,
- 0x790a, 0x8001, 0x6812, 0x00c0, 0x1e2b, 0x7910, 0xc1a5, 0x7912,
- 0x017f, 0x6902, 0x6906, 0x2d00, 0x2060, 0x1078, 0x2acc, 0x0e7f,
- 0x007c, 0xa065, 0x0040, 0x1e5a, 0x2008, 0x609c, 0xa005, 0x0040,
- 0x1e57, 0x2062, 0x609f, 0x0000, 0xa065, 0x0078, 0x1e4d, 0x7848,
- 0x794a, 0x2062, 0x007c, 0x6007, 0x0103, 0x608f, 0x0000, 0x20a9,
- 0x001c, 0xac80, 0x0005, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x6828,
- 0x601a, 0x682c, 0x6022, 0x007c, 0x0e7e, 0xd7fc, 0x00c0, 0x1e76,
- 0x2071, 0x4e40, 0x2031, 0x4ec0, 0x0078, 0x1e7a, 0x2071, 0x4e80,
- 0x2031, 0x50c0, 0x7050, 0xa08c, 0x0200, 0x00c0, 0x1e84, 0xa608,
- 0x2d0a, 0x8000, 0x7052, 0xa006, 0x0e7f, 0x007c, 0x0f7e, 0xd7fc,
- 0x00c0, 0x1e8e, 0x2079, 0x4e40, 0x0078, 0x1e90, 0x2079, 0x4e80,
- 0x1078, 0x1de4, 0x2091, 0x8000, 0x6804, 0x780a, 0xa065, 0x0040,
- 0x1ee4, 0x0078, 0x1ea2, 0x2c00, 0x780a, 0x2060, 0x6000, 0xa065,
- 0x0040, 0x1ee4, 0x6010, 0xa306, 0x00c0, 0x1e9b, 0x600c, 0xa206,
- 0x00c0, 0x1e9b, 0x2c28, 0x784c, 0xac06, 0x00c0, 0x1eb1, 0x0078,
- 0x1ee1, 0x6804, 0xac06, 0x00c0, 0x1ebf, 0x6000, 0x2060, 0x6806,
- 0xa005, 0x00c0, 0x1ebf, 0x6803, 0x0000, 0x0078, 0x1ec9, 0x6400,
- 0x7808, 0x2060, 0x6402, 0xa486, 0x0000, 0x00c0, 0x1ec9, 0x2c00,
- 0x6802, 0x2560, 0x0f7f, 0x1078, 0x1e5b, 0x0f7e, 0x601b, 0x0005,
- 0x6023, 0x0020, 0x0f7f, 0x1078, 0x201d, 0x0f7e, 0x7908, 0x8109,
- 0x790a, 0x6810, 0x8001, 0x6812, 0x00c0, 0x1ee1, 0x7810, 0xc0a5,
- 0x7812, 0x2001, 0xffff, 0xa005, 0x0f7f, 0x007c, 0x077e, 0x2700,
- 0x2039, 0x0000, 0xd0fc, 0x0040, 0x1eee, 0xc7fd, 0x2041, 0x0021,
- 0x2049, 0x0004, 0x2051, 0x0008, 0x2091, 0x8000, 0x1078, 0x1dff,
- 0x8738, 0xa784, 0x001f, 0x00c0, 0x1ef6, 0xa7bc, 0xff00, 0x873f,
- 0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0, 0x1ef6, 0x2091, 0x8001,
- 0x077f, 0x007c, 0x786c, 0x2009, 0x9674, 0x210c, 0xa10d, 0x0040,
- 0x1f14, 0xa065, 0x0078, 0x2395, 0x2061, 0x0000, 0x6018, 0xd084,
- 0x00c0, 0x1f34, 0x7810, 0xd08c, 0x0040, 0x1f25, 0xc08c, 0x7812,
- 0xc7fc, 0x2069, 0x4e40, 0x0078, 0x1f2a, 0xc08d, 0x7812, 0x2069,
- 0x4e80, 0xc7fd, 0x2091, 0x8000, 0x681c, 0x681f, 0x0000, 0x2091,
- 0x8001, 0xa005, 0x00c0, 0x1f35, 0x007c, 0xa08c, 0xfff0, 0x0040,
- 0x1f3b, 0x1078, 0x296b, 0x0079, 0x1f3d, 0x1f4d, 0x1f50, 0x1f56,
- 0x1f5a, 0x1f4e, 0x1f5e, 0x1f4e, 0x1f4e, 0x1f4e, 0x1f64, 0x1f95,
- 0x1f99, 0x1f9f, 0x1fb4, 0x1f4e, 0x1f4e, 0x007c, 0x1078, 0x296b,
- 0x1078, 0x1ee6, 0x2001, 0x8001, 0x0078, 0x1fc0, 0x2001, 0x8003,
- 0x0078, 0x1fc0, 0x2001, 0x8004, 0x0078, 0x1fc0, 0x1078, 0x1ee6,
- 0x2001, 0x8006, 0x0078, 0x1fc0, 0x2091, 0x8000, 0x077e, 0xd7fc,
- 0x00c0, 0x1f70, 0x2069, 0x4e40, 0x2039, 0x0009, 0x0078, 0x1f74,
- 0x2069, 0x4e80, 0x2039, 0x0009, 0x6800, 0xa086, 0x0000, 0x0040,
- 0x1f7e, 0x007f, 0x6f1e, 0x2091, 0x8001, 0x007c, 0x6874, 0x077f,
- 0xa0bc, 0xff00, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0010,
- 0x1078, 0x1dff, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1f88, 0x2091,
- 0x8001, 0x2001, 0x800a, 0x0078, 0x1fc0, 0x2001, 0x800c, 0x0078,
- 0x1fc0, 0x1078, 0x1ee6, 0x2001, 0x800d, 0x0078, 0x1fc0, 0x7814,
- 0xd0e4, 0x00c0, 0x1fb2, 0xd0ec, 0x0040, 0x1fac, 0xd7fc, 0x0040,
- 0x1fac, 0x78e4, 0x0078, 0x1fad, 0x78e0, 0x70c6, 0x2001, 0x800e,
- 0x0078, 0x1fc0, 0x0078, 0x1f4e, 0xd7fc, 0x0040, 0x1fba, 0x78ec,
- 0x0078, 0x1fbb, 0x78e8, 0x70c6, 0x2001, 0x800f, 0x0078, 0x1fc0,
- 0x70c2, 0xd7fc, 0x00c0, 0x1fc8, 0x70db, 0x0000, 0x0078, 0x1fca,
- 0x70db, 0x0001, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x4080,
- 0x007c, 0xac80, 0x0001, 0x81ff, 0x0040, 0x1ffc, 0x2099, 0x0030,
- 0x20a0, 0x700c, 0xa084, 0x03ff, 0x0040, 0x1fde, 0x7018, 0x007e,
- 0x701c, 0x007e, 0x7020, 0x007e, 0x7024, 0x007e, 0x7112, 0x81ac,
- 0x721a, 0x731e, 0x7422, 0x7526, 0x7003, 0x0001, 0x7007, 0x0001,
- 0x7008, 0x800b, 0x00c8, 0x1ff0, 0x7007, 0x0002, 0xa08c, 0x01e0,
- 0x00c0, 0x1ffc, 0x53a5, 0xa006, 0x7003, 0x0000, 0x7007, 0x0004,
- 0x007f, 0x7026, 0x007f, 0x7022, 0x007f, 0x701e, 0x007f, 0x701a,
- 0x007c, 0x2011, 0x0020, 0x2009, 0x0010, 0x6b0a, 0x6c0e, 0x6803,
- 0xfd00, 0x6807, 0x0018, 0x6a1a, 0x2d00, 0xa0e8, 0x0008, 0xa290,
- 0x0004, 0x8109, 0x00c0, 0x200d, 0x007c, 0x6004, 0x6086, 0x2c08,
- 0x2063, 0x0000, 0x7868, 0xa005, 0x796a, 0x0040, 0x202a, 0x2c02,
- 0x0078, 0x202b, 0x796e, 0x007c, 0x0c7e, 0x2061, 0x4e00, 0x6887,
- 0x0103, 0x2d08, 0x206b, 0x0000, 0x6068, 0xa005, 0x616a, 0x0040,
- 0x203c, 0x2d02, 0x0078, 0x203d, 0x616e, 0x0c7f, 0x007c, 0x2091,
- 0x8000, 0x2c04, 0x786e, 0xa005, 0x00c0, 0x2047, 0x786a, 0x2091,
- 0x8001, 0x609c, 0xa005, 0x0040, 0x2060, 0x0c7e, 0x2060, 0x2008,
- 0x609c, 0xa005, 0x0040, 0x205c, 0x2062, 0x609f, 0x0000, 0xa065,
- 0x609c, 0xa005, 0x00c0, 0x2054, 0x7848, 0x794a, 0x2062, 0x0c7f,
- 0x7848, 0x2062, 0x609f, 0x0000, 0xac85, 0x0000, 0x00c0, 0x206a,
- 0x1078, 0x296b, 0x784a, 0x007c, 0x20a9, 0x0010, 0xa006, 0x8004,
- 0x8086, 0x818e, 0x00c8, 0x2075, 0xa200, 0x00f0, 0x2070, 0x8086,
- 0x818e, 0x007c, 0x157e, 0x20a9, 0x0010, 0xa005, 0x0040, 0x209b,
- 0xa11a, 0x00c8, 0x209b, 0x8213, 0x818d, 0x0048, 0x208e, 0xa11a,
- 0x00c8, 0x208f, 0x00f0, 0x2083, 0x0078, 0x2093, 0xa11a, 0x2308,
- 0x8210, 0x00f0, 0x2083, 0x007e, 0x3200, 0xa084, 0xf7ff, 0x2080,
- 0x007f, 0x157f, 0x007c, 0x007e, 0x3200, 0xa085, 0x0800, 0x0078,
- 0x2097, 0x7d74, 0x70d0, 0xa506, 0x0040, 0x2187, 0x7810, 0x2050,
- 0x7800, 0xd08c, 0x0040, 0x20c3, 0xdaec, 0x0040, 0x20c3, 0x0e7e,
- 0x2091, 0x8000, 0x2071, 0x0020, 0x7004, 0xa005, 0x00c0, 0x20c0,
- 0x7008, 0x0e7f, 0xa086, 0x0008, 0x0040, 0x20c3, 0x0078, 0x2187,
- 0x0e7f, 0x0078, 0x2187, 0x1078, 0x1dbd, 0x0040, 0x2187, 0xa046,
- 0x7970, 0x2500, 0x8000, 0xa112, 0x2009, 0x0040, 0x00c8, 0x20d2,
- 0x0078, 0x20d9, 0x72d0, 0xa206, 0x0040, 0x20d9, 0x8840, 0x2009,
- 0x0080, 0x0c7e, 0x7112, 0x7007, 0x0001, 0x2099, 0x0030, 0x20a9,
- 0x0020, 0xac80, 0x0001, 0x20a0, 0x2061, 0x0000, 0x88ff, 0x0040,
- 0x20eb, 0x1078, 0x1dbd, 0x7008, 0xd0fc, 0x0040, 0x20eb, 0x7007,
- 0x0002, 0x2091, 0x8001, 0xa08c, 0x01e0, 0x00c0, 0x2122, 0x53a5,
- 0x8cff, 0x00c0, 0x2100, 0x88ff, 0x0040, 0x2171, 0x0078, 0x210a,
- 0x2c00, 0x788e, 0x20a9, 0x0020, 0xac80, 0x0001, 0x20a0, 0x53a5,
- 0x0078, 0x2171, 0xa046, 0x7218, 0x731c, 0xdac4, 0x0040, 0x2112,
- 0x7420, 0x7524, 0xa292, 0x0040, 0xa39b, 0x0000, 0xa4a3, 0x0000,
- 0xa5ab, 0x0000, 0x721a, 0x731e, 0xdac4, 0x0040, 0x2122, 0x7422,
- 0x7526, 0xa006, 0x7007, 0x0004, 0x0040, 0x2171, 0x8cff, 0x0040,
- 0x212b, 0x1078, 0x1dc6, 0x0c7f, 0x1078, 0x1dc6, 0xa046, 0x7888,
- 0x8000, 0x788a, 0xa086, 0x0002, 0x0040, 0x2151, 0x7a7c, 0x7b78,
- 0xdac4, 0x0040, 0x213d, 0x7c84, 0x7d80, 0x7974, 0x8107, 0x8004,
- 0x8004, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000,
- 0x721a, 0x731e, 0xdac4, 0x0040, 0x2187, 0x7422, 0x7526, 0x0078,
- 0x2187, 0x6014, 0xd0fc, 0x00c0, 0x2159, 0x2069, 0x4e40, 0x0078,
- 0x215b, 0x2069, 0x4e80, 0x2091, 0x8000, 0x681f, 0x0002, 0x88ff,
- 0x0040, 0x2167, 0xa046, 0x788c, 0x2060, 0x0078, 0x2151, 0x788b,
- 0x0000, 0x78ac, 0xa085, 0x0003, 0x78ae, 0x2091, 0x8001, 0x0078,
- 0x2187, 0x0c7f, 0x788b, 0x0000, 0x1078, 0x2346, 0x6004, 0xa084,
- 0x000f, 0x1078, 0x2188, 0x88ff, 0x0040, 0x2185, 0x788c, 0x2060,
- 0x6004, 0xa084, 0x000f, 0x1078, 0x2188, 0x0078, 0x20a1, 0x007c,
- 0x0079, 0x218a, 0x219a, 0x21b8, 0x21d6, 0x219a, 0x21e7, 0x21ab,
- 0x219a, 0x219a, 0x219a, 0x21b6, 0x21d4, 0x219a, 0x219a, 0x219a,
- 0x219a, 0x219a, 0x2039, 0x0400, 0x78bc, 0xa705, 0x78be, 0x6008,
- 0xa705, 0x600a, 0x1078, 0x222a, 0x609c, 0x78ba, 0x609f, 0x0000,
- 0x1078, 0x2330, 0x007c, 0x78bc, 0xd0c4, 0x0040, 0x21b1, 0x0078,
- 0x219a, 0x601c, 0xc0bd, 0x601e, 0x0078, 0x21be, 0x1078, 0x2378,
- 0x78bc, 0xd0c4, 0x0040, 0x21be, 0x0078, 0x219a, 0x78bf, 0x0000,
- 0x6004, 0x8007, 0xa084, 0x00ff, 0x78b2, 0x8001, 0x0040, 0x21d1,
- 0x1078, 0x222a, 0x0040, 0x21d1, 0x78bc, 0xc0c5, 0x78be, 0x0078,
- 0x21d3, 0x0078, 0x2249, 0x007c, 0x1078, 0x2374, 0x78bc, 0xa08c,
- 0x0e00, 0x00c0, 0x21de, 0xd0c4, 0x00c0, 0x21e0, 0x0078, 0x219a,
- 0x1078, 0x222a, 0x00c0, 0x21e6, 0x0078, 0x2249, 0x007c, 0x78bc,
- 0xd0c4, 0x0040, 0x21ed, 0x0078, 0x219a, 0x78bf, 0x0000, 0x6714,
- 0x2011, 0x0001, 0x22a8, 0x6018, 0xa084, 0x00ff, 0xa005, 0x0040,
- 0x220d, 0xa7bc, 0xff00, 0x20a9, 0x0020, 0xa08e, 0x0001, 0x0040,
- 0x220d, 0xa7bc, 0x8000, 0x2011, 0x0002, 0x20a9, 0x0100, 0xa08e,
- 0x0002, 0x0040, 0x220d, 0x0078, 0x2227, 0x1078, 0x1de4, 0x2d00,
- 0x2091, 0x8000, 0x682b, 0x0000, 0x682f, 0x0000, 0x6808, 0xa084,
- 0xffde, 0x680a, 0xade8, 0x0010, 0x2091, 0x8001, 0x00f0, 0x2210,
- 0x8211, 0x0040, 0x2227, 0x20a9, 0x0100, 0x0078, 0x2210, 0x1078,
- 0x1dc6, 0x007c, 0x609f, 0x0000, 0x78b4, 0xa06d, 0x2c00, 0x78b6,
- 0x00c0, 0x2235, 0x78ba, 0x0078, 0x223d, 0x689e, 0x2d00, 0x6002,
- 0x78b8, 0xad06, 0x00c0, 0x223d, 0x6002, 0x78b0, 0x8001, 0x78b2,
- 0x00c0, 0x2248, 0x78bc, 0xc0c4, 0x78be, 0x78b8, 0x2060, 0xa006,
- 0x007c, 0x0e7e, 0xa02e, 0x2530, 0x7dba, 0x7db6, 0x65ae, 0x65b2,
- 0x601c, 0x60a2, 0x2048, 0xa984, 0xe1ff, 0x601e, 0xa984, 0x0060,
- 0x0040, 0x225c, 0x1078, 0x4632, 0x6596, 0x65a6, 0x669a, 0x66aa,
- 0x6714, 0x2071, 0x4e80, 0xd7fc, 0x00c0, 0x2268, 0x2071, 0x4e40,
- 0xa784, 0x0f00, 0x800b, 0xa784, 0x001f, 0x0040, 0x2273, 0x8003,
- 0x8003, 0x8003, 0x8003, 0xa105, 0x71c4, 0xa168, 0x2700, 0x8007,
- 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0x71c8, 0xa100, 0x60c2,
- 0x2091, 0x8000, 0x7814, 0xd0c4, 0x0040, 0x2298, 0xd0ec, 0x0040,
- 0x2294, 0xd7fc, 0x00c0, 0x2291, 0xd0f4, 0x00c0, 0x229f, 0x0078,
- 0x2298, 0xd0fc, 0x00c0, 0x229f, 0x7810, 0xd0f4, 0x00c0, 0x229f,
- 0x6e08, 0xd684, 0x0040, 0x22c9, 0xd9fc, 0x00c0, 0x22c9, 0x2091,
- 0x8001, 0x1078, 0x1e5b, 0x2091, 0x8000, 0x1078, 0x201d, 0x2091,
- 0x8001, 0x7814, 0xd0e4, 0x00c0, 0x232e, 0x7814, 0xd0c4, 0x0040,
- 0x232e, 0xd0ec, 0x0040, 0x22c1, 0xd7fc, 0x00c0, 0x22bc, 0xd0f4,
- 0x00c0, 0x22c5, 0x0078, 0x232e, 0xd0fc, 0x00c0, 0x22c5, 0x0078,
- 0x232e, 0x7810, 0xd0f4, 0x0040, 0x232e, 0x601b, 0x0021, 0x0078,
- 0x232e, 0x6024, 0xa096, 0x0001, 0x00c0, 0x22d0, 0x8000, 0x6026,
- 0x6a10, 0x6814, 0xa202, 0x0048, 0x22e3, 0x0040, 0x22e3, 0x2091,
- 0x8001, 0x2039, 0x0200, 0x609c, 0x78ba, 0x609f, 0x0000, 0x1078,
- 0x2330, 0x0078, 0x232e, 0x2c08, 0xd9fc, 0x0040, 0x230b, 0x6800,
- 0xa065, 0x0040, 0x230b, 0x6a04, 0x7000, 0xa084, 0x0002, 0x0040,
- 0x2301, 0x704c, 0xa206, 0x00c0, 0x2301, 0x6b04, 0x2160, 0x2304,
- 0x6002, 0xa005, 0x00c0, 0x22fd, 0x6902, 0x2260, 0x6102, 0x0078,
- 0x2317, 0x2d00, 0x2060, 0x1078, 0x2acc, 0x6e08, 0x2160, 0x6202,
- 0x6906, 0x0078, 0x2317, 0x6800, 0x6902, 0xa065, 0x0040, 0x2313,
- 0x6102, 0x0078, 0x2314, 0x6906, 0x2160, 0x6003, 0x0000, 0x2160,
- 0xd9fc, 0x0040, 0x231e, 0xa6b4, 0xfffc, 0x6e0a, 0x6810, 0x7d08,
- 0x8528, 0x7d0a, 0x8000, 0x6812, 0x2091, 0x8001, 0xd6b4, 0x0040,
- 0x232e, 0xa6b6, 0x0040, 0x6e0a, 0x1078, 0x1e6c, 0x0e7f, 0x007c,
- 0x6008, 0xa705, 0x600a, 0x2091, 0x8000, 0x1078, 0x201d, 0x2091,
- 0x8001, 0x78b8, 0xa065, 0x0040, 0x2343, 0x609c, 0x78ba, 0x609f,
- 0x0000, 0x0078, 0x2330, 0x78b6, 0x78ba, 0x007c, 0x7970, 0x7874,
- 0x2818, 0xd384, 0x0040, 0x2350, 0x8000, 0xa112, 0x0048, 0x2355,
- 0x8000, 0xa112, 0x00c8, 0x2365, 0xc384, 0x7a7c, 0x721a, 0x7a78,
- 0x721e, 0xdac4, 0x0040, 0x2360, 0x7a84, 0x7222, 0x7a80, 0x7226,
- 0xa006, 0xd384, 0x0040, 0x2365, 0x8000, 0x7876, 0x70d2, 0x781c,
- 0xa005, 0x0040, 0x2373, 0x8001, 0x781e, 0x00c0, 0x2373, 0x0068,
- 0x2373, 0x2091, 0x4080, 0x007c, 0x2039, 0x238c, 0x0078, 0x237a,
- 0x2039, 0x2392, 0x2704, 0xa005, 0x0040, 0x238b, 0xac00, 0x2068,
- 0x6908, 0x6810, 0x6912, 0x680a, 0x690c, 0x6814, 0x6916, 0x680e,
- 0x8738, 0x0078, 0x237a, 0x007c, 0x0003, 0x0009, 0x000f, 0x0015,
- 0x001b, 0x0000, 0x0015, 0x001b, 0x0000, 0x2041, 0x0000, 0x780c,
- 0x0079, 0x239a, 0x256c, 0x253f, 0x239e, 0x2417, 0x2039, 0x9674,
- 0x2734, 0x7d10, 0x0078, 0x23be, 0x6084, 0xa086, 0x0103, 0x00c0,
- 0x2400, 0x6114, 0x6018, 0xa105, 0x0040, 0x23b3, 0x86ff, 0x00c0,
- 0x23cf, 0x0078, 0x2400, 0x8603, 0xa080, 0x9655, 0x620c, 0x2202,
- 0x8000, 0x6210, 0x2202, 0x1078, 0x203f, 0x8630, 0xa68e, 0x000f,
- 0x0040, 0x248b, 0x786c, 0xa065, 0x00c0, 0x23a4, 0x7808, 0xa602,
- 0x00c8, 0x23cf, 0xd5ac, 0x00c0, 0x23cf, 0x263a, 0x007c, 0xa682,
- 0x0003, 0x00c8, 0x248b, 0x2091, 0x8000, 0x2069, 0x0000, 0x6818,
- 0xd084, 0x00c0, 0x23fb, 0x2011, 0x9655, 0x2204, 0x70c6, 0x8210,
- 0x2204, 0x70ca, 0xd684, 0x00c0, 0x23eb, 0x8210, 0x2204, 0x70da,
- 0x8210, 0x2204, 0x70de, 0xa685, 0x8020, 0x70c2, 0x681b, 0x0001,
+ 0x017f, 0x027f, 0x0078, 0x15bf, 0x2061, 0x4f40, 0x6130, 0x70c4,
+ 0x6032, 0x7810, 0xd0ec, 0x00c0, 0x15c0, 0x2061, 0x4f80, 0x6230,
+ 0x70c8, 0x6032, 0x0078, 0x15bf, 0x7918, 0x0078, 0x15c0, 0x71c4,
+ 0xa184, 0xffcf, 0x0040, 0x18a3, 0x7810, 0xd0ec, 0x00c0, 0x15b9,
+ 0x72c8, 0x0078, 0x15b8, 0x2011, 0x4f4d, 0x2204, 0x2112, 0x007e,
+ 0x2019, 0x0000, 0x1078, 0x27ab, 0x7810, 0xd0ec, 0x0040, 0x18b3,
+ 0x017f, 0x0078, 0x15c0, 0x71c8, 0xa184, 0xffcf, 0x0040, 0x18bc,
+ 0x2110, 0x71c4, 0x0078, 0x15b8, 0x2011, 0x4f8d, 0x2204, 0x2112,
+ 0x007e, 0xc3fd, 0x1078, 0x27ab, 0x027f, 0x017f, 0x0078, 0x15bf,
+ 0x71c4, 0xa182, 0x0010, 0x0048, 0x18d4, 0x7810, 0xd0ec, 0x00c0,
+ 0x15b9, 0x72c8, 0x0078, 0x15b8, 0x2011, 0x4f4e, 0x2204, 0x007e,
+ 0x2112, 0x2019, 0x0000, 0x1078, 0x2789, 0x7810, 0xd0ec, 0x0040,
+ 0x18e4, 0x017f, 0x0078, 0x15c0, 0x71c8, 0xa182, 0x0010, 0x0048,
+ 0x18ed, 0x2110, 0x71c4, 0x0078, 0x15b8, 0x2011, 0x4f8e, 0x2204,
+ 0x007e, 0x2112, 0xc3fd, 0x1078, 0x2789, 0x027f, 0x017f, 0x0078,
+ 0x15bf, 0x71c4, 0x72c8, 0xa184, 0xfffd, 0x00c0, 0x15b8, 0xa284,
+ 0xfffd, 0x00c0, 0x15b8, 0x2100, 0x7920, 0x7822, 0x2200, 0x7a24,
+ 0x7826, 0x0078, 0x15bf, 0x71c4, 0xd1fc, 0x00c0, 0x1913, 0x2011,
+ 0x53c0, 0x0078, 0x1915, 0x2011, 0x5440, 0x8107, 0xa084, 0x000f,
+ 0x8003, 0x8003, 0x8003, 0xa268, 0x2019, 0x0000, 0x72c8, 0xd2bc,
+ 0x0040, 0x1924, 0xa39d, 0x0010, 0xd2b4, 0x0040, 0x1929, 0xa39d,
+ 0x0008, 0x2091, 0x8000, 0x6800, 0x007e, 0xa226, 0x0040, 0x1948,
+ 0x6a02, 0xd4ec, 0x0040, 0x1935, 0xc3a5, 0xd4e4, 0x0040, 0x1939,
+ 0xc39d, 0xd4f4, 0x0040, 0x1948, 0x810f, 0xd2f4, 0x0040, 0x1944,
+ 0x1078, 0x2808, 0x0078, 0x1948, 0x1078, 0x27e6, 0x0078, 0x1948,
+ 0x72cc, 0x6808, 0xa206, 0x0040, 0x196a, 0xa2a4, 0x00ff, 0x7814,
+ 0xd0e4, 0x00c0, 0x195b, 0xa482, 0x0028, 0x0048, 0x1967, 0x0040,
+ 0x1967, 0x0078, 0x195f, 0xa482, 0x0043, 0x0048, 0x1967, 0x71c4,
+ 0x71c6, 0x027f, 0x72ca, 0x2091, 0x8001, 0x0078, 0x15ba, 0x6a0a,
+ 0xa39d, 0x000a, 0x6804, 0xa305, 0x6806, 0x027f, 0x6b0c, 0x71c4,
+ 0x2091, 0x8001, 0x0078, 0x15be, 0x77c4, 0x1078, 0x1e2b, 0x2091,
+ 0x8000, 0x6a14, 0x6b1c, 0x2091, 0x8001, 0x70c8, 0x6816, 0x70cc,
+ 0x681e, 0x2708, 0x0078, 0x15be, 0x70c4, 0x2061, 0x4f40, 0x6118,
+ 0x601a, 0x7810, 0xd0ec, 0x00c0, 0x15c0, 0x70c8, 0x2061, 0x4f80,
+ 0x6218, 0x601a, 0x0078, 0x15bf, 0x71c4, 0x72c8, 0x73cc, 0xa182,
+ 0x0010, 0x00c8, 0x15b9, 0x1078, 0x282a, 0xa384, 0x4000, 0x0040,
+ 0x19a3, 0xa295, 0x0020, 0x0078, 0x15be, 0x77c4, 0x1078, 0x1e2b,
+ 0x2091, 0x8000, 0x6a08, 0xc28d, 0x6a0a, 0x2091, 0x8001, 0x2708,
+ 0x0078, 0x15bf, 0x77c4, 0x1078, 0x1e2b, 0x2091, 0x8000, 0x6a08,
+ 0xa294, 0xfff9, 0x6a0a, 0x6804, 0xa005, 0x0040, 0x19c1, 0x1078,
+ 0x266f, 0x2091, 0x8001, 0x2708, 0x0078, 0x15bf, 0x77c4, 0x1078,
+ 0x1e2b, 0x2091, 0x8000, 0x6a08, 0xc295, 0x6a0a, 0x6804, 0xa005,
+ 0x0040, 0x19d4, 0x1078, 0x266f, 0x2091, 0x8001, 0x2708, 0x0078,
+ 0x15bf, 0x77c4, 0x2041, 0x0001, 0x2049, 0x0005, 0x2051, 0x0020,
+ 0x2091, 0x8000, 0x1078, 0x1e46, 0x2091, 0x8001, 0x2708, 0x6a08,
+ 0x0078, 0x15bf, 0x77c4, 0x7814, 0xd0e4, 0x00c0, 0x19fe, 0xd7fc,
+ 0x0040, 0x19f8, 0x1078, 0x1dae, 0x0040, 0x19fe, 0x0078, 0x15c3,
+ 0x1078, 0x1da1, 0x0040, 0x19fe, 0x0078, 0x15c3, 0x73c8, 0x72cc,
+ 0x77c6, 0x73ca, 0x72ce, 0x1078, 0x1ecd, 0x00c0, 0x1a28, 0x6818,
+ 0xa005, 0x0040, 0x1a22, 0x2708, 0x077e, 0x1078, 0x285a, 0x077f,
+ 0x00c0, 0x1a22, 0x2001, 0x0015, 0xd7fc, 0x00c0, 0x1a1b, 0x2061,
+ 0x4f40, 0x0078, 0x1a1e, 0xc0fd, 0x2061, 0x4f80, 0x782a, 0x2091,
+ 0x8001, 0x007c, 0x2091, 0x8001, 0x2001, 0x4005, 0x0078, 0x15c3,
+ 0x2091, 0x8001, 0x0078, 0x15c1, 0x77c4, 0x7814, 0xd0e4, 0x00c0,
+ 0x1a40, 0xd7fc, 0x0040, 0x1a3a, 0x1078, 0x1dae, 0x0040, 0x1a40,
+ 0x0078, 0x15c3, 0x1078, 0x1da1, 0x0040, 0x1a40, 0x0078, 0x15c3,
+ 0x77c6, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091,
+ 0x8000, 0x1078, 0x1e46, 0x2009, 0x0016, 0xd7fc, 0x00c0, 0x1a54,
+ 0x2061, 0x4f40, 0x0078, 0x1a57, 0x2061, 0x4f80, 0xc1fd, 0x6067,
+ 0x0003, 0x607f, 0x0000, 0x6776, 0x6083, 0x000f, 0x792a, 0x61d4,
+ 0xc1dc, 0x61d6, 0x1078, 0x266f, 0x2091, 0x8001, 0x007c, 0x77c8,
+ 0x77ca, 0x77c4, 0x77c6, 0x7814, 0xd0e4, 0x00c0, 0x1a7e, 0xd7fc,
+ 0x0040, 0x1a78, 0x1078, 0x1dae, 0x0040, 0x1a7e, 0x0078, 0x15c3,
+ 0x1078, 0x1da1, 0x0040, 0x1a7e, 0x0078, 0x15c3, 0xa7bc, 0xff00,
+ 0x2091, 0x8000, 0x2009, 0x0017, 0xd7fc, 0x00c0, 0x1a8b, 0x2061,
+ 0x4f40, 0x0078, 0x1a8e, 0x2061, 0x4f80, 0xc1fd, 0x607f, 0x0000,
+ 0x6067, 0x0002, 0x6776, 0x6083, 0x000f, 0x792a, 0x61d4, 0xc1dc,
+ 0x61d6, 0x1078, 0x266f, 0x2091, 0x8001, 0x2041, 0x0021, 0x2049,
+ 0x0005, 0x2051, 0x0010, 0x2091, 0x8000, 0x70c8, 0xa005, 0x0040,
+ 0x1aac, 0x60d4, 0xc0fd, 0x60d6, 0x1078, 0x1e46, 0x70c8, 0x6836,
+ 0x8738, 0xa784, 0x001f, 0x00c0, 0x1aac, 0x2091, 0x8001, 0x007c,
+ 0x2019, 0x0000, 0x7814, 0xd0e4, 0x00c0, 0x1ace, 0x72c8, 0xd284,
+ 0x0040, 0x1ac8, 0x1078, 0x1dae, 0x0040, 0x1ace, 0x0078, 0x15c3,
+ 0x1078, 0x1da1, 0x0040, 0x1ace, 0x0078, 0x15c3, 0x72c8, 0x72ca,
+ 0x78ac, 0xa084, 0x0003, 0x00c0, 0x1af9, 0x2039, 0x0000, 0xd284,
+ 0x0040, 0x1adb, 0xc7fd, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051,
+ 0x0008, 0x1078, 0x1e2b, 0x2091, 0x8000, 0x6808, 0xc0d4, 0xa80d,
+ 0x690a, 0x2091, 0x8001, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1ae1,
+ 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0,
+ 0x1ae1, 0x2091, 0x8000, 0x72c8, 0xd284, 0x00c0, 0x1b0b, 0x7810,
+ 0xd0ec, 0x0040, 0x1b07, 0x2069, 0x0100, 0x0078, 0x1b0d, 0x2069,
+ 0x0200, 0x0078, 0x1b0d, 0x2069, 0x0100, 0x6808, 0xa084, 0xfffd,
+ 0x680a, 0x6830, 0xd0b4, 0x0040, 0x1b2d, 0x684b, 0x0004, 0x20a9,
+ 0x0014, 0x6848, 0xd094, 0x0040, 0x1b1f, 0x00f0, 0x1b19, 0x684b,
+ 0x0009, 0x20a9, 0x0014, 0x6848, 0xd084, 0x0040, 0x1b29, 0x00f0,
+ 0x1b23, 0x20a9, 0x00fa, 0x00f0, 0x1b2b, 0x2079, 0x4f00, 0x2009,
+ 0x0018, 0x72c8, 0xd284, 0x00c0, 0x1b39, 0x2061, 0x4f40, 0x0078,
+ 0x1b3c, 0x2061, 0x4f80, 0xc1fd, 0x607f, 0x0000, 0x792a, 0x6067,
+ 0x0001, 0x6083, 0x000f, 0x60a7, 0x0000, 0x60a8, 0x60b2, 0x60b6,
+ 0x60d4, 0xd0b4, 0x0040, 0x1b58, 0xc0b4, 0x60d6, 0x0c7e, 0x60b8,
+ 0xa065, 0x6008, 0xc0d4, 0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f,
+ 0x60d4, 0xa084, 0x77ff, 0x60d6, 0x78ac, 0xc08d, 0x78ae, 0x83ff,
+ 0x0040, 0x1b63, 0x007c, 0x681b, 0x0047, 0x2091, 0x8001, 0x007c,
+ 0x73cc, 0x1078, 0x1aba, 0x69ec, 0x6a48, 0xa185, 0x1800, 0x684a,
+ 0xa185, 0x0040, 0x68ee, 0x73cc, 0x2021, 0x0004, 0x20a9, 0x09ff,
+ 0x00f0, 0x1b78, 0x8421, 0x00c0, 0x1b76, 0x8319, 0x00c0, 0x1b74,
+ 0x69ee, 0x6a4a, 0x2091, 0x8001, 0x007c, 0xd7fc, 0x00c0, 0x1b8c,
+ 0x2069, 0x4f40, 0x0078, 0x1b8e, 0x2069, 0x4f80, 0x71c4, 0x71c6,
+ 0x6916, 0x81ff, 0x00c0, 0x1b96, 0x68a7, 0x0001, 0x78ac, 0xc08c,
+ 0x78ae, 0xd084, 0x00c0, 0x1b9e, 0x1078, 0x1f2d, 0x007c, 0x75d8,
+ 0x74dc, 0x75da, 0x74de, 0x0078, 0x1ba7, 0xa02e, 0x2520, 0x71c4,
+ 0x73c8, 0x72cc, 0x71c6, 0x73ca, 0x72ce, 0x2079, 0x4f00, 0x7dde,
+ 0x7cda, 0x7bd6, 0x7ad2, 0x1078, 0x1e04, 0x0040, 0x1cd1, 0x20a9,
+ 0x0005, 0x20a1, 0x4f14, 0x2091, 0x8000, 0x41a1, 0x2091, 0x8001,
+ 0x2009, 0x0040, 0x1078, 0x2018, 0x0040, 0x1bca, 0x1078, 0x1e0d,
+ 0x0078, 0x1cd1, 0x6004, 0xa08c, 0x00ff, 0xa18e, 0x0009, 0x00c0,
+ 0x1bd5, 0x007e, 0x1078, 0x23bf, 0x007f, 0xa084, 0xff00, 0x8007,
+ 0x8009, 0x0040, 0x1c61, 0x0c7e, 0x2c68, 0x1078, 0x1e04, 0x0040,
+ 0x1c1b, 0x2c00, 0x689e, 0x8109, 0x00c0, 0x1bdc, 0x609f, 0x0000,
+ 0x0c7f, 0x0c7e, 0x7ddc, 0x7cd8, 0x7bd4, 0x7ad0, 0xa290, 0x0040,
+ 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x7dde, 0x7cda,
+ 0x7bd6, 0x7ad2, 0x2c68, 0x689c, 0xa065, 0x0040, 0x1c60, 0x2009,
+ 0x0040, 0x1078, 0x2018, 0x00c0, 0x1c3e, 0x6004, 0xa084, 0x00ff,
+ 0xa086, 0x0002, 0x00c0, 0x1c1b, 0x6004, 0xa084, 0x00ff, 0xa086,
+ 0x000a, 0x00c0, 0x1c17, 0x017e, 0x1078, 0x23bb, 0x017f, 0x2d00,
+ 0x6002, 0x0078, 0x1bea, 0x0c7f, 0x0c7e, 0x609c, 0x1078, 0x1e90,
+ 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1cd5, 0x2009, 0x0018, 0x6008,
+ 0xc0cd, 0x600a, 0x6004, 0x6086, 0x7810, 0x007e, 0x84ff, 0x00c0,
+ 0x1c34, 0x85ff, 0x0040, 0x1c36, 0xc0c5, 0x7812, 0x1078, 0x1dbb,
+ 0x007f, 0x7812, 0x1078, 0x1e0d, 0x0078, 0x1cd1, 0x0c7f, 0x0c7e,
+ 0x609c, 0x1078, 0x1e90, 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1cd5,
+ 0x2009, 0x0018, 0x6087, 0x0103, 0x601b, 0x0003, 0x7810, 0x007e,
+ 0x84ff, 0x00c0, 0x1c56, 0x85ff, 0x0040, 0x1c58, 0xc0c5, 0x7812,
+ 0x1078, 0x1dbb, 0x007f, 0x7812, 0x1078, 0x1e0d, 0x0078, 0x1cd1,
+ 0x0c7f, 0x7814, 0xd0e4, 0x00c0, 0x1c8f, 0x6114, 0xd1fc, 0x0040,
+ 0x1c6f, 0x1078, 0x1dae, 0x0040, 0x1c8f, 0x0078, 0x1c73, 0x1078,
+ 0x1da1, 0x0040, 0x1c8f, 0x1078, 0x1cd5, 0x2009, 0x0018, 0x6087,
+ 0x0103, 0x601b, 0x0021, 0x7810, 0x007e, 0x84ff, 0x00c0, 0x1c83,
+ 0x85ff, 0x0040, 0x1c85, 0xc0c5, 0x7812, 0x1078, 0x1dbb, 0x007f,
+ 0x7812, 0x1078, 0x1e0d, 0x2001, 0x4007, 0x0078, 0x15c3, 0x74c4,
+ 0x73c8, 0x72cc, 0x6014, 0x2091, 0x8000, 0x0e7e, 0x2009, 0x0012,
+ 0xd0fc, 0x00c0, 0x1c9f, 0x2071, 0x4f40, 0x0078, 0x1ca2, 0x2071,
+ 0x4f80, 0xc1fd, 0x792a, 0x7067, 0x0005, 0x71d4, 0xc1dc, 0x71d6,
+ 0x736a, 0x726e, 0x7472, 0x7076, 0x707b, 0x0000, 0x2c00, 0x707e,
+ 0xa02e, 0x2530, 0x611c, 0xa184, 0x0060, 0x0040, 0x1cb9, 0x1078,
+ 0x46b6, 0x0e7f, 0x6596, 0x65a6, 0x669a, 0x66aa, 0x60af, 0x0000,
+ 0x60b3, 0x0000, 0x6714, 0x6023, 0x0000, 0x6024, 0xa096, 0x0001,
+ 0x00c0, 0x1ccc, 0x8000, 0x6026, 0x1078, 0x266f, 0x2091, 0x8001,
+ 0x007c, 0x70c3, 0x4005, 0x0078, 0x15c4, 0x20a9, 0x0005, 0x2099,
+ 0x4f14, 0x2091, 0x8000, 0x530a, 0x2091, 0x8001, 0x2100, 0xa210,
+ 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x007c, 0x71c4,
+ 0x70c7, 0x0000, 0x791e, 0x0078, 0x15c1, 0x71c4, 0x71c6, 0x2168,
+ 0x0078, 0x1cf4, 0x2069, 0x1000, 0x690c, 0xa016, 0x2d04, 0xa210,
+ 0x8d68, 0x8109, 0x00c0, 0x1cf6, 0xa285, 0x0000, 0x00c0, 0x1d04,
+ 0x70c3, 0x4000, 0x0078, 0x1d06, 0x70c3, 0x4003, 0x70ca, 0x0078,
+ 0x15c4, 0x7964, 0x71c6, 0x71c4, 0xa182, 0x0003, 0x00c8, 0x15b9,
+ 0x7966, 0x0078, 0x15c1, 0x7964, 0x71c6, 0x0078, 0x15c1, 0x7900,
+ 0x71c6, 0x71c4, 0x7902, 0x0078, 0x15c1, 0x7900, 0x71c6, 0x0078,
+ 0x15c1, 0x70c4, 0x2011, 0x0000, 0xa08c, 0x000d, 0x0040, 0x1d36,
+ 0x810c, 0x0048, 0x1d32, 0x8210, 0x810c, 0x810c, 0x0048, 0x1d32,
+ 0x8210, 0x810c, 0x81ff, 0x00c0, 0x15ba, 0x8210, 0x7a0e, 0xd28c,
+ 0x0040, 0x1d62, 0x7910, 0xc1cd, 0x7912, 0x2009, 0x0021, 0x2019,
+ 0x0003, 0xd284, 0x0040, 0x1d5c, 0x8108, 0x2019, 0x0041, 0x2011,
+ 0x974e, 0x2312, 0x2019, 0x0042, 0x8210, 0x2312, 0x2019, 0x0043,
+ 0x8210, 0x2312, 0x2019, 0x0046, 0x8210, 0x2312, 0x2019, 0x0047,
+ 0x8210, 0x2312, 0x2019, 0x0006, 0x2011, 0x9753, 0x2112, 0x2011,
+ 0x9773, 0x2312, 0x7904, 0x7806, 0x0078, 0x15c0, 0x7804, 0x70c6,
+ 0x0078, 0x15c1, 0x71c4, 0xd1fc, 0x00c0, 0x1d72, 0x2011, 0x53c0,
+ 0x0078, 0x1d74, 0x2011, 0x5440, 0x8107, 0xa084, 0x000f, 0x8003,
+ 0x8003, 0x8003, 0xa268, 0x6a14, 0xd2b4, 0x0040, 0x1d83, 0x2011,
+ 0x0001, 0x0078, 0x1d85, 0x2011, 0x0000, 0x6b0c, 0x6800, 0x70da,
+ 0x0078, 0x15be, 0x7814, 0xd0f4, 0x0040, 0x1d95, 0x2001, 0x4007,
+ 0x70db, 0x0000, 0xa005, 0x0078, 0x1da0, 0xd0fc, 0x0040, 0x1d9f,
+ 0x2001, 0x4007, 0x70db, 0x0001, 0xa005, 0x0078, 0x1da0, 0xa006,
+ 0x007c, 0x7814, 0xd0f4, 0x0040, 0x1dac, 0x2001, 0x4007, 0x70db,
+ 0x0000, 0xa005, 0x0078, 0x1dad, 0xa006, 0x007c, 0x7814, 0xd0fc,
+ 0x0040, 0x1db9, 0x2001, 0x4007, 0x70db, 0x0001, 0xa005, 0x0078,
+ 0x1dba, 0xa006, 0x007c, 0x7112, 0x721a, 0x731e, 0x7810, 0xd0c4,
+ 0x0040, 0x1dc4, 0x7422, 0x7526, 0xac80, 0x0001, 0x8108, 0x810c,
+ 0x81a9, 0x8098, 0x20a1, 0x0030, 0x7003, 0x0000, 0x6084, 0x20a2,
+ 0x53a6, 0x7007, 0x0001, 0x7974, 0xa184, 0xff00, 0x0040, 0x1de1,
+ 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0078,
+ 0x1de4, 0x8107, 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78, 0xa006,
+ 0xa211, 0x7d10, 0xd5c4, 0x0040, 0x1df1, 0x7b84, 0xa319, 0x7c80,
+ 0xa421, 0x7008, 0xd0fc, 0x0040, 0x1df1, 0x7003, 0x0001, 0x7007,
+ 0x0006, 0x711a, 0x721e, 0x7d10, 0xd5c4, 0x0040, 0x1e01, 0x7322,
+ 0x7426, 0xa084, 0x01e0, 0x007c, 0x7848, 0xa065, 0x0040, 0x1e0c,
+ 0x2c04, 0x784a, 0x2063, 0x0000, 0x007c, 0x0f7e, 0x2079, 0x4f00,
+ 0x7848, 0x2062, 0x2c00, 0xa005, 0x00c0, 0x1e18, 0x1078, 0x29b2,
+ 0x784a, 0x0f7f, 0x007c, 0x2011, 0x9900, 0x7a4a, 0x7bc4, 0x8319,
+ 0x0040, 0x1e28, 0xa280, 0x0032, 0x2012, 0x2010, 0x0078, 0x1e1f,
+ 0x2013, 0x0000, 0x007c, 0x017e, 0x027e, 0xd7fc, 0x00c0, 0x1e34,
+ 0x2011, 0x54c0, 0x0078, 0x1e36, 0x2011, 0x74c0, 0xa784, 0x0f00,
+ 0x800b, 0xa784, 0x001f, 0x0040, 0x1e41, 0x8003, 0x8003, 0x8003,
+ 0x8003, 0xa105, 0xa268, 0x027f, 0x017f, 0x007c, 0x1078, 0x1e2b,
+ 0x2900, 0x682a, 0x2a00, 0x682e, 0x6808, 0xa084, 0xf9ef, 0xa80d,
+ 0x690a, 0x0e7e, 0xd7fc, 0x00c0, 0x1e5b, 0x2009, 0x4f53, 0x2071,
+ 0x4f40, 0x0078, 0x1e5f, 0x2009, 0x4f93, 0x2071, 0x4f80, 0x210c,
+ 0x6804, 0xa005, 0x0040, 0x1e6f, 0xa116, 0x00c0, 0x1e6f, 0x2060,
+ 0x6000, 0x6806, 0x017e, 0x200b, 0x0000, 0x0078, 0x1e72, 0x2009,
+ 0x0000, 0x017e, 0x6804, 0xa065, 0x0040, 0x1e87, 0x6000, 0x6806,
+ 0x1078, 0x1ea2, 0x1078, 0x2064, 0x6810, 0x7908, 0x8109, 0x790a,
+ 0x8001, 0x6812, 0x00c0, 0x1e72, 0x7910, 0xc1a5, 0x7912, 0x017f,
+ 0x6902, 0x6906, 0x2d00, 0x2060, 0x1078, 0x2b13, 0x0e7f, 0x007c,
+ 0xa065, 0x0040, 0x1ea1, 0x2008, 0x609c, 0xa005, 0x0040, 0x1e9e,
+ 0x2062, 0x609f, 0x0000, 0xa065, 0x0078, 0x1e94, 0x7848, 0x794a,
+ 0x2062, 0x007c, 0x6007, 0x0103, 0x608f, 0x0000, 0x20a9, 0x001c,
+ 0xac80, 0x0005, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x6828, 0x601a,
+ 0x682c, 0x6022, 0x007c, 0x0e7e, 0xd7fc, 0x00c0, 0x1ebd, 0x2071,
+ 0x4f40, 0x2031, 0x4fc0, 0x0078, 0x1ec1, 0x2071, 0x4f80, 0x2031,
+ 0x51c0, 0x7050, 0xa08c, 0x0200, 0x00c0, 0x1ecb, 0xa608, 0x2d0a,
+ 0x8000, 0x7052, 0xa006, 0x0e7f, 0x007c, 0x0f7e, 0xd7fc, 0x00c0,
+ 0x1ed5, 0x2079, 0x4f40, 0x0078, 0x1ed7, 0x2079, 0x4f80, 0x1078,
+ 0x1e2b, 0x2091, 0x8000, 0x6804, 0x780a, 0xa065, 0x0040, 0x1f2b,
+ 0x0078, 0x1ee9, 0x2c00, 0x780a, 0x2060, 0x6000, 0xa065, 0x0040,
+ 0x1f2b, 0x6010, 0xa306, 0x00c0, 0x1ee2, 0x600c, 0xa206, 0x00c0,
+ 0x1ee2, 0x2c28, 0x784c, 0xac06, 0x00c0, 0x1ef8, 0x0078, 0x1f28,
+ 0x6804, 0xac06, 0x00c0, 0x1f06, 0x6000, 0x2060, 0x6806, 0xa005,
+ 0x00c0, 0x1f06, 0x6803, 0x0000, 0x0078, 0x1f10, 0x6400, 0x7808,
+ 0x2060, 0x6402, 0xa486, 0x0000, 0x00c0, 0x1f10, 0x2c00, 0x6802,
+ 0x2560, 0x0f7f, 0x1078, 0x1ea2, 0x0f7e, 0x601b, 0x0005, 0x6023,
+ 0x0020, 0x0f7f, 0x1078, 0x2064, 0x0f7e, 0x7908, 0x8109, 0x790a,
+ 0x6810, 0x8001, 0x6812, 0x00c0, 0x1f28, 0x7810, 0xc0a5, 0x7812,
+ 0x2001, 0xffff, 0xa005, 0x0f7f, 0x007c, 0x077e, 0x2700, 0x2039,
+ 0x0000, 0xd0fc, 0x0040, 0x1f35, 0xc7fd, 0x2041, 0x0021, 0x2049,
+ 0x0004, 0x2051, 0x0008, 0x2091, 0x8000, 0x1078, 0x1e46, 0x8738,
+ 0xa784, 0x001f, 0x00c0, 0x1f3d, 0xa7bc, 0xff00, 0x873f, 0x8738,
+ 0x873f, 0xa784, 0x0f00, 0x00c0, 0x1f3d, 0x2091, 0x8001, 0x077f,
+ 0x007c, 0x786c, 0x2009, 0x9774, 0x210c, 0xa10d, 0x0040, 0x1f5b,
+ 0xa065, 0x0078, 0x23dc, 0x2061, 0x0000, 0x6018, 0xd084, 0x00c0,
+ 0x1f7b, 0x7810, 0xd08c, 0x0040, 0x1f6c, 0xc08c, 0x7812, 0xc7fc,
+ 0x2069, 0x4f40, 0x0078, 0x1f71, 0xc08d, 0x7812, 0x2069, 0x4f80,
+ 0xc7fd, 0x2091, 0x8000, 0x681c, 0x681f, 0x0000, 0x2091, 0x8001,
+ 0xa005, 0x00c0, 0x1f7c, 0x007c, 0xa08c, 0xfff0, 0x0040, 0x1f82,
+ 0x1078, 0x29b2, 0x0079, 0x1f84, 0x1f94, 0x1f97, 0x1f9d, 0x1fa1,
+ 0x1f95, 0x1fa5, 0x1f95, 0x1f95, 0x1f95, 0x1fab, 0x1fdc, 0x1fe0,
+ 0x1fe6, 0x1ffb, 0x1f95, 0x1f95, 0x007c, 0x1078, 0x29b2, 0x1078,
+ 0x1f2d, 0x2001, 0x8001, 0x0078, 0x2007, 0x2001, 0x8003, 0x0078,
+ 0x2007, 0x2001, 0x8004, 0x0078, 0x2007, 0x1078, 0x1f2d, 0x2001,
+ 0x8006, 0x0078, 0x2007, 0x2091, 0x8000, 0x077e, 0xd7fc, 0x00c0,
+ 0x1fb7, 0x2069, 0x4f40, 0x2039, 0x0009, 0x0078, 0x1fbb, 0x2069,
+ 0x4f80, 0x2039, 0x0009, 0x6800, 0xa086, 0x0000, 0x0040, 0x1fc5,
+ 0x007f, 0x6f1e, 0x2091, 0x8001, 0x007c, 0x6874, 0x077f, 0xa0bc,
+ 0xff00, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0010, 0x1078,
+ 0x1e46, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1fcf, 0x2091, 0x8001,
+ 0x2001, 0x800a, 0x0078, 0x2007, 0x2001, 0x800c, 0x0078, 0x2007,
+ 0x1078, 0x1f2d, 0x2001, 0x800d, 0x0078, 0x2007, 0x7814, 0xd0e4,
+ 0x00c0, 0x1ff9, 0xd0ec, 0x0040, 0x1ff3, 0xd7fc, 0x0040, 0x1ff3,
+ 0x78e4, 0x0078, 0x1ff4, 0x78e0, 0x70c6, 0x2001, 0x800e, 0x0078,
+ 0x2007, 0x0078, 0x1f95, 0xd7fc, 0x0040, 0x2001, 0x78ec, 0x0078,
+ 0x2002, 0x78e8, 0x70c6, 0x2001, 0x800f, 0x0078, 0x2007, 0x70c2,
+ 0xd7fc, 0x00c0, 0x200f, 0x70db, 0x0000, 0x0078, 0x2011, 0x70db,
+ 0x0001, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x4080, 0x007c,
+ 0xac80, 0x0001, 0x81ff, 0x0040, 0x2043, 0x2099, 0x0030, 0x20a0,
+ 0x700c, 0xa084, 0x03ff, 0x0040, 0x2025, 0x7018, 0x007e, 0x701c,
+ 0x007e, 0x7020, 0x007e, 0x7024, 0x007e, 0x7112, 0x81ac, 0x721a,
+ 0x731e, 0x7422, 0x7526, 0x7003, 0x0001, 0x7007, 0x0001, 0x7008,
+ 0x800b, 0x00c8, 0x2037, 0x7007, 0x0002, 0xa08c, 0x01e0, 0x00c0,
+ 0x2043, 0x53a5, 0xa006, 0x7003, 0x0000, 0x7007, 0x0004, 0x007f,
+ 0x7026, 0x007f, 0x7022, 0x007f, 0x701e, 0x007f, 0x701a, 0x007c,
+ 0x2011, 0x0020, 0x2009, 0x0010, 0x6b0a, 0x6c0e, 0x6803, 0xfd00,
+ 0x6807, 0x0018, 0x6a1a, 0x2d00, 0xa0e8, 0x0008, 0xa290, 0x0004,
+ 0x8109, 0x00c0, 0x2054, 0x007c, 0x6004, 0x6086, 0x2c08, 0x2063,
+ 0x0000, 0x7868, 0xa005, 0x796a, 0x0040, 0x2071, 0x2c02, 0x0078,
+ 0x2072, 0x796e, 0x007c, 0x0c7e, 0x2061, 0x4f00, 0x6887, 0x0103,
+ 0x2d08, 0x206b, 0x0000, 0x6068, 0xa005, 0x616a, 0x0040, 0x2083,
+ 0x2d02, 0x0078, 0x2084, 0x616e, 0x0c7f, 0x007c, 0x2091, 0x8000,
+ 0x2c04, 0x786e, 0xa005, 0x00c0, 0x208e, 0x786a, 0x2091, 0x8001,
+ 0x609c, 0xa005, 0x0040, 0x20a7, 0x0c7e, 0x2060, 0x2008, 0x609c,
+ 0xa005, 0x0040, 0x20a3, 0x2062, 0x609f, 0x0000, 0xa065, 0x609c,
+ 0xa005, 0x00c0, 0x209b, 0x7848, 0x794a, 0x2062, 0x0c7f, 0x7848,
+ 0x2062, 0x609f, 0x0000, 0xac85, 0x0000, 0x00c0, 0x20b1, 0x1078,
+ 0x29b2, 0x784a, 0x007c, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086,
+ 0x818e, 0x00c8, 0x20bc, 0xa200, 0x00f0, 0x20b7, 0x8086, 0x818e,
+ 0x007c, 0x157e, 0x20a9, 0x0010, 0xa005, 0x0040, 0x20e2, 0xa11a,
+ 0x00c8, 0x20e2, 0x8213, 0x818d, 0x0048, 0x20d5, 0xa11a, 0x00c8,
+ 0x20d6, 0x00f0, 0x20ca, 0x0078, 0x20da, 0xa11a, 0x2308, 0x8210,
+ 0x00f0, 0x20ca, 0x007e, 0x3200, 0xa084, 0xf7ff, 0x2080, 0x007f,
+ 0x157f, 0x007c, 0x007e, 0x3200, 0xa085, 0x0800, 0x0078, 0x20de,
+ 0x7d74, 0x70d0, 0xa506, 0x0040, 0x21ce, 0x7810, 0x2050, 0x7800,
+ 0xd08c, 0x0040, 0x210a, 0xdaec, 0x0040, 0x210a, 0x0e7e, 0x2091,
+ 0x8000, 0x2071, 0x0020, 0x7004, 0xa005, 0x00c0, 0x2107, 0x7008,
+ 0x0e7f, 0xa086, 0x0008, 0x0040, 0x210a, 0x0078, 0x21ce, 0x0e7f,
+ 0x0078, 0x21ce, 0x1078, 0x1e04, 0x0040, 0x21ce, 0xa046, 0x7970,
+ 0x2500, 0x8000, 0xa112, 0x2009, 0x0040, 0x00c8, 0x2119, 0x0078,
+ 0x2120, 0x72d0, 0xa206, 0x0040, 0x2120, 0x8840, 0x2009, 0x0080,
+ 0x0c7e, 0x7112, 0x7007, 0x0001, 0x2099, 0x0030, 0x20a9, 0x0020,
+ 0xac80, 0x0001, 0x20a0, 0x2061, 0x0000, 0x88ff, 0x0040, 0x2132,
+ 0x1078, 0x1e04, 0x7008, 0xd0fc, 0x0040, 0x2132, 0x7007, 0x0002,
+ 0x2091, 0x8001, 0xa08c, 0x01e0, 0x00c0, 0x2169, 0x53a5, 0x8cff,
+ 0x00c0, 0x2147, 0x88ff, 0x0040, 0x21b8, 0x0078, 0x2151, 0x2c00,
+ 0x788e, 0x20a9, 0x0020, 0xac80, 0x0001, 0x20a0, 0x53a5, 0x0078,
+ 0x21b8, 0xa046, 0x7218, 0x731c, 0xdac4, 0x0040, 0x2159, 0x7420,
+ 0x7524, 0xa292, 0x0040, 0xa39b, 0x0000, 0xa4a3, 0x0000, 0xa5ab,
+ 0x0000, 0x721a, 0x731e, 0xdac4, 0x0040, 0x2169, 0x7422, 0x7526,
+ 0xa006, 0x7007, 0x0004, 0x0040, 0x21b8, 0x8cff, 0x0040, 0x2172,
+ 0x1078, 0x1e0d, 0x0c7f, 0x1078, 0x1e0d, 0xa046, 0x7888, 0x8000,
+ 0x788a, 0xa086, 0x0002, 0x0040, 0x2198, 0x7a7c, 0x7b78, 0xdac4,
+ 0x0040, 0x2184, 0x7c84, 0x7d80, 0x7974, 0x8107, 0x8004, 0x8004,
+ 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x721a,
+ 0x731e, 0xdac4, 0x0040, 0x21ce, 0x7422, 0x7526, 0x0078, 0x21ce,
+ 0x6014, 0xd0fc, 0x00c0, 0x21a0, 0x2069, 0x4f40, 0x0078, 0x21a2,
+ 0x2069, 0x4f80, 0x2091, 0x8000, 0x681f, 0x0002, 0x88ff, 0x0040,
+ 0x21ae, 0xa046, 0x788c, 0x2060, 0x0078, 0x2198, 0x788b, 0x0000,
+ 0x78ac, 0xa085, 0x0003, 0x78ae, 0x2091, 0x8001, 0x0078, 0x21ce,
+ 0x0c7f, 0x788b, 0x0000, 0x1078, 0x238d, 0x6004, 0xa084, 0x000f,
+ 0x1078, 0x21cf, 0x88ff, 0x0040, 0x21cc, 0x788c, 0x2060, 0x6004,
+ 0xa084, 0x000f, 0x1078, 0x21cf, 0x0078, 0x20e8, 0x007c, 0x0079,
+ 0x21d1, 0x21e1, 0x21ff, 0x221d, 0x21e1, 0x222e, 0x21f2, 0x21e1,
+ 0x21e1, 0x21e1, 0x21fd, 0x221b, 0x21e1, 0x21e1, 0x21e1, 0x21e1,
+ 0x21e1, 0x2039, 0x0400, 0x78bc, 0xa705, 0x78be, 0x6008, 0xa705,
+ 0x600a, 0x1078, 0x2271, 0x609c, 0x78ba, 0x609f, 0x0000, 0x1078,
+ 0x2377, 0x007c, 0x78bc, 0xd0c4, 0x0040, 0x21f8, 0x0078, 0x21e1,
+ 0x601c, 0xc0bd, 0x601e, 0x0078, 0x2205, 0x1078, 0x23bf, 0x78bc,
+ 0xd0c4, 0x0040, 0x2205, 0x0078, 0x21e1, 0x78bf, 0x0000, 0x6004,
+ 0x8007, 0xa084, 0x00ff, 0x78b2, 0x8001, 0x0040, 0x2218, 0x1078,
+ 0x2271, 0x0040, 0x2218, 0x78bc, 0xc0c5, 0x78be, 0x0078, 0x221a,
+ 0x0078, 0x2290, 0x007c, 0x1078, 0x23bb, 0x78bc, 0xa08c, 0x0e00,
+ 0x00c0, 0x2225, 0xd0c4, 0x00c0, 0x2227, 0x0078, 0x21e1, 0x1078,
+ 0x2271, 0x00c0, 0x222d, 0x0078, 0x2290, 0x007c, 0x78bc, 0xd0c4,
+ 0x0040, 0x2234, 0x0078, 0x21e1, 0x78bf, 0x0000, 0x6714, 0x2011,
+ 0x0001, 0x22a8, 0x6018, 0xa084, 0x00ff, 0xa005, 0x0040, 0x2254,
+ 0xa7bc, 0xff00, 0x20a9, 0x0020, 0xa08e, 0x0001, 0x0040, 0x2254,
+ 0xa7bc, 0x8000, 0x2011, 0x0002, 0x20a9, 0x0100, 0xa08e, 0x0002,
+ 0x0040, 0x2254, 0x0078, 0x226e, 0x1078, 0x1e2b, 0x2d00, 0x2091,
+ 0x8000, 0x682b, 0x0000, 0x682f, 0x0000, 0x6808, 0xa084, 0xffde,
+ 0x680a, 0xade8, 0x0010, 0x2091, 0x8001, 0x00f0, 0x2257, 0x8211,
+ 0x0040, 0x226e, 0x20a9, 0x0100, 0x0078, 0x2257, 0x1078, 0x1e0d,
+ 0x007c, 0x609f, 0x0000, 0x78b4, 0xa06d, 0x2c00, 0x78b6, 0x00c0,
+ 0x227c, 0x78ba, 0x0078, 0x2284, 0x689e, 0x2d00, 0x6002, 0x78b8,
+ 0xad06, 0x00c0, 0x2284, 0x6002, 0x78b0, 0x8001, 0x78b2, 0x00c0,
+ 0x228f, 0x78bc, 0xc0c4, 0x78be, 0x78b8, 0x2060, 0xa006, 0x007c,
+ 0x0e7e, 0xa02e, 0x2530, 0x7dba, 0x7db6, 0x65ae, 0x65b2, 0x601c,
+ 0x60a2, 0x2048, 0xa984, 0xe1ff, 0x601e, 0xa984, 0x0060, 0x0040,
+ 0x22a3, 0x1078, 0x46b6, 0x6596, 0x65a6, 0x669a, 0x66aa, 0x6714,
+ 0x2071, 0x4f80, 0xd7fc, 0x00c0, 0x22af, 0x2071, 0x4f40, 0xa784,
+ 0x0f00, 0x800b, 0xa784, 0x001f, 0x0040, 0x22ba, 0x8003, 0x8003,
+ 0x8003, 0x8003, 0xa105, 0x71c4, 0xa168, 0x2700, 0x8007, 0xa084,
+ 0x000f, 0x8003, 0x8003, 0x8003, 0x71c8, 0xa100, 0x60c2, 0x2091,
+ 0x8000, 0x7814, 0xd0c4, 0x0040, 0x22df, 0xd0ec, 0x0040, 0x22db,
+ 0xd7fc, 0x00c0, 0x22d8, 0xd0f4, 0x00c0, 0x22e6, 0x0078, 0x22df,
+ 0xd0fc, 0x00c0, 0x22e6, 0x7810, 0xd0f4, 0x00c0, 0x22e6, 0x6e08,
+ 0xd684, 0x0040, 0x2310, 0xd9fc, 0x00c0, 0x2310, 0x2091, 0x8001,
+ 0x1078, 0x1ea2, 0x2091, 0x8000, 0x1078, 0x2064, 0x2091, 0x8001,
+ 0x7814, 0xd0e4, 0x00c0, 0x2375, 0x7814, 0xd0c4, 0x0040, 0x2375,
+ 0xd0ec, 0x0040, 0x2308, 0xd7fc, 0x00c0, 0x2303, 0xd0f4, 0x00c0,
+ 0x230c, 0x0078, 0x2375, 0xd0fc, 0x00c0, 0x230c, 0x0078, 0x2375,
+ 0x7810, 0xd0f4, 0x0040, 0x2375, 0x601b, 0x0021, 0x0078, 0x2375,
+ 0x6024, 0xa096, 0x0001, 0x00c0, 0x2317, 0x8000, 0x6026, 0x6a10,
+ 0x6814, 0xa202, 0x0048, 0x232a, 0x0040, 0x232a, 0x2091, 0x8001,
+ 0x2039, 0x0200, 0x609c, 0x78ba, 0x609f, 0x0000, 0x1078, 0x2377,
+ 0x0078, 0x2375, 0x2c08, 0xd9fc, 0x0040, 0x2352, 0x6800, 0xa065,
+ 0x0040, 0x2352, 0x6a04, 0x7000, 0xa084, 0x0002, 0x0040, 0x2348,
+ 0x704c, 0xa206, 0x00c0, 0x2348, 0x6b04, 0x2160, 0x2304, 0x6002,
+ 0xa005, 0x00c0, 0x2344, 0x6902, 0x2260, 0x6102, 0x0078, 0x235e,
+ 0x2d00, 0x2060, 0x1078, 0x2b13, 0x6e08, 0x2160, 0x6202, 0x6906,
+ 0x0078, 0x235e, 0x6800, 0x6902, 0xa065, 0x0040, 0x235a, 0x6102,
+ 0x0078, 0x235b, 0x6906, 0x2160, 0x6003, 0x0000, 0x2160, 0xd9fc,
+ 0x0040, 0x2365, 0xa6b4, 0xfffc, 0x6e0a, 0x6810, 0x7d08, 0x8528,
+ 0x7d0a, 0x8000, 0x6812, 0x2091, 0x8001, 0xd6b4, 0x0040, 0x2375,
+ 0xa6b6, 0x0040, 0x6e0a, 0x1078, 0x1eb3, 0x0e7f, 0x007c, 0x6008,
+ 0xa705, 0x600a, 0x2091, 0x8000, 0x1078, 0x2064, 0x2091, 0x8001,
+ 0x78b8, 0xa065, 0x0040, 0x238a, 0x609c, 0x78ba, 0x609f, 0x0000,
+ 0x0078, 0x2377, 0x78b6, 0x78ba, 0x007c, 0x7970, 0x7874, 0x2818,
+ 0xd384, 0x0040, 0x2397, 0x8000, 0xa112, 0x0048, 0x239c, 0x8000,
+ 0xa112, 0x00c8, 0x23ac, 0xc384, 0x7a7c, 0x721a, 0x7a78, 0x721e,
+ 0xdac4, 0x0040, 0x23a7, 0x7a84, 0x7222, 0x7a80, 0x7226, 0xa006,
+ 0xd384, 0x0040, 0x23ac, 0x8000, 0x7876, 0x70d2, 0x781c, 0xa005,
+ 0x0040, 0x23ba, 0x8001, 0x781e, 0x00c0, 0x23ba, 0x0068, 0x23ba,
+ 0x2091, 0x4080, 0x007c, 0x2039, 0x23d3, 0x0078, 0x23c1, 0x2039,
+ 0x23d9, 0x2704, 0xa005, 0x0040, 0x23d2, 0xac00, 0x2068, 0x6908,
+ 0x6810, 0x6912, 0x680a, 0x690c, 0x6814, 0x6916, 0x680e, 0x8738,
+ 0x0078, 0x23c1, 0x007c, 0x0003, 0x0009, 0x000f, 0x0015, 0x001b,
+ 0x0000, 0x0015, 0x001b, 0x0000, 0x2041, 0x0000, 0x780c, 0x0079,
+ 0x23e1, 0x25b3, 0x2586, 0x23e5, 0x245e, 0x2039, 0x9774, 0x2734,
+ 0x7d10, 0x0078, 0x2405, 0x6084, 0xa086, 0x0103, 0x00c0, 0x2447,
+ 0x6114, 0x6018, 0xa105, 0x0040, 0x23fa, 0x86ff, 0x00c0, 0x2416,
+ 0x0078, 0x2447, 0x8603, 0xa080, 0x9755, 0x620c, 0x2202, 0x8000,
+ 0x6210, 0x2202, 0x1078, 0x2086, 0x8630, 0xa68e, 0x000f, 0x0040,
+ 0x24d2, 0x786c, 0xa065, 0x00c0, 0x23eb, 0x7808, 0xa602, 0x00c8,
+ 0x2416, 0xd5ac, 0x00c0, 0x2416, 0x263a, 0x007c, 0xa682, 0x0003,
+ 0x00c8, 0x24d2, 0x2091, 0x8000, 0x2069, 0x0000, 0x6818, 0xd084,
+ 0x00c0, 0x2442, 0x2011, 0x9755, 0x2204, 0x70c6, 0x8210, 0x2204,
+ 0x70ca, 0xd684, 0x00c0, 0x2432, 0x8210, 0x2204, 0x70da, 0x8210,
+ 0x2204, 0x70de, 0xa685, 0x8020, 0x70c2, 0x681b, 0x0001, 0x2091,
+ 0x4080, 0x7810, 0xa084, 0xffcf, 0x7812, 0x2091, 0x8001, 0x203b,
+ 0x0000, 0x007c, 0x7810, 0xc0ad, 0x7812, 0x0078, 0x24d2, 0x263a,
+ 0x1078, 0x25bd, 0x00c0, 0x25e0, 0x786c, 0xa065, 0x00c0, 0x23eb,
+ 0x2091, 0x8000, 0x7810, 0xa084, 0xffcf, 0x86ff, 0x0040, 0x2459,
+ 0xc0ad, 0x7812, 0x2091, 0x8001, 0x0078, 0x25e0, 0x2039, 0x9774,
+ 0x2734, 0x7d10, 0x0078, 0x247a, 0x6084, 0xa086, 0x0103, 0x00c0,
+ 0x24bb, 0x6114, 0x6018, 0xa105, 0x0040, 0x2473, 0x86ff, 0x00c0,
+ 0x248b, 0x0078, 0x24bb, 0xa680, 0x9755, 0x620c, 0x2202, 0x1078,
+ 0x2086, 0x8630, 0xa68e, 0x001e, 0x0040, 0x24d2, 0x786c, 0xa065,
+ 0x00c0, 0x2464, 0x7808, 0xa602, 0x00c8, 0x248b, 0xd5ac, 0x00c0,
+ 0x248b, 0x263a, 0x007c, 0xa682, 0x0006, 0x00c8, 0x24d2, 0x2091,
+ 0x8000, 0x2069, 0x0000, 0x6818, 0xd084, 0x00c0, 0x24b6, 0x2011,
+ 0x9755, 0x2009, 0x974e, 0x26a8, 0x211c, 0x2204, 0x201a, 0x8108,
+ 0x8210, 0x00f0, 0x249c, 0xa685, 0x8030, 0x70c2, 0x681b, 0x0001,
0x2091, 0x4080, 0x7810, 0xa084, 0xffcf, 0x7812, 0x2091, 0x8001,
- 0x203b, 0x0000, 0x007c, 0x7810, 0xc0ad, 0x7812, 0x0078, 0x248b,
- 0x263a, 0x1078, 0x2576, 0x00c0, 0x2599, 0x786c, 0xa065, 0x00c0,
- 0x23a4, 0x2091, 0x8000, 0x7810, 0xa084, 0xffcf, 0x86ff, 0x0040,
- 0x2412, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x0078, 0x2599, 0x2039,
- 0x9674, 0x2734, 0x7d10, 0x0078, 0x2433, 0x6084, 0xa086, 0x0103,
- 0x00c0, 0x2474, 0x6114, 0x6018, 0xa105, 0x0040, 0x242c, 0x86ff,
- 0x00c0, 0x2444, 0x0078, 0x2474, 0xa680, 0x9655, 0x620c, 0x2202,
- 0x1078, 0x203f, 0x8630, 0xa68e, 0x001e, 0x0040, 0x248b, 0x786c,
- 0xa065, 0x00c0, 0x241d, 0x7808, 0xa602, 0x00c8, 0x2444, 0xd5ac,
- 0x00c0, 0x2444, 0x263a, 0x007c, 0xa682, 0x0006, 0x00c8, 0x248b,
- 0x2091, 0x8000, 0x2069, 0x0000, 0x6818, 0xd084, 0x00c0, 0x246f,
- 0x2011, 0x9655, 0x2009, 0x964e, 0x26a8, 0x211c, 0x2204, 0x201a,
- 0x8108, 0x8210, 0x00f0, 0x2455, 0xa685, 0x8030, 0x70c2, 0x681b,
- 0x0001, 0x2091, 0x4080, 0x7810, 0xa084, 0xffcf, 0x7812, 0x2091,
- 0x8001, 0xa006, 0x2009, 0x9675, 0x200a, 0x203a, 0x007c, 0x7810,
- 0xc0ad, 0x7812, 0x0078, 0x248b, 0x263a, 0x1078, 0x2576, 0x00c0,
- 0x2599, 0x786c, 0xa065, 0x00c0, 0x241d, 0x2091, 0x8000, 0x7810,
- 0xa084, 0xffcf, 0x86ff, 0x0040, 0x2486, 0xc0ad, 0x7812, 0x2091,
- 0x8001, 0x0078, 0x2599, 0x2091, 0x8000, 0x7007, 0x0004, 0x7994,
- 0x70d4, 0xa102, 0x0048, 0x249c, 0x0040, 0x24a6, 0x7b90, 0xa302,
- 0x00c0, 0x24a6, 0x0078, 0x249f, 0x8002, 0x00c0, 0x24a6, 0x263a,
- 0x7810, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x007c, 0xa184, 0xff00,
- 0x0040, 0x24b3, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007,
- 0xa100, 0x0078, 0x24b6, 0x8107, 0x8004, 0x8004, 0x7a9c, 0xa210,
- 0x721a, 0x7a98, 0xa006, 0xa211, 0x721e, 0xd4c4, 0x0040, 0x24c6,
- 0x7aa4, 0xa211, 0x7222, 0x7aa0, 0xa211, 0x7226, 0x20a1, 0x0030,
- 0x7003, 0x0000, 0x2009, 0x9654, 0x260a, 0x8109, 0x2198, 0x2104,
- 0xd084, 0x0040, 0x24d4, 0x8633, 0xa6b0, 0x0002, 0x26a8, 0x53a6,
- 0x8603, 0x7012, 0x7007, 0x0001, 0x7990, 0x7894, 0x8000, 0xa10a,
- 0x00c8, 0x24e3, 0xa006, 0x2028, 0x7974, 0xa184, 0xff00, 0x0040,
- 0x24f2, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100,
- 0x0078, 0x24f5, 0x8107, 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78,
- 0xa006, 0xa211, 0xd4c4, 0x0040, 0x2501, 0x7b84, 0xa319, 0x7c80,
- 0xa421, 0x7008, 0xd0fc, 0x0040, 0x2501, 0xa084, 0x01e0, 0x0040,
- 0x2526, 0x7d10, 0x2031, 0x9654, 0x2634, 0x78a8, 0x8000, 0x78aa,
- 0xd08c, 0x00c0, 0x251b, 0x7007, 0x0006, 0x7004, 0xd094, 0x00c0,
- 0x2515, 0x0078, 0x248d, 0x2069, 0x4e47, 0x206b, 0x0003, 0x78ac,
- 0xa085, 0x0300, 0x78ae, 0xa006, 0x0078, 0x252f, 0x2030, 0x75d6,
- 0x2091, 0x4080, 0x7d96, 0x7d10, 0xa5ac, 0xffcf, 0x7d12, 0x2091,
- 0x8001, 0x78aa, 0x7007, 0x0006, 0x263a, 0x7003, 0x0001, 0x711a,
- 0x721e, 0xd5c4, 0x0040, 0x253e, 0x7322, 0x7426, 0x007c, 0x6084,
- 0xa086, 0x0103, 0x00c0, 0x2562, 0x6114, 0x6018, 0xa105, 0x00c0,
- 0x2562, 0x2069, 0x0000, 0x6818, 0xd084, 0x00c0, 0x2562, 0x600c,
- 0x70c6, 0x6010, 0x70ca, 0x70c3, 0x8020, 0x681b, 0x0001, 0x2091,
- 0x4080, 0x1078, 0x203f, 0x0068, 0x2561, 0x786c, 0xa065, 0x00c0,
- 0x253f, 0x007c, 0x1078, 0x2576, 0x00c0, 0x2599, 0x786c, 0xa065,
- 0x00c0, 0x253f, 0x0078, 0x2599, 0x1078, 0x2576, 0x00c0, 0x2599,
- 0x786c, 0xa065, 0x00c0, 0x256c, 0x0078, 0x2599, 0x6084, 0xa086,
- 0x0103, 0x00c0, 0x258a, 0x6018, 0xc0fc, 0x601a, 0xa086, 0x0004,
- 0x00c0, 0x258a, 0x7804, 0xd0a4, 0x0040, 0x258a, 0x1078, 0x203f,
- 0xa006, 0x007c, 0x1078, 0x259f, 0x00c0, 0x2591, 0xa085, 0x0001,
- 0x007c, 0x1078, 0x25ae, 0x00c0, 0x2597, 0x2041, 0x0001, 0x7d10,
- 0x007c, 0x88ff, 0x0040, 0x259e, 0x2091, 0x4080, 0x007c, 0x7b90,
- 0x7994, 0x70d4, 0xa102, 0x00c0, 0x25a8, 0xa385, 0x0000, 0x007c,
- 0x0048, 0x25ac, 0xa302, 0x007c, 0x8002, 0x007c, 0x7810, 0xd0ec,
- 0x0040, 0x25c6, 0x0e7e, 0x2091, 0x8000, 0x2071, 0x0020, 0x7004,
- 0xa005, 0x00c0, 0x25c3, 0x7008, 0x0e7f, 0xa086, 0x0008, 0x0040,
- 0x25c6, 0x0078, 0x2617, 0x0e7f, 0x0078, 0x2617, 0xa184, 0xff00,
- 0x0040, 0x25d3, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007,
- 0xa100, 0x0078, 0x25d6, 0x8107, 0x8004, 0x8004, 0x7a9c, 0x7b98,
- 0x7ca4, 0x7da0, 0xa210, 0xa006, 0xa319, 0xa421, 0xa529, 0x2009,
- 0x0018, 0x6028, 0xa005, 0x0040, 0x25e7, 0x2009, 0x0040, 0x1078,
- 0x1d74, 0x0040, 0x2609, 0x78a8, 0x8000, 0x78aa, 0xd08c, 0x00c0,
- 0x2617, 0x6014, 0xd0fc, 0x00c0, 0x25f9, 0x2069, 0x4e40, 0x0078,
- 0x25fb, 0x2069, 0x4e80, 0x2091, 0x8000, 0x681f, 0x0003, 0x78ab,
- 0x0000, 0x78ac, 0xa085, 0x0300, 0x78ae, 0x2091, 0x8001, 0x0078,
- 0x2617, 0x78ab, 0x0000, 0x1078, 0x203f, 0x7990, 0x7894, 0x8000,
- 0xa10a, 0x00c8, 0x2614, 0xa006, 0x7896, 0x70d6, 0xa006, 0x2071,
- 0x0010, 0x2091, 0x8001, 0x007c, 0xd7fc, 0x00c0, 0x2623, 0x2009,
- 0x4e59, 0x0078, 0x2625, 0x2009, 0x4e99, 0x2091, 0x8000, 0x200a,
- 0x0f7e, 0xd7fc, 0x00c0, 0x263c, 0x2009, 0x4e40, 0x2001, 0x4e04,
- 0x2004, 0xd0ec, 0x0040, 0x2638, 0x2079, 0x0100, 0x0078, 0x2640,
- 0x2079, 0x0200, 0x0078, 0x2640, 0x2009, 0x4e80, 0x2079, 0x0100,
- 0x2104, 0xa086, 0x0000, 0x00c0, 0x2659, 0xd7fc, 0x00c0, 0x264c,
- 0x2009, 0x4e45, 0x0078, 0x264e, 0x2009, 0x4e85, 0x2104, 0xa005,
- 0x00c0, 0x2659, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x2659, 0x781b,
- 0x0045, 0x0f7f, 0x007c, 0x2009, 0x0002, 0x2069, 0x4e00, 0x6810,
- 0xd0ec, 0x00c0, 0x26c8, 0x2071, 0x4e80, 0x2079, 0x0100, 0x2021,
- 0x50bf, 0x784b, 0x000f, 0x2019, 0x4457, 0xd184, 0x0040, 0x267c,
- 0x6810, 0xd0ec, 0x0040, 0x2678, 0x20a1, 0x012b, 0x0078, 0x267e,
- 0x20a1, 0x022b, 0x0078, 0x267e, 0x20a1, 0x012b, 0x2304, 0xa005,
- 0x0040, 0x268b, 0x789a, 0x8318, 0x23ac, 0x8318, 0x2398, 0x53a6,
- 0x3318, 0x0078, 0x267e, 0x789b, 0x0020, 0x20a9, 0x0010, 0x6814,
- 0xd0e4, 0x0040, 0x269b, 0x78af, 0x0000, 0x78af, 0x9020, 0x00f0,
- 0x2693, 0x0078, 0x26a1, 0x78af, 0x0000, 0x78af, 0x8020, 0x00f0,
- 0x269b, 0x7003, 0x0000, 0x017e, 0xd18c, 0x2009, 0x0000, 0x0040,
- 0x26aa, 0xc1bd, 0x1078, 0x289b, 0x017f, 0x7020, 0xa084, 0x000f,
- 0x007e, 0x6814, 0xd0e4, 0x007f, 0x00c0, 0x26ba, 0xa085, 0x6340,
- 0x0078, 0x26bc, 0xa085, 0x62c0, 0x7806, 0x780f, 0x9200, 0x7843,
- 0x00d8, 0x7853, 0x0080, 0x780b, 0x0008, 0x7456, 0x7053, 0x0000,
- 0x8109, 0x0040, 0x26db, 0x2071, 0x4e40, 0x6810, 0xd0ec, 0x0040,
- 0x26d5, 0x2079, 0x0100, 0x0078, 0x26d7, 0x2079, 0x0200, 0x2021,
- 0x4ebf, 0x0078, 0x2669, 0x007c, 0x017e, 0xd1bc, 0x00c0, 0x26f0,
- 0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x26ec,
- 0x2011, 0x0101, 0x0078, 0x26f2, 0x2011, 0x0201, 0x0078, 0x26f2,
- 0x2011, 0x0101, 0xa18c, 0x000f, 0x2204, 0xa084, 0xfff0, 0xa105,
- 0x2012, 0x017f, 0x1078, 0x289b, 0x007c, 0xd3fc, 0x00c0, 0x2710,
- 0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x270c,
- 0x2011, 0x0101, 0x0078, 0x2712, 0x2011, 0x0201, 0x0078, 0x2712,
- 0x2011, 0x0101, 0x20a9, 0x0009, 0x810b, 0x00f0, 0x2714, 0xa18c,
- 0x0e00, 0x2204, 0xa084, 0xf1ff, 0xa105, 0x2012, 0x007c, 0x2019,
- 0x0002, 0x2001, 0x4e04, 0x2004, 0xd0ec, 0x0040, 0x272c, 0x8319,
- 0x2009, 0x0101, 0x0078, 0x272e, 0x2009, 0x0101, 0x20a9, 0x0005,
- 0x8213, 0x00f0, 0x2730, 0xa294, 0x00e0, 0x2104, 0xa084, 0xff1f,
- 0xa205, 0x200a, 0x8319, 0x0040, 0x2741, 0x2009, 0x0201, 0x0078,
- 0x272e, 0x007c, 0xd3fc, 0x00c0, 0x2755, 0x007e, 0x2001, 0x4e04,
- 0x2004, 0xd0ec, 0x007f, 0x0040, 0x2751, 0x2011, 0x0101, 0x0078,
- 0x2757, 0x2011, 0x0201, 0x0078, 0x2757, 0x2011, 0x0101, 0x20a9,
- 0x000c, 0x810b, 0x00f0, 0x2759, 0xa18c, 0xf000, 0x2204, 0xa084,
- 0x0fff, 0xa105, 0x2012, 0x007c, 0xd3fc, 0x00c0, 0x2777, 0x007e,
- 0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x2773, 0x2011,
- 0x0102, 0x0078, 0x2779, 0x2011, 0x0202, 0x0078, 0x2779, 0x2011,
- 0x0102, 0x2204, 0xa084, 0xffcf, 0xa105, 0x2012, 0x007c, 0x0c7e,
- 0xd1bc, 0x00c0, 0x2793, 0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec,
- 0x007f, 0x0040, 0x278f, 0x2061, 0x0100, 0x0078, 0x2795, 0x2061,
- 0x0200, 0x0078, 0x2795, 0x2061, 0x0100, 0xc1bc, 0x8103, 0x8003,
- 0xa080, 0x0020, 0x609a, 0x62ac, 0x63ac, 0x0c7f, 0x007c, 0x0c7e,
- 0xd1bc, 0x00c0, 0x27b3, 0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec,
- 0x007f, 0x0040, 0x27af, 0x2061, 0x0100, 0x0078, 0x27b5, 0x2061,
- 0x0200, 0x0078, 0x27b5, 0x2061, 0x0100, 0xc1bc, 0x8103, 0x8003,
- 0xa080, 0x0022, 0x609a, 0x60a4, 0xa084, 0xffdf, 0x60ae, 0x0c7f,
- 0x007c, 0x0c7e, 0xd1bc, 0x00c0, 0x27d5, 0x007e, 0x2001, 0x4e04,
- 0x2004, 0xd0ec, 0x007f, 0x0040, 0x27d1, 0x2061, 0x0100, 0x0078,
- 0x27d7, 0x2061, 0x0200, 0x0078, 0x27d7, 0x2061, 0x0100, 0xc1bc,
- 0x8103, 0x8003, 0xa080, 0x0022, 0x609a, 0x60a4, 0xa085, 0x0020,
- 0x60ae, 0x0c7f, 0x007c, 0x0c7e, 0xd1bc, 0x00c0, 0x27f7, 0x007e,
- 0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x27f3, 0x2061,
- 0x0100, 0x0078, 0x27f9, 0x2061, 0x0200, 0x0078, 0x27f9, 0x2061,
- 0x0100, 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0020, 0x609a, 0x60a4,
- 0xa28c, 0x0020, 0x0040, 0x2807, 0xc2ac, 0xa39d, 0x4000, 0xc3fc,
- 0xd3b4, 0x00c0, 0x280c, 0xc3fd, 0x62ae, 0x2010, 0x60a4, 0x63ae,
- 0x2018, 0x0c7f, 0x007c, 0x2091, 0x8000, 0x0c7e, 0x0e7e, 0x6818,
- 0xa005, 0x0040, 0x2879, 0xd1fc, 0x0040, 0x2822, 0x2061, 0x95d0,
- 0x0078, 0x2824, 0x2061, 0x94c0, 0x1078, 0x2881, 0x0040, 0x285b,
- 0x20a9, 0x0101, 0xd1fc, 0x0040, 0x2831, 0x2061, 0x94d0, 0x0078,
- 0x2833, 0x2061, 0x93c0, 0x0c7e, 0x1078, 0x2881, 0x0040, 0x283e,
- 0x0c7f, 0x8c60, 0x00f0, 0x2833, 0x0078, 0x2879, 0x007f, 0xd1fc,
- 0x0040, 0x2848, 0xa082, 0x94d0, 0x2071, 0x4e80, 0x0078, 0x284c,
- 0xa082, 0x93c0, 0x2071, 0x4e40, 0x707a, 0x7176, 0x2138, 0x2001,
- 0x0004, 0x7066, 0x7083, 0x000f, 0x71d4, 0xc1dc, 0x71d6, 0x1078,
- 0x261c, 0x0078, 0x2875, 0xd1fc, 0x00c0, 0x2862, 0x2071, 0x4e40,
- 0x0078, 0x2864, 0x2071, 0x4e80, 0x6020, 0xc0dd, 0x6022, 0x7176,
- 0x2138, 0x2c00, 0x707e, 0x2001, 0x0006, 0x7066, 0x7083, 0x000f,
- 0x71d4, 0xc1dc, 0x71d6, 0x1078, 0x261c, 0x2001, 0x0000, 0x0078,
- 0x287b, 0x2001, 0x0001, 0x2091, 0x8001, 0xa005, 0x0e7f, 0x0c7f,
- 0x007c, 0x2c04, 0xa005, 0x0040, 0x2898, 0x2060, 0x6010, 0xa306,
- 0x00c0, 0x2895, 0x600c, 0xa206, 0x00c0, 0x2895, 0x6014, 0xa106,
- 0x00c0, 0x2895, 0xa006, 0x0078, 0x289a, 0x6000, 0x0078, 0x2882,
- 0xa085, 0x0001, 0x007c, 0x0f7e, 0x0e7e, 0x017e, 0xd1bc, 0x00c0,
- 0x28b3, 0x2079, 0x4e40, 0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec,
- 0x007f, 0x0040, 0x28af, 0x2071, 0x0100, 0x0078, 0x28b7, 0x2071,
- 0x0200, 0x0078, 0x28b7, 0x2079, 0x4e80, 0x2071, 0x0100, 0x7920,
- 0xa18c, 0x000f, 0x70ec, 0xd0c4, 0x00c0, 0x28c1, 0x017f, 0x0078,
- 0x28dc, 0x810b, 0x810b, 0x810b, 0x810b, 0x007f, 0xd0bc, 0x00c0,
- 0x28d9, 0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f, 0x0040,
- 0x28d5, 0xa18d, 0x0f00, 0x0078, 0x28db, 0xa18d, 0x0f00, 0x0078,
- 0x28db, 0xa18d, 0x0800, 0x2104, 0x0e7f, 0x0f7f, 0x007c, 0x0e7e,
- 0x2001, 0x4e01, 0x2004, 0xd0ac, 0x00c0, 0x295c, 0x68e4, 0xd0ac,
- 0x0040, 0x295c, 0xa084, 0x0006, 0x00c0, 0x295c, 0x6014, 0xd0fc,
- 0x00c0, 0x28f6, 0x2071, 0x52c0, 0x0078, 0x28f8, 0x2071, 0x5340,
- 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xae70, 0x7004,
- 0xa084, 0x000a, 0x00c0, 0x295c, 0x7108, 0xa194, 0xff00, 0x0040,
- 0x295c, 0xa18c, 0x00ff, 0x2001, 0x000a, 0xa106, 0x0040, 0x292b,
- 0x2001, 0x000c, 0xa106, 0x0040, 0x292f, 0x2001, 0x0012, 0xa106,
- 0x0040, 0x2933, 0x2001, 0x0014, 0xa106, 0x0040, 0x2937, 0x2001,
- 0x0019, 0xa106, 0x0040, 0x293b, 0x2001, 0x0032, 0xa106, 0x0040,
- 0x293f, 0x0078, 0x2943, 0x2009, 0x000c, 0x0078, 0x2945, 0x2009,
- 0x0012, 0x0078, 0x2945, 0x2009, 0x0014, 0x0078, 0x2945, 0x2009,
- 0x0019, 0x0078, 0x2945, 0x2009, 0x0020, 0x0078, 0x2945, 0x2009,
- 0x003f, 0x0078, 0x2945, 0x2011, 0x0000, 0x2100, 0xa205, 0x700a,
- 0x2071, 0x4e00, 0x7004, 0xd0bc, 0x0040, 0x295c, 0x6014, 0xd0fc,
- 0x00c0, 0x2957, 0x70ea, 0x2071, 0x4e40, 0x0078, 0x295a, 0x70ee,
- 0x2071, 0x4e80, 0x701f, 0x000d, 0x0e7f, 0x007c, 0x2001, 0x4e05,
- 0x2004, 0xd0e4, 0x00c0, 0x296a, 0x7804, 0xa084, 0xff1f, 0xa085,
- 0x6340, 0x7806, 0x007c, 0x0068, 0x296b, 0x2091, 0x8000, 0x2071,
- 0x0000, 0x007e, 0x7018, 0xd084, 0x00c0, 0x2972, 0x007f, 0x2071,
- 0x0010, 0x70ca, 0x007f, 0x70c6, 0x70c3, 0x8002, 0x70db, 0x080f,
- 0x70df, 0x0000, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080,
- 0x0078, 0x2988, 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x78a0, 0x708e,
- 0x7592, 0x7496, 0x769a, 0x779e, 0xa594, 0x003f, 0xd4f4, 0x0040,
- 0x299f, 0xa784, 0x007d, 0x00c0, 0x43cd, 0x1078, 0x296b, 0xa49c,
- 0x000f, 0xa382, 0x0004, 0x0050, 0x29aa, 0xa3a6, 0x0007, 0x00c0,
- 0x296b, 0x2418, 0x8507, 0xa084, 0x000f, 0x0079, 0x29af, 0x3028,
- 0x3119, 0x3144, 0x33b6, 0x379f, 0x3819, 0x38ce, 0x395f, 0x3a4d,
- 0x3b3c, 0x29c2, 0x29bf, 0x2df9, 0x2f1c, 0x3770, 0x29bf, 0x1078,
- 0x296b, 0x007c, 0xa006, 0x0078, 0x29cc, 0x7808, 0xc08d, 0x780a,
- 0xa006, 0x7002, 0x704e, 0x7046, 0x70d2, 0x7060, 0xa005, 0x00c0,
- 0x2b32, 0x7064, 0xa084, 0x0007, 0x0079, 0x29d6, 0x29de, 0x2a51,
- 0x2a5a, 0x2a65, 0x2a70, 0x2b18, 0x2a7b, 0x2a51, 0x7830, 0xd0bc,
- 0x00c0, 0x29c1, 0x71d4, 0xd1bc, 0x00c0, 0x29c1, 0xd1b4, 0x00c0,
- 0x2a2e, 0x70a4, 0xa086, 0x0001, 0x0040, 0x29c1, 0x70b4, 0xa06d,
- 0x6800, 0xa065, 0xa055, 0x789b, 0x0010, 0x6b0c, 0x7baa, 0x6808,
- 0xa045, 0x6d10, 0x6804, 0xa06d, 0xa05d, 0xa886, 0x0001, 0x0040,
- 0x2a04, 0x69bc, 0x7daa, 0x79aa, 0x68c0, 0xa04d, 0x6e1c, 0x2001,
- 0x0010, 0x0078, 0x2c8c, 0x7060, 0xa005, 0x00c0, 0x29c1, 0x0c7e,
- 0x0d7e, 0x70b4, 0xa06d, 0x6800, 0xa065, 0xa055, 0x789b, 0x0010,
- 0x6b0c, 0x7baa, 0x6808, 0xa045, 0x6d10, 0x6804, 0xa06d, 0xa05d,
- 0xa886, 0x0001, 0x0040, 0x2a27, 0x69bc, 0x7daa, 0x79aa, 0x68c0,
- 0xa04d, 0x6e1c, 0x2001, 0x0020, 0x0078, 0x2c8c, 0x1078, 0x4360,
- 0x00c0, 0x29c1, 0x781b, 0x005b, 0x70bc, 0xa06d, 0x68b4, 0x785a,
- 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0x7808, 0xc08d,
- 0x780a, 0x68bc, 0x7042, 0xc1b4, 0x71d6, 0x70b8, 0xa065, 0x68c0,
- 0x705a, 0x7003, 0x0002, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046,
- 0x007c, 0x1078, 0x4360, 0x00c0, 0x2a59, 0x781b, 0x0047, 0x7003,
- 0x0004, 0x007c, 0x1078, 0x4360, 0x00c0, 0x2a64, 0x2011, 0x000c,
- 0x1078, 0x2a8b, 0x7003, 0x0004, 0x007c, 0x1078, 0x4360, 0x00c0,
- 0x2a6f, 0x2011, 0x0006, 0x1078, 0x2a8b, 0x7003, 0x0004, 0x007c,
- 0x1078, 0x4360, 0x00c0, 0x2a7a, 0x2011, 0x000d, 0x1078, 0x2a8b,
- 0x7003, 0x0004, 0x007c, 0x1078, 0x4360, 0x00c0, 0x2a8a, 0x2011,
- 0x0006, 0x1078, 0x2a8b, 0x707c, 0x707f, 0x0000, 0x2068, 0x704e,
- 0x7003, 0x0001, 0x007c, 0x7174, 0xc1fc, 0x8107, 0x7882, 0x789b,
- 0x0010, 0xa286, 0x000c, 0x00c0, 0x2a9a, 0x7aaa, 0x2001, 0x0001,
- 0x0078, 0x2aaf, 0xa18c, 0x001f, 0xa18d, 0x00c0, 0x79aa, 0xa286,
- 0x000d, 0x0040, 0x2aa8, 0x7aaa, 0x2001, 0x0002, 0x0078, 0x2aaf,
- 0x78ab, 0x0020, 0x7178, 0x79aa, 0x7aaa, 0x2001, 0x0004, 0x789b,
- 0x0060, 0x78aa, 0x785b, 0x0004, 0x781b, 0x0116, 0x1078, 0x4383,
- 0x7083, 0x000f, 0x70d4, 0xd0b4, 0x0040, 0x2acb, 0xc0b4, 0x70d6,
- 0x0c7e, 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018,
- 0x8001, 0x601a, 0x0c7f, 0x007c, 0x7014, 0xa005, 0x00c0, 0x2ada,
- 0x70d4, 0xd0b4, 0x0040, 0x2adb, 0x70b8, 0xac06, 0x00c0, 0x2adb,
- 0x1078, 0x2aba, 0x007c, 0x017e, 0x71a4, 0xa186, 0x0001, 0x0040,
- 0x2b0d, 0x0d7e, 0x027e, 0x2100, 0x2011, 0x0001, 0xa212, 0x70b4,
- 0x2068, 0x6800, 0xac06, 0x0040, 0x2af4, 0x8211, 0x0040, 0x2b0b,
- 0x1078, 0x2b0f, 0x0078, 0x2ae9, 0x0c7e, 0x2100, 0x2011, 0x0001,
- 0xa212, 0x70b4, 0x2068, 0x6800, 0x2060, 0x6008, 0xa084, 0xfbef,
- 0x600a, 0x8211, 0x0040, 0x2b08, 0x1078, 0x2b0f, 0x0078, 0x2afb,
- 0x70a7, 0x0001, 0x0c7f, 0x027f, 0x0d7f, 0x017f, 0x007c, 0xade8,
- 0x0005, 0x70ac, 0xad06, 0x00c0, 0x2b17, 0x70a8, 0x2068, 0x007c,
- 0x1078, 0x4360, 0x00c0, 0x29c1, 0x707c, 0x2068, 0x7774, 0x1078,
- 0x41fe, 0x2c50, 0x1078, 0x4442, 0x789b, 0x0010, 0x6814, 0xa084,
- 0x001f, 0xc0bd, 0x78aa, 0x6e1c, 0x2041, 0x0001, 0x2001, 0x0004,
- 0x0078, 0x2c92, 0x1078, 0x4360, 0x00c0, 0x29c1, 0x789b, 0x0010,
- 0x7060, 0x2068, 0x6f14, 0x70d4, 0xd0b4, 0x0040, 0x2b4c, 0xc0b4,
- 0x70d6, 0x0c7e, 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a,
- 0x6018, 0x8001, 0x601a, 0x0c7f, 0x1078, 0x41fe, 0x2c50, 0x1078,
- 0x4442, 0x6824, 0xa005, 0x0040, 0x2b5d, 0xa082, 0x0006, 0x0048,
- 0x2b5b, 0x0078, 0x2b5d, 0x6827, 0x0005, 0x6814, 0xa084, 0x001f,
- 0xc0bd, 0x78aa, 0x2031, 0x0020, 0x2041, 0x0001, 0x2001, 0x0003,
- 0x0078, 0x2c92, 0xc28d, 0x72d6, 0x72c0, 0xa200, 0xa015, 0x7154,
- 0x8108, 0xa12a, 0x0048, 0x2b75, 0x71c0, 0x2164, 0x6504, 0x85ff,
- 0x00c0, 0x2b8c, 0x7156, 0x8421, 0x00c0, 0x2b70, 0x70d4, 0xd08c,
- 0x0040, 0x2b88, 0x70d0, 0xa005, 0x00c0, 0x2b88, 0x70d3, 0x000a,
- 0x007c, 0x2200, 0x0078, 0x2b7a, 0x70d4, 0xc08c, 0x70d6, 0x70d3,
- 0x0000, 0x6034, 0xa005, 0x00c0, 0x2b89, 0x6708, 0xa784, 0x073f,
- 0x0040, 0x2bbb, 0xd7d4, 0x00c0, 0x2b89, 0xa784, 0x0021, 0x00c0,
- 0x2b89, 0xa784, 0x0002, 0x0040, 0x2bac, 0xa784, 0x0004, 0x0040,
- 0x2b89, 0xa7bc, 0xfffb, 0x670a, 0xa784, 0x0218, 0x00c0, 0x2b89,
- 0xa784, 0x0100, 0x0040, 0x2bbb, 0x6018, 0xa005, 0x00c0, 0x2b89,
- 0xa7bc, 0xfeff, 0x670a, 0x2568, 0x6823, 0x0000, 0x6e1c, 0xa684,
- 0x000e, 0x6318, 0x0040, 0x2bcc, 0x601c, 0xa302, 0x0048, 0x2bcf,
- 0x0040, 0x2bcf, 0x0078, 0x2b89, 0x83ff, 0x00c0, 0x2b89, 0x2d58,
- 0x2c50, 0x7156, 0xd7bc, 0x00c0, 0x2bd8, 0x7028, 0x6022, 0x603a,
- 0xc7bc, 0x670a, 0x68c0, 0xa065, 0xa04d, 0x6100, 0x2a60, 0x2041,
- 0x0001, 0x6b14, 0xa39c, 0x001f, 0xa39d, 0x00c0, 0xd1fc, 0x0040,
- 0x2bec, 0xd684, 0x0040, 0x2bee, 0xa39c, 0xffbf, 0xd6a4, 0x0040,
- 0x2bf3, 0xa39d, 0x0020, 0xa684, 0x000e, 0x00c0, 0x2c3e, 0xc7a5,
- 0x670a, 0x2c00, 0x68c6, 0x77a4, 0xa786, 0x0001, 0x00c0, 0x2c12,
- 0x70d4, 0xd0b4, 0x00c0, 0x2c12, 0x7000, 0xa082, 0x0002, 0x00c8,
- 0x2c12, 0x7830, 0xd0bc, 0x00c0, 0x2c12, 0x789b, 0x0010, 0x7baa,
- 0x0078, 0x2c8a, 0x8739, 0x77a6, 0x2750, 0x77b0, 0xa7b0, 0x0005,
- 0x70ac, 0xa606, 0x00c0, 0x2c1d, 0x76a8, 0x76b2, 0x2c3a, 0x8738,
- 0x2d3a, 0x8738, 0x283a, 0x8738, 0x233a, 0x8738, 0x253a, 0x7830,
- 0xd0bc, 0x0040, 0x2c35, 0x2091, 0x8000, 0x2091, 0x303d, 0x70d4,
- 0xa084, 0x303d, 0x2091, 0x8000, 0x2090, 0xaad5, 0x0000, 0x0040,
- 0x2c3d, 0x8421, 0x2200, 0x00c0, 0x2b6f, 0x007c, 0xd1dc, 0x0040,
- 0x3e00, 0x2029, 0x0020, 0xd69c, 0x00c0, 0x2c4b, 0x8528, 0xd68c,
- 0x00c0, 0x2c4b, 0x8528, 0x8840, 0x6f14, 0x610c, 0x8108, 0xa18c,
- 0x00ff, 0x70cc, 0xa160, 0x2c64, 0x8cff, 0x0040, 0x2c6a, 0x6014,
- 0xa706, 0x00c0, 0x2c53, 0x60b8, 0x8001, 0x60ba, 0x00c0, 0x2c4e,
- 0x2a60, 0x6008, 0xa085, 0x0100, 0x600a, 0x2200, 0x8421, 0x00c0,
- 0x2b6f, 0x007c, 0x2a60, 0x610e, 0x69be, 0x2c00, 0x68c6, 0x8840,
- 0x6008, 0xc0d5, 0x600a, 0x77a4, 0xa786, 0x0001, 0x00c0, 0x2c12,
- 0x70d4, 0xd0b4, 0x00c0, 0x2c12, 0x7000, 0xa082, 0x0002, 0x00c8,
- 0x2c12, 0x7830, 0xd0bc, 0x00c0, 0x2c12, 0x789b, 0x0010, 0x7baa,
- 0x7daa, 0x79aa, 0x2001, 0x0002, 0x007e, 0x6018, 0x8000, 0x601a,
- 0x0078, 0x2c93, 0x007e, 0x2960, 0x6104, 0x2a60, 0xa184, 0x0018,
- 0x0040, 0x2caf, 0xa184, 0x0010, 0x0040, 0x2ca2, 0x1078, 0x4011,
- 0x00c0, 0x2cd4, 0xa184, 0x0008, 0x0040, 0x2caf, 0x69a0, 0xa184,
- 0x0600, 0x00c0, 0x2caf, 0x1078, 0x3ef5, 0x0078, 0x2cd4, 0x69a0,
- 0xa184, 0x1e00, 0x0040, 0x2cdf, 0xa184, 0x0800, 0x0040, 0x2cc8,
- 0x0c7e, 0x2960, 0x6000, 0xa085, 0x2000, 0x6002, 0x6104, 0xa18d,
- 0x0010, 0x6106, 0x0c7f, 0x1078, 0x4011, 0x00c0, 0x2cd4, 0x69a0,
- 0xa184, 0x0200, 0x0040, 0x2cd0, 0x1078, 0x3f54, 0x0078, 0x2cd4,
- 0xa184, 0x0400, 0x00c0, 0x2cab, 0x69a0, 0xa184, 0x1000, 0x0040,
- 0x2cdf, 0x6914, 0xa18c, 0xff00, 0x810f, 0x1078, 0x279f, 0x027f,
- 0xa68c, 0x00e0, 0xa684, 0x0060, 0x0040, 0x2cec, 0xa086, 0x0060,
- 0x00c0, 0x2cec, 0xa18d, 0x4000, 0xa18d, 0x0104, 0x69b6, 0x789b,
- 0x0060, 0x2800, 0x78aa, 0x6818, 0xc0fd, 0x681a, 0xd6bc, 0x0040,
- 0x2d07, 0xc0fc, 0x7087, 0x0000, 0xa08a, 0x000d, 0x0050, 0x2d05,
- 0xa08a, 0x000c, 0x7186, 0x2001, 0x000c, 0x800c, 0x718a, 0x78aa,
- 0x3518, 0x3340, 0x3428, 0x8000, 0x80ac, 0xaf80, 0x002b, 0x20a0,
- 0x789b, 0x0000, 0xad80, 0x000b, 0x2098, 0x53a6, 0x23a8, 0x2898,
- 0x25a0, 0xa286, 0x0020, 0x00c0, 0x2d3f, 0x70d4, 0xc0b5, 0x70d6,
- 0x2c00, 0x70ba, 0x2d00, 0x70be, 0x6814, 0xc0fc, 0x8007, 0x7882,
- 0xa286, 0x0002, 0x0040, 0x2d75, 0x70a4, 0x8000, 0x70a6, 0x74b4,
- 0xa498, 0x0005, 0x70ac, 0xa306, 0x00c0, 0x2d37, 0x73a8, 0x73b6,
- 0xa286, 0x0010, 0x0040, 0x29c1, 0x0d7f, 0x0c7f, 0x007c, 0x7000,
- 0xa005, 0x00c0, 0x2d1d, 0xa286, 0x0002, 0x00c0, 0x2d8f, 0x1078,
- 0x4360, 0x00c0, 0x2d1d, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x2091,
- 0x8000, 0x781b, 0x005b, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de,
- 0x6898, 0x78d2, 0x78da, 0x2091, 0x8001, 0x7808, 0xc08d, 0x780a,
- 0x127e, 0x0d7e, 0x0c7e, 0x70d4, 0xa084, 0x2700, 0x2090, 0x0c7f,
- 0x0d7f, 0x127f, 0x2900, 0x705a, 0x68bc, 0x7042, 0x7003, 0x0002,
- 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x7830, 0xd0bc, 0x0040,
- 0x2d81, 0x2091, 0x303d, 0x70d4, 0xa084, 0x303d, 0x2091, 0x8000,
- 0x2090, 0x70a4, 0xa005, 0x00c0, 0x2d86, 0x007c, 0x8421, 0x0040,
- 0x2d85, 0x7250, 0x70c0, 0xa200, 0xa015, 0x0078, 0x2b6f, 0xa286,
- 0x0010, 0x00c0, 0x2dc0, 0x1078, 0x4360, 0x00c0, 0x2d1d, 0x6814,
- 0xc0fc, 0x8007, 0x7882, 0x781b, 0x005b, 0x68b4, 0x785a, 0x6894,
+ 0xa006, 0x2009, 0x9775, 0x200a, 0x203a, 0x007c, 0x7810, 0xc0ad,
+ 0x7812, 0x0078, 0x24d2, 0x263a, 0x1078, 0x25bd, 0x00c0, 0x25e0,
+ 0x786c, 0xa065, 0x00c0, 0x2464, 0x2091, 0x8000, 0x7810, 0xa084,
+ 0xffcf, 0x86ff, 0x0040, 0x24cd, 0xc0ad, 0x7812, 0x2091, 0x8001,
+ 0x0078, 0x25e0, 0x2091, 0x8000, 0x7007, 0x0004, 0x7994, 0x70d4,
+ 0xa102, 0x0048, 0x24e3, 0x0040, 0x24ed, 0x7b90, 0xa302, 0x00c0,
+ 0x24ed, 0x0078, 0x24e6, 0x8002, 0x00c0, 0x24ed, 0x263a, 0x7810,
+ 0xc0ad, 0x7812, 0x2091, 0x8001, 0x007c, 0xa184, 0xff00, 0x0040,
+ 0x24fa, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100,
+ 0x0078, 0x24fd, 0x8107, 0x8004, 0x8004, 0x7a9c, 0xa210, 0x721a,
+ 0x7a98, 0xa006, 0xa211, 0x721e, 0xd4c4, 0x0040, 0x250d, 0x7aa4,
+ 0xa211, 0x7222, 0x7aa0, 0xa211, 0x7226, 0x20a1, 0x0030, 0x7003,
+ 0x0000, 0x2009, 0x9754, 0x260a, 0x8109, 0x2198, 0x2104, 0xd084,
+ 0x0040, 0x251b, 0x8633, 0xa6b0, 0x0002, 0x26a8, 0x53a6, 0x8603,
+ 0x7012, 0x7007, 0x0001, 0x7990, 0x7894, 0x8000, 0xa10a, 0x00c8,
+ 0x252a, 0xa006, 0x2028, 0x7974, 0xa184, 0xff00, 0x0040, 0x2539,
+ 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0078,
+ 0x253c, 0x8107, 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78, 0xa006,
+ 0xa211, 0xd4c4, 0x0040, 0x2548, 0x7b84, 0xa319, 0x7c80, 0xa421,
+ 0x7008, 0xd0fc, 0x0040, 0x2548, 0xa084, 0x01e0, 0x0040, 0x256d,
+ 0x7d10, 0x2031, 0x9754, 0x2634, 0x78a8, 0x8000, 0x78aa, 0xd08c,
+ 0x00c0, 0x2562, 0x7007, 0x0006, 0x7004, 0xd094, 0x00c0, 0x255c,
+ 0x0078, 0x24d4, 0x2069, 0x4f47, 0x206b, 0x0003, 0x78ac, 0xa085,
+ 0x0300, 0x78ae, 0xa006, 0x0078, 0x2576, 0x2030, 0x75d6, 0x2091,
+ 0x4080, 0x7d96, 0x7d10, 0xa5ac, 0xffcf, 0x7d12, 0x2091, 0x8001,
+ 0x78aa, 0x7007, 0x0006, 0x263a, 0x7003, 0x0001, 0x711a, 0x721e,
+ 0xd5c4, 0x0040, 0x2585, 0x7322, 0x7426, 0x007c, 0x6084, 0xa086,
+ 0x0103, 0x00c0, 0x25a9, 0x6114, 0x6018, 0xa105, 0x00c0, 0x25a9,
+ 0x2069, 0x0000, 0x6818, 0xd084, 0x00c0, 0x25a9, 0x600c, 0x70c6,
+ 0x6010, 0x70ca, 0x70c3, 0x8020, 0x681b, 0x0001, 0x2091, 0x4080,
+ 0x1078, 0x2086, 0x0068, 0x25a8, 0x786c, 0xa065, 0x00c0, 0x2586,
+ 0x007c, 0x1078, 0x25bd, 0x00c0, 0x25e0, 0x786c, 0xa065, 0x00c0,
+ 0x2586, 0x0078, 0x25e0, 0x1078, 0x25bd, 0x00c0, 0x25e0, 0x786c,
+ 0xa065, 0x00c0, 0x25b3, 0x0078, 0x25e0, 0x6084, 0xa086, 0x0103,
+ 0x00c0, 0x25d1, 0x6018, 0xc0fc, 0x601a, 0xa086, 0x0004, 0x00c0,
+ 0x25d1, 0x7804, 0xd0a4, 0x0040, 0x25d1, 0x1078, 0x2086, 0xa006,
+ 0x007c, 0x1078, 0x25e6, 0x00c0, 0x25d8, 0xa085, 0x0001, 0x007c,
+ 0x1078, 0x25f5, 0x00c0, 0x25de, 0x2041, 0x0001, 0x7d10, 0x007c,
+ 0x88ff, 0x0040, 0x25e5, 0x2091, 0x4080, 0x007c, 0x7b90, 0x7994,
+ 0x70d4, 0xa102, 0x00c0, 0x25ef, 0xa385, 0x0000, 0x007c, 0x0048,
+ 0x25f3, 0xa302, 0x007c, 0x8002, 0x007c, 0x7810, 0xd0ec, 0x0040,
+ 0x260d, 0x0e7e, 0x2091, 0x8000, 0x2071, 0x0020, 0x7004, 0xa005,
+ 0x00c0, 0x260a, 0x7008, 0x0e7f, 0xa086, 0x0008, 0x0040, 0x260d,
+ 0x0078, 0x265e, 0x0e7f, 0x0078, 0x265e, 0xa184, 0xff00, 0x0040,
+ 0x261a, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100,
+ 0x0078, 0x261d, 0x8107, 0x8004, 0x8004, 0x7a9c, 0x7b98, 0x7ca4,
+ 0x7da0, 0xa210, 0xa006, 0xa319, 0xa421, 0xa529, 0x2009, 0x0018,
+ 0x6028, 0xa005, 0x0040, 0x262e, 0x2009, 0x0040, 0x1078, 0x1dbb,
+ 0x0040, 0x2650, 0x78a8, 0x8000, 0x78aa, 0xd08c, 0x00c0, 0x265e,
+ 0x6014, 0xd0fc, 0x00c0, 0x2640, 0x2069, 0x4f40, 0x0078, 0x2642,
+ 0x2069, 0x4f80, 0x2091, 0x8000, 0x681f, 0x0003, 0x78ab, 0x0000,
+ 0x78ac, 0xa085, 0x0300, 0x78ae, 0x2091, 0x8001, 0x0078, 0x265e,
+ 0x78ab, 0x0000, 0x1078, 0x2086, 0x7990, 0x7894, 0x8000, 0xa10a,
+ 0x00c8, 0x265b, 0xa006, 0x7896, 0x70d6, 0xa006, 0x2071, 0x0010,
+ 0x2091, 0x8001, 0x007c, 0xd7fc, 0x00c0, 0x266a, 0x2009, 0x4f59,
+ 0x0078, 0x266c, 0x2009, 0x4f99, 0x2091, 0x8000, 0x200a, 0x0f7e,
+ 0xd7fc, 0x00c0, 0x2683, 0x2009, 0x4f40, 0x2001, 0x4f04, 0x2004,
+ 0xd0ec, 0x0040, 0x267f, 0x2079, 0x0100, 0x0078, 0x2687, 0x2079,
+ 0x0200, 0x0078, 0x2687, 0x2009, 0x4f80, 0x2079, 0x0100, 0x2104,
+ 0xa086, 0x0000, 0x00c0, 0x26a0, 0xd7fc, 0x00c0, 0x2693, 0x2009,
+ 0x4f45, 0x0078, 0x2695, 0x2009, 0x4f85, 0x2104, 0xa005, 0x00c0,
+ 0x26a0, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x26a0, 0x781b, 0x0045,
+ 0x0f7f, 0x007c, 0x2009, 0x0002, 0x2069, 0x4f00, 0x6810, 0xd0ec,
+ 0x00c0, 0x270f, 0x2071, 0x4f80, 0x2079, 0x0100, 0x2021, 0x51bf,
+ 0x784b, 0x000f, 0x2019, 0x44a7, 0xd184, 0x0040, 0x26c3, 0x6810,
+ 0xd0ec, 0x0040, 0x26bf, 0x20a1, 0x012b, 0x0078, 0x26c5, 0x20a1,
+ 0x022b, 0x0078, 0x26c5, 0x20a1, 0x012b, 0x2304, 0xa005, 0x0040,
+ 0x26d2, 0x789a, 0x8318, 0x23ac, 0x8318, 0x2398, 0x53a6, 0x3318,
+ 0x0078, 0x26c5, 0x789b, 0x0020, 0x20a9, 0x0010, 0x6814, 0xd0e4,
+ 0x0040, 0x26e2, 0x78af, 0x0000, 0x78af, 0x9020, 0x00f0, 0x26da,
+ 0x0078, 0x26e8, 0x78af, 0x0000, 0x78af, 0x8020, 0x00f0, 0x26e2,
+ 0x7003, 0x0000, 0x017e, 0xd18c, 0x2009, 0x0000, 0x0040, 0x26f1,
+ 0xc1bd, 0x1078, 0x28e2, 0x017f, 0x7020, 0xa084, 0x000f, 0x007e,
+ 0x6814, 0xd0e4, 0x007f, 0x00c0, 0x2701, 0xa085, 0x6340, 0x0078,
+ 0x2703, 0xa085, 0x62c0, 0x7806, 0x780f, 0x9200, 0x7843, 0x00d8,
+ 0x7853, 0x0080, 0x780b, 0x0008, 0x7456, 0x7053, 0x0000, 0x8109,
+ 0x0040, 0x2722, 0x2071, 0x4f40, 0x6810, 0xd0ec, 0x0040, 0x271c,
+ 0x2079, 0x0100, 0x0078, 0x271e, 0x2079, 0x0200, 0x2021, 0x4fbf,
+ 0x0078, 0x26b0, 0x007c, 0x017e, 0xd1bc, 0x00c0, 0x2737, 0x007e,
+ 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x2733, 0x2011,
+ 0x0101, 0x0078, 0x2739, 0x2011, 0x0201, 0x0078, 0x2739, 0x2011,
+ 0x0101, 0xa18c, 0x000f, 0x2204, 0xa084, 0xfff0, 0xa105, 0x2012,
+ 0x017f, 0x1078, 0x28e2, 0x007c, 0xd3fc, 0x00c0, 0x2757, 0x007e,
+ 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x2753, 0x2011,
+ 0x0101, 0x0078, 0x2759, 0x2011, 0x0201, 0x0078, 0x2759, 0x2011,
+ 0x0101, 0x20a9, 0x0009, 0x810b, 0x00f0, 0x275b, 0xa18c, 0x0e00,
+ 0x2204, 0xa084, 0xf1ff, 0xa105, 0x2012, 0x007c, 0x2019, 0x0002,
+ 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x0040, 0x2773, 0x8319, 0x2009,
+ 0x0101, 0x0078, 0x2775, 0x2009, 0x0101, 0x20a9, 0x0005, 0x8213,
+ 0x00f0, 0x2777, 0xa294, 0x00e0, 0x2104, 0xa084, 0xff1f, 0xa205,
+ 0x200a, 0x8319, 0x0040, 0x2788, 0x2009, 0x0201, 0x0078, 0x2775,
+ 0x007c, 0xd3fc, 0x00c0, 0x279c, 0x007e, 0x2001, 0x4f04, 0x2004,
+ 0xd0ec, 0x007f, 0x0040, 0x2798, 0x2011, 0x0101, 0x0078, 0x279e,
+ 0x2011, 0x0201, 0x0078, 0x279e, 0x2011, 0x0101, 0x20a9, 0x000c,
+ 0x810b, 0x00f0, 0x27a0, 0xa18c, 0xf000, 0x2204, 0xa084, 0x0fff,
+ 0xa105, 0x2012, 0x007c, 0xd3fc, 0x00c0, 0x27be, 0x007e, 0x2001,
+ 0x4f04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x27ba, 0x2011, 0x0102,
+ 0x0078, 0x27c0, 0x2011, 0x0202, 0x0078, 0x27c0, 0x2011, 0x0102,
+ 0x2204, 0xa084, 0xffcf, 0xa105, 0x2012, 0x007c, 0x0c7e, 0xd1bc,
+ 0x00c0, 0x27da, 0x007e, 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f,
+ 0x0040, 0x27d6, 0x2061, 0x0100, 0x0078, 0x27dc, 0x2061, 0x0200,
+ 0x0078, 0x27dc, 0x2061, 0x0100, 0xc1bc, 0x8103, 0x8003, 0xa080,
+ 0x0020, 0x609a, 0x62ac, 0x63ac, 0x0c7f, 0x007c, 0x0c7e, 0xd1bc,
+ 0x00c0, 0x27fa, 0x007e, 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f,
+ 0x0040, 0x27f6, 0x2061, 0x0100, 0x0078, 0x27fc, 0x2061, 0x0200,
+ 0x0078, 0x27fc, 0x2061, 0x0100, 0xc1bc, 0x8103, 0x8003, 0xa080,
+ 0x0022, 0x609a, 0x60a4, 0xa084, 0xffdf, 0x60ae, 0x0c7f, 0x007c,
+ 0x0c7e, 0xd1bc, 0x00c0, 0x281c, 0x007e, 0x2001, 0x4f04, 0x2004,
+ 0xd0ec, 0x007f, 0x0040, 0x2818, 0x2061, 0x0100, 0x0078, 0x281e,
+ 0x2061, 0x0200, 0x0078, 0x281e, 0x2061, 0x0100, 0xc1bc, 0x8103,
+ 0x8003, 0xa080, 0x0022, 0x609a, 0x60a4, 0xa085, 0x0020, 0x60ae,
+ 0x0c7f, 0x007c, 0x0c7e, 0xd1bc, 0x00c0, 0x283e, 0x007e, 0x2001,
+ 0x4f04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x283a, 0x2061, 0x0100,
+ 0x0078, 0x2840, 0x2061, 0x0200, 0x0078, 0x2840, 0x2061, 0x0100,
+ 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0020, 0x609a, 0x60a4, 0xa28c,
+ 0x0020, 0x0040, 0x284e, 0xc2ac, 0xa39d, 0x4000, 0xc3fc, 0xd3b4,
+ 0x00c0, 0x2853, 0xc3fd, 0x62ae, 0x2010, 0x60a4, 0x63ae, 0x2018,
+ 0x0c7f, 0x007c, 0x2091, 0x8000, 0x0c7e, 0x0e7e, 0x6818, 0xa005,
+ 0x0040, 0x28c0, 0xd1fc, 0x0040, 0x2869, 0x2061, 0x96d0, 0x0078,
+ 0x286b, 0x2061, 0x95c0, 0x1078, 0x28c8, 0x0040, 0x28a2, 0x20a9,
+ 0x0101, 0xd1fc, 0x0040, 0x2878, 0x2061, 0x95d0, 0x0078, 0x287a,
+ 0x2061, 0x94c0, 0x0c7e, 0x1078, 0x28c8, 0x0040, 0x2885, 0x0c7f,
+ 0x8c60, 0x00f0, 0x287a, 0x0078, 0x28c0, 0x007f, 0xd1fc, 0x0040,
+ 0x288f, 0xa082, 0x95d0, 0x2071, 0x4f80, 0x0078, 0x2893, 0xa082,
+ 0x94c0, 0x2071, 0x4f40, 0x707a, 0x7176, 0x2138, 0x2001, 0x0004,
+ 0x7066, 0x7083, 0x000f, 0x71d4, 0xc1dc, 0x71d6, 0x1078, 0x2663,
+ 0x0078, 0x28bc, 0xd1fc, 0x00c0, 0x28a9, 0x2071, 0x4f40, 0x0078,
+ 0x28ab, 0x2071, 0x4f80, 0x6020, 0xc0dd, 0x6022, 0x7176, 0x2138,
+ 0x2c00, 0x707e, 0x2001, 0x0006, 0x7066, 0x7083, 0x000f, 0x71d4,
+ 0xc1dc, 0x71d6, 0x1078, 0x2663, 0x2001, 0x0000, 0x0078, 0x28c2,
+ 0x2001, 0x0001, 0x2091, 0x8001, 0xa005, 0x0e7f, 0x0c7f, 0x007c,
+ 0x2c04, 0xa005, 0x0040, 0x28df, 0x2060, 0x6010, 0xa306, 0x00c0,
+ 0x28dc, 0x600c, 0xa206, 0x00c0, 0x28dc, 0x6014, 0xa106, 0x00c0,
+ 0x28dc, 0xa006, 0x0078, 0x28e1, 0x6000, 0x0078, 0x28c9, 0xa085,
+ 0x0001, 0x007c, 0x0f7e, 0x0e7e, 0x017e, 0xd1bc, 0x00c0, 0x28fa,
+ 0x2079, 0x4f40, 0x007e, 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f,
+ 0x0040, 0x28f6, 0x2071, 0x0100, 0x0078, 0x28fe, 0x2071, 0x0200,
+ 0x0078, 0x28fe, 0x2079, 0x4f80, 0x2071, 0x0100, 0x7920, 0xa18c,
+ 0x000f, 0x70ec, 0xd0c4, 0x00c0, 0x2908, 0x017f, 0x0078, 0x2923,
+ 0x810b, 0x810b, 0x810b, 0x810b, 0x007f, 0xd0bc, 0x00c0, 0x2920,
+ 0x007e, 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x291c,
+ 0xa18d, 0x0f00, 0x0078, 0x2922, 0xa18d, 0x0f00, 0x0078, 0x2922,
+ 0xa18d, 0x0800, 0x2104, 0x0e7f, 0x0f7f, 0x007c, 0x0e7e, 0x2001,
+ 0x4f01, 0x2004, 0xd0ac, 0x00c0, 0x29a3, 0x68e4, 0xd0ac, 0x0040,
+ 0x29a3, 0xa084, 0x0006, 0x00c0, 0x29a3, 0x6014, 0xd0fc, 0x00c0,
+ 0x293d, 0x2071, 0x53c0, 0x0078, 0x293f, 0x2071, 0x5440, 0x8007,
+ 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xae70, 0x7004, 0xa084,
+ 0x000a, 0x00c0, 0x29a3, 0x7108, 0xa194, 0xff00, 0x0040, 0x29a3,
+ 0xa18c, 0x00ff, 0x2001, 0x000a, 0xa106, 0x0040, 0x2972, 0x2001,
+ 0x000c, 0xa106, 0x0040, 0x2976, 0x2001, 0x0012, 0xa106, 0x0040,
+ 0x297a, 0x2001, 0x0014, 0xa106, 0x0040, 0x297e, 0x2001, 0x0019,
+ 0xa106, 0x0040, 0x2982, 0x2001, 0x0032, 0xa106, 0x0040, 0x2986,
+ 0x0078, 0x298a, 0x2009, 0x000c, 0x0078, 0x298c, 0x2009, 0x0012,
+ 0x0078, 0x298c, 0x2009, 0x0014, 0x0078, 0x298c, 0x2009, 0x0019,
+ 0x0078, 0x298c, 0x2009, 0x0020, 0x0078, 0x298c, 0x2009, 0x003f,
+ 0x0078, 0x298c, 0x2011, 0x0000, 0x2100, 0xa205, 0x700a, 0x2071,
+ 0x4f00, 0x7004, 0xd0bc, 0x0040, 0x29a3, 0x6014, 0xd0fc, 0x00c0,
+ 0x299e, 0x70ea, 0x2071, 0x4f40, 0x0078, 0x29a1, 0x70ee, 0x2071,
+ 0x4f80, 0x701f, 0x000d, 0x0e7f, 0x007c, 0x2001, 0x4f05, 0x2004,
+ 0xd0e4, 0x00c0, 0x29b1, 0x7804, 0xa084, 0xff1f, 0xa085, 0x6340,
+ 0x7806, 0x007c, 0x0068, 0x29b2, 0x2091, 0x8000, 0x2071, 0x0000,
+ 0x007e, 0x7018, 0xd084, 0x00c0, 0x29b9, 0x007f, 0x2071, 0x0010,
+ 0x70ca, 0x007f, 0x70c6, 0x70c3, 0x8002, 0x70db, 0x080f, 0x70df,
+ 0x000b, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078,
+ 0x29cf, 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x78a0, 0x708e, 0x7592,
+ 0x7496, 0x769a, 0x779e, 0xa594, 0x003f, 0xd4f4, 0x0040, 0x29e6,
+ 0xa784, 0x007d, 0x00c0, 0x441d, 0x1078, 0x29b2, 0xa49c, 0x000f,
+ 0xa382, 0x0004, 0x0050, 0x29f1, 0xa3a6, 0x0007, 0x00c0, 0x29b2,
+ 0x2418, 0x8507, 0xa084, 0x000f, 0x0079, 0x29f6, 0x3071, 0x3162,
+ 0x318d, 0x33ff, 0x37e8, 0x3862, 0x3917, 0x39a8, 0x3a96, 0x3b85,
+ 0x2a09, 0x2a06, 0x2e42, 0x2f65, 0x37b9, 0x2a06, 0x1078, 0x29b2,
+ 0x007c, 0xa006, 0x0078, 0x2a13, 0x7808, 0xc08d, 0x780a, 0xa006,
+ 0x7002, 0x704e, 0x7046, 0x70d2, 0x7060, 0xa005, 0x00c0, 0x2b79,
+ 0x7064, 0xa084, 0x0007, 0x0079, 0x2a1d, 0x2a25, 0x2a98, 0x2aa1,
+ 0x2aac, 0x2ab7, 0x2b5f, 0x2ac2, 0x2a98, 0x7830, 0xd0bc, 0x00c0,
+ 0x2a08, 0x71d4, 0xd1bc, 0x00c0, 0x2a08, 0xd1b4, 0x00c0, 0x2a75,
+ 0x70a4, 0xa086, 0x0001, 0x0040, 0x2a08, 0x70b4, 0xa06d, 0x6800,
+ 0xa065, 0xa055, 0x789b, 0x0010, 0x6b0c, 0x7baa, 0x6808, 0xa045,
+ 0x6d10, 0x6804, 0xa06d, 0xa05d, 0xa886, 0x0001, 0x0040, 0x2a4b,
+ 0x69bc, 0x7daa, 0x79aa, 0x68c0, 0xa04d, 0x6e1c, 0x2001, 0x0010,
+ 0x0078, 0x2cd3, 0x7060, 0xa005, 0x00c0, 0x2a08, 0x0c7e, 0x0d7e,
+ 0x70b4, 0xa06d, 0x6800, 0xa065, 0xa055, 0x789b, 0x0010, 0x6b0c,
+ 0x7baa, 0x6808, 0xa045, 0x6d10, 0x6804, 0xa06d, 0xa05d, 0xa886,
+ 0x0001, 0x0040, 0x2a6e, 0x69bc, 0x7daa, 0x79aa, 0x68c0, 0xa04d,
+ 0x6e1c, 0x2001, 0x0020, 0x0078, 0x2cd3, 0x1078, 0x43b0, 0x00c0,
+ 0x2a08, 0x781b, 0x005b, 0x70bc, 0xa06d, 0x68b4, 0x785a, 0x6894,
0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0x7808, 0xc08d, 0x780a,
- 0x70a4, 0x8000, 0x70a6, 0x74b4, 0xa490, 0x0005, 0x70ac, 0xa206,
- 0x00c0, 0x2db3, 0x72a8, 0x72b6, 0x2900, 0x705a, 0x68bc, 0x7042,
+ 0x68bc, 0x7042, 0xc1b4, 0x71d6, 0x70b8, 0xa065, 0x68c0, 0x705a,
0x7003, 0x0002, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x007c,
- 0x6bb4, 0xa39d, 0x2000, 0x7b5a, 0x6814, 0xc0fc, 0x8007, 0x7882,
- 0x6b94, 0x7bd6, 0x7bde, 0x6e98, 0x7ed2, 0x7eda, 0x781b, 0x005b,
- 0x2900, 0x705a, 0x7202, 0x7808, 0xc08d, 0x780a, 0x2300, 0xa605,
- 0x0040, 0x2deb, 0x70d4, 0xa084, 0x2700, 0xa086, 0x2300, 0x00c0,
- 0x2de5, 0x2009, 0x0000, 0x0078, 0x2de7, 0x2009, 0x0001, 0xa284,
- 0x000f, 0x1079, 0x2def, 0xad80, 0x0009, 0x7046, 0x007c, 0x2df7,
- 0x48bd, 0x48bd, 0x48aa, 0x48bd, 0x2df7, 0x2df7, 0x2df7, 0x1078,
- 0x296b, 0x7808, 0xa084, 0xfffd, 0x780a, 0x1078, 0x295e, 0x0f7e,
- 0x2079, 0x4e00, 0x78ac, 0x0f7f, 0xd084, 0x0040, 0x2e21, 0x7064,
- 0xa086, 0x0001, 0x00c0, 0x2e0f, 0x7066, 0x0078, 0x2ef8, 0x7064,
- 0xa086, 0x0005, 0x00c0, 0x2e1f, 0x707c, 0x2068, 0x681b, 0x0004,
- 0x6817, 0x0000, 0x6820, 0xa084, 0x00ff, 0xc09d, 0x6822, 0x7067,
- 0x0000, 0x70a7, 0x0000, 0x70a8, 0x70b2, 0x70b6, 0x1078, 0x2aba,
- 0x157e, 0x2011, 0x0004, 0x7164, 0xa186, 0x0001, 0x0040, 0x2e41,
- 0xa186, 0x0007, 0x00c0, 0x2e38, 0x701f, 0x0005, 0x0078, 0x2e41,
- 0x701f, 0x0001, 0x7067, 0x0000, 0x70d4, 0xc0dd, 0x70d6, 0x0078,
- 0x2e43, 0x7067, 0x0000, 0x2001, 0x4e0a, 0x2004, 0xa084, 0x00ff,
- 0xa086, 0x0018, 0x0040, 0x2e53, 0x7018, 0x7016, 0xa005, 0x00c0,
- 0x2e53, 0x70a7, 0x0001, 0x067e, 0x1078, 0x4586, 0x20a9, 0x0010,
- 0x2039, 0x0000, 0x1078, 0x40f8, 0xa7b8, 0x0100, 0x00f0, 0x2e5a,
- 0x067f, 0x7000, 0x0079, 0x2e64, 0x2e9e, 0x2e79, 0x2e79, 0x2e6e,
- 0x2e9e, 0x2e9e, 0x2e9e, 0x2e6c, 0x1078, 0x296b, 0x7060, 0xa005,
- 0x0040, 0x2e9e, 0xad06, 0x00c0, 0x2e79, 0x6800, 0x7062, 0x0078,
- 0x2e8b, 0x6820, 0xd084, 0x00c0, 0x2e87, 0x6f14, 0x1078, 0x41fe,
- 0x6008, 0xc0d4, 0x600a, 0x1078, 0x3dd0, 0x0078, 0x2e8b, 0x705c,
- 0x2060, 0x6800, 0x6002, 0xa684, 0x5f00, 0x681e, 0x6818, 0xd0fc,
- 0x0040, 0x2e93, 0x6a1a, 0x6817, 0x0000, 0x682b, 0x0000, 0x6820,
- 0xa084, 0x00ff, 0xc09d, 0x6822, 0x1078, 0x202c, 0xb284, 0x0400,
- 0x0040, 0x2ea6, 0x2021, 0x95d0, 0x0078, 0x2ea8, 0x2021, 0x94c0,
- 0x1078, 0x2efd, 0xb284, 0x0400, 0x0040, 0x2eb2, 0x2021, 0x4e98,
- 0x0078, 0x2eb4, 0x2021, 0x4e58, 0x1078, 0x2efd, 0x20a9, 0x0101,
- 0xb284, 0x0400, 0x0040, 0x2ec0, 0x2021, 0x94d0, 0x0078, 0x2ec2,
- 0x2021, 0x93c0, 0x1078, 0x2efd, 0x8420, 0x00f0, 0x2ec2, 0xb284,
- 0x0300, 0x0040, 0x2ecf, 0x2061, 0x53c0, 0x0078, 0x2ed1, 0x2061,
- 0x73c0, 0x2021, 0x0002, 0x20a9, 0x0100, 0x6110, 0x81ff, 0x0040,
- 0x2eee, 0x6018, 0x017e, 0x007e, 0x2011, 0x4e02, 0x220c, 0xa102,
- 0x2012, 0x007f, 0x017f, 0xa102, 0x0050, 0x2eee, 0x6012, 0x00c0,
- 0x2eee, 0x2011, 0x4e04, 0x2204, 0xc0a5, 0x2012, 0x601b, 0x0000,
- 0xace0, 0x0010, 0x00f0, 0x2ed5, 0x8421, 0x00c0, 0x2ed3, 0x157f,
- 0x7003, 0x0000, 0x704f, 0x0000, 0x007c, 0x047e, 0x2404, 0xa005,
- 0x0040, 0x2f18, 0x2068, 0x6800, 0x007e, 0x6a1a, 0x6817, 0x0000,
+ 0x1078, 0x43b0, 0x00c0, 0x2aa0, 0x781b, 0x0047, 0x7003, 0x0004,
+ 0x007c, 0x1078, 0x43b0, 0x00c0, 0x2aab, 0x2011, 0x000c, 0x1078,
+ 0x2ad2, 0x7003, 0x0004, 0x007c, 0x1078, 0x43b0, 0x00c0, 0x2ab6,
+ 0x2011, 0x0006, 0x1078, 0x2ad2, 0x7003, 0x0004, 0x007c, 0x1078,
+ 0x43b0, 0x00c0, 0x2ac1, 0x2011, 0x000d, 0x1078, 0x2ad2, 0x7003,
+ 0x0004, 0x007c, 0x1078, 0x43b0, 0x00c0, 0x2ad1, 0x2011, 0x0006,
+ 0x1078, 0x2ad2, 0x707c, 0x707f, 0x0000, 0x2068, 0x704e, 0x7003,
+ 0x0001, 0x007c, 0x7174, 0xc1fc, 0x8107, 0x7882, 0x789b, 0x0010,
+ 0xa286, 0x000c, 0x00c0, 0x2ae1, 0x7aaa, 0x2001, 0x0001, 0x0078,
+ 0x2af6, 0xa18c, 0x001f, 0xa18d, 0x00c0, 0x79aa, 0xa286, 0x000d,
+ 0x0040, 0x2aef, 0x7aaa, 0x2001, 0x0002, 0x0078, 0x2af6, 0x78ab,
+ 0x0020, 0x7178, 0x79aa, 0x7aaa, 0x2001, 0x0004, 0x789b, 0x0060,
+ 0x78aa, 0x785b, 0x0004, 0x781b, 0x0116, 0x1078, 0x43d3, 0x7083,
+ 0x000f, 0x70d4, 0xd0b4, 0x0040, 0x2b12, 0xc0b4, 0x70d6, 0x0c7e,
+ 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001,
+ 0x601a, 0x0c7f, 0x007c, 0x7014, 0xa005, 0x00c0, 0x2b21, 0x70d4,
+ 0xd0b4, 0x0040, 0x2b22, 0x70b8, 0xac06, 0x00c0, 0x2b22, 0x1078,
+ 0x2b01, 0x007c, 0x017e, 0x71a4, 0xa186, 0x0001, 0x0040, 0x2b54,
+ 0x0d7e, 0x027e, 0x2100, 0x2011, 0x0001, 0xa212, 0x70b4, 0x2068,
+ 0x6800, 0xac06, 0x0040, 0x2b3b, 0x8211, 0x0040, 0x2b52, 0x1078,
+ 0x2b56, 0x0078, 0x2b30, 0x0c7e, 0x2100, 0x2011, 0x0001, 0xa212,
+ 0x70b4, 0x2068, 0x6800, 0x2060, 0x6008, 0xa084, 0xfbef, 0x600a,
+ 0x8211, 0x0040, 0x2b4f, 0x1078, 0x2b56, 0x0078, 0x2b42, 0x70a7,
+ 0x0001, 0x0c7f, 0x027f, 0x0d7f, 0x017f, 0x007c, 0xade8, 0x0005,
+ 0x70ac, 0xad06, 0x00c0, 0x2b5e, 0x70a8, 0x2068, 0x007c, 0x1078,
+ 0x43b0, 0x00c0, 0x2a08, 0x707c, 0x2068, 0x7774, 0x1078, 0x424e,
+ 0x2c50, 0x1078, 0x4492, 0x789b, 0x0010, 0x6814, 0xa084, 0x001f,
+ 0xc0bd, 0x78aa, 0x6e1c, 0x2041, 0x0001, 0x2001, 0x0004, 0x0078,
+ 0x2cd9, 0x1078, 0x43b0, 0x00c0, 0x2a08, 0x789b, 0x0010, 0x7060,
+ 0x2068, 0x6f14, 0x70d4, 0xd0b4, 0x0040, 0x2b93, 0xc0b4, 0x70d6,
+ 0x0c7e, 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018,
+ 0x8001, 0x601a, 0x0c7f, 0x1078, 0x424e, 0x2c50, 0x1078, 0x4492,
+ 0x6824, 0xa005, 0x0040, 0x2ba4, 0xa082, 0x0006, 0x0048, 0x2ba2,
+ 0x0078, 0x2ba4, 0x6827, 0x0005, 0x6814, 0xa084, 0x001f, 0xc0bd,
+ 0x78aa, 0x2031, 0x0020, 0x2041, 0x0001, 0x2001, 0x0003, 0x0078,
+ 0x2cd9, 0xc28d, 0x72d6, 0x72c0, 0xa200, 0xa015, 0x7154, 0x8108,
+ 0xa12a, 0x0048, 0x2bbc, 0x71c0, 0x2164, 0x6504, 0x85ff, 0x00c0,
+ 0x2bd3, 0x7156, 0x8421, 0x00c0, 0x2bb7, 0x70d4, 0xd08c, 0x0040,
+ 0x2bcf, 0x70d0, 0xa005, 0x00c0, 0x2bcf, 0x70d3, 0x000a, 0x007c,
+ 0x2200, 0x0078, 0x2bc1, 0x70d4, 0xc08c, 0x70d6, 0x70d3, 0x0000,
+ 0x6034, 0xa005, 0x00c0, 0x2bd0, 0x6708, 0xa784, 0x073f, 0x0040,
+ 0x2c02, 0xd7d4, 0x00c0, 0x2bd0, 0xa784, 0x0021, 0x00c0, 0x2bd0,
+ 0xa784, 0x0002, 0x0040, 0x2bf3, 0xa784, 0x0004, 0x0040, 0x2bd0,
+ 0xa7bc, 0xfffb, 0x670a, 0xa784, 0x0218, 0x00c0, 0x2bd0, 0xa784,
+ 0x0100, 0x0040, 0x2c02, 0x6018, 0xa005, 0x00c0, 0x2bd0, 0xa7bc,
+ 0xfeff, 0x670a, 0x2568, 0x6823, 0x0000, 0x6e1c, 0xa684, 0x000e,
+ 0x6318, 0x0040, 0x2c13, 0x601c, 0xa302, 0x0048, 0x2c16, 0x0040,
+ 0x2c16, 0x0078, 0x2bd0, 0x83ff, 0x00c0, 0x2bd0, 0x2d58, 0x2c50,
+ 0x7156, 0xd7bc, 0x00c0, 0x2c1f, 0x7028, 0x6022, 0x603a, 0xc7bc,
+ 0x670a, 0x68c0, 0xa065, 0xa04d, 0x6100, 0x2a60, 0x2041, 0x0001,
+ 0x6b14, 0xa39c, 0x001f, 0xa39d, 0x00c0, 0xd1fc, 0x0040, 0x2c33,
+ 0xd684, 0x0040, 0x2c35, 0xa39c, 0xffbf, 0xd6a4, 0x0040, 0x2c3a,
+ 0xa39d, 0x0020, 0xa684, 0x000e, 0x00c0, 0x2c85, 0xc7a5, 0x670a,
+ 0x2c00, 0x68c6, 0x77a4, 0xa786, 0x0001, 0x00c0, 0x2c59, 0x70d4,
+ 0xd0b4, 0x00c0, 0x2c59, 0x7000, 0xa082, 0x0002, 0x00c8, 0x2c59,
+ 0x7830, 0xd0bc, 0x00c0, 0x2c59, 0x789b, 0x0010, 0x7baa, 0x0078,
+ 0x2cd1, 0x8739, 0x77a6, 0x2750, 0x77b0, 0xa7b0, 0x0005, 0x70ac,
+ 0xa606, 0x00c0, 0x2c64, 0x76a8, 0x76b2, 0x2c3a, 0x8738, 0x2d3a,
+ 0x8738, 0x283a, 0x8738, 0x233a, 0x8738, 0x253a, 0x7830, 0xd0bc,
+ 0x0040, 0x2c7c, 0x2091, 0x8000, 0x2091, 0x303d, 0x70d4, 0xa084,
+ 0x303d, 0x2091, 0x8000, 0x2090, 0xaad5, 0x0000, 0x0040, 0x2c84,
+ 0x8421, 0x2200, 0x00c0, 0x2bb6, 0x007c, 0xd1dc, 0x0040, 0x3e49,
+ 0x2029, 0x0020, 0xd69c, 0x00c0, 0x2c92, 0x8528, 0xd68c, 0x00c0,
+ 0x2c92, 0x8528, 0x8840, 0x6f14, 0x610c, 0x8108, 0xa18c, 0x00ff,
+ 0x70cc, 0xa160, 0x2c64, 0x8cff, 0x0040, 0x2cb1, 0x6014, 0xa706,
+ 0x00c0, 0x2c9a, 0x60b8, 0x8001, 0x60ba, 0x00c0, 0x2c95, 0x2a60,
+ 0x6008, 0xa085, 0x0100, 0x600a, 0x2200, 0x8421, 0x00c0, 0x2bb6,
+ 0x007c, 0x2a60, 0x610e, 0x69be, 0x2c00, 0x68c6, 0x8840, 0x6008,
+ 0xc0d5, 0x600a, 0x77a4, 0xa786, 0x0001, 0x00c0, 0x2c59, 0x70d4,
+ 0xd0b4, 0x00c0, 0x2c59, 0x7000, 0xa082, 0x0002, 0x00c8, 0x2c59,
+ 0x7830, 0xd0bc, 0x00c0, 0x2c59, 0x789b, 0x0010, 0x7baa, 0x7daa,
+ 0x79aa, 0x2001, 0x0002, 0x007e, 0x6018, 0x8000, 0x601a, 0x0078,
+ 0x2cda, 0x007e, 0x2960, 0x6104, 0x2a60, 0xa184, 0x0018, 0x0040,
+ 0x2cf6, 0xa184, 0x0010, 0x0040, 0x2ce9, 0x1078, 0x405e, 0x00c0,
+ 0x2d1b, 0xa184, 0x0008, 0x0040, 0x2cf6, 0x69a0, 0xa184, 0x0600,
+ 0x00c0, 0x2cf6, 0x1078, 0x3f3e, 0x0078, 0x2d1b, 0x69a0, 0xa184,
+ 0x1e00, 0x0040, 0x2d26, 0xa184, 0x0800, 0x0040, 0x2d0f, 0x0c7e,
+ 0x2960, 0x6000, 0xa085, 0x2000, 0x6002, 0x6104, 0xa18d, 0x0010,
+ 0x6106, 0x0c7f, 0x1078, 0x405e, 0x00c0, 0x2d1b, 0x69a0, 0xa184,
+ 0x0200, 0x0040, 0x2d17, 0x1078, 0x3fa1, 0x0078, 0x2d1b, 0xa184,
+ 0x0400, 0x00c0, 0x2cf2, 0x69a0, 0xa184, 0x1000, 0x0040, 0x2d26,
+ 0x6914, 0xa18c, 0xff00, 0x810f, 0x1078, 0x27e6, 0x027f, 0xa68c,
+ 0x00e0, 0xa684, 0x0060, 0x0040, 0x2d33, 0xa086, 0x0060, 0x00c0,
+ 0x2d33, 0xa18d, 0x4000, 0xa18d, 0x0104, 0x69b6, 0x789b, 0x0060,
+ 0x2800, 0x78aa, 0x6818, 0xc0fd, 0x681a, 0xd6bc, 0x0040, 0x2d4e,
+ 0xc0fc, 0x7087, 0x0000, 0xa08a, 0x000d, 0x0050, 0x2d4c, 0xa08a,
+ 0x000c, 0x7186, 0x2001, 0x000c, 0x800c, 0x718a, 0x78aa, 0x3518,
+ 0x3340, 0x3428, 0x8000, 0x80ac, 0xaf80, 0x002b, 0x20a0, 0x789b,
+ 0x0000, 0xad80, 0x000b, 0x2098, 0x53a6, 0x23a8, 0x2898, 0x25a0,
+ 0xa286, 0x0020, 0x00c0, 0x2d86, 0x70d4, 0xc0b5, 0x70d6, 0x2c00,
+ 0x70ba, 0x2d00, 0x70be, 0x6814, 0xc0fc, 0x8007, 0x7882, 0xa286,
+ 0x0002, 0x0040, 0x2dbc, 0x70a4, 0x8000, 0x70a6, 0x74b4, 0xa498,
+ 0x0005, 0x70ac, 0xa306, 0x00c0, 0x2d7e, 0x73a8, 0x73b6, 0xa286,
+ 0x0010, 0x0040, 0x2a08, 0x0d7f, 0x0c7f, 0x007c, 0x7000, 0xa005,
+ 0x00c0, 0x2d64, 0xa286, 0x0002, 0x00c0, 0x2dd6, 0x1078, 0x43b0,
+ 0x00c0, 0x2d64, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x2091, 0x8000,
+ 0x781b, 0x005b, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898,
+ 0x78d2, 0x78da, 0x2091, 0x8001, 0x7808, 0xc08d, 0x780a, 0x127e,
+ 0x0d7e, 0x0c7e, 0x70d4, 0xa084, 0x2700, 0x2090, 0x0c7f, 0x0d7f,
+ 0x127f, 0x2900, 0x705a, 0x68bc, 0x7042, 0x7003, 0x0002, 0x2d00,
+ 0x704e, 0xad80, 0x0009, 0x7046, 0x7830, 0xd0bc, 0x0040, 0x2dc8,
+ 0x2091, 0x303d, 0x70d4, 0xa084, 0x303d, 0x2091, 0x8000, 0x2090,
+ 0x70a4, 0xa005, 0x00c0, 0x2dcd, 0x007c, 0x8421, 0x0040, 0x2dcc,
+ 0x7250, 0x70c0, 0xa200, 0xa015, 0x0078, 0x2bb6, 0xa286, 0x0010,
+ 0x00c0, 0x2e07, 0x1078, 0x43b0, 0x00c0, 0x2d64, 0x6814, 0xc0fc,
+ 0x8007, 0x7882, 0x781b, 0x005b, 0x68b4, 0x785a, 0x6894, 0x78d6,
+ 0x78de, 0x6898, 0x78d2, 0x78da, 0x7808, 0xc08d, 0x780a, 0x70a4,
+ 0x8000, 0x70a6, 0x74b4, 0xa490, 0x0005, 0x70ac, 0xa206, 0x00c0,
+ 0x2dfa, 0x72a8, 0x72b6, 0x2900, 0x705a, 0x68bc, 0x7042, 0x7003,
+ 0x0002, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x007c, 0x6bb4,
+ 0xa39d, 0x2000, 0x7b5a, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x6b94,
+ 0x7bd6, 0x7bde, 0x6e98, 0x7ed2, 0x7eda, 0x781b, 0x005b, 0x2900,
+ 0x705a, 0x7202, 0x7808, 0xc08d, 0x780a, 0x2300, 0xa605, 0x0040,
+ 0x2e32, 0x70d4, 0xa084, 0x2700, 0xa086, 0x2300, 0x00c0, 0x2e2c,
+ 0x2009, 0x0000, 0x0078, 0x2e2e, 0x2009, 0x0001, 0xa284, 0x000f,
+ 0x1079, 0x2e38, 0xad80, 0x0009, 0x7046, 0x2d00, 0x704e, 0x007c,
+ 0x2e40, 0x493f, 0x493f, 0x492c, 0x493f, 0x2e40, 0x2e40, 0x2e40,
+ 0x1078, 0x29b2, 0x7808, 0xa084, 0xfffd, 0x780a, 0x1078, 0x29a5,
+ 0x0f7e, 0x2079, 0x4f00, 0x78ac, 0x0f7f, 0xd084, 0x0040, 0x2e6a,
+ 0x7064, 0xa086, 0x0001, 0x00c0, 0x2e58, 0x7066, 0x0078, 0x2f41,
+ 0x7064, 0xa086, 0x0005, 0x00c0, 0x2e68, 0x707c, 0x2068, 0x681b,
+ 0x0004, 0x6817, 0x0000, 0x6820, 0xa084, 0x00ff, 0xc09d, 0x6822,
+ 0x7067, 0x0000, 0x70a7, 0x0000, 0x70a8, 0x70b2, 0x70b6, 0x1078,
+ 0x2b01, 0x157e, 0x2011, 0x0004, 0x7164, 0xa186, 0x0001, 0x0040,
+ 0x2e8a, 0xa186, 0x0007, 0x00c0, 0x2e81, 0x701f, 0x0005, 0x0078,
+ 0x2e8a, 0x701f, 0x0001, 0x7067, 0x0000, 0x70d4, 0xc0dd, 0x70d6,
+ 0x0078, 0x2e8c, 0x7067, 0x0000, 0x2001, 0x4f0a, 0x2004, 0xa084,
+ 0x00ff, 0xa086, 0x0018, 0x0040, 0x2e9c, 0x7018, 0x7016, 0xa005,
+ 0x00c0, 0x2e9c, 0x70a7, 0x0001, 0x067e, 0x1078, 0x45d6, 0x20a9,
+ 0x0010, 0x2039, 0x0000, 0x1078, 0x4148, 0xa7b8, 0x0100, 0x00f0,
+ 0x2ea3, 0x067f, 0x7000, 0x0079, 0x2ead, 0x2ee7, 0x2ec2, 0x2ec2,
+ 0x2eb7, 0x2ee7, 0x2ee7, 0x2ee7, 0x2eb5, 0x1078, 0x29b2, 0x7060,
+ 0xa005, 0x0040, 0x2ee7, 0xad06, 0x00c0, 0x2ec2, 0x6800, 0x7062,
+ 0x0078, 0x2ed4, 0x6820, 0xd084, 0x00c0, 0x2ed0, 0x6f14, 0x1078,
+ 0x424e, 0x6008, 0xc0d4, 0x600a, 0x1078, 0x3e19, 0x0078, 0x2ed4,
+ 0x705c, 0x2060, 0x6800, 0x6002, 0xa684, 0x5f00, 0x681e, 0x6818,
+ 0xd0fc, 0x0040, 0x2edc, 0x6a1a, 0x6817, 0x0000, 0x682b, 0x0000,
+ 0x6820, 0xa084, 0x00ff, 0xc09d, 0x6822, 0x1078, 0x2073, 0xb284,
+ 0x0400, 0x0040, 0x2eef, 0x2021, 0x96d0, 0x0078, 0x2ef1, 0x2021,
+ 0x95c0, 0x1078, 0x2f46, 0xb284, 0x0400, 0x0040, 0x2efb, 0x2021,
+ 0x4f98, 0x0078, 0x2efd, 0x2021, 0x4f58, 0x1078, 0x2f46, 0x20a9,
+ 0x0101, 0xb284, 0x0400, 0x0040, 0x2f09, 0x2021, 0x95d0, 0x0078,
+ 0x2f0b, 0x2021, 0x94c0, 0x1078, 0x2f46, 0x8420, 0x00f0, 0x2f0b,
+ 0xb284, 0x0300, 0x0040, 0x2f18, 0x2061, 0x54c0, 0x0078, 0x2f1a,
+ 0x2061, 0x74c0, 0x2021, 0x0002, 0x20a9, 0x0100, 0x6110, 0x81ff,
+ 0x0040, 0x2f37, 0x6018, 0x017e, 0x007e, 0x2011, 0x4f02, 0x220c,
+ 0xa102, 0x2012, 0x007f, 0x017f, 0xa102, 0x0050, 0x2f37, 0x6012,
+ 0x00c0, 0x2f37, 0x2011, 0x4f04, 0x2204, 0xc0a5, 0x2012, 0x601b,
+ 0x0000, 0xace0, 0x0010, 0x00f0, 0x2f1e, 0x8421, 0x00c0, 0x2f1c,
+ 0x157f, 0x7003, 0x0000, 0x704f, 0x0000, 0x007c, 0x047e, 0x2404,
+ 0xa005, 0x0040, 0x2f61, 0x2068, 0x6800, 0x007e, 0x6a1a, 0x6817,
+ 0x0000, 0x682b, 0x0000, 0x68b4, 0xa084, 0x5f00, 0x681e, 0x6820,
+ 0xa084, 0x00ff, 0xc09d, 0x6822, 0x1078, 0x2073, 0x007f, 0x0078,
+ 0x2f48, 0x047f, 0x2023, 0x0000, 0x007c, 0xa282, 0x0003, 0x0050,
+ 0x2f6b, 0x1078, 0x29b2, 0x2300, 0x0079, 0x2f6e, 0x2f71, 0x2ffc,
+ 0x3019, 0xa282, 0x0002, 0x0040, 0x2f77, 0x1078, 0x29b2, 0x7064,
+ 0x7067, 0x0000, 0x7083, 0x0000, 0x0079, 0x2f7e, 0x2f86, 0x2f86,
+ 0x2f88, 0x2fc8, 0x3e55, 0x2f86, 0x2fc8, 0x2f86, 0x1078, 0x29b2,
+ 0x7774, 0x1078, 0x4148, 0x7774, 0xa7bc, 0x8f00, 0x1078, 0x424e,
+ 0x6018, 0xa005, 0x0040, 0x2fbf, 0xd7fc, 0x00c0, 0x2f9b, 0x2021,
+ 0x95c0, 0x0078, 0x2f9d, 0x2021, 0x96d0, 0x2009, 0x0005, 0x2011,
+ 0x0010, 0x1078, 0x3034, 0x0040, 0x2fbf, 0x157e, 0x20a9, 0x0101,
+ 0xd7fc, 0x00c0, 0x2faf, 0x2021, 0x94c0, 0x0078, 0x2fb1, 0x2021,
+ 0x95d0, 0x047e, 0x2009, 0x0005, 0x2011, 0x0010, 0x1078, 0x3034,
+ 0x047f, 0x0040, 0x2fbe, 0x8420, 0x00f0, 0x2fb1, 0x157f, 0x8738,
+ 0xa784, 0x001f, 0x00c0, 0x2f8e, 0x0078, 0x2a0c, 0x0078, 0x2a0c,
+ 0x7774, 0x1078, 0x424e, 0x6018, 0xa005, 0x0040, 0x2ffa, 0xd7fc,
+ 0x00c0, 0x2fd6, 0x2021, 0x95c0, 0x0078, 0x2fd8, 0x2021, 0x96d0,
+ 0x2009, 0x0005, 0x2011, 0x0020, 0x1078, 0x3034, 0x0040, 0x2ffa,
+ 0x157e, 0x20a9, 0x0101, 0xd7fc, 0x00c0, 0x2fea, 0x2021, 0x94c0,
+ 0x0078, 0x2fec, 0x2021, 0x95d0, 0x047e, 0x2009, 0x0005, 0x2011,
+ 0x0020, 0x1078, 0x3034, 0x047f, 0x0040, 0x2ff9, 0x8420, 0x00f0,
+ 0x2fec, 0x157f, 0x0078, 0x2a0c, 0x2200, 0x0079, 0x2fff, 0x3002,
+ 0x3004, 0x3004, 0x1078, 0x29b2, 0x2009, 0x0012, 0x7064, 0xa086,
+ 0x0002, 0x0040, 0x300d, 0x2009, 0x000e, 0x6818, 0xd0fc, 0x0040,
+ 0x3012, 0x691a, 0x7067, 0x0000, 0x70d4, 0xc0dd, 0x70d6, 0x0078,
+ 0x435d, 0x2200, 0x0079, 0x301c, 0x3021, 0x3004, 0x301f, 0x1078,
+ 0x29b2, 0x1078, 0x45d6, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3dc7,
+ 0x1078, 0x3e36, 0x6008, 0xa084, 0xfbef, 0x600a, 0x1078, 0x3db8,
+ 0x0040, 0x3dc7, 0x0078, 0x2a0c, 0x2404, 0xa005, 0x0040, 0x306d,
+ 0x2068, 0x2d04, 0x007e, 0x6814, 0xa706, 0x0040, 0x3043, 0x2d20,
+ 0x007f, 0x0078, 0x3035, 0x007f, 0x2022, 0x691a, 0x6817, 0x0000,
0x682b, 0x0000, 0x68b4, 0xa084, 0x5f00, 0x681e, 0x6820, 0xa084,
- 0x00ff, 0xc09d, 0x6822, 0x1078, 0x202c, 0x007f, 0x0078, 0x2eff,
- 0x047f, 0x2023, 0x0000, 0x007c, 0xa282, 0x0003, 0x0050, 0x2f22,
- 0x1078, 0x296b, 0x2300, 0x0079, 0x2f25, 0x2f28, 0x2fb3, 0x2fd0,
- 0xa282, 0x0002, 0x0040, 0x2f2e, 0x1078, 0x296b, 0x7064, 0x7067,
- 0x0000, 0x7083, 0x0000, 0x0079, 0x2f35, 0x2f3d, 0x2f3d, 0x2f3f,
- 0x2f7f, 0x3e0c, 0x2f3d, 0x2f7f, 0x2f3d, 0x1078, 0x296b, 0x7774,
- 0x1078, 0x40f8, 0x7774, 0xa7bc, 0x8f00, 0x1078, 0x41fe, 0x6018,
- 0xa005, 0x0040, 0x2f76, 0xd7fc, 0x00c0, 0x2f52, 0x2021, 0x94c0,
- 0x0078, 0x2f54, 0x2021, 0x95d0, 0x2009, 0x0005, 0x2011, 0x0010,
- 0x1078, 0x2feb, 0x0040, 0x2f76, 0x157e, 0x20a9, 0x0101, 0xd7fc,
- 0x00c0, 0x2f66, 0x2021, 0x93c0, 0x0078, 0x2f68, 0x2021, 0x94d0,
- 0x047e, 0x2009, 0x0005, 0x2011, 0x0010, 0x1078, 0x2feb, 0x047f,
- 0x0040, 0x2f75, 0x8420, 0x00f0, 0x2f68, 0x157f, 0x8738, 0xa784,
- 0x001f, 0x00c0, 0x2f45, 0x0078, 0x29c5, 0x0078, 0x29c5, 0x7774,
- 0x1078, 0x41fe, 0x6018, 0xa005, 0x0040, 0x2fb1, 0xd7fc, 0x00c0,
- 0x2f8d, 0x2021, 0x94c0, 0x0078, 0x2f8f, 0x2021, 0x95d0, 0x2009,
- 0x0005, 0x2011, 0x0020, 0x1078, 0x2feb, 0x0040, 0x2fb1, 0x157e,
- 0x20a9, 0x0101, 0xd7fc, 0x00c0, 0x2fa1, 0x2021, 0x93c0, 0x0078,
- 0x2fa3, 0x2021, 0x94d0, 0x047e, 0x2009, 0x0005, 0x2011, 0x0020,
- 0x1078, 0x2feb, 0x047f, 0x0040, 0x2fb0, 0x8420, 0x00f0, 0x2fa3,
- 0x157f, 0x0078, 0x29c5, 0x2200, 0x0079, 0x2fb6, 0x2fb9, 0x2fbb,
- 0x2fbb, 0x1078, 0x296b, 0x2009, 0x0012, 0x7064, 0xa086, 0x0002,
- 0x0040, 0x2fc4, 0x2009, 0x000e, 0x6818, 0xd0fc, 0x0040, 0x2fc9,
- 0x691a, 0x7067, 0x0000, 0x70d4, 0xc0dd, 0x70d6, 0x0078, 0x430d,
- 0x2200, 0x0079, 0x2fd3, 0x2fd8, 0x2fbb, 0x2fd6, 0x1078, 0x296b,
- 0x1078, 0x4586, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3d7e, 0x1078,
- 0x3ded, 0x6008, 0xa084, 0xfbef, 0x600a, 0x1078, 0x3d6f, 0x0040,
- 0x3d7e, 0x0078, 0x29c5, 0x2404, 0xa005, 0x0040, 0x3024, 0x2068,
- 0x2d04, 0x007e, 0x6814, 0xa706, 0x0040, 0x2ffa, 0x2d20, 0x007f,
- 0x0078, 0x2fec, 0x007f, 0x2022, 0x691a, 0x6817, 0x0000, 0x682b,
- 0x0000, 0x68b4, 0xa084, 0x5f00, 0x681e, 0x6820, 0xa084, 0x00ff,
- 0xa205, 0x6822, 0x1078, 0x202c, 0x2021, 0x4e02, 0x241c, 0x8319,
- 0x2322, 0x6010, 0x8001, 0x6012, 0x00c0, 0x301b, 0x2021, 0x4e04,
- 0x2404, 0xc0a5, 0x2022, 0x6008, 0xa084, 0xf9ef, 0x600a, 0x1078,
- 0x2adb, 0x1078, 0x3ded, 0x007c, 0xa085, 0x0001, 0x0078, 0x3023,
- 0x2300, 0x0079, 0x302b, 0x3030, 0x302e, 0x30b0, 0x1078, 0x296b,
- 0x78e4, 0xa005, 0x00d0, 0x3066, 0x3208, 0x007e, 0x2001, 0x4e04,
- 0x2004, 0xd0ec, 0x007f, 0x0040, 0x3041, 0xa18c, 0x0300, 0x0078,
- 0x3043, 0xa18c, 0x0400, 0x0040, 0x3049, 0x0018, 0x29c1, 0x0078,
- 0x304b, 0x0028, 0x29c1, 0x2008, 0xa084, 0x0030, 0x00c0, 0x3052,
- 0x0078, 0x3770, 0x78ec, 0xa084, 0x0003, 0x0040, 0x3050, 0x2100,
- 0xa084, 0x0007, 0x0079, 0x305c, 0x3090, 0x309a, 0x3085, 0x3064,
- 0x4355, 0x4355, 0x3064, 0x30a5, 0x1078, 0x296b, 0x7000, 0xa086,
- 0x0004, 0x00c0, 0x3080, 0x7064, 0xa086, 0x0002, 0x00c0, 0x3076,
- 0x2011, 0x0002, 0x2019, 0x0000, 0x0078, 0x2f1c, 0x7064, 0xa086,
- 0x0006, 0x0040, 0x3070, 0x7064, 0xa086, 0x0004, 0x0040, 0x3070,
- 0x79e4, 0x2001, 0x0003, 0x0078, 0x33fa, 0x6818, 0xd0fc, 0x0040,
- 0x308b, 0x681b, 0x001d, 0x1078, 0x40c8, 0x781b, 0x0064, 0x007c,
- 0x6818, 0xd0fc, 0x0040, 0x3096, 0x681b, 0x001d, 0x1078, 0x40c8,
- 0x0078, 0x4331, 0x6818, 0xd0fc, 0x0040, 0x30a0, 0x681b, 0x001d,
- 0x1078, 0x40c8, 0x781b, 0x00f8, 0x007c, 0x6818, 0xd0fc, 0x0040,
- 0x30ab, 0x681b, 0x001d, 0x1078, 0x40c8, 0x781b, 0x00c8, 0x007c,
- 0xa584, 0x000f, 0x00c0, 0x30cf, 0x1078, 0x295e, 0x7000, 0x0079,
- 0x30b9, 0x29c5, 0x30c1, 0x30c3, 0x3d7e, 0x3d7e, 0x3d7e, 0x30c1,
- 0x30c1, 0x1078, 0x296b, 0x1078, 0x3ded, 0x6008, 0xa084, 0xfbef,
- 0x600a, 0x1078, 0x3d6f, 0x0040, 0x3d7e, 0x0078, 0x29c5, 0x78e4,
- 0xa005, 0x00d0, 0x3066, 0x3208, 0x007e, 0x2001, 0x4e04, 0x2004,
- 0xd0ec, 0x007f, 0x0040, 0x30e0, 0xa18c, 0x0300, 0x0078, 0x30e2,
- 0xa18c, 0x0400, 0x0040, 0x30e8, 0x0018, 0x3066, 0x0078, 0x30ea,
- 0x0028, 0x3066, 0x2008, 0xa084, 0x0030, 0x00c0, 0x30f2, 0x781b,
- 0x005b, 0x007c, 0x78ec, 0xa084, 0x0003, 0x0040, 0x30ef, 0x2100,
- 0xa184, 0x0007, 0x0079, 0x30fc, 0x310b, 0x310f, 0x3106, 0x3104,
- 0x4355, 0x4355, 0x3104, 0x434f, 0x1078, 0x296b, 0x1078, 0x40d0,
- 0x781b, 0x0064, 0x007c, 0x1078, 0x40d0, 0x0078, 0x4331, 0x1078,
- 0x40d0, 0x781b, 0x00f8, 0x007c, 0x1078, 0x40d0, 0x781b, 0x00c8,
- 0x007c, 0x2300, 0x0079, 0x311c, 0x3121, 0x311f, 0x3123, 0x1078,
- 0x296b, 0x0078, 0x395f, 0x681b, 0x0016, 0x78a3, 0x0000, 0x79e4,
- 0xa184, 0x0030, 0x0040, 0x395f, 0x78ec, 0xa084, 0x0003, 0x0040,
- 0x395f, 0xa184, 0x0100, 0x0040, 0x3127, 0xa184, 0x0007, 0x0079,
- 0x3139, 0x3141, 0x310f, 0x3085, 0x430d, 0x4355, 0x4355, 0x430d,
- 0x434f, 0x1078, 0x4319, 0x007c, 0xa282, 0x0005, 0x0050, 0x314a,
- 0x1078, 0x296b, 0x2300, 0x0079, 0x314d, 0x3150, 0x3380, 0x338b,
- 0x2200, 0x0079, 0x3153, 0x316d, 0x315a, 0x316d, 0x3158, 0x3363,
- 0x1078, 0x296b, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff, 0xa082,
- 0x0020, 0x0048, 0x40b7, 0xa08a, 0x0004, 0x00c8, 0x40b7, 0x0079,
- 0x3169, 0x40b7, 0x40b7, 0x40b7, 0x4061, 0x789b, 0x0018, 0x79a8,
- 0xa184, 0x0080, 0x0040, 0x317e, 0x0078, 0x40b7, 0x7000, 0xa005,
- 0x00c0, 0x3174, 0x2011, 0x0004, 0x0078, 0x3b4a, 0xa184, 0x00ff,
- 0xa08a, 0x0010, 0x00c8, 0x40b7, 0x0079, 0x3186, 0x3198, 0x3196,
- 0x31ad, 0x31b1, 0x3284, 0x40b7, 0x40b7, 0x3286, 0x40b7, 0x40b7,
- 0x335f, 0x335f, 0x40b7, 0x40b7, 0x40b7, 0x3361, 0x1078, 0x296b,
- 0xd6e4, 0x0040, 0x31a3, 0x2001, 0x0300, 0x8000, 0x8000, 0x783a,
- 0x781b, 0x00c3, 0x007c, 0x6818, 0xd0fc, 0x0040, 0x31ab, 0x681b,
- 0x001d, 0x0078, 0x319b, 0x0078, 0x430d, 0x681b, 0x001d, 0x0078,
- 0x40c1, 0x6920, 0x6922, 0xa684, 0x1800, 0x00c0, 0x3216, 0x6820,
- 0xd084, 0x00c0, 0x321c, 0x6818, 0xa086, 0x0008, 0x00c0, 0x31c2,
- 0x681b, 0x0000, 0xd6d4, 0x0040, 0x3281, 0xd6bc, 0x0040, 0x3202,
- 0x7087, 0x0000, 0x6818, 0xa084, 0x003f, 0xa08a, 0x000d, 0x0050,
- 0x3202, 0xa08a, 0x000c, 0x7186, 0x2001, 0x000c, 0x800c, 0x718a,
- 0x789b, 0x0061, 0x78aa, 0x157e, 0x137e, 0x147e, 0x017e, 0x3208,
- 0xa18c, 0x0300, 0x0040, 0x31f4, 0x007e, 0x2001, 0x4e04, 0x2004,
- 0xd0ec, 0x007f, 0x0040, 0x31f0, 0x20a1, 0x012b, 0x0078, 0x31f6,
- 0x20a1, 0x022b, 0x0078, 0x31f6, 0x20a1, 0x012b, 0x017f, 0x789b,
- 0x0000, 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f,
- 0x137f, 0x157f, 0x6038, 0xa005, 0x00c0, 0x3211, 0x681c, 0xa084,
- 0x000e, 0x0040, 0x40c1, 0x1078, 0x40d7, 0x782b, 0x3008, 0x0078,
- 0x3213, 0x8001, 0x603a, 0x781b, 0x0067, 0x007c, 0xd6e4, 0x0040,
- 0x321c, 0x781b, 0x0079, 0x007c, 0xa684, 0x0060, 0x0040, 0x327e,
- 0xd6dc, 0x0040, 0x327e, 0xd6fc, 0x00c0, 0x3228, 0x0078, 0x323f,
- 0xc6fc, 0x7e5a, 0x6eb6, 0x7adc, 0x79d8, 0x78d0, 0x801b, 0x00c8,
- 0x3232, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x6b98,
- 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0xd6f4,
- 0x0040, 0x3245, 0xc6f4, 0x7e5a, 0x6eb6, 0x7000, 0xa086, 0x0003,
- 0x00c0, 0x3253, 0x007e, 0x1078, 0x4586, 0x1078, 0x48bd, 0x007f,
- 0x781b, 0x0076, 0x007c, 0xa006, 0x1078, 0x49c3, 0x6ab0, 0x69ac,
- 0x6c98, 0x6b94, 0x2200, 0xa105, 0x0040, 0x3262, 0x2200, 0xa422,
- 0x2100, 0xa31b, 0x6caa, 0x7cd2, 0x7cda, 0x6ba6, 0x7bd6, 0x7bde,
- 0x2300, 0xa405, 0x00c0, 0x3272, 0xc6f5, 0x7e5a, 0x6eb6, 0x781b,
- 0x0076, 0x007c, 0x781b, 0x0076, 0x2200, 0xa115, 0x00c0, 0x327b,
- 0x1078, 0x48bd, 0x007c, 0x1078, 0x48f5, 0x007c, 0x781b, 0x0079,
- 0x007c, 0x781b, 0x0067, 0x007c, 0x1078, 0x296b, 0x0078, 0x32d2,
- 0x6920, 0xd1c4, 0x0040, 0x329b, 0xc1c4, 0x6922, 0x0c7e, 0x7058,
- 0x2060, 0x6000, 0xc0e4, 0x6002, 0x6004, 0xa084, 0xfff5, 0x6006,
- 0x0c7f, 0x0078, 0x32c6, 0xd1cc, 0x0040, 0x32c6, 0xc1cc, 0x6922,
- 0x0c7e, 0x7058, 0x2060, 0x6000, 0xc0ec, 0x6002, 0x6004, 0xc0a4,
- 0x6006, 0x2008, 0x2c48, 0x0c7f, 0xd19c, 0x0040, 0x32c6, 0x1078,
- 0x41fa, 0x1078, 0x3ef5, 0x88ff, 0x0040, 0x32c6, 0x789b, 0x0060,
- 0x2800, 0x78aa, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x00c0, 0x32c3,
- 0x781b, 0x0064, 0x007c, 0x781b, 0x0078, 0x007c, 0x7e58, 0xd6d4,
- 0x00c0, 0x32cd, 0x781b, 0x0067, 0x007c, 0x781b, 0x0079, 0x007c,
- 0x0078, 0x40bc, 0x2019, 0x0000, 0x7990, 0xa18c, 0x0007, 0x00c0,
- 0x32e0, 0x6820, 0xa084, 0x0100, 0x0040, 0x32d0, 0x2009, 0x0008,
- 0x789b, 0x0010, 0x78a8, 0xa094, 0x00ff, 0xa286, 0x0001, 0x00c0,
- 0x32fc, 0x2300, 0x7ca8, 0xa400, 0x2018, 0xa102, 0x0040, 0x32f4,
- 0x0048, 0x32f4, 0x0078, 0x32f6, 0x0078, 0x3288, 0x24a8, 0x7aa8,
- 0x00f0, 0x32f6, 0x0078, 0x32e2, 0xa284, 0x00f0, 0xa086, 0x0020,
- 0x00c0, 0x3350, 0x8318, 0x8318, 0x2300, 0xa102, 0x0040, 0x330c,
- 0x0048, 0x330c, 0x0078, 0x334d, 0xa286, 0x0023, 0x0040, 0x32d0,
- 0x681c, 0xa084, 0xfff1, 0x681e, 0x7e58, 0xa684, 0xfff1, 0xc0a5,
- 0x2030, 0x7e5a, 0x6008, 0xc0a5, 0x600a, 0x0c7e, 0x7058, 0x2060,
- 0x6004, 0x2008, 0x2c48, 0x0c7f, 0xd1a4, 0x0040, 0x332d, 0x1078,
- 0x41fa, 0x1078, 0x4011, 0x0078, 0x333b, 0x0c7e, 0x7058, 0x2060,
- 0x6004, 0x2008, 0x2c48, 0x0c7f, 0xd19c, 0x0040, 0x32c6, 0x1078,
- 0x41fa, 0x1078, 0x3ef5, 0x88ff, 0x0040, 0x32c6, 0x789b, 0x0060,
- 0x2800, 0x78aa, 0xc695, 0x7e5a, 0xd6d4, 0x00c0, 0x334a, 0x781b,
- 0x0064, 0x007c, 0x781b, 0x0078, 0x007c, 0x7aa8, 0x0078, 0x32e2,
- 0x8318, 0x2300, 0xa102, 0x0040, 0x3359, 0x0048, 0x3359, 0x0078,
- 0x32e2, 0xa284, 0x0080, 0x00c0, 0x40c1, 0x0078, 0x40bc, 0x0078,
- 0x40c1, 0x0078, 0x40b7, 0x7058, 0xa04d, 0x789b, 0x0018, 0x78a8,
- 0xa084, 0x00ff, 0xa08e, 0x0001, 0x0040, 0x3370, 0x1078, 0x296b,
- 0x7aa8, 0xa294, 0x00ff, 0x78a8, 0xa084, 0x00ff, 0xa08a, 0x0004,
- 0x00c8, 0x40b7, 0x0079, 0x337c, 0x40b7, 0x3e46, 0x40b7, 0x3fb9,
- 0xa282, 0x0000, 0x00c0, 0x3386, 0x1078, 0x296b, 0x1078, 0x40c8,
- 0x781b, 0x0078, 0x007c, 0xa282, 0x0003, 0x00c0, 0x3391, 0x1078,
- 0x296b, 0xd4fc, 0x00c0, 0x33b1, 0x7064, 0xa005, 0x0040, 0x339a,
- 0x1078, 0x296b, 0x6f14, 0x7776, 0xa7bc, 0x8f00, 0x1078, 0x41fe,
- 0x6008, 0xa085, 0x0021, 0x600a, 0x8738, 0xa784, 0x001f, 0x00c0,
- 0x339e, 0x1078, 0x40cc, 0x7067, 0x0002, 0x701f, 0x0009, 0x0078,
- 0x33b3, 0x1078, 0x40db, 0x781b, 0x0078, 0x007c, 0xa282, 0x0004,
- 0x0050, 0x33bc, 0x1078, 0x296b, 0x2300, 0x0079, 0x33bf, 0x33c2,
- 0x3582, 0x35c5, 0xa286, 0x0003, 0x0040, 0x33fa, 0x7200, 0x7cd8,
- 0x7ddc, 0x7fd0, 0x71d4, 0xd1bc, 0x00c0, 0x33f2, 0xd1b4, 0x0040,
- 0x33f2, 0x7868, 0xa084, 0x00ff, 0x00c0, 0x33f2, 0xa282, 0x0002,
- 0x00c8, 0x33f2, 0x0d7e, 0x783b, 0x8300, 0x781b, 0x004c, 0x70bc,
- 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2,
- 0x78da, 0xc1b4, 0x71d6, 0x7003, 0x0030, 0x0d7f, 0x2001, 0x0000,
- 0x0078, 0x33fe, 0x783b, 0x1300, 0x781b, 0x004a, 0x2001, 0x0000,
- 0x0078, 0x33fe, 0x7200, 0x7cd8, 0x7ddc, 0x7fd0, 0x704a, 0x68a0,
- 0xd0ec, 0x0040, 0x3406, 0x6008, 0xc08d, 0x600a, 0xa284, 0x000f,
- 0x0079, 0x340a, 0x3562, 0x3417, 0x3414, 0x36c8, 0x3754, 0x29c5,
- 0x3412, 0x3412, 0x1078, 0x296b, 0x6008, 0xc0d4, 0x600a, 0xd6e4,
- 0x0040, 0x341f, 0x7048, 0xa086, 0x0014, 0x00c0, 0x343f, 0x1078,
- 0x4586, 0x2009, 0x0000, 0x6818, 0xd0fc, 0x0040, 0x3428, 0x7048,
- 0xa086, 0x0014, 0x0040, 0x3439, 0x6818, 0xa086, 0x0008, 0x00c0,
- 0x351a, 0x7858, 0xd09c, 0x0040, 0x351a, 0x6820, 0xd0ac, 0x0040,
- 0x351a, 0x681b, 0x0014, 0x2009, 0x0002, 0x0078, 0x347e, 0x7868,
- 0xa08c, 0x00ff, 0x0040, 0x347e, 0xa186, 0x0008, 0x00c0, 0x3455,
- 0x6008, 0xc0a4, 0x600a, 0x1078, 0x3d6f, 0x0040, 0x347e, 0x1078,
- 0x3ded, 0x1078, 0x4586, 0x0078, 0x3466, 0xa186, 0x0028, 0x00c0,
- 0x347e, 0x6018, 0xa005, 0x0040, 0x3448, 0x8001, 0x0040, 0x3448,
- 0x8001, 0x0040, 0x3448, 0x601e, 0x0078, 0x3448, 0x6820, 0xd084,
- 0x0040, 0x29c5, 0xc084, 0x6822, 0x1078, 0x2acc, 0x705c, 0x0c7e,
- 0x2060, 0x6800, 0x6002, 0x0c7f, 0x6004, 0x6802, 0xa005, 0x2d00,
- 0x00c0, 0x347b, 0x6002, 0x6006, 0x0078, 0x29c5, 0x017e, 0x81ff,
- 0x00c0, 0x34c8, 0x7000, 0xa086, 0x0030, 0x0040, 0x34c8, 0x71d4,
- 0xd1bc, 0x00c0, 0x34c8, 0xd1b4, 0x00c0, 0x34af, 0x7060, 0xa005,
- 0x00c0, 0x34c8, 0x70a4, 0xa086, 0x0001, 0x0040, 0x34c8, 0x7003,
- 0x0000, 0x047e, 0x057e, 0x077e, 0x067e, 0x0c7e, 0x0d7e, 0x1078,
- 0x29ee, 0x0d7f, 0x0c7f, 0x067f, 0x077f, 0x057f, 0x047f, 0x71d4,
- 0xd1b4, 0x00c0, 0x34c8, 0x7003, 0x0040, 0x0078, 0x34c8, 0x1078,
- 0x4360, 0x00c0, 0x34c8, 0x781b, 0x005b, 0x0d7e, 0x70bc, 0xa06d,
- 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da,
- 0xc1b4, 0x71d6, 0x7003, 0x0030, 0x7808, 0xc08d, 0x780a, 0x0d7f,
- 0x1078, 0x35ff, 0x017f, 0x81ff, 0x0040, 0x351a, 0xa684, 0xdf00,
- 0x681e, 0x682b, 0x0000, 0x6f14, 0xa186, 0x0002, 0x00c0, 0x351b,
- 0x6818, 0xa086, 0x0014, 0x00c0, 0x34e4, 0x2008, 0xd6e4, 0x0040,
- 0x34e4, 0x7868, 0xa08c, 0x00ff, 0x1078, 0x2aba, 0x1078, 0x2adb,
- 0x6820, 0xd0dc, 0x00c0, 0x351b, 0x8717, 0xa294, 0x000f, 0x8213,
- 0x8213, 0x8213, 0xb284, 0x0300, 0x0040, 0x34fa, 0xa290, 0x52c0,
- 0x0078, 0x34fc, 0xa290, 0x5340, 0xa290, 0x0000, 0x221c, 0xd3c4,
- 0x00c0, 0x3504, 0x0078, 0x350a, 0x8210, 0x2204, 0xa085, 0x0018,
- 0x2012, 0x8211, 0xd3d4, 0x0040, 0x3515, 0x68a0, 0xd0c4, 0x00c0,
- 0x3515, 0x1078, 0x3679, 0x0078, 0x29c5, 0x6008, 0xc08d, 0x600a,
- 0x0078, 0x351b, 0x692a, 0x6916, 0x6818, 0xd0fc, 0x0040, 0x3522,
- 0x7048, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x6410, 0x84ff, 0x0040,
- 0x3537, 0x2009, 0x4e02, 0x2104, 0x8001, 0x200a, 0x8421, 0x6412,
- 0x00c0, 0x3537, 0x2021, 0x4e04, 0x2404, 0xc0a5, 0x2022, 0x6018,
- 0xa005, 0x0040, 0x353f, 0x8001, 0x601a, 0x00c0, 0x3542, 0x6008,
- 0xc0a4, 0x600a, 0x6820, 0xd084, 0x00c0, 0x354e, 0x6800, 0xa005,
- 0x00c0, 0x354b, 0x6002, 0x6006, 0x0078, 0x3552, 0x705c, 0x2060,
- 0x6800, 0x6002, 0x2061, 0x4e00, 0x6887, 0x0103, 0x2d08, 0x206b,
- 0x0000, 0x6068, 0xa005, 0x616a, 0x0040, 0x3561, 0x2d02, 0x0078,
- 0x3562, 0x616e, 0x7200, 0xa286, 0x0030, 0x0040, 0x3572, 0xa286,
- 0x0040, 0x00c0, 0x29c5, 0x7003, 0x0002, 0x704c, 0x2068, 0x68c4,
- 0x2060, 0x007c, 0x7003, 0x0002, 0x70bc, 0xa06d, 0x68bc, 0x7042,
- 0x70b8, 0xa065, 0x68c0, 0x705a, 0x2d00, 0x704e, 0xad80, 0x0009,
- 0x7046, 0x007c, 0xa282, 0x0004, 0x0048, 0x3588, 0x1078, 0x296b,
- 0x2200, 0x0079, 0x358b, 0x358f, 0x35a0, 0x35ad, 0x35a0, 0xa586,
- 0x1300, 0x0040, 0x35a0, 0xa586, 0x8300, 0x00c0, 0x3586, 0x7003,
- 0x0000, 0x6018, 0x8001, 0x601a, 0x6008, 0xa084, 0xfbef, 0x600a,
- 0x7000, 0xa086, 0x0005, 0x0040, 0x35aa, 0x1078, 0x40c8, 0x781b,
- 0x0078, 0x007c, 0x781b, 0x0079, 0x007c, 0x7890, 0x8007, 0x8001,
- 0xa084, 0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c, 0x00ff,
- 0xa186, 0x0003, 0x0040, 0x35c2, 0xa186, 0x0000, 0x0040, 0x35c2,
- 0x0078, 0x40b7, 0x781b, 0x0079, 0x007c, 0x6820, 0xc095, 0x6822,
- 0x82ff, 0x00c0, 0x35cf, 0x1078, 0x40c8, 0x0078, 0x35d6, 0x8211,
- 0x0040, 0x35d4, 0x1078, 0x296b, 0x1078, 0x40db, 0x781b, 0x0078,
- 0x007c, 0x1078, 0x4383, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x35fc,
- 0x017e, 0x3208, 0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f,
- 0x0040, 0x35ee, 0xa18c, 0x0300, 0x0078, 0x35f0, 0xa18c, 0x0400,
- 0x017f, 0x0040, 0x35f7, 0x0018, 0x35fc, 0x0078, 0x35f9, 0x0028,
- 0x35fc, 0x791a, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c, 0xa684,
- 0x0060, 0x00c0, 0x3609, 0x682f, 0x0000, 0x6833, 0x0000, 0x0078,
- 0x3678, 0xd6dc, 0x00c0, 0x3621, 0x68b4, 0xd0dc, 0x00c0, 0x3621,
- 0x6998, 0x6a94, 0x692e, 0x6a32, 0x7048, 0xa005, 0x00c0, 0x361e,
- 0x2200, 0xa105, 0x0040, 0x4586, 0x704b, 0x0015, 0x0078, 0x4586,
- 0x007c, 0xd6ac, 0x0040, 0x3647, 0xd6f4, 0x0040, 0x362d, 0x682f,
- 0x0000, 0x6833, 0x0000, 0x0078, 0x4586, 0x68b4, 0xa084, 0x4000,
- 0xa635, 0xd6f4, 0x00c0, 0x3627, 0x7048, 0xa005, 0x00c0, 0x363a,
- 0x704b, 0x0015, 0xd6dc, 0x00c0, 0x3643, 0x68b4, 0xd0dc, 0x0040,
- 0x3643, 0x6ca8, 0x6da4, 0x6c2e, 0x6d32, 0x0078, 0x4586, 0xd6f4,
- 0x0040, 0x3650, 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x4586,
- 0x68b4, 0xa084, 0x4800, 0xa635, 0xd6f4, 0x00c0, 0x364a, 0x7048,
- 0xa005, 0x00c0, 0x365d, 0x704b, 0x0015, 0x2408, 0x2510, 0x2700,
- 0x80fb, 0x00c8, 0x3664, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291,
- 0x0000, 0x692e, 0x6a32, 0x2100, 0xa205, 0x00c0, 0x3671, 0x0078,
- 0x4586, 0x7000, 0xa086, 0x0006, 0x0040, 0x3678, 0x0078, 0x4586,
- 0x007c, 0x6946, 0x6008, 0xc0cd, 0xd3cc, 0x0040, 0x3680, 0xc08d,
- 0x600a, 0x6818, 0x683a, 0x681b, 0x0006, 0x688f, 0x0000, 0x6893,
- 0x0000, 0x6a30, 0x692c, 0x6a3e, 0x6942, 0x682f, 0x0003, 0x6833,
- 0x0000, 0x6837, 0x0020, 0x6897, 0x0000, 0x689b, 0x0020, 0x7000,
- 0x0079, 0x369a, 0x29c5, 0x36ac, 0x36a4, 0x36a2, 0x36a2, 0x36a2,
- 0x36a2, 0x36a2, 0x1078, 0x296b, 0x6820, 0xd084, 0x00c0, 0x36ac,
- 0x1078, 0x3dd0, 0x0078, 0x36b2, 0x705c, 0x2c50, 0x2060, 0x6800,
- 0x6002, 0x2a60, 0x3208, 0xa18c, 0x0300, 0x0040, 0x36bb, 0x2021,
- 0x4e58, 0x0078, 0x36bd, 0x2021, 0x4e98, 0x2404, 0xa005, 0x0040,
- 0x36c4, 0x2020, 0x0078, 0x36bd, 0x2d22, 0x206b, 0x0000, 0x007c,
- 0x1078, 0x3dd7, 0x1078, 0x3ded, 0x6008, 0xc0cc, 0x600a, 0x682b,
- 0x0000, 0x789b, 0x000e, 0x6f14, 0x6938, 0x691a, 0x6944, 0x6916,
- 0x3208, 0xa18c, 0x0300, 0x0040, 0x36e1, 0x2009, 0x0000, 0x0078,
- 0x36e3, 0x2009, 0x0001, 0x1078, 0x49f8, 0xd6dc, 0x0040, 0x36eb,
- 0x691c, 0xc1ed, 0x691e, 0x6818, 0xd0fc, 0x0040, 0x36fa, 0x7868,
- 0xa08c, 0x00ff, 0x0040, 0x36f8, 0x681b, 0x001e, 0x0078, 0x36fa,
- 0x681b, 0x0000, 0xb284, 0x0300, 0x00c0, 0x3702, 0x2021, 0x4e98,
- 0x0078, 0x3704, 0x2021, 0x4e58, 0x6800, 0x2022, 0x6a3c, 0x6940,
- 0x6a32, 0x692e, 0x68c0, 0x2060, 0x6000, 0xd0a4, 0x0040, 0x3744,
- 0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x0d7e, 0x0f7e,
- 0x157e, 0x147e, 0x2079, 0x4e00, 0x1078, 0x1dff, 0x147f, 0x157f,
- 0x0f7f, 0x70cc, 0x2010, 0x2009, 0x0101, 0x027e, 0x2204, 0xa06d,
- 0x0040, 0x3734, 0x6814, 0xa706, 0x0040, 0x3731, 0x6800, 0x0078,
- 0x3727, 0x6820, 0xc0d5, 0x6822, 0x027f, 0x8210, 0x8109, 0x00c0,
- 0x3725, 0x0d7f, 0x7067, 0x0003, 0x707f, 0x0000, 0x7776, 0x7083,
- 0x000f, 0x71d4, 0xc1dc, 0x71d6, 0x6818, 0xa086, 0x0002, 0x00c0,
- 0x3750, 0x6817, 0x0000, 0x682b, 0x0000, 0x681c, 0xc0ec, 0x681e,
- 0x1078, 0x202c, 0x0078, 0x29c5, 0x7cd8, 0x7ddc, 0x7fd0, 0x1078,
- 0x35ff, 0x682b, 0x0000, 0x789b, 0x000e, 0x6f14, 0x1078, 0x4387,
- 0xa08c, 0x00ff, 0x6916, 0x6818, 0xd0fc, 0x0040, 0x3769, 0x7048,
- 0x681a, 0xa68c, 0xdf00, 0x691e, 0x7067, 0x0000, 0x0078, 0x29c5,
- 0x7000, 0xa005, 0x00c0, 0x3776, 0x0078, 0x29c5, 0xa006, 0x1078,
- 0x4586, 0x6920, 0xd1ac, 0x00c0, 0x377f, 0x681b, 0x0014, 0xa68c,
- 0xdf00, 0x691e, 0x682b, 0x0000, 0x6820, 0xa084, 0x00ff, 0x6822,
- 0x7000, 0x0079, 0x378b, 0x29c5, 0x3795, 0x3795, 0x3798, 0x3798,
- 0x3798, 0x3793, 0x3793, 0x1078, 0x296b, 0x6818, 0x0078, 0x33fa,
- 0x6008, 0xc0a4, 0x600a, 0x6817, 0x0000, 0x0078, 0x3d95, 0x2300,
- 0x0079, 0x37a2, 0x37a5, 0x37a7, 0x3817, 0x1078, 0x296b, 0xd6fc,
- 0x00c0, 0x37fe, 0x7000, 0xa00d, 0x0079, 0x37ae, 0x29c5, 0x37b8,
- 0x37b8, 0x37e8, 0x37b8, 0x37fb, 0x37b6, 0x37b6, 0x1078, 0x296b,
- 0xa684, 0x0060, 0x0040, 0x37e8, 0xa086, 0x0060, 0x00c0, 0x37e5,
- 0xc6ac, 0xc6f4, 0xc6ed, 0x7e5a, 0x6eb6, 0x681c, 0xc0ac, 0x681e,
- 0xa186, 0x0002, 0x0040, 0x37d7, 0x1078, 0x4586, 0x69ac, 0x68b0,
- 0xa115, 0x0040, 0x37d7, 0x1078, 0x48f5, 0x0078, 0x37d9, 0x1078,
- 0x48bd, 0x781b, 0x0079, 0x71d4, 0xd1b4, 0x00c0, 0x29c1, 0x70a4,
- 0xa086, 0x0001, 0x00c0, 0x2a0b, 0x007c, 0xd6ec, 0x0040, 0x37c2,
- 0x6818, 0xd0fc, 0x0040, 0x37fb, 0xd6f4, 0x00c0, 0x37f5, 0x681b,
- 0x0015, 0x781b, 0x0079, 0x0078, 0x29c1, 0x681b, 0x0007, 0x682f,
- 0x0000, 0x6833, 0x0000, 0x1078, 0x4319, 0x007c, 0xc6fc, 0x7e5a,
- 0x7adc, 0x79d8, 0x78d0, 0x801b, 0x00c8, 0x3807, 0x8000, 0xa084,
- 0x003f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2,
- 0x6b94, 0x2200, 0xa303, 0x68ae, 0x781b, 0x0079, 0x007c, 0x1078,
- 0x296b, 0x2300, 0x0079, 0x381c, 0x3821, 0x3846, 0x38a6, 0x1078,
- 0x296b, 0x7000, 0x0079, 0x3824, 0x382c, 0x382e, 0x3837, 0x382c,
- 0x382c, 0x382c, 0x382c, 0x382c, 0x1078, 0x296b, 0x69ac, 0x68b0,
- 0xa115, 0x0040, 0x3837, 0x1078, 0x48f5, 0x0078, 0x3839, 0x1078,
- 0x48bd, 0x681c, 0xc0b4, 0x681e, 0x70d4, 0xd0b4, 0x00c0, 0x29c1,
- 0x70a4, 0xa086, 0x0001, 0x00c0, 0x2a0b, 0x007c, 0xd6fc, 0x00c0,
- 0x3896, 0x7000, 0xa00d, 0x0079, 0x384d, 0x29c5, 0x385d, 0x3857,
- 0x388d, 0x385d, 0x3893, 0x3855, 0x3855, 0x1078, 0x296b, 0x6894,
- 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0xa684, 0x0060, 0x0040,
- 0x388d, 0xa086, 0x0060, 0x00c0, 0x388a, 0xa6b4, 0xbfbf, 0xc6ed,
- 0x7e5a, 0x6eb6, 0xa186, 0x0002, 0x0040, 0x3879, 0x1078, 0x4586,
- 0x69ac, 0x68b0, 0xa115, 0x0040, 0x3879, 0x1078, 0x48f5, 0x0078,
- 0x387b, 0x1078, 0x48bd, 0x781b, 0x0079, 0x681c, 0xc0b4, 0x681e,
- 0x71d4, 0xd1b4, 0x00c0, 0x29c1, 0x70a4, 0xa086, 0x0001, 0x00c0,
- 0x2a0b, 0x007c, 0xd6ec, 0x0040, 0x3867, 0x6818, 0xd0fc, 0x0040,
- 0x3893, 0x681b, 0x0007, 0x781b, 0x00f9, 0x007c, 0xc6fc, 0x7e5a,
- 0x7adc, 0x79d8, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200,
- 0xa303, 0x68ae, 0x79d2, 0x781b, 0x0079, 0x007c, 0xd6dc, 0x0040,
- 0x38af, 0x782b, 0x3009, 0x781b, 0x0079, 0x0078, 0x29c1, 0x7884,
- 0xc0ac, 0x7886, 0x78e4, 0xa084, 0x0008, 0x00c0, 0x38c2, 0xa484,
- 0x0200, 0x0040, 0x38bc, 0xc6f5, 0xc6dd, 0x7e5a, 0x781b, 0x0079,
- 0x0078, 0x29c1, 0x6820, 0xc095, 0x6822, 0x1078, 0x4292, 0xc6dd,
- 0x1078, 0x40c8, 0x781b, 0x0078, 0x0078, 0x29c1, 0x2300, 0x0079,
- 0x38d1, 0x38d4, 0x38d6, 0x38d8, 0x1078, 0x296b, 0x0078, 0x40c1,
- 0xd6d4, 0x00c0, 0x3913, 0x79e4, 0xd1ac, 0x0040, 0x38e6, 0x78ec,
- 0xa084, 0x0003, 0x0040, 0x38e6, 0x782b, 0x3009, 0x789b, 0x0060,
- 0x78ab, 0x0000, 0xa684, 0xfffb, 0x785a, 0x79e4, 0xd1ac, 0x0040,
- 0x38f6, 0x78ec, 0xa084, 0x0003, 0x00c0, 0x390f, 0x2001, 0x4e04,
- 0x2004, 0xd0e4, 0x00c0, 0x390b, 0x6820, 0xd0c4, 0x0040, 0x390b,
- 0x0c7e, 0x7058, 0x2060, 0x6004, 0xc09d, 0x6006, 0x6008, 0xa084,
- 0x00ff, 0x600a, 0x0c7f, 0x2001, 0x0014, 0x0078, 0x33fa, 0xa184,
- 0x0007, 0x0079, 0x3949, 0x7a90, 0xa294, 0x0007, 0x789b, 0x0060,
- 0x79a8, 0x81ff, 0x0040, 0x3947, 0x789b, 0x0010, 0x7ba8, 0xa384,
- 0x0001, 0x00c0, 0x393a, 0x7ba8, 0x7ba8, 0xa386, 0x0001, 0x00c0,
- 0x392d, 0x2009, 0xfff7, 0x0078, 0x3933, 0xa386, 0x0003, 0x00c0,
- 0x393a, 0x2009, 0xffef, 0x0c7e, 0x7058, 0x2060, 0x6004, 0xa104,
- 0x6006, 0x0c7f, 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb,
- 0x785a, 0x782b, 0x3009, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0078,
- 0x430d, 0x3090, 0x309a, 0x3953, 0x3959, 0x3951, 0x3951, 0x430d,
- 0x430d, 0x1078, 0x296b, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0078,
- 0x4313, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0078, 0x430d, 0x79e4,
- 0xa184, 0x0030, 0x0040, 0x3969, 0x78ec, 0xa084, 0x0003, 0x00c0,
- 0x399d, 0x7000, 0xa086, 0x0004, 0x00c0, 0x3983, 0x7064, 0xa086,
- 0x0002, 0x00c0, 0x3979, 0x2011, 0x0002, 0x2019, 0x0000, 0x0078,
- 0x2f1c, 0x7064, 0xa086, 0x0006, 0x0040, 0x3973, 0x7064, 0xa086,
- 0x0004, 0x0040, 0x3973, 0x7000, 0xa086, 0x0000, 0x0040, 0x29c1,
- 0x6920, 0xa184, 0x0420, 0x0040, 0x3992, 0xc1d4, 0x6922, 0x6818,
- 0x0078, 0x33fa, 0x6818, 0xa08e, 0x0002, 0x0040, 0x399b, 0xc0fd,
- 0x681a, 0x2001, 0x0014, 0x0078, 0x33fa, 0xa184, 0x0007, 0x0079,
- 0x39a1, 0x430d, 0x430d, 0x39a9, 0x430d, 0x4355, 0x4355, 0x430d,
- 0x430d, 0xd6bc, 0x0040, 0x39eb, 0x7184, 0x81ff, 0x0040, 0x39eb,
- 0xa182, 0x000d, 0x00d0, 0x39b8, 0x7087, 0x0000, 0x0078, 0x39bd,
- 0xa182, 0x000c, 0x7086, 0x2009, 0x000c, 0x789b, 0x0061, 0x79aa,
- 0x157e, 0x137e, 0x147e, 0x7088, 0x8114, 0xa210, 0x728a, 0xa080,
- 0x000b, 0xad00, 0x2098, 0xb284, 0x0300, 0x0040, 0x39df, 0x007e,
- 0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x39db, 0x20a1,
- 0x012b, 0x0078, 0x39e1, 0x20a1, 0x022b, 0x0078, 0x39e1, 0x20a1,
- 0x012b, 0x789b, 0x0000, 0x8108, 0x81ac, 0x53a6, 0x147f, 0x137f,
- 0x157f, 0x0078, 0x4313, 0xd6d4, 0x00c0, 0x3a3f, 0x6820, 0xd084,
- 0x0040, 0x4313, 0xa68c, 0x0060, 0xa684, 0x0060, 0x0040, 0x39fd,
- 0xa086, 0x0060, 0x00c0, 0x39fd, 0xc1f5, 0xc194, 0x795a, 0x69b6,
- 0x789b, 0x0060, 0x78ab, 0x0000, 0x789b, 0x0061, 0x6818, 0xc0fd,
- 0x681a, 0x78aa, 0x8008, 0x810c, 0x0040, 0x3e06, 0xa18c, 0x00f8,
- 0x00c0, 0x3e06, 0x157e, 0x137e, 0x147e, 0x017e, 0x3208, 0xa18c,
- 0x0300, 0x0040, 0x3a2b, 0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec,
- 0x007f, 0x0040, 0x3a27, 0x20a1, 0x012b, 0x0078, 0x3a2d, 0x20a1,
- 0x022b, 0x0078, 0x3a2d, 0x20a1, 0x012b, 0x017f, 0x789b, 0x0000,
- 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f, 0x137f,
- 0x157f, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x0078, 0x4313, 0x6818,
- 0xd0fc, 0x0040, 0x3a45, 0x681b, 0x0008, 0x6820, 0xc0ad, 0x6822,
- 0x1078, 0x40d0, 0x781b, 0x00ea, 0x007c, 0x2300, 0x0079, 0x3a50,
- 0x3a55, 0x3b2d, 0x3a53, 0x1078, 0x296b, 0x7cd8, 0x7ddc, 0x7fd0,
- 0x82ff, 0x00c0, 0x3a7e, 0x7200, 0xa286, 0x0003, 0x0040, 0x33c7,
- 0x71d4, 0xd1bc, 0x00c0, 0x3a81, 0xd1b4, 0x0040, 0x3a81, 0x0d7e,
- 0x783b, 0x8800, 0x781b, 0x004c, 0x70bc, 0xa06d, 0x68b4, 0xc0a5,
- 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0xc1b4,
- 0x71d6, 0x7003, 0x0030, 0x0d7f, 0x0078, 0x3a85, 0x7200, 0x0078,
- 0x3a85, 0x783b, 0x1800, 0x781b, 0x004a, 0xa284, 0x000f, 0x0079,
- 0x3a89, 0x3b18, 0x3ac7, 0x3a93, 0x33f6, 0x3a91, 0x3b18, 0x3a91,
- 0x3a91, 0x1078, 0x296b, 0x681c, 0xd0ec, 0x0040, 0x3a9a, 0x6008,
- 0xc08d, 0x600a, 0x6920, 0xc185, 0x6922, 0x6800, 0x6006, 0xa005,
- 0x00c0, 0x3aa3, 0x6002, 0x6008, 0xc0d4, 0x600a, 0x681c, 0xa084,
- 0x000e, 0x00c0, 0x3ab7, 0xb284, 0x0300, 0x0040, 0x3ab3, 0x2009,
- 0x94c0, 0x0078, 0x3abc, 0x2009, 0x95d0, 0x0078, 0x3abc, 0x7030,
- 0x68ba, 0x7140, 0x70cc, 0xa108, 0x2104, 0x6802, 0x2d0a, 0x715e,
- 0xd6dc, 0x00c0, 0x3ac7, 0xc6fc, 0x6eb6, 0x0078, 0x3b18, 0x6eb6,
- 0xa684, 0x0060, 0x00c0, 0x3ad1, 0xa684, 0x7fff, 0x68b6, 0x0078,
- 0x3b18, 0xd6dc, 0x00c0, 0x3adf, 0xa684, 0x7fff, 0x68b6, 0x6894,
- 0x68a6, 0x6898, 0x68aa, 0x1078, 0x4586, 0x0078, 0x3b18, 0xd6ac,
- 0x0040, 0x3aeb, 0xa006, 0x1078, 0x4586, 0x2408, 0x2510, 0x69aa,
- 0x6aa6, 0x0078, 0x3afb, 0x2408, 0x2510, 0x2700, 0x801b, 0x00c8,
- 0x3af2, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x69aa,
- 0x6aa6, 0x1078, 0x4586, 0xd6fc, 0x0040, 0x3b18, 0xa684, 0x7fff,
- 0x68b6, 0x2510, 0x2408, 0xd6ac, 0x00c0, 0x3b10, 0x2700, 0x801b,
- 0x00c8, 0x3b0b, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000,
+ 0x00ff, 0xa205, 0x6822, 0x1078, 0x2073, 0x2021, 0x4f02, 0x241c,
+ 0x8319, 0x2322, 0x6010, 0x8001, 0x6012, 0x00c0, 0x3064, 0x2021,
+ 0x4f04, 0x2404, 0xc0a5, 0x2022, 0x6008, 0xa084, 0xf9ef, 0x600a,
+ 0x1078, 0x2b22, 0x1078, 0x3e36, 0x007c, 0xa085, 0x0001, 0x0078,
+ 0x306c, 0x2300, 0x0079, 0x3074, 0x3079, 0x3077, 0x30f9, 0x1078,
+ 0x29b2, 0x78e4, 0xa005, 0x00d0, 0x30af, 0x3208, 0x007e, 0x2001,
+ 0x4f04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x308a, 0xa18c, 0x0300,
+ 0x0078, 0x308c, 0xa18c, 0x0400, 0x0040, 0x3092, 0x0018, 0x2a08,
+ 0x0078, 0x3094, 0x0028, 0x2a08, 0x2008, 0xa084, 0x0030, 0x00c0,
+ 0x309b, 0x0078, 0x37b9, 0x78ec, 0xa084, 0x0003, 0x0040, 0x3099,
+ 0x2100, 0xa084, 0x0007, 0x0079, 0x30a5, 0x30d9, 0x30e3, 0x30ce,
+ 0x30ad, 0x43a5, 0x43a5, 0x30ad, 0x30ee, 0x1078, 0x29b2, 0x7000,
+ 0xa086, 0x0004, 0x00c0, 0x30c9, 0x7064, 0xa086, 0x0002, 0x00c0,
+ 0x30bf, 0x2011, 0x0002, 0x2019, 0x0000, 0x0078, 0x2f65, 0x7064,
+ 0xa086, 0x0006, 0x0040, 0x30b9, 0x7064, 0xa086, 0x0004, 0x0040,
+ 0x30b9, 0x79e4, 0x2001, 0x0003, 0x0078, 0x3443, 0x6818, 0xd0fc,
+ 0x0040, 0x30d4, 0x681b, 0x001d, 0x1078, 0x4118, 0x781b, 0x0064,
+ 0x007c, 0x6818, 0xd0fc, 0x0040, 0x30df, 0x681b, 0x001d, 0x1078,
+ 0x4118, 0x0078, 0x4381, 0x6818, 0xd0fc, 0x0040, 0x30e9, 0x681b,
+ 0x001d, 0x1078, 0x4118, 0x781b, 0x00f8, 0x007c, 0x6818, 0xd0fc,
+ 0x0040, 0x30f4, 0x681b, 0x001d, 0x1078, 0x4118, 0x781b, 0x00c8,
+ 0x007c, 0xa584, 0x000f, 0x00c0, 0x3118, 0x1078, 0x29a5, 0x7000,
+ 0x0079, 0x3102, 0x2a0c, 0x310a, 0x310c, 0x3dc7, 0x3dc7, 0x3dc7,
+ 0x310a, 0x310a, 0x1078, 0x29b2, 0x1078, 0x3e36, 0x6008, 0xa084,
+ 0xfbef, 0x600a, 0x1078, 0x3db8, 0x0040, 0x3dc7, 0x0078, 0x2a0c,
+ 0x78e4, 0xa005, 0x00d0, 0x30af, 0x3208, 0x007e, 0x2001, 0x4f04,
+ 0x2004, 0xd0ec, 0x007f, 0x0040, 0x3129, 0xa18c, 0x0300, 0x0078,
+ 0x312b, 0xa18c, 0x0400, 0x0040, 0x3131, 0x0018, 0x30af, 0x0078,
+ 0x3133, 0x0028, 0x30af, 0x2008, 0xa084, 0x0030, 0x00c0, 0x313b,
+ 0x781b, 0x005b, 0x007c, 0x78ec, 0xa084, 0x0003, 0x0040, 0x3138,
+ 0x2100, 0xa184, 0x0007, 0x0079, 0x3145, 0x3154, 0x3158, 0x314f,
+ 0x314d, 0x43a5, 0x43a5, 0x314d, 0x439f, 0x1078, 0x29b2, 0x1078,
+ 0x4120, 0x781b, 0x0064, 0x007c, 0x1078, 0x4120, 0x0078, 0x4381,
+ 0x1078, 0x4120, 0x781b, 0x00f8, 0x007c, 0x1078, 0x4120, 0x781b,
+ 0x00c8, 0x007c, 0x2300, 0x0079, 0x3165, 0x316a, 0x3168, 0x316c,
+ 0x1078, 0x29b2, 0x0078, 0x39a8, 0x681b, 0x0016, 0x78a3, 0x0000,
+ 0x79e4, 0xa184, 0x0030, 0x0040, 0x39a8, 0x78ec, 0xa084, 0x0003,
+ 0x0040, 0x39a8, 0xa184, 0x0100, 0x0040, 0x3170, 0xa184, 0x0007,
+ 0x0079, 0x3182, 0x318a, 0x3158, 0x30ce, 0x435d, 0x43a5, 0x43a5,
+ 0x435d, 0x439f, 0x1078, 0x4369, 0x007c, 0xa282, 0x0005, 0x0050,
+ 0x3193, 0x1078, 0x29b2, 0x2300, 0x0079, 0x3196, 0x3199, 0x33c9,
+ 0x33d4, 0x2200, 0x0079, 0x319c, 0x31b6, 0x31a3, 0x31b6, 0x31a1,
+ 0x33ac, 0x1078, 0x29b2, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff,
+ 0xa082, 0x0020, 0x0048, 0x4107, 0xa08a, 0x0004, 0x00c8, 0x4107,
+ 0x0079, 0x31b2, 0x4107, 0x4107, 0x4107, 0x40b1, 0x789b, 0x0018,
+ 0x79a8, 0xa184, 0x0080, 0x0040, 0x31c7, 0x0078, 0x4107, 0x7000,
+ 0xa005, 0x00c0, 0x31bd, 0x2011, 0x0004, 0x0078, 0x3b93, 0xa184,
+ 0x00ff, 0xa08a, 0x0010, 0x00c8, 0x4107, 0x0079, 0x31cf, 0x31e1,
+ 0x31df, 0x31f6, 0x31fa, 0x32cd, 0x4107, 0x4107, 0x32cf, 0x4107,
+ 0x4107, 0x33a8, 0x33a8, 0x4107, 0x4107, 0x4107, 0x33aa, 0x1078,
+ 0x29b2, 0xd6e4, 0x0040, 0x31ec, 0x2001, 0x0300, 0x8000, 0x8000,
+ 0x783a, 0x781b, 0x00c3, 0x007c, 0x6818, 0xd0fc, 0x0040, 0x31f4,
+ 0x681b, 0x001d, 0x0078, 0x31e4, 0x0078, 0x435d, 0x681b, 0x001d,
+ 0x0078, 0x4111, 0x6920, 0x6922, 0xa684, 0x1800, 0x00c0, 0x325f,
+ 0x6820, 0xd084, 0x00c0, 0x3265, 0x6818, 0xa086, 0x0008, 0x00c0,
+ 0x320b, 0x681b, 0x0000, 0xd6d4, 0x0040, 0x32ca, 0xd6bc, 0x0040,
+ 0x324b, 0x7087, 0x0000, 0x6818, 0xa084, 0x003f, 0xa08a, 0x000d,
+ 0x0050, 0x324b, 0xa08a, 0x000c, 0x7186, 0x2001, 0x000c, 0x800c,
+ 0x718a, 0x789b, 0x0061, 0x78aa, 0x157e, 0x137e, 0x147e, 0x017e,
+ 0x3208, 0xa18c, 0x0300, 0x0040, 0x323d, 0x007e, 0x2001, 0x4f04,
+ 0x2004, 0xd0ec, 0x007f, 0x0040, 0x3239, 0x20a1, 0x012b, 0x0078,
+ 0x323f, 0x20a1, 0x022b, 0x0078, 0x323f, 0x20a1, 0x012b, 0x017f,
+ 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6,
+ 0x147f, 0x137f, 0x157f, 0x6038, 0xa005, 0x00c0, 0x325a, 0x681c,
+ 0xa084, 0x000e, 0x0040, 0x4111, 0x1078, 0x4127, 0x782b, 0x3008,
+ 0x0078, 0x325c, 0x8001, 0x603a, 0x781b, 0x0067, 0x007c, 0xd6e4,
+ 0x0040, 0x3265, 0x781b, 0x0079, 0x007c, 0xa684, 0x0060, 0x0040,
+ 0x32c7, 0xd6dc, 0x0040, 0x32c7, 0xd6fc, 0x00c0, 0x3271, 0x0078,
+ 0x3288, 0xc6fc, 0x7e5a, 0x6eb6, 0x7adc, 0x79d8, 0x78d0, 0x801b,
+ 0x00c8, 0x327b, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000,
0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae,
- 0x7000, 0xa086, 0x0030, 0x00c0, 0x29c5, 0x7003, 0x0002, 0x70bc,
- 0xa06d, 0x68bc, 0x7042, 0x70b8, 0xa065, 0x68c0, 0x705a, 0x2d00,
- 0x704e, 0xad80, 0x0009, 0x7046, 0x007c, 0xa586, 0x8800, 0x00c0,
- 0x3b3a, 0x7003, 0x0000, 0x6018, 0x8001, 0x601a, 0x6008, 0xa084,
- 0xfbef, 0x600a, 0x0078, 0x40c1, 0x7047, 0x0000, 0xa282, 0x0006,
- 0x0050, 0x3b44, 0x1078, 0x296b, 0x2300, 0x0079, 0x3b47, 0x3b4a,
- 0x3b5c, 0x3b68, 0x2200, 0x0079, 0x3b4d, 0x3b53, 0x40c1, 0x3b55,
- 0x3b53, 0x3ba2, 0x3bf7, 0x1078, 0x296b, 0x7a80, 0xa294, 0x0f00,
- 0x1078, 0x3c81, 0x0078, 0x40b7, 0x1078, 0x3b79, 0x0079, 0x3b60,
- 0x40c1, 0x3b66, 0x3b66, 0x3ba2, 0x3b66, 0x40c1, 0x1078, 0x296b,
- 0x1078, 0x3b79, 0x0079, 0x3b6c, 0x3b74, 0x3b72, 0x3b72, 0x3b74,
- 0x3b72, 0x3b74, 0x1078, 0x296b, 0x1078, 0x40db, 0x781b, 0x0078,
- 0x007c, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3b8a, 0x1078, 0x3ded,
- 0x0078, 0x3b84, 0x1078, 0x4586, 0x6008, 0xa084, 0xfbef, 0x600a,
- 0x0078, 0x3b8f, 0x7000, 0xa086, 0x0003, 0x0040, 0x3b82, 0x7003,
- 0x0005, 0xb284, 0x0300, 0x0040, 0x3b99, 0x2001, 0x95e0, 0x0078,
- 0x3b9b, 0x2001, 0x9612, 0x2068, 0x704e, 0xad80, 0x0009, 0x7046,
- 0x2200, 0x007c, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3bb4, 0x70d4,
- 0xc0b5, 0x70d6, 0x2c00, 0x70ba, 0x2d00, 0x70be, 0x0078, 0x3bb9,
- 0x1078, 0x4586, 0x0078, 0x3bb9, 0x7000, 0xa086, 0x0003, 0x0040,
- 0x3bb0, 0x7003, 0x0001, 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018,
- 0x7ca8, 0xa484, 0x001f, 0xa215, 0x2069, 0x94c0, 0xb284, 0x0300,
- 0x00c0, 0x3bcd, 0xc2fd, 0x2069, 0x95d0, 0x2d04, 0x2d08, 0x715e,
- 0xa06d, 0x0040, 0x3bda, 0x6814, 0xa206, 0x0040, 0x3bdc, 0x6800,
- 0x0078, 0x3bce, 0x1078, 0x3c81, 0x6eb4, 0x7e5a, 0x6920, 0xa184,
- 0x0c00, 0x0040, 0x3cab, 0x7064, 0xa086, 0x0006, 0x00c0, 0x3bee,
- 0x7074, 0xa206, 0x00c0, 0x3bee, 0x7066, 0x707e, 0x681b, 0x0005,
- 0xc1ad, 0xc1d4, 0x6922, 0x1078, 0x40d0, 0x0078, 0x3cab, 0x7200,
- 0xa286, 0x0002, 0x00c0, 0x3c09, 0x70d4, 0xc0b5, 0x70d6, 0x2c00,
- 0x70ba, 0x2d00, 0x70be, 0x0078, 0x3c0d, 0x1078, 0x4586, 0x0078,
- 0x3c0d, 0xa286, 0x0003, 0x0040, 0x3c05, 0x7003, 0x0001, 0x7a80,
- 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, 0x001f, 0xa215,
- 0xb284, 0x0300, 0x00c0, 0x3c1d, 0xc2fd, 0x79a8, 0x79a8, 0xa18c,
- 0x00ff, 0x2118, 0x70cc, 0xa168, 0x2d04, 0x2d08, 0x715e, 0xa06d,
- 0x0040, 0x3c31, 0x6814, 0xa206, 0x0040, 0x3c5a, 0x6800, 0x0078,
- 0x3c25, 0x7003, 0x0005, 0xb284, 0x0300, 0x0040, 0x3c3b, 0x2001,
- 0x95e0, 0x0078, 0x3c3d, 0x2001, 0x9612, 0x2068, 0x704e, 0x157e,
- 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, 0x00f0, 0x3c42, 0x157f,
- 0xb284, 0x0300, 0x0040, 0x3c4f, 0xc2fc, 0x0078, 0x3c50, 0xc2fd,
- 0x6a16, 0xad80, 0x0009, 0x7046, 0x68b7, 0x0700, 0x6823, 0x0800,
- 0x6827, 0x0003, 0x6eb4, 0x6920, 0xa184, 0x0c00, 0x0040, 0x3cab,
- 0xd0dc, 0x0040, 0x3c76, 0x7064, 0xa086, 0x0004, 0x00c0, 0x3c72,
- 0x7074, 0xa206, 0x00c0, 0x3c72, 0x7078, 0xa306, 0x00c0, 0x3c72,
- 0x7066, 0x707e, 0x1078, 0x40d7, 0x0078, 0x3cab, 0x681b, 0x0005,
- 0xc1ad, 0xc1d4, 0x6922, 0x1078, 0x40d0, 0x707f, 0x0000, 0x0078,
- 0x3cab, 0x7003, 0x0005, 0xb284, 0x0300, 0x0040, 0x3c8b, 0x2001,
- 0x95e0, 0x0078, 0x3c8d, 0x2001, 0x9612, 0x2068, 0x704e, 0x157e,
- 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, 0x00f0, 0x3c92, 0x157f,
- 0xb284, 0x0300, 0x0040, 0x3c9f, 0xc2fc, 0x0078, 0x3ca0, 0xc2fd,
- 0x6a16, 0xad80, 0x0009, 0x7046, 0x68b7, 0x0700, 0x6823, 0x0800,
- 0x6827, 0x0003, 0x007c, 0xc6ec, 0xa6ac, 0x0060, 0x0040, 0x3cfd,
- 0x6b98, 0x6c94, 0x69ac, 0x68b0, 0xa105, 0x00c0, 0x3cd8, 0x7bd2,
- 0x7bda, 0x7cd6, 0x7cde, 0xa586, 0x0060, 0x0040, 0x3d02, 0xd6f4,
- 0x00c0, 0x3cc3, 0xc6ed, 0xa6b4, 0xb7ff, 0x7e5a, 0x2009, 0x0079,
- 0xd69c, 0x0040, 0x3cd0, 0x2009, 0x0078, 0x2019, 0x0000, 0x2320,
- 0x791a, 0xd6ec, 0x0040, 0x3d0d, 0x1078, 0x48bd, 0x0078, 0x3d0d,
- 0x68b0, 0xa31a, 0x2100, 0xa423, 0x2400, 0xa305, 0x0040, 0x3d04,
- 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0x68b0, 0xd6f4, 0x00c0, 0x3ce9,
- 0xc6ed, 0xc6f4, 0x7e5a, 0x2011, 0x0079, 0xd69c, 0x0040, 0x3cf5,
- 0x2011, 0x0078, 0x2019, 0x0000, 0x2320, 0x7a1a, 0xd6ec, 0x0040,
- 0x3d0d, 0x1078, 0x48f5, 0x0078, 0x3d0d, 0x2019, 0x0000, 0x2320,
- 0x0078, 0x3d04, 0xa6b4, 0xb7ff, 0x7e5a, 0x2009, 0x0079, 0xd69c,
- 0x0040, 0x3d0c, 0x2009, 0x0078, 0x791a, 0x68c0, 0x705a, 0x2d00,
- 0x704e, 0x68c4, 0x2060, 0x71d4, 0x2001, 0x4e01, 0x2004, 0xd0c4,
- 0x00c0, 0x3d62, 0x70d8, 0xa02d, 0x0040, 0x3d3b, 0xd1bc, 0x0040,
- 0x3d55, 0x7a80, 0xa294, 0x0f00, 0x70dc, 0xa206, 0x0040, 0x3d2c,
- 0x78e0, 0xa504, 0x00c0, 0x3d62, 0x70da, 0xc1bc, 0x71d6, 0x0078,
- 0x3d62, 0x2031, 0x0001, 0x852c, 0x0048, 0x3d3a, 0x8633, 0x8210,
- 0x0078, 0x3d33, 0x007c, 0x7de0, 0xa594, 0xff00, 0x0040, 0x3d48,
- 0x2011, 0x0008, 0x852f, 0x1078, 0x3d31, 0x8637, 0x0078, 0x3d4a,
- 0x1078, 0x3d31, 0x8217, 0x7880, 0xa084, 0x0f00, 0xa206, 0x0040,
- 0x3d62, 0x72de, 0x76da, 0x0078, 0x3d62, 0x7a80, 0xa294, 0x0f00,
- 0x70dc, 0xa236, 0x0040, 0x3d52, 0x78e0, 0xa534, 0x0040, 0x3d52,
- 0xc1bd, 0x71d6, 0xd1b4, 0x00c0, 0x29c1, 0x2300, 0xa405, 0x0040,
- 0x29c1, 0x70a4, 0xa086, 0x0001, 0x00c0, 0x2a0b, 0x007c, 0x6020,
- 0xa005, 0x0040, 0x3d7d, 0x8001, 0x6022, 0x6008, 0xa085, 0x0008,
- 0x600a, 0x700f, 0x0100, 0x702c, 0x6026, 0x007c, 0xa006, 0x1078,
- 0x4586, 0x7000, 0xa086, 0x0002, 0x0040, 0x3d8b, 0x7064, 0xa086,
- 0x0005, 0x00c0, 0x3d95, 0x682b, 0x0000, 0x6817, 0x0000, 0x681b,
- 0x0001, 0x6823, 0x0040, 0x681f, 0x0100, 0x7000, 0xa084, 0x000f,
- 0x0079, 0x3d9a, 0x29c5, 0x3daa, 0x3da4, 0x3dcc, 0x3db4, 0x29c5,
- 0x3da2, 0x3da2, 0x1078, 0x296b, 0x1078, 0x3dd7, 0x1078, 0x3dd0,
- 0x0078, 0x3db0, 0x1078, 0x3dd7, 0x705c, 0x2060, 0x6800, 0x6002,
- 0x1078, 0x202c, 0x0078, 0x29c5, 0x7064, 0x7067, 0x0000, 0x7083,
- 0x0000, 0x0079, 0x3dbb, 0x3dc8, 0x3dc8, 0x3dc3, 0x3dc3, 0x3dc3,
- 0x3dc8, 0x3dc3, 0x3dc8, 0x77d4, 0xc7dd, 0x77d6, 0x0079, 0x2f35,
- 0x7067, 0x0000, 0x0078, 0x29c5, 0x681b, 0x0000, 0x0078, 0x36c8,
- 0x6800, 0xa005, 0x00c0, 0x3dd5, 0x6002, 0x6006, 0x007c, 0x6410,
- 0x84ff, 0x0040, 0x3de9, 0x2009, 0x4e02, 0x2104, 0x8001, 0x200a,
- 0x8421, 0x6412, 0x00c0, 0x3de9, 0x2021, 0x4e04, 0x2404, 0xc0a5,
- 0x2022, 0x6008, 0xc0a4, 0x600a, 0x007c, 0x6018, 0xa005, 0x0040,
- 0x3df3, 0x8001, 0x601a, 0x007c, 0x1078, 0x4383, 0x681b, 0x0018,
- 0x0078, 0x3e34, 0x1078, 0x4383, 0x681b, 0x0019, 0x0078, 0x3e34,
- 0x1078, 0x4383, 0x681b, 0x001a, 0x0078, 0x3e34, 0x1078, 0x4383,
- 0x681b, 0x0003, 0x0078, 0x3e34, 0x7774, 0x1078, 0x41fe, 0x7178,
- 0xa18c, 0x00ff, 0x3210, 0xa294, 0x0300, 0x0040, 0x3e1b, 0xa1e8,
- 0x93c0, 0x0078, 0x3e1d, 0xa1e8, 0x94d0, 0x2d04, 0x2d08, 0x2068,
- 0xa005, 0x00c0, 0x3e26, 0x707e, 0x0078, 0x29c5, 0x6814, 0x7274,
- 0xa206, 0x0040, 0x3e2e, 0x6800, 0x0078, 0x3e1e, 0x6800, 0x200a,
- 0x681b, 0x0005, 0x707f, 0x0000, 0x1078, 0x3dd7, 0x6820, 0xd084,
- 0x00c0, 0x3e3c, 0x1078, 0x3dd0, 0x1078, 0x3ded, 0x681f, 0x0000,
- 0x6823, 0x0020, 0x1078, 0x202c, 0x0078, 0x29c5, 0xa282, 0x0003,
- 0x00c0, 0x40b7, 0x7da8, 0xa5ac, 0x00ff, 0x7e5a, 0x7ea8, 0xa6b4,
- 0x00ff, 0x6920, 0xc1bd, 0x6922, 0xd1c4, 0x0040, 0x3ea1, 0xc1c4,
- 0x6922, 0xa6b4, 0x00ff, 0x0040, 0x3e8e, 0xa682, 0x000c, 0x0048,
- 0x3e65, 0x0040, 0x3e65, 0x2031, 0x000c, 0x2500, 0xa086, 0x000a,
- 0x0040, 0x3e6c, 0x852b, 0x852b, 0x1078, 0x4190, 0x0040, 0x3e74,
- 0x1078, 0x3f6f, 0x0078, 0x3e97, 0x1078, 0x414b, 0x0c7e, 0x2960,
- 0x6004, 0xa084, 0xfff5, 0x6006, 0x1078, 0x3fa5, 0x0c7f, 0x6920,
- 0xc1c5, 0x6922, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x00c0, 0x3e8b,
- 0x781b, 0x0064, 0x007c, 0x781b, 0x0078, 0x007c, 0x0c7e, 0x2960,
- 0x6004, 0xa084, 0xfff5, 0x6006, 0x1078, 0x3fa5, 0x0c7f, 0x7e58,
- 0xd6d4, 0x00c0, 0x3e9e, 0x781b, 0x0067, 0x007c, 0x781b, 0x0079,
- 0x007c, 0x0c7e, 0x7058, 0x2060, 0x6100, 0xd1e4, 0x0040, 0x3eea,
- 0x6208, 0x8217, 0xa294, 0x00ff, 0xa282, 0x000c, 0x0048, 0x3eb4,
- 0x0040, 0x3eb4, 0x2011, 0x000c, 0x2600, 0xa202, 0x00c8, 0x3eb9,
- 0x2230, 0x6208, 0xa294, 0x00ff, 0x2001, 0x4e05, 0x2004, 0xd0e4,
- 0x00c0, 0x3ece, 0x78ec, 0xd0e4, 0x0040, 0x3ece, 0xa282, 0x000a,
- 0x00c8, 0x3ed4, 0x2011, 0x000a, 0x0078, 0x3ed4, 0xa282, 0x000c,
- 0x00c8, 0x3ed4, 0x2011, 0x000c, 0x2200, 0xa502, 0x00c8, 0x3ed9,
- 0x2228, 0x1078, 0x414f, 0x2500, 0xa086, 0x000a, 0x0040, 0x3ee2,
- 0x852b, 0x852b, 0x1078, 0x4190, 0x0040, 0x3eea, 0x1078, 0x3f6f,
- 0x0078, 0x3eee, 0x1078, 0x414b, 0x1078, 0x3fa5, 0x7858, 0xc095,
- 0x785a, 0x0c7f, 0x781b, 0x0078, 0x007c, 0x0c7e, 0x2960, 0x6000,
- 0xd0e4, 0x00c0, 0x3f0b, 0xa084, 0x0040, 0x00c0, 0x3f05, 0x6104,
- 0xa18c, 0xfff5, 0x6106, 0x0c7f, 0x007c, 0x2011, 0x0032, 0x2019,
- 0x0000, 0x0078, 0x3f36, 0x68a0, 0xd0cc, 0x00c0, 0x3f05, 0x6208,
- 0xa294, 0x00ff, 0x2001, 0x4e05, 0x2004, 0xd0e4, 0x00c0, 0x3f24,
- 0x78ec, 0xd0e4, 0x0040, 0x3f24, 0xa282, 0x000b, 0x00c8, 0x3f24,
- 0x2011, 0x000a, 0x0078, 0x3f2a, 0xa282, 0x000c, 0x00c8, 0x3f2a,
- 0x2011, 0x000c, 0x6308, 0x831f, 0xa39c, 0x00ff, 0xa382, 0x000c,
- 0x0048, 0x3f36, 0x0040, 0x3f36, 0x2019, 0x000c, 0x78ab, 0x0001,
- 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005,
- 0x6820, 0xc0c5, 0x6822, 0x70d4, 0xd0b4, 0x0040, 0x3f52, 0xc0b4,
- 0x70d6, 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018,
- 0x8001, 0x601a, 0x0c7f, 0x007c, 0x0c7e, 0x2960, 0x6104, 0xa18c,
- 0xfff5, 0x6106, 0x2011, 0x0032, 0x2019, 0x0000, 0x0078, 0x3f60,
- 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa,
- 0xa8c0, 0x0005, 0x6820, 0xc0c5, 0x6822, 0x0c7f, 0x007c, 0x0c7e,
- 0x7158, 0x2160, 0x2018, 0xa08c, 0x0020, 0x0040, 0x3f78, 0xc0ac,
- 0x2008, 0xa084, 0xfff0, 0xa635, 0x7e86, 0x6018, 0x789a, 0x7eae,
- 0x6612, 0x78a4, 0xa084, 0xfff0, 0xa18c, 0x000f, 0xa105, 0xc0f4,
- 0xa39c, 0x0020, 0x0040, 0x3f8e, 0xa085, 0x4000, 0xc0fc, 0xd0b4,
- 0x00c0, 0x3f93, 0xc0fd, 0x78a6, 0x6016, 0x788a, 0xa6b4, 0x000f,
- 0x8637, 0x8204, 0x8004, 0xa084, 0x00ff, 0xa605, 0x600e, 0x6004,
- 0xa084, 0xfff5, 0x6006, 0x0c7f, 0x007c, 0x0c7e, 0x7058, 0x2060,
- 0x6018, 0x789a, 0x78a4, 0xa084, 0xfff0, 0x78a6, 0x6012, 0x7884,
- 0xa084, 0xfff0, 0x7886, 0x600c, 0xa084, 0x00ff, 0x600e, 0x0c7f,
- 0x007c, 0xa282, 0x0002, 0x00c0, 0x40b7, 0x7aa8, 0x6920, 0xc1bd,
- 0x6922, 0xd1cc, 0x0040, 0x3ff4, 0xc1cc, 0x6922, 0xa294, 0x00ff,
- 0xa282, 0x0002, 0x00c8, 0x40b7, 0x1078, 0x4044, 0x1078, 0x3fa5,
- 0xa980, 0x0001, 0x200c, 0x1078, 0x41fa, 0x1078, 0x3ef5, 0x88ff,
- 0x0040, 0x3fea, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695,
- 0x7e5a, 0xd6d4, 0x00c0, 0x3fe7, 0x781b, 0x0064, 0x007c, 0x781b,
- 0x0078, 0x007c, 0x7e58, 0xd6d4, 0x00c0, 0x3ff1, 0x781b, 0x0067,
- 0x007c, 0x781b, 0x0079, 0x007c, 0xa282, 0x0002, 0x00c8, 0x3ffc,
- 0xa284, 0x0001, 0x0040, 0x4005, 0x7158, 0xa188, 0x0000, 0x210c,
- 0xd1ec, 0x00c0, 0x4005, 0x2011, 0x0000, 0x1078, 0x412c, 0x1078,
- 0x4044, 0x1078, 0x3fa5, 0x7858, 0xc095, 0x785a, 0x781b, 0x0078,
- 0x007c, 0x0c7e, 0x027e, 0x2960, 0x6000, 0x2011, 0x0001, 0xd0ec,
- 0x00c0, 0x4025, 0xa084, 0x0080, 0x00c0, 0x4023, 0xc1a4, 0x6106,
- 0xa006, 0x0078, 0x4041, 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab,
+ 0xd6f4, 0x0040, 0x328e, 0xc6f4, 0x7e5a, 0x6eb6, 0x7000, 0xa086,
+ 0x0003, 0x00c0, 0x329c, 0x007e, 0x1078, 0x45d6, 0x1078, 0x493f,
+ 0x007f, 0x781b, 0x0076, 0x007c, 0xa006, 0x1078, 0x4a44, 0x6ab0,
+ 0x69ac, 0x6c98, 0x6b94, 0x2200, 0xa105, 0x0040, 0x32ab, 0x2200,
+ 0xa422, 0x2100, 0xa31b, 0x6caa, 0x7cd2, 0x7cda, 0x6ba6, 0x7bd6,
+ 0x7bde, 0x2300, 0xa405, 0x00c0, 0x32bb, 0xc6f5, 0x7e5a, 0x6eb6,
+ 0x781b, 0x0076, 0x007c, 0x781b, 0x0076, 0x2200, 0xa115, 0x00c0,
+ 0x32c4, 0x1078, 0x493f, 0x007c, 0x1078, 0x4977, 0x007c, 0x781b,
+ 0x0079, 0x007c, 0x781b, 0x0067, 0x007c, 0x1078, 0x29b2, 0x0078,
+ 0x331b, 0x6920, 0xd1c4, 0x0040, 0x32e4, 0xc1c4, 0x6922, 0x0c7e,
+ 0x7058, 0x2060, 0x6000, 0xc0e4, 0x6002, 0x6004, 0xa084, 0xfff5,
+ 0x6006, 0x0c7f, 0x0078, 0x330f, 0xd1cc, 0x0040, 0x330f, 0xc1cc,
+ 0x6922, 0x0c7e, 0x7058, 0x2060, 0x6000, 0xc0ec, 0x6002, 0x6004,
+ 0xc0a4, 0x6006, 0x2008, 0x2c48, 0x0c7f, 0xd19c, 0x0040, 0x330f,
+ 0x1078, 0x424a, 0x1078, 0x3f3e, 0x88ff, 0x0040, 0x330f, 0x789b,
+ 0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x00c0,
+ 0x330c, 0x781b, 0x0064, 0x007c, 0x781b, 0x0078, 0x007c, 0x7e58,
+ 0xd6d4, 0x00c0, 0x3316, 0x781b, 0x0067, 0x007c, 0x781b, 0x0079,
+ 0x007c, 0x0078, 0x410c, 0x2019, 0x0000, 0x7990, 0xa18c, 0x0007,
+ 0x00c0, 0x3329, 0x6820, 0xa084, 0x0100, 0x0040, 0x3319, 0x2009,
+ 0x0008, 0x789b, 0x0010, 0x78a8, 0xa094, 0x00ff, 0xa286, 0x0001,
+ 0x00c0, 0x3345, 0x2300, 0x7ca8, 0xa400, 0x2018, 0xa102, 0x0040,
+ 0x333d, 0x0048, 0x333d, 0x0078, 0x333f, 0x0078, 0x32d1, 0x24a8,
+ 0x7aa8, 0x00f0, 0x333f, 0x0078, 0x332b, 0xa284, 0x00f0, 0xa086,
+ 0x0020, 0x00c0, 0x3399, 0x8318, 0x8318, 0x2300, 0xa102, 0x0040,
+ 0x3355, 0x0048, 0x3355, 0x0078, 0x3396, 0xa286, 0x0023, 0x0040,
+ 0x3319, 0x681c, 0xa084, 0xfff1, 0x681e, 0x7e58, 0xa684, 0xfff1,
+ 0xc0a5, 0x2030, 0x7e5a, 0x6008, 0xc0a5, 0x600a, 0x0c7e, 0x7058,
+ 0x2060, 0x6004, 0x2008, 0x2c48, 0x0c7f, 0xd1a4, 0x0040, 0x3376,
+ 0x1078, 0x424a, 0x1078, 0x405e, 0x0078, 0x3384, 0x0c7e, 0x7058,
+ 0x2060, 0x6004, 0x2008, 0x2c48, 0x0c7f, 0xd19c, 0x0040, 0x330f,
+ 0x1078, 0x424a, 0x1078, 0x3f3e, 0x88ff, 0x0040, 0x330f, 0x789b,
+ 0x0060, 0x2800, 0x78aa, 0xc695, 0x7e5a, 0xd6d4, 0x00c0, 0x3393,
+ 0x781b, 0x0064, 0x007c, 0x781b, 0x0078, 0x007c, 0x7aa8, 0x0078,
+ 0x332b, 0x8318, 0x2300, 0xa102, 0x0040, 0x33a2, 0x0048, 0x33a2,
+ 0x0078, 0x332b, 0xa284, 0x0080, 0x00c0, 0x4111, 0x0078, 0x410c,
+ 0x0078, 0x4111, 0x0078, 0x4107, 0x7058, 0xa04d, 0x789b, 0x0018,
+ 0x78a8, 0xa084, 0x00ff, 0xa08e, 0x0001, 0x0040, 0x33b9, 0x1078,
+ 0x29b2, 0x7aa8, 0xa294, 0x00ff, 0x78a8, 0xa084, 0x00ff, 0xa08a,
+ 0x0004, 0x00c8, 0x4107, 0x0079, 0x33c5, 0x4107, 0x3e8f, 0x4107,
+ 0x4006, 0xa282, 0x0000, 0x00c0, 0x33cf, 0x1078, 0x29b2, 0x1078,
+ 0x4118, 0x781b, 0x0078, 0x007c, 0xa282, 0x0003, 0x00c0, 0x33da,
+ 0x1078, 0x29b2, 0xd4fc, 0x00c0, 0x33fa, 0x7064, 0xa005, 0x0040,
+ 0x33e3, 0x1078, 0x29b2, 0x6f14, 0x7776, 0xa7bc, 0x8f00, 0x1078,
+ 0x424e, 0x6008, 0xa085, 0x0021, 0x600a, 0x8738, 0xa784, 0x001f,
+ 0x00c0, 0x33e7, 0x1078, 0x411c, 0x7067, 0x0002, 0x701f, 0x0009,
+ 0x0078, 0x33fc, 0x1078, 0x412b, 0x781b, 0x0078, 0x007c, 0xa282,
+ 0x0004, 0x0050, 0x3405, 0x1078, 0x29b2, 0x2300, 0x0079, 0x3408,
+ 0x340b, 0x35cb, 0x360e, 0xa286, 0x0003, 0x0040, 0x3443, 0x7200,
+ 0x7cd8, 0x7ddc, 0x7fd0, 0x71d4, 0xd1bc, 0x00c0, 0x343b, 0xd1b4,
+ 0x0040, 0x343b, 0x7868, 0xa084, 0x00ff, 0x00c0, 0x343b, 0xa282,
+ 0x0002, 0x00c8, 0x343b, 0x0d7e, 0x783b, 0x8300, 0x781b, 0x004c,
+ 0x70bc, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898,
+ 0x78d2, 0x78da, 0xc1b4, 0x71d6, 0x7003, 0x0030, 0x0d7f, 0x2001,
+ 0x0000, 0x0078, 0x3447, 0x783b, 0x1300, 0x781b, 0x004a, 0x2001,
+ 0x0000, 0x0078, 0x3447, 0x7200, 0x7cd8, 0x7ddc, 0x7fd0, 0x704a,
+ 0x68a0, 0xd0ec, 0x0040, 0x344f, 0x6008, 0xc08d, 0x600a, 0xa284,
+ 0x000f, 0x0079, 0x3453, 0x35ab, 0x3460, 0x345d, 0x3711, 0x379d,
+ 0x2a0c, 0x345b, 0x345b, 0x1078, 0x29b2, 0x6008, 0xc0d4, 0x600a,
+ 0xd6e4, 0x0040, 0x3468, 0x7048, 0xa086, 0x0014, 0x00c0, 0x3488,
+ 0x1078, 0x45d6, 0x2009, 0x0000, 0x6818, 0xd0fc, 0x0040, 0x3471,
+ 0x7048, 0xa086, 0x0014, 0x0040, 0x3482, 0x6818, 0xa086, 0x0008,
+ 0x00c0, 0x3563, 0x7858, 0xd09c, 0x0040, 0x3563, 0x6820, 0xd0ac,
+ 0x0040, 0x3563, 0x681b, 0x0014, 0x2009, 0x0002, 0x0078, 0x34c7,
+ 0x7868, 0xa08c, 0x00ff, 0x0040, 0x34c7, 0xa186, 0x0008, 0x00c0,
+ 0x349e, 0x6008, 0xc0a4, 0x600a, 0x1078, 0x3db8, 0x0040, 0x34c7,
+ 0x1078, 0x3e36, 0x1078, 0x45d6, 0x0078, 0x34af, 0xa186, 0x0028,
+ 0x00c0, 0x34c7, 0x6018, 0xa005, 0x0040, 0x3491, 0x8001, 0x0040,
+ 0x3491, 0x8001, 0x0040, 0x3491, 0x601e, 0x0078, 0x3491, 0x6820,
+ 0xd084, 0x0040, 0x2a0c, 0xc084, 0x6822, 0x1078, 0x2b13, 0x705c,
+ 0x0c7e, 0x2060, 0x6800, 0x6002, 0x0c7f, 0x6004, 0x6802, 0xa005,
+ 0x2d00, 0x00c0, 0x34c4, 0x6002, 0x6006, 0x0078, 0x2a0c, 0x017e,
+ 0x81ff, 0x00c0, 0x3511, 0x7000, 0xa086, 0x0030, 0x0040, 0x3511,
+ 0x71d4, 0xd1bc, 0x00c0, 0x3511, 0xd1b4, 0x00c0, 0x34f8, 0x7060,
+ 0xa005, 0x00c0, 0x3511, 0x70a4, 0xa086, 0x0001, 0x0040, 0x3511,
+ 0x7003, 0x0000, 0x047e, 0x057e, 0x077e, 0x067e, 0x0c7e, 0x0d7e,
+ 0x1078, 0x2a35, 0x0d7f, 0x0c7f, 0x067f, 0x077f, 0x057f, 0x047f,
+ 0x71d4, 0xd1b4, 0x00c0, 0x3511, 0x7003, 0x0040, 0x0078, 0x3511,
+ 0x1078, 0x43b0, 0x00c0, 0x3511, 0x781b, 0x005b, 0x0d7e, 0x70bc,
+ 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2,
+ 0x78da, 0xc1b4, 0x71d6, 0x7003, 0x0030, 0x7808, 0xc08d, 0x780a,
+ 0x0d7f, 0x1078, 0x3648, 0x017f, 0x81ff, 0x0040, 0x3563, 0xa684,
+ 0xdf00, 0x681e, 0x682b, 0x0000, 0x6f14, 0xa186, 0x0002, 0x00c0,
+ 0x3564, 0x6818, 0xa086, 0x0014, 0x00c0, 0x352d, 0x2008, 0xd6e4,
+ 0x0040, 0x352d, 0x7868, 0xa08c, 0x00ff, 0x1078, 0x2b01, 0x1078,
+ 0x2b22, 0x6820, 0xd0dc, 0x00c0, 0x3564, 0x8717, 0xa294, 0x000f,
+ 0x8213, 0x8213, 0x8213, 0xb284, 0x0300, 0x0040, 0x3543, 0xa290,
+ 0x53c0, 0x0078, 0x3545, 0xa290, 0x5440, 0xa290, 0x0000, 0x221c,
+ 0xd3c4, 0x00c0, 0x354d, 0x0078, 0x3553, 0x8210, 0x2204, 0xa085,
+ 0x0018, 0x2012, 0x8211, 0xd3d4, 0x0040, 0x355e, 0x68a0, 0xd0c4,
+ 0x00c0, 0x355e, 0x1078, 0x36c2, 0x0078, 0x2a0c, 0x6008, 0xc08d,
+ 0x600a, 0x0078, 0x3564, 0x692a, 0x6916, 0x6818, 0xd0fc, 0x0040,
+ 0x356b, 0x7048, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x6410, 0x84ff,
+ 0x0040, 0x3580, 0x2009, 0x4f02, 0x2104, 0x8001, 0x200a, 0x8421,
+ 0x6412, 0x00c0, 0x3580, 0x2021, 0x4f04, 0x2404, 0xc0a5, 0x2022,
+ 0x6018, 0xa005, 0x0040, 0x3588, 0x8001, 0x601a, 0x00c0, 0x358b,
+ 0x6008, 0xc0a4, 0x600a, 0x6820, 0xd084, 0x00c0, 0x3597, 0x6800,
+ 0xa005, 0x00c0, 0x3594, 0x6002, 0x6006, 0x0078, 0x359b, 0x705c,
+ 0x2060, 0x6800, 0x6002, 0x2061, 0x4f00, 0x6887, 0x0103, 0x2d08,
+ 0x206b, 0x0000, 0x6068, 0xa005, 0x616a, 0x0040, 0x35aa, 0x2d02,
+ 0x0078, 0x35ab, 0x616e, 0x7200, 0xa286, 0x0030, 0x0040, 0x35bb,
+ 0xa286, 0x0040, 0x00c0, 0x2a0c, 0x7003, 0x0002, 0x704c, 0x2068,
+ 0x68c4, 0x2060, 0x007c, 0x7003, 0x0002, 0x70bc, 0xa06d, 0x68bc,
+ 0x7042, 0x70b8, 0xa065, 0x68c0, 0x705a, 0x2d00, 0x704e, 0xad80,
+ 0x0009, 0x7046, 0x007c, 0xa282, 0x0004, 0x0048, 0x35d1, 0x1078,
+ 0x29b2, 0x2200, 0x0079, 0x35d4, 0x35d8, 0x35e9, 0x35f6, 0x35e9,
+ 0xa586, 0x1300, 0x0040, 0x35e9, 0xa586, 0x8300, 0x00c0, 0x35cf,
+ 0x7003, 0x0000, 0x6018, 0x8001, 0x601a, 0x6008, 0xa084, 0xfbef,
+ 0x600a, 0x7000, 0xa086, 0x0005, 0x0040, 0x35f3, 0x1078, 0x4118,
+ 0x781b, 0x0078, 0x007c, 0x781b, 0x0079, 0x007c, 0x7890, 0x8007,
+ 0x8001, 0xa084, 0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c,
+ 0x00ff, 0xa186, 0x0003, 0x0040, 0x360b, 0xa186, 0x0000, 0x0040,
+ 0x360b, 0x0078, 0x4107, 0x781b, 0x0079, 0x007c, 0x6820, 0xc095,
+ 0x6822, 0x82ff, 0x00c0, 0x3618, 0x1078, 0x4118, 0x0078, 0x361f,
+ 0x8211, 0x0040, 0x361d, 0x1078, 0x29b2, 0x1078, 0x412b, 0x781b,
+ 0x0078, 0x007c, 0x1078, 0x43d3, 0x7830, 0xa084, 0x00c0, 0x00c0,
+ 0x3645, 0x017e, 0x3208, 0x007e, 0x2001, 0x4f04, 0x2004, 0xd0ec,
+ 0x007f, 0x0040, 0x3637, 0xa18c, 0x0300, 0x0078, 0x3639, 0xa18c,
+ 0x0400, 0x017f, 0x0040, 0x3640, 0x0018, 0x3645, 0x0078, 0x3642,
+ 0x0028, 0x3645, 0x791a, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c,
+ 0xa684, 0x0060, 0x00c0, 0x3652, 0x682f, 0x0000, 0x6833, 0x0000,
+ 0x0078, 0x36c1, 0xd6dc, 0x00c0, 0x366a, 0x68b4, 0xd0dc, 0x00c0,
+ 0x366a, 0x6998, 0x6a94, 0x692e, 0x6a32, 0x7048, 0xa005, 0x00c0,
+ 0x3667, 0x2200, 0xa105, 0x0040, 0x45d6, 0x704b, 0x0015, 0x0078,
+ 0x45d6, 0x007c, 0xd6ac, 0x0040, 0x3690, 0xd6f4, 0x0040, 0x3676,
+ 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x45d6, 0x68b4, 0xa084,
+ 0x4000, 0xa635, 0xd6f4, 0x00c0, 0x3670, 0x7048, 0xa005, 0x00c0,
+ 0x3683, 0x704b, 0x0015, 0xd6dc, 0x00c0, 0x368c, 0x68b4, 0xd0dc,
+ 0x0040, 0x368c, 0x6ca8, 0x6da4, 0x6c2e, 0x6d32, 0x0078, 0x45d6,
+ 0xd6f4, 0x0040, 0x3699, 0x682f, 0x0000, 0x6833, 0x0000, 0x0078,
+ 0x45d6, 0x68b4, 0xa084, 0x4800, 0xa635, 0xd6f4, 0x00c0, 0x3693,
+ 0x7048, 0xa005, 0x00c0, 0x36a6, 0x704b, 0x0015, 0x2408, 0x2510,
+ 0x2700, 0x80fb, 0x00c8, 0x36ad, 0x8000, 0xa084, 0x003f, 0xa108,
+ 0xa291, 0x0000, 0x692e, 0x6a32, 0x2100, 0xa205, 0x00c0, 0x36ba,
+ 0x0078, 0x45d6, 0x7000, 0xa086, 0x0006, 0x0040, 0x36c1, 0x0078,
+ 0x45d6, 0x007c, 0x6946, 0x6008, 0xc0cd, 0xd3cc, 0x0040, 0x36c9,
+ 0xc08d, 0x600a, 0x6818, 0x683a, 0x681b, 0x0006, 0x688f, 0x0000,
+ 0x6893, 0x0000, 0x6a30, 0x692c, 0x6a3e, 0x6942, 0x682f, 0x0003,
+ 0x6833, 0x0000, 0x6837, 0x0020, 0x6897, 0x0000, 0x689b, 0x0020,
+ 0x7000, 0x0079, 0x36e3, 0x2a0c, 0x36f5, 0x36ed, 0x36eb, 0x36eb,
+ 0x36eb, 0x36eb, 0x36eb, 0x1078, 0x29b2, 0x6820, 0xd084, 0x00c0,
+ 0x36f5, 0x1078, 0x3e19, 0x0078, 0x36fb, 0x705c, 0x2c50, 0x2060,
+ 0x6800, 0x6002, 0x2a60, 0x3208, 0xa18c, 0x0300, 0x0040, 0x3704,
+ 0x2021, 0x4f58, 0x0078, 0x3706, 0x2021, 0x4f98, 0x2404, 0xa005,
+ 0x0040, 0x370d, 0x2020, 0x0078, 0x3706, 0x2d22, 0x206b, 0x0000,
+ 0x007c, 0x1078, 0x3e20, 0x1078, 0x3e36, 0x6008, 0xc0cc, 0x600a,
+ 0x682b, 0x0000, 0x789b, 0x000e, 0x6f14, 0x6938, 0x691a, 0x6944,
+ 0x6916, 0x3208, 0xa18c, 0x0300, 0x0040, 0x372a, 0x2009, 0x0000,
+ 0x0078, 0x372c, 0x2009, 0x0001, 0x1078, 0x4a81, 0xd6dc, 0x0040,
+ 0x3734, 0x691c, 0xc1ed, 0x691e, 0x6818, 0xd0fc, 0x0040, 0x3743,
+ 0x7868, 0xa08c, 0x00ff, 0x0040, 0x3741, 0x681b, 0x001e, 0x0078,
+ 0x3743, 0x681b, 0x0000, 0xb284, 0x0300, 0x00c0, 0x374b, 0x2021,
+ 0x4f98, 0x0078, 0x374d, 0x2021, 0x4f58, 0x6800, 0x2022, 0x6a3c,
+ 0x6940, 0x6a32, 0x692e, 0x68c0, 0x2060, 0x6000, 0xd0a4, 0x0040,
+ 0x378d, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x0d7e,
+ 0x0f7e, 0x157e, 0x147e, 0x2079, 0x4f00, 0x1078, 0x1e46, 0x147f,
+ 0x157f, 0x0f7f, 0x70cc, 0x2010, 0x2009, 0x0101, 0x027e, 0x2204,
+ 0xa06d, 0x0040, 0x377d, 0x6814, 0xa706, 0x0040, 0x377a, 0x6800,
+ 0x0078, 0x3770, 0x6820, 0xc0d5, 0x6822, 0x027f, 0x8210, 0x8109,
+ 0x00c0, 0x376e, 0x0d7f, 0x7067, 0x0003, 0x707f, 0x0000, 0x7776,
+ 0x7083, 0x000f, 0x71d4, 0xc1dc, 0x71d6, 0x6818, 0xa086, 0x0002,
+ 0x00c0, 0x3799, 0x6817, 0x0000, 0x682b, 0x0000, 0x681c, 0xc0ec,
+ 0x681e, 0x1078, 0x2073, 0x0078, 0x2a0c, 0x7cd8, 0x7ddc, 0x7fd0,
+ 0x1078, 0x3648, 0x682b, 0x0000, 0x789b, 0x000e, 0x6f14, 0x1078,
+ 0x43d7, 0xa08c, 0x00ff, 0x6916, 0x6818, 0xd0fc, 0x0040, 0x37b2,
+ 0x7048, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x7067, 0x0000, 0x0078,
+ 0x2a0c, 0x7000, 0xa005, 0x00c0, 0x37bf, 0x0078, 0x2a0c, 0xa006,
+ 0x1078, 0x45d6, 0x6920, 0xd1ac, 0x00c0, 0x37c8, 0x681b, 0x0014,
+ 0xa68c, 0xdf00, 0x691e, 0x682b, 0x0000, 0x6820, 0xa084, 0x00ff,
+ 0x6822, 0x7000, 0x0079, 0x37d4, 0x2a0c, 0x37de, 0x37de, 0x37e1,
+ 0x37e1, 0x37e1, 0x37dc, 0x37dc, 0x1078, 0x29b2, 0x6818, 0x0078,
+ 0x3443, 0x6008, 0xc0a4, 0x600a, 0x6817, 0x0000, 0x0078, 0x3dde,
+ 0x2300, 0x0079, 0x37eb, 0x37ee, 0x37f0, 0x3860, 0x1078, 0x29b2,
+ 0xd6fc, 0x00c0, 0x3847, 0x7000, 0xa00d, 0x0079, 0x37f7, 0x2a0c,
+ 0x3801, 0x3801, 0x3831, 0x3801, 0x3844, 0x37ff, 0x37ff, 0x1078,
+ 0x29b2, 0xa684, 0x0060, 0x0040, 0x3831, 0xa086, 0x0060, 0x00c0,
+ 0x382e, 0xc6ac, 0xc6f4, 0xc6ed, 0x7e5a, 0x6eb6, 0x681c, 0xc0ac,
+ 0x681e, 0xa186, 0x0002, 0x0040, 0x3820, 0x1078, 0x45d6, 0x69ac,
+ 0x68b0, 0xa115, 0x0040, 0x3820, 0x1078, 0x4977, 0x0078, 0x3822,
+ 0x1078, 0x493f, 0x781b, 0x0079, 0x71d4, 0xd1b4, 0x00c0, 0x2a08,
+ 0x70a4, 0xa086, 0x0001, 0x00c0, 0x2a52, 0x007c, 0xd6ec, 0x0040,
+ 0x380b, 0x6818, 0xd0fc, 0x0040, 0x3844, 0xd6f4, 0x00c0, 0x383e,
+ 0x681b, 0x0015, 0x781b, 0x0079, 0x0078, 0x2a08, 0x681b, 0x0007,
+ 0x682f, 0x0000, 0x6833, 0x0000, 0x1078, 0x4369, 0x007c, 0xc6fc,
+ 0x7e5a, 0x7adc, 0x79d8, 0x78d0, 0x801b, 0x00c8, 0x3850, 0x8000,
+ 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302,
+ 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x781b, 0x0079, 0x007c,
+ 0x1078, 0x29b2, 0x2300, 0x0079, 0x3865, 0x386a, 0x388f, 0x38ef,
+ 0x1078, 0x29b2, 0x7000, 0x0079, 0x386d, 0x3875, 0x3877, 0x3880,
+ 0x3875, 0x3875, 0x3875, 0x3875, 0x3875, 0x1078, 0x29b2, 0x69ac,
+ 0x68b0, 0xa115, 0x0040, 0x3880, 0x1078, 0x4977, 0x0078, 0x3882,
+ 0x1078, 0x493f, 0x681c, 0xc0b4, 0x681e, 0x70d4, 0xd0b4, 0x00c0,
+ 0x2a08, 0x70a4, 0xa086, 0x0001, 0x00c0, 0x2a52, 0x007c, 0xd6fc,
+ 0x00c0, 0x38df, 0x7000, 0xa00d, 0x0079, 0x3896, 0x2a0c, 0x38a6,
+ 0x38a0, 0x38d6, 0x38a6, 0x38dc, 0x389e, 0x389e, 0x1078, 0x29b2,
+ 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0xa684, 0x0060,
+ 0x0040, 0x38d6, 0xa086, 0x0060, 0x00c0, 0x38d3, 0xa6b4, 0xbfbf,
+ 0xc6ed, 0x7e5a, 0x6eb6, 0xa186, 0x0002, 0x0040, 0x38c2, 0x1078,
+ 0x45d6, 0x69ac, 0x68b0, 0xa115, 0x0040, 0x38c2, 0x1078, 0x4977,
+ 0x0078, 0x38c4, 0x1078, 0x493f, 0x781b, 0x0079, 0x681c, 0xc0b4,
+ 0x681e, 0x71d4, 0xd1b4, 0x00c0, 0x2a08, 0x70a4, 0xa086, 0x0001,
+ 0x00c0, 0x2a52, 0x007c, 0xd6ec, 0x0040, 0x38b0, 0x6818, 0xd0fc,
+ 0x0040, 0x38dc, 0x681b, 0x0007, 0x781b, 0x00f9, 0x007c, 0xc6fc,
+ 0x7e5a, 0x7adc, 0x79d8, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94,
+ 0x2200, 0xa303, 0x68ae, 0x79d2, 0x781b, 0x0079, 0x007c, 0xd6dc,
+ 0x0040, 0x38f8, 0x782b, 0x3009, 0x781b, 0x0079, 0x0078, 0x2a08,
+ 0x7884, 0xc0ac, 0x7886, 0x78e4, 0xa084, 0x0008, 0x00c0, 0x390b,
+ 0xa484, 0x0200, 0x0040, 0x3905, 0xc6f5, 0xc6dd, 0x7e5a, 0x781b,
+ 0x0079, 0x0078, 0x2a08, 0x6820, 0xc095, 0x6822, 0x1078, 0x42e2,
+ 0xc6dd, 0x1078, 0x4118, 0x781b, 0x0078, 0x0078, 0x2a08, 0x2300,
+ 0x0079, 0x391a, 0x391d, 0x391f, 0x3921, 0x1078, 0x29b2, 0x0078,
+ 0x4111, 0xd6d4, 0x00c0, 0x395c, 0x79e4, 0xd1ac, 0x0040, 0x392f,
+ 0x78ec, 0xa084, 0x0003, 0x0040, 0x392f, 0x782b, 0x3009, 0x789b,
+ 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb, 0x785a, 0x79e4, 0xd1ac,
+ 0x0040, 0x393f, 0x78ec, 0xa084, 0x0003, 0x00c0, 0x3958, 0x2001,
+ 0x4f04, 0x2004, 0xd0e4, 0x00c0, 0x3954, 0x6820, 0xd0c4, 0x0040,
+ 0x3954, 0x0c7e, 0x7058, 0x2060, 0x6004, 0xc09d, 0x6006, 0x6008,
+ 0xa084, 0x00ff, 0x600a, 0x0c7f, 0x2001, 0x0014, 0x0078, 0x3443,
+ 0xa184, 0x0007, 0x0079, 0x3992, 0x7a90, 0xa294, 0x0007, 0x789b,
+ 0x0060, 0x79a8, 0x81ff, 0x0040, 0x3990, 0x789b, 0x0010, 0x7ba8,
+ 0xa384, 0x0001, 0x00c0, 0x3983, 0x7ba8, 0x7ba8, 0xa386, 0x0001,
+ 0x00c0, 0x3976, 0x2009, 0xfff7, 0x0078, 0x397c, 0xa386, 0x0003,
+ 0x00c0, 0x3983, 0x2009, 0xffef, 0x0c7e, 0x7058, 0x2060, 0x6004,
+ 0xa104, 0x6006, 0x0c7f, 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684,
+ 0xfffb, 0x785a, 0x782b, 0x3009, 0x6920, 0xa18c, 0xfcff, 0x6922,
+ 0x0078, 0x435d, 0x30d9, 0x30e3, 0x399c, 0x39a2, 0x399a, 0x399a,
+ 0x435d, 0x435d, 0x1078, 0x29b2, 0x6920, 0xa18c, 0xfcff, 0x6922,
+ 0x0078, 0x4363, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0078, 0x435d,
+ 0x79e4, 0xa184, 0x0030, 0x0040, 0x39b2, 0x78ec, 0xa084, 0x0003,
+ 0x00c0, 0x39e6, 0x7000, 0xa086, 0x0004, 0x00c0, 0x39cc, 0x7064,
+ 0xa086, 0x0002, 0x00c0, 0x39c2, 0x2011, 0x0002, 0x2019, 0x0000,
+ 0x0078, 0x2f65, 0x7064, 0xa086, 0x0006, 0x0040, 0x39bc, 0x7064,
+ 0xa086, 0x0004, 0x0040, 0x39bc, 0x7000, 0xa086, 0x0000, 0x0040,
+ 0x2a08, 0x6920, 0xa184, 0x0420, 0x0040, 0x39db, 0xc1d4, 0x6922,
+ 0x6818, 0x0078, 0x3443, 0x6818, 0xa08e, 0x0002, 0x0040, 0x39e4,
+ 0xc0fd, 0x681a, 0x2001, 0x0014, 0x0078, 0x3443, 0xa184, 0x0007,
+ 0x0079, 0x39ea, 0x435d, 0x435d, 0x39f2, 0x435d, 0x43a5, 0x43a5,
+ 0x435d, 0x435d, 0xd6bc, 0x0040, 0x3a34, 0x7184, 0x81ff, 0x0040,
+ 0x3a34, 0xa182, 0x000d, 0x00d0, 0x3a01, 0x7087, 0x0000, 0x0078,
+ 0x3a06, 0xa182, 0x000c, 0x7086, 0x2009, 0x000c, 0x789b, 0x0061,
+ 0x79aa, 0x157e, 0x137e, 0x147e, 0x7088, 0x8114, 0xa210, 0x728a,
+ 0xa080, 0x000b, 0xad00, 0x2098, 0xb284, 0x0300, 0x0040, 0x3a28,
+ 0x007e, 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x3a24,
+ 0x20a1, 0x012b, 0x0078, 0x3a2a, 0x20a1, 0x022b, 0x0078, 0x3a2a,
+ 0x20a1, 0x012b, 0x789b, 0x0000, 0x8108, 0x81ac, 0x53a6, 0x147f,
+ 0x137f, 0x157f, 0x0078, 0x4363, 0xd6d4, 0x00c0, 0x3a88, 0x6820,
+ 0xd084, 0x0040, 0x4363, 0xa68c, 0x0060, 0xa684, 0x0060, 0x0040,
+ 0x3a46, 0xa086, 0x0060, 0x00c0, 0x3a46, 0xc1f5, 0xc194, 0x795a,
+ 0x69b6, 0x789b, 0x0060, 0x78ab, 0x0000, 0x789b, 0x0061, 0x6818,
+ 0xc0fd, 0x681a, 0x78aa, 0x8008, 0x810c, 0x0040, 0x3e4f, 0xa18c,
+ 0x00f8, 0x00c0, 0x3e4f, 0x157e, 0x137e, 0x147e, 0x017e, 0x3208,
+ 0xa18c, 0x0300, 0x0040, 0x3a74, 0x007e, 0x2001, 0x4f04, 0x2004,
+ 0xd0ec, 0x007f, 0x0040, 0x3a70, 0x20a1, 0x012b, 0x0078, 0x3a76,
+ 0x20a1, 0x022b, 0x0078, 0x3a76, 0x20a1, 0x012b, 0x017f, 0x789b,
+ 0x0000, 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f,
+ 0x137f, 0x157f, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x0078, 0x4363,
+ 0x6818, 0xd0fc, 0x0040, 0x3a8e, 0x681b, 0x0008, 0x6820, 0xc0ad,
+ 0x6822, 0x1078, 0x4120, 0x781b, 0x00ea, 0x007c, 0x2300, 0x0079,
+ 0x3a99, 0x3a9e, 0x3b76, 0x3a9c, 0x1078, 0x29b2, 0x7cd8, 0x7ddc,
+ 0x7fd0, 0x82ff, 0x00c0, 0x3ac7, 0x7200, 0xa286, 0x0003, 0x0040,
+ 0x3410, 0x71d4, 0xd1bc, 0x00c0, 0x3aca, 0xd1b4, 0x0040, 0x3aca,
+ 0x0d7e, 0x783b, 0x8800, 0x781b, 0x004c, 0x70bc, 0xa06d, 0x68b4,
+ 0xc0a5, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da,
+ 0xc1b4, 0x71d6, 0x7003, 0x0030, 0x0d7f, 0x0078, 0x3ace, 0x7200,
+ 0x0078, 0x3ace, 0x783b, 0x1800, 0x781b, 0x004a, 0xa284, 0x000f,
+ 0x0079, 0x3ad2, 0x3b61, 0x3b10, 0x3adc, 0x343f, 0x3ada, 0x3b61,
+ 0x3ada, 0x3ada, 0x1078, 0x29b2, 0x681c, 0xd0ec, 0x0040, 0x3ae3,
+ 0x6008, 0xc08d, 0x600a, 0x6920, 0xc185, 0x6922, 0x6800, 0x6006,
+ 0xa005, 0x00c0, 0x3aec, 0x6002, 0x6008, 0xc0d4, 0x600a, 0x681c,
+ 0xa084, 0x000e, 0x00c0, 0x3b00, 0xb284, 0x0300, 0x0040, 0x3afc,
+ 0x2009, 0x95c0, 0x0078, 0x3b05, 0x2009, 0x96d0, 0x0078, 0x3b05,
+ 0x7030, 0x68ba, 0x7140, 0x70cc, 0xa108, 0x2104, 0x6802, 0x2d0a,
+ 0x715e, 0xd6dc, 0x00c0, 0x3b10, 0xc6fc, 0x6eb6, 0x0078, 0x3b61,
+ 0x6eb6, 0xa684, 0x0060, 0x00c0, 0x3b1a, 0xa684, 0x7fff, 0x68b6,
+ 0x0078, 0x3b61, 0xd6dc, 0x00c0, 0x3b28, 0xa684, 0x7fff, 0x68b6,
+ 0x6894, 0x68a6, 0x6898, 0x68aa, 0x1078, 0x45d6, 0x0078, 0x3b61,
+ 0xd6ac, 0x0040, 0x3b34, 0xa006, 0x1078, 0x45d6, 0x2408, 0x2510,
+ 0x69aa, 0x6aa6, 0x0078, 0x3b44, 0x2408, 0x2510, 0x2700, 0x801b,
+ 0x00c8, 0x3b3b, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000,
+ 0x69aa, 0x6aa6, 0x1078, 0x45d6, 0xd6fc, 0x0040, 0x3b61, 0xa684,
+ 0x7fff, 0x68b6, 0x2510, 0x2408, 0xd6ac, 0x00c0, 0x3b59, 0x2700,
+ 0x801b, 0x00c8, 0x3b54, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291,
+ 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303,
+ 0x68ae, 0x7000, 0xa086, 0x0030, 0x00c0, 0x2a0c, 0x7003, 0x0002,
+ 0x70bc, 0xa06d, 0x68bc, 0x7042, 0x70b8, 0xa065, 0x68c0, 0x705a,
+ 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x007c, 0xa586, 0x8800,
+ 0x00c0, 0x3b83, 0x7003, 0x0000, 0x6018, 0x8001, 0x601a, 0x6008,
+ 0xa084, 0xfbef, 0x600a, 0x0078, 0x4111, 0x7047, 0x0000, 0xa282,
+ 0x0006, 0x0050, 0x3b8d, 0x1078, 0x29b2, 0x2300, 0x0079, 0x3b90,
+ 0x3b93, 0x3ba5, 0x3bb1, 0x2200, 0x0079, 0x3b96, 0x3b9c, 0x4111,
+ 0x3b9e, 0x3b9c, 0x3beb, 0x3c40, 0x1078, 0x29b2, 0x7a80, 0xa294,
+ 0x0f00, 0x1078, 0x3cca, 0x0078, 0x4107, 0x1078, 0x3bc2, 0x0079,
+ 0x3ba9, 0x4111, 0x3baf, 0x3baf, 0x3beb, 0x3baf, 0x4111, 0x1078,
+ 0x29b2, 0x1078, 0x3bc2, 0x0079, 0x3bb5, 0x3bbd, 0x3bbb, 0x3bbb,
+ 0x3bbd, 0x3bbb, 0x3bbd, 0x1078, 0x29b2, 0x1078, 0x412b, 0x781b,
+ 0x0078, 0x007c, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3bd3, 0x1078,
+ 0x3e36, 0x0078, 0x3bcd, 0x1078, 0x45d6, 0x6008, 0xa084, 0xfbef,
+ 0x600a, 0x0078, 0x3bd8, 0x7000, 0xa086, 0x0003, 0x0040, 0x3bcb,
+ 0x7003, 0x0005, 0xb284, 0x0300, 0x0040, 0x3be2, 0x2001, 0x96e0,
+ 0x0078, 0x3be4, 0x2001, 0x9712, 0x2068, 0x704e, 0xad80, 0x0009,
+ 0x7046, 0x2200, 0x007c, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3bfd,
+ 0x70d4, 0xc0b5, 0x70d6, 0x2c00, 0x70ba, 0x2d00, 0x70be, 0x0078,
+ 0x3c02, 0x1078, 0x45d6, 0x0078, 0x3c02, 0x7000, 0xa086, 0x0003,
+ 0x0040, 0x3bf9, 0x7003, 0x0001, 0x7a80, 0xa294, 0x0f00, 0x789b,
+ 0x0018, 0x7ca8, 0xa484, 0x001f, 0xa215, 0x2069, 0x95c0, 0xb284,
+ 0x0300, 0x00c0, 0x3c16, 0xc2fd, 0x2069, 0x96d0, 0x2d04, 0x2d08,
+ 0x715e, 0xa06d, 0x0040, 0x3c23, 0x6814, 0xa206, 0x0040, 0x3c25,
+ 0x6800, 0x0078, 0x3c17, 0x1078, 0x3cca, 0x6eb4, 0x7e5a, 0x6920,
+ 0xa184, 0x0c00, 0x0040, 0x3cf4, 0x7064, 0xa086, 0x0006, 0x00c0,
+ 0x3c37, 0x7074, 0xa206, 0x00c0, 0x3c37, 0x7066, 0x707e, 0x681b,
+ 0x0005, 0xc1ad, 0xc1d4, 0x6922, 0x1078, 0x4120, 0x0078, 0x3cf4,
+ 0x7200, 0xa286, 0x0002, 0x00c0, 0x3c52, 0x70d4, 0xc0b5, 0x70d6,
+ 0x2c00, 0x70ba, 0x2d00, 0x70be, 0x0078, 0x3c56, 0x1078, 0x45d6,
+ 0x0078, 0x3c56, 0xa286, 0x0003, 0x0040, 0x3c4e, 0x7003, 0x0001,
+ 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, 0x001f,
+ 0xa215, 0xb284, 0x0300, 0x00c0, 0x3c66, 0xc2fd, 0x79a8, 0x79a8,
+ 0xa18c, 0x00ff, 0x2118, 0x70cc, 0xa168, 0x2d04, 0x2d08, 0x715e,
+ 0xa06d, 0x0040, 0x3c7a, 0x6814, 0xa206, 0x0040, 0x3ca3, 0x6800,
+ 0x0078, 0x3c6e, 0x7003, 0x0005, 0xb284, 0x0300, 0x0040, 0x3c84,
+ 0x2001, 0x96e0, 0x0078, 0x3c86, 0x2001, 0x9712, 0x2068, 0x704e,
+ 0x157e, 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, 0x00f0, 0x3c8b,
+ 0x157f, 0xb284, 0x0300, 0x0040, 0x3c98, 0xc2fc, 0x0078, 0x3c99,
+ 0xc2fd, 0x6a16, 0xad80, 0x0009, 0x7046, 0x68b7, 0x0700, 0x6823,
+ 0x0800, 0x6827, 0x0003, 0x6eb4, 0x6920, 0xa184, 0x0c00, 0x0040,
+ 0x3cf4, 0xd0dc, 0x0040, 0x3cbf, 0x7064, 0xa086, 0x0004, 0x00c0,
+ 0x3cbb, 0x7074, 0xa206, 0x00c0, 0x3cbb, 0x7078, 0xa306, 0x00c0,
+ 0x3cbb, 0x7066, 0x707e, 0x1078, 0x4127, 0x0078, 0x3cf4, 0x681b,
+ 0x0005, 0xc1ad, 0xc1d4, 0x6922, 0x1078, 0x4120, 0x707f, 0x0000,
+ 0x0078, 0x3cf4, 0x7003, 0x0005, 0xb284, 0x0300, 0x0040, 0x3cd4,
+ 0x2001, 0x96e0, 0x0078, 0x3cd6, 0x2001, 0x9712, 0x2068, 0x704e,
+ 0x157e, 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, 0x00f0, 0x3cdb,
+ 0x157f, 0xb284, 0x0300, 0x0040, 0x3ce8, 0xc2fc, 0x0078, 0x3ce9,
+ 0xc2fd, 0x6a16, 0xad80, 0x0009, 0x7046, 0x68b7, 0x0700, 0x6823,
+ 0x0800, 0x6827, 0x0003, 0x007c, 0xc6ec, 0xa6ac, 0x0060, 0x0040,
+ 0x3d46, 0x6b98, 0x6c94, 0x69ac, 0x68b0, 0xa105, 0x00c0, 0x3d21,
+ 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0xa586, 0x0060, 0x0040, 0x3d4b,
+ 0xd6f4, 0x00c0, 0x3d0c, 0xc6ed, 0xa6b4, 0xb7ff, 0x7e5a, 0x2009,
+ 0x0079, 0xd69c, 0x0040, 0x3d19, 0x2009, 0x0078, 0x2019, 0x0000,
+ 0x2320, 0x791a, 0xd6ec, 0x0040, 0x3d56, 0x1078, 0x493f, 0x0078,
+ 0x3d56, 0x68b0, 0xa31a, 0x2100, 0xa423, 0x2400, 0xa305, 0x0040,
+ 0x3d4d, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0x68b0, 0xd6f4, 0x00c0,
+ 0x3d32, 0xc6ed, 0xc6f4, 0x7e5a, 0x2011, 0x0079, 0xd69c, 0x0040,
+ 0x3d3e, 0x2011, 0x0078, 0x2019, 0x0000, 0x2320, 0x7a1a, 0xd6ec,
+ 0x0040, 0x3d56, 0x1078, 0x4977, 0x0078, 0x3d56, 0x2019, 0x0000,
+ 0x2320, 0x0078, 0x3d4d, 0xa6b4, 0xb7ff, 0x7e5a, 0x2009, 0x0079,
+ 0xd69c, 0x0040, 0x3d55, 0x2009, 0x0078, 0x791a, 0x68c0, 0x705a,
+ 0x2d00, 0x704e, 0x68c4, 0x2060, 0x71d4, 0x2001, 0x4f01, 0x2004,
+ 0xd0c4, 0x00c0, 0x3dab, 0x70d8, 0xa02d, 0x0040, 0x3d84, 0xd1bc,
+ 0x0040, 0x3d9e, 0x7a80, 0xa294, 0x0f00, 0x70dc, 0xa206, 0x0040,
+ 0x3d75, 0x78e0, 0xa504, 0x00c0, 0x3dab, 0x70da, 0xc1bc, 0x71d6,
+ 0x0078, 0x3dab, 0x2031, 0x0001, 0x852c, 0x0048, 0x3d83, 0x8633,
+ 0x8210, 0x0078, 0x3d7c, 0x007c, 0x7de0, 0xa594, 0xff00, 0x0040,
+ 0x3d91, 0x2011, 0x0008, 0x852f, 0x1078, 0x3d7a, 0x8637, 0x0078,
+ 0x3d93, 0x1078, 0x3d7a, 0x8217, 0x7880, 0xa084, 0x0f00, 0xa206,
+ 0x0040, 0x3dab, 0x72de, 0x76da, 0x0078, 0x3dab, 0x7a80, 0xa294,
+ 0x0f00, 0x70dc, 0xa236, 0x0040, 0x3d9b, 0x78e0, 0xa534, 0x0040,
+ 0x3d9b, 0xc1bd, 0x71d6, 0xd1b4, 0x00c0, 0x2a08, 0x2300, 0xa405,
+ 0x0040, 0x2a08, 0x70a4, 0xa086, 0x0001, 0x00c0, 0x2a52, 0x007c,
+ 0x6020, 0xa005, 0x0040, 0x3dc6, 0x8001, 0x6022, 0x6008, 0xa085,
+ 0x0008, 0x600a, 0x700f, 0x0100, 0x702c, 0x6026, 0x007c, 0xa006,
+ 0x1078, 0x45d6, 0x7000, 0xa086, 0x0002, 0x0040, 0x3dd4, 0x7064,
+ 0xa086, 0x0005, 0x00c0, 0x3dde, 0x682b, 0x0000, 0x6817, 0x0000,
+ 0x681b, 0x0001, 0x6823, 0x0040, 0x681f, 0x0100, 0x7000, 0xa084,
+ 0x000f, 0x0079, 0x3de3, 0x2a0c, 0x3df3, 0x3ded, 0x3e15, 0x3dfd,
+ 0x2a0c, 0x3deb, 0x3deb, 0x1078, 0x29b2, 0x1078, 0x3e20, 0x1078,
+ 0x3e19, 0x0078, 0x3df9, 0x1078, 0x3e20, 0x705c, 0x2060, 0x6800,
+ 0x6002, 0x1078, 0x2073, 0x0078, 0x2a0c, 0x7064, 0x7067, 0x0000,
+ 0x7083, 0x0000, 0x0079, 0x3e04, 0x3e11, 0x3e11, 0x3e0c, 0x3e0c,
+ 0x3e0c, 0x3e11, 0x3e0c, 0x3e11, 0x77d4, 0xc7dd, 0x77d6, 0x0079,
+ 0x2f7e, 0x7067, 0x0000, 0x0078, 0x2a0c, 0x681b, 0x0000, 0x0078,
+ 0x3711, 0x6800, 0xa005, 0x00c0, 0x3e1e, 0x6002, 0x6006, 0x007c,
+ 0x6410, 0x84ff, 0x0040, 0x3e32, 0x2009, 0x4f02, 0x2104, 0x8001,
+ 0x200a, 0x8421, 0x6412, 0x00c0, 0x3e32, 0x2021, 0x4f04, 0x2404,
+ 0xc0a5, 0x2022, 0x6008, 0xc0a4, 0x600a, 0x007c, 0x6018, 0xa005,
+ 0x0040, 0x3e3c, 0x8001, 0x601a, 0x007c, 0x1078, 0x43d3, 0x681b,
+ 0x0018, 0x0078, 0x3e7d, 0x1078, 0x43d3, 0x681b, 0x0019, 0x0078,
+ 0x3e7d, 0x1078, 0x43d3, 0x681b, 0x001a, 0x0078, 0x3e7d, 0x1078,
+ 0x43d3, 0x681b, 0x0003, 0x0078, 0x3e7d, 0x7774, 0x1078, 0x424e,
+ 0x7178, 0xa18c, 0x00ff, 0x3210, 0xa294, 0x0300, 0x0040, 0x3e64,
+ 0xa1e8, 0x94c0, 0x0078, 0x3e66, 0xa1e8, 0x95d0, 0x2d04, 0x2d08,
+ 0x2068, 0xa005, 0x00c0, 0x3e6f, 0x707e, 0x0078, 0x2a0c, 0x6814,
+ 0x7274, 0xa206, 0x0040, 0x3e77, 0x6800, 0x0078, 0x3e67, 0x6800,
+ 0x200a, 0x681b, 0x0005, 0x707f, 0x0000, 0x1078, 0x3e20, 0x6820,
+ 0xd084, 0x00c0, 0x3e85, 0x1078, 0x3e19, 0x1078, 0x3e36, 0x681f,
+ 0x0000, 0x6823, 0x0020, 0x1078, 0x2073, 0x0078, 0x2a0c, 0xa282,
+ 0x0003, 0x00c0, 0x4107, 0x7da8, 0xa5ac, 0x00ff, 0x7e5a, 0x7ea8,
+ 0xa6b4, 0x00ff, 0x6920, 0xc1bd, 0x6922, 0xd1c4, 0x0040, 0x3eea,
+ 0xc1c4, 0x6922, 0xa6b4, 0x00ff, 0x0040, 0x3ed7, 0xa682, 0x000c,
+ 0x0048, 0x3eae, 0x0040, 0x3eae, 0x2031, 0x000c, 0x2500, 0xa086,
+ 0x000a, 0x0040, 0x3eb5, 0x852b, 0x852b, 0x1078, 0x41e0, 0x0040,
+ 0x3ebd, 0x1078, 0x3fbc, 0x0078, 0x3ee0, 0x1078, 0x419b, 0x0c7e,
+ 0x2960, 0x6004, 0xa084, 0xfff5, 0x6006, 0x1078, 0x3ff2, 0x0c7f,
+ 0x6920, 0xc1c5, 0x6922, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x00c0,
+ 0x3ed4, 0x781b, 0x0064, 0x007c, 0x781b, 0x0078, 0x007c, 0x0c7e,
+ 0x2960, 0x6004, 0xa084, 0xfff5, 0x6006, 0x1078, 0x3ff2, 0x0c7f,
+ 0x7e58, 0xd6d4, 0x00c0, 0x3ee7, 0x781b, 0x0067, 0x007c, 0x781b,
+ 0x0079, 0x007c, 0x0c7e, 0x7058, 0x2060, 0x6100, 0xd1e4, 0x0040,
+ 0x3f33, 0x6208, 0x8217, 0xa294, 0x00ff, 0xa282, 0x000c, 0x0048,
+ 0x3efd, 0x0040, 0x3efd, 0x2011, 0x000c, 0x2600, 0xa202, 0x00c8,
+ 0x3f02, 0x2230, 0x6208, 0xa294, 0x00ff, 0x2001, 0x4f05, 0x2004,
+ 0xd0e4, 0x00c0, 0x3f17, 0x78ec, 0xd0e4, 0x0040, 0x3f17, 0xa282,
+ 0x000a, 0x00c8, 0x3f1d, 0x2011, 0x000a, 0x0078, 0x3f1d, 0xa282,
+ 0x000c, 0x00c8, 0x3f1d, 0x2011, 0x000c, 0x2200, 0xa502, 0x00c8,
+ 0x3f22, 0x2228, 0x1078, 0x419f, 0x2500, 0xa086, 0x000a, 0x0040,
+ 0x3f2b, 0x852b, 0x852b, 0x1078, 0x41e0, 0x0040, 0x3f33, 0x1078,
+ 0x3fbc, 0x0078, 0x3f37, 0x1078, 0x419b, 0x1078, 0x3ff2, 0x7858,
+ 0xc095, 0x785a, 0x0c7f, 0x781b, 0x0078, 0x007c, 0x0c7e, 0x2960,
+ 0x6000, 0xd0e4, 0x00c0, 0x3f58, 0xd0b4, 0x00c0, 0x3f52, 0x6010,
+ 0xa084, 0x000f, 0x00c0, 0x3f52, 0x6104, 0xa18c, 0xfff5, 0x6106,
+ 0x0c7f, 0x007c, 0x2011, 0x0032, 0x2019, 0x0000, 0x0078, 0x3f83,
+ 0x68a0, 0xd0cc, 0x00c0, 0x3f52, 0x6208, 0xa294, 0x00ff, 0x2001,
+ 0x4f05, 0x2004, 0xd0e4, 0x00c0, 0x3f71, 0x78ec, 0xd0e4, 0x0040,
+ 0x3f71, 0xa282, 0x000b, 0x00c8, 0x3f71, 0x2011, 0x000a, 0x0078,
+ 0x3f77, 0xa282, 0x000c, 0x00c8, 0x3f77, 0x2011, 0x000c, 0x6308,
+ 0x831f, 0xa39c, 0x00ff, 0xa382, 0x000c, 0x0048, 0x3f83, 0x0040,
+ 0x3f83, 0x2019, 0x000c, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab,
+ 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820, 0xc0c5, 0x6822,
+ 0x70d4, 0xd0b4, 0x0040, 0x3f9f, 0xc0b4, 0x70d6, 0x70b8, 0xa065,
+ 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f,
+ 0x007c, 0x0c7e, 0x2960, 0x6104, 0xa18c, 0xfff5, 0x6106, 0x2011,
+ 0x0032, 0x2019, 0x0000, 0x0078, 0x3fad, 0x78ab, 0x0001, 0x78ab,
+ 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820,
+ 0xc0c5, 0x6822, 0x0c7f, 0x007c, 0x0c7e, 0x7158, 0x2160, 0x2018,
+ 0xa08c, 0x0020, 0x0040, 0x3fc5, 0xc0ac, 0x2008, 0xa084, 0xfff0,
+ 0xa635, 0x7e86, 0x6018, 0x789a, 0x7eae, 0x6612, 0x78a4, 0xa084,
+ 0xfff0, 0xa18c, 0x000f, 0xa105, 0xc0f4, 0xa39c, 0x0020, 0x0040,
+ 0x3fdb, 0xa085, 0x4000, 0xc0fc, 0xd0b4, 0x00c0, 0x3fe0, 0xc0fd,
+ 0x78a6, 0x6016, 0x788a, 0xa6b4, 0x000f, 0x8637, 0x8204, 0x8004,
+ 0xa084, 0x00ff, 0xa605, 0x600e, 0x6004, 0xa084, 0xfff5, 0x6006,
+ 0x0c7f, 0x007c, 0x0c7e, 0x7058, 0x2060, 0x6018, 0x789a, 0x78a4,
+ 0xa084, 0xfff0, 0x78a6, 0x6012, 0x7884, 0xa084, 0xfff0, 0x7886,
+ 0x600c, 0xa084, 0x00ff, 0x600e, 0x0c7f, 0x007c, 0xa282, 0x0002,
+ 0x00c0, 0x4107, 0x7aa8, 0x6920, 0xc1bd, 0x6922, 0xd1cc, 0x0040,
+ 0x4041, 0xc1cc, 0x6922, 0xa294, 0x00ff, 0xa282, 0x0002, 0x00c8,
+ 0x4107, 0x1078, 0x4094, 0x1078, 0x3ff2, 0xa980, 0x0001, 0x200c,
+ 0x1078, 0x424a, 0x1078, 0x3f3e, 0x88ff, 0x0040, 0x4037, 0x789b,
+ 0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x00c0,
+ 0x4034, 0x781b, 0x0064, 0x007c, 0x781b, 0x0078, 0x007c, 0x7e58,
+ 0xd6d4, 0x00c0, 0x403e, 0x781b, 0x0067, 0x007c, 0x781b, 0x0079,
+ 0x007c, 0xa282, 0x0002, 0x00c8, 0x4049, 0xa284, 0x0001, 0x0040,
+ 0x4052, 0x7158, 0xa188, 0x0000, 0x210c, 0xd1ec, 0x00c0, 0x4052,
+ 0x2011, 0x0000, 0x1078, 0x417c, 0x1078, 0x4094, 0x1078, 0x3ff2,
+ 0x7858, 0xc095, 0x785a, 0x781b, 0x0078, 0x007c, 0x0c7e, 0x027e,
+ 0x2960, 0x6000, 0x2011, 0x0001, 0xd0ec, 0x00c0, 0x4075, 0xd0bc,
+ 0x00c0, 0x4073, 0x6014, 0xd0b4, 0x00c0, 0x4073, 0xc1a4, 0x6106,
+ 0xa006, 0x0078, 0x4091, 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab,
0x0002, 0x78ab, 0x0003, 0x7aaa, 0xa8c0, 0x0004, 0x70d4, 0xd0b4,
- 0x0040, 0x403d, 0xc0b4, 0x70d6, 0x70b8, 0xa065, 0x6008, 0xa084,
+ 0x0040, 0x408d, 0xc0b4, 0x70d6, 0x70b8, 0xa065, 0x6008, 0xa084,
0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x6820, 0xa085, 0x0200,
0x6822, 0x027f, 0x0c7f, 0x007c, 0x0c7e, 0x7058, 0x2060, 0x82ff,
- 0x0040, 0x404c, 0x2011, 0x0040, 0x6018, 0xa080, 0x0002, 0x789a,
- 0x78a4, 0xa084, 0xffbf, 0xa205, 0xc0fc, 0xd0b4, 0x00c0, 0x4059,
+ 0x0040, 0x409c, 0x2011, 0x0040, 0x6018, 0xa080, 0x0002, 0x789a,
+ 0x78a4, 0xa084, 0xffbf, 0xa205, 0xc0fc, 0xd0b4, 0x00c0, 0x40a9,
0xc0fd, 0x78a6, 0x6016, 0x788a, 0x6004, 0xc0a4, 0x6006, 0x0c7f,
- 0x007c, 0x007e, 0x7000, 0xa086, 0x0003, 0x0040, 0x406a, 0x007f,
- 0x0078, 0x406d, 0x007f, 0x0078, 0x40b4, 0xd6ac, 0x0040, 0x40b4,
- 0x7888, 0xa084, 0x0040, 0x0040, 0x40b4, 0x7bb8, 0xa384, 0x003f,
- 0x831b, 0x00c8, 0x407c, 0x8000, 0xa005, 0x0040, 0x4091, 0x831b,
- 0x00c8, 0x4085, 0x8001, 0x0040, 0x40b1, 0xd6f4, 0x0040, 0x4091,
- 0x78b8, 0x801b, 0x00c8, 0x408d, 0x8000, 0xa084, 0x003f, 0x00c0,
- 0x40b1, 0xc6f4, 0x7e5a, 0x79d8, 0x7adc, 0x2001, 0x0001, 0xa108,
- 0x00c8, 0x409c, 0xa291, 0x0000, 0x79d2, 0x79da, 0x7ad6, 0x7ade,
- 0x1078, 0x49c3, 0x781b, 0x0076, 0xb284, 0x0300, 0x0040, 0x40ac,
- 0x2001, 0x0000, 0x0078, 0x40ae, 0x2001, 0x0001, 0x1078, 0x484b,
+ 0x007c, 0x007e, 0x7000, 0xa086, 0x0003, 0x0040, 0x40ba, 0x007f,
+ 0x0078, 0x40bd, 0x007f, 0x0078, 0x4104, 0xd6ac, 0x0040, 0x4104,
+ 0x7888, 0xa084, 0x0040, 0x0040, 0x4104, 0x7bb8, 0xa384, 0x003f,
+ 0x831b, 0x00c8, 0x40cc, 0x8000, 0xa005, 0x0040, 0x40e1, 0x831b,
+ 0x00c8, 0x40d5, 0x8001, 0x0040, 0x4101, 0xd6f4, 0x0040, 0x40e1,
+ 0x78b8, 0x801b, 0x00c8, 0x40dd, 0x8000, 0xa084, 0x003f, 0x00c0,
+ 0x4101, 0xc6f4, 0x7e5a, 0x79d8, 0x7adc, 0x2001, 0x0001, 0xa108,
+ 0x00c8, 0x40ec, 0xa291, 0x0000, 0x79d2, 0x79da, 0x7ad6, 0x7ade,
+ 0x1078, 0x4a44, 0x781b, 0x0076, 0xb284, 0x0300, 0x0040, 0x40fc,
+ 0x2001, 0x0000, 0x0078, 0x40fe, 0x2001, 0x0001, 0x1078, 0x48ce,
0x007c, 0x781b, 0x0076, 0x007c, 0x781b, 0x0079, 0x007c, 0x1078,
- 0x40df, 0x781b, 0x0078, 0x007c, 0x1078, 0x40c8, 0x781b, 0x0078,
- 0x007c, 0x6827, 0x0002, 0x1078, 0x40d0, 0x781b, 0x0078, 0x007c,
- 0x2001, 0x0005, 0x0078, 0x40e1, 0x2001, 0x000c, 0x0078, 0x40e1,
- 0x6820, 0xc0d5, 0x6822, 0x2001, 0x0006, 0x0078, 0x40e1, 0x2001,
- 0x000d, 0x0078, 0x40e1, 0x2001, 0x0009, 0x0078, 0x40e1, 0x2001,
+ 0x412f, 0x781b, 0x0078, 0x007c, 0x1078, 0x4118, 0x781b, 0x0078,
+ 0x007c, 0x6827, 0x0002, 0x1078, 0x4120, 0x781b, 0x0078, 0x007c,
+ 0x2001, 0x0005, 0x0078, 0x4131, 0x2001, 0x000c, 0x0078, 0x4131,
+ 0x6820, 0xc0d5, 0x6822, 0x2001, 0x0006, 0x0078, 0x4131, 0x2001,
+ 0x000d, 0x0078, 0x4131, 0x2001, 0x0009, 0x0078, 0x4131, 0x2001,
0x0007, 0x789b, 0x007e, 0x78aa, 0xc69d, 0x7e5a, 0x70d4, 0xd0b4,
- 0x0040, 0x40f7, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8, 0xa065, 0x6008,
+ 0x0040, 0x4147, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8, 0xa065, 0x6008,
0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f, 0x007c,
0x077e, 0x873f, 0xa7bc, 0x000f, 0x873b, 0x873b, 0x8703, 0x017e,
- 0xb28c, 0x0300, 0x0040, 0x4108, 0xa0e0, 0x52c0, 0x0078, 0x410a,
- 0xa0e0, 0x5340, 0x017f, 0xa7b8, 0x0020, 0x7f9a, 0x79a4, 0xa184,
- 0x000f, 0x0040, 0x411a, 0xa184, 0xfff0, 0x78a6, 0x6012, 0x6004,
+ 0xb28c, 0x0300, 0x0040, 0x4158, 0xa0e0, 0x53c0, 0x0078, 0x415a,
+ 0xa0e0, 0x5440, 0x017f, 0xa7b8, 0x0020, 0x7f9a, 0x79a4, 0xa184,
+ 0x000f, 0x0040, 0x416a, 0xa184, 0xfff0, 0x78a6, 0x6012, 0x6004,
0xc09d, 0x6006, 0x8738, 0x8738, 0x7f9a, 0x79a4, 0xa184, 0x0040,
- 0x0040, 0x412a, 0xa184, 0xffbf, 0xc0fd, 0x78a6, 0x6016, 0x6004,
+ 0x0040, 0x417a, 0xa184, 0xffbf, 0xc0fd, 0x78a6, 0x6016, 0x6004,
0xc0a5, 0x6006, 0x077f, 0x007c, 0x789b, 0x0010, 0x78ab, 0x0001,
0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0060, 0x78ab,
- 0x0004, 0x70d4, 0xd0b4, 0x0040, 0x414a, 0xc0b4, 0x70d6, 0x0c7e,
+ 0x0004, 0x70d4, 0xd0b4, 0x0040, 0x419a, 0xc0b4, 0x70d6, 0x0c7e,
0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001,
0x601a, 0x0c7f, 0x007c, 0x2031, 0x0000, 0x2029, 0x0032, 0x789b,
0x0010, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa,
0x7eaa, 0x789b, 0x0060, 0x78ab, 0x0005, 0x70d4, 0xd0b4, 0x0040,
- 0x416e, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8, 0xa065, 0x6008, 0xa084,
+ 0x41be, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8, 0xa065, 0x6008, 0xa084,
0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f, 0x007c, 0x157e,
0x8007, 0xa084, 0x00ff, 0x8003, 0x8003, 0xa080, 0x0020, 0x789a,
- 0x79a4, 0xa18c, 0xfff0, 0x2021, 0x41e3, 0x2019, 0x0011, 0x20a9,
+ 0x79a4, 0xa18c, 0xfff0, 0x2021, 0x4233, 0x2019, 0x0011, 0x20a9,
0x000e, 0x2011, 0x0032, 0x2404, 0xa084, 0xfff0, 0xa106, 0x0040,
- 0x418e, 0x8420, 0x2300, 0xa210, 0x00f0, 0x4183, 0x157f, 0x007c,
- 0x157e, 0x2001, 0x4e05, 0x2004, 0xd0e4, 0x00c0, 0x41c1, 0x2021,
- 0x41f1, 0x20a9, 0x0009, 0x2011, 0x0028, 0xa582, 0x0019, 0x0040,
- 0x41d7, 0x0048, 0x41d7, 0x8420, 0x95a9, 0x2011, 0x0032, 0xa582,
- 0x0032, 0x0040, 0x41d7, 0x0048, 0x41d7, 0x8420, 0x95a9, 0x2019,
- 0x000a, 0x2011, 0x0064, 0x2200, 0xa502, 0x0040, 0x41d7, 0x0048,
- 0x41d7, 0x8420, 0x2300, 0xa210, 0x00f0, 0x41b3, 0x157f, 0x0078,
- 0x41d5, 0x2021, 0x41e3, 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011,
- 0x0032, 0x2200, 0xa502, 0x0040, 0x41d7, 0x0048, 0x41d7, 0x8420,
- 0x2300, 0xa210, 0x00f0, 0x41c9, 0x157f, 0xa006, 0x007c, 0x157f,
- 0xa582, 0x0064, 0x00c8, 0x41e0, 0x7808, 0xa085, 0x0070, 0x780a,
+ 0x41de, 0x8420, 0x2300, 0xa210, 0x00f0, 0x41d3, 0x157f, 0x007c,
+ 0x157e, 0x2001, 0x4f05, 0x2004, 0xd0e4, 0x00c0, 0x4211, 0x2021,
+ 0x4241, 0x20a9, 0x0009, 0x2011, 0x0028, 0xa582, 0x0019, 0x0040,
+ 0x4227, 0x0048, 0x4227, 0x8420, 0x95a9, 0x2011, 0x0032, 0xa582,
+ 0x0032, 0x0040, 0x4227, 0x0048, 0x4227, 0x8420, 0x95a9, 0x2019,
+ 0x000a, 0x2011, 0x0064, 0x2200, 0xa502, 0x0040, 0x4227, 0x0048,
+ 0x4227, 0x8420, 0x2300, 0xa210, 0x00f0, 0x4203, 0x157f, 0x0078,
+ 0x4225, 0x2021, 0x4233, 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011,
+ 0x0032, 0x2200, 0xa502, 0x0040, 0x4227, 0x0048, 0x4227, 0x8420,
+ 0x2300, 0xa210, 0x00f0, 0x4219, 0x157f, 0xa006, 0x007c, 0x157f,
+ 0xa582, 0x0064, 0x00c8, 0x4230, 0x7808, 0xa085, 0x0070, 0x780a,
0x2404, 0xa005, 0x007c, 0x1209, 0x3002, 0x3202, 0x4203, 0x4403,
0x5404, 0x5604, 0x6605, 0x6805, 0x7806, 0x7a06, 0x0c07, 0x0c07,
0x0e07, 0x10e1, 0x330a, 0x5805, 0x5a05, 0x6a06, 0x6c06, 0x7c07,
0x7e07, 0x0e00, 0x789b, 0x0010, 0xa046, 0x007c, 0xa784, 0x0f00,
0x800b, 0xa784, 0x001f, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105,
- 0xd7fc, 0x0040, 0x420f, 0xa0e0, 0x73c0, 0x0078, 0x4211, 0xa0e0,
- 0x53c0, 0x007c, 0x0e7e, 0x0f7e, 0xd084, 0x0040, 0x421f, 0x2079,
- 0x0100, 0x2009, 0x4e80, 0x2071, 0x4e80, 0x0078, 0x422f, 0x2009,
- 0x4e40, 0x2071, 0x4e40, 0x2001, 0x4e04, 0x2004, 0xd0ec, 0x0040,
- 0x422d, 0x2079, 0x0100, 0x0078, 0x422f, 0x2079, 0x0200, 0x2091,
- 0x8000, 0x2104, 0xa084, 0x000f, 0x0079, 0x4236, 0x4240, 0x4240,
- 0x4240, 0x4240, 0x4240, 0x4240, 0x423e, 0x423e, 0x1078, 0x296b,
- 0x69b4, 0xc1f5, 0xa18c, 0xff9f, 0x69b6, 0xa005, 0x0040, 0x428f,
+ 0xd7fc, 0x0040, 0x425f, 0xa0e0, 0x74c0, 0x0078, 0x4261, 0xa0e0,
+ 0x54c0, 0x007c, 0x0e7e, 0x0f7e, 0xd084, 0x0040, 0x426f, 0x2079,
+ 0x0100, 0x2009, 0x4f80, 0x2071, 0x4f80, 0x0078, 0x427f, 0x2009,
+ 0x4f40, 0x2071, 0x4f40, 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x0040,
+ 0x427d, 0x2079, 0x0100, 0x0078, 0x427f, 0x2079, 0x0200, 0x2091,
+ 0x8000, 0x2104, 0xa084, 0x000f, 0x0079, 0x4286, 0x4290, 0x4290,
+ 0x4290, 0x4290, 0x4290, 0x4290, 0x428e, 0x428e, 0x1078, 0x29b2,
+ 0x69b4, 0xc1f5, 0xa18c, 0xff9f, 0x69b6, 0xa005, 0x0040, 0x42df,
0x7858, 0xa084, 0xff9f, 0xa085, 0x6000, 0x785a, 0x7828, 0xa086,
- 0x1814, 0x00c0, 0x428f, 0x784b, 0x0004, 0x7848, 0xa084, 0x0004,
- 0x00c0, 0x4255, 0x784b, 0x0008, 0x7848, 0xa084, 0x0008, 0x00c0,
- 0x425c, 0x7830, 0xd0bc, 0x00c0, 0x428f, 0x007e, 0x2001, 0x4e04,
- 0x2004, 0xd0ec, 0x007f, 0x0040, 0x4271, 0xb284, 0x0300, 0x0078,
- 0x4273, 0xb284, 0x0400, 0x0040, 0x4279, 0x0018, 0x428f, 0x0078,
- 0x427b, 0x0028, 0x428f, 0x79e4, 0xa184, 0x0030, 0x0040, 0x428f,
- 0x78ec, 0xa084, 0x0003, 0x0040, 0x428f, 0x681c, 0xd0ac, 0x00c0,
- 0x428d, 0x1078, 0x4319, 0x0078, 0x428f, 0x781b, 0x00f9, 0x0f7f,
- 0x0e7f, 0x007c, 0x0c7e, 0x2001, 0x4e01, 0x2004, 0xd0ac, 0x00c0,
- 0x430b, 0x6814, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
- 0xb28c, 0x0300, 0x0040, 0x42a8, 0xa0e0, 0x52c0, 0x0078, 0x42aa,
- 0xa0e0, 0x5340, 0x6004, 0xa084, 0x000a, 0x00c0, 0x430b, 0x6108,
- 0xa194, 0xff00, 0x0040, 0x430b, 0xa18c, 0x00ff, 0x2001, 0x000a,
- 0xa106, 0x0040, 0x42d6, 0x2001, 0x000c, 0xa106, 0x0040, 0x42da,
- 0x2001, 0x0012, 0xa106, 0x0040, 0x42de, 0x2001, 0x0014, 0xa106,
- 0x0040, 0x42e2, 0x2001, 0x0019, 0xa106, 0x0040, 0x42e6, 0x2001,
- 0x0032, 0xa106, 0x0040, 0x42ea, 0x0078, 0x42ee, 0x2009, 0x000c,
- 0x0078, 0x42f0, 0x2009, 0x0012, 0x0078, 0x42f0, 0x2009, 0x0014,
- 0x0078, 0x42f0, 0x2009, 0x0019, 0x0078, 0x42f0, 0x2009, 0x0020,
- 0x0078, 0x42f0, 0x2009, 0x003f, 0x0078, 0x42f0, 0x2011, 0x0000,
+ 0x1814, 0x00c0, 0x42df, 0x784b, 0x0004, 0x7848, 0xa084, 0x0004,
+ 0x00c0, 0x42a5, 0x784b, 0x0008, 0x7848, 0xa084, 0x0008, 0x00c0,
+ 0x42ac, 0x7830, 0xd0bc, 0x00c0, 0x42df, 0x007e, 0x2001, 0x4f04,
+ 0x2004, 0xd0ec, 0x007f, 0x0040, 0x42c1, 0xb284, 0x0300, 0x0078,
+ 0x42c3, 0xb284, 0x0400, 0x0040, 0x42c9, 0x0018, 0x42df, 0x0078,
+ 0x42cb, 0x0028, 0x42df, 0x79e4, 0xa184, 0x0030, 0x0040, 0x42df,
+ 0x78ec, 0xa084, 0x0003, 0x0040, 0x42df, 0x681c, 0xd0ac, 0x00c0,
+ 0x42dd, 0x1078, 0x4369, 0x0078, 0x42df, 0x781b, 0x00f9, 0x0f7f,
+ 0x0e7f, 0x007c, 0x0c7e, 0x2001, 0x4f01, 0x2004, 0xd0ac, 0x00c0,
+ 0x435b, 0x6814, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
+ 0xb28c, 0x0300, 0x0040, 0x42f8, 0xa0e0, 0x53c0, 0x0078, 0x42fa,
+ 0xa0e0, 0x5440, 0x6004, 0xa084, 0x000a, 0x00c0, 0x435b, 0x6108,
+ 0xa194, 0xff00, 0x0040, 0x435b, 0xa18c, 0x00ff, 0x2001, 0x000a,
+ 0xa106, 0x0040, 0x4326, 0x2001, 0x000c, 0xa106, 0x0040, 0x432a,
+ 0x2001, 0x0012, 0xa106, 0x0040, 0x432e, 0x2001, 0x0014, 0xa106,
+ 0x0040, 0x4332, 0x2001, 0x0019, 0xa106, 0x0040, 0x4336, 0x2001,
+ 0x0032, 0xa106, 0x0040, 0x433a, 0x0078, 0x433e, 0x2009, 0x000c,
+ 0x0078, 0x4340, 0x2009, 0x0012, 0x0078, 0x4340, 0x2009, 0x0014,
+ 0x0078, 0x4340, 0x2009, 0x0019, 0x0078, 0x4340, 0x2009, 0x0020,
+ 0x0078, 0x4340, 0x2009, 0x003f, 0x0078, 0x4340, 0x2011, 0x0000,
0x2100, 0xa205, 0x600a, 0x6004, 0xa085, 0x0002, 0x6006, 0x2061,
- 0x4e00, 0x6004, 0xd0bc, 0x0040, 0x430b, 0x6814, 0xd0fc, 0x00c0,
- 0x4306, 0x60ea, 0x2061, 0x4e40, 0x0078, 0x4309, 0x60ee, 0x2061,
- 0x4e80, 0x601f, 0x800f, 0x0c7f, 0x007c, 0x781b, 0x0079, 0x007c,
+ 0x4f00, 0x6004, 0xd0bc, 0x0040, 0x435b, 0x6814, 0xd0fc, 0x00c0,
+ 0x4356, 0x60ea, 0x2061, 0x4f40, 0x0078, 0x4359, 0x60ee, 0x2061,
+ 0x4f80, 0x601f, 0x800f, 0x0c7f, 0x007c, 0x781b, 0x0079, 0x007c,
0x781b, 0x0078, 0x007c, 0x781b, 0x0067, 0x007c, 0x781b, 0x0064,
- 0x007c, 0x2009, 0x4e19, 0x210c, 0xa186, 0x0000, 0x0040, 0x432b,
- 0xa186, 0x0001, 0x0040, 0x432e, 0x701f, 0x000b, 0x7067, 0x0001,
+ 0x007c, 0x2009, 0x4f19, 0x210c, 0xa186, 0x0000, 0x0040, 0x437b,
+ 0xa186, 0x0001, 0x0040, 0x437e, 0x701f, 0x000b, 0x7067, 0x0001,
0x781b, 0x0047, 0x007c, 0x781b, 0x00f0, 0x007c, 0x701f, 0x000a,
- 0x007c, 0x2009, 0x4e19, 0x210c, 0xa186, 0x0000, 0x0040, 0x4346,
- 0xa186, 0x0001, 0x0040, 0x4343, 0x701f, 0x000b, 0x7067, 0x0001,
+ 0x007c, 0x2009, 0x4f19, 0x210c, 0xa186, 0x0000, 0x0040, 0x4396,
+ 0xa186, 0x0001, 0x0040, 0x4393, 0x701f, 0x000b, 0x7067, 0x0001,
0x781b, 0x0047, 0x007c, 0x701f, 0x000a, 0x007c, 0x781b, 0x00ef,
0x007c, 0x781b, 0x00f9, 0x007c, 0x781b, 0x00f8, 0x007c, 0x781b,
0x00c9, 0x007c, 0x781b, 0x00c8, 0x007c, 0x6818, 0xd0fc, 0x0040,
- 0x435b, 0x681b, 0x001d, 0x7067, 0x0001, 0x781b, 0x0047, 0x007c,
- 0x7830, 0xa084, 0x00c0, 0x00c0, 0x4382, 0x7808, 0xc08c, 0x780a,
+ 0x43ab, 0x681b, 0x001d, 0x7067, 0x0001, 0x781b, 0x0047, 0x007c,
+ 0x7830, 0xa084, 0x00c0, 0x00c0, 0x43d2, 0x7808, 0xc08c, 0x780a,
0x0005, 0x0005, 0x0005, 0x0005, 0x78ec, 0xa084, 0x0021, 0x00c0,
- 0x437f, 0x2001, 0x4e05, 0x2004, 0xd0e4, 0x00c0, 0x437d, 0x7804,
+ 0x43cf, 0x2001, 0x4f05, 0x2004, 0xd0e4, 0x00c0, 0x43cd, 0x7804,
0xa084, 0xff1f, 0xa085, 0x00e0, 0x7806, 0xa006, 0x007c, 0x7808,
0xc08d, 0x780a, 0x007c, 0x7808, 0xc08d, 0x780a, 0x007c, 0x7830,
- 0xa084, 0x0040, 0x00c0, 0x4387, 0x2001, 0x4e04, 0x2004, 0xd0ec,
- 0x0040, 0x4396, 0xb284, 0x0300, 0x0078, 0x4398, 0xb284, 0x0400,
- 0x0040, 0x439e, 0x0098, 0x43a2, 0x0078, 0x43a0, 0x00a8, 0x43a2,
+ 0xa084, 0x0040, 0x00c0, 0x43d7, 0x2001, 0x4f04, 0x2004, 0xd0ec,
+ 0x0040, 0x43e6, 0xb284, 0x0300, 0x0078, 0x43e8, 0xb284, 0x0400,
+ 0x0040, 0x43ee, 0x0098, 0x43f2, 0x0078, 0x43f0, 0x00a8, 0x43f2,
0x78ac, 0x007c, 0x7808, 0xa084, 0xfffd, 0x780a, 0x0005, 0x0005,
- 0x0005, 0x0005, 0x78ec, 0xa084, 0x0021, 0x0040, 0x43c5, 0x007e,
- 0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x43bb, 0xb284,
- 0x0300, 0x0078, 0x43bd, 0xb284, 0x0400, 0x0040, 0x43c3, 0x0098,
- 0x43bf, 0x0078, 0x43c5, 0x00a8, 0x43c3, 0x78ac, 0x007e, 0x7808,
+ 0x0005, 0x0005, 0x78ec, 0xa084, 0x0021, 0x0040, 0x4415, 0x007e,
+ 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x440b, 0xb284,
+ 0x0300, 0x0078, 0x440d, 0xb284, 0x0400, 0x0040, 0x4413, 0x0098,
+ 0x440f, 0x0078, 0x4415, 0x00a8, 0x4413, 0x78ac, 0x007e, 0x7808,
0xa085, 0x0002, 0x780a, 0x007f, 0x007c, 0xa784, 0x0001, 0x00c0,
- 0x3770, 0xa784, 0x0070, 0x0040, 0x43dd, 0x0c7e, 0x2d60, 0x2f68,
- 0x1078, 0x28df, 0x2d78, 0x2c68, 0x0c7f, 0xa784, 0x0008, 0x0040,
- 0x43ea, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x3770,
- 0x0078, 0x430d, 0xa784, 0x0004, 0x0040, 0x4419, 0x78b8, 0xa084,
- 0x4001, 0x0040, 0x4419, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003,
- 0x0040, 0x3770, 0x78e4, 0xa084, 0x0007, 0xa086, 0x0001, 0x00c0,
- 0x4419, 0x78c0, 0xa685, 0x4800, 0x2030, 0x7e5a, 0x781b, 0x00f9,
- 0x007c, 0x784b, 0x0008, 0x6818, 0xd0fc, 0x0040, 0x4416, 0x681b,
- 0x0015, 0xd6f4, 0x0040, 0x4416, 0x681b, 0x0007, 0x1078, 0x4319,
+ 0x37b9, 0xa784, 0x0070, 0x0040, 0x442d, 0x0c7e, 0x2d60, 0x2f68,
+ 0x1078, 0x2926, 0x2d78, 0x2c68, 0x0c7f, 0xa784, 0x0008, 0x0040,
+ 0x443a, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x37b9,
+ 0x0078, 0x435d, 0xa784, 0x0004, 0x0040, 0x4469, 0x78b8, 0xa084,
+ 0x4001, 0x0040, 0x4469, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003,
+ 0x0040, 0x37b9, 0x78e4, 0xa084, 0x0007, 0xa086, 0x0001, 0x00c0,
+ 0x4469, 0x78c0, 0xa685, 0x4800, 0x2030, 0x7e5a, 0x781b, 0x00f9,
+ 0x007c, 0x784b, 0x0008, 0x6818, 0xd0fc, 0x0040, 0x4466, 0x681b,
+ 0x0015, 0xd6f4, 0x0040, 0x4466, 0x681b, 0x0007, 0x1078, 0x4369,
0x007c, 0x681b, 0x0003, 0x7858, 0xa084, 0x3f00, 0x681e, 0x682f,
0x0000, 0x6833, 0x0000, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003,
- 0x0040, 0x3066, 0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f,
- 0x0040, 0x4436, 0xb284, 0x0300, 0x0078, 0x4438, 0xb284, 0x0400,
- 0x0040, 0x443e, 0x0018, 0x29c1, 0x0078, 0x4440, 0x0028, 0x29c1,
- 0x0078, 0x40bc, 0x6b14, 0x8307, 0xa084, 0x000f, 0x8003, 0x8003,
- 0x8003, 0xd3fc, 0x0040, 0x4450, 0xa080, 0x5340, 0x0078, 0x4452,
- 0xa080, 0x52c0, 0x2060, 0x2048, 0x705a, 0x2a60, 0x007c, 0x0020,
+ 0x0040, 0x30af, 0x007e, 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f,
+ 0x0040, 0x4486, 0xb284, 0x0300, 0x0078, 0x4488, 0xb284, 0x0400,
+ 0x0040, 0x448e, 0x0018, 0x2a08, 0x0078, 0x4490, 0x0028, 0x2a08,
+ 0x0078, 0x410c, 0x6b14, 0x8307, 0xa084, 0x000f, 0x8003, 0x8003,
+ 0x8003, 0xd3fc, 0x0040, 0x44a0, 0xa080, 0x5440, 0x0078, 0x44a2,
+ 0xa080, 0x53c0, 0x2060, 0x2048, 0x705a, 0x2a60, 0x007c, 0x0020,
0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
@@ -1763,255 +1773,276 @@ static unsigned short risc_code01[] = {
0x0016, 0x7944, 0x8421, 0xa020, 0xa532, 0x84a1, 0x0016, 0x7944,
0x8421, 0xa0df, 0x9532, 0x84a1, 0x0016, 0x0000, 0x127e, 0x70d4,
0xa084, 0x4600, 0x8004, 0x2090, 0x7204, 0x7008, 0xc09c, 0xa205,
- 0x00c0, 0x45a2, 0x720c, 0x82ff, 0x0040, 0x459d, 0x8aff, 0x00c0,
- 0x45a2, 0x7200, 0xd284, 0x00c0, 0x45a2, 0x7003, 0x0008, 0x127f,
+ 0x00c0, 0x4602, 0x720c, 0x82ff, 0x0040, 0x45ed, 0x8aff, 0x00c0,
+ 0x4602, 0x7200, 0xd284, 0x00c0, 0x4602, 0x7804, 0xd0cc, 0x0040,
+ 0x45f3, 0x1078, 0x4acc, 0x7023, 0x0000, 0x7027, 0x0000, 0x7000,
+ 0xd084, 0x0040, 0x45fd, 0x7007, 0x0004, 0x7003, 0x0008, 0x127f,
0x2000, 0x007c, 0x7000, 0xa084, 0x0003, 0x7002, 0xc69c, 0xd084,
- 0x0040, 0x45e5, 0x7108, 0x0005, 0x7008, 0xa106, 0x00c0, 0x45aa,
- 0xa184, 0x0003, 0x0040, 0x4616, 0xa184, 0x01e0, 0x00c0, 0x4616,
- 0xd1f4, 0x00c0, 0x45aa, 0xa184, 0x3000, 0xa086, 0x1000, 0x0040,
- 0x45aa, 0x2011, 0x0180, 0x710c, 0x8211, 0x0040, 0x45cf, 0x7008,
- 0xd0f4, 0x00c0, 0x45aa, 0x700c, 0xa106, 0x0040, 0x45c4, 0x7007,
- 0x0012, 0x7108, 0x0005, 0x7008, 0xa106, 0x00c0, 0x45d1, 0xa184,
- 0x0003, 0x0040, 0x4616, 0xd194, 0x0040, 0x45d1, 0xd1f4, 0x0040,
- 0x4616, 0x7007, 0x0002, 0x0078, 0x45aa, 0x7108, 0xd1fc, 0x0040,
- 0x45f0, 0x1078, 0x4769, 0x8aff, 0x0040, 0x458c, 0x0078, 0x45e5,
- 0x700c, 0xa08c, 0x03ff, 0x0040, 0x461b, 0x7004, 0xd084, 0x0040,
- 0x460d, 0x7014, 0xa005, 0x00c0, 0x4609, 0x7010, 0x7310, 0xa306,
- 0x00c0, 0x45fd, 0x2300, 0xa005, 0x0040, 0x460d, 0xa102, 0x00c8,
- 0x45e5, 0x7007, 0x0010, 0x0078, 0x4616, 0x8aff, 0x0040, 0x461b,
- 0x1078, 0x4970, 0x00c0, 0x4610, 0x0040, 0x45e5, 0x1078, 0x46b4,
- 0x127f, 0x2000, 0x007c, 0x7204, 0x7108, 0xc19c, 0x8103, 0x00c8,
- 0x462a, 0x7007, 0x0002, 0x0078, 0x461b, 0x7003, 0x0008, 0x127f,
- 0x2000, 0x007c, 0xa205, 0x00c0, 0x4616, 0x7003, 0x0008, 0x127f,
- 0x2000, 0x007c, 0x6428, 0x84ff, 0x0040, 0x465e, 0x2c70, 0x7004,
- 0xa0bc, 0x000f, 0xa7b8, 0x466e, 0x273c, 0x87fb, 0x00c0, 0x464c,
- 0x0048, 0x4644, 0x1078, 0x296b, 0x609c, 0xa075, 0x0040, 0x465e,
- 0x0078, 0x4637, 0x2039, 0x4663, 0x2704, 0xae68, 0x6808, 0xa630,
- 0x680c, 0xa529, 0x8421, 0x0040, 0x465e, 0x8738, 0x2704, 0xa005,
- 0x00c0, 0x464d, 0x709c, 0xa075, 0x00c0, 0x4637, 0x007c, 0x0000,
- 0x0005, 0x0009, 0x000d, 0x0011, 0x0015, 0x0019, 0x001d, 0x0000,
- 0x0003, 0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0000, 0x4663,
- 0x4660, 0x0000, 0x0000, 0x8000, 0x0000, 0x4663, 0x0000, 0x466b,
- 0x4668, 0x0000, 0x0000, 0x0000, 0x0000, 0x466b, 0x0000, 0x4666,
- 0x4666, 0x0000, 0x0000, 0x8000, 0x0000, 0x4666, 0x0000, 0x466c,
- 0x466c, 0x0000, 0x0000, 0x0000, 0x0000, 0x466c, 0x2079, 0x4e00,
- 0x2071, 0x0010, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, 0x0001,
- 0x7810, 0xd0ec, 0x0040, 0x46a2, 0x2009, 0x0001, 0x2071, 0x0020,
- 0x0078, 0x46a6, 0x2009, 0x0002, 0x2071, 0x0050, 0x7007, 0x000a,
- 0x7007, 0x0002, 0x7003, 0x0000, 0x8109, 0x0040, 0x46b3, 0x2071,
- 0x0020, 0x0078, 0x46a6, 0x007c, 0x7004, 0x8004, 0x00c8, 0x473d,
- 0x7108, 0x7008, 0xa106, 0x00c0, 0x46b8, 0xa184, 0x01e0, 0x0040,
- 0x46c5, 0x1078, 0x47ac, 0x0078, 0x4765, 0x7007, 0x0012, 0x2019,
- 0x0000, 0x7108, 0x7008, 0xa106, 0x00c0, 0x46c9, 0xa184, 0x01e0,
- 0x0040, 0x46d6, 0x1078, 0x47ac, 0x0078, 0x4765, 0x7810, 0xd0ec,
- 0x0040, 0x46f0, 0x2001, 0x04fd, 0x2004, 0xa086, 0x0003, 0x00c0,
- 0x46f4, 0xa184, 0x4000, 0x0040, 0x46f8, 0xa382, 0x0003, 0x00c8,
- 0x46f8, 0xa184, 0x0004, 0x0040, 0x46c9, 0x8318, 0x0078, 0x46c9,
- 0x7814, 0xd0ec, 0x00c0, 0x46f8, 0xa184, 0x4000, 0x00c0, 0x46c9,
- 0xa19c, 0x300c, 0xa386, 0x2004, 0x0040, 0x4715, 0xa386, 0x0008,
- 0x0040, 0x4720, 0x7004, 0xd084, 0x00c0, 0x4711, 0x7108, 0x7008,
- 0xa106, 0x00c0, 0x4706, 0xa184, 0x0003, 0x0040, 0x4711, 0x0078,
- 0x47ac, 0xa386, 0x200c, 0x00c0, 0x46c9, 0x7200, 0x8204, 0x0048,
- 0x4720, 0x730c, 0xa384, 0x03ff, 0x0040, 0x4720, 0x1078, 0x296b,
- 0x7108, 0x7008, 0xa106, 0x00c0, 0x4720, 0xa184, 0x01e0, 0x0040,
- 0x472d, 0x1078, 0x47ac, 0x0078, 0x4765, 0x7007, 0x0012, 0x7000,
- 0xd084, 0x00c0, 0x473d, 0x7310, 0x7014, 0xa305, 0x0040, 0x473d,
- 0x710c, 0xa184, 0x03ff, 0x00c0, 0x46b4, 0x7108, 0x7008, 0xa106,
- 0x00c0, 0x473d, 0xa184, 0x01e0, 0x0040, 0x474a, 0x1078, 0x47ac,
- 0x0078, 0x4765, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004, 0xd09c,
- 0x00c0, 0x474e, 0x7108, 0x7008, 0xa106, 0x00c0, 0x4752, 0xa184,
- 0x01e0, 0x0040, 0x475f, 0x1078, 0x47ac, 0x0078, 0x4765, 0x7007,
- 0x0012, 0x7108, 0x8103, 0x0048, 0x4752, 0x7003, 0x0008, 0x007c,
- 0x7108, 0xa184, 0x01e0, 0x00c0, 0x47ac, 0x7108, 0xa184, 0x01e0,
- 0x00c0, 0x47ac, 0xa184, 0x0007, 0x0079, 0x4776, 0x4780, 0x4790,
- 0x477e, 0x4790, 0x477e, 0x47ee, 0x477e, 0x47ec, 0x1078, 0x296b,
- 0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x8aff, 0x00c0, 0x478b,
- 0x2049, 0x0000, 0x007c, 0x1078, 0x4970, 0x00c0, 0x478b, 0x007c,
- 0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x7004, 0xd084, 0x00c0,
- 0x47a4, 0x7108, 0x7008, 0xa106, 0x00c0, 0x4799, 0xa184, 0x0003,
- 0x0040, 0x47a4, 0x0078, 0x47ac, 0x8aff, 0x0040, 0x47ab, 0x1078,
- 0x4970, 0x00c0, 0x47a7, 0x007c, 0x7007, 0x0012, 0x7108, 0x00e0,
- 0x47af, 0x2091, 0x6000, 0x00e0, 0x47b3, 0x2091, 0x6000, 0x7007,
- 0x0012, 0x7007, 0x0008, 0x7004, 0xd09c, 0x00c0, 0x47bb, 0x7007,
- 0x0012, 0x7108, 0xd1fc, 0x00c0, 0x47bf, 0x7003, 0x0000, 0x7000,
- 0xa005, 0x00c0, 0x47d3, 0x7004, 0xa005, 0x00c0, 0x47d3, 0x700c,
- 0xa005, 0x0040, 0x47d5, 0x0078, 0x47b7, 0x2049, 0x0000, 0xb284,
- 0x0100, 0x0040, 0x47df, 0x2001, 0x0000, 0x0078, 0x47e1, 0x2001,
- 0x0001, 0x1078, 0x4212, 0x681b, 0x0002, 0x2051, 0x0000, 0x007c,
- 0x1078, 0x296b, 0x1078, 0x296b, 0x1078, 0x4836, 0x7210, 0x7114,
- 0x700c, 0xa09c, 0x03ff, 0x2800, 0xa300, 0xa211, 0xa189, 0x0000,
- 0x1078, 0x4836, 0x2704, 0x2c58, 0xac60, 0x6308, 0x2200, 0xa322,
- 0x630c, 0x2100, 0xa31b, 0x2400, 0xa305, 0x0040, 0x4811, 0x00c8,
- 0x4811, 0x8412, 0x8210, 0x830a, 0xa189, 0x0000, 0x2b60, 0x0078,
- 0x47f8, 0x2b60, 0x8a07, 0x007e, 0x6004, 0xa084, 0x0008, 0x0040,
- 0x481d, 0xa7ba, 0x4668, 0x0078, 0x481f, 0xa7ba, 0x4660, 0x007f,
- 0xa73d, 0x2c00, 0x6886, 0x6f8a, 0x6c92, 0x6b8e, 0x7108, 0x7008,
- 0xa106, 0x00c0, 0x4826, 0xa184, 0x01e0, 0x0040, 0x4831, 0x1078,
- 0x47ac, 0x7007, 0x0012, 0x1078, 0x46b4, 0x007c, 0x8a50, 0x8739,
- 0x2704, 0xa004, 0x00c0, 0x484a, 0x6000, 0xa064, 0x00c0, 0x4841,
- 0x2d60, 0x6004, 0xa084, 0x000f, 0xa080, 0x467e, 0x203c, 0x87fb,
- 0x1040, 0x296b, 0x007c, 0x127e, 0x0d7e, 0x70d4, 0xa084, 0x4600,
- 0x8004, 0x2090, 0x0d7f, 0x6884, 0x2060, 0x6888, 0x6b8c, 0x6c90,
- 0x8057, 0xaad4, 0x00ff, 0xa084, 0x00ff, 0x007e, 0x6804, 0xa084,
- 0x0008, 0x007f, 0x0040, 0x4868, 0xa0b8, 0x4668, 0x0078, 0x486a,
- 0xa0b8, 0x4660, 0xb284, 0x0100, 0x0040, 0x4871, 0x7e20, 0x0078,
- 0x4872, 0x7e24, 0xa6b5, 0x000c, 0x681c, 0xd0b4, 0x0040, 0x4879,
- 0xc685, 0x2400, 0xa305, 0x0040, 0x48a3, 0x2c58, 0x2704, 0x6104,
- 0xac60, 0x6000, 0xa400, 0x701a, 0x6004, 0xa301, 0x701e, 0xa184,
- 0x0008, 0x0040, 0x4893, 0x6010, 0xa081, 0x0000, 0x7022, 0x6014,
- 0xa081, 0x0000, 0x7026, 0x6208, 0x2400, 0xa202, 0x7012, 0x620c,
- 0x2300, 0xa203, 0x7016, 0x7602, 0x7007, 0x0001, 0x2b60, 0x1078,
- 0x499b, 0x0078, 0x48a5, 0x1078, 0x4970, 0x00c0, 0x48a3, 0x127f,
- 0x2000, 0x007c, 0x127e, 0x0d7e, 0x70d4, 0xa084, 0x4600, 0x8004,
- 0x2090, 0x0d7f, 0x7007, 0x0004, 0x7004, 0xd094, 0x00c0, 0x48b4,
- 0x7003, 0x0008, 0x127f, 0x2000, 0x007c, 0x127e, 0x0d7e, 0x70d4,
- 0xa084, 0x4600, 0x8004, 0x007e, 0x2090, 0x007f, 0x0d7f, 0x7e20,
- 0xb284, 0x0100, 0x00c0, 0x48cd, 0x7e24, 0xa6b5, 0x000c, 0x681c,
- 0xd0ac, 0x00c0, 0x48d8, 0xc685, 0x7003, 0x0000, 0x7007, 0x0004,
- 0x6828, 0x2050, 0x2d60, 0x6004, 0xa0bc, 0x000f, 0xa7b8, 0x466e,
- 0x273c, 0x87fb, 0x00c0, 0x48ee, 0x0048, 0x48e8, 0x1078, 0x296b,
- 0x689c, 0xa065, 0x0040, 0x48f2, 0x0078, 0x48db, 0x1078, 0x4970,
- 0x00c0, 0x48ee, 0x127f, 0x2000, 0x007c, 0x127e, 0x007e, 0x017e,
+ 0x0040, 0x465b, 0x7108, 0x0005, 0x7008, 0xa106, 0x00c0, 0x460a,
+ 0xa184, 0x0003, 0x0040, 0x468c, 0xa184, 0x01e0, 0x00c0, 0x468c,
+ 0xd1f4, 0x00c0, 0x460a, 0xa184, 0x3000, 0xa086, 0x1000, 0x0040,
+ 0x460a, 0x2001, 0x4f05, 0x2004, 0xd0e4, 0x0040, 0x4637, 0x2011,
+ 0x0180, 0x710c, 0x8211, 0x0040, 0x4645, 0x7008, 0xd0f4, 0x00c0,
+ 0x460a, 0x700c, 0xa106, 0x0040, 0x462a, 0x0078, 0x4627, 0x2011,
+ 0x0180, 0x710c, 0x8211, 0x0040, 0x4645, 0x7008, 0xd0f4, 0x00c0,
+ 0x460a, 0x700c, 0xa106, 0x0040, 0x463a, 0x7007, 0x0012, 0x7108,
+ 0x0005, 0x7008, 0xa106, 0x00c0, 0x4647, 0xa184, 0x0003, 0x0040,
+ 0x468c, 0xd194, 0x0040, 0x4647, 0xd1f4, 0x0040, 0x468c, 0x7007,
+ 0x0002, 0x0078, 0x460a, 0x7108, 0xd1fc, 0x0040, 0x4666, 0x1078,
+ 0x47ed, 0x8aff, 0x0040, 0x45dc, 0x0078, 0x465b, 0x700c, 0xa08c,
+ 0x03ff, 0x0040, 0x4691, 0x7004, 0xd084, 0x0040, 0x4683, 0x7014,
+ 0xa005, 0x00c0, 0x467f, 0x7010, 0x7310, 0xa306, 0x00c0, 0x4673,
+ 0x2300, 0xa005, 0x0040, 0x4683, 0xa102, 0x00c8, 0x465b, 0x7007,
+ 0x0010, 0x0078, 0x468c, 0x8aff, 0x0040, 0x4691, 0x1078, 0x49f2,
+ 0x00c0, 0x4686, 0x0040, 0x465b, 0x1078, 0x4738, 0x127f, 0x2000,
+ 0x007c, 0x7204, 0x7108, 0xc19c, 0x8103, 0x00c8, 0x46a0, 0x7007,
+ 0x0002, 0x0078, 0x4691, 0x7003, 0x0008, 0x127f, 0x2000, 0x007c,
+ 0xa205, 0x00c0, 0x468c, 0x7023, 0x0000, 0x7027, 0x0000, 0x7003,
+ 0x0008, 0x007e, 0x2001, 0x4f01, 0x2004, 0xd0cc, 0x0040, 0x46b2,
+ 0x1078, 0x4acc, 0x007f, 0x127f, 0x2000, 0x007c, 0x6428, 0x84ff,
+ 0x0040, 0x46e2, 0x2c70, 0x7004, 0xa0bc, 0x000f, 0xa7b8, 0x46f2,
+ 0x273c, 0x87fb, 0x00c0, 0x46d0, 0x0048, 0x46c8, 0x1078, 0x29b2,
+ 0x609c, 0xa075, 0x0040, 0x46e2, 0x0078, 0x46bb, 0x2039, 0x46e7,
+ 0x2704, 0xae68, 0x6808, 0xa630, 0x680c, 0xa529, 0x8421, 0x0040,
+ 0x46e2, 0x8738, 0x2704, 0xa005, 0x00c0, 0x46d1, 0x709c, 0xa075,
+ 0x00c0, 0x46bb, 0x007c, 0x0000, 0x0005, 0x0009, 0x000d, 0x0011,
+ 0x0015, 0x0019, 0x001d, 0x0000, 0x0003, 0x0009, 0x000f, 0x0015,
+ 0x001b, 0x0000, 0x0000, 0x46e7, 0x46e4, 0x0000, 0x0000, 0x8000,
+ 0x0000, 0x46e7, 0x0000, 0x46ef, 0x46ec, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x46ef, 0x0000, 0x46ea, 0x46ea, 0x0000, 0x0000, 0x8000,
+ 0x0000, 0x46ea, 0x0000, 0x46f0, 0x46f0, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x46f0, 0x2079, 0x4f00, 0x2071, 0x0010, 0x7007, 0x000a,
+ 0x7007, 0x0002, 0x7003, 0x0001, 0x7810, 0xd0ec, 0x0040, 0x4726,
+ 0x2009, 0x0001, 0x2071, 0x0020, 0x0078, 0x472a, 0x2009, 0x0002,
+ 0x2071, 0x0050, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, 0x0000,
+ 0x8109, 0x0040, 0x4737, 0x2071, 0x0020, 0x0078, 0x472a, 0x007c,
+ 0x7004, 0x8004, 0x00c8, 0x47c1, 0x7108, 0x7008, 0xa106, 0x00c0,
+ 0x473c, 0xa184, 0x01e0, 0x0040, 0x4749, 0x1078, 0x4830, 0x0078,
+ 0x47e9, 0x7007, 0x0012, 0x2019, 0x0000, 0x7108, 0x7008, 0xa106,
+ 0x00c0, 0x474d, 0xa184, 0x01e0, 0x0040, 0x475a, 0x1078, 0x4830,
+ 0x0078, 0x47e9, 0x7810, 0xd0ec, 0x0040, 0x4774, 0x2001, 0x04fd,
+ 0x2004, 0xa086, 0x0003, 0x00c0, 0x4778, 0xa184, 0x4000, 0x0040,
+ 0x477c, 0xa382, 0x0003, 0x00c8, 0x477c, 0xa184, 0x0004, 0x0040,
+ 0x474d, 0x8318, 0x0078, 0x474d, 0x7814, 0xd0ec, 0x00c0, 0x477c,
+ 0xa184, 0x4000, 0x00c0, 0x474d, 0xa19c, 0x300c, 0xa386, 0x2004,
+ 0x0040, 0x4799, 0xa386, 0x0008, 0x0040, 0x47a4, 0x7004, 0xd084,
+ 0x00c0, 0x4795, 0x7108, 0x7008, 0xa106, 0x00c0, 0x478a, 0xa184,
+ 0x0003, 0x0040, 0x4795, 0x0078, 0x4830, 0xa386, 0x200c, 0x00c0,
+ 0x474d, 0x7200, 0x8204, 0x0048, 0x47a4, 0x730c, 0xa384, 0x03ff,
+ 0x0040, 0x47a4, 0x1078, 0x29b2, 0x7108, 0x7008, 0xa106, 0x00c0,
+ 0x47a4, 0xa184, 0x01e0, 0x0040, 0x47b1, 0x1078, 0x4830, 0x0078,
+ 0x47e9, 0x7007, 0x0012, 0x7000, 0xd084, 0x00c0, 0x47c1, 0x7310,
+ 0x7014, 0xa305, 0x0040, 0x47c1, 0x710c, 0xa184, 0x03ff, 0x00c0,
+ 0x4738, 0x7108, 0x7008, 0xa106, 0x00c0, 0x47c1, 0xa184, 0x01e0,
+ 0x0040, 0x47ce, 0x1078, 0x4830, 0x0078, 0x47e9, 0x7007, 0x0012,
+ 0x7007, 0x0008, 0x7004, 0xd09c, 0x00c0, 0x47d2, 0x7108, 0x7008,
+ 0xa106, 0x00c0, 0x47d6, 0xa184, 0x01e0, 0x0040, 0x47e3, 0x1078,
+ 0x4830, 0x0078, 0x47e9, 0x7007, 0x0012, 0x7108, 0x8103, 0x0048,
+ 0x47d6, 0x7003, 0x0008, 0x007c, 0x7108, 0xa184, 0x01e0, 0x00c0,
+ 0x4830, 0x7108, 0xa184, 0x01e0, 0x00c0, 0x4830, 0xa184, 0x0007,
+ 0x0079, 0x47fa, 0x4804, 0x4814, 0x4802, 0x4814, 0x4802, 0x4872,
+ 0x4802, 0x4870, 0x1078, 0x29b2, 0x7004, 0xa084, 0x0010, 0xc08d,
+ 0x7006, 0x8aff, 0x00c0, 0x480f, 0x2049, 0x0000, 0x007c, 0x1078,
+ 0x49f2, 0x00c0, 0x480f, 0x007c, 0x7004, 0xa084, 0x0010, 0xc08d,
+ 0x7006, 0x7004, 0xd084, 0x00c0, 0x4828, 0x7108, 0x7008, 0xa106,
+ 0x00c0, 0x481d, 0xa184, 0x0003, 0x0040, 0x4828, 0x0078, 0x4830,
+ 0x8aff, 0x0040, 0x482f, 0x1078, 0x49f2, 0x00c0, 0x482b, 0x007c,
+ 0x7007, 0x0012, 0x7108, 0x00e0, 0x4833, 0x2091, 0x6000, 0x00e0,
+ 0x4837, 0x2091, 0x6000, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004,
+ 0xd09c, 0x00c0, 0x483f, 0x7007, 0x0012, 0x7108, 0xd1fc, 0x00c0,
+ 0x4843, 0x7003, 0x0000, 0x7000, 0xa005, 0x00c0, 0x4857, 0x7004,
+ 0xa005, 0x00c0, 0x4857, 0x700c, 0xa005, 0x0040, 0x4859, 0x0078,
+ 0x483b, 0x2049, 0x0000, 0xb284, 0x0100, 0x0040, 0x4863, 0x2001,
+ 0x0000, 0x0078, 0x4865, 0x2001, 0x0001, 0x1078, 0x4262, 0x681b,
+ 0x0002, 0x2051, 0x0000, 0x007c, 0x1078, 0x29b2, 0x1078, 0x29b2,
+ 0x1078, 0x48b9, 0x7210, 0x7114, 0x700c, 0xa09c, 0x03ff, 0x2800,
+ 0xa300, 0xa211, 0xa189, 0x0000, 0x1078, 0x48b9, 0x2704, 0x2c58,
+ 0xac60, 0x6308, 0x2200, 0xa322, 0x630c, 0x2100, 0xa31b, 0x2400,
+ 0xa305, 0x0040, 0x4895, 0x00c8, 0x4895, 0x8412, 0x8210, 0x830a,
+ 0xa189, 0x0000, 0x2b60, 0x0078, 0x487c, 0x2b60, 0x8a07, 0x007e,
+ 0x6004, 0xd09c, 0x0040, 0x48a0, 0xa7ba, 0x46ec, 0x0078, 0x48a2,
+ 0xa7ba, 0x46e4, 0x007f, 0xa73d, 0x2c00, 0x6886, 0x6f8a, 0x6c92,
+ 0x6b8e, 0x7108, 0x7008, 0xa106, 0x00c0, 0x48a9, 0xa184, 0x01e0,
+ 0x0040, 0x48b4, 0x1078, 0x4830, 0x7007, 0x0012, 0x1078, 0x4738,
+ 0x007c, 0x8a50, 0x8739, 0x2704, 0xa004, 0x00c0, 0x48cd, 0x6000,
+ 0xa064, 0x00c0, 0x48c4, 0x2d60, 0x6004, 0xa084, 0x000f, 0xa080,
+ 0x4702, 0x203c, 0x87fb, 0x1040, 0x29b2, 0x007c, 0x127e, 0x0d7e,
+ 0x70d4, 0xa084, 0x4600, 0x8004, 0x2090, 0x0d7f, 0x6884, 0x2060,
+ 0x6888, 0x6b8c, 0x6c90, 0x8057, 0xaad4, 0x00ff, 0xa084, 0x00ff,
+ 0x007e, 0x6804, 0xa084, 0x0008, 0x007f, 0x0040, 0x48eb, 0xa0b8,
+ 0x46ec, 0x0078, 0x48ed, 0xa0b8, 0x46e4, 0xb284, 0x0100, 0x0040,
+ 0x48f4, 0x7e20, 0x0078, 0x48f5, 0x7e24, 0xa6b5, 0x000c, 0x681c,
+ 0xd0b4, 0x0040, 0x48fc, 0xc685, 0x2400, 0xa305, 0x0040, 0x4925,
+ 0x2c58, 0x2704, 0x6104, 0xac60, 0x6000, 0xa400, 0x701a, 0x6004,
+ 0xa301, 0x701e, 0xd19c, 0x0040, 0x4915, 0x6010, 0xa081, 0x0000,
+ 0x7022, 0x6014, 0xa081, 0x0000, 0x7026, 0x6208, 0x2400, 0xa202,
+ 0x7012, 0x620c, 0x2300, 0xa203, 0x7016, 0x7602, 0x7007, 0x0001,
+ 0x2b60, 0x1078, 0x4a1c, 0x0078, 0x4927, 0x1078, 0x49f2, 0x00c0,
+ 0x4925, 0x127f, 0x2000, 0x007c, 0x127e, 0x0d7e, 0x70d4, 0xa084,
+ 0x4600, 0x8004, 0x2090, 0x0d7f, 0x7007, 0x0004, 0x7004, 0xd094,
+ 0x00c0, 0x4936, 0x7003, 0x0008, 0x127f, 0x2000, 0x007c, 0x127e,
0x0d7e, 0x70d4, 0xa084, 0x4600, 0x8004, 0x007e, 0x2090, 0x007f,
- 0x7e20, 0xb284, 0x0100, 0x00c0, 0x4906, 0x7e24, 0x0d7f, 0x037f,
- 0x047f, 0xa6b5, 0x000c, 0x681c, 0xd0b4, 0x0040, 0x4914, 0xc685,
- 0x7003, 0x0000, 0x7007, 0x0004, 0x2049, 0x48f5, 0x6828, 0xa055,
- 0x0d7e, 0x0040, 0x496c, 0x2d70, 0x2e60, 0x7004, 0xa0bc, 0x000f,
- 0xa7b8, 0x466e, 0x273c, 0x87fb, 0x00c0, 0x4931, 0x0048, 0x492a,
- 0x1078, 0x296b, 0x709c, 0xa075, 0x2060, 0x0040, 0x496c, 0x0078,
- 0x491d, 0x2704, 0xae68, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0048,
- 0x494a, 0x8a51, 0x00c0, 0x493e, 0x1078, 0x296b, 0x8738, 0x2704,
- 0xa005, 0x00c0, 0x4932, 0x709c, 0xa075, 0x2060, 0x0040, 0x496c,
- 0x0078, 0x491d, 0x8422, 0x8420, 0x831a, 0xa399, 0x0000, 0x6908,
- 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, 0x00c8, 0x4959, 0x1078,
- 0x296b, 0xb284, 0x0100, 0x0040, 0x4967, 0x2001, 0x4e04, 0x2004,
- 0xd0ec, 0x00c0, 0x4967, 0x2071, 0x0050, 0x0078, 0x4969, 0x2071,
- 0x0020, 0x0d7f, 0x0078, 0x4879, 0x0d7f, 0x127f, 0x2000, 0x007c,
- 0x7008, 0x007e, 0xa084, 0x01e0, 0x007f, 0x0040, 0x4979, 0xa006,
- 0x007c, 0xa084, 0x0003, 0xa086, 0x0003, 0x00c0, 0x4980, 0x007c,
- 0x2704, 0xac78, 0x7800, 0x701a, 0x7804, 0x701e, 0x7808, 0x7012,
- 0x780c, 0x7016, 0x6004, 0xa084, 0x0008, 0x0040, 0x4993, 0x7810,
- 0x7022, 0x7814, 0x7026, 0x7602, 0x7004, 0xa084, 0x0010, 0xc085,
- 0x7006, 0x2079, 0x4e00, 0x8a51, 0x0040, 0x49bf, 0x8738, 0x2704,
- 0xa005, 0x00c0, 0x49b1, 0x609c, 0xa005, 0x0040, 0x49c0, 0x2060,
- 0x6004, 0xa084, 0x000f, 0xa080, 0x466e, 0x203c, 0x87fb, 0x1040,
- 0x296b, 0x7008, 0x007e, 0xa084, 0x01e0, 0x007f, 0x0040, 0x49bb,
- 0xa006, 0x0078, 0x49c0, 0xa084, 0x0003, 0xa086, 0x0003, 0x007c,
- 0x2051, 0x0000, 0x007c, 0x127e, 0x007e, 0x0d7e, 0x70d4, 0xa084,
- 0x4600, 0x8004, 0x2090, 0x0d7f, 0x087f, 0x7108, 0xa184, 0x0003,
- 0x00c0, 0x49d8, 0x6828, 0xa005, 0x0040, 0x49e8, 0x0078, 0x45a2,
- 0x7108, 0xd1fc, 0x0040, 0x49e0, 0x1078, 0x4769, 0x0078, 0x49cd,
- 0x7007, 0x0010, 0x7108, 0xd1fc, 0x0040, 0x49e2, 0x1078, 0x4769,
- 0x7008, 0xa086, 0x0008, 0x00c0, 0x49cd, 0x7000, 0xa005, 0x00c0,
- 0x49cd, 0x7003, 0x0000, 0x2049, 0x0000, 0x127f, 0x2000, 0x007c,
- 0x127e, 0x147e, 0x137e, 0x157e, 0x0c7e, 0x0d7e, 0x70d4, 0xa084,
- 0x4600, 0x8004, 0x2090, 0x0d7f, 0x2049, 0x49f8, 0xad80, 0x0011,
- 0x20a0, 0xb284, 0x0100, 0x0040, 0x4a1b, 0x2001, 0x4e04, 0x2004,
- 0xd0ec, 0x0040, 0x4a17, 0x2099, 0x0031, 0x0078, 0x4a1d, 0x2099,
- 0x0032, 0x0078, 0x4a1d, 0x2099, 0x0031, 0x700c, 0xa084, 0x03ff,
- 0x682a, 0x7007, 0x0008, 0x7007, 0x0002, 0x7003, 0x0001, 0x0040,
- 0x4a2c, 0x8000, 0x80ac, 0x53a5, 0x700c, 0xa084, 0x03ff, 0x0040,
- 0x4a38, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x4a33,
- 0x0c7f, 0x2049, 0x0000, 0x7003, 0x0000, 0x157f, 0x137f, 0x147f,
- 0x127f, 0x2000, 0x007c, 0x2091, 0x8000, 0x2091, 0x6000, 0x78ac,
- 0xa005, 0x00c0, 0x4a5a, 0x7974, 0x70d0, 0xa106, 0x00c0, 0x4a5a,
- 0x781c, 0xa005, 0x0040, 0x4a5a, 0x781f, 0x0000, 0x0068, 0x4a5a,
- 0x2091, 0x4080, 0x7830, 0x8001, 0x7832, 0x00c0, 0x4ae2, 0x7834,
- 0x7832, 0x7810, 0xd0ec, 0x00c0, 0x4adb, 0x2061, 0x73c0, 0x2069,
- 0x4e80, 0xc7fd, 0x68d0, 0xa005, 0x0040, 0x4a74, 0x8001, 0x68d2,
- 0x00c0, 0x4a74, 0x1078, 0x4cb0, 0x6800, 0xa084, 0x000f, 0x0040,
- 0x4a89, 0xa086, 0x0001, 0x0040, 0x4a89, 0x6844, 0xa00d, 0x0040,
- 0x4a89, 0x2104, 0xa005, 0x0040, 0x4a89, 0x8001, 0x200a, 0x0040,
- 0x4c23, 0x6814, 0xa005, 0x0040, 0x4aae, 0x8001, 0x6816, 0x00c0,
- 0x4aae, 0x68a7, 0x0001, 0x0f7e, 0xd7fc, 0x00c0, 0x4aa3, 0x7810,
- 0xd0ec, 0x0040, 0x4a9f, 0x2079, 0x0100, 0x0078, 0x4aa5, 0x2079,
- 0x0200, 0x0078, 0x4aa5, 0x2079, 0x0100, 0x1078, 0x4383, 0x0f7f,
- 0x6864, 0xa005, 0x0040, 0x4aae, 0x1078, 0x2628, 0x6880, 0xa005,
- 0x0040, 0x4abb, 0x8001, 0x6882, 0x00c0, 0x4abb, 0x6867, 0x0000,
- 0x68d4, 0xc0dd, 0x68d6, 0x68d4, 0xd0fc, 0x0040, 0x4ad8, 0xc0fc,
- 0x68d6, 0x20a9, 0x0200, 0x6034, 0xa005, 0x0040, 0x4ad4, 0x8001,
- 0x6036, 0x68d4, 0xc0fd, 0x68d6, 0x00c0, 0x4ad4, 0x6010, 0xa005,
- 0x0040, 0x4ad4, 0x1078, 0x2628, 0xace0, 0x0010, 0x00f0, 0x4ac3,
- 0xd7fc, 0x0040, 0x4ae2, 0x2061, 0x53c0, 0x2069, 0x4e40, 0xc7fc,
- 0x0078, 0x4a6a, 0x1078, 0x4b1e, 0x7838, 0x8001, 0x783a, 0x00c0,
- 0x4b04, 0x783c, 0x783a, 0x2061, 0x53c0, 0x2069, 0x4e40, 0xc7fc,
- 0x680c, 0xa005, 0x0040, 0x4af6, 0x1078, 0x4b88, 0xd7fc, 0x00c0,
- 0x4b04, 0x7810, 0xd0ec, 0x00c0, 0x4b04, 0x2061, 0x73c0, 0x2069,
- 0x4e80, 0xc7fd, 0x0078, 0x4af0, 0x7814, 0xd0e4, 0x00c0, 0x4b08,
- 0x7810, 0xd0cc, 0x0040, 0x4b1b, 0xd0ac, 0x00c0, 0x4b14, 0xd0a4,
- 0x0040, 0x4b1b, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x0068, 0x4b1a,
- 0x1078, 0x2395, 0x007c, 0x2091, 0x8001, 0x007c, 0x7840, 0x8001,
- 0x7842, 0x00c0, 0x4b87, 0x7844, 0x7842, 0x2069, 0x4e40, 0xc7fc,
- 0x7810, 0x2079, 0x0200, 0xd0ec, 0x0040, 0x4b30, 0x2079, 0x0100,
- 0x68d8, 0xa005, 0x0040, 0x4b3c, 0x7de0, 0xa504, 0x00c0, 0x4b3c,
- 0x68da, 0x68d4, 0xc0bc, 0x68d6, 0x2079, 0x4e00, 0x6810, 0xa005,
- 0x00c0, 0x4b44, 0x2001, 0x0101, 0x8001, 0x6812, 0xd7fc, 0x0040,
- 0x4b4d, 0xa080, 0x94d0, 0x0078, 0x4b4f, 0xa080, 0x93c0, 0x2040,
- 0x2004, 0xa065, 0x0040, 0x4b79, 0x6024, 0xa005, 0x0040, 0x4b75,
- 0x8001, 0x6026, 0x00c0, 0x4b75, 0x6800, 0xa005, 0x0040, 0x4b68,
- 0x684c, 0xac06, 0x00c0, 0x4b68, 0x1078, 0x4c23, 0x0078, 0x4b79,
- 0x6864, 0xa005, 0x0040, 0x4b70, 0x6027, 0x0001, 0x0078, 0x4b75,
- 0x1078, 0x4bd6, 0x2804, 0x0078, 0x4b51, 0x6000, 0x2c40, 0x0078,
- 0x4b51, 0xd7fc, 0x00c0, 0x4b87, 0x7810, 0xd0ec, 0x00c0, 0x4b87,
- 0x2069, 0x4e80, 0xc7fd, 0x2079, 0x0100, 0x0078, 0x4b30, 0x007c,
- 0x2009, 0x0000, 0x20a9, 0x0200, 0x6008, 0xd09c, 0x0040, 0x4bc2,
- 0x6024, 0xa005, 0x0040, 0x4b98, 0x8001, 0x6026, 0x0078, 0x4bc0,
- 0x6008, 0xc09c, 0xd084, 0x00c0, 0x4ba0, 0xd0ac, 0x0040, 0x4bba,
- 0x600a, 0x6004, 0xa005, 0x0040, 0x4bc2, 0x0d7e, 0x0c7e, 0x017e,
- 0x2068, 0x6010, 0x8001, 0x6012, 0x1078, 0x3dd0, 0x2d00, 0x2c68,
- 0x2060, 0x1078, 0x1e5b, 0x1078, 0x201d, 0x017f, 0x0c7f, 0x0d7f,
- 0x0078, 0x4bc2, 0xc0bd, 0x600a, 0xa18d, 0x0001, 0x0078, 0x4bc2,
- 0xa18d, 0x0100, 0xace0, 0x0010, 0x00f0, 0x4b8c, 0xa184, 0x0001,
- 0x0040, 0x4bd1, 0xa18c, 0xfffe, 0x690e, 0x1078, 0x2628, 0x0078,
- 0x4bd2, 0x690e, 0x007c, 0x00c0, 0x4bd2, 0x786c, 0x2c00, 0x687e,
- 0x6714, 0x6f76, 0x6017, 0x0000, 0x602b, 0x0000, 0x601b, 0x0006,
- 0x60b4, 0xa084, 0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff, 0xa085,
- 0x0060, 0x6022, 0x6000, 0x2042, 0x1078, 0x1de4, 0x6818, 0xa005,
- 0x0040, 0x4bf4, 0x8001, 0x681a, 0x6808, 0xc0a4, 0x680a, 0x6810,
- 0x7908, 0x8109, 0x790a, 0x8001, 0x00d0, 0x4c00, 0x1078, 0x296b,
- 0x6812, 0x00c0, 0x4c06, 0x7910, 0xc1a5, 0x7912, 0x602f, 0x0000,
- 0x6033, 0x0000, 0x2c68, 0x1078, 0x202c, 0xd7fc, 0x00c0, 0x4c14,
- 0x2069, 0x4e40, 0x0078, 0x4c16, 0x2069, 0x4e80, 0x6910, 0xa184,
- 0x0100, 0x2001, 0x0006, 0x00c0, 0x4c20, 0x697a, 0x2001, 0x0004,
- 0x1078, 0x261c, 0x007c, 0x0d7e, 0x694c, 0x2160, 0xd7fc, 0x00c0,
- 0x4c35, 0x7810, 0xd0ec, 0x0040, 0x4c31, 0x2069, 0x0100, 0x0078,
- 0x4c37, 0x2069, 0x0200, 0x0078, 0x4c37, 0x2069, 0x0100, 0x1078,
- 0x28df, 0x601b, 0x0006, 0x6858, 0xa084, 0x3f00, 0x601e, 0x6020,
- 0xa084, 0x00ff, 0xa085, 0x0048, 0x6022, 0x602f, 0x0000, 0x6033,
- 0x0000, 0x6808, 0xa084, 0xfffd, 0x680a, 0x6830, 0xd0b4, 0x0040,
- 0x4c69, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, 0xd094, 0x0040,
- 0x4c5b, 0x00f0, 0x4c55, 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848,
- 0xd084, 0x0040, 0x4c65, 0x00f0, 0x4c5f, 0x20a9, 0x00fa, 0x00f0,
- 0x4c67, 0x681b, 0x0047, 0x0d7f, 0x6867, 0x0007, 0x007c, 0x2079,
- 0x4e00, 0x1078, 0x4ca3, 0x1078, 0x4c89, 0x1078, 0x4c96, 0x2009,
- 0x0002, 0x2069, 0x4e80, 0x680f, 0x0000, 0x6813, 0x0000, 0x6817,
- 0x0000, 0x8109, 0x0040, 0x4c88, 0x2069, 0x4e40, 0x0078, 0x4c7b,
- 0x007c, 0x7810, 0xd0ec, 0x0040, 0x4c91, 0x2019, 0x00cc, 0x0078,
- 0x4c93, 0x2019, 0x007b, 0x7b3a, 0x7b3e, 0x007c, 0x7814, 0xd0e4,
- 0x00c0, 0x4c9e, 0x2019, 0x0040, 0x0078, 0x4ca0, 0x2019, 0x0026,
- 0x7b42, 0x7b46, 0x007c, 0x7814, 0xd0e4, 0x00c0, 0x4cab, 0x2019,
- 0x3f94, 0x0078, 0x4cad, 0x2019, 0x2624, 0x7b32, 0x7b36, 0x007c,
- 0x6a50, 0xa285, 0x0000, 0x0040, 0x4cdc, 0x6954, 0x6bc0, 0xa300,
- 0x0c7e, 0x2164, 0x6304, 0x83ff, 0x00c0, 0x4cc8, 0x8211, 0x0040,
- 0x4ccc, 0x8108, 0xa11a, 0x0048, 0x4cb9, 0x69c0, 0x0078, 0x4cb9,
- 0x68d3, 0x000a, 0x0c7f, 0x007c, 0x6950, 0x6ac0, 0x2264, 0x602b,
- 0x0000, 0x602f, 0x0000, 0x6008, 0xc0b5, 0x600a, 0x8210, 0x8109,
- 0x00c0, 0x4cce, 0x6952, 0x0c7f, 0x007c, 0x00e0, 0x4cdd, 0x2091,
- 0x6000, 0x00e0, 0x4ce1, 0x2091, 0x6000, 0x70ec, 0xd0dc, 0x00c0,
- 0x4cee, 0xd0d4, 0x0040, 0x4d17, 0x0078, 0x4d1a, 0x2008, 0x7810,
- 0xd0ec, 0x0040, 0x4d01, 0xd1c4, 0x00c0, 0x4d39, 0x7814, 0xc0c5,
- 0x7816, 0x7810, 0xc0f5, 0x7812, 0xd0ec, 0x0040, 0x4d35, 0x0078,
- 0x4d31, 0xae8e, 0x0100, 0x0040, 0x4d0e, 0x7814, 0xc0f5, 0xc0c5,
- 0x7816, 0xd0d4, 0x00c0, 0x4d35, 0x0078, 0x4d31, 0x7814, 0xc0fd,
- 0xc0c5, 0x7816, 0xd0d4, 0x00c0, 0x4d35, 0x0078, 0x4d31, 0xd0e4,
- 0x0040, 0x4d37, 0x00e0, 0x4d1a, 0x2091, 0x6000, 0x2009, 0x000c,
- 0x00e0, 0x4d20, 0x2091, 0x6000, 0x8109, 0x00c0, 0x4d20, 0x70e4,
- 0xa084, 0x01ff, 0xa086, 0x01ff, 0x00c0, 0x4d31, 0x70ec, 0x0078,
- 0x4cee, 0x7804, 0xd08c, 0x0040, 0x4d37, 0x681f, 0x000c, 0x70a0,
- 0x70a2, 0x007c, 0x205b
+ 0x0d7f, 0x7e20, 0xb284, 0x0100, 0x00c0, 0x494f, 0x7e24, 0xa6b5,
+ 0x000c, 0x681c, 0xd0ac, 0x00c0, 0x495a, 0xc685, 0x7003, 0x0000,
+ 0x7007, 0x0004, 0x6828, 0x2050, 0x2d60, 0x6004, 0xa0bc, 0x000f,
+ 0xa7b8, 0x46f2, 0x273c, 0x87fb, 0x00c0, 0x4970, 0x0048, 0x496a,
+ 0x1078, 0x29b2, 0x689c, 0xa065, 0x0040, 0x4974, 0x0078, 0x495d,
+ 0x1078, 0x49f2, 0x00c0, 0x4970, 0x127f, 0x2000, 0x007c, 0x127e,
+ 0x007e, 0x017e, 0x0d7e, 0x70d4, 0xa084, 0x4600, 0x8004, 0x007e,
+ 0x2090, 0x007f, 0x7e20, 0xb284, 0x0100, 0x00c0, 0x4988, 0x7e24,
+ 0x0d7f, 0x037f, 0x047f, 0xa6b5, 0x000c, 0x681c, 0xd0b4, 0x0040,
+ 0x4996, 0xc685, 0x7003, 0x0000, 0x7007, 0x0004, 0x2049, 0x4977,
+ 0x6828, 0xa055, 0x0d7e, 0x0040, 0x49ee, 0x2d70, 0x2e60, 0x7004,
+ 0xa0bc, 0x000f, 0xa7b8, 0x46f2, 0x273c, 0x87fb, 0x00c0, 0x49b3,
+ 0x0048, 0x49ac, 0x1078, 0x29b2, 0x709c, 0xa075, 0x2060, 0x0040,
+ 0x49ee, 0x0078, 0x499f, 0x2704, 0xae68, 0x6808, 0xa422, 0x680c,
+ 0xa31b, 0x0048, 0x49cc, 0x8a51, 0x00c0, 0x49c0, 0x1078, 0x29b2,
+ 0x8738, 0x2704, 0xa005, 0x00c0, 0x49b4, 0x709c, 0xa075, 0x2060,
+ 0x0040, 0x49ee, 0x0078, 0x499f, 0x8422, 0x8420, 0x831a, 0xa399,
+ 0x0000, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, 0x00c8,
+ 0x49db, 0x1078, 0x29b2, 0xb284, 0x0100, 0x0040, 0x49e9, 0x2001,
+ 0x4f04, 0x2004, 0xd0ec, 0x00c0, 0x49e9, 0x2071, 0x0050, 0x0078,
+ 0x49eb, 0x2071, 0x0020, 0x0d7f, 0x0078, 0x48fc, 0x0d7f, 0x127f,
+ 0x2000, 0x007c, 0x7008, 0x007e, 0xa084, 0x01e0, 0x007f, 0x0040,
+ 0x49fb, 0xa006, 0x007c, 0xa084, 0x0003, 0xa086, 0x0003, 0x00c0,
+ 0x4a02, 0x007c, 0x2704, 0xac78, 0x7800, 0x701a, 0x7804, 0x701e,
+ 0x7808, 0x7012, 0x780c, 0x7016, 0x6004, 0xd09c, 0x0040, 0x4a14,
+ 0x7810, 0x7022, 0x7814, 0x7026, 0x7602, 0x7004, 0xa084, 0x0010,
+ 0xc085, 0x7006, 0x2079, 0x4f00, 0x8738, 0x8a51, 0x0040, 0x4a40,
+ 0x2704, 0xa005, 0x00c0, 0x4a32, 0x609c, 0xa005, 0x0040, 0x4a41,
+ 0x2060, 0x6004, 0xa084, 0x000f, 0xa080, 0x46f2, 0x203c, 0x87fb,
+ 0x1040, 0x29b2, 0x7008, 0x007e, 0xa084, 0x01e0, 0x007f, 0x0040,
+ 0x4a3c, 0xa006, 0x0078, 0x4a41, 0xa084, 0x0003, 0xa086, 0x0003,
+ 0x007c, 0x2051, 0x0000, 0x007c, 0x127e, 0x007e, 0x0d7e, 0x70d4,
+ 0xa084, 0x4600, 0x8004, 0x2090, 0x0d7f, 0x087f, 0x7108, 0xa184,
+ 0x0003, 0x00c0, 0x4a59, 0x6828, 0xa005, 0x0040, 0x4a69, 0x0078,
+ 0x4602, 0x7108, 0xd1fc, 0x0040, 0x4a61, 0x1078, 0x47ed, 0x0078,
+ 0x4a4e, 0x7007, 0x0010, 0x7108, 0xd1fc, 0x0040, 0x4a63, 0x1078,
+ 0x47ed, 0x7008, 0xa086, 0x0008, 0x00c0, 0x4a4e, 0x7000, 0xa005,
+ 0x00c0, 0x4a4e, 0x7003, 0x0000, 0x2049, 0x0000, 0x007e, 0x7804,
+ 0xd0cc, 0x0040, 0x4a7d, 0x1078, 0x4acc, 0x007f, 0x127f, 0x2000,
+ 0x007c, 0x127e, 0x147e, 0x137e, 0x157e, 0x0c7e, 0x0d7e, 0x70d4,
+ 0xa084, 0x4600, 0x8004, 0x2090, 0x0d7f, 0x2049, 0x4a81, 0xad80,
+ 0x0011, 0x20a0, 0xb284, 0x0100, 0x0040, 0x4aa4, 0x2001, 0x4f04,
+ 0x2004, 0xd0ec, 0x0040, 0x4aa0, 0x2099, 0x0031, 0x0078, 0x4aa6,
+ 0x2099, 0x0032, 0x0078, 0x4aa6, 0x2099, 0x0031, 0x700c, 0xa084,
+ 0x03ff, 0x682a, 0x7007, 0x0008, 0x7007, 0x0002, 0x7003, 0x0001,
+ 0x0040, 0x4ab5, 0x8000, 0x80ac, 0x53a5, 0x700c, 0xa084, 0x03ff,
+ 0x0040, 0x4ac1, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0,
+ 0x4abc, 0x0c7f, 0x2049, 0x0000, 0x7003, 0x0000, 0x157f, 0x137f,
+ 0x147f, 0x127f, 0x2000, 0x007c, 0x6814, 0xd0fc, 0x0040, 0x4b11,
+ 0x7000, 0xd084, 0x0040, 0x4b11, 0x7e24, 0xa6b5, 0x0004, 0x7007,
+ 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x4ad9, 0x7118, 0x017e,
+ 0x711c, 0x017e, 0x7120, 0x017e, 0x7124, 0x017e, 0xa00e, 0x711a,
+ 0x701f, 0x3fff, 0x7122, 0x7126, 0x7013, 0x0004, 0x7116, 0x7602,
+ 0x7007, 0x0001, 0x2001, 0xffff, 0x2009, 0x0031, 0x200a, 0x200a,
+ 0x7108, 0x7008, 0xa106, 0x00c0, 0x4af8, 0xd1fc, 0x0040, 0x4af8,
+ 0x027f, 0x7226, 0x027f, 0x7222, 0x027f, 0x721e, 0x027f, 0x721a,
+ 0x7007, 0x0002, 0x7008, 0xa086, 0x0008, 0x0040, 0x4b11, 0x0078,
+ 0x4830, 0x7007, 0x0004, 0x7003, 0x0000, 0x007c, 0x2091, 0x8000,
+ 0x2091, 0x6000, 0x78ac, 0xa005, 0x00c0, 0x4b2d, 0x7974, 0x70d0,
+ 0xa106, 0x00c0, 0x4b2d, 0x781c, 0xa005, 0x0040, 0x4b2d, 0x781f,
+ 0x0000, 0x0068, 0x4b2d, 0x2091, 0x4080, 0x7830, 0x8001, 0x7832,
+ 0x00c0, 0x4bb5, 0x7834, 0x7832, 0x7810, 0xd0ec, 0x00c0, 0x4bae,
+ 0x2061, 0x74c0, 0x2069, 0x4f80, 0xc7fd, 0x68d0, 0xa005, 0x0040,
+ 0x4b47, 0x8001, 0x68d2, 0x00c0, 0x4b47, 0x1078, 0x4d83, 0x6800,
+ 0xa084, 0x000f, 0x0040, 0x4b5c, 0xa086, 0x0001, 0x0040, 0x4b5c,
+ 0x6844, 0xa00d, 0x0040, 0x4b5c, 0x2104, 0xa005, 0x0040, 0x4b5c,
+ 0x8001, 0x200a, 0x0040, 0x4cf6, 0x6814, 0xa005, 0x0040, 0x4b81,
+ 0x8001, 0x6816, 0x00c0, 0x4b81, 0x68a7, 0x0001, 0x0f7e, 0xd7fc,
+ 0x00c0, 0x4b76, 0x7810, 0xd0ec, 0x0040, 0x4b72, 0x2079, 0x0100,
+ 0x0078, 0x4b78, 0x2079, 0x0200, 0x0078, 0x4b78, 0x2079, 0x0100,
+ 0x1078, 0x43d3, 0x0f7f, 0x6864, 0xa005, 0x0040, 0x4b81, 0x1078,
+ 0x266f, 0x6880, 0xa005, 0x0040, 0x4b8e, 0x8001, 0x6882, 0x00c0,
+ 0x4b8e, 0x6867, 0x0000, 0x68d4, 0xc0dd, 0x68d6, 0x68d4, 0xd0fc,
+ 0x0040, 0x4bab, 0xc0fc, 0x68d6, 0x20a9, 0x0200, 0x6034, 0xa005,
+ 0x0040, 0x4ba7, 0x8001, 0x6036, 0x68d4, 0xc0fd, 0x68d6, 0x00c0,
+ 0x4ba7, 0x6010, 0xa005, 0x0040, 0x4ba7, 0x1078, 0x266f, 0xace0,
+ 0x0010, 0x00f0, 0x4b96, 0xd7fc, 0x0040, 0x4bb5, 0x2061, 0x54c0,
+ 0x2069, 0x4f40, 0xc7fc, 0x0078, 0x4b3d, 0x1078, 0x4bf1, 0x7838,
+ 0x8001, 0x783a, 0x00c0, 0x4bd7, 0x783c, 0x783a, 0x2061, 0x54c0,
+ 0x2069, 0x4f40, 0xc7fc, 0x680c, 0xa005, 0x0040, 0x4bc9, 0x1078,
+ 0x4c5b, 0xd7fc, 0x00c0, 0x4bd7, 0x7810, 0xd0ec, 0x00c0, 0x4bd7,
+ 0x2061, 0x74c0, 0x2069, 0x4f80, 0xc7fd, 0x0078, 0x4bc3, 0x7814,
+ 0xd0e4, 0x00c0, 0x4bdb, 0x7810, 0xd0cc, 0x0040, 0x4bee, 0xd0ac,
+ 0x00c0, 0x4be7, 0xd0a4, 0x0040, 0x4bee, 0xc0ad, 0x7812, 0x2091,
+ 0x8001, 0x0068, 0x4bed, 0x1078, 0x23dc, 0x007c, 0x2091, 0x8001,
+ 0x007c, 0x7840, 0x8001, 0x7842, 0x00c0, 0x4c5a, 0x7844, 0x7842,
+ 0x2069, 0x4f40, 0xc7fc, 0x7810, 0x2079, 0x0200, 0xd0ec, 0x0040,
+ 0x4c03, 0x2079, 0x0100, 0x68d8, 0xa005, 0x0040, 0x4c0f, 0x7de0,
+ 0xa504, 0x00c0, 0x4c0f, 0x68da, 0x68d4, 0xc0bc, 0x68d6, 0x2079,
+ 0x4f00, 0x6810, 0xa005, 0x00c0, 0x4c17, 0x2001, 0x0101, 0x8001,
+ 0x6812, 0xd7fc, 0x0040, 0x4c20, 0xa080, 0x95d0, 0x0078, 0x4c22,
+ 0xa080, 0x94c0, 0x2040, 0x2004, 0xa065, 0x0040, 0x4c4c, 0x6024,
+ 0xa005, 0x0040, 0x4c48, 0x8001, 0x6026, 0x00c0, 0x4c48, 0x6800,
+ 0xa005, 0x0040, 0x4c3b, 0x684c, 0xac06, 0x00c0, 0x4c3b, 0x1078,
+ 0x4cf6, 0x0078, 0x4c4c, 0x6864, 0xa005, 0x0040, 0x4c43, 0x6027,
+ 0x0001, 0x0078, 0x4c48, 0x1078, 0x4ca9, 0x2804, 0x0078, 0x4c24,
+ 0x6000, 0x2c40, 0x0078, 0x4c24, 0xd7fc, 0x00c0, 0x4c5a, 0x7810,
+ 0xd0ec, 0x00c0, 0x4c5a, 0x2069, 0x4f80, 0xc7fd, 0x2079, 0x0100,
+ 0x0078, 0x4c03, 0x007c, 0x2009, 0x0000, 0x20a9, 0x0200, 0x6008,
+ 0xd09c, 0x0040, 0x4c95, 0x6024, 0xa005, 0x0040, 0x4c6b, 0x8001,
+ 0x6026, 0x0078, 0x4c93, 0x6008, 0xc09c, 0xd084, 0x00c0, 0x4c73,
+ 0xd0ac, 0x0040, 0x4c8d, 0x600a, 0x6004, 0xa005, 0x0040, 0x4c95,
+ 0x0d7e, 0x0c7e, 0x017e, 0x2068, 0x6010, 0x8001, 0x6012, 0x1078,
+ 0x3e19, 0x2d00, 0x2c68, 0x2060, 0x1078, 0x1ea2, 0x1078, 0x2064,
+ 0x017f, 0x0c7f, 0x0d7f, 0x0078, 0x4c95, 0xc0bd, 0x600a, 0xa18d,
+ 0x0001, 0x0078, 0x4c95, 0xa18d, 0x0100, 0xace0, 0x0010, 0x00f0,
+ 0x4c5f, 0xa184, 0x0001, 0x0040, 0x4ca4, 0xa18c, 0xfffe, 0x690e,
+ 0x1078, 0x266f, 0x0078, 0x4ca5, 0x690e, 0x007c, 0x00c0, 0x4ca5,
+ 0x786c, 0x2c00, 0x687e, 0x6714, 0x6f76, 0x6017, 0x0000, 0x602b,
+ 0x0000, 0x601b, 0x0006, 0x60b4, 0xa084, 0x3f00, 0x601e, 0x6020,
+ 0xa084, 0x00ff, 0xa085, 0x0060, 0x6022, 0x6000, 0x2042, 0x1078,
+ 0x1e2b, 0x6818, 0xa005, 0x0040, 0x4cc7, 0x8001, 0x681a, 0x6808,
+ 0xc0a4, 0x680a, 0x6810, 0x7908, 0x8109, 0x790a, 0x8001, 0x00d0,
+ 0x4cd3, 0x1078, 0x29b2, 0x6812, 0x00c0, 0x4cd9, 0x7910, 0xc1a5,
+ 0x7912, 0x602f, 0x0000, 0x6033, 0x0000, 0x2c68, 0x1078, 0x2073,
+ 0xd7fc, 0x00c0, 0x4ce7, 0x2069, 0x4f40, 0x0078, 0x4ce9, 0x2069,
+ 0x4f80, 0x6910, 0xa184, 0x0100, 0x2001, 0x0006, 0x00c0, 0x4cf3,
+ 0x697a, 0x2001, 0x0004, 0x1078, 0x2663, 0x007c, 0x0d7e, 0x694c,
+ 0x2160, 0xd7fc, 0x00c0, 0x4d08, 0x7810, 0xd0ec, 0x0040, 0x4d04,
+ 0x2069, 0x0100, 0x0078, 0x4d0a, 0x2069, 0x0200, 0x0078, 0x4d0a,
+ 0x2069, 0x0100, 0x1078, 0x2926, 0x601b, 0x0006, 0x6858, 0xa084,
+ 0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff, 0xa085, 0x0048, 0x6022,
+ 0x602f, 0x0000, 0x6033, 0x0000, 0x6808, 0xa084, 0xfffd, 0x680a,
+ 0x6830, 0xd0b4, 0x0040, 0x4d3c, 0x684b, 0x0004, 0x20a9, 0x0014,
+ 0x6848, 0xd094, 0x0040, 0x4d2e, 0x00f0, 0x4d28, 0x684b, 0x0009,
+ 0x20a9, 0x0014, 0x6848, 0xd084, 0x0040, 0x4d38, 0x00f0, 0x4d32,
+ 0x20a9, 0x00fa, 0x00f0, 0x4d3a, 0x681b, 0x0047, 0x0d7f, 0x6867,
+ 0x0007, 0x007c, 0x2079, 0x4f00, 0x1078, 0x4d76, 0x1078, 0x4d5c,
+ 0x1078, 0x4d69, 0x2009, 0x0002, 0x2069, 0x4f80, 0x680f, 0x0000,
+ 0x6813, 0x0000, 0x6817, 0x0000, 0x8109, 0x0040, 0x4d5b, 0x2069,
+ 0x4f40, 0x0078, 0x4d4e, 0x007c, 0x7810, 0xd0ec, 0x0040, 0x4d64,
+ 0x2019, 0x00cc, 0x0078, 0x4d66, 0x2019, 0x007b, 0x7b3a, 0x7b3e,
+ 0x007c, 0x7814, 0xd0e4, 0x00c0, 0x4d71, 0x2019, 0x0040, 0x0078,
+ 0x4d73, 0x2019, 0x0026, 0x7b42, 0x7b46, 0x007c, 0x7814, 0xd0e4,
+ 0x00c0, 0x4d7e, 0x2019, 0x3f94, 0x0078, 0x4d80, 0x2019, 0x2624,
+ 0x7b32, 0x7b36, 0x007c, 0x6a50, 0xa285, 0x0000, 0x0040, 0x4daf,
+ 0x6954, 0x6bc0, 0xa300, 0x0c7e, 0x2164, 0x6304, 0x83ff, 0x00c0,
+ 0x4d9b, 0x8211, 0x0040, 0x4d9f, 0x8108, 0xa11a, 0x0048, 0x4d8c,
+ 0x69c0, 0x0078, 0x4d8c, 0x68d3, 0x000a, 0x0c7f, 0x007c, 0x6950,
+ 0x6ac0, 0x2264, 0x602b, 0x0000, 0x602f, 0x0000, 0x6008, 0xc0b5,
+ 0x600a, 0x8210, 0x8109, 0x00c0, 0x4da1, 0x6952, 0x0c7f, 0x007c,
+ 0x00e0, 0x4db0, 0x2091, 0x6000, 0x00e0, 0x4db4, 0x2091, 0x6000,
+ 0x70ec, 0xd0dc, 0x00c0, 0x4dc1, 0xd0d4, 0x0040, 0x4dea, 0x0078,
+ 0x4ded, 0x2008, 0x7810, 0xd0ec, 0x0040, 0x4dd4, 0xd1c4, 0x00c0,
+ 0x4e0e, 0x7814, 0xc0c5, 0x7816, 0x7810, 0xc0f5, 0x7812, 0xd0ec,
+ 0x0040, 0x4e0a, 0x0078, 0x4e06, 0xae8e, 0x0100, 0x0040, 0x4de1,
+ 0x7814, 0xc0f5, 0xc0c5, 0x7816, 0xd0d4, 0x00c0, 0x4e0a, 0x0078,
+ 0x4e06, 0x7814, 0xc0fd, 0xc0c5, 0x7816, 0xd0d4, 0x00c0, 0x4e0a,
+ 0x0078, 0x4e06, 0xd0e4, 0x0040, 0x4e0c, 0x00e0, 0x4ded, 0x2091,
+ 0x6000, 0x2009, 0x000c, 0x00e0, 0x4df3, 0x2091, 0x6000, 0x8109,
+ 0x00c0, 0x4df3, 0x70e4, 0xa084, 0x01ff, 0xa086, 0x01ff, 0x00c0,
+ 0x4e04, 0x70ec, 0x0078, 0x4dc1, 0x1078, 0x4e0f, 0x7804, 0xd08c,
+ 0x0040, 0x4e0c, 0x681f, 0x000c, 0x70a0, 0x70a2, 0x007c, 0x7910,
+ 0xd1ec, 0x0040, 0x4e19, 0x7814, 0xc0c4, 0xc1f4, 0x7912, 0x0078,
+ 0x4e2b, 0xae8e, 0x0100, 0x0040, 0x4e25, 0x7814, 0xc0f4, 0xd0fc,
+ 0x00c0, 0x4e2b, 0xc0c4, 0x0078, 0x4e2b, 0x7814, 0xc0fc, 0xd0f4,
+ 0x00c0, 0x4e2b, 0xc0c4, 0x7816, 0x007c, 0x14e3
};
#ifdef UNIQUE_FW_NAME
-static unsigned short fw1280ei_length01 = 0x3d3b;
+static unsigned short fw1280ei_length01 = 0x3e2e;
#else
-static unsigned short risc_code_length01 = 0x3d3b;
+static unsigned short risc_code_length01 = 0x3e2e;
#endif
+
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 4ad28081499..1a4ce1c3947 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -1098,7 +1098,13 @@ qla1280_error_action(struct scsi_cmnd *cmd, enum action action)
static int
qla1280_eh_abort(struct scsi_cmnd * cmd)
{
- return qla1280_error_action(cmd, ABORT_COMMAND);
+ int rc;
+
+ spin_lock_irq(cmd->device->host->host_lock);
+ rc = qla1280_error_action(cmd, ABORT_COMMAND);
+ spin_unlock_irq(cmd->device->host->host_lock);
+
+ return rc;
}
/**************************************************************************
@@ -1108,7 +1114,13 @@ qla1280_eh_abort(struct scsi_cmnd * cmd)
static int
qla1280_eh_device_reset(struct scsi_cmnd *cmd)
{
- return qla1280_error_action(cmd, DEVICE_RESET);
+ int rc;
+
+ spin_lock_irq(cmd->device->host->host_lock);
+ rc = qla1280_error_action(cmd, DEVICE_RESET);
+ spin_unlock_irq(cmd->device->host->host_lock);
+
+ return rc;
}
/**************************************************************************
@@ -1118,7 +1130,13 @@ qla1280_eh_device_reset(struct scsi_cmnd *cmd)
static int
qla1280_eh_bus_reset(struct scsi_cmnd *cmd)
{
- return qla1280_error_action(cmd, BUS_RESET);
+ int rc;
+
+ spin_lock_irq(cmd->device->host->host_lock);
+ rc = qla1280_error_action(cmd, BUS_RESET);
+ spin_unlock_irq(cmd->device->host->host_lock);
+
+ return rc;
}
/**************************************************************************
@@ -1128,7 +1146,13 @@ qla1280_eh_bus_reset(struct scsi_cmnd *cmd)
static int
qla1280_eh_adapter_reset(struct scsi_cmnd *cmd)
{
- return qla1280_error_action(cmd, ADAPTER_RESET);
+ int rc;
+
+ spin_lock_irq(cmd->device->host->host_lock);
+ rc = qla1280_error_action(cmd, ADAPTER_RESET);
+ spin_unlock_irq(cmd->device->host->host_lock);
+
+ return rc;
}
static int
@@ -4038,11 +4062,10 @@ qla1280_status_entry(struct scsi_qla_host *ha, struct response *pkt,
scsi_status, handle);
}
- /* Target busy */
- if (scsi_status & SS_BUSY_CONDITION &&
- scsi_status != SS_RESERVE_CONFLICT) {
- CMD_RESULT(cmd) =
- DID_BUS_BUSY << 16 | (scsi_status & 0xff);
+ /* Target busy or queue full */
+ if ((scsi_status & 0xFF) == SAM_STAT_TASK_SET_FULL ||
+ (scsi_status & 0xFF) == SAM_STAT_BUSY) {
+ CMD_RESULT(cmd) = scsi_status & 0xff;
} else {
/* Save ISP completion status */
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index c4cd4ac414c..329d1a1fa54 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -1063,8 +1063,7 @@ qla2x00_print_scsi_cmd(struct scsi_cmnd * cmd)
return;
printk(" sp flags=0x%x\n", sp->flags);
- printk(" r_start=0x%lx, u_start=0x%lx, f_start=0x%lx, state=%d\n",
- sp->r_start, sp->u_start, sp->f_start, sp->state);
+ printk(" state=%d\n", sp->state);
}
#if defined(QL_DEBUG_ROUTINES)
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 7d47b8d9204..83a32e403e2 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -252,31 +252,12 @@ typedef struct srb {
/* Request state */
uint16_t state;
- /* Timing counts. */
- unsigned long e_start; /* Start of extend timeout */
- unsigned long r_start; /* Start of request */
- unsigned long u_start; /* When sent to RISC */
- unsigned long f_start; /* When placed in FO queue*/
-
/* Single transfer DMA context */
dma_addr_t dma_handle;
uint32_t request_sense_length;
uint8_t *request_sense_ptr;
- int ext_history;
-
- /* Suspend delay */
- int delay;
-
- /* Raw completion info for use by failover ? */
- uint8_t fo_retry_cnt; /* Retry count this request */
- uint8_t err_id; /* error id */
-#define SRB_ERR_PORT 1 /* Request failed -- "port down" */
-#define SRB_ERR_LOOP 2 /* Request failed -- "loop down" */
-#define SRB_ERR_DEVICE 3 /* Request failed -- "device error" */
-#define SRB_ERR_OTHER 4
-
/* SRB magic number */
uint16_t magic;
#define SRB_MAGIC 0x10CB
@@ -2082,23 +2063,8 @@ typedef struct scsi_qla_host {
uint32_t current_outstanding_cmd;
srb_t *status_srb; /* Status continuation entry. */
- unsigned long last_irq_cpu; /* cpu where we got our last irq */
-
uint16_t revision;
uint8_t ports;
- u_long actthreads;
- u_long ipreq_cnt;
- u_long qthreads;
-
- uint32_t total_isr_cnt; /* Interrupt count */
- uint32_t total_isp_aborts; /* controller err cnt */
- uint32_t total_lip_cnt; /* LIP cnt */
- uint32_t total_dev_errs; /* device error cnt */
- uint32_t total_ios; /* IO cnt */
- uint64_t total_bytes; /* xfr byte cnt */
- uint32_t total_mbx_timeout; /* mailbox timeout cnt */
- uint32_t total_loop_resync; /* loop resyn cnt */
- uint32_t dropped_frame_error_cnt;
/* ISP configuration data. */
uint16_t loop_id; /* Host adapter loop id */
@@ -2124,8 +2090,6 @@ typedef struct scsi_qla_host {
#define P2P_LOOP 3
uint8_t marker_needed;
- uint8_t sns_retry_cnt;
- uint8_t mem_err;
uint8_t interrupts_on;
@@ -2138,16 +2102,11 @@ typedef struct scsi_qla_host {
uint16_t nvram_base;
uint16_t loop_reset_delay;
- uint16_t minimum_timeout;
uint8_t retry_count;
uint8_t login_timeout;
uint16_t r_a_tov;
int port_down_retry_count;
- uint8_t loop_down_timeout;
uint8_t mbx_count;
- uint16_t max_probe_luns;
- uint16_t max_luns;
- uint16_t max_targets;
uint16_t last_loop_id;
uint32_t login_retry_count;
@@ -2181,7 +2140,6 @@ typedef struct scsi_qla_host {
uint8_t dpc_active; /* DPC routine is active */
/* Timeout timers. */
- uint8_t queue_restart_timer;
uint8_t loop_down_abort_time; /* port down timer */
atomic_t loop_down_timer; /* loop down timer */
uint8_t link_down_timeout; /* link down timeout */
@@ -2230,18 +2188,6 @@ typedef struct scsi_qla_host {
mbx_cmd_t mc;
- uint8_t *cmdline;
-
- uint32_t failover_type;
- uint32_t failback_delay;
- unsigned long cfg_flags;
-#define CFG_ACTIVE 0 /* CFG during a failover, event update, or ioctl */
-#define CFG_FAILOVER 1 /* CFG during path change */
-
- uint32_t binding_type;
-#define BIND_BY_PORT_NAME 0
-#define BIND_BY_PORT_ID 1
-
/* Basic firmware related information. */
struct qla_board_info *brd_info;
uint16_t fw_major_version;
@@ -2274,12 +2220,6 @@ typedef struct scsi_qla_host {
uint8_t nvram_version;
uint32_t isp_abort_cnt;
- /* Adapter I/O statistics for failover */
- uint64_t IosRequested;
- uint64_t BytesRequested;
- uint64_t IosExecuted;
- uint64_t BytesExecuted;
-
/* Needed for BEACON */
uint16_t beacon_blink_led;
uint16_t beacon_green_on;
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 2efec6c24d6..164866b199e 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -53,27 +53,13 @@ extern void qla2x00_reg_remote_port(scsi_qla_host_t *, fc_port_t *);
*/
extern char qla2x00_version_str[];
-extern int num_hosts;
-extern int apiHBAInstance;
-
-extern struct _qla2x00stats qla2x00_stats;
-extern int ql2xretrycount;
extern int ql2xlogintimeout;
extern int qlport_down_retry;
-extern int ql2xmaxqdepth;
-extern int displayConfig;
extern int ql2xplogiabsentdevice;
extern int ql2xenablezio;
extern int ql2xintrdelaytimer;
extern int ql2xloginretrycount;
-extern int ConfigRequired;
-
-extern int Bind;
-extern int ql2xsuspendcount;
-#if defined(MODULE)
-extern char *ql2xopts;
-#endif
extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *);
extern char *qla2x00_get_fw_version_str(struct scsi_qla_host *, char *);
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 0387005fcb6..7629558eba2 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -85,9 +85,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
atomic_set(&ha->loop_state, LOOP_DOWN);
ha->device_flags = 0;
- ha->sns_retry_cnt = 0;
ha->dpc_flags = 0;
- ha->failback_delay = 0;
ha->flags.management_server_logged_in = 0;
ha->marker_needed = 0;
ha->mbx_flags = 0;
@@ -171,8 +169,6 @@ check_fw_ready_again:
if (wait_time == 0)
rval = QLA_FUNCTION_FAILED;
- if (ha->mem_err)
- restart_risc = 1;
} else if (ha->device_flags & DFLG_NO_CABLE)
/* If no cable, then all is good. */
rval = QLA_SUCCESS;
@@ -1410,13 +1406,8 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
/* Set minimum RATOV to 200 tenths of a second. */
ha->r_a_tov = 200;
- ha->minimum_timeout =
- (ha->login_timeout * ha->retry_count) + nv->port_down_retry_count;
ha->loop_reset_delay = nv->reset_delay;
- /* Will get the value from NVRAM. */
- ha->loop_down_timeout = LOOP_DOWN_TIMEOUT;
-
/* Link Down Timeout = 0:
*
* When Port Down timer expires we will start returning
@@ -1429,18 +1420,13 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
*/
if (nv->link_down_timeout == 0) {
ha->loop_down_abort_time =
- (LOOP_DOWN_TIME - ha->loop_down_timeout);
+ (LOOP_DOWN_TIME - LOOP_DOWN_TIMEOUT);
} else {
ha->link_down_timeout = nv->link_down_timeout;
ha->loop_down_abort_time =
(LOOP_DOWN_TIME - ha->link_down_timeout);
}
- ha->max_luns = MAX_LUNS;
- ha->max_probe_luns = le16_to_cpu(nv->max_luns_per_target);
- if (ha->max_probe_luns == 0)
- ha->max_probe_luns = MIN_LUNS;
-
/*
* Need enough time to try and get the port back.
*/
@@ -1457,16 +1443,6 @@ qla2x00_nvram_config(scsi_qla_host_t *ha)
if (ql2xloginretrycount)
ha->login_retry_count = ql2xloginretrycount;
- ha->binding_type = Bind;
- if (ha->binding_type != BIND_BY_PORT_NAME &&
- ha->binding_type != BIND_BY_PORT_ID) {
- qla_printk(KERN_WARNING, ha,
- "Invalid binding type specified (%d), "
- "defaulting to BIND_BY_PORT_NAME!!!\n", ha->binding_type);
-
- ha->binding_type = BIND_BY_PORT_NAME;
- }
-
icb->lun_enables = __constant_cpu_to_le16(0);
icb->command_resource_count = 0;
icb->immediate_notify_resource_count = 0;
@@ -1578,7 +1554,6 @@ qla2x00_configure_loop(scsi_qla_host_t *ha)
*/
clear_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
clear_bit(RSCN_UPDATE, &ha->dpc_flags);
- ha->mem_err = 0 ;
/* Determine what we need to do */
if (ha->current_topology == ISP_CFG_FL &&
@@ -2707,7 +2682,6 @@ qla2x00_loop_resync(scsi_qla_host_t *ha)
rval = QLA_SUCCESS;
atomic_set(&ha->loop_state, LOOP_UPDATE);
- qla2x00_stats.loop_resync++;
clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags);
if (ha->flags.online) {
if (!(rval = qla2x00_fw_ready(ha))) {
@@ -2786,9 +2760,6 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
if (ha->flags.online) {
ha->flags.online = 0;
clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
- qla2x00_stats.ispAbort++;
- ha->total_isp_aborts++; /* used by ioctl */
- ha->sns_retry_cnt = 0;
qla_printk(KERN_INFO, ha,
"Performing ISP error recovery - ha= %p.\n", ha);
@@ -2810,8 +2781,6 @@ qla2x00_abort_isp(scsi_qla_host_t *ha)
sp = ha->outstanding_cmds[cnt];
if (sp) {
ha->outstanding_cmds[cnt] = NULL;
- if (ha->actthreads)
- ha->actthreads--;
sp->flags = 0;
sp->cmd->result = DID_RESET << 16;
sp->cmd->host_scribble = (unsigned char *)NULL;
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index af964bb3d87..ecaf9f83b2d 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -433,11 +433,8 @@ qla2x00_start_scsi(srb_t *sp)
} else
ha->request_ring_ptr++;
- ha->actthreads++;
- ha->total_ios++;
sp->flags |= SRB_DMA_VALID;
sp->state = SRB_ACTIVE_STATE;
- sp->u_start = jiffies;
/* Set chip new ring index. */
WRT_REG_WORD(ISP_REQ_Q_IN(ha, reg), ha->req_ring_index);
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 6792cfae56e..e7a8b74157a 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -91,9 +91,6 @@ qla2100_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
- ha->last_irq_cpu = _smp_processor_id();
- ha->total_isr_cnt++;
-
if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
(status & MBX_INTERRUPT) && ha->flags.mbox_int) {
spin_lock_irqsave(&ha->mbx_reg_lock, flags);
@@ -200,9 +197,6 @@ qla2300_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
}
spin_unlock_irqrestore(&ha->hardware_lock, flags);
- ha->last_irq_cpu = _smp_processor_id();
- ha->total_isr_cnt++;
-
if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
(status & MBX_INTERRUPT) && ha->flags.mbox_int) {
spin_lock_irqsave(&ha->mbx_reg_lock, flags);
@@ -417,7 +411,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx)
/* Update AEN queue. */
qla2x00_enqueue_aen(ha, MBA_LIP_OCCURRED, NULL);
- ha->total_lip_cnt++;
break;
case MBA_LOOP_UP: /* Loop Up Event */
@@ -485,7 +478,6 @@ qla2x00_async_event(scsi_qla_host_t *ha, uint32_t mbx)
/* Update AEN queue. */
qla2x00_enqueue_aen(ha, MBA_LIP_RESET, NULL);
- ha->total_lip_cnt++;
break;
case MBA_POINT_TO_POINT: /* Point-to-Point */
@@ -695,14 +687,11 @@ qla2x00_process_completed_request(struct scsi_qla_host *ha, uint32_t index)
/* Free outstanding command slot. */
ha->outstanding_cmds[index] = NULL;
- if (ha->actthreads)
- ha->actthreads--;
CMD_COMPL_STATUS(sp->cmd) = 0L;
CMD_SCSI_STATUS(sp->cmd) = 0L;
/* Save ISP completion status */
sp->cmd->result = DID_OK << 16;
- sp->fo_retry_cnt = 0;
qla2x00_sp_compl(ha, sp);
} else {
DEBUG2(printk("scsi(%ld): Invalid ISP SCSI completion handle\n",
@@ -865,9 +854,6 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
return;
}
- if (ha->actthreads)
- ha->actthreads--;
-
comp_status = le16_to_cpu(pkt->comp_status);
/* Mask of reserved bits 12-15, before we examine the scsi status */
scsi_status = le16_to_cpu(pkt->scsi_status) & SS_MASK;
@@ -1026,7 +1012,6 @@ qla2x00_status_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
cp->request_bufflen));
cp->result = DID_BUS_BUSY << 16;
- ha->dropped_frame_error_cnt++;
break;
}
@@ -1233,8 +1218,7 @@ qla2x00_error_entry(scsi_qla_host_t *ha, sts_entry_t *pkt)
if (sp) {
/* Free outstanding command slot. */
ha->outstanding_cmds[pkt->handle] = NULL;
- if (ha->actthreads)
- ha->actthreads--;
+
/* Bad payload or header */
if (pkt->entry_status &
(RF_INV_E_ORDER | RF_INV_E_COUNT |
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 15f6acaca30..eeaec7c50e6 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -219,10 +219,8 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
ha->flags.mbox_int = 0;
clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
- if (ha->mailbox_out[0] != MBS_COMMAND_COMPLETE) {
- qla2x00_stats.mboxerr++;
+ if (ha->mailbox_out[0] != MBS_COMMAND_COMPLETE)
rval = QLA_FUNCTION_FAILED;
- }
/* Load return mailbox registers. */
iptr2 = mcp->mb;
@@ -249,8 +247,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *ha, mbx_cmd_t *mcp)
qla2x00_dump_regs(ha);
#endif
- qla2x00_stats.mboxtout++;
- ha->total_mbx_timeout++;
rval = QLA_FUNCTION_TIMEOUT;
}
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 579448222d6..0b12498b767 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -36,27 +36,12 @@ char qla2x00_version_str[40];
/*
* SRB allocation cache
*/
-char srb_cachep_name[16];
-kmem_cache_t *srb_cachep;
-
-/*
- * Stats for all adpaters.
- */
-struct _qla2x00stats qla2x00_stats;
+static kmem_cache_t *srb_cachep;
/*
* Ioctl related information.
*/
-int num_hosts;
-int apiHBAInstance;
-
-/*
- * Module parameter information and variables
- */
-int ql2xmaxqdepth;
-module_param(ql2xmaxqdepth, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(ql2xmaxqdepth,
- "Maximum queue depth to report for target devices.");
+static int num_hosts;
int ql2xlogintimeout = 20;
module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR);
@@ -69,12 +54,6 @@ MODULE_PARM_DESC(qlport_down_retry,
"Maximum number of command retries to a port that returns"
"a PORT-DOWN status.");
-int ql2xretrycount = 20;
-module_param(ql2xretrycount, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(ql2xretrycount,
- "Maximum number of mid-layer retries allowed for a command. "
- "Default value is 20, ");
-
int ql2xplogiabsentdevice;
module_param(ql2xplogiabsentdevice, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(ql2xplogiabsentdevice,
@@ -95,25 +74,6 @@ MODULE_PARM_DESC(ql2xintrdelaytimer,
"ZIO: Waiting time for Firmware before it generates an "
"interrupt to the host to notify completion of request.");
-int ConfigRequired;
-module_param(ConfigRequired, int, S_IRUGO|S_IRUSR);
-MODULE_PARM_DESC(ConfigRequired,
- "If 1, then only configured devices passed in through the"
- "ql2xopts parameter will be presented to the OS");
-
-int Bind = BIND_BY_PORT_NAME;
-module_param(Bind, int, S_IRUGO|S_IRUSR);
-MODULE_PARM_DESC(Bind,
- "Target persistent binding method: "
- "0 by Portname (default); 1 by PortID; 2 by Nodename. ");
-
-int ql2xsuspendcount = SUSPEND_COUNT;
-module_param(ql2xsuspendcount, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(ql2xsuspendcount,
- "Number of 6-second suspend iterations to perform while a "
- "target returns a <NOT READY> status. Default is 10 "
- "iterations.");
-
int ql2xloginretrycount = 0;
module_param(ql2xloginretrycount, int, S_IRUGO|S_IRUSR);
MODULE_PARM_DESC(ql2xloginretrycount,
@@ -330,7 +290,6 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
sp->fcport = fcport;
sp->cmd = cmd;
sp->flags = 0;
- sp->err_id = 0;
CMD_SP(cmd) = (void *)sp;
cmd->scsi_done = done;
@@ -474,7 +433,6 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *ha)
while ((!atomic_read(&ha->loop_down_timer) &&
atomic_read(&ha->loop_state) == LOOP_DOWN) ||
- test_bit(CFG_ACTIVE, &ha->cfg_flags) ||
atomic_read(&ha->loop_state) != LOOP_READY) {
msleep(1000);
if (time_after_eq(jiffies, loop_timeout)) {
@@ -507,6 +465,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
int ret, i;
unsigned int id, lun;
unsigned long serial;
+ unsigned long flags;
if (!CMD_SP(cmd))
return FAILED;
@@ -518,8 +477,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
serial = cmd->serial_number;
/* Check active list for command command. */
- spin_unlock_irq(ha->host->host_lock);
- spin_lock(&ha->hardware_lock);
+ spin_lock_irqsave(&ha->hardware_lock, flags);
for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) {
sp = ha->outstanding_cmds[i];
@@ -534,7 +492,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
sp->state));
DEBUG3(qla2x00_print_scsi_cmd(cmd);)
- spin_unlock(&ha->hardware_lock);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (qla2x00_abort_command(ha, sp)) {
DEBUG2(printk("%s(%ld): abort_command "
"mbx failed.\n", __func__, ha->host_no));
@@ -543,22 +501,20 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
"mbx success.\n", __func__, ha->host_no));
ret = SUCCESS;
}
- spin_lock(&ha->hardware_lock);
+ spin_lock_irqsave(&ha->hardware_lock, flags);
break;
}
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
/* Wait for the command to be returned. */
if (ret == SUCCESS) {
- spin_unlock(&ha->hardware_lock);
if (qla2x00_eh_wait_on_command(ha, cmd) != QLA_SUCCESS) {
qla_printk(KERN_ERR, ha,
"scsi(%ld:%d:%d): Abort handler timed out -- %lx "
"%x.\n", ha->host_no, id, lun, serial, ret);
}
- spin_lock(&ha->hardware_lock);
}
- spin_lock_irq(ha->host->host_lock);
qla_printk(KERN_INFO, ha,
"scsi(%ld:%d:%d): Abort command issued -- %lx %x.\n", ha->host_no,
@@ -588,6 +544,7 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t)
int status;
srb_t *sp;
struct scsi_cmnd *cmd;
+ unsigned long flags;
status = 0;
@@ -596,11 +553,11 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t)
* array
*/
for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
- spin_lock(&ha->hardware_lock);
+ spin_lock_irqsave(&ha->hardware_lock, flags);
sp = ha->outstanding_cmds[cnt];
if (sp) {
cmd = sp->cmd;
- spin_unlock(&ha->hardware_lock);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
if (cmd->device->id == t) {
if (!qla2x00_eh_wait_on_command(ha, cmd)) {
status = 1;
@@ -608,7 +565,7 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t)
}
}
} else {
- spin_unlock(&ha->hardware_lock);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
}
return (status);
@@ -657,12 +614,8 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
qla_printk(KERN_INFO, ha,
"scsi(%ld:%d:%d): DEVICE RESET ISSUED.\n", ha->host_no, id, lun);
- spin_unlock_irq(ha->host->host_lock);
-
- if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS) {
- spin_lock_irq(ha->host->host_lock);
+ if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS)
goto eh_dev_reset_done;
- }
if (qla2x00_wait_for_loop_ready(ha) == QLA_SUCCESS) {
if (qla2x00_device_reset(ha, fcport) == 0)
@@ -713,8 +666,6 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
"scsi(%ld:%d:%d): DEVICE RESET SUCCEEDED.\n", ha->host_no, id, lun);
eh_dev_reset_done:
- spin_lock_irq(ha->host->host_lock);
-
return ret;
}
@@ -740,6 +691,7 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha)
int status;
srb_t *sp;
struct scsi_cmnd *cmd;
+ unsigned long flags;
status = 1;
@@ -748,17 +700,17 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha)
* array
*/
for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
- spin_lock(&ha->hardware_lock);
+ spin_lock_irqsave(&ha->hardware_lock, flags);
sp = ha->outstanding_cmds[cnt];
if (sp) {
cmd = sp->cmd;
- spin_unlock(&ha->hardware_lock);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
status = qla2x00_eh_wait_on_command(ha, cmd);
if (status == 0)
break;
}
else {
- spin_unlock(&ha->hardware_lock);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
}
return (status);
@@ -803,8 +755,6 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
qla_printk(KERN_INFO, ha,
"scsi(%ld:%d:%d): LOOP RESET ISSUED.\n", ha->host_no, id, lun);
- spin_unlock_irq(ha->host->host_lock);
-
if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS) {
DEBUG2(printk("%s failed:board disabled\n",__func__));
goto eh_bus_reset_done;
@@ -826,8 +776,6 @@ eh_bus_reset_done:
qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__,
(ret == FAILED) ? "failed" : "succeded");
- spin_lock_irq(ha->host->host_lock);
-
return ret;
}
@@ -869,8 +817,6 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
qla_printk(KERN_INFO, ha,
"scsi(%ld:%d:%d): ADAPTER RESET ISSUED.\n", ha->host_no, id, lun);
- spin_unlock_irq(ha->host->host_lock);
-
if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS)
goto eh_host_reset_lock;
@@ -899,8 +845,6 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
ret = SUCCESS;
eh_host_reset_lock:
- spin_lock_irq(ha->host->host_lock);
-
qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__,
(ret == FAILED) ? "failed" : "succeded");
@@ -1148,7 +1092,7 @@ iospace_error_exit:
*/
int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
{
- int ret;
+ int ret = -ENODEV;
device_reg_t __iomem *reg;
struct Scsi_Host *host;
scsi_qla_host_t *ha;
@@ -1159,7 +1103,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
fc_port_t *fcport;
if (pci_enable_device(pdev))
- return -1;
+ goto probe_out;
host = scsi_host_alloc(&qla2x00_driver_template,
sizeof(scsi_qla_host_t));
@@ -1181,9 +1125,8 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
/* Configure PCI I/O space */
ret = qla2x00_iospace_config(ha);
- if (ret != 0) {
- goto probe_alloc_failed;
- }
+ if (ret)
+ goto probe_failed;
/* Sanitize the information from PCI BIOS. */
host->irq = pdev->irq;
@@ -1194,34 +1137,24 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
spin_lock_init(&ha->hardware_lock);
- /* 4.23 Initialize /proc/scsi/qla2x00 counters */
- ha->actthreads = 0;
- ha->qthreads = 0;
- ha->total_isr_cnt = 0;
- ha->total_isp_aborts = 0;
- ha->total_lip_cnt = 0;
- ha->total_dev_errs = 0;
- ha->total_ios = 0;
- ha->total_bytes = 0;
-
ha->prev_topology = 0;
ha->ports = MAX_BUSES;
if (IS_QLA2100(ha)) {
- ha->max_targets = MAX_TARGETS_2100;
+ host->max_id = MAX_TARGETS_2100;
ha->mbx_count = MAILBOX_REGISTER_COUNT_2100;
ha->request_q_length = REQUEST_ENTRY_CNT_2100;
ha->response_q_length = RESPONSE_ENTRY_CNT_2100;
ha->last_loop_id = SNS_LAST_LOOP_ID_2100;
host->sg_tablesize = 32;
} else if (IS_QLA2200(ha)) {
- ha->max_targets = MAX_TARGETS_2200;
+ host->max_id = MAX_TARGETS_2200;
ha->mbx_count = MAILBOX_REGISTER_COUNT;
ha->request_q_length = REQUEST_ENTRY_CNT_2200;
ha->response_q_length = RESPONSE_ENTRY_CNT_2100;
ha->last_loop_id = SNS_LAST_LOOP_ID_2100;
} else /*if (IS_QLA2300(ha))*/ {
- ha->max_targets = MAX_TARGETS_2200;
+ host->max_id = MAX_TARGETS_2200;
ha->mbx_count = MAILBOX_REGISTER_COUNT;
ha->request_q_length = REQUEST_ENTRY_CNT_2200;
ha->response_q_length = RESPONSE_ENTRY_CNT_2300;
@@ -1256,23 +1189,10 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
qla_printk(KERN_WARNING, ha,
"[ERROR] Failed to allocate memory for adapter\n");
- goto probe_alloc_failed;
+ ret = -ENOMEM;
+ goto probe_failed;
}
- pci_set_drvdata(pdev, ha);
- host->this_id = 255;
- host->cmd_per_lun = 3;
- host->unique_id = ha->instance;
- host->max_cmd_len = MAX_CMDSZ;
- host->max_channel = ha->ports - 1;
- host->max_id = ha->max_targets;
- host->max_lun = ha->max_luns;
- host->transportt = qla2xxx_transport_template;
- if (scsi_add_host(host, &pdev->dev))
- goto probe_alloc_failed;
-
- qla2x00_alloc_sysfs_attr(ha);
-
if (qla2x00_initialize_adapter(ha) &&
!(ha->device_flags & DFLG_NO_CABLE)) {
@@ -1283,11 +1203,10 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
"Adapter flags %x.\n",
ha->host_no, ha->device_flags));
+ ret = -ENODEV;
goto probe_failed;
}
- qla2x00_init_host_attr(ha);
-
/*
* Startup the kernel thread for this host adapter
*/
@@ -1297,17 +1216,26 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
qla_printk(KERN_WARNING, ha,
"Unable to start DPC thread!\n");
+ ret = -ENODEV;
goto probe_failed;
}
wait_for_completion(&ha->dpc_inited);
+ host->this_id = 255;
+ host->cmd_per_lun = 3;
+ host->unique_id = ha->instance;
+ host->max_cmd_len = MAX_CMDSZ;
+ host->max_channel = ha->ports - 1;
+ host->max_lun = MAX_LUNS;
+ host->transportt = qla2xxx_transport_template;
+
if (IS_QLA2100(ha) || IS_QLA2200(ha))
ret = request_irq(host->irq, qla2100_intr_handler,
SA_INTERRUPT|SA_SHIRQ, ha->brd_info->drv_name, ha);
else
ret = request_irq(host->irq, qla2300_intr_handler,
SA_INTERRUPT|SA_SHIRQ, ha->brd_info->drv_name, ha);
- if (ret != 0) {
+ if (ret) {
qla_printk(KERN_WARNING, ha,
"Failed to reserve interrupt %d already in use.\n",
host->irq);
@@ -1361,9 +1289,18 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
msleep(10);
}
+ pci_set_drvdata(pdev, ha);
ha->flags.init_done = 1;
num_hosts++;
+ ret = scsi_add_host(host, &pdev->dev);
+ if (ret)
+ goto probe_failed;
+
+ qla2x00_alloc_sysfs_attr(ha);
+
+ qla2x00_init_host_attr(ha);
+
qla_printk(KERN_INFO, ha, "\n"
" QLogic Fibre Channel HBA Driver: %s\n"
" QLogic %s - %s\n"
@@ -1382,9 +1319,6 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
probe_failed:
fc_remove_host(ha->host);
- scsi_remove_host(host);
-
-probe_alloc_failed:
qla2x00_free_device(ha);
scsi_host_put(host);
@@ -1392,7 +1326,8 @@ probe_alloc_failed:
probe_disable_device:
pci_disable_device(pdev);
- return -1;
+probe_out:
+ return ret;
}
EXPORT_SYMBOL_GPL(qla2x00_probe_one);
@@ -2336,8 +2271,7 @@ static int __init
qla2x00_module_init(void)
{
/* Allocate cache for SRBs. */
- sprintf(srb_cachep_name, "qla2xxx_srbs");
- srb_cachep = kmem_cache_create(srb_cachep_name, sizeof(srb_t), 0,
+ srb_cachep = kmem_cache_create("qla2xxx_srbs", sizeof(srb_t), 0,
SLAB_HWCACHE_ALIGN, NULL, NULL);
if (srb_cachep == NULL) {
printk(KERN_ERR
@@ -2365,16 +2299,7 @@ qla2x00_module_init(void)
static void __exit
qla2x00_module_exit(void)
{
- /* Free SRBs cache. */
- if (srb_cachep != NULL) {
- if (kmem_cache_destroy(srb_cachep) != 0) {
- printk(KERN_ERR
- "qla2xxx: Unable to free SRB cache...Memory pools "
- "still active?\n");
- }
- srb_cachep = NULL;
- }
-
+ kmem_cache_destroy(srb_cachep);
fc_release_transport(qla2xxx_transport_template);
}
diff --git a/drivers/scsi/qlogicfas.c b/drivers/scsi/qlogicfas.c
index a1adb38f69b..55e698b651d 100644
--- a/drivers/scsi/qlogicfas.c
+++ b/drivers/scsi/qlogicfas.c
@@ -191,8 +191,6 @@ static Scsi_Host_Template qlogicfas_driver_template = {
.queuecommand = qlogicfas408_queuecommand,
.eh_abort_handler = qlogicfas408_abort,
.eh_bus_reset_handler = qlogicfas408_bus_reset,
- .eh_device_reset_handler= qlogicfas408_device_reset,
- .eh_host_reset_handler = qlogicfas408_host_reset,
.bios_param = qlogicfas408_biosparam,
.can_queue = 1,
.this_id = -1,
diff --git a/drivers/scsi/qlogicfas408.c b/drivers/scsi/qlogicfas408.c
index 5b6ce0a88f0..cb75e0b7bae 100644
--- a/drivers/scsi/qlogicfas408.c
+++ b/drivers/scsi/qlogicfas408.c
@@ -511,27 +511,15 @@ int qlogicfas408_abort(Scsi_Cmnd * cmd)
int qlogicfas408_bus_reset(Scsi_Cmnd * cmd)
{
struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd);
- priv->qabort = 2;
- ql_zap(priv);
- return SUCCESS;
-}
-
-/*
- * Reset SCSI host controller
- */
+ unsigned long flags;
-int qlogicfas408_host_reset(Scsi_Cmnd * cmd)
-{
- return FAILED;
-}
+ priv->qabort = 2;
-/*
- * Reset SCSI device
- */
+ spin_lock_irqsave(cmd->device->host->host_lock, flags);
+ ql_zap(priv);
+ spin_unlock_irqrestore(cmd->device->host->host_lock, flags);
-int qlogicfas408_device_reset(Scsi_Cmnd * cmd)
-{
- return FAILED;
+ return SUCCESS;
}
/*
@@ -626,8 +614,6 @@ EXPORT_SYMBOL(qlogicfas408_info);
EXPORT_SYMBOL(qlogicfas408_queuecommand);
EXPORT_SYMBOL(qlogicfas408_abort);
EXPORT_SYMBOL(qlogicfas408_bus_reset);
-EXPORT_SYMBOL(qlogicfas408_device_reset);
-EXPORT_SYMBOL(qlogicfas408_host_reset);
EXPORT_SYMBOL(qlogicfas408_biosparam);
EXPORT_SYMBOL(qlogicfas408_ihandl);
EXPORT_SYMBOL(qlogicfas408_get_chip_type);
diff --git a/drivers/scsi/qlogicfas408.h b/drivers/scsi/qlogicfas408.h
index f01cbd66c22..4b3df200366 100644
--- a/drivers/scsi/qlogicfas408.h
+++ b/drivers/scsi/qlogicfas408.h
@@ -109,8 +109,6 @@ int qlogicfas408_biosparam(struct scsi_device * disk,
sector_t capacity, int ip[]);
int qlogicfas408_abort(Scsi_Cmnd * cmd);
int qlogicfas408_bus_reset(Scsi_Cmnd * cmd);
-int qlogicfas408_host_reset(Scsi_Cmnd * cmd);
-int qlogicfas408_device_reset(Scsi_Cmnd * cmd);
const char *qlogicfas408_info(struct Scsi_Host *host);
int qlogicfas408_get_chip_type(int qbase, int int_type);
void qlogicfas408_setup(int qbase, int id, int int_type);
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
index 69009f853a4..b0403ccd8a2 100644
--- a/drivers/scsi/sata_nv.c
+++ b/drivers/scsi/sata_nv.c
@@ -329,6 +329,8 @@ static void nv_host_stop (struct ata_host_set *host_set)
host->host_desc->disable_hotplug(host_set);
kfree(host);
+
+ ata_host_stop(host_set);
}
static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index 19a13e3590f..5c1d4411457 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -59,6 +59,7 @@ enum {
board_2037x = 0, /* FastTrak S150 TX2plus */
board_20319 = 1, /* FastTrak S150 TX4 */
+ board_20619 = 2, /* FastTrak TX4000 */
PDC_HAS_PATA = (1 << 1), /* PDC20375 has PATA */
@@ -122,6 +123,7 @@ static struct ata_port_operations pdc_ata_ops = {
.scr_write = pdc_sata_scr_write,
.port_start = pdc_port_start,
.port_stop = pdc_port_stop,
+ .host_stop = ata_host_stop,
};
static struct ata_port_info pdc_port_info[] = {
@@ -146,11 +148,24 @@ static struct ata_port_info pdc_port_info[] = {
.udma_mask = 0x7f, /* udma0-6 ; FIXME */
.port_ops = &pdc_ata_ops,
},
+
+ /* board_20619 */
+ {
+ .sht = &pdc_ata_sht,
+ .host_flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST |
+ ATA_FLAG_MMIO | ATA_FLAG_SLAVE_POSS,
+ .pio_mask = 0x1f, /* pio0-4 */
+ .mwdma_mask = 0x07, /* mwdma0-2 */
+ .udma_mask = 0x7f, /* udma0-6 ; FIXME */
+ .port_ops = &pdc_ata_ops,
+ },
};
static struct pci_device_id pdc_ata_pci_tbl[] = {
{ PCI_VENDOR_ID_PROMISE, 0x3371, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_2037x },
+ { PCI_VENDOR_ID_PROMISE, 0x3571, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_2037x },
{ PCI_VENDOR_ID_PROMISE, 0x3373, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_2037x },
{ PCI_VENDOR_ID_PROMISE, 0x3375, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
@@ -169,6 +184,9 @@ static struct pci_device_id pdc_ata_pci_tbl[] = {
{ PCI_VENDOR_ID_PROMISE, 0x3d18, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_20319 },
+ { PCI_VENDOR_ID_PROMISE, 0x6629, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ board_20619 },
+
{ } /* terminate list */
};
@@ -633,6 +651,15 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
case board_2037x:
probe_ent->n_ports = 2;
break;
+ case board_20619:
+ probe_ent->n_ports = 4;
+
+ pdc_ata_setup_port(&probe_ent->port[2], base + 0x300);
+ pdc_ata_setup_port(&probe_ent->port[3], base + 0x380);
+
+ probe_ent->port[2].scr_addr = base + 0x600;
+ probe_ent->port[3].scr_addr = base + 0x700;
+ break;
default:
BUG();
break;
@@ -673,7 +700,7 @@ static void __exit pdc_ata_exit(void)
MODULE_AUTHOR("Jeff Garzik");
-MODULE_DESCRIPTION("Promise SATA TX2/TX4 low-level driver");
+MODULE_DESCRIPTION("Promise ATA TX2/TX4/TX4000 low-level driver");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, pdc_ata_pci_tbl);
MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c
index dfd36210471..1383e8a28d7 100644
--- a/drivers/scsi/sata_qstor.c
+++ b/drivers/scsi/sata_qstor.c
@@ -536,6 +536,8 @@ static void qs_host_stop(struct ata_host_set *host_set)
writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */
writeb(QS_CNFG3_GSRST, mmio_base + QS_HCF_CNFG3); /* global reset */
+
+ ata_host_stop(host_set);
}
static void qs_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index f0489dc302a..49ed557a4b6 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -82,6 +82,7 @@ static struct pci_device_id sil_pci_tbl[] = {
{ 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 },
{ 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
{ 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+ { 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
{ } /* terminate list */
};
@@ -160,6 +161,7 @@ static struct ata_port_operations sil_ops = {
.scr_write = sil_scr_write,
.port_start = ata_port_start,
.port_stop = ata_port_stop,
+ .host_stop = ata_host_stop,
};
static struct ata_port_info sil_port_info[] = {
@@ -430,7 +432,13 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
writeb(cls, mmio_base + SIL_FIFO_R0);
writeb(cls, mmio_base + SIL_FIFO_W0);
writeb(cls, mmio_base + SIL_FIFO_R1);
- writeb(cls, mmio_base + SIL_FIFO_W2);
+ writeb(cls, mmio_base + SIL_FIFO_W1);
+ if (ent->driver_data == sil_3114) {
+ writeb(cls, mmio_base + SIL_FIFO_R2);
+ writeb(cls, mmio_base + SIL_FIFO_W2);
+ writeb(cls, mmio_base + SIL_FIFO_R3);
+ writeb(cls, mmio_base + SIL_FIFO_W3);
+ }
} else
printk(KERN_WARNING DRV_NAME "(%s): cache line size not set. Driver may not function\n",
pci_name(pdev));
diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
index 5105ddd0844..e418b89c6b9 100644
--- a/drivers/scsi/sata_sis.c
+++ b/drivers/scsi/sata_sis.c
@@ -114,6 +114,7 @@ static struct ata_port_operations sis_ops = {
.scr_write = sis_scr_write,
.port_start = ata_port_start,
.port_stop = ata_port_stop,
+ .host_stop = ata_host_stop,
};
static struct ata_port_info sis_port_info = {
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
index 8d1a5d25c05..858e07185db 100644
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -49,7 +49,7 @@
#endif /* CONFIG_PPC_OF */
#define DRV_NAME "sata_svw"
-#define DRV_VERSION "1.05"
+#define DRV_VERSION "1.06"
/* Taskfile registers offsets */
#define K2_SATA_TF_CMD_OFFSET 0x00
@@ -313,6 +313,7 @@ static struct ata_port_operations k2_sata_ops = {
.scr_write = k2_sata_scr_write,
.port_start = ata_port_start,
.port_stop = ata_port_stop,
+ .host_stop = ata_host_stop,
};
static void k2_sata_setup_port(struct ata_ioports *port, unsigned long base)
@@ -343,6 +344,7 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
void *mmio_base;
int pci_dev_busy = 0;
int rc;
+ int i;
if (!printed_version++)
printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
@@ -395,7 +397,7 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
/* Clear a magic bit in SCR1 according to Darwin, those help
* some funky seagate drives (though so far, those were already
- * set by the firmware on the machines I had access to
+ * set by the firmware on the machines I had access to)
*/
writel(readl(mmio_base + K2_SATA_SICR1_OFFSET) & ~0x00040000,
mmio_base + K2_SATA_SICR1_OFFSET);
@@ -420,11 +422,11 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
probe_ent->mwdma_mask = 0x7;
probe_ent->udma_mask = 0x7f;
- /* We have 4 ports per PCI function */
- k2_sata_setup_port(&probe_ent->port[0], base + 0 * K2_SATA_PORT_OFFSET);
- k2_sata_setup_port(&probe_ent->port[1], base + 1 * K2_SATA_PORT_OFFSET);
- k2_sata_setup_port(&probe_ent->port[2], base + 2 * K2_SATA_PORT_OFFSET);
- k2_sata_setup_port(&probe_ent->port[3], base + 3 * K2_SATA_PORT_OFFSET);
+ /* different controllers have different number of ports - currently 4 or 8 */
+ /* All ports are on the same function. Multi-function device is no
+ * longer available. This should not be seen in any system. */
+ for (i = 0; i < ent->driver_data; i++)
+ k2_sata_setup_port(&probe_ent->port[i], base + i * K2_SATA_PORT_OFFSET);
pci_set_master(pdev);
@@ -444,11 +446,17 @@ err_out:
return rc;
}
-
+/* 0x240 is device ID for Apple K2 device
+ * 0x241 is device ID for Serverworks Frodo4
+ * 0x242 is device ID for Serverworks Frodo8
+ * 0x24a is device ID for BCM5785 (aka HT1000) HT southbridge integrated SATA
+ * controller
+ * */
static struct pci_device_id k2_sata_pci_tbl[] = {
- { 0x1166, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { 0x1166, 0x0241, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { 0x1166, 0x0242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 0x1166, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
+ { 0x1166, 0x0241, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
+ { 0x1166, 0x0242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
+ { 0x1166, 0x024a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
{ }
};
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
index 70118650c46..140cea05de3 100644
--- a/drivers/scsi/sata_sx4.c
+++ b/drivers/scsi/sata_sx4.c
@@ -245,6 +245,8 @@ static void pdc20621_host_stop(struct ata_host_set *host_set)
iounmap(dimm_mmio);
kfree(hpriv);
+
+ ata_host_stop(host_set);
}
static int pdc_port_start(struct ata_port *ap)
diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c
index 0bff4f475f2..a71fb54eebd 100644
--- a/drivers/scsi/sata_uli.c
+++ b/drivers/scsi/sata_uli.c
@@ -113,6 +113,7 @@ static struct ata_port_operations uli_ops = {
.port_start = ata_port_start,
.port_stop = ata_port_stop,
+ .host_stop = ata_host_stop,
};
static struct ata_port_info uli_port_info = {
diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
index 3a783066727..f43183c19a1 100644
--- a/drivers/scsi/sata_via.c
+++ b/drivers/scsi/sata_via.c
@@ -134,6 +134,7 @@ static struct ata_port_operations svia_sata_ops = {
.port_start = ata_port_start,
.port_stop = ata_port_stop,
+ .host_stop = ata_host_stop,
};
static struct ata_port_info svia_port_info = {
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
index 2c28f0ad73c..c5e09dc6f3d 100644
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -21,6 +21,7 @@
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
#include "scsi.h"
#include <scsi/scsi_host.h>
#include <linux/libata.h>
@@ -230,6 +231,7 @@ static struct ata_port_operations vsc_sata_ops = {
.scr_write = vsc_sata_scr_write,
.port_start = ata_port_start,
.port_stop = ata_port_stop,
+ .host_stop = ata_host_stop,
};
static void __devinit vsc_sata_setup_port(struct ata_ioports *port, unsigned long base)
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 184bcaeaf81..1cb5f7d4f27 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -68,6 +68,8 @@
#include "scsi_priv.h"
#include "scsi_logging.h"
+static void scsi_done(struct scsi_cmnd *cmd);
+static int scsi_retry_command(struct scsi_cmnd *cmd);
/*
* Definitions and constants.
@@ -638,10 +640,12 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd)
}
spin_unlock_irqrestore(host->host_lock, flags);
if (rtn) {
- atomic_inc(&cmd->device->iodone_cnt);
- scsi_queue_insert(cmd,
- (rtn == SCSI_MLQUEUE_DEVICE_BUSY) ?
- rtn : SCSI_MLQUEUE_HOST_BUSY);
+ if (scsi_delete_timer(cmd)) {
+ atomic_inc(&cmd->device->iodone_cnt);
+ scsi_queue_insert(cmd,
+ (rtn == SCSI_MLQUEUE_DEVICE_BUSY) ?
+ rtn : SCSI_MLQUEUE_HOST_BUSY);
+ }
SCSI_LOG_MLQUEUE(3,
printk("queuecommand : request rejected\n"));
}
@@ -739,7 +743,7 @@ static DEFINE_PER_CPU(struct list_head, scsi_done_q);
*
* This function is interrupt context safe.
*/
-void scsi_done(struct scsi_cmnd *cmd)
+static void scsi_done(struct scsi_cmnd *cmd)
{
/*
* We don't have to worry about this one timing out any more.
@@ -834,7 +838,7 @@ static void scsi_softirq(struct softirq_action *h)
* level drivers should not become re-entrant as a result of
* this.
*/
-int scsi_retry_command(struct scsi_cmnd *cmd)
+static int scsi_retry_command(struct scsi_cmnd *cmd)
{
/*
* Restore the SCSI command state.
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index e0208886b45..322b5a41a36 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -1783,7 +1783,7 @@ static void __exit scsi_debug_exit(void)
device_initcall(scsi_debug_init);
module_exit(scsi_debug_exit);
-void pseudo_0_release(struct device * dev)
+static void pseudo_0_release(struct device * dev)
{
if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
printk(KERN_INFO "scsi_debug: pseudo_0_release() called\n");
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 2bf1ee2b47b..ceb4e0c99b3 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -434,8 +434,7 @@ static void scsi_eh_times_out(struct scsi_cmnd *scmd)
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd:%p\n", __FUNCTION__,
scmd));
- if (scmd->device->host->eh_action)
- up(scmd->device->host->eh_action);
+ up(scmd->device->host->eh_action);
}
/**
@@ -457,8 +456,7 @@ static void scsi_eh_done(struct scsi_cmnd *scmd)
SCSI_LOG_ERROR_RECOVERY(3, printk("%s scmd: %p result: %x\n",
__FUNCTION__, scmd, scmd->result));
- if (scmd->device->host->eh_action)
- up(scmd->device->host->eh_action);
+ up(scmd->device->host->eh_action);
}
}
@@ -528,10 +526,8 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, int timeout)
* abort a timed out command or not. not sure how
* we should treat them differently anyways.
*/
- spin_lock_irqsave(shost->host_lock, flags);
if (shost->hostt->eh_abort_handler)
shost->hostt->eh_abort_handler(scmd);
- spin_unlock_irqrestore(shost->host_lock, flags);
scmd->request->rq_status = RQ_SCSI_DONE;
scmd->owner = SCSI_OWNER_ERROR_HANDLER;
@@ -737,11 +733,8 @@ static int scsi_eh_get_sense(struct list_head *work_q,
**/
static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
{
- unsigned long flags;
- int rtn = FAILED;
-
if (!scmd->device->host->hostt->eh_abort_handler)
- return rtn;
+ return FAILED;
/*
* scsi_done was called just after the command timed out and before
@@ -752,11 +745,7 @@ static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
scmd->owner = SCSI_OWNER_LOWLEVEL;
- spin_lock_irqsave(scmd->device->host->host_lock, flags);
- rtn = scmd->device->host->hostt->eh_abort_handler(scmd);
- spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
-
- return rtn;
+ return scmd->device->host->hostt->eh_abort_handler(scmd);
}
/**
@@ -770,6 +759,7 @@ static int scsi_eh_tur(struct scsi_cmnd *scmd)
{
static unsigned char tur_command[6] = {TEST_UNIT_READY, 0, 0, 0, 0, 0};
int retry_cnt = 1, rtn;
+ int saved_result;
retry_tur:
memcpy(scmd->cmnd, tur_command, sizeof(tur_command));
@@ -780,6 +770,7 @@ retry_tur:
*/
memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer));
+ saved_result = scmd->result;
scmd->request_buffer = NULL;
scmd->request_bufflen = 0;
scmd->use_sg = 0;
@@ -794,6 +785,7 @@ retry_tur:
* the original request, so let's restore the original data. (db)
*/
scsi_setup_cmd_retry(scmd);
+ scmd->result = saved_result;
/*
* hey, we are done. let's look to see what happened.
@@ -865,17 +857,14 @@ static int scsi_eh_abort_cmds(struct list_head *work_q,
**/
static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd)
{
- unsigned long flags;
- int rtn = FAILED;
+ int rtn;
if (!scmd->device->host->hostt->eh_device_reset_handler)
- return rtn;
+ return FAILED;
scmd->owner = SCSI_OWNER_LOWLEVEL;
- spin_lock_irqsave(scmd->device->host->host_lock, flags);
rtn = scmd->device->host->hostt->eh_device_reset_handler(scmd);
- spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
if (rtn == SUCCESS) {
scmd->device->was_reset = 1;
@@ -896,6 +885,7 @@ static int scsi_eh_try_stu(struct scsi_cmnd *scmd)
{
static unsigned char stu_command[6] = {START_STOP, 0, 0, 0, 1, 0};
int rtn;
+ int saved_result;
if (!scmd->device->allow_restart)
return 1;
@@ -908,6 +898,7 @@ static int scsi_eh_try_stu(struct scsi_cmnd *scmd)
*/
memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer));
+ saved_result = scmd->result;
scmd->request_buffer = NULL;
scmd->request_bufflen = 0;
scmd->use_sg = 0;
@@ -922,6 +913,7 @@ static int scsi_eh_try_stu(struct scsi_cmnd *scmd)
* the original request, so let's restore the original data. (db)
*/
scsi_setup_cmd_retry(scmd);
+ scmd->result = saved_result;
/*
* hey, we are done. let's look to see what happened.
@@ -1061,9 +1053,7 @@ static int scsi_try_bus_reset(struct scsi_cmnd *scmd)
if (!scmd->device->host->hostt->eh_bus_reset_handler)
return FAILED;
- spin_lock_irqsave(scmd->device->host->host_lock, flags);
rtn = scmd->device->host->hostt->eh_bus_reset_handler(scmd);
- spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
if (rtn == SUCCESS) {
if (!scmd->device->host->hostt->skip_settle_delay)
@@ -1092,9 +1082,7 @@ static int scsi_try_host_reset(struct scsi_cmnd *scmd)
if (!scmd->device->host->hostt->eh_host_reset_handler)
return FAILED;
- spin_lock_irqsave(scmd->device->host->host_lock, flags);
rtn = scmd->device->host->hostt->eh_host_reset_handler(scmd);
- spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
if (rtn == SUCCESS) {
if (!scmd->device->host->hostt->skip_settle_delay)
@@ -1561,6 +1549,11 @@ static void scsi_eh_flush_done_q(struct list_head *done_q)
scmd));
scsi_queue_insert(scmd, SCSI_MLQUEUE_EH_RETRY);
} else {
+ /*
+ * If just we got sense for the device (called
+ * scsi_eh_get_sense), scmd->result is already
+ * set, do not set DRIVER_TIMEOUT.
+ */
if (!scmd->result)
scmd->result |= (DRIVER_TIMEOUT << 24);
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: flush finish"
@@ -1870,7 +1863,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
rtn = FAILED;
}
- scsi_delete_timer(scmd);
scsi_next_command(scmd);
return rtn;
}
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index d18da21c9c5..621dee8b8cb 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -44,7 +44,7 @@ struct scsi_host_sg_pool {
#endif
#define SP(x) { x, "sgpool-" #x }
-struct scsi_host_sg_pool scsi_sg_pools[] = {
+static struct scsi_host_sg_pool scsi_sg_pools[] = {
SP(8),
SP(16),
SP(32),
@@ -92,10 +92,12 @@ int scsi_insert_special_req(struct scsi_request *sreq, int at_head)
*/
sreq->sr_request->flags &= ~REQ_DONTPREP;
blk_insert_request(sreq->sr_device->request_queue, sreq->sr_request,
- at_head, sreq, 0);
+ at_head, sreq);
return 0;
}
+static void scsi_run_queue(struct request_queue *q);
+
/*
* Function: scsi_queue_insert()
*
@@ -119,18 +121,14 @@ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
{
struct Scsi_Host *host = cmd->device->host;
struct scsi_device *device = cmd->device;
+ struct request_queue *q = device->request_queue;
+ unsigned long flags;
SCSI_LOG_MLQUEUE(1,
printk("Inserting command %p into mlqueue\n", cmd));
/*
- * We are inserting the command into the ml queue. First, we
- * cancel the timer, so it doesn't time out.
- */
- scsi_delete_timer(cmd);
-
- /*
- * Next, set the appropriate busy bit for the device/host.
+ * Set the appropriate busy bit for the device/host.
*
* If the host/device isn't busy, assume that something actually
* completed, and that we should be able to queue a command now.
@@ -160,17 +158,22 @@ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
scsi_device_unbusy(device);
/*
- * Insert this command at the head of the queue for it's device.
- * It will go before all other commands that are already in the queue.
+ * Requeue this command. It will go before all other commands
+ * that are already in the queue.
*
* NOTE: there is magic here about the way the queue is plugged if
* we have no outstanding commands.
*
- * Although this *doesn't* plug the queue, it does call the request
+ * Although we *don't* plug the queue, we call the request
* function. The SCSI request function detects the blocked condition
* and plugs the queue appropriately.
- */
- blk_insert_request(device->request_queue, cmd->request, 1, cmd, 1);
+ */
+ spin_lock_irqsave(q->queue_lock, flags);
+ blk_requeue_request(q, cmd->request);
+ spin_unlock_irqrestore(q->queue_lock, flags);
+
+ scsi_run_queue(q);
+
return 0;
}
@@ -485,8 +488,13 @@ static void scsi_run_queue(struct request_queue *q)
*/
static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd)
{
+ unsigned long flags;
+
cmd->request->flags &= ~REQ_DONTPREP;
- blk_insert_request(q, cmd->request, 1, cmd, 1);
+
+ spin_lock_irqsave(q->queue_lock, flags);
+ blk_requeue_request(q, cmd->request);
+ spin_unlock_irqrestore(q->queue_lock, flags);
scsi_run_queue(q);
}
@@ -941,10 +949,8 @@ static int scsi_init_io(struct scsi_cmnd *cmd)
* if sg table allocation fails, requeue request later.
*/
sgpnt = scsi_alloc_sgtable(cmd, GFP_ATOMIC);
- if (unlikely(!sgpnt)) {
- req->flags |= REQ_SPECIAL;
+ if (unlikely(!sgpnt))
return BLKPREP_DEFER;
- }
cmd->request_buffer = (char *) sgpnt;
cmd->request_bufflen = req->nr_sectors << 9;
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index c01580df447..96d4f745975 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -61,8 +61,6 @@ extern void scsi_exit_hosts(void);
extern int scsi_dispatch_cmd(struct scsi_cmnd *cmd);
extern int scsi_setup_command_freelist(struct Scsi_Host *shost);
extern void scsi_destroy_command_freelist(struct Scsi_Host *shost);
-extern void scsi_done(struct scsi_cmnd *cmd);
-extern int scsi_retry_command(struct scsi_cmnd *cmd);
extern int scsi_insert_special_req(struct scsi_request *sreq, int);
extern void scsi_init_cmd_from_req(struct scsi_cmnd *cmd,
struct scsi_request *sreq);
@@ -136,7 +134,6 @@ extern void scsi_exit_sysctl(void);
#endif /* CONFIG_SYSCTL */
/* scsi_sysfs.c */
-extern void scsi_device_dev_release(struct device *);
extern int scsi_sysfs_add_sdev(struct scsi_device *);
extern int scsi_sysfs_add_host(struct Scsi_Host *);
extern int scsi_sysfs_register(void);
@@ -145,7 +142,6 @@ extern void scsi_sysfs_device_initialize(struct scsi_device *);
extern int scsi_sysfs_target_initialize(struct scsi_device *);
extern struct scsi_transport_template blank_transport_template;
-extern struct class sdev_class;
extern struct bus_type scsi_bus_type;
/*
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index cca772624ae..9fa209097e3 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -293,6 +293,10 @@ static void scsi_target_dev_release(struct device *dev)
{
struct device *parent = dev->parent;
struct scsi_target *starget = to_scsi_target(dev);
+ struct Scsi_Host *shost = dev_to_shost(parent);
+
+ if (shost->hostt->target_destroy)
+ shost->hostt->target_destroy(starget);
kfree(starget);
put_device(parent);
}
@@ -360,9 +364,23 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
list_add_tail(&starget->siblings, &shost->__targets);
spin_unlock_irqrestore(shost->host_lock, flags);
/* allocate and add */
- transport_setup_device(&starget->dev);
- device_add(&starget->dev);
- transport_add_device(&starget->dev);
+ transport_setup_device(dev);
+ device_add(dev);
+ transport_add_device(dev);
+ if (shost->hostt->target_alloc) {
+ int error = shost->hostt->target_alloc(starget);
+
+ if(error) {
+ dev_printk(KERN_ERR, dev, "target allocation failed, error %d\n", error);
+ /* don't want scsi_target_reap to do the final
+ * put because it will be under the host lock */
+ get_device(dev);
+ scsi_target_reap(starget);
+ put_device(dev);
+ return NULL;
+ }
+ }
+
return starget;
found:
@@ -625,6 +643,7 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags)
case TYPE_MEDIUM_CHANGER:
case TYPE_ENCLOSURE:
case TYPE_COMM:
+ case TYPE_RBC:
sdev->writeable = 1;
break;
case TYPE_WORM:
@@ -1197,6 +1216,7 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
if (!starget)
return ERR_PTR(-ENOMEM);
+ get_device(&starget->dev);
down(&shost->scan_mutex);
res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata);
if (res != SCSI_SCAN_LUN_PRESENT)
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index e75ee4671ee..beed7fbe1cb 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -150,7 +150,7 @@ static void scsi_device_cls_release(struct class_device *class_dev)
put_device(&sdev->sdev_gendev);
}
-void scsi_device_dev_release(struct device *dev)
+static void scsi_device_dev_release(struct device *dev)
{
struct scsi_device *sdev;
struct device *parent;
@@ -185,7 +185,7 @@ void scsi_device_dev_release(struct device *dev)
put_device(parent);
}
-struct class sdev_class = {
+static struct class sdev_class = {
.name = "scsi_device",
.release = scsi_device_cls_release,
};
@@ -230,7 +230,7 @@ void scsi_sysfs_unregister(void)
*/
#define sdev_show_function(field, format_string) \
static ssize_t \
-sdev_show_##field (struct device *dev, char *buf) \
+sdev_show_##field (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct scsi_device *sdev; \
sdev = to_scsi_device(dev); \
@@ -254,7 +254,7 @@ static DEVICE_ATTR(field, S_IRUGO, sdev_show_##field, NULL);
sdev_show_function(field, format_string) \
\
static ssize_t \
-sdev_store_##field (struct device *dev, const char *buf, size_t count) \
+sdev_store_##field (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
{ \
struct scsi_device *sdev; \
sdev = to_scsi_device(dev); \
@@ -274,7 +274,7 @@ static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, sdev_show_##field, sdev_store_##fie
sdev_show_function(field, "%d\n") \
\
static ssize_t \
-sdev_store_##field (struct device *dev, const char *buf, size_t count) \
+sdev_store_##field (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
{ \
int ret; \
struct scsi_device *sdev; \
@@ -317,7 +317,7 @@ sdev_rd_attr (model, "%.16s\n");
sdev_rd_attr (rev, "%.4s\n");
static ssize_t
-sdev_show_timeout (struct device *dev, char *buf)
+sdev_show_timeout (struct device *dev, struct device_attribute *attr, char *buf)
{
struct scsi_device *sdev;
sdev = to_scsi_device(dev);
@@ -325,7 +325,7 @@ sdev_show_timeout (struct device *dev, char *buf)
}
static ssize_t
-sdev_store_timeout (struct device *dev, const char *buf, size_t count)
+sdev_store_timeout (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct scsi_device *sdev;
int timeout;
@@ -337,14 +337,14 @@ sdev_store_timeout (struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(timeout, S_IRUGO | S_IWUSR, sdev_show_timeout, sdev_store_timeout);
static ssize_t
-store_rescan_field (struct device *dev, const char *buf, size_t count)
+store_rescan_field (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
scsi_rescan_device(dev);
return count;
}
static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field);
-static ssize_t sdev_store_delete(struct device *dev, const char *buf,
+static ssize_t sdev_store_delete(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
scsi_remove_device(to_scsi_device(dev));
@@ -353,7 +353,7 @@ static ssize_t sdev_store_delete(struct device *dev, const char *buf,
static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete);
static ssize_t
-store_state_field(struct device *dev, const char *buf, size_t count)
+store_state_field(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int i;
struct scsi_device *sdev = to_scsi_device(dev);
@@ -376,7 +376,7 @@ store_state_field(struct device *dev, const char *buf, size_t count)
}
static ssize_t
-show_state_field(struct device *dev, char *buf)
+show_state_field(struct device *dev, struct device_attribute *attr, char *buf)
{
struct scsi_device *sdev = to_scsi_device(dev);
const char *name = scsi_device_state_name(sdev->sdev_state);
@@ -390,7 +390,7 @@ show_state_field(struct device *dev, char *buf)
static DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_state_field, store_state_field);
static ssize_t
-show_queue_type_field(struct device *dev, char *buf)
+show_queue_type_field(struct device *dev, struct device_attribute *attr, char *buf)
{
struct scsi_device *sdev = to_scsi_device(dev);
const char *name = "none";
@@ -406,7 +406,7 @@ show_queue_type_field(struct device *dev, char *buf)
static DEVICE_ATTR(queue_type, S_IRUGO, show_queue_type_field, NULL);
static ssize_t
-show_iostat_counterbits(struct device *dev, char *buf)
+show_iostat_counterbits(struct device *dev, struct device_attribute *attr, char *buf)
{
return snprintf(buf, 20, "%d\n", (int)sizeof(atomic_t) * 8);
}
@@ -415,7 +415,7 @@ static DEVICE_ATTR(iocounterbits, S_IRUGO, show_iostat_counterbits, NULL);
#define show_sdev_iostat(field) \
static ssize_t \
-show_iostat_##field(struct device *dev, char *buf) \
+show_iostat_##field(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct scsi_device *sdev = to_scsi_device(dev); \
unsigned long long count = atomic_read(&sdev->field); \
@@ -449,7 +449,7 @@ static struct device_attribute *scsi_sysfs_sdev_attrs[] = {
NULL
};
-static ssize_t sdev_store_queue_depth_rw(struct device *dev, const char *buf,
+static ssize_t sdev_store_queue_depth_rw(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
int depth, retval;
@@ -475,7 +475,7 @@ static struct device_attribute sdev_attr_queue_depth_rw =
__ATTR(queue_depth, S_IRUGO | S_IWUSR, sdev_show_queue_depth,
sdev_store_queue_depth_rw);
-static ssize_t sdev_store_queue_type_rw(struct device *dev, const char *buf,
+static ssize_t sdev_store_queue_type_rw(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
struct scsi_device *sdev = to_scsi_device(dev);
@@ -669,6 +669,13 @@ void __scsi_remove_target(struct scsi_target *starget)
scsi_target_reap(starget);
}
+static int __remove_child (struct device * dev, void * data)
+{
+ if (scsi_is_target_device(dev))
+ __scsi_remove_target(to_scsi_target(dev));
+ return 0;
+}
+
/**
* scsi_remove_target - try to remove a target and all its devices
* @dev: generic starget or parent of generic stargets to be removed
@@ -679,7 +686,7 @@ void __scsi_remove_target(struct scsi_target *starget)
*/
void scsi_remove_target(struct device *dev)
{
- struct device *rdev, *idev, *next;
+ struct device *rdev;
if (scsi_is_target_device(dev)) {
__scsi_remove_target(to_scsi_target(dev));
@@ -687,10 +694,7 @@ void scsi_remove_target(struct device *dev)
}
rdev = get_device(dev);
- list_for_each_entry_safe(idev, next, &dev->children, node) {
- if (scsi_is_target_device(idev))
- __scsi_remove_target(to_scsi_target(idev));
- }
+ device_for_each_child(dev, NULL, __remove_child);
put_device(rdev);
}
EXPORT_SYMBOL(scsi_remove_target);
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index 28966d05435..2918b9600db 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -35,7 +35,7 @@
#define SPI_PRINTK(x, l, f, a...) dev_printk(l, &(x)->dev, f , ##a)
-#define SPI_NUM_ATTRS 10 /* increase this if you add attributes */
+#define SPI_NUM_ATTRS 13 /* increase this if you add attributes */
#define SPI_OTHER_ATTRS 1 /* Increase this if you add "always
* on" attributes */
#define SPI_HOST_ATTRS 1
@@ -219,8 +219,11 @@ static int spi_setup_transport_attrs(struct device *dev)
struct scsi_target *starget = to_scsi_target(dev);
spi_period(starget) = -1; /* illegal value */
+ spi_min_period(starget) = 0;
spi_offset(starget) = 0; /* async */
+ spi_max_offset(starget) = 255;
spi_width(starget) = 0; /* narrow */
+ spi_max_width(starget) = 1;
spi_iu(starget) = 0; /* no IU */
spi_dt(starget) = 0; /* ST */
spi_qas(starget) = 0;
@@ -235,6 +238,34 @@ static int spi_setup_transport_attrs(struct device *dev)
return 0;
}
+#define spi_transport_show_simple(field, format_string) \
+ \
+static ssize_t \
+show_spi_transport_##field(struct class_device *cdev, char *buf) \
+{ \
+ struct scsi_target *starget = transport_class_to_starget(cdev); \
+ struct spi_transport_attrs *tp; \
+ \
+ tp = (struct spi_transport_attrs *)&starget->starget_data; \
+ return snprintf(buf, 20, format_string, tp->field); \
+}
+
+#define spi_transport_store_simple(field, format_string) \
+ \
+static ssize_t \
+store_spi_transport_##field(struct class_device *cdev, const char *buf, \
+ size_t count) \
+{ \
+ int val; \
+ struct scsi_target *starget = transport_class_to_starget(cdev); \
+ struct spi_transport_attrs *tp; \
+ \
+ tp = (struct spi_transport_attrs *)&starget->starget_data; \
+ val = simple_strtoul(buf, NULL, 0); \
+ tp->field = val; \
+ return count; \
+}
+
#define spi_transport_show_function(field, format_string) \
\
static ssize_t \
@@ -261,6 +292,25 @@ store_spi_transport_##field(struct class_device *cdev, const char *buf, \
struct spi_internal *i = to_spi_internal(shost->transportt); \
\
val = simple_strtoul(buf, NULL, 0); \
+ i->f->set_##field(starget, val); \
+ return count; \
+}
+
+#define spi_transport_store_max(field, format_string) \
+static ssize_t \
+store_spi_transport_##field(struct class_device *cdev, const char *buf, \
+ size_t count) \
+{ \
+ int val; \
+ struct scsi_target *starget = transport_class_to_starget(cdev); \
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \
+ struct spi_internal *i = to_spi_internal(shost->transportt); \
+ struct spi_transport_attrs *tp \
+ = (struct spi_transport_attrs *)&starget->starget_data; \
+ \
+ val = simple_strtoul(buf, NULL, 0); \
+ if (val > tp->max_##field) \
+ val = tp->max_##field; \
i->f->set_##field(starget, val); \
return count; \
}
@@ -272,9 +322,24 @@ static CLASS_DEVICE_ATTR(field, S_IRUGO | S_IWUSR, \
show_spi_transport_##field, \
store_spi_transport_##field);
+#define spi_transport_simple_attr(field, format_string) \
+ spi_transport_show_simple(field, format_string) \
+ spi_transport_store_simple(field, format_string) \
+static CLASS_DEVICE_ATTR(field, S_IRUGO | S_IWUSR, \
+ show_spi_transport_##field, \
+ store_spi_transport_##field);
+
+#define spi_transport_max_attr(field, format_string) \
+ spi_transport_show_function(field, format_string) \
+ spi_transport_store_max(field, format_string) \
+ spi_transport_simple_attr(max_##field, format_string) \
+static CLASS_DEVICE_ATTR(field, S_IRUGO | S_IWUSR, \
+ show_spi_transport_##field, \
+ store_spi_transport_##field);
+
/* The Parallel SCSI Tranport Attributes: */
-spi_transport_rd_attr(offset, "%d\n");
-spi_transport_rd_attr(width, "%d\n");
+spi_transport_max_attr(offset, "%d\n");
+spi_transport_max_attr(width, "%d\n");
spi_transport_rd_attr(iu, "%d\n");
spi_transport_rd_attr(dt, "%d\n");
spi_transport_rd_attr(qas, "%d\n");
@@ -283,43 +348,39 @@ spi_transport_rd_attr(rd_strm, "%d\n");
spi_transport_rd_attr(rti, "%d\n");
spi_transport_rd_attr(pcomp_en, "%d\n");
+/* we only care about the first child device so we return 1 */
+static int child_iter(struct device *dev, void *data)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+
+ spi_dv_device(sdev);
+ return 1;
+}
+
static ssize_t
store_spi_revalidate(struct class_device *cdev, const char *buf, size_t count)
{
struct scsi_target *starget = transport_class_to_starget(cdev);
- /* FIXME: we're relying on an awful lot of device internals
- * here. We really need a function to get the first available
- * child */
- struct device *dev = container_of(starget->dev.children.next, struct device, node);
- struct scsi_device *sdev = to_scsi_device(dev);
- spi_dv_device(sdev);
+ device_for_each_child(&starget->dev, NULL, child_iter);
return count;
}
static CLASS_DEVICE_ATTR(revalidate, S_IWUSR, NULL, store_spi_revalidate);
/* Translate the period into ns according to the current spec
* for SDTR/PPR messages */
-static ssize_t show_spi_transport_period(struct class_device *cdev, char *buf)
-
+static ssize_t
+show_spi_transport_period_helper(struct class_device *cdev, char *buf,
+ int period)
{
- struct scsi_target *starget = transport_class_to_starget(cdev);
- struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- struct spi_transport_attrs *tp;
int len, picosec;
- struct spi_internal *i = to_spi_internal(shost->transportt);
- tp = (struct spi_transport_attrs *)&starget->starget_data;
-
- if (i->f->get_period)
- i->f->get_period(starget);
-
- if (tp->period < 0 || tp->period > 0xff) {
+ if (period < 0 || period > 0xff) {
picosec = -1;
- } else if (tp->period <= SPI_STATIC_PPR) {
- picosec = ppr_to_ps[tp->period];
+ } else if (period <= SPI_STATIC_PPR) {
+ picosec = ppr_to_ps[period];
} else {
- picosec = tp->period * 4000;
+ picosec = period * 4000;
}
if (picosec == -1) {
@@ -334,12 +395,9 @@ static ssize_t show_spi_transport_period(struct class_device *cdev, char *buf)
}
static ssize_t
-store_spi_transport_period(struct class_device *cdev, const char *buf,
- size_t count)
+store_spi_transport_period_helper(struct class_device *cdev, const char *buf,
+ size_t count, int *periodp)
{
- struct scsi_target *starget = transport_class_to_starget(cdev);
- struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
- struct spi_internal *i = to_spi_internal(shost->transportt);
int j, picosec, period = -1;
char *endp;
@@ -368,15 +426,79 @@ store_spi_transport_period(struct class_device *cdev, const char *buf,
if (period > 0xff)
period = 0xff;
- i->f->set_period(starget, period);
+ *periodp = period;
return count;
}
+static ssize_t
+show_spi_transport_period(struct class_device *cdev, char *buf)
+{
+ struct scsi_target *starget = transport_class_to_starget(cdev);
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct spi_internal *i = to_spi_internal(shost->transportt);
+ struct spi_transport_attrs *tp =
+ (struct spi_transport_attrs *)&starget->starget_data;
+
+ if (i->f->get_period)
+ i->f->get_period(starget);
+
+ return show_spi_transport_period_helper(cdev, buf, tp->period);
+}
+
+static ssize_t
+store_spi_transport_period(struct class_device *cdev, const char *buf,
+ size_t count)
+{
+ struct scsi_target *starget = transport_class_to_starget(cdev);
+ struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+ struct spi_internal *i = to_spi_internal(shost->transportt);
+ struct spi_transport_attrs *tp =
+ (struct spi_transport_attrs *)&starget->starget_data;
+ int period, retval;
+
+ retval = store_spi_transport_period_helper(cdev, buf, count, &period);
+
+ if (period < tp->min_period)
+ period = tp->min_period;
+
+ i->f->set_period(starget, period);
+
+ return retval;
+}
+
static CLASS_DEVICE_ATTR(period, S_IRUGO | S_IWUSR,
show_spi_transport_period,
store_spi_transport_period);
+static ssize_t
+show_spi_transport_min_period(struct class_device *cdev, char *buf)
+{
+ struct scsi_target *starget = transport_class_to_starget(cdev);
+ struct spi_transport_attrs *tp =
+ (struct spi_transport_attrs *)&starget->starget_data;
+
+ return show_spi_transport_period_helper(cdev, buf, tp->min_period);
+}
+
+static ssize_t
+store_spi_transport_min_period(struct class_device *cdev, const char *buf,
+ size_t count)
+{
+ struct scsi_target *starget = transport_class_to_starget(cdev);
+ struct spi_transport_attrs *tp =
+ (struct spi_transport_attrs *)&starget->starget_data;
+
+ return store_spi_transport_period_helper(cdev, buf, count,
+ &tp->min_period);
+}
+
+
+static CLASS_DEVICE_ATTR(min_period, S_IRUGO | S_IWUSR,
+ show_spi_transport_min_period,
+ store_spi_transport_min_period);
+
+
static ssize_t show_spi_host_signalling(struct class_device *cdev, char *buf)
{
struct Scsi_Host *shost = transport_class_to_shost(cdev);
@@ -551,6 +673,7 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr,
{
struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt);
struct scsi_device *sdev = sreq->sr_device;
+ struct scsi_target *starget = sdev->sdev_target;
int period = 0, prevperiod = 0;
enum spi_compare_returns retval;
@@ -564,24 +687,40 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr,
break;
/* OK, retrain, fallback */
+ if (i->f->get_iu)
+ i->f->get_iu(starget);
+ if (i->f->get_qas)
+ i->f->get_qas(starget);
if (i->f->get_period)
i->f->get_period(sdev->sdev_target);
- newperiod = spi_period(sdev->sdev_target);
- period = newperiod > period ? newperiod : period;
- if (period < 0x0d)
- period++;
- else
- period += period >> 1;
-
- if (unlikely(period > 0xff || period == prevperiod)) {
- /* Total failure; set to async and return */
- SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation Failure, dropping back to Asynchronous\n");
- DV_SET(offset, 0);
- return SPI_COMPARE_FAILURE;
+
+ /* Here's the fallback sequence; first try turning off
+ * IU, then QAS (if we can control them), then finally
+ * fall down the periods */
+ if (i->f->set_iu && spi_iu(starget)) {
+ SPI_PRINTK(starget, KERN_ERR, "Domain Validation Disabing Information Units\n");
+ DV_SET(iu, 0);
+ } else if (i->f->set_qas && spi_qas(starget)) {
+ SPI_PRINTK(starget, KERN_ERR, "Domain Validation Disabing Quick Arbitration and Selection\n");
+ DV_SET(qas, 0);
+ } else {
+ newperiod = spi_period(starget);
+ period = newperiod > period ? newperiod : period;
+ if (period < 0x0d)
+ period++;
+ else
+ period += period >> 1;
+
+ if (unlikely(period > 0xff || period == prevperiod)) {
+ /* Total failure; set to async and return */
+ SPI_PRINTK(starget, KERN_ERR, "Domain Validation Failure, dropping back to Asynchronous\n");
+ DV_SET(offset, 0);
+ return SPI_COMPARE_FAILURE;
+ }
+ SPI_PRINTK(starget, KERN_ERR, "Domain Validation detected failure, dropping back\n");
+ DV_SET(period, period);
+ prevperiod = period;
}
- SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation detected failure, dropping back\n");
- DV_SET(period, period);
- prevperiod = period;
}
return retval;
}
@@ -642,6 +781,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
{
struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt);
struct scsi_device *sdev = sreq->sr_device;
+ struct scsi_target *starget = sdev->sdev_target;
int len = sdev->inquiry_len;
/* first set us up for narrow async */
DV_SET(offset, 0);
@@ -649,21 +789,21 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
if (spi_dv_device_compare_inquiry(sreq, buffer, buffer, DV_LOOPS)
!= SPI_COMPARE_SUCCESS) {
- SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation Initial Inquiry Failed\n");
+ SPI_PRINTK(starget, KERN_ERR, "Domain Validation Initial Inquiry Failed\n");
/* FIXME: should probably offline the device here? */
return;
}
/* test width */
- if (i->f->set_width && sdev->wdtr) {
- i->f->set_width(sdev->sdev_target, 1);
+ if (i->f->set_width && spi_max_width(starget) && sdev->wdtr) {
+ i->f->set_width(starget, 1);
if (spi_dv_device_compare_inquiry(sreq, buffer,
buffer + len,
DV_LOOPS)
!= SPI_COMPARE_SUCCESS) {
- SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Wide Transfers Fail\n");
- i->f->set_width(sdev->sdev_target, 0);
+ SPI_PRINTK(starget, KERN_ERR, "Wide Transfers Fail\n");
+ i->f->set_width(starget, 0);
}
}
@@ -671,7 +811,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
return;
/* device can't handle synchronous */
- if(!sdev->ppr && !sdev->sdtr)
+ if (!sdev->ppr && !sdev->sdtr)
return;
/* see if the device has an echo buffer. If it does we can
@@ -684,18 +824,32 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
retry:
/* now set up to the maximum */
- DV_SET(offset, 255);
- DV_SET(period, 1);
+ DV_SET(offset, spi_max_offset(starget));
+ DV_SET(period, spi_min_period(starget));
+ /* try QAS requests; this should be harmless to set if the
+ * target supports it */
+ DV_SET(qas, 1);
+ /* Also try IU transfers */
+ DV_SET(iu, 1);
+ if (spi_min_period(starget) < 9) {
+ /* This u320 (or u640). Ignore the coupled parameters
+ * like DT and IU, but set the optional ones */
+ DV_SET(rd_strm, 1);
+ DV_SET(wr_flow, 1);
+ DV_SET(rti, 1);
+ if (spi_min_period(starget) == 8)
+ DV_SET(pcomp_en, 1);
+ }
if (len == 0) {
- SPI_PRINTK(sdev->sdev_target, KERN_INFO, "Domain Validation skipping write tests\n");
+ SPI_PRINTK(starget, KERN_INFO, "Domain Validation skipping write tests\n");
spi_dv_retrain(sreq, buffer, buffer + len,
spi_dv_device_compare_inquiry);
return;
}
if (len > SPI_MAX_ECHO_BUFFER_SIZE) {
- SPI_PRINTK(sdev->sdev_target, KERN_WARNING, "Echo buffer size %d is too big, trimming to %d\n", len, SPI_MAX_ECHO_BUFFER_SIZE);
+ SPI_PRINTK(starget, KERN_WARNING, "Echo buffer size %d is too big, trimming to %d\n", len, SPI_MAX_ECHO_BUFFER_SIZE);
len = SPI_MAX_ECHO_BUFFER_SIZE;
}
@@ -892,6 +1046,16 @@ EXPORT_SYMBOL(spi_display_xfer_agreement);
if (i->f->show_##field) \
count++
+#define SETUP_RELATED_ATTRIBUTE(field, rel_field) \
+ i->private_attrs[count] = class_device_attr_##field; \
+ if (!i->f->set_##rel_field) { \
+ i->private_attrs[count].attr.mode = S_IRUGO; \
+ i->private_attrs[count].store = NULL; \
+ } \
+ i->attrs[count] = &i->private_attrs[count]; \
+ if (i->f->show_##rel_field) \
+ count++
+
#define SETUP_HOST_ATTRIBUTE(field) \
i->private_host_attrs[count] = class_device_attr_##field; \
if (!i->f->set_##field) { \
@@ -975,8 +1139,11 @@ spi_attach_transport(struct spi_function_template *ft)
i->f = ft;
SETUP_ATTRIBUTE(period);
+ SETUP_RELATED_ATTRIBUTE(min_period, period);
SETUP_ATTRIBUTE(offset);
+ SETUP_RELATED_ATTRIBUTE(max_offset, offset);
SETUP_ATTRIBUTE(width);
+ SETUP_RELATED_ATTRIBUTE(max_width, width);
SETUP_ATTRIBUTE(iu);
SETUP_ATTRIBUTE(dt);
SETUP_ATTRIBUTE(qas);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 19afb25e44d..bb823559878 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1368,17 +1368,26 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname,
*/
static void
sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
- struct scsi_request *SRpnt, unsigned char *buffer) {
+ struct scsi_request *SRpnt, unsigned char *buffer)
+{
int len = 0, res;
- const int dbd = 0; /* DBD */
- const int modepage = 0x08; /* current values, cache page */
+ int dbd;
+ int modepage;
struct scsi_mode_data data;
struct scsi_sense_hdr sshdr;
if (sdkp->device->skip_ms_page_8)
goto defaults;
+ if (sdkp->device->type == TYPE_RBC) {
+ modepage = 6;
+ dbd = 8;
+ } else {
+ modepage = 8;
+ dbd = 0;
+ }
+
/* cautiously ask */
res = sd_do_mode_sense(SRpnt, dbd, modepage, buffer, 4, &data);
@@ -1409,11 +1418,20 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
"write back, no read (daft)"
};
int ct = 0;
- int offset = data.header_length +
- data.block_descriptor_length + 2;
+ int offset = data.header_length + data.block_descriptor_length;
- sdkp->WCE = ((buffer[offset] & 0x04) != 0);
- sdkp->RCD = ((buffer[offset] & 0x01) != 0);
+ if ((buffer[offset] & 0x3f) != modepage) {
+ printk(KERN_ERR "%s: got wrong page\n", diskname);
+ goto defaults;
+ }
+
+ if (modepage == 8) {
+ sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0);
+ sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0);
+ } else {
+ sdkp->WCE = ((buffer[offset + 2] & 0x01) == 0);
+ sdkp->RCD = 0;
+ }
ct = sdkp->RCD + 2*sdkp->WCE;
@@ -1533,7 +1551,7 @@ static int sd_probe(struct device *dev)
int error;
error = -ENODEV;
- if ((sdp->type != TYPE_DISK) && (sdp->type != TYPE_MOD))
+ if (sdp->type != TYPE_DISK && sdp->type != TYPE_MOD && sdp->type != TYPE_RBC)
goto out;
SCSI_LOG_HLQUEUE(3, printk("sd_attach: scsi device: <%d,%d,%d,%d>\n",
@@ -1570,7 +1588,7 @@ static int sd_probe(struct device *dev)
sdkp->openers = 0;
if (!sdp->timeout) {
- if (sdp->type == TYPE_DISK)
+ if (sdp->type != TYPE_MOD)
sdp->timeout = SD_TIMEOUT;
else
sdp->timeout = SD_MOD_TIMEOUT;
diff --git a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c
index 4c95abb5405..a0cace9aeb7 100644
--- a/drivers/scsi/seagate.c
+++ b/drivers/scsi/seagate.c
@@ -97,6 +97,7 @@
#include <linux/delay.h>
#include <linux/blkdev.h>
#include <linux/stat.h>
+#include <linux/delay.h>
#include <asm/io.h>
#include <asm/system.h>
@@ -1631,7 +1632,7 @@ static int seagate_st0x_bus_reset(Scsi_Cmnd * SCpnt)
/* assert RESET signal on SCSI bus. */
WRITE_CONTROL (BASE_CMD | CMD_RST);
- udelay (20 * 1000);
+ mdelay (20);
WRITE_CONTROL (BASE_CMD);
st0x_aborted = DID_RESET;
@@ -1640,16 +1641,6 @@ static int seagate_st0x_bus_reset(Scsi_Cmnd * SCpnt)
return SUCCESS;
}
-static int seagate_st0x_host_reset(Scsi_Cmnd *SCpnt)
-{
- return FAILED;
-}
-
-static int seagate_st0x_device_reset(Scsi_Cmnd *SCpnt)
-{
- return FAILED;
-}
-
static int seagate_st0x_release(struct Scsi_Host *shost)
{
if (shost->irq)
@@ -1665,8 +1656,6 @@ static Scsi_Host_Template driver_template = {
.queuecommand = seagate_st0x_queue_command,
.eh_abort_handler = seagate_st0x_abort,
.eh_bus_reset_handler = seagate_st0x_bus_reset,
- .eh_host_reset_handler = seagate_st0x_host_reset,
- .eh_device_reset_handler = seagate_st0x_device_reset,
.can_queue = 1,
.this_id = 7,
.sg_tablesize = SG_ALL,
diff --git a/drivers/scsi/seagate.h b/drivers/scsi/seagate.h
index e49e8ecfb54..8889ff1a6b2 100644
--- a/drivers/scsi/seagate.h
+++ b/drivers/scsi/seagate.h
@@ -15,7 +15,5 @@ static int seagate_st0x_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
static int seagate_st0x_abort(Scsi_Cmnd *);
static const char *seagate_st0x_info(struct Scsi_Host *);
static int seagate_st0x_bus_reset(Scsi_Cmnd *);
-static int seagate_st0x_device_reset(Scsi_Cmnd *);
-static int seagate_st0x_host_reset(Scsi_Cmnd *);
#endif /* _SEAGATE_H */
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 7936aafc3d0..51292f269ce 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1430,7 +1430,7 @@ static struct file_operations sg_fops = {
.fasync = sg_fasync,
};
-static struct class_simple * sg_sysfs_class;
+static struct class *sg_sysfs_class;
static int sg_sysfs_valid = 0;
@@ -1551,13 +1551,13 @@ sg_add(struct class_device *cl_dev)
if (sg_sysfs_valid) {
struct class_device * sg_class_member;
- sg_class_member = class_simple_device_add(sg_sysfs_class,
+ sg_class_member = class_device_create(sg_sysfs_class,
MKDEV(SCSI_GENERIC_MAJOR, k),
cl_dev->dev, "%s",
disk->disk_name);
if (IS_ERR(sg_class_member))
printk(KERN_WARNING "sg_add: "
- "class_simple_device_add failed\n");
+ "class_device_create failed\n");
class_set_devdata(sg_class_member, sdp);
error = sysfs_create_link(&scsidp->sdev_gendev.kobj,
&sg_class_member->kobj, "generic");
@@ -1636,7 +1636,7 @@ sg_remove(struct class_device *cl_dev)
if (sdp) {
sysfs_remove_link(&scsidp->sdev_gendev.kobj, "generic");
- class_simple_device_remove(MKDEV(SCSI_GENERIC_MAJOR, k));
+ class_device_destroy(sg_sysfs_class, MKDEV(SCSI_GENERIC_MAJOR, k));
cdev_del(sdp->cdev);
sdp->cdev = NULL;
devfs_remove("%s/generic", scsidp->devfs_name);
@@ -1677,7 +1677,7 @@ init_sg(void)
SG_MAX_DEVS, "sg");
if (rc)
return rc;
- sg_sysfs_class = class_simple_create(THIS_MODULE, "scsi_generic");
+ sg_sysfs_class = class_create(THIS_MODULE, "scsi_generic");
if ( IS_ERR(sg_sysfs_class) ) {
rc = PTR_ERR(sg_sysfs_class);
goto err_out;
@@ -1690,7 +1690,7 @@ init_sg(void)
#endif /* CONFIG_SCSI_PROC_FS */
return 0;
}
- class_simple_destroy(sg_sysfs_class);
+ class_destroy(sg_sysfs_class);
err_out:
unregister_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0), SG_MAX_DEVS);
return rc;
@@ -1703,7 +1703,7 @@ exit_sg(void)
sg_proc_cleanup();
#endif /* CONFIG_SCSI_PROC_FS */
scsi_unregister_interface(&sg_interface);
- class_simple_destroy(sg_sysfs_class);
+ class_destroy(sg_sysfs_class);
sg_sysfs_valid = 0;
unregister_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0),
SG_MAX_DEVS);
@@ -2472,6 +2472,8 @@ sg_remove_request(Sg_fd * sfp, Sg_request * srp)
if ((!sfp) || (!srp) || (!sfp->headrp))
return res;
write_lock_irqsave(&sfp->rq_list_lock, iflags);
+ if (srp->my_cmdp)
+ srp->my_cmdp->upper_private_data = NULL;
prev_rp = sfp->headrp;
if (srp == prev_rp) {
sfp->headrp = prev_rp->nextrp;
diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c
index 270f2aa88fa..a5ba2c69275 100644
--- a/drivers/scsi/sgiwd93.c
+++ b/drivers/scsi/sgiwd93.c
@@ -310,7 +310,14 @@ int sgiwd93_release(struct Scsi_Host *instance)
static int sgiwd93_bus_reset(Scsi_Cmnd *cmd)
{
/* FIXME perform bus-specific reset */
+
+ /* FIXME 2: kill this function, and let midlayer fallback
+ to the same result, calling wd33c93_host_reset() */
+
+ spin_lock_irq(cmd->device->host->host_lock);
wd33c93_host_reset(cmd);
+ spin_unlock_irq(cmd->device->host->host_lock);
+
return SUCCESS;
}
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 265d1eed64f..0291a8fb654 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -17,7 +17,7 @@
Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
*/
-static char *verstr = "20050312";
+static char *verstr = "20050501";
#include <linux/module.h>
@@ -29,6 +29,7 @@ static char *verstr = "20050312";
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/mtio.h>
+#include <linux/cdrom.h>
#include <linux/ioctl.h>
#include <linux/fcntl.h>
#include <linux/spinlock.h>
@@ -50,6 +51,7 @@ static char *verstr = "20050312";
#include <scsi/scsi_host.h>
#include <scsi/scsi_ioctl.h>
#include <scsi/scsi_request.h>
+#include <scsi/sg.h>
/* The driver prints some debugging information on the console if DEBUG
@@ -82,7 +84,7 @@ static int try_wdio = 1;
static int st_dev_max;
static int st_nr_dev;
-static struct class_simple *st_sysfs_class;
+static struct class *st_sysfs_class;
MODULE_AUTHOR("Kai Makisara");
MODULE_DESCRIPTION("SCSI Tape Driver");
@@ -3463,7 +3465,10 @@ static int st_ioctl(struct inode *inode, struct file *file,
case SCSI_IOCTL_GET_BUS_NUMBER:
break;
default:
- if (!capable(CAP_SYS_ADMIN))
+ if ((cmd_in == SG_IO ||
+ cmd_in == SCSI_IOCTL_SEND_COMMAND ||
+ cmd_in == CDROM_SEND_PACKET) &&
+ !capable(CAP_SYS_RAWIO))
i = -EPERM;
else
i = scsi_cmd_ioctl(file, STp->disk, cmd_in, p);
@@ -3471,10 +3476,12 @@ static int st_ioctl(struct inode *inode, struct file *file,
return i;
break;
}
- if (!capable(CAP_SYS_ADMIN) &&
- (cmd_in == SCSI_IOCTL_START_UNIT || cmd_in == SCSI_IOCTL_STOP_UNIT))
- return -EPERM;
- return scsi_ioctl(STp->device, cmd_in, p);
+ retval = scsi_ioctl(STp->device, cmd_in, p);
+ if (!retval && cmd_in == SCSI_IOCTL_STOP_UNIT) { /* unload */
+ STp->rew_at_close = 0;
+ STp->ready = ST_NO_TAPE;
+ }
+ return retval;
out:
up(&STp->lock);
@@ -4017,8 +4024,9 @@ out_free_tape:
if (STm->cdevs[j]) {
if (cdev == STm->cdevs[j])
cdev = NULL;
- class_simple_device_remove(MKDEV(SCSI_TAPE_MAJOR,
- TAPE_MINOR(i, mode, j)));
+ class_device_destroy(st_sysfs_class,
+ MKDEV(SCSI_TAPE_MAJOR,
+ TAPE_MINOR(i, mode, j)));
cdev_del(STm->cdevs[j]);
}
}
@@ -4061,8 +4069,9 @@ static int st_remove(struct device *dev)
devfs_remove("%s/mt%s", SDp->devfs_name, st_formats[j]);
devfs_remove("%s/mt%sn", SDp->devfs_name, st_formats[j]);
for (j=0; j < 2; j++) {
- class_simple_device_remove(MKDEV(SCSI_TAPE_MAJOR,
- TAPE_MINOR(i, mode, j)));
+ class_device_destroy(st_sysfs_class,
+ MKDEV(SCSI_TAPE_MAJOR,
+ TAPE_MINOR(i, mode, j)));
cdev_del(tpnt->modes[mode].cdevs[j]);
tpnt->modes[mode].cdevs[j] = NULL;
}
@@ -4127,7 +4136,7 @@ static int __init init_st(void)
"st: Version %s, fixed bufsize %d, s/g segs %d\n",
verstr, st_fixed_buffer_size, st_max_sg_segs);
- st_sysfs_class = class_simple_create(THIS_MODULE, "scsi_tape");
+ st_sysfs_class = class_create(THIS_MODULE, "scsi_tape");
if (IS_ERR(st_sysfs_class)) {
st_sysfs_class = NULL;
printk(KERN_ERR "Unable create sysfs class for SCSI tapes\n");
@@ -4141,7 +4150,7 @@ static int __init init_st(void)
return 0;
}
if (st_sysfs_class)
- class_simple_destroy(st_sysfs_class);
+ class_destroy(st_sysfs_class);
unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
ST_MAX_TAPE_ENTRIES);
@@ -4154,7 +4163,7 @@ static int __init init_st(void)
static void __exit exit_st(void)
{
if (st_sysfs_class)
- class_simple_destroy(st_sysfs_class);
+ class_destroy(st_sysfs_class);
st_sysfs_class = NULL;
do_remove_driverfs_files();
scsi_unregister_driver(&st_template.gendrv);
@@ -4277,12 +4286,12 @@ static void do_create_class_files(struct scsi_tape *STp, int dev_num, int mode)
snprintf(name, 10, "%s%s%s", rew ? "n" : "",
STp->disk->disk_name, st_formats[i]);
st_class_member =
- class_simple_device_add(st_sysfs_class,
- MKDEV(SCSI_TAPE_MAJOR,
- TAPE_MINOR(dev_num, mode, rew)),
- &STp->device->sdev_gendev, "%s", name);
+ class_device_create(st_sysfs_class,
+ MKDEV(SCSI_TAPE_MAJOR,
+ TAPE_MINOR(dev_num, mode, rew)),
+ &STp->device->sdev_gendev, "%s", name);
if (IS_ERR(st_class_member)) {
- printk(KERN_WARNING "st%d: class_simple_device_add failed\n",
+ printk(KERN_WARNING "st%d: class_device_create failed\n",
dev_num);
goto out;
}
diff --git a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c
index 5d1dc0e8ba2..09d7639079b 100644
--- a/drivers/scsi/sun3x_esp.c
+++ b/drivers/scsi/sun3x_esp.c
@@ -23,8 +23,6 @@
#include <asm/dvma.h>
#include <asm/irq.h>
-extern struct NCR_ESP *espchain;
-
static void dma_barrier(struct NCR_ESP *esp);
static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
diff --git a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c
index ebfddd40ce6..ef19adc67ef 100644
--- a/drivers/scsi/sym53c416.c
+++ b/drivers/scsi/sym53c416.c
@@ -785,26 +785,14 @@ int sym53c416_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
return 0;
}
-static int sym53c416_abort(Scsi_Cmnd *SCpnt)
-{
- return FAILED;
-}
-
-static int sym53c416_bus_reset(Scsi_Cmnd *SCpnt)
-{
- return FAILED;
-}
-
-static int sym53c416_device_reset(Scsi_Cmnd *SCpnt)
-{
- return FAILED;
-}
-
static int sym53c416_host_reset(Scsi_Cmnd *SCpnt)
{
int base;
int scsi_id = -1;
int i;
+ unsigned long flags;
+
+ spin_lock_irqsave(&sym53c416_lock, flags);
/* printk("sym53c416_reset\n"); */
base = SCpnt->device->host->io_port;
@@ -816,6 +804,8 @@ static int sym53c416_host_reset(Scsi_Cmnd *SCpnt)
outb(NOOP | PIO_MODE, base + COMMAND_REG);
outb(RESET_SCSI_BUS, base + COMMAND_REG);
sym53c416_init(base, scsi_id);
+
+ spin_unlock_irqrestore(&sym53c416_lock, flags);
return SUCCESS;
}
@@ -865,10 +855,7 @@ static Scsi_Host_Template driver_template = {
.detect = sym53c416_detect,
.info = sym53c416_info,
.queuecommand = sym53c416_queuecommand,
- .eh_abort_handler = sym53c416_abort,
.eh_host_reset_handler =sym53c416_host_reset,
- .eh_bus_reset_handler = sym53c416_bus_reset,
- .eh_device_reset_handler =sym53c416_device_reset,
.release = sym53c416_release,
.bios_param = sym53c416_bios_param,
.can_queue = 1,
diff --git a/drivers/scsi/sym53c416.h b/drivers/scsi/sym53c416.h
index 3c0e3f8301f..fd6b120d38c 100644
--- a/drivers/scsi/sym53c416.h
+++ b/drivers/scsi/sym53c416.h
@@ -26,10 +26,7 @@ static int sym53c416_detect(Scsi_Host_Template *);
static const char *sym53c416_info(struct Scsi_Host *);
static int sym53c416_release(struct Scsi_Host *);
static int sym53c416_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-static int sym53c416_abort(Scsi_Cmnd *);
static int sym53c416_host_reset(Scsi_Cmnd *);
-static int sym53c416_bus_reset(Scsi_Cmnd *);
-static int sym53c416_device_reset(Scsi_Cmnd *);
static int sym53c416_bios_param(struct scsi_device *, struct block_device *,
sector_t, int *);
static void sym53c416_setup(char *str, int *ints);
diff --git a/drivers/scsi/sym53c8xx_2/sym_defs.h b/drivers/scsi/sym53c8xx_2/sym_defs.h
index 15bb89195c0..2d9437d7242 100644
--- a/drivers/scsi/sym53c8xx_2/sym_defs.h
+++ b/drivers/scsi/sym53c8xx_2/sym_defs.h
@@ -40,7 +40,7 @@
#ifndef SYM_DEFS_H
#define SYM_DEFS_H
-#define SYM_VERSION "2.2.0"
+#define SYM_VERSION "2.2.1"
#define SYM_DRIVER_NAME "sym-" SYM_VERSION
/*
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 5b07c6ec3ec..d76766c3ce1 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -155,10 +155,11 @@ pci_get_base_address(struct pci_dev *pdev, int index, unsigned long *basep)
base = tmp;
if ((tmp & 0x7) == PCI_BASE_ADDRESS_MEM_TYPE_64) {
pci_read_config_dword(pdev, PCI_BAR_OFFSET(index++), &tmp);
- if (tmp > 0)
+ if (tmp > 0) {
dev_err(&pdev->dev,
"BAR %d is 64-bit, disabling\n", index - 1);
- base = 0;
+ base = 0;
+ }
}
if ((base & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) {
@@ -389,13 +390,20 @@ static int sym_scatter_no_sglist(struct sym_hcb *np, struct sym_ccb *cp, struct
{
struct sym_tblmove *data = &cp->phys.data[SYM_CONF_MAX_SG-1];
int segment;
+ unsigned int len = cmd->request_bufflen;
- cp->data_len = cmd->request_bufflen;
-
- if (cmd->request_bufflen) {
+ if (len) {
dma_addr_t baddr = map_scsi_single_data(np, cmd);
if (baddr) {
- sym_build_sge(np, data, baddr, cmd->request_bufflen);
+ if (len & 1) {
+ struct sym_tcb *tp = &np->target[cp->target];
+ if (tp->head.wval & EWS) {
+ len++;
+ cp->odd_byte_adjustment++;
+ }
+ }
+ cp->data_len = len;
+ sym_build_sge(np, data, baddr, len);
segment = 1;
} else {
segment = -2;
@@ -418,6 +426,7 @@ static int sym_scatter(struct sym_hcb *np, struct sym_ccb *cp, struct scsi_cmnd
segment = sym_scatter_no_sglist(np, cp, cmd);
else if ((use_sg = map_scsi_sg_data(np, cmd)) > 0) {
struct scatterlist *scatter = (struct scatterlist *)cmd->buffer;
+ struct sym_tcb *tp = &np->target[cp->target];
struct sym_tblmove *data;
if (use_sg > SYM_CONF_MAX_SG) {
@@ -431,6 +440,11 @@ static int sym_scatter(struct sym_hcb *np, struct sym_ccb *cp, struct scsi_cmnd
dma_addr_t baddr = sg_dma_address(&scatter[segment]);
unsigned int len = sg_dma_len(&scatter[segment]);
+ if ((len & 1) && (tp->head.wval & EWS)) {
+ len++;
+ cp->odd_byte_adjustment++;
+ }
+
sym_build_sge(np, &data[segment], baddr, len);
cp->data_len += len;
}
@@ -456,10 +470,8 @@ static int sym_queue_command(struct sym_hcb *np, struct scsi_cmnd *cmd)
* Minimal checkings, so that we will not
* go outside our tables.
*/
- if (sdev->id == np->myaddr ||
- sdev->id >= SYM_CONF_MAX_TARGET ||
- sdev->lun >= SYM_CONF_MAX_LUN) {
- sym_xpt_done2(np, cmd, CAM_DEV_NOT_THERE);
+ if (sdev->id == np->myaddr) {
+ sym_xpt_done2(np, cmd, DID_NO_CONNECT);
return 0;
}
@@ -469,28 +481,6 @@ static int sym_queue_command(struct sym_hcb *np, struct scsi_cmnd *cmd)
tp = &np->target[sdev->id];
/*
- * Complete the 1st INQUIRY command with error
- * condition if the device is flagged NOSCAN
- * at BOOT in the NVRAM. This may speed up
- * the boot and maintain coherency with BIOS
- * device numbering. Clearing the flag allows
- * user to rescan skipped devices later.
- * We also return error for devices not flagged
- * for SCAN LUNS in the NVRAM since some mono-lun
- * devices behave badly when asked for some non
- * zero LUN. Btw, this is an absolute hack.:-)
- */
- if (cmd->cmnd[0] == 0x12 || cmd->cmnd[0] == 0x0) {
- if ((tp->usrflags & SYM_SCAN_BOOT_DISABLED) ||
- ((tp->usrflags & SYM_SCAN_LUNS_DISABLED) &&
- sdev->lun != 0)) {
- tp->usrflags &= ~SYM_SCAN_BOOT_DISABLED;
- sym_xpt_done2(np, cmd, CAM_DEV_NOT_THERE);
- return 0;
- }
- }
-
- /*
* Select tagged/untagged.
*/
lp = sym_lp(tp, sdev->lun);
@@ -511,23 +501,10 @@ static int sym_queue_command(struct sym_hcb *np, struct scsi_cmnd *cmd)
*/
static inline int sym_setup_cdb(struct sym_hcb *np, struct scsi_cmnd *cmd, struct sym_ccb *cp)
{
- u32 cmd_ba;
- int cmd_len;
-
- /*
- * CDB is 16 bytes max.
- */
- if (cmd->cmd_len > sizeof(cp->cdb_buf)) {
- sym_set_cam_status(cp->cmd, CAM_REQ_INVALID);
- return -1;
- }
-
memcpy(cp->cdb_buf, cmd->cmnd, cmd->cmd_len);
- cmd_ba = CCB_BA (cp, cdb_buf[0]);
- cmd_len = cmd->cmd_len;
- cp->phys.cmd.addr = cpu_to_scr(cmd_ba);
- cp->phys.cmd.size = cpu_to_scr(cmd_len);
+ cp->phys.cmd.addr = CCB_BA(cp, cdb_buf[0]);
+ cp->phys.cmd.size = cpu_to_scr(cmd->cmd_len);
return 0;
}
@@ -554,10 +531,7 @@ int sym_setup_data_and_start(struct sym_hcb *np, struct scsi_cmnd *cmd, struct s
if (dir != DMA_NONE) {
cp->segments = sym_scatter(np, cp, cmd);
if (cp->segments < 0) {
- if (cp->segments == -2)
- sym_set_cam_status(cmd, CAM_RESRC_UNAVAIL);
- else
- sym_set_cam_status(cmd, CAM_REQ_TOO_BIG);
+ sym_set_cam_status(cmd, DID_ERROR);
goto out_abort;
}
} else {
@@ -855,7 +829,7 @@ prepare:
ep->to_do = to_do;
/* Complete the command with locks held as required by the driver */
if (to_do == SYM_EH_DO_COMPLETE)
- sym_xpt_done2(np, cmd, CAM_REQ_ABORTED);
+ sym_xpt_done2(np, cmd, DID_ABORT);
/* Wait for completion with locks released, as required by kernel */
if (to_do == SYM_EH_DO_WAIT) {
@@ -882,22 +856,46 @@ prepare:
*/
static int sym53c8xx_eh_abort_handler(struct scsi_cmnd *cmd)
{
- return sym_eh_handler(SYM_EH_ABORT, "ABORT", cmd);
+ int rc;
+
+ spin_lock_irq(cmd->device->host->host_lock);
+ rc = sym_eh_handler(SYM_EH_ABORT, "ABORT", cmd);
+ spin_unlock_irq(cmd->device->host->host_lock);
+
+ return rc;
}
static int sym53c8xx_eh_device_reset_handler(struct scsi_cmnd *cmd)
{
- return sym_eh_handler(SYM_EH_DEVICE_RESET, "DEVICE RESET", cmd);
+ int rc;
+
+ spin_lock_irq(cmd->device->host->host_lock);
+ rc = sym_eh_handler(SYM_EH_DEVICE_RESET, "DEVICE RESET", cmd);
+ spin_unlock_irq(cmd->device->host->host_lock);
+
+ return rc;
}
static int sym53c8xx_eh_bus_reset_handler(struct scsi_cmnd *cmd)
{
- return sym_eh_handler(SYM_EH_BUS_RESET, "BUS RESET", cmd);
+ int rc;
+
+ spin_lock_irq(cmd->device->host->host_lock);
+ rc = sym_eh_handler(SYM_EH_BUS_RESET, "BUS RESET", cmd);
+ spin_unlock_irq(cmd->device->host->host_lock);
+
+ return rc;
}
static int sym53c8xx_eh_host_reset_handler(struct scsi_cmnd *cmd)
{
- return sym_eh_handler(SYM_EH_HOST_RESET, "HOST RESET", cmd);
+ int rc;
+
+ spin_lock_irq(cmd->device->host->host_lock);
+ rc = sym_eh_handler(SYM_EH_HOST_RESET, "HOST RESET", cmd);
+ spin_unlock_irq(cmd->device->host->host_lock);
+
+ return rc;
}
/*
@@ -921,7 +919,7 @@ static void sym_tune_dev_queuing(struct sym_tcb *tp, int lun, u_short reqtags)
lp->s.reqtags = reqtags;
if (reqtags != oldtags) {
- dev_info(&tp->sdev->sdev_target->dev,
+ dev_info(&tp->starget->dev,
"tagged command queuing %s, command queue depth %d.\n",
lp->s.reqtags ? "enabled" : "disabled",
lp->started_limit);
@@ -981,22 +979,34 @@ static int device_queue_depth(struct sym_hcb *np, int target, int lun)
return DEF_DEPTH;
}
-static int sym53c8xx_slave_alloc(struct scsi_device *device)
+static int sym53c8xx_slave_alloc(struct scsi_device *sdev)
{
- struct sym_hcb *np = sym_get_hcb(device->host);
- struct sym_tcb *tp = &np->target[device->id];
- if (!tp->sdev)
- tp->sdev = device;
+ struct sym_hcb *np;
+ struct sym_tcb *tp;
- return 0;
-}
+ if (sdev->id >= SYM_CONF_MAX_TARGET || sdev->lun >= SYM_CONF_MAX_LUN)
+ return -ENXIO;
-static void sym53c8xx_slave_destroy(struct scsi_device *device)
-{
- struct sym_hcb *np = sym_get_hcb(device->host);
- struct sym_tcb *tp = &np->target[device->id];
- if (tp->sdev == device)
- tp->sdev = NULL;
+ np = sym_get_hcb(sdev->host);
+ tp = &np->target[sdev->id];
+
+ /*
+ * Fail the device init if the device is flagged NOSCAN at BOOT in
+ * the NVRAM. This may speed up boot and maintain coherency with
+ * BIOS device numbering. Clearing the flag allows the user to
+ * rescan skipped devices later. We also return an error for
+ * devices not flagged for SCAN LUNS in the NVRAM since some single
+ * lun devices behave badly when asked for a non zero LUN.
+ */
+
+ if ((tp->usrflags & SYM_SCAN_BOOT_DISABLED) ||
+ ((tp->usrflags & SYM_SCAN_LUNS_DISABLED) && sdev->lun != 0)) {
+ tp->usrflags &= ~SYM_SCAN_BOOT_DISABLED;
+ return -ENXIO;
+ }
+
+ tp->starget = sdev->sdev_target;
+ return 0;
}
/*
@@ -1897,6 +1907,7 @@ static int sym_detach(struct sym_hcb *np, struct pci_dev *pdev)
*/
printk("%s: resetting chip\n", sym_name(np));
OUTB(np, nc_istat, SRST);
+ INB(np, nc_mbox1);
udelay(10);
OUTB(np, nc_istat, 0);
@@ -1915,7 +1926,6 @@ static struct scsi_host_template sym2_template = {
.queuecommand = sym53c8xx_queue_command,
.slave_alloc = sym53c8xx_slave_alloc,
.slave_configure = sym53c8xx_slave_configure,
- .slave_destroy = sym53c8xx_slave_destroy,
.eh_abort_handler = sym53c8xx_eh_abort_handler,
.eh_device_reset_handler = sym53c8xx_eh_device_reset_handler,
.eh_bus_reset_handler = sym53c8xx_eh_bus_reset_handler,
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h
index e943f167fb5..d3d52f14d7c 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.h
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.h
@@ -142,33 +142,6 @@
#define scr_to_cpu(dw) le32_to_cpu(dw)
/*
- * Remap some status field values.
- */
-#define CAM_REQ_CMP DID_OK
-#define CAM_SEL_TIMEOUT DID_NO_CONNECT
-#define CAM_CMD_TIMEOUT DID_TIME_OUT
-#define CAM_REQ_ABORTED DID_ABORT
-#define CAM_UNCOR_PARITY DID_PARITY
-#define CAM_SCSI_BUS_RESET DID_RESET
-#define CAM_REQUEUE_REQ DID_SOFT_ERROR
-#define CAM_UNEXP_BUSFREE DID_ERROR
-#define CAM_SCSI_BUSY DID_BUS_BUSY
-
-#define CAM_DEV_NOT_THERE DID_NO_CONNECT
-#define CAM_REQ_INVALID DID_ERROR
-#define CAM_REQ_TOO_BIG DID_ERROR
-
-#define CAM_RESRC_UNAVAIL DID_ERROR
-
-/*
- * Remap data direction values.
- */
-#define CAM_DIR_NONE DMA_NONE
-#define CAM_DIR_IN DMA_FROM_DEVICE
-#define CAM_DIR_OUT DMA_TO_DEVICE
-#define CAM_DIR_UNKNOWN DMA_BIDIRECTIONAL
-
-/*
* These ones are used as return code from
* error recovery handlers under Linux.
*/
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index 50a176b3888..e753ba27dc5 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -97,7 +97,7 @@ static void sym_print_msg(struct sym_ccb *cp, char *label, u_char *msg)
static void sym_print_nego_msg(struct sym_hcb *np, int target, char *label, u_char *msg)
{
struct sym_tcb *tp = &np->target[target];
- dev_info(&tp->sdev->sdev_target->dev, "%s: ", label);
+ dev_info(&tp->starget->dev, "%s: ", label);
sym_show_msg(msg);
printf(".\n");
@@ -149,8 +149,10 @@ static char *sym_scsi_bus_mode(int mode)
static void sym_chip_reset (struct sym_hcb *np)
{
OUTB(np, nc_istat, SRST);
+ INB(np, nc_mbox1);
udelay(10);
OUTB(np, nc_istat, 0);
+ INB(np, nc_mbox1);
udelay(2000); /* For BUS MODE to settle */
}
@@ -216,6 +218,7 @@ int sym_reset_scsi_bus(struct sym_hcb *np, int enab_int)
OUTB(np, nc_stest3, TE);
OUTB(np, nc_dcntl, (np->rv_dcntl & IRQM));
OUTB(np, nc_scntl1, CRST);
+ INB(np, nc_mbox1);
udelay(200);
if (!SYM_SETUP_SCSI_BUS_CHECK)
@@ -280,8 +283,10 @@ static void sym_selectclock(struct sym_hcb *np, u_char scntl3)
if (!i)
printf("%s: the chip cannot lock the frequency\n",
sym_name(np));
- } else
- udelay((50+10));
+ } else {
+ INB(np, nc_mbox1);
+ udelay(50+10);
+ }
OUTB(np, nc_stest3, HSC); /* Halt the scsi clock */
OUTB(np, nc_scntl3, scntl3);
OUTB(np, nc_stest1, (DBLEN|DBLSEL));/* Select clock multiplier */
@@ -1445,7 +1450,7 @@ static void sym_check_goals(struct sym_hcb *np, struct scsi_target *starget,
static int sym_prepare_nego(struct sym_hcb *np, struct sym_ccb *cp, u_char *msgptr)
{
struct sym_tcb *tp = &np->target[cp->target];
- struct scsi_target *starget = tp->sdev->sdev_target;
+ struct scsi_target *starget = tp->starget;
struct sym_trans *goal = &tp->tgoal;
int msglen = 0;
int nego;
@@ -1690,7 +1695,7 @@ static void sym_flush_comp_queue(struct sym_hcb *np, int cam_status)
if (cam_status)
sym_set_cam_status(cmd, cam_status);
#ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
- if (sym_get_cam_status(cmd) == CAM_REQUEUE_REQ) {
+ if (sym_get_cam_status(cmd) == DID_SOFT_ERROR) {
struct sym_tcb *tp = &np->target[cp->target];
struct sym_lcb *lp = sym_lp(tp, cp->lun);
if (lp) {
@@ -1791,12 +1796,13 @@ void sym_start_up (struct sym_hcb *np, int reason)
/*
* Wakeup all pending jobs.
*/
- sym_flush_busy_queue(np, CAM_SCSI_BUS_RESET);
+ sym_flush_busy_queue(np, DID_RESET);
/*
* Init chip.
*/
OUTB(np, nc_istat, 0x00); /* Remove Reset, abort */
+ INB(np, nc_mbox1);
udelay(2000); /* The 895 needs time for the bus mode to settle */
OUTB(np, nc_scntl0, np->rv_scntl0 | 0xc0);
@@ -1905,6 +1911,7 @@ void sym_start_up (struct sym_hcb *np, int reason)
if (np->features & (FE_ULTRA2|FE_ULTRA3)) {
OUTONW(np, nc_sien, SBMC);
if (reason == 0) {
+ INB(np, nc_mbox1);
mdelay(100);
INW(np, nc_sist);
}
@@ -2074,7 +2081,7 @@ static void sym_settrans(struct sym_hcb *np, int target, u_char opts, u_char ofs
static void sym_setwide(struct sym_hcb *np, int target, u_char wide)
{
struct sym_tcb *tp = &np->target[target];
- struct scsi_target *starget = tp->sdev->sdev_target;
+ struct scsi_target *starget = tp->starget;
if (spi_width(starget) == wide)
return;
@@ -2102,7 +2109,7 @@ sym_setsync(struct sym_hcb *np, int target,
u_char ofs, u_char per, u_char div, u_char fak)
{
struct sym_tcb *tp = &np->target[target];
- struct scsi_target *starget = tp->sdev->sdev_target;
+ struct scsi_target *starget = tp->starget;
u_char wide = (tp->head.wval & EWS) ? BUS_16_BIT : BUS_8_BIT;
sym_settrans(np, target, 0, ofs, per, wide, div, fak);
@@ -2129,7 +2136,7 @@ sym_setpprot(struct sym_hcb *np, int target, u_char opts, u_char ofs,
u_char per, u_char wide, u_char div, u_char fak)
{
struct sym_tcb *tp = &np->target[target];
- struct scsi_target *starget = tp->sdev->sdev_target;
+ struct scsi_target *starget = tp->starget;
sym_settrans(np, target, opts, ofs, per, wide, div, fak);
@@ -2944,7 +2951,7 @@ unknown_int:
* Dequeue from the START queue all CCBs that match
* a given target/lun/task condition (-1 means all),
* and move them from the BUSY queue to the COMP queue
- * with CAM_REQUEUE_REQ status condition.
+ * with DID_SOFT_ERROR status condition.
* This function is used during error handling/recovery.
* It is called with SCRIPTS not running.
*/
@@ -2974,7 +2981,7 @@ sym_dequeue_from_squeue(struct sym_hcb *np, int i, int target, int lun, int task
if ((target == -1 || cp->target == target) &&
(lun == -1 || cp->lun == lun) &&
(task == -1 || cp->tag == task)) {
- sym_set_cam_status(cp->cmd, CAM_REQUEUE_REQ);
+ sym_set_cam_status(cp->cmd, DID_SOFT_ERROR);
sym_remque(&cp->link_ccbq);
sym_insque_tail(&cp->link_ccbq, &np->comp_ccbq);
}
@@ -3093,13 +3100,13 @@ static void sym_sir_bad_scsi_status(struct sym_hcb *np, int num, struct sym_ccb
/*
* Message table indirect structure.
*/
- cp->phys.smsg.addr = cpu_to_scr(CCB_BA(cp, scsi_smsg2));
+ cp->phys.smsg.addr = CCB_BA(cp, scsi_smsg2);
cp->phys.smsg.size = cpu_to_scr(msglen);
/*
* sense command
*/
- cp->phys.cmd.addr = cpu_to_scr(CCB_BA(cp, sensecmd));
+ cp->phys.cmd.addr = CCB_BA(cp, sensecmd);
cp->phys.cmd.size = cpu_to_scr(6);
/*
@@ -3116,7 +3123,7 @@ static void sym_sir_bad_scsi_status(struct sym_hcb *np, int num, struct sym_ccb
* sense data
*/
memset(cp->sns_bbuf, 0, SYM_SNS_BBUF_LEN);
- cp->phys.sense.addr = cpu_to_scr(CCB_BA(cp, sns_bbuf));
+ cp->phys.sense.addr = CCB_BA(cp, sns_bbuf);
cp->phys.sense.size = cpu_to_scr(SYM_SNS_BBUF_LEN);
/*
@@ -3198,7 +3205,7 @@ int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int
sym_insque_tail(&cp->link_ccbq, &np->comp_ccbq);
/* Preserve the software timeout condition */
- if (sym_get_cam_status(cmd) != CAM_CMD_TIMEOUT)
+ if (sym_get_cam_status(cmd) != DID_TIME_OUT)
sym_set_cam_status(cmd, cam_status);
++i;
#if 0
@@ -3366,7 +3373,7 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num)
* Make sure at least our IO to abort has been dequeued.
*/
#ifndef SYM_OPT_HANDLE_DEVICE_QUEUEING
- assert(i && sym_get_cam_status(cp->cmd) == CAM_REQUEUE_REQ);
+ assert(i && sym_get_cam_status(cp->cmd) == DID_SOFT_ERROR);
#else
sym_remque(&cp->link_ccbq);
sym_insque_tail(&cp->link_ccbq, &np->comp_ccbq);
@@ -3375,9 +3382,9 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num)
* Keep track in cam status of the reason of the abort.
*/
if (cp->to_abort == 2)
- sym_set_cam_status(cp->cmd, CAM_CMD_TIMEOUT);
+ sym_set_cam_status(cp->cmd, DID_TIME_OUT);
else
- sym_set_cam_status(cp->cmd, CAM_REQ_ABORTED);
+ sym_set_cam_status(cp->cmd, DID_ABORT);
/*
* Complete with error everything that we have dequeued.
@@ -3491,7 +3498,7 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num)
* conditions not due to timeout.
*/
if (cp->to_abort == 2)
- sym_set_cam_status(cp->cmd, CAM_CMD_TIMEOUT);
+ sym_set_cam_status(cp->cmd, DID_TIME_OUT);
cp->to_abort = 0; /* We donnot expect to fail here */
break;
@@ -3502,7 +3509,7 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num)
case SIR_ABORT_SENT:
target = INB(np, nc_sdid) & 0xf;
tp = &np->target[target];
- starget = tp->sdev->sdev_target;
+ starget = tp->starget;
/*
** If we didn't abort anything, leave here.
@@ -3551,7 +3558,7 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num)
*/
i = (INL(np, nc_scratcha) - np->squeue_ba) / 4;
sym_dequeue_from_squeue(np, i, target, lun, -1);
- sym_clear_tasks(np, CAM_REQ_ABORTED, target, lun, task);
+ sym_clear_tasks(np, DID_ABORT, target, lun, task);
sym_flush_comp_queue(np, 0);
/*
@@ -3566,7 +3573,7 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num)
* Print to the log the message we intend to send.
*/
if (num == SIR_TARGET_SELECTED) {
- dev_info(&tp->sdev->sdev_target->dev, "control msgout:");
+ dev_info(&tp->starget->dev, "control msgout:");
sym_printl_hex(np->abrt_msg, np->abrt_tbl.size);
np->abrt_tbl.size = cpu_to_scr(np->abrt_tbl.size);
}
@@ -3877,6 +3884,8 @@ int sym_compute_residual(struct sym_hcb *np, struct sym_ccb *cp)
resid += (tmp & 0xffffff);
}
+ resid -= cp->odd_byte_adjustment;
+
/*
* Hopefully, the result is not too wrong.
*/
@@ -4758,10 +4767,8 @@ struct sym_ccb *sym_get_ccb (struct sym_hcb *np, struct scsi_cmnd *cmd, u_char t
}
#endif
- /*
- * Remember all informations needed to free this CCB.
- */
cp->to_abort = 0;
+ cp->odd_byte_adjustment = 0;
cp->tag = tag;
cp->order = tag_order;
cp->target = tn;
@@ -5104,7 +5111,7 @@ static void sym_alloc_lcb_tags (struct sym_hcb *np, u_char tn, u_char ln)
lp->itlq_tbl = sym_calloc_dma(SYM_CONF_MAX_TASK*4, "ITLQ_TBL");
if (!lp->itlq_tbl)
goto fail;
- lp->cb_tags = kcalloc(SYM_CONF_MAX_TASK, 1, GFP_KERNEL);
+ lp->cb_tags = kcalloc(SYM_CONF_MAX_TASK, 1, GFP_ATOMIC);
if (!lp->cb_tags) {
sym_mfree_dma(lp->itlq_tbl, SYM_CONF_MAX_TASK*4, "ITLQ_TBL");
lp->itlq_tbl = NULL;
@@ -5243,7 +5250,7 @@ int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *cmd, struct sym_ccb *
/*
* message
*/
- cp->phys.smsg.addr = cpu_to_scr(CCB_BA(cp, scsi_smsg));
+ cp->phys.smsg.addr = CCB_BA(cp, scsi_smsg);
cp->phys.smsg.size = cpu_to_scr(msglen);
/*
@@ -5343,7 +5350,7 @@ int sym_abort_scsiio(struct sym_hcb *np, struct scsi_cmnd *cmd, int timed_out)
}
/*
- * Complete execution of a SCSI command with extented
+ * Complete execution of a SCSI command with extended
* error, SCSI status error, or having been auto-sensed.
*
* The SCRIPTS processor is not running there, so we
@@ -5441,7 +5448,7 @@ if (resid)
/*
* Let's requeue it to device.
*/
- sym_set_cam_status(cmd, CAM_REQUEUE_REQ);
+ sym_set_cam_status(cmd, DID_SOFT_ERROR);
goto finish;
}
weirdness:
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h
index a95cbe4b8e3..c55c7a57afa 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.h
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h
@@ -444,7 +444,7 @@ struct sym_tcb {
*/
u_char usrflags;
u_short usrtags;
- struct scsi_device *sdev;
+ struct scsi_target *starget;
};
/*
@@ -754,10 +754,8 @@ struct sym_ccb {
int segments; /* Number of SG segments */
u8 order; /* Tag type (if tagged command) */
+ unsigned char odd_byte_adjustment; /* odd-sized req on wide bus */
- /*
- * Miscellaneous status'.
- */
u_char nego_status; /* Negotiation status */
u_char xerr_status; /* Extended error flags */
u32 extra_bytes; /* Extraneous bytes transferred */
@@ -809,7 +807,7 @@ struct sym_ccb {
#endif
};
-#define CCB_BA(cp,lbl) (cp->ccb_ba + offsetof(struct sym_ccb, lbl))
+#define CCB_BA(cp,lbl) cpu_to_scr(cp->ccb_ba + offsetof(struct sym_ccb, lbl))
#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
#define sym_goalp(cp) ((cp->host_flags & HF_DATA_IN) ? cp->goalp : cp->wgoalp)
@@ -1138,33 +1136,33 @@ static inline void sym_setup_data_pointers(struct sym_hcb *np,
* No segments means no data.
*/
if (!cp->segments)
- dir = CAM_DIR_NONE;
+ dir = DMA_NONE;
/*
* Set the data pointer.
*/
switch(dir) {
#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
- case CAM_DIR_UNKNOWN:
+ case DMA_BIDIRECTIONAL:
#endif
- case CAM_DIR_OUT:
+ case DMA_TO_DEVICE:
goalp = SCRIPTA_BA(np, data_out2) + 8;
lastp = goalp - 8 - (cp->segments * (2*4));
#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
cp->wgoalp = cpu_to_scr(goalp);
- if (dir != CAM_DIR_UNKNOWN)
+ if (dir != DMA_BIDIRECTIONAL)
break;
cp->phys.head.wlastp = cpu_to_scr(lastp);
/* fall through */
#else
break;
#endif
- case CAM_DIR_IN:
+ case DMA_FROM_DEVICE:
cp->host_flags |= HF_DATA_IN;
goalp = SCRIPTA_BA(np, data_in2) + 8;
lastp = goalp - 8 - (cp->segments * (2*4));
break;
- case CAM_DIR_NONE:
+ case DMA_NONE:
default:
#ifdef SYM_OPT_HANDLE_DIR_UNKNOWN
cp->host_flags |= HF_DATA_IN;
@@ -1185,7 +1183,7 @@ static inline void sym_setup_data_pointers(struct sym_hcb *np,
/*
* If direction is unknown, start at data_io.
*/
- if (dir == CAM_DIR_UNKNOWN)
+ if (dir == DMA_BIDIRECTIONAL)
cp->phys.head.savep = cpu_to_scr(SCRIPTB_BA(np, data_io));
#endif
}
diff --git a/drivers/scsi/sym53c8xx_2/sym_nvram.c b/drivers/scsi/sym53c8xx_2/sym_nvram.c
index 1b721e3ec52..cd9140e158c 100644
--- a/drivers/scsi/sym53c8xx_2/sym_nvram.c
+++ b/drivers/scsi/sym53c8xx_2/sym_nvram.c
@@ -270,6 +270,7 @@ static void S24C16_set_bit(struct sym_device *np, u_char write_bit, u_char *gpre
}
OUTB(np, nc_gpreg, *gpreg);
+ INB(np, nc_mbox1);
udelay(5);
}
@@ -547,6 +548,7 @@ static int sym_read_Symbios_nvram(struct sym_device *np, Symbios_nvram *nvram)
static void T93C46_Clk(struct sym_device *np, u_char *gpreg)
{
OUTB(np, nc_gpreg, *gpreg | 0x04);
+ INB(np, nc_mbox1);
udelay(2);
OUTB(np, nc_gpreg, *gpreg);
}
@@ -574,6 +576,7 @@ static void T93C46_Write_Bit(struct sym_device *np, u_char write_bit, u_char *gp
*gpreg |= 0x10;
OUTB(np, nc_gpreg, *gpreg);
+ INB(np, nc_mbox1);
udelay(2);
T93C46_Clk(np, gpreg);
@@ -586,6 +589,7 @@ static void T93C46_Stop(struct sym_device *np, u_char *gpreg)
{
*gpreg &= 0xef;
OUTB(np, nc_gpreg, *gpreg);
+ INB(np, nc_mbox1);
udelay(2);
T93C46_Clk(np, gpreg);
@@ -733,7 +737,8 @@ static int sym_read_parisc_pdc(struct sym_device *np, struct pdc_initiator *pdc)
return SYM_PARISC_PDC;
}
#else
-static int sym_read_parisc_pdc(struct sym_device *np, struct pdc_initiator *x)
+static inline int sym_read_parisc_pdc(struct sym_device *np,
+ struct pdc_initiator *x)
{
return 0;
}
diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c
index 6dc2897672a..f4b780e35cb 100644
--- a/drivers/scsi/t128.c
+++ b/drivers/scsi/t128.c
@@ -437,8 +437,6 @@ static Scsi_Host_Template driver_template = {
.queuecommand = t128_queue_command,
.eh_abort_handler = t128_abort,
.eh_bus_reset_handler = t128_bus_reset,
- .eh_host_reset_handler = t128_host_reset,
- .eh_device_reset_handler = t128_device_reset,
.bios_param = t128_biosparam,
.can_queue = CAN_QUEUE,
.this_id = 7,
diff --git a/drivers/scsi/t128.h b/drivers/scsi/t128.h
index 161ba53d982..9ad1d68827a 100644
--- a/drivers/scsi/t128.h
+++ b/drivers/scsi/t128.h
@@ -96,9 +96,7 @@ static int t128_biosparam(struct scsi_device *, struct block_device *,
sector_t, int*);
static int t128_detect(Scsi_Host_Template *);
static int t128_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-static int t128_host_reset(Scsi_Cmnd *);
static int t128_bus_reset(Scsi_Cmnd *);
-static int t128_device_reset(Scsi_Cmnd *);
#ifndef CMD_PER_LUN
#define CMD_PER_LUN 2
@@ -140,8 +138,6 @@ static int t128_device_reset(Scsi_Cmnd *);
#define do_NCR5380_intr do_t128_intr
#define NCR5380_queue_command t128_queue_command
#define NCR5380_abort t128_abort
-#define NCR5380_host_reset t128_host_reset
-#define NCR5380_device_reset t128_device_reset
#define NCR5380_bus_reset t128_bus_reset
#define NCR5380_proc_info t128_proc_info
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
index ee9df02efd5..9589c67de53 100644
--- a/drivers/scsi/tmscsim.c
+++ b/drivers/scsi/tmscsim.c
@@ -2120,6 +2120,8 @@ static int DC390_bus_reset (struct scsi_cmnd *cmd)
struct dc390_acb* pACB = (struct dc390_acb*) cmd->device->host->hostdata;
u8 bval;
+ spin_lock_irq(cmd->device->host->host_lock);
+
bval = DC390_read8(CtrlReg1) | DIS_INT_ON_SCSI_RST;
DC390_write8(CtrlReg1, bval); /* disable IRQ on bus reset */
@@ -2127,7 +2129,7 @@ static int DC390_bus_reset (struct scsi_cmnd *cmd)
dc390_ResetSCSIBus(pACB);
dc390_ResetDevParam(pACB);
- udelay(1000);
+ mdelay(1);
pACB->pScsiHost->last_reset = jiffies + 3*HZ/2
+ HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
@@ -2142,6 +2144,8 @@ static int DC390_bus_reset (struct scsi_cmnd *cmd)
bval = DC390_read8(CtrlReg1) & ~DIS_INT_ON_SCSI_RST;
DC390_write8(CtrlReg1, bval); /* re-enable interrupt */
+ spin_unlock_irq(cmd->device->host->host_lock);
+
return SUCCESS;
}
diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c
index dca215411f6..98369ce0928 100644
--- a/drivers/scsi/u14-34f.c
+++ b/drivers/scsi/u14-34f.c
@@ -446,8 +446,6 @@ static struct scsi_host_template driver_template = {
.release = u14_34f_release,
.queuecommand = u14_34f_queuecommand,
.eh_abort_handler = u14_34f_eh_abort,
- .eh_device_reset_handler = NULL,
- .eh_bus_reset_handler = NULL,
.eh_host_reset_handler = u14_34f_eh_host_reset,
.bios_param = u14_34f_bios_param,
.slave_configure = u14_34f_slave_configure,
@@ -1419,16 +1417,20 @@ static int u14_34f_eh_host_reset(struct scsi_cmnd *SCarg) {
printk("%s: reset, enter, target %d.%d:%d, pid %ld.\n",
BN(j), SCarg->device->channel, SCarg->device->id, SCarg->device->lun, SCarg->pid);
+ spin_lock_irq(sh[j]->host_lock);
+
if (SCarg->host_scribble == NULL)
printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->pid);
if (HD(j)->in_reset) {
printk("%s: reset, exit, already in reset.\n", BN(j));
+ spin_unlock_irq(sh[j]->host_lock);
return FAILED;
}
if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {
printk("%s: reset, exit, timeout error.\n", BN(j));
+ spin_unlock_irq(sh[j]->host_lock);
return FAILED;
}
@@ -1479,6 +1481,7 @@ static int u14_34f_eh_host_reset(struct scsi_cmnd *SCarg) {
if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {
printk("%s: reset, cannot reset, timeout error.\n", BN(j));
+ spin_unlock_irq(sh[j]->host_lock);
return FAILED;
}
@@ -1540,6 +1543,7 @@ static int u14_34f_eh_host_reset(struct scsi_cmnd *SCarg) {
if (arg_done) printk("%s: reset, exit, pid %ld done.\n", BN(j), SCarg->pid);
else printk("%s: reset, exit.\n", BN(j));
+ spin_unlock_irq(sh[j]->host_lock);
return SUCCESS;
}
diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c
index 97f4d9112b4..486551bd54b 100644
--- a/drivers/scsi/ultrastor.c
+++ b/drivers/scsi/ultrastor.c
@@ -879,7 +879,7 @@ static int ultrastor_abort(Scsi_Cmnd *SCpnt)
ogm_addr = (unsigned int)isa_bus_to_virt(inl(port0 + 23));
icm_status = inb(port0 + 27);
icm_addr = (unsigned int)isa_bus_to_virt(inl(port0 + 28));
- spin_lock_irqsave(host->host_lock, flags);
+ spin_unlock_irqrestore(host->host_lock, flags);
}
/* First check to see if an interrupt is pending. I suspect the SiS
@@ -954,9 +954,7 @@ static int ultrastor_abort(Scsi_Cmnd *SCpnt)
SCpnt->result = DID_ABORT << 16;
/* Take the host lock to guard against scsi layer re-entry */
- spin_lock_irqsave(host->host_lock, flags);
done(SCpnt);
- spin_unlock_irqrestore(host->host_lock, flags);
/* Need to set a timeout here in case command never completes. */
return SUCCESS;
diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c
index bf4a758e280..fb54a87a80a 100644
--- a/drivers/scsi/wd7000.c
+++ b/drivers/scsi/wd7000.c
@@ -1586,9 +1586,16 @@ static int wd7000_host_reset(struct scsi_cmnd *SCpnt)
{
Adapter *host = (Adapter *) SCpnt->device->host->hostdata;
- if (wd7000_adapter_reset(host) < 0)
+ spin_unlock_irq(SCpnt->device->host->host_lock);
+
+ if (wd7000_adapter_reset(host) < 0) {
+ spin_unlock_irq(SCpnt->device->host->host_lock);
return FAILED;
+ }
+
wd7000_enable_intr(host);
+
+ spin_unlock_irq(SCpnt->device->host->host_lock);
return SUCCESS;
}
diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c
index 33fbda79f35..0b10169961e 100644
--- a/drivers/serial/21285.c
+++ b/drivers/serial/21285.c
@@ -126,18 +126,8 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id, struct pt_regs *r
flag = TTY_FRAME;
}
- if ((rxs & port->ignore_status_mask) == 0) {
- tty_insert_flip_char(tty, ch, flag);
- }
- if ((rxs & RXSTAT_OVERRUN) &&
- tty->flip.count < TTY_FLIPBUF_SIZE) {
- /*
- * Overrun is special, since it's reported
- * immediately, and doesn't affect the current
- * character.
- */
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- }
+ uart_insert_char(port, rxs, RXSTAT_OVERRUN, ch, flag);
+
status = *CSR_UARTFLG;
}
tty_flip_buffer_push(tty);
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
index db92a0ceda7..feb8e73fc1c 100644
--- a/drivers/serial/68328serial.c
+++ b/drivers/serial/68328serial.c
@@ -992,18 +992,17 @@ static int get_lsr_info(struct m68k_serial * info, unsigned int *value)
/*
* This routine sends a break character out the serial port.
*/
-static void send_break( struct m68k_serial * info, int duration)
+static void send_break(struct m68k_serial * info, unsigned int duration)
{
m68328_uart *uart = &uart_addr[info->line];
unsigned long flags;
if (!info->port)
return;
- set_current_state(TASK_INTERRUPTIBLE);
save_flags(flags);
cli();
#ifdef USE_INTS
uart->utx.w |= UTX_SEND_BREAK;
- schedule_timeout(duration);
+ msleep_interruptible(duration);
uart->utx.w &= ~UTX_SEND_BREAK;
#endif
restore_flags(flags);
@@ -1033,14 +1032,14 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
return retval;
tty_wait_until_sent(tty, 0);
if (!arg)
- send_break(info, HZ/4); /* 1/4 second */
+ send_break(info, 250); /* 1/4 second */
return 0;
case TCSBRKP: /* support for POSIX tcsendbreak() */
retval = tty_check_change(tty);
if (retval)
return retval;
tty_wait_until_sent(tty, 0);
- send_break(info, arg ? arg*(HZ/10) : HZ/4);
+ send_break(info, arg ? arg*(100) : 250);
return 0;
case TIOCGSOFTCAR:
error = put_user(C_CLOCAL(tty) ? 1 : 0,
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
index f148022b6b4..b116122e569 100644
--- a/drivers/serial/68360serial.c
+++ b/drivers/serial/68360serial.c
@@ -1394,14 +1394,13 @@ static void end_break(ser_info_t *info)
/*
* This routine sends a break character out the serial port.
*/
-static void send_break(ser_info_t *info, int duration)
+static void send_break(ser_info_t *info, unsigned int duration)
{
- set_current_state(TASK_INTERRUPTIBLE);
#ifdef SERIAL_DEBUG_SEND_BREAK
printk("rs_send_break(%d) jiff=%lu...", duration, jiffies);
#endif
begin_break(info);
- schedule_timeout(duration);
+ msleep_interruptible(duration);
end_break(info);
#ifdef SERIAL_DEBUG_SEND_BREAK
printk("done jiffies=%lu\n", jiffies);
@@ -1436,7 +1435,7 @@ static int rs_360_ioctl(struct tty_struct *tty, struct file * file,
if (signal_pending(current))
return -EINTR;
if (!arg) {
- send_break(info, HZ/4); /* 1/4 second */
+ send_break(info, 250); /* 1/4 second */
if (signal_pending(current))
return -EINTR;
}
@@ -1448,7 +1447,7 @@ static int rs_360_ioctl(struct tty_struct *tty, struct file * file,
tty_wait_until_sent(tty, 0);
if (signal_pending(current))
return -EINTR;
- send_break(info, arg ? arg*(HZ/10) : HZ/4);
+ send_break(info, arg ? arg*100 : 250);
if (signal_pending(current))
return -EINTR;
return 0;
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 0d9358608fd..d8b9d2b8c20 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -132,9 +132,9 @@ struct uart_8250_port {
struct uart_port port;
struct timer_list timer; /* "no irq" timer */
struct list_head list; /* ports on this IRQ */
- unsigned int capabilities; /* port capabilities */
+ unsigned short capabilities; /* port capabilities */
+ unsigned short bugs; /* port bugs */
unsigned int tx_loadsz; /* transmit fifo load size */
- unsigned short rev;
unsigned char acr;
unsigned char ier;
unsigned char lcr;
@@ -560,7 +560,14 @@ static void autoconfig_has_efr(struct uart_8250_port *up)
if (id1 == 0x16 && id2 == 0xC9 &&
(id3 == 0x50 || id3 == 0x52 || id3 == 0x54)) {
up->port.type = PORT_16C950;
- up->rev = rev | (id3 << 8);
+
+ /*
+ * Enable work around for the Oxford Semiconductor 952 rev B
+ * chip which causes it to seriously miscalculate baud rates
+ * when DLL is 0.
+ */
+ if (id3 == 0x52 && rev == 0x01)
+ up->bugs |= UART_BUG_QUOT;
return;
}
@@ -577,8 +584,6 @@ static void autoconfig_has_efr(struct uart_8250_port *up)
id2 = id1 >> 8;
if (id2 == 0x10 || id2 == 0x12 || id2 == 0x14) {
- if (id2 == 0x10)
- up->rev = id1 & 255;
up->port.type = PORT_16850;
return;
}
@@ -682,8 +687,6 @@ static void autoconfig_16550a(struct uart_8250_port *up)
* from EXCR1. Switch back to bank 0, change it in MCR. Then
* switch back to bank 2, read it from EXCR1 again and check
* it's changed. If so, set baud_base in EXCR2 to 921600. -- dwmw2
- * On PowerPC we don't want to change baud_base, as we have
- * a number of different divisors. -- Tom Rini
*/
serial_outp(up, UART_LCR, 0);
status1 = serial_in(up, UART_MCR);
@@ -699,16 +702,25 @@ static void autoconfig_16550a(struct uart_8250_port *up)
serial_outp(up, UART_MCR, status1);
if ((status2 ^ status1) & UART_MCR_LOOP) {
-#ifndef CONFIG_PPC
+ unsigned short quot;
+
serial_outp(up, UART_LCR, 0xE0);
+
+ quot = serial_inp(up, UART_DLM) << 8;
+ quot += serial_inp(up, UART_DLL);
+ quot <<= 3;
+
status1 = serial_in(up, 0x04); /* EXCR1 */
status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
status1 |= 0x10; /* 1.625 divisor for baud_base --> 921600 */
serial_outp(up, 0x04, status1);
+
+ serial_outp(up, UART_DLL, quot & 0xff);
+ serial_outp(up, UART_DLM, quot >> 8);
+
serial_outp(up, UART_LCR, 0);
- up->port.uartclk = 921600*16;
-#endif
+ up->port.uartclk = 921600*16;
up->port.type = PORT_NS16550A;
up->capabilities |= UART_NATSEMI;
return;
@@ -802,6 +814,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
// save_flags(flags); cli();
up->capabilities = 0;
+ up->bugs = 0;
if (!(up->port.flags & UPF_BUGGY_UART)) {
/*
@@ -1014,6 +1027,8 @@ static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop)
}
}
+static void transmit_chars(struct uart_8250_port *up);
+
static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start)
{
struct uart_8250_port *up = (struct uart_8250_port *)port;
@@ -1021,6 +1036,14 @@ static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start)
if (!(up->ier & UART_IER_THRI)) {
up->ier |= UART_IER_THRI;
serial_out(up, UART_IER, up->ier);
+
+ if (up->bugs & UART_BUG_TXEN) {
+ unsigned char lsr, iir;
+ lsr = serial_in(up, UART_LSR);
+ iir = serial_in(up, UART_IIR);
+ if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT)
+ transmit_chars(up);
+ }
}
/*
* We only do this from uart_start
@@ -1122,18 +1145,9 @@ receive_chars(struct uart_8250_port *up, int *status, struct pt_regs *regs)
}
if (uart_handle_sysrq_char(&up->port, ch, regs))
goto ignore_char;
- if ((lsr & up->port.ignore_status_mask) == 0) {
- tty_insert_flip_char(tty, ch, flag);
- }
- if ((lsr & UART_LSR_OE) &&
- tty->flip.count < TTY_FLIPBUF_SIZE) {
- /*
- * Overrun is special, since it's reported
- * immediately, and doesn't affect the current
- * character.
- */
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- }
+
+ uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);
+
ignore_char:
lsr = serial_inp(up, UART_LSR);
} while ((lsr & UART_LSR_DR) && (max_count-- > 0));
@@ -1435,6 +1449,7 @@ static int serial8250_startup(struct uart_port *port)
{
struct uart_8250_port *up = (struct uart_8250_port *)port;
unsigned long flags;
+ unsigned char lsr, iir;
int retval;
up->capabilities = uart_config[up->port.type].flags;
@@ -1538,6 +1553,26 @@ static int serial8250_startup(struct uart_port *port)
up->port.mctrl |= TIOCM_OUT2;
serial8250_set_mctrl(&up->port, up->port.mctrl);
+
+ /*
+ * Do a quick test to see if we receive an
+ * interrupt when we enable the TX irq.
+ */
+ serial_outp(up, UART_IER, UART_IER_THRI);
+ lsr = serial_in(up, UART_LSR);
+ iir = serial_in(up, UART_IIR);
+ serial_outp(up, UART_IER, 0);
+
+ if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
+ if (!(up->bugs & UART_BUG_TXEN)) {
+ up->bugs |= UART_BUG_TXEN;
+ pr_debug("ttyS%d - enabling bad tx status workarounds\n",
+ port->line);
+ }
+ } else {
+ up->bugs &= ~UART_BUG_TXEN;
+ }
+
spin_unlock_irqrestore(&up->port.lock, flags);
/*
@@ -1647,22 +1682,22 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios,
switch (termios->c_cflag & CSIZE) {
case CS5:
- cval = 0x00;
+ cval = UART_LCR_WLEN5;
break;
case CS6:
- cval = 0x01;
+ cval = UART_LCR_WLEN6;
break;
case CS7:
- cval = 0x02;
+ cval = UART_LCR_WLEN7;
break;
default:
case CS8:
- cval = 0x03;
+ cval = UART_LCR_WLEN8;
break;
}
if (termios->c_cflag & CSTOPB)
- cval |= 0x04;
+ cval |= UART_LCR_STOP;
if (termios->c_cflag & PARENB)
cval |= UART_LCR_PARITY;
if (!(termios->c_cflag & PARODD))
@@ -1679,12 +1714,9 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios,
quot = serial8250_get_divisor(port, baud);
/*
- * Work around a bug in the Oxford Semiconductor 952 rev B
- * chip which causes it to seriously miscalculate baud rates
- * when DLL is 0.
+ * Oxford Semi 952 rev B workaround
*/
- if ((quot & 0xff) == 0 && up->port.type == PORT_16C950 &&
- up->rev == 0x5201)
+ if (up->bugs & UART_BUG_QUOT && (quot & 0xff) == 0)
quot ++;
if (up->capabilities & UART_CAP_FIFO && up->port.fifosize > 1) {
diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h
index 4f3d62f222f..9225c82faeb 100644
--- a/drivers/serial/8250.h
+++ b/drivers/serial/8250.h
@@ -51,6 +51,9 @@ struct serial8250_config {
#define UART_CAP_AFE (1 << 11) /* MCR-based hw flow control */
#define UART_CAP_UUE (1 << 12) /* UART needs IER bit 6 set (Xscale) */
+#define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */
+#define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */
+
#if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486))
#define _INLINE_ inline
#else
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 6e44b46c9e9..25fcef2c42d 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -753,7 +753,7 @@ config SERIAL_MPC52xx_CONSOLE_BAUD
config SERIAL_ICOM
tristate "IBM Multiport Serial Adapter"
- depends on PPC_ISERIES || PPC_PSERIES
+ depends on PCI && (PPC_ISERIES || PPC_PSERIES)
select SERIAL_CORE
help
This driver is for a family of multiport serial adapters
@@ -843,4 +843,13 @@ config SERIAL_JSM
To compile this driver as a module, choose M here: the
module will be called jsm.
+config SERIAL_SGI_IOC4
+ tristate "SGI IOC4 controller serial support"
+ depends on (IA64_GENERIC || IA64_SGI_SN2) && SGI_IOC4
+ select SERIAL_CORE
+ help
+ If you have an SGI Altix with an IOC4 based Base IO card
+ and wish to use the serial ports on this card, say Y.
+ Otherwise, say N.
+
endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 81b77d769b8..8f1cdde7dbe 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -51,4 +51,4 @@ obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
obj-$(CONFIG_SERIAL_JSM) += jsm/
obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o
-obj-$(CONFIG_BLK_DEV_SGIIOC4) += ioc4_serial.o
+obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o
diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c
index f2a5e2933c4..2884b310e54 100644
--- a/drivers/serial/amba-pl010.c
+++ b/drivers/serial/amba-pl010.c
@@ -198,18 +198,8 @@ pl010_rx_chars(struct uart_port *port)
if (uart_handle_sysrq_char(port, ch, regs))
goto ignore_char;
- if ((rsr & port->ignore_status_mask) == 0) {
- tty_insert_flip_char(tty, ch, flag);
- }
- if ((rsr & UART01x_RSR_OE) &&
- tty->flip.count < TTY_FLIPBUF_SIZE) {
- /*
- * Overrun is special, since it's reported
- * immediately, and doesn't affect the current
- * character
- */
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- }
+ uart_insert_char(port, rsr, UART01x_RSR_OE, ch, flag);
+
ignore_char:
status = UART_GET_FR(port);
}
diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c
index d5cbef3fe8b..7db88ee18f7 100644
--- a/drivers/serial/amba-pl011.c
+++ b/drivers/serial/amba-pl011.c
@@ -163,18 +163,8 @@ pl011_rx_chars(struct uart_amba_port *uap)
if (uart_handle_sysrq_char(&uap->port, ch, regs))
goto ignore_char;
- if ((rsr & uap->port.ignore_status_mask) == 0) {
- tty_insert_flip_char(tty, ch, flag);
- }
- if ((rsr & UART01x_RSR_OE) &&
- tty->flip.count < TTY_FLIPBUF_SIZE) {
- /*
- * Overrun is special, since it's reported
- * immediately, and doesn't affect the current
- * character
- */
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- }
+ uart_insert_char(&uap->port, rsr, UART01x_RSR_OE, ch, flag);
+
ignore_char:
status = readw(uap->port.membase + UART01x_FR);
}
diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c
index b6d3d503494..5400dc2c087 100644
--- a/drivers/serial/au1x00_uart.c
+++ b/drivers/serial/au1x00_uart.c
@@ -773,22 +773,22 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios,
switch (termios->c_cflag & CSIZE) {
case CS5:
- cval = 0x00;
+ cval = UART_LCR_WLEN5;
break;
case CS6:
- cval = 0x01;
+ cval = UART_LCR_WLEN6;
break;
case CS7:
- cval = 0x02;
+ cval = UART_LCR_WLEN7;
break;
default:
case CS8:
- cval = 0x03;
+ cval = UART_LCR_WLEN8;
break;
}
if (termios->c_cflag & CSTOPB)
- cval |= 0x04;
+ cval |= UART_LCR_STOP;
if (termios->c_cflag & PARENB)
cval |= UART_LCR_PARITY;
if (!(termios->c_cflag & PARODD))
diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c
index 6242f3090a9..e92522b33c4 100644
--- a/drivers/serial/clps711x.c
+++ b/drivers/serial/clps711x.c
@@ -143,10 +143,7 @@ static irqreturn_t clps711xuart_int_rx(int irq, void *dev_id, struct pt_regs *re
* CHECK: does overrun affect the current character?
* ASSUMPTION: it does not.
*/
- if ((ch & port->ignore_status_mask & ~RXSTAT_OVERRUN) == 0)
- tty_insert_flip_char(tty, ch, flg);
- if ((ch & ~port->ignore_status_mask & RXSTAT_OVERRUN) == 0)
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ uart_insert_char(port, ch, UARTDR_OVERR, ch, flg);
ignore_char:
status = clps_readl(SYSFLG(port));
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
index b422c3abfba..c4c8f4b44f5 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
@@ -134,12 +134,21 @@ void scc1_lineif(struct uart_cpm_port *pinfo)
void scc2_lineif(struct uart_cpm_port *pinfo)
{
+ /*
+ * STx GP3 uses the SCC2 secondary option pin assignment
+ * which this driver doesn't account for in the static
+ * pin assignments. This kind of board specific info
+ * really has to get out of the driver so boards can
+ * be supported in a sane fashion.
+ */
+#ifndef CONFIG_STX_GP3
volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
io->iop_pparb |= 0x008b0000;
io->iop_pdirb |= 0x00880000;
io->iop_psorb |= 0x00880000;
io->iop_pdirb &= ~0x00030000;
io->iop_psorb &= ~0x00030000;
+#endif
cpm2_immr->im_cpmux.cmx_scr &= 0xff00ffff;
cpm2_immr->im_cpmux.cmx_scr |= 0x00090000;
pinfo->brg = 2;
diff --git a/drivers/serial/icom.h b/drivers/serial/icom.h
index 23dc0f7ddf8..798f1ef2371 100644
--- a/drivers/serial/icom.h
+++ b/drivers/serial/icom.h
@@ -286,5 +286,3 @@ struct lookup_int_table {
u32 __iomem *global_int_mask;
unsigned long processor_id;
};
-
-#define MSECS_TO_JIFFIES(ms) (((ms)*HZ+999)/1000)
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c
index ba4e13a22a5..793c3a7cbe4 100644
--- a/drivers/serial/ioc4_serial.c
+++ b/drivers/serial/ioc4_serial.c
@@ -20,7 +20,7 @@
#include <linux/serial_reg.h>
#include <linux/module.h>
#include <linux/pci.h>
-#include <linux/ioc4_common.h>
+#include <linux/ioc4.h>
#include <linux/serial_core.h>
/*
@@ -130,12 +130,19 @@
IOC4_SIO_IR_S3_TX_EXPLICIT)
/* Bitmasks for IOC4_OTHER_IR, IOC4_OTHER_IEC, and IOC4_OTHER_IES */
-#define IOC4_OTHER_IR_ATA_INT 0x00000001 /* ATAPI intr pass-thru */
-#define IOC4_OTHER_IR_ATA_MEMERR 0x00000002 /* ATAPI DMA PCI error */
-#define IOC4_OTHER_IR_S0_MEMERR 0x00000004 /* Port 0 PCI error */
-#define IOC4_OTHER_IR_S1_MEMERR 0x00000008 /* Port 1 PCI error */
-#define IOC4_OTHER_IR_S2_MEMERR 0x00000010 /* Port 2 PCI error */
-#define IOC4_OTHER_IR_S3_MEMERR 0x00000020 /* Port 3 PCI error */
+#define IOC4_OTHER_IR_ATA_INT 0x00000001 /* ATAPI intr pass-thru */
+#define IOC4_OTHER_IR_ATA_MEMERR 0x00000002 /* ATAPI DMA PCI error */
+#define IOC4_OTHER_IR_S0_MEMERR 0x00000004 /* Port 0 PCI error */
+#define IOC4_OTHER_IR_S1_MEMERR 0x00000008 /* Port 1 PCI error */
+#define IOC4_OTHER_IR_S2_MEMERR 0x00000010 /* Port 2 PCI error */
+#define IOC4_OTHER_IR_S3_MEMERR 0x00000020 /* Port 3 PCI error */
+#define IOC4_OTHER_IR_KBD_INT 0x00000040 /* Keyboard/mouse */
+#define IOC4_OTHER_IR_RESERVED 0x007fff80 /* Reserved */
+#define IOC4_OTHER_IR_RT_INT 0x00800000 /* INT_OUT section output */
+#define IOC4_OTHER_IR_GEN_INT 0xff000000 /* Generic pins */
+
+#define IOC4_OTHER_IR_SER_MEMERR (IOC4_OTHER_IR_S0_MEMERR | IOC4_OTHER_IR_S1_MEMERR | \
+ IOC4_OTHER_IR_S2_MEMERR | IOC4_OTHER_IR_S3_MEMERR)
/* Bitmasks for IOC4_SIO_CR */
#define IOC4_SIO_CR_CMD_PULSE_SHIFT 0 /* byte bus strobe shift */
@@ -274,70 +281,24 @@ struct ioc4_uartregs {
#define i4u_dlm u2.dlm
#define i4u_fcr u3.fcr
-/* PCI memory space register map addressed using pci_bar0 */
-struct ioc4_memregs {
- struct ioc4_mem {
- /* Miscellaneous IOC4 registers */
- uint32_t pci_err_addr_l;
- uint32_t pci_err_addr_h;
- uint32_t sio_ir;
- uint32_t other_ir;
-
- /* These registers are read-only for general kernel code. */
- uint32_t sio_ies_ro;
- uint32_t other_ies_ro;
- uint32_t sio_iec_ro;
- uint32_t other_iec_ro;
- uint32_t sio_cr;
- uint32_t misc_fill1;
- uint32_t int_out;
- uint32_t misc_fill2;
- uint32_t gpcr_s;
- uint32_t gpcr_c;
- uint32_t gpdr;
- uint32_t misc_fill3;
- uint32_t gppr_0;
- uint32_t gppr_1;
- uint32_t gppr_2;
- uint32_t gppr_3;
- uint32_t gppr_4;
- uint32_t gppr_5;
- uint32_t gppr_6;
- uint32_t gppr_7;
- } ioc4_mem;
-
- char misc_fill4[0x100 - 0x5C - 4];
-
- /* ATA/ATAP registers */
- uint32_t ata_notused[9];
- char ata_fill1[0x140 - 0x120 - 4];
- uint32_t ata_notused1[8];
- char ata_fill2[0x200 - 0x15C - 4];
-
- /* Keyboard and mouse registers */
- uint32_t km_notused[5];;
- char km_fill1[0x300 - 0x210 - 4];
-
- /* Serial port registers used for DMA serial I/O */
- struct ioc4_serial {
- uint32_t sbbr01_l;
- uint32_t sbbr01_h;
- uint32_t sbbr23_l;
- uint32_t sbbr23_h;
-
- struct ioc4_serialregs port_0;
- struct ioc4_serialregs port_1;
- struct ioc4_serialregs port_2;
- struct ioc4_serialregs port_3;
- struct ioc4_uartregs uart_0;
- struct ioc4_uartregs uart_1;
- struct ioc4_uartregs uart_2;
- struct ioc4_uartregs uart_3;
- } ioc4_serial;
-};
+/* Serial port registers used for DMA serial I/O */
+struct ioc4_serial {
+ uint32_t sbbr01_l;
+ uint32_t sbbr01_h;
+ uint32_t sbbr23_l;
+ uint32_t sbbr23_h;
+
+ struct ioc4_serialregs port_0;
+ struct ioc4_serialregs port_1;
+ struct ioc4_serialregs port_2;
+ struct ioc4_serialregs port_3;
+ struct ioc4_uartregs uart_0;
+ struct ioc4_uartregs uart_1;
+ struct ioc4_uartregs uart_2;
+ struct ioc4_uartregs uart_3;
+} ioc4_serial;
/* UART clock speed */
-#define IOC4_SER_XIN_CLK IOC4_SER_XIN_CLK_66
#define IOC4_SER_XIN_CLK_66 66666667
#define IOC4_SER_XIN_CLK_33 33333333
@@ -412,8 +373,8 @@ enum sio_proto {
| UART_LCR_WLEN7 | UART_LCR_WLEN8)
#define LCR_MASK_STOP_BITS (UART_LCR_STOP)
-#define PENDING(_p) (readl(&(_p)->ip_mem->sio_ir) & _p->ip_ienb)
-#define READ_SIO_IR(_p) readl(&(_p)->ip_mem->sio_ir)
+#define PENDING(_p) (readl(&(_p)->ip_mem->sio_ir.raw) & _p->ip_ienb)
+#define READ_SIO_IR(_p) readl(&(_p)->ip_mem->sio_ir.raw)
/* Default to 4k buffers */
#ifdef IOC4_1K_BUFFERS
@@ -447,7 +408,7 @@ struct ioc4_control {
*/
#define MAX_IOC4_INTR_ENTS (8 * sizeof(uint32_t))
struct ioc4_soft {
- struct ioc4_mem __iomem *is_ioc4_mem_addr;
+ struct ioc4_misc_regs __iomem *is_ioc4_misc_addr;
struct ioc4_serial __iomem *is_ioc4_serial_addr;
/* Each interrupt type has an entry in the array */
@@ -486,7 +447,7 @@ struct ioc4_port {
struct ioc4_soft *ip_ioc4_soft;
/* pci mem addresses */
- struct ioc4_mem __iomem *ip_mem;
+ struct ioc4_misc_regs __iomem *ip_mem;
struct ioc4_serial __iomem *ip_serial;
struct ioc4_serialregs __iomem *ip_serial_regs;
struct ioc4_uartregs __iomem *ip_uart_regs;
@@ -553,7 +514,7 @@ struct hooks {
uint32_t intr_dma_error;
uint32_t intr_clear;
uint32_t intr_all;
- char rs422_select_pin;
+ int rs422_select_pin;
};
static struct hooks hooks_array[IOC4_NUM_SERIAL_PORTS] = {
@@ -669,7 +630,7 @@ static void handle_intr(void *arg, uint32_t sio_ir);
static inline void
write_ireg(struct ioc4_soft *ioc4_soft, uint32_t val, int which, int type)
{
- struct ioc4_mem __iomem *mem = ioc4_soft->is_ioc4_mem_addr;
+ struct ioc4_misc_regs __iomem *mem = ioc4_soft->is_ioc4_misc_addr;
unsigned long flags;
spin_lock_irqsave(&ioc4_soft->is_ir_lock, flags);
@@ -678,11 +639,11 @@ write_ireg(struct ioc4_soft *ioc4_soft, uint32_t val, int which, int type)
case IOC4_SIO_INTR_TYPE:
switch (which) {
case IOC4_W_IES:
- writel(val, &mem->sio_ies_ro);
+ writel(val, &mem->sio_ies.raw);
break;
case IOC4_W_IEC:
- writel(val, &mem->sio_iec_ro);
+ writel(val, &mem->sio_iec.raw);
break;
}
break;
@@ -690,11 +651,11 @@ write_ireg(struct ioc4_soft *ioc4_soft, uint32_t val, int which, int type)
case IOC4_OTHER_INTR_TYPE:
switch (which) {
case IOC4_W_IES:
- writel(val, &mem->other_ies_ro);
+ writel(val, &mem->other_ies.raw);
break;
case IOC4_W_IEC:
- writel(val, &mem->other_iec_ro);
+ writel(val, &mem->other_iec.raw);
break;
}
break;
@@ -747,7 +708,8 @@ static int set_baud(struct ioc4_port *port, int baud)
*/
static struct ioc4_port *get_ioc4_port(struct uart_port *the_port)
{
- struct ioc4_control *control = dev_get_drvdata(the_port->dev);
+ struct ioc4_driver_data *idd = dev_get_drvdata(the_port->dev);
+ struct ioc4_control *control = idd->idd_serial_data;
int ii;
if (control) {
@@ -782,7 +744,7 @@ static struct ioc4_port *get_ioc4_port(struct uart_port *the_port)
static inline uint32_t
pending_intrs(struct ioc4_soft *soft, int type)
{
- struct ioc4_mem __iomem *mem = soft->is_ioc4_mem_addr;
+ struct ioc4_misc_regs __iomem *mem = soft->is_ioc4_misc_addr;
unsigned long flag;
uint32_t intrs = 0;
@@ -793,11 +755,11 @@ pending_intrs(struct ioc4_soft *soft, int type)
switch (type) {
case IOC4_SIO_INTR_TYPE:
- intrs = readl(&mem->sio_ir) & readl(&mem->sio_ies_ro);
+ intrs = readl(&mem->sio_ir.raw) & readl(&mem->sio_ies.raw);
break;
case IOC4_OTHER_INTR_TYPE:
- intrs = readl(&mem->other_ir) & readl(&mem->other_ies_ro);
+ intrs = readl(&mem->other_ir.raw) & readl(&mem->other_ies.raw);
/* Don't process any ATA interrupte */
intrs &= ~(IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR);
@@ -826,7 +788,7 @@ static int inline port_init(struct ioc4_port *port)
/* Wait until any pending bus activity for this port has ceased */
do
- sio_cr = readl(&port->ip_mem->sio_cr);
+ sio_cr = readl(&port->ip_mem->sio_cr.raw);
while (!(sio_cr & IOC4_SIO_CR_SIO_DIAG_IDLE));
/* Finish reset sequence */
@@ -899,7 +861,7 @@ static int inline port_init(struct ioc4_port *port)
write_ireg(port->ip_ioc4_soft, hooks->intr_clear,
IOC4_W_IEC, IOC4_SIO_INTR_TYPE);
port->ip_ienb &= ~hooks->intr_clear;
- writel(hooks->intr_clear, &port->ip_mem->sio_ir);
+ writel(hooks->intr_clear, &port->ip_mem->sio_ir.raw);
return 0;
}
@@ -918,23 +880,23 @@ static void handle_dma_error_intr(void *arg, uint32_t other_ir)
spin_lock_irqsave(&port->ip_lock, flags);
/* ACK the interrupt */
- writel(hooks->intr_dma_error, &port->ip_mem->other_ir);
+ writel(hooks->intr_dma_error, &port->ip_mem->other_ir.raw);
- if (readl(&port->ip_mem->pci_err_addr_l) & IOC4_PCI_ERR_ADDR_VLD) {
+ if (readl(&port->ip_mem->pci_err_addr_l.raw) & IOC4_PCI_ERR_ADDR_VLD) {
printk(KERN_ERR
"PCI error address is 0x%lx, "
"master is serial port %c %s\n",
(((uint64_t)readl(&port->ip_mem->pci_err_addr_h)
<< 32)
- | readl(&port->ip_mem->pci_err_addr_l))
+ | readl(&port->ip_mem->pci_err_addr_l.raw))
& IOC4_PCI_ERR_ADDR_ADDR_MSK, '1' +
- ((char)(readl(&port->ip_mem-> pci_err_addr_l) &
+ ((char)(readl(&port->ip_mem->pci_err_addr_l.raw) &
IOC4_PCI_ERR_ADDR_MST_NUM_MSK) >> 1),
- (readl(&port->ip_mem->pci_err_addr_l)
+ (readl(&port->ip_mem->pci_err_addr_l.raw)
& IOC4_PCI_ERR_ADDR_MST_TYP_MSK)
? "RX" : "TX");
- if (readl(&port->ip_mem->pci_err_addr_l)
+ if (readl(&port->ip_mem->pci_err_addr_l.raw)
& IOC4_PCI_ERR_ADDR_MUL_ERR) {
printk(KERN_ERR
"Multiple errors occurred\n");
@@ -1018,26 +980,26 @@ static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs)
"other_ies = 0x%x\n",
(intr_type == IOC4_SIO_INTR_TYPE) ? "sio" :
"other", this_ir,
- readl(&soft->is_ioc4_mem_addr->sio_ir),
- readl(&soft->is_ioc4_mem_addr->sio_ies_ro),
- readl(&soft->is_ioc4_mem_addr->other_ir),
- readl(&soft->is_ioc4_mem_addr->other_ies_ro));
+ readl(&soft->is_ioc4_misc_addr->sio_ir.raw),
+ readl(&soft->is_ioc4_misc_addr->sio_ies.raw),
+ readl(&soft->is_ioc4_misc_addr->other_ir.raw),
+ readl(&soft->is_ioc4_misc_addr->other_ies.raw));
}
}
#ifdef DEBUG_INTERRUPTS
{
- struct ioc4_mem __iomem *mem = soft->is_ioc4_mem_addr;
+ struct ioc4_misc_regs __iomem *mem = soft->is_ioc4_misc_addr;
spinlock_t *lp = &soft->is_ir_lock;
unsigned long flag;
spin_lock_irqsave(&soft->is_ir_lock, flag);
- printk ("%s : %d : mem 0x%p sio_ir 0x%x sio_ies_ro 0x%x "
- "other_ir 0x%x other_ies_ro 0x%x mask 0x%x\n",
+ printk ("%s : %d : mem 0x%p sio_ir 0x%x sio_ies 0x%x "
+ "other_ir 0x%x other_ies 0x%x mask 0x%x\n",
__FUNCTION__, __LINE__,
- (void *)mem, readl(&mem->sio_ir),
- readl(&mem->sio_ies_ro),
- readl(&mem->other_ir),
- readl(&mem->other_ies_ro),
+ (void *)mem, readl(&mem->sio_ir.raw),
+ readl(&mem->sio_ies.raw),
+ readl(&mem->other_ir.raw),
+ readl(&mem->other_ies.raw),
IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR);
spin_unlock_irqrestore(&soft->is_ir_lock, flag);
}
@@ -1049,21 +1011,20 @@ static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs)
* ioc4_attach_local - Device initialization.
* Called at *_attach() time for each
* IOC4 with serial ports in the system.
- * @control: ioc4_control ptr
- * @pdev: PCI handle for this device
- * @soft: soft struct for this device
- * @ioc4: ioc4 mem space
+ * @idd: Master module data for this IOC4
*/
-static int inline ioc4_attach_local(struct pci_dev *pdev,
- struct ioc4_control *control,
- struct ioc4_soft *soft, void __iomem *ioc4_mem,
- void __iomem *ioc4_serial)
+static int inline ioc4_attach_local(struct ioc4_driver_data *idd)
{
struct ioc4_port *port;
struct ioc4_port *ports[IOC4_NUM_SERIAL_PORTS];
int port_number;
uint16_t ioc4_revid_min = 62;
uint16_t ioc4_revid;
+ struct pci_dev *pdev = idd->idd_pdev;
+ struct ioc4_control* control = idd->idd_serial_data;
+ struct ioc4_soft *soft = control->ic_soft;
+ void __iomem *ioc4_misc = idd->idd_misc_regs;
+ void __iomem *ioc4_serial = soft->is_ioc4_serial_addr;
/* IOC4 firmware must be at least rev 62 */
pci_read_config_word(pdev, PCI_COMMAND_SPECIAL, &ioc4_revid);
@@ -1076,7 +1037,7 @@ static int inline ioc4_attach_local(struct pci_dev *pdev,
ioc4_revid, ioc4_revid_min);
return -EPERM;
}
- BUG_ON(ioc4_mem == NULL);
+ BUG_ON(ioc4_misc == NULL);
BUG_ON(ioc4_serial == NULL);
/* Create port structures for each port */
@@ -1100,10 +1061,18 @@ static int inline ioc4_attach_local(struct pci_dev *pdev,
port->ip_ioc4_soft = soft;
port->ip_pdev = pdev;
port->ip_ienb = 0;
- port->ip_pci_bus_speed = IOC4_SER_XIN_CLK;
+ /* Use baud rate calculations based on detected PCI
+ * bus speed. Simply test whether the PCI clock is
+ * running closer to 66MHz or 33MHz.
+ */
+ if (idd->count_period/IOC4_EXTINT_COUNT_DIVISOR < 20) {
+ port->ip_pci_bus_speed = IOC4_SER_XIN_CLK_66;
+ } else {
+ port->ip_pci_bus_speed = IOC4_SER_XIN_CLK_33;
+ }
port->ip_baud = 9600;
port->ip_control = control;
- port->ip_mem = ioc4_mem;
+ port->ip_mem = ioc4_misc;
port->ip_serial = ioc4_serial;
/* point to the right hook */
@@ -1604,14 +1573,12 @@ static int ioc4_set_proto(struct ioc4_port *port, enum sio_proto proto)
switch (proto) {
case PROTO_RS232:
/* Clear the appropriate GIO pin */
- writel(0, (&port->ip_mem->gppr_0 +
- hooks->rs422_select_pin));
+ writel(0, (&port->ip_mem->gppr[hooks->rs422_select_pin].raw));
break;
case PROTO_RS422:
/* Set the appropriate GIO pin */
- writel(1, (&port->ip_mem->gppr_0 +
- hooks->rs422_select_pin));
+ writel(1, (&port->ip_mem->gppr[hooks->rs422_select_pin].raw));
break;
default:
@@ -1885,7 +1852,7 @@ static void handle_intr(void *arg, uint32_t sio_ir)
if (sio_ir & hooks->intr_delta_dcd) {
/* ACK the interrupt */
writel(hooks->intr_delta_dcd,
- &port->ip_mem->sio_ir);
+ &port->ip_mem->sio_ir.raw);
shadow = readl(&port->ip_serial_regs->shadow);
@@ -1907,7 +1874,7 @@ static void handle_intr(void *arg, uint32_t sio_ir)
if (sio_ir & hooks->intr_delta_cts) {
/* ACK the interrupt */
writel(hooks->intr_delta_cts,
- &port->ip_mem->sio_ir);
+ &port->ip_mem->sio_ir.raw);
shadow = readl(&port->ip_serial_regs->shadow);
@@ -1928,7 +1895,7 @@ static void handle_intr(void *arg, uint32_t sio_ir)
if (sio_ir & hooks->intr_rx_timer) {
/* ACK the interrupt */
writel(hooks->intr_rx_timer,
- &port->ip_mem->sio_ir);
+ &port->ip_mem->sio_ir.raw);
if ((port->ip_notify & N_DATA_READY)
&& (port->ip_port)) {
@@ -1974,7 +1941,7 @@ static void handle_intr(void *arg, uint32_t sio_ir)
/* ACK the interrupt */
writel(hooks->intr_tx_explicit,
- &port->ip_mem->sio_ir);
+ &port->ip_mem->sio_ir.raw);
if (port->ip_notify & N_OUTPUT_LOWAT)
ioc4_cb_output_lowat(port);
@@ -2634,7 +2601,8 @@ ioc4_serial_core_attach(struct pci_dev *pdev)
{
struct ioc4_port *port;
struct uart_port *the_port;
- struct ioc4_control *control = pci_get_drvdata(pdev);
+ struct ioc4_driver_data *idd = pci_get_drvdata(pdev);
+ struct ioc4_control *control = idd->idd_serial_data;
int ii;
DPRINT_CONFIG(("%s: attach pdev 0x%p - control 0x%p\n",
@@ -2680,55 +2648,29 @@ ioc4_serial_core_attach(struct pci_dev *pdev)
/**
* ioc4_serial_attach_one - register attach function
- * called per card found from ioc4_serial_detect as part
- * of module_init().
- * @pdev: handle for this card
- * @pci_id: pci id for this card
+ * called per card found from IOC4 master module.
+ * @idd: Master module data for this IOC4
*/
int
-ioc4_serial_attach_one(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+ioc4_serial_attach_one(struct ioc4_driver_data *idd)
{
- struct ioc4_mem __iomem *mem;
- unsigned long tmp_addr, tmp_addr1;
+ unsigned long tmp_addr1;
struct ioc4_serial __iomem *serial;
struct ioc4_soft *soft;
struct ioc4_control *control;
- int tmp, ret = 0;
+ int ret = 0;
- DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, pdev, pci_id));
-
- /* Map in the ioc4 memory */
- tmp_addr = pci_resource_start(pdev, 0);
- if (!tmp_addr) {
- printk(KERN_WARNING
- "ioc4 (%p) : unable to get PIO mapping for "
- "MEM space\n", (void *)pdev);
- return -ENODEV;
- }
- if (!request_region(tmp_addr, sizeof(struct ioc4_mem), "sioc4_mem")) {
- printk(KERN_ALERT
- "ioc4 (%p): unable to get request region for "
- "MEM space\n", (void *)pdev);
- return -ENODEV;
- }
- mem = ioremap(tmp_addr, sizeof(struct ioc4_mem));
- if (!mem) {
- printk(KERN_WARNING
- "ioc4 (%p) : unable to remap ioc4 memory\n",
- (void *)pdev);
- ret = -ENODEV;
- goto out1;
- }
+ DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, idd->idd_pdev, idd->idd_pci_id));
/* request serial registers */
- tmp_addr1 = pci_resource_start(pdev, 0) + IOC4_SERIAL_OFFSET;
+ tmp_addr1 = idd->idd_bar0 + IOC4_SERIAL_OFFSET;
if (!request_region(tmp_addr1, sizeof(struct ioc4_serial),
"sioc4_uart")) {
printk(KERN_WARNING
"ioc4 (%p): unable to get request region for "
- "uart space\n", (void *)pdev);
+ "uart space\n", (void *)idd->idd_pdev);
ret = -ENODEV;
goto out1;
}
@@ -2736,12 +2678,12 @@ ioc4_serial_attach_one(struct pci_dev *pdev, const struct pci_device_id *pci_id)
if (!serial) {
printk(KERN_WARNING
"ioc4 (%p) : unable to remap ioc4 serial register\n",
- (void *)pdev);
+ (void *)idd->idd_pdev);
ret = -ENODEV;
goto out2;
}
DPRINT_CONFIG(("%s : mem 0x%p, serial 0x%p\n",
- __FUNCTION__, (void *)mem, (void *)serial));
+ __FUNCTION__, (void *)idd->idd_misc_regs, (void *)serial));
/* Get memory for the new card */
control = kmalloc(sizeof(struct ioc4_control) * IOC4_NUM_SERIAL_PORTS,
@@ -2754,59 +2696,56 @@ ioc4_serial_attach_one(struct pci_dev *pdev, const struct pci_device_id *pci_id)
goto out2;
}
memset(control, 0, sizeof(struct ioc4_control));
- pci_set_drvdata(pdev, control);
+ idd->idd_serial_data = control;
/* Allocate the soft structure */
soft = kmalloc(sizeof(struct ioc4_soft), GFP_KERNEL);
if (!soft) {
printk(KERN_WARNING
"ioc4 (%p): unable to get memory for the soft struct\n",
- (void *)pdev);
+ (void *)idd->idd_pdev);
ret = -ENOMEM;
goto out3;
}
memset(soft, 0, sizeof(struct ioc4_soft));
spin_lock_init(&soft->is_ir_lock);
- soft->is_ioc4_mem_addr = mem;
+ soft->is_ioc4_misc_addr = idd->idd_misc_regs;
soft->is_ioc4_serial_addr = serial;
/* Init the IOC4 */
- pci_read_config_dword(pdev, PCI_COMMAND, &tmp);
- pci_write_config_dword(pdev, PCI_COMMAND,
- tmp | PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
-
- writel(0xf << IOC4_SIO_CR_CMD_PULSE_SHIFT, &mem->sio_cr);
+ writel(0xf << IOC4_SIO_CR_CMD_PULSE_SHIFT,
+ &idd->idd_misc_regs->sio_cr.raw);
/* Enable serial port mode select generic PIO pins as outputs */
writel(IOC4_GPCR_UART0_MODESEL | IOC4_GPCR_UART1_MODESEL
| IOC4_GPCR_UART2_MODESEL | IOC4_GPCR_UART3_MODESEL,
- &mem->gpcr_s);
+ &idd->idd_misc_regs->gpcr_s.raw);
- /* Clear and disable all interrupts */
+ /* Clear and disable all serial interrupts */
write_ireg(soft, ~0, IOC4_W_IEC, IOC4_SIO_INTR_TYPE);
- writel(~0, &mem->sio_ir);
- write_ireg(soft, ~(IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR),
- IOC4_W_IEC, IOC4_OTHER_INTR_TYPE);
- writel(~(IOC4_OTHER_IR_ATA_MEMERR | IOC4_OTHER_IR_ATA_MEMERR),
- &mem->other_ir);
+ writel(~0, &idd->idd_misc_regs->sio_ir.raw);
+ write_ireg(soft, IOC4_OTHER_IR_SER_MEMERR, IOC4_W_IEC,
+ IOC4_OTHER_INTR_TYPE);
+ writel(IOC4_OTHER_IR_SER_MEMERR, &idd->idd_misc_regs->other_ir.raw);
control->ic_soft = soft;
- if (!request_irq(pdev->irq, ioc4_intr, SA_SHIRQ,
+
+ /* Hook up interrupt handler */
+ if (!request_irq(idd->idd_pdev->irq, ioc4_intr, SA_SHIRQ,
"sgi-ioc4serial", (void *)soft)) {
- control->ic_irq = pdev->irq;
+ control->ic_irq = idd->idd_pdev->irq;
} else {
printk(KERN_WARNING
"%s : request_irq fails for IRQ 0x%x\n ",
- __FUNCTION__, pdev->irq);
+ __FUNCTION__, idd->idd_pdev->irq);
}
- if ((ret = ioc4_attach_local(pdev, control, soft,
- soft->is_ioc4_mem_addr,
- soft->is_ioc4_serial_addr)))
+ ret = ioc4_attach_local(idd);
+ if (ret)
goto out4;
/* register port with the serial core */
- if ((ret = ioc4_serial_core_attach(pdev)))
+ if ((ret = ioc4_serial_core_attach(idd->idd_pdev)))
goto out4;
return ret;
@@ -2819,7 +2758,6 @@ out3:
out2:
release_region(tmp_addr1, sizeof(struct ioc4_serial));
out1:
- release_region(tmp_addr, sizeof(struct ioc4_mem));
return ret;
}
@@ -2828,11 +2766,10 @@ out1:
/**
* ioc4_serial_remove_one - detach function
*
- * @pdev: handle for this card
+ * @idd: IOC4 master module data for this IOC4
*/
-#if 0
-void ioc4_serial_remove_one(struct pci_dev *pdev)
+int ioc4_serial_remove_one(struct ioc4_driver_data *idd)
{
int ii;
struct ioc4_control *control;
@@ -2840,7 +2777,7 @@ void ioc4_serial_remove_one(struct pci_dev *pdev)
struct ioc4_port *port;
struct ioc4_soft *soft;
- control = pci_get_drvdata(pdev);
+ control = idd->idd_serial_data;
for (ii = 0; ii < IOC4_NUM_SERIAL_PORTS; ii++) {
the_port = &control->ic_port[ii].icp_uart_port;
@@ -2867,10 +2804,17 @@ void ioc4_serial_remove_one(struct pci_dev *pdev)
kfree(soft);
}
kfree(control);
- pci_set_drvdata(pdev, NULL);
- uart_unregister_driver(&ioc4_uart);
+ idd->idd_serial_data = NULL;
+
+ return 0;
}
-#endif
+
+static struct ioc4_submodule ioc4_serial_submodule = {
+ .is_name = "IOC4_serial",
+ .is_owner = THIS_MODULE,
+ .is_probe = ioc4_serial_attach_one,
+ .is_remove = ioc4_serial_remove_one,
+};
/**
* ioc4_serial_init - module init
@@ -2886,12 +2830,20 @@ int ioc4_serial_init(void)
__FUNCTION__);
return ret;
}
- return 0;
+
+ /* register with IOC4 main module */
+ return ioc4_register_submodule(&ioc4_serial_submodule);
+}
+
+static void __devexit ioc4_serial_exit(void)
+{
+ ioc4_unregister_submodule(&ioc4_serial_submodule);
+ uart_unregister_driver(&ioc4_uart);
}
+module_init(ioc4_serial_init);
+module_exit(ioc4_serial_exit);
+
MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>");
MODULE_DESCRIPTION("Serial PCI driver module for SGI IOC4 Base-IO Card");
MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(ioc4_serial_init);
-EXPORT_SYMBOL(ioc4_serial_attach_one);
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c
index 08d61f13edc..0301feacbde 100644
--- a/drivers/serial/m32r_sio.c
+++ b/drivers/serial/m32r_sio.c
@@ -724,22 +724,22 @@ static void m32r_sio_set_termios(struct uart_port *port,
switch (termios->c_cflag & CSIZE) {
case CS5:
- cval = 0x00;
+ cval = UART_LCR_WLEN5;
break;
case CS6:
- cval = 0x01;
+ cval = UART_LCR_WLEN6;
break;
case CS7:
- cval = 0x02;
+ cval = UART_LCR_WLEN7;
break;
default:
case CS8:
- cval = 0x03;
+ cval = UART_LCR_WLEN8;
break;
}
if (termios->c_cflag & CSTOPB)
- cval |= 0x04;
+ cval |= UART_LCR_STOP;
if (termios->c_cflag & PARENB)
cval |= UART_LCR_PARITY;
if (!(termios->c_cflag & PARODD))
diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c
index a8314aee2ab..a2a64331800 100644
--- a/drivers/serial/mpsc.c
+++ b/drivers/serial/mpsc.c
@@ -67,7 +67,11 @@
static struct mpsc_port_info mpsc_ports[MPSC_NUM_CTLRS];
static struct mpsc_shared_regs mpsc_shared_regs;
+static struct uart_driver mpsc_reg;
+static void mpsc_start_rx(struct mpsc_port_info *pi);
+static void mpsc_free_ring_mem(struct mpsc_port_info *pi);
+static void mpsc_release_port(struct uart_port *port);
/*
******************************************************************************
*
@@ -546,7 +550,6 @@ static int
mpsc_alloc_ring_mem(struct mpsc_port_info *pi)
{
int rc = 0;
- static void mpsc_free_ring_mem(struct mpsc_port_info *pi);
pr_debug("mpsc_alloc_ring_mem[%d]: Allocating ring mem\n",
pi->port.line);
@@ -745,7 +748,6 @@ mpsc_rx_intr(struct mpsc_port_info *pi, struct pt_regs *regs)
int rc = 0;
u8 *bp;
char flag = TTY_NORMAL;
- static void mpsc_start_rx(struct mpsc_port_info *pi);
pr_debug("mpsc_rx_intr[%d]: Handling Rx intr\n", pi->port.line);
@@ -1178,7 +1180,6 @@ static void
mpsc_shutdown(struct uart_port *port)
{
struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
- static void mpsc_release_port(struct uart_port *port);
pr_debug("mpsc_shutdown[%d]: Shutting down MPSC\n", port->line);
@@ -1448,7 +1449,6 @@ mpsc_console_setup(struct console *co, char *options)
return uart_set_options(&pi->port, co, baud, parity, bits, flow);
}
-extern struct uart_driver mpsc_reg;
static struct console mpsc_console = {
.name = MPSC_DEV_NAME,
.write = mpsc_console_write,
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c
index 51d8a49f447..08b08d6ae90 100644
--- a/drivers/serial/pxa.c
+++ b/drivers/serial/pxa.c
@@ -161,20 +161,12 @@ receive_chars(struct uart_pxa_port *up, int *status, struct pt_regs *regs)
else if (*status & UART_LSR_FE)
flag = TTY_FRAME;
}
+
if (uart_handle_sysrq_char(&up->port, ch, regs))
goto ignore_char;
- if ((*status & up->port.ignore_status_mask) == 0) {
- tty_insert_flip_char(tty, ch, flag);
- }
- if ((*status & UART_LSR_OE) &&
- tty->flip.count < TTY_FLIPBUF_SIZE) {
- /*
- * Overrun is special, since it's reported
- * immediately, and doesn't affect the current
- * character.
- */
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- }
+
+ uart_insert_char(&up->port, *status, UART_LSR_OE, ch, flag);
+
ignore_char:
*status = serial_in(up, UART_LSR);
} while ((*status & UART_LSR_DR) && (max_count-- > 0));
@@ -463,22 +455,22 @@ serial_pxa_set_termios(struct uart_port *port, struct termios *termios,
switch (termios->c_cflag & CSIZE) {
case CS5:
- cval = 0x00;
+ cval = UART_LCR_WLEN5;
break;
case CS6:
- cval = 0x01;
+ cval = UART_LCR_WLEN6;
break;
case CS7:
- cval = 0x02;
+ cval = UART_LCR_WLEN7;
break;
default:
case CS8:
- cval = 0x03;
+ cval = UART_LCR_WLEN8;
break;
}
if (termios->c_cflag & CSTOPB)
- cval |= 0x04;
+ cval |= UART_LCR_STOP;
if (termios->c_cflag & PARENB)
cval |= UART_LCR_PARITY;
if (!(termios->c_cflag & PARODD))
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index 435750d40a4..5c4678478b1 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -198,7 +198,7 @@ static inline struct s3c24xx_uart_port *to_ourport(struct uart_port *port)
/* translate a port to the device name */
-static inline char *s3c24xx_serial_portname(struct uart_port *port)
+static inline const char *s3c24xx_serial_portname(struct uart_port *port)
{
return to_platform_device(port->dev)->name;
}
@@ -394,20 +394,7 @@ s3c24xx_serial_rx_chars(int irq, void *dev_id, struct pt_regs *regs)
if (uart_handle_sysrq_char(port, ch, regs))
goto ignore_char;
- if ((uerstat & port->ignore_status_mask) == 0) {
- tty_insert_flip_char(tty, ch, flag);
- }
-
- if ((uerstat & S3C2410_UERSTAT_OVERRUN) &&
- tty->flip.count < TTY_FLIPBUF_SIZE) {
- /*
- * Overrun is special, since it's reported
- * immediately, and doesn't affect the current
- * character.
- */
-
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- }
+ uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN, ch, flag);
ignore_char:
continue;
@@ -916,7 +903,7 @@ static void s3c24xx_serial_release_port(struct uart_port *port)
static int s3c24xx_serial_request_port(struct uart_port *port)
{
- char *name = s3c24xx_serial_portname(port);
+ const char *name = s3c24xx_serial_portname(port);
return request_mem_region(port->mapbase, MAP_SIZE, name) ? 0 : -EBUSY;
}
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
index 157218bc6c6..98641c3f5ab 100644
--- a/drivers/serial/sa1100.c
+++ b/drivers/serial/sa1100.c
@@ -197,7 +197,7 @@ static void
sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs)
{
struct tty_struct *tty = sport->port.info->tty;
- unsigned int status, ch, flg, ignored = 0;
+ unsigned int status, ch, flg;
status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
UTSR0_TO_SM(UART_GET_UTSR0(sport));
@@ -237,10 +237,7 @@ sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs)
if (uart_handle_sysrq_char(&sport->port, ch, regs))
goto ignore_char;
- if ((status & port->ignore_status_mask & ~UTSR1_TO_SM(UTSR1_ROR)) == 0)
- tty_insert_flip_char(tty, ch, flg);
- if (status & ~port->ignore_status_mask & UTSR1_TO_SM(UTSR1_ROR))
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ uart_insert_char(&sport->port, status, UTSR1_TO_SM(UTSR1_ROR), ch, flg);
ignore_char:
status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index 6eeb48f6a48..0d7b65f93e8 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -661,10 +661,10 @@ void serial_config(dev_link_t * link)
/* Is this a multiport card? */
tuple->DesiredTuple = CISTPL_MANFID;
if (first_tuple(handle, tuple, parse) == CS_SUCCESS) {
- info->manfid = le16_to_cpu(buf[0]);
+ info->manfid = parse->manfid.manf;
for (i = 0; i < MULTI_COUNT; i++)
if ((info->manfid == multi_id[i].manfid) &&
- (le16_to_cpu(buf[1]) == multi_id[i].prodid))
+ (parse->manfid.card == multi_id[i].prodid))
break;
if (i < MULTI_COUNT)
info->multi = multi_id[i].multi;
diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c
index 85cfa08d3ba..56f269b6bfb 100644
--- a/drivers/serial/serial_lh7a40x.c
+++ b/drivers/serial/serial_lh7a40x.c
@@ -190,18 +190,7 @@ lh7a40xuart_rx_chars (struct uart_port* port)
if (uart_handle_sysrq_char (port, (unsigned char) data, regs))
continue;
- if ((data & port->ignore_status_mask) == 0) {
- tty_insert_flip_char(tty, data, flag);
- }
- if ((data & RxOverrunError)
- && tty->flip.count < TTY_FLIPBUF_SIZE) {
- /*
- * Overrun is special, since it's reported
- * immediately, and doesn't affect the current
- * character
- */
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- }
+ uart_insert_char(port, data, RxOverrunError, data, flag);
}
tty_flip_buffer_push (tty);
return;
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c
index 37b2ef297cb..3f1051a4a13 100644
--- a/drivers/serial/serial_txx9.c
+++ b/drivers/serial/serial_txx9.c
@@ -350,18 +350,9 @@ receive_chars(struct uart_txx9_port *up, unsigned int *status, struct pt_regs *r
}
if (uart_handle_sysrq_char(&up->port, ch, regs))
goto ignore_char;
- if ((disr & up->port.ignore_status_mask) == 0) {
- tty_insert_flip_char(tty, ch, flag);
- }
- if ((disr & TXX9_SIDISR_UOER) &&
- tty->flip.count < TTY_FLIPBUF_SIZE) {
- /*
- * Overrun is special, since it's reported
- * immediately, and doesn't affect the current
- * character.
- */
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
- }
+
+ uart_insert_char(&up->port, disr, TXX9_SIDISR_UOER, ch, flag);
+
ignore_char:
disr = sio_in(up, TXX9_SIDISR);
} while (!(disr & TXX9_SIDISR_UVALID) && (max_count-- > 0));
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
index fee6418e84c..840815fde49 100644
--- a/drivers/serial/sn_console.c
+++ b/drivers/serial/sn_console.c
@@ -572,6 +572,7 @@ static void sn_transmit_chars(struct sn_cons_port *port, int raw)
if (uart_circ_empty(xmit) || uart_tx_stopped(&port->sc_port)) {
/* Nothing to do. */
+ ia64_sn_console_intr_disable(SAL_CONSOLE_INTR_XMIT);
return;
}
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c
index 39b788d95e3..10e2990a40d 100644
--- a/drivers/serial/sunsab.c
+++ b/drivers/serial/sunsab.c
@@ -61,6 +61,16 @@ struct uart_sunsab_port {
unsigned char pvr_dtr_bit; /* Which PVR bit is DTR */
unsigned char pvr_dsr_bit; /* Which PVR bit is DSR */
int type; /* SAB82532 version */
+
+ /* Setting configuration bits while the transmitter is active
+ * can cause garbage characters to get emitted by the chip.
+ * Therefore, we cache such writes here and do the real register
+ * write the next time the transmitter becomes idle.
+ */
+ unsigned int cached_ebrg;
+ unsigned char cached_mode;
+ unsigned char cached_pvr;
+ unsigned char cached_dafo;
};
/*
@@ -236,6 +246,7 @@ receive_chars(struct uart_sunsab_port *up,
}
static void sunsab_stop_tx(struct uart_port *, unsigned int);
+static void sunsab_tx_idle(struct uart_sunsab_port *);
static void transmit_chars(struct uart_sunsab_port *up,
union sab82532_irq_status *stat)
@@ -258,6 +269,7 @@ static void transmit_chars(struct uart_sunsab_port *up,
return;
set_bit(SAB82532_XPR, &up->irqflags);
+ sunsab_tx_idle(up);
if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
up->interrupt_mask1 |= SAB82532_IMR1_XPR;
@@ -397,21 +409,21 @@ static void sunsab_set_mctrl(struct uart_port *port, unsigned int mctrl)
struct uart_sunsab_port *up = (struct uart_sunsab_port *) port;
if (mctrl & TIOCM_RTS) {
- writeb(readb(&up->regs->rw.mode) & ~SAB82532_MODE_FRTS,
- &up->regs->rw.mode);
- writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_RTS,
- &up->regs->rw.mode);
+ up->cached_mode &= ~SAB82532_MODE_FRTS;
+ up->cached_mode |= SAB82532_MODE_RTS;
} else {
- writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_FRTS,
- &up->regs->rw.mode);
- writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_RTS,
- &up->regs->rw.mode);
+ up->cached_mode |= (SAB82532_MODE_FRTS |
+ SAB82532_MODE_RTS);
}
if (mctrl & TIOCM_DTR) {
- writeb(readb(&up->regs->rw.pvr) & ~(up->pvr_dtr_bit), &up->regs->rw.pvr);
+ up->cached_pvr &= ~(up->pvr_dtr_bit);
} else {
- writeb(readb(&up->regs->rw.pvr) | up->pvr_dtr_bit, &up->regs->rw.pvr);
+ up->cached_pvr |= up->pvr_dtr_bit;
}
+
+ set_bit(SAB82532_REGS_PENDING, &up->irqflags);
+ if (test_bit(SAB82532_XPR, &up->irqflags))
+ sunsab_tx_idle(up);
}
/* port->lock is not held. */
@@ -450,6 +462,25 @@ static void sunsab_stop_tx(struct uart_port *port, unsigned int tty_stop)
}
/* port->lock held by caller. */
+static void sunsab_tx_idle(struct uart_sunsab_port *up)
+{
+ if (test_bit(SAB82532_REGS_PENDING, &up->irqflags)) {
+ u8 tmp;
+
+ clear_bit(SAB82532_REGS_PENDING, &up->irqflags);
+ writeb(up->cached_mode, &up->regs->rw.mode);
+ writeb(up->cached_pvr, &up->regs->rw.pvr);
+ writeb(up->cached_dafo, &up->regs->w.dafo);
+
+ writeb(up->cached_ebrg & 0xff, &up->regs->w.bgr);
+ tmp = readb(&up->regs->rw.ccr2);
+ tmp &= ~0xc0;
+ tmp |= (up->cached_ebrg >> 2) & 0xc0;
+ writeb(tmp, &up->regs->rw.ccr2);
+ }
+}
+
+/* port->lock held by caller. */
static void sunsab_start_tx(struct uart_port *port, unsigned int tty_start)
{
struct uart_sunsab_port *up = (struct uart_sunsab_port *) port;
@@ -517,12 +548,16 @@ static void sunsab_break_ctl(struct uart_port *port, int break_state)
spin_lock_irqsave(&up->port.lock, flags);
- val = readb(&up->regs->rw.dafo);
+ val = up->cached_dafo;
if (break_state)
val |= SAB82532_DAFO_XBRK;
else
val &= ~SAB82532_DAFO_XBRK;
- writeb(val, &up->regs->rw.dafo);
+ up->cached_dafo = val;
+
+ set_bit(SAB82532_REGS_PENDING, &up->irqflags);
+ if (test_bit(SAB82532_XPR, &up->irqflags))
+ sunsab_tx_idle(up);
spin_unlock_irqrestore(&up->port.lock, flags);
}
@@ -566,8 +601,9 @@ static int sunsab_startup(struct uart_port *port)
SAB82532_CCR2_TOE, &up->regs->w.ccr2);
writeb(0, &up->regs->w.ccr3);
writeb(SAB82532_CCR4_MCK4 | SAB82532_CCR4_EBRG, &up->regs->w.ccr4);
- writeb(SAB82532_MODE_RTS | SAB82532_MODE_FCTS |
- SAB82532_MODE_RAC, &up->regs->w.mode);
+ up->cached_mode = (SAB82532_MODE_RTS | SAB82532_MODE_FCTS |
+ SAB82532_MODE_RAC);
+ writeb(up->cached_mode, &up->regs->w.mode);
writeb(SAB82532_RFC_DPS|SAB82532_RFC_RFTH_32, &up->regs->w.rfc);
tmp = readb(&up->regs->rw.ccr0);
@@ -598,7 +634,6 @@ static void sunsab_shutdown(struct uart_port *port)
{
struct uart_sunsab_port *up = (struct uart_sunsab_port *) port;
unsigned long flags;
- unsigned char tmp;
spin_lock_irqsave(&up->port.lock, flags);
@@ -609,14 +644,13 @@ static void sunsab_shutdown(struct uart_port *port)
writeb(up->interrupt_mask1, &up->regs->w.imr1);
/* Disable break condition */
- tmp = readb(&up->regs->rw.dafo);
- tmp &= ~SAB82532_DAFO_XBRK;
- writeb(tmp, &up->regs->rw.dafo);
+ up->cached_dafo = readb(&up->regs->rw.dafo);
+ up->cached_dafo &= ~SAB82532_DAFO_XBRK;
+ writeb(up->cached_dafo, &up->regs->rw.dafo);
/* Disable Receiver */
- tmp = readb(&up->regs->rw.mode);
- tmp &= ~SAB82532_MODE_RAC;
- writeb(tmp, &up->regs->rw.mode);
+ up->cached_mode &= ~SAB82532_MODE_RAC;
+ writeb(up->cached_mode, &up->regs->rw.mode);
/*
* XXX FIXME
@@ -685,7 +719,6 @@ static void sunsab_convert_to_sab(struct uart_sunsab_port *up, unsigned int cfla
unsigned int iflag, unsigned int baud,
unsigned int quot)
{
- unsigned int ebrg;
unsigned char dafo;
int bits, n, m;
@@ -714,10 +747,11 @@ static void sunsab_convert_to_sab(struct uart_sunsab_port *up, unsigned int cfla
} else {
dafo |= SAB82532_DAFO_PAR_EVEN;
}
+ up->cached_dafo = dafo;
calc_ebrg(baud, &n, &m);
- ebrg = n | (m << 6);
+ up->cached_ebrg = n | (m << 6);
up->tec_timeout = (10 * 1000000) / baud;
up->cec_timeout = up->tec_timeout >> 2;
@@ -770,16 +804,13 @@ static void sunsab_convert_to_sab(struct uart_sunsab_port *up, unsigned int cfla
uart_update_timeout(&up->port, cflag,
(up->port.uartclk / (16 * quot)));
- /* Now bang the new settings into the chip. */
- sunsab_cec_wait(up);
- sunsab_tec_wait(up);
- writeb(dafo, &up->regs->w.dafo);
- writeb(ebrg & 0xff, &up->regs->w.bgr);
- writeb((readb(&up->regs->rw.ccr2) & ~0xc0) | ((ebrg >> 2) & 0xc0),
- &up->regs->rw.ccr2);
-
- writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_RAC, &up->regs->rw.mode);
-
+ /* Now schedule a register update when the chip's
+ * transmitter is idle.
+ */
+ up->cached_mode |= SAB82532_MODE_RAC;
+ set_bit(SAB82532_REGS_PENDING, &up->irqflags);
+ if (test_bit(SAB82532_XPR, &up->irqflags))
+ sunsab_tx_idle(up);
}
/* port->lock is not held. */
@@ -1084,11 +1115,13 @@ static void __init sunsab_init_hw(void)
up->pvr_dsr_bit = (1 << 3);
up->pvr_dtr_bit = (1 << 2);
}
- writeb((1 << 1) | (1 << 2) | (1 << 4), &up->regs->w.pvr);
- writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_FRTS,
- &up->regs->rw.mode);
- writeb(readb(&up->regs->rw.mode) | SAB82532_MODE_RTS,
- &up->regs->rw.mode);
+ up->cached_pvr = (1 << 1) | (1 << 2) | (1 << 4);
+ writeb(up->cached_pvr, &up->regs->w.pvr);
+ up->cached_mode = readb(&up->regs->rw.mode);
+ up->cached_mode |= SAB82532_MODE_FRTS;
+ writeb(up->cached_mode, &up->regs->rw.mode);
+ up->cached_mode |= SAB82532_MODE_RTS;
+ writeb(up->cached_mode, &up->regs->rw.mode);
up->tec_timeout = SAB82532_MAX_TEC_TIMEOUT;
up->cec_timeout = SAB82532_MAX_CEC_TIMEOUT;
diff --git a/drivers/serial/sunsab.h b/drivers/serial/sunsab.h
index 686086fcbbf..b78e1f7b805 100644
--- a/drivers/serial/sunsab.h
+++ b/drivers/serial/sunsab.h
@@ -126,6 +126,7 @@ union sab82532_irq_status {
/* irqflags bits */
#define SAB82532_ALLS 0x00000001
#define SAB82532_XPR 0x00000002
+#define SAB82532_REGS_PENDING 0x00000004
/* RFIFO Status Byte */
#define SAB82532_RSTAT_PE 0x80
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 5c4231ae295..8e65206d3d7 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -1071,7 +1071,7 @@ static void __init sunzilog_alloc_tables(void)
*/
static struct zilog_layout __iomem * __init get_zs_sun4u(int chip, int zsnode)
{
- unsigned long mapped_addr;
+ void __iomem *mapped_addr;
unsigned int sun4u_ino;
struct sbus_bus *sbus = NULL;
struct sbus_dev *sdev = NULL;
@@ -1111,9 +1111,9 @@ static struct zilog_layout __iomem * __init get_zs_sun4u(int chip, int zsnode)
apply_fhc_ranges(central_bus->child,
&zsregs[0], 1);
apply_central_ranges(central_bus, &zsregs[0], 1);
- mapped_addr =
- (((u64)zsregs[0].which_io)<<32UL) |
- ((u64)zsregs[0].phys_addr);
+ mapped_addr = (void __iomem *)
+ ((((u64)zsregs[0].which_io)<<32UL) |
+ ((u64)zsregs[0].phys_addr));
}
if (zilog_irq == -1) {
diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c
index 307886199f2..1f985327b0d 100644
--- a/drivers/serial/vr41xx_siu.c
+++ b/drivers/serial/vr41xx_siu.c
@@ -234,7 +234,7 @@ static inline const char *siu_type_name(struct uart_port *port)
return "DSIU";
}
- return "unknown";
+ return NULL;
}
static unsigned int siu_tx_empty(struct uart_port *port)
@@ -412,10 +412,8 @@ static inline void receive_chars(struct uart_port *port, uint8_t *status,
if (uart_handle_sysrq_char(port, ch, regs))
goto ignore_char;
- if ((lsr & port->ignore_status_mask) == 0)
- tty_insert_flip_char(tty, ch, flag);
- if ((lsr & UART_LSR_OE) && (tty->flip.count < TTY_FLIPBUF_SIZE))
- tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+
+ uart_insert_char(port, lsr, UART_LSR_OE, ch, flag);
ignore_char:
lsr = siu_read(port, UART_LSR);
@@ -484,9 +482,6 @@ static irqreturn_t siu_interrupt(int irq, void *dev_id, struct pt_regs *regs)
struct uart_port *port;
uint8_t iir, lsr;
- if (dev_id == NULL)
- return IRQ_NONE;
-
port = (struct uart_port *)dev_id;
iir = siu_read(port, UART_IIR);
@@ -509,6 +504,9 @@ static int siu_startup(struct uart_port *port)
{
int retval;
+ if (port->membase == NULL)
+ return -ENODEV;
+
siu_clear_fifo(port);
(void)siu_read(port, UART_LSR);
@@ -547,9 +545,6 @@ static void siu_shutdown(struct uart_port *port)
unsigned long flags;
uint8_t lcr;
- if (port->membase == NULL)
- return;
-
siu_write(port, UART_IER, 0);
spin_lock_irqsave(&port->lock, flags);
@@ -804,53 +799,6 @@ static int siu_init_ports(void)
#ifdef CONFIG_SERIAL_VR41XX_CONSOLE
-static void early_set_termios(struct uart_port *port, struct termios *new,
- struct termios *old)
-{
- tcflag_t c_cflag;
- uint8_t lcr;
- unsigned int baud, quot;
-
- c_cflag = new->c_cflag;
- switch (c_cflag & CSIZE) {
- case CS5:
- lcr = UART_LCR_WLEN5;
- break;
- case CS6:
- lcr = UART_LCR_WLEN6;
- break;
- case CS7:
- lcr = UART_LCR_WLEN7;
- break;
- default:
- lcr = UART_LCR_WLEN8;
- break;
- }
-
- if (c_cflag & CSTOPB)
- lcr |= UART_LCR_STOP;
- if (c_cflag & PARENB)
- lcr |= UART_LCR_PARITY;
- if ((c_cflag & PARODD) != PARODD)
- lcr |= UART_LCR_EPAR;
- if (c_cflag & CMSPAR)
- lcr |= UART_LCR_SPAR;
-
- baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16);
- quot = uart_get_divisor(port, baud);
-
- siu_write(port, UART_LCR, lcr | UART_LCR_DLAB);
-
- siu_write(port, UART_DLL, (uint8_t)quot);
- siu_write(port, UART_DLM, (uint8_t)(quot >> 8));
-
- siu_write(port, UART_LCR, lcr);
-}
-
-static struct uart_ops early_uart_ops = {
- .set_termios = early_set_termios,
-};
-
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
static void wait_for_xmitr(struct uart_port *port)
@@ -917,7 +865,7 @@ static int siu_console_setup(struct console *con, char *options)
if (port->membase == NULL) {
if (port->mapbase == 0)
return -ENODEV;
- port->membase = (unsigned char __iomem *)KSEG1ADDR(port->mapbase);
+ port->membase = ioremap(port->mapbase, siu_port_size(port));
}
vr41xx_select_siu_interface(SIU_INTERFACE_RS232C);
@@ -951,7 +899,7 @@ static int __devinit siu_console_init(void)
for (i = 0; i < num; i++) {
port = &siu_uart_ports[i];
- port->ops = &early_uart_ops;
+ port->ops = &siu_uart_ops;
}
register_console(&siu_console);
@@ -996,8 +944,10 @@ static int siu_probe(struct device *dev)
port->dev = dev;
retval = uart_add_one_port(&siu_uart_driver, port);
- if (retval)
+ if (retval < 0) {
+ port->dev = NULL;
break;
+ }
}
if (i == 0 && retval < 0) {
diff --git a/drivers/sh/superhyway/superhyway-sysfs.c b/drivers/sh/superhyway/superhyway-sysfs.c
index 39ab6a12da7..dc119ce68e3 100644
--- a/drivers/sh/superhyway/superhyway-sysfs.c
+++ b/drivers/sh/superhyway/superhyway-sysfs.c
@@ -15,7 +15,7 @@
#include <linux/superhyway.h>
#define superhyway_ro_attr(name, fmt, field) \
-static ssize_t name##_show(struct device *dev, char *buf) \
+static ssize_t name##_show(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct superhyway_device *s = to_superhyway_device(dev); \
return sprintf(buf, fmt, s->field); \
diff --git a/drivers/sn/Kconfig b/drivers/sn/Kconfig
new file mode 100644
index 00000000000..13b8d249da5
--- /dev/null
+++ b/drivers/sn/Kconfig
@@ -0,0 +1,20 @@
+#
+# Miscellaneous SN-specific devices
+#
+
+menu "SN Devices"
+
+config SGI_IOC4
+ tristate "SGI IOC4 Base IO support"
+ depends on (IA64_GENERIC || IA64_SGI_SN2) && MMTIMER
+ default m
+ ---help---
+ This option enables basic support for the SGI IOC4-based Base IO
+ controller card. This option does not enable any specific
+ functions on such a card, but provides necessary infrastructure
+ for other drivers to utilize.
+
+ If you have an SGI Altix with an IOC4-based
+ I/O controller say Y. Otherwise say N.
+
+endmenu
diff --git a/drivers/sn/Makefile b/drivers/sn/Makefile
index 631e5495844..c2a28418537 100644
--- a/drivers/sn/Makefile
+++ b/drivers/sn/Makefile
@@ -3,4 +3,4 @@
#
#
-obj-$(CONFIG_BLK_DEV_SGIIOC4) += ioc4.o
+obj-$(CONFIG_SGI_IOC4) += ioc4.o
diff --git a/drivers/sn/ioc4.c b/drivers/sn/ioc4.c
index d9e4ee280e5..ea75b3d0612 100644
--- a/drivers/sn/ioc4.c
+++ b/drivers/sn/ioc4.c
@@ -6,60 +6,422 @@
* Copyright (C) 2005 Silicon Graphics, Inc. All Rights Reserved.
*/
-/*
- * This file contains a shim driver for the IOC4 IDE and serial drivers.
+/* This file contains the master driver module for use by SGI IOC4 subdrivers.
+ *
+ * It allocates any resources shared between multiple subdevices, and
+ * provides accessor functions (where needed) and the like for those
+ * resources. It also provides a mechanism for the subdevice modules
+ * to support loading and unloading.
+ *
+ * Non-shared resources (e.g. external interrupt A_INT_OUT register page
+ * alias, serial port and UART registers) are handled by the subdevice
+ * modules themselves.
+ *
+ * This is all necessary because IOC4 is not implemented as a multi-function
+ * PCI device, but an amalgamation of disparate registers for several
+ * types of device (ATA, serial, external interrupts). The normal
+ * resource management in the kernel doesn't have quite the right interfaces
+ * to handle this situation (e.g. multiple modules can't claim the same
+ * PCI ID), thus this IOC4 master module.
*/
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/pci.h>
-#include <linux/ioc4_common.h>
-#include <linux/ide.h>
+#include <linux/ioc4.h>
+#include <linux/mmtimer.h>
+#include <linux/rtc.h>
+#include <linux/rwsem.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/clksupport.h>
+#include <asm/sn/shub_mmr.h>
+/***************
+ * Definitions *
+ ***************/
-static int __devinit
-ioc4_probe_one(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+/* Tweakable values */
+
+/* PCI bus speed detection/calibration */
+#define IOC4_CALIBRATE_COUNT 63 /* Calibration cycle period */
+#define IOC4_CALIBRATE_CYCLES 256 /* Average over this many cycles */
+#define IOC4_CALIBRATE_DISCARD 2 /* Discard first few cycles */
+#define IOC4_CALIBRATE_LOW_MHZ 25 /* Lower bound on bus speed sanity */
+#define IOC4_CALIBRATE_HIGH_MHZ 75 /* Upper bound on bus speed sanity */
+#define IOC4_CALIBRATE_DEFAULT_MHZ 66 /* Assumed if sanity check fails */
+
+/************************
+ * Submodule management *
+ ************************/
+
+static LIST_HEAD(ioc4_devices);
+static DECLARE_RWSEM(ioc4_devices_rwsem);
+
+static LIST_HEAD(ioc4_submodules);
+static DECLARE_RWSEM(ioc4_submodules_rwsem);
+
+/* Register an IOC4 submodule */
+int
+ioc4_register_submodule(struct ioc4_submodule *is)
+{
+ struct ioc4_driver_data *idd;
+
+ down_write(&ioc4_submodules_rwsem);
+ list_add(&is->is_list, &ioc4_submodules);
+ up_write(&ioc4_submodules_rwsem);
+
+ /* Initialize submodule for each IOC4 */
+ if (!is->is_probe)
+ return 0;
+
+ down_read(&ioc4_devices_rwsem);
+ list_for_each_entry(idd, &ioc4_devices, idd_list) {
+ if (is->is_probe(idd)) {
+ printk(KERN_WARNING
+ "%s: IOC4 submodule %s probe failed "
+ "for pci_dev %s",
+ __FUNCTION__, module_name(is->is_owner),
+ pci_name(idd->idd_pdev));
+ }
+ }
+ up_read(&ioc4_devices_rwsem);
+
+ return 0;
+}
+
+/* Unregister an IOC4 submodule */
+void
+ioc4_unregister_submodule(struct ioc4_submodule *is)
+{
+ struct ioc4_driver_data *idd;
+
+ down_write(&ioc4_submodules_rwsem);
+ list_del(&is->is_list);
+ up_write(&ioc4_submodules_rwsem);
+
+ /* Remove submodule for each IOC4 */
+ if (!is->is_remove)
+ return;
+
+ down_read(&ioc4_devices_rwsem);
+ list_for_each_entry(idd, &ioc4_devices, idd_list) {
+ if (is->is_remove(idd)) {
+ printk(KERN_WARNING
+ "%s: IOC4 submodule %s remove failed "
+ "for pci_dev %s.\n",
+ __FUNCTION__, module_name(is->is_owner),
+ pci_name(idd->idd_pdev));
+ }
+ }
+ up_read(&ioc4_devices_rwsem);
+}
+
+/*********************
+ * Device management *
+ *********************/
+
+#define IOC4_CALIBRATE_LOW_LIMIT \
+ (1000*IOC4_EXTINT_COUNT_DIVISOR/IOC4_CALIBRATE_LOW_MHZ)
+#define IOC4_CALIBRATE_HIGH_LIMIT \
+ (1000*IOC4_EXTINT_COUNT_DIVISOR/IOC4_CALIBRATE_HIGH_MHZ)
+#define IOC4_CALIBRATE_DEFAULT \
+ (1000*IOC4_EXTINT_COUNT_DIVISOR/IOC4_CALIBRATE_DEFAULT_MHZ)
+
+#define IOC4_CALIBRATE_END \
+ (IOC4_CALIBRATE_CYCLES + IOC4_CALIBRATE_DISCARD)
+
+#define IOC4_INT_OUT_MODE_TOGGLE 0x7 /* Toggle INT_OUT every COUNT+1 ticks */
+
+/* Determines external interrupt output clock period of the PCI bus an
+ * IOC4 is attached to. This value can be used to determine the PCI
+ * bus speed.
+ *
+ * IOC4 has a design feature that various internal timers are derived from
+ * the PCI bus clock. This causes IOC4 device drivers to need to take the
+ * bus speed into account when setting various register values (e.g. INT_OUT
+ * register COUNT field, UART divisors, etc). Since this information is
+ * needed by several subdrivers, it is determined by the main IOC4 driver,
+ * even though the following code utilizes external interrupt registers
+ * to perform the speed calculation.
+ */
+static void
+ioc4_clock_calibrate(struct ioc4_driver_data *idd)
+{
+ extern unsigned long sn_rtc_cycles_per_second;
+ union ioc4_int_out int_out;
+ union ioc4_gpcr gpcr;
+ unsigned int state, last_state = 1;
+ uint64_t start = 0, end, period;
+ unsigned int count = 0;
+
+ /* Enable output */
+ gpcr.raw = 0;
+ gpcr.fields.dir = IOC4_GPCR_DIR_0;
+ gpcr.fields.int_out_en = 1;
+ writel(gpcr.raw, &idd->idd_misc_regs->gpcr_s.raw);
+
+ /* Reset to power-on state */
+ writel(0, &idd->idd_misc_regs->int_out.raw);
+ mmiowb();
+
+ printk(KERN_INFO
+ "%s: Calibrating PCI bus speed "
+ "for pci_dev %s ... ", __FUNCTION__, pci_name(idd->idd_pdev));
+ /* Set up square wave */
+ int_out.raw = 0;
+ int_out.fields.count = IOC4_CALIBRATE_COUNT;
+ int_out.fields.mode = IOC4_INT_OUT_MODE_TOGGLE;
+ int_out.fields.diag = 0;
+ writel(int_out.raw, &idd->idd_misc_regs->int_out.raw);
+ mmiowb();
+
+ /* Check square wave period averaged over some number of cycles */
+ do {
+ int_out.raw = readl(&idd->idd_misc_regs->int_out.raw);
+ state = int_out.fields.int_out;
+ if (!last_state && state) {
+ count++;
+ if (count == IOC4_CALIBRATE_END) {
+ end = rtc_time();
+ break;
+ } else if (count == IOC4_CALIBRATE_DISCARD)
+ start = rtc_time();
+ }
+ last_state = state;
+ } while (1);
+
+ /* Calculation rearranged to preserve intermediate precision.
+ * Logically:
+ * 1. "end - start" gives us number of RTC cycles over all the
+ * square wave cycles measured.
+ * 2. Divide by number of square wave cycles to get number of
+ * RTC cycles per square wave cycle.
+ * 3. Divide by 2*(int_out.fields.count+1), which is the formula
+ * by which the IOC4 generates the square wave, to get the
+ * number of RTC cycles per IOC4 INT_OUT count.
+ * 4. Divide by sn_rtc_cycles_per_second to get seconds per
+ * count.
+ * 5. Multiply by 1E9 to get nanoseconds per count.
+ */
+ period = ((end - start) * 1000000000) /
+ (IOC4_CALIBRATE_CYCLES * 2 * (IOC4_CALIBRATE_COUNT + 1)
+ * sn_rtc_cycles_per_second);
+
+ /* Bounds check the result. */
+ if (period > IOC4_CALIBRATE_LOW_LIMIT ||
+ period < IOC4_CALIBRATE_HIGH_LIMIT) {
+ printk("failed. Assuming PCI clock ticks are %d ns.\n",
+ IOC4_CALIBRATE_DEFAULT / IOC4_EXTINT_COUNT_DIVISOR);
+ period = IOC4_CALIBRATE_DEFAULT;
+ } else {
+ printk("succeeded. PCI clock ticks are %ld ns.\n",
+ period / IOC4_EXTINT_COUNT_DIVISOR);
+ }
+
+ /* Remember results. We store the extint clock period rather
+ * than the PCI clock period so that greater precision is
+ * retained. Divide by IOC4_EXTINT_COUNT_DIVISOR to get
+ * PCI clock period.
+ */
+ idd->count_period = period;
+}
+
+/* Adds a new instance of an IOC4 card */
+static int
+ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
{
+ struct ioc4_driver_data *idd;
+ struct ioc4_submodule *is;
+ uint32_t pcmd;
int ret;
+ /* Enable IOC4 and take ownership of it */
if ((ret = pci_enable_device(pdev))) {
printk(KERN_WARNING
- "%s: Failed to enable device with "
- "pci_dev 0x%p... returning\n",
- __FUNCTION__, (void *)pdev);
- return ret;
+ "%s: Failed to enable IOC4 device for pci_dev %s.\n",
+ __FUNCTION__, pci_name(pdev));
+ goto out;
}
pci_set_master(pdev);
- /* attach each sub-device */
- ret = ioc4_ide_attach_one(pdev, pci_id);
- if (ret)
- return ret;
- return ioc4_serial_attach_one(pdev, pci_id);
+ /* Set up per-IOC4 data */
+ idd = kmalloc(sizeof(struct ioc4_driver_data), GFP_KERNEL);
+ if (!idd) {
+ printk(KERN_WARNING
+ "%s: Failed to allocate IOC4 data for pci_dev %s.\n",
+ __FUNCTION__, pci_name(pdev));
+ ret = -ENODEV;
+ goto out_idd;
+ }
+ idd->idd_pdev = pdev;
+ idd->idd_pci_id = pci_id;
+
+ /* Map IOC4 misc registers. These are shared between subdevices
+ * so the main IOC4 module manages them.
+ */
+ idd->idd_bar0 = pci_resource_start(idd->idd_pdev, 0);
+ if (!idd->idd_bar0) {
+ printk(KERN_WARNING
+ "%s: Unable to find IOC4 misc resource "
+ "for pci_dev %s.\n",
+ __FUNCTION__, pci_name(idd->idd_pdev));
+ ret = -ENODEV;
+ goto out_pci;
+ }
+ if (!request_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs),
+ "ioc4_misc")) {
+ printk(KERN_WARNING
+ "%s: Unable to request IOC4 misc region "
+ "for pci_dev %s.\n",
+ __FUNCTION__, pci_name(idd->idd_pdev));
+ ret = -ENODEV;
+ goto out_pci;
+ }
+ idd->idd_misc_regs = ioremap(idd->idd_bar0,
+ sizeof(struct ioc4_misc_regs));
+ if (!idd->idd_misc_regs) {
+ printk(KERN_WARNING
+ "%s: Unable to remap IOC4 misc region "
+ "for pci_dev %s.\n",
+ __FUNCTION__, pci_name(idd->idd_pdev));
+ ret = -ENODEV;
+ goto out_misc_region;
+ }
+
+ /* Failsafe portion of per-IOC4 initialization */
+
+ /* Initialize IOC4 */
+ pci_read_config_dword(idd->idd_pdev, PCI_COMMAND, &pcmd);
+ pci_write_config_dword(idd->idd_pdev, PCI_COMMAND,
+ pcmd | PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
+
+ /* Determine PCI clock */
+ ioc4_clock_calibrate(idd);
+
+ /* Disable/clear all interrupts. Need to do this here lest
+ * one submodule request the shared IOC4 IRQ, but interrupt
+ * is generated by a different subdevice.
+ */
+ /* Disable */
+ writel(~0, &idd->idd_misc_regs->other_iec.raw);
+ writel(~0, &idd->idd_misc_regs->sio_iec);
+ /* Clear (i.e. acknowledge) */
+ writel(~0, &idd->idd_misc_regs->other_ir.raw);
+ writel(~0, &idd->idd_misc_regs->sio_ir);
+
+ /* Track PCI-device specific data */
+ idd->idd_serial_data = NULL;
+ pci_set_drvdata(idd->idd_pdev, idd);
+ down_write(&ioc4_devices_rwsem);
+ list_add(&idd->idd_list, &ioc4_devices);
+ up_write(&ioc4_devices_rwsem);
+
+ /* Add this IOC4 to all submodules */
+ down_read(&ioc4_submodules_rwsem);
+ list_for_each_entry(is, &ioc4_submodules, is_list) {
+ if (is->is_probe && is->is_probe(idd)) {
+ printk(KERN_WARNING
+ "%s: IOC4 submodule 0x%s probe failed "
+ "for pci_dev %s.\n",
+ __FUNCTION__, module_name(is->is_owner),
+ pci_name(idd->idd_pdev));
+ }
+ }
+ up_read(&ioc4_submodules_rwsem);
+
+ return 0;
+
+out_misc_region:
+ release_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs));
+out_pci:
+ kfree(idd);
+out_idd:
+ pci_disable_device(pdev);
+out:
+ return ret;
}
-/* pci device struct */
-static struct pci_device_id ioc4_s_id_table[] = {
+/* Removes a particular instance of an IOC4 card. */
+static void
+ioc4_remove(struct pci_dev *pdev)
+{
+ struct ioc4_submodule *is;
+ struct ioc4_driver_data *idd;
+
+ idd = pci_get_drvdata(pdev);
+
+ /* Remove this IOC4 from all submodules */
+ down_read(&ioc4_submodules_rwsem);
+ list_for_each_entry(is, &ioc4_submodules, is_list) {
+ if (is->is_remove && is->is_remove(idd)) {
+ printk(KERN_WARNING
+ "%s: IOC4 submodule 0x%s remove failed "
+ "for pci_dev %s.\n",
+ __FUNCTION__, module_name(is->is_owner),
+ pci_name(idd->idd_pdev));
+ }
+ }
+ up_read(&ioc4_submodules_rwsem);
+
+ /* Release resources */
+ iounmap(idd->idd_misc_regs);
+ if (!idd->idd_bar0) {
+ printk(KERN_WARNING
+ "%s: Unable to get IOC4 misc mapping for pci_dev %s. "
+ "Device removal may be incomplete.\n",
+ __FUNCTION__, pci_name(idd->idd_pdev));
+ }
+ release_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs));
+
+ /* Disable IOC4 and relinquish */
+ pci_disable_device(pdev);
+
+ /* Remove and free driver data */
+ down_write(&ioc4_devices_rwsem);
+ list_del(&idd->idd_list);
+ up_write(&ioc4_devices_rwsem);
+ kfree(idd);
+}
+
+static struct pci_device_id ioc4_id_table[] = {
{PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC4, PCI_ANY_ID,
PCI_ANY_ID, 0x0b4000, 0xFFFFFF},
{0}
};
-MODULE_DEVICE_TABLE(pci, ioc4_s_id_table);
-static struct pci_driver __devinitdata ioc4_s_driver = {
- .name = "IOC4",
- .id_table = ioc4_s_id_table,
- .probe = ioc4_probe_one,
+static struct pci_driver __devinitdata ioc4_driver = {
+ .name = "IOC4",
+ .id_table = ioc4_id_table,
+ .probe = ioc4_probe,
+ .remove = ioc4_remove,
};
-static int __devinit ioc4_detect(void)
+MODULE_DEVICE_TABLE(pci, ioc4_id_table);
+
+/*********************
+ * Module management *
+ *********************/
+
+/* Module load */
+static int __devinit
+ioc4_init(void)
{
- ioc4_serial_init();
+ return pci_register_driver(&ioc4_driver);
+}
- return pci_register_driver(&ioc4_s_driver);
+/* Module unload */
+static void __devexit
+ioc4_exit(void)
+{
+ pci_unregister_driver(&ioc4_driver);
}
-module_init(ioc4_detect);
-MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>");
-MODULE_DESCRIPTION("PCI driver module for SGI IOC4 Base-IO Card");
+module_init(ioc4_init);
+module_exit(ioc4_exit);
+
+MODULE_AUTHOR("Brent Casavant - Silicon Graphics, Inc. <bcasavan@sgi.com>");
+MODULE_DESCRIPTION("PCI driver master module for SGI IOC4 Base-IO Card");
MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(ioc4_register_submodule);
+EXPORT_SYMBOL(ioc4_unregister_submodule);
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
index d5863b8b56e..f2c9fa423d4 100644
--- a/drivers/telephony/ixj.c
+++ b/drivers/telephony/ixj.c
@@ -329,10 +329,8 @@ static IXJ *ixj_alloc()
static void ixj_fsk_free(IXJ *j)
{
- if(j->fskdata != NULL) {
- kfree(j->fskdata);
- j->fskdata = NULL;
- }
+ kfree(j->fskdata);
+ j->fskdata = NULL;
}
static void ixj_fsk_alloc(IXJ *j)
@@ -3867,13 +3865,11 @@ static int set_rec_codec(IXJ *j, int rate)
j->rec_mode = 7;
break;
default:
+ kfree(j->read_buffer);
j->rec_frame_size = 0;
j->rec_mode = -1;
- if (j->read_buffer) {
- kfree(j->read_buffer);
- j->read_buffer = NULL;
- j->read_buffer_size = 0;
- }
+ j->read_buffer = NULL;
+ j->read_buffer_size = 0;
retval = 1;
break;
}
@@ -3991,14 +3987,12 @@ static int ixj_record_start(IXJ *j)
static void ixj_record_stop(IXJ *j)
{
- if(ixjdebug & 0x0002)
+ if (ixjdebug & 0x0002)
printk("IXJ %d Stopping Record Codec %d at %ld\n", j->board, j->rec_codec, jiffies);
- if (j->read_buffer) {
- kfree(j->read_buffer);
- j->read_buffer = NULL;
- j->read_buffer_size = 0;
- }
+ kfree(j->read_buffer);
+ j->read_buffer = NULL;
+ j->read_buffer_size = 0;
if (j->rec_mode > -1) {
ixj_WriteDSPCommand(0x5120, j);
j->rec_mode = -1;
@@ -4449,13 +4443,11 @@ static int set_play_codec(IXJ *j, int rate)
j->play_mode = 5;
break;
default:
+ kfree(j->write_buffer);
j->play_frame_size = 0;
j->play_mode = -1;
- if (j->write_buffer) {
- kfree(j->write_buffer);
- j->write_buffer = NULL;
- j->write_buffer_size = 0;
- }
+ j->write_buffer = NULL;
+ j->write_buffer_size = 0;
retval = 1;
break;
}
@@ -4578,14 +4570,12 @@ static int ixj_play_start(IXJ *j)
static void ixj_play_stop(IXJ *j)
{
- if(ixjdebug & 0x0002)
+ if (ixjdebug & 0x0002)
printk("IXJ %d Stopping Play Codec %d at %ld\n", j->board, j->play_codec, jiffies);
- if (j->write_buffer) {
- kfree(j->write_buffer);
- j->write_buffer = NULL;
- j->write_buffer_size = 0;
- }
+ kfree(j->write_buffer);
+ j->write_buffer = NULL;
+ j->write_buffer_size = 0;
if (j->play_mode > -1) {
ixj_WriteDSPCommand(0x5221, j); /* Stop playback and flush buffers. 8022 reference page 9-40 */
@@ -5810,9 +5800,7 @@ static void ixj_cpt_stop(IXJ *j)
ixj_play_tone(j, 0);
j->tone_state = j->tone_cadence_state = 0;
if (j->cadence_t) {
- if (j->cadence_t->ce) {
- kfree(j->cadence_t->ce);
- }
+ kfree(j->cadence_t->ce);
kfree(j->cadence_t);
j->cadence_t = NULL;
}
@@ -7497,10 +7485,8 @@ static void cleanup(void)
printk(KERN_INFO "IXJ: Releasing XILINX address for /dev/phone%d\n", cnt);
release_region(j->XILINXbase, 4);
}
- if (j->read_buffer)
- kfree(j->read_buffer);
- if (j->write_buffer)
- kfree(j->write_buffer);
+ kfree(j->read_buffer);
+ kfree(j->write_buffer);
if (j->dev)
pnp_device_detach(j->dev);
if (ixjdebug & 0x0002)
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index 233f9229bad..2a1697bfd69 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -386,6 +386,8 @@ static void speedtch_poll_status(struct speedtch_instance_data *instance)
if (instance->u.atm_dev->signal != ATM_PHY_SIG_LOST) {
instance->u.atm_dev->signal = ATM_PHY_SIG_LOST;
printk(KERN_NOTICE "ADSL line is down\n");
+ /* It'll never resync again unless we ask it to... */
+ speedtch_start_synchro(instance);
}
break;
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index ef0b35731ff..83e815d3cd5 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -239,7 +239,7 @@ static char *usb_dump_interface_descriptor(char *start, char *end,
int setno)
{
const struct usb_interface_descriptor *desc = &intfc->altsetting[setno].desc;
- char *driver_name = "";
+ const char *driver_name = "";
if (start > end)
return start;
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index 38ed2220c9f..65ca131cc44 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -68,7 +68,7 @@ static struct file_operations usb_fops = {
.open = usb_open,
};
-static struct class_simple *usb_class;
+static struct class *usb_class;
int usb_major_init(void)
{
@@ -80,9 +80,10 @@ int usb_major_init(void)
goto out;
}
- usb_class = class_simple_create(THIS_MODULE, "usb");
+ usb_class = class_create(THIS_MODULE, "usb");
if (IS_ERR(usb_class)) {
- err("class_simple_create failed for usb devices");
+ error = PTR_ERR(usb_class);
+ err("class_create failed for usb devices");
unregister_chrdev(USB_MAJOR, "usb");
goto out;
}
@@ -95,7 +96,7 @@ out:
void usb_major_cleanup(void)
{
- class_simple_destroy(usb_class);
+ class_destroy(usb_class);
devfs_remove("usb");
unregister_chrdev(USB_MAJOR, "usb");
}
@@ -171,7 +172,7 @@ int usb_register_dev(struct usb_interface *intf,
++temp;
else
temp = name;
- intf->class_dev = class_simple_device_add(usb_class, MKDEV(USB_MAJOR, minor), &intf->dev, "%s", temp);
+ intf->class_dev = class_device_create(usb_class, MKDEV(USB_MAJOR, minor), &intf->dev, "%s", temp);
if (IS_ERR(intf->class_dev)) {
spin_lock (&minor_lock);
usb_minors[intf->minor] = NULL;
@@ -220,7 +221,7 @@ void usb_deregister_dev(struct usb_interface *intf,
snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base);
devfs_remove (name);
- class_simple_device_remove(MKDEV(USB_MAJOR, intf->minor));
+ class_device_destroy(usb_class, MKDEV(USB_MAJOR, intf->minor));
intf->class_dev = NULL;
intf->minor = -1;
}
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 266e9e06a9f..0da23732e80 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -651,50 +651,45 @@ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
/*-------------------------------------------------------------------------*/
/* exported only within usbcore */
-struct usb_bus *usb_bus_get (struct usb_bus *bus)
+struct usb_bus *usb_bus_get(struct usb_bus *bus)
{
- struct class_device *tmp;
+ if (bus)
+ kref_get(&bus->kref);
+ return bus;
+}
- if (!bus)
- return NULL;
+static void usb_host_release(struct kref *kref)
+{
+ struct usb_bus *bus = container_of(kref, struct usb_bus, kref);
- tmp = class_device_get(&bus->class_dev);
- if (tmp)
- return to_usb_bus(tmp);
- else
- return NULL;
+ if (bus->release)
+ bus->release(bus);
}
/* exported only within usbcore */
-void usb_bus_put (struct usb_bus *bus)
+void usb_bus_put(struct usb_bus *bus)
{
if (bus)
- class_device_put(&bus->class_dev);
+ kref_put(&bus->kref, usb_host_release);
}
/*-------------------------------------------------------------------------*/
-static void usb_host_release(struct class_device *class_dev)
-{
- struct usb_bus *bus = to_usb_bus(class_dev);
-
- if (bus->release)
- bus->release(bus);
-}
-
-static struct class usb_host_class = {
- .name = "usb_host",
- .release = &usb_host_release,
-};
+static struct class *usb_host_class;
int usb_host_init(void)
{
- return class_register(&usb_host_class);
+ int retval = 0;
+
+ usb_host_class = class_create(THIS_MODULE, "usb_host");
+ if (IS_ERR(usb_host_class))
+ retval = PTR_ERR(usb_host_class);
+ return retval;
}
void usb_host_cleanup(void)
{
- class_unregister(&usb_host_class);
+ class_destroy(usb_host_class);
}
/**
@@ -719,8 +714,7 @@ static void usb_bus_init (struct usb_bus *bus)
INIT_LIST_HEAD (&bus->bus_list);
- class_device_initialize(&bus->class_dev);
- bus->class_dev.class = &usb_host_class;
+ kref_init(&bus->kref);
}
/**
@@ -761,7 +755,6 @@ struct usb_bus *usb_alloc_bus (struct usb_operations *op)
static int usb_register_bus(struct usb_bus *bus)
{
int busnum;
- int retval;
down (&usb_bus_list_lock);
busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1);
@@ -774,15 +767,15 @@ static int usb_register_bus(struct usb_bus *bus)
return -E2BIG;
}
- snprintf(bus->class_dev.class_id, BUS_ID_SIZE, "usb%d", busnum);
- bus->class_dev.dev = bus->controller;
- retval = class_device_add(&bus->class_dev);
- if (retval) {
+ bus->class_dev = class_device_create(usb_host_class, MKDEV(0,0), bus->controller, "usb%d", busnum);
+ if (IS_ERR(bus->class_dev)) {
clear_bit(busnum, busmap.busmap);
up(&usb_bus_list_lock);
- return retval;
+ return PTR_ERR(bus->class_dev);
}
+ class_set_devdata(bus->class_dev, bus);
+
/* Add it to the local list of buses */
list_add (&bus->bus_list, &usb_bus_list);
up (&usb_bus_list_lock);
@@ -820,7 +813,7 @@ static void usb_deregister_bus (struct usb_bus *bus)
clear_bit (bus->busnum, busmap.busmap);
- class_device_del(&bus->class_dev);
+ class_device_unregister(bus->class_dev);
}
/**
@@ -1801,7 +1794,7 @@ EXPORT_SYMBOL (usb_remove_hcd);
/*-------------------------------------------------------------------------*/
-#if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)
+#if defined(CONFIG_USB_MON)
struct usb_mon_operations *mon_ops;
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index f67cf1e634f..325a51656c3 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -399,7 +399,7 @@ static inline void usbfs_cleanup(void) { }
/*-------------------------------------------------------------------------*/
-#if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)
+#if defined(CONFIG_USB_MON)
struct usb_mon_operations {
void (*urb_submit)(struct usb_bus *bus, struct urb *urb);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index d2d648ee864..a8d879a85d0 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -2808,7 +2808,7 @@ static int hub_thread(void *__unused)
do {
hub_events();
wait_event_interruptible(khubd_wait, !list_empty(&hub_event_list));
- try_to_freeze(PF_FREEZE);
+ try_to_freeze();
} while (!signal_pending(current));
pr_debug ("%s: khubd exiting\n", usbcore_name);
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index f9f9561c6ba..c3e3a95d380 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -453,17 +453,6 @@ static int usbfs_fill_super(struct super_block *sb, void *data, int silent)
return 0;
}
-static struct dentry * get_dentry(struct dentry *parent, const char *name)
-{
- struct qstr qstr;
-
- qstr.name = name;
- qstr.len = strlen(name);
- qstr.hash = full_name_hash(name,qstr.len);
- return lookup_hash(&qstr,parent);
-}
-
-
/*
* fs_create_by_name - create a file, given a name
* @name: name of file
@@ -496,7 +485,7 @@ static int fs_create_by_name (const char *name, mode_t mode,
*dentry = NULL;
down(&parent->d_inode->i_sem);
- *dentry = get_dentry (parent, name);
+ *dentry = lookup_one_len(name, parent, strlen(name));
if (!IS_ERR(dentry)) {
if ((mode & S_IFMT) == S_IFDIR)
error = usbfs_mkdir (parent->d_inode, *dentry, mode);
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index ec9b3bde8ae..740cb4c668d 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -24,7 +24,7 @@
/* Active configuration fields */
#define usb_actconfig_show(field, multiplier, format_string) \
-static ssize_t show_##field (struct device *dev, char *buf) \
+static ssize_t show_##field (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct usb_device *udev; \
struct usb_host_config *actconfig; \
@@ -46,7 +46,7 @@ usb_actconfig_attr (bNumInterfaces, 1, "%2d\n")
usb_actconfig_attr (bmAttributes, 1, "%2x\n")
usb_actconfig_attr (bMaxPower, 2, "%3dmA\n")
-static ssize_t show_configuration_string(struct device *dev, char *buf)
+static ssize_t show_configuration_string(struct device *dev, struct device_attribute *attr, char *buf)
{
struct usb_device *udev;
struct usb_host_config *actconfig;
@@ -69,7 +69,7 @@ static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL);
usb_actconfig_show(bConfigurationValue, 1, "%u\n");
static ssize_t
-set_bConfigurationValue (struct device *dev, const char *buf, size_t count)
+set_bConfigurationValue (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct usb_device *udev = udev = to_usb_device (dev);
int config, value;
@@ -87,7 +87,7 @@ static DEVICE_ATTR(bConfigurationValue, S_IRUGO | S_IWUSR,
/* String fields */
#define usb_string_attr(name) \
-static ssize_t show_##name(struct device *dev, char *buf) \
+static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct usb_device *udev; \
int len; \
@@ -107,7 +107,7 @@ usb_string_attr(manufacturer);
usb_string_attr(serial);
static ssize_t
-show_speed (struct device *dev, char *buf)
+show_speed (struct device *dev, struct device_attribute *attr, char *buf)
{
struct usb_device *udev;
char *speed;
@@ -133,7 +133,7 @@ show_speed (struct device *dev, char *buf)
static DEVICE_ATTR(speed, S_IRUGO, show_speed, NULL);
static ssize_t
-show_devnum (struct device *dev, char *buf)
+show_devnum (struct device *dev, struct device_attribute *attr, char *buf)
{
struct usb_device *udev;
@@ -143,7 +143,7 @@ show_devnum (struct device *dev, char *buf)
static DEVICE_ATTR(devnum, S_IRUGO, show_devnum, NULL);
static ssize_t
-show_version (struct device *dev, char *buf)
+show_version (struct device *dev, struct device_attribute *attr, char *buf)
{
struct usb_device *udev;
u16 bcdUSB;
@@ -155,7 +155,7 @@ show_version (struct device *dev, char *buf)
static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
static ssize_t
-show_maxchild (struct device *dev, char *buf)
+show_maxchild (struct device *dev, struct device_attribute *attr, char *buf)
{
struct usb_device *udev;
@@ -167,7 +167,7 @@ static DEVICE_ATTR(maxchild, S_IRUGO, show_maxchild, NULL);
/* Descriptor fields */
#define usb_descriptor_attr_le16(field, format_string) \
static ssize_t \
-show_##field (struct device *dev, char *buf) \
+show_##field (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct usb_device *udev; \
\
@@ -183,7 +183,7 @@ usb_descriptor_attr_le16(bcdDevice, "%04x\n")
#define usb_descriptor_attr(field, format_string) \
static ssize_t \
-show_##field (struct device *dev, char *buf) \
+show_##field (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct usb_device *udev; \
\
@@ -254,7 +254,7 @@ void usb_remove_sysfs_dev_files (struct usb_device *udev)
/* Interface fields */
#define usb_intf_attr(field, format_string) \
static ssize_t \
-show_##field (struct device *dev, char *buf) \
+show_##field (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct usb_interface *intf = to_usb_interface (dev); \
\
@@ -269,7 +269,7 @@ usb_intf_attr (bInterfaceClass, "%02x\n")
usb_intf_attr (bInterfaceSubClass, "%02x\n")
usb_intf_attr (bInterfaceProtocol, "%02x\n")
-static ssize_t show_interface_string(struct device *dev, char *buf)
+static ssize_t show_interface_string(struct device *dev, struct device_attribute *attr, char *buf)
{
struct usb_interface *intf;
struct usb_device *udev;
@@ -286,6 +286,37 @@ static ssize_t show_interface_string(struct device *dev, char *buf)
}
static DEVICE_ATTR(interface, S_IRUGO, show_interface_string, NULL);
+static ssize_t show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct usb_interface *intf;
+ struct usb_device *udev;
+ int len;
+
+ intf = to_usb_interface(dev);
+ udev = interface_to_usbdev(intf);
+
+ len = sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic",
+ le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct),
+ le16_to_cpu(udev->descriptor.bcdDevice),
+ udev->descriptor.bDeviceClass,
+ udev->descriptor.bDeviceSubClass,
+ udev->descriptor.bDeviceProtocol);
+ buf += len;
+
+ if (udev->descriptor.bDeviceClass == 0) {
+ struct usb_host_interface *alt = intf->cur_altsetting;
+
+ return len + sprintf(buf, "%02Xisc%02Xip%02X\n",
+ alt->desc.bInterfaceClass,
+ alt->desc.bInterfaceSubClass,
+ alt->desc.bInterfaceProtocol);
+ } else {
+ return len + sprintf(buf, "*isc*ip*\n");
+ }
+}
+static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
+
static struct attribute *intf_attrs[] = {
&dev_attr_bInterfaceNumber.attr,
&dev_attr_bAlternateSetting.attr,
@@ -293,6 +324,7 @@ static struct attribute *intf_attrs[] = {
&dev_attr_bInterfaceClass.attr,
&dev_attr_bInterfaceSubClass.attr,
&dev_attr_bInterfaceProtocol.attr,
+ &dev_attr_modalias.attr,
NULL,
};
static struct attribute_group intf_attr_grp = {
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 25cf7e9eccf..a3c42203213 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -293,7 +293,7 @@ int usb_driver_claim_interface(struct usb_driver *driver,
/* if interface was already added, bind now; else let
* the future device_add() bind it, bypassing probe()
*/
- if (!list_empty (&dev->bus_list))
+ if (klist_node_attached(&dev->knode_bus))
device_bind_driver(dev);
return 0;
@@ -322,9 +322,15 @@ void usb_driver_release_interface(struct usb_driver *driver,
if (!dev->driver || dev->driver != &driver->driver)
return;
- /* don't disconnect from disconnect(), or before dev_add() */
- if (!list_empty (&dev->driver_list) && !list_empty (&dev->bus_list))
+ /* don't release from within disconnect() */
+ if (iface->condition != USB_INTERFACE_BOUND)
+ return;
+
+ /* release only after device_add() */
+ if (klist_node_attached(&dev->knode_bus)) {
+ iface->condition = USB_INTERFACE_UNBINDING;
device_release_driver(dev);
+ }
dev->driver = NULL;
usb_set_intfdata(iface, NULL);
@@ -462,6 +468,25 @@ usb_match_id(struct usb_interface *interface, const struct usb_device_id *id)
return NULL;
}
+
+static int __find_interface(struct device * dev, void * data)
+{
+ struct usb_interface ** ret = (struct usb_interface **)data;
+ struct usb_interface * intf = *ret;
+ int *minor = (int *)data;
+
+ /* can't look at usb devices, only interfaces */
+ if (dev->driver == &usb_generic_driver)
+ return 0;
+
+ intf = to_usb_interface(dev);
+ if (intf->minor != -1 && intf->minor == *minor) {
+ *ret = intf;
+ return 1;
+ }
+ return 0;
+}
+
/**
* usb_find_interface - find usb_interface pointer for driver and device
* @drv: the driver whose current configuration is considered
@@ -473,26 +498,12 @@ usb_match_id(struct usb_interface *interface, const struct usb_device_id *id)
*/
struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)
{
- struct list_head *entry;
- struct device *dev;
- struct usb_interface *intf;
+ struct usb_interface *intf = (struct usb_interface *)(long)minor;
+ int ret;
- list_for_each(entry, &drv->driver.devices) {
- dev = container_of(entry, struct device, driver_list);
-
- /* can't look at usb devices, only interfaces */
- if (dev->driver == &usb_generic_driver)
- continue;
-
- intf = to_usb_interface(dev);
- if (intf->minor == -1)
- continue;
- if (intf->minor == minor)
- return intf;
- }
+ ret = driver_for_each_device(&drv->driver, NULL, &intf, __find_interface);
- /* no device found that matches */
- return NULL;
+ return ret ? intf : NULL;
}
static int usb_device_match (struct device *dev, struct device_driver *drv)
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 8ef8a9cd9ac..c039d2fbe7a 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -633,7 +633,7 @@ static const struct usb_gadget_ops dummy_ops = {
/* "function" sysfs attribute */
static ssize_t
-show_function (struct device *dev, char *buf)
+show_function (struct device *dev, struct device_attribute *attr, char *buf)
{
struct dummy *dum = gadget_dev_to_dummy (dev);
@@ -1600,7 +1600,7 @@ show_urb (char *buf, size_t size, struct urb *urb)
}
static ssize_t
-show_urbs (struct device *dev, char *buf)
+show_urbs (struct device *dev, struct device_attribute *attr, char *buf)
{
struct usb_hcd *hcd = dev_get_drvdata (dev);
struct dummy *dum = hcd_to_dummy (hcd);
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 4857f0e4ef4..a9be85103d2 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -1554,8 +1554,7 @@ static int sleep_thread(struct fsg_dev *fsg)
rc = wait_event_interruptible(fsg->thread_wqh,
fsg->thread_wakeup_needed);
fsg->thread_wakeup_needed = 0;
- if (current->flags & PF_FREEZE)
- refrigerator(PF_FREEZE);
+ try_to_freeze();
return (rc ? -EINTR : 0);
}
@@ -3554,14 +3553,14 @@ static void close_all_backing_files(struct fsg_dev *fsg)
}
-static ssize_t show_ro(struct device *dev, char *buf)
+static ssize_t show_ro(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lun *curlun = dev_to_lun(dev);
return sprintf(buf, "%d\n", curlun->ro);
}
-static ssize_t show_file(struct device *dev, char *buf)
+static ssize_t show_file(struct device *dev, struct device_attribute *attr, char *buf)
{
struct lun *curlun = dev_to_lun(dev);
struct fsg_dev *fsg = (struct fsg_dev *) dev_get_drvdata(dev);
@@ -3589,7 +3588,7 @@ static ssize_t show_file(struct device *dev, char *buf)
}
-static ssize_t store_ro(struct device *dev, const char *buf, size_t count)
+static ssize_t store_ro(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
ssize_t rc = count;
struct lun *curlun = dev_to_lun(dev);
@@ -3613,7 +3612,7 @@ static ssize_t store_ro(struct device *dev, const char *buf, size_t count)
return rc;
}
-static ssize_t store_file(struct device *dev, const char *buf, size_t count)
+static ssize_t store_file(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct lun *curlun = dev_to_lun(dev);
struct fsg_dev *fsg = (struct fsg_dev *) dev_get_drvdata(dev);
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index e5457f2026c..e47e398daeb 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -1469,7 +1469,7 @@ static const struct usb_gadget_ops net2280_ops = {
/* "function" sysfs attribute */
static ssize_t
-show_function (struct device *_dev, char *buf)
+show_function (struct device *_dev, struct device_attribute *attr, char *buf)
{
struct net2280 *dev = dev_get_drvdata (_dev);
@@ -1482,7 +1482,7 @@ show_function (struct device *_dev, char *buf)
static DEVICE_ATTR (function, S_IRUGO, show_function, NULL);
static ssize_t
-show_registers (struct device *_dev, char *buf)
+show_registers (struct device *_dev, struct device_attribute *attr, char *buf)
{
struct net2280 *dev;
char *next;
@@ -1637,7 +1637,7 @@ show_registers (struct device *_dev, char *buf)
static DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
static ssize_t
-show_queues (struct device *_dev, char *buf)
+show_queues (struct device *_dev, struct device_attribute *attr, char *buf)
{
struct net2280 *dev;
char *next;
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index 6390c5726d8..b8b4524ed74 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -1429,7 +1429,7 @@ done:
/* "function" sysfs attribute */
static ssize_t
-show_function (struct device *_dev, char *buf)
+show_function (struct device *_dev, struct device_attribute *attr, char *buf)
{
struct pxa2xx_udc *dev = dev_get_drvdata (_dev);
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 3196c3265ff..19e598c9641 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -124,3 +124,14 @@ config USB_SL811_HCD
To compile this driver as a module, choose M here: the
module will be called sl811-hcd.
+config USB_SL811_CS
+ tristate "CF/PCMCIA support for SL811HS HCD"
+ depends on USB_SL811_HCD && PCMCIA
+ default N
+ help
+ Wraps a PCMCIA driver around the SL811HS HCD, supporting the RATOC
+ REX-CFU1U CF card (often used with PDAs). If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called "sl811_cs".
+
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index a574ca06cf6..5dbd3e7a27c 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -7,4 +7,5 @@ obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o
obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o
obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o
+obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o
obj-$(CONFIG_ETRAX_ARCH_V10) += hc_crisv10.o
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 9b347d76538..2ff11d53567 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -450,7 +450,7 @@ show_async (struct class_device *class_dev, char *buf)
*buf = 0;
- bus = to_usb_bus(class_dev);
+ bus = class_get_devdata(class_dev);
hcd = bus->hcpriv;
ehci = hcd_to_ehci (hcd);
next = buf;
@@ -496,7 +496,7 @@ show_periodic (struct class_device *class_dev, char *buf)
return 0;
seen_count = 0;
- bus = to_usb_bus(class_dev);
+ bus = class_get_devdata(class_dev);
hcd = bus->hcpriv;
ehci = hcd_to_ehci (hcd);
next = buf;
@@ -633,7 +633,7 @@ show_registers (struct class_device *class_dev, char *buf)
static char fmt [] = "%*s\n";
static char label [] = "";
- bus = to_usb_bus(class_dev);
+ bus = class_get_devdata(class_dev);
hcd = bus->hcpriv;
ehci = hcd_to_ehci (hcd);
next = buf;
@@ -735,7 +735,7 @@ static CLASS_DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
static inline void create_debug_files (struct ehci_hcd *ehci)
{
- struct class_device *cldev = &ehci_to_hcd(ehci)->self.class_dev;
+ struct class_device *cldev = ehci_to_hcd(ehci)->self.class_dev;
class_device_create_file(cldev, &class_device_attr_async);
class_device_create_file(cldev, &class_device_attr_periodic);
@@ -744,7 +744,7 @@ static inline void create_debug_files (struct ehci_hcd *ehci)
static inline void remove_debug_files (struct ehci_hcd *ehci)
{
- struct class_device *cldev = &ehci_to_hcd(ehci)->self.class_dev;
+ struct class_device *cldev = ehci_to_hcd(ehci)->self.class_dev;
class_device_remove_file(cldev, &class_device_attr_async);
class_device_remove_file(cldev, &class_device_attr_periodic);
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 02fefab3501..d7b4f7939de 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -72,6 +72,7 @@ static int ehci_hub_suspend (struct usb_hcd *hcd)
}
/* turn off now-idle HC */
+ del_timer_sync (&ehci->watchdog);
ehci_halt (ehci);
hcd->state = HC_STATE_SUSPENDED;
@@ -438,9 +439,12 @@ static int ehci_hub_control (
/* force reset to complete */
writel (temp & ~PORT_RESET,
&ehci->regs->port_status [wIndex]);
+ /* REVISIT: some hardware needs 550+ usec to clear
+ * this bit; seems too long to spin routinely...
+ */
retval = handshake (
&ehci->regs->port_status [wIndex],
- PORT_RESET, 0, 500);
+ PORT_RESET, 0, 750);
if (retval != 0) {
ehci_err (ehci, "port %d reset error %d\n",
wIndex + 1, retval);
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index 62f53a21380..c58408c95c3 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -481,7 +481,7 @@ show_async (struct class_device *class_dev, char *buf)
size_t temp;
unsigned long flags;
- bus = to_usb_bus(class_dev);
+ bus = class_get_devdata(class_dev);
hcd = bus->hcpriv;
ohci = hcd_to_ohci(hcd);
@@ -514,7 +514,7 @@ show_periodic (struct class_device *class_dev, char *buf)
return 0;
seen_count = 0;
- bus = to_usb_bus(class_dev);
+ bus = class_get_devdata(class_dev);
hcd = bus->hcpriv;
ohci = hcd_to_ohci(hcd);
next = buf;
@@ -611,7 +611,7 @@ show_registers (struct class_device *class_dev, char *buf)
char *next;
u32 rdata;
- bus = to_usb_bus(class_dev);
+ bus = class_get_devdata(class_dev);
hcd = bus->hcpriv;
ohci = hcd_to_ohci(hcd);
regs = ohci->regs;
@@ -684,7 +684,7 @@ static CLASS_DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
static inline void create_debug_files (struct ohci_hcd *ohci)
{
- struct class_device *cldev = &ohci_to_hcd(ohci)->self.class_dev;
+ struct class_device *cldev = ohci_to_hcd(ohci)->self.class_dev;
class_device_create_file(cldev, &class_device_attr_async);
class_device_create_file(cldev, &class_device_attr_periodic);
@@ -694,7 +694,7 @@ static inline void create_debug_files (struct ohci_hcd *ohci)
static inline void remove_debug_files (struct ohci_hcd *ohci)
{
- struct class_device *cldev = &ohci_to_hcd(ohci)->self.class_dev;
+ struct class_device *cldev = ohci_to_hcd(ohci)->self.class_dev;
class_device_remove_file(cldev, &class_device_attr_async);
class_device_remove_file(cldev, &class_device_attr_periodic);
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index a374b769207..99d43f758ad 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -2,8 +2,8 @@
* SL811HS HCD (Host Controller Driver) for USB.
*
* Copyright (C) 2004 Psion Teklogix (for NetBook PRO)
- * Copyright (C) 2004 David Brownell
- *
+ * Copyright (C) 2004-2005 David Brownell
+ *
* Periodic scheduling is based on Roman's OHCI code
* Copyright (C) 1999 Roman Weissgaerber
*
@@ -15,7 +15,7 @@
* For documentation, see the SL811HS spec and the "SL811HS Embedded Host"
* document (providing significant pieces missing from that spec); plus
* the SL811S spec if you want peripheral side info.
- */
+ */
/*
* Status: Passed basic stress testing, works with hubs, mice, keyboards,
@@ -67,7 +67,7 @@
MODULE_DESCRIPTION("SL811HS USB Host Controller Driver");
MODULE_LICENSE("GPL");
-#define DRIVER_VERSION "15 Dec 2004"
+#define DRIVER_VERSION "19 May 2005"
#ifndef DEBUG
@@ -121,6 +121,10 @@ static void port_power(struct sl811 *sl811, int is_on)
/* reset as thoroughly as we can */
if (sl811->board && sl811->board->reset)
sl811->board->reset(hcd->self.controller);
+ else {
+ sl811_write(sl811, SL11H_CTLREG1, SL11H_CTL1MASK_SE0);
+ mdelay(20);
+ }
sl811_write(sl811, SL11H_IRQ_ENABLE, 0);
sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1);
@@ -443,6 +447,7 @@ static void finish_request(
spin_lock(&urb->lock);
if (urb->status == -EINPROGRESS)
urb->status = status;
+ urb->hcpriv = NULL;
spin_unlock(&urb->lock);
spin_unlock(&sl811->lock);
@@ -472,7 +477,7 @@ static void finish_request(
if (*prev)
*prev = ep->next;
sl811->load[i] -= ep->load;
- }
+ }
ep->branch = PERIODIC_SIZE;
sl811->periodic_count--;
sl811_to_hcd(sl811)->self.bandwidth_allocated
@@ -661,9 +666,9 @@ retry:
#ifdef QUIRK2
/* this may no longer be necessary ... */
- if (irqstat == 0 && ret == IRQ_NONE) {
+ if (irqstat == 0) {
irqstat = checkdone(sl811);
- if (irqstat /* && irq != ~0 */ )
+ if (irqstat)
sl811->stat_lost++;
}
#endif
@@ -722,7 +727,8 @@ retry:
if (sl811->active_a) {
sl811_write(sl811, SL811_EP_A(SL11H_HOSTCTLREG), 0);
finish_request(sl811, sl811->active_a,
- container_of(sl811->active_a->hep->urb_list.next,
+ container_of(sl811->active_a
+ ->hep->urb_list.next,
struct urb, urb_list),
NULL, -ESHUTDOWN);
sl811->active_a = NULL;
@@ -731,7 +737,8 @@ retry:
if (sl811->active_b) {
sl811_write(sl811, SL811_EP_B(SL11H_HOSTCTLREG), 0);
finish_request(sl811, sl811->active_b,
- container_of(sl811->active_b->hep->urb_list.next,
+ container_of(sl811->active_b
+ ->hep->urb_list.next,
struct urb, urb_list),
NULL, -ESHUTDOWN);
sl811->active_b = NULL;
@@ -761,7 +768,7 @@ retry:
goto retry;
}
- if (sl811->periodic_count == 0 && list_empty(&sl811->async))
+ if (sl811->periodic_count == 0 && list_empty(&sl811->async))
sofirq_off(sl811);
sl811_write(sl811, SL11H_IRQ_ENABLE, sl811->irq_enable);
@@ -796,7 +803,7 @@ static int balance(struct sl811 *sl811, u16 period, u16 load)
}
if (j < PERIODIC_SIZE)
continue;
- branch = i;
+ branch = i;
}
}
return branch;
@@ -890,6 +897,7 @@ static int sl811h_urb_enqueue(
break;
}
+ ep->hep = hep;
hep->hcpriv = ep;
}
@@ -961,15 +969,16 @@ fail:
static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
{
struct sl811 *sl811 = hcd_to_sl811(hcd);
- struct usb_host_endpoint *hep = urb->hcpriv;
+ struct usb_host_endpoint *hep;
unsigned long flags;
struct sl811h_ep *ep;
int retval = 0;
+ spin_lock_irqsave(&sl811->lock, flags);
+ hep = urb->hcpriv;
if (!hep)
- return -EINVAL;
+ goto fail;
- spin_lock_irqsave(&sl811->lock, flags);
ep = hep->hcpriv;
if (ep) {
/* finish right away if this urb can't be active ...
@@ -1017,6 +1026,7 @@ static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
VDBG("dequeue, urb %p active %s; wait4irq\n", urb,
(sl811->active_a == ep) ? "A" : "B");
} else
+fail:
retval = -EINVAL;
spin_unlock_irqrestore(&sl811->lock, flags);
return retval;
@@ -1576,6 +1586,9 @@ sl811h_start(struct usb_hcd *hcd)
if (sl811->board && sl811->board->power)
hub_set_power_budget(udev, sl811->board->power * 2);
+ /* enable power and interupts */
+ port_power(sl811, 1);
+
return 0;
}
@@ -1618,7 +1631,7 @@ static struct hc_driver sl811h_hc_driver = {
/*-------------------------------------------------------------------------*/
-static int __init_or_module
+static int __devexit
sl811h_remove(struct device *dev)
{
struct usb_hcd *hcd = dev_get_drvdata(dev);
@@ -1631,21 +1644,20 @@ sl811h_remove(struct device *dev)
remove_debug_file(sl811);
usb_remove_hcd(hcd);
- iounmap(sl811->data_reg);
+ /* some platforms may use IORESOURCE_IO */
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- release_mem_region(res->start, 1);
+ if (res)
+ iounmap(sl811->data_reg);
- iounmap(sl811->addr_reg);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(res->start, 1);
+ if (res)
+ iounmap(sl811->addr_reg);
usb_put_hcd(hcd);
return 0;
}
-#define resource_len(r) (((r)->end - (r)->start) + 1)
-
-static int __init
+static int __devinit
sl811h_probe(struct device *dev)
{
struct usb_hcd *hcd;
@@ -1656,7 +1668,7 @@ sl811h_probe(struct device *dev)
void __iomem *addr_reg;
void __iomem *data_reg;
int retval;
- u8 tmp;
+ u8 tmp, ioaddr = 0;
/* basic sanity checks first. board-specific init logic should
* have initialized these three resources and probably board
@@ -1664,13 +1676,8 @@ sl811h_probe(struct device *dev)
* minimal sanity checking.
*/
pdev = container_of(dev, struct platform_device, dev);
- if (pdev->num_resources < 3)
- return -ENODEV;
-
- addr = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- data = platform_get_resource(pdev, IORESOURCE_MEM, 1);
irq = platform_get_irq(pdev, 0);
- if (!addr || !data || irq < 0)
+ if (pdev->num_resources < 3 || irq < 0)
return -ENODEV;
/* refuse to confuse usbcore */
@@ -1679,24 +1686,31 @@ sl811h_probe(struct device *dev)
return -EINVAL;
}
- if (!request_mem_region(addr->start, 1, hcd_name)) {
- retval = -EBUSY;
- goto err1;
- }
- addr_reg = ioremap(addr->start, resource_len(addr));
- if (addr_reg == NULL) {
- retval = -ENOMEM;
- goto err2;
- }
+ /* the chip may be wired for either kind of addressing */
+ addr = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ data = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ retval = -EBUSY;
+ if (!addr || !data) {
+ addr = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ data = platform_get_resource(pdev, IORESOURCE_IO, 1);
+ if (!addr || !data)
+ return -ENODEV;
+ ioaddr = 1;
+
+ addr_reg = (void __iomem *) addr->start;
+ data_reg = (void __iomem *) data->start;
+ } else {
+ addr_reg = ioremap(addr->start, 1);
+ if (addr_reg == NULL) {
+ retval = -ENOMEM;
+ goto err2;
+ }
- if (!request_mem_region(data->start, 1, hcd_name)) {
- retval = -EBUSY;
- goto err3;
- }
- data_reg = ioremap(data->start, resource_len(addr));
- if (data_reg == NULL) {
- retval = -ENOMEM;
- goto err4;
+ data_reg = ioremap(data->start, 1);
+ if (data_reg == NULL) {
+ retval = -ENOMEM;
+ goto err4;
+ }
}
/* allocate and initialize hcd */
@@ -1737,12 +1751,14 @@ sl811h_probe(struct device *dev)
goto err6;
}
- /* sl811s would need a different handler for this irq */
-#ifdef CONFIG_ARM
- /* Cypress docs say the IRQ is IRQT_HIGH ... */
- set_irq_type(irq, IRQT_RISING);
-#endif
- retval = usb_add_hcd(hcd, irq, SA_INTERRUPT);
+ /* The chip's IRQ is level triggered, active high. A requirement
+ * for platform device setup is to cope with things like signal
+ * inverters (e.g. CF is active low) or working only with edge
+ * triggers (e.g. most ARM CPUs). Initial driver stress testing
+ * was on a system with single edge triggering, so most sorts of
+ * triggering arrangement should work.
+ */
+ retval = usb_add_hcd(hcd, irq, SA_INTERRUPT | SA_SHIRQ);
if (retval != 0)
goto err6;
@@ -1752,14 +1768,12 @@ sl811h_probe(struct device *dev)
err6:
usb_put_hcd(hcd);
err5:
- iounmap(data_reg);
+ if (!ioaddr)
+ iounmap(data_reg);
err4:
- release_mem_region(data->start, 1);
- err3:
- iounmap(addr_reg);
+ if (!ioaddr)
+ iounmap(addr_reg);
err2:
- release_mem_region(addr->start, 1);
- err1:
DBG("init error, %d\n", retval);
return retval;
}
@@ -1767,7 +1781,7 @@ sl811h_probe(struct device *dev)
#ifdef CONFIG_PM
/* for this device there's no useful distinction between the controller
- * and its root hub, except that the root hub only gets direct PM calls
+ * and its root hub, except that the root hub only gets direct PM calls
* when CONFIG_USB_SUSPEND is enabled.
*/
@@ -1821,20 +1835,22 @@ sl811h_resume(struct device *dev, u32 phase)
#endif
-static struct device_driver sl811h_driver = {
+/* this driver is exported so sl811_cs can depend on it */
+struct device_driver sl811h_driver = {
.name = (char *) hcd_name,
.bus = &platform_bus_type,
.probe = sl811h_probe,
- .remove = sl811h_remove,
+ .remove = __devexit_p(sl811h_remove),
.suspend = sl811h_suspend,
.resume = sl811h_resume,
};
+EXPORT_SYMBOL(sl811h_driver);
/*-------------------------------------------------------------------------*/
-
-static int __init sl811h_init(void)
+
+static int __init sl811h_init(void)
{
if (usb_disabled())
return -ENODEV;
@@ -1844,8 +1860,8 @@ static int __init sl811h_init(void)
}
module_init(sl811h_init);
-static void __exit sl811h_cleanup(void)
-{
+static void __exit sl811h_cleanup(void)
+{
driver_unregister(&sl811h_driver);
}
module_exit(sl811h_cleanup);
diff --git a/drivers/usb/host/sl811_cs.c b/drivers/usb/host/sl811_cs.c
new file mode 100644
index 00000000000..6e173265095
--- /dev/null
+++ b/drivers/usb/host/sl811_cs.c
@@ -0,0 +1,442 @@
+/*
+ * PCMCIA driver for SL811HS (as found in REX-CFU1U)
+ * Filename: sl811_cs.c
+ * Author: Yukio Yamamoto
+ *
+ * Port to sl811-hcd and 2.6.x by
+ * Botond Botyanszki <boti@rocketmail.com>
+ * Simon Pickering
+ *
+ * Last update: 2005-05-12
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/ioport.h>
+
+#include <pcmcia/version.h>
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/cistpl.h>
+#include <pcmcia/cisreg.h>
+#include <pcmcia/ds.h>
+
+#include <linux/usb_sl811.h>
+
+MODULE_AUTHOR("Botond Botyanszki");
+MODULE_DESCRIPTION("REX-CFU1U PCMCIA driver for 2.6");
+MODULE_LICENSE("GPL");
+
+
+/*====================================================================*/
+/* MACROS */
+/*====================================================================*/
+
+#if defined(DEBUG) || defined(CONFIG_USB_DEBUG) || defined(PCMCIA_DEBUG)
+
+static int pc_debug = 0;
+module_param(pc_debug, int, 0644);
+
+#define DBG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG "sl811_cs: " args)
+
+#else
+#define DBG(n, args...) do{}while(0)
+#endif /* no debugging */
+
+#define INFO(args...) printk(KERN_INFO "sl811_cs: " args)
+
+#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444)
+
+#define CS_CHECK(fn, ret) \
+ do { \
+ last_fn = (fn); \
+ if ((last_ret = (ret)) != 0) \
+ goto cs_failed; \
+ } while (0)
+
+/*====================================================================*/
+/* VARIABLES */
+/*====================================================================*/
+
+static const char driver_name[DEV_NAME_LEN] = "sl811_cs";
+
+static dev_link_t *dev_list = NULL;
+
+static int irq_list[4] = { -1 };
+static int irq_list_count;
+
+module_param_array(irq_list, int, &irq_list_count, 0444);
+
+INT_MODULE_PARM(irq_mask, 0xdeb8);
+
+typedef struct local_info_t {
+ dev_link_t link;
+ dev_node_t node;
+} local_info_t;
+
+/*====================================================================*/
+
+static void release_platform_dev(struct device * dev)
+{
+ DBG(0, "sl811_cs platform_dev release\n");
+ dev->parent = NULL;
+}
+
+static struct sl811_platform_data platform_data = {
+ .potpg = 100,
+ .power = 50, /* == 100mA */
+ // .reset = ... FIXME: invoke CF reset on the card
+};
+
+static struct resource resources[] = {
+ [0] = {
+ .flags = IORESOURCE_IRQ,
+ },
+ [1] = {
+ // .name = "address",
+ .flags = IORESOURCE_IO,
+ },
+ [2] = {
+ // .name = "data",
+ .flags = IORESOURCE_IO,
+ },
+};
+
+extern struct device_driver sl811h_driver;
+
+static struct platform_device platform_dev = {
+ .id = -1,
+ .dev = {
+ .platform_data = &platform_data,
+ .release = release_platform_dev,
+ },
+ .resource = resources,
+ .num_resources = ARRAY_SIZE(resources),
+};
+
+static int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq)
+{
+ if (platform_dev.dev.parent)
+ return -EBUSY;
+ platform_dev.dev.parent = parent;
+
+ /* finish seting up the platform device */
+ resources[0].start = irq;
+
+ resources[1].start = base_addr;
+ resources[1].end = base_addr;
+
+ resources[2].start = base_addr + 1;
+ resources[2].end = base_addr + 1;
+
+ /* The driver core will probe for us. We know sl811-hcd has been
+ * initialized already because of the link order dependency.
+ */
+ platform_dev.name = sl811h_driver.name;
+ return platform_device_register(&platform_dev);
+}
+
+/*====================================================================*/
+
+static void sl811_cs_detach(dev_link_t *link)
+{
+ dev_link_t **linkp;
+
+ DBG(0, "sl811_cs_detach(0x%p)\n", link);
+
+ /* Locate device structure */
+ for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) {
+ if (*linkp == link)
+ break;
+ }
+ if (*linkp == NULL)
+ return;
+
+ /* Break the link with Card Services */
+ if (link->handle)
+ pcmcia_deregister_client(link->handle);
+
+ /* Unlink device structure, and free it */
+ *linkp = link->next;
+ /* This points to the parent local_info_t struct */
+ kfree(link->priv);
+}
+
+static void sl811_cs_release(dev_link_t * link)
+{
+
+ DBG(0, "sl811_cs_release(0x%p)\n", link);
+
+ if (link->open) {
+ DBG(1, "sl811_cs: release postponed, '%s' still open\n",
+ link->dev->dev_name);
+ link->state |= DEV_STALE_CONFIG;
+ return;
+ }
+
+ /* Unlink the device chain */
+ link->dev = NULL;
+
+ platform_device_unregister(&platform_dev);
+ pcmcia_release_configuration(link->handle);
+ if (link->io.NumPorts1)
+ pcmcia_release_io(link->handle, &link->io);
+ if (link->irq.AssignedIRQ)
+ pcmcia_release_irq(link->handle, &link->irq);
+ link->state &= ~DEV_CONFIG;
+
+ if (link->state & DEV_STALE_LINK)
+ sl811_cs_detach(link);
+}
+
+static void sl811_cs_config(dev_link_t *link)
+{
+ client_handle_t handle = link->handle;
+ struct device *parent = &handle_to_dev(handle);
+ local_info_t *dev = link->priv;
+ tuple_t tuple;
+ cisparse_t parse;
+ int last_fn, last_ret;
+ u_char buf[64];
+ config_info_t conf;
+ cistpl_cftable_entry_t dflt = { 0 };
+
+ DBG(0, "sl811_cs_config(0x%p)\n", link);
+
+ tuple.DesiredTuple = CISTPL_CONFIG;
+ tuple.Attributes = 0;
+ tuple.TupleData = buf;
+ tuple.TupleDataMax = sizeof(buf);
+ tuple.TupleOffset = 0;
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
+ CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
+ link->conf.ConfigBase = parse.config.base;
+ link->conf.Present = parse.config.rmask[0];
+
+ /* Configure card */
+ link->state |= DEV_CONFIG;
+
+ /* Look up the current Vcc */
+ CS_CHECK(GetConfigurationInfo,
+ pcmcia_get_configuration_info(handle, &conf));
+ link->conf.Vcc = conf.Vcc;
+
+ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+ CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
+ while (1) {
+ cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
+
+ if (pcmcia_get_tuple_data(handle, &tuple) != 0
+ || pcmcia_parse_tuple(handle, &tuple, &parse)
+ != 0)
+ goto next_entry;
+
+ if (cfg->flags & CISTPL_CFTABLE_DEFAULT) {
+ dflt = *cfg;
+ }
+
+ if (cfg->index == 0)
+ goto next_entry;
+
+ link->conf.ConfigIndex = cfg->index;
+
+ /* Use power settings for Vcc and Vpp if present */
+ /* Note that the CIS values need to be rescaled */
+ if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
+ if (cfg->vcc.param[CISTPL_POWER_VNOM]/10000
+ != conf.Vcc)
+ goto next_entry;
+ } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
+ if (dflt.vcc.param[CISTPL_POWER_VNOM]/10000
+ != conf.Vcc)
+ goto next_entry;
+ }
+
+ if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
+ link->conf.Vpp1 = link->conf.Vpp2 =
+ cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
+ else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
+ link->conf.Vpp1 = link->conf.Vpp2 =
+ dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
+
+ /* we need an interrupt */
+ if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
+ link->conf.Attributes |= CONF_ENABLE_IRQ;
+
+ /* IO window settings */
+ link->io.NumPorts1 = link->io.NumPorts2 = 0;
+ if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
+ cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
+
+ link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
+ link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+ link->io.BasePort1 = io->win[0].base;
+ link->io.NumPorts1 = io->win[0].len;
+
+ if (pcmcia_request_io(link->handle, &link->io) != 0)
+ goto next_entry;
+ }
+ break;
+
+next_entry:
+ if (link->io.NumPorts1)
+ pcmcia_release_io(link->handle, &link->io);
+ last_ret = pcmcia_get_next_tuple(handle, &tuple);
+ }
+
+ /* require an IRQ and two registers */
+ if (!link->io.NumPorts1 || link->io.NumPorts1 < 2)
+ goto cs_failed;
+ if (link->conf.Attributes & CONF_ENABLE_IRQ)
+ CS_CHECK(RequestIRQ,
+ pcmcia_request_irq(link->handle, &link->irq));
+ else
+ goto cs_failed;
+
+ CS_CHECK(RequestConfiguration,
+ pcmcia_request_configuration(link->handle, &link->conf));
+
+ sprintf(dev->node.dev_name, driver_name);
+ dev->node.major = dev->node.minor = 0;
+ link->dev = &dev->node;
+
+ printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
+ dev->node.dev_name, link->conf.ConfigIndex,
+ link->conf.Vcc/10, link->conf.Vcc%10);
+ if (link->conf.Vpp1)
+ printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
+ printk(", irq %d", link->irq.AssignedIRQ);
+ printk(", io 0x%04x-0x%04x", link->io.BasePort1,
+ link->io.BasePort1+link->io.NumPorts1-1);
+ printk("\n");
+
+ link->state &= ~DEV_CONFIG_PENDING;
+
+ if (sl811_hc_init(parent, link->io.BasePort1, link->irq.AssignedIRQ)
+ < 0) {
+cs_failed:
+ printk("sl811_cs_config failed\n");
+ cs_error(link->handle, last_fn, last_ret);
+ sl811_cs_release(link);
+ link->state &= ~DEV_CONFIG_PENDING;
+ }
+}
+
+static int
+sl811_cs_event(event_t event, int priority, event_callback_args_t *args)
+{
+ dev_link_t *link = args->client_data;
+
+ DBG(1, "sl811_cs_event(0x%06x)\n", event);
+
+ switch (event) {
+ case CS_EVENT_CARD_REMOVAL:
+ link->state &= ~DEV_PRESENT;
+ if (link->state & DEV_CONFIG)
+ sl811_cs_release(link);
+ break;
+
+ case CS_EVENT_CARD_INSERTION:
+ link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
+ sl811_cs_config(link);
+ break;
+
+ case CS_EVENT_PM_SUSPEND:
+ link->state |= DEV_SUSPEND;
+ /* Fall through... */
+ case CS_EVENT_RESET_PHYSICAL:
+ if (link->state & DEV_CONFIG)
+ pcmcia_release_configuration(link->handle);
+ break;
+
+ case CS_EVENT_PM_RESUME:
+ link->state &= ~DEV_SUSPEND;
+ /* Fall through... */
+ case CS_EVENT_CARD_RESET:
+ if (link->state & DEV_CONFIG)
+ pcmcia_request_configuration(link->handle, &link->conf);
+ DBG(0, "reset sl811-hcd here?\n");
+ break;
+ }
+ return 0;
+}
+
+static dev_link_t *sl811_cs_attach(void)
+{
+ local_info_t *local;
+ dev_link_t *link;
+ client_reg_t client_reg;
+ int ret, i;
+
+ local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
+ if (!local)
+ return NULL;
+ memset(local, 0, sizeof(local_info_t));
+ link = &local->link;
+ link->priv = local;
+
+ /* Initialize */
+ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+ link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
+ if (irq_list[0] == -1)
+ link->irq.IRQInfo2 = irq_mask;
+ else
+ for (i = 0; i < irq_list_count; i++)
+ link->irq.IRQInfo2 |= 1 << irq_list[i];
+ link->irq.Handler = NULL;
+
+ link->conf.Attributes = 0;
+ link->conf.Vcc = 33;
+ link->conf.IntType = INT_MEMORY_AND_IO;
+
+ /* Register with Card Services */
+ link->next = dev_list;
+ dev_list = link;
+ client_reg.dev_info = (dev_info_t *) &driver_name;
+ client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
+ client_reg.EventMask =
+ CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
+ CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
+ CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
+ client_reg.event_handler = &sl811_cs_event;
+ client_reg.Version = 0x0210;
+ client_reg.event_callback_args.client_data = link;
+ ret = pcmcia_register_client(&link->handle, &client_reg);
+ if (ret != CS_SUCCESS) {
+ cs_error(link->handle, RegisterClient, ret);
+ sl811_cs_detach(link);
+ return NULL;
+ }
+
+ return link;
+}
+
+static struct pcmcia_driver sl811_cs_driver = {
+ .owner = THIS_MODULE,
+ .drv = {
+ .name = (char *)driver_name,
+ },
+ .attach = sl811_cs_attach,
+ .detach = sl811_cs_detach,
+};
+
+/*====================================================================*/
+
+static int __init init_sl811_cs(void)
+{
+ return pcmcia_register_driver(&sl811_cs_driver);
+}
+module_init(init_sl811_cs);
+
+static void __exit exit_sl811_cs(void)
+{
+ pcmcia_unregister_driver(&sl811_cs_driver);
+}
+module_exit(exit_sl811_cs);
diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c
index 94ce2a9ad50..e991f7ed733 100644
--- a/drivers/usb/input/aiptek.c
+++ b/drivers/usb/input/aiptek.c
@@ -1025,7 +1025,7 @@ static int aiptek_program_tablet(struct aiptek *aiptek)
/***********************************************************************
* support the 'size' file -- display support
*/
-static ssize_t show_tabletSize(struct device *dev, char *buf)
+static ssize_t show_tabletSize(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
@@ -1048,7 +1048,7 @@ static DEVICE_ATTR(size, S_IRUGO, show_tabletSize, NULL);
/***********************************************************************
* support routines for the 'product_id' file
*/
-static ssize_t show_tabletProductId(struct device *dev, char *buf)
+static ssize_t show_tabletProductId(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
@@ -1064,7 +1064,7 @@ static DEVICE_ATTR(product_id, S_IRUGO, show_tabletProductId, NULL);
/***********************************************************************
* support routines for the 'vendor_id' file
*/
-static ssize_t show_tabletVendorId(struct device *dev, char *buf)
+static ssize_t show_tabletVendorId(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
@@ -1079,7 +1079,7 @@ static DEVICE_ATTR(vendor_id, S_IRUGO, show_tabletVendorId, NULL);
/***********************************************************************
* support routines for the 'vendor' file
*/
-static ssize_t show_tabletManufacturer(struct device *dev, char *buf)
+static ssize_t show_tabletManufacturer(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
int retval;
@@ -1096,7 +1096,7 @@ static DEVICE_ATTR(vendor, S_IRUGO, show_tabletManufacturer, NULL);
/***********************************************************************
* support routines for the 'product' file
*/
-static ssize_t show_tabletProduct(struct device *dev, char *buf)
+static ssize_t show_tabletProduct(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
int retval;
@@ -1114,7 +1114,7 @@ static DEVICE_ATTR(product, S_IRUGO, show_tabletProduct, NULL);
* support routines for the 'pointer_mode' file. Note that this file
* both displays current setting and allows reprogramming.
*/
-static ssize_t show_tabletPointerMode(struct device *dev, char *buf)
+static ssize_t show_tabletPointerMode(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
char *s;
@@ -1143,7 +1143,7 @@ static ssize_t show_tabletPointerMode(struct device *dev, char *buf)
}
static ssize_t
-store_tabletPointerMode(struct device *dev, const char *buf, size_t count)
+store_tabletPointerMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
if (aiptek == NULL)
@@ -1168,7 +1168,7 @@ static DEVICE_ATTR(pointer_mode,
* support routines for the 'coordinate_mode' file. Note that this file
* both displays current setting and allows reprogramming.
*/
-static ssize_t show_tabletCoordinateMode(struct device *dev, char *buf)
+static ssize_t show_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
char *s;
@@ -1193,7 +1193,7 @@ static ssize_t show_tabletCoordinateMode(struct device *dev, char *buf)
}
static ssize_t
-store_tabletCoordinateMode(struct device *dev, const char *buf, size_t count)
+store_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
if (aiptek == NULL)
@@ -1217,7 +1217,7 @@ static DEVICE_ATTR(coordinate_mode,
* support routines for the 'tool_mode' file. Note that this file
* both displays current setting and allows reprogramming.
*/
-static ssize_t show_tabletToolMode(struct device *dev, char *buf)
+static ssize_t show_tabletToolMode(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
char *s;
@@ -1262,7 +1262,7 @@ static ssize_t show_tabletToolMode(struct device *dev, char *buf)
}
static ssize_t
-store_tabletToolMode(struct device *dev, const char *buf, size_t count)
+store_tabletToolMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
if (aiptek == NULL)
@@ -1295,7 +1295,7 @@ static DEVICE_ATTR(tool_mode,
* support routines for the 'xtilt' file. Note that this file
* both displays current setting and allows reprogramming.
*/
-static ssize_t show_tabletXtilt(struct device *dev, char *buf)
+static ssize_t show_tabletXtilt(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
@@ -1311,7 +1311,7 @@ static ssize_t show_tabletXtilt(struct device *dev, char *buf)
}
static ssize_t
-store_tabletXtilt(struct device *dev, const char *buf, size_t count)
+store_tabletXtilt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
int x;
@@ -1337,7 +1337,7 @@ static DEVICE_ATTR(xtilt,
* support routines for the 'ytilt' file. Note that this file
* both displays current setting and allows reprogramming.
*/
-static ssize_t show_tabletYtilt(struct device *dev, char *buf)
+static ssize_t show_tabletYtilt(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
@@ -1353,7 +1353,7 @@ static ssize_t show_tabletYtilt(struct device *dev, char *buf)
}
static ssize_t
-store_tabletYtilt(struct device *dev, const char *buf, size_t count)
+store_tabletYtilt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
int y;
@@ -1379,7 +1379,7 @@ static DEVICE_ATTR(ytilt,
* support routines for the 'jitter' file. Note that this file
* both displays current setting and allows reprogramming.
*/
-static ssize_t show_tabletJitterDelay(struct device *dev, char *buf)
+static ssize_t show_tabletJitterDelay(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
@@ -1390,7 +1390,7 @@ static ssize_t show_tabletJitterDelay(struct device *dev, char *buf)
}
static ssize_t
-store_tabletJitterDelay(struct device *dev, const char *buf, size_t count)
+store_tabletJitterDelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
@@ -1409,7 +1409,7 @@ static DEVICE_ATTR(jitter,
* support routines for the 'delay' file. Note that this file
* both displays current setting and allows reprogramming.
*/
-static ssize_t show_tabletProgrammableDelay(struct device *dev, char *buf)
+static ssize_t show_tabletProgrammableDelay(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
@@ -1421,7 +1421,7 @@ static ssize_t show_tabletProgrammableDelay(struct device *dev, char *buf)
}
static ssize_t
-store_tabletProgrammableDelay(struct device *dev, const char *buf, size_t count)
+store_tabletProgrammableDelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
@@ -1440,7 +1440,7 @@ static DEVICE_ATTR(delay,
* support routines for the 'input_path' file. Note that this file
* only displays current setting.
*/
-static ssize_t show_tabletInputDevice(struct device *dev, char *buf)
+static ssize_t show_tabletInputDevice(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
@@ -1457,7 +1457,7 @@ static DEVICE_ATTR(input_path, S_IRUGO, show_tabletInputDevice, NULL);
* support routines for the 'event_count' file. Note that this file
* only displays current setting.
*/
-static ssize_t show_tabletEventsReceived(struct device *dev, char *buf)
+static ssize_t show_tabletEventsReceived(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
@@ -1473,7 +1473,7 @@ static DEVICE_ATTR(event_count, S_IRUGO, show_tabletEventsReceived, NULL);
* support routines for the 'diagnostic' file. Note that this file
* only displays current setting.
*/
-static ssize_t show_tabletDiagnosticMessage(struct device *dev, char *buf)
+static ssize_t show_tabletDiagnosticMessage(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
char *retMsg;
@@ -1515,7 +1515,7 @@ static DEVICE_ATTR(diagnostic, S_IRUGO, show_tabletDiagnosticMessage, NULL);
* support routines for the 'stylus_upper' file. Note that this file
* both displays current setting and allows for setting changing.
*/
-static ssize_t show_tabletStylusUpper(struct device *dev, char *buf)
+static ssize_t show_tabletStylusUpper(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
char *s;
@@ -1540,7 +1540,7 @@ static ssize_t show_tabletStylusUpper(struct device *dev, char *buf)
}
static ssize_t
-store_tabletStylusUpper(struct device *dev, const char *buf, size_t count)
+store_tabletStylusUpper(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
@@ -1565,7 +1565,7 @@ static DEVICE_ATTR(stylus_upper,
* support routines for the 'stylus_lower' file. Note that this file
* both displays current setting and allows for setting changing.
*/
-static ssize_t show_tabletStylusLower(struct device *dev, char *buf)
+static ssize_t show_tabletStylusLower(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
char *s;
@@ -1590,7 +1590,7 @@ static ssize_t show_tabletStylusLower(struct device *dev, char *buf)
}
static ssize_t
-store_tabletStylusLower(struct device *dev, const char *buf, size_t count)
+store_tabletStylusLower(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
@@ -1615,7 +1615,7 @@ static DEVICE_ATTR(stylus_lower,
* support routines for the 'mouse_left' file. Note that this file
* both displays current setting and allows for setting changing.
*/
-static ssize_t show_tabletMouseLeft(struct device *dev, char *buf)
+static ssize_t show_tabletMouseLeft(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
char *s;
@@ -1644,7 +1644,7 @@ static ssize_t show_tabletMouseLeft(struct device *dev, char *buf)
}
static ssize_t
-store_tabletMouseLeft(struct device *dev, const char *buf, size_t count)
+store_tabletMouseLeft(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
@@ -1669,7 +1669,7 @@ static DEVICE_ATTR(mouse_left,
* support routines for the 'mouse_middle' file. Note that this file
* both displays current setting and allows for setting changing.
*/
-static ssize_t show_tabletMouseMiddle(struct device *dev, char *buf)
+static ssize_t show_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
char *s;
@@ -1698,7 +1698,7 @@ static ssize_t show_tabletMouseMiddle(struct device *dev, char *buf)
}
static ssize_t
-store_tabletMouseMiddle(struct device *dev, const char *buf, size_t count)
+store_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
@@ -1725,7 +1725,7 @@ static DEVICE_ATTR(mouse_middle,
* support routines for the 'mouse_right' file. Note that this file
* both displays current setting and allows for setting changing.
*/
-static ssize_t show_tabletMouseRight(struct device *dev, char *buf)
+static ssize_t show_tabletMouseRight(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
char *s;
@@ -1754,7 +1754,7 @@ static ssize_t show_tabletMouseRight(struct device *dev, char *buf)
}
static ssize_t
-store_tabletMouseRight(struct device *dev, const char *buf, size_t count)
+store_tabletMouseRight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
@@ -1780,7 +1780,7 @@ static DEVICE_ATTR(mouse_right,
* support routines for the 'wheel' file. Note that this file
* both displays current setting and allows for setting changing.
*/
-static ssize_t show_tabletWheel(struct device *dev, char *buf)
+static ssize_t show_tabletWheel(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
@@ -1796,7 +1796,7 @@ static ssize_t show_tabletWheel(struct device *dev, char *buf)
}
static ssize_t
-store_tabletWheel(struct device *dev, const char *buf, size_t count)
+store_tabletWheel(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
@@ -1814,7 +1814,7 @@ static DEVICE_ATTR(wheel,
* support routines for the 'execute' file. Note that this file
* both displays current setting and allows for setting changing.
*/
-static ssize_t show_tabletExecute(struct device *dev, char *buf)
+static ssize_t show_tabletExecute(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
@@ -1829,7 +1829,7 @@ static ssize_t show_tabletExecute(struct device *dev, char *buf)
}
static ssize_t
-store_tabletExecute(struct device *dev, const char *buf, size_t count)
+store_tabletExecute(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
@@ -1855,7 +1855,7 @@ static DEVICE_ATTR(execute,
* support routines for the 'odm_code' file. Note that this file
* only displays current setting.
*/
-static ssize_t show_tabletODMCode(struct device *dev, char *buf)
+static ssize_t show_tabletODMCode(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
@@ -1871,7 +1871,7 @@ static DEVICE_ATTR(odm_code, S_IRUGO, show_tabletODMCode, NULL);
* support routines for the 'model_code' file. Note that this file
* only displays current setting.
*/
-static ssize_t show_tabletModelCode(struct device *dev, char *buf)
+static ssize_t show_tabletModelCode(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
@@ -1887,7 +1887,7 @@ static DEVICE_ATTR(model_code, S_IRUGO, show_tabletModelCode, NULL);
* support routines for the 'firmware_code' file. Note that this file
* only displays current setting.
*/
-static ssize_t show_firmwareCode(struct device *dev, char *buf)
+static ssize_t show_firmwareCode(struct device *dev, struct device_attribute *attr, char *buf)
{
struct aiptek *aiptek = dev_get_drvdata(dev);
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index 869ff73690a..740dec1f521 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1315,6 +1315,8 @@ void hid_init_reports(struct hid_device *hid)
#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_VENDOR_ID_KBGEAR 0x084e
#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001
@@ -1401,6 +1403,7 @@ void hid_init_reports(struct hid_device *hid)
#define USB_VENDOR_ID_DELORME 0x1163
#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
+#define USB_DEVICE_ID_DELORME_EM_LT20 0x0200
#define USB_VENDOR_ID_MCC 0x09db
#define USB_DEVICE_ID_MCC_PMD1024LS 0x0076
@@ -1412,6 +1415,12 @@ void hid_init_reports(struct hid_device *hid)
#define USB_VENDOR_ID_BTC 0x046e
#define USB_DEVICE_ID_BTC_KEYBOARD 0x5303
+#define USB_VENDOR_ID_VERNIER 0x08f7
+#define USB_DEVICE_ID_VERNIER_LABPRO 0x0001
+#define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002
+#define USB_DEVICE_ID_VERNIER_SKIP 0x0003
+#define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004
+
/*
* Alphabetically sorted blacklist by quirk type.
@@ -1437,6 +1446,7 @@ static struct hid_blacklist {
{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
@@ -1456,6 +1466,10 @@ static struct hid_blacklist {
{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500, HID_QUIRK_IGNORE },
+ { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO, HID_QUIRK_IGNORE },
+ { 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 },
@@ -1481,6 +1495,10 @@ static struct hid_blacklist {
{ 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_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_CINTIQ, 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 },
@@ -1744,7 +1762,7 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
intf->altsetting->desc.bInterfaceNumber);
if (!(hid = usb_hid_configure(intf)))
- return -EIO;
+ return -ENODEV;
hid_init_reports(hid);
hid_dump_device(hid);
@@ -1759,7 +1777,7 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
if (!hid->claimed) {
printk ("HID device not claimed by input or hiddev\n");
hid_disconnect(intf);
- return -EIO;
+ return -ENODEV;
}
printk(KERN_INFO);
diff --git a/drivers/usb/media/pwc/ChangeLog b/drivers/usb/media/pwc/ChangeLog
deleted file mode 100644
index b2eb71a9afb..00000000000
--- a/drivers/usb/media/pwc/ChangeLog
+++ /dev/null
@@ -1,143 +0,0 @@
-9.0.2
-
-* Adding #ifdef to compile PWC before and after 2.6.5
-
-9.0.1
-
-9.0
-
-
-8.12
-
-* Implement motorized pan/tilt feature for Logitech QuickCam Orbit/Spere.
-
-8.11.1
-
-* Fix for PCVC720/40, would not be able to set videomode
-* Fix for Samsung MPC models, appearantly they are based on a newer chipset
-
-8.11
-
-* 20 dev_hints (per request)
-* Hot unplugging should be better, no more dangling pointers or memory leaks
-* Added reserved Logitech webcam IDs
-* Device now remembers size & fps between close()/open()
-* Removed palette stuff altogether
-
-8.10.1
-
-* Added IDs for PCVC720K/40 and Creative Labs Webcam Pro
-
-8.10
-
-* Fixed ID for QuickCam Notebook pro
-* Added GREALSIZE ioctl() call
-* Fixed bug in case PWCX was not loaded and invalid size was set
-
-8.9
-
-* Merging with kernel 2.5.49
-* Adding IDs for QuickCam Zoom & QuickCam Notebook
-
-8.8
-
-* Fixing 'leds' parameter
-* Adding IDs for Logitech QuickCam Pro 4000
-* Making URB init/cleanup a little nicer
-
-8.7
-
-* Incorporating changes in ioctl() parameter passing
-* Also changes to URB mechanism
-
-8.6
-
-* Added ID's for Visionite VCS UM100 and UC300
-* Removed YUV420-interlaced palette altogether (was confusing)
-* Removed MIRROR stuff as it didn't work anyway
-* Fixed a problem with the 'leds' parameter (wouldn't blink)
-* Added ioctl()s for advanced features: 'extended' whitebalance ioctl()s,
- CONTOUR, BACKLIGHT, FLICKER, DYNNOISE.
-* VIDIOCGCAP.name now contains real camera model name instead of
- 'Philips xxx webcam'
-* Added PROBE ioctl (see previous point & API doc)
-
-8.5
-
-* Adding IDs for Creative Labs Webcam 5
-* Adding IDs for SOTEC CMS-001 webcam
-* Solving possible hang in VIDIOCSYNC when unplugging the cam
-* Forgot to return structure in VIDIOCPWCGAWB, oops
-* Time interval for the LEDs are now in milliseconds
-
-8.4
-
-* Fixing power_save option for Vesta range
-* Handling new error codes in ISOC callback
-* Adding dev_hint module parameter, to specify /dev/videoX device nodes
-
-8.3
-
-* Adding Samsung C10 and C30 cameras
-* Removing palette module parameter
-* Fixed typo in ID of QuickCam 3000 Pro
-* Adding LED settings (blinking while in use) for ToUCam cameras.
-* Turns LED off when camera is not in use.
-
-8.2
-
-* Making module more silent when trace = 0
-* Adding QuickCam 3000 Pro IDs
-* Chrominance control for the Vesta cameras
-* Hopefully fixed problems on machines with BIGMEM and > 1GB of RAM
-* Included Oliver Neukem's lock_kernel() patch
-* Allocates less memory for image buffers
-* Adds ioctl()s for the whitebalancing
-
-8.1
-
-* Adding support for 750
-* Adding V4L GAUDIO/SAUDIO/UNIT ioctl() calls
-
-8.0
-* 'damage control' after inclusion in 2.4.5.
-* Changed wait-queue mechanism in read/mmap/poll according to the book.
-* Included YUV420P palette.
-* Changed interface to decompressor module.
-* Cleaned up pwc structure a bit.
-
-7.0
-
-* Fixed bug in vcvt_420i_yuyv; extra variables on stack were misaligned.
-* There is now a clear error message when an image size is selected that
- is only supported using the decompressor, and the decompressor isn't
- loaded.
-* When the decompressor wasn't loaded, selecting large image size
- would create skewed or double images.
-
-6.3
-
-* Introduced spinlocks for the buffer pointer manipulation; a number of
- reports seem to suggest the down()/up() semaphores were the cause of
- lockups, since they are not suitable for interrupt/user locking.
-* Separated decompressor and core code into 2 modules.
-
-6.2
-
-* Non-integral image sizes are now padded with gray or black.
-* Added SHUTTERSPEED ioctl().
-* Fixed buglet in VIDIOCPWCSAGC; the function would always return an error,
- even though the call succeeded.
-* Added hotplug support for 2.4.*.
-* Memory: the 645/646 uses less memory now.
-
-6.1
-
-* VIDIOCSPICT returns -EINVAL with invalid palettes.
-* Added saturation control.
-* Split decompressors from rest.
-* Fixed bug that would reset the framerate to the default framerate if
- the rate field was set to 0 (which is not what I intended, nl. do not
- change the framerate!).
-* VIDIOCPWCSCQUAL (setting compression quality) now takes effect immediately.
-* Workaround for a bug in the 730 sensor.
diff --git a/drivers/usb/media/pwc/Makefile b/drivers/usb/media/pwc/Makefile
index e0b41ed4407..2d93a775011 100644
--- a/drivers/usb/media/pwc/Makefile
+++ b/drivers/usb/media/pwc/Makefile
@@ -1,6 +1,6 @@
ifneq ($(KERNELRELEASE),)
-pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o pwc-dec1.o pwc-dec23.o pwc-kiara.o pwc-timon.o
+pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o pwc-timon.o pwc-kiara.o
obj-$(CONFIG_USB_PWC) += pwc.o
diff --git a/drivers/usb/media/pwc/pwc-ctrl.c b/drivers/usb/media/pwc/pwc-ctrl.c
index 42ec468d52d..53099190952 100644
--- a/drivers/usb/media/pwc/pwc-ctrl.c
+++ b/drivers/usb/media/pwc/pwc-ctrl.c
@@ -48,8 +48,6 @@
#include "pwc-uncompress.h"
#include "pwc-kiara.h"
#include "pwc-timon.h"
-#include "pwc-dec1.h"
-#include "pwc-dec23.h"
/* Request types: video */
#define SET_LUM_CTL 0x01
@@ -246,7 +244,7 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra
switch(pdev->type) {
case 645:
case 646:
- pwc_dec1_init(pdev->type, pdev->release, buf, pdev->decompress_data);
+/* pwc_dec1_init(pdev->type, pdev->release, buf, pdev->decompress_data); */
break;
case 675:
@@ -256,7 +254,7 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra
case 730:
case 740:
case 750:
- pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data);
+/* pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */
break;
}
}
@@ -318,8 +316,8 @@ static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int fr
if (ret < 0)
return ret;
- if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
- pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data);
+/* if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
+ pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */
pdev->cmd_len = 13;
memcpy(pdev->cmd_buf, buf, 13);
@@ -397,8 +395,8 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr
if (ret < 0)
return ret;
- if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
- pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data);
+/* if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
+ pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data); */
pdev->cmd_len = 12;
memcpy(pdev->cmd_buf, buf, 12);
diff --git a/drivers/usb/media/pwc/pwc-dec1.c b/drivers/usb/media/pwc/pwc-dec1.c
deleted file mode 100644
index 57d03d9178f..00000000000
--- a/drivers/usb/media/pwc/pwc-dec1.c
+++ /dev/null
@@ -1,42 +0,0 @@
-/* Linux driver for Philips webcam
- Decompression for chipset version 1
- (C) 2004 Luc Saillard (luc@saillard.org)
-
- NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
- driver and thus may have bugs that are not present in the original version.
- Please send bug reports and support requests to <luc@saillard.org>.
- The decompression routines have been implemented by reverse-engineering the
- Nemosoft binary pwcx module. Caveat emptor.
-
- 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 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 "pwc-dec1.h"
-
-
-void pwc_dec1_init(int type, int release, void *buffer, void *table)
-{
-
-}
-
-void pwc_dec1_exit(void)
-{
-
-
-
-}
-
diff --git a/drivers/usb/media/pwc/pwc-dec1.h b/drivers/usb/media/pwc/pwc-dec1.h
deleted file mode 100644
index a7ffd9c45a2..00000000000
--- a/drivers/usb/media/pwc/pwc-dec1.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Linux driver for Philips webcam
- (C) 2004 Luc Saillard (luc@saillard.org)
-
- NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
- driver and thus may have bugs that are not present in the original version.
- Please send bug reports and support requests to <luc@saillard.org>.
- The decompression routines have been implemented by reverse-engineering the
- Nemosoft binary pwcx module. Caveat emptor.
-
- 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 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
-*/
-
-
-
-#ifndef PWC_DEC1_H
-#define PWC_DEC1_H
-
-void pwc_dec1_init(int type, int release, void *buffer, void *private_data);
-void pwc_dec1_exit(void);
-
-#endif
-
-
-
diff --git a/drivers/usb/media/pwc/pwc-dec23.c b/drivers/usb/media/pwc/pwc-dec23.c
deleted file mode 100644
index 98fa3f7a9ef..00000000000
--- a/drivers/usb/media/pwc/pwc-dec23.c
+++ /dev/null
@@ -1,623 +0,0 @@
-/* Linux driver for Philips webcam
- Decompression for chipset version 2 et 3
- (C) 2004 Luc Saillard (luc@saillard.org)
-
- NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
- driver and thus may have bugs that are not present in the original version.
- Please send bug reports and support requests to <luc@saillard.org>.
- The decompression routines have been implemented by reverse-engineering the
- Nemosoft binary pwcx module. Caveat emptor.
-
- 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 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 "pwc-timon.h"
-#include "pwc-kiara.h"
-#include "pwc-dec23.h"
-#include "pwc-ioctl.h"
-
-#include <linux/string.h>
-
-/****
- *
- *
- *
- */
-
-
-static void fill_table_a000(unsigned int *p)
-{
- static unsigned int initial_values[12] = {
- 0xFFAD9B00, 0xFFDDEE00, 0x00221200, 0x00526500,
- 0xFFC21E00, 0x003DE200, 0xFF924B80, 0xFFD2A300,
- 0x002D5D00, 0x006DB480, 0xFFED3E00, 0x0012C200
- };
- static unsigned int values_derivated[12] = {
- 0x0000A4CA, 0x00004424, 0xFFFFBBDC, 0xFFFF5B36,
- 0x00007BC4, 0xFFFF843C, 0x0000DB69, 0x00005ABA,
- 0xFFFFA546, 0xFFFF2497, 0x00002584, 0xFFFFDA7C
- };
- unsigned int temp_values[12];
- int i,j;
-
- memcpy(temp_values,initial_values,sizeof(initial_values));
- for (i=0;i<256;i++)
- {
- for (j=0;j<12;j++)
- {
- *p++ = temp_values[j];
- temp_values[j] += values_derivated[j];
- }
- }
-}
-
-static void fill_table_d000(unsigned char *p)
-{
- int bit,byte;
-
- for (bit=0; bit<8; bit++)
- {
- unsigned char bitpower = 1<<bit;
- unsigned char mask = bitpower-1;
- for (byte=0; byte<256; byte++)
- {
- if (byte & bitpower)
- *p++ = -(byte & mask);
- else
- *p++ = (byte & mask);
- }
- }
-}
-
-/*
- *
- * Kiara: 0 <= ver <= 7
- * Timon: 0 <= ver <= 15
- *
- */
-static void fill_table_color(unsigned int version, const unsigned int *romtable,
- unsigned char *p0004,
- unsigned char *p8004)
-{
- const unsigned int *table;
- unsigned char *p0, *p8;
- int i,j,k;
- int dl,bit,pw;
-
- romtable += version*256;
-
- for (i=0; i<2; i++)
- {
- table = romtable + i*128;
-
- for (dl=0; dl<16; dl++)
- {
- p0 = p0004 + (i<<14) + (dl<<10);
- p8 = p8004 + (i<<12) + (dl<<8);
-
- for (j=0; j<8; j++ , table++, p0+=128)
- {
- for (k=0; k<16; k++)
- {
- if (k==0)
- bit=1;
- else if (k>=1 && k<3)
- bit=(table[0]>>15)&7;
- else if (k>=3 && k<6)
- bit=(table[0]>>12)&7;
- else if (k>=6 && k<10)
- bit=(table[0]>>9)&7;
- else if (k>=10 && k<13)
- bit=(table[0]>>6)&7;
- else if (k>=13 && k<15)
- bit=(table[0]>>3)&7;
- else
- bit=(table[0])&7;
- if (k == 0)
- *(unsigned char *)p8++ = 8;
- else
- *(unsigned char *)p8++ = j - bit;
- *(unsigned char *)p8++ = bit;
-
- pw = 1<<bit;
- p0[k+0x00] = (1*pw) + 0x80;
- p0[k+0x10] = (2*pw) + 0x80;
- p0[k+0x20] = (3*pw) + 0x80;
- p0[k+0x30] = (4*pw) + 0x80;
- p0[k+0x40] = (-pw) + 0x80;
- p0[k+0x50] = (2*-pw) + 0x80;
- p0[k+0x60] = (3*-pw) + 0x80;
- p0[k+0x70] = (4*-pw) + 0x80;
- } /* end of for (k=0; k<16; k++, p8++) */
- } /* end of for (j=0; j<8; j++ , table++) */
- } /* end of for (dl=0; dl<16; dl++) */
- } /* end of for (i=0; i<2; i++) */
-}
-
-/*
- * precision = (pdev->xx + pdev->yy)
- *
- */
-static void fill_table_dc00_d800(unsigned int precision, unsigned int *pdc00, unsigned int *pd800)
-{
- int i;
- unsigned int offset1, offset2;
-
- for(i=0,offset1=0x4000, offset2=0; i<256 ; i++,offset1+=0x7BC4, offset2+=0x7BC4)
- {
- unsigned int msb = offset1 >> 15;
-
- if ( msb > 255)
- {
- if (msb)
- msb=0;
- else
- msb=255;
- }
-
- *pdc00++ = msb << precision;
- *pd800++ = offset2;
- }
-
-}
-
-/*
- * struct {
- * unsigned char op; // operation to execute
- * unsigned char bits; // bits use to perform operation
- * unsigned char offset1; // offset to add to access in the table_0004 % 16
- * unsigned char offset2; // offset to add to access in the table_0004
- * }
- *
- */
-static unsigned int table_ops[] = {
-0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x10, 0x00,0x06,0x01,0x30,
-0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x01,0x20, 0x01,0x00,0x00,0x00,
-0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x50, 0x00,0x05,0x02,0x00,
-0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x03,0x00, 0x01,0x00,0x00,0x00,
-0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x10, 0x00,0x06,0x02,0x10,
-0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x01,0x60, 0x01,0x00,0x00,0x00,
-0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x50, 0x00,0x05,0x02,0x40,
-0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x03,0x40, 0x01,0x00,0x00,0x00,
-0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x10, 0x00,0x06,0x01,0x70,
-0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x01,0x20, 0x01,0x00,0x00,0x00,
-0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x50, 0x00,0x05,0x02,0x00,
-0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x03,0x00, 0x01,0x00,0x00,0x00,
-0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x10, 0x00,0x06,0x02,0x50,
-0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x01,0x60, 0x01,0x00,0x00,0x00,
-0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x50, 0x00,0x05,0x02,0x40,
-0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x03,0x40, 0x01,0x00,0x00,0x00
-};
-
-/*
- * TODO: multiply by 4 all values
- *
- */
-static unsigned int MulIdx[256] = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
- 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
- 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,
- 6, 7, 8, 9, 7,10,11, 8, 8,11,10, 7, 9, 8, 7, 6,
- 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4,
- 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2,
- 0, 3, 3, 0, 1, 2, 2, 1, 2, 1, 1, 2, 3, 0, 0, 3,
- 0, 1, 2, 3, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 2, 3,
- 1, 1, 1, 1, 3, 3, 3, 3, 0, 0, 0, 0, 2, 2, 2, 2,
- 7,10,11, 8, 9, 8, 7, 6, 6, 7, 8, 9, 8,11,10, 7,
- 4, 5, 5, 4, 5, 4, 4, 5, 5, 4, 4, 5, 4, 5, 5, 4,
- 7, 9, 6, 8,10, 8, 7,11,11, 7, 8,10, 8, 6, 9, 7,
- 1, 3, 0, 2, 2, 0, 3, 1, 2, 0, 3, 1, 1, 3, 0, 2,
- 1, 2, 2, 1, 3, 0, 0, 3, 0, 3, 3, 0, 2, 1, 1, 2,
-10, 8, 7,11, 8, 6, 9, 7, 7, 9, 6, 8,11, 7, 8,10
-};
-
-
-
-void pwc_dec23_init(int type, int release, unsigned char *mode, void *data)
-{
- int flags;
- struct pwc_dec23_private *pdev = data;
- release = release;
-
- switch (type)
- {
- case 720:
- case 730:
- case 740:
- case 750:
- flags = mode[2]&0x18; /* our: flags = 8, mode[2]==e8 */
- if (flags==8)
- pdev->zz = 7;
- else if (flags==0x10)
- pdev->zz = 8;
- else
- pdev->zz = 6;
- flags = mode[2]>>5; /* our: 7 */
-
- fill_table_color(flags, (unsigned int *)KiaraRomTable, pdev->table_0004, pdev->table_8004);
- break;
-
-
- case 675:
- case 680:
- case 690:
- flags = mode[2]&6;
- if (flags==2)
- pdev->zz = 7;
- else if (flags==4)
- pdev->zz = 8;
- else
- pdev->zz = 6;
- flags = mode[2]>>3;
-
- fill_table_color(flags, (unsigned int *)TimonRomTable, pdev->table_0004, pdev->table_8004);
- break;
-
- default:
- /* Not supported */
- return;
- }
-
- /* * * * ** */
- pdev->xx = 8 - pdev->zz;
- pdev->yy = 15 - pdev->xx;
- pdev->zzmask = 0xFF>>pdev->xx;
- //pdev->zzmask = (1U<<pdev->zz)-1;
-
-
- fill_table_dc00_d800(pdev->xx + pdev->yy, pdev->table_dc00, pdev->table_d800);
- fill_table_a000(pdev->table_a004);
- fill_table_d000(pdev->table_d004);
-}
-
-
-/*
- * To manage the stream, we keep in a 32 bits variables,
- * the next bits in the stream. fill_reservoir() add to
- * the reservoir at least wanted nbits.
- *
- *
- */
-#define fill_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted) do { \
- while (nbits_in_reservoir<nbits_wanted) \
- { \
- reservoir |= (*(stream)++) << nbits_in_reservoir; \
- nbits_in_reservoir+=8; \
- } \
-} while(0);
-
-#define get_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted,result) do { \
- fill_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted); \
- result = (reservoir) & ((1U<<nbits_wanted)-1); \
- reservoir >>= nbits_wanted; \
- nbits_in_reservoir -= nbits_wanted; \
-} while(0);
-
-
-
-static void DecompressBand23(const struct pwc_dec23_private *pdev,
- const unsigned char *rawyuv,
- unsigned char *planar_y,
- unsigned char *planar_u,
- unsigned char *planar_v,
- unsigned int image_x, /* aka number of pixels wanted ??? */
- unsigned int pixels_per_line, /* aka number of pixels per line */
- int flags)
-{
-
-
- unsigned int reservoir, nbits_in_reservoir;
- int first_4_bits;
- unsigned int bytes_per_channel;
- int line_size; /* size of the line (4Y+U+V) */
- int passes;
- const unsigned char *ptable0004, *ptable8004;
-
- int even_line;
- unsigned int temp_colors[16];
- int nblocks;
-
- const unsigned char *stream;
- unsigned char *dest_y, *dest_u=NULL, *dest_v=NULL;
- unsigned int offset_to_plane_u, offset_to_plane_v;
-
- int i;
-
-
- reservoir = 0;
- nbits_in_reservoir = 0;
- stream = rawyuv+1; /* The first byte of the stream is skipped */
- even_line = 1;
-
- get_nbits(reservoir,nbits_in_reservoir,stream,4,first_4_bits);
-
- line_size = pixels_per_line*3;
-
- for (passes=0;passes<2;passes++)
- {
- if (passes==0)
- {
- bytes_per_channel = pixels_per_line;
- dest_y = planar_y;
- nblocks = image_x/4;
- }
- else
- {
- /* Format planar: All Y, then all U, then all V */
- bytes_per_channel = pixels_per_line/2;
- dest_u = planar_u;
- dest_v = planar_v;
- dest_y = dest_u;
- nblocks = image_x/8;
- }
-
- offset_to_plane_u = bytes_per_channel*2;
- offset_to_plane_v = bytes_per_channel*3;
- /*
- printf("bytes_per_channel = %d\n",bytes_per_channel);
- printf("offset_to_plane_u = %d\n",offset_to_plane_u);
- printf("offset_to_plane_v = %d\n",offset_to_plane_v);
- */
-
- while (nblocks-->0)
- {
- unsigned int gray_index;
-
- fill_nbits(reservoir,nbits_in_reservoir,stream,16);
- gray_index = reservoir & pdev->zzmask;
- reservoir >>= pdev->zz;
- nbits_in_reservoir -= pdev->zz;
-
- fill_nbits(reservoir,nbits_in_reservoir,stream,2);
-
- if ( (reservoir & 3) == 0)
- {
- reservoir>>=2;
- nbits_in_reservoir-=2;
- for (i=0;i<16;i++)
- temp_colors[i] = pdev->table_dc00[gray_index];
-
- }
- else
- {
- unsigned int channel_v, offset1;
-
- /* swap bit 0 and 2 of offset_OR */
- channel_v = ((reservoir & 1) << 2) | (reservoir & 2) | ((reservoir & 4)>>2);
- reservoir>>=3;
- nbits_in_reservoir-=3;
-
- for (i=0;i<16;i++)
- temp_colors[i] = pdev->table_d800[gray_index];
-
- ptable0004 = pdev->table_0004 + (passes*16384) + (first_4_bits*1024) + (channel_v*128);
- ptable8004 = pdev->table_8004 + (passes*4096) + (first_4_bits*256) + (channel_v*32);
-
- offset1 = 0;
- while(1)
- {
- unsigned int index_in_table_ops, op, rows=0;
- fill_nbits(reservoir,nbits_in_reservoir,stream,16);
-
- /* mode is 0,1 or 2 */
- index_in_table_ops = (reservoir&0x3F);
- op = table_ops[ index_in_table_ops*4 ];
- if (op == 2)
- {
- reservoir >>= 2;
- nbits_in_reservoir -= 2;
- break; /* exit the while(1) */
- }
- if (op == 0)
- {
- unsigned int shift;
-
- offset1 = (offset1 + table_ops[index_in_table_ops*4+2]) & 0x0F;
- shift = table_ops[ index_in_table_ops*4+1 ];
- reservoir >>= shift;
- nbits_in_reservoir -= shift;
- rows = ptable0004[ offset1 + table_ops[index_in_table_ops*4+3] ];
- }
- if (op == 1)
- {
- /* 10bits [ xxxx xxxx yyyy 000 ]
- * yyy => offset in the table8004
- * xxx => offset in the tabled004
- */
- unsigned int mask, shift;
- unsigned int col1, row1, total_bits;
-
- offset1 = (offset1 + ((reservoir>>3)&0x0F)+1) & 0x0F;
-
- col1 = (reservoir>>7) & 0xFF;
- row1 = ptable8004 [ offset1*2 ];
-
- /* Bit mask table */
- mask = pdev->table_d004[ (row1<<8) + col1 ];
- shift = ptable8004 [ offset1*2 + 1];
- rows = ((mask << shift) + 0x80) & 0xFF;
-
- total_bits = row1 + 8;
- reservoir >>= total_bits;
- nbits_in_reservoir -= total_bits;
- }
- {
- const unsigned int *table_a004 = pdev->table_a004 + rows*12;
- unsigned int *poffset = MulIdx + offset1*16; /* 64/4 (int) */
- for (i=0;i<16;i++)
- {
- temp_colors[i] += table_a004[ *poffset ];
- poffset++;
- }
- }
- }
- }
-#define USE_SIGNED_INT_FOR_COLOR
-#ifdef USE_SIGNED_INT_FOR_COLOR
-# define CLAMP(x) ((x)>255?255:((x)<0?0:x))
-#else
-# define CLAMP(x) ((x)>255?255:x)
-#endif
-
- if (passes == 0)
- {
-#ifdef USE_SIGNED_INT_FOR_COLOR
- const int *c = temp_colors;
-#else
- const unsigned int *c = temp_colors;
-#endif
- unsigned char *d;
-
- d = dest_y;
- for (i=0;i<4;i++,c++)
- *d++ = CLAMP((*c) >> pdev->yy);
-
- d = dest_y + bytes_per_channel;
- for (i=0;i<4;i++,c++)
- *d++ = CLAMP((*c) >> pdev->yy);
-
- d = dest_y + offset_to_plane_u;
- for (i=0;i<4;i++,c++)
- *d++ = CLAMP((*c) >> pdev->yy);
-
- d = dest_y + offset_to_plane_v;
- for (i=0;i<4;i++,c++)
- *d++ = CLAMP((*c) >> pdev->yy);
-
- dest_y += 4;
- }
- else if (passes == 1)
- {
-#ifdef USE_SIGNED_INT_FOR_COLOR
- int *c1 = temp_colors;
- int *c2 = temp_colors+4;
-#else
- unsigned int *c1 = temp_colors;
- unsigned int *c2 = temp_colors+4;
-#endif
- unsigned char *d;
-
- d = dest_y;
- for (i=0;i<4;i++,c1++,c2++)
- {
- *d++ = CLAMP((*c1) >> pdev->yy);
- *d++ = CLAMP((*c2) >> pdev->yy);
- }
- c1 = temp_colors+12;
- //c2 = temp_colors+8;
- d = dest_y + bytes_per_channel;
- for (i=0;i<4;i++,c1++,c2++)
- {
- *d++ = CLAMP((*c1) >> pdev->yy);
- *d++ = CLAMP((*c2) >> pdev->yy);
- }
-
- if (even_line) /* Each line, swap u/v */
- {
- even_line=0;
- dest_y = dest_v;
- dest_u += 8;
- }
- else
- {
- even_line=1;
- dest_y = dest_u;
- dest_v += 8;
- }
- }
-
- } /* end of while (nblocks-->0) */
-
- } /* end of for (passes=0;passes<2;passes++) */
-
-}
-
-
-/**
- *
- * image: size of the image wanted
- * view : size of the image returned by the camera
- * offset: (x,y) to displayer image in the view
- *
- * src: raw data
- * dst: image output
- * flags: PWCX_FLAG_PLANAR
- * pdev: private buffer
- * bandlength:
- *
- */
-void pwc_dec23_decompress(const struct pwc_coord *image,
- const struct pwc_coord *view,
- const struct pwc_coord *offset,
- const void *src,
- void *dst,
- int flags,
- const void *data,
- int bandlength)
-{
- const struct pwc_dec23_private *pdev = data;
- unsigned char *pout, *pout_planar_y=NULL, *pout_planar_u=NULL, *pout_planar_v=NULL;
- int i,n,stride,pixel_size;
-
-
- if (flags & PWCX_FLAG_BAYER)
- {
- pout = dst + (view->x * offset->y) + offset->x;
- pixel_size = view->x * 4;
- }
- else
- {
- n = view->x * view->y;
-
- /* offset in Y plane */
- stride = view->x * offset->y;
- pout_planar_y = dst + stride + offset->x;
-
- /* offsets in U/V planes */
- stride = (view->x * offset->y)/4 + offset->x/2;
- pout_planar_u = dst + n + + stride;
- pout_planar_v = dst + n + n/4 + stride;
-
- pixel_size = view->x * 4;
- }
-
-
- for (i=0;i<image->y;i+=4)
- {
- if (flags & PWCX_FLAG_BAYER)
- {
- //TODO:
- //DecompressBandBayer(pdev,src,pout,image.x,view->x,flags);
- src += bandlength;
- pout += pixel_size;
- }
- else
- {
- DecompressBand23(pdev,src,pout_planar_y,pout_planar_u,pout_planar_v,image->x,view->x,flags);
- src += bandlength;
- pout_planar_y += pixel_size;
- pout_planar_u += view->x;
- pout_planar_v += view->x;
- }
- }
-}
-
-void pwc_dec23_exit(void)
-{
- /* Do nothing */
-
-}
-
diff --git a/drivers/usb/media/pwc/pwc-dec23.h b/drivers/usb/media/pwc/pwc-dec23.h
deleted file mode 100644
index 5b2aacdefa6..00000000000
--- a/drivers/usb/media/pwc/pwc-dec23.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* Linux driver for Philips webcam
- (C) 2004 Luc Saillard (luc@saillard.org)
-
- NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
- driver and thus may have bugs that are not present in the original version.
- Please send bug reports and support requests to <luc@saillard.org>.
- The decompression routines have been implemented by reverse-engineering the
- Nemosoft binary pwcx module. Caveat emptor.
-
- 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 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
-*/
-
-#ifndef PWC_DEC23_H
-#define PWC_DEC23_H
-
-struct pwc_dec23_private
-{
- unsigned char xx,yy,zz,zzmask;
-
- unsigned char table_0004[2*0x4000];
- unsigned char table_8004[2*0x1000];
- unsigned int table_a004[256*12];
-
- unsigned char table_d004[8*256];
- unsigned int table_d800[256];
- unsigned int table_dc00[256];
-};
-
-
-void pwc_dec23_init(int type, int release, unsigned char *buffer, void *private_data);
-void pwc_dec23_exit(void);
-void pwc_dec23_decompress(const struct pwc_coord *image,
- const struct pwc_coord *view,
- const struct pwc_coord *offset,
- const void *src,
- void *dst,
- int flags,
- const void *data,
- int bandlength);
-
-
-
-#endif
-
-
-
diff --git a/drivers/usb/media/pwc/pwc-if.c b/drivers/usb/media/pwc/pwc-if.c
index cca47f480a8..b77e65c0365 100644
--- a/drivers/usb/media/pwc/pwc-if.c
+++ b/drivers/usb/media/pwc/pwc-if.c
@@ -68,8 +68,6 @@
#include "pwc-ioctl.h"
#include "pwc-kiara.h"
#include "pwc-timon.h"
-#include "pwc-dec23.h"
-#include "pwc-dec1.h"
#include "pwc-uncompress.h"
/* Function prototypes and driver templates */
@@ -322,6 +320,7 @@ static int pwc_allocate_buffers(struct pwc_device *pdev)
case 730:
case 740:
case 750:
+#if 0
Trace(TRACE_MEMORY,"private_data(%zu)\n",sizeof(struct pwc_dec23_private));
kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL); /* Timon & Kiara */
break;
@@ -330,11 +329,9 @@ static int pwc_allocate_buffers(struct pwc_device *pdev)
/* TODO & FIXME */
kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);
break;
+#endif
+ ;
}
- if (kbuf == NULL) {
- Err("Failed to allocate decompress table.\n");
- return -ENOMEM;
- }
pdev->decompress_data = kbuf;
/* Allocate image buffer; double buffer for mmap() */
@@ -1131,11 +1128,11 @@ static int pwc_video_close(struct inode *inode, struct file *file)
case 730:
case 740:
case 750:
- pwc_dec23_exit(); /* Timon & Kiara */
+/* pwc_dec23_exit(); *//* Timon & Kiara */
break;
case 645:
case 646:
- pwc_dec1_exit();
+/* pwc_dec1_exit(); */
break;
}
diff --git a/drivers/usb/media/pwc/pwc-kiara.c b/drivers/usb/media/pwc/pwc-kiara.c
index 5485800efd8..c498c68bace 100644
--- a/drivers/usb/media/pwc/pwc-kiara.c
+++ b/drivers/usb/media/pwc/pwc-kiara.c
@@ -316,576 +316,3 @@ const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] =
},
};
-
-/*
- * Rom table for kiara chips
- *
- * 32 roms tables (one for each resolution ?)
- * 2 tables per roms (one for each passes) (Y, and U&V)
- * 128 bytes per passes
- */
-
-const unsigned int KiaraRomTable [8][2][16][8] =
-{
- { /* version 0 */
- { /* version 0, passes 0 */
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000001,0x00000001},
- {0x00000000,0x00000000,0x00000009,0x00000009,
- 0x00000009,0x00000009,0x00000009,0x00000009},
- {0x00000000,0x00000000,0x00000009,0x00000049,
- 0x00000049,0x00000049,0x00000049,0x00000049},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000249,0x0000024a,0x00000049},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000249,0x00000249,0x0000024a,0x0000024a},
- {0x00000000,0x00000000,0x00000049,0x00000249,
- 0x00000249,0x0000124a,0x0000024a,0x0000024a},
- {0x00000000,0x00000000,0x00000049,0x00000249,
- 0x0000124a,0x00009252,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00009252,0x00009292,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x00000249,0x00001249,
- 0x00009292,0x00009292,0x00009493,0x000124db},
- {0x00000000,0x00000000,0x00000249,0x0000924a,
- 0x00009492,0x0000a49b,0x0000a49b,0x000124db},
- {0x00000000,0x00000000,0x00001249,0x00009252,
- 0x0000a493,0x000124db,0x000124db,0x000126dc},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x000124db,0x000126dc,0x000136e4,0x000126dc},
- {0x00000000,0x00000000,0x00009292,0x0000a49b,
- 0x000124db,0x000136e4,0x000136e4,0x000136e4},
- {0x00000000,0x00000000,0x00009292,0x0000a49b,
- 0x000126dc,0x0001b724,0x0001b92d,0x0001b925},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x000136e4,0x0001b925,0x0001c96e,0x0001c92d},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- },
- { /* version 0, passes 1 */
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000},
- {0x00000000,0x00000000,0x00000001,0x00000009,
- 0x00000009,0x00000009,0x00000009,0x00000001},
- {0x00000000,0x00000000,0x00000009,0x00000009,
- 0x00000049,0x00000049,0x00000049,0x00000049},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000049,0x0000024a,0x0000024a},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000249,0x00000249,0x0000024a,0x0000024a},
- {0x00000000,0x00000000,0x00000049,0x00000249,
- 0x00000249,0x00000249,0x0000024a,0x00001252},
- {0x00000000,0x00000000,0x00000049,0x00001249,
- 0x0000124a,0x0000124a,0x00001252,0x00009292},
- {0x00000000,0x00000000,0x00000249,0x00001249,
- 0x00009252,0x00009252,0x00009292,0x00009493},
- {0x00000000,0x00000000,0x00000249,0x0000924a,
- 0x00009292,0x00009292,0x00009292,0x00009493},
- {0x00000000,0x00000000,0x00000249,0x00009292,
- 0x00009492,0x00009493,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x0000a493,0x000124db,0x000126dc,0x000126dc},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x000126dc,0x000136e4,0x000136e4},
- {0x00000000,0x00000000,0x00009252,0x00009493,
- 0x000126dc,0x000126dc,0x000136e4,0x000136e4},
- {0x00000000,0x00000000,0x00009292,0x0000a49b,
- 0x000136e4,0x000136e4,0x0001b725,0x0001b724},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- }
- },
- { /* version 1 */
- { /* version 1, passes 0 */
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000001},
- {0x00000000,0x00000000,0x00000009,0x00000009,
- 0x00000009,0x00000009,0x00000009,0x00000009},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000049,0x00000049,0x00000049},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000249,0x0000024a,0x0000024a},
- {0x00000000,0x00000000,0x00000049,0x00000249,
- 0x00000249,0x00000249,0x0000024a,0x00001252},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00000249,0x0000124a,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x0000124a,0x0000124a,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x00000249,0x00001249,
- 0x0000124a,0x00009252,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x00000249,0x00001249,
- 0x00009252,0x00009292,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x00000249,0x00001249,
- 0x00009252,0x00009292,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x00000249,0x0000924a,
- 0x00009252,0x00009493,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x00000249,0x0000924a,
- 0x00009292,0x00009493,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x00000249,0x00009252,
- 0x00009492,0x00009493,0x0000a49b,0x0000a49b},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x00009492,0x000124db,0x000124db,0x000124db},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x000126dc,0x000126dc,0x000126dc},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- },
- { /* version 1, passes 1 */
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000},
- {0x00000000,0x00000000,0x00000049,0x00000009,
- 0x00000049,0x00000009,0x00000001,0x00000000},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000049,0x00000049,0x00000000},
- {0x00000000,0x00000000,0x00000249,0x00000049,
- 0x00000249,0x00000049,0x0000024a,0x00000001},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00000249,0x00000249,0x0000024a,0x00000001},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00000249,0x00000249,0x0000024a,0x00000001},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00000249,0x00000249,0x0000024a,0x00000009},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x0000124a,0x0000124a,0x0000024a,0x00000009},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x0000124a,0x0000124a,0x0000024a,0x00000009},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x0000124a,0x00009252,0x00001252,0x00000049},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x0000124a,0x00009292,0x00001252,0x00000049},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x0000124a,0x00009292,0x00001252,0x00000049},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x00009292,0x00001252,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009292,0x00009292,0x00001252,0x0000024a},
- {0x00000000,0x00000000,0x0000924a,0x0000924a,
- 0x00009492,0x00009493,0x00009292,0x00001252},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- }
- },
- { /* version 2 */
- { /* version 2, passes 0 */
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000049,0x0000024a,0x0000024a},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00000249,0x0000124a,0x00001252,0x00009292},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x0000124a,0x00009252,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x00000249,0x00001249,
- 0x0000124a,0x00009292,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x00000249,0x00001249,
- 0x00009252,0x00009493,0x00009493,0x0000a49b},
- {0x00000000,0x00000000,0x00000249,0x0000924a,
- 0x00009292,0x00009493,0x0000a49b,0x0000a49b},
- {0x00000000,0x00000000,0x00001249,0x0000924a,
- 0x00009292,0x00009493,0x0000a49b,0x000124db},
- {0x00000000,0x00000000,0x00001249,0x00009252,
- 0x00009492,0x0000a49b,0x0000a49b,0x000124db},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x00009492,0x000124db,0x000124db,0x000126dc},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x0000a493,0x000124db,0x000126dc,0x000126dc},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x000124db,0x000126dc,0x000136e4},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x000126dc,0x000136e4,0x000136e4},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0001249b,0x000126dc,0x000136e4,0x000136e4},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000124db,0x000136e4,0x000136e4,0x0001b724},
- {0x00000000,0x00000000,0x00009252,0x000124db,
- 0x000126dc,0x0001b724,0x0001b725,0x0001b925},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- },
- { /* version 2, passes 1 */
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000049,0x00000049,0x00000049},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00000249,0x00000249,0x0000024a,0x00000049},
- {0x00000000,0x00000000,0x00001249,0x00000249,
- 0x0000124a,0x0000124a,0x00001252,0x00000049},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x0000124a,0x0000124a,0x00009292,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x00009292,0x00009292,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x00009292,0x0000a49b,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009292,0x00009493,0x0000a49b,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009292,0x00009493,0x0000a49b,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x0000924a,
- 0x00009492,0x0000a49b,0x0000a49b,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x00009252,
- 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x000124db,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x00009252,0x0000a49b,
- 0x0001249b,0x000126dc,0x000124db,0x0000a49b},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- }
- },
- { /* version 3 */
- { /* version 3, passes 0 */
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x0000124a,0x0000124a,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009292,0x00009493,0x0000a49b,0x0000a49b},
- {0x00000000,0x00000000,0x00001249,0x0000924a,
- 0x00009492,0x0000a49b,0x0000a49b,0x000124db},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x00009492,0x000124db,0x000126dc,0x000126dc},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x000124db,0x000126dc,0x000126dc},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x000126dc,0x000136e4,0x000136e4},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x000126dc,0x000136e4,0x0001b724},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0001249b,0x000126dc,0x000136e4,0x0001b724},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000126dc,0x000136e4,0x0001b724},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000136e4,0x0001b725,0x0001b724},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000124db,0x000136e4,0x0001b725,0x0001b925},
- {0x00000000,0x00000000,0x00009292,0x0000a49b,
- 0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
- {0x00000000,0x00000000,0x00009292,0x0000a49b,
- 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
- {0x00000000,0x00000000,0x0000a492,0x000126db,
- 0x000136e4,0x0001b925,0x00025bb6,0x00024b77},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- },
- { /* version 3, passes 1 */
- {0x00000000,0x00000000,0x00001249,0x00000249,
- 0x0000124a,0x0000124a,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x00009292,0x00009292,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x0000924a,
- 0x00009492,0x00009493,0x0000a49b,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x00009252,
- 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x0000a49b,0x000126dc,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x0000a49b,0x000126dc,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x0000a49b,0x000126dc,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x000124db,0x000126dc,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000124db,0x000136e4,0x000126dc,0x000124db},
- {0x00000000,0x00000000,0x00009492,0x0000a49b,
- 0x000136e4,0x000136e4,0x000126dc,0x000124db},
- {0x00000000,0x00000000,0x0000a492,0x000124db,
- 0x0001b724,0x0001b724,0x000136e4,0x000126dc},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- }
- },
- { /* version 4 */
- { /* version 4, passes 0 */
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000049,0x00000049,0x00000049},
- {0x00000000,0x00000000,0x00000249,0x00000049,
- 0x00000249,0x00000249,0x0000024a,0x00000049},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x0000124a,0x00009252,0x00001252,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x00009292,0x00009493,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x0000924a,
- 0x00009292,0x00009493,0x00009493,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x000124db,0x000124db,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0001249b,0x000126dc,0x000126dc,0x000124db},
- {0x00000000,0x00000000,0x00009252,0x00009493,
- 0x000124db,0x000136e4,0x000136e4,0x000126dc},
- {0x00000000,0x00000000,0x00009252,0x0000a49b,
- 0x000124db,0x000136e4,0x000136e4,0x000126dc},
- {0x00000000,0x00000000,0x00009292,0x0000a49b,
- 0x000126dc,0x000136e4,0x000136e4,0x000136e4},
- {0x00000000,0x00000000,0x00009492,0x0000a49b,
- 0x000126dc,0x0001b724,0x0001b725,0x0001b724},
- {0x00000000,0x00000000,0x0000a492,0x000124db,
- 0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- },
- { /* version 4, passes 1 */
- {0x00000000,0x00000000,0x00000249,0x00000049,
- 0x00000009,0x00000009,0x00000009,0x00000009},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00000049,0x00000049,0x00000009,0x00000009},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x0000124a,0x00000249,0x00000049,0x00000049},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x0000124a,0x0000124a,0x00000049,0x00000049},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x0000124a,0x0000024a,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x0000924a,
- 0x00009252,0x0000124a,0x0000024a,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x00009492,0x00009252,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x00009292,0x00009292,0x00001252},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x00009292,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x00009493,0x00009493,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x0000a49b,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000124db,0x0000a49b,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
- {0x00000000,0x00000000,0x00009252,0x000124db,
- 0x0001b724,0x000136e4,0x000126dc,0x000124db},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- }
- },
- { /* version 5 */
- { /* version 5, passes 0 */
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00000249,0x00000249,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x00009292,0x00009292,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x0000924a,
- 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x0000a49b,0x000124db,0x00009493},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x000124db,0x000126dc,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000126dc,0x000136e4,0x000124db},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000126dc,0x000136e4,0x000136e4,0x000126dc},
- {0x00000000,0x00000000,0x00009292,0x0000a49b,
- 0x000126dc,0x000136e4,0x000136e4,0x000126dc},
- {0x00000000,0x00000000,0x00009292,0x0000a49b,
- 0x000126dc,0x0001b724,0x0001b725,0x000136e4},
- {0x00000000,0x00000000,0x00009292,0x0000a49b,
- 0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
- {0x00000000,0x00000000,0x00009492,0x0000a49b,
- 0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x000136e4,0x0001b925,0x0001c96e,0x0001b925},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
- {0x00000000,0x00000000,0x0000a492,0x000126db,
- 0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- },
- { /* version 5, passes 1 */
- {0x00000000,0x00000000,0x00001249,0x00000249,
- 0x00000249,0x00000249,0x0000024a,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x0000124a,0x0000124a,0x0000024a,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x0000924a,
- 0x00009252,0x00009252,0x0000024a,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x00009492,0x0000a49b,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x0000a49b,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x0000a49b,0x00009292,0x00001252},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x0000a49b,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x0000a49b,0x00009493,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000124db,0x00009493,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000124db,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000124db,0x000124db,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x000124db,
- 0x000126dc,0x000126dc,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x000124db,
- 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
- {0x00000000,0x00000000,0x00009292,0x000124db,
- 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
- {0x00000000,0x00000000,0x00009492,0x000126db,
- 0x0001b724,0x000136e4,0x000126dc,0x000124db},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- }
- },
- { /* version 6 */
- { /* version 6, passes 0 */
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x00009292,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x000124db,0x000124db,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000126dc,0x000136e4,0x000124db},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000126dc,0x000136e4,0x000136e4,0x000126dc},
- {0x00000000,0x00000000,0x00009292,0x0000a49b,
- 0x000126dc,0x0001b724,0x0001b725,0x000126dc},
- {0x00000000,0x00000000,0x00009292,0x0000a49b,
- 0x000136e4,0x0001b724,0x0001b92d,0x000136e4},
- {0x00000000,0x00000000,0x00009492,0x0000a49b,
- 0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
- {0x00000000,0x00000000,0x0000a492,0x000124db,
- 0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d},
- {0x00000000,0x00000000,0x0000a492,0x000124db,
- 0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
- {0x00000000,0x00000000,0x00012492,0x000126db,
- 0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- },
- { /* version 6, passes 1 */
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x0000124a,0x0000124a,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x00009492,0x00009252,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x00009292,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x0000a49b,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x0000a49b,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x0000a49b,0x00009493,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000124db,0x000124db,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000124db,0x000124db,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x000124db,
- 0x000126dc,0x000124db,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x000124db,
- 0x000126dc,0x000126dc,0x0000a49b,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x000124db,
- 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
- {0x00000000,0x00000000,0x00009492,0x000126db,
- 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
- {0x00000000,0x00000000,0x00009492,0x000126db,
- 0x0001b724,0x000136e4,0x000126dc,0x000124db},
- {0x00000000,0x00000000,0x00009492,0x000126db,
- 0x0001b724,0x000136e4,0x000126dc,0x000124db},
- {0x00000000,0x00000000,0x0000a492,0x000136db,
- 0x0001c924,0x0001b724,0x000136e4,0x000126dc},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- }
- },
- { /* version 7 */
- { /* version 7, passes 0 */
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x00009292,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x000124db,0x000126dc,0x00009493},
- {0x00000000,0x00000000,0x00001249,0x0000a49b,
- 0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000126dc,0x000136e4,0x0001b725,0x000124db},
- {0x00000000,0x00000000,0x00009292,0x0000a49b,
- 0x000136e4,0x0001b724,0x0001b725,0x000126dc},
- {0x00000000,0x00000000,0x00009292,0x000124db,
- 0x000136e4,0x0001b724,0x0001b725,0x000126dc},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x000136e4,0x0001b724,0x0001c96e,0x000136e4},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
- {0x00000000,0x00000000,0x0000a492,0x000124db,
- 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
- {0x00000000,0x00000000,0x0000a492,0x000124db,
- 0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
- {0x00000000,0x00000000,0x0000a492,0x000126db,
- 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
- {0x00000000,0x00000000,0x0000a492,0x000126db,
- 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
- {0x00000000,0x00000000,0x0000a492,0x000126db,
- 0x0001b924,0x0001c92d,0x00024b76,0x0002496e},
- {0x00000000,0x00000000,0x00012492,0x000136db,
- 0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- },
- { /* version 7, passes 1 */
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x0000124a,0x0000124a,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x00009492,0x00009292,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x0000a49b,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x0000a49b,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x0000a49b,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000126dc,0x0000a49b,0x00009493,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x000124db,
- 0x000126dc,0x000124db,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x000124db,
- 0x000136e4,0x000124db,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x000136db,
- 0x0001b724,0x000124db,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x000136db,
- 0x0001b724,0x000126dc,0x0000a49b,0x0000a49b},
- {0x00000000,0x00000000,0x00009292,0x000136db,
- 0x0001b724,0x000126dc,0x000124db,0x0000a49b},
- {0x00000000,0x00000000,0x00009492,0x000136db,
- 0x0001b724,0x000126dc,0x000124db,0x0000a49b},
- {0x00000000,0x00000000,0x0000a492,0x000136db,
- 0x0001b724,0x000136e4,0x000126dc,0x000124db},
- {0x00000000,0x00000000,0x0000a492,0x000136db,
- 0x0001b724,0x000136e4,0x000126dc,0x000124db},
- {0x00000000,0x00000000,0x00012492,0x0001b6db,
- 0x0001c924,0x0001b724,0x000136e4,0x000126dc},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- }
- }
-};
-
diff --git a/drivers/usb/media/pwc/pwc-timon.c b/drivers/usb/media/pwc/pwc-timon.c
index f950a4e5ed9..dee967173d6 100644
--- a/drivers/usb/media/pwc/pwc-timon.c
+++ b/drivers/usb/media/pwc/pwc-timon.c
@@ -314,1133 +314,3 @@ const struct Timon_table_entry Timon_table[PSZ_MAX][6][4] =
},
};
-/*
- * 16 versions:
- * 2 tables (one for Y, and one for U&V)
- * 16 levels of details per tables
- * 8 blocs
- */
-
-const unsigned int TimonRomTable [16][2][16][8] =
-{
- { /* version 0 */
- { /* version 0, passes 0 */
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000001},
- {0x00000000,0x00000000,0x00000001,0x00000001,
- 0x00000001,0x00000001,0x00000001,0x00000001},
- {0x00000000,0x00000000,0x00000001,0x00000001,
- 0x00000001,0x00000009,0x00000009,0x00000009},
- {0x00000000,0x00000000,0x00000009,0x00000001,
- 0x00000009,0x00000009,0x00000009,0x00000009},
- {0x00000000,0x00000000,0x00000009,0x00000009,
- 0x00000009,0x00000009,0x00000049,0x00000009},
- {0x00000000,0x00000000,0x00000009,0x00000009,
- 0x00000009,0x00000049,0x00000049,0x00000049},
- {0x00000000,0x00000000,0x00000009,0x00000009,
- 0x00000049,0x00000049,0x00000049,0x00000049},
- {0x00000000,0x00000000,0x00000009,0x00000049,
- 0x00000049,0x00000049,0x00000049,0x00000049},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000049,0x0000024a,0x0000024a},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000249,0x0000024a,0x0000024a},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000249,0x00000249,0x0000024a,0x0000024a},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000249,0x00000249,0x00001252,0x0000024a},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000249,0x0000124a,0x00001252,0x0000024a},
- {0x00000000,0x00000000,0x00000049,0x00000249,
- 0x00000249,0x0000124a,0x00001252,0x0000024a},
- {0x00000000,0x00000000,0x00000249,0x00001249,
- 0x0000124a,0x00009252,0x00009292,0x00001252},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- },
- { /* version 0, passes 1 */
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000},
- {0x00000000,0x00000000,0x00000001,0x00000001,
- 0x00000001,0x00000001,0x00000000,0x00000000},
- {0x00000000,0x00000000,0x00000009,0x00000001,
- 0x00000001,0x00000009,0x00000000,0x00000000},
- {0x00000000,0x00000000,0x00000009,0x00000009,
- 0x00000009,0x00000009,0x00000000,0x00000000},
- {0x00000000,0x00000000,0x00000009,0x00000009,
- 0x00000009,0x00000009,0x00000001,0x00000000},
- {0x00000000,0x00000000,0x00000049,0x00000009,
- 0x00000009,0x00000049,0x00000001,0x00000001},
- {0x00000000,0x00000000,0x00000049,0x00000009,
- 0x00000009,0x00000049,0x00000001,0x00000001},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000049,0x00000009,0x00000001},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000049,0x00000009,0x00000001},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000049,0x00000009,0x00000001},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000049,0x00000009,0x00000009},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000249,0x00000049,0x00000009},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000249,0x00000049,0x00000009},
- {0x00000000,0x00000000,0x00000249,0x00000049,
- 0x00000249,0x00000249,0x00000049,0x00000009},
- {0x00000000,0x00000000,0x00001249,0x00000249,
- 0x0000124a,0x0000124a,0x0000024a,0x00000049},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- }
- },
- { /* version 1 */
- { /* version 1, passes 0 */
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000001},
- {0x00000000,0x00000000,0x00000001,0x00000001,
- 0x00000001,0x00000009,0x00000009,0x00000009},
- {0x00000000,0x00000000,0x00000009,0x00000009,
- 0x00000009,0x00000009,0x00000009,0x00000009},
- {0x00000000,0x00000000,0x00000009,0x00000009,
- 0x00000009,0x00000049,0x00000049,0x00000049},
- {0x00000000,0x00000000,0x00000009,0x00000049,
- 0x00000049,0x00000049,0x00000049,0x00000049},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000249,0x0000024a,0x0000024a},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000249,0x00000249,0x0000024a,0x0000024a},
- {0x00000000,0x00000000,0x00000049,0x00000249,
- 0x00000249,0x00000249,0x0000024a,0x00001252},
- {0x00000000,0x00000000,0x00000049,0x00000249,
- 0x00000249,0x0000124a,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x00000049,0x00000249,
- 0x0000124a,0x0000124a,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x0000124a,0x0000124a,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x00000249,0x00001249,
- 0x0000124a,0x00009252,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x00000249,0x00001249,
- 0x00009252,0x00009252,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x00000249,0x0000924a,
- 0x00009292,0x00009493,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x00001249,0x00009252,
- 0x00009492,0x0000a49b,0x0000a49b,0x0000a49b},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- },
- { /* version 1, passes 1 */
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000},
- {0x00000000,0x00000000,0x00000009,0x00000009,
- 0x00000009,0x00000001,0x00000001,0x00000000},
- {0x00000000,0x00000000,0x00000009,0x00000009,
- 0x00000009,0x00000009,0x00000001,0x00000000},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000009,0x00000001,0x00000000},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000049,0x00000001,0x00000001},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000049,0x00000009,0x00000001},
- {0x00000000,0x00000000,0x00000249,0x00000049,
- 0x00000049,0x00000249,0x00000009,0x00000001},
- {0x00000000,0x00000000,0x00000249,0x00000049,
- 0x00000249,0x00000249,0x00000009,0x00000009},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00000249,0x00000249,0x00000049,0x00000009},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00000249,0x0000124a,0x00000049,0x00000009},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00000249,0x0000124a,0x00000049,0x00000009},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00000249,0x0000124a,0x0000024a,0x00000049},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x0000124a,0x0000124a,0x0000024a,0x00000049},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x0000124a,0x0000124a,0x0000024a,0x00000049},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x00009252,0x00001252,0x0000024a},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- }
- },
- { /* version 2 */
- { /* version 2, passes 0 */
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000001},
- {0x00000000,0x00000000,0x00000009,0x00000009,
- 0x00000009,0x00000009,0x00000009,0x00000009},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000049,0x00000049,0x00000049},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000249,0x0000024a,0x0000024a},
- {0x00000000,0x00000000,0x00000049,0x00000249,
- 0x00000249,0x00000249,0x0000024a,0x00001252},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00000249,0x0000124a,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x0000124a,0x0000124a,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x00000249,0x00001249,
- 0x0000124a,0x00009252,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x00000249,0x00001249,
- 0x00009252,0x00009292,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x00000249,0x00001249,
- 0x00009252,0x00009292,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x00000249,0x0000924a,
- 0x00009252,0x00009493,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x00000249,0x0000924a,
- 0x00009292,0x00009493,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x00000249,0x00009252,
- 0x00009492,0x00009493,0x0000a49b,0x0000a49b},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x00009492,0x000124db,0x000124db,0x000124db},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x000126dc,0x000126dc,0x000126dc},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- },
- { /* version 2, passes 1 */
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000},
- {0x00000000,0x00000000,0x00000049,0x00000009,
- 0x00000049,0x00000009,0x00000001,0x00000000},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000049,0x00000049,0x00000000},
- {0x00000000,0x00000000,0x00000249,0x00000049,
- 0x00000249,0x00000049,0x0000024a,0x00000001},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00000249,0x00000249,0x0000024a,0x00000001},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00000249,0x00000249,0x0000024a,0x00000001},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00000249,0x00000249,0x0000024a,0x00000009},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x0000124a,0x0000124a,0x0000024a,0x00000009},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x0000124a,0x0000124a,0x0000024a,0x00000009},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x0000124a,0x00009252,0x00001252,0x00000049},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x0000124a,0x00009292,0x00001252,0x00000049},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x0000124a,0x00009292,0x00001252,0x00000049},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x00009292,0x00001252,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009292,0x00009292,0x00001252,0x0000024a},
- {0x00000000,0x00000000,0x0000924a,0x0000924a,
- 0x00009492,0x00009493,0x00009292,0x00001252},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- }
- },
- { /* version 3 */
- { /* version 3, passes 0 */
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000001},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000049,0x00000049,0x00000049},
- {0x00000000,0x00000000,0x00000049,0x00000249,
- 0x00000249,0x00000249,0x00001252,0x0000024a},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00000249,0x0000124a,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x0000124a,0x00009252,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x00000249,0x00001249,
- 0x0000124a,0x00009292,0x00009292,0x00009493},
- {0x00000000,0x00000000,0x00000249,0x00001249,
- 0x00009252,0x00009292,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x00000249,0x00001249,
- 0x00009292,0x00009493,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x00000249,0x00009252,
- 0x00009292,0x00009493,0x0000a49b,0x0000a49b},
- {0x00000000,0x00000000,0x00001249,0x00009252,
- 0x00009292,0x0000a49b,0x0000a49b,0x0000a49b},
- {0x00000000,0x00000000,0x00001249,0x00009252,
- 0x00009492,0x0000a49b,0x0000a49b,0x0000a49b},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x00009492,0x0000a49b,0x000124db,0x000124db},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x0000a493,0x0000a49b,0x000124db,0x000124db},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0001249b,0x000126dc,0x000136e4,0x000126dc},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000124db,0x000136e4,0x0001b725,0x000136e4},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- },
- { /* version 3, passes 1 */
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000},
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000049,0x00000001,0x00000000},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00000249,0x00000249,0x00000049,0x00000001},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00000249,0x0000124a,0x00001252,0x00000001},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x0000124a,0x0000124a,0x00001252,0x00000009},
- {0x00000000,0x00000000,0x00000249,0x00001249,
- 0x0000124a,0x00009252,0x00009292,0x00000009},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x0000124a,0x00009252,0x00009292,0x00000049},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x00009252,0x00009292,0x00000049},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x00009493,0x00009292,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x00009493,0x00009292,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x00009493,0x00009493,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x0000924a,
- 0x00009292,0x00009493,0x00009493,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x0000924a,
- 0x00009492,0x00009493,0x00009493,0x00009292},
- {0x00000000,0x00000000,0x00001249,0x00009252,
- 0x00009492,0x0000a49b,0x00009493,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x00009292,
- 0x0000a493,0x000124db,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- }
- },
- { /* version 4 */
- { /* version 4, passes 0 */
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000049,0x0000024a,0x0000024a},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00000249,0x0000124a,0x00001252,0x00009292},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x0000124a,0x00009252,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x00000249,0x00001249,
- 0x0000124a,0x00009292,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x00000249,0x00001249,
- 0x00009252,0x00009493,0x00009493,0x0000a49b},
- {0x00000000,0x00000000,0x00000249,0x0000924a,
- 0x00009292,0x00009493,0x0000a49b,0x0000a49b},
- {0x00000000,0x00000000,0x00001249,0x0000924a,
- 0x00009292,0x00009493,0x0000a49b,0x000124db},
- {0x00000000,0x00000000,0x00001249,0x00009252,
- 0x00009492,0x0000a49b,0x0000a49b,0x000124db},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x00009492,0x000124db,0x000124db,0x000126dc},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x0000a493,0x000124db,0x000126dc,0x000126dc},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x000124db,0x000126dc,0x000136e4},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x000126dc,0x000136e4,0x000136e4},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0001249b,0x000126dc,0x000136e4,0x000136e4},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000124db,0x000136e4,0x000136e4,0x0001b724},
- {0x00000000,0x00000000,0x00009252,0x000124db,
- 0x000126dc,0x0001b724,0x0001b725,0x0001b925},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- },
- { /* version 4, passes 1 */
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000049,0x00000049,0x00000049},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00000249,0x00000249,0x0000024a,0x00000049},
- {0x00000000,0x00000000,0x00001249,0x00000249,
- 0x0000124a,0x0000124a,0x00001252,0x00000049},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x0000124a,0x0000124a,0x00009292,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x00009292,0x00009292,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x00009292,0x0000a49b,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009292,0x00009493,0x0000a49b,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009292,0x00009493,0x0000a49b,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x0000924a,
- 0x00009492,0x0000a49b,0x0000a49b,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x00009252,
- 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x000124db,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x00009252,0x0000a49b,
- 0x0001249b,0x000126dc,0x000124db,0x0000a49b},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- }
- },
- { /* version 5 */
- { /* version 5, passes 0 */
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00000249,0x0000124a,0x00001252,0x00009292},
- {0x00000000,0x00000000,0x00000249,0x00001249,
- 0x0000124a,0x00009292,0x00009292,0x00009493},
- {0x00000000,0x00000000,0x00000249,0x0000924a,
- 0x00009292,0x00009493,0x0000a49b,0x0000a49b},
- {0x00000000,0x00000000,0x00001249,0x0000924a,
- 0x00009292,0x00009493,0x0000a49b,0x0000a49b},
- {0x00000000,0x00000000,0x00001249,0x0000924a,
- 0x00009492,0x0000a49b,0x0000a49b,0x000124db},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x00009492,0x0000a49b,0x000124db,0x000124db},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x0000a493,0x000124db,0x000124db,0x000126dc},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x000124db,0x000126dc,0x000126dc},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x000126dc,0x000136e4,0x000136e4},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0001249b,0x000126dc,0x000136e4,0x000136e4},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0001249b,0x000126dc,0x000136e4,0x000136e4},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0001249b,0x000126dc,0x0001b725,0x0001b724},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000124db,0x000126dc,0x0001b725,0x0001b724},
- {0x00000000,0x00000000,0x00009292,0x0000a49b,
- 0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x000136e4,0x0001b724,0x0001c96e,0x0001c92d},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- },
- { /* version 5, passes 1 */
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x0000124a,0x00000249,0x0000024a,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x0000124a,0x0000124a,0x00001252,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009292,0x00009493,0x00009493,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009292,0x00009493,0x00009493,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009292,0x00009493,0x0000a49b,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x0000924a,
- 0x00009492,0x00009493,0x000124db,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x00009492,0x00009493,0x000124db,0x00009292},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x00009492,0x0000a49b,0x000124db,0x00009292},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x0000a49b,0x000124db,0x00009292},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x000124db,0x000124db,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x000124db,0x000124db,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x000124db,0x000124db,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x000124db,0x000124db,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000124db,0x000126dc,0x000124db,0x0000a49b},
- {0x00000000,0x00000000,0x00009252,0x000124db,
- 0x000126dc,0x000136e4,0x000126dc,0x000124db},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- }
- },
- { /* version 6 */
- { /* version 6, passes 0 */
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x0000124a,0x0000124a,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009292,0x00009493,0x0000a49b,0x0000a49b},
- {0x00000000,0x00000000,0x00001249,0x0000924a,
- 0x00009492,0x0000a49b,0x0000a49b,0x000124db},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x00009492,0x000124db,0x000126dc,0x000126dc},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x000124db,0x000126dc,0x000126dc},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x000126dc,0x000136e4,0x000136e4},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x000126dc,0x000136e4,0x0001b724},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0001249b,0x000126dc,0x000136e4,0x0001b724},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000126dc,0x000136e4,0x0001b724},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000136e4,0x0001b725,0x0001b724},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000124db,0x000136e4,0x0001b725,0x0001b925},
- {0x00000000,0x00000000,0x00009292,0x0000a49b,
- 0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
- {0x00000000,0x00000000,0x00009292,0x0000a49b,
- 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
- {0x00000000,0x00000000,0x0000a492,0x000126db,
- 0x000136e4,0x0001b925,0x00025bb6,0x00024b77},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- },
- { /* version 6, passes 1 */
- {0x00000000,0x00000000,0x00001249,0x00000249,
- 0x0000124a,0x0000124a,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x00009292,0x00009292,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x0000924a,
- 0x00009492,0x00009493,0x0000a49b,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x00009252,
- 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x0000a49b,0x000126dc,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x0000a49b,0x000126dc,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x0000a49b,0x000126dc,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x000124db,0x000126dc,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000124db,0x000136e4,0x000126dc,0x000124db},
- {0x00000000,0x00000000,0x00009492,0x0000a49b,
- 0x000136e4,0x000136e4,0x000126dc,0x000124db},
- {0x00000000,0x00000000,0x0000a492,0x000124db,
- 0x0001b724,0x0001b724,0x000136e4,0x000126dc},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- }
- },
- { /* version 7 */
- { /* version 7, passes 0 */
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009292,0x00009493,0x0000a49b,0x000124db},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x0000a493,0x0000a49b,0x000124db,0x000126dc},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x000124db,0x000126dc,0x000136e4},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x000124db,0x000136e4,0x000136e4},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0001249b,0x000126dc,0x000136e4,0x000136e4},
- {0x00000000,0x00000000,0x00001249,0x0000a49b,
- 0x0001249b,0x000126dc,0x000136e4,0x0001b724},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000126dc,0x000136e4,0x0001b724},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000124db,0x000136e4,0x0001b725,0x0001b724},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000126dc,0x000136e4,0x0001b725,0x0001b925},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000126dc,0x0001b724,0x0001b92d,0x0001b925},
- {0x00000000,0x00000000,0x00009292,0x0000a49b,
- 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
- {0x00000000,0x00000000,0x00009292,0x000124db,
- 0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x000136e4,0x0001b724,0x0001c96e,0x0002496e},
- {0x00000000,0x00000000,0x00009492,0x000126db,
- 0x000136e4,0x0001b925,0x0001c96e,0x0002496e},
- {0x00000000,0x00000000,0x0000a492,0x000136db,
- 0x0001b724,0x0002496d,0x00025bb6,0x00025bbf},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- },
- { /* version 7, passes 1 */
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x00009292,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x00001249,0x0000924a,
- 0x00009492,0x00009493,0x00009493,0x00009292},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x0000a49b,0x000124db,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x000124db,0x000124db,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x000124db,0x000136e4,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x000124db,0x000136e4,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000124db,0x000136e4,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000126dc,0x000136e4,0x000124db},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000126dc,0x000136e4,0x000136e4,0x000124db},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000126dc,0x000136e4,0x000136e4,0x000124db},
- {0x00000000,0x00000000,0x0000924a,0x000124db,
- 0x000136e4,0x000136e4,0x000136e4,0x000126dc},
- {0x00000000,0x00000000,0x0000a492,0x000124db,
- 0x000136e4,0x0001b724,0x000136e4,0x000126dc},
- {0x00000000,0x00000000,0x00012492,0x000126db,
- 0x0001b724,0x0001b925,0x0001b725,0x000136e4},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- }
- },
- { /* version 8 */
- { /* version 8, passes 0 */
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009292,0x00009493,0x0000a49b,0x000124db},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x0000a493,0x000124db,0x000126dc,0x000126dc},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x000124db,0x000126dc,0x000136e4},
- {0x00000000,0x00000000,0x00001249,0x0000a49b,
- 0x0001249b,0x000126dc,0x000136e4,0x0001b724},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000126dc,0x000136e4,0x0001b724},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000124db,0x000136e4,0x0001b725,0x0001b724},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000126dc,0x000136e4,0x0001b725,0x0001b925},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
- {0x00000000,0x00000000,0x00009252,0x000124db,
- 0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
- {0x00000000,0x00000000,0x00009292,0x000124db,
- 0x000126dc,0x0001b925,0x0001c96e,0x0001c92d},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x000136e4,0x0001b925,0x0001c96e,0x0001c92d},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x000136e4,0x0001b925,0x00024b76,0x00024b77},
- {0x00000000,0x00000000,0x00009492,0x000126db,
- 0x000136e4,0x0001b925,0x00024b76,0x00025bbf},
- {0x00000000,0x00000000,0x0000a492,0x000126db,
- 0x000136e4,0x0001c92d,0x00024b76,0x00025bbf},
- {0x00000000,0x00000000,0x00012492,0x000136db,
- 0x0001b724,0x00024b6d,0x0002ddb6,0x0002efff},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- },
- { /* version 8, passes 1 */
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x00009493,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x0000a49b,0x000124db,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x000124db,0x000136e4,0x000124db},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000126dc,0x000136e4,0x000124db},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000126dc,0x000126dc,0x000136e4,0x000126dc},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000126dc,0x000136e4,0x000136e4,0x000126dc},
- {0x00000000,0x00000000,0x0000924a,0x000124db,
- 0x000126dc,0x000136e4,0x000136e4,0x000126dc},
- {0x00000000,0x00000000,0x0000924a,0x000124db,
- 0x000126dc,0x000136e4,0x000136e4,0x000136e4},
- {0x00000000,0x00000000,0x00009292,0x000124db,
- 0x000136e4,0x0001b724,0x0001b725,0x000136e4},
- {0x00000000,0x00000000,0x00009492,0x000126db,
- 0x000136e4,0x0001b925,0x0001b725,0x0001b724},
- {0x00000000,0x00000000,0x00009492,0x000126db,
- 0x000136e4,0x0001b925,0x0001b725,0x0001b724},
- {0x00000000,0x00000000,0x0000a492,0x000136db,
- 0x0001b724,0x0002496d,0x0001b92d,0x0001b925},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- }
- },
- { /* version 9 */
- { /* version 9, passes 0 */
- {0x00000000,0x00000000,0x00000049,0x00000049,
- 0x00000049,0x00000049,0x00000049,0x00000049},
- {0x00000000,0x00000000,0x00000249,0x00000049,
- 0x00000249,0x00000249,0x0000024a,0x00000049},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x0000124a,0x00009252,0x00001252,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x00009292,0x00009493,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x0000924a,
- 0x00009292,0x00009493,0x00009493,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x000124db,0x000124db,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0001249b,0x000126dc,0x000126dc,0x000124db},
- {0x00000000,0x00000000,0x00009252,0x00009493,
- 0x000124db,0x000136e4,0x000136e4,0x000126dc},
- {0x00000000,0x00000000,0x00009252,0x0000a49b,
- 0x000124db,0x000136e4,0x000136e4,0x000126dc},
- {0x00000000,0x00000000,0x00009292,0x0000a49b,
- 0x000126dc,0x000136e4,0x000136e4,0x000136e4},
- {0x00000000,0x00000000,0x00009492,0x0000a49b,
- 0x000126dc,0x0001b724,0x0001b725,0x0001b724},
- {0x00000000,0x00000000,0x0000a492,0x000124db,
- 0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- },
- { /* version 9, passes 1 */
- {0x00000000,0x00000000,0x00000249,0x00000049,
- 0x00000009,0x00000009,0x00000009,0x00000009},
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00000049,0x00000049,0x00000009,0x00000009},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x0000124a,0x00000249,0x00000049,0x00000049},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x0000124a,0x0000124a,0x00000049,0x00000049},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x0000124a,0x0000024a,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x0000924a,
- 0x00009252,0x0000124a,0x0000024a,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x00009492,0x00009252,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x00009292,0x00009292,0x00001252},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x00009292,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x00009493,0x00009493,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x0000a49b,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000124db,0x0000a49b,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
- {0x00000000,0x00000000,0x00009252,0x000124db,
- 0x0001b724,0x000136e4,0x000126dc,0x000124db},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- }
- },
- { /* version 10 */
- { /* version 10, passes 0 */
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00000249,0x00000249,0x0000024a,0x0000024a},
- {0x00000000,0x00000000,0x00000249,0x00001249,
- 0x00009252,0x00009292,0x00009292,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x00009292,0x00009292,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x0000924a,
- 0x00009492,0x00009493,0x0000a49b,0x00009292},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x00009492,0x000124db,0x000124db,0x00009292},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x000124db,0x000124db,0x00009493},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x000124db,0x000126dc,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x000124db,0x000126dc,0x000124db},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0001249b,0x000126dc,0x000126dc,0x000124db},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000124db,0x000126dc,0x000136e4,0x000126dc},
- {0x00000000,0x00000000,0x00009252,0x0000a49b,
- 0x000124db,0x000136e4,0x000136e4,0x000136e4},
- {0x00000000,0x00000000,0x00009292,0x0000a49b,
- 0x000126dc,0x000136e4,0x000136e4,0x000136e4},
- {0x00000000,0x00000000,0x00009492,0x0000a49b,
- 0x000126dc,0x0001b724,0x0001b92d,0x0001b724},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x000126dc,0x0001b925,0x0001b92d,0x0001b925},
- {0x00000000,0x00000000,0x0000a492,0x000126db,
- 0x000136e4,0x0002496d,0x0001c96e,0x0001c92d},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- },
- { /* version 10, passes 1 */
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00000049,0x00000049,0x00000049,0x00000049},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x0000124a,0x00000249,0x00000049,0x00000049},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x0000124a,0x00009252,0x0000024a,0x00000049},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x00009493,0x0000024a,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x00009252,
- 0x00009492,0x00009493,0x00001252,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x00009492,0x00009493,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x00009492,0x00009493,0x00009292,0x00001252},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x00009493,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x0000a49b,0x00009493,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x0000a49b,0x00009493,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x000124db,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x000124db,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x000124db,
- 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x000124db,
- 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
- {0x00000000,0x00000000,0x00009252,0x000126db,
- 0x0001b724,0x000136e4,0x000126dc,0x000124db},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- }
- },
- { /* version 11 */
- { /* version 11, passes 0 */
- {0x00000000,0x00000000,0x00000249,0x00000249,
- 0x00000249,0x00000249,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x00009292,0x00009292,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x0000924a,
- 0x00009492,0x0000a49b,0x0000a49b,0x00009292},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x0000a49b,0x000124db,0x00009493},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x000124db,0x000126dc,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000126dc,0x000136e4,0x000124db},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000126dc,0x000136e4,0x000136e4,0x000126dc},
- {0x00000000,0x00000000,0x00009292,0x0000a49b,
- 0x000126dc,0x000136e4,0x000136e4,0x000126dc},
- {0x00000000,0x00000000,0x00009292,0x0000a49b,
- 0x000126dc,0x0001b724,0x0001b725,0x000136e4},
- {0x00000000,0x00000000,0x00009292,0x0000a49b,
- 0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
- {0x00000000,0x00000000,0x00009492,0x0000a49b,
- 0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x000136e4,0x0001b925,0x0001c96e,0x0001b925},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
- {0x00000000,0x00000000,0x0000a492,0x000126db,
- 0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- },
- { /* version 11, passes 1 */
- {0x00000000,0x00000000,0x00001249,0x00000249,
- 0x00000249,0x00000249,0x0000024a,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x0000124a,0x0000124a,0x0000024a,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x0000924a,
- 0x00009252,0x00009252,0x0000024a,0x0000024a},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x00009492,0x0000a49b,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x0000a49b,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x0000a49b,0x00009292,0x00001252},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x0000a49b,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x0000a49b,0x00009493,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000124db,0x00009493,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000124db,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000124db,0x000124db,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x000124db,
- 0x000126dc,0x000126dc,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x000124db,
- 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
- {0x00000000,0x00000000,0x00009292,0x000124db,
- 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
- {0x00000000,0x00000000,0x00009492,0x000126db,
- 0x0001b724,0x000136e4,0x000126dc,0x000124db},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- }
- },
- { /* version 12 */
- { /* version 12, passes 0 */
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x00009292,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x000124db,0x000124db,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000126dc,0x000136e4,0x000124db},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000126dc,0x000136e4,0x000136e4,0x000126dc},
- {0x00000000,0x00000000,0x00009292,0x0000a49b,
- 0x000126dc,0x0001b724,0x0001b725,0x000126dc},
- {0x00000000,0x00000000,0x00009292,0x0000a49b,
- 0x000136e4,0x0001b724,0x0001b92d,0x000136e4},
- {0x00000000,0x00000000,0x00009492,0x0000a49b,
- 0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
- {0x00000000,0x00000000,0x0000a492,0x000124db,
- 0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d},
- {0x00000000,0x00000000,0x0000a492,0x000124db,
- 0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
- {0x00000000,0x00000000,0x00012492,0x000126db,
- 0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- },
- { /* version 12, passes 1 */
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x0000124a,0x0000124a,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x00001249,0x00009292,
- 0x00009492,0x00009252,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x00009292,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x0000a49b,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x0000a49b,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x0000a49b,0x00009493,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000124db,0x000124db,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000124db,0x000124db,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x000124db,
- 0x000126dc,0x000124db,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x000124db,
- 0x000126dc,0x000126dc,0x0000a49b,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x000124db,
- 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
- {0x00000000,0x00000000,0x00009492,0x000126db,
- 0x000136e4,0x000126dc,0x000124db,0x0000a49b},
- {0x00000000,0x00000000,0x00009492,0x000126db,
- 0x0001b724,0x000136e4,0x000126dc,0x000124db},
- {0x00000000,0x00000000,0x00009492,0x000126db,
- 0x0001b724,0x000136e4,0x000126dc,0x000124db},
- {0x00000000,0x00000000,0x0000a492,0x000136db,
- 0x0001c924,0x0001b724,0x000136e4,0x000126dc},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- }
- },
- { /* version 13 */
- { /* version 13, passes 0 */
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x00009252,0x00009292,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x000124db,0x000126dc,0x00009493},
- {0x00000000,0x00000000,0x00001249,0x0000a49b,
- 0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000126dc,0x000136e4,0x0001b725,0x000124db},
- {0x00000000,0x00000000,0x00009292,0x0000a49b,
- 0x000136e4,0x0001b724,0x0001b725,0x000126dc},
- {0x00000000,0x00000000,0x00009292,0x000124db,
- 0x000136e4,0x0001b724,0x0001b725,0x000126dc},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x000136e4,0x0001b724,0x0001c96e,0x000136e4},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
- {0x00000000,0x00000000,0x0000a492,0x000124db,
- 0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
- {0x00000000,0x00000000,0x0000a492,0x000124db,
- 0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
- {0x00000000,0x00000000,0x0000a492,0x000126db,
- 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
- {0x00000000,0x00000000,0x0000a492,0x000126db,
- 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
- {0x00000000,0x00000000,0x0000a492,0x000126db,
- 0x0001b924,0x0001c92d,0x00024b76,0x0002496e},
- {0x00000000,0x00000000,0x00012492,0x000136db,
- 0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- },
- { /* version 13, passes 1 */
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x0000124a,0x0000124a,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x00009492,0x00009292,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x0000a49b,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x0000a49b,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x0000a49b,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000126dc,0x0000a49b,0x00009493,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x000124db,
- 0x000126dc,0x000124db,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x000124db,
- 0x000136e4,0x000124db,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x000136db,
- 0x0001b724,0x000124db,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x000136db,
- 0x0001b724,0x000126dc,0x0000a49b,0x0000a49b},
- {0x00000000,0x00000000,0x00009292,0x000136db,
- 0x0001b724,0x000126dc,0x000124db,0x0000a49b},
- {0x00000000,0x00000000,0x00009492,0x000136db,
- 0x0001b724,0x000126dc,0x000124db,0x0000a49b},
- {0x00000000,0x00000000,0x0000a492,0x000136db,
- 0x0001b724,0x000136e4,0x000126dc,0x000124db},
- {0x00000000,0x00000000,0x0000a492,0x000136db,
- 0x0001b724,0x000136e4,0x000126dc,0x000124db},
- {0x00000000,0x00000000,0x00012492,0x0001b6db,
- 0x0001c924,0x0001b724,0x000136e4,0x000126dc},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- }
- },
- { /* version 14 */
- { /* version 14, passes 0 */
- {0x00000000,0x00000000,0x00001249,0x0000924a,
- 0x00009292,0x00009493,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x00001249,0x0000a49b,
- 0x0000a493,0x000124db,0x000126dc,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
- {0x00000000,0x00000000,0x0000924a,0x000124db,
- 0x000126dc,0x000136e4,0x0001b725,0x000124db},
- {0x00000000,0x00000000,0x00009292,0x000124db,
- 0x000126dc,0x0001b724,0x0001b92d,0x000126dc},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x000136e4,0x0001b724,0x0001b92d,0x000126dc},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x000136e4,0x0001c92d,0x0001c96e,0x000136e4},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
- {0x00000000,0x00000000,0x0000a492,0x000124db,
- 0x0001b724,0x0001c92d,0x00024b76,0x0001b925},
- {0x00000000,0x00000000,0x0000a492,0x000126db,
- 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
- {0x00000000,0x00000000,0x0000a492,0x000126db,
- 0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
- {0x00000000,0x00000000,0x0000a492,0x000136db,
- 0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
- {0x00000000,0x00000000,0x0000a492,0x000136db,
- 0x0001b924,0x0002496d,0x00024b76,0x00024b77},
- {0x00000000,0x00000000,0x0000a492,0x000136db,
- 0x0001b924,0x00024b6d,0x0002ddb6,0x00025bbf},
- {0x00000000,0x00000000,0x00012492,0x0001b6db,
- 0x00024924,0x0002db6d,0x00036db6,0x0002efff},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- },
- { /* version 14, passes 1 */
- {0x00000000,0x00000000,0x00001249,0x00001249,
- 0x0000124a,0x0000124a,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x0000924a,0x00009493,
- 0x0000a493,0x00009292,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x0000a49b,0x00001252,0x00001252},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000136e4,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000136e4,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x000124db,
- 0x000136e4,0x000136e4,0x00009493,0x00009292},
- {0x00000000,0x00000000,0x00009492,0x000136db,
- 0x0001b724,0x000136e4,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x00009492,0x000136db,
- 0x0001b724,0x000136e4,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x00009492,0x000136db,
- 0x0001b724,0x000136e4,0x0000a49b,0x00009493},
- {0x00000000,0x00000000,0x00009492,0x000136db,
- 0x0001b724,0x000136e4,0x0000a49b,0x0000a49b},
- {0x00000000,0x00000000,0x0000a492,0x000136db,
- 0x0001b724,0x000136e4,0x000124db,0x0000a49b},
- {0x00000000,0x00000000,0x0000a492,0x000136db,
- 0x0001b724,0x000136e4,0x000124db,0x0000a49b},
- {0x00000000,0x00000000,0x0000a492,0x000136db,
- 0x0001b724,0x000136e4,0x000126dc,0x000124db},
- {0x00000000,0x00000000,0x0000a492,0x000136db,
- 0x0001b724,0x000136e4,0x000126dc,0x000124db},
- {0x00000000,0x00000000,0x00012492,0x0001b6db,
- 0x0001c924,0x0001b724,0x000136e4,0x000126dc},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- }
- },
- { /* version 15 */
- { /* version 15, passes 0 */
- {0x00000000,0x00000000,0x00001249,0x00009493,
- 0x0000a493,0x0000a49b,0x000124db,0x000124db},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0001249b,0x000126dc,0x000136e4,0x000124db},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x000126dc,0x0001b724,0x0001b725,0x000126dc},
- {0x00000000,0x00000000,0x0000924a,0x000124db,
- 0x000136e4,0x0001b724,0x0001b92d,0x000126dc},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x000136e4,0x0001b925,0x0001c96e,0x000136e4},
- {0x00000000,0x00000000,0x00009492,0x000124db,
- 0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
- {0x00000000,0x00000000,0x0000a492,0x000124db,
- 0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
- {0x00000000,0x00000000,0x0000a492,0x000126db,
- 0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
- {0x00000000,0x00000000,0x0000a492,0x000126db,
- 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
- {0x00000000,0x00000000,0x0000a492,0x000136db,
- 0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
- {0x00000000,0x00000000,0x0000a492,0x000136db,
- 0x0001b924,0x0002496d,0x00024b76,0x0002496e},
- {0x00000000,0x00000000,0x0000a492,0x000136db,
- 0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
- {0x00000000,0x00000000,0x0000a492,0x000136db,
- 0x0001c924,0x00024b6d,0x00025bb6,0x00024b77},
- {0x00000000,0x00000000,0x00012492,0x000136db,
- 0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
- {0x00000000,0x00000000,0x00012492,0x0001b6db,
- 0x00024924,0x0002db6d,0x00036db6,0x0002efff},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- },
- { /* version 15, passes 1 */
- {0x00000000,0x00000000,0x0000924a,0x0000924a,
- 0x00009292,0x00009292,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x0000a49b,
- 0x0000a493,0x000124db,0x00009292,0x00009292},
- {0x00000000,0x00000000,0x0000924a,0x000124db,
- 0x000124db,0x0001b724,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x000124db,
- 0x000126dc,0x0001b724,0x00009493,0x00009493},
- {0x00000000,0x00000000,0x0000924a,0x000124db,
- 0x000136e4,0x0001b724,0x0000a49b,0x0000a49b},
- {0x00000000,0x00000000,0x00009292,0x000136db,
- 0x0001b724,0x0001b724,0x0000a49b,0x0000a49b},
- {0x00000000,0x00000000,0x00009492,0x000136db,
- 0x0001c924,0x0001b724,0x000124db,0x000124db},
- {0x00000000,0x00000000,0x00009492,0x000136db,
- 0x0001c924,0x0001b724,0x000124db,0x000124db},
- {0x00000000,0x00000000,0x0000a492,0x000136db,
- 0x0001c924,0x0001b724,0x000126dc,0x000126dc},
- {0x00000000,0x00000000,0x0000a492,0x000136db,
- 0x0001c924,0x0001b925,0x000126dc,0x000126dc},
- {0x00000000,0x00000000,0x0000a492,0x000136db,
- 0x0001c924,0x0001b925,0x000136e4,0x000136e4},
- {0x00000000,0x00000000,0x0000a492,0x000136db,
- 0x0001c924,0x0001b925,0x000136e4,0x000136e4},
- {0x00000000,0x00000000,0x0000a492,0x000136db,
- 0x0001c924,0x0001b925,0x0001b725,0x0001b724},
- {0x00000000,0x00000000,0x00012492,0x000136db,
- 0x0001c924,0x0001b925,0x0001b725,0x0001b724},
- {0x00000000,0x00000000,0x00012492,0x0001b6db,
- 0x00024924,0x0002496d,0x0001b92d,0x0001b925},
- {0x00000000,0x00000000,0x00000000,0x00000000,
- 0x00000000,0x00000000,0x00000000,0x00000000}
- }
- }
-};
diff --git a/drivers/usb/media/pwc/pwc-uncompress.c b/drivers/usb/media/pwc/pwc-uncompress.c
index c062e43b3ac..ef4204eab6c 100644
--- a/drivers/usb/media/pwc/pwc-uncompress.c
+++ b/drivers/usb/media/pwc/pwc-uncompress.c
@@ -29,8 +29,6 @@
#include "pwc.h"
#include "pwc-uncompress.h"
-#include "pwc-dec1.h"
-#include "pwc-dec23.h"
int pwc_decompress(struct pwc_device *pdev)
{
@@ -120,6 +118,7 @@ int pwc_decompress(struct pwc_device *pdev)
return -ENXIO; /* No such device or address: missing decompressor */
}
+#if 0
switch (pdev->type)
{
case 675:
@@ -129,17 +128,17 @@ int pwc_decompress(struct pwc_device *pdev)
case 730:
case 740:
case 750:
- pwc_dec23_decompress(&pdev->image, &pdev->view, &pdev->offset,
- yuv, image,
- flags,
+ pwc_dec23_decompress(&pdev->image, &pdev->view,
+ &pdev->offset, yuv, image, flags,
pdev->decompress_data, pdev->vbandlength);
break;
case 645:
case 646:
/* TODO & FIXME */
- return -ENXIO; /* No such device or address: missing decompressor */
+ return -ENXIO; /* Missing decompressor */
break;
}
+#endif
}
return 0;
}
diff --git a/drivers/usb/misc/cytherm.c b/drivers/usb/misc/cytherm.c
index 626e2b05f71..b33044d56a1 100644
--- a/drivers/usb/misc/cytherm.c
+++ b/drivers/usb/misc/cytherm.c
@@ -85,7 +85,7 @@ static int vendor_command(struct usb_device *dev, unsigned char request,
#define BRIGHTNESS 0x2c /* RAM location for brightness value */
#define BRIGHTNESS_SEM 0x2b /* RAM location for brightness semaphore */
-static ssize_t show_brightness(struct device *dev, char *buf)
+static ssize_t show_brightness(struct device *dev, struct device_attribute *attr, char *buf)
{
struct usb_interface *intf = to_usb_interface(dev);
struct usb_cytherm *cytherm = usb_get_intfdata(intf);
@@ -93,7 +93,7 @@ static ssize_t show_brightness(struct device *dev, char *buf)
return sprintf(buf, "%i", cytherm->brightness);
}
-static ssize_t set_brightness(struct device *dev, const char *buf,
+static ssize_t set_brightness(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
struct usb_interface *intf = to_usb_interface(dev);
@@ -138,7 +138,7 @@ static DEVICE_ATTR(brightness, S_IRUGO | S_IWUSR | S_IWGRP,
#define TEMP 0x33 /* RAM location for temperature */
#define SIGN 0x34 /* RAM location for temperature sign */
-static ssize_t show_temp(struct device *dev, char *buf)
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf)
{
struct usb_interface *intf = to_usb_interface(dev);
@@ -174,7 +174,7 @@ static ssize_t show_temp(struct device *dev, char *buf)
}
-static ssize_t set_temp(struct device *dev, const char *buf, size_t count)
+static ssize_t set_temp(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
return count;
}
@@ -184,7 +184,7 @@ static DEVICE_ATTR(temp, S_IRUGO, show_temp, set_temp);
#define BUTTON 0x7a
-static ssize_t show_button(struct device *dev, char *buf)
+static ssize_t show_button(struct device *dev, struct device_attribute *attr, char *buf)
{
struct usb_interface *intf = to_usb_interface(dev);
@@ -215,7 +215,7 @@ static ssize_t show_button(struct device *dev, char *buf)
}
-static ssize_t set_button(struct device *dev, const char *buf, size_t count)
+static ssize_t set_button(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
return count;
}
@@ -223,7 +223,7 @@ static ssize_t set_button(struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(button, S_IRUGO, show_button, set_button);
-static ssize_t show_port0(struct device *dev, char *buf)
+static ssize_t show_port0(struct device *dev, struct device_attribute *attr, char *buf)
{
struct usb_interface *intf = to_usb_interface(dev);
struct usb_cytherm *cytherm = usb_get_intfdata(intf);
@@ -249,7 +249,7 @@ static ssize_t show_port0(struct device *dev, char *buf)
}
-static ssize_t set_port0(struct device *dev, const char *buf, size_t count)
+static ssize_t set_port0(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct usb_interface *intf = to_usb_interface(dev);
struct usb_cytherm *cytherm = usb_get_intfdata(intf);
@@ -283,7 +283,7 @@ static ssize_t set_port0(struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(port0, S_IRUGO | S_IWUSR | S_IWGRP, show_port0, set_port0);
-static ssize_t show_port1(struct device *dev, char *buf)
+static ssize_t show_port1(struct device *dev, struct device_attribute *attr, char *buf)
{
struct usb_interface *intf = to_usb_interface(dev);
struct usb_cytherm *cytherm = usb_get_intfdata(intf);
@@ -309,7 +309,7 @@ static ssize_t show_port1(struct device *dev, char *buf)
}
-static ssize_t set_port1(struct device *dev, const char *buf, size_t count)
+static ssize_t set_port1(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct usb_interface *intf = to_usb_interface(dev);
struct usb_cytherm *cytherm = usb_get_intfdata(intf);
diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c
index ddbf8e99236..067a8148692 100644
--- a/drivers/usb/misc/phidgetkit.c
+++ b/drivers/usb/misc/phidgetkit.c
@@ -173,7 +173,7 @@ exit:
}
#define set_lcd_line(number) \
-static ssize_t lcd_line_##number(struct device *dev, const char *buf, size_t count) \
+static ssize_t lcd_line_##number(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
{ \
struct usb_interface *intf = to_usb_interface(dev); \
struct phidget_interfacekit *kit = usb_get_intfdata(intf); \
@@ -184,7 +184,7 @@ static DEVICE_ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number);
set_lcd_line(1);
set_lcd_line(2);
-static ssize_t set_backlight(struct device *dev, const char *buf, size_t count)
+static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct usb_interface *intf = to_usb_interface(dev);
struct phidget_interfacekit *kit = usb_get_intfdata(intf);
@@ -232,7 +232,7 @@ static void remove_lcd_files(struct phidget_interfacekit *kit)
}
}
-static ssize_t enable_lcd_files(struct device *dev, const char *buf, size_t count)
+static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct usb_interface *intf = to_usb_interface(dev);
struct phidget_interfacekit *kit = usb_get_intfdata(intf);
@@ -307,7 +307,7 @@ resubmit:
}
#define show_set_output(value) \
-static ssize_t set_output##value(struct device *dev, const char *buf, \
+static ssize_t set_output##value(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
{ \
struct usb_interface *intf = to_usb_interface(dev); \
@@ -324,7 +324,7 @@ static ssize_t set_output##value(struct device *dev, const char *buf, \
return retval ? retval : count; \
} \
\
-static ssize_t show_output##value(struct device *dev, char *buf) \
+static ssize_t show_output##value(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct usb_interface *intf = to_usb_interface(dev); \
struct phidget_interfacekit *kit = usb_get_intfdata(intf); \
@@ -343,7 +343,7 @@ show_set_output(7);
show_set_output(8); /* should be MAX_INTERFACES - 1 */
#define show_input(value) \
-static ssize_t show_input##value(struct device *dev, char *buf) \
+static ssize_t show_input##value(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct usb_interface *intf = to_usb_interface(dev); \
struct phidget_interfacekit *kit = usb_get_intfdata(intf); \
@@ -362,7 +362,7 @@ show_input(7);
show_input(8); /* should be MAX_INTERFACES - 1 */
#define show_sensor(value) \
-static ssize_t show_sensor##value(struct device *dev, char *buf) \
+static ssize_t show_sensor##value(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct usb_interface *intf = to_usb_interface(dev); \
struct phidget_interfacekit *kit = usb_get_intfdata(intf); \
diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c
index 4bd291502a3..b84eda631ab 100644
--- a/drivers/usb/misc/phidgetservo.c
+++ b/drivers/usb/misc/phidgetservo.c
@@ -207,7 +207,7 @@ change_position_v20(struct phidget_servo *servo, int servo_no, int degrees,
}
#define show_set(value) \
-static ssize_t set_servo##value (struct device *dev, \
+static ssize_t set_servo##value (struct device *dev, struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
int degrees, minutes, retval; \
@@ -233,7 +233,7 @@ static ssize_t set_servo##value (struct device *dev, \
return retval < 0 ? retval : count; \
} \
\
-static ssize_t show_servo##value (struct device *dev, char *buf) \
+static ssize_t show_servo##value (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct usb_interface *intf = to_usb_interface (dev); \
struct phidget_servo *servo = usb_get_intfdata (intf); \
diff --git a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c
index ee329d5e1c5..f6ba4c788db 100644
--- a/drivers/usb/misc/usbled.c
+++ b/drivers/usb/misc/usbled.c
@@ -81,14 +81,14 @@ static void change_color(struct usb_led *led)
}
#define show_set(value) \
-static ssize_t show_##value(struct device *dev, char *buf) \
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct usb_interface *intf = to_usb_interface(dev); \
struct usb_led *led = usb_get_intfdata(intf); \
\
return sprintf(buf, "%d\n", led->value); \
} \
-static ssize_t set_##value(struct device *dev, const char *buf, size_t count) \
+static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
{ \
struct usb_interface *intf = to_usb_interface(dev); \
struct usb_led *led = usb_get_intfdata(intf); \
diff --git a/drivers/usb/mon/Kconfig b/drivers/usb/mon/Kconfig
index 4e6152aa5f1..777642e26b9 100644
--- a/drivers/usb/mon/Kconfig
+++ b/drivers/usb/mon/Kconfig
@@ -2,13 +2,9 @@
# USB Monitor configuration
#
-# In normal life, it makes little sense to have usbmon as a module, and in fact
-# it is harmful, because there is no way to autoload the module.
-# The 'm' option is allowed for hackers who debug the usbmon itself,
-# and for those who have usbcore as a module.
config USB_MON
- tristate "USB Monitor"
- depends on USB
+ bool "USB Monitor"
+ depends on USB!=n
default y
help
If you say Y here, a component which captures the USB traffic
@@ -17,6 +13,5 @@ config USB_MON
Harding's USBMon.
This is somewhat experimental at this time, but it should be safe,
- as long as you aren't building this as a module and then removing it.
-
- If unsure, say Y. Do not say M.
+ as long as you aren't using modular USB and try to remove this
+ module.
diff --git a/drivers/usb/mon/Makefile b/drivers/usb/mon/Makefile
index 3cff8d444bb..f18d10ce91f 100644
--- a/drivers/usb/mon/Makefile
+++ b/drivers/usb/mon/Makefile
@@ -4,4 +4,4 @@
usbmon-objs := mon_main.o mon_stat.o mon_text.o
-obj-$(CONFIG_USB_MON) += usbmon.o
+obj-$(CONFIG_USB) += usbmon.o
diff --git a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig
index db64c908d4a..b104430e2c6 100644
--- a/drivers/usb/net/Kconfig
+++ b/drivers/usb/net/Kconfig
@@ -219,17 +219,21 @@ config USB_EPSON2888
by some sample firmware from Epson.
config USB_ZAURUS
- boolean "Sharp Zaurus (stock ROMs)"
+ boolean "Sharp Zaurus (stock ROMs) and compatible"
depends on USB_USBNET
select CRC32
default y
help
Choose this option to support the usb networking links used by
Zaurus models like the SL-5000D, SL-5500, SL-5600, A-300, B-500.
-
- If you install an alternate ROM image, you may no longer need
- to support this protocol. Only the "eth-fd" driver really needs
- this non-conformant variant of CDC Ethernet protocol.
+ This also supports some related device firmware, as used in some
+ PDAs from Olympus and some cell phones from Motorola.
+
+ If you install an alternate ROM image, such as the Linux 2.6 based
+ versions of OpenZaurus, you should no longer need to support this
+ protocol. Only the "eth-fd" or "net_fd" drivers in these devices
+ really need this non-conformant variant of CDC Ethernet (or in
+ some cases CDC MDLM) protocol, not "g_ether".
config USB_CDCETHER
boolean "CDC Ethernet support (smart devices such as cable modems)"
diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
index a9a7cf4a38e..fd6ff4cb2c6 100644
--- a/drivers/usb/net/kaweth.c
+++ b/drivers/usb/net/kaweth.c
@@ -520,7 +520,7 @@ static void int_callback(struct urb *u, struct pt_regs *regs)
/* we check the link state to report changes */
if (kaweth->linkstate != (act_state = ( kaweth->intbuffer[STATE_OFFSET] | STATE_MASK) >> STATE_SHIFT)) {
- if (!act_state)
+ if (act_state)
netif_carrier_on(kaweth->net);
else
netif_carrier_off(kaweth->net);
diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
index f6bc6b3b333..4cbb408af72 100644
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -1517,6 +1517,26 @@ static void cdc_unbind (struct usbnet *dev, struct usb_interface *intf)
}
}
+#endif /* NEED_GENERIC_CDC */
+
+
+#ifdef CONFIG_USB_CDCETHER
+#define HAVE_HARDWARE
+
+/*-------------------------------------------------------------------------
+ *
+ * Communications Device Class, Ethernet Control model
+ *
+ * Takes two interfaces. The DATA interface is inactive till an altsetting
+ * is selected. Configuration data includes class descriptors.
+ *
+ * This should interop with whatever the 2.4 "CDCEther.c" driver
+ * (by Brad Hards) talked with.
+ *
+ *-------------------------------------------------------------------------*/
+
+#include <linux/ctype.h>
+
static void dumpspeed (struct usbnet *dev, __le32 *speeds)
{
@@ -1567,26 +1587,6 @@ static void cdc_status (struct usbnet *dev, struct urb *urb)
}
}
-#endif /* NEED_GENERIC_CDC */
-
-
-#ifdef CONFIG_USB_CDCETHER
-#define HAVE_HARDWARE
-
-/*-------------------------------------------------------------------------
- *
- * Communications Device Class, Ethernet Control model
- *
- * Takes two interfaces. The DATA interface is inactive till an altsetting
- * is selected. Configuration data includes class descriptors.
- *
- * This should interop with whatever the 2.4 "CDCEther.c" driver
- * (by Brad Hards) talked with.
- *
- *-------------------------------------------------------------------------*/
-
-#include <linux/ctype.h>
-
static u8 nibble (unsigned char c)
{
if (likely (isdigit (c)))
@@ -2765,7 +2765,7 @@ static int blan_mdlm_bind (struct usbnet *dev, struct usb_interface *intf)
}
/* expect bcdVersion 1.0, ignore */
if (memcmp(&desc->bGUID, blan_guid, 16)
- || memcmp(&desc->bGUID, blan_guid, 16) ) {
+ && memcmp(&desc->bGUID, safe_guid, 16) ) {
/* hey, this one might _really_ be MDLM! */
dev_dbg (&intf->dev, "MDLM guid\n");
goto bad_desc;
@@ -2797,11 +2797,13 @@ static int blan_mdlm_bind (struct usbnet *dev, struct usb_interface *intf)
* - bPad (ignored, for PADAFTER -- BLAN-only)
* bits are:
* - 0x01 -- Zaurus framing (add CRC)
- * - 0x02 -- PADBEFORE
- * - 0x04 -- PADAFTER
+ * - 0x02 -- PADBEFORE (CRC includes some padding)
+ * - 0x04 -- PADAFTER (some padding after CRC)
* - 0x08 -- "fermat" packet mangling (for hw bugs)
+ * the PADBEFORE appears not to matter; we interop
+ * with devices that use it and those that don't.
*/
- if (detail->bDetailData[1] != 0x01) {
+ if ((detail->bDetailData[1] & ~02) != 0x01) {
/* bmDataCapabilites == 0 would be fine too,
* but framing is minidriver-coupled for now.
*/
@@ -4071,9 +4073,6 @@ static const struct usb_device_id products [] = {
USB_DEVICE (0x8086, 0x07d3), // "blob" bootloader
.driver_info = (unsigned long) &blob_info,
}, {
- USB_DEVICE (0x22b8, 0x600c), // USBNET Motorola E680
- .driver_info = (unsigned long) &linuxdev_info,
-}, {
// Linux Ethernet/RNDIS gadget on pxa210/25x/26x
// e.g. Gumstix, current OpenZaurus, ...
USB_DEVICE_VER (0x0525, 0xa4a2, 0x0203, 0x0203),
diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
index bc798edf035..9438909e87a 100644
--- a/drivers/usb/serial/Kconfig
+++ b/drivers/usb/serial/Kconfig
@@ -455,6 +455,17 @@ config USB_SERIAL_XIRCOM
To compile this driver as a module, choose M here: the
module will be called keyspan_pda.
+config USB_SERIAL_OPTION
+ tristate "USB Option PCMCIA serial driver"
+ depends on USB_SERIAL && USB_OHCI_HCD && PCCARD
+ help
+ Say Y here if you want to use an Option card. This is a
+ GSM card, controlled by three serial ports which are connected
+ via an OHCI adapter located on a PC card.
+
+ To compile this driver as a module, choose M here: the
+ module will be called option.
+
config USB_SERIAL_OMNINET
tristate "USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)"
depends on USB_SERIAL && EXPERIMENTAL
diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile
index d56ff6d86cc..6c7cdcc99a9 100644
--- a/drivers/usb/serial/Makefile
+++ b/drivers/usb/serial/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_USB_SERIAL_KLSI) += kl5kusb105.o
obj-$(CONFIG_USB_SERIAL_KOBIL_SCT) += kobil_sct.o
obj-$(CONFIG_USB_SERIAL_MCT_U232) += mct_u232.o
obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o
+obj-$(CONFIG_USB_SERIAL_OPTION) += option.o
obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o
obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o
obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o
diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c
index 7e9bb63eb46..4ace9964fc6 100644
--- a/drivers/usb/serial/cp2101.c
+++ b/drivers/usb/serial/cp2101.c
@@ -7,6 +7,14 @@
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*
+ * Support to set flow control line levels using TIOCMGET and TIOCMSET
+ * thanks to Karl Hiramoto karl@hiramoto.org. RTSCTS hardware flow
+ * control thanks to Munir Nassar nassarmu@real-time.com
+ *
+ * Outstanding Issues:
+ * Buffers are not flushed when the port is opened.
+ * Multiple calls to write() may fail with "Resource temporarily unavailable"
+ *
*/
#include <linux/config.h>
@@ -24,7 +32,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v0.03"
+#define DRIVER_VERSION "v0.04"
#define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver"
/*
@@ -35,6 +43,9 @@ static void cp2101_cleanup(struct usb_serial_port*);
static void cp2101_close(struct usb_serial_port*, struct file*);
static void cp2101_get_termios(struct usb_serial_port*);
static void cp2101_set_termios(struct usb_serial_port*, struct termios*);
+static int cp2101_tiocmget (struct usb_serial_port *, struct file *);
+static int cp2101_tiocmset (struct usb_serial_port *, struct file *,
+ unsigned int, unsigned int);
static void cp2101_break_ctl(struct usb_serial_port*, int);
static int cp2101_startup (struct usb_serial *);
static void cp2101_shutdown(struct usb_serial*);
@@ -43,9 +54,10 @@ static void cp2101_shutdown(struct usb_serial*);
static int debug;
static struct usb_device_id id_table [] = {
- {USB_DEVICE(0x10c4, 0xea60) }, /*Silicon labs factory default*/
- {USB_DEVICE(0x10ab, 0x10c5) }, /*Siemens MC60 Cable*/
- { } /* Terminating Entry*/
+ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
+ { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */
+ { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
+ { } /* Terminating Entry */
};
MODULE_DEVICE_TABLE (usb, id_table);
@@ -70,32 +82,35 @@ static struct usb_serial_device_type cp2101_device = {
.close = cp2101_close,
.break_ctl = cp2101_break_ctl,
.set_termios = cp2101_set_termios,
+ .tiocmget = cp2101_tiocmget,
+ .tiocmset = cp2101_tiocmset,
.attach = cp2101_startup,
.shutdown = cp2101_shutdown,
};
-/*Config request types*/
+/* Config request types */
#define REQTYPE_HOST_TO_DEVICE 0x41
#define REQTYPE_DEVICE_TO_HOST 0xc1
-/*Config SET requests. To GET, add 1 to the request number*/
-#define CP2101_UART 0x00 /*Enable / Disable*/
-#define CP2101_BAUDRATE 0x01 /*(BAUD_RATE_GEN_FREQ / baudrate)*/
-#define CP2101_BITS 0x03 /*0x(0)(data bits)(parity)(stop bits)*/
-#define CP2101_BREAK 0x05 /*On / Off*/
-#define CP2101_DTRRTS 0x07 /*101 / 202 ???*/
-#define CP2101_CONFIG_16 0x13 /*16 bytes of config data ???*/
-#define CP2101_CONFIG_6 0x19 /*6 bytes of config data ???*/
+/* Config SET requests. To GET, add 1 to the request number */
+#define CP2101_UART 0x00 /* Enable / Disable */
+#define CP2101_BAUDRATE 0x01 /* (BAUD_RATE_GEN_FREQ / baudrate) */
+#define CP2101_BITS 0x03 /* 0x(0)(databits)(parity)(stopbits) */
+#define CP2101_BREAK 0x05 /* On / Off */
+#define CP2101_CONTROL 0x07 /* Flow control line states */
+#define CP2101_MODEMCTL 0x13 /* Modem controls */
+#define CP2101_CONFIG_6 0x19 /* 6 bytes of config data ??? */
-/*CP2101_UART*/
+/* CP2101_UART */
#define UART_ENABLE 0x0001
#define UART_DISABLE 0x0000
-/*CP2101_BAUDRATE*/
+/* CP2101_BAUDRATE */
#define BAUD_RATE_GEN_FREQ 0x384000
-/*CP2101_BITS*/
+/* CP2101_BITS */
#define BITS_DATA_MASK 0X0f00
+#define BITS_DATA_5 0X0500
#define BITS_DATA_6 0X0600
#define BITS_DATA_7 0X0700
#define BITS_DATA_8 0X0800
@@ -112,64 +127,137 @@ static struct usb_serial_device_type cp2101_device = {
#define BITS_STOP_1 0x0000
#define BITS_STOP_1_5 0x0001
#define BITS_STOP_2 0x0002
+
+/* CP2101_BREAK */
#define BREAK_ON 0x0000
#define BREAK_OFF 0x0001
+/* CP2101_CONTROL */
+#define CONTROL_DTR 0x0001
+#define CONTROL_RTS 0x0002
+#define CONTROL_CTS 0x0010
+#define CONTROL_DSR 0x0020
+#define CONTROL_RING 0x0040
+#define CONTROL_DCD 0x0080
+#define CONTROL_WRITE_DTR 0x0100
+#define CONTROL_WRITE_RTS 0x0200
-static int cp2101_get_config(struct usb_serial_port* port, u8 request)
+/*
+ * cp2101_get_config
+ * Reads from the CP2101 configuration registers
+ * 'size' is specified in bytes.
+ * 'data' is a pointer to a pre-allocated array of integers large
+ * enough to hold 'size' bytes (with 4 bytes to each integer)
+ */
+static int cp2101_get_config(struct usb_serial_port* port, u8 request,
+ unsigned int *data, int size)
{
struct usb_serial *serial = port->serial;
- unsigned char buf[4];
- unsigned int value;
- int result, i;
+ u32 *buf;
+ int result, i, length;
+
+ /* Number of integers required to contain the array */
+ length = (((size - 1) | 3) + 1)/4;
+
+ buf = kmalloc (length * sizeof(u32), GFP_KERNEL);
+ memset(buf, 0, length * sizeof(u32));
+
+ if (!buf) {
+ dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__);
+ return -ENOMEM;
+ }
- /*For get requests, the request number must be incremented*/
+ /* For get requests, the request number must be incremented */
request++;
- /*Issue the request, attempting to read 4 bytes*/
+ /* Issue the request, attempting to read 'size' bytes */
result = usb_control_msg (serial->dev,usb_rcvctrlpipe (serial->dev, 0),
request, REQTYPE_DEVICE_TO_HOST, 0x0000,
- 0, buf, 4, 300);
+ 0, buf, size, 300);
- if (result < 0) {
- dev_err(&port->dev, "%s - Unable to send config request, "
- "request=0x%x result=%d\n",
- __FUNCTION__, request, result);
- return result;
- }
+ /* Convert data into an array of integers */
+ for (i=0; i<length; i++)
+ data[i] = le32_to_cpu(buf[i]);
- /*Assemble each byte read into an integer value*/
- value = 0;
- for (i=0; i<4 && i<result; i++)
- value |= (buf[i] << (i * 8));
+ kfree(buf);
- dbg( " %s - request=0x%x result=%d value=0x%x",
- __FUNCTION__, request, result, value);
+ if (result != size) {
+ dev_err(&port->dev, "%s - Unable to send config request, "
+ "request=0x%x size=%d result=%d\n",
+ __FUNCTION__, request, size, result);
+ return -EPROTO;
+ }
- return value;
+ return 0;
}
-static int cp2101_set_config(struct usb_serial_port* port, u8 request, u16 value)
+/*
+ * cp2101_set_config
+ * Writes to the CP2101 configuration registers
+ * Values less than 16 bits wide are sent directly
+ * 'size' is specified in bytes.
+ */
+static int cp2101_set_config(struct usb_serial_port* port, u8 request,
+ unsigned int *data, int size)
{
struct usb_serial *serial = port->serial;
- int result;
- result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0),
- request, REQTYPE_HOST_TO_DEVICE, value,
- 0, NULL, 0, 300);
+ u32 *buf;
+ int result, i, length;
- if (result <0) {
- dev_err(&port->dev, "%s - Unable to send config request, "
- "request=0x%x value=0x%x result=%d\n",
- __FUNCTION__, request, value, result);
- return result;
+ /* Number of integers required to contain the array */
+ length = (((size - 1) | 3) + 1)/4;
+
+ buf = kmalloc(length * sizeof(u32), GFP_KERNEL);
+ if (!buf) {
+ dev_err(&port->dev, "%s - out of memory.\n",
+ __FUNCTION__);
+ return -ENOMEM;
+ }
+
+ /* Array of integers into bytes */
+ for (i = 0; i < length; i++)
+ buf[i] = cpu_to_le32(data[i]);
+
+ if (size > 2) {
+ result = usb_control_msg (serial->dev,
+ usb_sndctrlpipe(serial->dev, 0),
+ request, REQTYPE_HOST_TO_DEVICE, 0x0000,
+ 0, buf, size, 300);
+ } else {
+ result = usb_control_msg (serial->dev,
+ usb_sndctrlpipe(serial->dev, 0),
+ request, REQTYPE_HOST_TO_DEVICE, data[0],
+ 0, NULL, 0, 300);
}
- dbg(" %s - request=0x%x value=0x%x result=%d",
- __FUNCTION__, request, value, result);
+ kfree(buf);
+
+ if ((size > 2 && result != size) || result < 0) {
+ dev_err(&port->dev, "%s - Unable to send request, "
+ "request=0x%x size=%d result=%d\n",
+ __FUNCTION__, request, size, result);
+ return -EPROTO;
+ }
+ /* Single data value */
+ result = usb_control_msg (serial->dev,
+ usb_sndctrlpipe(serial->dev, 0),
+ request, REQTYPE_HOST_TO_DEVICE, data[0],
+ 0, NULL, 0, 300);
return 0;
}
+/*
+ * cp2101_set_config_single
+ * Convenience function for calling cp2101_set_config on single data values
+ * without requiring an integer pointer
+ */
+static inline int cp2101_set_config_single(struct usb_serial_port* port,
+ u8 request, unsigned int data)
+{
+ return cp2101_set_config(port, request, &data, 2);
+}
+
static int cp2101_open (struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
@@ -177,7 +265,7 @@ static int cp2101_open (struct usb_serial_port *port, struct file *filp)
dbg("%s - port %d", __FUNCTION__, port->number);
- if (cp2101_set_config(port, CP2101_UART, UART_ENABLE)) {
+ if (cp2101_set_config_single(port, CP2101_UART, UART_ENABLE)) {
dev_err(&port->dev, "%s - Unable to enable UART\n",
__FUNCTION__);
return -EPROTO;
@@ -198,9 +286,12 @@ static int cp2101_open (struct usb_serial_port *port, struct file *filp)
return result;
}
- /*Configure the termios structure*/
+ /* Configure the termios structure */
cp2101_get_termios(port);
+ /* Set the DTR and RTS pins low */
+ cp2101_tiocmset(port, NULL, TIOCM_DTR | TIOCM_RTS, 0);
+
return 0;
}
@@ -228,16 +319,18 @@ static void cp2101_close (struct usb_serial_port *port, struct file * filp)
usb_kill_urb(port->write_urb);
usb_kill_urb(port->read_urb);
- cp2101_set_config(port, CP2101_UART, UART_DISABLE);
+ cp2101_set_config_single(port, CP2101_UART, UART_DISABLE);
}
-/* cp2101_get_termios*/
-/* Reads the baud rate, data bits, parity and stop bits from the device*/
-/* Corrects any unsupported values*/
-/* Configures the termios structure to reflect the state of the device*/
+/*
+ * cp2101_get_termios
+ * Reads the baud rate, data bits, parity, stop bits and flow control mode
+ * from the device, corrects any unsupported values, and configures the
+ * termios structure to reflect the state of the device
+ */
static void cp2101_get_termios (struct usb_serial_port *port)
{
- unsigned int cflag;
+ unsigned int cflag, modem_ctl[4];
int baud;
int bits;
@@ -249,15 +342,16 @@ static void cp2101_get_termios (struct usb_serial_port *port)
}
cflag = port->tty->termios->c_cflag;
- baud = cp2101_get_config(port, CP2101_BAUDRATE);
- /*Convert to baudrate*/
+ cp2101_get_config(port, CP2101_BAUDRATE, &baud, 2);
+ /* Convert to baudrate */
if (baud)
baud = BAUD_RATE_GEN_FREQ / baud;
dbg("%s - baud rate = %d", __FUNCTION__, baud);
cflag &= ~CBAUD;
switch (baud) {
- /* The baud rates which are commented out below
+ /*
+ * The baud rates which are commented out below
* appear to be supported by the device
* but are non-standard
*/
@@ -284,14 +378,18 @@ static void cp2101_get_termios (struct usb_serial_port *port)
dbg("%s - Baud rate is not supported, "
"using 9600 baud", __FUNCTION__);
cflag |= B9600;
- cp2101_set_config(port, CP2101_BAUDRATE,
+ cp2101_set_config_single(port, CP2101_BAUDRATE,
(BAUD_RATE_GEN_FREQ/9600));
break;
}
- bits = cp2101_get_config(port, CP2101_BITS);
+ cp2101_get_config(port, CP2101_BITS, &bits, 2);
cflag &= ~CSIZE;
switch(bits & BITS_DATA_MASK) {
+ case BITS_DATA_5:
+ dbg("%s - data bits = 5", __FUNCTION__);
+ cflag |= CS5;
+ break;
case BITS_DATA_6:
dbg("%s - data bits = 6", __FUNCTION__);
cflag |= CS6;
@@ -310,7 +408,7 @@ static void cp2101_get_termios (struct usb_serial_port *port)
cflag |= CS8;
bits &= ~BITS_DATA_MASK;
bits |= BITS_DATA_8;
- cp2101_set_config(port, CP2101_BITS, bits);
+ cp2101_set_config(port, CP2101_BITS, &bits, 2);
break;
default:
dbg("%s - Unknown number of data bits, "
@@ -318,7 +416,7 @@ static void cp2101_get_termios (struct usb_serial_port *port)
cflag |= CS8;
bits &= ~BITS_DATA_MASK;
bits |= BITS_DATA_8;
- cp2101_set_config(port, CP2101_BITS, bits);
+ cp2101_set_config(port, CP2101_BITS, &bits, 2);
break;
}
@@ -341,21 +439,21 @@ static void cp2101_get_termios (struct usb_serial_port *port)
"disabling parity)", __FUNCTION__);
cflag &= ~PARENB;
bits &= ~BITS_PARITY_MASK;
- cp2101_set_config(port, CP2101_BITS, bits);
+ cp2101_set_config(port, CP2101_BITS, &bits, 2);
break;
case BITS_PARITY_SPACE:
dbg("%s - parity = SPACE (not supported, "
"disabling parity)", __FUNCTION__);
cflag &= ~PARENB;
bits &= ~BITS_PARITY_MASK;
- cp2101_set_config(port, CP2101_BITS, bits);
+ cp2101_set_config(port, CP2101_BITS, &bits, 2);
break;
default:
dbg("%s - Unknown parity mode, "
"disabling parity", __FUNCTION__);
cflag &= ~PARENB;
bits &= ~BITS_PARITY_MASK;
- cp2101_set_config(port, CP2101_BITS, bits);
+ cp2101_set_config(port, CP2101_BITS, &bits, 2);
break;
}
@@ -366,9 +464,9 @@ static void cp2101_get_termios (struct usb_serial_port *port)
break;
case BITS_STOP_1_5:
dbg("%s - stop bits = 1.5 (not supported, "
- "using 1 stop bit", __FUNCTION__);
+ "using 1 stop bit)", __FUNCTION__);
bits &= ~BITS_STOP_MASK;
- cp2101_set_config(port, CP2101_BITS, bits);
+ cp2101_set_config(port, CP2101_BITS, &bits, 2);
break;
case BITS_STOP_2:
dbg("%s - stop bits = 2", __FUNCTION__);
@@ -378,10 +476,19 @@ static void cp2101_get_termios (struct usb_serial_port *port)
dbg("%s - Unknown number of stop bits, "
"using 1 stop bit", __FUNCTION__);
bits &= ~BITS_STOP_MASK;
- cp2101_set_config(port, CP2101_BITS, bits);
+ cp2101_set_config(port, CP2101_BITS, &bits, 2);
break;
}
+ cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16);
+ if (modem_ctl[0] & 0x0008) {
+ dbg("%s - flow control = CRTSCTS", __FUNCTION__);
+ cflag |= CRTSCTS;
+ } else {
+ dbg("%s - flow control = NONE", __FUNCTION__);
+ cflag &= ~CRTSCTS;
+ }
+
port->tty->termios->c_cflag = cflag;
}
@@ -389,8 +496,8 @@ static void cp2101_set_termios (struct usb_serial_port *port,
struct termios *old_termios)
{
unsigned int cflag, old_cflag=0;
- int baud=0;
- int bits;
+ int baud=0, bits;
+ unsigned int modem_ctl[4];
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -400,7 +507,7 @@ static void cp2101_set_termios (struct usb_serial_port *port,
}
cflag = port->tty->termios->c_cflag;
- /* check that they really want us to change something */
+ /* Check that they really want us to change something */
if (old_termios) {
if ((cflag == old_termios->c_cflag) &&
(RELEVANT_IFLAG(port->tty->termios->c_iflag)
@@ -415,7 +522,8 @@ static void cp2101_set_termios (struct usb_serial_port *port,
/* If the baud rate is to be updated*/
if ((cflag & CBAUD) != (old_cflag & CBAUD)) {
switch (cflag & CBAUD) {
- /* The baud rates which are commented out below
+ /*
+ * The baud rates which are commented out below
* appear to be supported by the device
* but are non-standard
*/
@@ -448,18 +556,22 @@ static void cp2101_set_termios (struct usb_serial_port *port,
if (baud) {
dbg("%s - Setting baud rate to %d baud", __FUNCTION__,
baud);
- if (cp2101_set_config(port, CP2101_BAUDRATE,
+ if (cp2101_set_config_single(port, CP2101_BAUDRATE,
(BAUD_RATE_GEN_FREQ / baud)))
dev_err(&port->dev, "Baud rate requested not "
"supported by device\n");
}
}
- /*If the number of data bits is to be updated*/
+ /* If the number of data bits is to be updated */
if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
- bits = cp2101_get_config(port, CP2101_BITS);
+ cp2101_get_config(port, CP2101_BITS, &bits, 2);
bits &= ~BITS_DATA_MASK;
switch (cflag & CSIZE) {
+ case CS5:
+ bits |= BITS_DATA_5;
+ dbg("%s - data bits = 5", __FUNCTION__);
+ break;
case CS6:
bits |= BITS_DATA_6;
dbg("%s - data bits = 6", __FUNCTION__);
@@ -483,13 +595,13 @@ static void cp2101_set_termios (struct usb_serial_port *port,
bits |= BITS_DATA_8;
break;
}
- if (cp2101_set_config(port, CP2101_BITS, bits))
+ if (cp2101_set_config(port, CP2101_BITS, &bits, 2))
dev_err(&port->dev, "Number of data bits requested "
"not supported by device\n");
}
if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))) {
- bits = cp2101_get_config(port, CP2101_BITS);
+ cp2101_get_config(port, CP2101_BITS, &bits, 2);
bits &= ~BITS_PARITY_MASK;
if (cflag & PARENB) {
if (cflag & PARODD) {
@@ -500,13 +612,13 @@ static void cp2101_set_termios (struct usb_serial_port *port,
dbg("%s - parity = EVEN", __FUNCTION__);
}
}
- if (cp2101_set_config(port, CP2101_BITS, bits))
+ if (cp2101_set_config(port, CP2101_BITS, &bits, 2))
dev_err(&port->dev, "Parity mode not supported "
"by device\n");
}
if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) {
- bits = cp2101_get_config(port, CP2101_BITS);
+ cp2101_get_config(port, CP2101_BITS, &bits, 2);
bits &= ~BITS_STOP_MASK;
if (cflag & CSTOPB) {
bits |= BITS_STOP_2;
@@ -515,15 +627,90 @@ static void cp2101_set_termios (struct usb_serial_port *port,
bits |= BITS_STOP_1;
dbg("%s - stop bits = 1", __FUNCTION__);
}
- if (cp2101_set_config(port, CP2101_BITS, bits))
+ if (cp2101_set_config(port, CP2101_BITS, &bits, 2))
dev_err(&port->dev, "Number of stop bits requested "
"not supported by device\n");
}
+
+ if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {
+ cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16);
+ dbg("%s - read modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x",
+ __FUNCTION__, modem_ctl[0], modem_ctl[1],
+ modem_ctl[2], modem_ctl[3]);
+
+ if (cflag & CRTSCTS) {
+ modem_ctl[0] &= ~0x7B;
+ modem_ctl[0] |= 0x09;
+ modem_ctl[1] = 0x80;
+ dbg("%s - flow control = CRTSCTS", __FUNCTION__);
+ } else {
+ modem_ctl[0] &= ~0x7B;
+ modem_ctl[0] |= 0x01;
+ modem_ctl[1] |= 0x40;
+ dbg("%s - flow control = NONE", __FUNCTION__);
+ }
+
+ dbg("%s - write modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x",
+ __FUNCTION__, modem_ctl[0], modem_ctl[1],
+ modem_ctl[2], modem_ctl[3]);
+ cp2101_set_config(port, CP2101_MODEMCTL, modem_ctl, 16);
+ }
+
+}
+
+static int cp2101_tiocmset (struct usb_serial_port *port, struct file *file,
+ unsigned int set, unsigned int clear)
+{
+ int control = 0;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ if (set & TIOCM_RTS) {
+ control |= CONTROL_RTS;
+ control |= CONTROL_WRITE_RTS;
+ }
+ if (set & TIOCM_DTR) {
+ control |= CONTROL_DTR;
+ control |= CONTROL_WRITE_DTR;
+ }
+ if (clear & TIOCM_RTS) {
+ control &= ~CONTROL_RTS;
+ control |= CONTROL_WRITE_RTS;
+ }
+ if (clear & TIOCM_DTR) {
+ control &= ~CONTROL_DTR;
+ control |= CONTROL_WRITE_DTR;
+ }
+
+ dbg("%s - control = 0x%.4x", __FUNCTION__, control);
+
+ return cp2101_set_config(port, CP2101_CONTROL, &control, 2);
+
+}
+
+static int cp2101_tiocmget (struct usb_serial_port *port, struct file *file)
+{
+ int control, result;
+
+ dbg("%s - port %d", __FUNCTION__, port->number);
+
+ cp2101_get_config(port, CP2101_CONTROL, &control, 1);
+
+ result = ((control & CONTROL_DTR) ? TIOCM_DTR : 0)
+ |((control & CONTROL_RTS) ? TIOCM_RTS : 0)
+ |((control & CONTROL_CTS) ? TIOCM_CTS : 0)
+ |((control & CONTROL_DSR) ? TIOCM_DSR : 0)
+ |((control & CONTROL_RING)? TIOCM_RI : 0)
+ |((control & CONTROL_DCD) ? TIOCM_CD : 0);
+
+ dbg("%s - control = 0x%.2x", __FUNCTION__, control);
+
+ return result;
}
static void cp2101_break_ctl (struct usb_serial_port *port, int break_state)
{
- u16 state;
+ int state;
dbg("%s - port %d", __FUNCTION__, port->number);
if (break_state == 0)
@@ -532,12 +719,12 @@ static void cp2101_break_ctl (struct usb_serial_port *port, int break_state)
state = BREAK_ON;
dbg("%s - turning break %s", __FUNCTION__,
state==BREAK_OFF ? "off" : "on");
- cp2101_set_config(port, CP2101_BREAK, state);
+ cp2101_set_config(port, CP2101_BREAK, &state, 2);
}
static int cp2101_startup (struct usb_serial *serial)
{
- /*CP2101 buffers behave strangely unless device is reset*/
+ /* CP2101 buffers behave strangely unless device is reset */
usb_reset_device(serial->dev);
return 0;
}
@@ -548,7 +735,7 @@ static void cp2101_shutdown (struct usb_serial *serial)
dbg("%s", __FUNCTION__);
- /* stop reads and writes on all ports */
+ /* Stop reads and writes on all ports */
for (i=0; i < serial->num_ports; ++i) {
cp2101_cleanup(serial->port[i]);
}
@@ -560,16 +747,16 @@ static int __init cp2101_init (void)
retval = usb_serial_register(&cp2101_device);
if (retval)
- return retval; /*Failed to register*/
+ return retval; /* Failed to register */
retval = usb_register(&cp2101_driver);
if (retval) {
- /*Failed to register*/
+ /* Failed to register */
usb_serial_deregister(&cp2101_device);
return retval;
}
- /*Success*/
+ /* Success */
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
}
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
index f34a9bb6a21..012e63e0580 100644
--- a/drivers/usb/serial/cypress_m8.c
+++ b/drivers/usb/serial/cypress_m8.c
@@ -89,6 +89,7 @@ static int interval;
static struct usb_device_id id_table_earthmate [] = {
{ USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) },
+ { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) },
{ } /* Terminating entry */
};
@@ -99,6 +100,7 @@ static struct usb_device_id id_table_cyphidcomrs232 [] = {
static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) },
+ { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) },
{ USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
{ } /* Terminating entry */
};
diff --git a/drivers/usb/serial/cypress_m8.h b/drivers/usb/serial/cypress_m8.h
index 1012ee6b19c..1fa119efe41 100644
--- a/drivers/usb/serial/cypress_m8.h
+++ b/drivers/usb/serial/cypress_m8.h
@@ -13,6 +13,7 @@
/* DeLorme Earthmate USB - a GPS device */
#define VENDOR_ID_DELORME 0x1163
#define PRODUCT_ID_EARTHMATEUSB 0x0100
+#define PRODUCT_ID_EARTHMATEUSB_LT20 0x0200
/* Cypress HID->COM RS232 Adapter */
#define VENDOR_ID_CYPRESS 0x04b4
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 52394f08a94..d882fa3ad19 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -264,7 +264,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.4.1"
+#define DRIVER_VERSION "v1.4.2"
#define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>"
#define DRIVER_DESC "USB FTDI Serial Converters Driver"
@@ -364,6 +364,7 @@ static struct usb_device_id id_table_8U232AM [] = {
{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_3, 0, 0x3ff) },
{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_4, 0, 0x3ff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0, 0x3ff) },
+ { USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UM100_PID, 0, 0x3ff) },
{ USB_DEVICE_VER(FTDI_VID, INSIDE_ACCESSO, 0, 0x3ff) },
{ USB_DEVICE_VER(INTREPID_VID, INTREPID_VALUECAN_PID, 0, 0x3ff) },
{ USB_DEVICE_VER(INTREPID_VID, INTREPID_NEOVI_PID, 0, 0x3ff) },
@@ -475,6 +476,7 @@ static struct usb_device_id id_table_FT232BM [] = {
{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88E_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88F_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0x400, 0xffff) },
+ { USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UM100_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, LINX_SDMUSBQSS_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, LINX_MASTERDEVEL2_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_0_PID, 0x400, 0xffff) },
@@ -618,6 +620,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88E_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88F_PID, 0x400, 0xffff) },
{ USB_DEVICE(FTDI_VID, FTDI_ELV_UO100_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_ELV_UM100_PID) },
{ USB_DEVICE_VER(FTDI_VID, LINX_SDMUSBQSS_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, LINX_MASTERDEVEL2_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_0_PID, 0x400, 0xffff) },
@@ -684,6 +687,8 @@ struct ftdi_private {
char prev_status, diff_status; /* Used for TIOCMIWAIT */
__u8 rx_flags; /* receive state flags (throttling) */
spinlock_t rx_lock; /* spinlock for receive state */
+ struct work_struct rx_work;
+ int rx_processed;
__u16 interface; /* FT2232C port interface (0 for FT232/245) */
@@ -714,7 +719,7 @@ static int ftdi_write_room (struct usb_serial_port *port);
static int ftdi_chars_in_buffer (struct usb_serial_port *port);
static void ftdi_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
static void ftdi_read_bulk_callback (struct urb *urb, struct pt_regs *regs);
-static void ftdi_process_read (struct usb_serial_port *port);
+static void ftdi_process_read (void *param);
static void ftdi_set_termios (struct usb_serial_port *port, struct termios * old);
static int ftdi_tiocmget (struct usb_serial_port *port, struct file *file);
static int ftdi_tiocmset (struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear);
@@ -1213,7 +1218,7 @@ check_and_exit:
* ***************************************************************************
*/
-static ssize_t show_latency_timer(struct device *dev, char *buf)
+static ssize_t show_latency_timer(struct device *dev, struct device_attribute *attr, char *buf)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1240,7 +1245,7 @@ static ssize_t show_latency_timer(struct device *dev, char *buf)
}
/* Write a new value of the latency timer, in units of milliseconds. */
-static ssize_t store_latency_timer(struct device *dev, const char *valbuf,
+static ssize_t store_latency_timer(struct device *dev, struct device_attribute *attr, const char *valbuf,
size_t count)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
@@ -1271,7 +1276,7 @@ static ssize_t store_latency_timer(struct device *dev, const char *valbuf,
/* Write an event character directly to the FTDI register. The ASCII
value is in the low 8 bits, with the enable bit in the 9th bit. */
-static ssize_t store_event_char(struct device *dev, const char *valbuf,
+static ssize_t store_event_char(struct device *dev, struct device_attribute *attr, const char *valbuf,
size_t count)
{
struct usb_serial_port *port = to_usb_serial_port(dev);
@@ -1384,6 +1389,8 @@ static int ftdi_common_startup (struct usb_serial *serial)
port->read_urb->transfer_buffer_length = BUFSZ;
}
+ INIT_WORK(&priv->rx_work, ftdi_process_read, port);
+
/* Free port's existing write urb and transfer buffer. */
if (port->write_urb) {
usb_free_urb (port->write_urb);
@@ -1614,6 +1621,7 @@ static int ftdi_open (struct usb_serial_port *port, struct file *filp)
spin_unlock_irqrestore(&priv->rx_lock, flags);
/* Start reading from the device */
+ priv->rx_processed = 0;
usb_fill_bulk_urb(port->read_urb, dev,
usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
@@ -1664,6 +1672,10 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp)
err("Error from RTS LOW urb");
}
} /* Note change no line if hupcl is off */
+
+ /* cancel any scheduled reading */
+ cancel_delayed_work(&priv->rx_work);
+ flush_scheduled_work();
/* shutdown our bulk read */
if (port->read_urb)
@@ -1859,23 +1871,14 @@ static void ftdi_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
return;
}
- /* If throttled, delay receive processing until unthrottled. */
- spin_lock(&priv->rx_lock);
- if (priv->rx_flags & THROTTLED) {
- dbg("Deferring read urb processing until unthrottled");
- priv->rx_flags |= ACTUALLY_THROTTLED;
- spin_unlock(&priv->rx_lock);
- return;
- }
- spin_unlock(&priv->rx_lock);
-
ftdi_process_read(port);
} /* ftdi_read_bulk_callback */
-static void ftdi_process_read (struct usb_serial_port *port)
+static void ftdi_process_read (void *param)
{ /* ftdi_process_read */
+ struct usb_serial_port *port = (struct usb_serial_port*)param;
struct urb *urb;
struct tty_struct *tty;
struct ftdi_private *priv;
@@ -1886,6 +1889,7 @@ static void ftdi_process_read (struct usb_serial_port *port)
int result;
int need_flip;
int packet_offset;
+ unsigned long flags;
dbg("%s - port %d", __FUNCTION__, port->number);
@@ -1912,12 +1916,18 @@ static void ftdi_process_read (struct usb_serial_port *port)
data = urb->transfer_buffer;
- /* The first two bytes of every read packet are status */
- if (urb->actual_length > 2) {
- usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+ if (priv->rx_processed) {
+ dbg("%s - already processed: %d bytes, %d remain", __FUNCTION__,
+ priv->rx_processed,
+ urb->actual_length - priv->rx_processed);
} else {
- dbg("Status only: %03oo %03oo",data[0],data[1]);
- }
+ /* The first two bytes of every read packet are status */
+ if (urb->actual_length > 2) {
+ usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+ } else {
+ dbg("Status only: %03oo %03oo",data[0],data[1]);
+ }
+ }
/* TO DO -- check for hung up line and handle appropriately: */
@@ -1926,8 +1936,12 @@ static void ftdi_process_read (struct usb_serial_port *port)
/* if CD is dropped and the line is not CLOCAL then we should hangup */
need_flip = 0;
- for (packet_offset=0; packet_offset < urb->actual_length; packet_offset += PKTSZ) {
+ for (packet_offset = priv->rx_processed; packet_offset < urb->actual_length; packet_offset += PKTSZ) {
+ int length;
+
/* Compare new line status to the old one, signal if different */
+ /* N.B. packet may be processed more than once, but differences
+ * are only processed once. */
if (priv != NULL) {
char new_status = data[packet_offset+0] & FTDI_STATUS_B0_MASK;
if (new_status != priv->prev_status) {
@@ -1937,6 +1951,35 @@ static void ftdi_process_read (struct usb_serial_port *port)
}
}
+ length = min(PKTSZ, urb->actual_length-packet_offset)-2;
+ if (length < 0) {
+ err("%s - bad packet length: %d", __FUNCTION__, length+2);
+ length = 0;
+ }
+
+ /* have to make sure we don't overflow the buffer
+ with tty_insert_flip_char's */
+ if (tty->flip.count+length > TTY_FLIPBUF_SIZE) {
+ tty_flip_buffer_push(tty);
+ need_flip = 0;
+
+ if (tty->flip.count != 0) {
+ /* flip didn't work, this happens when ftdi_process_read() is
+ * called from ftdi_unthrottle, because TTY_DONT_FLIP is set */
+ dbg("%s - flip buffer push failed", __FUNCTION__);
+ break;
+ }
+ }
+ if (priv->rx_flags & THROTTLED) {
+ dbg("%s - throttled", __FUNCTION__);
+ break;
+ }
+ if (tty->ldisc.receive_room(tty)-tty->flip.count < length) {
+ /* break out & wait for throttling/unthrottling to happen */
+ dbg("%s - receive room low", __FUNCTION__);
+ break;
+ }
+
/* Handle errors and break */
error_flag = TTY_NORMAL;
/* Although the device uses a bitmask and hence can have multiple */
@@ -1959,13 +2002,8 @@ static void ftdi_process_read (struct usb_serial_port *port)
error_flag = TTY_FRAME;
dbg("FRAMING error");
}
- if (urb->actual_length > packet_offset + 2) {
- for (i = 2; (i < PKTSZ) && ((i+packet_offset) < urb->actual_length); ++i) {
- /* have to make sure we don't overflow the buffer
- with tty_insert_flip_char's */
- if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
- tty_flip_buffer_push(tty);
- }
+ if (length > 0) {
+ for (i = 2; i < length+2; i++) {
/* Note that the error flag is duplicated for
every character received since we don't know
which character it applied to */
@@ -2002,6 +2040,35 @@ static void ftdi_process_read (struct usb_serial_port *port)
tty_flip_buffer_push(tty);
}
+ if (packet_offset < urb->actual_length) {
+ /* not completely processed - record progress */
+ priv->rx_processed = packet_offset;
+ dbg("%s - incomplete, %d bytes processed, %d remain",
+ __FUNCTION__, packet_offset,
+ urb->actual_length - packet_offset);
+ /* check if we were throttled while processing */
+ spin_lock_irqsave(&priv->rx_lock, flags);
+ if (priv->rx_flags & THROTTLED) {
+ priv->rx_flags |= ACTUALLY_THROTTLED;
+ spin_unlock_irqrestore(&priv->rx_lock, flags);
+ dbg("%s - deferring remainder until unthrottled",
+ __FUNCTION__);
+ return;
+ }
+ spin_unlock_irqrestore(&priv->rx_lock, flags);
+ /* if the port is closed stop trying to read */
+ if (port->open_count > 0){
+ /* delay processing of remainder */
+ schedule_delayed_work(&priv->rx_work, 1);
+ } else {
+ dbg("%s - port is closed", __FUNCTION__);
+ }
+ return;
+ }
+
+ /* urb is completely processed */
+ priv->rx_processed = 0;
+
/* if the port is closed stop trying to read */
if (port->open_count > 0){
/* Continue trying to always read */
@@ -2441,7 +2508,7 @@ static void ftdi_unthrottle (struct usb_serial_port *port)
spin_unlock_irqrestore(&priv->rx_lock, flags);
if (actually_throttled)
- ftdi_process_read(port);
+ schedule_work(&priv->rx_work);
}
static int __init ftdi_init (void)
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index a52bb13a9ce..8866376823a 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -144,6 +144,8 @@
/* ELV USB Module UO100 (PID sent by Stefan Frings) */
#define FTDI_ELV_UO100_PID 0xFB58 /* Product Id */
+/* ELV USB Module UM100 (PID sent by Arnim Laeuger) */
+#define FTDI_ELV_UM100_PID 0xFB5A /* Product Id */
/*
* Definitions for ID TECH (www.idt-net.com) devices
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
new file mode 100644
index 00000000000..b722175f108
--- /dev/null
+++ b/drivers/usb/serial/option.c
@@ -0,0 +1,729 @@
+/*
+ Option Card (PCMCIA to) USB to Serial Driver
+
+ Copyright (C) 2005 Matthias Urlichs <smurf@smurf.noris.de>
+
+ This driver is free software; you can redistribute it and/or modify
+ it under the terms of Version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ Portions copied from the Keyspan driver by Hugh Blemings <hugh@blemings.org>
+
+ History:
+
+ 2005-05-19 v0.1 Initial version, based on incomplete docs
+ and analysis of misbehavior of the standard driver
+ 2005-05-20 v0.2 Extended the input buffer to avoid losing
+ random 64-byte chunks of data
+ 2005-05-21 v0.3 implemented chars_in_buffer()
+ turned on low_latency
+ simplified the code somewhat
+*/
+#define DRIVER_VERSION "v0.3"
+#define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>"
+#define DRIVER_DESC "Option Card (PC-Card to) USB to Serial Driver"
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/jiffies.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include "usb-serial.h"
+
+/* Function prototypes */
+static int option_open (struct usb_serial_port *port, struct file *filp);
+static void option_close (struct usb_serial_port *port, struct file *filp);
+static int option_startup (struct usb_serial *serial);
+static void option_shutdown (struct usb_serial *serial);
+static void option_rx_throttle (struct usb_serial_port *port);
+static void option_rx_unthrottle (struct usb_serial_port *port);
+static int option_write_room (struct usb_serial_port *port);
+
+static void option_instat_callback(struct urb *urb, struct pt_regs *regs);
+
+
+static int option_write (struct usb_serial_port *port,
+ const unsigned char *buf, int count);
+
+static int option_chars_in_buffer (struct usb_serial_port *port);
+static int option_ioctl (struct usb_serial_port *port, struct file *file,
+ unsigned int cmd, unsigned long arg);
+static void option_set_termios (struct usb_serial_port *port,
+ struct termios *old);
+static void option_break_ctl (struct usb_serial_port *port, int break_state);
+static int option_tiocmget (struct usb_serial_port *port, struct file *file);
+static int option_tiocmset (struct usb_serial_port *port, struct file *file,
+ unsigned int set, unsigned int clear);
+static int option_send_setup (struct usb_serial_port *port);
+
+/* Vendor and product IDs */
+#define OPTION_VENDOR_ID 0x0AF0
+
+#define OPTION_PRODUCT_OLD 0x5000
+#define OPTION_PRODUCT_WLAN 0x6000
+
+static struct usb_device_id option_ids[] = {
+ { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) },
+ { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_WLAN) },
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, option_ids);
+
+static struct usb_driver option_driver = {
+ .owner = THIS_MODULE,
+ .name = "option",
+ .probe = usb_serial_probe,
+ .disconnect = usb_serial_disconnect,
+ .id_table = option_ids,
+};
+
+/* The card has three separate interfaces, wich the serial driver
+ * recognizes separately, thus num_port=1.
+ */
+static struct usb_serial_device_type option_3port_device = {
+ .owner = THIS_MODULE,
+ .name = "Option 3-port card",
+ .short_name = "option",
+ .id_table = option_ids,
+ .num_interrupt_in = NUM_DONT_CARE,
+ .num_bulk_in = NUM_DONT_CARE,
+ .num_bulk_out = NUM_DONT_CARE,
+ .num_ports = 1, /* 3 */
+ .open = option_open,
+ .close = option_close,
+ .write = option_write,
+ .write_room = option_write_room,
+ .chars_in_buffer = option_chars_in_buffer,
+ .throttle = option_rx_throttle,
+ .unthrottle = option_rx_unthrottle,
+ .ioctl = option_ioctl,
+ .set_termios = option_set_termios,
+ .break_ctl = option_break_ctl,
+ .tiocmget = option_tiocmget,
+ .tiocmset = option_tiocmset,
+ .attach = option_startup,
+ .shutdown = option_shutdown,
+ .read_int_callback = option_instat_callback,
+};
+
+static int debug;
+
+/* per port private data */
+
+#define N_IN_URB 4
+#define N_OUT_URB 1
+#define IN_BUFLEN 1024
+#define OUT_BUFLEN 1024
+
+struct option_port_private {
+ /* Input endpoints and buffer for this port */
+ struct urb *in_urbs[N_IN_URB];
+ char in_buffer[N_IN_URB][IN_BUFLEN];
+ /* Output endpoints and buffer for this port */
+ struct urb *out_urbs[N_OUT_URB];
+ char out_buffer[N_OUT_URB][OUT_BUFLEN];
+
+ /* Settings for the port */
+ int rts_state; /* Handshaking pins (outputs) */
+ int dtr_state;
+ int cts_state; /* Handshaking pins (inputs) */
+ int dsr_state;
+ int dcd_state;
+ int ri_state;
+ // int break_on;
+
+ unsigned long tx_start_time[N_OUT_URB];
+};
+
+
+/* Functions used by new usb-serial code. */
+static int __init
+option_init (void)
+{
+ int retval;
+ retval = usb_serial_register(&option_3port_device);
+ if (retval)
+ goto failed_3port_device_register;
+ retval = usb_register(&option_driver);
+ if (retval)
+ goto failed_driver_register;
+
+ info(DRIVER_DESC ": " DRIVER_VERSION);
+
+ return 0;
+
+failed_driver_register:
+ usb_serial_deregister (&option_3port_device);
+failed_3port_device_register:
+ return retval;
+}
+
+static void __exit
+option_exit (void)
+{
+ usb_deregister (&option_driver);
+ usb_serial_deregister (&option_3port_device);
+}
+
+module_init(option_init);
+module_exit(option_exit);
+
+static void
+option_rx_throttle (struct usb_serial_port *port)
+{
+ dbg("%s", __FUNCTION__);
+}
+
+
+static void
+option_rx_unthrottle (struct usb_serial_port *port)
+{
+ dbg("%s", __FUNCTION__);
+}
+
+
+static void
+option_break_ctl (struct usb_serial_port *port, int break_state)
+{
+ /* Unfortunately, I don't know how to send a break */
+ dbg("%s", __FUNCTION__);
+}
+
+
+static void
+option_set_termios (struct usb_serial_port *port,
+ struct termios *old_termios)
+{
+ dbg("%s", __FUNCTION__);
+
+ option_send_setup(port);
+}
+
+static int
+option_tiocmget(struct usb_serial_port *port, struct file *file)
+{
+ unsigned int value;
+ struct option_port_private *portdata;
+
+ portdata = usb_get_serial_port_data(port);
+
+ value = ((portdata->rts_state) ? TIOCM_RTS : 0) |
+ ((portdata->dtr_state) ? TIOCM_DTR : 0) |
+ ((portdata->cts_state) ? TIOCM_CTS : 0) |
+ ((portdata->dsr_state) ? TIOCM_DSR : 0) |
+ ((portdata->dcd_state) ? TIOCM_CAR : 0) |
+ ((portdata->ri_state) ? TIOCM_RNG : 0);
+
+ return value;
+}
+
+static int
+option_tiocmset (struct usb_serial_port *port, struct file *file,
+ unsigned int set, unsigned int clear)
+{
+ struct option_port_private *portdata;
+
+ portdata = usb_get_serial_port_data(port);
+
+ if (set & TIOCM_RTS)
+ portdata->rts_state = 1;
+ if (set & TIOCM_DTR)
+ portdata->dtr_state = 1;
+
+ if (clear & TIOCM_RTS)
+ portdata->rts_state = 0;
+ if (clear & TIOCM_DTR)
+ portdata->dtr_state = 0;
+ return option_send_setup(port);
+}
+
+static int
+option_ioctl (struct usb_serial_port *port, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ return -ENOIOCTLCMD;
+}
+
+/* Write */
+static int
+option_write(struct usb_serial_port *port,
+ const unsigned char *buf, int count)
+{
+ struct option_port_private *portdata;
+ int i;
+ int left, todo;
+ struct urb *this_urb = NULL; /* spurious */
+ int err;
+
+ portdata = usb_get_serial_port_data(port);
+
+ dbg("%s: write (%d chars)", __FUNCTION__, count);
+
+#if 0
+ spin_lock(&port->lock);
+ if (port->write_urb_busy) {
+ spin_unlock(&port->lock);
+ dbg("%s: already writing", __FUNCTION__);
+ return 0;
+ }
+ port->write_urb_busy = 1;
+ spin_unlock(&port->lock);
+#endif
+
+ i = 0;
+ left = count;
+ while (left>0) {
+ todo = left;
+ if (todo > OUT_BUFLEN)
+ todo = OUT_BUFLEN;
+
+ for (;i < N_OUT_URB; i++) {
+ /* Check we have a valid urb/endpoint before we use it... */
+ this_urb = portdata->out_urbs[i];
+ if (this_urb->status != -EINPROGRESS)
+ break;
+ if (this_urb->transfer_flags & URB_ASYNC_UNLINK)
+ continue;
+ if (time_before(jiffies, portdata->tx_start_time[i] + 10 * HZ))
+ continue;
+ this_urb->transfer_flags |= URB_ASYNC_UNLINK;
+ usb_unlink_urb(this_urb);
+ }
+
+ if (i == N_OUT_URB) {
+ /* no bulk out free! */
+ dbg("%s: no output urb -- left %d", __FUNCTION__,count-left);
+#if 0
+ port->write_urb_busy = 0;
+#endif
+ return count-left;
+ }
+
+ dbg("%s: endpoint %d buf %d", __FUNCTION__, usb_pipeendpoint(this_urb->pipe), i);
+
+ memcpy (this_urb->transfer_buffer, buf, todo);
+
+ /* send the data out the bulk port */
+ this_urb->transfer_buffer_length = todo;
+
+ this_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
+ this_urb->dev = port->serial->dev;
+ err = usb_submit_urb(this_urb, GFP_ATOMIC);
+ if (err) {
+ dbg("usb_submit_urb %p (write bulk) failed (%d,, has %d)", this_urb, err, this_urb->status);
+ continue;
+ }
+ portdata->tx_start_time[i] = jiffies;
+ buf += todo;
+ left -= todo;
+ }
+
+ count -= left;
+#if 0
+ port->write_urb_busy = 0;
+#endif
+ dbg("%s: wrote (did %d)", __FUNCTION__, count);
+ return count;
+}
+
+static void
+option_indat_callback (struct urb *urb, struct pt_regs *regs)
+{
+ int i, err;
+ int endpoint;
+ struct usb_serial_port *port;
+ struct tty_struct *tty;
+ unsigned char *data = urb->transfer_buffer;
+
+ dbg("%s: %p", __FUNCTION__, urb);
+
+ endpoint = usb_pipeendpoint(urb->pipe);
+ port = (struct usb_serial_port *) urb->context;
+
+ if (urb->status) {
+ dbg("%s: nonzero status: %d on endpoint %02x.",
+ __FUNCTION__, urb->status, endpoint);
+ } else {
+ tty = port->tty;
+ if (urb->actual_length) {
+ for (i = 0; i < urb->actual_length ; ++i) {
+ if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+ tty_flip_buffer_push(tty);
+ tty_insert_flip_char(tty, data[i], 0);
+ }
+ tty_flip_buffer_push(tty);
+ } else {
+ dbg("%s: empty read urb received", __FUNCTION__);
+ }
+
+ /* Resubmit urb so we continue receiving */
+ if (port->open_count && urb->status != -ESHUTDOWN) {
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err)
+ printk(KERN_ERR "%s: resubmit read urb failed. (%d)", __FUNCTION__, err);
+ }
+ }
+ return;
+}
+
+static void
+option_outdat_callback (struct urb *urb, struct pt_regs *regs)
+{
+ struct usb_serial_port *port;
+
+ dbg("%s", __FUNCTION__);
+
+ port = (struct usb_serial_port *) urb->context;
+
+ if (port->open_count)
+ schedule_work(&port->work);
+}
+
+static void
+option_instat_callback (struct urb *urb, struct pt_regs *regs)
+{
+ int err;
+ struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+ struct option_port_private *portdata = usb_get_serial_port_data(port);
+ struct usb_serial *serial = port->serial;
+
+ dbg("%s", __FUNCTION__);
+ dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata);
+
+ if (urb->status == 0) {
+ struct usb_ctrlrequest *req_pkt =
+ (struct usb_ctrlrequest *)urb->transfer_buffer;
+
+ if (!req_pkt) {
+ dbg("%s: NULL req_pkt\n", __FUNCTION__);
+ return;
+ }
+ if ((req_pkt->bRequestType == 0xA1) && (req_pkt->bRequest == 0x20)) {
+ int old_dcd_state;
+ unsigned char signals = *((unsigned char *)
+ urb->transfer_buffer + sizeof(struct usb_ctrlrequest));
+
+ dbg("%s: signal x%x", __FUNCTION__, signals);
+
+ old_dcd_state = portdata->dcd_state;
+ portdata->cts_state = 1;
+ portdata->dcd_state = ((signals & 0x01) ? 1 : 0);
+ portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
+ portdata->ri_state = ((signals & 0x08) ? 1 : 0);
+
+ if (port->tty && !C_CLOCAL(port->tty)
+ && old_dcd_state && !portdata->dcd_state) {
+ tty_hangup(port->tty);
+ }
+ } else
+ dbg("%s: type %x req %x", __FUNCTION__, req_pkt->bRequestType,req_pkt->bRequest);
+ } else
+ dbg("%s: error %d", __FUNCTION__, urb->status);
+
+ /* Resubmit urb so we continue receiving IRQ data */
+ if (urb->status != -ESHUTDOWN) {
+ urb->dev = serial->dev;
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err)
+ dbg("%s: resubmit intr urb failed. (%d)", __FUNCTION__, err);
+ }
+}
+
+
+static int
+option_write_room (struct usb_serial_port *port)
+{
+ struct option_port_private *portdata;
+ int i;
+ int data_len = 0;
+ struct urb *this_urb;
+
+ portdata = usb_get_serial_port_data(port);
+
+ for (i=0; i < N_OUT_URB; i++)
+ this_urb = portdata->out_urbs[i];
+ if (this_urb && this_urb->status != -EINPROGRESS)
+ data_len += OUT_BUFLEN;
+
+ dbg("%s: %d", __FUNCTION__, data_len);
+ return data_len;
+}
+
+
+static int
+option_chars_in_buffer (struct usb_serial_port *port)
+{
+ struct option_port_private *portdata;
+ int i;
+ int data_len = 0;
+ struct urb *this_urb;
+
+ portdata = usb_get_serial_port_data(port);
+
+ for (i=0; i < N_OUT_URB; i++)
+ this_urb = portdata->out_urbs[i];
+ if (this_urb && this_urb->status == -EINPROGRESS)
+ data_len += this_urb->transfer_buffer_length;
+
+ dbg("%s: %d", __FUNCTION__, data_len);
+ return data_len;
+}
+
+
+static int
+option_open (struct usb_serial_port *port, struct file *filp)
+{
+ struct option_port_private *portdata;
+ struct usb_serial *serial = port->serial;
+ int i, err;
+ struct urb *urb;
+
+ portdata = usb_get_serial_port_data(port);
+
+ dbg("%s", __FUNCTION__);
+
+ /* Set some sane defaults */
+ portdata->rts_state = 1;
+ portdata->dtr_state = 1;
+
+ /* Reset low level data toggle and start reading from endpoints */
+ for (i = 0; i < N_IN_URB; i++) {
+ urb = portdata->in_urbs[i];
+ if (! urb)
+ continue;
+ if (urb->dev != serial->dev) {
+ dbg("%s: dev %p != %p", __FUNCTION__, urb->dev, serial->dev);
+ continue;
+ }
+
+ /* make sure endpoint data toggle is synchronized with the device */
+
+ usb_clear_halt(urb->dev, urb->pipe);
+
+ err = usb_submit_urb(urb, GFP_KERNEL);
+ if (err) {
+ dbg("%s: submit urb %d failed (%d) %d", __FUNCTION__, i, err,
+ urb->transfer_buffer_length);
+ }
+ }
+
+ /* Reset low level data toggle on out endpoints */
+ for (i = 0; i < N_OUT_URB; i++) {
+ urb = portdata->out_urbs[i];
+ if (! urb)
+ continue;
+ urb->dev = serial->dev;
+ /* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0); */
+ }
+
+ port->tty->low_latency = 1;
+
+ option_send_setup(port);
+
+ return (0);
+}
+
+static inline void
+stop_urb(struct urb *urb)
+{
+ if (urb && urb->status == -EINPROGRESS) {
+ urb->transfer_flags &= ~URB_ASYNC_UNLINK;
+ usb_kill_urb(urb);
+ }
+}
+
+static void
+option_close(struct usb_serial_port *port, struct file *filp)
+{
+ int i;
+ struct usb_serial *serial = port->serial;
+ struct option_port_private *portdata;
+
+ dbg("%s", __FUNCTION__);
+ portdata = usb_get_serial_port_data(port);
+
+ portdata->rts_state = 0;
+ portdata->dtr_state = 0;
+
+ if (serial->dev) {
+ option_send_setup(port);
+
+ /* Stop reading/writing urbs */
+ for (i = 0; i < N_IN_URB; i++)
+ stop_urb(portdata->in_urbs[i]);
+ for (i = 0; i < N_OUT_URB; i++)
+ stop_urb(portdata->out_urbs[i]);
+ }
+ port->tty = NULL;
+}
+
+
+/* Helper functions used by option_setup_urbs */
+static struct urb *
+option_setup_urb (struct usb_serial *serial, int endpoint,
+ int dir, void *ctx, char *buf, int len,
+ void (*callback)(struct urb *, struct pt_regs *regs))
+{
+ struct urb *urb;
+
+ if (endpoint == -1)
+ return NULL; /* endpoint not needed */
+
+ urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
+ if (urb == NULL) {
+ dbg("%s: alloc for endpoint %d failed.", __FUNCTION__, endpoint);
+ return NULL;
+ }
+
+ /* Fill URB using supplied data. */
+ usb_fill_bulk_urb(urb, serial->dev,
+ usb_sndbulkpipe(serial->dev, endpoint) | dir,
+ buf, len, callback, ctx);
+
+ return urb;
+}
+
+/* Setup urbs */
+static void
+option_setup_urbs(struct usb_serial *serial)
+{
+ int j;
+ struct usb_serial_port *port;
+ struct option_port_private *portdata;
+
+ dbg("%s", __FUNCTION__);
+
+ port = serial->port[0];
+ portdata = usb_get_serial_port_data(port);
+
+ /* Do indat endpoints first */
+ for (j = 0; j <= N_IN_URB; ++j) {
+ portdata->in_urbs[j] = option_setup_urb (serial,
+ port->bulk_in_endpointAddress, USB_DIR_IN, port,
+ portdata->in_buffer[j], IN_BUFLEN, option_indat_callback);
+ }
+
+ /* outdat endpoints */
+ for (j = 0; j <= N_OUT_URB; ++j) {
+ portdata->out_urbs[j] = option_setup_urb (serial,
+ port->bulk_out_endpointAddress, USB_DIR_OUT, port,
+ portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback);
+ }
+}
+
+
+static int
+option_send_setup(struct usb_serial_port *port)
+{
+ struct usb_serial *serial = port->serial;
+ struct option_port_private *portdata;
+
+ dbg("%s", __FUNCTION__);
+
+ portdata = usb_get_serial_port_data(port);
+
+ if (port->tty) {
+ int val = 0;
+ if (portdata->dtr_state)
+ val |= 0x01;
+ if (portdata->rts_state)
+ val |= 0x02;
+
+ return usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ 0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
+ }
+
+ return 0;
+}
+
+
+static int
+option_startup (struct usb_serial *serial)
+{
+ int i, err;
+ struct usb_serial_port *port;
+ struct option_port_private *portdata;
+
+ dbg("%s", __FUNCTION__);
+
+ /* Now setup per port private data */
+ for (i = 0; i < serial->num_ports; i++) {
+ port = serial->port[i];
+ portdata = kmalloc(sizeof(struct option_port_private), GFP_KERNEL);
+ if (!portdata) {
+ dbg("%s: kmalloc for option_port_private (%d) failed!.", __FUNCTION__, i);
+ return (1);
+ }
+ memset(portdata, 0, sizeof(struct option_port_private));
+
+ usb_set_serial_port_data(port, portdata);
+
+ if (! port->interrupt_in_urb)
+ continue;
+ err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+ if (err)
+ dbg("%s: submit irq_in urb failed %d", __FUNCTION__, err);
+ }
+
+ option_setup_urbs(serial);
+
+ return (0);
+}
+
+static void
+option_shutdown (struct usb_serial *serial)
+{
+ int i, j;
+ struct usb_serial_port *port;
+ struct option_port_private *portdata;
+
+ dbg("%s", __FUNCTION__);
+
+ /* Stop reading/writing urbs */
+ for (i = 0; i < serial->num_ports; ++i) {
+ port = serial->port[i];
+ portdata = usb_get_serial_port_data(port);
+ for (j = 0; j < N_IN_URB; j++)
+ stop_urb(portdata->in_urbs[j]);
+ for (j = 0; j < N_OUT_URB; j++)
+ stop_urb(portdata->out_urbs[j]);
+ }
+
+ /* Now free them */
+ for (i = 0; i < serial->num_ports; ++i) {
+ port = serial->port[i];
+ portdata = usb_get_serial_port_data(port);
+
+ for (j = 0; j < N_IN_URB; j++) {
+ if (portdata->in_urbs[j]) {
+ usb_free_urb(portdata->in_urbs[j]);
+ portdata->in_urbs[j] = NULL;
+ }
+ }
+ for (j = 0; j < N_OUT_URB; j++) {
+ if (portdata->out_urbs[j]) {
+ usb_free_urb(portdata->out_urbs[j]);
+ portdata->out_urbs[j] = NULL;
+ }
+ }
+ }
+
+ /* Now free per port private data */
+ for (i = 0; i < serial->num_ports; i++) {
+ port = serial->port[i];
+ kfree(usb_get_serial_port_data(port));
+ }
+}
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");
+
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug messages");
+
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 4536f63faae..5da76dd8fb2 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -1297,13 +1297,6 @@ static int __init usb_serial_init(void)
goto exit_bus;
}
- /* register the generic driver, if we should */
- result = usb_serial_generic_register(debug);
- if (result < 0) {
- err("%s - registering generic driver failed", __FUNCTION__);
- goto exit_generic;
- }
-
usb_serial_tty_driver->owner = THIS_MODULE;
usb_serial_tty_driver->driver_name = "usbserial";
usb_serial_tty_driver->devfs_name = "usb/tts/";
@@ -1329,17 +1322,24 @@ static int __init usb_serial_init(void)
goto exit_tty;
}
+ /* register the generic driver, if we should */
+ result = usb_serial_generic_register(debug);
+ if (result < 0) {
+ err("%s - registering generic driver failed", __FUNCTION__);
+ goto exit_generic;
+ }
+
info(DRIVER_DESC " " DRIVER_VERSION);
return result;
+exit_generic:
+ usb_deregister(&usb_serial_driver);
+
exit_tty:
tty_unregister_driver(usb_serial_tty_driver);
exit_reg_driver:
- usb_serial_generic_deregister();
-
-exit_generic:
bus_unregister(&usb_serial_bus_type);
exit_bus:
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 22e48a2b0bd..e43eddc3d44 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -233,13 +233,11 @@ static int command_abort(struct scsi_cmnd *srb)
set_bit(US_FLIDX_ABORTING, &us->flags);
usb_stor_stop_transport(us);
}
- scsi_unlock(us_to_host(us));
/* Wait for the aborted command to finish */
wait_for_completion(&us->notify);
/* Reacquire the lock and allow USB transfers to resume */
- scsi_lock(us_to_host(us));
clear_bit(US_FLIDX_ABORTING, &us->flags);
clear_bit(US_FLIDX_TIMED_OUT, &us->flags);
return SUCCESS;
@@ -255,8 +253,6 @@ static int device_reset(struct scsi_cmnd *srb)
US_DEBUGP("%s called\n", __FUNCTION__);
- scsi_unlock(us_to_host(us));
-
/* lock the device pointers and do the reset */
down(&(us->dev_semaphore));
if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
@@ -266,8 +262,6 @@ static int device_reset(struct scsi_cmnd *srb)
result = us->transport_reset(us);
up(&(us->dev_semaphore));
- /* lock the host for the return */
- scsi_lock(us_to_host(us));
return result;
}
@@ -282,8 +276,6 @@ static int bus_reset(struct scsi_cmnd *srb)
US_DEBUGP("%s called\n", __FUNCTION__);
- scsi_unlock(us_to_host(us));
-
/* The USB subsystem doesn't handle synchronisation between
* a device's several drivers. Therefore we reset only devices
* with just one interface, which we of course own. */
@@ -310,7 +302,6 @@ static int bus_reset(struct scsi_cmnd *srb)
up(&(us->dev_semaphore));
/* lock the host for the return */
- scsi_lock(us_to_host(us));
return result < 0 ? FAILED : SUCCESS;
}
@@ -407,7 +398,7 @@ US_DO_ALL_FLAGS
***********************************************************************/
/* Output routine for the sysfs max_sectors file */
-static ssize_t show_max_sectors(struct device *dev, char *buf)
+static ssize_t show_max_sectors(struct device *dev, struct device_attribute *attr, char *buf)
{
struct scsi_device *sdev = to_scsi_device(dev);
@@ -415,7 +406,7 @@ static ssize_t show_max_sectors(struct device *dev, char *buf)
}
/* Input routine for the sysfs max_sectors file */
-static ssize_t store_max_sectors(struct device *dev, const char *buf,
+static ssize_t store_max_sectors(struct device *dev, struct device_attribute *attr, const char *buf,
size_t count)
{
struct scsi_device *sdev = to_scsi_device(dev);
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index d2891f47579..9fcc7bd1fbe 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -862,6 +862,15 @@ UNUSUAL_DEV( 0x090a, 0x1001, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_BULK, NULL,
US_FL_NEED_OVERRIDE ),
+/* Reported by Filippo Bardelli <filibard@libero.it>
+ * The device reports a subclass of RBC, which is wrong.
+ */
+UNUSUAL_DEV( 0x090a, 0x1050, 0x0100, 0x0100,
+ "Trumpion Microelectronics, Inc.",
+ "33520 USB Digital Voice Recorder",
+ US_SC_UFI, US_PR_DEVICE, NULL,
+ 0),
+
/* Trumpion Microelectronics MP3 player (felipe_alfaro@linuxmail.org) */
UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999,
"Trumpion",
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 35c1ca6b5a8..77e7fc258aa 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -847,10 +847,8 @@ retry:
wait_event_interruptible_timeout(us->delay_wait,
test_bit(US_FLIDX_DISCONNECTING, &us->flags),
delay_use * HZ);
- if (current->flags & PF_FREEZE) {
- refrigerator(PF_FREEZE);
+ if (try_to_freeze())
goto retry;
- }
}
/* If the device is still connected, perform the scanning */
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 6be8fbec0a0..04d3120f723 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -322,6 +322,22 @@ config FB_FM2
This is the frame buffer device driver for the Amiga FrameMaster
card from BSC (exhibited 1992 but not shipped as a CBM product).
+config FB_ARC
+ tristate "Arc Monochrome LCD board support"
+ depends on FB && X86
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ select FB_SOFT_CURSOR
+ help
+ This enables support for the Arc Monochrome LCD board. The board
+ is based on the KS-108 lcd controller and is typically a matrix
+ of 2*n chips. This driver was tested with a 128x64 panel. This
+ driver supports it for use with x86 SBCs through a 16 bit GPIO
+ interface (8 bit data, 8 bit control). If you anticpate using
+ this driver, say Y or M; otherwise say N. You must specify the
+ GPIO IO address to be used for setting control and data.
+
config FB_ATARI
bool "Atari native chipset support"
depends on (FB = y) && ATARI && BROKEN
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index bd8dc0ffe72..b018df4e95c 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_FB_MACMODES) += macmodes.o
# Hardware specific drivers go first
obj-$(CONFIG_FB_RETINAZ3) += retz3fb.o
obj-$(CONFIG_FB_AMIGA) += amifb.o c2p.o
+obj-$(CONFIG_FB_ARC) += arcfb.o
obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o
obj-$(CONFIG_FB_CYBER) += cyberfb.o
obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c
new file mode 100644
index 00000000000..d28457e0c06
--- /dev/null
+++ b/drivers/video/arcfb.c
@@ -0,0 +1,684 @@
+/*
+ * linux/drivers/video/arcfb.c -- FB driver for Arc monochrome LCD board
+ *
+ * Copyright (C) 2005, Jaya Kumar <jayalk@intworks.biz>
+ * http://www.intworks.biz/arclcd
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive for
+ * more details.
+ *
+ * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
+ *
+ * This driver was written to be used with the Arc LCD board. Arc uses a
+ * set of KS108 chips that control individual 64x64 LCD matrices. The board
+ * can be paneled in a variety of setups such as 2x1=128x64, 4x4=256x256 and
+ * so on. The interface between the board and the host is TTL based GPIO. The
+ * GPIO requirements are 8 writable data lines and 4+n lines for control. On a
+ * GPIO-less system, the board can be tested by connecting the respective sigs
+ * up to a parallel port connector. The driver requires the IO addresses for
+ * data and control GPIO at load time. It is unable to probe for the
+ * existence of the LCD so it must be told at load time whether it should
+ * be enabled or not.
+ *
+ * Todo:
+ * - testing with 4x4
+ * - testing with interrupt hw
+ *
+ * General notes:
+ * - User must set tuhold. It's in microseconds. According to the 108 spec,
+ * the hold time is supposed to be at least 1 microsecond.
+ * - User must set num_cols=x num_rows=y, eg: x=2 means 128
+ * - User must set arcfb_enable=1 to enable it
+ * - User must set dio_addr=0xIOADDR cio_addr=0xIOADDR
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/arcfb.h>
+
+#include <asm/uaccess.h>
+
+#define floor8(a) (a&(~0x07))
+#define floorXres(a,xres) (a&(~(xres - 1)))
+#define iceil8(a) (((int)((a+7)/8))*8)
+#define ceil64(a) (a|0x3F)
+#define ceilXres(a,xres) (a|(xres - 1))
+
+/* ks108 chipset specific defines and code */
+
+#define KS_SET_DPY_START_LINE 0xC0
+#define KS_SET_PAGE_NUM 0xB8
+#define KS_SET_X 0x40
+#define KS_CEHI 0x01
+#define KS_CELO 0x00
+#define KS_SEL_CMD 0x08
+#define KS_SEL_DATA 0x00
+#define KS_DPY_ON 0x3F
+#define KS_DPY_OFF 0x3E
+#define KS_INTACK 0x40
+#define KS_CLRINT 0x02
+
+struct arcfb_par {
+ unsigned long dio_addr;
+ unsigned long cio_addr;
+ unsigned long c2io_addr;
+ atomic_t ref_count;
+ unsigned char cslut[9];
+ struct fb_info *info;
+ unsigned int irq;
+ spinlock_t lock;
+};
+
+static struct fb_fix_screeninfo arcfb_fix __initdata = {
+ .id = "arcfb",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_MONO01,
+ .xpanstep = 0,
+ .ypanstep = 1,
+ .ywrapstep = 0,
+ .accel = FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo arcfb_var __initdata = {
+ .xres = 128,
+ .yres = 64,
+ .xres_virtual = 128,
+ .yres_virtual = 64,
+ .bits_per_pixel = 1,
+ .nonstd = 1,
+};
+
+static unsigned long num_cols;
+static unsigned long num_rows;
+static unsigned long dio_addr;
+static unsigned long cio_addr;
+static unsigned long c2io_addr;
+static unsigned long splashval;
+static unsigned long tuhold;
+static unsigned int nosplash;
+static unsigned int arcfb_enable;
+static unsigned int irq;
+
+static DECLARE_WAIT_QUEUE_HEAD(arcfb_waitq);
+
+static void ks108_writeb_ctl(struct arcfb_par *par,
+ unsigned int chipindex, unsigned char value)
+{
+ unsigned char chipselval = par->cslut[chipindex];
+
+ outb(chipselval|KS_CEHI|KS_SEL_CMD, par->cio_addr);
+ outb(value, par->dio_addr);
+ udelay(tuhold);
+ outb(chipselval|KS_CELO|KS_SEL_CMD, par->cio_addr);
+}
+
+static void ks108_writeb_mainctl(struct arcfb_par *par, unsigned char value)
+{
+
+ outb(value, par->cio_addr);
+ udelay(tuhold);
+}
+
+static unsigned char ks108_readb_ctl2(struct arcfb_par *par)
+{
+ return inb(par->c2io_addr);
+}
+
+static void ks108_writeb_data(struct arcfb_par *par,
+ unsigned int chipindex, unsigned char value)
+{
+ unsigned char chipselval = par->cslut[chipindex];
+
+ outb(chipselval|KS_CEHI|KS_SEL_DATA, par->cio_addr);
+ outb(value, par->dio_addr);
+ udelay(tuhold);
+ outb(chipselval|KS_CELO|KS_SEL_DATA, par->cio_addr);
+}
+
+static void ks108_set_start_line(struct arcfb_par *par,
+ unsigned int chipindex, unsigned char y)
+{
+ ks108_writeb_ctl(par, chipindex, KS_SET_DPY_START_LINE|y);
+}
+
+static void ks108_set_yaddr(struct arcfb_par *par,
+ unsigned int chipindex, unsigned char y)
+{
+ ks108_writeb_ctl(par, chipindex, KS_SET_PAGE_NUM|y);
+}
+
+static void ks108_set_xaddr(struct arcfb_par *par,
+ unsigned int chipindex, unsigned char x)
+{
+ ks108_writeb_ctl(par, chipindex, KS_SET_X|x);
+}
+
+static void ks108_clear_lcd(struct arcfb_par *par, unsigned int chipindex)
+{
+ int i,j;
+
+ for (i = 0; i <= 8; i++) {
+ ks108_set_yaddr(par, chipindex, i);
+ ks108_set_xaddr(par, chipindex, 0);
+ for (j = 0; j < 64; j++) {
+ ks108_writeb_data(par, chipindex,
+ (unsigned char) splashval);
+ }
+ }
+}
+
+/* main arcfb functions */
+
+static int arcfb_open(struct fb_info *info, int user)
+{
+ struct arcfb_par *par = info->par;
+
+ atomic_inc(&par->ref_count);
+ return 0;
+}
+
+static int arcfb_release(struct fb_info *info, int user)
+{
+ struct arcfb_par *par = info->par;
+ int count = atomic_read(&par->ref_count);
+
+ if (!count)
+ return -EINVAL;
+ atomic_dec(&par->ref_count);
+ return 0;
+}
+
+static int arcfb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ int i;
+ struct arcfb_par *par = info->par;
+
+ if ((var->vmode & FB_VMODE_YWRAP) && (var->yoffset < 64)
+ && (info->var.yres <= 64)) {
+ for (i = 0; i < num_cols; i++) {
+ ks108_set_start_line(par, i, var->yoffset);
+ }
+ info->var.yoffset = var->yoffset;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static irqreturn_t arcfb_interrupt(int vec, void *dev_instance,
+ struct pt_regs *regs)
+{
+ struct fb_info *info = dev_instance;
+ unsigned char ctl2status;
+ struct arcfb_par *par = info->par;
+
+ ctl2status = ks108_readb_ctl2(par);
+
+ if (!(ctl2status & KS_INTACK)) /* not arc generated interrupt */
+ return IRQ_NONE;
+
+ ks108_writeb_mainctl(par, KS_CLRINT);
+
+ spin_lock(&par->lock);
+ if (waitqueue_active(&arcfb_waitq)) {
+ wake_up(&arcfb_waitq);
+ }
+ spin_unlock(&par->lock);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * here we handle a specific page on the lcd. the complexity comes from
+ * the fact that the fb is laidout in 8xX vertical columns. we extract
+ * each write of 8 vertical pixels. then we shift out as we move along
+ * X. That's what rightshift does. bitmask selects the desired input bit.
+ */
+static void arcfb_lcd_update_page(struct arcfb_par *par, unsigned int upper,
+ unsigned int left, unsigned int right, unsigned int distance)
+{
+ unsigned char *src;
+ unsigned int xindex, yindex, chipindex, linesize;
+ int i, count;
+ unsigned char val;
+ unsigned char bitmask, rightshift;
+
+ xindex = left >> 6;
+ yindex = upper >> 6;
+ chipindex = (xindex + (yindex*num_cols));
+
+ ks108_set_yaddr(par, chipindex, upper/8);
+
+ linesize = par->info->var.xres/8;
+ src = par->info->screen_base + (left/8) + (upper * linesize);
+ ks108_set_xaddr(par, chipindex, left);
+
+ bitmask=1;
+ rightshift=0;
+ while (left <= right) {
+ val = 0;
+ for (i = 0; i < 8; i++) {
+ if ( i > rightshift) {
+ val |= (*(src + (i*linesize)) & bitmask)
+ << (i - rightshift);
+ } else {
+ val |= (*(src + (i*linesize)) & bitmask)
+ >> (rightshift - i);
+ }
+ }
+ ks108_writeb_data(par, chipindex, val);
+ left++;
+ count++;
+ if (bitmask == 0x80) {
+ bitmask = 1;
+ src++;
+ rightshift=0;
+ } else {
+ bitmask <<= 1;
+ rightshift++;
+ }
+ }
+}
+
+/*
+ * here we handle the entire vertical page of the update. we write across
+ * lcd chips. update_page uses the upper/left values to decide which
+ * chip to select for the right. upper is needed for setting the page
+ * desired for the write.
+ */
+static void arcfb_lcd_update_vert(struct arcfb_par *par, unsigned int top,
+ unsigned int bottom, unsigned int left, unsigned int right)
+{
+ unsigned int distance, upper, lower;
+
+ distance = (bottom - top) + 1;
+ upper = top;
+ lower = top + 7;
+
+ while (distance > 0) {
+ distance -= 8;
+ arcfb_lcd_update_page(par, upper, left, right, 8);
+ upper = lower + 1;
+ lower = upper + 7;
+ }
+}
+
+/*
+ * here we handle horizontal blocks for the update. update_vert will
+ * handle spaning multiple pages. we break out each horizontal
+ * block in to individual blocks no taller than 64 pixels.
+ */
+static void arcfb_lcd_update_horiz(struct arcfb_par *par, unsigned int left,
+ unsigned int right, unsigned int top, unsigned int h)
+{
+ unsigned int distance, upper, lower;
+
+ distance = h;
+ upper = floor8(top);
+ lower = min(upper + distance - 1, ceil64(upper));
+
+ while (distance > 0) {
+ distance -= ((lower - upper) + 1 );
+ arcfb_lcd_update_vert(par, upper, lower, left, right);
+ upper = lower + 1;
+ lower = min(upper + distance - 1, ceil64(upper));
+ }
+}
+
+/*
+ * here we start the process of spliting out the fb update into
+ * individual blocks of pixels. we end up spliting into 64x64 blocks
+ * and finally down to 64x8 pages.
+ */
+static void arcfb_lcd_update(struct arcfb_par *par, unsigned int dx,
+ unsigned int dy, unsigned int w, unsigned int h)
+{
+ unsigned int left, right, distance, y;
+
+ /* align the request first */
+ y = floor8(dy);
+ h += dy - y;
+ h = iceil8(h);
+
+ distance = w;
+ left = dx;
+ right = min(left + w - 1, ceil64(left));
+
+ while (distance > 0) {
+ arcfb_lcd_update_horiz(par, left, right, y, h);
+ distance -= ((right - left) + 1);
+ left = right + 1;
+ right = min(left + distance - 1, ceil64(left));
+ }
+}
+
+void arcfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+ struct arcfb_par *par = info->par;
+
+ cfb_fillrect(info, rect);
+
+ /* update the physical lcd */
+ arcfb_lcd_update(par, rect->dx, rect->dy, rect->width, rect->height);
+}
+
+void arcfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+ struct arcfb_par *par = info->par;
+
+ cfb_copyarea(info, area);
+
+ /* update the physical lcd */
+ arcfb_lcd_update(par, area->dx, area->dy, area->width, area->height);
+}
+
+void arcfb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+ struct arcfb_par *par = info->par;
+
+ cfb_imageblit(info, image);
+
+ /* update the physical lcd */
+ arcfb_lcd_update(par, image->dx, image->dy, image->width,
+ image->height);
+}
+
+static int arcfb_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg,
+ struct fb_info *info)
+{
+ void __user *argp = (void __user *)arg;
+ struct arcfb_par *par = info->par;
+ unsigned long flags;
+
+ switch (cmd) {
+ case FBIO_WAITEVENT:
+ {
+ DEFINE_WAIT(wait);
+ /* illegal to wait on arc if no irq will occur */
+ if (!par->irq)
+ return -EINVAL;
+
+ /* wait until the Arc has generated an interrupt
+ * which will wake us up */
+ spin_lock_irqsave(&par->lock, flags);
+ prepare_to_wait(&arcfb_waitq, &wait,
+ TASK_INTERRUPTIBLE);
+ spin_unlock_irqrestore(&par->lock, flags);
+ schedule();
+ finish_wait(&arcfb_waitq, &wait);
+ }
+ case FBIO_GETCONTROL2:
+ {
+ unsigned char ctl2;
+
+ ctl2 = ks108_readb_ctl2(info->par);
+ if (copy_to_user(argp, &ctl2, sizeof(ctl2)))
+ return -EFAULT;
+ return 0;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+/*
+ * this is the access path from userspace. they can seek and write to
+ * the fb. it's inefficient for them to do anything less than 64*8
+ * writes since we update the lcd in each write() anyway.
+ */
+static ssize_t arcfb_write(struct file *file, const char *buf, size_t count,
+ loff_t *ppos)
+{
+ /* modded from epson 1355 */
+
+ struct inode *inode;
+ int fbidx;
+ struct fb_info *info;
+ unsigned long p;
+ int err=-EINVAL;
+ unsigned int fbmemlength,x,y,w,h, bitppos, startpos, endpos, bitcount;
+ struct arcfb_par *par;
+ unsigned int xres;
+
+ p = *ppos;
+ inode = file->f_dentry->d_inode;
+ fbidx = iminor(inode);
+ info = registered_fb[fbidx];
+ par = info->par;
+
+ if (!info || !info->screen_base)
+ return -ENODEV;
+
+ xres = info->var.xres;
+ fbmemlength = (xres * info->var.yres)/8;
+
+ if (p > fbmemlength)
+ return -ENOSPC;
+
+ err = 0;
+ if ((count + p) > fbmemlength) {
+ count = fbmemlength - p;
+ err = -ENOSPC;
+ }
+
+ if (count) {
+ char *base_addr;
+
+ base_addr = info->screen_base;
+ count -= copy_from_user(base_addr + p, buf, count);
+ *ppos += count;
+ err = -EFAULT;
+ }
+
+
+ bitppos = p*8;
+ startpos = floorXres(bitppos, xres);
+ endpos = ceilXres((bitppos + (count*8)), xres);
+ bitcount = endpos - startpos;
+
+ x = startpos % xres;
+ y = startpos / xres;
+ w = xres;
+ h = bitcount / xres;
+ arcfb_lcd_update(par, x, y, w, h);
+
+ if (count)
+ return count;
+ return err;
+}
+
+static void arcfb_platform_release(struct device *device)
+{
+}
+
+static struct fb_ops arcfb_ops = {
+ .owner = THIS_MODULE,
+ .fb_open = arcfb_open,
+ .fb_write = arcfb_write,
+ .fb_release = arcfb_release,
+ .fb_pan_display = arcfb_pan_display,
+ .fb_fillrect = arcfb_fillrect,
+ .fb_copyarea = arcfb_copyarea,
+ .fb_imageblit = arcfb_imageblit,
+ .fb_cursor = soft_cursor,
+ .fb_ioctl = arcfb_ioctl,
+};
+
+static int __init arcfb_probe(struct device *device)
+{
+ struct platform_device *dev = to_platform_device(device);
+ struct fb_info *info;
+ int retval = -ENOMEM;
+ int videomemorysize;
+ unsigned char *videomemory;
+ struct arcfb_par *par;
+ int i;
+
+ videomemorysize = (((64*64)*num_cols)*num_rows)/8;
+
+ /* We need a flat backing store for the Arc's
+ less-flat actual paged framebuffer */
+ if (!(videomemory = vmalloc(videomemorysize)))
+ return retval;
+
+ memset(videomemory, 0, videomemorysize);
+
+ info = framebuffer_alloc(sizeof(struct arcfb_par), &dev->dev);
+ if (!info)
+ goto err;
+
+ info->screen_base = (char __iomem *)videomemory;
+ info->fbops = &arcfb_ops;
+
+ info->var = arcfb_var;
+ info->fix = arcfb_fix;
+ par = info->par;
+ par->info = info;
+
+ if (!dio_addr || !cio_addr || !c2io_addr) {
+ printk(KERN_WARNING "no IO addresses supplied\n");
+ goto err1;
+ }
+ par->dio_addr = dio_addr;
+ par->cio_addr = cio_addr;
+ par->c2io_addr = c2io_addr;
+ par->cslut[0] = 0x00;
+ par->cslut[1] = 0x06;
+ info->flags = FBINFO_FLAG_DEFAULT;
+ spin_lock_init(&par->lock);
+ retval = register_framebuffer(info);
+ if (retval < 0)
+ goto err1;
+ dev_set_drvdata(&dev->dev, info);
+ if (irq) {
+ par->irq = irq;
+ if (request_irq(par->irq, &arcfb_interrupt, SA_SHIRQ,
+ "arcfb", info)) {
+ printk(KERN_INFO
+ "arcfb: Failed req IRQ %d\n", par->irq);
+ goto err1;
+ }
+ }
+ printk(KERN_INFO
+ "fb%d: Arc frame buffer device, using %dK of video memory\n",
+ info->node, videomemorysize >> 10);
+
+ /* this inits the lcd but doesn't clear dirty pixels */
+ for (i = 0; i < num_cols * num_rows; i++) {
+ ks108_writeb_ctl(par, i, KS_DPY_OFF);
+ ks108_set_start_line(par, i, 0);
+ ks108_set_yaddr(par, i, 0);
+ ks108_set_xaddr(par, i, 0);
+ ks108_writeb_ctl(par, i, KS_DPY_ON);
+ }
+
+ /* if we were told to splash the screen, we just clear it */
+ if (!nosplash) {
+ for (i = 0; i < num_cols * num_rows; i++) {
+ printk(KERN_INFO "fb%d: splashing lcd %d\n",
+ info->node, i);
+ ks108_set_start_line(par, i, 0);
+ ks108_clear_lcd(par, i);
+ }
+ }
+
+ return 0;
+err1:
+ framebuffer_release(info);
+err:
+ vfree(videomemory);
+ return retval;
+}
+
+static int arcfb_remove(struct device *device)
+{
+ struct fb_info *info = dev_get_drvdata(device);
+
+ if (info) {
+ unregister_framebuffer(info);
+ vfree(info->screen_base);
+ framebuffer_release(info);
+ }
+ return 0;
+}
+
+static struct device_driver arcfb_driver = {
+ .name = "arcfb",
+ .bus = &platform_bus_type,
+ .probe = arcfb_probe,
+ .remove = arcfb_remove,
+};
+
+static struct platform_device arcfb_device = {
+ .name = "arcfb",
+ .id = 0,
+ .dev = {
+ .release = arcfb_platform_release,
+ }
+};
+
+static int __init arcfb_init(void)
+{
+ int ret;
+
+ if (!arcfb_enable)
+ return -ENXIO;
+
+ ret = driver_register(&arcfb_driver);
+ if (!ret) {
+ ret = platform_device_register(&arcfb_device);
+ if (ret)
+ driver_unregister(&arcfb_driver);
+ }
+ return ret;
+
+}
+
+static void __exit arcfb_exit(void)
+{
+ platform_device_unregister(&arcfb_device);
+ driver_unregister(&arcfb_driver);
+}
+
+module_param(num_cols, ulong, 0);
+MODULE_PARM_DESC(num_cols, "Num horiz panels, eg: 2 = 128 bit wide");
+module_param(num_rows, ulong, 0);
+MODULE_PARM_DESC(num_rows, "Num vert panels, eg: 1 = 64 bit high");
+module_param(nosplash, uint, 0);
+MODULE_PARM_DESC(nosplash, "Disable doing the splash screen");
+module_param(arcfb_enable, uint, 0);
+MODULE_PARM_DESC(arcfb_enable, "Enable communication with Arc board");
+module_param(dio_addr, ulong, 0);
+MODULE_PARM_DESC(dio_addr, "IO address for data, eg: 0x480");
+module_param(cio_addr, ulong, 0);
+MODULE_PARM_DESC(cio_addr, "IO address for control, eg: 0x400");
+module_param(c2io_addr, ulong, 0);
+MODULE_PARM_DESC(c2io_addr, "IO address for secondary control, eg: 0x408");
+module_param(splashval, ulong, 0);
+MODULE_PARM_DESC(splashval, "Splash pattern: 0xFF is black, 0x00 is green");
+module_param(tuhold, ulong, 0);
+MODULE_PARM_DESC(tuhold, "Time to hold between strobing data to Arc board");
+module_param(irq, uint, 0);
+MODULE_PARM_DESC(irq, "IRQ for the Arc board");
+
+module_init(arcfb_init);
+module_exit(arcfb_exit);
+
+MODULE_DESCRIPTION("fbdev driver for Arc monochrome LCD board");
+MODULE_AUTHOR("Jaya Kumar");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index ee25b9e8db6..47a6b12bc96 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -2374,10 +2374,9 @@ static int radeonfb_pci_register (struct pci_dev *pdev,
} while ( rinfo->fb_base == 0 &&
((rinfo->mapped_vram /=2) >= MIN_MAPPED_VRAM) );
- if (rinfo->fb_base)
- memset_io(rinfo->fb_base, 0, rinfo->mapped_vram);
- else {
- printk (KERN_ERR "radeonfb (%s): cannot map FB\n", pci_name(rinfo->pdev));
+ if (rinfo->fb_base == NULL) {
+ printk (KERN_ERR "radeonfb (%s): cannot map FB\n",
+ pci_name(rinfo->pdev));
ret = -EIO;
goto err_unmap_rom;
}
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index cacd88cc84a..b6fe30c3ad6 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -111,15 +111,15 @@ static int au1100fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
void au1100_nocursor(struct display *p, int mode, int xx, int yy){};
static struct fb_ops au1100fb_ops = {
- owner: THIS_MODULE,
- fb_get_fix: fbgen_get_fix,
- fb_get_var: fbgen_get_var,
- fb_set_var: fbgen_set_var,
- fb_get_cmap: fbgen_get_cmap,
- fb_set_cmap: fbgen_set_cmap,
- fb_pan_display: fbgen_pan_display,
- fb_ioctl: au1100fb_ioctl,
- fb_mmap: au1100fb_mmap,
+ .owner = THIS_MODULE,
+ .fb_get_fix = fbgen_get_fix,
+ .fb_get_var = fbgen_get_var,
+ .fb_set_var = fbgen_set_var,
+ .fb_get_cmap = fbgen_get_cmap,
+ .fb_set_cmap = fbgen_set_cmap,
+ .fb_pan_display = fbgen_pan_display,
+ .fb_ioctl = au1100fb_ioctl,
+ .fb_mmap = au1100fb_mmap,
};
static void au1100_detect(void)
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index ab98f225fe3..95e72550d43 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -423,9 +423,6 @@ chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
pmu_register_sleep_notifier(&chips_sleep_notifier);
#endif /* CONFIG_PMAC_PBOOK */
- /* Clear the entire framebuffer */
- memset(p->screen_base, 0, 0x100000);
-
pci_set_drvdata(dp, p);
return 0;
}
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index ccf55811d24..cbff98337aa 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -153,6 +153,14 @@ config FONT_6x11
Small console font with Macintosh-style high-half glyphs. Some Mac
framebuffer drivers don't support this one at all.
+config FONT_7x14
+ bool "console 7x14 font (not supported by all drivers)" if FONTS
+ depends on FRAMEBUFFER_CONSOLE
+ help
+ Console font with characters just a bit smaller than the default.
+ If the standard 8x16 font is a little too big for you, say Y.
+ Otherwise, say N.
+
config FONT_PEARL_8x8
bool "Pearl (old m68k) console 8x8 font" if FONTS
depends on FRAMEBUFFER_CONSOLE
@@ -187,5 +195,13 @@ config FONT_SUN12x22
big letters (like the letters used in the SPARC PROM). If the
standard font is unreadable for you, say Y, otherwise say N.
+config FONT_10x18
+ bool "console 10x18 font (not supported by all drivers)" if FONTS
+ depends on FRAMEBUFFER_CONSOLE
+ help
+ This is a high resolution console font for machines with very
+ big letters. It fits between the sun 12x22 and the normal 8x16 font.
+ If other fonts are too big or too small for you, say Y, otherwise say N.
+
endmenu
diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile
index 33516447f9f..b562f6bb9d3 100644
--- a/drivers/video/console/Makefile
+++ b/drivers/video/console/Makefile
@@ -10,6 +10,8 @@ font-objs-$(CONFIG_FONT_SUN12x22) += font_sun12x22.o
font-objs-$(CONFIG_FONT_8x8) += font_8x8.o
font-objs-$(CONFIG_FONT_8x16) += font_8x16.o
font-objs-$(CONFIG_FONT_6x11) += font_6x11.o
+font-objs-$(CONFIG_FONT_7x14) += font_7x14.o
+font-objs-$(CONFIG_FONT_10x18) += font_10x18.o
font-objs-$(CONFIG_FONT_PEARL_8x8) += font_pearl_8x8.o
font-objs-$(CONFIG_FONT_ACORN_8x8) += font_acorn_8x8.o
font-objs-$(CONFIG_FONT_MINI_4x6) += font_mini_4x6.o
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
index b28a4b0e395..3c731577fed 100644
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -107,13 +107,6 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
const unsigned short *s, int count, int yy, int xx,
int fg, int bg)
{
- void (*move_unaligned)(struct fb_info *info, struct fb_pixmap *buf,
- u8 *dst, u32 d_pitch, u8 *src, u32 idx,
- u32 height, u32 shift_high, u32 shift_low,
- u32 mod);
- void (*move_aligned)(struct fb_info *info, struct fb_pixmap *buf,
- u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch,
- u32 height);
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
unsigned int width = (vc->vc_font.width + 7) >> 3;
unsigned int cellsize = vc->vc_font.height * width;
@@ -141,13 +134,6 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
image.height = vc->vc_font.height;
image.depth = 1;
- if (info->pixmap.outbuf && info->pixmap.inbuf) {
- move_aligned = fb_iomove_buf_aligned;
- move_unaligned = fb_iomove_buf_unaligned;
- } else {
- move_aligned = fb_sysmove_buf_aligned;
- move_unaligned = fb_sysmove_buf_unaligned;
- }
while (count) {
if (count > maxcnt)
cnt = k = maxcnt;
@@ -171,9 +157,9 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
src = buf;
}
- move_unaligned(info, &info->pixmap, dst, pitch,
- src, idx, image.height,
- shift_high, shift_low, mod);
+ fb_pad_unaligned_buffer(dst, pitch, src, idx,
+ image.height, shift_high,
+ shift_low, mod);
shift_low += mod;
dst += (shift_low >= 8) ? width : width - 1;
shift_low &= 7;
@@ -189,8 +175,7 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
src = buf;
}
- move_aligned(info, &info->pixmap, dst, pitch,
- src, idx, image.height);
+ fb_pad_aligned_buffer(dst, pitch, src, idx, image.height);
dst += width;
}
}
diff --git a/drivers/video/console/font_10x18.c b/drivers/video/console/font_10x18.c
new file mode 100644
index 00000000000..ff0af96e4df
--- /dev/null
+++ b/drivers/video/console/font_10x18.c
@@ -0,0 +1,5146 @@
+/********************************
+ * adapted from font_sun12x22.c *
+ * by Jurriaan Kalkman 06-2005 *
+ ********************************/
+
+#include <linux/font.h>
+
+#define FONTDATAMAX 9216
+
+static unsigned char fontdata_10x18[FONTDATAMAX] = {
+
+ /* 0 0x00 '^@' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 1 0x01 '^A' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x3f, 0x80, /* 0011111110 */
+ 0x40, 0x40, /* 0100000001 */
+ 0x5b, 0x40, /* 0101101101 */
+ 0x40, 0x40, /* 0100000001 */
+ 0x44, 0x40, /* 0100010001 */
+ 0x44, 0x40, /* 0100010001 */
+ 0x51, 0x40, /* 0101000101 */
+ 0x4e, 0x40, /* 0100111001 */
+ 0x40, 0x40, /* 0100000001 */
+ 0x3f, 0x80, /* 0011111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 2 0x02 '^B' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x3f, 0x80, /* 0011111110 */
+ 0x7f, 0xc0, /* 0111111111 */
+ 0x64, 0xc0, /* 0110010011 */
+ 0x7f, 0xc0, /* 0111111111 */
+ 0x7b, 0xc0, /* 0111101111 */
+ 0x7b, 0xc0, /* 0111101111 */
+ 0x6e, 0xc0, /* 0110111011 */
+ 0x71, 0xc0, /* 0111000111 */
+ 0x7f, 0xc0, /* 0111111111 */
+ 0x3f, 0x80, /* 0011111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 3 0x03 '^C' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x11, 0x00, /* 0001000100 */
+ 0x3b, 0x80, /* 0011101110 */
+ 0x7f, 0xc0, /* 0111111111 */
+ 0x3f, 0x80, /* 0011111110 */
+ 0x3f, 0x80, /* 0011111110 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x04, 0x00, /* 0000010000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 4 0x04 '^D' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x04, 0x00, /* 0000010000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x3f, 0x80, /* 0011111110 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x04, 0x00, /* 0000010000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 5 0x05 '^E' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x7b, 0xc0, /* 0111101111 */
+ 0x35, 0x80, /* 0011010110 */
+ 0x04, 0x00, /* 0000010000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 6 0x06 '^F' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x04, 0x00, /* 0000010000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x3f, 0x80, /* 0011111110 */
+ 0x7f, 0xc0, /* 0111111111 */
+ 0x7f, 0xc0, /* 0111111111 */
+ 0x35, 0x80, /* 0011010110 */
+ 0x04, 0x00, /* 0000010000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 7 0x07 '^G' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 8 0x08 '^H' */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xf3, 0xc0, /* 1111001111 */
+ 0xe1, 0xc0, /* 1110000111 */
+ 0xe1, 0xc0, /* 1110000111 */
+ 0xc0, 0xc0, /* 1100000011 */
+ 0xc0, 0xc0, /* 1100000011 */
+ 0xe1, 0xc0, /* 1110000111 */
+ 0xe1, 0xc0, /* 1110000111 */
+ 0xf3, 0xc0, /* 1111001111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+
+ /* 9 0x09 '^I' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x12, 0x00, /* 0001001000 */
+ 0x12, 0x00, /* 0001001000 */
+ 0x21, 0x00, /* 0010000100 */
+ 0x21, 0x00, /* 0010000100 */
+ 0x12, 0x00, /* 0001001000 */
+ 0x12, 0x00, /* 0001001000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 10 0x0a '^J' */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xf3, 0xc0, /* 1111001111 */
+ 0xed, 0xc0, /* 1110110111 */
+ 0xed, 0xc0, /* 1110110111 */
+ 0xde, 0xc0, /* 1101111011 */
+ 0xde, 0xc0, /* 1101111011 */
+ 0xed, 0xc0, /* 1110110111 */
+ 0xed, 0xc0, /* 1110110111 */
+ 0xf3, 0xc0, /* 1111001111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+
+ /* 11 0x0b '^K' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0f, 0xc0, /* 0000111111 */
+ 0x0f, 0xc0, /* 0000111111 */
+ 0x03, 0xc0, /* 0000001111 */
+ 0x06, 0xc0, /* 0000011011 */
+ 0x0c, 0xc0, /* 0000110011 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x66, 0x00, /* 0110011000 */
+ 0xc3, 0x00, /* 1100001100 */
+ 0xc3, 0x00, /* 1100001100 */
+ 0xc3, 0x00, /* 1100001100 */
+ 0x66, 0x00, /* 0110011000 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 12 0x0c '^L' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 13 0x0d '^M' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0f, 0x80, /* 0000111110 */
+ 0x08, 0x80, /* 0000100010 */
+ 0x0f, 0x80, /* 0000111110 */
+ 0x08, 0x00, /* 0000100000 */
+ 0x08, 0x00, /* 0000100000 */
+ 0x08, 0x00, /* 0000100000 */
+ 0x08, 0x00, /* 0000100000 */
+ 0x08, 0x00, /* 0000100000 */
+ 0x08, 0x00, /* 0000100000 */
+ 0x38, 0x00, /* 0011100000 */
+ 0x78, 0x00, /* 0111100000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 14 0x0e '^N' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1f, 0x80, /* 0001111110 */
+ 0x10, 0x80, /* 0001000010 */
+ 0x1f, 0x80, /* 0001111110 */
+ 0x10, 0x80, /* 0001000010 */
+ 0x10, 0x80, /* 0001000010 */
+ 0x10, 0x80, /* 0001000010 */
+ 0x10, 0x80, /* 0001000010 */
+ 0x13, 0x80, /* 0001001110 */
+ 0x17, 0x80, /* 0001011110 */
+ 0x73, 0x00, /* 0111001100 */
+ 0xf0, 0x00, /* 1111000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 15 0x0f '^O' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x04, 0x00, /* 0000010000 */
+ 0x24, 0x80, /* 0010010010 */
+ 0x15, 0x00, /* 0001010100 */
+ 0x55, 0x40, /* 0101010101 */
+ 0x3f, 0x80, /* 0011111110 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x3f, 0x80, /* 0011111110 */
+ 0x55, 0x40, /* 0101010101 */
+ 0x15, 0x00, /* 0001010100 */
+ 0x24, 0x80, /* 0010010010 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 16 0x10 '^P' */
+ 0x00, 0x80, /* 0000000010 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x03, 0x80, /* 0000001110 */
+ 0x07, 0x80, /* 0000011110 */
+ 0x0f, 0x80, /* 0000111110 */
+ 0x1f, 0x80, /* 0001111110 */
+ 0x3f, 0x80, /* 0011111110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0xff, 0x80, /* 1111111110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x3f, 0x80, /* 0011111110 */
+ 0x1f, 0x80, /* 0001111110 */
+ 0x0f, 0x80, /* 0000111110 */
+ 0x07, 0x80, /* 0000011110 */
+ 0x03, 0x80, /* 0000001110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x00, 0x80, /* 0000000010 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 17 0x11 '^Q' */
+ 0x40, 0x00, /* 0100000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x70, 0x00, /* 0111000000 */
+ 0x78, 0x00, /* 0111100000 */
+ 0x7c, 0x00, /* 0111110000 */
+ 0x7e, 0x00, /* 0111111000 */
+ 0x7f, 0x00, /* 0111111100 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x7f, 0xc0, /* 0111111111 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x7f, 0x00, /* 0111111100 */
+ 0x7e, 0x00, /* 0111111000 */
+ 0x7c, 0x00, /* 0111110000 */
+ 0x78, 0x00, /* 0111100000 */
+ 0x70, 0x00, /* 0111000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x40, 0x00, /* 0100000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 18 0x12 '^R' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 19 0x13 '^S' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 20 0x14 '^T' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1f, 0xc0, /* 0001111111 */
+ 0x39, 0x80, /* 0011100110 */
+ 0x79, 0x80, /* 0111100110 */
+ 0x79, 0x80, /* 0111100110 */
+ 0x79, 0x80, /* 0111100110 */
+ 0x39, 0x80, /* 0011100110 */
+ 0x19, 0x80, /* 0001100110 */
+ 0x19, 0x80, /* 0001100110 */
+ 0x19, 0x80, /* 0001100110 */
+ 0x19, 0x80, /* 0001100110 */
+ 0x19, 0x80, /* 0001100110 */
+ 0x19, 0x80, /* 0001100110 */
+ 0x39, 0xc0, /* 0011100111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 21 0x15 '^U' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x3e, 0x00, /* 0011111000 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x3e, 0x00, /* 0011111000 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x3e, 0x00, /* 0011111000 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x3e, 0x00, /* 0011111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 22 0x16 '^V' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 23 0x17 '^W' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 24 0x18 '^X' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 25 0x19 '^Y' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 26 0x1a '^Z' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x04, 0x00, /* 0000010000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x07, 0x00, /* 0000011100 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x07, 0x00, /* 0000011100 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x04, 0x00, /* 0000010000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 27 0x1b '^[' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x08, 0x00, /* 0000100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x38, 0x00, /* 0011100000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x38, 0x00, /* 0011100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x08, 0x00, /* 0000100000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 28 0x1c '^\' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 29 0x1d '^]' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x12, 0x00, /* 0001001000 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x73, 0x80, /* 0111001110 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0x73, 0x80, /* 0111001110 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x12, 0x00, /* 0001001000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 30 0x1e '^^' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x04, 0x00, /* 0000010000 */
+ 0x04, 0x00, /* 0000010000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x3f, 0x80, /* 0011111110 */
+ 0x3f, 0x80, /* 0011111110 */
+ 0x7f, 0xc0, /* 0111111111 */
+ 0x7f, 0xc0, /* 0111111111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 31 0x1f '^_' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x7f, 0xc0, /* 0111111111 */
+ 0x7f, 0xc0, /* 0111111111 */
+ 0x3f, 0x80, /* 0011111110 */
+ 0x3f, 0x80, /* 0011111110 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x04, 0x00, /* 0000010000 */
+ 0x04, 0x00, /* 0000010000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 32 0x20 ' ' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 33 0x21 '!' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 34 0x22 '"' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x63, 0x00, /* 0110001100 */
+ 0xf7, 0x80, /* 1111011110 */
+ 0xf7, 0x80, /* 1111011110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x42, 0x00, /* 0100001000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 35 0x23 '#' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 36 0x24 '$' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x3e, 0x00, /* 0011111000 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x6f, 0x80, /* 0110111110 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0x6c, 0x80, /* 0110110010 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x0f, 0x00, /* 0000111100 */
+ 0x0d, 0x80, /* 0000110110 */
+ 0x4d, 0x80, /* 0100110110 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0x7f, 0x00, /* 0111111100 */
+ 0x3e, 0x00, /* 0011111000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 37 0x25 '%' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x7b, 0x00, /* 0111101100 */
+ 0x7b, 0x00, /* 0111101100 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x37, 0x80, /* 0011011110 */
+ 0x37, 0x80, /* 0011011110 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 38 0x26 '&' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x07, 0x00, /* 0000011100 */
+ 0x0f, 0x80, /* 0000111110 */
+ 0x19, 0x80, /* 0001100110 */
+ 0x19, 0x80, /* 0001100110 */
+ 0x0f, 0x80, /* 0000111110 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x3e, 0x00, /* 0011111000 */
+ 0x76, 0x00, /* 0111011000 */
+ 0x66, 0x40, /* 0110011001 */
+ 0x63, 0xc0, /* 0110001111 */
+ 0x63, 0x80, /* 0110001110 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x3f, 0x80, /* 0011111110 */
+ 0x1c, 0xc0, /* 0001110011 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 39 0x27 ''' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x78, 0x00, /* 0111100000 */
+ 0x78, 0x00, /* 0111100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x20, 0x00, /* 0010000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 40 0x28 '(' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 41 0x29 ')' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 42 0x2a '*' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x4c, 0x80, /* 0100110010 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0x4c, 0x80, /* 0100110010 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 43 0x2b '+' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 44 0x2c ',' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x78, 0x00, /* 0111100000 */
+ 0x78, 0x00, /* 0111100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x40, 0x00, /* 0100000000 */
+
+ /* 45 0x2d '-' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 46 0x2e '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 47 0x2f '/' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 48 0x30 '0' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x23, 0x00, /* 0010001100 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x63, 0x80, /* 0110001110 */
+ 0x65, 0x80, /* 0110010110 */
+ 0x65, 0x80, /* 0110010110 */
+ 0x69, 0x80, /* 0110100110 */
+ 0x69, 0x80, /* 0110100110 */
+ 0x71, 0x80, /* 0111000110 */
+ 0x61, 0x00, /* 0110000100 */
+ 0x31, 0x00, /* 0011000100 */
+ 0x3e, 0x00, /* 0011111000 */
+ 0x1c, 0x00, /* 0001110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 49 0x31 '1' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x04, 0x00, /* 0000010000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x1c, 0x00, /* 0001110000 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x6c, 0x00, /* 0110110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 50 0x32 '2' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x63, 0x80, /* 0110001110 */
+ 0x41, 0x80, /* 0100000110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x30, 0x80, /* 0011000010 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 51 0x33 '3' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1c, 0x00, /* 0001110000 */
+ 0x3e, 0x00, /* 0011111000 */
+ 0x47, 0x00, /* 0100011100 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x07, 0x00, /* 0000011100 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x07, 0x00, /* 0000011100 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x41, 0x80, /* 0100000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 52 0x34 '4' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x66, 0x00, /* 0110011000 */
+ 0x66, 0x00, /* 0110011000 */
+ 0xc6, 0x00, /* 1100011000 */
+ 0xc6, 0x00, /* 1100011000 */
+ 0xff, 0x80, /* 1111111110 */
+ 0xff, 0x80, /* 1111111110 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 53 0x35 '5' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x7e, 0x00, /* 0111111000 */
+ 0x67, 0x00, /* 0110011100 */
+ 0x03, 0x80, /* 0000001110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x41, 0x80, /* 0100000110 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x3e, 0x00, /* 0011111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 54 0x36 '6' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x6e, 0x00, /* 0110111000 */
+ 0x7f, 0x00, /* 0111111100 */
+ 0x73, 0x80, /* 0111001110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x71, 0x00, /* 0111000100 */
+ 0x3e, 0x00, /* 0011111000 */
+ 0x1c, 0x00, /* 0001110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 55 0x37 '7' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1f, 0x80, /* 0001111110 */
+ 0x3f, 0x80, /* 0011111110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 56 0x38 '8' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x23, 0x00, /* 0010001100 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x31, 0x00, /* 0011000100 */
+ 0x1a, 0x00, /* 0001101000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x16, 0x00, /* 0001011000 */
+ 0x23, 0x00, /* 0010001100 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x31, 0x00, /* 0011000100 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 57 0x39 '9' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x17, 0x00, /* 0001011100 */
+ 0x23, 0x80, /* 0010001110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x73, 0x80, /* 0111001110 */
+ 0x3d, 0x80, /* 0011110110 */
+ 0x19, 0x80, /* 0001100110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 58 0x3a ':' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 59 0x3b ';' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x20, 0x00, /* 0010000000 */
+
+ /* 60 0x3c '<' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 61 0x3d '=' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 62 0x3e '>' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 63 0x3f '?' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x3b, 0x80, /* 0011101110 */
+ 0x21, 0x80, /* 0010000110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 64 0x40 '@' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x65, 0x80, /* 0110010110 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0x6f, 0x80, /* 0110111110 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x3f, 0x80, /* 0011111110 */
+ 0x0f, 0x00, /* 0000111100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 65 0x41 'A' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x04, 0x00, /* 0000010000 */
+ 0x04, 0x00, /* 0000010000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x19, 0x80, /* 0001100110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x3f, 0x80, /* 0011111110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x60, 0xc0, /* 0110000011 */
+ 0x60, 0xc0, /* 0110000011 */
+ 0xf1, 0xc0, /* 1111000111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 66 0x42 'B' */
+ 0x00, 0x00, /* 0000000000 */
+ 0xfc, 0x00, /* 1111110000 */
+ 0x62, 0x00, /* 0110001000 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x66, 0x00, /* 0110011000 */
+ 0x7e, 0x00, /* 0111111000 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x63, 0x00, /* 0110001100 */
+ 0xfe, 0x00, /* 1111111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 67 0x43 'C' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0f, 0x00, /* 0000111100 */
+ 0x11, 0x80, /* 0001000110 */
+ 0x20, 0x80, /* 0010000010 */
+ 0x20, 0x00, /* 0010000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x20, 0x00, /* 0010000000 */
+ 0x30, 0x80, /* 0011000010 */
+ 0x19, 0x00, /* 0001100100 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 68 0x44 'D' */
+ 0x00, 0x00, /* 0000000000 */
+ 0xfc, 0x00, /* 1111110000 */
+ 0x67, 0x00, /* 0110011100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x00, /* 0110000100 */
+ 0x66, 0x00, /* 0110011000 */
+ 0xf8, 0x00, /* 1111100000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 69 0x45 'E' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x30, 0x80, /* 0011000010 */
+ 0x30, 0x80, /* 0011000010 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x31, 0x00, /* 0011000100 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x31, 0x00, /* 0011000100 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x80, /* 0011000010 */
+ 0x30, 0x80, /* 0011000010 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 70 0x46 'F' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x30, 0x80, /* 0011000010 */
+ 0x30, 0x80, /* 0011000010 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x31, 0x00, /* 0011000100 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x31, 0x00, /* 0011000100 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x78, 0x00, /* 0111100000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 71 0x47 'G' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0f, 0x00, /* 0000111100 */
+ 0x11, 0x80, /* 0001000110 */
+ 0x20, 0x80, /* 0010000010 */
+ 0x20, 0x00, /* 0010000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x67, 0xc0, /* 0110011111 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x21, 0x80, /* 0010000110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x19, 0x80, /* 0001100110 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 72 0x48 'H' */
+ 0x00, 0x00, /* 0000000000 */
+ 0xf3, 0xc0, /* 1111001111 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0xf3, 0xc0, /* 1111001111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 73 0x49 'I' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 74 0x4a 'J' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x08, 0x00, /* 0000100000 */
+ 0x70, 0x00, /* 0111000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 75 0x4b 'K' */
+ 0x00, 0x00, /* 0000000000 */
+ 0xf1, 0x80, /* 1111000110 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x66, 0x00, /* 0110011000 */
+ 0x6c, 0x00, /* 0110110000 */
+ 0x78, 0x00, /* 0111100000 */
+ 0x70, 0x00, /* 0111000000 */
+ 0x70, 0x00, /* 0111000000 */
+ 0x78, 0x00, /* 0111100000 */
+ 0x78, 0x00, /* 0111100000 */
+ 0x6c, 0x00, /* 0110110000 */
+ 0x66, 0x00, /* 0110011000 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x61, 0x80, /* 0110000110 */
+ 0xf0, 0xc0, /* 1111000011 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 76 0x4c 'L' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x78, 0x00, /* 0111100000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x80, /* 0011000010 */
+ 0x30, 0x80, /* 0011000010 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 77 0x4d 'M' */
+ 0x00, 0x00, /* 0000000000 */
+ 0xe0, 0xc0, /* 1110000011 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x73, 0x80, /* 0111001110 */
+ 0x73, 0x80, /* 0111001110 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0xf3, 0xc0, /* 1111001111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 78 0x4e 'N' */
+ 0x00, 0x00, /* 0000000000 */
+ 0xf3, 0xc0, /* 1111001111 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x71, 0x80, /* 0111000110 */
+ 0x79, 0x80, /* 0111100110 */
+ 0x79, 0x80, /* 0111100110 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0x67, 0x80, /* 0110011110 */
+ 0x67, 0x80, /* 0110011110 */
+ 0x63, 0x80, /* 0110001110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0xf3, 0xc0, /* 1111001111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 79 0x4f 'O' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x17, 0x00, /* 0001011100 */
+ 0x23, 0x00, /* 0010001100 */
+ 0x21, 0x80, /* 0010000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x21, 0x00, /* 0010000100 */
+ 0x31, 0x00, /* 0011000100 */
+ 0x1a, 0x00, /* 0001101000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 80 0x50 'P' */
+ 0x00, 0x00, /* 0000000000 */
+ 0xfe, 0x00, /* 1111111000 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x7e, 0x00, /* 0111111000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0xf0, 0x00, /* 1111000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 81 0x51 'Q' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x13, 0x00, /* 0001001100 */
+ 0x23, 0x00, /* 0010001100 */
+ 0x21, 0x80, /* 0010000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x3b, 0x00, /* 0011101100 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x26, 0x00, /* 0010011000 */
+ 0x03, 0x80, /* 0000001110 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 82 0x52 'R' */
+ 0x00, 0x00, /* 0000000000 */
+ 0xfe, 0x00, /* 1111111000 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x00, /* 0110000100 */
+ 0x7e, 0x00, /* 0111111000 */
+ 0x78, 0x00, /* 0111100000 */
+ 0x6c, 0x00, /* 0110110000 */
+ 0x6e, 0x00, /* 0110111000 */
+ 0x67, 0x00, /* 0110011100 */
+ 0x63, 0x80, /* 0110001110 */
+ 0x61, 0xc0, /* 0110000111 */
+ 0xf0, 0xc0, /* 1111000011 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 83 0x53 'S' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x60, 0x80, /* 0110000010 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x41, 0x80, /* 0100000110 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x3e, 0x00, /* 0011111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 84 0x54 'T' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x4c, 0x80, /* 0100110010 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 85 0x55 'U' */
+ 0x00, 0x00, /* 0000000000 */
+ 0xf3, 0xc0, /* 1111001111 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x73, 0x00, /* 0111001100 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 86 0x56 'V' */
+ 0x00, 0x00, /* 0000000000 */
+ 0xe1, 0xc0, /* 1110000111 */
+ 0xc0, 0xc0, /* 1100000011 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x12, 0x00, /* 0001001000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 87 0x57 'W' */
+ 0x00, 0x00, /* 0000000000 */
+ 0xe1, 0xc0, /* 1110000111 */
+ 0xc0, 0xc0, /* 1100000011 */
+ 0xc0, 0xc0, /* 1100000011 */
+ 0xc0, 0xc0, /* 1100000011 */
+ 0xe0, 0xc0, /* 1110000011 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x77, 0x00, /* 0111011100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 88 0x58 'X' */
+ 0x00, 0x00, /* 0000000000 */
+ 0xf7, 0x80, /* 1111011110 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x1c, 0x00, /* 0001110000 */
+ 0x1c, 0x00, /* 0001110000 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0xf7, 0x80, /* 1111011110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 89 0x59 'Y' */
+ 0x00, 0x00, /* 0000000000 */
+ 0xf3, 0xc0, /* 1111001111 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 90 0x5a 'Z' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x3f, 0x80, /* 0011111110 */
+ 0x21, 0x80, /* 0010000110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x80, /* 0011000010 */
+ 0x3f, 0x80, /* 0011111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 91 0x5b '[' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 92 0x5c '\' */
+ 0x00, 0x00, /* 0000000000 */
+ 0xc0, 0x00, /* 1100000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x00, 0xc0, /* 0000000011 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 93 0x5d ']' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x3e, 0x00, /* 0011111000 */
+ 0x3e, 0x00, /* 0011111000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x3e, 0x00, /* 0011111000 */
+ 0x3e, 0x00, /* 0011111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 94 0x5e '^' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 95 0x5f '_' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 96 0x60 '`' */
+ 0x04, 0x00, /* 0000010000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 97 0x61 'a' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x21, 0x80, /* 0010000110 */
+ 0x07, 0x80, /* 0000011110 */
+ 0x39, 0x80, /* 0011100110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x73, 0x80, /* 0111001110 */
+ 0x3d, 0xc0, /* 0011110111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 98 0x62 'b' */
+ 0x20, 0x00, /* 0010000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0xe0, 0x00, /* 1110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x66, 0x00, /* 0110011000 */
+ 0x6f, 0x00, /* 0110111100 */
+ 0x73, 0x80, /* 0111001110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x71, 0x80, /* 0111000110 */
+ 0x7b, 0x00, /* 0111101100 */
+ 0x4e, 0x00, /* 0100111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 99 0x63 'c' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x37, 0x00, /* 0011011100 */
+ 0x23, 0x00, /* 0010001100 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x71, 0x00, /* 0111000100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 100 0x64 'd' */
+ 0x01, 0x80, /* 0000000110 */
+ 0x03, 0x80, /* 0000001110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x0d, 0x80, /* 0000110110 */
+ 0x37, 0x80, /* 0011011110 */
+ 0x23, 0x80, /* 0010001110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x73, 0x80, /* 0111001110 */
+ 0x35, 0x80, /* 0011010110 */
+ 0x19, 0xc0, /* 0001100111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 101 0x65 'e' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x19, 0x80, /* 0001100110 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 102 0x66 'f' */
+ 0x07, 0x00, /* 0000011100 */
+ 0x09, 0x80, /* 0000100110 */
+ 0x09, 0x80, /* 0000100110 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x7f, 0x00, /* 0111111100 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 103 0x67 'g' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1c, 0x80, /* 0001110010 */
+ 0x37, 0x80, /* 0011011110 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x7f, 0x00, /* 0111111100 */
+ 0x3f, 0x80, /* 0011111110 */
+ 0x21, 0x80, /* 0010000110 */
+ 0x40, 0x80, /* 0100000010 */
+ 0x7f, 0x00, /* 0111111100 */
+ 0x3e, 0x00, /* 0011111000 */
+
+ /* 104 0x68 'h' */
+ 0x10, 0x00, /* 0001000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x70, 0x00, /* 0111000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x37, 0x00, /* 0011011100 */
+ 0x3b, 0x80, /* 0011101110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x7b, 0xc0, /* 0111101111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 105 0x69 'i' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 106 0x6a 'j' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x07, 0x80, /* 0000011110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x41, 0x80, /* 0100000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x71, 0x80, /* 0111000110 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x1c, 0x00, /* 0001110000 */
+
+ /* 107 0x6b 'k' */
+ 0x60, 0x00, /* 0110000000 */
+ 0xe0, 0x00, /* 1110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x63, 0x80, /* 0110001110 */
+ 0x66, 0x00, /* 0110011000 */
+ 0x6c, 0x00, /* 0110110000 */
+ 0x78, 0x00, /* 0111100000 */
+ 0x70, 0x00, /* 0111000000 */
+ 0x78, 0x00, /* 0111100000 */
+ 0x6c, 0x00, /* 0110110000 */
+ 0x6e, 0x00, /* 0110111000 */
+ 0x67, 0x00, /* 0110011100 */
+ 0xf3, 0x80, /* 1111001110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 108 0x6c 'l' */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 109 0x6d 'm' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xdb, 0x80, /* 1101101110 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0xed, 0xc0, /* 1110110111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 110 0x6e 'n' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x6f, 0x00, /* 0110111100 */
+ 0x7b, 0x80, /* 0111101110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x7b, 0xc0, /* 0111101111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 111 0x6f 'o' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x66, 0x00, /* 0110011000 */
+ 0xc3, 0x00, /* 1100001100 */
+ 0xc1, 0x80, /* 1100000110 */
+ 0xc1, 0x80, /* 1100000110 */
+ 0xc1, 0x80, /* 1100000110 */
+ 0xc1, 0x80, /* 1100000110 */
+ 0xe1, 0x80, /* 1110000110 */
+ 0x73, 0x00, /* 0111001100 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 112 0x70 'p' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xde, 0x00, /* 1101111000 */
+ 0x76, 0x00, /* 0111011000 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x71, 0x80, /* 0111000110 */
+ 0x7b, 0x00, /* 0111101100 */
+ 0x7e, 0x00, /* 0111111000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0xf0, 0x00, /* 1111000000 */
+
+ /* 113 0x71 'q' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0e, 0xc0, /* 0000111011 */
+ 0x1b, 0x80, /* 0001101110 */
+ 0x33, 0x80, /* 0011001110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x71, 0x80, /* 0111000110 */
+ 0x3b, 0x80, /* 0011101110 */
+ 0x1f, 0x80, /* 0001111110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x03, 0xc0, /* 0000001111 */
+
+ /* 114 0x72 'r' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x73, 0x00, /* 0111001100 */
+ 0x35, 0x80, /* 0011010110 */
+ 0x39, 0x80, /* 0011100110 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x78, 0x00, /* 0111100000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 115 0x73 's' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x61, 0x00, /* 0110000100 */
+ 0x70, 0x00, /* 0111000000 */
+ 0x38, 0x00, /* 0011100000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x07, 0x00, /* 0000011100 */
+ 0x43, 0x00, /* 0100001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x7e, 0x00, /* 0111111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 116 0x74 't' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x08, 0x00, /* 0000100000 */
+ 0x08, 0x00, /* 0000100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x1c, 0x80, /* 0001110010 */
+ 0x0f, 0x00, /* 0000111100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 117 0x75 'u' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xf7, 0x80, /* 1111011110 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x77, 0x00, /* 0111011100 */
+ 0x3d, 0x80, /* 0011110110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 118 0x76 'v' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xf1, 0xc0, /* 1111000111 */
+ 0x60, 0xc0, /* 0110000011 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x19, 0x80, /* 0001100110 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x0f, 0x00, /* 0000111100 */
+ 0x0f, 0x00, /* 0000111100 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 119 0x77 'w' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xe3, 0xc0, /* 1110001111 */
+ 0xc1, 0x80, /* 1100000110 */
+ 0xc1, 0x80, /* 1100000110 */
+ 0xc1, 0x80, /* 1100000110 */
+ 0xc1, 0x80, /* 1100000110 */
+ 0x6b, 0x00, /* 0110101100 */
+ 0x6b, 0x00, /* 0110101100 */
+ 0x7e, 0x00, /* 0111111000 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 120 0x78 'x' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xf7, 0x80, /* 1111011110 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x1c, 0x00, /* 0001110000 */
+ 0x1c, 0x00, /* 0001110000 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x66, 0x00, /* 0110011000 */
+ 0x63, 0x00, /* 0110001100 */
+ 0xf7, 0x80, /* 1111011110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 121 0x79 'y' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xf3, 0xc0, /* 1111001111 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x78, 0x00, /* 0111100000 */
+ 0x70, 0x00, /* 0111000000 */
+
+ /* 122 0x7a 'z' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x43, 0x00, /* 0100001100 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x60, 0x80, /* 0110000010 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 123 0x7b '{' */
+ 0x07, 0x00, /* 0000011100 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x70, 0x00, /* 0111000000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x07, 0x00, /* 0000011100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 124 0x7c '|' */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 125 0x7d '}' */
+ 0x38, 0x00, /* 0011100000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x03, 0x80, /* 0000001110 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x38, 0x00, /* 0011100000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 126 0x7e '~' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x18, 0x80, /* 0001100010 */
+ 0x3d, 0x80, /* 0011110110 */
+ 0x6f, 0x00, /* 0110111100 */
+ 0x46, 0x00, /* 0100011000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 127 0x7f '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x12, 0x00, /* 0001001000 */
+ 0x21, 0x00, /* 0010000100 */
+ 0x40, 0x80, /* 0100000010 */
+ 0x40, 0x80, /* 0100000010 */
+ 0x40, 0x80, /* 0100000010 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 128 0x80 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x21, 0x80, /* 0010000110 */
+ 0x40, 0x80, /* 0100000010 */
+ 0x40, 0x00, /* 0100000000 */
+ 0x40, 0x00, /* 0100000000 */
+ 0x40, 0x00, /* 0100000000 */
+ 0x40, 0x00, /* 0100000000 */
+ 0x40, 0x00, /* 0100000000 */
+ 0x40, 0x00, /* 0100000000 */
+ 0x60, 0x80, /* 0110000010 */
+ 0x31, 0x00, /* 0011000100 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x08, 0x00, /* 0000100000 */
+ 0x04, 0x00, /* 0000010000 */
+ 0x02, 0x00, /* 0000001000 */
+ 0x02, 0x00, /* 0000001000 */
+ 0x1c, 0x00, /* 0001110000 */
+
+ /* 129 0x81 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x7b, 0x80, /* 0111101110 */
+ 0x31, 0x00, /* 0011000100 */
+ 0x31, 0x00, /* 0011000100 */
+ 0x31, 0x00, /* 0011000100 */
+ 0x31, 0x00, /* 0011000100 */
+ 0x31, 0x00, /* 0011000100 */
+ 0x31, 0x00, /* 0011000100 */
+ 0x31, 0x00, /* 0011000100 */
+ 0x3b, 0x00, /* 0011101100 */
+ 0x1c, 0x80, /* 0001110010 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 130 0x82 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x01, 0x00, /* 0000000100 */
+ 0x02, 0x00, /* 0000001000 */
+ 0x04, 0x00, /* 0000010000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x19, 0x80, /* 0001100110 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 131 0x83 '.' */
+ 0x04, 0x00, /* 0000010000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x21, 0x80, /* 0010000110 */
+ 0x07, 0x80, /* 0000011110 */
+ 0x39, 0x80, /* 0011100110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x73, 0x80, /* 0111001110 */
+ 0x3d, 0xc0, /* 0011110111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 132 0x84 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x21, 0x80, /* 0010000110 */
+ 0x07, 0x80, /* 0000011110 */
+ 0x39, 0x80, /* 0011100110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x73, 0x80, /* 0111001110 */
+ 0x3d, 0xc0, /* 0011110111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 133 0x85 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x21, 0x80, /* 0010000110 */
+ 0x07, 0x80, /* 0000011110 */
+ 0x39, 0x80, /* 0011100110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x73, 0x80, /* 0111001110 */
+ 0x3d, 0xc0, /* 0011110111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 134 0x86 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x21, 0x80, /* 0010000110 */
+ 0x07, 0x80, /* 0000011110 */
+ 0x39, 0x80, /* 0011100110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x73, 0x80, /* 0111001110 */
+ 0x3d, 0xc0, /* 0011110111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 135 0x87 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x20, 0x80, /* 0010000010 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x70, 0x80, /* 0111000010 */
+ 0x30, 0x80, /* 0011000010 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x04, 0x00, /* 0000010000 */
+ 0x02, 0x00, /* 0000001000 */
+ 0x01, 0x00, /* 0000000100 */
+ 0x0e, 0x00, /* 0000111000 */
+
+ /* 136 0x88 '.' */
+ 0x04, 0x00, /* 0000010000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x19, 0x80, /* 0001100110 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 137 0x89 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x19, 0x80, /* 0001100110 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 138 0x8a '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x19, 0x80, /* 0001100110 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 139 0x8b '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 140 0x8c '.' */
+ 0x08, 0x00, /* 0000100000 */
+ 0x1c, 0x00, /* 0001110000 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 141 0x8d '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 142 0x8e '.' */
+ 0x31, 0x80, /* 0011000110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x04, 0x00, /* 0000010000 */
+ 0x04, 0x00, /* 0000010000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x19, 0x00, /* 0001100100 */
+ 0x19, 0x00, /* 0001100100 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x31, 0x00, /* 0011000100 */
+ 0x31, 0x00, /* 0011000100 */
+ 0x60, 0x80, /* 0110000010 */
+ 0x60, 0x80, /* 0110000010 */
+ 0xf3, 0xc0, /* 1111001111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 143 0x8f '.' */
+ 0x04, 0x00, /* 0000010000 */
+ 0x0a, 0x00, /* 0000101000 */
+ 0x0a, 0x00, /* 0000101000 */
+ 0x04, 0x00, /* 0000010000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x19, 0x00, /* 0001100100 */
+ 0x19, 0x00, /* 0001100100 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x31, 0x00, /* 0011000100 */
+ 0x31, 0x00, /* 0011000100 */
+ 0x60, 0x80, /* 0110000010 */
+ 0x60, 0x80, /* 0110000010 */
+ 0xf3, 0xc0, /* 1111001111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 144 0x90 '.' */
+ 0x03, 0x00, /* 0000001100 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x30, 0x80, /* 0011000010 */
+ 0x30, 0x80, /* 0011000010 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x31, 0x00, /* 0011000100 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x31, 0x00, /* 0011000100 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x80, /* 0011000010 */
+ 0x30, 0x80, /* 0011000010 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 145 0x91 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x3b, 0x80, /* 0011101110 */
+ 0x6c, 0xc0, /* 0110110011 */
+ 0x4c, 0xc0, /* 0100110011 */
+ 0x0c, 0xc0, /* 0000110011 */
+ 0x3f, 0xc0, /* 0011111111 */
+ 0x6c, 0x00, /* 0110110000 */
+ 0xcc, 0x00, /* 1100110000 */
+ 0xcc, 0x00, /* 1100110000 */
+ 0xee, 0xc0, /* 1110111011 */
+ 0x7b, 0x80, /* 0111101110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 146 0x92 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x07, 0xc0, /* 0000011111 */
+ 0x0e, 0x40, /* 0000111001 */
+ 0x0e, 0x40, /* 0000111001 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x16, 0x00, /* 0001011000 */
+ 0x16, 0x80, /* 0001011010 */
+ 0x17, 0x80, /* 0001011110 */
+ 0x16, 0x80, /* 0001011010 */
+ 0x3e, 0x00, /* 0011111000 */
+ 0x26, 0x00, /* 0010011000 */
+ 0x26, 0x00, /* 0010011000 */
+ 0x46, 0x40, /* 0100011001 */
+ 0x46, 0x40, /* 0100011001 */
+ 0xef, 0xc0, /* 1110111111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 147 0x93 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x08, 0x00, /* 0000100000 */
+ 0x1c, 0x00, /* 0001110000 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x66, 0x00, /* 0110011000 */
+ 0xc3, 0x00, /* 1100001100 */
+ 0xc1, 0x80, /* 1100000110 */
+ 0xc1, 0x80, /* 1100000110 */
+ 0xc1, 0x80, /* 1100000110 */
+ 0xc1, 0x80, /* 1100000110 */
+ 0xe1, 0x80, /* 1110000110 */
+ 0x73, 0x00, /* 0111001100 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 148 0x94 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x66, 0x00, /* 0110011000 */
+ 0xc3, 0x00, /* 1100001100 */
+ 0xc1, 0x80, /* 1100000110 */
+ 0xc1, 0x80, /* 1100000110 */
+ 0xc1, 0x80, /* 1100000110 */
+ 0xc1, 0x80, /* 1100000110 */
+ 0xe1, 0x80, /* 1110000110 */
+ 0x73, 0x00, /* 0111001100 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 149 0x95 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x66, 0x00, /* 0110011000 */
+ 0xc3, 0x00, /* 1100001100 */
+ 0xc1, 0x80, /* 1100000110 */
+ 0xc1, 0x80, /* 1100000110 */
+ 0xc1, 0x80, /* 1100000110 */
+ 0xc1, 0x80, /* 1100000110 */
+ 0xe1, 0x80, /* 1110000110 */
+ 0x73, 0x00, /* 0111001100 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 150 0x96 '.' */
+ 0x08, 0x00, /* 0000100000 */
+ 0x1c, 0x00, /* 0001110000 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xf7, 0x80, /* 1111011110 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x77, 0x00, /* 0111011100 */
+ 0x3d, 0x80, /* 0011110110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 151 0x97 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xf7, 0x80, /* 1111011110 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x77, 0x00, /* 0111011100 */
+ 0x3d, 0x80, /* 0011110110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 152 0x98 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xf3, 0xc0, /* 1111001111 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x78, 0x00, /* 0111100000 */
+ 0x70, 0x00, /* 0111000000 */
+
+ /* 153 0x99 '.' */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x17, 0x00, /* 0001011100 */
+ 0x23, 0x00, /* 0010001100 */
+ 0x21, 0x80, /* 0010000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x21, 0x00, /* 0010000100 */
+ 0x31, 0x00, /* 0011000100 */
+ 0x1a, 0x00, /* 0001101000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 154 0x9a '.' */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xf1, 0xc0, /* 1111000111 */
+ 0x60, 0x80, /* 0110000010 */
+ 0x60, 0x80, /* 0110000010 */
+ 0x60, 0x80, /* 0110000010 */
+ 0x60, 0x80, /* 0110000010 */
+ 0x60, 0x80, /* 0110000010 */
+ 0x60, 0x80, /* 0110000010 */
+ 0x60, 0x80, /* 0110000010 */
+ 0x60, 0x80, /* 0110000010 */
+ 0x71, 0x00, /* 0111000100 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 155 0x9b '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x1f, 0x80, /* 0001111110 */
+ 0x36, 0x80, /* 0011011010 */
+ 0x26, 0x00, /* 0010011000 */
+ 0x66, 0x00, /* 0110011000 */
+ 0x66, 0x00, /* 0110011000 */
+ 0x66, 0x00, /* 0110011000 */
+ 0x66, 0x00, /* 0110011000 */
+ 0x76, 0x00, /* 0111011000 */
+ 0x36, 0x80, /* 0011011010 */
+ 0x1f, 0x80, /* 0001111110 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 156 0x9c '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x3b, 0x00, /* 0011101100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x7e, 0x00, /* 0111111000 */
+ 0x7e, 0x00, /* 0111111000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x7c, 0x80, /* 0111110010 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x43, 0x00, /* 0100001100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 157 0x9d '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x40, 0x80, /* 0100000010 */
+ 0x40, 0x80, /* 0100000010 */
+ 0x21, 0x00, /* 0010000100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 158 0x9e '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0xbf, 0x00, /* 1011111100 */
+ 0x40, 0x80, /* 0100000010 */
+ 0x40, 0x80, /* 0100000010 */
+ 0x7f, 0x00, /* 0111111100 */
+ 0x40, 0x00, /* 0100000000 */
+ 0x48, 0x00, /* 0100100000 */
+ 0x48, 0x00, /* 0100100000 */
+ 0x5e, 0x00, /* 0101111000 */
+ 0x48, 0x00, /* 0100100000 */
+ 0x48, 0x00, /* 0100100000 */
+ 0x48, 0x00, /* 0100100000 */
+ 0x48, 0x80, /* 0100100010 */
+ 0x47, 0x00, /* 0100011100 */
+ 0xe0, 0x00, /* 1110000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 159 0x9f '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x04, 0x80, /* 0000010010 */
+ 0x08, 0x00, /* 0000100000 */
+ 0x08, 0x00, /* 0000100000 */
+ 0x08, 0x00, /* 0000100000 */
+ 0x08, 0x00, /* 0000100000 */
+ 0x09, 0x00, /* 0000100100 */
+ 0x3e, 0x00, /* 0011111000 */
+ 0x48, 0x00, /* 0100100000 */
+ 0x08, 0x00, /* 0000100000 */
+ 0x08, 0x00, /* 0000100000 */
+ 0x08, 0x00, /* 0000100000 */
+ 0x08, 0x00, /* 0000100000 */
+ 0x08, 0x00, /* 0000100000 */
+ 0x90, 0x00, /* 1001000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 160 0xa0 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x21, 0x80, /* 0010000110 */
+ 0x07, 0x80, /* 0000011110 */
+ 0x39, 0x80, /* 0011100110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x73, 0x80, /* 0111001110 */
+ 0x3d, 0xc0, /* 0011110111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 161 0xa1 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 162 0xa2 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x66, 0x00, /* 0110011000 */
+ 0xc3, 0x00, /* 1100001100 */
+ 0xc1, 0x80, /* 1100000110 */
+ 0xc1, 0x80, /* 1100000110 */
+ 0xc1, 0x80, /* 1100000110 */
+ 0xc1, 0x80, /* 1100000110 */
+ 0xe1, 0x80, /* 1110000110 */
+ 0x73, 0x00, /* 0111001100 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 163 0xa3 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xf7, 0x80, /* 1111011110 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x77, 0x00, /* 0111011100 */
+ 0x3d, 0x80, /* 0011110110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 164 0xa4 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x38, 0x80, /* 0011100010 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x47, 0x00, /* 0100011100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x6f, 0x00, /* 0110111100 */
+ 0x7b, 0x80, /* 0111101110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x7b, 0xc0, /* 0111101111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 165 0xa5 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x38, 0x80, /* 0011100010 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x47, 0x00, /* 0100011100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xe3, 0xc0, /* 1110001111 */
+ 0x71, 0x80, /* 0111000110 */
+ 0x79, 0x80, /* 0111100110 */
+ 0x79, 0x80, /* 0111100110 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0x67, 0x80, /* 0110011110 */
+ 0x63, 0x80, /* 0110001110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0xf0, 0xc0, /* 1111000011 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 166 0xa6 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x3e, 0x00, /* 0011111000 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x0f, 0x00, /* 0000111100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x67, 0x00, /* 0110011100 */
+ 0x3b, 0x80, /* 0011101110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 167 0xa7 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x21, 0x80, /* 0010000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x00, /* 0110000100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x1c, 0x00, /* 0001110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 168 0xa8 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x80, /* 0110000010 */
+ 0x73, 0x80, /* 0111001110 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 169 0xa9 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 170 0xaa '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 171 0xab '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x20, 0x00, /* 0010000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x20, 0x00, /* 0010000000 */
+ 0x20, 0x80, /* 0010000010 */
+ 0x21, 0x00, /* 0010000100 */
+ 0x22, 0x00, /* 0010001000 */
+ 0x74, 0x00, /* 0111010000 */
+ 0x08, 0x00, /* 0000100000 */
+ 0x17, 0x00, /* 0001011100 */
+ 0x28, 0x80, /* 0010100010 */
+ 0x43, 0x00, /* 0100001100 */
+ 0x04, 0x00, /* 0000010000 */
+ 0x08, 0x00, /* 0000100000 */
+ 0x0f, 0x80, /* 0000111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 172 0xac '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x20, 0x00, /* 0010000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x20, 0x00, /* 0010000000 */
+ 0x20, 0x80, /* 0010000010 */
+ 0x21, 0x00, /* 0010000100 */
+ 0x22, 0x00, /* 0010001000 */
+ 0x74, 0x00, /* 0111010000 */
+ 0x09, 0x00, /* 0000100100 */
+ 0x13, 0x00, /* 0001001100 */
+ 0x25, 0x00, /* 0010010100 */
+ 0x49, 0x00, /* 0100100100 */
+ 0x1f, 0x80, /* 0001111110 */
+ 0x01, 0x00, /* 0000000100 */
+ 0x01, 0x00, /* 0000000100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 173 0xad '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 174 0xae '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0d, 0x80, /* 0000110110 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x6c, 0x00, /* 0110110000 */
+ 0xd8, 0x00, /* 1101100000 */
+ 0x6c, 0x00, /* 0110110000 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x0d, 0x80, /* 0000110110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 175 0xaf '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x6c, 0x00, /* 0110110000 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x0d, 0x80, /* 0000110110 */
+ 0x06, 0xc0, /* 0000011011 */
+ 0x0d, 0x80, /* 0000110110 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x6c, 0x00, /* 0110110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 176 0xb0 '.' */
+ 0xc3, 0x00, /* 1100001100 */
+ 0x41, 0x00, /* 0100000100 */
+ 0x18, 0x40, /* 0001100001 */
+ 0x10, 0x40, /* 0001000001 */
+ 0xc3, 0x00, /* 1100001100 */
+ 0x41, 0x00, /* 0100000100 */
+ 0x18, 0x40, /* 0001100001 */
+ 0x10, 0x40, /* 0001000001 */
+ 0xc3, 0x00, /* 1100001100 */
+ 0x41, 0x00, /* 0100000100 */
+ 0x18, 0x40, /* 0001100001 */
+ 0x10, 0x40, /* 0001000001 */
+ 0xc3, 0x00, /* 1100001100 */
+ 0x41, 0x00, /* 0100000100 */
+ 0x18, 0x40, /* 0001100001 */
+ 0x10, 0x40, /* 0001000001 */
+ 0xc3, 0x00, /* 1100001100 */
+ 0x41, 0x00, /* 0100000100 */
+
+ /* 177 0xb1 '.' */
+ 0x11, 0x00, /* 0001000100 */
+ 0xbb, 0x80, /* 1011101110 */
+ 0x11, 0x00, /* 0001000100 */
+ 0x44, 0x40, /* 0100010001 */
+ 0xee, 0xc0, /* 1110111011 */
+ 0x44, 0x40, /* 0100010001 */
+ 0x11, 0x00, /* 0001000100 */
+ 0xbb, 0x80, /* 1011101110 */
+ 0x11, 0x00, /* 0001000100 */
+ 0x44, 0x40, /* 0100010001 */
+ 0xee, 0xc0, /* 1110111011 */
+ 0x44, 0x40, /* 0100010001 */
+ 0x11, 0x00, /* 0001000100 */
+ 0xbb, 0x80, /* 1011101110 */
+ 0x11, 0x00, /* 0001000100 */
+ 0x44, 0x40, /* 0100010001 */
+ 0xee, 0xc0, /* 1110111011 */
+ 0x44, 0x40, /* 0100010001 */
+
+ /* 178 0xb2 '.' */
+ 0x3c, 0xc0, /* 0011110011 */
+ 0xbe, 0xc0, /* 1011111011 */
+ 0xe7, 0x80, /* 1110011110 */
+ 0xef, 0x80, /* 1110111110 */
+ 0x3c, 0xc0, /* 0011110011 */
+ 0xbe, 0xc0, /* 1011111011 */
+ 0xe7, 0x80, /* 1110011110 */
+ 0xef, 0x80, /* 1110111110 */
+ 0x3c, 0xc0, /* 0011110011 */
+ 0xbe, 0xc0, /* 1011111011 */
+ 0xe7, 0x80, /* 1110011110 */
+ 0xef, 0x80, /* 1110111110 */
+ 0x3c, 0xc0, /* 0011110011 */
+ 0xbe, 0xc0, /* 1011111011 */
+ 0xe7, 0x80, /* 1110011110 */
+ 0xef, 0x80, /* 1110111110 */
+ 0x3c, 0xc0, /* 0011110011 */
+ 0xbe, 0xc0, /* 1011111011 */
+
+ /* 179 0xb3 '.' */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+
+ /* 180 0xb4 '.' */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0xfc, 0x00, /* 1111110000 */
+ 0xfc, 0x00, /* 1111110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+
+ /* 181 0xb5 '.' */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0xfc, 0x00, /* 1111110000 */
+ 0xfc, 0x00, /* 1111110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0xfc, 0x00, /* 1111110000 */
+ 0xfc, 0x00, /* 1111110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+
+ /* 182 0xb6 '.' */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0xfb, 0x00, /* 1111101100 */
+ 0xfb, 0x00, /* 1111101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+
+ /* 183 0xb7 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xff, 0x00, /* 1111111100 */
+ 0xff, 0x00, /* 1111111100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+
+ /* 184 0xb8 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xfc, 0x00, /* 1111110000 */
+ 0xfc, 0x00, /* 1111110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0xfc, 0x00, /* 1111110000 */
+ 0xfc, 0x00, /* 1111110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+
+ /* 185 0xb9 '.' */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0xfb, 0x00, /* 1111101100 */
+ 0xfb, 0x00, /* 1111101100 */
+ 0x03, 0x00, /* 0000001100 */
+ 0xfb, 0x00, /* 1111101100 */
+ 0xfb, 0x00, /* 1111101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+
+ /* 186 0xba '.' */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+
+ /* 187 0xbb '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xff, 0x00, /* 1111111100 */
+ 0xff, 0x00, /* 1111111100 */
+ 0x03, 0x00, /* 0000001100 */
+ 0xfb, 0x00, /* 1111101100 */
+ 0xfb, 0x00, /* 1111101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+
+ /* 188 0xbc '.' */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0xfb, 0x00, /* 1111101100 */
+ 0xfb, 0x00, /* 1111101100 */
+ 0x03, 0x00, /* 0000001100 */
+ 0xff, 0x00, /* 1111111100 */
+ 0xff, 0x00, /* 1111111100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 189 0xbd '.' */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0xff, 0x00, /* 1111111100 */
+ 0xff, 0x00, /* 1111111100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 190 0xbe '.' */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0xfc, 0x00, /* 1111110000 */
+ 0xfc, 0x00, /* 1111110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0xfc, 0x00, /* 1111110000 */
+ 0xfc, 0x00, /* 1111110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 191 0xbf '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xfc, 0x00, /* 1111110000 */
+ 0xfc, 0x00, /* 1111110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+
+ /* 192 0xc0 '.' */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0f, 0xc0, /* 0000111111 */
+ 0x0f, 0xc0, /* 0000111111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 193 0xc1 '.' */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 194 0xc2 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+
+ /* 195 0xc3 '.' */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0f, 0xc0, /* 0000111111 */
+ 0x0f, 0xc0, /* 0000111111 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+
+ /* 196 0xc4 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 197 0xc5 '.' */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+
+ /* 198 0xc6 '.' */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0f, 0xc0, /* 0000111111 */
+ 0x0f, 0xc0, /* 0000111111 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0f, 0xc0, /* 0000111111 */
+ 0x0f, 0xc0, /* 0000111111 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+
+ /* 199 0xc7 '.' */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0xc0, /* 0001101111 */
+ 0x1b, 0xc0, /* 0001101111 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+
+ /* 200 0xc8 '.' */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0xc0, /* 0001101111 */
+ 0x1b, 0xc0, /* 0001101111 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x1f, 0xc0, /* 0001111111 */
+ 0x1f, 0xc0, /* 0001111111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 201 0xc9 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1f, 0xc0, /* 0001111111 */
+ 0x1f, 0xc0, /* 0001111111 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x1b, 0xc0, /* 0001101111 */
+ 0x1b, 0xc0, /* 0001101111 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+
+ /* 202 0xca '.' */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0xfb, 0xc0, /* 1111101111 */
+ 0xfb, 0xc0, /* 1111101111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 203 0xcb '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xfb, 0xc0, /* 1111101111 */
+ 0xfb, 0xc0, /* 1111101111 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+
+ /* 204 0xcc '.' */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0xc0, /* 0001101111 */
+ 0x1b, 0xc0, /* 0001101111 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x1b, 0xc0, /* 0001101111 */
+ 0x1b, 0xc0, /* 0001101111 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+
+ /* 205 0xcd '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 206 0xce '.' */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0xfb, 0xc0, /* 1111101111 */
+ 0xfb, 0xc0, /* 1111101111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xfb, 0xc0, /* 1111101111 */
+ 0xfb, 0xc0, /* 1111101111 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+
+ /* 207 0xcf '.' */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 208 0xd0 '.' */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 209 0xd1 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+
+ /* 210 0xd2 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+
+ /* 211 0xd3 '.' */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1f, 0xc0, /* 0001111111 */
+ 0x1f, 0xc0, /* 0001111111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 212 0xd4 '.' */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0f, 0xc0, /* 0000111111 */
+ 0x0f, 0xc0, /* 0000111111 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0f, 0xc0, /* 0000111111 */
+ 0x0f, 0xc0, /* 0000111111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 213 0xd5 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0f, 0xc0, /* 0000111111 */
+ 0x0f, 0xc0, /* 0000111111 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0f, 0xc0, /* 0000111111 */
+ 0x0f, 0xc0, /* 0000111111 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+
+ /* 214 0xd6 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1f, 0xc0, /* 0001111111 */
+ 0x1f, 0xc0, /* 0001111111 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+
+ /* 215 0xd7 '.' */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+ 0x1b, 0x00, /* 0001101100 */
+
+ /* 216 0xd8 '.' */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+
+ /* 217 0xd9 '.' */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0xfc, 0x00, /* 1111110000 */
+ 0xfc, 0x00, /* 1111110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 218 0xda '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0f, 0xc0, /* 0000111111 */
+ 0x0f, 0xc0, /* 0000111111 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+
+ /* 219 0xdb '.' */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+
+ /* 220 0xdc '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+
+ /* 221 0xdd '.' */
+ 0xf8, 0x00, /* 1111100000 */
+ 0xf8, 0x00, /* 1111100000 */
+ 0xf8, 0x00, /* 1111100000 */
+ 0xf8, 0x00, /* 1111100000 */
+ 0xf8, 0x00, /* 1111100000 */
+ 0xf8, 0x00, /* 1111100000 */
+ 0xf8, 0x00, /* 1111100000 */
+ 0xf8, 0x00, /* 1111100000 */
+ 0xf8, 0x00, /* 1111100000 */
+ 0xf8, 0x00, /* 1111100000 */
+ 0xf8, 0x00, /* 1111100000 */
+ 0xf8, 0x00, /* 1111100000 */
+ 0xf8, 0x00, /* 1111100000 */
+ 0xf8, 0x00, /* 1111100000 */
+ 0xf8, 0x00, /* 1111100000 */
+ 0xf8, 0x00, /* 1111100000 */
+ 0xf8, 0x00, /* 1111100000 */
+ 0xf8, 0x00, /* 1111100000 */
+
+ /* 222 0xde '.' */
+ 0x07, 0xc0, /* 0000011111 */
+ 0x07, 0xc0, /* 0000011111 */
+ 0x07, 0xc0, /* 0000011111 */
+ 0x07, 0xc0, /* 0000011111 */
+ 0x07, 0xc0, /* 0000011111 */
+ 0x07, 0xc0, /* 0000011111 */
+ 0x07, 0xc0, /* 0000011111 */
+ 0x07, 0xc0, /* 0000011111 */
+ 0x07, 0xc0, /* 0000011111 */
+ 0x07, 0xc0, /* 0000011111 */
+ 0x07, 0xc0, /* 0000011111 */
+ 0x07, 0xc0, /* 0000011111 */
+ 0x07, 0xc0, /* 0000011111 */
+ 0x07, 0xc0, /* 0000011111 */
+ 0x07, 0xc0, /* 0000011111 */
+ 0x07, 0xc0, /* 0000011111 */
+ 0x07, 0xc0, /* 0000011111 */
+ 0x07, 0xc0, /* 0000011111 */
+
+ /* 223 0xdf '.' */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0xff, 0xc0, /* 1111111111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 224 0xe0 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1c, 0x80, /* 0001110010 */
+ 0x35, 0x80, /* 0011010110 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x37, 0x80, /* 0011011110 */
+ 0x1c, 0x80, /* 0001110010 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 225 0xe1 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x6f, 0x00, /* 0110111100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x6e, 0x00, /* 0110111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 226 0xe2 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 227 0xe3 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 228 0xe4 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xff, 0x80, /* 1111111110 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x80, /* 0011000010 */
+ 0x61, 0x80, /* 0110000110 */
+ 0xff, 0x80, /* 1111111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 229 0xe5 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1f, 0xc0, /* 0001111111 */
+ 0x36, 0x00, /* 0011011000 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x3e, 0x00, /* 0011111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 230 0xe6 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x73, 0x80, /* 0111001110 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0xc0, 0x00, /* 1100000000 */
+
+ /* 231 0xe7 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x36, 0x40, /* 0011011001 */
+ 0x5e, 0x00, /* 0101111000 */
+ 0x8c, 0x00, /* 1000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 232 0xe8 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 233 0xe9 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x60, 0xc0, /* 0110000011 */
+ 0x7f, 0xc0, /* 0111111111 */
+ 0x7f, 0xc0, /* 0111111111 */
+ 0x60, 0xc0, /* 0110000011 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x31, 0x80, /* 0011000110 */
+ 0x1f, 0x00, /* 0001111100 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 234 0xea '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x61, 0x80, /* 0110000110 */
+ 0xc0, 0xc0, /* 1100000011 */
+ 0xc0, 0xc0, /* 1100000011 */
+ 0xc0, 0xc0, /* 1100000011 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0xf3, 0xc0, /* 1111001111 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 235 0xeb '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x07, 0x00, /* 0000011100 */
+ 0x1f, 0x80, /* 0001111110 */
+ 0x30, 0xc0, /* 0011000011 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x3e, 0x00, /* 0011111000 */
+ 0x66, 0x00, /* 0110011000 */
+ 0xc3, 0x00, /* 1100001100 */
+ 0xc3, 0x00, /* 1100001100 */
+ 0xc3, 0x00, /* 1100001100 */
+ 0x66, 0x00, /* 0110011000 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 236 0xec '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0xcc, 0xc0, /* 1100110011 */
+ 0xcc, 0xc0, /* 1100110011 */
+ 0xcc, 0xc0, /* 1100110011 */
+ 0xcc, 0xc0, /* 1100110011 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 237 0xed '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x01, 0x80, /* 0000000110 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x37, 0x00, /* 0011011100 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0xcc, 0xc0, /* 1100110011 */
+ 0xcc, 0xc0, /* 1100110011 */
+ 0xcc, 0xc0, /* 1100110011 */
+ 0xcc, 0xc0, /* 1100110011 */
+ 0x6d, 0x80, /* 0110110110 */
+ 0x3b, 0x00, /* 0011101100 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x60, 0x00, /* 0110000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 238 0xee '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x03, 0x80, /* 0000001110 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x3f, 0x80, /* 0011111110 */
+ 0x3f, 0x80, /* 0011111110 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x03, 0x80, /* 0000001110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 239 0xef '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x61, 0x80, /* 0110000110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 240 0xf0 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 241 0xf1 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 242 0xf2 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xe0, 0x00, /* 1110000000 */
+ 0x38, 0x00, /* 0011100000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x03, 0x80, /* 0000001110 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x38, 0x00, /* 0011100000 */
+ 0xe0, 0x00, /* 1110000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xff, 0x00, /* 1111111100 */
+ 0xff, 0x00, /* 1111111100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 243 0xf3 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x03, 0x80, /* 0000001110 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x38, 0x00, /* 0011100000 */
+ 0xe0, 0x00, /* 1110000000 */
+ 0x38, 0x00, /* 0011100000 */
+ 0x0e, 0x00, /* 0000111000 */
+ 0x03, 0x80, /* 0000001110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0xff, 0x80, /* 1111111110 */
+ 0xff, 0x80, /* 1111111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 244 0xf4 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x30, 0x00, /* 0011000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 245 0xf5 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x03, 0x00, /* 0000001100 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 246 0xf6 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 247 0xf7 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x38, 0x00, /* 0011100000 */
+ 0x6c, 0x00, /* 0110110000 */
+ 0x06, 0xc0, /* 0000011011 */
+ 0x03, 0x80, /* 0000001110 */
+ 0x38, 0x00, /* 0011100000 */
+ 0x6c, 0x00, /* 0110110000 */
+ 0x06, 0xc0, /* 0000011011 */
+ 0x03, 0x80, /* 0000001110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 248 0xf8 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x33, 0x00, /* 0011001100 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 249 0xf9 '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 250 0xfa '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 251 0xfb '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x0f, 0xc0, /* 0000111111 */
+ 0x0f, 0xc0, /* 0000111111 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0xcc, 0x00, /* 1100110000 */
+ 0x6c, 0x00, /* 0110110000 */
+ 0x3c, 0x00, /* 0011110000 */
+ 0x1c, 0x00, /* 0001110000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 252 0xfc '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x27, 0x00, /* 0010011100 */
+ 0x7b, 0x00, /* 0111101100 */
+ 0x31, 0x00, /* 0011000100 */
+ 0x31, 0x00, /* 0011000100 */
+ 0x31, 0x00, /* 0011000100 */
+ 0x7b, 0x80, /* 0111101110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 253 0xfd '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x1e, 0x00, /* 0001111000 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x63, 0x00, /* 0110001100 */
+ 0x43, 0x00, /* 0100001100 */
+ 0x06, 0x00, /* 0000011000 */
+ 0x0c, 0x00, /* 0000110000 */
+ 0x18, 0x00, /* 0001100000 */
+ 0x30, 0x80, /* 0011000010 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x7f, 0x80, /* 0111111110 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 254 0xfe '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x3f, 0x00, /* 0011111100 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+ /* 255 0xff '.' */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+ 0x00, 0x00, /* 0000000000 */
+
+};
+
+
+struct font_desc font_10x18 = {
+ FONT10x18_IDX,
+ "10x18",
+ 10,
+ 18,
+ fontdata_10x18,
+#ifdef __sparc__
+ 5
+#else
+ -1
+#endif
+};
diff --git a/drivers/video/console/font_7x14.c b/drivers/video/console/font_7x14.c
new file mode 100644
index 00000000000..1fa7fcf2ff7
--- /dev/null
+++ b/drivers/video/console/font_7x14.c
@@ -0,0 +1,4118 @@
+/**************************************/
+/* this file adapted from font_8x16.c */
+/* by Jurriaan Kalkman 05-2005 */
+/**************************************/
+
+#include <linux/font.h>
+
+#define FONTDATAMAX 3584
+
+static unsigned char fontdata_7x14[FONTDATAMAX] = {
+
+ /* 0 0x00 '^@' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 1 0x01 '^A' */
+ 0x00, /* 0000000 */
+ 0x7c, /* 0111110 */
+ 0x82, /* 1000001 */
+ 0xaa, /* 1010101 */
+ 0x82, /* 1000001 */
+ 0x82, /* 1000001 */
+ 0xba, /* 1011101 */
+ 0x92, /* 1001001 */
+ 0x82, /* 1000001 */
+ 0x7c, /* 0111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 2 0x02 '^B' */
+ 0x00, /* 0000000 */
+ 0x7c, /* 0111110 */
+ 0xfe, /* 1111111 */
+ 0xd6, /* 1101011 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xc6, /* 1100011 */
+ 0xee, /* 1110111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0x7c, /* 0111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 3 0x03 '^C' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x6c, /* 0110110 */
+ 0x7c, /* 0111110 */
+ 0xfe, /* 1111111 */
+ 0x7c, /* 0111110 */
+ 0x38, /* 0011100 */
+ 0x18, /* 0001100 */
+ 0x10, /* 0001000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 4 0x04 '^D' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x10, /* 0001000 */
+ 0x38, /* 0011100 */
+ 0x7c, /* 0111110 */
+ 0xfe, /* 1111111 */
+ 0x7c, /* 0111110 */
+ 0x38, /* 0011100 */
+ 0x10, /* 0001000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 5 0x05 '^E' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x38, /* 0011100 */
+ 0x38, /* 0011100 */
+ 0x38, /* 0011100 */
+ 0xee, /* 1110111 */
+ 0xee, /* 1110111 */
+ 0xee, /* 1110111 */
+ 0x10, /* 0001000 */
+ 0x10, /* 0001000 */
+ 0x38, /* 0011100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 6 0x06 '^F' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x10, /* 0001000 */
+ 0x38, /* 0011100 */
+ 0x7c, /* 0111110 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0x7c, /* 0111110 */
+ 0x10, /* 0001000 */
+ 0x10, /* 0001000 */
+ 0x38, /* 0011100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 7 0x07 '^G' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x18, /* 0001100 */
+ 0x3c, /* 0011110 */
+ 0x3c, /* 0011110 */
+ 0x18, /* 0001100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 8 0x08 '^H' */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xe6, /* 1110011 */
+ 0xc2, /* 1100001 */
+ 0xc2, /* 1100001 */
+ 0xe6, /* 1110011 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+
+ /* 9 0x09 '^I' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x38, /* 0011100 */
+ 0x6c, /* 0110110 */
+ 0x44, /* 0100010 */
+ 0x6c, /* 0110110 */
+ 0x38, /* 0011100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 10 0x0a '^J' */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xc6, /* 1100011 */
+ 0x92, /* 1001001 */
+ 0xba, /* 1011101 */
+ 0x92, /* 1001001 */
+ 0xc6, /* 1100011 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+
+ /* 11 0x0b '^K' */
+ 0x00, /* 0000000 */
+ 0x1e, /* 0001111 */
+ 0x0e, /* 0000111 */
+ 0x1a, /* 0001101 */
+ 0x1a, /* 0001101 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 12 0x0c '^L' */
+ 0x00, /* 0000000 */
+ 0x3c, /* 0011110 */
+ 0x66, /* 0110011 */
+ 0x66, /* 0110011 */
+ 0x66, /* 0110011 */
+ 0x66, /* 0110011 */
+ 0x3c, /* 0011110 */
+ 0x18, /* 0001100 */
+ 0x7e, /* 0111111 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 13 0x0d '^M' */
+ 0x00, /* 0000000 */
+ 0x3e, /* 0011111 */
+ 0x36, /* 0011011 */
+ 0x3e, /* 0011111 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x70, /* 0111000 */
+ 0xf0, /* 1111000 */
+ 0xe0, /* 1110000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 14 0x0e '^N' */
+ 0x00, /* 0000000 */
+ 0x7e, /* 0111111 */
+ 0x66, /* 0110011 */
+ 0x7e, /* 0111111 */
+ 0x66, /* 0110011 */
+ 0x66, /* 0110011 */
+ 0x66, /* 0110011 */
+ 0x66, /* 0110011 */
+ 0x6e, /* 0110111 */
+ 0xee, /* 1110111 */
+ 0xec, /* 1110110 */
+ 0xc0, /* 1100000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 15 0x0f '^O' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x10, /* 0001000 */
+ 0x10, /* 0001000 */
+ 0xd6, /* 1101011 */
+ 0x38, /* 0011100 */
+ 0xee, /* 1110111 */
+ 0x38, /* 0011100 */
+ 0xd6, /* 1101011 */
+ 0x10, /* 0001000 */
+ 0x10, /* 0001000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 16 0x10 '^P' */
+ 0x00, /* 0000000 */
+ 0x80, /* 1000000 */
+ 0xc0, /* 1100000 */
+ 0xe0, /* 1110000 */
+ 0xf0, /* 1111000 */
+ 0xfc, /* 1111110 */
+ 0xf0, /* 1111000 */
+ 0xe0, /* 1110000 */
+ 0xc0, /* 1100000 */
+ 0x80, /* 1000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 17 0x11 '^Q' */
+ 0x00, /* 0000000 */
+ 0x04, /* 0000010 */
+ 0x0c, /* 0000110 */
+ 0x1c, /* 0001110 */
+ 0x3c, /* 0011110 */
+ 0xfc, /* 1111110 */
+ 0x3c, /* 0011110 */
+ 0x1c, /* 0001110 */
+ 0x0c, /* 0000110 */
+ 0x04, /* 0000010 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 18 0x12 '^R' */
+ 0x00, /* 0000000 */
+ 0x18, /* 0001100 */
+ 0x3c, /* 0011110 */
+ 0x7e, /* 0111111 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x7e, /* 0111111 */
+ 0x3c, /* 0011110 */
+ 0x18, /* 0001100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 19 0x13 '^S' */
+ 0x00, /* 0000000 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x00, /* 0000000 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 20 0x14 '^T' */
+ 0x00, /* 0000000 */
+ 0x7e, /* 0111111 */
+ 0xd4, /* 1101010 */
+ 0xd4, /* 1101010 */
+ 0xd4, /* 1101010 */
+ 0x74, /* 0111010 */
+ 0x14, /* 0001010 */
+ 0x14, /* 0001010 */
+ 0x14, /* 0001010 */
+ 0x14, /* 0001010 */
+ 0x16, /* 0001011 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 21 0x15 '^U' */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0x60, /* 0110000 */
+ 0x38, /* 0011100 */
+ 0x6c, /* 0110110 */
+ 0xc6, /* 1100011 */
+ 0xc6, /* 1100011 */
+ 0x6c, /* 0110110 */
+ 0x38, /* 0011100 */
+ 0x18, /* 0001100 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 22 0x16 '^V' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xfc, /* 1111110 */
+ 0xfc, /* 1111110 */
+ 0xfc, /* 1111110 */
+ 0xfc, /* 1111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 23 0x17 '^W' */
+ 0x00, /* 0000000 */
+ 0x18, /* 0001100 */
+ 0x3c, /* 0011110 */
+ 0x7e, /* 0111111 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x7e, /* 0111111 */
+ 0x3c, /* 0011110 */
+ 0x18, /* 0001100 */
+ 0x7e, /* 0111111 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 24 0x18 '^X' */
+ 0x00, /* 0000000 */
+ 0x18, /* 0001100 */
+ 0x3c, /* 0011110 */
+ 0x7e, /* 0111111 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 25 0x19 '^Y' */
+ 0x00, /* 0000000 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x7e, /* 0111111 */
+ 0x3c, /* 0011110 */
+ 0x18, /* 0001100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 26 0x1a '^Z' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x30, /* 0011000 */
+ 0x18, /* 0001100 */
+ 0xfc, /* 1111110 */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 27 0x1b '^[' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x30, /* 0011000 */
+ 0x60, /* 0110000 */
+ 0xfc, /* 1111110 */
+ 0x60, /* 0110000 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 28 0x1c '^\' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xfc, /* 1111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 29 0x1d '^]' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x28, /* 0010100 */
+ 0x6c, /* 0110110 */
+ 0xfe, /* 1111111 */
+ 0x6c, /* 0110110 */
+ 0x28, /* 0010100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 30 0x1e '^^' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x78, /* 0111100 */
+ 0x78, /* 0111100 */
+ 0xfc, /* 1111110 */
+ 0xfc, /* 1111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 31 0x1f '^_' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xfc, /* 1111110 */
+ 0xfc, /* 1111110 */
+ 0x78, /* 0111100 */
+ 0x78, /* 0111100 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 32 0x20 ' ' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 33 0x21 '!' */
+ 0x00, /* 0000000 */
+ 0x18, /* 0001100 */
+ 0x3c, /* 0011110 */
+ 0x3c, /* 0011110 */
+ 0x3c, /* 0011110 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x00, /* 0000000 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 34 0x22 '"' */
+ 0x00, /* 0000000 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x28, /* 0010100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 35 0x23 '#' */
+ 0x00, /* 0000000 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 36 0x24 '$' */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xc4, /* 1100010 */
+ 0xc0, /* 1100000 */
+ 0x78, /* 0111100 */
+ 0x0c, /* 0000110 */
+ 0x8c, /* 1000110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+
+ /* 37 0x25 '%' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xc0, /* 1100000 */
+ 0xc4, /* 1100010 */
+ 0x0c, /* 0000110 */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0x60, /* 0110000 */
+ 0xcc, /* 1100110 */
+ 0x8c, /* 1000110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 38 0x26 '&' */
+ 0x00, /* 0000000 */
+ 0x38, /* 0011100 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x38, /* 0011100 */
+ 0x78, /* 0111100 */
+ 0xde, /* 1101111 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xdc, /* 1101110 */
+ 0x76, /* 0111011 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 39 0x27 ''' */
+ 0x00, /* 0000000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x60, /* 0110000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 40 0x28 '(' */
+ 0x00, /* 0000000 */
+ 0x0c, /* 0000110 */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x18, /* 0001100 */
+ 0x0c, /* 0000110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 41 0x29 ')' */
+ 0x00, /* 0000000 */
+ 0x30, /* 0011000 */
+ 0x18, /* 0001100 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 42 0x2a '*' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x6c, /* 0110110 */
+ 0x38, /* 0011100 */
+ 0xfe, /* 1111111 */
+ 0x38, /* 0011100 */
+ 0x6c, /* 0110110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 43 0x2b '+' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x10, /* 0001000 */
+ 0x10, /* 0001000 */
+ 0x7c, /* 0111110 */
+ 0x10, /* 0001000 */
+ 0x10, /* 0001000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 44 0x2c ',' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 45 0x2d '-' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xfc, /* 1111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 46 0x2e '.' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 47 0x2f '/' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x04, /* 0000010 */
+ 0x0c, /* 0000110 */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0x60, /* 0110000 */
+ 0xc0, /* 1100000 */
+ 0x80, /* 1000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 48 0x30 '0' */
+ 0x00, /* 0000000 */
+ 0x30, /* 0011000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xdc, /* 1101110 */
+ 0xec, /* 1110110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 49 0x31 '1' */
+ 0x00, /* 0000000 */
+ 0x18, /* 0001100 */
+ 0x38, /* 0011100 */
+ 0x78, /* 0111100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x7c, /* 0111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 50 0x32 '2' */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0x0c, /* 0000110 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0x60, /* 0110000 */
+ 0xc0, /* 1100000 */
+ 0xcc, /* 1100110 */
+ 0xfc, /* 1111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 51 0x33 '3' */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x38, /* 0011100 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 52 0x34 '4' */
+ 0x00, /* 0000000 */
+ 0x0c, /* 0000110 */
+ 0x1c, /* 0001110 */
+ 0x3c, /* 0011110 */
+ 0x6c, /* 0110110 */
+ 0xcc, /* 1100110 */
+ 0xfe, /* 1111111 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 53 0x35 '5' */
+ 0x00, /* 0000000 */
+ 0xfc, /* 1111110 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xf8, /* 1111100 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 54 0x36 '6' */
+ 0x00, /* 0000000 */
+ 0x30, /* 0011000 */
+ 0x60, /* 0110000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xf8, /* 1111100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 55 0x37 '7' */
+ 0x00, /* 0000000 */
+ 0xfc, /* 1111110 */
+ 0xcc, /* 1100110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 56 0x38 '8' */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 57 0x39 '9' */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x7c, /* 0111110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x18, /* 0001100 */
+ 0x70, /* 0111000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 58 0x3a ':' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 59 0x3b ';' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 60 0x3c '<' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x04, /* 0000010 */
+ 0x0c, /* 0000110 */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0x60, /* 0110000 */
+ 0x30, /* 0011000 */
+ 0x18, /* 0001100 */
+ 0x0c, /* 0000110 */
+ 0x04, /* 0000010 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 61 0x3d '=' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x7c, /* 0111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x7c, /* 0111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 62 0x3e '>' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x40, /* 0100000 */
+ 0x60, /* 0110000 */
+ 0x30, /* 0011000 */
+ 0x18, /* 0001100 */
+ 0x0c, /* 0000110 */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0x60, /* 0110000 */
+ 0x40, /* 0100000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 63 0x3f '?' */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 64 0x40 '@' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xdc, /* 1101110 */
+ 0xdc, /* 1101110 */
+ 0xd8, /* 1101100 */
+ 0xc0, /* 1100000 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 65 0x41 'A' */
+ 0x00, /* 0000000 */
+ 0x30, /* 0011000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xfc, /* 1111110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 66 0x42 'B' */
+ 0x00, /* 0000000 */
+ 0xf8, /* 1111100 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x78, /* 0111100 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0xf8, /* 1111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 67 0x43 'C' */
+ 0x00, /* 0000000 */
+ 0x38, /* 0011100 */
+ 0x6c, /* 0110110 */
+ 0xc4, /* 1100010 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc4, /* 1100010 */
+ 0x6c, /* 0110110 */
+ 0x38, /* 0011100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 68 0x44 'D' */
+ 0x00, /* 0000000 */
+ 0xf0, /* 1111000 */
+ 0xd8, /* 1101100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xd8, /* 1101100 */
+ 0xf0, /* 1111000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 69 0x45 'E' */
+ 0x00, /* 0000000 */
+ 0x7c, /* 0111110 */
+ 0x6c, /* 0110110 */
+ 0x64, /* 0110010 */
+ 0x68, /* 0110100 */
+ 0x78, /* 0111100 */
+ 0x68, /* 0110100 */
+ 0x60, /* 0110000 */
+ 0x64, /* 0110010 */
+ 0x6c, /* 0110110 */
+ 0x7c, /* 0111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 70 0x46 'F' */
+ 0x00, /* 0000000 */
+ 0x7c, /* 0111110 */
+ 0x64, /* 0110010 */
+ 0x60, /* 0110000 */
+ 0x68, /* 0110100 */
+ 0x78, /* 0111100 */
+ 0x68, /* 0110100 */
+ 0x60, /* 0110000 */
+ 0x60, /* 0110000 */
+ 0x60, /* 0110000 */
+ 0x70, /* 0111000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 71 0x47 'G' */
+ 0x00, /* 0000000 */
+ 0x38, /* 0011100 */
+ 0x6c, /* 0110110 */
+ 0xc4, /* 1100010 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xdc, /* 1101110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x6c, /* 0110110 */
+ 0x34, /* 0011010 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 72 0x48 'H' */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xfc, /* 1111110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 73 0x49 'I' */
+ 0x00, /* 0000000 */
+ 0x3c, /* 0011110 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x3c, /* 0011110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 74 0x4a 'J' */
+ 0x00, /* 0000000 */
+ 0x1c, /* 0001110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 75 0x4b 'K' */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xd8, /* 1101100 */
+ 0xf0, /* 1111000 */
+ 0xf0, /* 1111000 */
+ 0xd8, /* 1101100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 76 0x4c 'L' */
+ 0x00, /* 0000000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc4, /* 1100010 */
+ 0xcc, /* 1100110 */
+ 0xfc, /* 1111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 77 0x4d 'M' */
+ 0x00, /* 0000000 */
+ 0xc6, /* 1100011 */
+ 0xee, /* 1110111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xd6, /* 1101011 */
+ 0xc6, /* 1100011 */
+ 0xc6, /* 1100011 */
+ 0xc6, /* 1100011 */
+ 0xc6, /* 1100011 */
+ 0xc6, /* 1100011 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 78 0x4e 'N' */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0xec, /* 1110110 */
+ 0xec, /* 1110110 */
+ 0xfc, /* 1111110 */
+ 0xdc, /* 1101110 */
+ 0xdc, /* 1101110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 79 0x4f 'O' */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 80 0x50 'P' */
+ 0x00, /* 0000000 */
+ 0xf8, /* 1111100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xf8, /* 1111100 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 81 0x51 'Q' */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xdc, /* 1101110 */
+ 0x78, /* 0111100 */
+ 0x18, /* 0001100 */
+ 0x1c, /* 0001110 */
+ 0x00, /* 0000000 */
+
+ /* 82 0x52 'R' */
+ 0x00, /* 0000000 */
+ 0xf8, /* 1111100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xf8, /* 1111100 */
+ 0xd8, /* 1101100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 83 0x53 'S' */
+ 0x00, /* 0000000 */
+ 0x7c, /* 0111110 */
+ 0xc4, /* 1100010 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0x60, /* 0110000 */
+ 0x38, /* 0011100 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x8c, /* 1000110 */
+ 0xf8, /* 1111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 84 0x54 'T' */
+ 0x00, /* 0000000 */
+ 0xfc, /* 1111110 */
+ 0xfc, /* 1111110 */
+ 0xb4, /* 1011010 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 85 0x55 'U' */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 86 0x56 'V' */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x78, /* 0111100 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 87 0x57 'W' */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xfc, /* 1111110 */
+ 0xfc, /* 1111110 */
+ 0x48, /* 0100100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 88 0x58 'X' */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x78, /* 0111100 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x78, /* 0111100 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 89 0x59 'Y' */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 90 0x5a 'Z' */
+ 0x00, /* 0000000 */
+ 0xfc, /* 1111110 */
+ 0xcc, /* 1100110 */
+ 0x8c, /* 1000110 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0x60, /* 0110000 */
+ 0xc4, /* 1100010 */
+ 0xcc, /* 1100110 */
+ 0xfc, /* 1111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 91 0x5b '[' */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0x60, /* 0110000 */
+ 0x60, /* 0110000 */
+ 0x60, /* 0110000 */
+ 0x60, /* 0110000 */
+ 0x60, /* 0110000 */
+ 0x60, /* 0110000 */
+ 0x60, /* 0110000 */
+ 0x60, /* 0110000 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 92 0x5c '\' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x80, /* 1000000 */
+ 0xc0, /* 1100000 */
+ 0xe0, /* 1110000 */
+ 0x70, /* 0111000 */
+ 0x38, /* 0011100 */
+ 0x1c, /* 0001110 */
+ 0x0c, /* 0000110 */
+ 0x04, /* 0000010 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 93 0x5d ']' */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 94 0x5e '^' */
+ 0x10, /* 0001000 */
+ 0x38, /* 0011100 */
+ 0x6c, /* 0110110 */
+ 0xc6, /* 1100011 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 95 0x5f '_' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xfe, /* 1111111 */
+ 0x00, /* 0000000 */
+
+ /* 96 0x60 '`' */
+ 0x00, /* 0000000 */
+ 0x60, /* 0110000 */
+ 0x30, /* 0011000 */
+ 0x18, /* 0001100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 97 0x61 'a' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0x0c, /* 0000110 */
+ 0x7c, /* 0111110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x76, /* 0111011 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 98 0x62 'b' */
+ 0x00, /* 0000000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xf0, /* 1111000 */
+ 0xd8, /* 1101100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xf8, /* 1111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 99 0x63 'c' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 100 0x64 'd' */
+ 0x00, /* 0000000 */
+ 0x1c, /* 0001110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x3c, /* 0011110 */
+ 0x6c, /* 0110110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x76, /* 0111011 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 101 0x65 'e' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xfc, /* 1111110 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 102 0x66 'f' */
+ 0x00, /* 0000000 */
+ 0x38, /* 0011100 */
+ 0x6c, /* 0110110 */
+ 0x64, /* 0110010 */
+ 0x60, /* 0110000 */
+ 0xf0, /* 1111000 */
+ 0x60, /* 0110000 */
+ 0x60, /* 0110000 */
+ 0x60, /* 0110000 */
+ 0x60, /* 0110000 */
+ 0xf0, /* 1111000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 103 0x67 'g' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x76, /* 0111011 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x7c, /* 0111110 */
+ 0x0c, /* 0000110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+
+ /* 104 0x68 'h' */
+ 0x00, /* 0000000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xd8, /* 1101100 */
+ 0xec, /* 1110110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 105 0x69 'i' */
+ 0x00, /* 0000000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x70, /* 0111000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 106 0x6a 'j' */
+ 0x00, /* 0000000 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x00, /* 0000000 */
+ 0x1c, /* 0001110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+
+ /* 107 0x6b 'k' */
+ 0x00, /* 0000000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xcc, /* 1100110 */
+ 0xd8, /* 1101100 */
+ 0xf0, /* 1111000 */
+ 0xf0, /* 1111000 */
+ 0xd8, /* 1101100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 108 0x6c 'l' */
+ 0x00, /* 0000000 */
+ 0x70, /* 0111000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 109 0x6d 'm' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xec, /* 1110110 */
+ 0xfe, /* 1111111 */
+ 0xd6, /* 1101011 */
+ 0xd6, /* 1101011 */
+ 0xd6, /* 1101011 */
+ 0xd6, /* 1101011 */
+ 0xd6, /* 1101011 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 110 0x6e 'n' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xb8, /* 1011100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 111 0x6f 'o' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 112 0x70 'p' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xb8, /* 1011100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xf8, /* 1111100 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+
+ /* 113 0x71 'q' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x74, /* 0111010 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x7c, /* 0111110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+
+ /* 114 0x72 'r' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xb8, /* 1011100 */
+ 0xec, /* 1110110 */
+ 0xcc, /* 1100110 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 115 0x73 's' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0x60, /* 0110000 */
+ 0x30, /* 0011000 */
+ 0x18, /* 0001100 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 116 0x74 't' */
+ 0x00, /* 0000000 */
+ 0x10, /* 0001000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0xfc, /* 1111110 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x36, /* 0011011 */
+ 0x1c, /* 0001110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 117 0x75 'u' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x76, /* 0111011 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 118 0x76 'v' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 119 0x77 'w' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xc6, /* 1100011 */
+ 0xc6, /* 1100011 */
+ 0xd6, /* 1101011 */
+ 0xd6, /* 1101011 */
+ 0xd6, /* 1101011 */
+ 0xfe, /* 1111111 */
+ 0x6c, /* 0110110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 120 0x78 'x' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x30, /* 0011000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 121 0x79 'y' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x7c, /* 0111110 */
+ 0x0c, /* 0000110 */
+ 0x18, /* 0001100 */
+ 0xf0, /* 1111000 */
+
+ /* 122 0x7a 'z' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xfc, /* 1111110 */
+ 0xcc, /* 1100110 */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0x60, /* 0110000 */
+ 0xcc, /* 1100110 */
+ 0xfc, /* 1111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 123 0x7b '{' */
+ 0x00, /* 0000000 */
+ 0x1c, /* 0001110 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0xe0, /* 1110000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x1c, /* 0001110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 124 0x7c '|' */
+ 0x00, /* 0000000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 125 0x7d '}' */
+ 0x00, /* 0000000 */
+ 0x70, /* 0111000 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x0e, /* 0000111 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x70, /* 0111000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 126 0x7e '~' */
+ 0x00, /* 0000000 */
+ 0xec, /* 1110110 */
+ 0xb8, /* 1011100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 127 0x7f '' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x10, /* 0001000 */
+ 0x38, /* 0011100 */
+ 0x6c, /* 0110110 */
+ 0xc6, /* 1100011 */
+ 0xc6, /* 1100011 */
+ 0xc6, /* 1100011 */
+ 0xfe, /* 1111111 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 128 0x80 '€' */
+ 0x00, /* 0000000 */
+ 0x38, /* 0011100 */
+ 0x6c, /* 0110110 */
+ 0xc4, /* 1100010 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc4, /* 1100010 */
+ 0x6c, /* 0110110 */
+ 0x38, /* 0011100 */
+ 0x18, /* 0001100 */
+ 0x70, /* 0111000 */
+ 0x00, /* 0000000 */
+
+ /* 129 0x81 '' */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x76, /* 0111011 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 130 0x82 '‚' */
+ 0x0c, /* 0000110 */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xfc, /* 1111110 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 131 0x83 'ƒ' */
+ 0x10, /* 0001000 */
+ 0x38, /* 0011100 */
+ 0x6c, /* 0110110 */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0x0c, /* 0000110 */
+ 0x7c, /* 0111110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x76, /* 0111011 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 132 0x84 '„' */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0x0c, /* 0000110 */
+ 0x7c, /* 0111110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x76, /* 0111011 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 133 0x85 '…' */
+ 0x60, /* 0110000 */
+ 0x30, /* 0011000 */
+ 0x18, /* 0001100 */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0x0c, /* 0000110 */
+ 0x7c, /* 0111110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x76, /* 0111011 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 134 0x86 '†' */
+ 0x38, /* 0011100 */
+ 0x6c, /* 0110110 */
+ 0x38, /* 0011100 */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0x0c, /* 0000110 */
+ 0x7c, /* 0111110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x76, /* 0111011 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 135 0x87 '‡' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0xe0, /* 1110000 */
+
+ /* 136 0x88 'ˆ' */
+ 0x10, /* 0001000 */
+ 0x38, /* 0011100 */
+ 0x6c, /* 0110110 */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xfc, /* 1111110 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 137 0x89 '‰' */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xfc, /* 1111110 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 138 0x8a 'Š' */
+ 0xc0, /* 1100000 */
+ 0x60, /* 0110000 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xfc, /* 1111110 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 139 0x8b '‹' */
+ 0x00, /* 0000000 */
+ 0x6c, /* 0110110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x38, /* 0011100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x3c, /* 0011110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 140 0x8c 'Œ' */
+ 0x30, /* 0011000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0x00, /* 0000000 */
+ 0x70, /* 0111000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 141 0x8d '' */
+ 0xc0, /* 1100000 */
+ 0x60, /* 0110000 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x70, /* 0111000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 142 0x8e 'Ž' */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0x00, /* 0000000 */
+ 0x30, /* 0011000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xfc, /* 1111110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 143 0x8f '' */
+ 0x30, /* 0011000 */
+ 0x48, /* 0100100 */
+ 0x48, /* 0100100 */
+ 0x30, /* 0011000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xfc, /* 1111110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 144 0x90 '' */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0xfc, /* 1111110 */
+ 0xcc, /* 1100110 */
+ 0xc4, /* 1100010 */
+ 0xd0, /* 1101000 */
+ 0xf0, /* 1111000 */
+ 0xd0, /* 1101000 */
+ 0xc4, /* 1100010 */
+ 0xcc, /* 1100110 */
+ 0xfc, /* 1111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 145 0x91 '‘' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xec, /* 1110110 */
+ 0x36, /* 0011011 */
+ 0x36, /* 0011011 */
+ 0x7e, /* 0111111 */
+ 0xd8, /* 1101100 */
+ 0xd8, /* 1101100 */
+ 0x6e, /* 0110111 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 146 0x92 '’' */
+ 0x00, /* 0000000 */
+ 0x3e, /* 0011111 */
+ 0x6c, /* 0110110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xfe, /* 1111111 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xce, /* 1100111 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 147 0x93 '“' */
+ 0x10, /* 0001000 */
+ 0x38, /* 0011100 */
+ 0x6c, /* 0110110 */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 148 0x94 '”' */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 149 0x95 '•' */
+ 0xc0, /* 1100000 */
+ 0x60, /* 0110000 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 150 0x96 '–' */
+ 0x30, /* 0011000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x76, /* 0111011 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 151 0x97 '—' */
+ 0x60, /* 0110000 */
+ 0x30, /* 0011000 */
+ 0x18, /* 0001100 */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x76, /* 0111011 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 152 0x98 '˜' */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x7c, /* 0111110 */
+ 0x0c, /* 0000110 */
+ 0x18, /* 0001100 */
+ 0x70, /* 0111000 */
+
+ /* 153 0x99 '™' */
+ 0xcc, /* 1100110 */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 154 0x9a 'š' */
+ 0xcc, /* 1100110 */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 155 0x9b '›' */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x7c, /* 0111110 */
+ 0xcc, /* 1100110 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xcc, /* 1100110 */
+ 0x7c, /* 0111110 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 156 0x9c 'œ' */
+ 0x38, /* 0011100 */
+ 0x6c, /* 0110110 */
+ 0x64, /* 0110010 */
+ 0x60, /* 0110000 */
+ 0xf0, /* 1111000 */
+ 0x60, /* 0110000 */
+ 0x60, /* 0110000 */
+ 0x60, /* 0110000 */
+ 0x60, /* 0110000 */
+ 0xe6, /* 1110011 */
+ 0xfc, /* 1111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 157 0x9d '' */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x30, /* 0011000 */
+ 0xfc, /* 1111110 */
+ 0x30, /* 0011000 */
+ 0xfc, /* 1111110 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 158 0x9e 'ž' */
+ 0xf8, /* 1111100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xf8, /* 1111100 */
+ 0xc4, /* 1100010 */
+ 0xcc, /* 1100110 */
+ 0xde, /* 1101111 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xc6, /* 1100011 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 159 0x9f 'Ÿ' */
+ 0x1c, /* 0001110 */
+ 0x36, /* 0011011 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0xfc, /* 1111110 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0xb0, /* 1011000 */
+ 0xe0, /* 1110000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 160 0xa0 ' ' */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0x60, /* 0110000 */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0x0c, /* 0000110 */
+ 0x7c, /* 0111110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x76, /* 0111011 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 161 0xa1 '¡' */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0x60, /* 0110000 */
+ 0x00, /* 0000000 */
+ 0x70, /* 0111000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 162 0xa2 '¢' */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0x60, /* 0110000 */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 163 0xa3 '£' */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0x60, /* 0110000 */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x76, /* 0111011 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 164 0xa4 '¤' */
+ 0x00, /* 0000000 */
+ 0x76, /* 0111011 */
+ 0xdc, /* 1101110 */
+ 0x00, /* 0000000 */
+ 0xb8, /* 1011100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 165 0xa5 '¥' */
+ 0x76, /* 0111011 */
+ 0xdc, /* 1101110 */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0xec, /* 1110110 */
+ 0xec, /* 1110110 */
+ 0xfc, /* 1111110 */
+ 0xdc, /* 1101110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 166 0xa6 '¦' */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0xd8, /* 1101100 */
+ 0xd8, /* 1101100 */
+ 0x7c, /* 0111110 */
+ 0x00, /* 0000000 */
+ 0xfc, /* 1111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 167 0xa7 '§' */
+ 0x00, /* 0000000 */
+ 0x70, /* 0111000 */
+ 0xd8, /* 1101100 */
+ 0xd8, /* 1101100 */
+ 0x70, /* 0111000 */
+ 0x00, /* 0000000 */
+ 0xf8, /* 1111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 168 0xa8 '¨' */
+ 0x00, /* 0000000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x60, /* 0110000 */
+ 0xc0, /* 1100000 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 169 0xa9 '©' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xfc, /* 1111110 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 170 0xaa 'ª' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xfc, /* 1111110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 171 0xab '«' */
+ 0x60, /* 0110000 */
+ 0xe0, /* 1110000 */
+ 0x62, /* 0110001 */
+ 0x66, /* 0110011 */
+ 0x6c, /* 0110110 */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0x60, /* 0110000 */
+ 0xc0, /* 1100000 */
+ 0xb8, /* 1011100 */
+ 0x4c, /* 0100110 */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0x7c, /* 0111110 */
+
+ /* 172 0xac '¬' */
+ 0x60, /* 0110000 */
+ 0xe0, /* 1110000 */
+ 0x62, /* 0110001 */
+ 0x66, /* 0110011 */
+ 0x6c, /* 0110110 */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0x6c, /* 0110110 */
+ 0xdc, /* 1101110 */
+ 0xb4, /* 1011010 */
+ 0x7e, /* 0111111 */
+ 0x0c, /* 0000110 */
+ 0x0c, /* 0000110 */
+ 0x00, /* 0000000 */
+
+ /* 173 0xad '­' */
+ 0x00, /* 0000000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x78, /* 0111100 */
+ 0x78, /* 0111100 */
+ 0x78, /* 0111100 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 174 0xae '®' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x36, /* 0011011 */
+ 0x6c, /* 0110110 */
+ 0xd8, /* 1101100 */
+ 0x6c, /* 0110110 */
+ 0x36, /* 0011011 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 175 0xaf '¯' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xd8, /* 1101100 */
+ 0x6c, /* 0110110 */
+ 0x36, /* 0011011 */
+ 0x6c, /* 0110110 */
+ 0xd8, /* 1101100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 176 0xb0 '°' */
+ 0x88, /* 1000100 */
+ 0x22, /* 0010001 */
+ 0x88, /* 1000100 */
+ 0x22, /* 0010001 */
+ 0x88, /* 1000100 */
+ 0x22, /* 0010001 */
+ 0x88, /* 1000100 */
+ 0x22, /* 0010001 */
+ 0x88, /* 1000100 */
+ 0x22, /* 0010001 */
+ 0x88, /* 1000100 */
+ 0x22, /* 0010001 */
+ 0x88, /* 1000100 */
+ 0x22, /* 0010001 */
+
+ /* 177 0xb1 '±' */
+ 0x54, /* 0101010 */
+ 0xaa, /* 1010101 */
+ 0x54, /* 0101010 */
+ 0xaa, /* 1010101 */
+ 0x54, /* 0101010 */
+ 0xaa, /* 1010101 */
+ 0x54, /* 0101010 */
+ 0xaa, /* 1010101 */
+ 0x54, /* 0101010 */
+ 0xaa, /* 1010101 */
+ 0x54, /* 0101010 */
+ 0xaa, /* 1010101 */
+ 0x54, /* 0101010 */
+ 0xaa, /* 1010101 */
+
+ /* 178 0xb2 '²' */
+ 0xee, /* 1110111 */
+ 0xba, /* 1011101 */
+ 0xee, /* 1110111 */
+ 0xba, /* 1011101 */
+ 0xee, /* 1110111 */
+ 0xba, /* 1011101 */
+ 0xee, /* 1110111 */
+ 0xba, /* 1011101 */
+ 0xee, /* 1110111 */
+ 0xba, /* 1011101 */
+ 0xee, /* 1110111 */
+ 0xba, /* 1011101 */
+ 0xee, /* 1110111 */
+ 0xba, /* 1011101 */
+
+ /* 179 0xb3 '³' */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+
+ /* 180 0xb4 '´' */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0xf0, /* 1111000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+
+ /* 181 0xb5 'µ' */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0xf0, /* 1111000 */
+ 0x30, /* 0011000 */
+ 0xf0, /* 1111000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+
+ /* 182 0xb6 '¶' */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0xec, /* 1110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+
+ /* 183 0xb7 '·' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xfc, /* 1111110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+
+ /* 184 0xb8 '¸' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xf0, /* 1111000 */
+ 0x30, /* 0011000 */
+ 0xf0, /* 1111000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+
+ /* 185 0xb9 '¹' */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0xec, /* 1110110 */
+ 0x0c, /* 0000110 */
+ 0xec, /* 1110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+
+ /* 186 0xba 'º' */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+
+ /* 187 0xbb '»' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xfc, /* 1111110 */
+ 0x0c, /* 0000110 */
+ 0xec, /* 1110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+
+ /* 188 0xbc '¼' */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0xec, /* 1110110 */
+ 0x0c, /* 0000110 */
+ 0xfc, /* 1111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 189 0xbd '½' */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0xfc, /* 1111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 190 0xbe '¾' */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0xf0, /* 1111000 */
+ 0x30, /* 0011000 */
+ 0xf0, /* 1111000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 191 0xbf '¿' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xf0, /* 1111000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+
+ /* 192 0xc0 'À' */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x3e, /* 0011111 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 193 0xc1 'Á' */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0xfe, /* 1111111 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 194 0xc2 'Â' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xfe, /* 1111111 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+
+ /* 195 0xc3 'Ã' */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x3e, /* 0011111 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+
+ /* 196 0xc4 'Ä' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xfe, /* 1111111 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 197 0xc5 'Å' */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0xfe, /* 1111111 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+
+ /* 198 0xc6 'Æ' */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x3e, /* 0011111 */
+ 0x30, /* 0011000 */
+ 0x3e, /* 0011111 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+
+ /* 199 0xc7 'Ç' */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6e, /* 0110111 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+
+ /* 200 0xc8 'È' */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6e, /* 0110111 */
+ 0x60, /* 0110000 */
+ 0x7e, /* 0111111 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 201 0xc9 'É' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x7e, /* 0111111 */
+ 0x60, /* 0110000 */
+ 0x6e, /* 0110111 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+
+ /* 202 0xca 'Ê' */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0xee, /* 1110111 */
+ 0x00, /* 0000000 */
+ 0xfe, /* 1111111 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 203 0xcb 'Ë' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xfe, /* 1111111 */
+ 0x00, /* 0000000 */
+ 0xee, /* 1110111 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+
+ /* 204 0xcc 'Ì' */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6e, /* 0110111 */
+ 0x60, /* 0110000 */
+ 0x6e, /* 0110111 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+
+ /* 205 0xcd 'Í' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xfe, /* 1111111 */
+ 0x00, /* 0000000 */
+ 0xfe, /* 1111111 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 206 0xce 'Î' */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0xee, /* 1110111 */
+ 0x00, /* 0000000 */
+ 0xee, /* 1110111 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+
+ /* 207 0xcf 'Ï' */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0xfe, /* 1111111 */
+ 0x00, /* 0000000 */
+ 0xfe, /* 1111111 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 208 0xd0 'Ð' */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0xfe, /* 1111111 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 209 0xd1 'Ñ' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xfe, /* 1111111 */
+ 0x00, /* 0000000 */
+ 0xfe, /* 1111111 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+
+ /* 210 0xd2 'Ò' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xfe, /* 1111111 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+
+ /* 211 0xd3 'Ó' */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x7e, /* 0111111 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 212 0xd4 'Ô' */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x3e, /* 0011111 */
+ 0x30, /* 0011000 */
+ 0x3e, /* 0011111 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 213 0xd5 'Õ' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x3e, /* 0011111 */
+ 0x30, /* 0011000 */
+ 0x3e, /* 0011111 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+
+ /* 214 0xd6 'Ö' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x7e, /* 0111111 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+
+ /* 215 0xd7 '×' */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0xfe, /* 1111111 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+
+ /* 216 0xd8 'Ø' */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0xfe, /* 1111111 */
+ 0x30, /* 0011000 */
+ 0xfe, /* 1111111 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+
+ /* 217 0xd9 'Ù' */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0xf0, /* 1111000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 218 0xda 'Ú' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x3e, /* 0011111 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+
+ /* 219 0xdb 'Û' */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+
+ /* 220 0xdc 'Ü' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+
+ /* 221 0xdd 'Ý' */
+ 0xe0, /* 1110000 */
+ 0xe0, /* 1110000 */
+ 0xe0, /* 1110000 */
+ 0xe0, /* 1110000 */
+ 0xe0, /* 1110000 */
+ 0xe0, /* 1110000 */
+ 0xe0, /* 1110000 */
+ 0xe0, /* 1110000 */
+ 0xe0, /* 1110000 */
+ 0xe0, /* 1110000 */
+ 0xe0, /* 1110000 */
+ 0xe0, /* 1110000 */
+ 0xe0, /* 1110000 */
+ 0xe0, /* 1110000 */
+
+ /* 222 0xde 'Þ' */
+ 0x1e, /* 0001111 */
+ 0x1e, /* 0001111 */
+ 0x1e, /* 0001111 */
+ 0x1e, /* 0001111 */
+ 0x1e, /* 0001111 */
+ 0x1e, /* 0001111 */
+ 0x1e, /* 0001111 */
+ 0x1e, /* 0001111 */
+ 0x1e, /* 0001111 */
+ 0x1e, /* 0001111 */
+ 0x1e, /* 0001111 */
+ 0x1e, /* 0001111 */
+ 0x1e, /* 0001111 */
+ 0x1e, /* 0001111 */
+
+ /* 223 0xdf 'ß' */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 224 0xe0 'à' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x76, /* 0111011 */
+ 0xdc, /* 1101110 */
+ 0xd8, /* 1101100 */
+ 0xd8, /* 1101100 */
+ 0xd8, /* 1101100 */
+ 0xdc, /* 1101110 */
+ 0x76, /* 0111011 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 225 0xe1 'á' */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xd8, /* 1101100 */
+ 0xcc, /* 1100110 */
+ 0xc6, /* 1100011 */
+ 0xc6, /* 1100011 */
+ 0xc6, /* 1100011 */
+ 0xcc, /* 1100110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 226 0xe2 'â' */
+ 0x00, /* 0000000 */
+ 0xfc, /* 1111110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 227 0xe3 'ã' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xfe, /* 1111111 */
+ 0xfe, /* 1111111 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 228 0xe4 'ä' */
+ 0x00, /* 0000000 */
+ 0xfc, /* 1111110 */
+ 0xcc, /* 1100110 */
+ 0x60, /* 0110000 */
+ 0x30, /* 0011000 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0x60, /* 0110000 */
+ 0xcc, /* 1100110 */
+ 0xfc, /* 1111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 229 0xe5 'å' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x7e, /* 0111111 */
+ 0xd8, /* 1101100 */
+ 0xd8, /* 1101100 */
+ 0xd8, /* 1101100 */
+ 0xd8, /* 1101100 */
+ 0xd8, /* 1101100 */
+ 0x70, /* 0111000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 230 0xe6 'æ' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xf8, /* 1111100 */
+ 0xc0, /* 1100000 */
+ 0xc0, /* 1100000 */
+ 0x80, /* 1000000 */
+
+ /* 231 0xe7 'ç' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x76, /* 0111011 */
+ 0xdc, /* 1101110 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 232 0xe8 'è' */
+ 0x00, /* 0000000 */
+ 0xfc, /* 1111110 */
+ 0x30, /* 0011000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x30, /* 0011000 */
+ 0xfc, /* 1111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 233 0xe9 'é' */
+ 0x00, /* 0000000 */
+ 0x38, /* 0011100 */
+ 0x6c, /* 0110110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xfc, /* 1111110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x6c, /* 0110110 */
+ 0x38, /* 0011100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 234 0xea 'ê' */
+ 0x00, /* 0000000 */
+ 0x38, /* 0011100 */
+ 0x6c, /* 0110110 */
+ 0xc6, /* 1100011 */
+ 0xc6, /* 1100011 */
+ 0xc6, /* 1100011 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0xee, /* 1110111 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 235 0xeb 'ë' */
+ 0x00, /* 0000000 */
+ 0x3c, /* 0011110 */
+ 0x60, /* 0110000 */
+ 0x30, /* 0011000 */
+ 0x18, /* 0001100 */
+ 0x7c, /* 0111110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x78, /* 0111100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 236 0xec 'ì' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x7c, /* 0111110 */
+ 0xd6, /* 1101011 */
+ 0xd6, /* 1101011 */
+ 0xd6, /* 1101011 */
+ 0x7c, /* 0111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 237 0xed 'í' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x06, /* 0000011 */
+ 0x0c, /* 0000110 */
+ 0x7c, /* 0111110 */
+ 0xd6, /* 1101011 */
+ 0xd6, /* 1101011 */
+ 0xe6, /* 1110011 */
+ 0x7c, /* 0111110 */
+ 0x60, /* 0110000 */
+ 0xc0, /* 1100000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 238 0xee 'î' */
+ 0x00, /* 0000000 */
+ 0x1c, /* 0001110 */
+ 0x30, /* 0011000 */
+ 0x60, /* 0110000 */
+ 0x60, /* 0110000 */
+ 0x7c, /* 0111110 */
+ 0x60, /* 0110000 */
+ 0x60, /* 0110000 */
+ 0x60, /* 0110000 */
+ 0x30, /* 0011000 */
+ 0x1c, /* 0001110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 239 0xef 'ï' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0xcc, /* 1100110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 240 0xf0 'ð' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xfc, /* 1111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xfc, /* 1111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xfc, /* 1111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 241 0xf1 'ñ' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0xfc, /* 1111110 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0xfc, /* 1111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 242 0xf2 'ò' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x60, /* 0110000 */
+ 0x30, /* 0011000 */
+ 0x18, /* 0001100 */
+ 0x0c, /* 0000110 */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0x60, /* 0110000 */
+ 0x00, /* 0000000 */
+ 0xfc, /* 1111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 243 0xf3 'ó' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0x60, /* 0110000 */
+ 0xc0, /* 1100000 */
+ 0x60, /* 0110000 */
+ 0x30, /* 0011000 */
+ 0x18, /* 0001100 */
+ 0x00, /* 0000000 */
+ 0xfc, /* 1111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 244 0xf4 'ô' */
+ 0x00, /* 0000000 */
+ 0x1c, /* 0001110 */
+ 0x36, /* 0011011 */
+ 0x36, /* 0011011 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+
+ /* 245 0xf5 'õ' */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0xd8, /* 1101100 */
+ 0xd8, /* 1101100 */
+ 0xd8, /* 1101100 */
+ 0x70, /* 0111000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 246 0xf6 'ö' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0xfc, /* 1111110 */
+ 0x00, /* 0000000 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 247 0xf7 '÷' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x76, /* 0111011 */
+ 0xdc, /* 1101110 */
+ 0x00, /* 0000000 */
+ 0x76, /* 0111011 */
+ 0xdc, /* 1101110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 248 0xf8 'ø' */
+ 0x38, /* 0011100 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x38, /* 0011100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 249 0xf9 'ù' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x30, /* 0011000 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 250 0xfa 'ú' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x30, /* 0011000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 251 0xfb 'û' */
+ 0x1e, /* 0001111 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0x18, /* 0001100 */
+ 0xd8, /* 1101100 */
+ 0xd8, /* 1101100 */
+ 0xd8, /* 1101100 */
+ 0x78, /* 0111100 */
+ 0x38, /* 0011100 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 252 0xfc 'ü' */
+ 0xd8, /* 1101100 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x6c, /* 0110110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 253 0xfd 'ý' */
+ 0x78, /* 0111100 */
+ 0xcc, /* 1100110 */
+ 0x18, /* 0001100 */
+ 0x30, /* 0011000 */
+ 0x64, /* 0110010 */
+ 0xfc, /* 1111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 254 0xfe 'þ' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x7c, /* 0111110 */
+ 0x7c, /* 0111110 */
+ 0x7c, /* 0111110 */
+ 0x7c, /* 0111110 */
+ 0x7c, /* 0111110 */
+ 0x7c, /* 0111110 */
+ 0x7c, /* 0111110 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+ /* 255 0xff 'ÿ' */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+ 0x00, /* 0000000 */
+
+};
+
+
+struct font_desc font_7x14 = {
+ FONT7x14_IDX,
+ "7x14",
+ 7,
+ 14,
+ fontdata_7x14,
+ 0
+};
diff --git a/drivers/video/console/font_sun12x22.c b/drivers/video/console/font_sun12x22.c
index 05215d0c3e0..c7bd967ea10 100644
--- a/drivers/video/console/font_sun12x22.c
+++ b/drivers/video/console/font_sun12x22.c
@@ -29,24 +29,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 1 0x01 '^A' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x1f, 0xc0, /* 000111111100 */
+ 0x30, 0x60, /* 001100000110 */
+ 0x65, 0x30, /* 011001010011 */
+ 0x6d, 0xb0, /* 011011011011 */
+ 0x60, 0x30, /* 011000000011 */
+ 0x62, 0x30, /* 011000100011 */
+ 0x62, 0x30, /* 011000100011 */
+ 0x60, 0x30, /* 011000000011 */
+ 0x6f, 0xb0, /* 011011111011 */
+ 0x67, 0x30, /* 011001110011 */
+ 0x30, 0x60, /* 001100000110 */
+ 0x1f, 0xc0, /* 000111111100 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -54,24 +53,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 2 0x02 '^B' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x1f, 0xc0, /* 000111111100 */
+ 0x3f, 0xe0, /* 001111111110 */
+ 0x7a, 0xf0, /* 011110101111 */
+ 0x72, 0x70, /* 011100100111 */
+ 0x7f, 0xf0, /* 011111111111 */
+ 0x7d, 0xf0, /* 011111011111 */
+ 0x7d, 0xf0, /* 011111011111 */
+ 0x7f, 0xf0, /* 011111111111 */
+ 0x70, 0x70, /* 011100000111 */
+ 0x78, 0xf0, /* 011110001111 */
+ 0x3f, 0xe0, /* 001111111110 */
+ 0x1f, 0xc0, /* 000111111100 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -79,24 +77,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 3 0x03 '^C' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x19, 0x80, /* 000110011000 */
0x3f, 0xc0, /* 001111111100 */
+ 0x7f, 0xe0, /* 011111111110 */
0x3f, 0xc0, /* 001111111100 */
0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -104,49 +101,47 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 4 0x04 '^D' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x02, 0x00, /* 000000100000 */
+ 0x07, 0x00, /* 000001110000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x1f, 0xc0, /* 000111111100 */
+ 0x1f, 0xc0, /* 000111111100 */
+ 0x3f, 0xe0, /* 001111111110 */
+ 0x1f, 0xc0, /* 000111111100 */
+ 0x1f, 0xc0, /* 000111111100 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x07, 0x00, /* 000001110000 */
+ 0x02, 0x00, /* 000000100000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
/* 5 0x05 '^E' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x02, 0x00, /* 000000100000 */
+ 0x07, 0x00, /* 000001110000 */
+ 0x07, 0x00, /* 000001110000 */
+ 0x02, 0x00, /* 000000100000 */
+ 0x18, 0xc0, /* 000110001100 */
+ 0x3d, 0xe0, /* 001111011110 */
+ 0x3d, 0xe0, /* 001111011110 */
+ 0x1a, 0xc0, /* 000110101100 */
+ 0x02, 0x00, /* 000000100000 */
+ 0x07, 0x00, /* 000001110000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x1f, 0xc0, /* 000111111100 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -154,23 +149,22 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 6 0x06 '^F' */
- /* FIXME */
- 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x1f, 0x80, /* 000111111000 */
0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x36, 0xc0, /* 001101101100 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x1f, 0x80, /* 000111111000 */
0x3f, 0xc0, /* 001111111100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -179,24 +173,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 7 0x07 '^G' */
- /* FIXME */
- 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x1f, 0x80, /* 000111111000 */
0x3f, 0xc0, /* 001111111100 */
0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -204,49 +197,47 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 8 0x08 '^H' */
- /* FIXME */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xf9, 0xf0, /* 111110011111 */
+ 0xf0, 0xf0, /* 111100001111 */
+ 0xf0, 0xf0, /* 111100001111 */
+ 0xe0, 0x70, /* 111000000111 */
+ 0xe0, 0x70, /* 111000000111 */
+ 0xc0, 0x30, /* 110000000011 */
+ 0xc0, 0x30, /* 110000000011 */
+ 0xe0, 0x70, /* 111000000111 */
+ 0xe0, 0x70, /* 111000000111 */
+ 0xf0, 0xf0, /* 111100001111 */
+ 0xf0, 0xf0, /* 111100001111 */
+ 0xf9, 0xf0, /* 111110011111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
/* 9 0x09 '^I' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x06, 0x00, /* 000001100000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -254,49 +245,47 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 10 0x0a '^J' */
- /* FIXME */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xf9, 0xf0, /* 111110011111 */
+ 0xf0, 0xf0, /* 111100001111 */
+ 0xf0, 0xf0, /* 111100001111 */
+ 0xe6, 0x70, /* 111001100111 */
+ 0xe6, 0x70, /* 111001100111 */
+ 0xcf, 0x30, /* 110011110011 */
+ 0xcf, 0x30, /* 110011110011 */
+ 0xe6, 0x70, /* 111001100111 */
+ 0xe6, 0x70, /* 111001100111 */
+ 0xf0, 0xf0, /* 111100001111 */
+ 0xf0, 0xf0, /* 111100001111 */
+ 0xf9, 0xf0, /* 111110011111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
/* 11 0x0b '^K' */
- /* FIXME */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x0f, 0xe0, /* 000011111110 */
+ 0x0f, 0xe0, /* 000011111110 */
+ 0x01, 0xe0, /* 000000011110 */
+ 0x03, 0x60, /* 000000110110 */
+ 0x06, 0x60, /* 000001100110 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x33, 0x00, /* 001100110000 */
+ 0x33, 0x00, /* 001100110000 */
+ 0x61, 0x80, /* 011000011000 */
+ 0x61, 0x80, /* 011000011000 */
+ 0x33, 0x00, /* 001100110000 */
+ 0x33, 0x00, /* 001100110000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x0c, 0x00, /* 000011000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -304,24 +293,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 12 0x0c '^L' */
- /* FIXME */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
0x3f, 0xc0, /* 001111111100 */
0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -329,149 +317,143 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 13 0x0d '^M' */
- /* FIXME */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x0f, 0xe0, /* 000011111110 */
+ 0x0c, 0x60, /* 000011000110 */
+ 0x0c, 0x60, /* 000011000110 */
+ 0x0f, 0xe0, /* 000011111110 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x3c, 0x00, /* 001111000000 */
+ 0x7c, 0x00, /* 011111000000 */
+ 0x78, 0x00, /* 011110000000 */
+ 0x30, 0x00, /* 001100000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
/* 14 0x0e '^N' */
- /* FIXME */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x1f, 0xe0, /* 000111111110 */
+ 0x18, 0x60, /* 000110000110 */
+ 0x18, 0x60, /* 000110000110 */
+ 0x1f, 0xe0, /* 000111111110 */
+ 0x18, 0x60, /* 000110000110 */
+ 0x18, 0x60, /* 000110000110 */
+ 0x18, 0x60, /* 000110000110 */
+ 0x18, 0x60, /* 000110000110 */
+ 0x18, 0x60, /* 000110000110 */
+ 0x18, 0x60, /* 000110000110 */
+ 0x19, 0xe0, /* 000110011110 */
+ 0x1b, 0xe0, /* 000110111110 */
+ 0x1b, 0xc0, /* 000110111100 */
+ 0x79, 0x80, /* 011110011000 */
+ 0xf8, 0x00, /* 111110000000 */
+ 0xf0, 0x00, /* 111100000000 */
+ 0x60, 0x00, /* 011000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
/* 15 0x0f '^O' */
- /* FIXME */
- 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
-
- /* 16 0x10 '^P' */
- /* FIXME */
+ 0x18, 0xc0, /* 000110001100 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x6d, 0xb0, /* 011011011011 */
+ 0x3d, 0xe0, /* 001111011110 */
0x00, 0x00, /* 000000000000 */
+ 0x3d, 0xe0, /* 001111011110 */
+ 0x6d, 0xb0, /* 011011011011 */
+ 0x0d, 0x80, /* 000011011000 */
+ 0x18, 0xc0, /* 000110001100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+
+ /* 16 0x10 '^P' */
0x00, 0x00, /* 000000000000 */
+ 0x00, 0x20, /* 000000000010 */
+ 0x00, 0x60, /* 000000000110 */
+ 0x00, 0xe0, /* 000000001110 */
+ 0x01, 0xe0, /* 000000011110 */
+ 0x03, 0xe0, /* 000000111110 */
+ 0x07, 0xe0, /* 000001111110 */
+ 0x0f, 0xe0, /* 000011111110 */
+ 0x1f, 0xe0, /* 000111111110 */
+ 0x3f, 0xe0, /* 001111111110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x3f, 0xe0, /* 001111111110 */
+ 0x1f, 0xe0, /* 000111111110 */
+ 0x0f, 0xe0, /* 000011111110 */
+ 0x07, 0xe0, /* 000001111110 */
+ 0x03, 0xe0, /* 000000111110 */
+ 0x01, 0xe0, /* 000000011110 */
+ 0x00, 0xe0, /* 000000001110 */
+ 0x00, 0x60, /* 000000000110 */
+ 0x00, 0x20, /* 000000000010 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
/* 17 0x11 '^Q' */
- /* FIXME */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x40, 0x00, /* 010000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x70, 0x00, /* 011100000000 */
+ 0x78, 0x00, /* 011110000000 */
+ 0x7c, 0x00, /* 011111000000 */
+ 0x7e, 0x00, /* 011111100000 */
+ 0x7f, 0x00, /* 011111110000 */
+ 0x7f, 0x80, /* 011111111000 */
+ 0x7f, 0xc0, /* 011111111100 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x7f, 0xc0, /* 011111111100 */
+ 0x7f, 0x80, /* 011111111000 */
+ 0x7f, 0x00, /* 011111110000 */
+ 0x7e, 0x00, /* 011111100000 */
+ 0x7c, 0x00, /* 011111000000 */
+ 0x78, 0x00, /* 011110000000 */
+ 0x70, 0x00, /* 011100000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x40, 0x00, /* 010000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
/* 18 0x12 '^R' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x04, 0x00, /* 000001000000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x3f, 0x80, /* 001111111000 */
+ 0x7f, 0xc0, /* 011111111100 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x7f, 0xc0, /* 011111111100 */
+ 0x3f, 0x80, /* 001111111000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x04, 0x00, /* 000001000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -551,99 +533,95 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 22 0x16 '^V' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
-
- /* 23 0x17 '^W' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x7f, 0xe0, /* 011111111110 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
- /* 24 0x18 '^X' */
- /* FIXME */
+ /* 23 0x17 '^W' */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x04, 0x00, /* 000001000000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x3f, 0x80, /* 001111111000 */
+ 0x7f, 0xc0, /* 011111111100 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x7f, 0xc0, /* 011111111100 */
+ 0x3f, 0x80, /* 001111111000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x04, 0x00, /* 000001000000 */
0x00, 0x00, /* 000000000000 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x7f, 0xe0, /* 011111111110 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+
+ /* 24 0x18 '^X' */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
-
- /* 25 0x19 '^Y' */
- /* FIXME */
+ 0x04, 0x00, /* 000001000000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x3f, 0x80, /* 001111111000 */
+ 0x7f, 0xc0, /* 011111111100 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x0e, 0x00, /* 000011100000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+
+ /* 25 0x19 '^Y' */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x7f, 0xc0, /* 011111111100 */
+ 0x3f, 0x80, /* 001111111000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x04, 0x00, /* 000001000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -651,24 +629,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 26 0x1a '^Z' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x08, 0x00, /* 000010000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x38, 0x00, /* 001110000000 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0xff, 0xe0, /* 111111111110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x38, 0x00, /* 001110000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x08, 0x00, /* 000010000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -676,24 +653,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 27 0x1b '^[' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x01, 0x00, /* 000000010000 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x01, 0xc0, /* 000000011100 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x7f, 0xf0, /* 011111111111 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x01, 0xc0, /* 000000011100 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x01, 0x00, /* 000000010000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -701,24 +677,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 28 0x1c '^\' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x3f, 0xe0, /* 001111111110 */
+ 0x3f, 0xe0, /* 001111111110 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -726,24 +701,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 29 0x1d '^]' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x09, 0x00, /* 000010010000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x39, 0xc0, /* 001110011100 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x39, 0xc0, /* 001110011100 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x09, 0x00, /* 000010010000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -751,24 +725,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 30 0x1e '^^' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x04, 0x00, /* 000001000000 */
+ 0x04, 0x00, /* 000001000000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x3f, 0x80, /* 001111111000 */
+ 0x3f, 0x80, /* 001111111000 */
+ 0x7f, 0xc0, /* 011111111100 */
+ 0x7f, 0xc0, /* 011111111100 */
+ 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -776,24 +749,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 31 0x1f '^_' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x7f, 0xc0, /* 011111111100 */
+ 0x7f, 0xc0, /* 011111111100 */
+ 0x3f, 0x80, /* 001111111000 */
+ 0x3f, 0x80, /* 001111111000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x04, 0x00, /* 000001000000 */
+ 0x04, 0x00, /* 000001000000 */
+ 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -3081,29 +3053,28 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 127 0x7f '.' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0xff, 0xf0, /* 111111111111 */
+ 0x00, 0x00, /* 000000000000 */
/* 128 0x80 '.' */
0x00, 0x00, /* 000000000000 */
@@ -3826,24 +3797,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 158 0x9e '.' */
- /* FIXME */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x7f, 0x80, /* 011111111000 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0x60, /* 001100000110 */
+ 0x30, 0x60, /* 001100000110 */
+ 0x30, 0x60, /* 001100000110 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x37, 0x80, /* 001101111000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x33, 0x00, /* 001100110000 */
+ 0x37, 0x80, /* 001101111000 */
+ 0x33, 0x00, /* 001100110000 */
+ 0x33, 0x00, /* 001100110000 */
+ 0x33, 0x30, /* 001100110011 */
+ 0x31, 0xe0, /* 001100011110 */
+ 0x78, 0xc0, /* 011110001100 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -3851,28 +3821,27 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 159 0x9f '.' */
- /* FIXME */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x01, 0xe0, /* 000000011110 */
+ 0x03, 0x30, /* 000000110011 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x3f, 0xe0, /* 001111111110 */
+ 0x7f, 0xc0, /* 011111111100 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0xcc, 0x00, /* 110011000000 */
+ 0x78, 0x00, /* 011110000000 */
+ 0x30, 0x00, /* 001100000000 */
0x00, 0x00, /* 000000000000 */
/* 160 0xa0 '.' */
@@ -4092,24 +4061,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 169 0xa9 '.' */
- /* FIXME */
- 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x3f, 0xc0, /* 001111111100 */
0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -5413,24 +5381,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 224 0xe0 '.' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x60, /* 000011110110 */
+ 0x13, 0xe0, /* 000100111110 */
+ 0x21, 0xc0, /* 001000011100 */
+ 0x60, 0xc0, /* 011000001100 */
+ 0x60, 0xc0, /* 011000001100 */
+ 0x60, 0xc0, /* 011000001100 */
+ 0x60, 0xc0, /* 011000001100 */
+ 0x70, 0x80, /* 011100001000 */
+ 0x39, 0xc0, /* 001110011100 */
+ 0x1f, 0x60, /* 000111110110 */
+ 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -5462,24 +5429,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 226 0xe2 '.' */
- /* FIXME */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x3f, 0xe0, /* 001111111110 */
+ 0x3f, 0xe0, /* 001111111110 */
+ 0x30, 0x60, /* 001100000110 */
+ 0x30, 0x60, /* 001100000110 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -5487,49 +5453,47 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 227 0xe3 '.' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
-
- /* 228 0xe4 '.' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+
+ /* 228 0xe4 '.' */
0x00, 0x00, /* 000000000000 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x30, 0x60, /* 001100000110 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x60, /* 001100000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x7f, 0xe0, /* 011111111110 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -5537,24 +5501,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 229 0xe5 '.' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
+ 0x07, 0xe0, /* 000001111110 */
+ 0x0f, 0xe0, /* 000011111110 */
+ 0x13, 0x80, /* 000100111000 */
+ 0x21, 0xc0, /* 001000011100 */
+ 0x60, 0xc0, /* 011000001100 */
+ 0x60, 0xc0, /* 011000001100 */
+ 0x60, 0xc0, /* 011000001100 */
+ 0x60, 0xc0, /* 011000001100 */
+ 0x70, 0x80, /* 011100001000 */
+ 0x39, 0x00, /* 001110010000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -5586,24 +5549,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 231 0xe7 '.' */
- /* FIXME */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
+ 0x19, 0x80, /* 000110011000 */
0x3f, 0xc0, /* 001111111100 */
+ 0x66, 0x60, /* 011001100110 */
+ 0x66, 0x60, /* 011001100110 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -5611,24 +5573,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 232 0xe8 '.' */
- /* FIXME */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x7f, 0xe0, /* 011111111110 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -5636,24 +5597,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 233 0xe9 '.' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x0f, 0x00, /* 000011110000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -5661,24 +5621,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 234 0xea '.' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x1f, 0x00, /* 000111110000 */
+ 0x31, 0x80, /* 001100011000 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x19, 0x80, /* 000110011000 */
+ 0x19, 0x80, /* 000110011000 */
+ 0xd9, 0xb0, /* 110110011011 */
+ 0x79, 0xe0, /* 011110011110 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -5686,24 +5645,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 235 0xeb '.' */
- /* FIXME */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x07, 0x80, /* 000001111000 */
+ 0x0c, 0xc0, /* 000011001100 */
+ 0x18, 0x60, /* 000110000110 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x0f, 0x80, /* 000011111000 */
+ 0x11, 0xc0, /* 000100011100 */
+ 0x20, 0xe0, /* 001000001110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x60, 0x60, /* 011000000110 */
+ 0x70, 0x40, /* 011100000100 */
+ 0x38, 0x80, /* 001110001000 */
+ 0x1f, 0x00, /* 000111110000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -5711,99 +5669,95 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 236 0xec '.' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x39, 0xc0, /* 001110011100 */
+ 0x6f, 0x60, /* 011011110110 */
+ 0x66, 0x60, /* 011001100110 */
+ 0xc6, 0x30, /* 110001100011 */
+ 0xc6, 0x30, /* 110001100011 */
+ 0x66, 0x60, /* 011001100110 */
+ 0x6f, 0x60, /* 011011110110 */
+ 0x39, 0xc0, /* 001110011100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
-
- /* 237 0xed '.' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+
+ /* 237 0xed '.' */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x00, 0xc0, /* 000000001100 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x01, 0x80, /* 000000011000 */
+ 0x3b, 0xc0, /* 001110111100 */
+ 0x6f, 0x60, /* 011011110110 */
+ 0x66, 0x60, /* 011001100110 */
+ 0xc6, 0x30, /* 110001100011 */
+ 0xc6, 0x30, /* 110001100011 */
+ 0x66, 0x60, /* 011001100110 */
+ 0x6f, 0x60, /* 011011110110 */
+ 0x3d, 0xc0, /* 001111011100 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x30, 0x00, /* 001100000000 */
+ 0x30, 0x00, /* 001100000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
/* 238 0xee '.' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
+ 0x01, 0xc0, /* 000000011100 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x1f, 0xc0, /* 000111111100 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x01, 0xc0, /* 000000011100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
/* 239 0xef '.' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
+ 0x0f, 0x00, /* 000011110000 */
+ 0x1f, 0x80, /* 000111111000 */
+ 0x39, 0xc0, /* 001110011100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
+ 0x30, 0xc0, /* 001100001100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -5811,24 +5765,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 240 0xf0 '.' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x7f, 0xe0, /* 011111111110 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -5860,24 +5813,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 242 0xf2 '.' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x60, 0x00, /* 011000000000 */
+ 0x38, 0x00, /* 001110000000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x03, 0x80, /* 000000111000 */
+ 0x00, 0xe0, /* 000000001110 */
+ 0x00, 0xe0, /* 000000001110 */
+ 0x03, 0x80, /* 000000111000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x38, 0x00, /* 001110000000 */
+ 0x60, 0x00, /* 011000000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x7f, 0xe0, /* 011111111110 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -5885,24 +5837,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 243 0xf3 '.' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x00, 0x60, /* 000000000110 */
+ 0x01, 0xc0, /* 000000011100 */
+ 0x07, 0x00, /* 000001110000 */
+ 0x1c, 0x00, /* 000111000000 */
+ 0x70, 0x00, /* 011100000000 */
+ 0x70, 0x00, /* 011100000000 */
+ 0x1c, 0x00, /* 000111000000 */
+ 0x07, 0x00, /* 000001110000 */
+ 0x01, 0xc0, /* 000000011100 */
+ 0x00, 0x60, /* 000000000110 */
0x00, 0x00, /* 000000000000 */
+ 0x7f, 0xe0, /* 011111111110 */
+ 0x7f, 0xe0, /* 011111111110 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -5910,54 +5861,52 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 244 0xf4 '.' */
- /* FIXME */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x03, 0x80, /* 000000111000 */
+ 0x07, 0xc0, /* 000001111100 */
+ 0x0c, 0x60, /* 000011000110 */
+ 0x0c, 0x60, /* 000011000110 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
+ 0x0c, 0x00, /* 000011000000 */
/* 245 0xf5 '.' */
- /* FIXME */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
- 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x1c, 0x00, /* 000111000000 */
+ 0x3e, 0x00, /* 001111100000 */
+ 0x63, 0x00, /* 011000110000 */
+ 0x63, 0x00, /* 011000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
+ 0x03, 0x00, /* 000000110000 */
/* 246 0xf6 '.' */
0x00, 0x00, /* 000000000000 */
@@ -5984,24 +5933,23 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 247 0xf7 '.' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x38, 0x00, /* 001110000000 */
+ 0x6c, 0x00, /* 011011000000 */
+ 0x06, 0x30, /* 000001100011 */
+ 0x03, 0x60, /* 000000110110 */
+ 0x39, 0xc0, /* 001110011100 */
+ 0x6c, 0x00, /* 011011000000 */
+ 0x06, 0x30, /* 000001100011 */
+ 0x03, 0x60, /* 000000110110 */
+ 0x01, 0xc0, /* 000000011100 */
+ 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -6033,44 +5981,31 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
/* 249 0xf9 '.' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
-
- /* 250 0xfa '.' */
- 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x1c, 0x00, /* 000111000000 */
+ 0x3e, 0x00, /* 001111100000 */
+ 0x3e, 0x00, /* 001111100000 */
+ 0x3e, 0x00, /* 001111100000 */
+ 0x1c, 0x00, /* 000111000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+
+ /* 250 0xfa '.' */
0x00, 0x00, /* 000000000000 */
- 0x06, 0x00, /* 000001100000 */
- 0x0f, 0x00, /* 000011110000 */
- 0x0f, 0x00, /* 000011110000 */
- 0x06, 0x00, /* 000001100000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
@@ -6080,51 +6015,61 @@ static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
-
- /* 251 0xfb '.' */
- /* FIXME */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+ 0x18, 0x00, /* 000110000000 */
+ 0x3c, 0x00, /* 001111000000 */
+ 0x3c, 0x00, /* 001111000000 */
+ 0x18, 0x00, /* 000110000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
+
+ /* 251 0xfb '.' */
0x00, 0x00, /* 000000000000 */
+ 0x07, 0xe0, /* 000001111110 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0xc6, 0x00, /* 110001100000 */
+ 0x66, 0x00, /* 011001100000 */
+ 0x36, 0x00, /* 001101100000 */
+ 0x1e, 0x00, /* 000111100000 */
+ 0x0e, 0x00, /* 000011100000 */
+ 0x06, 0x00, /* 000001100000 */
+ 0x02, 0x00, /* 000000100000 */
0x00, 0x00, /* 000000000000 */
/* 252 0xfc '.' */
- /* FIXME */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x13, 0x80, /* 000100111000 */
+ 0x3d, 0xc0, /* 001111011100 */
+ 0x18, 0xc0, /* 000110001100 */
+ 0x18, 0xc0, /* 000110001100 */
+ 0x18, 0xc0, /* 000110001100 */
+ 0x18, 0xc0, /* 000110001100 */
+ 0x3d, 0xe0, /* 001111011110 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
+ 0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
- 0x3f, 0xc0, /* 001111111100 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
0x00, 0x00, /* 000000000000 */
diff --git a/drivers/video/console/fonts.c b/drivers/video/console/fonts.c
index 465d678230a..e79b2970264 100644
--- a/drivers/video/console/fonts.c
+++ b/drivers/video/console/fonts.c
@@ -36,6 +36,10 @@ static struct font_desc *fonts[] = {
#undef NO_FONTS
&font_vga_6x11,
#endif
+#ifdef CONFIG_FONT_7x14
+#undef NO_FONTS
+ &font_7x14,
+#endif
#ifdef CONFIG_FONT_SUN8x16
#undef NO_FONTS
&font_sun_8x16,
@@ -44,6 +48,10 @@ static struct font_desc *fonts[] = {
#undef NO_FONTS
&font_sun_12x22,
#endif
+#ifdef CONFIG_FONT_10x18
+#undef NO_FONTS
+ &font_10x18,
+#endif
#ifdef CONFIG_FONT_ACORN_8x8
#undef NO_FONTS
&font_acorn_8x8,
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index bcf59b28a14..d27fa91e588 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -95,6 +95,7 @@ static unsigned long vgacon_uni_pagedir[2];
/* Description of the hardware situation */
static unsigned long vga_vram_base; /* Base of video memory */
static unsigned long vga_vram_end; /* End of video memory */
+static int vga_vram_size; /* Size of video memory */
static u16 vga_video_port_reg; /* Video register select port */
static u16 vga_video_port_val; /* Video register value port */
static unsigned int vga_video_num_columns; /* Number of text columns */
@@ -288,6 +289,7 @@ static const char __init *vgacon_startup(void)
vga_vram_base = VGA_MAP_MEM(vga_vram_base);
vga_vram_end = VGA_MAP_MEM(vga_vram_end);
+ vga_vram_size = vga_vram_end - vga_vram_base;
/*
* Find out if there is a graphics card present.
@@ -504,9 +506,13 @@ static int vgacon_switch(struct vc_data *c)
*/
vga_video_num_columns = c->vc_cols;
vga_video_num_lines = c->vc_rows;
+
+ /* We can only copy out the size of the video buffer here,
+ * otherwise we get into VGA BIOS */
+
if (!vga_is_gfx)
scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
- c->vc_screenbuf_size);
+ c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size);
return 0; /* Redrawing not needed */
}
@@ -961,7 +967,6 @@ static int vgacon_scrolldelta(struct vc_data *c, int lines)
if (!lines) /* Turn scrollback off */
c->vc_visible_origin = c->vc_origin;
else {
- int vram_size = vga_vram_end - vga_vram_base;
int margin = c->vc_size_row * 4;
int ul, we, p, st;
@@ -971,7 +976,7 @@ static int vgacon_scrolldelta(struct vc_data *c, int lines)
we = vga_rolled_over + c->vc_size_row;
} else {
ul = 0;
- we = vram_size;
+ we = vga_vram_size;
}
p = (c->vc_visible_origin - vga_vram_base - ul + we) % we +
lines * c->vc_size_row;
@@ -1012,9 +1017,13 @@ static void vgacon_save_screen(struct vc_data *c)
c->vc_x = ORIG_X;
c->vc_y = ORIG_Y;
}
+
+ /* We can't copy in more then the size of the video buffer,
+ * or we'll be copying in VGA BIOS */
+
if (!vga_is_gfx)
scr_memcpyw((u16 *) c->vc_screenbuf, (u16 *) c->vc_origin,
- c->vc_screenbuf_size);
+ c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size);
}
static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 7705070191d..2222de6ad84 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -76,70 +76,22 @@ int fb_get_color_depth(struct fb_var_screeninfo *var)
EXPORT_SYMBOL(fb_get_color_depth);
/*
- * Drawing helpers.
+ * Data padding functions.
*/
-void fb_iomove_buf_aligned(struct fb_info *info, struct fb_pixmap *buf,
- u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch,
- u32 height)
+void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height)
{
int i;
for (i = height; i--; ) {
- buf->outbuf(info, dst, src, s_pitch);
+ memcpy(dst, src, s_pitch);
src += s_pitch;
dst += d_pitch;
}
}
+EXPORT_SYMBOL(fb_pad_aligned_buffer);
-void fb_sysmove_buf_aligned(struct fb_info *info, struct fb_pixmap *buf,
- u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch,
- u32 height)
-{
- int i, j;
-
- for (i = height; i--; ) {
- for (j = 0; j < s_pitch; j++)
- dst[j] = src[j];
- src += s_pitch;
- dst += d_pitch;
- }
-}
-
-void fb_iomove_buf_unaligned(struct fb_info *info, struct fb_pixmap *buf,
- u8 *dst, u32 d_pitch, u8 *src, u32 idx,
- u32 height, u32 shift_high, u32 shift_low,
- u32 mod)
-{
- u8 mask = (u8) (0xfff << shift_high), tmp;
- int i, j;
-
- for (i = height; i--; ) {
- for (j = 0; j < idx; j++) {
- tmp = buf->inbuf(info, dst+j);
- tmp &= mask;
- tmp |= *src >> shift_low;
- buf->outbuf(info, dst+j, &tmp, 1);
- tmp = *src << shift_high;
- buf->outbuf(info, dst+j+1, &tmp, 1);
- src++;
- }
- tmp = buf->inbuf(info, dst+idx);
- tmp &= mask;
- tmp |= *src >> shift_low;
- buf->outbuf(info, dst+idx, &tmp, 1);
- if (shift_high < mod) {
- tmp = *src << shift_high;
- buf->outbuf(info, dst+idx+1, &tmp, 1);
- }
- src++;
- dst += d_pitch;
- }
-}
-
-void fb_sysmove_buf_unaligned(struct fb_info *info, struct fb_pixmap *buf,
- u8 *dst, u32 d_pitch, u8 *src, u32 idx,
- u32 height, u32 shift_high, u32 shift_low,
- u32 mod)
+void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx, u32 height,
+ u32 shift_high, u32 shift_low, u32 mod)
{
u8 mask = (u8) (0xfff << shift_high), tmp;
int i, j;
@@ -166,6 +118,7 @@ void fb_sysmove_buf_unaligned(struct fb_info *info, struct fb_pixmap *buf,
dst += d_pitch;
}
}
+EXPORT_SYMBOL(fb_pad_unaligned_buffer);
/*
* we need to lock this section since fb_cursor
@@ -1040,7 +993,7 @@ static struct file_operations fb_fops = {
#endif
};
-static struct class_simple *fb_class;
+static struct class *fb_class;
/**
* register_framebuffer - registers a frame buffer device
@@ -1066,7 +1019,7 @@ register_framebuffer(struct fb_info *fb_info)
break;
fb_info->node = i;
- fb_info->class_device = class_simple_device_add(fb_class, MKDEV(FB_MAJOR, i),
+ fb_info->class_device = class_device_create(fb_class, MKDEV(FB_MAJOR, i),
fb_info->device, "fb%d", i);
if (IS_ERR(fb_info->class_device)) {
/* Not fatal */
@@ -1081,7 +1034,7 @@ register_framebuffer(struct fb_info *fb_info)
fb_info->pixmap.size = FBPIXMAPSIZE;
fb_info->pixmap.buf_align = 1;
fb_info->pixmap.scan_align = 1;
- fb_info->pixmap.access_align = 4;
+ fb_info->pixmap.access_align = 32;
fb_info->pixmap.flags = FB_PIXMAP_DEFAULT;
}
}
@@ -1134,7 +1087,7 @@ unregister_framebuffer(struct fb_info *fb_info)
registered_fb[i]=NULL;
num_registered_fb--;
fb_cleanup_class_device(fb_info);
- class_simple_device_remove(MKDEV(FB_MAJOR, i));
+ class_device_destroy(fb_class, MKDEV(FB_MAJOR, i));
return 0;
}
@@ -1197,7 +1150,7 @@ fbmem_init(void)
if (register_chrdev(FB_MAJOR,"fb",&fb_fops))
printk("unable to get major %d for fb devs\n", FB_MAJOR);
- fb_class = class_simple_create(THIS_MODULE, "graphics");
+ fb_class = class_create(THIS_MODULE, "graphics");
if (IS_ERR(fb_class)) {
printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class));
fb_class = NULL;
@@ -1210,7 +1163,7 @@ module_init(fbmem_init);
static void __exit
fbmem_exit(void)
{
- class_simple_destroy(fb_class);
+ class_destroy(fb_class);
}
module_exit(fbmem_exit);
@@ -1357,10 +1310,6 @@ EXPORT_SYMBOL(fb_set_var);
EXPORT_SYMBOL(fb_blank);
EXPORT_SYMBOL(fb_pan_display);
EXPORT_SYMBOL(fb_get_buffer_offset);
-EXPORT_SYMBOL(fb_iomove_buf_unaligned);
-EXPORT_SYMBOL(fb_iomove_buf_aligned);
-EXPORT_SYMBOL(fb_sysmove_buf_unaligned);
-EXPORT_SYMBOL(fb_sysmove_buf_aligned);
EXPORT_SYMBOL(fb_set_suspend);
EXPORT_SYMBOL(fb_register_client);
EXPORT_SYMBOL(fb_unregister_client);
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index c78a2c5961d..7dfbf39b4ed 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -228,8 +228,6 @@ static ssize_t store_virtual(struct class_device *class_device,
if (last - buf >= count)
return -EINVAL;
var.yres_virtual = simple_strtoul(last, &last, 0);
- printk(KERN_ERR "fb: xres %d yres %d\n", var.xres_virtual,
- var.yres_virtual);
if ((err = activate(fb_info, &var)))
return err;
@@ -241,7 +239,7 @@ static ssize_t show_virtual(struct class_device *class_device, char *buf)
struct fb_info *fb_info =
(struct fb_info *)class_get_devdata(class_device);
return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xres_virtual,
- fb_info->var.xres_virtual);
+ fb_info->var.yres_virtual);
}
static ssize_t store_cmap(struct class_device *class_device, const char * buf,
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index 2a023282d7a..d3c1922cb13 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -1045,14 +1045,14 @@ static struct fb_ops gbefb_ops = {
* sysfs
*/
-static ssize_t gbefb_show_memsize(struct device *dev, char *buf)
+static ssize_t gbefb_show_memsize(struct device *dev, struct device_attribute *attr, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d\n", gbe_mem_size);
}
static DEVICE_ATTR(size, S_IRUGO, gbefb_show_memsize, NULL);
-static ssize_t gbefb_show_rev(struct device *device, char *buf)
+static ssize_t gbefb_show_rev(struct device *device, struct device_attribute *attr, char *buf)
{
return snprintf(buf, PAGE_SIZE, "%d\n", gbe_revision);
}
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index a9a618f2aa6..7513fb9b19c 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -1885,6 +1885,7 @@ static int __devinit i810fb_init_pci (struct pci_dev *dev,
memset(info->pixmap.addr, 0, 8*1024);
info->pixmap.size = 8*1024;
info->pixmap.buf_align = 8;
+ info->pixmap.access_align = 32;
info->pixmap.flags = FB_PIXMAP_SYSTEM;
if ((err = i810_allocate_pci_resource(par, entry))) {
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index 549e2293926..298bc9cd99e 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -214,7 +214,7 @@ static struct fb_ops intel_fb_ops = {
/* PCI driver module table */
static struct pci_driver intelfb_driver = {
- .name = "Intel(R) " SUPPORTED_CHIPSETS " Framebuffer Driver",
+ .name = "intelfb",
.id_table = intelfb_pci_table,
.probe = intelfb_pci_register,
.remove = __devexit_p(intelfb_pci_unregister)
@@ -228,22 +228,25 @@ MODULE_DESCRIPTION(
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DEVICE_TABLE(pci, intelfb_pci_table);
-static int accel __initdata = 1;
-static int vram __initdata = 4;
-static int hwcursor __initdata = 1;
-static int mtrr __initdata = 1;
-static int fixed __initdata = 0;
-static int noinit __initdata = 0;
-static int noregister __initdata = 0;
-static int probeonly __initdata = 0;
-static int idonly __initdata = 0;
-static int bailearly __initdata = 0;
-static char *mode __initdata = NULL;
+static int accel = 1;
+static int vram = 4;
+static int hwcursor = 1;
+static int mtrr = 1;
+static int fixed = 0;
+static int noinit = 0;
+static int noregister = 0;
+static int probeonly = 0;
+static int idonly = 0;
+static int bailearly = 0;
+static int voffset = 48;
+static char *mode = NULL;
module_param(accel, bool, S_IRUGO);
MODULE_PARM_DESC(accel, "Enable console acceleration");
module_param(vram, int, S_IRUGO);
MODULE_PARM_DESC(vram, "System RAM to allocate to framebuffer in MiB");
+module_param(voffset, int, S_IRUGO);
+MODULE_PARM_DESC(voffset, "Offset of framebuffer in MiB");
module_param(hwcursor, bool, S_IRUGO);
MODULE_PARM_DESC(hwcursor, "Enable HW cursor");
module_param(mtrr, bool, S_IRUGO);
@@ -503,6 +506,7 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
struct agp_bridge_data *bridge;
int aperture_bar = 0;
int mmio_bar = 1;
+ int offset;
DBG_MSG("intelfb_pci_register\n");
@@ -659,17 +663,21 @@ intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
return -ENODEV;
}
+ if (MB(voffset) < stolen_size)
+ offset = (stolen_size >> 12);
+ else
+ offset = ROUND_UP_TO_PAGE(MB(voffset))/GTT_PAGE_SIZE;
+
/* set the mem offsets - set them after the already used pages */
if (dinfo->accel) {
- dinfo->ring.offset = (stolen_size >> 12)
- + gtt_info.current_memory;
+ dinfo->ring.offset = offset + gtt_info.current_memory;
}
if (dinfo->hwcursor) {
- dinfo->cursor.offset = (stolen_size >> 12) +
+ dinfo->cursor.offset = offset +
+ gtt_info.current_memory + (dinfo->ring.size >> 12);
}
if (dinfo->fbmem_gart) {
- dinfo->fb.offset = (stolen_size >> 12) +
+ dinfo->fb.offset = offset +
+ gtt_info.current_memory + (dinfo->ring.size >> 12)
+ (dinfo->cursor.size >> 12);
}
@@ -1083,6 +1091,7 @@ intelfb_set_fbinfo(struct intelfb_info *dinfo)
info->pixmap.size = 64*1024;
info->pixmap.buf_align = 8;
+ info->pixmap.access_align = 32;
info->pixmap.flags = FB_PIXMAP_SYSTEM;
if (intelfb_init_var(dinfo))
@@ -1293,7 +1302,7 @@ intelfb_set_par(struct fb_info *info)
intelfb_blank(FB_BLANK_POWERDOWN, info);
- if (dinfo->accel)
+ if (ACCEL(dinfo, info))
intelfbhw_2d_stop(dinfo);
memcpy(hw, &dinfo->save_state, sizeof(*hw));
@@ -1309,7 +1318,7 @@ intelfb_set_par(struct fb_info *info)
update_dinfo(dinfo, &info->var);
- if (dinfo->accel)
+ if (ACCEL(dinfo, info))
intelfbhw_2d_start(dinfo);
intelfb_pan_display(&info->var, info);
diff --git a/drivers/video/macmodes.c b/drivers/video/macmodes.c
index de5a0f38360..2fc71081f7e 100644
--- a/drivers/video/macmodes.c
+++ b/drivers/video/macmodes.c
@@ -387,3 +387,4 @@ int __init mac_find_mode(struct fb_var_screeninfo *var, struct fb_info *info,
}
EXPORT_SYMBOL(mac_find_mode);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index e529841cd83..67f85344f0c 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -1230,7 +1230,6 @@ static int maven_shutdown_client(struct i2c_client* clnt) {
}
static unsigned short normal_i2c[] = { MAVEN_I2CID, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { MAVEN_I2CID, MAVEN_I2CID, I2C_CLIENT_END };
I2C_CLIENT_INSMOD;
static struct i2c_driver maven_driver;
diff --git a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/matrox/matroxfb_misc.c
index 76fd3a519b8..a18dd024fc8 100644
--- a/drivers/video/matrox/matroxfb_misc.c
+++ b/drivers/video/matrox/matroxfb_misc.c
@@ -197,10 +197,7 @@ int matroxfb_vgaHWinit(WPMINFO struct my_timming* m) {
DBG(__FUNCTION__)
hw->SEQ[0] = 0x00;
- if (fwidth == 9)
- hw->SEQ[1] = 0x00;
- else
- hw->SEQ[1] = 0x01; /* or 0x09 */
+ hw->SEQ[1] = 0x01; /* or 0x09 */
hw->SEQ[2] = 0x0F; /* bitplanes */
hw->SEQ[3] = 0x00;
hw->SEQ[4] = 0x0E;
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index 47733f58153..b2e6b240786 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -516,9 +516,9 @@ static struct backlight_controller nvidia_backlight_controller = {
static void nvidiafb_load_cursor_image(struct nvidia_par *par, u8 * data8,
u16 bg, u16 fg, u32 w, u32 h)
{
+ u32 *data = (u32 *) data8;
int i, j, k = 0;
u32 b, tmp;
- u32 *data = (u32 *) data8;
w = (w + 1) & ~1;
@@ -890,11 +890,11 @@ static int nvidiafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
struct nvidia_par *par = info->par;
u8 data[MAX_CURS * MAX_CURS / 8];
- u16 fg, bg;
int i, set = cursor->set;
+ u16 fg, bg;
if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
- return soft_cursor(info, cursor);
+ return -ENXIO;
NVShowHideCursor(par, 0);
@@ -931,21 +931,18 @@ static int nvidiafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
if (src) {
switch (cursor->rop) {
case ROP_XOR:
- for (i = 0; i < s_pitch * cursor->image.height;
- i++)
+ for (i = 0; i < s_pitch * cursor->image.height; i++)
src[i] = dat[i] ^ msk[i];
break;
case ROP_COPY:
default:
- for (i = 0; i < s_pitch * cursor->image.height;
- i++)
+ for (i = 0; i < s_pitch * cursor->image.height; i++)
src[i] = dat[i] & msk[i];
break;
}
- fb_sysmove_buf_aligned(info, &info->pixmap, data,
- d_pitch, src, s_pitch,
- cursor->image.height);
+ fb_pad_aligned_buffer(data, d_pitch, src, s_pitch,
+ cursor->image.height);
bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
((info->cmap.green[bg_idx] & 0xf8) << 2) |
@@ -1348,6 +1345,7 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info)
info->pixmap.scan_align = 4;
info->pixmap.buf_align = 4;
+ info->pixmap.access_align = 32;
info->pixmap.size = 8 * 1024;
info->pixmap.flags = FB_PIXMAP_SYSTEM;
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index 8e024aad1b5..e0dad948467 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -5,7 +5,7 @@
* Based on code written by:
* Sven Luther, <luther@dpt-info.u-strasbg.fr>
* Alan Hourihane, <alanh@fairlite.demon.co.uk>
- * Russel King, <rmk@arm.linux.org.uk>
+ * Russell King, <rmk@arm.linux.org.uk>
* Based on linux/drivers/video/skeletonfb.c:
* Copyright (C) 1997 Geert Uytterhoeven
* Based on linux/driver/video/pm2fb.c:
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 815fbc8317f..16e37a535d8 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -43,6 +43,7 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
+#include <asm/div64.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/bitfield.h>
#include <asm/arch/pxafb.h>
@@ -460,7 +461,7 @@ static inline unsigned int get_pcd(unsigned int pixclock)
* speeds */
pcd = (unsigned long long)get_lcdclk_frequency_10khz() * pixclock;
- pcd /= 100000000 * 2;
+ do_div(pcd, 100000000 * 2);
/* no need for this, since we should subtract 1 anyway. they cancel */
/* pcd += 1; */ /* make up for integer math truncations */
return (unsigned int)pcd;
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index b0c886de040..6a9e183be41 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -1582,12 +1582,11 @@ static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
struct riva_par *par = (struct riva_par *) info->par;
u8 data[MAX_CURS * MAX_CURS/8];
- u16 fg, bg;
int i, set = cursor->set;
+ u16 fg, bg;
- if (cursor->image.width > MAX_CURS ||
- cursor->image.height > MAX_CURS)
- return soft_cursor(info, cursor);
+ if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
+ return -ENXIO;
par->riva.ShowHideCursor(&par->riva, 0);
@@ -1625,21 +1624,18 @@ static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
if (src) {
switch (cursor->rop) {
case ROP_XOR:
- for (i = 0; i < s_pitch * cursor->image.height;
- i++)
+ for (i = 0; i < s_pitch * cursor->image.height; i++)
src[i] = dat[i] ^ msk[i];
break;
case ROP_COPY:
default:
- for (i = 0; i < s_pitch * cursor->image.height;
- i++)
+ for (i = 0; i < s_pitch * cursor->image.height; i++)
src[i] = dat[i] & msk[i];
break;
}
- fb_sysmove_buf_aligned(info, &info->pixmap, data,
- d_pitch, src, s_pitch,
- cursor->image.height);
+ fb_pad_aligned_buffer(data, d_pitch, src, s_pitch,
+ cursor->image.height);
bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
((info->cmap.green[bg_idx] & 0xf8) << 2) |
@@ -1727,6 +1723,7 @@ static int __devinit riva_set_fbinfo(struct fb_info *info)
info->pixmap.size = 8 * 1024;
info->pixmap.buf_align = 4;
+ info->pixmap.access_align = 32;
info->pixmap.flags = FB_PIXMAP_SYSTEM;
info->var.yres_virtual = -1;
NVTRACE_LEAVE();
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c
index b637c389e4f..789de13f461 100644
--- a/drivers/video/s1d13xxxfb.c
+++ b/drivers/video/s1d13xxxfb.c
@@ -493,7 +493,7 @@ s1d13xxxfb_fetch_hw_state(struct fb_info *info)
}
-static int __devexit
+static int
s1d13xxxfb_remove(struct device *dev)
{
struct fb_info *info = dev_get_drvdata(dev);
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index 03d74e8ee06..8fadcdae6f4 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -1897,7 +1897,7 @@ static int __devinit savage_init_fb_info (struct fb_info *info,
info->pixmap.size = 8*1024;
info->pixmap.scan_align = 4;
info->pixmap.buf_align = 4;
- info->pixmap.access_align = 4;
+ info->pixmap.access_align = 32;
fb_alloc_cmap (&info->cmap, NR_PALETTE, 0);
info->flags |= FBINFO_HWACCEL_COPYAREA |
diff --git a/drivers/video/softcursor.c b/drivers/video/softcursor.c
index 13a4511539a..229c4bc3507 100644
--- a/drivers/video/softcursor.c
+++ b/drivers/video/softcursor.c
@@ -58,17 +58,10 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
} else
memcpy(src, image->data, dsize);
- if (info->pixmap.outbuf)
- fb_iomove_buf_aligned(info, &info->pixmap, dst, d_pitch, src,
- s_pitch, image->height);
- else
- fb_sysmove_buf_aligned(info, &info->pixmap, dst, d_pitch, src,
- s_pitch, image->height);
-
+ fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, image->height);
image->data = dst;
info->fbops->fb_imageblit(info, image);
kfree(src);
-
return 0;
}
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index 3027841f9c2..9ed1a931dd3 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -271,7 +271,7 @@ static int __init vesafb_probe(struct device *device)
if (!request_mem_region(vesafb_fix.smem_start, size_total, "vesafb")) {
printk(KERN_WARNING
- "vesafb: abort, cannot reserve video memory at 0x%lx\n",
+ "vesafb: cannot reserve video memory at 0x%lx\n",
vesafb_fix.smem_start);
/* We cannot make this fatal. Sometimes this comes from magic
spaces our resource handlers simply don't know about */
@@ -279,13 +279,13 @@ static int __init vesafb_probe(struct device *device)
info = framebuffer_alloc(sizeof(u32) * 256, &dev->dev);
if (!info) {
- release_mem_region(vesafb_fix.smem_start, vesafb_fix.smem_len);
+ release_mem_region(vesafb_fix.smem_start, size_total);
return -ENOMEM;
}
info->pseudo_palette = info->par;
info->par = NULL;
- info->screen_base = ioremap(vesafb_fix.smem_start, vesafb_fix.smem_len);
+ info->screen_base = ioremap(vesafb_fix.smem_start, vesafb_fix.smem_len);
if (!info->screen_base) {
printk(KERN_ERR
"vesafb: abort, cannot ioremap video memory 0x%x @ 0x%lx\n",
@@ -386,13 +386,14 @@ static int __init vesafb_probe(struct device *device)
request_region(0x3c0, 32, "vesafb");
if (mtrr) {
- int temp_size = size_total;
+ unsigned int temp_size = size_total;
/* Find the largest power-of-two */
while (temp_size & (temp_size - 1))
- temp_size &= (temp_size - 1);
-
- /* Try and find a power of two to add */
- while (temp_size && mtrr_add(vesafb_fix.smem_start, temp_size, MTRR_TYPE_WRCOMB, 1)==-EINVAL) {
+ temp_size &= (temp_size - 1);
+
+ /* Try and find a power of two to add */
+ while (temp_size > PAGE_SIZE &&
+ mtrr_add(vesafb_fix.smem_start, temp_size, MTRR_TYPE_WRCOMB, 1)==-EINVAL) {
temp_size >>= 1;
}
}
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
index 58cd2ad84af..adcda697ea6 100644
--- a/drivers/video/w100fb.c
+++ b/drivers/video/w100fb.c
@@ -101,7 +101,7 @@ static void(*w100fb_ssp_send)(u8 adrs, u8 data);
* Sysfs functions
*/
-static ssize_t rotation_show(struct device *dev, char *buf)
+static ssize_t rotation_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct fb_info *info = dev_get_drvdata(dev);
struct w100fb_par *par=info->par;
@@ -109,7 +109,7 @@ static ssize_t rotation_show(struct device *dev, char *buf)
return sprintf(buf, "%d\n",par->rotation_flag);
}
-static ssize_t rotation_store(struct device *dev, const char *buf, size_t count)
+static ssize_t rotation_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
unsigned int rotate;
struct fb_info *info = dev_get_drvdata(dev);
@@ -134,7 +134,7 @@ static ssize_t rotation_store(struct device *dev, const char *buf, size_t count)
static DEVICE_ATTR(rotation, 0644, rotation_show, rotation_store);
-static ssize_t w100fb_reg_read(struct device *dev, const char *buf, size_t count)
+static ssize_t w100fb_reg_read(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
unsigned long param;
unsigned long regs;
@@ -146,7 +146,7 @@ static ssize_t w100fb_reg_read(struct device *dev, const char *buf, size_t count
static DEVICE_ATTR(reg_read, 0200, NULL, w100fb_reg_read);
-static ssize_t w100fb_reg_write(struct device *dev, const char *buf, size_t count)
+static ssize_t w100fb_reg_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
unsigned long regs;
unsigned long param;
@@ -163,7 +163,7 @@ static ssize_t w100fb_reg_write(struct device *dev, const char *buf, size_t coun
static DEVICE_ATTR(reg_write, 0200, NULL, w100fb_reg_write);
-static ssize_t fastsysclk_show(struct device *dev, char *buf)
+static ssize_t fastsysclk_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct fb_info *info = dev_get_drvdata(dev);
struct w100fb_par *par=info->par;
@@ -171,7 +171,7 @@ static ssize_t fastsysclk_show(struct device *dev, char *buf)
return sprintf(buf, "%d\n",par->fastsysclk_mode);
}
-static ssize_t fastsysclk_store(struct device *dev, const char *buf, size_t count)
+static ssize_t fastsysclk_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int param;
struct fb_info *info = dev_get_drvdata(dev);
diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig
index 2ab65c902fe..4f120796273 100644
--- a/drivers/w1/Kconfig
+++ b/drivers/w1/Kconfig
@@ -3,9 +3,9 @@ menu "Dallas's 1-wire bus"
config W1
tristate "Dallas's 1-wire support"
---help---
- Dallas's 1-wire bus is usefull to connect slow 1-pin devices
+ Dallas's 1-wire bus is usefull to connect slow 1-pin devices
such as iButtons and thermal sensors.
-
+
If you want W1 support, you should say Y here.
This W1 support can also be built as a module. If so, the module
@@ -17,8 +17,8 @@ config W1_MATROX
help
Say Y here if you want to communicate with your 1-wire devices
using Matrox's G400 GPIO pins.
-
- This support is also available as a module. If so, the module
+
+ This support is also available as a module. If so, the module
will be called matrox_w1.ko.
config W1_DS9490
@@ -27,17 +27,17 @@ config W1_DS9490
help
Say Y here if you want to have a driver for DS9490R UWB <-> W1 bridge.
- This support is also available as a module. If so, the module
+ This support is also available as a module. If so, the module
will be called ds9490r.ko.
-config W1_DS9490_BRIDGE
+config W1_DS9490R_BRIDGE
tristate "DS9490R USB <-> W1 transport layer for 1-wire"
depends on W1_DS9490
help
Say Y here if you want to communicate with your 1-wire devices
using DS9490R USB bridge.
- This support is also available as a module. If so, the module
+ This support is also available as a module. If so, the module
will be called ds_w1_bridge.ko.
config W1_THERM
@@ -51,7 +51,7 @@ config W1_SMEM
tristate "Simple 64bit memory family implementation"
depends on W1
help
- Say Y here if you want to connect 1-wire
+ Say Y here if you want to connect 1-wire
simple 64bit memory rom(ds2401/ds2411/ds1990*) to you wire.
endmenu
diff --git a/drivers/w1/ds_w1_bridge.c b/drivers/w1/ds_w1_bridge.c
index 0baaeb5fd63..7bddd8ac7d7 100644
--- a/drivers/w1/ds_w1_bridge.c
+++ b/drivers/w1/ds_w1_bridge.c
@@ -83,11 +83,11 @@ static u8 ds9490r_read_byte(unsigned long data)
return byte;
}
-static void ds9490r_write_block(unsigned long data, u8 *buf, int len)
+static void ds9490r_write_block(unsigned long data, const u8 *buf, int len)
{
struct ds_device *dev = (struct ds_device *)data;
- ds_write_block(dev, buf, len);
+ ds_write_block(dev, (u8 *)buf, len);
}
static u8 ds9490r_read_block(unsigned long data, u8 *buf, int len)
diff --git a/drivers/w1/matrox_w1.c b/drivers/w1/matrox_w1.c
index e565416458e..0b03f8f93f6 100644
--- a/drivers/w1/matrox_w1.c
+++ b/drivers/w1/matrox_w1.c
@@ -1,8 +1,8 @@
/*
- * matrox_w1.c
+ * matrox_w1.c
*
* Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- *
+ *
*
* 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
@@ -59,7 +59,7 @@ static struct pci_driver matrox_w1_pci_driver = {
.remove = __devexit_p(matrox_w1_remove),
};
-/*
+/*
* Matrox G400 DDC registers.
*/
@@ -177,8 +177,8 @@ static int __devinit matrox_w1_probe(struct pci_dev *pdev, const struct pci_devi
dev->bus_master = (struct w1_bus_master *)(dev + 1);
- /*
- * True for G400, for some other we need resource 0, see drivers/video/matrox/matroxfb_base.c
+ /*
+ * True for G400, for some other we need resource 0, see drivers/video/matrox/matroxfb_base.c
*/
dev->phys_addr = pci_resource_start(pdev, 1);
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index 8d7821899cc..312cf3220f1 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -1,8 +1,8 @@
/*
- * w1.c
+ * w1.c
*
* Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- *
+ *
*
* 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
@@ -59,6 +59,19 @@ static pid_t control_thread;
static int control_needs_exit;
static DECLARE_COMPLETION(w1_control_complete);
+/* stuff for the default family */
+static ssize_t w1_famdefault_read_name(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
+ return(sprintf(buf, "%s\n", sl->name));
+}
+static struct w1_family_ops w1_default_fops = {
+ .rname = &w1_famdefault_read_name,
+};
+static struct w1_family w1_default_family = {
+ .fops = &w1_default_fops,
+};
+
static int w1_master_match(struct device *dev, struct device_driver *drv)
{
return 1;
@@ -88,7 +101,7 @@ static void w1_slave_release(struct device *dev)
complete(&sl->dev_released);
}
-static ssize_t w1_default_read_name(struct device *dev, char *buf)
+static ssize_t w1_default_read_name(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf, "No family registered.\n");
}
@@ -99,6 +112,20 @@ static ssize_t w1_default_read_bin(struct kobject *kobj, char *buf, loff_t off,
return sprintf(buf, "No family registered.\n");
}
+static struct device_attribute w1_slave_attribute =
+ __ATTR(name, S_IRUGO, w1_default_read_name, NULL);
+
+static struct bin_attribute w1_slave_bin_attribute = {
+ .attr = {
+ .name = "w1_slave",
+ .mode = S_IRUGO,
+ .owner = THIS_MODULE,
+ },
+ .size = W1_SLAVE_DATA_SIZE,
+ .read = &w1_default_read_bin,
+};
+
+
static struct bus_type w1_bus_type = {
.name = "w1",
.match = w1_master_match,
@@ -119,104 +146,118 @@ struct device w1_device = {
.release = &w1_master_release
};
-static struct device_attribute w1_slave_attribute = {
- .attr = {
- .name = "name",
- .mode = S_IRUGO,
- .owner = THIS_MODULE
- },
- .show = &w1_default_read_name,
-};
+static ssize_t w1_master_attribute_show_name(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct w1_master *md = container_of(dev, struct w1_master, dev);
+ ssize_t count;
-static struct device_attribute w1_slave_attribute_val = {
- .attr = {
- .name = "value",
- .mode = S_IRUGO,
- .owner = THIS_MODULE
- },
- .show = &w1_default_read_name,
-};
+ if (down_interruptible (&md->mutex))
+ return -EBUSY;
-static ssize_t w1_master_attribute_show_name(struct device *dev, char *buf)
+ count = sprintf(buf, "%s\n", md->name);
+
+ up(&md->mutex);
+
+ return count;
+}
+
+static ssize_t w1_master_attribute_store_search(struct device * dev,
+ struct device_attribute *attr,
+ const char * buf, size_t count)
{
- struct w1_master *md = container_of (dev, struct w1_master, dev);
+ struct w1_master *md = container_of(dev, struct w1_master, dev);
+
+ if (down_interruptible (&md->mutex))
+ return -EBUSY;
+
+ md->search_count = simple_strtol(buf, NULL, 0);
+
+ up(&md->mutex);
+
+ return count;
+}
+
+static ssize_t w1_master_attribute_show_search(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct w1_master *md = container_of(dev, struct w1_master, dev);
ssize_t count;
-
+
if (down_interruptible (&md->mutex))
return -EBUSY;
- count = sprintf(buf, "%s\n", md->name);
-
+ count = sprintf(buf, "%d\n", md->search_count);
+
up(&md->mutex);
return count;
}
-static ssize_t w1_master_attribute_show_pointer(struct device *dev, char *buf)
+static ssize_t w1_master_attribute_show_pointer(struct device *dev, struct device_attribute *attr, char *buf)
{
struct w1_master *md = container_of(dev, struct w1_master, dev);
ssize_t count;
-
+
if (down_interruptible(&md->mutex))
return -EBUSY;
count = sprintf(buf, "0x%p\n", md->bus_master);
-
+
up(&md->mutex);
return count;
}
-static ssize_t w1_master_attribute_show_timeout(struct device *dev, char *buf)
+static ssize_t w1_master_attribute_show_timeout(struct device *dev, struct device_attribute *attr, char *buf)
{
ssize_t count;
count = sprintf(buf, "%d\n", w1_timeout);
return count;
}
-static ssize_t w1_master_attribute_show_max_slave_count(struct device *dev, char *buf)
+static ssize_t w1_master_attribute_show_max_slave_count(struct device *dev, struct device_attribute *attr, char *buf)
{
struct w1_master *md = container_of(dev, struct w1_master, dev);
ssize_t count;
-
+
if (down_interruptible(&md->mutex))
return -EBUSY;
count = sprintf(buf, "%d\n", md->max_slave_count);
-
+
up(&md->mutex);
return count;
}
-static ssize_t w1_master_attribute_show_attempts(struct device *dev, char *buf)
+static ssize_t w1_master_attribute_show_attempts(struct device *dev, struct device_attribute *attr, char *buf)
{
struct w1_master *md = container_of(dev, struct w1_master, dev);
ssize_t count;
-
+
if (down_interruptible(&md->mutex))
return -EBUSY;
count = sprintf(buf, "%lu\n", md->attempts);
-
+
up(&md->mutex);
return count;
}
-static ssize_t w1_master_attribute_show_slave_count(struct device *dev, char *buf)
+static ssize_t w1_master_attribute_show_slave_count(struct device *dev, struct device_attribute *attr, char *buf)
{
struct w1_master *md = container_of(dev, struct w1_master, dev);
ssize_t count;
-
+
if (down_interruptible(&md->mutex))
return -EBUSY;
count = sprintf(buf, "%d\n", md->slave_count);
-
+
up(&md->mutex);
return count;
}
-static ssize_t w1_master_attribute_show_slaves(struct device *dev, char *buf)
-
+static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device_attribute *attr, char *buf)
{
struct w1_master *md = container_of(dev, struct w1_master, dev);
int c = PAGE_SIZE;
@@ -233,7 +274,7 @@ static ssize_t w1_master_attribute_show_slaves(struct device *dev, char *buf)
list_for_each_safe(ent, n, &md->slist) {
sl = list_entry(ent, struct w1_slave, w1_slave_entry);
- c -= snprintf(buf + PAGE_SIZE - c, c, "%s\n", sl->name);
+ c -= snprintf(buf + PAGE_SIZE - c, c, "%s\n", sl->name);
}
}
@@ -242,73 +283,52 @@ static ssize_t w1_master_attribute_show_slaves(struct device *dev, char *buf)
return PAGE_SIZE - c;
}
-static struct device_attribute w1_master_attribute_slaves = {
- .attr = {
- .name = "w1_master_slaves",
- .mode = S_IRUGO,
- .owner = THIS_MODULE,
- },
- .show = &w1_master_attribute_show_slaves,
-};
-static struct device_attribute w1_master_attribute_slave_count = {
- .attr = {
- .name = "w1_master_slave_count",
- .mode = S_IRUGO,
- .owner = THIS_MODULE
- },
- .show = &w1_master_attribute_show_slave_count,
-};
-static struct device_attribute w1_master_attribute_attempts = {
- .attr = {
- .name = "w1_master_attempts",
- .mode = S_IRUGO,
- .owner = THIS_MODULE
- },
- .show = &w1_master_attribute_show_attempts,
-};
-static struct device_attribute w1_master_attribute_max_slave_count = {
- .attr = {
- .name = "w1_master_max_slave_count",
- .mode = S_IRUGO,
- .owner = THIS_MODULE
- },
- .show = &w1_master_attribute_show_max_slave_count,
-};
-static struct device_attribute w1_master_attribute_timeout = {
- .attr = {
- .name = "w1_master_timeout",
- .mode = S_IRUGO,
- .owner = THIS_MODULE
- },
- .show = &w1_master_attribute_show_timeout,
-};
-static struct device_attribute w1_master_attribute_pointer = {
- .attr = {
- .name = "w1_master_pointer",
- .mode = S_IRUGO,
- .owner = THIS_MODULE
- },
- .show = &w1_master_attribute_show_pointer,
-};
-static struct device_attribute w1_master_attribute_name = {
- .attr = {
- .name = "w1_master_name",
- .mode = S_IRUGO,
- .owner = THIS_MODULE
- },
- .show = &w1_master_attribute_show_name,
+#define W1_MASTER_ATTR_RO(_name, _mode) \
+ struct device_attribute w1_master_attribute_##_name = \
+ __ATTR(w1_master_##_name, _mode, \
+ w1_master_attribute_show_##_name, NULL)
+
+#define W1_MASTER_ATTR_RW(_name, _mode) \
+ struct device_attribute w1_master_attribute_##_name = \
+ __ATTR(w1_master_##_name, _mode, \
+ w1_master_attribute_show_##_name, \
+ w1_master_attribute_store_##_name)
+
+static W1_MASTER_ATTR_RO(name, S_IRUGO);
+static W1_MASTER_ATTR_RO(slaves, S_IRUGO);
+static W1_MASTER_ATTR_RO(slave_count, S_IRUGO);
+static W1_MASTER_ATTR_RO(max_slave_count, S_IRUGO);
+static W1_MASTER_ATTR_RO(attempts, S_IRUGO);
+static W1_MASTER_ATTR_RO(timeout, S_IRUGO);
+static W1_MASTER_ATTR_RO(pointer, S_IRUGO);
+static W1_MASTER_ATTR_RW(search, S_IRUGO | S_IWUGO);
+
+static struct attribute *w1_master_default_attrs[] = {
+ &w1_master_attribute_name.attr,
+ &w1_master_attribute_slaves.attr,
+ &w1_master_attribute_slave_count.attr,
+ &w1_master_attribute_max_slave_count.attr,
+ &w1_master_attribute_attempts.attr,
+ &w1_master_attribute_timeout.attr,
+ &w1_master_attribute_pointer.attr,
+ &w1_master_attribute_search.attr,
+ NULL
};
-static struct bin_attribute w1_slave_bin_attribute = {
- .attr = {
- .name = "w1_slave",
- .mode = S_IRUGO,
- .owner = THIS_MODULE,
- },
- .size = W1_SLAVE_DATA_SIZE,
- .read = &w1_default_read_bin,
+static struct attribute_group w1_master_defattr_group = {
+ .attrs = w1_master_default_attrs,
};
+int w1_create_master_attributes(struct w1_master *master)
+{
+ return sysfs_create_group(&master->dev.kobj, &w1_master_defattr_group);
+}
+
+void w1_destroy_master_attributes(struct w1_master *master)
+{
+ sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group);
+}
+
static int __w1_attach_slave_device(struct w1_slave *sl)
{
int err;
@@ -319,13 +339,13 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
sl->dev.release = &w1_slave_release;
snprintf(&sl->dev.bus_id[0], sizeof(sl->dev.bus_id),
- "%02x-%012llx",
- (unsigned int) sl->reg_num.family,
- (unsigned long long) sl->reg_num.id);
- snprintf (&sl->name[0], sizeof(sl->name),
- "%02x-%012llx",
- (unsigned int) sl->reg_num.family,
- (unsigned long long) sl->reg_num.id);
+ "%02x-%012llx",
+ (unsigned int) sl->reg_num.family,
+ (unsigned long long) sl->reg_num.id);
+ snprintf(&sl->name[0], sizeof(sl->name),
+ "%02x-%012llx",
+ (unsigned int) sl->reg_num.family,
+ (unsigned long long) sl->reg_num.id);
dev_dbg(&sl->dev, "%s: registering %s.\n", __func__,
&sl->dev.bus_id[0]);
@@ -333,48 +353,36 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
err = device_register(&sl->dev);
if (err < 0) {
dev_err(&sl->dev,
- "Device registration [%s] failed. err=%d\n",
- sl->dev.bus_id, err);
+ "Device registration [%s] failed. err=%d\n",
+ sl->dev.bus_id, err);
return err;
}
memcpy(&sl->attr_bin, &w1_slave_bin_attribute, sizeof(sl->attr_bin));
memcpy(&sl->attr_name, &w1_slave_attribute, sizeof(sl->attr_name));
- memcpy(&sl->attr_val, &w1_slave_attribute_val, sizeof(sl->attr_val));
-
+
sl->attr_bin.read = sl->family->fops->rbin;
sl->attr_name.show = sl->family->fops->rname;
- sl->attr_val.show = sl->family->fops->rval;
- sl->attr_val.attr.name = sl->family->fops->rvalname;
err = device_create_file(&sl->dev, &sl->attr_name);
if (err < 0) {
dev_err(&sl->dev,
- "sysfs file creation for [%s] failed. err=%d\n",
- sl->dev.bus_id, err);
- device_unregister(&sl->dev);
- return err;
- }
-
- err = device_create_file(&sl->dev, &sl->attr_val);
- if (err < 0) {
- dev_err(&sl->dev,
- "sysfs file creation for [%s] failed. err=%d\n",
- sl->dev.bus_id, err);
- device_remove_file(&sl->dev, &sl->attr_name);
+ "sysfs file creation for [%s] failed. err=%d\n",
+ sl->dev.bus_id, err);
device_unregister(&sl->dev);
return err;
}
- err = sysfs_create_bin_file(&sl->dev.kobj, &sl->attr_bin);
- if (err < 0) {
- dev_err(&sl->dev,
- "sysfs file creation for [%s] failed. err=%d\n",
- sl->dev.bus_id, err);
- device_remove_file(&sl->dev, &sl->attr_name);
- device_remove_file(&sl->dev, &sl->attr_val);
- device_unregister(&sl->dev);
- return err;
+ if ( sl->attr_bin.read ) {
+ err = sysfs_create_bin_file(&sl->dev.kobj, &sl->attr_bin);
+ if (err < 0) {
+ dev_err(&sl->dev,
+ "sysfs file creation for [%s] failed. err=%d\n",
+ sl->dev.bus_id, err);
+ device_remove_file(&sl->dev, &sl->attr_name);
+ device_unregister(&sl->dev);
+ return err;
+ }
}
list_add_tail(&sl->w1_slave_entry, &sl->master->slist);
@@ -410,12 +418,10 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
spin_lock(&w1_flock);
f = w1_family_registered(rn->family);
if (!f) {
- spin_unlock(&w1_flock);
+ f= &w1_default_family;
dev_info(&dev->dev, "Family %x for %02x.%012llx.%02x is not registered.\n",
rn->family, rn->family,
(unsigned long long)rn->id, rn->crc);
- kfree(sl);
- return -ENODEV;
}
__w1_family_get(f);
spin_unlock(&w1_flock);
@@ -445,7 +451,7 @@ static int w1_attach_slave_device(struct w1_master *dev, struct w1_reg_num *rn)
static void w1_slave_detach(struct w1_slave *sl)
{
struct w1_netlink_msg msg;
-
+
dev_info(&sl->dev, "%s: detaching %s.\n", __func__, sl->name);
while (atomic_read(&sl->refcnt)) {
@@ -456,12 +462,15 @@ static void w1_slave_detach(struct w1_slave *sl)
flush_signals(current);
}
- sysfs_remove_bin_file (&sl->dev.kobj, &sl->attr_bin);
+ if ( sl->attr_bin.read ) {
+ sysfs_remove_bin_file (&sl->dev.kobj, &sl->attr_bin);
+ }
device_remove_file(&sl->dev, &sl->attr_name);
- device_remove_file(&sl->dev, &sl->attr_val);
device_unregister(&sl->dev);
w1_family_put(sl->family);
+ sl->master->slave_count--;
+
memcpy(&msg.id.id, &sl->reg_num, sizeof(msg.id.id));
msg.type = W1_SLAVE_REMOVE;
w1_netlink_send(sl->master, &msg);
@@ -471,8 +480,8 @@ static struct w1_master *w1_search_master(unsigned long data)
{
struct w1_master *dev;
int found = 0;
-
- spin_lock_irq(&w1_mlock);
+
+ spin_lock_bh(&w1_mlock);
list_for_each_entry(dev, &w1_masters, w1_master_entry) {
if (dev->bus_master->data == data) {
found = 1;
@@ -480,12 +489,26 @@ static struct w1_master *w1_search_master(unsigned long data)
break;
}
}
- spin_unlock_irq(&w1_mlock);
+ spin_unlock_bh(&w1_mlock);
return (found)?dev:NULL;
}
-void w1_slave_found(unsigned long data, u64 rn)
+void w1_reconnect_slaves(struct w1_family *f)
+{
+ struct w1_master *dev;
+
+ spin_lock_bh(&w1_mlock);
+ list_for_each_entry(dev, &w1_masters, w1_master_entry) {
+ dev_info(&dev->dev, "Reconnecting slaves in %s into new family %02x.\n",
+ dev->name, f->fid);
+ set_bit(W1_MASTER_NEED_RECONNECT, &dev->flags);
+ }
+ spin_unlock_bh(&w1_mlock);
+}
+
+
+static void w1_slave_found(unsigned long data, u64 rn)
{
int slave_count;
struct w1_slave *sl;
@@ -500,7 +523,7 @@ void w1_slave_found(unsigned long data, u64 rn)
data);
return;
}
-
+
tmp = (struct w1_reg_num *) &rn;
slave_count = 0;
@@ -513,8 +536,7 @@ void w1_slave_found(unsigned long data, u64 rn)
sl->reg_num.crc == tmp->crc) {
set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
break;
- }
- else if (sl->reg_num.family == tmp->family) {
+ } else if (sl->reg_num.family == tmp->family) {
family_found = 1;
break;
}
@@ -528,30 +550,43 @@ void w1_slave_found(unsigned long data, u64 rn)
rn && ((le64_to_cpu(rn) >> 56) & 0xff) == w1_calc_crc8((u8 *)&rn, 7)) {
w1_attach_slave_device(dev, tmp);
}
-
+
atomic_dec(&dev->refcnt);
}
-void w1_search(struct w1_master *dev)
+/**
+ * Performs a ROM Search & registers any devices found.
+ * The 1-wire search is a simple binary tree search.
+ * For each bit of the address, we read two bits and write one bit.
+ * The bit written will put to sleep all devies that don't match that bit.
+ * When the two reads differ, the direction choice is obvious.
+ * When both bits are 0, we must choose a path to take.
+ * When we can scan all 64 bits without having to choose a path, we are done.
+ *
+ * See "Application note 187 1-wire search algorithm" at www.maxim-ic.com
+ *
+ * @dev The master device to search
+ * @cb Function to call when a device is found
+ */
+void w1_search(struct w1_master *dev, w1_slave_found_callback cb)
{
- u64 last, rn, tmp;
- int i, count = 0;
- int last_family_desc, last_zero, last_device;
- int search_bit, id_bit, comp_bit, desc_bit;
+ u64 last_rn, rn, tmp64;
+ int i, slave_count = 0;
+ int last_zero, last_device;
+ int search_bit, desc_bit;
+ u8 triplet_ret = 0;
- search_bit = id_bit = comp_bit = 0;
- rn = tmp = last = 0;
- last_device = last_zero = last_family_desc = 0;
+ search_bit = 0;
+ rn = last_rn = 0;
+ last_device = 0;
+ last_zero = -1;
desc_bit = 64;
- while (!(id_bit && comp_bit) && !last_device
- && count++ < dev->max_slave_count) {
- last = rn;
+ while ( !last_device && (slave_count++ < dev->max_slave_count) ) {
+ last_rn = rn;
rn = 0;
- last_family_desc = 0;
-
/*
* Reset bus and all 1-wire device state machines
* so they can respond to our requests.
@@ -563,94 +598,46 @@ void w1_search(struct w1_master *dev)
break;
}
-#if 1
+ /* Start the search */
w1_write_8(dev, W1_SEARCH);
for (i = 0; i < 64; ++i) {
- /*
- * Read 2 bits from bus.
- * All who don't sleep must send ID bit and COMPLEMENT ID bit.
- * They actually are ANDed between all senders.
- */
- id_bit = w1_touch_bit(dev, 1);
- comp_bit = w1_touch_bit(dev, 1);
-
- if (id_bit && comp_bit)
- break;
-
- if (id_bit == 0 && comp_bit == 0) {
- if (i == desc_bit)
- search_bit = 1;
- else if (i > desc_bit)
- search_bit = 0;
- else
- search_bit = ((last >> i) & 0x1);
-
- if (search_bit == 0) {
- last_zero = i;
- if (last_zero < 9)
- last_family_desc = last_zero;
- }
-
- }
+ /* Determine the direction/search bit */
+ if (i == desc_bit)
+ search_bit = 1; /* took the 0 path last time, so take the 1 path */
+ else if (i > desc_bit)
+ search_bit = 0; /* take the 0 path on the next branch */
else
- search_bit = id_bit;
+ search_bit = ((last_rn >> i) & 0x1);
- tmp = search_bit;
- rn |= (tmp << i);
+ /** Read two bits and write one bit */
+ triplet_ret = w1_triplet(dev, search_bit);
- /*
- * Write 1 bit to bus
- * and make all who don't have "search_bit" in "i"'th position
- * in it's registration number sleep.
- */
- if (dev->bus_master->touch_bit)
- w1_touch_bit(dev, search_bit);
- else
- w1_write_bit(dev, search_bit);
+ /* quit if no device responded */
+ if ( (triplet_ret & 0x03) == 0x03 )
+ break;
- }
-#endif
+ /* If both directions were valid, and we took the 0 path... */
+ if (triplet_ret == 0)
+ last_zero = i;
- if (desc_bit == last_zero)
- last_device = 1;
+ /* extract the direction taken & update the device number */
+ tmp64 = (triplet_ret >> 2);
+ rn |= (tmp64 << i);
+ }
- desc_bit = last_zero;
-
- w1_slave_found(dev->bus_master->data, rn);
+ if ( (triplet_ret & 0x03) != 0x03 ) {
+ if ( (desc_bit == last_zero) || (last_zero < 0))
+ last_device = 1;
+ desc_bit = last_zero;
+ cb(dev->bus_master->data, rn);
+ }
}
}
-int w1_create_master_attributes(struct w1_master *dev)
+static int w1_control(void *data)
{
- if ( device_create_file(&dev->dev, &w1_master_attribute_slaves) < 0 ||
- device_create_file(&dev->dev, &w1_master_attribute_slave_count) < 0 ||
- device_create_file(&dev->dev, &w1_master_attribute_attempts) < 0 ||
- device_create_file(&dev->dev, &w1_master_attribute_max_slave_count) < 0 ||
- device_create_file(&dev->dev, &w1_master_attribute_timeout) < 0||
- device_create_file(&dev->dev, &w1_master_attribute_pointer) < 0||
- device_create_file(&dev->dev, &w1_master_attribute_name) < 0)
- return -EINVAL;
-
- return 0;
-}
-
-void w1_destroy_master_attributes(struct w1_master *dev)
-{
- device_remove_file(&dev->dev, &w1_master_attribute_slaves);
- device_remove_file(&dev->dev, &w1_master_attribute_slave_count);
- device_remove_file(&dev->dev, &w1_master_attribute_attempts);
- device_remove_file(&dev->dev, &w1_master_attribute_max_slave_count);
- device_remove_file(&dev->dev, &w1_master_attribute_timeout);
- device_remove_file(&dev->dev, &w1_master_attribute_pointer);
- device_remove_file(&dev->dev, &w1_master_attribute_name);
-}
-
-
-int w1_control(void *data)
-{
- struct w1_slave *sl;
- struct w1_master *dev;
- struct list_head *ent, *ment, *n, *mn;
+ struct w1_slave *sl, *sln;
+ struct w1_master *dev, *n;
int err, have_to_wait = 0;
daemonize("w1_control");
@@ -659,16 +646,14 @@ int w1_control(void *data)
while (!control_needs_exit || have_to_wait) {
have_to_wait = 0;
- try_to_freeze(PF_FREEZE);
+ try_to_freeze();
msleep_interruptible(w1_timeout * 1000);
if (signal_pending(current))
flush_signals(current);
- list_for_each_safe(ment, mn, &w1_masters) {
- dev = list_entry(ment, struct w1_master, w1_master_entry);
-
- if (!control_needs_exit && !dev->need_exit)
+ list_for_each_entry_safe(dev, n, &w1_masters, w1_master_entry) {
+ if (!control_needs_exit && !dev->flags)
continue;
/*
* Little race: we can create thread but not set the flag.
@@ -679,12 +664,8 @@ int w1_control(void *data)
continue;
}
- spin_lock(&w1_mlock);
- list_del(&dev->w1_master_entry);
- spin_unlock(&w1_mlock);
-
if (control_needs_exit) {
- dev->need_exit = 1;
+ set_bit(W1_MASTER_NEED_EXIT, &dev->flags);
err = kill_proc(dev->kpid, SIGTERM, 1);
if (err)
@@ -693,24 +674,42 @@ int w1_control(void *data)
dev->kpid);
}
- wait_for_completion(&dev->dev_exited);
-
- list_for_each_safe(ent, n, &dev->slist) {
- sl = list_entry(ent, struct w1_slave, w1_slave_entry);
+ if (test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) {
+ wait_for_completion(&dev->dev_exited);
+ spin_lock_bh(&w1_mlock);
+ list_del(&dev->w1_master_entry);
+ spin_unlock_bh(&w1_mlock);
- if (!sl)
- dev_warn(&dev->dev,
- "%s: slave entry is NULL.\n",
- __func__);
- else {
+ list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
list_del(&sl->w1_slave_entry);
w1_slave_detach(sl);
kfree(sl);
}
+ w1_destroy_master_attributes(dev);
+ atomic_dec(&dev->refcnt);
+ continue;
+ }
+
+ if (test_bit(W1_MASTER_NEED_RECONNECT, &dev->flags)) {
+ dev_info(&dev->dev, "Reconnecting slaves in device %s.\n", dev->name);
+ down(&dev->mutex);
+ list_for_each_entry(sl, &dev->slist, w1_slave_entry) {
+ if (sl->family->fid == W1_FAMILY_DEFAULT) {
+ struct w1_reg_num rn;
+ list_del(&sl->w1_slave_entry);
+ w1_slave_detach(sl);
+
+ memcpy(&rn, &sl->reg_num, sizeof(rn));
+
+ kfree(sl);
+
+ w1_attach_slave_device(dev, &rn);
+ }
+ }
+ clear_bit(W1_MASTER_NEED_RECONNECT, &dev->flags);
+ up(&dev->mutex);
}
- w1_destroy_master_attributes(dev);
- atomic_dec(&dev->refcnt);
}
}
@@ -720,51 +719,50 @@ int w1_control(void *data)
int w1_process(void *data)
{
struct w1_master *dev = (struct w1_master *) data;
- struct list_head *ent, *n;
- struct w1_slave *sl;
+ struct w1_slave *sl, *sln;
daemonize("%s", dev->name);
allow_signal(SIGTERM);
- while (!dev->need_exit) {
- try_to_freeze(PF_FREEZE);
+ while (!test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) {
+ try_to_freeze();
msleep_interruptible(w1_timeout * 1000);
if (signal_pending(current))
flush_signals(current);
- if (dev->need_exit)
+ if (test_bit(W1_MASTER_NEED_EXIT, &dev->flags))
break;
if (!dev->initialized)
continue;
+ if (dev->search_count == 0)
+ continue;
+
if (down_interruptible(&dev->mutex))
continue;
- list_for_each_safe(ent, n, &dev->slist) {
- sl = list_entry(ent, struct w1_slave, w1_slave_entry);
+ list_for_each_entry(sl, &dev->slist, w1_slave_entry)
+ clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
- if (sl)
- clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
- }
-
w1_search_devices(dev, w1_slave_found);
- list_for_each_safe(ent, n, &dev->slist) {
- sl = list_entry(ent, struct w1_slave, w1_slave_entry);
-
- if (sl && !test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) {
+ list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
+ if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) {
list_del (&sl->w1_slave_entry);
w1_slave_detach (sl);
kfree (sl);
dev->slave_count--;
- }
- else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags))
+ } else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags))
sl->ttl = dev->slave_ttl;
}
+
+ if (dev->search_count > 0)
+ dev->search_count--;
+
up(&dev->mutex);
}
@@ -774,7 +772,7 @@ int w1_process(void *data)
return 0;
}
-int w1_init(void)
+static int w1_init(void)
{
int retval;
@@ -814,18 +812,14 @@ err_out_exit_init:
return retval;
}
-void w1_fini(void)
+static void w1_fini(void)
{
struct w1_master *dev;
- struct list_head *ent, *n;
- list_for_each_safe(ent, n, &w1_masters) {
- dev = list_entry(ent, struct w1_master, w1_master_entry);
+ list_for_each_entry(dev, &w1_masters, w1_master_entry)
__w1_remove_master_device(dev);
- }
control_needs_exit = 1;
-
wait_for_completion(&w1_control_complete);
driver_unregister(&w1_driver);
diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h
index abbddaf3f8e..4f0a986e33e 100644
--- a/drivers/w1/w1.h
+++ b/drivers/w1/w1.h
@@ -1,8 +1,8 @@
/*
- * w1.h
+ * w1.h
*
* Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- *
+ *
*
* 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
@@ -74,36 +74,86 @@ struct w1_slave
int ttl;
struct w1_master *master;
- struct w1_family *family;
- struct device dev;
- struct completion dev_released;
+ struct w1_family *family;
+ struct device dev;
+ struct completion dev_released;
- struct bin_attribute attr_bin;
- struct device_attribute attr_name, attr_val;
+ struct bin_attribute attr_bin;
+ struct device_attribute attr_name;
};
typedef void (* w1_slave_found_callback)(unsigned long, u64);
+
+/**
+ * Note: read_bit and write_bit are very low level functions and should only
+ * be used with hardware that doesn't really support 1-wire operations,
+ * like a parallel/serial port.
+ * Either define read_bit and write_bit OR define, at minimum, touch_bit and
+ * reset_bus.
+ */
struct w1_bus_master
{
- unsigned long data;
-
- u8 (*read_bit)(unsigned long);
- void (*write_bit)(unsigned long, u8);
-
- u8 (*read_byte)(unsigned long);
- void (*write_byte)(unsigned long, u8);
-
- u8 (*read_block)(unsigned long, u8 *, int);
- void (*write_block)(unsigned long, u8 *, int);
-
- u8 (*touch_bit)(unsigned long, u8);
-
- u8 (*reset_bus)(unsigned long);
-
- void (*search)(unsigned long, w1_slave_found_callback);
+ /** the first parameter in all the functions below */
+ unsigned long data;
+
+ /**
+ * Sample the line level
+ * @return the level read (0 or 1)
+ */
+ u8 (*read_bit)(unsigned long);
+
+ /** Sets the line level */
+ void (*write_bit)(unsigned long, u8);
+
+ /**
+ * touch_bit is the lowest-level function for devices that really
+ * support the 1-wire protocol.
+ * touch_bit(0) = write-0 cycle
+ * touch_bit(1) = write-1 / read cycle
+ * @return the bit read (0 or 1)
+ */
+ u8 (*touch_bit)(unsigned long, u8);
+
+ /**
+ * Reads a bytes. Same as 8 touch_bit(1) calls.
+ * @return the byte read
+ */
+ u8 (*read_byte)(unsigned long);
+
+ /**
+ * Writes a byte. Same as 8 touch_bit(x) calls.
+ */
+ void (*write_byte)(unsigned long, u8);
+
+ /**
+ * Same as a series of read_byte() calls
+ * @return the number of bytes read
+ */
+ u8 (*read_block)(unsigned long, u8 *, int);
+
+ /** Same as a series of write_byte() calls */
+ void (*write_block)(unsigned long, const u8 *, int);
+
+ /**
+ * Combines two reads and a smart write for ROM searches
+ * @return bit0=Id bit1=comp_id bit2=dir_taken
+ */
+ u8 (*triplet)(unsigned long, u8);
+
+ /**
+ * long write-0 with a read for the presence pulse detection
+ * @return -1=Error, 0=Device present, 1=No device present
+ */
+ u8 (*reset_bus)(unsigned long);
+
+ /** Really nice hardware can handles the ROM searches */
+ void (*search)(unsigned long, w1_slave_found_callback);
};
+#define W1_MASTER_NEED_EXIT 0
+#define W1_MASTER_NEED_RECONNECT 1
+
struct w1_master
{
struct list_head w1_master_entry;
@@ -115,30 +165,31 @@ struct w1_master
int slave_ttl;
int initialized;
u32 id;
+ int search_count;
atomic_t refcnt;
void *priv;
int priv_size;
- int need_exit;
+ long flags;
+
pid_t kpid;
- struct semaphore mutex;
+ struct semaphore mutex;
struct device_driver *driver;
- struct device dev;
- struct completion dev_released;
- struct completion dev_exited;
+ struct device dev;
+ struct completion dev_released;
+ struct completion dev_exited;
struct w1_bus_master *bus_master;
u32 seq, groups;
- struct sock *nls;
+ struct sock *nls;
};
int w1_create_master_attributes(struct w1_master *);
-void w1_destroy_master_attributes(struct w1_master *);
-void w1_search(struct w1_master *dev);
+void w1_search(struct w1_master *dev, w1_slave_found_callback cb);
#endif /* __KERNEL__ */
diff --git a/drivers/w1/w1_family.c b/drivers/w1/w1_family.c
index d1d56eca106..02eee57d3c0 100644
--- a/drivers/w1/w1_family.c
+++ b/drivers/w1/w1_family.c
@@ -1,8 +1,8 @@
/*
- * w1_family.c
+ * w1_family.c
*
* Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- *
+ *
*
* 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
@@ -27,10 +27,11 @@
DEFINE_SPINLOCK(w1_flock);
static LIST_HEAD(w1_families);
+extern void w1_reconnect_slaves(struct w1_family *f);
static int w1_check_family(struct w1_family *f)
{
- if (!f->fops->rname || !f->fops->rbin || !f->fops->rval || !f->fops->rvalname)
+ if (!f->fops->rname || !f->fops->rbin)
return -EINVAL;
return 0;
@@ -60,9 +61,10 @@ int w1_register_family(struct w1_family *newf)
newf->need_exit = 0;
list_add_tail(&newf->family_entry, &w1_families);
}
-
spin_unlock(&w1_flock);
+ w1_reconnect_slaves(newf);
+
return ret;
}
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h
index 03a2de7a601..b26da01bbc3 100644
--- a/drivers/w1/w1_family.h
+++ b/drivers/w1/w1_family.h
@@ -1,8 +1,8 @@
/*
- * w1_family.h
+ * w1_family.h
*
* Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- *
+ *
*
* 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
@@ -27,27 +27,27 @@
#include <asm/atomic.h>
#define W1_FAMILY_DEFAULT 0
-#define W1_FAMILY_THERM 0x10
-#define W1_FAMILY_SMEM 0x01
+#define W1_FAMILY_SMEM_01 0x01
+#define W1_FAMILY_SMEM_81 0x81
+#define W1_THERM_DS18S20 0x10
+#define W1_THERM_DS1822 0x22
+#define W1_THERM_DS18B20 0x28
#define MAXNAMELEN 32
struct w1_family_ops
{
- ssize_t (* rname)(struct device *, char *);
+ ssize_t (* rname)(struct device *, struct device_attribute *, char *);
ssize_t (* rbin)(struct kobject *, char *, loff_t, size_t);
-
- ssize_t (* rval)(struct device *, char *);
- unsigned char rvalname[MAXNAMELEN];
};
struct w1_family
{
struct list_head family_entry;
u8 fid;
-
+
struct w1_family_ops *fops;
-
+
atomic_t refcnt;
u8 need_exit;
};
diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c
index 5f0bafbbd57..35e85d96170 100644
--- a/drivers/w1/w1_int.c
+++ b/drivers/w1/w1_int.c
@@ -1,8 +1,8 @@
/*
- * w1_int.c
+ * w1_int.c
*
* Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- *
+ *
*
* 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
@@ -39,8 +39,9 @@ extern spinlock_t w1_mlock;
extern int w1_process(void *);
-struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
- struct device_driver *driver, struct device *device)
+static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
+ struct device_driver *driver,
+ struct device *device)
{
struct w1_master *dev;
int err;
@@ -60,14 +61,15 @@ struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
dev->bus_master = (struct w1_bus_master *)(dev + 1);
- dev->owner = THIS_MODULE;
- dev->max_slave_count = slave_count;
- dev->slave_count = 0;
- dev->attempts = 0;
- dev->kpid = -1;
- dev->initialized = 0;
- dev->id = id;
+ dev->owner = THIS_MODULE;
+ dev->max_slave_count = slave_count;
+ dev->slave_count = 0;
+ dev->attempts = 0;
+ dev->kpid = -1;
+ dev->initialized = 0;
+ dev->id = id;
dev->slave_ttl = slave_ttl;
+ dev->search_count = -1; /* continual scan */
atomic_set(&dev->refcnt, 2);
@@ -105,7 +107,7 @@ struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
return dev;
}
-void w1_free_dev(struct w1_master *dev)
+static void w1_free_dev(struct w1_master *dev)
{
device_unregister(&dev->dev);
if (dev->nls && dev->nls->sk_socket)
@@ -120,6 +122,13 @@ int w1_add_master_device(struct w1_bus_master *master)
int retval = 0;
struct w1_netlink_msg msg;
+ /* validate minimum functionality */
+ if (!(master->touch_bit && master->reset_bus) &&
+ !(master->write_bit && master->read_bit)) {
+ printk(KERN_ERR "w1_add_master_device: invalid function set\n");
+ return(-EINVAL);
+ }
+
dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, w1_max_slave_ttl, &w1_driver, &w1_device);
if (!dev)
return -ENOMEM;
@@ -153,7 +162,7 @@ int w1_add_master_device(struct w1_bus_master *master)
return 0;
err_out_kill_thread:
- dev->need_exit = 1;
+ set_bit(W1_MASTER_NEED_EXIT, &dev->flags);
if (kill_proc(dev->kpid, SIGTERM, 1))
dev_err(&dev->dev,
"Failed to send signal to w1 kernel thread %d.\n",
@@ -171,7 +180,7 @@ void __w1_remove_master_device(struct w1_master *dev)
int err;
struct w1_netlink_msg msg;
- dev->need_exit = 1;
+ set_bit(W1_MASTER_NEED_EXIT, &dev->flags);
err = kill_proc(dev->kpid, SIGTERM, 1);
if (err)
dev_err(&dev->dev,
@@ -197,10 +206,8 @@ void __w1_remove_master_device(struct w1_master *dev)
void w1_remove_master_device(struct w1_bus_master *bm)
{
struct w1_master *dev = NULL;
- struct list_head *ent, *n;
- list_for_each_safe(ent, n, &w1_masters) {
- dev = list_entry(ent, struct w1_master, w1_master_entry);
+ list_for_each_entry(dev, &w1_masters, w1_master_entry) {
if (!dev->initialized)
continue;
diff --git a/drivers/w1/w1_int.h b/drivers/w1/w1_int.h
index fdb531e87fa..4274082d226 100644
--- a/drivers/w1/w1_int.h
+++ b/drivers/w1/w1_int.h
@@ -1,8 +1,8 @@
/*
- * w1_int.h
+ * w1_int.h
*
* Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- *
+ *
*
* 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
@@ -27,8 +27,6 @@
#include "w1.h"
-struct w1_master * w1_alloc_dev(u32, int, int, struct device_driver *, struct device *);
-void w1_free_dev(struct w1_master *dev);
int w1_add_master_device(struct w1_bus_master *);
void w1_remove_master_device(struct w1_bus_master *);
void __w1_remove_master_device(struct w1_master *);
diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c
index 02796b5a39f..00f03222017 100644
--- a/drivers/w1/w1_io.c
+++ b/drivers/w1/w1_io.c
@@ -1,8 +1,8 @@
/*
- * w1_io.c
+ * w1_io.c
*
* Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- *
+ *
*
* 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
@@ -55,15 +55,29 @@ void w1_delay(unsigned long tm)
udelay(tm * w1_delay_parm);
}
+static void w1_write_bit(struct w1_master *dev, int bit);
+static u8 w1_read_bit(struct w1_master *dev);
+
+/**
+ * Generates a write-0 or write-1 cycle and samples the level.
+ */
u8 w1_touch_bit(struct w1_master *dev, int bit)
{
if (dev->bus_master->touch_bit)
return dev->bus_master->touch_bit(dev->bus_master->data, bit);
- else
+ else if (bit)
return w1_read_bit(dev);
+ else {
+ w1_write_bit(dev, 0);
+ return(0);
+ }
}
-void w1_write_bit(struct w1_master *dev, int bit)
+/**
+ * Generates a write-0 or write-1 cycle.
+ * Only call if dev->bus_master->touch_bit is NULL
+ */
+static void w1_write_bit(struct w1_master *dev, int bit)
{
if (bit) {
dev->bus_master->write_bit(dev->bus_master->data, 0);
@@ -78,6 +92,12 @@ void w1_write_bit(struct w1_master *dev, int bit)
}
}
+/**
+ * Writes 8 bits.
+ *
+ * @param dev the master device
+ * @param byte the byte to write
+ */
void w1_write_8(struct w1_master *dev, u8 byte)
{
int i;
@@ -86,10 +106,15 @@ void w1_write_8(struct w1_master *dev, u8 byte)
dev->bus_master->write_byte(dev->bus_master->data, byte);
else
for (i = 0; i < 8; ++i)
- w1_write_bit(dev, (byte >> i) & 0x1);
+ w1_touch_bit(dev, (byte >> i) & 0x1);
}
-u8 w1_read_bit(struct w1_master *dev)
+
+/**
+ * Generates a write-1 cycle and samples the level.
+ * Only call if dev->bus_master->touch_bit is NULL
+ */
+static u8 w1_read_bit(struct w1_master *dev)
{
int result;
@@ -104,6 +129,53 @@ u8 w1_read_bit(struct w1_master *dev)
return result & 0x1;
}
+/**
+ * Does a triplet - used for searching ROM addresses.
+ * Return bits:
+ * bit 0 = id_bit
+ * bit 1 = comp_bit
+ * bit 2 = dir_taken
+ * If both bits 0 & 1 are set, the search should be restarted.
+ *
+ * @param dev the master device
+ * @param bdir the bit to write if both id_bit and comp_bit are 0
+ * @return bit fields - see above
+ */
+u8 w1_triplet(struct w1_master *dev, int bdir)
+{
+ if ( dev->bus_master->triplet )
+ return(dev->bus_master->triplet(dev->bus_master->data, bdir));
+ else {
+ u8 id_bit = w1_touch_bit(dev, 1);
+ u8 comp_bit = w1_touch_bit(dev, 1);
+ u8 retval;
+
+ if ( id_bit && comp_bit )
+ return(0x03); /* error */
+
+ if ( !id_bit && !comp_bit ) {
+ /* Both bits are valid, take the direction given */
+ retval = bdir ? 0x04 : 0;
+ } else {
+ /* Only one bit is valid, take that direction */
+ bdir = id_bit;
+ retval = id_bit ? 0x05 : 0x02;
+ }
+
+ if ( dev->bus_master->touch_bit )
+ w1_touch_bit(dev, bdir);
+ else
+ w1_write_bit(dev, bdir);
+ return(retval);
+ }
+}
+
+/**
+ * Reads 8 bits.
+ *
+ * @param dev the master device
+ * @return the byte read
+ */
u8 w1_read_8(struct w1_master * dev)
{
int i;
@@ -113,12 +185,20 @@ u8 w1_read_8(struct w1_master * dev)
res = dev->bus_master->read_byte(dev->bus_master->data);
else
for (i = 0; i < 8; ++i)
- res |= (w1_read_bit(dev) << i);
+ res |= (w1_touch_bit(dev,1) << i);
return res;
}
-void w1_write_block(struct w1_master *dev, u8 *buf, int len)
+/**
+ * Writes a series of bytes.
+ *
+ * @param dev the master device
+ * @param buf pointer to the data to write
+ * @param len the number of bytes to write
+ * @return the byte read
+ */
+void w1_write_block(struct w1_master *dev, const u8 *buf, int len)
{
int i;
@@ -129,6 +209,14 @@ void w1_write_block(struct w1_master *dev, u8 *buf, int len)
w1_write_8(dev, buf[i]);
}
+/**
+ * Reads a series of bytes.
+ *
+ * @param dev the master device
+ * @param buf pointer to the buffer to fill
+ * @param len the number of bytes to read
+ * @return the number of bytes read
+ */
u8 w1_read_block(struct w1_master *dev, u8 *buf, int len)
{
int i;
@@ -145,9 +233,15 @@ u8 w1_read_block(struct w1_master *dev, u8 *buf, int len)
return ret;
}
+/**
+ * Issues a reset bus sequence.
+ *
+ * @param dev The bus master pointer
+ * @return 0=Device present, 1=No device present or error
+ */
int w1_reset_bus(struct w1_master *dev)
{
- int result = 0;
+ int result;
if (dev->bus_master->reset_bus)
result = dev->bus_master->reset_bus(dev->bus_master->data) & 0x1;
@@ -180,12 +274,11 @@ void w1_search_devices(struct w1_master *dev, w1_slave_found_callback cb)
if (dev->bus_master->search)
dev->bus_master->search(dev->bus_master->data, cb);
else
- w1_search(dev);
+ w1_search(dev, cb);
}
-EXPORT_SYMBOL(w1_write_bit);
+EXPORT_SYMBOL(w1_touch_bit);
EXPORT_SYMBOL(w1_write_8);
-EXPORT_SYMBOL(w1_read_bit);
EXPORT_SYMBOL(w1_read_8);
EXPORT_SYMBOL(w1_reset_bus);
EXPORT_SYMBOL(w1_calc_crc8);
diff --git a/drivers/w1/w1_io.h b/drivers/w1/w1_io.h
index 6c573005a71..af5829778aa 100644
--- a/drivers/w1/w1_io.h
+++ b/drivers/w1/w1_io.h
@@ -1,8 +1,8 @@
/*
- * w1_io.h
+ * w1_io.h
*
* Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- *
+ *
*
* 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
@@ -26,13 +26,12 @@
void w1_delay(unsigned long);
u8 w1_touch_bit(struct w1_master *, int);
-void w1_write_bit(struct w1_master *, int);
+u8 w1_triplet(struct w1_master *dev, int bdir);
void w1_write_8(struct w1_master *, u8);
-u8 w1_read_bit(struct w1_master *);
u8 w1_read_8(struct w1_master *);
int w1_reset_bus(struct w1_master *);
u8 w1_calc_crc8(u8 *, int);
-void w1_write_block(struct w1_master *, u8 *, int);
+void w1_write_block(struct w1_master *, const u8 *, int);
u8 w1_read_block(struct w1_master *, u8 *, int);
void w1_search_devices(struct w1_master *dev, w1_slave_found_callback cb);
diff --git a/drivers/w1/w1_log.h b/drivers/w1/w1_log.h
index a6bf6f44dce..fe6bdf43380 100644
--- a/drivers/w1/w1_log.h
+++ b/drivers/w1/w1_log.h
@@ -1,8 +1,8 @@
/*
- * w1_log.h
+ * w1_log.h
*
* Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- *
+ *
*
* 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
diff --git a/drivers/w1/w1_netlink.h b/drivers/w1/w1_netlink.h
index ea1b530abad..8615756946d 100644
--- a/drivers/w1/w1_netlink.h
+++ b/drivers/w1/w1_netlink.h
@@ -33,13 +33,13 @@ enum w1_netlink_message_types {
W1_MASTER_REMOVE,
};
-struct w1_netlink_msg
+struct w1_netlink_msg
{
__u8 type;
__u8 reserved[3];
union
{
- struct w1_reg_num id;
+ struct w1_reg_num id;
__u64 w1_id;
struct
{
diff --git a/drivers/w1/w1_smem.c b/drivers/w1/w1_smem.c
index a54e425217a..70d2d469963 100644
--- a/drivers/w1/w1_smem.c
+++ b/drivers/w1/w1_smem.c
@@ -1,8 +1,8 @@
/*
- * w1_smem.c
+ * w1_smem.c
*
* Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- *
+ *
*
* This program is free software; you can redistribute it and/or modify
* it under the smems of the GNU General Public License as published by
@@ -36,41 +36,25 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, 64bit memory family.");
-static ssize_t w1_smem_read_name(struct device *, char *);
-static ssize_t w1_smem_read_val(struct device *, char *);
+static ssize_t w1_smem_read_name(struct device *, struct device_attribute *attr, char *);
static ssize_t w1_smem_read_bin(struct kobject *, char *, loff_t, size_t);
static struct w1_family_ops w1_smem_fops = {
.rname = &w1_smem_read_name,
.rbin = &w1_smem_read_bin,
- .rval = &w1_smem_read_val,
- .rvalname = "id",
};
-static ssize_t w1_smem_read_name(struct device *dev, char *buf)
+static ssize_t w1_smem_read_name(struct device *dev, struct device_attribute *attr, char *buf)
{
struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
return sprintf(buf, "%s\n", sl->name);
}
-static ssize_t w1_smem_read_val(struct device *dev, char *buf)
-{
- struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
- int i;
- ssize_t count = 0;
-
- for (i = 0; i < 8; ++i)
- count += sprintf(buf + count, "%02x ", ((u8 *)&sl->reg_num)[i]);
- count += sprintf(buf + count, "\n");
-
- return count;
-}
-
static ssize_t w1_smem_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
struct w1_slave *sl = container_of(container_of(kobj, struct device, kobj),
- struct w1_slave, dev);
+ struct w1_slave, dev);
int i;
atomic_inc(&sl->refcnt);
@@ -90,7 +74,7 @@ static ssize_t w1_smem_read_bin(struct kobject *kobj, char *buf, loff_t off, siz
for (i = 0; i < 8; ++i)
count += sprintf(buf + count, "%02x ", ((u8 *)&sl->reg_num)[i]);
count += sprintf(buf + count, "\n");
-
+
out:
up(&sl->master->mutex);
out_dec:
@@ -99,19 +83,37 @@ out_dec:
return count;
}
-static struct w1_family w1_smem_family = {
- .fid = W1_FAMILY_SMEM,
+static struct w1_family w1_smem_family_01 = {
+ .fid = W1_FAMILY_SMEM_01,
+ .fops = &w1_smem_fops,
+};
+
+static struct w1_family w1_smem_family_81 = {
+ .fid = W1_FAMILY_SMEM_81,
.fops = &w1_smem_fops,
};
static int __init w1_smem_init(void)
{
- return w1_register_family(&w1_smem_family);
+ int err;
+
+ err = w1_register_family(&w1_smem_family_01);
+ if (err)
+ return err;
+
+ err = w1_register_family(&w1_smem_family_81);
+ if (err) {
+ w1_unregister_family(&w1_smem_family_01);
+ return err;
+ }
+
+ return 0;
}
static void __exit w1_smem_fini(void)
{
- w1_unregister_family(&w1_smem_family);
+ w1_unregister_family(&w1_smem_family_01);
+ w1_unregister_family(&w1_smem_family_81);
}
module_init(w1_smem_init);
diff --git a/drivers/w1/w1_therm.c b/drivers/w1/w1_therm.c
index 0b181789050..165526c9360 100644
--- a/drivers/w1/w1_therm.c
+++ b/drivers/w1/w1_therm.c
@@ -1,8 +1,8 @@
/*
- * w1_therm.c
+ * w1_therm.c
*
* Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
- *
+ *
*
* This program is free software; you can redistribute it and/or modify
* it under the therms of the GNU General Public License as published by
@@ -38,31 +38,78 @@ MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, temperature family.");
static u8 bad_roms[][9] = {
- {0xaa, 0x00, 0x4b, 0x46, 0xff, 0xff, 0x0c, 0x10, 0x87},
+ {0xaa, 0x00, 0x4b, 0x46, 0xff, 0xff, 0x0c, 0x10, 0x87},
{}
};
-static ssize_t w1_therm_read_name(struct device *, char *);
-static ssize_t w1_therm_read_temp(struct device *, char *);
+static ssize_t w1_therm_read_name(struct device *, struct device_attribute *attr, char *);
static ssize_t w1_therm_read_bin(struct kobject *, char *, loff_t, size_t);
static struct w1_family_ops w1_therm_fops = {
.rname = &w1_therm_read_name,
.rbin = &w1_therm_read_bin,
- .rval = &w1_therm_read_temp,
- .rvalname = "temp1_input",
};
-static ssize_t w1_therm_read_name(struct device *dev, char *buf)
+static struct w1_family w1_therm_family_DS18S20 = {
+ .fid = W1_THERM_DS18S20,
+ .fops = &w1_therm_fops,
+};
+
+static struct w1_family w1_therm_family_DS18B20 = {
+ .fid = W1_THERM_DS18B20,
+ .fops = &w1_therm_fops,
+};
+static struct w1_family w1_therm_family_DS1822 = {
+ .fid = W1_THERM_DS1822,
+ .fops = &w1_therm_fops,
+};
+
+struct w1_therm_family_converter
+{
+ u8 broken;
+ u16 reserved;
+ struct w1_family *f;
+ int (*convert)(u8 rom[9]);
+};
+
+static inline int w1_DS18B20_convert_temp(u8 rom[9]);
+static inline int w1_DS18S20_convert_temp(u8 rom[9]);
+
+static struct w1_therm_family_converter w1_therm_families[] = {
+ {
+ .f = &w1_therm_family_DS18S20,
+ .convert = w1_DS18S20_convert_temp
+ },
+ {
+ .f = &w1_therm_family_DS1822,
+ .convert = w1_DS18B20_convert_temp
+ },
+ {
+ .f = &w1_therm_family_DS18B20,
+ .convert = w1_DS18B20_convert_temp
+ },
+};
+
+static ssize_t w1_therm_read_name(struct device *dev, struct device_attribute *attr, char *buf)
{
struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
return sprintf(buf, "%s\n", sl->name);
}
-static inline int w1_convert_temp(u8 rom[9])
+static inline int w1_DS18B20_convert_temp(u8 rom[9])
+{
+ int t = (rom[1] << 8) | rom[0];
+ t /= 16;
+ return t;
+}
+
+static inline int w1_DS18S20_convert_temp(u8 rom[9])
{
int t, h;
+
+ if (!rom[7])
+ return 0;
if (rom[1] == 0)
t = ((s32)rom[0] >> 1)*1000;
@@ -77,11 +124,15 @@ static inline int w1_convert_temp(u8 rom[9])
return t;
}
-static ssize_t w1_therm_read_temp(struct device *dev, char *buf)
+static inline int w1_convert_temp(u8 rom[9], u8 fid)
{
- struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
+ int i;
+
+ for (i=0; i<sizeof(w1_therm_families)/sizeof(w1_therm_families[0]); ++i)
+ if (w1_therm_families[i].f->fid == fid)
+ return w1_therm_families[i].convert(rom);
- return sprintf(buf, "%d\n", w1_convert_temp(sl->rom));
+ return 0;
}
static int w1_therm_check_rom(u8 rom[9])
@@ -98,7 +149,7 @@ static int w1_therm_check_rom(u8 rom[9])
static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
struct w1_slave *sl = container_of(container_of(kobj, struct device, kobj),
- struct w1_slave, dev);
+ struct w1_slave, dev);
struct w1_master *dev = sl->master;
u8 rom[9], crc, verdict;
int i, max_trying = 10;
@@ -133,7 +184,7 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
unsigned int tm = 750;
memcpy(&match[1], (u64 *) & sl->reg_num, 8);
-
+
w1_write_block(dev, match, 9);
w1_write_8(dev, W1_CONVERT_TEMP);
@@ -146,7 +197,7 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
if (!w1_reset_bus (dev)) {
w1_write_block(dev, match, 9);
-
+
w1_write_8(dev, W1_READ_SCRATCHPAD);
if ((count = w1_read_block(dev, rom, 9)) != 9) {
dev_warn(&dev->dev, "w1_read_block() returned %d instead of 9.\n", count);
@@ -176,7 +227,7 @@ static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, si
for (i = 0; i < 9; ++i)
count += sprintf(buf + count, "%02x ", sl->rom[i]);
- count += sprintf(buf + count, "t=%d\n", w1_convert_temp(rom));
+ count += sprintf(buf + count, "t=%d\n", w1_convert_temp(rom, sl->family->fid));
out:
up(&dev->mutex);
out_dec:
@@ -186,19 +237,26 @@ out_dec:
return count;
}
-static struct w1_family w1_therm_family = {
- .fid = W1_FAMILY_THERM,
- .fops = &w1_therm_fops,
-};
-
static int __init w1_therm_init(void)
{
- return w1_register_family(&w1_therm_family);
+ int err, i;
+
+ for (i=0; i<sizeof(w1_therm_families)/sizeof(w1_therm_families[0]); ++i) {
+ err = w1_register_family(w1_therm_families[i].f);
+ if (err)
+ w1_therm_families[i].broken = 1;
+ }
+
+ return 0;
}
static void __exit w1_therm_fini(void)
{
- w1_unregister_family(&w1_therm_family);
+ int i;
+
+ for (i=0; i<sizeof(w1_therm_families)/sizeof(w1_therm_families[0]); ++i)
+ if (!w1_therm_families[i].broken)
+ w1_unregister_family(w1_therm_families[i].f);
}
module_init(w1_therm_init);
diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c
index dad03fc33a4..04ca8840acf 100644
--- a/drivers/zorro/zorro-sysfs.c
+++ b/drivers/zorro/zorro-sysfs.c
@@ -21,7 +21,7 @@
/* show configuration fields */
#define zorro_config_attr(name, field, format_string) \
static ssize_t \
-show_##name(struct device *dev, char *buf) \
+show_##name(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct zorro_dev *z; \
\
@@ -36,7 +36,7 @@ zorro_config_attr(serial, rom.er_SerialNumber, "0x%08x\n");
zorro_config_attr(slotaddr, slotaddr, "0x%04x\n");
zorro_config_attr(slotsize, slotsize, "0x%04x\n");
-static ssize_t zorro_show_resource(struct device *dev, char *buf)
+static ssize_t zorro_show_resource(struct device *dev, struct device_attribute *attr, char *buf)
{
struct zorro_dev *z = to_zorro_dev(dev);
diff --git a/fs/Kconfig b/fs/Kconfig
index 6a4ad4bb7a5..06217795623 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -50,6 +50,23 @@ config EXT2_FS_SECURITY
If you are not using a security module that requires using
extended attributes for file security labels, say N.
+config EXT2_FS_XIP
+ bool "Ext2 execute in place support"
+ depends on EXT2_FS
+ help
+ Execute in place can be used on memory-backed block devices. If you
+ enable this option, you can select to mount block devices which are
+ capable of this feature without using the page cache.
+
+ If you do not use a block device that is capable of using this,
+ or if unsure, say N.
+
+config FS_XIP
+# execute in place
+ bool
+ depends on EXT2_FS_XIP
+ default y
+
config EXT3_FS
tristate "Ext3 journalling file system support"
help
@@ -717,6 +734,12 @@ config PROC_KCORE
bool "/proc/kcore support" if !ARM
depends on PROC_FS && MMU
+config PROC_VMCORE
+ bool "/proc/vmcore support (EXPERIMENTAL)"
+ depends on PROC_FS && EMBEDDED && EXPERIMENTAL && CRASH_DUMP
+ help
+ Exports the dump image of crashed kernel in ELF format.
+
config SYSFS
bool "sysfs file system support" if EMBEDDED
default y
@@ -741,56 +764,6 @@ config SYSFS
Designers of embedded systems may wish to say N here to conserve space.
-config DEVFS_FS
- bool "/dev file system support (OBSOLETE)"
- depends on EXPERIMENTAL
- help
- This is support for devfs, a virtual file system (like /proc) which
- provides the file system interface to device drivers, normally found
- in /dev. Devfs does not depend on major and minor number
- allocations. Device drivers register entries in /dev which then
- appear automatically, which means that the system administrator does
- not have to create character and block special device files in the
- /dev directory using the mknod command (or MAKEDEV script) anymore.
-
- This is work in progress. If you want to use this, you *must* read
- the material in <file:Documentation/filesystems/devfs/>, especially
- the file README there.
-
- Note that devfs no longer manages /dev/pts! If you are using UNIX98
- ptys, you will also need to mount the /dev/pts filesystem (devpts).
-
- Note that devfs has been obsoleted by udev,
- <http://www.kernel.org/pub/linux/utils/kernel/hotplug/>.
- It has been stripped down to a bare minimum and is only provided for
- legacy installations that use its naming scheme which is
- unfortunately different from the names normal Linux installations
- use.
-
- If unsure, say N.
-
-config DEVFS_MOUNT
- bool "Automatically mount at boot"
- depends on DEVFS_FS
- help
- This option appears if you have CONFIG_DEVFS_FS enabled. Setting
- this to 'Y' will make the kernel automatically mount devfs onto /dev
- when the system is booted, before the init thread is started.
- You can override this with the "devfs=nomount" boot option.
-
- If unsure, say N.
-
-config DEVFS_DEBUG
- bool "Debug devfs"
- depends on DEVFS_FS
- help
- If you say Y here, then the /dev file system code will generate
- debugging messages. See the file
- <file:Documentation/filesystems/devfs/boot-options> for more
- details.
-
- If unsure, say N.
-
config DEVPTS_FS_XATTR
bool "/dev/pts Extended Attributes"
depends on UNIX98_PTYS
@@ -1318,6 +1291,7 @@ config NFS_FS
depends on INET
select LOCKD
select SUNRPC
+ select NFS_ACL_SUPPORT if NFS_V3_ACL
help
If you are connected to some other (usually local) Unix computer
(using SLIP, PLIP, PPP or Ethernet) and want to mount files residing
@@ -1360,6 +1334,16 @@ config NFS_V3
If unsure, say Y.
+config NFS_V3_ACL
+ bool "Provide client support for the NFSv3 ACL protocol extension"
+ depends on NFS_V3
+ help
+ Implement the NFSv3 ACL protocol extension for manipulating POSIX
+ Access Control Lists. The server should also be compiled with
+ the NFSv3 ACL protocol extension; see the CONFIG_NFSD_V3_ACL option.
+
+ If unsure, say N.
+
config NFS_V4
bool "Provide NFSv4 client support (EXPERIMENTAL)"
depends on NFS_FS && EXPERIMENTAL
@@ -1403,6 +1387,7 @@ config NFSD
select LOCKD
select SUNRPC
select EXPORTFS
+ select NFS_ACL_SUPPORT if NFSD_V3_ACL || NFSD_V2_ACL
help
If you want your Linux box to act as an NFS *server*, so that other
computers on your local network which support NFS can access certain
@@ -1426,6 +1411,10 @@ config NFSD
To compile the NFS server support as a module, choose M here: the
module will be called nfsd. If unsure, say N.
+config NFSD_V2_ACL
+ bool
+ depends on NFSD
+
config NFSD_V3
bool "Provide NFSv3 server support"
depends on NFSD
@@ -1433,10 +1422,22 @@ config NFSD_V3
If you would like to include the NFSv3 server as well as the NFSv2
server, say Y here. If unsure, say Y.
+config NFSD_V3_ACL
+ bool "Provide server support for the NFSv3 ACL protocol extension"
+ depends on NFSD_V3
+ select NFSD_V2_ACL
+ help
+ Implement the NFSv3 ACL protocol extension for manipulating POSIX
+ Access Control Lists on exported file systems. NFS clients should
+ be compiled with the NFSv3 ACL protocol extension; see the
+ CONFIG_NFS_V3_ACL option. If unsure, say N.
+
config NFSD_V4
bool "Provide NFSv4 server support (EXPERIMENTAL)"
depends on NFSD_V3 && EXPERIMENTAL
select NFSD_TCP
+ select CRYPTO_MD5
+ select CRYPTO
help
If you would like to include the NFSv4 server as well as the NFSv2
and NFSv3 servers, say Y here. This feature is experimental, and
@@ -1477,6 +1478,15 @@ config LOCKD_V4
config EXPORTFS
tristate
+config NFS_ACL_SUPPORT
+ tristate
+ select FS_POSIX_ACL
+
+config NFS_COMMON
+ bool
+ depends on NFSD || NFS_FS
+ default y
+
config SUNRPC
tristate
diff --git a/fs/Makefile b/fs/Makefile
index 443f2bc56cc..fc92e59e9fa 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_BINFMT_FLAT) += binfmt_flat.o
obj-$(CONFIG_FS_MBCACHE) += mbcache.o
obj-$(CONFIG_FS_POSIX_ACL) += posix_acl.o xattr_acl.o
+obj-$(CONFIG_NFS_COMMON) += nfs_common/
obj-$(CONFIG_QUOTA) += dquot.o
obj-$(CONFIG_QFMT_V1) += quota_v1.o
diff --git a/fs/afs/kafsasyncd.c b/fs/afs/kafsasyncd.c
index 6fc88ae8ad9..7ac07d0d47b 100644
--- a/fs/afs/kafsasyncd.c
+++ b/fs/afs/kafsasyncd.c
@@ -116,7 +116,7 @@ static int kafsasyncd(void *arg)
remove_wait_queue(&kafsasyncd_sleepq, &myself);
set_current_state(TASK_RUNNING);
- try_to_freeze(PF_FREEZE);
+ try_to_freeze();
/* discard pending signals */
afs_discard_my_signals();
diff --git a/fs/afs/kafstimod.c b/fs/afs/kafstimod.c
index 86e710dd057..65bc05ab818 100644
--- a/fs/afs/kafstimod.c
+++ b/fs/afs/kafstimod.c
@@ -91,7 +91,7 @@ static int kafstimod(void *arg)
complete_and_exit(&kafstimod_dead, 0);
}
- try_to_freeze(PF_FREEZE);
+ try_to_freeze();
/* discard pending signals */
afs_discard_my_signals();
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index c7b2b889018..9c09641ce90 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -185,6 +185,19 @@ int autofs4_wait(struct autofs_sb_info *,struct dentry *, enum autofs_notify);
int autofs4_wait_release(struct autofs_sb_info *,autofs_wqt_t,int);
void autofs4_catatonic_mode(struct autofs_sb_info *);
+static inline int autofs4_follow_mount(struct vfsmount **mnt, struct dentry **dentry)
+{
+ int res = 0;
+
+ while (d_mountpoint(*dentry)) {
+ int followed = follow_down(mnt, dentry);
+ if (!followed)
+ break;
+ res = 1;
+ }
+ return res;
+}
+
static inline int simple_positive(struct dentry *dentry)
{
return dentry->d_inode && !d_unhashed(dentry);
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index 500425e24fb..feb6ac427d0 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -56,12 +56,9 @@ static int autofs4_check_mount(struct vfsmount *mnt, struct dentry *dentry)
mntget(mnt);
dget(dentry);
- if (!follow_down(&mnt, &dentry))
+ if (!autofs4_follow_mount(&mnt, &dentry))
goto done;
- while (d_mountpoint(dentry) && follow_down(&mnt, &dentry))
- ;
-
/* This is an autofs submount, we can't expire it */
if (is_autofs4_dentry(dentry))
goto done;
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 3765c047f15..2a771ec6695 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -205,7 +205,11 @@ static int autofs4_dir_open(struct inode *inode, struct file *file)
struct vfsmount *fp_mnt = mntget(mnt);
struct dentry *fp_dentry = dget(dentry);
- while (follow_down(&fp_mnt, &fp_dentry) && d_mountpoint(fp_dentry));
+ if (!autofs4_follow_mount(&fp_mnt, &fp_dentry)) {
+ dput(fp_dentry);
+ mntput(fp_mnt);
+ return -ENOENT;
+ }
fp = dentry_open(fp_dentry, fp_mnt, file->f_flags);
status = PTR_ERR(fp);
@@ -302,7 +306,14 @@ static int try_to_fill_dentry(struct dentry *dentry,
DPRINTK("expire done status=%d", status);
- return 0;
+ /*
+ * If the directory still exists the mount request must
+ * continue otherwise it can't be followed at the right
+ * time during the walk.
+ */
+ status = d_invalidate(dentry);
+ if (status != -EBUSY)
+ return 0;
}
DPRINTK("dentry=%p %.*s ino=%p",
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index 5a40d36e5a5..fa2348dcd67 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -191,6 +191,13 @@ int autofs4_wait(struct autofs_sb_info *sbi, struct dentry *dentry,
}
if ( !wq ) {
+ /* Can't wait for an expire if there's no mount */
+ if (notify == NFY_NONE && !d_mountpoint(dentry)) {
+ kfree(name);
+ up(&sbi->wq_sem);
+ return -ENOENT;
+ }
+
/* Create a new wait queue */
wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL);
if ( !wq ) {
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index 009b8920c1f..dd9baabaf01 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -316,6 +316,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
current->mm->brk = ex.a_bss +
(current->mm->start_brk = N_BSSADDR(ex));
current->mm->free_area_cache = current->mm->mmap_base;
+ current->mm->cached_hole_size = 0;
set_mm_counter(current->mm, rss, 0);
current->mm->mmap = NULL;
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index ce9423bb2de..7976a238f0a 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -251,7 +251,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec,
}
/* Populate argv and envp */
- p = current->mm->arg_start;
+ p = current->mm->arg_end = current->mm->arg_start;
while (argc-- > 0) {
size_t len;
__put_user((elf_addr_t)p, argv++);
@@ -775,6 +775,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
change some of these later */
set_mm_counter(current->mm, rss, 0);
current->mm->free_area_cache = current->mm->mmap_base;
+ current->mm->cached_hole_size = 0;
retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP),
executable_stack);
if (retval < 0) {
@@ -1125,7 +1126,7 @@ static int dump_write(struct file *file, const void *addr, int nr)
return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
}
-static int dump_seek(struct file *file, off_t off)
+static int dump_seek(struct file *file, loff_t off)
{
if (file->f_op->llseek) {
if (file->f_op->llseek(file, off, 0) != off)
@@ -1301,7 +1302,7 @@ static void fill_prstatus(struct elf_prstatus *prstatus,
static int fill_psinfo(struct elf_prpsinfo *psinfo, struct task_struct *p,
struct mm_struct *mm)
{
- int i, len;
+ unsigned int i, len;
/* first copy the parameters from user space */
memset(psinfo, 0, sizeof(struct elf_prpsinfo));
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index f0cd67d9d31..c8998dc6688 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -520,7 +520,7 @@ static int load_flat_file(struct linux_binprm * bprm,
DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n");
down_write(&current->mm->mmap_sem);
- textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, 0, 0);
+ textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, MAP_SHARED, 0);
up_write(&current->mm->mmap_sem);
if (!textpos || textpos >= (unsigned long) -4096) {
if (!textpos)
@@ -532,7 +532,7 @@ static int load_flat_file(struct linux_binprm * bprm,
down_write(&current->mm->mmap_sem);
realdatastart = do_mmap(0, 0, data_len + extra +
MAX_SHARED_LIBS * sizeof(unsigned long),
- PROT_READ|PROT_WRITE|PROT_EXEC, 0, 0);
+ PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
up_write(&current->mm->mmap_sem);
if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) {
@@ -574,7 +574,7 @@ static int load_flat_file(struct linux_binprm * bprm,
down_write(&current->mm->mmap_sem);
textpos = do_mmap(0, 0, text_len + data_len + extra +
MAX_SHARED_LIBS * sizeof(unsigned long),
- PROT_READ | PROT_EXEC | PROT_WRITE, 0, 0);
+ PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
up_write(&current->mm->mmap_sem);
if (!textpos || textpos >= (unsigned long) -4096) {
if (!textpos)
diff --git a/fs/block_dev.c b/fs/block_dev.c
index c0cbd1bc1a0..e0df94c37b7 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -777,8 +777,7 @@ static ssize_t blkdev_file_aio_write(struct kiocb *iocb, const char __user *buf,
return generic_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos);
}
-static int block_ioctl(struct inode *inode, struct file *file, unsigned cmd,
- unsigned long arg)
+static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{
return blkdev_ioctl(file->f_mapping->host, file, cmd, arg);
}
@@ -803,7 +802,7 @@ struct file_operations def_blk_fops = {
.aio_write = blkdev_file_aio_write,
.mmap = generic_file_mmap,
.fsync = block_fsync,
- .ioctl = block_ioctl,
+ .unlocked_ioctl = block_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = compat_blkdev_ioctl,
#endif
diff --git a/fs/buffer.c b/fs/buffer.c
index 6f88dcc6d00..13e5938a64f 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -331,7 +331,7 @@ int file_fsync(struct file *filp, struct dentry *dentry, int datasync)
return ret;
}
-asmlinkage long sys_fsync(unsigned int fd)
+static long do_fsync(unsigned int fd, int datasync)
{
struct file * file;
struct address_space *mapping;
@@ -342,14 +342,14 @@ asmlinkage long sys_fsync(unsigned int fd)
if (!file)
goto out;
- mapping = file->f_mapping;
-
ret = -EINVAL;
if (!file->f_op || !file->f_op->fsync) {
/* Why? We can still call filemap_fdatawrite */
goto out_putf;
}
+ mapping = file->f_mapping;
+
current->flags |= PF_SYNCWRITE;
ret = filemap_fdatawrite(mapping);
@@ -358,7 +358,7 @@ asmlinkage long sys_fsync(unsigned int fd)
* which could cause livelocks in fsync_buffers_list
*/
down(&mapping->host->i_sem);
- err = file->f_op->fsync(file, file->f_dentry, 0);
+ err = file->f_op->fsync(file, file->f_dentry, datasync);
if (!ret)
ret = err;
up(&mapping->host->i_sem);
@@ -373,39 +373,14 @@ out:
return ret;
}
-asmlinkage long sys_fdatasync(unsigned int fd)
+asmlinkage long sys_fsync(unsigned int fd)
{
- struct file * file;
- struct address_space *mapping;
- int ret, err;
-
- ret = -EBADF;
- file = fget(fd);
- if (!file)
- goto out;
-
- ret = -EINVAL;
- if (!file->f_op || !file->f_op->fsync)
- goto out_putf;
-
- mapping = file->f_mapping;
-
- current->flags |= PF_SYNCWRITE;
- ret = filemap_fdatawrite(mapping);
- down(&mapping->host->i_sem);
- err = file->f_op->fsync(file, file->f_dentry, 1);
- if (!ret)
- ret = err;
- up(&mapping->host->i_sem);
- err = filemap_fdatawait(mapping);
- if (!ret)
- ret = err;
- current->flags &= ~PF_SYNCWRITE;
+ return do_fsync(fd, 0);
+}
-out_putf:
- fput(file);
-out:
- return ret;
+asmlinkage long sys_fdatasync(unsigned int fd)
+{
+ return do_fsync(fd, 1);
}
/*
@@ -528,7 +503,7 @@ static void free_more_memory(void)
for_each_pgdat(pgdat) {
zones = pgdat->node_zonelists[GFP_NOFS&GFP_ZONEMASK].zones;
if (*zones)
- try_to_free_pages(zones, GFP_NOFS, 0);
+ try_to_free_pages(zones, GFP_NOFS);
}
}
@@ -1951,7 +1926,6 @@ static int __block_prepare_write(struct inode *inode, struct page *page,
if (err)
break;
if (buffer_new(bh)) {
- clear_buffer_new(bh);
unmap_underlying_metadata(bh->b_bdev,
bh->b_blocknr);
if (PageUptodate(page)) {
@@ -1993,9 +1967,14 @@ static int __block_prepare_write(struct inode *inode, struct page *page,
if (!buffer_uptodate(*wait_bh))
err = -EIO;
}
- if (!err)
- return err;
-
+ if (!err) {
+ bh = head;
+ do {
+ if (buffer_new(bh))
+ clear_buffer_new(bh);
+ } while ((bh = bh->b_this_page) != head);
+ return 0;
+ }
/* Error case: */
/*
* Zero out any newly allocated blocks to avoid exposing stale
@@ -2094,9 +2073,12 @@ int block_read_full_page(struct page *page, get_block_t *get_block)
continue;
if (!buffer_mapped(bh)) {
+ int err = 0;
+
fully_mapped = 0;
if (iblock < lblock) {
- if (get_block(inode, iblock, bh, 0))
+ err = get_block(inode, iblock, bh, 0);
+ if (err)
SetPageError(page);
}
if (!buffer_mapped(bh)) {
@@ -2104,7 +2086,8 @@ int block_read_full_page(struct page *page, get_block_t *get_block)
memset(kaddr + i * blocksize, 0, blocksize);
flush_dcache_page(page);
kunmap_atomic(kaddr, KM_USER0);
- set_buffer_uptodate(bh);
+ if (!err)
+ set_buffer_uptodate(bh);
continue;
}
/*
diff --git a/fs/char_dev.c b/fs/char_dev.c
index c1e3537909f..e82aac9cc2f 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -56,10 +56,21 @@ int get_chrdev_list(char *page)
down(&chrdevs_lock);
for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) {
- for (cd = chrdevs[i]; cd; cd = cd->next)
+ for (cd = chrdevs[i]; cd; cd = cd->next) {
+ /*
+ * if the current name, plus the 5 extra characters
+ * in the device line for this entry
+ * would run us off the page, we're done
+ */
+ if ((len+strlen(cd->name) + 5) >= PAGE_SIZE)
+ goto page_full;
+
+
len += sprintf(page+len, "%3d %s\n",
cd->major, cd->name);
+ }
}
+page_full:
up(&chrdevs_lock);
return len;
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 95483baab70..dab4774ee7b 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -6,7 +6,8 @@ kills the cifsd thread (NB: killing the cifs kernel threads is not
recommended, unmount and rmmod cifs will kill them when they are
no longer needed). Fix readdir to ASCII servers (ie older servers
which do not support Unicode) and also require asterik.
-
+Fix out of memory case in which data could be written one page
+off in the page cache.
Version 1.33
------------
diff --git a/fs/cifs/README b/fs/cifs/README
index e74df0c7325..34b0cf7111f 100644
--- a/fs/cifs/README
+++ b/fs/cifs/README
@@ -371,7 +371,7 @@ A partial list of the supported mount options follows:
on newly created files, directories, and devices (create,
mkdir, mknod) which will result in the server setting the
uid and gid to the default (usually the server uid of the
- usern who mounted the share). Letting the server (rather than
+ user who mounted the share). Letting the server (rather than
the client) set the uid and gid is the default. This
parameter has no effect if the CIFS Unix Extensions are not
negotiated.
@@ -384,7 +384,7 @@ A partial list of the supported mount options follows:
client (e.g. when the application is doing large sequential
reads bigger than page size without rereading the same data)
this can provide better performance than the default
- behavior which caches reads (reaadahead) and writes
+ behavior which caches reads (readahead) and writes
(writebehind) through the local Linux client pagecache
if oplock (caching token) is granted and held. Note that
direct allows write operations larger than page size
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index d00b3bfe1a5..78af5850c55 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -96,5 +96,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.34"
+#define CIFS_VERSION "1.35"
#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 0010511083f..ea239dea571 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -228,7 +228,7 @@ extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
const struct nls_table *nls_codepage,
int remap_special_chars);
#endif /* CONFIG_CIFS_EXPERIMENTAL */
-extern int cifs_convertUCSpath(char *target, const __u16 *source, int maxlen,
+extern int cifs_convertUCSpath(char *target, const __le16 *source, int maxlen,
const struct nls_table * codepage);
extern int cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
const struct nls_table * cp, int mapChars);
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 741ff0c69f3..3c628bf667a 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -567,7 +567,7 @@ DelFileRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->fileName, fileName,
+ cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -665,7 +665,7 @@ MkDirRetry:
return rc;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len = cifsConvertToUCS((__u16 *) pSMB->DirName, name,
+ name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -719,7 +719,7 @@ openRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
count = 1; /* account for one byte pad to word boundary */
name_len =
- cifsConvertToUCS((__u16 *) (pSMB->fileName + 1),
+ cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
fileName, PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -1141,7 +1141,7 @@ renameRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->OldFileName, fromName,
+ cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -1149,7 +1149,7 @@ renameRetry:
/* protocol requires ASCII signature byte on Unicode string */
pSMB->OldFileName[name_len + 1] = 0x00;
name_len2 =
- cifsConvertToUCS((__u16 *) &pSMB->OldFileName[name_len + 2],
+ cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
toName, PATH_MAX, nls_codepage, remap);
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
name_len2 *= 2; /* convert to bytes */
@@ -1236,10 +1236,10 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
/* unicode only call */
if(target_name == NULL) {
sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
- len_of_str = cifsConvertToUCS((__u16 *)rename_info->target_name,
+ len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
dummy_string, 24, nls_codepage, remap);
} else {
- len_of_str = cifsConvertToUCS((__u16 *)rename_info->target_name,
+ len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
target_name, PATH_MAX, nls_codepage, remap);
}
rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
@@ -1296,7 +1296,7 @@ copyRetry:
pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len = cifsConvertToUCS((__u16 *) pSMB->OldFileName,
+ name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
fromName, PATH_MAX, nls_codepage,
remap);
name_len++; /* trailing null */
@@ -1304,7 +1304,7 @@ copyRetry:
pSMB->OldFileName[name_len] = 0x04; /* pad */
/* protocol requires ASCII signature byte on Unicode string */
pSMB->OldFileName[name_len + 1] = 0x00;
- name_len2 = cifsConvertToUCS((__u16 *)&pSMB->OldFileName[name_len + 2],
+ name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
toName, PATH_MAX, nls_codepage, remap);
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
name_len2 *= 2; /* convert to bytes */
@@ -1453,7 +1453,7 @@ createHardLinkRetry:
return rc;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len = cifsConvertToUCS((__u16 *) pSMB->FileName, toName,
+ name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -1476,7 +1476,7 @@ createHardLinkRetry:
data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len_target =
- cifsConvertToUCS((__u16 *) data_offset, fromName, PATH_MAX,
+ cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
nls_codepage, remap);
name_len_target++; /* trailing null */
name_len_target *= 2;
@@ -1546,14 +1546,14 @@ winCreateHardLinkRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->OldFileName, fromName,
+ cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
pSMB->OldFileName[name_len] = 0; /* pad */
pSMB->OldFileName[name_len + 1] = 0x04;
name_len2 =
- cifsConvertToUCS((__u16 *)&pSMB->OldFileName[name_len + 2],
+ cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
toName, PATH_MAX, nls_codepage, remap);
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
name_len2 *= 2; /* convert to bytes */
@@ -1939,7 +1939,7 @@ queryAclRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
+ cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -2024,7 +2024,7 @@ setAclRetry:
return rc;
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
+ cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -2188,7 +2188,7 @@ QPathInfoRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
+ cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -2269,7 +2269,7 @@ UnixQPathInfoRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
+ cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -2350,7 +2350,7 @@ findUniqueRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
+ cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
/* find define for this maxpathcomponent */
, nls_codepage);
name_len++; /* trailing null */
@@ -2435,7 +2435,7 @@ findFirstRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->FileName,searchName,
+ cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
PATH_MAX, nls_codepage, remap);
/* We can not add the asterik earlier in case
it got remapped to 0xF03A as if it were part of the
@@ -2726,7 +2726,7 @@ GetInodeNumberRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
+ cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
PATH_MAX,nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -2837,7 +2837,7 @@ getDFSRetry:
if (ses->capabilities & CAP_UNICODE) {
pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
name_len =
- cifsConvertToUCS((__u16 *) pSMB->RequestFileName,
+ cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
searchName, PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -3369,7 +3369,7 @@ SetEOFRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
+ cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -3627,7 +3627,7 @@ SetTimesRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
+ cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -3708,7 +3708,7 @@ SetAttrLgcyRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- ConvertToUCS((wchar_t *) pSMB->fileName, fileName,
+ ConvertToUCS((__le16 *) pSMB->fileName, fileName,
PATH_MAX, nls_codepage);
name_len++; /* trailing null */
name_len *= 2;
@@ -3759,7 +3759,7 @@ setPermsRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
+ cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -3904,7 +3904,7 @@ QAllEAsRetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((wchar_t *) pSMB->FileName, searchName,
+ cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -4047,7 +4047,7 @@ QEARetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
+ cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
@@ -4194,7 +4194,7 @@ SetEARetry:
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
name_len =
- cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
+ cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
PATH_MAX, nls_codepage, remap);
name_len++; /* trailing null */
name_len *= 2;
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index e3137aa48cd..3f3538d4a1f 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -392,7 +392,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
rc = 0;
d_add(direntry, NULL);
} else {
- cERROR(1,("Error 0x%x or on cifs_get_inode_info in lookup",rc));
+ cERROR(1,("Error 0x%x on cifs_get_inode_info in lookup of %s",
+ rc,full_path));
/* BB special case check for Access Denied - watch security
exposure of returning dir info implicitly via different rc
if file exists or not but no access BB */
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index dde2d251fc3..30ab70ce554 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1352,6 +1352,8 @@ static void cifs_copy_cache_pages(struct address_space *mapping,
GFP_KERNEL)) {
page_cache_release(page);
cFYI(1, ("Add page cache failed"));
+ data += PAGE_CACHE_SIZE;
+ bytes_read -= PAGE_CACHE_SIZE;
continue;
}
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 67094728826..8d336a90025 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -82,12 +82,12 @@ int cifs_get_inode_info_unix(struct inode **pinode,
/* get new inode */
if (*pinode == NULL) {
*pinode = new_inode(sb);
- if(*pinode == NULL)
+ if (*pinode == NULL)
return -ENOMEM;
/* Is an i_ino of zero legal? */
/* Are there sanity checks we can use to ensure that
the server is really filling in that field? */
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
(*pinode)->i_ino =
(unsigned long)findData.UniqueId;
} /* note ino incremented to unique num in new_inode */
@@ -134,7 +134,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
inode->i_gid = le64_to_cpu(findData.Gid);
inode->i_nlink = le64_to_cpu(findData.Nlinks);
- if(is_size_safe_to_change(cifsInfo)) {
+ if (is_size_safe_to_change(cifsInfo)) {
/* can not safely change the file size here if the
client is writing to it due to potential races */
@@ -162,7 +162,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
if (S_ISREG(inode->i_mode)) {
cFYI(1, (" File inode "));
inode->i_op = &cifs_file_inode_ops;
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
inode->i_fop = &cifs_file_direct_ops;
else
inode->i_fop = &cifs_file_ops;
@@ -198,17 +198,17 @@ int cifs_get_inode_info(struct inode **pinode,
pTcon = cifs_sb->tcon;
cFYI(1,("Getting info on %s ", search_path));
- if((pfindData == NULL) && (*pinode != NULL)) {
- if(CIFS_I(*pinode)->clientCanCacheRead) {
+ if ((pfindData == NULL) && (*pinode != NULL)) {
+ if (CIFS_I(*pinode)->clientCanCacheRead) {
cFYI(1,("No need to revalidate cached inode sizes"));
return rc;
}
}
/* if file info not passed in then get it from server */
- if(pfindData == NULL) {
+ if (pfindData == NULL) {
buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
- if(buf == NULL)
+ if (buf == NULL)
return -ENOMEM;
pfindData = (FILE_ALL_INFO *)buf;
/* could do find first instead but this returns more info */
@@ -268,7 +268,7 @@ int cifs_get_inode_info(struct inode **pinode,
IndexNumber field is not guaranteed unique? */
#ifdef CONFIG_CIFS_EXPERIMENTAL
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){
int rc1 = 0;
__u64 inode_num;
@@ -277,7 +277,7 @@ int cifs_get_inode_info(struct inode **pinode,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
- if(rc1) {
+ if (rc1) {
cFYI(1,("GetSrvInodeNum rc %d", rc1));
/* BB EOPNOSUPP disable SERVER_INUM? */
} else /* do we need cast or hash to ino? */
@@ -355,7 +355,7 @@ int cifs_get_inode_info(struct inode **pinode,
if (S_ISREG(inode->i_mode)) {
cFYI(1, (" File inode "));
inode->i_op = &cifs_file_inode_ops;
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
inode->i_fop = &cifs_file_direct_ops;
else
inode->i_fop = &cifs_file_ops;
@@ -422,7 +422,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
if (!rc) {
- direntry->d_inode->i_nlink--;
+ if (direntry->d_inode)
+ direntry->d_inode->i_nlink--;
} else if (rc == -ENOENT) {
d_drop(direntry);
} else if (rc == -ETXTBSY) {
@@ -440,7 +441,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
CIFSSMBClose(xid, pTcon, netfid);
- direntry->d_inode->i_nlink--;
+ if (direntry->d_inode)
+ direntry->d_inode->i_nlink--;
}
} else if (rc == -EACCES) {
/* try only if r/o attribute set in local lookup data? */
@@ -494,7 +496,8 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (!rc) {
- direntry->d_inode->i_nlink--;
+ if (direntry->d_inode)
+ direntry->d_inode->i_nlink--;
} else if (rc == -ETXTBSY) {
int oplock = FALSE;
__u16 netfid;
@@ -514,17 +517,20 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
CIFSSMBClose(xid, pTcon, netfid);
- direntry->d_inode->i_nlink--;
+ if (direntry->d_inode)
+ direntry->d_inode->i_nlink--;
}
/* BB if rc = -ETXTBUSY goto the rename logic BB */
}
}
}
- cifsInode = CIFS_I(direntry->d_inode);
- cifsInode->time = 0; /* will force revalidate to get info when
- needed */
- direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
- current_fs_time(inode->i_sb);
+ if (direntry->d_inode) {
+ cifsInode = CIFS_I(direntry->d_inode);
+ cifsInode->time = 0; /* will force revalidate to get info
+ when needed */
+ direntry->d_inode->i_ctime = current_fs_time(inode->i_sb);
+ }
+ inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
cifsInode = CIFS_I(inode);
cifsInode->time = 0; /* force revalidate of dir as well */
@@ -576,7 +582,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
if (direntry->d_inode)
direntry->d_inode->i_nlink = 2;
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
- if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
CIFSSMBUnixSetPerms(xid, pTcon, full_path,
mode,
(__u64)current->euid,
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index db14b503d89..072b4ee8c53 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -571,6 +571,7 @@ cifs_convertUCSpath(char *target, const __le16 * source, int maxlen,
break;
case UNI_LESSTHAN:
target[j] = '<';
+ break;
default:
len = cp->uni2char(src_char, &target[j],
NLS_MAX_CHARSET_SIZE);
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
index ef001a9313e..3d1cce3653b 100644
--- a/fs/coda/psdev.c
+++ b/fs/coda/psdev.c
@@ -61,7 +61,7 @@ unsigned long coda_timeout = 30; /* .. secs, then signals will dequeue */
struct venus_comm coda_comms[MAX_CODADEVS];
-static struct class_simple *coda_psdev_class;
+static struct class *coda_psdev_class;
/*
* Device operations
@@ -363,14 +363,14 @@ static int init_coda_psdev(void)
CODA_PSDEV_MAJOR);
return -EIO;
}
- coda_psdev_class = class_simple_create(THIS_MODULE, "coda");
+ coda_psdev_class = class_create(THIS_MODULE, "coda");
if (IS_ERR(coda_psdev_class)) {
err = PTR_ERR(coda_psdev_class);
goto out_chrdev;
}
devfs_mk_dir ("coda");
for (i = 0; i < MAX_CODADEVS; i++) {
- class_simple_device_add(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR,i),
+ class_device_create(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR,i),
NULL, "cfs%d", i);
err = devfs_mk_cdev(MKDEV(CODA_PSDEV_MAJOR, i),
S_IFCHR|S_IRUSR|S_IWUSR, "coda/%d", i);
@@ -382,8 +382,8 @@ static int init_coda_psdev(void)
out_class:
for (i = 0; i < MAX_CODADEVS; i++)
- class_simple_device_remove(MKDEV(CODA_PSDEV_MAJOR, i));
- class_simple_destroy(coda_psdev_class);
+ class_device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i));
+ class_destroy(coda_psdev_class);
out_chrdev:
unregister_chrdev(CODA_PSDEV_MAJOR, "coda");
out:
@@ -425,10 +425,10 @@ static int __init init_coda(void)
return 0;
out:
for (i = 0; i < MAX_CODADEVS; i++) {
- class_simple_device_remove(MKDEV(CODA_PSDEV_MAJOR, i));
+ class_device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i));
devfs_remove("coda/%d", i);
}
- class_simple_destroy(coda_psdev_class);
+ class_destroy(coda_psdev_class);
devfs_remove("coda");
unregister_chrdev(CODA_PSDEV_MAJOR, "coda");
coda_sysctl_clean();
@@ -447,10 +447,10 @@ static void __exit exit_coda(void)
printk("coda: failed to unregister filesystem\n");
}
for (i = 0; i < MAX_CODADEVS; i++) {
- class_simple_device_remove(MKDEV(CODA_PSDEV_MAJOR, i));
+ class_device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i));
devfs_remove("coda/%d", i);
}
- class_simple_destroy(coda_psdev_class);
+ class_destroy(coda_psdev_class);
devfs_remove("coda");
unregister_chrdev(CODA_PSDEV_MAJOR, "coda");
coda_sysctl_clean();
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 548556ff250..efc97d9b786 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -45,44 +45,15 @@ struct file_operations debugfs_file_operations = {
.open = default_open,
};
-#define simple_type(type, format, temptype, strtolfn) \
-static ssize_t read_file_##type(struct file *file, char __user *user_buf, \
- size_t count, loff_t *ppos) \
-{ \
- char buf[32]; \
- type *val = file->private_data; \
- \
- snprintf(buf, sizeof(buf), format "\n", *val); \
- return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));\
-} \
-static ssize_t write_file_##type(struct file *file, const char __user *user_buf,\
- size_t count, loff_t *ppos) \
-{ \
- char *endp; \
- char buf[32]; \
- int buf_size; \
- type *val = file->private_data; \
- temptype tmp; \
- \
- memset(buf, 0x00, sizeof(buf)); \
- buf_size = min(count, (sizeof(buf)-1)); \
- if (copy_from_user(buf, user_buf, buf_size)) \
- return -EFAULT; \
- \
- tmp = strtolfn(buf, &endp, 0); \
- if ((endp == buf) || ((type)tmp != tmp)) \
- return -EINVAL; \
- *val = tmp; \
- return count; \
-} \
-static struct file_operations fops_##type = { \
- .read = read_file_##type, \
- .write = write_file_##type, \
- .open = default_open, \
-};
-simple_type(u8, "%c", unsigned long, simple_strtoul);
-simple_type(u16, "%hi", unsigned long, simple_strtoul);
-simple_type(u32, "%i", unsigned long, simple_strtoul);
+static void debugfs_u8_set(void *data, u64 val)
+{
+ *(u8 *)data = val;
+}
+static u64 debugfs_u8_get(void *data)
+{
+ return *(u8 *)data;
+}
+DEFINE_SIMPLE_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%llu\n");
/**
* debugfs_create_u8 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value.
@@ -116,6 +87,16 @@ struct dentry *debugfs_create_u8(const char *name, mode_t mode,
}
EXPORT_SYMBOL_GPL(debugfs_create_u8);
+static void debugfs_u16_set(void *data, u64 val)
+{
+ *(u16 *)data = val;
+}
+static u64 debugfs_u16_get(void *data)
+{
+ return *(u16 *)data;
+}
+DEFINE_SIMPLE_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%llu\n");
+
/**
* debugfs_create_u16 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value.
*
@@ -148,6 +129,16 @@ struct dentry *debugfs_create_u16(const char *name, mode_t mode,
}
EXPORT_SYMBOL_GPL(debugfs_create_u16);
+static void debugfs_u32_set(void *data, u64 val)
+{
+ *(u32 *)data = val;
+}
+static u64 debugfs_u32_get(void *data)
+{
+ return *(u32 *)data;
+}
+DEFINE_SIMPLE_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%llu\n");
+
/**
* debugfs_create_u32 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value.
*
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index b529786699e..a86ac4aeaed 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -110,16 +110,6 @@ static int debug_fill_super(struct super_block *sb, void *data, int silent)
return simple_fill_super(sb, DEBUGFS_MAGIC, debug_files);
}
-static struct dentry * get_dentry(struct dentry *parent, const char *name)
-{
- struct qstr qstr;
-
- qstr.name = name;
- qstr.len = strlen(name);
- qstr.hash = full_name_hash(name,qstr.len);
- return lookup_hash(&qstr,parent);
-}
-
static struct super_block *debug_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name,
void *data)
@@ -157,7 +147,7 @@ static int debugfs_create_by_name(const char *name, mode_t mode,
*dentry = NULL;
down(&parent->d_inode->i_sem);
- *dentry = get_dentry (parent, name);
+ *dentry = lookup_one_len(name, parent, strlen(name));
if (!IS_ERR(dentry)) {
if ((mode & S_IFMT) == S_IFDIR)
error = debugfs_mkdir(parent->d_inode, *dentry, mode);
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 1d55e7e6734..0d06097bc99 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -215,7 +215,7 @@ static struct page *dio_get_page(struct dio *dio)
static void dio_complete(struct dio *dio, loff_t offset, ssize_t bytes)
{
if (dio->end_io && dio->result)
- dio->end_io(dio->inode, offset, bytes, dio->map_bh.b_private);
+ dio->end_io(dio->iocb, offset, bytes, dio->map_bh.b_private);
if (dio->lock_type == DIO_LOCKING)
up_read(&dio->inode->i_alloc_sem);
}
diff --git a/fs/dquot.c b/fs/dquot.c
index 3995ce7907c..b9732335bcd 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -409,13 +409,10 @@ out_dqlock:
* for this sb+type at all. */
static void invalidate_dquots(struct super_block *sb, int type)
{
- struct dquot *dquot;
- struct list_head *head;
+ struct dquot *dquot, *tmp;
spin_lock(&dq_list_lock);
- for (head = inuse_list.next; head != &inuse_list;) {
- dquot = list_entry(head, struct dquot, dq_inuse);
- head = head->next;
+ list_for_each_entry_safe(dquot, tmp, &inuse_list, dq_inuse) {
if (dquot->dq_sb != sb)
continue;
if (dquot->dq_type != type)
@@ -1519,14 +1516,22 @@ out_path:
* This function is used when filesystem needs to initialize quotas
* during mount time.
*/
-int vfs_quota_on_mount(int type, int format_id, struct dentry *dentry)
+int vfs_quota_on_mount(struct super_block *sb, char *qf_name,
+ int format_id, int type)
{
+ struct dentry *dentry;
int error;
+ dentry = lookup_one_len(qf_name, sb->s_root, strlen(qf_name));
+ if (IS_ERR(dentry))
+ return PTR_ERR(dentry);
+
error = security_quota_on(dentry);
- if (error)
- return error;
- return vfs_quota_on_inode(dentry->d_inode, type, format_id);
+ if (!error)
+ error = vfs_quota_on_inode(dentry->d_inode, type, format_id);
+
+ dput(dentry);
+ return error;
}
/* Generic routine for getting common part of quota structure */
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 9900e333655..6ab1dd0ca90 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -101,57 +101,6 @@
/* Maximum number of poll wake up nests we are allowing */
#define EP_MAX_POLLWAKE_NESTS 4
-/* Macro to allocate a "struct epitem" from the slab cache */
-#define EPI_MEM_ALLOC() (struct epitem *) kmem_cache_alloc(epi_cache, SLAB_KERNEL)
-
-/* Macro to free a "struct epitem" to the slab cache */
-#define EPI_MEM_FREE(p) kmem_cache_free(epi_cache, p)
-
-/* Macro to allocate a "struct eppoll_entry" from the slab cache */
-#define PWQ_MEM_ALLOC() (struct eppoll_entry *) kmem_cache_alloc(pwq_cache, SLAB_KERNEL)
-
-/* Macro to free a "struct eppoll_entry" to the slab cache */
-#define PWQ_MEM_FREE(p) kmem_cache_free(pwq_cache, p)
-
-/* Fast test to see if the file is an evenpoll file */
-#define IS_FILE_EPOLL(f) ((f)->f_op == &eventpoll_fops)
-
-/* Setup the structure that is used as key for the rb-tree */
-#define EP_SET_FFD(p, f, d) do { (p)->file = (f); (p)->fd = (d); } while (0)
-
-/* Compare rb-tree keys */
-#define EP_CMP_FFD(p1, p2) ((p1)->file > (p2)->file ? +1: \
- ((p1)->file < (p2)->file ? -1: (p1)->fd - (p2)->fd))
-
-/* Special initialization for the rb-tree node to detect linkage */
-#define EP_RB_INITNODE(n) (n)->rb_parent = (n)
-
-/* Removes a node from the rb-tree and marks it for a fast is-linked check */
-#define EP_RB_ERASE(n, r) do { rb_erase(n, r); (n)->rb_parent = (n); } while (0)
-
-/* Fast check to verify that the item is linked to the main rb-tree */
-#define EP_RB_LINKED(n) ((n)->rb_parent != (n))
-
-/*
- * Remove the item from the list and perform its initialization.
- * This is useful for us because we can test if the item is linked
- * using "EP_IS_LINKED(p)".
- */
-#define EP_LIST_DEL(p) do { list_del(p); INIT_LIST_HEAD(p); } while (0)
-
-/* Tells us if the item is currently linked */
-#define EP_IS_LINKED(p) (!list_empty(p))
-
-/* Get the "struct epitem" from a wait queue pointer */
-#define EP_ITEM_FROM_WAIT(p) ((struct epitem *) container_of(p, struct eppoll_entry, wait)->base)
-
-/* Get the "struct epitem" from an epoll queue wrapper */
-#define EP_ITEM_FROM_EPQUEUE(p) (container_of(p, struct ep_pqueue, pt)->epi)
-
-/* Tells if the epoll_ctl(2) operation needs an event copy from userspace */
-#define EP_OP_HASH_EVENT(op) ((op) != EPOLL_CTL_DEL)
-
-
struct epoll_filefd {
struct file *file;
int fd;
@@ -357,6 +306,82 @@ static struct dentry_operations eventpollfs_dentry_operations = {
+/* Fast test to see if the file is an evenpoll file */
+static inline int is_file_epoll(struct file *f)
+{
+ return f->f_op == &eventpoll_fops;
+}
+
+/* Setup the structure that is used as key for the rb-tree */
+static inline void ep_set_ffd(struct epoll_filefd *ffd,
+ struct file *file, int fd)
+{
+ ffd->file = file;
+ ffd->fd = fd;
+}
+
+/* Compare rb-tree keys */
+static inline int ep_cmp_ffd(struct epoll_filefd *p1,
+ struct epoll_filefd *p2)
+{
+ return (p1->file > p2->file ? +1:
+ (p1->file < p2->file ? -1 : p1->fd - p2->fd));
+}
+
+/* Special initialization for the rb-tree node to detect linkage */
+static inline void ep_rb_initnode(struct rb_node *n)
+{
+ n->rb_parent = n;
+}
+
+/* Removes a node from the rb-tree and marks it for a fast is-linked check */
+static inline void ep_rb_erase(struct rb_node *n, struct rb_root *r)
+{
+ rb_erase(n, r);
+ n->rb_parent = n;
+}
+
+/* Fast check to verify that the item is linked to the main rb-tree */
+static inline int ep_rb_linked(struct rb_node *n)
+{
+ return n->rb_parent != n;
+}
+
+/*
+ * Remove the item from the list and perform its initialization.
+ * This is useful for us because we can test if the item is linked
+ * using "ep_is_linked(p)".
+ */
+static inline void ep_list_del(struct list_head *p)
+{
+ list_del(p);
+ INIT_LIST_HEAD(p);
+}
+
+/* Tells us if the item is currently linked */
+static inline int ep_is_linked(struct list_head *p)
+{
+ return !list_empty(p);
+}
+
+/* Get the "struct epitem" from a wait queue pointer */
+static inline struct epitem * ep_item_from_wait(wait_queue_t *p)
+{
+ return container_of(p, struct eppoll_entry, wait)->base;
+}
+
+/* Get the "struct epitem" from an epoll queue wrapper */
+static inline struct epitem * ep_item_from_epqueue(poll_table *p)
+{
+ return container_of(p, struct ep_pqueue, pt)->epi;
+}
+
+/* Tells if the epoll_ctl(2) operation needs an event copy from userspace */
+static inline int ep_op_hash_event(int op)
+{
+ return op != EPOLL_CTL_DEL;
+}
+
/* Initialize the poll safe wake up structure */
static void ep_poll_safewake_init(struct poll_safewake *psw)
{
@@ -456,7 +481,7 @@ void eventpoll_release_file(struct file *file)
epi = list_entry(lsthead->next, struct epitem, fllink);
ep = epi->ep;
- EP_LIST_DEL(&epi->fllink);
+ ep_list_del(&epi->fllink);
down_write(&ep->sem);
ep_remove(ep, epi);
up_write(&ep->sem);
@@ -534,7 +559,7 @@ sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event __user *event)
current, epfd, op, fd, event));
error = -EFAULT;
- if (EP_OP_HASH_EVENT(op) &&
+ if (ep_op_hash_event(op) &&
copy_from_user(&epds, event, sizeof(struct epoll_event)))
goto eexit_1;
@@ -560,7 +585,7 @@ sys_epoll_ctl(int epfd, int op, int fd, struct epoll_event __user *event)
* adding an epoll file descriptor inside itself.
*/
error = -EINVAL;
- if (file == tfile || !IS_FILE_EPOLL(file))
+ if (file == tfile || !is_file_epoll(file))
goto eexit_3;
/*
@@ -656,7 +681,7 @@ asmlinkage long sys_epoll_wait(int epfd, struct epoll_event __user *events,
* the user passed to us _is_ an eventpoll file.
*/
error = -EINVAL;
- if (!IS_FILE_EPOLL(file))
+ if (!is_file_epoll(file))
goto eexit_2;
/*
@@ -831,11 +856,11 @@ static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd)
struct epitem *epi, *epir = NULL;
struct epoll_filefd ffd;
- EP_SET_FFD(&ffd, file, fd);
+ ep_set_ffd(&ffd, file, fd);
read_lock_irqsave(&ep->lock, flags);
for (rbp = ep->rbr.rb_node; rbp; ) {
epi = rb_entry(rbp, struct epitem, rbn);
- kcmp = EP_CMP_FFD(&ffd, &epi->ffd);
+ kcmp = ep_cmp_ffd(&ffd, &epi->ffd);
if (kcmp > 0)
rbp = rbp->rb_right;
else if (kcmp < 0)
@@ -875,7 +900,7 @@ static void ep_release_epitem(struct epitem *epi)
{
if (atomic_dec_and_test(&epi->usecnt))
- EPI_MEM_FREE(epi);
+ kmem_cache_free(epi_cache, epi);
}
@@ -886,10 +911,10 @@ static void ep_release_epitem(struct epitem *epi)
static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
poll_table *pt)
{
- struct epitem *epi = EP_ITEM_FROM_EPQUEUE(pt);
+ struct epitem *epi = ep_item_from_epqueue(pt);
struct eppoll_entry *pwq;
- if (epi->nwait >= 0 && (pwq = PWQ_MEM_ALLOC())) {
+ if (epi->nwait >= 0 && (pwq = kmem_cache_alloc(pwq_cache, SLAB_KERNEL))) {
init_waitqueue_func_entry(&pwq->wait, ep_poll_callback);
pwq->whead = whead;
pwq->base = epi;
@@ -912,7 +937,7 @@ static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi)
while (*p) {
parent = *p;
epic = rb_entry(parent, struct epitem, rbn);
- kcmp = EP_CMP_FFD(&epi->ffd, &epic->ffd);
+ kcmp = ep_cmp_ffd(&epi->ffd, &epic->ffd);
if (kcmp > 0)
p = &parent->rb_right;
else
@@ -932,17 +957,17 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
struct ep_pqueue epq;
error = -ENOMEM;
- if (!(epi = EPI_MEM_ALLOC()))
+ if (!(epi = kmem_cache_alloc(epi_cache, SLAB_KERNEL)))
goto eexit_1;
/* Item initialization follow here ... */
- EP_RB_INITNODE(&epi->rbn);
+ ep_rb_initnode(&epi->rbn);
INIT_LIST_HEAD(&epi->rdllink);
INIT_LIST_HEAD(&epi->fllink);
INIT_LIST_HEAD(&epi->txlink);
INIT_LIST_HEAD(&epi->pwqlist);
epi->ep = ep;
- EP_SET_FFD(&epi->ffd, tfile, fd);
+ ep_set_ffd(&epi->ffd, tfile, fd);
epi->event = *event;
atomic_set(&epi->usecnt, 1);
epi->nwait = 0;
@@ -978,7 +1003,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
ep_rbtree_insert(ep, epi);
/* If the file is already "ready" we drop it inside the ready list */
- if ((revents & event->events) && !EP_IS_LINKED(&epi->rdllink)) {
+ if ((revents & event->events) && !ep_is_linked(&epi->rdllink)) {
list_add_tail(&epi->rdllink, &ep->rdllist);
/* Notify waiting tasks that events are available */
@@ -1007,11 +1032,11 @@ eexit_2:
* allocated wait queue.
*/
write_lock_irqsave(&ep->lock, flags);
- if (EP_IS_LINKED(&epi->rdllink))
- EP_LIST_DEL(&epi->rdllink);
+ if (ep_is_linked(&epi->rdllink))
+ ep_list_del(&epi->rdllink);
write_unlock_irqrestore(&ep->lock, flags);
- EPI_MEM_FREE(epi);
+ kmem_cache_free(epi_cache, epi);
eexit_1:
return error;
}
@@ -1050,14 +1075,14 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even
* If the item is not linked to the hash it means that it's on its
* way toward the removal. Do nothing in this case.
*/
- if (EP_RB_LINKED(&epi->rbn)) {
+ if (ep_rb_linked(&epi->rbn)) {
/*
* If the item is "hot" and it is not registered inside the ready
* list, push it inside. If the item is not "hot" and it is currently
* registered inside the ready list, unlink it.
*/
if (revents & event->events) {
- if (!EP_IS_LINKED(&epi->rdllink)) {
+ if (!ep_is_linked(&epi->rdllink)) {
list_add_tail(&epi->rdllink, &ep->rdllist);
/* Notify waiting tasks that events are available */
@@ -1097,9 +1122,9 @@ static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi)
while (!list_empty(lsthead)) {
pwq = list_entry(lsthead->next, struct eppoll_entry, llink);
- EP_LIST_DEL(&pwq->llink);
+ ep_list_del(&pwq->llink);
remove_wait_queue(pwq->whead, &pwq->wait);
- PWQ_MEM_FREE(pwq);
+ kmem_cache_free(pwq_cache, pwq);
}
}
}
@@ -1118,7 +1143,7 @@ static int ep_unlink(struct eventpoll *ep, struct epitem *epi)
* The check protect us from doing a double unlink ( crash ).
*/
error = -ENOENT;
- if (!EP_RB_LINKED(&epi->rbn))
+ if (!ep_rb_linked(&epi->rbn))
goto eexit_1;
/*
@@ -1133,14 +1158,14 @@ static int ep_unlink(struct eventpoll *ep, struct epitem *epi)
* This operation togheter with the above check closes the door to
* double unlinks.
*/
- EP_RB_ERASE(&epi->rbn, &ep->rbr);
+ ep_rb_erase(&epi->rbn, &ep->rbr);
/*
* If the item we are going to remove is inside the ready file descriptors
* we want to remove it from this list to avoid stale events.
*/
- if (EP_IS_LINKED(&epi->rdllink))
- EP_LIST_DEL(&epi->rdllink);
+ if (ep_is_linked(&epi->rdllink))
+ ep_list_del(&epi->rdllink);
error = 0;
eexit_1:
@@ -1174,8 +1199,8 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi)
/* Remove the current item from the list of epoll hooks */
spin_lock(&file->f_ep_lock);
- if (EP_IS_LINKED(&epi->fllink))
- EP_LIST_DEL(&epi->fllink);
+ if (ep_is_linked(&epi->fllink))
+ ep_list_del(&epi->fllink);
spin_unlock(&file->f_ep_lock);
/* We need to acquire the write IRQ lock before calling ep_unlink() */
@@ -1210,7 +1235,7 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k
{
int pwake = 0;
unsigned long flags;
- struct epitem *epi = EP_ITEM_FROM_WAIT(wait);
+ struct epitem *epi = ep_item_from_wait(wait);
struct eventpoll *ep = epi->ep;
DNPRINTK(3, (KERN_INFO "[%p] eventpoll: poll_callback(%p) epi=%p ep=%p\n",
@@ -1228,7 +1253,7 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k
goto is_disabled;
/* If this file is already in the ready list we exit soon */
- if (EP_IS_LINKED(&epi->rdllink))
+ if (ep_is_linked(&epi->rdllink))
goto is_linked;
list_add_tail(&epi->rdllink, &ep->rdllist);
@@ -1307,7 +1332,7 @@ static int ep_collect_ready_items(struct eventpoll *ep, struct list_head *txlist
lnk = lnk->next;
/* If this file is already in the ready list we exit soon */
- if (!EP_IS_LINKED(&epi->txlink)) {
+ if (!ep_is_linked(&epi->txlink)) {
/*
* This is initialized in this way so that the default
* behaviour of the reinjecting code will be to push back
@@ -1322,7 +1347,7 @@ static int ep_collect_ready_items(struct eventpoll *ep, struct list_head *txlist
/*
* Unlink the item from the ready list.
*/
- EP_LIST_DEL(&epi->rdllink);
+ ep_list_del(&epi->rdllink);
}
}
@@ -1401,7 +1426,7 @@ static void ep_reinject_items(struct eventpoll *ep, struct list_head *txlist)
epi = list_entry(txlist->next, struct epitem, txlink);
/* Unlink the current item from the transfer list */
- EP_LIST_DEL(&epi->txlink);
+ ep_list_del(&epi->txlink);
/*
* If the item is no more linked to the interest set, we don't
@@ -1410,8 +1435,8 @@ static void ep_reinject_items(struct eventpoll *ep, struct list_head *txlist)
* item is set to have an Edge Triggered behaviour, we don't have
* to push it back either.
*/
- if (EP_RB_LINKED(&epi->rbn) && !(epi->event.events & EPOLLET) &&
- (epi->revents & epi->event.events) && !EP_IS_LINKED(&epi->rdllink)) {
+ if (ep_rb_linked(&epi->rbn) && !(epi->event.events & EPOLLET) &&
+ (epi->revents & epi->event.events) && !ep_is_linked(&epi->rdllink)) {
list_add_tail(&epi->rdllink, &ep->rdllist);
ricnt++;
}
diff --git a/fs/exec.c b/fs/exec.c
index e56ee243702..48871917d36 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -58,6 +58,9 @@
int core_uses_pid;
char core_pattern[65] = "core";
+int suid_dumpable = 0;
+
+EXPORT_SYMBOL(suid_dumpable);
/* The maximal length of core_pattern is also specified in sysctl.c */
static struct linux_binfmt *formats;
@@ -649,6 +652,7 @@ static inline int de_thread(struct task_struct *tsk)
}
sig->group_exit_task = NULL;
sig->notify_count = 0;
+ sig->real_timer.data = (unsigned long)current;
spin_unlock_irq(lock);
/*
@@ -675,10 +679,8 @@ static inline int de_thread(struct task_struct *tsk)
proc_dentry2 = proc_pid_unhash(leader);
write_lock_irq(&tasklist_lock);
- if (leader->tgid != current->tgid)
- BUG();
- if (current->pid == current->tgid)
- BUG();
+ BUG_ON(leader->tgid != current->tgid);
+ BUG_ON(current->pid == current->tgid);
/*
* An exec() starts a new thread group with the
* TGID of the previous thread group. Rehash the
@@ -726,8 +728,7 @@ static inline int de_thread(struct task_struct *tsk)
proc_pid_flush(proc_dentry1);
proc_pid_flush(proc_dentry2);
- if (exit_state != EXIT_ZOMBIE)
- BUG();
+ BUG_ON(exit_state != EXIT_ZOMBIE);
release_task(leader);
}
@@ -772,10 +773,8 @@ no_thread_group:
kmem_cache_free(sighand_cachep, oldsighand);
}
- if (!thread_group_empty(current))
- BUG();
- if (!thread_group_leader(current))
- BUG();
+ BUG_ON(!thread_group_empty(current));
+ BUG_ON(!thread_group_leader(current));
return 0;
}
@@ -868,6 +867,9 @@ int flush_old_exec(struct linux_binprm * bprm)
if (current->euid == current->uid && current->egid == current->gid)
current->mm->dumpable = 1;
+ else
+ current->mm->dumpable = suid_dumpable;
+
name = bprm->filename;
/* Copies the binary name from after last slash */
@@ -888,7 +890,7 @@ int flush_old_exec(struct linux_binprm * bprm)
permission(bprm->file->f_dentry->d_inode,MAY_READ, NULL) ||
(bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) {
suid_keys(current);
- current->mm->dumpable = 0;
+ current->mm->dumpable = suid_dumpable;
}
/* An exec changes our domain. We are no longer part of the thread
@@ -1436,6 +1438,8 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
struct inode * inode;
struct file * file;
int retval = 0;
+ int fsuid = current->fsuid;
+ int flag = 0;
binfmt = current->binfmt;
if (!binfmt || !binfmt->core_dump)
@@ -1445,6 +1449,16 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
up_write(&mm->mmap_sem);
goto fail;
}
+
+ /*
+ * We cannot trust fsuid as being the "true" uid of the
+ * process nor do we know its entire history. We only know it
+ * was tainted so we dump it as root in mode 2.
+ */
+ if (mm->dumpable == 2) { /* Setuid core dump mode */
+ flag = O_EXCL; /* Stop rewrite attacks */
+ current->fsuid = 0; /* Dump root private */
+ }
mm->dumpable = 0;
init_completion(&mm->core_done);
spin_lock_irq(&current->sighand->siglock);
@@ -1470,7 +1484,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
lock_kernel();
format_corename(corename, core_pattern, signr);
unlock_kernel();
- file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE, 0600);
+ file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, 0600);
if (IS_ERR(file))
goto fail_unlock;
inode = file->f_dentry->d_inode;
@@ -1495,6 +1509,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
close_fail:
filp_close(file, NULL);
fail_unlock:
+ current->fsuid = fsuid;
complete_all(&mm->core_done);
fail:
return retval;
diff --git a/fs/ext2/Makefile b/fs/ext2/Makefile
index ee240a14e70..c5d02da73bc 100644
--- a/fs/ext2/Makefile
+++ b/fs/ext2/Makefile
@@ -10,3 +10,4 @@ ext2-y := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o xattr_user.o xattr_trusted.o
ext2-$(CONFIG_EXT2_FS_POSIX_ACL) += acl.o
ext2-$(CONFIG_EXT2_FS_SECURITY) += xattr_security.o
+ext2-$(CONFIG_EXT2_FS_XIP) += xip.o
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index 25f4a64fd6b..213148c36eb 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -396,12 +396,12 @@ static size_t
ext2_xattr_list_acl_access(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
{
- const size_t size = sizeof(XATTR_NAME_ACL_ACCESS);
+ const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
if (!test_opt(inode->i_sb, POSIX_ACL))
return 0;
if (list && size <= list_size)
- memcpy(list, XATTR_NAME_ACL_ACCESS, size);
+ memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
return size;
}
@@ -409,12 +409,12 @@ static size_t
ext2_xattr_list_acl_default(struct inode *inode, char *list, size_t list_size,
const char *name, size_t name_len)
{
- const size_t size = sizeof(XATTR_NAME_ACL_DEFAULT);
+ const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
if (!test_opt(inode->i_sb, POSIX_ACL))
return 0;
if (list && size <= list_size)
- memcpy(list, XATTR_NAME_ACL_DEFAULT, size);
+ memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
return size;
}
@@ -506,14 +506,14 @@ ext2_xattr_set_acl_default(struct inode *inode, const char *name,
}
struct xattr_handler ext2_xattr_acl_access_handler = {
- .prefix = XATTR_NAME_ACL_ACCESS,
+ .prefix = POSIX_ACL_XATTR_ACCESS,
.list = ext2_xattr_list_acl_access,
.get = ext2_xattr_get_acl_access,
.set = ext2_xattr_set_acl_access,
};
struct xattr_handler ext2_xattr_acl_default_handler = {
- .prefix = XATTR_NAME_ACL_DEFAULT,
+ .prefix = POSIX_ACL_XATTR_DEFAULT,
.list = ext2_xattr_list_acl_default,
.get = ext2_xattr_get_acl_default,
.set = ext2_xattr_set_acl_default,
diff --git a/fs/ext2/acl.h b/fs/ext2/acl.h
index fed96ae81a7..0bde85bafe3 100644
--- a/fs/ext2/acl.h
+++ b/fs/ext2/acl.h
@@ -4,7 +4,7 @@
(C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
*/
-#include <linux/xattr_acl.h>
+#include <linux/posix_acl_xattr.h>
#define EXT2_ACL_VERSION 0x0001
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index 8f0fd726c3f..eed521d22cf 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -147,9 +147,11 @@ extern struct file_operations ext2_dir_operations;
/* file.c */
extern struct inode_operations ext2_file_inode_operations;
extern struct file_operations ext2_file_operations;
+extern struct file_operations ext2_xip_file_operations;
/* inode.c */
extern struct address_space_operations ext2_aops;
+extern struct address_space_operations ext2_aops_xip;
extern struct address_space_operations ext2_nobh_aops;
/* namei.c */
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index f5e86141ec5..a484412fc78 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -55,6 +55,20 @@ struct file_operations ext2_file_operations = {
.sendfile = generic_file_sendfile,
};
+#ifdef CONFIG_EXT2_FS_XIP
+struct file_operations ext2_xip_file_operations = {
+ .llseek = generic_file_llseek,
+ .read = xip_file_read,
+ .write = xip_file_write,
+ .ioctl = ext2_ioctl,
+ .mmap = xip_file_mmap,
+ .open = generic_file_open,
+ .release = ext2_release_file,
+ .fsync = ext2_sync_file,
+ .sendfile = xip_file_sendfile,
+};
+#endif
+
struct inode_operations ext2_file_inode_operations = {
.truncate = ext2_truncate,
#ifdef CONFIG_EXT2_FS_XATTR
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index a50d9db4b6e..53dceb0c659 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -33,6 +33,7 @@
#include <linux/mpage.h>
#include "ext2.h"
#include "acl.h"
+#include "xip.h"
MODULE_AUTHOR("Remy Card and others");
MODULE_DESCRIPTION("Second Extended Filesystem");
@@ -594,6 +595,16 @@ out:
if (err)
goto cleanup;
+ if (ext2_use_xip(inode->i_sb)) {
+ /*
+ * we need to clear the block
+ */
+ err = ext2_clear_xip_target (inode,
+ le32_to_cpu(chain[depth-1].key));
+ if (err)
+ goto cleanup;
+ }
+
if (ext2_splice_branch(inode, iblock, chain, partial, left) < 0)
goto changed;
@@ -691,6 +702,11 @@ struct address_space_operations ext2_aops = {
.writepages = ext2_writepages,
};
+struct address_space_operations ext2_aops_xip = {
+ .bmap = ext2_bmap,
+ .get_xip_page = ext2_get_xip_page,
+};
+
struct address_space_operations ext2_nobh_aops = {
.readpage = ext2_readpage,
.readpages = ext2_readpages,
@@ -910,7 +926,9 @@ void ext2_truncate (struct inode * inode)
iblock = (inode->i_size + blocksize-1)
>> EXT2_BLOCK_SIZE_BITS(inode->i_sb);
- if (test_opt(inode->i_sb, NOBH))
+ if (mapping_is_xip(inode->i_mapping))
+ xip_truncate_page(inode->i_mapping, inode->i_size);
+ else if (test_opt(inode->i_sb, NOBH))
nobh_truncate_page(inode->i_mapping, inode->i_size);
else
block_truncate_page(inode->i_mapping,
@@ -1110,11 +1128,16 @@ void ext2_read_inode (struct inode * inode)
if (S_ISREG(inode->i_mode)) {
inode->i_op = &ext2_file_inode_operations;
- inode->i_fop = &ext2_file_operations;
- if (test_opt(inode->i_sb, NOBH))
+ if (ext2_use_xip(inode->i_sb)) {
+ inode->i_mapping->a_ops = &ext2_aops_xip;
+ inode->i_fop = &ext2_xip_file_operations;
+ } else if (test_opt(inode->i_sb, NOBH)) {
inode->i_mapping->a_ops = &ext2_nobh_aops;
- else
+ inode->i_fop = &ext2_file_operations;
+ } else {
inode->i_mapping->a_ops = &ext2_aops;
+ inode->i_fop = &ext2_file_operations;
+ }
} else if (S_ISDIR(inode->i_mode)) {
inode->i_op = &ext2_dir_inode_operations;
inode->i_fop = &ext2_dir_operations;
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index 3176b3d3ffa..c5513953c82 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -34,6 +34,7 @@
#include "ext2.h"
#include "xattr.h"
#include "acl.h"
+#include "xip.h"
/*
* Couple of helper functions - make the code slightly cleaner.
@@ -127,11 +128,16 @@ static int ext2_create (struct inode * dir, struct dentry * dentry, int mode, st
int err = PTR_ERR(inode);
if (!IS_ERR(inode)) {
inode->i_op = &ext2_file_inode_operations;
- inode->i_fop = &ext2_file_operations;
- if (test_opt(inode->i_sb, NOBH))
+ if (ext2_use_xip(inode->i_sb)) {
+ inode->i_mapping->a_ops = &ext2_aops_xip;
+ inode->i_fop = &ext2_xip_file_operations;
+ } else if (test_opt(inode->i_sb, NOBH)) {
inode->i_mapping->a_ops = &ext2_nobh_aops;
- else
+ inode->i_fop = &ext2_file_operations;
+ } else {
inode->i_mapping->a_ops = &ext2_aops;
+ inode->i_fop = &ext2_file_operations;
+ }
mark_inode_dirty(inode);
err = ext2_add_nondir(dentry, inode);
}
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 661c3d98d94..876e391f287 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -31,6 +31,7 @@
#include "ext2.h"
#include "xattr.h"
#include "acl.h"
+#include "xip.h"
static void ext2_sync_super(struct super_block *sb,
struct ext2_super_block *es);
@@ -257,7 +258,7 @@ enum {
Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid,
Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro,
Opt_nouid32, Opt_check, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov, Opt_nobh,
- Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
+ Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, Opt_xip,
Opt_ignore, Opt_err,
};
@@ -286,6 +287,7 @@ static match_table_t tokens = {
{Opt_nouser_xattr, "nouser_xattr"},
{Opt_acl, "acl"},
{Opt_noacl, "noacl"},
+ {Opt_xip, "xip"},
{Opt_ignore, "grpquota"},
{Opt_ignore, "noquota"},
{Opt_ignore, "quota"},
@@ -397,6 +399,13 @@ static int parse_options (char * options,
printk("EXT2 (no)acl options not supported\n");
break;
#endif
+ case Opt_xip:
+#ifdef CONFIG_EXT2_FS_XIP
+ set_opt (sbi->s_mount_opt, XIP);
+#else
+ printk("EXT2 xip option not supported\n");
+#endif
+ break;
case Opt_ignore:
break;
default:
@@ -640,6 +649,9 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
((EXT2_SB(sb)->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ?
MS_POSIXACL : 0);
+ ext2_xip_verify_sb(sb); /* see if bdev supports xip, unset
+ EXT2_MOUNT_XIP if not */
+
if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV &&
(EXT2_HAS_COMPAT_FEATURE(sb, ~0U) ||
EXT2_HAS_RO_COMPAT_FEATURE(sb, ~0U) ||
@@ -668,6 +680,13 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
blocksize = BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size);
+ if ((ext2_use_xip(sb)) && ((blocksize != PAGE_SIZE) ||
+ (sb->s_blocksize != blocksize))) {
+ if (!silent)
+ printk("XIP: Unsupported blocksize\n");
+ goto failed_mount;
+ }
+
/* If the blocksize doesn't match, re-read the thing.. */
if (sb->s_blocksize != blocksize) {
brelse(bh);
@@ -916,6 +935,7 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data)
{
struct ext2_sb_info * sbi = EXT2_SB(sb);
struct ext2_super_block * es;
+ unsigned long old_mount_opt = sbi->s_mount_opt;
/*
* Allow the "check" option to be passed as a remount option.
@@ -927,6 +947,11 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data)
((sbi->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
es = sbi->s_es;
+ if (((sbi->s_mount_opt & EXT2_MOUNT_XIP) !=
+ (old_mount_opt & EXT2_MOUNT_XIP)) &&
+ invalidate_inodes(sb))
+ ext2_warning(sb, __FUNCTION__, "busy inodes while remounting "\
+ "xip remain in cache (no functional problem)");
if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
return 0;
if (*flags & MS_RDONLY) {
diff --git a/fs/ext2/xip.c b/fs/ext2/xip.c
new file mode 100644
index 00000000000..d44431d1a33
--- /dev/null
+++ b/fs/ext2/xip.c
@@ -0,0 +1,80 @@
+/*
+ * linux/fs/ext2/xip.c
+ *
+ * Copyright (C) 2005 IBM Corporation
+ * Author: Carsten Otte (cotte@de.ibm.com)
+ */
+
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/buffer_head.h>
+#include <linux/ext2_fs_sb.h>
+#include <linux/ext2_fs.h>
+#include "ext2.h"
+#include "xip.h"
+
+static inline int
+__inode_direct_access(struct inode *inode, sector_t sector, unsigned long *data) {
+ BUG_ON(!inode->i_sb->s_bdev->bd_disk->fops->direct_access);
+ return inode->i_sb->s_bdev->bd_disk->fops
+ ->direct_access(inode->i_sb->s_bdev,sector,data);
+}
+
+int
+ext2_clear_xip_target(struct inode *inode, int block) {
+ sector_t sector = block*(PAGE_SIZE/512);
+ unsigned long data;
+ int rc;
+
+ rc = __inode_direct_access(inode, sector, &data);
+ if (rc)
+ return rc;
+ clear_page((void*)data);
+ return 0;
+}
+
+void ext2_xip_verify_sb(struct super_block *sb)
+{
+ struct ext2_sb_info *sbi = EXT2_SB(sb);
+
+ if ((sbi->s_mount_opt & EXT2_MOUNT_XIP)) {
+ if ((sb->s_bdev == NULL) ||
+ sb->s_bdev->bd_disk == NULL ||
+ sb->s_bdev->bd_disk->fops == NULL ||
+ sb->s_bdev->bd_disk->fops->direct_access == NULL) {
+ sbi->s_mount_opt &= (~EXT2_MOUNT_XIP);
+ ext2_warning(sb, __FUNCTION__,
+ "ignoring xip option - not supported by bdev");
+ }
+ }
+}
+
+struct page*
+ext2_get_xip_page(struct address_space *mapping, sector_t blockno,
+ int create)
+{
+ int rc;
+ unsigned long data;
+ struct buffer_head tmp;
+
+ tmp.b_state = 0;
+ tmp.b_blocknr = 0;
+ rc = ext2_get_block(mapping->host, blockno/(PAGE_SIZE/512) , &tmp,
+ create);
+ if (rc)
+ return ERR_PTR(rc);
+ if (tmp.b_blocknr == 0) {
+ /* SPARSE block */
+ BUG_ON(create);
+ return ERR_PTR(-ENODATA);
+ }
+
+ rc = __inode_direct_access
+ (mapping->host,tmp.b_blocknr*(PAGE_SIZE/512) ,&data);
+ if (rc)
+ return ERR_PTR(rc);
+
+ SetPageUptodate(virt_to_page(data));
+ return virt_to_page(data);
+}
diff --git a/fs/ext2/xip.h b/fs/ext2/xip.h
new file mode 100644
index 00000000000..aa85331d6c5
--- /dev/null
+++ b/fs/ext2/xip.h
@@ -0,0 +1,25 @@
+/*
+ * linux/fs/ext2/xip.h
+ *
+ * Copyright (C) 2005 IBM Corporation
+ * Author: Carsten Otte (cotte@de.ibm.com)
+ */
+
+#ifdef CONFIG_EXT2_FS_XIP
+extern void ext2_xip_verify_sb (struct super_block *);
+extern int ext2_clear_xip_target (struct inode *, int);
+
+static inline int ext2_use_xip (struct super_block *sb)
+{
+ struct ext2_sb_info *sbi = EXT2_SB(sb);
+ return (sbi->s_mount_opt & EXT2_MOUNT_XIP);
+}
+struct page* ext2_get_xip_page (struct address_space *, sector_t, int);
+#define mapping_is_xip(map) unlikely(map->a_ops->get_xip_page)
+#else
+#define mapping_is_xip(map) 0
+#define ext2_xip_verify_sb(sb) do { } while (0)
+#define ext2_use_xip(sb) 0
+#define ext2_clear_xip_target(inode, chain) 0
+#define ext2_get_xip_page NULL
+#endif
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index 638c13a26c0..3ac38266fc9 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -393,7 +393,8 @@ ext3_acl_chmod(struct inode *inode)
int retries = 0;
retry:
- handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS);
+ handle = ext3_journal_start(inode,
+ EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
if (IS_ERR(handle)) {
error = PTR_ERR(handle);
ext3_std_error(inode->i_sb, error);
@@ -417,12 +418,12 @@ static size_t
ext3_xattr_list_acl_access(struct inode *inode, char *list, size_t list_len,
const char *name, size_t name_len)
{
- const size_t size = sizeof(XATTR_NAME_ACL_ACCESS);
+ const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
if (!test_opt(inode->i_sb, POSIX_ACL))
return 0;
if (list && size <= list_len)
- memcpy(list, XATTR_NAME_ACL_ACCESS, size);
+ memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
return size;
}
@@ -430,12 +431,12 @@ static size_t
ext3_xattr_list_acl_default(struct inode *inode, char *list, size_t list_len,
const char *name, size_t name_len)
{
- const size_t size = sizeof(XATTR_NAME_ACL_DEFAULT);
+ const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
if (!test_opt(inode->i_sb, POSIX_ACL))
return 0;
if (list && size <= list_len)
- memcpy(list, XATTR_NAME_ACL_DEFAULT, size);
+ memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
return size;
}
@@ -503,7 +504,7 @@ ext3_xattr_set_acl(struct inode *inode, int type, const void *value,
acl = NULL;
retry:
- handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS);
+ handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
if (IS_ERR(handle))
return PTR_ERR(handle);
error = ext3_set_acl(handle, inode, type, acl);
@@ -535,14 +536,14 @@ ext3_xattr_set_acl_default(struct inode *inode, const char *name,
}
struct xattr_handler ext3_xattr_acl_access_handler = {
- .prefix = XATTR_NAME_ACL_ACCESS,
+ .prefix = POSIX_ACL_XATTR_ACCESS,
.list = ext3_xattr_list_acl_access,
.get = ext3_xattr_get_acl_access,
.set = ext3_xattr_set_acl_access,
};
struct xattr_handler ext3_xattr_acl_default_handler = {
- .prefix = XATTR_NAME_ACL_DEFAULT,
+ .prefix = POSIX_ACL_XATTR_DEFAULT,
.list = ext3_xattr_list_acl_default,
.get = ext3_xattr_get_acl_default,
.set = ext3_xattr_set_acl_default,
diff --git a/fs/ext3/acl.h b/fs/ext3/acl.h
index 98af0c0d0ba..92d50b53a93 100644
--- a/fs/ext3/acl.h
+++ b/fs/ext3/acl.h
@@ -4,7 +4,7 @@
(C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
*/
-#include <linux/xattr_acl.h>
+#include <linux/posix_acl_xattr.h>
#define EXT3_ACL_VERSION 0x0001
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 0d5fa73b18d..0b2db4f618c 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -128,7 +128,7 @@ static unsigned long blocks_for_truncate(struct inode *inode)
if (needed > EXT3_MAX_TRANS_DATA)
needed = EXT3_MAX_TRANS_DATA;
- return EXT3_DATA_TRANS_BLOCKS + needed;
+ return EXT3_DATA_TRANS_BLOCKS(inode->i_sb) + needed;
}
/*
@@ -2763,7 +2763,8 @@ int ext3_setattr(struct dentry *dentry, struct iattr *attr)
/* (user+group)*(old+new) structure, inode write (sb,
* inode block, ? - but truncate inode update has it) */
- handle = ext3_journal_start(inode, 4*EXT3_QUOTA_INIT_BLOCKS+3);
+ handle = ext3_journal_start(inode, 2*(EXT3_QUOTA_INIT_BLOCKS(inode->i_sb)+
+ EXT3_QUOTA_DEL_BLOCKS(inode->i_sb))+3);
if (IS_ERR(handle)) {
error = PTR_ERR(handle);
goto err_out;
@@ -2861,7 +2862,7 @@ static int ext3_writepage_trans_blocks(struct inode *inode)
#ifdef CONFIG_QUOTA
/* We know that structure was already allocated during DQUOT_INIT so
* we will be updating only the data blocks + inodes */
- ret += 2*EXT3_QUOTA_TRANS_BLOCKS;
+ ret += 2*EXT3_QUOTA_TRANS_BLOCKS(inode->i_sb);
#endif
return ret;
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 79742d824a0..50378d8ff84 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -932,8 +932,16 @@ static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry,
struct inode *dir = dentry->d_parent->d_inode;
sb = dir->i_sb;
- if (!(frame = dx_probe(dentry, NULL, &hinfo, frames, err)))
- return NULL;
+ /* NFS may look up ".." - look at dx_root directory block */
+ if (namelen > 2 || name[0] != '.'||(name[1] != '.' && name[1] != '\0')){
+ if (!(frame = dx_probe(dentry, NULL, &hinfo, frames, err)))
+ return NULL;
+ } else {
+ frame = frames;
+ frame->bh = NULL; /* for dx_release() */
+ frame->at = (struct dx_entry *)frames; /* hack for zero entry*/
+ dx_set_block(frame->at, 0); /* dx_root block is 0 */
+ }
hash = hinfo.hash;
do {
block = dx_get_block(frame->at);
@@ -1637,9 +1645,9 @@ static int ext3_create (struct inode * dir, struct dentry * dentry, int mode,
int err, retries = 0;
retry:
- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
- 2*EXT3_QUOTA_INIT_BLOCKS);
+ 2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
if (IS_ERR(handle))
return PTR_ERR(handle);
@@ -1671,9 +1679,9 @@ static int ext3_mknod (struct inode * dir, struct dentry *dentry,
return -EINVAL;
retry:
- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
- 2*EXT3_QUOTA_INIT_BLOCKS);
+ 2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
if (IS_ERR(handle))
return PTR_ERR(handle);
@@ -1707,9 +1715,9 @@ static int ext3_mkdir(struct inode * dir, struct dentry * dentry, int mode)
return -EMLINK;
retry:
- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
- 2*EXT3_QUOTA_INIT_BLOCKS);
+ 2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
if (IS_ERR(handle))
return PTR_ERR(handle);
@@ -1998,7 +2006,7 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry)
/* Initialize quotas before so that eventual writes go in
* separate transaction */
DQUOT_INIT(dentry->d_inode);
- handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
+ handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS(dir->i_sb));
if (IS_ERR(handle))
return PTR_ERR(handle);
@@ -2057,7 +2065,7 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry)
/* Initialize quotas before so that eventual writes go
* in separate transaction */
DQUOT_INIT(dentry->d_inode);
- handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
+ handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS(dir->i_sb));
if (IS_ERR(handle))
return PTR_ERR(handle);
@@ -2112,9 +2120,9 @@ static int ext3_symlink (struct inode * dir,
return -ENAMETOOLONG;
retry:
- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5 +
- 2*EXT3_QUOTA_INIT_BLOCKS);
+ 2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
if (IS_ERR(handle))
return PTR_ERR(handle);
@@ -2166,7 +2174,7 @@ static int ext3_link (struct dentry * old_dentry,
return -EMLINK;
retry:
- handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
+ handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
EXT3_INDEX_EXTRA_TRANS_BLOCKS);
if (IS_ERR(handle))
return PTR_ERR(handle);
@@ -2208,7 +2216,8 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
* in separate transaction */
if (new_dentry->d_inode)
DQUOT_INIT(new_dentry->d_inode);
- handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS +
+ handle = ext3_journal_start(old_dir, 2 *
+ EXT3_DATA_TRANS_BLOCKS(old_dir->i_sb) +
EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2);
if (IS_ERR(handle))
return PTR_ERR(handle);
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 545b440a2d2..b4b3e8a3913 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -225,8 +225,16 @@ void __ext3_std_error (struct super_block * sb, const char * function,
int errno)
{
char nbuf[16];
- const char *errstr = ext3_decode_error(sb, errno, nbuf);
+ const char *errstr;
+
+ /* Special case: if the error is EROFS, and we're not already
+ * inside a transaction, then there's really no point in logging
+ * an error. */
+ if (errno == -EROFS && journal_current_handle() == NULL &&
+ (sb->s_flags & MS_RDONLY))
+ return;
+ errstr = ext3_decode_error(sb, errno, nbuf);
printk (KERN_CRIT "EXT3-fs error (device %s) in %s: %s\n",
sb->s_id, function, errstr);
@@ -581,7 +589,7 @@ enum {
Opt_commit, Opt_journal_update, Opt_journal_inum,
Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
- Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0,
+ Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
Opt_ignore, Opt_barrier, Opt_err, Opt_resize,
};
@@ -626,10 +634,10 @@ static match_table_t tokens = {
{Opt_grpjquota, "grpjquota=%s"},
{Opt_jqfmt_vfsold, "jqfmt=vfsold"},
{Opt_jqfmt_vfsv0, "jqfmt=vfsv0"},
- {Opt_ignore, "grpquota"},
- {Opt_ignore, "noquota"},
- {Opt_ignore, "quota"},
- {Opt_ignore, "usrquota"},
+ {Opt_quota, "grpquota"},
+ {Opt_noquota, "noquota"},
+ {Opt_quota, "quota"},
+ {Opt_quota, "usrquota"},
{Opt_barrier, "barrier=%u"},
{Opt_err, NULL},
{Opt_resize, "resize"},
@@ -868,6 +876,7 @@ set_qf_name:
sbi->s_qf_names[qtype] = NULL;
return 0;
}
+ set_opt(sbi->s_mount_opt, QUOTA);
break;
case Opt_offusrjquota:
qtype = USRQUOTA;
@@ -890,6 +899,17 @@ clear_qf_name:
case Opt_jqfmt_vfsv0:
sbi->s_jquota_fmt = QFMT_VFS_V0;
break;
+ case Opt_quota:
+ set_opt(sbi->s_mount_opt, QUOTA);
+ break;
+ case Opt_noquota:
+ if (sb_any_quota_enabled(sb)) {
+ printk(KERN_ERR "EXT3-fs: Cannot change quota "
+ "options when quota turned on.\n");
+ return 0;
+ }
+ clear_opt(sbi->s_mount_opt, QUOTA);
+ break;
#else
case Opt_usrjquota:
case Opt_grpjquota:
@@ -901,6 +921,9 @@ clear_qf_name:
"EXT3-fs: journalled quota options not "
"supported.\n");
break;
+ case Opt_quota:
+ case Opt_noquota:
+ break;
#endif
case Opt_abort:
set_opt(sbi->s_mount_opt, ABORT);
@@ -2230,7 +2253,7 @@ static int ext3_dquot_initialize(struct inode *inode, int type)
int ret, err;
/* We may create quota structure so we need to reserve enough blocks */
- handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS);
+ handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS(inode->i_sb));
if (IS_ERR(handle))
return PTR_ERR(handle);
ret = dquot_initialize(inode, type);
@@ -2246,7 +2269,7 @@ static int ext3_dquot_drop(struct inode *inode)
int ret, err;
/* We may delete quota structure so we need to reserve enough blocks */
- handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS);
+ handle = ext3_journal_start(inode, 2*EXT3_QUOTA_DEL_BLOCKS(inode->i_sb));
if (IS_ERR(handle))
return PTR_ERR(handle);
ret = dquot_drop(inode);
@@ -2264,7 +2287,7 @@ static int ext3_write_dquot(struct dquot *dquot)
inode = dquot_to_inode(dquot);
handle = ext3_journal_start(inode,
- EXT3_QUOTA_TRANS_BLOCKS);
+ EXT3_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
if (IS_ERR(handle))
return PTR_ERR(handle);
ret = dquot_commit(dquot);
@@ -2280,7 +2303,7 @@ static int ext3_acquire_dquot(struct dquot *dquot)
handle_t *handle;
handle = ext3_journal_start(dquot_to_inode(dquot),
- EXT3_QUOTA_INIT_BLOCKS);
+ EXT3_QUOTA_INIT_BLOCKS(dquot->dq_sb));
if (IS_ERR(handle))
return PTR_ERR(handle);
ret = dquot_acquire(dquot);
@@ -2296,7 +2319,7 @@ static int ext3_release_dquot(struct dquot *dquot)
handle_t *handle;
handle = ext3_journal_start(dquot_to_inode(dquot),
- EXT3_QUOTA_INIT_BLOCKS);
+ EXT3_QUOTA_DEL_BLOCKS(dquot->dq_sb));
if (IS_ERR(handle))
return PTR_ERR(handle);
ret = dquot_release(dquot);
@@ -2340,22 +2363,8 @@ static int ext3_write_info(struct super_block *sb, int type)
*/
static int ext3_quota_on_mount(struct super_block *sb, int type)
{
- int err;
- struct dentry *dentry;
- struct qstr name = { .name = EXT3_SB(sb)->s_qf_names[type],
- .hash = 0,
- .len = strlen(EXT3_SB(sb)->s_qf_names[type])};
-
- dentry = lookup_hash(&name, sb->s_root);
- if (IS_ERR(dentry))
- return PTR_ERR(dentry);
- err = vfs_quota_on_mount(type, EXT3_SB(sb)->s_jquota_fmt, dentry);
- /* Now invalidate and put the dentry - quota got its own reference
- * to inode and dentry has at least wrong hash so we had better
- * throw it away */
- d_invalidate(dentry);
- dput(dentry);
- return err;
+ return vfs_quota_on_mount(sb, EXT3_SB(sb)->s_qf_names[type],
+ EXT3_SB(sb)->s_jquota_fmt, type);
}
/*
@@ -2367,6 +2376,8 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id,
int err;
struct nameidata nd;
+ if (!test_opt(sb, QUOTA))
+ return -EINVAL;
/* Not journalling quota? */
if (!EXT3_SB(sb)->s_qf_names[USRQUOTA] &&
!EXT3_SB(sb)->s_qf_names[GRPQUOTA])
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index 4cbc6d0212d..3f9dfa643b1 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -1044,7 +1044,7 @@ ext3_xattr_set(struct inode *inode, int name_index, const char *name,
int error, retries = 0;
retry:
- handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS);
+ handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
if (IS_ERR(handle)) {
error = PTR_ERR(handle);
} else {
diff --git a/fs/file_table.c b/fs/file_table.c
index 03d83cb686b..fa7849fae13 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -63,42 +63,45 @@ static inline void file_free(struct file *f)
*/
struct file *get_empty_filp(void)
{
-static int old_max;
+ static int old_max;
struct file * f;
/*
* Privileged users can go above max_files
*/
- if (files_stat.nr_files < files_stat.max_files ||
- capable(CAP_SYS_ADMIN)) {
- f = kmem_cache_alloc(filp_cachep, GFP_KERNEL);
- if (f) {
- memset(f, 0, sizeof(*f));
- if (security_file_alloc(f)) {
- file_free(f);
- goto fail;
- }
- eventpoll_init_file(f);
- atomic_set(&f->f_count, 1);
- f->f_uid = current->fsuid;
- f->f_gid = current->fsgid;
- rwlock_init(&f->f_owner.lock);
- /* f->f_version: 0 */
- INIT_LIST_HEAD(&f->f_list);
- f->f_maxcount = INT_MAX;
- return f;
- }
- }
-
+ if (files_stat.nr_files >= files_stat.max_files &&
+ !capable(CAP_SYS_ADMIN))
+ goto over;
+
+ f = kmem_cache_alloc(filp_cachep, GFP_KERNEL);
+ if (f == NULL)
+ goto fail;
+
+ memset(f, 0, sizeof(*f));
+ if (security_file_alloc(f))
+ goto fail_sec;
+
+ eventpoll_init_file(f);
+ atomic_set(&f->f_count, 1);
+ f->f_uid = current->fsuid;
+ f->f_gid = current->fsgid;
+ rwlock_init(&f->f_owner.lock);
+ /* f->f_version: 0 */
+ INIT_LIST_HEAD(&f->f_list);
+ f->f_maxcount = INT_MAX;
+ return f;
+
+over:
/* Ran out of filps - report that */
- if (files_stat.max_files >= old_max) {
+ if (files_stat.nr_files > old_max) {
printk(KERN_INFO "VFS: file-max limit %d reached\n",
files_stat.max_files);
- old_max = files_stat.max_files;
- } else {
- /* Big problems... */
- printk(KERN_WARNING "VFS: filp allocation failed\n");
+ old_max = files_stat.nr_files;
}
+ goto fail;
+
+fail_sec:
+ file_free(f);
fail:
return NULL;
}
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 8e050fa5821..e94ab398b71 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -485,32 +485,6 @@ static void set_sb_syncing(int val)
spin_unlock(&sb_lock);
}
-/*
- * Find a superblock with inodes that need to be synced
- */
-static struct super_block *get_super_to_sync(void)
-{
- struct super_block *sb;
-restart:
- spin_lock(&sb_lock);
- sb = sb_entry(super_blocks.prev);
- for (; sb != sb_entry(&super_blocks); sb = sb_entry(sb->s_list.prev)) {
- if (sb->s_syncing)
- continue;
- sb->s_syncing = 1;
- sb->s_count++;
- spin_unlock(&sb_lock);
- down_read(&sb->s_umount);
- if (!sb->s_root) {
- drop_super(sb);
- goto restart;
- }
- return sb;
- }
- spin_unlock(&sb_lock);
- return NULL;
-}
-
/**
* sync_inodes - writes all inodes to disk
* @wait: wait for completion
@@ -530,23 +504,39 @@ restart:
* outstanding dirty inodes, the writeback goes block-at-a-time within the
* filesystem's write_inode(). This is extremely slow.
*/
-void sync_inodes(int wait)
+static void __sync_inodes(int wait)
{
struct super_block *sb;
- set_sb_syncing(0);
- while ((sb = get_super_to_sync()) != NULL) {
- sync_inodes_sb(sb, 0);
- sync_blockdev(sb->s_bdev);
- drop_super(sb);
+ spin_lock(&sb_lock);
+restart:
+ list_for_each_entry(sb, &super_blocks, s_list) {
+ if (sb->s_syncing)
+ continue;
+ sb->s_syncing = 1;
+ sb->s_count++;
+ spin_unlock(&sb_lock);
+ down_read(&sb->s_umount);
+ if (sb->s_root) {
+ sync_inodes_sb(sb, wait);
+ sync_blockdev(sb->s_bdev);
+ }
+ up_read(&sb->s_umount);
+ spin_lock(&sb_lock);
+ if (__put_super_and_need_restart(sb))
+ goto restart;
}
+ spin_unlock(&sb_lock);
+}
+
+void sync_inodes(int wait)
+{
+ set_sb_syncing(0);
+ __sync_inodes(0);
+
if (wait) {
set_sb_syncing(0);
- while ((sb = get_super_to_sync()) != NULL) {
- sync_inodes_sb(sb, 1);
- sync_blockdev(sb->s_bdev);
- drop_super(sb);
- }
+ __sync_inodes(1);
}
}
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 14a0d339d03..4bf43ea87c4 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -23,7 +23,6 @@
#include "kern_util.h"
#include "kern.h"
#include "user_util.h"
-#include "2_5compat.h"
#include "init.h"
struct hostfs_inode_info {
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 2af3338f891..3a9b6d179cb 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -122,6 +122,9 @@ hugetlb_get_unmapped_area(struct file *file, unsigned long addr,
start_addr = mm->free_area_cache;
+ if (len <= mm->cached_hole_size)
+ start_addr = TASK_UNMAPPED_BASE;
+
full_search:
addr = ALIGN(start_addr, HPAGE_SIZE);
diff --git a/fs/inode.c b/fs/inode.c
index 801fe7f3628..1f9a3a2b89b 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -500,7 +500,7 @@ repeat:
continue;
if (!test(inode, data))
continue;
- if (inode->i_state & (I_FREEING|I_CLEAR)) {
+ if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)) {
__wait_on_freeing_inode(inode);
goto repeat;
}
@@ -525,7 +525,7 @@ repeat:
continue;
if (inode->i_sb != sb)
continue;
- if (inode->i_state & (I_FREEING|I_CLEAR)) {
+ if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)) {
__wait_on_freeing_inode(inode);
goto repeat;
}
@@ -727,7 +727,7 @@ EXPORT_SYMBOL(iunique);
struct inode *igrab(struct inode *inode)
{
spin_lock(&inode_lock);
- if (!(inode->i_state & I_FREEING))
+ if (!(inode->i_state & (I_FREEING|I_WILL_FREE)))
__iget(inode);
else
/*
@@ -1024,17 +1024,21 @@ static void generic_forget_inode(struct inode *inode)
if (!(inode->i_state & (I_DIRTY|I_LOCK)))
list_move(&inode->i_list, &inode_unused);
inodes_stat.nr_unused++;
- spin_unlock(&inode_lock);
- if (!sb || (sb->s_flags & MS_ACTIVE))
+ if (!sb || (sb->s_flags & MS_ACTIVE)) {
+ spin_unlock(&inode_lock);
return;
+ }
+ inode->i_state |= I_WILL_FREE;
+ spin_unlock(&inode_lock);
write_inode_now(inode, 1);
spin_lock(&inode_lock);
+ inode->i_state &= ~I_WILL_FREE;
inodes_stat.nr_unused--;
hlist_del_init(&inode->i_hash);
}
list_del_init(&inode->i_list);
list_del_init(&inode->i_sb_list);
- inode->i_state|=I_FREEING;
+ inode->i_state |= I_FREEING;
inodes_stat.nr_inodes--;
spin_unlock(&inode_lock);
if (inode->i_data.nrpages)
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index 6030956b894..7901ac9f97a 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -193,12 +193,17 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp,
/* Handle everything else. Do name translation if there
is no Rock Ridge NM field. */
- if (sbi->s_unhide == 'n') {
- /* Do not report hidden or associated files */
- if (de->flags[-sbi->s_high_sierra] & 5) {
- filp->f_pos += de_len;
- continue;
- }
+
+ /*
+ * Do not report hidden files if so instructed, or associated
+ * files unless instructed to do so
+ */
+ if ((sbi->s_hide == 'y' &&
+ (de->flags[-sbi->s_high_sierra] & 1)) ||
+ (sbi->s_showassoc =='n' &&
+ (de->flags[-sbi->s_high_sierra] & 4))) {
+ filp->f_pos += de_len;
+ continue;
}
map = 1;
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index abd7b12eeca..1652de1b6cb 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -28,11 +28,6 @@
#define BEQUIET
-#ifdef LEAK_CHECK
-static int check_malloc;
-static int check_bread;
-#endif
-
static int isofs_hashi(struct dentry *parent, struct qstr *qstr);
static int isofs_hash(struct dentry *parent, struct qstr *qstr);
static int isofs_dentry_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b);
@@ -55,11 +50,6 @@ static void isofs_put_super(struct super_block *sb)
}
#endif
-#ifdef LEAK_CHECK
- printk("Outstanding mallocs:%d, outstanding buffers: %d\n",
- check_malloc, check_bread);
-#endif
-
kfree(sbi);
sb->s_fs_info = NULL;
return;
@@ -73,7 +63,7 @@ static kmem_cache_t *isofs_inode_cachep;
static struct inode *isofs_alloc_inode(struct super_block *sb)
{
struct iso_inode_info *ei;
- ei = (struct iso_inode_info *)kmem_cache_alloc(isofs_inode_cachep, SLAB_KERNEL);
+ ei = kmem_cache_alloc(isofs_inode_cachep, SLAB_KERNEL);
if (!ei)
return NULL;
return &ei->vfs_inode;
@@ -84,9 +74,9 @@ static void isofs_destroy_inode(struct inode *inode)
kmem_cache_free(isofs_inode_cachep, ISOFS_I(inode));
}
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
{
- struct iso_inode_info *ei = (struct iso_inode_info *) foo;
+ struct iso_inode_info *ei = foo;
if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
SLAB_CTOR_CONSTRUCTOR)
@@ -107,7 +97,8 @@ static int init_inodecache(void)
static void destroy_inodecache(void)
{
if (kmem_cache_destroy(isofs_inode_cachep))
- printk(KERN_INFO "iso_inode_cache: not all structures were freed\n");
+ printk(KERN_INFO "iso_inode_cache: not all structures were "
+ "freed\n");
}
static int isofs_remount(struct super_block *sb, int *flags, char *data)
@@ -144,7 +135,7 @@ static struct dentry_operations isofs_dentry_ops[] = {
{
.d_hash = isofs_hashi_ms,
.d_compare = isofs_dentry_cmpi_ms,
- }
+ },
#endif
};
@@ -153,7 +144,8 @@ struct iso9660_options{
char rock;
char joliet;
char cruft;
- char unhide;
+ char hide;
+ char showassoc;
char nocompress;
unsigned char check;
unsigned int blocksize;
@@ -219,8 +211,8 @@ isofs_hashi_common(struct dentry *dentry, struct qstr *qstr, int ms)
/*
* Case insensitive compare of two isofs names.
*/
-static int
-isofs_dentry_cmpi_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int ms)
+static int isofs_dentry_cmpi_common(struct dentry *dentry, struct qstr *a,
+ struct qstr *b, int ms)
{
int alen, blen;
@@ -243,8 +235,8 @@ isofs_dentry_cmpi_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int
/*
* Case sensitive compare of two isofs names.
*/
-static int
-isofs_dentry_cmp_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int ms)
+static int isofs_dentry_cmp_common(struct dentry *dentry, struct qstr *a,
+ struct qstr *b, int ms)
{
int alen, blen;
@@ -318,13 +310,15 @@ enum {
Opt_block, Opt_check_r, Opt_check_s, Opt_cruft, Opt_gid, Opt_ignore,
Opt_iocharset, Opt_map_a, Opt_map_n, Opt_map_o, Opt_mode, Opt_nojoliet,
Opt_norock, Opt_sb, Opt_session, Opt_uid, Opt_unhide, Opt_utf8, Opt_err,
- Opt_nocompress,
+ Opt_nocompress, Opt_hide, Opt_showassoc,
};
static match_table_t tokens = {
{Opt_norock, "norock"},
{Opt_nojoliet, "nojoliet"},
{Opt_unhide, "unhide"},
+ {Opt_hide, "hide"},
+ {Opt_showassoc, "showassoc"},
{Opt_cruft, "cruft"},
{Opt_utf8, "utf8"},
{Opt_iocharset, "iocharset=%s"},
@@ -356,7 +350,7 @@ static match_table_t tokens = {
{Opt_err, NULL}
};
-static int parse_options(char *options, struct iso9660_options * popt)
+static int parse_options(char *options, struct iso9660_options *popt)
{
char *p;
int option;
@@ -365,7 +359,8 @@ static int parse_options(char *options, struct iso9660_options * popt)
popt->rock = 'y';
popt->joliet = 'y';
popt->cruft = 'n';
- popt->unhide = 'n';
+ popt->hide = 'n';
+ popt->showassoc = 'n';
popt->check = 'u'; /* unset */
popt->nocompress = 0;
popt->blocksize = 1024;
@@ -398,8 +393,12 @@ static int parse_options(char *options, struct iso9660_options * popt)
case Opt_nojoliet:
popt->joliet = 'n';
break;
+ case Opt_hide:
+ popt->hide = 'y';
+ break;
case Opt_unhide:
- popt->unhide = 'y';
+ case Opt_showassoc:
+ popt->showassoc = 'y';
break;
case Opt_cruft:
popt->cruft = 'y';
@@ -493,7 +492,7 @@ static int parse_options(char *options, struct iso9660_options * popt)
*/
#define WE_OBEY_THE_WRITTEN_STANDARDS 1
-static unsigned int isofs_get_last_session(struct super_block *sb,s32 session )
+static unsigned int isofs_get_last_session(struct super_block *sb, s32 session)
{
struct cdrom_multisession ms_info;
unsigned int vol_desc_start;
@@ -518,7 +517,8 @@ static unsigned int isofs_get_last_session(struct super_block *sb,s32 session )
printk(KERN_ERR "Invalid session number or type of track\n");
}
i = ioctl_by_bdev(bdev, CDROMMULTISESSION, (unsigned long) &ms_info);
- if(session > 0) printk(KERN_ERR "Invalid session number\n");
+ if (session > 0)
+ printk(KERN_ERR "Invalid session number\n");
#if 0
printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i);
if (i==0) {
@@ -557,13 +557,13 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent)
struct iso9660_options opt;
struct isofs_sb_info * sbi;
- sbi = kmalloc(sizeof(struct isofs_sb_info), GFP_KERNEL);
+ sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
if (!sbi)
return -ENOMEM;
s->s_fs_info = sbi;
- memset(sbi, 0, sizeof(struct isofs_sb_info));
+ memset(sbi, 0, sizeof(*sbi));
- if (!parse_options((char *) data, &opt))
+ if (!parse_options((char *)data, &opt))
goto out_freesbi;
/*
@@ -792,7 +792,8 @@ root_found:
sbi->s_rock = (opt.rock == 'y' ? 2 : 0);
sbi->s_rock_offset = -1; /* initial offset, will guess until SP is found*/
sbi->s_cruft = opt.cruft;
- sbi->s_unhide = opt.unhide;
+ sbi->s_hide = opt.hide;
+ sbi->s_showassoc = opt.showassoc;
sbi->s_uid = opt.uid;
sbi->s_gid = opt.gid;
sbi->s_utf8 = opt.utf8;
@@ -1002,7 +1003,6 @@ int isofs_get_blocks(struct inode *inode, sector_t iblock_s,
rv++;
}
-
abort:
unlock_kernel();
return rv;
@@ -1014,7 +1014,7 @@ abort:
static int isofs_get_block(struct inode *inode, sector_t iblock,
struct buffer_head *bh_result, int create)
{
- if ( create ) {
+ if (create) {
printk("isofs_get_block: Kernel tries to allocate a block\n");
return -EROFS;
}
@@ -1061,19 +1061,17 @@ static struct address_space_operations isofs_aops = {
static inline void test_and_set_uid(uid_t *p, uid_t value)
{
- if(value) {
+ if (value)
*p = value;
- }
}
static inline void test_and_set_gid(gid_t *p, gid_t value)
{
- if(value) {
+ if (value)
*p = value;
- }
}
-static int isofs_read_level3_size(struct inode * inode)
+static int isofs_read_level3_size(struct inode *inode)
{
unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
int high_sierra = ISOFS_SB(inode->i_sb)->s_high_sierra;
@@ -1136,7 +1134,7 @@ static int isofs_read_level3_size(struct inode * inode)
bh = sb_bread(inode->i_sb, block);
if (!bh)
goto out_noread;
- memcpy((void *) tmpde + slop, bh->b_data, offset);
+ memcpy((void *)tmpde+slop, bh->b_data, offset);
}
de = tmpde;
}
@@ -1150,12 +1148,11 @@ static int isofs_read_level3_size(struct inode * inode)
more_entries = de->flags[-high_sierra] & 0x80;
i++;
- if(i > 100)
+ if (i > 100)
goto out_toomany;
- } while(more_entries);
+ } while (more_entries);
out:
- if (tmpde)
- kfree(tmpde);
+ kfree(tmpde);
if (bh)
brelse(bh);
return 0;
@@ -1179,7 +1176,7 @@ out_toomany:
goto out;
}
-static void isofs_read_inode(struct inode * inode)
+static void isofs_read_inode(struct inode *inode)
{
struct super_block *sb = inode->i_sb;
struct isofs_sb_info *sbi = ISOFS_SB(sb);
@@ -1249,7 +1246,7 @@ static void isofs_read_inode(struct inode * inode)
ei->i_format_parm[2] = 0;
ei->i_section_size = isonum_733 (de->size);
- if(de->flags[-high_sierra] & 0x80) {
+ if (de->flags[-high_sierra] & 0x80) {
if(isofs_read_level3_size(inode)) goto fail;
} else {
ei->i_next_section_block = 0;
@@ -1336,16 +1333,16 @@ static void isofs_read_inode(struct inode * inode)
/* XXX - parse_rock_ridge_inode() had already set i_rdev. */
init_special_inode(inode, inode->i_mode, inode->i_rdev);
- out:
+out:
if (tmpde)
kfree(tmpde);
if (bh)
brelse(bh);
return;
- out_badread:
+out_badread:
printk(KERN_WARNING "ISOFS: unable to read i-node block\n");
- fail:
+fail:
make_bad_inode(inode);
goto out;
}
@@ -1394,11 +1391,8 @@ struct inode *isofs_iget(struct super_block *sb,
hashval = (block << sb->s_blocksize_bits) | offset;
- inode = iget5_locked(sb,
- hashval,
- &isofs_iget5_test,
- &isofs_iget5_set,
- &data);
+ inode = iget5_locked(sb, hashval, &isofs_iget5_test,
+ &isofs_iget5_set, &data);
if (inode && (inode->i_state & I_NEW)) {
sb->s_op->read_inode(inode);
@@ -1408,36 +1402,6 @@ struct inode *isofs_iget(struct super_block *sb,
return inode;
}
-#ifdef LEAK_CHECK
-#undef malloc
-#undef free_s
-#undef sb_bread
-#undef brelse
-
-void * leak_check_malloc(unsigned int size){
- void * tmp;
- check_malloc++;
- tmp = kmalloc(size, GFP_KERNEL);
- return tmp;
-}
-
-void leak_check_free_s(void * obj, int size){
- check_malloc--;
- return kfree(obj);
-}
-
-struct buffer_head * leak_check_bread(struct super_block *sb, int block){
- check_bread++;
- return sb_bread(sb, block);
-}
-
-void leak_check_brelse(struct buffer_head * bh){
- check_bread--;
- return brelse(bh);
-}
-
-#endif
-
static struct super_block *isofs_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data)
{
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h
index 9ce7b51fb61..38c75151fc6 100644
--- a/fs/isofs/isofs.h
+++ b/fs/isofs/isofs.h
@@ -47,6 +47,8 @@ struct isofs_sb_info {
unsigned char s_nosuid;
unsigned char s_nodev;
unsigned char s_nocompress;
+ unsigned char s_hide;
+ unsigned char s_showassoc;
mode_t s_mode;
gid_t s_gid;
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c
index 690edf37173..e37e82b7cbf 100644
--- a/fs/isofs/namei.c
+++ b/fs/isofs/namei.c
@@ -131,14 +131,16 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry,
}
/*
- * Skip hidden or associated files unless unhide is set
+ * Skip hidden or associated files unless hide or showassoc,
+ * respectively, is set
*/
match = 0;
if (dlen > 0 &&
- (!(de->flags[-sbi->s_high_sierra] & 5)
- || sbi->s_unhide == 'y'))
- {
- match = (isofs_cmp(dentry,dpnt,dlen) == 0);
+ (sbi->s_hide =='n' ||
+ (!(de->flags[-sbi->s_high_sierra] & 1))) &&
+ (sbi->s_showassoc =='y' ||
+ (!(de->flags[-sbi->s_high_sierra] & 4)))) {
+ match = (isofs_cmp(dentry, dpnt, dlen) == 0);
}
if (match) {
isofs_normalize_block_and_offset(de,
@@ -146,11 +148,11 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry,
&offset_saved);
*block_rv = block_saved;
*offset_rv = offset_saved;
- if (bh) brelse(bh);
+ brelse(bh);
return 1;
}
}
- if (bh) brelse(bh);
+ brelse(bh);
return 0;
}
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index 089e79c6558..4326cb47f8f 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -13,352 +13,542 @@
#include "isofs.h"
#include "rock.h"
-/* These functions are designed to read the system areas of a directory record
+/*
+ * These functions are designed to read the system areas of a directory record
* and extract relevant information. There are different functions provided
* depending upon what information we need at the time. One function fills
* out an inode structure, a second one extracts a filename, a third one
* returns a symbolic link name, and a fourth one returns the extent number
- * for the file. */
-
-#define SIG(A,B) ((A) | ((B) << 8)) /* isonum_721() */
-
-
-/* This is a way of ensuring that we have something in the system
- use fields that is compatible with Rock Ridge */
-#define CHECK_SP(FAIL) \
- if(rr->u.SP.magic[0] != 0xbe) FAIL; \
- if(rr->u.SP.magic[1] != 0xef) FAIL; \
- ISOFS_SB(inode->i_sb)->s_rock_offset=rr->u.SP.skip;
-/* We define a series of macros because each function must do exactly the
- same thing in certain places. We use the macros to ensure that everything
- is done correctly */
-
-#define CONTINUE_DECLS \
- int cont_extent = 0, cont_offset = 0, cont_size = 0; \
- void *buffer = NULL
-
-#define CHECK_CE \
- {cont_extent = isonum_733(rr->u.CE.extent); \
- cont_offset = isonum_733(rr->u.CE.offset); \
- cont_size = isonum_733(rr->u.CE.size);}
-
-#define SETUP_ROCK_RIDGE(DE,CHR,LEN) \
- {LEN= sizeof(struct iso_directory_record) + DE->name_len[0]; \
- if(LEN & 1) LEN++; \
- CHR = ((unsigned char *) DE) + LEN; \
- LEN = *((unsigned char *) DE) - LEN; \
- if (LEN<0) LEN=0; \
- if (ISOFS_SB(inode->i_sb)->s_rock_offset!=-1) \
- { \
- LEN-=ISOFS_SB(inode->i_sb)->s_rock_offset; \
- CHR+=ISOFS_SB(inode->i_sb)->s_rock_offset; \
- if (LEN<0) LEN=0; \
- } \
-}
-
-#define MAYBE_CONTINUE(LABEL,DEV) \
- {if (buffer) { kfree(buffer); buffer = NULL; } \
- if (cont_extent){ \
- int block, offset, offset1; \
- struct buffer_head * pbh; \
- buffer = kmalloc(cont_size,GFP_KERNEL); \
- if (!buffer) goto out; \
- block = cont_extent; \
- offset = cont_offset; \
- offset1 = 0; \
- pbh = sb_bread(DEV->i_sb, block); \
- if(pbh){ \
- if (offset > pbh->b_size || offset + cont_size > pbh->b_size){ \
- brelse(pbh); \
- goto out; \
- } \
- memcpy(buffer + offset1, pbh->b_data + offset, cont_size - offset1); \
- brelse(pbh); \
- chr = (unsigned char *) buffer; \
- len = cont_size; \
- cont_extent = 0; \
- cont_size = 0; \
- cont_offset = 0; \
- goto LABEL; \
- } \
- printk("Unable to read rock-ridge attributes\n"); \
- }}
-
-/* return length of name field; 0: not found, -1: to be ignored */
-int get_rock_ridge_filename(struct iso_directory_record * de,
- char * retname, struct inode * inode)
+ * for the file.
+ */
+
+#define SIG(A,B) ((A) | ((B) << 8)) /* isonum_721() */
+
+struct rock_state {
+ void *buffer;
+ unsigned char *chr;
+ int len;
+ int cont_size;
+ int cont_extent;
+ int cont_offset;
+ struct inode *inode;
+};
+
+/*
+ * This is a way of ensuring that we have something in the system
+ * use fields that is compatible with Rock Ridge. Return zero on success.
+ */
+
+static int check_sp(struct rock_ridge *rr, struct inode *inode)
{
- int len;
- unsigned char * chr;
- CONTINUE_DECLS;
- int retnamlen = 0, truncate=0;
-
- if (!ISOFS_SB(inode->i_sb)->s_rock) return 0;
- *retname = 0;
-
- SETUP_ROCK_RIDGE(de, chr, len);
- repeat:
- {
- struct rock_ridge * rr;
- int sig;
-
- while (len > 2){ /* There may be one byte for padding somewhere */
- rr = (struct rock_ridge *) chr;
- if (rr->len < 3) goto out; /* Something got screwed up here */
- sig = isonum_721(chr);
- chr += rr->len;
- len -= rr->len;
- if (len < 0) goto out; /* corrupted isofs */
-
- switch(sig){
- case SIG('R','R'):
- if((rr->u.RR.flags[0] & RR_NM) == 0) goto out;
- break;
- case SIG('S','P'):
- CHECK_SP(goto out);
- break;
- case SIG('C','E'):
- CHECK_CE;
- break;
- case SIG('N','M'):
- if (truncate) break;
- if (rr->len < 5) break;
- /*
- * If the flags are 2 or 4, this indicates '.' or '..'.
- * We don't want to do anything with this, because it
- * screws up the code that calls us. We don't really
- * care anyways, since we can just use the non-RR
- * name.
- */
- if (rr->u.NM.flags & 6) {
- break;
+ if (rr->u.SP.magic[0] != 0xbe)
+ return -1;
+ if (rr->u.SP.magic[1] != 0xef)
+ return -1;
+ ISOFS_SB(inode->i_sb)->s_rock_offset = rr->u.SP.skip;
+ return 0;
+}
+
+static void setup_rock_ridge(struct iso_directory_record *de,
+ struct inode *inode, struct rock_state *rs)
+{
+ rs->len = sizeof(struct iso_directory_record) + de->name_len[0];
+ if (rs->len & 1)
+ (rs->len)++;
+ rs->chr = (unsigned char *)de + rs->len;
+ rs->len = *((unsigned char *)de) - rs->len;
+ if (rs->len < 0)
+ rs->len = 0;
+
+ if (ISOFS_SB(inode->i_sb)->s_rock_offset != -1) {
+ rs->len -= ISOFS_SB(inode->i_sb)->s_rock_offset;
+ rs->chr += ISOFS_SB(inode->i_sb)->s_rock_offset;
+ if (rs->len < 0)
+ rs->len = 0;
+ }
+}
+
+static void init_rock_state(struct rock_state *rs, struct inode *inode)
+{
+ memset(rs, 0, sizeof(*rs));
+ rs->inode = inode;
+}
+
+/*
+ * Returns 0 if the caller should continue scanning, 1 if the scan must end
+ * and -ve on error.
+ */
+static int rock_continue(struct rock_state *rs)
+{
+ int ret = 1;
+ int blocksize = 1 << rs->inode->i_blkbits;
+ const int min_de_size = offsetof(struct rock_ridge, u);
+
+ kfree(rs->buffer);
+ rs->buffer = NULL;
+
+ if ((unsigned)rs->cont_offset > blocksize - min_de_size ||
+ (unsigned)rs->cont_size > blocksize ||
+ (unsigned)(rs->cont_offset + rs->cont_size) > blocksize) {
+ printk(KERN_NOTICE "rock: corrupted directory entry. "
+ "extent=%d, offset=%d, size=%d\n",
+ rs->cont_extent, rs->cont_offset, rs->cont_size);
+ ret = -EIO;
+ goto out;
}
- if (rr->u.NM.flags & ~1) {
- printk("Unsupported NM flag settings (%d)\n",rr->u.NM.flags);
- break;
+ if (rs->cont_extent) {
+ struct buffer_head *bh;
+
+ rs->buffer = kmalloc(rs->cont_size, GFP_KERNEL);
+ if (!rs->buffer) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ ret = -EIO;
+ bh = sb_bread(rs->inode->i_sb, rs->cont_extent);
+ if (bh) {
+ memcpy(rs->buffer, bh->b_data + rs->cont_offset,
+ rs->cont_size);
+ put_bh(bh);
+ rs->chr = rs->buffer;
+ rs->len = rs->cont_size;
+ rs->cont_extent = 0;
+ rs->cont_size = 0;
+ rs->cont_offset = 0;
+ return 0;
+ }
+ printk("Unable to read rock-ridge attributes\n");
+ }
+out:
+ kfree(rs->buffer);
+ rs->buffer = NULL;
+ return ret;
+}
+
+/*
+ * We think there's a record of type `sig' at rs->chr. Parse the signature
+ * and make sure that there's really room for a record of that type.
+ */
+static int rock_check_overflow(struct rock_state *rs, int sig)
+{
+ int len;
+
+ switch (sig) {
+ case SIG('S', 'P'):
+ len = sizeof(struct SU_SP_s);
+ break;
+ case SIG('C', 'E'):
+ len = sizeof(struct SU_CE_s);
+ break;
+ case SIG('E', 'R'):
+ len = sizeof(struct SU_ER_s);
+ break;
+ case SIG('R', 'R'):
+ len = sizeof(struct RR_RR_s);
+ break;
+ case SIG('P', 'X'):
+ len = sizeof(struct RR_PX_s);
+ break;
+ case SIG('P', 'N'):
+ len = sizeof(struct RR_PN_s);
+ break;
+ case SIG('S', 'L'):
+ len = sizeof(struct RR_SL_s);
+ break;
+ case SIG('N', 'M'):
+ len = sizeof(struct RR_NM_s);
+ break;
+ case SIG('C', 'L'):
+ len = sizeof(struct RR_CL_s);
+ break;
+ case SIG('P', 'L'):
+ len = sizeof(struct RR_PL_s);
+ break;
+ case SIG('T', 'F'):
+ len = sizeof(struct RR_TF_s);
+ break;
+ case SIG('Z', 'F'):
+ len = sizeof(struct RR_ZF_s);
+ break;
+ default:
+ len = 0;
+ break;
}
- if((strlen(retname) + rr->len - 5) >= 254) {
- truncate = 1;
- break;
+ len += offsetof(struct rock_ridge, u);
+ if (len > rs->len) {
+ printk(KERN_NOTICE "rock: directory entry would overflow "
+ "storage\n");
+ printk(KERN_NOTICE "rock: sig=0x%02x, size=%d, remaining=%d\n",
+ sig, len, rs->len);
+ return -EIO;
+ }
+ return 0;
+}
+
+/*
+ * return length of name field; 0: not found, -1: to be ignored
+ */
+int get_rock_ridge_filename(struct iso_directory_record *de,
+ char *retname, struct inode *inode)
+{
+ struct rock_state rs;
+ struct rock_ridge *rr;
+ int sig;
+ int retnamlen = 0;
+ int truncate = 0;
+ int ret = 0;
+
+ if (!ISOFS_SB(inode->i_sb)->s_rock)
+ return 0;
+ *retname = 0;
+
+ init_rock_state(&rs, inode);
+ setup_rock_ridge(de, inode, &rs);
+repeat:
+
+ while (rs.len > 2) { /* There may be one byte for padding somewhere */
+ rr = (struct rock_ridge *)rs.chr;
+ if (rr->len < 3)
+ goto out; /* Something got screwed up here */
+ sig = isonum_721(rs.chr);
+ if (rock_check_overflow(&rs, sig))
+ goto eio;
+ rs.chr += rr->len;
+ rs.len -= rr->len;
+ if (rs.len < 0)
+ goto eio; /* corrupted isofs */
+
+ switch (sig) {
+ case SIG('R', 'R'):
+ if ((rr->u.RR.flags[0] & RR_NM) == 0)
+ goto out;
+ break;
+ case SIG('S', 'P'):
+ if (check_sp(rr, inode))
+ goto out;
+ break;
+ case SIG('C', 'E'):
+ rs.cont_extent = isonum_733(rr->u.CE.extent);
+ rs.cont_offset = isonum_733(rr->u.CE.offset);
+ rs.cont_size = isonum_733(rr->u.CE.size);
+ break;
+ case SIG('N', 'M'):
+ if (truncate)
+ break;
+ if (rr->len < 5)
+ break;
+ /*
+ * If the flags are 2 or 4, this indicates '.' or '..'.
+ * We don't want to do anything with this, because it
+ * screws up the code that calls us. We don't really
+ * care anyways, since we can just use the non-RR
+ * name.
+ */
+ if (rr->u.NM.flags & 6)
+ break;
+
+ if (rr->u.NM.flags & ~1) {
+ printk("Unsupported NM flag settings (%d)\n",
+ rr->u.NM.flags);
+ break;
+ }
+ if ((strlen(retname) + rr->len - 5) >= 254) {
+ truncate = 1;
+ break;
+ }
+ strncat(retname, rr->u.NM.name, rr->len - 5);
+ retnamlen += rr->len - 5;
+ break;
+ case SIG('R', 'E'):
+ kfree(rs.buffer);
+ return -1;
+ default:
+ break;
+ }
}
- strncat(retname, rr->u.NM.name, rr->len - 5);
- retnamlen += rr->len - 5;
- break;
- case SIG('R','E'):
- if (buffer) kfree(buffer);
- return -1;
- default:
- break;
- }
- }
- }
- MAYBE_CONTINUE(repeat,inode);
- if (buffer) kfree(buffer);
- return retnamlen; /* If 0, this file did not have a NM field */
- out:
- if(buffer) kfree(buffer);
- return 0;
+ ret = rock_continue(&rs);
+ if (ret == 0)
+ goto repeat;
+ if (ret == 1)
+ return retnamlen; /* If 0, this file did not have a NM field */
+out:
+ kfree(rs.buffer);
+ return ret;
+eio:
+ ret = -EIO;
+ goto out;
}
static int
parse_rock_ridge_inode_internal(struct iso_directory_record *de,
struct inode *inode, int regard_xa)
{
- int len;
- unsigned char * chr;
- int symlink_len = 0;
- CONTINUE_DECLS;
-
- if (!ISOFS_SB(inode->i_sb)->s_rock) return 0;
-
- SETUP_ROCK_RIDGE(de, chr, len);
- if (regard_xa)
- {
- chr+=14;
- len-=14;
- if (len<0) len=0;
- }
-
- repeat:
- {
- int cnt, sig;
- struct inode * reloc;
- struct rock_ridge * rr;
- int rootflag;
-
- while (len > 2){ /* There may be one byte for padding somewhere */
- rr = (struct rock_ridge *) chr;
- if (rr->len < 3) goto out; /* Something got screwed up here */
- sig = isonum_721(chr);
- chr += rr->len;
- len -= rr->len;
- if (len < 0) goto out; /* corrupted isofs */
-
- switch(sig){
+ int symlink_len = 0;
+ int cnt, sig;
+ struct inode *reloc;
+ struct rock_ridge *rr;
+ int rootflag;
+ struct rock_state rs;
+ int ret = 0;
+
+ if (!ISOFS_SB(inode->i_sb)->s_rock)
+ return 0;
+
+ init_rock_state(&rs, inode);
+ setup_rock_ridge(de, inode, &rs);
+ if (regard_xa) {
+ rs.chr += 14;
+ rs.len -= 14;
+ if (rs.len < 0)
+ rs.len = 0;
+ }
+
+repeat:
+ while (rs.len > 2) { /* There may be one byte for padding somewhere */
+ rr = (struct rock_ridge *)rs.chr;
+ if (rr->len < 3)
+ goto out; /* Something got screwed up here */
+ sig = isonum_721(rs.chr);
+ if (rock_check_overflow(&rs, sig))
+ goto eio;
+ rs.chr += rr->len;
+ rs.len -= rr->len;
+ if (rs.len < 0)
+ goto eio; /* corrupted isofs */
+
+ switch (sig) {
#ifndef CONFIG_ZISOFS /* No flag for SF or ZF */
- case SIG('R','R'):
- if((rr->u.RR.flags[0] &
- (RR_PX | RR_TF | RR_SL | RR_CL)) == 0) goto out;
- break;
+ case SIG('R', 'R'):
+ if ((rr->u.RR.flags[0] &
+ (RR_PX | RR_TF | RR_SL | RR_CL)) == 0)
+ goto out;
+ break;
#endif
- case SIG('S','P'):
- CHECK_SP(goto out);
- break;
- case SIG('C','E'):
- CHECK_CE;
- break;
- case SIG('E','R'):
- ISOFS_SB(inode->i_sb)->s_rock = 1;
- printk(KERN_DEBUG "ISO 9660 Extensions: ");
- { int p;
- for(p=0;p<rr->u.ER.len_id;p++) printk("%c",rr->u.ER.data[p]);
- }
- printk("\n");
- break;
- case SIG('P','X'):
- inode->i_mode = isonum_733(rr->u.PX.mode);
- inode->i_nlink = isonum_733(rr->u.PX.n_links);
- inode->i_uid = isonum_733(rr->u.PX.uid);
- inode->i_gid = isonum_733(rr->u.PX.gid);
- break;
- case SIG('P','N'):
- { int high, low;
- high = isonum_733(rr->u.PN.dev_high);
- low = isonum_733(rr->u.PN.dev_low);
- /*
- * The Rock Ridge standard specifies that if sizeof(dev_t) <= 4,
- * then the high field is unused, and the device number is completely
- * stored in the low field. Some writers may ignore this subtlety,
- * and as a result we test to see if the entire device number is
- * stored in the low field, and use that.
- */
- if((low & ~0xff) && high == 0) {
- inode->i_rdev = MKDEV(low >> 8, low & 0xff);
- } else {
- inode->i_rdev = MKDEV(high, low);
- }
- }
- break;
- case SIG('T','F'):
- /* Some RRIP writers incorrectly place ctime in the TF_CREATE field.
- Try to handle this correctly for either case. */
- cnt = 0; /* Rock ridge never appears on a High Sierra disk */
- if(rr->u.TF.flags & TF_CREATE) {
- inode->i_ctime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0);
- inode->i_ctime.tv_nsec = 0;
- }
- if(rr->u.TF.flags & TF_MODIFY) {
- inode->i_mtime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0);
- inode->i_mtime.tv_nsec = 0;
- }
- if(rr->u.TF.flags & TF_ACCESS) {
- inode->i_atime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0);
- inode->i_atime.tv_nsec = 0;
- }
- if(rr->u.TF.flags & TF_ATTRIBUTES) {
- inode->i_ctime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0);
- inode->i_ctime.tv_nsec = 0;
- }
- break;
- case SIG('S','L'):
- {int slen;
- struct SL_component * slp;
- struct SL_component * oldslp;
- slen = rr->len - 5;
- slp = &rr->u.SL.link;
- inode->i_size = symlink_len;
- while (slen > 1){
- rootflag = 0;
- switch(slp->flags &~1){
- case 0:
- inode->i_size += slp->len;
- break;
- case 2:
- inode->i_size += 1;
- break;
- case 4:
- inode->i_size += 2;
- break;
- case 8:
- rootflag = 1;
- inode->i_size += 1;
- break;
- default:
- printk("Symlink component flag not implemented\n");
- }
- slen -= slp->len + 2;
- oldslp = slp;
- slp = (struct SL_component *) (((char *) slp) + slp->len + 2);
-
- if(slen < 2) {
- if( ((rr->u.SL.flags & 1) != 0)
- && ((oldslp->flags & 1) == 0) ) inode->i_size += 1;
- break;
- }
-
- /*
- * If this component record isn't continued, then append a '/'.
- */
- if (!rootflag && (oldslp->flags & 1) == 0)
- inode->i_size += 1;
- }
- }
- symlink_len = inode->i_size;
- break;
- case SIG('R','E'):
- printk(KERN_WARNING "Attempt to read inode for relocated directory\n");
- goto out;
- case SIG('C','L'):
- ISOFS_I(inode)->i_first_extent = isonum_733(rr->u.CL.location);
- reloc = isofs_iget(inode->i_sb, ISOFS_I(inode)->i_first_extent, 0);
- if (!reloc)
- goto out;
- inode->i_mode = reloc->i_mode;
- inode->i_nlink = reloc->i_nlink;
- inode->i_uid = reloc->i_uid;
- inode->i_gid = reloc->i_gid;
- inode->i_rdev = reloc->i_rdev;
- inode->i_size = reloc->i_size;
- inode->i_blocks = reloc->i_blocks;
- inode->i_atime = reloc->i_atime;
- inode->i_ctime = reloc->i_ctime;
- inode->i_mtime = reloc->i_mtime;
- iput(reloc);
- break;
+ case SIG('S', 'P'):
+ if (check_sp(rr, inode))
+ goto out;
+ break;
+ case SIG('C', 'E'):
+ rs.cont_extent = isonum_733(rr->u.CE.extent);
+ rs.cont_offset = isonum_733(rr->u.CE.offset);
+ rs.cont_size = isonum_733(rr->u.CE.size);
+ break;
+ case SIG('E', 'R'):
+ ISOFS_SB(inode->i_sb)->s_rock = 1;
+ printk(KERN_DEBUG "ISO 9660 Extensions: ");
+ {
+ int p;
+ for (p = 0; p < rr->u.ER.len_id; p++)
+ printk("%c", rr->u.ER.data[p]);
+ }
+ printk("\n");
+ break;
+ case SIG('P', 'X'):
+ inode->i_mode = isonum_733(rr->u.PX.mode);
+ inode->i_nlink = isonum_733(rr->u.PX.n_links);
+ inode->i_uid = isonum_733(rr->u.PX.uid);
+ inode->i_gid = isonum_733(rr->u.PX.gid);
+ break;
+ case SIG('P', 'N'):
+ {
+ int high, low;
+ high = isonum_733(rr->u.PN.dev_high);
+ low = isonum_733(rr->u.PN.dev_low);
+ /*
+ * The Rock Ridge standard specifies that if
+ * sizeof(dev_t) <= 4, then the high field is
+ * unused, and the device number is completely
+ * stored in the low field. Some writers may
+ * ignore this subtlety,
+ * and as a result we test to see if the entire
+ * device number is
+ * stored in the low field, and use that.
+ */
+ if ((low & ~0xff) && high == 0) {
+ inode->i_rdev =
+ MKDEV(low >> 8, low & 0xff);
+ } else {
+ inode->i_rdev =
+ MKDEV(high, low);
+ }
+ }
+ break;
+ case SIG('T', 'F'):
+ /*
+ * Some RRIP writers incorrectly place ctime in the
+ * TF_CREATE field. Try to handle this correctly for
+ * either case.
+ */
+ /* Rock ridge never appears on a High Sierra disk */
+ cnt = 0;
+ if (rr->u.TF.flags & TF_CREATE) {
+ inode->i_ctime.tv_sec =
+ iso_date(rr->u.TF.times[cnt++].time,
+ 0);
+ inode->i_ctime.tv_nsec = 0;
+ }
+ if (rr->u.TF.flags & TF_MODIFY) {
+ inode->i_mtime.tv_sec =
+ iso_date(rr->u.TF.times[cnt++].time,
+ 0);
+ inode->i_mtime.tv_nsec = 0;
+ }
+ if (rr->u.TF.flags & TF_ACCESS) {
+ inode->i_atime.tv_sec =
+ iso_date(rr->u.TF.times[cnt++].time,
+ 0);
+ inode->i_atime.tv_nsec = 0;
+ }
+ if (rr->u.TF.flags & TF_ATTRIBUTES) {
+ inode->i_ctime.tv_sec =
+ iso_date(rr->u.TF.times[cnt++].time,
+ 0);
+ inode->i_ctime.tv_nsec = 0;
+ }
+ break;
+ case SIG('S', 'L'):
+ {
+ int slen;
+ struct SL_component *slp;
+ struct SL_component *oldslp;
+ slen = rr->len - 5;
+ slp = &rr->u.SL.link;
+ inode->i_size = symlink_len;
+ while (slen > 1) {
+ rootflag = 0;
+ switch (slp->flags & ~1) {
+ case 0:
+ inode->i_size +=
+ slp->len;
+ break;
+ case 2:
+ inode->i_size += 1;
+ break;
+ case 4:
+ inode->i_size += 2;
+ break;
+ case 8:
+ rootflag = 1;
+ inode->i_size += 1;
+ break;
+ default:
+ printk("Symlink component flag "
+ "not implemented\n");
+ }
+ slen -= slp->len + 2;
+ oldslp = slp;
+ slp = (struct SL_component *)
+ (((char *)slp) + slp->len + 2);
+
+ if (slen < 2) {
+ if (((rr->u.SL.
+ flags & 1) != 0)
+ &&
+ ((oldslp->
+ flags & 1) == 0))
+ inode->i_size +=
+ 1;
+ break;
+ }
+
+ /*
+ * If this component record isn't
+ * continued, then append a '/'.
+ */
+ if (!rootflag
+ && (oldslp->flags & 1) == 0)
+ inode->i_size += 1;
+ }
+ }
+ symlink_len = inode->i_size;
+ break;
+ case SIG('R', 'E'):
+ printk(KERN_WARNING "Attempt to read inode for "
+ "relocated directory\n");
+ goto out;
+ case SIG('C', 'L'):
+ ISOFS_I(inode)->i_first_extent =
+ isonum_733(rr->u.CL.location);
+ reloc =
+ isofs_iget(inode->i_sb,
+ ISOFS_I(inode)->i_first_extent,
+ 0);
+ if (!reloc)
+ goto out;
+ inode->i_mode = reloc->i_mode;
+ inode->i_nlink = reloc->i_nlink;
+ inode->i_uid = reloc->i_uid;
+ inode->i_gid = reloc->i_gid;
+ inode->i_rdev = reloc->i_rdev;
+ inode->i_size = reloc->i_size;
+ inode->i_blocks = reloc->i_blocks;
+ inode->i_atime = reloc->i_atime;
+ inode->i_ctime = reloc->i_ctime;
+ inode->i_mtime = reloc->i_mtime;
+ iput(reloc);
+ break;
#ifdef CONFIG_ZISOFS
- case SIG('Z','F'):
- if ( !ISOFS_SB(inode->i_sb)->s_nocompress ) {
- int algo;
- algo = isonum_721(rr->u.ZF.algorithm);
- if ( algo == SIG('p','z') ) {
- int block_shift = isonum_711(&rr->u.ZF.parms[1]);
- if ( block_shift < PAGE_CACHE_SHIFT || block_shift > 17 ) {
- printk(KERN_WARNING "isofs: Can't handle ZF block size of 2^%d\n", block_shift);
- } else {
- /* Note: we don't change i_blocks here */
- ISOFS_I(inode)->i_file_format = isofs_file_compressed;
- /* Parameters to compression algorithm (header size, block size) */
- ISOFS_I(inode)->i_format_parm[0] = isonum_711(&rr->u.ZF.parms[0]);
- ISOFS_I(inode)->i_format_parm[1] = isonum_711(&rr->u.ZF.parms[1]);
- inode->i_size = isonum_733(rr->u.ZF.real_size);
- }
- } else {
- printk(KERN_WARNING "isofs: Unknown ZF compression algorithm: %c%c\n",
- rr->u.ZF.algorithm[0], rr->u.ZF.algorithm[1]);
- }
- }
- break;
+ case SIG('Z', 'F'): {
+ int algo;
+
+ if (ISOFS_SB(inode->i_sb)->s_nocompress)
+ break;
+ algo = isonum_721(rr->u.ZF.algorithm);
+ if (algo == SIG('p', 'z')) {
+ int block_shift =
+ isonum_711(&rr->u.ZF.parms[1]);
+ if (block_shift < PAGE_CACHE_SHIFT
+ || block_shift > 17) {
+ printk(KERN_WARNING "isofs: "
+ "Can't handle ZF block "
+ "size of 2^%d\n",
+ block_shift);
+ } else {
+ /*
+ * Note: we don't change
+ * i_blocks here
+ */
+ ISOFS_I(inode)->i_file_format =
+ isofs_file_compressed;
+ /*
+ * Parameters to compression
+ * algorithm (header size,
+ * block size)
+ */
+ ISOFS_I(inode)->i_format_parm[0] =
+ isonum_711(&rr->u.ZF.parms[0]);
+ ISOFS_I(inode)->i_format_parm[1] =
+ isonum_711(&rr->u.ZF.parms[1]);
+ inode->i_size =
+ isonum_733(rr->u.ZF.
+ real_size);
+ }
+ } else {
+ printk(KERN_WARNING
+ "isofs: Unknown ZF compression "
+ "algorithm: %c%c\n",
+ rr->u.ZF.algorithm[0],
+ rr->u.ZF.algorithm[1]);
+ }
+ break;
+ }
#endif
- default:
- break;
- }
- }
- }
- MAYBE_CONTINUE(repeat,inode);
- out:
- if(buffer) kfree(buffer);
- return 0;
+ default:
+ break;
+ }
+ }
+ ret = rock_continue(&rs);
+ if (ret == 0)
+ goto repeat;
+ if (ret == 1)
+ ret = 0;
+out:
+ kfree(rs.buffer);
+ return ret;
+eio:
+ ret = -EIO;
+ goto out;
}
static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit)
@@ -376,32 +566,32 @@ static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit)
if (slp->len > plimit - rpnt)
return NULL;
memcpy(rpnt, slp->text, slp->len);
- rpnt+=slp->len;
+ rpnt += slp->len;
break;
case 2:
if (rpnt >= plimit)
return NULL;
- *rpnt++='.';
+ *rpnt++ = '.';
break;
case 4:
if (2 > plimit - rpnt)
return NULL;
- *rpnt++='.';
- *rpnt++='.';
+ *rpnt++ = '.';
+ *rpnt++ = '.';
break;
case 8:
if (rpnt >= plimit)
return NULL;
rootflag = 1;
- *rpnt++='/';
+ *rpnt++ = '/';
break;
default:
printk("Symlink component flag not implemented (%d)\n",
- slp->flags);
+ slp->flags);
}
slen -= slp->len + 2;
oldslp = slp;
- slp = (struct SL_component *) ((char *) slp + slp->len + 2);
+ slp = (struct SL_component *)((char *)slp + slp->len + 2);
if (slen < 2) {
/*
@@ -412,7 +602,7 @@ static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit)
!(oldslp->flags & 1)) {
if (rpnt >= plimit)
return NULL;
- *rpnt++='/';
+ *rpnt++ = '/';
}
break;
}
@@ -423,59 +613,61 @@ static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit)
if (!rootflag && !(oldslp->flags & 1)) {
if (rpnt >= plimit)
return NULL;
- *rpnt++='/';
+ *rpnt++ = '/';
}
}
return rpnt;
}
-int parse_rock_ridge_inode(struct iso_directory_record * de,
- struct inode * inode)
+int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode)
{
- int result=parse_rock_ridge_inode_internal(de,inode,0);
- /* if rockridge flag was reset and we didn't look for attributes
- * behind eventual XA attributes, have a look there */
- if ((ISOFS_SB(inode->i_sb)->s_rock_offset==-1)
- &&(ISOFS_SB(inode->i_sb)->s_rock==2))
- {
- result=parse_rock_ridge_inode_internal(de,inode,14);
- }
- return result;
-}
+ int result = parse_rock_ridge_inode_internal(de, inode, 0);
-/* readpage() for symlinks: reads symlink contents into the page and either
- makes it uptodate and returns 0 or returns error (-EIO) */
+ /*
+ * if rockridge flag was reset and we didn't look for attributes
+ * behind eventual XA attributes, have a look there
+ */
+ if ((ISOFS_SB(inode->i_sb)->s_rock_offset == -1)
+ && (ISOFS_SB(inode->i_sb)->s_rock == 2)) {
+ result = parse_rock_ridge_inode_internal(de, inode, 14);
+ }
+ return result;
+}
+/*
+ * readpage() for symlinks: reads symlink contents into the page and either
+ * makes it uptodate and returns 0 or returns error (-EIO)
+ */
static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
{
struct inode *inode = page->mapping->host;
- struct iso_inode_info *ei = ISOFS_I(inode);
+ struct iso_inode_info *ei = ISOFS_I(inode);
char *link = kmap(page);
unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
struct buffer_head *bh;
char *rpnt = link;
unsigned char *pnt;
- struct iso_directory_record *raw_inode;
- CONTINUE_DECLS;
+ struct iso_directory_record *raw_de;
unsigned long block, offset;
int sig;
- int len;
- unsigned char *chr;
struct rock_ridge *rr;
+ struct rock_state rs;
+ int ret;
if (!ISOFS_SB(inode->i_sb)->s_rock)
goto error;
+ init_rock_state(&rs, inode);
block = ei->i_iget5_block;
lock_kernel();
bh = sb_bread(inode->i_sb, block);
if (!bh)
goto out_noread;
- offset = ei->i_iget5_offset;
- pnt = (unsigned char *) bh->b_data + offset;
+ offset = ei->i_iget5_offset;
+ pnt = (unsigned char *)bh->b_data + offset;
- raw_inode = (struct iso_directory_record *) pnt;
+ raw_de = (struct iso_directory_record *)pnt;
/*
* If we go past the end of the buffer, there is some sort of error.
@@ -483,20 +675,24 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
if (offset + *pnt > bufsize)
goto out_bad_span;
- /* Now test for possible Rock Ridge extensions which will override
- some of these numbers in the inode structure. */
+ /*
+ * Now test for possible Rock Ridge extensions which will override
+ * some of these numbers in the inode structure.
+ */
- SETUP_ROCK_RIDGE(raw_inode, chr, len);
+ setup_rock_ridge(raw_de, inode, &rs);
- repeat:
- while (len > 2) { /* There may be one byte for padding somewhere */
- rr = (struct rock_ridge *) chr;
+repeat:
+ while (rs.len > 2) { /* There may be one byte for padding somewhere */
+ rr = (struct rock_ridge *)rs.chr;
if (rr->len < 3)
goto out; /* Something got screwed up here */
- sig = isonum_721(chr);
- chr += rr->len;
- len -= rr->len;
- if (len < 0)
+ sig = isonum_721(rs.chr);
+ if (rock_check_overflow(&rs, sig))
+ goto out;
+ rs.chr += rr->len;
+ rs.len -= rr->len;
+ if (rs.len < 0)
goto out; /* corrupted isofs */
switch (sig) {
@@ -505,7 +701,8 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
goto out;
break;
case SIG('S', 'P'):
- CHECK_SP(goto out);
+ if (check_sp(rr, inode))
+ goto out;
break;
case SIG('S', 'L'):
rpnt = get_symlink_chunk(rpnt, rr,
@@ -515,14 +712,18 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
break;
case SIG('C', 'E'):
/* This tells is if there is a continuation record */
- CHECK_CE;
+ rs.cont_extent = isonum_733(rr->u.CE.extent);
+ rs.cont_offset = isonum_733(rr->u.CE.offset);
+ rs.cont_size = isonum_733(rr->u.CE.size);
default:
break;
}
}
- MAYBE_CONTINUE(repeat, inode);
- if (buffer)
- kfree(buffer);
+ ret = rock_continue(&rs);
+ if (ret == 0)
+ goto repeat;
+ if (ret < 0)
+ goto fail;
if (rpnt == link)
goto fail;
@@ -535,19 +736,18 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
return 0;
/* error exit from macro */
- out:
- if (buffer)
- kfree(buffer);
+out:
+ kfree(rs.buffer);
goto fail;
- out_noread:
+out_noread:
printk("unable to read i-node block");
goto fail;
- out_bad_span:
+out_bad_span:
printk("symlink spans iso9660 blocks\n");
- fail:
+fail:
brelse(bh);
unlock_kernel();
- error:
+error:
SetPageError(page);
kunmap(page);
unlock_page(page);
@@ -555,5 +755,5 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
}
struct address_space_operations isofs_symlink_aops = {
- .readpage = rock_ridge_symlink_readpage
+ .readpage = rock_ridge_symlink_readpage
};
diff --git a/fs/isofs/rock.h b/fs/isofs/rock.h
index deaf5c8e8b4..ed09e2b0863 100644
--- a/fs/isofs/rock.h
+++ b/fs/isofs/rock.h
@@ -1,85 +1,88 @@
-/* These structs are used by the system-use-sharing protocol, in which the
- Rock Ridge extensions are embedded. It is quite possible that other
- extensions are present on the disk, and this is fine as long as they
- all use SUSP */
-
-struct SU_SP{
- unsigned char magic[2];
- unsigned char skip;
-} __attribute__((packed));
-
-struct SU_CE{
- char extent[8];
- char offset[8];
- char size[8];
+/*
+ * These structs are used by the system-use-sharing protocol, in which the
+ * Rock Ridge extensions are embedded. It is quite possible that other
+ * extensions are present on the disk, and this is fine as long as they
+ * all use SUSP
+ */
+
+struct SU_SP_s {
+ unsigned char magic[2];
+ unsigned char skip;
+} __attribute__ ((packed));
+
+struct SU_CE_s {
+ char extent[8];
+ char offset[8];
+ char size[8];
};
-struct SU_ER{
- unsigned char len_id;
- unsigned char len_des;
- unsigned char len_src;
- unsigned char ext_ver;
- char data[0];
-} __attribute__((packed));
-
-struct RR_RR{
- char flags[1];
-} __attribute__((packed));
-
-struct RR_PX{
- char mode[8];
- char n_links[8];
- char uid[8];
- char gid[8];
+struct SU_ER_s {
+ unsigned char len_id;
+ unsigned char len_des;
+ unsigned char len_src;
+ unsigned char ext_ver;
+ char data[0];
+} __attribute__ ((packed));
+
+struct RR_RR_s {
+ char flags[1];
+} __attribute__ ((packed));
+
+struct RR_PX_s {
+ char mode[8];
+ char n_links[8];
+ char uid[8];
+ char gid[8];
};
-struct RR_PN{
- char dev_high[8];
- char dev_low[8];
+struct RR_PN_s {
+ char dev_high[8];
+ char dev_low[8];
};
+struct SL_component {
+ unsigned char flags;
+ unsigned char len;
+ char text[0];
+} __attribute__ ((packed));
-struct SL_component{
- unsigned char flags;
- unsigned char len;
- char text[0];
-} __attribute__((packed));
+struct RR_SL_s {
+ unsigned char flags;
+ struct SL_component link;
+} __attribute__ ((packed));
-struct RR_SL{
- unsigned char flags;
- struct SL_component link;
-} __attribute__((packed));
+struct RR_NM_s {
+ unsigned char flags;
+ char name[0];
+} __attribute__ ((packed));
-struct RR_NM{
- unsigned char flags;
- char name[0];
-} __attribute__((packed));
-
-struct RR_CL{
- char location[8];
+struct RR_CL_s {
+ char location[8];
};
-struct RR_PL{
- char location[8];
+struct RR_PL_s {
+ char location[8];
};
-struct stamp{
- char time[7];
-} __attribute__((packed));
+struct stamp {
+ char time[7];
+} __attribute__ ((packed));
-struct RR_TF{
- char flags;
- struct stamp times[0]; /* Variable number of these beasts */
-} __attribute__((packed));
+struct RR_TF_s {
+ char flags;
+ struct stamp times[0]; /* Variable number of these beasts */
+} __attribute__ ((packed));
/* Linux-specific extension for transparent decompression */
-struct RR_ZF{
- char algorithm[2];
- char parms[2];
- char real_size[8];
+struct RR_ZF_s {
+ char algorithm[2];
+ char parms[2];
+ char real_size[8];
};
-/* These are the bits and their meanings for flags in the TF structure. */
+/*
+ * These are the bits and their meanings for flags in the TF structure.
+ */
#define TF_CREATE 1
#define TF_MODIFY 2
#define TF_ACCESS 4
@@ -89,31 +92,31 @@ struct RR_ZF{
#define TF_EFFECTIVE 64
#define TF_LONG_FORM 128
-struct rock_ridge{
- char signature[2];
- unsigned char len;
- unsigned char version;
- union{
- struct SU_SP SP;
- struct SU_CE CE;
- struct SU_ER ER;
- struct RR_RR RR;
- struct RR_PX PX;
- struct RR_PN PN;
- struct RR_SL SL;
- struct RR_NM NM;
- struct RR_CL CL;
- struct RR_PL PL;
- struct RR_TF TF;
- struct RR_ZF ZF;
- } u;
+struct rock_ridge {
+ char signature[2];
+ unsigned char len;
+ unsigned char version;
+ union {
+ struct SU_SP_s SP;
+ struct SU_CE_s CE;
+ struct SU_ER_s ER;
+ struct RR_RR_s RR;
+ struct RR_PX_s PX;
+ struct RR_PN_s PN;
+ struct RR_SL_s SL;
+ struct RR_NM_s NM;
+ struct RR_CL_s CL;
+ struct RR_PL_s PL;
+ struct RR_TF_s TF;
+ struct RR_ZF_s ZF;
+ } u;
};
-#define RR_PX 1 /* POSIX attributes */
-#define RR_PN 2 /* POSIX devices */
-#define RR_SL 4 /* Symbolic link */
-#define RR_NM 8 /* Alternate Name */
-#define RR_CL 16 /* Child link */
-#define RR_PL 32 /* Parent link */
-#define RR_RE 64 /* Relocation directory */
-#define RR_TF 128 /* Timestamps */
+#define RR_PX 1 /* POSIX attributes */
+#define RR_PN 2 /* POSIX devices */
+#define RR_SL 4 /* Symbolic link */
+#define RR_NM 8 /* Alternate Name */
+#define RR_CL 16 /* Child link */
+#define RR_PL 32 /* Parent link */
+#define RR_RE 64 /* Relocation directory */
+#define RR_TF 128 /* Timestamps */
diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c
index 98d830401c5..5a97e346bd9 100644
--- a/fs/jbd/checkpoint.c
+++ b/fs/jbd/checkpoint.c
@@ -188,7 +188,6 @@ static int __cleanup_transaction(journal_t *journal, transaction_t *transaction)
} else {
jbd_unlock_bh_state(bh);
}
- jh = next_jh;
} while (jh != last_jh);
return ret;
@@ -339,8 +338,10 @@ int log_do_checkpoint(journal_t *journal)
}
} while (jh != last_jh && !retry);
- if (batch_count)
+ if (batch_count) {
__flush_batch(journal, bhs, &batch_count);
+ retry = 1;
+ }
/*
* If someone cleaned up this transaction while we slept, we're
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index 1e6f2e2ad4a..5e7b4394951 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -167,7 +167,7 @@ loop:
}
wake_up(&journal->j_wait_done_commit);
- if (current->flags & PF_FREEZE) {
+ if (freezing(current)) {
/*
* The simpler the better. Flushing journal isn't a
* good idea, because that depends on threads that may
@@ -175,7 +175,7 @@ loop:
*/
jbd_debug(1, "Now suspending kjournald\n");
spin_unlock(&journal->j_state_lock);
- refrigerator(PF_FREEZE);
+ refrigerator();
spin_lock(&journal->j_state_lock);
} else {
/*
diff --git a/fs/jffs/intrep.c b/fs/jffs/intrep.c
index 8cc6893fc56..fc589ddd076 100644
--- a/fs/jffs/intrep.c
+++ b/fs/jffs/intrep.c
@@ -175,8 +175,64 @@ jffs_hexdump(struct mtd_info *mtd, loff_t pos, int size)
}
}
+/* Print the contents of a node. */
+static void
+jffs_print_node(struct jffs_node *n)
+{
+ D(printk("jffs_node: 0x%p\n", n));
+ D(printk("{\n"));
+ D(printk(" 0x%08x, /* version */\n", n->version));
+ D(printk(" 0x%08x, /* data_offset */\n", n->data_offset));
+ D(printk(" 0x%08x, /* data_size */\n", n->data_size));
+ D(printk(" 0x%08x, /* removed_size */\n", n->removed_size));
+ D(printk(" 0x%08x, /* fm_offset */\n", n->fm_offset));
+ D(printk(" 0x%02x, /* name_size */\n", n->name_size));
+ D(printk(" 0x%p, /* fm, fm->offset: %u */\n",
+ n->fm, (n->fm ? n->fm->offset : 0)));
+ D(printk(" 0x%p, /* version_prev */\n", n->version_prev));
+ D(printk(" 0x%p, /* version_next */\n", n->version_next));
+ D(printk(" 0x%p, /* range_prev */\n", n->range_prev));
+ D(printk(" 0x%p, /* range_next */\n", n->range_next));
+ D(printk("}\n"));
+}
+
#endif
+/* Print the contents of a raw inode. */
+static void
+jffs_print_raw_inode(struct jffs_raw_inode *raw_inode)
+{
+ D(printk("jffs_raw_inode: inode number: %u\n", raw_inode->ino));
+ D(printk("{\n"));
+ D(printk(" 0x%08x, /* magic */\n", raw_inode->magic));
+ D(printk(" 0x%08x, /* ino */\n", raw_inode->ino));
+ D(printk(" 0x%08x, /* pino */\n", raw_inode->pino));
+ D(printk(" 0x%08x, /* version */\n", raw_inode->version));
+ D(printk(" 0x%08x, /* mode */\n", raw_inode->mode));
+ D(printk(" 0x%04x, /* uid */\n", raw_inode->uid));
+ D(printk(" 0x%04x, /* gid */\n", raw_inode->gid));
+ D(printk(" 0x%08x, /* atime */\n", raw_inode->atime));
+ D(printk(" 0x%08x, /* mtime */\n", raw_inode->mtime));
+ D(printk(" 0x%08x, /* ctime */\n", raw_inode->ctime));
+ D(printk(" 0x%08x, /* offset */\n", raw_inode->offset));
+ D(printk(" 0x%08x, /* dsize */\n", raw_inode->dsize));
+ D(printk(" 0x%08x, /* rsize */\n", raw_inode->rsize));
+ D(printk(" 0x%02x, /* nsize */\n", raw_inode->nsize));
+ D(printk(" 0x%02x, /* nlink */\n", raw_inode->nlink));
+ D(printk(" 0x%02x, /* spare */\n",
+ raw_inode->spare));
+ D(printk(" %u, /* rename */\n",
+ raw_inode->rename));
+ D(printk(" %u, /* deleted */\n",
+ raw_inode->deleted));
+ D(printk(" 0x%02x, /* accurate */\n",
+ raw_inode->accurate));
+ D(printk(" 0x%08x, /* dchksum */\n", raw_inode->dchksum));
+ D(printk(" 0x%04x, /* nchksum */\n", raw_inode->nchksum));
+ D(printk(" 0x%04x, /* chksum */\n", raw_inode->chksum));
+ D(printk("}\n"));
+}
+
#define flash_safe_acquire(arg)
#define flash_safe_release(arg)
@@ -2507,64 +2563,6 @@ jffs_update_file(struct jffs_file *f, struct jffs_node *node)
return 0;
}
-/* Print the contents of a node. */
-void
-jffs_print_node(struct jffs_node *n)
-{
- D(printk("jffs_node: 0x%p\n", n));
- D(printk("{\n"));
- D(printk(" 0x%08x, /* version */\n", n->version));
- D(printk(" 0x%08x, /* data_offset */\n", n->data_offset));
- D(printk(" 0x%08x, /* data_size */\n", n->data_size));
- D(printk(" 0x%08x, /* removed_size */\n", n->removed_size));
- D(printk(" 0x%08x, /* fm_offset */\n", n->fm_offset));
- D(printk(" 0x%02x, /* name_size */\n", n->name_size));
- D(printk(" 0x%p, /* fm, fm->offset: %u */\n",
- n->fm, (n->fm ? n->fm->offset : 0)));
- D(printk(" 0x%p, /* version_prev */\n", n->version_prev));
- D(printk(" 0x%p, /* version_next */\n", n->version_next));
- D(printk(" 0x%p, /* range_prev */\n", n->range_prev));
- D(printk(" 0x%p, /* range_next */\n", n->range_next));
- D(printk("}\n"));
-}
-
-
-/* Print the contents of a raw inode. */
-void
-jffs_print_raw_inode(struct jffs_raw_inode *raw_inode)
-{
- D(printk("jffs_raw_inode: inode number: %u\n", raw_inode->ino));
- D(printk("{\n"));
- D(printk(" 0x%08x, /* magic */\n", raw_inode->magic));
- D(printk(" 0x%08x, /* ino */\n", raw_inode->ino));
- D(printk(" 0x%08x, /* pino */\n", raw_inode->pino));
- D(printk(" 0x%08x, /* version */\n", raw_inode->version));
- D(printk(" 0x%08x, /* mode */\n", raw_inode->mode));
- D(printk(" 0x%04x, /* uid */\n", raw_inode->uid));
- D(printk(" 0x%04x, /* gid */\n", raw_inode->gid));
- D(printk(" 0x%08x, /* atime */\n", raw_inode->atime));
- D(printk(" 0x%08x, /* mtime */\n", raw_inode->mtime));
- D(printk(" 0x%08x, /* ctime */\n", raw_inode->ctime));
- D(printk(" 0x%08x, /* offset */\n", raw_inode->offset));
- D(printk(" 0x%08x, /* dsize */\n", raw_inode->dsize));
- D(printk(" 0x%08x, /* rsize */\n", raw_inode->rsize));
- D(printk(" 0x%02x, /* nsize */\n", raw_inode->nsize));
- D(printk(" 0x%02x, /* nlink */\n", raw_inode->nlink));
- D(printk(" 0x%02x, /* spare */\n",
- raw_inode->spare));
- D(printk(" %u, /* rename */\n",
- raw_inode->rename));
- D(printk(" %u, /* deleted */\n",
- raw_inode->deleted));
- D(printk(" 0x%02x, /* accurate */\n",
- raw_inode->accurate));
- D(printk(" 0x%08x, /* dchksum */\n", raw_inode->dchksum));
- D(printk(" 0x%04x, /* nchksum */\n", raw_inode->nchksum));
- D(printk(" 0x%04x, /* chksum */\n", raw_inode->chksum));
- D(printk("}\n"));
-}
-
-
/* Print the contents of a file. */
#if 0
int
diff --git a/fs/jffs/intrep.h b/fs/jffs/intrep.h
index 4ae97b17911..5c7abe0e269 100644
--- a/fs/jffs/intrep.h
+++ b/fs/jffs/intrep.h
@@ -49,8 +49,6 @@ int jffs_garbage_collect_thread(void *c);
void jffs_garbage_collect_trigger(struct jffs_control *c);
/* For debugging purposes. */
-void jffs_print_node(struct jffs_node *n);
-void jffs_print_raw_inode(struct jffs_raw_inode *raw_inode);
#if 0
int jffs_print_file(struct jffs_file *f);
#endif /* 0 */
diff --git a/fs/jffs/jffs_fm.c b/fs/jffs/jffs_fm.c
index 0cab8da49d3..053e3a98a27 100644
--- a/fs/jffs/jffs_fm.c
+++ b/fs/jffs/jffs_fm.c
@@ -31,6 +31,60 @@ static void jffs_free_fm(struct jffs_fm *n);
extern kmem_cache_t *fm_cache;
extern kmem_cache_t *node_cache;
+#if CONFIG_JFFS_FS_VERBOSE > 0
+void
+jffs_print_fmcontrol(struct jffs_fmcontrol *fmc)
+{
+ D(printk("struct jffs_fmcontrol: 0x%p\n", fmc));
+ D(printk("{\n"));
+ D(printk(" %u, /* flash_size */\n", fmc->flash_size));
+ D(printk(" %u, /* used_size */\n", fmc->used_size));
+ D(printk(" %u, /* dirty_size */\n", fmc->dirty_size));
+ D(printk(" %u, /* free_size */\n", fmc->free_size));
+ D(printk(" %u, /* sector_size */\n", fmc->sector_size));
+ D(printk(" %u, /* min_free_size */\n", fmc->min_free_size));
+ D(printk(" %u, /* max_chunk_size */\n", fmc->max_chunk_size));
+ D(printk(" 0x%p, /* mtd */\n", fmc->mtd));
+ D(printk(" 0x%p, /* head */ "
+ "(head->offset = 0x%08x)\n",
+ fmc->head, (fmc->head ? fmc->head->offset : 0)));
+ D(printk(" 0x%p, /* tail */ "
+ "(tail->offset + tail->size = 0x%08x)\n",
+ fmc->tail,
+ (fmc->tail ? fmc->tail->offset + fmc->tail->size : 0)));
+ D(printk(" 0x%p, /* head_extra */\n", fmc->head_extra));
+ D(printk(" 0x%p, /* tail_extra */\n", fmc->tail_extra));
+ D(printk("}\n"));
+}
+#endif /* CONFIG_JFFS_FS_VERBOSE > 0 */
+
+#if CONFIG_JFFS_FS_VERBOSE > 2
+static void
+jffs_print_fm(struct jffs_fm *fm)
+{
+ D(printk("struct jffs_fm: 0x%p\n", fm));
+ D(printk("{\n"));
+ D(printk(" 0x%08x, /* offset */\n", fm->offset));
+ D(printk(" %u, /* size */\n", fm->size));
+ D(printk(" 0x%p, /* prev */\n", fm->prev));
+ D(printk(" 0x%p, /* next */\n", fm->next));
+ D(printk(" 0x%p, /* nodes */\n", fm->nodes));
+ D(printk("}\n"));
+}
+#endif /* CONFIG_JFFS_FS_VERBOSE > 2 */
+
+#if 0
+void
+jffs_print_node_ref(struct jffs_node_ref *ref)
+{
+ D(printk("struct jffs_node_ref: 0x%p\n", ref));
+ D(printk("{\n"));
+ D(printk(" 0x%p, /* node */\n", ref->node));
+ D(printk(" 0x%p, /* next */\n", ref->next));
+ D(printk("}\n"));
+}
+#endif /* 0 */
+
/* This function creates a new shiny flash memory control structure. */
struct jffs_fmcontrol *
jffs_build_begin(struct jffs_control *c, int unit)
@@ -742,54 +796,3 @@ int jffs_get_node_inuse(void)
{
return no_jffs_node;
}
-
-void
-jffs_print_fmcontrol(struct jffs_fmcontrol *fmc)
-{
- D(printk("struct jffs_fmcontrol: 0x%p\n", fmc));
- D(printk("{\n"));
- D(printk(" %u, /* flash_size */\n", fmc->flash_size));
- D(printk(" %u, /* used_size */\n", fmc->used_size));
- D(printk(" %u, /* dirty_size */\n", fmc->dirty_size));
- D(printk(" %u, /* free_size */\n", fmc->free_size));
- D(printk(" %u, /* sector_size */\n", fmc->sector_size));
- D(printk(" %u, /* min_free_size */\n", fmc->min_free_size));
- D(printk(" %u, /* max_chunk_size */\n", fmc->max_chunk_size));
- D(printk(" 0x%p, /* mtd */\n", fmc->mtd));
- D(printk(" 0x%p, /* head */ "
- "(head->offset = 0x%08x)\n",
- fmc->head, (fmc->head ? fmc->head->offset : 0)));
- D(printk(" 0x%p, /* tail */ "
- "(tail->offset + tail->size = 0x%08x)\n",
- fmc->tail,
- (fmc->tail ? fmc->tail->offset + fmc->tail->size : 0)));
- D(printk(" 0x%p, /* head_extra */\n", fmc->head_extra));
- D(printk(" 0x%p, /* tail_extra */\n", fmc->tail_extra));
- D(printk("}\n"));
-}
-
-void
-jffs_print_fm(struct jffs_fm *fm)
-{
- D(printk("struct jffs_fm: 0x%p\n", fm));
- D(printk("{\n"));
- D(printk(" 0x%08x, /* offset */\n", fm->offset));
- D(printk(" %u, /* size */\n", fm->size));
- D(printk(" 0x%p, /* prev */\n", fm->prev));
- D(printk(" 0x%p, /* next */\n", fm->next));
- D(printk(" 0x%p, /* nodes */\n", fm->nodes));
- D(printk("}\n"));
-}
-
-#if 0
-void
-jffs_print_node_ref(struct jffs_node_ref *ref)
-{
- D(printk("struct jffs_node_ref: 0x%p\n", ref));
- D(printk("{\n"));
- D(printk(" 0x%p, /* node */\n", ref->node));
- D(printk(" 0x%p, /* next */\n", ref->next));
- D(printk("}\n"));
-}
-#endif /* 0 */
-
diff --git a/fs/jffs/jffs_fm.h b/fs/jffs/jffs_fm.h
index bc291c43182..f64151e7412 100644
--- a/fs/jffs/jffs_fm.h
+++ b/fs/jffs/jffs_fm.h
@@ -139,8 +139,9 @@ int jffs_add_node(struct jffs_node *node);
void jffs_fmfree_partly(struct jffs_fmcontrol *fmc, struct jffs_fm *fm,
__u32 size);
+#if CONFIG_JFFS_FS_VERBOSE > 0
void jffs_print_fmcontrol(struct jffs_fmcontrol *fmc);
-void jffs_print_fm(struct jffs_fm *fm);
+#endif
#if 0
void jffs_print_node_ref(struct jffs_node_ref *ref);
#endif /* 0 */
diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c
index 1be6de27dd8..638836b277d 100644
--- a/fs/jffs2/background.c
+++ b/fs/jffs2/background.c
@@ -92,7 +92,7 @@ static int jffs2_garbage_collect_thread(void *_c)
schedule();
}
- if (try_to_freeze(0))
+ if (try_to_freeze())
continue;
cond_resched();
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c
index 8d2a9ab981d..e892dab40c2 100644
--- a/fs/jfs/acl.c
+++ b/fs/jfs/acl.c
@@ -21,6 +21,7 @@
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/quotaops.h>
+#include <linux/posix_acl_xattr.h>
#include "jfs_incore.h"
#include "jfs_xattr.h"
#include "jfs_acl.h"
@@ -36,11 +37,11 @@ static struct posix_acl *jfs_get_acl(struct inode *inode, int type)
switch(type) {
case ACL_TYPE_ACCESS:
- ea_name = XATTR_NAME_ACL_ACCESS;
+ ea_name = POSIX_ACL_XATTR_ACCESS;
p_acl = &ji->i_acl;
break;
case ACL_TYPE_DEFAULT:
- ea_name = XATTR_NAME_ACL_DEFAULT;
+ ea_name = POSIX_ACL_XATTR_DEFAULT;
p_acl = &ji->i_default_acl;
break;
default:
@@ -70,8 +71,7 @@ static struct posix_acl *jfs_get_acl(struct inode *inode, int type)
if (!IS_ERR(acl))
*p_acl = posix_acl_dup(acl);
}
- if (value)
- kfree(value);
+ kfree(value);
return acl;
}
@@ -89,11 +89,11 @@ static int jfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
switch(type) {
case ACL_TYPE_ACCESS:
- ea_name = XATTR_NAME_ACL_ACCESS;
+ ea_name = POSIX_ACL_XATTR_ACCESS;
p_acl = &ji->i_acl;
break;
case ACL_TYPE_DEFAULT:
- ea_name = XATTR_NAME_ACL_DEFAULT;
+ ea_name = POSIX_ACL_XATTR_DEFAULT;
p_acl = &ji->i_default_acl;
if (!S_ISDIR(inode->i_mode))
return acl ? -EACCES : 0;
@@ -102,7 +102,7 @@ static int jfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
return -EINVAL;
}
if (acl) {
- size = xattr_acl_size(acl->a_count);
+ size = posix_acl_xattr_size(acl->a_count);
value = kmalloc(size, GFP_KERNEL);
if (!value)
return -ENOMEM;
@@ -112,8 +112,7 @@ static int jfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
}
rc = __jfs_setxattr(inode, ea_name, value, size, 0);
out:
- if (value)
- kfree(value);
+ kfree(value);
if (!rc) {
if (*p_acl && (*p_acl != JFS_ACL_NOT_CACHED))
diff --git a/fs/jfs/file.c b/fs/jfs/file.c
index a87b06fa8ff..c2c19c9ed9a 100644
--- a/fs/jfs/file.c
+++ b/fs/jfs/file.c
@@ -1,6 +1,6 @@
/*
- * Copyright (c) International Business Machines Corp., 2000-2002
- * Portions Copyright (c) Christoph Hellwig, 2001-2002
+ * Copyright (C) International Business Machines Corp., 2000-2002
+ * Portions Copyright (C) Christoph Hellwig, 2001-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
@@ -19,16 +19,13 @@
#include <linux/fs.h>
#include "jfs_incore.h"
+#include "jfs_inode.h"
#include "jfs_dmap.h"
#include "jfs_txnmgr.h"
#include "jfs_xattr.h"
#include "jfs_acl.h"
#include "jfs_debug.h"
-
-extern int jfs_commit_inode(struct inode *, int);
-extern void jfs_truncate(struct inode *);
-
int jfs_fsync(struct file *file, struct dentry *dentry, int datasync)
{
struct inode *inode = dentry->d_inode;
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index 24a689179af..2137138c59b 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -23,6 +23,7 @@
#include <linux/pagemap.h>
#include <linux/quotaops.h>
#include "jfs_incore.h"
+#include "jfs_inode.h"
#include "jfs_filsys.h"
#include "jfs_imap.h"
#include "jfs_extent.h"
@@ -30,14 +31,6 @@
#include "jfs_debug.h"
-extern struct inode_operations jfs_dir_inode_operations;
-extern struct inode_operations jfs_file_inode_operations;
-extern struct inode_operations jfs_symlink_inode_operations;
-extern struct file_operations jfs_dir_operations;
-extern struct file_operations jfs_file_operations;
-struct address_space_operations jfs_aops;
-extern int freeZeroLink(struct inode *);
-
void jfs_read_inode(struct inode *inode)
{
if (diRead(inode)) {
@@ -136,7 +129,7 @@ void jfs_delete_inode(struct inode *inode)
jfs_info("In jfs_delete_inode, inode = 0x%p", inode);
if (test_cflag(COMMIT_Freewmap, inode))
- freeZeroLink(inode);
+ jfs_free_zero_link(inode);
diFree(inode);
diff --git a/fs/jfs/jfs_acl.h b/fs/jfs/jfs_acl.h
index d2ae430adec..a3acd3eec05 100644
--- a/fs/jfs/jfs_acl.h
+++ b/fs/jfs/jfs_acl.h
@@ -20,8 +20,6 @@
#ifdef CONFIG_JFS_POSIX_ACL
-#include <linux/xattr_acl.h>
-
int jfs_permission(struct inode *, int, struct nameidata *);
int jfs_init_acl(struct inode *, struct inode *);
int jfs_setattr(struct dentry *, struct iattr *);
diff --git a/fs/jfs/jfs_debug.c b/fs/jfs/jfs_debug.c
index 91a0a889ebc..4caea6b43b9 100644
--- a/fs/jfs/jfs_debug.c
+++ b/fs/jfs/jfs_debug.c
@@ -58,8 +58,6 @@ void dump_mem(char *label, void *data, int length)
static struct proc_dir_entry *base;
#ifdef CONFIG_JFS_DEBUG
-extern read_proc_t jfs_txanchor_read;
-
static int loglevel_read(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
@@ -97,14 +95,6 @@ static int loglevel_write(struct file *file, const char __user *buffer,
}
#endif
-
-#ifdef CONFIG_JFS_STATISTICS
-extern read_proc_t jfs_lmstats_read;
-extern read_proc_t jfs_txstats_read;
-extern read_proc_t jfs_xtstat_read;
-extern read_proc_t jfs_mpstat_read;
-#endif
-
static struct {
const char *name;
read_proc_t *read_fn;
diff --git a/fs/jfs/jfs_debug.h b/fs/jfs/jfs_debug.h
index a38079ae1e0..ddffbbd4d95 100644
--- a/fs/jfs/jfs_debug.h
+++ b/fs/jfs/jfs_debug.h
@@ -1,6 +1,6 @@
/*
- * Copyright (c) International Business Machines Corp., 2000-2002
- * Portions Copyright (c) Christoph Hellwig, 2001-2002
+ * Copyright (C) International Business Machines Corp., 2000-2002
+ * Portions Copyright (C) Christoph Hellwig, 2001-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
@@ -31,7 +31,9 @@
* CONFIG_JFS_DEBUG or CONFIG_JFS_STATISTICS is defined
*/
#if defined(CONFIG_PROC_FS) && (defined(CONFIG_JFS_DEBUG) || defined(CONFIG_JFS_STATISTICS))
- #define PROC_FS_JFS
+#define PROC_FS_JFS
+extern void jfs_proc_init(void);
+extern void jfs_proc_clean(void);
#endif
/*
@@ -65,8 +67,8 @@
extern int jfsloglevel;
-/* dump memory contents */
extern void dump_mem(char *label, void *data, int length);
+extern int jfs_txanchor_read(char *, char **, off_t, int, int *, void *);
/* information message: e.g., configuration, major event */
#define jfs_info(fmt, arg...) do { \
@@ -110,6 +112,11 @@ extern void dump_mem(char *label, void *data, int length);
* ----------
*/
#ifdef CONFIG_JFS_STATISTICS
+extern int jfs_lmstats_read(char *, char **, off_t, int, int *, void *);
+extern int jfs_txstats_read(char *, char **, off_t, int, int *, void *);
+extern int jfs_mpstat_read(char *, char **, off_t, int, int *, void *);
+extern int jfs_xtstat_read(char *, char **, off_t, int, int *, void *);
+
#define INCREMENT(x) ((x)++)
#define DECREMENT(x) ((x)--)
#define HIGHWATERMARK(x,y) ((x) = max((x), (y)))
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
index 69007fd546e..cced2fed9d0 100644
--- a/fs/jfs/jfs_dmap.c
+++ b/fs/jfs/jfs_dmap.c
@@ -272,7 +272,6 @@ int dbMount(struct inode *ipbmap)
int dbUnmount(struct inode *ipbmap, int mounterror)
{
struct bmap *bmp = JFS_SBI(ipbmap->i_sb)->bmap;
- int i;
if (!(mounterror || isReadOnly(ipbmap)))
dbSync(ipbmap);
@@ -282,14 +281,6 @@ int dbUnmount(struct inode *ipbmap, int mounterror)
*/
truncate_inode_pages(ipbmap->i_mapping, 0);
- /*
- * Sanity Check
- */
- for (i = 0; i < bmp->db_numag; i++)
- if (atomic_read(&bmp->db_active[i]))
- printk(KERN_ERR "dbUnmount: db_active[%d] = %d\n",
- i, atomic_read(&bmp->db_active[i]));
-
/* free the memory for the in-memory bmap. */
kfree(bmp);
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
index ac41f72d6d5..8676aee3ae4 100644
--- a/fs/jfs/jfs_dtree.c
+++ b/fs/jfs/jfs_dtree.c
@@ -2931,6 +2931,9 @@ static void add_missing_indices(struct inode *inode, s64 bn)
ASSERT(p->header.flag & BT_LEAF);
tlck = txLock(tid, inode, mp, tlckDTREE | tlckENTRY);
+ if (BT_IS_ROOT(mp))
+ tlck->type |= tlckBTROOT;
+
dtlck = (struct dt_lock *) &tlck->lock;
stbl = DT_GETSTBL(p);
diff --git a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c
index 1953acb7926..4879603daa1 100644
--- a/fs/jfs/jfs_extent.c
+++ b/fs/jfs/jfs_extent.c
@@ -19,6 +19,7 @@
#include <linux/fs.h>
#include <linux/quotaops.h>
#include "jfs_incore.h"
+#include "jfs_inode.h"
#include "jfs_superblock.h"
#include "jfs_dmap.h"
#include "jfs_extent.h"
@@ -33,12 +34,6 @@ static int extBrealloc(struct inode *, s64, s64, s64 *, s64 *);
#endif
static s64 extRoundDown(s64 nb);
-/*
- * external references
- */
-extern int jfs_commit_inode(struct inode *, int);
-
-
#define DPD(a) (printk("(a): %d\n",(a)))
#define DPC(a) (printk("(a): %c\n",(a)))
#define DPL1(a) \
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index 7acff2ce3c8..971af2977ef 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -47,6 +47,7 @@
#include <linux/quotaops.h>
#include "jfs_incore.h"
+#include "jfs_inode.h"
#include "jfs_filsys.h"
#include "jfs_dinode.h"
#include "jfs_dmap.h"
@@ -69,11 +70,6 @@
#define AG_UNLOCK(imap,agno) up(&imap->im_aglock[agno])
/*
- * external references
- */
-extern struct address_space_operations jfs_aops;
-
-/*
* forward references
*/
static int diAllocAG(struct inomap *, int, boolean_t, struct inode *);
diff --git a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c
index 84f2459b219..2af5efbfd06 100644
--- a/fs/jfs/jfs_inode.c
+++ b/fs/jfs/jfs_inode.c
@@ -19,6 +19,7 @@
#include <linux/fs.h>
#include <linux/quotaops.h>
#include "jfs_incore.h"
+#include "jfs_inode.h"
#include "jfs_filsys.h"
#include "jfs_imap.h"
#include "jfs_dinode.h"
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h
index 3df91fbfe78..b54bac576cb 100644
--- a/fs/jfs/jfs_inode.h
+++ b/fs/jfs/jfs_inode.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) International Business Machines Corp., 2000-2001
+ * Copyright (C) International Business Machines Corp., 2000-2001
*
* 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
@@ -19,5 +19,22 @@
#define _H_JFS_INODE
extern struct inode *ialloc(struct inode *, umode_t);
+extern int jfs_fsync(struct file *, struct dentry *, int);
+extern void jfs_read_inode(struct inode *);
+extern int jfs_commit_inode(struct inode *, int);
+extern int jfs_write_inode(struct inode*, int);
+extern void jfs_delete_inode(struct inode *);
+extern void jfs_dirty_inode(struct inode *);
+extern void jfs_truncate(struct inode *);
+extern void jfs_truncate_nolock(struct inode *, loff_t);
+extern void jfs_free_zero_link(struct inode *);
+extern struct dentry *jfs_get_parent(struct dentry *dentry);
+extern struct address_space_operations jfs_aops;
+extern struct inode_operations jfs_dir_inode_operations;
+extern struct file_operations jfs_dir_operations;
+extern struct inode_operations jfs_file_inode_operations;
+extern struct file_operations jfs_file_operations;
+extern struct inode_operations jfs_symlink_inode_operations;
+extern struct dentry_operations jfs_ci_dentry_operations;
#endif /* _H_JFS_INODE */
diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
index dfa1200daa6..79d07624bfe 100644
--- a/fs/jfs/jfs_logmgr.c
+++ b/fs/jfs/jfs_logmgr.c
@@ -71,6 +71,7 @@
#include "jfs_incore.h"
#include "jfs_filsys.h"
#include "jfs_metapage.h"
+#include "jfs_superblock.h"
#include "jfs_txnmgr.h"
#include "jfs_debug.h"
@@ -167,14 +168,6 @@ static struct jfs_log *dummy_log = NULL;
static DECLARE_MUTEX(jfs_log_sem);
/*
- * external references
- */
-extern void txLazyUnlock(struct tblock * tblk);
-extern int jfs_stop_threads;
-extern struct completion jfsIOwait;
-extern int jfs_tlocks_low;
-
-/*
* forward references
*/
static int lmWriteRecord(struct jfs_log * log, struct tblock * tblk,
@@ -1624,6 +1617,8 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
}
}
assert(list_empty(&log->cqueue));
+
+#ifdef CONFIG_JFS_DEBUG
if (!list_empty(&log->synclist)) {
struct logsyncblk *lp;
@@ -1638,9 +1633,8 @@ void jfs_flush_journal(struct jfs_log *log, int wait)
dump_mem("orphan tblock", lp,
sizeof(struct tblock));
}
-// current->state = TASK_INTERRUPTIBLE;
-// schedule();
}
+#endif
//assert(list_empty(&log->synclist));
clear_bit(log_FLUSH, &log->flag);
}
@@ -2365,9 +2359,9 @@ int jfsIOWait(void *arg)
lbmStartIO(bp);
spin_lock_irq(&log_redrive_lock);
}
- if (current->flags & PF_FREEZE) {
+ if (freezing(current)) {
spin_unlock_irq(&log_redrive_lock);
- refrigerator(PF_FREEZE);
+ refrigerator();
} else {
add_wait_queue(&jfs_IO_thread_wait, &wq);
set_current_state(TASK_INTERRUPTIBLE);
diff --git a/fs/jfs/jfs_logmgr.h b/fs/jfs/jfs_logmgr.h
index 51291fbc420..747114cd38b 100644
--- a/fs/jfs/jfs_logmgr.h
+++ b/fs/jfs/jfs_logmgr.h
@@ -507,6 +507,8 @@ extern int lmLogClose(struct super_block *sb);
extern int lmLogShutdown(struct jfs_log * log);
extern int lmLogInit(struct jfs_log * log);
extern int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize);
+extern int lmGroupCommit(struct jfs_log *, struct tblock *);
+extern int jfsIOWait(void *);
extern void jfs_flush_journal(struct jfs_log * log, int wait);
extern void jfs_syncpt(struct jfs_log *log);
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index 41bf078dce0..6c5485d16c3 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -198,7 +198,7 @@ static void init_once(void *foo, kmem_cache_t *cachep, unsigned long flags)
}
}
-static inline struct metapage *alloc_metapage(int gfp_mask)
+static inline struct metapage *alloc_metapage(unsigned int gfp_mask)
{
return mempool_alloc(metapage_mempool, gfp_mask);
}
@@ -726,12 +726,12 @@ void force_metapage(struct metapage *mp)
page_cache_release(page);
}
-extern void hold_metapage(struct metapage *mp)
+void hold_metapage(struct metapage *mp)
{
lock_page(mp->page);
}
-extern void put_metapage(struct metapage *mp)
+void put_metapage(struct metapage *mp)
{
if (mp->count || mp->nohomeok) {
/* Someone else will release this */
diff --git a/fs/jfs/jfs_metapage.h b/fs/jfs/jfs_metapage.h
index 991e9fb84c7..f0b7d3282b0 100644
--- a/fs/jfs/jfs_metapage.h
+++ b/fs/jfs/jfs_metapage.h
@@ -1,6 +1,6 @@
/*
- * Copyright (c) International Business Machines Corp., 2000-2002
- * Portions Copyright (c) Christoph Hellwig, 2001-2002
+ * Copyright (C) International Business Machines Corp., 2000-2002
+ * Portions Copyright (C) Christoph Hellwig, 2001-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
@@ -58,6 +58,8 @@ struct metapage {
#define mark_metapage_dirty(mp) set_bit(META_dirty, &(mp)->flag)
/* function prototypes */
+extern int metapage_init(void);
+extern void metapage_exit(void);
extern struct metapage *__get_metapage(struct inode *inode,
unsigned long lblock, unsigned int size,
int absolute, unsigned long new);
diff --git a/fs/jfs/jfs_superblock.h b/fs/jfs/jfs_superblock.h
index ab0566f70cf..fcf781bf31c 100644
--- a/fs/jfs/jfs_superblock.h
+++ b/fs/jfs/jfs_superblock.h
@@ -109,5 +109,16 @@ struct jfs_superblock {
extern int readSuper(struct super_block *, struct buffer_head **);
extern int updateSuper(struct super_block *, uint);
extern void jfs_error(struct super_block *, const char *, ...);
+extern int jfs_mount(struct super_block *);
+extern int jfs_mount_rw(struct super_block *, int);
+extern int jfs_umount(struct super_block *);
+extern int jfs_umount_rw(struct super_block *);
+
+extern int jfs_stop_threads;
+extern struct completion jfsIOwait;
+extern wait_queue_head_t jfs_IO_thread_wait;
+extern wait_queue_head_t jfs_commit_thread_wait;
+extern wait_queue_head_t jfs_sync_thread_wait;
+extern int jfs_extendfs(struct super_block *, s64, int);
#endif /*_H_JFS_SUPERBLOCK */
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index e93d01aa12c..121c981ff45 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -42,7 +42,6 @@
* hold on to mp+lock thru update of maps
*/
-
#include <linux/fs.h>
#include <linux/vmalloc.h>
#include <linux/smp_lock.h>
@@ -51,6 +50,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include "jfs_incore.h"
+#include "jfs_inode.h"
#include "jfs_filsys.h"
#include "jfs_metapage.h"
#include "jfs_dinode.h"
@@ -109,7 +109,6 @@ static int TxLockHWM; /* High water mark for number of txLocks used */
static int TxLockVHWM; /* Very High water mark */
struct tlock *TxLock; /* transaction lock table */
-
/*
* transaction management lock
*/
@@ -149,7 +148,6 @@ static inline void TXN_SLEEP_DROP_LOCK(wait_queue_head_t * event)
#define TXN_WAKEUP(event) wake_up_all(event)
-
/*
* statistics
*/
@@ -161,16 +159,6 @@ static struct {
int waitlock; /* 4: # of tlock wait */
} stattx;
-
-/*
- * external references
- */
-extern int lmGroupCommit(struct jfs_log *, struct tblock *);
-extern int jfs_commit_inode(struct inode *, int);
-extern int jfs_stop_threads;
-
-extern struct completion jfsIOwait;
-
/*
* forward references
*/
@@ -358,7 +346,6 @@ void txExit(void)
TxBlock = NULL;
}
-
/*
* NAME: txBegin()
*
@@ -460,7 +447,6 @@ tid_t txBegin(struct super_block *sb, int flag)
return t;
}
-
/*
* NAME: txBeginAnon()
*
@@ -503,7 +489,6 @@ void txBeginAnon(struct super_block *sb)
TXN_UNLOCK();
}
-
/*
* txEnd()
*
@@ -592,7 +577,6 @@ wakeup:
TXN_WAKEUP(&TxAnchor.freewait);
}
-
/*
* txLock()
*
@@ -868,7 +852,6 @@ struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage * mp,
return NULL;
}
-
/*
* NAME: txRelease()
*
@@ -908,7 +891,6 @@ static void txRelease(struct tblock * tblk)
TXN_UNLOCK();
}
-
/*
* NAME: txUnlock()
*
@@ -996,7 +978,6 @@ static void txUnlock(struct tblock * tblk)
}
}
-
/*
* txMaplock()
*
@@ -1069,7 +1050,6 @@ struct tlock *txMaplock(tid_t tid, struct inode *ip, int type)
return tlck;
}
-
/*
* txLinelock()
*
@@ -1103,8 +1083,6 @@ struct linelock *txLinelock(struct linelock * tlock)
return linelock;
}
-
-
/*
* transaction commit management
* -----------------------------
@@ -1373,7 +1351,6 @@ int txCommit(tid_t tid, /* transaction identifier */
return rc;
}
-
/*
* NAME: txLog()
*
@@ -1437,7 +1414,6 @@ static int txLog(struct jfs_log * log, struct tblock * tblk, struct commit * cd)
return rc;
}
-
/*
* diLog()
*
@@ -1465,7 +1441,6 @@ static int diLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
if (tlck->type & tlckENTRY) {
/* log after-image for logredo(): */
lrd->type = cpu_to_le16(LOG_REDOPAGE);
-// *pxd = mp->cm_pxd;
PXDaddress(pxd, mp->index);
PXDlength(pxd,
mp->logical_size >> tblk->sb->s_blocksize_bits);
@@ -1552,7 +1527,6 @@ static int diLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
return rc;
}
-
/*
* dataLog()
*
@@ -1599,7 +1573,6 @@ static int dataLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
return 0;
}
-
/*
* dtLog()
*
@@ -1639,7 +1612,6 @@ static void dtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
lrd->log.redopage.type |= cpu_to_le16(LOG_EXTEND);
else
lrd->log.redopage.type |= cpu_to_le16(LOG_NEW);
-// *pxd = mp->cm_pxd;
PXDaddress(pxd, mp->index);
PXDlength(pxd,
mp->logical_size >> tblk->sb->s_blocksize_bits);
@@ -1704,7 +1676,6 @@ static void dtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
return;
}
-
/*
* xtLog()
*
@@ -1760,7 +1731,6 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
* applying the after-image to the meta-data page.
*/
lrd->type = cpu_to_le16(LOG_REDOPAGE);
-// *page_pxd = mp->cm_pxd;
PXDaddress(page_pxd, mp->index);
PXDlength(page_pxd,
mp->logical_size >> tblk->sb->s_blocksize_bits);
@@ -2093,7 +2063,6 @@ static void xtLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
return;
}
-
/*
* mapLog()
*
@@ -2180,7 +2149,6 @@ void mapLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
}
}
-
/*
* txEA()
*
@@ -2233,7 +2201,6 @@ void txEA(tid_t tid, struct inode *ip, dxd_t * oldea, dxd_t * newea)
}
}
-
/*
* txForce()
*
@@ -2300,7 +2267,6 @@ void txForce(struct tblock * tblk)
}
}
-
/*
* txUpdateMap()
*
@@ -2437,7 +2403,6 @@ static void txUpdateMap(struct tblock * tblk)
}
}
-
/*
* txAllocPMap()
*
@@ -2509,7 +2474,6 @@ static void txAllocPMap(struct inode *ip, struct maplock * maplock,
}
}
-
/*
* txFreeMap()
*
@@ -2611,7 +2575,6 @@ void txFreeMap(struct inode *ip,
}
}
-
/*
* txFreelock()
*
@@ -2652,7 +2615,6 @@ void txFreelock(struct inode *ip)
TXN_UNLOCK();
}
-
/*
* txAbort()
*
@@ -2826,9 +2788,9 @@ int jfs_lazycommit(void *arg)
/* In case a wakeup came while all threads were active */
jfs_commit_thread_waking = 0;
- if (current->flags & PF_FREEZE) {
+ if (freezing(current)) {
LAZY_UNLOCK(flags);
- refrigerator(PF_FREEZE);
+ refrigerator();
} else {
DECLARE_WAITQUEUE(wq, current);
@@ -3025,9 +2987,9 @@ int jfs_sync(void *arg)
/* Add anon_list2 back to anon_list */
list_splice_init(&TxAnchor.anon_list2, &TxAnchor.anon_list);
- if (current->flags & PF_FREEZE) {
+ if (freezing(current)) {
TXN_UNLOCK();
- refrigerator(PF_FREEZE);
+ refrigerator();
} else {
DECLARE_WAITQUEUE(wq, current);
diff --git a/fs/jfs/jfs_txnmgr.h b/fs/jfs/jfs_txnmgr.h
index b71b82c2df0..59ad0f6b723 100644
--- a/fs/jfs/jfs_txnmgr.h
+++ b/fs/jfs/jfs_txnmgr.h
@@ -285,34 +285,26 @@ struct commit {
/*
* external declarations
*/
-extern struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage *mp,
- int flag);
-
-extern struct tlock *txMaplock(tid_t tid, struct inode *ip, int flag);
-
-extern int txCommit(tid_t tid, int nip, struct inode **iplist, int flag);
-
-extern tid_t txBegin(struct super_block *sb, int flag);
-
-extern void txBeginAnon(struct super_block *sb);
-
-extern void txEnd(tid_t tid);
-
-extern void txAbort(tid_t tid, int dirty);
-
-extern struct linelock *txLinelock(struct linelock * tlock);
-
-extern void txFreeMap(struct inode *ip, struct maplock * maplock,
- struct tblock * tblk, int maptype);
-
-extern void txEA(tid_t tid, struct inode *ip, dxd_t * oldea, dxd_t * newea);
-
-extern void txFreelock(struct inode *ip);
-
-extern int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
- struct tlock * tlck);
-
-extern void txQuiesce(struct super_block *sb);
-
-extern void txResume(struct super_block *sb);
+extern int jfs_tlocks_low;
+
+extern int txInit(void);
+extern void txExit(void);
+extern struct tlock *txLock(tid_t, struct inode *, struct metapage *, int);
+extern struct tlock *txMaplock(tid_t, struct inode *, int);
+extern int txCommit(tid_t, int, struct inode **, int);
+extern tid_t txBegin(struct super_block *, int);
+extern void txBeginAnon(struct super_block *);
+extern void txEnd(tid_t);
+extern void txAbort(tid_t, int);
+extern struct linelock *txLinelock(struct linelock *);
+extern void txFreeMap(struct inode *, struct maplock *, struct tblock *, int);
+extern void txEA(tid_t, struct inode *, dxd_t *, dxd_t *);
+extern void txFreelock(struct inode *);
+extern int lmLog(struct jfs_log *, struct tblock *, struct lrd *,
+ struct tlock *);
+extern void txQuiesce(struct super_block *);
+extern void txResume(struct super_block *);
+extern void txLazyUnlock(struct tblock *);
+extern int jfs_lazycommit(void *);
+extern int jfs_sync(void *);
#endif /* _H_JFS_TXNMGR */
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 8413a368f44..1cae14e741e 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -31,20 +31,9 @@
#include "jfs_acl.h"
#include "jfs_debug.h"
-extern struct inode_operations jfs_file_inode_operations;
-extern struct inode_operations jfs_symlink_inode_operations;
-extern struct file_operations jfs_file_operations;
-extern struct address_space_operations jfs_aops;
-
-extern int jfs_fsync(struct file *, struct dentry *, int);
-extern void jfs_truncate_nolock(struct inode *, loff_t);
-extern int jfs_init_acl(struct inode *, struct inode *);
-
/*
* forward references
*/
-struct inode_operations jfs_dir_inode_operations;
-struct file_operations jfs_dir_operations;
struct dentry_operations jfs_ci_dentry_operations;
static s64 commitZeroLink(tid_t, struct inode *);
@@ -655,7 +644,7 @@ static s64 commitZeroLink(tid_t tid, struct inode *ip)
/*
- * NAME: freeZeroLink()
+ * NAME: jfs_free_zero_link()
*
* FUNCTION: for non-directory, called by iClose(),
* free resources of a file from cache and WORKING map
@@ -663,15 +652,12 @@ static s64 commitZeroLink(tid_t tid, struct inode *ip)
* while associated with a pager object,
*
* PARAMETER: ip - pointer to inode of file.
- *
- * RETURN: 0 -ok
*/
-int freeZeroLink(struct inode *ip)
+void jfs_free_zero_link(struct inode *ip)
{
- int rc = 0;
int type;
- jfs_info("freeZeroLink: ip = 0x%p", ip);
+ jfs_info("jfs_free_zero_link: ip = 0x%p", ip);
/* return if not reg or symbolic link or if size is
* already ok.
@@ -684,10 +670,10 @@ int freeZeroLink(struct inode *ip)
case S_IFLNK:
/* if its contained in inode nothing to do */
if (ip->i_size < IDATASIZE)
- return 0;
+ return;
break;
default:
- return 0;
+ return;
}
/*
@@ -737,9 +723,7 @@ int freeZeroLink(struct inode *ip)
* free xtree/data blocks from working block map;
*/
if (ip->i_size)
- rc = xtTruncate(0, ip, 0, COMMIT_WMAP);
-
- return rc;
+ xtTruncate(0, ip, 0, COMMIT_WMAP);
}
/*
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 5e774ed7fb6..ee32211288c 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -24,10 +24,12 @@
#include <linux/completion.h>
#include <linux/vfs.h>
#include <linux/moduleparam.h>
+#include <linux/posix_acl.h>
#include <asm/uaccess.h>
#include "jfs_incore.h"
#include "jfs_filsys.h"
+#include "jfs_inode.h"
#include "jfs_metapage.h"
#include "jfs_superblock.h"
#include "jfs_dmap.h"
@@ -62,37 +64,6 @@ module_param(jfsloglevel, int, 0644);
MODULE_PARM_DESC(jfsloglevel, "Specify JFS loglevel (0, 1 or 2)");
#endif
-/*
- * External declarations
- */
-extern int jfs_mount(struct super_block *);
-extern int jfs_mount_rw(struct super_block *, int);
-extern int jfs_umount(struct super_block *);
-extern int jfs_umount_rw(struct super_block *);
-
-extern int jfsIOWait(void *);
-extern int jfs_lazycommit(void *);
-extern int jfs_sync(void *);
-
-extern void jfs_read_inode(struct inode *inode);
-extern void jfs_dirty_inode(struct inode *inode);
-extern void jfs_delete_inode(struct inode *inode);
-extern int jfs_write_inode(struct inode *inode, int wait);
-
-extern struct dentry *jfs_get_parent(struct dentry *dentry);
-extern int jfs_extendfs(struct super_block *, s64, int);
-
-extern struct dentry_operations jfs_ci_dentry_operations;
-
-#ifdef PROC_FS_JFS /* see jfs_debug.h */
-extern void jfs_proc_init(void);
-extern void jfs_proc_clean(void);
-#endif
-
-extern wait_queue_head_t jfs_IO_thread_wait;
-extern wait_queue_head_t jfs_commit_thread_wait;
-extern wait_queue_head_t jfs_sync_thread_wait;
-
static void jfs_handle_error(struct super_block *sb)
{
struct jfs_sb_info *sbi = JFS_SBI(sb);
@@ -593,11 +564,6 @@ static struct file_system_type jfs_fs_type = {
.fs_flags = FS_REQUIRES_DEV,
};
-extern int metapage_init(void);
-extern int txInit(void);
-extern void txExit(void);
-extern void metapage_exit(void);
-
static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
{
struct jfs_inode_info *jfs_ip = (struct jfs_inode_info *) foo;
diff --git a/fs/jfs/symlink.c b/fs/jfs/symlink.c
index ef4c07ee92b..287d8d6c3cf 100644
--- a/fs/jfs/symlink.c
+++ b/fs/jfs/symlink.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) Christoph Hellwig, 2001-2002
+ * Copyright (C) Christoph Hellwig, 2001-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
@@ -19,6 +19,7 @@
#include <linux/fs.h>
#include <linux/namei.h>
#include "jfs_incore.h"
+#include "jfs_inode.h"
#include "jfs_xattr.h"
static int jfs_follow_link(struct dentry *dentry, struct nameidata *nd)
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index 7a9ffd5d03d..ee438d429d4 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -19,6 +19,7 @@
#include <linux/fs.h>
#include <linux/xattr.h>
+#include <linux/posix_acl_xattr.h>
#include <linux/quotaops.h>
#include "jfs_incore.h"
#include "jfs_superblock.h"
@@ -718,9 +719,9 @@ static int can_set_system_xattr(struct inode *inode, const char *name,
return -EPERM;
/*
- * XATTR_NAME_ACL_ACCESS is tied to i_mode
+ * POSIX_ACL_XATTR_ACCESS is tied to i_mode
*/
- if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0) {
+ if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0) {
acl = posix_acl_from_xattr(value, value_len);
if (IS_ERR(acl)) {
rc = PTR_ERR(acl);
@@ -750,7 +751,7 @@ static int can_set_system_xattr(struct inode *inode, const char *name,
JFS_IP(inode)->i_acl = JFS_ACL_NOT_CACHED;
return 0;
- } else if (strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0) {
+ } else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0) {
acl = posix_acl_from_xattr(value, value_len);
if (IS_ERR(acl)) {
rc = PTR_ERR(acl);
@@ -946,8 +947,7 @@ int __jfs_setxattr(struct inode *inode, const char *name, const void *value,
out:
up_write(&JFS_IP(inode)->xattr_sem);
- if (os2name)
- kfree(os2name);
+ kfree(os2name);
return rc;
}
@@ -1042,8 +1042,7 @@ ssize_t __jfs_getxattr(struct inode *inode, const char *name, void *data,
out:
up_read(&JFS_IP(inode)->xattr_sem);
- if (os2name)
- kfree(os2name);
+ kfree(os2name);
return size;
}
diff --git a/fs/libfs.c b/fs/libfs.c
index f90b2959592..58101dff2c6 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -183,6 +183,7 @@ struct file_operations simple_dir_operations = {
.llseek = dcache_dir_lseek,
.read = generic_read_dir,
.readdir = dcache_readdir,
+ .fsync = simple_sync_file,
};
struct inode_operations simple_dir_inode_operations = {
@@ -519,6 +520,102 @@ int simple_transaction_release(struct inode *inode, struct file *file)
return 0;
}
+/* Simple attribute files */
+
+struct simple_attr {
+ u64 (*get)(void *);
+ void (*set)(void *, u64);
+ char get_buf[24]; /* enough to store a u64 and "\n\0" */
+ char set_buf[24];
+ void *data;
+ const char *fmt; /* format for read operation */
+ struct semaphore sem; /* protects access to these buffers */
+};
+
+/* simple_attr_open is called by an actual attribute open file operation
+ * to set the attribute specific access operations. */
+int simple_attr_open(struct inode *inode, struct file *file,
+ u64 (*get)(void *), void (*set)(void *, u64),
+ const char *fmt)
+{
+ struct simple_attr *attr;
+
+ attr = kmalloc(sizeof(*attr), GFP_KERNEL);
+ if (!attr)
+ return -ENOMEM;
+
+ attr->get = get;
+ attr->set = set;
+ attr->data = inode->u.generic_ip;
+ attr->fmt = fmt;
+ init_MUTEX(&attr->sem);
+
+ file->private_data = attr;
+
+ return nonseekable_open(inode, file);
+}
+
+int simple_attr_close(struct inode *inode, struct file *file)
+{
+ kfree(file->private_data);
+ return 0;
+}
+
+/* read from the buffer that is filled with the get function */
+ssize_t simple_attr_read(struct file *file, char __user *buf,
+ size_t len, loff_t *ppos)
+{
+ struct simple_attr *attr;
+ size_t size;
+ ssize_t ret;
+
+ attr = file->private_data;
+
+ if (!attr->get)
+ return -EACCES;
+
+ down(&attr->sem);
+ if (*ppos) /* continued read */
+ size = strlen(attr->get_buf);
+ else /* first read */
+ size = scnprintf(attr->get_buf, sizeof(attr->get_buf),
+ attr->fmt,
+ (unsigned long long)attr->get(attr->data));
+
+ ret = simple_read_from_buffer(buf, len, ppos, attr->get_buf, size);
+ up(&attr->sem);
+ return ret;
+}
+
+/* interpret the buffer as a number to call the set function with */
+ssize_t simple_attr_write(struct file *file, const char __user *buf,
+ size_t len, loff_t *ppos)
+{
+ struct simple_attr *attr;
+ u64 val;
+ size_t size;
+ ssize_t ret;
+
+ attr = file->private_data;
+
+ if (!attr->set)
+ return -EACCES;
+
+ down(&attr->sem);
+ ret = -EFAULT;
+ size = min(sizeof(attr->set_buf) - 1, len);
+ if (copy_from_user(attr->set_buf, buf, size))
+ goto out;
+
+ ret = len; /* claim we got the whole input */
+ attr->set_buf[size] = '\0';
+ val = simple_strtol(attr->set_buf, NULL, 0);
+ attr->set(attr->data, val);
+out:
+ up(&attr->sem);
+ return ret;
+}
+
EXPORT_SYMBOL(dcache_dir_close);
EXPORT_SYMBOL(dcache_dir_lseek);
EXPORT_SYMBOL(dcache_dir_open);
@@ -547,3 +644,7 @@ EXPORT_SYMBOL(simple_read_from_buffer);
EXPORT_SYMBOL(simple_transaction_get);
EXPORT_SYMBOL(simple_transaction_read);
EXPORT_SYMBOL(simple_transaction_release);
+EXPORT_SYMBOL_GPL(simple_attr_open);
+EXPORT_SYMBOL_GPL(simple_attr_close);
+EXPORT_SYMBOL_GPL(simple_attr_read);
+EXPORT_SYMBOL_GPL(simple_attr_write);
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index ef7103b8c5b..006bb9e1457 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -31,7 +31,7 @@ static int reclaimer(void *ptr);
* This is the representation of a blocked client lock.
*/
struct nlm_wait {
- struct nlm_wait * b_next; /* linked list */
+ struct list_head b_list; /* linked list */
wait_queue_head_t b_wait; /* where to wait on */
struct nlm_host * b_host;
struct file_lock * b_lock; /* local file lock */
@@ -39,27 +39,54 @@ struct nlm_wait {
u32 b_status; /* grant callback status */
};
-static struct nlm_wait * nlm_blocked;
+static LIST_HEAD(nlm_blocked);
/*
- * Block on a lock
+ * Queue up a lock for blocking so that the GRANTED request can see it
*/
-int
-nlmclnt_block(struct nlm_host *host, struct file_lock *fl, u32 *statp)
+int nlmclnt_prepare_block(struct nlm_rqst *req, struct nlm_host *host, struct file_lock *fl)
+{
+ struct nlm_wait *block;
+
+ BUG_ON(req->a_block != NULL);
+ block = kmalloc(sizeof(*block), GFP_KERNEL);
+ if (block == NULL)
+ return -ENOMEM;
+ block->b_host = host;
+ block->b_lock = fl;
+ init_waitqueue_head(&block->b_wait);
+ block->b_status = NLM_LCK_BLOCKED;
+
+ list_add(&block->b_list, &nlm_blocked);
+ req->a_block = block;
+
+ return 0;
+}
+
+void nlmclnt_finish_block(struct nlm_rqst *req)
{
- struct nlm_wait block, **head;
- int err;
- u32 pstate;
+ struct nlm_wait *block = req->a_block;
- block.b_host = host;
- block.b_lock = fl;
- init_waitqueue_head(&block.b_wait);
- block.b_status = NLM_LCK_BLOCKED;
- block.b_next = nlm_blocked;
- nlm_blocked = &block;
+ if (block == NULL)
+ return;
+ req->a_block = NULL;
+ list_del(&block->b_list);
+ kfree(block);
+}
+
+/*
+ * Block on a lock
+ */
+long nlmclnt_block(struct nlm_rqst *req, long timeout)
+{
+ struct nlm_wait *block = req->a_block;
+ long ret;
- /* Remember pseudo nsm state */
- pstate = host->h_state;
+ /* A borken server might ask us to block even if we didn't
+ * request it. Just say no!
+ */
+ if (!req->a_args.block)
+ return -EAGAIN;
/* Go to sleep waiting for GRANT callback. Some servers seem
* to lose callbacks, however, so we're going to poll from
@@ -69,28 +96,16 @@ nlmclnt_block(struct nlm_host *host, struct file_lock *fl, u32 *statp)
* a 1 minute timeout would do. See the comment before
* nlmclnt_lock for an explanation.
*/
- sleep_on_timeout(&block.b_wait, 30*HZ);
-
- for (head = &nlm_blocked; *head; head = &(*head)->b_next) {
- if (*head == &block) {
- *head = block.b_next;
- break;
- }
- }
+ ret = wait_event_interruptible_timeout(block->b_wait,
+ block->b_status != NLM_LCK_BLOCKED,
+ timeout);
- if (!signalled()) {
- *statp = block.b_status;
- return 0;
+ if (block->b_status != NLM_LCK_BLOCKED) {
+ req->a_res.status = block->b_status;
+ block->b_status = NLM_LCK_BLOCKED;
}
- /* Okay, we were interrupted. Cancel the pending request
- * unless the server has rebooted.
- */
- if (pstate == host->h_state && (err = nlmclnt_cancel(host, fl)) < 0)
- printk(KERN_NOTICE
- "lockd: CANCEL call failed (errno %d)\n", -err);
-
- return -ERESTARTSYS;
+ return ret;
}
/*
@@ -100,27 +115,23 @@ u32
nlmclnt_grant(struct nlm_lock *lock)
{
struct nlm_wait *block;
+ u32 res = nlm_lck_denied;
/*
* Look up blocked request based on arguments.
* Warning: must not use cookie to match it!
*/
- for (block = nlm_blocked; block; block = block->b_next) {
- if (nlm_compare_locks(block->b_lock, &lock->fl))
- break;
+ list_for_each_entry(block, &nlm_blocked, b_list) {
+ if (nlm_compare_locks(block->b_lock, &lock->fl)) {
+ /* Alright, we found a lock. Set the return status
+ * and wake up the caller
+ */
+ block->b_status = NLM_LCK_GRANTED;
+ wake_up(&block->b_wait);
+ res = nlm_granted;
+ }
}
-
- /* Ooops, no blocked request found. */
- if (block == NULL)
- return nlm_lck_denied;
-
- /* Alright, we found the lock. Set the return status and
- * wake up the caller.
- */
- block->b_status = NLM_LCK_GRANTED;
- wake_up(&block->b_wait);
-
- return nlm_granted;
+ return res;
}
/*
@@ -230,7 +241,7 @@ restart:
host->h_reclaiming = 0;
/* Now, wake up all processes that sleep on a blocked lock */
- for (block = nlm_blocked; block; block = block->b_next) {
+ list_for_each_entry(block, &nlm_blocked, b_list) {
if (block->b_host == host) {
block->b_status = NLM_LCK_DENIED_GRACE_PERIOD;
wake_up(&block->b_wait);
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index a4407619b1f..14b3ce87fa2 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -21,6 +21,7 @@
#define NLMDBG_FACILITY NLMDBG_CLIENT
#define NLMCLNT_GRACE_WAIT (5*HZ)
+#define NLMCLNT_POLL_TIMEOUT (30*HZ)
static int nlmclnt_test(struct nlm_rqst *, struct file_lock *);
static int nlmclnt_lock(struct nlm_rqst *, struct file_lock *);
@@ -312,7 +313,7 @@ static int nlm_wait_on_grace(wait_queue_head_t *queue)
prepare_to_wait(queue, &wait, TASK_INTERRUPTIBLE);
if (!signalled ()) {
schedule_timeout(NLMCLNT_GRACE_WAIT);
- try_to_freeze(PF_FREEZE);
+ try_to_freeze();
if (!signalled ())
status = 0;
}
@@ -553,7 +554,8 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
{
struct nlm_host *host = req->a_host;
struct nlm_res *resp = &req->a_res;
- int status;
+ long timeout;
+ int status;
if (!host->h_monitored && nsm_monitor(host) < 0) {
printk(KERN_NOTICE "lockd: failed to monitor %s\n",
@@ -562,15 +564,32 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
goto out;
}
- do {
- if ((status = nlmclnt_call(req, NLMPROC_LOCK)) >= 0) {
- if (resp->status != NLM_LCK_BLOCKED)
- break;
- status = nlmclnt_block(host, fl, &resp->status);
- }
+ if (req->a_args.block) {
+ status = nlmclnt_prepare_block(req, host, fl);
if (status < 0)
goto out;
- } while (resp->status == NLM_LCK_BLOCKED && req->a_args.block);
+ }
+ for(;;) {
+ status = nlmclnt_call(req, NLMPROC_LOCK);
+ if (status < 0)
+ goto out_unblock;
+ if (resp->status != NLM_LCK_BLOCKED)
+ break;
+ /* Wait on an NLM blocking lock */
+ timeout = nlmclnt_block(req, NLMCLNT_POLL_TIMEOUT);
+ /* Did a reclaimer thread notify us of a server reboot? */
+ if (resp->status == NLM_LCK_DENIED_GRACE_PERIOD)
+ continue;
+ if (resp->status != NLM_LCK_BLOCKED)
+ break;
+ if (timeout >= 0)
+ continue;
+ /* We were interrupted. Send a CANCEL request to the server
+ * and exit
+ */
+ status = (int)timeout;
+ goto out_unblock;
+ }
if (resp->status == NLM_LCK_GRANTED) {
fl->fl_u.nfs_fl.state = host->h_state;
@@ -579,6 +598,11 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
do_vfs_lock(fl);
}
status = nlm_stat_to_errno(resp->status);
+out_unblock:
+ nlmclnt_finish_block(req);
+ /* Cancel the blocked request if it is still pending */
+ if (resp->status == NLM_LCK_BLOCKED)
+ nlmclnt_cancel(host, fl);
out:
nlmclnt_release_lockargs(req);
return status;
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 52707c5ad6e..82c77df81c5 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -189,17 +189,15 @@ nlm_bind_host(struct nlm_host *host)
goto forgetit;
xprt_set_timeout(&xprt->timeout, 5, nlmsvc_timeout);
+ xprt->nocong = 1; /* No congestion control for NLM */
+ xprt->resvport = 1; /* NLM requires a reserved port */
/* Existing NLM servers accept AUTH_UNIX only */
clnt = rpc_create_client(xprt, host->h_name, &nlm_program,
host->h_version, RPC_AUTH_UNIX);
- if (IS_ERR(clnt)) {
- xprt_destroy(xprt);
+ if (IS_ERR(clnt))
goto forgetit;
- }
clnt->cl_autobind = 1; /* turn on pmap queries */
- xprt->nocong = 1; /* No congestion control for NLM */
- xprt->resvport = 1; /* NLM requires a reserved port */
host->h_rpcclnt = clnt;
}
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 6fc1bebeec1..2d144abe84a 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -115,20 +115,19 @@ nsm_create(void)
xprt = xprt_create_proto(IPPROTO_UDP, &sin, NULL);
if (IS_ERR(xprt))
return (struct rpc_clnt *)xprt;
+ xprt->resvport = 1; /* NSM requires a reserved port */
clnt = rpc_create_client(xprt, "localhost",
&nsm_program, SM_VERSION,
RPC_AUTH_NULL);
if (IS_ERR(clnt))
- goto out_destroy;
+ goto out_err;
clnt->cl_softrtry = 1;
clnt->cl_chatty = 1;
clnt->cl_oneshot = 1;
- xprt->resvport = 1; /* NSM requires a reserved port */
return clnt;
-out_destroy:
- xprt_destroy(xprt);
+out_err:
return clnt;
}
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index b82e470912e..6e242556b90 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -191,7 +191,9 @@ lockd(struct svc_rqst *rqstp)
printk(KERN_DEBUG
"lockd: new process, skipping host shutdown\n");
wake_up(&lockd_exit);
-
+
+ flush_signals(current);
+
/* Exit the RPC thread */
svc_exit_thread(rqstp);
diff --git a/fs/locks.c b/fs/locks.c
index 3fa6a7ce57a..a0bc03495bd 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1548,6 +1548,8 @@ int fcntl_getlk(struct file *filp, struct flock __user *l)
if (filp->f_op && filp->f_op->lock) {
error = filp->f_op->lock(filp, F_GETLK, &file_lock);
+ if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
+ file_lock.fl_ops->fl_release_private(&file_lock);
if (error < 0)
goto out;
else
@@ -1690,6 +1692,8 @@ int fcntl_getlk64(struct file *filp, struct flock64 __user *l)
if (filp->f_op && filp->f_op->lock) {
error = filp->f_op->lock(filp, F_GETLK, &file_lock);
+ if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
+ file_lock.fl_ops->fl_release_private(&file_lock);
if (error < 0)
goto out;
else
@@ -1873,6 +1877,8 @@ void locks_remove_flock(struct file *filp)
.fl_end = OFFSET_MAX,
};
filp->f_op->flock(filp, F_SETLKW, &fl);
+ if (fl.fl_ops && fl.fl_ops->fl_release_private)
+ fl.fl_ops->fl_release_private(&fl);
}
lock_kernel();
diff --git a/fs/mpage.c b/fs/mpage.c
index b92c0e64aef..bb9aebe9386 100644
--- a/fs/mpage.c
+++ b/fs/mpage.c
@@ -79,8 +79,11 @@ static int mpage_end_io_write(struct bio *bio, unsigned int bytes_done, int err)
if (--bvec >= bio->bi_io_vec)
prefetchw(&bvec->bv_page->flags);
- if (!uptodate)
+ if (!uptodate){
SetPageError(page);
+ if (page->mapping)
+ set_bit(AS_EIO, &page->mapping->flags);
+ }
end_page_writeback(page);
} while (bvec >= bio->bi_io_vec);
bio_put(bio);
diff --git a/fs/namei.c b/fs/namei.c
index defe6781e00..fa8df81ce8c 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -493,12 +493,21 @@ fail:
return PTR_ERR(link);
}
-static inline int __do_follow_link(struct dentry *dentry, struct nameidata *nd)
+struct path {
+ struct vfsmount *mnt;
+ struct dentry *dentry;
+};
+
+static inline int __do_follow_link(struct path *path, struct nameidata *nd)
{
int error;
+ struct dentry *dentry = path->dentry;
- touch_atime(nd->mnt, dentry);
+ touch_atime(path->mnt, dentry);
nd_set_link(nd, NULL);
+
+ if (path->mnt == nd->mnt)
+ mntget(path->mnt);
error = dentry->d_inode->i_op->follow_link(dentry, nd);
if (!error) {
char *s = nd_get_link(nd);
@@ -507,6 +516,8 @@ static inline int __do_follow_link(struct dentry *dentry, struct nameidata *nd)
if (dentry->d_inode->i_op->put_link)
dentry->d_inode->i_op->put_link(dentry, nd);
}
+ dput(dentry);
+ mntput(path->mnt);
return error;
}
@@ -518,7 +529,7 @@ static inline int __do_follow_link(struct dentry *dentry, struct nameidata *nd)
* Without that kind of total limit, nasty chains of consecutive
* symlinks can cause almost arbitrarily long lookups.
*/
-static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd)
+static inline int do_follow_link(struct path *path, struct nameidata *nd)
{
int err = -ELOOP;
if (current->link_count >= MAX_NESTED_LINKS)
@@ -527,17 +538,20 @@ static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd)
goto loop;
BUG_ON(nd->depth >= MAX_NESTED_LINKS);
cond_resched();
- err = security_inode_follow_link(dentry, nd);
+ err = security_inode_follow_link(path->dentry, nd);
if (err)
goto loop;
current->link_count++;
current->total_link_count++;
nd->depth++;
- err = __do_follow_link(dentry, nd);
+ err = __do_follow_link(path, nd);
current->link_count--;
nd->depth--;
return err;
loop:
+ dput(path->dentry);
+ if (path->mnt != nd->mnt)
+ mntput(path->mnt);
path_release(nd);
return err;
}
@@ -565,87 +579,91 @@ int follow_up(struct vfsmount **mnt, struct dentry **dentry)
/* no need for dcache_lock, as serialization is taken care in
* namespace.c
*/
-static int follow_mount(struct vfsmount **mnt, struct dentry **dentry)
+static int __follow_mount(struct path *path)
{
int res = 0;
+ while (d_mountpoint(path->dentry)) {
+ struct vfsmount *mounted = lookup_mnt(path->mnt, path->dentry);
+ if (!mounted)
+ break;
+ dput(path->dentry);
+ if (res)
+ mntput(path->mnt);
+ path->mnt = mounted;
+ path->dentry = dget(mounted->mnt_root);
+ res = 1;
+ }
+ return res;
+}
+
+static void follow_mount(struct vfsmount **mnt, struct dentry **dentry)
+{
while (d_mountpoint(*dentry)) {
struct vfsmount *mounted = lookup_mnt(*mnt, *dentry);
if (!mounted)
break;
+ dput(*dentry);
mntput(*mnt);
*mnt = mounted;
- dput(*dentry);
*dentry = dget(mounted->mnt_root);
- res = 1;
}
- return res;
}
/* no need for dcache_lock, as serialization is taken care in
* namespace.c
*/
-static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry)
+int follow_down(struct vfsmount **mnt, struct dentry **dentry)
{
struct vfsmount *mounted;
mounted = lookup_mnt(*mnt, *dentry);
if (mounted) {
+ dput(*dentry);
mntput(*mnt);
*mnt = mounted;
- dput(*dentry);
*dentry = dget(mounted->mnt_root);
return 1;
}
return 0;
}
-int follow_down(struct vfsmount **mnt, struct dentry **dentry)
-{
- return __follow_down(mnt,dentry);
-}
-
-static inline void follow_dotdot(struct vfsmount **mnt, struct dentry **dentry)
+static inline void follow_dotdot(struct nameidata *nd)
{
while(1) {
struct vfsmount *parent;
- struct dentry *old = *dentry;
+ struct dentry *old = nd->dentry;
read_lock(&current->fs->lock);
- if (*dentry == current->fs->root &&
- *mnt == current->fs->rootmnt) {
+ if (nd->dentry == current->fs->root &&
+ nd->mnt == current->fs->rootmnt) {
read_unlock(&current->fs->lock);
break;
}
read_unlock(&current->fs->lock);
spin_lock(&dcache_lock);
- if (*dentry != (*mnt)->mnt_root) {
- *dentry = dget((*dentry)->d_parent);
+ if (nd->dentry != nd->mnt->mnt_root) {
+ nd->dentry = dget(nd->dentry->d_parent);
spin_unlock(&dcache_lock);
dput(old);
break;
}
spin_unlock(&dcache_lock);
spin_lock(&vfsmount_lock);
- parent = (*mnt)->mnt_parent;
- if (parent == *mnt) {
+ parent = nd->mnt->mnt_parent;
+ if (parent == nd->mnt) {
spin_unlock(&vfsmount_lock);
break;
}
mntget(parent);
- *dentry = dget((*mnt)->mnt_mountpoint);
+ nd->dentry = dget(nd->mnt->mnt_mountpoint);
spin_unlock(&vfsmount_lock);
dput(old);
- mntput(*mnt);
- *mnt = parent;
+ mntput(nd->mnt);
+ nd->mnt = parent;
}
- follow_mount(mnt, dentry);
+ follow_mount(&nd->mnt, &nd->dentry);
}
-struct path {
- struct vfsmount *mnt;
- struct dentry *dentry;
-};
-
/*
* It's more convoluted than I'd like it to be, but... it's still fairly
* small and for now I'd prefer to have fast path as straight as possible.
@@ -664,6 +682,7 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
done:
path->mnt = mnt;
path->dentry = dentry;
+ __follow_mount(path);
return 0;
need_lookup:
@@ -751,7 +770,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
case 2:
if (this.name[1] != '.')
break;
- follow_dotdot(&nd->mnt, &nd->dentry);
+ follow_dotdot(nd);
inode = nd->dentry->d_inode;
/* fallthrough */
case 1:
@@ -771,8 +790,6 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
err = do_lookup(nd, &this, &next);
if (err)
break;
- /* Check mountpoints.. */
- follow_mount(&next.mnt, &next.dentry);
err = -ENOENT;
inode = next.dentry->d_inode;
@@ -783,10 +800,7 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
goto out_dput;
if (inode->i_op->follow_link) {
- mntget(next.mnt);
- err = do_follow_link(next.dentry, nd);
- dput(next.dentry);
- mntput(next.mnt);
+ err = do_follow_link(&next, nd);
if (err)
goto return_err;
err = -ENOENT;
@@ -798,6 +812,8 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
break;
} else {
dput(nd->dentry);
+ if (nd->mnt != next.mnt)
+ mntput(nd->mnt);
nd->mnt = next.mnt;
nd->dentry = next.dentry;
}
@@ -819,7 +835,7 @@ last_component:
case 2:
if (this.name[1] != '.')
break;
- follow_dotdot(&nd->mnt, &nd->dentry);
+ follow_dotdot(nd);
inode = nd->dentry->d_inode;
/* fallthrough */
case 1:
@@ -833,19 +849,17 @@ last_component:
err = do_lookup(nd, &this, &next);
if (err)
break;
- follow_mount(&next.mnt, &next.dentry);
inode = next.dentry->d_inode;
if ((lookup_flags & LOOKUP_FOLLOW)
&& inode && inode->i_op && inode->i_op->follow_link) {
- mntget(next.mnt);
- err = do_follow_link(next.dentry, nd);
- dput(next.dentry);
- mntput(next.mnt);
+ err = do_follow_link(&next, nd);
if (err)
goto return_err;
inode = nd->dentry->d_inode;
} else {
dput(nd->dentry);
+ if (nd->mnt != next.mnt)
+ mntput(nd->mnt);
nd->mnt = next.mnt;
nd->dentry = next.dentry;
}
@@ -885,6 +899,8 @@ return_base:
return 0;
out_dput:
dput(next.dentry);
+ if (nd->mnt != next.mnt)
+ mntput(next.mnt);
break;
}
path_release(nd);
@@ -1398,7 +1414,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
{
int acc_mode, error = 0;
- struct dentry *dentry;
+ struct path path;
struct dentry *dir;
int count = 0;
@@ -1442,23 +1458,24 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
dir = nd->dentry;
nd->flags &= ~LOOKUP_PARENT;
down(&dir->d_inode->i_sem);
- dentry = __lookup_hash(&nd->last, nd->dentry, nd);
+ path.dentry = __lookup_hash(&nd->last, nd->dentry, nd);
+ path.mnt = nd->mnt;
do_last:
- error = PTR_ERR(dentry);
- if (IS_ERR(dentry)) {
+ error = PTR_ERR(path.dentry);
+ if (IS_ERR(path.dentry)) {
up(&dir->d_inode->i_sem);
goto exit;
}
/* Negative dentry, just create the file */
- if (!dentry->d_inode) {
+ if (!path.dentry->d_inode) {
if (!IS_POSIXACL(dir->d_inode))
mode &= ~current->fs->umask;
- error = vfs_create(dir->d_inode, dentry, mode, nd);
+ error = vfs_create(dir->d_inode, path.dentry, mode, nd);
up(&dir->d_inode->i_sem);
dput(nd->dentry);
- nd->dentry = dentry;
+ nd->dentry = path.dentry;
if (error)
goto exit;
/* Don't check for write permission, don't truncate */
@@ -1476,22 +1493,24 @@ do_last:
if (flag & O_EXCL)
goto exit_dput;
- if (d_mountpoint(dentry)) {
+ if (__follow_mount(&path)) {
error = -ELOOP;
if (flag & O_NOFOLLOW)
goto exit_dput;
- while (__follow_down(&nd->mnt,&dentry) && d_mountpoint(dentry));
}
error = -ENOENT;
- if (!dentry->d_inode)
+ if (!path.dentry->d_inode)
goto exit_dput;
- if (dentry->d_inode->i_op && dentry->d_inode->i_op->follow_link)
+ if (path.dentry->d_inode->i_op && path.dentry->d_inode->i_op->follow_link)
goto do_link;
dput(nd->dentry);
- nd->dentry = dentry;
+ nd->dentry = path.dentry;
+ if (nd->mnt != path.mnt)
+ mntput(nd->mnt);
+ nd->mnt = path.mnt;
error = -EISDIR;
- if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode))
+ if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode))
goto exit;
ok:
error = may_open(nd, acc_mode, flag);
@@ -1500,7 +1519,9 @@ ok:
return 0;
exit_dput:
- dput(dentry);
+ dput(path.dentry);
+ if (nd->mnt != path.mnt)
+ mntput(path.mnt);
exit:
path_release(nd);
return error;
@@ -1520,18 +1541,15 @@ do_link:
* are done. Procfs-like symlinks just set LAST_BIND.
*/
nd->flags |= LOOKUP_PARENT;
- error = security_inode_follow_link(dentry, nd);
+ error = security_inode_follow_link(path.dentry, nd);
if (error)
goto exit_dput;
- error = __do_follow_link(dentry, nd);
- dput(dentry);
+ error = __do_follow_link(&path, nd);
if (error)
return error;
nd->flags &= ~LOOKUP_PARENT;
- if (nd->last_type == LAST_BIND) {
- dentry = nd->dentry;
+ if (nd->last_type == LAST_BIND)
goto ok;
- }
error = -EISDIR;
if (nd->last_type != LAST_NORM)
goto exit;
@@ -1546,7 +1564,8 @@ do_link:
}
dir = nd->dentry;
down(&dir->d_inode->i_sem);
- dentry = __lookup_hash(&nd->last, nd->dentry, nd);
+ path.dentry = __lookup_hash(&nd->last, nd->dentry, nd);
+ path.mnt = nd->mnt;
putname(nd->last.name);
goto do_last;
}
@@ -1558,19 +1577,35 @@ do_link:
*
* Simple function to lookup and return a dentry and create it
* if it doesn't exist. Is SMP-safe.
+ *
+ * Returns with nd->dentry->d_inode->i_sem locked.
*/
struct dentry *lookup_create(struct nameidata *nd, int is_dir)
{
- struct dentry *dentry;
+ struct dentry *dentry = ERR_PTR(-EEXIST);
down(&nd->dentry->d_inode->i_sem);
- dentry = ERR_PTR(-EEXIST);
+ /*
+ * Yucky last component or no last component at all?
+ * (foo/., foo/.., /////)
+ */
if (nd->last_type != LAST_NORM)
goto fail;
nd->flags &= ~LOOKUP_PARENT;
+
+ /*
+ * Do the final lookup.
+ */
dentry = lookup_hash(&nd->last, nd->dentry);
if (IS_ERR(dentry))
goto fail;
+
+ /*
+ * Special case - lookup gave negative, but... we had foo/bar/
+ * From the vfs_mknod() POV we just have a negative dentry -
+ * all is fine. Let's be bastards - you had / on the end, you've
+ * been asking for (non-existent) directory. -ENOENT for you.
+ */
if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
goto enoent;
return dentry;
@@ -1580,6 +1615,7 @@ enoent:
fail:
return dentry;
}
+EXPORT_SYMBOL_GPL(lookup_create);
int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
{
diff --git a/fs/namespace.c b/fs/namespace.c
index 3b93e5d750e..208c079e9fd 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -337,7 +337,7 @@ int may_umount(struct vfsmount *mnt)
EXPORT_SYMBOL(may_umount);
-void umount_tree(struct vfsmount *mnt)
+static void umount_tree(struct vfsmount *mnt)
{
struct vfsmount *p;
LIST_HEAD(kill);
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index 2dc2d869396..a9f7a8ab1d5 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -705,18 +705,6 @@ ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
DPRINTK("ncp_do_readdir: init failed, err=%d\n", err);
return;
}
-#ifdef USE_OLD_SLOW_DIRECTORY_LISTING
- for (;;) {
- err = ncp_search_for_file_or_subdir(server, &seq, &entry.i);
- if (err) {
- DPRINTK("ncp_do_readdir: search failed, err=%d\n", err);
- break;
- }
- entry.volume = entry.i.volNumber;
- if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry))
- break;
- }
-#else
/* We MUST NOT use server->buffer_size handshaked with server if we are
using UDP, as for UDP server uses max. buffer size determined by
MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes).
@@ -754,7 +742,6 @@ ncp_do_readdir(struct file *filp, void *dirent, filldir_t filldir,
}
} while (more);
vfree(buf);
-#endif
return;
}
diff --git a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c
index e4eb5ed4bee..c755e1848a4 100644
--- a/fs/ncpfs/ncplib_kernel.c
+++ b/fs/ncpfs/ncplib_kernel.c
@@ -845,46 +845,6 @@ out:
return result;
}
-/* Search for everything */
-int ncp_search_for_file_or_subdir(struct ncp_server *server,
- struct nw_search_sequence *seq,
- struct nw_info_struct *target)
-{
- int result;
-
- ncp_init_request(server);
- ncp_add_byte(server, 3); /* subfunction */
- ncp_add_byte(server, server->name_space[seq->volNumber]);
- ncp_add_byte(server, 0); /* data stream (???) */
- ncp_add_word(server, cpu_to_le16(0x8006)); /* Search attribs */
- ncp_add_dword(server, RIM_ALL); /* return info mask */
- ncp_add_mem(server, seq, 9);
-#ifdef CONFIG_NCPFS_NFS_NS
- if (server->name_space[seq->volNumber] == NW_NS_NFS) {
- ncp_add_byte(server, 0); /* 0 byte pattern */
- } else
-#endif
- {
- ncp_add_byte(server, 2); /* 2 byte pattern */
- ncp_add_byte(server, 0xff); /* following is a wildcard */
- ncp_add_byte(server, '*');
- }
-
- if ((result = ncp_request(server, 87)) != 0)
- goto out;
- memcpy(seq, ncp_reply_data(server, 0), sizeof(*seq));
- ncp_extract_file_info(ncp_reply_data(server, 10), target);
-
- ncp_unlock_server(server);
-
- result = ncp_obtain_nfs_info(server, target);
- return result;
-
-out:
- ncp_unlock_server(server);
- return result;
-}
-
int ncp_search_for_fileset(struct ncp_server *server,
struct nw_search_sequence *seq,
int* more,
diff --git a/fs/ncpfs/ncplib_kernel.h b/fs/ncpfs/ncplib_kernel.h
index 05ec2e9d90c..9e4dc30c243 100644
--- a/fs/ncpfs/ncplib_kernel.h
+++ b/fs/ncpfs/ncplib_kernel.h
@@ -87,9 +87,6 @@ int ncp_open_create_file_or_subdir(struct ncp_server *, struct inode *, char *,
int ncp_initialize_search(struct ncp_server *, struct inode *,
struct nw_search_sequence *target);
-int ncp_search_for_file_or_subdir(struct ncp_server *server,
- struct nw_search_sequence *seq,
- struct nw_info_struct *target);
int ncp_search_for_fileset(struct ncp_server *server,
struct nw_search_sequence *seq,
int* more, int* cnt,
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index b4baa031edf..8b3bb715d17 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -8,6 +8,7 @@ nfs-y := dir.o file.o inode.o nfs2xdr.o pagelist.o \
proc.o read.o symlink.o unlink.o write.o
nfs-$(CONFIG_ROOT_NFS) += nfsroot.o mount_clnt.o
nfs-$(CONFIG_NFS_V3) += nfs3proc.o nfs3xdr.o
+nfs-$(CONFIG_NFS_V3_ACL) += nfs3acl.o
nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
delegation.o idmap.o \
callback.o callback_xdr.o callback_proc.o
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 560d6175dd5..f2ca782aba3 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -14,6 +14,7 @@
#include <linux/sunrpc/svc.h>
#include <linux/sunrpc/svcsock.h>
#include <linux/nfs_fs.h>
+#include "nfs4_fs.h"
#include "callback.h"
#define NFSDBG_FACILITY NFSDBG_CALLBACK
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index ece27e42b93..65f1e19e4d1 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -8,6 +8,7 @@
#include <linux/config.h>
#include <linux/nfs4.h>
#include <linux/nfs_fs.h>
+#include "nfs4_fs.h"
#include "callback.h"
#include "delegation.h"
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index d271df9df2b..7c33b9a81a9 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -10,6 +10,7 @@
#include <linux/sunrpc/svc.h>
#include <linux/nfs4.h>
#include <linux/nfs_fs.h>
+#include "nfs4_fs.h"
#include "callback.h"
#define CB_OP_TAGLEN_MAXSZ (512)
@@ -410,7 +411,6 @@ static int nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *resp
xdr_init_decode(&xdr_in, &rqstp->rq_arg, rqstp->rq_arg.head[0].iov_base);
p = (uint32_t*)((char *)rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len);
- rqstp->rq_res.head[0].iov_len = PAGE_SIZE;
xdr_init_encode(&xdr_out, &rqstp->rq_res, p);
decode_compound_hdr_arg(&xdr_in, &hdr_arg);
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 5b9c60f9779..d7f7eb669d0 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -16,6 +16,7 @@
#include <linux/nfs_fs.h>
#include <linux/nfs_xdr.h>
+#include "nfs4_fs.h"
#include "delegation.h"
static struct nfs_delegation *nfs_alloc_delegation(void)
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 73f96acd5d3..b38a57e78a6 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -32,6 +32,7 @@
#include <linux/smp_lock.h>
#include <linux/namei.h>
+#include "nfs4_fs.h"
#include "delegation.h"
#define NFS_PARANOIA 1
@@ -50,8 +51,10 @@ static int nfs_mknod(struct inode *, struct dentry *, int, dev_t);
static int nfs_rename(struct inode *, struct dentry *,
struct inode *, struct dentry *);
static int nfs_fsync_dir(struct file *, struct dentry *, int);
+static loff_t nfs_llseek_dir(struct file *, loff_t, int);
struct file_operations nfs_dir_operations = {
+ .llseek = nfs_llseek_dir,
.read = generic_read_dir,
.readdir = nfs_readdir,
.open = nfs_opendir,
@@ -74,6 +77,27 @@ struct inode_operations nfs_dir_inode_operations = {
.setattr = nfs_setattr,
};
+#ifdef CONFIG_NFS_V3
+struct inode_operations nfs3_dir_inode_operations = {
+ .create = nfs_create,
+ .lookup = nfs_lookup,
+ .link = nfs_link,
+ .unlink = nfs_unlink,
+ .symlink = nfs_symlink,
+ .mkdir = nfs_mkdir,
+ .rmdir = nfs_rmdir,
+ .mknod = nfs_mknod,
+ .rename = nfs_rename,
+ .permission = nfs_permission,
+ .getattr = nfs_getattr,
+ .setattr = nfs_setattr,
+ .listxattr = nfs3_listxattr,
+ .getxattr = nfs3_getxattr,
+ .setxattr = nfs3_setxattr,
+ .removexattr = nfs3_removexattr,
+};
+#endif /* CONFIG_NFS_V3 */
+
#ifdef CONFIG_NFS_V4
static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *);
@@ -90,6 +114,9 @@ struct inode_operations nfs4_dir_inode_operations = {
.permission = nfs_permission,
.getattr = nfs_getattr,
.setattr = nfs_setattr,
+ .getxattr = nfs4_getxattr,
+ .setxattr = nfs4_setxattr,
+ .listxattr = nfs4_listxattr,
};
#endif /* CONFIG_NFS_V4 */
@@ -116,7 +143,8 @@ typedef struct {
struct page *page;
unsigned long page_index;
u32 *ptr;
- u64 target;
+ u64 *dir_cookie;
+ loff_t current_index;
struct nfs_entry *entry;
decode_dirent_t decode;
int plus;
@@ -164,12 +192,10 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
NFS_FLAGS(inode) |= NFS_INO_INVALID_ATIME;
/* Ensure consistent page alignment of the data.
* Note: assumes we have exclusive access to this mapping either
- * throught inode->i_sem or some other mechanism.
+ * through inode->i_sem or some other mechanism.
*/
- if (page->index == 0) {
- invalidate_inode_pages(inode->i_mapping);
- NFS_I(inode)->readdir_timestamp = timestamp;
- }
+ if (page->index == 0)
+ invalidate_inode_pages2_range(inode->i_mapping, PAGE_CACHE_SIZE, -1);
unlock_page(page);
return 0;
error:
@@ -202,22 +228,22 @@ void dir_page_release(nfs_readdir_descriptor_t *desc)
/*
* Given a pointer to a buffer that has already been filled by a call
- * to readdir, find the next entry.
+ * to readdir, find the next entry with cookie '*desc->dir_cookie'.
*
* If the end of the buffer has been reached, return -EAGAIN, if not,
* return the offset within the buffer of the next entry to be
* read.
*/
static inline
-int find_dirent(nfs_readdir_descriptor_t *desc, struct page *page)
+int find_dirent(nfs_readdir_descriptor_t *desc)
{
struct nfs_entry *entry = desc->entry;
int loop_count = 0,
status;
while((status = dir_decode(desc)) == 0) {
- dfprintk(VFS, "NFS: found cookie %Lu\n", (long long)entry->cookie);
- if (entry->prev_cookie == desc->target)
+ dfprintk(VFS, "NFS: found cookie %Lu\n", (unsigned long long)entry->cookie);
+ if (entry->prev_cookie == *desc->dir_cookie)
break;
if (loop_count++ > 200) {
loop_count = 0;
@@ -229,8 +255,44 @@ int find_dirent(nfs_readdir_descriptor_t *desc, struct page *page)
}
/*
- * Find the given page, and call find_dirent() in order to try to
- * return the next entry.
+ * Given a pointer to a buffer that has already been filled by a call
+ * to readdir, find the entry at offset 'desc->file->f_pos'.
+ *
+ * If the end of the buffer has been reached, return -EAGAIN, if not,
+ * return the offset within the buffer of the next entry to be
+ * read.
+ */
+static inline
+int find_dirent_index(nfs_readdir_descriptor_t *desc)
+{
+ struct nfs_entry *entry = desc->entry;
+ int loop_count = 0,
+ status;
+
+ for(;;) {
+ status = dir_decode(desc);
+ if (status)
+ break;
+
+ dfprintk(VFS, "NFS: found cookie %Lu at index %Ld\n", (unsigned long long)entry->cookie, desc->current_index);
+
+ if (desc->file->f_pos == desc->current_index) {
+ *desc->dir_cookie = entry->cookie;
+ break;
+ }
+ desc->current_index++;
+ if (loop_count++ > 200) {
+ loop_count = 0;
+ schedule();
+ }
+ }
+ dfprintk(VFS, "NFS: find_dirent_index() returns %d\n", status);
+ return status;
+}
+
+/*
+ * Find the given page, and call find_dirent() or find_dirent_index in
+ * order to try to return the next entry.
*/
static inline
int find_dirent_page(nfs_readdir_descriptor_t *desc)
@@ -253,7 +315,10 @@ int find_dirent_page(nfs_readdir_descriptor_t *desc)
/* NOTE: Someone else may have changed the READDIRPLUS flag */
desc->page = page;
desc->ptr = kmap(page); /* matching kunmap in nfs_do_filldir */
- status = find_dirent(desc, page);
+ if (*desc->dir_cookie != 0)
+ status = find_dirent(desc);
+ else
+ status = find_dirent_index(desc);
if (status < 0)
dir_page_release(desc);
out:
@@ -268,7 +333,8 @@ int find_dirent_page(nfs_readdir_descriptor_t *desc)
* Recurse through the page cache pages, and return a
* filled nfs_entry structure of the next directory entry if possible.
*
- * The target for the search is 'desc->target'.
+ * The target for the search is '*desc->dir_cookie' if non-0,
+ * 'desc->file->f_pos' otherwise
*/
static inline
int readdir_search_pagecache(nfs_readdir_descriptor_t *desc)
@@ -276,7 +342,16 @@ int readdir_search_pagecache(nfs_readdir_descriptor_t *desc)
int loop_count = 0;
int res;
- dfprintk(VFS, "NFS: readdir_search_pagecache() searching for cookie %Lu\n", (long long)desc->target);
+ /* Always search-by-index from the beginning of the cache */
+ if (*desc->dir_cookie == 0) {
+ dfprintk(VFS, "NFS: readdir_search_pagecache() searching for offset %Ld\n", (long long)desc->file->f_pos);
+ desc->page_index = 0;
+ desc->entry->cookie = desc->entry->prev_cookie = 0;
+ desc->entry->eof = 0;
+ desc->current_index = 0;
+ } else
+ dfprintk(VFS, "NFS: readdir_search_pagecache() searching for cookie %Lu\n", (unsigned long long)*desc->dir_cookie);
+
for (;;) {
res = find_dirent_page(desc);
if (res != -EAGAIN)
@@ -313,7 +388,7 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
int loop_count = 0,
res;
- dfprintk(VFS, "NFS: nfs_do_filldir() filling starting @ cookie %Lu\n", (long long)desc->target);
+ dfprintk(VFS, "NFS: nfs_do_filldir() filling starting @ cookie %Lu\n", (long long)entry->cookie);
for(;;) {
unsigned d_type = DT_UNKNOWN;
@@ -333,10 +408,11 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
}
res = filldir(dirent, entry->name, entry->len,
- entry->prev_cookie, fileid, d_type);
+ file->f_pos, fileid, d_type);
if (res < 0)
break;
- file->f_pos = desc->target = entry->cookie;
+ file->f_pos++;
+ *desc->dir_cookie = entry->cookie;
if (dir_decode(desc) != 0) {
desc->page_index ++;
break;
@@ -349,7 +425,7 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
dir_page_release(desc);
if (dentry != NULL)
dput(dentry);
- dfprintk(VFS, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n", (long long)desc->target, res);
+ dfprintk(VFS, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n", (unsigned long long)*desc->dir_cookie, res);
return res;
}
@@ -375,14 +451,14 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
struct page *page = NULL;
int status;
- dfprintk(VFS, "NFS: uncached_readdir() searching for cookie %Lu\n", (long long)desc->target);
+ dfprintk(VFS, "NFS: uncached_readdir() searching for cookie %Lu\n", (unsigned long long)*desc->dir_cookie);
page = alloc_page(GFP_HIGHUSER);
if (!page) {
status = -ENOMEM;
goto out;
}
- desc->error = NFS_PROTO(inode)->readdir(file->f_dentry, cred, desc->target,
+ desc->error = NFS_PROTO(inode)->readdir(file->f_dentry, cred, *desc->dir_cookie,
page,
NFS_SERVER(inode)->dtsize,
desc->plus);
@@ -391,7 +467,7 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
desc->ptr = kmap(page); /* matching kunmap in nfs_do_filldir */
if (desc->error >= 0) {
if ((status = dir_decode(desc)) == 0)
- desc->entry->prev_cookie = desc->target;
+ desc->entry->prev_cookie = *desc->dir_cookie;
} else
status = -EIO;
if (status < 0)
@@ -412,8 +488,9 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
goto out;
}
-/* The file offset position is now represented as a true offset into the
- * page cache as is the case in most of the other filesystems.
+/* The file offset position represents the dirent entry number. A
+ last cookie cache takes care of the common case of reading the
+ whole directory.
*/
static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
@@ -435,15 +512,15 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
}
/*
- * filp->f_pos points to the file offset in the page cache.
- * but if the cache has meanwhile been zapped, we need to
- * read from the last dirent to revalidate f_pos
- * itself.
+ * filp->f_pos points to the dirent entry number.
+ * *desc->dir_cookie has the cookie for the next entry. We have
+ * to either find the entry with the appropriate number or
+ * revalidate the cookie.
*/
memset(desc, 0, sizeof(*desc));
desc->file = filp;
- desc->target = filp->f_pos;
+ desc->dir_cookie = &((struct nfs_open_context *)filp->private_data)->dir_cookie;
desc->decode = NFS_PROTO(inode)->decode_dirent;
desc->plus = NFS_USE_READDIRPLUS(inode);
@@ -455,9 +532,10 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
while(!desc->entry->eof) {
res = readdir_search_pagecache(desc);
+
if (res == -EBADCOOKIE) {
/* This means either end of directory */
- if (desc->entry->cookie != desc->target) {
+ if (*desc->dir_cookie && desc->entry->cookie != *desc->dir_cookie) {
/* Or that the server has 'lost' a cookie */
res = uncached_readdir(desc, dirent, filldir);
if (res >= 0)
@@ -490,6 +568,28 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
return 0;
}
+loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin)
+{
+ down(&filp->f_dentry->d_inode->i_sem);
+ switch (origin) {
+ case 1:
+ offset += filp->f_pos;
+ case 0:
+ if (offset >= 0)
+ break;
+ default:
+ offset = -EINVAL;
+ goto out;
+ }
+ if (offset != filp->f_pos) {
+ filp->f_pos = offset;
+ ((struct nfs_open_context *)filp->private_data)->dir_cookie = 0;
+ }
+out:
+ up(&filp->f_dentry->d_inode->i_sem);
+ return offset;
+}
+
/*
* All directory operations under NFS are synchronous, so fsync()
* is a dummy operation.
@@ -528,19 +628,39 @@ static inline void nfs_renew_times(struct dentry * dentry)
dentry->d_time = jiffies;
}
+/*
+ * Return the intent data that applies to this particular path component
+ *
+ * Note that the current set of intents only apply to the very last
+ * component of the path.
+ * We check for this using LOOKUP_CONTINUE and LOOKUP_PARENT.
+ */
+static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd, unsigned int mask)
+{
+ if (nd->flags & (LOOKUP_CONTINUE|LOOKUP_PARENT))
+ return 0;
+ return nd->flags & mask;
+}
+
+/*
+ * Inode and filehandle revalidation for lookups.
+ *
+ * We force revalidation in the cases where the VFS sets LOOKUP_REVAL,
+ * or if the intent information indicates that we're about to open this
+ * particular file and the "nocto" mount flag is not set.
+ *
+ */
static inline
int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd)
{
struct nfs_server *server = NFS_SERVER(inode);
if (nd != NULL) {
- int ndflags = nd->flags;
/* VFS wants an on-the-wire revalidation */
- if (ndflags & LOOKUP_REVAL)
+ if (nd->flags & LOOKUP_REVAL)
goto out_force;
/* This is an open(2) */
- if ((ndflags & LOOKUP_OPEN) &&
- !(ndflags & LOOKUP_CONTINUE) &&
+ if (nfs_lookup_check_intent(nd, LOOKUP_OPEN) != 0 &&
!(server->flags & NFS_MOUNT_NOCTO))
goto out_force;
}
@@ -560,12 +680,8 @@ static inline
int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
struct nameidata *nd)
{
- int ndflags = 0;
-
- if (nd)
- ndflags = nd->flags;
/* Don't revalidate a negative dentry if we're creating a new file */
- if ((ndflags & LOOKUP_CREATE) && !(ndflags & LOOKUP_CONTINUE))
+ if (nd != NULL && nfs_lookup_check_intent(nd, LOOKUP_CREATE) != 0)
return 0;
return !nfs_check_verifier(dir, dentry);
}
@@ -700,12 +816,16 @@ struct dentry_operations nfs_dentry_operations = {
.d_iput = nfs_dentry_iput,
};
+/*
+ * Use intent information to check whether or not we're going to do
+ * an O_EXCL create using this path component.
+ */
static inline
int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd)
{
if (NFS_PROTO(dir)->version == 2)
return 0;
- if (!nd || (nd->flags & LOOKUP_CONTINUE) || !(nd->flags & LOOKUP_CREATE))
+ if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_CREATE) == 0)
return 0;
return (nd->intent.open.flags & O_EXCL) != 0;
}
@@ -772,12 +892,13 @@ struct dentry_operations nfs4_dentry_operations = {
.d_iput = nfs_dentry_iput,
};
+/*
+ * Use intent information to determine whether we need to substitute
+ * the NFSv4-style stateful OPEN for the LOOKUP call
+ */
static int is_atomic_open(struct inode *dir, struct nameidata *nd)
{
- if (!nd)
- return 0;
- /* Check that we are indeed trying to open this file */
- if ((nd->flags & LOOKUP_CONTINUE) || !(nd->flags & LOOKUP_OPEN))
+ if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_OPEN) == 0)
return 0;
/* NFS does not (yet) have a stateful open for directories */
if (nd->flags & LOOKUP_DIRECTORY)
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 68df803f27c..6537f2c4ae4 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -517,7 +517,7 @@ retry:
result = tot_bytes;
out:
- nfs_end_data_update_defer(inode);
+ nfs_end_data_update(inode);
nfs_writedata_free(wdata);
return result;
@@ -751,11 +751,6 @@ nfs_file_direct_write(struct kiocb *iocb, const char __user *buf, size_t count,
retval = -EFAULT;
if (!access_ok(VERIFY_READ, iov.iov_base, iov.iov_len))
goto out;
- if (file->f_error) {
- retval = file->f_error;
- file->f_error = 0;
- goto out;
- }
retval = -EFBIG;
if (limit != RLIM_INFINITY) {
if (pos >= limit) {
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index f06eee6dcff..5621ba9885f 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -37,6 +37,7 @@
static int nfs_file_open(struct inode *, struct file *);
static int nfs_file_release(struct inode *, struct file *);
+static loff_t nfs_file_llseek(struct file *file, loff_t offset, int origin);
static int nfs_file_mmap(struct file *, struct vm_area_struct *);
static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *);
static ssize_t nfs_file_read(struct kiocb *, char __user *, size_t, loff_t);
@@ -48,7 +49,7 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl);
static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl);
struct file_operations nfs_file_operations = {
- .llseek = remote_llseek,
+ .llseek = nfs_file_llseek,
.read = do_sync_read,
.write = do_sync_write,
.aio_read = nfs_file_read,
@@ -70,6 +71,18 @@ struct inode_operations nfs_file_inode_operations = {
.setattr = nfs_setattr,
};
+#ifdef CONFIG_NFS_V3
+struct inode_operations nfs3_file_inode_operations = {
+ .permission = nfs_permission,
+ .getattr = nfs_getattr,
+ .setattr = nfs_setattr,
+ .listxattr = nfs3_listxattr,
+ .getxattr = nfs3_getxattr,
+ .setxattr = nfs3_setxattr,
+ .removexattr = nfs3_removexattr,
+};
+#endif /* CONFIG_NFS_v3 */
+
/* Hack for future NFS swap support */
#ifndef IS_SWAPFILE
# define IS_SWAPFILE(inode) (0)
@@ -114,6 +127,61 @@ nfs_file_release(struct inode *inode, struct file *filp)
return NFS_PROTO(inode)->file_release(inode, filp);
}
+/**
+ * nfs_revalidate_file - Revalidate the page cache & related metadata
+ * @inode - pointer to inode struct
+ * @file - pointer to file
+ */
+static int nfs_revalidate_file(struct inode *inode, struct file *filp)
+{
+ int retval = 0;
+
+ if ((NFS_FLAGS(inode) & NFS_INO_REVAL_PAGECACHE) || nfs_attribute_timeout(inode))
+ retval = __nfs_revalidate_inode(NFS_SERVER(inode), inode);
+ nfs_revalidate_mapping(inode, filp->f_mapping);
+ return 0;
+}
+
+/**
+ * nfs_revalidate_size - Revalidate the file size
+ * @inode - pointer to inode struct
+ * @file - pointer to struct file
+ *
+ * Revalidates the file length. This is basically a wrapper around
+ * nfs_revalidate_inode() that takes into account the fact that we may
+ * have cached writes (in which case we don't care about the server's
+ * idea of what the file length is), or O_DIRECT (in which case we
+ * shouldn't trust the cache).
+ */
+static int nfs_revalidate_file_size(struct inode *inode, struct file *filp)
+{
+ struct nfs_server *server = NFS_SERVER(inode);
+ struct nfs_inode *nfsi = NFS_I(inode);
+
+ if (server->flags & NFS_MOUNT_NOAC)
+ goto force_reval;
+ if (filp->f_flags & O_DIRECT)
+ goto force_reval;
+ if (nfsi->npages != 0)
+ return 0;
+ if (!(NFS_FLAGS(inode) & NFS_INO_REVAL_PAGECACHE) && !nfs_attribute_timeout(inode))
+ return 0;
+force_reval:
+ return __nfs_revalidate_inode(server, inode);
+}
+
+static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin)
+{
+ /* origin == SEEK_END => we must revalidate the cached file length */
+ if (origin == 2) {
+ struct inode *inode = filp->f_mapping->host;
+ int retval = nfs_revalidate_file_size(inode, filp);
+ if (retval < 0)
+ return (loff_t)retval;
+ }
+ return remote_llseek(filp, offset, origin);
+}
+
/*
* Flush all dirty pages, and check for write errors.
*
@@ -158,7 +226,7 @@ nfs_file_read(struct kiocb *iocb, char __user * buf, size_t count, loff_t pos)
dentry->d_parent->d_name.name, dentry->d_name.name,
(unsigned long) count, (unsigned long) pos);
- result = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+ result = nfs_revalidate_file(inode, iocb->ki_filp);
if (!result)
result = generic_file_aio_read(iocb, buf, count, pos);
return result;
@@ -176,7 +244,7 @@ nfs_file_sendfile(struct file *filp, loff_t *ppos, size_t count,
dentry->d_parent->d_name.name, dentry->d_name.name,
(unsigned long) count, (unsigned long long) *ppos);
- res = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+ res = nfs_revalidate_file(inode, filp);
if (!res)
res = generic_file_sendfile(filp, ppos, count, actor, target);
return res;
@@ -192,7 +260,7 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma)
dfprintk(VFS, "nfs: mmap(%s/%s)\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
- status = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+ status = nfs_revalidate_file(inode, file);
if (!status)
status = generic_file_mmap(file, vma);
return status;
@@ -281,9 +349,15 @@ nfs_file_write(struct kiocb *iocb, const char __user *buf, size_t count, loff_t
result = -EBUSY;
if (IS_SWAPFILE(inode))
goto out_swapfile;
- result = nfs_revalidate_inode(NFS_SERVER(inode), inode);
- if (result)
- goto out;
+ /*
+ * O_APPEND implies that we must revalidate the file length.
+ */
+ if (iocb->ki_filp->f_flags & O_APPEND) {
+ result = nfs_revalidate_file_size(inode, iocb->ki_filp);
+ if (result)
+ goto out;
+ }
+ nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping);
result = count;
if (!count)
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c
index 87f4f9aeac8..ffb8df91dc3 100644
--- a/fs/nfs/idmap.c
+++ b/fs/nfs/idmap.c
@@ -50,6 +50,7 @@
#include <linux/nfs_fs.h>
#include <linux/nfs_idmap.h>
+#include "nfs4_fs.h"
#define IDMAP_HASH_SZ 128
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index f2317f3e29f..4845911f1c6 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -39,6 +39,7 @@
#include <asm/system.h>
#include <asm/uaccess.h>
+#include "nfs4_fs.h"
#include "delegation.h"
#define NFSDBG_FACILITY NFSDBG_VFS
@@ -63,6 +64,7 @@ static void nfs_clear_inode(struct inode *);
static void nfs_umount_begin(struct super_block *);
static int nfs_statfs(struct super_block *, struct kstatfs *);
static int nfs_show_options(struct seq_file *, struct vfsmount *);
+static void nfs_zap_acl_cache(struct inode *);
static struct rpc_program nfs_program;
@@ -106,6 +108,21 @@ static struct rpc_program nfs_program = {
.pipe_dir_name = "/nfs",
};
+#ifdef CONFIG_NFS_V3_ACL
+static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program };
+static struct rpc_version * nfsacl_version[] = {
+ [3] = &nfsacl_version3,
+};
+
+struct rpc_program nfsacl_program = {
+ .name = "nfsacl",
+ .number = NFS_ACL_PROGRAM,
+ .nrvers = sizeof(nfsacl_version) / sizeof(nfsacl_version[0]),
+ .version = nfsacl_version,
+ .stats = &nfsacl_rpcstat,
+};
+#endif /* CONFIG_NFS_V3_ACL */
+
static inline unsigned long
nfs_fattr_to_ino_t(struct nfs_fattr *fattr)
{
@@ -118,7 +135,7 @@ nfs_write_inode(struct inode *inode, int sync)
int flags = sync ? FLUSH_WAIT : 0;
int ret;
- ret = nfs_commit_inode(inode, 0, 0, flags);
+ ret = nfs_commit_inode(inode, flags);
if (ret < 0)
return ret;
return 0;
@@ -140,10 +157,6 @@ nfs_delete_inode(struct inode * inode)
clear_inode(inode);
}
-/*
- * For the moment, the only task for the NFS clear_inode method is to
- * release the mmap credential
- */
static void
nfs_clear_inode(struct inode *inode)
{
@@ -152,6 +165,7 @@ nfs_clear_inode(struct inode *inode)
nfs_wb_all(inode);
BUG_ON (!list_empty(&nfsi->open_files));
+ nfs_zap_acl_cache(inode);
cred = nfsi->cache_access.cred;
if (cred)
put_rpccred(cred);
@@ -161,11 +175,13 @@ nfs_clear_inode(struct inode *inode)
void
nfs_umount_begin(struct super_block *sb)
{
- struct nfs_server *server = NFS_SB(sb);
- struct rpc_clnt *rpc;
+ struct rpc_clnt *rpc = NFS_SB(sb)->client;
/* -EIO all pending I/O */
- if ((rpc = server->client) != NULL)
+ if (!IS_ERR(rpc))
+ rpc_killall_tasks(rpc);
+ rpc = NFS_SB(sb)->client_acl;
+ if (!IS_ERR(rpc))
rpc_killall_tasks(rpc);
}
@@ -366,13 +382,15 @@ nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data)
xprt = xprt_create_proto(tcp ? IPPROTO_TCP : IPPROTO_UDP,
&server->addr, &timeparms);
if (IS_ERR(xprt)) {
- printk(KERN_WARNING "NFS: cannot create RPC transport.\n");
+ dprintk("%s: cannot create RPC transport. Error = %ld\n",
+ __FUNCTION__, PTR_ERR(xprt));
return (struct rpc_clnt *)xprt;
}
clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
server->rpc_ops->version, data->pseudoflavor);
if (IS_ERR(clnt)) {
- printk(KERN_WARNING "NFS: cannot create RPC client.\n");
+ dprintk("%s: cannot create RPC client. Error = %ld\n",
+ __FUNCTION__, PTR_ERR(xprt));
goto out_fail;
}
@@ -383,7 +401,6 @@ nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data)
return clnt;
out_fail:
- xprt_destroy(xprt);
return clnt;
}
@@ -427,21 +444,16 @@ nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent)
/* Check NFS protocol revision and initialize RPC op vector
* and file handle pool. */
- if (server->flags & NFS_MOUNT_VER3) {
#ifdef CONFIG_NFS_V3
+ if (server->flags & NFS_MOUNT_VER3) {
server->rpc_ops = &nfs_v3_clientops;
server->caps |= NFS_CAP_READDIRPLUS;
- if (data->version < 4) {
- printk(KERN_NOTICE "NFS: NFSv3 not supported by mount program.\n");
- return -EIO;
- }
-#else
- printk(KERN_NOTICE "NFS: NFSv3 not supported.\n");
- return -EIO;
-#endif
} else {
server->rpc_ops = &nfs_v2_clientops;
}
+#else
+ server->rpc_ops = &nfs_v2_clientops;
+#endif
/* Fill in pseudoflavor for mount version < 5 */
if (!(data->flags & NFS_MOUNT_SECFLAVOUR))
@@ -455,17 +467,34 @@ nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent)
return PTR_ERR(server->client);
/* RFC 2623, sec 2.3.2 */
if (authflavor != RPC_AUTH_UNIX) {
+ struct rpc_auth *auth;
+
server->client_sys = rpc_clone_client(server->client);
if (IS_ERR(server->client_sys))
return PTR_ERR(server->client_sys);
- if (!rpcauth_create(RPC_AUTH_UNIX, server->client_sys))
- return -ENOMEM;
+ auth = rpcauth_create(RPC_AUTH_UNIX, server->client_sys);
+ if (IS_ERR(auth))
+ return PTR_ERR(auth);
} else {
atomic_inc(&server->client->cl_count);
server->client_sys = server->client;
}
-
if (server->flags & NFS_MOUNT_VER3) {
+#ifdef CONFIG_NFS_V3_ACL
+ if (!(server->flags & NFS_MOUNT_NOACL)) {
+ server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3);
+ /* No errors! Assume that Sun nfsacls are supported */
+ if (!IS_ERR(server->client_acl))
+ server->caps |= NFS_CAP_ACLS;
+ }
+#else
+ server->flags &= ~NFS_MOUNT_NOACL;
+#endif /* CONFIG_NFS_V3_ACL */
+ /*
+ * The VFS shouldn't apply the umask to mode bits. We will
+ * do so ourselves when necessary.
+ */
+ sb->s_flags |= MS_POSIXACL;
if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN)
server->namelen = NFS3_MAXNAMLEN;
sb->s_time_gran = 1;
@@ -549,6 +578,7 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt)
{ NFS_MOUNT_NOCTO, ",nocto", "" },
{ NFS_MOUNT_NOAC, ",noac", "" },
{ NFS_MOUNT_NONLM, ",nolock", ",lock" },
+ { NFS_MOUNT_NOACL, ",noacl", "" },
{ 0, NULL, NULL }
};
struct proc_nfs_info *nfs_infop;
@@ -590,9 +620,19 @@ nfs_zap_caches(struct inode *inode)
memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))
- nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS;
+ nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
else
- nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS;
+ nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
+}
+
+static void nfs_zap_acl_cache(struct inode *inode)
+{
+ void (*clear_acl_cache)(struct inode *);
+
+ clear_acl_cache = NFS_PROTO(inode)->clear_acl_cache;
+ if (clear_acl_cache != NULL)
+ clear_acl_cache(inode);
+ NFS_I(inode)->flags &= ~NFS_INO_INVALID_ACL;
}
/*
@@ -689,7 +729,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
/* Why so? Because we want revalidate for devices/FIFOs, and
* that's precisely what we have in nfs_file_inode_operations.
*/
- inode->i_op = &nfs_file_inode_operations;
+ inode->i_op = NFS_SB(sb)->rpc_ops->file_inode_ops;
if (S_ISREG(inode->i_mode)) {
inode->i_fop = &nfs_file_operations;
inode->i_data.a_ops = &nfs_file_aops;
@@ -792,7 +832,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
}
}
if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0)
- NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS;
+ NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
nfs_end_data_update(inode);
unlock_kernel();
return error;
@@ -851,7 +891,7 @@ struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rp
ctx->state = NULL;
ctx->lockowner = current->files;
ctx->error = 0;
- init_waitqueue_head(&ctx->waitq);
+ ctx->dir_cookie = 0;
}
return ctx;
}
@@ -1015,6 +1055,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
goto out;
}
flags = nfsi->flags;
+ nfsi->flags &= ~NFS_INO_REVAL_PAGECACHE;
/*
* We may need to keep the attributes marked as invalid if
* we raced with nfs_end_attr_update().
@@ -1022,21 +1063,9 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
if (verifier == nfsi->cache_change_attribute)
nfsi->flags &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME);
/* Do the page cache invalidation */
- if (flags & NFS_INO_INVALID_DATA) {
- if (S_ISREG(inode->i_mode)) {
- if (filemap_fdatawrite(inode->i_mapping) == 0)
- filemap_fdatawait(inode->i_mapping);
- nfs_wb_all(inode);
- }
- nfsi->flags &= ~NFS_INO_INVALID_DATA;
- invalidate_inode_pages2(inode->i_mapping);
- memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
- dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n",
- inode->i_sb->s_id,
- (long long)NFS_FILEID(inode));
- /* This ensures we revalidate dentries */
- nfsi->cache_change_attribute++;
- }
+ nfs_revalidate_mapping(inode, inode->i_mapping);
+ if (flags & NFS_INO_INVALID_ACL)
+ nfs_zap_acl_cache(inode);
dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n",
inode->i_sb->s_id,
(long long)NFS_FILEID(inode));
@@ -1074,6 +1103,34 @@ int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
}
/**
+ * nfs_revalidate_mapping - Revalidate the pagecache
+ * @inode - pointer to host inode
+ * @mapping - pointer to mapping
+ */
+void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
+{
+ struct nfs_inode *nfsi = NFS_I(inode);
+
+ if (nfsi->flags & NFS_INO_INVALID_DATA) {
+ if (S_ISREG(inode->i_mode)) {
+ if (filemap_fdatawrite(mapping) == 0)
+ filemap_fdatawait(mapping);
+ nfs_wb_all(inode);
+ }
+ invalidate_inode_pages2(mapping);
+ nfsi->flags &= ~NFS_INO_INVALID_DATA;
+ if (S_ISDIR(inode->i_mode)) {
+ memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf));
+ /* This ensures we revalidate child dentries */
+ nfsi->cache_change_attribute++;
+ }
+ dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n",
+ inode->i_sb->s_id,
+ (long long)NFS_FILEID(inode));
+ }
+}
+
+/**
* nfs_begin_data_update
* @inode - pointer to inode
* Declare that a set of operations will update file data on the server
@@ -1106,27 +1163,6 @@ void nfs_end_data_update(struct inode *inode)
}
/**
- * nfs_end_data_update_defer
- * @inode - pointer to inode
- * Declare end of the operations that will update file data
- * This will defer marking the inode as needing revalidation
- * unless there are no other pending updates.
- */
-void nfs_end_data_update_defer(struct inode *inode)
-{
- struct nfs_inode *nfsi = NFS_I(inode);
-
- if (atomic_dec_and_test(&nfsi->data_updates)) {
- /* Mark the attribute cache for revalidation */
- nfsi->flags |= NFS_INO_INVALID_ATTR;
- /* Directories and symlinks: invalidate page cache too */
- if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
- nfsi->flags |= NFS_INO_INVALID_DATA;
- nfsi->cache_change_attribute ++;
- }
-}
-
-/**
* nfs_refresh_inode - verify consistency of the inode attribute cache
* @inode - pointer to inode
* @fattr - updated attributes
@@ -1152,8 +1188,11 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
if ((fattr->valid & NFS_ATTR_PRE_CHANGE) != 0
&& nfsi->change_attr == fattr->pre_change_attr)
nfsi->change_attr = fattr->change_attr;
- if (!data_unstable && nfsi->change_attr != fattr->change_attr)
+ if (nfsi->change_attr != fattr->change_attr) {
nfsi->flags |= NFS_INO_INVALID_ATTR;
+ if (!data_unstable)
+ nfsi->flags |= NFS_INO_REVAL_PAGECACHE;
+ }
}
if ((fattr->valid & NFS_ATTR_FATTR) == 0)
@@ -1176,18 +1215,22 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
}
/* Verify a few of the more important attributes */
- if (!data_unstable) {
- if (!timespec_equal(&inode->i_mtime, &fattr->mtime)
- || cur_size != new_isize)
- nfsi->flags |= NFS_INO_INVALID_ATTR;
- } else if (S_ISREG(inode->i_mode) && new_isize > cur_size)
- nfsi->flags |= NFS_INO_INVALID_ATTR;
+ if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) {
+ nfsi->flags |= NFS_INO_INVALID_ATTR;
+ if (!data_unstable)
+ nfsi->flags |= NFS_INO_REVAL_PAGECACHE;
+ }
+ if (cur_size != new_isize) {
+ nfsi->flags |= NFS_INO_INVALID_ATTR;
+ if (nfsi->npages == 0)
+ nfsi->flags |= NFS_INO_REVAL_PAGECACHE;
+ }
/* Have any file permissions changed? */
if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)
|| inode->i_uid != fattr->uid
|| inode->i_gid != fattr->gid)
- nfsi->flags |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS;
+ nfsi->flags |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL;
/* Has the link count changed? */
if (inode->i_nlink != fattr->nlink)
@@ -1215,10 +1258,8 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsigned long verifier)
{
struct nfs_inode *nfsi = NFS_I(inode);
- __u64 new_size;
- loff_t new_isize;
+ loff_t cur_isize, new_isize;
unsigned int invalid = 0;
- loff_t cur_isize;
int data_unstable;
dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n",
@@ -1251,61 +1292,56 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign
/* Are we racing with known updates of the metadata on the server? */
data_unstable = ! nfs_verify_change_attribute(inode, verifier);
- /* Check if the file size agrees */
- new_size = fattr->size;
+ /* Check if our cached file size is stale */
new_isize = nfs_size_to_loff_t(fattr->size);
cur_isize = i_size_read(inode);
- if (cur_isize != new_size) {
-#ifdef NFS_DEBUG_VERBOSE
- printk(KERN_DEBUG "NFS: isize change on %s/%ld\n", inode->i_sb->s_id, inode->i_ino);
-#endif
- /*
- * If we have pending writebacks, things can get
- * messy.
- */
- if (S_ISREG(inode->i_mode) && data_unstable) {
- if (new_isize > cur_isize) {
+ if (new_isize != cur_isize) {
+ /* Do we perhaps have any outstanding writes? */
+ if (nfsi->npages == 0) {
+ /* No, but did we race with nfs_end_data_update()? */
+ if (verifier == nfsi->cache_change_attribute) {
inode->i_size = new_isize;
- invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
+ invalid |= NFS_INO_INVALID_DATA;
}
- } else {
+ invalid |= NFS_INO_INVALID_ATTR;
+ } else if (new_isize > cur_isize) {
inode->i_size = new_isize;
invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
}
+ dprintk("NFS: isize change on server for file %s/%ld\n",
+ inode->i_sb->s_id, inode->i_ino);
}
- /*
- * Note: we don't check inode->i_mtime since pipes etc.
- * can change this value in VFS without requiring a
- * cache revalidation.
- */
+ /* Check if the mtime agrees */
if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) {
memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
-#ifdef NFS_DEBUG_VERBOSE
- printk(KERN_DEBUG "NFS: mtime change on %s/%ld\n", inode->i_sb->s_id, inode->i_ino);
-#endif
+ dprintk("NFS: mtime change on server for file %s/%ld\n",
+ inode->i_sb->s_id, inode->i_ino);
if (!data_unstable)
invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
}
if ((fattr->valid & NFS_ATTR_FATTR_V4)
&& nfsi->change_attr != fattr->change_attr) {
-#ifdef NFS_DEBUG_VERBOSE
- printk(KERN_DEBUG "NFS: change_attr change on %s/%ld\n",
+ dprintk("NFS: change_attr change on server for file %s/%ld\n",
inode->i_sb->s_id, inode->i_ino);
-#endif
nfsi->change_attr = fattr->change_attr;
if (!data_unstable)
- invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS;
+ invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
}
- memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
+ /* If ctime has changed we should definitely clear access+acl caches */
+ if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) {
+ if (!data_unstable)
+ invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
+ memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
+ }
memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime));
if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) ||
inode->i_uid != fattr->uid ||
inode->i_gid != fattr->gid)
- invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS;
+ invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
inode->i_mode = fattr->mode;
inode->i_nlink = fattr->nlink;
@@ -1385,74 +1421,95 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *raw_data)
{
int error;
- struct nfs_server *server;
+ struct nfs_server *server = NULL;
struct super_block *s;
struct nfs_fh *root;
struct nfs_mount_data *data = raw_data;
- if (!data) {
- printk("nfs_read_super: missing data argument\n");
- return ERR_PTR(-EINVAL);
+ s = ERR_PTR(-EINVAL);
+ if (data == NULL) {
+ dprintk("%s: missing data argument\n", __FUNCTION__);
+ goto out_err;
+ }
+ if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) {
+ dprintk("%s: bad mount version\n", __FUNCTION__);
+ goto out_err;
}
+ switch (data->version) {
+ case 1:
+ data->namlen = 0;
+ case 2:
+ data->bsize = 0;
+ case 3:
+ if (data->flags & NFS_MOUNT_VER3) {
+ dprintk("%s: mount structure version %d does not support NFSv3\n",
+ __FUNCTION__,
+ data->version);
+ goto out_err;
+ }
+ data->root.size = NFS2_FHSIZE;
+ memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
+ case 4:
+ if (data->flags & NFS_MOUNT_SECFLAVOUR) {
+ dprintk("%s: mount structure version %d does not support strong security\n",
+ __FUNCTION__,
+ data->version);
+ goto out_err;
+ }
+ case 5:
+ memset(data->context, 0, sizeof(data->context));
+ }
+#ifndef CONFIG_NFS_V3
+ /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */
+ s = ERR_PTR(-EPROTONOSUPPORT);
+ if (data->flags & NFS_MOUNT_VER3) {
+ dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__);
+ goto out_err;
+ }
+#endif /* CONFIG_NFS_V3 */
+ s = ERR_PTR(-ENOMEM);
server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL);
if (!server)
- return ERR_PTR(-ENOMEM);
+ goto out_err;
memset(server, 0, sizeof(struct nfs_server));
/* Zero out the NFS state stuff */
init_nfsv4_state(server);
-
- if (data->version != NFS_MOUNT_VERSION) {
- printk("nfs warning: mount version %s than kernel\n",
- data->version < NFS_MOUNT_VERSION ? "older" : "newer");
- if (data->version < 2)
- data->namlen = 0;
- if (data->version < 3)
- data->bsize = 0;
- if (data->version < 4) {
- data->flags &= ~NFS_MOUNT_VER3;
- data->root.size = NFS2_FHSIZE;
- memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
- }
- if (data->version < 5)
- data->flags &= ~NFS_MOUNT_SECFLAVOUR;
- }
+ server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
root = &server->fh;
if (data->flags & NFS_MOUNT_VER3)
root->size = data->root.size;
else
root->size = NFS2_FHSIZE;
+ s = ERR_PTR(-EINVAL);
if (root->size > sizeof(root->data)) {
- printk("nfs_get_sb: invalid root filehandle\n");
- kfree(server);
- return ERR_PTR(-EINVAL);
+ dprintk("%s: invalid root filehandle\n", __FUNCTION__);
+ goto out_err;
}
memcpy(root->data, data->root.data, root->size);
/* We now require that the mount process passes the remote address */
memcpy(&server->addr, &data->addr, sizeof(server->addr));
if (server->addr.sin_addr.s_addr == INADDR_ANY) {
- printk("NFS: mount program didn't pass remote address!\n");
- kfree(server);
- return ERR_PTR(-EINVAL);
+ dprintk("%s: mount program didn't pass remote address!\n",
+ __FUNCTION__);
+ goto out_err;
}
- s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
-
- if (IS_ERR(s) || s->s_root) {
- kfree(server);
- return s;
+ /* Fire up rpciod if not yet running */
+ s = ERR_PTR(rpciod_up());
+ if (IS_ERR(s)) {
+ dprintk("%s: couldn't start rpciod! Error = %ld\n",
+ __FUNCTION__, PTR_ERR(s));
+ goto out_err;
}
- s->s_flags = flags;
+ s = sget(fs_type, nfs_compare_super, nfs_set_super, server);
+ if (IS_ERR(s) || s->s_root)
+ goto out_rpciod_down;
- /* Fire up rpciod if not yet running */
- if (rpciod_up() != 0) {
- printk(KERN_WARNING "NFS: couldn't start rpciod!\n");
- kfree(server);
- return ERR_PTR(-EIO);
- }
+ s->s_flags = flags;
error = nfs_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
if (error) {
@@ -1462,6 +1519,11 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type,
}
s->s_flags |= MS_ACTIVE;
return s;
+out_rpciod_down:
+ rpciod_down();
+out_err:
+ kfree(server);
+ return s;
}
static void nfs_kill_super(struct super_block *s)
@@ -1470,10 +1532,12 @@ static void nfs_kill_super(struct super_block *s)
kill_anon_super(s);
- if (server->client != NULL && !IS_ERR(server->client))
+ if (!IS_ERR(server->client))
rpc_shutdown_client(server->client);
- if (server->client_sys != NULL && !IS_ERR(server->client_sys))
+ if (!IS_ERR(server->client_sys))
rpc_shutdown_client(server->client_sys);
+ if (!IS_ERR(server->client_acl))
+ rpc_shutdown_client(server->client_acl);
if (!(server->flags & NFS_MOUNT_NONLM))
lockd_down(); /* release rpc.lockd */
@@ -1594,15 +1658,19 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
clp = nfs4_get_client(&server->addr.sin_addr);
if (!clp) {
- printk(KERN_WARNING "NFS: failed to create NFS4 client.\n");
+ dprintk("%s: failed to create NFS4 client.\n", __FUNCTION__);
return -EIO;
}
/* Now create transport and client */
authflavour = RPC_AUTH_UNIX;
if (data->auth_flavourlen != 0) {
- if (data->auth_flavourlen > 1)
- printk(KERN_INFO "NFS: cannot yet deal with multiple auth flavours.\n");
+ if (data->auth_flavourlen != 1) {
+ dprintk("%s: Invalid number of RPC auth flavours %d.\n",
+ __FUNCTION__, data->auth_flavourlen);
+ err = -EINVAL;
+ goto out_fail;
+ }
if (copy_from_user(&authflavour, data->auth_flavours, sizeof(authflavour))) {
err = -EFAULT;
goto out_fail;
@@ -1610,21 +1678,22 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
}
down_write(&clp->cl_sem);
- if (clp->cl_rpcclient == NULL) {
+ if (IS_ERR(clp->cl_rpcclient)) {
xprt = xprt_create_proto(proto, &server->addr, &timeparms);
if (IS_ERR(xprt)) {
up_write(&clp->cl_sem);
- printk(KERN_WARNING "NFS: cannot create RPC transport.\n");
err = PTR_ERR(xprt);
+ dprintk("%s: cannot create RPC transport. Error = %d\n",
+ __FUNCTION__, err);
goto out_fail;
}
clnt = rpc_create_client(xprt, server->hostname, &nfs_program,
server->rpc_ops->version, authflavour);
if (IS_ERR(clnt)) {
up_write(&clp->cl_sem);
- printk(KERN_WARNING "NFS: cannot create RPC client.\n");
- xprt_destroy(xprt);
err = PTR_ERR(clnt);
+ dprintk("%s: cannot create RPC client. Error = %d\n",
+ __FUNCTION__, err);
goto out_fail;
}
clnt->cl_intr = 1;
@@ -1656,21 +1725,26 @@ static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data,
clp = NULL;
if (IS_ERR(clnt)) {
- printk(KERN_WARNING "NFS: cannot create RPC client.\n");
- return PTR_ERR(clnt);
+ err = PTR_ERR(clnt);
+ dprintk("%s: cannot create RPC client. Error = %d\n",
+ __FUNCTION__, err);
+ return err;
}
server->client = clnt;
if (server->nfs4_state->cl_idmap == NULL) {
- printk(KERN_WARNING "NFS: failed to create idmapper.\n");
+ dprintk("%s: failed to create idmapper.\n", __FUNCTION__);
return -ENOMEM;
}
if (clnt->cl_auth->au_flavor != authflavour) {
- if (rpcauth_create(authflavour, clnt) == NULL) {
- printk(KERN_WARNING "NFS: couldn't create credcache!\n");
- return -ENOMEM;
+ struct rpc_auth *auth;
+
+ auth = rpcauth_create(authflavour, clnt);
+ if (IS_ERR(auth)) {
+ dprintk("%s: couldn't create credcache!\n", __FUNCTION__);
+ return PTR_ERR(auth);
}
}
@@ -1730,8 +1804,12 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
struct nfs4_mount_data *data = raw_data;
void *p;
- if (!data) {
- printk("nfs_read_super: missing data argument\n");
+ if (data == NULL) {
+ dprintk("%s: missing data argument\n", __FUNCTION__);
+ return ERR_PTR(-EINVAL);
+ }
+ if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) {
+ dprintk("%s: bad mount version\n", __FUNCTION__);
return ERR_PTR(-EINVAL);
}
@@ -1741,11 +1819,7 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
memset(server, 0, sizeof(struct nfs_server));
/* Zero out the NFS state stuff */
init_nfsv4_state(server);
-
- if (data->version != NFS4_MOUNT_VERSION) {
- printk("nfs warning: mount version %s than kernel\n",
- data->version < NFS4_MOUNT_VERSION ? "older" : "newer");
- }
+ server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
p = nfs_copy_user_string(NULL, &data->hostname, 256);
if (IS_ERR(p))
@@ -1773,11 +1847,20 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
}
if (server->addr.sin_family != AF_INET ||
server->addr.sin_addr.s_addr == INADDR_ANY) {
- printk("NFS: mount program didn't pass remote IP address!\n");
+ dprintk("%s: mount program didn't pass remote IP address!\n",
+ __FUNCTION__);
s = ERR_PTR(-EINVAL);
goto out_free;
}
+ /* Fire up rpciod if not yet running */
+ s = ERR_PTR(rpciod_up());
+ if (IS_ERR(s)) {
+ dprintk("%s: couldn't start rpciod! Error = %ld\n",
+ __FUNCTION__, PTR_ERR(s));
+ goto out_free;
+ }
+
s = sget(fs_type, nfs4_compare_super, nfs_set_super, server);
if (IS_ERR(s) || s->s_root)
@@ -1785,13 +1868,6 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type,
s->s_flags = flags;
- /* Fire up rpciod if not yet running */
- if (rpciod_up() != 0) {
- printk(KERN_WARNING "NFS: couldn't start rpciod!\n");
- s = ERR_PTR(-EIO);
- goto out_free;
- }
-
error = nfs4_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
if (error) {
up_write(&s->s_umount);
@@ -1875,6 +1951,13 @@ static struct inode *nfs_alloc_inode(struct super_block *sb)
if (!nfsi)
return NULL;
nfsi->flags = 0;
+#ifdef CONFIG_NFS_V3_ACL
+ nfsi->acl_access = ERR_PTR(-EAGAIN);
+ nfsi->acl_default = ERR_PTR(-EAGAIN);
+#endif
+#ifdef CONFIG_NFS_V4
+ nfsi->nfs4_acl = NULL;
+#endif /* CONFIG_NFS_V4 */
return &nfsi->vfs_inode;
}
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index 9d3ddad96d9..0e82617f2de 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -80,9 +80,7 @@ mnt_create(char *hostname, struct sockaddr_in *srvaddr, int version,
clnt = rpc_create_client(xprt, hostname,
&mnt_program, version,
RPC_AUTH_UNIX);
- if (IS_ERR(clnt)) {
- xprt_destroy(xprt);
- } else {
+ if (!IS_ERR(clnt)) {
clnt->cl_softrtry = 1;
clnt->cl_chatty = 1;
clnt->cl_oneshot = 1;
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c
new file mode 100644
index 00000000000..ee3536fc84a
--- /dev/null
+++ b/fs/nfs/nfs3acl.c
@@ -0,0 +1,403 @@
+#include <linux/fs.h>
+#include <linux/nfs.h>
+#include <linux/nfs3.h>
+#include <linux/nfs_fs.h>
+#include <linux/xattr_acl.h>
+#include <linux/nfsacl.h>
+
+#define NFSDBG_FACILITY NFSDBG_PROC
+
+ssize_t nfs3_listxattr(struct dentry *dentry, char *buffer, size_t size)
+{
+ struct inode *inode = dentry->d_inode;
+ struct posix_acl *acl;
+ int pos=0, len=0;
+
+# define output(s) do { \
+ if (pos + sizeof(s) <= size) { \
+ memcpy(buffer + pos, s, sizeof(s)); \
+ pos += sizeof(s); \
+ } \
+ len += sizeof(s); \
+ } while(0)
+
+ acl = nfs3_proc_getacl(inode, ACL_TYPE_ACCESS);
+ if (IS_ERR(acl))
+ return PTR_ERR(acl);
+ if (acl) {
+ output("system.posix_acl_access");
+ posix_acl_release(acl);
+ }
+
+ if (S_ISDIR(inode->i_mode)) {
+ acl = nfs3_proc_getacl(inode, ACL_TYPE_DEFAULT);
+ if (IS_ERR(acl))
+ return PTR_ERR(acl);
+ if (acl) {
+ output("system.posix_acl_default");
+ posix_acl_release(acl);
+ }
+ }
+
+# undef output
+
+ if (!buffer || len <= size)
+ return len;
+ return -ERANGE;
+}
+
+ssize_t nfs3_getxattr(struct dentry *dentry, const char *name,
+ void *buffer, size_t size)
+{
+ struct inode *inode = dentry->d_inode;
+ struct posix_acl *acl;
+ int type, error = 0;
+
+ if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0)
+ type = ACL_TYPE_ACCESS;
+ else if (strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0)
+ type = ACL_TYPE_DEFAULT;
+ else
+ return -EOPNOTSUPP;
+
+ acl = nfs3_proc_getacl(inode, type);
+ if (IS_ERR(acl))
+ return PTR_ERR(acl);
+ else if (acl) {
+ if (type == ACL_TYPE_ACCESS && acl->a_count == 0)
+ error = -ENODATA;
+ else
+ error = posix_acl_to_xattr(acl, buffer, size);
+ posix_acl_release(acl);
+ } else
+ error = -ENODATA;
+
+ return error;
+}
+
+int nfs3_setxattr(struct dentry *dentry, const char *name,
+ const void *value, size_t size, int flags)
+{
+ struct inode *inode = dentry->d_inode;
+ struct posix_acl *acl;
+ int type, error;
+
+ if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0)
+ type = ACL_TYPE_ACCESS;
+ else if (strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0)
+ type = ACL_TYPE_DEFAULT;
+ else
+ return -EOPNOTSUPP;
+
+ acl = posix_acl_from_xattr(value, size);
+ if (IS_ERR(acl))
+ return PTR_ERR(acl);
+ error = nfs3_proc_setacl(inode, type, acl);
+ posix_acl_release(acl);
+
+ return error;
+}
+
+int nfs3_removexattr(struct dentry *dentry, const char *name)
+{
+ struct inode *inode = dentry->d_inode;
+ int type;
+
+ if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0)
+ type = ACL_TYPE_ACCESS;
+ else if (strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0)
+ type = ACL_TYPE_DEFAULT;
+ else
+ return -EOPNOTSUPP;
+
+ return nfs3_proc_setacl(inode, type, NULL);
+}
+
+static void __nfs3_forget_cached_acls(struct nfs_inode *nfsi)
+{
+ if (!IS_ERR(nfsi->acl_access)) {
+ posix_acl_release(nfsi->acl_access);
+ nfsi->acl_access = ERR_PTR(-EAGAIN);
+ }
+ if (!IS_ERR(nfsi->acl_default)) {
+ posix_acl_release(nfsi->acl_default);
+ nfsi->acl_default = ERR_PTR(-EAGAIN);
+ }
+}
+
+void nfs3_forget_cached_acls(struct inode *inode)
+{
+ dprintk("NFS: nfs3_forget_cached_acls(%s/%ld)\n", inode->i_sb->s_id,
+ inode->i_ino);
+ spin_lock(&inode->i_lock);
+ __nfs3_forget_cached_acls(NFS_I(inode));
+ spin_unlock(&inode->i_lock);
+}
+
+static struct posix_acl *nfs3_get_cached_acl(struct inode *inode, int type)
+{
+ struct nfs_inode *nfsi = NFS_I(inode);
+ struct posix_acl *acl = ERR_PTR(-EINVAL);
+
+ spin_lock(&inode->i_lock);
+ switch(type) {
+ case ACL_TYPE_ACCESS:
+ acl = nfsi->acl_access;
+ break;
+
+ case ACL_TYPE_DEFAULT:
+ acl = nfsi->acl_default;
+ break;
+
+ default:
+ goto out;
+ }
+ if (IS_ERR(acl))
+ acl = ERR_PTR(-EAGAIN);
+ else
+ acl = posix_acl_dup(acl);
+out:
+ spin_unlock(&inode->i_lock);
+ dprintk("NFS: nfs3_get_cached_acl(%s/%ld, %d) = %p\n", inode->i_sb->s_id,
+ inode->i_ino, type, acl);
+ return acl;
+}
+
+static void nfs3_cache_acls(struct inode *inode, struct posix_acl *acl,
+ struct posix_acl *dfacl)
+{
+ struct nfs_inode *nfsi = NFS_I(inode);
+
+ dprintk("nfs3_cache_acls(%s/%ld, %p, %p)\n", inode->i_sb->s_id,
+ inode->i_ino, acl, dfacl);
+ spin_lock(&inode->i_lock);
+ __nfs3_forget_cached_acls(NFS_I(inode));
+ nfsi->acl_access = posix_acl_dup(acl);
+ nfsi->acl_default = posix_acl_dup(dfacl);
+ spin_unlock(&inode->i_lock);
+}
+
+struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
+{
+ struct nfs_server *server = NFS_SERVER(inode);
+ struct nfs_fattr fattr;
+ struct page *pages[NFSACL_MAXPAGES] = { };
+ struct nfs3_getaclargs args = {
+ .fh = NFS_FH(inode),
+ /* The xdr layer may allocate pages here. */
+ .pages = pages,
+ };
+ struct nfs3_getaclres res = {
+ .fattr = &fattr,
+ };
+ struct posix_acl *acl;
+ int status, count;
+
+ if (!nfs_server_capable(inode, NFS_CAP_ACLS))
+ return ERR_PTR(-EOPNOTSUPP);
+
+ status = nfs_revalidate_inode(server, inode);
+ if (status < 0)
+ return ERR_PTR(status);
+ acl = nfs3_get_cached_acl(inode, type);
+ if (acl != ERR_PTR(-EAGAIN))
+ return acl;
+ acl = NULL;
+
+ /*
+ * Only get the access acl when explicitly requested: We don't
+ * need it for access decisions, and only some applications use
+ * it. Applications which request the access acl first are not
+ * penalized from this optimization.
+ */
+ if (type == ACL_TYPE_ACCESS)
+ args.mask |= NFS_ACLCNT|NFS_ACL;
+ if (S_ISDIR(inode->i_mode))
+ args.mask |= NFS_DFACLCNT|NFS_DFACL;
+ if (args.mask == 0)
+ return NULL;
+
+ dprintk("NFS call getacl\n");
+ status = rpc_call(server->client_acl, ACLPROC3_GETACL,
+ &args, &res, 0);
+ dprintk("NFS reply getacl: %d\n", status);
+
+ /* pages may have been allocated at the xdr layer. */
+ for (count = 0; count < NFSACL_MAXPAGES && args.pages[count]; count++)
+ __free_page(args.pages[count]);
+
+ switch (status) {
+ case 0:
+ status = nfs_refresh_inode(inode, &fattr);
+ break;
+ case -EPFNOSUPPORT:
+ case -EPROTONOSUPPORT:
+ dprintk("NFS_V3_ACL extension not supported; disabling\n");
+ server->caps &= ~NFS_CAP_ACLS;
+ case -ENOTSUPP:
+ status = -EOPNOTSUPP;
+ default:
+ goto getout;
+ }
+ if ((args.mask & res.mask) != args.mask) {
+ status = -EIO;
+ goto getout;
+ }
+
+ if (res.acl_access != NULL) {
+ if (posix_acl_equiv_mode(res.acl_access, NULL) == 0) {
+ posix_acl_release(res.acl_access);
+ res.acl_access = NULL;
+ }
+ }
+ nfs3_cache_acls(inode, res.acl_access, res.acl_default);
+
+ switch(type) {
+ case ACL_TYPE_ACCESS:
+ acl = res.acl_access;
+ res.acl_access = NULL;
+ break;
+
+ case ACL_TYPE_DEFAULT:
+ acl = res.acl_default;
+ res.acl_default = NULL;
+ }
+
+getout:
+ posix_acl_release(res.acl_access);
+ posix_acl_release(res.acl_default);
+
+ if (status != 0) {
+ posix_acl_release(acl);
+ acl = ERR_PTR(status);
+ }
+ return acl;
+}
+
+static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
+ struct posix_acl *dfacl)
+{
+ struct nfs_server *server = NFS_SERVER(inode);
+ struct nfs_fattr fattr;
+ struct page *pages[NFSACL_MAXPAGES] = { };
+ struct nfs3_setaclargs args = {
+ .inode = inode,
+ .mask = NFS_ACL,
+ .acl_access = acl,
+ .pages = pages,
+ };
+ int status, count;
+
+ status = -EOPNOTSUPP;
+ if (!nfs_server_capable(inode, NFS_CAP_ACLS))
+ goto out;
+
+ /* We are doing this here, because XDR marshalling can only
+ return -ENOMEM. */
+ status = -ENOSPC;
+ if (acl != NULL && acl->a_count > NFS_ACL_MAX_ENTRIES)
+ goto out;
+ if (dfacl != NULL && dfacl->a_count > NFS_ACL_MAX_ENTRIES)
+ goto out;
+ if (S_ISDIR(inode->i_mode)) {
+ args.mask |= NFS_DFACL;
+ args.acl_default = dfacl;
+ }
+
+ dprintk("NFS call setacl\n");
+ nfs_begin_data_update(inode);
+ status = rpc_call(server->client_acl, ACLPROC3_SETACL,
+ &args, &fattr, 0);
+ NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS;
+ nfs_end_data_update(inode);
+ dprintk("NFS reply setacl: %d\n", status);
+
+ /* pages may have been allocated at the xdr layer. */
+ for (count = 0; count < NFSACL_MAXPAGES && args.pages[count]; count++)
+ __free_page(args.pages[count]);
+
+ switch (status) {
+ case 0:
+ status = nfs_refresh_inode(inode, &fattr);
+ break;
+ case -EPFNOSUPPORT:
+ case -EPROTONOSUPPORT:
+ dprintk("NFS_V3_ACL SETACL RPC not supported"
+ "(will not retry)\n");
+ server->caps &= ~NFS_CAP_ACLS;
+ case -ENOTSUPP:
+ status = -EOPNOTSUPP;
+ }
+out:
+ return status;
+}
+
+int nfs3_proc_setacl(struct inode *inode, int type, struct posix_acl *acl)
+{
+ struct posix_acl *alloc = NULL, *dfacl = NULL;
+ int status;
+
+ if (S_ISDIR(inode->i_mode)) {
+ switch(type) {
+ case ACL_TYPE_ACCESS:
+ alloc = dfacl = nfs3_proc_getacl(inode,
+ ACL_TYPE_DEFAULT);
+ if (IS_ERR(alloc))
+ goto fail;
+ break;
+
+ case ACL_TYPE_DEFAULT:
+ dfacl = acl;
+ alloc = acl = nfs3_proc_getacl(inode,
+ ACL_TYPE_ACCESS);
+ if (IS_ERR(alloc))
+ goto fail;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ } else if (type != ACL_TYPE_ACCESS)
+ return -EINVAL;
+
+ if (acl == NULL) {
+ alloc = acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
+ if (IS_ERR(alloc))
+ goto fail;
+ }
+ status = nfs3_proc_setacls(inode, acl, dfacl);
+ posix_acl_release(alloc);
+ return status;
+
+fail:
+ return PTR_ERR(alloc);
+}
+
+int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode,
+ mode_t mode)
+{
+ struct posix_acl *dfacl, *acl;
+ int error = 0;
+
+ dfacl = nfs3_proc_getacl(dir, ACL_TYPE_DEFAULT);
+ if (IS_ERR(dfacl)) {
+ error = PTR_ERR(dfacl);
+ return (error == -EOPNOTSUPP) ? 0 : error;
+ }
+ if (!dfacl)
+ return 0;
+ acl = posix_acl_clone(dfacl, GFP_KERNEL);
+ error = -ENOMEM;
+ if (!acl)
+ goto out_release_dfacl;
+ error = posix_acl_create_masq(acl, &mode);
+ if (error < 0)
+ goto out_release_acl;
+ error = nfs3_proc_setacls(inode, acl, S_ISDIR(inode->i_mode) ?
+ dfacl : NULL);
+out_release_acl:
+ posix_acl_release(acl);
+out_release_dfacl:
+ posix_acl_release(dfacl);
+ return error;
+}
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 3878494dfc2..7851569b31c 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -17,6 +17,7 @@
#include <linux/nfs_page.h>
#include <linux/lockd/bind.h>
#include <linux/smp_lock.h>
+#include <linux/nfs_mount.h>
#define NFSDBG_FACILITY NFSDBG_PROC
@@ -45,7 +46,7 @@ static inline int
nfs3_rpc_call_wrapper(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags)
{
struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[proc],
+ .rpc_proc = &clnt->cl_procinfo[proc],
.rpc_argp = argp,
.rpc_resp = resp,
};
@@ -313,7 +314,8 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
.fh = &fhandle,
.fattr = &fattr
};
- int status;
+ mode_t mode = sattr->ia_mode;
+ int status;
dprintk("NFS call create %s\n", dentry->d_name.name);
arg.createmode = NFS3_CREATE_UNCHECKED;
@@ -323,6 +325,8 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
arg.verifier[1] = current->pid;
}
+ sattr->ia_mode &= ~current->fs->umask;
+
again:
dir_attr.valid = 0;
fattr.valid = 0;
@@ -369,6 +373,9 @@ again:
nfs_refresh_inode(dentry->d_inode, &fattr);
dprintk("NFS reply setattr (post-create): %d\n", status);
}
+ if (status != 0)
+ goto out;
+ status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode);
out:
dprintk("NFS reply create: %d\n", status);
return status;
@@ -538,15 +545,24 @@ nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
.fh = &fhandle,
.fattr = &fattr
};
- int status;
+ int mode = sattr->ia_mode;
+ int status;
dprintk("NFS call mkdir %s\n", dentry->d_name.name);
dir_attr.valid = 0;
fattr.valid = 0;
+
+ sattr->ia_mode &= ~current->fs->umask;
+
status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKDIR, &arg, &res, 0);
nfs_refresh_inode(dir, &dir_attr);
- if (status == 0)
- status = nfs_instantiate(dentry, &fhandle, &fattr);
+ if (status != 0)
+ goto out;
+ status = nfs_instantiate(dentry, &fhandle, &fattr);
+ if (status != 0)
+ goto out;
+ status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode);
+out:
dprintk("NFS reply mkdir: %d\n", status);
return status;
}
@@ -641,6 +657,7 @@ nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
.fh = &fh,
.fattr = &fattr
};
+ mode_t mode = sattr->ia_mode;
int status;
switch (sattr->ia_mode & S_IFMT) {
@@ -653,12 +670,20 @@ nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
dprintk("NFS call mknod %s %u:%u\n", dentry->d_name.name,
MAJOR(rdev), MINOR(rdev));
+
+ sattr->ia_mode &= ~current->fs->umask;
+
dir_attr.valid = 0;
fattr.valid = 0;
status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKNOD, &arg, &res, 0);
nfs_refresh_inode(dir, &dir_attr);
- if (status == 0)
- status = nfs_instantiate(dentry, &fh, &fattr);
+ if (status != 0)
+ goto out;
+ status = nfs_instantiate(dentry, &fh, &fattr);
+ if (status != 0)
+ goto out;
+ status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode);
+out:
dprintk("NFS reply mknod: %d\n", status);
return status;
}
@@ -825,7 +850,8 @@ nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
struct nfs_rpc_ops nfs_v3_clientops = {
.version = 3, /* protocol version */
.dentry_ops = &nfs_dentry_operations,
- .dir_inode_ops = &nfs_dir_inode_operations,
+ .dir_inode_ops = &nfs3_dir_inode_operations,
+ .file_inode_ops = &nfs3_file_inode_operations,
.getroot = nfs3_proc_get_root,
.getattr = nfs3_proc_getattr,
.setattr = nfs3_proc_setattr,
@@ -856,4 +882,5 @@ struct nfs_rpc_ops nfs_v3_clientops = {
.file_open = nfs_open,
.file_release = nfs_release,
.lock = nfs3_proc_lock,
+ .clear_acl_cache = nfs3_forget_cached_acls,
};
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index a3593d47e5a..db4a904810a 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -21,6 +21,7 @@
#include <linux/nfs.h>
#include <linux/nfs3.h>
#include <linux/nfs_fs.h>
+#include <linux/nfsacl.h>
#define NFSDBG_FACILITY NFSDBG_XDR
@@ -79,6 +80,11 @@ extern int nfs_stat_to_errno(int);
#define NFS3_pathconfres_sz (1+NFS3_post_op_attr_sz+6)
#define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2)
+#define ACL3_getaclargs_sz (NFS3_fh_sz+1)
+#define ACL3_setaclargs_sz (NFS3_fh_sz+1+2*(2+5*3))
+#define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+2*(2+5*3))
+#define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz)
+
/*
* Map file type to S_IFMT bits
*/
@@ -627,6 +633,74 @@ nfs3_xdr_commitargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args)
return 0;
}
+#ifdef CONFIG_NFS_V3_ACL
+/*
+ * Encode GETACL arguments
+ */
+static int
+nfs3_xdr_getaclargs(struct rpc_rqst *req, u32 *p,
+ struct nfs3_getaclargs *args)
+{
+ struct rpc_auth *auth = req->rq_task->tk_auth;
+ unsigned int replen;
+
+ p = xdr_encode_fhandle(p, args->fh);
+ *p++ = htonl(args->mask);
+ req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
+
+ if (args->mask & (NFS_ACL | NFS_DFACL)) {
+ /* Inline the page array */
+ replen = (RPC_REPHDRSIZE + auth->au_rslack +
+ ACL3_getaclres_sz) << 2;
+ xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0,
+ NFSACL_MAXPAGES << PAGE_SHIFT);
+ }
+ return 0;
+}
+
+/*
+ * Encode SETACL arguments
+ */
+static int
+nfs3_xdr_setaclargs(struct rpc_rqst *req, u32 *p,
+ struct nfs3_setaclargs *args)
+{
+ struct xdr_buf *buf = &req->rq_snd_buf;
+ unsigned int base, len_in_head, len = nfsacl_size(
+ (args->mask & NFS_ACL) ? args->acl_access : NULL,
+ (args->mask & NFS_DFACL) ? args->acl_default : NULL);
+ int count, err;
+
+ p = xdr_encode_fhandle(p, NFS_FH(args->inode));
+ *p++ = htonl(args->mask);
+ base = (char *)p - (char *)buf->head->iov_base;
+ /* put as much of the acls into head as possible. */
+ len_in_head = min_t(unsigned int, buf->head->iov_len - base, len);
+ len -= len_in_head;
+ req->rq_slen = xdr_adjust_iovec(req->rq_svec, p + (len_in_head >> 2));
+
+ for (count = 0; (count << PAGE_SHIFT) < len; count++) {
+ args->pages[count] = alloc_page(GFP_KERNEL);
+ if (!args->pages[count]) {
+ while (count)
+ __free_page(args->pages[--count]);
+ return -ENOMEM;
+ }
+ }
+ xdr_encode_pages(buf, args->pages, 0, len);
+
+ err = nfsacl_encode(buf, base, args->inode,
+ (args->mask & NFS_ACL) ?
+ args->acl_access : NULL, 1, 0);
+ if (err > 0)
+ err = nfsacl_encode(buf, base + err, args->inode,
+ (args->mask & NFS_DFACL) ?
+ args->acl_default : NULL, 1,
+ NFS_ACL_DEFAULT);
+ return (err > 0) ? 0 : err;
+}
+#endif /* CONFIG_NFS_V3_ACL */
+
/*
* NFS XDR decode functions
*/
@@ -978,6 +1052,54 @@ nfs3_xdr_commitres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
return 0;
}
+#ifdef CONFIG_NFS_V3_ACL
+/*
+ * Decode GETACL reply
+ */
+static int
+nfs3_xdr_getaclres(struct rpc_rqst *req, u32 *p,
+ struct nfs3_getaclres *res)
+{
+ struct xdr_buf *buf = &req->rq_rcv_buf;
+ int status = ntohl(*p++);
+ struct posix_acl **acl;
+ unsigned int *aclcnt;
+ int err, base;
+
+ if (status != 0)
+ return -nfs_stat_to_errno(status);
+ p = xdr_decode_post_op_attr(p, res->fattr);
+ res->mask = ntohl(*p++);
+ if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
+ return -EINVAL;
+ base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base;
+
+ acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL;
+ aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL;
+ err = nfsacl_decode(buf, base, aclcnt, acl);
+
+ acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL;
+ aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL;
+ if (err > 0)
+ err = nfsacl_decode(buf, base + err, aclcnt, acl);
+ return (err > 0) ? 0 : err;
+}
+
+/*
+ * Decode setacl reply.
+ */
+static int
+nfs3_xdr_setaclres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
+{
+ int status = ntohl(*p++);
+
+ if (status)
+ return -nfs_stat_to_errno(status);
+ xdr_decode_post_op_attr(p, fattr);
+ return 0;
+}
+#endif /* CONFIG_NFS_V3_ACL */
+
#ifndef MAX
# define MAX(a, b) (((a) > (b))? (a) : (b))
#endif
@@ -1021,3 +1143,28 @@ struct rpc_version nfs_version3 = {
.procs = nfs3_procedures
};
+#ifdef CONFIG_NFS_V3_ACL
+static struct rpc_procinfo nfs3_acl_procedures[] = {
+ [ACLPROC3_GETACL] = {
+ .p_proc = ACLPROC3_GETACL,
+ .p_encode = (kxdrproc_t) nfs3_xdr_getaclargs,
+ .p_decode = (kxdrproc_t) nfs3_xdr_getaclres,
+ .p_bufsiz = MAX(ACL3_getaclargs_sz, ACL3_getaclres_sz) << 2,
+ .p_timer = 1,
+ },
+ [ACLPROC3_SETACL] = {
+ .p_proc = ACLPROC3_SETACL,
+ .p_encode = (kxdrproc_t) nfs3_xdr_setaclargs,
+ .p_decode = (kxdrproc_t) nfs3_xdr_setaclres,
+ .p_bufsiz = MAX(ACL3_setaclargs_sz, ACL3_setaclres_sz) << 2,
+ .p_timer = 0,
+ },
+};
+
+struct rpc_version nfsacl_version3 = {
+ .number = 3,
+ .nrprocs = sizeof(nfs3_acl_procedures)/
+ sizeof(nfs3_acl_procedures[0]),
+ .procs = nfs3_acl_procedures,
+};
+#endif /* CONFIG_NFS_V3_ACL */
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
new file mode 100644
index 00000000000..ec1a22d7b87
--- /dev/null
+++ b/fs/nfs/nfs4_fs.h
@@ -0,0 +1,253 @@
+/*
+ * linux/fs/nfs/nfs4_fs.h
+ *
+ * Copyright (C) 2005 Trond Myklebust
+ *
+ * NFSv4-specific filesystem definitions and declarations
+ */
+
+#ifndef __LINUX_FS_NFS_NFS4_FS_H
+#define __LINUX_FS_NFS_NFS4_FS_H
+
+#ifdef CONFIG_NFS_V4
+
+struct idmap;
+
+/*
+ * In a seqid-mutating op, this macro controls which error return
+ * values trigger incrementation of the seqid.
+ *
+ * from rfc 3010:
+ * The client MUST monotonically increment the sequence number for the
+ * CLOSE, LOCK, LOCKU, OPEN, OPEN_CONFIRM, and OPEN_DOWNGRADE
+ * operations. This is true even in the event that the previous
+ * operation that used the sequence number received an error. The only
+ * exception to this rule is if the previous operation received one of
+ * the following errors: NFSERR_STALE_CLIENTID, NFSERR_STALE_STATEID,
+ * NFSERR_BAD_STATEID, NFSERR_BAD_SEQID, NFSERR_BADXDR,
+ * NFSERR_RESOURCE, NFSERR_NOFILEHANDLE.
+ *
+ */
+#define seqid_mutating_err(err) \
+(((err) != NFSERR_STALE_CLIENTID) && \
+ ((err) != NFSERR_STALE_STATEID) && \
+ ((err) != NFSERR_BAD_STATEID) && \
+ ((err) != NFSERR_BAD_SEQID) && \
+ ((err) != NFSERR_BAD_XDR) && \
+ ((err) != NFSERR_RESOURCE) && \
+ ((err) != NFSERR_NOFILEHANDLE))
+
+enum nfs4_client_state {
+ NFS4CLNT_OK = 0,
+};
+
+/*
+ * The nfs4_client identifies our client state to the server.
+ */
+struct nfs4_client {
+ struct list_head cl_servers; /* Global list of servers */
+ struct in_addr cl_addr; /* Server identifier */
+ u64 cl_clientid; /* constant */
+ nfs4_verifier cl_confirm;
+ unsigned long cl_state;
+
+ u32 cl_lockowner_id;
+
+ /*
+ * The following rwsem ensures exclusive access to the server
+ * while we recover the state following a lease expiration.
+ */
+ struct rw_semaphore cl_sem;
+
+ struct list_head cl_delegations;
+ struct list_head cl_state_owners;
+ struct list_head cl_unused;
+ int cl_nunused;
+ spinlock_t cl_lock;
+ atomic_t cl_count;
+
+ struct rpc_clnt * cl_rpcclient;
+ struct rpc_cred * cl_cred;
+
+ struct list_head cl_superblocks; /* List of nfs_server structs */
+
+ unsigned long cl_lease_time;
+ unsigned long cl_last_renewal;
+ struct work_struct cl_renewd;
+ struct work_struct cl_recoverd;
+
+ wait_queue_head_t cl_waitq;
+ struct rpc_wait_queue cl_rpcwaitq;
+
+ /* used for the setclientid verifier */
+ struct timespec cl_boot_time;
+
+ /* idmapper */
+ struct idmap * cl_idmap;
+
+ /* Our own IP address, as a null-terminated string.
+ * This is used to generate the clientid, and the callback address.
+ */
+ char cl_ipaddr[16];
+ unsigned char cl_id_uniquifier;
+};
+
+/*
+ * NFS4 state_owners and lock_owners are simply labels for ordered
+ * sequences of RPC calls. Their sole purpose is to provide once-only
+ * semantics by allowing the server to identify replayed requests.
+ *
+ * The ->so_sema is held during all state_owner seqid-mutating operations:
+ * OPEN, OPEN_DOWNGRADE, and CLOSE. Its purpose is to properly serialize
+ * so_seqid.
+ */
+struct nfs4_state_owner {
+ struct list_head so_list; /* per-clientid list of state_owners */
+ struct nfs4_client *so_client;
+ u32 so_id; /* 32-bit identifier, unique */
+ struct semaphore so_sema;
+ u32 so_seqid; /* protected by so_sema */
+ atomic_t so_count;
+
+ struct rpc_cred *so_cred; /* Associated cred */
+ struct list_head so_states;
+ struct list_head so_delegations;
+};
+
+/*
+ * struct nfs4_state maintains the client-side state for a given
+ * (state_owner,inode) tuple (OPEN) or state_owner (LOCK).
+ *
+ * OPEN:
+ * In order to know when to OPEN_DOWNGRADE or CLOSE the state on the server,
+ * we need to know how many files are open for reading or writing on a
+ * given inode. This information too is stored here.
+ *
+ * LOCK: one nfs4_state (LOCK) to hold the lock stateid nfs4_state(OPEN)
+ */
+
+struct nfs4_lock_state {
+ struct list_head ls_locks; /* Other lock stateids */
+ struct nfs4_state * ls_state; /* Pointer to open state */
+ fl_owner_t ls_owner; /* POSIX lock owner */
+#define NFS_LOCK_INITIALIZED 1
+ int ls_flags;
+ u32 ls_seqid;
+ u32 ls_id;
+ nfs4_stateid ls_stateid;
+ atomic_t ls_count;
+};
+
+/* bits for nfs4_state->flags */
+enum {
+ LK_STATE_IN_USE,
+ NFS_DELEGATED_STATE,
+};
+
+struct nfs4_state {
+ struct list_head open_states; /* List of states for the same state_owner */
+ struct list_head inode_states; /* List of states for the same inode */
+ struct list_head lock_states; /* List of subservient lock stateids */
+
+ struct nfs4_state_owner *owner; /* Pointer to the open owner */
+ struct inode *inode; /* Pointer to the inode */
+
+ unsigned long flags; /* Do we hold any locks? */
+ struct semaphore lock_sema; /* Serializes file locking operations */
+ spinlock_t state_lock; /* Protects the lock_states list */
+
+ nfs4_stateid stateid;
+
+ unsigned int nreaders;
+ unsigned int nwriters;
+ int state; /* State on the server (R,W, or RW) */
+ atomic_t count;
+};
+
+
+struct nfs4_exception {
+ long timeout;
+ int retry;
+};
+
+struct nfs4_state_recovery_ops {
+ int (*recover_open)(struct nfs4_state_owner *, struct nfs4_state *);
+ int (*recover_lock)(struct nfs4_state *, struct file_lock *);
+};
+
+extern struct dentry_operations nfs4_dentry_operations;
+extern struct inode_operations nfs4_dir_inode_operations;
+
+/* inode.c */
+extern ssize_t nfs4_getxattr(struct dentry *, const char *, void *, size_t);
+extern int nfs4_setxattr(struct dentry *, const char *, const void *, size_t, int);
+extern ssize_t nfs4_listxattr(struct dentry *, char *, size_t);
+
+
+/* nfs4proc.c */
+extern int nfs4_map_errors(int err);
+extern int nfs4_proc_setclientid(struct nfs4_client *, u32, unsigned short);
+extern int nfs4_proc_setclientid_confirm(struct nfs4_client *);
+extern int nfs4_proc_async_renew(struct nfs4_client *);
+extern int nfs4_proc_renew(struct nfs4_client *);
+extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode);
+extern struct inode *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
+extern int nfs4_open_revalidate(struct inode *, struct dentry *, int);
+
+extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;
+extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops;
+
+extern const u32 nfs4_fattr_bitmap[2];
+extern const u32 nfs4_statfs_bitmap[2];
+extern const u32 nfs4_pathconf_bitmap[2];
+extern const u32 nfs4_fsinfo_bitmap[2];
+
+/* nfs4renewd.c */
+extern void nfs4_schedule_state_renewal(struct nfs4_client *);
+extern void nfs4_renewd_prepare_shutdown(struct nfs_server *);
+extern void nfs4_kill_renewd(struct nfs4_client *);
+extern void nfs4_renew_state(void *);
+
+/* nfs4state.c */
+extern void init_nfsv4_state(struct nfs_server *);
+extern void destroy_nfsv4_state(struct nfs_server *);
+extern struct nfs4_client *nfs4_get_client(struct in_addr *);
+extern void nfs4_put_client(struct nfs4_client *clp);
+extern int nfs4_init_client(struct nfs4_client *clp);
+extern struct nfs4_client *nfs4_find_client(struct in_addr *);
+extern u32 nfs4_alloc_lockowner_id(struct nfs4_client *);
+
+extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *);
+extern void nfs4_put_state_owner(struct nfs4_state_owner *);
+extern void nfs4_drop_state_owner(struct nfs4_state_owner *);
+extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *);
+extern void nfs4_put_open_state(struct nfs4_state *);
+extern void nfs4_close_state(struct nfs4_state *, mode_t);
+extern struct nfs4_state *nfs4_find_state(struct inode *, struct rpc_cred *, mode_t mode);
+extern void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp);
+extern void nfs4_schedule_state_recovery(struct nfs4_client *);
+extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl);
+extern void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *ls);
+extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t);
+
+extern const nfs4_stateid zero_stateid;
+
+/* nfs4xdr.c */
+extern uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus);
+extern struct rpc_procinfo nfs4_procedures[];
+
+struct nfs4_mount_data;
+
+/* callback_xdr.c */
+extern struct svc_version nfs4_callback_version1;
+
+#else
+
+#define init_nfsv4_state(server) do { } while (0)
+#define destroy_nfsv4_state(server) do { } while (0)
+#define nfs4_put_state_owner(inode, owner) do { } while (0)
+#define nfs4_put_open_state(state) do { } while (0)
+#define nfs4_close_state(a, b) do { } while (0)
+
+#endif /* CONFIG_NFS_V4 */
+#endif /* __LINUX_FS_NFS_NFS4_FS.H */
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 1d5cb3e80c3..1b76f80aedb 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -48,6 +48,7 @@
#include <linux/smp_lock.h>
#include <linux/namei.h>
+#include "nfs4_fs.h"
#include "delegation.h"
#define NFSDBG_FACILITY NFSDBG_PROC
@@ -62,8 +63,6 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus);
extern struct rpc_procinfo nfs4_procedures[];
-extern nfs4_stateid zero_stateid;
-
/* Prevent leaks of NFSv4 errors into userland */
int nfs4_map_errors(int err)
{
@@ -104,7 +103,7 @@ const u32 nfs4_statfs_bitmap[2] = {
| FATTR4_WORD1_SPACE_TOTAL
};
-u32 nfs4_pathconf_bitmap[2] = {
+const u32 nfs4_pathconf_bitmap[2] = {
FATTR4_WORD0_MAXLINK
| FATTR4_WORD0_MAXNAME,
0
@@ -124,7 +123,7 @@ static void nfs4_setup_readdir(u64 cookie, u32 *verifier, struct dentry *dentry,
BUG_ON(readdir->count < 80);
if (cookie > 2) {
- readdir->cookie = (cookie > 2) ? cookie : 0;
+ readdir->cookie = cookie;
memcpy(&readdir->verifier, verifier, sizeof(readdir->verifier));
return;
}
@@ -270,14 +269,9 @@ static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *sta
int err;
do {
err = _nfs4_open_reclaim(sp, state);
- switch (err) {
- case 0:
- case -NFS4ERR_STALE_CLIENTID:
- case -NFS4ERR_STALE_STATEID:
- case -NFS4ERR_EXPIRED:
- return err;
- }
- err = nfs4_handle_exception(server, err, &exception);
+ if (err != -NFS4ERR_DELAY)
+ break;
+ nfs4_handle_exception(server, err, &exception);
} while (exception.retry);
return err;
}
@@ -509,6 +503,20 @@ out_stale:
goto out_nodeleg;
}
+static inline int nfs4_do_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
+{
+ struct nfs_server *server = NFS_SERVER(dentry->d_inode);
+ struct nfs4_exception exception = { };
+ int err;
+
+ do {
+ err = _nfs4_open_expired(sp, state, dentry);
+ if (err == -NFS4ERR_DELAY)
+ nfs4_handle_exception(server, err, &exception);
+ } while (exception.retry);
+ return err;
+}
+
static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state)
{
struct nfs_inode *nfsi = NFS_I(state->inode);
@@ -521,7 +529,7 @@ static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *sta
continue;
get_nfs_open_context(ctx);
spin_unlock(&state->inode->i_lock);
- status = _nfs4_open_expired(sp, state, ctx->dentry);
+ status = nfs4_do_open_expired(sp, state, ctx->dentry);
put_nfs_open_context(ctx);
return status;
}
@@ -748,11 +756,10 @@ static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
fattr->valid = 0;
- if (state != NULL)
+ if (state != NULL) {
msg.rpc_cred = state->owner->so_cred;
- if (sattr->ia_valid & ATTR_SIZE)
- nfs4_copy_stateid(&arg.stateid, state, NULL);
- else
+ nfs4_copy_stateid(&arg.stateid, state, current->files);
+ } else
memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid));
return rpc_call_sync(server->client, &msg, 0);
@@ -1116,47 +1123,31 @@ static int
nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
struct iattr *sattr)
{
- struct inode * inode = dentry->d_inode;
- int size_change = sattr->ia_valid & ATTR_SIZE;
- struct nfs4_state *state = NULL;
- int need_iput = 0;
+ struct rpc_cred *cred;
+ struct inode *inode = dentry->d_inode;
+ struct nfs4_state *state;
int status;
fattr->valid = 0;
- if (size_change) {
- struct rpc_cred *cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
- if (IS_ERR(cred))
- return PTR_ERR(cred);
+ cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
+ if (IS_ERR(cred))
+ return PTR_ERR(cred);
+ /* Search for an existing WRITE delegation first */
+ state = nfs4_open_delegated(inode, FMODE_WRITE, cred);
+ if (!IS_ERR(state)) {
+ /* NB: nfs4_open_delegated() bumps the inode->i_count */
+ iput(inode);
+ } else {
+ /* Search for an existing open(O_WRITE) stateid */
state = nfs4_find_state(inode, cred, FMODE_WRITE);
- if (state == NULL) {
- state = nfs4_open_delegated(dentry->d_inode,
- FMODE_WRITE, cred);
- if (IS_ERR(state))
- state = nfs4_do_open(dentry->d_parent->d_inode,
- dentry, FMODE_WRITE,
- NULL, cred);
- need_iput = 1;
- }
- put_rpccred(cred);
- if (IS_ERR(state))
- return PTR_ERR(state);
-
- if (state->inode != inode) {
- printk(KERN_WARNING "nfs: raced in setattr (%p != %p), returning -EIO\n", inode, state->inode);
- status = -EIO;
- goto out;
- }
}
+
status = nfs4_do_setattr(NFS_SERVER(inode), fattr,
NFS_FH(inode), sattr, state);
-out:
- if (state) {
- inode = state->inode;
+ if (state != NULL)
nfs4_close_state(state, FMODE_WRITE);
- if (need_iput)
- iput(inode);
- }
+ put_rpccred(cred);
return status;
}
@@ -1731,6 +1722,10 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
};
int status;
+ dprintk("%s: dentry = %s/%s, cookie = %Lu\n", __FUNCTION__,
+ dentry->d_parent->d_name.name,
+ dentry->d_name.name,
+ (unsigned long long)cookie);
lock_kernel();
nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args);
res.pgbase = args.pgbase;
@@ -1738,6 +1733,7 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
if (status == 0)
memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE);
unlock_kernel();
+ dprintk("%s: returns %d\n", __FUNCTION__, status);
return status;
}
@@ -2163,6 +2159,193 @@ nfs4_proc_file_release(struct inode *inode, struct file *filp)
return 0;
}
+static inline int nfs4_server_supports_acls(struct nfs_server *server)
+{
+ return (server->caps & NFS_CAP_ACLS)
+ && (server->acl_bitmask & ACL4_SUPPORT_ALLOW_ACL)
+ && (server->acl_bitmask & ACL4_SUPPORT_DENY_ACL);
+}
+
+/* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_CACHE_SIZE, and that
+ * it's OK to put sizeof(void) * (XATTR_SIZE_MAX/PAGE_CACHE_SIZE) bytes on
+ * the stack.
+ */
+#define NFS4ACL_MAXPAGES (XATTR_SIZE_MAX >> PAGE_CACHE_SHIFT)
+
+static void buf_to_pages(const void *buf, size_t buflen,
+ struct page **pages, unsigned int *pgbase)
+{
+ const void *p = buf;
+
+ *pgbase = offset_in_page(buf);
+ p -= *pgbase;
+ while (p < buf + buflen) {
+ *(pages++) = virt_to_page(p);
+ p += PAGE_CACHE_SIZE;
+ }
+}
+
+struct nfs4_cached_acl {
+ int cached;
+ size_t len;
+ char data[0];
+};
+
+static void nfs4_set_cached_acl(struct inode *inode, struct nfs4_cached_acl *acl)
+{
+ struct nfs_inode *nfsi = NFS_I(inode);
+
+ spin_lock(&inode->i_lock);
+ kfree(nfsi->nfs4_acl);
+ nfsi->nfs4_acl = acl;
+ spin_unlock(&inode->i_lock);
+}
+
+static void nfs4_zap_acl_attr(struct inode *inode)
+{
+ nfs4_set_cached_acl(inode, NULL);
+}
+
+static inline ssize_t nfs4_read_cached_acl(struct inode *inode, char *buf, size_t buflen)
+{
+ struct nfs_inode *nfsi = NFS_I(inode);
+ struct nfs4_cached_acl *acl;
+ int ret = -ENOENT;
+
+ spin_lock(&inode->i_lock);
+ acl = nfsi->nfs4_acl;
+ if (acl == NULL)
+ goto out;
+ if (buf == NULL) /* user is just asking for length */
+ goto out_len;
+ if (acl->cached == 0)
+ goto out;
+ ret = -ERANGE; /* see getxattr(2) man page */
+ if (acl->len > buflen)
+ goto out;
+ memcpy(buf, acl->data, acl->len);
+out_len:
+ ret = acl->len;
+out:
+ spin_unlock(&inode->i_lock);
+ return ret;
+}
+
+static void nfs4_write_cached_acl(struct inode *inode, const char *buf, size_t acl_len)
+{
+ struct nfs4_cached_acl *acl;
+
+ if (buf && acl_len <= PAGE_SIZE) {
+ acl = kmalloc(sizeof(*acl) + acl_len, GFP_KERNEL);
+ if (acl == NULL)
+ goto out;
+ acl->cached = 1;
+ memcpy(acl->data, buf, acl_len);
+ } else {
+ acl = kmalloc(sizeof(*acl), GFP_KERNEL);
+ if (acl == NULL)
+ goto out;
+ acl->cached = 0;
+ }
+ acl->len = acl_len;
+out:
+ nfs4_set_cached_acl(inode, acl);
+}
+
+static inline ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
+{
+ struct page *pages[NFS4ACL_MAXPAGES];
+ struct nfs_getaclargs args = {
+ .fh = NFS_FH(inode),
+ .acl_pages = pages,
+ .acl_len = buflen,
+ };
+ size_t resp_len = buflen;
+ void *resp_buf;
+ struct rpc_message msg = {
+ .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL],
+ .rpc_argp = &args,
+ .rpc_resp = &resp_len,
+ };
+ struct page *localpage = NULL;
+ int ret;
+
+ if (buflen < PAGE_SIZE) {
+ /* As long as we're doing a round trip to the server anyway,
+ * let's be prepared for a page of acl data. */
+ localpage = alloc_page(GFP_KERNEL);
+ resp_buf = page_address(localpage);
+ if (localpage == NULL)
+ return -ENOMEM;
+ args.acl_pages[0] = localpage;
+ args.acl_pgbase = 0;
+ args.acl_len = PAGE_SIZE;
+ } else {
+ resp_buf = buf;
+ buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase);
+ }
+ ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+ if (ret)
+ goto out_free;
+ if (resp_len > args.acl_len)
+ nfs4_write_cached_acl(inode, NULL, resp_len);
+ else
+ nfs4_write_cached_acl(inode, resp_buf, resp_len);
+ if (buf) {
+ ret = -ERANGE;
+ if (resp_len > buflen)
+ goto out_free;
+ if (localpage)
+ memcpy(buf, resp_buf, resp_len);
+ }
+ ret = resp_len;
+out_free:
+ if (localpage)
+ __free_page(localpage);
+ return ret;
+}
+
+static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
+{
+ struct nfs_server *server = NFS_SERVER(inode);
+ int ret;
+
+ if (!nfs4_server_supports_acls(server))
+ return -EOPNOTSUPP;
+ ret = nfs_revalidate_inode(server, inode);
+ if (ret < 0)
+ return ret;
+ ret = nfs4_read_cached_acl(inode, buf, buflen);
+ if (ret != -ENOENT)
+ return ret;
+ return nfs4_get_acl_uncached(inode, buf, buflen);
+}
+
+static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen)
+{
+ struct nfs_server *server = NFS_SERVER(inode);
+ struct page *pages[NFS4ACL_MAXPAGES];
+ struct nfs_setaclargs arg = {
+ .fh = NFS_FH(inode),
+ .acl_pages = pages,
+ .acl_len = buflen,
+ };
+ struct rpc_message msg = {
+ .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETACL],
+ .rpc_argp = &arg,
+ .rpc_resp = NULL,
+ };
+ int ret;
+
+ if (!nfs4_server_supports_acls(server))
+ return -EOPNOTSUPP;
+ buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
+ ret = rpc_call_sync(NFS_SERVER(inode)->client, &msg, 0);
+ if (ret == 0)
+ nfs4_write_cached_acl(inode, buf, buflen);
+ return ret;
+}
+
static int
nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server)
{
@@ -2448,14 +2631,11 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock
down_read(&clp->cl_sem);
nlo.clientid = clp->cl_clientid;
down(&state->lock_sema);
- lsp = nfs4_find_lock_state(state, request->fl_owner);
- if (lsp)
- nlo.id = lsp->ls_id;
- else {
- spin_lock(&clp->cl_lock);
- nlo.id = nfs4_alloc_lockowner_id(clp);
- spin_unlock(&clp->cl_lock);
- }
+ status = nfs4_set_lock_state(state, request);
+ if (status != 0)
+ goto out;
+ lsp = request->fl_u.nfs4_fl.owner;
+ nlo.id = lsp->ls_id;
arg.u.lockt = &nlo;
status = rpc_call_sync(server->client, &msg, 0);
if (!status) {
@@ -2476,8 +2656,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock
request->fl_pid = 0;
status = 0;
}
- if (lsp)
- nfs4_put_lock_state(lsp);
+out:
up(&state->lock_sema);
up_read(&clp->cl_sem);
return status;
@@ -2537,28 +2716,26 @@ static int _nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock
};
struct nfs4_lock_state *lsp;
struct nfs_locku_opargs luargs;
- int status = 0;
+ int status;
down_read(&clp->cl_sem);
down(&state->lock_sema);
- lsp = nfs4_find_lock_state(state, request->fl_owner);
- if (!lsp)
+ status = nfs4_set_lock_state(state, request);
+ if (status != 0)
goto out;
+ lsp = request->fl_u.nfs4_fl.owner;
/* We might have lost the locks! */
- if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) {
- luargs.seqid = lsp->ls_seqid;
- memcpy(&luargs.stateid, &lsp->ls_stateid, sizeof(luargs.stateid));
- arg.u.locku = &luargs;
- status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
- nfs4_increment_lock_seqid(status, lsp);
- }
+ if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0)
+ goto out;
+ luargs.seqid = lsp->ls_seqid;
+ memcpy(&luargs.stateid, &lsp->ls_stateid, sizeof(luargs.stateid));
+ arg.u.locku = &luargs;
+ status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
+ nfs4_increment_lock_seqid(status, lsp);
- if (status == 0) {
+ if (status == 0)
memcpy(&lsp->ls_stateid, &res.u.stateid,
sizeof(lsp->ls_stateid));
- nfs4_notify_unlck(state, request, lsp);
- }
- nfs4_put_lock_state(lsp);
out:
up(&state->lock_sema);
if (status == 0)
@@ -2584,7 +2761,7 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *r
{
struct inode *inode = state->inode;
struct nfs_server *server = NFS_SERVER(inode);
- struct nfs4_lock_state *lsp;
+ struct nfs4_lock_state *lsp = request->fl_u.nfs4_fl.owner;
struct nfs_lockargs arg = {
.fh = NFS_FH(inode),
.type = nfs4_lck_type(cmd, request),
@@ -2606,9 +2783,6 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *r
};
int status;
- lsp = nfs4_get_lock_state(state, request->fl_owner);
- if (lsp == NULL)
- return -ENOMEM;
if (!(lsp->ls_flags & NFS_LOCK_INITIALIZED)) {
struct nfs4_state_owner *owner = state->owner;
struct nfs_open_to_lock otl = {
@@ -2630,38 +2804,57 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *r
* seqid mutating errors */
nfs4_increment_seqid(status, owner);
up(&owner->so_sema);
+ if (status == 0) {
+ lsp->ls_flags |= NFS_LOCK_INITIALIZED;
+ lsp->ls_seqid++;
+ }
} else {
struct nfs_exist_lock el = {
.seqid = lsp->ls_seqid,
};
memcpy(&el.stateid, &lsp->ls_stateid, sizeof(el.stateid));
largs.u.exist_lock = &el;
- largs.new_lock_owner = 0;
arg.u.lock = &largs;
status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
+ /* increment seqid on success, and * seqid mutating errors*/
+ nfs4_increment_lock_seqid(status, lsp);
}
- /* increment seqid on success, and * seqid mutating errors*/
- nfs4_increment_lock_seqid(status, lsp);
/* save the returned stateid. */
- if (status == 0) {
+ if (status == 0)
memcpy(&lsp->ls_stateid, &res.u.stateid, sizeof(nfs4_stateid));
- lsp->ls_flags |= NFS_LOCK_INITIALIZED;
- if (!reclaim)
- nfs4_notify_setlk(state, request, lsp);
- } else if (status == -NFS4ERR_DENIED)
+ else if (status == -NFS4ERR_DENIED)
status = -EAGAIN;
- nfs4_put_lock_state(lsp);
return status;
}
static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request)
{
- return _nfs4_do_setlk(state, F_SETLK, request, 1);
+ struct nfs_server *server = NFS_SERVER(state->inode);
+ struct nfs4_exception exception = { };
+ int err;
+
+ do {
+ err = _nfs4_do_setlk(state, F_SETLK, request, 1);
+ if (err != -NFS4ERR_DELAY)
+ break;
+ nfs4_handle_exception(server, err, &exception);
+ } while (exception.retry);
+ return err;
}
static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request)
{
- return _nfs4_do_setlk(state, F_SETLK, request, 0);
+ struct nfs_server *server = NFS_SERVER(state->inode);
+ struct nfs4_exception exception = { };
+ int err;
+
+ do {
+ err = _nfs4_do_setlk(state, F_SETLK, request, 0);
+ if (err != -NFS4ERR_DELAY)
+ break;
+ nfs4_handle_exception(server, err, &exception);
+ } while (exception.retry);
+ return err;
}
static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
@@ -2671,7 +2864,9 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock
down_read(&clp->cl_sem);
down(&state->lock_sema);
- status = _nfs4_do_setlk(state, cmd, request, 0);
+ status = nfs4_set_lock_state(state, request);
+ if (status == 0)
+ status = _nfs4_do_setlk(state, cmd, request, 0);
up(&state->lock_sema);
if (status == 0) {
/* Note: we always want to sleep here! */
@@ -2729,10 +2924,53 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
if (signalled())
break;
} while(status < 0);
-
return status;
}
+
+#define XATTR_NAME_NFSV4_ACL "system.nfs4_acl"
+
+int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf,
+ size_t buflen, int flags)
+{
+ struct inode *inode = dentry->d_inode;
+
+ if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0)
+ return -EOPNOTSUPP;
+
+ if (!S_ISREG(inode->i_mode) &&
+ (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
+ return -EPERM;
+
+ return nfs4_proc_set_acl(inode, buf, buflen);
+}
+
+/* The getxattr man page suggests returning -ENODATA for unknown attributes,
+ * and that's what we'll do for e.g. user attributes that haven't been set.
+ * But we'll follow ext2/ext3's lead by returning -EOPNOTSUPP for unsupported
+ * attributes in kernel-managed attribute namespaces. */
+ssize_t nfs4_getxattr(struct dentry *dentry, const char *key, void *buf,
+ size_t buflen)
+{
+ struct inode *inode = dentry->d_inode;
+
+ if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0)
+ return -EOPNOTSUPP;
+
+ return nfs4_proc_get_acl(inode, buf, buflen);
+}
+
+ssize_t nfs4_listxattr(struct dentry *dentry, char *buf, size_t buflen)
+{
+ size_t len = strlen(XATTR_NAME_NFSV4_ACL) + 1;
+
+ if (buf && buflen < len)
+ return -ERANGE;
+ if (buf)
+ memcpy(buf, XATTR_NAME_NFSV4_ACL, len);
+ return len;
+}
+
struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = {
.recover_open = nfs4_open_reclaim,
.recover_lock = nfs4_lock_reclaim,
@@ -2743,10 +2981,20 @@ struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops = {
.recover_lock = nfs4_lock_expired,
};
+static struct inode_operations nfs4_file_inode_operations = {
+ .permission = nfs_permission,
+ .getattr = nfs_getattr,
+ .setattr = nfs_setattr,
+ .getxattr = nfs4_getxattr,
+ .setxattr = nfs4_setxattr,
+ .listxattr = nfs4_listxattr,
+};
+
struct nfs_rpc_ops nfs_v4_clientops = {
.version = 4, /* protocol version */
.dentry_ops = &nfs4_dentry_operations,
.dir_inode_ops = &nfs4_dir_inode_operations,
+ .file_inode_ops = &nfs4_file_inode_operations,
.getroot = nfs4_proc_get_root,
.getattr = nfs4_proc_getattr,
.setattr = nfs4_proc_setattr,
@@ -2777,6 +3025,7 @@ struct nfs_rpc_ops nfs_v4_clientops = {
.file_open = nfs4_proc_file_open,
.file_release = nfs4_proc_file_release,
.lock = nfs4_proc_lock,
+ .clear_acl_cache = nfs4_zap_acl_attr,
};
/*
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c
index 667e06f1c64..a3001628ad3 100644
--- a/fs/nfs/nfs4renewd.c
+++ b/fs/nfs/nfs4renewd.c
@@ -53,6 +53,7 @@
#include <linux/nfs.h>
#include <linux/nfs4.h>
#include <linux/nfs_fs.h>
+#include "nfs4_fs.h"
#define NFSDBG_FACILITY NFSDBG_PROC
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 231cebce3c8..afe587d82f1 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -46,24 +46,18 @@
#include <linux/workqueue.h>
#include <linux/bitops.h>
+#include "nfs4_fs.h"
#include "callback.h"
#include "delegation.h"
#define OPENOWNER_POOL_SIZE 8
-static DEFINE_SPINLOCK(state_spinlock);
-
-nfs4_stateid zero_stateid;
-
-#if 0
-nfs4_stateid one_stateid =
- { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-#endif
+const nfs4_stateid zero_stateid;
+static DEFINE_SPINLOCK(state_spinlock);
static LIST_HEAD(nfs4_clientid_list);
static void nfs4_recover_state(void *);
-extern void nfs4_renew_state(void *);
void
init_nfsv4_state(struct nfs_server *server)
@@ -116,6 +110,7 @@ nfs4_alloc_client(struct in_addr *addr)
INIT_LIST_HEAD(&clp->cl_superblocks);
init_waitqueue_head(&clp->cl_waitq);
rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client");
+ clp->cl_rpcclient = ERR_PTR(-EINVAL);
clp->cl_boot_time = CURRENT_TIME;
clp->cl_state = 1 << NFS4CLNT_OK;
return clp;
@@ -137,7 +132,7 @@ nfs4_free_client(struct nfs4_client *clp)
if (clp->cl_cred)
put_rpccred(clp->cl_cred);
nfs_idmap_delete(clp);
- if (clp->cl_rpcclient)
+ if (!IS_ERR(clp->cl_rpcclient))
rpc_shutdown_client(clp->cl_rpcclient);
kfree(clp);
nfs_callback_down();
@@ -365,7 +360,7 @@ nfs4_alloc_open_state(void)
atomic_set(&state->count, 1);
INIT_LIST_HEAD(&state->lock_states);
init_MUTEX(&state->lock_sema);
- rwlock_init(&state->state_lock);
+ spin_lock_init(&state->state_lock);
return state;
}
@@ -547,16 +542,6 @@ __nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
return NULL;
}
-struct nfs4_lock_state *
-nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
-{
- struct nfs4_lock_state *lsp;
- read_lock(&state->state_lock);
- lsp = __nfs4_find_lock_state(state, fl_owner);
- read_unlock(&state->state_lock);
- return lsp;
-}
-
/*
* Return a compatible lock_state. If no initialized lock_state structure
* exists, return an uninitialized one.
@@ -573,14 +558,13 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f
return NULL;
lsp->ls_flags = 0;
lsp->ls_seqid = 0; /* arbitrary */
- lsp->ls_id = -1;
memset(lsp->ls_stateid.data, 0, sizeof(lsp->ls_stateid.data));
atomic_set(&lsp->ls_count, 1);
lsp->ls_owner = fl_owner;
- INIT_LIST_HEAD(&lsp->ls_locks);
spin_lock(&clp->cl_lock);
lsp->ls_id = nfs4_alloc_lockowner_id(clp);
spin_unlock(&clp->cl_lock);
+ INIT_LIST_HEAD(&lsp->ls_locks);
return lsp;
}
@@ -590,121 +574,112 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f
*
* The caller must be holding state->lock_sema and clp->cl_sem
*/
-struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner)
+static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner)
{
- struct nfs4_lock_state * lsp;
+ struct nfs4_lock_state *lsp, *new = NULL;
- lsp = nfs4_find_lock_state(state, owner);
- if (lsp == NULL)
- lsp = nfs4_alloc_lock_state(state, owner);
+ for(;;) {
+ spin_lock(&state->state_lock);
+ lsp = __nfs4_find_lock_state(state, owner);
+ if (lsp != NULL)
+ break;
+ if (new != NULL) {
+ new->ls_state = state;
+ list_add(&new->ls_locks, &state->lock_states);
+ set_bit(LK_STATE_IN_USE, &state->flags);
+ lsp = new;
+ new = NULL;
+ break;
+ }
+ spin_unlock(&state->state_lock);
+ new = nfs4_alloc_lock_state(state, owner);
+ if (new == NULL)
+ return NULL;
+ }
+ spin_unlock(&state->state_lock);
+ kfree(new);
return lsp;
}
/*
- * Byte-range lock aware utility to initialize the stateid of read/write
- * requests.
+ * Release reference to lock_state, and free it if we see that
+ * it is no longer in use
*/
-void
-nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner)
+static void nfs4_put_lock_state(struct nfs4_lock_state *lsp)
{
- if (test_bit(LK_STATE_IN_USE, &state->flags)) {
- struct nfs4_lock_state *lsp;
+ struct nfs4_state *state;
- lsp = nfs4_find_lock_state(state, fl_owner);
- if (lsp) {
- memcpy(dst, &lsp->ls_stateid, sizeof(*dst));
- nfs4_put_lock_state(lsp);
- return;
- }
- }
- memcpy(dst, &state->stateid, sizeof(*dst));
+ if (lsp == NULL)
+ return;
+ state = lsp->ls_state;
+ if (!atomic_dec_and_lock(&lsp->ls_count, &state->state_lock))
+ return;
+ list_del(&lsp->ls_locks);
+ if (list_empty(&state->lock_states))
+ clear_bit(LK_STATE_IN_USE, &state->flags);
+ spin_unlock(&state->state_lock);
+ kfree(lsp);
}
-/*
-* Called with state->lock_sema and clp->cl_sem held.
-*/
-void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *lsp)
+static void nfs4_fl_copy_lock(struct file_lock *dst, struct file_lock *src)
{
- if (status == NFS_OK || seqid_mutating_err(-status))
- lsp->ls_seqid++;
-}
+ struct nfs4_lock_state *lsp = src->fl_u.nfs4_fl.owner;
-/*
-* Check to see if the request lock (type FL_UNLK) effects the fl lock.
-*
-* fl and request must have the same posix owner
-*
-* return:
-* 0 -> fl not effected by request
-* 1 -> fl consumed by request
-*/
+ dst->fl_u.nfs4_fl.owner = lsp;
+ atomic_inc(&lsp->ls_count);
+}
-static int
-nfs4_check_unlock(struct file_lock *fl, struct file_lock *request)
+static void nfs4_fl_release_lock(struct file_lock *fl)
{
- if (fl->fl_start >= request->fl_start && fl->fl_end <= request->fl_end)
- return 1;
- return 0;
+ nfs4_put_lock_state(fl->fl_u.nfs4_fl.owner);
}
-/*
- * Post an initialized lock_state on the state->lock_states list.
- */
-void nfs4_notify_setlk(struct nfs4_state *state, struct file_lock *request, struct nfs4_lock_state *lsp)
+static struct file_lock_operations nfs4_fl_lock_ops = {
+ .fl_copy_lock = nfs4_fl_copy_lock,
+ .fl_release_private = nfs4_fl_release_lock,
+};
+
+int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl)
{
- if (!list_empty(&lsp->ls_locks))
- return;
- atomic_inc(&lsp->ls_count);
- write_lock(&state->state_lock);
- list_add(&lsp->ls_locks, &state->lock_states);
- set_bit(LK_STATE_IN_USE, &state->flags);
- write_unlock(&state->state_lock);
+ struct nfs4_lock_state *lsp;
+
+ if (fl->fl_ops != NULL)
+ return 0;
+ lsp = nfs4_get_lock_state(state, fl->fl_owner);
+ if (lsp == NULL)
+ return -ENOMEM;
+ fl->fl_u.nfs4_fl.owner = lsp;
+ fl->fl_ops = &nfs4_fl_lock_ops;
+ return 0;
}
-/*
- * to decide to 'reap' lock state:
- * 1) search i_flock for file_locks with fl.lock_state = to ls.
- * 2) determine if unlock will consume found lock.
- * if so, reap
- *
- * else, don't reap.
- *
+/*
+ * Byte-range lock aware utility to initialize the stateid of read/write
+ * requests.
*/
-void
-nfs4_notify_unlck(struct nfs4_state *state, struct file_lock *request, struct nfs4_lock_state *lsp)
+void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner)
{
- struct inode *inode = state->inode;
- struct file_lock *fl;
+ struct nfs4_lock_state *lsp;
- for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
- if (!(fl->fl_flags & FL_POSIX))
- continue;
- if (fl->fl_owner != lsp->ls_owner)
- continue;
- /* Exit if we find at least one lock which is not consumed */
- if (nfs4_check_unlock(fl,request) == 0)
- return;
- }
+ memcpy(dst, &state->stateid, sizeof(*dst));
+ if (test_bit(LK_STATE_IN_USE, &state->flags) == 0)
+ return;
- write_lock(&state->state_lock);
- list_del_init(&lsp->ls_locks);
- if (list_empty(&state->lock_states))
- clear_bit(LK_STATE_IN_USE, &state->flags);
- write_unlock(&state->state_lock);
+ spin_lock(&state->state_lock);
+ lsp = __nfs4_find_lock_state(state, fl_owner);
+ if (lsp != NULL && (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0)
+ memcpy(dst, &lsp->ls_stateid, sizeof(*dst));
+ spin_unlock(&state->state_lock);
nfs4_put_lock_state(lsp);
}
/*
- * Release reference to lock_state, and free it if we see that
- * it is no longer in use
- */
-void
-nfs4_put_lock_state(struct nfs4_lock_state *lsp)
+* Called with state->lock_sema and clp->cl_sem held.
+*/
+void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *lsp)
{
- if (!atomic_dec_and_test(&lsp->ls_count))
- return;
- BUG_ON (!list_empty(&lsp->ls_locks));
- kfree(lsp);
+ if (status == NFS_OK || seqid_mutating_err(-status))
+ lsp->ls_seqid++;
}
/*
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 5f4de05763c..6c564ef9489 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -51,6 +51,7 @@
#include <linux/nfs4.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_idmap.h>
+#include "nfs4_fs.h"
#define NFSDBG_FACILITY NFSDBG_XDR
@@ -82,12 +83,16 @@ static int nfs_stat_to_errno(int);
#define encode_getfh_maxsz (op_encode_hdr_maxsz)
#define decode_getfh_maxsz (op_decode_hdr_maxsz + 1 + \
((3+NFS4_FHSIZE) >> 2))
-#define encode_getattr_maxsz (op_encode_hdr_maxsz + 3)
+#define nfs4_fattr_bitmap_maxsz 3
+#define encode_getattr_maxsz (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz)
#define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2))
#define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2))
-#define nfs4_fattr_bitmap_maxsz (36 + 2 * nfs4_name_maxsz)
-#define decode_getattr_maxsz (op_decode_hdr_maxsz + 3 + \
- nfs4_fattr_bitmap_maxsz)
+/* This is based on getfattr, which uses the most attributes: */
+#define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \
+ 3 + 3 + 3 + 2 * nfs4_name_maxsz))
+#define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \
+ nfs4_fattr_value_maxsz)
+#define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz)
#define encode_savefh_maxsz (op_encode_hdr_maxsz)
#define decode_savefh_maxsz (op_decode_hdr_maxsz)
#define encode_fsinfo_maxsz (op_encode_hdr_maxsz + 2)
@@ -122,11 +127,11 @@ static int nfs_stat_to_errno(int);
#define encode_symlink_maxsz (op_encode_hdr_maxsz + \
1 + nfs4_name_maxsz + \
nfs4_path_maxsz + \
- nfs4_fattr_bitmap_maxsz)
+ nfs4_fattr_maxsz)
#define decode_symlink_maxsz (op_decode_hdr_maxsz + 8)
#define encode_create_maxsz (op_encode_hdr_maxsz + \
2 + nfs4_name_maxsz + \
- nfs4_fattr_bitmap_maxsz)
+ nfs4_fattr_maxsz)
#define decode_create_maxsz (op_decode_hdr_maxsz + 8)
#define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4)
#define decode_delegreturn_maxsz (op_decode_hdr_maxsz)
@@ -205,7 +210,7 @@ static int nfs_stat_to_errno(int);
#define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
op_encode_hdr_maxsz + 4 + \
- nfs4_fattr_bitmap_maxsz + \
+ nfs4_fattr_maxsz + \
encode_getattr_maxsz)
#define NFS4_dec_setattr_sz (compound_decode_hdr_maxsz + \
decode_putfh_maxsz + \
@@ -360,6 +365,20 @@ static int nfs_stat_to_errno(int);
encode_delegreturn_maxsz)
#define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \
decode_delegreturn_maxsz)
+#define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \
+ encode_putfh_maxsz + \
+ encode_getattr_maxsz)
+#define NFS4_dec_getacl_sz (compound_decode_hdr_maxsz + \
+ decode_putfh_maxsz + \
+ op_decode_hdr_maxsz + \
+ nfs4_fattr_bitmap_maxsz + 1)
+#define NFS4_enc_setacl_sz (compound_encode_hdr_maxsz + \
+ encode_putfh_maxsz + \
+ op_encode_hdr_maxsz + 4 + \
+ nfs4_fattr_bitmap_maxsz + 1)
+#define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \
+ decode_putfh_maxsz + \
+ op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz)
static struct {
unsigned int mode;
@@ -459,7 +478,7 @@ static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const s
* In the worst-case, this would be
* 12(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime)
* = 36 bytes, plus any contribution from variable-length fields
- * such as owner/group/acl's.
+ * such as owner/group.
*/
len = 16;
@@ -660,8 +679,6 @@ static int encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1
static int encode_getfattr(struct xdr_stream *xdr, const u32* bitmask)
{
- extern u32 nfs4_fattr_bitmap[];
-
return encode_getattr_two(xdr,
bitmask[0] & nfs4_fattr_bitmap[0],
bitmask[1] & nfs4_fattr_bitmap[1]);
@@ -669,8 +686,6 @@ static int encode_getfattr(struct xdr_stream *xdr, const u32* bitmask)
static int encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask)
{
- extern u32 nfs4_fsinfo_bitmap[];
-
return encode_getattr_two(xdr, bitmask[0] & nfs4_fsinfo_bitmap[0],
bitmask[1] & nfs4_fsinfo_bitmap[1]);
}
@@ -969,7 +984,6 @@ static int encode_putrootfh(struct xdr_stream *xdr)
static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx)
{
- extern nfs4_stateid zero_stateid;
nfs4_stateid stateid;
uint32_t *p;
@@ -1000,6 +1014,10 @@ static int encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args)
static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req)
{
struct rpc_auth *auth = req->rq_task->tk_auth;
+ uint32_t attrs[2] = {
+ FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID,
+ FATTR4_WORD1_MOUNTED_ON_FILEID,
+ };
int replen;
uint32_t *p;
@@ -1010,13 +1028,20 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
WRITE32(readdir->count >> 1); /* We're not doing readdirplus */
WRITE32(readdir->count);
WRITE32(2);
- if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID) {
- WRITE32(0);
- WRITE32(FATTR4_WORD1_MOUNTED_ON_FILEID);
- } else {
- WRITE32(FATTR4_WORD0_FILEID);
- WRITE32(0);
- }
+ /* Switch to mounted_on_fileid if the server supports it */
+ if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)
+ attrs[0] &= ~FATTR4_WORD0_FILEID;
+ else
+ attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
+ WRITE32(attrs[0] & readdir->bitmask[0]);
+ WRITE32(attrs[1] & readdir->bitmask[1]);
+ dprintk("%s: cookie = %Lu, verifier = 0x%x%x, bitmap = 0x%x%x\n",
+ __FUNCTION__,
+ (unsigned long long)readdir->cookie,
+ ((u32 *)readdir->verifier.data)[0],
+ ((u32 *)readdir->verifier.data)[1],
+ attrs[0] & readdir->bitmask[0],
+ attrs[1] & readdir->bitmask[1]);
/* set up reply kvec
* toplevel_status + taglen + rescount + OP_PUTFH + status
@@ -1025,6 +1050,9 @@ static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
replen = (RPC_REPHDRSIZE + auth->au_rslack + 9) << 2;
xdr_inline_pages(&req->rq_rcv_buf, replen, readdir->pages,
readdir->pgbase, readdir->count);
+ dprintk("%s: inlined page args = (%u, %p, %u, %u)\n",
+ __FUNCTION__, replen, readdir->pages,
+ readdir->pgbase, readdir->count);
return 0;
}
@@ -1089,6 +1117,25 @@ static int encode_renew(struct xdr_stream *xdr, const struct nfs4_client *client
}
static int
+encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg)
+{
+ uint32_t *p;
+
+ RESERVE_SPACE(4+sizeof(zero_stateid.data));
+ WRITE32(OP_SETATTR);
+ WRITEMEM(zero_stateid.data, sizeof(zero_stateid.data));
+ RESERVE_SPACE(2*4);
+ WRITE32(1);
+ WRITE32(FATTR4_WORD0_ACL);
+ if (arg->acl_len % 4)
+ return -EINVAL;
+ RESERVE_SPACE(4);
+ WRITE32(arg->acl_len);
+ xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len);
+ return 0;
+}
+
+static int
encode_savefh(struct xdr_stream *xdr)
{
uint32_t *p;
@@ -1632,6 +1679,34 @@ out:
}
/*
+ * Encode a GETACL request
+ */
+static int
+nfs4_xdr_enc_getacl(struct rpc_rqst *req, uint32_t *p,
+ struct nfs_getaclargs *args)
+{
+ struct xdr_stream xdr;
+ struct rpc_auth *auth = req->rq_task->tk_auth;
+ struct compound_hdr hdr = {
+ .nops = 2,
+ };
+ int replen, status;
+
+ xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+ encode_compound_hdr(&xdr, &hdr);
+ status = encode_putfh(&xdr, args->fh);
+ if (status)
+ goto out;
+ status = encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0);
+ /* set up reply buffer: */
+ replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_dec_getacl_sz) << 2;
+ xdr_inline_pages(&req->rq_rcv_buf, replen,
+ args->acl_pages, args->acl_pgbase, args->acl_len);
+out:
+ return status;
+}
+
+/*
* Encode a WRITE request
*/
static int nfs4_xdr_enc_write(struct rpc_rqst *req, uint32_t *p, struct nfs_writeargs *args)
@@ -1697,7 +1772,6 @@ static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, uint32_t *p, struct nfs4_fs
*/
static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, uint32_t *p, const struct nfs4_pathconf_arg *args)
{
- extern u32 nfs4_pathconf_bitmap[2];
struct xdr_stream xdr;
struct compound_hdr hdr = {
.nops = 2,
@@ -1718,7 +1792,6 @@ static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, uint32_t *p, const struct
*/
static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, uint32_t *p, const struct nfs4_statfs_arg *args)
{
- extern u32 nfs4_statfs_bitmap[];
struct xdr_stream xdr;
struct compound_hdr hdr = {
.nops = 2,
@@ -3003,6 +3076,11 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
return status;
READ_BUF(8);
COPYMEM(readdir->verifier.data, 8);
+ dprintk("%s: verifier = 0x%x%x\n",
+ __FUNCTION__,
+ ((u32 *)readdir->verifier.data)[0],
+ ((u32 *)readdir->verifier.data)[1]);
+
hdrlen = (char *) p - (char *) iov->iov_base;
recvd = rcvbuf->len - hdrlen;
@@ -3017,12 +3095,14 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
for (nr = 0; *p++; nr++) {
if (p + 3 > end)
goto short_pkt;
+ dprintk("cookie = %Lu, ", *((unsigned long long *)p));
p += 2; /* cookie */
len = ntohl(*p++); /* filename length */
if (len > NFS4_MAXNAMLEN) {
printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)\n", len);
goto err_unmap;
}
+ dprintk("filename = %*s\n", len, (char *)p);
p += XDR_QUADLEN(len);
if (p + 1 > end)
goto short_pkt;
@@ -3042,6 +3122,7 @@ out:
kunmap_atomic(kaddr, KM_USER0);
return 0;
short_pkt:
+ dprintk("%s: short packet at entry %d\n", __FUNCTION__, nr);
entry[0] = entry[1] = 0;
/* truncate listing ? */
if (!nr) {
@@ -3127,6 +3208,47 @@ static int decode_renew(struct xdr_stream *xdr)
return decode_op_hdr(xdr, OP_RENEW);
}
+static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
+ size_t *acl_len)
+{
+ uint32_t *savep;
+ uint32_t attrlen,
+ bitmap[2] = {0};
+ struct kvec *iov = req->rq_rcv_buf.head;
+ int status;
+
+ *acl_len = 0;
+ if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
+ goto out;
+ if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
+ goto out;
+ if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
+ goto out;
+
+ if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U)))
+ return -EIO;
+ if (likely(bitmap[0] & FATTR4_WORD0_ACL)) {
+ int hdrlen, recvd;
+
+ /* We ignore &savep and don't do consistency checks on
+ * the attr length. Let userspace figure it out.... */
+ hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base;
+ recvd = req->rq_rcv_buf.len - hdrlen;
+ if (attrlen > recvd) {
+ printk(KERN_WARNING "NFS: server cheating in getattr"
+ " acl reply: attrlen %u > recvd %u\n",
+ attrlen, recvd);
+ return -EINVAL;
+ }
+ if (attrlen <= *acl_len)
+ xdr_read_pages(xdr, attrlen);
+ *acl_len = attrlen;
+ }
+
+out:
+ return status;
+}
+
static int
decode_savefh(struct xdr_stream *xdr)
{
@@ -3418,6 +3540,71 @@ out:
}
+/*
+ * Encode an SETACL request
+ */
+static int
+nfs4_xdr_enc_setacl(struct rpc_rqst *req, uint32_t *p, struct nfs_setaclargs *args)
+{
+ struct xdr_stream xdr;
+ struct compound_hdr hdr = {
+ .nops = 2,
+ };
+ int status;
+
+ xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+ encode_compound_hdr(&xdr, &hdr);
+ status = encode_putfh(&xdr, args->fh);
+ if (status)
+ goto out;
+ status = encode_setacl(&xdr, args);
+out:
+ return status;
+}
+/*
+ * Decode SETACL response
+ */
+static int
+nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, uint32_t *p, void *res)
+{
+ struct xdr_stream xdr;
+ struct compound_hdr hdr;
+ int status;
+
+ xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (status)
+ goto out;
+ status = decode_putfh(&xdr);
+ if (status)
+ goto out;
+ status = decode_setattr(&xdr, res);
+out:
+ return status;
+}
+
+/*
+ * Decode GETACL response
+ */
+static int
+nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, uint32_t *p, size_t *acl_len)
+{
+ struct xdr_stream xdr;
+ struct compound_hdr hdr;
+ int status;
+
+ xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+ status = decode_compound_hdr(&xdr, &hdr);
+ if (status)
+ goto out;
+ status = decode_putfh(&xdr);
+ if (status)
+ goto out;
+ status = decode_getacl(&xdr, rqstp, acl_len);
+
+out:
+ return status;
+}
/*
* Decode CLOSE response
@@ -3895,6 +4082,12 @@ uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus)
}
len = XDR_QUADLEN(ntohl(*p++)); /* attribute buffer length */
if (len > 0) {
+ if (bitmap[0] & FATTR4_WORD0_RDATTR_ERROR) {
+ bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR;
+ /* Ignore the return value of rdattr_error for now */
+ p++;
+ len--;
+ }
if (bitmap[0] == 0 && bitmap[1] == FATTR4_WORD1_MOUNTED_ON_FILEID)
xdr_decode_hyper(p, &entry->ino);
else if (bitmap[0] == FATTR4_WORD0_FILEID)
@@ -3934,6 +4127,8 @@ static struct {
{ NFS4ERR_DQUOT, EDQUOT },
{ NFS4ERR_STALE, ESTALE },
{ NFS4ERR_BADHANDLE, EBADHANDLE },
+ { NFS4ERR_BADOWNER, EINVAL },
+ { NFS4ERR_BADNAME, EINVAL },
{ NFS4ERR_BAD_COOKIE, EBADCOOKIE },
{ NFS4ERR_NOTSUPP, ENOTSUPP },
{ NFS4ERR_TOOSMALL, ETOOSMALL },
@@ -4019,6 +4214,8 @@ struct rpc_procinfo nfs4_procedures[] = {
PROC(READDIR, enc_readdir, dec_readdir),
PROC(SERVER_CAPS, enc_server_caps, dec_server_caps),
PROC(DELEGRETURN, enc_delegreturn, dec_delegreturn),
+ PROC(GETACL, enc_getacl, dec_getacl),
+ PROC(SETACL, enc_setacl, dec_setacl),
};
struct rpc_version nfs_version4 = {
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
index fd5bc596fe8..1b272a135a3 100644
--- a/fs/nfs/nfsroot.c
+++ b/fs/nfs/nfsroot.c
@@ -124,6 +124,7 @@ enum {
Opt_soft, Opt_hard, Opt_intr,
Opt_nointr, Opt_posix, Opt_noposix, Opt_cto, Opt_nocto, Opt_ac,
Opt_noac, Opt_lock, Opt_nolock, Opt_v2, Opt_v3, Opt_udp, Opt_tcp,
+ Opt_acl, Opt_noacl,
/* Error token */
Opt_err
};
@@ -158,6 +159,8 @@ static match_table_t __initdata tokens = {
{Opt_udp, "udp"},
{Opt_tcp, "proto=tcp"},
{Opt_tcp, "tcp"},
+ {Opt_acl, "acl"},
+ {Opt_noacl, "noacl"},
{Opt_err, NULL}
};
@@ -266,6 +269,12 @@ static int __init root_nfs_parse(char *name, char *buf)
case Opt_tcp:
nfs_data.flags |= NFS_MOUNT_TCP;
break;
+ case Opt_acl:
+ nfs_data.flags &= ~NFS_MOUNT_NOACL;
+ break;
+ case Opt_noacl:
+ nfs_data.flags |= NFS_MOUNT_NOACL;
+ break;
default :
return 0;
}
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index 4f1ba723848..d53857b148e 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -107,11 +107,38 @@ void nfs_unlock_request(struct nfs_page *req)
smp_mb__before_clear_bit();
clear_bit(PG_BUSY, &req->wb_flags);
smp_mb__after_clear_bit();
- wake_up_all(&req->wb_context->waitq);
+ wake_up_bit(&req->wb_flags, PG_BUSY);
nfs_release_request(req);
}
/**
+ * nfs_set_page_writeback_locked - Lock a request for writeback
+ * @req:
+ */
+int nfs_set_page_writeback_locked(struct nfs_page *req)
+{
+ struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode);
+
+ if (!nfs_lock_request(req))
+ return 0;
+ radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_WRITEBACK);
+ return 1;
+}
+
+/**
+ * nfs_clear_page_writeback - Unlock request and wake up sleepers
+ */
+void nfs_clear_page_writeback(struct nfs_page *req)
+{
+ struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode);
+
+ spin_lock(&nfsi->req_lock);
+ radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_WRITEBACK);
+ spin_unlock(&nfsi->req_lock);
+ nfs_unlock_request(req);
+}
+
+/**
* nfs_clear_request - Free up all resources allocated to the request
* @req:
*
@@ -150,34 +177,15 @@ nfs_release_request(struct nfs_page *req)
nfs_page_free(req);
}
-/**
- * nfs_list_add_request - Insert a request into a sorted list
- * @req: request
- * @head: head of list into which to insert the request.
- *
- * Note that the wb_list is sorted by page index in order to facilitate
- * coalescing of requests.
- * We use an insertion sort that is optimized for the case of appended
- * writes.
- */
-void
-nfs_list_add_request(struct nfs_page *req, struct list_head *head)
+static int nfs_wait_bit_interruptible(void *word)
{
- struct list_head *pos;
+ int ret = 0;
-#ifdef NFS_PARANOIA
- if (!list_empty(&req->wb_list)) {
- printk(KERN_ERR "NFS: Add to list failed!\n");
- BUG();
- }
-#endif
- list_for_each_prev(pos, head) {
- struct nfs_page *p = nfs_list_entry(pos);
- if (p->wb_index < req->wb_index)
- break;
- }
- list_add(&req->wb_list, pos);
- req->wb_list_head = head;
+ if (signal_pending(current))
+ ret = -ERESTARTSYS;
+ else
+ schedule();
+ return ret;
}
/**
@@ -190,12 +198,22 @@ nfs_list_add_request(struct nfs_page *req, struct list_head *head)
int
nfs_wait_on_request(struct nfs_page *req)
{
- struct inode *inode = req->wb_context->dentry->d_inode;
- struct rpc_clnt *clnt = NFS_CLIENT(inode);
-
- if (!NFS_WBACK_BUSY(req))
- return 0;
- return nfs_wait_event(clnt, req->wb_context->waitq, !NFS_WBACK_BUSY(req));
+ struct rpc_clnt *clnt = NFS_CLIENT(req->wb_context->dentry->d_inode);
+ sigset_t oldmask;
+ int ret = 0;
+
+ if (!test_bit(PG_BUSY, &req->wb_flags))
+ goto out;
+ /*
+ * Note: the call to rpc_clnt_sigmask() suffices to ensure that we
+ * are not interrupted if intr flag is not set
+ */
+ rpc_clnt_sigmask(clnt, &oldmask);
+ ret = out_of_line_wait_on_bit(&req->wb_flags, PG_BUSY,
+ nfs_wait_bit_interruptible, TASK_INTERRUPTIBLE);
+ rpc_clnt_sigunmask(clnt, &oldmask);
+out:
+ return ret;
}
/**
@@ -243,6 +261,62 @@ nfs_coalesce_requests(struct list_head *head, struct list_head *dst,
return npages;
}
+#define NFS_SCAN_MAXENTRIES 16
+/**
+ * nfs_scan_lock_dirty - Scan the radix tree for dirty requests
+ * @nfsi: NFS inode
+ * @dst: Destination list
+ * @idx_start: lower bound of page->index to scan
+ * @npages: idx_start + npages sets the upper bound to scan.
+ *
+ * Moves elements from one of the inode request lists.
+ * If the number of requests is set to 0, the entire address_space
+ * starting at index idx_start, is scanned.
+ * The requests are *not* checked to ensure that they form a contiguous set.
+ * You must be holding the inode's req_lock when calling this function
+ */
+int
+nfs_scan_lock_dirty(struct nfs_inode *nfsi, struct list_head *dst,
+ unsigned long idx_start, unsigned int npages)
+{
+ struct nfs_page *pgvec[NFS_SCAN_MAXENTRIES];
+ struct nfs_page *req;
+ unsigned long idx_end;
+ int found, i;
+ int res;
+
+ res = 0;
+ if (npages == 0)
+ idx_end = ~0;
+ else
+ idx_end = idx_start + npages - 1;
+
+ for (;;) {
+ found = radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree,
+ (void **)&pgvec[0], idx_start, NFS_SCAN_MAXENTRIES,
+ NFS_PAGE_TAG_DIRTY);
+ if (found <= 0)
+ break;
+ for (i = 0; i < found; i++) {
+ req = pgvec[i];
+ if (req->wb_index > idx_end)
+ goto out;
+
+ idx_start = req->wb_index + 1;
+
+ if (nfs_set_page_writeback_locked(req)) {
+ radix_tree_tag_clear(&nfsi->nfs_page_tree,
+ req->wb_index, NFS_PAGE_TAG_DIRTY);
+ nfs_list_remove_request(req);
+ nfs_list_add_request(req, dst);
+ res++;
+ }
+ }
+ }
+out:
+ return res;
+}
+
/**
* nfs_scan_list - Scan a list for matching requests
* @head: One of the NFS inode request lists
@@ -280,7 +354,7 @@ nfs_scan_list(struct list_head *head, struct list_head *dst,
if (req->wb_index > idx_end)
break;
- if (!nfs_lock_request(req))
+ if (!nfs_set_page_writeback_locked(req))
continue;
nfs_list_remove_request(req);
nfs_list_add_request(req, dst);
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index d31b4d6e5a5..cedf636bcf3 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -622,6 +622,7 @@ struct nfs_rpc_ops nfs_v2_clientops = {
.version = 2, /* protocol version */
.dentry_ops = &nfs_dentry_operations,
.dir_inode_ops = &nfs_dir_inode_operations,
+ .file_inode_ops = &nfs_file_inode_operations,
.getroot = nfs_proc_get_root,
.getattr = nfs_proc_getattr,
.setattr = nfs_proc_setattr,
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index a0042fb5863..6f866b8aa2d 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -173,7 +173,6 @@ static int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
if (len < PAGE_CACHE_SIZE)
memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len);
- nfs_lock_request(new);
nfs_list_add_request(new, &one_request);
nfs_pagein_one(&one_request, inode);
return 0;
@@ -185,7 +184,6 @@ static void nfs_readpage_release(struct nfs_page *req)
nfs_clear_request(req);
nfs_release_request(req);
- nfs_unlock_request(req);
dprintk("NFS: read done (%s/%Ld %d@%Ld)\n",
req->wb_context->dentry->d_inode->i_sb->s_id,
@@ -553,7 +551,6 @@ readpage_async_filler(void *data, struct page *page)
}
if (len < PAGE_CACHE_SIZE)
memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len);
- nfs_lock_request(new);
nfs_list_add_request(new, desc->head);
return 0;
}
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 6f7a4af3bc4..5130eda231d 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -220,7 +220,7 @@ static int nfs_writepage_sync(struct nfs_open_context *ctx, struct inode *inode,
ClearPageError(page);
io_error:
- nfs_end_data_update_defer(inode);
+ nfs_end_data_update(inode);
nfs_writedata_free(wdata);
return written ? written : result;
}
@@ -352,7 +352,7 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
if (err < 0)
goto out;
}
- err = nfs_commit_inode(inode, 0, 0, wb_priority(wbc));
+ err = nfs_commit_inode(inode, wb_priority(wbc));
if (err > 0) {
wbc->nr_to_write -= err;
err = 0;
@@ -401,7 +401,7 @@ static void nfs_inode_remove_request(struct nfs_page *req)
nfsi->npages--;
if (!nfsi->npages) {
spin_unlock(&nfsi->req_lock);
- nfs_end_data_update_defer(inode);
+ nfs_end_data_update(inode);
iput(inode);
} else
spin_unlock(&nfsi->req_lock);
@@ -446,6 +446,8 @@ nfs_mark_request_dirty(struct nfs_page *req)
struct nfs_inode *nfsi = NFS_I(inode);
spin_lock(&nfsi->req_lock);
+ radix_tree_tag_set(&nfsi->nfs_page_tree,
+ req->wb_index, NFS_PAGE_TAG_DIRTY);
nfs_list_add_request(req, &nfsi->dirty);
nfsi->ndirty++;
spin_unlock(&nfsi->req_lock);
@@ -503,13 +505,12 @@ nfs_wait_on_requests(struct inode *inode, unsigned long idx_start, unsigned int
spin_lock(&nfsi->req_lock);
next = idx_start;
- while (radix_tree_gang_lookup(&nfsi->nfs_page_tree, (void **)&req, next, 1)) {
+ while (radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree, (void **)&req, next, 1, NFS_PAGE_TAG_WRITEBACK)) {
if (req->wb_index > idx_end)
break;
next = req->wb_index + 1;
- if (!NFS_WBACK_BUSY(req))
- continue;
+ BUG_ON(!NFS_WBACK_BUSY(req));
atomic_inc(&req->wb_count);
spin_unlock(&nfsi->req_lock);
@@ -538,12 +539,15 @@ static int
nfs_scan_dirty(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages)
{
struct nfs_inode *nfsi = NFS_I(inode);
- int res;
- res = nfs_scan_list(&nfsi->dirty, dst, idx_start, npages);
- nfsi->ndirty -= res;
- sub_page_state(nr_dirty,res);
- if ((nfsi->ndirty == 0) != list_empty(&nfsi->dirty))
- printk(KERN_ERR "NFS: desynchronized value of nfs_i.ndirty.\n");
+ int res = 0;
+
+ if (nfsi->ndirty != 0) {
+ res = nfs_scan_lock_dirty(nfsi, dst, idx_start, npages);
+ nfsi->ndirty -= res;
+ sub_page_state(nr_dirty,res);
+ if ((nfsi->ndirty == 0) != list_empty(&nfsi->dirty))
+ printk(KERN_ERR "NFS: desynchronized value of nfs_i.ndirty.\n");
+ }
return res;
}
@@ -562,11 +566,14 @@ static int
nfs_scan_commit(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages)
{
struct nfs_inode *nfsi = NFS_I(inode);
- int res;
- res = nfs_scan_list(&nfsi->commit, dst, idx_start, npages);
- nfsi->ncommit -= res;
- if ((nfsi->ncommit == 0) != list_empty(&nfsi->commit))
- printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n");
+ int res = 0;
+
+ if (nfsi->ncommit != 0) {
+ res = nfs_scan_list(&nfsi->commit, dst, idx_start, npages);
+ nfsi->ncommit -= res;
+ if ((nfsi->ncommit == 0) != list_empty(&nfsi->commit))
+ printk(KERN_ERR "NFS: desynchronized value of nfs_i.ncommit.\n");
+ }
return res;
}
#endif
@@ -750,7 +757,7 @@ int nfs_updatepage(struct file *file, struct page *page,
* is entirely in cache, it may be more efficient to avoid
* fragmenting write requests.
*/
- if (PageUptodate(page) && inode->i_flock == NULL) {
+ if (PageUptodate(page) && inode->i_flock == NULL && !(file->f_mode & O_SYNC)) {
loff_t end_offs = i_size_read(inode) - 1;
unsigned long end_index = end_offs >> PAGE_CACHE_SHIFT;
@@ -821,7 +828,7 @@ out:
#else
nfs_inode_remove_request(req);
#endif
- nfs_unlock_request(req);
+ nfs_clear_page_writeback(req);
}
static inline int flush_task_priority(int how)
@@ -952,7 +959,7 @@ out_bad:
nfs_writedata_free(data);
}
nfs_mark_request_dirty(req);
- nfs_unlock_request(req);
+ nfs_clear_page_writeback(req);
return -ENOMEM;
}
@@ -1002,7 +1009,7 @@ static int nfs_flush_one(struct list_head *head, struct inode *inode, int how)
struct nfs_page *req = nfs_list_entry(head->next);
nfs_list_remove_request(req);
nfs_mark_request_dirty(req);
- nfs_unlock_request(req);
+ nfs_clear_page_writeback(req);
}
return -ENOMEM;
}
@@ -1029,7 +1036,7 @@ nfs_flush_list(struct list_head *head, int wpages, int how)
req = nfs_list_entry(head->next);
nfs_list_remove_request(req);
nfs_mark_request_dirty(req);
- nfs_unlock_request(req);
+ nfs_clear_page_writeback(req);
}
return error;
}
@@ -1121,7 +1128,7 @@ static void nfs_writeback_done_full(struct nfs_write_data *data, int status)
nfs_inode_remove_request(req);
#endif
next:
- nfs_unlock_request(req);
+ nfs_clear_page_writeback(req);
}
}
@@ -1210,36 +1217,24 @@ static void nfs_commit_rpcsetup(struct list_head *head,
struct nfs_write_data *data, int how)
{
struct rpc_task *task = &data->task;
- struct nfs_page *first, *last;
+ struct nfs_page *first;
struct inode *inode;
- loff_t start, end, len;
/* Set up the RPC argument and reply structs
* NB: take care not to mess about with data->commit et al. */
list_splice_init(head, &data->pages);
first = nfs_list_entry(data->pages.next);
- last = nfs_list_entry(data->pages.prev);
inode = first->wb_context->dentry->d_inode;
- /*
- * Determine the offset range of requests in the COMMIT call.
- * We rely on the fact that data->pages is an ordered list...
- */
- start = req_offset(first);
- end = req_offset(last) + last->wb_bytes;
- len = end - start;
- /* If 'len' is not a 32-bit quantity, pass '0' in the COMMIT call */
- if (end >= i_size_read(inode) || len < 0 || len > (~((u32)0) >> 1))
- len = 0;
-
data->inode = inode;
data->cred = first->wb_context->cred;
data->args.fh = NFS_FH(data->inode);
- data->args.offset = start;
- data->args.count = len;
- data->res.count = len;
+ /* Note: we always request a commit of the entire inode */
+ data->args.offset = 0;
+ data->args.count = 0;
+ data->res.count = 0;
data->res.fattr = &data->fattr;
data->res.verf = &data->verf;
@@ -1278,7 +1273,7 @@ nfs_commit_list(struct list_head *head, int how)
req = nfs_list_entry(head->next);
nfs_list_remove_request(req);
nfs_mark_request_commit(req);
- nfs_unlock_request(req);
+ nfs_clear_page_writeback(req);
}
return -ENOMEM;
}
@@ -1324,7 +1319,7 @@ nfs_commit_done(struct rpc_task *task)
dprintk(" mismatch\n");
nfs_mark_request_dirty(req);
next:
- nfs_unlock_request(req);
+ nfs_clear_page_writeback(req);
res++;
}
sub_page_state(nr_unstable,res);
@@ -1342,16 +1337,23 @@ static int nfs_flush_inode(struct inode *inode, unsigned long idx_start,
spin_lock(&nfsi->req_lock);
res = nfs_scan_dirty(inode, &head, idx_start, npages);
spin_unlock(&nfsi->req_lock);
- if (res)
- error = nfs_flush_list(&head, NFS_SERVER(inode)->wpages, how);
+ if (res) {
+ struct nfs_server *server = NFS_SERVER(inode);
+
+ /* For single writes, FLUSH_STABLE is more efficient */
+ if (res == nfsi->npages && nfsi->npages <= server->wpages) {
+ if (res > 1 || nfs_list_entry(head.next)->wb_bytes <= server->wsize)
+ how |= FLUSH_STABLE;
+ }
+ error = nfs_flush_list(&head, server->wpages, how);
+ }
if (error < 0)
return error;
return res;
}
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
-int nfs_commit_inode(struct inode *inode, unsigned long idx_start,
- unsigned int npages, int how)
+int nfs_commit_inode(struct inode *inode, int how)
{
struct nfs_inode *nfsi = NFS_I(inode);
LIST_HEAD(head);
@@ -1359,15 +1361,13 @@ int nfs_commit_inode(struct inode *inode, unsigned long idx_start,
error = 0;
spin_lock(&nfsi->req_lock);
- res = nfs_scan_commit(inode, &head, idx_start, npages);
+ res = nfs_scan_commit(inode, &head, 0, 0);
+ spin_unlock(&nfsi->req_lock);
if (res) {
- res += nfs_scan_commit(inode, &head, 0, 0);
- spin_unlock(&nfsi->req_lock);
error = nfs_commit_list(&head, how);
- } else
- spin_unlock(&nfsi->req_lock);
- if (error < 0)
- return error;
+ if (error < 0)
+ return error;
+ }
return res;
}
#endif
@@ -1389,7 +1389,7 @@ int nfs_sync_inode(struct inode *inode, unsigned long idx_start,
error = nfs_flush_inode(inode, idx_start, npages, how);
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
if (error == 0)
- error = nfs_commit_inode(inode, idx_start, npages, how);
+ error = nfs_commit_inode(inode, how);
#endif
} while (error > 0);
return error;
diff --git a/fs/nfs_common/Makefile b/fs/nfs_common/Makefile
new file mode 100644
index 00000000000..f689ed82af3
--- /dev/null
+++ b/fs/nfs_common/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for Linux filesystem routines that are shared by client and server.
+#
+
+obj-$(CONFIG_NFS_ACL_SUPPORT) += nfs_acl.o
+
+nfs_acl-objs := nfsacl.o
diff --git a/fs/nfs_common/nfsacl.c b/fs/nfs_common/nfsacl.c
new file mode 100644
index 00000000000..18c58c32e32
--- /dev/null
+++ b/fs/nfs_common/nfsacl.c
@@ -0,0 +1,257 @@
+/*
+ * fs/nfs_common/nfsacl.c
+ *
+ * Copyright (C) 2002-2003 Andreas Gruenbacher <agruen@suse.de>
+ */
+
+/*
+ * The Solaris nfsacl protocol represents some ACLs slightly differently
+ * than POSIX 1003.1e draft 17 does (and we do):
+ *
+ * - Minimal ACLs always have an ACL_MASK entry, so they have
+ * four instead of three entries.
+ * - The ACL_MASK entry in such minimal ACLs always has the same
+ * permissions as the ACL_GROUP_OBJ entry. (In extended ACLs
+ * the ACL_MASK and ACL_GROUP_OBJ entries may differ.)
+ * - The identifier fields of the ACL_USER_OBJ and ACL_GROUP_OBJ
+ * entries contain the identifiers of the owner and owning group.
+ * (In POSIX ACLs we always set them to ACL_UNDEFINED_ID).
+ * - ACL entries in the kernel are kept sorted in ascending order
+ * of (e_tag, e_id). Solaris ACLs are unsorted.
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/sunrpc/xdr.h>
+#include <linux/nfsacl.h>
+#include <linux/nfs3.h>
+#include <linux/sort.h>
+
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(nfsacl_encode);
+EXPORT_SYMBOL(nfsacl_decode);
+
+struct nfsacl_encode_desc {
+ struct xdr_array2_desc desc;
+ unsigned int count;
+ struct posix_acl *acl;
+ int typeflag;
+ uid_t uid;
+ gid_t gid;
+};
+
+static int
+xdr_nfsace_encode(struct xdr_array2_desc *desc, void *elem)
+{
+ struct nfsacl_encode_desc *nfsacl_desc =
+ (struct nfsacl_encode_desc *) desc;
+ u32 *p = (u32 *) elem;
+
+ if (nfsacl_desc->count < nfsacl_desc->acl->a_count) {
+ struct posix_acl_entry *entry =
+ &nfsacl_desc->acl->a_entries[nfsacl_desc->count++];
+
+ *p++ = htonl(entry->e_tag | nfsacl_desc->typeflag);
+ switch(entry->e_tag) {
+ case ACL_USER_OBJ:
+ *p++ = htonl(nfsacl_desc->uid);
+ break;
+ case ACL_GROUP_OBJ:
+ *p++ = htonl(nfsacl_desc->gid);
+ break;
+ case ACL_USER:
+ case ACL_GROUP:
+ *p++ = htonl(entry->e_id);
+ break;
+ default: /* Solaris depends on that! */
+ *p++ = 0;
+ break;
+ }
+ *p++ = htonl(entry->e_perm & S_IRWXO);
+ } else {
+ const struct posix_acl_entry *pa, *pe;
+ int group_obj_perm = ACL_READ|ACL_WRITE|ACL_EXECUTE;
+
+ FOREACH_ACL_ENTRY(pa, nfsacl_desc->acl, pe) {
+ if (pa->e_tag == ACL_GROUP_OBJ) {
+ group_obj_perm = pa->e_perm & S_IRWXO;
+ break;
+ }
+ }
+ /* fake up ACL_MASK entry */
+ *p++ = htonl(ACL_MASK | nfsacl_desc->typeflag);
+ *p++ = htonl(0);
+ *p++ = htonl(group_obj_perm);
+ }
+
+ return 0;
+}
+
+unsigned int
+nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode,
+ struct posix_acl *acl, int encode_entries, int typeflag)
+{
+ int entries = (acl && acl->a_count) ? max_t(int, acl->a_count, 4) : 0;
+ struct nfsacl_encode_desc nfsacl_desc = {
+ .desc = {
+ .elem_size = 12,
+ .array_len = encode_entries ? entries : 0,
+ .xcode = xdr_nfsace_encode,
+ },
+ .acl = acl,
+ .typeflag = typeflag,
+ .uid = inode->i_uid,
+ .gid = inode->i_gid,
+ };
+ int err;
+
+ if (entries > NFS_ACL_MAX_ENTRIES ||
+ xdr_encode_word(buf, base, entries))
+ return -EINVAL;
+ err = xdr_encode_array2(buf, base + 4, &nfsacl_desc.desc);
+ if (!err)
+ err = 8 + nfsacl_desc.desc.elem_size *
+ nfsacl_desc.desc.array_len;
+ return err;
+}
+
+struct nfsacl_decode_desc {
+ struct xdr_array2_desc desc;
+ unsigned int count;
+ struct posix_acl *acl;
+};
+
+static int
+xdr_nfsace_decode(struct xdr_array2_desc *desc, void *elem)
+{
+ struct nfsacl_decode_desc *nfsacl_desc =
+ (struct nfsacl_decode_desc *) desc;
+ u32 *p = (u32 *) elem;
+ struct posix_acl_entry *entry;
+
+ if (!nfsacl_desc->acl) {
+ if (desc->array_len > NFS_ACL_MAX_ENTRIES)
+ return -EINVAL;
+ nfsacl_desc->acl = posix_acl_alloc(desc->array_len, GFP_KERNEL);
+ if (!nfsacl_desc->acl)
+ return -ENOMEM;
+ nfsacl_desc->count = 0;
+ }
+
+ entry = &nfsacl_desc->acl->a_entries[nfsacl_desc->count++];
+ entry->e_tag = ntohl(*p++) & ~NFS_ACL_DEFAULT;
+ entry->e_id = ntohl(*p++);
+ entry->e_perm = ntohl(*p++);
+
+ switch(entry->e_tag) {
+ case ACL_USER_OBJ:
+ case ACL_USER:
+ case ACL_GROUP_OBJ:
+ case ACL_GROUP:
+ case ACL_OTHER:
+ if (entry->e_perm & ~S_IRWXO)
+ return -EINVAL;
+ break;
+ case ACL_MASK:
+ /* Solaris sometimes sets additonal bits in the mask */
+ entry->e_perm &= S_IRWXO;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
+cmp_acl_entry(const void *x, const void *y)
+{
+ const struct posix_acl_entry *a = x, *b = y;
+
+ if (a->e_tag != b->e_tag)
+ return a->e_tag - b->e_tag;
+ else if (a->e_id > b->e_id)
+ return 1;
+ else if (a->e_id < b->e_id)
+ return -1;
+ else
+ return 0;
+}
+
+/*
+ * Convert from a Solaris ACL to a POSIX 1003.1e draft 17 ACL.
+ */
+static int
+posix_acl_from_nfsacl(struct posix_acl *acl)
+{
+ struct posix_acl_entry *pa, *pe,
+ *group_obj = NULL, *mask = NULL;
+
+ if (!acl)
+ return 0;
+
+ sort(acl->a_entries, acl->a_count, sizeof(struct posix_acl_entry),
+ cmp_acl_entry, NULL);
+
+ /* Clear undefined identifier fields and find the ACL_GROUP_OBJ
+ and ACL_MASK entries. */
+ FOREACH_ACL_ENTRY(pa, acl, pe) {
+ switch(pa->e_tag) {
+ case ACL_USER_OBJ:
+ pa->e_id = ACL_UNDEFINED_ID;
+ break;
+ case ACL_GROUP_OBJ:
+ pa->e_id = ACL_UNDEFINED_ID;
+ group_obj = pa;
+ break;
+ case ACL_MASK:
+ mask = pa;
+ /* fall through */
+ case ACL_OTHER:
+ pa->e_id = ACL_UNDEFINED_ID;
+ break;
+ }
+ }
+ if (acl->a_count == 4 && group_obj && mask &&
+ mask->e_perm == group_obj->e_perm) {
+ /* remove bogus ACL_MASK entry */
+ memmove(mask, mask+1, (3 - (mask - acl->a_entries)) *
+ sizeof(struct posix_acl_entry));
+ acl->a_count = 3;
+ }
+ return 0;
+}
+
+unsigned int
+nfsacl_decode(struct xdr_buf *buf, unsigned int base, unsigned int *aclcnt,
+ struct posix_acl **pacl)
+{
+ struct nfsacl_decode_desc nfsacl_desc = {
+ .desc = {
+ .elem_size = 12,
+ .xcode = pacl ? xdr_nfsace_decode : NULL,
+ },
+ };
+ u32 entries;
+ int err;
+
+ if (xdr_decode_word(buf, base, &entries) ||
+ entries > NFS_ACL_MAX_ENTRIES)
+ return -EINVAL;
+ err = xdr_decode_array2(buf, base + 4, &nfsacl_desc.desc);
+ if (err)
+ return err;
+ if (pacl) {
+ if (entries != nfsacl_desc.desc.array_len ||
+ posix_acl_from_nfsacl(nfsacl_desc.acl) != 0) {
+ posix_acl_release(nfsacl_desc.acl);
+ return -EINVAL;
+ }
+ *pacl = nfsacl_desc.acl;
+ }
+ if (aclcnt)
+ *aclcnt = entries;
+ return 8 + nfsacl_desc.desc.elem_size *
+ nfsacl_desc.desc.array_len;
+}
diff --git a/fs/nfsd/Makefile b/fs/nfsd/Makefile
index b8680a247f8..ce341dc76d5 100644
--- a/fs/nfsd/Makefile
+++ b/fs/nfsd/Makefile
@@ -6,7 +6,9 @@ obj-$(CONFIG_NFSD) += nfsd.o
nfsd-y := nfssvc.o nfsctl.o nfsproc.o nfsfh.o vfs.o \
export.o auth.o lockd.o nfscache.o nfsxdr.o stats.o
+nfsd-$(CONFIG_NFSD_V2_ACL) += nfs2acl.o
nfsd-$(CONFIG_NFSD_V3) += nfs3proc.o nfs3xdr.o
+nfsd-$(CONFIG_NFSD_V3_ACL) += nfs3acl.o
nfsd-$(CONFIG_NFSD_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o \
- nfs4acl.o nfs4callback.o
+ nfs4acl.o nfs4callback.o nfs4recover.o
nfsd-objs := $(nfsd-y)
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
new file mode 100644
index 00000000000..7cbf0682b2f
--- /dev/null
+++ b/fs/nfsd/nfs2acl.c
@@ -0,0 +1,336 @@
+/*
+ * linux/fs/nfsd/nfsacl.c
+ *
+ * Process version 2 NFSACL requests.
+ *
+ * Copyright (C) 2002-2003 Andreas Gruenbacher <agruen@suse.de>
+ */
+
+#include <linux/sunrpc/svc.h>
+#include <linux/nfs.h>
+#include <linux/nfsd/nfsd.h>
+#include <linux/nfsd/cache.h>
+#include <linux/nfsd/xdr.h>
+#include <linux/nfsd/xdr3.h>
+#include <linux/posix_acl.h>
+#include <linux/nfsacl.h>
+
+#define NFSDDBG_FACILITY NFSDDBG_PROC
+#define RETURN_STATUS(st) { resp->status = (st); return (st); }
+
+/*
+ * NULL call.
+ */
+static int
+nfsacld_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
+{
+ return nfs_ok;
+}
+
+/*
+ * Get the Access and/or Default ACL of a file.
+ */
+static int nfsacld_proc_getacl(struct svc_rqst * rqstp,
+ struct nfsd3_getaclargs *argp, struct nfsd3_getaclres *resp)
+{
+ svc_fh *fh;
+ struct posix_acl *acl;
+ int nfserr = 0;
+
+ dprintk("nfsd: GETACL(2acl) %s\n", SVCFH_fmt(&argp->fh));
+
+ fh = fh_copy(&resp->fh, &argp->fh);
+ if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP)))
+ RETURN_STATUS(nfserr_inval);
+
+ if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
+ RETURN_STATUS(nfserr_inval);
+ resp->mask = argp->mask;
+
+ if (resp->mask & (NFS_ACL|NFS_ACLCNT)) {
+ acl = nfsd_get_posix_acl(fh, ACL_TYPE_ACCESS);
+ if (IS_ERR(acl)) {
+ int err = PTR_ERR(acl);
+
+ if (err == -ENODATA || err == -EOPNOTSUPP)
+ acl = NULL;
+ else {
+ nfserr = nfserrno(err);
+ goto fail;
+ }
+ }
+ if (acl == NULL) {
+ /* Solaris returns the inode's minimum ACL. */
+
+ struct inode *inode = fh->fh_dentry->d_inode;
+ acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
+ }
+ resp->acl_access = acl;
+ }
+ if (resp->mask & (NFS_DFACL|NFS_DFACLCNT)) {
+ /* Check how Solaris handles requests for the Default ACL
+ of a non-directory! */
+
+ acl = nfsd_get_posix_acl(fh, ACL_TYPE_DEFAULT);
+ if (IS_ERR(acl)) {
+ int err = PTR_ERR(acl);
+
+ if (err == -ENODATA || err == -EOPNOTSUPP)
+ acl = NULL;
+ else {
+ nfserr = nfserrno(err);
+ goto fail;
+ }
+ }
+ resp->acl_default = acl;
+ }
+
+ /* resp->acl_{access,default} are released in nfssvc_release_getacl. */
+ RETURN_STATUS(0);
+
+fail:
+ posix_acl_release(resp->acl_access);
+ posix_acl_release(resp->acl_default);
+ RETURN_STATUS(nfserr);
+}
+
+/*
+ * Set the Access and/or Default ACL of a file.
+ */
+static int nfsacld_proc_setacl(struct svc_rqst * rqstp,
+ struct nfsd3_setaclargs *argp,
+ struct nfsd_attrstat *resp)
+{
+ svc_fh *fh;
+ int nfserr = 0;
+
+ dprintk("nfsd: SETACL(2acl) %s\n", SVCFH_fmt(&argp->fh));
+
+ fh = fh_copy(&resp->fh, &argp->fh);
+ nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
+
+ if (!nfserr) {
+ nfserr = nfserrno( nfsd_set_posix_acl(
+ fh, ACL_TYPE_ACCESS, argp->acl_access) );
+ }
+ if (!nfserr) {
+ nfserr = nfserrno( nfsd_set_posix_acl(
+ fh, ACL_TYPE_DEFAULT, argp->acl_default) );
+ }
+
+ /* argp->acl_{access,default} may have been allocated in
+ nfssvc_decode_setaclargs. */
+ posix_acl_release(argp->acl_access);
+ posix_acl_release(argp->acl_default);
+ return nfserr;
+}
+
+/*
+ * Check file attributes
+ */
+static int nfsacld_proc_getattr(struct svc_rqst * rqstp,
+ struct nfsd_fhandle *argp, struct nfsd_attrstat *resp)
+{
+ dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh));
+
+ fh_copy(&resp->fh, &argp->fh);
+ return fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
+}
+
+/*
+ * Check file access
+ */
+static int nfsacld_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessargs *argp,
+ struct nfsd3_accessres *resp)
+{
+ int nfserr;
+
+ dprintk("nfsd: ACCESS(2acl) %s 0x%x\n",
+ SVCFH_fmt(&argp->fh),
+ argp->access);
+
+ fh_copy(&resp->fh, &argp->fh);
+ resp->access = argp->access;
+ nfserr = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
+ return nfserr;
+}
+
+/*
+ * XDR decode functions
+ */
+static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_getaclargs *argp)
+{
+ if (!(p = nfs2svc_decode_fh(p, &argp->fh)))
+ return 0;
+ argp->mask = ntohl(*p); p++;
+
+ return xdr_argsize_check(rqstp, p);
+}
+
+
+static int nfsaclsvc_decode_setaclargs(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_setaclargs *argp)
+{
+ struct kvec *head = rqstp->rq_arg.head;
+ unsigned int base;
+ int n;
+
+ if (!(p = nfs2svc_decode_fh(p, &argp->fh)))
+ return 0;
+ argp->mask = ntohl(*p++);
+ if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT) ||
+ !xdr_argsize_check(rqstp, p))
+ return 0;
+
+ base = (char *)p - (char *)head->iov_base;
+ n = nfsacl_decode(&rqstp->rq_arg, base, NULL,
+ (argp->mask & NFS_ACL) ?
+ &argp->acl_access : NULL);
+ if (n > 0)
+ n = nfsacl_decode(&rqstp->rq_arg, base + n, NULL,
+ (argp->mask & NFS_DFACL) ?
+ &argp->acl_default : NULL);
+ return (n > 0);
+}
+
+static int nfsaclsvc_decode_fhandleargs(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd_fhandle *argp)
+{
+ if (!(p = nfs2svc_decode_fh(p, &argp->fh)))
+ return 0;
+ return xdr_argsize_check(rqstp, p);
+}
+
+static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_accessargs *argp)
+{
+ if (!(p = nfs2svc_decode_fh(p, &argp->fh)))
+ return 0;
+ argp->access = ntohl(*p++);
+
+ return xdr_argsize_check(rqstp, p);
+}
+
+/*
+ * XDR encode functions
+ */
+
+/* GETACL */
+static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_getaclres *resp)
+{
+ struct dentry *dentry = resp->fh.fh_dentry;
+ struct inode *inode = dentry->d_inode;
+ int w = nfsacl_size(
+ (resp->mask & NFS_ACL) ? resp->acl_access : NULL,
+ (resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
+ struct kvec *head = rqstp->rq_res.head;
+ unsigned int base;
+ int n;
+
+ if (dentry == NULL || dentry->d_inode == NULL)
+ return 0;
+ inode = dentry->d_inode;
+
+ p = nfs2svc_encode_fattr(rqstp, p, &resp->fh);
+ *p++ = htonl(resp->mask);
+ if (!xdr_ressize_check(rqstp, p))
+ return 0;
+ base = (char *)p - (char *)head->iov_base;
+
+ rqstp->rq_res.page_len = w;
+ while (w > 0) {
+ if (!svc_take_res_page(rqstp))
+ return 0;
+ w -= PAGE_SIZE;
+ }
+
+ n = nfsacl_encode(&rqstp->rq_res, base, inode,
+ resp->acl_access,
+ resp->mask & NFS_ACL, 0);
+ if (n > 0)
+ n = nfsacl_encode(&rqstp->rq_res, base + n, inode,
+ resp->acl_default,
+ resp->mask & NFS_DFACL,
+ NFS_ACL_DEFAULT);
+ if (n <= 0)
+ return 0;
+ return 1;
+}
+
+static int nfsaclsvc_encode_attrstatres(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd_attrstat *resp)
+{
+ p = nfs2svc_encode_fattr(rqstp, p, &resp->fh);
+ return xdr_ressize_check(rqstp, p);
+}
+
+/* ACCESS */
+static int nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_accessres *resp)
+{
+ p = nfs2svc_encode_fattr(rqstp, p, &resp->fh);
+ *p++ = htonl(resp->access);
+ return xdr_ressize_check(rqstp, p);
+}
+
+/*
+ * XDR release functions
+ */
+static int nfsaclsvc_release_getacl(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_getaclres *resp)
+{
+ fh_put(&resp->fh);
+ posix_acl_release(resp->acl_access);
+ posix_acl_release(resp->acl_default);
+ return 1;
+}
+
+static int nfsaclsvc_release_fhandle(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd_fhandle *resp)
+{
+ fh_put(&resp->fh);
+ return 1;
+}
+
+#define nfsaclsvc_decode_voidargs NULL
+#define nfsaclsvc_encode_voidres NULL
+#define nfsaclsvc_release_void NULL
+#define nfsd3_fhandleargs nfsd_fhandle
+#define nfsd3_attrstatres nfsd_attrstat
+#define nfsd3_voidres nfsd3_voidargs
+struct nfsd3_voidargs { int dummy; };
+
+#define PROC(name, argt, rest, relt, cache, respsize) \
+ { (svc_procfunc) nfsacld_proc_##name, \
+ (kxdrproc_t) nfsaclsvc_decode_##argt##args, \
+ (kxdrproc_t) nfsaclsvc_encode_##rest##res, \
+ (kxdrproc_t) nfsaclsvc_release_##relt, \
+ sizeof(struct nfsd3_##argt##args), \
+ sizeof(struct nfsd3_##rest##res), \
+ 0, \
+ cache, \
+ respsize, \
+ }
+
+#define ST 1 /* status*/
+#define AT 21 /* attributes */
+#define pAT (1+AT) /* post attributes - conditional */
+#define ACL (1+NFS_ACL_MAX_ENTRIES*3) /* Access Control List */
+
+static struct svc_procedure nfsd_acl_procedures2[] = {
+ PROC(null, void, void, void, RC_NOCACHE, ST),
+ PROC(getacl, getacl, getacl, getacl, RC_NOCACHE, ST+1+2*(1+ACL)),
+ PROC(setacl, setacl, attrstat, fhandle, RC_NOCACHE, ST+AT),
+ PROC(getattr, fhandle, attrstat, fhandle, RC_NOCACHE, ST+AT),
+ PROC(access, access, access, fhandle, RC_NOCACHE, ST+AT+1),
+};
+
+struct svc_version nfsd_acl_version2 = {
+ .vs_vers = 2,
+ .vs_nproc = 5,
+ .vs_proc = nfsd_acl_procedures2,
+ .vs_dispatch = nfsd_dispatch,
+ .vs_xdrsize = NFS3_SVC_XDRSIZE,
+};
diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c
new file mode 100644
index 00000000000..64ba40572fe
--- /dev/null
+++ b/fs/nfsd/nfs3acl.c
@@ -0,0 +1,267 @@
+/*
+ * linux/fs/nfsd/nfs3acl.c
+ *
+ * Process version 3 NFSACL requests.
+ *
+ * Copyright (C) 2002-2003 Andreas Gruenbacher <agruen@suse.de>
+ */
+
+#include <linux/sunrpc/svc.h>
+#include <linux/nfs3.h>
+#include <linux/nfsd/nfsd.h>
+#include <linux/nfsd/cache.h>
+#include <linux/nfsd/xdr3.h>
+#include <linux/posix_acl.h>
+#include <linux/nfsacl.h>
+
+#define RETURN_STATUS(st) { resp->status = (st); return (st); }
+
+/*
+ * NULL call.
+ */
+static int
+nfsd3_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
+{
+ return nfs_ok;
+}
+
+/*
+ * Get the Access and/or Default ACL of a file.
+ */
+static int nfsd3_proc_getacl(struct svc_rqst * rqstp,
+ struct nfsd3_getaclargs *argp, struct nfsd3_getaclres *resp)
+{
+ svc_fh *fh;
+ struct posix_acl *acl;
+ int nfserr = 0;
+
+ fh = fh_copy(&resp->fh, &argp->fh);
+ if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP)))
+ RETURN_STATUS(nfserr_inval);
+
+ if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
+ RETURN_STATUS(nfserr_inval);
+ resp->mask = argp->mask;
+
+ if (resp->mask & (NFS_ACL|NFS_ACLCNT)) {
+ acl = nfsd_get_posix_acl(fh, ACL_TYPE_ACCESS);
+ if (IS_ERR(acl)) {
+ int err = PTR_ERR(acl);
+
+ if (err == -ENODATA || err == -EOPNOTSUPP)
+ acl = NULL;
+ else {
+ nfserr = nfserrno(err);
+ goto fail;
+ }
+ }
+ if (acl == NULL) {
+ /* Solaris returns the inode's minimum ACL. */
+
+ struct inode *inode = fh->fh_dentry->d_inode;
+ acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
+ }
+ resp->acl_access = acl;
+ }
+ if (resp->mask & (NFS_DFACL|NFS_DFACLCNT)) {
+ /* Check how Solaris handles requests for the Default ACL
+ of a non-directory! */
+
+ acl = nfsd_get_posix_acl(fh, ACL_TYPE_DEFAULT);
+ if (IS_ERR(acl)) {
+ int err = PTR_ERR(acl);
+
+ if (err == -ENODATA || err == -EOPNOTSUPP)
+ acl = NULL;
+ else {
+ nfserr = nfserrno(err);
+ goto fail;
+ }
+ }
+ resp->acl_default = acl;
+ }
+
+ /* resp->acl_{access,default} are released in nfs3svc_release_getacl. */
+ RETURN_STATUS(0);
+
+fail:
+ posix_acl_release(resp->acl_access);
+ posix_acl_release(resp->acl_default);
+ RETURN_STATUS(nfserr);
+}
+
+/*
+ * Set the Access and/or Default ACL of a file.
+ */
+static int nfsd3_proc_setacl(struct svc_rqst * rqstp,
+ struct nfsd3_setaclargs *argp,
+ struct nfsd3_attrstat *resp)
+{
+ svc_fh *fh;
+ int nfserr = 0;
+
+ fh = fh_copy(&resp->fh, &argp->fh);
+ nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
+
+ if (!nfserr) {
+ nfserr = nfserrno( nfsd_set_posix_acl(
+ fh, ACL_TYPE_ACCESS, argp->acl_access) );
+ }
+ if (!nfserr) {
+ nfserr = nfserrno( nfsd_set_posix_acl(
+ fh, ACL_TYPE_DEFAULT, argp->acl_default) );
+ }
+
+ /* argp->acl_{access,default} may have been allocated in
+ nfs3svc_decode_setaclargs. */
+ posix_acl_release(argp->acl_access);
+ posix_acl_release(argp->acl_default);
+ RETURN_STATUS(nfserr);
+}
+
+/*
+ * XDR decode functions
+ */
+static int nfs3svc_decode_getaclargs(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_getaclargs *args)
+{
+ if (!(p = nfs3svc_decode_fh(p, &args->fh)))
+ return 0;
+ args->mask = ntohl(*p); p++;
+
+ return xdr_argsize_check(rqstp, p);
+}
+
+
+static int nfs3svc_decode_setaclargs(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_setaclargs *args)
+{
+ struct kvec *head = rqstp->rq_arg.head;
+ unsigned int base;
+ int n;
+
+ if (!(p = nfs3svc_decode_fh(p, &args->fh)))
+ return 0;
+ args->mask = ntohl(*p++);
+ if (args->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT) ||
+ !xdr_argsize_check(rqstp, p))
+ return 0;
+
+ base = (char *)p - (char *)head->iov_base;
+ n = nfsacl_decode(&rqstp->rq_arg, base, NULL,
+ (args->mask & NFS_ACL) ?
+ &args->acl_access : NULL);
+ if (n > 0)
+ n = nfsacl_decode(&rqstp->rq_arg, base + n, NULL,
+ (args->mask & NFS_DFACL) ?
+ &args->acl_default : NULL);
+ return (n > 0);
+}
+
+/*
+ * XDR encode functions
+ */
+
+/* GETACL */
+static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_getaclres *resp)
+{
+ struct dentry *dentry = resp->fh.fh_dentry;
+
+ p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh);
+ if (resp->status == 0 && dentry && dentry->d_inode) {
+ struct inode *inode = dentry->d_inode;
+ int w = nfsacl_size(
+ (resp->mask & NFS_ACL) ? resp->acl_access : NULL,
+ (resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
+ struct kvec *head = rqstp->rq_res.head;
+ unsigned int base;
+ int n;
+
+ *p++ = htonl(resp->mask);
+ if (!xdr_ressize_check(rqstp, p))
+ return 0;
+ base = (char *)p - (char *)head->iov_base;
+
+ rqstp->rq_res.page_len = w;
+ while (w > 0) {
+ if (!svc_take_res_page(rqstp))
+ return 0;
+ w -= PAGE_SIZE;
+ }
+
+ n = nfsacl_encode(&rqstp->rq_res, base, inode,
+ resp->acl_access,
+ resp->mask & NFS_ACL, 0);
+ if (n > 0)
+ n = nfsacl_encode(&rqstp->rq_res, base + n, inode,
+ resp->acl_default,
+ resp->mask & NFS_DFACL,
+ NFS_ACL_DEFAULT);
+ if (n <= 0)
+ return 0;
+ } else
+ if (!xdr_ressize_check(rqstp, p))
+ return 0;
+
+ return 1;
+}
+
+/* SETACL */
+static int nfs3svc_encode_setaclres(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_attrstat *resp)
+{
+ p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh);
+
+ return xdr_ressize_check(rqstp, p);
+}
+
+/*
+ * XDR release functions
+ */
+static int nfs3svc_release_getacl(struct svc_rqst *rqstp, u32 *p,
+ struct nfsd3_getaclres *resp)
+{
+ fh_put(&resp->fh);
+ posix_acl_release(resp->acl_access);
+ posix_acl_release(resp->acl_default);
+ return 1;
+}
+
+#define nfs3svc_decode_voidargs NULL
+#define nfs3svc_release_void NULL
+#define nfsd3_setaclres nfsd3_attrstat
+#define nfsd3_voidres nfsd3_voidargs
+struct nfsd3_voidargs { int dummy; };
+
+#define PROC(name, argt, rest, relt, cache, respsize) \
+ { (svc_procfunc) nfsd3_proc_##name, \
+ (kxdrproc_t) nfs3svc_decode_##argt##args, \
+ (kxdrproc_t) nfs3svc_encode_##rest##res, \
+ (kxdrproc_t) nfs3svc_release_##relt, \
+ sizeof(struct nfsd3_##argt##args), \
+ sizeof(struct nfsd3_##rest##res), \
+ 0, \
+ cache, \
+ respsize, \
+ }
+
+#define ST 1 /* status*/
+#define AT 21 /* attributes */
+#define pAT (1+AT) /* post attributes - conditional */
+#define ACL (1+NFS_ACL_MAX_ENTRIES*3) /* Access Control List */
+
+static struct svc_procedure nfsd_acl_procedures3[] = {
+ PROC(null, void, void, void, RC_NOCACHE, ST),
+ PROC(getacl, getacl, getacl, getacl, RC_NOCACHE, ST+1+2*(1+ACL)),
+ PROC(setacl, setacl, setacl, fhandle, RC_NOCACHE, ST+pAT),
+};
+
+struct svc_version nfsd_acl_version3 = {
+ .vs_vers = 3,
+ .vs_nproc = 3,
+ .vs_proc = nfsd_acl_procedures3,
+ .vs_dispatch = nfsd_dispatch,
+ .vs_xdrsize = NFS3_SVC_XDRSIZE,
+};
+
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 11f806835c5..e0e134d6bab 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -71,6 +71,12 @@ decode_fh(u32 *p, struct svc_fh *fhp)
return p + XDR_QUADLEN(size);
}
+/* Helper function for NFSv3 ACL code */
+u32 *nfs3svc_decode_fh(u32 *p, struct svc_fh *fhp)
+{
+ return decode_fh(p, fhp);
+}
+
static inline u32 *
encode_fh(u32 *p, struct svc_fh *fhp)
{
@@ -233,6 +239,13 @@ encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
return p;
}
+/* Helper for NFSv3 ACLs */
+u32 *
+nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
+{
+ return encode_post_op_attr(rqstp, p, fhp);
+}
+
/*
* Enocde weak cache consistency data
*/
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 11ebf6c4aa5..4a2105552ac 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -125,7 +125,7 @@ static short ace2type(struct nfs4_ace *);
static int _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, unsigned int);
static struct posix_acl *_nfsv4_to_posix_one(struct nfs4_acl *, unsigned int);
int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
-int nfs4_acl_split(struct nfs4_acl *, struct nfs4_acl *);
+static int nfs4_acl_split(struct nfs4_acl *, struct nfs4_acl *);
struct nfs4_acl *
nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl,
@@ -775,7 +775,7 @@ out_err:
return pacl;
}
-int
+static int
nfs4_acl_split(struct nfs4_acl *acl, struct nfs4_acl *dacl)
{
struct list_head *h, *n;
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 1a55dfcb74b..583c0710e45 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -54,7 +54,6 @@
/* declarations */
static void nfs4_cb_null(struct rpc_task *task);
-extern spinlock_t recall_lock;
/* Index of predefined Linux callback client operations */
@@ -329,12 +328,12 @@ out:
.p_bufsiz = MAX(NFS4_##argtype##_sz,NFS4_##restype##_sz) << 2, \
}
-struct rpc_procinfo nfs4_cb_procedures[] = {
+static struct rpc_procinfo nfs4_cb_procedures[] = {
PROC(CB_NULL, NULL, enc_cb_null, dec_cb_null),
PROC(CB_RECALL, COMPOUND, enc_cb_recall, dec_cb_recall),
};
-struct rpc_version nfs_cb_version4 = {
+static struct rpc_version nfs_cb_version4 = {
.number = 1,
.nrprocs = sizeof(nfs4_cb_procedures)/sizeof(nfs4_cb_procedures[0]),
.procs = nfs4_cb_procedures
@@ -348,7 +347,7 @@ static struct rpc_version * nfs_cb_version[] = {
/*
* Use the SETCLIENTID credential
*/
-struct rpc_cred *
+static struct rpc_cred *
nfsd4_lookupcred(struct nfs4_client *clp, int taskflags)
{
struct auth_cred acred;
@@ -387,9 +386,7 @@ nfsd4_probe_callback(struct nfs4_client *clp)
char hostname[32];
int status;
- dprintk("NFSD: probe_callback. cb_parsed %d cb_set %d\n",
- cb->cb_parsed, atomic_read(&cb->cb_set));
- if (!cb->cb_parsed || atomic_read(&cb->cb_set))
+ if (atomic_read(&cb->cb_set))
return;
/* Initialize address */
@@ -427,10 +424,10 @@ nfsd4_probe_callback(struct nfs4_client *clp)
* XXX AUTH_UNIX only - need AUTH_GSS....
*/
sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(addr.sin_addr.s_addr));
- clnt = rpc_create_client(xprt, hostname, program, 1, RPC_AUTH_UNIX);
+ clnt = rpc_new_client(xprt, hostname, program, 1, RPC_AUTH_UNIX);
if (IS_ERR(clnt)) {
dprintk("NFSD: couldn't create callback client\n");
- goto out_xprt;
+ goto out_err;
}
clnt->cl_intr = 0;
clnt->cl_softrtry = 1;
@@ -465,8 +462,6 @@ out_rpciod:
out_clnt:
rpc_shutdown_client(clnt);
goto out_err;
-out_xprt:
- xprt_destroy(xprt);
out_err:
dprintk("NFSD: warning: no callback path to client %.*s\n",
(int)clp->cl_name.len, clp->cl_name.data);
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
index 4ba540841cf..5605a26efc5 100644
--- a/fs/nfsd/nfs4idmap.c
+++ b/fs/nfsd/nfs4idmap.c
@@ -104,7 +104,7 @@ ent_update(struct ent *new, struct ent *itm)
ent_init(new, itm);
}
-void
+static void
ent_put(struct cache_head *ch, struct cache_detail *cd)
{
if (cache_put(ch, cd)) {
@@ -186,7 +186,7 @@ warn_no_idmapd(struct cache_detail *detail)
static int idtoname_parse(struct cache_detail *, char *, int);
static struct ent *idtoname_lookup(struct ent *, int);
-struct cache_detail idtoname_cache = {
+static struct cache_detail idtoname_cache = {
.hash_size = ENT_HASHMAX,
.hash_table = idtoname_table,
.name = "nfs4.idtoname",
@@ -277,7 +277,7 @@ nametoid_hash(struct ent *ent)
return hash_str(ent->name, ENT_HASHBITS);
}
-void
+static void
nametoid_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
int *blen)
{
@@ -317,9 +317,9 @@ nametoid_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
}
static struct ent *nametoid_lookup(struct ent *, int);
-int nametoid_parse(struct cache_detail *, char *, int);
+static int nametoid_parse(struct cache_detail *, char *, int);
-struct cache_detail nametoid_cache = {
+static struct cache_detail nametoid_cache = {
.hash_size = ENT_HASHMAX,
.hash_table = nametoid_table,
.name = "nfs4.nametoid",
@@ -330,7 +330,7 @@ struct cache_detail nametoid_cache = {
.warn_no_listener = warn_no_idmapd,
};
-int
+static int
nametoid_parse(struct cache_detail *cd, char *buf, int buflen)
{
struct ent ent, *res;
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index e8158741e8b..d71f14517b9 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -45,6 +45,7 @@
#include <linux/param.h>
#include <linux/major.h>
#include <linux/slab.h>
+#include <linux/file.h>
#include <linux/sunrpc/svc.h>
#include <linux/nfsd/nfsd.h>
@@ -198,6 +199,11 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
if (status)
goto out;
switch (open->op_claim_type) {
+ case NFS4_OPEN_CLAIM_DELEGATE_CUR:
+ status = nfserr_inval;
+ if (open->op_create)
+ goto out;
+ /* fall through */
case NFS4_OPEN_CLAIM_NULL:
/*
* (1) set CURRENT_FH to the file being opened,
@@ -220,7 +226,6 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open
if (status)
goto out;
break;
- case NFS4_OPEN_CLAIM_DELEGATE_CUR:
case NFS4_OPEN_CLAIM_DELEGATE_PREV:
printk("NFSD: unsupported OPEN claim type %d\n",
open->op_claim_type);
@@ -473,26 +478,27 @@ static inline int
nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read)
{
int status;
- struct file *filp = NULL;
/* no need to check permission - this will be done in nfsd_read() */
+ read->rd_filp = NULL;
if (read->rd_offset >= OFFSET_MAX)
return nfserr_inval;
nfs4_lock_state();
/* check stateid */
if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid,
- CHECK_FH | RD_STATE, &filp))) {
+ CHECK_FH | RD_STATE, &read->rd_filp))) {
dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
goto out;
}
+ if (read->rd_filp)
+ get_file(read->rd_filp);
status = nfs_ok;
out:
nfs4_unlock_state();
read->rd_rqstp = rqstp;
read->rd_fhp = current_fh;
- read->rd_filp = filp;
return status;
}
@@ -532,6 +538,8 @@ nfsd4_remove(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_rem
{
int status;
+ if (nfs4_in_grace())
+ return nfserr_grace;
status = nfsd_unlink(rqstp, current_fh, 0, remove->rm_name, remove->rm_namelen);
if (status == nfserr_symlink)
return nfserr_notdir;
@@ -550,6 +558,9 @@ nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh,
if (!save_fh->fh_dentry)
return status;
+ if (nfs4_in_grace() && !(save_fh->fh_export->ex_flags
+ & NFSEXP_NOSUBTREECHECK))
+ return nfserr_grace;
status = nfsd_rename(rqstp, save_fh, rename->rn_sname,
rename->rn_snamelen, current_fh,
rename->rn_tname, rename->rn_tnamelen);
@@ -624,6 +635,8 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
goto out;
}
+ if (filp)
+ get_file(filp);
nfs4_unlock_state();
write->wr_bytes_written = write->wr_buflen;
@@ -635,6 +648,8 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
status = nfsd_write(rqstp, current_fh, filp, write->wr_offset,
write->wr_vec, write->wr_vlen, write->wr_buflen,
&write->wr_how_written);
+ if (filp)
+ fput(filp);
if (status == nfserr_symlink)
status = nfserr_inval;
@@ -923,6 +938,9 @@ encode_op:
nfs4_put_stateowner(replay_owner);
replay_owner = NULL;
}
+ /* XXX Ugh, we need to get rid of this kind of special case: */
+ if (op->opnum == OP_READ && op->u.read.rd_filp)
+ fput(op->u.read.rd_filp);
}
out:
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
new file mode 100644
index 00000000000..095f1740f3a
--- /dev/null
+++ b/fs/nfsd/nfs4recover.c
@@ -0,0 +1,431 @@
+/*
+* linux/fs/nfsd/nfs4recover.c
+*
+* Copyright (c) 2004 The Regents of the University of Michigan.
+* All rights reserved.
+*
+* Andy Adamson <andros@citi.umich.edu>
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* 1. Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* 2. Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* 3. Neither the name of the University nor the names of its
+* contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* 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 REGENTS OR CONTRIBUTORS 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.
+*
+*/
+
+
+#include <linux/sunrpc/svc.h>
+#include <linux/nfsd/nfsd.h>
+#include <linux/nfs4.h>
+#include <linux/nfsd/state.h>
+#include <linux/nfsd/xdr4.h>
+#include <linux/param.h>
+#include <linux/file.h>
+#include <linux/namei.h>
+#include <asm/uaccess.h>
+#include <asm/scatterlist.h>
+#include <linux/crypto.h>
+
+
+#define NFSDDBG_FACILITY NFSDDBG_PROC
+
+/* Globals */
+static struct nameidata rec_dir;
+static int rec_dir_init = 0;
+
+static void
+nfs4_save_user(uid_t *saveuid, gid_t *savegid)
+{
+ *saveuid = current->fsuid;
+ *savegid = current->fsgid;
+ current->fsuid = 0;
+ current->fsgid = 0;
+}
+
+static void
+nfs4_reset_user(uid_t saveuid, gid_t savegid)
+{
+ current->fsuid = saveuid;
+ current->fsgid = savegid;
+}
+
+static void
+md5_to_hex(char *out, char *md5)
+{
+ int i;
+
+ for (i=0; i<16; i++) {
+ unsigned char c = md5[i];
+
+ *out++ = '0' + ((c&0xf0)>>4) + (c>=0xa0)*('a'-'9'-1);
+ *out++ = '0' + (c&0x0f) + ((c&0x0f)>=0x0a)*('a'-'9'-1);
+ }
+ *out = '\0';
+}
+
+int
+nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname)
+{
+ struct xdr_netobj cksum;
+ struct crypto_tfm *tfm;
+ struct scatterlist sg[1];
+ int status = nfserr_resource;
+
+ dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n",
+ clname->len, clname->data);
+ tfm = crypto_alloc_tfm("md5", 0);
+ if (tfm == NULL)
+ goto out;
+ cksum.len = crypto_tfm_alg_digestsize(tfm);
+ cksum.data = kmalloc(cksum.len, GFP_KERNEL);
+ if (cksum.data == NULL)
+ goto out;
+ crypto_digest_init(tfm);
+
+ sg[0].page = virt_to_page(clname->data);
+ sg[0].offset = offset_in_page(clname->data);
+ sg[0].length = clname->len;
+
+ crypto_digest_update(tfm, sg, 1);
+ crypto_digest_final(tfm, cksum.data);
+
+ md5_to_hex(dname, cksum.data);
+
+ kfree(cksum.data);
+ status = nfs_ok;
+out:
+ if (tfm)
+ crypto_free_tfm(tfm);
+ return status;
+}
+
+static int
+nfsd4_rec_fsync(struct dentry *dentry)
+{
+ struct file *filp;
+ int status = nfs_ok;
+
+ dprintk("NFSD: nfs4_fsync_rec_dir\n");
+ filp = dentry_open(dget(dentry), mntget(rec_dir.mnt), O_RDWR);
+ if (IS_ERR(filp)) {
+ status = PTR_ERR(filp);
+ goto out;
+ }
+ if (filp->f_op && filp->f_op->fsync)
+ status = filp->f_op->fsync(filp, filp->f_dentry, 0);
+ fput(filp);
+out:
+ if (status)
+ printk("nfsd4: unable to sync recovery directory\n");
+ return status;
+}
+
+int
+nfsd4_create_clid_dir(struct nfs4_client *clp)
+{
+ char *dname = clp->cl_recdir;
+ struct dentry *dentry;
+ uid_t uid;
+ gid_t gid;
+ int status;
+
+ dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname);
+
+ if (!rec_dir_init || clp->cl_firststate)
+ return 0;
+
+ nfs4_save_user(&uid, &gid);
+
+ /* lock the parent */
+ down(&rec_dir.dentry->d_inode->i_sem);
+
+ dentry = lookup_one_len(dname, rec_dir.dentry, HEXDIR_LEN-1);
+ if (IS_ERR(dentry)) {
+ status = PTR_ERR(dentry);
+ goto out_unlock;
+ }
+ status = -EEXIST;
+ if (dentry->d_inode) {
+ dprintk("NFSD: nfsd4_create_clid_dir: DIRECTORY EXISTS\n");
+ goto out_put;
+ }
+ status = vfs_mkdir(rec_dir.dentry->d_inode, dentry, S_IRWXU);
+out_put:
+ dput(dentry);
+out_unlock:
+ up(&rec_dir.dentry->d_inode->i_sem);
+ if (status == 0) {
+ clp->cl_firststate = 1;
+ status = nfsd4_rec_fsync(rec_dir.dentry);
+ }
+ nfs4_reset_user(uid, gid);
+ dprintk("NFSD: nfsd4_create_clid_dir returns %d\n", status);
+ return status;
+}
+
+typedef int (recdir_func)(struct dentry *, struct dentry *);
+
+struct dentry_list {
+ struct dentry *dentry;
+ struct list_head list;
+};
+
+struct dentry_list_arg {
+ struct list_head dentries;
+ struct dentry *parent;
+};
+
+static int
+nfsd4_build_dentrylist(void *arg, const char *name, int namlen,
+ loff_t offset, ino_t ino, unsigned int d_type)
+{
+ struct dentry_list_arg *dla = arg;
+ struct list_head *dentries = &dla->dentries;
+ struct dentry *parent = dla->parent;
+ struct dentry *dentry;
+ struct dentry_list *child;
+
+ if (name && isdotent(name, namlen))
+ return nfs_ok;
+ dentry = lookup_one_len(name, parent, namlen);
+ if (IS_ERR(dentry))
+ return PTR_ERR(dentry);
+ child = kmalloc(sizeof(*child), GFP_KERNEL);
+ if (child == NULL)
+ return -ENOMEM;
+ child->dentry = dentry;
+ list_add(&child->list, dentries);
+ return 0;
+}
+
+static int
+nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
+{
+ struct file *filp;
+ struct dentry_list_arg dla = {
+ .parent = dir,
+ };
+ struct list_head *dentries = &dla.dentries;
+ struct dentry_list *child;
+ uid_t uid;
+ gid_t gid;
+ int status;
+
+ if (!rec_dir_init)
+ return 0;
+
+ nfs4_save_user(&uid, &gid);
+
+ filp = dentry_open(dget(dir), mntget(rec_dir.mnt),
+ O_RDWR);
+ status = PTR_ERR(filp);
+ if (IS_ERR(filp))
+ goto out;
+ INIT_LIST_HEAD(dentries);
+ status = vfs_readdir(filp, nfsd4_build_dentrylist, &dla);
+ fput(filp);
+ while (!list_empty(dentries)) {
+ child = list_entry(dentries->next, struct dentry_list, list);
+ status = f(dir, child->dentry);
+ if (status)
+ goto out;
+ list_del(&child->list);
+ dput(child->dentry);
+ kfree(child);
+ }
+out:
+ while (!list_empty(dentries)) {
+ child = list_entry(dentries->next, struct dentry_list, list);
+ list_del(&child->list);
+ dput(child->dentry);
+ kfree(child);
+ }
+ nfs4_reset_user(uid, gid);
+ return status;
+}
+
+static int
+nfsd4_remove_clid_file(struct dentry *dir, struct dentry *dentry)
+{
+ int status;
+
+ if (!S_ISREG(dir->d_inode->i_mode)) {
+ printk("nfsd4: non-file found in client recovery directory\n");
+ return -EINVAL;
+ }
+ down(&dir->d_inode->i_sem);
+ status = vfs_unlink(dir->d_inode, dentry);
+ up(&dir->d_inode->i_sem);
+ return status;
+}
+
+static int
+nfsd4_clear_clid_dir(struct dentry *dir, struct dentry *dentry)
+{
+ int status;
+
+ /* For now this directory should already be empty, but we empty it of
+ * any regular files anyway, just in case the directory was created by
+ * a kernel from the future.... */
+ nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file);
+ down(&dir->d_inode->i_sem);
+ status = vfs_rmdir(dir->d_inode, dentry);
+ up(&dir->d_inode->i_sem);
+ return status;
+}
+
+static int
+nfsd4_unlink_clid_dir(char *name, int namlen)
+{
+ struct dentry *dentry;
+ int status;
+
+ dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name);
+
+ dentry = lookup_one_len(name, rec_dir.dentry, namlen);
+ if (IS_ERR(dentry)) {
+ status = PTR_ERR(dentry);
+ return status;
+ }
+ status = -ENOENT;
+ if (!dentry->d_inode)
+ goto out;
+
+ status = nfsd4_clear_clid_dir(rec_dir.dentry, dentry);
+out:
+ dput(dentry);
+ return status;
+}
+
+void
+nfsd4_remove_clid_dir(struct nfs4_client *clp)
+{
+ uid_t uid;
+ gid_t gid;
+ int status;
+
+ if (!rec_dir_init || !clp->cl_firststate)
+ return;
+
+ nfs4_save_user(&uid, &gid);
+ status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1);
+ nfs4_reset_user(uid, gid);
+ if (status == 0)
+ status = nfsd4_rec_fsync(rec_dir.dentry);
+ if (status)
+ printk("NFSD: Failed to remove expired client state directory"
+ " %.*s\n", HEXDIR_LEN, clp->cl_recdir);
+ return;
+}
+
+static int
+purge_old(struct dentry *parent, struct dentry *child)
+{
+ int status;
+
+ if (nfs4_has_reclaimed_state(child->d_name.name))
+ return nfs_ok;
+
+ status = nfsd4_clear_clid_dir(parent, child);
+ if (status)
+ printk("failed to remove client recovery directory %s\n",
+ child->d_name.name);
+ /* Keep trying, success or failure: */
+ return nfs_ok;
+}
+
+void
+nfsd4_recdir_purge_old(void) {
+ int status;
+
+ if (!rec_dir_init)
+ return;
+ status = nfsd4_list_rec_dir(rec_dir.dentry, purge_old);
+ if (status == 0)
+ status = nfsd4_rec_fsync(rec_dir.dentry);
+ if (status)
+ printk("nfsd4: failed to purge old clients from recovery"
+ " directory %s\n", rec_dir.dentry->d_name.name);
+ return;
+}
+
+static int
+load_recdir(struct dentry *parent, struct dentry *child)
+{
+ if (child->d_name.len != HEXDIR_LEN - 1) {
+ printk("nfsd4: illegal name %s in recovery directory\n",
+ child->d_name.name);
+ /* Keep trying; maybe the others are OK: */
+ return nfs_ok;
+ }
+ nfs4_client_to_reclaim(child->d_name.name);
+ return nfs_ok;
+}
+
+int
+nfsd4_recdir_load(void) {
+ int status;
+
+ status = nfsd4_list_rec_dir(rec_dir.dentry, load_recdir);
+ if (status)
+ printk("nfsd4: failed loading clients from recovery"
+ " directory %s\n", rec_dir.dentry->d_name.name);
+ return status;
+}
+
+/*
+ * Hold reference to the recovery directory.
+ */
+
+void
+nfsd4_init_recdir(char *rec_dirname)
+{
+ uid_t uid = 0;
+ gid_t gid = 0;
+ int status;
+
+ printk("NFSD: Using %s as the NFSv4 state recovery directory\n",
+ rec_dirname);
+
+ BUG_ON(rec_dir_init);
+
+ nfs4_save_user(&uid, &gid);
+
+ status = path_lookup(rec_dirname, LOOKUP_FOLLOW, &rec_dir);
+ if (status == -ENOENT)
+ printk("NFSD: recovery directory %s doesn't exist\n",
+ rec_dirname);
+
+ if (!status)
+ rec_dir_init = 1;
+ nfs4_reset_user(uid, gid);
+}
+
+void
+nfsd4_shutdown_recdir(void)
+{
+ if (!rec_dir_init)
+ return;
+ rec_dir_init = 0;
+ path_release(&rec_dir);
+}
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 75e8b137580..89e36526d7f 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -48,39 +48,32 @@
#include <linux/nfs4.h>
#include <linux/nfsd/state.h>
#include <linux/nfsd/xdr4.h>
+#include <linux/namei.h>
#define NFSDDBG_FACILITY NFSDDBG_PROC
/* Globals */
static time_t lease_time = 90; /* default lease time */
-static time_t old_lease_time = 90; /* past incarnation lease time */
-static u32 nfs4_reclaim_init = 0;
-time_t boot_time;
-static time_t grace_end = 0;
+static time_t user_lease_time = 90;
+static time_t boot_time;
+static int in_grace = 1;
static u32 current_clientid = 1;
static u32 current_ownerid = 1;
static u32 current_fileid = 1;
static u32 current_delegid = 1;
static u32 nfs4_init;
-stateid_t zerostateid; /* bits all 0 */
-stateid_t onestateid; /* bits all 1 */
-
-/* debug counters */
-u32 list_add_perfile = 0;
-u32 list_del_perfile = 0;
-u32 add_perclient = 0;
-u32 del_perclient = 0;
-u32 alloc_file = 0;
-u32 free_file = 0;
-u32 vfsopen = 0;
-u32 vfsclose = 0;
-u32 alloc_delegation= 0;
-u32 free_delegation= 0;
+static stateid_t zerostateid; /* bits all 0 */
+static stateid_t onestateid; /* bits all 1 */
+
+#define ZERO_STATEID(stateid) (!memcmp((stateid), &zerostateid, sizeof(stateid_t)))
+#define ONE_STATEID(stateid) (!memcmp((stateid), &onestateid, sizeof(stateid_t)))
/* forward declarations */
-struct nfs4_stateid * find_stateid(stateid_t *stid, int flags);
+static struct nfs4_stateid * find_stateid(stateid_t *stid, int flags);
static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid);
static void release_stateid_lockowners(struct nfs4_stateid *open_stp);
+static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
+static void nfs4_set_recdir(char *recdir);
/* Locking:
*
@@ -90,6 +83,11 @@ static void release_stateid_lockowners(struct nfs4_stateid *open_stp);
*/
static DECLARE_MUTEX(client_sema);
+static kmem_cache_t *stateowner_slab = NULL;
+static kmem_cache_t *file_slab = NULL;
+static kmem_cache_t *stateid_slab = NULL;
+static kmem_cache_t *deleg_slab = NULL;
+
void
nfs4_lock_state(void)
{
@@ -118,16 +116,36 @@ opaque_hashval(const void *ptr, int nbytes)
/* forward declarations */
static void release_stateowner(struct nfs4_stateowner *sop);
static void release_stateid(struct nfs4_stateid *stp, int flags);
-static void release_file(struct nfs4_file *fp);
/*
* Delegation state
*/
/* recall_lock protects the del_recall_lru */
-spinlock_t recall_lock;
+static spinlock_t recall_lock = SPIN_LOCK_UNLOCKED;
static struct list_head del_recall_lru;
+static void
+free_nfs4_file(struct kref *kref)
+{
+ struct nfs4_file *fp = container_of(kref, struct nfs4_file, fi_ref);
+ list_del(&fp->fi_hash);
+ iput(fp->fi_inode);
+ kmem_cache_free(file_slab, fp);
+}
+
+static inline void
+put_nfs4_file(struct nfs4_file *fi)
+{
+ kref_put(&fi->fi_ref, free_nfs4_file);
+}
+
+static inline void
+get_nfs4_file(struct nfs4_file *fi)
+{
+ kref_get(&fi->fi_ref);
+}
+
static struct nfs4_delegation *
alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_fh *current_fh, u32 type)
{
@@ -136,13 +154,14 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
struct nfs4_callback *cb = &stp->st_stateowner->so_client->cl_callback;
dprintk("NFSD alloc_init_deleg\n");
- if ((dp = kmalloc(sizeof(struct nfs4_delegation),
- GFP_KERNEL)) == NULL)
+ dp = kmem_cache_alloc(deleg_slab, GFP_KERNEL);
+ if (dp == NULL)
return dp;
- INIT_LIST_HEAD(&dp->dl_del_perfile);
- INIT_LIST_HEAD(&dp->dl_del_perclnt);
+ INIT_LIST_HEAD(&dp->dl_perfile);
+ INIT_LIST_HEAD(&dp->dl_perclnt);
INIT_LIST_HEAD(&dp->dl_recall_lru);
dp->dl_client = clp;
+ get_nfs4_file(fp);
dp->dl_file = fp;
dp->dl_flock = NULL;
get_file(stp->st_vfs_file);
@@ -160,9 +179,8 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
current_fh->fh_handle.fh_size);
dp->dl_time = 0;
atomic_set(&dp->dl_count, 1);
- list_add(&dp->dl_del_perfile, &fp->fi_del_perfile);
- list_add(&dp->dl_del_perclnt, &clp->cl_del_perclnt);
- alloc_delegation++;
+ list_add(&dp->dl_perfile, &fp->fi_delegations);
+ list_add(&dp->dl_perclnt, &clp->cl_delegations);
return dp;
}
@@ -171,8 +189,8 @@ nfs4_put_delegation(struct nfs4_delegation *dp)
{
if (atomic_dec_and_test(&dp->dl_count)) {
dprintk("NFSD: freeing dp %p\n",dp);
- kfree(dp);
- free_delegation++;
+ put_nfs4_file(dp->dl_file);
+ kmem_cache_free(deleg_slab, dp);
}
}
@@ -193,15 +211,14 @@ nfs4_close_delegation(struct nfs4_delegation *dp)
if (dp->dl_flock)
setlease(filp, F_UNLCK, &dp->dl_flock);
nfsd_close(filp);
- vfsclose++;
}
/* Called under the state lock. */
static void
unhash_delegation(struct nfs4_delegation *dp)
{
- list_del_init(&dp->dl_del_perfile);
- list_del_init(&dp->dl_del_perclnt);
+ list_del_init(&dp->dl_perfile);
+ list_del_init(&dp->dl_perclnt);
spin_lock(&recall_lock);
list_del_init(&dp->dl_recall_lru);
spin_unlock(&recall_lock);
@@ -220,8 +237,8 @@ unhash_delegation(struct nfs4_delegation *dp)
#define clientid_hashval(id) \
((id) & CLIENT_HASH_MASK)
-#define clientstr_hashval(name, namelen) \
- (opaque_hashval((name), (namelen)) & CLIENT_HASH_MASK)
+#define clientstr_hashval(name) \
+ (opaque_hashval((name), 8) & CLIENT_HASH_MASK)
/*
* reclaim_str_hashtbl[] holds known client info from previous reset/reboot
* used in reboot/reset lease grace period processing
@@ -331,11 +348,11 @@ expire_client(struct nfs4_client *clp)
INIT_LIST_HEAD(&reaplist);
spin_lock(&recall_lock);
- while (!list_empty(&clp->cl_del_perclnt)) {
- dp = list_entry(clp->cl_del_perclnt.next, struct nfs4_delegation, dl_del_perclnt);
+ while (!list_empty(&clp->cl_delegations)) {
+ dp = list_entry(clp->cl_delegations.next, struct nfs4_delegation, dl_perclnt);
dprintk("NFSD: expire client. dp %p, fp %p\n", dp,
dp->dl_flock);
- list_del_init(&dp->dl_del_perclnt);
+ list_del_init(&dp->dl_perclnt);
list_move(&dp->dl_recall_lru, &reaplist);
}
spin_unlock(&recall_lock);
@@ -347,26 +364,26 @@ expire_client(struct nfs4_client *clp)
list_del(&clp->cl_idhash);
list_del(&clp->cl_strhash);
list_del(&clp->cl_lru);
- while (!list_empty(&clp->cl_perclient)) {
- sop = list_entry(clp->cl_perclient.next, struct nfs4_stateowner, so_perclient);
+ while (!list_empty(&clp->cl_openowners)) {
+ sop = list_entry(clp->cl_openowners.next, struct nfs4_stateowner, so_perclient);
release_stateowner(sop);
}
put_nfs4_client(clp);
}
static struct nfs4_client *
-create_client(struct xdr_netobj name) {
+create_client(struct xdr_netobj name, char *recdir) {
struct nfs4_client *clp;
if (!(clp = alloc_client(name)))
goto out;
+ memcpy(clp->cl_recdir, recdir, HEXDIR_LEN);
atomic_set(&clp->cl_count, 1);
atomic_set(&clp->cl_callback.cb_set, 0);
- clp->cl_callback.cb_parsed = 0;
INIT_LIST_HEAD(&clp->cl_idhash);
INIT_LIST_HEAD(&clp->cl_strhash);
- INIT_LIST_HEAD(&clp->cl_perclient);
- INIT_LIST_HEAD(&clp->cl_del_perclnt);
+ INIT_LIST_HEAD(&clp->cl_openowners);
+ INIT_LIST_HEAD(&clp->cl_delegations);
INIT_LIST_HEAD(&clp->cl_lru);
out:
return clp;
@@ -392,11 +409,9 @@ copy_cred(struct svc_cred *target, struct svc_cred *source) {
get_group_info(target->cr_group_info);
}
-static int
-cmp_name(struct xdr_netobj *n1, struct xdr_netobj *n2) {
- if (!n1 || !n2)
- return 0;
- return((n1->len == n2->len) && !memcmp(n1->data, n2->data, n2->len));
+static inline int
+same_name(const char *n1, const char *n2) {
+ return 0 == memcmp(n1, n2, HEXDIR_LEN);
}
static int
@@ -446,7 +461,7 @@ check_name(struct xdr_netobj name) {
return 1;
}
-void
+static void
add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval)
{
unsigned int idhashval;
@@ -458,7 +473,7 @@ add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval)
clp->cl_time = get_seconds();
}
-void
+static void
move_to_confirmed(struct nfs4_client *clp)
{
unsigned int idhashval = clientid_hashval(clp->cl_clientid.cl_id);
@@ -468,8 +483,7 @@ move_to_confirmed(struct nfs4_client *clp)
list_del_init(&clp->cl_strhash);
list_del_init(&clp->cl_idhash);
list_add(&clp->cl_idhash, &conf_id_hashtbl[idhashval]);
- strhashval = clientstr_hashval(clp->cl_name.data,
- clp->cl_name.len);
+ strhashval = clientstr_hashval(clp->cl_recdir);
list_add(&clp->cl_strhash, &conf_str_hashtbl[strhashval]);
renew_client(clp);
}
@@ -500,6 +514,30 @@ find_unconfirmed_client(clientid_t *clid)
return NULL;
}
+static struct nfs4_client *
+find_confirmed_client_by_str(const char *dname, unsigned int hashval)
+{
+ struct nfs4_client *clp;
+
+ list_for_each_entry(clp, &conf_str_hashtbl[hashval], cl_strhash) {
+ if (same_name(clp->cl_recdir, dname))
+ return clp;
+ }
+ return NULL;
+}
+
+static struct nfs4_client *
+find_unconfirmed_client_by_str(const char *dname, unsigned int hashval)
+{
+ struct nfs4_client *clp;
+
+ list_for_each_entry(clp, &unconf_str_hashtbl[hashval], cl_strhash) {
+ if (same_name(clp->cl_recdir, dname))
+ return clp;
+ }
+ return NULL;
+}
+
/* a helper function for parse_callback */
static int
parse_octet(unsigned int *lenp, char **addrp)
@@ -534,7 +572,7 @@ parse_octet(unsigned int *lenp, char **addrp)
}
/* parse and set the setclientid ipv4 callback address */
-int
+static int
parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigned short *cbportp)
{
int temp = 0;
@@ -570,7 +608,7 @@ parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigne
return 1;
}
-void
+static void
gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
{
struct nfs4_callback *cb = &clp->cl_callback;
@@ -584,14 +622,12 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
goto out_err;
cb->cb_prog = se->se_callback_prog;
cb->cb_ident = se->se_callback_ident;
- cb->cb_parsed = 1;
return;
out_err:
printk(KERN_INFO "NFSD: this client (clientid %08x/%08x) "
"will not receive delegations\n",
clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
- cb->cb_parsed = 0;
return;
}
@@ -638,59 +674,43 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
};
nfs4_verifier clverifier = setclid->se_verf;
unsigned int strhashval;
- struct nfs4_client * conf, * unconf, * new, * clp;
+ struct nfs4_client *conf, *unconf, *new;
int status;
+ char dname[HEXDIR_LEN];
status = nfserr_inval;
if (!check_name(clname))
goto out;
+ status = nfs4_make_rec_clidname(dname, &clname);
+ if (status)
+ goto out;
+
/*
* XXX The Duplicate Request Cache (DRC) has been checked (??)
* We get here on a DRC miss.
*/
- strhashval = clientstr_hashval(clname.data, clname.len);
+ strhashval = clientstr_hashval(dname);
- conf = NULL;
nfs4_lock_state();
- list_for_each_entry(clp, &conf_str_hashtbl[strhashval], cl_strhash) {
- if (!cmp_name(&clp->cl_name, &clname))
- continue;
+ conf = find_confirmed_client_by_str(dname, strhashval);
+ if (conf) {
/*
* CASE 0:
* clname match, confirmed, different principal
* or different ip_address
*/
status = nfserr_clid_inuse;
- if (!cmp_creds(&clp->cl_cred,&rqstp->rq_cred)) {
- printk("NFSD: setclientid: string in use by client"
- "(clientid %08x/%08x)\n",
- clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
- goto out;
- }
- if (clp->cl_addr != ip_addr) {
+ if (!cmp_creds(&conf->cl_cred, &rqstp->rq_cred)
+ || conf->cl_addr != ip_addr) {
printk("NFSD: setclientid: string in use by client"
"(clientid %08x/%08x)\n",
- clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
+ conf->cl_clientid.cl_boot, conf->cl_clientid.cl_id);
goto out;
}
-
- /*
- * cl_name match from a previous SETCLIENTID operation
- * XXX check for additional matches?
- */
- conf = clp;
- break;
- }
- unconf = NULL;
- list_for_each_entry(clp, &unconf_str_hashtbl[strhashval], cl_strhash) {
- if (!cmp_name(&clp->cl_name, &clname))
- continue;
- /* cl_name match from a previous SETCLIENTID operation */
- unconf = clp;
- break;
}
+ unconf = find_unconfirmed_client_by_str(dname, strhashval);
status = nfserr_resource;
if (!conf) {
/*
@@ -699,7 +719,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
*/
if (unconf)
expire_client(unconf);
- if (!(new = create_client(clname)))
+ new = create_client(clname, dname);
+ if (new == NULL)
goto out;
copy_verf(new, &clverifier);
new->cl_addr = ip_addr;
@@ -722,12 +743,16 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
* nfs4_client, but with the new callback info and a
* new cl_confirm
*/
- if ((unconf) &&
- cmp_verf(&unconf->cl_verifier, &conf->cl_verifier) &&
- cmp_clid(&unconf->cl_clientid, &conf->cl_clientid)) {
- expire_client(unconf);
+ if (unconf) {
+ /* Note this is removing unconfirmed {*x***},
+ * which is stronger than RFC recommended {vxc**}.
+ * This has the advantage that there is at most
+ * one {*x***} in either list at any time.
+ */
+ expire_client(unconf);
}
- if (!(new = create_client(clname)))
+ new = create_client(clname, dname);
+ if (new == NULL)
goto out;
copy_verf(new,&conf->cl_verifier);
new->cl_addr = ip_addr;
@@ -745,7 +770,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
* using input clverifier, clname, and callback info
* and generate a new cl_clientid and cl_confirm.
*/
- if (!(new = create_client(clname)))
+ new = create_client(clname, dname);
+ if (new == NULL)
goto out;
copy_verf(new,&clverifier);
new->cl_addr = ip_addr;
@@ -771,7 +797,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
* new cl_verifier and a new cl_confirm
*/
expire_client(unconf);
- if (!(new = create_client(clname)))
+ new = create_client(clname, dname);
+ if (new == NULL)
goto out;
copy_verf(new,&clverifier);
new->cl_addr = ip_addr;
@@ -807,7 +834,7 @@ int
nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm)
{
u32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
- struct nfs4_client *clp, *conf = NULL, *unconf = NULL;
+ struct nfs4_client *conf, *unconf;
nfs4_verifier confirm = setclientid_confirm->sc_confirm;
clientid_t * clid = &setclientid_confirm->sc_clientid;
int status;
@@ -820,102 +847,90 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi
*/
nfs4_lock_state();
- clp = find_confirmed_client(clid);
- if (clp) {
- status = nfserr_inval;
- /*
- * Found a record for this clientid. If the IP addresses
- * don't match, return ERR_INVAL just as if the record had
- * not been found.
- */
- if (clp->cl_addr != ip_addr) {
- printk("NFSD: setclientid: string in use by client"
- "(clientid %08x/%08x)\n",
- clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
- goto out;
- }
- conf = clp;
- }
- clp = find_unconfirmed_client(clid);
- if (clp) {
- status = nfserr_inval;
- if (clp->cl_addr != ip_addr) {
- printk("NFSD: setclientid: string in use by client"
- "(clientid %08x/%08x)\n",
- clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
- goto out;
- }
- unconf = clp;
- }
- /* CASE 1:
- * unconf record that matches input clientid and input confirm.
- * conf record that matches input clientid.
- * conf and unconf records match names, verifiers
- */
+
+ conf = find_confirmed_client(clid);
+ unconf = find_unconfirmed_client(clid);
+
+ status = nfserr_clid_inuse;
+ if (conf && conf->cl_addr != ip_addr)
+ goto out;
+ if (unconf && unconf->cl_addr != ip_addr)
+ goto out;
+
if ((conf && unconf) &&
(cmp_verf(&unconf->cl_confirm, &confirm)) &&
(cmp_verf(&conf->cl_verifier, &unconf->cl_verifier)) &&
- (cmp_name(&conf->cl_name,&unconf->cl_name)) &&
+ (same_name(conf->cl_recdir,unconf->cl_recdir)) &&
(!cmp_verf(&conf->cl_confirm, &unconf->cl_confirm))) {
+ /* CASE 1:
+ * unconf record that matches input clientid and input confirm.
+ * conf record that matches input clientid.
+ * conf and unconf records match names, verifiers
+ */
if (!cmp_creds(&conf->cl_cred, &unconf->cl_cred))
status = nfserr_clid_inuse;
else {
- expire_client(conf);
- clp = unconf;
- move_to_confirmed(unconf);
+ /* XXX: We just turn off callbacks until we can handle
+ * change request correctly. */
+ atomic_set(&conf->cl_callback.cb_set, 0);
+ gen_confirm(conf);
+ expire_client(unconf);
status = nfs_ok;
+
}
- goto out;
- }
- /* CASE 2:
- * conf record that matches input clientid.
- * if unconf record that matches input clientid, then unconf->cl_name
- * or unconf->cl_verifier don't match the conf record.
- */
- if ((conf && !unconf) ||
+ } else if ((conf && !unconf) ||
((conf && unconf) &&
(!cmp_verf(&conf->cl_verifier, &unconf->cl_verifier) ||
- !cmp_name(&conf->cl_name, &unconf->cl_name)))) {
- if (!cmp_creds(&conf->cl_cred,&rqstp->rq_cred)) {
+ !same_name(conf->cl_recdir, unconf->cl_recdir)))) {
+ /* CASE 2:
+ * conf record that matches input clientid.
+ * if unconf record matches input clientid, then
+ * unconf->cl_name or unconf->cl_verifier don't match the
+ * conf record.
+ */
+ if (!cmp_creds(&conf->cl_cred,&rqstp->rq_cred))
status = nfserr_clid_inuse;
- } else {
- clp = conf;
+ else
status = nfs_ok;
- }
- goto out;
- }
- /* CASE 3:
- * conf record not found.
- * unconf record found.
- * unconf->cl_confirm matches input confirm
- */
- if (!conf && unconf && cmp_verf(&unconf->cl_confirm, &confirm)) {
+ } else if (!conf && unconf
+ && cmp_verf(&unconf->cl_confirm, &confirm)) {
+ /* CASE 3:
+ * conf record not found.
+ * unconf record found.
+ * unconf->cl_confirm matches input confirm
+ */
if (!cmp_creds(&unconf->cl_cred, &rqstp->rq_cred)) {
status = nfserr_clid_inuse;
} else {
- status = nfs_ok;
- clp = unconf;
+ unsigned int hash =
+ clientstr_hashval(unconf->cl_recdir);
+ conf = find_confirmed_client_by_str(unconf->cl_recdir,
+ hash);
+ if (conf) {
+ nfsd4_remove_clid_dir(conf);
+ expire_client(conf);
+ }
move_to_confirmed(unconf);
+ conf = unconf;
+ status = nfs_ok;
}
- goto out;
- }
- /* CASE 4:
- * conf record not found, or if conf, then conf->cl_confirm does not
- * match input confirm.
- * unconf record not found, or if unconf, then unconf->cl_confirm
- * does not match input confirm.
- */
- if ((!conf || (conf && !cmp_verf(&conf->cl_confirm, &confirm))) &&
- (!unconf || (unconf && !cmp_verf(&unconf->cl_confirm, &confirm)))) {
+ } else if ((!conf || (conf && !cmp_verf(&conf->cl_confirm, &confirm)))
+ && (!unconf || (unconf && !cmp_verf(&unconf->cl_confirm,
+ &confirm)))) {
+ /* CASE 4:
+ * conf record not found, or if conf, conf->cl_confirm does not
+ * match input confirm.
+ * unconf record not found, or if unconf, unconf->cl_confirm
+ * does not match input confirm.
+ */
status = nfserr_stale_clientid;
- goto out;
+ } else {
+ /* check that we have hit one of the cases...*/
+ status = nfserr_clid_inuse;
}
- /* check that we have hit one of the cases...*/
- status = nfserr_inval;
- goto out;
out:
if (!status)
- nfsd4_probe_callback(clp);
+ nfsd4_probe_callback(conf);
nfs4_unlock_state();
return status;
}
@@ -961,60 +976,65 @@ alloc_init_file(struct inode *ino)
struct nfs4_file *fp;
unsigned int hashval = file_hashval(ino);
- if ((fp = kmalloc(sizeof(struct nfs4_file),GFP_KERNEL))) {
+ fp = kmem_cache_alloc(file_slab, GFP_KERNEL);
+ if (fp) {
+ kref_init(&fp->fi_ref);
INIT_LIST_HEAD(&fp->fi_hash);
- INIT_LIST_HEAD(&fp->fi_perfile);
- INIT_LIST_HEAD(&fp->fi_del_perfile);
+ INIT_LIST_HEAD(&fp->fi_stateids);
+ INIT_LIST_HEAD(&fp->fi_delegations);
list_add(&fp->fi_hash, &file_hashtbl[hashval]);
fp->fi_inode = igrab(ino);
fp->fi_id = current_fileid++;
- alloc_file++;
return fp;
}
return NULL;
}
static void
-release_all_files(void)
+nfsd4_free_slab(kmem_cache_t **slab)
{
- int i;
- struct nfs4_file *fp;
+ int status;
- for (i=0;i<FILE_HASH_SIZE;i++) {
- while (!list_empty(&file_hashtbl[i])) {
- fp = list_entry(file_hashtbl[i].next, struct nfs4_file, fi_hash);
- /* this should never be more than once... */
- if (!list_empty(&fp->fi_perfile) || !list_empty(&fp->fi_del_perfile)) {
- printk("ERROR: release_all_files: file %p is open, creating dangling state !!!\n",fp);
- }
- release_file(fp);
- }
- }
+ if (*slab == NULL)
+ return;
+ status = kmem_cache_destroy(*slab);
+ *slab = NULL;
+ WARN_ON(status);
}
-kmem_cache_t *stateowner_slab = NULL;
+static void
+nfsd4_free_slabs(void)
+{
+ nfsd4_free_slab(&stateowner_slab);
+ nfsd4_free_slab(&file_slab);
+ nfsd4_free_slab(&stateid_slab);
+ nfsd4_free_slab(&deleg_slab);
+}
static int
nfsd4_init_slabs(void)
{
stateowner_slab = kmem_cache_create("nfsd4_stateowners",
sizeof(struct nfs4_stateowner), 0, 0, NULL, NULL);
- if (stateowner_slab == NULL) {
- dprintk("nfsd4: out of memory while initializing nfsv4\n");
- return -ENOMEM;
- }
+ if (stateowner_slab == NULL)
+ goto out_nomem;
+ file_slab = kmem_cache_create("nfsd4_files",
+ sizeof(struct nfs4_file), 0, 0, NULL, NULL);
+ if (file_slab == NULL)
+ goto out_nomem;
+ stateid_slab = kmem_cache_create("nfsd4_stateids",
+ sizeof(struct nfs4_stateid), 0, 0, NULL, NULL);
+ if (stateid_slab == NULL)
+ goto out_nomem;
+ deleg_slab = kmem_cache_create("nfsd4_delegations",
+ sizeof(struct nfs4_delegation), 0, 0, NULL, NULL);
+ if (deleg_slab == NULL)
+ goto out_nomem;
return 0;
-}
-
-static void
-nfsd4_free_slabs(void)
-{
- int status = 0;
-
- if (stateowner_slab)
- status = kmem_cache_destroy(stateowner_slab);
- stateowner_slab = NULL;
- BUG_ON(status);
+out_nomem:
+ nfsd4_free_slabs();
+ dprintk("nfsd4: out of memory while initializing nfsv4\n");
+ return -ENOMEM;
}
void
@@ -1055,14 +1075,13 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
INIT_LIST_HEAD(&sop->so_idhash);
INIT_LIST_HEAD(&sop->so_strhash);
INIT_LIST_HEAD(&sop->so_perclient);
- INIT_LIST_HEAD(&sop->so_perfilestate);
- INIT_LIST_HEAD(&sop->so_perlockowner); /* not used */
+ INIT_LIST_HEAD(&sop->so_stateids);
+ INIT_LIST_HEAD(&sop->so_perstateid); /* not used */
INIT_LIST_HEAD(&sop->so_close_lru);
sop->so_time = 0;
list_add(&sop->so_idhash, &ownerid_hashtbl[idhashval]);
list_add(&sop->so_strhash, &ownerstr_hashtbl[strhashval]);
- list_add(&sop->so_perclient, &clp->cl_perclient);
- add_perclient++;
+ list_add(&sop->so_perclient, &clp->cl_openowners);
sop->so_is_open_owner = 1;
sop->so_id = current_ownerid++;
sop->so_client = clp;
@@ -1080,10 +1099,10 @@ release_stateid_lockowners(struct nfs4_stateid *open_stp)
{
struct nfs4_stateowner *lock_sop;
- while (!list_empty(&open_stp->st_perlockowner)) {
- lock_sop = list_entry(open_stp->st_perlockowner.next,
- struct nfs4_stateowner, so_perlockowner);
- /* list_del(&open_stp->st_perlockowner); */
+ while (!list_empty(&open_stp->st_lockowners)) {
+ lock_sop = list_entry(open_stp->st_lockowners.next,
+ struct nfs4_stateowner, so_perstateid);
+ /* list_del(&open_stp->st_lockowners); */
BUG_ON(lock_sop->so_is_open_owner);
release_stateowner(lock_sop);
}
@@ -1096,14 +1115,12 @@ unhash_stateowner(struct nfs4_stateowner *sop)
list_del(&sop->so_idhash);
list_del(&sop->so_strhash);
- if (sop->so_is_open_owner) {
+ if (sop->so_is_open_owner)
list_del(&sop->so_perclient);
- del_perclient++;
- }
- list_del(&sop->so_perlockowner);
- while (!list_empty(&sop->so_perfilestate)) {
- stp = list_entry(sop->so_perfilestate.next,
- struct nfs4_stateid, st_perfilestate);
+ list_del(&sop->so_perstateid);
+ while (!list_empty(&sop->so_stateids)) {
+ stp = list_entry(sop->so_stateids.next,
+ struct nfs4_stateid, st_perstateowner);
if (sop->so_is_open_owner)
release_stateid(stp, OPEN_STATE);
else
@@ -1125,14 +1142,14 @@ init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *
unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id);
INIT_LIST_HEAD(&stp->st_hash);
- INIT_LIST_HEAD(&stp->st_perfilestate);
- INIT_LIST_HEAD(&stp->st_perlockowner);
+ INIT_LIST_HEAD(&stp->st_perstateowner);
+ INIT_LIST_HEAD(&stp->st_lockowners);
INIT_LIST_HEAD(&stp->st_perfile);
list_add(&stp->st_hash, &stateid_hashtbl[hashval]);
- list_add(&stp->st_perfilestate, &sop->so_perfilestate);
- list_add_perfile++;
- list_add(&stp->st_perfile, &fp->fi_perfile);
+ list_add(&stp->st_perstateowner, &sop->so_stateids);
+ list_add(&stp->st_perfile, &fp->fi_stateids);
stp->st_stateowner = sop;
+ get_nfs4_file(fp);
stp->st_file = fp;
stp->st_stateid.si_boot = boot_time;
stp->st_stateid.si_stateownerid = sop->so_id;
@@ -1150,30 +1167,20 @@ release_stateid(struct nfs4_stateid *stp, int flags)
struct file *filp = stp->st_vfs_file;
list_del(&stp->st_hash);
- list_del_perfile++;
list_del(&stp->st_perfile);
- list_del(&stp->st_perfilestate);
+ list_del(&stp->st_perstateowner);
if (flags & OPEN_STATE) {
release_stateid_lockowners(stp);
stp->st_vfs_file = NULL;
nfsd_close(filp);
- vfsclose++;
} else if (flags & LOCK_STATE)
locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner);
- kfree(stp);
+ put_nfs4_file(stp->st_file);
+ kmem_cache_free(stateid_slab, stp);
stp = NULL;
}
static void
-release_file(struct nfs4_file *fp)
-{
- free_file++;
- list_del(&fp->fi_hash);
- iput(fp->fi_inode);
- kfree(fp);
-}
-
-void
move_to_close_lru(struct nfs4_stateowner *sop)
{
dprintk("NFSD: move_to_close_lru nfs4_stateowner %p\n", sop);
@@ -1183,11 +1190,10 @@ move_to_close_lru(struct nfs4_stateowner *sop)
sop->so_time = get_seconds();
}
-void
+static void
release_state_owner(struct nfs4_stateid *stp, int flag)
{
struct nfs4_stateowner *sop = stp->st_stateowner;
- struct nfs4_file *fp = stp->st_file;
dprintk("NFSD: release_state_owner\n");
release_stateid(stp, flag);
@@ -1196,12 +1202,8 @@ release_state_owner(struct nfs4_stateid *stp, int flag)
* released by the laundromat service after the lease period
* to enable us to handle CLOSE replay
*/
- if (sop->so_confirmed && list_empty(&sop->so_perfilestate))
+ if (sop->so_confirmed && list_empty(&sop->so_stateids))
move_to_close_lru(sop);
- /* unused nfs4_file's are releseed. XXX slab cache? */
- if (list_empty(&fp->fi_perfile) && list_empty(&fp->fi_del_perfile)) {
- release_file(fp);
- }
}
static int
@@ -1231,8 +1233,10 @@ find_file(struct inode *ino)
struct nfs4_file *fp;
list_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) {
- if (fp->fi_inode == ino)
+ if (fp->fi_inode == ino) {
+ get_nfs4_file(fp);
return fp;
+ }
}
return NULL;
}
@@ -1240,7 +1244,7 @@ find_file(struct inode *ino)
#define TEST_ACCESS(x) ((x > 0 || x < 4)?1:0)
#define TEST_DENY(x) ((x >= 0 || x < 5)?1:0)
-void
+static void
set_access(unsigned int *access, unsigned long bmap) {
int i;
@@ -1251,7 +1255,7 @@ set_access(unsigned int *access, unsigned long bmap) {
}
}
-void
+static void
set_deny(unsigned int *deny, unsigned long bmap) {
int i;
@@ -1277,25 +1281,30 @@ test_share(struct nfs4_stateid *stp, struct nfsd4_open *open) {
* Called to check deny when READ with all zero stateid or
* WRITE with all zero or all one stateid
*/
-int
+static int
nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
{
struct inode *ino = current_fh->fh_dentry->d_inode;
struct nfs4_file *fp;
struct nfs4_stateid *stp;
+ int ret;
dprintk("NFSD: nfs4_share_conflict\n");
fp = find_file(ino);
- if (fp) {
+ if (!fp)
+ return nfs_ok;
+ ret = nfserr_share_denied;
/* Search for conflicting share reservations */
- list_for_each_entry(stp, &fp->fi_perfile, st_perfile) {
- if (test_bit(deny_type, &stp->st_deny_bmap) ||
- test_bit(NFS4_SHARE_DENY_BOTH, &stp->st_deny_bmap))
- return nfserr_share_denied;
- }
+ list_for_each_entry(stp, &fp->fi_stateids, st_perfile) {
+ if (test_bit(deny_type, &stp->st_deny_bmap) ||
+ test_bit(NFS4_SHARE_DENY_BOTH, &stp->st_deny_bmap))
+ goto out;
}
- return nfs_ok;
+ ret = nfs_ok;
+out:
+ put_nfs4_file(fp);
+ return ret;
}
static inline void
@@ -1427,7 +1436,7 @@ int nfsd_change_deleg_cb(struct file_lock **onlist, int arg)
return -EAGAIN;
}
-struct lock_manager_operations nfsd_lease_mng_ops = {
+static struct lock_manager_operations nfsd_lease_mng_ops = {
.fl_break = nfsd_break_deleg_cb,
.fl_release_private = nfsd_release_deleg_cb,
.fl_copy_lock = nfsd_copy_lock_deleg_cb,
@@ -1526,6 +1535,51 @@ out:
return status;
}
+static inline int
+nfs4_check_delegmode(struct nfs4_delegation *dp, int flags)
+{
+ if ((flags & WR_STATE) && (dp->dl_type == NFS4_OPEN_DELEGATE_READ))
+ return nfserr_openmode;
+ else
+ return nfs_ok;
+}
+
+static struct nfs4_delegation *
+find_delegation_file(struct nfs4_file *fp, stateid_t *stid)
+{
+ struct nfs4_delegation *dp;
+
+ list_for_each_entry(dp, &fp->fi_delegations, dl_perfile) {
+ if (dp->dl_stateid.si_stateownerid == stid->si_stateownerid)
+ return dp;
+ }
+ return NULL;
+}
+
+static int
+nfs4_check_deleg(struct nfs4_file *fp, struct nfsd4_open *open,
+ struct nfs4_delegation **dp)
+{
+ int flags;
+ int status = nfserr_bad_stateid;
+
+ *dp = find_delegation_file(fp, &open->op_delegate_stateid);
+ if (*dp == NULL)
+ goto out;
+ flags = open->op_share_access == NFS4_SHARE_ACCESS_READ ?
+ RD_STATE : WR_STATE;
+ status = nfs4_check_delegmode(*dp, flags);
+ if (status)
+ *dp = NULL;
+out:
+ if (open->op_claim_type != NFS4_OPEN_CLAIM_DELEGATE_CUR)
+ return nfs_ok;
+ if (status)
+ return status;
+ open->op_stateowner->so_confirmed = 1;
+ return nfs_ok;
+}
+
static int
nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_stateid **stpp)
{
@@ -1533,7 +1587,7 @@ nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_state
int status = nfserr_share_denied;
struct nfs4_stateowner *sop = open->op_stateowner;
- list_for_each_entry(local, &fp->fi_perfile, st_perfile) {
+ list_for_each_entry(local, &fp->fi_stateids, st_perfile) {
/* ignore lock owners */
if (local->st_stateowner->so_is_open_owner == 0)
continue;
@@ -1549,25 +1603,37 @@ out:
return status;
}
+static inline struct nfs4_stateid *
+nfs4_alloc_stateid(void)
+{
+ return kmem_cache_alloc(stateid_slab, GFP_KERNEL);
+}
+
static int
nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp,
+ struct nfs4_delegation *dp,
struct svc_fh *cur_fh, int flags)
{
struct nfs4_stateid *stp;
- int status;
- stp = kmalloc(sizeof(struct nfs4_stateid), GFP_KERNEL);
+ stp = nfs4_alloc_stateid();
if (stp == NULL)
return nfserr_resource;
- status = nfsd_open(rqstp, cur_fh, S_IFREG, flags, &stp->st_vfs_file);
- if (status) {
- if (status == nfserr_dropit)
- status = nfserr_jukebox;
- kfree(stp);
- return status;
+ if (dp) {
+ get_file(dp->dl_vfs_file);
+ stp->st_vfs_file = dp->dl_vfs_file;
+ } else {
+ int status;
+ status = nfsd_open(rqstp, cur_fh, S_IFREG, flags,
+ &stp->st_vfs_file);
+ if (status) {
+ if (status == nfserr_dropit)
+ status = nfserr_jukebox;
+ kmem_cache_free(stateid_slab, stp);
+ return status;
+ }
}
- vfsopen++;
*stpp = stp;
return 0;
}
@@ -1628,6 +1694,7 @@ nfs4_set_claim_prev(struct nfsd4_open *open, int *status)
*status = nfserr_reclaim_bad;
else {
open->op_stateowner->so_confirmed = 1;
+ open->op_stateowner->so_client->cl_firststate = 1;
open->op_stateowner->so_seqid--;
}
}
@@ -1646,14 +1713,30 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
int status, flag = 0;
flag = NFS4_OPEN_DELEGATE_NONE;
- if (open->op_claim_type != NFS4_OPEN_CLAIM_NULL
- || !atomic_read(&cb->cb_set) || !sop->so_confirmed)
- goto out;
-
- if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
- flag = NFS4_OPEN_DELEGATE_WRITE;
- else
- flag = NFS4_OPEN_DELEGATE_READ;
+ open->op_recall = 0;
+ switch (open->op_claim_type) {
+ case NFS4_OPEN_CLAIM_PREVIOUS:
+ if (!atomic_read(&cb->cb_set))
+ open->op_recall = 1;
+ flag = open->op_delegate_type;
+ if (flag == NFS4_OPEN_DELEGATE_NONE)
+ goto out;
+ break;
+ case NFS4_OPEN_CLAIM_NULL:
+ /* Let's not give out any delegations till everyone's
+ * had the chance to reclaim theirs.... */
+ if (nfs4_in_grace())
+ goto out;
+ if (!atomic_read(&cb->cb_set) || !sop->so_confirmed)
+ goto out;
+ if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
+ flag = NFS4_OPEN_DELEGATE_WRITE;
+ else
+ flag = NFS4_OPEN_DELEGATE_READ;
+ break;
+ default:
+ goto out;
+ }
dp = alloc_init_deleg(sop->so_client, stp, fh, flag);
if (dp == NULL) {
@@ -1687,6 +1770,10 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
dp->dl_stateid.si_fileid,
dp->dl_stateid.si_generation);
out:
+ if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS
+ && flag == NFS4_OPEN_DELEGATE_NONE
+ && open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE)
+ printk("NFSD: WARNING: refusing delegation reclaim\n");
open->op_delegate_type = flag;
}
@@ -1699,6 +1786,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
struct nfs4_file *fp = NULL;
struct inode *ino = current_fh->fh_dentry->d_inode;
struct nfs4_stateid *stp = NULL;
+ struct nfs4_delegation *dp = NULL;
int status;
status = nfserr_inval;
@@ -1713,7 +1801,13 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
if (fp) {
if ((status = nfs4_check_open(fp, open, &stp)))
goto out;
+ status = nfs4_check_deleg(fp, open, &dp);
+ if (status)
+ goto out;
} else {
+ status = nfserr_bad_stateid;
+ if (open->op_claim_type == NFS4_OPEN_CLAIM_DELEGATE_CUR)
+ goto out;
status = nfserr_resource;
fp = alloc_init_file(ino);
if (fp == NULL)
@@ -1736,7 +1830,8 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
flags = MAY_WRITE;
else
flags = MAY_READ;
- if ((status = nfs4_new_open(rqstp, &stp, current_fh, flags)))
+ status = nfs4_new_open(rqstp, &stp, dp, current_fh, flags);
+ if (status)
goto out;
init_stateid(stp, fp, open);
status = nfsd4_truncate(rqstp, current_fh, open);
@@ -1759,10 +1854,8 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
stp->st_stateid.si_boot, stp->st_stateid.si_stateownerid,
stp->st_stateid.si_fileid, stp->st_stateid.si_generation);
out:
- /* take the opportunity to clean up unused state */
- if (fp && list_empty(&fp->fi_perfile) && list_empty(&fp->fi_del_perfile))
- release_file(fp);
-
+ if (fp)
+ put_nfs4_file(fp);
/* CLAIM_PREVIOUS has different error returns */
nfs4_set_claim_prev(open, &status);
/*
@@ -1775,6 +1868,7 @@ out:
return status;
}
+static struct workqueue_struct *laundry_wq;
static struct work_struct laundromat_work;
static void laundromat_main(void *);
static DECLARE_WORK(laundromat_work, laundromat_main, NULL);
@@ -1800,7 +1894,7 @@ nfsd4_renew(clientid_t *clid)
}
renew_client(clp);
status = nfserr_cb_path_down;
- if (!list_empty(&clp->cl_del_perclnt)
+ if (!list_empty(&clp->cl_delegations)
&& !atomic_read(&clp->cl_callback.cb_set))
goto out;
status = nfs_ok;
@@ -1809,7 +1903,15 @@ out:
return status;
}
-time_t
+static void
+end_grace(void)
+{
+ dprintk("NFSD: end of grace period\n");
+ nfsd4_recdir_purge_old();
+ in_grace = 0;
+}
+
+static time_t
nfs4_laundromat(void)
{
struct nfs4_client *clp;
@@ -1823,6 +1925,8 @@ nfs4_laundromat(void)
nfs4_lock_state();
dprintk("NFSD: laundromat service - starting\n");
+ if (in_grace)
+ end_grace();
list_for_each_safe(pos, next, &client_lru) {
clp = list_entry(pos, struct nfs4_client, cl_lru);
if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) {
@@ -1833,6 +1937,7 @@ nfs4_laundromat(void)
}
dprintk("NFSD: purging unused client (clientid %08x)\n",
clp->cl_clientid.cl_id);
+ nfsd4_remove_clid_dir(clp);
expire_client(clp);
}
INIT_LIST_HEAD(&reaplist);
@@ -1882,13 +1987,13 @@ laundromat_main(void *not_used)
t = nfs4_laundromat();
dprintk("NFSD: laundromat_main - sleeping for %ld seconds\n", t);
- schedule_delayed_work(&laundromat_work, t*HZ);
+ queue_delayed_work(laundry_wq, &laundromat_work, t*HZ);
}
/* search ownerid_hashtbl[] and close_lru for stateid owner
* (stateid->si_stateownerid)
*/
-struct nfs4_stateowner *
+static struct nfs4_stateowner *
find_openstateowner_id(u32 st_id, int flags) {
struct nfs4_stateowner *local = NULL;
@@ -1949,15 +2054,6 @@ out:
}
static inline int
-nfs4_check_delegmode(struct nfs4_delegation *dp, int flags)
-{
- if ((flags & WR_STATE) && (dp->dl_type == NFS4_OPEN_DELEGATE_READ))
- return nfserr_openmode;
- else
- return nfs_ok;
-}
-
-static inline int
check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
{
/* Trying to call delegreturn with a special stateid? Yuch: */
@@ -2071,7 +2167,7 @@ out:
/*
* Checks for sequence id mutating operations.
*/
-int
+static int
nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, clientid_t *lockclid)
{
int status;
@@ -2230,6 +2326,8 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs
stp->st_stateid.si_stateownerid,
stp->st_stateid.si_fileid,
stp->st_stateid.si_generation);
+
+ nfsd4_create_clid_dir(sop->so_client);
out:
if (oc->oc_stateowner)
nfs4_get_stateowner(oc->oc_stateowner);
@@ -2387,7 +2485,7 @@ static struct list_head lock_ownerid_hashtbl[LOCK_HASH_SIZE];
static struct list_head lock_ownerstr_hashtbl[LOCK_HASH_SIZE];
static struct list_head lockstateid_hashtbl[STATEID_HASH_SIZE];
-struct nfs4_stateid *
+static struct nfs4_stateid *
find_stateid(stateid_t *stid, int flags)
{
struct nfs4_stateid *local = NULL;
@@ -2419,25 +2517,19 @@ find_stateid(stateid_t *stid, int flags)
static struct nfs4_delegation *
find_delegation_stateid(struct inode *ino, stateid_t *stid)
{
- struct nfs4_delegation *dp = NULL;
- struct nfs4_file *fp = NULL;
- u32 st_id;
+ struct nfs4_file *fp;
+ struct nfs4_delegation *dl;
dprintk("NFSD:find_delegation_stateid stateid=(%08x/%08x/%08x/%08x)\n",
stid->si_boot, stid->si_stateownerid,
stid->si_fileid, stid->si_generation);
- st_id = stid->si_stateownerid;
fp = find_file(ino);
- if (fp) {
- list_for_each_entry(dp, &fp->fi_del_perfile, dl_del_perfile) {
- if(dp->dl_stateid.si_stateownerid == st_id) {
- dprintk("NFSD: find_delegation dp %p\n",dp);
- return dp;
- }
- }
- }
- return NULL;
+ if (!fp)
+ return NULL;
+ dl = find_delegation_file(fp, stid);
+ put_nfs4_file(fp);
+ return dl;
}
/*
@@ -2457,7 +2549,7 @@ nfs4_transform_lock_offset(struct file_lock *lock)
lock->fl_end = OFFSET_MAX;
}
-int
+static int
nfs4_verify_lock_stateowner(struct nfs4_stateowner *sop, unsigned int hashval)
{
struct nfs4_stateowner *local = NULL;
@@ -2498,22 +2590,6 @@ nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny)
}
static struct nfs4_stateowner *
-find_lockstateowner(struct xdr_netobj *owner, clientid_t *clid)
-{
- struct nfs4_stateowner *local = NULL;
- int i;
-
- for (i = 0; i < LOCK_HASH_SIZE; i++) {
- list_for_each_entry(local, &lock_ownerid_hashtbl[i], so_idhash) {
- if (!cmp_owner_str(local, owner, clid))
- continue;
- return local;
- }
- }
- return NULL;
-}
-
-static struct nfs4_stateowner *
find_lockstateowner_str(struct inode *inode, clientid_t *clid,
struct xdr_netobj *owner)
{
@@ -2548,13 +2624,13 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
INIT_LIST_HEAD(&sop->so_idhash);
INIT_LIST_HEAD(&sop->so_strhash);
INIT_LIST_HEAD(&sop->so_perclient);
- INIT_LIST_HEAD(&sop->so_perfilestate);
- INIT_LIST_HEAD(&sop->so_perlockowner);
+ INIT_LIST_HEAD(&sop->so_stateids);
+ INIT_LIST_HEAD(&sop->so_perstateid);
INIT_LIST_HEAD(&sop->so_close_lru); /* not used */
sop->so_time = 0;
list_add(&sop->so_idhash, &lock_ownerid_hashtbl[idhashval]);
list_add(&sop->so_strhash, &lock_ownerstr_hashtbl[strhashval]);
- list_add(&sop->so_perlockowner, &open_stp->st_perlockowner);
+ list_add(&sop->so_perstateid, &open_stp->st_lockowners);
sop->so_is_open_owner = 0;
sop->so_id = current_ownerid++;
sop->so_client = clp;
@@ -2567,24 +2643,24 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
return sop;
}
-struct nfs4_stateid *
+static struct nfs4_stateid *
alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struct nfs4_stateid *open_stp)
{
struct nfs4_stateid *stp;
unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id);
- if ((stp = kmalloc(sizeof(struct nfs4_stateid),
- GFP_KERNEL)) == NULL)
+ stp = nfs4_alloc_stateid();
+ if (stp == NULL)
goto out;
INIT_LIST_HEAD(&stp->st_hash);
INIT_LIST_HEAD(&stp->st_perfile);
- INIT_LIST_HEAD(&stp->st_perfilestate);
- INIT_LIST_HEAD(&stp->st_perlockowner); /* not used */
+ INIT_LIST_HEAD(&stp->st_perstateowner);
+ INIT_LIST_HEAD(&stp->st_lockowners); /* not used */
list_add(&stp->st_hash, &lockstateid_hashtbl[hashval]);
- list_add(&stp->st_perfile, &fp->fi_perfile);
- list_add_perfile++;
- list_add(&stp->st_perfilestate, &sop->so_perfilestate);
+ list_add(&stp->st_perfile, &fp->fi_stateids);
+ list_add(&stp->st_perstateowner, &sop->so_stateids);
stp->st_stateowner = sop;
+ get_nfs4_file(fp);
stp->st_file = fp;
stp->st_stateid.si_boot = boot_time;
stp->st_stateid.si_stateownerid = sop->so_id;
@@ -2598,7 +2674,7 @@ out:
return stp;
}
-int
+static int
check_lock_length(u64 offset, u64 length)
{
return ((length == 0) || ((length != ~(u64)0) &&
@@ -2611,7 +2687,7 @@ check_lock_length(u64 offset, u64 length)
int
nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock)
{
- struct nfs4_stateowner *lock_sop = NULL, *open_sop = NULL;
+ struct nfs4_stateowner *open_sop = NULL;
struct nfs4_stateid *lock_stp;
struct file *filp;
struct file_lock file_lock;
@@ -2670,16 +2746,9 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
strhashval = lock_ownerstr_hashval(fp->fi_inode,
open_sop->so_client->cl_clientid.cl_id,
&lock->v.new.owner);
- /*
- * If we already have this lock owner, the client is in
- * error (or our bookeeping is wrong!)
- * for asking for a 'new lock'.
- */
- status = nfserr_bad_stateid;
- lock_sop = find_lockstateowner(&lock->v.new.owner,
- &lock->v.new.clientid);
- if (lock_sop)
- goto out;
+ /* XXX: Do we need to check for duplicate stateowners on
+ * the same file, or should they just be allowed (and
+ * create new stateids)? */
status = nfserr_resource;
if (!(lock->lk_stateowner = alloc_init_lock_stateowner(strhashval, open_sop->so_client, open_stp, lock)))
goto out;
@@ -2970,8 +3039,11 @@ int
nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *rlockowner)
{
clientid_t *clid = &rlockowner->rl_clientid;
- struct nfs4_stateowner *local = NULL;
+ struct nfs4_stateowner *sop;
+ struct nfs4_stateid *stp;
struct xdr_netobj *owner = &rlockowner->rl_owner;
+ struct list_head matches;
+ int i;
int status;
dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n",
@@ -2987,22 +3059,32 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *
nfs4_lock_state();
- status = nfs_ok;
- local = find_lockstateowner(owner, clid);
- if (local) {
- struct nfs4_stateid *stp;
-
- /* check for any locks held by any stateid
- * associated with the (lock) stateowner */
- status = nfserr_locks_held;
- list_for_each_entry(stp, &local->so_perfilestate,
- st_perfilestate) {
- if (check_for_locks(stp->st_vfs_file, local))
- goto out;
+ status = nfserr_locks_held;
+ /* XXX: we're doing a linear search through all the lockowners.
+ * Yipes! For now we'll just hope clients aren't really using
+ * release_lockowner much, but eventually we have to fix these
+ * data structures. */
+ INIT_LIST_HEAD(&matches);
+ for (i = 0; i < LOCK_HASH_SIZE; i++) {
+ list_for_each_entry(sop, &lock_ownerid_hashtbl[i], so_idhash) {
+ if (!cmp_owner_str(sop, owner, clid))
+ continue;
+ list_for_each_entry(stp, &sop->so_stateids,
+ st_perstateowner) {
+ if (check_for_locks(stp->st_vfs_file, sop))
+ goto out;
+ /* Note: so_perclient unused for lockowners,
+ * so it's OK to fool with here. */
+ list_add(&sop->so_perclient, &matches);
+ }
}
- /* no locks held by (lock) stateowner */
- status = nfs_ok;
- release_stateowner(local);
+ }
+ /* Clients probably won't expect us to return with some (but not all)
+ * of the lockowner state released; so don't release any until all
+ * have been checked. */
+ status = nfs_ok;
+ list_for_each_entry(sop, &matches, so_perclient) {
+ release_stateowner(sop);
}
out:
nfs4_unlock_state();
@@ -3010,39 +3092,38 @@ out:
}
static inline struct nfs4_client_reclaim *
-alloc_reclaim(int namelen)
+alloc_reclaim(void)
{
- struct nfs4_client_reclaim *crp = NULL;
+ return kmalloc(sizeof(struct nfs4_client_reclaim), GFP_KERNEL);
+}
- crp = kmalloc(sizeof(struct nfs4_client_reclaim), GFP_KERNEL);
- if (!crp)
- return NULL;
- crp->cr_name.data = kmalloc(namelen, GFP_KERNEL);
- if (!crp->cr_name.data) {
- kfree(crp);
- return NULL;
- }
- return crp;
+int
+nfs4_has_reclaimed_state(const char *name)
+{
+ unsigned int strhashval = clientstr_hashval(name);
+ struct nfs4_client *clp;
+
+ clp = find_confirmed_client_by_str(name, strhashval);
+ return clp ? 1 : 0;
}
/*
* failure => all reset bets are off, nfserr_no_grace...
*/
-static int
-nfs4_client_to_reclaim(char *name, int namlen)
+int
+nfs4_client_to_reclaim(const char *name)
{
unsigned int strhashval;
struct nfs4_client_reclaim *crp = NULL;
- dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", namlen, name);
- crp = alloc_reclaim(namlen);
+ dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", HEXDIR_LEN, name);
+ crp = alloc_reclaim();
if (!crp)
return 0;
- strhashval = clientstr_hashval(name, namlen);
+ strhashval = clientstr_hashval(name);
INIT_LIST_HEAD(&crp->cr_strhash);
list_add(&crp->cr_strhash, &reclaim_str_hashtbl[strhashval]);
- memcpy(crp->cr_name.data, name, namlen);
- crp->cr_name.len = namlen;
+ memcpy(crp->cr_recdir, name, HEXDIR_LEN);
reclaim_str_hashtbl_size++;
return 1;
}
@@ -3053,13 +3134,11 @@ nfs4_release_reclaim(void)
struct nfs4_client_reclaim *crp = NULL;
int i;
- BUG_ON(!nfs4_reclaim_init);
for (i = 0; i < CLIENT_HASH_SIZE; i++) {
while (!list_empty(&reclaim_str_hashtbl[i])) {
crp = list_entry(reclaim_str_hashtbl[i].next,
struct nfs4_client_reclaim, cr_strhash);
list_del(&crp->cr_strhash);
- kfree(crp->cr_name.data);
kfree(crp);
reclaim_str_hashtbl_size--;
}
@@ -3069,7 +3148,7 @@ nfs4_release_reclaim(void)
/*
* called from OPEN, CLAIM_PREVIOUS with a new clientid. */
-struct nfs4_client_reclaim *
+static struct nfs4_client_reclaim *
nfs4_find_reclaim_client(clientid_t *clid)
{
unsigned int strhashval;
@@ -3082,13 +3161,14 @@ nfs4_find_reclaim_client(clientid_t *clid)
if (clp == NULL)
return NULL;
- dprintk("NFSD: nfs4_find_reclaim_client for %.*s\n",
- clp->cl_name.len, clp->cl_name.data);
+ dprintk("NFSD: nfs4_find_reclaim_client for %.*s with recdir %s\n",
+ clp->cl_name.len, clp->cl_name.data,
+ clp->cl_recdir);
/* find clp->cl_name in reclaim_str_hashtbl */
- strhashval = clientstr_hashval(clp->cl_name.data, clp->cl_name.len);
+ strhashval = clientstr_hashval(clp->cl_recdir);
list_for_each_entry(crp, &reclaim_str_hashtbl[strhashval], cr_strhash) {
- if (cmp_name(&crp->cr_name, &clp->cl_name)) {
+ if (same_name(crp->cr_recdir, clp->cl_recdir)) {
return crp;
}
}
@@ -3101,30 +3181,16 @@ nfs4_find_reclaim_client(clientid_t *clid)
int
nfs4_check_open_reclaim(clientid_t *clid)
{
- struct nfs4_client_reclaim *crp;
-
- if ((crp = nfs4_find_reclaim_client(clid)) == NULL)
- return nfserr_reclaim_bad;
- return nfs_ok;
+ return nfs4_find_reclaim_client(clid) ? nfs_ok : nfserr_reclaim_bad;
}
+/* initialization to perform at module load time: */
-/*
- * Start and stop routines
- */
-
-static void
-__nfs4_state_init(void)
+void
+nfs4_state_init(void)
{
int i;
- time_t grace_time;
- if (!nfs4_reclaim_init) {
- for (i = 0; i < CLIENT_HASH_SIZE; i++)
- INIT_LIST_HEAD(&reclaim_str_hashtbl[i]);
- reclaim_str_hashtbl_size = 0;
- nfs4_reclaim_init = 1;
- }
for (i = 0; i < CLIENT_HASH_SIZE; i++) {
INIT_LIST_HEAD(&conf_id_hashtbl[i]);
INIT_LIST_HEAD(&conf_str_hashtbl[i]);
@@ -3146,26 +3212,46 @@ __nfs4_state_init(void)
INIT_LIST_HEAD(&lock_ownerid_hashtbl[i]);
INIT_LIST_HEAD(&lock_ownerstr_hashtbl[i]);
}
- memset(&zerostateid, 0, sizeof(stateid_t));
memset(&onestateid, ~0, sizeof(stateid_t));
-
INIT_LIST_HEAD(&close_lru);
INIT_LIST_HEAD(&client_lru);
INIT_LIST_HEAD(&del_recall_lru);
- spin_lock_init(&recall_lock);
+ for (i = 0; i < CLIENT_HASH_SIZE; i++)
+ INIT_LIST_HEAD(&reclaim_str_hashtbl[i]);
+ reclaim_str_hashtbl_size = 0;
+}
+
+static void
+nfsd4_load_reboot_recovery_data(void)
+{
+ int status;
+
+ nfs4_lock_state();
+ nfsd4_init_recdir(user_recovery_dirname);
+ status = nfsd4_recdir_load();
+ nfs4_unlock_state();
+ if (status)
+ printk("NFSD: Failure reading reboot recovery data\n");
+}
+
+/* initialization to perform when the nfsd service is started: */
+
+static void
+__nfs4_state_start(void)
+{
+ time_t grace_time;
+
boot_time = get_seconds();
- grace_time = max(old_lease_time, lease_time);
- if (reclaim_str_hashtbl_size == 0)
- grace_time = 0;
- if (grace_time)
- printk("NFSD: starting %ld-second grace period\n", grace_time);
- grace_end = boot_time + grace_time;
- INIT_WORK(&laundromat_work,laundromat_main, NULL);
- schedule_delayed_work(&laundromat_work, NFSD_LEASE_TIME*HZ);
+ grace_time = max(user_lease_time, lease_time);
+ lease_time = user_lease_time;
+ in_grace = 1;
+ printk("NFSD: starting %ld-second grace period\n", grace_time);
+ laundry_wq = create_singlethread_workqueue("nfsd4");
+ queue_delayed_work(laundry_wq, &laundromat_work, grace_time*HZ);
}
int
-nfs4_state_init(void)
+nfs4_state_start(void)
{
int status;
@@ -3174,7 +3260,8 @@ nfs4_state_init(void)
status = nfsd4_init_slabs();
if (status)
return status;
- __nfs4_state_init();
+ nfsd4_load_reboot_recovery_data();
+ __nfs4_state_start();
nfs4_init = 1;
return 0;
}
@@ -3182,14 +3269,7 @@ nfs4_state_init(void)
int
nfs4_in_grace(void)
{
- return get_seconds() < grace_end;
-}
-
-void
-set_no_grace(void)
-{
- printk("NFSD: ERROR in reboot recovery. State reclaims will fail.\n");
- grace_end = get_seconds();
+ return in_grace;
}
time_t
@@ -3236,21 +3316,11 @@ __nfs4_state_shutdown(void)
unhash_delegation(dp);
}
- release_all_files();
cancel_delayed_work(&laundromat_work);
- flush_scheduled_work();
+ flush_workqueue(laundry_wq);
+ destroy_workqueue(laundry_wq);
+ nfsd4_shutdown_recdir();
nfs4_init = 0;
- dprintk("NFSD: list_add_perfile %d list_del_perfile %d\n",
- list_add_perfile, list_del_perfile);
- dprintk("NFSD: add_perclient %d del_perclient %d\n",
- add_perclient, del_perclient);
- dprintk("NFSD: alloc_file %d free_file %d\n",
- alloc_file, free_file);
- dprintk("NFSD: vfsopen %d vfsclose %d\n",
- vfsopen, vfsclose);
- dprintk("NFSD: alloc_delegation %d free_delegation %d\n",
- alloc_delegation, free_delegation);
-
}
void
@@ -3263,56 +3333,48 @@ nfs4_state_shutdown(void)
nfs4_unlock_state();
}
+static void
+nfs4_set_recdir(char *recdir)
+{
+ nfs4_lock_state();
+ strcpy(user_recovery_dirname, recdir);
+ nfs4_unlock_state();
+}
+
+/*
+ * Change the NFSv4 recovery directory to recdir.
+ */
+int
+nfs4_reset_recoverydir(char *recdir)
+{
+ int status;
+ struct nameidata nd;
+
+ status = path_lookup(recdir, LOOKUP_FOLLOW, &nd);
+ if (status)
+ return status;
+ status = -ENOTDIR;
+ if (S_ISDIR(nd.dentry->d_inode->i_mode)) {
+ nfs4_set_recdir(recdir);
+ status = 0;
+ }
+ path_release(&nd);
+ return status;
+}
+
/*
* Called when leasetime is changed.
*
- * if nfsd is not started, simply set the global lease.
- *
- * if nfsd(s) are running, lease change requires nfsv4 state to be reset.
- * e.g: boot_time is reset, existing nfs4_client structs are
- * used to fill reclaim_str_hashtbl, then all state (except for the
- * reclaim_str_hashtbl) is re-initialized.
- *
- * if the old lease time is greater than the new lease time, the grace
- * period needs to be set to the old lease time to allow clients to reclaim
- * their state. XXX - we may want to set the grace period == lease time
- * after an initial grace period == old lease time
- *
- * if an error occurs in this process, the new lease is set, but the server
- * will not honor OPEN or LOCK reclaims, and will return nfserr_no_grace
- * which means OPEN/LOCK/READ/WRITE will fail during grace period.
- *
- * clients will attempt to reset all state with SETCLIENTID/CONFIRM, and
- * OPEN and LOCK reclaims.
+ * The only way the protocol gives us to handle on-the-fly lease changes is to
+ * simulate a reboot. Instead of doing that, we just wait till the next time
+ * we start to register any changes in lease time. If the administrator
+ * really wants to change the lease time *now*, they can go ahead and bring
+ * nfsd down and then back up again after changing the lease time.
*/
void
nfs4_reset_lease(time_t leasetime)
{
- struct nfs4_client *clp;
- int i;
-
- printk("NFSD: New leasetime %ld\n",leasetime);
- if (!nfs4_init)
- return;
- nfs4_lock_state();
- old_lease_time = lease_time;
- lease_time = leasetime;
-
- nfs4_release_reclaim();
-
- /* populate reclaim_str_hashtbl with current confirmed nfs4_clientid */
- for (i = 0; i < CLIENT_HASH_SIZE; i++) {
- list_for_each_entry(clp, &conf_id_hashtbl[i], cl_idhash) {
- if (!nfs4_client_to_reclaim(clp->cl_name.data,
- clp->cl_name.len)) {
- nfs4_release_reclaim();
- goto init_state;
- }
- }
- }
-init_state:
- __nfs4_state_shutdown();
- __nfs4_state_init();
- nfs4_unlock_state();
+ lock_kernel();
+ user_lease_time = leasetime;
+ unlock_kernel();
}
-
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 36a058a112d..91fb171d2ac 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -136,7 +136,7 @@ xdr_error: \
} \
} while (0)
-u32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes)
+static u32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes)
{
/* We want more bytes than seem to be available.
* Maybe we need a new page, maybe we have just run out
@@ -190,7 +190,7 @@ defer_free(struct nfsd4_compoundargs *argp,
return 0;
}
-char *savemem(struct nfsd4_compoundargs *argp, u32 *p, int nbytes)
+static char *savemem(struct nfsd4_compoundargs *argp, u32 *p, int nbytes)
{
void *new = NULL;
if (p == argp->tmp) {
@@ -1366,7 +1366,10 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) {
if ((buflen -= 4) < 0)
goto out_resource;
- WRITE32( NFS4_FH_NOEXPIRE_WITH_OPEN | NFS4_FH_VOL_RENAME );
+ if (exp->ex_flags & NFSEXP_NOSUBTREECHECK)
+ WRITE32(NFS4_FH_VOLATILE_ANY);
+ else
+ WRITE32(NFS4_FH_VOLATILE_ANY|NFS4_FH_VOL_RENAME);
}
if (bmval0 & FATTR4_WORD0_CHANGE) {
/*
@@ -1969,7 +1972,7 @@ nfsd4_encode_open(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_open
case NFS4_OPEN_DELEGATE_READ:
RESERVE_SPACE(20 + sizeof(stateid_t));
WRITEMEM(&open->op_delegate_stateid, sizeof(stateid_t));
- WRITE32(0);
+ WRITE32(open->op_recall);
/*
* TODO: ACE's in delegations
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 161afdcb8f7..841c562991e 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -51,6 +51,7 @@ enum {
NFSD_Fh,
NFSD_Threads,
NFSD_Leasetime,
+ NFSD_RecoveryDir,
};
/*
@@ -66,6 +67,7 @@ static ssize_t write_getfs(struct file *file, char *buf, size_t size);
static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
static ssize_t write_threads(struct file *file, char *buf, size_t size);
static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
+static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
static ssize_t (*write_op[])(struct file *, char *, size_t) = {
[NFSD_Svc] = write_svc,
@@ -78,6 +80,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
[NFSD_Fh] = write_filehandle,
[NFSD_Threads] = write_threads,
[NFSD_Leasetime] = write_leasetime,
+ [NFSD_RecoveryDir] = write_recoverydir,
};
static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
@@ -349,6 +352,25 @@ static ssize_t write_leasetime(struct file *file, char *buf, size_t size)
return strlen(buf);
}
+static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
+{
+ char *mesg = buf;
+ char *recdir;
+ int len, status;
+
+ if (size > PATH_MAX || buf[size-1] != '\n')
+ return -EINVAL;
+ buf[size-1] = 0;
+
+ recdir = mesg;
+ len = qword_get(&mesg, recdir, size);
+ if (len <= 0)
+ return -EINVAL;
+
+ status = nfs4_reset_recoverydir(recdir);
+ return strlen(buf);
+}
+
/*----------------------------------------------------------------------------*/
/*
* populating the filesystem.
@@ -369,6 +391,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
[NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
#ifdef CONFIG_NFSD_V4
[NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
+ [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR},
#endif
/* last one */ {""}
};
@@ -397,9 +420,8 @@ static int __init init_nfsd(void)
nfsd_cache_init(); /* RPC reply cache */
nfsd_export_init(); /* Exports table */
nfsd_lockd_init(); /* lockd->nfsd callbacks */
-#ifdef CONFIG_NFSD_V4
+ nfs4_state_init(); /* NFSv4 locking state */
nfsd_idmap_init(); /* Name to ID mapping */
-#endif /* CONFIG_NFSD_V4 */
if (proc_mkdir("fs/nfs", NULL)) {
struct proc_dir_entry *entry;
entry = create_proc_entry("fs/nfs/exports", 0, NULL);
@@ -426,9 +448,7 @@ static void __exit exit_nfsd(void)
remove_proc_entry("fs/nfs", NULL);
nfsd_stat_shutdown();
nfsd_lockd_shutdown();
-#ifdef CONFIG_NFSD_V4
nfsd_idmap_shutdown();
-#endif /* CONFIG_NFSD_V4 */
unregister_filesystem(&nfsd_fs_type);
}
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 757f9d20803..0aa1b9603d7 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -591,6 +591,7 @@ nfserrno (int errno)
{ nfserr_dropit, -ENOMEM },
{ nfserr_badname, -ESRCH },
{ nfserr_io, -ETXTBSY },
+ { nfserr_notsupp, -EOPNOTSUPP },
{ -1, -EIO }
};
int i;
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 02ded7cfbdc..07b9a065e9d 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -31,6 +31,7 @@
#include <linux/nfsd/stats.h>
#include <linux/nfsd/cache.h>
#include <linux/lockd/bind.h>
+#include <linux/nfsacl.h>
#define NFSDDBG_FACILITY NFSDDBG_SVC
@@ -94,7 +95,7 @@ nfsd_svc(unsigned short port, int nrservs)
error = nfsd_racache_init(2*nrservs);
if (error<0)
goto out;
- error = nfs4_state_init();
+ error = nfs4_state_start();
if (error<0)
goto out;
if (!nfsd_serv) {
@@ -362,6 +363,32 @@ nfsd_dispatch(struct svc_rqst *rqstp, u32 *statp)
return 1;
}
+#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
+static struct svc_stat nfsd_acl_svcstats;
+static struct svc_version * nfsd_acl_version[] = {
+ [2] = &nfsd_acl_version2,
+ [3] = &nfsd_acl_version3,
+};
+
+#define NFSD_ACL_NRVERS (sizeof(nfsd_acl_version)/sizeof(nfsd_acl_version[0]))
+static struct svc_program nfsd_acl_program = {
+ .pg_prog = NFS_ACL_PROGRAM,
+ .pg_nvers = NFSD_ACL_NRVERS,
+ .pg_vers = nfsd_acl_version,
+ .pg_name = "nfsd",
+ .pg_class = "nfsd",
+ .pg_stats = &nfsd_acl_svcstats,
+};
+
+static struct svc_stat nfsd_acl_svcstats = {
+ .program = &nfsd_acl_program,
+};
+
+#define nfsd_acl_program_p &nfsd_acl_program
+#else
+#define nfsd_acl_program_p NULL
+#endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
+
extern struct svc_version nfsd_version2, nfsd_version3, nfsd_version4;
static struct svc_version * nfsd_version[] = {
@@ -376,6 +403,7 @@ static struct svc_version * nfsd_version[] = {
#define NFSD_NRVERS (sizeof(nfsd_version)/sizeof(nfsd_version[0]))
struct svc_program nfsd_program = {
+ .pg_next = nfsd_acl_program_p,
.pg_prog = NFS_PROGRAM, /* program number */
.pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */
.pg_vers = nfsd_version, /* version table */
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 948b08287c9..b45999ff33e 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -49,6 +49,12 @@ decode_fh(u32 *p, struct svc_fh *fhp)
return p + (NFS_FHSIZE >> 2);
}
+/* Helper function for NFSv2 ACL code */
+u32 *nfs2svc_decode_fh(u32 *p, struct svc_fh *fhp)
+{
+ return decode_fh(p, fhp);
+}
+
static inline u32 *
encode_fh(u32 *p, struct svc_fh *fhp)
{
@@ -190,6 +196,11 @@ encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
return p;
}
+/* Helper function for NFSv2 ACL code */
+u32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
+{
+ return encode_fattr(rqstp, p, fhp);
+}
/*
* XDR decode functions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index e3e9d217236..de340ffd33c 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -46,10 +46,10 @@
#include <linux/nfsd/nfsfh.h>
#include <linux/quotaops.h>
#include <linux/dnotify.h>
-#ifdef CONFIG_NFSD_V4
+#include <linux/xattr_acl.h>
#include <linux/posix_acl.h>
+#ifdef CONFIG_NFSD_V4
#include <linux/posix_acl_xattr.h>
-#include <linux/xattr_acl.h>
#include <linux/xattr.h>
#include <linux/nfs4.h>
#include <linux/nfs4_acl.h>
@@ -424,13 +424,13 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
goto out_nfserr;
if (pacl) {
- error = set_nfsv4_acl_one(dentry, pacl, XATTR_NAME_ACL_ACCESS);
+ error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS);
if (error < 0)
goto out_nfserr;
}
if (dpacl) {
- error = set_nfsv4_acl_one(dentry, dpacl, XATTR_NAME_ACL_DEFAULT);
+ error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT);
if (error < 0)
goto out_nfserr;
}
@@ -497,7 +497,7 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_ac
struct posix_acl *pacl = NULL, *dpacl = NULL;
unsigned int flags = 0;
- pacl = _get_posix_acl(dentry, XATTR_NAME_ACL_ACCESS);
+ pacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_ACCESS);
if (IS_ERR(pacl) && PTR_ERR(pacl) == -ENODATA)
pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
if (IS_ERR(pacl)) {
@@ -507,7 +507,7 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_ac
}
if (S_ISDIR(inode->i_mode)) {
- dpacl = _get_posix_acl(dentry, XATTR_NAME_ACL_DEFAULT);
+ dpacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_DEFAULT);
if (IS_ERR(dpacl) && PTR_ERR(dpacl) == -ENODATA)
dpacl = NULL;
else if (IS_ERR(dpacl)) {
@@ -1857,3 +1857,107 @@ nfsd_racache_init(int cache_size)
nfsdstats.ra_size = cache_size;
return 0;
}
+
+#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
+struct posix_acl *
+nfsd_get_posix_acl(struct svc_fh *fhp, int type)
+{
+ struct inode *inode = fhp->fh_dentry->d_inode;
+ char *name;
+ void *value = NULL;
+ ssize_t size;
+ struct posix_acl *acl;
+
+ if (!IS_POSIXACL(inode) || !inode->i_op || !inode->i_op->getxattr)
+ return ERR_PTR(-EOPNOTSUPP);
+ switch(type) {
+ case ACL_TYPE_ACCESS:
+ name = XATTR_NAME_ACL_ACCESS;
+ break;
+ case ACL_TYPE_DEFAULT:
+ name = XATTR_NAME_ACL_DEFAULT;
+ break;
+ default:
+ return ERR_PTR(-EOPNOTSUPP);
+ }
+
+ size = inode->i_op->getxattr(fhp->fh_dentry, name, NULL, 0);
+
+ if (size < 0) {
+ acl = ERR_PTR(size);
+ goto getout;
+ } else if (size > 0) {
+ value = kmalloc(size, GFP_KERNEL);
+ if (!value) {
+ acl = ERR_PTR(-ENOMEM);
+ goto getout;
+ }
+ size = inode->i_op->getxattr(fhp->fh_dentry, name, value, size);
+ if (size < 0) {
+ acl = ERR_PTR(size);
+ goto getout;
+ }
+ }
+ acl = posix_acl_from_xattr(value, size);
+
+getout:
+ kfree(value);
+ return acl;
+}
+
+int
+nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
+{
+ struct inode *inode = fhp->fh_dentry->d_inode;
+ char *name;
+ void *value = NULL;
+ size_t size;
+ int error;
+
+ if (!IS_POSIXACL(inode) || !inode->i_op ||
+ !inode->i_op->setxattr || !inode->i_op->removexattr)
+ return -EOPNOTSUPP;
+ switch(type) {
+ case ACL_TYPE_ACCESS:
+ name = XATTR_NAME_ACL_ACCESS;
+ break;
+ case ACL_TYPE_DEFAULT:
+ name = XATTR_NAME_ACL_DEFAULT;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ if (acl && acl->a_count) {
+ size = xattr_acl_size(acl->a_count);
+ value = kmalloc(size, GFP_KERNEL);
+ if (!value)
+ return -ENOMEM;
+ size = posix_acl_to_xattr(acl, value, size);
+ if (size < 0) {
+ error = size;
+ goto getout;
+ }
+ } else
+ size = 0;
+
+ if (!fhp->fh_locked)
+ fh_lock(fhp); /* unlocking is done automatically */
+ if (size)
+ error = inode->i_op->setxattr(fhp->fh_dentry, name,
+ value, size, 0);
+ else {
+ if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
+ error = 0;
+ else {
+ error = inode->i_op->removexattr(fhp->fh_dentry, name);
+ if (error == -ENODATA)
+ error = 0;
+ }
+ }
+
+getout:
+ kfree(value);
+ return error;
+}
+#endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
diff --git a/fs/open.c b/fs/open.c
index 963bd81a44c..3f4a4286fdc 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -21,6 +21,7 @@
#include <linux/vfs.h>
#include <asm/uaccess.h>
#include <linux/fs.h>
+#include <linux/personality.h>
#include <linux/pagemap.h>
#include <linux/syscalls.h>
@@ -807,7 +808,9 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
/* NB: we're sure to have correct a_ops only after f_op->open */
if (f->f_flags & O_DIRECT) {
- if (!f->f_mapping->a_ops || !f->f_mapping->a_ops->direct_IO) {
+ if (!f->f_mapping->a_ops ||
+ ((!f->f_mapping->a_ops->direct_IO) &&
+ (!f->f_mapping->a_ops->get_xip_page))) {
fput(f);
f = ERR_PTR(-EINVAL);
}
@@ -933,31 +936,27 @@ EXPORT_SYMBOL(fd_install);
asmlinkage long sys_open(const char __user * filename, int flags, int mode)
{
char * tmp;
- int fd, error;
+ int fd;
+
+ if (force_o_largefile())
+ flags |= O_LARGEFILE;
-#if BITS_PER_LONG != 32
- flags |= O_LARGEFILE;
-#endif
tmp = getname(filename);
fd = PTR_ERR(tmp);
if (!IS_ERR(tmp)) {
fd = get_unused_fd();
if (fd >= 0) {
struct file *f = filp_open(tmp, flags, mode);
- error = PTR_ERR(f);
- if (IS_ERR(f))
- goto out_error;
- fd_install(fd, f);
+ if (IS_ERR(f)) {
+ put_unused_fd(fd);
+ fd = PTR_ERR(f);
+ } else {
+ fd_install(fd, f);
+ }
}
-out:
putname(tmp);
}
return fd;
-
-out_error:
- put_unused_fd(fd);
- fd = error;
- goto out;
}
EXPORT_SYMBOL_GPL(sys_open);
@@ -980,23 +979,15 @@ asmlinkage long sys_creat(const char __user * pathname, int mode)
*/
int filp_close(struct file *filp, fl_owner_t id)
{
- int retval;
-
- /* Report and clear outstanding errors */
- retval = filp->f_error;
- if (retval)
- filp->f_error = 0;
+ int retval = 0;
if (!file_count(filp)) {
printk(KERN_ERR "VFS: Close: file count is 0\n");
- return retval;
+ return 0;
}
- if (filp->f_op && filp->f_op->flush) {
- int err = filp->f_op->flush(filp);
- if (!retval)
- retval = err;
- }
+ if (filp->f_op && filp->f_op->flush)
+ retval = filp->f_op->flush(filp);
dnotify_flush(filp, id);
locks_remove_posix(filp, id);
diff --git a/fs/partitions/Makefile b/fs/partitions/Makefile
index 4c83c17969e..66d5cc26faf 100644
--- a/fs/partitions/Makefile
+++ b/fs/partitions/Makefile
@@ -17,4 +17,3 @@ obj-$(CONFIG_SUN_PARTITION) += sun.o
obj-$(CONFIG_ULTRIX_PARTITION) += ultrix.o
obj-$(CONFIG_IBM_PARTITION) += ibm.o
obj-$(CONFIG_EFI_PARTITION) += efi.o
-obj-$(CONFIG_NEC98_PARTITION) += nec98.o msdos.o
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 2cab98a9a62..77e178f1316 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -79,9 +79,6 @@ static int (*check_part[])(struct parsed_partitions *, struct block_device *) =
#ifdef CONFIG_LDM_PARTITION
ldm_partition, /* this must come before msdos */
#endif
-#ifdef CONFIG_NEC98_PARTITION
- nec98_partition, /* must be come before `msdos_partition' */
-#endif
#ifdef CONFIG_MSDOS_PARTITION
msdos_partition,
#endif
diff --git a/fs/partitions/check.h b/fs/partitions/check.h
index 43adcc68e47..17ae8ecd9e8 100644
--- a/fs/partitions/check.h
+++ b/fs/partitions/check.h
@@ -30,7 +30,3 @@ put_partition(struct parsed_partitions *p, int n, sector_t from, sector_t size)
extern int warn_no_part;
-extern void parse_bsd(struct parsed_partitions *state,
- struct block_device *bdev, u32 offset, u32 size,
- int origin, char *flavour, int max_partitions);
-
diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c
index 584a27b2bbd..9935d254186 100644
--- a/fs/partitions/msdos.c
+++ b/fs/partitions/msdos.c
@@ -202,12 +202,12 @@ parse_solaris_x86(struct parsed_partitions *state, struct block_device *bdev,
#endif
}
-#if defined(CONFIG_BSD_DISKLABEL) || defined(CONFIG_NEC98_PARTITION)
+#if defined(CONFIG_BSD_DISKLABEL)
/*
* Create devices for BSD partitions listed in a disklabel, under a
* dos-like partition. See parse_extended() for more information.
*/
-void
+static void
parse_bsd(struct parsed_partitions *state, struct block_device *bdev,
u32 offset, u32 size, int origin, char *flavour,
int max_partitions)
diff --git a/fs/proc/Makefile b/fs/proc/Makefile
index 738b9b60293..7431d7ba2d0 100644
--- a/fs/proc/Makefile
+++ b/fs/proc/Makefile
@@ -11,4 +11,5 @@ proc-y += inode.o root.o base.o generic.o array.o \
kmsg.o proc_tty.o proc_misc.o
proc-$(CONFIG_PROC_KCORE) += kcore.o
+proc-$(CONFIG_PROC_VMCORE) += vmcore.o
proc-$(CONFIG_PROC_DEVICETREE) += proc_devtree.o
diff --git a/fs/proc/base.c b/fs/proc/base.c
index e31903aadd9..ace151fa487 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -314,7 +314,7 @@ static int may_ptrace_attach(struct task_struct *task)
(current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
goto out;
rmb();
- if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE))
+ if (task->mm->dumpable != 1 && !capable(CAP_SYS_PTRACE))
goto out;
if (security_ptrace(current, task))
goto out;
@@ -1113,7 +1113,9 @@ static int task_dumpable(struct task_struct *task)
if (mm)
dumpable = mm->dumpable;
task_unlock(task);
- return dumpable;
+ if(dumpable == 1)
+ return 1;
+ return 0;
}
diff --git a/fs/proc/mmu.c b/fs/proc/mmu.c
index a7041038ad5..25d2d9c6e32 100644
--- a/fs/proc/mmu.c
+++ b/fs/proc/mmu.c
@@ -50,13 +50,23 @@ void get_vmalloc_info(struct vmalloc_info *vmi)
read_lock(&vmlist_lock);
for (vma = vmlist; vma; vma = vma->next) {
+ unsigned long addr = (unsigned long) vma->addr;
+
+ /*
+ * Some archs keep another range for modules in vmlist
+ */
+ if (addr < VMALLOC_START)
+ continue;
+ if (addr >= VMALLOC_END)
+ break;
+
vmi->used += vma->size;
- free_area_size = (unsigned long) vma->addr - prev_end;
+ free_area_size = addr - prev_end;
if (vmi->largest_chunk < free_area_size)
vmi->largest_chunk = free_area_size;
- prev_end = vma->size + (unsigned long) vma->addr;
+ prev_end = vma->size + addr;
}
if (VMALLOC_END - prev_end > vmi->largest_chunk)
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
index 67423c696c0..6fd57f15419 100644
--- a/fs/proc/proc_devtree.c
+++ b/fs/proc/proc_devtree.c
@@ -12,15 +12,8 @@
#include <asm/uaccess.h>
#ifndef HAVE_ARCH_DEVTREE_FIXUPS
-static inline void set_node_proc_entry(struct device_node *np, struct proc_dir_entry *de)
-{
-}
-
-static void inline set_node_name_link(struct device_node *np, struct proc_dir_entry *de)
-{
-}
-
-static void inline set_node_addr_link(struct device_node *np, struct proc_dir_entry *de)
+static inline void set_node_proc_entry(struct device_node *np,
+ struct proc_dir_entry *de)
{
}
#endif
@@ -58,89 +51,67 @@ static int property_read_proc(char *page, char **start, off_t off,
/*
* Process a node, adding entries for its children and its properties.
*/
-void proc_device_tree_add_node(struct device_node *np, struct proc_dir_entry *de)
+void proc_device_tree_add_node(struct device_node *np,
+ struct proc_dir_entry *de)
{
struct property *pp;
struct proc_dir_entry *ent;
- struct device_node *child, *sib;
- const char *p, *at;
- int l;
- struct proc_dir_entry *list, **lastp, *al;
+ struct device_node *child;
+ struct proc_dir_entry *list = NULL, **lastp;
+ const char *p;
set_node_proc_entry(np, de);
lastp = &list;
- for (pp = np->properties; pp != 0; pp = pp->next) {
- /*
- * Unfortunately proc_register puts each new entry
- * at the beginning of the list. So we rearrange them.
- */
- ent = create_proc_read_entry(pp->name, strncmp(pp->name, "security-", 9) ?
- S_IRUGO : S_IRUSR, de, property_read_proc, pp);
- if (ent == 0)
- break;
- if (!strncmp(pp->name, "security-", 9))
- ent->size = 0; /* don't leak number of password chars */
- else
- ent->size = pp->length;
- *lastp = ent;
- lastp = &ent->next;
- }
- child = NULL;
- while ((child = of_get_next_child(np, child))) {
+ for (child = NULL; (child = of_get_next_child(np, child));) {
p = strrchr(child->full_name, '/');
if (!p)
p = child->full_name;
else
++p;
- /* chop off '@0' if the name ends with that */
- l = strlen(p);
- if (l > 2 && p[l-2] == '@' && p[l-1] == '0')
- l -= 2;
ent = proc_mkdir(p, de);
if (ent == 0)
break;
*lastp = ent;
+ ent->next = NULL;
lastp = &ent->next;
proc_device_tree_add_node(child, ent);
-
- /*
- * If we left the address part on the name, consider
- * adding symlinks from the name and address parts.
- */
- if (p[l] != 0 || (at = strchr(p, '@')) == 0)
- continue;
-
+ }
+ of_node_put(child);
+ for (pp = np->properties; pp != 0; pp = pp->next) {
/*
- * If this is the first node with a given name property,
- * add a symlink with the name property as its name.
+ * Yet another Apple device-tree bogosity: on some machines,
+ * they have properties & nodes with the same name. Those
+ * properties are quite unimportant for us though, thus we
+ * simply "skip" them here, but we do have to check.
*/
- sib = NULL;
- while ((sib = of_get_next_child(np, sib)) && sib != child)
- if (sib->name && strcmp(sib->name, child->name) == 0)
- break;
- if (sib == child && strncmp(p, child->name, l) != 0) {
- al = proc_symlink(child->name, de, ent->name);
- if (al == 0) {
- of_node_put(sib);
+ for (ent = list; ent != NULL; ent = ent->next)
+ if (!strcmp(ent->name, pp->name))
break;
- }
- set_node_name_link(child, al);
- *lastp = al;
- lastp = &al->next;
+ if (ent != NULL) {
+ printk(KERN_WARNING "device-tree: property \"%s\" name"
+ " conflicts with node in %s\n", pp->name,
+ np->full_name);
+ continue;
}
- of_node_put(sib);
+
/*
- * Add another directory with the @address part as its name.
+ * Unfortunately proc_register puts each new entry
+ * at the beginning of the list. So we rearrange them.
*/
- al = proc_symlink(at, de, ent->name);
- if (al == 0)
+ ent = create_proc_read_entry(pp->name,
+ strncmp(pp->name, "security-", 9)
+ ? S_IRUGO : S_IRUSR, de,
+ property_read_proc, pp);
+ if (ent == 0)
break;
- set_node_addr_link(child, al);
- *lastp = al;
- lastp = &al->next;
+ if (!strncmp(pp->name, "security-", 9))
+ ent->size = 0; /* don't leak number of password chars */
+ else
+ ent->size = pp->length;
+ ent->next = NULL;
+ *lastp = ent;
+ lastp = &ent->next;
}
- of_node_put(child);
- *lastp = NULL;
de->subdir = list;
}
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index a60a3b3d8a7..a3453555a94 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -44,6 +44,7 @@
#include <linux/jiffies.h>
#include <linux/sysrq.h>
#include <linux/vmalloc.h>
+#include <linux/crash_dump.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/io.h>
@@ -219,6 +220,19 @@ static struct file_operations fragmentation_file_operations = {
.release = seq_release,
};
+extern struct seq_operations zoneinfo_op;
+static int zoneinfo_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &zoneinfo_op);
+}
+
+static struct file_operations proc_zoneinfo_file_operations = {
+ .open = zoneinfo_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
static int version_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
@@ -438,7 +452,7 @@ static int devices_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
int len = get_chrdev_list(page);
- len += get_blkdev_list(page+len);
+ len += get_blkdev_list(page+len, len);
return proc_calc_metrics(page, start, off, count, eof, len);
}
@@ -589,6 +603,7 @@ void __init proc_misc_init(void)
create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations);
create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations);
+ create_seq_entry("zoneinfo",S_IRUGO, &proc_zoneinfo_file_operations);
create_seq_entry("diskstats", 0, &proc_diskstats_operations);
#ifdef CONFIG_MODULES
create_seq_entry("modules", 0, &proc_modules_operations);
@@ -604,6 +619,11 @@ void __init proc_misc_init(void)
(size_t)high_memory - PAGE_OFFSET + PAGE_SIZE;
}
#endif
+#ifdef CONFIG_PROC_VMCORE
+ proc_vmcore = create_proc_entry("vmcore", S_IRUSR, NULL);
+ if (proc_vmcore)
+ proc_vmcore->proc_fops = &proc_vmcore_operations;
+#endif
#ifdef CONFIG_MAGIC_SYSRQ
entry = create_proc_entry("sysrq-trigger", S_IWUSR, NULL);
if (entry)
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c
new file mode 100644
index 00000000000..3b2e7b69e63
--- /dev/null
+++ b/fs/proc/vmcore.c
@@ -0,0 +1,669 @@
+/*
+ * fs/proc/vmcore.c Interface for accessing the crash
+ * dump from the system's previous life.
+ * Heavily borrowed from fs/proc/kcore.c
+ * Created by: Hariprasad Nellitheertha (hari@in.ibm.com)
+ * Copyright (C) IBM Corporation, 2004. All rights reserved
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/proc_fs.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/elf.h>
+#include <linux/elfcore.h>
+#include <linux/proc_fs.h>
+#include <linux/highmem.h>
+#include <linux/bootmem.h>
+#include <linux/init.h>
+#include <linux/crash_dump.h>
+#include <linux/list.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+/* List representing chunks of contiguous memory areas and their offsets in
+ * vmcore file.
+ */
+static LIST_HEAD(vmcore_list);
+
+/* Stores the pointer to the buffer containing kernel elf core headers. */
+static char *elfcorebuf;
+static size_t elfcorebuf_sz;
+
+/* Total size of vmcore file. */
+static u64 vmcore_size;
+
+struct proc_dir_entry *proc_vmcore = NULL;
+
+/* Reads a page from the oldmem device from given offset. */
+static ssize_t read_from_oldmem(char *buf, size_t count,
+ loff_t *ppos, int userbuf)
+{
+ unsigned long pfn, offset;
+ size_t nr_bytes;
+ ssize_t read = 0, tmp;
+
+ if (!count)
+ return 0;
+
+ offset = (unsigned long)(*ppos % PAGE_SIZE);
+ pfn = (unsigned long)(*ppos / PAGE_SIZE);
+ if (pfn > saved_max_pfn)
+ return -EINVAL;
+
+ do {
+ if (count > (PAGE_SIZE - offset))
+ nr_bytes = PAGE_SIZE - offset;
+ else
+ nr_bytes = count;
+
+ tmp = copy_oldmem_page(pfn, buf, nr_bytes, offset, userbuf);
+ if (tmp < 0)
+ return tmp;
+ *ppos += nr_bytes;
+ count -= nr_bytes;
+ buf += nr_bytes;
+ read += nr_bytes;
+ ++pfn;
+ offset = 0;
+ } while (count);
+
+ return read;
+}
+
+/* Maps vmcore file offset to respective physical address in memroy. */
+static u64 map_offset_to_paddr(loff_t offset, struct list_head *vc_list,
+ struct vmcore **m_ptr)
+{
+ struct vmcore *m;
+ u64 paddr;
+
+ list_for_each_entry(m, vc_list, list) {
+ u64 start, end;
+ start = m->offset;
+ end = m->offset + m->size - 1;
+ if (offset >= start && offset <= end) {
+ paddr = m->paddr + offset - start;
+ *m_ptr = m;
+ return paddr;
+ }
+ }
+ *m_ptr = NULL;
+ return 0;
+}
+
+/* Read from the ELF header and then the crash dump. On error, negative value is
+ * returned otherwise number of bytes read are returned.
+ */
+static ssize_t read_vmcore(struct file *file, char __user *buffer,
+ size_t buflen, loff_t *fpos)
+{
+ ssize_t acc = 0, tmp;
+ size_t tsz, nr_bytes;
+ u64 start;
+ struct vmcore *curr_m = NULL;
+
+ if (buflen == 0 || *fpos >= vmcore_size)
+ return 0;
+
+ /* trim buflen to not go beyond EOF */
+ if (buflen > vmcore_size - *fpos)
+ buflen = vmcore_size - *fpos;
+
+ /* Read ELF core header */
+ if (*fpos < elfcorebuf_sz) {
+ tsz = elfcorebuf_sz - *fpos;
+ if (buflen < tsz)
+ tsz = buflen;
+ if (copy_to_user(buffer, elfcorebuf + *fpos, tsz))
+ return -EFAULT;
+ buflen -= tsz;
+ *fpos += tsz;
+ buffer += tsz;
+ acc += tsz;
+
+ /* leave now if filled buffer already */
+ if (buflen == 0)
+ return acc;
+ }
+
+ start = map_offset_to_paddr(*fpos, &vmcore_list, &curr_m);
+ if (!curr_m)
+ return -EINVAL;
+ if ((tsz = (PAGE_SIZE - (start & ~PAGE_MASK))) > buflen)
+ tsz = buflen;
+
+ /* Calculate left bytes in current memory segment. */
+ nr_bytes = (curr_m->size - (start - curr_m->paddr));
+ if (tsz > nr_bytes)
+ tsz = nr_bytes;
+
+ while (buflen) {
+ tmp = read_from_oldmem(buffer, tsz, &start, 1);
+ if (tmp < 0)
+ return tmp;
+ buflen -= tsz;
+ *fpos += tsz;
+ buffer += tsz;
+ acc += tsz;
+ if (start >= (curr_m->paddr + curr_m->size)) {
+ if (curr_m->list.next == &vmcore_list)
+ return acc; /*EOF*/
+ curr_m = list_entry(curr_m->list.next,
+ struct vmcore, list);
+ start = curr_m->paddr;
+ }
+ if ((tsz = (PAGE_SIZE - (start & ~PAGE_MASK))) > buflen)
+ tsz = buflen;
+ /* Calculate left bytes in current memory segment. */
+ nr_bytes = (curr_m->size - (start - curr_m->paddr));
+ if (tsz > nr_bytes)
+ tsz = nr_bytes;
+ }
+ return acc;
+}
+
+static int open_vmcore(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+struct file_operations proc_vmcore_operations = {
+ .read = read_vmcore,
+ .open = open_vmcore,
+};
+
+static struct vmcore* __init get_new_element(void)
+{
+ struct vmcore *p;
+
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if (p)
+ memset(p, 0, sizeof(*p));
+ return p;
+}
+
+static u64 __init get_vmcore_size_elf64(char *elfptr)
+{
+ int i;
+ u64 size;
+ Elf64_Ehdr *ehdr_ptr;
+ Elf64_Phdr *phdr_ptr;
+
+ ehdr_ptr = (Elf64_Ehdr *)elfptr;
+ phdr_ptr = (Elf64_Phdr*)(elfptr + sizeof(Elf64_Ehdr));
+ size = sizeof(Elf64_Ehdr) + ((ehdr_ptr->e_phnum) * sizeof(Elf64_Phdr));
+ for (i = 0; i < ehdr_ptr->e_phnum; i++) {
+ size += phdr_ptr->p_memsz;
+ phdr_ptr++;
+ }
+ return size;
+}
+
+static u64 __init get_vmcore_size_elf32(char *elfptr)
+{
+ int i;
+ u64 size;
+ Elf32_Ehdr *ehdr_ptr;
+ Elf32_Phdr *phdr_ptr;
+
+ ehdr_ptr = (Elf32_Ehdr *)elfptr;
+ phdr_ptr = (Elf32_Phdr*)(elfptr + sizeof(Elf32_Ehdr));
+ size = sizeof(Elf32_Ehdr) + ((ehdr_ptr->e_phnum) * sizeof(Elf32_Phdr));
+ for (i = 0; i < ehdr_ptr->e_phnum; i++) {
+ size += phdr_ptr->p_memsz;
+ phdr_ptr++;
+ }
+ return size;
+}
+
+/* Merges all the PT_NOTE headers into one. */
+static int __init merge_note_headers_elf64(char *elfptr, size_t *elfsz,
+ struct list_head *vc_list)
+{
+ int i, nr_ptnote=0, rc=0;
+ char *tmp;
+ Elf64_Ehdr *ehdr_ptr;
+ Elf64_Phdr phdr, *phdr_ptr;
+ Elf64_Nhdr *nhdr_ptr;
+ u64 phdr_sz = 0, note_off;
+
+ ehdr_ptr = (Elf64_Ehdr *)elfptr;
+ phdr_ptr = (Elf64_Phdr*)(elfptr + sizeof(Elf64_Ehdr));
+ for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
+ int j;
+ void *notes_section;
+ struct vmcore *new;
+ u64 offset, max_sz, sz, real_sz = 0;
+ if (phdr_ptr->p_type != PT_NOTE)
+ continue;
+ nr_ptnote++;
+ max_sz = phdr_ptr->p_memsz;
+ offset = phdr_ptr->p_offset;
+ notes_section = kmalloc(max_sz, GFP_KERNEL);
+ if (!notes_section)
+ return -ENOMEM;
+ rc = read_from_oldmem(notes_section, max_sz, &offset, 0);
+ if (rc < 0) {
+ kfree(notes_section);
+ return rc;
+ }
+ nhdr_ptr = notes_section;
+ for (j = 0; j < max_sz; j += sz) {
+ if (nhdr_ptr->n_namesz == 0)
+ break;
+ sz = sizeof(Elf64_Nhdr) +
+ ((nhdr_ptr->n_namesz + 3) & ~3) +
+ ((nhdr_ptr->n_descsz + 3) & ~3);
+ real_sz += sz;
+ nhdr_ptr = (Elf64_Nhdr*)((char*)nhdr_ptr + sz);
+ }
+
+ /* Add this contiguous chunk of notes section to vmcore list.*/
+ new = get_new_element();
+ if (!new) {
+ kfree(notes_section);
+ return -ENOMEM;
+ }
+ new->paddr = phdr_ptr->p_offset;
+ new->size = real_sz;
+ list_add_tail(&new->list, vc_list);
+ phdr_sz += real_sz;
+ kfree(notes_section);
+ }
+
+ /* Prepare merged PT_NOTE program header. */
+ phdr.p_type = PT_NOTE;
+ phdr.p_flags = 0;
+ note_off = sizeof(Elf64_Ehdr) +
+ (ehdr_ptr->e_phnum - nr_ptnote +1) * sizeof(Elf64_Phdr);
+ phdr.p_offset = note_off;
+ phdr.p_vaddr = phdr.p_paddr = 0;
+ phdr.p_filesz = phdr.p_memsz = phdr_sz;
+ phdr.p_align = 0;
+
+ /* Add merged PT_NOTE program header*/
+ tmp = elfptr + sizeof(Elf64_Ehdr);
+ memcpy(tmp, &phdr, sizeof(phdr));
+ tmp += sizeof(phdr);
+
+ /* Remove unwanted PT_NOTE program headers. */
+ i = (nr_ptnote - 1) * sizeof(Elf64_Phdr);
+ *elfsz = *elfsz - i;
+ memmove(tmp, tmp+i, ((*elfsz)-sizeof(Elf64_Ehdr)-sizeof(Elf64_Phdr)));
+
+ /* Modify e_phnum to reflect merged headers. */
+ ehdr_ptr->e_phnum = ehdr_ptr->e_phnum - nr_ptnote + 1;
+
+ return 0;
+}
+
+/* Merges all the PT_NOTE headers into one. */
+static int __init merge_note_headers_elf32(char *elfptr, size_t *elfsz,
+ struct list_head *vc_list)
+{
+ int i, nr_ptnote=0, rc=0;
+ char *tmp;
+ Elf32_Ehdr *ehdr_ptr;
+ Elf32_Phdr phdr, *phdr_ptr;
+ Elf32_Nhdr *nhdr_ptr;
+ u64 phdr_sz = 0, note_off;
+
+ ehdr_ptr = (Elf32_Ehdr *)elfptr;
+ phdr_ptr = (Elf32_Phdr*)(elfptr + sizeof(Elf32_Ehdr));
+ for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
+ int j;
+ void *notes_section;
+ struct vmcore *new;
+ u64 offset, max_sz, sz, real_sz = 0;
+ if (phdr_ptr->p_type != PT_NOTE)
+ continue;
+ nr_ptnote++;
+ max_sz = phdr_ptr->p_memsz;
+ offset = phdr_ptr->p_offset;
+ notes_section = kmalloc(max_sz, GFP_KERNEL);
+ if (!notes_section)
+ return -ENOMEM;
+ rc = read_from_oldmem(notes_section, max_sz, &offset, 0);
+ if (rc < 0) {
+ kfree(notes_section);
+ return rc;
+ }
+ nhdr_ptr = notes_section;
+ for (j = 0; j < max_sz; j += sz) {
+ if (nhdr_ptr->n_namesz == 0)
+ break;
+ sz = sizeof(Elf32_Nhdr) +
+ ((nhdr_ptr->n_namesz + 3) & ~3) +
+ ((nhdr_ptr->n_descsz + 3) & ~3);
+ real_sz += sz;
+ nhdr_ptr = (Elf32_Nhdr*)((char*)nhdr_ptr + sz);
+ }
+
+ /* Add this contiguous chunk of notes section to vmcore list.*/
+ new = get_new_element();
+ if (!new) {
+ kfree(notes_section);
+ return -ENOMEM;
+ }
+ new->paddr = phdr_ptr->p_offset;
+ new->size = real_sz;
+ list_add_tail(&new->list, vc_list);
+ phdr_sz += real_sz;
+ kfree(notes_section);
+ }
+
+ /* Prepare merged PT_NOTE program header. */
+ phdr.p_type = PT_NOTE;
+ phdr.p_flags = 0;
+ note_off = sizeof(Elf32_Ehdr) +
+ (ehdr_ptr->e_phnum - nr_ptnote +1) * sizeof(Elf32_Phdr);
+ phdr.p_offset = note_off;
+ phdr.p_vaddr = phdr.p_paddr = 0;
+ phdr.p_filesz = phdr.p_memsz = phdr_sz;
+ phdr.p_align = 0;
+
+ /* Add merged PT_NOTE program header*/
+ tmp = elfptr + sizeof(Elf32_Ehdr);
+ memcpy(tmp, &phdr, sizeof(phdr));
+ tmp += sizeof(phdr);
+
+ /* Remove unwanted PT_NOTE program headers. */
+ i = (nr_ptnote - 1) * sizeof(Elf32_Phdr);
+ *elfsz = *elfsz - i;
+ memmove(tmp, tmp+i, ((*elfsz)-sizeof(Elf32_Ehdr)-sizeof(Elf32_Phdr)));
+
+ /* Modify e_phnum to reflect merged headers. */
+ ehdr_ptr->e_phnum = ehdr_ptr->e_phnum - nr_ptnote + 1;
+
+ return 0;
+}
+
+/* Add memory chunks represented by program headers to vmcore list. Also update
+ * the new offset fields of exported program headers. */
+static int __init process_ptload_program_headers_elf64(char *elfptr,
+ size_t elfsz,
+ struct list_head *vc_list)
+{
+ int i;
+ Elf64_Ehdr *ehdr_ptr;
+ Elf64_Phdr *phdr_ptr;
+ loff_t vmcore_off;
+ struct vmcore *new;
+
+ ehdr_ptr = (Elf64_Ehdr *)elfptr;
+ phdr_ptr = (Elf64_Phdr*)(elfptr + sizeof(Elf64_Ehdr)); /* PT_NOTE hdr */
+
+ /* First program header is PT_NOTE header. */
+ vmcore_off = sizeof(Elf64_Ehdr) +
+ (ehdr_ptr->e_phnum) * sizeof(Elf64_Phdr) +
+ phdr_ptr->p_memsz; /* Note sections */
+
+ for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
+ if (phdr_ptr->p_type != PT_LOAD)
+ continue;
+
+ /* Add this contiguous chunk of memory to vmcore list.*/
+ new = get_new_element();
+ if (!new)
+ return -ENOMEM;
+ new->paddr = phdr_ptr->p_offset;
+ new->size = phdr_ptr->p_memsz;
+ list_add_tail(&new->list, vc_list);
+
+ /* Update the program header offset. */
+ phdr_ptr->p_offset = vmcore_off;
+ vmcore_off = vmcore_off + phdr_ptr->p_memsz;
+ }
+ return 0;
+}
+
+static int __init process_ptload_program_headers_elf32(char *elfptr,
+ size_t elfsz,
+ struct list_head *vc_list)
+{
+ int i;
+ Elf32_Ehdr *ehdr_ptr;
+ Elf32_Phdr *phdr_ptr;
+ loff_t vmcore_off;
+ struct vmcore *new;
+
+ ehdr_ptr = (Elf32_Ehdr *)elfptr;
+ phdr_ptr = (Elf32_Phdr*)(elfptr + sizeof(Elf32_Ehdr)); /* PT_NOTE hdr */
+
+ /* First program header is PT_NOTE header. */
+ vmcore_off = sizeof(Elf32_Ehdr) +
+ (ehdr_ptr->e_phnum) * sizeof(Elf32_Phdr) +
+ phdr_ptr->p_memsz; /* Note sections */
+
+ for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
+ if (phdr_ptr->p_type != PT_LOAD)
+ continue;
+
+ /* Add this contiguous chunk of memory to vmcore list.*/
+ new = get_new_element();
+ if (!new)
+ return -ENOMEM;
+ new->paddr = phdr_ptr->p_offset;
+ new->size = phdr_ptr->p_memsz;
+ list_add_tail(&new->list, vc_list);
+
+ /* Update the program header offset */
+ phdr_ptr->p_offset = vmcore_off;
+ vmcore_off = vmcore_off + phdr_ptr->p_memsz;
+ }
+ return 0;
+}
+
+/* Sets offset fields of vmcore elements. */
+static void __init set_vmcore_list_offsets_elf64(char *elfptr,
+ struct list_head *vc_list)
+{
+ loff_t vmcore_off;
+ Elf64_Ehdr *ehdr_ptr;
+ struct vmcore *m;
+
+ ehdr_ptr = (Elf64_Ehdr *)elfptr;
+
+ /* Skip Elf header and program headers. */
+ vmcore_off = sizeof(Elf64_Ehdr) +
+ (ehdr_ptr->e_phnum) * sizeof(Elf64_Phdr);
+
+ list_for_each_entry(m, vc_list, list) {
+ m->offset = vmcore_off;
+ vmcore_off += m->size;
+ }
+}
+
+/* Sets offset fields of vmcore elements. */
+static void __init set_vmcore_list_offsets_elf32(char *elfptr,
+ struct list_head *vc_list)
+{
+ loff_t vmcore_off;
+ Elf32_Ehdr *ehdr_ptr;
+ struct vmcore *m;
+
+ ehdr_ptr = (Elf32_Ehdr *)elfptr;
+
+ /* Skip Elf header and program headers. */
+ vmcore_off = sizeof(Elf32_Ehdr) +
+ (ehdr_ptr->e_phnum) * sizeof(Elf32_Phdr);
+
+ list_for_each_entry(m, vc_list, list) {
+ m->offset = vmcore_off;
+ vmcore_off += m->size;
+ }
+}
+
+static int __init parse_crash_elf64_headers(void)
+{
+ int rc=0;
+ Elf64_Ehdr ehdr;
+ u64 addr;
+
+ addr = elfcorehdr_addr;
+
+ /* Read Elf header */
+ rc = read_from_oldmem((char*)&ehdr, sizeof(Elf64_Ehdr), &addr, 0);
+ if (rc < 0)
+ return rc;
+
+ /* Do some basic Verification. */
+ if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
+ (ehdr.e_type != ET_CORE) ||
+ !elf_check_arch(&ehdr) ||
+ ehdr.e_ident[EI_CLASS] != ELFCLASS64 ||
+ ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
+ ehdr.e_version != EV_CURRENT ||
+ ehdr.e_ehsize != sizeof(Elf64_Ehdr) ||
+ ehdr.e_phentsize != sizeof(Elf64_Phdr) ||
+ ehdr.e_phnum == 0) {
+ printk(KERN_WARNING "Warning: Core image elf header is not"
+ "sane\n");
+ return -EINVAL;
+ }
+
+ /* Read in all elf headers. */
+ elfcorebuf_sz = sizeof(Elf64_Ehdr) + ehdr.e_phnum * sizeof(Elf64_Phdr);
+ elfcorebuf = kmalloc(elfcorebuf_sz, GFP_KERNEL);
+ if (!elfcorebuf)
+ return -ENOMEM;
+ addr = elfcorehdr_addr;
+ rc = read_from_oldmem(elfcorebuf, elfcorebuf_sz, &addr, 0);
+ if (rc < 0) {
+ kfree(elfcorebuf);
+ return rc;
+ }
+
+ /* Merge all PT_NOTE headers into one. */
+ rc = merge_note_headers_elf64(elfcorebuf, &elfcorebuf_sz, &vmcore_list);
+ if (rc) {
+ kfree(elfcorebuf);
+ return rc;
+ }
+ rc = process_ptload_program_headers_elf64(elfcorebuf, elfcorebuf_sz,
+ &vmcore_list);
+ if (rc) {
+ kfree(elfcorebuf);
+ return rc;
+ }
+ set_vmcore_list_offsets_elf64(elfcorebuf, &vmcore_list);
+ return 0;
+}
+
+static int __init parse_crash_elf32_headers(void)
+{
+ int rc=0;
+ Elf32_Ehdr ehdr;
+ u64 addr;
+
+ addr = elfcorehdr_addr;
+
+ /* Read Elf header */
+ rc = read_from_oldmem((char*)&ehdr, sizeof(Elf32_Ehdr), &addr, 0);
+ if (rc < 0)
+ return rc;
+
+ /* Do some basic Verification. */
+ if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
+ (ehdr.e_type != ET_CORE) ||
+ !elf_check_arch(&ehdr) ||
+ ehdr.e_ident[EI_CLASS] != ELFCLASS32||
+ ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
+ ehdr.e_version != EV_CURRENT ||
+ ehdr.e_ehsize != sizeof(Elf32_Ehdr) ||
+ ehdr.e_phentsize != sizeof(Elf32_Phdr) ||
+ ehdr.e_phnum == 0) {
+ printk(KERN_WARNING "Warning: Core image elf header is not"
+ "sane\n");
+ return -EINVAL;
+ }
+
+ /* Read in all elf headers. */
+ elfcorebuf_sz = sizeof(Elf32_Ehdr) + ehdr.e_phnum * sizeof(Elf32_Phdr);
+ elfcorebuf = kmalloc(elfcorebuf_sz, GFP_KERNEL);
+ if (!elfcorebuf)
+ return -ENOMEM;
+ addr = elfcorehdr_addr;
+ rc = read_from_oldmem(elfcorebuf, elfcorebuf_sz, &addr, 0);
+ if (rc < 0) {
+ kfree(elfcorebuf);
+ return rc;
+ }
+
+ /* Merge all PT_NOTE headers into one. */
+ rc = merge_note_headers_elf32(elfcorebuf, &elfcorebuf_sz, &vmcore_list);
+ if (rc) {
+ kfree(elfcorebuf);
+ return rc;
+ }
+ rc = process_ptload_program_headers_elf32(elfcorebuf, elfcorebuf_sz,
+ &vmcore_list);
+ if (rc) {
+ kfree(elfcorebuf);
+ return rc;
+ }
+ set_vmcore_list_offsets_elf32(elfcorebuf, &vmcore_list);
+ return 0;
+}
+
+static int __init parse_crash_elf_headers(void)
+{
+ unsigned char e_ident[EI_NIDENT];
+ u64 addr;
+ int rc=0;
+
+ addr = elfcorehdr_addr;
+ rc = read_from_oldmem(e_ident, EI_NIDENT, &addr, 0);
+ if (rc < 0)
+ return rc;
+ if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) {
+ printk(KERN_WARNING "Warning: Core image elf header"
+ " not found\n");
+ return -EINVAL;
+ }
+
+ if (e_ident[EI_CLASS] == ELFCLASS64) {
+ rc = parse_crash_elf64_headers();
+ if (rc)
+ return rc;
+
+ /* Determine vmcore size. */
+ vmcore_size = get_vmcore_size_elf64(elfcorebuf);
+ } else if (e_ident[EI_CLASS] == ELFCLASS32) {
+ rc = parse_crash_elf32_headers();
+ if (rc)
+ return rc;
+
+ /* Determine vmcore size. */
+ vmcore_size = get_vmcore_size_elf32(elfcorebuf);
+ } else {
+ printk(KERN_WARNING "Warning: Core image elf header is not"
+ " sane\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/* Init function for vmcore module. */
+static int __init vmcore_init(void)
+{
+ int rc = 0;
+
+ /* If elfcorehdr= has been passed in cmdline, then capture the dump.*/
+ if (!(elfcorehdr_addr < ELFCORE_ADDR_MAX))
+ return rc;
+ rc = parse_crash_elf_headers();
+ if (rc) {
+ printk(KERN_WARNING "Kdump: vmcore not initialized\n");
+ return rc;
+ }
+
+ /* Initialize /proc/vmcore size if proc is already up. */
+ if (proc_vmcore)
+ proc_vmcore->size = vmcore_size;
+ return 0;
+}
+module_init(vmcore_init)
diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c
index cd66147cca0..7a8f5595c26 100644
--- a/fs/qnx4/dir.c
+++ b/fs/qnx4/dir.c
@@ -61,7 +61,7 @@ static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir)
ino = blknum * QNX4_INODES_PER_BLOCK + ix - 1;
else {
le = (struct qnx4_link_info*)de;
- ino = ( le->dl_inode_blk - 1 ) *
+ ino = ( le32_to_cpu(le->dl_inode_blk) - 1 ) *
QNX4_INODES_PER_BLOCK +
le->dl_inode_ndx;
}
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index aa92d6b76a9..b79162a3547 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -236,7 +236,7 @@ unsigned long qnx4_block_map( struct inode *inode, long iblock )
struct buffer_head *bh = NULL;
struct qnx4_xblk *xblk = NULL;
struct qnx4_inode_entry *qnx4_inode = qnx4_raw_inode(inode);
- qnx4_nxtnt_t nxtnt = le16_to_cpu(qnx4_inode->di_num_xtnts);
+ u16 nxtnt = le16_to_cpu(qnx4_inode->di_num_xtnts);
if ( iblock < le32_to_cpu(qnx4_inode->di_first_xtnt.xtnt_size) ) {
// iblock is in the first extent. This is easy.
@@ -372,7 +372,7 @@ static int qnx4_fill_super(struct super_block *s, void *data, int silent)
printk("qnx4: unable to read the superblock\n");
goto outnobh;
}
- if ( le32_to_cpu( *(__u32*)bh->b_data ) != QNX4_SUPER_MAGIC ) {
+ if ( le32_to_cpup((__le32*) bh->b_data) != QNX4_SUPER_MAGIC ) {
if (!silent)
printk("qnx4: wrong fsid in superblock.\n");
goto out;
diff --git a/fs/quota.c b/fs/quota.c
index 3f0333a51a2..f5d1cff5519 100644
--- a/fs/quota.c
+++ b/fs/quota.c
@@ -149,36 +149,6 @@ static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t
return error;
}
-static struct super_block *get_super_to_sync(int type)
-{
- struct list_head *head;
- int cnt, dirty;
-
-restart:
- spin_lock(&sb_lock);
- list_for_each(head, &super_blocks) {
- struct super_block *sb = list_entry(head, struct super_block, s_list);
-
- /* This test just improves performance so it needn't be reliable... */
- for (cnt = 0, dirty = 0; cnt < MAXQUOTAS; cnt++)
- if ((type == cnt || type == -1) && sb_has_quota_enabled(sb, cnt)
- && info_any_dirty(&sb_dqopt(sb)->info[cnt]))
- dirty = 1;
- if (!dirty)
- continue;
- sb->s_count++;
- spin_unlock(&sb_lock);
- down_read(&sb->s_umount);
- if (!sb->s_root) {
- drop_super(sb);
- goto restart;
- }
- return sb;
- }
- spin_unlock(&sb_lock);
- return NULL;
-}
-
static void quota_sync_sb(struct super_block *sb, int type)
{
int cnt;
@@ -219,17 +189,35 @@ static void quota_sync_sb(struct super_block *sb, int type)
void sync_dquots(struct super_block *sb, int type)
{
+ int cnt, dirty;
+
if (sb) {
if (sb->s_qcop->quota_sync)
quota_sync_sb(sb, type);
+ return;
}
- else {
- while ((sb = get_super_to_sync(type)) != NULL) {
- if (sb->s_qcop->quota_sync)
- quota_sync_sb(sb, type);
- drop_super(sb);
- }
+
+ spin_lock(&sb_lock);
+restart:
+ list_for_each_entry(sb, &super_blocks, s_list) {
+ /* This test just improves performance so it needn't be reliable... */
+ for (cnt = 0, dirty = 0; cnt < MAXQUOTAS; cnt++)
+ if ((type == cnt || type == -1) && sb_has_quota_enabled(sb, cnt)
+ && info_any_dirty(&sb_dqopt(sb)->info[cnt]))
+ dirty = 1;
+ if (!dirty)
+ continue;
+ sb->s_count++;
+ spin_unlock(&sb_lock);
+ down_read(&sb->s_umount);
+ if (sb->s_root && sb->s_qcop->quota_sync)
+ quota_sync_sb(sb, type);
+ up_read(&sb->s_umount);
+ spin_lock(&sb_lock);
+ if (__put_super_and_need_restart(sb))
+ goto restart;
}
+ spin_unlock(&sb_lock);
}
/* Copy parameters and call proper function */
diff --git a/fs/read_write.c b/fs/read_write.c
index c4c2bee373e..9292f5fa4d6 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -203,6 +203,16 @@ Einval:
return -EINVAL;
}
+static void wait_on_retry_sync_kiocb(struct kiocb *iocb)
+{
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ if (!kiocbIsKicked(iocb))
+ schedule();
+ else
+ kiocbClearKicked(iocb);
+ __set_current_state(TASK_RUNNING);
+}
+
ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
{
struct kiocb kiocb;
@@ -210,7 +220,10 @@ ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *pp
init_sync_kiocb(&kiocb, filp);
kiocb.ki_pos = *ppos;
- ret = filp->f_op->aio_read(&kiocb, buf, len, kiocb.ki_pos);
+ while (-EIOCBRETRY ==
+ (ret = filp->f_op->aio_read(&kiocb, buf, len, kiocb.ki_pos)))
+ wait_on_retry_sync_kiocb(&kiocb);
+
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&kiocb);
*ppos = kiocb.ki_pos;
@@ -258,7 +271,10 @@ ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, lof
init_sync_kiocb(&kiocb, filp);
kiocb.ki_pos = *ppos;
- ret = filp->f_op->aio_write(&kiocb, buf, len, kiocb.ki_pos);
+ while (-EIOCBRETRY ==
+ (ret = filp->f_op->aio_write(&kiocb, buf, len, kiocb.ki_pos)))
+ wait_on_retry_sync_kiocb(&kiocb);
+
if (-EIOCBQUEUED == ret)
ret = wait_on_sync_kiocb(&kiocb);
*ppos = kiocb.ki_pos;
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 2230afff187..12e91209544 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -201,7 +201,7 @@ static int reiserfs_allocate_blocks_for_region(
/* If we came here, it means we absolutely need to open a transaction,
since we need to allocate some blocks */
reiserfs_write_lock(inode->i_sb); // Journaling stuff and we need that.
- res = journal_begin(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS); // Wish I know if this number enough
+ res = journal_begin(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb)); // Wish I know if this number enough
if (res)
goto error_exit;
reiserfs_update_inode_transaction(inode) ;
@@ -576,7 +576,7 @@ error_exit:
int err;
// update any changes we made to blk count
reiserfs_update_sd(th, inode);
- err = journal_end(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS);
+ err = journal_end(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb));
if (err)
res = err;
}
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 2711dff1b7b..289d864fe73 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -28,7 +28,7 @@ static int reiserfs_prepare_write(struct file *f, struct page *page,
void reiserfs_delete_inode (struct inode * inode)
{
/* We need blocks for transaction + (user+group) quota update (possibly delete) */
- int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 * REISERFS_QUOTA_INIT_BLOCKS;
+ int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb);
struct reiserfs_transaction_handle th ;
reiserfs_write_lock(inode->i_sb);
@@ -254,6 +254,7 @@ static int _get_block_create_0 (struct inode * inode, long block,
char * p = NULL;
int chars;
int ret ;
+ int result ;
int done = 0 ;
unsigned long offset ;
@@ -262,10 +263,13 @@ static int _get_block_create_0 (struct inode * inode, long block,
(loff_t)block * inode->i_sb->s_blocksize + 1, TYPE_ANY, 3);
research:
- if (search_for_position_by_key (inode->i_sb, &key, &path) != POSITION_FOUND) {
+ result = search_for_position_by_key (inode->i_sb, &key, &path) ;
+ if (result != POSITION_FOUND) {
pathrelse (&path);
if (p)
kunmap(bh_result->b_page) ;
+ if (result == IO_ERROR)
+ return -EIO;
// We do not return -ENOENT if there is a hole but page is uptodate, because it means
// That there is some MMAPED data associated with it that is yet to be written to disk.
if ((args & GET_BLOCK_NO_HOLE) && !PageUptodate(bh_result->b_page) ) {
@@ -382,8 +386,9 @@ research:
// update key to look for the next piece
set_cpu_key_k_offset (&key, cpu_key_k_offset (&key) + chars);
- if (search_for_position_by_key (inode->i_sb, &key, &path) != POSITION_FOUND)
- // we read something from tail, even if now we got IO_ERROR
+ result = search_for_position_by_key (inode->i_sb, &key, &path);
+ if (result != POSITION_FOUND)
+ // i/o error most likely
break;
bh = get_last_bh (&path);
ih = get_ih (&path);
@@ -394,6 +399,10 @@ research:
finished:
pathrelse (&path);
+
+ if (result == IO_ERROR)
+ return -EIO;
+
/* this buffer has valid data, but isn't valid for io. mapping it to
* block #0 tells the rest of reiserfs it just has a tail in it
*/
@@ -591,7 +600,7 @@ int reiserfs_get_block (struct inode * inode, sector_t block,
XXX in practically impossible worst case direct2indirect()
can incur (much) more than 3 balancings.
quota update for user, group */
- int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS;
+ int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb);
int version;
int dangle = 1;
loff_t new_offset = (((loff_t)block) << inode->i_sb->s_blocksize_bits) + 1 ;
@@ -2796,12 +2805,15 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) {
if (!error) {
struct reiserfs_transaction_handle th;
+ int jbegin_count = 2*(REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb)+REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb))+2;
/* (user+group)*(old+new) structure - we count quota info and , inode write (sb, inode) */
- journal_begin(&th, inode->i_sb, 4*REISERFS_QUOTA_INIT_BLOCKS+2);
+ error = journal_begin(&th, inode->i_sb, jbegin_count);
+ if (error)
+ goto out;
error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0;
if (error) {
- journal_end(&th, inode->i_sb, 4*REISERFS_QUOTA_INIT_BLOCKS+2);
+ journal_end(&th, inode->i_sb, jbegin_count);
goto out;
}
/* Update corresponding info in inode so that everything is in
@@ -2811,7 +2823,7 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) {
if (attr->ia_valid & ATTR_GID)
inode->i_gid = attr->ia_gid;
mark_inode_dirty(inode);
- journal_end(&th, inode->i_sb, 4*REISERFS_QUOTA_INIT_BLOCKS+2);
+ error = journal_end(&th, inode->i_sb, jbegin_count);
}
}
if (!error)
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index 3072cfdee95..7b87707acc3 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -2631,6 +2631,8 @@ static int do_journal_begin_r(struct reiserfs_transaction_handle *th, struct sup
int retval;
reiserfs_check_lock_depth(p_s_sb, "journal_begin") ;
+ if (nblocks > journal->j_trans_max)
+ BUG();
PROC_INFO_INC( p_s_sb, journal.journal_being );
/* set here for journal_join */
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 7d4dc5f5aa8..4a333255f27 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -586,7 +586,7 @@ static int reiserfs_create (struct inode * dir, struct dentry *dentry, int mode,
int retval;
struct inode * inode;
/* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
- int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS);
+ int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb)+REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
struct reiserfs_transaction_handle th ;
int locked;
@@ -653,7 +653,7 @@ static int reiserfs_mknod (struct inode * dir, struct dentry *dentry, int mode,
struct inode * inode;
struct reiserfs_transaction_handle th ;
/* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
- int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS);
+ int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb)+REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
int locked;
if (!new_valid_dev(rdev))
@@ -727,7 +727,7 @@ static int reiserfs_mkdir (struct inode * dir, struct dentry *dentry, int mode)
struct inode * inode;
struct reiserfs_transaction_handle th ;
/* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
- int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS);
+ int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb)+REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
int locked;
#ifdef DISPLACE_NEW_PACKING_LOCALITIES
@@ -829,8 +829,10 @@ static int reiserfs_rmdir (struct inode * dir, struct dentry *dentry)
/* we will be doing 2 balancings and update 2 stat data, we change quotas
- * of the owner of the directory and of the owner of the parent directory */
- jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS);
+ * of the owner of the directory and of the owner of the parent directory.
+ * The quota structure is possibly deleted only on last iput => outside
+ * of this transaction */
+ jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 + 4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
reiserfs_write_lock(dir->i_sb);
retval = journal_begin(&th, dir->i_sb, jbegin_count) ;
@@ -913,9 +915,10 @@ static int reiserfs_unlink (struct inode * dir, struct dentry *dentry)
inode = dentry->d_inode;
/* in this transaction we can be doing at max two balancings and update
- two stat datas, we change quotas of the owner of the directory and of
- the owner of the parent directory */
- jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS);
+ * two stat datas, we change quotas of the owner of the directory and of
+ * the owner of the parent directory. The quota structure is possibly
+ * deleted only on iput => outside of this transaction */
+ jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 + 4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
reiserfs_write_lock(dir->i_sb);
retval = journal_begin(&th, dir->i_sb, jbegin_count) ;
@@ -1000,7 +1003,7 @@ static int reiserfs_symlink (struct inode * parent_dir,
struct reiserfs_transaction_handle th ;
int mode = S_IFLNK | S_IRWXUGO;
/* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
- int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS);
+ int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(parent_dir->i_sb)+REISERFS_QUOTA_TRANS_BLOCKS(parent_dir->i_sb));
if (!(inode = new_inode(parent_dir->i_sb))) {
return -ENOMEM ;
@@ -1076,7 +1079,7 @@ static int reiserfs_link (struct dentry * old_dentry, struct inode * dir, struct
struct inode *inode = old_dentry->d_inode;
struct reiserfs_transaction_handle th ;
/* We need blocks for transaction + update of quotas for the owners of the directory */
- int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * REISERFS_QUOTA_TRANS_BLOCKS;
+ int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
reiserfs_write_lock(dir->i_sb);
if (inode->i_nlink >= REISERFS_LINK_MAX) {
@@ -1196,7 +1199,7 @@ static int reiserfs_rename (struct inode * old_dir, struct dentry *old_dentry,
pointed initially and (5) maybe block containing ".." of
renamed directory
quota updates: two parent directories */
- jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 5 + 4 * REISERFS_QUOTA_TRANS_BLOCKS;
+ jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 5 + 4 * REISERFS_QUOTA_TRANS_BLOCKS(old_dir->i_sb);
old_inode = old_dentry->d_inode;
new_dentry_inode = new_dentry->d_inode;
diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
index da23ba75f3d..63158491e15 100644
--- a/fs/reiserfs/stree.c
+++ b/fs/reiserfs/stree.c
@@ -223,14 +223,13 @@ extern struct tree_balance * cur_tb;
const struct reiserfs_key MIN_KEY = {0, 0, {{0, 0},}};
/* Maximal possible key. It is never in the tree. */
-const struct reiserfs_key MAX_KEY = {
+static const struct reiserfs_key MAX_KEY = {
__constant_cpu_to_le32(0xffffffff),
__constant_cpu_to_le32(0xffffffff),
{{__constant_cpu_to_le32(0xffffffff),
__constant_cpu_to_le32(0xffffffff)},}
};
-const struct in_core_key MAX_IN_CORE_KEY = {~0U, ~0U, ~0ULL>>4, 15};
/* Get delimiting key of the buffer by looking for it in the buffers in the path, starting from the bottom
of the path, and going upwards. We must check the path's validity at each step. If the key is not in
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 31e75125f48..660aefca1fd 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -164,7 +164,9 @@ static int finish_unfinished (struct super_block * s)
/* compose key to look for "save" links */
max_cpu_key.version = KEY_FORMAT_3_5;
- max_cpu_key.on_disk_key = MAX_IN_CORE_KEY;
+ max_cpu_key.on_disk_key.k_dir_id = ~0U;
+ max_cpu_key.on_disk_key.k_objectid = ~0U;
+ set_cpu_key_k_offset (&max_cpu_key, ~0U);
max_cpu_key.key_length = 3;
#ifdef CONFIG_QUOTA
@@ -864,8 +866,9 @@ static int reiserfs_parse_options (struct super_block * s, char * options, /* st
{"jdev", .arg_required = 'j', .values = NULL},
{"nolargeio", .arg_required = 'w', .values = NULL},
{"commit", .arg_required = 'c', .values = NULL},
- {"usrquota",},
- {"grpquota",},
+ {"usrquota", .setmask = 1<<REISERFS_QUOTA},
+ {"grpquota", .setmask = 1<<REISERFS_QUOTA},
+ {"noquota", .clrmask = 1<<REISERFS_QUOTA},
{"errors", .arg_required = 'e', .values = error_actions},
{"usrjquota", .arg_required = 'u'|(1<<REISERFS_OPT_ALLOWEMPTY), .values = NULL},
{"grpjquota", .arg_required = 'g'|(1<<REISERFS_OPT_ALLOWEMPTY), .values = NULL},
@@ -962,6 +965,7 @@ static int reiserfs_parse_options (struct super_block * s, char * options, /* st
return 0;
}
strcpy(REISERFS_SB(s)->s_qf_names[qtype], arg);
+ *mount_options |= 1<<REISERFS_QUOTA;
}
else {
if (REISERFS_SB(s)->s_qf_names[qtype]) {
@@ -993,7 +997,13 @@ static int reiserfs_parse_options (struct super_block * s, char * options, /* st
reiserfs_warning(s, "reiserfs_parse_options: journalled quota format not specified.");
return 0;
}
+ /* This checking is not precise wrt the quota type but for our purposes it is sufficient */
+ if (!(*mount_options & (1<<REISERFS_QUOTA)) && sb_any_quota_enabled(s)) {
+ reiserfs_warning(s, "reiserfs_parse_options: quota options must be present when quota is turned on.");
+ return 0;
+ }
#endif
+
return 1;
}
@@ -1103,6 +1113,7 @@ static int reiserfs_remount (struct super_block * s, int * mount_flags, char * a
safe_mask |= 1 << REISERFS_ERROR_RO;
safe_mask |= 1 << REISERFS_ERROR_CONTINUE;
safe_mask |= 1 << REISERFS_ERROR_PANIC;
+ safe_mask |= 1 << REISERFS_QUOTA;
/* Update the bitmask, taking care to keep
* the bits we're not allowed to change here */
@@ -1839,13 +1850,18 @@ static int reiserfs_statfs (struct super_block * s, struct kstatfs * buf)
static int reiserfs_dquot_initialize(struct inode *inode, int type)
{
struct reiserfs_transaction_handle th;
- int ret;
+ int ret, err;
/* We may create quota structure so we need to reserve enough blocks */
reiserfs_write_lock(inode->i_sb);
- journal_begin(&th, inode->i_sb, 2*REISERFS_QUOTA_INIT_BLOCKS);
+ ret = journal_begin(&th, inode->i_sb, 2*REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb));
+ if (ret)
+ goto out;
ret = dquot_initialize(inode, type);
- journal_end(&th, inode->i_sb, 2*REISERFS_QUOTA_INIT_BLOCKS);
+ err = journal_end(&th, inode->i_sb, 2*REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb));
+ if (!ret && err)
+ ret = err;
+out:
reiserfs_write_unlock(inode->i_sb);
return ret;
}
@@ -1853,13 +1869,18 @@ static int reiserfs_dquot_initialize(struct inode *inode, int type)
static int reiserfs_dquot_drop(struct inode *inode)
{
struct reiserfs_transaction_handle th;
- int ret;
+ int ret, err;
/* We may delete quota structure so we need to reserve enough blocks */
reiserfs_write_lock(inode->i_sb);
- journal_begin(&th, inode->i_sb, 2*REISERFS_QUOTA_INIT_BLOCKS);
+ ret = journal_begin(&th, inode->i_sb, 2*REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb));
+ if (ret)
+ goto out;
ret = dquot_drop(inode);
- journal_end(&th, inode->i_sb, 2*REISERFS_QUOTA_INIT_BLOCKS);
+ err = journal_end(&th, inode->i_sb, 2*REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb));
+ if (!ret && err)
+ ret = err;
+out:
reiserfs_write_unlock(inode->i_sb);
return ret;
}
@@ -1867,12 +1888,17 @@ static int reiserfs_dquot_drop(struct inode *inode)
static int reiserfs_write_dquot(struct dquot *dquot)
{
struct reiserfs_transaction_handle th;
- int ret;
+ int ret, err;
reiserfs_write_lock(dquot->dq_sb);
- journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_TRANS_BLOCKS);
+ ret = journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
+ if (ret)
+ goto out;
ret = dquot_commit(dquot);
- journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_TRANS_BLOCKS);
+ err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
+ if (!ret && err)
+ ret = err;
+out:
reiserfs_write_unlock(dquot->dq_sb);
return ret;
}
@@ -1880,12 +1906,17 @@ static int reiserfs_write_dquot(struct dquot *dquot)
static int reiserfs_acquire_dquot(struct dquot *dquot)
{
struct reiserfs_transaction_handle th;
- int ret;
+ int ret, err;
reiserfs_write_lock(dquot->dq_sb);
- journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS);
+ ret = journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
+ if (ret)
+ goto out;
ret = dquot_acquire(dquot);
- journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS);
+ err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
+ if (!ret && err)
+ ret = err;
+out:
reiserfs_write_unlock(dquot->dq_sb);
return ret;
}
@@ -1893,12 +1924,17 @@ static int reiserfs_acquire_dquot(struct dquot *dquot)
static int reiserfs_release_dquot(struct dquot *dquot)
{
struct reiserfs_transaction_handle th;
- int ret;
+ int ret, err;
reiserfs_write_lock(dquot->dq_sb);
- journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS);
+ ret = journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
+ if (ret)
+ goto out;
ret = dquot_release(dquot);
- journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS);
+ err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
+ if (!ret && err)
+ ret = err;
+out:
reiserfs_write_unlock(dquot->dq_sb);
return ret;
}
@@ -1918,39 +1954,29 @@ static int reiserfs_mark_dquot_dirty(struct dquot *dquot)
static int reiserfs_write_info(struct super_block *sb, int type)
{
struct reiserfs_transaction_handle th;
- int ret;
+ int ret, err;
/* Data block + inode block */
reiserfs_write_lock(sb);
- journal_begin(&th, sb, 2);
+ ret = journal_begin(&th, sb, 2);
+ if (ret)
+ goto out;
ret = dquot_commit_info(sb, type);
- journal_end(&th, sb, 2);
+ err = journal_end(&th, sb, 2);
+ if (!ret && err)
+ ret = err;
+out:
reiserfs_write_unlock(sb);
return ret;
}
/*
- * Turn on quotas during mount time - we need to find
- * the quota file and such...
+ * Turn on quotas during mount time - we need to find the quota file and such...
*/
static int reiserfs_quota_on_mount(struct super_block *sb, int type)
{
- int err;
- struct dentry *dentry;
- struct qstr name = { .name = REISERFS_SB(sb)->s_qf_names[type],
- .hash = 0,
- .len = strlen(REISERFS_SB(sb)->s_qf_names[type])};
-
- dentry = lookup_hash(&name, sb->s_root);
- if (IS_ERR(dentry))
- return PTR_ERR(dentry);
- err = vfs_quota_on_mount(type, REISERFS_SB(sb)->s_jquota_fmt, dentry);
- /* Now invalidate and put the dentry - quota got its own reference
- * to inode and dentry has at least wrong hash so we had better
- * throw it away */
- d_invalidate(dentry);
- dput(dentry);
- return err;
+ return vfs_quota_on_mount(sb, REISERFS_SB(sb)->s_qf_names[type],
+ REISERFS_SB(sb)->s_jquota_fmt, type);
}
/*
@@ -1961,6 +1987,8 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, ch
int err;
struct nameidata nd;
+ if (!(REISERFS_SB(sb)->s_mount_opt & (1<<REISERFS_QUOTA)))
+ return -EINVAL;
err = path_lookup(path, LOOKUP_FOLLOW, &nd);
if (err)
return err;
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index e302071903a..c312881c5f5 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -4,7 +4,7 @@
#include <linux/errno.h>
#include <linux/pagemap.h>
#include <linux/xattr.h>
-#include <linux/xattr_acl.h>
+#include <linux/posix_acl_xattr.h>
#include <linux/reiserfs_xattr.h>
#include <linux/reiserfs_acl.h>
#include <asm/uaccess.h>
@@ -192,11 +192,11 @@ reiserfs_get_acl(struct inode *inode, int type)
switch (type) {
case ACL_TYPE_ACCESS:
- name = XATTR_NAME_ACL_ACCESS;
+ name = POSIX_ACL_XATTR_ACCESS;
p_acl = &reiserfs_i->i_acl_access;
break;
case ACL_TYPE_DEFAULT:
- name = XATTR_NAME_ACL_DEFAULT;
+ name = POSIX_ACL_XATTR_DEFAULT;
p_acl = &reiserfs_i->i_acl_default;
break;
default:
@@ -260,7 +260,7 @@ reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
switch (type) {
case ACL_TYPE_ACCESS:
- name = XATTR_NAME_ACL_ACCESS;
+ name = POSIX_ACL_XATTR_ACCESS;
p_acl = &reiserfs_i->i_acl_access;
if (acl) {
mode_t mode = inode->i_mode;
@@ -275,7 +275,7 @@ reiserfs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
}
break;
case ACL_TYPE_DEFAULT:
- name = XATTR_NAME_ACL_DEFAULT;
+ name = POSIX_ACL_XATTR_DEFAULT;
p_acl = &reiserfs_i->i_acl_default;
if (!S_ISDIR (inode->i_mode))
return acl ? -EACCES : 0;
@@ -468,7 +468,7 @@ static int
posix_acl_access_get(struct inode *inode, const char *name,
void *buffer, size_t size)
{
- if (strlen(name) != sizeof(XATTR_NAME_ACL_ACCESS)-1)
+ if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS)-1)
return -EINVAL;
return xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
}
@@ -477,7 +477,7 @@ static int
posix_acl_access_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
{
- if (strlen(name) != sizeof(XATTR_NAME_ACL_ACCESS)-1)
+ if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS)-1)
return -EINVAL;
return xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
}
@@ -487,7 +487,7 @@ posix_acl_access_del (struct inode *inode, const char *name)
{
struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode);
struct posix_acl **acl = &reiserfs_i->i_acl_access;
- if (strlen(name) != sizeof(XATTR_NAME_ACL_ACCESS)-1)
+ if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS)-1)
return -EINVAL;
if (!IS_ERR (*acl) && *acl) {
posix_acl_release (*acl);
@@ -510,7 +510,7 @@ posix_acl_access_list (struct inode *inode, const char *name, int namelen, char
}
struct reiserfs_xattr_handler posix_acl_access_handler = {
- .prefix = XATTR_NAME_ACL_ACCESS,
+ .prefix = POSIX_ACL_XATTR_ACCESS,
.get = posix_acl_access_get,
.set = posix_acl_access_set,
.del = posix_acl_access_del,
@@ -521,7 +521,7 @@ static int
posix_acl_default_get (struct inode *inode, const char *name,
void *buffer, size_t size)
{
- if (strlen(name) != sizeof(XATTR_NAME_ACL_DEFAULT)-1)
+ if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT)-1)
return -EINVAL;
return xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
}
@@ -530,7 +530,7 @@ static int
posix_acl_default_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
{
- if (strlen(name) != sizeof(XATTR_NAME_ACL_DEFAULT)-1)
+ if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT)-1)
return -EINVAL;
return xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
}
@@ -540,7 +540,7 @@ posix_acl_default_del (struct inode *inode, const char *name)
{
struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode);
struct posix_acl **acl = &reiserfs_i->i_acl_default;
- if (strlen(name) != sizeof(XATTR_NAME_ACL_DEFAULT)-1)
+ if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT)-1)
return -EINVAL;
if (!IS_ERR (*acl) && *acl) {
posix_acl_release (*acl);
@@ -563,7 +563,7 @@ posix_acl_default_list (struct inode *inode, const char *name, int namelen, char
}
struct reiserfs_xattr_handler posix_acl_default_handler = {
- .prefix = XATTR_NAME_ACL_DEFAULT,
+ .prefix = POSIX_ACL_XATTR_DEFAULT,
.get = posix_acl_default_get,
.set = posix_acl_default_set,
.del = posix_acl_default_del,
diff --git a/fs/super.c b/fs/super.c
index 3a1b8ca04ba..25bc1ec6bc5 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -341,20 +341,22 @@ static inline void write_super(struct super_block *sb)
*/
void sync_supers(void)
{
- struct super_block * sb;
-restart:
+ struct super_block *sb;
+
spin_lock(&sb_lock);
- sb = sb_entry(super_blocks.next);
- while (sb != sb_entry(&super_blocks))
+restart:
+ list_for_each_entry(sb, &super_blocks, s_list) {
if (sb->s_dirt) {
sb->s_count++;
spin_unlock(&sb_lock);
down_read(&sb->s_umount);
write_super(sb);
- drop_super(sb);
- goto restart;
- } else
- sb = sb_entry(sb->s_list.next);
+ up_read(&sb->s_umount);
+ spin_lock(&sb_lock);
+ if (__put_super_and_need_restart(sb))
+ goto restart;
+ }
+ }
spin_unlock(&sb_lock);
}
@@ -381,20 +383,16 @@ void sync_filesystems(int wait)
down(&mutex); /* Could be down_interruptible */
spin_lock(&sb_lock);
- for (sb = sb_entry(super_blocks.next); sb != sb_entry(&super_blocks);
- sb = sb_entry(sb->s_list.next)) {
+ list_for_each_entry(sb, &super_blocks, s_list) {
if (!sb->s_op->sync_fs)
continue;
if (sb->s_flags & MS_RDONLY)
continue;
sb->s_need_sync_fs = 1;
}
- spin_unlock(&sb_lock);
restart:
- spin_lock(&sb_lock);
- for (sb = sb_entry(super_blocks.next); sb != sb_entry(&super_blocks);
- sb = sb_entry(sb->s_list.next)) {
+ list_for_each_entry(sb, &super_blocks, s_list) {
if (!sb->s_need_sync_fs)
continue;
sb->s_need_sync_fs = 0;
@@ -405,8 +403,11 @@ restart:
down_read(&sb->s_umount);
if (sb->s_root && (wait || sb->s_dirt))
sb->s_op->sync_fs(sb, wait);
- drop_super(sb);
- goto restart;
+ up_read(&sb->s_umount);
+ /* restart only when sb is no longer on the list */
+ spin_lock(&sb_lock);
+ if (__put_super_and_need_restart(sb))
+ goto restart;
}
spin_unlock(&sb_lock);
up(&mutex);
@@ -422,21 +423,25 @@ restart:
struct super_block * get_super(struct block_device *bdev)
{
- struct list_head *p;
+ struct super_block *sb;
+
if (!bdev)
return NULL;
-rescan:
+
spin_lock(&sb_lock);
- list_for_each(p, &super_blocks) {
- struct super_block *s = sb_entry(p);
- if (s->s_bdev == bdev) {
- s->s_count++;
+rescan:
+ list_for_each_entry(sb, &super_blocks, s_list) {
+ if (sb->s_bdev == bdev) {
+ sb->s_count++;
spin_unlock(&sb_lock);
- down_read(&s->s_umount);
- if (s->s_root)
- return s;
- drop_super(s);
- goto rescan;
+ down_read(&sb->s_umount);
+ if (sb->s_root)
+ return sb;
+ up_read(&sb->s_umount);
+ /* restart only when sb is no longer on the list */
+ spin_lock(&sb_lock);
+ if (__put_super_and_need_restart(sb))
+ goto rescan;
}
}
spin_unlock(&sb_lock);
@@ -447,20 +452,22 @@ EXPORT_SYMBOL(get_super);
struct super_block * user_get_super(dev_t dev)
{
- struct list_head *p;
+ struct super_block *sb;
-rescan:
spin_lock(&sb_lock);
- list_for_each(p, &super_blocks) {
- struct super_block *s = sb_entry(p);
- if (s->s_dev == dev) {
- s->s_count++;
+rescan:
+ list_for_each_entry(sb, &super_blocks, s_list) {
+ if (sb->s_dev == dev) {
+ sb->s_count++;
spin_unlock(&sb_lock);
- down_read(&s->s_umount);
- if (s->s_root)
- return s;
- drop_super(s);
- goto rescan;
+ down_read(&sb->s_umount);
+ if (sb->s_root)
+ return sb;
+ up_read(&sb->s_umount);
+ /* restart only when sb is no longer on the list */
+ spin_lock(&sb_lock);
+ if (__put_super_and_need_restart(sb))
+ goto rescan;
}
}
spin_unlock(&sb_lock);
@@ -835,6 +842,7 @@ do_kern_mount(const char *fstype, int flags, const char *name, void *data)
mnt->mnt_parent = mnt;
mnt->mnt_namespace = current->namespace;
up_write(&sb->s_umount);
+ free_secdata(secdata);
put_filesystem(type);
return mnt;
out_sb:
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index d4aaa88d021..78899eeab97 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -25,7 +25,7 @@ fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count)
struct kobject * kobj = to_kobj(dentry->d_parent);
if (!attr->read)
- return -EINVAL;
+ return -EIO;
return attr->read(kobj, buffer, off, count);
}
@@ -71,7 +71,7 @@ flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count)
struct kobject *kobj = to_kobj(dentry->d_parent);
if (!attr->write)
- return -EINVAL;
+ return -EIO;
return attr->write(kobj, buffer, offset, count);
}
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index fe198210bc2..59734ba1ee6 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -8,6 +8,7 @@
#include <linux/mount.h>
#include <linux/module.h>
#include <linux/kobject.h>
+#include <linux/namei.h>
#include "sysfs.h"
DECLARE_RWSEM(sysfs_rename_sem);
@@ -99,20 +100,21 @@ static int create_dir(struct kobject * k, struct dentry * p,
umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
down(&p->d_inode->i_sem);
- *d = sysfs_get_dentry(p,n);
+ *d = lookup_one_len(n, p, strlen(n));
if (!IS_ERR(*d)) {
- error = sysfs_create(*d, mode, init_dir);
+ error = sysfs_make_dirent(p->d_fsdata, *d, k, mode, SYSFS_DIR);
if (!error) {
- error = sysfs_make_dirent(p->d_fsdata, *d, k, mode,
- SYSFS_DIR);
+ error = sysfs_create(*d, mode, init_dir);
if (!error) {
p->d_inode->i_nlink++;
(*d)->d_op = &sysfs_dentry_ops;
d_rehash(*d);
}
}
- if (error && (error != -EEXIST))
+ if (error && (error != -EEXIST)) {
+ sysfs_put((*d)->d_fsdata);
d_drop(*d);
+ }
dput(*d);
} else
error = PTR_ERR(*d);
@@ -171,17 +173,19 @@ static int sysfs_attach_attr(struct sysfs_dirent * sd, struct dentry * dentry)
init = init_file;
}
+ dentry->d_fsdata = sysfs_get(sd);
+ sd->s_dentry = dentry;
error = sysfs_create(dentry, (attr->mode & S_IALLUGO) | S_IFREG, init);
- if (error)
+ if (error) {
+ sysfs_put(sd);
return error;
+ }
if (bin_attr) {
dentry->d_inode->i_size = bin_attr->size;
dentry->d_inode->i_fop = &bin_fops;
}
dentry->d_op = &sysfs_dentry_ops;
- dentry->d_fsdata = sysfs_get(sd);
- sd->s_dentry = dentry;
d_rehash(dentry);
return 0;
@@ -191,13 +195,15 @@ static int sysfs_attach_link(struct sysfs_dirent * sd, struct dentry * dentry)
{
int err = 0;
+ dentry->d_fsdata = sysfs_get(sd);
+ sd->s_dentry = dentry;
err = sysfs_create(dentry, S_IFLNK|S_IRWXUGO, init_symlink);
if (!err) {
dentry->d_op = &sysfs_dentry_ops;
- dentry->d_fsdata = sysfs_get(sd);
- sd->s_dentry = dentry;
d_rehash(dentry);
- }
+ } else
+ sysfs_put(sd);
+
return err;
}
@@ -228,6 +234,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
struct inode_operations sysfs_dir_inode_operations = {
.lookup = sysfs_lookup,
+ .setattr = sysfs_setattr,
};
static void remove_dir(struct dentry * d)
@@ -309,7 +316,7 @@ int sysfs_rename_dir(struct kobject * kobj, const char *new_name)
down(&parent->d_inode->i_sem);
- new_dentry = sysfs_get_dentry(parent, new_name);
+ new_dentry = lookup_one_len(new_name, parent, strlen(new_name));
if (!IS_ERR(new_dentry)) {
if (!new_dentry->d_inode) {
error = kobject_set_name(kobj, "%s", new_name);
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 364208071e1..d72c1ce4855 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -5,6 +5,7 @@
#include <linux/module.h>
#include <linux/dnotify.h>
#include <linux/kobject.h>
+#include <linux/namei.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
@@ -13,7 +14,7 @@
#define to_subsys(k) container_of(k,struct subsystem,kset.kobj)
#define to_sattr(a) container_of(a,struct subsys_attribute,attr)
-/**
+/*
* Subsystem file operations.
* These operations allow subsystems to have files that can be
* read/written.
@@ -23,7 +24,7 @@ subsys_attr_show(struct kobject * kobj, struct attribute * attr, char * page)
{
struct subsystem * s = to_subsys(kobj);
struct subsys_attribute * sattr = to_sattr(attr);
- ssize_t ret = 0;
+ ssize_t ret = -EIO;
if (sattr->show)
ret = sattr->show(s,page);
@@ -36,7 +37,7 @@ subsys_attr_store(struct kobject * kobj, struct attribute * attr,
{
struct subsystem * s = to_subsys(kobj);
struct subsys_attribute * sattr = to_sattr(attr);
- ssize_t ret = 0;
+ ssize_t ret = -EIO;
if (sattr->store)
ret = sattr->store(s,page,count);
@@ -182,7 +183,7 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
return -ENOMEM;
if (count >= PAGE_SIZE)
- count = PAGE_SIZE - 1;
+ count = PAGE_SIZE;
error = copy_from_user(buffer->page,buf,count);
buffer->needs_read_fill = 1;
return error ? -EFAULT : count;
@@ -191,8 +192,9 @@ fill_write_buffer(struct sysfs_buffer * buffer, const char __user * buf, size_t
/**
* flush_write_buffer - push buffer to kobject.
- * @file: file pointer.
+ * @dentry: dentry to the attribute
* @buffer: data buffer for file.
+ * @count: number of bytes
*
* Get the correct pointers for the kobject and the attribute we're
* dealing with, then call the store() method for the attribute,
@@ -400,7 +402,7 @@ int sysfs_update_file(struct kobject * kobj, const struct attribute * attr)
int res = -ENOENT;
down(&dir->d_inode->i_sem);
- victim = sysfs_get_dentry(dir, attr->name);
+ victim = lookup_one_len(attr->name, dir, strlen(attr->name));
if (!IS_ERR(victim)) {
/* make sure dentry is really there */
if (victim->d_inode &&
@@ -443,7 +445,7 @@ int sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode)
int res = -ENOENT;
down(&dir->d_inode->i_sem);
- victim = sysfs_get_dentry(dir, attr->name);
+ victim = lookup_one_len(attr->name, dir, strlen(attr->name));
if (!IS_ERR(victim)) {
if (victim->d_inode &&
(victim->d_parent->d_inode == dir->d_inode)) {
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index f11ac5ea702..122145b0895 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -11,6 +11,7 @@
#include <linux/kobject.h>
#include <linux/module.h>
#include <linux/dcache.h>
+#include <linux/namei.h>
#include <linux/err.h>
#include "sysfs.h"
@@ -68,7 +69,8 @@ void sysfs_remove_group(struct kobject * kobj,
struct dentry * dir;
if (grp->name)
- dir = sysfs_get_dentry(kobj->dentry,grp->name);
+ dir = lookup_one_len(grp->name, kobj->dentry,
+ strlen(grp->name));
else
dir = dget(kobj->dentry);
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index aff7b2dfa8e..8de13bafaa7 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -26,18 +26,107 @@ static struct backing_dev_info sysfs_backing_dev_info = {
.capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
};
-struct inode * sysfs_new_inode(mode_t mode)
+static struct inode_operations sysfs_inode_operations ={
+ .setattr = sysfs_setattr,
+};
+
+int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
+{
+ struct inode * inode = dentry->d_inode;
+ struct sysfs_dirent * sd = dentry->d_fsdata;
+ struct iattr * sd_iattr;
+ unsigned int ia_valid = iattr->ia_valid;
+ int error;
+
+ if (!sd)
+ return -EINVAL;
+
+ sd_iattr = sd->s_iattr;
+
+ error = inode_change_ok(inode, iattr);
+ if (error)
+ return error;
+
+ error = inode_setattr(inode, iattr);
+ if (error)
+ return error;
+
+ if (!sd_iattr) {
+ /* setting attributes for the first time, allocate now */
+ sd_iattr = kmalloc(sizeof(struct iattr), GFP_KERNEL);
+ if (!sd_iattr)
+ return -ENOMEM;
+ /* assign default attributes */
+ memset(sd_iattr, 0, sizeof(struct iattr));
+ sd_iattr->ia_mode = sd->s_mode;
+ sd_iattr->ia_uid = 0;
+ sd_iattr->ia_gid = 0;
+ sd_iattr->ia_atime = sd_iattr->ia_mtime = sd_iattr->ia_ctime = CURRENT_TIME;
+ sd->s_iattr = sd_iattr;
+ }
+
+ /* attributes were changed atleast once in past */
+
+ if (ia_valid & ATTR_UID)
+ sd_iattr->ia_uid = iattr->ia_uid;
+ if (ia_valid & ATTR_GID)
+ sd_iattr->ia_gid = iattr->ia_gid;
+ if (ia_valid & ATTR_ATIME)
+ sd_iattr->ia_atime = timespec_trunc(iattr->ia_atime,
+ inode->i_sb->s_time_gran);
+ if (ia_valid & ATTR_MTIME)
+ sd_iattr->ia_mtime = timespec_trunc(iattr->ia_mtime,
+ inode->i_sb->s_time_gran);
+ if (ia_valid & ATTR_CTIME)
+ sd_iattr->ia_ctime = timespec_trunc(iattr->ia_ctime,
+ inode->i_sb->s_time_gran);
+ if (ia_valid & ATTR_MODE) {
+ umode_t mode = iattr->ia_mode;
+
+ if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
+ mode &= ~S_ISGID;
+ sd_iattr->ia_mode = mode;
+ }
+
+ return error;
+}
+
+static inline void set_default_inode_attr(struct inode * inode, mode_t mode)
+{
+ inode->i_mode = mode;
+ inode->i_uid = 0;
+ inode->i_gid = 0;
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+}
+
+static inline void set_inode_attr(struct inode * inode, struct iattr * iattr)
+{
+ inode->i_mode = iattr->ia_mode;
+ inode->i_uid = iattr->ia_uid;
+ inode->i_gid = iattr->ia_gid;
+ inode->i_atime = iattr->ia_atime;
+ inode->i_mtime = iattr->ia_mtime;
+ inode->i_ctime = iattr->ia_ctime;
+}
+
+struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent * sd)
{
struct inode * inode = new_inode(sysfs_sb);
if (inode) {
- inode->i_mode = mode;
- inode->i_uid = 0;
- inode->i_gid = 0;
inode->i_blksize = PAGE_CACHE_SIZE;
inode->i_blocks = 0;
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
inode->i_mapping->a_ops = &sysfs_aops;
inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
+ inode->i_op = &sysfs_inode_operations;
+
+ if (sd->s_iattr) {
+ /* sysfs_dirent has non-default attributes
+ * get them for the new inode from persistent copy
+ * in sysfs_dirent
+ */
+ set_inode_attr(inode, sd->s_iattr);
+ } else
+ set_default_inode_attr(inode, mode);
}
return inode;
}
@@ -48,7 +137,8 @@ int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *))
struct inode * inode = NULL;
if (dentry) {
if (!dentry->d_inode) {
- if ((inode = sysfs_new_inode(mode))) {
+ struct sysfs_dirent * sd = dentry->d_fsdata;
+ if ((inode = sysfs_new_inode(mode, sd))) {
if (dentry->d_parent && dentry->d_parent->d_inode) {
struct inode *p_inode = dentry->d_parent->d_inode;
p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
@@ -76,16 +166,6 @@ int sysfs_create(struct dentry * dentry, int mode, int (*init)(struct inode *))
return error;
}
-struct dentry * sysfs_get_dentry(struct dentry * parent, const char * name)
-{
- struct qstr qstr;
-
- qstr.name = name;
- qstr.len = strlen(name);
- qstr.hash = full_name_hash(name,qstr.len);
- return lookup_hash(&qstr,parent);
-}
-
/*
* Get the name for corresponding element represented by the given sysfs_dirent
*/
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index 5c805bb1a4b..f1117e885bd 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -28,6 +28,7 @@ static struct sysfs_dirent sysfs_root = {
.s_children = LIST_HEAD_INIT(sysfs_root.s_children),
.s_element = NULL,
.s_type = SYSFS_ROOT,
+ .s_iattr = NULL,
};
static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
@@ -42,7 +43,8 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
sb->s_time_gran = 1;
sysfs_sb = sb;
- inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO);
+ inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
+ &sysfs_root);
if (inode) {
inode->i_op = &sysfs_dir_inode_operations;
inode->i_fop = &sysfs_dir_operations;
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index dfdf7017435..fae57c83a72 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -43,7 +43,7 @@ static void fill_object_path(struct kobject * kobj, char * buffer, int length)
}
}
-static int sysfs_add_link(struct dentry * parent, char * name, struct kobject * target)
+static int sysfs_add_link(struct dentry * parent, const char * name, struct kobject * target)
{
struct sysfs_dirent * parent_sd = parent->d_fsdata;
struct sysfs_symlink * sl;
@@ -79,7 +79,7 @@ exit1:
* @target: object we're pointing to.
* @name: name of the symlink.
*/
-int sysfs_create_link(struct kobject * kobj, struct kobject * target, char * name)
+int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name)
{
struct dentry * dentry = kobj->dentry;
int error = 0;
@@ -99,13 +99,13 @@ int sysfs_create_link(struct kobject * kobj, struct kobject * target, char * nam
* @name: name of the symlink to remove.
*/
-void sysfs_remove_link(struct kobject * kobj, char * name)
+void sysfs_remove_link(struct kobject * kobj, const char * name)
{
sysfs_hash_and_remove(kobj->dentry,name);
}
static int sysfs_get_target_path(struct kobject * kobj, struct kobject * target,
- char *path)
+ char *path)
{
char * s;
int depth, size;
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index a8a24a0c0b3..3f8953e0e5d 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -2,12 +2,11 @@
extern struct vfsmount * sysfs_mount;
extern kmem_cache_t *sysfs_dir_cachep;
-extern struct inode * sysfs_new_inode(mode_t mode);
+extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *);
extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *));
extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *,
umode_t, int);
-extern struct dentry * sysfs_get_dentry(struct dentry *, const char *);
extern int sysfs_add_file(struct dentry *, const struct attribute *, int);
extern void sysfs_hash_and_remove(struct dentry * dir, const char * name);
@@ -17,6 +16,7 @@ extern void sysfs_remove_subdir(struct dentry *);
extern const unsigned char * sysfs_get_name(struct sysfs_dirent *sd);
extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent);
+extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
extern struct rw_semaphore sysfs_rename_sem;
extern struct super_block * sysfs_sb;
@@ -75,6 +75,7 @@ static inline void release_sysfs_dirent(struct sysfs_dirent * sd)
kobject_put(sl->target_kobj);
kfree(sl);
}
+ kfree(sd->s_iattr);
kmem_cache_free(sysfs_dir_cachep, sd);
}
diff --git a/fs/udf/udftime.c b/fs/udf/udftime.c
index 457a8fe2857..85d8dbe843f 100644
--- a/fs/udf/udftime.c
+++ b/fs/udf/udftime.c
@@ -46,7 +46,7 @@
#endif
/* How many days come before each month (0-12). */
-const unsigned short int __mon_yday[2][13] =
+static const unsigned short int __mon_yday[2][13] =
{
/* Normal years. */
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 9278e9aba9b..a3a4b5aaf5d 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -149,11 +149,12 @@ linvfs_unwritten_convert(
*/
STATIC void
linvfs_unwritten_convert_direct(
- struct inode *inode,
+ struct kiocb *iocb,
loff_t offset,
ssize_t size,
void *private)
{
+ struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
ASSERT(!private || inode == (struct inode *)private);
/* private indicates an unwritten extent lay beneath this IO */
@@ -886,7 +887,6 @@ xfs_page_state_convert(
SetPageUptodate(page);
if (startio) {
- WARN_ON(page_dirty);
xfs_submit_page(page, wbc, bh_arr, cnt, 0, !page_dirty);
}
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 997963e5362..df0cba239dd 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -61,12 +61,13 @@
* File wide globals
*/
-STATIC kmem_cache_t *pagebuf_cache;
+STATIC kmem_cache_t *pagebuf_zone;
STATIC kmem_shaker_t pagebuf_shake;
-STATIC int pagebuf_daemon_wakeup(int, unsigned int);
+STATIC int xfsbufd_wakeup(int, unsigned int);
STATIC void pagebuf_delwri_queue(xfs_buf_t *, int);
-STATIC struct workqueue_struct *pagebuf_logio_workqueue;
-STATIC struct workqueue_struct *pagebuf_dataio_workqueue;
+
+STATIC struct workqueue_struct *xfslogd_workqueue;
+STATIC struct workqueue_struct *xfsdatad_workqueue;
/*
* Pagebuf debugging
@@ -123,9 +124,9 @@ ktrace_t *pagebuf_trace_buf;
#define pagebuf_allocate(flags) \
- kmem_zone_alloc(pagebuf_cache, pb_to_km(flags))
+ kmem_zone_alloc(pagebuf_zone, pb_to_km(flags))
#define pagebuf_deallocate(pb) \
- kmem_zone_free(pagebuf_cache, (pb));
+ kmem_zone_free(pagebuf_zone, (pb));
/*
* Page Region interfaces.
@@ -425,7 +426,7 @@ _pagebuf_lookup_pages(
__FUNCTION__, gfp_mask);
XFS_STATS_INC(pb_page_retries);
- pagebuf_daemon_wakeup(0, gfp_mask);
+ xfsbufd_wakeup(0, gfp_mask);
blk_congestion_wait(WRITE, HZ/50);
goto retry;
}
@@ -1136,8 +1137,8 @@ pagebuf_iodone(
if ((pb->pb_iodone) || (pb->pb_flags & PBF_ASYNC)) {
if (schedule) {
INIT_WORK(&pb->pb_iodone_work, pagebuf_iodone_work, pb);
- queue_work(dataio ? pagebuf_dataio_workqueue :
- pagebuf_logio_workqueue, &pb->pb_iodone_work);
+ queue_work(dataio ? xfsdatad_workqueue :
+ xfslogd_workqueue, &pb->pb_iodone_work);
} else {
pagebuf_iodone_work(pb);
}
@@ -1562,16 +1563,6 @@ xfs_free_buftarg(
kmem_free(btp, sizeof(*btp));
}
-void
-xfs_incore_relse(
- xfs_buftarg_t *btp,
- int delwri_only,
- int wait)
-{
- invalidate_bdev(btp->pbr_bdev, 1);
- truncate_inode_pages(btp->pbr_mapping, 0LL);
-}
-
STATIC int
xfs_setsize_buftarg_flags(
xfs_buftarg_t *btp,
@@ -1742,27 +1733,27 @@ pagebuf_runall_queues(
}
/* Defines for pagebuf daemon */
-STATIC DECLARE_COMPLETION(pagebuf_daemon_done);
-STATIC struct task_struct *pagebuf_daemon_task;
-STATIC int pagebuf_daemon_active;
-STATIC int force_flush;
-STATIC int force_sleep;
+STATIC DECLARE_COMPLETION(xfsbufd_done);
+STATIC struct task_struct *xfsbufd_task;
+STATIC int xfsbufd_active;
+STATIC int xfsbufd_force_flush;
+STATIC int xfsbufd_force_sleep;
STATIC int
-pagebuf_daemon_wakeup(
+xfsbufd_wakeup(
int priority,
unsigned int mask)
{
- if (force_sleep)
+ if (xfsbufd_force_sleep)
return 0;
- force_flush = 1;
+ xfsbufd_force_flush = 1;
barrier();
- wake_up_process(pagebuf_daemon_task);
+ wake_up_process(xfsbufd_task);
return 0;
}
STATIC int
-pagebuf_daemon(
+xfsbufd(
void *data)
{
struct list_head tmp;
@@ -1774,17 +1765,17 @@ pagebuf_daemon(
daemonize("xfsbufd");
current->flags |= PF_MEMALLOC;
- pagebuf_daemon_task = current;
- pagebuf_daemon_active = 1;
+ xfsbufd_task = current;
+ xfsbufd_active = 1;
barrier();
INIT_LIST_HEAD(&tmp);
do {
- if (unlikely(current->flags & PF_FREEZE)) {
- force_sleep = 1;
- refrigerator(PF_FREEZE);
+ if (unlikely(freezing(current))) {
+ xfsbufd_force_sleep = 1;
+ refrigerator();
} else {
- force_sleep = 0;
+ xfsbufd_force_sleep = 0;
}
set_current_state(TASK_INTERRUPTIBLE);
@@ -1797,7 +1788,7 @@ pagebuf_daemon(
ASSERT(pb->pb_flags & PBF_DELWRI);
if (!pagebuf_ispin(pb) && !pagebuf_cond_lock(pb)) {
- if (!force_flush &&
+ if (!xfsbufd_force_flush &&
time_before(jiffies,
pb->pb_queuetime + age)) {
pagebuf_unlock(pb);
@@ -1824,10 +1815,10 @@ pagebuf_daemon(
if (as_list_len > 0)
purge_addresses();
- force_flush = 0;
- } while (pagebuf_daemon_active);
+ xfsbufd_force_flush = 0;
+ } while (xfsbufd_active);
- complete_and_exit(&pagebuf_daemon_done, 0);
+ complete_and_exit(&xfsbufd_done, 0);
}
/*
@@ -1844,8 +1835,8 @@ xfs_flush_buftarg(
xfs_buf_t *pb, *n;
int pincount = 0;
- pagebuf_runall_queues(pagebuf_dataio_workqueue);
- pagebuf_runall_queues(pagebuf_logio_workqueue);
+ pagebuf_runall_queues(xfsdatad_workqueue);
+ pagebuf_runall_queues(xfslogd_workqueue);
INIT_LIST_HEAD(&tmp);
spin_lock(&pbd_delwrite_lock);
@@ -1898,43 +1889,43 @@ xfs_flush_buftarg(
}
STATIC int
-pagebuf_daemon_start(void)
+xfs_buf_daemons_start(void)
{
- int rval;
+ int error = -ENOMEM;
- pagebuf_logio_workqueue = create_workqueue("xfslogd");
- if (!pagebuf_logio_workqueue)
- return -ENOMEM;
+ xfslogd_workqueue = create_workqueue("xfslogd");
+ if (!xfslogd_workqueue)
+ goto out;
- pagebuf_dataio_workqueue = create_workqueue("xfsdatad");
- if (!pagebuf_dataio_workqueue) {
- destroy_workqueue(pagebuf_logio_workqueue);
- return -ENOMEM;
- }
+ xfsdatad_workqueue = create_workqueue("xfsdatad");
+ if (!xfsdatad_workqueue)
+ goto out_destroy_xfslogd_workqueue;
- rval = kernel_thread(pagebuf_daemon, NULL, CLONE_FS|CLONE_FILES);
- if (rval < 0) {
- destroy_workqueue(pagebuf_logio_workqueue);
- destroy_workqueue(pagebuf_dataio_workqueue);
- }
+ error = kernel_thread(xfsbufd, NULL, CLONE_FS|CLONE_FILES);
+ if (error < 0)
+ goto out_destroy_xfsdatad_workqueue;
+ return 0;
- return rval;
+ out_destroy_xfsdatad_workqueue:
+ destroy_workqueue(xfsdatad_workqueue);
+ out_destroy_xfslogd_workqueue:
+ destroy_workqueue(xfslogd_workqueue);
+ out:
+ return error;
}
/*
- * pagebuf_daemon_stop
- *
* Note: do not mark as __exit, it is called from pagebuf_terminate.
*/
STATIC void
-pagebuf_daemon_stop(void)
+xfs_buf_daemons_stop(void)
{
- pagebuf_daemon_active = 0;
+ xfsbufd_active = 0;
barrier();
- wait_for_completion(&pagebuf_daemon_done);
+ wait_for_completion(&xfsbufd_done);
- destroy_workqueue(pagebuf_logio_workqueue);
- destroy_workqueue(pagebuf_dataio_workqueue);
+ destroy_workqueue(xfslogd_workqueue);
+ destroy_workqueue(xfsdatad_workqueue);
}
/*
@@ -1944,27 +1935,37 @@ pagebuf_daemon_stop(void)
int __init
pagebuf_init(void)
{
- pagebuf_cache = kmem_cache_create("xfs_buf_t", sizeof(xfs_buf_t), 0,
- SLAB_HWCACHE_ALIGN, NULL, NULL);
- if (pagebuf_cache == NULL) {
- printk("XFS: couldn't init xfs_buf_t cache\n");
- pagebuf_terminate();
- return -ENOMEM;
- }
+ int error = -ENOMEM;
+
+ pagebuf_zone = kmem_zone_init(sizeof(xfs_buf_t), "xfs_buf");
+ if (!pagebuf_zone)
+ goto out;
#ifdef PAGEBUF_TRACE
pagebuf_trace_buf = ktrace_alloc(PAGEBUF_TRACE_SIZE, KM_SLEEP);
#endif
- pagebuf_daemon_start();
+ error = xfs_buf_daemons_start();
+ if (error)
+ goto out_free_buf_zone;
- pagebuf_shake = kmem_shake_register(pagebuf_daemon_wakeup);
- if (pagebuf_shake == NULL) {
- pagebuf_terminate();
- return -ENOMEM;
+ pagebuf_shake = kmem_shake_register(xfsbufd_wakeup);
+ if (!pagebuf_shake) {
+ error = -ENOMEM;
+ goto out_stop_daemons;
}
return 0;
+
+ out_stop_daemons:
+ xfs_buf_daemons_stop();
+ out_free_buf_zone:
+#ifdef PAGEBUF_TRACE
+ ktrace_free(pagebuf_trace_buf);
+#endif
+ kmem_zone_destroy(pagebuf_zone);
+ out:
+ return error;
}
@@ -1976,12 +1977,12 @@ pagebuf_init(void)
void
pagebuf_terminate(void)
{
- pagebuf_daemon_stop();
+ xfs_buf_daemons_stop();
#ifdef PAGEBUF_TRACE
ktrace_free(pagebuf_trace_buf);
#endif
- kmem_zone_destroy(pagebuf_cache);
+ kmem_zone_destroy(pagebuf_zone);
kmem_shake_deregister(pagebuf_shake);
}
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h
index 74deed8e6d9..3f8f69a66ae 100644
--- a/fs/xfs/linux-2.6/xfs_buf.h
+++ b/fs/xfs/linux-2.6/xfs_buf.h
@@ -576,7 +576,6 @@ extern xfs_buftarg_t *xfs_alloc_buftarg(struct block_device *, int);
extern void xfs_free_buftarg(xfs_buftarg_t *, int);
extern void xfs_wait_buftarg(xfs_buftarg_t *);
extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int);
-extern void xfs_incore_relse(xfs_buftarg_t *, int, int);
extern int xfs_flush_buftarg(xfs_buftarg_t *, int);
#define xfs_getsize_buftarg(buftarg) \
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index d0d412afd26..f1ce4323f56 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -57,7 +57,9 @@
#include <linux/smp_lock.h>
static struct vm_operations_struct linvfs_file_vm_ops;
-
+#ifdef CONFIG_XFS_DMAPI
+static struct vm_operations_struct linvfs_dmapi_file_vm_ops;
+#endif
STATIC inline ssize_t
__linvfs_read(
@@ -388,6 +390,14 @@ done:
return -error;
}
+#ifdef CONFIG_XFS_DMAPI
+STATIC void
+linvfs_mmap_close(
+ struct vm_area_struct *vma)
+{
+ xfs_dm_mm_put(vma);
+}
+#endif /* CONFIG_XFS_DMAPI */
STATIC int
linvfs_file_mmap(
@@ -399,16 +409,19 @@ linvfs_file_mmap(
vattr_t va = { .va_mask = XFS_AT_UPDATIME };
int error;
+ vma->vm_ops = &linvfs_file_vm_ops;
+
if (vp->v_vfsp->vfs_flag & VFS_DMI) {
xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp);
error = -XFS_SEND_MMAP(mp, vma, 0);
if (error)
return error;
+#ifdef CONFIG_XFS_DMAPI
+ vma->vm_ops = &linvfs_dmapi_file_vm_ops;
+#endif
}
- vma->vm_ops = &linvfs_file_vm_ops;
-
VOP_SETATTR(vp, &va, XFS_AT_UPDATIME, NULL, error);
if (!error)
vn_revalidate(vp); /* update Linux inode flags */
@@ -565,7 +578,7 @@ struct file_operations linvfs_file_operations = {
.sendfile = linvfs_sendfile,
.unlocked_ioctl = linvfs_ioctl,
#ifdef CONFIG_COMPAT
- .compat_ioctl = xfs_compat_ioctl,
+ .compat_ioctl = linvfs_compat_ioctl,
#endif
.mmap = linvfs_file_mmap,
.open = linvfs_open,
@@ -587,7 +600,7 @@ struct file_operations linvfs_invis_file_operations = {
.sendfile = linvfs_sendfile,
.unlocked_ioctl = linvfs_ioctl_invis,
#ifdef CONFIG_COMPAT
- .compat_ioctl = xfs_compat_invis_ioctl,
+ .compat_ioctl = linvfs_compat_invis_ioctl,
#endif
.mmap = linvfs_file_mmap,
.open = linvfs_open,
@@ -600,13 +613,24 @@ struct file_operations linvfs_dir_operations = {
.read = generic_read_dir,
.readdir = linvfs_readdir,
.unlocked_ioctl = linvfs_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = linvfs_compat_ioctl,
+#endif
.fsync = linvfs_fsync,
};
static struct vm_operations_struct linvfs_file_vm_ops = {
.nopage = filemap_nopage,
.populate = filemap_populate,
+};
+
+#ifdef CONFIG_XFS_DMAPI
+static struct vm_operations_struct linvfs_dmapi_file_vm_ops = {
+ .close = linvfs_mmap_close,
+ .nopage = filemap_nopage,
+ .populate = filemap_populate,
#ifdef HAVE_VMOP_MPROTECT
.mprotect = linvfs_mprotect,
#endif
};
+#endif /* CONFIG_XFS_DMAPI */
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index 69809eef8a5..05a447e51cc 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -1174,7 +1174,8 @@ xfs_ioc_xattr(
switch (cmd) {
case XFS_IOC_FSGETXATTR: {
- va.va_mask = XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_NEXTENTS;
+ va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
+ XFS_AT_NEXTENTS | XFS_AT_PROJID;
VOP_GETATTR(vp, &va, 0, NULL, error);
if (error)
return -error;
@@ -1182,6 +1183,7 @@ xfs_ioc_xattr(
fa.fsx_xflags = va.va_xflags;
fa.fsx_extsize = va.va_extsize;
fa.fsx_nextents = va.va_nextents;
+ fa.fsx_projid = va.va_projid;
if (copy_to_user(arg, &fa, sizeof(fa)))
return -XFS_ERROR(EFAULT);
@@ -1196,9 +1198,10 @@ xfs_ioc_xattr(
if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
attr_flags |= ATTR_NONBLOCK;
- va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE;
+ va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | XFS_AT_PROJID;
va.va_xflags = fa.fsx_xflags;
va.va_extsize = fa.fsx_extsize;
+ va.va_projid = fa.fsx_projid;
VOP_SETATTR(vp, &va, attr_flags, NULL, error);
if (!error)
@@ -1207,7 +1210,8 @@ xfs_ioc_xattr(
}
case XFS_IOC_FSGETXATTRA: {
- va.va_mask = XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_ANEXTENTS;
+ va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
+ XFS_AT_ANEXTENTS | XFS_AT_PROJID;
VOP_GETATTR(vp, &va, 0, NULL, error);
if (error)
return -error;
@@ -1215,6 +1219,7 @@ xfs_ioc_xattr(
fa.fsx_xflags = va.va_xflags;
fa.fsx_extsize = va.va_extsize;
fa.fsx_nextents = va.va_anextents;
+ fa.fsx_projid = va.va_projid;
if (copy_to_user(arg, &fa, sizeof(fa)))
return -XFS_ERROR(EFAULT);
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c
index 7a12c83184f..0f8f1384eb3 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -58,8 +58,9 @@ typedef struct xfs_fsop_bulkreq32 {
__s32 ocount; /* output count pointer */
} xfs_fsop_bulkreq32_t;
-static unsigned long
-xfs_ioctl32_bulkstat(unsigned long arg)
+STATIC unsigned long
+xfs_ioctl32_bulkstat(
+ unsigned long arg)
{
xfs_fsop_bulkreq32_t __user *p32 = (void __user *)arg;
xfs_fsop_bulkreq_t __user *p = compat_alloc_user_space(sizeof(*p));
@@ -78,11 +79,11 @@ xfs_ioctl32_bulkstat(unsigned long arg)
}
#endif
-static long
-__xfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg)
+STATIC long
+__linvfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg)
{
int error;
- struct inode *inode = f->f_dentry->d_inode;
+ struct inode *inode = f->f_dentry->d_inode;
vnode_t *vp = LINVFS_GET_VP(inode);
switch (cmd) {
@@ -152,12 +153,20 @@ __xfs_compat_ioctl(int mode, struct file *f, unsigned cmd, unsigned long arg)
return error;
}
-long xfs_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg)
+long
+linvfs_compat_ioctl(
+ struct file *f,
+ unsigned cmd,
+ unsigned long arg)
{
- return __xfs_compat_ioctl(0, f, cmd, arg);
+ return __linvfs_compat_ioctl(0, f, cmd, arg);
}
-long xfs_compat_invis_ioctl(struct file *f, unsigned cmd, unsigned long arg)
+long
+linvfs_compat_invis_ioctl(
+ struct file *f,
+ unsigned cmd,
+ unsigned long arg)
{
- return __xfs_compat_ioctl(IO_INVIS, f, cmd, arg);
+ return __linvfs_compat_ioctl(IO_INVIS, f, cmd, arg);
}
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.h b/fs/xfs/linux-2.6/xfs_ioctl32.h
index 779f69a4811..c874793a1dc 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl32.h
+++ b/fs/xfs/linux-2.6/xfs_ioctl32.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2004-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -30,5 +30,5 @@
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
-long xfs_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg);
-long xfs_compat_invis_ioctl(struct file *f, unsigned cmd, unsigned long arg);
+long linvfs_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg);
+long linvfs_compat_invis_ioctl(struct file *f, unsigned cmd, unsigned long arg);
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 71bb41019a1..42dc5e4662e 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -145,10 +145,10 @@ static inline void set_buffer_unwritten_io(struct buffer_head *bh)
#define xfs_inherit_nosymlinks xfs_params.inherit_nosym.val
#define xfs_rotorstep xfs_params.rotorstep.val
-#ifndef __smp_processor_id
-#define __smp_processor_id() smp_processor_id()
+#ifndef raw_smp_processor_id
+#define raw_smp_processor_id() smp_processor_id()
#endif
-#define current_cpu() __smp_processor_id()
+#define current_cpu() raw_smp_processor_id()
#define current_pid() (current->pid)
#define current_fsuid(cred) (current->fsuid)
#define current_fsgid(cred) (current->fsgid)
@@ -230,8 +230,10 @@ static inline void set_buffer_unwritten_io(struct buffer_head *bh)
* field (see the QCMD macro in quota.h). These macros help keep the
* code portable - they are not visible from the syscall interface.
*/
-#define Q_XSETGQLIM XQM_CMD(0x8) /* set groups disk limits */
-#define Q_XGETGQUOTA XQM_CMD(0x9) /* get groups disk limits */
+#define Q_XSETGQLIM XQM_CMD(8) /* set groups disk limits */
+#define Q_XGETGQUOTA XQM_CMD(9) /* get groups disk limits */
+#define Q_XSETPQLIM XQM_CMD(10) /* set projects disk limits */
+#define Q_XGETPQUOTA XQM_CMD(11) /* get projects disk limits */
/* IRIX uses a dynamic sizing algorithm (ndquot = 200 + numprocs*2) */
/* we may well need to fine-tune this if it ever becomes an issue. */
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index aa9daaea6c3..acab58c4804 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -209,30 +209,6 @@ unlock:
return (-status);
}
-/*
- * xfs_inval_cached_pages
- *
- * This routine is responsible for keeping direct I/O and buffered I/O
- * somewhat coherent. From here we make sure that we're at least
- * temporarily holding the inode I/O lock exclusively and then call
- * the page cache to flush and invalidate any cached pages. If there
- * are no cached pages this routine will be very quick.
- */
-void
-xfs_inval_cached_pages(
- vnode_t *vp,
- xfs_iocore_t *io,
- xfs_off_t offset,
- int write,
- int relock)
-{
- if (VN_CACHED(vp)) {
- xfs_inval_cached_trace(io, offset, -1, ctooff(offtoct(offset)), -1);
- VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(offset)), -1, FI_REMAPF_LOCKED);
- }
-
-}
-
ssize_t /* bytes read, or (-) error */
xfs_read(
bhv_desc_t *bdp,
@@ -304,10 +280,11 @@ xfs_read(
if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) &&
!(ioflags & IO_INVIS)) {
vrwlock_t locktype = VRWLOCK_READ;
+ int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
ret = -XFS_SEND_DATA(mp, DM_EVENT_READ,
BHV_TO_VNODE(bdp), *offset, size,
- FILP_DELAY_FLAG(file), &locktype);
+ dmflags, &locktype);
if (ret) {
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
goto unlock_isem;
@@ -867,11 +844,15 @@ retry:
!(ioflags & IO_INVIS)) {
xfs_rwunlock(bdp, locktype);
+ if (need_isem)
+ up(&inode->i_sem);
error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, vp,
DM_RIGHT_NULL, vp, DM_RIGHT_NULL, NULL, NULL,
0, 0, 0); /* Delay flag intentionally unused */
if (error)
- goto out_unlock_isem;
+ goto out_nounlocks;
+ if (need_isem)
+ down(&inode->i_sem);
xfs_rwlock(bdp, locktype);
pos = xip->i_d.di_size;
ret = 0;
@@ -986,6 +967,7 @@ retry:
out_unlock_isem:
if (need_isem)
up(&inode->i_sem);
+ out_nounlocks:
return -error;
}
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h
index d723e35254a..f197a720e39 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.h
+++ b/fs/xfs/linux-2.6/xfs_lrw.h
@@ -94,8 +94,6 @@ extern int xfs_bdstrat_cb(struct xfs_buf *);
extern int xfs_zero_eof(struct vnode *, struct xfs_iocore *, xfs_off_t,
xfs_fsize_t, xfs_fsize_t);
-extern void xfs_inval_cached_pages(struct vnode *, struct xfs_iocore *,
- xfs_off_t, int, int);
extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *,
const struct iovec *, unsigned int,
loff_t *, int, struct cred *);
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 53dc658cafa..f6dd7de2592 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -66,7 +66,6 @@
#include "xfs_buf_item.h"
#include "xfs_utils.h"
#include "xfs_version.h"
-#include "xfs_ioctl32.h"
#include <linux/namei.h>
#include <linux/init.h>
@@ -484,7 +483,7 @@ xfssyncd(
set_current_state(TASK_INTERRUPTIBLE);
timeleft = schedule_timeout(timeleft);
/* swsusp */
- try_to_freeze(PF_FREEZE);
+ try_to_freeze();
if (vfsp->vfs_flag & VFS_UMOUNT)
break;
@@ -591,8 +590,10 @@ linvfs_sync_super(
int error;
int flags = SYNC_FSDATA;
- if (wait)
- flags |= SYNC_WAIT;
+ if (unlikely(sb->s_frozen == SB_FREEZE_WRITE))
+ flags = SYNC_QUIESCE;
+ else
+ flags = SYNC_FSDATA | (wait ? SYNC_WAIT : 0);
VFS_SYNC(vfsp, flags, NULL, error);
sb->s_dirt = 0;
@@ -702,7 +703,8 @@ linvfs_getxquota(
struct vfs *vfsp = LINVFS_GET_VFS(sb);
int error, getmode;
- getmode = (type == GRPQUOTA) ? Q_XGETGQUOTA : Q_XGETQUOTA;
+ getmode = (type == USRQUOTA) ? Q_XGETQUOTA :
+ ((type == GRPQUOTA) ? Q_XGETGQUOTA : Q_XGETPQUOTA);
VFS_QUOTACTL(vfsp, getmode, id, (caddr_t)fdq, error);
return -error;
}
@@ -717,7 +719,8 @@ linvfs_setxquota(
struct vfs *vfsp = LINVFS_GET_VFS(sb);
int error, setmode;
- setmode = (type == GRPQUOTA) ? Q_XSETGQLIM : Q_XSETQLIM;
+ setmode = (type == USRQUOTA) ? Q_XSETQLIM :
+ ((type == GRPQUOTA) ? Q_XSETGQLIM : Q_XSETPQLIM);
VFS_QUOTACTL(vfsp, setmode, id, (caddr_t)fdq, error);
return -error;
}
diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h
index 76493991578..7ee1f714e9b 100644
--- a/fs/xfs/linux-2.6/xfs_vfs.h
+++ b/fs/xfs/linux-2.6/xfs_vfs.h
@@ -107,6 +107,7 @@ typedef enum {
#define SYNC_FSDATA 0x0020 /* flush fs data (e.g. superblocks) */
#define SYNC_REFCACHE 0x0040 /* prune some of the nfs ref cache */
#define SYNC_REMOUNT 0x0080 /* remount readonly, no dummy LRs */
+#define SYNC_QUIESCE 0x0100 /* quiesce fileystem for a snapshot */
typedef int (*vfs_mount_t)(bhv_desc_t *,
struct xfs_mount_args *, struct cred *);
diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c
index a832d165f24..250cad54e89 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.c
+++ b/fs/xfs/linux-2.6/xfs_vnode.c
@@ -411,13 +411,13 @@ vn_remove(
/* 0 */ (void *)(__psint_t)(vk), \
/* 1 */ (void *)(s), \
/* 2 */ (void *)(__psint_t) line, \
-/* 3 */ (void *)(vn_count(vp)), \
+/* 3 */ (void *)(__psint_t)(vn_count(vp)), \
/* 4 */ (void *)(ra), \
/* 5 */ (void *)(__psunsigned_t)(vp)->v_flag, \
/* 6 */ (void *)(__psint_t)current_cpu(), \
/* 7 */ (void *)(__psint_t)current_pid(), \
/* 8 */ (void *)__return_address, \
-/* 9 */ 0, 0, 0, 0, 0, 0, 0)
+/* 9 */ NULL, NULL, NULL, NULL, NULL, NULL, NULL)
/*
* Vnode tracing code.
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index 00466c3194a..a6e57c647be 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -426,7 +426,7 @@ typedef struct vattr {
u_long va_extsize; /* file extent size */
u_long va_nextents; /* number of extents in file */
u_long va_anextents; /* number of attr extents in file */
- int va_projid; /* project id */
+ prid_t va_projid; /* project id */
} vattr_t;
/*
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c
index 740d20d3318..46ce1e3ce1d 100644
--- a/fs/xfs/quota/xfs_dquot.c
+++ b/fs/xfs/quota/xfs_dquot.c
@@ -101,7 +101,7 @@ int xfs_dqerror_mod = 33;
* is the d_id field. The idea is to fill in the entire q_core
* when we read in the on disk dquot.
*/
-xfs_dquot_t *
+STATIC xfs_dquot_t *
xfs_qm_dqinit(
xfs_mount_t *mp,
xfs_dqid_t id,
@@ -286,7 +286,9 @@ xfs_qm_adjust_dqlimits(
* We also return 0 as the values of the timers in Q_GETQUOTA calls, when
* enforcement's off.
* In contrast, warnings are a little different in that they don't
- * 'automatically' get started when limits get exceeded.
+ * 'automatically' get started when limits get exceeded. They do
+ * get reset to zero, however, when we find the count to be under
+ * the soft limit (they are only ever set non-zero via userspace).
*/
void
xfs_qm_adjust_dqtimers(
@@ -315,6 +317,8 @@ xfs_qm_adjust_dqtimers(
INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
INT_SET(d->d_btimer, ARCH_CONVERT,
get_seconds() + XFS_QI_BTIMELIMIT(mp));
+ } else {
+ d->d_bwarns = 0;
}
} else {
if ((!d->d_blk_softlimit ||
@@ -336,6 +340,8 @@ xfs_qm_adjust_dqtimers(
INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
INT_SET(d->d_itimer, ARCH_CONVERT,
get_seconds() + XFS_QI_ITIMELIMIT(mp));
+ } else {
+ d->d_iwarns = 0;
}
} else {
if ((!d->d_ino_softlimit ||
@@ -357,6 +363,8 @@ xfs_qm_adjust_dqtimers(
INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT)))) {
INT_SET(d->d_rtbtimer, ARCH_CONVERT,
get_seconds() + XFS_QI_RTBTIMELIMIT(mp));
+ } else {
+ d->d_rtbwarns = 0;
}
} else {
if ((!d->d_rtb_softlimit ||
@@ -371,68 +379,6 @@ xfs_qm_adjust_dqtimers(
}
/*
- * Increment or reset warnings of a given dquot.
- */
-int
-xfs_qm_dqwarn(
- xfs_disk_dquot_t *d,
- uint flags)
-{
- int warned;
-
- /*
- * root's limits are not real limits.
- */
- if (!d->d_id)
- return (0);
-
- warned = 0;
- if (INT_GET(d->d_blk_softlimit, ARCH_CONVERT) &&
- (INT_GET(d->d_bcount, ARCH_CONVERT) >=
- INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) {
- if (flags & XFS_QMOPT_DOWARN) {
- INT_MOD(d->d_bwarns, ARCH_CONVERT, +1);
- warned++;
- }
- } else {
- if (!d->d_blk_softlimit ||
- (INT_GET(d->d_bcount, ARCH_CONVERT) <
- INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) {
- d->d_bwarns = 0;
- }
- }
-
- if (INT_GET(d->d_ino_softlimit, ARCH_CONVERT) > 0 &&
- (INT_GET(d->d_icount, ARCH_CONVERT) >=
- INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) {
- if (flags & XFS_QMOPT_DOWARN) {
- INT_MOD(d->d_iwarns, ARCH_CONVERT, +1);
- warned++;
- }
- } else {
- if (!d->d_ino_softlimit ||
- (INT_GET(d->d_icount, ARCH_CONVERT) <
- INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) {
- d->d_iwarns = 0;
- }
- }
-#ifdef QUOTADEBUG
- if (INT_GET(d->d_iwarns, ARCH_CONVERT))
- cmn_err(CE_DEBUG,
- "--------@@Inode warnings running : %Lu >= %Lu",
- INT_GET(d->d_icount, ARCH_CONVERT),
- INT_GET(d->d_ino_softlimit, ARCH_CONVERT));
- if (INT_GET(d->d_bwarns, ARCH_CONVERT))
- cmn_err(CE_DEBUG,
- "--------@@Blks warnings running : %Lu >= %Lu",
- INT_GET(d->d_bcount, ARCH_CONVERT),
- INT_GET(d->d_blk_softlimit, ARCH_CONVERT));
-#endif
- return (warned);
-}
-
-
-/*
* initialize a buffer full of dquots and log the whole thing
*/
STATIC void
@@ -461,9 +407,9 @@ xfs_qm_init_dquot_blk(
for (i = 0; i < XFS_QM_DQPERBLK(mp); i++, d++, curid++)
xfs_qm_dqinit_core(curid, type, d);
xfs_trans_dquot_buf(tp, bp,
- type & XFS_DQ_USER ?
- XFS_BLI_UDQUOT_BUF :
- XFS_BLI_GDQUOT_BUF);
+ (type & XFS_DQ_USER ? XFS_BLI_UDQUOT_BUF :
+ ((type & XFS_DQ_PROJ) ? XFS_BLI_PDQUOT_BUF :
+ XFS_BLI_GDQUOT_BUF)));
xfs_trans_log_buf(tp, bp, 0, BBTOB(XFS_QI_DQCHUNKLEN(mp)) - 1);
}
@@ -544,8 +490,7 @@ xfs_qm_dqalloc(
* the entire thing.
*/
xfs_qm_init_dquot_blk(tp, mp, INT_GET(dqp->q_core.d_id, ARCH_CONVERT),
- dqp->dq_flags & (XFS_DQ_USER|XFS_DQ_GROUP),
- bp);
+ dqp->dq_flags & XFS_DQ_ALLTYPES, bp);
if ((error = xfs_bmap_finish(&tp, &flist, firstblock, &committed))) {
goto error1;
@@ -675,8 +620,7 @@ xfs_qm_dqtobp(
/*
* A simple sanity check in case we got a corrupted dquot...
*/
- if (xfs_qm_dqcheck(ddq, id,
- dqp->dq_flags & (XFS_DQ_USER|XFS_DQ_GROUP),
+ if (xfs_qm_dqcheck(ddq, id, dqp->dq_flags & XFS_DQ_ALLTYPES,
flags & (XFS_QMOPT_DQREPAIR|XFS_QMOPT_DOWARN),
"dqtobp")) {
if (!(flags & XFS_QMOPT_DQREPAIR)) {
@@ -953,8 +897,8 @@ int
xfs_qm_dqget(
xfs_mount_t *mp,
xfs_inode_t *ip, /* locked inode (optional) */
- xfs_dqid_t id, /* gid or uid, depending on type */
- uint type, /* UDQUOT or GDQUOT */
+ xfs_dqid_t id, /* uid/projid/gid depending on type */
+ uint type, /* XFS_DQ_USER/XFS_DQ_PROJ/XFS_DQ_GROUP */
uint flags, /* DQALLOC, DQSUSER, DQREPAIR, DOWARN */
xfs_dquot_t **O_dqpp) /* OUT : locked incore dquot */
{
@@ -965,6 +909,7 @@ xfs_qm_dqget(
ASSERT(XFS_IS_QUOTA_RUNNING(mp));
if ((! XFS_IS_UQUOTA_ON(mp) && type == XFS_DQ_USER) ||
+ (! XFS_IS_PQUOTA_ON(mp) && type == XFS_DQ_PROJ) ||
(! XFS_IS_GQUOTA_ON(mp) && type == XFS_DQ_GROUP)) {
return (ESRCH);
}
@@ -983,7 +928,9 @@ xfs_qm_dqget(
again:
#ifdef DEBUG
- ASSERT(type == XFS_DQ_USER || type == XFS_DQ_GROUP);
+ ASSERT(type == XFS_DQ_USER ||
+ type == XFS_DQ_PROJ ||
+ type == XFS_DQ_GROUP);
if (ip) {
ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
if (type == XFS_DQ_USER)
@@ -1306,8 +1253,8 @@ xfs_qm_dqflush(
return (error);
}
- if (xfs_qm_dqcheck(&dqp->q_core, INT_GET(ddqp->d_id, ARCH_CONVERT), 0, XFS_QMOPT_DOWARN,
- "dqflush (incore copy)")) {
+ if (xfs_qm_dqcheck(&dqp->q_core, INT_GET(ddqp->d_id, ARCH_CONVERT),
+ 0, XFS_QMOPT_DOWARN, "dqflush (incore copy)")) {
xfs_force_shutdown(dqp->q_mount, XFS_CORRUPT_INCORE);
return XFS_ERROR(EIO);
}
@@ -1459,7 +1406,8 @@ xfs_dqlock2(
{
if (d1 && d2) {
ASSERT(d1 != d2);
- if (INT_GET(d1->q_core.d_id, ARCH_CONVERT) > INT_GET(d2->q_core.d_id, ARCH_CONVERT)) {
+ if (INT_GET(d1->q_core.d_id, ARCH_CONVERT) >
+ INT_GET(d2->q_core.d_id, ARCH_CONVERT)) {
xfs_dqlock(d2);
xfs_dqlock(d1);
} else {
@@ -1582,8 +1530,7 @@ xfs_qm_dqprint(xfs_dquot_t *dqp)
cmn_err(CE_DEBUG, "-----------KERNEL DQUOT----------------");
cmn_err(CE_DEBUG, "---- dquotID = %d",
(int)INT_GET(dqp->q_core.d_id, ARCH_CONVERT));
- cmn_err(CE_DEBUG, "---- type = %s",
- XFS_QM_ISUDQ(dqp) ? "USR" : "GRP");
+ cmn_err(CE_DEBUG, "---- type = %s", DQFLAGTO_TYPESTR(dqp));
cmn_err(CE_DEBUG, "---- fs = 0x%p", dqp->q_mount);
cmn_err(CE_DEBUG, "---- blkno = 0x%x", (int) dqp->q_blkno);
cmn_err(CE_DEBUG, "---- boffset = 0x%x", (int) dqp->q_bufoffset);
diff --git a/fs/xfs/quota/xfs_dquot.h b/fs/xfs/quota/xfs_dquot.h
index 0c3fe3175ba..39175103c8e 100644
--- a/fs/xfs/quota/xfs_dquot.h
+++ b/fs/xfs/quota/xfs_dquot.h
@@ -114,25 +114,18 @@ typedef struct xfs_dquot {
#define XFS_DQHOLD(dqp) ((dqp)->q_nrefs++)
/*
- * Quota Accounting flags
+ * Quota Accounting/Enforcement flags
*/
-#define XFS_ALL_QUOTA_ACCT (XFS_UQUOTA_ACCT | XFS_GQUOTA_ACCT)
-#define XFS_ALL_QUOTA_ENFD (XFS_UQUOTA_ENFD | XFS_GQUOTA_ENFD)
-#define XFS_ALL_QUOTA_CHKD (XFS_UQUOTA_CHKD | XFS_GQUOTA_CHKD)
-#define XFS_ALL_QUOTA_ACTV (XFS_UQUOTA_ACTIVE | XFS_GQUOTA_ACTIVE)
-#define XFS_ALL_QUOTA_ACCT_ENFD (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
- XFS_GQUOTA_ACCT|XFS_GQUOTA_ENFD)
+#define XFS_ALL_QUOTA_ACCT \
+ (XFS_UQUOTA_ACCT | XFS_GQUOTA_ACCT | XFS_PQUOTA_ACCT)
+#define XFS_ALL_QUOTA_ENFD (XFS_UQUOTA_ENFD | XFS_OQUOTA_ENFD)
+#define XFS_ALL_QUOTA_CHKD (XFS_UQUOTA_CHKD | XFS_OQUOTA_CHKD)
-#define XFS_IS_QUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_ALL_QUOTA_ACCT)
-#define XFS_IS_UQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_UQUOTA_ACCT)
-#define XFS_IS_GQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_GQUOTA_ACCT)
-
-/*
- * Quota Limit Enforcement flags
- */
+#define XFS_IS_QUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_ALL_QUOTA_ACCT)
#define XFS_IS_QUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_ALL_QUOTA_ENFD)
-#define XFS_IS_UQUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_UQUOTA_ENFD)
-#define XFS_IS_GQUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_GQUOTA_ENFD)
+#define XFS_IS_UQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_UQUOTA_ACCT)
+#define XFS_IS_PQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_PQUOTA_ACCT)
+#define XFS_IS_GQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_GQUOTA_ACCT)
#ifdef DEBUG
static inline int
@@ -167,6 +160,8 @@ XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp)
#define XFS_DQ_IS_ON_FREELIST(dqp) ((dqp)->dq_flnext != (dqp))
#define XFS_DQ_IS_DIRTY(dqp) ((dqp)->dq_flags & XFS_DQ_DIRTY)
#define XFS_QM_ISUDQ(dqp) ((dqp)->dq_flags & XFS_DQ_USER)
+#define XFS_QM_ISPDQ(dqp) ((dqp)->dq_flags & XFS_DQ_PROJ)
+#define XFS_QM_ISGDQ(dqp) ((dqp)->dq_flags & XFS_DQ_GROUP)
#define XFS_DQ_TO_QINF(dqp) ((dqp)->q_mount->m_quotainfo)
#define XFS_DQ_TO_QIP(dqp) (XFS_QM_ISUDQ(dqp) ? \
XFS_DQ_TO_QINF(dqp)->qi_uquotaip : \
@@ -174,7 +169,7 @@ XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp)
#define XFS_IS_THIS_QUOTA_OFF(d) (! (XFS_QM_ISUDQ(d) ? \
(XFS_IS_UQUOTA_ON((d)->q_mount)) : \
- (XFS_IS_GQUOTA_ON((d)->q_mount))))
+ (XFS_IS_OQUOTA_ON((d)->q_mount))))
#ifdef XFS_DQUOT_TRACE
/*
@@ -211,7 +206,6 @@ extern void xfs_qm_adjust_dqtimers(xfs_mount_t *,
xfs_disk_dquot_t *);
extern void xfs_qm_adjust_dqlimits(xfs_mount_t *,
xfs_disk_dquot_t *);
-extern int xfs_qm_dqwarn(xfs_disk_dquot_t *, uint);
extern int xfs_qm_dqget(xfs_mount_t *, xfs_inode_t *,
xfs_dqid_t, uint, uint, xfs_dquot_t **);
extern void xfs_qm_dqput(xfs_dquot_t *);
diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c
index a5425ee6e7b..f5271b7b1e8 100644
--- a/fs/xfs/quota/xfs_dquot_item.c
+++ b/fs/xfs/quota/xfs_dquot_item.c
@@ -428,7 +428,7 @@ xfs_qm_dquot_logitem_committing(
/*
* This is the ops vector for dquots
*/
-struct xfs_item_ops xfs_dquot_item_ops = {
+STATIC struct xfs_item_ops xfs_dquot_item_ops = {
.iop_size = (uint(*)(xfs_log_item_t*))xfs_qm_dquot_logitem_size,
.iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
xfs_qm_dquot_logitem_format,
@@ -646,7 +646,7 @@ xfs_qm_qoffend_logitem_committing(xfs_qoff_logitem_t *qip, xfs_lsn_t commit_lsn)
return;
}
-struct xfs_item_ops xfs_qm_qoffend_logitem_ops = {
+STATIC struct xfs_item_ops xfs_qm_qoffend_logitem_ops = {
.iop_size = (uint(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_size,
.iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
xfs_qm_qoff_logitem_format,
@@ -669,7 +669,7 @@ struct xfs_item_ops xfs_qm_qoffend_logitem_ops = {
/*
* This is the ops vector shared by all quotaoff-start log items.
*/
-struct xfs_item_ops xfs_qm_qoff_logitem_ops = {
+STATIC struct xfs_item_ops xfs_qm_qoff_logitem_ops = {
.iop_size = (uint(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_size,
.iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
xfs_qm_qoff_logitem_format,
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 89f2cd656eb..f665ca8f9e9 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -81,12 +81,18 @@ struct xfs_qm *xfs_Gqm;
kmem_zone_t *qm_dqzone;
kmem_zone_t *qm_dqtrxzone;
-kmem_shaker_t xfs_qm_shaker;
+STATIC kmem_shaker_t xfs_qm_shaker;
STATIC void xfs_qm_list_init(xfs_dqlist_t *, char *, int);
STATIC void xfs_qm_list_destroy(xfs_dqlist_t *);
+STATIC void xfs_qm_freelist_init(xfs_frlist_t *);
+STATIC void xfs_qm_freelist_destroy(xfs_frlist_t *);
+STATIC int xfs_qm_mplist_nowait(xfs_mount_t *);
+STATIC int xfs_qm_dqhashlock_nowait(xfs_dquot_t *);
+
STATIC int xfs_qm_init_quotainos(xfs_mount_t *);
+STATIC int xfs_qm_init_quotainfo(xfs_mount_t *);
STATIC int xfs_qm_shake(int, unsigned int);
#ifdef DEBUG
@@ -184,7 +190,7 @@ xfs_Gqm_init(void)
/*
* Destroy the global quota manager when its reference count goes to zero.
*/
-void
+STATIC void
xfs_qm_destroy(
struct xfs_qm *xqm)
{
@@ -304,9 +310,9 @@ xfs_qm_mount_quotainit(
uint flags)
{
/*
- * User or group quotas has to be on.
+ * User, projects or group quotas has to be on.
*/
- ASSERT(flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA));
+ ASSERT(flags & (XFSMNT_UQUOTA | XFSMNT_PQUOTA | XFSMNT_GQUOTA));
/*
* Initialize the flags in the mount structure. From this point
@@ -324,7 +330,11 @@ xfs_qm_mount_quotainit(
if (flags & XFSMNT_GQUOTA) {
mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE);
if (flags & XFSMNT_GQUOTAENF)
- mp->m_qflags |= XFS_GQUOTA_ENFD;
+ mp->m_qflags |= XFS_OQUOTA_ENFD;
+ } else if (flags & XFSMNT_PQUOTA) {
+ mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE);
+ if (flags & XFSMNT_PQUOTAENF)
+ mp->m_qflags |= XFS_OQUOTA_ENFD;
}
}
@@ -357,11 +367,11 @@ xfs_qm_mount_quotas(
/*
* If a file system had quotas running earlier, but decided to
- * mount without -o quota/uquota/gquota options, revoke the
+ * mount without -o uquota/pquota/gquota options, revoke the
* quotachecked license, and bail out.
*/
if (! XFS_IS_QUOTA_ON(mp) &&
- (mp->m_sb.sb_qflags & (XFS_UQUOTA_ACCT|XFS_GQUOTA_ACCT))) {
+ (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT)) {
mp->m_qflags = 0;
goto write_changes;
}
@@ -509,7 +519,7 @@ out:
* Flush all dquots of the given file system to disk. The dquots are
* _not_ purged from memory here, just their data written to disk.
*/
-int
+STATIC int
xfs_qm_dqflush_all(
xfs_mount_t *mp,
int flags)
@@ -613,7 +623,7 @@ xfs_qm_detach_gdquots(
STATIC int
xfs_qm_dqpurge_int(
xfs_mount_t *mp,
- uint flags) /* QUOTAOFF/UMOUNTING/UQUOTA/GQUOTA */
+ uint flags) /* QUOTAOFF/UMOUNTING/UQUOTA/PQUOTA/GQUOTA */
{
xfs_dquot_t *dqp;
uint dqtype;
@@ -625,6 +635,7 @@ xfs_qm_dqpurge_int(
return (0);
dqtype = (flags & XFS_QMOPT_UQUOTA) ? XFS_DQ_USER : 0;
+ dqtype |= (flags & XFS_QMOPT_PQUOTA) ? XFS_DQ_PROJ : 0;
dqtype |= (flags & XFS_QMOPT_GQUOTA) ? XFS_DQ_GROUP : 0;
xfs_qm_mplist_lock(mp);
@@ -734,11 +745,11 @@ xfs_qm_dqattach_one(
/*
* udqhint is the i_udquot field in inode, and is non-NULL only
- * when the type arg is XFS_DQ_GROUP. Its purpose is to save a
+ * when the type arg is group/project. Its purpose is to save a
* lookup by dqid (xfs_qm_dqget) by caching a group dquot inside
* the user dquot.
*/
- ASSERT(!udqhint || type == XFS_DQ_GROUP);
+ ASSERT(!udqhint || type == XFS_DQ_GROUP || type == XFS_DQ_PROJ);
if (udqhint && !dolock)
xfs_dqlock(udqhint);
@@ -897,8 +908,8 @@ xfs_qm_dqattach_grouphint(
/*
- * Given a locked inode, attach dquot(s) to it, taking UQUOTAON / GQUOTAON
- * in to account.
+ * Given a locked inode, attach dquot(s) to it, taking U/G/P-QUOTAON
+ * into account.
* If XFS_QMOPT_DQALLOC, the dquot(s) will be allocated if needed.
* If XFS_QMOPT_DQLOCK, the dquot(s) will be returned locked. This option pretty
* much made this code a complete mess, but it has been pretty useful.
@@ -937,8 +948,13 @@ xfs_qm_dqattach(
nquotas++;
}
ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
- if (XFS_IS_GQUOTA_ON(mp)) {
- error = xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP,
+ if (XFS_IS_OQUOTA_ON(mp)) {
+ error = XFS_IS_GQUOTA_ON(mp) ?
+ xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP,
+ flags & XFS_QMOPT_DQALLOC,
+ flags & XFS_QMOPT_DQLOCK,
+ ip->i_udquot, &ip->i_gdquot) :
+ xfs_qm_dqattach_one(ip, ip->i_d.di_projid, XFS_DQ_PROJ,
flags & XFS_QMOPT_DQALLOC,
flags & XFS_QMOPT_DQLOCK,
ip->i_udquot, &ip->i_gdquot);
@@ -989,7 +1005,7 @@ xfs_qm_dqattach(
}
if (XFS_IS_UQUOTA_ON(mp))
ASSERT(ip->i_udquot);
- if (XFS_IS_GQUOTA_ON(mp))
+ if (XFS_IS_OQUOTA_ON(mp))
ASSERT(ip->i_gdquot);
}
#endif
@@ -1018,13 +1034,13 @@ xfs_qm_dqdetach(
ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_uquotino);
ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_gquotino);
- if (ip->i_udquot)
- xfs_dqtrace_entry_ino(ip->i_udquot, "DQDETTACH", ip);
if (ip->i_udquot) {
+ xfs_dqtrace_entry_ino(ip->i_udquot, "DQDETTACH", ip);
xfs_qm_dqrele(ip->i_udquot);
ip->i_udquot = NULL;
}
if (ip->i_gdquot) {
+ xfs_dqtrace_entry_ino(ip->i_gdquot, "DQDETTACH", ip);
xfs_qm_dqrele(ip->i_gdquot);
ip->i_gdquot = NULL;
}
@@ -1149,7 +1165,7 @@ xfs_qm_sync(
* This initializes all the quota information that's kept in the
* mount structure
*/
-int
+STATIC int
xfs_qm_init_quotainfo(
xfs_mount_t *mp)
{
@@ -1202,8 +1218,9 @@ xfs_qm_init_quotainfo(
* and group quotas, at least not at this point.
*/
error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)0,
- (XFS_IS_UQUOTA_RUNNING(mp)) ?
- XFS_DQ_USER : XFS_DQ_GROUP,
+ XFS_IS_UQUOTA_RUNNING(mp) ? XFS_DQ_USER :
+ (XFS_IS_GQUOTA_RUNNING(mp) ? XFS_DQ_GROUP :
+ XFS_DQ_PROJ),
XFS_QMOPT_DQSUSER|XFS_QMOPT_DOWARN,
&dqp);
if (! error) {
@@ -1234,6 +1251,10 @@ xfs_qm_init_quotainfo(
INT_GET(ddqp->d_iwarns, ARCH_CONVERT) ?
INT_GET(ddqp->d_iwarns, ARCH_CONVERT) :
XFS_QM_IWARNLIMIT;
+ qinf->qi_rtbwarnlimit =
+ INT_GET(ddqp->d_rtbwarns, ARCH_CONVERT) ?
+ INT_GET(ddqp->d_rtbwarns, ARCH_CONVERT) :
+ XFS_QM_RTBWARNLIMIT;
qinf->qi_bhardlimit =
INT_GET(ddqp->d_blk_hardlimit, ARCH_CONVERT);
qinf->qi_bsoftlimit =
@@ -1259,6 +1280,7 @@ xfs_qm_init_quotainfo(
qinf->qi_rtbtimelimit = XFS_QM_RTBTIMELIMIT;
qinf->qi_bwarnlimit = XFS_QM_BWARNLIMIT;
qinf->qi_iwarnlimit = XFS_QM_IWARNLIMIT;
+ qinf->qi_rtbwarnlimit = XFS_QM_RTBWARNLIMIT;
}
return (0);
@@ -1366,13 +1388,20 @@ xfs_qm_dqget_noattach(
ASSERT(udqp);
}
- if (XFS_IS_GQUOTA_ON(mp)) {
+ if (XFS_IS_OQUOTA_ON(mp)) {
ASSERT(ip->i_gdquot == NULL);
if (udqp)
xfs_dqunlock(udqp);
- if ((error = xfs_qm_dqget(mp, ip, ip->i_d.di_gid, XFS_DQ_GROUP,
- XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN,
- &gdqp))) {
+ error = XFS_IS_GQUOTA_ON(mp) ?
+ xfs_qm_dqget(mp, ip,
+ ip->i_d.di_gid, XFS_DQ_GROUP,
+ XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN,
+ &gdqp) :
+ xfs_qm_dqget(mp, ip,
+ ip->i_d.di_projid, XFS_DQ_PROJ,
+ XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN,
+ &gdqp);
+ if (error) {
if (udqp)
xfs_qm_dqrele(udqp);
ASSERT(error != ESRCH);
@@ -1521,8 +1550,10 @@ xfs_qm_reset_dqcounts(
INT_SET(ddq->d_rtbcount, ARCH_CONVERT, 0ULL);
INT_SET(ddq->d_btimer, ARCH_CONVERT, (time_t)0);
INT_SET(ddq->d_itimer, ARCH_CONVERT, (time_t)0);
+ INT_SET(ddq->d_rtbtimer, ARCH_CONVERT, (time_t)0);
INT_SET(ddq->d_bwarns, ARCH_CONVERT, 0UL);
INT_SET(ddq->d_iwarns, ARCH_CONVERT, 0UL);
+ INT_SET(ddq->d_rtbwarns, ARCH_CONVERT, 0UL);
ddq = (xfs_disk_dquot_t *) ((xfs_dqblk_t *)ddq + 1);
}
@@ -1541,11 +1572,14 @@ xfs_qm_dqiter_bufs(
int error;
int notcommitted;
int incr;
+ int type;
ASSERT(blkcnt > 0);
notcommitted = 0;
incr = (blkcnt > XFS_QM_MAX_DQCLUSTER_LOGSZ) ?
XFS_QM_MAX_DQCLUSTER_LOGSZ : blkcnt;
+ type = flags & XFS_QMOPT_UQUOTA ? XFS_DQ_USER :
+ (flags & XFS_QMOPT_PQUOTA ? XFS_DQ_PROJ : XFS_DQ_GROUP);
error = 0;
/*
@@ -1564,9 +1598,7 @@ xfs_qm_dqiter_bufs(
if (error)
break;
- (void) xfs_qm_reset_dqcounts(mp, bp, firstid,
- flags & XFS_QMOPT_UQUOTA ?
- XFS_DQ_USER : XFS_DQ_GROUP);
+ (void) xfs_qm_reset_dqcounts(mp, bp, firstid, type);
xfs_bdwrite(mp, bp);
/*
* goto the next block.
@@ -1578,7 +1610,7 @@ xfs_qm_dqiter_bufs(
}
/*
- * Iterate over all allocated USR/GRP dquots in the system, calling a
+ * Iterate over all allocated USR/GRP/PRJ dquots in the system, calling a
* caller supplied function for every chunk of dquots that we find.
*/
STATIC int
@@ -1849,7 +1881,7 @@ xfs_qm_dqusage_adjust(
xfs_qm_quotacheck_dqadjust(udqp, nblks, rtblks);
xfs_qm_dqput(udqp);
}
- if (XFS_IS_GQUOTA_ON(mp)) {
+ if (XFS_IS_OQUOTA_ON(mp)) {
ASSERT(gdqp);
xfs_qm_quotacheck_dqadjust(gdqp, nblks, rtblks);
xfs_qm_dqput(gdqp);
@@ -1898,7 +1930,7 @@ xfs_qm_quotacheck(
cmn_err(CE_NOTE, "XFS quotacheck %s: Please wait.", mp->m_fsname);
/*
- * First we go thru all the dquots on disk, USR and GRP, and reset
+ * First we go thru all the dquots on disk, USR and GRP/PRJ, and reset
* their counters to zero. We need a clean slate.
* We don't log our changes till later.
*/
@@ -1909,9 +1941,10 @@ xfs_qm_quotacheck(
}
if ((gip = XFS_QI_GQIP(mp))) {
- if ((error = xfs_qm_dqiterate(mp, gip, XFS_QMOPT_GQUOTA)))
+ if ((error = xfs_qm_dqiterate(mp, gip, XFS_IS_GQUOTA_ON(mp) ?
+ XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA)))
goto error_return;
- flags |= XFS_GQUOTA_CHKD;
+ flags |= XFS_OQUOTA_CHKD;
}
do {
@@ -1938,7 +1971,7 @@ xfs_qm_quotacheck(
if (error) {
xfs_qm_dqpurge_all(mp,
XFS_QMOPT_UQUOTA|XFS_QMOPT_GQUOTA|
- XFS_QMOPT_QUOTAOFF);
+ XFS_QMOPT_PQUOTA|XFS_QMOPT_QUOTAOFF);
goto error_return;
}
/*
@@ -1961,7 +1994,7 @@ xfs_qm_quotacheck(
* quotachecked status, since we won't be doing accounting for
* that type anymore.
*/
- mp->m_qflags &= ~(XFS_GQUOTA_CHKD | XFS_UQUOTA_CHKD);
+ mp->m_qflags &= ~(XFS_OQUOTA_CHKD | XFS_UQUOTA_CHKD);
mp->m_qflags |= flags;
XQM_LIST_PRINT(&(XFS_QI_MPL_LIST(mp)), MPL_NEXT, "++++ Mp list +++");
@@ -2013,7 +2046,7 @@ xfs_qm_init_quotainos(
0, 0, &uip, 0)))
return XFS_ERROR(error);
}
- if (XFS_IS_GQUOTA_ON(mp) &&
+ if (XFS_IS_OQUOTA_ON(mp) &&
mp->m_sb.sb_gquotino != NULLFSINO) {
ASSERT(mp->m_sb.sb_gquotino > 0);
if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
@@ -2043,10 +2076,12 @@ xfs_qm_init_quotainos(
flags &= ~XFS_QMOPT_SBVERSION;
}
- if (XFS_IS_GQUOTA_ON(mp) && gip == NULL) {
- if ((error = xfs_qm_qino_alloc(mp, &gip,
- sbflags | XFS_SB_GQUOTINO,
- flags | XFS_QMOPT_GQUOTA))) {
+ if (XFS_IS_OQUOTA_ON(mp) && gip == NULL) {
+ flags |= (XFS_IS_GQUOTA_ON(mp) ?
+ XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA);
+ error = xfs_qm_qino_alloc(mp, &gip,
+ sbflags | XFS_SB_GQUOTINO, flags);
+ if (error) {
if (uip)
VN_RELE(XFS_ITOV(uip));
@@ -2452,6 +2487,7 @@ xfs_qm_vop_dqalloc(
xfs_inode_t *ip,
uid_t uid,
gid_t gid,
+ prid_t prid,
uint flags,
xfs_dquot_t **O_udqpp,
xfs_dquot_t **O_gdqpp)
@@ -2483,8 +2519,7 @@ xfs_qm_vop_dqalloc(
}
uq = gq = NULL;
- if ((flags & XFS_QMOPT_UQUOTA) &&
- XFS_IS_UQUOTA_ON(mp)) {
+ if ((flags & XFS_QMOPT_UQUOTA) && XFS_IS_UQUOTA_ON(mp)) {
if (ip->i_d.di_uid != uid) {
/*
* What we need is the dquot that has this uid, and
@@ -2522,8 +2557,7 @@ xfs_qm_vop_dqalloc(
xfs_dqunlock(uq);
}
}
- if ((flags & XFS_QMOPT_GQUOTA) &&
- XFS_IS_GQUOTA_ON(mp)) {
+ if ((flags & XFS_QMOPT_GQUOTA) && XFS_IS_GQUOTA_ON(mp)) {
if (ip->i_d.di_gid != gid) {
xfs_iunlock(ip, lockflags);
if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)gid,
@@ -2546,6 +2580,29 @@ xfs_qm_vop_dqalloc(
XFS_DQHOLD(gq);
xfs_dqunlock(gq);
}
+ } else if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) {
+ if (ip->i_d.di_projid != prid) {
+ xfs_iunlock(ip, lockflags);
+ if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid,
+ XFS_DQ_PROJ,
+ XFS_QMOPT_DQALLOC |
+ XFS_QMOPT_DOWARN,
+ &gq))) {
+ if (uq)
+ xfs_qm_dqrele(uq);
+ ASSERT(error != ENOENT);
+ return (error);
+ }
+ xfs_dqunlock(gq);
+ lockflags = XFS_ILOCK_SHARED;
+ xfs_ilock(ip, lockflags);
+ } else {
+ ASSERT(ip->i_gdquot);
+ gq = ip->i_gdquot;
+ xfs_dqlock(gq);
+ XFS_DQHOLD(gq);
+ xfs_dqunlock(gq);
+ }
}
if (uq)
xfs_dqtrace_entry_ino(uq, "DQALLOC", ip);
@@ -2574,6 +2631,9 @@ xfs_qm_vop_chown(
xfs_dquot_t *newdq)
{
xfs_dquot_t *prevdq;
+ uint bfield = XFS_IS_REALTIME_INODE(ip) ?
+ XFS_TRANS_DQ_RTBCOUNT : XFS_TRANS_DQ_BCOUNT;
+
ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount));
@@ -2582,20 +2642,12 @@ xfs_qm_vop_chown(
ASSERT(prevdq);
ASSERT(prevdq != newdq);
- xfs_trans_mod_dquot(tp, prevdq,
- XFS_TRANS_DQ_BCOUNT,
- -(ip->i_d.di_nblocks));
- xfs_trans_mod_dquot(tp, prevdq,
- XFS_TRANS_DQ_ICOUNT,
- -1);
+ xfs_trans_mod_dquot(tp, prevdq, bfield, -(ip->i_d.di_nblocks));
+ xfs_trans_mod_dquot(tp, prevdq, XFS_TRANS_DQ_ICOUNT, -1);
/* the sparkling new dquot */
- xfs_trans_mod_dquot(tp, newdq,
- XFS_TRANS_DQ_BCOUNT,
- ip->i_d.di_nblocks);
- xfs_trans_mod_dquot(tp, newdq,
- XFS_TRANS_DQ_ICOUNT,
- 1);
+ xfs_trans_mod_dquot(tp, newdq, bfield, ip->i_d.di_nblocks);
+ xfs_trans_mod_dquot(tp, newdq, XFS_TRANS_DQ_ICOUNT, 1);
/*
* Take an extra reference, because the inode
@@ -2611,7 +2663,7 @@ xfs_qm_vop_chown(
}
/*
- * Quota reservations for setattr(AT_UID|AT_GID).
+ * Quota reservations for setattr(AT_UID|AT_GID|AT_PROJID).
*/
int
xfs_qm_vop_chown_reserve(
@@ -2623,7 +2675,7 @@ xfs_qm_vop_chown_reserve(
{
int error;
xfs_mount_t *mp;
- uint delblks;
+ uint delblks, blkflags;
xfs_dquot_t *unresudq, *unresgdq, *delblksudq, *delblksgdq;
ASSERT(XFS_ISLOCKED_INODE(ip));
@@ -2632,6 +2684,8 @@ xfs_qm_vop_chown_reserve(
delblks = ip->i_delayed_blks;
delblksudq = delblksgdq = unresudq = unresgdq = NULL;
+ blkflags = XFS_IS_REALTIME_INODE(ip) ?
+ XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS;
if (XFS_IS_UQUOTA_ON(mp) && udqp &&
ip->i_d.di_uid != (uid_t)INT_GET(udqp->q_core.d_id, ARCH_CONVERT)) {
@@ -2646,18 +2700,22 @@ xfs_qm_vop_chown_reserve(
unresudq = ip->i_udquot;
}
}
- if (XFS_IS_GQUOTA_ON(ip->i_mount) && gdqp &&
- ip->i_d.di_gid != INT_GET(gdqp->q_core.d_id, ARCH_CONVERT)) {
- delblksgdq = gdqp;
- if (delblks) {
- ASSERT(ip->i_gdquot);
- unresgdq = ip->i_gdquot;
+ if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) {
+ if ((XFS_IS_GQUOTA_ON(ip->i_mount) && ip->i_d.di_gid !=
+ INT_GET(gdqp->q_core.d_id, ARCH_CONVERT)) ||
+ (XFS_IS_PQUOTA_ON(ip->i_mount) && ip->i_d.di_projid !=
+ INT_GET(gdqp->q_core.d_id, ARCH_CONVERT))) {
+ delblksgdq = gdqp;
+ if (delblks) {
+ ASSERT(ip->i_gdquot);
+ unresgdq = ip->i_gdquot;
+ }
}
}
if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
delblksudq, delblksgdq, ip->i_d.di_nblocks, 1,
- flags | XFS_QMOPT_RES_REGBLKS)))
+ flags | blkflags)))
return (error);
/*
@@ -2674,11 +2732,11 @@ xfs_qm_vop_chown_reserve(
ASSERT(unresudq || unresgdq);
if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0,
- flags | XFS_QMOPT_RES_REGBLKS)))
+ flags | blkflags)))
return (error);
xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0,
- XFS_QMOPT_RES_REGBLKS);
+ blkflags);
}
return (0);
@@ -2751,7 +2809,7 @@ xfs_qm_vop_dqattach_and_dqmod_newinode(
}
/* ------------- list stuff -----------------*/
-void
+STATIC void
xfs_qm_freelist_init(xfs_frlist_t *ql)
{
ql->qh_next = ql->qh_prev = (xfs_dquot_t *) ql;
@@ -2760,7 +2818,7 @@ xfs_qm_freelist_init(xfs_frlist_t *ql)
ql->qh_nelems = 0;
}
-void
+STATIC void
xfs_qm_freelist_destroy(xfs_frlist_t *ql)
{
xfs_dquot_t *dqp, *nextdqp;
@@ -2786,7 +2844,7 @@ xfs_qm_freelist_destroy(xfs_frlist_t *ql)
ASSERT(ql->qh_nelems == 0);
}
-void
+STATIC void
xfs_qm_freelist_insert(xfs_frlist_t *ql, xfs_dquot_t *dq)
{
dq->dq_flnext = ql->qh_next;
@@ -2816,7 +2874,7 @@ xfs_qm_freelist_append(xfs_frlist_t *ql, xfs_dquot_t *dq)
xfs_qm_freelist_insert((xfs_frlist_t *)ql->qh_prev, dq);
}
-int
+STATIC int
xfs_qm_dqhashlock_nowait(
xfs_dquot_t *dqp)
{
@@ -2836,7 +2894,7 @@ xfs_qm_freelist_lock_nowait(
return (locked);
}
-int
+STATIC int
xfs_qm_mplist_nowait(
xfs_mount_t *mp)
{
diff --git a/fs/xfs/quota/xfs_qm.h b/fs/xfs/quota/xfs_qm.h
index dcf1a7a831d..b03eecf3b6c 100644
--- a/fs/xfs/quota/xfs_qm.h
+++ b/fs/xfs/quota/xfs_qm.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -133,8 +133,9 @@ typedef struct xfs_quotainfo {
time_t qi_btimelimit; /* limit for blks timer */
time_t qi_itimelimit; /* limit for inodes timer */
time_t qi_rtbtimelimit;/* limit for rt blks timer */
- xfs_qwarncnt_t qi_bwarnlimit; /* limit for num warnings */
- xfs_qwarncnt_t qi_iwarnlimit; /* limit for num warnings */
+ xfs_qwarncnt_t qi_bwarnlimit; /* limit for blks warnings */
+ xfs_qwarncnt_t qi_iwarnlimit; /* limit for inodes warnings */
+ xfs_qwarncnt_t qi_rtbwarnlimit;/* limit for rt blks warnings */
mutex_t qi_quotaofflock;/* to serialize quotaoff */
xfs_filblks_t qi_dqchunklen; /* # BBs in a chunk of dqs */
uint qi_dqperchunk; /* # ondisk dqs in above chunk */
@@ -176,6 +177,7 @@ typedef struct xfs_dquot_acct {
#define XFS_QM_BWARNLIMIT 5
#define XFS_QM_IWARNLIMIT 5
+#define XFS_QM_RTBWARNLIMIT 5
#define XFS_QM_LOCK(xqm) (mutex_lock(&xqm##_lock, PINOD))
#define XFS_QM_UNLOCK(xqm) (mutex_unlock(&xqm##_lock))
@@ -184,7 +186,6 @@ typedef struct xfs_dquot_acct {
extern void xfs_mount_reset_sbqflags(xfs_mount_t *);
-extern int xfs_qm_init_quotainfo(xfs_mount_t *);
extern void xfs_qm_destroy_quotainfo(xfs_mount_t *);
extern int xfs_qm_mount_quotas(xfs_mount_t *, int);
extern void xfs_qm_mount_quotainit(xfs_mount_t *, uint);
@@ -203,7 +204,7 @@ extern void xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint);
/* vop stuff */
extern int xfs_qm_vop_dqalloc(xfs_mount_t *, xfs_inode_t *,
- uid_t, gid_t, uint,
+ uid_t, gid_t, prid_t, uint,
xfs_dquot_t **, xfs_dquot_t **);
extern void xfs_qm_vop_dqattach_and_dqmod_newinode(
xfs_trans_t *, xfs_inode_t *,
@@ -215,14 +216,9 @@ extern int xfs_qm_vop_chown_reserve(xfs_trans_t *, xfs_inode_t *,
xfs_dquot_t *, xfs_dquot_t *, uint);
/* list stuff */
-extern void xfs_qm_freelist_init(xfs_frlist_t *);
-extern void xfs_qm_freelist_destroy(xfs_frlist_t *);
-extern void xfs_qm_freelist_insert(xfs_frlist_t *, xfs_dquot_t *);
extern void xfs_qm_freelist_append(xfs_frlist_t *, xfs_dquot_t *);
extern void xfs_qm_freelist_unlink(xfs_dquot_t *);
extern int xfs_qm_freelist_lock_nowait(xfs_qm_t *);
-extern int xfs_qm_mplist_nowait(xfs_mount_t *);
-extern int xfs_qm_dqhashlock_nowait(xfs_dquot_t *);
/* system call interface */
extern int xfs_qm_quotactl(bhv_desc_t *, int, int, xfs_caddr_t);
diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c
index be67d9c265f..dc3c37a1e15 100644
--- a/fs/xfs/quota/xfs_qm_bhv.c
+++ b/fs/xfs/quota/xfs_qm_bhv.c
@@ -71,10 +71,13 @@
#define MNTOPT_NOQUOTA "noquota" /* no quotas */
#define MNTOPT_USRQUOTA "usrquota" /* user quota enabled */
#define MNTOPT_GRPQUOTA "grpquota" /* group quota enabled */
+#define MNTOPT_PRJQUOTA "prjquota" /* project quota enabled */
#define MNTOPT_UQUOTA "uquota" /* user quota (IRIX variant) */
#define MNTOPT_GQUOTA "gquota" /* group quota (IRIX variant) */
+#define MNTOPT_PQUOTA "pquota" /* project quota (IRIX variant) */
#define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */
#define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */
+#define MNTOPT_PQUOTANOENF "pqnoenforce"/* project quota limit enforcement */
#define MNTOPT_QUOTANOENF "qnoenforce" /* same as uqnoenforce */
STATIC int
@@ -109,6 +112,14 @@ xfs_qm_parseargs(
args->flags |= XFSMNT_UQUOTA;
args->flags &= ~XFSMNT_UQUOTAENF;
referenced = 1;
+ } else if (!strcmp(this_char, MNTOPT_PQUOTA) ||
+ !strcmp(this_char, MNTOPT_PRJQUOTA)) {
+ args->flags |= XFSMNT_PQUOTA | XFSMNT_PQUOTAENF;
+ referenced = 1;
+ } else if (!strcmp(this_char, MNTOPT_PQUOTANOENF)) {
+ args->flags |= XFSMNT_PQUOTA;
+ args->flags &= ~XFSMNT_PQUOTAENF;
+ referenced = 1;
} else if (!strcmp(this_char, MNTOPT_GQUOTA) ||
!strcmp(this_char, MNTOPT_GRPQUOTA)) {
args->flags |= XFSMNT_GQUOTA | XFSMNT_GQUOTAENF;
@@ -127,6 +138,12 @@ xfs_qm_parseargs(
*this_char++ = ',';
}
+ if ((args->flags & XFSMNT_GQUOTA) && (args->flags & XFSMNT_PQUOTA)) {
+ cmn_err(CE_WARN,
+ "XFS: cannot mount with both project and group quota");
+ return XFS_ERROR(EINVAL);
+ }
+
PVFS_PARSEARGS(BHV_NEXT(bhv), options, args, update, error);
if (!error && !referenced)
bhv_remove_vfsops(bhvtovfs(bhv), VFS_POSITION_QM);
@@ -148,13 +165,19 @@ xfs_qm_showargs(
seq_puts(m, "," MNTOPT_UQUOTANOENF);
}
+ if (mp->m_qflags & XFS_PQUOTA_ACCT) {
+ (mp->m_qflags & XFS_OQUOTA_ENFD) ?
+ seq_puts(m, "," MNTOPT_PRJQUOTA) :
+ seq_puts(m, "," MNTOPT_PQUOTANOENF);
+ }
+
if (mp->m_qflags & XFS_GQUOTA_ACCT) {
- (mp->m_qflags & XFS_GQUOTA_ENFD) ?
+ (mp->m_qflags & XFS_OQUOTA_ENFD) ?
seq_puts(m, "," MNTOPT_GRPQUOTA) :
seq_puts(m, "," MNTOPT_GQUOTANOENF);
}
- if (!(mp->m_qflags & (XFS_UQUOTA_ACCT|XFS_GQUOTA_ACCT)))
+ if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT))
seq_puts(m, "," MNTOPT_NOQUOTA);
PVFS_SHOWARGS(BHV_NEXT(bhv), m, error);
@@ -171,7 +194,7 @@ xfs_qm_mount(
struct xfs_mount *mp = XFS_VFSTOM(vfsp);
int error;
- if (args->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA))
+ if (args->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA | XFSMNT_PQUOTA))
xfs_qm_mount_quotainit(mp, args->flags);
PVFS_MOUNT(BHV_NEXT(bhv), args, cr, error);
return error;
@@ -255,16 +278,17 @@ xfs_qm_newmount(
uint *quotaflags)
{
uint quotaondisk;
- uint uquotaondisk = 0, gquotaondisk = 0;
+ uint uquotaondisk = 0, gquotaondisk = 0, pquotaondisk = 0;
*quotaflags = 0;
*needquotamount = B_FALSE;
quotaondisk = XFS_SB_VERSION_HASQUOTA(&mp->m_sb) &&
- mp->m_sb.sb_qflags & (XFS_UQUOTA_ACCT|XFS_GQUOTA_ACCT);
+ (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT);
if (quotaondisk) {
uquotaondisk = mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT;
+ pquotaondisk = mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT;
gquotaondisk = mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT;
}
@@ -277,13 +301,16 @@ xfs_qm_newmount(
if (((uquotaondisk && !XFS_IS_UQUOTA_ON(mp)) ||
(!uquotaondisk && XFS_IS_UQUOTA_ON(mp)) ||
+ (pquotaondisk && !XFS_IS_PQUOTA_ON(mp)) ||
+ (!pquotaondisk && XFS_IS_PQUOTA_ON(mp)) ||
(gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) ||
- (!gquotaondisk && XFS_IS_GQUOTA_ON(mp))) &&
+ (!gquotaondisk && XFS_IS_OQUOTA_ON(mp))) &&
xfs_dev_is_read_only(mp, "changing quota state")) {
cmn_err(CE_WARN,
- "XFS: please mount with%s%s%s.",
+ "XFS: please mount with%s%s%s%s.",
(!quotaondisk ? "out quota" : ""),
(uquotaondisk ? " usrquota" : ""),
+ (pquotaondisk ? " prjquota" : ""),
(gquotaondisk ? " grpquota" : ""));
return XFS_ERROR(EPERM);
}
@@ -359,7 +386,7 @@ xfs_qm_dqrele_null(
}
-struct xfs_qmops xfs_qmcore_xfs = {
+STATIC struct xfs_qmops xfs_qmcore_xfs = {
.xfs_qminit = xfs_qm_newmount,
.xfs_qmdone = xfs_qm_unmount_quotadestroy,
.xfs_qmmount = xfs_qm_endmount,
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index 229f5b5a2d2..68e98962dbe 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -118,40 +118,41 @@ xfs_qm_quotactl(
* The following commands are valid even when quotaoff.
*/
switch (cmd) {
+ case Q_XQUOTARM:
/*
- * truncate quota files. quota must be off.
+ * Truncate quota files. quota must be off.
*/
- case Q_XQUOTARM:
if (XFS_IS_QUOTA_ON(mp) || addr == NULL)
return XFS_ERROR(EINVAL);
if (vfsp->vfs_flag & VFS_RDONLY)
return XFS_ERROR(EROFS);
return (xfs_qm_scall_trunc_qfiles(mp,
xfs_qm_import_qtype_flags(*(uint *)addr)));
+
+ case Q_XGETQSTAT:
/*
* Get quota status information.
*/
- case Q_XGETQSTAT:
return (xfs_qm_scall_getqstat(mp, (fs_quota_stat_t *)addr));
+ case Q_XQUOTAON:
/*
- * QUOTAON for root f/s and quota enforcement on others..
- * Quota accounting for non-root f/s's must be turned on
- * at mount time.
+ * QUOTAON - enabling quota enforcement.
+ * Quota accounting must be turned on at mount time.
*/
- case Q_XQUOTAON:
if (addr == NULL)
return XFS_ERROR(EINVAL);
if (vfsp->vfs_flag & VFS_RDONLY)
return XFS_ERROR(EROFS);
return (xfs_qm_scall_quotaon(mp,
xfs_qm_import_flags(*(uint *)addr)));
- case Q_XQUOTAOFF:
+
+ case Q_XQUOTAOFF:
if (vfsp->vfs_flag & VFS_RDONLY)
return XFS_ERROR(EROFS);
break;
- default:
+ default:
break;
}
@@ -159,7 +160,7 @@ xfs_qm_quotactl(
return XFS_ERROR(ESRCH);
switch (cmd) {
- case Q_XQUOTAOFF:
+ case Q_XQUOTAOFF:
if (vfsp->vfs_flag & VFS_RDONLY)
return XFS_ERROR(EROFS);
error = xfs_qm_scall_quotaoff(mp,
@@ -167,42 +168,39 @@ xfs_qm_quotactl(
B_FALSE);
break;
- /*
- * Defaults to XFS_GETUQUOTA.
- */
- case Q_XGETQUOTA:
+ case Q_XGETQUOTA:
error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_USER,
(fs_disk_quota_t *)addr);
break;
- /*
- * Set limits, both hard and soft. Defaults to Q_SETUQLIM.
- */
- case Q_XSETQLIM:
+ case Q_XGETGQUOTA:
+ error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_GROUP,
+ (fs_disk_quota_t *)addr);
+ break;
+ case Q_XGETPQUOTA:
+ error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_PROJ,
+ (fs_disk_quota_t *)addr);
+ break;
+
+ case Q_XSETQLIM:
if (vfsp->vfs_flag & VFS_RDONLY)
return XFS_ERROR(EROFS);
error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_USER,
(fs_disk_quota_t *)addr);
break;
-
- case Q_XSETGQLIM:
+ case Q_XSETGQLIM:
if (vfsp->vfs_flag & VFS_RDONLY)
return XFS_ERROR(EROFS);
error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_GROUP,
(fs_disk_quota_t *)addr);
break;
-
-
- case Q_XGETGQUOTA:
- error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_GROUP,
- (fs_disk_quota_t *)addr);
+ case Q_XSETPQLIM:
+ if (vfsp->vfs_flag & VFS_RDONLY)
+ return XFS_ERROR(EROFS);
+ error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_PROJ,
+ (fs_disk_quota_t *)addr);
break;
- /*
- * Quotas are entirely undefined after quotaoff in XFS quotas.
- * For instance, there's no way to set limits when quotaoff.
- */
-
- default:
+ default:
error = XFS_ERROR(EINVAL);
break;
}
@@ -286,8 +284,12 @@ xfs_qm_scall_quotaoff(
}
if (flags & XFS_GQUOTA_ACCT) {
dqtype |= XFS_QMOPT_GQUOTA;
- flags |= (XFS_GQUOTA_CHKD | XFS_GQUOTA_ENFD);
+ flags |= (XFS_OQUOTA_CHKD | XFS_OQUOTA_ENFD);
inactivate_flags |= XFS_GQUOTA_ACTIVE;
+ } else if (flags & XFS_PQUOTA_ACCT) {
+ dqtype |= XFS_QMOPT_PQUOTA;
+ flags |= (XFS_OQUOTA_CHKD | XFS_OQUOTA_ENFD);
+ inactivate_flags |= XFS_PQUOTA_ACTIVE;
}
/*
@@ -364,7 +366,8 @@ xfs_qm_scall_quotaoff(
/*
* If quotas is completely disabled, close shop.
*/
- if ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_ALL) {
+ if (((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET1) ||
+ ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET2)) {
mutex_unlock(&(XFS_QI_QOFFLOCK(mp)));
xfs_qm_destroy_quotainfo(mp);
return (0);
@@ -378,7 +381,7 @@ xfs_qm_scall_quotaoff(
XFS_PURGE_INODE(XFS_QI_UQIP(mp));
XFS_QI_UQIP(mp) = NULL;
}
- if ((dqtype & XFS_QMOPT_GQUOTA) && XFS_QI_GQIP(mp)) {
+ if ((dqtype & (XFS_QMOPT_GQUOTA|XFS_QMOPT_PQUOTA)) && XFS_QI_GQIP(mp)) {
XFS_PURGE_INODE(XFS_QI_GQIP(mp));
XFS_QI_GQIP(mp) = NULL;
}
@@ -411,7 +414,8 @@ xfs_qm_scall_trunc_qfiles(
}
}
- if ((flags & XFS_DQ_GROUP) && mp->m_sb.sb_gquotino != NULLFSINO) {
+ if ((flags & (XFS_DQ_GROUP|XFS_DQ_PROJ)) &&
+ mp->m_sb.sb_gquotino != NULLFSINO) {
error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip, 0);
if (! error) {
(void) xfs_truncate_file(mp, qip);
@@ -434,7 +438,7 @@ xfs_qm_scall_quotaon(
uint flags)
{
int error;
- unsigned long s;
+ unsigned long s;
uint qf;
uint accflags;
__int64_t sbflags;
@@ -468,9 +472,13 @@ xfs_qm_scall_quotaon(
(mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
(flags & XFS_UQUOTA_ENFD))
||
+ ((flags & XFS_PQUOTA_ACCT) == 0 &&
+ (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
+ (flags & XFS_OQUOTA_ENFD))
+ ||
((flags & XFS_GQUOTA_ACCT) == 0 &&
(mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
- (flags & XFS_GQUOTA_ENFD))) {
+ (flags & XFS_OQUOTA_ENFD))) {
qdprintk("Can't enforce without acct, flags=%x sbflags=%x\n",
flags, mp->m_sb.sb_qflags);
return XFS_ERROR(EINVAL);
@@ -504,6 +512,10 @@ xfs_qm_scall_quotaon(
*/
if (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) !=
(mp->m_qflags & XFS_UQUOTA_ACCT)) ||
+ ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) !=
+ (mp->m_qflags & XFS_PQUOTA_ACCT)) ||
+ ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) !=
+ (mp->m_qflags & XFS_GQUOTA_ACCT)) ||
(flags & XFS_ALL_QUOTA_ENFD) == 0)
return (0);
@@ -521,7 +533,6 @@ xfs_qm_scall_quotaon(
}
-
/*
* Return quota status information, such as uquota-off, enforcements, etc.
*/
@@ -606,7 +617,8 @@ xfs_qm_scall_setqlim(
if (!capable(CAP_SYS_ADMIN))
return XFS_ERROR(EPERM);
- if ((newlim->d_fieldmask & (FS_DQ_LIMIT_MASK|FS_DQ_TIMER_MASK)) == 0)
+ if ((newlim->d_fieldmask &
+ (FS_DQ_LIMIT_MASK|FS_DQ_TIMER_MASK|FS_DQ_WARNS_MASK)) == 0)
return (0);
tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SETQLIM);
@@ -691,12 +703,23 @@ xfs_qm_scall_setqlim(
qdprintk("ihard %Ld < isoft %Ld\n", hard, soft);
}
+ /*
+ * Update warnings counter(s) if requested
+ */
+ if (newlim->d_fieldmask & FS_DQ_BWARNS)
+ INT_SET(ddq->d_bwarns, ARCH_CONVERT, newlim->d_bwarns);
+ if (newlim->d_fieldmask & FS_DQ_IWARNS)
+ INT_SET(ddq->d_iwarns, ARCH_CONVERT, newlim->d_iwarns);
+ if (newlim->d_fieldmask & FS_DQ_RTBWARNS)
+ INT_SET(ddq->d_rtbwarns, ARCH_CONVERT, newlim->d_rtbwarns);
+
if (id == 0) {
/*
* Timelimits for the super user set the relative time
* the other users can be over quota for this file system.
* If it is zero a default is used. Ditto for the default
- * soft and hard limit values (already done, above).
+ * soft and hard limit values (already done, above), and
+ * for warnings.
*/
if (newlim->d_fieldmask & FS_DQ_BTIMER) {
mp->m_quotainfo->qi_btimelimit = newlim->d_btimer;
@@ -710,7 +733,13 @@ xfs_qm_scall_setqlim(
mp->m_quotainfo->qi_rtbtimelimit = newlim->d_rtbtimer;
INT_SET(ddq->d_rtbtimer, ARCH_CONVERT, newlim->d_rtbtimer);
}
- } else /* if (XFS_IS_QUOTA_ENFORCED(mp)) */ {
+ if (newlim->d_fieldmask & FS_DQ_BWARNS)
+ mp->m_quotainfo->qi_bwarnlimit = newlim->d_bwarns;
+ if (newlim->d_fieldmask & FS_DQ_IWARNS)
+ mp->m_quotainfo->qi_iwarnlimit = newlim->d_iwarns;
+ if (newlim->d_fieldmask & FS_DQ_RTBWARNS)
+ mp->m_quotainfo->qi_rtbwarnlimit = newlim->d_rtbwarns;
+ } else {
/*
* If the user is now over quota, start the timelimit.
* The user will not be 'warned'.
@@ -776,9 +805,9 @@ xfs_qm_log_quotaoff_end(
xfs_qoff_logitem_t *startqoff,
uint flags)
{
- xfs_trans_t *tp;
+ xfs_trans_t *tp;
int error;
- xfs_qoff_logitem_t *qoffi;
+ xfs_qoff_logitem_t *qoffi;
tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QUOTAOFF_END);
@@ -928,18 +957,26 @@ xfs_qm_export_dquot(
STATIC uint
xfs_qm_import_qtype_flags(
- uint uflags)
+ uint uflags)
{
+ uint oflags = 0;
+
/*
- * Can't be both at the same time.
+ * Can't be more than one, or none.
*/
if (((uflags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) ==
- (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) ||
- ((uflags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) == 0))
+ (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) ||
+ ((uflags & (XFS_GROUP_QUOTA | XFS_PROJ_QUOTA)) ==
+ (XFS_GROUP_QUOTA | XFS_PROJ_QUOTA)) ||
+ ((uflags & (XFS_USER_QUOTA | XFS_PROJ_QUOTA)) ==
+ (XFS_USER_QUOTA | XFS_PROJ_QUOTA)) ||
+ ((uflags & (XFS_GROUP_QUOTA|XFS_USER_QUOTA|XFS_PROJ_QUOTA)) == 0))
return (0);
- return (uflags & XFS_USER_QUOTA) ?
- XFS_DQ_USER : XFS_DQ_GROUP;
+ oflags |= (uflags & XFS_USER_QUOTA) ? XFS_DQ_USER : 0;
+ oflags |= (uflags & XFS_PROJ_QUOTA) ? XFS_DQ_PROJ : 0;
+ oflags |= (uflags & XFS_GROUP_QUOTA) ? XFS_DQ_GROUP: 0;
+ return oflags;
}
STATIC uint
@@ -947,14 +984,19 @@ xfs_qm_export_qtype_flags(
uint flags)
{
/*
- * Can't be both at the same time.
+ * Can't be more than one, or none.
*/
- ASSERT((flags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) !=
- (XFS_GROUP_QUOTA | XFS_USER_QUOTA));
- ASSERT((flags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) != 0);
+ ASSERT((flags & (XFS_PROJ_QUOTA | XFS_USER_QUOTA)) !=
+ (XFS_PROJ_QUOTA | XFS_USER_QUOTA));
+ ASSERT((flags & (XFS_PROJ_QUOTA | XFS_GROUP_QUOTA)) !=
+ (XFS_PROJ_QUOTA | XFS_GROUP_QUOTA));
+ ASSERT((flags & (XFS_USER_QUOTA | XFS_GROUP_QUOTA)) !=
+ (XFS_USER_QUOTA | XFS_GROUP_QUOTA));
+ ASSERT((flags & (XFS_PROJ_QUOTA|XFS_USER_QUOTA|XFS_GROUP_QUOTA)) != 0);
return (flags & XFS_DQ_USER) ?
- XFS_USER_QUOTA : XFS_GROUP_QUOTA;
+ XFS_USER_QUOTA : (flags & XFS_DQ_PROJ) ?
+ XFS_PROJ_QUOTA : XFS_GROUP_QUOTA;
}
STATIC uint
@@ -965,12 +1007,14 @@ xfs_qm_import_flags(
if (uflags & XFS_QUOTA_UDQ_ACCT)
flags |= XFS_UQUOTA_ACCT;
+ if (uflags & XFS_QUOTA_PDQ_ACCT)
+ flags |= XFS_PQUOTA_ACCT;
if (uflags & XFS_QUOTA_GDQ_ACCT)
flags |= XFS_GQUOTA_ACCT;
if (uflags & XFS_QUOTA_UDQ_ENFD)
flags |= XFS_UQUOTA_ENFD;
- if (uflags & XFS_QUOTA_GDQ_ENFD)
- flags |= XFS_GQUOTA_ENFD;
+ if (uflags & (XFS_QUOTA_PDQ_ENFD|XFS_QUOTA_GDQ_ENFD))
+ flags |= XFS_OQUOTA_ENFD;
return (flags);
}
@@ -984,12 +1028,16 @@ xfs_qm_export_flags(
uflags = 0;
if (flags & XFS_UQUOTA_ACCT)
uflags |= XFS_QUOTA_UDQ_ACCT;
+ if (flags & XFS_PQUOTA_ACCT)
+ uflags |= XFS_QUOTA_PDQ_ACCT;
if (flags & XFS_GQUOTA_ACCT)
uflags |= XFS_QUOTA_GDQ_ACCT;
if (flags & XFS_UQUOTA_ENFD)
uflags |= XFS_QUOTA_UDQ_ENFD;
- if (flags & XFS_GQUOTA_ENFD)
- uflags |= XFS_QUOTA_GDQ_ENFD;
+ if (flags & (XFS_OQUOTA_ENFD)) {
+ uflags |= (flags & XFS_GQUOTA_ACCT) ?
+ XFS_QUOTA_GDQ_ENFD : XFS_QUOTA_PDQ_ENFD;
+ }
return (uflags);
}
@@ -1070,7 +1118,7 @@ again:
xfs_qm_dqrele(ip->i_udquot);
ip->i_udquot = NULL;
}
- if ((flags & XFS_GQUOTA_ACCT) && ip->i_gdquot) {
+ if (flags & (XFS_PQUOTA_ACCT|XFS_GQUOTA_ACCT) && ip->i_gdquot) {
xfs_qm_dqrele(ip->i_gdquot);
ip->i_gdquot = NULL;
}
@@ -1160,7 +1208,6 @@ xfs_qm_dqtest_print(
{
cmn_err(CE_DEBUG, "-----------DQTEST DQUOT----------------");
cmn_err(CE_DEBUG, "---- dquot ID = %d", d->d_id);
- cmn_err(CE_DEBUG, "---- type = %s", XFS_QM_ISUDQ(d)? "USR" : "GRP");
cmn_err(CE_DEBUG, "---- fs = 0x%p", d->q_mount);
cmn_err(CE_DEBUG, "---- bcount = %Lu (0x%x)",
d->d_bcount, (int)d->d_bcount);
@@ -1231,7 +1278,7 @@ xfs_dqtest_cmp2(
#ifdef QUOTADEBUG
if (!err) {
cmn_err(CE_DEBUG, "%d [%s] [0x%p] qchecked",
- d->d_id, XFS_QM_ISUDQ(d) ? "USR" : "GRP", d->q_mount);
+ d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount);
}
#endif
return (err);
@@ -1287,6 +1334,7 @@ STATIC void
xfs_qm_internalqcheck_get_dquots(
xfs_mount_t *mp,
xfs_dqid_t uid,
+ xfs_dqid_t projid,
xfs_dqid_t gid,
xfs_dqtest_t **ud,
xfs_dqtest_t **gd)
@@ -1295,6 +1343,8 @@ xfs_qm_internalqcheck_get_dquots(
xfs_qm_internalqcheck_dqget(mp, uid, XFS_DQ_USER, ud);
if (XFS_IS_GQUOTA_ON(mp))
xfs_qm_internalqcheck_dqget(mp, gid, XFS_DQ_GROUP, gd);
+ else if (XFS_IS_PQUOTA_ON(mp))
+ xfs_qm_internalqcheck_dqget(mp, projid, XFS_DQ_PROJ, gd);
}
@@ -1362,13 +1412,14 @@ xfs_qm_internalqcheck_adjust(
}
xfs_qm_internalqcheck_get_dquots(mp,
(xfs_dqid_t) ip->i_d.di_uid,
+ (xfs_dqid_t) ip->i_d.di_projid,
(xfs_dqid_t) ip->i_d.di_gid,
&ud, &gd);
if (XFS_IS_UQUOTA_ON(mp)) {
ASSERT(ud);
xfs_qm_internalqcheck_dqadjust(ip, ud);
}
- if (XFS_IS_GQUOTA_ON(mp)) {
+ if (XFS_IS_OQUOTA_ON(mp)) {
ASSERT(gd);
xfs_qm_internalqcheck_dqadjust(ip, gd);
}
diff --git a/fs/xfs/quota/xfs_quota_priv.h b/fs/xfs/quota/xfs_quota_priv.h
index 414b6004af2..bf413e70ec0 100644
--- a/fs/xfs/quota/xfs_quota_priv.h
+++ b/fs/xfs/quota/xfs_quota_priv.h
@@ -56,6 +56,7 @@
#define XFS_QI_RTBTIMELIMIT(mp) ((mp)->m_quotainfo->qi_rtbtimelimit)
#define XFS_QI_ITIMELIMIT(mp) ((mp)->m_quotainfo->qi_itimelimit)
#define XFS_QI_BWARNLIMIT(mp) ((mp)->m_quotainfo->qi_bwarnlimit)
+#define XFS_QI_RTBWARNLIMIT(mp) ((mp)->m_quotainfo->qi_rtbwarnlimit)
#define XFS_QI_IWARNLIMIT(mp) ((mp)->m_quotainfo->qi_iwarnlimit)
#define XFS_QI_QOFFLOCK(mp) ((mp)->m_quotainfo->qi_quotaofflock)
@@ -102,7 +103,8 @@ static inline int XQMISLCKD(struct xfs_dqhash *h)
(xfs_Gqm->qm_grp_dqhtable + \
XFS_DQ_HASHVAL(mp, id)))
#define XFS_IS_DQTYPE_ON(mp, type) (type == XFS_DQ_USER ? \
- XFS_IS_UQUOTA_ON(mp):XFS_IS_GQUOTA_ON(mp))
+ XFS_IS_UQUOTA_ON(mp) : \
+ XFS_IS_OQUOTA_ON(mp))
#define XFS_IS_DQUOT_UNINITIALIZED(dqp) ( \
!dqp->q_core.d_blk_hardlimit && \
!dqp->q_core.d_blk_softlimit && \
@@ -177,16 +179,11 @@ for ((dqp) = (qlist)->qh_next; (dqp) != (xfs_dquot_t *)(qlist); \
(!((dqp)->q_core.d_id))
#define XFS_PURGE_INODE(ip) \
- { \
- vmap_t dqvmap; \
- vnode_t *dqvp; \
- dqvp = XFS_ITOV(ip); \
- VMAP(dqvp, dqvmap); \
- VN_RELE(dqvp); \
- }
+ IRELE(ip);
#define DQFLAGTO_TYPESTR(d) (((d)->dq_flags & XFS_DQ_USER) ? "USR" : \
- (((d)->dq_flags & XFS_DQ_GROUP) ? "GRP" : "???"))
+ (((d)->dq_flags & XFS_DQ_GROUP) ? "GRP" : \
+ (((d)->dq_flags & XFS_DQ_PROJ) ? "PRJ":"???")))
#define DQFLAGTO_DIRTYSTR(d) (XFS_DQ_IS_DIRTY(d) ? "DIRTY" : "NOTDIRTY")
#endif /* __XFS_QUOTA_PRIV_H__ */
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c
index 149b2a1fd94..3b99daf8a64 100644
--- a/fs/xfs/quota/xfs_trans_dquot.c
+++ b/fs/xfs/quota/xfs_trans_dquot.c
@@ -187,7 +187,7 @@ xfs_trans_dup_dqinfo(
/*
* Wrap around mod_dquot to account for both user and group quotas.
*/
-void
+STATIC void
xfs_trans_mod_dquot_byino(
xfs_trans_t *tp,
xfs_inode_t *ip,
@@ -207,12 +207,10 @@ xfs_trans_mod_dquot_byino(
if (tp->t_dqinfo == NULL)
xfs_trans_alloc_dqinfo(tp);
- if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot) {
+ if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot)
(void) xfs_trans_mod_dquot(tp, ip->i_udquot, field, delta);
- }
- if (XFS_IS_GQUOTA_ON(mp) && ip->i_gdquot) {
+ if (XFS_IS_OQUOTA_ON(mp) && ip->i_gdquot)
(void) xfs_trans_mod_dquot(tp, ip->i_gdquot, field, delta);
- }
}
STATIC xfs_dqtrx_t *
@@ -368,7 +366,7 @@ xfs_trans_dqlockedjoin(
* Unreserve just the reservations done by this transaction.
* dquot is still left locked at exit.
*/
-void
+STATIC void
xfs_trans_apply_dquot_deltas(
xfs_trans_t *tp)
{
@@ -499,7 +497,7 @@ xfs_trans_apply_dquot_deltas(
* Adjust the RT reservation.
*/
if (qtrx->qt_rtblk_res != 0) {
- if (qtrx->qt_blk_res != qtrx->qt_blk_res_used) {
+ if (qtrx->qt_rtblk_res != qtrx->qt_rtblk_res_used) {
if (qtrx->qt_rtblk_res >
qtrx->qt_rtblk_res_used)
dqp->q_res_rtbcount -= (xfs_qcnt_t)
@@ -532,12 +530,6 @@ xfs_trans_apply_dquot_deltas(
(xfs_qcnt_t)qtrx->qt_icount_delta;
}
-
-#ifdef QUOTADEBUG
- if (qtrx->qt_rtblk_res != 0)
- cmn_err(CE_DEBUG, "RT res %d for 0x%p\n",
- (int) qtrx->qt_rtblk_res, dqp);
-#endif
ASSERT(dqp->q_res_bcount >=
INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT));
ASSERT(dqp->q_res_icount >=
@@ -638,7 +630,10 @@ xfs_trans_dqresv(
int error;
xfs_qcnt_t hardlimit;
xfs_qcnt_t softlimit;
- time_t btimer;
+ time_t timer;
+ xfs_qwarncnt_t warns;
+ xfs_qwarncnt_t warnlimit;
+ xfs_qcnt_t count;
xfs_qcnt_t *resbcountp;
xfs_quotainfo_t *q = mp->m_quotainfo;
@@ -653,7 +648,9 @@ xfs_trans_dqresv(
softlimit = INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT);
if (!softlimit)
softlimit = q->qi_bsoftlimit;
- btimer = INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT);
+ timer = INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT);
+ warns = INT_GET(dqp->q_core.d_bwarns, ARCH_CONVERT);
+ warnlimit = XFS_QI_BWARNLIMIT(dqp->q_mount);
resbcountp = &dqp->q_res_bcount;
} else {
ASSERT(flags & XFS_TRANS_DQ_RES_RTBLKS);
@@ -663,7 +660,9 @@ xfs_trans_dqresv(
softlimit = INT_GET(dqp->q_core.d_rtb_softlimit, ARCH_CONVERT);
if (!softlimit)
softlimit = q->qi_rtbsoftlimit;
- btimer = INT_GET(dqp->q_core.d_rtbtimer, ARCH_CONVERT);
+ timer = INT_GET(dqp->q_core.d_rtbtimer, ARCH_CONVERT);
+ warns = INT_GET(dqp->q_core.d_rtbwarns, ARCH_CONVERT);
+ warnlimit = XFS_QI_RTBWARNLIMIT(dqp->q_mount);
resbcountp = &dqp->q_res_rtbcount;
}
error = 0;
@@ -693,37 +692,36 @@ xfs_trans_dqresv(
* If timer or warnings has expired,
* return EDQUOT
*/
- if ((btimer != 0 && get_seconds() > btimer) ||
- (dqp->q_core.d_bwarns &&
- INT_GET(dqp->q_core.d_bwarns, ARCH_CONVERT) >=
- XFS_QI_BWARNLIMIT(dqp->q_mount))) {
+ if ((timer != 0 && get_seconds() > timer) ||
+ (warns != 0 && warns >= warnlimit)) {
error = EDQUOT;
goto error_return;
}
}
}
if (ninos > 0) {
- hardlimit = INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT);
+ count = INT_GET(dqp->q_core.d_icount, ARCH_CONVERT);
+ timer = INT_GET(dqp->q_core.d_itimer, ARCH_CONVERT);
+ warns = INT_GET(dqp->q_core.d_iwarns, ARCH_CONVERT);
+ warnlimit = XFS_QI_IWARNLIMIT(dqp->q_mount);
+ hardlimit = INT_GET(dqp->q_core.d_ino_hardlimit,
+ ARCH_CONVERT);
if (!hardlimit)
hardlimit = q->qi_ihardlimit;
- softlimit = INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT);
+ softlimit = INT_GET(dqp->q_core.d_ino_softlimit,
+ ARCH_CONVERT);
if (!softlimit)
softlimit = q->qi_isoftlimit;
- if (hardlimit > 0ULL &&
- INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >= hardlimit) {
+ if (hardlimit > 0ULL && count >= hardlimit) {
error = EDQUOT;
goto error_return;
- } else if (softlimit > 0ULL &&
- INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >= softlimit) {
+ } else if (softlimit > 0ULL && count >= softlimit) {
/*
* If timer or warnings has expired,
* return EDQUOT
*/
- if ((dqp->q_core.d_itimer &&
- get_seconds() > INT_GET(dqp->q_core.d_itimer, ARCH_CONVERT)) ||
- (dqp->q_core.d_iwarns &&
- INT_GET(dqp->q_core.d_iwarns, ARCH_CONVERT) >=
- XFS_QI_IWARNLIMIT(dqp->q_mount))) {
+ if ((timer != 0 && get_seconds() > timer) ||
+ (warns != 0 && warns >= warnlimit)) {
error = EDQUOT;
goto error_return;
}
diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c
index 7d6e1f37df1..4ed7b6928cd 100644
--- a/fs/xfs/support/debug.c
+++ b/fs/xfs/support/debug.c
@@ -36,7 +36,6 @@
#include <linux/sched.h>
#include <linux/kernel.h>
-int doass = 1;
static char message[256]; /* keep it off the stack */
static DEFINE_SPINLOCK(xfs_err_lock);
diff --git a/fs/xfs/support/debug.h b/fs/xfs/support/debug.h
index 40b0f4c54d9..c5b9365a7e2 100644
--- a/fs/xfs/support/debug.h
+++ b/fs/xfs/support/debug.h
@@ -50,16 +50,11 @@ extern void cmn_err(int, char *, ...);
#endif
#ifdef DEBUG
-# ifdef lint
-# define ASSERT(EX) ((void)0) /* avoid "constant in conditional" babble */
-# else
-# define ASSERT(EX) ((!doass||(EX))?((void)0):assfail(#EX, __FILE__, __LINE__))
-# endif /* lint */
+# define ASSERT(EX) ((EX) ? ((void)0) : assfail(#EX, __FILE__, __LINE__))
#else
# define ASSERT(x) ((void)0)
#endif
-extern int doass; /* dynamically turn off asserts */
extern void assfail(char *, char *, int);
#ifdef DEBUG
extern unsigned long random(void);
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index 36603db10fe..dcfe1970362 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -59,7 +59,7 @@
#define XFSA_FIXUP_BNO_OK 1
#define XFSA_FIXUP_CNT_OK 2
-int
+STATIC int
xfs_alloc_search_busy(xfs_trans_t *tp,
xfs_agnumber_t agno,
xfs_agblock_t bno,
@@ -2562,7 +2562,7 @@ xfs_alloc_clear_busy(xfs_trans_t *tp,
/*
* returns non-zero if any of (agno,bno):len is in a busy list
*/
-int
+STATIC int
xfs_alloc_search_busy(xfs_trans_t *tp,
xfs_agnumber_t agno,
xfs_agblock_t bno,
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index ee8b5904ec7..a41ad3a5e55 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -71,6 +71,11 @@
* Provide the external interfaces to manage attribute lists.
*/
+#define ATTR_SYSCOUNT 2
+STATIC struct attrnames posix_acl_access;
+STATIC struct attrnames posix_acl_default;
+STATIC struct attrnames *attr_system_names[ATTR_SYSCOUNT];
+
/*========================================================================
* Function prototypes for the kernel.
*========================================================================*/
@@ -83,6 +88,7 @@ STATIC int xfs_attr_shortform_addname(xfs_da_args_t *args);
/*
* Internal routines when attribute list is one block.
*/
+STATIC int xfs_attr_leaf_get(xfs_da_args_t *args);
STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args);
STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args);
STATIC int xfs_attr_leaf_list(xfs_attr_list_context_t *context);
@@ -90,6 +96,7 @@ STATIC int xfs_attr_leaf_list(xfs_attr_list_context_t *context);
/*
* Internal routines when attribute list is more than one block.
*/
+STATIC int xfs_attr_node_get(xfs_da_args_t *args);
STATIC int xfs_attr_node_addname(xfs_da_args_t *args);
STATIC int xfs_attr_node_removename(xfs_da_args_t *args);
STATIC int xfs_attr_node_list(xfs_attr_list_context_t *context);
@@ -1102,7 +1109,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args)
* This leaf block cannot have a "remote" value, we only call this routine
* if bmap_one_block() says there is only one block (ie: no remote blks).
*/
-int
+STATIC int
xfs_attr_leaf_get(xfs_da_args_t *args)
{
xfs_dabuf_t *bp;
@@ -1707,7 +1714,7 @@ xfs_attr_refillstate(xfs_da_state_t *state)
* block, ie: both true Btree attr lists and for single-leaf-blocks with
* "remote" values taking up more blocks.
*/
-int
+STATIC int
xfs_attr_node_get(xfs_da_args_t *args)
{
xfs_da_state_t *state;
@@ -2398,7 +2405,7 @@ posix_acl_default_exists(
return xfs_acl_vhasacl_default(vp);
}
-struct attrnames posix_acl_access = {
+STATIC struct attrnames posix_acl_access = {
.attr_name = "posix_acl_access",
.attr_namelen = sizeof("posix_acl_access") - 1,
.attr_get = posix_acl_access_get,
@@ -2407,7 +2414,7 @@ struct attrnames posix_acl_access = {
.attr_exists = posix_acl_access_exists,
};
-struct attrnames posix_acl_default = {
+STATIC struct attrnames posix_acl_default = {
.attr_name = "posix_acl_default",
.attr_namelen = sizeof("posix_acl_default") - 1,
.attr_get = posix_acl_default_get,
@@ -2416,7 +2423,7 @@ struct attrnames posix_acl_default = {
.attr_exists = posix_acl_default_exists,
};
-struct attrnames *attr_system_names[] =
+STATIC struct attrnames *attr_system_names[] =
{ &posix_acl_access, &posix_acl_default };
diff --git a/fs/xfs/xfs_attr.h b/fs/xfs/xfs_attr.h
index 67cd0f5ac1a..45ab1c542ba 100644
--- a/fs/xfs/xfs_attr.h
+++ b/fs/xfs/xfs_attr.h
@@ -76,11 +76,6 @@ extern struct attrnames attr_system;
extern struct attrnames attr_trusted;
extern struct attrnames *attr_namespaces[ATTR_NAMECOUNT];
-#define ATTR_SYSCOUNT 2
-extern struct attrnames posix_acl_access;
-extern struct attrnames posix_acl_default;
-extern struct attrnames *attr_system_names[ATTR_SYSCOUNT];
-
extern attrnames_t *attr_lookup_namespace(char *, attrnames_t **, int);
extern int attr_generic_list(struct vnode *, void *, size_t, int, ssize_t *);
@@ -184,8 +179,6 @@ int xfs_attr_list(bhv_desc_t *, char *, int, int,
struct attrlist_cursor_kern *, struct cred *);
int xfs_attr_inactive(struct xfs_inode *dp);
-int xfs_attr_node_get(struct xfs_da_args *);
-int xfs_attr_leaf_get(struct xfs_da_args *);
int xfs_attr_shortform_getvalue(struct xfs_da_args *);
int xfs_attr_fetch(struct xfs_inode *, char *, int,
char *, int *, int, struct cred *);
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index b11256e58bf..1cdd574c63a 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -79,6 +79,8 @@
/*
* Routines used for growing the Btree.
*/
+STATIC int xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t which_block,
+ xfs_dabuf_t **bpp);
STATIC int xfs_attr_leaf_add_work(xfs_dabuf_t *leaf_buffer, xfs_da_args_t *args,
int freemap_index);
STATIC void xfs_attr_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *leaf_buffer);
@@ -92,6 +94,16 @@ STATIC int xfs_attr_leaf_figure_balance(xfs_da_state_t *state,
int *number_usedbytes_in_blk1);
/*
+ * Routines used for shrinking the Btree.
+ */
+STATIC int xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp,
+ xfs_dabuf_t *bp, int level);
+STATIC int xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp,
+ xfs_dabuf_t *bp);
+STATIC int xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp,
+ xfs_dablk_t blkno, int blkcnt);
+
+/*
* Utility routines.
*/
STATIC void xfs_attr_leaf_moveents(xfs_attr_leafblock_t *src_leaf,
@@ -99,6 +111,10 @@ STATIC void xfs_attr_leaf_moveents(xfs_attr_leafblock_t *src_leaf,
xfs_attr_leafblock_t *dst_leaf,
int dst_start, int move_count,
xfs_mount_t *mp);
+STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index);
+STATIC int xfs_attr_put_listent(xfs_attr_list_context_t *context,
+ attrnames_t *, char *name, int namelen,
+ int valuelen);
/*========================================================================
@@ -774,7 +790,7 @@ out:
* Create the initial contents of a leaf attribute list
* or a leaf in a node attribute list.
*/
-int
+STATIC int
xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp)
{
xfs_attr_leafblock_t *leaf;
@@ -2209,7 +2225,7 @@ xfs_attr_leaf_lasthash(xfs_dabuf_t *bp, int *count)
* Calculate the number of bytes used to store the indicated attribute
* (whether local or remote only calculate bytes in this block).
*/
-int
+STATIC int
xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index)
{
xfs_attr_leaf_name_local_t *name_loc;
@@ -2380,7 +2396,7 @@ xfs_attr_leaf_list_int(xfs_dabuf_t *bp, xfs_attr_list_context_t *context)
* we may be reading them directly out of a user buffer.
*/
/*ARGSUSED*/
-int
+STATIC int
xfs_attr_put_listent(xfs_attr_list_context_t *context,
attrnames_t *namesp, char *name, int namelen, int valuelen)
{
@@ -2740,7 +2756,7 @@ xfs_attr_root_inactive(xfs_trans_t **trans, xfs_inode_t *dp)
* Recurse (gasp!) through the attribute nodes until we find leaves.
* We're doing a depth-first traversal in order to invalidate everything.
*/
-int
+STATIC int
xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp,
int level)
{
@@ -2849,7 +2865,7 @@ xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp,
* Note that we must release the lock on the buffer so that we are not
* caught holding something that the logging code wants to flush to disk.
*/
-int
+STATIC int
xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp)
{
xfs_attr_leafblock_t *leaf;
@@ -2934,7 +2950,7 @@ xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp)
* Look at all the extents for this logical region,
* invalidate any buffers that are incore/in transactions.
*/
-int
+STATIC int
xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp,
xfs_dablk_t blkno, int blkcnt)
{
diff --git a/fs/xfs/xfs_attr_leaf.h b/fs/xfs/xfs_attr_leaf.h
index b1480e0b334..0a4cfad6df9 100644
--- a/fs/xfs/xfs_attr_leaf.h
+++ b/fs/xfs/xfs_attr_leaf.h
@@ -261,8 +261,6 @@ int xfs_attr_leaf_flipflags(xfs_da_args_t *args);
/*
* Routines used for growing the Btree.
*/
-int xfs_attr_leaf_create(struct xfs_da_args *args, xfs_dablk_t which_block,
- struct xfs_dabuf **bpp);
int xfs_attr_leaf_split(struct xfs_da_state *state,
struct xfs_da_state_blk *oldblk,
struct xfs_da_state_blk *newblk);
@@ -284,12 +282,6 @@ void xfs_attr_leaf_unbalance(struct xfs_da_state *state,
struct xfs_da_state_blk *drop_blk,
struct xfs_da_state_blk *save_blk);
int xfs_attr_root_inactive(struct xfs_trans **trans, struct xfs_inode *dp);
-int xfs_attr_node_inactive(struct xfs_trans **trans, struct xfs_inode *dp,
- struct xfs_dabuf *bp, int level);
-int xfs_attr_leaf_inactive(struct xfs_trans **trans, struct xfs_inode *dp,
- struct xfs_dabuf *bp);
-int xfs_attr_leaf_freextent(struct xfs_trans **trans, struct xfs_inode *dp,
- xfs_dablk_t blkno, int blkcnt);
/*
* Utility routines.
@@ -299,10 +291,6 @@ int xfs_attr_leaf_order(struct xfs_dabuf *leaf1_bp,
struct xfs_dabuf *leaf2_bp);
int xfs_attr_leaf_newentsize(struct xfs_da_args *args, int blocksize,
int *local);
-int xfs_attr_leaf_entsize(struct xfs_attr_leafblock *leaf, int index);
-int xfs_attr_put_listent(struct xfs_attr_list_context *context,
- struct attrnames *, char *name, int namelen,
- int valuelen);
int xfs_attr_rolltrans(struct xfs_trans **transp, struct xfs_inode *dp);
#endif /* __XFS_ATTR_LEAF_H__ */
diff --git a/fs/xfs/xfs_bit.c b/fs/xfs/xfs_bit.c
index a20a6c3dc13..76c9ad3875e 100644
--- a/fs/xfs/xfs_bit.c
+++ b/fs/xfs/xfs_bit.c
@@ -45,7 +45,7 @@
/*
* Index of high bit number in byte, -1 for none set, 0..7 otherwise.
*/
-const char xfs_highbit[256] = {
+STATIC const char xfs_highbit[256] = {
-1, 0, 1, 1, 2, 2, 2, 2, /* 00 .. 07 */
3, 3, 3, 3, 3, 3, 3, 3, /* 08 .. 0f */
4, 4, 4, 4, 4, 4, 4, 4, /* 10 .. 17 */
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index de316241866..6f5d283888a 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -301,6 +301,19 @@ xfs_bmap_search_extents(
xfs_bmbt_irec_t *gotp, /* out: extent entry found */
xfs_bmbt_irec_t *prevp); /* out: previous extent entry found */
+/*
+ * Check the last inode extent to determine whether this allocation will result
+ * in blocks being allocated at the end of the file. When we allocate new data
+ * blocks at the end of the file which do not start at the previous data block,
+ * we will try to align the new blocks at stripe unit boundaries.
+ */
+STATIC int /* error */
+xfs_bmap_isaeof(
+ xfs_inode_t *ip, /* incore inode pointer */
+ xfs_fileoff_t off, /* file offset in fsblocks */
+ int whichfork, /* data or attribute fork */
+ char *aeof); /* return value */
+
#ifdef XFS_BMAP_TRACE
/*
* Add a bmap trace buffer entry. Base routine for the others.
@@ -4532,18 +4545,17 @@ xfs_bmapi(
xfs_extlen_t alen; /* allocated extent length */
xfs_fileoff_t aoff; /* allocated file offset */
xfs_bmalloca_t bma; /* args for xfs_bmap_alloc */
- char contig; /* allocation must be one extent */
xfs_btree_cur_t *cur; /* bmap btree cursor */
- char delay; /* this request is for delayed alloc */
xfs_fileoff_t end; /* end of mapped file region */
int eof; /* we've hit the end of extent list */
+ char contig; /* allocation must be one extent */
+ char delay; /* this request is for delayed alloc */
+ char exact; /* don't do all of wasdelayed extent */
xfs_bmbt_rec_t *ep; /* extent list entry pointer */
int error; /* error return */
- char exact; /* don't do all of wasdelayed extent */
xfs_bmbt_irec_t got; /* current extent list record */
xfs_ifork_t *ifp; /* inode fork pointer */
xfs_extlen_t indlen; /* indirect blocks length */
- char inhole; /* current location is hole in file */
xfs_extnum_t lastx; /* last useful extent number */
int logflags; /* flags for transaction logging */
xfs_extlen_t minleft; /* min blocks left after allocation */
@@ -4554,13 +4566,15 @@ xfs_bmapi(
xfs_extnum_t nextents; /* number of extents in file */
xfs_fileoff_t obno; /* old block number (offset) */
xfs_bmbt_irec_t prev; /* previous extent list record */
- char stateless; /* ignore state flag set */
int tmp_logflags; /* temp flags holder */
+ int whichfork; /* data or attr fork */
+ char inhole; /* current location is hole in file */
+ char stateless; /* ignore state flag set */
char trim; /* output trimmed to match range */
char userdata; /* allocating non-metadata */
char wasdelay; /* old extent was delayed */
- int whichfork; /* data or attr fork */
char wr; /* this is a write request */
+ char rt; /* this is a realtime file */
char rsvd; /* OK to allocate reserved blocks */
#ifdef DEBUG
xfs_fileoff_t orig_bno; /* original block number value */
@@ -4590,6 +4604,7 @@ xfs_bmapi(
}
if (XFS_FORCED_SHUTDOWN(mp))
return XFS_ERROR(EIO);
+ rt = XFS_IS_REALTIME_INODE(ip);
ifp = XFS_IFORK_PTR(ip, whichfork);
ASSERT(ifp->if_ext_max ==
XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
@@ -4694,9 +4709,16 @@ xfs_bmapi(
}
minlen = contig ? alen : 1;
if (delay) {
- indlen = (xfs_extlen_t)
- xfs_bmap_worst_indlen(ip, alen);
- ASSERT(indlen > 0);
+ xfs_extlen_t extsz = 0;
+
+ /* Figure out the extent size, adjust alen */
+ if (rt) {
+ if (!(extsz = ip->i_d.di_extsize))
+ extsz = mp->m_sb.sb_rextsize;
+ alen = roundup(alen, extsz);
+ extsz = alen / mp->m_sb.sb_rextsize;
+ }
+
/*
* Make a transaction-less quota reservation for
* delayed allocation blocks. This number gets
@@ -4704,8 +4726,10 @@ xfs_bmapi(
* We return EDQUOT if we haven't allocated
* blks already inside this loop;
*/
- if (XFS_TRANS_RESERVE_BLKQUOTA(
- mp, NULL, ip, (long)alen)) {
+ if (XFS_TRANS_RESERVE_QUOTA_NBLKS(
+ mp, NULL, ip, (long)alen, 0,
+ rt ? XFS_QMOPT_RES_RTBLKS :
+ XFS_QMOPT_RES_REGBLKS)) {
if (n == 0) {
*nmap = 0;
ASSERT(cur == NULL);
@@ -4718,40 +4742,34 @@ xfs_bmapi(
* Split changing sb for alen and indlen since
* they could be coming from different places.
*/
- if (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) {
- xfs_extlen_t extsz;
- xfs_extlen_t ralen;
- if (!(extsz = ip->i_d.di_extsize))
- extsz = mp->m_sb.sb_rextsize;
- ralen = roundup(alen, extsz);
- ralen = ralen / mp->m_sb.sb_rextsize;
- if (xfs_mod_incore_sb(mp,
- XFS_SBS_FREXTENTS,
- -(ralen), rsvd)) {
- if (XFS_IS_QUOTA_ON(ip->i_mount))
- XFS_TRANS_UNRESERVE_BLKQUOTA(
- mp, NULL, ip,
- (long)alen);
- break;
- }
- } else {
- if (xfs_mod_incore_sb(mp,
- XFS_SBS_FDBLOCKS,
- -(alen), rsvd)) {
- if (XFS_IS_QUOTA_ON(ip->i_mount))
- XFS_TRANS_UNRESERVE_BLKQUOTA(
- mp, NULL, ip,
- (long)alen);
- break;
- }
- }
+ indlen = (xfs_extlen_t)
+ xfs_bmap_worst_indlen(ip, alen);
+ ASSERT(indlen > 0);
- if (xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS,
- -(indlen), rsvd)) {
- XFS_TRANS_UNRESERVE_BLKQUOTA(
- mp, NULL, ip, (long)alen);
+ if (rt)
+ error = xfs_mod_incore_sb(mp,
+ XFS_SBS_FREXTENTS,
+ -(extsz), rsvd);
+ else
+ error = xfs_mod_incore_sb(mp,
+ XFS_SBS_FDBLOCKS,
+ -(alen), rsvd);
+ if (!error)
+ error = xfs_mod_incore_sb(mp,
+ XFS_SBS_FDBLOCKS,
+ -(indlen), rsvd);
+
+ if (error) {
+ if (XFS_IS_QUOTA_ON(ip->i_mount))
+ /* unreserve the blocks now */
+ XFS_TRANS_UNRESERVE_QUOTA_NBLKS(
+ mp, NULL, ip,
+ (long)alen, 0, rt ?
+ XFS_QMOPT_RES_RTBLKS :
+ XFS_QMOPT_RES_REGBLKS);
break;
}
+
ip->i_delayed_blks += alen;
abno = NULLSTARTBLOCK(indlen);
} else {
@@ -5376,13 +5394,24 @@ xfs_bunmapi(
}
if (wasdel) {
ASSERT(STARTBLOCKVAL(del.br_startblock) > 0);
- xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS,
- (int)del.br_blockcount, rsvd);
- /* Unreserve our quota space */
- XFS_TRANS_RESERVE_QUOTA_NBLKS(
- mp, NULL, ip, -((long)del.br_blockcount), 0,
- isrt ? XFS_QMOPT_RES_RTBLKS :
+ /* Update realtim/data freespace, unreserve quota */
+ if (isrt) {
+ xfs_filblks_t rtexts;
+
+ rtexts = XFS_FSB_TO_B(mp, del.br_blockcount);
+ do_div(rtexts, mp->m_sb.sb_rextsize);
+ xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
+ (int)rtexts, rsvd);
+ XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, NULL, ip,
+ -((long)del.br_blockcount), 0,
+ XFS_QMOPT_RES_RTBLKS);
+ } else {
+ xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS,
+ (int)del.br_blockcount, rsvd);
+ XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, NULL, ip,
+ -((long)del.br_blockcount), 0,
XFS_QMOPT_RES_REGBLKS);
+ }
ip->i_delayed_blks -= del.br_blockcount;
if (cur)
cur->bc_private.b.flags |=
@@ -5714,7 +5743,7 @@ unlock_and_return:
* blocks at the end of the file which do not start at the previous data block,
* we will try to align the new blocks at stripe unit boundaries.
*/
-int /* error */
+STATIC int /* error */
xfs_bmap_isaeof(
xfs_inode_t *ip, /* incore inode pointer */
xfs_fileoff_t off, /* file offset in fsblocks */
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
index f1bc22fb26a..e6d22ec9b2e 100644
--- a/fs/xfs/xfs_bmap.h
+++ b/fs/xfs/xfs_bmap.h
@@ -332,19 +332,6 @@ xfs_getbmap(
int iflags); /* interface flags */
/*
- * Check the last inode extent to determine whether this allocation will result
- * in blocks being allocated at the end of the file. When we allocate new data
- * blocks at the end of the file which do not start at the previous data block,
- * we will try to align the new blocks at stripe unit boundaries.
- */
-int
-xfs_bmap_isaeof(
- struct xfs_inode *ip,
- xfs_fileoff_t off,
- int whichfork,
- char *aeof);
-
-/*
* Check if the endoff is outside the last extent. If so the caller will grow
* the allocation to a stripe unit boundary
*/
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index 163305a79fc..09c413576ba 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -2331,20 +2331,6 @@ xfs_bmbt_lookup_ge(
return xfs_bmbt_lookup(cur, XFS_LOOKUP_GE, stat);
}
-int /* error */
-xfs_bmbt_lookup_le(
- xfs_btree_cur_t *cur,
- xfs_fileoff_t off,
- xfs_fsblock_t bno,
- xfs_filblks_t len,
- int *stat) /* success/failure */
-{
- cur->bc_rec.b.br_startoff = off;
- cur->bc_rec.b.br_startblock = bno;
- cur->bc_rec.b.br_blockcount = len;
- return xfs_bmbt_lookup(cur, XFS_LOOKUP_LE, stat);
-}
-
/*
* Give the bmap btree a new root block. Copy the old broot contents
* down into a real block and make the broot point to it.
diff --git a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h
index 843ff12b4bf..0a40cf126c2 100644
--- a/fs/xfs/xfs_bmap_btree.h
+++ b/fs/xfs/xfs_bmap_btree.h
@@ -580,14 +580,6 @@ xfs_bmbt_lookup_ge(
xfs_filblks_t,
int *);
-int
-xfs_bmbt_lookup_le(
- struct xfs_btree_cur *,
- xfs_fileoff_t,
- xfs_fsblock_t,
- xfs_filblks_t,
- int *);
-
/*
* Give the bmap btree a new root block. Copy the old broot contents
* down into a real block and make the broot point to it.
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c
index 9dd22dd9548..0cc63d657a1 100644
--- a/fs/xfs/xfs_btree.c
+++ b/fs/xfs/xfs_btree.c
@@ -90,6 +90,16 @@ xfs_btree_maxrecs(
*/
/*
+ * Retrieve the block pointer from the cursor at the given level.
+ * This may be a bmap btree root or from a buffer.
+ */
+STATIC xfs_btree_block_t * /* generic btree block pointer */
+xfs_btree_get_block(
+ xfs_btree_cur_t *cur, /* btree cursor */
+ int level, /* level in btree */
+ struct xfs_buf **bpp); /* buffer containing the block */
+
+/*
* Checking routine: return maxrecs for the block.
*/
STATIC int /* number of records fitting in block */
@@ -497,7 +507,7 @@ xfs_btree_firstrec(
* Retrieve the block pointer from the cursor at the given level.
* This may be a bmap btree root or from a buffer.
*/
-xfs_btree_block_t * /* generic btree block pointer */
+STATIC xfs_btree_block_t * /* generic btree block pointer */
xfs_btree_get_block(
xfs_btree_cur_t *cur, /* btree cursor */
int level, /* level in btree */
diff --git a/fs/xfs/xfs_btree.h b/fs/xfs/xfs_btree.h
index 93872bba41f..09b4e1532a3 100644
--- a/fs/xfs/xfs_btree.h
+++ b/fs/xfs/xfs_btree.h
@@ -325,16 +325,6 @@ xfs_btree_firstrec(
int level); /* level to change */
/*
- * Retrieve the block pointer from the cursor at the given level.
- * This may be a bmap btree root or from a buffer.
- */
-xfs_btree_block_t * /* generic btree block pointer */
-xfs_btree_get_block(
- xfs_btree_cur_t *cur, /* btree cursor */
- int level, /* level in btree */
- struct xfs_buf **bpp); /* buffer containing the block */
-
-/*
* Get a buffer for the block, return it with no data read.
* Long-form addressing.
*/
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 9ab0039f07d..30b8285ad47 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -172,7 +172,7 @@ STATIC void xfs_buf_do_callbacks(xfs_buf_t *bp, xfs_log_item_t *lip);
*
* If the XFS_BLI_STALE flag has been set, then log nothing.
*/
-uint
+STATIC uint
xfs_buf_item_size(
xfs_buf_log_item_t *bip)
{
@@ -240,7 +240,7 @@ xfs_buf_item_size(
* format structure, and the rest point to contiguous chunks
* within the buffer.
*/
-void
+STATIC void
xfs_buf_item_format(
xfs_buf_log_item_t *bip,
xfs_log_iovec_t *log_vector)
@@ -365,7 +365,7 @@ xfs_buf_item_format(
* item in memory so it cannot be written out. Simply call bpin()
* on the buffer to do this.
*/
-void
+STATIC void
xfs_buf_item_pin(
xfs_buf_log_item_t *bip)
{
@@ -391,7 +391,7 @@ xfs_buf_item_pin(
* If the XFS_BLI_STALE flag is set and we are the last reference,
* then free up the buf log item and unlock the buffer.
*/
-void
+STATIC void
xfs_buf_item_unpin(
xfs_buf_log_item_t *bip,
int stale)
@@ -446,7 +446,7 @@ xfs_buf_item_unpin(
* so we need to free the item's descriptor (that points to the item)
* in the transaction.
*/
-void
+STATIC void
xfs_buf_item_unpin_remove(
xfs_buf_log_item_t *bip,
xfs_trans_t *tp)
@@ -493,7 +493,7 @@ xfs_buf_item_unpin_remove(
* the lock right away, return 0. If we can get the lock, pull the
* buffer from the free list, mark it busy, and return 1.
*/
-uint
+STATIC uint
xfs_buf_item_trylock(
xfs_buf_log_item_t *bip)
{
@@ -537,7 +537,7 @@ xfs_buf_item_trylock(
* This is for support of xfs_trans_bhold(). Make sure the
* XFS_BLI_HOLD field is cleared if we don't free the item.
*/
-void
+STATIC void
xfs_buf_item_unlock(
xfs_buf_log_item_t *bip)
{
@@ -635,7 +635,7 @@ xfs_buf_item_unlock(
* by returning the original lsn of that transaction here rather than
* the current one.
*/
-xfs_lsn_t
+STATIC xfs_lsn_t
xfs_buf_item_committed(
xfs_buf_log_item_t *bip,
xfs_lsn_t lsn)
@@ -654,7 +654,7 @@ xfs_buf_item_committed(
* and have aborted this transaction, we'll trap this buffer when it tries to
* get written out.
*/
-void
+STATIC void
xfs_buf_item_abort(
xfs_buf_log_item_t *bip)
{
@@ -674,7 +674,7 @@ xfs_buf_item_abort(
* B_DELWRI set, then get it going out to disk with a call to bawrite().
* If not, then just release the buffer.
*/
-void
+STATIC void
xfs_buf_item_push(
xfs_buf_log_item_t *bip)
{
@@ -693,7 +693,7 @@ xfs_buf_item_push(
}
/* ARGSUSED */
-void
+STATIC void
xfs_buf_item_committing(xfs_buf_log_item_t *bip, xfs_lsn_t commit_lsn)
{
}
@@ -701,7 +701,7 @@ xfs_buf_item_committing(xfs_buf_log_item_t *bip, xfs_lsn_t commit_lsn)
/*
* This is the ops vector shared by all buf log items.
*/
-struct xfs_item_ops xfs_buf_item_ops = {
+STATIC struct xfs_item_ops xfs_buf_item_ops = {
.iop_size = (uint(*)(xfs_log_item_t*))xfs_buf_item_size,
.iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
xfs_buf_item_format,
diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h
index 5f1b0c9308f..01aed5f2d57 100644
--- a/fs/xfs/xfs_buf_item.h
+++ b/fs/xfs/xfs_buf_item.h
@@ -80,7 +80,7 @@ typedef struct xfs_buf_log_format_t {
* user or group dquots and may require special recovery handling.
*/
#define XFS_BLI_UDQUOT_BUF 0x4
-/* #define XFS_BLI_PDQUOT_BUF 0x8 */
+#define XFS_BLI_PDQUOT_BUF 0x8
#define XFS_BLI_GDQUOT_BUF 0x10
#define XFS_BLI_CHUNK 128
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
index d7fe2886676..8b792ddf216 100644
--- a/fs/xfs/xfs_da_btree.c
+++ b/fs/xfs/xfs_da_btree.c
@@ -113,7 +113,10 @@ STATIC void xfs_da_node_unbalance(xfs_da_state_t *state,
STATIC uint xfs_da_node_lasthash(xfs_dabuf_t *bp, int *count);
STATIC int xfs_da_node_order(xfs_dabuf_t *node1_bp, xfs_dabuf_t *node2_bp);
STATIC xfs_dabuf_t *xfs_da_buf_make(int nbuf, xfs_buf_t **bps, inst_t *ra);
-
+STATIC int xfs_da_blk_unlink(xfs_da_state_t *state,
+ xfs_da_state_blk_t *drop_blk,
+ xfs_da_state_blk_t *save_blk);
+STATIC void xfs_da_state_kill_altpath(xfs_da_state_t *state);
/*========================================================================
* Routines used for growing the Btree.
@@ -1424,7 +1427,7 @@ xfs_da_node_lasthash(xfs_dabuf_t *bp, int *count)
/*
* Unlink a block from a doubly linked list of blocks.
*/
-int /* error */
+STATIC int /* error */
xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
xfs_da_state_blk_t *save_blk)
{
@@ -2381,7 +2384,7 @@ xfs_da_state_alloc(void)
/*
* Kill the altpath contents of a da-state structure.
*/
-void
+STATIC void
xfs_da_state_kill_altpath(xfs_da_state_t *state)
{
int i;
diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h
index 9fc699d9699..3a9b9e809c6 100644
--- a/fs/xfs/xfs_da_btree.h
+++ b/fs/xfs/xfs_da_btree.h
@@ -296,8 +296,6 @@ int xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path,
/*
* Utility routines.
*/
-int xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
- xfs_da_state_blk_t *save_blk);
int xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk,
xfs_da_state_blk_t *new_blk);
@@ -320,7 +318,6 @@ uint xfs_da_hashname(uchar_t *name_string, int name_length);
uint xfs_da_log2_roundup(uint i);
xfs_da_state_t *xfs_da_state_alloc(void);
void xfs_da_state_free(xfs_da_state_t *state);
-void xfs_da_state_kill_altpath(xfs_da_state_t *state);
void xfs_da_buf_done(xfs_dabuf_t *dabuf);
void xfs_da_log_buf(struct xfs_trans *tp, xfs_dabuf_t *dabuf, uint first,
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
index 63abdc2ac7f..681be5c93af 100644
--- a/fs/xfs/xfs_dfrag.c
+++ b/fs/xfs/xfs_dfrag.c
@@ -180,9 +180,10 @@ xfs_swapext(
goto error0;
}
- if (VN_CACHED(tvp) != 0)
- xfs_inval_cached_pages(XFS_ITOV(tip), &(tip->i_iocore),
- (xfs_off_t)0, 0, 0);
+ if (VN_CACHED(tvp) != 0) {
+ xfs_inval_cached_trace(&tip->i_iocore, 0, -1, 0, -1);
+ VOP_FLUSHINVAL_PAGES(tvp, 0, -1, FI_REMAPF_LOCKED);
+ }
/* Verify O_DIRECT for ftmp */
if (VN_CACHED(tvp) != 0) {
diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c
index db9887a107d..a0aa0e44ff9 100644
--- a/fs/xfs/xfs_dir2_data.c
+++ b/fs/xfs/xfs_dir2_data.c
@@ -304,7 +304,7 @@ xfs_dir2_data_freeinsert(
/*
* Remove a bestfree entry from the table.
*/
-void
+STATIC void
xfs_dir2_data_freeremove(
xfs_dir2_data_t *d, /* data block pointer */
xfs_dir2_data_free_t *dfp, /* bestfree entry pointer */
diff --git a/fs/xfs/xfs_dir2_data.h b/fs/xfs/xfs_dir2_data.h
index 3f02294ccff..476cac920bf 100644
--- a/fs/xfs/xfs_dir2_data.h
+++ b/fs/xfs/xfs_dir2_data.h
@@ -193,10 +193,6 @@ extern xfs_dir2_data_free_t *
xfs_dir2_data_unused_t *dup, int *loghead);
extern void
- xfs_dir2_data_freeremove(xfs_dir2_data_t *d,
- xfs_dir2_data_free_t *dfp, int *loghead);
-
-extern void
xfs_dir2_data_freescan(struct xfs_mount *mp, xfs_dir2_data_t *d,
int *loghead, char *aendp);
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index 262d1e86df3..056f5283904 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -77,6 +77,10 @@ static void xfs_dir2_leaf_check(xfs_inode_t *dp, xfs_dabuf_t *bp);
#endif
static int xfs_dir2_leaf_lookup_int(xfs_da_args_t *args, xfs_dabuf_t **lbpp,
int *indexp, xfs_dabuf_t **dbpp);
+static void xfs_dir2_leaf_log_bests(struct xfs_trans *tp, struct xfs_dabuf *bp,
+ int first, int last);
+static void xfs_dir2_leaf_log_tail(struct xfs_trans *tp, struct xfs_dabuf *bp);
+
/*
* Convert a block form directory to a leaf form directory.
@@ -1214,7 +1218,7 @@ xfs_dir2_leaf_init(
/*
* Log the bests entries indicated from a leaf1 block.
*/
-void
+static void
xfs_dir2_leaf_log_bests(
xfs_trans_t *tp, /* transaction pointer */
xfs_dabuf_t *bp, /* leaf buffer */
@@ -1278,7 +1282,7 @@ xfs_dir2_leaf_log_header(
/*
* Log the tail of the leaf1 block.
*/
-void
+STATIC void
xfs_dir2_leaf_log_tail(
xfs_trans_t *tp, /* transaction pointer */
xfs_dabuf_t *bp) /* leaf buffer */
diff --git a/fs/xfs/xfs_dir2_leaf.h b/fs/xfs/xfs_dir2_leaf.h
index 7f20eee56a5..3303cd6f4c0 100644
--- a/fs/xfs/xfs_dir2_leaf.h
+++ b/fs/xfs/xfs_dir2_leaf.h
@@ -330,15 +330,8 @@ extern void
int first, int last);
extern void
- xfs_dir2_leaf_log_bests(struct xfs_trans *tp, struct xfs_dabuf *bp,
- int first, int last);
-
-extern void
xfs_dir2_leaf_log_header(struct xfs_trans *tp, struct xfs_dabuf *bp);
-extern void
- xfs_dir2_leaf_log_tail(struct xfs_trans *tp, struct xfs_dabuf *bp);
-
extern int
xfs_dir2_leaf_lookup(struct xfs_da_args *args);
diff --git a/fs/xfs/xfs_dir_leaf.c b/fs/xfs/xfs_dir_leaf.c
index 617018d6bbd..c2ea6171fb0 100644
--- a/fs/xfs/xfs_dir_leaf.c
+++ b/fs/xfs/xfs_dir_leaf.c
@@ -91,6 +91,10 @@ STATIC int xfs_dir_leaf_figure_balance(xfs_da_state_t *state,
int *number_entries_in_blk1,
int *number_namebytes_in_blk1);
+STATIC int xfs_dir_leaf_create(struct xfs_da_args *args,
+ xfs_dablk_t which_block,
+ struct xfs_dabuf **bpp);
+
/*
* Utility routines.
*/
@@ -781,7 +785,7 @@ xfs_dir_leaf_to_node(xfs_da_args_t *args)
* Create the initial contents of a leaf directory
* or a leaf in a node directory.
*/
-int
+STATIC int
xfs_dir_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp)
{
xfs_dir_leafblock_t *leaf;
diff --git a/fs/xfs/xfs_dir_leaf.h b/fs/xfs/xfs_dir_leaf.h
index 00d68d33cc7..dd423ce1bc8 100644
--- a/fs/xfs/xfs_dir_leaf.h
+++ b/fs/xfs/xfs_dir_leaf.h
@@ -202,8 +202,6 @@ int xfs_dir_leaf_to_shortform(struct xfs_da_args *args);
/*
* Routines used for growing the Btree.
*/
-int xfs_dir_leaf_create(struct xfs_da_args *args, xfs_dablk_t which_block,
- struct xfs_dabuf **bpp);
int xfs_dir_leaf_split(struct xfs_da_state *state,
struct xfs_da_state_blk *oldblk,
struct xfs_da_state_blk *newblk);
diff --git a/fs/xfs/xfs_dmapi.h b/fs/xfs/xfs_dmapi.h
index 55ae3e67d24..55c17adaaa3 100644
--- a/fs/xfs/xfs_dmapi.h
+++ b/fs/xfs/xfs_dmapi.h
@@ -166,27 +166,32 @@ typedef enum {
#define DM_FLAGS_NDELAY 0x001 /* return EAGAIN after dm_pending() */
#define DM_FLAGS_UNWANTED 0x002 /* event not in fsys dm_eventset_t */
#define DM_FLAGS_ISEM 0x004 /* thread holds i_sem */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21)
-/* i_alloc_sem was added in 2.4.22-pre1 */
#define DM_FLAGS_IALLOCSEM_RD 0x010 /* thread holds i_alloc_sem rd */
#define DM_FLAGS_IALLOCSEM_WR 0x020 /* thread holds i_alloc_sem wr */
-#endif
-#endif
/*
* Based on IO_ISDIRECT, decide which i_ flag is set.
*/
-#ifdef DM_FLAGS_IALLOCSEM_RD
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
+#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \
+ DM_FLAGS_ISEM : 0)
+#define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_ISEM)
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) && \
+ (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,22))
#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \
DM_FLAGS_IALLOCSEM_RD : DM_FLAGS_ISEM)
#define DM_SEM_FLAG_WR (DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_ISEM)
-#else
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,21)
#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \
0 : DM_FLAGS_ISEM)
#define DM_SEM_FLAG_WR (DM_FLAGS_ISEM)
#endif
+
/*
* Macros to turn caller specified delay/block flags into
* dm_send_xxxx_event flag DM_FLAGS_NDELAY.
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c
index bbe1dea11c0..dcd3fdd5c1f 100644
--- a/fs/xfs/xfs_error.c
+++ b/fs/xfs/xfs_error.c
@@ -280,7 +280,7 @@ xfs_error_report(
}
}
-void
+STATIC void
xfs_hex_dump(void *p, int length)
{
__uint8_t *uip = (__uint8_t*)p;
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h
index 6bc0535c0a6..52ee2b90b5e 100644
--- a/fs/xfs/xfs_error.h
+++ b/fs/xfs/xfs_error.h
@@ -73,9 +73,6 @@ xfs_corruption_error(
int linenum,
inst_t *ra);
-extern void
-xfs_hex_dump(void *p, int length);
-
#define XFS_ERROR_REPORT(e, lvl, mp) \
xfs_error_report(e, lvl, mp, __FILE__, __LINE__, __return_address)
#define XFS_CORRUPTION_ERROR(e, lvl, mp, mem) \
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index 5eafd5b6321..db7cbd1bc85 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -59,6 +59,18 @@ STATIC void xfs_efi_item_abort(xfs_efi_log_item_t *);
STATIC void xfs_efd_item_abort(xfs_efd_log_item_t *);
+void
+xfs_efi_item_free(xfs_efi_log_item_t *efip)
+{
+ int nexts = efip->efi_format.efi_nextents;
+
+ if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
+ kmem_free(efip, sizeof(xfs_efi_log_item_t) +
+ (nexts - 1) * sizeof(xfs_extent_t));
+ } else {
+ kmem_zone_free(xfs_efi_zone, efip);
+ }
+}
/*
* This returns the number of iovecs needed to log the given efi item.
@@ -120,8 +132,6 @@ xfs_efi_item_pin(xfs_efi_log_item_t *efip)
STATIC void
xfs_efi_item_unpin(xfs_efi_log_item_t *efip, int stale)
{
- int nexts;
- int size;
xfs_mount_t *mp;
SPLDECL(s);
@@ -132,21 +142,11 @@ xfs_efi_item_unpin(xfs_efi_log_item_t *efip, int stale)
* xfs_trans_delete_ail() drops the AIL lock.
*/
xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);
-
- nexts = efip->efi_format.efi_nextents;
- if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
- size = sizeof(xfs_efi_log_item_t);
- size += (nexts - 1) * sizeof(xfs_extent_t);
- kmem_free(efip, size);
- } else {
- kmem_zone_free(xfs_efi_zone, efip);
- }
+ xfs_efi_item_free(efip);
} else {
efip->efi_flags |= XFS_EFI_COMMITTED;
AIL_UNLOCK(mp, s);
}
-
- return;
}
/*
@@ -159,8 +159,6 @@ xfs_efi_item_unpin(xfs_efi_log_item_t *efip, int stale)
STATIC void
xfs_efi_item_unpin_remove(xfs_efi_log_item_t *efip, xfs_trans_t *tp)
{
- int nexts;
- int size;
xfs_mount_t *mp;
xfs_log_item_desc_t *lidp;
SPLDECL(s);
@@ -178,23 +176,11 @@ xfs_efi_item_unpin_remove(xfs_efi_log_item_t *efip, xfs_trans_t *tp)
* xfs_trans_delete_ail() drops the AIL lock.
*/
xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);
- /*
- * now free the item itself
- */
- nexts = efip->efi_format.efi_nextents;
- if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
- size = sizeof(xfs_efi_log_item_t);
- size += (nexts - 1) * sizeof(xfs_extent_t);
- kmem_free(efip, size);
- } else {
- kmem_zone_free(xfs_efi_zone, efip);
- }
+ xfs_efi_item_free(efip);
} else {
efip->efi_flags |= XFS_EFI_COMMITTED;
AIL_UNLOCK(mp, s);
}
-
- return;
}
/*
@@ -245,18 +231,7 @@ xfs_efi_item_committed(xfs_efi_log_item_t *efip, xfs_lsn_t lsn)
STATIC void
xfs_efi_item_abort(xfs_efi_log_item_t *efip)
{
- int nexts;
- int size;
-
- nexts = efip->efi_format.efi_nextents;
- if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
- size = sizeof(xfs_efi_log_item_t);
- size += (nexts - 1) * sizeof(xfs_extent_t);
- kmem_free(efip, size);
- } else {
- kmem_zone_free(xfs_efi_zone, efip);
- }
- return;
+ xfs_efi_item_free(efip);
}
/*
@@ -288,7 +263,7 @@ xfs_efi_item_committing(xfs_efi_log_item_t *efip, xfs_lsn_t lsn)
/*
* This is the ops vector shared by all efi log items.
*/
-struct xfs_item_ops xfs_efi_item_ops = {
+STATIC struct xfs_item_ops xfs_efi_item_ops = {
.iop_size = (uint(*)(xfs_log_item_t*))xfs_efi_item_size,
.iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
xfs_efi_item_format,
@@ -355,8 +330,6 @@ xfs_efi_release(xfs_efi_log_item_t *efip,
{
xfs_mount_t *mp;
int extents_left;
- uint size;
- int nexts;
SPLDECL(s);
mp = efip->efi_item.li_mountp;
@@ -372,20 +345,10 @@ xfs_efi_release(xfs_efi_log_item_t *efip,
* xfs_trans_delete_ail() drops the AIL lock.
*/
xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);
+ xfs_efi_item_free(efip);
} else {
AIL_UNLOCK(mp, s);
}
-
- if (extents_left == 0) {
- nexts = efip->efi_format.efi_nextents;
- if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
- size = sizeof(xfs_efi_log_item_t);
- size += (nexts - 1) * sizeof(xfs_extent_t);
- kmem_free(efip, size);
- } else {
- kmem_zone_free(xfs_efi_zone, efip);
- }
- }
}
/*
@@ -398,8 +361,6 @@ STATIC void
xfs_efi_cancel(
xfs_efi_log_item_t *efip)
{
- int nexts;
- int size;
xfs_mount_t *mp;
SPLDECL(s);
@@ -410,26 +371,25 @@ xfs_efi_cancel(
* xfs_trans_delete_ail() drops the AIL lock.
*/
xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);
-
- nexts = efip->efi_format.efi_nextents;
- if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
- size = sizeof(xfs_efi_log_item_t);
- size += (nexts - 1) * sizeof(xfs_extent_t);
- kmem_free(efip, size);
- } else {
- kmem_zone_free(xfs_efi_zone, efip);
- }
+ xfs_efi_item_free(efip);
} else {
efip->efi_flags |= XFS_EFI_CANCELED;
AIL_UNLOCK(mp, s);
}
-
- return;
}
+STATIC void
+xfs_efd_item_free(xfs_efd_log_item_t *efdp)
+{
+ int nexts = efdp->efd_format.efd_nextents;
-
-
+ if (nexts > XFS_EFD_MAX_FAST_EXTENTS) {
+ kmem_free(efdp, sizeof(xfs_efd_log_item_t) +
+ (nexts - 1) * sizeof(xfs_extent_t));
+ } else {
+ kmem_zone_free(xfs_efd_zone, efdp);
+ }
+}
/*
* This returns the number of iovecs needed to log the given efd item.
@@ -533,9 +493,6 @@ xfs_efd_item_unlock(xfs_efd_log_item_t *efdp)
STATIC xfs_lsn_t
xfs_efd_item_committed(xfs_efd_log_item_t *efdp, xfs_lsn_t lsn)
{
- uint size;
- int nexts;
-
/*
* If we got a log I/O error, it's always the case that the LR with the
* EFI got unpinned and freed before the EFD got aborted.
@@ -543,15 +500,7 @@ xfs_efd_item_committed(xfs_efd_log_item_t *efdp, xfs_lsn_t lsn)
if ((efdp->efd_item.li_flags & XFS_LI_ABORTED) == 0)
xfs_efi_release(efdp->efd_efip, efdp->efd_format.efd_nextents);
- nexts = efdp->efd_format.efd_nextents;
- if (nexts > XFS_EFD_MAX_FAST_EXTENTS) {
- size = sizeof(xfs_efd_log_item_t);
- size += (nexts - 1) * sizeof(xfs_extent_t);
- kmem_free(efdp, size);
- } else {
- kmem_zone_free(xfs_efd_zone, efdp);
- }
-
+ xfs_efd_item_free(efdp);
return (xfs_lsn_t)-1;
}
@@ -565,9 +514,6 @@ xfs_efd_item_committed(xfs_efd_log_item_t *efdp, xfs_lsn_t lsn)
STATIC void
xfs_efd_item_abort(xfs_efd_log_item_t *efdp)
{
- int nexts;
- int size;
-
/*
* If we got a log I/O error, it's always the case that the LR with the
* EFI got unpinned and freed before the EFD got aborted. So don't
@@ -576,15 +522,7 @@ xfs_efd_item_abort(xfs_efd_log_item_t *efdp)
if ((efdp->efd_item.li_flags & XFS_LI_ABORTED) == 0)
xfs_efi_cancel(efdp->efd_efip);
- nexts = efdp->efd_format.efd_nextents;
- if (nexts > XFS_EFD_MAX_FAST_EXTENTS) {
- size = sizeof(xfs_efd_log_item_t);
- size += (nexts - 1) * sizeof(xfs_extent_t);
- kmem_free(efdp, size);
- } else {
- kmem_zone_free(xfs_efd_zone, efdp);
- }
- return;
+ xfs_efd_item_free(efdp);
}
/*
@@ -615,7 +553,7 @@ xfs_efd_item_committing(xfs_efd_log_item_t *efip, xfs_lsn_t lsn)
/*
* This is the ops vector shared by all efd log items.
*/
-struct xfs_item_ops xfs_efd_item_ops = {
+STATIC struct xfs_item_ops xfs_efd_item_ops = {
.iop_size = (uint(*)(xfs_log_item_t*))xfs_efd_item_size,
.iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
xfs_efd_item_format,
diff --git a/fs/xfs/xfs_extfree_item.h b/fs/xfs/xfs_extfree_item.h
index 7122d6101d1..d433bac9f59 100644
--- a/fs/xfs/xfs_extfree_item.h
+++ b/fs/xfs/xfs_extfree_item.h
@@ -118,6 +118,8 @@ xfs_efi_log_item_t *xfs_efi_init(struct xfs_mount *, uint);
xfs_efd_log_item_t *xfs_efd_init(struct xfs_mount *, xfs_efi_log_item_t *,
uint);
+void xfs_efi_item_free(xfs_efi_log_item_t *);
+
#endif /* __KERNEL__ */
#endif /* __XFS_EXTFREE_ITEM_H__ */
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
index 6ee8443bf9d..095af0a5cff 100644
--- a/fs/xfs/xfs_fs.h
+++ b/fs/xfs/xfs_fs.h
@@ -60,7 +60,8 @@ struct fsxattr {
__u32 fsx_xflags; /* xflags field value (get/set) */
__u32 fsx_extsize; /* extsize field value (get/set)*/
__u32 fsx_nextents; /* nextents field value (get) */
- unsigned char fsx_pad[16];
+ __u32 fsx_projid; /* project identifier (get/set) */
+ unsigned char fsx_pad[12];
};
#endif
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index 21213057c27..ca535d61319 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -559,32 +559,6 @@ xfs_reserve_blocks(
return(0);
}
-void
-xfs_fs_log_dummy(xfs_mount_t *mp)
-{
- xfs_trans_t *tp;
- xfs_inode_t *ip;
-
-
- tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1);
- atomic_inc(&mp->m_active_trans);
- if (xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0)) {
- xfs_trans_cancel(tp, 0);
- return;
- }
-
- ip = mp->m_rootip;
- xfs_ilock(ip, XFS_ILOCK_EXCL);
-
- xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
- xfs_trans_ihold(tp, ip);
- xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
- xfs_trans_set_sync(tp);
- xfs_trans_commit(tp, 0, NULL);
-
- xfs_iunlock(ip, XFS_ILOCK_EXCL);
-}
-
int
xfs_fs_goingdown(
xfs_mount_t *mp,
diff --git a/fs/xfs/xfs_ialloc_btree.h b/fs/xfs/xfs_ialloc_btree.h
index 803c4d17a05..44be188674a 100644
--- a/fs/xfs/xfs_ialloc_btree.h
+++ b/fs/xfs/xfs_ialloc_btree.h
@@ -100,9 +100,13 @@ xfs_inofree_t xfs_inobt_mask(int i);
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_INOBT_IS_FREE)
int xfs_inobt_is_free(xfs_inobt_rec_t *rp, int i);
-#define XFS_INOBT_IS_FREE(rp,i) xfs_inobt_is_free(rp,i)
+#define XFS_INOBT_IS_FREE(rp,i) xfs_inobt_is_free(rp,i)
+#define XFS_INOBT_IS_FREE_DISK(rp,i) xfs_inobt_is_free_disk(rp,i)
#else
-#define XFS_INOBT_IS_FREE(rp,i) (((rp)->ir_free & XFS_INOBT_MASK(i)) != 0)
+#define XFS_INOBT_IS_FREE(rp,i) \
+ (((rp)->ir_free & XFS_INOBT_MASK(i)) != 0)
+#define XFS_INOBT_IS_FREE_DISK(rp,i) \
+ ((INT_GET((rp)->ir_free, ARCH_CONVERT) & XFS_INOBT_MASK(i)) != 0)
#endif
#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_INOBT_SET_FREE)
void xfs_inobt_set_free(xfs_inobt_rec_t *rp, int i);
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index bc8c8c7f903..34bdf590968 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -146,51 +146,6 @@ xfs_inobp_check(
#endif
/*
- * called from bwrite on xfs inode buffers
- */
-void
-xfs_inobp_bwcheck(xfs_buf_t *bp)
-{
- xfs_mount_t *mp;
- int i;
- int j;
- xfs_dinode_t *dip;
-
- ASSERT(XFS_BUF_FSPRIVATE3(bp, void *) != NULL);
-
- mp = XFS_BUF_FSPRIVATE3(bp, xfs_mount_t *);
-
-
- j = mp->m_inode_cluster_size >> mp->m_sb.sb_inodelog;
-
- for (i = 0; i < j; i++) {
- dip = (xfs_dinode_t *) xfs_buf_offset(bp,
- i * mp->m_sb.sb_inodesize);
- if (INT_GET(dip->di_core.di_magic, ARCH_CONVERT) != XFS_DINODE_MAGIC) {
- cmn_err(CE_WARN,
-"Bad magic # 0x%x in XFS inode buffer 0x%Lx, starting blockno %Ld, offset 0x%x",
- INT_GET(dip->di_core.di_magic, ARCH_CONVERT),
- (__uint64_t)(__psunsigned_t) bp,
- (__int64_t) XFS_BUF_ADDR(bp),
- xfs_buf_offset(bp, i * mp->m_sb.sb_inodesize));
- xfs_fs_cmn_err(CE_WARN, mp,
- "corrupt, unmount and run xfs_repair");
- }
- if (!dip->di_next_unlinked) {
- cmn_err(CE_WARN,
-"Bad next_unlinked field (0) in XFS inode buffer 0x%p, starting blockno %Ld, offset 0x%x",
- (__uint64_t)(__psunsigned_t) bp,
- (__int64_t) XFS_BUF_ADDR(bp),
- xfs_buf_offset(bp, i * mp->m_sb.sb_inodesize));
- xfs_fs_cmn_err(CE_WARN, mp,
- "corrupt, unmount and run xfs_repair");
- }
- }
-
- return;
-}
-
-/*
* This routine is called to map an inode number within a file
* system to the buffer containing the on-disk version of the
* inode. It returns a pointer to the buffer containing the
@@ -203,7 +158,7 @@ xfs_inobp_bwcheck(xfs_buf_t *bp)
* Use xfs_imap() to determine the size and location of the
* buffer to read from disk.
*/
-int
+STATIC int
xfs_inotobp(
xfs_mount_t *mp,
xfs_trans_t *tp,
@@ -1247,26 +1202,32 @@ xfs_ialloc(
case S_IFREG:
case S_IFDIR:
if (unlikely(pip->i_d.di_flags & XFS_DIFLAG_ANY)) {
- if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) {
- if ((mode & S_IFMT) == S_IFDIR) {
- ip->i_d.di_flags |= XFS_DIFLAG_RTINHERIT;
- } else {
- ip->i_d.di_flags |= XFS_DIFLAG_REALTIME;
+ uint di_flags = 0;
+
+ if ((mode & S_IFMT) == S_IFDIR) {
+ if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT)
+ di_flags |= XFS_DIFLAG_RTINHERIT;
+ } else {
+ if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) {
+ di_flags |= XFS_DIFLAG_REALTIME;
ip->i_iocore.io_flags |= XFS_IOCORE_RT;
}
}
if ((pip->i_d.di_flags & XFS_DIFLAG_NOATIME) &&
xfs_inherit_noatime)
- ip->i_d.di_flags |= XFS_DIFLAG_NOATIME;
+ di_flags |= XFS_DIFLAG_NOATIME;
if ((pip->i_d.di_flags & XFS_DIFLAG_NODUMP) &&
xfs_inherit_nodump)
- ip->i_d.di_flags |= XFS_DIFLAG_NODUMP;
+ di_flags |= XFS_DIFLAG_NODUMP;
if ((pip->i_d.di_flags & XFS_DIFLAG_SYNC) &&
xfs_inherit_sync)
- ip->i_d.di_flags |= XFS_DIFLAG_SYNC;
+ di_flags |= XFS_DIFLAG_SYNC;
if ((pip->i_d.di_flags & XFS_DIFLAG_NOSYMLINKS) &&
xfs_inherit_nosymlinks)
- ip->i_d.di_flags |= XFS_DIFLAG_NOSYMLINKS;
+ di_flags |= XFS_DIFLAG_NOSYMLINKS;
+ if (pip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
+ di_flags |= XFS_DIFLAG_PROJINHERIT;
+ ip->i_d.di_flags |= di_flags;
}
/* FALLTHROUGH */
case S_IFLNK:
@@ -2156,7 +2117,7 @@ static __inline__ int xfs_inode_clean(xfs_inode_t *ip)
(ip->i_update_core == 0));
}
-void
+STATIC void
xfs_ifree_cluster(
xfs_inode_t *free_ip,
xfs_trans_t *tp,
@@ -2875,7 +2836,7 @@ xfs_iunpin(
* be subsequently pinned once someone is waiting for it to be
* unpinned.
*/
-void
+STATIC void
xfs_iunpin_wait(
xfs_inode_t *ip)
{
@@ -3601,107 +3562,43 @@ corrupt_out:
/*
- * Flush all inactive inodes in mp. Return true if no user references
- * were found, false otherwise.
+ * Flush all inactive inodes in mp.
*/
-int
+void
xfs_iflush_all(
- xfs_mount_t *mp,
- int flag)
+ xfs_mount_t *mp)
{
- int busy;
- int done;
- int purged;
xfs_inode_t *ip;
- vmap_t vmap;
vnode_t *vp;
- busy = done = 0;
- while (!done) {
- purged = 0;
- XFS_MOUNT_ILOCK(mp);
- ip = mp->m_inodes;
- if (ip == NULL) {
- break;
- }
- do {
- /* Make sure we skip markers inserted by sync */
- if (ip->i_mount == NULL) {
- ip = ip->i_mnext;
- continue;
- }
-
- /*
- * It's up to our caller to purge the root
- * and quota vnodes later.
- */
- vp = XFS_ITOV_NULL(ip);
-
- if (!vp) {
- XFS_MOUNT_IUNLOCK(mp);
- xfs_finish_reclaim(ip, 0, XFS_IFLUSH_ASYNC);
- purged = 1;
- break;
- }
+ again:
+ XFS_MOUNT_ILOCK(mp);
+ ip = mp->m_inodes;
+ if (ip == NULL)
+ goto out;
- if (vn_count(vp) != 0) {
- if (vn_count(vp) == 1 &&
- (ip == mp->m_rootip ||
- (mp->m_quotainfo &&
- (ip->i_ino == mp->m_sb.sb_uquotino ||
- ip->i_ino == mp->m_sb.sb_gquotino)))) {
+ do {
+ /* Make sure we skip markers inserted by sync */
+ if (ip->i_mount == NULL) {
+ ip = ip->i_mnext;
+ continue;
+ }
- ip = ip->i_mnext;
- continue;
- }
- if (!(flag & XFS_FLUSH_ALL)) {
- busy = 1;
- done = 1;
- break;
- }
- /*
- * Ignore busy inodes but continue flushing
- * others.
- */
- ip = ip->i_mnext;
- continue;
- }
- /*
- * Sample vp mapping while holding mp locked on MP
- * systems, so we don't purge a reclaimed or
- * nonexistent vnode. We break from the loop
- * since we know that we modify
- * it by pulling ourselves from it in xfs_reclaim()
- * called via vn_purge() below. Set ip to the next
- * entry in the list anyway so we'll know below
- * whether we reached the end or not.
- */
- VMAP(vp, vmap);
+ vp = XFS_ITOV_NULL(ip);
+ if (!vp) {
XFS_MOUNT_IUNLOCK(mp);
+ xfs_finish_reclaim(ip, 0, XFS_IFLUSH_ASYNC);
+ goto again;
+ }
- vn_purge(vp, &vmap);
+ ASSERT(vn_count(vp) == 0);
- purged = 1;
- break;
- } while (ip != mp->m_inodes);
- /*
- * We need to distinguish between when we exit the loop
- * after a purge and when we simply hit the end of the
- * list. We can't use the (ip == mp->m_inodes) test,
- * because when we purge an inode at the start of the list
- * the next inode on the list becomes mp->m_inodes. That
- * would cause such a test to bail out early. The purged
- * variable tells us how we got out of the loop.
- */
- if (!purged) {
- done = 1;
- }
- }
+ ip = ip->i_mnext;
+ } while (ip != mp->m_inodes);
+ out:
XFS_MOUNT_IUNLOCK(mp);
- return !busy;
}
-
/*
* xfs_iaccess: check accessibility of inode for mode.
*/
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 37e1c316f3b..54d9e54c7c9 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -412,11 +412,6 @@ void xfs_ifork_next_set(xfs_inode_t *ip, int w, int n);
#define XFS_IFLUSH_DELWRI 5
/*
- * Flags for xfs_iflush_all.
- */
-#define XFS_FLUSH_ALL 0x1
-
-/*
* Flags for xfs_itruncate_start().
*/
#define XFS_ITRUNC_DEFINITE 0x1
@@ -487,8 +482,6 @@ int xfs_finish_reclaim_all(struct xfs_mount *, int);
/*
* xfs_inode.c prototypes.
*/
-int xfs_inotobp(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
- xfs_dinode_t **, struct xfs_buf **, int *);
int xfs_itobp(struct xfs_mount *, struct xfs_trans *,
xfs_inode_t *, xfs_dinode_t **, struct xfs_buf **,
xfs_daddr_t);
@@ -522,7 +515,7 @@ void xfs_ipin(xfs_inode_t *);
void xfs_iunpin(xfs_inode_t *);
int xfs_iextents_copy(xfs_inode_t *, xfs_bmbt_rec_t *, int);
int xfs_iflush(xfs_inode_t *, uint);
-int xfs_iflush_all(struct xfs_mount *, int);
+void xfs_iflush_all(struct xfs_mount *);
int xfs_iaccess(xfs_inode_t *, mode_t, cred_t *);
uint xfs_iroundup(uint);
void xfs_ichgtime(xfs_inode_t *, int);
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 768cb1816b8..0eed30f5cb1 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -910,7 +910,7 @@ xfs_inode_item_committing(
/*
* This is the ops vector shared by all buf log items.
*/
-struct xfs_item_ops xfs_inode_item_ops = {
+STATIC struct xfs_item_ops xfs_inode_item_ops = {
.iop_size = (uint(*)(xfs_log_item_t*))xfs_inode_item_size,
.iop_format = (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
xfs_inode_item_format,
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 991f8a61f7c..2edd6769e5d 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -278,7 +278,9 @@ phase2:
switch (flags & (BMAPI_WRITE|BMAPI_ALLOCATE|BMAPI_UNWRITTEN)) {
case BMAPI_WRITE:
/* If we found an extent, return it */
- if (nimaps && (imap.br_startblock != HOLESTARTBLOCK)) {
+ if (nimaps &&
+ (imap.br_startblock != HOLESTARTBLOCK) &&
+ (imap.br_startblock != DELAYSTARTBLOCK)) {
xfs_iomap_map_trace(XFS_IOMAP_WRITE_MAP, io,
offset, count, iomapp, &imap, flags);
break;
@@ -383,15 +385,15 @@ xfs_iomap_write_direct(
int nimaps, maps;
int error;
int bmapi_flag;
+ int quota_flag;
int rt;
xfs_trans_t *tp;
xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS], *imapp;
xfs_bmap_free_t free_list;
int aeof;
- xfs_filblks_t datablocks;
+ xfs_filblks_t datablocks, qblocks, resblks;
int committed;
int numrtextents;
- uint resblks;
/*
* Make sure that the dquots are there. This doesn't hold
@@ -417,7 +419,6 @@ xfs_iomap_write_direct(
xfs_fileoff_t map_last_fsb;
map_last_fsb = ret_imap->br_blockcount + ret_imap->br_startoff;
-
if (map_last_fsb < last_fsb) {
last_fsb = map_last_fsb;
count_fsb = last_fsb - offset_fsb;
@@ -426,56 +427,47 @@ xfs_iomap_write_direct(
}
/*
- * determine if reserving space on
- * the data or realtime partition.
+ * Determine if reserving space on the data or realtime partition.
*/
if ((rt = XFS_IS_REALTIME_INODE(ip))) {
- int sbrtextsize, iprtextsize;
+ xfs_extlen_t extsz;
- sbrtextsize = mp->m_sb.sb_rextsize;
- iprtextsize =
- ip->i_d.di_extsize ? ip->i_d.di_extsize : sbrtextsize;
- numrtextents = (count_fsb + iprtextsize - 1);
- do_div(numrtextents, sbrtextsize);
+ if (!(extsz = ip->i_d.di_extsize))
+ extsz = mp->m_sb.sb_rextsize;
+ numrtextents = qblocks = (count_fsb + extsz - 1);
+ do_div(numrtextents, mp->m_sb.sb_rextsize);
+ quota_flag = XFS_QMOPT_RES_RTBLKS;
datablocks = 0;
} else {
- datablocks = count_fsb;
+ datablocks = qblocks = count_fsb;
+ quota_flag = XFS_QMOPT_RES_REGBLKS;
numrtextents = 0;
}
/*
- * allocate and setup the transaction
+ * Allocate and setup the transaction
*/
xfs_iunlock(ip, XFS_ILOCK_EXCL);
tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
-
resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks);
-
error = xfs_trans_reserve(tp, resblks,
XFS_WRITE_LOG_RES(mp), numrtextents,
XFS_TRANS_PERM_LOG_RES,
XFS_WRITE_LOG_COUNT);
/*
- * check for running out of space
+ * Check for running out of space, note: need lock to return
*/
if (error)
- /*
- * Free the transaction structure.
- */
xfs_trans_cancel(tp, 0);
-
xfs_ilock(ip, XFS_ILOCK_EXCL);
-
if (error)
- goto error_out; /* Don't return in above if .. trans ..,
- need lock to return */
+ goto error_out;
- if (XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, resblks)) {
+ if (XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag)) {
error = (EDQUOT);
goto error1;
}
- nimaps = 1;
bmapi_flag = XFS_BMAPI_WRITE;
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
@@ -485,31 +477,29 @@ xfs_iomap_write_direct(
bmapi_flag |= XFS_BMAPI_PREALLOC;
/*
- * issue the bmapi() call to allocate the blocks
+ * Issue the bmapi() call to allocate the blocks
*/
XFS_BMAP_INIT(&free_list, &firstfsb);
+ nimaps = 1;
imapp = &imap[0];
error = xfs_bmapi(tp, ip, offset_fsb, count_fsb,
bmapi_flag, &firstfsb, 0, imapp, &nimaps, &free_list);
- if (error) {
+ if (error)
goto error0;
- }
/*
- * complete the transaction
+ * Complete the transaction
*/
-
error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed);
- if (error) {
+ if (error)
goto error0;
- }
-
error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
- if (error) {
+ if (error)
goto error_out;
- }
- /* copy any maps to caller's array and return any error. */
+ /*
+ * Copy any maps to caller's array and return any error.
+ */
if (nimaps == 0) {
error = (ENOSPC);
goto error_out;
@@ -528,10 +518,11 @@ xfs_iomap_write_direct(
}
return 0;
- error0: /* Cancel bmap, unlock inode, and cancel trans */
+error0: /* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */
xfs_bmap_cancel(&free_list);
+ XFS_TRANS_UNRESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag);
- error1: /* Just cancel transaction */
+error1: /* Just cancel transaction */
xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
*nmaps = 0; /* nothing set-up here */
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 092d5fb096b..1cd2ac16387 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -134,7 +134,7 @@ STATIC void xlog_verify_tail_lsn(xlog_t *log, xlog_in_core_t *iclog,
#define xlog_verify_tail_lsn(a,b,c)
#endif
-int xlog_iclogs_empty(xlog_t *log);
+STATIC int xlog_iclogs_empty(xlog_t *log);
#ifdef DEBUG
int xlog_do_error = 0;
@@ -1857,7 +1857,7 @@ xlog_write(xfs_mount_t * mp,
*
* State Change: DIRTY -> ACTIVE
*/
-void
+STATIC void
xlog_state_clean_log(xlog_t *log)
{
xlog_in_core_t *iclog;
@@ -3542,7 +3542,7 @@ xfs_log_force_umount(
return (retval);
}
-int
+STATIC int
xlog_iclogs_empty(xlog_t *log)
{
xlog_in_core_t *iclog;
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index c31e3ce3be6..1a1d452f15f 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -535,7 +535,6 @@ typedef struct log {
/* common routines */
extern xfs_lsn_t xlog_assign_tail_lsn(struct xfs_mount *mp);
-extern int xlog_find_head(xlog_t *log, xfs_daddr_t *head_blk);
extern int xlog_find_tail(xlog_t *log,
xfs_daddr_t *head_blk,
xfs_daddr_t *tail_blk,
@@ -548,7 +547,6 @@ extern void xlog_recover_process_iunlinks(xlog_t *log);
extern struct xfs_buf *xlog_get_bp(xlog_t *, int);
extern void xlog_put_bp(struct xfs_buf *);
extern int xlog_bread(xlog_t *, xfs_daddr_t, int, struct xfs_buf *);
-extern xfs_caddr_t xlog_align(xlog_t *, xfs_daddr_t, int, struct xfs_buf *);
/* iclog tracing */
#define XLOG_TRACE_GRAB_FLUSH 1
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 9824b5bf0ec..0aac28ddb81 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -148,7 +148,7 @@ xlog_bread(
* The buffer is kept locked across the write and is returned locked.
* This can only be used for synchronous log writes.
*/
-int
+STATIC int
xlog_bwrite(
xlog_t *log,
xfs_daddr_t blk_no,
@@ -179,7 +179,7 @@ xlog_bwrite(
return error;
}
-xfs_caddr_t
+STATIC xfs_caddr_t
xlog_align(
xlog_t *log,
xfs_daddr_t blk_no,
@@ -528,7 +528,7 @@ out:
*
* Return: zero if normal, non-zero if error.
*/
-int
+STATIC int
xlog_find_head(
xlog_t *log,
xfs_daddr_t *return_head_blk)
@@ -1964,7 +1964,8 @@ xlog_recover_do_reg_buffer(
* probably a good thing to do for other buf types also.
*/
error = 0;
- if (buf_f->blf_flags & (XFS_BLI_UDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) {
+ if (buf_f->blf_flags &
+ (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) {
error = xfs_qm_dqcheck((xfs_disk_dquot_t *)
item->ri_buf[i].i_addr,
-1, 0, XFS_QMOPT_DOWARN,
@@ -2030,6 +2031,7 @@ xfs_qm_dqcheck(
}
if (INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_USER &&
+ INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_PROJ &&
INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_GROUP) {
if (flags & XFS_QMOPT_DOWARN)
cmn_err(CE_ALERT,
@@ -2135,6 +2137,8 @@ xlog_recover_do_dquot_buffer(
type = 0;
if (buf_f->blf_flags & XFS_BLI_UDQUOT_BUF)
type |= XFS_DQ_USER;
+ if (buf_f->blf_flags & XFS_BLI_PDQUOT_BUF)
+ type |= XFS_DQ_PROJ;
if (buf_f->blf_flags & XFS_BLI_GDQUOT_BUF)
type |= XFS_DQ_GROUP;
/*
@@ -2247,7 +2251,8 @@ xlog_recover_do_buffer_trans(
error = 0;
if (flags & XFS_BLI_INODE_BUF) {
error = xlog_recover_do_inode_buffer(mp, item, bp, buf_f);
- } else if (flags & (XFS_BLI_UDQUOT_BUF | XFS_BLI_GDQUOT_BUF)) {
+ } else if (flags &
+ (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) {
xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f);
} else {
xlog_recover_do_reg_buffer(mp, item, bp, buf_f);
@@ -2619,7 +2624,7 @@ xlog_recover_do_dquot_trans(
* This type of quotas was turned off, so ignore this record.
*/
type = INT_GET(recddq->d_flags, ARCH_CONVERT) &
- (XFS_DQ_USER | XFS_DQ_GROUP);
+ (XFS_DQ_USER | XFS_DQ_PROJ | XFS_DQ_GROUP);
ASSERT(type);
if (log->l_quotaoffs_flag & type)
return (0);
@@ -2742,7 +2747,6 @@ xlog_recover_do_efd_trans(
xfs_efi_log_item_t *efip = NULL;
xfs_log_item_t *lip;
int gen;
- int nexts;
__uint64_t efi_id;
SPLDECL(s);
@@ -2777,22 +2781,15 @@ xlog_recover_do_efd_trans(
}
lip = xfs_trans_next_ail(mp, lip, &gen, NULL);
}
- if (lip == NULL) {
- AIL_UNLOCK(mp, s);
- }
/*
* If we found it, then free it up. If it wasn't there, it
* must have been overwritten in the log. Oh well.
*/
if (lip != NULL) {
- nexts = efip->efi_format.efi_nextents;
- if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
- kmem_free(lip, sizeof(xfs_efi_log_item_t) +
- ((nexts - 1) * sizeof(xfs_extent_t)));
- } else {
- kmem_zone_free(xfs_efi_zone, efip);
- }
+ xfs_efi_item_free(efip);
+ } else {
+ AIL_UNLOCK(mp, s);
}
}
diff --git a/fs/xfs/xfs_macros.c b/fs/xfs/xfs_macros.c
index ce4f46c6b3a..698c2cd6285 100644
--- a/fs/xfs/xfs_macros.c
+++ b/fs/xfs/xfs_macros.c
@@ -1658,6 +1658,11 @@ xfs_inobt_is_free(xfs_inobt_rec_t *rp, int i)
{
return XFS_INOBT_IS_FREE(rp, i);
}
+int
+xfs_inobt_is_free_disk(xfs_inobt_rec_t *rp, int i)
+{
+ return XFS_INOBT_IS_FREE_DISK(rp, i);
+}
#endif
#if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_INOBT_IS_LAST_REC)
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 2ec967d93e5..82e1646e624 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -64,6 +64,7 @@
STATIC void xfs_mount_log_sbunit(xfs_mount_t *, __int64_t);
STATIC int xfs_uuid_mount(xfs_mount_t *);
STATIC void xfs_uuid_unmount(xfs_mount_t *mp);
+STATIC void xfs_unmountfs_wait(xfs_mount_t *);
static struct {
short offset;
@@ -555,7 +556,7 @@ xfs_readsb(xfs_mount_t *mp)
* fields from the superblock associated with the given
* mount structure
*/
-void
+STATIC void
xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp)
{
int i;
@@ -1081,7 +1082,7 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
int64_t fsid;
#endif
- xfs_iflush_all(mp, XFS_FLUSH_ALL);
+ xfs_iflush_all(mp);
XFS_QM_DQPURGEALL(mp,
XFS_QMOPT_UQUOTA | XFS_QMOPT_GQUOTA | XFS_QMOPT_UMOUNTING);
@@ -1111,15 +1112,6 @@ xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
*/
ASSERT(mp->m_inodes == NULL);
- /*
- * We may have bufs that are in the process of getting written still.
- * We must wait for the I/O completion of those. The sync flag here
- * does a two pass iteration thru the bufcache.
- */
- if (XFS_FORCED_SHUTDOWN(mp)) {
- xfs_incore_relse(mp->m_ddev_targp, 0, 1); /* synchronous */
- }
-
xfs_unmountfs_close(mp, cr);
if ((mp->m_flags & XFS_MOUNT_NOUUID) == 0)
xfs_uuid_unmount(mp);
@@ -1146,7 +1138,7 @@ xfs_unmountfs_close(xfs_mount_t *mp, struct cred *cr)
xfs_free_buftarg(mp->m_ddev_targp, 0);
}
-void
+STATIC void
xfs_unmountfs_wait(xfs_mount_t *mp)
{
if (mp->m_logdev_targp != mp->m_ddev_targp)
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 30dd08fb9f5..5affba38a57 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -141,7 +141,7 @@ typedef int (*xfs_dqattach_t)(struct xfs_inode *, uint);
typedef void (*xfs_dqdetach_t)(struct xfs_inode *);
typedef int (*xfs_dqpurgeall_t)(struct xfs_mount *, uint);
typedef int (*xfs_dqvopalloc_t)(struct xfs_mount *,
- struct xfs_inode *, uid_t, gid_t, uint,
+ struct xfs_inode *, uid_t, gid_t, prid_t, uint,
struct xfs_dquot **, struct xfs_dquot **);
typedef void (*xfs_dqvopcreate_t)(struct xfs_trans *, struct xfs_inode *,
struct xfs_dquot *, struct xfs_dquot *);
@@ -185,8 +185,8 @@ typedef struct xfs_qmops {
(*(mp)->m_qm_ops.xfs_dqdetach)(ip)
#define XFS_QM_DQPURGEALL(mp, fl) \
(*(mp)->m_qm_ops.xfs_dqpurgeall)(mp, fl)
-#define XFS_QM_DQVOPALLOC(mp, ip, uid, gid, fl, dq1, dq2) \
- (*(mp)->m_qm_ops.xfs_dqvopalloc)(mp, ip, uid, gid, fl, dq1, dq2)
+#define XFS_QM_DQVOPALLOC(mp, ip, uid, gid, prid, fl, dq1, dq2) \
+ (*(mp)->m_qm_ops.xfs_dqvopalloc)(mp, ip, uid, gid, prid, fl, dq1, dq2)
#define XFS_QM_DQVOPCREATE(mp, tp, ip, dq1, dq2) \
(*(mp)->m_qm_ops.xfs_dqvopcreate)(tp, ip, dq1, dq2)
#define XFS_QM_DQVOPRENAME(mp, ip) \
@@ -544,7 +544,6 @@ extern void xfs_mount_free(xfs_mount_t *mp, int remove_bhv);
extern int xfs_mountfs(struct vfs *, xfs_mount_t *mp, int);
extern int xfs_unmountfs(xfs_mount_t *, struct cred *);
-extern void xfs_unmountfs_wait(xfs_mount_t *);
extern void xfs_unmountfs_close(xfs_mount_t *, struct cred *);
extern int xfs_unmountfs_writesb(xfs_mount_t *);
extern int xfs_unmount_flush(xfs_mount_t *, int);
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index 703ec4efcb4..7134576ae7f 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -96,7 +96,7 @@ typedef struct xfs_dqblk {
* flags for q_flags field in the dquot.
*/
#define XFS_DQ_USER 0x0001 /* a user quota */
-/* #define XFS_DQ_PROJ 0x0002 -- project quota (IRIX) */
+#define XFS_DQ_PROJ 0x0002 /* project quota */
#define XFS_DQ_GROUP 0x0004 /* a group quota */
#define XFS_DQ_FLOCKED 0x0008 /* flush lock taken */
#define XFS_DQ_DIRTY 0x0010 /* dquot is dirty */
@@ -104,6 +104,8 @@ typedef struct xfs_dqblk {
#define XFS_DQ_INACTIVE 0x0040 /* dq off mplist & hashlist */
#define XFS_DQ_MARKER 0x0080 /* sentinel */
+#define XFS_DQ_ALLTYPES (XFS_DQ_USER|XFS_DQ_PROJ|XFS_DQ_GROUP)
+
/*
* In the worst case, when both user and group quotas are on,
* we can have a max of three dquots changing in a single transaction.
@@ -124,7 +126,7 @@ typedef struct xfs_dqblk {
typedef struct xfs_dq_logformat {
__uint16_t qlf_type; /* dquot log item type */
__uint16_t qlf_size; /* size of this item */
- xfs_dqid_t qlf_id; /* usr/grp id number : 32 bits */
+ xfs_dqid_t qlf_id; /* usr/grp/proj id : 32 bits */
__int64_t qlf_blkno; /* blkno of dquot buffer */
__int32_t qlf_len; /* len of dquot buffer */
__uint32_t qlf_boffset; /* off of dquot in buffer */
@@ -152,9 +154,9 @@ typedef struct xfs_qoff_logformat {
#define XFS_UQUOTA_ACCT 0x0001 /* user quota accounting ON */
#define XFS_UQUOTA_ENFD 0x0002 /* user quota limits enforced */
#define XFS_UQUOTA_CHKD 0x0004 /* quotacheck run on usr quotas */
-#define XFS_PQUOTA_ACCT 0x0008 /* (IRIX) project quota accounting ON */
-#define XFS_GQUOTA_ENFD 0x0010 /* group quota limits enforced */
-#define XFS_GQUOTA_CHKD 0x0020 /* quotacheck run on grp quotas */
+#define XFS_PQUOTA_ACCT 0x0008 /* project quota accounting ON */
+#define XFS_OQUOTA_ENFD 0x0010 /* other (grp/prj) quota limits enforced */
+#define XFS_OQUOTA_CHKD 0x0020 /* quotacheck run on other (grp/prj) quotas */
#define XFS_GQUOTA_ACCT 0x0040 /* group quota accounting ON */
/*
@@ -162,17 +164,22 @@ typedef struct xfs_qoff_logformat {
* are in the process of getting turned off. These flags are in m_qflags but
* never in sb_qflags.
*/
-#define XFS_UQUOTA_ACTIVE 0x0080 /* uquotas are being turned off */
-#define XFS_GQUOTA_ACTIVE 0x0100 /* gquotas are being turned off */
+#define XFS_UQUOTA_ACTIVE 0x0100 /* uquotas are being turned off */
+#define XFS_PQUOTA_ACTIVE 0x0200 /* pquotas are being turned off */
+#define XFS_GQUOTA_ACTIVE 0x0400 /* gquotas are being turned off */
/*
* Checking XFS_IS_*QUOTA_ON() while holding any inode lock guarantees
* quota will be not be switched off as long as that inode lock is held.
*/
#define XFS_IS_QUOTA_ON(mp) ((mp)->m_qflags & (XFS_UQUOTA_ACTIVE | \
- XFS_GQUOTA_ACTIVE))
+ XFS_GQUOTA_ACTIVE | \
+ XFS_PQUOTA_ACTIVE))
+#define XFS_IS_OQUOTA_ON(mp) ((mp)->m_qflags & (XFS_GQUOTA_ACTIVE | \
+ XFS_PQUOTA_ACTIVE))
#define XFS_IS_UQUOTA_ON(mp) ((mp)->m_qflags & XFS_UQUOTA_ACTIVE)
#define XFS_IS_GQUOTA_ON(mp) ((mp)->m_qflags & XFS_GQUOTA_ACTIVE)
+#define XFS_IS_PQUOTA_ON(mp) ((mp)->m_qflags & XFS_PQUOTA_ACTIVE)
/*
* Flags to tell various functions what to do. Not all of these are meaningful
@@ -182,7 +189,7 @@ typedef struct xfs_qoff_logformat {
#define XFS_QMOPT_DQLOCK 0x0000001 /* dqlock */
#define XFS_QMOPT_DQALLOC 0x0000002 /* alloc dquot ondisk if needed */
#define XFS_QMOPT_UQUOTA 0x0000004 /* user dquot requested */
-#define XFS_QMOPT_GQUOTA 0x0000008 /* group dquot requested */
+#define XFS_QMOPT_PQUOTA 0x0000008 /* project dquot requested */
#define XFS_QMOPT_FORCE_RES 0x0000010 /* ignore quota limits */
#define XFS_QMOPT_DQSUSER 0x0000020 /* don't cache super users dquot */
#define XFS_QMOPT_SBVERSION 0x0000040 /* change superblock version num */
@@ -192,6 +199,7 @@ typedef struct xfs_qoff_logformat {
#define XFS_QMOPT_DOWARN 0x0000400 /* increase warning cnt if necessary */
#define XFS_QMOPT_ILOCKED 0x0000800 /* inode is already locked (excl) */
#define XFS_QMOPT_DQREPAIR 0x0001000 /* repair dquot, if damaged. */
+#define XFS_QMOPT_GQUOTA 0x0002000 /* group dquot requested */
/*
* flags to xfs_trans_mod_dquot to indicate which field needs to be
@@ -231,7 +239,8 @@ typedef struct xfs_qoff_logformat {
#define XFS_TRANS_DQ_DELRTBCOUNT XFS_QMOPT_DELRTBCOUNT
-#define XFS_QMOPT_QUOTALL (XFS_QMOPT_UQUOTA|XFS_QMOPT_GQUOTA)
+#define XFS_QMOPT_QUOTALL \
+ (XFS_QMOPT_UQUOTA | XFS_QMOPT_PQUOTA | XFS_QMOPT_GQUOTA)
#define XFS_QMOPT_RESBLK_MASK (XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_RES_RTBLKS)
#ifdef __KERNEL__
@@ -246,21 +255,33 @@ typedef struct xfs_qoff_logformat {
*/
#define XFS_NOT_DQATTACHED(mp, ip) ((XFS_IS_UQUOTA_ON(mp) &&\
(ip)->i_udquot == NULL) || \
- (XFS_IS_GQUOTA_ON(mp) && \
+ (XFS_IS_OQUOTA_ON(mp) && \
(ip)->i_gdquot == NULL))
-#define XFS_QM_NEED_QUOTACHECK(mp) ((XFS_IS_UQUOTA_ON(mp) && \
- (mp->m_sb.sb_qflags & \
- XFS_UQUOTA_CHKD) == 0) || \
- (XFS_IS_GQUOTA_ON(mp) && \
- (mp->m_sb.sb_qflags & \
- XFS_GQUOTA_CHKD) == 0))
+#define XFS_QM_NEED_QUOTACHECK(mp) \
+ ((XFS_IS_UQUOTA_ON(mp) && \
+ (mp->m_sb.sb_qflags & XFS_UQUOTA_CHKD) == 0) || \
+ (XFS_IS_GQUOTA_ON(mp) && \
+ ((mp->m_sb.sb_qflags & XFS_OQUOTA_CHKD) == 0 || \
+ (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT))) || \
+ (XFS_IS_PQUOTA_ON(mp) && \
+ ((mp->m_sb.sb_qflags & XFS_OQUOTA_CHKD) == 0 || \
+ (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT))))
+
+#define XFS_MOUNT_QUOTA_SET1 (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
+ XFS_UQUOTA_CHKD|XFS_PQUOTA_ACCT|\
+ XFS_OQUOTA_ENFD|XFS_OQUOTA_CHKD)
+
+#define XFS_MOUNT_QUOTA_SET2 (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
+ XFS_UQUOTA_CHKD|XFS_GQUOTA_ACCT|\
+ XFS_OQUOTA_ENFD|XFS_OQUOTA_CHKD)
#define XFS_MOUNT_QUOTA_ALL (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
- XFS_UQUOTA_CHKD|XFS_GQUOTA_ACCT|\
- XFS_GQUOTA_ENFD|XFS_GQUOTA_CHKD)
+ XFS_UQUOTA_CHKD|XFS_PQUOTA_ACCT|\
+ XFS_OQUOTA_ENFD|XFS_OQUOTA_CHKD|\
+ XFS_GQUOTA_ACCT)
#define XFS_MOUNT_QUOTA_MASK (XFS_MOUNT_QUOTA_ALL | XFS_UQUOTA_ACTIVE | \
- XFS_GQUOTA_ACTIVE)
+ XFS_GQUOTA_ACTIVE | XFS_PQUOTA_ACTIVE)
/*
@@ -331,15 +352,8 @@ typedef struct xfs_dqtrxops {
#define XFS_TRANS_UNRESERVE_AND_MOD_DQUOTS(mp, tp) \
XFS_DQTRXOP_VOID(mp, tp, qo_unreserve_and_mod_dquots)
-#define XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, nblks) \
- XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, 0, \
- XFS_QMOPT_RES_REGBLKS)
-#define XFS_TRANS_RESERVE_BLKQUOTA_FORCE(mp, tp, ip, nblks) \
- XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, 0, \
- XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES)
-#define XFS_TRANS_UNRESERVE_BLKQUOTA(mp, tp, ip, nblks) \
- XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, -(nblks), 0, \
- XFS_QMOPT_RES_REGBLKS)
+#define XFS_TRANS_UNRESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, ninos, flags) \
+ XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, -(nblks), -(ninos), flags)
#define XFS_TRANS_RESERVE_QUOTA(mp, tp, ud, gd, nb, ni, f) \
XFS_TRANS_RESERVE_QUOTA_BYDQUOTS(mp, tp, ud, gd, nb, ni, \
f | XFS_QMOPT_RES_REGBLKS)
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c
index cb13f9a1d45..23b48ac1cb7 100644
--- a/fs/xfs/xfs_rename.c
+++ b/fs/xfs/xfs_rename.c
@@ -234,9 +234,6 @@ xfs_lock_for_rename(
return 0;
}
-
-int rename_which_error_return = 0;
-
/*
* xfs_rename
*/
@@ -316,7 +313,6 @@ xfs_rename(
&num_inodes);
if (error) {
- rename_which_error_return = __LINE__;
/*
* We have nothing locked, no inode references, and
* no transaction, so just get out.
@@ -332,7 +328,6 @@ xfs_rename(
*/
if (target_ip == NULL && (src_dp != target_dp) &&
target_dp->i_d.di_nlink >= XFS_MAXLINK) {
- rename_which_error_return = __LINE__;
error = XFS_ERROR(EMLINK);
xfs_rename_unlock4(inodes, XFS_ILOCK_SHARED);
goto rele_return;
@@ -359,7 +354,6 @@ xfs_rename(
XFS_TRANS_PERM_LOG_RES, XFS_RENAME_LOG_COUNT);
}
if (error) {
- rename_which_error_return = __LINE__;
xfs_trans_cancel(tp, 0);
goto rele_return;
}
@@ -369,7 +363,6 @@ xfs_rename(
*/
if ((error = XFS_QM_DQVOPRENAME(mp, inodes))) {
xfs_trans_cancel(tp, cancel_flags);
- rename_which_error_return = __LINE__;
goto rele_return;
}
@@ -413,7 +406,6 @@ xfs_rename(
if (spaceres == 0 &&
(error = XFS_DIR_CANENTER(mp, tp, target_dp, target_name,
target_namelen))) {
- rename_which_error_return = __LINE__;
goto error_return;
}
/*
@@ -425,11 +417,9 @@ xfs_rename(
target_namelen, src_ip->i_ino,
&first_block, &free_list, spaceres);
if (error == ENOSPC) {
- rename_which_error_return = __LINE__;
goto error_return;
}
if (error) {
- rename_which_error_return = __LINE__;
goto abort_return;
}
xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
@@ -437,7 +427,6 @@ xfs_rename(
if (new_parent && src_is_directory) {
error = xfs_bumplink(tp, target_dp);
if (error) {
- rename_which_error_return = __LINE__;
goto abort_return;
}
}
@@ -455,7 +444,6 @@ xfs_rename(
if (!(XFS_DIR_ISEMPTY(target_ip->i_mount, target_ip)) ||
(target_ip->i_d.di_nlink > 2)) {
error = XFS_ERROR(EEXIST);
- rename_which_error_return = __LINE__;
goto error_return;
}
}
@@ -473,7 +461,6 @@ xfs_rename(
target_namelen, src_ip->i_ino, &first_block,
&free_list, spaceres);
if (error) {
- rename_which_error_return = __LINE__;
goto abort_return;
}
xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
@@ -484,7 +471,6 @@ xfs_rename(
*/
error = xfs_droplink(tp, target_ip);
if (error) {
- rename_which_error_return = __LINE__;
goto abort_return;
}
target_ip_dropped = 1;
@@ -495,7 +481,6 @@ xfs_rename(
*/
error = xfs_droplink(tp, target_ip);
if (error) {
- rename_which_error_return = __LINE__;
goto abort_return;
}
}
@@ -519,7 +504,6 @@ xfs_rename(
&free_list, spaceres);
ASSERT(error != EEXIST);
if (error) {
- rename_which_error_return = __LINE__;
goto abort_return;
}
xfs_ichgtime(src_ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
@@ -550,7 +534,6 @@ xfs_rename(
*/
error = xfs_droplink(tp, src_dp);
if (error) {
- rename_which_error_return = __LINE__;
goto abort_return;
}
}
@@ -558,7 +541,6 @@ xfs_rename(
error = XFS_DIR_REMOVENAME(mp, tp, src_dp, src_name, src_namelen,
src_ip->i_ino, &first_block, &free_list, spaceres);
if (error) {
- rename_which_error_return = __LINE__;
goto abort_return;
}
xfs_ichgtime(src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 3db0e220077..06dfca531f7 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -332,25 +332,6 @@ undo_blocks:
/*
- * This is called to set the a callback to be called when the given
- * transaction is committed to disk. The transaction pointer and the
- * argument pointer will be passed to the callback routine.
- *
- * Only one callback can be associated with any single transaction.
- */
-void
-xfs_trans_callback(
- xfs_trans_t *tp,
- xfs_trans_callback_t callback,
- void *arg)
-{
- ASSERT(tp->t_callback == NULL);
- tp->t_callback = callback;
- tp->t_callarg = arg;
-}
-
-
-/*
* Record the indicated change to the given field for application
* to the file system's superblock when the transaction commits.
* For now, just store the change in the transaction structure.
@@ -551,7 +532,7 @@ xfs_trans_apply_sb_deltas(
*
* This is done efficiently with a single call to xfs_mod_incore_sb_batch().
*/
-void
+STATIC void
xfs_trans_unreserve_and_mod_sb(
xfs_trans_t *tp)
{
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index bd37ccb85e7..ec541d66fa2 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -987,8 +987,6 @@ xfs_trans_t *_xfs_trans_alloc(struct xfs_mount *, uint);
xfs_trans_t *xfs_trans_dup(xfs_trans_t *);
int xfs_trans_reserve(xfs_trans_t *, uint, uint, uint,
uint, uint);
-void xfs_trans_callback(xfs_trans_t *,
- void (*)(xfs_trans_t *, void *), void *);
void xfs_trans_mod_sb(xfs_trans_t *, uint, long);
struct xfs_buf *xfs_trans_get_buf(xfs_trans_t *, struct xfs_buftarg *, xfs_daddr_t,
int, uint);
@@ -1010,7 +1008,6 @@ int xfs_trans_iget(struct xfs_mount *, xfs_trans_t *,
xfs_ino_t , uint, uint, struct xfs_inode **);
void xfs_trans_ijoin(xfs_trans_t *, struct xfs_inode *, uint);
void xfs_trans_ihold(xfs_trans_t *, struct xfs_inode *);
-void xfs_trans_ihold_release(xfs_trans_t *, struct xfs_inode *);
void xfs_trans_log_buf(xfs_trans_t *, struct xfs_buf *, uint, uint);
void xfs_trans_log_inode(xfs_trans_t *, struct xfs_inode *, uint);
struct xfs_efi_log_item *xfs_trans_get_efi(xfs_trans_t *, uint);
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
index a9682b9510c..144da7a8546 100644
--- a/fs/xfs/xfs_trans_buf.c
+++ b/fs/xfs/xfs_trans_buf.c
@@ -976,6 +976,7 @@ xfs_trans_dquot_buf(
ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
ASSERT(type == XFS_BLI_UDQUOT_BUF ||
+ type == XFS_BLI_PDQUOT_BUF ||
type == XFS_BLI_GDQUOT_BUF);
bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c
index e2c3706f453..7e7631ca497 100644
--- a/fs/xfs/xfs_trans_inode.c
+++ b/fs/xfs/xfs_trans_inode.c
@@ -253,24 +253,6 @@ xfs_trans_ihold(
ip->i_itemp->ili_flags |= XFS_ILI_HOLD;
}
-/*
- * Cancel the previous inode hold request made on this inode
- * for this transaction.
- */
-/*ARGSUSED*/
-void
-xfs_trans_ihold_release(
- xfs_trans_t *tp,
- xfs_inode_t *ip)
-{
- ASSERT(ip->i_transp == tp);
- ASSERT(ip->i_itemp != NULL);
- ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
- ASSERT(ip->i_itemp->ili_flags & XFS_ILI_HOLD);
-
- ip->i_itemp->ili_flags &= ~XFS_ILI_HOLD;
-}
-
/*
* This is called to mark the fields indicated in fieldmask as needing
diff --git a/fs/xfs/xfs_types.h b/fs/xfs/xfs_types.h
index e4bf711e48f..16f5371ce10 100644
--- a/fs/xfs/xfs_types.h
+++ b/fs/xfs/xfs_types.h
@@ -55,7 +55,7 @@ typedef signed long long int __int64_t;
typedef unsigned long long int __uint64_t;
typedef enum { B_FALSE,B_TRUE } boolean_t;
-typedef __int64_t prid_t; /* project ID */
+typedef __uint32_t prid_t; /* project ID */
typedef __uint32_t inst_t; /* an instruction */
typedef __s64 xfs_off_t; /* <file offset> type */
diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c
index d1f8146a06e..11351f08d43 100644
--- a/fs/xfs/xfs_utils.c
+++ b/fs/xfs/xfs_utils.c
@@ -428,7 +428,7 @@ xfs_truncate_file(
if (ip->i_ino != mp->m_sb.sb_uquotino)
ASSERT(ip->i_udquot);
}
- if (XFS_IS_GQUOTA_ON(mp)) {
+ if (XFS_IS_OQUOTA_ON(mp)) {
if (ip->i_ino != mp->m_sb.sb_gquotino)
ASSERT(ip->i_gdquot);
}
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index b5373665010..42bcc021520 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -368,16 +368,6 @@ xfs_finish_flags(
}
/*
- * disallow mount attempts with (IRIX) project quota enabled
- */
- if (XFS_SB_VERSION_HASQUOTA(&mp->m_sb) &&
- (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT)) {
- cmn_err(CE_WARN,
- "XFS: cannot mount a filesystem with IRIX project quota enabled");
- return XFS_ERROR(ENOSYS);
- }
-
- /*
* check for shared mount.
*/
if (ap->flags & XFSMNT_SHARED) {
@@ -622,7 +612,34 @@ out:
return XFS_ERROR(error);
}
-#define REMOUNT_READONLY_FLAGS (SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT)
+STATIC int
+xfs_quiesce_fs(
+ xfs_mount_t *mp)
+{
+ int count = 0, pincount;
+
+ xfs_refcache_purge_mp(mp);
+ xfs_flush_buftarg(mp->m_ddev_targp, 0);
+ xfs_finish_reclaim_all(mp, 0);
+
+ /* This loop must run at least twice.
+ * The first instance of the loop will flush
+ * most meta data but that will generate more
+ * meta data (typically directory updates).
+ * Which then must be flushed and logged before
+ * we can write the unmount record.
+ */
+ do {
+ xfs_syncsub(mp, SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT, 0, NULL);
+ pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1);
+ if (!pincount) {
+ delay(50);
+ count++;
+ }
+ } while (count < 2);
+
+ return 0;
+}
STATIC int
xfs_mntupdate(
@@ -632,8 +649,7 @@ xfs_mntupdate(
{
struct vfs *vfsp = bhvtovfs(bdp);
xfs_mount_t *mp = XFS_BHVTOM(bdp);
- int pincount, error;
- int count = 0;
+ int error;
if (args->flags & XFSMNT_NOATIME)
mp->m_flags |= XFS_MOUNT_NOATIME;
@@ -645,25 +661,7 @@ xfs_mntupdate(
}
if (*flags & MS_RDONLY) {
- xfs_refcache_purge_mp(mp);
- xfs_flush_buftarg(mp->m_ddev_targp, 0);
- xfs_finish_reclaim_all(mp, 0);
-
- /* This loop must run at least twice.
- * The first instance of the loop will flush
- * most meta data but that will generate more
- * meta data (typically directory updates).
- * Which then must be flushed and logged before
- * we can write the unmount record.
- */
- do {
- VFS_SYNC(vfsp, REMOUNT_READONLY_FLAGS, NULL, error);
- pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1);
- if (!pincount) {
- delay(50);
- count++;
- }
- } while (count < 2);
+ xfs_quiesce_fs(mp);
/* Ok now write out an unmount record */
xfs_log_unmount_write(mp);
@@ -879,10 +877,12 @@ xfs_sync(
int flags,
cred_t *credp)
{
- xfs_mount_t *mp;
+ xfs_mount_t *mp = XFS_BHVTOM(bdp);
- mp = XFS_BHVTOM(bdp);
- return (xfs_syncsub(mp, flags, 0, NULL));
+ if (unlikely(flags == SYNC_QUIESCE))
+ return xfs_quiesce_fs(mp);
+ else
+ return xfs_syncsub(mp, flags, 0, NULL);
}
/*
@@ -1681,7 +1681,7 @@ suffix_strtoul(const char *cp, char **endp, unsigned int base)
return simple_strtoul(cp, endp, base) << shift_left_factor;
}
-int
+STATIC int
xfs_parseargs(
struct bhv_desc *bhv,
char *options,
@@ -1867,7 +1867,7 @@ printk("XFS: irixsgid is now a sysctl(2) variable, option is deprecated.\n");
return 0;
}
-int
+STATIC int
xfs_showargs(
struct bhv_desc *bhv,
struct seq_file *m)
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 25a526629b1..1377c868f3f 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -351,21 +351,28 @@ xfs_setattr(
* If the IDs do change before we take the ilock, we're covered
* because the i_*dquot fields will get updated anyway.
*/
- if (XFS_IS_QUOTA_ON(mp) && (mask & (XFS_AT_UID|XFS_AT_GID))) {
+ if (XFS_IS_QUOTA_ON(mp) &&
+ (mask & (XFS_AT_UID|XFS_AT_GID|XFS_AT_PROJID))) {
uint qflags = 0;
- if (mask & XFS_AT_UID) {
+ if ((mask & XFS_AT_UID) && XFS_IS_UQUOTA_ON(mp)) {
uid = vap->va_uid;
qflags |= XFS_QMOPT_UQUOTA;
} else {
uid = ip->i_d.di_uid;
}
- if (mask & XFS_AT_GID) {
+ if ((mask & XFS_AT_GID) && XFS_IS_GQUOTA_ON(mp)) {
gid = vap->va_gid;
qflags |= XFS_QMOPT_GQUOTA;
} else {
gid = ip->i_d.di_gid;
}
+ if ((mask & XFS_AT_PROJID) && XFS_IS_PQUOTA_ON(mp)) {
+ projid = vap->va_projid;
+ qflags |= XFS_QMOPT_PQUOTA;
+ } else {
+ projid = ip->i_d.di_projid;
+ }
/*
* We take a reference when we initialize udqp and gdqp,
* so it is important that we never blindly double trip on
@@ -373,7 +380,8 @@ xfs_setattr(
*/
ASSERT(udqp == NULL);
ASSERT(gdqp == NULL);
- code = XFS_QM_DQVOPALLOC(mp, ip, uid,gid, qflags, &udqp, &gdqp);
+ code = XFS_QM_DQVOPALLOC(mp, ip, uid, gid, projid, qflags,
+ &udqp, &gdqp);
if (code)
return (code);
}
@@ -499,8 +507,6 @@ xfs_setattr(
* that the group ID supplied to the chown() function
* shall be equal to either the group ID or one of the
* supplementary group IDs of the calling process.
- *
- * XXX: How does restricted_chown affect projid?
*/
if (restricted_chown &&
(iuid != uid || (igid != gid &&
@@ -510,10 +516,11 @@ xfs_setattr(
goto error_return;
}
/*
- * Do a quota reservation only if uid or gid is actually
+ * Do a quota reservation only if uid/projid/gid is actually
* going to change.
*/
if ((XFS_IS_UQUOTA_ON(mp) && iuid != uid) ||
+ (XFS_IS_PQUOTA_ON(mp) && iprojid != projid) ||
(XFS_IS_GQUOTA_ON(mp) && igid != gid)) {
ASSERT(tp);
code = XFS_QM_DQVOPCHOWNRESV(mp, tp, ip, udqp, gdqp,
@@ -774,6 +781,7 @@ xfs_setattr(
}
if (igid != gid) {
if (XFS_IS_GQUOTA_ON(mp)) {
+ ASSERT(!XFS_IS_PQUOTA_ON(mp));
ASSERT(mask & XFS_AT_GID);
ASSERT(gdqp);
olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip,
@@ -782,6 +790,13 @@ xfs_setattr(
ip->i_d.di_gid = gid;
}
if (iprojid != projid) {
+ if (XFS_IS_PQUOTA_ON(mp)) {
+ ASSERT(!XFS_IS_GQUOTA_ON(mp));
+ ASSERT(mask & XFS_AT_PROJID);
+ ASSERT(gdqp);
+ olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip,
+ &ip->i_gdquot, gdqp);
+ }
ip->i_d.di_projid = projid;
/*
* We may have to rev the inode as well as
@@ -843,6 +858,8 @@ xfs_setattr(
di_flags |= XFS_DIFLAG_NOATIME;
if (vap->va_xflags & XFS_XFLAG_NODUMP)
di_flags |= XFS_DIFLAG_NODUMP;
+ if (vap->va_xflags & XFS_XFLAG_PROJINHERIT)
+ di_flags |= XFS_DIFLAG_PROJINHERIT;
if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
if (vap->va_xflags & XFS_XFLAG_RTINHERIT)
di_flags |= XFS_DIFLAG_RTINHERIT;
@@ -1898,7 +1915,9 @@ xfs_create(
/* Return through std_return after this point. */
udqp = gdqp = NULL;
- if (vap->va_mask & XFS_AT_PROJID)
+ if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
+ prid = dp->i_d.di_projid;
+ else if (vap->va_mask & XFS_AT_PROJID)
prid = (xfs_prid_t)vap->va_projid;
else
prid = (xfs_prid_t)dfltprid;
@@ -1907,7 +1926,7 @@ xfs_create(
* Make sure that we have allocated dquot(s) on disk.
*/
error = XFS_QM_DQVOPALLOC(mp, dp,
- current_fsuid(credp), current_fsgid(credp),
+ current_fsuid(credp), current_fsgid(credp), prid,
XFS_QMOPT_QUOTALL|XFS_QMOPT_INHERIT, &udqp, &gdqp);
if (error)
goto std_return;
@@ -2604,17 +2623,7 @@ xfs_link(
if (src_vp->v_type == VDIR)
return XFS_ERROR(EPERM);
- /*
- * For now, manually find the XFS behavior descriptor for
- * the source vnode. If it doesn't exist then something
- * is wrong and we should just return an error.
- * Eventually we need to figure out how link is going to
- * work in the face of stacked vnodes.
- */
src_bdp = vn_bhv_lookup_unlocked(VN_BHV_HEAD(src_vp), &xfs_vnodeops);
- if (src_bdp == NULL) {
- return XFS_ERROR(EXDEV);
- }
sip = XFS_BHVTOI(src_bdp);
tdp = XFS_BHVTOI(target_dir_bdp);
mp = tdp->i_mount;
@@ -2681,6 +2690,17 @@ xfs_link(
goto error_return;
}
+ /*
+ * If we are using project inheritance, we only allow hard link
+ * creation in our tree when the project IDs are the same; else
+ * the tree quota mechanism could be circumvented.
+ */
+ if (unlikely((tdp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
+ (tdp->i_d.di_projid != sip->i_d.di_projid))) {
+ error = XFS_ERROR(EPERM);
+ goto error_return;
+ }
+
if (resblks == 0 &&
(error = XFS_DIR_CANENTER(mp, tp, tdp, target_name,
target_namelen)))
@@ -2803,7 +2823,9 @@ xfs_mkdir(
mp = dp->i_mount;
udqp = gdqp = NULL;
- if (vap->va_mask & XFS_AT_PROJID)
+ if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
+ prid = dp->i_d.di_projid;
+ else if (vap->va_mask & XFS_AT_PROJID)
prid = (xfs_prid_t)vap->va_projid;
else
prid = (xfs_prid_t)dfltprid;
@@ -2812,7 +2834,7 @@ xfs_mkdir(
* Make sure that we have allocated dquot(s) on disk.
*/
error = XFS_QM_DQVOPALLOC(mp, dp,
- current_fsuid(credp), current_fsgid(credp),
+ current_fsuid(credp), current_fsgid(credp), prid,
XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
if (error)
goto std_return;
@@ -3357,7 +3379,9 @@ xfs_symlink(
/* Return through std_return after this point. */
udqp = gdqp = NULL;
- if (vap->va_mask & XFS_AT_PROJID)
+ if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
+ prid = dp->i_d.di_projid;
+ else if (vap->va_mask & XFS_AT_PROJID)
prid = (xfs_prid_t)vap->va_projid;
else
prid = (xfs_prid_t)dfltprid;
@@ -3366,7 +3390,7 @@ xfs_symlink(
* Make sure that we have allocated dquot(s) on disk.
*/
error = XFS_QM_DQVOPALLOC(mp, dp,
- current_fsuid(credp), current_fsgid(credp),
+ current_fsuid(credp), current_fsgid(credp), prid,
XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
if (error)
goto std_return;
@@ -4028,7 +4052,7 @@ xfs_finish_reclaim_all(xfs_mount_t *mp, int noblock)
* errno on error
*
*/
-int
+STATIC int
xfs_alloc_file_space(
xfs_inode_t *ip,
xfs_off_t offset,
@@ -4151,9 +4175,8 @@ retry:
break;
}
xfs_ilock(ip, XFS_ILOCK_EXCL);
- error = XFS_TRANS_RESERVE_QUOTA_BYDQUOTS(mp, tp,
- ip->i_udquot, ip->i_gdquot, resblks, 0, rt ?
- XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS);
+ error = XFS_TRANS_RESERVE_QUOTA(mp, tp,
+ ip->i_udquot, ip->i_gdquot, resblks, 0, 0);
if (error)
goto error1;
@@ -4305,6 +4328,7 @@ xfs_free_file_space(
xfs_off_t len,
int attr_flags)
{
+ vnode_t *vp;
int committed;
int done;
xfs_off_t end_dmi_offset;
@@ -4325,9 +4349,11 @@ xfs_free_file_space(
xfs_trans_t *tp;
int need_iolock = 1;
- vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
+ vp = XFS_ITOV(ip);
mp = ip->i_mount;
+ vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
+
if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
return error;
@@ -4344,7 +4370,7 @@ xfs_free_file_space(
DM_EVENT_ENABLED(XFS_MTOVFS(mp), ip, DM_EVENT_WRITE)) {
if (end_dmi_offset > ip->i_d.di_size)
end_dmi_offset = ip->i_d.di_size;
- error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, XFS_ITOV(ip),
+ error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, vp,
offset, end_dmi_offset - offset,
AT_DELAY_FLAG(attr_flags), NULL);
if (error)
@@ -4363,7 +4389,14 @@ xfs_free_file_space(
ioffset = offset & ~(rounding - 1);
if (ilen & (rounding - 1))
ilen = (ilen + rounding) & ~(rounding - 1);
- xfs_inval_cached_pages(XFS_ITOV(ip), &(ip->i_iocore), ioffset, 0, 0);
+
+ if (VN_CACHED(vp) != 0) {
+ xfs_inval_cached_trace(&ip->i_iocore, ioffset, -1,
+ ctooff(offtoct(ioffset)), -1);
+ VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(ioffset)),
+ -1, FI_REMAPF_LOCKED);
+ }
+
/*
* Need to zero the stuff we're not freeing, on disk.
* If its a realtime file & can't use unwritten extents then we
diff --git a/include/asm-alpha/agp.h b/include/asm-alpha/agp.h
index c99dbbb5bcb..ef855a3bc0f 100644
--- a/include/asm-alpha/agp.h
+++ b/include/asm-alpha/agp.h
@@ -10,4 +10,14 @@
#define flush_agp_mappings()
#define flush_agp_cache() mb()
+/* Convert a physical address to an address suitable for the GART. */
+#define phys_to_gart(x) (x)
+#define gart_to_phys(x) (x)
+
+/* GATT allocation. Returns/accepts GATT kernel virtual address. */
+#define alloc_gatt_pages(order) \
+ ((char *)__get_free_pages(GFP_KERNEL, (order)))
+#define free_gatt_pages(table, order) \
+ free_pages((unsigned long)(table), (order))
+
#endif
diff --git a/include/asm-alpha/mmzone.h b/include/asm-alpha/mmzone.h
index 726c150dcbe..a011ef4cf3d 100644
--- a/include/asm-alpha/mmzone.h
+++ b/include/asm-alpha/mmzone.h
@@ -57,7 +57,6 @@ PLAT_NODE_DATA_LOCALNR(unsigned long p, int n)
* Given a kernel address, find the home node of the underlying memory.
*/
#define kvaddr_to_nid(kaddr) pa_to_nid(__pa(kaddr))
-#define node_mem_map(nid) (NODE_DATA(nid)->node_mem_map)
#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn)
#define local_mapnr(kvaddr) \
@@ -108,7 +107,7 @@ PLAT_NODE_DATA_LOCALNR(unsigned long p, int n)
#define pfn_to_page(pfn) \
({ \
unsigned long kaddr = (unsigned long)__va((pfn) << PAGE_SHIFT); \
- (node_mem_map(kvaddr_to_nid(kaddr)) + local_mapnr(kaddr)); \
+ (NODE_DATA(kvaddr_to_nid(kaddr))->node_mem_map + local_mapnr(kaddr)); \
})
#define page_to_pfn(page) \
diff --git a/include/asm-alpha/smp.h b/include/asm-alpha/smp.h
index cbc173ae45a..9950706abdf 100644
--- a/include/asm-alpha/smp.h
+++ b/include/asm-alpha/smp.h
@@ -43,7 +43,7 @@ extern struct cpuinfo_alpha cpu_data[NR_CPUS];
#define PROC_CHANGE_PENALTY 20
#define hard_smp_processor_id() __hard_smp_processor_id()
-#define smp_processor_id() (current_thread_info()->cpu)
+#define raw_smp_processor_id() (current_thread_info()->cpu)
extern cpumask_t cpu_present_mask;
extern cpumask_t cpu_online_map;
diff --git a/include/asm-arm/arch-aaec2000/aaec2000.h b/include/asm-arm/arch-aaec2000/aaec2000.h
new file mode 100644
index 00000000000..0e9b7e18af0
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/aaec2000.h
@@ -0,0 +1,151 @@
+/*
+ * linux/include/asm-arm/arch-aaec2000/aaec2000.h
+ *
+ * AAEC-2000 registers definition
+ *
+ * Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_AAEC2000_H
+#define __ASM_ARCH_AAEC2000_H
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#error You must include hardware.h not this file
+#endif /* __ASM_ARCH_HARDWARE_H */
+
+/* Interrupt controller */
+#define IRQ_BASE __REG(0x80000500)
+#define IRQ_INTSR __REG(0x80000500) /* Int Status Register */
+#define IRQ_INTRSR __REG(0x80000504) /* Int Raw (unmasked) Status */
+#define IRQ_INTENS __REG(0x80000508) /* Int Enable Set */
+#define IRQ_INTENC __REG(0x8000050c) /* Int Enable Clear */
+
+/* UART 1 */
+#define UART1_BASE __REG(0x80000600)
+#define UART1_DR __REG(0x80000600) /* Data/FIFO Register */
+#define UART1_LCR __REG(0x80000604) /* Link Control Register */
+#define UART1_BRCR __REG(0x80000608) /* Baud Rate Control Register */
+#define UART1_CR __REG(0x8000060c) /* Control Register */
+#define UART1_SR __REG(0x80000610) /* Status Register */
+#define UART1_INT __REG(0x80000614) /* Interrupt Status Register */
+#define UART1_INTM __REG(0x80000618) /* Interrupt Mask Register */
+#define UART1_INTRES __REG(0x8000061c) /* Int Result (masked status) Register */
+
+/* UART 2 */
+#define UART2_BASE __REG(0x80000700)
+#define UART2_DR __REG(0x80000700) /* Data/FIFO Register */
+#define UART2_LCR __REG(0x80000704) /* Link Control Register */
+#define UART2_BRCR __REG(0x80000708) /* Baud Rate Control Register */
+#define UART2_CR __REG(0x8000070c) /* Control Register */
+#define UART2_SR __REG(0x80000710) /* Status Register */
+#define UART2_INT __REG(0x80000714) /* Interrupt Status Register */
+#define UART2_INTM __REG(0x80000718) /* Interrupt Mask Register */
+#define UART2_INTRES __REG(0x8000071c) /* Int Result (masked status) Register */
+
+/* UART 3 */
+#define UART3_BASE __REG(0x80000800)
+#define UART3_DR __REG(0x80000800) /* Data/FIFO Register */
+#define UART3_LCR __REG(0x80000804) /* Link Control Register */
+#define UART3_BRCR __REG(0x80000808) /* Baud Rate Control Register */
+#define UART3_CR __REG(0x8000080c) /* Control Register */
+#define UART3_SR __REG(0x80000810) /* Status Register */
+#define UART3_INT __REG(0x80000814) /* Interrupt Status Register */
+#define UART3_INTM __REG(0x80000818) /* Interrupt Mask Register */
+#define UART3_INTRES __REG(0x8000081c) /* Int Result (masked status) Register */
+
+/* These are used in some places */
+#define _UART1_BASE __PREG(UART1_BASE)
+#define _UART2_BASE __PREG(UART2_BASE)
+#define _UART3_BASE __PREG(UART3_BASE)
+
+/* UART Registers Offsets */
+#define UART_DR 0x00
+#define UART_LCR 0x04
+#define UART_BRCR 0x08
+#define UART_CR 0x0c
+#define UART_SR 0x10
+#define UART_INT 0x14
+#define UART_INTM 0x18
+#define UART_INTRES 0x1c
+
+/* UART_LCR Bitmask */
+#define UART_LCR_BRK (1 << 0) /* Send Break */
+#define UART_LCR_PEN (1 << 1) /* Parity Enable */
+#define UART_LCR_EP (1 << 2) /* Even/Odd Parity */
+#define UART_LCR_S2 (1 << 3) /* One/Two Stop bits */
+#define UART_LCR_FIFO (1 << 4) /* FIFO Enable */
+#define UART_LCR_WL5 (0 << 5) /* Word Length - 5 bits */
+#define UART_LCR_WL6 (1 << 5) /* Word Length - 6 bits */
+#define UART_LCR_WL7 (1 << 6) /* Word Length - 7 bits */
+#define UART_LCR_WL8 (1 << 7) /* Word Length - 8 bits */
+
+/* UART_CR Bitmask */
+#define UART_CR_EN (1 << 0) /* UART Enable */
+#define UART_CR_SIR (1 << 1) /* IrDA SIR Enable */
+#define UART_CR_SIRLP (1 << 2) /* Low Power IrDA Enable */
+#define UART_CR_RXP (1 << 3) /* Receive Pin Polarity */
+#define UART_CR_TXP (1 << 4) /* Transmit Pin Polarity */
+#define UART_CR_MXP (1 << 5) /* Modem Pin Polarity */
+#define UART_CR_LOOP (1 << 6) /* Loopback Mode */
+
+/* UART_SR Bitmask */
+#define UART_SR_CTS (1 << 0) /* Clear To Send Status */
+#define UART_SR_DSR (1 << 1) /* Data Set Ready Status */
+#define UART_SR_DCD (1 << 2) /* Data Carrier Detect Status */
+#define UART_SR_TxBSY (1 << 3) /* Transmitter Busy Status */
+#define UART_SR_RxFE (1 << 4) /* Receive FIFO Empty Status */
+#define UART_SR_TxFF (1 << 5) /* Transmit FIFO Full Status */
+#define UART_SR_RxFF (1 << 6) /* Receive FIFO Full Status */
+#define UART_SR_TxFE (1 << 7) /* Transmit FIFO Empty Status */
+
+/* UART_INT Bitmask */
+#define UART_INT_RIS (1 << 0) /* Rx Interrupt */
+#define UART_INT_TIS (1 << 1) /* Tx Interrupt */
+#define UART_INT_MIS (1 << 2) /* Modem Interrupt */
+#define UART_INT_RTIS (1 << 3) /* Receive Timeout Interrupt */
+
+/* Timer 1 */
+#define TIMER1_BASE __REG(0x80000c00)
+#define TIMER1_LOAD __REG(0x80000c00) /* Timer 1 Load Register */
+#define TIMER1_VAL __REG(0x80000c04) /* Timer 1 Value Register */
+#define TIMER1_CTRL __REG(0x80000c08) /* Timer 1 Control Register */
+#define TIMER1_CLEAR __REG(0x80000c0c) /* Timer 1 Clear Register */
+
+/* Timer 2 */
+#define TIMER2_BASE __REG(0x80000d00)
+#define TIMER2_LOAD __REG(0x80000d00) /* Timer 2 Load Register */
+#define TIMER2_VAL __REG(0x80000d04) /* Timer 2 Value Register */
+#define TIMER2_CTRL __REG(0x80000d08) /* Timer 2 Control Register */
+#define TIMER2_CLEAR __REG(0x80000d0c) /* Timer 2 Clear Register */
+
+/* Timer 3 */
+#define TIMER3_BASE __REG(0x80000e00)
+#define TIMER3_LOAD __REG(0x80000e00) /* Timer 3 Load Register */
+#define TIMER3_VAL __REG(0x80000e04) /* Timer 3 Value Register */
+#define TIMER3_CTRL __REG(0x80000e08) /* Timer 3 Control Register */
+#define TIMER3_CLEAR __REG(0x80000e0c) /* Timer 3 Clear Register */
+
+/* Timer Control register bits */
+#define TIMER_CTRL_ENABLE (1 << 7) /* Enable (Start° Timer */
+#define TIMER_CTRL_PERIODIC (1 << 6) /* Periodic Running Mode */
+#define TIMER_CTRL_FREE_RUNNING (0 << 6) /* Normal Running Mode */
+#define TIMER_CTRL_CLKSEL_508K (1 << 3) /* 508KHz Clock select (Timer 1, 2) */
+#define TIMER_CTRL_CLKSEL_2K (0 << 3) /* 2KHz Clock Select (Timer 1, 2)*/
+
+/* Power and State Control */
+#define POWER_BASE __REG(0x80000400)
+#define POWER_PWRSR __REG(0x80000400) /* Power Status Register */
+#define POWER_PWRCNT __REG(0x80000404) /* Power/Clock control */
+#define POWER_HALT __REG(0x80000408) /* Power Idle Mode */
+#define POWER_STDBY __REG(0x8000040c) /* Power Standby Mode */
+#define POWER_BLEOI __REG(0x80000410) /* Battery Low End of Interrupt */
+#define POWER_MCEOI __REG(0x80000414) /* Media Changed EoI */
+#define POWER_TEOI __REG(0x80000418) /* Tick EoI */
+#define POWER_STFCLR __REG(0x8000041c) /* NbFlg, RSTFlg, PFFlg, CLDFlg Clear */
+#define POWER_CLKSET __REG(0x80000420) /* Clock Speed Control */
+
+#endif /* __ARM_ARCH_AAEC2000_H */
diff --git a/include/asm-arm/arch-aaec2000/debug-macro.S b/include/asm-arm/arch-aaec2000/debug-macro.S
new file mode 100644
index 00000000000..e4f1fa539a7
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/debug-macro.S
@@ -0,0 +1,36 @@
+/* linux/include/asm-arm/arch-aaec2000/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ * Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ * 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.
+ */
+
+ .macro addruart,rx
+ mrc p15, 0, \rx, c1, c0
+ tst \rx, #1 @ MMU enabled?
+ moveq \rx, #0x80000000 @ physical
+ movne \rx, #io_p2v(0x80000000) @ virtual
+ orr \rx, \rx, #0x00000800
+ .endm
+
+ .macro senduart,rd,rx
+ str \rd, [\rx, #0]
+ .endm
+
+ .macro busyuart,rd,rx
+1002: ldr \rd, [\rx, #0x10]
+ tst \rd, #(1 << 7)
+ beq 1002b
+ .endm
+
+ .macro waituart,rd,rx
+#if 0
+1001: ldr \rd, [\rx, #0x10]
+ tst \rd, #(1 << 5)
+ beq 1001b
+#endif
+ .endm
diff --git a/include/asm-arm/arch-aaec2000/dma.h b/include/asm-arm/arch-aaec2000/dma.h
new file mode 100644
index 00000000000..28c890b4a1d
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/dma.h
@@ -0,0 +1,17 @@
+/*
+ * linux/include/asm-arm/arch-aaec2000/dma.h
+ *
+ * Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+#define MAX_DMA_ADDRESS 0xffffffff
+#define MAX_DMA_CHANNELS 0
+
+#endif
diff --git a/include/asm-arm/arch-aaec2000/entry-macro.S b/include/asm-arm/arch-aaec2000/entry-macro.S
new file mode 100644
index 00000000000..df31313ab07
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/entry-macro.S
@@ -0,0 +1,33 @@
+/*
+ * linux/include/asm-arm/arch-aaec2000/entry-macro.S
+ *
+ * Low-level IRQ helper for aaec-2000 based platforms
+ *
+ * Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ * 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.
+ *
+ */
+
+ .macro disable_fiq
+ .endm
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+ mov r4, #0xf8000000
+ add r4, r4, #0x00000500
+ mov \base, r4
+ ldr \irqstat, [\base, #0]
+ cmp \irqstat, #0
+ bne 1001f
+ ldr \irqnr, =NR_IRQS+1
+ b 1003f
+1001: mov \irqnr, #0
+1002: ands \tmp, \irqstat, #1
+ mov \irqstat, \irqstat, LSR #1
+ add \irqnr, \irqnr, #1
+ beq 1002b
+ sub \irqnr, \irqnr, #1
+1003:
+ .endm
diff --git a/include/asm-arm/arch-aaec2000/hardware.h b/include/asm-arm/arch-aaec2000/hardware.h
new file mode 100644
index 00000000000..4c37219e030
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/hardware.h
@@ -0,0 +1,49 @@
+/*
+ * linux/include/asm-arm/arch-aaec2000/hardware.h
+ *
+ * Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <linux/config.h>
+
+/* The kernel is loaded at physical address 0xf8000000.
+ * We map the IO space a bit after
+ */
+#define PIO_APB_BASE 0x80000000
+#define VIO_APB_BASE 0xf8000000
+#define IO_APB_LENGTH 0x2000
+#define PIO_AHB_BASE 0x80002000
+#define VIO_AHB_BASE 0xf8002000
+#define IO_AHB_LENGTH 0x2000
+
+#define VIO_BASE VIO_APB_BASE
+#define PIO_BASE PIO_APB_BASE
+
+#define io_p2v(x) ( (x) - PIO_BASE + VIO_BASE )
+#define io_v2p(x) ( (x) + PIO_BASE - VIO_BASE )
+
+#ifndef __ASSEMBLY__
+
+#include <asm/types.h>
+
+/* FIXME: Is it needed to optimize this a la pxa ?? */
+#define __REG(x) (*((volatile u32 *)io_p2v(x)))
+#define __PREG(x) (io_v2p((u32)&(x)))
+
+#else /* __ASSEMBLY__ */
+
+#define __REG(x) io_p2v(x)
+#define __PREG(x) io_v2p(x)
+
+#endif
+
+#include "aaec2000.h"
+
+#endif /* __ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-aaec2000/io.h b/include/asm-arm/arch-aaec2000/io.h
new file mode 100644
index 00000000000..c58a8d10425
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/io.h
@@ -0,0 +1,19 @@
+/*
+ * linux/include/asm-arm/arch-aaec2000/io.h
+ *
+ * Copied from asm/arch/sa1100/io.h
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+/*
+ * We don't actually have real ISA nor PCI buses, but there is so many
+ * drivers out there that might just work if we fake them...
+ */
+#define __io(a) ((void __iomem *)(a))
+#define __mem_pci(a) (a)
+#define __mem_isa(a) (a)
+
+#endif
diff --git a/include/asm-arm/arch-aaec2000/irqs.h b/include/asm-arm/arch-aaec2000/irqs.h
new file mode 100644
index 00000000000..de252220e80
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/irqs.h
@@ -0,0 +1,46 @@
+/*
+ * linux/include/asm-arm/arch-aaec2000/irqs.h
+ *
+ * Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H
+
+
+#define INT_GPIOF0_FIQ 0 /* External GPIO Port F O Fast Interrupt Input */
+#define INT_BL_FIQ 1 /* Battery Low Fast Interrupt */
+#define INT_WE_FIQ 2 /* Watchdog Expired Fast Interrupt */
+#define INT_MV_FIQ 3 /* Media Changed Interrupt */
+#define INT_SC 4 /* Sound Codec Interrupt */
+#define INT_GPIO1 5 /* GPIO Port F Configurable Int 1 */
+#define INT_GPIO2 6 /* GPIO Port F Configurable Int 2 */
+#define INT_GPIO3 7 /* GPIO Port F Configurable Int 3 */
+#define INT_TMR1_OFL 8 /* Timer 1 Overflow Interrupt */
+#define INT_TMR2_OFL 9 /* Timer 2 Overflow Interrupt */
+#define INT_RTC_CM 10 /* RTC Compare Match Interrupt */
+#define INT_TICK 11 /* 64Hz Tick Interrupt */
+#define INT_UART1 12 /* UART1 Interrupt */
+#define INT_UART2 13 /* UART2 & Modem State Changed Interrupt */
+#define INT_LCD 14 /* LCD Interrupt */
+#define INT_SSI 15 /* SSI End of Transfer Interrupt */
+#define INT_UART3 16 /* UART3 Interrupt */
+#define INT_SCI 17 /* SCI Interrupt */
+#define INT_AAC 18 /* Advanced Audio Codec Interrupt */
+#define INT_MMC 19 /* MMC Interrupt */
+#define INT_USB 20 /* USB Interrupt */
+#define INT_DMA 21 /* DMA Interrupt */
+#define INT_TMR3_UOFL 22 /* Timer 3 Underflow Interrupt */
+#define INT_GPIO4 23 /* GPIO Port F Configurable Int 4 */
+#define INT_GPIO5 24 /* GPIO Port F Configurable Int 4 */
+#define INT_GPIO6 25 /* GPIO Port F Configurable Int 4 */
+#define INT_GPIO7 26 /* GPIO Port F Configurable Int 4 */
+#define INT_BMI 27 /* BMI Interrupt */
+
+#define NR_IRQS (INT_BMI + 1)
+
+#endif /* __ASM_ARCH_IRQS_H */
diff --git a/include/asm-arm/arch-aaec2000/memory.h b/include/asm-arm/arch-aaec2000/memory.h
new file mode 100644
index 00000000000..681b6a6171a
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/memory.h
@@ -0,0 +1,73 @@
+/*
+ * linux/include/asm-arm/arch-aaec2000/memory.h
+ *
+ * Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+#include <linux/config.h>
+
+#define PHYS_OFFSET (0xf0000000UL)
+
+#define __virt_to_bus(x) __virt_to_phys(x)
+#define __bus_to_virt(x) __phys_to_virt(x)
+
+#ifdef CONFIG_DISCONTIGMEM
+
+/*
+ * The nodes are the followings:
+ *
+ * node 0: 0xf000.0000 - 0xf3ff.ffff
+ * node 1: 0xf400.0000 - 0xf7ff.ffff
+ * node 2: 0xf800.0000 - 0xfbff.ffff
+ * node 3: 0xfc00.0000 - 0xffff.ffff
+ */
+
+/*
+ * Given a kernel address, find the home node of the underlying memory.
+ */
+#define KVADDR_TO_NID(addr) \
+ (((unsigned long)(addr) - PAGE_OFFSET) >> NODE_MAX_MEM_SHIFT)
+
+/*
+ * Given a page frame number, convert it to a node id.
+ */
+#define PFN_TO_NID(pfn) \
+ (((pfn) - PHYS_PFN_OFFSET) >> (NODE_MAX_MEM_SHIFT - PAGE_SHIFT))
+
+/*
+ * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
+ * and return the mem_map of that node.
+ */
+#define ADDR_TO_MAPBASE(kaddr) NODE_MEM_MAP(KVADDR_TO_NID(kaddr))
+
+/*
+ * Given a page frame number, find the owning node of the memory
+ * and return the mem_map of that node.
+ */
+#define PFN_TO_MAPBASE(pfn) NODE_MEM_MAP(PFN_TO_NID(pfn))
+
+/*
+ * Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory
+ * and returns the index corresponding to the appropriate page in the
+ * node's mem_map.
+ */
+#define LOCAL_MAP_NR(addr) \
+ (((unsigned long)(addr) & (NODE_MAX_MEM_SIZE - 1)) >> PAGE_SHIFT)
+
+#define NODE_MAX_MEM_SHIFT 26
+#define NODE_MAX_MEM_SIZE (1 << NODE_MAX_MEM_SHIFT)
+
+#else
+
+#define PFN_TO_NID(addr) (0)
+
+#endif /* CONFIG_DISCONTIGMEM */
+
+#endif /* __ASM_ARCH_MEMORY_H */
diff --git a/include/asm-arm/arch-aaec2000/param.h b/include/asm-arm/arch-aaec2000/param.h
new file mode 100644
index 00000000000..139936c2faf
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/param.h
@@ -0,0 +1,15 @@
+/*
+ * linux/include/asm-arm/arch-aaec2000/param.h
+ *
+ * Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_PARAM_H
+#define __ASM_ARCH_PARAM_H
+
+#endif /* __ASM_ARCH_PARAM_H */
+
diff --git a/include/asm-arm/arch-aaec2000/system.h b/include/asm-arm/arch-aaec2000/system.h
new file mode 100644
index 00000000000..08de97b407a
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/system.h
@@ -0,0 +1,24 @@
+/*
+ * linux/include/asm-arm/arch-aaed2000/system.h
+ *
+ * Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+static inline void arch_idle(void)
+{
+ cpu_do_idle();
+}
+
+static inline void arch_reset(char mode)
+{
+ cpu_reset(0);
+}
+
+#endif /* __ASM_ARCH_SYSTEM_H */
diff --git a/include/asm-arm/arch-aaec2000/timex.h b/include/asm-arm/arch-aaec2000/timex.h
new file mode 100644
index 00000000000..f5708b38fb7
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/timex.h
@@ -0,0 +1,18 @@
+/*
+ * linux/include/asm-arm/arch-aaec2000/timex.h
+ *
+ * AAEC-2000 Architecture timex specification
+ *
+ * Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_TIMEX_H
+#define __ASM_ARCH_TIMEX_H
+
+#define CLOCK_TICK_RATE 508000
+
+#endif /* __ASM_ARCH_TIMEX_H */
diff --git a/include/asm-arm/arch-aaec2000/uncompress.h b/include/asm-arm/arch-aaec2000/uncompress.h
new file mode 100644
index 00000000000..fff0c94b75c
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/uncompress.h
@@ -0,0 +1,47 @@
+/*
+ * linux/include/asm-arm/arch-aaec2000/uncompress.h
+ *
+ * Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_UNCOMPRESS_H
+#define __ASM_ARCH_UNCOMPRESS_H
+
+#include "hardware.h"
+
+#define UART(x) (*(volatile unsigned long *)(serial_port + (x)))
+
+static void putstr( const char *s )
+{
+ unsigned long serial_port;
+ do {
+ serial_port = _UART3_BASE;
+ if (UART(UART_CR) & UART_CR_EN) break;
+ serial_port = _UART1_BASE;
+ if (UART(UART_CR) & UART_CR_EN) break;
+ serial_port = _UART2_BASE;
+ if (UART(UART_CR) & UART_CR_EN) break;
+ return;
+ } while (0);
+
+ for (; *s; s++) {
+ /* wait for space in the UART's transmitter */
+ while ((UART(UART_SR) & UART_SR_TxFF));
+ /* send the character out. */
+ UART(UART_DR) = *s;
+ /* if a LF, also do CR... */
+ if (*s == 10) {
+ while ((UART(UART_SR) & UART_SR_TxFF));
+ UART(UART_DR) = 13;
+ }
+ }
+}
+
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
+
+#endif /* __ASM_ARCH_UNCOMPRESS_H */
diff --git a/include/asm-arm/arch-aaec2000/vmalloc.h b/include/asm-arm/arch-aaec2000/vmalloc.h
new file mode 100644
index 00000000000..ecb991e2e4f
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/vmalloc.h
@@ -0,0 +1,16 @@
+/*
+ * linux/include/asm-arm/arch-aaec2000/vmalloc.h
+ *
+ * Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_VMALLOC_H
+#define __ASM_ARCH_VMALLOC_H
+
+#define VMALLOC_END (PAGE_OFFSET + 0x10000000)
+
+#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/include/asm-arm/arch-imx/imx-regs.h b/include/asm-arm/arch-imx/imx-regs.h
index f32c203952c..93b840e8fa6 100644
--- a/include/asm-arm/arch-imx/imx-regs.h
+++ b/include/asm-arm/arch-imx/imx-regs.h
@@ -228,6 +228,30 @@
#define PD31_BIN_SPI2_TXD ( GPIO_PORTD | GPIO_BIN | 31 )
/*
+ * PWM controller
+ */
+#define PWMC __REG(IMX_PWM_BASE + 0x00) /* PWM Control Register */
+#define PWMS __REG(IMX_PWM_BASE + 0x04) /* PWM Sample Register */
+#define PWMP __REG(IMX_PWM_BASE + 0x08) /* PWM Period Register */
+#define PWMCNT __REG(IMX_PWM_BASE + 0x0C) /* PWM Counter Register */
+
+#define PWMC_HCTR (0x01<<18) /* Halfword FIFO Data Swapping */
+#define PWMC_BCTR (0x01<<17) /* Byte FIFO Data Swapping */
+#define PWMC_SWR (0x01<<16) /* Software Reset */
+#define PWMC_CLKSRC (0x01<<15) /* Clock Source */
+#define PWMC_PRESCALER(x) (((x-1) & 0x7F) << 8) /* PRESCALER */
+#define PWMC_IRQ (0x01<< 7) /* Interrupt Request */
+#define PWMC_IRQEN (0x01<< 6) /* Interrupt Request Enable */
+#define PWMC_FIFOAV (0x01<< 5) /* FIFO Available */
+#define PWMC_EN (0x01<< 4) /* Enables/Disables the PWM */
+#define PWMC_REPEAT(x) (((x) & 0x03) << 2) /* Sample Repeats */
+#define PWMC_CLKSEL(x) (((x) & 0x03) << 0) /* Clock Selection */
+
+#define PWMS_SAMPLE(x) ((x) & 0xFFFF) /* Contains a two-sample word */
+#define PWMP_PERIOD(x) ((x) & 0xFFFF) /* Represents the PWM's period */
+#define PWMC_COUNTER(x) ((x) & 0xFFFF) /* Represents the current count value */
+
+/*
* DMA Controller
*/
#define DCR __REG(IMX_DMAC_BASE +0x00) /* DMA Control Register */
diff --git a/include/asm-arm/arch-integrator/platform.h b/include/asm-arm/arch-integrator/platform.h
index bd364f5a99b..96ad3d2a66d 100644
--- a/include/asm-arm/arch-integrator/platform.h
+++ b/include/asm-arm/arch-integrator/platform.h
@@ -293,7 +293,11 @@
#define INTEGRATOR_DBG_SWITCH (INTEGRATOR_DBG_BASE + INTEGRATOR_DBG_SWITCH_OFFSET)
+#if defined(CONFIG_ARCH_INTEGRATOR_AP)
#define INTEGRATOR_GPIO_BASE 0x1B000000 /* GPIO */
+#elif defined(CONFIG_ARCH_INTEGRATOR_CP)
+#define INTEGRATOR_GPIO_BASE 0xC9000000 /* GPIO */
+#endif
/* ------------------------------------------------------------------------
* KMI keyboard/mouse definitions
diff --git a/include/asm-arm/arch-integrator/smp.h b/include/asm-arm/arch-integrator/smp.h
new file mode 100644
index 00000000000..0ec7093f7c3
--- /dev/null
+++ b/include/asm-arm/arch-integrator/smp.h
@@ -0,0 +1,19 @@
+#ifndef ASMARM_ARCH_SMP_H
+#define ASMARM_ARCH_SMP_H
+
+#include <linux/config.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/io.h>
+
+#define hard_smp_processor_id() \
+ ({ \
+ unsigned int cpunum; \
+ __asm__("mrc p15, 0, %0, c0, c0, 5" \
+ : "=r" (cpunum)); \
+ cpunum &= 0x0F; \
+ })
+
+extern void secondary_scan_irqs(void);
+
+#endif
diff --git a/include/asm-arm/arch-ixp2000/gpio.h b/include/asm-arm/arch-ixp2000/gpio.h
index 84634af5cc6..03cbbe1fd9d 100644
--- a/include/asm-arm/arch-ixp2000/gpio.h
+++ b/include/asm-arm/arch-ixp2000/gpio.h
@@ -1,5 +1,5 @@
/*
- * include/asm-arm/arch-ixp2000/ixp2000-gpio.h
+ * include/asm-arm/arch-ixp2000/gpio.h
*
* Copyright (C) 2002 Intel Corporation.
*
@@ -16,26 +16,18 @@
* Use this instead of directly setting the GPIO registers.
* GPIOs may also be used as GPIOs (e.g. for emulating i2c/smb)
*/
-#ifndef _ASM_ARCH_IXP2000_GPIO_H_
-#define _ASM_ARCH_IXP2000_GPIO_H_
+#ifndef __ASM_ARCH_GPIO_H
+#define __ASM_ARCH_GPIO_H
#ifndef __ASSEMBLY__
-#define GPIO_OUT 0x0
-#define GPIO_IN 0x80
+
+#define GPIO_IN 0
+#define GPIO_OUT 1
#define IXP2000_GPIO_LOW 0
#define IXP2000_GPIO_HIGH 1
-#define GPIO_NO_EDGES 0
-#define GPIO_FALLING_EDGE 1
-#define GPIO_RISING_EDGE 2
-#define GPIO_BOTH_EDGES 3
-#define GPIO_LEVEL_LOW 4
-#define GPIO_LEVEL_HIGH 8
-
-extern void set_GPIO_IRQ_edge(int gpio_nr, int edge);
-extern void set_GPIO_IRQ_level(int gpio_nr, int level);
-extern void gpio_line_config(int line, int style);
+extern void gpio_line_config(int line, int direction);
static inline int gpio_line_get(int line)
{
@@ -45,11 +37,12 @@ static inline int gpio_line_get(int line)
static inline void gpio_line_set(int line, int value)
{
if (value == IXP2000_GPIO_HIGH) {
- ixp_reg_write(IXP2000_GPIO_POSR, BIT(line));
- } else if (value == IXP2000_GPIO_LOW)
- ixp_reg_write(IXP2000_GPIO_POCR, BIT(line));
+ ixp2000_reg_write(IXP2000_GPIO_POSR, 1 << line);
+ } else if (value == IXP2000_GPIO_LOW) {
+ ixp2000_reg_write(IXP2000_GPIO_POCR, 1 << line);
+ }
}
#endif /* !__ASSEMBLY__ */
-#endif /* ASM_ARCH_IXP2000_GPIO_H_ */
+#endif /* ASM_ARCH_IXP2000_GPIO_H_ */
diff --git a/include/asm-arm/arch-ixp2000/io.h b/include/asm-arm/arch-ixp2000/io.h
index a8e3c2daefd..3241cd6f077 100644
--- a/include/asm-arm/arch-ixp2000/io.h
+++ b/include/asm-arm/arch-ixp2000/io.h
@@ -17,18 +17,23 @@
#define IO_SPACE_LIMIT 0xffffffff
#define __mem_pci(a) (a)
-#define ___io(p) ((void __iomem *)((p)+IXP2000_PCI_IO_VIRT_BASE))
/*
- * The IXP2400 before revision B0 asserts byte lanes for PCI I/O
+ * The A? revisions of the IXP2000s assert byte lanes for PCI I/O
* transactions the other way round (MEM transactions don't have this
- * issue), so we need to override the standard functions. B0 and later
- * have a bit that can be set to 1 to get the 'proper' behavior, but
- * since that isn't available on the A? revisions we just keep doing
- * things manually.
+ * issue), so if we want to support those models, we need to override
+ * the standard I/O functions.
+ *
+ * B0 and later have a bit that can be set to 1 to get the proper
+ * behavior for I/O transactions, which then allows us to use the
+ * standard I/O functions. This is what we do if the user does not
+ * explicitly ask for support for pre-B0.
*/
-#define alignb(addr) (void __iomem *)((unsigned long)addr ^ 3)
-#define alignw(addr) (void __iomem *)((unsigned long)addr ^ 2)
+#ifdef CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO
+#define ___io(p) ((void __iomem *)((p)+IXP2000_PCI_IO_VIRT_BASE))
+
+#define alignb(addr) (void __iomem *)((unsigned long)(addr) ^ 3)
+#define alignw(addr) (void __iomem *)((unsigned long)(addr) ^ 2)
#define outb(v,p) __raw_writeb((v),alignb(___io(p)))
#define outw(v,p) __raw_writew((v),alignw(___io(p)))
@@ -48,6 +53,81 @@
#define insw(p,d,l) __raw_readsw(alignw(___io(p)),d,l)
#define insl(p,d,l) __raw_readsl(___io(p),d,l)
+#define __is_io_address(p) ((((unsigned long)(p)) & ~(IXP2000_PCI_IO_SIZE - 1)) == IXP2000_PCI_IO_VIRT_BASE)
+
+#define ioread8(p) \
+ ({ \
+ unsigned int __v; \
+ \
+ if (__is_io_address(p)) { \
+ __v = __raw_readb(alignb(p)); \
+ } else { \
+ __v = __raw_readb(p); \
+ } \
+ \
+ __v; \
+ }) \
+
+#define ioread16(p) \
+ ({ \
+ unsigned int __v; \
+ \
+ if (__is_io_address(p)) { \
+ __v = __raw_readw(alignw(p)); \
+ } else { \
+ __v = le16_to_cpu(__raw_readw(p)); \
+ } \
+ \
+ __v; \
+ })
+
+#define ioread32(p) \
+ ({ \
+ unsigned int __v; \
+ \
+ if (__is_io_address(p)) { \
+ __v = __raw_readl(p); \
+ } else { \
+ __v = le32_to_cpu(__raw_readl(p)); \
+ } \
+ \
+ __v; \
+ })
+
+#define iowrite8(v,p) \
+ ({ \
+ if (__is_io_address(p)) { \
+ __raw_writeb((v), alignb(p)); \
+ } else { \
+ __raw_writeb((v), p); \
+ } \
+ })
+
+#define iowrite16(v,p) \
+ ({ \
+ if (__is_io_address(p)) { \
+ __raw_writew((v), alignw(p)); \
+ } else { \
+ __raw_writew(cpu_to_le16(v), p); \
+ } \
+ })
+
+#define iowrite32(v,p) \
+ ({ \
+ if (__is_io_address(p)) { \
+ __raw_writel((v), p); \
+ } else { \
+ __raw_writel(cpu_to_le32(v), p); \
+ } \
+ })
+
+#define ioport_map(port, nr) ___io(port)
+
+#define ioport_unmap(addr)
+#else
+#define __io(p) ((void __iomem *)((p)+IXP2000_PCI_IO_VIRT_BASE))
+#endif
+
#ifdef CONFIG_ARCH_IXDP2X01
/*
@@ -75,8 +155,8 @@ static inline void insw(u32 ptr, void *buf, int length)
* Is this cycle meant for the CS8900?
*/
if ((machine_is_ixdp2401() || machine_is_ixdp2801()) &&
- ((port >= IXDP2X01_CS8900_VIRT_BASE) &&
- (port <= IXDP2X01_CS8900_VIRT_END))) {
+ (((u32)port >= (u32)IXDP2X01_CS8900_VIRT_BASE) &&
+ ((u32)port <= (u32)IXDP2X01_CS8900_VIRT_END))) {
u8 *buf8 = (u8*)buf;
register u32 tmp32;
@@ -100,8 +180,8 @@ static inline void outsw(u32 ptr, void *buf, int length)
* Is this cycle meant for the CS8900?
*/
if ((machine_is_ixdp2401() || machine_is_ixdp2801()) &&
- ((port >= IXDP2X01_CS8900_VIRT_BASE) &&
- (port <= IXDP2X01_CS8900_VIRT_END))) {
+ (((u32)port >= (u32)IXDP2X01_CS8900_VIRT_BASE) &&
+ ((u32)port <= (u32)IXDP2X01_CS8900_VIRT_END))) {
register u32 tmp32;
u8 *buf8 = (u8*)buf;
do {
@@ -124,8 +204,8 @@ static inline u16 inw(u32 ptr)
* Is this cycle meant for the CS8900?
*/
if ((machine_is_ixdp2401() || machine_is_ixdp2801()) &&
- ((port >= IXDP2X01_CS8900_VIRT_BASE) &&
- (port <= IXDP2X01_CS8900_VIRT_END))) {
+ (((u32)port >= (u32)IXDP2X01_CS8900_VIRT_BASE) &&
+ ((u32)port <= (u32)IXDP2X01_CS8900_VIRT_END))) {
return (u16)(*port);
}
@@ -137,8 +217,8 @@ static inline void outw(u16 value, u32 ptr)
register volatile u32 *port = (volatile u32 *)ptr;
if ((machine_is_ixdp2401() || machine_is_ixdp2801()) &&
- ((port >= IXDP2X01_CS8900_VIRT_BASE) &&
- (port <= IXDP2X01_CS8900_VIRT_END))) {
+ (((u32)port >= (u32)IXDP2X01_CS8900_VIRT_BASE) &&
+ ((u32)port <= (u32)IXDP2X01_CS8900_VIRT_END))) {
*port = value;
return;
}
diff --git a/include/asm-arm/arch-ixp2000/ixp2000-regs.h b/include/asm-arm/arch-ixp2000/ixp2000-regs.h
index 6c56708d0ff..5eb47d4bfbf 100644
--- a/include/asm-arm/arch-ixp2000/ixp2000-regs.h
+++ b/include/asm-arm/arch-ixp2000/ixp2000-regs.h
@@ -241,7 +241,7 @@
#define PCI_CONTROL_BE_DEI (1 << 21) /* Big Endian Data Enable In */
#define PCI_CONTROL_BE_BEO (1 << 20) /* Big Endian Byte Enable Out */
#define PCI_CONTROL_BE_BEI (1 << 19) /* Big Endian Byte Enable In */
-#define PCI_CONTROL_PNR (1 << 17) /* PCI Not Reset bit */
+#define PCI_CONTROL_IEE (1 << 17) /* I/O cycle Endian swap Enable */
#define IXP2000_PCI_RST_REL (1 << 2)
#define CFG_RST_DIR (*IXP2000_PCI_CONTROL & IXP2000_PCICNTL_PCF)
@@ -363,6 +363,7 @@
#define IXP2000_MIN_REV_MASK 0x0000000F
#define IXP2000_PROD_ID_MASK 0xFFFFFFFF
+#define IXP2000_PRODUCT_ID GLOBAL_REG(0x00)
#define IXP2000_MISC_CONTROL GLOBAL_REG(0x04)
#define IXP2000_MSF_CLK_CNTRL GLOBAL_REG(0x08)
#define IXP2000_RESET0 GLOBAL_REG(0x0c)
diff --git a/include/asm-arm/arch-ixp2000/platform.h b/include/asm-arm/arch-ixp2000/platform.h
index 901bba6d02b..52ded516ea5 100644
--- a/include/asm-arm/arch-ixp2000/platform.h
+++ b/include/asm-arm/arch-ixp2000/platform.h
@@ -138,30 +138,10 @@ struct ixp2000_flash_data {
unsigned long (*bank_setup)(unsigned long);
};
-/*
- * GPIO helper functions
- */
-#define GPIO_IN 0
-#define GPIO_OUT 1
-
-extern void gpio_line_config(int line, int style);
-
-static inline int gpio_line_get(int line)
-{
- return (((*IXP2000_GPIO_PLR) >> line) & 1);
-}
-
-static inline void gpio_line_set(int line, int value)
-{
- if (value)
- ixp2000_reg_write(IXP2000_GPIO_POSR, (1 << line));
- else
- ixp2000_reg_write(IXP2000_GPIO_POCR, (1 << line));
-}
-
struct ixp2000_i2c_pins {
unsigned long sda_pin;
unsigned long scl_pin;
};
+
#endif /* !__ASSEMBLY__ */
diff --git a/include/asm-arm/arch-ixp4xx/debug-macro.S b/include/asm-arm/arch-ixp4xx/debug-macro.S
index 4499ae8e4b4..45a6c6cc29d 100644
--- a/include/asm-arm/arch-ixp4xx/debug-macro.S
+++ b/include/asm-arm/arch-ixp4xx/debug-macro.S
@@ -14,6 +14,7 @@
mrc p15, 0, \rx, c1, c0
tst \rx, #1 @ MMU enabled?
moveq \rx, #0xc8000000
+ orrne \rx, \rx, #0x00b00000
movne \rx, #0xff000000
add \rx,\rx,#3 @ Uart regs are at off set of 3 if
@ byte writes used - Big Endian.
diff --git a/include/asm-arm/arch-ixp4xx/ixp4xx-regs.h b/include/asm-arm/arch-ixp4xx/ixp4xx-regs.h
index 8eeb1db6309..004696a95bd 100644
--- a/include/asm-arm/arch-ixp4xx/ixp4xx-regs.h
+++ b/include/asm-arm/arch-ixp4xx/ixp4xx-regs.h
@@ -69,6 +69,16 @@
#define IXP4XX_PERIPHERAL_BASE_VIRT (0xFFBF2000)
#define IXP4XX_PERIPHERAL_REGION_SIZE (0x0000C000)
+/*
+ * Debug UART
+ *
+ * This is basically a remap of UART1 into a region that is section
+ * aligned so that it * can be used with the low-level debug code.
+ */
+#define IXP4XX_DEBUG_UART_BASE_PHYS (0xC8000000)
+#define IXP4XX_DEBUG_UART_BASE_VIRT (0xffb00000)
+#define IXP4XX_DEBUG_UART_REGION_SIZE (0x00001000)
+
#define IXP4XX_EXP_CS0_OFFSET 0x00
#define IXP4XX_EXP_CS1_OFFSET 0x04
#define IXP4XX_EXP_CS2_OFFSET 0x08
diff --git a/include/asm-arm/arch-omap/tps65010.h b/include/asm-arm/arch-omap/tps65010.h
index 0f97bb2e8fc..b9aa2b3a390 100644
--- a/include/asm-arm/arch-omap/tps65010.h
+++ b/include/asm-arm/arch-omap/tps65010.h
@@ -30,6 +30,66 @@
/*
* ----------------------------------------------------------------------------
+ * Registers, all 8 bits
+ * ----------------------------------------------------------------------------
+ */
+
+#define TPS_CHGSTATUS 0x01
+# define TPS_CHG_USB (1 << 7)
+# define TPS_CHG_AC (1 << 6)
+# define TPS_CHG_THERM (1 << 5)
+# define TPS_CHG_TERM (1 << 4)
+# define TPS_CHG_TAPER_TMO (1 << 3)
+# define TPS_CHG_CHG_TMO (1 << 2)
+# define TPS_CHG_PRECHG_TMO (1 << 1)
+# define TPS_CHG_TEMP_ERR (1 << 0)
+#define TPS_REGSTATUS 0x02
+# define TPS_REG_ONOFF (1 << 7)
+# define TPS_REG_COVER (1 << 6)
+# define TPS_REG_UVLO (1 << 5)
+# define TPS_REG_NO_CHG (1 << 4) /* tps65013 */
+# define TPS_REG_PG_LD02 (1 << 3)
+# define TPS_REG_PG_LD01 (1 << 2)
+# define TPS_REG_PG_MAIN (1 << 1)
+# define TPS_REG_PG_CORE (1 << 0)
+#define TPS_MASK1 0x03
+#define TPS_MASK2 0x04
+#define TPS_ACKINT1 0x05
+#define TPS_ACKINT2 0x06
+#define TPS_CHGCONFIG 0x07
+# define TPS_CHARGE_POR (1 << 7) /* 65010/65012 */
+# define TPS65013_AUA (1 << 7) /* 65011/65013 */
+# define TPS_CHARGE_RESET (1 << 6)
+# define TPS_CHARGE_FAST (1 << 5)
+# define TPS_CHARGE_CURRENT (3 << 3)
+# define TPS_VBUS_500MA (1 << 2)
+# define TPS_VBUS_CHARGING (1 << 1)
+# define TPS_CHARGE_ENABLE (1 << 0)
+#define TPS_LED1_ON 0x08
+#define TPS_LED1_PER 0x09
+#define TPS_LED2_ON 0x0a
+#define TPS_LED2_PER 0x0b
+#define TPS_VDCDC1 0x0c
+# define TPS_ENABLE_LP (1 << 3)
+#define TPS_VDCDC2 0x0d
+#define TPS_VREGS1 0x0e
+# define TPS_LDO2_ENABLE (1 << 7)
+# define TPS_LDO2_OFF (1 << 6)
+# define TPS_VLDO2_3_0V (3 << 4)
+# define TPS_VLDO2_2_75V (2 << 4)
+# define TPS_VLDO2_2_5V (1 << 4)
+# define TPS_VLDO2_1_8V (0 << 4)
+# define TPS_LDO1_ENABLE (1 << 3)
+# define TPS_LDO1_OFF (1 << 2)
+# define TPS_VLDO1_3_0V (3 << 0)
+# define TPS_VLDO1_2_75V (2 << 0)
+# define TPS_VLDO1_2_5V (1 << 0)
+# define TPS_VLDO1_ADJ (0 << 0)
+#define TPS_MASK3 0x0f
+#define TPS_DEFGPIO 0x10
+
+/*
+ * ----------------------------------------------------------------------------
* Macros used by exported functions
* ----------------------------------------------------------------------------
*/
@@ -71,10 +131,26 @@ extern int tps65010_set_gpio_out_value(unsigned gpio, unsigned value);
*/
extern int tps65010_set_led(unsigned led, unsigned mode);
+/* tps65010_set_vib parameter:
+ * value: ON or OFF
+ */
+extern int tps65010_set_vib(unsigned value);
+
/* tps65010_set_low_pwr parameter:
* mode: ON or OFF
*/
extern int tps65010_set_low_pwr(unsigned mode);
+/* tps65010_config_vregs1 parameter:
+ * value to be written to VREGS1 register
+ * Note: The complete register is written, set all bits you need
+ */
+extern int tps65010_config_vregs1(unsigned value);
+
+/* tps65013_set_low_pwr parameter:
+ * mode: ON or OFF
+ */
+extern int tps65013_set_low_pwr(unsigned mode);
+
#endif /* __ASM_ARCH_TPS65010_H */
diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
index 39741d3c9a3..b5e54a9e9fa 100644
--- a/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/include/asm-arm/arch-pxa/pxa-regs.h
@@ -1296,6 +1296,7 @@
#define GPIO111_MMCDAT3 111 /* MMC DAT3 (PXA27x) */
#define GPIO111_MMCCS1 111 /* MMC Chip Select 1 (PXA27x) */
#define GPIO112_MMCCMD 112 /* MMC CMD (PXA27x) */
+#define GPIO113_I2S_SYSCLK 113 /* I2S System Clock (PXA27x) */
#define GPIO113_AC97_RESET_N 113 /* AC97 NRESET on (PXA27x) */
/* GPIO alternate function mode & direction */
@@ -1428,6 +1429,7 @@
#define GPIO111_MMCDAT3_MD (111 | GPIO_ALT_FN_1_OUT)
#define GPIO110_MMCCS1_MD (111 | GPIO_ALT_FN_1_OUT)
#define GPIO112_MMCCMD_MD (112 | GPIO_ALT_FN_1_OUT)
+#define GPIO113_I2S_SYSCLK_MD (113 | GPIO_ALT_FN_1_OUT)
#define GPIO113_AC97_RESET_N_MD (113 | GPIO_ALT_FN_2_OUT)
#define GPIO117_I2CSCL_MD (117 | GPIO_ALT_FN_1_OUT)
#define GPIO118_I2CSDA_MD (118 | GPIO_ALT_FN_1_IN)
diff --git a/include/asm-arm/arch-s3c2410/regs-nand.h b/include/asm-arm/arch-s3c2410/regs-nand.h
index c443ac83469..7cff235e667 100644
--- a/include/asm-arm/arch-s3c2410/regs-nand.h
+++ b/include/asm-arm/arch-s3c2410/regs-nand.h
@@ -1,16 +1,17 @@
/* linux/include/asm-arm/arch-s3c2410/regs-nand.h
*
- * Copyright (c) 2004 Simtec Electronics <linux@simtec.co.uk>
+ * Copyright (c) 2004,2005 Simtec Electronics <linux@simtec.co.uk>
* http://www.simtec.co.uk/products/SWLINUX/
*
* 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.
*
- * S3C2410 clock register definitions
+ * S3C2410 NAND register definitions
*
* Changelog:
* 18-Aug-2004 BJD Copied file from 2.4 and updated
+ * 01-May-2005 BJD Added definitions for s3c2440 controller
*/
#ifndef __ASM_ARM_REGS_NAND
@@ -26,6 +27,22 @@
#define S3C2410_NFSTAT S3C2410_NFREG(0x10)
#define S3C2410_NFECC S3C2410_NFREG(0x14)
+#define S3C2440_NFCONT S3C2410_NFREG(0x04)
+#define S3C2440_NFCMD S3C2410_NFREG(0x08)
+#define S3C2440_NFADDR S3C2410_NFREG(0x0C)
+#define S3C2440_NFDATA S3C2410_NFREG(0x10)
+#define S3C2440_NFECCD0 S3C2410_NFREG(0x14)
+#define S3C2440_NFECCD1 S3C2410_NFREG(0x18)
+#define S3C2440_NFECCD S3C2410_NFREG(0x1C)
+#define S3C2440_NFSTAT S3C2410_NFREG(0x20)
+#define S3C2440_NFESTAT0 S3C2410_NFREG(0x24)
+#define S3C2440_NFESTAT1 S3C2410_NFREG(0x28)
+#define S3C2440_NFMECC0 S3C2410_NFREG(0x2C)
+#define S3C2440_NFMECC1 S3C2410_NFREG(0x30)
+#define S3C2440_NFSECC S3C2410_NFREG(0x34)
+#define S3C2440_NFSBLK S3C2410_NFREG(0x38)
+#define S3C2440_NFEBLK S3C2410_NFREG(0x3C)
+
#define S3C2410_NFCONF_EN (1<<15)
#define S3C2410_NFCONF_512BYTE (1<<14)
#define S3C2410_NFCONF_4STEP (1<<13)
@@ -37,7 +54,28 @@
#define S3C2410_NFSTAT_BUSY (1<<0)
-/* think ECC can only be 8bit read? */
+#define S3C2440_NFCONF_BUSWIDTH_8 (0<<0)
+#define S3C2440_NFCONF_BUSWIDTH_16 (1<<0)
+#define S3C2440_NFCONF_ADVFLASH (1<<3)
+#define S3C2440_NFCONF_TACLS(x) ((x)<<12)
+#define S3C2440_NFCONF_TWRPH0(x) ((x)<<8)
+#define S3C2440_NFCONF_TWRPH1(x) ((x)<<4)
+
+#define S3C2440_NFCONT_LOCKTIGHT (1<<13)
+#define S3C2440_NFCONT_SOFTLOCK (1<<12)
+#define S3C2440_NFCONT_ILLEGALACC_EN (1<<10)
+#define S3C2440_NFCONT_RNBINT_EN (1<<9)
+#define S3C2440_NFCONT_RN_FALLING (1<<8)
+#define S3C2440_NFCONT_SPARE_ECCLOCK (1<<6)
+#define S3C2440_NFCONT_MAIN_ECCLOCK (1<<5)
+#define S3C2440_NFCONT_INITECC (1<<4)
+#define S3C2440_NFCONT_nFCE (1<<1)
+#define S3C2440_NFCONT_ENABLE (1<<0)
+
+#define S3C2440_NFSTAT_READY (1<<0)
+#define S3C2440_NFSTAT_nCE (1<<1)
+#define S3C2440_NFSTAT_RnB_CHANGE (1<<2)
+#define S3C2440_NFSTAT_ILLEGAL_ACCESS (1<<3)
#endif /* __ASM_ARM_REGS_NAND */
diff --git a/include/asm-arm/arch-versatile/hardware.h b/include/asm-arm/arch-versatile/hardware.h
index d5fb4a251e7..41c1bee342a 100644
--- a/include/asm-arm/arch-versatile/hardware.h
+++ b/include/asm-arm/arch-versatile/hardware.h
@@ -25,19 +25,26 @@
#include <asm/sizes.h>
#include <asm/arch/platform.h>
-// FIXME = PCI settings need to be fixed!!!!!
-
/*
- * Similar to above, but for PCI addresses (memory, IO, Config and the
- * V3 chip itself). WARNING: this has to mirror definitions in platform.h
+ * PCI space virtual addresses
*/
-#define PCI_MEMORY_VADDR 0xe8000000
-#define PCI_CONFIG_VADDR 0xec000000
-#define PCI_V3_VADDR 0xed000000
-#define PCI_IO_VADDR 0xee000000
+#define VERSATILE_PCI_VIRT_BASE 0xe8000000
+#define VERSATILE_PCI_CFG_VIRT_BASE 0xe9000000
+
+#if 0
+#define VERSATILE_PCI_VIRT_MEM_BASE0 0xf4000000
+#define VERSATILE_PCI_VIRT_MEM_BASE1 0xf5000000
+#define VERSATILE_PCI_VIRT_MEM_BASE2 0xf6000000
+
+#define PCIO_BASE VERSATILE_PCI_VIRT_MEM_BASE0
+#define PCIMEM_BASE VERSATILE_PCI_VIRT_MEM_BASE1
+#endif
+
+/* CIK guesswork */
+#define PCIBIOS_MIN_IO 0x44000000
+#define PCIBIOS_MIN_MEM 0x50000000
-#define PCIO_BASE PCI_IO_VADDR
-#define PCIMEM_BASE PCI_MEMORY_VADDR
+#define pcibios_assign_all_busses() 1
/* macro to get at IO space when running virtually */
#define IO_ADDRESS(x) (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000)
diff --git a/include/asm-arm/arch-versatile/io.h b/include/asm-arm/arch-versatile/io.h
index dbb7158788f..9f895bf6149 100644
--- a/include/asm-arm/arch-versatile/io.h
+++ b/include/asm-arm/arch-versatile/io.h
@@ -20,7 +20,7 @@
#ifndef __ASM_ARM_ARCH_IO_H
#define __ASM_ARM_ARCH_IO_H
-#define IO_SPACE_LIMIT 0xffff
+#define IO_SPACE_LIMIT 0xffffffff
#define __io(a) ((void __iomem *)(a))
#define __mem_pci(a) (a)
diff --git a/include/asm-arm/arch-versatile/platform.h b/include/asm-arm/arch-versatile/platform.h
index 2598d1f0854..cbdd9fb9633 100644
--- a/include/asm-arm/arch-versatile/platform.h
+++ b/include/asm-arm/arch-versatile/platform.h
@@ -76,7 +76,7 @@
#define VERSATILE_SYS_NVFLAGSSET_OFFSET 0x38
#define VERSATILE_SYS_NVFLAGSCLR_OFFSET 0x3C
#define VERSATILE_SYS_RESETCTL_OFFSET 0x40
-#define VERSATILE_SYS_PICCTL_OFFSET 0x44
+#define VERSATILE_SYS_PCICTL_OFFSET 0x44
#define VERSATILE_SYS_MCI_OFFSET 0x48
#define VERSATILE_SYS_FLASH_OFFSET 0x4C
#define VERSATILE_SYS_CLCD_OFFSET 0x50
@@ -114,7 +114,7 @@
#define VERSATILE_SYS_NVFLAGSSET (VERSATILE_SYS_BASE + VERSATILE_SYS_NVFLAGSSET_OFFSET)
#define VERSATILE_SYS_NVFLAGSCLR (VERSATILE_SYS_BASE + VERSATILE_SYS_NVFLAGSCLR_OFFSET)
#define VERSATILE_SYS_RESETCTL (VERSATILE_SYS_BASE + VERSATILE_SYS_RESETCTL_OFFSET)
-#define VERSATILE_SYS_PICCTL (VERSATILE_SYS_BASE + VERSATILE_SYS_PICCTL_OFFSET)
+#define VERSATILE_SYS_PCICTL (VERSATILE_SYS_BASE + VERSATILE_SYS_PCICTL_OFFSET)
#define VERSATILE_SYS_MCI (VERSATILE_SYS_BASE + VERSATILE_SYS_MCI_OFFSET)
#define VERSATILE_SYS_FLASH (VERSATILE_SYS_BASE + VERSATILE_SYS_FLASH_OFFSET)
#define VERSATILE_SYS_CLCD (VERSATILE_SYS_BASE + VERSATILE_SYS_CLCD_OFFSET)
@@ -225,7 +225,20 @@
#define VERSATILE_SSMC_BASE 0x20000000 /* SSMC */
#define VERSATILE_IB2_BASE 0x24000000 /* IB2 module */
#define VERSATILE_MBX_BASE 0x40000000 /* MBX */
+
+/* PCI space */
#define VERSATILE_PCI_BASE 0x41000000 /* PCI Interface */
+#define VERSATILE_PCI_CFG_BASE 0x42000000
+#define VERSATILE_PCI_MEM_BASE0 0x44000000
+#define VERSATILE_PCI_MEM_BASE1 0x50000000
+#define VERSATILE_PCI_MEM_BASE2 0x60000000
+/* Sizes of above maps */
+#define VERSATILE_PCI_BASE_SIZE 0x01000000
+#define VERSATILE_PCI_CFG_BASE_SIZE 0x02000000
+#define VERSATILE_PCI_MEM_BASE0_SIZE 0x0c000000 /* 32Mb */
+#define VERSATILE_PCI_MEM_BASE1_SIZE 0x10000000 /* 256Mb */
+#define VERSATILE_PCI_MEM_BASE2_SIZE 0x10000000 /* 256Mb */
+
#define VERSATILE_SDRAM67_BASE 0x70000000 /* SDRAM banks 6 and 7 */
#define VERSATILE_LT_BASE 0x80000000 /* Logic Tile expansion */
@@ -498,11 +511,17 @@
/*
* IB2 Versatile/AB expansion board definitions
*/
-#define VERSATILE_IB2_CAMERA_BANK 0x24000000
-#define VERSATILE_IB2_KBD_DATAREG 0x25000000
-#define VERSATILE_IB2_IER 0x26000000 /* for VICINTSOURCE27 */
-#define VERSATILE_IB2_CTRL 0x27000000
-#define VERSATILE_IB2_STAT 0x27000004
+#define VERSATILE_IB2_CAMERA_BANK VERSATILE_IB2_BASE
+#define VERSATILE_IB2_KBD_DATAREG (VERSATILE_IB2_BASE + 0x01000000)
+
+/* VICINTSOURCE27 */
+#define VERSATILE_IB2_INT_BASE (VERSATILE_IB2_BASE + 0x02000000)
+#define VERSATILE_IB2_IER (VERSATILE_IB2_INT_BASE + 0)
+#define VERSATILE_IB2_ISR (VERSATILE_IB2_INT_BASE + 4)
+
+#define VERSATILE_IB2_CTL_BASE (VERSATILE_IB2_BASE + 0x03000000)
+#define VERSATILE_IB2_CTRL (VERSATILE_IB2_CTL_BASE + 0)
+#define VERSATILE_IB2_STAT (VERSATILE_IB2_CTL_BASE + 4)
#endif
#endif
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h
index 09ffeed507c..035cdcff43d 100644
--- a/include/asm-arm/cacheflush.h
+++ b/include/asm-arm/cacheflush.h
@@ -16,6 +16,9 @@
#include <asm/mman.h>
#include <asm/glue.h>
+#include <asm/shmparam.h>
+
+#define CACHE_COLOUR(vaddr) ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
/*
* Cache Model
diff --git a/include/asm-arm/elf.h b/include/asm-arm/elf.h
index cbceacbe5af..a1696ba238d 100644
--- a/include/asm-arm/elf.h
+++ b/include/asm-arm/elf.h
@@ -38,9 +38,9 @@ typedef struct user_fp elf_fpregset_t;
*/
#define ELF_CLASS ELFCLASS32
#ifdef __ARMEB__
-#define ELF_DATA ELFDATA2MSB;
+#define ELF_DATA ELFDATA2MSB
#else
-#define ELF_DATA ELFDATA2LSB;
+#define ELF_DATA ELFDATA2LSB
#endif
#define ELF_ARCH EM_ARM
diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h
index 658ffa384fd..cc4b5f5dbfc 100644
--- a/include/asm-arm/io.h
+++ b/include/asm-arm/io.h
@@ -273,6 +273,35 @@ extern void __iounmap(void __iomem *addr);
#endif
/*
+ * io{read,write}{8,16,32} macros
+ */
+#ifndef ioread8
+#define ioread8(p) ({ unsigned int __v = __raw_readb(p); __v; })
+#define ioread16(p) ({ unsigned int __v = le16_to_cpu(__raw_readw(p)); __v; })
+#define ioread32(p) ({ unsigned int __v = le32_to_cpu(__raw_readl(p)); __v; })
+
+#define iowrite8(v,p) __raw_writeb(v, p)
+#define iowrite16(v,p) __raw_writew(cpu_to_le16(v), p)
+#define iowrite32(v,p) __raw_writel(cpu_to_le32(v), p)
+
+#define ioread8_rep(p,d,c) __raw_readsb(p,d,c)
+#define ioread16_rep(p,d,c) __raw_readsw(p,d,c)
+#define ioread32_rep(p,d,c) __raw_readsl(p,d,c)
+
+#define iowrite8_rep(p,s,c) __raw_writesb(p,s,c)
+#define iowrite16_rep(p,s,c) __raw_writesw(p,s,c)
+#define iowrite32_rep(p,s,c) __raw_writesl(p,s,c)
+
+extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
+extern void ioport_unmap(void __iomem *addr);
+#endif
+
+struct pci_dev;
+
+extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen);
+extern void pci_iounmap(struct pci_dev *dev, void __iomem *addr);
+
+/*
* can the hardware map this into one segment or not, given no other
* constraints.
*/
diff --git a/include/asm-arm/mach/time.h b/include/asm-arm/mach/time.h
index 5cf4fd659fd..047980ad18d 100644
--- a/include/asm-arm/mach/time.h
+++ b/include/asm-arm/mach/time.h
@@ -39,8 +39,29 @@ struct sys_timer {
void (*suspend)(void);
void (*resume)(void);
unsigned long (*offset)(void);
+
+#ifdef CONFIG_NO_IDLE_HZ
+ struct dyn_tick_timer *dyn_tick;
+#endif
+};
+
+#ifdef CONFIG_NO_IDLE_HZ
+
+#define DYN_TICK_SKIPPING (1 << 2)
+#define DYN_TICK_ENABLED (1 << 1)
+#define DYN_TICK_SUITABLE (1 << 0)
+
+struct dyn_tick_timer {
+ unsigned int state; /* Current state */
+ int (*enable)(void); /* Enables dynamic tick */
+ int (*disable)(void); /* Disables dynamic tick */
+ void (*reprogram)(unsigned long); /* Reprograms the timer */
+ int (*handler)(int, void *, struct pt_regs *);
};
+void timer_dyn_reprogram(void);
+#endif
+
extern struct sys_timer *system_timer;
extern void timer_tick(struct pt_regs *);
diff --git a/include/asm-arm/page.h b/include/asm-arm/page.h
index 4ca3a8e9348..019c45d7573 100644
--- a/include/asm-arm/page.h
+++ b/include/asm-arm/page.h
@@ -114,19 +114,8 @@ extern void __cpu_copy_user_page(void *to, const void *from,
unsigned long user);
#endif
-#define clear_user_page(addr,vaddr,pg) \
- do { \
- preempt_disable(); \
- __cpu_clear_user_page(addr, vaddr); \
- preempt_enable(); \
- } while (0)
-
-#define copy_user_page(to,from,vaddr,pg) \
- do { \
- preempt_disable(); \
- __cpu_copy_user_page(to, from, vaddr); \
- preempt_enable(); \
- } while (0)
+#define clear_user_page(addr,vaddr,pg) __cpu_clear_user_page(addr, vaddr)
+#define copy_user_page(to,from,vaddr,pg) __cpu_copy_user_page(to, from, vaddr)
#define clear_page(page) memzero((void *)(page), PAGE_SIZE)
extern void copy_page(void *to, const void *from);
@@ -171,6 +160,9 @@ typedef unsigned long pgprot_t;
#endif /* STRICT_MM_TYPECHECKS */
+/* the upper-most page table pointer */
+extern pmd_t *top_pmd;
+
/* Pure 2^n version of get_order */
static inline int get_order(unsigned long size)
{
diff --git a/include/asm-arm/pgalloc.h b/include/asm-arm/pgalloc.h
index e814f8144f8..bc18ff40518 100644
--- a/include/asm-arm/pgalloc.h
+++ b/include/asm-arm/pgalloc.h
@@ -89,6 +89,13 @@ static inline void pte_free(struct page *pte)
__free_page(pte);
}
+static inline void __pmd_populate(pmd_t *pmdp, unsigned long pmdval)
+{
+ pmdp[0] = __pmd(pmdval);
+ pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
+ flush_pmd_entry(pmdp);
+}
+
/*
* Populate the pmdp entry with a pointer to the pte. This pmd is part
* of the mm address space.
@@ -99,32 +106,19 @@ static inline void
pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep)
{
unsigned long pte_ptr = (unsigned long)ptep;
- unsigned long pmdval;
-
- BUG_ON(mm != &init_mm);
/*
* The pmd must be loaded with the physical
* address of the PTE table
*/
pte_ptr -= PTRS_PER_PTE * sizeof(void *);
- pmdval = __pa(pte_ptr) | _PAGE_KERNEL_TABLE;
- pmdp[0] = __pmd(pmdval);
- pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
- flush_pmd_entry(pmdp);
+ __pmd_populate(pmdp, __pa(pte_ptr) | _PAGE_KERNEL_TABLE);
}
static inline void
pmd_populate(struct mm_struct *mm, pmd_t *pmdp, struct page *ptep)
{
- unsigned long pmdval;
-
- BUG_ON(mm == &init_mm);
-
- pmdval = page_to_pfn(ptep) << PAGE_SHIFT | _PAGE_USER_TABLE;
- pmdp[0] = __pmd(pmdval);
- pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
- flush_pmd_entry(pmdp);
+ __pmd_populate(pmdp, page_to_pfn(ptep) << PAGE_SHIFT | _PAGE_USER_TABLE);
}
#endif
diff --git a/include/asm-arm/signal.h b/include/asm-arm/signal.h
index 46e69ae395a..760f6e65af0 100644
--- a/include/asm-arm/signal.h
+++ b/include/asm-arm/signal.h
@@ -114,6 +114,7 @@ typedef unsigned long sigset_t;
#define SIGSTKSZ 8192
#ifdef __KERNEL__
+#define SA_TIMER 0x40000000
#define SA_IRQNOMASK 0x08000000
#endif
diff --git a/include/asm-arm/smp.h b/include/asm-arm/smp.h
index f21fd8f6bcd..6c6c60adbba 100644
--- a/include/asm-arm/smp.h
+++ b/include/asm-arm/smp.h
@@ -21,7 +21,7 @@
# error "<asm-arm/smp.h> included in non-SMP build"
#endif
-#define smp_processor_id() (current_thread_info()->cpu)
+#define raw_smp_processor_id() (current_thread_info()->cpu)
extern cpumask_t cpu_present_mask;
#define cpu_possible_map cpu_present_mask
@@ -55,4 +55,18 @@ extern void smp_cross_call(cpumask_t callmap);
*/
extern int boot_secondary(unsigned int cpu, struct task_struct *);
+/*
+ * Perform platform specific initialisation of the specified CPU.
+ */
+extern void platform_secondary_init(unsigned int cpu);
+
+/*
+ * Initial data for bringing up a secondary CPU.
+ */
+struct secondary_data {
+ unsigned long pgdir;
+ void *stack;
+};
+extern struct secondary_data secondary_data;
+
#endif /* ifndef __ASM_ARM_SMP_H */
diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h
index b13a8da4847..3d0d2860b6d 100644
--- a/include/asm-arm/system.h
+++ b/include/asm-arm/system.h
@@ -104,6 +104,7 @@ extern void show_pte(struct mm_struct *mm, unsigned long addr);
extern void __show_regs(struct pt_regs *);
extern int cpu_architecture(void);
+extern void cpu_init(void);
#define set_cr(x) \
__asm__ __volatile__( \
@@ -144,34 +145,12 @@ extern unsigned int user_debug;
#define set_wmb(var, value) do { var = value; wmb(); } while (0)
#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
-#ifdef CONFIG_SMP
/*
- * Define our own context switch locking. This allows us to enable
- * interrupts over the context switch, otherwise we end up with high
- * interrupt latency. The real problem area is switch_mm() which may
- * do a full cache flush.
+ * switch_mm() may do a full cache flush over the context switch,
+ * so enable interrupts over the context switch to avoid high
+ * latency.
*/
-#define prepare_arch_switch(rq,next) \
-do { \
- spin_lock(&(next)->switch_lock); \
- spin_unlock_irq(&(rq)->lock); \
-} while (0)
-
-#define finish_arch_switch(rq,prev) \
- spin_unlock(&(prev)->switch_lock)
-
-#define task_running(rq,p) \
- ((rq)->curr == (p) || spin_is_locked(&(p)->switch_lock))
-#else
-/*
- * Our UP-case is more simple, but we assume knowledge of how
- * spin_unlock_irq() and friends are implemented. This avoids
- * us needlessly decrementing and incrementing the preempt count.
- */
-#define prepare_arch_switch(rq,next) local_irq_enable()
-#define finish_arch_switch(rq,prev) spin_unlock(&(rq)->lock)
-#define task_running(rq,p) ((rq)->curr == (p))
-#endif
+#define __ARCH_WANT_INTERRUPTS_ON_CTXSW
/*
* switch_to(prev, next) should switch from task `prev' to `next'
@@ -307,7 +286,7 @@ do { \
({ \
unsigned long flags; \
local_save_flags(flags); \
- flags & PSR_I_BIT; \
+ (int)(flags & PSR_I_BIT); \
})
#ifdef CONFIG_SMP
diff --git a/include/asm-arm/thread_info.h b/include/asm-arm/thread_info.h
index 66c585c50cf..8252a4cd860 100644
--- a/include/asm-arm/thread_info.h
+++ b/include/asm-arm/thread_info.h
@@ -49,7 +49,7 @@ struct cpu_context_save {
*/
struct thread_info {
unsigned long flags; /* low level flags */
- __s32 preempt_count; /* 0 => preemptable, <0 => bug */
+ int preempt_count; /* 0 => preemptable, <0 => bug */
mm_segment_t addr_limit; /* address limit */
struct task_struct *task; /* main task structure */
struct exec_domain *exec_domain; /* execution domain */
diff --git a/include/asm-arm26/elf.h b/include/asm-arm26/elf.h
index 8b149474db2..5a47fdb3015 100644
--- a/include/asm-arm26/elf.h
+++ b/include/asm-arm26/elf.h
@@ -36,7 +36,7 @@ typedef struct { void *null; } elf_fpregset_t;
* These are used to set parameters in the core dumps.
*/
#define ELF_CLASS ELFCLASS32
-#define ELF_DATA ELFDATA2LSB;
+#define ELF_DATA ELFDATA2LSB
#define ELF_ARCH EM_ARM
#define USE_ELF_CORE_DUMP
diff --git a/include/asm-arm26/signal.h b/include/asm-arm26/signal.h
index dedb2928030..37ad2535559 100644
--- a/include/asm-arm26/signal.h
+++ b/include/asm-arm26/signal.h
@@ -166,9 +166,6 @@ typedef struct sigaltstack {
#include <asm/sigcontext.h>
#define sigmask(sig) (1UL << ((sig) - 1))
-//FIXME!!!
-//#define HAVE_ARCH_GET_SIGNAL_TO_DELIVER
-
#endif
diff --git a/include/asm-arm26/thread_info.h b/include/asm-arm26/thread_info.h
index 50f41b50268..aff3e5699c6 100644
--- a/include/asm-arm26/thread_info.h
+++ b/include/asm-arm26/thread_info.h
@@ -44,7 +44,7 @@ struct cpu_context_save {
*/
struct thread_info {
unsigned long flags; /* low level flags */
- __s32 preempt_count; /* 0 => preemptable, <0 => bug */
+ int preempt_count; /* 0 => preemptable, <0 => bug */
mm_segment_t addr_limit; /* address limit */
struct task_struct *task; /* main task structure */
struct exec_domain *exec_domain; /* execution domain */
diff --git a/include/asm-cris/thread_info.h b/include/asm-cris/thread_info.h
index 53193feb082..5ba4b7865cc 100644
--- a/include/asm-cris/thread_info.h
+++ b/include/asm-cris/thread_info.h
@@ -31,7 +31,7 @@ struct thread_info {
struct exec_domain *exec_domain; /* execution domain */
unsigned long flags; /* low level flags */
__u32 cpu; /* current CPU */
- __s32 preempt_count; /* 0 => preemptable, <0 => BUG */
+ int preempt_count; /* 0 => preemptable, <0 => BUG */
mm_segment_t addr_limit; /* thread address space:
0-0xBFFFFFFF for user-thead
diff --git a/include/asm-frv/thread_info.h b/include/asm-frv/thread_info.h
index b80a97f50af..c8cba7836f0 100644
--- a/include/asm-frv/thread_info.h
+++ b/include/asm-frv/thread_info.h
@@ -33,7 +33,7 @@ struct thread_info {
unsigned long flags; /* low level flags */
unsigned long status; /* thread-synchronous flags */
__u32 cpu; /* current CPU */
- __s32 preempt_count; /* 0 => preemptable, <0 => BUG */
+ int preempt_count; /* 0 => preemptable, <0 => BUG */
mm_segment_t addr_limit; /* thread address space:
0-0xBFFFFFFF for user-thead
diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h
index 3b709b84934..9044aeb3782 100644
--- a/include/asm-generic/percpu.h
+++ b/include/asm-generic/percpu.h
@@ -29,7 +29,7 @@ do { \
#define DEFINE_PER_CPU(type, name) \
__typeof__(type) per_cpu__##name
-#define per_cpu(var, cpu) (*((void)cpu, &per_cpu__##var))
+#define per_cpu(var, cpu) (*((void)(cpu), &per_cpu__##var))
#define __get_cpu_var(var) per_cpu__##var
#endif /* SMP */
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 1f4ec7b7027..f4059356517 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -125,6 +125,9 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addres
#ifndef __HAVE_ARCH_PAGE_TEST_AND_CLEAR_DIRTY
#define page_test_and_clear_dirty(page) (0)
+#define pte_maybe_dirty(pte) pte_dirty(pte)
+#else
+#define pte_maybe_dirty(pte) (1)
#endif
#ifndef __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG
diff --git a/include/asm-generic/topology.h b/include/asm-generic/topology.h
index ec96e8b0f19..5d9d70cd17f 100644
--- a/include/asm-generic/topology.h
+++ b/include/asm-generic/topology.h
@@ -41,8 +41,15 @@
#ifndef node_to_first_cpu
#define node_to_first_cpu(node) (0)
#endif
+#ifndef pcibus_to_node
+#define pcibus_to_node(node) (-1)
+#endif
+
#ifndef pcibus_to_cpumask
-#define pcibus_to_cpumask(bus) (cpu_online_map)
+#define pcibus_to_cpumask(bus) (pcibus_to_node(bus) == -1 ? \
+ CPU_MASK_ALL : \
+ node_to_cpumask(pcibus_to_node(bus)) \
+ )
#endif
#endif /* _ASM_GENERIC_TOPOLOGY_H */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 99cef06a364..b3bb326ae5b 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -73,7 +73,7 @@
}
#define SECURITY_INIT \
- .security_initcall.init : { \
+ .security_initcall.init : AT(ADDR(.security_initcall.init) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__security_initcall_start) = .; \
*(.security_initcall.init) \
VMLINUX_SYMBOL(__security_initcall_end) = .; \
diff --git a/include/asm-h8300/kmap_types.h b/include/asm-h8300/kmap_types.h
index 82431edeb2a..1ec8a342712 100644
--- a/include/asm-h8300/kmap_types.h
+++ b/include/asm-h8300/kmap_types.h
@@ -1,5 +1,5 @@
-#ifndef _ASM_KMAP_TYPES_H
-#define _ASM_KMAP_TYPES_H
+#ifndef _ASM_H8300_KMAP_TYPES_H
+#define _ASM_H8300_KMAP_TYPES_H
enum km_type {
KM_BOUNCE_READ,
@@ -13,6 +13,8 @@ enum km_type {
KM_PTE1,
KM_IRQ0,
KM_IRQ1,
+ KM_SOFTIRQ0,
+ KM_SOFTIRQ1,
KM_TYPE_NR
};
diff --git a/include/asm-h8300/mman.h b/include/asm-h8300/mman.h
index abe08856c84..63f727a5985 100644
--- a/include/asm-h8300/mman.h
+++ b/include/asm-h8300/mman.h
@@ -4,6 +4,7 @@
#define PROT_READ 0x1 /* page can be read */
#define PROT_WRITE 0x2 /* page can be written */
#define PROT_EXEC 0x4 /* page can be executed */
+#define PROT_SEM 0x8 /* page may be used for atomic ops */
#define PROT_NONE 0x0 /* page can not be accessed */
#define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */
#define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */
@@ -19,6 +20,8 @@
#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
#define MAP_LOCKED 0x2000 /* pages are locked */
#define MAP_NORESERVE 0x4000 /* don't check for reservations */
+#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
+#define MAP_NONBLOCK 0x10000 /* do not block on IO */
#define MS_ASYNC 1 /* sync memory asynchronously */
#define MS_INVALIDATE 2 /* invalidate the caches */
diff --git a/include/asm-h8300/thread_info.h b/include/asm-h8300/thread_info.h
index b07c9344776..bfcc755c3bb 100644
--- a/include/asm-h8300/thread_info.h
+++ b/include/asm-h8300/thread_info.h
@@ -23,7 +23,7 @@ struct thread_info {
struct exec_domain *exec_domain; /* execution domain */
unsigned long flags; /* low level flags */
int cpu; /* cpu we're on */
- int preempt_count; /* 0 => preemptable, <0 => BUG*/
+ int preempt_count; /* 0 => preemptable, <0 => BUG */
struct restart_block restart_block;
};
diff --git a/include/asm-i386/agp.h b/include/asm-i386/agp.h
index a917ff50354..b82f5f3ab88 100644
--- a/include/asm-i386/agp.h
+++ b/include/asm-i386/agp.h
@@ -21,4 +21,14 @@ int unmap_page_from_agp(struct page *page);
worth it. Would need a page for it. */
#define flush_agp_cache() asm volatile("wbinvd":::"memory")
+/* Convert a physical address to an address suitable for the GART. */
+#define phys_to_gart(x) (x)
+#define gart_to_phys(x) (x)
+
+/* GATT allocation. Returns/accepts GATT kernel virtual address. */
+#define alloc_gatt_pages(order) \
+ ((char *)__get_free_pages(GFP_KERNEL, (order)))
+#define free_gatt_pages(table, order) \
+ free_pages((unsigned long)(table), (order))
+
#endif
diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h
index a5810cf7b57..6a1b1882285 100644
--- a/include/asm-i386/apic.h
+++ b/include/asm-i386/apic.h
@@ -5,6 +5,7 @@
#include <linux/pm.h>
#include <asm/fixmap.h>
#include <asm/apicdef.h>
+#include <asm/processor.h>
#include <asm/system.h>
#define Dprintk(x...)
@@ -16,8 +17,20 @@
#define APIC_VERBOSE 1
#define APIC_DEBUG 2
+extern int enable_local_apic;
extern int apic_verbosity;
+static inline void lapic_disable(void)
+{
+ enable_local_apic = -1;
+ clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
+}
+
+static inline void lapic_enable(void)
+{
+ enable_local_apic = 1;
+}
+
/*
* Define the default level of output to be very little
* This can be turned up by using apic=verbose for more
@@ -87,7 +100,7 @@ extern void (*wait_timer_tick)(void);
extern int get_maxlvt(void);
extern void clear_local_APIC(void);
extern void connect_bsp_APIC (void);
-extern void disconnect_bsp_APIC (void);
+extern void disconnect_bsp_APIC (int virt_wire_setup);
extern void disable_local_APIC (void);
extern void lapic_shutdown (void);
extern int verify_local_APIC (void);
diff --git a/include/asm-i386/apicdef.h b/include/asm-i386/apicdef.h
index c689554ad5b..0fed5e3c699 100644
--- a/include/asm-i386/apicdef.h
+++ b/include/asm-i386/apicdef.h
@@ -86,11 +86,12 @@
#define APIC_LVT_REMOTE_IRR (1<<14)
#define APIC_INPUT_POLARITY (1<<13)
#define APIC_SEND_PENDING (1<<12)
+#define APIC_MODE_MASK 0x700
#define GET_APIC_DELIVERY_MODE(x) (((x)>>8)&0x7)
#define SET_APIC_DELIVERY_MODE(x,y) (((x)&~0x700)|((y)<<8))
#define APIC_MODE_FIXED 0x0
#define APIC_MODE_NMI 0x4
-#define APIC_MODE_EXINT 0x7
+#define APIC_MODE_EXTINT 0x7
#define APIC_LVT1 0x360
#define APIC_LVTERR 0x370
#define APIC_TMICT 0x380
diff --git a/include/asm-i386/checksum.h b/include/asm-i386/checksum.h
index 641342002bc..f949e44c2a3 100644
--- a/include/asm-i386/checksum.h
+++ b/include/asm-i386/checksum.h
@@ -3,6 +3,8 @@
#include <linux/in6.h>
+#include <asm/uaccess.h>
+
/*
* computes the checksum of a memory block at buff, length len,
* and adds in "sum" (32-bit)
diff --git a/include/asm-i386/cpu.h b/include/asm-i386/cpu.h
index 002740b2195..e7252c216ca 100644
--- a/include/asm-i386/cpu.h
+++ b/include/asm-i386/cpu.h
@@ -5,6 +5,7 @@
#include <linux/cpu.h>
#include <linux/topology.h>
#include <linux/nodemask.h>
+#include <linux/percpu.h>
#include <asm/node.h>
@@ -16,4 +17,5 @@ extern int arch_register_cpu(int num);
extern void arch_unregister_cpu(int);
#endif
+DECLARE_PER_CPU(int, cpu_state);
#endif /* _ASM_I386_CPU_H_ */
diff --git a/include/asm-i386/genapic.h b/include/asm-i386/genapic.h
index fc813b2e827..b3783a32abe 100644
--- a/include/asm-i386/genapic.h
+++ b/include/asm-i386/genapic.h
@@ -78,7 +78,6 @@ struct genapic {
.int_delivery_mode = INT_DELIVERY_MODE, \
.int_dest_mode = INT_DEST_MODE, \
.no_balance_irq = NO_BALANCE_IRQ, \
- .no_ioapic_check = NO_IOAPIC_CHECK, \
.ESR_DISABLE = esr_disable, \
.apic_destination_logical = APIC_DEST_LOGICAL, \
APICFUNC(apic_id_registered), \
diff --git a/include/asm-i386/highmem.h b/include/asm-i386/highmem.h
index 1df42bf347d..0fd331306b6 100644
--- a/include/asm-i386/highmem.h
+++ b/include/asm-i386/highmem.h
@@ -70,6 +70,7 @@ void *kmap(struct page *page);
void kunmap(struct page *page);
void *kmap_atomic(struct page *page, enum km_type type);
void kunmap_atomic(void *kvaddr, enum km_type type);
+void *kmap_atomic_pfn(unsigned long pfn, enum km_type type);
struct page *kmap_atomic_to_page(void *ptr);
#define flush_cache_kmaps() do { } while (0)
diff --git a/include/asm-i386/irq.h b/include/asm-i386/irq.h
index 05b9e61b0a7..270f1986b19 100644
--- a/include/asm-i386/irq.h
+++ b/include/asm-i386/irq.h
@@ -29,13 +29,19 @@ extern void release_vm86_irqs(struct task_struct *);
#ifdef CONFIG_4KSTACKS
extern void irq_ctx_init(int cpu);
+ extern void irq_ctx_exit(int cpu);
# define __ARCH_HAS_DO_SOFTIRQ
#else
# define irq_ctx_init(cpu) do { } while (0)
+# define irq_ctx_exit(cpu) do { } while (0)
#endif
#ifdef CONFIG_IRQBALANCE
extern int irqbalance_disable(char *str);
#endif
+#ifdef CONFIG_HOTPLUG_CPU
+extern void fixup_irqs(cpumask_t map);
+#endif
+
#endif /* _ASM_IRQ_H */
diff --git a/include/asm-i386/kdebug.h b/include/asm-i386/kdebug.h
index de6498b0d49..b3f8d5f59d5 100644
--- a/include/asm-i386/kdebug.h
+++ b/include/asm-i386/kdebug.h
@@ -18,7 +18,7 @@ struct die_args {
};
/* Note - you should never unregister because that can race with NMIs.
- If you really want to do it first unregister - then synchronize_kernel - then free.
+ If you really want to do it first unregister - then synchronize_sched - then free.
*/
int register_die_notifier(struct notifier_block *nb);
extern struct notifier_block *i386die_chain;
diff --git a/include/asm-i386/kexec.h b/include/asm-i386/kexec.h
new file mode 100644
index 00000000000..6ed2a03e37b
--- /dev/null
+++ b/include/asm-i386/kexec.h
@@ -0,0 +1,33 @@
+#ifndef _I386_KEXEC_H
+#define _I386_KEXEC_H
+
+#include <asm/fixmap.h>
+
+/*
+ * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return.
+ * I.e. Maximum page that is mapped directly into kernel memory,
+ * and kmap is not required.
+ *
+ * Someone correct me if FIXADDR_START - PAGEOFFSET is not the correct
+ * calculation for the amount of memory directly mappable into the
+ * kernel memory space.
+ */
+
+/* Maximum physical address we can use pages from */
+#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
+/* Maximum address we can reach in physical address mode */
+#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
+/* Maximum address we can use for the control code buffer */
+#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE
+
+#define KEXEC_CONTROL_CODE_SIZE 4096
+
+/* The native architecture */
+#define KEXEC_ARCH KEXEC_ARCH_386
+
+#define MAX_NOTE_BYTES 1024
+typedef u32 note_buf_t[MAX_NOTE_BYTES/4];
+
+extern note_buf_t crash_notes[];
+
+#endif /* _I386_KEXEC_H */
diff --git a/include/asm-i386/kprobes.h b/include/asm-i386/kprobes.h
index 4092f68d123..8b6d3a90cd7 100644
--- a/include/asm-i386/kprobes.h
+++ b/include/asm-i386/kprobes.h
@@ -39,6 +39,9 @@ typedef u8 kprobe_opcode_t;
: (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR)))
#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry
+#define ARCH_SUPPORTS_KRETPROBES
+
+void kretprobe_trampoline(void);
/* Architecture specific copy of original instruction*/
struct arch_specific_insn {
diff --git a/include/asm-i386/linkage.h b/include/asm-i386/linkage.h
index af3d8571c5c..f4a6ebac024 100644
--- a/include/asm-i386/linkage.h
+++ b/include/asm-i386/linkage.h
@@ -5,9 +5,7 @@
#define FASTCALL(x) x __attribute__((regparm(3)))
#define fastcall __attribute__((regparm(3)))
-#ifdef CONFIG_REGPARM
-# define prevent_tail_call(ret) __asm__ ("" : "=r" (ret) : "0" (ret))
-#endif
+#define prevent_tail_call(ret) __asm__ ("" : "=r" (ret) : "0" (ret))
#ifdef CONFIG_X86_ALIGNMENT_16
#define __ALIGN .align 16,0x90
diff --git a/include/asm-i386/mach-bigsmp/mach_apic.h b/include/asm-i386/mach-bigsmp/mach_apic.h
index 2339868270e..ba936d4daed 100644
--- a/include/asm-i386/mach-bigsmp/mach_apic.h
+++ b/include/asm-i386/mach-bigsmp/mach_apic.h
@@ -14,8 +14,6 @@
#define NO_BALANCE_IRQ (1)
#define esr_disable (1)
-#define NO_IOAPIC_CHECK (0)
-
static inline int apic_id_registered(void)
{
return (1);
diff --git a/include/asm-i386/mach-default/mach_apic.h b/include/asm-i386/mach-default/mach_apic.h
index 627f1cd084b..3ef6292db78 100644
--- a/include/asm-i386/mach-default/mach_apic.h
+++ b/include/asm-i386/mach-default/mach_apic.h
@@ -19,8 +19,6 @@ static inline cpumask_t target_cpus(void)
#define NO_BALANCE_IRQ (0)
#define esr_disable (0)
-#define NO_IOAPIC_CHECK (0)
-
#define INT_DELIVERY_MODE dest_LowestPrio
#define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */
diff --git a/include/asm-i386/mach-default/mach_ipi.h b/include/asm-i386/mach-default/mach_ipi.h
index 6f2b17a2008..cc756a67cd6 100644
--- a/include/asm-i386/mach-default/mach_ipi.h
+++ b/include/asm-i386/mach-default/mach_ipi.h
@@ -4,11 +4,34 @@
void send_IPI_mask_bitmask(cpumask_t mask, int vector);
void __send_IPI_shortcut(unsigned int shortcut, int vector);
+extern int no_broadcast;
+
static inline void send_IPI_mask(cpumask_t mask, int vector)
{
send_IPI_mask_bitmask(mask, vector);
}
+static inline void __local_send_IPI_allbutself(int vector)
+{
+ if (no_broadcast) {
+ cpumask_t mask = cpu_online_map;
+ int this_cpu = get_cpu();
+
+ cpu_clear(this_cpu, mask);
+ send_IPI_mask(mask, vector);
+ put_cpu();
+ } else
+ __send_IPI_shortcut(APIC_DEST_ALLBUT, vector);
+}
+
+static inline void __local_send_IPI_all(int vector)
+{
+ if (no_broadcast)
+ send_IPI_mask(cpu_online_map, vector);
+ else
+ __send_IPI_shortcut(APIC_DEST_ALLINC, vector);
+}
+
static inline void send_IPI_allbutself(int vector)
{
/*
@@ -18,13 +41,13 @@ static inline void send_IPI_allbutself(int vector)
if (!(num_online_cpus() > 1))
return;
- __send_IPI_shortcut(APIC_DEST_ALLBUT, vector);
+ __local_send_IPI_allbutself(vector);
return;
}
static inline void send_IPI_all(int vector)
{
- __send_IPI_shortcut(APIC_DEST_ALLINC, vector);
+ __local_send_IPI_all(vector);
}
#endif /* __ASM_MACH_IPI_H */
diff --git a/include/asm-i386/mach-es7000/mach_apic.h b/include/asm-i386/mach-es7000/mach_apic.h
index ceab2c464b1..b5f3f0d0b2b 100644
--- a/include/asm-i386/mach-es7000/mach_apic.h
+++ b/include/asm-i386/mach-es7000/mach_apic.h
@@ -38,8 +38,6 @@ static inline cpumask_t target_cpus(void)
#define WAKE_SECONDARY_VIA_INIT
#endif
-#define NO_IOAPIC_CHECK (1)
-
static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid)
{
return 0;
diff --git a/include/asm-i386/mach-generic/mach_apic.h b/include/asm-i386/mach-generic/mach_apic.h
index ab36d02ebed..b13767a4e93 100644
--- a/include/asm-i386/mach-generic/mach_apic.h
+++ b/include/asm-i386/mach-generic/mach_apic.h
@@ -5,7 +5,6 @@
#define esr_disable (genapic->ESR_DISABLE)
#define NO_BALANCE_IRQ (genapic->no_balance_irq)
-#define NO_IOAPIC_CHECK (genapic->no_ioapic_check)
#define INT_DELIVERY_MODE (genapic->int_delivery_mode)
#define INT_DEST_MODE (genapic->int_dest_mode)
#undef APIC_DEST_LOGICAL
diff --git a/include/asm-i386/mach-numaq/mach_apic.h b/include/asm-i386/mach-numaq/mach_apic.h
index e1a04494764..9d158095da8 100644
--- a/include/asm-i386/mach-numaq/mach_apic.h
+++ b/include/asm-i386/mach-numaq/mach_apic.h
@@ -17,8 +17,6 @@ static inline cpumask_t target_cpus(void)
#define NO_BALANCE_IRQ (1)
#define esr_disable (1)
-#define NO_IOAPIC_CHECK (0)
-
#define INT_DELIVERY_MODE dest_LowestPrio
#define INT_DEST_MODE 0 /* physical delivery on LOCAL quad */
diff --git a/include/asm-i386/mach-numaq/mach_ipi.h b/include/asm-i386/mach-numaq/mach_ipi.h
index 1b46fd3f2ae..c6044488e9e 100644
--- a/include/asm-i386/mach-numaq/mach_ipi.h
+++ b/include/asm-i386/mach-numaq/mach_ipi.h
@@ -1,7 +1,7 @@
#ifndef __ASM_MACH_IPI_H
#define __ASM_MACH_IPI_H
-inline void send_IPI_mask_sequence(cpumask_t, int vector);
+void send_IPI_mask_sequence(cpumask_t, int vector);
static inline void send_IPI_mask(cpumask_t mask, int vector)
{
diff --git a/include/asm-i386/mach-summit/mach_apic.h b/include/asm-i386/mach-summit/mach_apic.h
index 74e9cbc8c01..3d6d12937e1 100644
--- a/include/asm-i386/mach-summit/mach_apic.h
+++ b/include/asm-i386/mach-summit/mach_apic.h
@@ -7,8 +7,6 @@
#define esr_disable (1)
#define NO_BALANCE_IRQ (0)
-#define NO_IOAPIC_CHECK (1) /* Don't check I/O APIC ID for xAPIC */
-
/* In clustered mode, the high nibble of APIC ID is a cluster number.
* The low nibble is a 4-bit bitmap. */
#define XAPIC_DEST_CPUS_SHIFT 4
diff --git a/include/asm-i386/mach-visws/mach_apic.h b/include/asm-i386/mach-visws/mach_apic.h
index 4e6cdfb8b09..de438c7147a 100644
--- a/include/asm-i386/mach-visws/mach_apic.h
+++ b/include/asm-i386/mach-visws/mach_apic.h
@@ -9,8 +9,6 @@
#define no_balance_irq (0)
#define esr_disable (0)
-#define NO_IOAPIC_CHECK (0)
-
#define INT_DELIVERY_MODE dest_LowestPrio
#define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */
diff --git a/include/asm-i386/mmzone.h b/include/asm-i386/mmzone.h
index 13830ae67ca..33ce5d37e89 100644
--- a/include/asm-i386/mmzone.h
+++ b/include/asm-i386/mmzone.h
@@ -8,7 +8,9 @@
#include <asm/smp.h>
-#ifdef CONFIG_DISCONTIGMEM
+#if CONFIG_NUMA
+extern struct pglist_data *node_data[];
+#define NODE_DATA(nid) (node_data[nid])
#ifdef CONFIG_NUMA
#ifdef CONFIG_X86_NUMAQ
@@ -21,8 +23,28 @@
#define get_zholes_size(n) (0)
#endif /* CONFIG_NUMA */
-extern struct pglist_data *node_data[];
-#define NODE_DATA(nid) (node_data[nid])
+extern int get_memcfg_numa_flat(void );
+/*
+ * This allows any one NUMA architecture to be compiled
+ * for, and still fall back to the flat function if it
+ * fails.
+ */
+static inline void get_memcfg_numa(void)
+{
+#ifdef CONFIG_X86_NUMAQ
+ if (get_memcfg_numaq())
+ return;
+#elif CONFIG_ACPI_SRAT
+ if (get_memcfg_from_srat())
+ return;
+#endif
+
+ get_memcfg_numa_flat();
+}
+
+#endif /* CONFIG_NUMA */
+
+#ifdef CONFIG_DISCONTIGMEM
/*
* generic node memory support, the following assumptions apply:
@@ -48,26 +70,6 @@ static inline int pfn_to_nid(unsigned long pfn)
#endif
}
-/*
- * Following are macros that are specific to this numa platform.
- */
-#define reserve_bootmem(addr, size) \
- reserve_bootmem_node(NODE_DATA(0), (addr), (size))
-#define alloc_bootmem(x) \
- __alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
-#define alloc_bootmem_low(x) \
- __alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES, 0)
-#define alloc_bootmem_pages(x) \
- __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
-#define alloc_bootmem_low_pages(x) \
- __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, 0)
-#define alloc_bootmem_node(ignore, x) \
- __alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
-#define alloc_bootmem_pages_node(ignore, x) \
- __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
-#define alloc_bootmem_low_pages_node(ignore, x) \
- __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, 0)
-
#define node_localnr(pfn, nid) ((pfn) - node_data[nid]->node_start_pfn)
/*
@@ -79,7 +81,6 @@ static inline int pfn_to_nid(unsigned long pfn)
*/
#define kvaddr_to_nid(kaddr) pfn_to_nid(__pa(kaddr) >> PAGE_SHIFT)
-#define node_mem_map(nid) (NODE_DATA(nid)->node_mem_map)
#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn)
#define node_end_pfn(nid) \
({ \
@@ -100,7 +101,7 @@ static inline int pfn_to_nid(unsigned long pfn)
({ \
unsigned long __pfn = pfn; \
int __node = pfn_to_nid(__pfn); \
- &node_mem_map(__node)[node_localnr(__pfn,__node)]; \
+ &NODE_DATA(__node)->node_mem_map[node_localnr(__pfn,__node)]; \
})
#define page_to_pfn(pg) \
@@ -122,26 +123,34 @@ static inline int pfn_valid(int pfn)
return (pfn < node_end_pfn(nid));
return 0;
}
-#endif
+#endif /* CONFIG_X86_NUMAQ */
+
+#endif /* CONFIG_DISCONTIGMEM */
+
+#ifdef CONFIG_NEED_MULTIPLE_NODES
-extern int get_memcfg_numa_flat(void );
/*
- * This allows any one NUMA architecture to be compiled
- * for, and still fall back to the flat function if it
- * fails.
+ * Following are macros that are specific to this numa platform.
*/
-static inline void get_memcfg_numa(void)
-{
-#ifdef CONFIG_X86_NUMAQ
- if (get_memcfg_numaq())
- return;
-#elif CONFIG_ACPI_SRAT
- if (get_memcfg_from_srat())
- return;
-#endif
+#define reserve_bootmem(addr, size) \
+ reserve_bootmem_node(NODE_DATA(0), (addr), (size))
+#define alloc_bootmem(x) \
+ __alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
+#define alloc_bootmem_low(x) \
+ __alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES, 0)
+#define alloc_bootmem_pages(x) \
+ __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
+#define alloc_bootmem_low_pages(x) \
+ __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, 0)
+#define alloc_bootmem_node(ignore, x) \
+ __alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
+#define alloc_bootmem_pages_node(ignore, x) \
+ __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
+#define alloc_bootmem_low_pages_node(ignore, x) \
+ __alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, 0)
- get_memcfg_numa_flat();
-}
+#endif /* CONFIG_NEED_MULTIPLE_NODES */
+
+extern int early_pfn_to_nid(unsigned long pfn);
-#endif /* CONFIG_DISCONTIGMEM */
#endif /* _ASM_MMZONE_H_ */
diff --git a/include/asm-i386/page.h b/include/asm-i386/page.h
index ed13969fa2d..8d93f732d72 100644
--- a/include/asm-i386/page.h
+++ b/include/asm-i386/page.h
@@ -68,6 +68,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#define HPAGE_MASK (~(HPAGE_SIZE - 1))
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
#define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
+#define ARCH_HAS_HUGETLB_CLEAN_STALE_PGTABLE
#endif
#define pgd_val(x) ((x).pgd)
@@ -119,13 +120,18 @@ static __inline__ int get_order(unsigned long size)
extern int sysctl_legacy_va_layout;
+extern int page_is_ram(unsigned long pagenr);
+
#endif /* __ASSEMBLY__ */
#ifdef __ASSEMBLY__
#define __PAGE_OFFSET (0xC0000000)
+#define __PHYSICAL_START CONFIG_PHYSICAL_START
#else
#define __PAGE_OFFSET (0xC0000000UL)
+#define __PHYSICAL_START ((unsigned long)CONFIG_PHYSICAL_START)
#endif
+#define __KERNEL_START (__PAGE_OFFSET + __PHYSICAL_START)
#define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)
@@ -134,11 +140,11 @@ extern int sysctl_legacy_va_layout;
#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
-#ifndef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_FLATMEM
#define pfn_to_page(pfn) (mem_map + (pfn))
#define page_to_pfn(page) ((unsigned long)((page) - mem_map))
#define pfn_valid(pfn) ((pfn) < max_mapnr)
-#endif /* !CONFIG_DISCONTIGMEM */
+#endif /* CONFIG_FLATMEM */
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
diff --git a/include/asm-i386/param.h b/include/asm-i386/param.h
index b6440526e42..fa02e67ea86 100644
--- a/include/asm-i386/param.h
+++ b/include/asm-i386/param.h
@@ -1,8 +1,10 @@
+#include <linux/config.h>
+
#ifndef _ASMi386_PARAM_H
#define _ASMi386_PARAM_H
#ifdef __KERNEL__
-# define HZ 1000 /* Internal kernel timer frequency */
+# define HZ CONFIG_HZ /* Internal kernel timer frequency */
# define USER_HZ 100 /* .. some user interfaces are in "ticks" */
# define CLOCKS_PER_SEC (USER_HZ) /* like times() */
#endif
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
index 8d60c2b4b00..77c6497f416 100644
--- a/include/asm-i386/pgtable.h
+++ b/include/asm-i386/pgtable.h
@@ -236,6 +236,7 @@ static inline pte_t pte_mkexec(pte_t pte) { (pte).pte_low |= _PAGE_USER; return
static inline pte_t pte_mkdirty(pte_t pte) { (pte).pte_low |= _PAGE_DIRTY; return pte; }
static inline pte_t pte_mkyoung(pte_t pte) { (pte).pte_low |= _PAGE_ACCESSED; return pte; }
static inline pte_t pte_mkwrite(pte_t pte) { (pte).pte_low |= _PAGE_RW; return pte; }
+static inline pte_t pte_mkhuge(pte_t pte) { (pte).pte_low |= _PAGE_PRESENT | _PAGE_PSE; return pte; }
#ifdef CONFIG_X86_PAE
# include <asm/pgtable-3level.h>
@@ -275,7 +276,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
*/
#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot))
-#define mk_pte_huge(entry) ((entry).pte_low |= _PAGE_PRESENT | _PAGE_PSE)
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
{
@@ -398,9 +398,9 @@ extern void noexec_setup(const char *str);
#endif /* !__ASSEMBLY__ */
-#ifndef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_FLATMEM
#define kern_addr_valid(addr) (1)
-#endif /* !CONFIG_DISCONTIGMEM */
+#endif /* CONFIG_FLATMEM */
#define io_remap_page_range(vma, vaddr, paddr, size, prot) \
remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index 359bb015174..6f0f93d0d41 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -501,12 +501,16 @@ static inline void load_esp0(struct tss_struct *tss, struct thread_struct *threa
} while (0)
/*
- * This special macro can be used to load a debugging register
+ * These special macros can be used to get or set a debugging register
*/
-#define loaddebug(thread,register) \
- __asm__("movl %0,%%db" #register \
- : /* no output */ \
- :"r" ((thread)->debugreg[register]))
+#define get_debugreg(var, register) \
+ __asm__("movl %%db" #register ", %0" \
+ :"=r" (var))
+#define set_debugreg(value, register) \
+ __asm__("movl %0,%%db" #register \
+ : /* no output */ \
+ :"r" (value))
+
/* Forward declaration, a strange C thing */
struct task_struct;
@@ -687,5 +691,7 @@ extern void select_idle_routine(const struct cpuinfo_x86 *c);
#define cache_line_size() (boot_cpu_data.x86_cache_alignment)
extern unsigned long boot_option_idle_override;
+extern void enable_sep_cpu(void);
+extern int sysenter_setup(void);
#endif /* __ASM_I386_PROCESSOR_H */
diff --git a/include/asm-i386/ptrace.h b/include/asm-i386/ptrace.h
index 8618914b352..eef9f93870d 100644
--- a/include/asm-i386/ptrace.h
+++ b/include/asm-i386/ptrace.h
@@ -57,7 +57,8 @@ struct pt_regs {
#ifdef __KERNEL__
struct task_struct;
extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code);
-#define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs))
+#define user_mode(regs) (3 & (regs)->xcs)
+#define user_mode_vm(regs) ((VM_MASK & (regs)->eflags) || user_mode(regs))
#define instruction_pointer(regs) ((regs)->eip)
#if defined(CONFIG_SMP) && defined(CONFIG_FRAME_POINTER)
extern unsigned long profile_pc(struct pt_regs *regs);
diff --git a/include/asm-i386/smp.h b/include/asm-i386/smp.h
index e03a206dfa3..edad9b4712f 100644
--- a/include/asm-i386/smp.h
+++ b/include/asm-i386/smp.h
@@ -42,16 +42,23 @@ extern void smp_message_irq(int cpl, void *dev_id, struct pt_regs *regs);
extern void smp_invalidate_rcv(void); /* Process an NMI */
extern void (*mtrr_hook) (void);
extern void zap_low_mappings (void);
+extern void lock_ipi_call_lock(void);
+extern void unlock_ipi_call_lock(void);
#define MAX_APICID 256
extern u8 x86_cpu_to_apicid[];
+#ifdef CONFIG_HOTPLUG_CPU
+extern void cpu_exit_clear(void);
+extern void cpu_uninit(void);
+#endif
+
/*
* This function is needed by all SMP systems. It must _always_ be valid
* from the initial startup. We map APIC_BASE very early in page_setup(),
* so this is correct in the x86 case.
*/
-#define __smp_processor_id() (current_thread_info()->cpu)
+#define raw_smp_processor_id() (current_thread_info()->cpu)
extern cpumask_t cpu_callout_map;
extern cpumask_t cpu_callin_map;
@@ -83,6 +90,9 @@ static __inline int logical_smp_processor_id(void)
}
#endif
+
+extern int __cpu_disable(void);
+extern void __cpu_die(unsigned int cpu);
#endif /* !__ASSEMBLY__ */
#define NO_PROC_ID 0xFF /* No processor magic marker */
diff --git a/include/asm-i386/sparsemem.h b/include/asm-i386/sparsemem.h
new file mode 100644
index 00000000000..cfeed990585
--- /dev/null
+++ b/include/asm-i386/sparsemem.h
@@ -0,0 +1,31 @@
+#ifndef _I386_SPARSEMEM_H
+#define _I386_SPARSEMEM_H
+#ifdef CONFIG_SPARSEMEM
+
+/*
+ * generic non-linear memory support:
+ *
+ * 1) we will not split memory into more chunks than will fit into the
+ * flags field of the struct page
+ */
+
+/*
+ * SECTION_SIZE_BITS 2^N: how big each section will be
+ * MAX_PHYSADDR_BITS 2^N: how much physical address space we have
+ * MAX_PHYSMEM_BITS 2^N: how much memory we can have in that space
+ */
+#ifdef CONFIG_X86_PAE
+#define SECTION_SIZE_BITS 30
+#define MAX_PHYSADDR_BITS 36
+#define MAX_PHYSMEM_BITS 36
+#else
+#define SECTION_SIZE_BITS 26
+#define MAX_PHYSADDR_BITS 32
+#define MAX_PHYSMEM_BITS 32
+#endif
+
+/* XXX: FIXME -- wli */
+#define kern_addr_valid(kaddr) (0)
+
+#endif /* CONFIG_SPARSEMEM */
+#endif /* _I386_SPARSEMEM_H */
diff --git a/include/asm-i386/string.h b/include/asm-i386/string.h
index 6a78ac58c19..02c8f5d2206 100644
--- a/include/asm-i386/string.h
+++ b/include/asm-i386/string.h
@@ -116,7 +116,8 @@ __asm__ __volatile__(
"orb $1,%%al\n"
"3:"
:"=a" (__res), "=&S" (d0), "=&D" (d1)
- :"1" (cs),"2" (ct));
+ :"1" (cs),"2" (ct)
+ :"memory");
return __res;
}
@@ -138,8 +139,9 @@ __asm__ __volatile__(
"3:\tsbbl %%eax,%%eax\n\t"
"orb $1,%%al\n"
"4:"
- :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
- :"1" (cs),"2" (ct),"3" (count));
+ :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
+ :"1" (cs),"2" (ct),"3" (count)
+ :"memory");
return __res;
}
@@ -158,7 +160,9 @@ __asm__ __volatile__(
"movl $1,%1\n"
"2:\tmovl %1,%0\n\t"
"decl %0"
- :"=a" (__res), "=&S" (d0) : "1" (s),"0" (c));
+ :"=a" (__res), "=&S" (d0)
+ :"1" (s),"0" (c)
+ :"memory");
return __res;
}
@@ -175,7 +179,9 @@ __asm__ __volatile__(
"leal -1(%%esi),%0\n"
"2:\ttestb %%al,%%al\n\t"
"jne 1b"
- :"=g" (__res), "=&S" (d0), "=&a" (d1) :"0" (0),"1" (s),"2" (c));
+ :"=g" (__res), "=&S" (d0), "=&a" (d1)
+ :"0" (0),"1" (s),"2" (c)
+ :"memory");
return __res;
}
@@ -189,7 +195,9 @@ __asm__ __volatile__(
"scasb\n\t"
"notl %0\n\t"
"decl %0"
- :"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffffu));
+ :"=c" (__res), "=&D" (d0)
+ :"1" (s),"a" (0), "0" (0xffffffffu)
+ :"memory");
return __res;
}
@@ -333,7 +341,9 @@ __asm__ __volatile__(
"je 1f\n\t"
"movl $1,%0\n"
"1:\tdecl %0"
- :"=D" (__res), "=&c" (d0) : "a" (c),"0" (cs),"1" (count));
+ :"=D" (__res), "=&c" (d0)
+ :"a" (c),"0" (cs),"1" (count)
+ :"memory");
return __res;
}
@@ -369,7 +379,7 @@ __asm__ __volatile__(
"je 2f\n\t"
"stosb\n"
"2:"
- : "=&c" (d0), "=&D" (d1)
+ :"=&c" (d0), "=&D" (d1)
:"a" (c), "q" (count), "0" (count/4), "1" ((long) s)
:"memory");
return (s);
@@ -392,7 +402,8 @@ __asm__ __volatile__(
"jne 1b\n"
"3:\tsubl %2,%0"
:"=a" (__res), "=&d" (d0)
- :"c" (s),"1" (count));
+ :"c" (s),"1" (count)
+ :"memory");
return __res;
}
/* end of additional stuff */
@@ -473,7 +484,8 @@ static inline void * memscan(void * addr, int c, size_t size)
"dec %%edi\n"
"1:"
: "=D" (addr), "=c" (size)
- : "0" (addr), "1" (size), "a" (c));
+ : "0" (addr), "1" (size), "a" (c)
+ : "memory");
return addr;
}
diff --git a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
index 2cd57271801..95add81237e 100644
--- a/include/asm-i386/thread_info.h
+++ b/include/asm-i386/thread_info.h
@@ -31,7 +31,7 @@ struct thread_info {
unsigned long flags; /* low level flags */
unsigned long status; /* thread-synchronous flags */
__u32 cpu; /* current CPU */
- __s32 preempt_count; /* 0 => preemptable, <0 => BUG */
+ int preempt_count; /* 0 => preemptable, <0 => BUG */
mm_segment_t addr_limit; /* thread address space:
diff --git a/include/asm-i386/timer.h b/include/asm-i386/timer.h
index 40c54f69780..dcf1e07db08 100644
--- a/include/asm-i386/timer.h
+++ b/include/asm-i386/timer.h
@@ -22,6 +22,7 @@ struct timer_opts {
unsigned long (*get_offset)(void);
unsigned long long (*monotonic_clock)(void);
void (*delay)(unsigned long);
+ unsigned long (*read_timer)(void);
};
struct init_timer_opts {
@@ -52,7 +53,9 @@ extern struct init_timer_opts timer_cyclone_init;
#endif
extern unsigned long calibrate_tsc(void);
+extern unsigned long read_timer_tsc(void);
extern void init_cpu_khz(void);
+extern int recalibrate_cpu_khz(void);
#ifdef CONFIG_HPET_TIMER
extern struct init_timer_opts timer_hpet_init;
extern unsigned long calibrate_tsc_hpet(unsigned long *tsc_hpet_quotient_ptr);
diff --git a/include/asm-i386/timex.h b/include/asm-i386/timex.h
index b41e484c344..292b5a68f62 100644
--- a/include/asm-i386/timex.h
+++ b/include/asm-i386/timex.h
@@ -47,6 +47,9 @@ static inline cycles_t get_cycles (void)
return ret;
}
-extern unsigned long cpu_khz;
+extern unsigned int cpu_khz;
+
+extern int read_current_timer(unsigned long *timer_value);
+#define ARCH_HAS_READ_CURRENT_TIMER 1
#endif
diff --git a/include/asm-i386/topology.h b/include/asm-i386/topology.h
index 98f9e6850cb..2461b731781 100644
--- a/include/asm-i386/topology.h
+++ b/include/asm-i386/topology.h
@@ -60,12 +60,8 @@ static inline int node_to_first_cpu(int node)
return first_cpu(mask);
}
-/* Returns the number of the node containing PCI bus number 'busnr' */
-static inline cpumask_t __pcibus_to_cpumask(int busnr)
-{
- return node_to_cpumask(mp_bus_id_to_node[busnr]);
-}
-#define pcibus_to_cpumask(bus) __pcibus_to_cpumask(bus->number)
+#define pcibus_to_node(bus) mp_bus_id_to_node[(bus)->number]
+#define pcibus_to_cpumask(bus) node_to_cpumask(pcibus_to_node(bus))
/* sched_domains SD_NODE_INIT for NUMAQ machines */
#define SD_NODE_INIT (struct sched_domain) { \
@@ -78,11 +74,14 @@ static inline cpumask_t __pcibus_to_cpumask(int busnr)
.imbalance_pct = 125, \
.cache_hot_time = (10*1000000), \
.cache_nice_tries = 1, \
+ .busy_idx = 3, \
+ .idle_idx = 1, \
+ .newidle_idx = 2, \
+ .wake_idx = 1, \
.per_cpu_gain = 100, \
.flags = SD_LOAD_BALANCE \
| SD_BALANCE_EXEC \
- | SD_BALANCE_NEWIDLE \
- | SD_WAKE_IDLE \
+ | SD_BALANCE_FORK \
| SD_WAKE_BALANCE, \
.last_balance = jiffies, \
.balance_interval = 1, \
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
index 61bcc1b1e3f..176413fb9ae 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -256,7 +256,7 @@
#define __NR_io_submit 248
#define __NR_io_cancel 249
#define __NR_fadvise64 250
-
+#define __NR_set_zone_reclaim 251
#define __NR_exit_group 252
#define __NR_lookup_dcookie 253
#define __NR_epoll_create 254
diff --git a/include/asm-ia64/agp.h b/include/asm-ia64/agp.h
index d1316f1e6ee..4e517f0e6af 100644
--- a/include/asm-ia64/agp.h
+++ b/include/asm-ia64/agp.h
@@ -18,4 +18,14 @@
#define flush_agp_mappings() /* nothing */
#define flush_agp_cache() mb()
+/* Convert a physical address to an address suitable for the GART. */
+#define phys_to_gart(x) (x)
+#define gart_to_phys(x) (x)
+
+/* GATT allocation. Returns/accepts GATT kernel virtual address. */
+#define alloc_gatt_pages(order) \
+ ((char *)__get_free_pages(GFP_KERNEL, (order)))
+#define free_gatt_pages(table, order) \
+ free_pages((unsigned long)(table), (order))
+
#endif /* _ASM_IA64_AGP_H */
diff --git a/include/asm-ia64/break.h b/include/asm-ia64/break.h
index 97c7b2d7960..8167828edc4 100644
--- a/include/asm-ia64/break.h
+++ b/include/asm-ia64/break.h
@@ -12,6 +12,8 @@
* OS-specific debug break numbers:
*/
#define __IA64_BREAK_KDB 0x80100
+#define __IA64_BREAK_KPROBE 0x80200
+#define __IA64_BREAK_JPROBE 0x80300
/*
* OS-specific break numbers:
diff --git a/include/asm-ia64/compat.h b/include/asm-ia64/compat.h
index cc0ff0a4bdd..0c05e5bad8a 100644
--- a/include/asm-ia64/compat.h
+++ b/include/asm-ia64/compat.h
@@ -27,6 +27,7 @@ typedef u16 compat_ipc_pid_t;
typedef s32 compat_daddr_t;
typedef u32 compat_caddr_t;
typedef __kernel_fsid_t compat_fsid_t;
+typedef s32 compat_timer_t;
typedef s32 compat_int_t;
typedef s32 compat_long_t;
diff --git a/include/asm-ia64/fcntl.h b/include/asm-ia64/fcntl.h
index d193981bb1d..c9f8d835d0c 100644
--- a/include/asm-ia64/fcntl.h
+++ b/include/asm-ia64/fcntl.h
@@ -81,4 +81,6 @@ struct flock {
#define F_LINUX_SPECIFIC_BASE 1024
+#define force_o_largefile() ( ! (current->personality & PER_LINUX32) )
+
#endif /* _ASM_IA64_FCNTL_H */
diff --git a/include/asm-ia64/ioctl32.h b/include/asm-ia64/ioctl32.h
deleted file mode 100644
index d0d227f45e0..00000000000
--- a/include/asm-ia64/ioctl32.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/ioctl32.h>
diff --git a/include/asm-ia64/kdebug.h b/include/asm-ia64/kdebug.h
new file mode 100644
index 00000000000..4d376e1663f
--- /dev/null
+++ b/include/asm-ia64/kdebug.h
@@ -0,0 +1,61 @@
+#ifndef _IA64_KDEBUG_H
+#define _IA64_KDEBUG_H 1
+/*
+ * include/asm-ia64/kdebug.h
+ *
+ * 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 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.
+ *
+ * Copyright (C) Intel Corporation, 2005
+ *
+ * 2005-Apr Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
+ * <anil.s.keshavamurthy@intel.com> adopted from
+ * include/asm-x86_64/kdebug.h
+ */
+#include <linux/notifier.h>
+
+struct pt_regs;
+
+struct die_args {
+ struct pt_regs *regs;
+ const char *str;
+ long err;
+ int trapnr;
+ int signr;
+};
+
+int register_die_notifier(struct notifier_block *nb);
+extern struct notifier_block *ia64die_chain;
+
+enum die_val {
+ DIE_BREAK = 1,
+ DIE_SS,
+ DIE_PAGE_FAULT,
+};
+
+static inline int notify_die(enum die_val val, char *str, struct pt_regs *regs,
+ long err, int trap, int sig)
+{
+ struct die_args args = {
+ .regs = regs,
+ .str = str,
+ .err = err,
+ .trapnr = trap,
+ .signr = sig
+ };
+
+ return notifier_call_chain(&ia64die_chain, val, &args);
+}
+
+#endif
diff --git a/include/asm-ia64/kprobes.h b/include/asm-ia64/kprobes.h
new file mode 100644
index 00000000000..7b700035e36
--- /dev/null
+++ b/include/asm-ia64/kprobes.h
@@ -0,0 +1,116 @@
+#ifndef _ASM_KPROBES_H
+#define _ASM_KPROBES_H
+/*
+ * Kernel Probes (KProbes)
+ * include/asm-ia64/kprobes.h
+ *
+ * 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 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.
+ *
+ * Copyright (C) IBM Corporation, 2002, 2004
+ * Copyright (C) Intel Corporation, 2005
+ *
+ * 2005-Apr Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
+ * <anil.s.keshavamurthy@intel.com> adapted from i386
+ */
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <asm/break.h>
+
+#define BREAK_INST (long)(__IA64_BREAK_KPROBE << 6)
+
+typedef union cmp_inst {
+ struct {
+ unsigned long long qp : 6;
+ unsigned long long p1 : 6;
+ unsigned long long c : 1;
+ unsigned long long r2 : 7;
+ unsigned long long r3 : 7;
+ unsigned long long p2 : 6;
+ unsigned long long ta : 1;
+ unsigned long long x2 : 2;
+ unsigned long long tb : 1;
+ unsigned long long opcode : 4;
+ unsigned long long reserved : 23;
+ }f;
+ unsigned long long l;
+} cmp_inst_t;
+
+struct kprobe;
+
+typedef struct _bundle {
+ struct {
+ unsigned long long template : 5;
+ unsigned long long slot0 : 41;
+ unsigned long long slot1_p0 : 64-46;
+ } quad0;
+ struct {
+ unsigned long long slot1_p1 : 41 - (64-46);
+ unsigned long long slot2 : 41;
+ } quad1;
+} __attribute__((__aligned__(16))) bundle_t;
+
+#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry
+
+#define SLOT0_OPCODE_SHIFT (37)
+#define SLOT1_p1_OPCODE_SHIFT (37 - (64-46))
+#define SLOT2_OPCODE_SHIFT (37)
+
+#define INDIRECT_CALL_OPCODE (1)
+#define IP_RELATIVE_CALL_OPCODE (5)
+#define IP_RELATIVE_BRANCH_OPCODE (4)
+#define IP_RELATIVE_PREDICT_OPCODE (7)
+#define LONG_BRANCH_OPCODE (0xC)
+#define LONG_CALL_OPCODE (0xD)
+
+typedef struct kprobe_opcode {
+ bundle_t bundle;
+} kprobe_opcode_t;
+
+struct fnptr {
+ unsigned long ip;
+ unsigned long gp;
+};
+
+/* Architecture specific copy of original instruction*/
+struct arch_specific_insn {
+ /* copy of the instruction to be emulated */
+ kprobe_opcode_t insn;
+ #define INST_FLAG_FIX_RELATIVE_IP_ADDR 1
+ #define INST_FLAG_FIX_BRANCH_REG 2
+ unsigned long inst_flag;
+ unsigned short target_br_reg;
+};
+
+/* ia64 does not need this */
+static inline void jprobe_return(void)
+{
+}
+
+/* ia64 does not need this */
+static inline void arch_copy_kprobe(struct kprobe *p)
+{
+}
+
+#ifdef CONFIG_KPROBES
+extern int kprobe_exceptions_notify(struct notifier_block *self,
+ unsigned long val, void *data);
+#else /* !CONFIG_KPROBES */
+static inline int kprobe_exceptions_notify(struct notifier_block *self,
+ unsigned long val, void *data)
+{
+ return 0;
+}
+#endif
+#endif /* _ASM_KPROBES_H */
diff --git a/include/asm-ia64/mmzone.h b/include/asm-ia64/mmzone.h
index 9491dacc89c..d32f51e3d6c 100644
--- a/include/asm-ia64/mmzone.h
+++ b/include/asm-ia64/mmzone.h
@@ -17,6 +17,20 @@
#ifdef CONFIG_DISCONTIGMEM
+static inline int pfn_to_nid(unsigned long pfn)
+{
+#ifdef CONFIG_NUMA
+ extern int paddr_to_nid(unsigned long);
+ int nid = paddr_to_nid(pfn << PAGE_SHIFT);
+ if (nid < 0)
+ return 0;
+ else
+ return nid;
+#else
+ return 0;
+#endif
+}
+
#ifdef CONFIG_IA64_DIG /* DIG systems are small */
# define MAX_PHYSNODE_ID 8
# define NR_NODE_MEMBLKS (MAX_NUMNODES * 8)
diff --git a/include/asm-ia64/param.h b/include/asm-ia64/param.h
index 6c6b679b7a9..5e1e0d2d7ba 100644
--- a/include/asm-ia64/param.h
+++ b/include/asm-ia64/param.h
@@ -27,7 +27,7 @@
*/
# define HZ 32
# else
-# define HZ 1024
+# define HZ CONFIG_HZ
# endif
# define USER_HZ HZ
# define CLOCKS_PER_SEC HZ /* frequency at which times() counts */
diff --git a/include/asm-ia64/percpu.h b/include/asm-ia64/percpu.h
index 1e87f19dad5..2b14dee29ce 100644
--- a/include/asm-ia64/percpu.h
+++ b/include/asm-ia64/percpu.h
@@ -50,7 +50,7 @@ extern void *per_cpu_init(void);
#else /* ! SMP */
-#define per_cpu(var, cpu) (*((void)cpu, &per_cpu__##var))
+#define per_cpu(var, cpu) (*((void)(cpu), &per_cpu__##var))
#define __get_cpu_var(var) per_cpu__##var
#define per_cpu_init() (__phys_per_cpu_start)
diff --git a/include/asm-ia64/perfmon.h b/include/asm-ia64/perfmon.h
index ed5416c5b1a..7f3333dd00e 100644
--- a/include/asm-ia64/perfmon.h
+++ b/include/asm-ia64/perfmon.h
@@ -177,6 +177,10 @@ typedef union {
extern long perfmonctl(int fd, int cmd, void *arg, int narg);
+typedef struct {
+ void (*handler)(int irq, void *arg, struct pt_regs *regs);
+} pfm_intr_handler_desc_t;
+
extern void pfm_save_regs (struct task_struct *);
extern void pfm_load_regs (struct task_struct *);
@@ -187,6 +191,10 @@ extern void pfm_syst_wide_update_task(struct task_struct *, unsigned long info,
extern void pfm_inherit(struct task_struct *task, struct pt_regs *regs);
extern void pfm_init_percpu(void);
extern void pfm_handle_work(void);
+extern int pfm_install_alt_pmu_interrupt(pfm_intr_handler_desc_t *h);
+extern int pfm_remove_alt_pmu_interrupt(pfm_intr_handler_desc_t *h);
+
+
/*
* Reset PMD register flags
diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
index ea121a00230..48586e08f43 100644
--- a/include/asm-ia64/pgtable.h
+++ b/include/asm-ia64/pgtable.h
@@ -8,7 +8,7 @@
* This hopefully works with any (fixed) IA-64 page-size, as defined
* in <asm/page.h>.
*
- * Copyright (C) 1998-2004 Hewlett-Packard Co
+ * Copyright (C) 1998-2005 Hewlett-Packard Co
* David Mosberger-Tang <davidm@hpl.hp.com>
*/
@@ -283,6 +283,7 @@ ia64_phys_addr_valid (unsigned long addr)
#define pte_mkyoung(pte) (__pte(pte_val(pte) | _PAGE_A))
#define pte_mkclean(pte) (__pte(pte_val(pte) & ~_PAGE_D))
#define pte_mkdirty(pte) (__pte(pte_val(pte) | _PAGE_D))
+#define pte_mkhuge(pte) (__pte(pte_val(pte) | _PAGE_P))
/*
* Macro to a page protection value as "uncacheable". Note that "protection" is really a
@@ -551,7 +552,11 @@ do { \
/* These tell get_user_pages() that the first gate page is accessible from user-level. */
#define FIXADDR_USER_START GATE_ADDR
-#define FIXADDR_USER_END (GATE_ADDR + 2*PERCPU_PAGE_SIZE)
+#ifdef HAVE_BUGGY_SEGREL
+# define FIXADDR_USER_END (GATE_ADDR + 2*PAGE_SIZE)
+#else
+# define FIXADDR_USER_END (GATE_ADDR + 2*PERCPU_PAGE_SIZE)
+#endif
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
diff --git a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h
index 9e1ba8b7fb6..91bbd1f2246 100644
--- a/include/asm-ia64/processor.h
+++ b/include/asm-ia64/processor.h
@@ -403,7 +403,10 @@ extern void ia64_setreg_unknown_kr (void);
* task_struct at this point.
*/
-/* Return TRUE if task T owns the fph partition of the CPU we're running on. */
+/*
+ * Return TRUE if task T owns the fph partition of the CPU we're running on.
+ * Must be called from code that has preemption disabled.
+ */
#define ia64_is_local_fpu_owner(t) \
({ \
struct task_struct *__ia64_islfo_task = (t); \
@@ -411,7 +414,10 @@ extern void ia64_setreg_unknown_kr (void);
&& __ia64_islfo_task == (struct task_struct *) ia64_get_kr(IA64_KR_FPU_OWNER)); \
})
-/* Mark task T as owning the fph partition of the CPU we're running on. */
+/*
+ * Mark task T as owning the fph partition of the CPU we're running on.
+ * Must be called from code that has preemption disabled.
+ */
#define ia64_set_local_fpu_owner(t) do { \
struct task_struct *__ia64_slfo_task = (t); \
__ia64_slfo_task->thread.last_fph_cpu = smp_processor_id(); \
diff --git a/include/asm-ia64/smp.h b/include/asm-ia64/smp.h
index 3ba1a061e4a..a3914352c99 100644
--- a/include/asm-ia64/smp.h
+++ b/include/asm-ia64/smp.h
@@ -46,7 +46,7 @@ ia64_get_lid (void)
#define SMP_IRQ_REDIRECTION (1 << 0)
#define SMP_IPI_REDIRECTION (1 << 1)
-#define smp_processor_id() (current_thread_info()->cpu)
+#define raw_smp_processor_id() (current_thread_info()->cpu)
extern struct smp_boot_data {
int cpu_count;
diff --git a/include/asm-ia64/sn/mspec.h b/include/asm-ia64/sn/mspec.h
new file mode 100644
index 00000000000..dbe13c6121a
--- /dev/null
+++ b/include/asm-ia64/sn/mspec.h
@@ -0,0 +1,59 @@
+/*
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2001-2004 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#ifndef _ASM_IA64_SN_MSPEC_H
+#define _ASM_IA64_SN_MSPEC_H
+
+#define FETCHOP_VAR_SIZE 64 /* 64 byte per fetchop variable */
+
+#define FETCHOP_LOAD 0
+#define FETCHOP_INCREMENT 8
+#define FETCHOP_DECREMENT 16
+#define FETCHOP_CLEAR 24
+
+#define FETCHOP_STORE 0
+#define FETCHOP_AND 24
+#define FETCHOP_OR 32
+
+#define FETCHOP_CLEAR_CACHE 56
+
+#define FETCHOP_LOAD_OP(addr, op) ( \
+ *(volatile long *)((char*) (addr) + (op)))
+
+#define FETCHOP_STORE_OP(addr, op, x) ( \
+ *(volatile long *)((char*) (addr) + (op)) = (long) (x))
+
+#ifdef __KERNEL__
+
+/*
+ * Each Atomic Memory Operation (AMO formerly known as fetchop)
+ * variable is 64 bytes long. The first 8 bytes are used. The
+ * remaining 56 bytes are unaddressable due to the operation taking
+ * that portion of the address.
+ *
+ * NOTE: The AMO_t _MUST_ be placed in either the first or second half
+ * of the cache line. The cache line _MUST NOT_ be used for anything
+ * other than additional AMO_t entries. This is because there are two
+ * addresses which reference the same physical cache line. One will
+ * be a cached entry with the memory type bits all set. This address
+ * may be loaded into processor cache. The AMO_t will be referenced
+ * uncached via the memory special memory type. If any portion of the
+ * cached cache-line is modified, when that line is flushed, it will
+ * overwrite the uncached value in physical memory and lead to
+ * inconsistency.
+ */
+typedef struct {
+ u64 variable;
+ u64 unused[7];
+} AMO_t;
+
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_IA64_SN_MSPEC_H */
diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
index 56d74ca76b5..eb0395ad0d6 100644
--- a/include/asm-ia64/sn/sn_sal.h
+++ b/include/asm-ia64/sn/sn_sal.h
@@ -115,6 +115,13 @@
#define SAL_IROUTER_INTR_XMIT SAL_CONSOLE_INTR_XMIT
#define SAL_IROUTER_INTR_RECV SAL_CONSOLE_INTR_RECV
+/*
+ * Error Handling Features
+ */
+#define SAL_ERR_FEAT_MCA_SLV_TO_OS_INIT_SLV 0x1
+#define SAL_ERR_FEAT_LOG_SBES 0x2
+#define SAL_ERR_FEAT_MFR_OVERRIDE 0x4
+#define SAL_ERR_FEAT_SBE_THRESHOLD 0xffff0000
/*
* SAL Error Codes
@@ -342,6 +349,25 @@ ia64_sn_plat_cpei_handler(void)
}
/*
+ * Set Error Handling Features
+ */
+static inline u64
+ia64_sn_plat_set_error_handling_features(void)
+{
+ struct ia64_sal_retval ret_stuff;
+
+ ret_stuff.status = 0;
+ ret_stuff.v0 = 0;
+ ret_stuff.v1 = 0;
+ ret_stuff.v2 = 0;
+ SAL_CALL_REENTRANT(ret_stuff, SN_SAL_SET_ERROR_HANDLING_FEATURES,
+ (SAL_ERR_FEAT_MCA_SLV_TO_OS_INIT_SLV | SAL_ERR_FEAT_LOG_SBES),
+ 0, 0, 0, 0, 0, 0);
+
+ return ret_stuff.status;
+}
+
+/*
* Checks for console input.
*/
static inline u64
@@ -472,7 +498,7 @@ static inline u64
ia64_sn_pod_mode(void)
{
struct ia64_sal_retval isrv;
- SAL_CALL(isrv, SN_SAL_POD_MODE, 0, 0, 0, 0, 0, 0, 0);
+ SAL_CALL_REENTRANT(isrv, SN_SAL_POD_MODE, 0, 0, 0, 0, 0, 0, 0);
if (isrv.status)
return 0;
return isrv.v0;
diff --git a/include/asm-ia64/system.h b/include/asm-ia64/system.h
index 6f516e76d1f..cd2cf76b2db 100644
--- a/include/asm-ia64/system.h
+++ b/include/asm-ia64/system.h
@@ -183,8 +183,6 @@ do { \
#ifdef __KERNEL__
-#define prepare_to_switch() do { } while(0)
-
#ifdef CONFIG_IA32_SUPPORT
# define IS_IA32_PROCESS(regs) (ia64_psr(regs)->is != 0)
#else
@@ -274,13 +272,7 @@ extern void ia64_load_extra (struct task_struct *task);
* of that CPU which will not be released, because there we wait for the
* tasklist_lock to become available.
*/
-#define prepare_arch_switch(rq, next) \
-do { \
- spin_lock(&(next)->switch_lock); \
- spin_unlock(&(rq)->lock); \
-} while (0)
-#define finish_arch_switch(rq, prev) spin_unlock_irq(&(prev)->switch_lock)
-#define task_running(rq, p) ((rq)->curr == (p) || spin_is_locked(&(p)->switch_lock))
+#define __ARCH_WANT_UNLOCKED_CTXSW
#define ia64_platform_is(x) (strcmp(x, platform_name) == 0)
diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h
index 8d5b7e77028..7dc8951708a 100644
--- a/include/asm-ia64/thread_info.h
+++ b/include/asm-ia64/thread_info.h
@@ -25,7 +25,7 @@ struct thread_info {
__u32 flags; /* thread_info flags (see TIF_*) */
__u32 cpu; /* current CPU */
mm_segment_t addr_limit; /* user-level address space limit */
- __s32 preempt_count; /* 0=premptable, <0=BUG; will also serve as bh-counter */
+ int preempt_count; /* 0=premptable, <0=BUG; will also serve as bh-counter */
struct restart_block restart_block;
struct {
int signo;
diff --git a/include/asm-ia64/topology.h b/include/asm-ia64/topology.h
index 21cf351fd05..4e64c2a6b36 100644
--- a/include/asm-ia64/topology.h
+++ b/include/asm-ia64/topology.h
@@ -42,25 +42,54 @@
void build_cpu_to_node_map(void);
+#define SD_CPU_INIT (struct sched_domain) { \
+ .span = CPU_MASK_NONE, \
+ .parent = NULL, \
+ .groups = NULL, \
+ .min_interval = 1, \
+ .max_interval = 4, \
+ .busy_factor = 64, \
+ .imbalance_pct = 125, \
+ .cache_hot_time = (10*1000000), \
+ .per_cpu_gain = 100, \
+ .cache_nice_tries = 2, \
+ .busy_idx = 2, \
+ .idle_idx = 1, \
+ .newidle_idx = 2, \
+ .wake_idx = 1, \
+ .forkexec_idx = 1, \
+ .flags = SD_LOAD_BALANCE \
+ | SD_BALANCE_NEWIDLE \
+ | SD_BALANCE_EXEC \
+ | SD_WAKE_AFFINE, \
+ .last_balance = jiffies, \
+ .balance_interval = 1, \
+ .nr_balance_failed = 0, \
+}
+
/* sched_domains SD_NODE_INIT for IA64 NUMA machines */
#define SD_NODE_INIT (struct sched_domain) { \
.span = CPU_MASK_NONE, \
.parent = NULL, \
.groups = NULL, \
- .min_interval = 80, \
- .max_interval = 320, \
- .busy_factor = 320, \
+ .min_interval = 8, \
+ .max_interval = 8*(min(num_online_cpus(), 32)), \
+ .busy_factor = 64, \
.imbalance_pct = 125, \
.cache_hot_time = (10*1000000), \
- .cache_nice_tries = 1, \
+ .cache_nice_tries = 2, \
+ .busy_idx = 3, \
+ .idle_idx = 2, \
+ .newidle_idx = 0, /* unused */ \
+ .wake_idx = 1, \
+ .forkexec_idx = 1, \
.per_cpu_gain = 100, \
.flags = SD_LOAD_BALANCE \
| SD_BALANCE_EXEC \
- | SD_BALANCE_NEWIDLE \
- | SD_WAKE_IDLE \
+ | SD_BALANCE_FORK \
| SD_WAKE_BALANCE, \
.last_balance = jiffies, \
- .balance_interval = 1, \
+ .balance_interval = 64, \
.nr_balance_failed = 0, \
}
@@ -69,17 +98,21 @@ void build_cpu_to_node_map(void);
.span = CPU_MASK_NONE, \
.parent = NULL, \
.groups = NULL, \
- .min_interval = 80, \
- .max_interval = 320, \
- .busy_factor = 320, \
- .imbalance_pct = 125, \
+ .min_interval = 64, \
+ .max_interval = 64*num_online_cpus(), \
+ .busy_factor = 128, \
+ .imbalance_pct = 133, \
.cache_hot_time = (10*1000000), \
.cache_nice_tries = 1, \
+ .busy_idx = 3, \
+ .idle_idx = 3, \
+ .newidle_idx = 0, /* unused */ \
+ .wake_idx = 0, /* unused */ \
+ .forkexec_idx = 0, /* unused */ \
.per_cpu_gain = 100, \
- .flags = SD_LOAD_BALANCE \
- | SD_BALANCE_EXEC, \
+ .flags = SD_LOAD_BALANCE, \
.last_balance = jiffies, \
- .balance_interval = 100*(63+num_online_cpus())/64, \
+ .balance_interval = 64, \
.nr_balance_failed = 0, \
}
diff --git a/include/asm-ia64/uncached.h b/include/asm-ia64/uncached.h
new file mode 100644
index 00000000000..b82d923b73c
--- /dev/null
+++ b/include/asm-ia64/uncached.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2001-2005 Silicon Graphics, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * Prototypes for the uncached page allocator
+ */
+
+extern unsigned long uncached_alloc_page(int nid);
+extern void uncached_free_page(unsigned long);
diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
index 33e26c557c5..f7f43ec2483 100644
--- a/include/asm-ia64/unistd.h
+++ b/include/asm-ia64/unistd.h
@@ -263,6 +263,7 @@
#define __NR_add_key 1271
#define __NR_request_key 1272
#define __NR_keyctl 1273
+#define __NR_set_zone_reclaim 1276
#ifdef __KERNEL__
diff --git a/include/asm-m32r/div64.h b/include/asm-m32r/div64.h
index 417a51bd552..6cd978cefb2 100644
--- a/include/asm-m32r/div64.h
+++ b/include/asm-m32r/div64.h
@@ -1,38 +1 @@
-#ifndef _ASM_M32R_DIV64
-#define _ASM_M32R_DIV64
-
-/* $Id$ */
-
-/* unsigned long long division.
- * Input:
- * unsigned long long n
- * unsigned long base
- * Output:
- * n = n / base;
- * return value = n % base;
- */
-#define do_div(n, base) \
-({ \
- unsigned long _res, _high, _mid, _low; \
- \
- _low = (n) & 0xffffffffUL; \
- _high = (n) >> 32; \
- if (_high) { \
- _mid = (_high % (unsigned long)(base)) << 16; \
- _high = _high / (unsigned long)(base); \
- _mid += _low >> 16; \
- _low &= 0x0000ffffUL; \
- _low += (_mid % (unsigned long)(base)) << 16; \
- _mid = _mid / (unsigned long)(base); \
- _res = _low % (unsigned long)(base); \
- _low = _low / (unsigned long)(base); \
- n = _low + ((long long)_mid << 16) + \
- ((long long)_high << 32); \
- } else { \
- _res = _low % (unsigned long)(base); \
- n = (_low / (unsigned long)(base)); \
- } \
- _res; \
-})
-
-#endif /* _ASM_M32R_DIV64 */
+#include <asm-generic/div64.h>
diff --git a/include/asm-m32r/ide.h b/include/asm-m32r/ide.h
index be64f24e37e..194393bd8be 100644
--- a/include/asm-m32r/ide.h
+++ b/include/asm-m32r/ide.h
@@ -35,7 +35,7 @@
static __inline__ int ide_default_irq(unsigned long base)
{
switch (base) {
-#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_MAPPI2)
+#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3)
case 0x1f0: return PLD_IRQ_CFIREQ;
default:
return 0;
diff --git a/include/asm-m32r/m32102.h b/include/asm-m32r/m32102.h
index b56034026bf..cb98101f4f6 100644
--- a/include/asm-m32r/m32102.h
+++ b/include/asm-m32r/m32102.h
@@ -175,6 +175,7 @@
#define M32R_ICU_CR5_PORTL (0x210+M32R_ICU_OFFSET) /* INT4 */
#define M32R_ICU_CR6_PORTL (0x214+M32R_ICU_OFFSET) /* INT5 */
#define M32R_ICU_CR7_PORTL (0x218+M32R_ICU_OFFSET) /* INT6 */
+#define M32R_ICU_CR8_PORTL (0x219+M32R_ICU_OFFSET) /* INT7 */
#define M32R_ICU_CR16_PORTL (0x23C+M32R_ICU_OFFSET) /* MFT0 */
#define M32R_ICU_CR17_PORTL (0x240+M32R_ICU_OFFSET) /* MFT1 */
#define M32R_ICU_CR18_PORTL (0x244+M32R_ICU_OFFSET) /* MFT2 */
diff --git a/include/asm-m32r/m32102peri.h b/include/asm-m32r/m32102peri.h
deleted file mode 100644
index 3c12955ad0f..00000000000
--- a/include/asm-m32r/m32102peri.h
+++ /dev/null
@@ -1,468 +0,0 @@
-/* $Id$
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000,2001 by Hiroyuki Kondo
- */
-
-#ifndef __ASSEMBLY__
-
-typedef void V;
-typedef char B;
-typedef short S;
-typedef int W;
-typedef long L;
-typedef float F;
-typedef double D;
-typedef unsigned char UB;
-typedef unsigned short US;
-typedef unsigned int UW;
-typedef unsigned long UL;
-typedef const unsigned int CUW;
-
-/*********************************
-
-M32102 ICU
-
-*********************************/
-#define ICUISTS (UW *)0xa0EFF004
-#define ICUIREQ0 (UW *)0xa0EFF008
-#define ICUIREQ1 (UW *)0xa0EFF00C
-
-#define ICUSBICR (UW *)0xa0EFF018
-#define ICUIMASK (UW *)0xa0EFF01C
-
-#define ICUCR1 (UW *)0xa0EFF200 /* INT0 */
-#define ICUCR2 (UW *)0xa0EFF204 /* INT1 */
-#define ICUCR3 (UW *)0xa0EFF208 /* INT2 */
-#define ICUCR4 (UW *)0xa0EFF20C /* INT3 */
-#define ICUCR5 (UW *)0xa0EFF210 /* INT4 */
-#define ICUCR6 (UW *)0xa0EFF214 /* INT5 */
-#define ICUCR7 (UW *)0xa0EFF218 /* INT6 */
-
-#define ICUCR16 (UW *)0xa0EFF23C /* MFT0 */
-#define ICUCR17 (UW *)0xa0EFF240 /* MFT1 */
-#define ICUCR18 (UW *)0xa0EFF244 /* MFT2 */
-#define ICUCR19 (UW *)0xa0EFF248 /* MFT3 */
-#define ICUCR20 (UW *)0xa0EFF24C /* MFT4 */
-#define ICUCR21 (UW *)0xa0EFF250 /* MFT5 */
-
-#define ICUCR32 (UW *)0xa0EFF27C /* DMA0 */
-#define ICUCR33 (UW *)0xa0EFF280 /* DMA1 */
-
-#define ICUCR48 (UW *)0xa0EFF2BC /* SIO0R */
-#define ICUCR49 (UW *)0xa0EFF2C0 /* SIO0S */
-#define ICUCR50 (UW *)0xa0EFF2C4 /* SIO1R */
-#define ICUCR51 (UW *)0xa0EFF2C8 /* SIO1S */
-#define ICUCR52 (UW *)0xa0EFF2CC /* SIO2R */
-#define ICUCR53 (UW *)0xa0EFF2D0 /* SIO2S */
-#define ICUCR54 (UW *)0xa0EFF2D4 /* SIO3R */
-#define ICUCR55 (UW *)0xa0EFF2D8 /* SIO3S */
-#define ICUCR56 (UW *)0xa0EFF2DC /* SIO4R */
-#define ICUCR57 (UW *)0xa0EFF2E0 /* SIO4S */
-
-/*********************************
-
-M32102 MFT
-
-*********************************/
-#define MFTCR (US *)0xa0EFC002
-#define MFTRPR (UB *)0xa0EFC006
-
-#define MFT0MOD (US *)0xa0EFC102
-#define MFT0BOS (US *)0xa0EFC106
-#define MFT0CUT (US *)0xa0EFC10A
-#define MFT0RLD (US *)0xa0EFC10E
-#define MFT0CRLD (US *)0xa0EFC112
-
-#define MFT1MOD (US *)0xa0EFC202
-#define MFT1BOS (US *)0xa0EFC206
-#define MFT1CUT (US *)0xa0EFC20A
-#define MFT1RLD (US *)0xa0EFC20E
-#define MFT1CRLD (US *)0xa0EFC212
-
-#define MFT2MOD (US *)0xa0EFC302
-#define MFT2BOS (US *)0xa0EFC306
-#define MFT2CUT (US *)0xa0EFC30A
-#define MFT2RLD (US *)0xa0EFC30E
-#define MFT2CRLD (US *)0xa0EFC312
-
-#define MFT3MOD (US *)0xa0EFC402
-#define MFT3CUT (US *)0xa0EFC40A
-#define MFT3RLD (US *)0xa0EFC40E
-#define MFT3CRLD (US *)0xa0EFC412
-
-#define MFT4MOD (US *)0xa0EFC502
-#define MFT4CUT (US *)0xa0EFC50A
-#define MFT4RLD (US *)0xa0EFC50E
-#define MFT4CRLD (US *)0xa0EFC512
-
-#define MFT5MOD (US *)0xa0EFC602
-#define MFT5CUT (US *)0xa0EFC60A
-#define MFT5RLD (US *)0xa0EFC60E
-#define MFT5CRLD (US *)0xa0EFC612
-
-/*********************************
-
-M32102 SIO
-
-*********************************/
-
-#define SIO0CR (volatile int *)0xa0efd000
-#define SIO0MOD0 (volatile int *)0xa0efd004
-#define SIO0MOD1 (volatile int *)0xa0efd008
-#define SIO0STS (volatile int *)0xa0efd00c
-#define SIO0IMASK (volatile int *)0xa0efd010
-#define SIO0BAUR (volatile int *)0xa0efd014
-#define SIO0RBAUR (volatile int *)0xa0efd018
-#define SIO0TXB (volatile int *)0xa0efd01c
-#define SIO0RXB (volatile int *)0xa0efd020
-
-#define SIO1CR (volatile int *)0xa0efd100
-#define SIO1MOD0 (volatile int *)0xa0efd104
-#define SIO1MOD1 (volatile int *)0xa0efd108
-#define SIO1STS (volatile int *)0xa0efd10c
-#define SIO1IMASK (volatile int *)0xa0efd110
-#define SIO1BAUR (volatile int *)0xa0efd114
-#define SIO1RBAUR (volatile int *)0xa0efd118
-#define SIO1TXB (volatile int *)0xa0efd11c
-#define SIO1RXB (volatile int *)0xa0efd120
-/*********************************
-
-M32102 PORT
-
-*********************************/
-#define PIEN (UB *)0xa0EF1003 /* input enable */
-
-#define P0DATA (UB *)0xa0EF1020 /* data */
-#define P1DATA (UB *)0xa0EF1021
-#define P2DATA (UB *)0xa0EF1022
-#define P3DATA (UB *)0xa0EF1023
-#define P4DATA (UB *)0xa0EF1024
-#define P5DATA (UB *)0xa0EF1025
-#define P6DATA (UB *)0xa0EF1026
-#define P7DATA (UB *)0xa0EF1027
-
-#define P0DIR (UB *)0xa0EF1040 /* direction */
-#define P1DIR (UB *)0xa0EF1041
-#define P2DIR (UB *)0xa0EF1042
-#define P3DIR (UB *)0xa0EF1043
-#define P4DIR (UB *)0xa0EF1044
-#define P5DIR (UB *)0xa0EF1045
-#define P6DIR (UB *)0xa0EF1046
-#define P7DIR (UB *)0xa0EF1047
-
-#define P0MOD (US *)0xa0EF1060 /* mode control */
-#define P1MOD (US *)0xa0EF1062
-#define P2MOD (US *)0xa0EF1064
-#define P3MOD (US *)0xa0EF1066
-#define P4MOD (US *)0xa0EF1068
-#define P5MOD (US *)0xa0EF106A
-#define P6MOD (US *)0xa0EF106C
-#define P7MOD (US *)0xa0EF106E
-
-#define P0ODCR (UB *)0xa0EF1080 /* open-drain control */
-#define P1ODCR (UB *)0xa0EF1081
-#define P2ODCR (UB *)0xa0EF1082
-#define P3ODCR (UB *)0xa0EF1083
-#define P4ODCR (UB *)0xa0EF1084
-#define P5ODCR (UB *)0xa0EF1085
-#define P6ODCR (UB *)0xa0EF1086
-#define P7ODCR (UB *)0xa0EF1087
-
-/*********************************
-
-M32102 Cache
-
-********************************/
-
-#define MCCR (US *)0xFFFFFFFE
-
-
-#else /* __ASSEMBLY__ */
-
-;;
-;; PIO 0x80ef1000
-;;
-
-#define PIEN 0xa0ef1000
-
-#define P0DATA 0xa0ef1020
-#define P1DATA 0xa0ef1021
-#define P2DATA 0xa0ef1022
-#define P3DATA 0xa0ef1023
-#define P4DATA 0xa0ef1024
-#define P5DATA 0xa0ef1025
-#define P6DATA 0xa0ef1026
-#define P7DATA 0xa0ef1027
-
-#define P0DIR 0xa0ef1040
-#define P1DIR 0xa0ef1041
-#define P2DIR 0xa0ef1042
-#define P3DIR 0xa0ef1043
-#define P4DIR 0xa0ef1044
-#define P5DIR 0xa0ef1045
-#define P6DIR 0xa0ef1046
-#define P7DIR 0xa0ef1047
-
-#define P0MOD 0xa0ef1060
-#define P1MOD 0xa0ef1062
-#define P2MOD 0xa0ef1064
-#define P3MOD 0xa0ef1066
-#define P4MOD 0xa0ef1068
-#define P5MOD 0xa0ef106a
-#define P6MOD 0xa0ef106c
-#define P7MOD 0xa0ef106e
-;
-#define P0ODCR 0xa0ef1080
-#define P1ODCR 0xa0ef1081
-#define P2ODCR 0xa0ef1082
-#define P3ODCR 0xa0ef1083
-#define P4ODCR 0xa0ef1084
-#define P5ODCR 0xa0ef1085
-#define P6ODCR 0xa0ef1086
-#define P7ODCR 0xa0ef1087
-
-;;
-;; WDT 0xa0ef2000
-;;
-
-#define WDTCR 0xa0ef2000
-
-
-;;
-;; CLK 0xa0ef4000
-;;
-
-#define CPUCLKCR 0xa0ef4000
-#define CLKMOD 0xa0ef4004
-#define PLLCR 0xa0ef4008
-
-
-;;
-;; BSEL 0xa0ef5000
-;;
-
-#define BSEL0CR 0xa0ef5000
-#define BSEL1CR 0xa0ef5004
-#define BSEL2CR 0xa0ef5008
-#define BSEL3CR 0xa0ef500c
-#define BSEL4CR 0xa0ef5010
-#define BSEL5CR 0xa0ef5014
-
-
-;;
-;; SDRAMC 0xa0ef6000
-;;
-
-#define SDRF0 0xa0ef6000
-#define SDRF1 0xa0ef6004
-#define SDIR0 0xa0ef6008
-#define SDIR1 0xa0ef600c
-#define SDBR 0xa0ef6010
-
-;; CH0
-#define SD0ADR 0xa0ef6020
-#define SD0SZ 0xa0ef6022
-#define SD0ER 0xa0ef6024
-#define SD0TR 0xa0ef6028
-#define SD0MOD 0xa0ef602c
-
-;; CH1
-#define SD1ADR 0xa0ef6040
-#define SD1SZ 0xa0ef6042
-#define SD1ER 0xa0ef6044
-#define SD1TR 0xa0ef6048
-#define SD1MOD 0xa0ef604c
-
-
-;;
-;; DMAC 0xa0ef8000
-;;
-
-#define DMAEN 0xa0ef8000
-#define DMAISTS 0xa0ef8004
-#define DMAEDET 0xa0ef8008
-#define DMAASTS 0xa0ef800c
-
-;; CH0
-#define DMA0CR0 0xa0ef8100
-#define DMA0CR1 0xa0ef8104
-#define DMA0CSA 0xa0ef8108
-#define DMA0RSA 0xa0ef810c
-#define DMA0CDA 0xa0ef8110
-#define DMA0RDA 0xa0ef8114
-#define DMA0CBCUT 0xa0ef8118
-#define DMA0RBCUT 0xa0ef811c
-
-;; CH1
-#define DMA1CR0 0xa0ef8200
-#define DMA1CR1 0xa0ef8204
-#define DMA1CSA 0xa0ef8208
-#define DMA1RSA 0xa0ef820c
-#define DMA1CDA 0xa0ef8210
-#define DMA1RDA 0xa0ef8214
-#define DMA1CBCUT 0xa0ef8218
-#define DMA1RBCUT 0xa0ef821c
-
-
-;;
-;; MFT 0xa0efc000
-;;
-
-#define MFTCR 0xa0efc000
-#define MFTRPR 0xa0efc004
-
-;; CH0
-#define MFT0MOD 0xa0efc100
-#define MFT0BOS 0xa0efc104
-#define MFT0CUT 0xa0efc108
-#define MFT0RLD 0xa0efc10c
-#define MFT0CMPRLD 0xa0efc110
-
-;; CH1
-#define MFT1MOD 0xa0efc200
-#define MFT1BOS 0xa0efc204
-#define MFT1CUT 0xa0efc208
-#define MFT1RLD 0xa0efc20c
-#define MFT1CMPRLD 0xa0efc210
-
-;; CH2
-#define MFT2MOD 0xa0efc300
-#define MFT2BOS 0xa0efc304
-#define MFT2CUT 0xa0efc308
-#define MFT2RLD 0xa0efc30c
-#define MFT2CMPRLD 0xa0efc310
-
-;; CH3
-#define MFT3MOD 0xa0efc400
-#define MFT3BOS 0xa0efc404
-#define MFT3CUT 0xa0efc408
-#define MFT3RLD 0xa0efc40c
-#define MFT3CMPRLD 0xa0efc410
-
-;; CH4
-#define MFT4MOD 0xa0efc500
-#define MFT4BOS 0xa0efc504
-#define MFT4CUT 0xa0efc508
-#define MFT4RLD 0xa0efc50c
-#define MFT4CMPRLD 0xa0efc510
-
-;; CH5
-#define MFT5MOD 0xa0efc600
-#define MFT5BOS 0xa0efc604
-#define MFT5CUT 0xa0efc608
-#define MFT5RLD 0xa0efc60c
-#define MFT5CMPRLD 0xa0efc610
-
-
-;;
-;; SIO 0xa0efd000
-;;
-
-;; CH0
-#define SIO0CR 0xa0efd000
-#define SIO0MOD0 0xa0efd004
-#define SIO0MOD1 0xa0efd008
-#define SIO0STS 0xa0efd00c
-#define SIO0IMASK 0xa0efd010
-#define SIO0BAUR 0xa0efd014
-#define SIO0RBAUR 0xa0efd018
-#define SIO0TXB 0xa0efd01c
-#define SIO0RXB 0xa0efd020
-
-;; CH1
-#define SIO1CR 0xa0efd100
-#define SIO1MOD0 0xa0efd104
-#define SIO1MOD1 0xa0efd108
-#define SIO1STS 0xa0efd10c
-#define SIO1IMASK 0xa0efd110
-#define SIO1BAUR 0xa0efd114
-#define SIO1RBAUR 0xa0efd118
-#define SIO1TXB 0xa0efd11c
-#define SIO1RXB 0xa0efd120
-
-;; CH2
-#define SIO2CR 0xa0efd200
-#define SIO2MOD0 0xa0efd204
-#define SIO2MOD1 0xa0efd208
-#define SIO2STS 0xa0efd20c
-#define SIO2IMASK 0xa0efd210
-#define SIO2BAUR 0xa0efd214
-#define SIO2RBAUR 0xa0efd218
-#define SIO2TXB 0xa0efd21c
-#define SIO2RXB 0xa0efd220
-
-;; CH3
-#define SIO3CR 0xa0efd300
-#define SIO3MOD0 0xa0efd304
-#define SIO3MOD1 0xa0efd308
-#define SIO3STS 0xa0efd30c
-#define SIO3IMASK 0xa0efd310
-#define SIO3BAUR 0xa0efd314
-#define SIO3RBAUR 0xa0efd318
-#define SIO3TXB 0xa0efd31c
-#define SIO3RXB 0xa0efd320
-
-;; CH4
-#define SIO4CR 0xa0efd400
-#define SIO4MOD0 0xa0efd404
-#define SIO4MOD1 0xa0efd408
-#define SIO4STS 0xa0efd40c
-#define SIO4IMASK 0xa0efd410
-#define SIO4BAUR 0xa0efd414
-#define SIO4RBAUR 0xa0efd418
-#define SIO4TXB 0xa0efd41c
-#define SIO4RXB 0xa0efd420
-
-
-;;
-;; ICU 0xa0eff000
-;;
-
-#define ICUISTS 0xa0eff004
-#define ICUIREQ0 0xa0eff008
-#define ICUIREQ1 0xa0eff00c
-
-#define ICUSBICR 0xa0eff018
-#define ICUIMASK 0xa0eff01c
-
-#define ICUCR1 0xa0eff200
-#define ICUCR2 0xa0eff204
-#define ICUCR3 0xa0eff208
-#define ICUCR4 0xa0eff20c
-#define ICUCR5 0xa0eff210
-#define ICUCR6 0xa0eff214
-#define ICUCR7 0xa0eff218
-
-#define ICUCR16 0xa0eff23c
-#define ICUCR17 0xa0eff240
-#define ICUCR18 0xa0eff244
-#define ICUCR19 0xa0eff248
-#define ICUCR20 0xa0eff24c
-#define ICUCR21 0xa0eff250
-
-#define ICUCR32 0xa0eff27c
-#define ICUCR33 0xa0eff280
-
-#define ICUCR48 0xa0eff2bc
-#define ICUCR49 0xa0eff2c0
-#define ICUCR50 0xa0eff2c4
-#define ICUCR51 0xa0eff2c8
-#define ICUCR52 0xa0eff2cc
-#define ICUCR53 0xa0eff2d0
-#define ICUCR54 0xa0eff2d4
-#define ICUCR55 0xa0eff2d8
-#define ICUCR56 0xa0eff2dc
-#define ICUCR57 0xa0eff2e0
-
-;;
-;; CACHE
-;;
-
-#define MCCR 0xfffffffc
-
-
-#endif /* __ASSEMBLY__ */
diff --git a/include/asm-m32r/m32r.h b/include/asm-m32r/m32r.h
index f116649bbef..ec142be0086 100644
--- a/include/asm-m32r/m32r.h
+++ b/include/asm-m32r/m32r.h
@@ -16,7 +16,6 @@
|| defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32102) \
|| defined(CONFIG_CHIP_OPSP)
#include <asm/m32102.h>
-#include <asm/m32102peri.h>
#endif
/* Platform type */
@@ -36,6 +35,10 @@
#include <asm/mappi2/mappi2_pld.h>
#endif /* CONFIG_PLAT_MAPPI2 */
+#if defined(CONFIG_PLAT_MAPPI3)
+#include <asm/mappi3/mappi3_pld.h>
+#endif /* CONFIG_PLAT_MAPPI3 */
+
#if defined(CONFIG_PLAT_USRV)
#include <asm/m32700ut/m32700ut_pld.h>
#endif
diff --git a/include/asm-m32r/mappi3/mappi3_pld.h b/include/asm-m32r/mappi3/mappi3_pld.h
new file mode 100644
index 00000000000..3f1551f7f01
--- /dev/null
+++ b/include/asm-m32r/mappi3/mappi3_pld.h
@@ -0,0 +1,143 @@
+/*
+ * include/asm/mappi3/mappi3_pld.h
+ *
+ * Definitions for Extended IO Logic on MAPPI3 board.
+ * based on m32700ut_pld.h
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ *
+ */
+
+#ifndef _MAPPI3_PLD_H
+#define _MAPPI3_PLD_H
+
+#ifndef __ASSEMBLY__
+/* FIXME:
+ * Some C functions use non-cache address, so can't define non-cache address.
+ */
+#define PLD_BASE (0x1c000000 /* + NONCACHE_OFFSET */)
+#define __reg8 (volatile unsigned char *)
+#define __reg16 (volatile unsigned short *)
+#define __reg32 (volatile unsigned int *)
+#else
+#define PLD_BASE (0x1c000000 + NONCACHE_OFFSET)
+#define __reg8
+#define __reg16
+#define __reg32
+#endif /* __ASSEMBLY__ */
+
+/* CFC */
+#define PLD_CFRSTCR __reg16(PLD_BASE + 0x0000)
+#define PLD_CFSTS __reg16(PLD_BASE + 0x0002)
+#define PLD_CFIMASK __reg16(PLD_BASE + 0x0004)
+#define PLD_CFBUFCR __reg16(PLD_BASE + 0x0006)
+#define PLD_CFCR0 __reg16(PLD_BASE + 0x000a)
+#define PLD_CFCR1 __reg16(PLD_BASE + 0x000c)
+
+/* MMC */
+#define PLD_MMCCR __reg16(PLD_BASE + 0x4000)
+#define PLD_MMCMOD __reg16(PLD_BASE + 0x4002)
+#define PLD_MMCSTS __reg16(PLD_BASE + 0x4006)
+#define PLD_MMCBAUR __reg16(PLD_BASE + 0x400a)
+#define PLD_MMCCMDBCUT __reg16(PLD_BASE + 0x400c)
+#define PLD_MMCCDTBCUT __reg16(PLD_BASE + 0x400e)
+#define PLD_MMCDET __reg16(PLD_BASE + 0x4010)
+#define PLD_MMCWP __reg16(PLD_BASE + 0x4012)
+#define PLD_MMCWDATA __reg16(PLD_BASE + 0x5000)
+#define PLD_MMCRDATA __reg16(PLD_BASE + 0x6000)
+#define PLD_MMCCMDDATA __reg16(PLD_BASE + 0x7000)
+#define PLD_MMCRSPDATA __reg16(PLD_BASE + 0x7006)
+
+/* Power Control of MMC and CF */
+#define PLD_CPCR __reg16(PLD_BASE + 0x14000)
+
+
+/*==== ICU ====*/
+#define M32R_IRQ_PC104 (5) /* INT4(PC/104) */
+#define M32R_IRQ_I2C (28) /* I2C-BUS */
+#define PLD_IRQ_CFIREQ (6) /* INT5 CFC Card Interrupt */
+#define PLD_IRQ_CFC_INSERT (7) /* INT6 CFC Card Insert */
+#define PLD_IRQ_CFC_EJECT (8) /* INT7 CFC Card Eject */
+#define PLD_IRQ_MMCCARD (43) /* MMC Card Insert */
+#define PLD_IRQ_MMCIRQ (44) /* MMC Transfer Done */
+
+
+#if 0
+/* LED Control
+ *
+ * 1: DIP swich side
+ * 2: Reset switch side
+ */
+#define PLD_IOLEDCR __reg16(PLD_BASE + 0x14002)
+#define PLD_IOLED_1_ON 0x001
+#define PLD_IOLED_1_OFF 0x000
+#define PLD_IOLED_2_ON 0x002
+#define PLD_IOLED_2_OFF 0x000
+
+/* DIP Switch
+ * 0: Write-protect of Flash Memory (0:protected, 1:non-protected)
+ * 1: -
+ * 2: -
+ * 3: -
+ */
+#define PLD_IOSWSTS __reg16(PLD_BASE + 0x14004)
+#define PLD_IOSWSTS_IOSW2 0x0200
+#define PLD_IOSWSTS_IOSW1 0x0100
+#define PLD_IOSWSTS_IOWP0 0x0001
+
+#endif
+
+/* CRC */
+#define PLD_CRC7DATA __reg16(PLD_BASE + 0x18000)
+#define PLD_CRC7INDATA __reg16(PLD_BASE + 0x18002)
+#define PLD_CRC16DATA __reg16(PLD_BASE + 0x18004)
+#define PLD_CRC16INDATA __reg16(PLD_BASE + 0x18006)
+#define PLD_CRC16ADATA __reg16(PLD_BASE + 0x18008)
+#define PLD_CRC16AINDATA __reg16(PLD_BASE + 0x1800a)
+
+
+#if 0
+/* RTC */
+#define PLD_RTCCR __reg16(PLD_BASE + 0x1c000)
+#define PLD_RTCBAUR __reg16(PLD_BASE + 0x1c002)
+#define PLD_RTCWRDATA __reg16(PLD_BASE + 0x1c004)
+#define PLD_RTCRDDATA __reg16(PLD_BASE + 0x1c006)
+#define PLD_RTCRSTODT __reg16(PLD_BASE + 0x1c008)
+
+/* SIO0 */
+#define PLD_ESIO0CR __reg16(PLD_BASE + 0x20000)
+#define PLD_ESIO0CR_TXEN 0x0001
+#define PLD_ESIO0CR_RXEN 0x0002
+#define PLD_ESIO0MOD0 __reg16(PLD_BASE + 0x20002)
+#define PLD_ESIO0MOD0_CTSS 0x0040
+#define PLD_ESIO0MOD0_RTSS 0x0080
+#define PLD_ESIO0MOD1 __reg16(PLD_BASE + 0x20004)
+#define PLD_ESIO0MOD1_LMFS 0x0010
+#define PLD_ESIO0STS __reg16(PLD_BASE + 0x20006)
+#define PLD_ESIO0STS_TEMP 0x0001
+#define PLD_ESIO0STS_TXCP 0x0002
+#define PLD_ESIO0STS_RXCP 0x0004
+#define PLD_ESIO0STS_TXSC 0x0100
+#define PLD_ESIO0STS_RXSC 0x0200
+#define PLD_ESIO0STS_TXREADY (PLD_ESIO0STS_TXCP | PLD_ESIO0STS_TEMP)
+#define PLD_ESIO0INTCR __reg16(PLD_BASE + 0x20008)
+#define PLD_ESIO0INTCR_TXIEN 0x0002
+#define PLD_ESIO0INTCR_RXCEN 0x0004
+#define PLD_ESIO0BAUR __reg16(PLD_BASE + 0x2000a)
+#define PLD_ESIO0TXB __reg16(PLD_BASE + 0x2000c)
+#define PLD_ESIO0RXB __reg16(PLD_BASE + 0x2000e)
+
+/* SIM Card */
+#define PLD_SCCR __reg16(PLD_BASE + 0x38000)
+#define PLD_SCMOD __reg16(PLD_BASE + 0x38004)
+#define PLD_SCSTS __reg16(PLD_BASE + 0x38006)
+#define PLD_SCINTCR __reg16(PLD_BASE + 0x38008)
+#define PLD_SCBAUR __reg16(PLD_BASE + 0x3800a)
+#define PLD_SCTXB __reg16(PLD_BASE + 0x3800c)
+#define PLD_SCRXB __reg16(PLD_BASE + 0x3800e)
+
+#endif
+
+#endif /* _MAPPI3_PLD.H */
diff --git a/include/asm-m32r/mmzone.h b/include/asm-m32r/mmzone.h
index ebf0228fec4..d58878ec899 100644
--- a/include/asm-m32r/mmzone.h
+++ b/include/asm-m32r/mmzone.h
@@ -14,7 +14,6 @@ extern struct pglist_data *node_data[];
#define NODE_DATA(nid) (node_data[nid])
#define node_localnr(pfn, nid) ((pfn) - NODE_DATA(nid)->node_start_pfn)
-#define node_mem_map(nid) (NODE_DATA(nid)->node_mem_map)
#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn)
#define node_end_pfn(nid) \
({ \
@@ -32,7 +31,7 @@ extern struct pglist_data *node_data[];
({ \
unsigned long __pfn = pfn; \
int __node = pfn_to_nid(__pfn); \
- &node_mem_map(__node)[node_localnr(__pfn,__node)]; \
+ &NODE_DATA(__node)->node_mem_map[node_localnr(__pfn,__node)]; \
})
#define page_to_pfn(pg) \
diff --git a/include/asm-m32r/smp.h b/include/asm-m32r/smp.h
index 8cd4d0da4be..b9a20cdad65 100644
--- a/include/asm-m32r/smp.h
+++ b/include/asm-m32r/smp.h
@@ -66,7 +66,7 @@ extern volatile int cpu_2_physid[NR_CPUS];
#define physid_to_cpu(physid) physid_2_cpu[physid]
#define cpu_to_physid(cpu_id) cpu_2_physid[cpu_id]
-#define smp_processor_id() (current_thread_info()->cpu)
+#define raw_smp_processor_id() (current_thread_info()->cpu)
extern cpumask_t cpu_callout_map;
#define cpu_possible_map cpu_callout_map
diff --git a/include/asm-m32r/thread_info.h b/include/asm-m32r/thread_info.h
index 9f3a0fcf6e2..7a6be7727a9 100644
--- a/include/asm-m32r/thread_info.h
+++ b/include/asm-m32r/thread_info.h
@@ -28,7 +28,7 @@ struct thread_info {
unsigned long flags; /* low level flags */
unsigned long status; /* thread-synchronous flags */
__u32 cpu; /* current CPU */
- __s32 preempt_count; /* 0 => preemptable, <0 => BUG */
+ int preempt_count; /* 0 => preemptable, <0 => BUG */
mm_segment_t addr_limit; /* thread address space:
0-0xBFFFFFFF for user-thread
diff --git a/include/asm-m32r/topology.h b/include/asm-m32r/topology.h
index 299a89d91bd..d607eb32bd7 100644
--- a/include/asm-m32r/topology.h
+++ b/include/asm-m32r/topology.h
@@ -1,48 +1,6 @@
-/*
- * linux/include/asm-generic/topology.h
- *
- * Written by: Matthew Dobson, IBM Corporation
- *
- * Copyright (C) 2002, IBM Corp.
- *
- * 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 of the License, 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, GOOD TITLE or
- * NON INFRINGEMENT. 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <colpatch@us.ibm.com>
- */
#ifndef _ASM_M32R_TOPOLOGY_H
#define _ASM_M32R_TOPOLOGY_H
-/* Other architectures wishing to use this simple topology API should fill
- in the below functions as appropriate in their own <asm/topology.h> file. */
-
-#define cpu_to_node(cpu) (0)
-
-#ifndef parent_node
-#define parent_node(node) (0)
-#endif
-#ifndef node_to_cpumask
-#define node_to_cpumask(node) (cpu_online_map)
-#endif
-#ifndef node_to_first_cpu
-#define node_to_first_cpu(node) (0)
-#endif
-#ifndef pcibus_to_cpumask
-#define pcibus_to_cpumask(bus) (cpu_online_map)
-#endif
+#include <asm-generic/topology.h>
#endif /* _ASM_M32R_TOPOLOGY_H */
diff --git a/include/asm-m68k/thread_info.h b/include/asm-m68k/thread_info.h
index 5f58939c59d..2aed24f6fd2 100644
--- a/include/asm-m68k/thread_info.h
+++ b/include/asm-m68k/thread_info.h
@@ -8,7 +8,7 @@
struct thread_info {
struct task_struct *task; /* main task structure */
struct exec_domain *exec_domain; /* execution domain */
- __s32 preempt_count; /* 0 => preemptable, <0 => BUG */
+ int preempt_count; /* 0 => preemptable, <0 => BUG */
__u32 cpu; /* should always be 0 on m68k */
struct restart_block restart_block;
diff --git a/include/asm-m68knommu/thread_info.h b/include/asm-m68knommu/thread_info.h
index c8153b7c1f5..7b9a3fa3af5 100644
--- a/include/asm-m68knommu/thread_info.h
+++ b/include/asm-m68knommu/thread_info.h
@@ -36,7 +36,7 @@ struct thread_info {
struct exec_domain *exec_domain; /* execution domain */
unsigned long flags; /* low level flags */
int cpu; /* cpu we're on */
- int preempt_count; /* 0 => preemptable, <0 => BUG*/
+ int preempt_count; /* 0 => preemptable, <0 => BUG */
struct restart_block restart_block;
};
diff --git a/include/asm-mips/compat.h b/include/asm-mips/compat.h
index dce92079e7f..d78002afb1e 100644
--- a/include/asm-mips/compat.h
+++ b/include/asm-mips/compat.h
@@ -29,6 +29,7 @@ typedef s32 compat_caddr_t;
typedef struct {
s32 val[2];
} compat_fsid_t;
+typedef s32 compat_timer_t;
typedef s32 compat_int_t;
typedef s32 compat_long_t;
diff --git a/include/asm-mips/mmzone.h b/include/asm-mips/mmzone.h
index 29ee13be0b2..d721143dbd4 100644
--- a/include/asm-mips/mmzone.h
+++ b/include/asm-mips/mmzone.h
@@ -8,6 +8,8 @@
#include <asm/page.h>
#include <mmzone.h>
+#ifdef CONFIG_DISCONTIGMEM
+
#define kvaddr_to_nid(kvaddr) pa_to_nid(__pa(kvaddr))
#define pfn_to_nid(pfn) pa_to_nid((pfn) << PAGE_SHIFT)
@@ -36,4 +38,6 @@
/* XXX: FIXME -- wli */
#define kern_addr_valid(addr) (0)
+#endif /* CONFIG_DISCONTIGMEM */
+
#endif /* _ASM_MMZONE_H_ */
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h
index d1bf8240e73..5cae35cd9ba 100644
--- a/include/asm-mips/page.h
+++ b/include/asm-mips/page.h
@@ -127,7 +127,7 @@ static __inline__ int get_order(unsigned long size)
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
-#ifndef CONFIG_DISCONTIGMEM
+#ifndef CONFIG_NEED_MULTIPLE_NODES
#define pfn_to_page(pfn) (mem_map + (pfn))
#define page_to_pfn(page) ((unsigned long)((page) - mem_map))
#define pfn_valid(pfn) ((pfn) < max_mapnr)
diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h
index 878843203d6..e76ccd6e3a5 100644
--- a/include/asm-mips/pgtable.h
+++ b/include/asm-mips/pgtable.h
@@ -350,7 +350,7 @@ static inline void update_mmu_cache(struct vm_area_struct *vma,
__update_cache(vma, address, pte);
}
-#ifndef CONFIG_DISCONTIGMEM
+#ifndef CONFIG_NEED_MULTIPLE_NODES
#define kern_addr_valid(addr) (1)
#endif
diff --git a/include/asm-mips/smp.h b/include/asm-mips/smp.h
index 8ba370ecfd4..5618f1e12f4 100644
--- a/include/asm-mips/smp.h
+++ b/include/asm-mips/smp.h
@@ -21,7 +21,7 @@
#include <linux/cpumask.h>
#include <asm/atomic.h>
-#define smp_processor_id() (current_thread_info()->cpu)
+#define raw_smp_processor_id() (current_thread_info()->cpu)
/* Map from cpu id to sequential logical cpu number. This will only
not be idempotent when cpus failed to come on-line. */
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h
index 888fd890846..169f3d4265b 100644
--- a/include/asm-mips/system.h
+++ b/include/asm-mips/system.h
@@ -422,16 +422,10 @@ extern void __die_if_kernel(const char *, struct pt_regs *, const char *file,
extern int stop_a_enabled;
/*
- * Taken from include/asm-ia64/system.h; prevents deadlock on SMP
+ * See include/asm-ia64/system.h; prevents deadlock on SMP
* systems.
*/
-#define prepare_arch_switch(rq, next) \
-do { \
- spin_lock(&(next)->switch_lock); \
- spin_unlock(&(rq)->lock); \
-} while (0)
-#define finish_arch_switch(rq, prev) spin_unlock_irq(&(prev)->switch_lock)
-#define task_running(rq, p) ((rq)->curr == (p) || spin_is_locked(&(p)->switch_lock))
+#define __ARCH_WANT_UNLOCKED_CTXSW
#define arch_align_stack(x) (x)
diff --git a/include/asm-mips/thread_info.h b/include/asm-mips/thread_info.h
index 768900305e2..42fcd6f2c20 100644
--- a/include/asm-mips/thread_info.h
+++ b/include/asm-mips/thread_info.h
@@ -27,7 +27,7 @@ struct thread_info {
struct exec_domain *exec_domain; /* execution domain */
unsigned long flags; /* low level flags */
__u32 cpu; /* current CPU */
- __s32 preempt_count; /* 0 => preemptable, <0 => BUG */
+ int preempt_count; /* 0 => preemptable, <0 => BUG */
mm_segment_t addr_limit; /* thread address space:
0-0xBFFFFFFF for user-thead
diff --git a/include/asm-mips/vr41xx/giu.h b/include/asm-mips/vr41xx/giu.h
new file mode 100644
index 00000000000..8590885a763
--- /dev/null
+++ b/include/asm-mips/vr41xx/giu.h
@@ -0,0 +1,69 @@
+/*
+ * Include file for NEC VR4100 series General-purpose I/O Unit.
+ *
+ * Copyright (C) 2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ * 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 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
+ */
+#ifndef __NEC_VR41XX_GIU_H
+#define __NEC_VR41XX_GIU_H
+
+typedef enum {
+ IRQ_TRIGGER_LEVEL,
+ IRQ_TRIGGER_EDGE,
+ IRQ_TRIGGER_EDGE_FALLING,
+ IRQ_TRIGGER_EDGE_RISING,
+} irq_trigger_t;
+
+typedef enum {
+ IRQ_SIGNAL_THROUGH,
+ IRQ_SIGNAL_HOLD,
+} irq_signal_t;
+
+extern void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal);
+
+typedef enum {
+ IRQ_LEVEL_LOW,
+ IRQ_LEVEL_HIGH,
+} irq_level_t;
+
+extern void vr41xx_set_irq_level(unsigned int pin, irq_level_t level);
+
+typedef enum {
+ GPIO_DATA_LOW,
+ GPIO_DATA_HIGH,
+ GPIO_DATA_INVAL,
+} gpio_data_t;
+
+extern gpio_data_t vr41xx_gpio_get_pin(unsigned int pin);
+extern int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data);
+
+typedef enum {
+ GPIO_INPUT,
+ GPIO_OUTPUT,
+ GPIO_OUTPUT_DISABLE,
+} gpio_direction_t;
+
+extern int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir);
+
+typedef enum {
+ GPIO_PULL_DOWN,
+ GPIO_PULL_UP,
+ GPIO_PULL_DISABLE,
+} gpio_pull_t;
+
+extern int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull);
+
+#endif /* __NEC_VR41XX_GIU_H */
diff --git a/include/asm-mips/vr41xx/vr41xx.h b/include/asm-mips/vr41xx/vr41xx.h
index ad0d1ea144f..7d41e44463f 100644
--- a/include/asm-mips/vr41xx/vr41xx.h
+++ b/include/asm-mips/vr41xx/vr41xx.h
@@ -126,7 +126,6 @@ extern void vr41xx_mask_clock(vr41xx_clock_t clock);
#define GIU_IRQ_BASE 40
#define GIU_IRQ(x) (GIU_IRQ_BASE + (x)) /* IRQ 40-71 */
#define GIU_IRQ_LAST GIU_IRQ(31)
-#define GIU_IRQ_TO_PIN(x) ((x) - GIU_IRQ_BASE) /* Pin 0-31 */
extern int vr41xx_set_intassign(unsigned int irq, unsigned char intassign);
extern int vr41xx_cascade_irq(unsigned int irq, int (*get_irq_number)(int irq));
@@ -197,38 +196,4 @@ extern void vr41xx_disable_csiint(uint16_t mask);
extern void vr41xx_enable_bcuint(void);
extern void vr41xx_disable_bcuint(void);
-/*
- * General-Purpose I/O Unit
- */
-enum {
- TRIGGER_LEVEL,
- TRIGGER_EDGE,
- TRIGGER_EDGE_FALLING,
- TRIGGER_EDGE_RISING
-};
-
-enum {
- SIGNAL_THROUGH,
- SIGNAL_HOLD
-};
-
-extern void vr41xx_set_irq_trigger(int pin, int trigger, int hold);
-
-enum {
- LEVEL_LOW,
- LEVEL_HIGH
-};
-
-extern void vr41xx_set_irq_level(int pin, int level);
-
-enum {
- PIO_INPUT,
- PIO_OUTPUT
-};
-
-enum {
- DATA_LOW,
- DATA_HIGH
-};
-
#endif /* __NEC_VR41XX_H */
diff --git a/include/asm-parisc/compat.h b/include/asm-parisc/compat.h
index ca0eac647a0..7630d1ad239 100644
--- a/include/asm-parisc/compat.h
+++ b/include/asm-parisc/compat.h
@@ -24,7 +24,7 @@ typedef u16 compat_nlink_t;
typedef u16 compat_ipc_pid_t;
typedef s32 compat_daddr_t;
typedef u32 compat_caddr_t;
-typedef u32 compat_timer_t;
+typedef s32 compat_timer_t;
typedef s32 compat_int_t;
typedef s32 compat_long_t;
diff --git a/include/asm-parisc/mmzone.h b/include/asm-parisc/mmzone.h
index 928bf50c469..595d3dce120 100644
--- a/include/asm-parisc/mmzone.h
+++ b/include/asm-parisc/mmzone.h
@@ -19,7 +19,6 @@ extern struct node_map_data node_data[];
*/
#define kvaddr_to_nid(kaddr) pfn_to_nid(__pa(kaddr) >> PAGE_SHIFT)
-#define node_mem_map(nid) (NODE_DATA(nid)->node_mem_map)
#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn)
#define node_end_pfn(nid) \
({ \
@@ -38,7 +37,7 @@ extern struct node_map_data node_data[];
({ \
unsigned long __pfn = (pfn); \
int __node = pfn_to_nid(__pfn); \
- &node_mem_map(__node)[node_localnr(__pfn,__node)]; \
+ &NODE_DATA(__node)->node_mem_map[node_localnr(__pfn,__node)]; \
})
#define page_to_pfn(pg) \
diff --git a/include/asm-parisc/smp.h b/include/asm-parisc/smp.h
index fde77ac3546..9413f67a540 100644
--- a/include/asm-parisc/smp.h
+++ b/include/asm-parisc/smp.h
@@ -51,7 +51,7 @@ extern void smp_send_reschedule(int cpu);
extern unsigned long cpu_present_mask;
-#define smp_processor_id() (current_thread_info()->cpu)
+#define raw_smp_processor_id() (current_thread_info()->cpu)
#endif /* CONFIG_SMP */
diff --git a/include/asm-parisc/thread_info.h b/include/asm-parisc/thread_info.h
index fe9b7f8ae4c..57bbb76cb6c 100644
--- a/include/asm-parisc/thread_info.h
+++ b/include/asm-parisc/thread_info.h
@@ -12,7 +12,7 @@ struct thread_info {
unsigned long flags; /* thread_info flags (see TIF_*) */
mm_segment_t addr_limit; /* user-level address space limit */
__u32 cpu; /* current CPU */
- __s32 preempt_count; /* 0=premptable, <0=BUG; will also serve as bh-counter */
+ int preempt_count; /* 0=premptable, <0=BUG; will also serve as bh-counter */
struct restart_block restart_block;
};
diff --git a/include/asm-ppc/agp.h b/include/asm-ppc/agp.h
index be27cfa8c5b..ca9e423307f 100644
--- a/include/asm-ppc/agp.h
+++ b/include/asm-ppc/agp.h
@@ -10,4 +10,14 @@
#define flush_agp_mappings()
#define flush_agp_cache() mb()
+/* Convert a physical address to an address suitable for the GART. */
+#define phys_to_gart(x) (x)
+#define gart_to_phys(x) (x)
+
+/* GATT allocation. Returns/accepts GATT kernel virtual address. */
+#define alloc_gatt_pages(order) \
+ ((char *)__get_free_pages(GFP_KERNEL, (order)))
+#define free_gatt_pages(table, order) \
+ free_pages((unsigned long)(table), (order))
+
#endif
diff --git a/include/asm-ppc/cpm2.h b/include/asm-ppc/cpm2.h
index 42fd1068cf2..c5883dbed63 100644
--- a/include/asm-ppc/cpm2.h
+++ b/include/asm-ppc/cpm2.h
@@ -1039,6 +1039,52 @@ typedef struct im_idma {
#define CMXSCR_TS4CS_CLK7 0x00000006 /* SCC4 Tx Clock Source is CLK7 */
#define CMXSCR_TS4CS_CLK8 0x00000007 /* SCC4 Tx Clock Source is CLK8 */
+/*-----------------------------------------------------------------------
+ * SIUMCR - SIU Module Configuration Register 4-31
+ */
+#define SIUMCR_BBD 0x80000000 /* Bus Busy Disable */
+#define SIUMCR_ESE 0x40000000 /* External Snoop Enable */
+#define SIUMCR_PBSE 0x20000000 /* Parity Byte Select Enable */
+#define SIUMCR_CDIS 0x10000000 /* Core Disable */
+#define SIUMCR_DPPC00 0x00000000 /* Data Parity Pins Configuration*/
+#define SIUMCR_DPPC01 0x04000000 /* - " - */
+#define SIUMCR_DPPC10 0x08000000 /* - " - */
+#define SIUMCR_DPPC11 0x0c000000 /* - " - */
+#define SIUMCR_L2CPC00 0x00000000 /* L2 Cache Pins Configuration */
+#define SIUMCR_L2CPC01 0x01000000 /* - " - */
+#define SIUMCR_L2CPC10 0x02000000 /* - " - */
+#define SIUMCR_L2CPC11 0x03000000 /* - " - */
+#define SIUMCR_LBPC00 0x00000000 /* Local Bus Pins Configuration */
+#define SIUMCR_LBPC01 0x00400000 /* - " - */
+#define SIUMCR_LBPC10 0x00800000 /* - " - */
+#define SIUMCR_LBPC11 0x00c00000 /* - " - */
+#define SIUMCR_APPC00 0x00000000 /* Address Parity Pins Configuration*/
+#define SIUMCR_APPC01 0x00100000 /* - " - */
+#define SIUMCR_APPC10 0x00200000 /* - " - */
+#define SIUMCR_APPC11 0x00300000 /* - " - */
+#define SIUMCR_CS10PC00 0x00000000 /* CS10 Pin Configuration */
+#define SIUMCR_CS10PC01 0x00040000 /* - " - */
+#define SIUMCR_CS10PC10 0x00080000 /* - " - */
+#define SIUMCR_CS10PC11 0x000c0000 /* - " - */
+#define SIUMCR_BCTLC00 0x00000000 /* Buffer Control Configuration */
+#define SIUMCR_BCTLC01 0x00010000 /* - " - */
+#define SIUMCR_BCTLC10 0x00020000 /* - " - */
+#define SIUMCR_BCTLC11 0x00030000 /* - " - */
+#define SIUMCR_MMR00 0x00000000 /* Mask Masters Requests */
+#define SIUMCR_MMR01 0x00004000 /* - " - */
+#define SIUMCR_MMR10 0x00008000 /* - " - */
+#define SIUMCR_MMR11 0x0000c000 /* - " - */
+#define SIUMCR_LPBSE 0x00002000 /* LocalBus Parity Byte Select Enable*/
+
+/*-----------------------------------------------------------------------
+ * SCCR - System Clock Control Register 9-8
+*/
+#define SCCR_PCI_MODE 0x00000100 /* PCI Mode */
+#define SCCR_PCI_MODCK 0x00000080 /* Value of PCI_MODCK pin */
+#define SCCR_PCIDF_MSK 0x00000078 /* PCI division factor */
+#define SCCR_PCIDF_SHIFT 3
+
+
#endif /* __CPM2__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-ppc/fsl_ocp.h b/include/asm-ppc/fsl_ocp.h
deleted file mode 100644
index 050fbba8d04..00000000000
--- a/include/asm-ppc/fsl_ocp.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * include/asm-ppc/fsl_ocp.h
- *
- * Definitions for the on-chip peripherals on Freescale PPC processors
- *
- * Maintainer: Kumar Gala (kumar.gala@freescale.com)
- *
- * Copyright 2004 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.
- */
-
-#ifdef __KERNEL__
-#ifndef __ASM_FS_OCP_H__
-#define __ASM_FS_OCP_H__
-
-/* A table of information for supporting the Gianfar Ethernet Controller
- * This helps identify which enet controller we are dealing with,
- * and what type of enet controller it is
- */
-struct ocp_gfar_data {
- uint interruptTransmit;
- uint interruptError;
- uint interruptReceive;
- uint interruptPHY;
- uint flags;
- uint phyid;
- uint phyregidx;
- unsigned char mac_addr[6];
-};
-
-/* Flags in the flags field */
-#define GFAR_HAS_COALESCE 0x20
-#define GFAR_HAS_RMON 0x10
-#define GFAR_HAS_MULTI_INTR 0x08
-#define GFAR_FIRM_SET_MACADDR 0x04
-#define GFAR_HAS_PHY_INTR 0x02 /* if not set use a timer */
-#define GFAR_HAS_GIGABIT 0x01
-
-/* Data structure for I2C support. Just contains a couple flags
- * to distinguish various I2C implementations*/
-struct ocp_fs_i2c_data {
- uint flags;
-};
-
-/* Flags for I2C */
-#define FS_I2C_SEPARATE_DFSRR 0x02
-#define FS_I2C_CLOCK_5200 0x01
-
-#endif /* __ASM_FS_OCP_H__ */
-#endif /* __KERNEL__ */
diff --git a/include/asm-ppc/irq.h b/include/asm-ppc/irq.h
index 06b86be61ed..a9b33324f56 100644
--- a/include/asm-ppc/irq.h
+++ b/include/asm-ppc/irq.h
@@ -176,7 +176,7 @@ static __inline__ int irq_canonicalize(int irq)
*/
#include <asm/mpc85xx.h>
-/* The MPC8560 openpic has 32 internal interrupts and 12 external
+/* The MPC8548 openpic has 48 internal interrupts and 12 external
* interrupts.
*
* We are "flattening" the interrupt vectors of the cascaded CPM
@@ -184,7 +184,7 @@ static __inline__ int irq_canonicalize(int irq)
* single integer.
*/
#define NR_CPM_INTS 64
-#define NR_EPIC_INTS 44
+#define NR_EPIC_INTS 60
#ifndef NR_8259_INTS
#define NR_8259_INTS 0
#endif
@@ -223,9 +223,15 @@ static __inline__ int irq_canonicalize(int irq)
#define MPC85xx_IRQ_RIO_RX (12 + MPC85xx_OPENPIC_IRQ_OFFSET)
#define MPC85xx_IRQ_TSEC1_TX (13 + MPC85xx_OPENPIC_IRQ_OFFSET)
#define MPC85xx_IRQ_TSEC1_RX (14 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC3_TX (15 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC3_RX (16 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC3_ERROR (17 + MPC85xx_OPENPIC_IRQ_OFFSET)
#define MPC85xx_IRQ_TSEC1_ERROR (18 + MPC85xx_OPENPIC_IRQ_OFFSET)
#define MPC85xx_IRQ_TSEC2_TX (19 + MPC85xx_OPENPIC_IRQ_OFFSET)
#define MPC85xx_IRQ_TSEC2_RX (20 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC4_TX (21 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC4_RX (22 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC4_ERROR (23 + MPC85xx_OPENPIC_IRQ_OFFSET)
#define MPC85xx_IRQ_TSEC2_ERROR (24 + MPC85xx_OPENPIC_IRQ_OFFSET)
#define MPC85xx_IRQ_FEC (25 + MPC85xx_OPENPIC_IRQ_OFFSET)
#define MPC85xx_IRQ_DUART (26 + MPC85xx_OPENPIC_IRQ_OFFSET)
@@ -235,18 +241,18 @@ static __inline__ int irq_canonicalize(int irq)
#define MPC85xx_IRQ_CPM (30 + MPC85xx_OPENPIC_IRQ_OFFSET)
/* The 12 external interrupt lines */
-#define MPC85xx_IRQ_EXT0 (32 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT1 (33 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT2 (34 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT3 (35 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT4 (36 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT5 (37 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT6 (38 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT7 (39 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT8 (40 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT9 (41 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT10 (42 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT11 (43 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT0 (48 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT1 (49 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT2 (50 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT3 (51 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT4 (52 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT5 (53 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT6 (54 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT7 (55 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT8 (56 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT9 (57 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT10 (58 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT11 (59 + MPC85xx_OPENPIC_IRQ_OFFSET)
/* CPM related interrupts */
#define SIU_INT_ERROR ((uint)0x00+CPM_IRQ_OFFSET)
diff --git a/include/asm-ppc/kexec.h b/include/asm-ppc/kexec.h
new file mode 100644
index 00000000000..73191310d8d
--- /dev/null
+++ b/include/asm-ppc/kexec.h
@@ -0,0 +1,38 @@
+#ifndef _PPC_KEXEC_H
+#define _PPC_KEXEC_H
+
+#ifdef CONFIG_KEXEC
+
+/*
+ * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return.
+ * I.e. Maximum page that is mapped directly into kernel memory,
+ * and kmap is not required.
+ *
+ * Someone correct me if FIXADDR_START - PAGEOFFSET is not the correct
+ * calculation for the amount of memory directly mappable into the
+ * kernel memory space.
+ */
+
+/* Maximum physical address we can use pages from */
+#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
+/* Maximum address we can reach in physical address mode */
+#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
+/* Maximum address we can use for the control code buffer */
+#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE
+
+#define KEXEC_CONTROL_CODE_SIZE 4096
+
+/* The native architecture */
+#define KEXEC_ARCH KEXEC_ARCH_PPC
+
+#ifndef __ASSEMBLY__
+
+struct kimage;
+
+extern void machine_kexec_simple(struct kimage *image);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* CONFIG_KEXEC */
+
+#endif /* _PPC_KEXEC_H */
diff --git a/include/asm-ppc/m8260_pci.h b/include/asm-ppc/m8260_pci.h
index 163a6b91d5b..bf9e05dd54b 100644
--- a/include/asm-ppc/m8260_pci.h
+++ b/include/asm-ppc/m8260_pci.h
@@ -19,6 +19,7 @@
* Define the vendor/device ID for the MPC8265.
*/
#define PCI_DEVICE_ID_MPC8265 ((0x18C0 << 16) | PCI_VENDOR_ID_MOTOROLA)
+#define PCI_DEVICE_ID_MPC8272 ((0x18C1 << 16) | PCI_VENDOR_ID_MOTOROLA)
#define M8265_PCIBR0 0x101ac
#define M8265_PCIBR1 0x101b0
diff --git a/include/asm-ppc/machdep.h b/include/asm-ppc/machdep.h
index b78d40870c9..1d4ab70a56f 100644
--- a/include/asm-ppc/machdep.h
+++ b/include/asm-ppc/machdep.h
@@ -4,6 +4,7 @@
#include <linux/config.h>
#include <linux/init.h>
+#include <linux/kexec.h>
#include <asm/setup.h>
#include <asm/page.h>
@@ -114,6 +115,36 @@ struct machdep_calls {
/* functions for dealing with other cpus */
struct smp_ops_t *smp_ops;
#endif /* CONFIG_SMP */
+
+#ifdef CONFIG_KEXEC
+ /* Called to shutdown machine specific hardware not already controlled
+ * by other drivers.
+ * XXX Should we move this one out of kexec scope?
+ */
+ void (*machine_shutdown)(void);
+
+ /* Called to do the minimal shutdown needed to run a kexec'd kernel
+ * to run successfully.
+ * XXX Should we move this one out of kexec scope?
+ */
+ void (*machine_crash_shutdown)(void);
+
+ /* Called to do what every setup is needed on image and the
+ * reboot code buffer. Returns 0 on success.
+ * Provide your own (maybe dummy) implementation if your platform
+ * claims to support kexec.
+ */
+ int (*machine_kexec_prepare)(struct kimage *image);
+
+ /* Called to handle any machine specific cleanup on image */
+ void (*machine_kexec_cleanup)(struct kimage *image);
+
+ /* Called to perform the _real_ kexec.
+ * Do NOT allocate memory or fail here. We are past the point of
+ * no return.
+ */
+ void (*machine_kexec)(struct kimage *image);
+#endif /* CONFIG_KEXEC */
};
extern struct machdep_calls ppc_md;
diff --git a/include/asm-ppc/mmu.h b/include/asm-ppc/mmu.h
index d465aee1c82..9205db404c7 100644
--- a/include/asm-ppc/mmu.h
+++ b/include/asm-ppc/mmu.h
@@ -405,7 +405,7 @@ typedef struct _P601_BAT {
#define MAS0_TLBSEL(x) ((x << 28) & 0x30000000)
#define MAS0_ESEL(x) ((x << 16) & 0x0FFF0000)
-#define MAS0_NV 0x00000FFF
+#define MAS0_NV(x) ((x) & 0x00000FFF)
#define MAS1_VALID 0x80000000
#define MAS1_IPROT 0x40000000
diff --git a/include/asm-ppc/mmu_context.h b/include/asm-ppc/mmu_context.h
index 9222fa6ca17..ccabbce39d8 100644
--- a/include/asm-ppc/mmu_context.h
+++ b/include/asm-ppc/mmu_context.h
@@ -63,7 +63,7 @@ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
#define LAST_CONTEXT 255
#define FIRST_CONTEXT 1
-#elif defined(CONFIG_E500)
+#elif defined(CONFIG_E200) || defined(CONFIG_E500)
#define NO_CONTEXT 256
#define LAST_CONTEXT 255
#define FIRST_CONTEXT 1
diff --git a/include/asm-ppc/mpc10x.h b/include/asm-ppc/mpc10x.h
index d8e7e2d6128..f5196a4efbe 100644
--- a/include/asm-ppc/mpc10x.h
+++ b/include/asm-ppc/mpc10x.h
@@ -159,6 +159,12 @@ extern unsigned long ioremap_base;
#define MPC10X_MAPA_EUMB_BASE (ioremap_base - MPC10X_EUMB_SIZE)
#define MPC10X_MAPB_EUMB_BASE MPC10X_MAPA_EUMB_BASE
+enum ppc_sys_devices {
+ MPC10X_IIC1,
+ MPC10X_DMA0,
+ MPC10X_DMA1,
+ MPC10X_DUART,
+};
int mpc10x_bridge_init(struct pci_controller *hose,
uint current_map,
diff --git a/include/asm-ppc/mpc8260.h b/include/asm-ppc/mpc8260.h
index d820894e599..89eb8a2ac69 100644
--- a/include/asm-ppc/mpc8260.h
+++ b/include/asm-ppc/mpc8260.h
@@ -41,7 +41,7 @@
#endif
#ifdef CONFIG_PCI_8260
-#include <syslib/m8260_pci.h>
+#include <syslib/m82xx_pci.h>
#endif
/* Make sure the memory translation stuff is there if PCI not used.
diff --git a/include/asm-ppc/mpc85xx.h b/include/asm-ppc/mpc85xx.h
index 22713e33158..516984ee14b 100644
--- a/include/asm-ppc/mpc85xx.h
+++ b/include/asm-ppc/mpc85xx.h
@@ -25,7 +25,7 @@
#ifdef CONFIG_MPC8540_ADS
#include <platforms/85xx/mpc8540_ads.h>
#endif
-#ifdef CONFIG_MPC8555_CDS
+#if defined(CONFIG_MPC8555_CDS) || defined(CONFIG_MPC8548_CDS)
#include <platforms/85xx/mpc8555_cds.h>
#endif
#ifdef CONFIG_MPC8560_ADS
@@ -74,7 +74,7 @@ extern unsigned char __res[];
#define MPC85xx_GUTS_OFFSET (0xe0000)
#define MPC85xx_GUTS_SIZE (0x01000)
#define MPC85xx_IIC1_OFFSET (0x03000)
-#define MPC85xx_IIC1_SIZE (0x01000)
+#define MPC85xx_IIC1_SIZE (0x00100)
#define MPC85xx_OPENPIC_OFFSET (0x40000)
#define MPC85xx_OPENPIC_SIZE (0x40000)
#define MPC85xx_PCI1_OFFSET (0x08000)
@@ -127,8 +127,64 @@ enum ppc_sys_devices {
MPC85xx_CPM_MCC2,
MPC85xx_CPM_SMC1,
MPC85xx_CPM_SMC2,
+ MPC85xx_eTSEC1,
+ MPC85xx_eTSEC2,
+ MPC85xx_eTSEC3,
+ MPC85xx_eTSEC4,
+ MPC85xx_IIC2,
};
+/* Internal interrupts are all Level Sensitive, and Positive Polarity */
+#define MPC85XX_INTERNAL_IRQ_SENSES \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 0 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 1 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 2 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 3 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 4 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 5 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 6 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 7 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 8 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 9 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 10 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 11 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 12 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 13 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 14 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 15 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 16 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 17 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 18 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 19 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 20 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 21 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 22 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 23 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 24 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 25 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 26 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 27 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 28 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 29 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 30 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 31 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 32 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 33 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 34 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 35 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 36 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 37 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 38 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 39 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 40 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 41 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 42 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 43 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 44 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 45 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* Internal 46 */ \
+ (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE) /* Internal 47 */
+
#endif /* CONFIG_85xx */
#endif /* __ASM_MPC85xx_H__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-ppc/ocp.h b/include/asm-ppc/ocp.h
index b98db3cdae8..983116f59d9 100644
--- a/include/asm-ppc/ocp.h
+++ b/include/asm-ppc/ocp.h
@@ -189,7 +189,7 @@ extern void ocp_for_each_device(void(*callback)(struct ocp_device *, void *arg),
/* Sysfs support */
#define OCP_SYSFS_ADDTL(type, format, name, field) \
static ssize_t \
-show_##name##_##field(struct device *dev, char *buf) \
+show_##name##_##field(struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct ocp_device *odev = to_ocp_dev(dev); \
type *add = odev->def->additions; \
@@ -202,10 +202,6 @@ static DEVICE_ATTR(name##_##field, S_IRUGO, show_##name##_##field, NULL);
#include <asm/ibm_ocp.h>
#endif
-#ifdef CONFIG_FSL_OCP
-#include <asm/fsl_ocp.h>
-#endif
-
#endif /* CONFIG_PPC_OCP */
#endif /* __OCP_H__ */
#endif /* __KERNEL__ */
diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
index a38606d1554..4d4b20c9de7 100644
--- a/include/asm-ppc/pgtable.h
+++ b/include/asm-ppc/pgtable.h
@@ -267,8 +267,6 @@ extern unsigned long ioremap_bot, ioremap_base;
#define _PMD_PRESENT_MASK (PAGE_MASK)
#define _PMD_BAD (~PAGE_MASK)
-#define NUM_TLBCAMS (16)
-
#elif defined(CONFIG_8xx)
/* Definitions for 8xx embedded chips. */
#define _PAGE_PRESENT 0x0001 /* Page is valid */
diff --git a/include/asm-ppc/ppc_asm.h b/include/asm-ppc/ppc_asm.h
index 13fa8e7483c..f76221def48 100644
--- a/include/asm-ppc/ppc_asm.h
+++ b/include/asm-ppc/ppc_asm.h
@@ -174,6 +174,8 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601)
#define CLR_TOP32(r)
#endif /* CONFIG_PPC64BRIDGE */
+#define RFCI .long 0x4c000066 /* rfci instruction */
+#define RFDI .long 0x4c00004e /* rfdi instruction */
#define RFMCI .long 0x4c00004c /* rfmci instruction */
#ifdef CONFIG_IBM405_ERR77
diff --git a/include/asm-ppc/ppc_sys.h b/include/asm-ppc/ppc_sys.h
index 24b991c4276..8ea62456623 100644
--- a/include/asm-ppc/ppc_sys.h
+++ b/include/asm-ppc/ppc_sys.h
@@ -27,6 +27,8 @@
#include <asm/mpc85xx.h>
#elif defined(CONFIG_PPC_MPC52xx)
#include <asm/mpc52xx.h>
+#elif defined(CONFIG_MPC10X_BRIDGE)
+#include <asm/mpc10x.h>
#else
#error "need definition of ppc_sys_devices"
#endif
diff --git a/include/asm-ppc/reg.h b/include/asm-ppc/reg.h
index c418aab7cd3..88b4222154d 100644
--- a/include/asm-ppc/reg.h
+++ b/include/asm-ppc/reg.h
@@ -160,6 +160,7 @@
#define HID0_ICFI (1<<11) /* Instr. Cache Flash Invalidate */
#define HID0_DCI (1<<10) /* Data Cache Invalidate */
#define HID0_SPD (1<<9) /* Speculative disable */
+#define HID0_DAPUEN (1<<8) /* Debug APU enable */
#define HID0_SGE (1<<7) /* Store Gathering Enable */
#define HID0_SIED (1<<7) /* Serial Instr. Execution [Disable] */
#define HID0_DFCA (1<<6) /* Data Cache Flush Assist */
diff --git a/include/asm-ppc/reg_booke.h b/include/asm-ppc/reg_booke.h
index 45c5e6f2b7a..00ad9c754c7 100644
--- a/include/asm-ppc/reg_booke.h
+++ b/include/asm-ppc/reg_booke.h
@@ -165,6 +165,8 @@ do { \
#define SPRN_MCSRR1 0x23B /* Machine Check Save and Restore Register 1 */
#define SPRN_MCSR 0x23C /* Machine Check Status Register */
#define SPRN_MCAR 0x23D /* Machine Check Address Register */
+#define SPRN_DSRR0 0x23E /* Debug Save and Restore Register 0 */
+#define SPRN_DSRR1 0x23F /* Debug Save and Restore Register 1 */
#define SPRN_MAS0 0x270 /* MMU Assist Register 0 */
#define SPRN_MAS1 0x271 /* MMU Assist Register 1 */
#define SPRN_MAS2 0x272 /* MMU Assist Register 2 */
@@ -264,6 +266,17 @@ do { \
#define MCSR_BUS_IPERR 0x00000002UL /* Instruction parity Error */
#define MCSR_BUS_RPERR 0x00000001UL /* Read parity Error */
#endif
+#ifdef CONFIG_E200
+#define MCSR_MCP 0x80000000UL /* Machine Check Input Pin */
+#define MCSR_CP_PERR 0x20000000UL /* Cache Push Parity Error */
+#define MCSR_CPERR 0x10000000UL /* Cache Parity Error */
+#define MCSR_EXCP_ERR 0x08000000UL /* ISI, ITLB, or Bus Error on 1st insn
+ fetch for an exception handler */
+#define MCSR_BUS_IRERR 0x00000010UL /* Read Bus Error on instruction fetch*/
+#define MCSR_BUS_DRERR 0x00000008UL /* Read Bus Error on data load */
+#define MCSR_BUS_WRERR 0x00000004UL /* Write Bus Error on buffered
+ store or cache line push */
+#endif
/* Bit definitions for the DBSR. */
/*
@@ -311,6 +324,7 @@ do { \
#define ESR_ST 0x00800000 /* Store Operation */
#define ESR_DLK 0x00200000 /* Data Cache Locking */
#define ESR_ILK 0x00100000 /* Instr. Cache Locking */
+#define ESR_PUO 0x00040000 /* Unimplemented Operation exception */
#define ESR_BO 0x00020000 /* Byte Ordering */
/* Bit definitions related to the DBCR0. */
@@ -387,10 +401,12 @@ do { \
#define ICCR_CACHE 1 /* Cacheable */
/* Bit definitions for L1CSR0. */
+#define L1CSR0_CLFC 0x00000100 /* Cache Lock Bits Flash Clear */
#define L1CSR0_DCFI 0x00000002 /* Data Cache Flash Invalidate */
+#define L1CSR0_CFI 0x00000002 /* Cache Flash Invalidate */
#define L1CSR0_DCE 0x00000001 /* Data Cache Enable */
-/* Bit definitions for L1CSR0. */
+/* Bit definitions for L1CSR1. */
#define L1CSR1_ICLFR 0x00000100 /* Instr Cache Lock Bits Flash Reset */
#define L1CSR1_ICFI 0x00000002 /* Instr Cache Flash Invalidate */
#define L1CSR1_ICE 0x00000001 /* Instr Cache Enable */
diff --git a/include/asm-ppc/seccomp.h b/include/asm-ppc/seccomp.h
new file mode 100644
index 00000000000..666c4da96d8
--- /dev/null
+++ b/include/asm-ppc/seccomp.h
@@ -0,0 +1,10 @@
+#ifndef _ASM_SECCOMP_H
+
+#include <linux/unistd.h>
+
+#define __NR_seccomp_read __NR_read
+#define __NR_seccomp_write __NR_write
+#define __NR_seccomp_exit __NR_exit
+#define __NR_seccomp_sigreturn __NR_rt_sigreturn
+
+#endif /* _ASM_SECCOMP_H */
diff --git a/include/asm-ppc/sigcontext.h b/include/asm-ppc/sigcontext.h
index f82dcccdee1..b7a417e0a92 100644
--- a/include/asm-ppc/sigcontext.h
+++ b/include/asm-ppc/sigcontext.h
@@ -2,7 +2,7 @@
#define _ASM_PPC_SIGCONTEXT_H
#include <asm/ptrace.h>
-
+#include <linux/compiler.h>
struct sigcontext {
unsigned long _unused[4];
diff --git a/include/asm-ppc/smp.h b/include/asm-ppc/smp.h
index ebfb614f55f..17530c232c7 100644
--- a/include/asm-ppc/smp.h
+++ b/include/asm-ppc/smp.h
@@ -44,7 +44,7 @@ extern void smp_message_recv(int, struct pt_regs *);
#define NO_PROC_ID 0xFF /* No processor magic marker */
#define PROC_CHANGE_PENALTY 20
-#define smp_processor_id() (current_thread_info()->cpu)
+#define raw_smp_processor_id() (current_thread_info()->cpu)
extern int __cpu_up(unsigned int cpu);
diff --git a/include/asm-ppc/thread_info.h b/include/asm-ppc/thread_info.h
index f7f01524e8a..27903db42ef 100644
--- a/include/asm-ppc/thread_info.h
+++ b/include/asm-ppc/thread_info.h
@@ -20,7 +20,8 @@ struct thread_info {
unsigned long flags; /* low level flags */
unsigned long local_flags; /* non-racy flags */
int cpu; /* cpu we're on */
- int preempt_count;
+ int preempt_count; /* 0 => preemptable,
+ <0 => BUG */
struct restart_block restart_block;
};
@@ -77,12 +78,19 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_POLLING_NRFLAG 4 /* true if poll_idle() is polling
TIF_NEED_RESCHED */
#define TIF_MEMDIE 5
+#define TIF_SYSCALL_AUDIT 6 /* syscall auditing active */
+#define TIF_SECCOMP 7 /* secure computing */
+
/* as above, but as bit values */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
+#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
+#define _TIF_SECCOMP (1<<TIF_SECCOMP)
+
+#define _TIF_SYSCALL_T_OR_A (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
/*
* Non racy (local) flags bit numbers
diff --git a/include/asm-ppc64/agp.h b/include/asm-ppc64/agp.h
index be27cfa8c5b..ca9e423307f 100644
--- a/include/asm-ppc64/agp.h
+++ b/include/asm-ppc64/agp.h
@@ -10,4 +10,14 @@
#define flush_agp_mappings()
#define flush_agp_cache() mb()
+/* Convert a physical address to an address suitable for the GART. */
+#define phys_to_gart(x) (x)
+#define gart_to_phys(x) (x)
+
+/* GATT allocation. Returns/accepts GATT kernel virtual address. */
+#define alloc_gatt_pages(order) \
+ ((char *)__get_free_pages(GFP_KERNEL, (order)))
+#define free_gatt_pages(table, order) \
+ free_pages((unsigned long)(table), (order))
+
#endif
diff --git a/include/asm-ppc64/compat.h b/include/asm-ppc64/compat.h
index 09c28d28ce6..12414f5fc66 100644
--- a/include/asm-ppc64/compat.h
+++ b/include/asm-ppc64/compat.h
@@ -26,6 +26,7 @@ typedef s32 compat_daddr_t;
typedef u32 compat_caddr_t;
typedef __kernel_fsid_t compat_fsid_t;
typedef s32 compat_key_t;
+typedef s32 compat_timer_t;
typedef s32 compat_int_t;
typedef s32 compat_long_t;
diff --git a/include/asm-ppc64/dma.h b/include/asm-ppc64/dma.h
index d693b8026bc..dfd1f69059b 100644
--- a/include/asm-ppc64/dma.h
+++ b/include/asm-ppc64/dma.h
@@ -27,6 +27,8 @@
/* Doesn't really apply... */
#define MAX_DMA_ADDRESS (~0UL)
+#if !defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI)
+
#define dma_outb outb
#define dma_inb inb
@@ -323,4 +325,5 @@ extern int isa_dma_bridge_buggy;
#else
#define isa_dma_bridge_buggy (0)
#endif
+#endif /* !defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI) */
#endif /* _ASM_DMA_H */
diff --git a/include/asm-ppc64/elf.h b/include/asm-ppc64/elf.h
index 6c42d61bedd..085eedb956f 100644
--- a/include/asm-ppc64/elf.h
+++ b/include/asm-ppc64/elf.h
@@ -221,9 +221,7 @@ do { \
set_thread_flag(TIF_ABI_PENDING); \
else \
clear_thread_flag(TIF_ABI_PENDING); \
- if (ibcs2) \
- set_personality(PER_SVR4); \
- else if (current->personality != PER_LINUX32) \
+ if (personality(current->personality) != PER_LINUX32) \
set_personality(PER_LINUX); \
} while (0)
diff --git a/include/asm-ppc64/iSeries/HvCall.h b/include/asm-ppc64/iSeries/HvCall.h
index d9a2e74e239..c3f19475c0d 100644
--- a/include/asm-ppc64/iSeries/HvCall.h
+++ b/include/asm-ppc64/iSeries/HvCall.h
@@ -1,84 +1,36 @@
/*
* HvCall.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
- *
+ *
* 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 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
*/
-
-//===========================================================================
-//
-// This file contains the "hypervisor call" interface which is used to
-// drive the hypervisor from the OS.
-//
-//===========================================================================
+/*
+ * This file contains the "hypervisor call" interface which is used to
+ * drive the hypervisor from the OS.
+ */
#ifndef _HVCALL_H
#define _HVCALL_H
-//-------------------------------------------------------------------
-// Standard Includes
-//-------------------------------------------------------------------
#include <asm/iSeries/HvCallSc.h>
#include <asm/iSeries/HvTypes.h>
#include <asm/paca.h>
-/*
-enum HvCall_ReturnCode
-{
- HvCall_Good = 0,
- HvCall_Partial = 1,
- HvCall_NotOwned = 2,
- HvCall_NotFreed = 3,
- HvCall_UnspecifiedError = 4
-};
-
-enum HvCall_TypeOfSIT
-{
- HvCall_ReduceOnly = 0,
- HvCall_Unconditional = 1
-};
-
-enum HvCall_TypeOfYield
-{
- HvCall_YieldTimed = 0, // Yield until specified time
- HvCall_YieldToActive = 1, // Yield until all active procs have run
- HvCall_YieldToProc = 2 // Yield until the specified processor has run
-};
-
-enum HvCall_InterruptMasks
-{
- HvCall_MaskIPI = 0x00000001,
- HvCall_MaskLpEvent = 0x00000002,
- HvCall_MaskLpProd = 0x00000004,
- HvCall_MaskTimeout = 0x00000008
-};
-
-enum HvCall_VaryOffChunkRc
-{
- HvCall_VaryOffSucceeded = 0,
- HvCall_VaryOffWithdrawn = 1,
- HvCall_ChunkInLoadArea = 2,
- HvCall_ChunkInHPT = 3,
- HvCall_ChunkNotAccessible = 4,
- HvCall_ChunkInUse = 5
-};
-*/
-
/* Type of yield for HvCallBaseYieldProcessor */
-#define HvCall_YieldTimed 0 // Yield until specified time (tb)
-#define HvCall_YieldToActive 1 // Yield until all active procs have run
-#define HvCall_YieldToProc 2 // Yield until the specified processor has run
+#define HvCall_YieldTimed 0 /* Yield until specified time (tb) */
+#define HvCall_YieldToActive 1 /* Yield until all active procs have run */
+#define HvCall_YieldToProc 2 /* Yield until the specified processor has run */
/* interrupt masks for setEnabledInterrupts */
#define HvCall_MaskIPI 0x00000001
@@ -86,7 +38,7 @@ enum HvCall_VaryOffChunkRc
#define HvCall_MaskLpProd 0x00000004
#define HvCall_MaskTimeout 0x00000008
-/* Log buffer formats */
+/* Log buffer formats */
#define HvCall_LogBuffer_ASCII 0
#define HvCall_LogBuffer_EBCDIC 1
@@ -95,7 +47,7 @@ enum HvCall_VaryOffChunkRc
#define HvCallBaseGetHwPatch HvCallBase + 2
#define HvCallBaseReIplSpAttn HvCallBase + 3
#define HvCallBaseSetASR HvCallBase + 4
-#define HvCallBaseSetASRAndRfi HvCallBase + 5
+#define HvCallBaseSetASRAndRfi HvCallBase + 5
#define HvCallBaseSetIMR HvCallBase + 6
#define HvCallBaseSendIPI HvCallBase + 7
#define HvCallBaseTerminateMachine HvCallBase + 8
@@ -115,91 +67,47 @@ enum HvCall_VaryOffChunkRc
#define HvCallBaseGetLogBufferCodePage HvCallBase + 22
#define HvCallBaseGetLogBufferFormat HvCallBase + 23
#define HvCallBaseGetLogBufferLength HvCallBase + 24
-#define HvCallBaseReadLogBuffer HvCallBase + 25
+#define HvCallBaseReadLogBuffer HvCallBase + 25
#define HvCallBaseSetLogBufferFormatAndCodePage HvCallBase + 26
-#define HvCallBaseWriteLogBuffer HvCallBase + 27
+#define HvCallBaseWriteLogBuffer HvCallBase + 27
#define HvCallBaseRouter28 HvCallBase + 28
#define HvCallBaseRouter29 HvCallBase + 29
#define HvCallBaseRouter30 HvCallBase + 30
-#define HvCallBaseSetDebugBus HvCallBase + 31
+#define HvCallBaseSetDebugBus HvCallBase + 31
-#define HvCallCcSetDABR HvCallCc + 7
+#define HvCallCcSetDABR HvCallCc + 7
-//=====================================================================================
-static inline void HvCall_setVirtualDecr(void)
+static inline void HvCall_setVirtualDecr(void)
{
- /* Ignore any error return codes - most likely means that the target value for the
- * LP has been increased and this vary off would bring us below the new target. */
+ /*
+ * Ignore any error return codes - most likely means that the
+ * target value for the LP has been increased and this vary off
+ * would bring us below the new target.
+ */
HvCall0(HvCallBaseSetVirtualDecr);
}
-//=====================================================================
-static inline void HvCall_yieldProcessor(unsigned typeOfYield, u64 yieldParm)
-{
- HvCall2( HvCallBaseYieldProcessor, typeOfYield, yieldParm );
-}
-//=====================================================================
-static inline void HvCall_setEnabledInterrupts(u64 enabledInterrupts)
-{
- HvCall1(HvCallBaseSetEnabledInterrupts,enabledInterrupts);
-}
-
-//=====================================================================
-static inline void HvCall_clearLogBuffer(HvLpIndex lpindex)
-{
- HvCall1(HvCallBaseClearLogBuffer,lpindex);
-}
-
-//=====================================================================
-static inline u32 HvCall_getLogBufferCodePage(HvLpIndex lpindex)
-{
- u32 retVal = HvCall1(HvCallBaseGetLogBufferCodePage,lpindex);
- return retVal;
-}
-
-//=====================================================================
-static inline int HvCall_getLogBufferFormat(HvLpIndex lpindex)
-{
- int retVal = HvCall1(HvCallBaseGetLogBufferFormat,lpindex);
- return retVal;
-}
-
-//=====================================================================
-static inline u32 HvCall_getLogBufferLength(HvLpIndex lpindex)
-{
- u32 retVal = HvCall1(HvCallBaseGetLogBufferLength,lpindex);
- return retVal;
-}
-//=====================================================================
-static inline void HvCall_setLogBufferFormatAndCodepage(int format, u32 codePage)
+static inline void HvCall_yieldProcessor(unsigned typeOfYield, u64 yieldParm)
{
- HvCall2(HvCallBaseSetLogBufferFormatAndCodePage,format, codePage);
+ HvCall2(HvCallBaseYieldProcessor, typeOfYield, yieldParm);
}
-//=====================================================================
-int HvCall_readLogBuffer(HvLpIndex lpindex, void *buffer, u64 bufLen);
-void HvCall_writeLogBuffer(const void *buffer, u64 bufLen);
-
-//=====================================================================
-static inline void HvCall_sendIPI(struct paca_struct * targetPaca)
+static inline void HvCall_setEnabledInterrupts(u64 enabledInterrupts)
{
- HvCall1( HvCallBaseSendIPI, targetPaca->paca_index );
+ HvCall1(HvCallBaseSetEnabledInterrupts, enabledInterrupts);
}
-//=====================================================================
-static inline void HvCall_terminateMachineSrc(void)
+static inline void HvCall_setLogBufferFormatAndCodepage(int format,
+ u32 codePage)
{
- HvCall0( HvCallBaseTerminateMachineSrc );
+ HvCall2(HvCallBaseSetLogBufferFormatAndCodePage, format, codePage);
}
-static inline void HvCall_setDABR(unsigned long val)
-{
- HvCall1(HvCallCcSetDABR, val);
-}
+extern void HvCall_writeLogBuffer(const void *buffer, u64 bufLen);
-static inline void HvCall_setDebugBus(unsigned long val)
+static inline void HvCall_sendIPI(struct paca_struct *targetPaca)
{
- HvCall1(HvCallBaseSetDebugBus, val);
+ HvCall1(HvCallBaseSendIPI, targetPaca->paca_index);
}
#endif /* _HVCALL_H */
diff --git a/include/asm-ppc64/iSeries/HvCallCfg.h b/include/asm-ppc64/iSeries/HvCallCfg.h
deleted file mode 100644
index 9f40f16de53..00000000000
--- a/include/asm-ppc64/iSeries/HvCallCfg.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * HvCallCfg.h
- * Copyright (C) 2001 Mike Corrigan IBM Corporation
- *
- * 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 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
- */
-
-//=====================================================================================
-//
-// This file contains the "hypervisor call" interface which is used to
-// drive the hypervisor from the OS.
-//
-//=====================================================================================
-#ifndef _HVCALLCFG_H
-#define _HVCALLCFG_H
-
-//-------------------------------------------------------------------
-// Standard Includes
-//-------------------------------------------------------------------
-#include <asm/iSeries/HvCallSc.h>
-#include <asm/iSeries/HvTypes.h>
-
-//-------------------------------------------------------------------------------------
-// Constants
-//-------------------------------------------------------------------------------------
-
-enum HvCallCfg_ReqQual
-{
- HvCallCfg_Cur = 0,
- HvCallCfg_Init = 1,
- HvCallCfg_Max = 2,
- HvCallCfg_Min = 3
-};
-
-#define HvCallCfgGetLps HvCallCfg + 0
-#define HvCallCfgGetActiveLpMap HvCallCfg + 1
-#define HvCallCfgGetLpVrmIndex HvCallCfg + 2
-#define HvCallCfgGetLpMinSupportedPlicVrmIndex HvCallCfg + 3
-#define HvCallCfgGetLpMinCompatablePlicVrmIndex HvCallCfg + 4
-#define HvCallCfgGetLpVrmName HvCallCfg + 5
-#define HvCallCfgGetSystemPhysicalProcessors HvCallCfg + 6
-#define HvCallCfgGetPhysicalProcessors HvCallCfg + 7
-#define HvCallCfgGetSystemMsChunks HvCallCfg + 8
-#define HvCallCfgGetMsChunks HvCallCfg + 9
-#define HvCallCfgGetInteractivePercentage HvCallCfg + 10
-#define HvCallCfgIsBusDedicated HvCallCfg + 11
-#define HvCallCfgGetBusOwner HvCallCfg + 12
-#define HvCallCfgGetBusAllocation HvCallCfg + 13
-#define HvCallCfgGetBusUnitOwner HvCallCfg + 14
-#define HvCallCfgGetBusUnitAllocation HvCallCfg + 15
-#define HvCallCfgGetVirtualBusPool HvCallCfg + 16
-#define HvCallCfgGetBusUnitInterruptProc HvCallCfg + 17
-#define HvCallCfgGetConfiguredBusUnitsForIntProc HvCallCfg + 18
-#define HvCallCfgGetRioSanBusPool HvCallCfg + 19
-#define HvCallCfgGetSharedPoolIndex HvCallCfg + 20
-#define HvCallCfgGetSharedProcUnits HvCallCfg + 21
-#define HvCallCfgGetNumProcsInSharedPool HvCallCfg + 22
-#define HvCallCfgRouter23 HvCallCfg + 23
-#define HvCallCfgRouter24 HvCallCfg + 24
-#define HvCallCfgRouter25 HvCallCfg + 25
-#define HvCallCfgRouter26 HvCallCfg + 26
-#define HvCallCfgRouter27 HvCallCfg + 27
-#define HvCallCfgGetMinRuntimeMsChunks HvCallCfg + 28
-#define HvCallCfgSetMinRuntimeMsChunks HvCallCfg + 29
-#define HvCallCfgGetVirtualLanIndexMap HvCallCfg + 30
-#define HvCallCfgGetLpExecutionMode HvCallCfg + 31
-#define HvCallCfgGetHostingLpIndex HvCallCfg + 32
-
-//====================================================================
-static inline HvLpIndex HvCallCfg_getLps(void)
-{
- HvLpIndex retVal = HvCall0(HvCallCfgGetLps);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
-}
-//====================================================================
-static inline int HvCallCfg_isBusDedicated(u64 busIndex)
-{
- int retVal = HvCall1(HvCallCfgIsBusDedicated,busIndex);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
-}
-//====================================================================
-static inline HvLpIndex HvCallCfg_getBusOwner(u64 busIndex)
-{
- HvLpIndex retVal = HvCall1(HvCallCfgGetBusOwner,busIndex);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
-}
-//====================================================================
-static inline HvLpIndexMap HvCallCfg_getBusAllocation(u64 busIndex)
-{
- HvLpIndexMap retVal = HvCall1(HvCallCfgGetBusAllocation,busIndex);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
-}
-//====================================================================
-static inline HvLpIndexMap HvCallCfg_getActiveLpMap(void)
-{
- HvLpIndexMap retVal = HvCall0(HvCallCfgGetActiveLpMap);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
-}
-//====================================================================
-static inline HvLpVirtualLanIndexMap HvCallCfg_getVirtualLanIndexMap(HvLpIndex lp)
-{
- // This is a new function in V5R1 so calls to this on older
- // hypervisors will return -1
- u64 retVal = HvCall1(HvCallCfgGetVirtualLanIndexMap, lp);
- if(retVal == -1)
- retVal = 0;
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
-}
-//===================================================================
-static inline u64 HvCallCfg_getSystemMsChunks(void)
-{
- u64 retVal = HvCall0(HvCallCfgGetSystemMsChunks);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
-}
-//===================================================================
-static inline u64 HvCallCfg_getMsChunks(HvLpIndex lp,enum HvCallCfg_ReqQual qual)
-{
- u64 retVal = HvCall2(HvCallCfgGetMsChunks,lp,qual);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
-}
-//===================================================================
-static inline u64 HvCallCfg_getMinRuntimeMsChunks(HvLpIndex lp)
-{
- // NOTE: This function was added in v5r1 so older hypervisors will return a -1 value
- u64 retVal = HvCall1(HvCallCfgGetMinRuntimeMsChunks,lp);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
-}
-//===================================================================
-static inline u64 HvCallCfg_setMinRuntimeMsChunks(u64 chunks)
-{
- u64 retVal = HvCall1(HvCallCfgSetMinRuntimeMsChunks,chunks);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
-}
-//===================================================================
-static inline u64 HvCallCfg_getSystemPhysicalProcessors(void)
-{
- u64 retVal = HvCall0(HvCallCfgGetSystemPhysicalProcessors);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
-}
-//===================================================================
-static inline u64 HvCallCfg_getPhysicalProcessors(HvLpIndex lp,enum HvCallCfg_ReqQual qual)
-{
- u64 retVal = HvCall2(HvCallCfgGetPhysicalProcessors,lp,qual);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
-}
-//===================================================================
-static inline u64 HvCallCfg_getConfiguredBusUnitsForInterruptProc(HvLpIndex lp,
- u16 hvLogicalProcIndex)
-{
- u64 retVal = HvCall2(HvCallCfgGetConfiguredBusUnitsForIntProc,lp,hvLogicalProcIndex);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
-
-}
-//==================================================================
-static inline HvLpSharedPoolIndex HvCallCfg_getSharedPoolIndex(HvLpIndex lp)
-{
- HvLpSharedPoolIndex retVal =
- HvCall1(HvCallCfgGetSharedPoolIndex,lp);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
-
-}
-//==================================================================
-static inline u64 HvCallCfg_getSharedProcUnits(HvLpIndex lp,enum HvCallCfg_ReqQual qual)
-{
- u64 retVal = HvCall2(HvCallCfgGetSharedProcUnits,lp,qual);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
-
-}
-//==================================================================
-static inline u64 HvCallCfg_getNumProcsInSharedPool(HvLpSharedPoolIndex sPI)
-{
- u16 retVal = HvCall1(HvCallCfgGetNumProcsInSharedPool,sPI);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
-
-}
-//==================================================================
-static inline HvLpIndex HvCallCfg_getHostingLpIndex(HvLpIndex lp)
-{
- u64 retVal = HvCall1(HvCallCfgGetHostingLpIndex,lp);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
-
-}
-
-#endif /* _HVCALLCFG_H */
diff --git a/include/asm-ppc64/iSeries/HvCallEvent.h b/include/asm-ppc64/iSeries/HvCallEvent.h
index 191ddce0c2c..5d9a327d012 100644
--- a/include/asm-ppc64/iSeries/HvCallEvent.h
+++ b/include/asm-ppc64/iSeries/HvCallEvent.h
@@ -1,32 +1,28 @@
/*
* HvCallEvent.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
- *
+ *
* 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 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
*/
-
/*
- * This file contains the "hypervisor call" interface which is used to
- * drive the hypervisor from the OS.
+ * This file contains the "hypervisor call" interface which is used to
+ * drive the hypervisor from the OS.
*/
#ifndef _HVCALLEVENT_H
#define _HVCALLEVENT_H
-/*
- * Standard Includes
- */
#include <asm/iSeries/HvCallSc.h>
#include <asm/iSeries/HvTypes.h>
#include <asm/abs_addr.h>
@@ -71,7 +67,7 @@ typedef u64 HvLpDma_Rc;
#define HvCallEventCloseLpEventPath HvCallEvent + 2
#define HvCallEventDmaBufList HvCallEvent + 3
#define HvCallEventDmaSingle HvCallEvent + 4
-#define HvCallEventDmaToSp HvCallEvent + 5
+#define HvCallEventDmaToSp HvCallEvent + 5
#define HvCallEventGetOverflowLpEvents HvCallEvent + 6
#define HvCallEventGetSourceLpInstanceId HvCallEvent + 7
#define HvCallEventGetTargetLpInstanceId HvCallEvent + 8
@@ -85,14 +81,12 @@ typedef u64 HvLpDma_Rc;
static inline void HvCallEvent_getOverflowLpEvents(u8 queueIndex)
{
- HvCall1(HvCallEventGetOverflowLpEvents,queueIndex);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
+ HvCall1(HvCallEventGetOverflowLpEvents, queueIndex);
}
static inline void HvCallEvent_setInterLpQueueIndex(u8 queueIndex)
{
- HvCall1(HvCallEventSetInterLpQueueIndex,queueIndex);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
+ HvCall1(HvCallEventSetInterLpQueueIndex, queueIndex);
}
static inline void HvCallEvent_setLpEventStack(u8 queueIndex,
@@ -103,7 +97,6 @@ static inline void HvCallEvent_setLpEventStack(u8 queueIndex,
abs_addr = virt_to_abs(eventStackAddr);
HvCall3(HvCallEventSetLpEventStack, queueIndex, abs_addr,
eventStackSize);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
}
static inline void HvCallEvent_setLpEventQueueInterruptProc(u8 queueIndex,
@@ -111,22 +104,18 @@ static inline void HvCallEvent_setLpEventQueueInterruptProc(u8 queueIndex,
{
HvCall2(HvCallEventSetLpEventQueueInterruptProc, queueIndex,
lpLogicalProcIndex);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
}
static inline HvLpEvent_Rc HvCallEvent_signalLpEvent(struct HvLpEvent *event)
{
u64 abs_addr;
- HvLpEvent_Rc retVal;
#ifdef DEBUG_SENDEVENT
printk("HvCallEvent_signalLpEvent: *event = %016lx\n ",
(unsigned long)event);
#endif
abs_addr = virt_to_abs(event);
- retVal = (HvLpEvent_Rc)HvCall1(HvCallEventSignalLpEvent, abs_addr);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
+ return HvCall1(HvCallEventSignalLpEvent, abs_addr);
}
static inline HvLpEvent_Rc HvCallEvent_signalLpEventFast(HvLpIndex targetLp,
@@ -136,9 +125,7 @@ static inline HvLpEvent_Rc HvCallEvent_signalLpEventFast(HvLpIndex targetLp,
u64 eventData1, u64 eventData2, u64 eventData3,
u64 eventData4, u64 eventData5)
{
- HvLpEvent_Rc retVal;
-
- // Pack the misc bits into a single Dword to pass to PLIC
+ /* Pack the misc bits into a single Dword to pass to PLIC */
union {
struct HvCallEvent_PackedParms parms;
u64 dword;
@@ -152,67 +139,49 @@ static inline HvLpEvent_Rc HvCallEvent_signalLpEventFast(HvLpIndex targetLp,
packed.parms.xSourceInstId = sourceInstanceId;
packed.parms.xTargetInstId = targetInstanceId;
- retVal = (HvLpEvent_Rc)HvCall7(HvCallEventSignalLpEventParms,
- packed.dword, correlationToken, eventData1,eventData2,
- eventData3,eventData4, eventData5);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
+ return HvCall7(HvCallEventSignalLpEventParms, packed.dword,
+ correlationToken, eventData1, eventData2,
+ eventData3, eventData4, eventData5);
}
static inline HvLpEvent_Rc HvCallEvent_ackLpEvent(struct HvLpEvent *event)
{
u64 abs_addr;
- HvLpEvent_Rc retVal;
abs_addr = virt_to_abs(event);
- retVal = (HvLpEvent_Rc)HvCall1(HvCallEventAckLpEvent, abs_addr);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
+ return HvCall1(HvCallEventAckLpEvent, abs_addr);
}
static inline HvLpEvent_Rc HvCallEvent_cancelLpEvent(struct HvLpEvent *event)
{
u64 abs_addr;
- HvLpEvent_Rc retVal;
abs_addr = virt_to_abs(event);
- retVal = (HvLpEvent_Rc)HvCall1(HvCallEventCancelLpEvent, abs_addr);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
+ return HvCall1(HvCallEventCancelLpEvent, abs_addr);
}
static inline HvLpInstanceId HvCallEvent_getSourceLpInstanceId(
HvLpIndex targetLp, HvLpEvent_Type type)
{
- HvLpInstanceId retVal;
-
- retVal = HvCall2(HvCallEventGetSourceLpInstanceId, targetLp, type);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
+ return HvCall2(HvCallEventGetSourceLpInstanceId, targetLp, type);
}
static inline HvLpInstanceId HvCallEvent_getTargetLpInstanceId(
HvLpIndex targetLp, HvLpEvent_Type type)
{
- HvLpInstanceId retVal;
-
- retVal = HvCall2(HvCallEventGetTargetLpInstanceId, targetLp, type);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
+ return HvCall2(HvCallEventGetTargetLpInstanceId, targetLp, type);
}
static inline void HvCallEvent_openLpEventPath(HvLpIndex targetLp,
HvLpEvent_Type type)
{
HvCall2(HvCallEventOpenLpEventPath, targetLp, type);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
}
static inline void HvCallEvent_closeLpEventPath(HvLpIndex targetLp,
HvLpEvent_Type type)
{
HvCall2(HvCallEventCloseLpEventPath, targetLp, type);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
}
static inline HvLpDma_Rc HvCallEvent_dmaBufList(HvLpEvent_Type type,
@@ -224,8 +193,7 @@ static inline HvLpDma_Rc HvCallEvent_dmaBufList(HvLpEvent_Type type,
/* Do these need to be converted to absolute addresses? */
u64 localBufList, u64 remoteBufList, u32 transferLength)
{
- HvLpDma_Rc retVal;
- // Pack the misc bits into a single Dword to pass to PLIC
+ /* Pack the misc bits into a single Dword to pass to PLIC */
union {
struct HvCallEvent_PackedDmaParms parms;
u64 dword;
@@ -241,11 +209,8 @@ static inline HvLpDma_Rc HvCallEvent_dmaBufList(HvLpEvent_Type type,
packed.parms.xLocalInstId = localInstanceId;
packed.parms.xRemoteInstId = remoteInstanceId;
- retVal = (HvLpDma_Rc)HvCall4(HvCallEventDmaBufList,
- packed.dword, localBufList, remoteBufList,
- transferLength);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
+ return HvCall4(HvCallEventDmaBufList, packed.dword, localBufList,
+ remoteBufList, transferLength);
}
static inline HvLpDma_Rc HvCallEvent_dmaSingle(HvLpEvent_Type type,
@@ -256,8 +221,7 @@ static inline HvLpDma_Rc HvCallEvent_dmaSingle(HvLpEvent_Type type,
HvLpDma_AddressType remoteAddressType,
u64 localAddrOrTce, u64 remoteAddrOrTce, u32 transferLength)
{
- HvLpDma_Rc retVal;
- // Pack the misc bits into a single Dword to pass to PLIC
+ /* Pack the misc bits into a single Dword to pass to PLIC */
union {
struct HvCallEvent_PackedDmaParms parms;
u64 dword;
@@ -273,25 +237,17 @@ static inline HvLpDma_Rc HvCallEvent_dmaSingle(HvLpEvent_Type type,
packed.parms.xLocalInstId = localInstanceId;
packed.parms.xRemoteInstId = remoteInstanceId;
- retVal = (HvLpDma_Rc)HvCall4(HvCallEventDmaSingle,
- packed.dword, localAddrOrTce, remoteAddrOrTce,
- transferLength);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
+ return (HvLpDma_Rc)HvCall4(HvCallEventDmaSingle, packed.dword,
+ localAddrOrTce, remoteAddrOrTce, transferLength);
}
-static inline HvLpDma_Rc HvCallEvent_dmaToSp(void* local, u32 remote,
+static inline HvLpDma_Rc HvCallEvent_dmaToSp(void *local, u32 remote,
u32 length, HvLpDma_Direction dir)
{
u64 abs_addr;
- HvLpDma_Rc retVal;
abs_addr = virt_to_abs(local);
- retVal = (HvLpDma_Rc)HvCall4(HvCallEventDmaToSp, abs_addr, remote,
- length, dir);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
+ return HvCall4(HvCallEventDmaToSp, abs_addr, remote, length, dir);
}
-
#endif /* _HVCALLEVENT_H */
diff --git a/include/asm-ppc64/iSeries/HvCallHpt.h b/include/asm-ppc64/iSeries/HvCallHpt.h
index da769873d18..66f38222ff7 100644
--- a/include/asm-ppc64/iSeries/HvCallHpt.h
+++ b/include/asm-ppc64/iSeries/HvCallHpt.h
@@ -1,17 +1,17 @@
/*
* HvCallHpt.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
- *
+ *
* 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 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
@@ -19,21 +19,15 @@
#ifndef _HVCALLHPT_H
#define _HVCALLHPT_H
-//============================================================================
-//
-// This file contains the "hypervisor call" interface which is used to
-// drive the hypervisor from the OS.
-//
-//============================================================================
+/*
+ * This file contains the "hypervisor call" interface which is used to
+ * drive the hypervisor from the OS.
+ */
#include <asm/iSeries/HvCallSc.h>
#include <asm/iSeries/HvTypes.h>
#include <asm/mmu.h>
-//-----------------------------------------------------------------------------
-// Constants
-//-----------------------------------------------------------------------------
-
#define HvCallHptGetHptAddress HvCallHpt + 0
#define HvCallHptGetHptPages HvCallHpt + 1
#define HvCallHptSetPp HvCallHpt + 5
@@ -47,81 +41,63 @@
#define HvCallHptInvalidateSetSwBitsGet HvCallHpt + 18
-//============================================================================
-static inline u64 HvCallHpt_getHptAddress(void)
+static inline u64 HvCallHpt_getHptAddress(void)
{
- u64 retval = HvCall0(HvCallHptGetHptAddress);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retval;
+ return HvCall0(HvCallHptGetHptAddress);
}
-//============================================================================
-static inline u64 HvCallHpt_getHptPages(void)
-{
- u64 retval = HvCall0(HvCallHptGetHptPages);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retval;
+
+static inline u64 HvCallHpt_getHptPages(void)
+{
+ return HvCall0(HvCallHptGetHptPages);
}
-//=============================================================================
-static inline void HvCallHpt_setPp(u32 hpteIndex, u8 value)
+
+static inline void HvCallHpt_setPp(u32 hpteIndex, u8 value)
{
- HvCall2( HvCallHptSetPp, hpteIndex, value );
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
+ HvCall2(HvCallHptSetPp, hpteIndex, value);
}
-//=============================================================================
-static inline void HvCallHpt_setSwBits(u32 hpteIndex, u8 bitson, u8 bitsoff )
+
+static inline void HvCallHpt_setSwBits(u32 hpteIndex, u8 bitson, u8 bitsoff)
{
- HvCall3( HvCallHptSetSwBits, hpteIndex, bitson, bitsoff );
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
+ HvCall3(HvCallHptSetSwBits, hpteIndex, bitson, bitsoff);
}
-//=============================================================================
-static inline void HvCallHpt_invalidateNoSyncICache(u32 hpteIndex)
-
+
+static inline void HvCallHpt_invalidateNoSyncICache(u32 hpteIndex)
{
- HvCall1( HvCallHptInvalidateNoSyncICache, hpteIndex );
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
+ HvCall1(HvCallHptInvalidateNoSyncICache, hpteIndex);
}
-//=============================================================================
-static inline u64 HvCallHpt_invalidateSetSwBitsGet(u32 hpteIndex, u8 bitson, u8 bitsoff )
-
+
+static inline u64 HvCallHpt_invalidateSetSwBitsGet(u32 hpteIndex, u8 bitson,
+ u8 bitsoff)
{
u64 compressedStatus;
- compressedStatus = HvCall4( HvCallHptInvalidateSetSwBitsGet, hpteIndex, bitson, bitsoff, 1 );
- HvCall1( HvCallHptInvalidateNoSyncICache, hpteIndex );
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
+
+ compressedStatus = HvCall4(HvCallHptInvalidateSetSwBitsGet,
+ hpteIndex, bitson, bitsoff, 1);
+ HvCall1(HvCallHptInvalidateNoSyncICache, hpteIndex);
return compressedStatus;
}
-//=============================================================================
-static inline u64 HvCallHpt_findValid( HPTE *hpte, u64 vpn )
+
+static inline u64 HvCallHpt_findValid(HPTE *hpte, u64 vpn)
{
- u64 retIndex = HvCall3Ret16( HvCallHptFindValid, hpte, vpn, 0, 0 );
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retIndex;
+ return HvCall3Ret16(HvCallHptFindValid, hpte, vpn, 0, 0);
}
-//=============================================================================
-static inline u64 HvCallHpt_findNextValid( HPTE *hpte, u32 hpteIndex, u8 bitson, u8 bitsoff )
+
+static inline u64 HvCallHpt_findNextValid(HPTE *hpte, u32 hpteIndex,
+ u8 bitson, u8 bitsoff)
{
- u64 retIndex = HvCall3Ret16( HvCallHptFindNextValid, hpte, hpteIndex, bitson, bitsoff );
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retIndex;
+ return HvCall3Ret16(HvCallHptFindNextValid, hpte, hpteIndex,
+ bitson, bitsoff);
}
-//=============================================================================
-static inline void HvCallHpt_get( HPTE *hpte, u32 hpteIndex )
+
+static inline void HvCallHpt_get(HPTE *hpte, u32 hpteIndex)
{
- HvCall2Ret16( HvCallHptGet, hpte, hpteIndex, 0 );
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
+ HvCall2Ret16(HvCallHptGet, hpte, hpteIndex, 0);
}
-//============================================================================
-static inline void HvCallHpt_addValidate( u32 hpteIndex,
- u32 hBit,
- HPTE *hpte )
-
+
+static inline void HvCallHpt_addValidate(u32 hpteIndex, u32 hBit, HPTE *hpte)
{
- HvCall4( HvCallHptAddValidate, hpteIndex,
- hBit, (*((u64 *)hpte)), (*(((u64 *)hpte)+1)) );
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
+ HvCall4(HvCallHptAddValidate, hpteIndex, hBit, (*((u64 *)hpte)),
+ (*(((u64 *)hpte)+1)));
}
-
-//=============================================================================
-
#endif /* _HVCALLHPT_H */
diff --git a/include/asm-ppc64/iSeries/HvCallPci.h b/include/asm-ppc64/iSeries/HvCallPci.h
index 6887b619288..c8d675c40f5 100644
--- a/include/asm-ppc64/iSeries/HvCallPci.h
+++ b/include/asm-ppc64/iSeries/HvCallPci.h
@@ -1,26 +1,26 @@
-/************************************************************************/
-/* Provides the Hypervisor PCI calls for iSeries Linux Parition. */
-/* Copyright (C) 2001 <Wayne G Holm> <IBM Corporation> */
-/* */
-/* 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 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 */
-/************************************************************************/
-/* Change Activity: */
-/* Created, Jan 9, 2001 */
-/************************************************************************/
+/*
+ * Provides the Hypervisor PCI calls for iSeries Linux Parition.
+ * Copyright (C) 2001 <Wayne G Holm> <IBM Corporation>
+ *
+ * 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 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
+ *
+ * Change Activity:
+ * Created, Jan 9, 2001
+ */
#ifndef _HVCALLPCI_H
#define _HVCALLPCI_H
@@ -34,8 +34,8 @@
*/
struct HvCallPci_DsaAddr {
u16 busNumber; /* PHB index? */
- u8 subBusNumber; /* PCI bus number? */
- u8 deviceId; /* device and function? */
+ u8 subBusNumber; /* PCI bus number? */
+ u8 deviceId; /* device and function? */
u8 barNumber;
u8 reserved[3];
};
@@ -52,34 +52,37 @@ struct HvCallPci_LoadReturn {
enum HvCallPci_DeviceType {
HvCallPci_NodeDevice = 1,
- HvCallPci_SpDevice = 2,
- HvCallPci_IopDevice = 3,
- HvCallPci_BridgeDevice = 4,
- HvCallPci_MultiFunctionDevice = 5,
- HvCallPci_IoaDevice = 6
+ HvCallPci_SpDevice = 2,
+ HvCallPci_IopDevice = 3,
+ HvCallPci_BridgeDevice = 4,
+ HvCallPci_MultiFunctionDevice = 5,
+ HvCallPci_IoaDevice = 6
};
struct HvCallPci_DeviceInfo {
- u32 deviceType; // See DeviceType enum for values
+ u32 deviceType; /* See DeviceType enum for values */
};
-
+
struct HvCallPci_BusUnitInfo {
- u32 sizeReturned; // length of data returned
- u32 deviceType; // see DeviceType enum for values
+ u32 sizeReturned; /* length of data returned */
+ u32 deviceType; /* see DeviceType enum for values */
};
struct HvCallPci_BridgeInfo {
- struct HvCallPci_BusUnitInfo busUnitInfo; // Generic bus unit info
- u8 subBusNumber; // Bus number of secondary bus
- u8 maxAgents; // Max idsels on secondary bus
- u8 maxSubBusNumber; // Max Sub Bus
- u8 logicalSlotNumber; // Logical Slot Number for IOA
+ struct HvCallPci_BusUnitInfo busUnitInfo; /* Generic bus unit info */
+ u8 subBusNumber; /* Bus number of secondary bus */
+ u8 maxAgents; /* Max idsels on secondary bus */
+ u8 maxSubBusNumber; /* Max Sub Bus */
+ u8 logicalSlotNumber; /* Logical Slot Number for IOA */
};
-
-// Maximum BusUnitInfo buffer size. Provided for clients so they can allocate
-// a buffer big enough for any type of bus unit. Increase as needed.
+
+/*
+ * Maximum BusUnitInfo buffer size. Provided for clients so
+ * they can allocate a buffer big enough for any type of bus
+ * unit. Increase as needed.
+ */
enum {HvCallPci_MaxBusUnitInfoSize = 128};
struct HvCallPci_BarParms {
@@ -89,12 +92,12 @@ struct HvCallPci_BarParms {
u64 protectStart;
u64 protectEnd;
u64 relocationOffset;
- u64 pciAddress;
+ u64 pciAddress;
u64 reserved[3];
-};
+};
enum HvCallPci_VpdType {
- HvCallPci_BusVpd = 1,
+ HvCallPci_BusVpd = 1,
HvCallPci_BusAdapterVpd = 2
};
@@ -123,15 +126,13 @@ enum HvCallPci_VpdType {
#define HvCallPciUnmaskInterrupts HvCallPci + 49
#define HvCallPciGetBusUnitInfo HvCallPci + 50
-//============================================================================
static inline u64 HvCallPci_configLoad8(u16 busNumber, u8 subBusNumber,
- u8 deviceId, u32 offset,
- u8 *value)
+ u8 deviceId, u32 offset, u8 *value)
{
struct HvCallPci_DsaAddr dsa;
struct HvCallPci_LoadReturn retVal;
- *((u64*)&dsa) = 0;
+ *((u64*)&dsa) = 0;
dsa.busNumber = busNumber;
dsa.subBusNumber = subBusNumber;
@@ -139,21 +140,18 @@ static inline u64 HvCallPci_configLoad8(u16 busNumber, u8 subBusNumber,
HvCall3Ret16(HvCallPciConfigLoad8, &retVal, *(u64 *)&dsa, offset, 0);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
*value = retVal.value;
return retVal.rc;
}
-//============================================================================
+
static inline u64 HvCallPci_configLoad16(u16 busNumber, u8 subBusNumber,
- u8 deviceId, u32 offset,
- u16 *value)
+ u8 deviceId, u32 offset, u16 *value)
{
struct HvCallPci_DsaAddr dsa;
struct HvCallPci_LoadReturn retVal;
- *((u64*)&dsa) = 0;
+ *((u64*)&dsa) = 0;
dsa.busNumber = busNumber;
dsa.subBusNumber = subBusNumber;
@@ -161,21 +159,18 @@ static inline u64 HvCallPci_configLoad16(u16 busNumber, u8 subBusNumber,
HvCall3Ret16(HvCallPciConfigLoad16, &retVal, *(u64 *)&dsa, offset, 0);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
*value = retVal.value;
return retVal.rc;
}
-//============================================================================
-static inline u64 HvCallPci_configLoad32(u16 busNumber, u8 subBusNumber,
- u8 deviceId, u32 offset,
- u32 *value)
+
+static inline u64 HvCallPci_configLoad32(u16 busNumber, u8 subBusNumber,
+ u8 deviceId, u32 offset, u32 *value)
{
struct HvCallPci_DsaAddr dsa;
struct HvCallPci_LoadReturn retVal;
- *((u64*)&dsa) = 0;
+ *((u64*)&dsa) = 0;
dsa.busNumber = busNumber;
dsa.subBusNumber = subBusNumber;
@@ -183,84 +178,61 @@ static inline u64 HvCallPci_configLoad32(u16 busNumber, u8 subBusNumber,
HvCall3Ret16(HvCallPciConfigLoad32, &retVal, *(u64 *)&dsa, offset, 0);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
*value = retVal.value;
return retVal.rc;
}
-//============================================================================
-static inline u64 HvCallPci_configStore8(u16 busNumber, u8 subBusNumber,
- u8 deviceId, u32 offset,
- u8 value)
+
+static inline u64 HvCallPci_configStore8(u16 busNumber, u8 subBusNumber,
+ u8 deviceId, u32 offset, u8 value)
{
struct HvCallPci_DsaAddr dsa;
- u64 retVal;
- *((u64*)&dsa) = 0;
+ *((u64*)&dsa) = 0;
dsa.busNumber = busNumber;
dsa.subBusNumber = subBusNumber;
dsa.deviceId = deviceId;
- retVal = HvCall4(HvCallPciConfigStore8, *(u64 *)&dsa, offset, value, 0);
-
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
- return retVal;
+ return HvCall4(HvCallPciConfigStore8, *(u64 *)&dsa, offset, value, 0);
}
-//============================================================================
-static inline u64 HvCallPci_configStore16(u16 busNumber, u8 subBusNumber,
- u8 deviceId, u32 offset,
- u16 value)
+
+static inline u64 HvCallPci_configStore16(u16 busNumber, u8 subBusNumber,
+ u8 deviceId, u32 offset, u16 value)
{
struct HvCallPci_DsaAddr dsa;
- u64 retVal;
- *((u64*)&dsa) = 0;
+ *((u64*)&dsa) = 0;
dsa.busNumber = busNumber;
dsa.subBusNumber = subBusNumber;
dsa.deviceId = deviceId;
- retVal = HvCall4(HvCallPciConfigStore16, *(u64 *)&dsa, offset, value, 0);
-
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
- return retVal;
+ return HvCall4(HvCallPciConfigStore16, *(u64 *)&dsa, offset, value, 0);
}
-//============================================================================
-static inline u64 HvCallPci_configStore32(u16 busNumber, u8 subBusNumber,
- u8 deviceId, u32 offset,
- u32 value)
+
+static inline u64 HvCallPci_configStore32(u16 busNumber, u8 subBusNumber,
+ u8 deviceId, u32 offset, u32 value)
{
struct HvCallPci_DsaAddr dsa;
- u64 retVal;
- *((u64*)&dsa) = 0;
+ *((u64*)&dsa) = 0;
dsa.busNumber = busNumber;
dsa.subBusNumber = subBusNumber;
dsa.deviceId = deviceId;
- retVal = HvCall4(HvCallPciConfigStore32, *(u64 *)&dsa, offset, value, 0);
-
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
- return retVal;
+ return HvCall4(HvCallPciConfigStore32, *(u64 *)&dsa, offset, value, 0);
}
-//============================================================================
-static inline u64 HvCallPci_barLoad8(u16 busNumberParm,
- u8 subBusParm,
- u8 deviceIdParm,
- u8 barNumberParm,
- u64 offsetParm,
- u8* valueParm)
+
+static inline u64 HvCallPci_barLoad8(u16 busNumberParm, u8 subBusParm,
+ u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+ u8 *valueParm)
{
struct HvCallPci_DsaAddr dsa;
struct HvCallPci_LoadReturn retVal;
- *((u64*)&dsa) = 0;
+ *((u64*)&dsa) = 0;
dsa.busNumber = busNumberParm;
dsa.subBusNumber = subBusParm;
@@ -269,24 +241,19 @@ static inline u64 HvCallPci_barLoad8(u16 busNumberParm,
HvCall3Ret16(HvCallPciBarLoad8, &retVal, *(u64 *)&dsa, offsetParm, 0);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
*valueParm = retVal.value;
return retVal.rc;
}
-//============================================================================
-static inline u64 HvCallPci_barLoad16(u16 busNumberParm,
- u8 subBusParm,
- u8 deviceIdParm,
- u8 barNumberParm,
- u64 offsetParm,
- u16* valueParm)
+
+static inline u64 HvCallPci_barLoad16(u16 busNumberParm, u8 subBusParm,
+ u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+ u16 *valueParm)
{
struct HvCallPci_DsaAddr dsa;
struct HvCallPci_LoadReturn retVal;
- *((u64*)&dsa) = 0;
+ *((u64*)&dsa) = 0;
dsa.busNumber = busNumberParm;
dsa.subBusNumber = subBusParm;
@@ -295,24 +262,19 @@ static inline u64 HvCallPci_barLoad16(u16 busNumberParm,
HvCall3Ret16(HvCallPciBarLoad16, &retVal, *(u64 *)&dsa, offsetParm, 0);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
*valueParm = retVal.value;
return retVal.rc;
}
-//============================================================================
-static inline u64 HvCallPci_barLoad32(u16 busNumberParm,
- u8 subBusParm,
- u8 deviceIdParm,
- u8 barNumberParm,
- u64 offsetParm,
- u32* valueParm)
+
+static inline u64 HvCallPci_barLoad32(u16 busNumberParm, u8 subBusParm,
+ u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+ u32 *valueParm)
{
struct HvCallPci_DsaAddr dsa;
struct HvCallPci_LoadReturn retVal;
- *((u64*)&dsa) = 0;
+ *((u64*)&dsa) = 0;
dsa.busNumber = busNumberParm;
dsa.subBusNumber = subBusParm;
@@ -321,24 +283,19 @@ static inline u64 HvCallPci_barLoad32(u16 busNumberParm,
HvCall3Ret16(HvCallPciBarLoad32, &retVal, *(u64 *)&dsa, offsetParm, 0);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
*valueParm = retVal.value;
return retVal.rc;
}
-//============================================================================
-static inline u64 HvCallPci_barLoad64(u16 busNumberParm,
- u8 subBusParm,
- u8 deviceIdParm,
- u8 barNumberParm,
- u64 offsetParm,
- u64* valueParm)
+
+static inline u64 HvCallPci_barLoad64(u16 busNumberParm, u8 subBusParm,
+ u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+ u64 *valueParm)
{
struct HvCallPci_DsaAddr dsa;
struct HvCallPci_LoadReturn retVal;
- *((u64*)&dsa) = 0;
+ *((u64*)&dsa) = 0;
dsa.busNumber = busNumberParm;
dsa.subBusNumber = subBusParm;
@@ -347,112 +304,81 @@ static inline u64 HvCallPci_barLoad64(u16 busNumberParm,
HvCall3Ret16(HvCallPciBarLoad64, &retVal, *(u64 *)&dsa, offsetParm, 0);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
*valueParm = retVal.value;
return retVal.rc;
}
-//============================================================================
-static inline u64 HvCallPci_barStore8(u16 busNumberParm,
- u8 subBusParm,
- u8 deviceIdParm,
- u8 barNumberParm,
- u64 offsetParm,
- u8 valueParm)
+
+static inline u64 HvCallPci_barStore8(u16 busNumberParm, u8 subBusParm,
+ u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+ u8 valueParm)
{
struct HvCallPci_DsaAddr dsa;
- u64 retVal;
*((u64*)&dsa) = 0;
-
+
dsa.busNumber = busNumberParm;
dsa.subBusNumber = subBusParm;
dsa.deviceId = deviceIdParm;
dsa.barNumber = barNumberParm;
- retVal = HvCall4(HvCallPciBarStore8, *(u64 *)&dsa, offsetParm, valueParm, 0);
-
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
- return retVal;
+ return HvCall4(HvCallPciBarStore8, *(u64 *)&dsa, offsetParm,
+ valueParm, 0);
}
-//============================================================================
-static inline u64 HvCallPci_barStore16(u16 busNumberParm,
- u8 subBusParm,
- u8 deviceIdParm,
- u8 barNumberParm,
- u64 offsetParm,
- u16 valueParm)
+
+static inline u64 HvCallPci_barStore16(u16 busNumberParm, u8 subBusParm,
+ u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+ u16 valueParm)
{
struct HvCallPci_DsaAddr dsa;
- u64 retVal;
*((u64*)&dsa) = 0;
-
+
dsa.busNumber = busNumberParm;
dsa.subBusNumber = subBusParm;
dsa.deviceId = deviceIdParm;
dsa.barNumber = barNumberParm;
- retVal = HvCall4(HvCallPciBarStore16, *(u64 *)&dsa, offsetParm, valueParm, 0);
-
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
- return retVal;
+ return HvCall4(HvCallPciBarStore16, *(u64 *)&dsa, offsetParm,
+ valueParm, 0);
}
-//============================================================================
-static inline u64 HvCallPci_barStore32(u16 busNumberParm,
- u8 subBusParm,
- u8 deviceIdParm,
- u8 barNumberParm,
- u64 offsetParm,
- u32 valueParm)
+
+static inline u64 HvCallPci_barStore32(u16 busNumberParm, u8 subBusParm,
+ u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+ u32 valueParm)
{
struct HvCallPci_DsaAddr dsa;
- u64 retVal;
*((u64*)&dsa) = 0;
-
+
dsa.busNumber = busNumberParm;
dsa.subBusNumber = subBusParm;
dsa.deviceId = deviceIdParm;
dsa.barNumber = barNumberParm;
- retVal = HvCall4(HvCallPciBarStore32, *(u64 *)&dsa, offsetParm, valueParm, 0);
-
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
- return retVal;
+ return HvCall4(HvCallPciBarStore32, *(u64 *)&dsa, offsetParm,
+ valueParm, 0);
}
-//============================================================================
-static inline u64 HvCallPci_barStore64(u16 busNumberParm,
- u8 subBusParm,
- u8 deviceIdParm,
- u8 barNumberParm,
- u64 offsetParm,
- u64 valueParm)
+
+static inline u64 HvCallPci_barStore64(u16 busNumberParm, u8 subBusParm,
+ u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+ u64 valueParm)
{
struct HvCallPci_DsaAddr dsa;
- u64 retVal;
*((u64*)&dsa) = 0;
-
+
dsa.busNumber = busNumberParm;
dsa.subBusNumber = subBusParm;
dsa.deviceId = deviceIdParm;
dsa.barNumber = barNumberParm;
- retVal = HvCall4(HvCallPciBarStore64, *(u64 *)&dsa, offsetParm, valueParm, 0);
-
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
- return retVal;
+ return HvCall4(HvCallPciBarStore64, *(u64 *)&dsa, offsetParm,
+ valueParm, 0);
}
-//============================================================================
-static inline u64 HvCallPci_eoi(u16 busNumberParm,
- u8 subBusParm,
- u8 deviceIdParm)
+
+static inline u64 HvCallPci_eoi(u16 busNumberParm, u8 subBusParm,
+ u8 deviceIdParm)
{
struct HvCallPci_DsaAddr dsa;
struct HvCallPci_LoadReturn retVal;
@@ -465,20 +391,13 @@ static inline u64 HvCallPci_eoi(u16 busNumberParm,
HvCall1Ret16(HvCallPciEoi, &retVal, *(u64*)&dsa);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
return retVal.rc;
}
-//============================================================================
-static inline u64 HvCallPci_getBarParms(u16 busNumberParm,
- u8 subBusParm,
- u8 deviceIdParm,
- u8 barNumberParm,
- u64 parms,
- u32 sizeofParms)
+
+static inline u64 HvCallPci_getBarParms(u16 busNumberParm, u8 subBusParm,
+ u8 deviceIdParm, u8 barNumberParm, u64 parms, u32 sizeofParms)
{
struct HvCallPci_DsaAddr dsa;
- u64 retVal;
*((u64*)&dsa) = 0;
@@ -487,62 +406,41 @@ static inline u64 HvCallPci_getBarParms(u16 busNumberParm,
dsa.deviceId = deviceIdParm;
dsa.barNumber = barNumberParm;
- retVal = HvCall3(HvCallPciGetBarParms, *(u64*)&dsa, parms, sizeofParms);
-
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
- return retVal;
+ return HvCall3(HvCallPciGetBarParms, *(u64*)&dsa, parms, sizeofParms);
}
-//============================================================================
-static inline u64 HvCallPci_maskFisr(u16 busNumberParm,
- u8 subBusParm,
- u8 deviceIdParm,
- u64 fisrMask)
+
+static inline u64 HvCallPci_maskFisr(u16 busNumberParm, u8 subBusParm,
+ u8 deviceIdParm, u64 fisrMask)
{
struct HvCallPci_DsaAddr dsa;
- u64 retVal;
- *((u64*)&dsa) = 0;
+ *((u64*)&dsa) = 0;
dsa.busNumber = busNumberParm;
dsa.subBusNumber = subBusParm;
dsa.deviceId = deviceIdParm;
- retVal = HvCall2(HvCallPciMaskFisr, *(u64*)&dsa, fisrMask);
-
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
- return retVal;
+ return HvCall2(HvCallPciMaskFisr, *(u64*)&dsa, fisrMask);
}
-//============================================================================
-static inline u64 HvCallPci_unmaskFisr(u16 busNumberParm,
- u8 subBusParm,
- u8 deviceIdParm,
- u64 fisrMask)
+
+static inline u64 HvCallPci_unmaskFisr(u16 busNumberParm, u8 subBusParm,
+ u8 deviceIdParm, u64 fisrMask)
{
struct HvCallPci_DsaAddr dsa;
- u64 retVal;
- *((u64*)&dsa) = 0;
+ *((u64*)&dsa) = 0;
dsa.busNumber = busNumberParm;
dsa.subBusNumber = subBusParm;
dsa.deviceId = deviceIdParm;
- retVal = HvCall2(HvCallPciUnmaskFisr, *(u64*)&dsa, fisrMask);
-
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
- return retVal;
+ return HvCall2(HvCallPciUnmaskFisr, *(u64*)&dsa, fisrMask);
}
-//============================================================================
-static inline u64 HvCallPci_setSlotReset(u16 busNumberParm,
- u8 subBusParm,
- u8 deviceIdParm,
- u64 onNotOff)
+
+static inline u64 HvCallPci_setSlotReset(u16 busNumberParm, u8 subBusParm,
+ u8 deviceIdParm, u64 onNotOff)
{
struct HvCallPci_DsaAddr dsa;
- u64 retVal;
*((u64*)&dsa) = 0;
@@ -550,21 +448,13 @@ static inline u64 HvCallPci_setSlotReset(u16 busNumberParm,
dsa.subBusNumber = subBusParm;
dsa.deviceId = deviceIdParm;
- retVal = HvCall2(HvCallPciSetSlotReset, *(u64*)&dsa, onNotOff);
-
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
- return retVal;
+ return HvCall2(HvCallPciSetSlotReset, *(u64*)&dsa, onNotOff);
}
-//============================================================================
-static inline u64 HvCallPci_getDeviceInfo(u16 busNumberParm,
- u8 subBusParm,
- u8 deviceNumberParm,
- u64 parms,
- u32 sizeofParms)
+
+static inline u64 HvCallPci_getDeviceInfo(u16 busNumberParm, u8 subBusParm,
+ u8 deviceNumberParm, u64 parms, u32 sizeofParms)
{
struct HvCallPci_DsaAddr dsa;
- u64 retVal;
*((u64*)&dsa) = 0;
@@ -572,102 +462,72 @@ static inline u64 HvCallPci_getDeviceInfo(u16 busNumberParm,
dsa.subBusNumber = subBusParm;
dsa.deviceId = deviceNumberParm << 4;
- retVal = HvCall3(HvCallPciGetDeviceInfo, *(u64*)&dsa, parms, sizeofParms);
-
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
- return retVal;
+ return HvCall3(HvCallPciGetDeviceInfo, *(u64*)&dsa, parms, sizeofParms);
}
-//============================================================================
-static inline u64 HvCallPci_maskInterrupts(u16 busNumberParm,
- u8 subBusParm,
- u8 deviceIdParm,
- u64 interruptMask)
+
+static inline u64 HvCallPci_maskInterrupts(u16 busNumberParm, u8 subBusParm,
+ u8 deviceIdParm, u64 interruptMask)
{
struct HvCallPci_DsaAddr dsa;
- u64 retVal;
- *((u64*)&dsa) = 0;
+ *((u64*)&dsa) = 0;
dsa.busNumber = busNumberParm;
dsa.subBusNumber = subBusParm;
dsa.deviceId = deviceIdParm;
- retVal = HvCall2(HvCallPciMaskInterrupts, *(u64*)&dsa, interruptMask);
-
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
- return retVal;
+ return HvCall2(HvCallPciMaskInterrupts, *(u64*)&dsa, interruptMask);
}
-//============================================================================
-static inline u64 HvCallPci_unmaskInterrupts(u16 busNumberParm,
- u8 subBusParm,
- u8 deviceIdParm,
- u64 interruptMask)
+
+static inline u64 HvCallPci_unmaskInterrupts(u16 busNumberParm, u8 subBusParm,
+ u8 deviceIdParm, u64 interruptMask)
{
struct HvCallPci_DsaAddr dsa;
- u64 retVal;
- *((u64*)&dsa) = 0;
+ *((u64*)&dsa) = 0;
dsa.busNumber = busNumberParm;
dsa.subBusNumber = subBusParm;
dsa.deviceId = deviceIdParm;
- retVal = HvCall2(HvCallPciUnmaskInterrupts, *(u64*)&dsa, interruptMask);
-
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
- return retVal;
+ return HvCall2(HvCallPciUnmaskInterrupts, *(u64*)&dsa, interruptMask);
}
-//============================================================================
-static inline u64 HvCallPci_getBusUnitInfo(u16 busNumberParm,
- u8 subBusParm,
- u8 deviceIdParm,
- u64 parms,
- u32 sizeofParms)
+static inline u64 HvCallPci_getBusUnitInfo(u16 busNumberParm, u8 subBusParm,
+ u8 deviceIdParm, u64 parms, u32 sizeofParms)
{
struct HvCallPci_DsaAddr dsa;
- u64 retVal;
- *((u64*)&dsa) = 0;
+ *((u64*)&dsa) = 0;
dsa.busNumber = busNumberParm;
dsa.subBusNumber = subBusParm;
dsa.deviceId = deviceIdParm;
- retVal = HvCall3(HvCallPciGetBusUnitInfo, *(u64*)&dsa, parms, sizeofParms);
-
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
- return retVal;
+ return HvCall3(HvCallPciGetBusUnitInfo, *(u64*)&dsa, parms,
+ sizeofParms);
}
-//============================================================================
-static inline int HvCallPci_getBusVpd(u16 busNumParm, u64 destParm, u16 sizeParm)
+static inline int HvCallPci_getBusVpd(u16 busNumParm, u64 destParm,
+ u16 sizeParm)
{
- int xRetSize;
- u64 xRc = HvCall4(HvCallPciGetCardVpd, busNumParm, destParm, sizeParm, HvCallPci_BusVpd);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
+ u64 xRc = HvCall4(HvCallPciGetCardVpd, busNumParm, destParm,
+ sizeParm, HvCallPci_BusVpd);
if (xRc == -1)
- xRetSize = -1;
+ return -1;
else
- xRetSize = xRc & 0xFFFF;
- return xRetSize;
+ return xRc & 0xFFFF;
}
-//============================================================================
-static inline int HvCallPci_getBusAdapterVpd(u16 busNumParm, u64 destParm, u16 sizeParm)
+static inline int HvCallPci_getBusAdapterVpd(u16 busNumParm, u64 destParm,
+ u16 sizeParm)
{
- int xRetSize;
- u64 xRc = HvCall4(HvCallPciGetCardVpd, busNumParm, destParm, sizeParm, HvCallPci_BusAdapterVpd);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
+ u64 xRc = HvCall4(HvCallPciGetCardVpd, busNumParm, destParm,
+ sizeParm, HvCallPci_BusAdapterVpd);
if (xRc == -1)
- xRetSize = -1;
+ return -1;
else
- xRetSize = xRc & 0xFFFF;
- return xRetSize;
+ return xRc & 0xFFFF;
}
-//============================================================================
+
#endif /* _HVCALLPCI_H */
diff --git a/include/asm-ppc64/iSeries/HvCallSc.h b/include/asm-ppc64/iSeries/HvCallSc.h
index eea25844764..a62cef3822f 100644
--- a/include/asm-ppc64/iSeries/HvCallSc.h
+++ b/include/asm-ppc64/iSeries/HvCallSc.h
@@ -1,17 +1,17 @@
/*
* HvCallSc.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
- *
+ *
* 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 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
@@ -19,7 +19,7 @@
#ifndef _HVCALLSC_H
#define _HVCALLSC_H
-#include <asm/iSeries/HvTypes.h>
+#include <linux/types.h>
#define HvCallBase 0x8000000000000000ul
#define HvCallCc 0x8001000000000000ul
@@ -30,22 +30,22 @@
#define HvCallSm 0x8007000000000000ul
#define HvCallXm 0x8009000000000000ul
-u64 HvCall0( u64 );
-u64 HvCall1( u64, u64 );
-u64 HvCall2( u64, u64, u64 );
-u64 HvCall3( u64, u64, u64, u64 );
-u64 HvCall4( u64, u64, u64, u64, u64 );
-u64 HvCall5( u64, u64, u64, u64, u64, u64 );
-u64 HvCall6( u64, u64, u64, u64, u64, u64, u64 );
-u64 HvCall7( u64, u64, u64, u64, u64, u64, u64, u64 );
+extern u64 HvCall0(u64);
+extern u64 HvCall1(u64, u64);
+extern u64 HvCall2(u64, u64, u64);
+extern u64 HvCall3(u64, u64, u64, u64);
+extern u64 HvCall4(u64, u64, u64, u64, u64);
+extern u64 HvCall5(u64, u64, u64, u64, u64, u64);
+extern u64 HvCall6(u64, u64, u64, u64, u64, u64, u64);
+extern u64 HvCall7(u64, u64, u64, u64, u64, u64, u64, u64);
-u64 HvCall0Ret16( u64, void * );
-u64 HvCall1Ret16( u64, void *, u64 );
-u64 HvCall2Ret16( u64, void *, u64, u64 );
-u64 HvCall3Ret16( u64, void *, u64, u64, u64 );
-u64 HvCall4Ret16( u64, void *, u64, u64, u64, u64 );
-u64 HvCall5Ret16( u64, void *, u64, u64, u64, u64, u64 );
-u64 HvCall6Ret16( u64, void *, u64, u64, u64, u64, u64, u64 );
-u64 HvCall7Ret16( u64, void *, u64, u64 ,u64 ,u64 ,u64 ,u64 ,u64 );
+extern u64 HvCall0Ret16(u64, void *);
+extern u64 HvCall1Ret16(u64, void *, u64);
+extern u64 HvCall2Ret16(u64, void *, u64, u64);
+extern u64 HvCall3Ret16(u64, void *, u64, u64, u64);
+extern u64 HvCall4Ret16(u64, void *, u64, u64, u64, u64);
+extern u64 HvCall5Ret16(u64, void *, u64, u64, u64, u64, u64);
+extern u64 HvCall6Ret16(u64, void *, u64, u64, u64, u64, u64, u64);
+extern u64 HvCall7Ret16(u64, void *, u64, u64 ,u64 ,u64 ,u64 ,u64 ,u64);
#endif /* _HVCALLSC_H */
diff --git a/include/asm-ppc64/iSeries/HvCallSm.h b/include/asm-ppc64/iSeries/HvCallSm.h
index 9050c94a529..8a3dbb071a4 100644
--- a/include/asm-ppc64/iSeries/HvCallSm.h
+++ b/include/asm-ppc64/iSeries/HvCallSm.h
@@ -1,17 +1,17 @@
/*
* HvCallSm.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
- *
+ *
* 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 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
@@ -19,34 +19,20 @@
#ifndef _HVCALLSM_H
#define _HVCALLSM_H
-//============================================================================
-//
-// This file contains the "hypervisor call" interface which is used to
-// drive the hypervisor from the OS.
-//
-//============================================================================
+/*
+ * This file contains the "hypervisor call" interface which is used to
+ * drive the hypervisor from the OS.
+ */
-//-------------------------------------------------------------------
-// Standard Includes
-//-------------------------------------------------------------------
#include <asm/iSeries/HvCallSc.h>
#include <asm/iSeries/HvTypes.h>
-//-----------------------------------------------------------------------------
-// Constants
-//-----------------------------------------------------------------------------
-
#define HvCallSmGet64BitsOfAccessMap HvCallSm + 11
-
-//============================================================================
-static inline u64 HvCallSm_get64BitsOfAccessMap(
- HvLpIndex lpIndex, u64 indexIntoBitMap )
+static inline u64 HvCallSm_get64BitsOfAccessMap(HvLpIndex lpIndex,
+ u64 indexIntoBitMap)
{
- u64 retval = HvCall2(HvCallSmGet64BitsOfAccessMap, lpIndex,
- indexIntoBitMap );
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retval;
+ return HvCall2(HvCallSmGet64BitsOfAccessMap, lpIndex, indexIntoBitMap);
}
-//============================================================================
+
#endif /* _HVCALLSM_H */
diff --git a/include/asm-ppc64/iSeries/HvCallXm.h b/include/asm-ppc64/iSeries/HvCallXm.h
index bfb898f4db8..8b9ba608daa 100644
--- a/include/asm-ppc64/iSeries/HvCallXm.h
+++ b/include/asm-ppc64/iSeries/HvCallXm.h
@@ -1,30 +1,13 @@
-//============================================================================
-// Header File Id
-// Name______________: HvCallXm.H
-//
-// Description_______:
-//
-// This file contains the "hypervisor call" interface which is used to
-// drive the hypervisor from SLIC.
-//
-//============================================================================
+/*
+ * This file contains the "hypervisor call" interface which is used to
+ * drive the hypervisor from SLIC.
+ */
#ifndef _HVCALLXM_H
#define _HVCALLXM_H
-//-------------------------------------------------------------------
-// Forward declarations
-//-------------------------------------------------------------------
-
-//-------------------------------------------------------------------
-// Standard Includes
-//-------------------------------------------------------------------
#include <asm/iSeries/HvCallSc.h>
#include <asm/iSeries/HvTypes.h>
-//-----------------------------------------------------------------------------
-// Constants
-//-----------------------------------------------------------------------------
-
#define HvCallXmGetTceTableParms HvCallXm + 0
#define HvCallXmTestBus HvCallXm + 1
#define HvCallXmConnectBusUnit HvCallXm + 2
@@ -33,63 +16,63 @@
#define HvCallXmSetTce HvCallXm + 11
#define HvCallXmSetTces HvCallXm + 13
+/*
+ * Structure passed to HvCallXm_getTceTableParms
+ */
+struct iommu_table_cb {
+ unsigned long itc_busno; /* Bus number for this tce table */
+ unsigned long itc_start; /* Will be NULL for secondary */
+ unsigned long itc_totalsize; /* Size (in pages) of whole table */
+ unsigned long itc_offset; /* Index into real tce table of the
+ start of our section */
+ unsigned long itc_size; /* Size (in pages) of our section */
+ unsigned long itc_index; /* Index of this tce table */
+ unsigned short itc_maxtables; /* Max num of tables for partition */
+ unsigned char itc_virtbus; /* Flag to indicate virtual bus */
+ unsigned char itc_slotno; /* IOA Tce Slot Index */
+ unsigned char itc_rsvd[4];
+};
-
-//============================================================================
-static inline void HvCallXm_getTceTableParms(u64 cb)
+static inline void HvCallXm_getTceTableParms(u64 cb)
{
HvCall1(HvCallXmGetTceTableParms, cb);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
}
-//============================================================================
-static inline u64 HvCallXm_setTce(u64 tceTableToken, u64 tceOffset, u64 tce)
-{
- u64 retval = HvCall3(HvCallXmSetTce, tceTableToken, tceOffset, tce );
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retval;
-}
-//============================================================================
-static inline u64 HvCallXm_setTces(u64 tceTableToken, u64 tceOffset, u64 numTces, u64 tce1, u64 tce2, u64 tce3, u64 tce4)
-{
- u64 retval = HvCall7(HvCallXmSetTces, tceTableToken, tceOffset, numTces,
- tce1, tce2, tce3, tce4 );
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retval;
+
+static inline u64 HvCallXm_setTce(u64 tceTableToken, u64 tceOffset, u64 tce)
+{
+ return HvCall3(HvCallXmSetTce, tceTableToken, tceOffset, tce);
}
-//=============================================================================
-static inline u64 HvCallXm_testBus(u16 busNumber)
+
+static inline u64 HvCallXm_setTces(u64 tceTableToken, u64 tceOffset,
+ u64 numTces, u64 tce1, u64 tce2, u64 tce3, u64 tce4)
{
- u64 retVal = HvCall1(HvCallXmTestBus, busNumber);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
+ return HvCall7(HvCallXmSetTces, tceTableToken, tceOffset, numTces,
+ tce1, tce2, tce3, tce4);
}
-//=====================================================================================
-static inline u64 HvCallXm_testBusUnit(u16 busNumber, u8 subBusNumber, u8 deviceId)
+
+static inline u64 HvCallXm_testBus(u16 busNumber)
{
- u64 busUnitNumber = (subBusNumber << 8) | deviceId;
- u64 retVal = HvCall2(HvCallXmTestBusUnit, busNumber, busUnitNumber);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
+ return HvCall1(HvCallXmTestBus, busNumber);
}
-//=====================================================================================
-static inline u64 HvCallXm_connectBusUnit(u16 busNumber, u8 subBusNumber, u8 deviceId,
- u64 interruptToken)
+
+static inline u64 HvCallXm_testBusUnit(u16 busNumber, u8 subBusNumber,
+ u8 deviceId)
{
- u64 busUnitNumber = (subBusNumber << 8) | deviceId;
- u64 queueIndex = 0; // HvLpConfig::mapDsaToQueueIndex(HvLpDSA(busNumber, xBoard, xCard));
+ return HvCall2(HvCallXmTestBusUnit, busNumber,
+ (subBusNumber << 8) | deviceId);
+}
- u64 retVal = HvCall5(HvCallXmConnectBusUnit, busNumber, busUnitNumber,
- interruptToken, 0, queueIndex);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
+static inline u64 HvCallXm_connectBusUnit(u16 busNumber, u8 subBusNumber,
+ u8 deviceId, u64 interruptToken)
+{
+ return HvCall5(HvCallXmConnectBusUnit, busNumber,
+ (subBusNumber << 8) | deviceId, interruptToken, 0,
+ 0 /* HvLpConfig::mapDsaToQueueIndex(HvLpDSA(busNumber, xBoard, xCard)) */);
}
-//=====================================================================================
-static inline u64 HvCallXm_loadTod(void)
+
+static inline u64 HvCallXm_loadTod(void)
{
- u64 retVal = HvCall0(HvCallXmLoadTod);
- // getPaca()->adjustHmtForNoOfSpinLocksHeld();
- return retVal;
+ return HvCall0(HvCallXmLoadTod);
}
-//=====================================================================================
#endif /* _HVCALLXM_H */
diff --git a/include/asm-ppc64/iSeries/HvLpConfig.h b/include/asm-ppc64/iSeries/HvLpConfig.h
index bdbd70f42c9..f1cf1e70ca3 100644
--- a/include/asm-ppc64/iSeries/HvLpConfig.h
+++ b/include/asm-ppc64/iSeries/HvLpConfig.h
@@ -1,17 +1,17 @@
/*
* HvLpConfig.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
- *
+ *
* 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 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
@@ -19,262 +19,120 @@
#ifndef _HVLPCONFIG_H
#define _HVLPCONFIG_H
-//===========================================================================
-//
-// This file contains the interface to the LPAR configuration data
-// to determine which resources should be allocated to each partition.
-//
-//===========================================================================
+/*
+ * This file contains the interface to the LPAR configuration data
+ * to determine which resources should be allocated to each partition.
+ */
-#include <asm/iSeries/HvCallCfg.h>
+#include <asm/iSeries/HvCallSc.h>
#include <asm/iSeries/HvTypes.h>
#include <asm/iSeries/ItLpNaca.h>
-#include <asm/iSeries/LparData.h>
-//-------------------------------------------------------------------
-// Constants
-//-------------------------------------------------------------------
+enum {
+ HvCallCfg_Cur = 0,
+ HvCallCfg_Init = 1,
+ HvCallCfg_Max = 2,
+ HvCallCfg_Min = 3
+};
+
+#define HvCallCfgGetSystemPhysicalProcessors HvCallCfg + 6
+#define HvCallCfgGetPhysicalProcessors HvCallCfg + 7
+#define HvCallCfgGetMsChunks HvCallCfg + 9
+#define HvCallCfgGetSharedPoolIndex HvCallCfg + 20
+#define HvCallCfgGetSharedProcUnits HvCallCfg + 21
+#define HvCallCfgGetNumProcsInSharedPool HvCallCfg + 22
+#define HvCallCfgGetVirtualLanIndexMap HvCallCfg + 30
+#define HvCallCfgGetHostingLpIndex HvCallCfg + 32
extern HvLpIndex HvLpConfig_getLpIndex_outline(void);
-//===================================================================
static inline HvLpIndex HvLpConfig_getLpIndex(void)
{
return itLpNaca.xLpIndex;
}
-//===================================================================
+
static inline HvLpIndex HvLpConfig_getPrimaryLpIndex(void)
{
return itLpNaca.xPrimaryLpIndex;
}
-//=================================================================
-static inline HvLpIndex HvLpConfig_getLps(void)
-{
- return HvCallCfg_getLps();
-}
-//=================================================================
-static inline HvLpIndexMap HvLpConfig_getActiveLpMap(void)
-{
- return HvCallCfg_getActiveLpMap();
-}
-//=================================================================
-static inline u64 HvLpConfig_getSystemMsMegs(void)
-{
- return HvCallCfg_getSystemMsChunks() / HVCHUNKSPERMEG;
-}
-//=================================================================
-static inline u64 HvLpConfig_getSystemMsChunks(void)
-{
- return HvCallCfg_getSystemMsChunks();
-}
-//=================================================================
-static inline u64 HvLpConfig_getSystemMsPages(void)
-{
- return HvCallCfg_getSystemMsChunks() * HVPAGESPERCHUNK;
-}
-//================================================================
-static inline u64 HvLpConfig_getMsMegs(void)
-{
- return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Cur) / HVCHUNKSPERMEG;
-}
-//================================================================
-static inline u64 HvLpConfig_getMsChunks(void)
-{
- return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Cur);
-}
-//================================================================
-static inline u64 HvLpConfig_getMsPages(void)
-{
- return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Cur) * HVPAGESPERCHUNK;
-}
-//================================================================
-static inline u64 HvLpConfig_getMinMsMegs(void)
-{
- return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Min) / HVCHUNKSPERMEG;
-}
-//================================================================
-static inline u64 HvLpConfig_getMinMsChunks(void)
-{
- return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Min);
-}
-//================================================================
-static inline u64 HvLpConfig_getMinMsPages(void)
-{
- return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Min) * HVPAGESPERCHUNK;
-}
-//================================================================
-static inline u64 HvLpConfig_getMinRuntimeMsMegs(void)
-{
- return HvCallCfg_getMinRuntimeMsChunks(HvLpConfig_getLpIndex()) / HVCHUNKSPERMEG;
-}
-//===============================================================
-static inline u64 HvLpConfig_getMinRuntimeMsChunks(void)
-{
- return HvCallCfg_getMinRuntimeMsChunks(HvLpConfig_getLpIndex());
-}
-//===============================================================
-static inline u64 HvLpConfig_getMinRuntimeMsPages(void)
-{
- return HvCallCfg_getMinRuntimeMsChunks(HvLpConfig_getLpIndex()) * HVPAGESPERCHUNK;
-}
-//===============================================================
-static inline u64 HvLpConfig_getMaxMsMegs(void)
-{
- return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Max) / HVCHUNKSPERMEG;
-}
-//===============================================================
-static inline u64 HvLpConfig_getMaxMsChunks(void)
-{
- return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Max);
-}
-//===============================================================
-static inline u64 HvLpConfig_getMaxMsPages(void)
-{
- return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Max) * HVPAGESPERCHUNK;
-}
-//===============================================================
-static inline u64 HvLpConfig_getInitMsMegs(void)
-{
- return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Init) / HVCHUNKSPERMEG;
-}
-//===============================================================
-static inline u64 HvLpConfig_getInitMsChunks(void)
-{
- return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Init);
-}
-//===============================================================
-static inline u64 HvLpConfig_getInitMsPages(void)
-{ return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Init) * HVPAGESPERCHUNK;
-}
-//===============================================================
-static inline u64 HvLpConfig_getSystemPhysicalProcessors(void)
-{
- return HvCallCfg_getSystemPhysicalProcessors();
-}
-//===============================================================
-static inline u64 HvLpConfig_getSystemLogicalProcessors(void)
-{
- return HvCallCfg_getSystemPhysicalProcessors() * (/*getPaca()->getSecondaryThreadCount() +*/ 1);
-}
-//===============================================================
-static inline u64 HvLpConfig_getNumProcsInSharedPool(HvLpSharedPoolIndex sPI)
-{
- return HvCallCfg_getNumProcsInSharedPool(sPI);
-}
-//===============================================================
-static inline u64 HvLpConfig_getPhysicalProcessors(void)
-{
- return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Cur);
-}
-//===============================================================
-static inline u64 HvLpConfig_getLogicalProcessors(void)
-{
- return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Cur) * (/*getPaca()->getSecondaryThreadCount() +*/ 1);
-}
-//===============================================================
-static inline HvLpSharedPoolIndex HvLpConfig_getSharedPoolIndex(void)
-{
- return HvCallCfg_getSharedPoolIndex(HvLpConfig_getLpIndex());
-}
-//===============================================================
-static inline u64 HvLpConfig_getSharedProcUnits(void)
-{
- return HvCallCfg_getSharedProcUnits(HvLpConfig_getLpIndex(),HvCallCfg_Cur);
-}
-//===============================================================
-static inline u64 HvLpConfig_getMinSharedProcUnits(void)
-{
- return HvCallCfg_getSharedProcUnits(HvLpConfig_getLpIndex(),HvCallCfg_Min);
-}
-//===============================================================
-static inline u64 HvLpConfig_getMaxSharedProcUnits(void)
-{
- return HvCallCfg_getSharedProcUnits(HvLpConfig_getLpIndex(),HvCallCfg_Max);
-}
-//===============================================================
-static inline u64 HvLpConfig_getMinPhysicalProcessors(void)
-{
- return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Min);
-}
-//===============================================================
-static inline u64 HvLpConfig_getMinLogicalProcessors(void)
-{
- return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Min) * (/*getPaca()->getSecondaryThreadCount() +*/ 1);
-}
-//===============================================================
-static inline u64 HvLpConfig_getMaxPhysicalProcessors(void)
-{
- return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Max);
-}
-//===============================================================
-static inline u64 HvLpConfig_getMaxLogicalProcessors(void)
-{
- return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Max) * (/*getPaca()->getSecondaryThreadCount() +*/ 1);
-}
-//===============================================================
-static inline u64 HvLpConfig_getInitPhysicalProcessors(void)
+
+static inline u64 HvLpConfig_getMsChunks(void)
{
- return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Init);
+ return HvCall2(HvCallCfgGetMsChunks, HvLpConfig_getLpIndex(),
+ HvCallCfg_Cur);
}
-//===============================================================
-static inline u64 HvLpConfig_getInitLogicalProcessors(void)
+
+static inline u64 HvLpConfig_getSystemPhysicalProcessors(void)
{
- return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Init) * (/*getPaca()->getSecondaryThreadCount() +*/ 1);
+ return HvCall0(HvCallCfgGetSystemPhysicalProcessors);
}
-//================================================================
-static inline HvLpVirtualLanIndexMap HvLpConfig_getVirtualLanIndexMap(void)
+
+static inline u64 HvLpConfig_getNumProcsInSharedPool(HvLpSharedPoolIndex sPI)
{
- return HvCallCfg_getVirtualLanIndexMap(HvLpConfig_getLpIndex_outline());
+ return (u16)HvCall1(HvCallCfgGetNumProcsInSharedPool, sPI);
}
-//===============================================================
-static inline HvLpVirtualLanIndexMap HvLpConfig_getVirtualLanIndexMapForLp(HvLpIndex lp)
+
+static inline u64 HvLpConfig_getPhysicalProcessors(void)
{
- return HvCallCfg_getVirtualLanIndexMap(lp);
+ return HvCall2(HvCallCfgGetPhysicalProcessors, HvLpConfig_getLpIndex(),
+ HvCallCfg_Cur);
}
-//================================================================
-static inline HvLpIndex HvLpConfig_getBusOwner(HvBusNumber busNumber)
+
+static inline HvLpSharedPoolIndex HvLpConfig_getSharedPoolIndex(void)
{
- return HvCallCfg_getBusOwner(busNumber);
+ return HvCall1(HvCallCfgGetSharedPoolIndex, HvLpConfig_getLpIndex());
}
-//===============================================================
-static inline int HvLpConfig_isBusDedicated(HvBusNumber busNumber)
+
+static inline u64 HvLpConfig_getSharedProcUnits(void)
{
- return HvCallCfg_isBusDedicated(busNumber);
+ return HvCall2(HvCallCfgGetSharedProcUnits, HvLpConfig_getLpIndex(),
+ HvCallCfg_Cur);
}
-//================================================================
-static inline HvLpIndexMap HvLpConfig_getBusAllocation(HvBusNumber busNumber)
+
+static inline u64 HvLpConfig_getMaxSharedProcUnits(void)
{
- return HvCallCfg_getBusAllocation(busNumber);
+ return HvCall2(HvCallCfgGetSharedProcUnits, HvLpConfig_getLpIndex(),
+ HvCallCfg_Max);
}
-//================================================================
-// returns the absolute real address of the load area
-static inline u64 HvLpConfig_getLoadAddress(void)
+
+static inline u64 HvLpConfig_getMaxPhysicalProcessors(void)
{
- return itLpNaca.xLoadAreaAddr & 0x7fffffffffffffff;
+ return HvCall2(HvCallCfgGetPhysicalProcessors, HvLpConfig_getLpIndex(),
+ HvCallCfg_Max);
}
-//================================================================
-static inline u64 HvLpConfig_getLoadPages(void)
-{
- return itLpNaca.xLoadAreaChunks * HVPAGESPERCHUNK;
+
+static inline HvLpVirtualLanIndexMap HvLpConfig_getVirtualLanIndexMapForLp(
+ HvLpIndex lp)
+{
+ /*
+ * This is a new function in V5R1 so calls to this on older
+ * hypervisors will return -1
+ */
+ u64 retVal = HvCall1(HvCallCfgGetVirtualLanIndexMap, lp);
+ if (retVal == -1)
+ retVal = 0;
+ return retVal;
}
-//================================================================
-static inline int HvLpConfig_isBusOwnedByThisLp(HvBusNumber busNumber)
+
+static inline HvLpVirtualLanIndexMap HvLpConfig_getVirtualLanIndexMap(void)
{
- HvLpIndex busOwner = HvLpConfig_getBusOwner(busNumber);
- return (busOwner == HvLpConfig_getLpIndex());
+ return HvLpConfig_getVirtualLanIndexMapForLp(
+ HvLpConfig_getLpIndex_outline());
}
-//================================================================
-static inline int HvLpConfig_doLpsCommunicateOnVirtualLan(HvLpIndex lp1, HvLpIndex lp2)
+
+static inline int HvLpConfig_doLpsCommunicateOnVirtualLan(HvLpIndex lp1,
+ HvLpIndex lp2)
{
- HvLpVirtualLanIndexMap virtualLanIndexMap1 = HvCallCfg_getVirtualLanIndexMap( lp1 );
- HvLpVirtualLanIndexMap virtualLanIndexMap2 = HvCallCfg_getVirtualLanIndexMap( lp2 );
+ HvLpVirtualLanIndexMap virtualLanIndexMap1 =
+ HvLpConfig_getVirtualLanIndexMapForLp(lp1);
+ HvLpVirtualLanIndexMap virtualLanIndexMap2 =
+ HvLpConfig_getVirtualLanIndexMapForLp(lp2);
return ((virtualLanIndexMap1 & virtualLanIndexMap2) != 0);
}
-//================================================================
-static inline HvLpIndex HvLpConfig_getHostingLpIndex(HvLpIndex lp)
+
+static inline HvLpIndex HvLpConfig_getHostingLpIndex(HvLpIndex lp)
{
- return HvCallCfg_getHostingLpIndex(lp);
+ return HvCall1(HvCallCfgGetHostingLpIndex, lp);
}
-//================================================================
#endif /* _HVLPCONFIG_H */
diff --git a/include/asm-ppc64/iSeries/HvLpEvent.h b/include/asm-ppc64/iSeries/HvLpEvent.h
index 30936e43306..865000de79b 100644
--- a/include/asm-ppc64/iSeries/HvLpEvent.h
+++ b/include/asm-ppc64/iSeries/HvLpEvent.h
@@ -1,27 +1,24 @@
/*
* HvLpEvent.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
- *
+ *
* 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 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
*/
-//======================================================================
-//
-// This file contains the class for HV events in the system.
-//
-//=====================================================================
+/* This file contains the class for HV events in the system. */
+
#ifndef _HVLPEVENT_H
#define _HVLPEVENT_H
@@ -30,69 +27,70 @@
#include <asm/iSeries/HvTypes.h>
#include <asm/iSeries/HvCallEvent.h>
-//=====================================================================
-//
-// HvLpEvent is the structure for Lp Event messages passed between
-// partitions through PLIC.
-//
-//=====================================================================
-
-struct HvEventFlags
-{
- u8 xValid:1; // Indicates a valid request x00-x00
- u8 xRsvd1:4; // Reserved ...
- u8 xAckType:1; // Immediate or deferred ...
- u8 xAckInd:1; // Indicates if ACK required ...
- u8 xFunction:1; // Interrupt or Acknowledge ...
+/*
+ * HvLpEvent is the structure for Lp Event messages passed between
+ * partitions through PLIC.
+ */
+
+struct HvEventFlags {
+ u8 xValid:1; /* Indicates a valid request x00-x00 */
+ u8 xRsvd1:4; /* Reserved ... */
+ u8 xAckType:1; /* Immediate or deferred ... */
+ u8 xAckInd:1; /* Indicates if ACK required ... */
+ u8 xFunction:1; /* Interrupt or Acknowledge ... */
};
-struct HvLpEvent
-{
- struct HvEventFlags xFlags; // Event flags x00-x00
- u8 xType; // Type of message x01-x01
- u16 xSubtype; // Subtype for event x02-x03
- u8 xSourceLp; // Source LP x04-x04
- u8 xTargetLp; // Target LP x05-x05
- u8 xSizeMinus1; // Size of Derived class - 1 x06-x06
- u8 xRc; // RC for Ack flows x07-x07
- u16 xSourceInstanceId; // Source sides instance id x08-x09
- u16 xTargetInstanceId; // Target sides instance id x0A-x0B
+struct HvLpEvent {
+ struct HvEventFlags xFlags; /* Event flags x00-x00 */
+ u8 xType; /* Type of message x01-x01 */
+ u16 xSubtype; /* Subtype for event x02-x03 */
+ u8 xSourceLp; /* Source LP x04-x04 */
+ u8 xTargetLp; /* Target LP x05-x05 */
+ u8 xSizeMinus1; /* Size of Derived class - 1 x06-x06 */
+ u8 xRc; /* RC for Ack flows x07-x07 */
+ u16 xSourceInstanceId; /* Source sides instance id x08-x09 */
+ u16 xTargetInstanceId; /* Target sides instance id x0A-x0B */
union {
- u32 xSubtypeData; // Data usable by the subtype x0C-x0F
- u16 xSubtypeDataShort[2]; // Data as 2 shorts
- u8 xSubtypeDataChar[4]; // Data as 4 chars
+ u32 xSubtypeData; /* Data usable by the subtype x0C-x0F */
+ u16 xSubtypeDataShort[2]; /* Data as 2 shorts */
+ u8 xSubtypeDataChar[4]; /* Data as 4 chars */
} x;
- u64 xCorrelationToken; // Unique value for source/type x10-x17
+ u64 xCorrelationToken; /* Unique value for source/type x10-x17 */
};
-// Lp Event handler function
typedef void (*LpEventHandler)(struct HvLpEvent *, struct pt_regs *);
-// Register a handler for an event type
-// returns 0 on success
-extern int HvLpEvent_registerHandler( HvLpEvent_Type eventType, LpEventHandler hdlr);
-
-// Unregister a handler for an event type
-// This call will sleep until the handler being removed is guaranteed to
-// be no longer executing on any CPU. Do not call with locks held.
-//
-// returns 0 on success
-// Unregister will fail if there are any paths open for the type
-extern int HvLpEvent_unregisterHandler( HvLpEvent_Type eventType );
+/* Register a handler for an event type - returns 0 on success */
+extern int HvLpEvent_registerHandler(HvLpEvent_Type eventType,
+ LpEventHandler hdlr);
-// Open an Lp Event Path for an event type
-// returns 0 on success
-// openPath will fail if there is no handler registered for the event type.
-// The lpIndex specified is the partition index for the target partition
-// (for VirtualIo, VirtualLan and SessionMgr) other types specify zero)
-extern int HvLpEvent_openPath( HvLpEvent_Type eventType, HvLpIndex lpIndex );
+/*
+ * Unregister a handler for an event type
+ *
+ * This call will sleep until the handler being removed is guaranteed to
+ * be no longer executing on any CPU. Do not call with locks held.
+ *
+ * returns 0 on success
+ * Unregister will fail if there are any paths open for the type
+ */
+extern int HvLpEvent_unregisterHandler(HvLpEvent_Type eventType);
+/*
+ * Open an Lp Event Path for an event type
+ * returns 0 on success
+ * openPath will fail if there is no handler registered for the event type.
+ * The lpIndex specified is the partition index for the target partition
+ * (for VirtualIo, VirtualLan and SessionMgr) other types specify zero)
+ */
+extern int HvLpEvent_openPath(HvLpEvent_Type eventType, HvLpIndex lpIndex);
-// Close an Lp Event Path for a type and partition
-// returns 0 on sucess
-extern int HvLpEvent_closePath( HvLpEvent_Type eventType, HvLpIndex lpIndex );
+/*
+ * Close an Lp Event Path for a type and partition
+ * returns 0 on sucess
+ */
+extern int HvLpEvent_closePath(HvLpEvent_Type eventType, HvLpIndex lpIndex);
#define HvLpEvent_Type_Hypervisor 0
#define HvLpEvent_Type_MachineFac 1
@@ -141,4 +139,4 @@ extern int HvLpEvent_closePath( HvLpEvent_Type eventType, HvLpIndex lpIndex );
#define HvLpDma_Rc_InvalidAddress 4
#define HvLpDma_Rc_InvalidLength 5
-#endif // _HVLPEVENT_H
+#endif /* _HVLPEVENT_H */
diff --git a/include/asm-ppc64/iSeries/HvReleaseData.h b/include/asm-ppc64/iSeries/HvReleaseData.h
index 183e5e738c2..01a1f13ea4a 100644
--- a/include/asm-ppc64/iSeries/HvReleaseData.h
+++ b/include/asm-ppc64/iSeries/HvReleaseData.h
@@ -1,17 +1,17 @@
/*
* HvReleaseData.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
- *
+ *
* 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 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
@@ -19,47 +19,45 @@
#ifndef _HVRELEASEDATA_H
#define _HVRELEASEDATA_H
-//=============================================================================
-//
-// This control block contains the critical information about the
-// release so that it can be changed in the future (ie, the virtual
-// address of the OS's NACA).
-//
+/*
+ * This control block contains the critical information about the
+ * release so that it can be changed in the future (ie, the virtual
+ * address of the OS's NACA).
+ */
#include <asm/types.h>
#include <asm/naca.h>
-//=============================================================================
-//
-// When we IPL a secondary partition, we will check if if the
-// secondary xMinPlicVrmIndex > the primary xVrmIndex.
-// If it is then this tells PLIC that this secondary is not
-// supported running on this "old" of a level of PLIC.
-//
-// Likewise, we will compare the primary xMinSlicVrmIndex to
-// the secondary xVrmIndex.
-// If the primary xMinSlicVrmDelta > secondary xVrmDelta then we
-// know that this PLIC does not support running an OS "that old".
-//
-//=============================================================================
+/*
+ * When we IPL a secondary partition, we will check if if the
+ * secondary xMinPlicVrmIndex > the primary xVrmIndex.
+ * If it is then this tells PLIC that this secondary is not
+ * supported running on this "old" of a level of PLIC.
+ *
+ * Likewise, we will compare the primary xMinSlicVrmIndex to
+ * the secondary xVrmIndex.
+ * If the primary xMinSlicVrmDelta > secondary xVrmDelta then we
+ * know that this PLIC does not support running an OS "that old".
+ */
-struct HvReleaseData
-{
- u32 xDesc; // Descriptor "HvRD" ebcdic x00-x03
- u16 xSize; // Size of this control block x04-x05
- u16 xVpdAreasPtrOffset; // Offset in NACA of ItVpdAreas x06-x07
- struct naca_struct * xSlicNacaAddr; // Virt addr of SLIC NACA x08-x0F
- u32 xMsNucDataOffset; // Offset of Linux Mapping Data x10-x13
- u32 xRsvd1; // Reserved x14-x17
- u16 xTagsMode:1; // 0 == tags active, 1 == tags inactive
- u16 xAddressSize:1; // 0 == 64-bit, 1 == 32-bit
- u16 xNoSharedProcs:1; // 0 == shared procs, 1 == no shared
- u16 xNoHMT:1; // 0 == allow HMT, 1 == no HMT
- u16 xRsvd2:12; // Reserved x18-x19
- u16 xVrmIndex; // VRM Index of OS image x1A-x1B
- u16 xMinSupportedPlicVrmIndex;// Min PLIC level (soft) x1C-x1D
- u16 xMinCompatablePlicVrmIndex;// Min PLIC levelP (hard) x1E-x1F
- char xVrmName[12]; // Displayable name x20-x2B
- char xRsvd3[20]; // Reserved x2C-x3F
+struct HvReleaseData {
+ u32 xDesc; /* Descriptor "HvRD" ebcdic x00-x03 */
+ u16 xSize; /* Size of this control block x04-x05 */
+ u16 xVpdAreasPtrOffset; /* Offset in NACA of ItVpdAreas x06-x07 */
+ struct naca_struct *xSlicNacaAddr; /* Virt addr of SLIC NACA x08-x0F */
+ u32 xMsNucDataOffset; /* Offset of Linux Mapping Data x10-x13 */
+ u32 xRsvd1; /* Reserved x14-x17 */
+ u16 xTagsMode:1; /* 0 == tags active, 1 == tags inactive */
+ u16 xAddressSize:1; /* 0 == 64-bit, 1 == 32-bit */
+ u16 xNoSharedProcs:1; /* 0 == shared procs, 1 == no shared */
+ u16 xNoHMT:1; /* 0 == allow HMT, 1 == no HMT */
+ u16 xRsvd2:12; /* Reserved x18-x19 */
+ u16 xVrmIndex; /* VRM Index of OS image x1A-x1B */
+ u16 xMinSupportedPlicVrmIndex; /* Min PLIC level (soft) x1C-x1D */
+ u16 xMinCompatablePlicVrmIndex; /* Min PLIC levelP (hard) x1E-x1F */
+ char xVrmName[12]; /* Displayable name x20-x2B */
+ char xRsvd3[20]; /* Reserved x2C-x3F */
};
+extern struct HvReleaseData hvReleaseData;
+
#endif /* _HVRELEASEDATA_H */
diff --git a/include/asm-ppc64/iSeries/HvTypes.h b/include/asm-ppc64/iSeries/HvTypes.h
index 3ec49c1aec3..b1ef2b4cb3e 100644
--- a/include/asm-ppc64/iSeries/HvTypes.h
+++ b/include/asm-ppc64/iSeries/HvTypes.h
@@ -1,17 +1,17 @@
/*
* HvTypes.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
- *
+ *
* 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 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
@@ -19,74 +19,60 @@
#ifndef _HVTYPES_H
#define _HVTYPES_H
-//===========================================================================
-// Header File Id
-// Name______________: HvTypes.H
-//
-// Description_______:
-//
-// General typedefs for the hypervisor.
-//
-// Declared Class(es):
-//
-//===========================================================================
+/*
+ * General typedefs for the hypervisor.
+ */
#include <asm/types.h>
-//-------------------------------------------------------------------
-// Typedefs
-//-------------------------------------------------------------------
typedef u8 HvLpIndex;
typedef u16 HvLpInstanceId;
-typedef u64 HvLpTOD;
-typedef u64 HvLpSystemSerialNum;
-typedef u8 HvLpDeviceSerialNum[12];
-typedef u16 HvLpSanHwSet;
-typedef u16 HvLpBus;
-typedef u16 HvLpBoard;
-typedef u16 HvLpCard;
-typedef u8 HvLpDeviceType[4];
-typedef u8 HvLpDeviceModel[3];
-typedef u64 HvIoToken;
-typedef u8 HvLpName[8];
+typedef u64 HvLpTOD;
+typedef u64 HvLpSystemSerialNum;
+typedef u8 HvLpDeviceSerialNum[12];
+typedef u16 HvLpSanHwSet;
+typedef u16 HvLpBus;
+typedef u16 HvLpBoard;
+typedef u16 HvLpCard;
+typedef u8 HvLpDeviceType[4];
+typedef u8 HvLpDeviceModel[3];
+typedef u64 HvIoToken;
+typedef u8 HvLpName[8];
typedef u32 HvIoId;
typedef u64 HvRealMemoryIndex;
-typedef u32 HvLpIndexMap; // Must hold HvMaxArchitectedLps bits!!!
+typedef u32 HvLpIndexMap; /* Must hold HVMAXARCHITECTEDLPS bits!!! */
typedef u16 HvLpVrmIndex;
typedef u32 HvXmGenerationId;
-typedef u8 HvLpBusPool;
-typedef u8 HvLpSharedPoolIndex;
+typedef u8 HvLpBusPool;
+typedef u8 HvLpSharedPoolIndex;
typedef u16 HvLpSharedProcUnitsX100;
typedef u8 HvLpVirtualLanIndex;
-typedef u16 HvLpVirtualLanIndexMap; // Must hold HvMaxArchitectedVirtualLans bits!!!
-typedef u16 HvBusNumber; // Hypervisor Bus Number
-typedef u8 HvSubBusNumber; // Hypervisor SubBus Number
-typedef u8 HvAgentId; // Hypervisor DevFn
+typedef u16 HvLpVirtualLanIndexMap; /* Must hold HVMAXARCHITECTEDVIRTUALLANS bits!!! */
+typedef u16 HvBusNumber; /* Hypervisor Bus Number */
+typedef u8 HvSubBusNumber; /* Hypervisor SubBus Number */
+typedef u8 HvAgentId; /* Hypervisor DevFn */
+
+#define HVMAXARCHITECTEDLPS 32
+#define HVMAXARCHITECTEDVIRTUALLANS 16
+#define HVMAXARCHITECTEDVIRTUALDISKS 32
+#define HVMAXARCHITECTEDVIRTUALCDROMS 8
+#define HVMAXARCHITECTEDVIRTUALTAPES 8
+#define HVCHUNKSIZE (256 * 1024)
+#define HVPAGESIZE (4 * 1024)
+#define HVLPMINMEGSPRIMARY 256
+#define HVLPMINMEGSSECONDARY 64
+#define HVCHUNKSPERMEG 4
+#define HVPAGESPERMEG 256
+#define HVPAGESPERCHUNK 64
-#define HVMAXARCHITECTEDLPS 32
-#define HVMAXARCHITECTEDVIRTUALLANS 16
-#define HVMAXARCHITECTEDVIRTUALDISKS 32
-#define HVMAXARCHITECTEDVIRTUALCDROMS 8
-#define HVMAXARCHITECTEDVIRTUALTAPES 8
-#define HVCHUNKSIZE 256 * 1024
-#define HVPAGESIZE 4 * 1024
-#define HVLPMINMEGSPRIMARY 256
-#define HVLPMINMEGSSECONDARY 64
-#define HVCHUNKSPERMEG 4
-#define HVPAGESPERMEG 256
-#define HVPAGESPERCHUNK 64
-
-#define HvMaxArchitectedLps ((HvLpIndex)HVMAXARCHITECTEDLPS)
-#define HvMaxArchitectedVirtualLans ((HvLpVirtualLanIndex)16)
#define HvLpIndexInvalid ((HvLpIndex)0xff)
-//--------------------------------------------------------------------
-// Enums for the sub-components under PLIC
-// Used in HvCall and HvPrimaryCall
-//--------------------------------------------------------------------
-enum HvCallCompIds
-{
+/*
+ * Enums for the sub-components under PLIC
+ * Used in HvCall and HvPrimaryCall
+ */
+enum {
HvCallCompId = 0,
HvCallCpuCtlsCompId = 1,
HvCallCfgCompId = 2,
@@ -97,18 +83,18 @@ enum HvCallCompIds
HvCallSmCompId = 7,
HvCallSpdCompId = 8,
HvCallXmCompId = 9,
- HvCallRioCompId = 10,
+ HvCallRioCompId = 10,
HvCallRsvd3CompId = 11,
HvCallRsvd2CompId = 12,
HvCallRsvd1CompId = 13,
HvCallMaxCompId = 14,
- HvPrimaryCallCompId = 0,
+ HvPrimaryCallCompId = 0,
HvPrimaryCallCfgCompId = 1,
- HvPrimaryCallPciCompId = 2,
+ HvPrimaryCallPciCompId = 2,
HvPrimaryCallSmCompId = 3,
HvPrimaryCallSpdCompId = 4,
HvPrimaryCallXmCompId = 5,
- HvPrimaryCallRioCompId = 6,
+ HvPrimaryCallRioCompId = 6,
HvPrimaryCallRsvd7CompId = 7,
HvPrimaryCallRsvd6CompId = 8,
HvPrimaryCallRsvd5CompId = 9,
@@ -116,7 +102,7 @@ enum HvCallCompIds
HvPrimaryCallRsvd3CompId = 11,
HvPrimaryCallRsvd2CompId = 12,
HvPrimaryCallRsvd1CompId = 13,
- HvPrimaryCallMaxCompId = HvCallMaxCompId
+ HvPrimaryCallMaxCompId = HvCallMaxCompId
};
struct HvLpBufferList {
diff --git a/include/asm-ppc64/iSeries/IoHriMainStore.h b/include/asm-ppc64/iSeries/IoHriMainStore.h
index ff00e865f62..45ed3ea67d0 100644
--- a/include/asm-ppc64/iSeries/IoHriMainStore.h
+++ b/include/asm-ppc64/iSeries/IoHriMainStore.h
@@ -1,17 +1,17 @@
/*
* IoHriMainStore.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
- *
+ *
* 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 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
@@ -21,7 +21,7 @@
#define _IOHRIMAINSTORE_H
/* Main Store Vpd for Condor,iStar,sStar */
-struct IoHriMainStoreSegment4 {
+struct IoHriMainStoreSegment4 {
u8 msArea0Exists:1;
u8 msArea1Exists:1;
u8 msArea2Exists:1;
@@ -51,7 +51,7 @@ struct IoHriMainStoreSegment4 {
u8 msArea1HasRiserVpd:1;
u8 msArea2HasRiserVpd:1;
u8 msArea3HasRiserVpd:1;
- u8 reserved5:4;
+ u8 reserved5:4;
u8 reserved6;
u16 reserved7;
@@ -82,8 +82,8 @@ struct IoHriMainStoreVpdFruData {
};
struct IoHriMainStoreAdrRangeBlock {
- void * blockStart __attribute((packed));
- void * blockEnd __attribute((packed));
+ void *blockStart __attribute((packed));
+ void *blockEnd __attribute((packed));
u32 blockProcChipId __attribute((packed));
};
@@ -102,7 +102,7 @@ struct IoHriMainStoreArea4 {
u32 procNodeId __attribute((packed));
u32 numAdrRangeBlocks __attribute((packed));
- struct IoHriMainStoreAdrRangeBlock xAdrRangeBlock[MaxAreaAdrRangeBlocks] __attribute((packed));
+ struct IoHriMainStoreAdrRangeBlock xAdrRangeBlock[MaxAreaAdrRangeBlocks] __attribute((packed));
struct IoHriMainStoreChipInfo1 chipInfo0 __attribute((packed));
struct IoHriMainStoreChipInfo1 chipInfo1 __attribute((packed));
@@ -113,17 +113,17 @@ struct IoHriMainStoreArea4 {
struct IoHriMainStoreChipInfo1 chipInfo6 __attribute((packed));
struct IoHriMainStoreChipInfo1 chipInfo7 __attribute((packed));
- void * msRamAreaArray __attribute((packed));
+ void *msRamAreaArray __attribute((packed));
u32 msRamAreaArrayNumEntries __attribute((packed));
u32 msRamAreaArrayEntrySize __attribute((packed));
u32 numaDimmExists __attribute((packed));
u32 numaDimmFunctional __attribute((packed));
- void * numaDimmArray __attribute((packed));
+ void *numaDimmArray __attribute((packed));
u32 numaDimmArrayNumEntries __attribute((packed));
u32 numaDimmArrayEntrySize __attribute((packed));
- struct IoHriMainStoreVpdIdData idData __attribute((packed));
+ struct IoHriMainStoreVpdIdData idData __attribute((packed));
u64 powerData __attribute((packed));
u64 cardAssemblyPartNum __attribute((packed));
@@ -143,7 +143,7 @@ struct IoHriMainStoreArea4 {
};
-struct IoHriMainStoreSegment5 {
+struct IoHriMainStoreSegment5 {
u16 reserved1;
u8 reserved2;
u8 msVpdFormat;
@@ -151,17 +151,16 @@ struct IoHriMainStoreSegment5 {
u32 totalMainStore;
u64 maxConfiguredMsAdr;
- struct IoHriMainStoreArea4* msAreaArray;
+ struct IoHriMainStoreArea4 *msAreaArray;
u32 msAreaArrayNumEntries;
u32 msAreaArrayEntrySize;
- u32 msAreaExists;
+ u32 msAreaExists;
u32 msAreaFunctional;
u64 reserved3;
};
+extern u64 xMsVpd[];
-
-#endif // _IOHRIMAINSTORE_H
-
+#endif /* _IOHRIMAINSTORE_H */
diff --git a/include/asm-ppc64/iSeries/IoHriProcessorVpd.h b/include/asm-ppc64/iSeries/IoHriProcessorVpd.h
index 96543388865..73b73d80b8b 100644
--- a/include/asm-ppc64/iSeries/IoHriProcessorVpd.h
+++ b/include/asm-ppc64/iSeries/IoHriProcessorVpd.h
@@ -1,17 +1,17 @@
/*
* IoHriProcessorVpd.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
- *
+ *
* 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 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
@@ -19,16 +19,12 @@
#ifndef _IOHRIPROCESSORVPD_H
#define _IOHRIPROCESSORVPD_H
-//===================================================================
-//
-// This struct maps Processor Vpd that is DMAd to SLIC by CSP
-//
-
#include <asm/types.h>
-struct IoHriProcessorVpd
-{
-
+/*
+ * This struct maps Processor Vpd that is DMAd to SLIC by CSP
+ */
+struct IoHriProcessorVpd {
u8 xFormat; // VPD format indicator x00-x00
u8 xProcStatus:8; // Processor State x01-x01
u8 xSecondaryThreadCount; // Secondary thread cnt x02-x02
@@ -40,12 +36,12 @@ struct IoHriProcessorVpd
u16 xRsvd2; // Reserved x06-x07
u32 xHwNodeId; // Hardware node id x08-x0B
u32 xHwProcId; // Hardware processor id x0C-x0F
-
+
u32 xTypeNum; // Card Type/CCIN number x10-x13
u32 xModelNum; // Model/Feature number x14-x17
u64 xSerialNum; // Serial number x18-x1F
- char xPartNum[12]; // Book Part or FPU number x20-x2B
- char xMfgID[4]; // Manufacturing ID x2C-x2F
+ char xPartNum[12]; // Book Part or FPU number x20-x2B
+ char xMfgID[4]; // Manufacturing ID x2C-x2F
u32 xProcFreq; // Processor Frequency x30-x33
u32 xTimeBaseFreq; // Time Base Frequency x34-x37
@@ -71,7 +67,7 @@ struct IoHriProcessorVpd
u32 xDataL3CacheSizeKB; // L3 data cache size in KB x80-x83
u32 xDataL3CacheLineSize; // L3 data cache block size x84-x87
u64 xRsvd6; // Reserved x88-x8F
-
+
u64 xFruLabel; // Card Location Label x90-x97
u8 xSlotsOnCard; // Slots on card (0=no slots) x98-x98
u8 xPartLocFlag; // Location flag (0-pluggable 1-imbedded) x99-x99
@@ -79,10 +75,12 @@ struct IoHriProcessorVpd
u8 xSmartCardPortNo; // Smart card port number x9C-x9C
u8 xRsvd7; // Reserved x9D-x9D
u16 xFrameIdAndRackUnit; // Frame ID and rack unit adr x9E-x9F
-
+
u8 xRsvd8[24]; // Reserved xA0-xB7
- char xProcSrc[72]; // CSP format SRC xB8-xFF
+ char xProcSrc[72]; // CSP format SRC xB8-xFF
};
+extern struct IoHriProcessorVpd xIoHriProcessorVpd[];
+
#endif /* _IOHRIPROCESSORVPD_H */
diff --git a/include/asm-ppc64/iSeries/ItExtVpdPanel.h b/include/asm-ppc64/iSeries/ItExtVpdPanel.h
index dee6b127303..4c546a8802b 100644
--- a/include/asm-ppc64/iSeries/ItExtVpdPanel.h
+++ b/include/asm-ppc64/iSeries/ItExtVpdPanel.h
@@ -1,17 +1,17 @@
/*
* ItExtVpdPanel.h
* Copyright (C) 2002 Dave Boutcher IBM Corporation
- *
+ *
* 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 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
@@ -20,39 +20,33 @@
#define _ITEXTVPDPANEL_H
/*
- *
- * This struct maps the panel information
+ * This struct maps the panel information
*
* Warning:
* This data must match the architecture for the panel information
- *
*/
-
-/*-------------------------------------------------------------------
- * Standard Includes
- *-------------------------------------------------------------------
-*/
#include <asm/types.h>
-struct ItExtVpdPanel
-{
- // Definition of the Extended Vpd On Panel Data Area
- char systemSerial[8];
- char mfgID[4];
- char reserved1[24];
- char machineType[4];
- char systemID[6];
- char somUniqueCnt[4];
- char serialNumberCount;
- char reserved2[7];
- u16 bbu3;
- u16 bbu2;
- u16 bbu1;
- char xLocationLabel[8];
- u8 xRsvd1[6];
- u16 xFrameId;
- u8 xRsvd2[48];
+struct ItExtVpdPanel {
+ /* Definition of the Extended Vpd On Panel Data Area */
+ char systemSerial[8];
+ char mfgID[4];
+ char reserved1[24];
+ char machineType[4];
+ char systemID[6];
+ char somUniqueCnt[4];
+ char serialNumberCount;
+ char reserved2[7];
+ u16 bbu3;
+ u16 bbu2;
+ u16 bbu1;
+ char xLocationLabel[8];
+ u8 xRsvd1[6];
+ u16 xFrameId;
+ u8 xRsvd2[48];
};
-#endif /* _ITEXTVPDPANEL_H */
+extern struct ItExtVpdPanel xItExtVpdPanel;
+
+#endif /* _ITEXTVPDPANEL_H */
diff --git a/include/asm-ppc64/iSeries/ItIplParmsReal.h b/include/asm-ppc64/iSeries/ItIplParmsReal.h
index 4d8b430ab12..ae3417dc599 100644
--- a/include/asm-ppc64/iSeries/ItIplParmsReal.h
+++ b/include/asm-ppc64/iSeries/ItIplParmsReal.h
@@ -1,17 +1,17 @@
/*
* ItIplParmsReal.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
- *
+ *
* 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 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
@@ -19,58 +19,53 @@
#ifndef _ITIPLPARMSREAL_H
#define _ITIPLPARMSREAL_H
-//==============================================================================
-//
-// This struct maps the IPL Parameters DMA'd from the SP.
-//
-// Warning:
-// This data must map in exactly 64 bytes and match the architecture for
-// the IPL parms
-//
-//=============================================================================
-
+/*
+ * This struct maps the IPL Parameters DMA'd from the SP.
+ *
+ * Warning:
+ * This data must map in exactly 64 bytes and match the architecture for
+ * the IPL parms
+ */
-//-------------------------------------------------------------------
-// Standard Includes
-//-------------------------------------------------------------------
#include <asm/types.h>
-struct ItIplParmsReal
-{
- u8 xFormat; // Defines format of IplParms x00-x00
- u8 xRsvd01:6; // Reserved x01-x01
- u8 xAlternateSearch:1; // Alternate search indicator ...
- u8 xUaSupplied:1; // UA Supplied on programmed IPL ...
- u8 xLsUaFormat; // Format byte for UA x02-x02
- u8 xRsvd02; // Reserved x03-x03
- u32 xLsUa; // LS UA x04-x07
- u32 xUnusedLsLid; // First OS LID to load x08-x0B
- u16 xLsBusNumber; // LS Bus Number x0C-x0D
- u8 xLsCardAdr; // LS Card Address x0E-x0E
- u8 xLsBoardAdr; // LS Board Address x0F-x0F
- u32 xRsvd03; // Reserved x10-x13
- u8 xSpcnPresent:1; // SPCN present x14-x14
- u8 xCpmPresent:1; // CPM present ...
- u8 xRsvd04:6; // Reserved ...
- u8 xRsvd05:4; // Reserved x15-x15
- u8 xKeyLock:4; // Keylock setting ...
- u8 xRsvd06:6; // Reserved x16-x16
- u8 xIplMode:2; // Ipl mode (A|B|C|D) ...
- u8 xHwIplType; // Fast v slow v slow EC HW IPL x17-x17
- u16 xCpmEnabledIpl:1; // CPM in effect when IPL initiated x18-x19
- u16 xPowerOnResetIpl:1; // Indicate POR condition ...
- u16 xMainStorePreserved:1; // Main Storage is preserved ...
- u16 xRsvd07:13; // Reserved ...
- u16 xIplSource:16; // Ipl source x1A-x1B
- u8 xIplReason:8; // Reason for this IPL x1C-x1C
- u8 xRsvd08; // Reserved x1D-x1D
- u16 xRsvd09; // Reserved x1E-x1F
- u16 xSysBoxType; // System Box Type x20-x21
- u16 xSysProcType; // System Processor Type x22-x23
- u32 xRsvd10; // Reserved x24-x27
- u64 xRsvd11; // Reserved x28-x2F
- u64 xRsvd12; // Reserved x30-x37
- u64 xRsvd13; // Reserved x38-x3F
+struct ItIplParmsReal {
+ u8 xFormat; // Defines format of IplParms x00-x00
+ u8 xRsvd01:6; // Reserved x01-x01
+ u8 xAlternateSearch:1; // Alternate search indicator ...
+ u8 xUaSupplied:1; // UA Supplied on programmed IPL...
+ u8 xLsUaFormat; // Format byte for UA x02-x02
+ u8 xRsvd02; // Reserved x03-x03
+ u32 xLsUa; // LS UA x04-x07
+ u32 xUnusedLsLid; // First OS LID to load x08-x0B
+ u16 xLsBusNumber; // LS Bus Number x0C-x0D
+ u8 xLsCardAdr; // LS Card Address x0E-x0E
+ u8 xLsBoardAdr; // LS Board Address x0F-x0F
+ u32 xRsvd03; // Reserved x10-x13
+ u8 xSpcnPresent:1; // SPCN present x14-x14
+ u8 xCpmPresent:1; // CPM present ...
+ u8 xRsvd04:6; // Reserved ...
+ u8 xRsvd05:4; // Reserved x15-x15
+ u8 xKeyLock:4; // Keylock setting ...
+ u8 xRsvd06:6; // Reserved x16-x16
+ u8 xIplMode:2; // Ipl mode (A|B|C|D) ...
+ u8 xHwIplType; // Fast v slow v slow EC HW IPL x17-x17
+ u16 xCpmEnabledIpl:1; // CPM in effect when IPL initiatedx18-x19
+ u16 xPowerOnResetIpl:1; // Indicate POR condition ...
+ u16 xMainStorePreserved:1; // Main Storage is preserved ...
+ u16 xRsvd07:13; // Reserved ...
+ u16 xIplSource:16; // Ipl source x1A-x1B
+ u8 xIplReason:8; // Reason for this IPL x1C-x1C
+ u8 xRsvd08; // Reserved x1D-x1D
+ u16 xRsvd09; // Reserved x1E-x1F
+ u16 xSysBoxType; // System Box Type x20-x21
+ u16 xSysProcType; // System Processor Type x22-x23
+ u32 xRsvd10; // Reserved x24-x27
+ u64 xRsvd11; // Reserved x28-x2F
+ u64 xRsvd12; // Reserved x30-x37
+ u64 xRsvd13; // Reserved x38-x3F
};
+extern struct ItIplParmsReal xItIplParmsReal;
+
#endif /* _ITIPLPARMSREAL_H */
diff --git a/include/asm-ppc64/iSeries/ItLpNaca.h b/include/asm-ppc64/iSeries/ItLpNaca.h
index 5baffddfae1..225d0176779 100644
--- a/include/asm-ppc64/iSeries/ItLpNaca.h
+++ b/include/asm-ppc64/iSeries/ItLpNaca.h
@@ -1,17 +1,17 @@
/*
* ItLpNaca.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
- *
+ *
* 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 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
@@ -19,18 +19,15 @@
#ifndef _ITLPNACA_H
#define _ITLPNACA_H
-//=============================================================================
-//
-// This control block contains the data that is shared between the
-// hypervisor (PLIC) and the OS.
-//
-//=============================================================================
+#include <linux/types.h>
-struct ItLpNaca
-{
-//=============================================================================
+/*
+ * This control block contains the data that is shared between the
+ * hypervisor (PLIC) and the OS.
+ */
+
+struct ItLpNaca {
// CACHE_LINE_1 0x0000 - 0x007F Contains read-only data
-//=============================================================================
u32 xDesc; // Eye catcher x00-x03
u16 xSize; // Size of this class x04-x05
u16 xIntHdlrOffset; // Offset to IntHdlr array x06-x07
@@ -59,30 +56,25 @@ struct ItLpNaca
u64 xLoadAreaAddr; // ER address of load area x28-x2F
u32 xLoadAreaChunks; // Chunks for the load area x30-x33
u32 xPaseSysCallCRMask; // Mask used to test CR before x34-x37
- // doing an ASR switch on PASE
- // system call.
- u64 xSlicSegmentTablePtr; // Pointer to Slic seg table. x38-x3f
- u8 xRsvd1_4[64]; // x40-x7F
-
-//=============================================================================
+ // doing an ASR switch on PASE
+ // system call.
+ u64 xSlicSegmentTablePtr; // Pointer to Slic seg table. x38-x3f
+ u8 xRsvd1_4[64]; // x40-x7F
+
// CACHE_LINE_2 0x0080 - 0x00FF Contains local read-write data
-//=============================================================================
u8 xRsvd2_0[128]; // Reserved x00-x7F
-//=============================================================================
// CACHE_LINE_3-6 0x0100 - 0x02FF Contains LP Queue indicators
-// NB: Padding required to keep xInterrruptHdlr at x300 which is required
+// NB: Padding required to keep xInterrruptHdlr at x300 which is required
// for v4r4 PLIC.
-//=============================================================================
u8 xOldLpQueue[128]; // LP Queue needed for v4r4 100-17F
u8 xRsvd3_0[384]; // Reserved 180-2FF
-//=============================================================================
+
// CACHE_LINE_7-8 0x0300 - 0x03FF Contains the address of the OS interrupt
// handlers
-//=============================================================================
u64 xInterruptHdlr[32]; // Interrupt handlers 300-x3FF
};
-//=============================================================================
+extern struct ItLpNaca itLpNaca;
#endif /* _ITLPNACA_H */
diff --git a/include/asm-ppc64/iSeries/ItLpQueue.h b/include/asm-ppc64/iSeries/ItLpQueue.h
index 4f4dde2a638..393299e04d7 100644
--- a/include/asm-ppc64/iSeries/ItLpQueue.h
+++ b/include/asm-ppc64/iSeries/ItLpQueue.h
@@ -1,17 +1,17 @@
/*
* ItLpQueue.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
- *
+ *
* 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 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
@@ -19,54 +19,54 @@
#ifndef _ITLPQUEUE_H
#define _ITLPQUEUE_H
-//=============================================================================
-//
-// This control block defines the simple LP queue structure that is
-// shared between the hypervisor (PLIC) and the OS in order to send
-// events to an LP.
-//
+/*
+ * This control block defines the simple LP queue structure that is
+ * shared between the hypervisor (PLIC) and the OS in order to send
+ * events to an LP.
+ */
#include <asm/types.h>
#include <asm/ptrace.h>
struct HvLpEvent;
-#define ITMaxLpQueues 8
+#define ITMaxLpQueues 8
#define NotUsed 0 // Queue will not be used by PLIC
#define DedicatedIo 1 // Queue dedicated to IO processor specified
#define DedicatedLp 2 // Queue dedicated to LP specified
#define Shared 3 // Queue shared for both IO and LP
-#define LpEventStackSize 4096
-#define LpEventMaxSize 256
-#define LpEventAlign 64
+#define LpEventStackSize 4096
+#define LpEventMaxSize 256
+#define LpEventAlign 64
-struct ItLpQueue
-{
-//
-// The xSlicCurEventPtr is the pointer to the next event stack entry that will
-// become valid. The OS must peek at this entry to determine if it is valid.
-// PLIC will set the valid indicator as the very last store into that entry.
-//
-// When the OS has completed processing of the event then it will mark the event
-// as invalid so that PLIC knows it can store into that event location again.
-//
-// If the event stack fills and there are overflow events, then PLIC will set
-// the xPlicOverflowIntPending flag in which case the OS will have to fetch the
-// additional LP events once they have drained the event stack.
-//
-// The first 16-bytes are known by both the OS and PLIC. The remainder of the
-// cache line is for use by the OS.
-//
-//=============================================================================
+struct ItLpQueue {
+/*
+ * The xSlicCurEventPtr is the pointer to the next event stack entry
+ * that will become valid. The OS must peek at this entry to determine
+ * if it is valid. PLIC will set the valid indicator as the very last
+ * store into that entry.
+ *
+ * When the OS has completed processing of the event then it will mark
+ * the event as invalid so that PLIC knows it can store into that event
+ * location again.
+ *
+ * If the event stack fills and there are overflow events, then PLIC
+ * will set the xPlicOverflowIntPending flag in which case the OS will
+ * have to fetch the additional LP events once they have drained the
+ * event stack.
+ *
+ * The first 16-bytes are known by both the OS and PLIC. The remainder
+ * of the cache line is for use by the OS.
+ */
u8 xPlicOverflowIntPending;// 0x00 Overflow events are pending
u8 xPlicStatus; // 0x01 DedicatedIo or DedicatedLp or NotUsed
u16 xSlicLogicalProcIndex; // 0x02 Logical Proc Index for correlation
u8 xPlicRsvd[12]; // 0x04
- char* xSlicCurEventPtr; // 0x10
- char* xSlicLastValidEventPtr; // 0x18
- char* xSlicEventStackPtr; // 0x20
+ char *xSlicCurEventPtr; // 0x10
+ char *xSlicLastValidEventPtr; // 0x18
+ char *xSlicEventStackPtr; // 0x20
u8 xIndex; // 0x28 unique sequential index.
u8 xSlicRsvd[3]; // 0x29-2b
u32 xInUseWord; // 0x2C
@@ -76,17 +76,9 @@ struct ItLpQueue
extern struct ItLpQueue xItLpQueue;
-extern struct HvLpEvent * ItLpQueue_getNextLpEvent( struct ItLpQueue * );
-extern int ItLpQueue_isLpIntPending( struct ItLpQueue * );
-extern unsigned ItLpQueue_process( struct ItLpQueue *, struct pt_regs * );
-extern void ItLpQueue_clearValid( struct HvLpEvent * );
-
-static __inline__ void process_iSeries_events( void )
-{
- __asm__ __volatile__ (
- " li 0,0x5555 \n\
- sc"
- : : : "r0", "r3" );
-}
+extern struct HvLpEvent *ItLpQueue_getNextLpEvent(struct ItLpQueue *);
+extern int ItLpQueue_isLpIntPending(struct ItLpQueue *);
+extern unsigned ItLpQueue_process(struct ItLpQueue *, struct pt_regs *);
+extern void ItLpQueue_clearValid(struct HvLpEvent *);
#endif /* _ITLPQUEUE_H */
diff --git a/include/asm-ppc64/iSeries/ItLpRegSave.h b/include/asm-ppc64/iSeries/ItLpRegSave.h
index dafc4c81378..1b3087e7620 100644
--- a/include/asm-ppc64/iSeries/ItLpRegSave.h
+++ b/include/asm-ppc64/iSeries/ItLpRegSave.h
@@ -1,17 +1,17 @@
/*
* ItLpRegSave.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
- *
+ *
* 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 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
@@ -19,33 +19,30 @@
#ifndef _ITLPREGSAVE_H
#define _ITLPREGSAVE_H
-//=====================================================================================
-//
-// This control block contains the data that is shared between PLIC
-// and the OS
-//
-//
+/*
+ * This control block contains the data that is shared between PLIC
+ * and the OS
+ */
-struct ItLpRegSave
-{
+struct ItLpRegSave {
u32 xDesc; // Eye catcher "LpRS" ebcdic 000-003
u16 xSize; // Size of this class 004-005
u8 xInUse; // Area is live 006-007
- u8 xRsvd1[9]; // Reserved 007-00F
+ u8 xRsvd1[9]; // Reserved 007-00F
- u8 xFixedRegSave[352]; // Fixed Register Save Area 010-16F
+ u8 xFixedRegSave[352]; // Fixed Register Save Area 010-16F
u32 xCTRL; // Control Register 170-173
- u32 xDEC; // Decrementer 174-177
+ u32 xDEC; // Decrementer 174-177
u32 xFPSCR; // FP Status and Control Reg 178-17B
u32 xPVR; // Processor Version Number 17C-17F
-
+
u64 xMMCR0; // Monitor Mode Control Reg 0 180-187
u32 xPMC1; // Perf Monitor Counter 1 188-18B
u32 xPMC2; // Perf Monitor Counter 2 18C-18F
u32 xPMC3; // Perf Monitor Counter 3 190-193
u32 xPMC4; // Perf Monitor Counter 4 194-197
u32 xPIR; // Processor ID Reg 198-19B
-
+
u32 xMMCR1; // Monitor Mode Control Reg 1 19C-19F
u32 xMMCRA; // Monitor Mode Control Reg A 1A0-1A3
u32 xPMC5; // Perf Monitor Counter 5 1A4-1A7
@@ -57,17 +54,17 @@ struct ItLpRegSave
u32 xRsvd; // Reserved 1BC-1BF
u64 xACCR; // Address Compare Control Reg 1C0-1C7
- u64 xIMR; // Instruction Match Register 1C8-1CF
- u64 xSDR1; // Storage Description Reg 1 1D0-1D7
+ u64 xIMR; // Instruction Match Register 1C8-1CF
+ u64 xSDR1; // Storage Description Reg 1 1D0-1D7
u64 xSPRG0; // Special Purpose Reg General0 1D8-1DF
u64 xSPRG1; // Special Purpose Reg General1 1E0-1E7
u64 xSPRG2; // Special Purpose Reg General2 1E8-1EF
u64 xSPRG3; // Special Purpose Reg General3 1F0-1F7
u64 xTB; // Time Base Register 1F8-1FF
-
+
u64 xFPR[32]; // Floating Point Registers 200-2FF
- u64 xMSR; // Machine State Register 300-307
+ u64 xMSR; // Machine State Register 300-307
u64 xNIA; // Next Instruction Address 308-30F
u64 xDABR; // Data Address Breakpoint Reg 310-317
@@ -76,8 +73,8 @@ struct ItLpRegSave
u64 xHID0; // HW Implementation Dependent0 320-327
u64 xHID4; // HW Implementation Dependent4 328-32F
- u64 xSCOMd; // SCON Data Reg (SPRG4) 330-337
- u64 xSCOMc; // SCON Command Reg (SPRG5) 338-33F
+ u64 xSCOMd; // SCON Data Reg (SPRG4) 330-337
+ u64 xSCOMc; // SCON Command Reg (SPRG5) 338-33F
u64 xSDAR; // Sample Data Address Register 340-347
u64 xSIAR; // Sample Inst Address Register 348-34F
diff --git a/include/asm-ppc64/iSeries/ItSpCommArea.h b/include/asm-ppc64/iSeries/ItSpCommArea.h
index f1b56f9e11e..5535f8271c9 100644
--- a/include/asm-ppc64/iSeries/ItSpCommArea.h
+++ b/include/asm-ppc64/iSeries/ItSpCommArea.h
@@ -1,29 +1,27 @@
/*
* ItSpCommArea.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
- *
+ *
* 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 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
*/
-
#ifndef _ITSPCOMMAREA_H
#define _ITSPCOMMAREA_H
-struct SpCommArea
-{
+struct SpCommArea {
u32 xDesc; // Descriptor (only in new formats) 000-003
u8 xFormat; // Format (only in new formats) 004-004
u8 xRsvd1[11]; // Reserved 005-00F
diff --git a/include/asm-ppc64/iSeries/ItVpdAreas.h b/include/asm-ppc64/iSeries/ItVpdAreas.h
index d120439f30a..71b3ad24f95 100644
--- a/include/asm-ppc64/iSeries/ItVpdAreas.h
+++ b/include/asm-ppc64/iSeries/ItVpdAreas.h
@@ -1,17 +1,17 @@
/*
* ItVpdAreas.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
- *
+ *
* 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 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
@@ -19,78 +19,71 @@
#ifndef _ITVPDAREAS_H
#define _ITVPDAREAS_H
-//=====================================================================================
-//
-// This file defines the address and length of all of the VPD area passed to
-// the OS from PLIC (most of which start from the SP).
-//
+/*
+ * This file defines the address and length of all of the VPD area passed to
+ * the OS from PLIC (most of which start from the SP).
+ */
#include <asm/types.h>
-// VPD Entry index is carved in stone - cannot be changed (easily).
-#define ItVpdCecVpd 0
-#define ItVpdDynamicSpace 1
-#define ItVpdExtVpd 2
-#define ItVpdExtVpdOnPanel 3
-#define ItVpdFirstPaca 4
-#define ItVpdIoVpd 5
-#define ItVpdIplParms 6
-#define ItVpdMsVpd 7
-#define ItVpdPanelVpd 8
-#define ItVpdLpNaca 9
-#define ItVpdBackplaneAndMaybeClockCardVpd 10
-#define ItVpdRecoveryLogBuffer 11
-#define ItVpdSpCommArea 12
-#define ItVpdSpLogBuffer 13
-#define ItVpdSpLogBufferSave 14
-#define ItVpdSpCardVpd 15
-#define ItVpdFirstProcVpd 16
-#define ItVpdApModelVpd 17
-#define ItVpdClockCardVpd 18
-#define ItVpdBusExtCardVpd 19
-#define ItVpdProcCapacityVpd 20
-#define ItVpdInteractiveCapacityVpd 21
-#define ItVpdFirstSlotLabel 22
-#define ItVpdFirstLpQueue 23
-#define ItVpdFirstL3CacheVpd 24
-#define ItVpdFirstProcFruVpd 25
-
-#define ItVpdMaxEntries 26
+/* VPD Entry index is carved in stone - cannot be changed (easily). */
+#define ItVpdCecVpd 0
+#define ItVpdDynamicSpace 1
+#define ItVpdExtVpd 2
+#define ItVpdExtVpdOnPanel 3
+#define ItVpdFirstPaca 4
+#define ItVpdIoVpd 5
+#define ItVpdIplParms 6
+#define ItVpdMsVpd 7
+#define ItVpdPanelVpd 8
+#define ItVpdLpNaca 9
+#define ItVpdBackplaneAndMaybeClockCardVpd 10
+#define ItVpdRecoveryLogBuffer 11
+#define ItVpdSpCommArea 12
+#define ItVpdSpLogBuffer 13
+#define ItVpdSpLogBufferSave 14
+#define ItVpdSpCardVpd 15
+#define ItVpdFirstProcVpd 16
+#define ItVpdApModelVpd 17
+#define ItVpdClockCardVpd 18
+#define ItVpdBusExtCardVpd 19
+#define ItVpdProcCapacityVpd 20
+#define ItVpdInteractiveCapacityVpd 21
+#define ItVpdFirstSlotLabel 22
+#define ItVpdFirstLpQueue 23
+#define ItVpdFirstL3CacheVpd 24
+#define ItVpdFirstProcFruVpd 25
+#define ItVpdMaxEntries 26
-#define ItDmaMaxEntries 10
+#define ItDmaMaxEntries 10
-#define ItVpdAreasMaxSlotLabels 192
+#define ItVpdAreasMaxSlotLabels 192
-struct SlicVpdAdrs {
- u32 pad1;
- void * vpdAddr;
+struct ItVpdAreas {
+ u32 xSlicDesc; // Descriptor 000-003
+ u16 xSlicSize; // Size of this control block 004-005
+ u16 xPlicAdjustVpdLens:1; // Flag to indicate new interface006-007
+ u16 xRsvd1:15; // Reserved bits ...
+ u16 xSlicVpdEntries; // Number of VPD entries 008-009
+ u16 xSlicDmaEntries; // Number of DMA entries 00A-00B
+ u16 xSlicMaxLogicalProcs; // Maximum logical processors 00C-00D
+ u16 xSlicMaxPhysicalProcs; // Maximum physical processors 00E-00F
+ u16 xSlicDmaToksOffset; // Offset into this of array 010-011
+ u16 xSlicVpdAdrsOffset; // Offset into this of array 012-013
+ u16 xSlicDmaLensOffset; // Offset into this of array 014-015
+ u16 xSlicVpdLensOffset; // Offset into this of array 016-017
+ u16 xSlicMaxSlotLabels; // Maximum number of slot labels018-019
+ u16 xSlicMaxLpQueues; // Maximum number of LP Queues 01A-01B
+ u8 xRsvd2[4]; // Reserved 01C-01F
+ u64 xRsvd3[12]; // Reserved 020-07F
+ u32 xPlicDmaLens[ItDmaMaxEntries];// Array of DMA lengths 080-0A7
+ u32 xPlicDmaToks[ItDmaMaxEntries];// Array of DMA tokens 0A8-0CF
+ u32 xSlicVpdLens[ItVpdMaxEntries];// Array of VPD lengths 0D0-12F
+ void *xSlicVpdAdrs[ItVpdMaxEntries];// Array of VPD buffers 130-1EF
};
-
-struct ItVpdAreas
-{
- u32 xSlicDesc; // Descriptor 000-003
- u16 xSlicSize; // Size of this control block 004-005
- u16 xPlicAdjustVpdLens:1; // Flag to indicate new interface 006-007
- u16 xRsvd1:15; // Reserved bits ...
- u16 xSlicVpdEntries; // Number of VPD entries 008-009
- u16 xSlicDmaEntries; // Number of DMA entries 00A-00B
- u16 xSlicMaxLogicalProcs; // Maximum logical processors 00C-00D
- u16 xSlicMaxPhysicalProcs; // Maximum physical processors 00E-00F
- u16 xSlicDmaToksOffset; // Offset into this of array 010-011
- u16 xSlicVpdAdrsOffset; // Offset into this of array 012-013
- u16 xSlicDmaLensOffset; // Offset into this of array 014-015
- u16 xSlicVpdLensOffset; // Offset into this of array 016-017
- u16 xSlicMaxSlotLabels; // Maximum number of slot labels 018-019
- u16 xSlicMaxLpQueues; // Maximum number of LP Queues 01A-01B
- u8 xRsvd2[4]; // Reserved 01C-01F
- u64 xRsvd3[12]; // Reserved 020-07F
- u32 xPlicDmaLens[ItDmaMaxEntries];// Array of DMA lengths 080-0A7
- u32 xPlicDmaToks[ItDmaMaxEntries];// Array of DMA tokens 0A8-0CF
- u32 xSlicVpdLens[ItVpdMaxEntries];// Array of VPD lengths 0D0-12F
- void * xSlicVpdAdrs[ItVpdMaxEntries];// Array of VPD buffers 130-1EF
-};
+extern struct ItVpdAreas itVpdAreas;
#endif /* _ITVPDAREAS_H */
diff --git a/include/asm-ppc64/iSeries/LparData.h b/include/asm-ppc64/iSeries/LparData.h
deleted file mode 100644
index e54f3b686e5..00000000000
--- a/include/asm-ppc64/iSeries/LparData.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * LparData.h
- * Copyright (C) 2001 Mike Corrigan IBM Corporation
- *
- * 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 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
- */
-
-#ifndef _LPARDATA_H
-#define _LPARDATA_H
-
-#include <asm/types.h>
-#include <asm/page.h>
-#include <asm/abs_addr.h>
-
-#include <asm/iSeries/ItLpNaca.h>
-#include <asm/iSeries/ItLpRegSave.h>
-#include <asm/iSeries/HvReleaseData.h>
-#include <asm/iSeries/LparMap.h>
-#include <asm/iSeries/ItVpdAreas.h>
-#include <asm/iSeries/ItIplParmsReal.h>
-#include <asm/iSeries/ItExtVpdPanel.h>
-#include <asm/iSeries/ItLpQueue.h>
-#include <asm/iSeries/IoHriProcessorVpd.h>
-
-extern struct LparMap xLparMap;
-extern struct HvReleaseData hvReleaseData;
-extern struct ItLpNaca itLpNaca;
-extern struct ItIplParmsReal xItIplParmsReal;
-extern struct ItExtVpdPanel xItExtVpdPanel;
-extern struct IoHriProcessorVpd xIoHriProcessorVpd[];
-extern struct ItLpQueue xItLpQueue;
-extern struct ItVpdAreas itVpdAreas;
-extern u64 xMsVpd[];
-extern struct msChunks msChunks;
-
-
-#endif /* _LPARDATA_H */
diff --git a/include/asm-ppc64/iSeries/LparMap.h b/include/asm-ppc64/iSeries/LparMap.h
index 075205bb0f4..038e5df7e9f 100644
--- a/include/asm-ppc64/iSeries/LparMap.h
+++ b/include/asm-ppc64/iSeries/LparMap.h
@@ -1,17 +1,17 @@
/*
* LparMap.h
* Copyright (C) 2001 Mike Corrigan IBM Corporation
- *
+ *
* 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 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
@@ -21,13 +21,14 @@
#include <asm/types.h>
-/* The iSeries hypervisor will set up mapping for one or more
+/*
+ * The iSeries hypervisor will set up mapping for one or more
* ESID/VSID pairs (in SLB/segment registers) and will set up
* mappings of one or more ranges of pages to VAs.
* We will have the hypervisor set up the ESID->VSID mapping
* for the four kernel segments (C-F). With shared processors,
* the hypervisor will clear all segment registers and reload
- * these four whenever the processor is switched from one
+ * these four whenever the processor is switched from one
* partition to another.
*/
@@ -38,30 +39,31 @@
* need to be located within the load area (if the total partition size
* is 64 MB), but cannot be mapped. Typically, this should specify
* to map half (32 MB) of the load area.
- *
- * The hypervisor will set up page table entries for the number of
+ *
+ * The hypervisor will set up page table entries for the number of
* pages specified.
*
* In 32-bit mode, the hypervisor will load all four of the
- * segment registers (identified by the low-order four bits of the
+ * segment registers (identified by the low-order four bits of the
* Esid field. In 64-bit mode, the hypervisor will load one SLB
* entry to map the Esid to the Vsid.
*/
-// Hypervisor initially maps 32MB of the load area
-#define HvPagesToMap 8192
+/* Hypervisor initially maps 32MB of the load area */
+#define HvPagesToMap 8192
-struct LparMap
-{
- u64 xNumberEsids; // Number of ESID/VSID pairs (1)
- u64 xNumberRanges; // Number of VA ranges to map (1)
- u64 xSegmentTableOffs; // Page number within load area of seg table (0)
- u64 xRsvd[5]; // Reserved (0)
- u64 xKernelEsid; // Esid used to map kernel load (0x0C00000000)
- u64 xKernelVsid; // Vsid used to map kernel load (0x0C00000000)
- u64 xPages; // Number of pages to be mapped (8192)
- u64 xOffset; // Offset from start of load area (0)
- u64 xVPN; // Virtual Page Number (0x000C000000000000)
+struct LparMap {
+ u64 xNumberEsids; // Number of ESID/VSID pairs (1)
+ u64 xNumberRanges; // Number of VA ranges to map (1)
+ u64 xSegmentTableOffs; // Page number within load area of seg table (0)
+ u64 xRsvd[5];
+ u64 xKernelEsid; // Esid used to map kernel load (0x0C00000000)
+ u64 xKernelVsid; // Vsid used to map kernel load (0x0C00000000)
+ u64 xPages; // Number of pages to be mapped (8192)
+ u64 xOffset; // Offset from start of load area (0)
+ u64 xVPN; // Virtual Page Number (0x000C000000000000)
};
+extern struct LparMap xLparMap;
+
#endif /* _LPARMAP_H */
diff --git a/include/asm-ppc64/iSeries/XmPciLpEvent.h b/include/asm-ppc64/iSeries/XmPciLpEvent.h
deleted file mode 100644
index a3d27f116e4..00000000000
--- a/include/asm-ppc64/iSeries/XmPciLpEvent.h
+++ /dev/null
@@ -1,18 +0,0 @@
-
-#ifndef __XMPCILPEVENT_H__
-#define __XMPCILPEVENT_H__
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int XmPciLpEvent_init(void);
-void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __XMPCILPEVENT_H__ */
diff --git a/include/asm-ppc64/iSeries/iSeries_io.h b/include/asm-ppc64/iSeries/iSeries_io.h
index f52b7599b37..9f79413342b 100644
--- a/include/asm-ppc64/iSeries/iSeries_io.h
+++ b/include/asm-ppc64/iSeries/iSeries_io.h
@@ -5,32 +5,33 @@
#ifdef CONFIG_PPC_ISERIES
#include <linux/types.h>
-/************************************************************************/
-/* File iSeries_io.h created by Allan Trautman on Thu Dec 28 2000. */
-/************************************************************************/
-/* Remaps the io.h for the iSeries Io */
-/* Copyright (C) 20yy Allan H Trautman, IBM Corporation */
-/* */
-/* 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 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 */
-/************************************************************************/
-/* Change Activity: */
-/* Created December 28, 2000 */
-/* End Change Activity */
-/************************************************************************/
+/*
+ * File iSeries_io.h created by Allan Trautman on Thu Dec 28 2000.
+ *
+ * Remaps the io.h for the iSeries Io
+ * Copyright (C) 2000 Allan H Trautman, IBM Corporation
+ *
+ * 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 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
+ *
+ * Change Activity:
+ * Created December 28, 2000
+ * End Change Activity
+ */
+
extern u8 iSeries_Read_Byte(const volatile void __iomem * IoAddress);
extern u16 iSeries_Read_Word(const volatile void __iomem * IoAddress);
extern u32 iSeries_Read_Long(const volatile void __iomem * IoAddress);
@@ -39,8 +40,10 @@ extern void iSeries_Write_Word(u16 IoData, volatile void __iomem * IoAddress);
extern void iSeries_Write_Long(u32 IoData, volatile void __iomem * IoAddress);
extern void iSeries_memset_io(volatile void __iomem *dest, char x, size_t n);
-extern void iSeries_memcpy_toio(volatile void __iomem *dest, void *source, size_t n);
-extern void iSeries_memcpy_fromio(void *dest, const volatile void __iomem *source, size_t n);
+extern void iSeries_memcpy_toio(volatile void __iomem *dest, void *source,
+ size_t n);
+extern void iSeries_memcpy_fromio(void *dest,
+ const volatile void __iomem *source, size_t n);
#endif /* CONFIG_PPC_ISERIES */
#endif /* _ISERIES_IO_H */
diff --git a/include/asm-ppc64/iSeries/iSeries_irq.h b/include/asm-ppc64/iSeries/iSeries_irq.h
index ff8ddede038..6c9767ac130 100644
--- a/include/asm-ppc64/iSeries/iSeries_irq.h
+++ b/include/asm-ppc64/iSeries/iSeries_irq.h
@@ -1,19 +1,8 @@
#ifndef __ISERIES_IRQ_H__
#define __ISERIES_IRQ_H__
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void iSeries_init_IRQ(void);
-int iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, HvAgentId);
-int iSeries_assign_IRQ(int, HvBusNumber, HvSubBusNumber, HvAgentId);
-void iSeries_activate_IRQs(void);
-
-int XmPciLpEvent_init(void);
-
-#ifdef __cplusplus
-}
-#endif
+extern void iSeries_init_IRQ(void);
+extern int iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, HvAgentId);
+extern void iSeries_activate_IRQs(void);
#endif /* __ISERIES_IRQ_H__ */
diff --git a/include/asm-ppc64/iSeries/iSeries_pci.h b/include/asm-ppc64/iSeries/iSeries_pci.h
index 5769cff4c00..575f611f8b3 100644
--- a/include/asm-ppc64/iSeries/iSeries_pci.h
+++ b/include/asm-ppc64/iSeries/iSeries_pci.h
@@ -1,112 +1,88 @@
#ifndef _ISERIES_64_PCI_H
#define _ISERIES_64_PCI_H
-/************************************************************************/
-/* File iSeries_pci.h created by Allan Trautman on Tue Feb 20, 2001. */
-/************************************************************************/
-/* Define some useful macros for the iSeries pci routines. */
-/* Copyright (C) 2001 Allan H Trautman, IBM Corporation */
-/* */
-/* 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 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 */
-/************************************************************************/
-/* Change Activity: */
-/* Created Feb 20, 2001 */
-/* Added device reset, March 22, 2001 */
-/* Ported to ppc64, May 25, 2001 */
-/* End Change Activity */
-/************************************************************************/
+/*
+ * File iSeries_pci.h created by Allan Trautman on Tue Feb 20, 2001.
+ *
+ * Define some useful macros for the iSeries pci routines.
+ * Copyright (C) 2001 Allan H Trautman, IBM Corporation
+ *
+ * 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 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
+ *
+ * Change Activity:
+ * Created Feb 20, 2001
+ * Added device reset, March 22, 2001
+ * Ported to ppc64, May 25, 2001
+ * End Change Activity
+ */
#include <asm/iSeries/HvCallPci.h>
#include <asm/abs_addr.h>
-struct pci_dev; /* For Forward Reference */
+struct pci_dev; /* For Forward Reference */
struct iSeries_Device_Node;
-/************************************************************************/
-/* Gets iSeries Bus, SubBus, DevFn using iSeries_Device_Node structure */
-/************************************************************************/
+/*
+ * Gets iSeries Bus, SubBus, DevFn using iSeries_Device_Node structure
+ */
#define ISERIES_BUS(DevPtr) DevPtr->DsaAddr.Dsa.busNumber
#define ISERIES_SUBBUS(DevPtr) DevPtr->DsaAddr.Dsa.subBusNumber
#define ISERIES_DEVICE(DevPtr) DevPtr->DsaAddr.Dsa.deviceId
#define ISERIES_DSA(DevPtr) DevPtr->DsaAddr.DsaAddr
-#define ISERIES_DEVFUN(DevPtr) DevPtr->DevFn
-#define ISERIES_DEVNODE(PciDev) ((struct iSeries_Device_Node*)PciDev->sysdata)
+#define ISERIES_DEVNODE(PciDev) ((struct iSeries_Device_Node *)PciDev->sysdata)
#define EADsMaxAgents 7
-/************************************************************************/
-/* Decodes Linux DevFn to iSeries DevFn, bridge device, or function. */
-/* For Linux, see PCI_SLOT and PCI_FUNC in include/linux/pci.h */
-/************************************************************************/
-
-#define ISERIES_PCI_AGENTID(idsel,func) ((idsel & 0x0F) << 4) | (func & 0x07)
-#define ISERIES_ENCODE_DEVICE(agentid) ((0x10) | ((agentid&0x20)>>2) | (agentid&07))
-
-#define ISERIES_GET_DEVICE_FROM_SUBBUS(subbus) ((subbus >> 5) & 0x7)
-#define ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus) ((subbus >> 2) & 0x7)
-
/*
- * N.B. the ISERIES_DECODE_* macros are not used anywhere, and I think
- * the 0x71 (at least) must be wrong - 0x78 maybe? -- paulus.
+ * Decodes Linux DevFn to iSeries DevFn, bridge device, or function.
+ * For Linux, see PCI_SLOT and PCI_FUNC in include/linux/pci.h
*/
-#define ISERIES_DECODE_DEVFN(linuxdevfn) (((linuxdevfn & 0x71) << 1) | (linuxdevfn & 0x07))
-#define ISERIES_DECODE_DEVICE(linuxdevfn) (((linuxdevfn & 0x38) >> 3) |(((linuxdevfn & 0x40) >> 2) + 0x10))
-#define ISERIES_DECODE_FUNCTION(linuxdevfn) (linuxdevfn & 0x07)
-/************************************************************************/
-/* Converts Virtual Address to Real Address for Hypervisor calls */
-/************************************************************************/
+#define ISERIES_PCI_AGENTID(idsel, func) \
+ (((idsel & 0x0F) << 4) | (func & 0x07))
+#define ISERIES_ENCODE_DEVICE(agentid) \
+ ((0x10) | ((agentid & 0x20) >> 2) | (agentid & 0x07))
-#define ISERIES_HV_ADDR(virtaddr) (0x8000000000000000 | virt_to_abs(virtaddr))
+#define ISERIES_GET_DEVICE_FROM_SUBBUS(subbus) ((subbus >> 5) & 0x7)
+#define ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus) ((subbus >> 2) & 0x7)
-/************************************************************************/
-/* iSeries Device Information */
-/************************************************************************/
+/*
+ * Converts Virtual Address to Real Address for Hypervisor calls
+ */
+#define ISERIES_HV_ADDR(virtaddr) \
+ (0x8000000000000000 | virt_to_abs(virtaddr))
+/*
+ * iSeries Device Information
+ */
struct iSeries_Device_Node {
struct list_head Device_List;
- struct pci_dev* PciDev; /* Pointer to pci_dev structure*/
- union HvDsaMap DsaAddr; /* Direct Select Address */
- /* busNumber,subBusNumber, */
- /* deviceId, barNumber */
- HvAgentId AgentId; /* Hypervisor DevFn */
- int DevFn; /* Linux devfn */
- int BarOffset;
- int Irq; /* Assigned IRQ */
- int ReturnCode; /* Return Code Holder */
- int IoRetry; /* Current Retry Count */
- int Flags; /* Possible flags(disable/bist)*/
- u16 Vendor; /* Vendor ID */
- u8 LogicalSlot; /* Hv Slot Index for Tces */
- struct iommu_table* iommu_table;/* Device TCE Table */
- u8 PhbId; /* Phb Card is on. */
- u16 Board; /* Board Number */
- u8 FrameId; /* iSeries spcn Frame Id */
- char CardLocation[4];/* Char format of planar vpd */
- char Location[20]; /* Frame 1, Card C10 */
+ struct pci_dev *PciDev;
+ union HvDsaMap DsaAddr; /* Direct Select Address */
+ /* busNumber, subBusNumber, */
+ /* deviceId, barNumber */
+ int DevFn; /* Linux devfn */
+ int Irq; /* Assigned IRQ */
+ int Flags; /* Possible flags(disable/bist)*/
+ u8 LogicalSlot; /* Hv Slot Index for Tces */
+ struct iommu_table *iommu_table;/* Device TCE Table */
};
-/************************************************************************/
-/* Functions */
-/************************************************************************/
-
-extern int iSeries_Device_Information(struct pci_dev*,char*, int);
-extern void iSeries_Get_Location_Code(struct iSeries_Device_Node*);
-extern int iSeries_Device_ToggleReset(struct pci_dev* PciDev, int AssertTime, int DelayTime);
+extern void iSeries_Device_Information(struct pci_dev*, int);
#endif /* _ISERIES_64_PCI_H */
diff --git a/include/asm-ppc64/iSeries/iSeries_proc.h b/include/asm-ppc64/iSeries/iSeries_proc.h
deleted file mode 100644
index adb6dc14dd4..00000000000
--- a/include/asm-ppc64/iSeries/iSeries_proc.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * iSeries_proc.h
- * Copyright (C) 2001 Kyle A. Lucke IBM Corporation
- *
- * 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 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
- */
-#ifndef _ISERIES_PROC_H
-#define _ISERIES_PROC_H
-
-extern void iSeries_proc_early_init(void);
-
-#endif /* _iSeries_PROC_H */
diff --git a/include/asm-ppc64/iSeries/mf.h b/include/asm-ppc64/iSeries/mf.h
index 2e59a8e15a0..7e6a0d93699 100644
--- a/include/asm-ppc64/iSeries/mf.h
+++ b/include/asm-ppc64/iSeries/mf.h
@@ -9,17 +9,16 @@
* all partitions in the iSeries. It also provides miscellaneous low-level
* machine facility type operations.
*
- *
* 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 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
@@ -52,6 +51,7 @@ extern void mf_clear_src(void);
extern void mf_init(void);
extern int mf_get_rtc(struct rtc_time *tm);
+extern int mf_get_boot_rtc(struct rtc_time *tm);
extern int mf_set_rtc(struct rtc_time *tm);
#endif /* _ASM_PPC64_ISERIES_MF_H */
diff --git a/include/asm-ppc64/iSeries/vio.h b/include/asm-ppc64/iSeries/vio.h
index 3e5766a849d..6c05e6257f5 100644
--- a/include/asm-ppc64/iSeries/vio.h
+++ b/include/asm-ppc64/iSeries/vio.h
@@ -8,32 +8,32 @@
* Colin Devilbiss <devilbis@us.ibm.com>
*
* (C) Copyright 2000 IBM Corporation
- *
+ *
* This header file is used by the iSeries virtual I/O device
* drivers. It defines the interfaces to the common functions
* (implemented in drivers/char/viopath.h) as well as defining
- * common functions and structures. Currently (at the time I
+ * common functions and structures. Currently (at the time I
* wrote this comment) the iSeries virtual I/O device drivers
- * that use this are
- * drivers/block/viodasd.c
+ * that use this are
+ * drivers/block/viodasd.c
* drivers/char/viocons.c
* drivers/char/viotape.c
* drivers/cdrom/viocd.c
*
* The iSeries virtual ethernet support (veth.c) uses a whole
* different set of functions.
- *
+ *
* 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) anyu later version.
*
* This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * 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.
+ * General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
+ * 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
*
@@ -44,39 +44,41 @@
#include <asm/iSeries/HvTypes.h>
#include <asm/iSeries/HvLpEvent.h>
-/* iSeries virtual I/O events use the subtype field in
+/*
+ * iSeries virtual I/O events use the subtype field in
* HvLpEvent to figure out what kind of vio event is coming
* in. We use a table to route these, and this defines
* the maximum number of distinct subtypes
*/
#define VIO_MAX_SUBTYPES 8
-/* Each subtype can register a handler to process their events.
+/*
+ * Each subtype can register a handler to process their events.
* The handler must have this interface.
*/
typedef void (vio_event_handler_t) (struct HvLpEvent * event);
-int viopath_open(HvLpIndex remoteLp, int subtype, int numReq);
-int viopath_close(HvLpIndex remoteLp, int subtype, int numReq);
-int vio_setHandler(int subtype, vio_event_handler_t * beh);
-int vio_clearHandler(int subtype);
-int viopath_isactive(HvLpIndex lp);
-HvLpInstanceId viopath_sourceinst(HvLpIndex lp);
-HvLpInstanceId viopath_targetinst(HvLpIndex lp);
-void vio_set_hostlp(void);
-void *vio_get_event_buffer(int subtype);
-void vio_free_event_buffer(int subtype, void *buffer);
+extern int viopath_open(HvLpIndex remoteLp, int subtype, int numReq);
+extern int viopath_close(HvLpIndex remoteLp, int subtype, int numReq);
+extern int vio_setHandler(int subtype, vio_event_handler_t * beh);
+extern int vio_clearHandler(int subtype);
+extern int viopath_isactive(HvLpIndex lp);
+extern HvLpInstanceId viopath_sourceinst(HvLpIndex lp);
+extern HvLpInstanceId viopath_targetinst(HvLpIndex lp);
+extern void vio_set_hostlp(void);
+extern void *vio_get_event_buffer(int subtype);
+extern void vio_free_event_buffer(int subtype, void *buffer);
extern HvLpIndex viopath_hostLp;
extern HvLpIndex viopath_ourLp;
-#define VIOCHAR_MAX_DATA 200
+#define VIOCHAR_MAX_DATA 200
-#define VIOMAJOR_SUBTYPE_MASK 0xff00
-#define VIOMINOR_SUBTYPE_MASK 0x00ff
-#define VIOMAJOR_SUBTYPE_SHIFT 8
+#define VIOMAJOR_SUBTYPE_MASK 0xff00
+#define VIOMINOR_SUBTYPE_MASK 0x00ff
+#define VIOMAJOR_SUBTYPE_SHIFT 8
-#define VIOVERSION 0x0101
+#define VIOVERSION 0x0101
/*
* This is the general structure for VIO errors; each module should have
@@ -89,8 +91,8 @@ struct vio_error_entry {
int errno;
const char *msg;
};
-const struct vio_error_entry *vio_lookup_rc(const struct vio_error_entry
- *local_table, u16 rc);
+extern const struct vio_error_entry *vio_lookup_rc(
+ const struct vio_error_entry *local_table, u16 rc);
enum viosubtypes {
viomajorsubtype_monitor = 0x0100,
@@ -102,7 +104,6 @@ enum viosubtypes {
viomajorsubtype_scsi = 0x0700
};
-
enum vioconfigsubtype {
vioconfigget = 0x0001,
};
diff --git a/include/asm-ppc64/imalloc.h b/include/asm-ppc64/imalloc.h
index 3a45e918bf1..e46ff68a6e4 100644
--- a/include/asm-ppc64/imalloc.h
+++ b/include/asm-ppc64/imalloc.h
@@ -4,9 +4,9 @@
/*
* Define the address range of the imalloc VM area.
*/
-#define PHBS_IO_BASE IOREGIONBASE
-#define IMALLOC_BASE (IOREGIONBASE + 0x80000000ul) /* Reserve 2 gigs for PHBs */
-#define IMALLOC_END (IOREGIONBASE + EADDR_MASK)
+#define PHBS_IO_BASE VMALLOC_END
+#define IMALLOC_BASE (PHBS_IO_BASE + 0x80000000ul) /* Reserve 2 gigs for PHBs */
+#define IMALLOC_END (VMALLOC_START + EADDR_MASK)
/* imalloc region types */
@@ -18,7 +18,9 @@
extern struct vm_struct * im_get_free_area(unsigned long size);
extern struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
- int region_type);
-unsigned long im_free(void *addr);
+ int region_type);
+extern void im_free(void *addr);
+
+extern unsigned long ioremap_bot;
#endif /* _PPC64_IMALLOC_H */
diff --git a/include/asm-ppc64/iommu.h b/include/asm-ppc64/iommu.h
index bd53ca4dcfa..729de5cc21d 100644
--- a/include/asm-ppc64/iommu.h
+++ b/include/asm-ppc64/iommu.h
@@ -82,24 +82,6 @@ struct iommu_table {
unsigned long *it_map; /* A simple allocation bitmap for now */
};
-#ifdef CONFIG_PPC_ISERIES
-struct iommu_table_cb {
- unsigned long itc_busno; /* Bus number for this tce table */
- unsigned long itc_start; /* Will be NULL for secondary */
- unsigned long itc_totalsize; /* Size (in pages) of whole table */
- unsigned long itc_offset; /* Index into real tce table of the
- start of our section */
- unsigned long itc_size; /* Size (in pages) of our section */
- unsigned long itc_index; /* Index of this tce table */
- unsigned short itc_maxtables; /* Max num of tables for partition */
- unsigned char itc_virtbus; /* Flag to indicate virtual bus */
- unsigned char itc_slotno; /* IOA Tce Slot Index */
- unsigned char itc_rsvd[4];
-};
-
-extern struct iommu_table vio_tce_table; /* Tce table for virtual bus */
-#endif /* CONFIG_PPC_ISERIES */
-
struct scatterlist;
#ifdef CONFIG_PPC_MULTIPLATFORM
@@ -122,9 +104,6 @@ extern void iommu_devnode_init_pSeries(struct device_node *dn);
#ifdef CONFIG_PPC_ISERIES
-/* Walks all buses and creates iommu tables */
-extern void iommu_setup_iSeries(void);
-
/* Initializes tables for bio buses */
extern void __init iommu_vio_init(void);
@@ -158,8 +137,12 @@ extern void iommu_init_early_pSeries(void);
extern void iommu_init_early_iSeries(void);
extern void iommu_init_early_u3(void);
+#ifdef CONFIG_PCI
extern void pci_iommu_init(void);
extern void pci_direct_iommu_init(void);
+#else
+static inline void pci_iommu_init(void) { }
+#endif
extern void alloc_u3_dart_table(void);
diff --git a/include/asm-ppc64/kdebug.h b/include/asm-ppc64/kdebug.h
index 488634258a7..d383d161cf8 100644
--- a/include/asm-ppc64/kdebug.h
+++ b/include/asm-ppc64/kdebug.h
@@ -17,7 +17,7 @@ struct die_args {
/*
Note - you should never unregister because that can race with NMIs.
- If you really want to do it first unregister - then synchronize_kernel -
+ If you really want to do it first unregister - then synchronize_sched -
then free.
*/
int register_die_notifier(struct notifier_block *nb);
diff --git a/include/asm-ppc64/kexec.h b/include/asm-ppc64/kexec.h
new file mode 100644
index 00000000000..511908afaee
--- /dev/null
+++ b/include/asm-ppc64/kexec.h
@@ -0,0 +1,41 @@
+#ifndef _PPC64_KEXEC_H
+#define _PPC64_KEXEC_H
+
+/*
+ * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return.
+ * I.e. Maximum page that is mapped directly into kernel memory,
+ * and kmap is not required.
+ */
+
+/* Maximum physical address we can use pages from */
+/* XXX: since we copy virt we can use any page we allocate */
+#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
+
+/* Maximum address we can reach in physical address mode */
+/* XXX: I want to allow initrd in highmem. otherwise set to rmo on lpar */
+#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
+
+/* Maximum address we can use for the control code buffer */
+/* XXX: unused today, ppc32 uses TASK_SIZE, probably left over from use_mm */
+#define KEXEC_CONTROL_MEMORY_LIMIT (-1UL)
+
+/* XXX: today we don't use this at all, althogh we have a static stack */
+#define KEXEC_CONTROL_CODE_SIZE 4096
+
+/* The native architecture */
+#define KEXEC_ARCH KEXEC_ARCH_PPC64
+
+#define MAX_NOTE_BYTES 1024
+
+#ifndef __ASSEMBLY__
+
+typedef u32 note_buf_t[MAX_NOTE_BYTES/4];
+
+extern note_buf_t crash_notes[];
+
+extern void kexec_smp_wait(void); /* get and clear naca physid, wait for
+ master to copy new code to 0 */
+
+#endif /* __ASSEMBLY__ */
+#endif /* _PPC_KEXEC_H */
+
diff --git a/include/asm-ppc64/machdep.h b/include/asm-ppc64/machdep.h
index 5d3cd9d042e..9cdad3ed152 100644
--- a/include/asm-ppc64/machdep.h
+++ b/include/asm-ppc64/machdep.h
@@ -76,6 +76,7 @@ struct machdep_calls {
void (*tce_flush)(struct iommu_table *tbl);
void (*iommu_dev_setup)(struct pci_dev *dev);
void (*iommu_bus_setup)(struct pci_bus *bus);
+ void (*irq_bus_setup)(struct pci_bus *bus);
int (*probe)(int platform);
void (*setup_arch)(void);
@@ -85,6 +86,7 @@ struct machdep_calls {
void (*init_IRQ)(void);
int (*get_irq)(struct pt_regs *);
+ void (*cpu_irq_down)(void);
/* PCI stuff */
void (*pcibios_fixup)(void);
diff --git a/include/asm-ppc64/mmu.h b/include/asm-ppc64/mmu.h
index c78282a67d8..f373de5e3dd 100644
--- a/include/asm-ppc64/mmu.h
+++ b/include/asm-ppc64/mmu.h
@@ -47,9 +47,10 @@
#define SLB_VSID_KS ASM_CONST(0x0000000000000800)
#define SLB_VSID_KP ASM_CONST(0x0000000000000400)
#define SLB_VSID_N ASM_CONST(0x0000000000000200) /* no-execute */
-#define SLB_VSID_L ASM_CONST(0x0000000000000100) /* largepage 16M */
+#define SLB_VSID_L ASM_CONST(0x0000000000000100) /* largepage */
#define SLB_VSID_C ASM_CONST(0x0000000000000080) /* class */
-
+#define SLB_VSID_LS ASM_CONST(0x0000000000000070) /* size of largepage */
+
#define SLB_VSID_KERNEL (SLB_VSID_KP|SLB_VSID_C)
#define SLB_VSID_USER (SLB_VSID_KP|SLB_VSID_KS)
@@ -180,6 +181,28 @@ static inline void tlbiel(unsigned long va)
asm volatile("ptesync": : :"memory");
}
+static inline unsigned long slot2va(unsigned long avpn, unsigned long large,
+ unsigned long secondary, unsigned long slot)
+{
+ unsigned long va;
+
+ va = avpn << 23;
+
+ if (!large) {
+ unsigned long vpi, pteg;
+
+ pteg = slot / HPTES_PER_GROUP;
+ if (secondary)
+ pteg = ~pteg;
+
+ vpi = ((va >> 28) ^ pteg) & htab_hash_mask;
+
+ va |= vpi << PAGE_SHIFT;
+ }
+
+ return va;
+}
+
/*
* Handle a fault by adding an HPTE. If the address can't be determined
* to be valid via Linux page tables, return 1. If handled return 0
diff --git a/include/asm-ppc64/mmzone.h b/include/asm-ppc64/mmzone.h
index 0619a41a3c9..ed473f4b015 100644
--- a/include/asm-ppc64/mmzone.h
+++ b/include/asm-ppc64/mmzone.h
@@ -10,9 +10,20 @@
#include <linux/config.h>
#include <asm/smp.h>
-#ifdef CONFIG_DISCONTIGMEM
+/* generic non-linear memory support:
+ *
+ * 1) we will not split memory into more chunks than will fit into the
+ * flags field of the struct page
+ */
+
+
+#ifdef CONFIG_NEED_MULTIPLE_NODES
extern struct pglist_data *node_data[];
+/*
+ * Return a pointer to the node data for node n.
+ */
+#define NODE_DATA(nid) (node_data[nid])
/*
* Following are specific to this numa platform.
@@ -47,36 +58,32 @@ static inline int pa_to_nid(unsigned long pa)
return nid;
}
-#define pfn_to_nid(pfn) pa_to_nid((pfn) << PAGE_SHIFT)
-
-/*
- * Return a pointer to the node data for node n.
- */
-#define NODE_DATA(nid) (node_data[nid])
-
#define node_localnr(pfn, nid) ((pfn) - NODE_DATA(nid)->node_start_pfn)
/*
* Following are macros that each numa implmentation must define.
*/
-/*
- * Given a kernel address, find the home node of the underlying memory.
- */
-#define kvaddr_to_nid(kaddr) pa_to_nid(__pa(kaddr))
-
-#define node_mem_map(nid) (NODE_DATA(nid)->node_mem_map)
#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn)
#define node_end_pfn(nid) (NODE_DATA(nid)->node_end_pfn)
#define local_mapnr(kvaddr) \
( (__pa(kvaddr) >> PAGE_SHIFT) - node_start_pfn(kvaddr_to_nid(kvaddr))
+#ifdef CONFIG_DISCONTIGMEM
+
+/*
+ * Given a kernel address, find the home node of the underlying memory.
+ */
+#define kvaddr_to_nid(kaddr) pa_to_nid(__pa(kaddr))
+
+#define pfn_to_nid(pfn) pa_to_nid((unsigned long)(pfn) << PAGE_SHIFT)
+
/* Written this way to avoid evaluating arguments twice */
#define discontigmem_pfn_to_page(pfn) \
({ \
unsigned long __tmp = pfn; \
- (node_mem_map(pfn_to_nid(__tmp)) + \
+ (NODE_DATA(pfn_to_nid(__tmp))->node_mem_map + \
node_localnr(__tmp, pfn_to_nid(__tmp))); \
})
@@ -91,4 +98,11 @@ static inline int pa_to_nid(unsigned long pa)
#define discontigmem_pfn_valid(pfn) ((pfn) < num_physpages)
#endif /* CONFIG_DISCONTIGMEM */
+
+#endif /* CONFIG_NEED_MULTIPLE_NODES */
+
+#ifdef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
+#define early_pfn_to_nid(pfn) pa_to_nid(((unsigned long)pfn) << PAGE_SHIFT)
+#endif
+
#endif /* _ASM_MMZONE_H_ */
diff --git a/include/asm-ppc64/nvram.h b/include/asm-ppc64/nvram.h
index 4e6dd370d93..dfaa21566c9 100644
--- a/include/asm-ppc64/nvram.h
+++ b/include/asm-ppc64/nvram.h
@@ -70,6 +70,7 @@ extern struct nvram_partition *nvram_find_partition(int sig, const char *name);
extern int pSeries_nvram_init(void);
extern int pmac_nvram_init(void);
+extern int bpa_nvram_init(void);
/* PowerMac specific nvram stuffs */
diff --git a/include/asm-ppc64/paca.h b/include/asm-ppc64/paca.h
index 1a0223b5f3b..ae76cae1483 100644
--- a/include/asm-ppc64/paca.h
+++ b/include/asm-ppc64/paca.h
@@ -20,13 +20,13 @@
#include <asm/types.h>
#include <asm/lppaca.h>
#include <asm/iSeries/ItLpRegSave.h>
+#include <asm/iSeries/ItLpQueue.h>
#include <asm/mmu.h>
register struct paca_struct *local_paca asm("r13");
#define get_paca() local_paca
struct task_struct;
-struct ItLpQueue;
/*
* Defines the layout of the paca.
diff --git a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h
index bcd21789d3b..a5893a305a0 100644
--- a/include/asm-ppc64/page.h
+++ b/include/asm-ppc64/page.h
@@ -202,9 +202,7 @@ extern u64 ppc64_pft_size; /* Log 2 of page table size */
#define PAGE_OFFSET ASM_CONST(0xC000000000000000)
#define KERNELBASE PAGE_OFFSET
#define VMALLOCBASE ASM_CONST(0xD000000000000000)
-#define IOREGIONBASE ASM_CONST(0xE000000000000000)
-#define IO_REGION_ID (IOREGIONBASE >> REGION_SHIFT)
#define VMALLOC_REGION_ID (VMALLOCBASE >> REGION_SHIFT)
#define KERNEL_REGION_ID (KERNELBASE >> REGION_SHIFT)
#define USER_REGION_ID (0UL)
@@ -219,7 +217,8 @@ extern u64 ppc64_pft_size; /* Log 2 of page table size */
#define page_to_pfn(page) discontigmem_page_to_pfn(page)
#define pfn_to_page(pfn) discontigmem_pfn_to_page(pfn)
#define pfn_valid(pfn) discontigmem_pfn_valid(pfn)
-#else
+#endif
+#ifdef CONFIG_FLATMEM
#define pfn_to_page(pfn) (mem_map + (pfn))
#define page_to_pfn(page) ((unsigned long)((page) - mem_map))
#define pfn_valid(pfn) ((pfn) < max_mapnr)
diff --git a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h
index 264c4f7993b..46cf61c2ff6 100644
--- a/include/asm-ppc64/pgtable.h
+++ b/include/asm-ppc64/pgtable.h
@@ -53,7 +53,8 @@
* Define the address range of the vmalloc VM area.
*/
#define VMALLOC_START (0xD000000000000000ul)
-#define VMALLOC_END (VMALLOC_START + EADDR_MASK)
+#define VMALLOC_SIZE (0x10000000000UL)
+#define VMALLOC_END (VMALLOC_START + VMALLOC_SIZE)
/*
* Bits in a linux-style PTE. These match the bits in the
@@ -239,9 +240,6 @@ static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot)
/* This now only contains the vmalloc pages */
#define pgd_offset_k(address) pgd_offset(&init_mm, address)
-/* to find an entry in the ioremap page-table-directory */
-#define pgd_offset_i(address) (ioremap_pgd + pgd_index(address))
-
/*
* The following only work if pte_present() is true.
* Undefined behaviour if not..
@@ -459,15 +457,12 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long addr,
#define __HAVE_ARCH_PTE_SAME
#define pte_same(A,B) (((pte_val(A) ^ pte_val(B)) & ~_PAGE_HPTEFLAGS) == 0)
-extern unsigned long ioremap_bot, ioremap_base;
-
#define pmd_ERROR(e) \
printk("%s:%d: bad pmd %08x.\n", __FILE__, __LINE__, pmd_val(e))
#define pgd_ERROR(e) \
printk("%s:%d: bad pgd %08x.\n", __FILE__, __LINE__, pgd_val(e))
extern pgd_t swapper_pg_dir[];
-extern pgd_t ioremap_dir[];
extern void paging_init(void);
diff --git a/include/asm-ppc64/ppc32.h b/include/asm-ppc64/ppc32.h
index 1d040489755..6b44a8caf39 100644
--- a/include/asm-ppc64/ppc32.h
+++ b/include/asm-ppc64/ppc32.h
@@ -32,7 +32,7 @@ typedef struct compat_siginfo {
/* POSIX.1b timers */
struct {
- timer_t _tid; /* timer id */
+ compat_timer_t _tid; /* timer id */
int _overrun; /* overrun count */
compat_sigval_t _sigval; /* same as below */
int _sys_private; /* not to be passed to user */
diff --git a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h
index 0035efe2db2..af28aa55d8c 100644
--- a/include/asm-ppc64/processor.h
+++ b/include/asm-ppc64/processor.h
@@ -120,128 +120,36 @@
/* Special Purpose Registers (SPRNs)*/
-#define SPRN_CDBCR 0x3D7 /* Cache Debug Control Register */
#define SPRN_CTR 0x009 /* Count Register */
#define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */
-#define SPRN_DAC1 0x3F6 /* Data Address Compare 1 */
-#define SPRN_DAC2 0x3F7 /* Data Address Compare 2 */
+#define DABR_TRANSLATION (1UL << 2)
#define SPRN_DAR 0x013 /* Data Address Register */
-#define SPRN_DBCR 0x3F2 /* Debug Control Regsiter */
-#define DBCR_EDM 0x80000000
-#define DBCR_IDM 0x40000000
-#define DBCR_RST(x) (((x) & 0x3) << 28)
-#define DBCR_RST_NONE 0
-#define DBCR_RST_CORE 1
-#define DBCR_RST_CHIP 2
-#define DBCR_RST_SYSTEM 3
-#define DBCR_IC 0x08000000 /* Instruction Completion Debug Evnt */
-#define DBCR_BT 0x04000000 /* Branch Taken Debug Event */
-#define DBCR_EDE 0x02000000 /* Exception Debug Event */
-#define DBCR_TDE 0x01000000 /* TRAP Debug Event */
-#define DBCR_FER 0x00F80000 /* First Events Remaining Mask */
-#define DBCR_FT 0x00040000 /* Freeze Timers on Debug Event */
-#define DBCR_IA1 0x00020000 /* Instr. Addr. Compare 1 Enable */
-#define DBCR_IA2 0x00010000 /* Instr. Addr. Compare 2 Enable */
-#define DBCR_D1R 0x00008000 /* Data Addr. Compare 1 Read Enable */
-#define DBCR_D1W 0x00004000 /* Data Addr. Compare 1 Write Enable */
-#define DBCR_D1S(x) (((x) & 0x3) << 12) /* Data Adrr. Compare 1 Size */
-#define DAC_BYTE 0
-#define DAC_HALF 1
-#define DAC_WORD 2
-#define DAC_QUAD 3
-#define DBCR_D2R 0x00000800 /* Data Addr. Compare 2 Read Enable */
-#define DBCR_D2W 0x00000400 /* Data Addr. Compare 2 Write Enable */
-#define DBCR_D2S(x) (((x) & 0x3) << 8) /* Data Addr. Compare 2 Size */
-#define DBCR_SBT 0x00000040 /* Second Branch Taken Debug Event */
-#define DBCR_SED 0x00000020 /* Second Exception Debug Event */
-#define DBCR_STD 0x00000010 /* Second Trap Debug Event */
-#define DBCR_SIA 0x00000008 /* Second IAC Enable */
-#define DBCR_SDA 0x00000004 /* Second DAC Enable */
-#define DBCR_JOI 0x00000002 /* JTAG Serial Outbound Int. Enable */
-#define DBCR_JII 0x00000001 /* JTAG Serial Inbound Int. Enable */
-#define SPRN_DBCR0 0x3F2 /* Debug Control Register 0 */
-#define SPRN_DBCR1 0x3BD /* Debug Control Register 1 */
-#define SPRN_DBSR 0x3F0 /* Debug Status Register */
-#define SPRN_DCCR 0x3FA /* Data Cache Cacheability Register */
-#define DCCR_NOCACHE 0 /* Noncacheable */
-#define DCCR_CACHE 1 /* Cacheable */
-#define SPRN_DCMP 0x3D1 /* Data TLB Compare Register */
-#define SPRN_DCWR 0x3BA /* Data Cache Write-thru Register */
-#define DCWR_COPY 0 /* Copy-back */
-#define DCWR_WRITE 1 /* Write-through */
-#define SPRN_DEAR 0x3D5 /* Data Error Address Register */
#define SPRN_DEC 0x016 /* Decrement Register */
-#define SPRN_DMISS 0x3D0 /* Data TLB Miss Register */
#define SPRN_DSISR 0x012 /* Data Storage Interrupt Status Register */
#define DSISR_NOHPTE 0x40000000 /* no translation found */
#define DSISR_PROTFAULT 0x08000000 /* protection fault */
#define DSISR_ISSTORE 0x02000000 /* access was a store */
#define DSISR_DABRMATCH 0x00400000 /* hit data breakpoint */
#define DSISR_NOSEGMENT 0x00200000 /* STAB/SLB miss */
-#define SPRN_EAR 0x11A /* External Address Register */
-#define SPRN_ESR 0x3D4 /* Exception Syndrome Register */
-#define ESR_IMCP 0x80000000 /* Instr. Machine Check - Protection */
-#define ESR_IMCN 0x40000000 /* Instr. Machine Check - Non-config */
-#define ESR_IMCB 0x20000000 /* Instr. Machine Check - Bus error */
-#define ESR_IMCT 0x10000000 /* Instr. Machine Check - Timeout */
-#define ESR_PIL 0x08000000 /* Program Exception - Illegal */
-#define ESR_PPR 0x04000000 /* Program Exception - Priveleged */
-#define ESR_PTR 0x02000000 /* Program Exception - Trap */
-#define ESR_DST 0x00800000 /* Storage Exception - Data miss */
-#define ESR_DIZ 0x00400000 /* Storage Exception - Zone fault */
-#define SPRN_EVPR 0x3D6 /* Exception Vector Prefix Register */
-#define SPRN_HASH1 0x3D2 /* Primary Hash Address Register */
-#define SPRN_HASH2 0x3D3 /* Secondary Hash Address Resgister */
#define SPRN_HID0 0x3F0 /* Hardware Implementation Register 0 */
-#define HID0_EMCP (1<<31) /* Enable Machine Check pin */
-#define HID0_EBA (1<<29) /* Enable Bus Address Parity */
-#define HID0_EBD (1<<28) /* Enable Bus Data Parity */
-#define HID0_SBCLK (1<<27)
-#define HID0_EICE (1<<26)
-#define HID0_ECLK (1<<25)
-#define HID0_PAR (1<<24)
-#define HID0_DOZE (1<<23)
-#define HID0_NAP (1<<22)
-#define HID0_SLEEP (1<<21)
-#define HID0_DPM (1<<20)
-#define HID0_ICE (1<<15) /* Instruction Cache Enable */
-#define HID0_DCE (1<<14) /* Data Cache Enable */
-#define HID0_ILOCK (1<<13) /* Instruction Cache Lock */
-#define HID0_DLOCK (1<<12) /* Data Cache Lock */
-#define HID0_ICFI (1<<11) /* Instr. Cache Flash Invalidate */
-#define HID0_DCI (1<<10) /* Data Cache Invalidate */
-#define HID0_SPD (1<<9) /* Speculative disable */
-#define HID0_SGE (1<<7) /* Store Gathering Enable */
-#define HID0_SIED (1<<7) /* Serial Instr. Execution [Disable] */
-#define HID0_BTIC (1<<5) /* Branch Target Instruction Cache Enable */
-#define HID0_ABE (1<<3) /* Address Broadcast Enable */
-#define HID0_BHTE (1<<2) /* Branch History Table Enable */
-#define HID0_BTCD (1<<1) /* Branch target cache disable */
#define SPRN_MSRDORM 0x3F1 /* Hardware Implementation Register 1 */
#define SPRN_HID1 0x3F1 /* Hardware Implementation Register 1 */
#define SPRN_IABR 0x3F2 /* Instruction Address Breakpoint Register */
#define SPRN_NIADORM 0x3F3 /* Hardware Implementation Register 2 */
#define SPRN_HID4 0x3F4 /* 970 HID4 */
#define SPRN_HID5 0x3F6 /* 970 HID5 */
-#define SPRN_TSC 0x3FD /* Thread switch control */
-#define SPRN_TST 0x3FC /* Thread switch timeout */
-#define SPRN_IAC1 0x3F4 /* Instruction Address Compare 1 */
-#define SPRN_IAC2 0x3F5 /* Instruction Address Compare 2 */
-#define SPRN_ICCR 0x3FB /* Instruction Cache Cacheability Register */
-#define ICCR_NOCACHE 0 /* Noncacheable */
-#define ICCR_CACHE 1 /* Cacheable */
-#define SPRN_ICDBDR 0x3D3 /* Instruction Cache Debug Data Register */
-#define SPRN_ICMP 0x3D5 /* Instruction TLB Compare Register */
-#define SPRN_ICTC 0x3FB /* Instruction Cache Throttling Control Reg */
-#define SPRN_IMISS 0x3D4 /* Instruction TLB Miss Register */
-#define SPRN_IMMR 0x27E /* Internal Memory Map Register */
+#define SPRN_HID6 0x3F9 /* BE HID 6 */
+#define HID6_LB (0x0F<<12) /* Concurrent Large Page Modes */
+#define HID6_DLP (1<<20) /* Disable all large page modes (4K only) */
+#define SPRN_TSCR 0x399 /* Thread switch control on BE */
+#define SPRN_TTR 0x39A /* Thread switch timeout on BE */
+#define TSCR_DEC_ENABLE 0x200000 /* Decrementer Interrupt */
+#define TSCR_EE_ENABLE 0x100000 /* External Interrupt */
+#define TSCR_EE_BOOST 0x080000 /* External Interrupt Boost */
+#define SPRN_TSC 0x3FD /* Thread switch control on others */
+#define SPRN_TST 0x3FC /* Thread switch timeout on others */
#define SPRN_L2CR 0x3F9 /* Level 2 Cache Control Regsiter */
#define SPRN_LR 0x008 /* Link Register */
-#define SPRN_PBL1 0x3FC /* Protection Bound Lower 1 */
-#define SPRN_PBL2 0x3FE /* Protection Bound Lower 2 */
-#define SPRN_PBU1 0x3FD /* Protection Bound Upper 1 */
-#define SPRN_PBU2 0x3FF /* Protection Bound Upper 2 */
-#define SPRN_PID 0x3B1 /* Process ID */
#define SPRN_PIR 0x3FF /* Processor Identification Register */
#define SPRN_PIT 0x3DB /* Programmable Interval Timer */
#define SPRN_PURR 0x135 /* Processor Utilization of Resources Register */
@@ -249,9 +157,6 @@
#define SPRN_RPA 0x3D6 /* Required Physical Address Register */
#define SPRN_SDA 0x3BF /* Sampled Data Address Register */
#define SPRN_SDR1 0x019 /* MMU Hash Base Register */
-#define SPRN_SGR 0x3B9 /* Storage Guarded Register */
-#define SGR_NORMAL 0
-#define SGR_GUARDED 1
#define SPRN_SIA 0x3BB /* Sampled Instruction Address Register */
#define SPRN_SPRG0 0x110 /* Special Purpose Register General 0 */
#define SPRN_SPRG1 0x111 /* Special Purpose Register General 1 */
@@ -264,50 +169,12 @@
#define SPRN_TBWL 0x11C /* Time Base Lower Register (super, W/O) */
#define SPRN_TBWU 0x11D /* Time Base Write Upper Register (super, W/O) */
#define SPRN_HIOR 0x137 /* 970 Hypervisor interrupt offset */
-#define SPRN_TCR 0x3DA /* Timer Control Register */
-#define TCR_WP(x) (((x)&0x3)<<30) /* WDT Period */
-#define WP_2_17 0 /* 2^17 clocks */
-#define WP_2_21 1 /* 2^21 clocks */
-#define WP_2_25 2 /* 2^25 clocks */
-#define WP_2_29 3 /* 2^29 clocks */
-#define TCR_WRC(x) (((x)&0x3)<<28) /* WDT Reset Control */
-#define WRC_NONE 0 /* No reset will occur */
-#define WRC_CORE 1 /* Core reset will occur */
-#define WRC_CHIP 2 /* Chip reset will occur */
-#define WRC_SYSTEM 3 /* System reset will occur */
-#define TCR_WIE 0x08000000 /* WDT Interrupt Enable */
-#define TCR_PIE 0x04000000 /* PIT Interrupt Enable */
-#define TCR_FP(x) (((x)&0x3)<<24) /* FIT Period */
-#define FP_2_9 0 /* 2^9 clocks */
-#define FP_2_13 1 /* 2^13 clocks */
-#define FP_2_17 2 /* 2^17 clocks */
-#define FP_2_21 3 /* 2^21 clocks */
-#define TCR_FIE 0x00800000 /* FIT Interrupt Enable */
-#define TCR_ARE 0x00400000 /* Auto Reload Enable */
-#define SPRN_THRM1 0x3FC /* Thermal Management Register 1 */
-#define THRM1_TIN (1<<0)
-#define THRM1_TIV (1<<1)
-#define THRM1_THRES (0x7f<<2)
-#define THRM1_TID (1<<29)
-#define THRM1_TIE (1<<30)
-#define THRM1_V (1<<31)
-#define SPRN_THRM2 0x3FD /* Thermal Management Register 2 */
-#define SPRN_THRM3 0x3FE /* Thermal Management Register 3 */
-#define THRM3_E (1<<31)
-#define SPRN_TSR 0x3D8 /* Timer Status Register */
-#define TSR_ENW 0x80000000 /* Enable Next Watchdog */
-#define TSR_WIS 0x40000000 /* WDT Interrupt Status */
-#define TSR_WRS(x) (((x)&0x3)<<28) /* WDT Reset Status */
-#define WRS_NONE 0 /* No WDT reset occurred */
-#define WRS_CORE 1 /* WDT forced core reset */
-#define WRS_CHIP 2 /* WDT forced chip reset */
-#define WRS_SYSTEM 3 /* WDT forced system reset */
-#define TSR_PIS 0x08000000 /* PIT Interrupt Status */
-#define TSR_FIS 0x04000000 /* FIT Interrupt Status */
#define SPRN_USIA 0x3AB /* User Sampled Instruction Address Register */
#define SPRN_XER 0x001 /* Fixed Point Exception Register */
-#define SPRN_ZPR 0x3B0 /* Zone Protection Register */
#define SPRN_VRSAVE 0x100 /* Vector save */
+#define SPRN_CTRLF 0x088
+#define SPRN_CTRLT 0x098
+#define CTRL_RUNLATCH 0x1
/* Performance monitor SPRs */
#define SPRN_SIAR 780
@@ -352,28 +219,19 @@
#define CTR SPRN_CTR /* Counter Register */
#define DAR SPRN_DAR /* Data Address Register */
#define DABR SPRN_DABR /* Data Address Breakpoint Register */
-#define DCMP SPRN_DCMP /* Data TLB Compare Register */
#define DEC SPRN_DEC /* Decrement Register */
-#define DMISS SPRN_DMISS /* Data TLB Miss Register */
#define DSISR SPRN_DSISR /* Data Storage Interrupt Status Register */
-#define EAR SPRN_EAR /* External Address Register */
-#define HASH1 SPRN_HASH1 /* Primary Hash Address Register */
-#define HASH2 SPRN_HASH2 /* Secondary Hash Address Register */
#define HID0 SPRN_HID0 /* Hardware Implementation Register 0 */
#define MSRDORM SPRN_MSRDORM /* MSR Dormant Register */
#define NIADORM SPRN_NIADORM /* NIA Dormant Register */
#define TSC SPRN_TSC /* Thread switch control */
#define TST SPRN_TST /* Thread switch timeout */
#define IABR SPRN_IABR /* Instruction Address Breakpoint Register */
-#define ICMP SPRN_ICMP /* Instruction TLB Compare Register */
-#define IMISS SPRN_IMISS /* Instruction TLB Miss Register */
-#define IMMR SPRN_IMMR /* PPC 860/821 Internal Memory Map Register */
#define L2CR SPRN_L2CR /* PPC 750 L2 control register */
#define __LR SPRN_LR
#define PVR SPRN_PVR /* Processor Version */
#define PIR SPRN_PIR /* Processor ID */
#define PURR SPRN_PURR /* Processor Utilization of Resource Register */
-//#define RPA SPRN_RPA /* Required Physical Address Register */
#define SDR1 SPRN_SDR1 /* MMU hash base register */
#define SPR0 SPRN_SPRG0 /* Supervisor Private Registers */
#define SPR1 SPRN_SPRG1
@@ -389,10 +247,6 @@
#define TBRU SPRN_TBRU /* Time Base Read Upper Register */
#define TBWL SPRN_TBWL /* Time Base Write Lower Register */
#define TBWU SPRN_TBWU /* Time Base Write Upper Register */
-#define ICTC 1019
-#define THRM1 SPRN_THRM1 /* Thermal Management Register 1 */
-#define THRM2 SPRN_THRM2 /* Thermal Management Register 2 */
-#define THRM3 SPRN_THRM3 /* Thermal Management Register 3 */
#define XER SPRN_XER
/* Processor Version Register (PVR) field extraction */
@@ -413,6 +267,7 @@
#define PV_970FX 0x003C
#define PV_630 0x0040
#define PV_630p 0x0041
+#define PV_BE 0x0070
/* Platforms supported by PPC64 */
#define PLATFORM_PSERIES 0x0100
@@ -421,6 +276,7 @@
#define PLATFORM_LPAR 0x0001
#define PLATFORM_POWERMAC 0x0400
#define PLATFORM_MAPLE 0x0500
+#define PLATFORM_BPA 0x1000
/* Compatibility with drivers coming from PPC32 world */
#define _machine (systemcfg->platform)
@@ -432,16 +288,11 @@
#define IC_INVALID 0
#define IC_OPEN_PIC 1
#define IC_PPC_XIC 2
+#define IC_BPA_IIC 3
#define XGLUE(a,b) a##b
#define GLUE(a,b) XGLUE(a,b)
-/* iSeries CTRL register (for runlatch) */
-
-#define CTRLT 0x098
-#define CTRLF 0x088
-#define RUNLATCH 0x0001
-
#ifdef __ASSEMBLY__
#define _GLOBAL(name) \
@@ -590,16 +441,6 @@ struct thread_struct {
}
/*
- * Note: the vm_start and vm_end fields here should *not*
- * be in kernel space. (Could vm_end == vm_start perhaps?)
- */
-#define IOREMAP_MMAP { &ioremap_mm, 0, 0x1000, NULL, \
- PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, \
- 1, NULL, NULL }
-
-extern struct mm_struct ioremap_mm;
-
-/*
* Return saved PC of a blocked thread. For now, this is the "user" PC
*/
#define thread_saved_pc(tsk) \
@@ -656,6 +497,24 @@ static inline void prefetchw(const void *x)
#define HAVE_ARCH_PICK_MMAP_LAYOUT
+static inline void ppc64_runlatch_on(void)
+{
+ unsigned long ctrl;
+
+ ctrl = mfspr(SPRN_CTRLF);
+ ctrl |= CTRL_RUNLATCH;
+ mtspr(SPRN_CTRLT, ctrl);
+}
+
+static inline void ppc64_runlatch_off(void)
+{
+ unsigned long ctrl;
+
+ ctrl = mfspr(SPRN_CTRLF);
+ ctrl &= ~CTRL_RUNLATCH;
+ mtspr(SPRN_CTRLT, ctrl);
+}
+
#endif /* __KERNEL__ */
#endif /* __ASSEMBLY__ */
diff --git a/include/asm-ppc64/prom.h b/include/asm-ppc64/prom.h
index 2440a2c90ae..04b1a84f7ca 100644
--- a/include/asm-ppc64/prom.h
+++ b/include/asm-ppc64/prom.h
@@ -147,9 +147,7 @@ struct device_node {
struct device_node *sibling;
struct device_node *next; /* next device of same type */
struct device_node *allnext; /* next in list of all nodes */
- struct proc_dir_entry *pde; /* this node's proc directory */
- struct proc_dir_entry *name_link; /* name symlink */
- struct proc_dir_entry *addr_link; /* addr symlink */
+ struct proc_dir_entry *pde; /* this node's proc directory */
struct kref kref;
unsigned long _flags;
};
@@ -174,15 +172,6 @@ static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_e
dn->pde = de;
}
-static void inline set_node_name_link(struct device_node *dn, struct proc_dir_entry *de)
-{
- dn->name_link = de;
-}
-
-static void inline set_node_addr_link(struct device_node *dn, struct proc_dir_entry *de)
-{
- dn->addr_link = de;
-}
/* OBSOLETE: Old stlye node lookup */
extern struct device_node *find_devices(const char *name);
diff --git a/include/asm-ppc64/rtas.h b/include/asm-ppc64/rtas.h
index a8ab0e9db84..e7d1b522280 100644
--- a/include/asm-ppc64/rtas.h
+++ b/include/asm-ppc64/rtas.h
@@ -186,8 +186,14 @@ extern int rtas_get_sensor(int sensor, int index, int *state);
extern int rtas_get_power_level(int powerdomain, int *level);
extern int rtas_set_power_level(int powerdomain, int level, int *setlevel);
extern int rtas_set_indicator(int indicator, int index, int new_value);
+extern void rtas_progress(char *s, unsigned short hex);
extern void rtas_initialize(void);
+struct rtc_time;
+extern void rtas_get_boot_time(struct rtc_time *rtc_time);
+extern void rtas_get_rtc_time(struct rtc_time *rtc_time);
+extern int rtas_set_rtc_time(struct rtc_time *rtc_time);
+
/* Given an RTAS status code of 9900..9905 compute the hinted delay */
unsigned int rtas_extended_busy_delay_time(int status);
static inline int rtas_is_extended_busy(int status)
diff --git a/include/asm-ppc64/smp.h b/include/asm-ppc64/smp.h
index c8646fa999c..d86f742e9a2 100644
--- a/include/asm-ppc64/smp.h
+++ b/include/asm-ppc64/smp.h
@@ -45,7 +45,7 @@ void generic_cpu_die(unsigned int cpu);
void generic_mach_cpu_die(void);
#endif
-#define __smp_processor_id() (get_paca()->paca_index)
+#define raw_smp_processor_id() (get_paca()->paca_index)
#define hard_smp_processor_id() (get_paca()->hw_cpu_id)
extern cpumask_t cpu_sibling_map[NR_CPUS];
@@ -85,6 +85,14 @@ extern void smp_generic_take_timebase(void);
extern struct smp_ops_t *smp_ops;
+#ifdef CONFIG_PPC_PSERIES
+void vpa_init(int cpu);
+#else
+static inline void vpa_init(int cpu)
+{
+}
+#endif /* CONFIG_PPC_PSERIES */
+
#endif /* __ASSEMBLY__ */
#endif /* !(_PPC64_SMP_H) */
diff --git a/include/asm-ppc64/sparsemem.h b/include/asm-ppc64/sparsemem.h
new file mode 100644
index 00000000000..c5bd47e57f1
--- /dev/null
+++ b/include/asm-ppc64/sparsemem.h
@@ -0,0 +1,16 @@
+#ifndef _ASM_PPC64_SPARSEMEM_H
+#define _ASM_PPC64_SPARSEMEM_H 1
+
+#ifdef CONFIG_SPARSEMEM
+/*
+ * SECTION_SIZE_BITS 2^N: how big each section will be
+ * MAX_PHYSADDR_BITS 2^N: how much physical address space we have
+ * MAX_PHYSMEM_BITS 2^N: how much memory we can have in that space
+ */
+#define SECTION_SIZE_BITS 24
+#define MAX_PHYSADDR_BITS 38
+#define MAX_PHYSMEM_BITS 36
+
+#endif /* CONFIG_SPARSEMEM */
+
+#endif /* _ASM_PPC64_SPARSEMEM_H */
diff --git a/include/asm-ppc64/thread_info.h b/include/asm-ppc64/thread_info.h
index 037b5e06083..0494df6fca7 100644
--- a/include/asm-ppc64/thread_info.h
+++ b/include/asm-ppc64/thread_info.h
@@ -24,7 +24,7 @@ struct thread_info {
struct task_struct *task; /* main task structure */
struct exec_domain *exec_domain; /* execution domain */
int cpu; /* cpu we're on */
- int preempt_count;
+ int preempt_count; /* 0 => preemptable, <0 => BUG */
struct restart_block restart_block;
/* set by force_successful_syscall_return */
unsigned char syscall_noerror;
@@ -96,7 +96,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_POLLING_NRFLAG 4 /* true if poll_idle() is polling
TIF_NEED_RESCHED */
#define TIF_32BIT 5 /* 32 bit binary */
-#define TIF_RUN_LIGHT 6 /* iSeries run light */
+/* #define SPARE 6 */
#define TIF_ABI_PENDING 7 /* 32/64 bit switch needed */
#define TIF_SYSCALL_AUDIT 8 /* syscall auditing active */
#define TIF_SINGLESTEP 9 /* singlestepping active */
@@ -110,7 +110,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
#define _TIF_32BIT (1<<TIF_32BIT)
-#define _TIF_RUN_LIGHT (1<<TIF_RUN_LIGHT)
+/* #define _SPARE (1<<SPARE) */
#define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING)
#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
diff --git a/include/asm-ppc64/time.h b/include/asm-ppc64/time.h
index 8d6e3760ee1..c6c762cad8b 100644
--- a/include/asm-ppc64/time.h
+++ b/include/asm-ppc64/time.h
@@ -34,6 +34,15 @@ struct rtc_time;
extern void to_tm(int tim, struct rtc_time * tm);
extern time_t last_rtc_update;
+void generic_calibrate_decr(void);
+void setup_default_decr(void);
+
+/* Some sane defaults: 125 MHz timebase, 1GHz processor */
+extern unsigned long ppc_proc_freq;
+#define DEFAULT_PROC_FREQ (DEFAULT_TB_FREQ * 8)
+extern unsigned long ppc_tb_freq;
+#define DEFAULT_TB_FREQ 125000000UL
+
/*
* By putting all of this stuff into a single struct we
* reduce the number of cache lines touched by do_gettimeofday.
diff --git a/include/asm-ppc64/topology.h b/include/asm-ppc64/topology.h
index d58d9dd7999..fcdcfd26a26 100644
--- a/include/asm-ppc64/topology.h
+++ b/include/asm-ppc64/topology.h
@@ -59,10 +59,8 @@ static inline int node_to_first_cpu(int node)
.nr_balance_failed = 0, \
}
-#else /* !CONFIG_NUMA */
+#endif /* CONFIG_NUMA */
#include <asm-generic/topology.h>
-#endif /* CONFIG_NUMA */
-
#endif /* _ASM_PPC64_TOPOLOGY_H */
diff --git a/include/asm-ppc64/xics.h b/include/asm-ppc64/xics.h
index fdec5e7a7af..0c45e14e26c 100644
--- a/include/asm-ppc64/xics.h
+++ b/include/asm-ppc64/xics.h
@@ -17,6 +17,7 @@
void xics_init_IRQ(void);
int xics_get_irq(struct pt_regs *);
void xics_setup_cpu(void);
+void xics_teardown_cpu(void);
void xics_cause_IPI(int cpu);
void xics_request_IPIs(void);
void xics_migrate_irqs_away(void);
diff --git a/include/asm-s390/cpcmd.h b/include/asm-s390/cpcmd.h
index 1d33c5da083..1fcf65be7a2 100644
--- a/include/asm-s390/cpcmd.h
+++ b/include/asm-s390/cpcmd.h
@@ -11,14 +11,28 @@
#define __CPCMD__
/*
+ * the lowlevel function for cpcmd
* the caller of __cpcmd has to ensure that the response buffer is below 2 GB
*/
-extern void __cpcmd(char *cmd, char *response, int rlen);
+extern int __cpcmd(const char *cmd, char *response, int rlen, int *response_code);
#ifndef __s390x__
#define cpcmd __cpcmd
#else
-extern void cpcmd(char *cmd, char *response, int rlen);
+/*
+ * cpcmd is the in-kernel interface for issuing CP commands
+ *
+ * cmd: null-terminated command string, max 240 characters
+ * response: response buffer for VM's textual response
+ * rlen: size of the response buffer, cpcmd will not exceed this size
+ * but will cap the output, if its too large. Everything that
+ * did not fit into the buffer will be silently dropped
+ * response_code: return pointer for VM's error code
+ * return value: the size of the response. The caller can check if the buffer
+ * was large enough by comparing the return value and rlen
+ * NOTE: If the response buffer is not below 2 GB, cpcmd can sleep
+ */
+extern int cpcmd(const char *cmd, char *response, int rlen, int *response_code);
#endif /*__s390x__*/
#endif
diff --git a/include/asm-s390/debug.h b/include/asm-s390/debug.h
index 6bbcdea42a8..92360d90144 100644
--- a/include/asm-s390/debug.h
+++ b/include/asm-s390/debug.h
@@ -9,6 +9,8 @@
#ifndef DEBUG_H
#define DEBUG_H
+#include <linux/config.h>
+#include <linux/fs.h>
#include <linux/string.h>
/* Note:
@@ -31,19 +33,18 @@ struct __debug_entry{
} __attribute__((packed));
-#define __DEBUG_FEATURE_VERSION 1 /* version of debug feature */
+#define __DEBUG_FEATURE_VERSION 2 /* version of debug feature */
#ifdef __KERNEL__
#include <linux/spinlock.h>
#include <linux/kernel.h>
#include <linux/time.h>
-#include <linux/proc_fs.h>
#define DEBUG_MAX_LEVEL 6 /* debug levels range from 0 to 6 */
#define DEBUG_OFF_LEVEL -1 /* level where debug is switched off */
#define DEBUG_FLUSH_ALL -1 /* parameter to flush all areas */
#define DEBUG_MAX_VIEWS 10 /* max number of views in proc fs */
-#define DEBUG_MAX_PROCF_LEN 64 /* max length for a proc file name */
+#define DEBUG_MAX_NAME_LEN 64 /* max length for a debugfs file name */
#define DEBUG_DEFAULT_LEVEL 3 /* initial debug level */
#define DEBUG_DIR_ROOT "s390dbf" /* name of debug root directory in proc fs */
@@ -64,16 +65,17 @@ typedef struct debug_info {
spinlock_t lock;
int level;
int nr_areas;
- int page_order;
+ int pages_per_area;
int buf_size;
int entry_size;
- debug_entry_t** areas;
+ debug_entry_t*** areas;
int active_area;
- int *active_entry;
- struct proc_dir_entry* proc_root_entry;
- struct proc_dir_entry* proc_entries[DEBUG_MAX_VIEWS];
+ int *active_pages;
+ int *active_entries;
+ struct dentry* debugfs_root_entry;
+ struct dentry* debugfs_entries[DEBUG_MAX_VIEWS];
struct debug_view* views[DEBUG_MAX_VIEWS];
- char name[DEBUG_MAX_PROCF_LEN];
+ char name[DEBUG_MAX_NAME_LEN];
} debug_info_t;
typedef int (debug_header_proc_t) (debug_info_t* id,
@@ -98,7 +100,7 @@ int debug_dflt_header_fn(debug_info_t* id, struct debug_view* view,
int area, debug_entry_t* entry, char* out_buf);
struct debug_view {
- char name[DEBUG_MAX_PROCF_LEN];
+ char name[DEBUG_MAX_NAME_LEN];
debug_prolog_proc_t* prolog_proc;
debug_header_proc_t* header_proc;
debug_format_proc_t* format_proc;
@@ -120,7 +122,7 @@ debug_entry_t* debug_exception_common(debug_info_t* id, int level,
/* Debug Feature API: */
-debug_info_t* debug_register(char* name, int pages_index, int nr_areas,
+debug_info_t* debug_register(char* name, int pages, int nr_areas,
int buf_size);
void debug_unregister(debug_info_t* id);
@@ -132,7 +134,8 @@ void debug_stop_all(void);
extern inline debug_entry_t*
debug_event(debug_info_t* id, int level, void* data, int length)
{
- if ((!id) || (level > id->level)) return NULL;
+ if ((!id) || (level > id->level) || (id->pages_per_area == 0))
+ return NULL;
return debug_event_common(id,level,data,length);
}
@@ -140,7 +143,8 @@ extern inline debug_entry_t*
debug_int_event(debug_info_t* id, int level, unsigned int tag)
{
unsigned int t=tag;
- if ((!id) || (level > id->level)) return NULL;
+ if ((!id) || (level > id->level) || (id->pages_per_area == 0))
+ return NULL;
return debug_event_common(id,level,&t,sizeof(unsigned int));
}
@@ -148,14 +152,16 @@ extern inline debug_entry_t *
debug_long_event (debug_info_t* id, int level, unsigned long tag)
{
unsigned long t=tag;
- if ((!id) || (level > id->level)) return NULL;
+ if ((!id) || (level > id->level) || (id->pages_per_area == 0))
+ return NULL;
return debug_event_common(id,level,&t,sizeof(unsigned long));
}
extern inline debug_entry_t*
debug_text_event(debug_info_t* id, int level, const char* txt)
{
- if ((!id) || (level > id->level)) return NULL;
+ if ((!id) || (level > id->level) || (id->pages_per_area == 0))
+ return NULL;
return debug_event_common(id,level,txt,strlen(txt));
}
@@ -167,7 +173,8 @@ debug_sprintf_event(debug_info_t* id,int level,char *string,...)
extern inline debug_entry_t*
debug_exception(debug_info_t* id, int level, void* data, int length)
{
- if ((!id) || (level > id->level)) return NULL;
+ if ((!id) || (level > id->level) || (id->pages_per_area == 0))
+ return NULL;
return debug_exception_common(id,level,data,length);
}
@@ -175,7 +182,8 @@ extern inline debug_entry_t*
debug_int_exception(debug_info_t* id, int level, unsigned int tag)
{
unsigned int t=tag;
- if ((!id) || (level > id->level)) return NULL;
+ if ((!id) || (level > id->level) || (id->pages_per_area == 0))
+ return NULL;
return debug_exception_common(id,level,&t,sizeof(unsigned int));
}
@@ -183,14 +191,16 @@ extern inline debug_entry_t *
debug_long_exception (debug_info_t* id, int level, unsigned long tag)
{
unsigned long t=tag;
- if ((!id) || (level > id->level)) return NULL;
+ if ((!id) || (level > id->level) || (id->pages_per_area == 0))
+ return NULL;
return debug_exception_common(id,level,&t,sizeof(unsigned long));
}
extern inline debug_entry_t*
debug_text_exception(debug_info_t* id, int level, const char* txt)
{
- if ((!id) || (level > id->level)) return NULL;
+ if ((!id) || (level > id->level) || (id->pages_per_area == 0))
+ return NULL;
return debug_exception_common(id,level,txt,strlen(txt));
}
diff --git a/include/asm-s390/kexec.h b/include/asm-s390/kexec.h
new file mode 100644
index 00000000000..54cf7d9f251
--- /dev/null
+++ b/include/asm-s390/kexec.h
@@ -0,0 +1,42 @@
+/*
+ * include/asm-s390/kexec.h
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com>
+ *
+ */
+
+#ifndef _S390_KEXEC_H
+#define _S390_KEXEC_H
+
+#include <asm/page.h>
+#include <asm/processor.h>
+/*
+ * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return.
+ * I.e. Maximum page that is mapped directly into kernel memory,
+ * and kmap is not required.
+ */
+
+/* Maximum physical address we can use pages from */
+#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
+
+/* Maximum address we can reach in physical address mode */
+#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
+
+/* Maximum address we can use for the control pages */
+/* Not more than 2GB */
+#define KEXEC_CONTROL_MEMORY_LIMIT (1<<31)
+
+/* Allocate one page for the pdp and the second for the code */
+#define KEXEC_CONTROL_CODE_SIZE 4096
+
+/* The native architecture */
+#define KEXEC_ARCH KEXEC_ARCH_S390
+
+#define MAX_NOTE_BYTES 1024
+typedef u32 note_buf_t[MAX_NOTE_BYTES/4];
+
+extern note_buf_t crash_notes[];
+
+#endif /*_S390_KEXEC_H */
diff --git a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h
index df5172fc589..76b5b19c0ae 100644
--- a/include/asm-s390/lowcore.h
+++ b/include/asm-s390/lowcore.h
@@ -109,10 +109,14 @@
#ifndef __s390x__
#define __LC_PFAULT_INTPARM 0x080
+#define __LC_CPU_TIMER_SAVE_AREA 0x0D8
#define __LC_AREGS_SAVE_AREA 0x120
+#define __LC_GPREGS_SAVE_AREA 0x180
#define __LC_CREGS_SAVE_AREA 0x1C0
#else /* __s390x__ */
#define __LC_PFAULT_INTPARM 0x11B8
+#define __LC_GPREGS_SAVE_AREA 0x1280
+#define __LC_CPU_TIMER_SAVE_AREA 0x1328
#define __LC_AREGS_SAVE_AREA 0x1340
#define __LC_CREGS_SAVE_AREA 0x1380
#endif /* __s390x__ */
@@ -167,7 +171,8 @@ struct _lowcore
__u16 subchannel_nr; /* 0x0ba */
__u32 io_int_parm; /* 0x0bc */
__u32 io_int_word; /* 0x0c0 */
- __u8 pad3[0xD8-0xC4]; /* 0x0c4 */
+ __u8 pad3[0xD4-0xC4]; /* 0x0c4 */
+ __u32 extended_save_area_addr; /* 0x0d4 */
__u32 cpu_timer_save_area[2]; /* 0x0d8 */
__u32 clock_comp_save_area[2]; /* 0x0e0 */
__u32 mcck_interruption_code[2]; /* 0x0e8 */
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h
index fb46e9090b5..8bd14de69e3 100644
--- a/include/asm-s390/processor.h
+++ b/include/asm-s390/processor.h
@@ -207,6 +207,18 @@ unsigned long get_wchan(struct task_struct *p);
#endif /* __s390x__ */
/*
+ * Set PSW to specified value.
+ */
+static inline void __load_psw(psw_t psw)
+{
+#ifndef __s390x__
+ asm volatile ("lpsw 0(%0)" : : "a" (&psw), "m" (psw) : "cc" );
+#else
+ asm volatile ("lpswe 0(%0)" : : "a" (&psw), "m" (psw) : "cc" );
+#endif
+}
+
+/*
* Set PSW mask to specified value, while leaving the
* PSW addr pointing to the next instruction.
*/
@@ -214,8 +226,8 @@ unsigned long get_wchan(struct task_struct *p);
static inline void __load_psw_mask (unsigned long mask)
{
unsigned long addr;
-
psw_t psw;
+
psw.mask = mask;
#ifndef __s390x__
@@ -241,30 +253,8 @@ static inline void __load_psw_mask (unsigned long mask)
*/
static inline void enabled_wait(void)
{
- unsigned long reg;
- psw_t wait_psw;
-
- wait_psw.mask = PSW_BASE_BITS | PSW_MASK_IO | PSW_MASK_EXT |
- PSW_MASK_MCHECK | PSW_MASK_WAIT | PSW_DEFAULT_KEY;
-#ifndef __s390x__
- asm volatile (
- " basr %0,0\n"
- "0: la %0,1f-0b(%0)\n"
- " st %0,4(%1)\n"
- " oi 4(%1),0x80\n"
- " lpsw 0(%1)\n"
- "1:"
- : "=&a" (reg) : "a" (&wait_psw), "m" (wait_psw)
- : "memory", "cc" );
-#else /* __s390x__ */
- asm volatile (
- " larl %0,0f\n"
- " stg %0,8(%1)\n"
- " lpswe 0(%1)\n"
- "0:"
- : "=&a" (reg) : "a" (&wait_psw), "m" (wait_psw)
- : "memory", "cc" );
-#endif /* __s390x__ */
+ __load_psw_mask(PSW_BASE_BITS | PSW_MASK_IO | PSW_MASK_EXT |
+ PSW_MASK_MCHECK | PSW_MASK_WAIT | PSW_DEFAULT_KEY);
}
/*
@@ -273,13 +263,11 @@ static inline void enabled_wait(void)
static inline void disabled_wait(unsigned long code)
{
- char psw_buffer[2*sizeof(psw_t)];
unsigned long ctl_buf;
- psw_t *dw_psw = (psw_t *)(((unsigned long) &psw_buffer+sizeof(psw_t)-1)
- & -sizeof(psw_t));
+ psw_t dw_psw;
- dw_psw->mask = PSW_BASE_BITS | PSW_MASK_WAIT;
- dw_psw->addr = code;
+ dw_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT;
+ dw_psw.addr = code;
/*
* Store status and then load disabled wait psw,
* the processor is dead afterwards
@@ -301,7 +289,7 @@ static inline void disabled_wait(unsigned long code)
" oi 0x1c0,0x10\n" /* fake protection bit */
" lpsw 0(%1)"
: "=m" (ctl_buf)
- : "a" (dw_psw), "a" (&ctl_buf), "m" (dw_psw) : "cc" );
+ : "a" (&dw_psw), "a" (&ctl_buf), "m" (dw_psw) : "cc" );
#else /* __s390x__ */
asm volatile (" stctg 0,0,0(%2)\n"
" ni 4(%2),0xef\n" /* switch off protection */
@@ -333,7 +321,7 @@ static inline void disabled_wait(unsigned long code)
" oi 0x384(1),0x10\n" /* fake protection bit */
" lpswe 0(%1)"
: "=m" (ctl_buf)
- : "a" (dw_psw), "a" (&ctl_buf),
+ : "a" (&dw_psw), "a" (&ctl_buf),
"m" (dw_psw) : "cc", "0", "1");
#endif /* __s390x__ */
}
diff --git a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h
index 4eff8f2e3bf..fc7c96edc69 100644
--- a/include/asm-s390/ptrace.h
+++ b/include/asm-s390/ptrace.h
@@ -276,7 +276,7 @@ typedef struct
#endif /* __s390x__ */
#define PSW_KERNEL_BITS (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY | \
- PSW_DEFAULT_KEY)
+ PSW_MASK_MCHECK | PSW_DEFAULT_KEY)
#define PSW_USER_BITS (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME | \
PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | \
PSW_MASK_PSTATE | PSW_DEFAULT_KEY)
diff --git a/include/asm-s390/smp.h b/include/asm-s390/smp.h
index 9473786387a..dd50e57a928 100644
--- a/include/asm-s390/smp.h
+++ b/include/asm-s390/smp.h
@@ -47,7 +47,7 @@ extern int smp_call_function_on(void (*func) (void *info), void *info,
#define PROC_CHANGE_PENALTY 20 /* Schedule penalty */
-#define smp_processor_id() (S390_lowcore.cpu_data.cpu_nr)
+#define raw_smp_processor_id() (S390_lowcore.cpu_data.cpu_nr)
extern int smp_get_cpu(cpumask_t cpu_map);
extern void smp_put_cpu(int cpu);
diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h
index 81514d76edc..b4a9f05a93d 100644
--- a/include/asm-s390/system.h
+++ b/include/asm-s390/system.h
@@ -16,6 +16,7 @@
#include <asm/types.h>
#include <asm/ptrace.h>
#include <asm/setup.h>
+#include <asm/processor.h>
#ifdef __KERNEL__
@@ -103,29 +104,18 @@ static inline void restore_access_regs(unsigned int *acrs)
prev = __switch_to(prev,next); \
} while (0)
-#define prepare_arch_switch(rq, next) do { } while(0)
-#define task_running(rq, p) ((rq)->curr == (p))
-
#ifdef CONFIG_VIRT_CPU_ACCOUNTING
extern void account_user_vtime(struct task_struct *);
extern void account_system_vtime(struct task_struct *);
-
-#define finish_arch_switch(rq, prev) do { \
- set_fs(current->thread.mm_segment); \
- spin_unlock(&(rq)->lock); \
- account_system_vtime(prev); \
- local_irq_enable(); \
-} while (0)
-
#else
+#define account_system_vtime(prev) do { } while (0)
+#endif
#define finish_arch_switch(rq, prev) do { \
set_fs(current->thread.mm_segment); \
- spin_unlock_irq(&(rq)->lock); \
+ account_system_vtime(prev); \
} while (0)
-#endif
-
#define nop() __asm__ __volatile__ ("nop")
#define xchg(ptr,x) \
@@ -331,9 +321,6 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
#ifdef __s390x__
-#define __load_psw(psw) \
- __asm__ __volatile__("lpswe 0(%0)" : : "a" (&psw), "m" (psw) : "cc" );
-
#define __ctl_load(array, low, high) ({ \
typedef struct { char _[sizeof(array)]; } addrtype; \
__asm__ __volatile__ ( \
@@ -390,9 +377,6 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
#else /* __s390x__ */
-#define __load_psw(psw) \
- __asm__ __volatile__("lpsw 0(%0)" : : "a" (&psw) : "cc" );
-
#define __ctl_load(array, low, high) ({ \
typedef struct { char _[sizeof(array)]; } addrtype; \
__asm__ __volatile__ ( \
@@ -451,6 +435,20 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
/* For spinlocks etc */
#define local_irq_save(x) ((x) = local_irq_disable())
+/*
+ * Use to set psw mask except for the first byte which
+ * won't be changed by this function.
+ */
+static inline void
+__set_psw_mask(unsigned long mask)
+{
+ local_save_flags(mask);
+ __load_psw_mask(mask);
+}
+
+#define local_mcck_enable() __set_psw_mask(PSW_KERNEL_BITS)
+#define local_mcck_disable() __set_psw_mask(PSW_KERNEL_BITS & ~PSW_MASK_MCHECK)
+
#ifdef CONFIG_SMP
extern void smp_ctl_set_bit(int cr, int bit);
diff --git a/include/asm-s390/thread_info.h b/include/asm-s390/thread_info.h
index aade85c53a6..6c18a3f2431 100644
--- a/include/asm-s390/thread_info.h
+++ b/include/asm-s390/thread_info.h
@@ -50,7 +50,7 @@ struct thread_info {
struct exec_domain *exec_domain; /* execution domain */
unsigned long flags; /* low level flags */
unsigned int cpu; /* current CPU */
- unsigned int preempt_count; /* 0 => preemptable */
+ int preempt_count; /* 0 => preemptable, <0 => BUG */
struct restart_block restart_block;
};
@@ -96,6 +96,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_RESTART_SVC 4 /* restart svc with new svc number */
#define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */
#define TIF_SINGLE_STEP 6 /* deliver sigtrap on return to user */
+#define TIF_MCCK_PENDING 7 /* machine check handling is pending */
#define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */
#define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling
TIF_NEED_RESCHED */
@@ -109,6 +110,7 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_RESTART_SVC (1<<TIF_RESTART_SVC)
#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
#define _TIF_SINGLE_STEP (1<<TIF_SINGLE_STEP)
+#define _TIF_MCCK_PENDING (1<<TIF_MCCK_PENDING)
#define _TIF_USEDFPU (1<<TIF_USEDFPU)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
#define _TIF_31BIT (1<<TIF_31BIT)
diff --git a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h
index f1a204f7c0f..363db45f8d0 100644
--- a/include/asm-s390/unistd.h
+++ b/include/asm-s390/unistd.h
@@ -269,7 +269,7 @@
#define __NR_mq_timedreceive 274
#define __NR_mq_notify 275
#define __NR_mq_getsetattr 276
-/* Number 277 is reserved for new sys_kexec_load */
+#define __NR_kexec_load 277
#define __NR_add_key 278
#define __NR_request_key 279
#define __NR_keyctl 280
diff --git a/include/asm-s390/user.h b/include/asm-s390/user.h
index c64f8c181df..1dc74baf03c 100644
--- a/include/asm-s390/user.h
+++ b/include/asm-s390/user.h
@@ -10,7 +10,7 @@
#define _S390_USER_H
#include <asm/page.h>
-#include <linux/ptrace.h>
+#include <asm/ptrace.h>
/* Core file format: The core file is written in such a way that gdb
can understand it and provide useful information to the user (under
linux we use the 'trad-core' bfd). There are quite a number of
diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h
index 4c6d129e7d9..180467be8e7 100644
--- a/include/asm-sh/page.h
+++ b/include/asm-sh/page.h
@@ -31,6 +31,7 @@
#define HPAGE_SIZE (1UL << HPAGE_SHIFT)
#define HPAGE_MASK (~(HPAGE_SIZE-1))
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT-PAGE_SHIFT)
+#define ARCH_HAS_SETCLEAR_HUGE_PTE
#endif
#ifdef __KERNEL__
diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h
index cd847a47a9a..ecb909572d3 100644
--- a/include/asm-sh/pgtable.h
+++ b/include/asm-sh/pgtable.h
@@ -196,6 +196,7 @@ static inline pte_t pte_mkexec(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _
static inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
static inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
static inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; }
+static inline pte_t pte_mkhuge(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_SZHUGE)); return pte; }
/*
* Macro and implementation to make a page protection as uncachable.
diff --git a/include/asm-sh/smp.h b/include/asm-sh/smp.h
index 38b54469d7d..f19a8b3b69a 100644
--- a/include/asm-sh/smp.h
+++ b/include/asm-sh/smp.h
@@ -25,7 +25,7 @@ extern cpumask_t cpu_possible_map;
#define cpu_online(cpu) cpu_isset(cpu, cpu_online_map)
-#define smp_processor_id() (current_thread_info()->cpu)
+#define raw_smp_processor_id() (current_thread_info()->cpu)
/* I've no idea what the real meaning of this is */
#define PROC_CHANGE_PENALTY 20
diff --git a/include/asm-sh/thread_info.h b/include/asm-sh/thread_info.h
index d82f883d8e6..46080cefaff 100644
--- a/include/asm-sh/thread_info.h
+++ b/include/asm-sh/thread_info.h
@@ -20,14 +20,14 @@ struct thread_info {
struct exec_domain *exec_domain; /* execution domain */
__u32 flags; /* low level flags */
__u32 cpu;
- __s32 preempt_count; /* 0 => preemptable, <0 => BUG */
+ int preempt_count; /* 0 => preemptable, <0 => BUG */
struct restart_block restart_block;
__u8 supervisor_stack[0];
};
#endif
-#define PREEMPT_ACTIVE 0x4000000
+#define PREEMPT_ACTIVE 0x10000000
/*
* macros/functions for gaining access to the thread information structure
diff --git a/include/asm-sh64/page.h b/include/asm-sh64/page.h
index e1f7f5a4121..d6167f1c0e9 100644
--- a/include/asm-sh64/page.h
+++ b/include/asm-sh64/page.h
@@ -41,6 +41,7 @@
#define HPAGE_SIZE (1UL << HPAGE_SHIFT)
#define HPAGE_MASK (~(HPAGE_SIZE-1))
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT-PAGE_SHIFT)
+#define ARCH_HAS_SETCLEAR_HUGE_PTE
#endif
#ifdef __KERNEL__
diff --git a/include/asm-sh64/pgtable.h b/include/asm-sh64/pgtable.h
index 525e1523ef5..78ac6be2d9e 100644
--- a/include/asm-sh64/pgtable.h
+++ b/include/asm-sh64/pgtable.h
@@ -430,6 +430,8 @@ extern inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) |
extern inline pte_t pte_mkexec(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_EXECUTE)); return pte; }
extern inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
extern inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
+extern inline pte_t pte_mkhuge(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_SZHUGE)); return pte; }
+
/*
* Conversion functions: convert a page and protection to a page entry.
diff --git a/include/asm-sh64/thread_info.h b/include/asm-sh64/thread_info.h
index e65f394da47..10f024c6a2e 100644
--- a/include/asm-sh64/thread_info.h
+++ b/include/asm-sh64/thread_info.h
@@ -22,7 +22,7 @@ struct thread_info {
struct exec_domain *exec_domain; /* execution domain */
unsigned long flags; /* low level flags */
/* Put the 4 32-bit fields together to make asm offsetting easier. */
- __s32 preempt_count; /* 0 => preemptable, <0 => BUG */
+ int preempt_count; /* 0 => preemptable, <0 => BUG */
__u16 cpu;
mm_segment_t addr_limit;
@@ -73,7 +73,7 @@ static inline struct thread_info *current_thread_info(void)
#define THREAD_SIZE 8192
-#define PREEMPT_ACTIVE 0x4000000
+#define PREEMPT_ACTIVE 0x10000000
/* thread information flags */
#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
diff --git a/include/asm-sparc/smp.h b/include/asm-sparc/smp.h
index f986c0d0922..4f96d8333a1 100644
--- a/include/asm-sparc/smp.h
+++ b/include/asm-sparc/smp.h
@@ -148,7 +148,7 @@ extern __inline__ int hard_smp_processor_id(void)
}
#endif
-#define smp_processor_id() (current_thread_info()->cpu)
+#define raw_smp_processor_id() (current_thread_info()->cpu)
#define prof_multiplier(__cpu) cpu_data(__cpu).multiplier
#define prof_counter(__cpu) cpu_data(__cpu).counter
diff --git a/include/asm-sparc/system.h b/include/asm-sparc/system.h
index 80cf20cfaee..898562ebe94 100644
--- a/include/asm-sparc/system.h
+++ b/include/asm-sparc/system.h
@@ -101,7 +101,7 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
* SWITCH_ENTER and SWITH_DO_LAZY_FPU do not work yet (e.g. SMP does not work)
* XXX WTF is the above comment? Found in late teen 2.4.x.
*/
-#define prepare_arch_switch(rq, next) do { \
+#define prepare_arch_switch(next) do { \
__asm__ __volatile__( \
".globl\tflush_patch_switch\nflush_patch_switch:\n\t" \
"save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \
@@ -109,8 +109,6 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
"save %sp, -0x40, %sp\n\t" \
"restore; restore; restore; restore; restore; restore; restore"); \
} while(0)
-#define finish_arch_switch(rq, next) spin_unlock_irq(&(rq)->lock)
-#define task_running(rq, p) ((rq)->curr == (p))
/* Much care has gone into this code, do not touch it.
*
diff --git a/include/asm-sparc/thread_info.h b/include/asm-sparc/thread_info.h
index 104f03c5541..ff6ccb3d24c 100644
--- a/include/asm-sparc/thread_info.h
+++ b/include/asm-sparc/thread_info.h
@@ -30,9 +30,9 @@ struct thread_info {
struct task_struct *task; /* main task structure */
struct exec_domain *exec_domain; /* execution domain */
unsigned long flags; /* low level flags */
-
int cpu; /* cpu we're on */
- int preempt_count;
+ int preempt_count; /* 0 => preemptable,
+ <0 => BUG */
int softirq_count;
int hardirq_count;
diff --git a/include/asm-sparc/uaccess.h b/include/asm-sparc/uaccess.h
index f461144067e..0a780e84a12 100644
--- a/include/asm-sparc/uaccess.h
+++ b/include/asm-sparc/uaccess.h
@@ -41,10 +41,11 @@
* No one can read/write anything from userland in the kernel space by setting
* large size and address near to PAGE_OFFSET - a fault will break his intentions.
*/
-#define __user_ok(addr,size) ((addr) < STACK_TOP)
+#define __user_ok(addr, size) ({ (void)(size); (addr) < STACK_TOP; })
#define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
#define __access_ok(addr,size) (__user_ok((addr) & get_fs().seg,(size)))
-#define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size))
+#define access_ok(type, addr, size) \
+ ({ (void)(type); __access_ok((unsigned long)(addr), size); })
/* this function will go away soon - use access_ok() instead */
static inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
diff --git a/include/asm-sparc64/agp.h b/include/asm-sparc64/agp.h
index ba05bdf9a21..58f8cb6ae76 100644
--- a/include/asm-sparc64/agp.h
+++ b/include/asm-sparc64/agp.h
@@ -8,4 +8,14 @@
#define flush_agp_mappings()
#define flush_agp_cache() mb()
+/* Convert a physical address to an address suitable for the GART. */
+#define phys_to_gart(x) (x)
+#define gart_to_phys(x) (x)
+
+/* GATT allocation. Returns/accepts GATT kernel virtual address. */
+#define alloc_gatt_pages(order) \
+ ((char *)__get_free_pages(GFP_KERNEL, (order)))
+#define free_gatt_pages(table, order) \
+ free_pages((unsigned long)(table), (order))
+
#endif
diff --git a/include/asm-sparc64/compat.h b/include/asm-sparc64/compat.h
index 22f58055b8a..b59122dd176 100644
--- a/include/asm-sparc64/compat.h
+++ b/include/asm-sparc64/compat.h
@@ -25,6 +25,7 @@ typedef s32 compat_daddr_t;
typedef u32 compat_caddr_t;
typedef __kernel_fsid_t compat_fsid_t;
typedef s32 compat_key_t;
+typedef s32 compat_timer_t;
typedef s32 compat_int_t;
typedef s32 compat_long_t;
diff --git a/include/asm-sparc64/iommu.h b/include/asm-sparc64/iommu.h
index 5fd16e42a04..0de7a3da79c 100644
--- a/include/asm-sparc64/iommu.h
+++ b/include/asm-sparc64/iommu.h
@@ -16,4 +16,6 @@
#define IOPTE_CACHE 0x0000000000000010UL /* Cached (in UPA E-cache) */
#define IOPTE_WRITE 0x0000000000000002UL /* Writeable */
+#define IOMMU_NUM_CTXS 4096
+
#endif /* !(_SPARC_IOMMU_H) */
diff --git a/include/asm-sparc64/kdebug.h b/include/asm-sparc64/kdebug.h
index f70d3dad01f..6321f5a0198 100644
--- a/include/asm-sparc64/kdebug.h
+++ b/include/asm-sparc64/kdebug.h
@@ -16,7 +16,7 @@ struct die_args {
};
/* Note - you should never unregister because that can race with NMIs.
- * If you really want to do it first unregister - then synchronize_kernel
+ * If you really want to do it first unregister - then synchronize_sched
* - then free.
*/
int register_die_notifier(struct notifier_block *nb);
diff --git a/include/asm-sparc64/page.h b/include/asm-sparc64/page.h
index 219ea043a14..b87dbbd64bc 100644
--- a/include/asm-sparc64/page.h
+++ b/include/asm-sparc64/page.h
@@ -95,6 +95,8 @@ typedef unsigned long pgprot_t;
#define HPAGE_SIZE (_AC(1,UL) << HPAGE_SHIFT)
#define HPAGE_MASK (~(HPAGE_SIZE - 1UL))
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
+#define ARCH_HAS_SETCLEAR_HUGE_PTE
+#define ARCH_HAS_HUGETLB_PREFAULT_HOOK
#endif
#define TASK_UNMAPPED_BASE (test_thread_flag(TIF_32BIT) ? \
diff --git a/include/asm-sparc64/pbm.h b/include/asm-sparc64/pbm.h
index 92999631c81..4c15610a2ba 100644
--- a/include/asm-sparc64/pbm.h
+++ b/include/asm-sparc64/pbm.h
@@ -15,6 +15,7 @@
#include <asm/io.h>
#include <asm/page.h>
#include <asm/oplib.h>
+#include <asm/iommu.h>
/* The abstraction used here is that there are PCI controllers,
* each with one (Sabre) or two (PSYCHO/SCHIZO) PCI bus modules
@@ -40,9 +41,6 @@ struct pci_iommu {
*/
spinlock_t lock;
- /* Context allocator. */
- unsigned int iommu_cur_ctx;
-
/* IOMMU page table, a linear array of ioptes. */
iopte_t *page_table; /* The page table itself. */
int page_table_sz_bits; /* log2 of ow many pages does it map? */
@@ -87,6 +85,10 @@ struct pci_iommu {
u16 flush;
} alloc_info[PBM_NCLUSTERS];
+ /* CTX allocation. */
+ unsigned long ctx_lowest_free;
+ unsigned long ctx_bitmap[IOMMU_NUM_CTXS / (sizeof(unsigned long) * 8)];
+
/* Here a PCI controller driver describes the areas of
* PCI memory space where DMA to/from physical memory
* are addressed. Drivers interrogate the PCI layer
diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h
index ae2cd5b09a7..1ae00c5087f 100644
--- a/include/asm-sparc64/pgtable.h
+++ b/include/asm-sparc64/pgtable.h
@@ -286,6 +286,7 @@ static inline pte_t pte_modify(pte_t orig_pte, pgprot_t new_prot)
#define pte_mkyoung(pte) (__pte(pte_val(pte) | _PAGE_ACCESSED | _PAGE_R))
#define pte_mkwrite(pte) (__pte(pte_val(pte) | _PAGE_WRITE))
#define pte_mkdirty(pte) (__pte(pte_val(pte) | _PAGE_MODIFIED | _PAGE_W))
+#define pte_mkhuge(pte) (__pte(pte_val(pte) | _PAGE_SZHUGE))
/* to find an entry in a page-table-directory. */
#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
diff --git a/include/asm-sparc64/processor.h b/include/asm-sparc64/processor.h
index bc1445b904e..d0bee241356 100644
--- a/include/asm-sparc64/processor.h
+++ b/include/asm-sparc64/processor.h
@@ -192,6 +192,40 @@ extern unsigned long get_wchan(struct task_struct *task);
#define cpu_relax() barrier()
+/* Prefetch support. This is tuned for UltraSPARC-III and later.
+ * UltraSPARC-I will treat these as nops, and UltraSPARC-II has
+ * a shallower prefetch queue than later chips.
+ */
+#define ARCH_HAS_PREFETCH
+#define ARCH_HAS_PREFETCHW
+#define ARCH_HAS_SPINLOCK_PREFETCH
+
+static inline void prefetch(const void *x)
+{
+ /* We do not use the read prefetch mnemonic because that
+ * prefetches into the prefetch-cache which only is accessible
+ * by floating point operations in UltraSPARC-III and later.
+ * By contrast, "#one_write" prefetches into the L2 cache
+ * in shared state.
+ */
+ __asm__ __volatile__("prefetch [%0], #one_write"
+ : /* no outputs */
+ : "r" (x));
+}
+
+static inline void prefetchw(const void *x)
+{
+ /* The most optimal prefetch to use for writes is
+ * "#n_writes". This brings the cacheline into the
+ * L2 cache in "owned" state.
+ */
+ __asm__ __volatile__("prefetch [%0], #n_writes"
+ : /* no outputs */
+ : "r" (x));
+}
+
+#define spin_lock_prefetch(x) prefetchw(x)
+
#endif /* !(__ASSEMBLY__) */
#endif /* !(__ASM_SPARC64_PROCESSOR_H) */
diff --git a/include/asm-sparc64/smp.h b/include/asm-sparc64/smp.h
index 5e3e06d908f..110a2de8912 100644
--- a/include/asm-sparc64/smp.h
+++ b/include/asm-sparc64/smp.h
@@ -64,7 +64,7 @@ static __inline__ int hard_smp_processor_id(void)
}
}
-#define smp_processor_id() (current_thread_info()->cpu)
+#define raw_smp_processor_id() (current_thread_info()->cpu)
#endif /* !(__ASSEMBLY__) */
diff --git a/include/asm-sparc64/spitfire.h b/include/asm-sparc64/spitfire.h
index ad78ce64d69..9d7613eea81 100644
--- a/include/asm-sparc64/spitfire.h
+++ b/include/asm-sparc64/spitfire.h
@@ -48,6 +48,9 @@ enum ultra_tlb_layout {
extern enum ultra_tlb_layout tlb_type;
+extern int cheetah_pcache_forced_on;
+extern void cheetah_enable_pcache(void);
+
#define sparc64_highest_locked_tlbent() \
(tlb_type == spitfire ? \
SPITFIRE_HIGHEST_LOCKED_TLBENT : \
diff --git a/include/asm-sparc64/system.h b/include/asm-sparc64/system.h
index fd12ca386f4..f9be2c5b4dc 100644
--- a/include/asm-sparc64/system.h
+++ b/include/asm-sparc64/system.h
@@ -139,19 +139,13 @@ extern void __flushw_user(void);
#define flush_user_windows flushw_user
#define flush_register_windows flushw_all
-#define prepare_arch_switch(rq, next) \
-do { spin_lock(&(next)->switch_lock); \
- spin_unlock(&(rq)->lock); \
+/* Don't hold the runqueue lock over context switch */
+#define __ARCH_WANT_UNLOCKED_CTXSW
+#define prepare_arch_switch(next) \
+do { \
flushw_all(); \
} while (0)
-#define finish_arch_switch(rq, prev) \
-do { spin_unlock_irq(&(prev)->switch_lock); \
-} while (0)
-
-#define task_running(rq, p) \
- ((rq)->curr == (p) || spin_is_locked(&(p)->switch_lock))
-
/* See what happens when you design the chip correctly?
*
* We tell gcc we clobber all non-fixed-usage registers except
diff --git a/include/asm-sparc64/termios.h b/include/asm-sparc64/termios.h
index 8effce0da08..9777a9cca88 100644
--- a/include/asm-sparc64/termios.h
+++ b/include/asm-sparc64/termios.h
@@ -100,16 +100,17 @@ struct winsize {
#define user_termio_to_kernel_termios(termios, termio) \
({ \
unsigned short tmp; \
- get_user(tmp, &(termio)->c_iflag); \
+ int err; \
+ err = get_user(tmp, &(termio)->c_iflag); \
(termios)->c_iflag = (0xffff0000 & ((termios)->c_iflag)) | tmp; \
- get_user(tmp, &(termio)->c_oflag); \
+ err |= get_user(tmp, &(termio)->c_oflag); \
(termios)->c_oflag = (0xffff0000 & ((termios)->c_oflag)) | tmp; \
- get_user(tmp, &(termio)->c_cflag); \
+ err |= get_user(tmp, &(termio)->c_cflag); \
(termios)->c_cflag = (0xffff0000 & ((termios)->c_cflag)) | tmp; \
- get_user(tmp, &(termio)->c_lflag); \
+ err |= get_user(tmp, &(termio)->c_lflag); \
(termios)->c_lflag = (0xffff0000 & ((termios)->c_lflag)) | tmp; \
- copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
- 0; \
+ err |= copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
+ err; \
})
/*
@@ -119,53 +120,56 @@ struct winsize {
*/
#define kernel_termios_to_user_termio(termio, termios) \
({ \
- put_user((termios)->c_iflag, &(termio)->c_iflag); \
- put_user((termios)->c_oflag, &(termio)->c_oflag); \
- put_user((termios)->c_cflag, &(termio)->c_cflag); \
- put_user((termios)->c_lflag, &(termio)->c_lflag); \
- put_user((termios)->c_line, &(termio)->c_line); \
- copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
+ int err; \
+ err = put_user((termios)->c_iflag, &(termio)->c_iflag); \
+ err |= put_user((termios)->c_oflag, &(termio)->c_oflag); \
+ err |= put_user((termios)->c_cflag, &(termio)->c_cflag); \
+ err |= put_user((termios)->c_lflag, &(termio)->c_lflag); \
+ err |= put_user((termios)->c_line, &(termio)->c_line); \
+ err |= copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
if (!((termios)->c_lflag & ICANON)) { \
- put_user((termios)->c_cc[VMIN], &(termio)->c_cc[_VMIN]); \
- put_user((termios)->c_cc[VTIME], &(termio)->c_cc[_VTIME]); \
+ err |= put_user((termios)->c_cc[VMIN], &(termio)->c_cc[_VMIN]); \
+ err |= put_user((termios)->c_cc[VTIME], &(termio)->c_cc[_VTIME]); \
} \
- 0; \
+ err; \
})
#define user_termios_to_kernel_termios(k, u) \
({ \
- get_user((k)->c_iflag, &(u)->c_iflag); \
- get_user((k)->c_oflag, &(u)->c_oflag); \
- get_user((k)->c_cflag, &(u)->c_cflag); \
- get_user((k)->c_lflag, &(u)->c_lflag); \
- get_user((k)->c_line, &(u)->c_line); \
- copy_from_user((k)->c_cc, (u)->c_cc, NCCS); \
+ int err; \
+ err = get_user((k)->c_iflag, &(u)->c_iflag); \
+ err |= get_user((k)->c_oflag, &(u)->c_oflag); \
+ err |= get_user((k)->c_cflag, &(u)->c_cflag); \
+ err |= get_user((k)->c_lflag, &(u)->c_lflag); \
+ err |= get_user((k)->c_line, &(u)->c_line); \
+ err |= copy_from_user((k)->c_cc, (u)->c_cc, NCCS); \
if((k)->c_lflag & ICANON) { \
- get_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \
- get_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \
+ err |= get_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \
+ err |= get_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \
} else { \
- get_user((k)->c_cc[VMIN], &(u)->c_cc[_VMIN]); \
- get_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \
+ err |= get_user((k)->c_cc[VMIN], &(u)->c_cc[_VMIN]); \
+ err |= get_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \
} \
- 0; \
+ err; \
})
#define kernel_termios_to_user_termios(u, k) \
({ \
- put_user((k)->c_iflag, &(u)->c_iflag); \
- put_user((k)->c_oflag, &(u)->c_oflag); \
- put_user((k)->c_cflag, &(u)->c_cflag); \
- put_user((k)->c_lflag, &(u)->c_lflag); \
- put_user((k)->c_line, &(u)->c_line); \
- copy_to_user((u)->c_cc, (k)->c_cc, NCCS); \
+ int err; \
+ err = put_user((k)->c_iflag, &(u)->c_iflag); \
+ err |= put_user((k)->c_oflag, &(u)->c_oflag); \
+ err |= put_user((k)->c_cflag, &(u)->c_cflag); \
+ err |= put_user((k)->c_lflag, &(u)->c_lflag); \
+ err |= put_user((k)->c_line, &(u)->c_line); \
+ err |= copy_to_user((u)->c_cc, (k)->c_cc, NCCS); \
if(!((k)->c_lflag & ICANON)) { \
- put_user((k)->c_cc[VMIN], &(u)->c_cc[_VMIN]); \
- put_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \
+ err |= put_user((k)->c_cc[VMIN], &(u)->c_cc[_VMIN]); \
+ err |= put_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \
} else { \
- put_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \
- put_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \
+ err |= put_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \
+ err |= put_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \
} \
- 0; \
+ err; \
})
#endif /* __KERNEL__ */
diff --git a/include/asm-sparc64/thread_info.h b/include/asm-sparc64/thread_info.h
index 517caaba1c8..0cd65295692 100644
--- a/include/asm-sparc64/thread_info.h
+++ b/include/asm-sparc64/thread_info.h
@@ -46,7 +46,7 @@ struct thread_info {
unsigned long fault_address;
struct pt_regs *kregs;
struct exec_domain *exec_domain;
- int preempt_count;
+ int preempt_count; /* 0 => preemptable, <0 => BUG */
int __pad;
unsigned long *utraps;
diff --git a/include/asm-um/arch-signal-i386.h b/include/asm-um/arch-signal-i386.h
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/include/asm-um/arch-signal-i386.h
+++ /dev/null
diff --git a/include/asm-um/elf-i386.h b/include/asm-um/elf-i386.h
index b72e23519e0..9bab712dc5c 100644
--- a/include/asm-um/elf-i386.h
+++ b/include/asm-um/elf-i386.h
@@ -5,7 +5,7 @@
#ifndef __UM_ELF_I386_H
#define __UM_ELF_I386_H
-#include "user.h"
+#include <asm/user.h>
#define R_386_NONE 0
#define R_386_32 1
diff --git a/include/asm-um/elf-x86_64.h b/include/asm-um/elf-x86_64.h
index 19309d001aa..8a8246d0393 100644
--- a/include/asm-um/elf-x86_64.h
+++ b/include/asm-um/elf-x86_64.h
@@ -8,6 +8,27 @@
#include <asm/user.h>
+/* x86-64 relocation types, taken from asm-x86_64/elf.h */
+#define R_X86_64_NONE 0 /* No reloc */
+#define R_X86_64_64 1 /* Direct 64 bit */
+#define R_X86_64_PC32 2 /* PC relative 32 bit signed */
+#define R_X86_64_GOT32 3 /* 32 bit GOT entry */
+#define R_X86_64_PLT32 4 /* 32 bit PLT address */
+#define R_X86_64_COPY 5 /* Copy symbol at runtime */
+#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */
+#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */
+#define R_X86_64_RELATIVE 8 /* Adjust by program base */
+#define R_X86_64_GOTPCREL 9 /* 32 bit signed pc relative
+ offset to GOT */
+#define R_X86_64_32 10 /* Direct 32 bit zero extended */
+#define R_X86_64_32S 11 /* Direct 32 bit sign extended */
+#define R_X86_64_16 12 /* Direct 16 bit zero extended */
+#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */
+#define R_X86_64_8 14 /* Direct 8 bit sign extended */
+#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */
+
+#define R_X86_64_NUM 16
+
typedef unsigned long elf_greg_t;
#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t))
@@ -44,7 +65,8 @@ typedef struct { } elf_fpregset_t;
} while (0)
#ifdef TIF_IA32 /* XXX */
- clear_thread_flag(TIF_IA32); \
+#error XXX, indeed
+ clear_thread_flag(TIF_IA32);
#endif
#define USE_ELF_CORE_DUMP
diff --git a/include/asm-um/elf.h b/include/asm-um/elf.h
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/include/asm-um/elf.h
+++ /dev/null
diff --git a/include/asm-um/page.h b/include/asm-um/page.h
index 504ea8e486b..5afee8a8cdf 100644
--- a/include/asm-um/page.h
+++ b/include/asm-um/page.h
@@ -98,7 +98,13 @@ extern unsigned long uml_physmem;
extern unsigned long to_phys(void *virt);
extern void *to_virt(unsigned long phys);
-#define __pa(virt) to_phys((void *) virt)
+
+/* Cast to unsigned long before casting to void * to avoid a warning from
+ * mmap_kmem about cutting a long long down to a void *. Not sure that
+ * casting is the right thing, but 32-bit UML can't have 64-bit virtual
+ * addresses
+ */
+#define __pa(virt) to_phys((void *) (unsigned long) virt)
#define __va(phys) to_virt((unsigned long) phys)
#define page_to_pfn(page) ((page) - mem_map)
diff --git a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h
index 510e513c7f8..a8804092031 100644
--- a/include/asm-um/pgtable.h
+++ b/include/asm-um/pgtable.h
@@ -114,17 +114,9 @@ extern unsigned long end_iomem;
extern unsigned long pg0[1024];
/*
- * BAD_PAGETABLE is used when we need a bogus page-table, while
- * BAD_PAGE is used for a bogus page.
- *
* ZERO_PAGE is a global shared page that is always zero: used
* for zero-mapped memory areas etc..
*/
-extern pte_t __bad_page(void);
-extern pte_t * __bad_pagetable(void);
-
-#define BAD_PAGETABLE __bad_pagetable()
-#define BAD_PAGE __bad_page()
#define ZERO_PAGE(vaddr) virt_to_page(empty_zero_page)
diff --git a/include/asm-um/ptrace-i386.h b/include/asm-um/ptrace-i386.h
index 04222f35c43..fe882b9d917 100644
--- a/include/asm-um/ptrace-i386.h
+++ b/include/asm-um/ptrace-i386.h
@@ -32,6 +32,10 @@
#define PT_REGS_SYSCALL_RET(r) PT_REGS_EAX(r)
#define PT_FIX_EXEC_STACK(sp) do ; while(0)
+/* Cope with a conditional i386 definition. */
+#undef profile_pc
+#define profile_pc(regs) PT_REGS_IP(regs)
+
#define user_mode(r) UPT_IS_USER(&(r)->regs)
#endif
diff --git a/include/asm-um/smp.h b/include/asm-um/smp.h
index 4412d5d9c26..d879eba2b52 100644
--- a/include/asm-um/smp.h
+++ b/include/asm-um/smp.h
@@ -8,7 +8,8 @@
#include "asm/current.h"
#include "linux/cpumask.h"
-#define smp_processor_id() (current_thread->cpu)
+#define raw_smp_processor_id() (current_thread->cpu)
+
#define cpu_logical_map(n) (n)
#define cpu_number_map(n) (n)
#define PROC_CHANGE_PENALTY 15 /* Pick a number, any number */
diff --git a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h
index a10ea155907..97267f059ef 100644
--- a/include/asm-um/thread_info.h
+++ b/include/asm-um/thread_info.h
@@ -17,7 +17,7 @@ struct thread_info {
struct exec_domain *exec_domain; /* execution domain */
unsigned long flags; /* low level flags */
__u32 cpu; /* current CPU */
- __s32 preempt_count; /* 0 => preemptable,
+ int preempt_count; /* 0 => preemptable,
<0 => BUG */
mm_segment_t addr_limit; /* thread address space:
0-0xBFFFFFFF for user
@@ -41,18 +41,17 @@ struct thread_info {
#define init_thread_info (init_thread_union.thread_info)
#define init_stack (init_thread_union.stack)
+#define THREAD_SIZE ((1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE)
/* how to get the thread information struct from C */
static inline struct thread_info *current_thread_info(void)
{
struct thread_info *ti;
- unsigned long mask = PAGE_SIZE *
- (1 << CONFIG_KERNEL_STACK_ORDER) - 1;
- ti = (struct thread_info *) (((unsigned long) &ti) & ~mask);
+ unsigned long mask = THREAD_SIZE - 1;
+ ti = (struct thread_info *) (((unsigned long) &ti) & ~mask);
return ti;
}
/* thread information allocation */
-#define THREAD_SIZE ((1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE)
#define alloc_thread_info(tsk) \
((struct thread_info *) kmalloc(THREAD_SIZE, GFP_KERNEL))
#define free_thread_info(ti) kfree(ti)
@@ -62,7 +61,7 @@ static inline struct thread_info *current_thread_info(void)
#endif
-#define PREEMPT_ACTIVE 0x4000000
+#define PREEMPT_ACTIVE 0x10000000
#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
#define TIF_SIGPENDING 1 /* signal pending */
diff --git a/include/asm-v850/thread_info.h b/include/asm-v850/thread_info.h
index e2ef4459375..e4cfad94a55 100644
--- a/include/asm-v850/thread_info.h
+++ b/include/asm-v850/thread_info.h
@@ -30,7 +30,8 @@ struct thread_info {
struct exec_domain *exec_domain; /* execution domain */
unsigned long flags; /* low level flags */
int cpu; /* cpu we're on */
- int preempt_count;
+ int preempt_count; /* 0 => preemptable,
+ <0 => BUG */
struct restart_block restart_block;
};
diff --git a/include/asm-x86_64/a.out.h b/include/asm-x86_64/a.out.h
index 5952914f412..7255cde0653 100644
--- a/include/asm-x86_64/a.out.h
+++ b/include/asm-x86_64/a.out.h
@@ -21,7 +21,7 @@ struct exec
#ifdef __KERNEL__
#include <linux/thread_info.h>
-#define STACK_TOP (test_thread_flag(TIF_IA32) ? IA32_PAGE_OFFSET : TASK_SIZE)
+#define STACK_TOP TASK_SIZE
#endif
#endif /* __A_OUT_GNU_H__ */
diff --git a/include/asm-x86_64/agp.h b/include/asm-x86_64/agp.h
index 0bb9019d58a..06c52ee9c06 100644
--- a/include/asm-x86_64/agp.h
+++ b/include/asm-x86_64/agp.h
@@ -19,4 +19,14 @@ int unmap_page_from_agp(struct page *page);
worth it. Would need a page for it. */
#define flush_agp_cache() asm volatile("wbinvd":::"memory")
+/* Convert a physical address to an address suitable for the GART. */
+#define phys_to_gart(x) (x)
+#define gart_to_phys(x) (x)
+
+/* GATT allocation. Returns/accepts GATT kernel virtual address. */
+#define alloc_gatt_pages(order) \
+ ((char *)__get_free_pages(GFP_KERNEL, (order)))
+#define free_gatt_pages(table, order) \
+ free_pages((unsigned long)(table), (order))
+
#endif
diff --git a/include/asm-x86_64/apic.h b/include/asm-x86_64/apic.h
index e4b1017b8b2..16ec82e16b2 100644
--- a/include/asm-x86_64/apic.h
+++ b/include/asm-x86_64/apic.h
@@ -77,7 +77,7 @@ static inline void ack_APIC_irq(void)
extern int get_maxlvt (void);
extern void clear_local_APIC (void);
extern void connect_bsp_APIC (void);
-extern void disconnect_bsp_APIC (void);
+extern void disconnect_bsp_APIC (int virt_wire_setup);
extern void disable_local_APIC (void);
extern int verify_local_APIC (void);
extern void cache_APIC_registers (void);
diff --git a/include/asm-x86_64/apicdef.h b/include/asm-x86_64/apicdef.h
index 3d7627ffe67..9388062c4f6 100644
--- a/include/asm-x86_64/apicdef.h
+++ b/include/asm-x86_64/apicdef.h
@@ -94,7 +94,7 @@
#define SET_APIC_DELIVERY_MODE(x,y) (((x)&~0x700)|((y)<<8))
#define APIC_MODE_FIXED 0x0
#define APIC_MODE_NMI 0x4
-#define APIC_MODE_EXINT 0x7
+#define APIC_MODE_EXTINT 0x7
#define APIC_LVT1 0x360
#define APIC_LVTERR 0x370
#define APIC_TMICT 0x380
@@ -112,7 +112,7 @@
#define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
-#define MAX_IO_APICS 32
+#define MAX_IO_APICS 128
/*
* All x86-64 systems are xAPIC compatible.
diff --git a/include/asm-x86_64/bitops.h b/include/asm-x86_64/bitops.h
index 5dd7727c756..a31bb99be53 100644
--- a/include/asm-x86_64/bitops.h
+++ b/include/asm-x86_64/bitops.h
@@ -411,8 +411,6 @@ static __inline__ int ffs(int x)
/* find last set bit */
#define fls(x) generic_fls(x)
-#define ARCH_HAS_ATOMIC_UNSIGNED 1
-
#endif /* __KERNEL__ */
#endif /* _X86_64_BITOPS_H */
diff --git a/include/asm-x86_64/bug.h b/include/asm-x86_64/bug.h
index bdbf66eab6e..3d2a666a5dd 100644
--- a/include/asm-x86_64/bug.h
+++ b/include/asm-x86_64/bug.h
@@ -21,6 +21,8 @@ struct bug_frame {
asm volatile("ud2 ; .quad %c1 ; .short %c0" :: \
"i"(__LINE__), "i" (__stringify(__FILE__)))
void out_of_line_bug(void);
+#else
+static inline void out_of_line_bug(void) { }
#endif
#include <asm-generic/bug.h>
diff --git a/include/asm-x86_64/ia32.h b/include/asm-x86_64/ia32.h
index c0a7717923e..6efa00fe4e7 100644
--- a/include/asm-x86_64/ia32.h
+++ b/include/asm-x86_64/ia32.h
@@ -94,7 +94,7 @@ typedef struct compat_siginfo{
/* POSIX.1b timers */
struct {
- int _tid; /* timer id */
+ compat_timer_t _tid; /* timer id */
int _overrun; /* overrun count */
compat_sigval_t _sigval; /* same as below */
int _sys_private; /* not to be passed to user */
diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
index 94202703fae..37fc3f149a5 100644
--- a/include/asm-x86_64/io.h
+++ b/include/asm-x86_64/io.h
@@ -124,12 +124,7 @@ extern inline void * phys_to_virt(unsigned long address)
/*
* Change "struct page" to physical address.
*/
-#ifdef CONFIG_DISCONTIGMEM
-#include <asm/mmzone.h>
#define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
-#else
-#define page_to_phys(page) ((page - mem_map) << PAGE_SHIFT)
-#endif
#include <asm-generic/iomap.h>
diff --git a/include/asm-x86_64/io_apic.h b/include/asm-x86_64/io_apic.h
index 7efc932e8f0..32573749004 100644
--- a/include/asm-x86_64/io_apic.h
+++ b/include/asm-x86_64/io_apic.h
@@ -202,7 +202,6 @@ extern int skip_ioapic_setup;
#define io_apic_assign_pci_irqs (mp_irq_entries && !skip_ioapic_setup && io_apic_irqs)
#ifdef CONFIG_ACPI_BOOT
-extern int io_apic_get_unique_id (int ioapic, int apic_id);
extern int io_apic_get_version (int ioapic);
extern int io_apic_get_redir_entries (int ioapic);
extern int io_apic_set_pci_routing (int ioapic, int pin, int irq, int, int);
diff --git a/include/asm-x86_64/ioctl32.h b/include/asm-x86_64/ioctl32.h
deleted file mode 100644
index d0d227f45e0..00000000000
--- a/include/asm-x86_64/ioctl32.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <linux/ioctl32.h>
diff --git a/include/asm-x86_64/irq.h b/include/asm-x86_64/irq.h
index 3af50b3c3b0..eb3b7aa9eb9 100644
--- a/include/asm-x86_64/irq.h
+++ b/include/asm-x86_64/irq.h
@@ -52,4 +52,9 @@ struct irqaction;
struct pt_regs;
int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
+#ifdef CONFIG_HOTPLUG_CPU
+#include <linux/cpumask.h>
+extern void fixup_irqs(cpumask_t map);
+#endif
+
#endif /* _ASM_IRQ_H */
diff --git a/include/asm-x86_64/kdebug.h b/include/asm-x86_64/kdebug.h
index 6277f75cbb4..b90341994d8 100644
--- a/include/asm-x86_64/kdebug.h
+++ b/include/asm-x86_64/kdebug.h
@@ -14,7 +14,7 @@ struct die_args {
};
/* Note - you should never unregister because that can race with NMIs.
- If you really want to do it first unregister - then synchronize_kernel - then free.
+ If you really want to do it first unregister - then synchronize_sched - then free.
*/
int register_die_notifier(struct notifier_block *nb);
extern struct notifier_block *die_chain;
diff --git a/include/asm-x86_64/kexec.h b/include/asm-x86_64/kexec.h
new file mode 100644
index 00000000000..42d2ff15c59
--- /dev/null
+++ b/include/asm-x86_64/kexec.h
@@ -0,0 +1,33 @@
+#ifndef _X86_64_KEXEC_H
+#define _X86_64_KEXEC_H
+
+#include <asm/page.h>
+#include <asm/proto.h>
+
+/*
+ * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return.
+ * I.e. Maximum page that is mapped directly into kernel memory,
+ * and kmap is not required.
+ *
+ * So far x86_64 is limited to 40 physical address bits.
+ */
+
+/* Maximum physical address we can use pages from */
+#define KEXEC_SOURCE_MEMORY_LIMIT (0xFFFFFFFFFFUL)
+/* Maximum address we can reach in physical address mode */
+#define KEXEC_DESTINATION_MEMORY_LIMIT (0xFFFFFFFFFFUL)
+/* Maximum address we can use for the control pages */
+#define KEXEC_CONTROL_MEMORY_LIMIT (0xFFFFFFFFFFUL)
+
+/* Allocate one page for the pdp and the second for the code */
+#define KEXEC_CONTROL_CODE_SIZE (4096UL + 4096UL)
+
+/* The native architecture */
+#define KEXEC_ARCH KEXEC_ARCH_X86_64
+
+#define MAX_NOTE_BYTES 1024
+typedef u32 note_buf_t[MAX_NOTE_BYTES/4];
+
+extern note_buf_t crash_notes[];
+
+#endif /* _X86_64_KEXEC_H */
diff --git a/include/asm-x86_64/kprobes.h b/include/asm-x86_64/kprobes.h
index bfea52d516f..6d6d883fdf6 100644
--- a/include/asm-x86_64/kprobes.h
+++ b/include/asm-x86_64/kprobes.h
@@ -38,6 +38,9 @@ typedef u8 kprobe_opcode_t;
: (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR)))
#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry
+#define ARCH_SUPPORTS_KRETPROBES
+
+void kretprobe_trampoline(void);
/* Architecture specific copy of original instruction*/
struct arch_specific_insn {
diff --git a/include/asm-x86_64/mmzone.h b/include/asm-x86_64/mmzone.h
index d95b7c24083..768413751b3 100644
--- a/include/asm-x86_64/mmzone.h
+++ b/include/asm-x86_64/mmzone.h
@@ -6,7 +6,7 @@
#include <linux/config.h>
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NUMA
#define VIRTUAL_BUG_ON(x)
@@ -30,27 +30,23 @@ static inline __attribute__((pure)) int phys_to_nid(unsigned long addr)
return nid;
}
-#define pfn_to_nid(pfn) phys_to_nid((unsigned long)(pfn) << PAGE_SHIFT)
-
-#define kvaddr_to_nid(kaddr) phys_to_nid(__pa(kaddr))
#define NODE_DATA(nid) (node_data[nid])
-#define node_mem_map(nid) (NODE_DATA(nid)->node_mem_map)
-
-#define node_mem_map(nid) (NODE_DATA(nid)->node_mem_map)
#define node_start_pfn(nid) (NODE_DATA(nid)->node_start_pfn)
#define node_end_pfn(nid) (NODE_DATA(nid)->node_start_pfn + \
NODE_DATA(nid)->node_spanned_pages)
-#define local_mapnr(kvaddr) \
- ( (__pa(kvaddr) >> PAGE_SHIFT) - node_start_pfn(kvaddr_to_nid(kvaddr)) )
+#ifdef CONFIG_DISCONTIGMEM
+
+#define pfn_to_nid(pfn) phys_to_nid((unsigned long)(pfn) << PAGE_SHIFT)
+#define kvaddr_to_nid(kaddr) phys_to_nid(__pa(kaddr))
/* AK: this currently doesn't deal with invalid addresses. We'll see
if the 2.5 kernel doesn't pass them
(2.4 used to). */
#define pfn_to_page(pfn) ({ \
int nid = phys_to_nid(((unsigned long)(pfn)) << PAGE_SHIFT); \
- ((pfn) - node_start_pfn(nid)) + node_mem_map(nid); \
+ ((pfn) - node_start_pfn(nid)) + NODE_DATA(nid)->node_mem_map; \
})
#define page_to_pfn(page) \
@@ -60,4 +56,8 @@ static inline __attribute__((pure)) int phys_to_nid(unsigned long addr)
({ u8 nid__ = pfn_to_nid(pfn); \
nid__ != 0xff && (pfn) >= node_start_pfn(nid__) && (pfn) <= node_end_pfn(nid__); }))
#endif
+
+#define local_mapnr(kvaddr) \
+ ( (__pa(kvaddr) >> PAGE_SHIFT) - node_start_pfn(kvaddr_to_nid(kvaddr)) )
+#endif
#endif
diff --git a/include/asm-x86_64/msr.h b/include/asm-x86_64/msr.h
index 513e52c7182..bc700232728 100644
--- a/include/asm-x86_64/msr.h
+++ b/include/asm-x86_64/msr.h
@@ -57,11 +57,6 @@
(val) = ((unsigned long)__a) | (((unsigned long)__d)<<32); \
} while(0)
-#define rdpmc(counter,low,high) \
- __asm__ __volatile__("rdpmc" \
- : "=a" (low), "=d" (high) \
- : "c" (counter))
-
#define write_tsc(val1,val2) wrmsr(0x10, val1, val2)
#define rdpmc(counter,low,high) \
diff --git a/include/asm-x86_64/nmi.h b/include/asm-x86_64/nmi.h
index 21d56b086b9..d3abfc6a8fd 100644
--- a/include/asm-x86_64/nmi.h
+++ b/include/asm-x86_64/nmi.h
@@ -53,5 +53,7 @@ extern void die_nmi(char *str, struct pt_regs *regs);
extern int panic_on_timeout;
extern int unknown_nmi_panic;
+
+extern int check_nmi_watchdog(void);
#endif /* ASM_NMI_H */
diff --git a/include/asm-x86_64/page.h b/include/asm-x86_64/page.h
index f43048035a0..431318764af 100644
--- a/include/asm-x86_64/page.h
+++ b/include/asm-x86_64/page.h
@@ -28,6 +28,7 @@
#define HPAGE_SIZE ((1UL) << HPAGE_SHIFT)
#define HPAGE_MASK (~(HPAGE_SIZE - 1))
#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT)
+#define ARCH_HAS_HUGETLB_CLEAN_STALE_PGTABLE
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
@@ -63,12 +64,14 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#define __pgd(x) ((pgd_t) { (x) } )
#define __pgprot(x) ((pgprot_t) { (x) } )
-#define __START_KERNEL 0xffffffff80100000UL
+#define __PHYSICAL_START ((unsigned long)CONFIG_PHYSICAL_START)
+#define __START_KERNEL (__START_KERNEL_map + __PHYSICAL_START)
#define __START_KERNEL_map 0xffffffff80000000UL
#define __PAGE_OFFSET 0xffff810000000000UL
#else
-#define __START_KERNEL 0xffffffff80100000
+#define __PHYSICAL_START CONFIG_PHYSICAL_START
+#define __START_KERNEL (__START_KERNEL_map + __PHYSICAL_START)
#define __START_KERNEL_map 0xffffffff80000000
#define __PAGE_OFFSET 0xffff810000000000
#endif /* !__ASSEMBLY__ */
@@ -118,7 +121,9 @@ extern __inline__ int get_order(unsigned long size)
__pa(v); })
#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
-#ifndef CONFIG_DISCONTIGMEM
+#define __boot_va(x) __va(x)
+#define __boot_pa(x) __pa(x)
+#ifdef CONFIG_FLATMEM
#define pfn_to_page(pfn) (mem_map + (pfn))
#define page_to_pfn(page) ((unsigned long)((page) - mem_map))
#define pfn_valid(pfn) ((pfn) < max_mapnr)
diff --git a/include/asm-x86_64/param.h b/include/asm-x86_64/param.h
index b707f0568c9..40b11937180 100644
--- a/include/asm-x86_64/param.h
+++ b/include/asm-x86_64/param.h
@@ -1,9 +1,11 @@
+#include <linux/config.h>
+
#ifndef _ASMx86_64_PARAM_H
#define _ASMx86_64_PARAM_H
#ifdef __KERNEL__
-# define HZ 1000 /* Internal kernel timer frequency */
-# define USER_HZ 100 /* .. some user interfaces are in "ticks */
+# define HZ CONFIG_HZ /* Internal kernel timer frequency */
+# define USER_HZ 100 /* .. some user interfaces are in "ticks */
#define CLOCKS_PER_SEC (USER_HZ) /* like times() */
#endif
diff --git a/include/asm-x86_64/percpu.h b/include/asm-x86_64/percpu.h
index 415d73f3c8e..9c71855736f 100644
--- a/include/asm-x86_64/percpu.h
+++ b/include/asm-x86_64/percpu.h
@@ -39,7 +39,7 @@ extern void setup_per_cpu_areas(void);
#define DEFINE_PER_CPU(type, name) \
__typeof__(type) per_cpu__##name
-#define per_cpu(var, cpu) (*((void)cpu, &per_cpu__##var))
+#define per_cpu(var, cpu) (*((void)(cpu), &per_cpu__##var))
#define __get_cpu_var(var) per_cpu__##var
#endif /* SMP */
diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h
index db2a0efbf57..4eec176c3c3 100644
--- a/include/asm-x86_64/pgtable.h
+++ b/include/asm-x86_64/pgtable.h
@@ -253,6 +253,7 @@ extern inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED;
extern inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
+#define __LARGE_PTE (_PAGE_PSE|_PAGE_PRESENT)
extern inline pte_t pte_rdprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
extern inline pte_t pte_exprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
extern inline pte_t pte_mkclean(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return pte; }
@@ -263,6 +264,7 @@ extern inline pte_t pte_mkexec(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _
extern inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
extern inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
extern inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; }
+extern inline pte_t pte_mkhuge(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | __LARGE_PTE)); return pte; }
struct vm_area_struct;
@@ -290,7 +292,6 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
*/
#define pgprot_noncached(prot) (__pgprot(pgprot_val(prot) | _PAGE_PCD | _PAGE_PWT))
-#define __LARGE_PTE (_PAGE_PSE|_PAGE_PRESENT)
static inline int pmd_large(pmd_t pte) {
return (pmd_val(pte) & __LARGE_PTE) == __LARGE_PTE;
}
diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h
index f0581c35628..106f666517b 100644
--- a/include/asm-x86_64/processor.h
+++ b/include/asm-x86_64/processor.h
@@ -62,7 +62,6 @@ struct cpuinfo_x86 {
int x86_tlbsize; /* number of 4K pages in DTLB/ITLB combined(in pages)*/
__u8 x86_virt_bits, x86_phys_bits;
__u8 x86_num_cores;
- __u8 x86_apicid;
__u32 x86_power;
__u32 extended_cpuid_level; /* Max extended CPUID function supported */
unsigned long loops_per_jiffy;
@@ -159,18 +158,19 @@ static inline void clear_in_cr4 (unsigned long mask)
/*
- * User space process size. 47bits.
+ * User space process size. 47bits minus one guard page.
*/
-#define TASK_SIZE (0x800000000000UL)
+#define TASK_SIZE64 (0x800000000000UL - 4096)
/* This decides where the kernel will search for a free chunk of vm
* space during mmap's.
*/
#define IA32_PAGE_OFFSET ((current->personality & ADDR_LIMIT_3GB) ? 0xc0000000 : 0xFFFFe000)
-#define TASK_UNMAPPED_32 PAGE_ALIGN(IA32_PAGE_OFFSET/3)
-#define TASK_UNMAPPED_64 PAGE_ALIGN(TASK_SIZE/3)
-#define TASK_UNMAPPED_BASE \
- (test_thread_flag(TIF_IA32) ? TASK_UNMAPPED_32 : TASK_UNMAPPED_64)
+
+#define TASK_SIZE (test_thread_flag(TIF_IA32) ? IA32_PAGE_OFFSET : TASK_SIZE64)
+#define TASK_SIZE_OF(child) ((test_tsk_thread_flag(child, TIF_IA32)) ? IA32_PAGE_OFFSET : TASK_SIZE64)
+
+#define TASK_UNMAPPED_BASE PAGE_ALIGN(TASK_SIZE/3)
/*
* Size of io_bitmap.
@@ -280,6 +280,14 @@ struct thread_struct {
set_fs(USER_DS); \
} while(0)
+#define get_debugreg(var, register) \
+ __asm__("movq %%db" #register ", %0" \
+ :"=r" (var))
+#define set_debugreg(value, register) \
+ __asm__("movq %0,%%db" #register \
+ : /* no output */ \
+ :"r" (value))
+
struct task_struct;
struct mm_struct;
diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h
index d0f8f8b4c39..f2f073642d6 100644
--- a/include/asm-x86_64/proto.h
+++ b/include/asm-x86_64/proto.h
@@ -30,6 +30,11 @@ extern void ia32_syscall(void);
extern void iommu_hole_init(void);
extern void time_init_gtod(void);
+extern int pmtimer_mark_offset(void);
+extern unsigned int do_gettimeoffset_pm(void);
+extern u32 pmtmr_ioport;
+extern unsigned long long monotonic_base;
+extern int sysctl_vsyscall;
extern void do_softirq_thunk(void);
diff --git a/include/asm-x86_64/ptrace.h b/include/asm-x86_64/ptrace.h
index 5bbc8d3141c..ca6f15ff61d 100644
--- a/include/asm-x86_64/ptrace.h
+++ b/include/asm-x86_64/ptrace.h
@@ -82,6 +82,7 @@ struct pt_regs {
#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
#define user_mode(regs) (!!((regs)->cs & 3))
+#define user_mode_vm(regs) user_mode(regs)
#define instruction_pointer(regs) ((regs)->rip)
extern unsigned long profile_pc(struct pt_regs *regs);
void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
diff --git a/include/asm-x86_64/smp.h b/include/asm-x86_64/smp.h
index 96844fecbde..aeb1b73e21e 100644
--- a/include/asm-x86_64/smp.h
+++ b/include/asm-x86_64/smp.h
@@ -43,6 +43,8 @@ extern cpumask_t cpu_callout_map;
extern void smp_alloc_memory(void);
extern volatile unsigned long smp_invalidate_needed;
extern int pic_mode;
+extern void lock_ipi_call_lock(void);
+extern void unlock_ipi_call_lock(void);
extern int smp_num_siblings;
extern void smp_flush_tlb(void);
extern void smp_message_irq(int cpl, void *dev_id, struct pt_regs *regs);
@@ -68,7 +70,7 @@ static inline int num_booting_cpus(void)
return cpus_weight(cpu_callout_map);
}
-#define __smp_processor_id() read_pda(cpunumber)
+#define raw_smp_processor_id() read_pda(cpunumber)
extern __inline int hard_smp_processor_id(void)
{
@@ -77,6 +79,8 @@ extern __inline int hard_smp_processor_id(void)
}
extern int safe_smp_processor_id(void);
+extern int __cpu_disable(void);
+extern void __cpu_die(unsigned int cpu);
#endif /* !ASSEMBLY */
diff --git a/include/asm-x86_64/sparsemem.h b/include/asm-x86_64/sparsemem.h
new file mode 100644
index 00000000000..dabb16714a7
--- /dev/null
+++ b/include/asm-x86_64/sparsemem.h
@@ -0,0 +1,26 @@
+#ifndef _ASM_X86_64_SPARSEMEM_H
+#define _ASM_X86_64_SPARSEMEM_H 1
+
+#ifdef CONFIG_SPARSEMEM
+
+/*
+ * generic non-linear memory support:
+ *
+ * 1) we will not split memory into more chunks than will fit into the flags
+ * field of the struct page
+ *
+ * SECTION_SIZE_BITS 2^n: size of each section
+ * MAX_PHYSADDR_BITS 2^n: max size of physical address space
+ * MAX_PHYSMEM_BITS 2^n: how much memory we can have in that space
+ *
+ */
+
+#define SECTION_SIZE_BITS 27 /* matt - 128 is convenient right now */
+#define MAX_PHYSADDR_BITS 40
+#define MAX_PHYSMEM_BITS 40
+
+extern int early_pfn_to_nid(unsigned long pfn);
+
+#endif /* CONFIG_SPARSEMEM */
+
+#endif /* _ASM_X86_64_SPARSEMEM_H */
diff --git a/include/asm-x86_64/suspend.h b/include/asm-x86_64/suspend.h
index ec745807fea..bb9f40597d0 100644
--- a/include/asm-x86_64/suspend.h
+++ b/include/asm-x86_64/suspend.h
@@ -16,7 +16,7 @@ arch_prepare_suspend(void)
struct saved_context {
u16 ds, es, fs, gs, ss;
unsigned long gs_base, gs_kernel_base, fs_base;
- unsigned long cr0, cr2, cr3, cr4;
+ unsigned long cr0, cr2, cr3, cr4, cr8;
u16 gdt_pad;
u16 gdt_limit;
unsigned long gdt_base;
diff --git a/include/asm-x86_64/thread_info.h b/include/asm-x86_64/thread_info.h
index f4b3b249639..08eb6e4f373 100644
--- a/include/asm-x86_64/thread_info.h
+++ b/include/asm-x86_64/thread_info.h
@@ -29,7 +29,7 @@ struct thread_info {
__u32 flags; /* low level flags */
__u32 status; /* thread synchronous flags */
__u32 cpu; /* current CPU */
- int preempt_count;
+ int preempt_count; /* 0 => preemptable, <0 => BUG */
mm_segment_t addr_limit;
struct restart_block restart_block;
diff --git a/include/asm-x86_64/timex.h b/include/asm-x86_64/timex.h
index 34f31a18f90..24ecf6a637c 100644
--- a/include/asm-x86_64/timex.h
+++ b/include/asm-x86_64/timex.h
@@ -26,6 +26,9 @@ static inline cycles_t get_cycles (void)
extern unsigned int cpu_khz;
+extern int read_current_timer(unsigned long *timer_value);
+#define ARCH_HAS_READ_CURRENT_TIMER 1
+
extern struct vxtime_data vxtime;
#endif
diff --git a/include/asm-x86_64/topology.h b/include/asm-x86_64/topology.h
index 67f24e0ea81..c1bc3fad482 100644
--- a/include/asm-x86_64/topology.h
+++ b/include/asm-x86_64/topology.h
@@ -3,7 +3,7 @@
#include <linux/config.h>
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NUMA
#include <asm/mpspec.h>
#include <asm/bitops.h>
@@ -13,8 +13,8 @@
extern cpumask_t cpu_online_map;
extern unsigned char cpu_to_node[];
+extern unsigned char pci_bus_to_node[];
extern cpumask_t node_to_cpumask[];
-extern cpumask_t pci_bus_to_cpumask[];
#ifdef CONFIG_ACPI_NUMA
extern int __node_distance(int, int);
@@ -26,18 +26,9 @@ extern int __node_distance(int, int);
#define parent_node(node) (node)
#define node_to_first_cpu(node) (__ffs(node_to_cpumask[node]))
#define node_to_cpumask(node) (node_to_cpumask[node])
+#define pcibus_to_node(bus) pci_bus_to_node[(bus)->number]
+#define pcibus_to_cpumask(bus) node_to_cpumask(pcibus_to_node(bus));
-static inline cpumask_t __pcibus_to_cpumask(int bus)
-{
- cpumask_t busmask = pci_bus_to_cpumask[bus];
- cpumask_t online = cpu_online_map;
- cpumask_t res;
- cpus_and(res, busmask, online);
- return res;
-}
-#define pcibus_to_cpumask(bus) __pcibus_to_cpumask(bus->number)
-
-#ifdef CONFIG_NUMA
/* sched_domains SD_NODE_INIT for x86_64 machines */
#define SD_NODE_INIT (struct sched_domain) { \
.span = CPU_MASK_NONE, \
@@ -48,18 +39,21 @@ static inline cpumask_t __pcibus_to_cpumask(int bus)
.busy_factor = 32, \
.imbalance_pct = 125, \
.cache_hot_time = (10*1000000), \
- .cache_nice_tries = 1, \
+ .cache_nice_tries = 2, \
+ .busy_idx = 3, \
+ .idle_idx = 2, \
+ .newidle_idx = 0, \
+ .wake_idx = 1, \
+ .forkexec_idx = 1, \
.per_cpu_gain = 100, \
.flags = SD_LOAD_BALANCE \
- | SD_BALANCE_NEWIDLE \
+ | SD_BALANCE_FORK \
| SD_BALANCE_EXEC \
- | SD_WAKE_IDLE \
| SD_WAKE_BALANCE, \
.last_balance = jiffies, \
.balance_interval = 1, \
.nr_balance_failed = 0, \
}
-#endif
#endif
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index 3c9af6fd433..d767adcbf0f 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -552,7 +552,7 @@ __SYSCALL(__NR_mq_notify, sys_mq_notify)
#define __NR_mq_getsetattr 245
__SYSCALL(__NR_mq_getsetattr, sys_mq_getsetattr)
#define __NR_kexec_load 246
-__SYSCALL(__NR_kexec_load, sys_ni_syscall)
+__SYSCALL(__NR_kexec_load, sys_kexec_load)
#define __NR_waitid 247
__SYSCALL(__NR_waitid, sys_waitid)
#define __NR_add_key 248
diff --git a/include/asm-x86_64/vsyscall.h b/include/asm-x86_64/vsyscall.h
index b0c8d433990..2872da23fc7 100644
--- a/include/asm-x86_64/vsyscall.h
+++ b/include/asm-x86_64/vsyscall.h
@@ -25,6 +25,7 @@ enum vsyscall_num {
#define VXTIME_TSC 1
#define VXTIME_HPET 2
+#define VXTIME_PMTMR 3
struct vxtime_data {
long hpet_address; /* HPET base address */
@@ -54,6 +55,8 @@ extern struct timezone sys_tz;
extern int sysctl_vsyscall;
extern seqlock_t xtime_lock;
+extern int sysctl_vsyscall;
+
#define ARCH_HAVE_XTIME_LOCK 1
#endif /* __KERNEL__ */
diff --git a/include/asm-xtensa/a.out.h b/include/asm-xtensa/a.out.h
new file mode 100644
index 00000000000..3be701dfe09
--- /dev/null
+++ b/include/asm-xtensa/a.out.h
@@ -0,0 +1,33 @@
+/*
+ * include/asm-xtensa/addrspace.h
+ *
+ * Dummy a.out file. Xtensa does not support the a.out format, but the kernel
+ * seems to depend on it.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_A_OUT_H
+#define _XTENSA_A_OUT_H
+
+/* Note: the kernel needs the a.out definitions, even if only ELF is used. */
+
+#define STACK_TOP TASK_SIZE
+
+struct exec
+{
+ unsigned long a_info;
+ unsigned a_text;
+ unsigned a_data;
+ unsigned a_bss;
+ unsigned a_syms;
+ unsigned a_entry;
+ unsigned a_trsize;
+ unsigned a_drsize;
+};
+
+#endif /* _XTENSA_A_OUT_H */
diff --git a/include/asm-xtensa/atomic.h b/include/asm-xtensa/atomic.h
new file mode 100644
index 00000000000..d72bcb32ba4
--- /dev/null
+++ b/include/asm-xtensa/atomic.h
@@ -0,0 +1,272 @@
+/*
+ * include/asm-xtensa/atomic.h
+ *
+ * Atomic operations that C can't guarantee us. Useful for resource counting..
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_ATOMIC_H
+#define _XTENSA_ATOMIC_H
+
+#include <linux/config.h>
+#include <linux/stringify.h>
+
+typedef struct { volatile int counter; } atomic_t;
+
+#ifdef __KERNEL__
+#include <asm/processor.h>
+#include <asm/system.h>
+
+#define ATOMIC_INIT(i) ( (atomic_t) { (i) } )
+
+/*
+ * This Xtensa implementation assumes that the right mechanism
+ * for exclusion is for locking interrupts to level 1.
+ *
+ * Locking interrupts looks like this:
+ *
+ * rsil a15, 1
+ * <code>
+ * wsr a15, PS
+ * rsync
+ *
+ * Note that a15 is used here because the register allocation
+ * done by the compiler is not guaranteed and a window overflow
+ * may not occur between the rsil and wsr instructions. By using
+ * a15 in the rsil, the machine is guaranteed to be in a state
+ * where no register reference will cause an overflow.
+ */
+
+/**
+ * atomic_read - read atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically reads the value of @v.
+ */
+#define atomic_read(v) ((v)->counter)
+
+/**
+ * atomic_set - set atomic variable
+ * @v: pointer of type atomic_t
+ * @i: required value
+ *
+ * Atomically sets the value of @v to @i.
+ */
+#define atomic_set(v,i) ((v)->counter = (i))
+
+/**
+ * atomic_add - add integer to atomic variable
+ * @i: integer value to add
+ * @v: pointer of type atomic_t
+ *
+ * Atomically adds @i to @v.
+ */
+extern __inline__ void atomic_add(int i, atomic_t * v)
+{
+ unsigned int vval;
+
+ __asm__ __volatile__(
+ "rsil a15, "__stringify(LOCKLEVEL)"\n\t"
+ "l32i %0, %2, 0 \n\t"
+ "add %0, %0, %1 \n\t"
+ "s32i %0, %2, 0 \n\t"
+ "wsr a15, "__stringify(PS)" \n\t"
+ "rsync \n"
+ : "=&a" (vval)
+ : "a" (i), "a" (v)
+ : "a15", "memory"
+ );
+}
+
+/**
+ * atomic_sub - subtract the atomic variable
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+ *
+ * Atomically subtracts @i from @v.
+ */
+extern __inline__ void atomic_sub(int i, atomic_t *v)
+{
+ unsigned int vval;
+
+ __asm__ __volatile__(
+ "rsil a15, "__stringify(LOCKLEVEL)"\n\t"
+ "l32i %0, %2, 0 \n\t"
+ "sub %0, %0, %1 \n\t"
+ "s32i %0, %2, 0 \n\t"
+ "wsr a15, "__stringify(PS)" \n\t"
+ "rsync \n"
+ : "=&a" (vval)
+ : "a" (i), "a" (v)
+ : "a15", "memory"
+ );
+}
+
+/*
+ * We use atomic_{add|sub}_return to define other functions.
+ */
+
+extern __inline__ int atomic_add_return(int i, atomic_t * v)
+{
+ unsigned int vval;
+
+ __asm__ __volatile__(
+ "rsil a15,"__stringify(LOCKLEVEL)"\n\t"
+ "l32i %0, %2, 0 \n\t"
+ "add %0, %0, %1 \n\t"
+ "s32i %0, %2, 0 \n\t"
+ "wsr a15, "__stringify(PS)" \n\t"
+ "rsync \n"
+ : "=&a" (vval)
+ : "a" (i), "a" (v)
+ : "a15", "memory"
+ );
+
+ return vval;
+}
+
+extern __inline__ int atomic_sub_return(int i, atomic_t * v)
+{
+ unsigned int vval;
+
+ __asm__ __volatile__(
+ "rsil a15,"__stringify(LOCKLEVEL)"\n\t"
+ "l32i %0, %2, 0 \n\t"
+ "sub %0, %0, %1 \n\t"
+ "s32i %0, %2, 0 \n\t"
+ "wsr a15, "__stringify(PS)" \n\t"
+ "rsync \n"
+ : "=&a" (vval)
+ : "a" (i), "a" (v)
+ : "a15", "memory"
+ );
+
+ return vval;
+}
+
+/**
+ * atomic_sub_and_test - subtract value from variable and test result
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+ *
+ * Atomically subtracts @i from @v and returns
+ * true if the result is zero, or false for all
+ * other cases.
+ */
+#define atomic_sub_and_test(i,v) (atomic_sub_return((i),(v)) == 0)
+
+/**
+ * atomic_inc - increment atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1.
+ */
+#define atomic_inc(v) atomic_add(1,(v))
+
+/**
+ * atomic_inc - increment atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1.
+ */
+#define atomic_inc_return(v) atomic_add_return(1,(v))
+
+/**
+ * atomic_dec - decrement atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1.
+ */
+#define atomic_dec(v) atomic_sub(1,(v))
+
+/**
+ * atomic_dec_return - decrement atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1.
+ */
+#define atomic_dec_return(v) atomic_sub_return(1,(v))
+
+/**
+ * atomic_dec_and_test - decrement and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases.
+ */
+#define atomic_dec_and_test(v) (atomic_sub_return(1,(v)) == 0)
+
+/**
+ * atomic_inc_and_test - increment and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+#define atomic_inc_and_test(v) (atomic_add_return(1,(v)) == 0)
+
+/**
+ * atomic_add_negative - add and test if negative
+ * @v: pointer of type atomic_t
+ * @i: integer value to add
+ *
+ * Atomically adds @i to @v and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero.
+ */
+#define atomic_add_negative(i,v) (atomic_add_return((i),(v)) < 0)
+
+
+extern __inline__ void atomic_clear_mask(unsigned int mask, atomic_t *v)
+{
+ unsigned int all_f = -1;
+ unsigned int vval;
+
+ __asm__ __volatile__(
+ "rsil a15,"__stringify(LOCKLEVEL)"\n\t"
+ "l32i %0, %2, 0 \n\t"
+ "xor %1, %4, %3 \n\t"
+ "and %0, %0, %4 \n\t"
+ "s32i %0, %2, 0 \n\t"
+ "wsr a15, "__stringify(PS)" \n\t"
+ "rsync \n"
+ : "=&a" (vval), "=a" (mask)
+ : "a" (v), "a" (all_f), "1" (mask)
+ : "a15", "memory"
+ );
+}
+
+extern __inline__ void atomic_set_mask(unsigned int mask, atomic_t *v)
+{
+ unsigned int vval;
+
+ __asm__ __volatile__(
+ "rsil a15,"__stringify(LOCKLEVEL)"\n\t"
+ "l32i %0, %2, 0 \n\t"
+ "or %0, %0, %1 \n\t"
+ "s32i %0, %2, 0 \n\t"
+ "wsr a15, "__stringify(PS)" \n\t"
+ "rsync \n"
+ : "=&a" (vval)
+ : "a" (mask), "a" (v)
+ : "a15", "memory"
+ );
+}
+
+/* Atomic operations are already serializing */
+#define smp_mb__before_atomic_dec() barrier()
+#define smp_mb__after_atomic_dec() barrier()
+#define smp_mb__before_atomic_inc() barrier()
+#define smp_mb__after_atomic_inc() barrier()
+
+#endif /* __KERNEL__ */
+
+#endif /* _XTENSA_ATOMIC_H */
+
diff --git a/include/asm-xtensa/bitops.h b/include/asm-xtensa/bitops.h
new file mode 100644
index 00000000000..d395ef226c3
--- /dev/null
+++ b/include/asm-xtensa/bitops.h
@@ -0,0 +1,446 @@
+/*
+ * include/asm-xtensa/bitops.h
+ *
+ * Atomic operations that C can't guarantee us.Useful for resource counting etc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_BITOPS_H
+#define _XTENSA_BITOPS_H
+
+#ifdef __KERNEL__
+
+#include <asm/processor.h>
+#include <asm/byteorder.h>
+#include <asm/system.h>
+
+#ifdef CONFIG_SMP
+# error SMP not supported on this architecture
+#endif
+
+static __inline__ void set_bit(int nr, volatile void * addr)
+{
+ unsigned long mask = 1 << (nr & 0x1f);
+ unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
+ unsigned long flags;
+
+ local_irq_save(flags);
+ *a |= mask;
+ local_irq_restore(flags);
+}
+
+static __inline__ void __set_bit(int nr, volatile unsigned long * addr)
+{
+ unsigned long mask = 1 << (nr & 0x1f);
+ unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
+
+ *a |= mask;
+}
+
+static __inline__ void clear_bit(int nr, volatile void * addr)
+{
+ unsigned long mask = 1 << (nr & 0x1f);
+ unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
+ unsigned long flags;
+
+ local_irq_save(flags);
+ *a &= ~mask;
+ local_irq_restore(flags);
+}
+
+static __inline__ void __clear_bit(int nr, volatile unsigned long *addr)
+{
+ unsigned long mask = 1 << (nr & 0x1f);
+ unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
+
+ *a &= ~mask;
+}
+
+/*
+ * clear_bit() doesn't provide any barrier for the compiler.
+ */
+
+#define smp_mb__before_clear_bit() barrier()
+#define smp_mb__after_clear_bit() barrier()
+
+static __inline__ void change_bit(int nr, volatile void * addr)
+{
+ unsigned long mask = 1 << (nr & 0x1f);
+ unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
+ unsigned long flags;
+
+ local_irq_save(flags);
+ *a ^= mask;
+ local_irq_restore(flags);
+}
+
+static __inline__ void __change_bit(int nr, volatile void * addr)
+{
+ unsigned long mask = 1 << (nr & 0x1f);
+ unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
+
+ *a ^= mask;
+}
+
+static __inline__ int test_and_set_bit(int nr, volatile void * addr)
+{
+ unsigned long retval;
+ unsigned long mask = 1 << (nr & 0x1f);
+ unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
+ unsigned long flags;
+
+ local_irq_save(flags);
+ retval = (mask & *a) != 0;
+ *a |= mask;
+ local_irq_restore(flags);
+
+ return retval;
+}
+
+static __inline__ int __test_and_set_bit(int nr, volatile void * addr)
+{
+ unsigned long retval;
+ unsigned long mask = 1 << (nr & 0x1f);
+ unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
+
+ retval = (mask & *a) != 0;
+ *a |= mask;
+
+ return retval;
+}
+
+static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
+{
+ unsigned long retval;
+ unsigned long mask = 1 << (nr & 0x1f);
+ unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
+ unsigned long flags;
+
+ local_irq_save(flags);
+ retval = (mask & *a) != 0;
+ *a &= ~mask;
+ local_irq_restore(flags);
+
+ return retval;
+}
+
+static __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
+{
+ unsigned long mask = 1 << (nr & 0x1f);
+ unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
+ unsigned long old = *a;
+
+ *a = old & ~mask;
+ return (old & mask) != 0;
+}
+
+static __inline__ int test_and_change_bit(int nr, volatile void * addr)
+{
+ unsigned long retval;
+ unsigned long mask = 1 << (nr & 0x1f);
+ unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ retval = (mask & *a) != 0;
+ *a ^= mask;
+ local_irq_restore(flags);
+
+ return retval;
+}
+
+/*
+ * non-atomic version; can be reordered
+ */
+
+static __inline__ int __test_and_change_bit(int nr, volatile void *addr)
+{
+ unsigned long mask = 1 << (nr & 0x1f);
+ unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
+ unsigned long old = *a;
+
+ *a = old ^ mask;
+ return (old & mask) != 0;
+}
+
+static __inline__ int test_bit(int nr, const volatile void *addr)
+{
+ return 1UL & (((const volatile unsigned int *)addr)[nr>>5] >> (nr&31));
+}
+
+#if XCHAL_HAVE_NSAU
+
+static __inline__ int __cntlz (unsigned long x)
+{
+ int lz;
+ asm ("nsau %0, %1" : "=r" (lz) : "r" (x));
+ return 31 - lz;
+}
+
+#else
+
+static __inline__ int __cntlz (unsigned long x)
+{
+ unsigned long sum, x1, x2, x4, x8, x16;
+ x1 = x & 0xAAAAAAAA;
+ x2 = x & 0xCCCCCCCC;
+ x4 = x & 0xF0F0F0F0;
+ x8 = x & 0xFF00FF00;
+ x16 = x & 0xFFFF0000;
+ sum = x2 ? 2 : 0;
+ sum += (x16 != 0) * 16;
+ sum += (x8 != 0) * 8;
+ sum += (x4 != 0) * 4;
+ sum += (x1 != 0);
+
+ return sum;
+}
+
+#endif
+
+/*
+ * ffz: Find first zero in word. Undefined if no zero exists.
+ * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
+ */
+
+static __inline__ int ffz(unsigned long x)
+{
+ if ((x = ~x) == 0)
+ return 32;
+ return __cntlz(x & -x);
+}
+
+/*
+ * __ffs: Find first bit set in word. Return 0 for bit 0
+ */
+
+static __inline__ int __ffs(unsigned long x)
+{
+ return __cntlz(x & -x);
+}
+
+/*
+ * ffs: Find first bit set in word. This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
+ */
+
+static __inline__ int ffs(unsigned long x)
+{
+ return __cntlz(x & -x) + 1;
+}
+
+/*
+ * fls: Find last (most-significant) bit set in word.
+ * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
+ */
+
+static __inline__ int fls (unsigned int x)
+{
+ return __cntlz(x);
+}
+
+static __inline__ int
+find_next_bit(const unsigned long *addr, int size, int offset)
+{
+ const unsigned long *p = addr + (offset >> 5);
+ unsigned long result = offset & ~31UL;
+ unsigned long tmp;
+
+ if (offset >= size)
+ return size;
+ size -= result;
+ offset &= 31UL;
+ if (offset) {
+ tmp = *p++;
+ tmp &= ~0UL << offset;
+ if (size < 32)
+ goto found_first;
+ if (tmp)
+ goto found_middle;
+ size -= 32;
+ result += 32;
+ }
+ while (size >= 32) {
+ if ((tmp = *p++) != 0)
+ goto found_middle;
+ result += 32;
+ size -= 32;
+ }
+ if (!size)
+ return result;
+ tmp = *p;
+
+found_first:
+ tmp &= ~0UL >> (32 - size);
+ if (tmp == 0UL) /* Are any bits set? */
+ return result + size; /* Nope. */
+found_middle:
+ return result + __ffs(tmp);
+}
+
+/**
+ * find_first_bit - find the first set bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum size to search
+ *
+ * Returns the bit-number of the first set bit, not the number of the byte
+ * containing a bit.
+ */
+
+#define find_first_bit(addr, size) \
+ find_next_bit((addr), (size), 0)
+
+static __inline__ int
+find_next_zero_bit(const unsigned long *addr, int size, int offset)
+{
+ const unsigned long *p = addr + (offset >> 5);
+ unsigned long result = offset & ~31UL;
+ unsigned long tmp;
+
+ if (offset >= size)
+ return size;
+ size -= result;
+ offset &= 31UL;
+ if (offset) {
+ tmp = *p++;
+ tmp |= ~0UL >> (32-offset);
+ if (size < 32)
+ goto found_first;
+ if (~tmp)
+ goto found_middle;
+ size -= 32;
+ result += 32;
+ }
+ while (size & ~31UL) {
+ if (~(tmp = *p++))
+ goto found_middle;
+ result += 32;
+ size -= 32;
+ }
+ if (!size)
+ return result;
+ tmp = *p;
+
+found_first:
+ tmp |= ~0UL << size;
+found_middle:
+ return result + ffz(tmp);
+}
+
+#define find_first_zero_bit(addr, size) \
+ find_next_zero_bit((addr), (size), 0)
+
+#ifdef __XTENSA_EL__
+# define ext2_set_bit(nr,addr) __test_and_set_bit((nr), (addr))
+# define ext2_set_bit_atomic(lock,nr,addr) test_and_set_bit((nr),(addr))
+# define ext2_clear_bit(nr,addr) __test_and_clear_bit((nr), (addr))
+# define ext2_clear_bit_atomic(lock,nr,addr) test_and_clear_bit((nr),(addr))
+# define ext2_test_bit(nr,addr) test_bit((nr), (addr))
+# define ext2_find_first_zero_bit(addr, size) find_first_zero_bit((addr),(size))
+# define ext2_find_next_zero_bit(addr, size, offset) \
+ find_next_zero_bit((addr), (size), (offset))
+#elif defined(__XTENSA_EB__)
+# define ext2_set_bit(nr,addr) __test_and_set_bit((nr) ^ 0x18, (addr))
+# define ext2_set_bit_atomic(lock,nr,addr) test_and_set_bit((nr) ^ 0x18, (addr))
+# define ext2_clear_bit(nr,addr) __test_and_clear_bit((nr) ^ 18, (addr))
+# define ext2_clear_bit_atomic(lock,nr,addr) test_and_clear_bit((nr)^0x18,(addr))
+# define ext2_test_bit(nr,addr) test_bit((nr) ^ 0x18, (addr))
+# define ext2_find_first_zero_bit(addr, size) \
+ ext2_find_next_zero_bit((addr), (size), 0)
+
+static __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
+{
+ unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
+ unsigned long result = offset & ~31UL;
+ unsigned long tmp;
+
+ if (offset >= size)
+ return size;
+ size -= result;
+ offset &= 31UL;
+ if(offset) {
+ /* We hold the little endian value in tmp, but then the
+ * shift is illegal. So we could keep a big endian value
+ * in tmp, like this:
+ *
+ * tmp = __swab32(*(p++));
+ * tmp |= ~0UL >> (32-offset);
+ *
+ * but this would decrease preformance, so we change the
+ * shift:
+ */
+ tmp = *(p++);
+ tmp |= __swab32(~0UL >> (32-offset));
+ if(size < 32)
+ goto found_first;
+ if(~tmp)
+ goto found_middle;
+ size -= 32;
+ result += 32;
+ }
+ while(size & ~31UL) {
+ if(~(tmp = *(p++)))
+ goto found_middle;
+ result += 32;
+ size -= 32;
+ }
+ if(!size)
+ return result;
+ tmp = *p;
+
+found_first:
+ /* tmp is little endian, so we would have to swab the shift,
+ * see above. But then we have to swab tmp below for ffz, so
+ * we might as well do this here.
+ */
+ return result + ffz(__swab32(tmp) | (~0UL << size));
+found_middle:
+ return result + ffz(__swab32(tmp));
+}
+
+#else
+# error processor byte order undefined!
+#endif
+
+
+#define hweight32(x) generic_hweight32(x)
+#define hweight16(x) generic_hweight16(x)
+#define hweight8(x) generic_hweight8(x)
+
+/*
+ * Find the first bit set in a 140-bit bitmap.
+ * The first 100 bits are unlikely to be set.
+ */
+
+static inline int sched_find_first_bit(const unsigned long *b)
+{
+ if (unlikely(b[0]))
+ return __ffs(b[0]);
+ if (unlikely(b[1]))
+ return __ffs(b[1]) + 32;
+ if (unlikely(b[2]))
+ return __ffs(b[2]) + 64;
+ if (b[3])
+ return __ffs(b[3]) + 96;
+ return __ffs(b[4]) + 128;
+}
+
+
+/* Bitmap functions for the minix filesystem. */
+
+#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
+#define minix_set_bit(nr,addr) set_bit(nr,addr)
+#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
+#define minix_test_bit(nr,addr) test_bit(nr,addr)
+#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
+
+#endif /* __KERNEL__ */
+
+#endif /* _XTENSA_BITOPS_H */
diff --git a/include/asm-xtensa/bootparam.h b/include/asm-xtensa/bootparam.h
new file mode 100644
index 00000000000..9983f2c1b7e
--- /dev/null
+++ b/include/asm-xtensa/bootparam.h
@@ -0,0 +1,61 @@
+/*
+ * include/asm-xtensa/bootparam.h
+ *
+ * Definition of the Linux/Xtensa boot parameter structure
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ *
+ * (Concept borrowed from the 68K port)
+ */
+
+#ifndef _XTENSA_BOOTPARAM_H
+#define _XTENSA_BOOTPARAM_H
+
+#define BP_VERSION 0x0001
+
+#define BP_TAG_COMMAND_LINE 0x1001 /* command line (0-terminated string)*/
+#define BP_TAG_INITRD 0x1002 /* ramdisk addr and size (bp_meminfo) */
+#define BP_TAG_MEMORY 0x1003 /* memory addr and size (bp_meminfo) */
+#define BP_TAG_SERIAL_BAUSRATE 0x1004 /* baud rate of current console. */
+#define BP_TAG_SERIAL_PORT 0x1005 /* serial device of current console */
+
+#define BP_TAG_FIRST 0x7B0B /* first tag with a version number */
+#define BP_TAG_LAST 0x7E0B /* last tag */
+
+#ifndef __ASSEMBLY__
+
+/* All records are aligned to 4 bytes */
+
+typedef struct bp_tag {
+ unsigned short id; /* tag id */
+ unsigned short size; /* size of this record excluding the structure*/
+ unsigned long data[0]; /* data */
+} bp_tag_t;
+
+typedef struct meminfo {
+ unsigned long type;
+ unsigned long start;
+ unsigned long end;
+} meminfo_t;
+
+#define SYSMEM_BANKS_MAX 5
+
+#define MEMORY_TYPE_CONVENTIONAL 0x1000
+#define MEMORY_TYPE_NONE 0x2000
+
+typedef struct sysmem_info {
+ int nr_banks;
+ meminfo_t bank[SYSMEM_BANKS_MAX];
+} sysmem_info_t;
+
+extern sysmem_info_t sysmem;
+
+#endif
+#endif
+
+
+
diff --git a/include/asm-xtensa/bug.h b/include/asm-xtensa/bug.h
new file mode 100644
index 00000000000..56703659b20
--- /dev/null
+++ b/include/asm-xtensa/bug.h
@@ -0,0 +1,41 @@
+/*
+ * include/asm-xtensa/bug.h
+ *
+ * Macros to cause a 'bug' message.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_BUG_H
+#define _XTENSA_BUG_H
+
+#include <linux/stringify.h>
+
+#define ILL __asm__ __volatile__ (".byte 0,0,0\n")
+
+#ifdef CONFIG_KALLSYMS
+# define BUG() do { \
+ printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
+ ILL; \
+} while (0)
+#else
+# define BUG() do { \
+ printk("kernel BUG!\n"); \
+ ILL; \
+} while (0)
+#endif
+
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+#define PAGE_BUG(page) do { BUG(); } while (0)
+#define WARN_ON(condition) do { \
+ if (unlikely((condition)!=0)) { \
+ printk ("Warning in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+ dump_stack(); \
+ } \
+} while (0)
+
+#endif /* _XTENSA_BUG_H */
diff --git a/include/asm-xtensa/bugs.h b/include/asm-xtensa/bugs.h
new file mode 100644
index 00000000000..c4228532013
--- /dev/null
+++ b/include/asm-xtensa/bugs.h
@@ -0,0 +1,22 @@
+/*
+ * include/asm-xtensa/bugs.h
+ *
+ * This is included by init/main.c to check for architecture-dependent bugs.
+ *
+ * Xtensa processors don't have any bugs. :)
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ */
+
+#ifndef _XTENSA_BUGS_H
+#define _XTENSA_BUGS_H
+
+#include <asm/processor.h>
+
+static void __init check_bugs(void)
+{
+}
+
+#endif /* _XTENSA_BUGS_H */
diff --git a/include/asm-xtensa/byteorder.h b/include/asm-xtensa/byteorder.h
new file mode 100644
index 00000000000..0b1552569aa
--- /dev/null
+++ b/include/asm-xtensa/byteorder.h
@@ -0,0 +1,82 @@
+/*
+ * include/asm-xtensa/byteorder.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_BYTEORDER_H
+#define _XTENSA_BYTEORDER_H
+
+#include <asm/processor.h>
+#include <asm/types.h>
+
+static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
+{
+ __u32 res;
+ /* instruction sequence from Xtensa ISA release 2/2000 */
+ __asm__("ssai 8 \n\t"
+ "srli %0, %1, 16 \n\t"
+ "src %0, %0, %1 \n\t"
+ "src %0, %0, %0 \n\t"
+ "src %0, %1, %0 \n"
+ : "=&a" (res)
+ : "a" (x)
+ );
+ return res;
+}
+
+static __inline__ __const__ __u16 ___arch__swab16(__u16 x)
+{
+ /* Given that 'short' values are signed (i.e., can be negative),
+ * we cannot assume that the upper 16-bits of the register are
+ * zero. We are careful to mask values after shifting.
+ */
+
+ /* There exists an anomaly between xt-gcc and xt-xcc. xt-gcc
+ * inserts an extui instruction after putting this function inline
+ * to ensure that it uses only the least-significant 16 bits of
+ * the result. xt-xcc doesn't use an extui, but assumes the
+ * __asm__ macro follows convention that the upper 16 bits of an
+ * 'unsigned short' result are still zero. This macro doesn't
+ * follow convention; indeed, it leaves garbage in the upport 16
+ * bits of the register.
+
+ * Declaring the temporary variables 'res' and 'tmp' to be 32-bit
+ * types while the return type of the function is a 16-bit type
+ * forces both compilers to insert exactly one extui instruction
+ * (or equivalent) to mask off the upper 16 bits. */
+
+ __u32 res;
+ __u32 tmp;
+
+ __asm__("extui %1, %2, 8, 8\n\t"
+ "slli %0, %2, 8 \n\t"
+ "or %0, %0, %1 \n"
+ : "=&a" (res), "=&a" (tmp)
+ : "a" (x)
+ );
+
+ return res;
+}
+
+#define __arch__swab32(x) ___arch__swab32(x)
+#define __arch__swab16(x) ___arch__swab16(x)
+
+#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+# define __BYTEORDER_HAS_U64__
+# define __SWAB_64_THRU_32__
+#endif
+
+#ifdef __XTENSA_EL__
+# include <linux/byteorder/little_endian.h>
+#elif defined(__XTENSA_EB__)
+# include <linux/byteorder/big_endian.h>
+#else
+# error processor byte order undefined!
+#endif
+
+#endif /* __ASM_XTENSA_BYTEORDER_H */
diff --git a/include/asm-xtensa/cache.h b/include/asm-xtensa/cache.h
new file mode 100644
index 00000000000..5aae3f12407
--- /dev/null
+++ b/include/asm-xtensa/cache.h
@@ -0,0 +1,32 @@
+/*
+ * include/asm-xtensa/cacheflush.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ * 2 of the License, or (at your option) any later version.
+ *
+ * (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_CACHE_H
+#define _XTENSA_CACHE_H
+
+#include <xtensa/config/core.h>
+
+#if XCHAL_ICACHE_SIZE > 0
+# if (XCHAL_ICACHE_SIZE % (XCHAL_ICACHE_LINESIZE*XCHAL_ICACHE_WAYS*4)) != 0
+# error cache configuration outside expected/supported range!
+# endif
+#endif
+
+#if XCHAL_DCACHE_SIZE > 0
+# if (XCHAL_DCACHE_SIZE % (XCHAL_DCACHE_LINESIZE*XCHAL_DCACHE_WAYS*4)) != 0
+# error cache configuration outside expected/supported range!
+# endif
+#endif
+
+#define L1_CACHE_SHIFT XCHAL_CACHE_LINEWIDTH_MAX
+#define L1_CACHE_BYTES XCHAL_CACHE_LINESIZE_MAX
+
+#endif /* _XTENSA_CACHE_H */
diff --git a/include/asm-xtensa/cacheflush.h b/include/asm-xtensa/cacheflush.h
new file mode 100644
index 00000000000..44a36e08784
--- /dev/null
+++ b/include/asm-xtensa/cacheflush.h
@@ -0,0 +1,122 @@
+/*
+ * include/asm-xtensa/cacheflush.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_CACHEFLUSH_H
+#define _XTENSA_CACHEFLUSH_H
+
+#ifdef __KERNEL__
+
+#include <linux/mm.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+
+/*
+ * flush and invalidate data cache, invalidate instruction cache:
+ *
+ * __flush_invalidate_cache_all()
+ * __flush_invalidate_cache_range(from,sze)
+ *
+ * invalidate data or instruction cache:
+ *
+ * __invalidate_icache_all()
+ * __invalidate_icache_page(adr)
+ * __invalidate_dcache_page(adr)
+ * __invalidate_icache_range(from,size)
+ * __invalidate_dcache_range(from,size)
+ *
+ * flush data cache:
+ *
+ * __flush_dcache_page(adr)
+ *
+ * flush and invalidate data cache:
+ *
+ * __flush_invalidate_dcache_all()
+ * __flush_invalidate_dcache_page(adr)
+ * __flush_invalidate_dcache_range(from,size)
+ */
+
+extern void __flush_invalidate_cache_all(void);
+extern void __flush_invalidate_cache_range(unsigned long, unsigned long);
+extern void __flush_invalidate_dcache_all(void);
+extern void __invalidate_icache_all(void);
+
+extern void __invalidate_dcache_page(unsigned long);
+extern void __invalidate_icache_page(unsigned long);
+extern void __invalidate_icache_range(unsigned long, unsigned long);
+extern void __invalidate_dcache_range(unsigned long, unsigned long);
+
+#if XCHAL_DCACHE_IS_WRITEBACK
+extern void __flush_dcache_page(unsigned long);
+extern void __flush_invalidate_dcache_page(unsigned long);
+extern void __flush_invalidate_dcache_range(unsigned long, unsigned long);
+#else
+# define __flush_dcache_page(p) do { } while(0)
+# define __flush_invalidate_dcache_page(p) do { } while(0)
+# define __flush_invalidate_dcache_range(p,s) do { } while(0)
+#endif
+
+/*
+ * We have physically tagged caches - nothing to do here -
+ * unless we have cache aliasing.
+ *
+ * Pages can get remapped. Because this might change the 'color' of that page,
+ * we have to flush the cache before the PTE is changed.
+ * (see also Documentation/cachetlb.txt)
+ */
+
+#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
+
+#define flush_cache_all() __flush_invalidate_cache_all();
+#define flush_cache_mm(mm) __flush_invalidate_cache_all();
+
+#define flush_cache_vmap(start,end) __flush_invalidate_cache_all();
+#define flush_cache_vunmap(start,end) __flush_invalidate_cache_all();
+
+extern void flush_dcache_page(struct page*);
+
+extern void flush_cache_range(struct vm_area_struct*, ulong, ulong);
+extern void flush_cache_page(struct vm_area_struct*, unsigned long, unsigned long);
+
+#else
+
+#define flush_cache_all() do { } while (0)
+#define flush_cache_mm(mm) do { } while (0)
+
+#define flush_cache_vmap(start,end) do { } while (0)
+#define flush_cache_vunmap(start,end) do { } while (0)
+
+#define flush_dcache_page(page) do { } while (0)
+
+#define flush_cache_page(vma,addr,pfn) do { } while (0)
+#define flush_cache_range(vma,start,end) do { } while (0)
+
+#endif
+
+#define flush_icache_range(start,end) \
+ __invalidate_icache_range(start,(end)-(start))
+
+/* This is not required, see Documentation/cachetlb.txt */
+
+#define flush_icache_page(vma,page) do { } while(0)
+
+#define flush_dcache_mmap_lock(mapping) do { } while (0)
+#define flush_dcache_mmap_unlock(mapping) do { } while (0)
+
+
+#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
+ memcpy(dst, src, len)
+
+#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
+ memcpy(dst, src, len)
+
+#endif /* __KERNEL__ */
+
+#endif /* _XTENSA_CACHEFLUSH_H */
+
diff --git a/include/asm-xtensa/checksum.h b/include/asm-xtensa/checksum.h
new file mode 100644
index 00000000000..1a00fad1992
--- /dev/null
+++ b/include/asm-xtensa/checksum.h
@@ -0,0 +1,264 @@
+/*
+ * include/asm-xtensa/checksum.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_CHECKSUM_H
+#define _XTENSA_CHECKSUM_H
+
+#include <linux/config.h>
+#include <linux/in6.h>
+#include <xtensa/config/core.h>
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+asmlinkage unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
+
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums, and handles user-space pointer exceptions correctly, when needed.
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+
+asmlinkage unsigned int csum_partial_copy_generic( const char *src, char *dst, int len, int sum,
+ int *src_err_ptr, int *dst_err_ptr);
+
+/*
+ * Note: when you get a NULL pointer exception here this means someone
+ * passed in an incorrect kernel address to one of these functions.
+ *
+ * If you use these functions directly please don't forget the
+ * verify_area().
+ */
+extern __inline__
+unsigned int csum_partial_copy_nocheck ( const char *src, char *dst,
+ int len, int sum)
+{
+ return csum_partial_copy_generic ( src, dst, len, sum, NULL, NULL);
+}
+
+extern __inline__
+unsigned int csum_partial_copy_from_user ( const char *src, char *dst,
+ int len, int sum, int *err_ptr)
+{
+ return csum_partial_copy_generic ( src, dst, len, sum, err_ptr, NULL);
+}
+
+/*
+ * These are the old (and unsafe) way of doing checksums, a warning message will be
+ * printed if they are used and an exeption occurs.
+ *
+ * these functions should go away after some time.
+ */
+
+#define csum_partial_copy_fromuser csum_partial_copy
+unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum);
+
+/*
+ * Fold a partial checksum
+ */
+
+static __inline__ unsigned int csum_fold(unsigned int sum)
+{
+ unsigned int __dummy;
+ __asm__("extui %1, %0, 16, 16\n\t"
+ "extui %0 ,%0, 0, 16\n\t"
+ "add %0, %0, %1\n\t"
+ "slli %1, %0, 16\n\t"
+ "add %0, %0, %1\n\t"
+ "extui %0, %0, 16, 16\n\t"
+ "neg %0, %0\n\t"
+ "addi %0, %0, -1\n\t"
+ "extui %0, %0, 0, 16\n\t"
+ : "=r" (sum), "=&r" (__dummy)
+ : "0" (sum));
+ return sum;
+}
+
+/*
+ * This is a version of ip_compute_csum() optimized for IP headers,
+ * which always checksum on 4 octet boundaries.
+ */
+static __inline__ unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl)
+{
+ unsigned int sum, tmp, endaddr;
+
+ __asm__ __volatile__(
+ "sub %0, %0, %0\n\t"
+#if XCHAL_HAVE_LOOPS
+ "loopgtz %2, 2f\n\t"
+#else
+ "beqz %2, 2f\n\t"
+ "slli %4, %2, 2\n\t"
+ "add %4, %4, %1\n\t"
+ "0:\t"
+#endif
+ "l32i %3, %1, 0\n\t"
+ "add %0, %0, %3\n\t"
+ "bgeu %0, %3, 1f\n\t"
+ "addi %0, %0, 1\n\t"
+ "1:\t"
+ "addi %1, %1, 4\n\t"
+#if !XCHAL_HAVE_LOOPS
+ "blt %1, %4, 0b\n\t"
+#endif
+ "2:\t"
+ /* Since the input registers which are loaded with iph and ihl
+ are modified, we must also specify them as outputs, or gcc
+ will assume they contain their original values. */
+ : "=r" (sum), "=r" (iph), "=r" (ihl), "=&r" (tmp), "=&r" (endaddr)
+ : "1" (iph), "2" (ihl));
+
+ return csum_fold(sum);
+}
+
+static __inline__ unsigned long csum_tcpudp_nofold(unsigned long saddr,
+ unsigned long daddr,
+ unsigned short len,
+ unsigned short proto,
+ unsigned int sum)
+{
+
+#ifdef __XTENSA_EL__
+ unsigned long len_proto = (ntohs(len)<<16)+proto*256;
+#elif defined(__XTENSA_EB__)
+ unsigned long len_proto = (proto<<16)+len;
+#else
+# error processor byte order undefined!
+#endif
+ __asm__("add %0, %0, %1\n\t"
+ "bgeu %0, %1, 1f\n\t"
+ "addi %0, %0, 1\n\t"
+ "1:\t"
+ "add %0, %0, %2\n\t"
+ "bgeu %0, %2, 1f\n\t"
+ "addi %0, %0, 1\n\t"
+ "1:\t"
+ "add %0, %0, %3\n\t"
+ "bgeu %0, %3, 1f\n\t"
+ "addi %0, %0, 1\n\t"
+ "1:\t"
+ : "=r" (sum), "=r" (len_proto)
+ : "r" (daddr), "r" (saddr), "1" (len_proto), "0" (sum));
+ return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static __inline__ unsigned short int csum_tcpudp_magic(unsigned long saddr,
+ unsigned long daddr,
+ unsigned short len,
+ unsigned short proto,
+ unsigned int sum)
+{
+ return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+
+static __inline__ unsigned short ip_compute_csum(unsigned char * buff, int len)
+{
+ return csum_fold (csum_partial(buff, len, 0));
+}
+
+#define _HAVE_ARCH_IPV6_CSUM
+static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
+ struct in6_addr *daddr,
+ __u32 len,
+ unsigned short proto,
+ unsigned int sum)
+{
+ unsigned int __dummy;
+ __asm__("l32i %1, %2, 0\n\t"
+ "add %0, %0, %1\n\t"
+ "bgeu %0, %1, 1f\n\t"
+ "addi %0, %0, 1\n\t"
+ "1:\t"
+ "l32i %1, %2, 4\n\t"
+ "add %0, %0, %1\n\t"
+ "bgeu %0, %1, 1f\n\t"
+ "addi %0, %0, 1\n\t"
+ "1:\t"
+ "l32i %1, %2, 8\n\t"
+ "add %0, %0, %1\n\t"
+ "bgeu %0, %1, 1f\n\t"
+ "addi %0, %0, 1\n\t"
+ "1:\t"
+ "l32i %1, %2, 12\n\t"
+ "add %0, %0, %1\n\t"
+ "bgeu %0, %1, 1f\n\t"
+ "addi %0, %0, 1\n\t"
+ "1:\t"
+ "l32i %1, %3, 0\n\t"
+ "add %0, %0, %1\n\t"
+ "bgeu %0, %1, 1f\n\t"
+ "addi %0, %0, 1\n\t"
+ "1:\t"
+ "l32i %1, %3, 4\n\t"
+ "add %0, %0, %1\n\t"
+ "bgeu %0, %1, 1f\n\t"
+ "addi %0, %0, 1\n\t"
+ "1:\t"
+ "l32i %1, %3, 8\n\t"
+ "add %0, %0, %1\n\t"
+ "bgeu %0, %1, 1f\n\t"
+ "addi %0, %0, 1\n\t"
+ "1:\t"
+ "l32i %1, %3, 12\n\t"
+ "add %0, %0, %1\n\t"
+ "bgeu %0, %1, 1f\n\t"
+ "addi %0, %0, 1\n\t"
+ "1:\t"
+ "add %0, %0, %4\n\t"
+ "bgeu %0, %4, 1f\n\t"
+ "addi %0, %0, 1\n\t"
+ "1:\t"
+ "add %0, %0, %5\n\t"
+ "bgeu %0, %5, 1f\n\t"
+ "addi %0, %0, 1\n\t"
+ "1:\t"
+ : "=r" (sum), "=&r" (__dummy)
+ : "r" (saddr), "r" (daddr),
+ "r" (htonl(len)), "r" (htonl(proto)), "0" (sum));
+
+ return csum_fold(sum);
+}
+
+/*
+ * Copy and checksum to user
+ */
+#define HAVE_CSUM_COPY_USER
+static __inline__ unsigned int csum_and_copy_to_user (const char *src, char *dst,
+ int len, int sum, int *err_ptr)
+{
+ if (access_ok(VERIFY_WRITE, dst, len))
+ return csum_partial_copy_generic(src, dst, len, sum, NULL, err_ptr);
+
+ if (len)
+ *err_ptr = -EFAULT;
+
+ return -1; /* invalid checksum */
+}
+#endif
diff --git a/include/asm-xtensa/coprocessor.h b/include/asm-xtensa/coprocessor.h
new file mode 100644
index 00000000000..a91b96dc0ef
--- /dev/null
+++ b/include/asm-xtensa/coprocessor.h
@@ -0,0 +1,70 @@
+/*
+ * include/asm-xtensa/cpextra.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_COPROCESSOR_H
+#define _XTENSA_COPROCESSOR_H
+
+#include <xtensa/config/core.h>
+
+#define XTOFS(last_start,last_size,align) \
+ ((last_start+last_size+align-1) & -align)
+
+#define XTENSA_CP_EXTRA_OFFSET 0
+#define XTENSA_CP_EXTRA_ALIGN XCHAL_EXTRA_SA_ALIGN
+
+#define XTENSA_CPE_CP0_OFFSET \
+ XTOFS(XTENSA_CP_EXTRA_OFFSET, XCHAL_EXTRA_SA_SIZE, XCHAL_CP0_SA_ALIGN)
+#define XTENSA_CPE_CP1_OFFSET \
+ XTOFS(XTENSA_CPE_CP0_OFFSET, XCHAL_CP0_SA_SIZE, XCHAL_CP1_SA_ALIGN)
+#define XTENSA_CPE_CP2_OFFSET \
+ XTOFS(XTENSA_CPE_CP1_OFFSET, XCHAL_CP1_SA_SIZE, XCHAL_CP2_SA_ALIGN)
+#define XTENSA_CPE_CP3_OFFSET \
+ XTOFS(XTENSA_CPE_CP2_OFFSET, XCHAL_CP2_SA_SIZE, XCHAL_CP3_SA_ALIGN)
+#define XTENSA_CPE_CP4_OFFSET \
+ XTOFS(XTENSA_CPE_CP3_OFFSET, XCHAL_CP3_SA_SIZE, XCHAL_CP4_SA_ALIGN)
+#define XTENSA_CPE_CP5_OFFSET \
+ XTOFS(XTENSA_CPE_CP4_OFFSET, XCHAL_CP4_SA_SIZE, XCHAL_CP5_SA_ALIGN)
+#define XTENSA_CPE_CP6_OFFSET \
+ XTOFS(XTENSA_CPE_CP5_OFFSET, XCHAL_CP5_SA_SIZE, XCHAL_CP6_SA_ALIGN)
+#define XTENSA_CPE_CP7_OFFSET \
+ XTOFS(XTENSA_CPE_CP6_OFFSET, XCHAL_CP6_SA_SIZE, XCHAL_CP7_SA_ALIGN)
+#define XTENSA_CP_EXTRA_SIZE \
+ XTOFS(XTENSA_CPE_CP7_OFFSET, XCHAL_CP7_SA_SIZE, 16)
+
+#if XCHAL_CP_NUM > 0
+# ifndef __ASSEMBLY__
+/*
+ * Tasks that own contents of (last user) each coprocessor.
+ * Entries are 0 for not-owned or non-existent coprocessors.
+ * Note: The size of this structure is fixed to 8 bytes in entry.S
+ */
+typedef struct {
+ struct task_struct *owner; /* owner */
+ int offset; /* offset in cpextra space. */
+} coprocessor_info_t;
+# else
+# define COPROCESSOR_INFO_OWNER 0
+# define COPROCESSOR_INFO_OFFSET 4
+# define COPROCESSOR_INFO_SIZE 8
+# endif
+#endif
+
+
+#ifndef __ASSEMBLY__
+# if XCHAL_CP_NUM > 0
+struct task_struct;
+extern void release_coprocessors (struct task_struct*);
+extern void save_coprocessor_registers(void*, int);
+# else
+# define release_coprocessors(task)
+# endif
+#endif
+
+#endif /* _XTENSA_COPROCESSOR_H */
diff --git a/include/asm-xtensa/cpumask.h b/include/asm-xtensa/cpumask.h
new file mode 100644
index 00000000000..ebeede397db
--- /dev/null
+++ b/include/asm-xtensa/cpumask.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-xtensa/cpumask.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_CPUMASK_H
+#define _XTENSA_CPUMASK_H
+
+#include <asm-generic/cpumask.h>
+
+#endif /* _XTENSA_CPUMASK_H */
diff --git a/include/asm-xtensa/cputime.h b/include/asm-xtensa/cputime.h
new file mode 100644
index 00000000000..a7fb864a50a
--- /dev/null
+++ b/include/asm-xtensa/cputime.h
@@ -0,0 +1,6 @@
+#ifndef _XTENSA_CPUTIME_H
+#define _XTENSA_CPUTIME_H
+
+#include <asm-generic/cputime.h>
+
+#endif /* _XTENSA_CPUTIME_H */
diff --git a/include/asm-xtensa/current.h b/include/asm-xtensa/current.h
new file mode 100644
index 00000000000..8d1eb5d7864
--- /dev/null
+++ b/include/asm-xtensa/current.h
@@ -0,0 +1,38 @@
+/*
+ * include/asm-xtensa/current.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_CURRENT_H
+#define _XTENSA_CURRENT_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/thread_info.h>
+
+struct task_struct;
+
+static inline struct task_struct *get_current(void)
+{
+ return current_thread_info()->task;
+}
+
+#define current get_current()
+
+#else
+
+#define CURRENT_SHIFT 13
+
+#define GET_CURRENT(reg,sp) \
+ GET_THREAD_INFO(reg,sp); \
+ l32i reg, reg, TI_TASK \
+
+#endif
+
+
+#endif /* XTENSA_CURRENT_H */
diff --git a/include/asm-xtensa/delay.h b/include/asm-xtensa/delay.h
new file mode 100644
index 00000000000..6359c55e77a
--- /dev/null
+++ b/include/asm-xtensa/delay.h
@@ -0,0 +1,50 @@
+/*
+ * include/asm-xtensa/delay.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ *
+ */
+
+#ifndef _XTENSA_DELAY_H
+#define _XTENSA_DELAY_H
+
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/param.h>
+
+extern unsigned long loops_per_jiffy;
+
+extern __inline__ void __delay(unsigned long loops)
+{
+ /* 2 cycles per loop. */
+ __asm__ __volatile__ ("1: addi %0, %0, -2; bgeui %0, 1, 1b"
+ : "=r" (loops) : "0" (loops));
+}
+
+static __inline__ u32 xtensa_get_ccount(void)
+{
+ u32 ccount;
+ asm volatile ("rsr %0, 234; # CCOUNT\n" : "=r" (ccount));
+ return ccount;
+}
+
+/* For SMP/NUMA systems, change boot_cpu_data to something like
+ * local_cpu_data->... where local_cpu_data points to the current
+ * cpu. */
+
+static __inline__ void udelay (unsigned long usecs)
+{
+ unsigned long start = xtensa_get_ccount();
+ unsigned long cycles = usecs * (loops_per_jiffy / (1000000UL / HZ));
+
+ /* Note: all variables are unsigned (can wrap around)! */
+ while (((unsigned long)xtensa_get_ccount()) - start < cycles)
+ ;
+}
+
+#endif
+
diff --git a/include/asm-xtensa/div64.h b/include/asm-xtensa/div64.h
new file mode 100644
index 00000000000..c4a10577638
--- /dev/null
+++ b/include/asm-xtensa/div64.h
@@ -0,0 +1,19 @@
+/*
+ * include/asm-xtensa/div64.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_DIV64_H
+#define _XTENSA_DIV64_H
+
+#define do_div(n,base) ({ \
+ int __res = n % ((unsigned int) base); \
+ n /= (unsigned int) base; \
+ __res; })
+
+#endif
diff --git a/include/asm-xtensa/dma-mapping.h b/include/asm-xtensa/dma-mapping.h
new file mode 100644
index 00000000000..e86a206f120
--- /dev/null
+++ b/include/asm-xtensa/dma-mapping.h
@@ -0,0 +1,182 @@
+/*
+ * include/asm-xtensa/dma_mapping.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_DMA_MAPPING_H
+#define _XTENSA_DMA_MAPPING_H
+
+#include <asm/scatterlist.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+#include <linux/mm.h>
+
+/*
+ * DMA-consistent mapping functions.
+ */
+
+extern void *consistent_alloc(int, size_t, dma_addr_t, unsigned long);
+extern void consistent_free(void*, size_t, dma_addr_t);
+extern void consistent_sync(void*, size_t, int);
+
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
+#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, int flag);
+
+void dma_free_coherent(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_handle);
+
+static inline dma_addr_t
+dma_map_single(struct device *dev, void *ptr, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+ consistent_sync(ptr, size, direction);
+ return virt_to_phys(ptr);
+}
+
+static inline void
+dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+}
+
+static inline int
+dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction direction)
+{
+ int i;
+
+ BUG_ON(direction == DMA_NONE);
+
+ for (i = 0; i < nents; i++, sg++ ) {
+ BUG_ON(!sg->page);
+
+ sg->dma_address = page_to_phys(sg->page) + sg->offset;
+ consistent_sync(page_address(sg->page) + sg->offset,
+ sg->length, direction);
+ }
+
+ return nents;
+}
+
+static inline dma_addr_t
+dma_map_page(struct device *dev, struct page *page, unsigned long offset,
+ size_t size, enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+ return (dma_addr_t)(page_to_pfn(page)) * PAGE_SIZE + offset;
+}
+
+static inline void
+dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+}
+
+
+static inline void
+dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+ enum dma_data_direction direction)
+{
+ BUG_ON(direction == DMA_NONE);
+}
+
+static inline void
+dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction direction)
+{
+ consistent_sync((void *)bus_to_virt(dma_handle), size, direction);
+}
+
+static inline void
+dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction direction)
+{
+ consistent_sync((void *)bus_to_virt(dma_handle), size, direction);
+}
+
+static inline void
+dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
+ unsigned long offset, size_t size,
+ enum dma_data_direction direction)
+{
+
+ consistent_sync((void *)bus_to_virt(dma_handle)+offset,size,direction);
+}
+
+static inline void
+dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
+ unsigned long offset, size_t size,
+ enum dma_data_direction direction)
+{
+
+ consistent_sync((void *)bus_to_virt(dma_handle)+offset,size,direction);
+}
+static inline void
+dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
+ enum dma_data_direction dir)
+{
+ int i;
+ for (i = 0; i < nelems; i++, sg++)
+ consistent_sync(page_address(sg->page) + sg->offset,
+ sg->length, dir);
+}
+
+static inline void
+dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
+ enum dma_data_direction dir)
+{
+ int i;
+ for (i = 0; i < nelems; i++, sg++)
+ consistent_sync(page_address(sg->page) + sg->offset,
+ sg->length, dir);
+}
+static inline int
+dma_mapping_error(dma_addr_t dma_addr)
+{
+ return 0;
+}
+
+static inline int
+dma_supported(struct device *dev, u64 mask)
+{
+ return 1;
+}
+
+static inline int
+dma_set_mask(struct device *dev, u64 mask)
+{
+ if(!dev->dma_mask || !dma_supported(dev, mask))
+ return -EIO;
+
+ *dev->dma_mask = mask;
+
+ return 0;
+}
+
+static inline int
+dma_get_cache_alignment(void)
+{
+ return L1_CACHE_BYTES;
+}
+
+#define dma_is_consistent(d) (1)
+
+static inline void
+dma_cache_sync(void *vaddr, size_t size,
+ enum dma_data_direction direction)
+{
+ consistent_sync(vaddr, size, direction);
+}
+
+#endif /* _XTENSA_DMA_MAPPING_H */
diff --git a/include/asm-xtensa/dma.h b/include/asm-xtensa/dma.h
new file mode 100644
index 00000000000..1c22b023458
--- /dev/null
+++ b/include/asm-xtensa/dma.h
@@ -0,0 +1,61 @@
+/*
+ * include/asm-xtensa/dma.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_DMA_H
+#define _XTENSA_DMA_H
+
+#include <linux/config.h>
+#include <asm/io.h> /* need byte IO */
+#include <xtensa/config/core.h>
+
+/*
+ * This is only to be defined if we have PC-like DMA.
+ * By default this is not true on an Xtensa processor,
+ * however on boards with a PCI bus, such functionality
+ * might be emulated externally.
+ *
+ * NOTE: there still exists driver code that assumes
+ * this is defined, eg. drivers/sound/soundcard.c (as of 2.4).
+ */
+#define MAX_DMA_CHANNELS 8
+
+/*
+ * The maximum virtual address to which DMA transfers
+ * can be performed on this platform.
+ *
+ * NOTE: This is board (platform) specific, not processor-specific!
+ *
+ * NOTE: This assumes DMA transfers can only be performed on
+ * the section of physical memory contiguously mapped in virtual
+ * space for the kernel. For the Xtensa architecture, this
+ * means the maximum possible size of this DMA area is
+ * the size of the statically mapped kernel segment
+ * (XCHAL_KSEG_{CACHED,BYPASS}_SIZE), ie. 128 MB.
+ *
+ * NOTE: When the entire KSEG area is DMA capable, we substract
+ * one from the max address so that the virt_to_phys() macro
+ * works correctly on the address (otherwise the address
+ * enters another area, and virt_to_phys() may not return
+ * the value desired).
+ */
+#define MAX_DMA_ADDRESS (PAGE_OFFSET + XCHAL_KSEG_CACHED_SIZE - 1)
+
+/* Reserve and release a DMA channel */
+extern int request_dma(unsigned int dmanr, const char * device_id);
+extern void free_dma(unsigned int dmanr);
+
+#ifdef CONFIG_PCI
+extern int isa_dma_bridge_buggy;
+#else
+#define isa_dma_bridge_buggy (0)
+#endif
+
+
+#endif
diff --git a/include/asm-xtensa/elf.h b/include/asm-xtensa/elf.h
new file mode 100644
index 00000000000..64f1f53874f
--- /dev/null
+++ b/include/asm-xtensa/elf.h
@@ -0,0 +1,222 @@
+/*
+ * include/asm-xtensa/elf.h
+ *
+ * ELF register definitions
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_ELF_H
+#define _XTENSA_ELF_H
+
+#include <asm/ptrace.h>
+#include <asm/coprocessor.h>
+#include <xtensa/config/core.h>
+
+/* Xtensa processor ELF architecture-magic number */
+
+#define EM_XTENSA 94
+#define EM_XTENSA_OLD 0xABC7
+
+/* ELF register definitions. This is needed for core dump support. */
+
+/*
+ * elf_gregset_t contains the application-level state in the following order:
+ * Processor info: config_version, cpuxy
+ * Processor state: pc, ps, exccause, excvaddr, wb, ws,
+ * lbeg, lend, lcount, sar
+ * GP regs: ar0 - arXX
+ */
+
+typedef unsigned long elf_greg_t;
+
+typedef struct {
+ elf_greg_t xchal_config_id0;
+ elf_greg_t xchal_config_id1;
+ elf_greg_t cpux;
+ elf_greg_t cpuy;
+ elf_greg_t pc;
+ elf_greg_t ps;
+ elf_greg_t exccause;
+ elf_greg_t excvaddr;
+ elf_greg_t windowbase;
+ elf_greg_t windowstart;
+ elf_greg_t lbeg;
+ elf_greg_t lend;
+ elf_greg_t lcount;
+ elf_greg_t sar;
+ elf_greg_t syscall;
+ elf_greg_t ar[XCHAL_NUM_AREGS];
+} xtensa_gregset_t;
+
+#define ELF_NGREG (sizeof(xtensa_gregset_t) / sizeof(elf_greg_t))
+
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+/*
+ * Compute the size of the coprocessor and extra state layout (register info)
+ * table (in bytes).
+ * This is actually the maximum size of the table, as opposed to the size,
+ * which is available from the _xtensa_reginfo_table_size global variable.
+ *
+ * (See also arch/xtensa/kernel/coprocessor.S)
+ *
+ */
+
+#ifndef XCHAL_EXTRA_SA_CONTENTS_LIBDB_NUM
+# define XTENSA_CPE_LTABLE_SIZE 0
+#else
+# define XTENSA_CPE_SEGMENT(num) (num ? (1+num) : 0)
+# define XTENSA_CPE_LTABLE_ENTRIES \
+ ( XTENSA_CPE_SEGMENT(XCHAL_EXTRA_SA_CONTENTS_LIBDB_NUM) \
+ + XTENSA_CPE_SEGMENT(XCHAL_CP0_SA_CONTENTS_LIBDB_NUM) \
+ + XTENSA_CPE_SEGMENT(XCHAL_CP1_SA_CONTENTS_LIBDB_NUM) \
+ + XTENSA_CPE_SEGMENT(XCHAL_CP2_SA_CONTENTS_LIBDB_NUM) \
+ + XTENSA_CPE_SEGMENT(XCHAL_CP3_SA_CONTENTS_LIBDB_NUM) \
+ + XTENSA_CPE_SEGMENT(XCHAL_CP4_SA_CONTENTS_LIBDB_NUM) \
+ + XTENSA_CPE_SEGMENT(XCHAL_CP5_SA_CONTENTS_LIBDB_NUM) \
+ + XTENSA_CPE_SEGMENT(XCHAL_CP6_SA_CONTENTS_LIBDB_NUM) \
+ + XTENSA_CPE_SEGMENT(XCHAL_CP7_SA_CONTENTS_LIBDB_NUM) \
+ + 1 /* final entry */ \
+ )
+# define XTENSA_CPE_LTABLE_SIZE (XTENSA_CPE_LTABLE_ENTRIES * 8)
+#endif
+
+
+/*
+ * Instantiations of the elf_fpregset_t type contain, in most
+ * architectures, the floating point (FPU) register set.
+ * For Xtensa, this type is extended to contain all custom state,
+ * ie. coprocessor and "extra" (non-coprocessor) state (including,
+ * for example, TIE-defined states and register files; as well
+ * as other optional processor state).
+ * This includes FPU state if a floating-point coprocessor happens
+ * to have been configured within the Xtensa processor.
+ *
+ * TOTAL_FPREGS_SIZE is the required size (without rounding)
+ * of elf_fpregset_t. It provides space for the following:
+ *
+ * a) 32-bit mask of active coprocessors for this task (similar
+ * to CPENABLE in single-threaded Xtensa processor systems)
+ *
+ * b) table describing the layout of custom states (ie. of
+ * individual registers, etc) within the save areas
+ *
+ * c) save areas for each coprocessor and for non-coprocessor
+ * ("extra") state
+ *
+ * Note that save areas may require up to 16-byte alignment when
+ * accessed by save/restore sequences. We do not need to ensure
+ * such alignment in an elf_fpregset_t structure because custom
+ * state is not directly loaded/stored into it; rather, save area
+ * contents are copied to elf_fpregset_t from the active save areas
+ * (see 'struct task_struct' definition in processor.h for that)
+ * using memcpy(). But we do allow space for such alignment,
+ * to allow optimizations of layout and copying.
+ */
+
+#define TOTAL_FPREGS_SIZE \
+ (4 + XTENSA_CPE_LTABLE_SIZE + XTENSA_CP_EXTRA_SIZE)
+#define ELF_NFPREG \
+ ((TOTAL_FPREGS_SIZE + sizeof(elf_fpreg_t) - 1) / sizeof(elf_fpreg_t))
+
+typedef unsigned int elf_fpreg_t;
+typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
+
+#define ELF_CORE_COPY_REGS(_eregs, _pregs) \
+ xtensa_elf_core_copy_regs (&_eregs, _pregs);
+
+extern void xtensa_elf_core_copy_regs (xtensa_gregset_t *, struct pt_regs *);
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+
+#define elf_check_arch(x) ( ( (x)->e_machine == EM_XTENSA ) || \
+ ( (x)->e_machine == EM_XTENSA_OLD ) )
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+
+#ifdef __XTENSA_EL__
+# define ELF_DATA ELFDATA2LSB
+#elif defined(__XTENSA_EB__)
+# define ELF_DATA ELFDATA2MSB
+#else
+# error processor byte order undefined!
+#endif
+
+#define ELF_CLASS ELFCLASS32
+#define ELF_ARCH EM_XTENSA
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE PAGE_SIZE
+
+/*
+ * This is the location that an ET_DYN program is loaded if exec'ed. Typical
+ * use of this is to invoke "./ld.so someprog" to test out a new version of
+ * the loader. We need to make sure that it is out of the way of the program
+ * that it will "exec", and that there is sufficient room for the brk.
+ */
+
+#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
+
+/*
+ * This yields a mask that user programs can use to figure out what
+ * instruction set this CPU supports. This could be done in user space,
+ * but it's not easy, and we've already done it here.
+ */
+
+#define ELF_HWCAP (0)
+
+/*
+ * This yields a string that ld.so will use to load implementation
+ * specific libraries for optimization. This is more specific in
+ * intent than poking at uname or /proc/cpuinfo.
+ * For the moment, we have only optimizations for the Intel generations,
+ * but that could change...
+ */
+
+#define ELF_PLATFORM (NULL)
+
+/*
+ * The Xtensa processor ABI says that when the program starts, a2
+ * contains a pointer to a function which might be registered using
+ * `atexit'. This provides a mean for the dynamic linker to call
+ * DT_FINI functions for shared libraries that have been loaded before
+ * the code runs.
+ *
+ * A value of 0 tells we have no such handler.
+ *
+ * We might as well make sure everything else is cleared too (except
+ * for the stack pointer in a1), just to make things more
+ * deterministic. Also, clearing a0 terminates debugger backtraces.
+ */
+
+#define ELF_PLAT_INIT(_r, load_addr) \
+ do { _r->areg[0]=0; /*_r->areg[1]=0;*/ _r->areg[2]=0; _r->areg[3]=0; \
+ _r->areg[4]=0; _r->areg[5]=0; _r->areg[6]=0; _r->areg[7]=0; \
+ _r->areg[8]=0; _r->areg[9]=0; _r->areg[10]=0; _r->areg[11]=0; \
+ _r->areg[12]=0; _r->areg[13]=0; _r->areg[14]=0; _r->areg[15]=0; \
+ } while (0)
+
+#ifdef __KERNEL__
+
+#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT)
+
+extern void do_copy_regs (xtensa_gregset_t*, struct pt_regs*,
+ struct task_struct*);
+extern void do_restore_regs (xtensa_gregset_t*, struct pt_regs*,
+ struct task_struct*);
+extern void do_save_fpregs (elf_fpregset_t*, struct pt_regs*,
+ struct task_struct*);
+extern int do_restore_fpregs (elf_fpregset_t*, struct pt_regs*,
+ struct task_struct*);
+
+#endif /* __KERNEL__ */
+#endif /* _XTENSA_ELF_H */
diff --git a/include/asm-xtensa/errno.h b/include/asm-xtensa/errno.h
new file mode 100644
index 00000000000..ced5194d275
--- /dev/null
+++ b/include/asm-xtensa/errno.h
@@ -0,0 +1,142 @@
+/*
+ * include/asm-xtensa/errno.h
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ *
+ * Copyright (C) 2002 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_ERRNO_H
+#define _XTENSA_ERRNO_H
+
+#define EPERM 1 /* Operation not permitted */
+#define ENOENT 2 /* No such file or directory */
+#define ESRCH 3 /* No such process */
+#define EINTR 4 /* Interrupted system call */
+#define EIO 5 /* I/O error */
+#define ENXIO 6 /* No such device or address */
+#define E2BIG 7 /* Arg list too long */
+#define ENOEXEC 8 /* Exec format error */
+#define EBADF 9 /* Bad file number */
+#define ECHILD 10 /* No child processes */
+#define EAGAIN 11 /* Try again */
+#define ENOMEM 12 /* Out of memory */
+#define EACCES 13 /* Permission denied */
+#define EFAULT 14 /* Bad address */
+#define ENOTBLK 15 /* Block device required */
+#define EBUSY 16 /* Device or resource busy */
+#define EEXIST 17 /* File exists */
+#define EXDEV 18 /* Cross-device link */
+#define ENODEV 19 /* No such device */
+#define ENOTDIR 20 /* Not a directory */
+#define EISDIR 21 /* Is a directory */
+#define EINVAL 22 /* Invalid argument */
+#define ENFILE 23 /* File table overflow */
+#define EMFILE 24 /* Too many open files */
+#define ENOTTY 25 /* Not a typewriter */
+#define ETXTBSY 26 /* Text file busy */
+#define EFBIG 27 /* File too large */
+#define ENOSPC 28 /* No space left on device */
+#define ESPIPE 29 /* Illegal seek */
+#define EROFS 30 /* Read-only file system */
+#define EMLINK 31 /* Too many links */
+#define EPIPE 32 /* Broken pipe */
+#define EDOM 33 /* Math argument out of domain of func */
+#define ERANGE 34 /* Math result not representable */
+#define EDEADLK 35 /* Resource deadlock would occur */
+#define ENAMETOOLONG 36 /* File name too long */
+#define ENOLCK 37 /* No record locks available */
+#define ENOSYS 38 /* Function not implemented */
+#define ENOTEMPTY 39 /* Directory not empty */
+#define ELOOP 40 /* Too many symbolic links encountered */
+#define EWOULDBLOCK EAGAIN /* Operation would block */
+#define ENOMSG 42 /* No message of desired type */
+#define EIDRM 43 /* Identifier removed */
+#define ECHRNG 44 /* Channel number out of range */
+#define EL2NSYNC 45 /* Level 2 not synchronized */
+#define EL3HLT 46 /* Level 3 halted */
+#define EL3RST 47 /* Level 3 reset */
+#define ELNRNG 48 /* Link number out of range */
+#define EUNATCH 49 /* Protocol driver not attached */
+#define ENOCSI 50 /* No CSI structure available */
+#define EL2HLT 51 /* Level 2 halted */
+#define EBADE 52 /* Invalid exchange */
+#define EBADR 53 /* Invalid request descriptor */
+#define EXFULL 54 /* Exchange full */
+#define ENOANO 55 /* No anode */
+#define EBADRQC 56 /* Invalid request code */
+#define EBADSLT 57 /* Invalid slot */
+
+#define EDEADLOCK EDEADLK
+
+#define EBFONT 59 /* Bad font file format */
+#define ENOSTR 60 /* Device not a stream */
+#define ENODATA 61 /* No data available */
+#define ETIME 62 /* Timer expired */
+#define ENOSR 63 /* Out of streams resources */
+#define ENONET 64 /* Machine is not on the network */
+#define ENOPKG 65 /* Package not installed */
+#define EREMOTE 66 /* Object is remote */
+#define ENOLINK 67 /* Link has been severed */
+#define EADV 68 /* Advertise error */
+#define ESRMNT 69 /* Srmount error */
+#define ECOMM 70 /* Communication error on send */
+#define EPROTO 71 /* Protocol error */
+#define EMULTIHOP 72 /* Multihop attempted */
+#define EDOTDOT 73 /* RFS specific error */
+#define EBADMSG 74 /* Not a data message */
+#define EOVERFLOW 75 /* Value too large for defined data type */
+#define ENOTUNIQ 76 /* Name not unique on network */
+#define EBADFD 77 /* File descriptor in bad state */
+#define EREMCHG 78 /* Remote address changed */
+#define ELIBACC 79 /* Can not access a needed shared library */
+#define ELIBBAD 80 /* Accessing a corrupted shared library */
+#define ELIBSCN 81 /* .lib section in a.out corrupted */
+#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
+#define ELIBEXEC 83 /* Cannot exec a shared library directly */
+#define EILSEQ 84 /* Illegal byte sequence */
+#define ERESTART 85 /* Interrupted system call should be restarted */
+#define ESTRPIPE 86 /* Streams pipe error */
+#define EUSERS 87 /* Too many users */
+#define ENOTSOCK 88 /* Socket operation on non-socket */
+#define EDESTADDRREQ 89 /* Destination address required */
+#define EMSGSIZE 90 /* Message too long */
+#define EPROTOTYPE 91 /* Protocol wrong type for socket */
+#define ENOPROTOOPT 92 /* Protocol not available */
+#define EPROTONOSUPPORT 93 /* Protocol not supported */
+#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
+#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
+#define EPFNOSUPPORT 96 /* Protocol family not supported */
+#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
+#define EADDRINUSE 98 /* Address already in use */
+#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
+#define ENETDOWN 100 /* Network is down */
+#define ENETUNREACH 101 /* Network is unreachable */
+#define ENETRESET 102 /* Network dropped connection because of reset */
+#define ECONNABORTED 103 /* Software caused connection abort */
+#define ECONNRESET 104 /* Connection reset by peer */
+#define ENOBUFS 105 /* No buffer space available */
+#define EISCONN 106 /* Transport endpoint is already connected */
+#define ENOTCONN 107 /* Transport endpoint is not connected */
+#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
+#define ETOOMANYREFS 109 /* Too many references: cannot splice */
+#define ETIMEDOUT 110 /* Connection timed out */
+#define ECONNREFUSED 111 /* Connection refused */
+#define EHOSTDOWN 112 /* Host is down */
+#define EHOSTUNREACH 113 /* No route to host */
+#define EALREADY 114 /* Operation already in progress */
+#define EINPROGRESS 115 /* Operation now in progress */
+#define ESTALE 116 /* Stale NFS file handle */
+#define EUCLEAN 117 /* Structure needs cleaning */
+#define ENOTNAM 118 /* Not a XENIX named type file */
+#define ENAVAIL 119 /* No XENIX semaphores available */
+#define EISNAM 120 /* Is a named type file */
+#define EREMOTEIO 121 /* Remote I/O error */
+#define EDQUOT 122 /* Quota exceeded */
+
+#define ENOMEDIUM 123 /* No medium found */
+#define EMEDIUMTYPE 124 /* Wrong medium type */
+
+#endif /* _XTENSA_ERRNO_H */
diff --git a/include/asm-xtensa/fcntl.h b/include/asm-xtensa/fcntl.h
new file mode 100644
index 00000000000..48876bb727d
--- /dev/null
+++ b/include/asm-xtensa/fcntl.h
@@ -0,0 +1,101 @@
+/*
+ * include/asm-xtensa/fcntl.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_FCNTL_H
+#define _XTENSA_FCNTL_H
+
+/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
+ located on an ext2 file system */
+#define O_ACCMODE 0x0003
+#define O_RDONLY 0x0000
+#define O_WRONLY 0x0001
+#define O_RDWR 0x0002
+#define O_APPEND 0x0008
+#define O_SYNC 0x0010
+#define O_NONBLOCK 0x0080
+#define O_CREAT 0x0100 /* not fcntl */
+#define O_TRUNC 0x0200 /* not fcntl */
+#define O_EXCL 0x0400 /* not fcntl */
+#define O_NOCTTY 0x0800 /* not fcntl */
+#define FASYNC 0x1000 /* fcntl, for BSD compatibility */
+#define O_LARGEFILE 0x2000 /* allow large file opens - currently ignored */
+#define O_DIRECT 0x8000 /* direct disk access hint - currently ignored*/
+#define O_DIRECTORY 0x10000 /* must be a directory */
+#define O_NOFOLLOW 0x20000 /* don't follow links */
+#define O_NOATIME 0x100000
+
+#define O_NDELAY O_NONBLOCK
+
+#define F_DUPFD 0 /* dup */
+#define F_GETFD 1 /* get close_on_exec */
+#define F_SETFD 2 /* set/clear close_on_exec */
+#define F_GETFL 3 /* get file->f_flags */
+#define F_SETFL 4 /* set file->f_flags */
+#define F_GETLK 14
+#define F_GETLK64 15
+#define F_SETLK 6
+#define F_SETLKW 7
+#define F_SETLK64 16
+#define F_SETLKW64 17
+
+#define F_SETOWN 24 /* for sockets. */
+#define F_GETOWN 23 /* for sockets. */
+#define F_SETSIG 10 /* for sockets. */
+#define F_GETSIG 11 /* for sockets. */
+
+/* for F_[GET|SET]FL */
+#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
+
+/* for posix fcntl() and lockf() */
+#define F_RDLCK 0
+#define F_WRLCK 1
+#define F_UNLCK 2
+
+/* for old implementation of bsd flock () */
+#define F_EXLCK 4 /* or 3 */
+#define F_SHLCK 8 /* or 4 */
+
+/* for leases */
+#define F_INPROGRESS 16
+
+/* operations for bsd flock(), also used by the kernel implementation */
+#define LOCK_SH 1 /* shared lock */
+#define LOCK_EX 2 /* exclusive lock */
+#define LOCK_NB 4 /* or'd with one of the above to prevent
+ blocking */
+#define LOCK_UN 8 /* remove lock */
+
+#define LOCK_MAND 32 /* This is a mandatory flock ... */
+#define LOCK_READ 64 /* which allows concurrent read operations */
+#define LOCK_WRITE 128 /* which allows concurrent write operations */
+#define LOCK_RW 192 /* which allows concurrent read & write ops */
+
+typedef struct flock {
+ short l_type;
+ short l_whence;
+ __kernel_off_t l_start;
+ __kernel_off_t l_len;
+ long l_sysid;
+ __kernel_pid_t l_pid;
+ long pad[4];
+} flock_t;
+
+struct flock64 {
+ short l_type;
+ short l_whence;
+ __kernel_off_t l_start;
+ __kernel_off_t l_len;
+ pid_t l_pid;
+};
+
+#define F_LINUX_SPECIFIC_BASE 1024
+
+#endif /* _XTENSA_FCNTL_H */
diff --git a/include/asm-xtensa/fixmap.h b/include/asm-xtensa/fixmap.h
new file mode 100644
index 00000000000..4423b8ad495
--- /dev/null
+++ b/include/asm-xtensa/fixmap.h
@@ -0,0 +1,252 @@
+/*
+ * include/asm-xtensa/fixmap.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_FIXMAP_H
+#define _XTENSA_FIXMAP_H
+
+#include <asm/processor.h>
+
+#ifdef CONFIG_MMU
+
+/*
+ * Here we define all the compile-time virtual addresses.
+ */
+
+#if XCHAL_SEG_MAPPABLE_VADDR != 0
+# error "Current port requires virtual user space starting at 0"
+#endif
+#if XCHAL_SEG_MAPPABLE_SIZE < 0x80000000
+# error "Current port requires at least 0x8000000 bytes for user space"
+#endif
+
+/* Verify instruction/data ram/rom and xlmi don't overlay vmalloc space. */
+
+#define __IN_VMALLOC(addr) \
+ (((addr) >= VMALLOC_START) && ((addr) < VMALLOC_END))
+#define __SPAN_VMALLOC(start,end) \
+ (((start) < VMALLOC_START) && ((end) >= VMALLOC_END))
+#define INSIDE_VMALLOC(start,end) \
+ (__IN_VMALLOC((start)) || __IN_VMALLOC(end) || __SPAN_VMALLOC((start),(end)))
+
+#if XCHAL_NUM_INSTROM
+# if XCHAL_NUM_INSTROM == 1
+# if INSIDE_VMALLOC(XCHAL_INSTROM0_VADDR,XCHAL_INSTROM0_VADDR+XCHAL_INSTROM0_SIZE)
+# error vmalloc range conflicts with instrom0
+# endif
+# endif
+# if XCHAL_NUM_INSTROM == 2
+# if INSIDE_VMALLOC(XCHAL_INSTROM1_VADDR,XCHAL_INSTROM1_VADDR+XCHAL_INSTROM1_SIZE)
+# error vmalloc range conflicts with instrom1
+# endif
+# endif
+#endif
+
+#if XCHAL_NUM_INSTRAM
+# if XCHAL_NUM_INSTRAM == 1
+# if INSIDE_VMALLOC(XCHAL_INSTRAM0_VADDR,XCHAL_INSTRAM0_VADDR+XCHAL_INSTRAM0_SIZE)
+# error vmalloc range conflicts with instram0
+# endif
+# endif
+# if XCHAL_NUM_INSTRAM == 2
+# if INSIDE_VMALLOC(XCHAL_INSTRAM1_VADDR,XCHAL_INSTRAM1_VADDR+XCHAL_INSTRAM1_SIZE)
+# error vmalloc range conflicts with instram1
+# endif
+# endif
+#endif
+
+#if XCHAL_NUM_DATAROM
+# if XCHAL_NUM_DATAROM == 1
+# if INSIDE_VMALLOC(XCHAL_DATAROM0_VADDR,XCHAL_DATAROM0_VADDR+XCHAL_DATAROM0_SIZE)
+# error vmalloc range conflicts with datarom0
+# endif
+# endif
+# if XCHAL_NUM_DATAROM == 2
+# if INSIDE_VMALLOC(XCHAL_DATAROM1_VADDR,XCHAL_DATAROM1_VADDR+XCHAL_DATAROM1_SIZE)
+# error vmalloc range conflicts with datarom1
+# endif
+# endif
+#endif
+
+#if XCHAL_NUM_DATARAM
+# if XCHAL_NUM_DATARAM == 1
+# if INSIDE_VMALLOC(XCHAL_DATARAM0_VADDR,XCHAL_DATARAM0_VADDR+XCHAL_DATARAM0_SIZE)
+# error vmalloc range conflicts with dataram0
+# endif
+# endif
+# if XCHAL_NUM_DATARAM == 2
+# if INSIDE_VMALLOC(XCHAL_DATARAM1_VADDR,XCHAL_DATARAM1_VADDR+XCHAL_DATARAM1_SIZE)
+# error vmalloc range conflicts with dataram1
+# endif
+# endif
+#endif
+
+#if XCHAL_NUM_XLMI
+# if XCHAL_NUM_XLMI == 1
+# if INSIDE_VMALLOC(XCHAL_XLMI0_VADDR,XCHAL_XLMI0_VADDR+XCHAL_XLMI0_SIZE)
+# error vmalloc range conflicts with xlmi0
+# endif
+# endif
+# if XCHAL_NUM_XLMI == 2
+# if INSIDE_VMALLOC(XCHAL_XLMI1_VADDR,XCHAL_XLMI1_VADDR+XCHAL_XLMI1_SIZE)
+# error vmalloc range conflicts with xlmi1
+# endif
+# endif
+#endif
+
+#if (XCHAL_NUM_INSTROM > 2) || \
+ (XCHAL_NUM_INSTRAM > 2) || \
+ (XCHAL_NUM_DATARAM > 2) || \
+ (XCHAL_NUM_DATAROM > 2) || \
+ (XCHAL_NUM_XLMI > 2)
+# error Insufficient checks on vmalloc above for more than 2 devices
+#endif
+
+/*
+ * USER_VM_SIZE does not necessarily equal TASK_SIZE. We bumped
+ * TASK_SIZE down to 0x4000000 to simplify the handling of windowed
+ * call instructions (currently limited to a range of 1 GByte). User
+ * tasks may very well reclaim the VM space from 0x40000000 to
+ * 0x7fffffff in the future, so we do not want the kernel becoming
+ * accustomed to having any of its stuff (e.g., page tables) in this
+ * region. This VM region is no-man's land for now.
+ */
+
+#define USER_VM_START XCHAL_SEG_MAPPABLE_VADDR
+#define USER_VM_SIZE 0x80000000
+
+/* Size of page table: */
+
+#define PGTABLE_SIZE_BITS (32 - XCHAL_MMU_MIN_PTE_PAGE_SIZE + 2)
+#define PGTABLE_SIZE (1L << PGTABLE_SIZE_BITS)
+
+/* All kernel-mappable space: */
+
+#define KERNEL_ALLMAP_START (USER_VM_START + USER_VM_SIZE)
+#define KERNEL_ALLMAP_SIZE (XCHAL_SEG_MAPPABLE_SIZE - KERNEL_ALLMAP_START)
+
+/* Carve out page table at start of kernel-mappable area: */
+
+#if KERNEL_ALLMAP_SIZE < PGTABLE_SIZE
+#error "Gimme some space for page table!"
+#endif
+#define PGTABLE_START KERNEL_ALLMAP_START
+
+/* Remaining kernel-mappable space: */
+
+#define KERNEL_MAPPED_START (KERNEL_ALLMAP_START + PGTABLE_SIZE)
+#define KERNEL_MAPPED_SIZE (KERNEL_ALLMAP_SIZE - PGTABLE_SIZE)
+
+#if KERNEL_MAPPED_SIZE < 0x01000000 /* 16 MB is arbitrary for now */
+# error "Shouldn't the kernel have at least *some* mappable space?"
+#endif
+
+#define MAX_LOW_MEMORY XCHAL_KSEG_CACHED_SIZE
+
+#endif
+
+/*
+ * Some constants used elsewhere, but perhaps only in Xtensa header
+ * files, so maybe we can get rid of some and access compile-time HAL
+ * directly...
+ *
+ * Note: We assume that system RAM is located at the very start of the
+ * kernel segments !!
+ */
+#define KERNEL_VM_LOW XCHAL_KSEG_CACHED_VADDR
+#define KERNEL_VM_HIGH XCHAL_KSEG_BYPASS_VADDR
+#define KERNEL_SPACE XCHAL_KSEG_CACHED_VADDR
+
+/*
+ * Returns the physical/virtual addresses of the kernel space
+ * (works with the cached kernel segment only, which is the
+ * one normally used for kernel operation).
+ */
+
+/* PHYSICAL BYPASS CACHED
+ *
+ * bypass vaddr bypass paddr * cached vaddr
+ * cached vaddr cached paddr bypass vaddr *
+ * bypass paddr * bypass vaddr cached vaddr
+ * cached paddr * bypass vaddr cached vaddr
+ * other * * *
+ */
+
+#define PHYSADDR(a) \
+(((unsigned)(a) >= XCHAL_KSEG_BYPASS_VADDR \
+ && (unsigned)(a) < XCHAL_KSEG_BYPASS_VADDR + XCHAL_KSEG_BYPASS_SIZE) ? \
+ (unsigned)(a) - XCHAL_KSEG_BYPASS_VADDR + XCHAL_KSEG_BYPASS_PADDR : \
+ ((unsigned)(a) >= XCHAL_KSEG_CACHED_VADDR \
+ && (unsigned)(a) < XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_CACHED_SIZE) ? \
+ (unsigned)(a) - XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_CACHED_PADDR : \
+ (unsigned)(a))
+
+#define BYPASS_ADDR(a) \
+(((unsigned)(a) >= XCHAL_KSEG_BYPASS_PADDR \
+ && (unsigned)(a) < XCHAL_KSEG_BYPASS_PADDR + XCHAL_KSEG_BYPASS_SIZE) ? \
+ (unsigned)(a) - XCHAL_KSEG_BYPASS_PADDR + XCHAL_KSEG_BYPASS_VADDR : \
+ ((unsigned)(a) >= XCHAL_KSEG_CACHED_PADDR \
+ && (unsigned)(a) < XCHAL_KSEG_CACHED_PADDR + XCHAL_KSEG_CACHED_SIZE) ? \
+ (unsigned)(a) - XCHAL_KSEG_CACHED_PADDR + XCHAL_KSEG_BYPASS_VADDR : \
+ ((unsigned)(a) >= XCHAL_KSEG_CACHED_VADDR \
+ && (unsigned)(a) < XCHAL_KSEG_CACHED_VADDR+XCHAL_KSEG_CACHED_SIZE)? \
+ (unsigned)(a) - XCHAL_KSEG_CACHED_VADDR+XCHAL_KSEG_BYPASS_VADDR: \
+ (unsigned)(a))
+
+#define CACHED_ADDR(a) \
+(((unsigned)(a) >= XCHAL_KSEG_BYPASS_PADDR \
+ && (unsigned)(a) < XCHAL_KSEG_BYPASS_PADDR + XCHAL_KSEG_BYPASS_SIZE) ? \
+ (unsigned)(a) - XCHAL_KSEG_BYPASS_PADDR + XCHAL_KSEG_CACHED_VADDR : \
+ ((unsigned)(a) >= XCHAL_KSEG_CACHED_PADDR \
+ && (unsigned)(a) < XCHAL_KSEG_CACHED_PADDR + XCHAL_KSEG_CACHED_SIZE) ? \
+ (unsigned)(a) - XCHAL_KSEG_CACHED_PADDR + XCHAL_KSEG_CACHED_VADDR : \
+ ((unsigned)(a) >= XCHAL_KSEG_BYPASS_VADDR \
+ && (unsigned)(a) < XCHAL_KSEG_BYPASS_VADDR+XCHAL_KSEG_BYPASS_SIZE) ? \
+ (unsigned)(a) - XCHAL_KSEG_BYPASS_VADDR+XCHAL_KSEG_CACHED_VADDR : \
+ (unsigned)(a))
+
+#define PHYSADDR_IO(a) \
+(((unsigned)(a) >= XCHAL_KIO_BYPASS_VADDR \
+ && (unsigned)(a) < XCHAL_KIO_BYPASS_VADDR + XCHAL_KIO_BYPASS_SIZE) ? \
+ (unsigned)(a) - XCHAL_KIO_BYPASS_VADDR + XCHAL_KIO_BYPASS_PADDR : \
+ ((unsigned)(a) >= XCHAL_KIO_CACHED_VADDR \
+ && (unsigned)(a) < XCHAL_KIO_CACHED_VADDR + XCHAL_KIO_CACHED_SIZE) ? \
+ (unsigned)(a) - XCHAL_KIO_CACHED_VADDR + XCHAL_KIO_CACHED_PADDR : \
+ (unsigned)(a))
+
+#define BYPASS_ADDR_IO(a) \
+(((unsigned)(a) >= XCHAL_KIO_BYPASS_PADDR \
+ && (unsigned)(a) < XCHAL_KIO_BYPASS_PADDR + XCHAL_KIO_BYPASS_SIZE) ? \
+ (unsigned)(a) - XCHAL_KIO_BYPASS_PADDR + XCHAL_KIO_BYPASS_VADDR : \
+ ((unsigned)(a) >= XCHAL_KIO_CACHED_PADDR \
+ && (unsigned)(a) < XCHAL_KIO_CACHED_PADDR + XCHAL_KIO_CACHED_SIZE) ? \
+ (unsigned)(a) - XCHAL_KIO_CACHED_PADDR + XCHAL_KIO_BYPASS_VADDR : \
+ ((unsigned)(a) >= XCHAL_KIO_CACHED_VADDR \
+ && (unsigned)(a) < XCHAL_KIO_CACHED_VADDR + XCHAL_KIO_CACHED_SIZE) ? \
+ (unsigned)(a) - XCHAL_KIO_CACHED_VADDR + XCHAL_KIO_BYPASS_VADDR : \
+ (unsigned)(a))
+
+#define CACHED_ADDR_IO(a) \
+(((unsigned)(a) >= XCHAL_KIO_BYPASS_PADDR \
+ && (unsigned)(a) < XCHAL_KIO_BYPASS_PADDR + XCHAL_KIO_BYPASS_SIZE) ? \
+ (unsigned)(a) - XCHAL_KIO_BYPASS_PADDR + XCHAL_KIO_CACHED_VADDR : \
+ ((unsigned)(a) >= XCHAL_KIO_CACHED_PADDR \
+ && (unsigned)(a) < XCHAL_KIO_CACHED_PADDR + XCHAL_KIO_CACHED_SIZE) ? \
+ (unsigned)(a) - XCHAL_KIO_CACHED_PADDR + XCHAL_KIO_CACHED_VADDR : \
+ ((unsigned)(a) >= XCHAL_KIO_BYPASS_VADDR \
+ && (unsigned)(a) < XCHAL_KIO_BYPASS_VADDR + XCHAL_KIO_BYPASS_SIZE) ? \
+ (unsigned)(a) - XCHAL_KIO_BYPASS_VADDR + XCHAL_KIO_CACHED_VADDR : \
+ (unsigned)(a))
+
+#endif /* _XTENSA_ADDRSPACE_H */
+
+
+
+
+
diff --git a/include/asm-xtensa/hardirq.h b/include/asm-xtensa/hardirq.h
new file mode 100644
index 00000000000..e07c76c36b9
--- /dev/null
+++ b/include/asm-xtensa/hardirq.h
@@ -0,0 +1,28 @@
+/*
+ * include/asm-xtensa/hardirq.h
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ *
+ * Copyright (C) 2002 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_HARDIRQ_H
+#define _XTENSA_HARDIRQ_H
+
+#include <linux/config.h>
+#include <linux/cache.h>
+#include <asm/irq.h>
+
+/* headers.S is sensitive to the offsets of these fields */
+typedef struct {
+ unsigned int __softirq_pending;
+ unsigned int __syscall_count;
+ struct task_struct * __ksoftirqd_task; /* waitqueue is too large */
+ unsigned int __nmi_count; /* arch dependent */
+} ____cacheline_aligned irq_cpustat_t;
+
+#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
+
+#endif /* _XTENSA_HARDIRQ_H */
diff --git a/include/asm-xtensa/hdreg.h b/include/asm-xtensa/hdreg.h
new file mode 100644
index 00000000000..64b80607b80
--- /dev/null
+++ b/include/asm-xtensa/hdreg.h
@@ -0,0 +1,17 @@
+/*
+ * include/asm-xtensa/hdreg.h
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ *
+ * Copyright (C) 2002 - 2005 Tensilica Inc.
+ * Copyright (C) 1994-1996 Linus Torvalds & authors
+ */
+
+#ifndef _XTENSA_HDREG_H
+#define _XTENSA_HDREG_H
+
+typedef unsigned int ide_ioreg_t;
+
+#endif
diff --git a/include/asm-xtensa/highmem.h b/include/asm-xtensa/highmem.h
new file mode 100644
index 00000000000..0a046ca5a68
--- /dev/null
+++ b/include/asm-xtensa/highmem.h
@@ -0,0 +1,17 @@
+/*
+ * include/asm-xtensa/highmem.h
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ *
+ * Copyright (C) 2003 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_HIGHMEM_H
+#define _XTENSA_HIGHMEM_H
+
+extern void flush_cache_kmaps(void);
+
+#endif
+
diff --git a/include/asm-xtensa/hw_irq.h b/include/asm-xtensa/hw_irq.h
new file mode 100644
index 00000000000..ccf436249ea
--- /dev/null
+++ b/include/asm-xtensa/hw_irq.h
@@ -0,0 +1,18 @@
+/*
+ * include/asm-xtensa/hw_irq.h
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ *
+ * Copyright (C) 2002 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_HW_IRQ_H
+#define _XTENSA_HW_IRQ_H
+
+static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i)
+{
+}
+
+#endif
diff --git a/include/asm-xtensa/ide.h b/include/asm-xtensa/ide.h
new file mode 100644
index 00000000000..b523cd4a486
--- /dev/null
+++ b/include/asm-xtensa/ide.h
@@ -0,0 +1,36 @@
+/*
+ * include/asm-xtensa/ide.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994 - 1996 Linus Torvalds & authors
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_IDE_H
+#define _XTENSA_IDE_H
+
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+
+#ifndef MAX_HWIFS
+# define MAX_HWIFS 1
+#endif
+
+static __inline__ int ide_default_irq(unsigned long base)
+{
+ /* Unsupported! */
+ return 0;
+}
+
+static __inline__ unsigned long ide_default_io_base(int index)
+{
+ /* Unsupported! */
+ return 0;
+}
+
+#endif /* __KERNEL__ */
+#endif /* _XTENSA_IDE_H */
diff --git a/include/asm-xtensa/io.h b/include/asm-xtensa/io.h
new file mode 100644
index 00000000000..2c471c42ecf
--- /dev/null
+++ b/include/asm-xtensa/io.h
@@ -0,0 +1,197 @@
+/*
+ * linux/include/asm-xtensa/io.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_IO_H
+#define _XTENSA_IO_H
+
+#ifdef __KERNEL__
+#include <linux/config.h>
+#include <asm/byteorder.h>
+
+#include <linux/types.h>
+#include <asm/fixmap.h>
+
+#define _IO_BASE 0
+
+
+/*
+ * swap functions to change byte order from little-endian to big-endian and
+ * vice versa.
+ */
+
+static inline unsigned short _swapw (unsigned short v)
+{
+ return (v << 8) | (v >> 8);
+}
+
+static inline unsigned int _swapl (unsigned int v)
+{
+ return (v << 24) | ((v & 0xff00) << 8) | ((v >> 8) & 0xff00) | (v >> 24);
+}
+
+/*
+ * Change virtual addresses to physical addresses and vv.
+ * These are trivial on the 1:1 Linux/Xtensa mapping
+ */
+
+extern inline unsigned long virt_to_phys(volatile void * address)
+{
+ return PHYSADDR((unsigned long)address);
+}
+
+extern inline void * phys_to_virt(unsigned long address)
+{
+ return (void*) CACHED_ADDR(address);
+}
+
+/*
+ * IO bus memory addresses are also 1:1 with the physical address
+ */
+
+extern inline unsigned long virt_to_bus(volatile void * address)
+{
+ return PHYSADDR((unsigned long)address);
+}
+
+extern inline void * bus_to_virt (unsigned long address)
+{
+ return (void *) CACHED_ADDR(address);
+}
+
+/*
+ * Change "struct page" to physical address.
+ */
+
+extern inline void *ioremap(unsigned long offset, unsigned long size)
+{
+ return (void *) CACHED_ADDR_IO(offset);
+}
+
+extern inline void *ioremap_nocache(unsigned long offset, unsigned long size)
+{
+ return (void *) BYPASS_ADDR_IO(offset);
+}
+
+extern inline void iounmap(void *addr)
+{
+}
+
+/*
+ * Generic I/O
+ */
+
+#define readb(addr) \
+ ({ unsigned char __v = (*(volatile unsigned char *)(addr)); __v; })
+#define readw(addr) \
+ ({ unsigned short __v = (*(volatile unsigned short *)(addr)); __v; })
+#define readl(addr) \
+ ({ unsigned int __v = (*(volatile unsigned int *)(addr)); __v; })
+#define writeb(b, addr) (void)((*(volatile unsigned char *)(addr)) = (b))
+#define writew(b, addr) (void)((*(volatile unsigned short *)(addr)) = (b))
+#define writel(b, addr) (void)((*(volatile unsigned int *)(addr)) = (b))
+
+static inline __u8 __raw_readb(const volatile void __iomem *addr)
+{
+ return *(__force volatile __u8 *)(addr);
+}
+static inline __u16 __raw_readw(const volatile void __iomem *addr)
+{
+ return *(__force volatile __u16 *)(addr);
+}
+static inline __u32 __raw_readl(const volatile void __iomem *addr)
+{
+ return *(__force volatile __u32 *)(addr);
+}
+static inline void __raw_writeb(__u8 b, volatile void __iomem *addr)
+{
+ *(__force volatile __u8 *)(addr) = b;
+}
+static inline void __raw_writew(__u16 b, volatile void __iomem *addr)
+{
+ *(__force volatile __u16 *)(addr) = b;
+}
+static inline void __raw_writel(__u32 b, volatile void __iomem *addr)
+{
+ *(__force volatile __u32 *)(addr) = b;
+}
+
+
+
+
+/* These are the definitions for the x86 IO instructions
+ * inb/inw/inl/outb/outw/outl, the "string" versions
+ * insb/insw/insl/outsb/outsw/outsl, and the "pausing" versions
+ * inb_p/inw_p/...
+ * The macros don't do byte-swapping.
+ */
+
+#define inb(port) readb((u8 *)((port)+_IO_BASE))
+#define outb(val, port) writeb((val),(u8 *)((unsigned long)(port)+_IO_BASE))
+#define inw(port) readw((u16 *)((port)+_IO_BASE))
+#define outw(val, port) writew((val),(u16 *)((unsigned long)(port)+_IO_BASE))
+#define inl(port) readl((u32 *)((port)+_IO_BASE))
+#define outl(val, port) writel((val),(u32 *)((unsigned long)(port)))
+
+#define inb_p(port) inb((port))
+#define outb_p(val, port) outb((val), (port))
+#define inw_p(port) inw((port))
+#define outw_p(val, port) outw((val), (port))
+#define inl_p(port) inl((port))
+#define outl_p(val, port) outl((val), (port))
+
+extern void insb (unsigned long port, void *dst, unsigned long count);
+extern void insw (unsigned long port, void *dst, unsigned long count);
+extern void insl (unsigned long port, void *dst, unsigned long count);
+extern void outsb (unsigned long port, const void *src, unsigned long count);
+extern void outsw (unsigned long port, const void *src, unsigned long count);
+extern void outsl (unsigned long port, const void *src, unsigned long count);
+
+#define IO_SPACE_LIMIT ~0
+
+#define memset_io(a,b,c) memset((void *)(a),(b),(c))
+#define memcpy_fromio(a,b,c) memcpy((a),(void *)(b),(c))
+#define memcpy_toio(a,b,c) memcpy((void *)(a),(b),(c))
+
+/* At this point the Xtensa doesn't provide byte swap instructions */
+
+#ifdef __XTENSA_EB__
+# define in_8(addr) (*(u8*)(addr))
+# define in_le16(addr) _swapw(*(u16*)(addr))
+# define in_le32(addr) _swapl(*(u32*)(addr))
+# define out_8(b, addr) *(u8*)(addr) = (b)
+# define out_le16(b, addr) *(u16*)(addr) = _swapw(b)
+# define out_le32(b, addr) *(u32*)(addr) = _swapl(b)
+#elif defined(__XTENSA_EL__)
+# define in_8(addr) (*(u8*)(addr))
+# define in_le16(addr) (*(u16*)(addr))
+# define in_le32(addr) (*(u32*)(addr))
+# define out_8(b, addr) *(u8*)(addr) = (b)
+# define out_le16(b, addr) *(u16*)(addr) = (b)
+# define out_le32(b, addr) *(u32*)(addr) = (b)
+#else
+# error processor byte order undefined!
+#endif
+
+
+/*
+ * * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * * access
+ * */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * * Convert a virtual cached pointer to an uncached pointer
+ * */
+#define xlate_dev_kmem_ptr(p) p
+
+
+#endif /* __KERNEL__ */
+
+#endif /* _XTENSA_IO_H */
diff --git a/include/asm-xtensa/ioctl.h b/include/asm-xtensa/ioctl.h
new file mode 100644
index 00000000000..856c605d62b
--- /dev/null
+++ b/include/asm-xtensa/ioctl.h
@@ -0,0 +1,83 @@
+/*
+ * include/asm-xtensa/ioctl.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 - 2005 Tensilica Inc.
+ *
+ * Derived from "include/asm-i386/ioctl.h"
+ */
+
+#ifndef _XTENSA_IOCTL_H
+#define _XTENSA_IOCTL_H
+
+
+/* ioctl command encoding: 32 bits total, command in lower 16 bits,
+ * size of the parameter structure in the lower 14 bits of the
+ * upper 16 bits.
+ * Encoding the size of the parameter structure in the ioctl request
+ * is useful for catching programs compiled with old versions
+ * and to avoid overwriting user space outside the user buffer area.
+ * The highest 2 bits are reserved for indicating the ``access mode''.
+ * NOTE: This limits the max parameter size to 16kB -1 !
+ */
+
+/*
+ * The following is for compatibility across the various Linux
+ * platforms. The i386 ioctl numbering scheme doesn't really enforce
+ * a type field. De facto, however, the top 8 bits of the lower 16
+ * bits are indeed used as a type field, so we might just as well make
+ * this explicit here. Please be sure to use the decoding macros
+ * below from now on.
+ */
+#define _IOC_NRBITS 8
+#define _IOC_TYPEBITS 8
+#define _IOC_SIZEBITS 14
+#define _IOC_DIRBITS 2
+
+#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1)
+#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1)
+#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1)
+#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1)
+
+#define _IOC_NRSHIFT 0
+#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS)
+#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS)
+#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS)
+
+/*
+ * Direction bits.
+ */
+#define _IOC_NONE 0U
+#define _IOC_WRITE 1U
+#define _IOC_READ 2U
+
+#define _IOC(dir,type,nr,size) \
+ (((dir) << _IOC_DIRSHIFT) | \
+ ((type) << _IOC_TYPESHIFT) | \
+ ((nr) << _IOC_NRSHIFT) | \
+ ((size) << _IOC_SIZESHIFT))
+
+/* used to create numbers */
+#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
+#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
+#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+
+/* used to decode ioctl numbers.. */
+#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
+#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
+#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
+#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
+
+/* ...and for the drivers/sound files... */
+
+#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT)
+#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT)
+#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
+#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT)
+#define IOCSIZE_SHIFT (_IOC_SIZESHIFT)
+
+#endif
diff --git a/include/asm-xtensa/ioctls.h b/include/asm-xtensa/ioctls.h
new file mode 100644
index 00000000000..10c443435c1
--- /dev/null
+++ b/include/asm-xtensa/ioctls.h
@@ -0,0 +1,112 @@
+/*
+ * include/asm-xtensa/ioctl.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 - 2005 Tensilica Inc.
+ *
+ * Derived from "include/asm-i386/ioctls.h"
+ */
+
+#ifndef _XTENSA_IOCTLS_H
+#define _XTENSA_IOCTLS_H
+
+#include <asm/ioctl.h>
+
+#define FIOCLEX _IO('f', 1)
+#define FIONCLEX _IO('f', 2)
+#define FIOASYNC _IOW('f', 125, int)
+#define FIONBIO _IOW('f', 126, int)
+#define FIONREAD _IOR('f', 127, int)
+#define TIOCINQ FIONREAD
+#define FIOQSIZE _IOR('f', 128, loff_t)
+
+#define TCGETS 0x5401
+#define TCSETS 0x5402
+#define TCSETSW 0x5403
+#define TCSETSF 0x5404
+
+#define TCGETA _IOR('t', 23, struct termio)
+#define TCSETA _IOW('t', 24, struct termio)
+#define TCSETAW _IOW('t', 25, struct termio)
+#define TCSETAF _IOW('t', 28, struct termio)
+
+#define TCSBRK _IO('t', 29)
+#define TCXONC _IO('t', 30)
+#define TCFLSH _IO('t', 31)
+
+#define TIOCSWINSZ _IOW('t', 103, struct winsize)
+#define TIOCGWINSZ _IOR('t', 104, struct winsize)
+#define TIOCSTART _IO('t', 110) /* start output, like ^Q */
+#define TIOCSTOP _IO('t', 111) /* stop output, like ^S */
+#define TIOCOUTQ _IOR('t', 115, int) /* output queue size */
+
+#define TIOCSPGRP _IOW('t', 118, int)
+#define TIOCGPGRP _IOR('t', 119, int)
+
+#define TIOCEXCL _IO('T', 12)
+#define TIOCNXCL _IO('T', 13)
+#define TIOCSCTTY _IO('T', 14)
+
+#define TIOCSTI _IOW('T', 18, char)
+#define TIOCMGET _IOR('T', 21, unsigned int)
+#define TIOCMBIS _IOW('T', 22, unsigned int)
+#define TIOCMBIC _IOW('T', 23, unsigned int)
+#define TIOCMSET _IOW('T', 24, unsigned int)
+# define TIOCM_LE 0x001
+# define TIOCM_DTR 0x002
+# define TIOCM_RTS 0x004
+# define TIOCM_ST 0x008
+# define TIOCM_SR 0x010
+# define TIOCM_CTS 0x020
+# define TIOCM_CAR 0x040
+# define TIOCM_RNG 0x080
+# define TIOCM_DSR 0x100
+# define TIOCM_CD TIOCM_CAR
+# define TIOCM_RI TIOCM_RNG
+
+#define TIOCGSOFTCAR _IOR('T', 25, unsigned int)
+#define TIOCSSOFTCAR _IOW('T', 26, unsigned int)
+#define TIOCLINUX _IOW('T', 28, char)
+#define TIOCCONS _IO('T', 29)
+#define TIOCGSERIAL _IOR('T', 30, struct serial_struct)
+#define TIOCSSERIAL _IOW('T', 31, struct serial_struct)
+#define TIOCPKT _IOW('T', 32, int)
+# define TIOCPKT_DATA 0
+# define TIOCPKT_FLUSHREAD 1
+# define TIOCPKT_FLUSHWRITE 2
+# define TIOCPKT_STOP 4
+# define TIOCPKT_START 8
+# define TIOCPKT_NOSTOP 16
+# define TIOCPKT_DOSTOP 32
+
+
+#define TIOCNOTTY _IO('T', 34)
+#define TIOCSETD _IOW('T', 35, int)
+#define TIOCGETD _IOR('T', 36, int)
+#define TCSBRKP _IOW('T', 37, int) /* Needed for POSIX tcsendbreak()*/
+#define TIOCTTYGSTRUCT _IOR('T', 38, struct tty_struct) /* For debugging only*/
+#define TIOCSBRK _IO('T', 39) /* BSD compatibility */
+#define TIOCCBRK _IO('T', 40) /* BSD compatibility */
+#define TIOCGSID _IOR('T', 41, pid_t) /* Return the session ID of FD*/
+#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
+#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
+
+#define TIOCSERCONFIG _IO('T', 83)
+#define TIOCSERGWILD _IOR('T', 84, int)
+#define TIOCSERSWILD _IOW('T', 85, int)
+#define TIOCGLCKTRMIOS 0x5456
+#define TIOCSLCKTRMIOS 0x5457
+#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
+#define TIOCSERGETLSR _IOR('T', 89, unsigned int) /* Get line status reg. */
+ /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+# define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
+#define TIOCSERGETMULTI _IOR('T', 90, struct serial_multiport_struct) /* Get multiport config */
+#define TIOCSERSETMULTI _IOW('T', 91, struct serial_multiport_struct) /* Set multiport config */
+
+#define TIOCMIWAIT _IO('T', 92) /* wait for a change on serial input line(s) */
+#define TIOCGICOUNT _IOR('T', 93, struct async_icount) /* read serial port inline interrupt counts */
+
+#endif /* _XTENSA_IOCTLS_H */
diff --git a/include/asm-xtensa/ipc.h b/include/asm-xtensa/ipc.h
new file mode 100644
index 00000000000..d37bdb4d4c9
--- /dev/null
+++ b/include/asm-xtensa/ipc.h
@@ -0,0 +1,34 @@
+/*
+ * include/asm-xtensa/ipc.h
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_IPC_H
+#define _XTENSA_IPC_H
+
+struct ipc_kludge {
+ struct msgbuf __user *msgp;
+ long msgtyp;
+};
+
+#define SEMOP 1
+#define SEMGET 2
+#define SEMCTL 3
+#define SEMTIMEDOP 4
+#define MSGSND 11
+#define MSGRCV 12
+#define MSGGET 13
+#define MSGCTL 14
+#define SHMAT 21
+#define SHMDT 22
+#define SHMGET 23
+#define SHMCTL 24
+
+#define IPCCALL(version,op) ((version)<<16 | (op))
+
+#endif /* _XTENSA_IPC_H */
diff --git a/include/asm-xtensa/ipcbuf.h b/include/asm-xtensa/ipcbuf.h
new file mode 100644
index 00000000000..c33aa6a4214
--- /dev/null
+++ b/include/asm-xtensa/ipcbuf.h
@@ -0,0 +1,37 @@
+/*
+ * include/asm-xtensa/ipcbuf.h
+ *
+ * The ipc64_perm structure for the Xtensa architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_IPCBUF_H
+#define _XTENSA_IPCBUF_H
+
+/*
+ * Pad space is left for:
+ * - 32-bit mode_t and seq
+ * - 2 miscellaneous 32-bit values
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ */
+
+struct ipc64_perm
+{
+ __kernel_key_t key;
+ __kernel_uid32_t uid;
+ __kernel_gid32_t gid;
+ __kernel_uid32_t cuid;
+ __kernel_gid32_t cgid;
+ __kernel_mode_t mode;
+ unsigned long seq;
+ unsigned long __unused1;
+ unsigned long __unused2;
+};
+
+#endif /* _XTENSA_IPCBUF_H */
diff --git a/include/asm-xtensa/irq.h b/include/asm-xtensa/irq.h
new file mode 100644
index 00000000000..d984e955938
--- /dev/null
+++ b/include/asm-xtensa/irq.h
@@ -0,0 +1,37 @@
+/*
+ * include/asm-xtensa/irq.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_IRQ_H
+#define _XTENSA_IRQ_H
+
+#include <linux/config.h>
+#include <asm/platform/hardware.h>
+
+#include <xtensa/config/core.h>
+
+#ifndef PLATFORM_NR_IRQS
+# define PLATFORM_NR_IRQS 0
+#endif
+#define XTENSA_NR_IRQS XCHAL_NUM_INTERRUPTS
+#define NR_IRQS (XTENSA_NR_IRQS + PLATFORM_NR_IRQS)
+
+static __inline__ int irq_canonicalize(int irq)
+{
+ return (irq);
+}
+
+struct irqaction;
+#if 0 // FIXME
+extern void disable_irq_nosync(unsigned int);
+extern void disable_irq(unsigned int);
+extern void enable_irq(unsigned int);
+#endif
+
+#endif /* _XTENSA_IRQ_H */
diff --git a/include/asm-xtensa/kmap_types.h b/include/asm-xtensa/kmap_types.h
new file mode 100644
index 00000000000..9e822d2e3bc
--- /dev/null
+++ b/include/asm-xtensa/kmap_types.h
@@ -0,0 +1,31 @@
+/*
+ * include/asm-xtensa/kmap_types.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_KMAP_TYPES_H
+#define _XTENSA_KMAP_TYPES_H
+
+enum km_type {
+ KM_BOUNCE_READ,
+ KM_SKB_SUNRPC_DATA,
+ KM_SKB_DATA_SOFTIRQ,
+ KM_USER0,
+ KM_USER1,
+ KM_BIO_SRC_IRQ,
+ KM_BIO_DST_IRQ,
+ KM_PTE0,
+ KM_PTE1,
+ KM_IRQ0,
+ KM_IRQ1,
+ KM_SOFTIRQ0,
+ KM_SOFTIRQ1,
+ KM_TYPE_NR
+};
+
+#endif /* _XTENSA_KMAP_TYPES_H */
diff --git a/include/asm-xtensa/linkage.h b/include/asm-xtensa/linkage.h
new file mode 100644
index 00000000000..bf2128a99d7
--- /dev/null
+++ b/include/asm-xtensa/linkage.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-xtensa/linkage.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_LINKAGE_H
+#define _XTENSA_LINKAGE_H
+
+/* Nothing to do here ... */
+
+#endif /* _XTENSA_LINKAGE_H */
diff --git a/include/asm-xtensa/local.h b/include/asm-xtensa/local.h
new file mode 100644
index 00000000000..48723e550d1
--- /dev/null
+++ b/include/asm-xtensa/local.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-xtensa/local.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_LOCAL_H
+#define _XTENSA_LOCAL_H
+
+#include <asm-generic/local.h>
+
+#endif /* _XTENSA_LOCAL_H */
diff --git a/include/asm-xtensa/mman.h b/include/asm-xtensa/mman.h
new file mode 100644
index 00000000000..9a95a45df99
--- /dev/null
+++ b/include/asm-xtensa/mman.h
@@ -0,0 +1,80 @@
+/*
+ * include/asm-xtensa/mman.h
+ *
+ * Xtensa Processor memory-manager definitions
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995 by Ralf Baechle
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_MMAN_H
+#define _XTENSA_MMAN_H
+
+/*
+ * Protections are chosen from these bits, OR'd together. The
+ * implementation does not necessarily support PROT_EXEC or PROT_WRITE
+ * without PROT_READ. The only guarantees are that no writing will be
+ * allowed without PROT_WRITE and no access will be allowed for PROT_NONE.
+ */
+
+#define PROT_NONE 0x0 /* page can not be accessed */
+#define PROT_READ 0x1 /* page can be read */
+#define PROT_WRITE 0x2 /* page can be written */
+#define PROT_EXEC 0x4 /* page can be executed */
+
+#define PROT_SEM 0x10 /* page may be used for atomic ops */
+#define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */
+#define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end fo growsup vma */
+
+/*
+ * Flags for mmap
+ */
+#define MAP_SHARED 0x001 /* Share changes */
+#define MAP_PRIVATE 0x002 /* Changes are private */
+#define MAP_TYPE 0x00f /* Mask for type of mapping */
+#define MAP_FIXED 0x010 /* Interpret addr exactly */
+
+/* not used by linux, but here to make sure we don't clash with ABI defines */
+#define MAP_RENAME 0x020 /* Assign page to file */
+#define MAP_AUTOGROW 0x040 /* File may grow by writing */
+#define MAP_LOCAL 0x080 /* Copy on fork/sproc */
+#define MAP_AUTORSRV 0x100 /* Logical swap reserved on demand */
+
+/* These are linux-specific */
+#define MAP_NORESERVE 0x0400 /* don't check for reservations */
+#define MAP_ANONYMOUS 0x0800 /* don't use a file */
+#define MAP_GROWSDOWN 0x1000 /* stack-like segment */
+#define MAP_DENYWRITE 0x2000 /* ETXTBSY */
+#define MAP_EXECUTABLE 0x4000 /* mark it as an executable */
+#define MAP_LOCKED 0x8000 /* pages are locked */
+#define MAP_POPULATE 0x10000 /* populate (prefault) pagetables */
+#define MAP_NONBLOCK 0x20000 /* do not block on IO */
+
+/*
+ * Flags for msync
+ */
+#define MS_ASYNC 0x0001 /* sync memory asynchronously */
+#define MS_INVALIDATE 0x0002 /* invalidate mappings & caches */
+#define MS_SYNC 0x0004 /* synchronous memory sync */
+
+/*
+ * Flags for mlockall
+ */
+#define MCL_CURRENT 1 /* lock all current mappings */
+#define MCL_FUTURE 2 /* lock all future mappings */
+
+#define MADV_NORMAL 0x0 /* default page-in behavior */
+#define MADV_RANDOM 0x1 /* page-in minimum required */
+#define MADV_SEQUENTIAL 0x2 /* read-ahead aggressively */
+#define MADV_WILLNEED 0x3 /* pre-fault pages */
+#define MADV_DONTNEED 0x4 /* discard these pages */
+
+/* compatibility flags */
+#define MAP_ANON MAP_ANONYMOUS
+#define MAP_FILE 0
+
+#endif /* _XTENSA_MMAN_H */
diff --git a/include/asm-xtensa/mmu.h b/include/asm-xtensa/mmu.h
new file mode 100644
index 00000000000..44c5bb04c55
--- /dev/null
+++ b/include/asm-xtensa/mmu.h
@@ -0,0 +1,17 @@
+/*
+ * include/asm-xtensa/mmu.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_MMU_H
+#define _XTENSA_MMU_H
+
+/* Default "unsigned long" context */
+typedef unsigned long mm_context_t;
+
+#endif /* _XTENSA_MMU_H */
diff --git a/include/asm-xtensa/mmu_context.h b/include/asm-xtensa/mmu_context.h
new file mode 100644
index 00000000000..1b0801548cd
--- /dev/null
+++ b/include/asm-xtensa/mmu_context.h
@@ -0,0 +1,330 @@
+/*
+ * include/asm-xtensa/mmu_context.h
+ *
+ * Switch an MMU context.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_MMU_CONTEXT_H
+#define _XTENSA_MMU_CONTEXT_H
+
+#include <linux/config.h>
+#include <linux/stringify.h>
+
+#include <asm/pgtable.h>
+#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+
+/*
+ * Linux was ported to Xtensa assuming all auto-refill ways in set 0
+ * had the same properties (a very likely assumption). Multiple sets
+ * of auto-refill ways will still work properly, but not as optimally
+ * as the Xtensa designer may have assumed.
+ *
+ * We make this case a hard #error, killing the kernel build, to alert
+ * the developer to this condition (which is more likely an error).
+ * You super-duper clever developers can change it to a warning or
+ * remove it altogether if you think you know what you're doing. :)
+ */
+
+#if (XCHAL_HAVE_TLBS != 1)
+# error "Linux must have an MMU!"
+#endif
+
+#if ((XCHAL_ITLB_ARF_WAYS == 0) || (XCHAL_DTLB_ARF_WAYS == 0))
+# error "MMU must have auto-refill ways"
+#endif
+
+#if ((XCHAL_ITLB_ARF_SETS != 1) || (XCHAL_DTLB_ARF_SETS != 1))
+# error Linux may not use all auto-refill ways as efficiently as you think
+#endif
+
+#if (XCHAL_MMU_MAX_PTE_PAGE_SIZE != XCHAL_MMU_MIN_PTE_PAGE_SIZE)
+# error Only one page size allowed!
+#endif
+
+extern unsigned long asid_cache;
+extern pgd_t *current_pgd;
+
+/*
+ * Define the number of entries per auto-refill way in set 0 of both I and D
+ * TLBs. We deal only with set 0 here (an assumption further explained in
+ * assertions.h). Also, define the total number of ARF entries in both TLBs.
+ */
+
+#define ITLB_ENTRIES_PER_ARF_WAY (XCHAL_ITLB_SET(XCHAL_ITLB_ARF_SET0,ENTRIES))
+#define DTLB_ENTRIES_PER_ARF_WAY (XCHAL_DTLB_SET(XCHAL_DTLB_ARF_SET0,ENTRIES))
+
+#define ITLB_ENTRIES \
+ (ITLB_ENTRIES_PER_ARF_WAY * (XCHAL_ITLB_SET(XCHAL_ITLB_ARF_SET0,WAYS)))
+#define DTLB_ENTRIES \
+ (DTLB_ENTRIES_PER_ARF_WAY * (XCHAL_DTLB_SET(XCHAL_DTLB_ARF_SET0,WAYS)))
+
+
+/*
+ * SMALLEST_NTLB_ENTRIES is the smaller of ITLB_ENTRIES and DTLB_ENTRIES.
+ * In practice, they are probably equal. This macro simplifies function
+ * flush_tlb_range().
+ */
+
+#if (DTLB_ENTRIES < ITLB_ENTRIES)
+# define SMALLEST_NTLB_ENTRIES DTLB_ENTRIES
+#else
+# define SMALLEST_NTLB_ENTRIES ITLB_ENTRIES
+#endif
+
+
+/*
+ * asid_cache tracks only the ASID[USER_RING] field of the RASID special
+ * register, which is the current user-task asid allocation value.
+ * mm->context has the same meaning. When it comes time to write the
+ * asid_cache or mm->context values to the RASID special register, we first
+ * shift the value left by 8, then insert the value.
+ * ASID[0] always contains the kernel's asid value, and we reserve three
+ * other asid values that we never assign to user tasks.
+ */
+
+#define ASID_INC 0x1
+#define ASID_MASK ((1 << XCHAL_MMU_ASID_BITS) - 1)
+
+/*
+ * XCHAL_MMU_ASID_INVALID is a configurable Xtensa processor constant
+ * indicating invalid address space. XCHAL_MMU_ASID_KERNEL is a configurable
+ * Xtensa processor constant indicating the kernel address space. They can
+ * be arbitrary values.
+ *
+ * We identify three more unique, reserved ASID values to use in the unused
+ * ring positions. No other user process will be assigned these reserved
+ * ASID values.
+ *
+ * For example, given that
+ *
+ * XCHAL_MMU_ASID_INVALID == 0
+ * XCHAL_MMU_ASID_KERNEL == 1
+ *
+ * the following maze of #if statements would generate
+ *
+ * ASID_RESERVED_1 == 2
+ * ASID_RESERVED_2 == 3
+ * ASID_RESERVED_3 == 4
+ * ASID_FIRST_NONRESERVED == 5
+ */
+
+#if (XCHAL_MMU_ASID_INVALID != XCHAL_MMU_ASID_KERNEL + 1)
+# define ASID_RESERVED_1 ((XCHAL_MMU_ASID_KERNEL + 1) & ASID_MASK)
+#else
+# define ASID_RESERVED_1 ((XCHAL_MMU_ASID_KERNEL + 2) & ASID_MASK)
+#endif
+
+#if (XCHAL_MMU_ASID_INVALID != ASID_RESERVED_1 + 1)
+# define ASID_RESERVED_2 ((ASID_RESERVED_1 + 1) & ASID_MASK)
+#else
+# define ASID_RESERVED_2 ((ASID_RESERVED_1 + 2) & ASID_MASK)
+#endif
+
+#if (XCHAL_MMU_ASID_INVALID != ASID_RESERVED_2 + 1)
+# define ASID_RESERVED_3 ((ASID_RESERVED_2 + 1) & ASID_MASK)
+#else
+# define ASID_RESERVED_3 ((ASID_RESERVED_2 + 2) & ASID_MASK)
+#endif
+
+#if (XCHAL_MMU_ASID_INVALID != ASID_RESERVED_3 + 1)
+# define ASID_FIRST_NONRESERVED ((ASID_RESERVED_3 + 1) & ASID_MASK)
+#else
+# define ASID_FIRST_NONRESERVED ((ASID_RESERVED_3 + 2) & ASID_MASK)
+#endif
+
+#define ASID_ALL_RESERVED ( ((ASID_RESERVED_1) << 24) + \
+ ((ASID_RESERVED_2) << 16) + \
+ ((ASID_RESERVED_3) << 8) + \
+ ((XCHAL_MMU_ASID_KERNEL)) )
+
+
+/*
+ * NO_CONTEXT is the invalid ASID value that we don't ever assign to
+ * any user or kernel context. NO_CONTEXT is a better mnemonic than
+ * XCHAL_MMU_ASID_INVALID, so we use it in code instead.
+ */
+
+#define NO_CONTEXT XCHAL_MMU_ASID_INVALID
+
+#if (KERNEL_RING != 0)
+# error The KERNEL_RING really should be zero.
+#endif
+
+#if (USER_RING >= XCHAL_MMU_RINGS)
+# error USER_RING cannot be greater than the highest numbered ring.
+#endif
+
+#if (USER_RING == KERNEL_RING)
+# error The user and kernel rings really should not be equal.
+#endif
+
+#if (USER_RING == 1)
+#define ASID_INSERT(x) ( ((ASID_RESERVED_1) << 24) + \
+ ((ASID_RESERVED_2) << 16) + \
+ (((x) & (ASID_MASK)) << 8) + \
+ ((XCHAL_MMU_ASID_KERNEL)) )
+
+#elif (USER_RING == 2)
+#define ASID_INSERT(x) ( ((ASID_RESERVED_1) << 24) + \
+ (((x) & (ASID_MASK)) << 16) + \
+ ((ASID_RESERVED_2) << 8) + \
+ ((XCHAL_MMU_ASID_KERNEL)) )
+
+#elif (USER_RING == 3)
+#define ASID_INSERT(x) ( (((x) & (ASID_MASK)) << 24) + \
+ ((ASID_RESERVED_1) << 16) + \
+ ((ASID_RESERVED_2) << 8) + \
+ ((XCHAL_MMU_ASID_KERNEL)) )
+
+#else
+#error Goofy value for USER_RING
+
+#endif /* USER_RING == 1 */
+
+
+/*
+ * All unused by hardware upper bits will be considered
+ * as a software asid extension.
+ */
+
+#define ASID_VERSION_MASK ((unsigned long)~(ASID_MASK|(ASID_MASK-1)))
+#define ASID_FIRST_VERSION \
+ ((unsigned long)(~ASID_VERSION_MASK) + 1 + ASID_FIRST_NONRESERVED)
+
+extern inline void set_rasid_register (unsigned long val)
+{
+ __asm__ __volatile__ (" wsr %0, "__stringify(RASID)"\n\t"
+ " isync\n" : : "a" (val));
+}
+
+extern inline unsigned long get_rasid_register (void)
+{
+ unsigned long tmp;
+ __asm__ __volatile__ (" rsr %0, "__stringify(RASID)"\n\t" : "=a" (tmp));
+ return tmp;
+}
+
+
+#if ((XCHAL_MMU_ASID_INVALID == 0) && (XCHAL_MMU_ASID_KERNEL == 1))
+
+extern inline void
+get_new_mmu_context(struct mm_struct *mm, unsigned long asid)
+{
+ extern void flush_tlb_all(void);
+ if (! ((asid += ASID_INC) & ASID_MASK) ) {
+ flush_tlb_all(); /* start new asid cycle */
+ if (!asid) /* fix version if needed */
+ asid = ASID_FIRST_VERSION - ASID_FIRST_NONRESERVED;
+ asid += ASID_FIRST_NONRESERVED;
+ }
+ mm->context = asid_cache = asid;
+}
+
+#else
+#warning ASID_{INVALID,KERNEL} values impose non-optimal get_new_mmu_context implementation
+
+/* XCHAL_MMU_ASID_INVALID == 0 and XCHAL_MMU_ASID_KERNEL ==1 are
+ really the best, but if you insist... */
+
+extern inline int validate_asid (unsigned long asid)
+{
+ switch (asid) {
+ case XCHAL_MMU_ASID_INVALID:
+ case XCHAL_MMU_ASID_KERNEL:
+ case ASID_RESERVED_1:
+ case ASID_RESERVED_2:
+ case ASID_RESERVED_3:
+ return 0; /* can't use these values as ASIDs */
+ }
+ return 1; /* valid */
+}
+
+extern inline void
+get_new_mmu_context(struct mm_struct *mm, unsigned long asid)
+{
+ extern void flush_tlb_all(void);
+ while (1) {
+ asid += ASID_INC;
+ if ( ! (asid & ASID_MASK) ) {
+ flush_tlb_all(); /* start new asid cycle */
+ if (!asid) /* fix version if needed */
+ asid = ASID_FIRST_VERSION - ASID_FIRST_NONRESERVED;
+ asid += ASID_FIRST_NONRESERVED;
+ break; /* no need to validate here */
+ }
+ if (validate_asid (asid & ASID_MASK))
+ break;
+ }
+ mm->context = asid_cache = asid;
+}
+
+#endif
+
+
+/*
+ * Initialize the context related info for a new mm_struct
+ * instance.
+ */
+
+extern inline int
+init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+ mm->context = NO_CONTEXT;
+ return 0;
+}
+
+extern inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+ struct task_struct *tsk)
+{
+ unsigned long asid = asid_cache;
+
+ /* Check if our ASID is of an older version and thus invalid */
+
+ if ((next->context ^ asid) & ASID_VERSION_MASK)
+ get_new_mmu_context(next, asid);
+
+ set_rasid_register (ASID_INSERT(next->context));
+ invalidate_page_directory();
+}
+
+#define deactivate_mm(tsk, mm) do { } while(0)
+
+/*
+ * Destroy context related info for an mm_struct that is about
+ * to be put to rest.
+ */
+extern inline void destroy_context(struct mm_struct *mm)
+{
+ /* Nothing to do. */
+}
+
+/*
+ * After we have set current->mm to a new value, this activates
+ * the context for the new mm so we see the new mappings.
+ */
+extern inline void
+activate_mm(struct mm_struct *prev, struct mm_struct *next)
+{
+ /* Unconditionally get a new ASID. */
+
+ get_new_mmu_context(next, asid_cache);
+ set_rasid_register (ASID_INSERT(next->context));
+ invalidate_page_directory();
+}
+
+
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+{
+ /* Nothing to do. */
+
+}
+
+#endif /* _XTENSA_MMU_CONTEXT_H */
diff --git a/include/asm-xtensa/module.h b/include/asm-xtensa/module.h
new file mode 100644
index 00000000000..ffb25bfdf6a
--- /dev/null
+++ b/include/asm-xtensa/module.h
@@ -0,0 +1,25 @@
+/*
+ * include/asm-xtensa/module.h
+ *
+ * This file contains the module code specific to the Xtensa architecture.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_MODULE_H
+#define _XTENSA_MODULE_H
+
+struct mod_arch_specific
+{
+ /* Module support is not completely implemented. */
+};
+
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Ehdr Elf32_Ehdr
+
+#endif /* _XTENSA_MODULE_H */
diff --git a/include/asm-xtensa/msgbuf.h b/include/asm-xtensa/msgbuf.h
new file mode 100644
index 00000000000..693c9675528
--- /dev/null
+++ b/include/asm-xtensa/msgbuf.h
@@ -0,0 +1,48 @@
+/*
+ * include/asm-xtensa/msgbuf.h
+ *
+ * The msqid64_ds structure for the Xtensa architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ */
+
+#ifndef _XTENSA_MSGBUF_H
+#define _XTENSA_MSGBUF_H
+
+struct msqid64_ds {
+ struct ipc64_perm msg_perm;
+#ifdef __XTENSA_EB__
+ unsigned int __unused1;
+ __kernel_time_t msg_stime; /* last msgsnd time */
+ unsigned int __unused2;
+ __kernel_time_t msg_rtime; /* last msgrcv time */
+ unsigned int __unused3;
+ __kernel_time_t msg_ctime; /* last change time */
+#elif defined(__XTENSA_EL__)
+ __kernel_time_t msg_stime; /* last msgsnd time */
+ unsigned int __unused1;
+ __kernel_time_t msg_rtime; /* last msgrcv time */
+ unsigned int __unused2;
+ __kernel_time_t msg_ctime; /* last change time */
+ unsigned int __unused3;
+#else
+# error processor byte order undefined!
+#endif
+ unsigned long msg_cbytes; /* current number of bytes on queue */
+ unsigned long msg_qnum; /* number of messages in queue */
+ unsigned long msg_qbytes; /* max number of bytes on queue */
+ __kernel_pid_t msg_lspid; /* pid of last msgsnd */
+ __kernel_pid_t msg_lrpid; /* last receive pid */
+ unsigned long __unused4;
+ unsigned long __unused5;
+};
+
+#endif /* _XTENSA_MSGBUF_H */
diff --git a/include/asm-xtensa/namei.h b/include/asm-xtensa/namei.h
new file mode 100644
index 00000000000..3fdff039d27
--- /dev/null
+++ b/include/asm-xtensa/namei.h
@@ -0,0 +1,26 @@
+/*
+ * include/asm-xtensa/namei.h
+ *
+ * Included from linux/fs/namei.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_NAMEI_H
+#define _XTENSA_NAMEI_H
+
+#ifdef __KERNEL__
+
+/* This dummy routine maybe changed to something useful
+ * for /usr/gnemul/ emulation stuff.
+ * Look at asm-sparc/namei.h for details.
+ */
+
+#define __emul_prefix() NULL
+
+#endif /* __KERNEL__ */
+#endif /* _XTENSA_NAMEI_H */
diff --git a/include/asm-xtensa/page.h b/include/asm-xtensa/page.h
new file mode 100644
index 00000000000..b495e5b5a94
--- /dev/null
+++ b/include/asm-xtensa/page.h
@@ -0,0 +1,133 @@
+/*
+ * linux/include/asm-xtensa/page.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version2 as
+ * published by the Free Software Foundation.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_PAGE_H
+#define _XTENSA_PAGE_H
+
+#ifdef __KERNEL__
+
+#include <asm/processor.h>
+#include <linux/config.h>
+
+/*
+ * PAGE_SHIFT determines the page size
+ * PAGE_ALIGN(x) aligns the pointer to the (next) page boundary
+ */
+
+#define PAGE_SHIFT XCHAL_MMU_MIN_PTE_PAGE_SIZE
+#define PAGE_SIZE (1 << PAGE_SHIFT)
+#define PAGE_MASK (~(PAGE_SIZE-1))
+#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE - 1) & PAGE_MASK)
+
+#define DCACHE_WAY_SIZE (XCHAL_DCACHE_SIZE / XCHAL_DCACHE_WAYS)
+#define PAGE_OFFSET XCHAL_KSEG_CACHED_VADDR
+
+#ifdef __ASSEMBLY__
+
+#define __pgprot(x) (x)
+
+#else
+
+/*
+ * These are used to make use of C type-checking..
+ */
+
+typedef struct { unsigned long pte; } pte_t; /* page table entry */
+typedef struct { unsigned long pgd; } pgd_t; /* PGD table entry */
+typedef struct { unsigned long pgprot; } pgprot_t;
+
+#define pte_val(x) ((x).pte)
+#define pgd_val(x) ((x).pgd)
+#define pgprot_val(x) ((x).pgprot)
+
+#define __pte(x) ((pte_t) { (x) } )
+#define __pgd(x) ((pgd_t) { (x) } )
+#define __pgprot(x) ((pgprot_t) { (x) } )
+
+/*
+ * Pure 2^n version of get_order
+ */
+
+extern __inline__ int get_order(unsigned long size)
+{
+ int order;
+#ifndef XCHAL_HAVE_NSU
+ unsigned long x1, x2, x4, x8, x16;
+
+ size = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ x1 = size & 0xAAAAAAAA;
+ x2 = size & 0xCCCCCCCC;
+ x4 = size & 0xF0F0F0F0;
+ x8 = size & 0xFF00FF00;
+ x16 = size & 0xFFFF0000;
+ order = x2 ? 2 : 0;
+ order += (x16 != 0) * 16;
+ order += (x8 != 0) * 8;
+ order += (x4 != 0) * 4;
+ order += (x1 != 0);
+
+ return order;
+#else
+ size = (size - 1) >> PAGE_SHIFT;
+ asm ("nsau %0, %1" : "=r" (order) : "r" (size));
+ return 32 - order;
+#endif
+}
+
+
+struct page;
+extern void clear_page(void *page);
+extern void copy_page(void *to, void *from);
+
+/*
+ * If we have cache aliasing and writeback caches, we might have to do
+ * some extra work
+ */
+
+#if (DCACHE_WAY_SIZE > PAGE_SIZE)
+void clear_user_page(void *addr, unsigned long vaddr, struct page* page);
+void copy_user_page(void *to,void* from,unsigned long vaddr,struct page* page);
+#else
+# define clear_user_page(page,vaddr,pg) clear_page(page)
+# define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
+#endif
+
+/*
+ * This handles the memory map. We handle pages at
+ * XCHAL_KSEG_CACHED_VADDR for kernels with 32 bit address space.
+ * These macros are for conversion of kernel address, not user
+ * addresses.
+ */
+
+#define __pa(x) ((unsigned long) (x) - PAGE_OFFSET)
+#define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET))
+#define pfn_valid(pfn) ((unsigned long)pfn < max_mapnr)
+#ifndef CONFIG_DISCONTIGMEM
+# define pfn_to_page(pfn) (mem_map + (pfn))
+# define page_to_pfn(page) ((unsigned long)((page) - mem_map))
+#else
+# error CONFIG_DISCONTIGMEM not supported
+#endif
+
+#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+#define page_to_virt(page) __va(page_to_pfn(page) << PAGE_SHIFT)
+#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
+
+#define WANT_PAGE_VIRTUAL
+
+
+#endif /* __ASSEMBLY__ */
+
+#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#endif /* __KERNEL__ */
+#endif /* _XTENSA_PAGE_H */
diff --git a/include/asm-xtensa/page.h.n b/include/asm-xtensa/page.h.n
new file mode 100644
index 00000000000..546cc6624f2
--- /dev/null
+++ b/include/asm-xtensa/page.h.n
@@ -0,0 +1,135 @@
+/*
+ * linux/include/asm-xtensa/page.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version2 as
+ * published by the Free Software Foundation.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_PAGE_H
+#define _XTENSA_PAGE_H
+
+#ifdef __KERNEL__
+
+#include <asm/processor.h>
+#include <linux/config.h>
+
+/*
+ * PAGE_SHIFT determines the page size
+ * PAGE_ALIGN(x) aligns the pointer to the (next) page boundary
+ */
+#define PAGE_SHIFT XCHAL_MMU_MIN_PTE_PAGE_SIZE
+#define PAGE_SIZE (1 << PAGE_SHIFT)
+#define PAGE_MASK (~(PAGE_SIZE-1))
+#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE - 1) & PAGE_MASK)
+
+#define DCACHE_WAY_SIZE (XCHAL_DCACHE_SIZE / XCHAL_DCACHE_WAYS)
+#define PAGE_OFFSET XCHAL_KSEG_CACHED_VADDR
+
+#ifdef __ASSEMBLY__
+
+#define __pgprot(x) (x)
+
+#else
+
+
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { unsigned long pte; } pte_t; /* page table entry */
+typedef struct { unsigned long pmd; } pmd_t; /* PMD table entry */
+typedef struct { unsigned long pgd; } pgd_t; /* PGD table entry */
+typedef struct { unsigned long pgprot; } pgprot_t;
+
+#define pte_val(x) ((x).pte)
+#define pmd_val(x) ((x).pmd)
+#define pgd_val(x) ((x).pgd)
+#define pgprot_val(x) ((x).pgprot)
+
+#define __pte(x) ((pte_t) { (x) } )
+#define __pmd(x) ((pmd_t) { (x) } )
+#define __pgd(x) ((pgd_t) { (x) } )
+#define __pgprot(x) ((pgprot_t) { (x) } )
+
+/*
+ * Pure 2^n version of get_order
+ */
+extern __inline__ int get_order(unsigned long size)
+{
+ int order;
+#ifndef XCHAL_HAVE_NSU
+ unsigned long x1, x2, x4, x8, x16;
+
+ size = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ x1 = size & 0xAAAAAAAA;
+ x2 = size & 0xCCCCCCCC;
+ x4 = size & 0xF0F0F0F0;
+ x8 = size & 0xFF00FF00;
+ x16 = size & 0xFFFF0000;
+ order = x2 ? 2 : 0;
+ order += (x16 != 0) * 16;
+ order += (x8 != 0) * 8;
+ order += (x4 != 0) * 4;
+ order += (x1 != 0);
+
+ return order;
+#else
+ size = (size - 1) >> PAGE_SHIFT;
+ asm ("nsau %0, %1" : "=r" (order) : "r" (size));
+ return 32 - order;
+#endif
+}
+
+
+struct page;
+extern void clear_page(void *page);
+extern void copy_page(void *to, void *from);
+
+/*
+ * If we have cache aliasing and writeback caches, we might have to do
+ * some extra work
+ */
+
+#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
+void clear_user_page(void *addr, unsigned long vaddr, struct page* page);
+void copy_user_page(void *to, void* from, unsigned long vaddr, struct page* page);
+#else
+# define clear_user_page(page,vaddr,pg) clear_page(page)
+# define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
+#endif
+
+
+/*
+ * This handles the memory map. We handle pages at
+ * XCHAL_KSEG_CACHED_VADDR for kernels with 32 bit address space.
+ * These macros are for conversion of kernel address, not user
+ * addresses.
+ */
+
+#define __pa(x) ((unsigned long) (x) - PAGE_OFFSET)
+#define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET))
+#define pfn_valid(pfn) ((unsigned long)pfn < max_mapnr)
+#ifndef CONFIG_DISCONTIGMEM
+# define pfn_to_page(pfn) (mem_map + (pfn))
+# define page_to_pfn(page) ((unsigned long)((page) - mem_map))
+#else
+# error CONFIG_DISCONTIGMEM not supported
+#endif
+
+#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+#define page_to_virt(page) __va(page_to_pfn(page) << PAGE_SHIFT)
+#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
+
+#define WANT_PAGE_VIRTUAL
+
+
+#endif /* __ASSEMBLY__ */
+
+#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#endif /* __KERNEL__ */
+#endif /* _XTENSA_PAGE_H */
diff --git a/include/asm-xtensa/param.h b/include/asm-xtensa/param.h
new file mode 100644
index 00000000000..c0eec8260b0
--- /dev/null
+++ b/include/asm-xtensa/param.h
@@ -0,0 +1,34 @@
+/*
+ * include/asm-xtensa/param.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_PARAM_H
+#define _XTENSA_PARAM_H
+
+#include <xtensa/config/core.h>
+
+#ifdef __KERNEL__
+# define HZ 100 /* internal timer frequency */
+# define USER_HZ 100 /* for user interfaces in "ticks" */
+# define CLOCKS_PER_SEC (USER_HZ) /* frequnzy at which times() counts */
+#endif
+
+#define EXEC_PAGESIZE (1 << XCHAL_MMU_MIN_PTE_PAGE_SIZE)
+
+#ifndef NGROUPS
+#define NGROUPS 32
+#endif
+
+#ifndef NOGROUP
+#define NOGROUP (-1)
+#endif
+
+#define MAXHOSTNAMELEN 64 /* max length of hostname */
+
+#endif /* _XTENSA_PARAM_H */
diff --git a/include/asm-xtensa/pci-bridge.h b/include/asm-xtensa/pci-bridge.h
new file mode 100644
index 00000000000..00fcbd7c534
--- /dev/null
+++ b/include/asm-xtensa/pci-bridge.h
@@ -0,0 +1,88 @@
+/*
+ * include/asm-xtensa/pci-bridge.h
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ *
+ * Copyright (C) 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_PCI_BRIDGE_H
+#define _XTENSA_PCI_BRIDGE_H
+
+#ifdef __KERNEL__
+
+struct device_node;
+struct pci_controller;
+
+/*
+ * pciauto_bus_scan() enumerates the pci space.
+ */
+
+extern int pciauto_bus_scan(struct pci_controller *, int);
+
+struct pci_space {
+ unsigned long start;
+ unsigned long end;
+ unsigned long base;
+};
+
+/*
+ * Structure of a PCI controller (host bridge)
+ */
+
+struct pci_controller {
+ int index; /* used for pci_controller_num */
+ struct pci_controller *next;
+ struct pci_bus *bus;
+ void *arch_data;
+
+ int first_busno;
+ int last_busno;
+
+ struct pci_ops *ops;
+ volatile unsigned int *cfg_addr;
+ volatile unsigned char *cfg_data;
+
+ /* Currently, we limit ourselves to 1 IO range and 3 mem
+ * ranges since the common pci_bus structure can't handle more
+ */
+ struct resource io_resource;
+ struct resource mem_resources[3];
+ int mem_resource_count;
+
+ /* Host bridge I/O and Memory space
+ * Used for BAR placement algorithms
+ */
+ struct pci_space io_space;
+ struct pci_space mem_space;
+
+ /* Return the interrupt number fo a device. */
+ int (*map_irq)(struct pci_dev*, u8, u8);
+
+};
+
+static inline void pcibios_init_resource(struct resource *res,
+ unsigned long start, unsigned long end, int flags, char *name)
+{
+ res->start = start;
+ res->end = end;
+ res->flags = flags;
+ res->name = name;
+ res->parent = NULL;
+ res->sibling = NULL;
+ res->child = NULL;
+}
+
+
+/* These are used for config access before all the PCI probing has been done. */
+int early_read_config_byte(struct pci_controller*, int, int, int, u8*);
+int early_read_config_word(struct pci_controller*, int, int, int, u16*);
+int early_read_config_dword(struct pci_controller*, int, int, int, u32*);
+int early_write_config_byte(struct pci_controller*, int, int, int, u8);
+int early_write_config_word(struct pci_controller*, int, int, int, u16);
+int early_write_config_dword(struct pci_controller*, int, int, int, u32);
+
+#endif /* __KERNEL__ */
+#endif /* _XTENSA_PCI_BRIDGE_H */
diff --git a/include/asm-xtensa/pci.h b/include/asm-xtensa/pci.h
new file mode 100644
index 00000000000..6817742301c
--- /dev/null
+++ b/include/asm-xtensa/pci.h
@@ -0,0 +1,89 @@
+/*
+ * linux/include/asm-xtensa/pci.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_PCI_H
+#define _XTENSA_PCI_H
+
+#ifdef __KERNEL__
+
+/* Can be used to override the logic in pci_scan_bus for skipping
+ * already-configured bus numbers - to be used for buggy BIOSes
+ * or architectures with incomplete PCI setup by the loader
+ */
+
+#define pcibios_assign_all_busses() 0
+
+extern struct pci_controller* pcibios_alloc_controller(void);
+
+extern inline void pcibios_set_master(struct pci_dev *dev)
+{
+ /* No special bus mastering setup handling */
+}
+
+extern inline void pcibios_penalize_isa_irq(int irq)
+{
+ /* We don't do dynamic PCI IRQ allocation */
+}
+
+/* Assume some values. (We should revise them, if necessary) */
+
+#define PCIBIOS_MIN_IO 0x2000
+#define PCIBIOS_MIN_MEM 0x10000000
+
+/* Dynamic DMA mapping stuff.
+ * Xtensa has everything mapped statically like x86.
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <asm/scatterlist.h>
+#include <linux/string.h>
+#include <asm/io.h>
+
+struct pci_dev;
+
+/* The PCI address space does equal the physical memory address space.
+ * The networking and block device layers use this boolean for bounce buffer
+ * decisions.
+ */
+
+#define PCI_DMA_BUS_IS_PHYS (1)
+
+/* pci_unmap_{page,single} is a no-op, so */
+#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
+#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
+#define pci_unmap_addr(PTR, ADDR_NAME) (0)
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0)
+#define pci_ubnmap_len(PTR, LEN_NAME) (0)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
+
+/* We cannot access memory above 4GB */
+#define pci_dac_dma_supported(pci_dev, mask) (0)
+
+/* Map a range of PCI memory or I/O space for a device into user space */
+int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
+ enum pci_mmap_state mmap_state, int write_combine);
+
+/* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */
+#define HAVE_PCI_MMAP 1
+
+static inline void pcibios_add_platform_entries(struct pci_dev *dev)
+{
+}
+
+#endif /* __KERNEL__ */
+
+/* Implement the pci_ DMA API in terms of the generic device dma_ one */
+#include <asm-generic/pci-dma-compat.h>
+
+/* Generic PCI */
+#include <asm-generic/pci.h>
+
+#endif /* _XTENSA_PCI_H */
diff --git a/include/asm-xtensa/percpu.h b/include/asm-xtensa/percpu.h
new file mode 100644
index 00000000000..6d2bc2ada9d
--- /dev/null
+++ b/include/asm-xtensa/percpu.h
@@ -0,0 +1,16 @@
+/*
+ * linux/include/asm-xtensa/percpu.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_PERCPU__
+#define _XTENSA_PERCPU__
+
+#include <asm-generic/percpu.h>
+
+#endif /* _XTENSA_PERCPU__ */
diff --git a/include/asm-xtensa/pgalloc.h b/include/asm-xtensa/pgalloc.h
new file mode 100644
index 00000000000..734a8d06039
--- /dev/null
+++ b/include/asm-xtensa/pgalloc.h
@@ -0,0 +1,116 @@
+/*
+ * linux/include/asm-xtensa/pgalloc.h
+ *
+ * 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.
+ *
+ * Copyright (C) 2001-2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_PGALLOC_H
+#define _XTENSA_PGALLOC_H
+
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <linux/highmem.h>
+#include <asm/processor.h>
+#include <asm/cacheflush.h>
+
+
+/* Cache aliasing:
+ *
+ * If the cache size for one way is greater than the page size, we have to
+ * deal with cache aliasing. The cache index is wider than the page size:
+ *
+ * |cache |
+ * |pgnum |page| virtual address
+ * |xxxxxX|zzzz|
+ * | | |
+ * \ / | |
+ * trans.| |
+ * / \ | |
+ * |yyyyyY|zzzz| physical address
+ *
+ * When the page number is translated to the physical page address, the lowest
+ * bit(s) (X) that are also part of the cache index are also translated (Y).
+ * If this translation changes this bit (X), the cache index is also afected,
+ * thus resulting in a different cache line than before.
+ * The kernel does not provide a mechanism to ensure that the page color
+ * (represented by this bit) remains the same when allocated or when pages
+ * are remapped. When user pages are mapped into kernel space, the color of
+ * the page might also change.
+ *
+ * We use the address space VMALLOC_END ... VMALLOC_END + DCACHE_WAY_SIZE * 2
+ * to temporarily map a patch so we can match the color.
+ */
+
+#if (DCACHE_WAY_SIZE > PAGE_SIZE)
+# define PAGE_COLOR_MASK (PAGE_MASK & (DCACHE_WAY_SIZE-1))
+# define PAGE_COLOR(a) \
+ (((unsigned long)(a)&PAGE_COLOR_MASK) >> PAGE_SHIFT)
+# define PAGE_COLOR_EQ(a,b) \
+ ((((unsigned long)(a) ^ (unsigned long)(b)) & PAGE_COLOR_MASK) == 0)
+# define PAGE_COLOR_MAP0(v) \
+ (VMALLOC_END + ((unsigned long)(v) & PAGE_COLOR_MASK))
+# define PAGE_COLOR_MAP1(v) \
+ (VMALLOC_END + ((unsigned long)(v) & PAGE_COLOR_MASK) + DCACHE_WAY_SIZE)
+#endif
+
+/*
+ * Allocating and freeing a pmd is trivial: the 1-entry pmd is
+ * inside the pgd, so has no extra memory associated with it.
+ */
+
+#define pgd_free(pgd) free_page((unsigned long)(pgd))
+
+#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
+
+static inline void
+pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *pte)
+{
+ pmd_val(*(pmdp)) = (unsigned long)(pte);
+ __asm__ __volatile__ ("memw; dhwb %0, 0; dsync" :: "a" (pmdp));
+}
+
+static inline void
+pmd_populate(struct mm_struct *mm, pmd_t *pmdp, struct page *page)
+{
+ pmd_val(*(pmdp)) = (unsigned long)page_to_virt(page);
+ __asm__ __volatile__ ("memw; dhwb %0, 0; dsync" :: "a" (pmdp));
+}
+
+
+
+#else
+
+# define pmd_populate_kernel(mm, pmdp, pte) \
+ (pmd_val(*(pmdp)) = (unsigned long)(pte))
+# define pmd_populate(mm, pmdp, page) \
+ (pmd_val(*(pmdp)) = (unsigned long)page_to_virt(page))
+
+#endif
+
+static inline pgd_t*
+pgd_alloc(struct mm_struct *mm)
+{
+ pgd_t *pgd;
+
+ pgd = (pgd_t *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, PGD_ORDER);
+
+ if (likely(pgd != NULL))
+ __flush_dcache_page((unsigned long)pgd);
+
+ return pgd;
+}
+
+extern pte_t* pte_alloc_one_kernel(struct mm_struct* mm, unsigned long addr);
+extern struct page* pte_alloc_one(struct mm_struct* mm, unsigned long addr);
+
+#define pte_free_kernel(pte) free_page((unsigned long)pte)
+#define pte_free(pte) __free_page(pte)
+
+#endif /* __KERNEL__ */
+#endif /* _XTENSA_PGALLOC_H */
diff --git a/include/asm-xtensa/pgtable.h b/include/asm-xtensa/pgtable.h
new file mode 100644
index 00000000000..0bb6416ae26
--- /dev/null
+++ b/include/asm-xtensa/pgtable.h
@@ -0,0 +1,468 @@
+/*
+ * linux/include/asm-xtensa/page.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version2 as
+ * published by the Free Software Foundation.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_PGTABLE_H
+#define _XTENSA_PGTABLE_H
+
+#include <asm-generic/pgtable-nopmd.h>
+#include <asm/page.h>
+
+/* Assertions. */
+
+#ifdef CONFIG_MMU
+
+
+#if (XCHAL_MMU_RINGS < 2)
+# error Linux build assumes at least 2 ring levels.
+#endif
+
+#if (XCHAL_MMU_CA_BITS != 4)
+# error We assume exactly four bits for CA.
+#endif
+
+#if (XCHAL_MMU_SR_BITS != 0)
+# error We have no room for SR bits.
+#endif
+
+/*
+ * Use the first min-wired way for mapping page-table pages.
+ * Page coloring requires a second min-wired way.
+ */
+
+#if (XCHAL_DTLB_MINWIRED_SETS == 0)
+# error Need a min-wired way for mapping page-table pages
+#endif
+
+#define DTLB_WAY_PGTABLE XCHAL_DTLB_SET(XCHAL_DTLB_MINWIRED_SET0, WAY)
+
+#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
+# if XCHAL_DTLB_SET(XCHAL_DTLB_MINWIRED_SET0, WAYS) >= 2
+# define DTLB_WAY_DCACHE_ALIAS0 (DTLB_WAY_PGTABLE + 1)
+# define DTLB_WAY_DCACHE_ALIAS1 (DTLB_WAY_PGTABLE + 2)
+# else
+# error Page coloring requires its own wired dtlb way!
+# endif
+#endif
+
+#endif /* CONFIG_MMU */
+
+/*
+ * We only use two ring levels, user and kernel space.
+ */
+
+#define USER_RING 1 /* user ring level */
+#define KERNEL_RING 0 /* kernel ring level */
+
+/*
+ * The Xtensa architecture port of Linux has a two-level page table system,
+ * i.e. the logical three-level Linux page table layout are folded.
+ * Each task has the following memory page tables:
+ *
+ * PGD table (page directory), ie. 3rd-level page table:
+ * One page (4 kB) of 1024 (PTRS_PER_PGD) pointers to PTE tables
+ * (Architectures that don't have the PMD folded point to the PMD tables)
+ *
+ * The pointer to the PGD table for a given task can be retrieved from
+ * the task structure (struct task_struct*) t, e.g. current():
+ * (t->mm ? t->mm : t->active_mm)->pgd
+ *
+ * PMD tables (page middle-directory), ie. 2nd-level page tables:
+ * Absent for the Xtensa architecture (folded, PTRS_PER_PMD == 1).
+ *
+ * PTE tables (page table entry), ie. 1st-level page tables:
+ * One page (4 kB) of 1024 (PTRS_PER_PTE) PTEs with a special PTE
+ * invalid_pte_table for absent mappings.
+ *
+ * The individual pages are 4 kB big with special pages for the empty_zero_page.
+ */
+#define PGDIR_SHIFT 22
+#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
+#define PGDIR_MASK (~(PGDIR_SIZE-1))
+
+/*
+ * Entries per page directory level: we use two-level, so
+ * we don't really have any PMD directory physically.
+ */
+#define PTRS_PER_PTE 1024
+#define PTRS_PER_PTE_SHIFT 10
+#define PTRS_PER_PMD 1
+#define PTRS_PER_PGD 1024
+#define PGD_ORDER 0
+#define PMD_ORDER 0
+#define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE)
+#define FIRST_USER_ADDRESS XCHAL_SEG_MAPPABLE_VADDR
+#define FIRST_USER_PGD_NR (FIRST_USER_ADDRESS >> PGDIR_SHIFT)
+
+/* virtual memory area. We keep a distance to other memory regions to be
+ * on the safe side. We also use this area for cache aliasing.
+ */
+
+// FIXME: virtual memory area must be configuration-dependent
+
+#define VMALLOC_START 0xC0000000
+#define VMALLOC_END 0xC7FF0000
+
+/* Xtensa Linux config PTE layout (when present):
+ * 31-12: PPN
+ * 11-6: Software
+ * 5-4: RING
+ * 3-0: CA
+ *
+ * Similar to the Alpha and MIPS ports, we need to keep track of the ref
+ * and mod bits in software. We have a software "you can read
+ * from this page" bit, and a hardware one which actually lets the
+ * process read from the page. On the same token we have a software
+ * writable bit and the real hardware one which actually lets the
+ * process write to the page.
+ *
+ * See further below for PTE layout for swapped-out pages.
+ */
+
+#define _PAGE_VALID (1<<0) /* hardware: page is accessible */
+#define _PAGE_WRENABLE (1<<1) /* hardware: page is writable */
+
+/* None of these cache modes include MP coherency: */
+#define _PAGE_NO_CACHE (0<<2) /* bypass, non-speculative */
+#if XCHAL_DCACHE_IS_WRITEBACK
+# define _PAGE_WRITEBACK (1<<2) /* write back */
+# define _PAGE_WRITETHRU (2<<2) /* write through */
+#else
+# define _PAGE_WRITEBACK (1<<2) /* assume write through */
+# define _PAGE_WRITETHRU (1<<2)
+#endif
+#define _PAGE_NOALLOC (3<<2) /* don't allocate cache,if not cached */
+#define _CACHE_MASK (3<<2)
+
+#define _PAGE_USER (1<<4) /* user access (ring=1) */
+#define _PAGE_KERNEL (0<<4) /* kernel access (ring=0) */
+
+/* Software */
+#define _PAGE_RW (1<<6) /* software: page writable */
+#define _PAGE_DIRTY (1<<7) /* software: page dirty */
+#define _PAGE_ACCESSED (1<<8) /* software: page accessed (read) */
+#define _PAGE_FILE (1<<9) /* nonlinear file mapping*/
+
+#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _CACHE_MASK | _PAGE_DIRTY)
+#define _PAGE_PRESENT ( _PAGE_VALID | _PAGE_WRITEBACK | _PAGE_ACCESSED)
+
+#ifdef CONFIG_MMU
+
+# define PAGE_NONE __pgprot(_PAGE_PRESENT)
+# define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_RW)
+# define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER)
+# define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER)
+# define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_KERNEL | _PAGE_WRENABLE)
+# define PAGE_INVALID __pgprot(_PAGE_USER)
+
+# if (DCACHE_WAY_SIZE > PAGE_SIZE)
+# define PAGE_DIRECTORY __pgprot(_PAGE_VALID | _PAGE_ACCESSED | _PAGE_KERNEL)
+# else
+# define PAGE_DIRECTORY __pgprot(_PAGE_PRESENT | _PAGE_KERNEL)
+# endif
+
+#else /* no mmu */
+
+# define PAGE_NONE __pgprot(0)
+# define PAGE_SHARED __pgprot(0)
+# define PAGE_COPY __pgprot(0)
+# define PAGE_READONLY __pgprot(0)
+# define PAGE_KERNEL __pgprot(0)
+
+#endif
+
+/*
+ * On certain configurations of Xtensa MMUs (eg. the initial Linux config),
+ * the MMU can't do page protection for execute, and considers that the same as
+ * read. Also, write permissions may imply read permissions.
+ * What follows is the closest we can get by reasonable means..
+ * See linux/mm/mmap.c for protection_map[] array that uses these definitions.
+ */
+#define __P000 PAGE_NONE /* private --- */
+#define __P001 PAGE_READONLY /* private --r */
+#define __P010 PAGE_COPY /* private -w- */
+#define __P011 PAGE_COPY /* private -wr */
+#define __P100 PAGE_READONLY /* private x-- */
+#define __P101 PAGE_READONLY /* private x-r */
+#define __P110 PAGE_COPY /* private xw- */
+#define __P111 PAGE_COPY /* private xwr */
+
+#define __S000 PAGE_NONE /* shared --- */
+#define __S001 PAGE_READONLY /* shared --r */
+#define __S010 PAGE_SHARED /* shared -w- */
+#define __S011 PAGE_SHARED /* shared -wr */
+#define __S100 PAGE_READONLY /* shared x-- */
+#define __S101 PAGE_READONLY /* shared x-r */
+#define __S110 PAGE_SHARED /* shared xw- */
+#define __S111 PAGE_SHARED /* shared xwr */
+
+#ifndef __ASSEMBLY__
+
+#define pte_ERROR(e) \
+ printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
+#define pgd_ERROR(e) \
+ printk("%s:%d: bad pgd entry %08lx.\n", __FILE__, __LINE__, pgd_val(e))
+
+extern unsigned long empty_zero_page[1024];
+
+#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+
+extern pgd_t swapper_pg_dir[PAGE_SIZE/sizeof(pgd_t)];
+
+/*
+ * The pmd contains the kernel virtual address of the pte page.
+ */
+#define pmd_page_kernel(pmd) ((unsigned long)(pmd_val(pmd) & PAGE_MASK))
+#define pmd_page(pmd) virt_to_page(pmd_val(pmd))
+
+/*
+ * The following only work if pte_present() is true.
+ */
+#define pte_none(pte) (!(pte_val(pte) ^ _PAGE_USER))
+#define pte_present(pte) (pte_val(pte) & _PAGE_VALID)
+#define pte_clear(mm,addr,ptep) \
+ do { update_pte(ptep, __pte(_PAGE_USER)); } while(0)
+
+#define pmd_none(pmd) (!pmd_val(pmd))
+#define pmd_present(pmd) (pmd_val(pmd) & PAGE_MASK)
+#define pmd_clear(pmdp) do { set_pmd(pmdp, __pmd(0)); } while (0)
+#define pmd_bad(pmd) (pmd_val(pmd) & ~PAGE_MASK)
+
+/* Note: We use the _PAGE_USER bit to indicate write-protect kernel memory */
+
+static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
+static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
+static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
+static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
+static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; }
+static inline pte_t pte_wrprotect(pte_t pte) { pte_val(pte) &= ~(_PAGE_RW | _PAGE_WRENABLE); return pte; }
+static inline pte_t pte_rdprotect(pte_t pte) { pte_val(pte) &= ~_PAGE_USER; return pte; }
+static inline pte_t pte_mkclean(pte_t pte) { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
+static inline pte_t pte_mkold(pte_t pte) { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
+static inline pte_t pte_mkread(pte_t pte) { pte_val(pte) |= _PAGE_USER; return pte; }
+static inline pte_t pte_mkdirty(pte_t pte) { pte_val(pte) |= _PAGE_DIRTY; return pte; }
+static inline pte_t pte_mkyoung(pte_t pte) { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
+static inline pte_t pte_mkwrite(pte_t pte) { pte_val(pte) |= _PAGE_RW; return pte; }
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+#define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT)
+#define pte_same(a,b) (pte_val(a) == pte_val(b))
+#define pte_page(x) pfn_to_page(pte_pfn(x))
+#define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+#define mk_pte(page, prot) pfn_pte(page_to_pfn(page), prot)
+
+extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+ return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
+}
+
+/*
+ * Certain architectures need to do special things when pte's
+ * within a page table are directly modified. Thus, the following
+ * hook is made available.
+ */
+static inline void update_pte(pte_t *ptep, pte_t pteval)
+{
+ *ptep = pteval;
+#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
+ __asm__ __volatile__ ("memw; dhwb %0, 0; dsync" :: "a" (ptep));
+#endif
+}
+
+extern inline void
+set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pteval)
+{
+ update_pte(ptep, pteval);
+}
+
+
+extern inline void
+set_pmd(pmd_t *pmdp, pmd_t pmdval)
+{
+ *pmdp = pmdval;
+#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
+ __asm__ __volatile__ ("memw; dhwb %0, 0; dsync" :: "a" (pmdp));
+#endif
+}
+
+
+static inline int
+ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr,
+ pte_t *ptep)
+{
+ pte_t pte = *ptep;
+ if (!pte_young(pte))
+ return 0;
+ update_pte(ptep, pte_mkold(pte));
+ return 1;
+}
+
+static inline int
+ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr,
+ pte_t *ptep)
+{
+ pte_t pte = *ptep;
+ if (!pte_dirty(pte))
+ return 0;
+ update_pte(ptep, pte_mkclean(pte));
+ return 1;
+}
+
+static inline pte_t
+ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+ pte_t pte = *ptep;
+ pte_clear(mm, addr, ptep);
+ return pte;
+}
+
+static inline void
+ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+ pte_t pte = *ptep;
+ update_pte(ptep, pte_wrprotect(pte));
+}
+
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(address) pgd_offset(&init_mm, address)
+
+/* to find an entry in a page-table-directory */
+#define pgd_offset(mm,address) ((mm)->pgd + pgd_index(address))
+
+#define pgd_index(address) ((address) >> PGDIR_SHIFT)
+
+/* Find an entry in the second-level page table.. */
+#define pmd_offset(dir,address) ((pmd_t*)(dir))
+
+/* Find an entry in the third-level page table.. */
+#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#define pte_offset_kernel(dir,addr) \
+ ((pte_t*) pmd_page_kernel(*(dir)) + pte_index(addr))
+#define pte_offset_map(dir,addr) pte_offset_kernel((dir),(addr))
+#define pte_offset_map_nested(dir,addr) pte_offset_kernel((dir),(addr))
+
+#define pte_unmap(pte) do { } while (0)
+#define pte_unmap_nested(pte) do { } while (0)
+
+
+/*
+ * Encode and decode a swap entry.
+ * Each PTE in a process VM's page table is either:
+ * "present" -- valid and not swapped out, protection bits are meaningful;
+ * "not present" -- which further subdivides in these two cases:
+ * "none" -- no mapping at all; identified by pte_none(), set by pte_clear(
+ * "swapped out" -- the page is swapped out, and the SWP macros below
+ * are used to store swap file info in the PTE itself.
+ *
+ * In the Xtensa processor MMU, any PTE entries in user space (or anywhere
+ * in virtual memory that can map differently across address spaces)
+ * must have a correct ring value that represents the RASID field that
+ * is changed when switching address spaces. Eg. such PTE entries cannot
+ * be set to ring zero, because that can cause a (global) kernel ASID
+ * entry to be created in the TLBs (even with invalid cache attribute),
+ * potentially causing a multihit exception when going back to another
+ * address space that mapped the same virtual address at another ring.
+ *
+ * SO: we avoid using ring bits (_PAGE_RING_MASK) in "not present" PTEs.
+ * We also avoid using the _PAGE_VALID bit which must be zero for non-present
+ * pages.
+ *
+ * We end up with the following available bits: 1..3 and 7..31.
+ * We don't bother with 1..3 for now (we can use them later if needed),
+ * and chose to allocate 6 bits for SWP_TYPE and the remaining 19 bits
+ * for SWP_OFFSET. At least 5 bits are needed for SWP_TYPE, because it
+ * is currently implemented as an index into swap_info[MAX_SWAPFILES]
+ * and MAX_SWAPFILES is currently defined as 32 in <linux/swap.h>.
+ * However, for some reason all other architectures in the 2.4 kernel
+ * reserve either 6, 7, or 8 bits so I'll not detract from that for now. :)
+ * SWP_OFFSET is an offset into the swap file in page-size units, so
+ * with 4 kB pages, 19 bits supports a maximum swap file size of 2 GB.
+ *
+ * FIXME: 2 GB isn't very big. Other bits can be used to allow
+ * larger swap sizes. In the meantime, it appears relatively easy to get
+ * around the 2 GB limitation by simply using multiple swap files.
+ */
+
+#define __swp_type(entry) (((entry).val >> 7) & 0x3f)
+#define __swp_offset(entry) ((entry).val >> 13)
+#define __swp_entry(type,offs) ((swp_entry_t) {((type) << 7) | ((offs) << 13)})
+#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
+#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
+
+#define PTE_FILE_MAX_BITS 29
+#define pte_to_pgoff(pte) (pte_val(pte) >> 3)
+#define pgoff_to_pte(off) ((pte_t) { ((off) << 3) | _PAGE_FILE })
+
+
+#endif /* !defined (__ASSEMBLY__) */
+
+
+#ifdef __ASSEMBLY__
+
+/* Assembly macro _PGD_INDEX is the same as C pgd_index(unsigned long),
+ * _PGD_OFFSET as C pgd_offset(struct mm_struct*, unsigned long),
+ * _PMD_OFFSET as C pmd_offset(pgd_t*, unsigned long)
+ * _PTE_OFFSET as C pte_offset(pmd_t*, unsigned long)
+ *
+ * Note: We require an additional temporary register which can be the same as
+ * the register that holds the address.
+ *
+ * ((pte_t*) ((unsigned long)(pmd_val(*pmd) & PAGE_MASK)) + pte_index(addr))
+ *
+ */
+#define _PGD_INDEX(rt,rs) extui rt, rs, PGDIR_SHIFT, 32-PGDIR_SHIFT
+#define _PTE_INDEX(rt,rs) extui rt, rs, PAGE_SHIFT, PTRS_PER_PTE_SHIFT
+
+#define _PGD_OFFSET(mm,adr,tmp) l32i mm, mm, MM_PGD; \
+ _PGD_INDEX(tmp, adr); \
+ addx4 mm, tmp, mm
+
+#define _PTE_OFFSET(pmd,adr,tmp) _PTE_INDEX(tmp, adr); \
+ srli pmd, pmd, PAGE_SHIFT; \
+ slli pmd, pmd, PAGE_SHIFT; \
+ addx4 pmd, tmp, pmd
+
+#else
+
+extern void paging_init(void);
+
+#define kern_addr_valid(addr) (1)
+
+extern void update_mmu_cache(struct vm_area_struct * vma,
+ unsigned long address, pte_t pte);
+
+/*
+ * remap a physical address `phys' of size `size' with page protection `prot'
+ * into virtual address `from'
+ */
+#define io_remap_page_range(vma,from,phys,size,prot) \
+ remap_pfn_range(vma, from, (phys) >> PAGE_SHIFT, size, prot)
+
+
+/* No page table caches to init */
+
+#define pgtable_cache_init() do { } while (0)
+
+typedef pte_t *pte_addr_t;
+
+#endif /* !defined (__ASSEMBLY__) */
+
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+#define __HAVE_ARCH_PTEP_SET_WRPROTECT
+#define __HAVE_ARCH_PTEP_MKDIRTY
+#define __HAVE_ARCH_PTE_SAME
+
+#include <asm-generic/pgtable.h>
+
+#endif /* _XTENSA_PGTABLE_H */
diff --git a/include/asm-xtensa/platform-iss/hardware.h b/include/asm-xtensa/platform-iss/hardware.h
new file mode 100644
index 00000000000..22240f00180
--- /dev/null
+++ b/include/asm-xtensa/platform-iss/hardware.h
@@ -0,0 +1,29 @@
+/*
+ * include/asm-xtensa/platform-iss/hardware.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 Tensilica Inc.
+ */
+
+/*
+ * This file contains the default configuration of ISS.
+ */
+
+#ifndef __ASM_XTENSA_ISS_HARDWARE
+#define __ASM_XTENSA_ISS_HARDWARE
+
+/*
+ * Memory configuration.
+ */
+
+#define PLATFORM_DEFAULT_MEM_START XSHAL_RAM_PADDR
+#define PLATFORM_DEFAULT_MEM_SIZE XSHAL_RAM_VSIZE
+
+/*
+ * Interrupt configuration.
+ */
+
+#endif /* __ASM_XTENSA_ISS_HARDWARE */
diff --git a/include/asm-xtensa/platform.h b/include/asm-xtensa/platform.h
new file mode 100644
index 00000000000..36163894bc2
--- /dev/null
+++ b/include/asm-xtensa/platform.h
@@ -0,0 +1,92 @@
+/*
+ * include/asm-xtensa/platform.h
+ *
+ * Platform specific functions
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_PLATFORM_H
+#define _XTENSA_PLATFORM_H
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+
+#include <asm/bootparam.h>
+
+/*
+ * platform_init is called before the mmu is initialized to give the
+ * platform a early hook-up. bp_tag_t is a list of configuration tags
+ * passed from the boot-loader.
+ */
+extern void platform_init(bp_tag_t*);
+
+/*
+ * platform_setup is called from setup_arch with a pointer to the command-line
+ * string.
+ */
+extern void platform_setup (char **);
+
+/*
+ * platform_init_irq is called from init_IRQ.
+ */
+extern void platform_init_irq (void);
+
+/*
+ * platform_restart is called to restart the system.
+ */
+extern void platform_restart (void);
+
+/*
+ * platform_halt is called to stop the system and halt.
+ */
+extern void platform_halt (void);
+
+/*
+ * platform_power_off is called to stop the system and power it off.
+ */
+extern void platform_power_off (void);
+
+/*
+ * platform_idle is called from the idle function.
+ */
+extern void platform_idle (void);
+
+/*
+ * platform_heartbeat is called every HZ
+ */
+extern void platform_heartbeat (void);
+
+/*
+ * platform_pcibios_init is called to allow the platform to setup the pci bus.
+ */
+extern void platform_pcibios_init (void);
+
+/*
+ * platform_pcibios_fixup allows to modify the PCI configuration.
+ */
+extern int platform_pcibios_fixup (void);
+
+/*
+ * platform_calibrate_ccount calibrates cpu clock freq (CONFIG_XTENSA_CALIBRATE)
+ */
+extern void platform_calibrate_ccount (void);
+
+/*
+ * platform_get_rtc_time returns RTC seconds (returns 0 for no error)
+ */
+extern int platform_get_rtc_time(time_t*);
+
+/*
+ * platform_set_rtc_time set RTC seconds (returns 0 for no error)
+ */
+extern int platform_set_rtc_time(time_t);
+
+
+#endif /* _XTENSA_PLATFORM_H */
+
diff --git a/include/asm-xtensa/poll.h b/include/asm-xtensa/poll.h
new file mode 100644
index 00000000000..dffe447534e
--- /dev/null
+++ b/include/asm-xtensa/poll.h
@@ -0,0 +1,37 @@
+/*
+ * include/asm-xtensa/poll.h
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_POLL_H
+#define _XTENSA_POLL_H
+
+
+#define POLLIN 0x0001
+#define POLLPRI 0x0002
+#define POLLOUT 0x0004
+
+#define POLLERR 0x0008
+#define POLLHUP 0x0010
+#define POLLNVAL 0x0020
+
+#define POLLRDNORM 0x0040
+#define POLLRDBAND 0x0080
+#define POLLWRNORM POLLOUT
+#define POLLWRBAND 0x0100
+
+#define POLLMSG 0x0400
+#define POLLREMOVE 0x0800
+
+struct pollfd {
+ int fd;
+ short events;
+ short revents;
+};
+
+#endif /* _XTENSA_POLL_H */
diff --git a/include/asm-xtensa/posix_types.h b/include/asm-xtensa/posix_types.h
new file mode 100644
index 00000000000..2c816b0e776
--- /dev/null
+++ b/include/asm-xtensa/posix_types.h
@@ -0,0 +1,123 @@
+/*
+ * include/asm-xtensa/posix_types.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Largely copied from include/asm-ppc/posix_types.h
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_POSIX_TYPES_H
+#define _XTENSA_POSIX_TYPES_H
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc. Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned long __kernel_ino_t;
+typedef unsigned int __kernel_mode_t;
+typedef unsigned short __kernel_nlink_t;
+typedef long __kernel_off_t;
+typedef int __kernel_pid_t;
+typedef unsigned short __kernel_ipc_pid_t;
+typedef unsigned int __kernel_uid_t;
+typedef unsigned int __kernel_gid_t;
+typedef unsigned int __kernel_size_t;
+typedef int __kernel_ssize_t;
+typedef long __kernel_ptrdiff_t;
+typedef long __kernel_time_t;
+typedef long __kernel_suseconds_t;
+typedef long __kernel_clock_t;
+typedef int __kernel_timer_t;
+typedef int __kernel_clockid_t;
+typedef int __kernel_daddr_t;
+typedef char * __kernel_caddr_t;
+typedef unsigned short __kernel_uid16_t;
+typedef unsigned short __kernel_gid16_t;
+typedef unsigned int __kernel_uid32_t;
+typedef unsigned int __kernel_gid32_t;
+
+typedef unsigned short __kernel_old_uid_t;
+typedef unsigned short __kernel_old_gid_t;
+typedef unsigned short __kernel_old_dev_t;
+
+#ifdef __GNUC__
+typedef long long __kernel_loff_t;
+#endif
+
+typedef struct {
+ int val[2];
+} __kernel_fsid_t;
+
+#ifndef __GNUC__
+
+#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
+#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
+#define __FD_ISSET(d, set) ((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
+#define __FD_ZERO(set) \
+ ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set)))
+
+#else /* __GNUC__ */
+
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) \
+ || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
+/* With GNU C, use inline functions instead so args are evaluated only once: */
+
+#undef __FD_SET
+static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
+{
+ unsigned long _tmp = fd / __NFDBITS;
+ unsigned long _rem = fd % __NFDBITS;
+ fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
+}
+
+#undef __FD_CLR
+static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
+{
+ unsigned long _tmp = fd / __NFDBITS;
+ unsigned long _rem = fd % __NFDBITS;
+ fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
+}
+
+#undef __FD_ISSET
+static __inline__ int __FD_ISSET(unsigned long fd, __kernel_fd_set *p)
+{
+ unsigned long _tmp = fd / __NFDBITS;
+ unsigned long _rem = fd % __NFDBITS;
+ return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
+}
+
+/*
+ * This will unroll the loop for the normal constant case (8 ints,
+ * for a 256-bit fd_set)
+ */
+#undef __FD_ZERO
+static __inline__ void __FD_ZERO(__kernel_fd_set *p)
+{
+ unsigned int *tmp = (unsigned int *)p->fds_bits;
+ int i;
+
+ if (__builtin_constant_p(__FDSET_LONGS)) {
+ switch (__FDSET_LONGS) {
+ case 8:
+ tmp[0] = 0; tmp[1] = 0; tmp[2] = 0; tmp[3] = 0;
+ tmp[4] = 0; tmp[5] = 0; tmp[6] = 0; tmp[7] = 0;
+ return;
+ }
+ }
+ i = __FDSET_LONGS;
+ while (i) {
+ i--;
+ *tmp = 0;
+ tmp++;
+ }
+}
+
+#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+#endif /* __GNUC__ */
+#endif /* _XTENSA_POSIX_TYPES_H */
diff --git a/include/asm-xtensa/processor.h b/include/asm-xtensa/processor.h
new file mode 100644
index 00000000000..9cab5e4298b
--- /dev/null
+++ b/include/asm-xtensa/processor.h
@@ -0,0 +1,205 @@
+/*
+ * include/asm-xtensa/processor.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_PROCESSOR_H
+#define _XTENSA_PROCESSOR_H
+
+#ifdef __ASSEMBLY__
+#define _ASMLANGUAGE
+#endif
+
+#include <xtensa/config/core.h>
+#include <xtensa/config/specreg.h>
+#include <xtensa/config/tie.h>
+#include <xtensa/config/system.h>
+
+#include <asm/ptrace.h>
+#include <asm/types.h>
+#include <asm/coprocessor.h>
+
+/* Assertions. */
+
+#if (XCHAL_HAVE_WINDOWED != 1)
+#error Linux requires the Xtensa Windowed Registers Option.
+#endif
+
+/*
+ * User space process size: 1 GB.
+ * Windowed call ABI requires caller and callee to be located within the same
+ * 1 GB region. The C compiler places trampoline code on the stack for sources
+ * that take the address of a nested C function (a feature used by glibc), so
+ * the 1 GB requirement applies to the stack as well.
+ */
+
+#define TASK_SIZE 0x40000000
+
+/*
+ * General exception cause assigned to debug exceptions. Debug exceptions go
+ * to their own vector, rather than the general exception vectors (user,
+ * kernel, double); and their specific causes are reported via DEBUGCAUSE
+ * rather than EXCCAUSE. However it is sometimes convenient to redirect debug
+ * exceptions to the general exception mechanism. To do this, an otherwise
+ * unused EXCCAUSE value was assigned to debug exceptions for this purpose.
+ */
+
+#define EXCCAUSE_MAPPED_DEBUG 63
+
+/*
+ * We use DEPC also as a flag to distinguish between double and regular
+ * exceptions. For performance reasons, DEPC might contain the value of
+ * EXCCAUSE for regular exceptions, so we use this definition to mark a
+ * valid double exception address.
+ * (Note: We use it in bgeui, so it should be 64, 128, or 256)
+ */
+
+#define VALID_DOUBLE_EXCEPTION_ADDRESS 64
+
+/* LOCKLEVEL defines the interrupt level that masks all
+ * general-purpose interrupts.
+ */
+#define LOCKLEVEL 1
+
+/* WSBITS and WBBITS are the width of the WINDOWSTART and WINDOWBASE
+ * registers
+ */
+#define WSBITS (XCHAL_NUM_AREGS / 4) /* width of WINDOWSTART in bits */
+#define WBBITS (XCHAL_NUM_AREGS_LOG2 - 2) /* width of WINDOWBASE in bits */
+
+#ifndef __ASSEMBLY__
+
+/* Build a valid return address for the specified call winsize.
+ * winsize must be 1 (call4), 2 (call8), or 3 (call12)
+ */
+#define MAKE_RA_FOR_CALL(ra,ws) (((ra) & 0x3fffffff) | (ws) << 30)
+
+/* Convert return address to a valid pc
+ * Note: We assume that the stack pointer is in the same 1GB ranges as the ra
+ */
+#define MAKE_PC_FROM_RA(ra,sp) (((ra) & 0x3fffffff) | ((sp) & 0xc0000000))
+
+typedef struct {
+ unsigned long seg;
+} mm_segment_t;
+
+struct thread_struct {
+
+ /* kernel's return address and stack pointer for context switching */
+ unsigned long ra; /* kernel's a0: return address and window call size */
+ unsigned long sp; /* kernel's a1: stack pointer */
+
+ mm_segment_t current_ds; /* see uaccess.h for example uses */
+
+ /* struct xtensa_cpuinfo info; */
+
+ unsigned long bad_vaddr; /* last user fault */
+ unsigned long bad_uaddr; /* last kernel fault accessing user space */
+ unsigned long error_code;
+
+ unsigned long ibreak[XCHAL_NUM_IBREAK];
+ unsigned long dbreaka[XCHAL_NUM_DBREAK];
+ unsigned long dbreakc[XCHAL_NUM_DBREAK];
+
+ /* Allocate storage for extra state and coprocessor state. */
+ unsigned char cp_save[XTENSA_CP_EXTRA_SIZE]
+ __attribute__ ((aligned(XTENSA_CP_EXTRA_ALIGN)));
+
+ /* Make structure 16 bytes aligned. */
+ int align[0] __attribute__ ((aligned(16)));
+};
+
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l;})
+
+
+/* This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE (TASK_SIZE / 2)
+
+#define INIT_THREAD \
+{ \
+ ra: 0, \
+ sp: sizeof(init_stack) + (long) &init_stack, \
+ current_ds: {0}, \
+ /*info: {0}, */ \
+ bad_vaddr: 0, \
+ bad_uaddr: 0, \
+ error_code: 0, \
+}
+
+
+/*
+ * Do necessary setup to start up a newly executed thread.
+ * Note: We set-up ps as if we did a call4 to the new pc.
+ * set_thread_state in signal.c depends on it.
+ */
+#define USER_PS_VALUE ( (1 << XCHAL_PS_WOE_SHIFT) + \
+ (1 << XCHAL_PS_CALLINC_SHIFT) + \
+ (USER_RING << XCHAL_PS_RING_SHIFT) + \
+ (1 << XCHAL_PS_PROGSTACK_SHIFT) + \
+ (1 << XCHAL_PS_EXCM_SHIFT) )
+
+/* Clearing a0 terminates the backtrace. */
+#define start_thread(regs, new_pc, new_sp) \
+ regs->pc = new_pc; \
+ regs->ps = USER_PS_VALUE; \
+ regs->areg[1] = new_sp; \
+ regs->areg[0] = 0; \
+ regs->wmask = 1; \
+ regs->depc = 0; \
+ regs->windowbase = 0; \
+ regs->windowstart = 1;
+
+/* Forward declaration */
+struct task_struct;
+struct mm_struct;
+
+// FIXME: do we need release_thread for CP??
+/* Free all resources held by a thread. */
+#define release_thread(thread) do { } while(0)
+
+// FIXME: do we need prepare_to_copy (lazy status) for CP??
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk) do { } while (0)
+
+/*
+ * create a kernel thread without removing it from tasklists
+ */
+extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+
+/* Copy and release all segment info associated with a VM */
+
+#define copy_segments(p, mm) do { } while(0)
+#define release_segments(mm) do { } while(0)
+#define forget_segments() do { } while (0)
+
+#define thread_saved_pc(tsk) (xtensa_pt_regs(tsk)->pc)
+
+extern unsigned long get_wchan(struct task_struct *p);
+
+#define KSTK_EIP(tsk) (xtensa_pt_regs(tsk)->pc)
+#define KSTK_ESP(tsk) (xtensa_pt_regs(tsk)->areg[1])
+
+#define cpu_relax() do { } while (0)
+
+/* Special register access. */
+
+#define WSR(v,sr) __asm__ __volatile__ ("wsr %0,"__stringify(sr) :: "a"(v));
+#define RSR(v,sr) __asm__ __volatile__ ("rsr %0,"__stringify(sr) : "=a"(v));
+
+#define set_sr(x,sr) ({unsigned int v=(unsigned int)x; WSR(v,sr);})
+#define get_sr(sr) ({unsigned int v; RSR(v,sr); v; })
+
+#endif /* __ASSEMBLY__ */
+#endif /* _XTENSA_PROCESSOR_H */
diff --git a/include/asm-xtensa/ptrace.h b/include/asm-xtensa/ptrace.h
new file mode 100644
index 00000000000..2848a5ff834
--- /dev/null
+++ b/include/asm-xtensa/ptrace.h
@@ -0,0 +1,135 @@
+/*
+ * include/asm-xtensa/ptrace.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_PTRACE_H
+#define _XTENSA_PTRACE_H
+
+#include <xtensa/config/core.h>
+
+/*
+ * Kernel stack
+ *
+ * +-----------------------+ -------- STACK_SIZE
+ * | register file | |
+ * +-----------------------+ |
+ * | struct pt_regs | |
+ * +-----------------------+ | ------ PT_REGS_OFFSET
+ * double : 16 bytes spill area : | ^
+ * excetion :- - - - - - - - - - - -: | |
+ * frame : struct pt_regs : | |
+ * :- - - - - - - - - - - -: | |
+ * | | | |
+ * | memory stack | | |
+ * | | | |
+ * ~ ~ ~ ~
+ * ~ ~ ~ ~
+ * | | | |
+ * | | | |
+ * +-----------------------+ | | --- STACK_BIAS
+ * | struct task_struct | | | ^
+ * current --> +-----------------------+ | | |
+ * | struct thread_info | | | |
+ * +-----------------------+ --------
+ */
+
+#define KERNEL_STACK_SIZE (2 * PAGE_SIZE)
+
+/* Offsets for exception_handlers[] (3 x 64-entries x 4-byte tables). */
+
+#define EXC_TABLE_KSTK 0x004 /* Kernel Stack */
+#define EXC_TABLE_DOUBLE_SAVE 0x008 /* Double exception save area for a0 */
+#define EXC_TABLE_FIXUP 0x00c /* Fixup handler */
+#define EXC_TABLE_PARAM 0x010 /* For passing a parameter to fixup */
+#define EXC_TABLE_SYSCALL_SAVE 0x014 /* For fast syscall handler */
+#define EXC_TABLE_FAST_USER 0x100 /* Fast user exception handler */
+#define EXC_TABLE_FAST_KERNEL 0x200 /* Fast kernel exception handler */
+#define EXC_TABLE_DEFAULT 0x300 /* Default C-Handler */
+#define EXC_TABLE_SIZE 0x400
+
+/* Registers used by strace */
+
+#define REG_A_BASE 0xfc000000
+#define REG_AR_BASE 0x04000000
+#define REG_PC 0x14000000
+#define REG_PS 0x080000e6
+#define REG_WB 0x08000048
+#define REG_WS 0x08000049
+#define REG_LBEG 0x08000000
+#define REG_LEND 0x08000001
+#define REG_LCOUNT 0x08000002
+#define REG_SAR 0x08000003
+#define REG_DEPC 0x080000c0
+#define REG_EXCCAUSE 0x080000e8
+#define REG_EXCVADDR 0x080000ee
+#define SYSCALL_NR 0x1
+
+#define AR_REGNO_TO_A_REGNO(ar, wb) (ar - wb*4) & ~(XCHAL_NUM_AREGS - 1)
+
+/* Other PTRACE_ values defined in <linux/ptrace.h> using values 0-9,16,17,24 */
+
+#define PTRACE_GETREGS 12
+#define PTRACE_SETREGS 13
+#define PTRACE_GETFPREGS 14
+#define PTRACE_SETFPREGS 15
+#define PTRACE_GETFPREGSIZE 18
+
+#ifndef __ASSEMBLY__
+
+/*
+ * This struct defines the way the registers are stored on the
+ * kernel stack during a system call or other kernel entry.
+ */
+struct pt_regs {
+ unsigned long pc; /* 4 */
+ unsigned long ps; /* 8 */
+ unsigned long depc; /* 12 */
+ unsigned long exccause; /* 16 */
+ unsigned long excvaddr; /* 20 */
+ unsigned long debugcause; /* 24 */
+ unsigned long wmask; /* 28 */
+ unsigned long lbeg; /* 32 */
+ unsigned long lend; /* 36 */
+ unsigned long lcount; /* 40 */
+ unsigned long sar; /* 44 */
+ unsigned long windowbase; /* 48 */
+ unsigned long windowstart; /* 52 */
+ unsigned long syscall; /* 56 */
+ int reserved[2]; /* 64 */
+
+ /* Make sure the areg field is 16 bytes aligned. */
+ int align[0] __attribute__ ((aligned(16)));
+
+ /* current register frame.
+ * Note: The ESF for kernel exceptions ends after 16 registers!
+ */
+ unsigned long areg[16]; /* 128 (64) */
+};
+
+#ifdef __KERNEL__
+# define xtensa_pt_regs(tsk) ((struct pt_regs*) \
+ (((long)(tsk)->thread_info + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4)) - 1)
+# define user_mode(regs) (((regs)->ps & 0x00000020)!=0)
+# define instruction_pointer(regs) ((regs)->pc)
+extern void show_regs(struct pt_regs *);
+
+# ifndef CONFIG_SMP
+# define profile_pc(regs) instruction_pointer(regs)
+# endif
+#endif /* __KERNEL__ */
+
+#else /* __ASSEMBLY__ */
+
+#ifdef __KERNEL__
+# include <asm/offsets.h>
+#define PT_REGS_OFFSET (KERNEL_STACK_SIZE - PT_USER_SIZE)
+#endif
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _XTENSA_PTRACE_H */
diff --git a/include/asm-xtensa/resource.h b/include/asm-xtensa/resource.h
new file mode 100644
index 00000000000..17b5ab31177
--- /dev/null
+++ b/include/asm-xtensa/resource.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-xtensa/resource.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_RESOURCE_H
+#define _XTENSA_RESOURCE_H
+
+#include <asm-generic/resource.h>
+
+#endif /* _XTENSA_RESOURCE_H */
diff --git a/include/asm-xtensa/rmap.h b/include/asm-xtensa/rmap.h
new file mode 100644
index 00000000000..649588b7e9a
--- /dev/null
+++ b/include/asm-xtensa/rmap.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-xtensa/rmap.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_RMAP_H
+#define _XTENSA_RMAP_H
+
+#include <asm-generic/rmap.h>
+
+#endif
diff --git a/include/asm-xtensa/rwsem.h b/include/asm-xtensa/rwsem.h
new file mode 100644
index 00000000000..3c02b0e033f
--- /dev/null
+++ b/include/asm-xtensa/rwsem.h
@@ -0,0 +1,175 @@
+/*
+ * include/asm-xtensa/rwsem.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Largely copied from include/asm-ppc/rwsem.h
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_RWSEM_H
+#define _XTENSA_RWSEM_H
+
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <asm/atomic.h>
+#include <asm/system.h>
+
+/*
+ * the semaphore definition
+ */
+struct rw_semaphore {
+ signed long count;
+#define RWSEM_UNLOCKED_VALUE 0x00000000
+#define RWSEM_ACTIVE_BIAS 0x00000001
+#define RWSEM_ACTIVE_MASK 0x0000ffff
+#define RWSEM_WAITING_BIAS (-0x00010000)
+#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS
+#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
+ spinlock_t wait_lock;
+ struct list_head wait_list;
+#if RWSEM_DEBUG
+ int debug;
+#endif
+};
+
+/*
+ * initialisation
+ */
+#if RWSEM_DEBUG
+#define __RWSEM_DEBUG_INIT , 0
+#else
+#define __RWSEM_DEBUG_INIT /* */
+#endif
+
+#define __RWSEM_INITIALIZER(name) \
+ { RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
+ LIST_HEAD_INIT((name).wait_list) \
+ __RWSEM_DEBUG_INIT }
+
+#define DECLARE_RWSEM(name) \
+ struct rw_semaphore name = __RWSEM_INITIALIZER(name)
+
+extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
+
+static inline void init_rwsem(struct rw_semaphore *sem)
+{
+ sem->count = RWSEM_UNLOCKED_VALUE;
+ spin_lock_init(&sem->wait_lock);
+ INIT_LIST_HEAD(&sem->wait_list);
+#if RWSEM_DEBUG
+ sem->debug = 0;
+#endif
+}
+
+/*
+ * lock for reading
+ */
+static inline void __down_read(struct rw_semaphore *sem)
+{
+ if (atomic_add_return(1,(atomic_t *)(&sem->count)) > 0)
+ smp_wmb();
+ else
+ rwsem_down_read_failed(sem);
+}
+
+static inline int __down_read_trylock(struct rw_semaphore *sem)
+{
+ int tmp;
+
+ while ((tmp = sem->count) >= 0) {
+ if (tmp == cmpxchg(&sem->count, tmp,
+ tmp + RWSEM_ACTIVE_READ_BIAS)) {
+ smp_wmb();
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * lock for writing
+ */
+static inline void __down_write(struct rw_semaphore *sem)
+{
+ int tmp;
+
+ tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS,
+ (atomic_t *)(&sem->count));
+ if (tmp == RWSEM_ACTIVE_WRITE_BIAS)
+ smp_wmb();
+ else
+ rwsem_down_write_failed(sem);
+}
+
+static inline int __down_write_trylock(struct rw_semaphore *sem)
+{
+ int tmp;
+
+ tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
+ RWSEM_ACTIVE_WRITE_BIAS);
+ smp_wmb();
+ return tmp == RWSEM_UNLOCKED_VALUE;
+}
+
+/*
+ * unlock after reading
+ */
+static inline void __up_read(struct rw_semaphore *sem)
+{
+ int tmp;
+
+ smp_wmb();
+ tmp = atomic_sub_return(1,(atomic_t *)(&sem->count));
+ if (tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0)
+ rwsem_wake(sem);
+}
+
+/*
+ * unlock after writing
+ */
+static inline void __up_write(struct rw_semaphore *sem)
+{
+ smp_wmb();
+ if (atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS,
+ (atomic_t *)(&sem->count)) < 0)
+ rwsem_wake(sem);
+}
+
+/*
+ * implement atomic add functionality
+ */
+static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
+{
+ atomic_add(delta, (atomic_t *)(&sem->count));
+}
+
+/*
+ * downgrade write lock to read lock
+ */
+static inline void __downgrade_write(struct rw_semaphore *sem)
+{
+ int tmp;
+
+ smp_wmb();
+ tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count));
+ if (tmp < 0)
+ rwsem_downgrade_wake(sem);
+}
+
+/*
+ * implement exchange and add functionality
+ */
+static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
+{
+ smp_mb();
+ return atomic_add_return(delta, (atomic_t *)(&sem->count));
+}
+
+#endif /* _XTENSA_RWSEM_XADD_H */
diff --git a/include/asm-xtensa/scatterlist.h b/include/asm-xtensa/scatterlist.h
new file mode 100644
index 00000000000..38a2b9acd65
--- /dev/null
+++ b/include/asm-xtensa/scatterlist.h
@@ -0,0 +1,34 @@
+/*
+ * include/asm-xtensa/scatterlist.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SCATTERLIST_H
+#define _XTENSA_SCATTERLIST_H
+
+struct scatterlist {
+ struct page *page;
+ unsigned int offset;
+ dma_addr_t dma_address;
+ unsigned int length;
+};
+
+/*
+ * These macros should be used after a pci_map_sg call has been done
+ * to get bus addresses of each of the SG entries and their lengths.
+ * You should only work with the number of sg entries pci_map_sg
+ * returns, or alternatively stop on the first sg_dma_len(sg) which
+ * is 0.
+ */
+#define sg_dma_address(sg) ((sg)->dma_address)
+#define sg_dma_len(sg) ((sg)->length)
+
+
+#define ISA_DMA_THRESHOLD (~0UL)
+
+#endif /* _XTENSA_SCATTERLIST_H */
diff --git a/include/asm-xtensa/sections.h b/include/asm-xtensa/sections.h
new file mode 100644
index 00000000000..40b5191b55a
--- /dev/null
+++ b/include/asm-xtensa/sections.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-xtensa/sections.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SECTIONS_H
+#define _XTENSA_SECTIONS_H
+
+#include <asm-generic/sections.h>
+
+#endif /* _XTENSA_SECTIONS_H */
diff --git a/include/asm-xtensa/segment.h b/include/asm-xtensa/segment.h
new file mode 100644
index 00000000000..a2eb547a1a7
--- /dev/null
+++ b/include/asm-xtensa/segment.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-xtensa/segment.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SEGMENT_H
+#define _XTENSA_SEGMENT_H
+
+#include <asm/uaccess.h>
+
+#endif /* _XTENSA_SEGEMENT_H */
diff --git a/include/asm-xtensa/semaphore.h b/include/asm-xtensa/semaphore.h
new file mode 100644
index 00000000000..c8a7574a9a5
--- /dev/null
+++ b/include/asm-xtensa/semaphore.h
@@ -0,0 +1,129 @@
+/*
+ * linux/include/asm-xtensa/semaphore.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SEMAPHORE_H
+#define _XTENSA_SEMAPHORE_H
+
+#include <asm/atomic.h>
+#include <asm/system.h>
+#include <linux/wait.h>
+#include <linux/rwsem.h>
+
+struct semaphore {
+ atomic_t count;
+ int sleepers;
+ wait_queue_head_t wait;
+#if WAITQUEUE_DEBUG
+ long __magic;
+#endif
+};
+
+#if WAITQUEUE_DEBUG
+# define __SEM_DEBUG_INIT(name) \
+ , (int)&(name).__magic
+#else
+# define __SEM_DEBUG_INIT(name)
+#endif
+
+#define __SEMAPHORE_INITIALIZER(name,count) \
+ { ATOMIC_INIT(count), \
+ 0, \
+ __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+ __SEM_DEBUG_INIT(name) }
+
+#define __MUTEX_INITIALIZER(name) \
+ __SEMAPHORE_INITIALIZER(name, 1)
+
+#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+ struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+
+#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
+
+extern inline void sema_init (struct semaphore *sem, int val)
+{
+/*
+ * *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
+ *
+ * i'd rather use the more flexible initialization above, but sadly
+ * GCC 2.7.2.3 emits a bogus warning. EGCS doesnt. Oh well.
+ */
+ atomic_set(&sem->count, val);
+ init_waitqueue_head(&sem->wait);
+#if WAITQUEUE_DEBUG
+ sem->__magic = (int)&sem->__magic;
+#endif
+}
+
+static inline void init_MUTEX (struct semaphore *sem)
+{
+ sema_init(sem, 1);
+}
+
+static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+{
+ sema_init(sem, 0);
+}
+
+asmlinkage void __down(struct semaphore * sem);
+asmlinkage int __down_interruptible(struct semaphore * sem);
+asmlinkage int __down_trylock(struct semaphore * sem);
+asmlinkage void __up(struct semaphore * sem);
+
+extern spinlock_t semaphore_wake_lock;
+
+extern __inline__ void down(struct semaphore * sem)
+{
+#if WAITQUEUE_DEBUG
+ CHECK_MAGIC(sem->__magic);
+#endif
+
+ if (atomic_sub_return(1, &sem->count) < 0)
+ __down(sem);
+}
+
+extern __inline__ int down_interruptible(struct semaphore * sem)
+{
+ int ret = 0;
+#if WAITQUEUE_DEBUG
+ CHECK_MAGIC(sem->__magic);
+#endif
+
+ if (atomic_sub_return(1, &sem->count) < 0)
+ ret = __down_interruptible(sem);
+ return ret;
+}
+
+extern __inline__ int down_trylock(struct semaphore * sem)
+{
+ int ret = 0;
+#if WAITQUEUE_DEBUG
+ CHECK_MAGIC(sem->__magic);
+#endif
+
+ if (atomic_sub_return(1, &sem->count) < 0)
+ ret = __down_trylock(sem);
+ return ret;
+}
+
+/*
+ * Note! This is subtle. We jump to wake people up only if
+ * the semaphore was negative (== somebody was waiting on it).
+ */
+extern __inline__ void up(struct semaphore * sem)
+{
+#if WAITQUEUE_DEBUG
+ CHECK_MAGIC(sem->__magic);
+#endif
+ if (atomic_add_return(1, &sem->count) <= 0)
+ __up(sem);
+}
+
+#endif /* _XTENSA_SEMAPHORE_H */
diff --git a/include/asm-xtensa/sembuf.h b/include/asm-xtensa/sembuf.h
new file mode 100644
index 00000000000..2d26c47666f
--- /dev/null
+++ b/include/asm-xtensa/sembuf.h
@@ -0,0 +1,44 @@
+/*
+ * include/asm-xtensa/sembuf.h
+ *
+ * The semid64_ds structure for Xtensa architecture.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ *
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ *
+ */
+
+#ifndef _XTENSA_SEMBUF_H
+#define _XTENSA_SEMBUF_H
+
+#include <asm/byteorder.h>
+
+struct semid64_ds {
+ struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
+#if XCHAL_HAVE_LE
+ __kernel_time_t sem_otime; /* last semop time */
+ unsigned long __unused1;
+ __kernel_time_t sem_ctime; /* last change time */
+ unsigned long __unused2;
+#else
+ unsigned long __unused1;
+ __kernel_time_t sem_otime; /* last semop time */
+ unsigned long __unused2;
+ __kernel_time_t sem_ctime; /* last change time */
+#endif
+ unsigned long sem_nsems; /* no. of semaphores in array */
+ unsigned long __unused3;
+ unsigned long __unused4;
+};
+
+#endif /* __ASM_XTENSA_SEMBUF_H */
diff --git a/include/asm-xtensa/serial.h b/include/asm-xtensa/serial.h
new file mode 100644
index 00000000000..ec04114fcf0
--- /dev/null
+++ b/include/asm-xtensa/serial.h
@@ -0,0 +1,18 @@
+/*
+ * include/asm-xtensa/serial.h
+ *
+ * Configuration details for 8250, 16450, 16550, etc. serial ports
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SERIAL_H
+#define _XTENSA_SERIAL_H
+
+#include <asm/platform/serial.h>
+
+#endif /* _XTENSA_SERIAL_H */
diff --git a/include/asm-xtensa/setup.h b/include/asm-xtensa/setup.h
new file mode 100644
index 00000000000..e3636520d8c
--- /dev/null
+++ b/include/asm-xtensa/setup.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-xtensa/setup.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SETUP_H
+#define _XTENSA_SETUP_H
+
+#define COMMAND_LINE_SIZE 256
+
+#endif
diff --git a/include/asm-xtensa/shmbuf.h b/include/asm-xtensa/shmbuf.h
new file mode 100644
index 00000000000..a30b81a4b93
--- /dev/null
+++ b/include/asm-xtensa/shmbuf.h
@@ -0,0 +1,50 @@
+/*
+ * include/asm-xtensa/shmbuf.h
+ *
+ * The shmid64_ds structure for Xtensa architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SHMBUF_H
+#define _XTENSA_SHMBUF_H
+
+struct shmid64_ds {
+ struct ipc64_perm shm_perm; /* operation perms */
+ size_t shm_segsz; /* size of segment (bytes) */
+ __kernel_time_t shm_atime; /* last attach time */
+ unsigned long __unused1;
+ __kernel_time_t shm_dtime; /* last detach time */
+ unsigned long __unused2;
+ __kernel_time_t shm_ctime; /* last change time */
+ unsigned long __unused3;
+ __kernel_pid_t shm_cpid; /* pid of creator */
+ __kernel_pid_t shm_lpid; /* pid of last operator */
+ unsigned long shm_nattch; /* no. of current attaches */
+ unsigned long __unused4;
+ unsigned long __unused5;
+};
+
+struct shminfo64 {
+ unsigned long shmmax;
+ unsigned long shmmin;
+ unsigned long shmmni;
+ unsigned long shmseg;
+ unsigned long shmall;
+ unsigned long __unused1;
+ unsigned long __unused2;
+ unsigned long __unused3;
+ unsigned long __unused4;
+};
+
+#endif /* _XTENSA_SHMBUF_H */
diff --git a/include/asm-xtensa/shmparam.h b/include/asm-xtensa/shmparam.h
new file mode 100644
index 00000000000..d3b65bfa71c
--- /dev/null
+++ b/include/asm-xtensa/shmparam.h
@@ -0,0 +1,23 @@
+/*
+ * include/asm-xtensa/shmparam.h
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ */
+
+#ifndef _XTENSA_SHMPARAM_H
+#define _XTENSA_SHMPARAM_H
+
+#include <asm/processor.h>
+
+/*
+ * Xtensa can have variable size caches, and if
+ * the size of single way is larger than the page size,
+ * then we have to start worrying about cache aliasing
+ * problems.
+ */
+
+#define SHMLBA ((PAGE_SIZE > DCACHE_WAY_SIZE)? PAGE_SIZE : DCACHE_WAY_SIZE)
+
+#endif /* _XTENSA_SHMPARAM_H */
diff --git a/include/asm-xtensa/sigcontext.h b/include/asm-xtensa/sigcontext.h
new file mode 100644
index 00000000000..a7517729141
--- /dev/null
+++ b/include/asm-xtensa/sigcontext.h
@@ -0,0 +1,44 @@
+/*
+ * include/asm-xtensa/sigcontext.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2003 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SIGCONTEXT_H
+#define _XTENSA_SIGCONTEXT_H
+
+#define _ASMLANGUAGE
+#include <asm/processor.h>
+#include <asm/coprocessor.h>
+
+
+struct _cpstate {
+ unsigned char _cpstate[XTENSA_CP_EXTRA_SIZE];
+} __attribute__ ((aligned (XTENSA_CP_EXTRA_ALIGN)));
+
+
+struct sigcontext {
+ unsigned long oldmask;
+
+ /* CPU registers */
+ unsigned long sc_pc;
+ unsigned long sc_ps;
+ unsigned long sc_wmask;
+ unsigned long sc_windowbase;
+ unsigned long sc_windowstart;
+ unsigned long sc_lbeg;
+ unsigned long sc_lend;
+ unsigned long sc_lcount;
+ unsigned long sc_sar;
+ unsigned long sc_depc;
+ unsigned long sc_dareg0;
+ unsigned long sc_treg[4];
+ unsigned long sc_areg[XCHAL_NUM_AREGS];
+ struct _cpstate *sc_cpstate;
+};
+
+#endif /* __ASM_XTENSA_SIGCONTEXT_H */
diff --git a/include/asm-xtensa/siginfo.h b/include/asm-xtensa/siginfo.h
new file mode 100644
index 00000000000..44f0ae77b53
--- /dev/null
+++ b/include/asm-xtensa/siginfo.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-xtensa/processor.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SIGINFO_H
+#define _XTENSA_SIGINFO_H
+
+#include <asm-generic/siginfo.h>
+
+#endif /* _XTENSA_SIGINFO_H */
diff --git a/include/asm-xtensa/signal.h b/include/asm-xtensa/signal.h
new file mode 100644
index 00000000000..5d6fc9cdf58
--- /dev/null
+++ b/include/asm-xtensa/signal.h
@@ -0,0 +1,187 @@
+/*
+ * include/asm-xtensa/signal.h
+ *
+ * Swiped from SH.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SIGNAL_H
+#define _XTENSA_SIGNAL_H
+
+
+#define _NSIG 64
+#define _NSIG_BPW 32
+#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+/* Avoid too many header ordering problems. */
+struct siginfo;
+typedef unsigned long old_sigset_t; /* at least 32 bits */
+typedef struct {
+ unsigned long sig[_NSIG_WORDS];
+} sigset_t;
+
+#endif
+
+#define SIGHUP 1
+#define SIGINT 2
+#define SIGQUIT 3
+#define SIGILL 4
+#define SIGTRAP 5
+#define SIGABRT 6
+#define SIGIOT 6
+#define SIGBUS 7
+#define SIGFPE 8
+#define SIGKILL 9
+#define SIGUSR1 10
+#define SIGSEGV 11
+#define SIGUSR2 12
+#define SIGPIPE 13
+#define SIGALRM 14
+#define SIGTERM 15
+#define SIGSTKFLT 16
+#define SIGCHLD 17
+#define SIGCONT 18
+#define SIGSTOP 19
+#define SIGTSTP 20
+#define SIGTTIN 21
+#define SIGTTOU 22
+#define SIGURG 23
+#define SIGXCPU 24
+#define SIGXFSZ 25
+#define SIGVTALRM 26
+#define SIGPROF 27
+#define SIGWINCH 28
+#define SIGIO 29
+#define SIGPOLL SIGIO
+/* #define SIGLOST 29 */
+#define SIGPWR 30
+#define SIGSYS 31
+#define SIGUNUSED 31
+
+/* These should not be considered constants from userland. */
+#define SIGRTMIN 32
+#define SIGRTMAX (_NSIG-1)
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+#define SA_NOCLDSTOP 0x00000001
+#define SA_NOCLDWAIT 0x00000002 /* not supported yet */
+#define SA_SIGINFO 0x00000004
+#define SA_ONSTACK 0x08000000
+#define SA_RESTART 0x10000000
+#define SA_NODEFER 0x40000000
+#define SA_RESETHAND 0x80000000
+
+#define SA_NOMASK SA_NODEFER
+#define SA_ONESHOT SA_RESETHAND
+#define SA_INTERRUPT 0x20000000 /* dummy -- ignored */
+
+#define SA_RESTORER 0x04000000
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK 1
+#define SS_DISABLE 2
+
+#define MINSIGSTKSZ 2048
+#define SIGSTKSZ 8192
+
+#ifndef __ASSEMBLY__
+#ifdef __KERNEL__
+
+/*
+ * These values of sa_flags are used only by the kernel as part of the
+ * irq handling routines.
+ *
+ * SA_INTERRUPT is also used by the irq handling routines.
+ * SA_SHIRQ is for shared interrupt support on PCI and EISA.
+ */
+#define SA_PROBE SA_ONESHOT
+#define SA_SAMPLE_RANDOM SA_RESTART
+#define SA_SHIRQ 0x04000000
+#endif
+
+#define SIG_BLOCK 0 /* for blocking signals */
+#define SIG_UNBLOCK 1 /* for unblocking signals */
+#define SIG_SETMASK 2 /* for setting the signal mask */
+
+/* Type of a signal handler. */
+typedef void (*__sighandler_t)(int);
+
+#define SIG_DFL ((__sighandler_t)0) /* default signal handling */
+#define SIG_IGN ((__sighandler_t)1) /* ignore signal */
+#define SIG_ERR ((__sighandler_t)-1) /* error return from signal */
+
+#ifdef __KERNEL__
+struct old_sigaction {
+ __sighandler_t sa_handler;
+ old_sigset_t sa_mask;
+ unsigned long sa_flags;
+ void (*sa_restorer)(void);
+};
+
+struct sigaction {
+ __sighandler_t sa_handler;
+ unsigned long sa_flags;
+ void (*sa_restorer)(void);
+ sigset_t sa_mask; /* mask last for extensibility */
+};
+
+struct k_sigaction {
+ struct sigaction sa;
+};
+
+#else
+
+/* Here we must cater to libcs that poke about in kernel headers. */
+
+struct sigaction {
+ union {
+ __sighandler_t _sa_handler;
+ void (*_sa_sigaction)(int, struct siginfo *, void *);
+ } _u;
+ sigset_t sa_mask;
+ unsigned long sa_flags;
+ void (*sa_restorer)(void);
+};
+
+#define sa_handler _u._sa_handler
+#define sa_sigaction _u._sa_sigaction
+
+#endif /* __KERNEL__ */
+
+typedef struct sigaltstack {
+ void *ss_sp;
+ int ss_flags;
+ size_t ss_size;
+} stack_t;
+
+#ifdef __KERNEL__
+#include <asm/sigcontext.h>
+#define ptrace_signal_deliver(regs, cookie) do { } while (0)
+
+#endif /* __KERNEL__ */
+#endif /* __ASSEMBLY__ */
+#endif /* _XTENSA_SIGNAL_H */
diff --git a/include/asm-xtensa/smp.h b/include/asm-xtensa/smp.h
new file mode 100644
index 00000000000..83c569e3bdb
--- /dev/null
+++ b/include/asm-xtensa/smp.h
@@ -0,0 +1,27 @@
+/*
+ * include/asm-xtensa/smp.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SMP_H
+#define _XTENSA_SMP_H
+
+extern struct xtensa_cpuinfo boot_cpu_data;
+
+#define cpu_data (&boot_cpu_data)
+#define current_cpu_data boot_cpu_data
+
+struct xtensa_cpuinfo {
+ unsigned long *pgd_cache;
+ unsigned long *pte_cache;
+ unsigned long pgtable_cache_sz;
+};
+
+#define cpu_logical_map(cpu) (cpu)
+
+#endif /* _XTENSA_SMP_H */
diff --git a/include/asm-xtensa/socket.h b/include/asm-xtensa/socket.h
new file mode 100644
index 00000000000..daccd05a14c
--- /dev/null
+++ b/include/asm-xtensa/socket.h
@@ -0,0 +1,61 @@
+/*
+ * include/asm-xtensa/socket.h
+ *
+ * Copied from i386.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef _XTENSA_SOCKET_H
+#define _XTENSA_SOCKET_H
+
+#include <asm/sockios.h>
+
+/* For setsockoptions(2) */
+#define SOL_SOCKET 1
+
+#define SO_DEBUG 1
+#define SO_REUSEADDR 2
+#define SO_TYPE 3
+#define SO_ERROR 4
+#define SO_DONTROUTE 5
+#define SO_BROADCAST 6
+#define SO_SNDBUF 7
+#define SO_RCVBUF 8
+#define SO_KEEPALIVE 9
+#define SO_OOBINLINE 10
+#define SO_NO_CHECK 11
+#define SO_PRIORITY 12
+#define SO_LINGER 13
+#define SO_BSDCOMPAT 14
+/* To add :#define SO_REUSEPORT 15 */
+#define SO_PASSCRED 16
+#define SO_PEERCRED 17
+#define SO_RCVLOWAT 18
+#define SO_SNDLOWAT 19
+#define SO_RCVTIMEO 20
+#define SO_SNDTIMEO 21
+
+/* Security levels - as per NRL IPv6 - don't actually do anything */
+
+#define SO_SECURITY_AUTHENTICATION 22
+#define SO_SECURITY_ENCRYPTION_TRANSPORT 23
+#define SO_SECURITY_ENCRYPTION_NETWORK 24
+
+#define SO_BINDTODEVICE 25
+
+/* Socket filtering */
+
+#define SO_ATTACH_FILTER 26
+#define SO_DETACH_FILTER 27
+
+#define SO_PEERNAME 28
+#define SO_TIMESTAMP 29
+#define SCM_TIMESTAMP SO_TIMESTAMP
+
+#define SO_ACCEPTCONN 30
+#define SO_PEERSEC 31
+
+#endif /* _XTENSA_SOCKET_H */
diff --git a/include/asm-xtensa/sockios.h b/include/asm-xtensa/sockios.h
new file mode 100644
index 00000000000..20d2ba10ecd
--- /dev/null
+++ b/include/asm-xtensa/sockios.h
@@ -0,0 +1,30 @@
+/*
+ * include/asm-xtensa/sockios.h
+ *
+ * Socket-level I/O control calls. Copied from MIPS.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1995 by Ralf Baechle
+ * Copyright (C) 2001 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SOCKIOS_H
+#define _XTENSA_SOCKIOS_H
+
+#include <asm/ioctl.h>
+
+/* Socket-level I/O control calls. */
+
+#define FIOGETOWN _IOR('f', 123, int)
+#define FIOSETOWN _IOW('f', 124, int)
+
+#define SIOCATMARK _IOR('s', 7, int)
+#define SIOCSPGRP _IOW('s', 8, pid_t)
+#define SIOCGPGRP _IOR('s', 9, pid_t)
+
+#define SIOCGSTAMP 0x8906 /* Get stamp - linux-specific */
+
+#endif /* _XTENSA_SOCKIOS_H */
diff --git a/include/asm-xtensa/spinlock.h b/include/asm-xtensa/spinlock.h
new file mode 100644
index 00000000000..8ff23649581
--- /dev/null
+++ b/include/asm-xtensa/spinlock.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-xtensa/spinlock.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SPINLOCK_H
+#define _XTENSA_SPINLOCK_H
+
+#include <linux/spinlock.h>
+
+#endif /* _XTENSA_SPINLOCK_H */
diff --git a/include/asm-xtensa/stat.h b/include/asm-xtensa/stat.h
new file mode 100644
index 00000000000..2f4662ff6c3
--- /dev/null
+++ b/include/asm-xtensa/stat.h
@@ -0,0 +1,105 @@
+/*
+ * include/asm-xtensa/stat.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_STAT_H
+#define _XTENSA_STAT_H
+
+#include <linux/types.h>
+
+struct __old_kernel_stat {
+ unsigned short st_dev;
+ unsigned short st_ino;
+ unsigned short st_mode;
+ unsigned short st_nlink;
+ unsigned short st_uid;
+ unsigned short st_gid;
+ unsigned short st_rdev;
+ unsigned long st_size;
+ unsigned long st_atime;
+ unsigned long st_mtime;
+ unsigned long st_ctime;
+};
+
+#define STAT_HAVE_NSEC 1
+
+struct stat {
+ unsigned short st_dev;
+ unsigned short __pad1;
+ unsigned long st_ino;
+ unsigned short st_mode;
+ unsigned short st_nlink;
+ unsigned short st_uid;
+ unsigned short st_gid;
+ unsigned short st_rdev;
+ unsigned short __pad2;
+ unsigned long st_size;
+ unsigned long st_blksize;
+ unsigned long st_blocks;
+ unsigned long st_atime;
+ unsigned long st_atime_nsec;
+ unsigned long st_mtime;
+ unsigned long st_mtime_nsec;
+ unsigned long st_ctime;
+ unsigned long st_ctime_nsec;
+ unsigned long __unused4;
+ unsigned long __unused5;
+};
+
+/* This matches struct stat64 in glibc-2.2.3. */
+
+struct stat64 {
+#ifdef __XTENSA_EL__
+ unsigned short st_dev; /* Device */
+ unsigned char __pad0[10];
+#else
+ unsigned char __pad0[6];
+ unsigned short st_dev;
+ unsigned char __pad1[2];
+#endif
+
+#define STAT64_HAS_BROKEN_ST_INO 1
+ unsigned long __st_ino; /* 32bit file serial number. */
+
+ unsigned int st_mode; /* File mode. */
+ unsigned int st_nlink; /* Link count. */
+ unsigned int st_uid; /* User ID of the file's owner. */
+ unsigned int st_gid; /* Group ID of the file's group. */
+
+#ifdef __XTENSA_EL__
+ unsigned short st_rdev; /* Device number, if device. */
+ unsigned char __pad3[10];
+#else
+ unsigned char __pad2[6];
+ unsigned short st_rdev;
+ unsigned char __pad3[2];
+#endif
+
+ long long int st_size; /* Size of file, in bytes. */
+ long int st_blksize; /* Optimal block size for I/O. */
+
+#ifdef __XTENSA_EL__
+ unsigned long st_blocks; /* Number 512-byte blocks allocated. */
+ unsigned long __pad4;
+#else
+ unsigned long __pad4;
+ unsigned long st_blocks;
+#endif
+
+ unsigned long __pad5;
+ long int st_atime; /* Time of last access. */
+ unsigned long st_atime_nsec;
+ long int st_mtime; /* Time of last modification. */
+ unsigned long st_mtime_nsec;
+ long int st_ctime; /* Time of last status change. */
+ unsigned long st_ctime_nsec;
+ unsigned long long int st_ino; /* File serial number. */
+};
+
+#endif /* _XTENSA_STAT_H */
diff --git a/include/asm-xtensa/statfs.h b/include/asm-xtensa/statfs.h
new file mode 100644
index 00000000000..9c3d1a21313
--- /dev/null
+++ b/include/asm-xtensa/statfs.h
@@ -0,0 +1,17 @@
+/*
+ * include/asm-xtensa/statfs.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_STATFS_H
+#define _XTENSA_STATFS_H
+
+#include <asm-generic/statfs.h>
+
+#endif /* _XTENSA_STATFS_H */
+
diff --git a/include/asm-xtensa/string.h b/include/asm-xtensa/string.h
new file mode 100644
index 00000000000..3f81b27d980
--- /dev/null
+++ b/include/asm-xtensa/string.h
@@ -0,0 +1,124 @@
+/*
+ * include/asm-xtensa/string.h
+ *
+ * These trivial string functions are considered part of the public domain.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+/* We should optimize these. See arch/xtensa/lib/strncpy_user.S */
+
+#ifndef _XTENSA_STRING_H
+#define _XTENSA_STRING_H
+
+#define __HAVE_ARCH_STRCPY
+extern __inline__ char *strcpy(char *__dest, const char *__src)
+{
+ register char *__xdest = __dest;
+ unsigned long __dummy;
+
+ __asm__ __volatile__("1:\n\t"
+ "l8ui %2, %1, 0\n\t"
+ "s8i %2, %0, 0\n\t"
+ "addi %1, %1, 1\n\t"
+ "addi %0, %0, 1\n\t"
+ "bnez %2, 1b\n\t"
+ : "=r" (__dest), "=r" (__src), "=&r" (__dummy)
+ : "0" (__dest), "1" (__src)
+ : "memory");
+
+ return __xdest;
+}
+
+#define __HAVE_ARCH_STRNCPY
+extern __inline__ char *strncpy(char *__dest, const char *__src, size_t __n)
+{
+ register char *__xdest = __dest;
+ unsigned long __dummy;
+
+ if (__n == 0)
+ return __xdest;
+
+ __asm__ __volatile__(
+ "1:\n\t"
+ "l8ui %2, %1, 0\n\t"
+ "s8i %2, %0, 0\n\t"
+ "addi %1, %1, 1\n\t"
+ "addi %0, %0, 1\n\t"
+ "beqz %2, 2f\n\t"
+ "bne %1, %5, 1b\n"
+ "2:"
+ : "=r" (__dest), "=r" (__src), "=&r" (__dummy)
+ : "0" (__dest), "1" (__src), "r" (__src+__n)
+ : "memory");
+
+ return __xdest;
+}
+
+#define __HAVE_ARCH_STRCMP
+extern __inline__ int strcmp(const char *__cs, const char *__ct)
+{
+ register int __res;
+ unsigned long __dummy;
+
+ __asm__ __volatile__(
+ "1:\n\t"
+ "l8ui %3, %1, 0\n\t"
+ "addi %1, %1, 1\n\t"
+ "l8ui %2, %0, 0\n\t"
+ "addi %0, %0, 1\n\t"
+ "beqz %2, 2f\n\t"
+ "beq %2, %3, 1b\n"
+ "2:\n\t"
+ "sub %2, %3, %2"
+ : "=r" (__cs), "=r" (__ct), "=&r" (__res), "=&r" (__dummy)
+ : "0" (__cs), "1" (__ct));
+
+ return __res;
+}
+
+#define __HAVE_ARCH_STRNCMP
+extern __inline__ int strncmp(const char *__cs, const char *__ct, size_t __n)
+{
+ register int __res;
+ unsigned long __dummy;
+
+ __asm__ __volatile__(
+ "mov %2, %3\n"
+ "1:\n\t"
+ "beq %0, %6, 2f\n\t"
+ "l8ui %3, %1, 0\n\t"
+ "addi %1, %1, 1\n\t"
+ "l8ui %2, %0, 0\n\t"
+ "addi %0, %0, 1\n\t"
+ "beqz %2, 2f\n\t"
+ "beqz %3, 2f\n\t"
+ "beq %2, %3, 1b\n"
+ "2:\n\t"
+ "sub %2, %3, %2"
+ : "=r" (__cs), "=r" (__ct), "=&r" (__res), "=&r" (__dummy)
+ : "0" (__cs), "1" (__ct), "r" (__cs+__n));
+
+ return __res;
+}
+
+#define __HAVE_ARCH_MEMSET
+extern void *memset(void *__s, int __c, size_t __count);
+
+#define __HAVE_ARCH_MEMCPY
+extern void *memcpy(void *__to, __const__ void *__from, size_t __n);
+
+#define __HAVE_ARCH_MEMMOVE
+extern void *memmove(void *__dest, __const__ void *__src, size_t __n);
+
+/* Don't build bcopy at all ... */
+#define __HAVE_ARCH_BCOPY
+
+#define __HAVE_ARCH_MEMSCAN
+#define memscan memchr
+
+#endif /* _XTENSA_STRING_H */
diff --git a/include/asm-xtensa/system.h b/include/asm-xtensa/system.h
new file mode 100644
index 00000000000..690fe325e67
--- /dev/null
+++ b/include/asm-xtensa/system.h
@@ -0,0 +1,252 @@
+/*
+ * include/asm-xtensa/system.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SYSTEM_H
+#define _XTENSA_SYSTEM_H
+
+#include <linux/config.h>
+#include <linux/stringify.h>
+
+#include <asm/processor.h>
+
+/* interrupt control */
+
+#define local_save_flags(x) \
+ __asm__ __volatile__ ("rsr %0,"__stringify(PS) : "=a" (x));
+#define local_irq_restore(x) do { \
+ __asm__ __volatile__ ("wsr %0, "__stringify(PS)" ; rsync" \
+ :: "a" (x) : "memory"); } while(0);
+#define local_irq_save(x) do { \
+ __asm__ __volatile__ ("rsil %0, "__stringify(LOCKLEVEL) \
+ : "=a" (x) :: "memory");} while(0);
+
+static inline void local_irq_disable(void)
+{
+ unsigned long flags;
+ __asm__ __volatile__ ("rsil %0, "__stringify(LOCKLEVEL)
+ : "=a" (flags) :: "memory");
+}
+static inline void local_irq_enable(void)
+{
+ unsigned long flags;
+ __asm__ __volatile__ ("rsil %0, 0" : "=a" (flags) :: "memory");
+
+}
+
+static inline int irqs_disabled(void)
+{
+ unsigned long flags;
+ local_save_flags(flags);
+ return flags & 0xf;
+}
+
+#define RSR_CPENABLE(x) do { \
+ __asm__ __volatile__("rsr %0," __stringify(CPENABLE) : "=a" (x)); \
+ } while(0);
+#define WSR_CPENABLE(x) do { \
+ __asm__ __volatile__("wsr %0," __stringify(CPENABLE)";rsync" \
+ :: "a" (x));} while(0);
+
+#define clear_cpenable() __clear_cpenable()
+
+extern __inline__ void __clear_cpenable(void)
+{
+#if XCHAL_HAVE_CP
+ unsigned long i = 0;
+ WSR_CPENABLE(i);
+#endif
+}
+
+extern __inline__ void enable_coprocessor(int i)
+{
+#if XCHAL_HAVE_CP
+ int cp;
+ RSR_CPENABLE(cp);
+ cp |= 1 << i;
+ WSR_CPENABLE(cp);
+#endif
+}
+
+extern __inline__ void disable_coprocessor(int i)
+{
+#if XCHAL_HAVE_CP
+ int cp;
+ RSR_CPENABLE(cp);
+ cp &= ~(1 << i);
+ WSR_CPENABLE(cp);
+#endif
+}
+
+#define smp_read_barrier_depends() do { } while(0)
+#define read_barrier_depends() do { } while(0)
+
+#define mb() barrier()
+#define rmb() mb()
+#define wmb() mb()
+
+#ifdef CONFIG_SMP
+#error smp_* not defined
+#else
+#define smp_mb() barrier()
+#define smp_rmb() barrier()
+#define smp_wmb() barrier()
+#endif
+
+#define set_mb(var, value) do { var = value; mb(); } while (0)
+#define set_wmb(var, value) do { var = value; wmb(); } while (0)
+
+#if !defined (__ASSEMBLY__)
+
+/* * switch_to(n) should switch tasks to task nr n, first
+ * checking that n isn't the current task, in which case it does nothing.
+ */
+extern void *_switch_to(void *last, void *next);
+
+#endif /* __ASSEMBLY__ */
+
+#define prepare_to_switch() do { } while(0)
+
+#define switch_to(prev,next,last) \
+do { \
+ clear_cpenable(); \
+ (last) = _switch_to(prev, next); \
+} while(0)
+
+/*
+ * cmpxchg
+ */
+
+extern __inline__ unsigned long
+__cmpxchg_u32(volatile int *p, int old, int new)
+{
+ __asm__ __volatile__("rsil a15, "__stringify(LOCKLEVEL)"\n\t"
+ "l32i %0, %1, 0 \n\t"
+ "bne %0, %2, 1f \n\t"
+ "s32i %3, %1, 0 \n\t"
+ "1: \n\t"
+ "wsr a15, "__stringify(PS)" \n\t"
+ "rsync \n\t"
+ : "=&a" (old)
+ : "a" (p), "a" (old), "r" (new)
+ : "a15", "memory");
+ return old;
+}
+/* This function doesn't exist, so you'll get a linker error
+ * if something tries to do an invalid cmpxchg(). */
+
+extern void __cmpxchg_called_with_bad_pointer(void);
+
+static __inline__ unsigned long
+__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
+{
+ switch (size) {
+ case 4: return __cmpxchg_u32(ptr, old, new);
+ default: __cmpxchg_called_with_bad_pointer();
+ return old;
+ }
+}
+
+#define cmpxchg(ptr,o,n) \
+ ({ __typeof__(*(ptr)) _o_ = (o); \
+ __typeof__(*(ptr)) _n_ = (n); \
+ (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
+ (unsigned long)_n_, sizeof (*(ptr))); \
+ })
+
+
+
+
+/*
+ * xchg_u32
+ *
+ * Note that a15 is used here because the register allocation
+ * done by the compiler is not guaranteed and a window overflow
+ * may not occur between the rsil and wsr instructions. By using
+ * a15 in the rsil, the machine is guaranteed to be in a state
+ * where no register reference will cause an overflow.
+ */
+
+extern __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val)
+{
+ unsigned long tmp;
+ __asm__ __volatile__("rsil a15, "__stringify(LOCKLEVEL)"\n\t"
+ "l32i %0, %1, 0 \n\t"
+ "s32i %2, %1, 0 \n\t"
+ "wsr a15, "__stringify(PS)" \n\t"
+ "rsync \n\t"
+ : "=&a" (tmp)
+ : "a" (m), "a" (val)
+ : "a15", "memory");
+ return tmp;
+}
+
+#define tas(ptr) (xchg((ptr),1))
+
+#if ( __XCC__ == 1 )
+
+/* xt-xcc processes __inline__ differently than xt-gcc and decides to
+ * insert an out-of-line copy of function __xchg. This presents the
+ * unresolved symbol at link time of __xchg_called_with_bad_pointer,
+ * even though such a function would never be called at run-time.
+ * xt-gcc always inlines __xchg, and optimizes away the undefined
+ * bad_pointer function.
+ */
+
+#define xchg(ptr,x) xchg_u32(ptr,x)
+
+#else /* assume xt-gcc */
+
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+/*
+ * This only works if the compiler isn't horribly bad at optimizing.
+ * gcc-2.5.8 reportedly can't handle this, but I define that one to
+ * be dead anyway.
+ */
+
+extern void __xchg_called_with_bad_pointer(void);
+
+static __inline__ unsigned long
+__xchg(unsigned long x, volatile void * ptr, int size)
+{
+ switch (size) {
+ case 4:
+ return xchg_u32(ptr, x);
+ }
+ __xchg_called_with_bad_pointer();
+ return x;
+}
+
+#endif
+
+extern void set_except_vector(int n, void *addr);
+
+static inline void spill_registers(void)
+{
+ unsigned int a0, ps;
+
+ __asm__ __volatile__ (
+ "movi a14," __stringify (PS_EXCM_MASK) " | 1\n\t"
+ "mov a12, a0\n\t"
+ "rsr a13," __stringify(SAR) "\n\t"
+ "xsr a14," __stringify(PS) "\n\t"
+ "movi a0, _spill_registers\n\t"
+ "rsync\n\t"
+ "callx0 a0\n\t"
+ "mov a0, a12\n\t"
+ "wsr a13," __stringify(SAR) "\n\t"
+ "wsr a14," __stringify(PS) "\n\t"
+ :: "a" (&a0), "a" (&ps)
+ : "a2", "a3", "a12", "a13", "a14", "a15", "memory");
+}
+
+#define arch_align_stack(x) (x)
+
+#endif /* _XTENSA_SYSTEM_H */
diff --git a/include/asm-xtensa/termbits.h b/include/asm-xtensa/termbits.h
new file mode 100644
index 00000000000..c780593ff5f
--- /dev/null
+++ b/include/asm-xtensa/termbits.h
@@ -0,0 +1,194 @@
+/*
+ * include/asm-xtensa/termbits.h
+ *
+ * Copied from SH.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_TERMBITS_H
+#define _XTENSA_TERMBITS_H
+
+
+#include <linux/posix_types.h>
+
+typedef unsigned char cc_t;
+typedef unsigned int speed_t;
+typedef unsigned int tcflag_t;
+
+#define NCCS 19
+struct termios {
+ tcflag_t c_iflag; /* input mode flags */
+ tcflag_t c_oflag; /* output mode flags */
+ tcflag_t c_cflag; /* control mode flags */
+ tcflag_t c_lflag; /* local mode flags */
+ cc_t c_line; /* line discipline */
+ cc_t c_cc[NCCS]; /* control characters */
+};
+
+/* c_cc characters */
+
+#define VINTR 0
+#define VQUIT 1
+#define VERASE 2
+#define VKILL 3
+#define VEOF 4
+#define VTIME 5
+#define VMIN 6
+#define VSWTC 7
+#define VSTART 8
+#define VSTOP 9
+#define VSUSP 10
+#define VEOL 11
+#define VREPRINT 12
+#define VDISCARD 13
+#define VWERASE 14
+#define VLNEXT 15
+#define VEOL2 16
+
+/* c_iflag bits */
+
+#define IGNBRK 0000001
+#define BRKINT 0000002
+#define IGNPAR 0000004
+#define PARMRK 0000010
+#define INPCK 0000020
+#define ISTRIP 0000040
+#define INLCR 0000100
+#define IGNCR 0000200
+#define ICRNL 0000400
+#define IUCLC 0001000
+#define IXON 0002000
+#define IXANY 0004000
+#define IXOFF 0010000
+#define IMAXBEL 0020000
+#define IUTF8 0040000
+
+/* c_oflag bits */
+
+#define OPOST 0000001
+#define OLCUC 0000002
+#define ONLCR 0000004
+#define OCRNL 0000010
+#define ONOCR 0000020
+#define ONLRET 0000040
+#define OFILL 0000100
+#define OFDEL 0000200
+#define NLDLY 0000400
+#define NL0 0000000
+#define NL1 0000400
+#define CRDLY 0003000
+#define CR0 0000000
+#define CR1 0001000
+#define CR2 0002000
+#define CR3 0003000
+#define TABDLY 0014000
+#define TAB0 0000000
+#define TAB1 0004000
+#define TAB2 0010000
+#define TAB3 0014000
+#define XTABS 0014000
+#define BSDLY 0020000
+#define BS0 0000000
+#define BS1 0020000
+#define VTDLY 0040000
+#define VT0 0000000
+#define VT1 0040000
+#define FFDLY 0100000
+#define FF0 0000000
+#define FF1 0100000
+
+/* c_cflag bit meaning */
+
+#define CBAUD 0010017
+#define B0 0000000 /* hang up */
+#define B50 0000001
+#define B75 0000002
+#define B110 0000003
+#define B134 0000004
+#define B150 0000005
+#define B200 0000006
+#define B300 0000007
+#define B600 0000010
+#define B1200 0000011
+#define B1800 0000012
+#define B2400 0000013
+#define B4800 0000014
+#define B9600 0000015
+#define B19200 0000016
+#define B38400 0000017
+#define EXTA B19200
+#define EXTB B38400
+#define CSIZE 0000060
+#define CS5 0000000
+#define CS6 0000020
+#define CS7 0000040
+#define CS8 0000060
+#define CSTOPB 0000100
+#define CREAD 0000200
+#define PARENB 0000400
+#define PARODD 0001000
+#define HUPCL 0002000
+#define CLOCAL 0004000
+#define CBAUDEX 0010000
+#define B57600 0010001
+#define B115200 0010002
+#define B230400 0010003
+#define B460800 0010004
+#define B500000 0010005
+#define B576000 0010006
+#define B921600 0010007
+#define B1000000 0010010
+#define B1152000 0010011
+#define B1500000 0010012
+#define B2000000 0010013
+#define B2500000 0010014
+#define B3000000 0010015
+#define B3500000 0010016
+#define B4000000 0010017
+#define CIBAUD 002003600000 /* input baud rate (not used) */
+#define CMSPAR 010000000000 /* mark or space (stick) parity */
+#define CRTSCTS 020000000000 /* flow control */
+
+/* c_lflag bits */
+
+#define ISIG 0000001
+#define ICANON 0000002
+#define XCASE 0000004
+#define ECHO 0000010
+#define ECHOE 0000020
+#define ECHOK 0000040
+#define ECHONL 0000100
+#define NOFLSH 0000200
+#define TOSTOP 0000400
+#define ECHOCTL 0001000
+#define ECHOPRT 0002000
+#define ECHOKE 0004000
+#define FLUSHO 0010000
+#define PENDIN 0040000
+#define IEXTEN 0100000
+
+/* tcflow() and TCXONC use these */
+
+#define TCOOFF 0
+#define TCOON 1
+#define TCIOFF 2
+#define TCION 3
+
+/* tcflush() and TCFLSH use these */
+
+#define TCIFLUSH 0
+#define TCOFLUSH 1
+#define TCIOFLUSH 2
+
+/* tcsetattr uses these */
+
+#define TCSANOW 0
+#define TCSADRAIN 1
+#define TCSAFLUSH 2
+
+#endif /* _XTENSA_TERMBITS_H */
diff --git a/include/asm-xtensa/termios.h b/include/asm-xtensa/termios.h
new file mode 100644
index 00000000000..83c6aed1d11
--- /dev/null
+++ b/include/asm-xtensa/termios.h
@@ -0,0 +1,122 @@
+/*
+ * include/asm-xtensa/termios.h
+ *
+ * Copied from SH.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_TERMIOS_H
+#define _XTENSA_TERMIOS_H
+
+#include <asm/termbits.h>
+#include <asm/ioctls.h>
+
+struct winsize {
+ unsigned short ws_row;
+ unsigned short ws_col;
+ unsigned short ws_xpixel;
+ unsigned short ws_ypixel;
+};
+
+#define NCC 8
+struct termio {
+ unsigned short c_iflag; /* input mode flags */
+ unsigned short c_oflag; /* output mode flags */
+ unsigned short c_cflag; /* control mode flags */
+ unsigned short c_lflag; /* local mode flags */
+ unsigned char c_line; /* line discipline */
+ unsigned char c_cc[NCC]; /* control characters */
+};
+
+/* Modem lines */
+
+#define TIOCM_LE 0x001
+#define TIOCM_DTR 0x002
+#define TIOCM_RTS 0x004
+#define TIOCM_ST 0x008
+#define TIOCM_SR 0x010
+#define TIOCM_CTS 0x020
+#define TIOCM_CAR 0x040
+#define TIOCM_RNG 0x080
+#define TIOCM_DSR 0x100
+#define TIOCM_CD TIOCM_CAR
+#define TIOCM_RI TIOCM_RNG
+#define TIOCM_OUT1 0x2000
+#define TIOCM_OUT2 0x4000
+#define TIOCM_LOOP 0x8000
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+
+/* Line disciplines */
+
+#define N_TTY 0
+#define N_SLIP 1
+#define N_MOUSE 2
+#define N_PPP 3
+#define N_STRIP 4
+#define N_AX25 5
+#define N_X25 6 /* X.25 async */
+#define N_6PACK 7
+#define N_MASC 8 /* Reserved for Mobitex module <kaz@cafe.net> */
+#define N_R3964 9 /* Reserved for Simatic R3964 module */
+#define N_PROFIBUS_FDL 10 /* Reserved for Profibus <Dave@mvhi.com> */
+#define N_IRDA 11 /* Linux IR - http://irda.sourceforge.net/ */
+#define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */
+#define N_HDLC 13 /* synchronous HDLC */
+#define N_SYNC_PPP 14
+#define N_HCI 15 /* Bluetooth HCI UART */
+
+#ifdef __KERNEL__
+
+/* intr=^C quit=^\ erase=del kill=^U
+ eof=^D vtime=\0 vmin=\1 sxtc=\0
+ start=^Q stop=^S susp=^Z eol=\0
+ reprint=^R discard=^U werase=^W lnext=^V
+ eol2=\0
+*/
+#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
+
+/*
+ * Translate a "termio" structure into a "termios". Ugh.
+ */
+
+#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \
+ unsigned short __tmp; \
+ get_user(__tmp,&(termio)->x); \
+ *(unsigned short *) &(termios)->x = __tmp; \
+}
+
+#define user_termio_to_kernel_termios(termios, termio) \
+({ \
+ SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \
+ SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \
+ SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \
+ SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \
+ copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
+})
+
+/*
+ * Translate a "termios" structure into a "termio". Ugh.
+ */
+
+#define kernel_termios_to_user_termio(termio, termios) \
+({ \
+ put_user((termios)->c_iflag, &(termio)->c_iflag); \
+ put_user((termios)->c_oflag, &(termio)->c_oflag); \
+ put_user((termios)->c_cflag, &(termio)->c_cflag); \
+ put_user((termios)->c_lflag, &(termio)->c_lflag); \
+ put_user((termios)->c_line, &(termio)->c_line); \
+ copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
+})
+
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+
+#endif /* __KERNEL__ */
+
+#endif /* _XTENSA_TERMIOS_H */
diff --git a/include/asm-xtensa/thread_info.h b/include/asm-xtensa/thread_info.h
new file mode 100644
index 00000000000..af208d41fd8
--- /dev/null
+++ b/include/asm-xtensa/thread_info.h
@@ -0,0 +1,146 @@
+/*
+ * include/asm-xtensa/thread_info.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_THREAD_INFO_H
+#define _XTENSA_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+# include <asm/processor.h>
+#endif
+
+/*
+ * low level task data that entry.S needs immediate access to
+ * - this struct should fit entirely inside of one cache line
+ * - this struct shares the supervisor stack pages
+ * - if the contents of this structure are changed, the assembly constants
+ * must also be changed
+ */
+
+#ifndef __ASSEMBLY__
+
+struct thread_info {
+ struct task_struct *task; /* main task structure */
+ struct exec_domain *exec_domain; /* execution domain */
+ unsigned long flags; /* low level flags */
+ unsigned long status; /* thread-synchronous flags */
+ __u32 cpu; /* current CPU */
+ __s32 preempt_count; /* 0 => preemptable,< 0 => BUG*/
+
+ mm_segment_t addr_limit; /* thread address space */
+ struct restart_block restart_block;
+
+
+};
+
+#else /* !__ASSEMBLY__ */
+
+/* offsets into the thread_info struct for assembly code access */
+#define TI_TASK 0x00000000
+#define TI_EXEC_DOMAIN 0x00000004
+#define TI_FLAGS 0x00000008
+#define TI_STATUS 0x0000000C
+#define TI_CPU 0x00000010
+#define TI_PRE_COUNT 0x00000014
+#define TI_ADDR_LIMIT 0x00000018
+#define TI_RESTART_BLOCK 0x000001C
+
+#endif
+
+#define PREEMPT_ACTIVE 0x10000000
+
+/*
+ * macros/functions for gaining access to the thread information structure
+ *
+ * preempt_count needs to be 1 initially, until the scheduler is functional.
+ */
+
+#ifndef __ASSEMBLY__
+
+#define INIT_THREAD_INFO(tsk) \
+{ \
+ .task = &tsk, \
+ .exec_domain = &default_exec_domain, \
+ .flags = 0, \
+ .cpu = 0, \
+ .preempt_count = 1, \
+ .addr_limit = KERNEL_DS, \
+ .restart_block = { \
+ .fn = do_no_restart_syscall, \
+ }, \
+}
+
+#define init_thread_info (init_thread_union.thread_info)
+#define init_stack (init_thread_union.stack)
+
+/* how to get the thread information struct from C */
+static inline struct thread_info *current_thread_info(void)
+{
+ struct thread_info *ti;
+ __asm__("extui %0,a1,0,13\n\t"
+ "xor %0, a1, %0" : "=&r" (ti) : );
+ return ti;
+}
+
+/* thread information allocation */
+#define alloc_thread_info(tsk) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
+#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
+#define get_thread_info(ti) get_task_struct((ti)->task)
+#define put_thread_info(ti) put_task_struct((ti)->task)
+
+#else /* !__ASSEMBLY__ */
+
+/* how to get the thread information struct from ASM */
+#define GET_THREAD_INFO(reg,sp) \
+ extui reg, sp, 0, 13; \
+ xor reg, sp, reg
+#endif
+
+
+/*
+ * thread information flags
+ * - these are process state flags that various assembly files may need to access
+ * - pending work-to-be-done flags are in LSW
+ * - other flags in MSW
+ */
+#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
+#define TIF_NOTIFY_RESUME 1 /* resumption notification requested */
+#define TIF_SIGPENDING 2 /* signal pending */
+#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
+#define TIF_SINGLESTEP 4 /* restore singlestep on return to user mode */
+#define TIF_IRET 5 /* return with iret */
+#define TIF_MEMDIE 6
+#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */
+
+#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
+#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
+#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
+#define _TIF_IRET (1<<TIF_IRET)
+#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
+
+#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */
+#define _TIF_ALLWORK_MASK 0x0000FFFF /* work to do on any return to u-space */
+
+/*
+ * Thread-synchronous status.
+ *
+ * This is different from the flags in that nobody else
+ * ever touches our thread-synchronous status, so we don't
+ * have to worry about atomic accesses.
+ */
+#define TS_USEDFPU 0x0001 /* FPU was used by this task this quantum (SMP) */
+
+#define THREAD_SIZE 8192 //(2*PAGE_SIZE)
+
+#endif /* __KERNEL__ */
+#endif /* _XTENSA_THREAD_INFO */
diff --git a/include/asm-xtensa/timex.h b/include/asm-xtensa/timex.h
new file mode 100644
index 00000000000..d14a3755a12
--- /dev/null
+++ b/include/asm-xtensa/timex.h
@@ -0,0 +1,94 @@
+/*
+ * include/asm-xtensa/timex.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_TIMEX_H
+#define _XTENSA_TIMEX_H
+
+#ifdef __KERNEL__
+
+#include <asm/processor.h>
+#include <linux/stringify.h>
+
+#if XCHAL_INT_LEVEL(XCHAL_TIMER0_INTERRUPT) == 1
+# define LINUX_TIMER 0
+#elif XCHAL_INT_LEVEL(XCHAL_TIMER1_INTERRUPT) == 1
+# define LINUX_TIMER 1
+#elif XCHAL_INT_LEVEL(XCHAL_TIMER2_INTERRUPT) == 1
+# define LINUX_TIMER 2
+#else
+# error "Bad timer number for Linux configurations!"
+#endif
+
+#define LINUX_TIMER_INT XCHAL_TIMER_INTERRUPT(LINUX_TIMER)
+#define LINUX_TIMER_MASK (1L << LINUX_TIMER_INT)
+
+#define CLOCK_TICK_RATE 1193180 /* (everyone is using this value) */
+#define CLOCK_TICK_FACTOR 20 /* Factor of both 10^6 and CLOCK_TICK_RATE */
+#define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \
+ (1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \
+ << (SHIFT_SCALE-SHIFT_HZ)) / HZ)
+
+#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT
+extern unsigned long ccount_per_jiffy;
+extern unsigned long ccount_nsec;
+#define CCOUNT_PER_JIFFY ccount_per_jiffy
+#define CCOUNT_NSEC ccount_nsec
+#else
+#define CCOUNT_PER_JIFFY (CONFIG_XTENSA_CPU_CLOCK*(1000000UL/HZ))
+#define CCOUNT_NSEC (1000000000UL / CONFIG_XTENSA_CPU_CLOCK)
+#endif
+
+
+typedef unsigned long long cycles_t;
+
+/*
+ * Only used for SMP.
+ */
+
+extern cycles_t cacheflush_time;
+
+#define get_cycles() (0)
+
+
+/*
+ * Register access.
+ */
+
+#define WSR_CCOUNT(r) __asm__("wsr %0,"__stringify(CCOUNT) :: "a" (r))
+#define RSR_CCOUNT(r) __asm__("rsr %0,"__stringify(CCOUNT) : "=a" (r))
+#define WSR_CCOMPARE(x,r) __asm__("wsr %0,"__stringify(CCOMPARE_0)"+"__stringify(x) :: "a"(r))
+#define RSR_CCOMPARE(x,r) __asm__("rsr %0,"__stringify(CCOMPARE_0)"+"__stringify(x) : "=a"(r))
+
+static inline unsigned long get_ccount (void)
+{
+ unsigned long ccount;
+ RSR_CCOUNT(ccount);
+ return ccount;
+}
+
+static inline void set_ccount (unsigned long ccount)
+{
+ WSR_CCOUNT(ccount);
+}
+
+static inline unsigned long get_linux_timer (void)
+{
+ unsigned ccompare;
+ RSR_CCOMPARE(LINUX_TIMER, ccompare);
+ return ccompare;
+}
+
+static inline void set_linux_timer (unsigned long ccompare)
+{
+ WSR_CCOMPARE(LINUX_TIMER, ccompare);
+}
+
+#endif /* __KERNEL__ */
+#endif /* _XTENSA_TIMEX_H */
diff --git a/include/asm-xtensa/tlb.h b/include/asm-xtensa/tlb.h
new file mode 100644
index 00000000000..4562b2dcfbc
--- /dev/null
+++ b/include/asm-xtensa/tlb.h
@@ -0,0 +1,25 @@
+/*
+ * include/asm-xtensa/tlb.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_TLB_H
+#define _XTENSA_TLB_H
+
+#define tlb_start_vma(tlb,vma) do { } while (0)
+#define tlb_end_vma(tlb,vma) do { } while (0)
+#define __tlb_remove_tlb_entry(tlb,pte,addr) do { } while (0)
+
+#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
+
+#include <asm-generic/tlb.h>
+#include <asm/page.h>
+
+#define __pte_free_tlb(tlb,pte) pte_free(pte)
+
+#endif /* _XTENSA_TLB_H */
diff --git a/include/asm-xtensa/tlbflush.h b/include/asm-xtensa/tlbflush.h
new file mode 100644
index 00000000000..23bfe9db45f
--- /dev/null
+++ b/include/asm-xtensa/tlbflush.h
@@ -0,0 +1,200 @@
+/*
+ * include/asm-xtensa/tlbflush.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_TLBFLUSH_H
+#define _XTENSA_TLBFLUSH_H
+
+#define DEBUG_TLB
+
+#ifdef __KERNEL__
+
+#include <asm/processor.h>
+#include <linux/stringify.h>
+
+/* TLB flushing:
+ *
+ * - flush_tlb_all() flushes all processes TLB entries
+ * - flush_tlb_mm(mm) flushes the specified mm context TLB entries
+ * - flush_tlb_page(mm, vmaddr) flushes a single page
+ * - flush_tlb_range(mm, start, end) flushes a range of pages
+ */
+
+extern void flush_tlb_all(void);
+extern void flush_tlb_mm(struct mm_struct*);
+extern void flush_tlb_page(struct vm_area_struct*,unsigned long);
+extern void flush_tlb_range(struct vm_area_struct*,unsigned long,unsigned long);
+
+#define flush_tlb_kernel_range(start,end) flush_tlb_all()
+
+
+/* This is calld in munmap when we have freed up some page-table pages.
+ * We don't need to do anything here, there's nothing special about our
+ * page-table pages.
+ */
+
+extern inline void flush_tlb_pgtables(struct mm_struct *mm,
+ unsigned long start, unsigned long end)
+{
+}
+
+/* TLB operations. */
+
+#define ITLB_WAYS_LOG2 XCHAL_ITLB_WAY_BITS
+#define DTLB_WAYS_LOG2 XCHAL_DTLB_WAY_BITS
+#define ITLB_PROBE_SUCCESS (1 << ITLB_WAYS_LOG2)
+#define DTLB_PROBE_SUCCESS (1 << DTLB_WAYS_LOG2)
+
+extern inline unsigned long itlb_probe(unsigned long addr)
+{
+ unsigned long tmp;
+ __asm__ __volatile__("pitlb %0, %1\n\t" : "=a" (tmp) : "a" (addr));
+ return tmp;
+}
+
+extern inline unsigned long dtlb_probe(unsigned long addr)
+{
+ unsigned long tmp;
+ __asm__ __volatile__("pdtlb %0, %1\n\t" : "=a" (tmp) : "a" (addr));
+ return tmp;
+}
+
+extern inline void invalidate_itlb_entry (unsigned long probe)
+{
+ __asm__ __volatile__("iitlb %0; isync\n\t" : : "a" (probe));
+}
+
+extern inline void invalidate_dtlb_entry (unsigned long probe)
+{
+ __asm__ __volatile__("idtlb %0; dsync\n\t" : : "a" (probe));
+}
+
+/* Use the .._no_isync functions with caution. Generally, these are
+ * handy for bulk invalidates followed by a single 'isync'. The
+ * caller must follow up with an 'isync', which can be relatively
+ * expensive on some Xtensa implementations.
+ */
+extern inline void invalidate_itlb_entry_no_isync (unsigned entry)
+{
+ /* Caller must follow up with 'isync'. */
+ __asm__ __volatile__ ("iitlb %0\n" : : "a" (entry) );
+}
+
+extern inline void invalidate_dtlb_entry_no_isync (unsigned entry)
+{
+ /* Caller must follow up with 'isync'. */
+ __asm__ __volatile__ ("idtlb %0\n" : : "a" (entry) );
+}
+
+extern inline void set_itlbcfg_register (unsigned long val)
+{
+ __asm__ __volatile__("wsr %0, "__stringify(ITLBCFG)"\n\t" "isync\n\t"
+ : : "a" (val));
+}
+
+extern inline void set_dtlbcfg_register (unsigned long val)
+{
+ __asm__ __volatile__("wsr %0, "__stringify(DTLBCFG)"; dsync\n\t"
+ : : "a" (val));
+}
+
+extern inline void set_ptevaddr_register (unsigned long val)
+{
+ __asm__ __volatile__(" wsr %0, "__stringify(PTEVADDR)"; isync\n"
+ : : "a" (val));
+}
+
+extern inline unsigned long read_ptevaddr_register (void)
+{
+ unsigned long tmp;
+ __asm__ __volatile__("rsr %0, "__stringify(PTEVADDR)"\n\t" : "=a" (tmp));
+ return tmp;
+}
+
+extern inline void write_dtlb_entry (pte_t entry, int way)
+{
+ __asm__ __volatile__("wdtlb %1, %0; dsync\n\t"
+ : : "r" (way), "r" (entry) );
+}
+
+extern inline void write_itlb_entry (pte_t entry, int way)
+{
+ __asm__ __volatile__("witlb %1, %0; isync\n\t"
+ : : "r" (way), "r" (entry) );
+}
+
+extern inline void invalidate_page_directory (void)
+{
+ invalidate_dtlb_entry (DTLB_WAY_PGTABLE);
+}
+
+extern inline void invalidate_itlb_mapping (unsigned address)
+{
+ unsigned long tlb_entry;
+ while ((tlb_entry = itlb_probe (address)) & ITLB_PROBE_SUCCESS)
+ invalidate_itlb_entry (tlb_entry);
+}
+
+extern inline void invalidate_dtlb_mapping (unsigned address)
+{
+ unsigned long tlb_entry;
+ while ((tlb_entry = dtlb_probe (address)) & DTLB_PROBE_SUCCESS)
+ invalidate_dtlb_entry (tlb_entry);
+}
+
+#define check_pgt_cache() do { } while (0)
+
+
+#ifdef DEBUG_TLB
+
+/* DO NOT USE THESE FUNCTIONS. These instructions aren't part of the Xtensa
+ * ISA and exist only for test purposes..
+ * You may find it helpful for MMU debugging, however.
+ *
+ * 'at' is the unmodified input register
+ * 'as' is the output register, as follows (specific to the Linux config):
+ *
+ * as[31..12] contain the virtual address
+ * as[11..08] are meaningless
+ * as[07..00] contain the asid
+ */
+
+extern inline unsigned long read_dtlb_virtual (int way)
+{
+ unsigned long tmp;
+ __asm__ __volatile__("rdtlb0 %0, %1\n\t" : "=a" (tmp), "+a" (way));
+ return tmp;
+}
+
+extern inline unsigned long read_dtlb_translation (int way)
+{
+ unsigned long tmp;
+ __asm__ __volatile__("rdtlb1 %0, %1\n\t" : "=a" (tmp), "+a" (way));
+ return tmp;
+}
+
+extern inline unsigned long read_itlb_virtual (int way)
+{
+ unsigned long tmp;
+ __asm__ __volatile__("ritlb0 %0, %1\n\t" : "=a" (tmp), "+a" (way));
+ return tmp;
+}
+
+extern inline unsigned long read_itlb_translation (int way)
+{
+ unsigned long tmp;
+ __asm__ __volatile__("ritlb1 %0, %1\n\t" : "=a" (tmp), "+a" (way));
+ return tmp;
+}
+
+#endif /* DEBUG_TLB */
+
+
+#endif /* __KERNEL__ */
+#endif /* _XTENSA_PGALLOC_H */
diff --git a/include/asm-xtensa/topology.h b/include/asm-xtensa/topology.h
new file mode 100644
index 00000000000..7309e38a0cc
--- /dev/null
+++ b/include/asm-xtensa/topology.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-xtensa/topology.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_TOPOLOGY_H
+#define _XTENSA_TOPOLOGY_H
+
+#include <asm-generic/topology.h>
+
+#endif /* _XTENSA_TOPOLOGY_H */
diff --git a/include/asm-xtensa/types.h b/include/asm-xtensa/types.h
new file mode 100644
index 00000000000..ebac0046985
--- /dev/null
+++ b/include/asm-xtensa/types.h
@@ -0,0 +1,66 @@
+/*
+ * include/asm-xtensa/types.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_TYPES_H
+#define _XTENSA_TYPES_H
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned short umode_t;
+
+/*
+ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
+ * header files exported to user space
+ */
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+#endif
+
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+#ifdef __KERNEL__
+
+typedef __signed__ char s8;
+typedef unsigned char u8;
+
+typedef __signed__ short s16;
+typedef unsigned short u16;
+
+typedef __signed__ int s32;
+typedef unsigned int u32;
+
+typedef __signed__ long long s64;
+typedef unsigned long long u64;
+
+
+#define BITS_PER_LONG 32
+
+/* Dma addresses are 32-bits wide. */
+
+typedef u32 dma_addr_t;
+
+typedef unsigned int kmem_bufctl_t;
+
+#endif /* __KERNEL__ */
+#endif
+
+#endif /* _XTENSA_TYPES_H */
diff --git a/include/asm-xtensa/uaccess.h b/include/asm-xtensa/uaccess.h
new file mode 100644
index 00000000000..35576b25c7b
--- /dev/null
+++ b/include/asm-xtensa/uaccess.h
@@ -0,0 +1,532 @@
+/*
+ * include/asm-xtensa/uaccess.h
+ *
+ * User space memory access functions
+ *
+ * These routines provide basic accessing functions to the user memory
+ * space for the kernel. This header file provides fuctions such as:
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_UACCESS_H
+#define _XTENSA_UACCESS_H
+
+#include <linux/errno.h>
+
+#define VERIFY_READ 0
+#define VERIFY_WRITE 1
+
+#ifdef __ASSEMBLY__
+
+#define _ASMLANGUAGE
+#include <asm/current.h>
+#include <asm/offsets.h>
+#include <asm/processor.h>
+
+/*
+ * These assembly macros mirror the C macros that follow below. They
+ * should always have identical functionality. See
+ * arch/xtensa/kernel/sys.S for usage.
+ */
+
+#define KERNEL_DS 0
+#define USER_DS 1
+
+#define get_ds (KERNEL_DS)
+
+/*
+ * get_fs reads current->thread.current_ds into a register.
+ * On Entry:
+ * <ad> anything
+ * <sp> stack
+ * On Exit:
+ * <ad> contains current->thread.current_ds
+ */
+ .macro get_fs ad, sp
+ GET_CURRENT(\ad,\sp)
+ l32i \ad, \ad, THREAD_CURRENT_DS
+ .endm
+
+/*
+ * set_fs sets current->thread.current_ds to some value.
+ * On Entry:
+ * <at> anything (temp register)
+ * <av> value to write
+ * <sp> stack
+ * On Exit:
+ * <at> destroyed (actually, current)
+ * <av> preserved, value to write
+ */
+ .macro set_fs at, av, sp
+ GET_CURRENT(\at,\sp)
+ s32i \av, \at, THREAD_CURRENT_DS
+ .endm
+
+/*
+ * kernel_ok determines whether we should bypass addr/size checking.
+ * See the equivalent C-macro version below for clarity.
+ * On success, kernel_ok branches to a label indicated by parameter
+ * <success>. This implies that the macro falls through to the next
+ * insruction on an error.
+ *
+ * Note that while this macro can be used independently, we designed
+ * in for optimal use in the access_ok macro below (i.e., we fall
+ * through on error).
+ *
+ * On Entry:
+ * <at> anything (temp register)
+ * <success> label to branch to on success; implies
+ * fall-through macro on error
+ * <sp> stack pointer
+ * On Exit:
+ * <at> destroyed (actually, current->thread.current_ds)
+ */
+
+#if ((KERNEL_DS != 0) || (USER_DS == 0))
+# error Assembly macro kernel_ok fails
+#endif
+ .macro kernel_ok at, sp, success
+ get_fs \at, \sp
+ beqz \at, \success
+ .endm
+
+/*
+ * user_ok determines whether the access to user-space memory is allowed.
+ * See the equivalent C-macro version below for clarity.
+ *
+ * On error, user_ok branches to a label indicated by parameter
+ * <error>. This implies that the macro falls through to the next
+ * instruction on success.
+ *
+ * Note that while this macro can be used independently, we designed
+ * in for optimal use in the access_ok macro below (i.e., we fall
+ * through on success).
+ *
+ * On Entry:
+ * <aa> register containing memory address
+ * <as> register containing memory size
+ * <at> temp register
+ * <error> label to branch to on error; implies fall-through
+ * macro on success
+ * On Exit:
+ * <aa> preserved
+ * <as> preserved
+ * <at> destroyed (actually, (TASK_SIZE + 1 - size))
+ */
+ .macro user_ok aa, as, at, error
+ movi \at, (TASK_SIZE+1)
+ bgeu \as, \at, \error
+ sub \at, \at, \as
+ bgeu \aa, \at, \error
+ .endm
+
+/*
+ * access_ok determines whether a memory access is allowed. See the
+ * equivalent C-macro version below for clarity.
+ *
+ * On error, access_ok branches to a label indicated by parameter
+ * <error>. This implies that the macro falls through to the next
+ * instruction on success.
+ *
+ * Note that we assume success is the common case, and we optimize the
+ * branch fall-through case on success.
+ *
+ * On Entry:
+ * <aa> register containing memory address
+ * <as> register containing memory size
+ * <at> temp register
+ * <sp>
+ * <error> label to branch to on error; implies fall-through
+ * macro on success
+ * On Exit:
+ * <aa> preserved
+ * <as> preserved
+ * <at> destroyed
+ */
+ .macro access_ok aa, as, at, sp, error
+ kernel_ok \at, \sp, .Laccess_ok_\@
+ user_ok \aa, \as, \at, \error
+.Laccess_ok_\@:
+ .endm
+
+/*
+ * verify_area determines whether a memory access is allowed. It's
+ * mostly an unnecessary wrapper for access_ok, but we provide it as a
+ * duplicate of the verify_area() C inline function below. See the
+ * equivalent C version below for clarity.
+ *
+ * On error, verify_area branches to a label indicated by parameter
+ * <error>. This implies that the macro falls through to the next
+ * instruction on success.
+ *
+ * Note that we assume success is the common case, and we optimize the
+ * branch fall-through case on success.
+ *
+ * On Entry:
+ * <aa> register containing memory address
+ * <as> register containing memory size
+ * <at> temp register
+ * <error> label to branch to on error; implies fall-through
+ * macro on success
+ * On Exit:
+ * <aa> preserved
+ * <as> preserved
+ * <at> destroyed
+ */
+ .macro verify_area aa, as, at, sp, error
+ access_ok \at, \aa, \as, \sp, \error
+ .endm
+
+
+#else /* __ASSEMBLY__ not defined */
+
+#include <linux/sched.h>
+#include <asm/types.h>
+
+/*
+ * The fs value determines whether argument validity checking should
+ * be performed or not. If get_fs() == USER_DS, checking is
+ * performed, with get_fs() == KERNEL_DS, checking is bypassed.
+ *
+ * For historical reasons (Data Segment Register?), these macros are
+ * grossly misnamed.
+ */
+
+#define KERNEL_DS ((mm_segment_t) { 0 })
+#define USER_DS ((mm_segment_t) { 1 })
+
+#define get_ds() (KERNEL_DS)
+#define get_fs() (current->thread.current_ds)
+#define set_fs(val) (current->thread.current_ds = (val))
+
+#define segment_eq(a,b) ((a).seg == (b).seg)
+
+#define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
+#define __user_ok(addr,size) (((size) <= TASK_SIZE)&&((addr) <= TASK_SIZE-(size)))
+#define __access_ok(addr,size) (__kernel_ok || __user_ok((addr),(size)))
+#define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size))
+
+extern inline int verify_area(int type, const void * addr, unsigned long size)
+{
+ return access_ok(type,addr,size) ? 0 : -EFAULT;
+}
+
+/*
+ * These are the main single-value transfer routines. They
+ * automatically use the right size if we just have the right pointer
+ * type.
+ *
+ * This gets kind of ugly. We want to return _two_ values in
+ * "get_user()" and yet we don't want to do any pointers, because that
+ * is too much of a performance impact. Thus we have a few rather ugly
+ * macros here, and hide all the uglyness from the user.
+ *
+ * Careful to not
+ * (a) re-use the arguments for side effects (sizeof is ok)
+ * (b) require any knowledge of processes at this stage
+ */
+#define put_user(x,ptr) __put_user_check((x),(ptr),sizeof(*(ptr)))
+#define get_user(x,ptr) __get_user_check((x),(ptr),sizeof(*(ptr)))
+
+/*
+ * The "__xxx" versions of the user access functions are versions that
+ * do not verify the address space, that must have been done previously
+ * with a separate "access_ok()" call (this is used when we do multiple
+ * accesses to the same area of user memory).
+ */
+#define __put_user(x,ptr) __put_user_nocheck((x),(ptr),sizeof(*(ptr)))
+#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
+
+
+extern long __put_user_bad(void);
+
+#define __put_user_nocheck(x,ptr,size) \
+({ \
+ long __pu_err; \
+ __put_user_size((x),(ptr),(size),__pu_err); \
+ __pu_err; \
+})
+
+#define __put_user_check(x,ptr,size) \
+({ \
+ long __pu_err = -EFAULT; \
+ __typeof__(*(ptr)) *__pu_addr = (ptr); \
+ if (access_ok(VERIFY_WRITE,__pu_addr,size)) \
+ __put_user_size((x),__pu_addr,(size),__pu_err); \
+ __pu_err; \
+})
+
+#define __put_user_size(x,ptr,size,retval) \
+do { \
+ retval = 0; \
+ switch (size) { \
+ case 1: __put_user_asm(x,ptr,retval,1,"s8i"); break; \
+ case 2: __put_user_asm(x,ptr,retval,2,"s16i"); break; \
+ case 4: __put_user_asm(x,ptr,retval,4,"s32i"); break; \
+ case 8: { \
+ __typeof__(*ptr) __v64 = x; \
+ retval = __copy_to_user(ptr,&__v64,8); \
+ break; \
+ } \
+ default: __put_user_bad(); \
+ } \
+} while (0)
+
+
+/*
+ * Consider a case of a user single load/store would cause both an
+ * unaligned exception and an MMU-related exception (unaligned
+ * exceptions happen first):
+ *
+ * User code passes a bad variable ptr to a system call.
+ * Kernel tries to access the variable.
+ * Unaligned exception occurs.
+ * Unaligned exception handler tries to make aligned accesses.
+ * Double exception occurs for MMU-related cause (e.g., page not mapped).
+ * do_page_fault() thinks the fault address belongs to the kernel, not the
+ * user, and panics.
+ *
+ * The kernel currently prohibits user unaligned accesses. We use the
+ * __check_align_* macros to check for unaligned addresses before
+ * accessing user space so we don't crash the kernel. Both
+ * __put_user_asm and __get_user_asm use these alignment macros, so
+ * macro-specific labels such as 0f, 1f, %0, %2, and %3 must stay in
+ * sync.
+ */
+
+#define __check_align_1 ""
+
+#define __check_align_2 \
+ " _bbci.l %2, 0, 1f \n" \
+ " movi %0, %3 \n" \
+ " _j 2f \n"
+
+#define __check_align_4 \
+ " _bbsi.l %2, 0, 0f \n" \
+ " _bbci.l %2, 1, 1f \n" \
+ "0: movi %0, %3 \n" \
+ " _j 2f \n"
+
+
+/*
+ * We don't tell gcc that we are accessing memory, but this is OK
+ * because we do not write to any memory gcc knows about, so there
+ * are no aliasing issues.
+ *
+ * WARNING: If you modify this macro at all, verify that the
+ * __check_align_* macros still work.
+ */
+#define __put_user_asm(x, addr, err, align, insn) \
+ __asm__ __volatile__( \
+ __check_align_##align \
+ "1: "insn" %1, %2, 0 \n" \
+ "2: \n" \
+ " .section .fixup,\"ax\" \n" \
+ " .align 4 \n" \
+ "4: \n" \
+ " .long 2b \n" \
+ "5: \n" \
+ " l32r %2, 4b \n" \
+ " movi %0, %3 \n" \
+ " jx %2 \n" \
+ " .previous \n" \
+ " .section __ex_table,\"a\" \n" \
+ " .long 1b, 5b \n" \
+ " .previous" \
+ :"=r" (err) \
+ :"r" ((int)(x)), "r" (addr), "i" (-EFAULT), "0" (err))
+
+#define __get_user_nocheck(x,ptr,size) \
+({ \
+ long __gu_err, __gu_val; \
+ __get_user_size(__gu_val,(ptr),(size),__gu_err); \
+ (x) = (__typeof__(*(ptr)))__gu_val; \
+ __gu_err; \
+})
+
+#define __get_user_check(x,ptr,size) \
+({ \
+ long __gu_err = -EFAULT, __gu_val = 0; \
+ const __typeof__(*(ptr)) *__gu_addr = (ptr); \
+ if (access_ok(VERIFY_READ,__gu_addr,size)) \
+ __get_user_size(__gu_val,__gu_addr,(size),__gu_err); \
+ (x) = (__typeof__(*(ptr)))__gu_val; \
+ __gu_err; \
+})
+
+extern long __get_user_bad(void);
+
+#define __get_user_size(x,ptr,size,retval) \
+do { \
+ retval = 0; \
+ switch (size) { \
+ case 1: __get_user_asm(x,ptr,retval,1,"l8ui"); break; \
+ case 2: __get_user_asm(x,ptr,retval,2,"l16ui"); break; \
+ case 4: __get_user_asm(x,ptr,retval,4,"l32i"); break; \
+ case 8: retval = __copy_from_user(&x,ptr,8); break; \
+ default: (x) = __get_user_bad(); \
+ } \
+} while (0)
+
+
+/*
+ * WARNING: If you modify this macro at all, verify that the
+ * __check_align_* macros still work.
+ */
+#define __get_user_asm(x, addr, err, align, insn) \
+ __asm__ __volatile__( \
+ __check_align_##align \
+ "1: "insn" %1, %2, 0 \n" \
+ "2: \n" \
+ " .section .fixup,\"ax\" \n" \
+ " .align 4 \n" \
+ "4: \n" \
+ " .long 2b \n" \
+ "5: \n" \
+ " l32r %2, 4b \n" \
+ " movi %1, 0 \n" \
+ " movi %0, %3 \n" \
+ " jx %2 \n" \
+ " .previous \n" \
+ " .section __ex_table,\"a\" \n" \
+ " .long 1b, 5b \n" \
+ " .previous" \
+ :"=r" (err), "=r" (x) \
+ :"r" (addr), "i" (-EFAULT), "0" (err))
+
+
+/*
+ * Copy to/from user space
+ */
+
+/*
+ * We use a generic, arbitrary-sized copy subroutine. The Xtensa
+ * architecture would cause heavy code bloat if we tried to inline
+ * these functions and provide __constant_copy_* equivalents like the
+ * i386 versions. __xtensa_copy_user is quite efficient. See the
+ * .fixup section of __xtensa_copy_user for a discussion on the
+ * X_zeroing equivalents for Xtensa.
+ */
+
+extern unsigned __xtensa_copy_user(void *to, const void *from, unsigned n);
+#define __copy_user(to,from,size) __xtensa_copy_user(to,from,size)
+
+
+static inline unsigned long
+__generic_copy_from_user_nocheck(void *to, const void *from, unsigned long n)
+{
+ return __copy_user(to,from,n);
+}
+
+static inline unsigned long
+__generic_copy_to_user_nocheck(void *to, const void *from, unsigned long n)
+{
+ return __copy_user(to,from,n);
+}
+
+static inline unsigned long
+__generic_copy_to_user(void *to, const void *from, unsigned long n)
+{
+ prefetch(from);
+ if (access_ok(VERIFY_WRITE, to, n))
+ return __copy_user(to,from,n);
+ return n;
+}
+
+static inline unsigned long
+__generic_copy_from_user(void *to, const void *from, unsigned long n)
+{
+ prefetchw(to);
+ if (access_ok(VERIFY_READ, from, n))
+ return __copy_user(to,from,n);
+ else
+ memset(to, 0, n);
+ return n;
+}
+
+#define copy_to_user(to,from,n) __generic_copy_to_user((to),(from),(n))
+#define copy_from_user(to,from,n) __generic_copy_from_user((to),(from),(n))
+#define __copy_to_user(to,from,n) __generic_copy_to_user_nocheck((to),(from),(n))
+#define __copy_from_user(to,from,n) __generic_copy_from_user_nocheck((to),(from),(n))
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
+
+/*
+ * We need to return the number of bytes not cleared. Our memset()
+ * returns zero if a problem occurs while accessing user-space memory.
+ * In that event, return no memory cleared. Otherwise, zero for
+ * success.
+ */
+
+extern inline unsigned long
+__xtensa_clear_user(void *addr, unsigned long size)
+{
+ if ( ! memset(addr, 0, size) )
+ return size;
+ return 0;
+}
+
+extern inline unsigned long
+clear_user(void *addr, unsigned long size)
+{
+ if (access_ok(VERIFY_WRITE, addr, size))
+ return __xtensa_clear_user(addr, size);
+ return size ? -EFAULT : 0;
+}
+
+#define __clear_user __xtensa_clear_user
+
+
+extern long __strncpy_user(char *, const char *, long);
+#define __strncpy_from_user __strncpy_user
+
+extern inline long
+strncpy_from_user(char *dst, const char *src, long count)
+{
+ if (access_ok(VERIFY_READ, src, 1))
+ return __strncpy_from_user(dst, src, count);
+ return -EFAULT;
+}
+
+
+#define strlen_user(str) strnlen_user((str), TASK_SIZE - 1)
+
+/*
+ * Return the size of a string (including the ending 0!)
+ */
+extern long __strnlen_user(const char *, long);
+
+extern inline long strnlen_user(const char *str, long len)
+{
+ unsigned long top = __kernel_ok ? ~0UL : TASK_SIZE - 1;
+
+ if ((unsigned long)str > top)
+ return 0;
+ return __strnlen_user(str, len);
+}
+
+
+struct exception_table_entry
+{
+ unsigned long insn, fixup;
+};
+
+/* Returns 0 if exception not found and fixup.unit otherwise. */
+
+extern unsigned long search_exception_table(unsigned long addr);
+extern void sort_exception_table(void);
+
+/* Returns the new pc */
+#define fixup_exception(map_reg, fixup_unit, pc) \
+({ \
+ fixup_unit; \
+})
+
+#endif /* __ASSEMBLY__ */
+#endif /* _XTENSA_UACCESS_H */
diff --git a/include/asm-xtensa/ucontext.h b/include/asm-xtensa/ucontext.h
new file mode 100644
index 00000000000..94c94ed3e00
--- /dev/null
+++ b/include/asm-xtensa/ucontext.h
@@ -0,0 +1,22 @@
+/*
+ * include/asm-xtensa/ucontext.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_UCONTEXT_H
+#define _XTENSA_UCONTEXT_H
+
+struct ucontext {
+ unsigned long uc_flags;
+ struct ucontext *uc_link;
+ stack_t uc_stack;
+ struct sigcontext uc_mcontext;
+ sigset_t uc_sigmask; /* mask last for extensibility */
+};
+
+#endif /* _XTENSA_UCONTEXT_H */
diff --git a/include/asm-xtensa/unaligned.h b/include/asm-xtensa/unaligned.h
new file mode 100644
index 00000000000..28220890d0a
--- /dev/null
+++ b/include/asm-xtensa/unaligned.h
@@ -0,0 +1,28 @@
+/*
+ * include/asm-xtensa/unaligned.h
+ *
+ * Xtensa doesn't handle unaligned accesses efficiently.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_UNALIGNED_H
+#define _XTENSA_UNALIGNED_H
+
+#include <linux/string.h>
+
+/* Use memmove here, so gcc does not insert a __builtin_memcpy. */
+
+#define get_unaligned(ptr) \
+ ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
+
+#define put_unaligned(val, ptr) \
+ ({ __typeof__(*(ptr)) __tmp = (val); \
+ memmove((ptr), &__tmp, sizeof(*(ptr))); \
+ (void)0; })
+
+#endif /* _XTENSA_UNALIGNED_H */
diff --git a/include/asm-xtensa/unistd.h b/include/asm-xtensa/unistd.h
new file mode 100644
index 00000000000..64c64dd83ba
--- /dev/null
+++ b/include/asm-xtensa/unistd.h
@@ -0,0 +1,537 @@
+/*
+ * include/asm-xtensa/unistd.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_UNISTD_H
+#define _XTENSA_UNISTD_H
+
+#include <linux/linkage.h>
+
+//#define __NR_setup 0 /* used only by init, to get system going */
+#define __NR_spill 0
+#define __NR_exit 1
+#define __NR_fork 2
+#define __NR_read 3
+#define __NR_write 4
+#define __NR_open 5
+#define __NR_close 6
+#define __NR_waitpid 7
+#define __NR_creat 8
+#define __NR_link 9
+#define __NR_unlink 10
+#define __NR_execve 11
+#define __NR_chdir 12
+#define __NR_time 13
+#define __NR_mknod 14
+#define __NR_chmod 15
+#define __NR_lchown 16
+#define __NR_break 17
+#define __NR_oldstat 18
+#define __NR_lseek 19
+#define __NR_getpid 20
+#define __NR_mount 21
+#define __NR_oldumount 22
+#define __NR_setuid 23
+#define __NR_getuid 24
+#define __NR_stime 25
+#define __NR_ptrace 26
+#define __NR_alarm 27
+#define __NR_oldfstat 28
+#define __NR_pause 29
+#define __NR_utime 30
+#define __NR_stty 31
+#define __NR_gtty 32
+#define __NR_access 33
+#define __NR_nice 34
+#define __NR_ftime 35
+#define __NR_sync 36
+#define __NR_kill 37
+#define __NR_rename 38
+#define __NR_mkdir 39
+#define __NR_rmdir 40
+#define __NR_dup 41
+#define __NR_pipe 42
+#define __NR_times 43
+#define __NR_prof 44
+#define __NR_brk 45
+#define __NR_setgid 46
+#define __NR_getgid 47
+#define __NR_signal 48
+#define __NR_geteuid 49
+#define __NR_getegid 50
+#define __NR_acct 51
+#define __NR_umount 52
+#define __NR_lock 53
+#define __NR_ioctl 54
+#define __NR_fcntl 55
+#define __NR_mpx 56
+#define __NR_setpgid 57
+#define __NR_ulimit 58
+#define __NR_oldolduname 59
+#define __NR_umask 60
+#define __NR_chroot 61
+#define __NR_ustat 62
+#define __NR_dup2 63
+#define __NR_getppid 64
+#define __NR_getpgrp 65
+#define __NR_setsid 66
+#define __NR_sigaction 67
+#define __NR_sgetmask 68
+#define __NR_ssetmask 69
+#define __NR_setreuid 70
+#define __NR_setregid 71
+#define __NR_sigsuspend 72
+#define __NR_sigpending 73
+#define __NR_sethostname 74
+#define __NR_setrlimit 75
+#define __NR_getrlimit 76 /* Back compatible 2Gig limited rlimit */
+#define __NR_getrusage 77
+#define __NR_gettimeofday 78
+#define __NR_settimeofday 79
+#define __NR_getgroups 80
+#define __NR_setgroups 81
+#define __NR_select 82
+#define __NR_symlink 83
+#define __NR_oldlstat 84
+#define __NR_readlink 85
+#define __NR_uselib 86
+#define __NR_swapon 87
+#define __NR_reboot 88
+#define __NR_readdir 89
+#define __NR_mmap 90
+#define __NR_munmap 91
+#define __NR_truncate 92
+#define __NR_ftruncate 93
+#define __NR_fchmod 94
+#define __NR_fchown 95
+#define __NR_getpriority 96
+#define __NR_setpriority 97
+#define __NR_profil 98
+#define __NR_statfs 99
+#define __NR_fstatfs 100
+#define __NR_ioperm 101
+#define __NR_socketcall 102
+#define __NR_syslog 103
+#define __NR_setitimer 104
+#define __NR_getitimer 105
+#define __NR_stat 106
+#define __NR_lstat 107
+#define __NR_fstat 108
+#define __NR_olduname 109
+#define __NR_iopl 110
+#define __NR_vhangup 111
+#define __NR_idle 112
+#define __NR_vm86 113
+#define __NR_wait4 114
+#define __NR_swapoff 115
+#define __NR_sysinfo 116
+#define __NR_ipc 117
+#define __NR_fsync 118
+#define __NR_sigreturn 119
+#define __NR_clone 120
+#define __NR_setdomainname 121
+#define __NR_uname 122
+#define __NR_modify_ldt 123
+#define __NR_adjtimex 124
+#define __NR_mprotect 125
+#define __NR_sigprocmask 126
+#define __NR_create_module 127
+#define __NR_init_module 128
+#define __NR_delete_module 129
+#define __NR_get_kernel_syms 130
+#define __NR_quotactl 131
+#define __NR_getpgid 132
+#define __NR_fchdir 133
+#define __NR_bdflush 134
+#define __NR_sysfs 135
+#define __NR_personality 136
+#define __NR_afs_syscall 137 /* Syscall for Andrew File System */
+#define __NR_setfsuid 138
+#define __NR_setfsgid 139
+#define __NR__llseek 140
+#define __NR_getdents 141
+#define __NR__newselect 142
+#define __NR_flock 143
+#define __NR_msync 144
+#define __NR_readv 145
+#define __NR_writev 146
+#define __NR_cacheflush 147
+#define __NR_cachectl 148
+#define __NR_sysxtensa 149
+#define __NR_sysdummy 150
+#define __NR_getsid 151
+#define __NR_fdatasync 152
+#define __NR__sysctl 153
+#define __NR_mlock 154
+#define __NR_munlock 155
+#define __NR_mlockall 156
+#define __NR_munlockall 157
+#define __NR_sched_setparam 158
+#define __NR_sched_getparam 159
+#define __NR_sched_setscheduler 160
+#define __NR_sched_getscheduler 161
+#define __NR_sched_yield 162
+#define __NR_sched_get_priority_max 163
+#define __NR_sched_get_priority_min 164
+#define __NR_sched_rr_get_interval 165
+#define __NR_nanosleep 166
+#define __NR_mremap 167
+#define __NR_accept 168
+#define __NR_bind 169
+#define __NR_connect 170
+#define __NR_getpeername 171
+#define __NR_getsockname 172
+#define __NR_getsockopt 173
+#define __NR_listen 174
+#define __NR_recv 175
+#define __NR_recvfrom 176
+#define __NR_recvmsg 177
+#define __NR_send 178
+#define __NR_sendmsg 179
+#define __NR_sendto 180
+#define __NR_setsockopt 181
+#define __NR_shutdown 182
+#define __NR_socket 183
+#define __NR_socketpair 184
+#define __NR_setresuid 185
+#define __NR_getresuid 186
+#define __NR_query_module 187
+#define __NR_poll 188
+#define __NR_nfsservctl 189
+#define __NR_setresgid 190
+#define __NR_getresgid 191
+#define __NR_prctl 192
+#define __NR_rt_sigreturn 193
+#define __NR_rt_sigaction 194
+#define __NR_rt_sigprocmask 195
+#define __NR_rt_sigpending 196
+#define __NR_rt_sigtimedwait 197
+#define __NR_rt_sigqueueinfo 198
+#define __NR_rt_sigsuspend 199
+#define __NR_pread 200
+#define __NR_pwrite 201
+#define __NR_chown 202
+#define __NR_getcwd 203
+#define __NR_capget 204
+#define __NR_capset 205
+#define __NR_sigaltstack 206
+#define __NR_sendfile 207
+#define __NR_streams1 208 /* some people actually want it */
+#define __NR_streams2 209 /* some people actually want it */
+#define __NR_mmap2 210
+#define __NR_truncate64 211
+#define __NR_ftruncate64 212
+#define __NR_stat64 213
+#define __NR_lstat64 214
+#define __NR_fstat64 215
+#define __NR_pivot_root 216
+#define __NR_mincore 217
+#define __NR_madvise 218
+#define __NR_getdents64 219
+#define __NR_vfork 220
+
+/* Keep this last; should always equal the last valid call number. */
+#define __NR_Linux_syscalls 220
+
+/* user-visible error numbers are in the range -1 - -125: see
+ * <asm-xtensa/errno.h> */
+
+#define SYSXTENSA_RESERVED 0 /* don't use this */
+#define SYSXTENSA_ATOMIC_SET 1 /* set variable */
+#define SYSXTENSA_ATOMIC_EXG_ADD 2 /* exchange memory and add */
+#define SYSXTENSA_ATOMIC_ADD 3 /* add to memory */
+#define SYSXTENSA_ATOMIC_CMP_SWP 4 /* compare and swap */
+
+#define SYSXTENSA_COUNT 5 /* count of syscall0 functions*/
+
+#ifdef __KERNEL__
+#define __syscall_return(type, res) return ((type)(res))
+#else
+#define __syscall_return(type, res) \
+do { \
+ if ((unsigned long)(res) >= (unsigned long)(-125)) { \
+ /* Avoid using "res" which is declared to be in register r2; \
+ * errno might expand to a function call and clobber it. */ \
+ int __err = -(res); \
+ errno = __err; \
+ res = -1; \
+ } \
+ return (type) (res); \
+} while (0)
+#endif
+
+
+/* Tensilica's xt-xcc compiler is much more agressive at code
+ * optimization than gcc. Multiple __asm__ statements are
+ * insufficient for xt-xcc because subsequent optimization passes
+ * (beyond the front-end that knows of __asm__ statements and other
+ * such GNU Extensions to C) can modify the register selection for
+ * containment of C variables.
+ *
+ * xt-xcc cannot modify the contents of a single __asm__ statement, so
+ * we create single-asm versions of the syscall macros that are
+ * suitable and optimal for both xt-xcc and gcc.
+ *
+ * Linux takes system-call arguments in registers. The following
+ * design is optimized for user-land apps (e.g., glibc) which
+ * typically have a function wrapper around the "syscall" assembly
+ * instruction. It satisfies the Xtensa ABI while minizing argument
+ * shifting.
+ *
+ * The Xtensa ABI and software conventions require the system-call
+ * number in a2. If an argument exists in a2, we move it to the next
+ * available register. Note that for improved efficiency, we do NOT
+ * shift all parameters down one register to maintain the original
+ * order.
+ *
+ * At best case (zero arguments), we just write the syscall number to
+ * a2. At worst case (1 to 6 arguments), we move the argument in a2
+ * to the next available register, then write the syscall number to
+ * a2.
+ *
+ * For clarity, the following truth table enumerates all possibilities.
+ *
+ * arguments syscall number arg0, arg1, arg2, arg3, arg4, arg5
+ * --------- -------------- ----------------------------------
+ * 0 a2
+ * 1 a2 a3
+ * 2 a2 a4, a3
+ * 3 a2 a5, a3, a4
+ * 4 a2 a6, a3, a4, a5
+ * 5 a2 a7, a3, a4, a5, a6
+ * 6 a2 a8, a3, a4, a5, a6, a7
+ */
+
+#define _syscall0(type,name) \
+type name(void) \
+{ \
+long __res; \
+__asm__ __volatile__ ( \
+ " movi a2, %1 \n" \
+ " syscall \n" \
+ " mov %0, a2 \n" \
+ : "=a" (__res) \
+ : "i" (__NR_##name) \
+ : "a2" \
+ ); \
+__syscall_return(type,__res); \
+}
+
+#define _syscall1(type,name,type0,arg0) \
+type name(type0 arg0) \
+{ \
+long __res; \
+__asm__ __volatile__ ( \
+ " mov a3, %2 \n" \
+ " movi a2, %1 \n" \
+ " syscall \n" \
+ " mov %0, a2 \n" \
+ : "=a" (__res) \
+ : "i" (__NR_##name), "a" (arg0) \
+ : "a2", "a3" \
+ ); \
+__syscall_return(type,__res); \
+}
+
+#define _syscall2(type,name,type0,arg0,type1,arg1) \
+type name(type0 arg0,type1 arg1) \
+{ \
+long __res; \
+__asm__ __volatile__ ( \
+ " mov a4, %2 \n" \
+ " mov a3, %3 \n" \
+ " movi a2, %1 \n" \
+ " syscall \n" \
+ " mov %0, a2 \n" \
+ : "=a" (__res) \
+ : "i" (__NR_##name), "a" (arg0), "a" (arg1) \
+ : "a2", "a3", "a4" \
+ ); \
+__syscall_return(type,__res); \
+}
+
+#define _syscall3(type,name,type0,arg0,type1,arg1,type2,arg2) \
+type name(type0 arg0,type1 arg1,type2 arg2) \
+{ \
+long __res; \
+__asm__ __volatile__ ( \
+ " mov a5, %2 \n" \
+ " mov a4, %4 \n" \
+ " mov a3, %3 \n" \
+ " movi a2, %1 \n" \
+ " syscall \n" \
+ " mov %0, a2 \n" \
+ : "=a" (__res) \
+ : "i" (__NR_##name), "a" (arg0), "a" (arg1), "a" (arg2) \
+ : "a2", "a3", "a4", "a5" \
+ ); \
+__syscall_return(type,__res); \
+}
+
+#define _syscall4(type,name,type0,arg0,type1,arg1,type2,arg2,type3,arg3) \
+type name(type0 arg0,type1 arg1,type2 arg2,type3 arg3) \
+{ \
+long __res; \
+__asm__ __volatile__ ( \
+ " mov a6, %2 \n" \
+ " mov a5, %5 \n" \
+ " mov a4, %4 \n" \
+ " mov a3, %3 \n" \
+ " movi a2, %1 \n" \
+ " syscall \n" \
+ " mov %0, a2 \n" \
+ : "=a" (__res) \
+ : "i" (__NR_##name), "a" (arg0), "a" (arg1), "a" (arg2), "a" (arg3) \
+ : "a2", "a3", "a4", "a5", "a6" \
+ ); \
+__syscall_return(type,__res); \
+}
+
+/* Note that we save and restore the a7 frame pointer.
+ * Including a7 in the clobber list doesn't do what you'd expect.
+ */
+#define _syscall5(type,name,type0,arg0,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+type name(type0 arg0,type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
+{ \
+long __res; \
+__asm__ __volatile__ ( \
+ " mov a9, a7 \n" \
+ " mov a7, %2 \n" \
+ " mov a6, %6 \n" \
+ " mov a5, %5 \n" \
+ " mov a4, %4 \n" \
+ " mov a3, %3 \n" \
+ " movi a2, %1 \n" \
+ " syscall \n" \
+ " mov a7, a9 \n" \
+ " mov %0, a2 \n" \
+ : "=a" (__res) \
+ : "i" (__NR_##name), "a" (arg0), "a" (arg1), "a" (arg2), \
+ "a" (arg3), "a" (arg4) \
+ : "a2", "a3", "a4", "a5", "a6", "a9" \
+ ); \
+__syscall_return(type,__res); \
+}
+
+/* Note that we save and restore the a7 frame pointer.
+ * Including a7 in the clobber list doesn't do what you'd expect.
+ */
+#define _syscall6(type,name,type0,arg0,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
+type name(type0 arg0,type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
+{ \
+long __res; \
+__asm__ __volatile__ ( \
+ " mov a9, a7 \n" \
+ " mov a8, %2 \n" \
+ " mov a7, %7 \n" \
+ " mov a6, %6 \n" \
+ " mov a5, %5 \n" \
+ " mov a4, %4 \n" \
+ " mov a3, %3 \n" \
+ " movi a2, %1 \n" \
+ " syscall \n" \
+ " mov a7, a9 \n" \
+ " mov %0, a2 \n" \
+ : "=a" (__res) \
+ : "i" (__NR_##name), "a" (arg0), "a" (arg1), "a" (arg2), \
+ "a" (arg3), "a" (arg4), "a" (arg5) \
+ : "a2", "a3", "a4", "a5", "a6", "a8", "a9" \
+ ); \
+__syscall_return(type,__res); \
+}
+
+
+#ifdef __KERNEL_SYSCALLS__
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <linux/syscalls.h>
+
+/*
+ * we need this inline - forking from kernel space will result
+ * in NO COPY ON WRITE (!!!), until an execve is executed. This
+ * is no problem, but for the stack. This is handled by not letting
+ * main() use the stack at all after fork(). Thus, no function
+ * calls - which means inline code for fork too, as otherwise we
+ * would use the stack upon exit from 'fork()'.
+ *
+ * Actually only pause and fork are needed inline, so that there
+ * won't be any messing with the stack from main(), but we define
+ * some others too.
+ */
+
+#define __NR__exit __NR_exit
+
+static __inline__ _syscall0(int,pause)
+//static __inline__ _syscall1(int,setup,int,magic) FIXME
+static __inline__ _syscall0(int,sync)
+static __inline__ _syscall0(pid_t,setsid)
+static __inline__ _syscall3(int,write,int,fd,const char *,buf,off_t,count)
+static __inline__ _syscall3(int,read,int,fd,char *,buf,off_t,count)
+static __inline__ _syscall3(off_t,lseek,int,fd,off_t,offset,int,count)
+static __inline__ _syscall1(int,dup,int,fd)
+static __inline__ _syscall3(int,execve,const char*,file,char**,argv,char**,envp)
+static __inline__ _syscall3(int,open,const char *,file,int,flag,int,mode)
+static __inline__ _syscall1(int,close,int,fd)
+static __inline__ _syscall1(int,_exit,int,exitcode)
+static __inline__ _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
+static __inline__ _syscall1(int,delete_module,const char *,name)
+
+struct stat;
+static __inline__ _syscall2(int,fstat,int,fd,struct stat *,buf)
+static __inline__ _syscall0(pid_t,getpid)
+static __inline__ _syscall2(int,kill,int,pid,int,sig)
+static __inline__ _syscall2(int,stat,const char *, path,struct stat *,buf)
+static __inline__ _syscall1(int,unlink,char *,pathname)
+
+
+
+extern pid_t waitpid(int, int*, int );
+static __inline__ pid_t wait(int * wait_stat)
+{
+ return waitpid(-1,wait_stat,0);
+}
+#endif
+
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+
+#ifdef __KERNEL__
+#define __ARCH_WANT_IPC_PARSE_VERSION
+#define __ARCH_WANT_OLD_READDIR
+#define __ARCH_WANT_OLD_STAT
+#define __ARCH_WANT_STAT64
+#define __ARCH_WANT_SYS_ALARM
+#define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_SYS_PAUSE
+#define __ARCH_WANT_SYS_SGETMASK
+#define __ARCH_WANT_SYS_SIGNAL
+#define __ARCH_WANT_SYS_TIME
+#define __ARCH_WANT_SYS_UTIME
+#define __ARCH_WANT_SYS_WAITPID
+#define __ARCH_WANT_SYS_SOCKETCALL
+#define __ARCH_WANT_SYS_FADVISE64
+#define __ARCH_WANT_SYS_GETPGRP
+#define __ARCH_WANT_SYS_LLSEEK
+#define __ARCH_WANT_SYS_NICE
+#define __ARCH_WANT_SYS_OLD_GETRLIMIT
+#define __ARCH_WANT_SYS_OLDUMOUNT
+#define __ARCH_WANT_SYS_SIGPENDING
+#define __ARCH_WANT_SYS_SIGPROCMASK
+#define __ARCH_WANT_SYS_RT_SIGACTION
+#endif
+
+
+
+#endif /* _XTENSA_UNISTD_H */
diff --git a/include/asm-xtensa/user.h b/include/asm-xtensa/user.h
new file mode 100644
index 00000000000..2c3ed23354a
--- /dev/null
+++ b/include/asm-xtensa/user.h
@@ -0,0 +1,20 @@
+/*
+ * include/asm-xtensa/user.h
+ *
+ * Xtensa Processor version.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_USER_H
+#define _XTENSA_USER_H
+
+/* This file usually defines a 'struct user' structure. However, it it only
+ * used for a.out file, which are not supported on Xtensa.
+ */
+
+#endif /* _XTENSA_USER_H */
diff --git a/include/asm-xtensa/vga.h b/include/asm-xtensa/vga.h
new file mode 100644
index 00000000000..23d82f6acb5
--- /dev/null
+++ b/include/asm-xtensa/vga.h
@@ -0,0 +1,19 @@
+/*
+ * include/asm-xtensa/vga.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_VGA_H
+#define _XTENSA_VGA_H
+
+#define VGA_MAP_MEM(x) (unsigned long)phys_to_virt(x)
+
+#define vga_readb(x) (*(x))
+#define vga_writeb(x,y) (*(y) = (x))
+
+#endif
diff --git a/include/asm-xtensa/xor.h b/include/asm-xtensa/xor.h
new file mode 100644
index 00000000000..e7b1f083991
--- /dev/null
+++ b/include/asm-xtensa/xor.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-xtensa/xor.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_XOR_H
+#define _XTENSA_XOR_H
+
+#include <asm-generic/xor.h>
+
+#endif
diff --git a/include/asm-xtensa/xtensa/cacheasm.h b/include/asm-xtensa/xtensa/cacheasm.h
new file mode 100644
index 00000000000..0cdbb0bf180
--- /dev/null
+++ b/include/asm-xtensa/xtensa/cacheasm.h
@@ -0,0 +1,708 @@
+#ifndef XTENSA_CACHEASM_H
+#define XTENSA_CACHEASM_H
+
+/*
+ * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
+ *
+ * include/asm-xtensa/xtensa/cacheasm.h -- assembler-specific cache
+ * related definitions that depend on CORE configuration.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2002 Tensilica Inc.
+ */
+
+
+#include <xtensa/coreasm.h>
+
+
+/*
+ * This header file defines assembler macros of the form:
+ * <x>cache_<func>
+ * where <x> is 'i' or 'd' for instruction and data caches,
+ * and <func> indicates the function of the macro.
+ *
+ * The following functions <func> are defined,
+ * and apply only to the specified cache (I or D):
+ *
+ * reset
+ * Resets the cache.
+ *
+ * sync
+ * Makes sure any previous cache instructions have been completed;
+ * ie. makes sure any previous cache control operations
+ * have had full effect and been synchronized to memory.
+ * Eg. any invalidate completed [so as not to generate a hit],
+ * any writebacks or other pipelined writes written to memory, etc.
+ *
+ * invalidate_line (single cache line)
+ * invalidate_region (specified memory range)
+ * invalidate_all (entire cache)
+ * Invalidates all cache entries that cache
+ * data from the specified memory range.
+ * NOTE: locked entries are not invalidated.
+ *
+ * writeback_line (single cache line)
+ * writeback_region (specified memory range)
+ * writeback_all (entire cache)
+ * Writes back to memory all dirty cache entries
+ * that cache data from the specified memory range,
+ * and marks these entries as clean.
+ * NOTE: on some future implementations, this might
+ * also invalidate.
+ * NOTE: locked entries are written back, but never invalidated.
+ * NOTE: instruction caches never implement writeback.
+ *
+ * writeback_inv_line (single cache line)
+ * writeback_inv_region (specified memory range)
+ * writeback_inv_all (entire cache)
+ * Writes back to memory all dirty cache entries
+ * that cache data from the specified memory range,
+ * and invalidates these entries (including all clean
+ * cache entries that cache data from that range).
+ * NOTE: locked entries are written back but not invalidated.
+ * NOTE: instruction caches never implement writeback.
+ *
+ * lock_line (single cache line)
+ * lock_region (specified memory range)
+ * Prefetch and lock the specified memory range into cache.
+ * NOTE: if any part of the specified memory range cannot
+ * be locked, a ??? exception occurs. These macros don't
+ * do anything special (yet anyway) to handle this situation.
+ *
+ * unlock_line (single cache line)
+ * unlock_region (specified memory range)
+ * unlock_all (entire cache)
+ * Unlock cache entries that cache the specified memory range.
+ * Entries not already locked are unaffected.
+ */
+
+
+
+/*************************** GENERIC -- ALL CACHES ***************************/
+
+
+/*
+ * The following macros assume the following cache size/parameter limits
+ * in the current Xtensa core implementation:
+ * cache size: 1024 bytes minimum
+ * line size: 16 - 64 bytes
+ * way count: 1 - 4
+ *
+ * Minimum entries per way (ie. per associativity) = 1024 / 64 / 4 = 4
+ * Hence the assumption that each loop can execute four cache instructions.
+ *
+ * Correspondingly, the offset range of instructions is assumed able to cover
+ * four lines, ie. offsets {0,1,2,3} * line_size are assumed valid for
+ * both hit and indexed cache instructions. Ie. these offsets are all
+ * valid: 0, 16, 32, 48, 64, 96, 128, 192 (for line sizes 16, 32, 64).
+ * This is true of all original cache instructions
+ * (dhi, ihi, dhwb, dhwbi, dii, iii) which have offsets
+ * of 0 to 1020 in multiples of 4 (ie. 8 bits shifted by 2).
+ * This is also true of subsequent cache instructions
+ * (dhu, ihu, diu, iiu, diwb, diwbi, dpfl, ipfl) which have offsets
+ * of 0 to 240 in multiples of 16 (ie. 4 bits shifted by 4).
+ *
+ * (Maximum cache size, currently 32k, doesn't affect the following macros.
+ * Cache ways > MMU min page size cause aliasing but that's another matter.)
+ */
+
+
+
+/*
+ * Macro to apply an 'indexed' cache instruction to the entire cache.
+ *
+ * Parameters:
+ * cainst instruction/ that takes an address register parameter
+ * and an offset parameter (in range 0 .. 3*linesize).
+ * size size of cache in bytes
+ * linesize size of cache line in bytes
+ * assoc_or1 number of associativities (ways/sets) in cache
+ * if all sets affected by cainst,
+ * or 1 if only one set (or not all sets) of the cache
+ * is affected by cainst (eg. DIWB or DIWBI [not yet ISA defined]).
+ * aa, ab unique address registers (temporaries)
+ */
+
+ .macro cache_index_all cainst, size, linesize, assoc_or1, aa, ab
+
+ // Sanity-check on cache parameters:
+ .ifne (\size % (\linesize * \assoc_or1 * 4))
+ .err // cache configuration outside expected/supported range!
+ .endif
+
+ // \size byte cache, \linesize byte lines, \assoc_or1 way(s) affected by each \cainst.
+ movi \aa, (\size / (\linesize * \assoc_or1 * 4))
+ // Possible improvement: need only loop if \aa > 1 ;
+ // however that particular condition is highly unlikely.
+ movi \ab, 0 // to iterate over cache
+ floop \aa, cachex\@
+ \cainst \ab, 0*\linesize
+ \cainst \ab, 1*\linesize
+ \cainst \ab, 2*\linesize
+ \cainst \ab, 3*\linesize
+ addi \ab, \ab, 4*\linesize // move to next line
+ floopend \aa, cachex\@
+
+ .endm
+
+
+/*
+ * Macro to apply a 'hit' cache instruction to a memory region,
+ * ie. to any cache entries that cache a specified portion (region) of memory.
+ * Takes care of the unaligned cases, ie. may apply to one
+ * more cache line than $asize / lineSize if $aaddr is not aligned.
+ *
+ *
+ * Parameters are:
+ * cainst instruction/macro that takes an address register parameter
+ * and an offset parameter (currently always zero)
+ * and generates a cache instruction (eg. "dhi", "dhwb", "ihi", etc.)
+ * linesize_log2 log2(size of cache line in bytes)
+ * addr register containing start address of region (clobbered)
+ * asize register containing size of the region in bytes (clobbered)
+ * askew unique register used as temporary
+ *
+ * !?!?! 2DO: optimization: iterate max(cache_size and \asize) / linesize
+ */
+
+ .macro cache_hit_region cainst, linesize_log2, addr, asize, askew
+
+ // Make \asize the number of iterations:
+ extui \askew, \addr, 0, \linesize_log2 // get unalignment amount of \addr
+ add \asize, \asize, \askew // ... and add it to \asize
+ addi \asize, \asize, (1 << \linesize_log2) - 1 // round up!
+ srli \asize, \asize, \linesize_log2
+
+ // Iterate over region:
+ floopnez \asize, cacheh\@
+ \cainst \addr, 0
+ addi \addr, \addr, (1 << \linesize_log2) // move to next line
+ floopend \asize, cacheh\@
+
+ .endm
+
+
+
+
+
+/*************************** INSTRUCTION CACHE ***************************/
+
+
+/*
+ * Reset/initialize the instruction cache by simply invalidating it:
+ * (need to unlock first also, if cache locking implemented):
+ *
+ * Parameters:
+ * aa, ab unique address registers (temporaries)
+ */
+ .macro icache_reset aa, ab
+ icache_unlock_all \aa, \ab
+ icache_invalidate_all \aa, \ab
+ .endm
+
+
+/*
+ * Synchronize after an instruction cache operation,
+ * to be sure everything is in sync with memory as to be
+ * expected following any previous instruction cache control operations.
+ *
+ * Parameters are:
+ * ar an address register (temporary) (currently unused, but may be used in future)
+ */
+ .macro icache_sync ar
+#if XCHAL_ICACHE_SIZE > 0
+ isync
+#endif
+ .endm
+
+
+
+/*
+ * Invalidate a single line of the instruction cache.
+ * Parameters are:
+ * ar address register that contains (virtual) address to invalidate
+ * (may get clobbered in a future implementation, but not currently)
+ * offset (optional) offset to add to \ar to compute effective address to invalidate
+ * (note: some number of lsbits are ignored)
+ */
+ .macro icache_invalidate_line ar, offset
+#if XCHAL_ICACHE_SIZE > 0
+ ihi \ar, \offset // invalidate icache line
+ /*
+ * NOTE: in some version of the silicon [!!!SHOULD HAVE BEEN DOCUMENTED!!!]
+ * 'ihi' doesn't work, so it had been replaced with 'iii'
+ * (which would just invalidate more than it should,
+ * which should be okay other than the performance hit
+ * because cache locking did not exist in that version,
+ * unless user somehow relies on something being cached).
+ * [WHAT VERSION IS IT!!?!?
+ * IS THERE ANY WAY TO TEST FOR THAT HERE, TO OUTPUT 'III' ONLY IF NEEDED!?!?].
+ *
+ * iii \ar, \offset
+ */
+ icache_sync \ar
+#endif
+ .endm
+
+
+
+
+/*
+ * Invalidate instruction cache entries that cache a specified portion of memory.
+ * Parameters are:
+ * astart start address (register gets clobbered)
+ * asize size of the region in bytes (register gets clobbered)
+ * ac unique register used as temporary
+ */
+ .macro icache_invalidate_region astart, asize, ac
+#if XCHAL_ICACHE_SIZE > 0
+ // Instruction cache region invalidation:
+ cache_hit_region ihi, XCHAL_ICACHE_LINEWIDTH, \astart, \asize, \ac
+ icache_sync \ac
+ // End of instruction cache region invalidation
+#endif
+ .endm
+
+
+
+/*
+ * Invalidate entire instruction cache.
+ *
+ * Parameters:
+ * aa, ab unique address registers (temporaries)
+ */
+ .macro icache_invalidate_all aa, ab
+#if XCHAL_ICACHE_SIZE > 0
+ // Instruction cache invalidation:
+ cache_index_all iii, XCHAL_ICACHE_SIZE, XCHAL_ICACHE_LINESIZE, XCHAL_ICACHE_WAYS, \aa, \ab
+ icache_sync \aa
+ // End of instruction cache invalidation
+#endif
+ .endm
+
+
+
+/*
+ * Lock (prefetch & lock) a single line of the instruction cache.
+ *
+ * Parameters are:
+ * ar address register that contains (virtual) address to lock
+ * (may get clobbered in a future implementation, but not currently)
+ * offset offset to add to \ar to compute effective address to lock
+ * (note: some number of lsbits are ignored)
+ */
+ .macro icache_lock_line ar, offset
+#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
+ ipfl \ar, \offset /* prefetch and lock icache line */
+ icache_sync \ar
+#endif
+ .endm
+
+
+
+/*
+ * Lock (prefetch & lock) a specified portion of memory into the instruction cache.
+ * Parameters are:
+ * astart start address (register gets clobbered)
+ * asize size of the region in bytes (register gets clobbered)
+ * ac unique register used as temporary
+ */
+ .macro icache_lock_region astart, asize, ac
+#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
+ // Instruction cache region lock:
+ cache_hit_region ipfl, XCHAL_ICACHE_LINEWIDTH, \astart, \asize, \ac
+ icache_sync \ac
+ // End of instruction cache region lock
+#endif
+ .endm
+
+
+
+/*
+ * Unlock a single line of the instruction cache.
+ *
+ * Parameters are:
+ * ar address register that contains (virtual) address to unlock
+ * (may get clobbered in a future implementation, but not currently)
+ * offset offset to add to \ar to compute effective address to unlock
+ * (note: some number of lsbits are ignored)
+ */
+ .macro icache_unlock_line ar, offset
+#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
+ ihu \ar, \offset /* unlock icache line */
+ icache_sync \ar
+#endif
+ .endm
+
+
+
+/*
+ * Unlock a specified portion of memory from the instruction cache.
+ * Parameters are:
+ * astart start address (register gets clobbered)
+ * asize size of the region in bytes (register gets clobbered)
+ * ac unique register used as temporary
+ */
+ .macro icache_unlock_region astart, asize, ac
+#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
+ // Instruction cache region unlock:
+ cache_hit_region ihu, XCHAL_ICACHE_LINEWIDTH, \astart, \asize, \ac
+ icache_sync \ac
+ // End of instruction cache region unlock
+#endif
+ .endm
+
+
+
+/*
+ * Unlock entire instruction cache.
+ *
+ * Parameters:
+ * aa, ab unique address registers (temporaries)
+ */
+ .macro icache_unlock_all aa, ab
+#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
+ // Instruction cache unlock:
+ cache_index_all iiu, XCHAL_ICACHE_SIZE, XCHAL_ICACHE_LINESIZE, 1, \aa, \ab
+ icache_sync \aa
+ // End of instruction cache unlock
+#endif
+ .endm
+
+
+
+
+
+/*************************** DATA CACHE ***************************/
+
+
+
+/*
+ * Reset/initialize the data cache by simply invalidating it
+ * (need to unlock first also, if cache locking implemented):
+ *
+ * Parameters:
+ * aa, ab unique address registers (temporaries)
+ */
+ .macro dcache_reset aa, ab
+ dcache_unlock_all \aa, \ab
+ dcache_invalidate_all \aa, \ab
+ .endm
+
+
+
+
+/*
+ * Synchronize after a data cache operation,
+ * to be sure everything is in sync with memory as to be
+ * expected following any previous data cache control operations.
+ *
+ * Parameters are:
+ * ar an address register (temporary) (currently unused, but may be used in future)
+ */
+ .macro dcache_sync ar
+#if XCHAL_DCACHE_SIZE > 0
+ // This previous sequence errs on the conservative side (too much so); a DSYNC should be sufficient:
+ //memw // synchronize data cache changes relative to subsequent memory accesses
+ //isync // be conservative and ISYNC as well (just to be sure)
+
+ dsync
+#endif
+ .endm
+
+
+
+/*
+ * Synchronize after a data store operation,
+ * to be sure the stored data is completely off the processor
+ * (and assuming there is no buffering outside the processor,
+ * that the data is in memory). This may be required to
+ * ensure that the processor's write buffers are emptied.
+ * A MEMW followed by a read guarantees this, by definition.
+ * We also try to make sure the read itself completes.
+ *
+ * Parameters are:
+ * ar an address register (temporary)
+ */
+ .macro write_sync ar
+ memw // ensure previous memory accesses are complete prior to subsequent memory accesses
+ l32i \ar, sp, 0 // completing this read ensures any previous write has completed, because of MEMW
+ //slot
+ add \ar, \ar, \ar // use the result of the read to help ensure the read completes (in future architectures)
+ .endm
+
+
+/*
+ * Invalidate a single line of the data cache.
+ * Parameters are:
+ * ar address register that contains (virtual) address to invalidate
+ * (may get clobbered in a future implementation, but not currently)
+ * offset (optional) offset to add to \ar to compute effective address to invalidate
+ * (note: some number of lsbits are ignored)
+ */
+ .macro dcache_invalidate_line ar, offset
+#if XCHAL_DCACHE_SIZE > 0
+ dhi \ar, \offset
+ dcache_sync \ar
+#endif
+ .endm
+
+
+
+
+
+/*
+ * Invalidate data cache entries that cache a specified portion of memory.
+ * Parameters are:
+ * astart start address (register gets clobbered)
+ * asize size of the region in bytes (register gets clobbered)
+ * ac unique register used as temporary
+ */
+ .macro dcache_invalidate_region astart, asize, ac
+#if XCHAL_DCACHE_SIZE > 0
+ // Data cache region invalidation:
+ cache_hit_region dhi, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
+ dcache_sync \ac
+ // End of data cache region invalidation
+#endif
+ .endm
+
+
+
+#if 0
+/*
+ * This is a work-around for a bug in SiChip1 (???).
+ * There should be a proper mechanism for not outputting
+ * these instructions when not needed.
+ * To enable work-around, uncomment this and replace 'dii'
+ * with 'dii_s1' everywhere, eg. in dcache_invalidate_all
+ * macro below.
+ */
+ .macro dii_s1 ar, offset
+ dii \ar, \offset
+ or \ar, \ar, \ar
+ or \ar, \ar, \ar
+ or \ar, \ar, \ar
+ or \ar, \ar, \ar
+ .endm
+#endif
+
+
+/*
+ * Invalidate entire data cache.
+ *
+ * Parameters:
+ * aa, ab unique address registers (temporaries)
+ */
+ .macro dcache_invalidate_all aa, ab
+#if XCHAL_DCACHE_SIZE > 0
+ // Data cache invalidation:
+ cache_index_all dii, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, XCHAL_DCACHE_WAYS, \aa, \ab
+ dcache_sync \aa
+ // End of data cache invalidation
+#endif
+ .endm
+
+
+
+/*
+ * Writeback a single line of the data cache.
+ * Parameters are:
+ * ar address register that contains (virtual) address to writeback
+ * (may get clobbered in a future implementation, but not currently)
+ * offset offset to add to \ar to compute effective address to writeback
+ * (note: some number of lsbits are ignored)
+ */
+ .macro dcache_writeback_line ar, offset
+#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK
+ dhwb \ar, \offset
+ dcache_sync \ar
+#endif
+ .endm
+
+
+
+/*
+ * Writeback dirty data cache entries that cache a specified portion of memory.
+ * Parameters are:
+ * astart start address (register gets clobbered)
+ * asize size of the region in bytes (register gets clobbered)
+ * ac unique register used as temporary
+ */
+ .macro dcache_writeback_region astart, asize, ac
+#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK
+ // Data cache region writeback:
+ cache_hit_region dhwb, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
+ dcache_sync \ac
+ // End of data cache region writeback
+#endif
+ .endm
+
+
+
+/*
+ * Writeback entire data cache.
+ * Parameters:
+ * aa, ab unique address registers (temporaries)
+ */
+ .macro dcache_writeback_all aa, ab
+#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK
+ // Data cache writeback:
+ cache_index_all diwb, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, 1, \aa, \ab
+ dcache_sync \aa
+ // End of data cache writeback
+#endif
+ .endm
+
+
+
+/*
+ * Writeback and invalidate a single line of the data cache.
+ * Parameters are:
+ * ar address register that contains (virtual) address to writeback and invalidate
+ * (may get clobbered in a future implementation, but not currently)
+ * offset offset to add to \ar to compute effective address to writeback and invalidate
+ * (note: some number of lsbits are ignored)
+ */
+ .macro dcache_writeback_inv_line ar, offset
+#if XCHAL_DCACHE_SIZE > 0
+ dhwbi \ar, \offset /* writeback and invalidate dcache line */
+ dcache_sync \ar
+#endif
+ .endm
+
+
+
+/*
+ * Writeback and invalidate data cache entries that cache a specified portion of memory.
+ * Parameters are:
+ * astart start address (register gets clobbered)
+ * asize size of the region in bytes (register gets clobbered)
+ * ac unique register used as temporary
+ */
+ .macro dcache_writeback_inv_region astart, asize, ac
+#if XCHAL_DCACHE_SIZE > 0
+ // Data cache region writeback and invalidate:
+ cache_hit_region dhwbi, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
+ dcache_sync \ac
+ // End of data cache region writeback and invalidate
+#endif
+ .endm
+
+
+
+/*
+ * Writeback and invalidate entire data cache.
+ * Parameters:
+ * aa, ab unique address registers (temporaries)
+ */
+ .macro dcache_writeback_inv_all aa, ab
+#if XCHAL_DCACHE_SIZE > 0
+ // Data cache writeback and invalidate:
+#if XCHAL_DCACHE_IS_WRITEBACK
+ cache_index_all diwbi, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, 1, \aa, \ab
+ dcache_sync \aa
+#else /*writeback*/
+ // Data cache does not support writeback, so just invalidate: */
+ dcache_invalidate_all \aa, \ab
+#endif /*writeback*/
+ // End of data cache writeback and invalidate
+#endif
+ .endm
+
+
+
+
+/*
+ * Lock (prefetch & lock) a single line of the data cache.
+ *
+ * Parameters are:
+ * ar address register that contains (virtual) address to lock
+ * (may get clobbered in a future implementation, but not currently)
+ * offset offset to add to \ar to compute effective address to lock
+ * (note: some number of lsbits are ignored)
+ */
+ .macro dcache_lock_line ar, offset
+#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
+ dpfl \ar, \offset /* prefetch and lock dcache line */
+ dcache_sync \ar
+#endif
+ .endm
+
+
+
+/*
+ * Lock (prefetch & lock) a specified portion of memory into the data cache.
+ * Parameters are:
+ * astart start address (register gets clobbered)
+ * asize size of the region in bytes (register gets clobbered)
+ * ac unique register used as temporary
+ */
+ .macro dcache_lock_region astart, asize, ac
+#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
+ // Data cache region lock:
+ cache_hit_region dpfl, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
+ dcache_sync \ac
+ // End of data cache region lock
+#endif
+ .endm
+
+
+
+/*
+ * Unlock a single line of the data cache.
+ *
+ * Parameters are:
+ * ar address register that contains (virtual) address to unlock
+ * (may get clobbered in a future implementation, but not currently)
+ * offset offset to add to \ar to compute effective address to unlock
+ * (note: some number of lsbits are ignored)
+ */
+ .macro dcache_unlock_line ar, offset
+#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
+ dhu \ar, \offset /* unlock dcache line */
+ dcache_sync \ar
+#endif
+ .endm
+
+
+
+/*
+ * Unlock a specified portion of memory from the data cache.
+ * Parameters are:
+ * astart start address (register gets clobbered)
+ * asize size of the region in bytes (register gets clobbered)
+ * ac unique register used as temporary
+ */
+ .macro dcache_unlock_region astart, asize, ac
+#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
+ // Data cache region unlock:
+ cache_hit_region dhu, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
+ dcache_sync \ac
+ // End of data cache region unlock
+#endif
+ .endm
+
+
+
+/*
+ * Unlock entire data cache.
+ *
+ * Parameters:
+ * aa, ab unique address registers (temporaries)
+ */
+ .macro dcache_unlock_all aa, ab
+#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
+ // Data cache unlock:
+ cache_index_all diu, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, 1, \aa, \ab
+ dcache_sync \aa
+ // End of data cache unlock
+#endif
+ .endm
+
+
+#endif /*XTENSA_CACHEASM_H*/
+
diff --git a/include/asm-xtensa/xtensa/cacheattrasm.h b/include/asm-xtensa/xtensa/cacheattrasm.h
new file mode 100644
index 00000000000..1c3e117b359
--- /dev/null
+++ b/include/asm-xtensa/xtensa/cacheattrasm.h
@@ -0,0 +1,432 @@
+#ifndef XTENSA_CACHEATTRASM_H
+#define XTENSA_CACHEATTRASM_H
+
+/*
+ * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
+ *
+ * include/asm-xtensa/xtensa/cacheattrasm.h -- assembler-specific
+ * CACHEATTR register related definitions that depend on CORE
+ * configuration.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2002 Tensilica Inc.
+ */
+
+
+#include <xtensa/coreasm.h>
+
+
+/*
+ * This header file defines assembler macros of the form:
+ * <x>cacheattr_<func>
+ * where:
+ * <x> is 'i', 'd' or absent for instruction, data
+ * or both caches; and
+ * <func> indicates the function of the macro.
+ *
+ * The following functions are defined:
+ *
+ * icacheattr_get
+ * Reads I-cache CACHEATTR into a2 (clobbers a3-a5).
+ *
+ * dcacheattr_get
+ * Reads D-cache CACHEATTR into a2 (clobbers a3-a5).
+ * (Note: for configs with a real CACHEATTR register, the
+ * above two macros are identical.)
+ *
+ * cacheattr_set
+ * Writes both I-cache and D-cache CACHEATTRs from a2 (a3-a8 clobbered).
+ * Works even when changing one's own code's attributes.
+ *
+ * icacheattr_is_enabled label
+ * Branches to \label if I-cache appears to have been enabled
+ * (eg. if CACHEATTR contains a cache-enabled attribute).
+ * (clobbers a2-a5,SAR)
+ *
+ * dcacheattr_is_enabled label
+ * Branches to \label if D-cache appears to have been enabled
+ * (eg. if CACHEATTR contains a cache-enabled attribute).
+ * (clobbers a2-a5,SAR)
+ *
+ * cacheattr_is_enabled label
+ * Branches to \label if either I-cache or D-cache appears to have been enabled
+ * (eg. if CACHEATTR contains a cache-enabled attribute).
+ * (clobbers a2-a5,SAR)
+ *
+ * The following macros are only defined under certain conditions:
+ *
+ * icacheattr_set (if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR)
+ * Writes I-cache CACHEATTR from a2 (a3-a8 clobbered).
+ *
+ * dcacheattr_set (if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR)
+ * Writes D-cache CACHEATTR from a2 (a3-a8 clobbered).
+ */
+
+
+
+/*************************** GENERIC -- ALL CACHES ***************************/
+
+/*
+ * _cacheattr_get
+ *
+ * (Internal macro.)
+ * Returns value of CACHEATTR register (or closest equivalent) in a2.
+ *
+ * Entry:
+ * (none)
+ * Exit:
+ * a2 value read from CACHEATTR
+ * a3-a5 clobbered (temporaries)
+ */
+ .macro _cacheattr_get tlb
+#if XCHAL_HAVE_CACHEATTR
+ rsr a2, CACHEATTR
+#elif XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
+ // We have a config that "mimics" CACHEATTR using a simplified
+ // "MMU" composed of a single statically-mapped way.
+ // DTLB and ITLB are independent, so there's no single
+ // cache attribute that can describe both. So for now
+ // just return the DTLB state.
+ movi a5, 0xE0000000
+ movi a2, 0
+ movi a3, 0
+1: add a3, a3, a5 // next segment
+ r&tlb&1 a4, a3 // get PPN+CA of segment at 0xE0000000, 0xC0000000, ..., 0
+ dsync // interlock???
+ slli a2, a2, 4
+ extui a4, a4, 0, 4 // extract CA
+ or a2, a2, a4
+ bnez a3, 1b
+#else
+ // This macro isn't applicable to arbitrary MMU configurations.
+ // Just return zero.
+ movi a2, 0
+#endif
+ .endm
+
+ .macro icacheattr_get
+ _cacheattr_get itlb
+ .endm
+
+ .macro dcacheattr_get
+ _cacheattr_get dtlb
+ .endm
+
+
+#define XCHAL_CACHEATTR_ALL_BYPASS 0x22222222 /* default (powerup/reset) value of CACHEATTR, all BYPASS
+ mode (ie. disabled/bypassed caches) */
+
+#if XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
+
+#define XCHAL_FCA_ENAMASK 0x001A /* bitmap of fetch attributes that require enabled icache */
+#define XCHAL_LCA_ENAMASK 0x0003 /* bitmap of load attributes that require enabled dcache */
+#define XCHAL_SCA_ENAMASK 0x0003 /* bitmap of store attributes that require enabled dcache */
+#define XCHAL_LSCA_ENAMASK (XCHAL_LCA_ENAMASK|XCHAL_SCA_ENAMASK) /* l/s attrs requiring enabled dcache */
+#define XCHAL_ALLCA_ENAMASK (XCHAL_FCA_ENAMASK|XCHAL_LSCA_ENAMASK) /* all attrs requiring enabled caches */
+
+/*
+ * _cacheattr_is_enabled
+ *
+ * (Internal macro.)
+ * Branches to \label if CACHEATTR in a2 indicates an enabled
+ * cache, using mask in a3.
+ *
+ * Parameters:
+ * label where to branch to if cache is enabled
+ * Entry:
+ * a2 contains CACHEATTR value used to determine whether
+ * caches are enabled
+ * a3 16-bit constant where each bit correspond to
+ * one of the 16 possible CA values (in a CACHEATTR mask);
+ * CA values that indicate the cache is enabled
+ * have their corresponding bit set in this mask
+ * (eg. use XCHAL_xCA_ENAMASK , above)
+ * Exit:
+ * a2,a4,a5 clobbered
+ * SAR clobbered
+ */
+ .macro _cacheattr_is_enabled label
+ movi a4, 8 // loop 8 times
+.Lcaife\@:
+ extui a5, a2, 0, 4 // get CA nibble
+ ssr a5 // index into mask according to CA...
+ srl a5, a3 // ...and get CA's mask bit in a5 bit 0
+ bbsi.l a5, 0, \label // if CA indicates cache enabled, jump to label
+ srli a2, a2, 4 // next nibble
+ addi a4, a4, -1
+ bnez a4, .Lcaife\@ // loop for each nibble
+ .endm
+
+#else /* XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR */
+ .macro _cacheattr_is_enabled label
+ j \label // macro not applicable, assume caches always enabled
+ .endm
+#endif /* XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR */
+
+
+
+/*
+ * icacheattr_is_enabled
+ *
+ * Branches to \label if I-cache is enabled.
+ *
+ * Parameters:
+ * label where to branch to if icache is enabled
+ * Entry:
+ * (none)
+ * Exit:
+ * a2-a5, SAR clobbered (temporaries)
+ */
+ .macro icacheattr_is_enabled label
+#if XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
+ icacheattr_get
+ movi a3, XCHAL_FCA_ENAMASK
+#endif
+ _cacheattr_is_enabled \label
+ .endm
+
+/*
+ * dcacheattr_is_enabled
+ *
+ * Branches to \label if D-cache is enabled.
+ *
+ * Parameters:
+ * label where to branch to if dcache is enabled
+ * Entry:
+ * (none)
+ * Exit:
+ * a2-a5, SAR clobbered (temporaries)
+ */
+ .macro dcacheattr_is_enabled label
+#if XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
+ dcacheattr_get
+ movi a3, XCHAL_LSCA_ENAMASK
+#endif
+ _cacheattr_is_enabled \label
+ .endm
+
+/*
+ * cacheattr_is_enabled
+ *
+ * Branches to \label if either I-cache or D-cache is enabled.
+ *
+ * Parameters:
+ * label where to branch to if a cache is enabled
+ * Entry:
+ * (none)
+ * Exit:
+ * a2-a5, SAR clobbered (temporaries)
+ */
+ .macro cacheattr_is_enabled label
+#if XCHAL_HAVE_CACHEATTR
+ rsr a2, CACHEATTR
+ movi a3, XCHAL_ALLCA_ENAMASK
+#elif XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
+ icacheattr_get
+ movi a3, XCHAL_FCA_ENAMASK
+ _cacheattr_is_enabled \label
+ dcacheattr_get
+ movi a3, XCHAL_LSCA_ENAMASK
+#endif
+ _cacheattr_is_enabled \label
+ .endm
+
+
+
+/*
+ * The ISA does not have a defined way to change the
+ * instruction cache attributes of the running code,
+ * ie. of the memory area that encloses the current PC.
+ * However, each micro-architecture (or class of
+ * configurations within a micro-architecture)
+ * provides a way to deal with this issue.
+ *
+ * Here are a few macros used to implement the relevant
+ * approach taken.
+ */
+
+#if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
+ // We have a config that "mimics" CACHEATTR using a simplified
+ // "MMU" composed of a single statically-mapped way.
+
+/*
+ * icacheattr_set
+ *
+ * Entry:
+ * a2 cacheattr value to set
+ * Exit:
+ * a2 unchanged
+ * a3-a8 clobbered (temporaries)
+ */
+ .macro icacheattr_set
+
+ movi a5, 0xE0000000 // mask of upper 3 bits
+ movi a6, 3f // PC where ITLB is set
+ movi a3, 0 // start at region 0 (0 .. 7)
+ and a6, a6, a5 // upper 3 bits of local PC area
+ mov a7, a2 // copy a2 so it doesn't get clobbered
+ j 3f
+
+# if XCHAL_HAVE_XLT_CACHEATTR
+ // Can do translations, use generic method:
+1: sub a6, a3, a5 // address of some other segment
+ ritlb1 a8, a6 // save its PPN+CA
+ dsync // interlock??
+ witlb a4, a6 // make it translate to this code area
+ movi a6, 5f // where to jump into it
+ isync
+ sub a6, a6, a5 // adjust jump address within that other segment
+ jx a6
+
+ // Note that in the following code snippet, which runs at a different virtual
+ // address than it is assembled for, we avoid using literals (eg. via movi/l32r)
+ // just in case literals end up in a different 512 MB segment, and we avoid
+ // instructions that rely on the current PC being what is expected.
+ //
+ .align 4
+ _j 6f // this is at label '5' minus 4 bytes
+ .align 4
+5: witlb a4, a3 // we're in other segment, now can write previous segment's CA
+ isync
+ add a6, a6, a5 // back to previous segment
+ addi a6, a6, -4 // next jump label
+ jx a6
+
+6: sub a6, a3, a5 // address of some other segment
+ witlb a8, a6 // restore PPN+CA of other segment
+ mov a6, a3 // restore a6
+ isync
+# else /* XCHAL_HAVE_XLT_CACHEATTR */
+ // Use micro-architecture specific method.
+ // The following 4-instruction sequence is aligned such that
+ // it all fits within a single I-cache line. Sixteen byte
+ // alignment is sufficient for this (using XCHAL_ICACHE_LINESIZE
+ // actually causes problems because that can be greater than
+ // the alignment of the reset vector, where this macro is often
+ // invoked, which would cause the linker to align the reset
+ // vector code away from the reset vector!!).
+ .align 16 /*XCHAL_ICACHE_LINESIZE*/
+1: _witlb a4, a3 // write wired PTE (CA, no PPN) of 512MB segment to ITLB
+ _isync
+ nop
+ nop
+# endif /* XCHAL_HAVE_XLT_CACHEATTR */
+ beq a3, a5, 4f // done?
+
+ // Note that in the WITLB loop, we don't do any load/stores
+ // (may not be an issue here, but it is important in the DTLB case).
+2: srli a7, a7, 4 // next CA
+ sub a3, a3, a5 // next segment (add 0x20000000)
+3:
+# if XCHAL_HAVE_XLT_CACHEATTR /* if have translation, preserve it */
+ ritlb1 a8, a3 // get current PPN+CA of segment
+ dsync // interlock???
+ extui a4, a7, 0, 4 // extract CA to set
+ srli a8, a8, 4 // clear CA but keep PPN ...
+ slli a8, a8, 4 // ...
+ add a4, a4, a8 // combine new CA with PPN to preserve
+# else
+ extui a4, a7, 0, 4 // extract CA
+# endif
+ beq a3, a6, 1b // current PC's region? if so, do it in a safe way
+ witlb a4, a3 // write wired PTE (CA [+PPN]) of 512MB segment to ITLB
+ bne a3, a5, 2b
+ isync // make sure all ifetch changes take effect
+4:
+ .endm // icacheattr_set
+
+
+/*
+ * dcacheattr_set
+ *
+ * Entry:
+ * a2 cacheattr value to set
+ * Exit:
+ * a2 unchanged
+ * a3-a8 clobbered (temporaries)
+ */
+
+ .macro dcacheattr_set
+
+ movi a5, 0xE0000000 // mask of upper 3 bits
+ movi a3, 0 // start at region 0 (0 .. 7)
+ mov a7, a2 // copy a2 so it doesn't get clobbered
+ j 3f
+ // Note that in the WDTLB loop, we don't do any load/stores
+ // (including implicit l32r via movi) because it isn't safe.
+2: srli a7, a7, 4 // next CA
+ sub a3, a3, a5 // next segment (add 0x20000000)
+3:
+# if XCHAL_HAVE_XLT_CACHEATTR /* if have translation, preserve it */
+ rdtlb1 a8, a3 // get current PPN+CA of segment
+ dsync // interlock???
+ extui a4, a7, 0, 4 // extract CA to set
+ srli a8, a8, 4 // clear CA but keep PPN ...
+ slli a8, a8, 4 // ...
+ add a4, a4, a8 // combine new CA with PPN to preserve
+# else
+ extui a4, a7, 0, 4 // extract CA to set
+# endif
+ wdtlb a4, a3 // write wired PTE (CA [+PPN]) of 512MB segment to DTLB
+ bne a3, a5, 2b
+ dsync // make sure all data path changes take effect
+ .endm // dcacheattr_set
+
+#endif /* XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR */
+
+
+
+/*
+ * cacheattr_set
+ *
+ * Macro that sets the current CACHEATTR safely
+ * (both i and d) according to the current contents of a2.
+ * It works even when changing the cache attributes of
+ * the currently running code.
+ *
+ * Entry:
+ * a2 cacheattr value to set
+ * Exit:
+ * a2 unchanged
+ * a3-a8 clobbered (temporaries)
+ */
+ .macro cacheattr_set
+
+#if XCHAL_HAVE_CACHEATTR
+# if XCHAL_ICACHE_LINESIZE < 4
+ // No i-cache, so can always safely write to CACHEATTR:
+ wsr a2, CACHEATTR
+# else
+ // The Athens micro-architecture, when using the old
+ // exception architecture option (ie. with the CACHEATTR register)
+ // allows changing the cache attributes of the running code
+ // using the following exact sequence aligned to be within
+ // an instruction cache line. (NOTE: using XCHAL_ICACHE_LINESIZE
+ // alignment actually causes problems because that can be greater
+ // than the alignment of the reset vector, where this macro is often
+ // invoked, which would cause the linker to align the reset
+ // vector code away from the reset vector!!).
+ j 1f
+ .align 16 /*XCHAL_ICACHE_LINESIZE*/ // align to within an I-cache line
+1: _wsr a2, CACHEATTR
+ _isync
+ nop
+ nop
+# endif
+#elif XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
+ // DTLB and ITLB are independent, but to keep semantics
+ // of this macro we simply write to both.
+ icacheattr_set
+ dcacheattr_set
+#else
+ // This macro isn't applicable to arbitrary MMU configurations.
+ // Do nothing in this case.
+#endif
+ .endm
+
+
+#endif /*XTENSA_CACHEATTRASM_H*/
+
diff --git a/include/asm-xtensa/xtensa/config-linux_be/core.h b/include/asm-xtensa/xtensa/config-linux_be/core.h
new file mode 100644
index 00000000000..d54fe5eb106
--- /dev/null
+++ b/include/asm-xtensa/xtensa/config-linux_be/core.h
@@ -0,0 +1,1270 @@
+/*
+ * xtensa/config/core.h -- HAL definitions that are dependent on CORE configuration
+ *
+ * This header file is sometimes referred to as the "compile-time HAL" or CHAL.
+ * It was generated for a specific Xtensa processor configuration.
+ *
+ * Source for configuration-independent binaries (which link in a
+ * configuration-specific HAL library) must NEVER include this file.
+ * It is perfectly normal, however, for the HAL source itself to include this file.
+ */
+
+/*
+ * Copyright (c) 2003 Tensilica, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
+ * USA.
+ */
+
+
+#ifndef XTENSA_CONFIG_CORE_H
+#define XTENSA_CONFIG_CORE_H
+
+#include <xtensa/hal.h>
+
+
+/*----------------------------------------------------------------------
+ GENERAL
+ ----------------------------------------------------------------------*/
+
+/*
+ * Separators for macros that expand into arrays.
+ * These can be predefined by files that #include this one,
+ * when different separators are required.
+ */
+/* Element separator for macros that expand into 1-dimensional arrays: */
+#ifndef XCHAL_SEP
+#define XCHAL_SEP ,
+#endif
+/* Array separator for macros that expand into 2-dimensional arrays: */
+#ifndef XCHAL_SEP2
+#define XCHAL_SEP2 },{
+#endif
+
+
+/*----------------------------------------------------------------------
+ ENDIANNESS
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_BE 1
+#define XCHAL_HAVE_LE 0
+#define XCHAL_MEMORY_ORDER XTHAL_BIGENDIAN
+
+
+/*----------------------------------------------------------------------
+ REGISTER WINDOWS
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_WINDOWED 1 /* 1 if windowed registers option configured, 0 otherwise */
+#define XCHAL_NUM_AREGS 64 /* number of physical address regs */
+#define XCHAL_NUM_AREGS_LOG2 6 /* log2(XCHAL_NUM_AREGS) */
+
+
+/*----------------------------------------------------------------------
+ ADDRESS ALIGNMENT
+ ----------------------------------------------------------------------*/
+
+/* These apply to a selected set of core load and store instructions only (see ISA): */
+#define XCHAL_UNALIGNED_LOAD_EXCEPTION 1 /* 1 if unaligned loads cause an exception, 0 otherwise */
+#define XCHAL_UNALIGNED_STORE_EXCEPTION 1 /* 1 if unaligned stores cause an exception, 0 otherwise */
+
+
+/*----------------------------------------------------------------------
+ INTERRUPTS
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_INTERRUPTS 1 /* 1 if interrupt option configured, 0 otherwise */
+#define XCHAL_HAVE_HIGHPRI_INTERRUPTS 1 /* 1 if high-priority interrupt option configured, 0 otherwise */
+#define XCHAL_HAVE_HIGHLEVEL_INTERRUPTS XCHAL_HAVE_HIGHPRI_INTERRUPTS
+#define XCHAL_HAVE_NMI 0 /* 1 if NMI option configured, 0 otherwise */
+#define XCHAL_NUM_INTERRUPTS 17 /* number of interrupts */
+#define XCHAL_NUM_INTERRUPTS_LOG2 5 /* number of bits to hold an interrupt number: roundup(log2(number of interrupts)) */
+#define XCHAL_NUM_EXTINTERRUPTS 10 /* number of external interrupts */
+#define XCHAL_NUM_INTLEVELS 4 /* number of interrupt levels (not including level zero!) */
+#define XCHAL_NUM_LOWPRI_LEVELS 1 /* number of low-priority interrupt levels (always 1) */
+#define XCHAL_FIRST_HIGHPRI_LEVEL (XCHAL_NUM_LOWPRI_LEVELS+1) /* level of first high-priority interrupt (always 2) */
+#define XCHAL_EXCM_LEVEL 1 /* level of interrupts masked by PS.EXCM (XEA2 only; always 1 in T10xx);
+ for XEA1, where there is no PS.EXCM, this is always 1;
+ interrupts at levels FIRST_HIGHPRI <= n <= EXCM_LEVEL, if any,
+ are termed "medium priority" interrupts (post T10xx only) */
+/* Note: 1 <= LOWPRI_LEVELS <= EXCM_LEVEL < DEBUGLEVEL <= NUM_INTLEVELS < NMILEVEL <= 15 */
+
+/* Masks of interrupts at each interrupt level: */
+#define XCHAL_INTLEVEL0_MASK 0x00000000
+#define XCHAL_INTLEVEL1_MASK 0x000064F9
+#define XCHAL_INTLEVEL2_MASK 0x00008902
+#define XCHAL_INTLEVEL3_MASK 0x00011204
+#define XCHAL_INTLEVEL4_MASK 0x00000000
+#define XCHAL_INTLEVEL5_MASK 0x00000000
+#define XCHAL_INTLEVEL6_MASK 0x00000000
+#define XCHAL_INTLEVEL7_MASK 0x00000000
+#define XCHAL_INTLEVEL8_MASK 0x00000000
+#define XCHAL_INTLEVEL9_MASK 0x00000000
+#define XCHAL_INTLEVEL10_MASK 0x00000000
+#define XCHAL_INTLEVEL11_MASK 0x00000000
+#define XCHAL_INTLEVEL12_MASK 0x00000000
+#define XCHAL_INTLEVEL13_MASK 0x00000000
+#define XCHAL_INTLEVEL14_MASK 0x00000000
+#define XCHAL_INTLEVEL15_MASK 0x00000000
+/* As an array of entries (eg. for C constant arrays): */
+#define XCHAL_INTLEVEL_MASKS 0x00000000 XCHAL_SEP \
+ 0x000064F9 XCHAL_SEP \
+ 0x00008902 XCHAL_SEP \
+ 0x00011204 XCHAL_SEP \
+ 0x00000000 XCHAL_SEP \
+ 0x00000000 XCHAL_SEP \
+ 0x00000000 XCHAL_SEP \
+ 0x00000000 XCHAL_SEP \
+ 0x00000000 XCHAL_SEP \
+ 0x00000000 XCHAL_SEP \
+ 0x00000000 XCHAL_SEP \
+ 0x00000000 XCHAL_SEP \
+ 0x00000000 XCHAL_SEP \
+ 0x00000000 XCHAL_SEP \
+ 0x00000000 XCHAL_SEP \
+ 0x00000000
+
+/* Masks of interrupts at each range 1..n of interrupt levels: */
+#define XCHAL_INTLEVEL0_ANDBELOW_MASK 0x00000000
+#define XCHAL_INTLEVEL1_ANDBELOW_MASK 0x000064F9
+#define XCHAL_INTLEVEL2_ANDBELOW_MASK 0x0000EDFB
+#define XCHAL_INTLEVEL3_ANDBELOW_MASK 0x0001FFFF
+#define XCHAL_INTLEVEL4_ANDBELOW_MASK 0x0001FFFF
+#define XCHAL_INTLEVEL5_ANDBELOW_MASK 0x0001FFFF
+#define XCHAL_INTLEVEL6_ANDBELOW_MASK 0x0001FFFF
+#define XCHAL_INTLEVEL7_ANDBELOW_MASK 0x0001FFFF
+#define XCHAL_INTLEVEL8_ANDBELOW_MASK 0x0001FFFF
+#define XCHAL_INTLEVEL9_ANDBELOW_MASK 0x0001FFFF
+#define XCHAL_INTLEVEL10_ANDBELOW_MASK 0x0001FFFF
+#define XCHAL_INTLEVEL11_ANDBELOW_MASK 0x0001FFFF
+#define XCHAL_INTLEVEL12_ANDBELOW_MASK 0x0001FFFF
+#define XCHAL_INTLEVEL13_ANDBELOW_MASK 0x0001FFFF
+#define XCHAL_INTLEVEL14_ANDBELOW_MASK 0x0001FFFF
+#define XCHAL_INTLEVEL15_ANDBELOW_MASK 0x0001FFFF
+#define XCHAL_LOWPRI_MASK XCHAL_INTLEVEL1_ANDBELOW_MASK /* mask of all low-priority interrupts */
+#define XCHAL_EXCM_MASK XCHAL_INTLEVEL1_ANDBELOW_MASK /* mask of all interrupts masked by PS.EXCM (or CEXCM) */
+/* As an array of entries (eg. for C constant arrays): */
+#define XCHAL_INTLEVEL_ANDBELOW_MASKS 0x00000000 XCHAL_SEP \
+ 0x000064F9 XCHAL_SEP \
+ 0x0000EDFB XCHAL_SEP \
+ 0x0001FFFF XCHAL_SEP \
+ 0x0001FFFF XCHAL_SEP \
+ 0x0001FFFF XCHAL_SEP \
+ 0x0001FFFF XCHAL_SEP \
+ 0x0001FFFF XCHAL_SEP \
+ 0x0001FFFF XCHAL_SEP \
+ 0x0001FFFF XCHAL_SEP \
+ 0x0001FFFF XCHAL_SEP \
+ 0x0001FFFF XCHAL_SEP \
+ 0x0001FFFF XCHAL_SEP \
+ 0x0001FFFF XCHAL_SEP \
+ 0x0001FFFF XCHAL_SEP \
+ 0x0001FFFF
+
+/* Interrupt numbers for each interrupt level at which only one interrupt was configured: */
+/*#define XCHAL_INTLEVEL1_NUM ...more than one interrupt at this level...*/
+/*#define XCHAL_INTLEVEL2_NUM ...more than one interrupt at this level...*/
+/*#define XCHAL_INTLEVEL3_NUM ...more than one interrupt at this level...*/
+
+/* Level of each interrupt: */
+#define XCHAL_INT0_LEVEL 1
+#define XCHAL_INT1_LEVEL 2
+#define XCHAL_INT2_LEVEL 3
+#define XCHAL_INT3_LEVEL 1
+#define XCHAL_INT4_LEVEL 1
+#define XCHAL_INT5_LEVEL 1
+#define XCHAL_INT6_LEVEL 1
+#define XCHAL_INT7_LEVEL 1
+#define XCHAL_INT8_LEVEL 2
+#define XCHAL_INT9_LEVEL 3
+#define XCHAL_INT10_LEVEL 1
+#define XCHAL_INT11_LEVEL 2
+#define XCHAL_INT12_LEVEL 3
+#define XCHAL_INT13_LEVEL 1
+#define XCHAL_INT14_LEVEL 1
+#define XCHAL_INT15_LEVEL 2
+#define XCHAL_INT16_LEVEL 3
+#define XCHAL_INT17_LEVEL 0
+#define XCHAL_INT18_LEVEL 0
+#define XCHAL_INT19_LEVEL 0
+#define XCHAL_INT20_LEVEL 0
+#define XCHAL_INT21_LEVEL 0
+#define XCHAL_INT22_LEVEL 0
+#define XCHAL_INT23_LEVEL 0
+#define XCHAL_INT24_LEVEL 0
+#define XCHAL_INT25_LEVEL 0
+#define XCHAL_INT26_LEVEL 0
+#define XCHAL_INT27_LEVEL 0
+#define XCHAL_INT28_LEVEL 0
+#define XCHAL_INT29_LEVEL 0
+#define XCHAL_INT30_LEVEL 0
+#define XCHAL_INT31_LEVEL 0
+/* As an array of entries (eg. for C constant arrays): */
+#define XCHAL_INT_LEVELS 1 XCHAL_SEP \
+ 2 XCHAL_SEP \
+ 3 XCHAL_SEP \
+ 1 XCHAL_SEP \
+ 1 XCHAL_SEP \
+ 1 XCHAL_SEP \
+ 1 XCHAL_SEP \
+ 1 XCHAL_SEP \
+ 2 XCHAL_SEP \
+ 3 XCHAL_SEP \
+ 1 XCHAL_SEP \
+ 2 XCHAL_SEP \
+ 3 XCHAL_SEP \
+ 1 XCHAL_SEP \
+ 1 XCHAL_SEP \
+ 2 XCHAL_SEP \
+ 3 XCHAL_SEP \
+ 0 XCHAL_SEP \
+ 0 XCHAL_SEP \
+ 0 XCHAL_SEP \
+ 0 XCHAL_SEP \
+ 0 XCHAL_SEP \
+ 0 XCHAL_SEP \
+ 0 XCHAL_SEP \
+ 0 XCHAL_SEP \
+ 0 XCHAL_SEP \
+ 0 XCHAL_SEP \
+ 0 XCHAL_SEP \
+ 0 XCHAL_SEP \
+ 0 XCHAL_SEP \
+ 0 XCHAL_SEP \
+ 0
+
+/* Type of each interrupt: */
+#define XCHAL_INT0_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT1_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT2_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT3_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT4_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT5_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT6_TYPE XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT7_TYPE XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT8_TYPE XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT9_TYPE XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT10_TYPE XTHAL_INTTYPE_TIMER
+#define XCHAL_INT11_TYPE XTHAL_INTTYPE_TIMER
+#define XCHAL_INT12_TYPE XTHAL_INTTYPE_TIMER
+#define XCHAL_INT13_TYPE XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT14_TYPE XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT15_TYPE XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT16_TYPE XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT17_TYPE XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT18_TYPE XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT19_TYPE XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT20_TYPE XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT21_TYPE XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT22_TYPE XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT23_TYPE XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT24_TYPE XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT25_TYPE XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT26_TYPE XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT27_TYPE XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT28_TYPE XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT29_TYPE XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT30_TYPE XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT31_TYPE XTHAL_INTTYPE_UNCONFIGURED
+/* As an array of entries (eg. for C constant arrays): */
+#define XCHAL_INT_TYPES XTHAL_INTTYPE_EXTERN_LEVEL XCHAL_SEP \
+ XTHAL_INTTYPE_EXTERN_LEVEL XCHAL_SEP \
+ XTHAL_INTTYPE_EXTERN_LEVEL XCHAL_SEP \
+ XTHAL_INTTYPE_EXTERN_LEVEL XCHAL_SEP \
+ XTHAL_INTTYPE_EXTERN_LEVEL XCHAL_SEP \
+ XTHAL_INTTYPE_EXTERN_LEVEL XCHAL_SEP \
+ XTHAL_INTTYPE_EXTERN_LEVEL XCHAL_SEP \
+ XTHAL_INTTYPE_EXTERN_EDGE XCHAL_SEP \
+ XTHAL_INTTYPE_EXTERN_EDGE XCHAL_SEP \
+ XTHAL_INTTYPE_EXTERN_EDGE XCHAL_SEP \
+ XTHAL_INTTYPE_TIMER XCHAL_SEP \
+ XTHAL_INTTYPE_TIMER XCHAL_SEP \
+ XTHAL_INTTYPE_TIMER XCHAL_SEP \
+ XTHAL_INTTYPE_SOFTWARE XCHAL_SEP \
+ XTHAL_INTTYPE_SOFTWARE XCHAL_SEP \
+ XTHAL_INTTYPE_SOFTWARE XCHAL_SEP \
+ XTHAL_INTTYPE_SOFTWARE XCHAL_SEP \
+ XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
+ XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
+ XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
+ XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
+ XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
+ XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
+ XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
+ XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
+ XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
+ XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
+ XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
+ XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
+ XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
+ XTHAL_INTTYPE_UNCONFIGURED XCHAL_SEP \
+ XTHAL_INTTYPE_UNCONFIGURED
+
+/* Masks of interrupts for each type of interrupt: */
+#define XCHAL_INTTYPE_MASK_UNCONFIGURED 0xFFFE0000
+#define XCHAL_INTTYPE_MASK_SOFTWARE 0x0001E000
+#define XCHAL_INTTYPE_MASK_EXTERN_EDGE 0x00000380
+#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL 0x0000007F
+#define XCHAL_INTTYPE_MASK_TIMER 0x00001C00
+#define XCHAL_INTTYPE_MASK_NMI 0x00000000
+/* As an array of entries (eg. for C constant arrays): */
+#define XCHAL_INTTYPE_MASKS 0xFFFE0000 XCHAL_SEP \
+ 0x0001E000 XCHAL_SEP \
+ 0x00000380 XCHAL_SEP \
+ 0x0000007F XCHAL_SEP \
+ 0x00001C00 XCHAL_SEP \
+ 0x00000000
+
+/* Interrupts assigned to each timer (CCOMPARE0 to CCOMPARE3), -1 if unassigned */
+#define XCHAL_TIMER0_INTERRUPT 10
+#define XCHAL_TIMER1_INTERRUPT 11
+#define XCHAL_TIMER2_INTERRUPT 12
+#define XCHAL_TIMER3_INTERRUPT XTHAL_TIMER_UNCONFIGURED
+/* As an array of entries (eg. for C constant arrays): */
+#define XCHAL_TIMER_INTERRUPTS 10 XCHAL_SEP \
+ 11 XCHAL_SEP \
+ 12 XCHAL_SEP \
+ XTHAL_TIMER_UNCONFIGURED
+
+/* Indexing macros: */
+#define _XCHAL_INTLEVEL_MASK(n) XCHAL_INTLEVEL ## n ## _MASK
+#define XCHAL_INTLEVEL_MASK(n) _XCHAL_INTLEVEL_MASK(n) /* n = 0 .. 15 */
+#define _XCHAL_INTLEVEL_ANDBELOWMASK(n) XCHAL_INTLEVEL ## n ## _ANDBELOW_MASK
+#define XCHAL_INTLEVEL_ANDBELOW_MASK(n) _XCHAL_INTLEVEL_ANDBELOWMASK(n) /* n = 0 .. 15 */
+#define _XCHAL_INT_LEVEL(n) XCHAL_INT ## n ## _LEVEL
+#define XCHAL_INT_LEVEL(n) _XCHAL_INT_LEVEL(n) /* n = 0 .. 31 */
+#define _XCHAL_INT_TYPE(n) XCHAL_INT ## n ## _TYPE
+#define XCHAL_INT_TYPE(n) _XCHAL_INT_TYPE(n) /* n = 0 .. 31 */
+#define _XCHAL_TIMER_INTERRUPT(n) XCHAL_TIMER ## n ## _INTERRUPT
+#define XCHAL_TIMER_INTERRUPT(n) _XCHAL_TIMER_INTERRUPT(n) /* n = 0 .. 3 */
+
+
+
+/*
+ * External interrupt vectors/levels.
+ * These macros describe how Xtensa processor interrupt numbers
+ * (as numbered internally, eg. in INTERRUPT and INTENABLE registers)
+ * map to external BInterrupt<n> pins, for those interrupts
+ * configured as external (level-triggered, edge-triggered, or NMI).
+ * See the Xtensa processor databook for more details.
+ */
+
+/* Core interrupt numbers mapped to each EXTERNAL interrupt number: */
+#define XCHAL_EXTINT0_NUM 0 /* (intlevel 1) */
+#define XCHAL_EXTINT1_NUM 1 /* (intlevel 2) */
+#define XCHAL_EXTINT2_NUM 2 /* (intlevel 3) */
+#define XCHAL_EXTINT3_NUM 3 /* (intlevel 1) */
+#define XCHAL_EXTINT4_NUM 4 /* (intlevel 1) */
+#define XCHAL_EXTINT5_NUM 5 /* (intlevel 1) */
+#define XCHAL_EXTINT6_NUM 6 /* (intlevel 1) */
+#define XCHAL_EXTINT7_NUM 7 /* (intlevel 1) */
+#define XCHAL_EXTINT8_NUM 8 /* (intlevel 2) */
+#define XCHAL_EXTINT9_NUM 9 /* (intlevel 3) */
+
+/* Corresponding interrupt masks: */
+#define XCHAL_EXTINT0_MASK 0x00000001
+#define XCHAL_EXTINT1_MASK 0x00000002
+#define XCHAL_EXTINT2_MASK 0x00000004
+#define XCHAL_EXTINT3_MASK 0x00000008
+#define XCHAL_EXTINT4_MASK 0x00000010
+#define XCHAL_EXTINT5_MASK 0x00000020
+#define XCHAL_EXTINT6_MASK 0x00000040
+#define XCHAL_EXTINT7_MASK 0x00000080
+#define XCHAL_EXTINT8_MASK 0x00000100
+#define XCHAL_EXTINT9_MASK 0x00000200
+
+/* Core config interrupt levels mapped to each external interrupt: */
+#define XCHAL_EXTINT0_LEVEL 1 /* (int number 0) */
+#define XCHAL_EXTINT1_LEVEL 2 /* (int number 1) */
+#define XCHAL_EXTINT2_LEVEL 3 /* (int number 2) */
+#define XCHAL_EXTINT3_LEVEL 1 /* (int number 3) */
+#define XCHAL_EXTINT4_LEVEL 1 /* (int number 4) */
+#define XCHAL_EXTINT5_LEVEL 1 /* (int number 5) */
+#define XCHAL_EXTINT6_LEVEL 1 /* (int number 6) */
+#define XCHAL_EXTINT7_LEVEL 1 /* (int number 7) */
+#define XCHAL_EXTINT8_LEVEL 2 /* (int number 8) */
+#define XCHAL_EXTINT9_LEVEL 3 /* (int number 9) */
+
+
+/*----------------------------------------------------------------------
+ EXCEPTIONS and VECTORS
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_EXCEPTIONS 1 /* 1 if exception option configured, 0 otherwise */
+
+#define XCHAL_XEA_VERSION 2 /* Xtensa Exception Architecture number: 1 for XEA1 (old), 2 for XEA2 (new) */
+#define XCHAL_HAVE_XEA1 0 /* 1 if XEA1, 0 otherwise */
+#define XCHAL_HAVE_XEA2 1 /* 1 if XEA2, 0 otherwise */
+/* For backward compatibility ONLY -- DO NOT USE (will be removed in future release): */
+#define XCHAL_HAVE_OLD_EXC_ARCH XCHAL_HAVE_XEA1 /* (DEPRECATED) 1 if old exception architecture (XEA1), 0 otherwise (eg. XEA2) */
+#define XCHAL_HAVE_EXCM XCHAL_HAVE_XEA2 /* (DEPRECATED) 1 if PS.EXCM bit exists (currently equals XCHAL_HAVE_TLBS) */
+
+#define XCHAL_RESET_VECTOR_VADDR 0xFE000020
+#define XCHAL_RESET_VECTOR_PADDR 0xFE000020
+#define XCHAL_USER_VECTOR_VADDR 0xD0000220
+#define XCHAL_PROGRAMEXC_VECTOR_VADDR XCHAL_USER_VECTOR_VADDR /* for backward compatibility */
+#define XCHAL_USEREXC_VECTOR_VADDR XCHAL_USER_VECTOR_VADDR /* for backward compatibility */
+#define XCHAL_USER_VECTOR_PADDR 0x00000220
+#define XCHAL_PROGRAMEXC_VECTOR_PADDR XCHAL_USER_VECTOR_PADDR /* for backward compatibility */
+#define XCHAL_USEREXC_VECTOR_PADDR XCHAL_USER_VECTOR_PADDR /* for backward compatibility */
+#define XCHAL_KERNEL_VECTOR_VADDR 0xD0000200
+#define XCHAL_STACKEDEXC_VECTOR_VADDR XCHAL_KERNEL_VECTOR_VADDR /* for backward compatibility */
+#define XCHAL_KERNELEXC_VECTOR_VADDR XCHAL_KERNEL_VECTOR_VADDR /* for backward compatibility */
+#define XCHAL_KERNEL_VECTOR_PADDR 0x00000200
+#define XCHAL_STACKEDEXC_VECTOR_PADDR XCHAL_KERNEL_VECTOR_PADDR /* for backward compatibility */
+#define XCHAL_KERNELEXC_VECTOR_PADDR XCHAL_KERNEL_VECTOR_PADDR /* for backward compatibility */
+#define XCHAL_DOUBLEEXC_VECTOR_VADDR 0xD0000290
+#define XCHAL_DOUBLEEXC_VECTOR_PADDR 0x00000290
+#define XCHAL_WINDOW_VECTORS_VADDR 0xD0000000
+#define XCHAL_WINDOW_VECTORS_PADDR 0x00000000
+#define XCHAL_INTLEVEL2_VECTOR_VADDR 0xD0000240
+#define XCHAL_INTLEVEL2_VECTOR_PADDR 0x00000240
+#define XCHAL_INTLEVEL3_VECTOR_VADDR 0xD0000250
+#define XCHAL_INTLEVEL3_VECTOR_PADDR 0x00000250
+#define XCHAL_INTLEVEL4_VECTOR_VADDR 0xFE000520
+#define XCHAL_INTLEVEL4_VECTOR_PADDR 0xFE000520
+#define XCHAL_DEBUG_VECTOR_VADDR XCHAL_INTLEVEL4_VECTOR_VADDR
+#define XCHAL_DEBUG_VECTOR_PADDR XCHAL_INTLEVEL4_VECTOR_PADDR
+
+/* Indexing macros: */
+#define _XCHAL_INTLEVEL_VECTOR_VADDR(n) XCHAL_INTLEVEL ## n ## _VECTOR_VADDR
+#define XCHAL_INTLEVEL_VECTOR_VADDR(n) _XCHAL_INTLEVEL_VECTOR_VADDR(n) /* n = 0 .. 15 */
+
+/*
+ * General Exception Causes
+ * (values of EXCCAUSE special register set by general exceptions,
+ * which vector to the user, kernel, or double-exception vectors):
+ */
+#define XCHAL_EXCCAUSE_ILLEGAL_INSTRUCTION 0 /* Illegal Instruction (IllegalInstruction) */
+#define XCHAL_EXCCAUSE_SYSTEM_CALL 1 /* System Call (SystemCall) */
+#define XCHAL_EXCCAUSE_INSTRUCTION_FETCH_ERROR 2 /* Instruction Fetch Error (InstructionFetchError) */
+#define XCHAL_EXCCAUSE_LOAD_STORE_ERROR 3 /* Load Store Error (LoadStoreError) */
+#define XCHAL_EXCCAUSE_LEVEL1_INTERRUPT 4 /* Level 1 Interrupt (Level1Interrupt) */
+#define XCHAL_EXCCAUSE_ALLOCA 5 /* Stack Extension Assist (Alloca) */
+#define XCHAL_EXCCAUSE_INTEGER_DIVIDE_BY_ZERO 6 /* Integer Divide by Zero (IntegerDivideByZero) */
+#define XCHAL_EXCCAUSE_SPECULATION 7 /* Speculation (Speculation) */
+#define XCHAL_EXCCAUSE_PRIVILEGED 8 /* Privileged Instruction (Privileged) */
+#define XCHAL_EXCCAUSE_UNALIGNED 9 /* Unaligned Load Store (Unaligned) */
+#define XCHAL_EXCCAUSE_ITLB_MISS 16 /* ITlb Miss Exception (ITlbMiss) */
+#define XCHAL_EXCCAUSE_ITLB_MULTIHIT 17 /* ITlb Mutltihit Exception (ITlbMultihit) */
+#define XCHAL_EXCCAUSE_ITLB_PRIVILEGE 18 /* ITlb Privilege Exception (ITlbPrivilege) */
+#define XCHAL_EXCCAUSE_ITLB_SIZE_RESTRICTION 19 /* ITlb Size Restriction Exception (ITlbSizeRestriction) */
+#define XCHAL_EXCCAUSE_FETCH_CACHE_ATTRIBUTE 20 /* Fetch Cache Attribute Exception (FetchCacheAttribute) */
+#define XCHAL_EXCCAUSE_DTLB_MISS 24 /* DTlb Miss Exception (DTlbMiss) */
+#define XCHAL_EXCCAUSE_DTLB_MULTIHIT 25 /* DTlb Multihit Exception (DTlbMultihit) */
+#define XCHAL_EXCCAUSE_DTLB_PRIVILEGE 26 /* DTlb Privilege Exception (DTlbPrivilege) */
+#define XCHAL_EXCCAUSE_DTLB_SIZE_RESTRICTION 27 /* DTlb Size Restriction Exception (DTlbSizeRestriction) */
+#define XCHAL_EXCCAUSE_LOAD_CACHE_ATTRIBUTE 28 /* Load Cache Attribute Exception (LoadCacheAttribute) */
+#define XCHAL_EXCCAUSE_STORE_CACHE_ATTRIBUTE 29 /* Store Cache Attribute Exception (StoreCacheAttribute) */
+#define XCHAL_EXCCAUSE_FLOATING_POINT 40 /* Floating Point Exception (FloatingPoint) */
+
+
+
+/*----------------------------------------------------------------------
+ TIMERS
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_CCOUNT 1 /* 1 if have CCOUNT, 0 otherwise */
+/*#define XCHAL_HAVE_TIMERS XCHAL_HAVE_CCOUNT*/
+#define XCHAL_NUM_TIMERS 3 /* number of CCOMPAREn regs */
+
+
+
+/*----------------------------------------------------------------------
+ DEBUG
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_DEBUG 1 /* 1 if debug option configured, 0 otherwise */
+#define XCHAL_HAVE_OCD 1 /* 1 if OnChipDebug option configured, 0 otherwise */
+#define XCHAL_NUM_IBREAK 2 /* number of IBREAKn regs */
+#define XCHAL_NUM_DBREAK 2 /* number of DBREAKn regs */
+#define XCHAL_DEBUGLEVEL 4 /* debug interrupt level */
+/*DebugExternalInterrupt 0 0|1*/
+/*DebugUseDIRArray 0 0|1*/
+
+
+
+
+/*----------------------------------------------------------------------
+ COPROCESSORS and EXTRA STATE
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_CP 0 /* 1 if coprocessor option configured (CPENABLE present) */
+#define XCHAL_CP_MAXCFG 0 /* max allowed cp id plus one (per cfg) */
+
+#include <xtensa/config/tie.h>
+
+
+
+
+/*----------------------------------------------------------------------
+ INTERNAL I/D RAM/ROMs and XLMI
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_NUM_INSTROM 0 /* number of core instruction ROMs configured */
+#define XCHAL_NUM_INSTRAM 0 /* number of core instruction RAMs configured */
+#define XCHAL_NUM_DATAROM 0 /* number of core data ROMs configured */
+#define XCHAL_NUM_DATARAM 0 /* number of core data RAMs configured */
+#define XCHAL_NUM_XLMI 0 /* number of core XLMI ports configured */
+#define XCHAL_NUM_IROM XCHAL_NUM_INSTROM /* (DEPRECATED) */
+#define XCHAL_NUM_IRAM XCHAL_NUM_INSTRAM /* (DEPRECATED) */
+#define XCHAL_NUM_DROM XCHAL_NUM_DATAROM /* (DEPRECATED) */
+#define XCHAL_NUM_DRAM XCHAL_NUM_DATARAM /* (DEPRECATED) */
+
+
+
+/*----------------------------------------------------------------------
+ CACHE
+ ----------------------------------------------------------------------*/
+
+/* Size of the cache lines in log2(bytes): */
+#define XCHAL_ICACHE_LINEWIDTH 4
+#define XCHAL_DCACHE_LINEWIDTH 4
+/* Size of the cache lines in bytes: */
+#define XCHAL_ICACHE_LINESIZE 16
+#define XCHAL_DCACHE_LINESIZE 16
+/* Max for both I-cache and D-cache (used for general alignment): */
+#define XCHAL_CACHE_LINEWIDTH_MAX 4
+#define XCHAL_CACHE_LINESIZE_MAX 16
+
+/* Number of cache sets in log2(lines per way): */
+#define XCHAL_ICACHE_SETWIDTH 8
+#define XCHAL_DCACHE_SETWIDTH 8
+/* Max for both I-cache and D-cache (used for general cache-coherency page alignment): */
+#define XCHAL_CACHE_SETWIDTH_MAX 8
+#define XCHAL_CACHE_SETSIZE_MAX 256
+
+/* Cache set associativity (number of ways): */
+#define XCHAL_ICACHE_WAYS 2
+#define XCHAL_DCACHE_WAYS 2
+
+/* Size of the caches in bytes (ways * 2^(linewidth + setwidth)): */
+#define XCHAL_ICACHE_SIZE 8192
+#define XCHAL_DCACHE_SIZE 8192
+
+/* Cache features: */
+#define XCHAL_DCACHE_IS_WRITEBACK 0
+/* Whether cache locking feature is available: */
+#define XCHAL_ICACHE_LINE_LOCKABLE 0
+#define XCHAL_DCACHE_LINE_LOCKABLE 0
+
+/* Number of (encoded) cache attribute bits: */
+#define XCHAL_CA_BITS 4 /* number of bits needed to hold cache attribute encoding */
+/* (The number of access mode bits (decoded cache attribute bits) is defined by the architecture; see xtensa/hal.h?) */
+
+
+/* Cache Attribute encodings -- lists of access modes for each cache attribute: */
+#define XCHAL_FCA_LIST XTHAL_FAM_EXCEPTION XCHAL_SEP \
+ XTHAL_FAM_BYPASS XCHAL_SEP \
+ XTHAL_FAM_EXCEPTION XCHAL_SEP \
+ XTHAL_FAM_BYPASS XCHAL_SEP \
+ XTHAL_FAM_EXCEPTION XCHAL_SEP \
+ XTHAL_FAM_CACHED XCHAL_SEP \
+ XTHAL_FAM_EXCEPTION XCHAL_SEP \
+ XTHAL_FAM_CACHED XCHAL_SEP \
+ XTHAL_FAM_EXCEPTION XCHAL_SEP \
+ XTHAL_FAM_CACHED XCHAL_SEP \
+ XTHAL_FAM_EXCEPTION XCHAL_SEP \
+ XTHAL_FAM_CACHED XCHAL_SEP \
+ XTHAL_FAM_EXCEPTION XCHAL_SEP \
+ XTHAL_FAM_EXCEPTION XCHAL_SEP \
+ XTHAL_FAM_EXCEPTION XCHAL_SEP \
+ XTHAL_FAM_EXCEPTION
+#define XCHAL_LCA_LIST XTHAL_LAM_EXCEPTION XCHAL_SEP \
+ XTHAL_LAM_BYPASSG XCHAL_SEP \
+ XTHAL_LAM_EXCEPTION XCHAL_SEP \
+ XTHAL_LAM_BYPASSG XCHAL_SEP \
+ XTHAL_LAM_EXCEPTION XCHAL_SEP \
+ XTHAL_LAM_CACHED XCHAL_SEP \
+ XTHAL_LAM_EXCEPTION XCHAL_SEP \
+ XTHAL_LAM_CACHED XCHAL_SEP \
+ XTHAL_LAM_EXCEPTION XCHAL_SEP \
+ XTHAL_LAM_NACACHED XCHAL_SEP \
+ XTHAL_LAM_EXCEPTION XCHAL_SEP \
+ XTHAL_LAM_NACACHED XCHAL_SEP \
+ XTHAL_LAM_EXCEPTION XCHAL_SEP \
+ XTHAL_LAM_ISOLATE XCHAL_SEP \
+ XTHAL_LAM_EXCEPTION XCHAL_SEP \
+ XTHAL_LAM_CACHED
+#define XCHAL_SCA_LIST XTHAL_SAM_EXCEPTION XCHAL_SEP \
+ XTHAL_SAM_EXCEPTION XCHAL_SEP \
+ XTHAL_SAM_EXCEPTION XCHAL_SEP \
+ XTHAL_SAM_BYPASS XCHAL_SEP \
+ XTHAL_SAM_EXCEPTION XCHAL_SEP \
+ XTHAL_SAM_EXCEPTION XCHAL_SEP \
+ XTHAL_SAM_EXCEPTION XCHAL_SEP \
+ XTHAL_SAM_WRITETHRU XCHAL_SEP \
+ XTHAL_SAM_EXCEPTION XCHAL_SEP \
+ XTHAL_SAM_EXCEPTION XCHAL_SEP \
+ XTHAL_SAM_EXCEPTION XCHAL_SEP \
+ XTHAL_SAM_WRITETHRU XCHAL_SEP \
+ XTHAL_SAM_EXCEPTION XCHAL_SEP \
+ XTHAL_SAM_ISOLATE XCHAL_SEP \
+ XTHAL_SAM_EXCEPTION XCHAL_SEP \
+ XTHAL_SAM_WRITETHRU
+
+/* Test:
+ read/only: 0 + 1 + 2 + 4 + 5 + 6 + 8 + 9 + 10 + 12 + 14
+ read/only: 0 + 1 + 2 + 4 + 5 + 6 + 8 + 9 + 10 + 12 + 14
+ all: 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15
+ fault: 0 + 2 + 4 + 6 + 8 + 10 + 12 + 14
+ r/w/x cached:
+ r/w/x dcached:
+ I-bypass: 1 + 3
+
+ load guard bit set: 1 + 3
+ load guard bit clr: 0 + 2 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15
+ hit-cache r/w/x: 7 + 11
+
+ fams: 5
+ fams: 0 / 6 / 18 / 1 / 2
+ fams: Bypass / Isolate / Cached / Exception / NACached
+
+ MMU okay: yes
+*/
+
+
+/*----------------------------------------------------------------------
+ MMU
+ ----------------------------------------------------------------------*/
+
+/*
+ * General notes on MMU parameters.
+ *
+ * Terminology:
+ * ASID = address-space ID (acts as an "extension" of virtual addresses)
+ * VPN = virtual page number
+ * PPN = physical page number
+ * CA = encoded cache attribute (access modes)
+ * TLB = translation look-aside buffer (term is stretched somewhat here)
+ * I = instruction (fetch accesses)
+ * D = data (load and store accesses)
+ * way = each TLB (ITLB and DTLB) consists of a number of "ways"
+ * that simultaneously match the virtual address of an access;
+ * a TLB successfully translates a virtual address if exactly
+ * one way matches the vaddr; if none match, it is a miss;
+ * if multiple match, one gets a "multihit" exception;
+ * each way can be independently configured in terms of number of
+ * entries, page sizes, which fields are writable or constant, etc.
+ * set = group of contiguous ways with exactly identical parameters
+ * ARF = auto-refill; hardware services a 1st-level miss by loading a PTE
+ * from the page table and storing it in one of the auto-refill ways;
+ * if this PTE load also misses, a miss exception is posted for s/w.
+ * min-wired = a "min-wired" way can be used to map a single (minimum-sized)
+ * page arbitrarily under program control; it has a single entry,
+ * is non-auto-refill (some other way(s) must be auto-refill),
+ * all its fields (VPN, PPN, ASID, CA) are all writable, and it
+ * supports the XCHAL_MMU_MIN_PTE_PAGE_SIZE page size (a current
+ * restriction is that this be the only page size it supports).
+ *
+ * TLB way entries are virtually indexed.
+ * TLB ways that support multiple page sizes:
+ * - must have all writable VPN and PPN fields;
+ * - can only use one page size at any given time (eg. setup at startup),
+ * selected by the respective ITLBCFG or DTLBCFG special register,
+ * whose bits n*4+3 .. n*4 index the list of page sizes for way n
+ * (XCHAL_xTLB_SETm_PAGESZ_LOG2_LIST for set m corresponding to way n);
+ * this list may be sparse for auto-refill ways because auto-refill
+ * ways have independent lists of supported page sizes sharing a
+ * common encoding with PTE entries; the encoding is the index into
+ * this list; unsupported sizes for a given way are zero in the list;
+ * selecting unsupported sizes results in undefined hardware behaviour;
+ * - is only possible for ways 0 thru 7 (due to ITLBCFG/DTLBCFG definition).
+ */
+
+#define XCHAL_HAVE_CACHEATTR 0 /* 1 if CACHEATTR register present, 0 if TLBs present instead */
+#define XCHAL_HAVE_TLBS 1 /* 1 if TLBs present, 0 if CACHEATTR present instead */
+#define XCHAL_HAVE_MMU XCHAL_HAVE_TLBS /* (DEPRECATED; use XCHAL_HAVE_TLBS instead; will be removed in future release) */
+#define XCHAL_HAVE_SPANNING_WAY 0 /* 1 if single way maps entire virtual address space in I+D */
+#define XCHAL_HAVE_IDENTITY_MAP 0 /* 1 if virtual addr == physical addr always, 0 otherwise */
+#define XCHAL_HAVE_MIMIC_CACHEATTR 0 /* 1 if have MMU that mimics a CACHEATTR config (CaMMU) */
+#define XCHAL_HAVE_XLT_CACHEATTR 0 /* 1 if have MMU that mimics a CACHEATTR config, but with translation (CaXltMMU) */
+
+#define XCHAL_MMU_ASID_BITS 8 /* number of bits in ASIDs (address space IDs) */
+#define XCHAL_MMU_ASID_INVALID 0 /* ASID value indicating invalid address space */
+#define XCHAL_MMU_ASID_KERNEL 1 /* ASID value indicating kernel (ring 0) address space */
+#define XCHAL_MMU_RINGS 4 /* number of rings supported (1..4) */
+#define XCHAL_MMU_RING_BITS 2 /* number of bits needed to hold ring number */
+#define XCHAL_MMU_SR_BITS 0 /* number of size-restriction bits supported */
+#define XCHAL_MMU_CA_BITS 4 /* number of bits needed to hold cache attribute encoding */
+#define XCHAL_MMU_MAX_PTE_PAGE_SIZE 12 /* max page size in a PTE structure (log2) */
+#define XCHAL_MMU_MIN_PTE_PAGE_SIZE 12 /* min page size in a PTE structure (log2) */
+
+
+/*** Instruction TLB: ***/
+
+#define XCHAL_ITLB_WAY_BITS 3 /* number of bits holding the ways */
+#define XCHAL_ITLB_WAYS 7 /* number of ways (n-way set-associative TLB) */
+#define XCHAL_ITLB_ARF_WAYS 4 /* number of auto-refill ways */
+#define XCHAL_ITLB_SETS 4 /* number of sets (groups of ways with identical settings) */
+
+/* Way set to which each way belongs: */
+#define XCHAL_ITLB_WAY0_SET 0
+#define XCHAL_ITLB_WAY1_SET 0
+#define XCHAL_ITLB_WAY2_SET 0
+#define XCHAL_ITLB_WAY3_SET 0
+#define XCHAL_ITLB_WAY4_SET 1
+#define XCHAL_ITLB_WAY5_SET 2
+#define XCHAL_ITLB_WAY6_SET 3
+
+/* Ways sets that are used by hardware auto-refill (ARF): */
+#define XCHAL_ITLB_ARF_SETS 1 /* number of auto-refill sets */
+#define XCHAL_ITLB_ARF_SET0 0 /* index of n'th auto-refill set */
+
+/* Way sets that are "min-wired" (see terminology comment above): */
+#define XCHAL_ITLB_MINWIRED_SETS 0 /* number of "min-wired" sets */
+
+
+/* ITLB way set 0 (group of ways 0 thru 3): */
+#define XCHAL_ITLB_SET0_WAY 0 /* index of first way in this way set */
+#define XCHAL_ITLB_SET0_WAYS 4 /* number of (contiguous) ways in this way set */
+#define XCHAL_ITLB_SET0_ENTRIES_LOG2 2 /* log2(number of entries in this way) */
+#define XCHAL_ITLB_SET0_ENTRIES 4 /* number of entries in this way (always a power of 2) */
+#define XCHAL_ITLB_SET0_ARF 1 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
+#define XCHAL_ITLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */
+#define XCHAL_ITLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */
+#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MIN 12 /* log2(minimum supported page size) */
+#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MAX 12 /* log2(maximum supported page size) */
+#define XCHAL_ITLB_SET0_PAGESZ_LOG2_LIST 12 /* list of log2(page size)s, separated by XCHAL_SEP;
+ 2^PAGESZ_BITS entries in list, unsupported entries are zero */
+#define XCHAL_ITLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */
+#define XCHAL_ITLB_SET0_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */
+#define XCHAL_ITLB_SET0_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */
+#define XCHAL_ITLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */
+#define XCHAL_ITLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
+#define XCHAL_ITLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_ITLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_ITLB_SET0_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
+
+/* ITLB way set 1 (group of ways 4 thru 4): */
+#define XCHAL_ITLB_SET1_WAY 4 /* index of first way in this way set */
+#define XCHAL_ITLB_SET1_WAYS 1 /* number of (contiguous) ways in this way set */
+#define XCHAL_ITLB_SET1_ENTRIES_LOG2 2 /* log2(number of entries in this way) */
+#define XCHAL_ITLB_SET1_ENTRIES 4 /* number of entries in this way (always a power of 2) */
+#define XCHAL_ITLB_SET1_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
+#define XCHAL_ITLB_SET1_PAGESIZES 4 /* number of supported page sizes in this way */
+#define XCHAL_ITLB_SET1_PAGESZ_BITS 2 /* number of bits to encode the page size */
+#define XCHAL_ITLB_SET1_PAGESZ_LOG2_MIN 20 /* log2(minimum supported page size) */
+#define XCHAL_ITLB_SET1_PAGESZ_LOG2_MAX 26 /* log2(maximum supported page size) */
+#define XCHAL_ITLB_SET1_PAGESZ_LOG2_LIST 20 XCHAL_SEP 22 XCHAL_SEP 24 XCHAL_SEP 26 /* list of log2(page size)s, separated by XCHAL_SEP;
+ 2^PAGESZ_BITS entries in list, unsupported entries are zero */
+#define XCHAL_ITLB_SET1_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */
+#define XCHAL_ITLB_SET1_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */
+#define XCHAL_ITLB_SET1_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */
+#define XCHAL_ITLB_SET1_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */
+#define XCHAL_ITLB_SET1_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
+#define XCHAL_ITLB_SET1_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_ITLB_SET1_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_ITLB_SET1_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
+
+/* ITLB way set 2 (group of ways 5 thru 5): */
+#define XCHAL_ITLB_SET2_WAY 5 /* index of first way in this way set */
+#define XCHAL_ITLB_SET2_WAYS 1 /* number of (contiguous) ways in this way set */
+#define XCHAL_ITLB_SET2_ENTRIES_LOG2 1 /* log2(number of entries in this way) */
+#define XCHAL_ITLB_SET2_ENTRIES 2 /* number of entries in this way (always a power of 2) */
+#define XCHAL_ITLB_SET2_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
+#define XCHAL_ITLB_SET2_PAGESIZES 1 /* number of supported page sizes in this way */
+#define XCHAL_ITLB_SET2_PAGESZ_BITS 0 /* number of bits to encode the page size */
+#define XCHAL_ITLB_SET2_PAGESZ_LOG2_MIN 27 /* log2(minimum supported page size) */
+#define XCHAL_ITLB_SET2_PAGESZ_LOG2_MAX 27 /* log2(maximum supported page size) */
+#define XCHAL_ITLB_SET2_PAGESZ_LOG2_LIST 27 /* list of log2(page size)s, separated by XCHAL_SEP;
+ 2^PAGESZ_BITS entries in list, unsupported entries are zero */
+#define XCHAL_ITLB_SET2_ASID_CONSTMASK 0xFF /* constant ASID bits; 0 if all writable */
+#define XCHAL_ITLB_SET2_VPN_CONSTMASK 0xF0000000 /* constant VPN bits, not including entry index bits; 0 if all writable */
+#define XCHAL_ITLB_SET2_PPN_CONSTMASK 0xF8000000 /* constant PPN bits, including entry index bits; 0 if all writable */
+#define XCHAL_ITLB_SET2_CA_CONSTMASK 0x0000000F /* constant CA bits; 0 if all writable */
+#define XCHAL_ITLB_SET2_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
+#define XCHAL_ITLB_SET2_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_ITLB_SET2_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_ITLB_SET2_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
+/* Constant ASID values for each entry of ITLB way set 2 (because ASID_CONSTMASK is non-zero): */
+#define XCHAL_ITLB_SET2_E0_ASID_CONST 0x01
+#define XCHAL_ITLB_SET2_E1_ASID_CONST 0x01
+/* Constant VPN values for each entry of ITLB way set 2 (because VPN_CONSTMASK is non-zero): */
+#define XCHAL_ITLB_SET2_E0_VPN_CONST 0xD0000000
+#define XCHAL_ITLB_SET2_E1_VPN_CONST 0xD8000000
+/* Constant PPN values for each entry of ITLB way set 2 (because PPN_CONSTMASK is non-zero): */
+#define XCHAL_ITLB_SET2_E0_PPN_CONST 0x00000000
+#define XCHAL_ITLB_SET2_E1_PPN_CONST 0x00000000
+/* Constant CA values for each entry of ITLB way set 2 (because CA_CONSTMASK is non-zero): */
+#define XCHAL_ITLB_SET2_E0_CA_CONST 0x07
+#define XCHAL_ITLB_SET2_E1_CA_CONST 0x03
+
+/* ITLB way set 3 (group of ways 6 thru 6): */
+#define XCHAL_ITLB_SET3_WAY 6 /* index of first way in this way set */
+#define XCHAL_ITLB_SET3_WAYS 1 /* number of (contiguous) ways in this way set */
+#define XCHAL_ITLB_SET3_ENTRIES_LOG2 1 /* log2(number of entries in this way) */
+#define XCHAL_ITLB_SET3_ENTRIES 2 /* number of entries in this way (always a power of 2) */
+#define XCHAL_ITLB_SET3_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
+#define XCHAL_ITLB_SET3_PAGESIZES 1 /* number of supported page sizes in this way */
+#define XCHAL_ITLB_SET3_PAGESZ_BITS 0 /* number of bits to encode the page size */
+#define XCHAL_ITLB_SET3_PAGESZ_LOG2_MIN 28 /* log2(minimum supported page size) */
+#define XCHAL_ITLB_SET3_PAGESZ_LOG2_MAX 28 /* log2(maximum supported page size) */
+#define XCHAL_ITLB_SET3_PAGESZ_LOG2_LIST 28 /* list of log2(page size)s, separated by XCHAL_SEP;
+ 2^PAGESZ_BITS entries in list, unsupported entries are zero */
+#define XCHAL_ITLB_SET3_ASID_CONSTMASK 0xFF /* constant ASID bits; 0 if all writable */
+#define XCHAL_ITLB_SET3_VPN_CONSTMASK 0xE0000000 /* constant VPN bits, not including entry index bits; 0 if all writable */
+#define XCHAL_ITLB_SET3_PPN_CONSTMASK 0xF0000000 /* constant PPN bits, including entry index bits; 0 if all writable */
+#define XCHAL_ITLB_SET3_CA_CONSTMASK 0x0000000F /* constant CA bits; 0 if all writable */
+#define XCHAL_ITLB_SET3_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
+#define XCHAL_ITLB_SET3_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_ITLB_SET3_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_ITLB_SET3_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
+/* Constant ASID values for each entry of ITLB way set 3 (because ASID_CONSTMASK is non-zero): */
+#define XCHAL_ITLB_SET3_E0_ASID_CONST 0x01
+#define XCHAL_ITLB_SET3_E1_ASID_CONST 0x01
+/* Constant VPN values for each entry of ITLB way set 3 (because VPN_CONSTMASK is non-zero): */
+#define XCHAL_ITLB_SET3_E0_VPN_CONST 0xE0000000
+#define XCHAL_ITLB_SET3_E1_VPN_CONST 0xF0000000
+/* Constant PPN values for each entry of ITLB way set 3 (because PPN_CONSTMASK is non-zero): */
+#define XCHAL_ITLB_SET3_E0_PPN_CONST 0xF0000000
+#define XCHAL_ITLB_SET3_E1_PPN_CONST 0xF0000000
+/* Constant CA values for each entry of ITLB way set 3 (because CA_CONSTMASK is non-zero): */
+#define XCHAL_ITLB_SET3_E0_CA_CONST 0x07
+#define XCHAL_ITLB_SET3_E1_CA_CONST 0x03
+
+/* Indexing macros: */
+#define _XCHAL_ITLB_SET(n,_what) XCHAL_ITLB_SET ## n ## _what
+#define XCHAL_ITLB_SET(n,what) _XCHAL_ITLB_SET(n, _ ## what )
+#define _XCHAL_ITLB_SET_E(n,i,_what) XCHAL_ITLB_SET ## n ## _E ## i ## _what
+#define XCHAL_ITLB_SET_E(n,i,what) _XCHAL_ITLB_SET_E(n,i, _ ## what )
+/*
+ * Example use: XCHAL_ITLB_SET(XCHAL_ITLB_ARF_SET0,ENTRIES)
+ * to get the value of XCHAL_ITLB_SET<n>_ENTRIES where <n> is the first auto-refill set.
+ */
+
+
+/*** Data TLB: ***/
+
+#define XCHAL_DTLB_WAY_BITS 4 /* number of bits holding the ways */
+#define XCHAL_DTLB_WAYS 10 /* number of ways (n-way set-associative TLB) */
+#define XCHAL_DTLB_ARF_WAYS 4 /* number of auto-refill ways */
+#define XCHAL_DTLB_SETS 5 /* number of sets (groups of ways with identical settings) */
+
+/* Way set to which each way belongs: */
+#define XCHAL_DTLB_WAY0_SET 0
+#define XCHAL_DTLB_WAY1_SET 0
+#define XCHAL_DTLB_WAY2_SET 0
+#define XCHAL_DTLB_WAY3_SET 0
+#define XCHAL_DTLB_WAY4_SET 1
+#define XCHAL_DTLB_WAY5_SET 2
+#define XCHAL_DTLB_WAY6_SET 3
+#define XCHAL_DTLB_WAY7_SET 4
+#define XCHAL_DTLB_WAY8_SET 4
+#define XCHAL_DTLB_WAY9_SET 4
+
+/* Ways sets that are used by hardware auto-refill (ARF): */
+#define XCHAL_DTLB_ARF_SETS 1 /* number of auto-refill sets */
+#define XCHAL_DTLB_ARF_SET0 0 /* index of n'th auto-refill set */
+
+/* Way sets that are "min-wired" (see terminology comment above): */
+#define XCHAL_DTLB_MINWIRED_SETS 1 /* number of "min-wired" sets */
+#define XCHAL_DTLB_MINWIRED_SET0 4 /* index of n'th "min-wired" set */
+
+
+/* DTLB way set 0 (group of ways 0 thru 3): */
+#define XCHAL_DTLB_SET0_WAY 0 /* index of first way in this way set */
+#define XCHAL_DTLB_SET0_WAYS 4 /* number of (contiguous) ways in this way set */
+#define XCHAL_DTLB_SET0_ENTRIES_LOG2 2 /* log2(number of entries in this way) */
+#define XCHAL_DTLB_SET0_ENTRIES 4 /* number of entries in this way (always a power of 2) */
+#define XCHAL_DTLB_SET0_ARF 1 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
+#define XCHAL_DTLB_SET0_PAGESIZES 1 /* number of supported page sizes in this way */
+#define XCHAL_DTLB_SET0_PAGESZ_BITS 0 /* number of bits to encode the page size */
+#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MIN 12 /* log2(minimum supported page size) */
+#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MAX 12 /* log2(maximum supported page size) */
+#define XCHAL_DTLB_SET0_PAGESZ_LOG2_LIST 12 /* list of log2(page size)s, separated by XCHAL_SEP;
+ 2^PAGESZ_BITS entries in list, unsupported entries are zero */
+#define XCHAL_DTLB_SET0_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */
+#define XCHAL_DTLB_SET0_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */
+#define XCHAL_DTLB_SET0_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */
+#define XCHAL_DTLB_SET0_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */
+#define XCHAL_DTLB_SET0_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET0_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET0_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET0_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
+
+/* DTLB way set 1 (group of ways 4 thru 4): */
+#define XCHAL_DTLB_SET1_WAY 4 /* index of first way in this way set */
+#define XCHAL_DTLB_SET1_WAYS 1 /* number of (contiguous) ways in this way set */
+#define XCHAL_DTLB_SET1_ENTRIES_LOG2 2 /* log2(number of entries in this way) */
+#define XCHAL_DTLB_SET1_ENTRIES 4 /* number of entries in this way (always a power of 2) */
+#define XCHAL_DTLB_SET1_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
+#define XCHAL_DTLB_SET1_PAGESIZES 4 /* number of supported page sizes in this way */
+#define XCHAL_DTLB_SET1_PAGESZ_BITS 2 /* number of bits to encode the page size */
+#define XCHAL_DTLB_SET1_PAGESZ_LOG2_MIN 20 /* log2(minimum supported page size) */
+#define XCHAL_DTLB_SET1_PAGESZ_LOG2_MAX 26 /* log2(maximum supported page size) */
+#define XCHAL_DTLB_SET1_PAGESZ_LOG2_LIST 20 XCHAL_SEP 22 XCHAL_SEP 24 XCHAL_SEP 26 /* list of log2(page size)s, separated by XCHAL_SEP;
+ 2^PAGESZ_BITS entries in list, unsupported entries are zero */
+#define XCHAL_DTLB_SET1_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */
+#define XCHAL_DTLB_SET1_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */
+#define XCHAL_DTLB_SET1_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */
+#define XCHAL_DTLB_SET1_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */
+#define XCHAL_DTLB_SET1_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET1_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET1_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET1_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
+
+/* DTLB way set 2 (group of ways 5 thru 5): */
+#define XCHAL_DTLB_SET2_WAY 5 /* index of first way in this way set */
+#define XCHAL_DTLB_SET2_WAYS 1 /* number of (contiguous) ways in this way set */
+#define XCHAL_DTLB_SET2_ENTRIES_LOG2 1 /* log2(number of entries in this way) */
+#define XCHAL_DTLB_SET2_ENTRIES 2 /* number of entries in this way (always a power of 2) */
+#define XCHAL_DTLB_SET2_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
+#define XCHAL_DTLB_SET2_PAGESIZES 1 /* number of supported page sizes in this way */
+#define XCHAL_DTLB_SET2_PAGESZ_BITS 0 /* number of bits to encode the page size */
+#define XCHAL_DTLB_SET2_PAGESZ_LOG2_MIN 27 /* log2(minimum supported page size) */
+#define XCHAL_DTLB_SET2_PAGESZ_LOG2_MAX 27 /* log2(maximum supported page size) */
+#define XCHAL_DTLB_SET2_PAGESZ_LOG2_LIST 27 /* list of log2(page size)s, separated by XCHAL_SEP;
+ 2^PAGESZ_BITS entries in list, unsupported entries are zero */
+#define XCHAL_DTLB_SET2_ASID_CONSTMASK 0xFF /* constant ASID bits; 0 if all writable */
+#define XCHAL_DTLB_SET2_VPN_CONSTMASK 0xF0000000 /* constant VPN bits, not including entry index bits; 0 if all writable */
+#define XCHAL_DTLB_SET2_PPN_CONSTMASK 0xF8000000 /* constant PPN bits, including entry index bits; 0 if all writable */
+#define XCHAL_DTLB_SET2_CA_CONSTMASK 0x0000000F /* constant CA bits; 0 if all writable */
+#define XCHAL_DTLB_SET2_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET2_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET2_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET2_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
+/* Constant ASID values for each entry of DTLB way set 2 (because ASID_CONSTMASK is non-zero): */
+#define XCHAL_DTLB_SET2_E0_ASID_CONST 0x01
+#define XCHAL_DTLB_SET2_E1_ASID_CONST 0x01
+/* Constant VPN values for each entry of DTLB way set 2 (because VPN_CONSTMASK is non-zero): */
+#define XCHAL_DTLB_SET2_E0_VPN_CONST 0xD0000000
+#define XCHAL_DTLB_SET2_E1_VPN_CONST 0xD8000000
+/* Constant PPN values for each entry of DTLB way set 2 (because PPN_CONSTMASK is non-zero): */
+#define XCHAL_DTLB_SET2_E0_PPN_CONST 0x00000000
+#define XCHAL_DTLB_SET2_E1_PPN_CONST 0x00000000
+/* Constant CA values for each entry of DTLB way set 2 (because CA_CONSTMASK is non-zero): */
+#define XCHAL_DTLB_SET2_E0_CA_CONST 0x07
+#define XCHAL_DTLB_SET2_E1_CA_CONST 0x03
+
+/* DTLB way set 3 (group of ways 6 thru 6): */
+#define XCHAL_DTLB_SET3_WAY 6 /* index of first way in this way set */
+#define XCHAL_DTLB_SET3_WAYS 1 /* number of (contiguous) ways in this way set */
+#define XCHAL_DTLB_SET3_ENTRIES_LOG2 1 /* log2(number of entries in this way) */
+#define XCHAL_DTLB_SET3_ENTRIES 2 /* number of entries in this way (always a power of 2) */
+#define XCHAL_DTLB_SET3_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
+#define XCHAL_DTLB_SET3_PAGESIZES 1 /* number of supported page sizes in this way */
+#define XCHAL_DTLB_SET3_PAGESZ_BITS 0 /* number of bits to encode the page size */
+#define XCHAL_DTLB_SET3_PAGESZ_LOG2_MIN 28 /* log2(minimum supported page size) */
+#define XCHAL_DTLB_SET3_PAGESZ_LOG2_MAX 28 /* log2(maximum supported page size) */
+#define XCHAL_DTLB_SET3_PAGESZ_LOG2_LIST 28 /* list of log2(page size)s, separated by XCHAL_SEP;
+ 2^PAGESZ_BITS entries in list, unsupported entries are zero */
+#define XCHAL_DTLB_SET3_ASID_CONSTMASK 0xFF /* constant ASID bits; 0 if all writable */
+#define XCHAL_DTLB_SET3_VPN_CONSTMASK 0xE0000000 /* constant VPN bits, not including entry index bits; 0 if all writable */
+#define XCHAL_DTLB_SET3_PPN_CONSTMASK 0xF0000000 /* constant PPN bits, including entry index bits; 0 if all writable */
+#define XCHAL_DTLB_SET3_CA_CONSTMASK 0x0000000F /* constant CA bits; 0 if all writable */
+#define XCHAL_DTLB_SET3_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET3_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET3_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET3_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
+/* Constant ASID values for each entry of DTLB way set 3 (because ASID_CONSTMASK is non-zero): */
+#define XCHAL_DTLB_SET3_E0_ASID_CONST 0x01
+#define XCHAL_DTLB_SET3_E1_ASID_CONST 0x01
+/* Constant VPN values for each entry of DTLB way set 3 (because VPN_CONSTMASK is non-zero): */
+#define XCHAL_DTLB_SET3_E0_VPN_CONST 0xE0000000
+#define XCHAL_DTLB_SET3_E1_VPN_CONST 0xF0000000
+/* Constant PPN values for each entry of DTLB way set 3 (because PPN_CONSTMASK is non-zero): */
+#define XCHAL_DTLB_SET3_E0_PPN_CONST 0xF0000000
+#define XCHAL_DTLB_SET3_E1_PPN_CONST 0xF0000000
+/* Constant CA values for each entry of DTLB way set 3 (because CA_CONSTMASK is non-zero): */
+#define XCHAL_DTLB_SET3_E0_CA_CONST 0x07
+#define XCHAL_DTLB_SET3_E1_CA_CONST 0x03
+
+/* DTLB way set 4 (group of ways 7 thru 9): */
+#define XCHAL_DTLB_SET4_WAY 7 /* index of first way in this way set */
+#define XCHAL_DTLB_SET4_WAYS 3 /* number of (contiguous) ways in this way set */
+#define XCHAL_DTLB_SET4_ENTRIES_LOG2 0 /* log2(number of entries in this way) */
+#define XCHAL_DTLB_SET4_ENTRIES 1 /* number of entries in this way (always a power of 2) */
+#define XCHAL_DTLB_SET4_ARF 0 /* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
+#define XCHAL_DTLB_SET4_PAGESIZES 1 /* number of supported page sizes in this way */
+#define XCHAL_DTLB_SET4_PAGESZ_BITS 0 /* number of bits to encode the page size */
+#define XCHAL_DTLB_SET4_PAGESZ_LOG2_MIN 12 /* log2(minimum supported page size) */
+#define XCHAL_DTLB_SET4_PAGESZ_LOG2_MAX 12 /* log2(maximum supported page size) */
+#define XCHAL_DTLB_SET4_PAGESZ_LOG2_LIST 12 /* list of log2(page size)s, separated by XCHAL_SEP;
+ 2^PAGESZ_BITS entries in list, unsupported entries are zero */
+#define XCHAL_DTLB_SET4_ASID_CONSTMASK 0 /* constant ASID bits; 0 if all writable */
+#define XCHAL_DTLB_SET4_VPN_CONSTMASK 0 /* constant VPN bits, not including entry index bits; 0 if all writable */
+#define XCHAL_DTLB_SET4_PPN_CONSTMASK 0 /* constant PPN bits, including entry index bits; 0 if all writable */
+#define XCHAL_DTLB_SET4_CA_CONSTMASK 0 /* constant CA bits; 0 if all writable */
+#define XCHAL_DTLB_SET4_ASID_RESET 0 /* 1 if ASID reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET4_VPN_RESET 0 /* 1 if VPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET4_PPN_RESET 0 /* 1 if PPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET4_CA_RESET 0 /* 1 if CA reset values defined (and all writable); 0 otherwise */
+
+/* Indexing macros: */
+#define _XCHAL_DTLB_SET(n,_what) XCHAL_DTLB_SET ## n ## _what
+#define XCHAL_DTLB_SET(n,what) _XCHAL_DTLB_SET(n, _ ## what )
+#define _XCHAL_DTLB_SET_E(n,i,_what) XCHAL_DTLB_SET ## n ## _E ## i ## _what
+#define XCHAL_DTLB_SET_E(n,i,what) _XCHAL_DTLB_SET_E(n,i, _ ## what )
+/*
+ * Example use: XCHAL_DTLB_SET(XCHAL_DTLB_ARF_SET0,ENTRIES)
+ * to get the value of XCHAL_DTLB_SET<n>_ENTRIES where <n> is the first auto-refill set.
+ */
+
+
+/*
+ * Determine whether we have a full MMU (with Page Table and Protection)
+ * usable for an MMU-based OS:
+ */
+#if XCHAL_HAVE_TLBS && !XCHAL_HAVE_SPANNING_WAY && XCHAL_ITLB_ARF_WAYS > 0 && XCHAL_DTLB_ARF_WAYS > 0 && XCHAL_MMU_RINGS >= 2
+# define XCHAL_HAVE_PTP_MMU 1 /* have full MMU (with page table [autorefill] and protection) */
+#else
+# define XCHAL_HAVE_PTP_MMU 0 /* don't have full MMU */
+#endif
+
+/*
+ * For full MMUs, report kernel RAM segment and kernel I/O segment static page mappings:
+ */
+#if XCHAL_HAVE_PTP_MMU
+#define XCHAL_KSEG_CACHED_VADDR 0xD0000000 /* virt.addr of kernel RAM cached static map */
+#define XCHAL_KSEG_CACHED_PADDR 0x00000000 /* phys.addr of kseg_cached */
+#define XCHAL_KSEG_CACHED_SIZE 0x08000000 /* size in bytes of kseg_cached (assumed power of 2!!!) */
+#define XCHAL_KSEG_BYPASS_VADDR 0xD8000000 /* virt.addr of kernel RAM bypass (uncached) static map */
+#define XCHAL_KSEG_BYPASS_PADDR 0x00000000 /* phys.addr of kseg_bypass */
+#define XCHAL_KSEG_BYPASS_SIZE 0x08000000 /* size in bytes of kseg_bypass (assumed power of 2!!!) */
+
+#define XCHAL_KIO_CACHED_VADDR 0xE0000000 /* virt.addr of kernel I/O cached static map */
+#define XCHAL_KIO_CACHED_PADDR 0xF0000000 /* phys.addr of kio_cached */
+#define XCHAL_KIO_CACHED_SIZE 0x10000000 /* size in bytes of kio_cached (assumed power of 2!!!) */
+#define XCHAL_KIO_BYPASS_VADDR 0xF0000000 /* virt.addr of kernel I/O bypass (uncached) static map */
+#define XCHAL_KIO_BYPASS_PADDR 0xF0000000 /* phys.addr of kio_bypass */
+#define XCHAL_KIO_BYPASS_SIZE 0x10000000 /* size in bytes of kio_bypass (assumed power of 2!!!) */
+
+#define XCHAL_SEG_MAPPABLE_VADDR 0x00000000 /* start of largest non-static-mapped virtual addr area */
+#define XCHAL_SEG_MAPPABLE_SIZE 0xD0000000 /* size in bytes of " */
+/* define XCHAL_SEG_MAPPABLE2_xxx if more areas present, sorted in order of descending size. */
+#endif
+
+
+/*----------------------------------------------------------------------
+ MISC
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_NUM_WRITEBUFFER_ENTRIES 4 /* number of write buffer entries */
+
+#define XCHAL_CORE_ID "linux_be" /* configuration's alphanumeric core identifier
+ (CoreID) set in the Xtensa Processor Generator */
+
+#define XCHAL_BUILD_UNIQUE_ID 0x00003256 /* software build-unique ID (22-bit) */
+
+/* These definitions describe the hardware targeted by this software: */
+#define XCHAL_HW_CONFIGID0 0xC103D1FF /* config ID reg 0 value (upper 32 of 64 bits) */
+#define XCHAL_HW_CONFIGID1 0x00803256 /* config ID reg 1 value (lower 32 of 64 bits) */
+#define XCHAL_CONFIGID0 XCHAL_HW_CONFIGID0 /* for backward compatibility only -- don't use! */
+#define XCHAL_CONFIGID1 XCHAL_HW_CONFIGID1 /* for backward compatibility only -- don't use! */
+#define XCHAL_HW_RELEASE_MAJOR 1050 /* major release of targeted hardware */
+#define XCHAL_HW_RELEASE_MINOR 1 /* minor release of targeted hardware */
+#define XCHAL_HW_RELEASE_NAME "T1050.1" /* full release name of targeted hardware */
+#define XTHAL_HW_REL_T1050 1
+#define XTHAL_HW_REL_T1050_1 1
+#define XCHAL_HW_CONFIGID_RELIABLE 1
+
+
+/*
+ * Miscellaneous special register fields:
+ */
+
+
+/* DBREAKC (special register number 160): */
+#define XCHAL_DBREAKC_VALIDMASK 0xC000003F /* bits of DBREAKC that are defined */
+/* MASK field: */
+#define XCHAL_DBREAKC_MASK_BITS 6 /* number of bits in MASK field */
+#define XCHAL_DBREAKC_MASK_NUM 64 /* max number of possible causes (2^bits) */
+#define XCHAL_DBREAKC_MASK_SHIFT 0 /* position of MASK bits in DBREAKC, starting from lsbit */
+#define XCHAL_DBREAKC_MASK_MASK 0x0000003F /* mask of bits in MASK field of DBREAKC */
+/* LOADBREAK field: */
+#define XCHAL_DBREAKC_LOADBREAK_BITS 1 /* number of bits in LOADBREAK field */
+#define XCHAL_DBREAKC_LOADBREAK_NUM 2 /* max number of possible causes (2^bits) */
+#define XCHAL_DBREAKC_LOADBREAK_SHIFT 30 /* position of LOADBREAK bits in DBREAKC, starting from lsbit */
+#define XCHAL_DBREAKC_LOADBREAK_MASK 0x40000000 /* mask of bits in LOADBREAK field of DBREAKC */
+/* STOREBREAK field: */
+#define XCHAL_DBREAKC_STOREBREAK_BITS 1 /* number of bits in STOREBREAK field */
+#define XCHAL_DBREAKC_STOREBREAK_NUM 2 /* max number of possible causes (2^bits) */
+#define XCHAL_DBREAKC_STOREBREAK_SHIFT 31 /* position of STOREBREAK bits in DBREAKC, starting from lsbit */
+#define XCHAL_DBREAKC_STOREBREAK_MASK 0x80000000 /* mask of bits in STOREBREAK field of DBREAKC */
+
+/* PS (special register number 230): */
+#define XCHAL_PS_VALIDMASK 0x00070FFF /* bits of PS that are defined */
+/* INTLEVEL field: */
+#define XCHAL_PS_INTLEVEL_BITS 4 /* number of bits in INTLEVEL field */
+#define XCHAL_PS_INTLEVEL_NUM 16 /* max number of possible causes (2^bits) */
+#define XCHAL_PS_INTLEVEL_SHIFT 0 /* position of INTLEVEL bits in PS, starting from lsbit */
+#define XCHAL_PS_INTLEVEL_MASK 0x0000000F /* mask of bits in INTLEVEL field of PS */
+/* EXCM field: */
+#define XCHAL_PS_EXCM_BITS 1 /* number of bits in EXCM field */
+#define XCHAL_PS_EXCM_NUM 2 /* max number of possible causes (2^bits) */
+#define XCHAL_PS_EXCM_SHIFT 4 /* position of EXCM bits in PS, starting from lsbit */
+#define XCHAL_PS_EXCM_MASK 0x00000010 /* mask of bits in EXCM field of PS */
+/* PROGSTACK field: */
+#define XCHAL_PS_PROGSTACK_BITS 1 /* number of bits in PROGSTACK field */
+#define XCHAL_PS_PROGSTACK_NUM 2 /* max number of possible causes (2^bits) */
+#define XCHAL_PS_PROGSTACK_SHIFT 5 /* position of PROGSTACK bits in PS, starting from lsbit */
+#define XCHAL_PS_PROGSTACK_MASK 0x00000020 /* mask of bits in PROGSTACK field of PS */
+/* RING field: */
+#define XCHAL_PS_RING_BITS 2 /* number of bits in RING field */
+#define XCHAL_PS_RING_NUM 4 /* max number of possible causes (2^bits) */
+#define XCHAL_PS_RING_SHIFT 6 /* position of RING bits in PS, starting from lsbit */
+#define XCHAL_PS_RING_MASK 0x000000C0 /* mask of bits in RING field of PS */
+/* OWB field: */
+#define XCHAL_PS_OWB_BITS 4 /* number of bits in OWB field */
+#define XCHAL_PS_OWB_NUM 16 /* max number of possible causes (2^bits) */
+#define XCHAL_PS_OWB_SHIFT 8 /* position of OWB bits in PS, starting from lsbit */
+#define XCHAL_PS_OWB_MASK 0x00000F00 /* mask of bits in OWB field of PS */
+/* CALLINC field: */
+#define XCHAL_PS_CALLINC_BITS 2 /* number of bits in CALLINC field */
+#define XCHAL_PS_CALLINC_NUM 4 /* max number of possible causes (2^bits) */
+#define XCHAL_PS_CALLINC_SHIFT 16 /* position of CALLINC bits in PS, starting from lsbit */
+#define XCHAL_PS_CALLINC_MASK 0x00030000 /* mask of bits in CALLINC field of PS */
+/* WOE field: */
+#define XCHAL_PS_WOE_BITS 1 /* number of bits in WOE field */
+#define XCHAL_PS_WOE_NUM 2 /* max number of possible causes (2^bits) */
+#define XCHAL_PS_WOE_SHIFT 18 /* position of WOE bits in PS, starting from lsbit */
+#define XCHAL_PS_WOE_MASK 0x00040000 /* mask of bits in WOE field of PS */
+
+/* EXCCAUSE (special register number 232): */
+#define XCHAL_EXCCAUSE_VALIDMASK 0x0000003F /* bits of EXCCAUSE that are defined */
+/* EXCCAUSE field: */
+#define XCHAL_EXCCAUSE_BITS 6 /* number of bits in EXCCAUSE register */
+#define XCHAL_EXCCAUSE_NUM 64 /* max number of possible causes (2^bits) */
+#define XCHAL_EXCCAUSE_SHIFT 0 /* position of EXCCAUSE bits in register, starting from lsbit */
+#define XCHAL_EXCCAUSE_MASK 0x0000003F /* mask of bits in EXCCAUSE register */
+
+/* DEBUGCAUSE (special register number 233): */
+#define XCHAL_DEBUGCAUSE_VALIDMASK 0x0000003F /* bits of DEBUGCAUSE that are defined */
+/* ICOUNT field: */
+#define XCHAL_DEBUGCAUSE_ICOUNT_BITS 1 /* number of bits in ICOUNT field */
+#define XCHAL_DEBUGCAUSE_ICOUNT_NUM 2 /* max number of possible causes (2^bits) */
+#define XCHAL_DEBUGCAUSE_ICOUNT_SHIFT 0 /* position of ICOUNT bits in DEBUGCAUSE, starting from lsbit */
+#define XCHAL_DEBUGCAUSE_ICOUNT_MASK 0x00000001 /* mask of bits in ICOUNT field of DEBUGCAUSE */
+/* IBREAK field: */
+#define XCHAL_DEBUGCAUSE_IBREAK_BITS 1 /* number of bits in IBREAK field */
+#define XCHAL_DEBUGCAUSE_IBREAK_NUM 2 /* max number of possible causes (2^bits) */
+#define XCHAL_DEBUGCAUSE_IBREAK_SHIFT 1 /* position of IBREAK bits in DEBUGCAUSE, starting from lsbit */
+#define XCHAL_DEBUGCAUSE_IBREAK_MASK 0x00000002 /* mask of bits in IBREAK field of DEBUGCAUSE */
+/* DBREAK field: */
+#define XCHAL_DEBUGCAUSE_DBREAK_BITS 1 /* number of bits in DBREAK field */
+#define XCHAL_DEBUGCAUSE_DBREAK_NUM 2 /* max number of possible causes (2^bits) */
+#define XCHAL_DEBUGCAUSE_DBREAK_SHIFT 2 /* position of DBREAK bits in DEBUGCAUSE, starting from lsbit */
+#define XCHAL_DEBUGCAUSE_DBREAK_MASK 0x00000004 /* mask of bits in DBREAK field of DEBUGCAUSE */
+/* BREAK field: */
+#define XCHAL_DEBUGCAUSE_BREAK_BITS 1 /* number of bits in BREAK field */
+#define XCHAL_DEBUGCAUSE_BREAK_NUM 2 /* max number of possible causes (2^bits) */
+#define XCHAL_DEBUGCAUSE_BREAK_SHIFT 3 /* position of BREAK bits in DEBUGCAUSE, starting from lsbit */
+#define XCHAL_DEBUGCAUSE_BREAK_MASK 0x00000008 /* mask of bits in BREAK field of DEBUGCAUSE */
+/* BREAKN field: */
+#define XCHAL_DEBUGCAUSE_BREAKN_BITS 1 /* number of bits in BREAKN field */
+#define XCHAL_DEBUGCAUSE_BREAKN_NUM 2 /* max number of possible causes (2^bits) */
+#define XCHAL_DEBUGCAUSE_BREAKN_SHIFT 4 /* position of BREAKN bits in DEBUGCAUSE, starting from lsbit */
+#define XCHAL_DEBUGCAUSE_BREAKN_MASK 0x00000010 /* mask of bits in BREAKN field of DEBUGCAUSE */
+/* DEBUGINT field: */
+#define XCHAL_DEBUGCAUSE_DEBUGINT_BITS 1 /* number of bits in DEBUGINT field */
+#define XCHAL_DEBUGCAUSE_DEBUGINT_NUM 2 /* max number of possible causes (2^bits) */
+#define XCHAL_DEBUGCAUSE_DEBUGINT_SHIFT 5 /* position of DEBUGINT bits in DEBUGCAUSE, starting from lsbit */
+#define XCHAL_DEBUGCAUSE_DEBUGINT_MASK 0x00000020 /* mask of bits in DEBUGINT field of DEBUGCAUSE */
+
+
+
+/*----------------------------------------------------------------------
+ ISA
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_DENSITY 1 /* 1 if density option configured, 0 otherwise */
+#define XCHAL_HAVE_LOOPS 1 /* 1 if zero-overhead loops option configured, 0 otherwise */
+/* Misc instructions: */
+#define XCHAL_HAVE_NSA 0 /* 1 if NSA/NSAU instructions option configured, 0 otherwise */
+#define XCHAL_HAVE_MINMAX 0 /* 1 if MIN/MAX instructions option configured, 0 otherwise */
+#define XCHAL_HAVE_SEXT 0 /* 1 if sign-extend instruction option configured, 0 otherwise */
+#define XCHAL_HAVE_CLAMPS 0 /* 1 if CLAMPS instruction option configured, 0 otherwise */
+#define XCHAL_HAVE_MAC16 0 /* 1 if MAC16 option configured, 0 otherwise */
+#define XCHAL_HAVE_MUL16 0 /* 1 if 16-bit integer multiply option configured, 0 otherwise */
+/*#define XCHAL_HAVE_POPC 0*/ /* 1 if CRC instruction option configured, 0 otherwise */
+/*#define XCHAL_HAVE_CRC 0*/ /* 1 if POPC instruction option configured, 0 otherwise */
+
+#define XCHAL_HAVE_SPECULATION 0 /* 1 if speculation option configured, 0 otherwise */
+/*#define XCHAL_HAVE_MP_SYNC 0*/ /* 1 if multiprocessor sync. option configured, 0 otherwise */
+#define XCHAL_HAVE_PRID 0 /* 1 if processor ID register configured, 0 otherwise */
+
+#define XCHAL_NUM_MISC_REGS 2 /* number of miscellaneous registers (0..4) */
+
+/* These relate a bit more to TIE: */
+#define XCHAL_HAVE_BOOLEANS 0 /* 1 if booleans option configured, 0 otherwise */
+#define XCHAL_HAVE_MUL32 0 /* 1 if 32-bit integer multiply option configured, 0 otherwise */
+#define XCHAL_HAVE_MUL32_HIGH 0 /* 1 if MUL32 option includes MULUH and MULSH, 0 otherwise */
+#define XCHAL_HAVE_FP 0 /* 1 if floating point option configured, 0 otherwise */
+
+
+/*----------------------------------------------------------------------
+ DERIVED
+ ----------------------------------------------------------------------*/
+
+#if XCHAL_HAVE_BE
+#define XCHAL_INST_ILLN 0xD60F /* 2-byte illegal instruction, msb-first */
+#define XCHAL_INST_ILLN_BYTE0 0xD6 /* 2-byte illegal instruction, 1st byte */
+#define XCHAL_INST_ILLN_BYTE1 0x0F /* 2-byte illegal instruction, 2nd byte */
+#else
+#define XCHAL_INST_ILLN 0xF06D /* 2-byte illegal instruction, lsb-first */
+#define XCHAL_INST_ILLN_BYTE0 0x6D /* 2-byte illegal instruction, 1st byte */
+#define XCHAL_INST_ILLN_BYTE1 0xF0 /* 2-byte illegal instruction, 2nd byte */
+#endif
+/* Belongs in xtensa/hal.h: */
+#define XTHAL_INST_ILL 0x000000 /* 3-byte illegal instruction */
+
+
+/*
+ * Because information as to exactly which hardware release is targeted
+ * by a given software build is not always available, compile-time HAL
+ * Hardware-Release "_AT" macros are fuzzy (return 0, 1, or XCHAL_MAYBE):
+ */
+#ifndef XCHAL_HW_RELEASE_MAJOR
+# define XCHAL_HW_CONFIGID_RELIABLE 0
+#endif
+#if XCHAL_HW_CONFIGID_RELIABLE
+# define XCHAL_HW_RELEASE_AT_OR_BELOW(major,minor) (XTHAL_REL_LE( XCHAL_HW_RELEASE_MAJOR,XCHAL_HW_RELEASE_MINOR, major,minor ) ? 1 : 0)
+# define XCHAL_HW_RELEASE_AT_OR_ABOVE(major,minor) (XTHAL_REL_GE( XCHAL_HW_RELEASE_MAJOR,XCHAL_HW_RELEASE_MINOR, major,minor ) ? 1 : 0)
+# define XCHAL_HW_RELEASE_AT(major,minor) (XTHAL_REL_EQ( XCHAL_HW_RELEASE_MAJOR,XCHAL_HW_RELEASE_MINOR, major,minor ) ? 1 : 0)
+# define XCHAL_HW_RELEASE_MAJOR_AT(major) ((XCHAL_HW_RELEASE_MAJOR == (major)) ? 1 : 0)
+#else
+# define XCHAL_HW_RELEASE_AT_OR_BELOW(major,minor) ( ((major) < 1040 && XCHAL_HAVE_XEA2) ? 0 \
+ : ((major) > 1050 && XCHAL_HAVE_XEA1) ? 1 \
+ : XTHAL_MAYBE )
+# define XCHAL_HW_RELEASE_AT_OR_ABOVE(major,minor) ( ((major) >= 2000 && XCHAL_HAVE_XEA1) ? 0 \
+ : (XTHAL_REL_LE(major,minor, 1040,0) && XCHAL_HAVE_XEA2) ? 1 \
+ : XTHAL_MAYBE )
+# define XCHAL_HW_RELEASE_AT(major,minor) ( (((major) < 1040 && XCHAL_HAVE_XEA2) || \
+ ((major) >= 2000 && XCHAL_HAVE_XEA1)) ? 0 : XTHAL_MAYBE)
+# define XCHAL_HW_RELEASE_MAJOR_AT(major) XCHAL_HW_RELEASE_AT(major,0)
+#endif
+
+/*
+ * Specific errata:
+ */
+
+/*
+ * Erratum T1020.H13, T1030.H7, T1040.H10, T1050.H4 (fixed in T1040.3 and T1050.1;
+ * relevant only in XEA1, kernel-vector mode, level-one interrupts and overflows enabled):
+ */
+#define XCHAL_MAYHAVE_ERRATUM_XEA1KWIN (XCHAL_HAVE_XEA1 && \
+ (XCHAL_HW_RELEASE_AT_OR_BELOW(1040,2) != 0 \
+ || XCHAL_HW_RELEASE_AT(1050,0)))
+
+
+
+#endif /*XTENSA_CONFIG_CORE_H*/
+
diff --git a/include/asm-xtensa/xtensa/config-linux_be/defs.h b/include/asm-xtensa/xtensa/config-linux_be/defs.h
new file mode 100644
index 00000000000..f7c58b27337
--- /dev/null
+++ b/include/asm-xtensa/xtensa/config-linux_be/defs.h
@@ -0,0 +1,270 @@
+/* Definitions for Xtensa instructions, types, and protos. */
+
+/*
+ * Copyright (c) 2003 Tensilica, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
+ * USA.
+ */
+
+/* Do not modify. This is automatically generated.*/
+
+#ifndef _XTENSA_BASE_HEADER
+#define _XTENSA_BASE_HEADER
+
+#ifdef __XTENSA__
+#if defined(__GNUC__) && !defined(__XCC__)
+
+#define L8UI_ASM(arr, ars, imm) { \
+ __asm__ volatile("l8ui %0, %1, %2" : "=a" (arr) : "a" (ars) , "i" (imm)); \
+}
+
+#define XT_L8UI(ars, imm) \
+({ \
+ unsigned char _arr; \
+ const unsigned char *_ars = ars; \
+ L8UI_ASM(_arr, _ars, imm); \
+ _arr; \
+})
+
+#define L16UI_ASM(arr, ars, imm) { \
+ __asm__ volatile("l16ui %0, %1, %2" : "=a" (arr) : "a" (ars) , "i" (imm)); \
+}
+
+#define XT_L16UI(ars, imm) \
+({ \
+ unsigned short _arr; \
+ const unsigned short *_ars = ars; \
+ L16UI_ASM(_arr, _ars, imm); \
+ _arr; \
+})
+
+#define L16SI_ASM(arr, ars, imm) {\
+ __asm__ volatile("l16si %0, %1, %2" : "=a" (arr) : "a" (ars) , "i" (imm)); \
+}
+
+#define XT_L16SI(ars, imm) \
+({ \
+ signed short _arr; \
+ const signed short *_ars = ars; \
+ L16SI_ASM(_arr, _ars, imm); \
+ _arr; \
+})
+
+#define L32I_ASM(arr, ars, imm) { \
+ __asm__ volatile("l32i %0, %1, %2" : "=a" (arr) : "a" (ars) , "i" (imm)); \
+}
+
+#define XT_L32I(ars, imm) \
+({ \
+ unsigned _arr; \
+ const unsigned *_ars = ars; \
+ L32I_ASM(_arr, _ars, imm); \
+ _arr; \
+})
+
+#define S8I_ASM(arr, ars, imm) {\
+ __asm__ volatile("s8i %0, %1, %2" : : "a" (arr), "a" (ars) , "i" (imm) : "memory" ); \
+}
+
+#define XT_S8I(arr, ars, imm) \
+({ \
+ signed char _arr = arr; \
+ const signed char *_ars = ars; \
+ S8I_ASM(_arr, _ars, imm); \
+})
+
+#define S16I_ASM(arr, ars, imm) {\
+ __asm__ volatile("s16i %0, %1, %2" : : "a" (arr), "a" (ars) , "i" (imm) : "memory" ); \
+}
+
+#define XT_S16I(arr, ars, imm) \
+({ \
+ signed short _arr = arr; \
+ const signed short *_ars = ars; \
+ S16I_ASM(_arr, _ars, imm); \
+})
+
+#define S32I_ASM(arr, ars, imm) { \
+ __asm__ volatile("s32i %0, %1, %2" : : "a" (arr), "a" (ars) , "i" (imm) : "memory" ); \
+}
+
+#define XT_S32I(arr, ars, imm) \
+({ \
+ signed int _arr = arr; \
+ const signed int *_ars = ars; \
+ S32I_ASM(_arr, _ars, imm); \
+})
+
+#define ADDI_ASM(art, ars, imm) {\
+ __asm__ ("addi %0, %1, %2" : "=a" (art) : "a" (ars), "i" (imm)); \
+}
+
+#define XT_ADDI(ars, imm) \
+({ \
+ unsigned _art; \
+ unsigned _ars = ars; \
+ ADDI_ASM(_art, _ars, imm); \
+ _art; \
+})
+
+#define ABS_ASM(arr, art) {\
+ __asm__ ("abs %0, %1" : "=a" (arr) : "a" (art)); \
+}
+
+#define XT_ABS(art) \
+({ \
+ unsigned _arr; \
+ signed _art = art; \
+ ABS_ASM(_arr, _art); \
+ _arr; \
+})
+
+/* Note: In the following macros that reference SAR, the magic "state"
+ register is used to capture the dependency on SAR. This is because
+ SAR is a 5-bit register and thus there are no C types that can be
+ used to represent it. It doesn't appear that the SAR register is
+ even relevant to GCC, but it is marked as "clobbered" just in
+ case. */
+
+#define SRC_ASM(arr, ars, art) {\
+ register int _xt_sar __asm__ ("state"); \
+ __asm__ ("src %0, %1, %2" \
+ : "=a" (arr) : "a" (ars), "a" (art), "t" (_xt_sar)); \
+}
+
+#define XT_SRC(ars, art) \
+({ \
+ unsigned _arr; \
+ unsigned _ars = ars; \
+ unsigned _art = art; \
+ SRC_ASM(_arr, _ars, _art); \
+ _arr; \
+})
+
+#define SSR_ASM(ars) {\
+ register int _xt_sar __asm__ ("state"); \
+ __asm__ ("ssr %1" : "=t" (_xt_sar) : "a" (ars) : "sar"); \
+}
+
+#define XT_SSR(ars) \
+({ \
+ unsigned _ars = ars; \
+ SSR_ASM(_ars); \
+})
+
+#define SSL_ASM(ars) {\
+ register int _xt_sar __asm__ ("state"); \
+ __asm__ ("ssl %1" : "=t" (_xt_sar) : "a" (ars) : "sar"); \
+}
+
+#define XT_SSL(ars) \
+({ \
+ unsigned _ars = ars; \
+ SSL_ASM(_ars); \
+})
+
+#define SSA8B_ASM(ars) {\
+ register int _xt_sar __asm__ ("state"); \
+ __asm__ ("ssa8b %1" : "=t" (_xt_sar) : "a" (ars) : "sar"); \
+}
+
+#define XT_SSA8B(ars) \
+({ \
+ unsigned _ars = ars; \
+ SSA8B_ASM(_ars); \
+})
+
+#define SSA8L_ASM(ars) {\
+ register int _xt_sar __asm__ ("state"); \
+ __asm__ ("ssa8l %1" : "=t" (_xt_sar) : "a" (ars) : "sar"); \
+}
+
+#define XT_SSA8L(ars) \
+({ \
+ unsigned _ars = ars; \
+ SSA8L_ASM(_ars); \
+})
+
+#define SSAI_ASM(imm) {\
+ register int _xt_sar __asm__ ("state"); \
+ __asm__ ("ssai %1" : "=t" (_xt_sar) : "i" (imm) : "sar"); \
+}
+
+#define XT_SSAI(imm) \
+({ \
+ SSAI_ASM(imm); \
+})
+
+
+
+
+
+
+
+
+#endif /* __GNUC__ && !__XCC__ */
+
+#ifdef __XCC__
+
+/* Core load/store instructions */
+extern unsigned char _TIE_L8UI(const unsigned char * ars, immediate imm);
+extern unsigned short _TIE_L16UI(const unsigned short * ars, immediate imm);
+extern signed short _TIE_L16SI(const signed short * ars, immediate imm);
+extern unsigned _TIE_L32I(const unsigned * ars, immediate imm);
+extern void _TIE_S8I(unsigned char arr, unsigned char * ars, immediate imm);
+extern void _TIE_S16I(unsigned short arr, unsigned short * ars, immediate imm);
+extern void _TIE_S32I(unsigned arr, unsigned * ars, immediate imm);
+
+#define XT_L8UI _TIE_L8UI
+#define XT_L16UI _TIE_L16UI
+#define XT_L16SI _TIE_L16SI
+#define XT_L32I _TIE_L32I
+#define XT_S8I _TIE_S8I
+#define XT_S16I _TIE_S16I
+#define XT_S32I _TIE_S32I
+
+/* Add-immediate instruction */
+extern unsigned _TIE_ADDI(unsigned ars, immediate imm);
+#define XT_ADDI _TIE_ADDI
+
+/* Absolute value instruction */
+extern unsigned _TIE_ABS(int art);
+#define XT_ABS _TIE_ABS
+
+/* funnel shift instructions */
+extern unsigned _TIE_SRC(unsigned ars, unsigned art);
+#define XT_SRC _TIE_SRC
+extern void _TIE_SSR(unsigned ars);
+#define XT_SSR _TIE_SSR
+extern void _TIE_SSL(unsigned ars);
+#define XT_SSL _TIE_SSL
+extern void _TIE_SSA8B(unsigned ars);
+#define XT_SSA8B _TIE_SSA8B
+extern void _TIE_SSA8L(unsigned ars);
+#define XT_SSA8L _TIE_SSA8L
+extern void _TIE_SSAI(immediate imm);
+#define XT_SSAI _TIE_SSAI
+
+
+#endif /* __XCC__ */
+
+#endif /* __XTENSA__ */
+#endif /* !_XTENSA_BASE_HEADER */
diff --git a/include/asm-xtensa/xtensa/config-linux_be/specreg.h b/include/asm-xtensa/xtensa/config-linux_be/specreg.h
new file mode 100644
index 00000000000..fa4106aa9a0
--- /dev/null
+++ b/include/asm-xtensa/xtensa/config-linux_be/specreg.h
@@ -0,0 +1,99 @@
+/*
+ * Xtensa Special Register symbolic names
+ */
+
+/* $Id: specreg.h,v 1.2 2003/03/07 19:15:18 joetaylor Exp $ */
+
+/*
+ * Copyright (c) 2003 Tensilica, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
+ * USA.
+ */
+
+#ifndef XTENSA_SPECREG_H
+#define XTENSA_SPECREG_H
+
+/* Include these special register bitfield definitions, for historical reasons: */
+#include <xtensa/corebits.h>
+
+
+/* Special registers: */
+#define LBEG 0
+#define LEND 1
+#define LCOUNT 2
+#define SAR 3
+#define WINDOWBASE 72
+#define WINDOWSTART 73
+#define PTEVADDR 83
+#define RASID 90
+#define ITLBCFG 91
+#define DTLBCFG 92
+#define IBREAKENABLE 96
+#define DDR 104
+#define IBREAKA_0 128
+#define IBREAKA_1 129
+#define DBREAKA_0 144
+#define DBREAKA_1 145
+#define DBREAKC_0 160
+#define DBREAKC_1 161
+#define EPC_1 177
+#define EPC_2 178
+#define EPC_3 179
+#define EPC_4 180
+#define DEPC 192
+#define EPS_2 194
+#define EPS_3 195
+#define EPS_4 196
+#define EXCSAVE_1 209
+#define EXCSAVE_2 210
+#define EXCSAVE_3 211
+#define EXCSAVE_4 212
+#define INTERRUPT 226
+#define INTENABLE 228
+#define PS 230
+#define EXCCAUSE 232
+#define DEBUGCAUSE 233
+#define CCOUNT 234
+#define ICOUNT 236
+#define ICOUNTLEVEL 237
+#define EXCVADDR 238
+#define CCOMPARE_0 240
+#define CCOMPARE_1 241
+#define CCOMPARE_2 242
+#define MISC_REG_0 244
+#define MISC_REG_1 245
+
+/* Special cases (bases of special register series): */
+#define IBREAKA 128
+#define DBREAKA 144
+#define DBREAKC 160
+#define EPC 176
+#define EPS 192
+#define EXCSAVE 208
+#define CCOMPARE 240
+
+/* Special names for read-only and write-only interrupt registers: */
+#define INTREAD 226
+#define INTSET 226
+#define INTCLEAR 227
+
+#endif /* XTENSA_SPECREG_H */
+
diff --git a/include/asm-xtensa/xtensa/config-linux_be/system.h b/include/asm-xtensa/xtensa/config-linux_be/system.h
new file mode 100644
index 00000000000..cf9d4d308e3
--- /dev/null
+++ b/include/asm-xtensa/xtensa/config-linux_be/system.h
@@ -0,0 +1,198 @@
+/*
+ * xtensa/config/system.h -- HAL definitions that are dependent on SYSTEM configuration
+ *
+ * NOTE: The location and contents of this file are highly subject to change.
+ *
+ * Source for configuration-independent binaries (which link in a
+ * configuration-specific HAL library) must NEVER include this file.
+ * The HAL itself has historically included this file in some instances,
+ * but this is not appropriate either, because the HAL is meant to be
+ * core-specific but system independent.
+ */
+
+/*
+ * Copyright (c) 2003 Tensilica, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
+ * USA.
+ */
+
+
+#ifndef XTENSA_CONFIG_SYSTEM_H
+#define XTENSA_CONFIG_SYSTEM_H
+
+/*#include <xtensa/hal.h>*/
+
+
+
+/*----------------------------------------------------------------------
+ DEVICE ADDRESSES
+ ----------------------------------------------------------------------*/
+
+/*
+ * Strange place to find these, but the configuration GUI
+ * allows moving these around to account for various core
+ * configurations. Specific boards (and their BSP software)
+ * will have specific meanings for these components.
+ */
+
+/* I/O Block areas: */
+#define XSHAL_IOBLOCK_CACHED_VADDR 0xE0000000
+#define XSHAL_IOBLOCK_CACHED_PADDR 0xF0000000
+#define XSHAL_IOBLOCK_CACHED_SIZE 0x0E000000
+
+#define XSHAL_IOBLOCK_BYPASS_VADDR 0xF0000000
+#define XSHAL_IOBLOCK_BYPASS_PADDR 0xF0000000
+#define XSHAL_IOBLOCK_BYPASS_SIZE 0x0E000000
+
+/* System ROM: */
+#define XSHAL_ROM_VADDR 0xEE000000
+#define XSHAL_ROM_PADDR 0xFE000000
+#define XSHAL_ROM_SIZE 0x00400000
+/* Largest available area (free of vectors): */
+#define XSHAL_ROM_AVAIL_VADDR 0xEE00052C
+#define XSHAL_ROM_AVAIL_VSIZE 0x003FFAD4
+
+/* System RAM: */
+#define XSHAL_RAM_VADDR 0xD0000000
+#define XSHAL_RAM_PADDR 0x00000000
+#define XSHAL_RAM_VSIZE 0x08000000
+#define XSHAL_RAM_PSIZE 0x10000000
+#define XSHAL_RAM_SIZE XSHAL_RAM_PSIZE
+/* Largest available area (free of vectors): */
+#define XSHAL_RAM_AVAIL_VADDR 0xD0000370
+#define XSHAL_RAM_AVAIL_VSIZE 0x07FFFC90
+
+/*
+ * Shadow system RAM (same device as system RAM, at different address).
+ * (Emulation boards need this for the SONIC Ethernet driver
+ * when data caches are configured for writeback mode.)
+ * NOTE: on full MMU configs, this points to the BYPASS virtual address
+ * of system RAM, ie. is the same as XSHAL_RAM_* except that virtual
+ * addresses are viewed through the BYPASS static map rather than
+ * the CACHED static map.
+ */
+#define XSHAL_RAM_BYPASS_VADDR 0xD8000000
+#define XSHAL_RAM_BYPASS_PADDR 0x00000000
+#define XSHAL_RAM_BYPASS_PSIZE 0x08000000
+
+/* Alternate system RAM (different device than system RAM): */
+#define XSHAL_ALTRAM_VADDR 0xCEE00000
+#define XSHAL_ALTRAM_PADDR 0xC0000000
+#define XSHAL_ALTRAM_SIZE 0x00200000
+
+
+/*----------------------------------------------------------------------
+ * DEVICE-ADDRESS DEPENDENT...
+ *
+ * Values written to CACHEATTR special register (or its equivalent)
+ * to enable and disable caches in various modes.
+ *----------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------
+ BACKWARD COMPATIBILITY ...
+ ----------------------------------------------------------------------*/
+
+/*
+ * NOTE: the following two macros are DEPRECATED. Use the latter
+ * board-specific macros instead, which are specially tuned for the
+ * particular target environments' memory maps.
+ */
+#define XSHAL_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS /* disable caches in bypass mode */
+#define XSHAL_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT /* default setting to enable caches (no writeback!) */
+
+/*----------------------------------------------------------------------
+ ISS (Instruction Set Simulator) SPECIFIC ...
+ ----------------------------------------------------------------------*/
+
+#define XSHAL_ISS_CACHEATTR_WRITEBACK 0x1122222F /* enable caches in write-back mode */
+#define XSHAL_ISS_CACHEATTR_WRITEALLOC 0x1122222F /* enable caches in write-allocate mode */
+#define XSHAL_ISS_CACHEATTR_WRITETHRU 0x1122222F /* enable caches in write-through mode */
+#define XSHAL_ISS_CACHEATTR_BYPASS 0x2222222F /* disable caches in bypass mode */
+#define XSHAL_ISS_CACHEATTR_DEFAULT XSHAL_ISS_CACHEATTR_WRITEBACK /* default setting to enable caches */
+
+/* For Coware only: */
+#define XSHAL_COWARE_CACHEATTR_WRITEBACK 0x11222222 /* enable caches in write-back mode */
+#define XSHAL_COWARE_CACHEATTR_WRITEALLOC 0x11222222 /* enable caches in write-allocate mode */
+#define XSHAL_COWARE_CACHEATTR_WRITETHRU 0x11222222 /* enable caches in write-through mode */
+#define XSHAL_COWARE_CACHEATTR_BYPASS 0x22222222 /* disable caches in bypass mode */
+#define XSHAL_COWARE_CACHEATTR_DEFAULT XSHAL_COWARE_CACHEATTR_WRITEBACK /* default setting to enable caches */
+
+/* For BFM and other purposes: */
+#define XSHAL_ALLVALID_CACHEATTR_WRITEBACK 0x11222222 /* enable caches without any invalid regions */
+#define XSHAL_ALLVALID_CACHEATTR_DEFAULT XSHAL_ALLVALID_CACHEATTR_WRITEBACK /* default setting for caches without any invalid regions */
+
+#define XSHAL_ISS_PIPE_REGIONS 0
+#define XSHAL_ISS_SDRAM_REGIONS 0
+
+
+/*----------------------------------------------------------------------
+ XT2000 BOARD SPECIFIC ...
+ ----------------------------------------------------------------------*/
+
+#define XSHAL_XT2000_CACHEATTR_WRITEBACK 0x22FFFFFF /* enable caches in write-back mode */
+#define XSHAL_XT2000_CACHEATTR_WRITEALLOC 0x22FFFFFF /* enable caches in write-allocate mode */
+#define XSHAL_XT2000_CACHEATTR_WRITETHRU 0x22FFFFFF /* enable caches in write-through mode */
+#define XSHAL_XT2000_CACHEATTR_BYPASS 0x22FFFFFF /* disable caches in bypass mode */
+#define XSHAL_XT2000_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_WRITEBACK /* default setting to enable caches */
+
+#define XSHAL_XT2000_PIPE_REGIONS 0x00001000 /* BusInt pipeline regions */
+#define XSHAL_XT2000_SDRAM_REGIONS 0x00000005 /* BusInt SDRAM regions */
+
+
+/*----------------------------------------------------------------------
+ VECTOR SIZES
+ ----------------------------------------------------------------------*/
+
+/*
+ * Sizes allocated to vectors by the system (memory map) configuration.
+ * These sizes are constrained by core configuration (eg. one vector's
+ * code cannot overflow into another vector) but are dependent on the
+ * system or board (or LSP) memory map configuration.
+ *
+ * Whether or not each vector happens to be in a system ROM is also
+ * a system configuration matter, sometimes useful, included here also:
+ */
+#define XSHAL_RESET_VECTOR_SIZE 0x000004E0
+#define XSHAL_RESET_VECTOR_ISROM 1
+#define XSHAL_USER_VECTOR_SIZE 0x0000001C
+#define XSHAL_USER_VECTOR_ISROM 0
+#define XSHAL_PROGRAMEXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */
+#define XSHAL_USEREXC_VECTOR_SIZE XSHAL_USER_VECTOR_SIZE /* for backward compatibility */
+#define XSHAL_KERNEL_VECTOR_SIZE 0x0000001C
+#define XSHAL_KERNEL_VECTOR_ISROM 0
+#define XSHAL_STACKEDEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */
+#define XSHAL_KERNELEXC_VECTOR_SIZE XSHAL_KERNEL_VECTOR_SIZE /* for backward compatibility */
+#define XSHAL_DOUBLEEXC_VECTOR_SIZE 0x000000E0
+#define XSHAL_DOUBLEEXC_VECTOR_ISROM 0
+#define XSHAL_WINDOW_VECTORS_SIZE 0x00000180
+#define XSHAL_WINDOW_VECTORS_ISROM 0
+#define XSHAL_INTLEVEL2_VECTOR_SIZE 0x0000000C
+#define XSHAL_INTLEVEL2_VECTOR_ISROM 0
+#define XSHAL_INTLEVEL3_VECTOR_SIZE 0x0000000C
+#define XSHAL_INTLEVEL3_VECTOR_ISROM 0
+#define XSHAL_INTLEVEL4_VECTOR_SIZE 0x0000000C
+#define XSHAL_INTLEVEL4_VECTOR_ISROM 1
+#define XSHAL_DEBUG_VECTOR_SIZE XSHAL_INTLEVEL4_VECTOR_SIZE
+#define XSHAL_DEBUG_VECTOR_ISROM XSHAL_INTLEVEL4_VECTOR_ISROM
+
+
+#endif /*XTENSA_CONFIG_SYSTEM_H*/
+
diff --git a/include/asm-xtensa/xtensa/config-linux_be/tie.h b/include/asm-xtensa/xtensa/config-linux_be/tie.h
new file mode 100644
index 00000000000..3c2e514602f
--- /dev/null
+++ b/include/asm-xtensa/xtensa/config-linux_be/tie.h
@@ -0,0 +1,275 @@
+/*
+ * xtensa/config/tie.h -- HAL definitions that are dependent on CORE and TIE configuration
+ *
+ * This header file is sometimes referred to as the "compile-time HAL" or CHAL.
+ * It was generated for a specific Xtensa processor configuration,
+ * and furthermore for a specific set of TIE source files that extend
+ * basic core functionality.
+ *
+ * Source for configuration-independent binaries (which link in a
+ * configuration-specific HAL library) must NEVER include this file.
+ * It is perfectly normal, however, for the HAL source itself to include this file.
+ */
+
+/*
+ * Copyright (c) 2003 Tensilica, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
+ * USA.
+ */
+
+
+#ifndef XTENSA_CONFIG_TIE_H
+#define XTENSA_CONFIG_TIE_H
+
+#include <xtensa/hal.h>
+
+
+/*----------------------------------------------------------------------
+ GENERAL
+ ----------------------------------------------------------------------*/
+
+/*
+ * Separators for macros that expand into arrays.
+ * These can be predefined by files that #include this one,
+ * when different separators are required.
+ */
+/* Element separator for macros that expand into 1-dimensional arrays: */
+#ifndef XCHAL_SEP
+#define XCHAL_SEP ,
+#endif
+/* Array separator for macros that expand into 2-dimensional arrays: */
+#ifndef XCHAL_SEP2
+#define XCHAL_SEP2 },{
+#endif
+
+
+
+
+
+
+/*----------------------------------------------------------------------
+ COPROCESSORS and EXTRA STATE
+ ----------------------------------------------------------------------*/
+
+#define XCHAL_CP_NUM 0 /* number of coprocessors */
+#define XCHAL_CP_MAX 0 /* max coprocessor id plus one (0 if none) */
+#define XCHAL_CP_MASK 0x00 /* bitmask of coprocessors by id */
+
+/* Space for coprocessors' state save areas: */
+#define XCHAL_CP0_SA_SIZE 0
+#define XCHAL_CP1_SA_SIZE 0
+#define XCHAL_CP2_SA_SIZE 0
+#define XCHAL_CP3_SA_SIZE 0
+#define XCHAL_CP4_SA_SIZE 0
+#define XCHAL_CP5_SA_SIZE 0
+#define XCHAL_CP6_SA_SIZE 0
+#define XCHAL_CP7_SA_SIZE 0
+/* Minimum required alignments of CP state save areas: */
+#define XCHAL_CP0_SA_ALIGN 1
+#define XCHAL_CP1_SA_ALIGN 1
+#define XCHAL_CP2_SA_ALIGN 1
+#define XCHAL_CP3_SA_ALIGN 1
+#define XCHAL_CP4_SA_ALIGN 1
+#define XCHAL_CP5_SA_ALIGN 1
+#define XCHAL_CP6_SA_ALIGN 1
+#define XCHAL_CP7_SA_ALIGN 1
+
+/* Indexing macros: */
+#define _XCHAL_CP_SA_SIZE(n) XCHAL_CP ## n ## _SA_SIZE
+#define XCHAL_CP_SA_SIZE(n) _XCHAL_CP_SA_SIZE(n) /* n = 0 .. 7 */
+#define _XCHAL_CP_SA_ALIGN(n) XCHAL_CP ## n ## _SA_ALIGN
+#define XCHAL_CP_SA_ALIGN(n) _XCHAL_CP_SA_ALIGN(n) /* n = 0 .. 7 */
+
+
+/* Space for "extra" state (user special registers and non-cp TIE) save area: */
+#define XCHAL_EXTRA_SA_SIZE 0
+#define XCHAL_EXTRA_SA_ALIGN 1
+
+/* Total save area size (extra + all coprocessors) */
+/* (not useful until xthal_{save,restore}_all_extra() is implemented, */
+/* but included for Tor2 beta; doesn't account for alignment!): */
+#define XCHAL_CPEXTRA_SA_SIZE_TOR2 0 /* Tor2Beta temporary definition -- do not use */
+
+/* Combined required alignment for all CP and EXTRA state save areas */
+/* (does not include required alignment for any base config registers): */
+#define XCHAL_CPEXTRA_SA_ALIGN 1
+
+/* ... */
+
+
+#ifdef _ASMLANGUAGE
+/*
+ * Assembly-language specific definitions (assembly macros, etc.).
+ */
+#include <xtensa/config/specreg.h>
+
+/********************
+ * Macros to save and restore the non-coprocessor TIE portion of EXTRA state.
+ */
+
+/* (none) */
+
+
+/********************
+ * Macros to create functions that save and restore all EXTRA (non-coprocessor) state
+ * (does not include zero-overhead loop registers and non-optional registers).
+ */
+
+ /*
+ * Macro that expands to the body of a function that
+ * stores the extra (non-coprocessor) optional/custom state.
+ * Entry: a2 = ptr to save area in which to save extra state
+ * Exit: any register a2-a15 (?) may have been clobbered.
+ */
+ .macro xchal_extra_store_funcbody
+ .endm
+
+
+ /*
+ * Macro that expands to the body of a function that
+ * loads the extra (non-coprocessor) optional/custom state.
+ * Entry: a2 = ptr to save area from which to restore extra state
+ * Exit: any register a2-a15 (?) may have been clobbered.
+ */
+ .macro xchal_extra_load_funcbody
+ .endm
+
+
+/********************
+ * Macros to save and restore the state of each TIE coprocessor.
+ */
+
+
+
+/********************
+ * Macros to create functions that save and restore the state of *any* TIE coprocessor.
+ */
+
+ /*
+ * Macro that expands to the body of a function
+ * that stores the selected coprocessor's state (registers etc).
+ * Entry: a2 = ptr to save area in which to save cp state
+ * a3 = coprocessor number
+ * Exit: any register a2-a15 (?) may have been clobbered.
+ */
+ .macro xchal_cpi_store_funcbody
+ .endm
+
+
+ /*
+ * Macro that expands to the body of a function
+ * that loads the selected coprocessor's state (registers etc).
+ * Entry: a2 = ptr to save area from which to restore cp state
+ * a3 = coprocessor number
+ * Exit: any register a2-a15 (?) may have been clobbered.
+ */
+ .macro xchal_cpi_load_funcbody
+ .endm
+
+#endif /*_ASMLANGUAGE*/
+
+
+/*
+ * Contents of save areas in terms of libdb register numbers.
+ * NOTE: CONTENTS_LIBDB_{UREG,REGF} macros are not defined in this file;
+ * it is up to the user of this header file to define these macros
+ * usefully before each expansion of the CONTENTS_LIBDB macros.
+ * (Fields rsv[123] are reserved for future additions; they are currently
+ * set to zero but may be set to some useful values in the future.)
+ *
+ * CONTENTS_LIBDB_SREG(libdbnum, offset, size, align, rsv1, name, sregnum, bitmask, rsv2, rsv3)
+ * CONTENTS_LIBDB_UREG(libdbnum, offset, size, align, rsv1, name, uregnum, bitmask, rsv2, rsv3)
+ * CONTENTS_LIBDB_REGF(libdbnum, offset, size, align, rsv1, name, index, numentries, contentsize, regname_base, regfile_name, rsv2, rsv3)
+ */
+
+#define XCHAL_EXTRA_SA_CONTENTS_LIBDB_NUM 0
+#define XCHAL_EXTRA_SA_CONTENTS_LIBDB /* empty */
+
+#define XCHAL_CP0_SA_CONTENTS_LIBDB_NUM 0
+#define XCHAL_CP0_SA_CONTENTS_LIBDB /* empty */
+
+#define XCHAL_CP1_SA_CONTENTS_LIBDB_NUM 0
+#define XCHAL_CP1_SA_CONTENTS_LIBDB /* empty */
+
+#define XCHAL_CP2_SA_CONTENTS_LIBDB_NUM 0
+#define XCHAL_CP2_SA_CONTENTS_LIBDB /* empty */
+
+#define XCHAL_CP3_SA_CONTENTS_LIBDB_NUM 0
+#define XCHAL_CP3_SA_CONTENTS_LIBDB /* empty */
+
+#define XCHAL_CP4_SA_CONTENTS_LIBDB_NUM 0
+#define XCHAL_CP4_SA_CONTENTS_LIBDB /* empty */
+
+#define XCHAL_CP5_SA_CONTENTS_LIBDB_NUM 0
+#define XCHAL_CP5_SA_CONTENTS_LIBDB /* empty */
+
+#define XCHAL_CP6_SA_CONTENTS_LIBDB_NUM 0
+#define XCHAL_CP6_SA_CONTENTS_LIBDB /* empty */
+
+#define XCHAL_CP7_SA_CONTENTS_LIBDB_NUM 0
+#define XCHAL_CP7_SA_CONTENTS_LIBDB /* empty */
+
+
+
+
+
+
+/*----------------------------------------------------------------------
+ MISC
+ ----------------------------------------------------------------------*/
+
+#if 0 /* is there something equivalent for user TIE? */
+#define XCHAL_CORE_ID "linux_be" /* configuration's alphanumeric core identifier
+ (CoreID) set in the Xtensa Processor Generator */
+
+#define XCHAL_BUILD_UNIQUE_ID 0x00003256 /* software build-unique ID (22-bit) */
+
+/* These definitions describe the hardware targeted by this software: */
+#define XCHAL_HW_CONFIGID0 0xC103D1FF /* config ID reg 0 value (upper 32 of 64 bits) */
+#define XCHAL_HW_CONFIGID1 0x00803256 /* config ID reg 1 value (lower 32 of 64 bits) */
+#define XCHAL_CONFIGID0 XCHAL_HW_CONFIGID0 /* for backward compatibility only -- don't use! */
+#define XCHAL_CONFIGID1 XCHAL_HW_CONFIGID1 /* for backward compatibility only -- don't use! */
+#define XCHAL_HW_RELEASE_MAJOR 1050 /* major release of targeted hardware */
+#define XCHAL_HW_RELEASE_MINOR 1 /* minor release of targeted hardware */
+#define XCHAL_HW_RELEASE_NAME "T1050.1" /* full release name of targeted hardware */
+#define XTHAL_HW_REL_T1050 1
+#define XTHAL_HW_REL_T1050_1 1
+#define XCHAL_HW_CONFIGID_RELIABLE 1
+#endif /*0*/
+
+
+
+/*----------------------------------------------------------------------
+ ISA
+ ----------------------------------------------------------------------*/
+
+#if 0 /* these probably don't belong here, but are related to or implemented using TIE */
+#define XCHAL_HAVE_BOOLEANS 0 /* 1 if booleans option configured, 0 otherwise */
+/* Misc instructions: */
+#define XCHAL_HAVE_MUL32 0 /* 1 if 32-bit integer multiply option configured, 0 otherwise */
+#define XCHAL_HAVE_MUL32_HIGH 0 /* 1 if MUL32 option includes MULUH and MULSH, 0 otherwise */
+
+#define XCHAL_HAVE_FP 0 /* 1 if floating point option configured, 0 otherwise */
+#endif /*0*/
+
+
+#endif /*XTENSA_CONFIG_TIE_H*/
+
diff --git a/include/asm-xtensa/xtensa/coreasm.h b/include/asm-xtensa/xtensa/coreasm.h
new file mode 100644
index 00000000000..a8cfb54c20a
--- /dev/null
+++ b/include/asm-xtensa/xtensa/coreasm.h
@@ -0,0 +1,526 @@
+#ifndef XTENSA_COREASM_H
+#define XTENSA_COREASM_H
+
+/*
+ * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
+ *
+ * include/asm-xtensa/xtensa/coreasm.h -- assembler-specific
+ * definitions that depend on CORE configuration.
+ *
+ * Source for configuration-independent binaries (which link in a
+ * configuration-specific HAL library) must NEVER include this file.
+ * It is perfectly normal, however, for the HAL itself to include this
+ * file.
+ *
+ * This file must NOT include xtensa/config/system.h. Any assembler
+ * header file that depends on system information should likely go in
+ * a new systemasm.h (or sysasm.h) header file.
+ *
+ * NOTE: macro beqi32 is NOT configuration-dependent, and is placed
+ * here til we will have configuration-independent header file.
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ *
+ * Copyright (C) 2002 Tensilica Inc.
+ */
+
+
+#include <xtensa/config/core.h>
+#include <xtensa/config/specreg.h>
+
+/*
+ * Assembly-language specific definitions (assembly macros, etc.).
+ */
+
+/*----------------------------------------------------------------------
+ * find_ms_setbit
+ *
+ * This macro finds the most significant bit that is set in <as>
+ * and return its index + <base> in <ad>, or <base> - 1 if <as> is zero.
+ * The index counts starting at zero for the lsbit, so the return
+ * value ranges from <base>-1 (no bit set) to <base>+31 (msbit set).
+ *
+ * Parameters:
+ * <ad> destination address register (any register)
+ * <as> source address register
+ * <at> temporary address register (must be different than <as>)
+ * <base> constant value added to result (usually 0 or 1)
+ * On entry:
+ * <ad> = undefined if different than <as>
+ * <as> = value whose most significant set bit is to be found
+ * <at> = undefined
+ * no other registers are used by this macro.
+ * On exit:
+ * <ad> = <base> + index of msbit set in original <as>,
+ * = <base> - 1 if original <as> was zero.
+ * <as> clobbered (if not <ad>)
+ * <at> clobbered (if not <ad>)
+ * Example:
+ * find_ms_setbit a0, a4, a0, 0 -- return in a0 index of msbit set in a4
+ */
+
+ .macro find_ms_setbit ad, as, at, base
+#if XCHAL_HAVE_NSA
+ movi \at, 31+\base
+ nsau \as, \as // get index of \as, numbered from msbit (32 if absent)
+ sub \ad, \at, \as // get numbering from lsbit (0..31, -1 if absent)
+#else /* XCHAL_HAVE_NSA */
+ movi \at, \base // start with result of 0 (point to lsbit of 32)
+
+ beqz \as, 2f // special case for zero argument: return -1
+ bltui \as, 0x10000, 1f // is it one of the 16 lsbits? (if so, check lower 16 bits)
+ addi \at, \at, 16 // no, increment result to upper 16 bits (of 32)
+ //srli \as, \as, 16 // check upper half (shift right 16 bits)
+ extui \as, \as, 16, 16 // check upper half (shift right 16 bits)
+1: bltui \as, 0x100, 1f // is it one of the 8 lsbits? (if so, check lower 8 bits)
+ addi \at, \at, 8 // no, increment result to upper 8 bits (of 16)
+ srli \as, \as, 8 // shift right to check upper 8 bits
+1: bltui \as, 0x10, 1f // is it one of the 4 lsbits? (if so, check lower 4 bits)
+ addi \at, \at, 4 // no, increment result to upper 4 bits (of 8)
+ srli \as, \as, 4 // shift right 4 bits to check upper half
+1: bltui \as, 0x4, 1f // is it one of the 2 lsbits? (if so, check lower 2 bits)
+ addi \at, \at, 2 // no, increment result to upper 2 bits (of 4)
+ srli \as, \as, 2 // shift right 2 bits to check upper half
+1: bltui \as, 0x2, 1f // is it the lsbit?
+ addi \at, \at, 2 // no, increment result to upper bit (of 2)
+2: addi \at, \at, -1 // (from just above: add 1; from beqz: return -1)
+ //srli \as, \as, 1
+1: // done! \at contains index of msbit set (or -1 if none set)
+ .if 0x\ad - 0x\at // destination different than \at ? (works because regs are a0-a15)
+ mov \ad, \at // then move result to \ad
+ .endif
+#endif /* XCHAL_HAVE_NSA */
+ .endm // find_ms_setbit
+
+/*----------------------------------------------------------------------
+ * find_ls_setbit
+ *
+ * This macro finds the least significant bit that is set in <as>,
+ * and return its index in <ad>.
+ * Usage is the same as for the find_ms_setbit macro.
+ * Example:
+ * find_ls_setbit a0, a4, a0, 0 -- return in a0 index of lsbit set in a4
+ */
+
+ .macro find_ls_setbit ad, as, at, base
+ neg \at, \as // keep only the least-significant bit that is set...
+ and \as, \at, \as // ... in \as
+ find_ms_setbit \ad, \as, \at, \base
+ .endm // find_ls_setbit
+
+/*----------------------------------------------------------------------
+ * find_ls_one
+ *
+ * Same as find_ls_setbit with base zero.
+ * Source (as) and destination (ad) registers must be different.
+ * Provided for backward compatibility.
+ */
+
+ .macro find_ls_one ad, as
+ find_ls_setbit \ad, \as, \ad, 0
+ .endm // find_ls_one
+
+/*----------------------------------------------------------------------
+ * floop, floopnez, floopgtz, floopend
+ *
+ * These macros are used for fast inner loops that
+ * work whether or not the Loops options is configured.
+ * If the Loops option is configured, they simply use
+ * the zero-overhead LOOP instructions; otherwise
+ * they use explicit decrement and branch instructions.
+ *
+ * They are used in pairs, with floop, floopnez or floopgtz
+ * at the beginning of the loop, and floopend at the end.
+ *
+ * Each pair of loop macro calls must be given the loop count
+ * address register and a unique label for that loop.
+ *
+ * Example:
+ *
+ * movi a3, 16 // loop 16 times
+ * floop a3, myloop1
+ * :
+ * bnez a7, end1 // exit loop if a7 != 0
+ * :
+ * floopend a3, myloop1
+ * end1:
+ *
+ * Like the LOOP instructions, these macros cannot be
+ * nested, must include at least one instruction,
+ * cannot call functions inside the loop, etc.
+ * The loop can be exited by jumping to the instruction
+ * following floopend (or elsewhere outside the loop),
+ * or continued by jumping to a NOP instruction placed
+ * immediately before floopend.
+ *
+ * Unlike LOOP instructions, the register passed to floop*
+ * cannot be used inside the loop, because it is used as
+ * the loop counter if the Loops option is not configured.
+ * And its value is undefined after exiting the loop.
+ * And because the loop counter register is active inside
+ * the loop, you can't easily use this construct to loop
+ * across a register file using ROTW as you might with LOOP
+ * instructions, unless you copy the loop register along.
+ */
+
+ /* Named label version of the macros: */
+
+ .macro floop ar, endlabel
+ floop_ \ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel
+ .endm
+
+ .macro floopnez ar, endlabel
+ floopnez_ \ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel
+ .endm
+
+ .macro floopgtz ar, endlabel
+ floopgtz_ \ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel
+ .endm
+
+ .macro floopend ar, endlabel
+ floopend_ \ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel
+ .endm
+
+ /* Numbered local label version of the macros: */
+#if 0 /*UNTESTED*/
+ .macro floop89 ar
+ floop_ \ar, 8, 9f
+ .endm
+
+ .macro floopnez89 ar
+ floopnez_ \ar, 8, 9f
+ .endm
+
+ .macro floopgtz89 ar
+ floopgtz_ \ar, 8, 9f
+ .endm
+
+ .macro floopend89 ar
+ floopend_ \ar, 8b, 9
+ .endm
+#endif /*0*/
+
+ /* Underlying version of the macros: */
+
+ .macro floop_ ar, startlabel, endlabelref
+ .ifdef _infloop_
+ .if _infloop_
+ .err // Error: floop cannot be nested
+ .endif
+ .endif
+ .set _infloop_, 1
+#if XCHAL_HAVE_LOOPS
+ loop \ar, \endlabelref
+#else /* XCHAL_HAVE_LOOPS */
+\startlabel:
+ addi \ar, \ar, -1
+#endif /* XCHAL_HAVE_LOOPS */
+ .endm // floop_
+
+ .macro floopnez_ ar, startlabel, endlabelref
+ .ifdef _infloop_
+ .if _infloop_
+ .err // Error: floopnez cannot be nested
+ .endif
+ .endif
+ .set _infloop_, 1
+#if XCHAL_HAVE_LOOPS
+ loopnez \ar, \endlabelref
+#else /* XCHAL_HAVE_LOOPS */
+ beqz \ar, \endlabelref
+\startlabel:
+ addi \ar, \ar, -1
+#endif /* XCHAL_HAVE_LOOPS */
+ .endm // floopnez_
+
+ .macro floopgtz_ ar, startlabel, endlabelref
+ .ifdef _infloop_
+ .if _infloop_
+ .err // Error: floopgtz cannot be nested
+ .endif
+ .endif
+ .set _infloop_, 1
+#if XCHAL_HAVE_LOOPS
+ loopgtz \ar, \endlabelref
+#else /* XCHAL_HAVE_LOOPS */
+ bltz \ar, \endlabelref
+ beqz \ar, \endlabelref
+\startlabel:
+ addi \ar, \ar, -1
+#endif /* XCHAL_HAVE_LOOPS */
+ .endm // floopgtz_
+
+
+ .macro floopend_ ar, startlabelref, endlabel
+ .ifndef _infloop_
+ .err // Error: floopend without matching floopXXX
+ .endif
+ .ifeq _infloop_
+ .err // Error: floopend without matching floopXXX
+ .endif
+ .set _infloop_, 0
+#if ! XCHAL_HAVE_LOOPS
+ bnez \ar, \startlabelref
+#endif /* XCHAL_HAVE_LOOPS */
+\endlabel:
+ .endm // floopend_
+
+/*----------------------------------------------------------------------
+ * crsil -- conditional RSIL (read/set interrupt level)
+ *
+ * Executes the RSIL instruction if it exists, else just reads PS.
+ * The RSIL instruction does not exist in the new exception architecture
+ * if the interrupt option is not selected.
+ */
+
+ .macro crsil ar, newlevel
+#if XCHAL_HAVE_OLD_EXC_ARCH || XCHAL_HAVE_INTERRUPTS
+ rsil \ar, \newlevel
+#else
+ rsr \ar, PS
+#endif
+ .endm // crsil
+
+/*----------------------------------------------------------------------
+ * window_spill{4,8,12}
+ *
+ * These macros spill callers' register windows to the stack.
+ * They work for both privileged and non-privileged tasks.
+ * Must be called from a windowed ABI context, eg. within
+ * a windowed ABI function (ie. valid stack frame, window
+ * exceptions enabled, not in exception mode, etc).
+ *
+ * This macro requires a single invocation of the window_spill_common
+ * macro in the same assembly unit and section.
+ *
+ * Note that using window_spill{4,8,12} macros is more efficient
+ * than calling a function implemented using window_spill_function,
+ * because the latter needs extra code to figure out the size of
+ * the call to the spilling function.
+ *
+ * Example usage:
+ *
+ * .text
+ * .align 4
+ * .global some_function
+ * .type some_function,@function
+ * some_function:
+ * entry a1, 16
+ * :
+ * :
+ *
+ * window_spill4 // spill windows of some_function's callers; preserves a0..a3 only;
+ * // to use window_spill{8,12} in this example function we'd have
+ * // to increase space allocated by the entry instruction, because
+ * // 16 bytes only allows call4; 32 or 48 bytes (+locals) are needed
+ * // for call8/window_spill8 or call12/window_spill12 respectively.
+ * :
+ *
+ * retw
+ *
+ * window_spill_common // instantiates code used by window_spill4
+ *
+ *
+ * On entry:
+ * none (if window_spill4)
+ * stack frame has enough space allocated for call8 (if window_spill8)
+ * stack frame has enough space allocated for call12 (if window_spill12)
+ * On exit:
+ * a4..a15 clobbered (if window_spill4)
+ * a8..a15 clobbered (if window_spill8)
+ * a12..a15 clobbered (if window_spill12)
+ * no caller windows are in live registers
+ */
+
+ .macro window_spill4
+#if XCHAL_HAVE_WINDOWED
+# if XCHAL_NUM_AREGS == 16
+ movi a15, 0 // for 16-register files, no need to call to reach the end
+# elif XCHAL_NUM_AREGS == 32
+ call4 .L__wdwspill_assist28 // call deep enough to clear out any live callers
+# elif XCHAL_NUM_AREGS == 64
+ call4 .L__wdwspill_assist60 // call deep enough to clear out any live callers
+# endif
+#endif
+ .endm // window_spill4
+
+ .macro window_spill8
+#if XCHAL_HAVE_WINDOWED
+# if XCHAL_NUM_AREGS == 16
+ movi a15, 0 // for 16-register files, no need to call to reach the end
+# elif XCHAL_NUM_AREGS == 32
+ call8 .L__wdwspill_assist24 // call deep enough to clear out any live callers
+# elif XCHAL_NUM_AREGS == 64
+ call8 .L__wdwspill_assist56 // call deep enough to clear out any live callers
+# endif
+#endif
+ .endm // window_spill8
+
+ .macro window_spill12
+#if XCHAL_HAVE_WINDOWED
+# if XCHAL_NUM_AREGS == 16
+ movi a15, 0 // for 16-register files, no need to call to reach the end
+# elif XCHAL_NUM_AREGS == 32
+ call12 .L__wdwspill_assist20 // call deep enough to clear out any live callers
+# elif XCHAL_NUM_AREGS == 64
+ call12 .L__wdwspill_assist52 // call deep enough to clear out any live callers
+# endif
+#endif
+ .endm // window_spill12
+
+/*----------------------------------------------------------------------
+ * window_spill_function
+ *
+ * This macro outputs a function that will spill its caller's callers'
+ * register windows to the stack. Eg. it could be used to implement
+ * a version of xthal_window_spill() that works in non-privileged tasks.
+ * This works for both privileged and non-privileged tasks.
+ *
+ * Typical usage:
+ *
+ * .text
+ * .align 4
+ * .global my_spill_function
+ * .type my_spill_function,@function
+ * my_spill_function:
+ * window_spill_function
+ *
+ * On entry to resulting function:
+ * none
+ * On exit from resulting function:
+ * none (no caller windows are in live registers)
+ */
+
+ .macro window_spill_function
+#if XCHAL_HAVE_WINDOWED
+# if XCHAL_NUM_AREGS == 32
+ entry sp, 48
+ bbci.l a0, 31, 1f // branch if called with call4
+ bbsi.l a0, 30, 2f // branch if called with call12
+ call8 .L__wdwspill_assist16 // called with call8, only need another 8
+ retw
+1: call12 .L__wdwspill_assist16 // called with call4, only need another 12
+ retw
+2: call4 .L__wdwspill_assist16 // called with call12, only need another 4
+ retw
+# elif XCHAL_NUM_AREGS == 64
+ entry sp, 48
+ bbci.l a0, 31, 1f // branch if called with call4
+ bbsi.l a0, 30, 2f // branch if called with call12
+ call4 .L__wdwspill_assist52 // called with call8, only need a call4
+ retw
+1: call8 .L__wdwspill_assist52 // called with call4, only need a call8
+ retw
+2: call12 .L__wdwspill_assist40 // called with call12, can skip a call12
+ retw
+# elif XCHAL_NUM_AREGS == 16
+ entry sp, 16
+ bbci.l a0, 31, 1f // branch if called with call4
+ bbsi.l a0, 30, 2f // branch if called with call12
+ movi a7, 0 // called with call8
+ retw
+1: movi a11, 0 // called with call4
+2: retw // if called with call12, everything already spilled
+
+// movi a15, 0 // trick to spill all but the direct caller
+// j 1f
+// // The entry instruction is magical in the assembler (gets auto-aligned)
+// // so we have to jump to it to avoid falling through the padding.
+// // We need entry/retw to know where to return.
+//1: entry sp, 16
+// retw
+# else
+# error "unrecognized address register file size"
+# endif
+#endif /* XCHAL_HAVE_WINDOWED */
+ window_spill_common
+ .endm // window_spill_function
+
+/*----------------------------------------------------------------------
+ * window_spill_common
+ *
+ * Common code used by any number of invocations of the window_spill##
+ * and window_spill_function macros.
+ *
+ * Must be instantiated exactly once within a given assembly unit,
+ * within call/j range of and same section as window_spill##
+ * macro invocations for that assembly unit.
+ * (Is automatically instantiated by the window_spill_function macro.)
+ */
+
+ .macro window_spill_common
+#if XCHAL_HAVE_WINDOWED && (XCHAL_NUM_AREGS == 32 || XCHAL_NUM_AREGS == 64)
+ .ifndef .L__wdwspill_defined
+# if XCHAL_NUM_AREGS >= 64
+.L__wdwspill_assist60:
+ entry sp, 32
+ call8 .L__wdwspill_assist52
+ retw
+.L__wdwspill_assist56:
+ entry sp, 16
+ call4 .L__wdwspill_assist52
+ retw
+.L__wdwspill_assist52:
+ entry sp, 48
+ call12 .L__wdwspill_assist40
+ retw
+.L__wdwspill_assist40:
+ entry sp, 48
+ call12 .L__wdwspill_assist28
+ retw
+# endif
+.L__wdwspill_assist28:
+ entry sp, 48
+ call12 .L__wdwspill_assist16
+ retw
+.L__wdwspill_assist24:
+ entry sp, 32
+ call8 .L__wdwspill_assist16
+ retw
+.L__wdwspill_assist20:
+ entry sp, 16
+ call4 .L__wdwspill_assist16
+ retw
+.L__wdwspill_assist16:
+ entry sp, 16
+ movi a15, 0
+ retw
+ .set .L__wdwspill_defined, 1
+ .endif
+#endif /* XCHAL_HAVE_WINDOWED with 32 or 64 aregs */
+ .endm // window_spill_common
+
+/*----------------------------------------------------------------------
+ * beqi32
+ *
+ * macro implements version of beqi for arbitrary 32-bit immidiate value
+ *
+ * beqi32 ax, ay, imm32, label
+ *
+ * Compares value in register ax with imm32 value and jumps to label if
+ * equal. Clobberes register ay if needed
+ *
+ */
+ .macro beqi32 ax, ay, imm, label
+ .ifeq ((\imm-1) & ~7) // 1..8 ?
+ beqi \ax, \imm, \label
+ .else
+ .ifeq (\imm+1) // -1 ?
+ beqi \ax, \imm, \label
+ .else
+ .ifeq (\imm) // 0 ?
+ beqz \ax, \label
+ .else
+ // We could also handle immediates 10,12,16,32,64,128,256
+ // but it would be a long macro...
+ movi \ay, \imm
+ beq \ax, \ay, \label
+ .endif
+ .endif
+ .endif
+ .endm // beqi32
+
+#endif /*XTENSA_COREASM_H*/
+
diff --git a/include/asm-xtensa/xtensa/corebits.h b/include/asm-xtensa/xtensa/corebits.h
new file mode 100644
index 00000000000..e578ade4163
--- /dev/null
+++ b/include/asm-xtensa/xtensa/corebits.h
@@ -0,0 +1,77 @@
+#ifndef XTENSA_COREBITS_H
+#define XTENSA_COREBITS_H
+
+/*
+ * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
+ *
+ * xtensa/corebits.h - Xtensa Special Register field positions and masks.
+ *
+ * (In previous releases, these were defined in specreg.h, a generated file.
+ * This file is not generated, i.e. it is processor configuration independent.)
+ */
+
+
+/* EXCCAUSE register fields: */
+#define EXCCAUSE_EXCCAUSE_SHIFT 0
+#define EXCCAUSE_EXCCAUSE_MASK 0x3F
+/* Exception causes (mostly incomplete!): */
+#define EXCCAUSE_ILLEGAL 0
+#define EXCCAUSE_SYSCALL 1
+#define EXCCAUSE_IFETCHERROR 2
+#define EXCCAUSE_LOADSTOREERROR 3
+#define EXCCAUSE_LEVEL1INTERRUPT 4
+#define EXCCAUSE_ALLOCA 5
+
+/* PS register fields: */
+#define PS_WOE_SHIFT 18
+#define PS_WOE_MASK 0x00040000
+#define PS_WOE PS_WOE_MASK
+#define PS_CALLINC_SHIFT 16
+#define PS_CALLINC_MASK 0x00030000
+#define PS_CALLINC(n) (((n)&3)<<PS_CALLINC_SHIFT) /* n = 0..3 */
+#define PS_OWB_SHIFT 8
+#define PS_OWB_MASK 0x00000F00
+#define PS_OWB(n) (((n)&15)<<PS_OWB_SHIFT) /* n = 0..15 (or 0..7) */
+#define PS_RING_SHIFT 6
+#define PS_RING_MASK 0x000000C0
+#define PS_RING(n) (((n)&3)<<PS_RING_SHIFT) /* n = 0..3 */
+#define PS_UM_SHIFT 5
+#define PS_UM_MASK 0x00000020
+#define PS_UM PS_UM_MASK
+#define PS_EXCM_SHIFT 4
+#define PS_EXCM_MASK 0x00000010
+#define PS_EXCM PS_EXCM_MASK
+#define PS_INTLEVEL_SHIFT 0
+#define PS_INTLEVEL_MASK 0x0000000F
+#define PS_INTLEVEL(n) ((n)&PS_INTLEVEL_MASK) /* n = 0..15 */
+/* Backward compatibility (deprecated): */
+#define PS_PROGSTACK_SHIFT PS_UM_SHIFT
+#define PS_PROGSTACK_MASK PS_UM_MASK
+#define PS_PROG_SHIFT PS_UM_SHIFT
+#define PS_PROG_MASK PS_UM_MASK
+#define PS_PROG PS_UM
+
+/* DBREAKCn register fields: */
+#define DBREAKC_MASK_SHIFT 0
+#define DBREAKC_MASK_MASK 0x0000003F
+#define DBREAKC_LOADBREAK_SHIFT 30
+#define DBREAKC_LOADBREAK_MASK 0x40000000
+#define DBREAKC_STOREBREAK_SHIFT 31
+#define DBREAKC_STOREBREAK_MASK 0x80000000
+
+/* DEBUGCAUSE register fields: */
+#define DEBUGCAUSE_DEBUGINT_SHIFT 5
+#define DEBUGCAUSE_DEBUGINT_MASK 0x20 /* debug interrupt */
+#define DEBUGCAUSE_BREAKN_SHIFT 4
+#define DEBUGCAUSE_BREAKN_MASK 0x10 /* BREAK.N instruction */
+#define DEBUGCAUSE_BREAK_SHIFT 3
+#define DEBUGCAUSE_BREAK_MASK 0x08 /* BREAK instruction */
+#define DEBUGCAUSE_DBREAK_SHIFT 2
+#define DEBUGCAUSE_DBREAK_MASK 0x04 /* DBREAK match */
+#define DEBUGCAUSE_IBREAK_SHIFT 1
+#define DEBUGCAUSE_IBREAK_MASK 0x02 /* IBREAK match */
+#define DEBUGCAUSE_ICOUNT_SHIFT 0
+#define DEBUGCAUSE_ICOUNT_MASK 0x01 /* ICOUNT would increment to zero */
+
+#endif /*XTENSA_COREBITS_H*/
+
diff --git a/include/asm-xtensa/xtensa/hal.h b/include/asm-xtensa/xtensa/hal.h
new file mode 100644
index 00000000000..d1047250545
--- /dev/null
+++ b/include/asm-xtensa/xtensa/hal.h
@@ -0,0 +1,822 @@
+#ifndef XTENSA_HAL_H
+#define XTENSA_HAL_H
+
+/*
+ * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
+ *
+ * include/asm-xtensa/xtensa/hal.h -- contains a definition of the
+ * Core HAL interface.
+ *
+ * All definitions in this header file are independent of any specific
+ * Xtensa processor configuration. Thus an OS or other software can
+ * include this header file and be compiled into configuration-
+ * independent objects that can be distributed and eventually linked
+ * to the HAL library (libhal.a) to create a configuration-specific
+ * final executable.
+ *
+ * Certain definitions, however, are release-specific -- such as the
+ * XTHAL_RELEASE_xxx macros (or additions made in later releases).
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2002 Tensilica Inc.
+ */
+
+
+/*----------------------------------------------------------------------
+ Constant Definitions
+ (shared with assembly)
+ ----------------------------------------------------------------------*/
+
+/* Software release information (not configuration-specific!): */
+#define XTHAL_RELEASE_MAJOR 1050
+#define XTHAL_RELEASE_MINOR 0
+#define XTHAL_RELEASE_NAME "T1050.0-2002-08-06-eng0"
+#define XTHAL_RELEASE_INTERNAL "2002-08-06-eng0"
+#define XTHAL_REL_T1050 1
+#define XTHAL_REL_T1050_0 1
+#define XTHAL_REL_T1050_0_2002 1
+#define XTHAL_REL_T1050_0_2002_08 1
+#define XTHAL_REL_T1050_0_2002_08_06 1
+#define XTHAL_REL_T1050_0_2002_08_06_ENG0 1
+
+/* HAL version numbers (these names are for backward compatibility): */
+#define XTHAL_MAJOR_REV XTHAL_RELEASE_MAJOR
+#define XTHAL_MINOR_REV XTHAL_RELEASE_MINOR
+/*
+ * A bit of software release history on values of XTHAL_{MAJOR,MINOR}_REV:
+ *
+ * Release MAJOR MINOR Comment
+ * ======= ===== ===== =======
+ * T1015.n n/a n/a (HAL not yet available)
+ * T1020.{0,1,2} 0 1 (HAL beta)
+ * T1020.{3,4} 0 2 First release.
+ * T1020.n (n>4) 0 2 or >3 (TBD)
+ * T1030.0 0 1 (HAL beta)
+ * T1030.{1,2} 0 3 Equivalent to first release.
+ * T1030.n (n>=3) 0 >= 3 (TBD)
+ * T1040.n 1040 n Full CHAL available from T1040.2
+ * T1050.n 1050 n Current release.
+ *
+ *
+ * Note: there is a distinction between the software release with
+ * which something is compiled (accessible using XTHAL_RELEASE_* macros)
+ * and the software release with which the HAL library was compiled
+ * (accessible using Xthal_release_* global variables). This
+ * distinction is particularly relevant for vendors that distribute
+ * configuration-independent binaries (eg. an OS), where their customer
+ * might link it with a HAL of a different Xtensa software release.
+ * In this case, it may be appropriate for the OS to verify at run-time
+ * whether XTHAL_RELEASE_* and Xthal_release_* are compatible.
+ * [Guidelines as to which release is compatible with which are not
+ * currently provided explicitly, but might be inferred from reading
+ * OSKit documentation for all releases -- compatibility is also highly
+ * dependent on which HAL features are used. Each release is usually
+ * backward compatible, with very few exceptions if any.]
+ *
+ * Notes:
+ * Tornado 2.0 supported in T1020.3+, T1030.1+, and T1040.{0,1} only.
+ * Tornado 2.0.2 supported in T1040.2+, and T1050.
+ * Compile-time HAL port of NucleusPlus supported by T1040.2+ and T1050.
+ */
+
+
+/*
+ * Architectural limits, independent of configuration.
+ * Note that these are ISA-defined limits, not micro-architecture implementation
+ * limits enforced by the Xtensa Processor Generator (which may be stricter than
+ * these below).
+ */
+#define XTHAL_MAX_CPS 8 /* max number of coprocessors (0..7) */
+#define XTHAL_MAX_INTERRUPTS 32 /* max number of interrupts (0..31) */
+#define XTHAL_MAX_INTLEVELS 16 /* max number of interrupt levels (0..15) */
+ /* (as of T1040, implementation limit is 7: 0..6) */
+#define XTHAL_MAX_TIMERS 4 /* max number of timers (CCOMPARE0..CCOMPARE3) */
+ /* (as of T1040, implementation limit is 3: 0..2) */
+
+/* Misc: */
+#define XTHAL_LITTLEENDIAN 0
+#define XTHAL_BIGENDIAN 1
+
+
+/* Interrupt types: */
+#define XTHAL_INTTYPE_UNCONFIGURED 0
+#define XTHAL_INTTYPE_SOFTWARE 1
+#define XTHAL_INTTYPE_EXTERN_EDGE 2
+#define XTHAL_INTTYPE_EXTERN_LEVEL 3
+#define XTHAL_INTTYPE_TIMER 4
+#define XTHAL_INTTYPE_NMI 5
+#define XTHAL_MAX_INTTYPES 6 /* number of interrupt types */
+
+/* Timer related: */
+#define XTHAL_TIMER_UNCONFIGURED -1 /* Xthal_timer_interrupt[] value for non-existent timers */
+#define XTHAL_TIMER_UNASSIGNED XTHAL_TIMER_UNCONFIGURED /* (for backwards compatibility only) */
+
+
+/* Access Mode bits (tentative): */ /* bit abbr unit short_name PPC equ - Description */
+#define XTHAL_AMB_EXCEPTION 0 /* 001 E EX fls: EXception none - generate exception on any access (aka "illegal") */
+#define XTHAL_AMB_HITCACHE 1 /* 002 C CH fls: use Cache on Hit ~(I CI) - use cache on hit -- way from tag match [or H HC, or U UC] (ISA: same, except for Isolate case) */
+#define XTHAL_AMB_ALLOCATE 2 /* 004 A AL fl?: ALlocate none - refill cache on miss -- way from LRU [or F FI fill] (ISA: Read/Write Miss Refill) */
+#define XTHAL_AMB_WRITETHRU 3 /* 008 W WT --s: WriteThrough W WT - store immediately to memory (ISA: same) */
+#define XTHAL_AMB_ISOLATE 4 /* 010 I IS fls: ISolate none - use cache regardless of hit-vs-miss -- way from vaddr (ISA: use-cache-on-miss+hit) */
+#define XTHAL_AMB_GUARD 5 /* 020 G GU ?l?: GUard G * - non-speculative; spec/replay refs not permitted */
+#if 0
+#define XTHAL_AMB_ORDERED x /* 000 O OR fls: ORdered G * - mem accesses cannot be out of order */
+#define XTHAL_AMB_FUSEWRITES x /* 000 F FW --s: FuseWrites none - allow combining/merging multiple writes (to same datapath data unit) into one (implied by writeback) */
+#define XTHAL_AMB_COHERENT x /* 000 M MC fl?: Mem/MP Coherent M - on reads, other CPUs/bus-masters may need to supply data */
+#define XTHAL_AMB_TRUSTED x /* 000 T TR ?l?: TRusted none - memory will not bus error (if it does, handle as fatal imprecise interrupt) */
+#define XTHAL_AMB_PREFETCH x /* 000 P PR fl?: PRefetch none - on refill, read line+1 into prefetch buffers */
+#define XTHAL_AMB_STREAM x /* 000 S ST ???: STreaming none - access one of N stream buffers */
+#endif /*0*/
+
+#define XTHAL_AM_EXCEPTION (1<<XTHAL_AMB_EXCEPTION)
+#define XTHAL_AM_HITCACHE (1<<XTHAL_AMB_HITCACHE)
+#define XTHAL_AM_ALLOCATE (1<<XTHAL_AMB_ALLOCATE)
+#define XTHAL_AM_WRITETHRU (1<<XTHAL_AMB_WRITETHRU)
+#define XTHAL_AM_ISOLATE (1<<XTHAL_AMB_ISOLATE)
+#define XTHAL_AM_GUARD (1<<XTHAL_AMB_GUARD)
+#if 0
+#define XTHAL_AM_ORDERED (1<<XTHAL_AMB_ORDERED)
+#define XTHAL_AM_FUSEWRITES (1<<XTHAL_AMB_FUSEWRITES)
+#define XTHAL_AM_COHERENT (1<<XTHAL_AMB_COHERENT)
+#define XTHAL_AM_TRUSTED (1<<XTHAL_AMB_TRUSTED)
+#define XTHAL_AM_PREFETCH (1<<XTHAL_AMB_PREFETCH)
+#define XTHAL_AM_STREAM (1<<XTHAL_AMB_STREAM)
+#endif /*0*/
+
+/*
+ * Allowed Access Modes (bit combinations).
+ *
+ * Columns are:
+ * "FOGIWACE"
+ * Access mode bits (see XTHAL_AMB_xxx above).
+ * <letter> = bit is set
+ * '-' = bit is clear
+ * '.' = bit is irrelevant / don't care, as follows:
+ * E=1 makes all others irrelevant
+ * W,F relevant only for stores
+ * "2345"
+ * Indicates which Xtensa releases support the corresponding
+ * access mode. Releases for each character column are:
+ * 2 = prior to T1020.2: T1015 (V1.5), T1020.0, T1020.1
+ * 3 = T1020.2 and later: T1020.2+, T1030
+ * 4 = T1040
+ * 5 = T1050 (maybe)
+ * And the character column contents are:
+ * <number> = support by release(s)
+ * "." = unsupported by release(s)
+ * "?" = support unknown
+ */
+ /* FOGIWACE 2345 */
+/* For instruction fetch: */
+#define XTHAL_FAM_EXCEPTION 0x001 /* .......E 2345 exception */
+#define XTHAL_FAM_ISOLATE 0x012 /* .--I.-C- .... isolate */
+#define XTHAL_FAM_BYPASS 0x000 /* .---.--- 2345 bypass */
+#define XTHAL_FAM_NACACHED 0x002 /* .---.-C- .... cached no-allocate (frozen) */
+#define XTHAL_FAM_CACHED 0x006 /* .---.AC- 2345 cached */
+/* For data load: */
+#define XTHAL_LAM_EXCEPTION 0x001 /* .......E 2345 exception */
+#define XTHAL_LAM_ISOLATE 0x012 /* .--I.-C- 2345 isolate */
+#define XTHAL_LAM_BYPASS 0x000 /* .O--.--- 2... bypass speculative */
+#define XTHAL_LAM_BYPASSG 0x020 /* .OG-.--- .345 bypass guarded */
+#define XTHAL_LAM_NACACHED 0x002 /* .O--.-C- 2... cached no-allocate speculative */
+#define XTHAL_LAM_NACACHEDG 0x022 /* .OG-.-C- .345 cached no-allocate guarded */
+#define XTHAL_LAM_CACHED 0x006 /* .---.AC- 2345 cached speculative */
+#define XTHAL_LAM_CACHEDG 0x026 /* .?G-.AC- .... cached guarded */
+/* For data store: */
+#define XTHAL_SAM_EXCEPTION 0x001 /* .......E 2345 exception */
+#define XTHAL_SAM_ISOLATE 0x032 /* .-GI--C- 2345 isolate */
+#define XTHAL_SAM_BYPASS 0x028 /* -OG-W--- 2345 bypass */
+/*efine XTHAL_SAM_BYPASSF 0x028*/ /* F-G-W--- ...? bypass write-combined */
+#define XTHAL_SAM_WRITETHRU 0x02A /* -OG-W-C- 234? writethrough */
+/*efine XTHAL_SAM_WRITETHRUF 0x02A*/ /* F-G-W-C- ...5 writethrough write-combined */
+#define XTHAL_SAM_WRITEALLOC 0x02E /* -OG-WAC- ...? writethrough-allocate */
+/*efine XTHAL_SAM_WRITEALLOCF 0x02E*/ /* F-G-WAC- ...? writethrough-allocate write-combined */
+#define XTHAL_SAM_WRITEBACK 0x026 /* F-G--AC- ...5 writeback */
+
+#if 0
+/*
+ Cache attribute encoding for CACHEATTR (per ISA):
+ (Note: if this differs from ISA Ref Manual, ISA has precedence)
+
+ Inst-fetches Loads Stores
+ ------------- ------------ -------------
+0x0 FCA_EXCEPTION ?LCA_NACACHED_G* SCA_WRITETHRU "uncached"
+0x1 FCA_CACHED LCA_CACHED SCA_WRITETHRU cached
+0x2 FCA_BYPASS LCA_BYPASS_G* SCA_BYPASS bypass
+0x3 FCA_CACHED LCA_CACHED SCA_WRITEALLOCF write-allocate
+ or LCA_EXCEPTION SCA_EXCEPTION (if unimplemented)
+0x4 FCA_CACHED LCA_CACHED SCA_WRITEBACK write-back
+ or LCA_EXCEPTION SCA_EXCEPTION (if unimplemented)
+0x5..D FCA_EXCEPTION LCA_EXCEPTION SCA_EXCEPTION (reserved)
+0xE FCA_EXCEPTION LCA_ISOLATE SCA_ISOLATE isolate
+0xF FCA_EXCEPTION LCA_EXCEPTION SCA_EXCEPTION illegal
+ * Prior to T1020.2?, guard feature not supported, this defaulted to speculative (no _G)
+*/
+#endif /*0*/
+
+
+#if !defined(__ASSEMBLY__) && !defined(_NOCLANGUAGE)
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*----------------------------------------------------------------------
+ HAL
+ ----------------------------------------------------------------------*/
+
+/* Constant to be checked in build = (XTHAL_MAJOR_REV<<16)|XTHAL_MINOR_REV */
+extern const unsigned int Xthal_rev_no;
+
+
+/*----------------------------------------------------------------------
+ Processor State
+ ----------------------------------------------------------------------*/
+/* save & restore the extra processor state */
+extern void xthal_save_extra(void *base);
+extern void xthal_restore_extra(void *base);
+
+extern void xthal_save_cpregs(void *base, int);
+extern void xthal_restore_cpregs(void *base, int);
+
+/*extern void xthal_save_all_extra(void *base);*/
+/*extern void xthal_restore_all_extra(void *base);*/
+
+/* space for processor state */
+extern const unsigned int Xthal_extra_size;
+extern const unsigned int Xthal_extra_align;
+/* space for TIE register files */
+extern const unsigned int Xthal_cpregs_size[XTHAL_MAX_CPS];
+extern const unsigned int Xthal_cpregs_align[XTHAL_MAX_CPS];
+
+/* total of space for the processor state (for Tor2) */
+extern const unsigned int Xthal_all_extra_size;
+extern const unsigned int Xthal_all_extra_align;
+
+/* initialize the extra processor */
+/*extern void xthal_init_extra(void);*/
+/* initialize the TIE coprocessor */
+/*extern void xthal_init_cp(int);*/
+
+/* initialize the extra processor */
+extern void xthal_init_mem_extra(void *);
+/* initialize the TIE coprocessor */
+extern void xthal_init_mem_cp(void *, int);
+
+/* validate & invalidate the TIE register file */
+extern void xthal_validate_cp(int);
+extern void xthal_invalidate_cp(int);
+
+/* the number of TIE coprocessors contiguous from zero (for Tor2) */
+extern const unsigned int Xthal_num_coprocessors;
+
+/* actual number of coprocessors */
+extern const unsigned char Xthal_cp_num;
+/* index of highest numbered coprocessor, plus one */
+extern const unsigned char Xthal_cp_max;
+/* index of highest allowed coprocessor number, per cfg, plus one */
+/*extern const unsigned char Xthal_cp_maxcfg;*/
+/* bitmask of which coprocessors are present */
+extern const unsigned int Xthal_cp_mask;
+
+/* read and write cpenable register */
+extern void xthal_set_cpenable(unsigned);
+extern unsigned xthal_get_cpenable(void);
+
+/* read & write extra state register */
+/*extern int xthal_read_extra(void *base, unsigned reg, unsigned *value);*/
+/*extern int xthal_write_extra(void *base, unsigned reg, unsigned value);*/
+
+/* read & write a TIE coprocessor register */
+/*extern int xthal_read_cpreg(void *base, int cp, unsigned reg, unsigned *value);*/
+/*extern int xthal_write_cpreg(void *base, int cp, unsigned reg, unsigned value);*/
+
+/* return coprocessor number based on register */
+/*extern int xthal_which_cp(unsigned reg);*/
+
+/*----------------------------------------------------------------------
+ Interrupts
+ ----------------------------------------------------------------------*/
+
+/* the number of interrupt levels */
+extern const unsigned char Xthal_num_intlevels;
+/* the number of interrupts */
+extern const unsigned char Xthal_num_interrupts;
+
+/* mask for level of interrupts */
+extern const unsigned int Xthal_intlevel_mask[XTHAL_MAX_INTLEVELS];
+/* mask for level 0 to N interrupts */
+extern const unsigned int Xthal_intlevel_andbelow_mask[XTHAL_MAX_INTLEVELS];
+
+/* level of each interrupt */
+extern const unsigned char Xthal_intlevel[XTHAL_MAX_INTERRUPTS];
+
+/* type per interrupt */
+extern const unsigned char Xthal_inttype[XTHAL_MAX_INTERRUPTS];
+
+/* masks of each type of interrupt */
+extern const unsigned int Xthal_inttype_mask[XTHAL_MAX_INTTYPES];
+
+/* interrupt numbers assigned to each timer interrupt */
+extern const int Xthal_timer_interrupt[XTHAL_MAX_TIMERS];
+
+/*** Virtual interrupt prioritization: ***/
+
+/* Convert between interrupt levels (as per PS.INTLEVEL) and virtual interrupt priorities: */
+extern unsigned xthal_vpri_to_intlevel(unsigned vpri);
+extern unsigned xthal_intlevel_to_vpri(unsigned intlevel);
+
+/* Enables/disables given set (mask) of interrupts; returns previous enabled-mask of all ints: */
+extern unsigned xthal_int_enable(unsigned);
+extern unsigned xthal_int_disable(unsigned);
+
+/* Set/get virtual priority of an interrupt: */
+extern int xthal_set_int_vpri(int intnum, int vpri);
+extern int xthal_get_int_vpri(int intnum);
+
+/* Set/get interrupt lockout level for exclusive access to virtual priority data structures: */
+extern void xthal_set_vpri_locklevel(unsigned intlevel);
+extern unsigned xthal_get_vpri_locklevel(void);
+
+/* Set/get current virtual interrupt priority: */
+extern unsigned xthal_set_vpri(unsigned vpri);
+extern unsigned xthal_get_vpri(unsigned vpri);
+extern unsigned xthal_set_vpri_intlevel(unsigned intlevel);
+extern unsigned xthal_set_vpri_lock(void);
+
+
+
+/*----------------------------------------------------------------------
+ Generic Interrupt Trampolining Support
+ ----------------------------------------------------------------------*/
+
+typedef void (XtHalVoidFunc)(void);
+
+/*
+ * Bitmask of interrupts currently trampolining down:
+ */
+extern unsigned Xthal_tram_pending;
+
+/*
+ * Bitmask of which interrupts currently trampolining down
+ * synchronously are actually enabled; this bitmask is necessary
+ * because INTENABLE cannot hold that state (sync-trampolining
+ * interrupts must be kept disabled while trampolining);
+ * in the current implementation, any bit set here is not set
+ * in INTENABLE, and vice-versa; once a sync-trampoline is
+ * handled (at level one), its enable bit must be moved from
+ * here to INTENABLE:
+ */
+extern unsigned Xthal_tram_enabled;
+
+/*
+ * Bitmask of interrupts configured for sync trampolining:
+ */
+extern unsigned Xthal_tram_sync;
+
+
+/* Trampoline support functions: */
+extern unsigned xthal_tram_pending_to_service( void );
+extern void xthal_tram_done( unsigned serviced_mask );
+extern int xthal_tram_set_sync( int intnum, int sync );
+extern XtHalVoidFunc* xthal_set_tram_trigger_func( XtHalVoidFunc *trigger_fn );
+
+/* INTENABLE,INTREAD,INTSET,INTCLEAR register access functions: */
+extern unsigned xthal_get_intenable( void );
+extern void xthal_set_intenable( unsigned );
+extern unsigned xthal_get_intread( void );
+extern void xthal_set_intset( unsigned );
+extern void xthal_set_intclear( unsigned );
+
+
+/*----------------------------------------------------------------------
+ Register Windows
+ ----------------------------------------------------------------------*/
+
+/* number of registers in register window */
+extern const unsigned int Xthal_num_aregs;
+extern const unsigned char Xthal_num_aregs_log2;
+
+/* This spill any live register windows (other than the caller's): */
+extern void xthal_window_spill( void );
+
+
+/*----------------------------------------------------------------------
+ Cache
+ ----------------------------------------------------------------------*/
+
+/* size of the cache lines in log2(bytes) */
+extern const unsigned char Xthal_icache_linewidth;
+extern const unsigned char Xthal_dcache_linewidth;
+/* size of the cache lines in bytes */
+extern const unsigned short Xthal_icache_linesize;
+extern const unsigned short Xthal_dcache_linesize;
+/* number of cache sets in log2(lines per way) */
+extern const unsigned char Xthal_icache_setwidth;
+extern const unsigned char Xthal_dcache_setwidth;
+/* cache set associativity (number of ways) */
+extern const unsigned int Xthal_icache_ways;
+extern const unsigned int Xthal_dcache_ways;
+/* size of the caches in bytes (ways * 2^(linewidth + setwidth)) */
+extern const unsigned int Xthal_icache_size;
+extern const unsigned int Xthal_dcache_size;
+/* cache features */
+extern const unsigned char Xthal_dcache_is_writeback;
+extern const unsigned char Xthal_icache_line_lockable;
+extern const unsigned char Xthal_dcache_line_lockable;
+
+/* cache attribute register control (used by other HAL routines) */
+extern unsigned xthal_get_cacheattr( void );
+extern unsigned xthal_get_icacheattr( void );
+extern unsigned xthal_get_dcacheattr( void );
+extern void xthal_set_cacheattr( unsigned );
+extern void xthal_set_icacheattr( unsigned );
+extern void xthal_set_dcacheattr( unsigned );
+
+/* initialize cache support (must be called once at startup, before all other cache calls) */
+/*extern void xthal_cache_startinit( void );*/
+/* reset caches */
+/*extern void xthal_icache_reset( void );*/
+/*extern void xthal_dcache_reset( void );*/
+/* enable caches */
+extern void xthal_icache_enable( void ); /* DEPRECATED */
+extern void xthal_dcache_enable( void ); /* DEPRECATED */
+/* disable caches */
+extern void xthal_icache_disable( void ); /* DEPRECATED */
+extern void xthal_dcache_disable( void ); /* DEPRECATED */
+
+/* invalidate the caches */
+extern void xthal_icache_all_invalidate( void );
+extern void xthal_dcache_all_invalidate( void );
+extern void xthal_icache_region_invalidate( void *addr, unsigned size );
+extern void xthal_dcache_region_invalidate( void *addr, unsigned size );
+extern void xthal_icache_line_invalidate(void *addr);
+extern void xthal_dcache_line_invalidate(void *addr);
+/* write dirty data back */
+extern void xthal_dcache_all_writeback( void );
+extern void xthal_dcache_region_writeback( void *addr, unsigned size );
+extern void xthal_dcache_line_writeback(void *addr);
+/* write dirty data back and invalidate */
+extern void xthal_dcache_all_writeback_inv( void );
+extern void xthal_dcache_region_writeback_inv( void *addr, unsigned size );
+extern void xthal_dcache_line_writeback_inv(void *addr);
+/* prefetch and lock specified memory range into cache */
+extern void xthal_icache_region_lock( void *addr, unsigned size );
+extern void xthal_dcache_region_lock( void *addr, unsigned size );
+extern void xthal_icache_line_lock(void *addr);
+extern void xthal_dcache_line_lock(void *addr);
+/* unlock from cache */
+extern void xthal_icache_all_unlock( void );
+extern void xthal_dcache_all_unlock( void );
+extern void xthal_icache_region_unlock( void *addr, unsigned size );
+extern void xthal_dcache_region_unlock( void *addr, unsigned size );
+extern void xthal_icache_line_unlock(void *addr);
+extern void xthal_dcache_line_unlock(void *addr);
+
+
+/* sync icache and memory */
+extern void xthal_icache_sync( void );
+/* sync dcache and memory */
+extern void xthal_dcache_sync( void );
+
+/*----------------------------------------------------------------------
+ Debug
+ ----------------------------------------------------------------------*/
+
+/* 1 if debug option configured, 0 if not: */
+extern const int Xthal_debug_configured;
+
+/* Number of instruction and data break registers: */
+extern const int Xthal_num_ibreak;
+extern const int Xthal_num_dbreak;
+
+/* Set (plant) and remove software breakpoint, both synchronizing cache: */
+extern unsigned int xthal_set_soft_break(void *addr);
+extern void xthal_remove_soft_break(void *addr, unsigned int);
+
+
+/*----------------------------------------------------------------------
+ Disassembler
+ ----------------------------------------------------------------------*/
+
+/* Max expected size of the return buffer for a disassembled instruction (hint only): */
+#define XTHAL_DISASM_BUFSIZE 80
+
+/* Disassembly option bits for selecting what to return: */
+#define XTHAL_DISASM_OPT_ADDR 0x0001 /* display address */
+#define XTHAL_DISASM_OPT_OPHEX 0x0002 /* display opcode bytes in hex */
+#define XTHAL_DISASM_OPT_OPCODE 0x0004 /* display opcode name (mnemonic) */
+#define XTHAL_DISASM_OPT_PARMS 0x0008 /* display parameters */
+#define XTHAL_DISASM_OPT_ALL 0x0FFF /* display everything */
+
+/* routine to get a string for the disassembled instruction */
+extern int xthal_disassemble( unsigned char *instr_buf, void *tgt_addr,
+ char *buffer, unsigned buflen, unsigned options );
+
+/* routine to get the size of the next instruction. Returns 0 for
+ illegal instruction */
+extern int xthal_disassemble_size( unsigned char *instr_buf );
+
+
+/*----------------------------------------------------------------------
+ Core Counter
+ ----------------------------------------------------------------------*/
+
+/* counter info */
+extern const unsigned char Xthal_have_ccount; /* set if CCOUNT register present */
+extern const unsigned char Xthal_num_ccompare; /* number of CCOMPAREn registers */
+
+/* get CCOUNT register (if not present return 0) */
+extern unsigned xthal_get_ccount(void);
+
+/* set and get CCOMPAREn registers (if not present, get returns 0) */
+extern void xthal_set_ccompare(int, unsigned);
+extern unsigned xthal_get_ccompare(int);
+
+
+/*----------------------------------------------------------------------
+ Instruction/Data RAM/ROM Access
+ ----------------------------------------------------------------------*/
+
+extern void* xthal_memcpy(void *dst, const void *src, unsigned len);
+extern void* xthal_bcopy(const void *src, void *dst, unsigned len);
+
+/*----------------------------------------------------------------------
+ MP Synchronization
+ ----------------------------------------------------------------------*/
+extern int xthal_compare_and_set( int *addr, int test_val, int compare_val );
+extern unsigned xthal_get_prid( void );
+
+/*extern const char Xthal_have_s32c1i;*/
+extern const unsigned char Xthal_have_prid;
+
+
+/*----------------------------------------------------------------------
+ Miscellaneous
+ ----------------------------------------------------------------------*/
+
+extern const unsigned int Xthal_release_major;
+extern const unsigned int Xthal_release_minor;
+extern const char * const Xthal_release_name;
+extern const char * const Xthal_release_internal;
+
+extern const unsigned char Xthal_memory_order;
+extern const unsigned char Xthal_have_windowed;
+extern const unsigned char Xthal_have_density;
+extern const unsigned char Xthal_have_booleans;
+extern const unsigned char Xthal_have_loops;
+extern const unsigned char Xthal_have_nsa;
+extern const unsigned char Xthal_have_minmax;
+extern const unsigned char Xthal_have_sext;
+extern const unsigned char Xthal_have_clamps;
+extern const unsigned char Xthal_have_mac16;
+extern const unsigned char Xthal_have_mul16;
+extern const unsigned char Xthal_have_fp;
+extern const unsigned char Xthal_have_speculation;
+extern const unsigned char Xthal_have_exceptions;
+extern const unsigned char Xthal_xea_version;
+extern const unsigned char Xthal_have_interrupts;
+extern const unsigned char Xthal_have_highlevel_interrupts;
+extern const unsigned char Xthal_have_nmi;
+
+extern const unsigned short Xthal_num_writebuffer_entries;
+
+extern const unsigned int Xthal_build_unique_id;
+/* Release info for hardware targeted by software upgrades: */
+extern const unsigned int Xthal_hw_configid0;
+extern const unsigned int Xthal_hw_configid1;
+extern const unsigned int Xthal_hw_release_major;
+extern const unsigned int Xthal_hw_release_minor;
+extern const char * const Xthal_hw_release_name;
+extern const char * const Xthal_hw_release_internal;
+
+
+/* Internal memories... */
+
+extern const unsigned char Xthal_num_instrom;
+extern const unsigned char Xthal_num_instram;
+extern const unsigned char Xthal_num_datarom;
+extern const unsigned char Xthal_num_dataram;
+extern const unsigned char Xthal_num_xlmi;
+extern const unsigned int Xthal_instrom_vaddr[1];
+extern const unsigned int Xthal_instrom_paddr[1];
+extern const unsigned int Xthal_instrom_size [1];
+extern const unsigned int Xthal_instram_vaddr[1];
+extern const unsigned int Xthal_instram_paddr[1];
+extern const unsigned int Xthal_instram_size [1];
+extern const unsigned int Xthal_datarom_vaddr[1];
+extern const unsigned int Xthal_datarom_paddr[1];
+extern const unsigned int Xthal_datarom_size [1];
+extern const unsigned int Xthal_dataram_vaddr[1];
+extern const unsigned int Xthal_dataram_paddr[1];
+extern const unsigned int Xthal_dataram_size [1];
+extern const unsigned int Xthal_xlmi_vaddr[1];
+extern const unsigned int Xthal_xlmi_paddr[1];
+extern const unsigned int Xthal_xlmi_size [1];
+
+
+
+/*----------------------------------------------------------------------
+ Memory Management Unit
+ ----------------------------------------------------------------------*/
+
+extern const unsigned char Xthal_have_spanning_way;
+extern const unsigned char Xthal_have_identity_map;
+extern const unsigned char Xthal_have_mimic_cacheattr;
+extern const unsigned char Xthal_have_xlt_cacheattr;
+extern const unsigned char Xthal_have_cacheattr;
+extern const unsigned char Xthal_have_tlbs;
+
+extern const unsigned char Xthal_mmu_asid_bits; /* 0 .. 8 */
+extern const unsigned char Xthal_mmu_asid_kernel;
+extern const unsigned char Xthal_mmu_rings; /* 1 .. 4 (perhaps 0 if no MMU and/or no protection?) */
+extern const unsigned char Xthal_mmu_ring_bits;
+extern const unsigned char Xthal_mmu_sr_bits;
+extern const unsigned char Xthal_mmu_ca_bits;
+extern const unsigned int Xthal_mmu_max_pte_page_size;
+extern const unsigned int Xthal_mmu_min_pte_page_size;
+
+extern const unsigned char Xthal_itlb_way_bits;
+extern const unsigned char Xthal_itlb_ways;
+extern const unsigned char Xthal_itlb_arf_ways;
+extern const unsigned char Xthal_dtlb_way_bits;
+extern const unsigned char Xthal_dtlb_ways;
+extern const unsigned char Xthal_dtlb_arf_ways;
+
+/* Convert between virtual and physical addresses (through static maps only): */
+/*** WARNING: these two functions may go away in a future release; don't depend on them! ***/
+extern int xthal_static_v2p( unsigned vaddr, unsigned *paddrp );
+extern int xthal_static_p2v( unsigned paddr, unsigned *vaddrp, unsigned cached );
+
+#if 0
+/******************* EXPERIMENTAL AND TENTATIVE ONLY ********************/
+
+#define XTHAL_MMU_PAGESZ_COUNT_MAX 8 /* maximum number of different page sizes */
+extern const char Xthal_mmu_pagesz_count; /* 0 .. 8 number of different page sizes configured */
+
+/* Note: the following table doesn't necessarily have page sizes in increasing order: */
+extern const char Xthal_mmu_pagesz_log2[XTHAL_MMU_PAGESZ_COUNT_MAX]; /* 10 .. 28 (0 past count) */
+
+/* Sorted (increasing) table of page sizes, that indexes into the above table: */
+extern const char Xthal_mmu_pagesz_sorted[XTHAL_MMU_PAGESZ_COUNT_MAX]; /* 0 .. 7 (0 past count) */
+
+/*u32 Xthal_virtual_exceptions;*/ /* bitmask of which exceptions execute in virtual mode... */
+
+extern const char Xthal_mmu_pte_pagesz_log2_min; /* ?? minimum page size in PTEs */
+extern const char Xthal_mmu_pte_pagesz_log2_max; /* ?? maximum page size in PTEs */
+
+/* Cache Attribute Bits Implemented by the Cache (part of the cache abstraction) */
+extern const char Xthal_icache_fca_bits_implemented; /* ITLB/UTLB only! */
+extern const char Xthal_dcache_lca_bits_implemented; /* DTLB/UTLB only! */
+extern const char Xthal_dcache_sca_bits_implemented; /* DTLB/UTLB only! */
+
+/* Per TLB Parameters (Instruction, Data, Unified) */
+struct XtHalMmuTlb Xthal_itlb; /* description of MMU I-TLB generic features */
+struct XtHalMmuTlb Xthal_dtlb; /* description of MMU D-TLB generic features */
+struct XtHalMmuTlb Xthal_utlb; /* description of MMU U-TLB generic features */
+
+#define XTHAL_MMU_WAYS_MAX 8 /* maximum number of ways (associativities) for each TLB */
+
+/* Structure for common information described for each possible TLB (instruction, data and unified): */
+typedef struct XtHalMmuTlb {
+ u8 va_bits; /* 32 (number of virtual address bits) */
+ u8 pa_bits; /* 32 (number of physical address bits) */
+ bool tlb_va_indexed; /* 1 (set if TLB is indexed by virtual address) */
+ bool tlb_va_tagged; /* 0 (set if TLB is tagged by virtual address) */
+ bool cache_va_indexed; /* 1 (set if cache is indexed by virtual address) */
+ bool cache_va_tagged; /* 0 (set if cache is tagged by virtual address) */
+ /*bool (whether page tables are traversed in vaddr sorted order, paddr sorted order, ...) */
+ /*u8 (set of available page attribute bits, other than cache attribute bits defined above) */
+ /*u32 (various masks for pages, MMU table/TLB entries, etc.) */
+ u8 way_count; /* 0 .. 8 (number of ways, a.k.a. associativities, for this TLB) */
+ XtHalMmuTlbWay * ways[XTHAL_MMU_WAYS_MAX]; /* pointers to per-way parms for each way */
+} XtHalMmuTlb;
+
+/* Per TLB Way (Per Associativity) Parameters */
+typedef struct XtHalMmuTlbWay {
+ u32 index_count_log2; /* 0 .. 4 */
+ u32 pagesz_mask; /* 0 .. 2^pagesz_count - 1 (each bit corresponds to a size */
+ /* defined in the Xthal_mmu_pagesz_log2[] table) */
+ u32 vpn_const_mask;
+ u32 vpn_const_value;
+ u64 ppn_const_mask; /* future may support pa_bits > 32 */
+ u64 ppn_const_value;
+ u32 ppn_id_mask; /* paddr bits taken directly from vaddr */
+ bool backgnd_match; /* 0 or 1 */
+ /* These are defined in terms of the XTHAL_CACHE_xxx bits: */
+ u8 fca_const_mask; /* ITLB/UTLB only! */
+ u8 fca_const_value; /* ITLB/UTLB only! */
+ u8 lca_const_mask; /* DTLB/UTLB only! */
+ u8 lca_const_value; /* DTLB/UTLB only! */
+ u8 sca_const_mask; /* DTLB/UTLB only! */
+ u8 sca_const_value; /* DTLB/UTLB only! */
+ /* These define an encoding that map 5 bits in TLB and PTE entries to */
+ /* 8 bits (FCA, ITLB), 16 bits (LCA+SCA, DTLB) or 24 bits (FCA+LCA+SCA, UTLB): */
+ /* (they may be moved to struct XtHalMmuTlb) */
+ u8 ca_bits; /* number of bits in TLB/PTE entries for cache attributes */
+ u32 * ca_map; /* pointer to array of 2^ca_bits entries of FCA+LCA+SCA bits */
+} XtHalMmuTlbWay;
+
+/*
+ * The way to determine whether protection support is present in core
+ * is to [look at Xthal_mmu_rings ???].
+ * Give info on memory requirements for MMU tables and other in-memory
+ * data structures (globally, per task, base and per page, etc.) - whatever bounds can be calculated.
+ */
+
+
+/* Default vectors: */
+xthal_immu_fetch_miss_vector
+xthal_dmmu_load_miss_vector
+xthal_dmmu_store_miss_vector
+
+/* Functions called when a fault is detected: */
+typedef void (XtHalMmuFaultFunc)( unsigned vaddr, ...context... );
+/* Or, */
+/* a? = vaddr */
+/* a? = context... */
+/* PS.xxx = xxx */
+XtHalMMuFaultFunc *Xthal_immu_fetch_fault_func;
+XtHalMMuFaultFunc *Xthal_dmmu_load_fault_func;
+XtHalMMuFaultFunc *Xthal_dmmu_store_fault_func;
+
+/* Default Handlers: */
+/* The user and/or kernel exception handlers may jump to these handlers to handle the relevant exceptions,
+ * according to the value of EXCCAUSE. The exact register state on entry to these handlers is TBD. */
+/* When multiple TLB entries match (hit) on the same access: */
+xthal_immu_fetch_multihit_handler
+xthal_dmmu_load_multihit_handler
+xthal_dmmu_store_multihit_handler
+/* Protection violations according to cache attributes, and other cache attribute mismatches: */
+xthal_immu_fetch_attr_handler
+xthal_dmmu_load_attr_handler
+xthal_dmmu_store_attr_handler
+/* Protection violations due to insufficient ring level: */
+xthal_immu_fetch_priv_handler
+xthal_dmmu_load_priv_handler
+xthal_dmmu_store_priv_handler
+/* Alignment exception handlers (if supported by the particular Xtensa MMU configuration): */
+xthal_dmmu_load_align_handler
+xthal_dmmu_store_align_handler
+
+/* Or, alternatively, the OS user and/or kernel exception handlers may simply jump to the
+ * following entry points which will handle any values of EXCCAUSE not handled by the OS: */
+xthal_user_exc_default_handler
+xthal_kernel_exc_default_handler
+
+#endif /*0*/
+
+#ifdef INCLUDE_DEPRECATED_HAL_CODE
+extern const unsigned char Xthal_have_old_exc_arch;
+extern const unsigned char Xthal_have_mmu;
+extern const unsigned int Xthal_num_regs;
+extern const unsigned char Xthal_num_iroms;
+extern const unsigned char Xthal_num_irams;
+extern const unsigned char Xthal_num_droms;
+extern const unsigned char Xthal_num_drams;
+extern const unsigned int Xthal_configid0;
+extern const unsigned int Xthal_configid1;
+#endif
+
+#ifdef INCLUDE_DEPRECATED_HAL_DEBUG_CODE
+#define XTHAL_24_BIT_BREAK 0x80000000
+#define XTHAL_16_BIT_BREAK 0x40000000
+extern const unsigned short Xthal_ill_inst_16[16];
+#define XTHAL_DEST_REG 0xf0000000 /* Mask for destination register */
+#define XTHAL_DEST_REG_INST 0x08000000 /* Branch address is in register */
+#define XTHAL_DEST_REL_INST 0x04000000 /* Branch address is relative */
+#define XTHAL_RFW_INST 0x00000800
+#define XTHAL_RFUE_INST 0x00000400
+#define XTHAL_RFI_INST 0x00000200
+#define XTHAL_RFE_INST 0x00000100
+#define XTHAL_RET_INST 0x00000080
+#define XTHAL_BREAK_INST 0x00000040
+#define XTHAL_SYSCALL_INST 0x00000020
+#define XTHAL_LOOP_END 0x00000010 /* Not set by xthal_inst_type */
+#define XTHAL_JUMP_INST 0x00000008 /* Call or jump instruction */
+#define XTHAL_BRANCH_INST 0x00000004 /* Branch instruction */
+#define XTHAL_24_BIT_INST 0x00000002
+#define XTHAL_16_BIT_INST 0x00000001
+typedef struct xthal_state {
+ unsigned pc;
+ unsigned ar[16];
+ unsigned lbeg;
+ unsigned lend;
+ unsigned lcount;
+ unsigned extra_ptr;
+ unsigned cpregs_ptr[XTHAL_MAX_CPS];
+} XTHAL_STATE;
+extern unsigned int xthal_inst_type(void *addr);
+extern unsigned int xthal_branch_addr(void *addr);
+extern unsigned int xthal_get_npc(XTHAL_STATE *user_state);
+#endif /* INCLUDE_DEPRECATED_HAL_DEBUG_CODE */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*!__ASSEMBLY__ */
+
+#endif /*XTENSA_HAL_H*/
+
diff --git a/include/asm-xtensa/xtensa/simcall.h b/include/asm-xtensa/xtensa/simcall.h
new file mode 100644
index 00000000000..a2b868929a4
--- /dev/null
+++ b/include/asm-xtensa/xtensa/simcall.h
@@ -0,0 +1,130 @@
+#ifndef SIMCALL_INCLUDED
+#define SIMCALL_INCLUDED
+
+/*
+ * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
+ *
+ * include/asm-xtensa/xtensa/simcall.h - Simulator call numbers
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of
+ * this archive for more details.
+ *
+ * Copyright (C) 2002 Tensilica Inc.
+ */
+
+
+/*
+ * System call like services offered by the simulator host.
+ * These are modeled after the Linux 2.4 kernel system calls
+ * for Xtensa processors. However not all system calls and
+ * not all functionality of a given system call are implemented,
+ * or necessarily have well defined or equivalent semantics in
+ * the context of a simulation (as opposed to a Unix kernel).
+ *
+ * These services behave largely as if they had been invoked
+ * as a task in the simulator host's operating system
+ * (eg. files accessed are those of the simulator host).
+ * However, these SIMCALLs model a virtual operating system
+ * so that various definitions, bit assignments etc
+ * (eg. open mode bits, errno values, etc) are independent
+ * of the host operating system used to run the simulation.
+ * Rather these definitions are specific to the Xtensa ISS.
+ * This way Xtensa ISA code written to use these SIMCALLs
+ * can (in principle) be simulated on any host.
+ *
+ * Up to 6 parameters are passed in registers a3 to a8
+ * (note the 6th parameter isn't passed on the stack,
+ * unlike windowed function calling conventions).
+ * The return value is in a2. A negative value in the
+ * range -4096 to -1 indicates a negated error code to be
+ * reported in errno with a return value of -1, otherwise
+ * the value in a2 is returned as is.
+ */
+
+/* These #defines need to match what's in Xtensa/OS/vxworks/xtiss/simcalls.c */
+
+#define SYS_nop 0 /* n/a - setup; used to flush register windows */
+#define SYS_exit 1 /*x*/
+#define SYS_fork 2
+#define SYS_read 3 /*x*/
+#define SYS_write 4 /*x*/
+#define SYS_open 5 /*x*/
+#define SYS_close 6 /*x*/
+#define SYS_rename 7 /*x 38 - waitpid */
+#define SYS_creat 8 /*x*/
+#define SYS_link 9 /*x (not implemented on WIN32) */
+#define SYS_unlink 10 /*x*/
+#define SYS_execv 11 /* n/a - execve */
+#define SYS_execve 12 /* 11 - chdir */
+#define SYS_pipe 13 /* 42 - time */
+#define SYS_stat 14 /* 106 - mknod */
+#define SYS_chmod 15
+#define SYS_chown 16 /* 202 - lchown */
+#define SYS_utime 17 /* 30 - break */
+#define SYS_wait 18 /* n/a - oldstat */
+#define SYS_lseek 19 /*x*/
+#define SYS_getpid 20
+#define SYS_isatty 21 /* n/a - mount */
+#define SYS_fstat 22 /* 108 - oldumount */
+#define SYS_time 23 /* 13 - setuid */
+#define SYS_gettimeofday 24 /*x 78 - getuid (not implemented on WIN32) */
+#define SYS_times 25 /*X 43 - stime (Xtensa-specific implementation) */
+#define SYS_socket 26
+#define SYS_sendto 27
+#define SYS_recvfrom 28
+#define SYS_select_one 29 /* not compitible select, one file descriptor at the time */
+#define SYS_bind 30
+#define SYS_ioctl 31
+
+/*
+ * Other...
+ */
+#define SYS_iss_argc 1000 /* returns value of argc */
+#define SYS_iss_argv_size 1001 /* bytes needed for argv & arg strings */
+#define SYS_iss_set_argv 1002 /* saves argv & arg strings at given addr */
+
+/*
+ * SIMCALLs for the ferret memory debugger. All are invoked by
+ * libferret.a ... ( Xtensa/Target-Libs/ferret )
+ */
+#define SYS_ferret 1010
+#define SYS_malloc 1011
+#define SYS_free 1012
+#define SYS_more_heap 1013
+#define SYS_no_heap 1014
+
+
+/*
+ * Extra SIMCALLs for GDB:
+ */
+#define SYS_gdb_break -1 /* invoked by XTOS on user exceptions if EPC points
+ to a break.n/break, regardless of cause! */
+#define SYS_xmon_out -2 /* invoked by XMON: ... */
+#define SYS_xmon_in -3 /* invoked by XMON: ... */
+#define SYS_xmon_flush -4 /* invoked by XMON: ... */
+#define SYS_gdb_abort -5 /* invoked by XTOS in _xtos_panic() */
+#define SYS_gdb_illegal_inst -6 /* invoked by XTOS for illegal instructions (too deeply) */
+#define SYS_xmon_init -7 /* invoked by XMON: ... */
+#define SYS_gdb_enter_sktloop -8 /* invoked by XTOS on debug exceptions */
+
+/*
+ * SIMCALLs for vxWorks xtiss BSP:
+ */
+#define SYS_setup_ppp_pipes -83
+#define SYS_log_msg -84
+
+/*
+ * Test SIMCALLs:
+ */
+#define SYS_test_write_state -100
+#define SYS_test_read_state -101
+
+/*
+ * SYS_select_one specifiers
+ */
+#define XTISS_SELECT_ONE_READ 1
+#define XTISS_SELECT_ONE_WRITE 2
+#define XTISS_SELECT_ONE_EXCEPT 3
+
+#endif /* !SIMCALL_INCLUDED */
diff --git a/include/asm-xtensa/xtensa/xt2000-uart.h b/include/asm-xtensa/xtensa/xt2000-uart.h
new file mode 100644
index 00000000000..0154460f0ed
--- /dev/null
+++ b/include/asm-xtensa/xtensa/xt2000-uart.h
@@ -0,0 +1,155 @@
+#ifndef _uart_h_included_
+#define _uart_h_included_
+
+/*
+ * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
+ *
+ * include/asm-xtensa/xtensa/xt2000-uart.h -- NatSemi PC16552D DUART
+ * definitions
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2002 Tensilica Inc.
+ */
+
+
+#include <xtensa/xt2000.h>
+
+
+/* 16550 UART DEVICE REGISTERS
+ The XT2000 board aligns each register to a 32-bit word but the UART device only uses
+ one byte of the word, which is the least-significant byte regardless of the
+ endianness of the core (ie. byte offset 0 for little-endian and 3 for big-endian).
+ So if using word accesses then endianness doesn't matter.
+ The macros provided here do that.
+*/
+struct uart_dev_s {
+ union {
+ unsigned int rxb; /* DLAB=0: receive buffer, read-only */
+ unsigned int txb; /* DLAB=0: transmit buffer, write-only */
+ unsigned int dll; /* DLAB=1: divisor, least-significant byte latch (was write-only?) */
+ } w0;
+ union {
+ unsigned int ier; /* DLAB=0: interrupt-enable register (was write-only?) */
+ unsigned int dlm; /* DLAB=1: divisor, most-significant byte latch (was write-only?) */
+ } w1;
+
+ union {
+ unsigned int isr; /* DLAB=0: interrupt status register, read-only */
+ unsigned int fcr; /* DLAB=0: FIFO control register, write-only */
+ unsigned int afr; /* DLAB=1: alternate function register */
+ } w2;
+
+ unsigned int lcr; /* line control-register, write-only */
+ unsigned int mcr; /* modem control-regsiter, write-only */
+ unsigned int lsr; /* line status register, read-only */
+ unsigned int msr; /* modem status register, read-only */
+ unsigned int scr; /* scratch regsiter, read/write */
+};
+
+#define _RXB(u) ((u)->w0.rxb)
+#define _TXB(u) ((u)->w0.txb)
+#define _DLL(u) ((u)->w0.dll)
+#define _IER(u) ((u)->w1.ier)
+#define _DLM(u) ((u)->w1.dlm)
+#define _ISR(u) ((u)->w2.isr)
+#define _FCR(u) ((u)->w2.fcr)
+#define _AFR(u) ((u)->w2.afr)
+#define _LCR(u) ((u)->lcr)
+#define _MCR(u) ((u)->mcr)
+#define _LSR(u) ((u)->lsr)
+#define _MSR(u) ((u)->msr)
+#define _SCR(u) ((u)->scr)
+
+typedef volatile struct uart_dev_s uart_dev_t;
+
+/* IER bits */
+#define RCVR_DATA_REG_INTENABLE 0x01
+#define XMIT_HOLD_REG_INTENABLE 0x02
+#define RCVR_STATUS_INTENABLE 0x04
+#define MODEM_STATUS_INTENABLE 0x08
+
+/* FCR bits */
+#define _FIFO_ENABLE 0x01
+#define RCVR_FIFO_RESET 0x02
+#define XMIT_FIFO_RESET 0x04
+#define DMA_MODE_SELECT 0x08
+#define RCVR_TRIGGER_LSB 0x40
+#define RCVR_TRIGGER_MSB 0x80
+
+/* AFR bits */
+#define AFR_CONC_WRITE 0x01
+#define AFR_BAUDOUT_SEL 0x02
+#define AFR_RXRDY_SEL 0x04
+
+/* ISR bits */
+#define INT_STATUS(r) ((r)&1)
+#define INT_PRIORITY(r) (((r)>>1)&0x7)
+
+/* LCR bits */
+#define WORD_LENGTH(n) (((n)-5)&0x3)
+#define STOP_BIT_ENABLE 0x04
+#define PARITY_ENABLE 0x08
+#define EVEN_PARITY 0x10
+#define FORCE_PARITY 0x20
+#define XMIT_BREAK 0x40
+#define DLAB_ENABLE 0x80
+
+/* MCR bits */
+#define _DTR 0x01
+#define _RTS 0x02
+#define _OP1 0x04
+#define _OP2 0x08
+#define LOOP_BACK 0x10
+
+/* LSR Bits */
+#define RCVR_DATA_READY 0x01
+#define OVERRUN_ERROR 0x02
+#define PARITY_ERROR 0x04
+#define FRAMING_ERROR 0x08
+#define BREAK_INTERRUPT 0x10
+#define XMIT_HOLD_EMPTY 0x20
+#define XMIT_EMPTY 0x40
+#define FIFO_ERROR 0x80
+#define RCVR_READY(u) (_LSR(u)&RCVR_DATA_READY)
+#define XMIT_READY(u) (_LSR(u)&XMIT_HOLD_EMPTY)
+
+/* MSR bits */
+#define _RDR 0x01
+#define DELTA_DSR 0x02
+#define DELTA_RI 0x04
+#define DELTA_CD 0x08
+#define _CTS 0x10
+#define _DSR 0x20
+#define _RI 0x40
+#define _CD 0x80
+
+/* prototypes */
+void uart_init( uart_dev_t *u, int bitrate );
+void uart_out( uart_dev_t *u, char c );
+void uart_puts( uart_dev_t *u, char *s );
+char uart_in( uart_dev_t *u );
+void uart_enable_rcvr_int( uart_dev_t *u );
+void uart_disable_rcvr_int( uart_dev_t *u );
+
+#ifdef DUART16552_1_VADDR
+/* DUART present. */
+#define DUART_1_BASE (*(uart_dev_t*)DUART16552_1_VADDR)
+#define DUART_2_BASE (*(uart_dev_t*)DUART16552_2_VADDR)
+#define UART1_PUTS(s) uart_puts( &DUART_1_BASE, s )
+#define UART2_PUTS(s) uart_puts( &DUART_2_BASE, s )
+#else
+/* DUART not configured, use dummy placeholders to allow compiles to work. */
+#define DUART_1_BASE (*(uart_dev_t*)0)
+#define DUART_2_BASE (*(uart_dev_t*)0)
+#define UART1_PUTS(s)
+#define UART2_PUTS(s)
+#endif
+
+/* Compute 16-bit divisor for baudrate generator, with rounding: */
+#define DUART_DIVISOR(crystal,speed) (((crystal)/16 + (speed)/2)/(speed))
+
+#endif /*_uart_h_included_*/
+
diff --git a/include/asm-xtensa/xtensa/xt2000.h b/include/asm-xtensa/xtensa/xt2000.h
new file mode 100644
index 00000000000..703a45002f8
--- /dev/null
+++ b/include/asm-xtensa/xtensa/xt2000.h
@@ -0,0 +1,408 @@
+#ifndef _INC_XT2000_H_
+#define _INC_XT2000_H_
+
+/*
+ * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
+ *
+ * include/asm-xtensa/xtensa/xt2000.h - Definitions specific to the
+ * Tensilica XT2000 Emulation Board
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2002 Tensilica Inc.
+ */
+
+
+#include <xtensa/config/core.h>
+#include <xtensa/config/system.h>
+
+
+/*
+ * Default assignment of XT2000 devices to external interrupts.
+ */
+
+/* Ethernet interrupt: */
+#ifdef XCHAL_EXTINT3_NUM
+#define SONIC83934_INTNUM XCHAL_EXTINT3_NUM
+#define SONIC83934_INTLEVEL XCHAL_EXTINT3_LEVEL
+#define SONIC83934_INTMASK XCHAL_EXTINT3_MASK
+#else
+#define SONIC83934_INTMASK 0
+#endif
+
+/* DUART channel 1 interrupt (P1 - console): */
+#ifdef XCHAL_EXTINT4_NUM
+#define DUART16552_1_INTNUM XCHAL_EXTINT4_NUM
+#define DUART16552_1_INTLEVEL XCHAL_EXTINT4_LEVEL
+#define DUART16552_1_INTMASK XCHAL_EXTINT4_MASK
+#else
+#define DUART16552_1_INTMASK 0
+#endif
+
+/* DUART channel 2 interrupt (P2 - 2nd serial port): */
+#ifdef XCHAL_EXTINT5_NUM
+#define DUART16552_2_INTNUM XCHAL_EXTINT5_NUM
+#define DUART16552_2_INTLEVEL XCHAL_EXTINT5_LEVEL
+#define DUART16552_2_INTMASK XCHAL_EXTINT5_MASK
+#else
+#define DUART16552_2_INTMASK 0
+#endif
+
+/* FPGA-combined PCI/etc interrupts: */
+#ifdef XCHAL_EXTINT6_NUM
+#define XT2000_FPGAPCI_INTNUM XCHAL_EXTINT6_NUM
+#define XT2000_FPGAPCI_INTLEVEL XCHAL_EXTINT6_LEVEL
+#define XT2000_FPGAPCI_INTMASK XCHAL_EXTINT6_MASK
+#else
+#define XT2000_FPGAPCI_INTMASK 0
+#endif
+
+
+
+/*
+ * Device addresses.
+ *
+ * Note: for endianness-independence, use 32-bit loads and stores for all
+ * register accesses to Ethernet, DUART and LED devices. Undefined bits
+ * may need to be masked out if needed when reading if the actual register
+ * size is smaller than 32 bits.
+ *
+ * Note: XT2000 bus byte lanes are defined in terms of msbyte and lsbyte
+ * relative to the processor. So 32-bit registers are accessed consistently
+ * from both big and little endian processors. However, this means byte
+ * sequences are not consistent between big and little endian processors.
+ * This is fine for RAM, and for ROM if ROM is created for a specific
+ * processor (and thus has correct byte sequences). However this may be
+ * unexpected for Flash, which might contain a file-system that one wants
+ * to use for multiple processor configurations (eg. the Flash might contain
+ * the Ethernet card's address, endianness-independent application data, etc).
+ * That is, byte sequences written in Flash by a core of a given endianness
+ * will be byte-swapped when seen by a core of the other endianness.
+ * Someone implementing an endianness-independent Flash file system will
+ * likely handle this byte-swapping issue in the Flash driver software.
+ */
+
+#define DUART16552_XTAL_FREQ 18432000 /* crystal frequency in Hz */
+#define XTBOARD_FLASH_MAXSIZE 0x4000000 /* 64 MB (max; depends on what is socketed!) */
+#define XTBOARD_EPROM_MAXSIZE 0x0400000 /* 4 MB (max; depends on what is socketed!) */
+#define XTBOARD_EEPROM_MAXSIZE 0x0080000 /* 512 kB (max; depends on what is socketed!) */
+#define XTBOARD_ASRAM_SIZE 0x0100000 /* 1 MB */
+#define XTBOARD_PCI_MEM_SIZE 0x8000000 /* 128 MB (allocated) */
+#define XTBOARD_PCI_IO_SIZE 0x1000000 /* 16 MB (allocated) */
+
+#ifdef XSHAL_IOBLOCK_BYPASS_PADDR
+/* PCI memory space: */
+# define XTBOARD_PCI_MEM_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x0000000)
+/* Socketed Flash (eg. 2 x 16-bit devices): */
+# define XTBOARD_FLASH_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0x8000000)
+/* PCI I/O space: */
+# define XTBOARD_PCI_IO_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xC000000)
+/* V3 PCI interface chip register/config space: */
+# define XTBOARD_V3PCI_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD000000)
+/* Bus Interface registers: */
+# define XTBOARD_BUSINT_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD010000)
+/* FPGA registers: */
+# define XT2000_FPGAREGS_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD020000)
+/* SONIC SN83934 Ethernet controller/transceiver: */
+# define SONIC83934_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD030000)
+/* 8-character bitmapped LED display: */
+# define XTBOARD_LED_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD040000)
+/* National-Semi PC16552D DUART: */
+# define DUART16552_1_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD050020) /* channel 1 (P1 - console) */
+# define DUART16552_2_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD050000) /* channel 2 (P2) */
+/* Asynchronous Static RAM: */
+# define XTBOARD_ASRAM_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD400000)
+/* 8-bit EEPROM: */
+# define XTBOARD_EEPROM_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD600000)
+/* 2 x 16-bit EPROMs: */
+# define XTBOARD_EPROM_PADDR (XSHAL_IOBLOCK_BYPASS_PADDR+0xD800000)
+#endif /* XSHAL_IOBLOCK_BYPASS_PADDR */
+
+/* These devices might be accessed cached: */
+#ifdef XSHAL_IOBLOCK_CACHED_PADDR
+# define XTBOARD_PCI_MEM_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0x0000000)
+# define XTBOARD_FLASH_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0x8000000)
+# define XTBOARD_ASRAM_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0xD400000)
+# define XTBOARD_EEPROM_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0xD600000)
+# define XTBOARD_EPROM_CACHED_PADDR (XSHAL_IOBLOCK_CACHED_PADDR+0xD800000)
+#endif /* XSHAL_IOBLOCK_CACHED_PADDR */
+
+
+/*** Same thing over again, this time with virtual addresses: ***/
+
+#ifdef XSHAL_IOBLOCK_BYPASS_VADDR
+/* PCI memory space: */
+# define XTBOARD_PCI_MEM_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x0000000)
+/* Socketed Flash (eg. 2 x 16-bit devices): */
+# define XTBOARD_FLASH_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0x8000000)
+/* PCI I/O space: */
+# define XTBOARD_PCI_IO_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xC000000)
+/* V3 PCI interface chip register/config space: */
+# define XTBOARD_V3PCI_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD000000)
+/* Bus Interface registers: */
+# define XTBOARD_BUSINT_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD010000)
+/* FPGA registers: */
+# define XT2000_FPGAREGS_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD020000)
+/* SONIC SN83934 Ethernet controller/transceiver: */
+# define SONIC83934_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD030000)
+/* 8-character bitmapped LED display: */
+# define XTBOARD_LED_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD040000)
+/* National-Semi PC16552D DUART: */
+# define DUART16552_1_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD050020) /* channel 1 (P1 - console) */
+# define DUART16552_2_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD050000) /* channel 2 (P2) */
+/* Asynchronous Static RAM: */
+# define XTBOARD_ASRAM_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD400000)
+/* 8-bit EEPROM: */
+# define XTBOARD_EEPROM_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD600000)
+/* 2 x 16-bit EPROMs: */
+# define XTBOARD_EPROM_VADDR (XSHAL_IOBLOCK_BYPASS_VADDR+0xD800000)
+#endif /* XSHAL_IOBLOCK_BYPASS_VADDR */
+
+/* These devices might be accessed cached: */
+#ifdef XSHAL_IOBLOCK_CACHED_VADDR
+# define XTBOARD_PCI_MEM_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0x0000000)
+# define XTBOARD_FLASH_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0x8000000)
+# define XTBOARD_ASRAM_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0xD400000)
+# define XTBOARD_EEPROM_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0xD600000)
+# define XTBOARD_EPROM_CACHED_VADDR (XSHAL_IOBLOCK_CACHED_VADDR+0xD800000)
+#endif /* XSHAL_IOBLOCK_CACHED_VADDR */
+
+
+/* System ROM: */
+#define XTBOARD_ROM_SIZE XSHAL_ROM_SIZE
+#ifdef XSHAL_ROM_VADDR
+#define XTBOARD_ROM_VADDR XSHAL_ROM_VADDR
+#endif
+#ifdef XSHAL_ROM_PADDR
+#define XTBOARD_ROM_PADDR XSHAL_ROM_PADDR
+#endif
+
+/* System RAM: */
+#define XTBOARD_RAM_SIZE XSHAL_RAM_SIZE
+#ifdef XSHAL_RAM_VADDR
+#define XTBOARD_RAM_VADDR XSHAL_RAM_VADDR
+#endif
+#ifdef XSHAL_RAM_PADDR
+#define XTBOARD_RAM_PADDR XSHAL_RAM_PADDR
+#endif
+#define XTBOARD_RAM_BYPASS_VADDR XSHAL_RAM_BYPASS_VADDR
+#define XTBOARD_RAM_BYPASS_PADDR XSHAL_RAM_BYPASS_PADDR
+
+
+
+/*
+ * Things that depend on device addresses.
+ */
+
+
+#define XTBOARD_CACHEATTR_WRITEBACK XSHAL_XT2000_CACHEATTR_WRITEBACK
+#define XTBOARD_CACHEATTR_WRITEALLOC XSHAL_XT2000_CACHEATTR_WRITEALLOC
+#define XTBOARD_CACHEATTR_WRITETHRU XSHAL_XT2000_CACHEATTR_WRITETHRU
+#define XTBOARD_CACHEATTR_BYPASS XSHAL_XT2000_CACHEATTR_BYPASS
+#define XTBOARD_CACHEATTR_DEFAULT XSHAL_XT2000_CACHEATTR_DEFAULT
+
+#define XTBOARD_BUSINT_PIPE_REGIONS XSHAL_XT2000_PIPE_REGIONS
+#define XTBOARD_BUSINT_SDRAM_REGIONS XSHAL_XT2000_SDRAM_REGIONS
+
+
+
+/*
+ * BusLogic (FPGA) registers.
+ * All these registers are normally accessed using 32-bit loads/stores.
+ */
+
+/* Register offsets: */
+#define XT2000_DATECD_OFS 0x00 /* date code (read-only) */
+#define XT2000_STSREG_OFS 0x04 /* status (read-only) */
+#define XT2000_SYSLED_OFS 0x08 /* system LED */
+#define XT2000_WRPROT_OFS 0x0C /* write protect */
+#define XT2000_SWRST_OFS 0x10 /* software reset */
+#define XT2000_SYSRST_OFS 0x14 /* system (peripherals) reset */
+#define XT2000_IMASK_OFS 0x18 /* interrupt mask */
+#define XT2000_ISTAT_OFS 0x1C /* interrupt status */
+#define XT2000_V3CFG_OFS 0x20 /* V3 config (V320 PCI) */
+
+/* Physical register addresses: */
+#ifdef XT2000_FPGAREGS_PADDR
+#define XT2000_DATECD_PADDR (XT2000_FPGAREGS_PADDR+XT2000_DATECD_OFS)
+#define XT2000_STSREG_PADDR (XT2000_FPGAREGS_PADDR+XT2000_STSREG_OFS)
+#define XT2000_SYSLED_PADDR (XT2000_FPGAREGS_PADDR+XT2000_SYSLED_OFS)
+#define XT2000_WRPROT_PADDR (XT2000_FPGAREGS_PADDR+XT2000_WRPROT_OFS)
+#define XT2000_SWRST_PADDR (XT2000_FPGAREGS_PADDR+XT2000_SWRST_OFS)
+#define XT2000_SYSRST_PADDR (XT2000_FPGAREGS_PADDR+XT2000_SYSRST_OFS)
+#define XT2000_IMASK_PADDR (XT2000_FPGAREGS_PADDR+XT2000_IMASK_OFS)
+#define XT2000_ISTAT_PADDR (XT2000_FPGAREGS_PADDR+XT2000_ISTAT_OFS)
+#define XT2000_V3CFG_PADDR (XT2000_FPGAREGS_PADDR+XT2000_V3CFG_OFS)
+#endif
+
+/* Virtual register addresses: */
+#ifdef XT2000_FPGAREGS_VADDR
+#define XT2000_DATECD_VADDR (XT2000_FPGAREGS_VADDR+XT2000_DATECD_OFS)
+#define XT2000_STSREG_VADDR (XT2000_FPGAREGS_VADDR+XT2000_STSREG_OFS)
+#define XT2000_SYSLED_VADDR (XT2000_FPGAREGS_VADDR+XT2000_SYSLED_OFS)
+#define XT2000_WRPROT_VADDR (XT2000_FPGAREGS_VADDR+XT2000_WRPROT_OFS)
+#define XT2000_SWRST_VADDR (XT2000_FPGAREGS_VADDR+XT2000_SWRST_OFS)
+#define XT2000_SYSRST_VADDR (XT2000_FPGAREGS_VADDR+XT2000_SYSRST_OFS)
+#define XT2000_IMASK_VADDR (XT2000_FPGAREGS_VADDR+XT2000_IMASK_OFS)
+#define XT2000_ISTAT_VADDR (XT2000_FPGAREGS_VADDR+XT2000_ISTAT_OFS)
+#define XT2000_V3CFG_VADDR (XT2000_FPGAREGS_VADDR+XT2000_V3CFG_OFS)
+/* Register access (for C code): */
+#define XT2000_DATECD_REG (*(volatile unsigned*) XT2000_DATECD_VADDR)
+#define XT2000_STSREG_REG (*(volatile unsigned*) XT2000_STSREG_VADDR)
+#define XT2000_SYSLED_REG (*(volatile unsigned*) XT2000_SYSLED_VADDR)
+#define XT2000_WRPROT_REG (*(volatile unsigned*) XT2000_WRPROT_VADDR)
+#define XT2000_SWRST_REG (*(volatile unsigned*) XT2000_SWRST_VADDR)
+#define XT2000_SYSRST_REG (*(volatile unsigned*) XT2000_SYSRST_VADDR)
+#define XT2000_IMASK_REG (*(volatile unsigned*) XT2000_IMASK_VADDR)
+#define XT2000_ISTAT_REG (*(volatile unsigned*) XT2000_ISTAT_VADDR)
+#define XT2000_V3CFG_REG (*(volatile unsigned*) XT2000_V3CFG_VADDR)
+#endif
+
+/* DATECD (date code) bit fields: */
+
+/* BCD-coded month (01..12): */
+#define XT2000_DATECD_MONTH_SHIFT 24
+#define XT2000_DATECD_MONTH_BITS 8
+#define XT2000_DATECD_MONTH_MASK 0xFF000000
+/* BCD-coded day (01..31): */
+#define XT2000_DATECD_DAY_SHIFT 16
+#define XT2000_DATECD_DAY_BITS 8
+#define XT2000_DATECD_DAY_MASK 0x00FF0000
+/* BCD-coded year (2001..9999): */
+#define XT2000_DATECD_YEAR_SHIFT 0
+#define XT2000_DATECD_YEAR_BITS 16
+#define XT2000_DATECD_YEAR_MASK 0x0000FFFF
+
+/* STSREG (status) bit fields: */
+
+/* Switch SW3 setting bit fields (0=off/up, 1=on/down): */
+#define XT2000_STSREG_SW3_SHIFT 0
+#define XT2000_STSREG_SW3_BITS 4
+#define XT2000_STSREG_SW3_MASK 0x0000000F
+/* Boot-select bits of switch SW3: */
+#define XT2000_STSREG_BOOTSEL_SHIFT 0
+#define XT2000_STSREG_BOOTSEL_BITS 2
+#define XT2000_STSREG_BOOTSEL_MASK 0x00000003
+/* Boot-select values: */
+#define XT2000_STSREG_BOOTSEL_FLASH 0
+#define XT2000_STSREG_BOOTSEL_EPROM16 1
+#define XT2000_STSREG_BOOTSEL_PROM8 2
+#define XT2000_STSREG_BOOTSEL_ASRAM 3
+/* User-defined bits of switch SW3: */
+#define XT2000_STSREG_SW3_2_SHIFT 2
+#define XT2000_STSREG_SW3_2_MASK 0x00000004
+#define XT2000_STSREG_SW3_3_SHIFT 3
+#define XT2000_STSREG_SW3_3_MASK 0x00000008
+
+/* SYSLED (system LED) bit fields: */
+
+/* LED control bit (0=off, 1=on): */
+#define XT2000_SYSLED_LEDON_SHIFT 0
+#define XT2000_SYSLED_LEDON_MASK 0x00000001
+
+/* WRPROT (write protect) bit fields (0=writable, 1=write-protected [default]): */
+
+/* Flash write protect: */
+#define XT2000_WRPROT_FLWP_SHIFT 0
+#define XT2000_WRPROT_FLWP_MASK 0x00000001
+/* Reserved but present write protect bits: */
+#define XT2000_WRPROT_WRP_SHIFT 1
+#define XT2000_WRPROT_WRP_BITS 7
+#define XT2000_WRPROT_WRP_MASK 0x000000FE
+
+/* SWRST (software reset; allows s/w to generate power-on equivalent reset): */
+
+/* Software reset bits: */
+#define XT2000_SWRST_SWR_SHIFT 0
+#define XT2000_SWRST_SWR_BITS 16
+#define XT2000_SWRST_SWR_MASK 0x0000FFFF
+/* Software reset value -- writing this value resets the board: */
+#define XT2000_SWRST_RESETVALUE 0x0000DEAD
+
+/* SYSRST (system reset; controls reset of individual peripherals): */
+
+/* All-device reset: */
+#define XT2000_SYSRST_ALL_SHIFT 0
+#define XT2000_SYSRST_ALL_BITS 4
+#define XT2000_SYSRST_ALL_MASK 0x0000000F
+/* HDSP-2534 LED display reset (1=reset, 0=nothing): */
+#define XT2000_SYSRST_LED_SHIFT 0
+#define XT2000_SYSRST_LED_MASK 0x00000001
+/* Sonic DP83934 Ethernet controller reset (1=reset, 0=nothing): */
+#define XT2000_SYSRST_SONIC_SHIFT 1
+#define XT2000_SYSRST_SONIC_MASK 0x00000002
+/* DP16552 DUART reset (1=reset, 0=nothing): */
+#define XT2000_SYSRST_DUART_SHIFT 2
+#define XT2000_SYSRST_DUART_MASK 0x00000004
+/* V3 V320 PCI bridge controller reset (1=reset, 0=nothing): */
+#define XT2000_SYSRST_V3_SHIFT 3
+#define XT2000_SYSRST_V3_MASK 0x00000008
+
+/* IMASK (interrupt mask; 0=disable, 1=enable): */
+/* ISTAT (interrupt status; 0=inactive, 1=pending): */
+
+/* PCI INTP interrupt: */
+#define XT2000_INTMUX_PCI_INTP_SHIFT 2
+#define XT2000_INTMUX_PCI_INTP_MASK 0x00000004
+/* PCI INTS interrupt: */
+#define XT2000_INTMUX_PCI_INTS_SHIFT 3
+#define XT2000_INTMUX_PCI_INTS_MASK 0x00000008
+/* PCI INTD interrupt: */
+#define XT2000_INTMUX_PCI_INTD_SHIFT 4
+#define XT2000_INTMUX_PCI_INTD_MASK 0x00000010
+/* V320 PCI controller interrupt: */
+#define XT2000_INTMUX_V3_SHIFT 5
+#define XT2000_INTMUX_V3_MASK 0x00000020
+/* PCI ENUM interrupt: */
+#define XT2000_INTMUX_PCI_ENUM_SHIFT 6
+#define XT2000_INTMUX_PCI_ENUM_MASK 0x00000040
+/* PCI DEG interrupt: */
+#define XT2000_INTMUX_PCI_DEG_SHIFT 7
+#define XT2000_INTMUX_PCI_DEG_MASK 0x00000080
+
+/* V3CFG (V3 config, V320 PCI controller): */
+
+/* V3 address control (0=pass-thru, 1=V3 address bits 31:28 set to 4'b0001 [default]): */
+#define XT2000_V3CFG_V3ADC_SHIFT 0
+#define XT2000_V3CFG_V3ADC_MASK 0x00000001
+
+/* I2C Devices */
+
+#define XT2000_I2C_RTC_ID 0x68
+#define XT2000_I2C_NVRAM0_ID 0x56 /* 1st 256 byte block */
+#define XT2000_I2C_NVRAM1_ID 0x57 /* 2nd 256 byte block */
+
+/* NVRAM Board Info structure: */
+
+#define XT2000_NVRAM_SIZE 512
+
+#define XT2000_NVRAM_BINFO_START 0x100
+#define XT2000_NVRAM_BINFO_SIZE 0x20
+#define XT2000_NVRAM_BINFO_VERSION 0x10 /* version 1.0 */
+#if 0
+#define XT2000_NVRAM_BINFO_VERSION_OFFSET 0x00
+#define XT2000_NVRAM_BINFO_VERSION_SIZE 0x1
+#define XT2000_NVRAM_BINFO_ETH_ADDR_OFFSET 0x02
+#define XT2000_NVRAM_BINFO_ETH_ADDR_SIZE 0x6
+#define XT2000_NVRAM_BINFO_SN_OFFSET 0x10
+#define XT2000_NVRAM_BINFO_SN_SIZE 0xE
+#define XT2000_NVRAM_BINFO_CRC_OFFSET 0x1E
+#define XT2000_NVRAM_BINFO_CRC_SIZE 0x2
+#endif /*0*/
+
+#if !defined(__ASSEMBLY__) && !defined(_NOCLANGUAGE)
+typedef struct xt2000_nvram_binfo {
+ unsigned char version;
+ unsigned char reserved1;
+ unsigned char eth_addr[6];
+ unsigned char reserved8[8];
+ unsigned char serialno[14];
+ unsigned char crc[2]; /* 16-bit CRC */
+} xt2000_nvram_binfo;
+#endif /*!__ASSEMBLY__ && !_NOCLANGUAGE*/
+
+
+#endif /*_INC_XT2000_H_*/
+
diff --git a/include/asm-xtensa/xtensa/xtboard.h b/include/asm-xtensa/xtensa/xtboard.h
new file mode 100644
index 00000000000..22469c17530
--- /dev/null
+++ b/include/asm-xtensa/xtensa/xtboard.h
@@ -0,0 +1,120 @@
+#ifndef _xtboard_h_included_
+#define _xtboard_h_included_
+
+/*
+ * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
+ *
+ * xtboard.h -- Routines for getting useful information from the board.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2002 Tensilica Inc.
+ */
+
+
+#include <xtensa/xt2000.h>
+
+#define XTBOARD_RTC_ERROR -1
+#define XTBOARD_RTC_STOPPED -2
+
+
+/* xt2000-i2cdev.c: */
+typedef void XtboardDelayFunc( unsigned );
+extern XtboardDelayFunc* xtboard_set_nsdelay_func( XtboardDelayFunc *delay_fn );
+extern int xtboard_i2c_read (unsigned id, unsigned char *buf, unsigned addr, unsigned size);
+extern int xtboard_i2c_write(unsigned id, unsigned char *buf, unsigned addr, unsigned size);
+extern int xtboard_i2c_wait_nvram_ack(unsigned id, unsigned swtimer);
+
+/* xtboard.c: */
+extern int xtboard_nvram_read (unsigned addr, unsigned len, unsigned char *buf);
+extern int xtboard_nvram_write(unsigned addr, unsigned len, unsigned char *buf);
+extern int xtboard_nvram_binfo_read (xt2000_nvram_binfo *buf);
+extern int xtboard_nvram_binfo_write(xt2000_nvram_binfo *buf);
+extern int xtboard_nvram_binfo_valid(xt2000_nvram_binfo *buf);
+extern int xtboard_ethermac_get(unsigned char *buf);
+extern int xtboard_ethermac_set(unsigned char *buf);
+
+/*+*----------------------------------------------------------------------------
+/ Function: xtboard_get_rtc_time
+/
+/ Description: Get time stored in real-time clock.
+/
+/ Returns: time in seconds stored in real-time clock.
+/-**----------------------------------------------------------------------------*/
+
+extern unsigned xtboard_get_rtc_time(void);
+
+/*+*----------------------------------------------------------------------------
+/ Function: xtboard_set_rtc_time
+/
+/ Description: Set time stored in real-time clock.
+/
+/ Parameters: time -- time in seconds to store to real-time clock
+/
+/ Returns: 0 on success, xtboard_i2c_write() error code otherwise.
+/-**----------------------------------------------------------------------------*/
+
+extern int xtboard_set_rtc_time(unsigned time);
+
+
+/* xtfreq.c: */
+/*+*----------------------------------------------------------------------------
+/ Function: xtboard_measure_sys_clk
+/
+/ Description: Get frequency of system clock.
+/
+/ Parameters: none
+/
+/ Returns: frequency of system clock.
+/-**----------------------------------------------------------------------------*/
+
+extern unsigned xtboard_measure_sys_clk(void);
+
+
+#if 0 /* old stuff from xtboard.c: */
+
+/*+*----------------------------------------------------------------------------
+/ Function: xtboard_nvram valid
+/
+/ Description: Determines if data in NVRAM is valid.
+/
+/ Parameters: delay -- 10us delay function
+/
+/ Returns: 1 if NVRAM is valid, 0 otherwise
+/-**----------------------------------------------------------------------------*/
+
+extern unsigned xtboard_nvram_valid(void (*delay)( void ));
+
+/*+*----------------------------------------------------------------------------
+/ Function: xtboard_get_nvram_contents
+/
+/ Description: Returns contents of NVRAM.
+/
+/ Parameters: buf -- buffer to NVRAM contents.
+/ delay -- 10us delay function
+/
+/ Returns: 1 if NVRAM is valid, 0 otherwise
+/-**----------------------------------------------------------------------------*/
+
+extern unsigned xtboard_get_nvram_contents(unsigned char *buf, void (*delay)( void ));
+
+/*+*----------------------------------------------------------------------------
+/ Function: xtboard_get_ether_addr
+/
+/ Description: Returns ethernet address of board.
+/
+/ Parameters: buf -- buffer to store ethernet address
+/ delay -- 10us delay function
+/
+/ Returns: nothing.
+/-**----------------------------------------------------------------------------*/
+
+extern void xtboard_get_ether_addr(unsigned char *buf, void (*delay)( void ));
+
+#endif /*0*/
+
+
+#endif /*_xtboard_h_included_*/
+
diff --git a/include/linux/a.out.h b/include/linux/a.out.h
index af8a1dfa5c3..f913cc3e1b0 100644
--- a/include/linux/a.out.h
+++ b/include/linux/a.out.h
@@ -138,7 +138,7 @@ enum machine_type {
#endif
#endif
-#define _N_SEGMENT_ROUND(x) (((x) + SEGMENT_SIZE - 1) & ~(SEGMENT_SIZE - 1))
+#define _N_SEGMENT_ROUND(x) ALIGN(x, SEGMENT_SIZE)
#define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index aefe6d051ac..b123cc08773 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -25,6 +25,10 @@
#ifndef _LINUX_ACPI_H
#define _LINUX_ACPI_H
+#include <linux/config.h>
+
+#ifdef CONFIG_ACPI
+
#ifndef _LINUX
#define _LINUX
#endif
@@ -533,4 +537,5 @@ static inline int acpi_get_pxm(acpi_handle handle)
extern int pnpacpi_disabled;
-#endif /*_LINUX_ACPI_H*/
+#endif /* CONFIG_ACPI */
+#endif /*_LINUX_ACPI_H*/
diff --git a/include/linux/arcfb.h b/include/linux/arcfb.h
new file mode 100644
index 00000000000..721e7654dae
--- /dev/null
+++ b/include/linux/arcfb.h
@@ -0,0 +1,8 @@
+#ifndef __LINUX_ARCFB_H__
+#define __LINUX_ARCFB_H__
+
+#define FBIO_WAITEVENT _IO('F', 0x88)
+#define FBIO_GETCONTROL2 _IOR('F', 0x89, size_t)
+
+#endif
+
diff --git a/include/linux/ata.h b/include/linux/ata.h
index f178894edd0..ca5fcadf998 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -224,6 +224,7 @@ struct ata_taskfile {
};
#define ata_id_is_ata(id) (((id)[0] & (1 << 15)) == 0)
+#define ata_id_is_sata(id) ((id)[93] == 0)
#define ata_id_rahead_enabled(id) ((id)[85] & (1 << 6))
#define ata_id_wcache_enabled(id) ((id)[85] & (1 << 5))
#define ata_id_has_flush(id) ((id)[83] & (1 << 12))
diff --git a/include/linux/atalk.h b/include/linux/atalk.h
index 31d3fc25ccb..09a1451c115 100644
--- a/include/linux/atalk.h
+++ b/include/linux/atalk.h
@@ -20,7 +20,7 @@
#define SIOCATALKDIFADDR (SIOCPROTOPRIVATE + 0)
struct atalk_addr {
- __u16 s_net;
+ __be16 s_net;
__u8 s_node;
};
@@ -33,8 +33,8 @@ struct sockaddr_at {
struct atalk_netrange {
__u8 nr_phase;
- __u16 nr_firstnet;
- __u16 nr_lastnet;
+ __be16 nr_firstnet;
+ __be16 nr_lastnet;
};
#ifdef __KERNEL__
@@ -70,8 +70,8 @@ struct atalk_iface {
struct atalk_sock {
/* struct sock has to be the first member of atalk_sock */
struct sock sk;
- unsigned short dest_net;
- unsigned short src_net;
+ __be16 dest_net;
+ __be16 src_net;
unsigned char dest_node;
unsigned char src_node;
unsigned char dest_port;
@@ -95,9 +95,9 @@ struct ddpehdr {
deh_hops:4,
deh_len:10;
#endif
- __u16 deh_sum;
- __u16 deh_dnet;
- __u16 deh_snet;
+ __be16 deh_sum;
+ __be16 deh_dnet;
+ __be16 deh_snet;
__u8 deh_dnode;
__u8 deh_snode;
__u8 deh_dport;
@@ -142,24 +142,24 @@ struct ddpshdr {
/* AppleTalk AARP headers */
struct elapaarp {
- __u16 hw_type;
+ __be16 hw_type;
#define AARP_HW_TYPE_ETHERNET 1
#define AARP_HW_TYPE_TOKENRING 2
- __u16 pa_type;
+ __be16 pa_type;
__u8 hw_len;
__u8 pa_len;
#define AARP_PA_ALEN 4
- __u16 function;
+ __be16 function;
#define AARP_REQUEST 1
#define AARP_REPLY 2
#define AARP_PROBE 3
__u8 hw_src[ETH_ALEN] __attribute__ ((packed));
__u8 pa_src_zero __attribute__ ((packed));
- __u16 pa_src_net __attribute__ ((packed));
+ __be16 pa_src_net __attribute__ ((packed));
__u8 pa_src_node __attribute__ ((packed));
__u8 hw_dst[ETH_ALEN] __attribute__ ((packed));
__u8 pa_dst_zero __attribute__ ((packed));
- __u16 pa_dst_net __attribute__ ((packed));
+ __be16 pa_dst_net __attribute__ ((packed));
__u8 pa_dst_node __attribute__ ((packed));
};
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 19f04b04979..bf2ad3ba72e 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -27,15 +27,52 @@
#include <linux/sched.h>
#include <linux/elf.h>
-/* Request and reply types */
-#define AUDIT_GET 1000 /* Get status */
-#define AUDIT_SET 1001 /* Set status (enable/disable/auditd) */
-#define AUDIT_LIST 1002 /* List filtering rules */
-#define AUDIT_ADD 1003 /* Add filtering rule */
-#define AUDIT_DEL 1004 /* Delete filtering rule */
-#define AUDIT_USER 1005 /* Send a message from user-space */
-#define AUDIT_LOGIN 1006 /* Define the login id and informaiton */
-#define AUDIT_KERNEL 2000 /* Asynchronous audit record. NOT A REQUEST. */
+/* The netlink messages for the audit system is divided into blocks:
+ * 1000 - 1099 are for commanding the audit system
+ * 1100 - 1199 user space trusted application messages
+ * 1200 - 1299 messages internal to the audit daemon
+ * 1300 - 1399 audit event messages
+ * 1400 - 1499 SE Linux use
+ * 1500 - 1999 future use
+ * 2000 is for otherwise unclassified kernel audit messages
+ *
+ * Messages from 1000-1199 are bi-directional. 1200-1299 are exclusively user
+ * space. Anything over that is kernel --> user space communication.
+ */
+#define AUDIT_GET 1000 /* Get status */
+#define AUDIT_SET 1001 /* Set status (enable/disable/auditd) */
+#define AUDIT_LIST 1002 /* List syscall filtering rules */
+#define AUDIT_ADD 1003 /* Add syscall filtering rule */
+#define AUDIT_DEL 1004 /* Delete syscall filtering rule */
+#define AUDIT_USER 1005 /* Message from userspace -- deprecated */
+#define AUDIT_LOGIN 1006 /* Define the login id and information */
+#define AUDIT_WATCH_INS 1007 /* Insert file/dir watch entry */
+#define AUDIT_WATCH_REM 1008 /* Remove file/dir watch entry */
+#define AUDIT_WATCH_LIST 1009 /* List all file/dir watches */
+#define AUDIT_SIGNAL_INFO 1010 /* Get info about sender of signal to auditd */
+
+#define AUDIT_FIRST_USER_MSG 1100 /* Userspace messages uninteresting to kernel */
+#define AUDIT_LAST_USER_MSG 1199
+
+#define AUDIT_DAEMON_START 1200 /* Daemon startup record */
+#define AUDIT_DAEMON_END 1201 /* Daemon normal stop record */
+#define AUDIT_DAEMON_ABORT 1202 /* Daemon error stop record */
+#define AUDIT_DAEMON_CONFIG 1203 /* Daemon config change */
+
+#define AUDIT_SYSCALL 1300 /* Syscall event */
+#define AUDIT_FS_WATCH 1301 /* Filesystem watch event */
+#define AUDIT_PATH 1302 /* Filename path information */
+#define AUDIT_IPC 1303 /* IPC record */
+#define AUDIT_SOCKETCALL 1304 /* sys_socketcall arguments */
+#define AUDIT_CONFIG_CHANGE 1305 /* Audit system configuration change */
+#define AUDIT_SOCKADDR 1306 /* sockaddr copied as syscall arg */
+#define AUDIT_CWD 1307 /* Current working directory */
+
+#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
+#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
+#define AUDIT_AVC_PATH 1402 /* dentry, vfsmount pair from avc */
+
+#define AUDIT_KERNEL 2000 /* Asynchronous audit record. NOT A REQUEST. */
/* Rule flags */
#define AUDIT_PER_TASK 0x01 /* Apply rule at task creation (not syscall) */
@@ -132,16 +169,9 @@
#define AUDIT_ARCH_V850 (EM_V850|__AUDIT_ARCH_LE)
#define AUDIT_ARCH_X86_64 (EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
-#ifndef __KERNEL__
-struct audit_message {
- struct nlmsghdr nlh;
- char data[1200];
-};
-#endif
-
struct audit_status {
__u32 mask; /* Bit mask for valid entries */
- __u32 enabled; /* 1 = enabled, 0 = disbaled */
+ __u32 enabled; /* 1 = enabled, 0 = disabled */
__u32 failure; /* Failure-to-log action */
__u32 pid; /* pid of auditd process */
__u32 rate_limit; /* messages rate limit (per second) */
@@ -161,6 +191,11 @@ struct audit_rule { /* for AUDIT_LIST, AUDIT_ADD, and AUDIT_DEL */
#ifdef __KERNEL__
+struct audit_sig_info {
+ uid_t uid;
+ pid_t pid;
+};
+
struct audit_buffer;
struct audit_context;
struct inode;
@@ -185,11 +220,16 @@ extern void audit_inode(const char *name, const struct inode *inode);
/* Private API (for audit.c only) */
extern int audit_receive_filter(int type, int pid, int uid, int seq,
void *data, uid_t loginuid);
-extern void audit_get_stamp(struct audit_context *ctx,
- struct timespec *t, unsigned int *serial);
+extern unsigned int audit_serial(void);
+extern void auditsc_get_stamp(struct audit_context *ctx,
+ struct timespec *t, unsigned int *serial);
extern int audit_set_loginuid(struct task_struct *task, uid_t loginuid);
extern uid_t audit_get_loginuid(struct audit_context *ctx);
extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode);
+extern int audit_socketcall(int nargs, unsigned long *args);
+extern int audit_sockaddr(int len, void *addr);
+extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt);
+extern void audit_signal_info(int sig, struct task_struct *t);
#else
#define audit_alloc(t) ({ 0; })
#define audit_free(t) do { ; } while (0)
@@ -198,18 +238,24 @@ extern int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mo
#define audit_getname(n) do { ; } while (0)
#define audit_putname(n) do { ; } while (0)
#define audit_inode(n,i) do { ; } while (0)
+#define audit_receive_filter(t,p,u,s,d,l) ({ -EOPNOTSUPP; })
+#define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
#define audit_get_loginuid(c) ({ -1; })
#define audit_ipc_perms(q,u,g,m) ({ 0; })
+#define audit_socketcall(n,a) ({ 0; })
+#define audit_sockaddr(len, addr) ({ 0; })
+#define audit_avc_path(dentry, mnt) ({ 0; })
+#define audit_signal_info(s,t) do { ; } while (0)
#endif
#ifdef CONFIG_AUDIT
/* These are defined in audit.c */
/* Public API */
-extern void audit_log(struct audit_context *ctx,
+extern void audit_log(struct audit_context *ctx, int type,
const char *fmt, ...)
- __attribute__((format(printf,2,3)));
+ __attribute__((format(printf,3,4)));
-extern struct audit_buffer *audit_log_start(struct audit_context *ctx);
+extern struct audit_buffer *audit_log_start(struct audit_context *ctx,int type);
extern void audit_log_format(struct audit_buffer *ab,
const char *fmt, ...)
__attribute__((format(printf,2,3)));
@@ -229,8 +275,8 @@ extern void audit_send_reply(int pid, int seq, int type,
void *payload, int size);
extern void audit_log_lost(const char *message);
#else
-#define audit_log(t,f,...) do { ; } while (0)
-#define audit_log_start(t) ({ NULL; })
+#define audit_log(c,t,f,...) do { ; } while (0)
+#define audit_log_start(c,t) ({ NULL; })
#define audit_log_vformat(b,f,a) do { ; } while (0)
#define audit_log_format(b,f,...) do { ; } while (0)
#define audit_log_end(b) do { ; } while (0)
diff --git a/include/linux/auto_fs4.h b/include/linux/auto_fs4.h
index a1657fb9951..9343c89d843 100644
--- a/include/linux/auto_fs4.h
+++ b/include/linux/auto_fs4.h
@@ -23,7 +23,7 @@
#define AUTOFS_MIN_PROTO_VERSION 3
#define AUTOFS_MAX_PROTO_VERSION 4
-#define AUTOFS_PROTO_SUBVERSION 6
+#define AUTOFS_PROTO_SUBVERSION 7
/* Mask for expire behaviour */
#define AUTOFS_EXP_IMMEDIATE 1
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index 7e736e201c4..c1e82c51444 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -69,6 +69,11 @@ extern void remove_arg_zero(struct linux_binprm *);
extern int search_binary_handler(struct linux_binprm *,struct pt_regs *);
extern int flush_old_exec(struct linux_binprm * bprm);
+extern int suid_dumpable;
+#define SUID_DUMP_DISABLE 0 /* No setuid dumping */
+#define SUID_DUMP_USER 1 /* Dump as user of process */
+#define SUID_DUMP_ROOT 2 /* Dump as root */
+
/* Stack area protections */
#define EXSTACK_DEFAULT 0 /* Whatever the arch defaults to */
#define EXSTACK_DISABLE_X 1 /* Disable executable stacks */
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index ef1afc178c0..b54a0348a89 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -285,16 +285,12 @@ enum blk_queue_state {
Queue_up,
};
-#define BLK_TAGS_PER_LONG (sizeof(unsigned long) * 8)
-#define BLK_TAGS_MASK (BLK_TAGS_PER_LONG - 1)
-
struct blk_queue_tag {
struct request **tag_index; /* map of busy tags */
unsigned long *tag_map; /* bit map of free/busy tags */
struct list_head busy_list; /* fifo list of busy tags */
int busy; /* current depth */
int max_depth; /* what we will send to device */
- int real_max_depth; /* what the array can hold */
atomic_t refcnt; /* map can be shared */
};
@@ -396,6 +392,7 @@ struct request_queue
*/
unsigned int sg_timeout;
unsigned int sg_reserved_size;
+ int node;
struct list_head drain_list;
@@ -542,15 +539,12 @@ extern void generic_make_request(struct bio *bio);
extern void blk_put_request(struct request *);
extern void blk_end_sync_rq(struct request *rq);
extern void blk_attempt_remerge(request_queue_t *, struct request *);
-extern void __blk_attempt_remerge(request_queue_t *, struct request *);
extern struct request *blk_get_request(request_queue_t *, int, int);
-extern void blk_insert_request(request_queue_t *, struct request *, int, void *, int);
+extern void blk_insert_request(request_queue_t *, struct request *, int, void *);
extern void blk_requeue_request(request_queue_t *, struct request *);
extern void blk_plug_device(request_queue_t *);
extern int blk_remove_plug(request_queue_t *);
extern void blk_recount_segments(request_queue_t *, struct bio *);
-extern int blk_phys_contig_segment(request_queue_t *q, struct bio *, struct bio *);
-extern int blk_hw_contig_segment(request_queue_t *q, struct bio *, struct bio *);
extern int scsi_cmd_ioctl(struct file *, struct gendisk *, unsigned int, void __user *);
extern void blk_start_queue(request_queue_t *q);
extern void blk_stop_queue(request_queue_t *q);
@@ -615,6 +609,8 @@ static inline void blkdev_dequeue_request(struct request *req)
/*
* Access functions for manipulating queue properties
*/
+extern request_queue_t *blk_init_queue_node(request_fn_proc *rfn,
+ spinlock_t *lock, int node_id);
extern request_queue_t *blk_init_queue(request_fn_proc *, spinlock_t *);
extern void blk_cleanup_queue(request_queue_t *);
extern void blk_queue_make_request(request_queue_t *, make_request_fn *);
@@ -632,7 +628,6 @@ extern void blk_queue_dma_alignment(request_queue_t *, int);
extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev);
extern void blk_queue_ordered(request_queue_t *, int);
extern void blk_queue_issue_flush_fn(request_queue_t *, issue_flush_fn *);
-extern int blkdev_scsi_issue_flush_fn(request_queue_t *, struct gendisk *, sector_t *);
extern struct request *blk_start_pre_flush(request_queue_t *,struct request *);
extern int blk_complete_barrier_rq(request_queue_t *, struct request *, int);
extern int blk_complete_barrier_rq_locked(request_queue_t *, struct request *, int);
@@ -646,7 +641,8 @@ extern void blk_wait_queue_drained(request_queue_t *, int);
extern void blk_finish_queue_drain(request_queue_t *);
int blk_get_queue(request_queue_t *);
-request_queue_t *blk_alloc_queue(int);
+request_queue_t *blk_alloc_queue(int gfp_mask);
+request_queue_t *blk_alloc_queue_node(int,int);
#define blk_put_queue(q) blk_cleanup_queue((q))
/*
@@ -675,8 +671,6 @@ extern int blkdev_issue_flush(struct block_device *, sector_t *);
#define blkdev_entry_to_request(entry) list_entry((entry), struct request, queuelist)
-extern void drive_stat_acct(struct request *, int, int);
-
static inline int queue_hardsect_size(request_queue_t *q)
{
int retval = 512;
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h
index 0dd8ca1a3d5..82bd8842d11 100644
--- a/include/linux/bootmem.h
+++ b/include/linux/bootmem.h
@@ -22,6 +22,10 @@ extern unsigned long min_low_pfn;
*/
extern unsigned long max_pfn;
+#ifdef CONFIG_CRASH_DUMP
+extern unsigned long saved_max_pfn;
+#endif
+
/*
* node_bootmem_map is a map pointer - the bits represent all physical
* memory pages (including holes) on the node.
@@ -67,6 +71,15 @@ extern void * __init __alloc_bootmem_node (pg_data_t *pgdat, unsigned long size,
__alloc_bootmem_node((pgdat), (x), PAGE_SIZE, 0)
#endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */
+#ifdef CONFIG_HAVE_ARCH_ALLOC_REMAP
+extern void *alloc_remap(int nid, unsigned long size);
+#else
+static inline void *alloc_remap(int nid, unsigned long size)
+{
+ return NULL;
+}
+#endif
+
extern unsigned long __initdata nr_kernel_pages;
extern unsigned long __initdata nr_all_pages;
diff --git a/include/linux/chio.h b/include/linux/chio.h
new file mode 100644
index 00000000000..63035ae67e6
--- /dev/null
+++ b/include/linux/chio.h
@@ -0,0 +1,168 @@
+/*
+ * ioctl interface for the scsi media changer driver
+ */
+
+/* changer element types */
+#define CHET_MT 0 /* media transport element (robot) */
+#define CHET_ST 1 /* storage element (media slots) */
+#define CHET_IE 2 /* import/export element */
+#define CHET_DT 3 /* data transfer element (tape/cdrom/whatever) */
+#define CHET_V1 4 /* vendor specific #1 */
+#define CHET_V2 5 /* vendor specific #2 */
+#define CHET_V3 6 /* vendor specific #3 */
+#define CHET_V4 7 /* vendor specific #4 */
+
+
+/*
+ * CHIOGPARAMS
+ * query changer properties
+ *
+ * CHIOVGPARAMS
+ * query vendor-specific element types
+ *
+ * accessing elements works by specifing type and unit of the element.
+ * for eample, storage elements are addressed with type = CHET_ST and
+ * unit = 0 .. cp_nslots-1
+ *
+ */
+struct changer_params {
+ int cp_curpicker; /* current transport element */
+ int cp_npickers; /* number of transport elements (CHET_MT) */
+ int cp_nslots; /* number of storage elements (CHET_ST) */
+ int cp_nportals; /* number of import/export elements (CHET_IE) */
+ int cp_ndrives; /* number of data transfer elements (CHET_DT) */
+};
+struct changer_vendor_params {
+ int cvp_n1; /* number of vendor specific elems (CHET_V1) */
+ char cvp_label1[16];
+ int cvp_n2; /* number of vendor specific elems (CHET_V2) */
+ char cvp_label2[16];
+ int cvp_n3; /* number of vendor specific elems (CHET_V3) */
+ char cvp_label3[16];
+ int cvp_n4; /* number of vendor specific elems (CHET_V4) */
+ char cvp_label4[16];
+ int reserved[8];
+};
+
+
+/*
+ * CHIOMOVE
+ * move a medium from one element to another
+ */
+struct changer_move {
+ int cm_fromtype; /* type/unit of source element */
+ int cm_fromunit;
+ int cm_totype; /* type/unit of destination element */
+ int cm_tounit;
+ int cm_flags;
+};
+#define CM_INVERT 1 /* flag: rotate media (for double-sided like MOD) */
+
+
+/*
+ * CHIOEXCHANGE
+ * move one medium from element #1 to element #2,
+ * and another one from element #2 to element #3.
+ * element #1 and #3 are allowed to be identical.
+ */
+struct changer_exchange {
+ int ce_srctype; /* type/unit of element #1 */
+ int ce_srcunit;
+ int ce_fdsttype; /* type/unit of element #2 */
+ int ce_fdstunit;
+ int ce_sdsttype; /* type/unit of element #3 */
+ int ce_sdstunit;
+ int ce_flags;
+};
+#define CE_INVERT1 1
+#define CE_INVERT2 2
+
+
+/*
+ * CHIOPOSITION
+ * move the transport element (robot arm) to a specific element.
+ */
+struct changer_position {
+ int cp_type;
+ int cp_unit;
+ int cp_flags;
+};
+#define CP_INVERT 1
+
+
+/*
+ * CHIOGSTATUS
+ * get element status for all elements of a specific type
+ */
+struct changer_element_status {
+ int ces_type;
+ unsigned char *ces_data;
+};
+#define CESTATUS_FULL 0x01 /* full */
+#define CESTATUS_IMPEXP 0x02 /* media was imported (inserted by sysop) */
+#define CESTATUS_EXCEPT 0x04 /* error condition */
+#define CESTATUS_ACCESS 0x08 /* access allowed */
+#define CESTATUS_EXENAB 0x10 /* element can export media */
+#define CESTATUS_INENAB 0x20 /* element can import media */
+
+
+/*
+ * CHIOGELEM
+ * get more detailed status informtion for a single element
+ */
+struct changer_get_element {
+ int cge_type; /* type/unit */
+ int cge_unit;
+ int cge_status; /* status */
+ int cge_errno; /* errno */
+ int cge_srctype; /* source element of the last move/exchange */
+ int cge_srcunit;
+ int cge_id; /* scsi id (for data transfer elements) */
+ int cge_lun; /* scsi lun (for data transfer elements) */
+ char cge_pvoltag[36]; /* primary volume tag */
+ char cge_avoltag[36]; /* alternate volume tag */
+ int cge_flags;
+};
+/* flags */
+#define CGE_ERRNO 0x01 /* errno available */
+#define CGE_INVERT 0x02 /* media inverted */
+#define CGE_SRC 0x04 /* media src available */
+#define CGE_IDLUN 0x08 /* ID+LUN available */
+#define CGE_PVOLTAG 0x10 /* primary volume tag available */
+#define CGE_AVOLTAG 0x20 /* alternate volume tag available */
+
+
+/*
+ * CHIOSVOLTAG
+ * set volume tag
+ */
+struct changer_set_voltag {
+ int csv_type; /* type/unit */
+ int csv_unit;
+ char csv_voltag[36]; /* volume tag */
+ int csv_flags;
+};
+#define CSV_PVOLTAG 0x01 /* primary volume tag */
+#define CSV_AVOLTAG 0x02 /* alternate volume tag */
+#define CSV_CLEARTAG 0x04 /* clear volume tag */
+
+/* ioctls */
+#define CHIOMOVE _IOW('c', 1,struct changer_move)
+#define CHIOEXCHANGE _IOW('c', 2,struct changer_exchange)
+#define CHIOPOSITION _IOW('c', 3,struct changer_position)
+#define CHIOGPICKER _IOR('c', 4,int) /* not impl. */
+#define CHIOSPICKER _IOW('c', 5,int) /* not impl. */
+#define CHIOGPARAMS _IOR('c', 6,struct changer_params)
+#define CHIOGSTATUS _IOW('c', 8,struct changer_element_status)
+#define CHIOGELEM _IOW('c',16,struct changer_get_element)
+#define CHIOINITELEM _IO('c',17)
+#define CHIOSVOLTAG _IOW('c',18,struct changer_set_voltag)
+#define CHIOGVPARAMS _IOR('c',19,struct changer_vendor_params)
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index fe0298e5dae..e8904c0da68 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -69,6 +69,7 @@ extern struct semaphore cpucontrol;
register_cpu_notifier(&fn##_nb); \
}
int cpu_down(unsigned int cpu);
+extern int __attribute__((weak)) smp_prepare_cpu(int cpu);
#define cpu_is_offline(cpu) unlikely(!cpu_online(cpu))
#else
#define lock_cpu_hotplug() do { } while (0)
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index f21af067d01..927daa86c9b 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -49,7 +49,7 @@ int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list);
/* Frequency values here are CPU kHz so that hardware which doesn't run
* with some frequencies can complain without having to guess what per
* cent / per mille means.
- * Maximum transition latency is in microseconds - if it's unknown,
+ * Maximum transition latency is in nanoseconds - if it's unknown,
* CPUFREQ_ETERNAL shall be used.
*/
diff --git a/include/linux/crash_dump.h b/include/linux/crash_dump.h
new file mode 100644
index 00000000000..534d750d922
--- /dev/null
+++ b/include/linux/crash_dump.h
@@ -0,0 +1,18 @@
+#ifndef LINUX_CRASH_DUMP_H
+#define LINUX_CRASH_DUMP_H
+
+#ifdef CONFIG_CRASH_DUMP
+#include <linux/kexec.h>
+#include <linux/smp_lock.h>
+#include <linux/device.h>
+#include <linux/proc_fs.h>
+
+#define ELFCORE_ADDR_MAX (-1ULL)
+extern unsigned long long elfcorehdr_addr;
+extern ssize_t copy_oldmem_page(unsigned long, char *, size_t,
+ unsigned long, int);
+extern struct file_operations proc_vmcore_operations;
+extern struct proc_dir_entry *proc_vmcore;
+
+#endif /* CONFIG_CRASH_DUMP */
+#endif /* LINUX_CRASHDUMP_H */
diff --git a/include/linux/device.h b/include/linux/device.h
index cf470459fa6..7b781a72b29 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -14,6 +14,7 @@
#include <linux/config.h>
#include <linux/ioport.h>
#include <linux/kobject.h>
+#include <linux/klist.h>
#include <linux/list.h>
#include <linux/types.h>
#include <linux/module.h>
@@ -44,14 +45,15 @@ struct device;
struct device_driver;
struct class;
struct class_device;
-struct class_simple;
struct bus_type {
- char * name;
+ const char * name;
struct subsystem subsys;
struct kset drivers;
struct kset devices;
+ struct klist klist_devices;
+ struct klist klist_drivers;
struct bus_attribute * bus_attrs;
struct device_attribute * dev_attrs;
@@ -98,17 +100,18 @@ extern int bus_create_file(struct bus_type *, struct bus_attribute *);
extern void bus_remove_file(struct bus_type *, struct bus_attribute *);
struct device_driver {
- char * name;
+ const char * name;
struct bus_type * bus;
struct completion unloaded;
struct kobject kobj;
- struct list_head devices;
+ struct klist klist_devices;
+ struct klist_node knode_bus;
- struct module * owner;
+ struct module * owner;
int (*probe) (struct device * dev);
- int (*remove) (struct device * dev);
+ int (*remove) (struct device * dev);
void (*shutdown) (struct device * dev);
int (*suspend) (struct device * dev, pm_message_t state, u32 level);
int (*resume) (struct device * dev, u32 level);
@@ -137,12 +140,16 @@ struct driver_attribute driver_attr_##_name = __ATTR(_name,_mode,_show,_store)
extern int driver_create_file(struct device_driver *, struct driver_attribute *);
extern void driver_remove_file(struct device_driver *, struct driver_attribute *);
+extern int driver_for_each_device(struct device_driver * drv, struct device * start,
+ void * data, int (*fn)(struct device *, void *));
+
/*
* device classes
*/
struct class {
- char * name;
+ const char * name;
+ struct module * owner;
struct subsystem subsys;
struct list_head children;
@@ -185,6 +192,7 @@ struct class_device {
struct kobject kobj;
struct class * class; /* required */
dev_t devt; /* dev_t, creates the sysfs "dev" */
+ struct class_device_attribute *devt_attr;
struct device * dev; /* not necessary, but nice to have */
void * class_data; /* class-specific data */
@@ -245,26 +253,28 @@ struct class_interface {
extern int class_interface_register(struct class_interface *);
extern void class_interface_unregister(struct class_interface *);
-/* interface for class simple stuff */
-extern struct class_simple *class_simple_create(struct module *owner, char *name);
-extern void class_simple_destroy(struct class_simple *cs);
-extern struct class_device *class_simple_device_add(struct class_simple *cs, dev_t dev, struct device *device, const char *fmt, ...)
- __attribute__((format(printf,4,5)));
-extern int class_simple_set_hotplug(struct class_simple *,
- int (*hotplug)(struct class_device *dev, char **envp, int num_envp, char *buffer, int buffer_size));
-extern void class_simple_device_remove(dev_t dev);
+extern struct class *class_create(struct module *owner, char *name);
+extern void class_destroy(struct class *cls);
+extern struct class_device *class_device_create(struct class *cls, dev_t devt,
+ struct device *device, char *fmt, ...)
+ __attribute__((format(printf,4,5)));
+extern void class_device_destroy(struct class *cls, dev_t devt);
struct device {
- struct list_head node; /* node in sibling list */
- struct list_head bus_list; /* node in bus's list */
- struct list_head driver_list;
- struct list_head children;
+ struct klist klist_children;
+ struct klist_node knode_parent; /* node in sibling list */
+ struct klist_node knode_driver;
+ struct klist_node knode_bus;
struct device * parent;
struct kobject kobj;
char bus_id[BUS_ID_SIZE]; /* position on parent bus */
+ struct semaphore sem; /* semaphore to synchronize calls to
+ * its driver.
+ */
+
struct bus_type * bus; /* type of bus device is on */
struct device_driver *driver; /* which driver has allocated this
device */
@@ -273,9 +283,6 @@ struct device {
BIOS data relevant to device) */
struct dev_pm_info power;
- u32 detach_state; /* State to enter when device is
- detached from its driver. */
-
u64 *dma_mask; /* dma mask (if dma'able device) */
u64 coherent_dma_mask;/* Like dma_mask, but for
alloc_coherent mappings as
@@ -291,12 +298,6 @@ struct device {
void (*release)(struct device * dev);
};
-static inline struct device *
-list_to_dev(struct list_head *node)
-{
- return list_entry(node, struct device, node);
-}
-
static inline void *
dev_get_drvdata (struct device *dev)
{
@@ -324,7 +325,6 @@ extern int device_for_each_child(struct device *, void *,
* Manual binding of a device to driver. See drivers/base/bus.c
* for information on use.
*/
-extern int driver_probe_device(struct device_driver * drv, struct device * dev);
extern void device_bind_driver(struct device * dev);
extern void device_release_driver(struct device * dev);
extern int device_attach(struct device * dev);
@@ -335,8 +335,10 @@ extern void driver_attach(struct device_driver * drv);
struct device_attribute {
struct attribute attr;
- ssize_t (*show)(struct device * dev, char * buf);
- ssize_t (*store)(struct device * dev, const char * buf, size_t count);
+ ssize_t (*show)(struct device *dev, struct device_attribute *attr,
+ char *buf);
+ ssize_t (*store)(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count);
};
#define DEVICE_ATTR(_name,_mode,_show,_store) \
@@ -363,13 +365,12 @@ extern int (*platform_notify_remove)(struct device * dev);
*/
extern struct device * get_device(struct device * dev);
extern void put_device(struct device * dev);
-extern struct device *device_find(const char *name, struct bus_type *bus);
/* drivers/base/platform.c */
struct platform_device {
- char * name;
+ const char * name;
u32 id;
struct device dev;
u32 num_resources;
diff --git a/include/linux/dm9000.h b/include/linux/dm9000.h
new file mode 100644
index 00000000000..0008e2ad0c9
--- /dev/null
+++ b/include/linux/dm9000.h
@@ -0,0 +1,36 @@
+/* include/linux/dm9000.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ * Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for dm9000 platform data
+ *
+ * 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.
+ *
+*/
+
+#ifndef __DM9000_PLATFORM_DATA
+#define __DM9000_PLATFORM_DATA __FILE__
+
+/* IO control flags */
+
+#define DM9000_PLATF_8BITONLY (0x0001)
+#define DM9000_PLATF_16BITONLY (0x0002)
+#define DM9000_PLATF_32BITONLY (0x0004)
+
+/* platfrom data for platfrom device structure's platfrom_data field */
+
+struct dm9000_plat_data {
+ unsigned int flags;
+
+ /* allow replacement IO routines */
+
+ void (*inblk)(void __iomem *reg, void *data, int len);
+ void (*outblk)(void __iomem *reg, void *data, int len);
+ void (*dumpblk)(void __iomem *reg, int len);
+};
+
+#endif /* __DM9000_PLATFORM_DATA */
+
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 806c305332c..2d80cc761a1 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -14,7 +14,12 @@ enum dma_data_direction {
};
#define DMA_64BIT_MASK 0xffffffffffffffffULL
+#define DMA_40BIT_MASK 0x000000ffffffffffULL
+#define DMA_39BIT_MASK 0x0000007fffffffffULL
#define DMA_32BIT_MASK 0x00000000ffffffffULL
+#define DMA_31BIT_MASK 0x000000007fffffffULL
+#define DMA_30BIT_MASK 0x000000003fffffffULL
+#define DMA_29BIT_MASK 0x000000001fffffffULL
#include <asm/dma-mapping.h>
diff --git a/include/linux/dmi.h b/include/linux/dmi.h
index d2bcf556088..5e93e6dce9a 100644
--- a/include/linux/dmi.h
+++ b/include/linux/dmi.h
@@ -9,6 +9,7 @@ enum dmi_field {
DMI_SYS_VENDOR,
DMI_PRODUCT_NAME,
DMI_PRODUCT_VERSION,
+ DMI_PRODUCT_SERIAL,
DMI_BOARD_VENDOR,
DMI_BOARD_NAME,
DMI_BOARD_VERSION,
diff --git a/include/linux/dqblk_v1.h b/include/linux/dqblk_v1.h
index 42fbf479715..57f1250d5a5 100644
--- a/include/linux/dqblk_v1.h
+++ b/include/linux/dqblk_v1.h
@@ -11,6 +11,12 @@
/* Root squash turned on */
#define V1_DQF_RSQUASH 1
+/* Numbers of blocks needed for updates */
+#define V1_INIT_ALLOC 1
+#define V1_INIT_REWRITE 1
+#define V1_DEL_ALLOC 0
+#define V1_DEL_REWRITE 2
+
/* Special information about quotafile */
struct v1_mem_dqinfo {
};
diff --git a/include/linux/dqblk_v2.h b/include/linux/dqblk_v2.h
index 4a6c5f6867b..4f853322cb7 100644
--- a/include/linux/dqblk_v2.h
+++ b/include/linux/dqblk_v2.h
@@ -10,6 +10,12 @@
/* id numbers of quota format */
#define QFMT_VFS_V0 2
+/* Numbers of blocks needed for updates */
+#define V2_INIT_ALLOC 4
+#define V2_INIT_REWRITE 2
+#define V2_DEL_ALLOC 0
+#define V2_DEL_REWRITE 6
+
/* Inmemory copy of version specific information */
struct v2_mem_dqinfo {
unsigned int dqi_blocks;
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 047e7222df7..73781ec165b 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -315,7 +315,7 @@ extern struct efi_memory_map memmap;
*/
static inline int efi_range_is_wc(unsigned long start, unsigned long len)
{
- int i;
+ unsigned long i;
for (i = 0; i < len; i += (1UL << EFI_PAGE_SHIFT)) {
unsigned long paddr = __pa(start + i);
diff --git a/include/linux/err.h b/include/linux/err.h
index 17c55df1361..ff71d2af5da 100644
--- a/include/linux/err.h
+++ b/include/linux/err.h
@@ -13,6 +13,8 @@
* This should be a per-architecture thing, to allow different
* error and pointer decisions.
*/
+#define IS_ERR_VALUE(x) unlikely((x) > (unsigned long)-1000L)
+
static inline void *ERR_PTR(long error)
{
return (void *) error;
@@ -25,7 +27,7 @@ static inline long PTR_ERR(const void *ptr)
static inline long IS_ERR(const void *ptr)
{
- return unlikely((unsigned long)ptr > (unsigned long)-1000L);
+ return IS_ERR_VALUE((unsigned long)ptr);
}
#endif /* _LINUX_ERR_H */
diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index 220748b7abe..a1478258d00 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -56,18 +56,32 @@ static inline int is_zero_ether_addr(const u8 *addr)
}
/**
+ * is_multicast_ether_addr - Determine if the given Ethernet address is a
+ * multicast address.
+ *
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Return true if the address is a multicast address.
+ */
+static inline int is_multicast_ether_addr(const u8 *addr)
+{
+ return addr[0] & 0x01;
+}
+
+/**
* is_valid_ether_addr - Determine if the given Ethernet address is valid
* @addr: Pointer to a six-byte array containing the Ethernet address
*
* Check that the Ethernet address (MAC) is not 00:00:00:00:00:00, is not
- * a multicast address, and is not FF:FF:FF:FF:FF:FF. The multicast
- * and FF:FF:... tests are combined into the single test "!(addr[0]&1)".
+ * a multicast address, and is not FF:FF:FF:FF:FF:FF.
*
* Return true if the address is valid.
*/
static inline int is_valid_ether_addr(const u8 *addr)
{
- return !(addr[0]&1) && !is_zero_ether_addr(addr);
+ /* FF:FF:FF:FF:FF:FF is a multicast address so we don't need to
+ * explicitly check for it here. */
+ return !is_multicast_ether_addr(addr) && !is_zero_ether_addr(addr);
}
/**
@@ -83,6 +97,6 @@ static inline void random_ether_addr(u8 *addr)
addr [0] &= 0xfe; /* clear multicast bit */
addr [0] |= 0x02; /* set local assignment bit (IEEE802) */
}
-#endif
+#endif /* __KERNEL__ */
#endif /* _LINUX_ETHERDEVICE_H */
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index c85b210490e..a0ab26aab45 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -256,6 +256,7 @@ struct net_device;
u32 ethtool_op_get_link(struct net_device *dev);
u32 ethtool_op_get_tx_csum(struct net_device *dev);
int ethtool_op_set_tx_csum(struct net_device *dev, u32 data);
+int ethtool_op_set_tx_hw_csum(struct net_device *dev, u32 data);
u32 ethtool_op_get_sg(struct net_device *dev);
int ethtool_op_set_sg(struct net_device *dev, u32 data);
u32 ethtool_op_get_tso(struct net_device *dev);
diff --git a/include/linux/ext2_fs.h b/include/linux/ext2_fs.h
index fab43527e59..a657130ba03 100644
--- a/include/linux/ext2_fs.h
+++ b/include/linux/ext2_fs.h
@@ -300,18 +300,19 @@ struct ext2_inode {
/*
* Mount flags
*/
-#define EXT2_MOUNT_CHECK 0x0001 /* Do mount-time checks */
-#define EXT2_MOUNT_OLDALLOC 0x0002 /* Don't use the new Orlov allocator */
-#define EXT2_MOUNT_GRPID 0x0004 /* Create files with directory's group */
-#define EXT2_MOUNT_DEBUG 0x0008 /* Some debugging messages */
-#define EXT2_MOUNT_ERRORS_CONT 0x0010 /* Continue on errors */
-#define EXT2_MOUNT_ERRORS_RO 0x0020 /* Remount fs ro on errors */
-#define EXT2_MOUNT_ERRORS_PANIC 0x0040 /* Panic on errors */
-#define EXT2_MOUNT_MINIX_DF 0x0080 /* Mimics the Minix statfs */
-#define EXT2_MOUNT_NOBH 0x0100 /* No buffer_heads */
-#define EXT2_MOUNT_NO_UID32 0x0200 /* Disable 32-bit UIDs */
-#define EXT2_MOUNT_XATTR_USER 0x4000 /* Extended user attributes */
-#define EXT2_MOUNT_POSIX_ACL 0x8000 /* POSIX Access Control Lists */
+#define EXT2_MOUNT_CHECK 0x000001 /* Do mount-time checks */
+#define EXT2_MOUNT_OLDALLOC 0x000002 /* Don't use the new Orlov allocator */
+#define EXT2_MOUNT_GRPID 0x000004 /* Create files with directory's group */
+#define EXT2_MOUNT_DEBUG 0x000008 /* Some debugging messages */
+#define EXT2_MOUNT_ERRORS_CONT 0x000010 /* Continue on errors */
+#define EXT2_MOUNT_ERRORS_RO 0x000020 /* Remount fs ro on errors */
+#define EXT2_MOUNT_ERRORS_PANIC 0x000040 /* Panic on errors */
+#define EXT2_MOUNT_MINIX_DF 0x000080 /* Mimics the Minix statfs */
+#define EXT2_MOUNT_NOBH 0x000100 /* No buffer_heads */
+#define EXT2_MOUNT_NO_UID32 0x000200 /* Disable 32-bit UIDs */
+#define EXT2_MOUNT_XATTR_USER 0x004000 /* Extended user attributes */
+#define EXT2_MOUNT_POSIX_ACL 0x008000 /* POSIX Access Control Lists */
+#define EXT2_MOUNT_XIP 0x010000 /* Execute in place */
#define clear_opt(o, opt) o &= ~EXT2_MOUNT_##opt
#define set_opt(o, opt) o |= EXT2_MOUNT_##opt
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index 74ad31781e3..4b6e1ab216a 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -358,6 +358,7 @@ struct ext3_inode {
#define EXT3_MOUNT_RESERVATION 0x10000 /* Preallocation */
#define EXT3_MOUNT_BARRIER 0x20000 /* Use block barriers */
#define EXT3_MOUNT_NOBH 0x40000 /* No bufferheads */
+#define EXT3_MOUNT_QUOTA 0x80000 /* Some quota option set */
/* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
#ifndef _LINUX_EXT2_FS_H
diff --git a/include/linux/ext3_jbd.h b/include/linux/ext3_jbd.h
index e8292af9033..c8307c02dd0 100644
--- a/include/linux/ext3_jbd.h
+++ b/include/linux/ext3_jbd.h
@@ -42,15 +42,15 @@
* superblock only gets updated once, of course, so don't bother
* counting that again for the quota updates. */
-#define EXT3_DATA_TRANS_BLOCKS (EXT3_SINGLEDATA_TRANS_BLOCKS + \
+#define EXT3_DATA_TRANS_BLOCKS(sb) (EXT3_SINGLEDATA_TRANS_BLOCKS + \
EXT3_XATTR_TRANS_BLOCKS - 2 + \
- 2*EXT3_QUOTA_TRANS_BLOCKS)
+ 2*EXT3_QUOTA_TRANS_BLOCKS(sb))
/* Delete operations potentially hit one directory's namespace plus an
* entire inode, plus arbitrary amounts of bitmap/indirection data. Be
* generous. We can grow the delete transaction later if necessary. */
-#define EXT3_DELETE_TRANS_BLOCKS (2 * EXT3_DATA_TRANS_BLOCKS + 64)
+#define EXT3_DELETE_TRANS_BLOCKS(sb) (2 * EXT3_DATA_TRANS_BLOCKS(sb) + 64)
/* Define an arbitrary limit for the amount of data we will anticipate
* writing to any given transaction. For unbounded transactions such as
@@ -74,14 +74,17 @@
#ifdef CONFIG_QUOTA
/* Amount of blocks needed for quota update - we know that the structure was
* allocated so we need to update only inode+data */
-#define EXT3_QUOTA_TRANS_BLOCKS 2
+#define EXT3_QUOTA_TRANS_BLOCKS(sb) (test_opt(sb, QUOTA) ? 2 : 0)
/* Amount of blocks needed for quota insert/delete - we do some block writes
* but inode, sb and group updates are done only once */
-#define EXT3_QUOTA_INIT_BLOCKS (DQUOT_MAX_WRITES*\
- (EXT3_SINGLEDATA_TRANS_BLOCKS-3)+3)
+#define EXT3_QUOTA_INIT_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_INIT_ALLOC*\
+ (EXT3_SINGLEDATA_TRANS_BLOCKS-3)+3+DQUOT_INIT_REWRITE) : 0)
+#define EXT3_QUOTA_DEL_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_DEL_ALLOC*\
+ (EXT3_SINGLEDATA_TRANS_BLOCKS-3)+3+DQUOT_DEL_REWRITE) : 0)
#else
-#define EXT3_QUOTA_TRANS_BLOCKS 0
-#define EXT3_QUOTA_INIT_BLOCKS 0
+#define EXT3_QUOTA_TRANS_BLOCKS(sb) 0
+#define EXT3_QUOTA_INIT_BLOCKS(sb) 0
+#define EXT3_QUOTA_DEL_BLOCKS(sb) 0
#endif
int
diff --git a/include/linux/fb.h b/include/linux/fb.h
index b468bf49654..bc24beeed97 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -524,11 +524,11 @@ struct fb_pixmap {
u32 offset; /* current offset to buffer */
u32 buf_align; /* byte alignment of each bitmap */
u32 scan_align; /* alignment per scanline */
- u32 access_align; /* alignment per read/write */
+ u32 access_align; /* alignment per read/write (bits) */
u32 flags; /* see FB_PIXMAP_* */
/* access methods */
- void (*outbuf)(struct fb_info *info, u8 *addr, u8 *src, unsigned int size);
- u8 (*inbuf) (struct fb_info *info, u8 *addr);
+ void (*writeio)(struct fb_info *info, void __iomem *dst, void *src, unsigned int size);
+ void (*readio) (struct fb_info *info, void *dst, void __iomem *src, unsigned int size);
};
@@ -816,18 +816,9 @@ extern int unregister_framebuffer(struct fb_info *fb_info);
extern int fb_prepare_logo(struct fb_info *fb_info);
extern int fb_show_logo(struct fb_info *fb_info);
extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size);
-extern void fb_iomove_buf_unaligned(struct fb_info *info, struct fb_pixmap *buf,
- u8 *dst, u32 d_pitch, u8 *src, u32 idx,
+extern void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx,
u32 height, u32 shift_high, u32 shift_low, u32 mod);
-extern void fb_iomove_buf_aligned(struct fb_info *info, struct fb_pixmap *buf,
- u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch,
- u32 height);
-extern void fb_sysmove_buf_unaligned(struct fb_info *info, struct fb_pixmap *buf,
- u8 *dst, u32 d_pitch, u8 *src, u32 idx,
- u32 height, u32 shift_high, u32 shift_low, u32 mod);
-extern void fb_sysmove_buf_aligned(struct fb_info *info, struct fb_pixmap *buf,
- u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch,
- u32 height);
+extern void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height);
extern void fb_set_suspend(struct fb_info *info, int state);
extern int fb_get_color_depth(struct fb_var_screeninfo *var);
extern int fb_get_options(char *name, char **option);
diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h
index 704fb76b633..8a7c82151de 100644
--- a/include/linux/fcntl.h
+++ b/include/linux/fcntl.h
@@ -25,6 +25,10 @@
#ifdef __KERNEL__
+#ifndef force_o_largefile
+#define force_o_largefile() (BITS_PER_LONG != 32)
+#endif
+
#if BITS_PER_LONG == 32
#define IS_GETLK32(cmd) ((cmd) == F_GETLK)
#define IS_SETLK32(cmd) ((cmd) == F_SETLK)
diff --git a/include/linux/font.h b/include/linux/font.h
index fc2d690c9d5..8fc80a7d78a 100644
--- a/include/linux/font.h
+++ b/include/linux/font.h
@@ -25,19 +25,23 @@ struct font_desc {
#define VGA8x16_IDX 1
#define PEARL8x8_IDX 2
#define VGA6x11_IDX 3
-#define SUN8x16_IDX 4
-#define SUN12x22_IDX 5
-#define ACORN8x8_IDX 6
-#define MINI4x6_IDX 7
+#define FONT7x14_IDX 4
+#define FONT10x18_IDX 5
+#define SUN8x16_IDX 6
+#define SUN12x22_IDX 7
+#define ACORN8x8_IDX 8
+#define MINI4x6_IDX 9
extern struct font_desc font_vga_8x8,
- font_vga_8x16,
- font_pearl_8x8,
- font_vga_6x11,
- font_sun_8x16,
- font_sun_12x22,
- font_acorn_8x8,
- font_mini_4x6;
+ font_vga_8x16,
+ font_pearl_8x8,
+ font_vga_6x11,
+ font_7x14,
+ font_10x18,
+ font_sun_8x16,
+ font_sun_12x22,
+ font_acorn_8x8,
+ font_mini_4x6;
/* Find a font with a specific name */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 0180102dace..3ae8e37bdfc 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -220,6 +220,7 @@ extern int dir_notify_enable;
struct iovec;
struct nameidata;
+struct kiocb;
struct pipe_inode_info;
struct poll_table_struct;
struct kstatfs;
@@ -240,7 +241,7 @@ typedef int (get_block_t)(struct inode *inode, sector_t iblock,
typedef int (get_blocks_t)(struct inode *inode, sector_t iblock,
unsigned long max_blocks,
struct buffer_head *bh_result, int create);
-typedef void (dio_iodone_t)(struct inode *inode, loff_t offset,
+typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
ssize_t bytes, void *private);
/*
@@ -302,7 +303,6 @@ struct iattr {
struct page;
struct address_space;
struct writeback_control;
-struct kiocb;
struct address_space_operations {
int (*writepage)(struct page *page, struct writeback_control *wbc);
@@ -330,6 +330,8 @@ struct address_space_operations {
int (*releasepage) (struct page *, int);
ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
loff_t offset, unsigned long nr_segs);
+ struct page* (*get_xip_page)(struct address_space *, sector_t,
+ int);
};
struct backing_dev_info;
@@ -581,7 +583,6 @@ struct file {
atomic_t f_count;
unsigned int f_flags;
mode_t f_mode;
- int f_error;
loff_t f_pos;
struct fown_struct f_owner;
unsigned int f_uid, f_gid;
@@ -674,6 +675,7 @@ struct file_lock {
struct lock_manager_operations *fl_lmops; /* Callbacks for lockmanagers */
union {
struct nfs_lock_info nfs_fl;
+ struct nfs4_lock_info nfs4_fl;
} fl_u;
};
@@ -883,7 +885,9 @@ struct block_device_operations {
int (*open) (struct inode *, struct file *);
int (*release) (struct inode *, struct file *);
int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);
+ long (*unlocked_ioctl) (struct file *, unsigned, unsigned long);
long (*compat_ioctl) (struct file *, unsigned, unsigned long);
+ int (*direct_access) (struct block_device *, sector_t, unsigned long *);
int (*media_changed) (struct gendisk *);
int (*revalidate_disk) (struct gendisk *);
struct module *owner;
@@ -1024,6 +1028,7 @@ struct super_operations {
#define I_FREEING 16
#define I_CLEAR 32
#define I_NEW 64
+#define I_WILL_FREE 128
#define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES)
@@ -1494,6 +1499,23 @@ extern loff_t remote_llseek(struct file *file, loff_t offset, int origin);
extern int generic_file_open(struct inode * inode, struct file * filp);
extern int nonseekable_open(struct inode * inode, struct file * filp);
+#ifdef CONFIG_FS_XIP
+extern ssize_t xip_file_read(struct file *filp, char __user *buf, size_t len,
+ loff_t *ppos);
+extern ssize_t xip_file_sendfile(struct file *in_file, loff_t *ppos,
+ size_t count, read_actor_t actor,
+ void *target);
+extern int xip_file_mmap(struct file * file, struct vm_area_struct * vma);
+extern ssize_t xip_file_write(struct file *filp, const char __user *buf,
+ size_t len, loff_t *ppos);
+extern int xip_truncate_page(struct address_space *mapping, loff_t from);
+#else
+static inline int xip_truncate_page(struct address_space *mapping, loff_t from)
+{
+ return 0;
+}
+#endif
+
static inline void do_generic_file_read(struct file * filp, loff_t *ppos,
read_descriptor_t * desc,
read_actor_t actor)
@@ -1657,6 +1679,52 @@ static inline void simple_transaction_set(struct file *file, size_t n)
ar->size = n;
}
+/*
+ * simple attribute files
+ *
+ * These attributes behave similar to those in sysfs:
+ *
+ * Writing to an attribute immediately sets a value, an open file can be
+ * written to multiple times.
+ *
+ * Reading from an attribute creates a buffer from the value that might get
+ * read with multiple read calls. When the attribute has been read
+ * completely, no further read calls are possible until the file is opened
+ * again.
+ *
+ * All attributes contain a text representation of a numeric value
+ * that are accessed with the get() and set() functions.
+ */
+#define DEFINE_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt) \
+static int __fops ## _open(struct inode *inode, struct file *file) \
+{ \
+ __simple_attr_check_format(__fmt, 0ull); \
+ return simple_attr_open(inode, file, __get, __set, __fmt); \
+} \
+static struct file_operations __fops = { \
+ .owner = THIS_MODULE, \
+ .open = __fops ## _open, \
+ .release = simple_attr_close, \
+ .read = simple_attr_read, \
+ .write = simple_attr_write, \
+};
+
+static inline void __attribute__((format(printf, 1, 2)))
+__simple_attr_check_format(const char *fmt, ...)
+{
+ /* don't do anything, just let the compiler check the arguments; */
+}
+
+int simple_attr_open(struct inode *inode, struct file *file,
+ u64 (*get)(void *), void (*set)(void *, u64),
+ const char *fmt);
+int simple_attr_close(struct inode *inode, struct file *file);
+ssize_t simple_attr_read(struct file *file, char __user *buf,
+ size_t len, loff_t *ppos);
+ssize_t simple_attr_write(struct file *file, const char __user *buf,
+ size_t len, loff_t *ppos);
+
+
#ifdef CONFIG_SECURITY
static inline char *alloc_secdata(void)
{
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index faaff4c6455..70f54af87b9 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -51,6 +51,7 @@ struct gianfar_platform_data {
/* board specific information */
u32 board_flags;
+ u32 phy_flags;
u32 phyid;
u32 interruptPHY;
u8 mac_addr[6];
@@ -61,9 +62,14 @@ struct gianfar_platform_data {
#define FSL_GIANFAR_DEV_HAS_COALESCE 0x00000002
#define FSL_GIANFAR_DEV_HAS_RMON 0x00000004
#define FSL_GIANFAR_DEV_HAS_MULTI_INTR 0x00000008
+#define FSL_GIANFAR_DEV_HAS_CSUM 0x00000010
+#define FSL_GIANFAR_DEV_HAS_VLAN 0x00000020
+#define FSL_GIANFAR_DEV_HAS_EXTENDED_HASH 0x00000040
+#define FSL_GIANFAR_DEV_HAS_PADDING 0x00000080
/* Flags in gianfar_platform_data */
-#define FSL_GIANFAR_BRD_HAS_PHY_INTR 0x00000001 /* if not set use a timer */
+#define FSL_GIANFAR_BRD_HAS_PHY_INTR 0x00000001 /* set or use a timer */
+#define FSL_GIANFAR_BRD_IS_REDUCED 0x00000002 /* Set if RGMII, RMII */
struct fsl_i2c_platform_data {
/* device specific information */
diff --git a/include/linux/gameport.h b/include/linux/gameport.h
index b1272f822cf..cd623eccdbe 100644
--- a/include/linux/gameport.h
+++ b/include/linux/gameport.h
@@ -67,6 +67,8 @@ int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mo
void gameport_close(struct gameport *gameport);
void gameport_rescan(struct gameport *gameport);
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
+
void __gameport_register_port(struct gameport *gameport, struct module *owner);
static inline void gameport_register_port(struct gameport *gameport)
{
@@ -75,6 +77,29 @@ static inline void gameport_register_port(struct gameport *gameport)
void gameport_unregister_port(struct gameport *gameport);
+void gameport_set_phys(struct gameport *gameport, const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+
+#else
+
+static inline void gameport_register_port(struct gameport *gameport)
+{
+ return;
+}
+
+static inline void gameport_unregister_port(struct gameport *gameport)
+{
+ return;
+}
+
+static inline void gameport_set_phys(struct gameport *gameport,
+ const char *fmt, ...)
+{
+ return;
+}
+
+#endif
+
static inline struct gameport *gameport_allocate_port(void)
{
struct gameport *gameport = kcalloc(1, sizeof(struct gameport), GFP_KERNEL);
@@ -92,9 +117,6 @@ static inline void gameport_set_name(struct gameport *gameport, const char *name
strlcpy(gameport->name, name, sizeof(gameport->name));
}
-void gameport_set_phys(struct gameport *gameport, const char *fmt, ...)
- __attribute__ ((format (printf, 2, 3)));
-
/*
* Use the following fucntions to manipulate gameport's per-port
* driver-specific data.
diff --git a/include/linux/genalloc.h b/include/linux/genalloc.h
new file mode 100644
index 00000000000..7fd0576a445
--- /dev/null
+++ b/include/linux/genalloc.h
@@ -0,0 +1,40 @@
+/*
+ * Basic general purpose allocator for managing special purpose memory
+ * not managed by the regular kmalloc/kfree interface.
+ * Uses for this includes on-device special memory, uncached memory
+ * etc.
+ *
+ * This code is based on the buddy allocator found in the sym53c8xx_2
+ * driver, adapted for general purpose use.
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/spinlock.h>
+
+#define ALLOC_MIN_SHIFT 5 /* 32 bytes minimum */
+/*
+ * Link between free memory chunks of a given size.
+ */
+struct gen_pool_link {
+ struct gen_pool_link *next;
+};
+
+/*
+ * Memory pool descriptor.
+ */
+struct gen_pool {
+ spinlock_t lock;
+ unsigned long (*get_new_chunk)(struct gen_pool *);
+ struct gen_pool *next;
+ struct gen_pool_link *h;
+ unsigned long private;
+ int max_chunk_shift;
+};
+
+unsigned long gen_pool_alloc(struct gen_pool *poolp, int size);
+void gen_pool_free(struct gen_pool *mp, unsigned long ptr, int size);
+struct gen_pool *gen_pool_create(int nr_chunks, int max_chunk_shift,
+ unsigned long (*fp)(struct gen_pool *),
+ unsigned long data);
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 47dedaf971d..01796c41c95 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -224,7 +224,7 @@ static inline void free_disk_stats(struct gendisk *disk)
extern void disk_round_stats(struct gendisk *disk);
/* drivers/block/genhd.c */
-extern int get_blkdev_list(char *);
+extern int get_blkdev_list(char *, int);
extern void add_disk(struct gendisk *disk);
extern void del_gendisk(struct gendisk *gp);
extern void unlink_gendisk(struct gendisk *gp);
@@ -403,6 +403,7 @@ extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev);
extern void add_partition(struct gendisk *, int, sector_t, sector_t);
extern void delete_partition(struct gendisk *, int);
+extern struct gendisk *alloc_disk_node(int minors, int node_id);
extern struct gendisk *alloc_disk(int minors);
extern struct kobject *get_disk(struct gendisk *disk);
extern void put_disk(struct gendisk *disk);
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index af7407e8cfc..8d6bf608b19 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -39,6 +39,7 @@ struct vm_area_struct;
#define __GFP_COMP 0x4000u /* Add compound page metadata */
#define __GFP_ZERO 0x8000u /* Return zeroed page on success */
#define __GFP_NOMEMALLOC 0x10000u /* Don't use emergency reserves */
+#define __GFP_NORECLAIM 0x20000u /* No realy zone reclaim during allocation */
#define __GFP_BITS_SHIFT 20 /* Room for 20 __GFP_FOO bits */
#define __GFP_BITS_MASK ((1 << __GFP_BITS_SHIFT) - 1)
@@ -47,7 +48,7 @@ struct vm_area_struct;
#define GFP_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS| \
__GFP_COLD|__GFP_NOWARN|__GFP_REPEAT| \
__GFP_NOFAIL|__GFP_NORETRY|__GFP_NO_GROW|__GFP_COMP| \
- __GFP_NOMEMALLOC)
+ __GFP_NOMEMALLOC|__GFP_NORECLAIM)
#define GFP_ATOMIC (__GFP_HIGH)
#define GFP_NOIO (__GFP_WAIT)
@@ -132,5 +133,10 @@ extern void FASTCALL(free_cold_page(struct page *page));
#define free_page(addr) free_pages((addr),0)
void page_alloc_init(void);
+#ifdef CONFIG_NUMA
+void drain_remote_pages(void);
+#else
+static inline void drain_remote_pages(void) { };
+#endif
#endif /* __LINUX_GFP_H */
diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
index ebc712e9106..8336dba1897 100644
--- a/include/linux/hardirq.h
+++ b/include/linux/hardirq.h
@@ -43,13 +43,17 @@
#define __IRQ_MASK(x) ((1UL << (x))-1)
#define PREEMPT_MASK (__IRQ_MASK(PREEMPT_BITS) << PREEMPT_SHIFT)
-#define HARDIRQ_MASK (__IRQ_MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
#define SOFTIRQ_MASK (__IRQ_MASK(SOFTIRQ_BITS) << SOFTIRQ_SHIFT)
+#define HARDIRQ_MASK (__IRQ_MASK(HARDIRQ_BITS) << HARDIRQ_SHIFT)
#define PREEMPT_OFFSET (1UL << PREEMPT_SHIFT)
#define SOFTIRQ_OFFSET (1UL << SOFTIRQ_SHIFT)
#define HARDIRQ_OFFSET (1UL << HARDIRQ_SHIFT)
+#if PREEMPT_ACTIVE < (1 << (HARDIRQ_SHIFT + HARDIRQ_BITS))
+#error PREEMPT_ACTIVE is too low!
+#endif
+
#define hardirq_count() (preempt_count() & HARDIRQ_MASK)
#define softirq_count() (preempt_count() & SOFTIRQ_MASK)
#define irq_count() (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_MASK))
diff --git a/include/linux/hdlc.h b/include/linux/hdlc.h
index 503194e62fe..ed2927ef1ff 100644
--- a/include/linux/hdlc.h
+++ b/include/linux/hdlc.h
@@ -1,7 +1,7 @@
/*
* Generic HDLC support routines for Linux
*
- * Copyright (C) 1999-2003 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 1999-2005 Krzysztof Halasa <khc@pm.waw.pl>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
@@ -41,6 +41,7 @@
#define LMI_NONE 1 /* No LMI, all PVCs are static */
#define LMI_ANSI 2 /* ANSI Annex D */
#define LMI_CCITT 3 /* ITU-T Annex A */
+#define LMI_CISCO 4 /* The "original" LMI, aka Gang of Four */
#define HDLC_MAX_MTU 1500 /* Ethernet 1500 bytes */
#define HDLC_MAX_MRU (HDLC_MAX_MTU + 10 + 14 + 4) /* for ETH+VLAN over FR */
@@ -89,6 +90,7 @@ typedef struct pvc_device_struct {
unsigned int deleted: 1;
unsigned int fecn: 1;
unsigned int becn: 1;
+ unsigned int bandwidth; /* Cisco LMI reporting only */
}state;
}pvc_device;
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index 2a7e6c65c88..6bece9280eb 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -28,6 +28,7 @@ static inline void *kmap(struct page *page)
#define kmap_atomic(page, idx) page_address(page)
#define kunmap_atomic(addr, idx) do { } while (0)
+#define kmap_atomic_pfn(pfn, idx) page_address(pfn_to_page(pfn))
#define kmap_atomic_to_page(ptr) virt_to_page(ptr)
#endif /* CONFIG_HIGHMEM */
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 6af1ae4a821..f529d144281 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -4,6 +4,7 @@
#ifdef CONFIG_HUGETLB_PAGE
#include <linux/mempolicy.h>
+#include <asm/tlbflush.h>
struct ctl_table;
@@ -22,12 +23,6 @@ int hugetlb_report_meminfo(char *);
int hugetlb_report_node_meminfo(int, char *);
int is_hugepage_mem_enough(size_t);
unsigned long hugetlb_total_pages(void);
-struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address,
- int write);
-struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
- pmd_t *pmd, int write);
-int is_aligned_hugepage_range(unsigned long addr, unsigned long len);
-int pmd_huge(pmd_t pmd);
struct page *alloc_huge_page(void);
void free_huge_page(struct page *);
@@ -35,6 +30,17 @@ extern unsigned long max_huge_pages;
extern const unsigned long hugetlb_zero, hugetlb_infinity;
extern int sysctl_hugetlb_shm_group;
+/* arch callbacks */
+
+pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr);
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr);
+struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address,
+ int write);
+struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
+ pmd_t *pmd, int write);
+int is_aligned_hugepage_range(unsigned long addr, unsigned long len);
+int pmd_huge(pmd_t pmd);
+
#ifndef ARCH_HAS_HUGEPAGE_ONLY_RANGE
#define is_hugepage_only_range(mm, addr, len) 0
#define hugetlb_free_pgd_range(tlb, addr, end, floor, ceiling) \
@@ -48,6 +54,28 @@ extern int sysctl_hugetlb_shm_group;
int prepare_hugepage_range(unsigned long addr, unsigned long len);
#endif
+#ifndef ARCH_HAS_SETCLEAR_HUGE_PTE
+#define set_huge_pte_at(mm, addr, ptep, pte) set_pte_at(mm, addr, ptep, pte)
+#define huge_ptep_get_and_clear(mm, addr, ptep) ptep_get_and_clear(mm, addr, ptep)
+#else
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pte);
+pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep);
+#endif
+
+#ifndef ARCH_HAS_HUGETLB_PREFAULT_HOOK
+#define hugetlb_prefault_arch_hook(mm) do { } while (0)
+#else
+void hugetlb_prefault_arch_hook(struct mm_struct *mm);
+#endif
+
+#ifndef ARCH_HAS_HUGETLB_CLEAN_STALE_PGTABLE
+#define hugetlb_clean_stale_pgtable(pte) BUG()
+#else
+void hugetlb_clean_stale_pgtable(pte_t *pte);
+#endif
+
#else /* !CONFIG_HUGETLB_PAGE */
static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
diff --git a/include/linux/hwmon-sysfs.h b/include/linux/hwmon-sysfs.h
new file mode 100644
index 00000000000..1b5018a965f
--- /dev/null
+++ b/include/linux/hwmon-sysfs.h
@@ -0,0 +1,36 @@
+/*
+ * hwmon-sysfs.h - hardware monitoring chip driver sysfs defines
+ *
+ * Copyright (C) 2005 Yani Ioannou <yani.ioannou@gmail.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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef _LINUX_HWMON_SYSFS_H
+#define _LINUX_HWMON_SYSFS_H
+
+struct sensor_device_attribute{
+ struct device_attribute dev_attr;
+ int index;
+};
+#define to_sensor_dev_attr(_dev_attr) \
+ container_of(_dev_attr, struct sensor_device_attribute, dev_attr)
+
+#define SENSOR_DEVICE_ATTR(_name,_mode,_show,_store,_index) \
+struct sensor_device_attribute sensor_dev_attr_##_name = { \
+ .dev_attr = __ATTR(_name,_mode,_show,_store), \
+ .index = _index, \
+}
+
+#endif /* _LINUX_HWMON_SYSFS_H */
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index 89270ce5147..33f08258f22 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -108,6 +108,7 @@
#define I2C_DRIVERID_TDA7313 62 /* TDA7313 audio processor */
#define I2C_DRIVERID_MAX6900 63 /* MAX6900 real-time clock */
#define I2C_DRIVERID_SAA7114H 64 /* video decoder */
+#define I2C_DRIVERID_DS1374 65 /* DS1374 real time clock */
#define I2C_DRIVERID_EXP0 0xF0 /* experimental use id's */
diff --git a/include/linux/i2c-vid.h b/include/linux/i2c-vid.h
index 974835e3530..41d0635e0ba 100644
--- a/include/linux/i2c-vid.h
+++ b/include/linux/i2c-vid.h
@@ -97,3 +97,15 @@ static inline int vid_from_reg(int val, int vrm)
2050 - (val) * 50);
}
}
+
+static inline int vid_to_reg(int val, int vrm)
+{
+ switch (vrm) {
+ case 91: /* VRM 9.1 */
+ case 90: /* VRM 9.0 */
+ return ((val >= 1100) && (val <= 1850) ?
+ ((18499 - val * 10) / 25 + 5) / 10 : -1);
+ default:
+ return -1;
+ }
+}
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index ebcd745f4cd..be837b13f29 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -290,11 +290,8 @@ static inline void i2c_set_adapdata (struct i2c_adapter *dev, void *data)
*/
struct i2c_client_address_data {
unsigned short *normal_i2c;
- unsigned short *normal_i2c_range;
unsigned short *probe;
- unsigned short *probe_range;
unsigned short *ignore;
- unsigned short *ignore_range;
unsigned short *force;
};
@@ -563,24 +560,15 @@ union i2c_smbus_data {
#define I2C_CLIENT_INSMOD \
I2C_CLIENT_MODULE_PARM(probe, \
"List of adapter,address pairs to scan additionally"); \
- I2C_CLIENT_MODULE_PARM(probe_range, \
- "List of adapter,start-addr,end-addr triples to scan " \
- "additionally"); \
I2C_CLIENT_MODULE_PARM(ignore, \
"List of adapter,address pairs not to scan"); \
- I2C_CLIENT_MODULE_PARM(ignore_range, \
- "List of adapter,start-addr,end-addr triples not to " \
- "scan"); \
I2C_CLIENT_MODULE_PARM(force, \
"List of adapter,address pairs to boldly assume " \
"to be present"); \
static struct i2c_client_address_data addr_data = { \
.normal_i2c = normal_i2c, \
- .normal_i2c_range = normal_i2c_range, \
.probe = probe, \
- .probe_range = probe_range, \
.ignore = ignore, \
- .ignore_range = ignore_range, \
.force = force, \
}
diff --git a/include/linux/i2o-dev.h b/include/linux/i2o-dev.h
index ef7f644dd87..36fd18cdad2 100644
--- a/include/linux/i2o-dev.h
+++ b/include/linux/i2o-dev.h
@@ -24,6 +24,13 @@
#define MAX_I2O_CONTROLLERS 32
//#include <linux/ioctl.h>
+#ifndef __KERNEL__
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+
+#endif /* __KERNEL__ */
/*
* I2O Control IOCTLs and structures
@@ -113,6 +120,10 @@ struct i2o_evt_get {
int lost;
};
+typedef struct i2o_sg_io_hdr {
+ unsigned int flags; /* see I2O_DPT_SG_IO_FLAGS */
+} i2o_sg_io_hdr_t;
+
/**************************************************************************
* HRT related constants and structures
**************************************************************************/
@@ -126,14 +137,6 @@ struct i2o_evt_get {
#define I2O_BUS_CARDBUS 7
#define I2O_BUS_UNKNOWN 0x80
-#ifndef __KERNEL__
-
-typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned int u32;
-
-#endif /* __KERNEL__ */
-
typedef struct _i2o_pci_bus {
u8 PciFunctionNumber;
u8 PciDeviceNumber;
@@ -333,7 +336,7 @@ typedef struct _i2o_status_block {
#define I2O_CLASS_ATE_PERIPHERAL 0x061
#define I2O_CLASS_FLOPPY_CONTROLLER 0x070
#define I2O_CLASS_FLOPPY_DEVICE 0x071
-#define I2O_CLASS_BUS_ADAPTER_PORT 0x080
+#define I2O_CLASS_BUS_ADAPTER 0x080
#define I2O_CLASS_PEER_TRANSPORT_AGENT 0x090
#define I2O_CLASS_PEER_TRANSPORT 0x091
#define I2O_CLASS_END 0xfff
@@ -399,4 +402,26 @@ typedef struct _i2o_status_block {
#define ADAPTER_STATE_FAILED 0x10
#define ADAPTER_STATE_FAULTED 0x11
+/*
+ * Software module types
+ */
+#define I2O_SOFTWARE_MODULE_IRTOS 0x11
+#define I2O_SOFTWARE_MODULE_IOP_PRIVATE 0x22
+#define I2O_SOFTWARE_MODULE_IOP_CONFIG 0x23
+
+/*
+ * Vendors
+ */
+#define I2O_VENDOR_DPT 0x001b
+
+/*
+ * DPT / Adaptec specific values for i2o_sg_io_hdr flags.
+ */
+#define I2O_DPT_SG_FLAG_INTERPRET 0x00010000
+#define I2O_DPT_SG_FLAG_PHYSICAL 0x00020000
+
+#define I2O_DPT_FLASH_FRAG_SIZE 0x10000
+#define I2O_DPT_FLASH_READ 0x0101
+#define I2O_DPT_FLASH_WRITE 0x0102
+
#endif /* _I2O_DEV_H */
diff --git a/include/linux/i2o.h b/include/linux/i2o.h
index ea9a3ad4b67..bdc286ec947 100644
--- a/include/linux/i2o.h
+++ b/include/linux/i2o.h
@@ -119,12 +119,21 @@ struct i2o_driver {
};
/*
- * Contains all information which are necessary for DMA operations
+ * Contains DMA mapped address information
*/
struct i2o_dma {
void *virt;
dma_addr_t phys;
- u32 len;
+ size_t len;
+};
+
+/*
+ * Contains IO mapped address information
+ */
+struct i2o_io {
+ void __iomem *virt;
+ unsigned long phys;
+ unsigned long len;
};
/*
@@ -147,28 +156,25 @@ struct i2o_controller {
struct pci_dev *pdev; /* PCI device */
- unsigned int short_req:1; /* use small block sizes */
+ unsigned int promise:1; /* Promise controller */
+ unsigned int adaptec:1; /* DPT / Adaptec controller */
+ unsigned int raptor:1; /* split bar */
unsigned int no_quiesce:1; /* dont quiesce before reset */
- unsigned int raptor:1; /* split bar */
- unsigned int promise:1; /* Promise controller */
-
-#ifdef CONFIG_MTRR
- int mtrr_reg0;
- int mtrr_reg1;
-#endif
+ unsigned int short_req:1; /* use small block sizes */
+ unsigned int limit_sectors:1; /* limit number of sectors / request */
+ unsigned int pae_support:1; /* controller has 64-bit SGL support */
struct list_head devices; /* list of I2O devices */
-
- struct notifier_block *event_notifer; /* Events */
- atomic_t users;
struct list_head list; /* Controller list */
- void __iomem *post_port; /* Inbout port address */
- void __iomem *reply_port; /* Outbound port address */
- void __iomem *irq_mask; /* Interrupt register address */
+
+ void __iomem *in_port; /* Inbout port address */
+ void __iomem *out_port; /* Outbound port address */
+ void __iomem *irq_status; /* Interrupt status register address */
+ void __iomem *irq_mask; /* Interrupt mask register address */
/* Dynamic LCT related data */
- struct i2o_dma status; /* status of IOP */
+ struct i2o_dma status; /* IOP status block */
struct i2o_dma hrt; /* HW Resource Table */
i2o_lct *lct; /* Logical Config Table */
@@ -176,21 +182,19 @@ struct i2o_controller {
struct semaphore lct_lock; /* Lock for LCT updates */
struct i2o_dma status_block; /* IOP status block */
- struct i2o_dma base; /* controller messaging unit */
- struct i2o_dma in_queue; /* inbound message queue Host->IOP */
+ struct i2o_io base; /* controller messaging unit */
+ struct i2o_io in_queue; /* inbound message queue Host->IOP */
struct i2o_dma out_queue; /* outbound message queue IOP->Host */
- unsigned int battery:1; /* Has a battery backup */
+ unsigned int battery:1; /* Has a battery backup */
unsigned int io_alloc:1; /* An I/O resource was allocated */
unsigned int mem_alloc:1; /* A memory resource was allocated */
struct resource io_resource; /* I/O resource allocated to the IOP */
struct resource mem_resource; /* Mem resource allocated to the IOP */
- struct proc_dir_entry *proc_entry; /* /proc dir */
-
- struct list_head bus_list; /* list of busses on IOP */
struct device device;
+ struct class_device classdev; /* I2O controller class */
struct i2o_device *exec; /* Executive */
#if BITS_PER_LONG == 64
spinlock_t context_list_lock; /* lock for context_list */
@@ -241,9 +245,10 @@ struct i2o_sys_tbl {
extern struct list_head i2o_controllers;
/* Message functions */
-static inline u32 i2o_msg_get(struct i2o_controller *, struct i2o_message __iomem **);
-extern u32 i2o_msg_get_wait(struct i2o_controller *, struct i2o_message __iomem **,
- int);
+static inline u32 i2o_msg_get(struct i2o_controller *,
+ struct i2o_message __iomem **);
+extern u32 i2o_msg_get_wait(struct i2o_controller *,
+ struct i2o_message __iomem **, int);
static inline void i2o_msg_post(struct i2o_controller *, u32);
static inline int i2o_msg_post_wait(struct i2o_controller *, u32,
unsigned long);
@@ -252,15 +257,6 @@ extern int i2o_msg_post_wait_mem(struct i2o_controller *, u32, unsigned long,
extern void i2o_msg_nop(struct i2o_controller *, u32);
static inline void i2o_flush_reply(struct i2o_controller *, u32);
-/* DMA handling functions */
-static inline int i2o_dma_alloc(struct device *, struct i2o_dma *, size_t,
- unsigned int);
-static inline void i2o_dma_free(struct device *, struct i2o_dma *);
-int i2o_dma_realloc(struct device *, struct i2o_dma *, size_t, unsigned int);
-
-static inline int i2o_dma_map(struct device *, struct i2o_dma *);
-static inline void i2o_dma_unmap(struct device *, struct i2o_dma *);
-
/* IOP functions */
extern int i2o_status_get(struct i2o_controller *);
@@ -285,6 +281,16 @@ static inline u32 i2o_ptr_high(void *ptr)
{
return (u32) ((u64) ptr >> 32);
};
+
+static inline u32 i2o_dma_low(dma_addr_t dma_addr)
+{
+ return (u32) (u64) dma_addr;
+};
+
+static inline u32 i2o_dma_high(dma_addr_t dma_addr)
+{
+ return (u32) ((u64) dma_addr >> 32);
+};
#else
static inline u32 i2o_cntxt_list_add(struct i2o_controller *c, void *ptr)
{
@@ -315,8 +321,246 @@ static inline u32 i2o_ptr_high(void *ptr)
{
return 0;
};
+
+static inline u32 i2o_dma_low(dma_addr_t dma_addr)
+{
+ return (u32) dma_addr;
+};
+
+static inline u32 i2o_dma_high(dma_addr_t dma_addr)
+{
+ return 0;
+};
#endif
+/**
+ * i2o_sg_tablesize - Calculate the maximum number of elements in a SGL
+ * @c: I2O controller for which the calculation should be done
+ * @body_size: maximum body size used for message in 32-bit words.
+ *
+ * Return the maximum number of SG elements in a SG list.
+ */
+static inline u16 i2o_sg_tablesize(struct i2o_controller *c, u16 body_size)
+{
+ i2o_status_block *sb = c->status_block.virt;
+ u16 sg_count =
+ (sb->inbound_frame_size - sizeof(struct i2o_message) / 4) -
+ body_size;
+
+ if (c->pae_support) {
+ /*
+ * for 64-bit a SG attribute element must be added and each
+ * SG element needs 12 bytes instead of 8.
+ */
+ sg_count -= 2;
+ sg_count /= 3;
+ } else
+ sg_count /= 2;
+
+ if (c->short_req && (sg_count > 8))
+ sg_count = 8;
+
+ return sg_count;
+};
+
+/**
+ * i2o_dma_map_single - Map pointer to controller and fill in I2O message.
+ * @c: I2O controller
+ * @ptr: pointer to the data which should be mapped
+ * @size: size of data in bytes
+ * @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE
+ * @sg_ptr: pointer to the SG list inside the I2O message
+ *
+ * This function does all necessary DMA handling and also writes the I2O
+ * SGL elements into the I2O message. For details on DMA handling see also
+ * dma_map_single(). The pointer sg_ptr will only be set to the end of the
+ * SG list if the allocation was successful.
+ *
+ * Returns DMA address which must be checked for failures using
+ * dma_mapping_error().
+ */
+static inline dma_addr_t i2o_dma_map_single(struct i2o_controller *c, void *ptr,
+ size_t size,
+ enum dma_data_direction direction,
+ u32 __iomem ** sg_ptr)
+{
+ u32 sg_flags;
+ u32 __iomem *mptr = *sg_ptr;
+ dma_addr_t dma_addr;
+
+ switch (direction) {
+ case DMA_TO_DEVICE:
+ sg_flags = 0xd4000000;
+ break;
+ case DMA_FROM_DEVICE:
+ sg_flags = 0xd0000000;
+ break;
+ default:
+ return 0;
+ }
+
+ dma_addr = dma_map_single(&c->pdev->dev, ptr, size, direction);
+ if (!dma_mapping_error(dma_addr)) {
+#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
+ if ((sizeof(dma_addr_t) > 4) && c->pae_support) {
+ writel(0x7C020002, mptr++);
+ writel(PAGE_SIZE, mptr++);
+ }
+#endif
+
+ writel(sg_flags | size, mptr++);
+ writel(i2o_dma_low(dma_addr), mptr++);
+#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
+ if ((sizeof(dma_addr_t) > 4) && c->pae_support)
+ writel(i2o_dma_high(dma_addr), mptr++);
+#endif
+ *sg_ptr = mptr;
+ }
+ return dma_addr;
+};
+
+/**
+ * i2o_dma_map_sg - Map a SG List to controller and fill in I2O message.
+ * @c: I2O controller
+ * @sg: SG list to be mapped
+ * @sg_count: number of elements in the SG list
+ * @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE
+ * @sg_ptr: pointer to the SG list inside the I2O message
+ *
+ * This function does all necessary DMA handling and also writes the I2O
+ * SGL elements into the I2O message. For details on DMA handling see also
+ * dma_map_sg(). The pointer sg_ptr will only be set to the end of the SG
+ * list if the allocation was successful.
+ *
+ * Returns 0 on failure or 1 on success.
+ */
+static inline int i2o_dma_map_sg(struct i2o_controller *c,
+ struct scatterlist *sg, int sg_count,
+ enum dma_data_direction direction,
+ u32 __iomem ** sg_ptr)
+{
+ u32 sg_flags;
+ u32 __iomem *mptr = *sg_ptr;
+
+ switch (direction) {
+ case DMA_TO_DEVICE:
+ sg_flags = 0x14000000;
+ break;
+ case DMA_FROM_DEVICE:
+ sg_flags = 0x10000000;
+ break;
+ default:
+ return 0;
+ }
+
+ sg_count = dma_map_sg(&c->pdev->dev, sg, sg_count, direction);
+ if (!sg_count)
+ return 0;
+
+#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
+ if ((sizeof(dma_addr_t) > 4) && c->pae_support) {
+ writel(0x7C020002, mptr++);
+ writel(PAGE_SIZE, mptr++);
+ }
+#endif
+
+ while (sg_count-- > 0) {
+ if (!sg_count)
+ sg_flags |= 0xC0000000;
+ writel(sg_flags | sg_dma_len(sg), mptr++);
+ writel(i2o_dma_low(sg_dma_address(sg)), mptr++);
+#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
+ if ((sizeof(dma_addr_t) > 4) && c->pae_support)
+ writel(i2o_dma_high(sg_dma_address(sg)), mptr++);
+#endif
+ sg++;
+ }
+ *sg_ptr = mptr;
+
+ return 1;
+};
+
+/**
+ * i2o_dma_alloc - Allocate DMA memory
+ * @dev: struct device pointer to the PCI device of the I2O controller
+ * @addr: i2o_dma struct which should get the DMA buffer
+ * @len: length of the new DMA memory
+ * @gfp_mask: GFP mask
+ *
+ * Allocate a coherent DMA memory and write the pointers into addr.
+ *
+ * Returns 0 on success or -ENOMEM on failure.
+ */
+static inline int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr,
+ size_t len, unsigned int gfp_mask)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ int dma_64 = 0;
+
+ if ((sizeof(dma_addr_t) > 4) && (pdev->dma_mask == DMA_64BIT_MASK)) {
+ dma_64 = 1;
+ if (pci_set_dma_mask(pdev, DMA_32BIT_MASK))
+ return -ENOMEM;
+ }
+
+ addr->virt = dma_alloc_coherent(dev, len, &addr->phys, gfp_mask);
+
+ if ((sizeof(dma_addr_t) > 4) && dma_64)
+ if (pci_set_dma_mask(pdev, DMA_64BIT_MASK))
+ printk(KERN_WARNING "i2o: unable to set 64-bit DMA");
+
+ if (!addr->virt)
+ return -ENOMEM;
+
+ memset(addr->virt, 0, len);
+ addr->len = len;
+
+ return 0;
+};
+
+/**
+ * i2o_dma_free - Free DMA memory
+ * @dev: struct device pointer to the PCI device of the I2O controller
+ * @addr: i2o_dma struct which contains the DMA buffer
+ *
+ * Free a coherent DMA memory and set virtual address of addr to NULL.
+ */
+static inline void i2o_dma_free(struct device *dev, struct i2o_dma *addr)
+{
+ if (addr->virt) {
+ if (addr->phys)
+ dma_free_coherent(dev, addr->len, addr->virt,
+ addr->phys);
+ else
+ kfree(addr->virt);
+ addr->virt = NULL;
+ }
+};
+
+/**
+ * i2o_dma_realloc - Realloc DMA memory
+ * @dev: struct device pointer to the PCI device of the I2O controller
+ * @addr: pointer to a i2o_dma struct DMA buffer
+ * @len: new length of memory
+ * @gfp_mask: GFP mask
+ *
+ * If there was something allocated in the addr, free it first. If len > 0
+ * than try to allocate it and write the addresses back to the addr
+ * structure. If len == 0 set the virtual address to NULL.
+ *
+ * Returns the 0 on success or negative error code on failure.
+ */
+static inline int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr,
+ size_t len, unsigned int gfp_mask)
+{
+ i2o_dma_free(dev, addr);
+
+ if (len)
+ return i2o_dma_alloc(dev, addr, len, gfp_mask);
+
+ return 0;
+};
+
/* I2O driver (OSM) functions */
extern int i2o_driver_register(struct i2o_driver *);
extern void i2o_driver_unregister(struct i2o_driver *);
@@ -385,49 +629,11 @@ extern int i2o_device_claim_release(struct i2o_device *);
/* Exec OSM functions */
extern int i2o_exec_lct_get(struct i2o_controller *);
-/* device to i2o_device and driver to i2o_driver convertion functions */
+/* device / driver / kobject conversion functions */
#define to_i2o_driver(drv) container_of(drv,struct i2o_driver, driver)
#define to_i2o_device(dev) container_of(dev, struct i2o_device, device)
-
-/*
- * Messenger inlines
- */
-static inline u32 I2O_POST_READ32(struct i2o_controller *c)
-{
- rmb();
- return readl(c->post_port);
-};
-
-static inline void I2O_POST_WRITE32(struct i2o_controller *c, u32 val)
-{
- wmb();
- writel(val, c->post_port);
-};
-
-static inline u32 I2O_REPLY_READ32(struct i2o_controller *c)
-{
- rmb();
- return readl(c->reply_port);
-};
-
-static inline void I2O_REPLY_WRITE32(struct i2o_controller *c, u32 val)
-{
- wmb();
- writel(val, c->reply_port);
-};
-
-static inline u32 I2O_IRQ_READ32(struct i2o_controller *c)
-{
- rmb();
- return readl(c->irq_mask);
-};
-
-static inline void I2O_IRQ_WRITE32(struct i2o_controller *c, u32 val)
-{
- wmb();
- writel(val, c->irq_mask);
- wmb();
-};
+#define to_i2o_controller(dev) container_of(dev, struct i2o_controller, device)
+#define kobj_to_i2o_device(kobj) to_i2o_device(container_of(kobj, struct device, kobj))
/**
* i2o_msg_get - obtain an I2O message from the IOP
@@ -443,11 +649,11 @@ static inline void I2O_IRQ_WRITE32(struct i2o_controller *c, u32 val)
* available returns I2O_QUEUE_EMPTY and msg is leaved untouched.
*/
static inline u32 i2o_msg_get(struct i2o_controller *c,
- struct i2o_message __iomem **msg)
+ struct i2o_message __iomem ** msg)
{
- u32 m;
+ u32 m = readl(c->in_port);
- if ((m = I2O_POST_READ32(c)) != I2O_QUEUE_EMPTY)
+ if (m != I2O_QUEUE_EMPTY)
*msg = c->in_queue.virt + m;
return m;
@@ -462,7 +668,7 @@ static inline u32 i2o_msg_get(struct i2o_controller *c,
*/
static inline void i2o_msg_post(struct i2o_controller *c, u32 m)
{
- I2O_POST_WRITE32(c, m);
+ writel(m, c->in_port);
};
/**
@@ -491,12 +697,10 @@ static inline int i2o_msg_post_wait(struct i2o_controller *c, u32 m,
* The I2O controller must be informed that the reply message is not needed
* anymore. If you forget to flush the reply, the message frame can't be
* used by the controller anymore and is therefore lost.
- *
- * FIXME: is there a timeout after which the controller reuse the message?
*/
static inline void i2o_flush_reply(struct i2o_controller *c, u32 m)
{
- I2O_REPLY_WRITE32(c, m);
+ writel(m, c->out_port);
};
/**
@@ -530,97 +734,13 @@ static inline struct i2o_message *i2o_msg_out_to_virt(struct i2o_controller *c,
* work for receive side messages as they are kmalloc objects
* in a different pool.
*/
-static inline struct i2o_message __iomem *i2o_msg_in_to_virt(struct i2o_controller *c,
- u32 m)
+static inline struct i2o_message __iomem *i2o_msg_in_to_virt(struct
+ i2o_controller *c,
+ u32 m)
{
return c->in_queue.virt + m;
};
-/**
- * i2o_dma_alloc - Allocate DMA memory
- * @dev: struct device pointer to the PCI device of the I2O controller
- * @addr: i2o_dma struct which should get the DMA buffer
- * @len: length of the new DMA memory
- * @gfp_mask: GFP mask
- *
- * Allocate a coherent DMA memory and write the pointers into addr.
- *
- * Returns 0 on success or -ENOMEM on failure.
- */
-static inline int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr,
- size_t len, unsigned int gfp_mask)
-{
- addr->virt = dma_alloc_coherent(dev, len, &addr->phys, gfp_mask);
- if (!addr->virt)
- return -ENOMEM;
-
- memset(addr->virt, 0, len);
- addr->len = len;
-
- return 0;
-};
-
-/**
- * i2o_dma_free - Free DMA memory
- * @dev: struct device pointer to the PCI device of the I2O controller
- * @addr: i2o_dma struct which contains the DMA buffer
- *
- * Free a coherent DMA memory and set virtual address of addr to NULL.
- */
-static inline void i2o_dma_free(struct device *dev, struct i2o_dma *addr)
-{
- if (addr->virt) {
- if (addr->phys)
- dma_free_coherent(dev, addr->len, addr->virt,
- addr->phys);
- else
- kfree(addr->virt);
- addr->virt = NULL;
- }
-};
-
-/**
- * i2o_dma_map - Map the memory to DMA
- * @dev: struct device pointer to the PCI device of the I2O controller
- * @addr: i2o_dma struct which should be mapped
- *
- * Map the memory in addr->virt to coherent DMA memory and write the
- * physical address into addr->phys.
- *
- * Returns 0 on success or -ENOMEM on failure.
- */
-static inline int i2o_dma_map(struct device *dev, struct i2o_dma *addr)
-{
- if (!addr->virt)
- return -EFAULT;
-
- if (!addr->phys)
- addr->phys = dma_map_single(dev, addr->virt, addr->len,
- DMA_BIDIRECTIONAL);
- if (!addr->phys)
- return -ENOMEM;
-
- return 0;
-};
-
-/**
- * i2o_dma_unmap - Unmap the DMA memory
- * @dev: struct device pointer to the PCI device of the I2O controller
- * @addr: i2o_dma struct which should be unmapped
- *
- * Unmap the memory in addr->virt from DMA memory.
- */
-static inline void i2o_dma_unmap(struct device *dev, struct i2o_dma *addr)
-{
- if (!addr->virt)
- return;
-
- if (addr->phys) {
- dma_unmap_single(dev, addr->phys, addr->len, DMA_BIDIRECTIONAL);
- addr->phys = 0;
- }
-};
-
/*
* Endian handling wrapped into the macro - keeps the core code
* cleaner.
@@ -773,6 +893,14 @@ extern void i2o_debug_state(struct i2o_controller *c);
#define I2O_CMD_SCSI_BUSRESET 0x27
/*
+ * Bus Adapter Class
+ */
+#define I2O_CMD_BUS_ADAPTER_RESET 0x85
+#define I2O_CMD_BUS_RESET 0x87
+#define I2O_CMD_BUS_SCAN 0x89
+#define I2O_CMD_BUS_QUIESCE 0x8b
+
+/*
* Random Block Storage Class
*/
#define I2O_CMD_BLOCK_READ 0x30
@@ -784,7 +912,7 @@ extern void i2o_debug_state(struct i2o_controller *c);
#define I2O_CMD_BLOCK_MEJECT 0x43
#define I2O_CMD_BLOCK_POWER 0x70
-#define I2O_PRIVATE_MSG 0xFF
+#define I2O_CMD_PRIVATE 0xFF
/* Command status values */
@@ -922,7 +1050,7 @@ extern void i2o_debug_state(struct i2o_controller *c);
#define I2OVER15 0x0001
#define I2OVER20 0x0002
-/* Default is 1.5, FIXME: Need support for both 1.5 and 2.0 */
+/* Default is 1.5 */
#define I2OVERSION I2OVER15
#define SGL_OFFSET_0 I2OVERSION
@@ -933,9 +1061,9 @@ extern void i2o_debug_state(struct i2o_controller *c);
#define SGL_OFFSET_8 (0x0080 | I2OVERSION)
#define SGL_OFFSET_9 (0x0090 | I2OVERSION)
#define SGL_OFFSET_10 (0x00A0 | I2OVERSION)
-
-#define TRL_OFFSET_5 (0x0050 | I2OVERSION)
-#define TRL_OFFSET_6 (0x0060 | I2OVERSION)
+#define SGL_OFFSET_11 (0x00B0 | I2OVERSION)
+#define SGL_OFFSET_12 (0x00C0 | I2OVERSION)
+#define SGL_OFFSET(x) (((x)<<4) | I2OVERSION)
/* Transaction Reply Lists (TRL) Control Word structure */
#define TRL_SINGLE_FIXED_LENGTH 0x00
@@ -962,17 +1090,13 @@ extern void i2o_debug_state(struct i2o_controller *c);
#define ELEVEN_WORD_MSG_SIZE 0x000B0000
#define I2O_MESSAGE_SIZE(x) ((x)<<16)
-/* Special TID Assignments */
-
+/* special TID assignments */
#define ADAPTER_TID 0
#define HOST_TID 1
-#define MSG_FRAME_SIZE 128 /* i2o_scsi assumes >= 32 */
-#define REPLY_FRAME_SIZE 17
-#define SG_TABLESIZE 30
-#define NMBR_MSG_FRAMES 128
-
-#define MSG_POOL_SIZE (MSG_FRAME_SIZE*NMBR_MSG_FRAMES*sizeof(u32))
+/* outbound queue defines */
+#define I2O_MAX_OUTBOUND_MSG_FRAMES 128
+#define I2O_OUTBOUND_MSG_FRAME_SIZE 128 /* in 32-bit words */
#define I2O_POST_WAIT_OK 0
#define I2O_POST_WAIT_TIMEOUT -ETIMEDOUT
@@ -993,11 +1117,10 @@ extern void i2o_debug_state(struct i2o_controller *c);
#define I2O_HRT_GET_TRIES 3
#define I2O_LCT_GET_TRIES 3
-/* request queue sizes */
+/* defines for max_sectors and max_phys_segments */
#define I2O_MAX_SECTORS 1024
-#define I2O_MAX_SEGMENTS 128
-
-#define I2O_REQ_MEMPOOL_SIZE 32
+#define I2O_MAX_SECTORS_LIMITED 256
+#define I2O_MAX_PHYS_SEGMENTS MAX_PHYS_SEGMENTS
#endif /* __KERNEL__ */
#endif /* _I2O_H */
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 9cfc0999bec..92129078d4f 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -664,7 +664,6 @@ typedef struct ide_drive_s {
struct request *rq; /* current request */
struct ide_drive_s *next; /* circular list of hwgroup drives */
- struct ide_driver_s *driver;/* (ide_driver_t *) */
void *driver_data; /* extra driver data */
struct hd_driveid *id; /* drive model identification info */
struct proc_dir_entry *proc; /* /proc/ide/ directory entry */
@@ -758,6 +757,8 @@ typedef struct ide_drive_s {
struct semaphore gendev_rel_sem; /* to deal with device release() */
} ide_drive_t;
+#define to_ide_device(dev)container_of(dev, ide_drive_t, gendev)
+
#define IDE_CHIPSET_PCI_MASK \
((1<<ide_pci)|(1<<ide_cmd646)|(1<<ide_ali14xx))
#define IDE_CHIPSET_IS_PCI(c) ((IDE_CHIPSET_PCI_MASK >> (c)) & 1)
@@ -916,7 +917,7 @@ typedef struct hwif_s {
unsigned dma;
void (*led_act)(void *data, int rw);
-} ide_hwif_t;
+} ____cacheline_maxaligned_in_smp ide_hwif_t;
/*
* internal ide interrupt handler type
@@ -1086,28 +1087,20 @@ enum {
*/
typedef struct ide_driver_s {
struct module *owner;
- const char *name;
const char *version;
u8 media;
- unsigned busy : 1;
unsigned supports_dsc_overlap : 1;
- int (*cleanup)(ide_drive_t *);
ide_startstop_t (*do_request)(ide_drive_t *, struct request *, sector_t);
int (*end_request)(ide_drive_t *, int, int);
ide_startstop_t (*error)(ide_drive_t *, struct request *rq, u8, u8);
ide_startstop_t (*abort)(ide_drive_t *, struct request *rq);
int (*ioctl)(ide_drive_t *, struct inode *, struct file *, unsigned int, unsigned long);
ide_proc_entry_t *proc;
- int (*attach)(ide_drive_t *);
void (*ata_prebuilder)(ide_drive_t *);
void (*atapi_prebuilder)(ide_drive_t *);
struct device_driver gen_driver;
- struct list_head drives;
- struct list_head drivers;
} ide_driver_t;
-#define DRIVER(drive) ((drive)->driver)
-
int generic_ide_ioctl(ide_drive_t *, struct file *, struct block_device *, unsigned, unsigned long);
/*
@@ -1328,8 +1321,6 @@ extern void ide_init_subdrivers(void);
void ide_init_disk(struct gendisk *, ide_drive_t *);
-extern int ata_attach(ide_drive_t *);
-
extern int ideprobe_init(void);
extern void ide_scan_pcibus(int scan_direction) __init;
@@ -1342,11 +1333,8 @@ extern void default_hwif_iops(ide_hwif_t *);
extern void default_hwif_mmiops(ide_hwif_t *);
extern void default_hwif_transport(ide_hwif_t *);
-int ide_register_driver(ide_driver_t *driver);
-void ide_unregister_driver(ide_driver_t *driver);
-int ide_register_subdriver(ide_drive_t *, ide_driver_t *);
-int ide_unregister_subdriver (ide_drive_t *drive);
-int ide_replace_subdriver(ide_drive_t *drive, const char *driver);
+void ide_register_subdriver(ide_drive_t *, ide_driver_t *);
+void ide_unregister_subdriver(ide_drive_t *, ide_driver_t *);
#define ON_BOARD 1
#define NEVER_BOARD 0
diff --git a/include/linux/if.h b/include/linux/if.h
index d73a9d62f20..ce627d9092e 100644
--- a/include/linux/if.h
+++ b/include/linux/if.h
@@ -33,7 +33,7 @@
#define IFF_LOOPBACK 0x8 /* is a loopback net */
#define IFF_POINTOPOINT 0x10 /* interface is has p-p link */
#define IFF_NOTRAILERS 0x20 /* avoid use of trailers */
-#define IFF_RUNNING 0x40 /* resources allocated */
+#define IFF_RUNNING 0x40 /* interface running and carrier ok */
#define IFF_NOARP 0x80 /* no ARP protocol */
#define IFF_PROMISC 0x100 /* receive all packets */
#define IFF_ALLMULTI 0x200 /* receive all multicast packets*/
diff --git a/include/linux/if_shaper.h b/include/linux/if_shaper.h
index 0485b256d04..004e6f09a6e 100644
--- a/include/linux/if_shaper.h
+++ b/include/linux/if_shaper.h
@@ -23,7 +23,7 @@ struct shaper
__u32 shapeclock;
unsigned long recovery; /* Time we can next clock a packet out on
an empty queue */
- unsigned long locked;
+ struct semaphore sem;
struct net_device_stats stats;
struct net_device *dev;
int (*hard_start_xmit) (struct sk_buff *skb,
@@ -38,7 +38,6 @@ struct shaper
int (*hard_header_cache)(struct neighbour *neigh, struct hh_cache *hh);
void (*header_cache_update)(struct hh_cache *hh, struct net_device *dev, unsigned char * haddr);
struct net_device_stats* (*get_stats)(struct net_device *dev);
- wait_queue_head_t wait_queue;
struct timer_list timer;
};
diff --git a/include/linux/if_tr.h b/include/linux/if_tr.h
index 4fd451f81cc..3fba9e2f542 100644
--- a/include/linux/if_tr.h
+++ b/include/linux/if_tr.h
@@ -9,7 +9,7 @@
*
* Author: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
* Donald Becker, <becker@super.org>
- * Peter De Schrijver, <stud11@cc4.kuleuven.ac.be>
+ * Peter De Schrijver, <stud11@cc4.kuleuven.ac.be>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -19,24 +19,18 @@
#ifndef _LINUX_IF_TR_H
#define _LINUX_IF_TR_H
+#include <asm/byteorder.h> /* For __be16 */
/* IEEE 802.5 Token-Ring magic constants. The frame sizes omit the preamble
and FCS/CRC (frame check sequence). */
-#define TR_ALEN 6 /* Octets in one ethernet addr */
-#define TR_HLEN (sizeof(struct trh_hdr)+sizeof(struct trllc))
-#define AC 0x10
-#define LLC_FRAME 0x40
-#if 0
-#define ETH_HLEN 14 /* Total octets in header. */
-#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */
-#define ETH_DATA_LEN 1500 /* Max. octets in payload */
-#define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */
-#endif
-
+#define TR_ALEN 6 /* Octets in one token-ring addr */
+#define TR_HLEN (sizeof(struct trh_hdr)+sizeof(struct trllc))
+#define AC 0x10
+#define LLC_FRAME 0x40
/* LLC and SNAP constants */
-#define EXTENDED_SAP 0xAA
-#define UI_CMD 0x03
+#define EXTENDED_SAP 0xAA
+#define UI_CMD 0x03
/* This is an Token-Ring frame header. */
struct trh_hdr {
@@ -44,8 +38,8 @@ struct trh_hdr {
__u8 fc; /* frame control field */
__u8 daddr[TR_ALEN]; /* destination address */
__u8 saddr[TR_ALEN]; /* source address */
- __u16 rcf; /* route control field */
- __u16 rseg[8]; /* routing registers */
+ __be16 rcf; /* route control field */
+ __be16 rseg[8]; /* routing registers */
};
#ifdef __KERNEL__
@@ -63,7 +57,7 @@ struct trllc {
__u8 ssap; /* source SAP */
__u8 llc; /* LLC control field */
__u8 protid[3]; /* protocol id */
- __u16 ethertype; /* ether type field */
+ __be16 ethertype; /* ether type field */
};
/* Token-Ring statistics collection data. */
@@ -96,14 +90,13 @@ struct tr_statistics {
};
/* source routing stuff */
-
-#define TR_RII 0x80
-#define TR_RCF_DIR_BIT 0x80
-#define TR_RCF_LEN_MASK 0x1f00
-#define TR_RCF_BROADCAST 0x8000 /* all-routes broadcast */
-#define TR_RCF_LIMITED_BROADCAST 0xC000 /* single-route broadcast */
-#define TR_RCF_FRAME2K 0x20
-#define TR_RCF_BROADCAST_MASK 0xC000
-#define TR_MAXRIFLEN 18
+#define TR_RII 0x80
+#define TR_RCF_DIR_BIT 0x80
+#define TR_RCF_LEN_MASK 0x1f00
+#define TR_RCF_BROADCAST 0x8000 /* all-routes broadcast */
+#define TR_RCF_LIMITED_BROADCAST 0xC000 /* single-route broadcast */
+#define TR_RCF_FRAME2K 0x20
+#define TR_RCF_BROADCAST_MASK 0xC000
+#define TR_MAXRIFLEN 18
#endif /* _LINUX_IF_TR_H */
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index 6fafb27877a..7e1e15f934f 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -29,6 +29,7 @@ struct ipv4_devconf
int no_xfrm;
int no_policy;
int force_igmp_version;
+ int promote_secondaries;
void *sysctl;
};
@@ -71,6 +72,7 @@ struct in_device
#define IN_DEV_SEC_REDIRECTS(in_dev) (ipv4_devconf.secure_redirects || (in_dev)->cnf.secure_redirects)
#define IN_DEV_IDTAG(in_dev) ((in_dev)->cnf.tag)
#define IN_DEV_MEDIUM_ID(in_dev) ((in_dev)->cnf.medium_id)
+#define IN_DEV_PROMOTE_SECONDARIES(in_dev) (ipv4_devconf.promote_secondaries || (in_dev)->cnf.promote_secondaries)
#define IN_DEV_RX_REDIRECTS(in_dev) \
((IN_DEV_FORWARD(in_dev) && \
diff --git a/include/linux/init.h b/include/linux/init.h
index 05c83e0521c..59008c3826c 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -229,6 +229,18 @@ void __init parse_early_param(void);
#define __devexitdata __exitdata
#endif
+#ifdef CONFIG_HOTPLUG_CPU
+#define __cpuinit
+#define __cpuinitdata
+#define __cpuexit
+#define __cpuexitdata
+#else
+#define __cpuinit __init
+#define __cpuinitdata __initdata
+#define __cpuexit __exit
+#define __cpuexitdata __exitdata
+#endif
+
/* Functions marked as __devexit may be discarded at kernel link time, depending
on config options. Newer versions of binutils detect references from
retained sections to discarded sections and flag an error. Pointers to
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index a6a8c1a38d5..03206a425d7 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -108,7 +108,6 @@ extern struct group_info init_groups;
.blocked = {{0}}, \
.alloc_lock = SPIN_LOCK_UNLOCKED, \
.proc_lock = SPIN_LOCK_UNLOCKED, \
- .switch_lock = SPIN_LOCK_UNLOCKED, \
.journal_info = NULL, \
.cpu_timers = INIT_CPU_TIMERS(tsk.cpu_timers), \
}
diff --git a/include/linux/input.h b/include/linux/input.h
index 72731d7d189..9d9598ed760 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -1015,7 +1015,7 @@ static inline void input_set_abs_params(struct input_dev *dev, int axis, int min
dev->absbit[LONG(axis)] |= BIT(axis);
}
-extern struct class_simple *input_class;
+extern struct class *input_class;
#endif
#endif
diff --git a/include/linux/ioc4.h b/include/linux/ioc4.h
new file mode 100644
index 00000000000..3dd18b785eb
--- /dev/null
+++ b/include/linux/ioc4.h
@@ -0,0 +1,179 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2005 Silicon Graphics, Inc. All Rights Reserved.
+ */
+
+#ifndef _LINUX_IOC4_H
+#define _LINUX_IOC4_H
+
+#include <linux/interrupt.h>
+
+/***************
+ * Definitions *
+ ***************/
+
+/* Miscellaneous values inherent to hardware */
+
+#define IOC4_EXTINT_COUNT_DIVISOR 520 /* PCI clocks per COUNT tick */
+
+/***********************************
+ * Structures needed by subdrivers *
+ ***********************************/
+
+/* This structure fully describes the IOC4 miscellaneous registers which
+ * appear at bar[0]+0x00000 through bar[0]+0x0005c. The corresponding
+ * PCI resource is managed by the main IOC4 driver because it contains
+ * registers of interest to many different IOC4 subdrivers.
+ */
+struct ioc4_misc_regs {
+ /* Miscellaneous IOC4 registers */
+ union ioc4_pci_err_addr_l {
+ uint32_t raw;
+ struct {
+ uint32_t valid:1; /* Address captured */
+ uint32_t master_id:4; /* Unit causing error
+ * 0/1: Serial port 0 TX/RX
+ * 2/3: Serial port 1 TX/RX
+ * 4/5: Serial port 2 TX/RX
+ * 6/7: Serial port 3 TX/RX
+ * 8: ATA/ATAPI
+ * 9-15: Undefined
+ */
+ uint32_t mul_err:1; /* Multiple errors occurred */
+ uint32_t addr:26; /* Bits 31-6 of error addr */
+ } fields;
+ } pci_err_addr_l;
+ uint32_t pci_err_addr_h; /* Bits 63-32 of error addr */
+ union ioc4_sio_int {
+ uint32_t raw;
+ struct {
+ uint8_t tx_mt:1; /* TX ring buffer empty */
+ uint8_t rx_full:1; /* RX ring buffer full */
+ uint8_t rx_high:1; /* RX high-water exceeded */
+ uint8_t rx_timer:1; /* RX timer has triggered */
+ uint8_t delta_dcd:1; /* DELTA_DCD seen */
+ uint8_t delta_cts:1; /* DELTA_CTS seen */
+ uint8_t intr_pass:1; /* Interrupt pass-through */
+ uint8_t tx_explicit:1; /* TX, MCW, or delay complete */
+ } fields[4];
+ } sio_ir; /* Serial interrupt state */
+ union ioc4_other_int {
+ uint32_t raw;
+ struct {
+ uint32_t ata_int:1; /* ATA port passthru */
+ uint32_t ata_memerr:1; /* ATA halted by mem error */
+ uint32_t memerr:4; /* Serial halted by mem err */
+ uint32_t kbd_int:1; /* kbd/mouse intr asserted */
+ uint32_t reserved:16; /* zero */
+ uint32_t rt_int:1; /* INT_OUT section latch */
+ uint32_t gen_int:8; /* Intr. from generic pins */
+ } fields;
+ } other_ir; /* Other interrupt state */
+ union ioc4_sio_int sio_ies; /* Serial interrupt enable set */
+ union ioc4_other_int other_ies; /* Other interrupt enable set */
+ union ioc4_sio_int sio_iec; /* Serial interrupt enable clear */
+ union ioc4_other_int other_iec; /* Other interrupt enable clear */
+ union ioc4_sio_cr {
+ uint32_t raw;
+ struct {
+ uint32_t cmd_pulse:4; /* Bytebus strobe width */
+ uint32_t arb_diag:3; /* PCI bus requester */
+ uint32_t sio_diag_idle:1; /* Active ser req? */
+ uint32_t ata_diag_idle:1; /* Active ATA req? */
+ uint32_t ata_diag_active:1; /* ATA req is winner */
+ uint32_t reserved:22; /* zero */
+ } fields;
+ } sio_cr;
+ uint32_t unused1;
+ union ioc4_int_out {
+ uint32_t raw;
+ struct {
+ uint32_t count:16; /* Period control */
+ uint32_t mode:3; /* Output signal shape */
+ uint32_t reserved:11; /* zero */
+ uint32_t diag:1; /* Timebase control */
+ uint32_t int_out:1; /* Current value */
+ } fields;
+ } int_out; /* External interrupt output control */
+ uint32_t unused2;
+ union ioc4_gpcr {
+ uint32_t raw;
+ struct {
+ uint32_t dir:8; /* Pin direction */
+ uint32_t edge:8; /* Edge/level mode */
+ uint32_t reserved1:4; /* zero */
+ uint32_t int_out_en:1; /* INT_OUT enable */
+ uint32_t reserved2:11; /* zero */
+ } fields;
+ } gpcr_s; /* Generic PIO control set */
+ union ioc4_gpcr gpcr_c; /* Generic PIO control clear */
+ union ioc4_gpdr {
+ uint32_t raw;
+ struct {
+ uint32_t gen_pin:8; /* State of pins */
+ uint32_t reserved:24;
+ } fields;
+ } gpdr; /* Generic PIO data */
+ uint32_t unused3;
+ union ioc4_gppr {
+ uint32_t raw;
+ struct {
+ uint32_t gen_pin:1; /* Single pin state */
+ uint32_t reserved:31;
+ } fields;
+ } gppr[8]; /* Generic PIO pins */
+};
+
+/* Masks for GPCR DIR pins */
+#define IOC4_GPCR_DIR_0 0x01 /* External interrupt output */
+#define IOC4_GPCR_DIR_1 0x02 /* External interrupt input */
+#define IOC4_GPCR_DIR_2 0x04
+#define IOC4_GPCR_DIR_3 0x08 /* Keyboard/mouse presence */
+#define IOC4_GPCR_DIR_4 0x10 /* Ser. port 0 xcvr select (0=232, 1=422) */
+#define IOC4_GPCR_DIR_5 0x20 /* Ser. port 1 xcvr select (0=232, 1=422) */
+#define IOC4_GPCR_DIR_6 0x40 /* Ser. port 2 xcvr select (0=232, 1=422) */
+#define IOC4_GPCR_DIR_7 0x80 /* Ser. port 3 xcvr select (0=232, 1=422) */
+
+/* Masks for GPCR EDGE pins */
+#define IOC4_GPCR_EDGE_0 0x01
+#define IOC4_GPCR_EDGE_1 0x02 /* External interrupt input */
+#define IOC4_GPCR_EDGE_2 0x04
+#define IOC4_GPCR_EDGE_3 0x08
+#define IOC4_GPCR_EDGE_4 0x10
+#define IOC4_GPCR_EDGE_5 0x20
+#define IOC4_GPCR_EDGE_6 0x40
+#define IOC4_GPCR_EDGE_7 0x80
+
+/* One of these per IOC4 */
+struct ioc4_driver_data {
+ struct list_head idd_list;
+ unsigned long idd_bar0;
+ struct pci_dev *idd_pdev;
+ const struct pci_device_id *idd_pci_id;
+ struct __iomem ioc4_misc_regs *idd_misc_regs;
+ unsigned long count_period;
+ void *idd_serial_data;
+};
+
+/* One per submodule */
+struct ioc4_submodule {
+ struct list_head is_list;
+ char *is_name;
+ struct module *is_owner;
+ int (*is_probe) (struct ioc4_driver_data *);
+ int (*is_remove) (struct ioc4_driver_data *);
+};
+
+#define IOC4_NUM_CARDS 8 /* max cards per partition */
+
+/**********************************
+ * Functions needed by submodules *
+ **********************************/
+
+extern int ioc4_register_submodule(struct ioc4_submodule *);
+extern void ioc4_unregister_submodule(struct ioc4_submodule *);
+
+#endif /* _LINUX_IOC4_H */
diff --git a/include/linux/ioc4_common.h b/include/linux/ioc4_common.h
deleted file mode 100644
index b03bcc46df5..00000000000
--- a/include/linux/ioc4_common.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (c) 2005 Silicon Graphics, Inc. All Rights Reserved.
- */
-
-#ifndef _LINUX_IOC4_COMMON_H
-#define _LINUX_IOC4_COMMON_H
-
-/* prototypes */
-
-int ioc4_serial_init(void);
-
-int ioc4_serial_attach_one(struct pci_dev *pdev, const struct
- pci_device_id *pci_id);
-int ioc4_ide_attach_one(struct pci_dev *pdev, const struct
- pci_device_id *pci_id);
-
-#endif /* _LINUX_IOC4_COMMON_H */
diff --git a/include/linux/ip.h b/include/linux/ip.h
index 8438c68591f..31e7cedd9f8 100644
--- a/include/linux/ip.h
+++ b/include/linux/ip.h
@@ -81,6 +81,7 @@
#ifdef __KERNEL__
#include <linux/config.h>
#include <linux/types.h>
+#include <net/request_sock.h>
#include <net/sock.h>
#include <linux/igmp.h>
#include <net/flow.h>
@@ -107,6 +108,26 @@ struct ip_options {
#define optlength(opt) (sizeof(struct ip_options) + opt->optlen)
+struct inet_request_sock {
+ struct request_sock req;
+ u32 loc_addr;
+ u32 rmt_addr;
+ u16 rmt_port;
+ u16 snd_wscale : 4,
+ rcv_wscale : 4,
+ tstamp_ok : 1,
+ sack_ok : 1,
+ wscale_ok : 1,
+ ecn_ok : 1,
+ acked : 1;
+ struct ip_options *opt;
+};
+
+static inline struct inet_request_sock *inet_rsk(const struct request_sock *sk)
+{
+ return (struct inet_request_sock *)sk;
+}
+
struct ipv6_pinfo;
struct inet_sock {
diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h
index 2ec265e1045..596ca613015 100644
--- a/include/linux/ipmi.h
+++ b/include/linux/ipmi.h
@@ -209,6 +209,11 @@ struct kernel_ipmi_msg
#include <linux/list.h>
#include <linux/module.h>
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+extern struct proc_dir_entry *proc_ipmi_root;
+#endif /* CONFIG_PROC_FS */
+
/* Opaque type for a IPMI message user. One of these is needed to
send and receive messages. */
typedef struct ipmi_user *ipmi_user_t;
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index ab0d0efbf24..6fcd6a0ade2 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -193,6 +193,19 @@ struct inet6_skb_parm {
#define IP6CB(skb) ((struct inet6_skb_parm*)((skb)->cb))
+struct tcp6_request_sock {
+ struct tcp_request_sock req;
+ struct in6_addr loc_addr;
+ struct in6_addr rmt_addr;
+ struct sk_buff *pktopts;
+ int iif;
+};
+
+static inline struct tcp6_request_sock *tcp6_rsk(const struct request_sock *sk)
+{
+ return (struct tcp6_request_sock *)sk;
+}
+
/**
* struct ipv6_pinfo - ipv6 private area
*
diff --git a/include/linux/irq.h b/include/linux/irq.h
index c3ff4d10166..12277799c00 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -47,6 +47,10 @@ struct hw_interrupt_type {
void (*ack)(unsigned int irq);
void (*end)(unsigned int irq);
void (*set_affinity)(unsigned int irq, cpumask_t dest);
+ /* Currently used only by UML, might disappear one day.*/
+#ifdef CONFIG_IRQ_RELEASE_METHOD
+ void (*release)(unsigned int irq, void *dev_id);
+#endif
};
typedef struct hw_interrupt_type hw_irq_controller;
@@ -84,7 +88,6 @@ extern fastcall int handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
struct irqaction *action);
extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs);
extern void note_interrupt(unsigned int irq, irq_desc_t *desc, int action_ret);
-extern void report_bad_irq(unsigned int irq, irq_desc_t *desc, int action_ret);
extern int can_request_irq(unsigned int irq, unsigned long irqflags);
extern void init_irq_proc(void);
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index e25b97062ce..687ba8c9973 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -58,15 +58,23 @@ struct completion;
* be biten later when the calling function happens to sleep when it is not
* supposed to.
*/
+#ifdef CONFIG_PREEMPT_VOLUNTARY
+extern int cond_resched(void);
+# define might_resched() cond_resched()
+#else
+# define might_resched() do { } while (0)
+#endif
+
#ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
-#define might_sleep() __might_sleep(__FILE__, __LINE__)
-#define might_sleep_if(cond) do { if (unlikely(cond)) might_sleep(); } while (0)
-void __might_sleep(char *file, int line);
+ void __might_sleep(char *file, int line);
+# define might_sleep() \
+ do { __might_sleep(__FILE__, __LINE__); might_resched(); } while (0)
#else
-#define might_sleep() do {} while(0)
-#define might_sleep_if(cond) do {} while (0)
+# define might_sleep() do { might_resched(); } while (0)
#endif
+#define might_sleep_if(cond) do { if (unlikely(cond)) might_sleep(); } while (0)
+
#define abs(x) ({ \
int __x = (x); \
(__x < 0) ? -__x : __x; \
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
new file mode 100644
index 00000000000..c8468472aec
--- /dev/null
+++ b/include/linux/kexec.h
@@ -0,0 +1,135 @@
+#ifndef LINUX_KEXEC_H
+#define LINUX_KEXEC_H
+
+#ifdef CONFIG_KEXEC
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/linkage.h>
+#include <linux/compat.h>
+#include <asm/kexec.h>
+
+/* Verify architecture specific macros are defined */
+
+#ifndef KEXEC_SOURCE_MEMORY_LIMIT
+#error KEXEC_SOURCE_MEMORY_LIMIT not defined
+#endif
+
+#ifndef KEXEC_DESTINATION_MEMORY_LIMIT
+#error KEXEC_DESTINATION_MEMORY_LIMIT not defined
+#endif
+
+#ifndef KEXEC_CONTROL_MEMORY_LIMIT
+#error KEXEC_CONTROL_MEMORY_LIMIT not defined
+#endif
+
+#ifndef KEXEC_CONTROL_CODE_SIZE
+#error KEXEC_CONTROL_CODE_SIZE not defined
+#endif
+
+#ifndef KEXEC_ARCH
+#error KEXEC_ARCH not defined
+#endif
+
+/*
+ * This structure is used to hold the arguments that are used when loading
+ * kernel binaries.
+ */
+
+typedef unsigned long kimage_entry_t;
+#define IND_DESTINATION 0x1
+#define IND_INDIRECTION 0x2
+#define IND_DONE 0x4
+#define IND_SOURCE 0x8
+
+#define KEXEC_SEGMENT_MAX 8
+struct kexec_segment {
+ void __user *buf;
+ size_t bufsz;
+ unsigned long mem; /* User space sees this as a (void *) ... */
+ size_t memsz;
+};
+
+#ifdef CONFIG_COMPAT
+struct compat_kexec_segment {
+ compat_uptr_t buf;
+ compat_size_t bufsz;
+ compat_ulong_t mem; /* User space sees this as a (void *) ... */
+ compat_size_t memsz;
+};
+#endif
+
+struct kimage {
+ kimage_entry_t head;
+ kimage_entry_t *entry;
+ kimage_entry_t *last_entry;
+
+ unsigned long destination;
+
+ unsigned long start;
+ struct page *control_code_page;
+
+ unsigned long nr_segments;
+ struct kexec_segment segment[KEXEC_SEGMENT_MAX];
+
+ struct list_head control_pages;
+ struct list_head dest_pages;
+ struct list_head unuseable_pages;
+
+ /* Address of next control page to allocate for crash kernels. */
+ unsigned long control_page;
+
+ /* Flags to indicate special processing */
+ unsigned int type : 1;
+#define KEXEC_TYPE_DEFAULT 0
+#define KEXEC_TYPE_CRASH 1
+};
+
+
+
+/* kexec interface functions */
+extern NORET_TYPE void machine_kexec(struct kimage *image) ATTRIB_NORET;
+extern int machine_kexec_prepare(struct kimage *image);
+extern void machine_kexec_cleanup(struct kimage *image);
+extern asmlinkage long sys_kexec_load(unsigned long entry,
+ unsigned long nr_segments,
+ struct kexec_segment __user *segments,
+ unsigned long flags);
+#ifdef CONFIG_COMPAT
+extern asmlinkage long compat_sys_kexec_load(unsigned long entry,
+ unsigned long nr_segments,
+ struct compat_kexec_segment __user *segments,
+ unsigned long flags);
+#endif
+extern struct page *kimage_alloc_control_pages(struct kimage *image,
+ unsigned int order);
+extern void crash_kexec(struct pt_regs *);
+int kexec_should_crash(struct task_struct *);
+extern struct kimage *kexec_image;
+
+#define KEXEC_ON_CRASH 0x00000001
+#define KEXEC_ARCH_MASK 0xffff0000
+
+/* These values match the ELF architecture values.
+ * Unless there is a good reason that should continue to be the case.
+ */
+#define KEXEC_ARCH_DEFAULT ( 0 << 16)
+#define KEXEC_ARCH_386 ( 3 << 16)
+#define KEXEC_ARCH_X86_64 (62 << 16)
+#define KEXEC_ARCH_PPC (20 << 16)
+#define KEXEC_ARCH_PPC64 (21 << 16)
+#define KEXEC_ARCH_IA_64 (50 << 16)
+#define KEXEC_ARCH_S390 (22 << 16)
+
+#define KEXEC_FLAGS (KEXEC_ON_CRASH) /* List of defined/legal kexec flags */
+
+/* Location of a reserved region to hold the crash kernel.
+ */
+extern struct resource crashk_res;
+
+#else /* !CONFIG_KEXEC */
+struct pt_regs;
+struct task_struct;
+static inline void crash_kexec(struct pt_regs *regs) { }
+static inline int kexec_should_crash(struct task_struct *p) { return 0; }
+#endif /* CONFIG_KEXEC */
+#endif /* LINUX_KEXEC_H */
diff --git a/include/linux/key-ui.h b/include/linux/key-ui.h
index 60cc7b762e7..cc326174a80 100644
--- a/include/linux/key-ui.h
+++ b/include/linux/key-ui.h
@@ -1,4 +1,4 @@
-/* key-ui.h: key userspace interface stuff for use by keyfs
+/* key-ui.h: key userspace interface stuff
*
* Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
@@ -31,8 +31,10 @@ extern spinlock_t key_serial_lock;
* subscribed
*/
struct keyring_list {
- unsigned maxkeys; /* max keys this list can hold */
- unsigned nkeys; /* number of keys currently held */
+ struct rcu_head rcu; /* RCU deletion hook */
+ unsigned short maxkeys; /* max keys this list can hold */
+ unsigned short nkeys; /* number of keys currently held */
+ unsigned short delkey; /* key to be unlinked by RCU */
struct key *keys[0];
};
@@ -82,8 +84,45 @@ static inline int key_any_permission(const struct key *key, key_perm_t perm)
return kperm != 0;
}
+static inline int key_task_groups_search(struct task_struct *tsk, gid_t gid)
+{
+ int ret;
+
+ task_lock(tsk);
+ ret = groups_search(tsk->group_info, gid);
+ task_unlock(tsk);
+ return ret;
+}
+
+static inline int key_task_permission(const struct key *key,
+ struct task_struct *context,
+ key_perm_t perm)
+{
+ key_perm_t kperm;
+
+ if (key->uid == context->fsuid) {
+ kperm = key->perm >> 16;
+ }
+ else if (key->gid != -1 &&
+ key->perm & KEY_GRP_ALL && (
+ key->gid == context->fsgid ||
+ key_task_groups_search(context, key->gid)
+ )
+ ) {
+ kperm = key->perm >> 8;
+ }
+ else {
+ kperm = key->perm;
+ }
+
+ kperm = kperm & perm & KEY_ALL;
+
+ return kperm == perm;
+
+}
-extern struct key *lookup_user_key(key_serial_t id, int create, int part,
+extern struct key *lookup_user_key(struct task_struct *context,
+ key_serial_t id, int create, int partial,
key_perm_t perm);
extern long join_session_keyring(const char *name);
diff --git a/include/linux/key.h b/include/linux/key.h
index 6aa46d0e812..970bbd916cf 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -18,7 +18,7 @@
#include <linux/types.h>
#include <linux/list.h>
#include <linux/rbtree.h>
-#include <linux/spinlock.h>
+#include <linux/rcupdate.h>
#include <asm/atomic.h>
#ifdef __KERNEL__
@@ -78,7 +78,6 @@ struct key {
key_serial_t serial; /* key serial number */
struct rb_node serial_node;
struct key_type *type; /* type of key */
- rwlock_t lock; /* examination vs change lock */
struct rw_semaphore sem; /* change vs change sem */
struct key_user *user; /* owner of this key */
time_t expiry; /* time at which key expires (or 0) */
@@ -86,14 +85,10 @@ struct key {
gid_t gid;
key_perm_t perm; /* access permissions */
unsigned short quotalen; /* length added to quota */
- unsigned short datalen; /* payload data length */
- unsigned short flags; /* status flags (change with lock writelocked) */
-#define KEY_FLAG_INSTANTIATED 0x00000001 /* set if key has been instantiated */
-#define KEY_FLAG_DEAD 0x00000002 /* set if key type has been deleted */
-#define KEY_FLAG_REVOKED 0x00000004 /* set if key had been revoked */
-#define KEY_FLAG_IN_QUOTA 0x00000008 /* set if key consumes quota */
-#define KEY_FLAG_USER_CONSTRUCT 0x00000010 /* set if key is being constructed in userspace */
-#define KEY_FLAG_NEGATIVE 0x00000020 /* set if key is negative */
+ unsigned short datalen; /* payload data length
+ * - may not match RCU dereferenced payload
+ * - payload should contain own length
+ */
#ifdef KEY_DEBUGGING
unsigned magic;
@@ -101,6 +96,14 @@ struct key {
#define KEY_DEBUG_MAGIC_X 0xf8e9dacbu
#endif
+ unsigned long flags; /* status flags (change with bitops) */
+#define KEY_FLAG_INSTANTIATED 0 /* set if key has been instantiated */
+#define KEY_FLAG_DEAD 1 /* set if key type has been deleted */
+#define KEY_FLAG_REVOKED 2 /* set if key had been revoked */
+#define KEY_FLAG_IN_QUOTA 3 /* set if key consumes quota */
+#define KEY_FLAG_USER_CONSTRUCT 4 /* set if key is being constructed in userspace */
+#define KEY_FLAG_NEGATIVE 5 /* set if key is negative */
+
/* the description string
* - this is used to match a key against search criteria
* - this should be a printable string
@@ -196,10 +199,12 @@ extern int key_payload_reserve(struct key *key, size_t datalen);
extern int key_instantiate_and_link(struct key *key,
const void *data,
size_t datalen,
- struct key *keyring);
+ struct key *keyring,
+ struct key *instkey);
extern int key_negate_and_link(struct key *key,
unsigned timeout,
- struct key *keyring);
+ struct key *keyring,
+ struct key *instkey);
extern void key_revoke(struct key *key);
extern void key_put(struct key *key);
@@ -242,14 +247,13 @@ extern struct key *keyring_search(struct key *keyring,
struct key_type *type,
const char *description);
-extern struct key *search_process_keyrings(struct key_type *type,
- const char *description);
-
extern int keyring_add_key(struct key *keyring,
struct key *key);
extern struct key *key_lookup(key_serial_t id);
+extern void keyring_replace_payload(struct key *key, void *replacement);
+
#define key_serial(key) ((key) ? (key)->serial : 0)
/*
@@ -268,14 +272,22 @@ extern void key_fsuid_changed(struct task_struct *tsk);
extern void key_fsgid_changed(struct task_struct *tsk);
extern void key_init(void);
+#define __install_session_keyring(tsk, keyring) \
+({ \
+ struct key *old_session = tsk->signal->session_keyring; \
+ tsk->signal->session_keyring = keyring; \
+ old_session; \
+})
+
#else /* CONFIG_KEYS */
#define key_validate(k) 0
#define key_serial(k) 0
-#define key_get(k) NULL
+#define key_get(k) ({ NULL; })
#define key_put(k) do { } while(0)
#define alloc_uid_keyring(u) 0
#define switch_uid_keyring(u) do { } while(0)
+#define __install_session_keyring(t, k) ({ NULL; })
#define copy_keys(f,t) 0
#define copy_thread_group_keys(t) 0
#define exit_keys(t) do { } while(0)
diff --git a/include/linux/keyctl.h b/include/linux/keyctl.h
index 381dedc370a..8d7c59a29e0 100644
--- a/include/linux/keyctl.h
+++ b/include/linux/keyctl.h
@@ -20,6 +20,16 @@
#define KEY_SPEC_USER_SESSION_KEYRING -5 /* - key ID for UID-session keyring */
#define KEY_SPEC_GROUP_KEYRING -6 /* - key ID for GID-specific keyring */
+/* request-key default keyrings */
+#define KEY_REQKEY_DEFL_NO_CHANGE -1
+#define KEY_REQKEY_DEFL_DEFAULT 0
+#define KEY_REQKEY_DEFL_THREAD_KEYRING 1
+#define KEY_REQKEY_DEFL_PROCESS_KEYRING 2
+#define KEY_REQKEY_DEFL_SESSION_KEYRING 3
+#define KEY_REQKEY_DEFL_USER_KEYRING 4
+#define KEY_REQKEY_DEFL_USER_SESSION_KEYRING 5
+#define KEY_REQKEY_DEFL_GROUP_KEYRING 6
+
/* keyctl commands */
#define KEYCTL_GET_KEYRING_ID 0 /* ask for a keyring's ID */
#define KEYCTL_JOIN_SESSION_KEYRING 1 /* join or start named session keyring */
@@ -35,5 +45,6 @@
#define KEYCTL_READ 11 /* read a key or keyring's contents */
#define KEYCTL_INSTANTIATE 12 /* instantiate a partially constructed key */
#define KEYCTL_NEGATE 13 /* negate a partially constructed key */
+#define KEYCTL_SET_REQKEY_KEYRING 14 /* set default request-key keyring */
#endif /* _LINUX_KEYCTL_H */
diff --git a/include/linux/klist.h b/include/linux/klist.h
new file mode 100644
index 00000000000..eebf5e5696e
--- /dev/null
+++ b/include/linux/klist.h
@@ -0,0 +1,55 @@
+/*
+ * klist.h - Some generic list helpers, extending struct list_head a bit.
+ *
+ * Implementations are found in lib/klist.c
+ *
+ *
+ * Copyright (C) 2005 Patrick Mochel
+ *
+ * This file is rleased under the GPL v2.
+ */
+
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/kref.h>
+#include <linux/list.h>
+
+
+struct klist {
+ spinlock_t k_lock;
+ struct list_head k_list;
+};
+
+
+extern void klist_init(struct klist * k);
+
+
+struct klist_node {
+ struct klist * n_klist;
+ struct list_head n_node;
+ struct kref n_ref;
+ struct completion n_removed;
+};
+
+extern void klist_add_tail(struct klist * k, struct klist_node * n);
+extern void klist_add_head(struct klist * k, struct klist_node * n);
+
+extern void klist_del(struct klist_node * n);
+extern void klist_remove(struct klist_node * n);
+
+extern int klist_node_attached(struct klist_node * n);
+
+
+struct klist_iter {
+ struct klist * i_klist;
+ struct list_head * i_head;
+ struct klist_node * i_cur;
+};
+
+
+extern void klist_iter_init(struct klist * k, struct klist_iter * i);
+extern void klist_iter_init_node(struct klist * k, struct klist_iter * i,
+ struct klist_node * n);
+extern void klist_iter_exit(struct klist_iter * i);
+extern struct klist_node * klist_next(struct klist_iter * i);
+
diff --git a/include/linux/kmod.h b/include/linux/kmod.h
index 95d0e4b0814..e4a23154940 100644
--- a/include/linux/kmod.h
+++ b/include/linux/kmod.h
@@ -19,6 +19,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <linux/stddef.h>
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/compiler.h>
@@ -34,7 +35,17 @@ static inline int request_module(const char * name, ...) { return -ENOSYS; }
#endif
#define try_then_request_module(x, mod...) ((x) ?: (request_module(mod), (x)))
-extern int call_usermodehelper(char *path, char *argv[], char *envp[], int wait);
+
+struct key;
+extern int call_usermodehelper_keys(char *path, char *argv[], char *envp[],
+ struct key *session_keyring, int wait);
+
+static inline int
+call_usermodehelper(char *path, char **argv, char **envp, int wait)
+{
+ return call_usermodehelper_keys(path, argv, envp, NULL, wait);
+}
+
extern void usermodehelper_init(void);
#endif /* __LINUX_KMOD_H__ */
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 765d660d3be..3b22304f12f 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -33,7 +33,7 @@
extern u64 hotplug_seqnum;
struct kobject {
- char * k_name;
+ const char * k_name;
char name[KOBJ_NAME_LEN];
struct kref kref;
struct list_head entry;
@@ -46,7 +46,7 @@ struct kobject {
extern int kobject_set_name(struct kobject *, const char *, ...)
__attribute__((format(printf,2,3)));
-static inline char * kobject_name(struct kobject * kobj)
+static inline const char * kobject_name(const struct kobject * kobj)
{
return kobj->k_name;
}
@@ -57,7 +57,7 @@ extern void kobject_cleanup(struct kobject *);
extern int kobject_add(struct kobject *);
extern void kobject_del(struct kobject *);
-extern int kobject_rename(struct kobject *, char *new_name);
+extern int kobject_rename(struct kobject *, const char *new_name);
extern int kobject_register(struct kobject *);
extern void kobject_unregister(struct kobject *);
@@ -94,7 +94,7 @@ struct kobj_type {
*/
struct kset_hotplug_ops {
int (*filter)(struct kset *kset, struct kobject *kobj);
- char *(*name)(struct kset *kset, struct kobject *kobj);
+ const char *(*name)(struct kset *kset, struct kobject *kobj);
int (*hotplug)(struct kset *kset, struct kobject *kobj, char **envp,
int num_envp, char *buffer, int buffer_size);
};
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 99ddba5a4e0..5e1a7b0d7b3 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -25,27 +25,45 @@
* Rusty Russell).
* 2004-July Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes
* interface to access function arguments.
+ * 2005-May Hien Nguyen <hien@us.ibm.com> and Jim Keniston
+ * <jkenisto@us.ibm.com> and Prasanna S Panchamukhi
+ * <prasanna@in.ibm.com> added function-return probes.
*/
#include <linux/config.h>
#include <linux/list.h>
#include <linux/notifier.h>
#include <linux/smp.h>
+
#include <asm/kprobes.h>
+/* kprobe_status settings */
+#define KPROBE_HIT_ACTIVE 0x00000001
+#define KPROBE_HIT_SS 0x00000002
+#define KPROBE_REENTER 0x00000004
+#define KPROBE_HIT_SSDONE 0x00000008
+
struct kprobe;
struct pt_regs;
+struct kretprobe;
+struct kretprobe_instance;
typedef int (*kprobe_pre_handler_t) (struct kprobe *, struct pt_regs *);
typedef int (*kprobe_break_handler_t) (struct kprobe *, struct pt_regs *);
typedef void (*kprobe_post_handler_t) (struct kprobe *, struct pt_regs *,
unsigned long flags);
typedef int (*kprobe_fault_handler_t) (struct kprobe *, struct pt_regs *,
int trapnr);
+typedef int (*kretprobe_handler_t) (struct kretprobe_instance *,
+ struct pt_regs *);
+
struct kprobe {
struct hlist_node hlist;
/* list of kprobes for multi-handler support */
struct list_head list;
+ /*count the number of times this probe was temporarily disarmed */
+ unsigned long nmissed;
+
/* location of the probe point */
kprobe_opcode_t *addr;
@@ -85,6 +103,62 @@ struct jprobe {
kprobe_opcode_t *entry; /* probe handling code to jump to */
};
+#ifdef ARCH_SUPPORTS_KRETPROBES
+extern int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs);
+extern void trampoline_post_handler(struct kprobe *p, struct pt_regs *regs,
+ unsigned long flags);
+extern struct task_struct *arch_get_kprobe_task(void *ptr);
+extern void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs);
+extern void arch_kprobe_flush_task(struct task_struct *tk);
+#else /* ARCH_SUPPORTS_KRETPROBES */
+static inline void kretprobe_trampoline(void)
+{
+}
+static inline int trampoline_probe_handler(struct kprobe *p,
+ struct pt_regs *regs)
+{
+ return 0;
+}
+static inline void trampoline_post_handler(struct kprobe *p,
+ struct pt_regs *regs, unsigned long flags)
+{
+}
+static inline void arch_prepare_kretprobe(struct kretprobe *rp,
+ struct pt_regs *regs)
+{
+}
+static inline void arch_kprobe_flush_task(struct task_struct *tk)
+{
+}
+#define arch_get_kprobe_task(ptr) ((struct task_struct *)NULL)
+#endif /* ARCH_SUPPORTS_KRETPROBES */
+/*
+ * Function-return probe -
+ * Note:
+ * User needs to provide a handler function, and initialize maxactive.
+ * maxactive - The maximum number of instances of the probed function that
+ * can be active concurrently.
+ * nmissed - tracks the number of times the probed function's return was
+ * ignored, due to maxactive being too low.
+ *
+ */
+struct kretprobe {
+ struct kprobe kp;
+ kretprobe_handler_t handler;
+ int maxactive;
+ int nmissed;
+ struct hlist_head free_instances;
+ struct hlist_head used_instances;
+};
+
+struct kretprobe_instance {
+ struct hlist_node uflist; /* either on free list or used list */
+ struct hlist_node hlist;
+ struct kretprobe *rp;
+ void *ret_addr;
+ void *stack_addr;
+};
+
#ifdef CONFIG_KPROBES
/* Locks kprobe: irq must be disabled */
void lock_kprobes(void);
@@ -99,11 +173,14 @@ static inline int kprobe_running(void)
extern int arch_prepare_kprobe(struct kprobe *p);
extern void arch_copy_kprobe(struct kprobe *p);
+extern void arch_arm_kprobe(struct kprobe *p);
+extern void arch_disarm_kprobe(struct kprobe *p);
extern void arch_remove_kprobe(struct kprobe *p);
extern void show_registers(struct pt_regs *regs);
/* Get the kprobe at this addr (if any). Must have called lock_kprobes */
struct kprobe *get_kprobe(void *addr);
+struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk);
int register_kprobe(struct kprobe *p);
void unregister_kprobe(struct kprobe *p);
@@ -113,7 +190,16 @@ int register_jprobe(struct jprobe *p);
void unregister_jprobe(struct jprobe *p);
void jprobe_return(void);
-#else
+int register_kretprobe(struct kretprobe *rp);
+void unregister_kretprobe(struct kretprobe *rp);
+
+struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp);
+struct kretprobe_instance *get_rp_inst(void *sara);
+struct kretprobe_instance *get_rp_inst_tsk(struct task_struct *tk);
+void add_rp_inst(struct kretprobe_instance *ri);
+void kprobe_flush_task(struct task_struct *tk);
+void recycle_rp_inst(struct kretprobe_instance *ri);
+#else /* CONFIG_KPROBES */
static inline int kprobe_running(void)
{
return 0;
@@ -135,5 +221,15 @@ static inline void unregister_jprobe(struct jprobe *p)
static inline void jprobe_return(void)
{
}
-#endif
+static inline int register_kretprobe(struct kretprobe *rp)
+{
+ return -ENOSYS;
+}
+static inline void unregister_kretprobe(struct kretprobe *rp)
+{
+}
+static inline void kprobe_flush_task(struct task_struct *tk)
+{
+}
+#endif /* CONFIG_KPROBES */
#endif /* _LINUX_KPROBES_H */
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 505160ab472..6cd9ba63563 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -410,6 +410,7 @@ extern u8 ata_chk_err(struct ata_port *ap);
extern void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf);
extern int ata_port_start (struct ata_port *ap);
extern void ata_port_stop (struct ata_port *ap);
+extern void ata_host_stop (struct ata_host_set *host_set);
extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
extern void ata_qc_prep(struct ata_queued_cmd *qc);
extern int ata_qc_issue_prot(struct ata_queued_cmd *qc);
@@ -420,6 +421,7 @@ extern void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
extern unsigned int ata_dev_classify(struct ata_taskfile *tf);
extern void ata_dev_id_string(u16 *id, unsigned char *s,
unsigned int ofs, unsigned int len);
+extern void ata_dev_config(struct ata_port *ap, unsigned int i);
extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
extern void ata_bmdma_start (struct ata_queued_cmd *qc);
extern void ata_bmdma_stop(struct ata_port *ap);
@@ -466,12 +468,34 @@ static inline u8 ata_chk_status(struct ata_port *ap)
return ap->ops->check_status(ap);
}
+
+/**
+ * ata_pause - Flush writes and pause 400 nanoseconds.
+ * @ap: Port to wait for.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+
static inline void ata_pause(struct ata_port *ap)
{
ata_altstatus(ap);
ndelay(400);
}
+
+/**
+ * ata_busy_wait - Wait for a port status register
+ * @ap: Port to wait for.
+ *
+ * Waits up to max*10 microseconds for the selected bits in the port's
+ * status register to be cleared.
+ * Returns final value of status register.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+
static inline u8 ata_busy_wait(struct ata_port *ap, unsigned int bits,
unsigned int max)
{
@@ -486,6 +510,18 @@ static inline u8 ata_busy_wait(struct ata_port *ap, unsigned int bits,
return status;
}
+
+/**
+ * ata_wait_idle - Wait for a port to be idle.
+ * @ap: Port to wait for.
+ *
+ * Waits up to 10ms for port's BUSY and DRQ signals to clear.
+ * Returns final value of status register.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+
static inline u8 ata_wait_idle(struct ata_port *ap)
{
u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
@@ -524,6 +560,18 @@ static inline void ata_tf_init(struct ata_port *ap, struct ata_taskfile *tf, uns
tf->device = ATA_DEVICE_OBS | ATA_DEV1;
}
+
+/**
+ * ata_irq_on - Enable interrupts on a port.
+ * @ap: Port on which interrupts are enabled.
+ *
+ * Enable interrupts on a legacy IDE device using MMIO or PIO,
+ * wait for idle, clear any pending interrupts.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+
static inline u8 ata_irq_on(struct ata_port *ap)
{
struct ata_ioports *ioaddr = &ap->ioaddr;
@@ -543,6 +591,18 @@ static inline u8 ata_irq_on(struct ata_port *ap)
return tmp;
}
+
+/**
+ * ata_irq_ack - Acknowledge a device interrupt.
+ * @ap: Port on which interrupts are enabled.
+ *
+ * Wait up to 10 ms for legacy IDE device to become idle (BUSY
+ * or BUSY+DRQ clear). Obtain dma status and port status from
+ * device. Clear the interrupt. Return port status.
+ *
+ * LOCKING:
+ */
+
static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)
{
unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY;
@@ -584,6 +644,13 @@ static inline void scr_write(struct ata_port *ap, unsigned int reg, u32 val)
ap->ops->scr_write(ap, reg, val);
}
+static inline void scr_write_flush(struct ata_port *ap, unsigned int reg,
+ u32 val)
+{
+ ap->ops->scr_write(ap, reg, val);
+ (void) ap->ops->scr_read(ap, reg);
+}
+
static inline unsigned int sata_dev_present(struct ata_port *ap)
{
return ((scr_read(ap, SCR_STATUS) & 0xf) == 0x3) ? 1 : 0;
diff --git a/include/linux/list.h b/include/linux/list.h
index 399b51d1721..aab2db21b01 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -185,7 +185,7 @@ static inline void list_del(struct list_head *entry)
* list_for_each_entry_rcu().
*
* Note that the caller is not permitted to immediately free
- * the newly deleted entry. Instead, either synchronize_kernel()
+ * the newly deleted entry. Instead, either synchronize_rcu()
* or call_rcu() must be used to defer freeing until an RCU
* grace period has elapsed.
*/
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index 0d9d2257821..16d4e5a08e1 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -72,6 +72,8 @@ struct nlm_lockowner {
uint32_t pid;
};
+struct nlm_wait;
+
/*
* Memory chunk for NLM client RPC request.
*/
@@ -81,6 +83,7 @@ struct nlm_rqst {
struct nlm_host * a_host; /* host handle */
struct nlm_args a_args; /* arguments */
struct nlm_res a_res; /* result */
+ struct nlm_wait * a_block;
char a_owner[NLMCLNT_OHSIZE];
};
@@ -142,7 +145,9 @@ extern unsigned long nlmsvc_timeout;
* Lockd client functions
*/
struct nlm_rqst * nlmclnt_alloc_call(void);
-int nlmclnt_block(struct nlm_host *, struct file_lock *, u32 *);
+int nlmclnt_prepare_block(struct nlm_rqst *req, struct nlm_host *host, struct file_lock *fl);
+void nlmclnt_finish_block(struct nlm_rqst *req);
+long nlmclnt_block(struct nlm_rqst *req, long timeout);
int nlmclnt_cancel(struct nlm_host *, struct file_lock *);
u32 nlmclnt_grant(struct nlm_lock *);
void nlmclnt_recovery(struct nlm_host *, u32);
diff --git a/include/linux/loop.h b/include/linux/loop.h
index 8220d9c9da0..53fa5159544 100644
--- a/include/linux/loop.h
+++ b/include/linux/loop.h
@@ -61,7 +61,7 @@ struct loop_device {
struct semaphore lo_sem;
struct semaphore lo_ctl_mutex;
struct semaphore lo_bh_mutex;
- atomic_t lo_pending;
+ int lo_pending;
request_queue_t *lo_queue;
};
diff --git a/include/linux/major.h b/include/linux/major.h
index 4b62c42b842..e36a46702d9 100644
--- a/include/linux/major.h
+++ b/include/linux/major.h
@@ -100,6 +100,7 @@
#define I2O_MAJOR 80 /* 80->87 */
#define SHMIQ_MAJOR 85 /* Linux/mips, SGI /dev/shmiq */
+#define SCSI_CHANGER_MAJOR 86
#define IDE6_MAJOR 88
#define IDE7_MAJOR 89
diff --git a/include/linux/mempool.h b/include/linux/mempool.h
index 4a36edf1c97..796220ce47c 100644
--- a/include/linux/mempool.h
+++ b/include/linux/mempool.h
@@ -20,9 +20,14 @@ typedef struct mempool_s {
mempool_free_t *free;
wait_queue_head_t wait;
} mempool_t;
-extern mempool_t * mempool_create(int min_nr, mempool_alloc_t *alloc_fn,
- mempool_free_t *free_fn, void *pool_data);
-extern int mempool_resize(mempool_t *pool, int new_min_nr, unsigned int __nocast gfp_mask);
+
+extern mempool_t *mempool_create(int min_nr, mempool_alloc_t *alloc_fn,
+ mempool_free_t *free_fn, void *pool_data);
+extern mempool_t *mempool_create_node(int min_nr, mempool_alloc_t *alloc_fn,
+ mempool_free_t *free_fn, void *pool_data, int nid);
+
+extern int mempool_resize(mempool_t *pool, int new_min_nr,
+ unsigned int __nocast gfp_mask);
extern void mempool_destroy(mempool_t *pool);
extern void * mempool_alloc(mempool_t *pool, unsigned int __nocast gfp_mask);
extern void mempool_free(void *element, mempool_t *pool);
diff --git a/include/linux/mii.h b/include/linux/mii.h
index 20971fe78a8..374b615ea9e 100644
--- a/include/linux/mii.h
+++ b/include/linux/mii.h
@@ -65,9 +65,13 @@
#define ADVERTISE_SLCT 0x001f /* Selector bits */
#define ADVERTISE_CSMA 0x0001 /* Only selector supported */
#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
+#define ADVERTISE_1000XFULL 0x0020 /* Try for 1000BASE-X full-duplex */
#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
+#define ADVERTISE_1000XHALF 0x0040 /* Try for 1000BASE-X half-duplex */
#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
+#define ADVERTISE_1000XPAUSE 0x0080 /* Try for 1000BASE-X pause */
#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
+#define ADVERTISE_1000XPSE_ASYM 0x0100 /* Try for 1000BASE-X asym pause */
#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */
#define ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */
#define ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymetric pause */
@@ -84,9 +88,13 @@
/* Link partner ability register. */
#define LPA_SLCT 0x001f /* Same as advertise selector */
#define LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */
+#define LPA_1000XFULL 0x0020 /* Can do 1000BASE-X full-duplex */
#define LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */
+#define LPA_1000XHALF 0x0040 /* Can do 1000BASE-X half-duplex */
#define LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */
+#define LPA_1000XPAUSE 0x0080 /* Can do 1000BASE-X pause */
#define LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */
+#define LPA_1000XPAUSE_ASYM 0x0100 /* Can do 1000BASE-X pause asym*/
#define LPA_100BASE4 0x0200 /* Can do 100mbps 4k packets */
#define LPA_PAUSE_CAP 0x0400 /* Can pause */
#define LPA_PAUSE_ASYM 0x0800 /* Can pause asymetrically */
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 17518fe0b31..6eb7f48317f 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -395,19 +395,81 @@ static inline void put_page(struct page *page)
/*
* The zone field is never updated after free_area_init_core()
* sets it, so none of the operations on it need to be atomic.
- * We'll have up to (MAX_NUMNODES * MAX_NR_ZONES) zones total,
- * so we use (MAX_NODES_SHIFT + MAX_ZONES_SHIFT) here to get enough bits.
*/
-#define NODEZONE_SHIFT (sizeof(page_flags_t)*8 - MAX_NODES_SHIFT - MAX_ZONES_SHIFT)
-#define NODEZONE(node, zone) ((node << ZONES_SHIFT) | zone)
+
+
+/*
+ * page->flags layout:
+ *
+ * There are three possibilities for how page->flags get
+ * laid out. The first is for the normal case, without
+ * sparsemem. The second is for sparsemem when there is
+ * plenty of space for node and section. The last is when
+ * we have run out of space and have to fall back to an
+ * alternate (slower) way of determining the node.
+ *
+ * No sparsemem: | NODE | ZONE | ... | FLAGS |
+ * with space for node: | SECTION | NODE | ZONE | ... | FLAGS |
+ * no space for node: | SECTION | ZONE | ... | FLAGS |
+ */
+#ifdef CONFIG_SPARSEMEM
+#define SECTIONS_WIDTH SECTIONS_SHIFT
+#else
+#define SECTIONS_WIDTH 0
+#endif
+
+#define ZONES_WIDTH ZONES_SHIFT
+
+#if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT <= FLAGS_RESERVED
+#define NODES_WIDTH NODES_SHIFT
+#else
+#define NODES_WIDTH 0
+#endif
+
+/* Page flags: | [SECTION] | [NODE] | ZONE | ... | FLAGS | */
+#define SECTIONS_PGOFF ((sizeof(page_flags_t)*8) - SECTIONS_WIDTH)
+#define NODES_PGOFF (SECTIONS_PGOFF - NODES_WIDTH)
+#define ZONES_PGOFF (NODES_PGOFF - ZONES_WIDTH)
+
+/*
+ * We are going to use the flags for the page to node mapping if its in
+ * there. This includes the case where there is no node, so it is implicit.
+ */
+#define FLAGS_HAS_NODE (NODES_WIDTH > 0 || NODES_SHIFT == 0)
+
+#ifndef PFN_SECTION_SHIFT
+#define PFN_SECTION_SHIFT 0
+#endif
+
+/*
+ * Define the bit shifts to access each section. For non-existant
+ * sections we define the shift as 0; that plus a 0 mask ensures
+ * the compiler will optimise away reference to them.
+ */
+#define SECTIONS_PGSHIFT (SECTIONS_PGOFF * (SECTIONS_WIDTH != 0))
+#define NODES_PGSHIFT (NODES_PGOFF * (NODES_WIDTH != 0))
+#define ZONES_PGSHIFT (ZONES_PGOFF * (ZONES_WIDTH != 0))
+
+/* NODE:ZONE or SECTION:ZONE is used to lookup the zone from a page. */
+#if FLAGS_HAS_NODE
+#define ZONETABLE_SHIFT (NODES_SHIFT + ZONES_SHIFT)
+#else
+#define ZONETABLE_SHIFT (SECTIONS_SHIFT + ZONES_SHIFT)
+#endif
+#define ZONETABLE_PGSHIFT ZONES_PGSHIFT
+
+#if SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH > FLAGS_RESERVED
+#error SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH > FLAGS_RESERVED
+#endif
+
+#define ZONES_MASK ((1UL << ZONES_WIDTH) - 1)
+#define NODES_MASK ((1UL << NODES_WIDTH) - 1)
+#define SECTIONS_MASK ((1UL << SECTIONS_WIDTH) - 1)
+#define ZONETABLE_MASK ((1UL << ZONETABLE_SHIFT) - 1)
static inline unsigned long page_zonenum(struct page *page)
{
- return (page->flags >> NODEZONE_SHIFT) & (~(~0UL << ZONES_SHIFT));
-}
-static inline unsigned long page_to_nid(struct page *page)
-{
- return (page->flags >> (NODEZONE_SHIFT + ZONES_SHIFT));
+ return (page->flags >> ZONES_PGSHIFT) & ZONES_MASK;
}
struct zone;
@@ -415,13 +477,44 @@ extern struct zone *zone_table[];
static inline struct zone *page_zone(struct page *page)
{
- return zone_table[page->flags >> NODEZONE_SHIFT];
+ return zone_table[(page->flags >> ZONETABLE_PGSHIFT) &
+ ZONETABLE_MASK];
}
-static inline void set_page_zone(struct page *page, unsigned long nodezone_num)
+static inline unsigned long page_to_nid(struct page *page)
+{
+ if (FLAGS_HAS_NODE)
+ return (page->flags >> NODES_PGSHIFT) & NODES_MASK;
+ else
+ return page_zone(page)->zone_pgdat->node_id;
+}
+static inline unsigned long page_to_section(struct page *page)
{
- page->flags &= ~(~0UL << NODEZONE_SHIFT);
- page->flags |= nodezone_num << NODEZONE_SHIFT;
+ return (page->flags >> SECTIONS_PGSHIFT) & SECTIONS_MASK;
+}
+
+static inline void set_page_zone(struct page *page, unsigned long zone)
+{
+ page->flags &= ~(ZONES_MASK << ZONES_PGSHIFT);
+ page->flags |= (zone & ZONES_MASK) << ZONES_PGSHIFT;
+}
+static inline void set_page_node(struct page *page, unsigned long node)
+{
+ page->flags &= ~(NODES_MASK << NODES_PGSHIFT);
+ page->flags |= (node & NODES_MASK) << NODES_PGSHIFT;
+}
+static inline void set_page_section(struct page *page, unsigned long section)
+{
+ page->flags &= ~(SECTIONS_MASK << SECTIONS_PGSHIFT);
+ page->flags |= (section & SECTIONS_MASK) << SECTIONS_PGSHIFT;
+}
+
+static inline void set_page_links(struct page *page, unsigned long zone,
+ unsigned long node, unsigned long pfn)
+{
+ set_page_zone(page, zone);
+ set_page_node(page, node);
+ set_page_section(page, pfn_to_section_nr(pfn));
}
#ifndef CONFIG_DISCONTIGMEM
@@ -691,6 +784,12 @@ extern void show_mem(void);
extern void si_meminfo(struct sysinfo * val);
extern void si_meminfo_node(struct sysinfo *val, int nid);
+#ifdef CONFIG_NUMA
+extern void setup_per_cpu_pageset(void);
+#else
+static inline void setup_per_cpu_pageset(void) {}
+#endif
+
/* prio_tree.c */
void vma_prio_tree_add(struct vm_area_struct *, struct vm_area_struct *old);
void vma_prio_tree_insert(struct vm_area_struct *, struct prio_tree_root *);
diff --git a/include/linux/mmc/protocol.h b/include/linux/mmc/protocol.h
index 7b904c5102f..896342817b9 100644
--- a/include/linux/mmc/protocol.h
+++ b/include/linux/mmc/protocol.h
@@ -195,6 +195,33 @@ struct _mmc_csd {
#define MMC_VDD_35_36 0x00800000 /* VDD voltage 3.5 ~ 3.6 */
#define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */
+/*
+ * Card Command Classes (CCC)
+ */
+#define CCC_BASIC (1<<0) /* (0) Basic protocol functions */
+ /* (CMD0,1,2,3,4,7,9,10,12,13,15) */
+#define CCC_STREAM_READ (1<<1) /* (1) Stream read commands */
+ /* (CMD11) */
+#define CCC_BLOCK_READ (1<<2) /* (2) Block read commands */
+ /* (CMD16,17,18) */
+#define CCC_STREAM_WRITE (1<<3) /* (3) Stream write commands */
+ /* (CMD20) */
+#define CCC_BLOCK_WRITE (1<<4) /* (4) Block write commands */
+ /* (CMD16,24,25,26,27) */
+#define CCC_ERASE (1<<5) /* (5) Ability to erase blocks */
+ /* (CMD32,33,34,35,36,37,38,39) */
+#define CCC_WRITE_PROT (1<<6) /* (6) Able to write protect blocks */
+ /* (CMD28,29,30) */
+#define CCC_LOCK_CARD (1<<7) /* (7) Able to lock down card */
+ /* (CMD16,CMD42) */
+#define CCC_APP_SPEC (1<<8) /* (8) Application specific */
+ /* (CMD55,56,57,ACMD*) */
+#define CCC_IO_MODE (1<<9) /* (9) I/O mode */
+ /* (CMD5,39,40,52,53) */
+#define CCC_SWITCH (1<<10) /* (10) High speed switch */
+ /* (CMD6,34,35,36,37,50) */
+ /* (11) Reserved */
+ /* (CMD?) */
/*
* CSD field definitions
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index e530c6c092f..6c90461ed99 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -63,6 +63,12 @@ struct per_cpu_pageset {
#endif
} ____cacheline_aligned_in_smp;
+#ifdef CONFIG_NUMA
+#define zone_pcp(__z, __cpu) ((__z)->pageset[(__cpu)])
+#else
+#define zone_pcp(__z, __cpu) (&(__z)->pageset[(__cpu)])
+#endif
+
#define ZONE_DMA 0
#define ZONE_NORMAL 1
#define ZONE_HIGHMEM 2
@@ -122,8 +128,11 @@ struct zone {
*/
unsigned long lowmem_reserve[MAX_NR_ZONES];
+#ifdef CONFIG_NUMA
+ struct per_cpu_pageset *pageset[NR_CPUS];
+#else
struct per_cpu_pageset pageset[NR_CPUS];
-
+#endif
/*
* free areas of different sizes
*/
@@ -145,6 +154,14 @@ struct zone {
int all_unreclaimable; /* All pages pinned */
/*
+ * Does the allocator try to reclaim pages from the zone as soon
+ * as it fails a watermark_ok() in __alloc_pages?
+ */
+ int reclaim_pages;
+ /* A count of how many reclaimers are scanning this zone */
+ atomic_t reclaim_in_progress;
+
+ /*
* prev_priority holds the scanning priority for this zone. It is
* defined as the scanning priority at which we achieved our reclaim
* target at the previous try_to_free_pages() or balance_pgdat()
@@ -252,7 +269,9 @@ typedef struct pglist_data {
struct zone node_zones[MAX_NR_ZONES];
struct zonelist node_zonelists[GFP_ZONETYPES];
int nr_zones;
+#ifdef CONFIG_FLAT_NODE_MEM_MAP
struct page *node_mem_map;
+#endif
struct bootmem_data *bdata;
unsigned long node_start_pfn;
unsigned long node_present_pages; /* total number of physical pages */
@@ -267,6 +286,12 @@ typedef struct pglist_data {
#define node_present_pages(nid) (NODE_DATA(nid)->node_present_pages)
#define node_spanned_pages(nid) (NODE_DATA(nid)->node_spanned_pages)
+#ifdef CONFIG_FLAT_NODE_MEM_MAP
+#define pgdat_page_nr(pgdat, pagenr) ((pgdat)->node_mem_map + (pagenr))
+#else
+#define pgdat_page_nr(pgdat, pagenr) pfn_to_page((pgdat)->node_start_pfn + (pagenr))
+#endif
+#define nid_page_nr(nid, pagenr) pgdat_page_nr(NODE_DATA(nid),(pagenr))
extern struct pglist_data *pgdat_list;
@@ -381,9 +406,9 @@ int lowmem_reserve_ratio_sysctl_handler(struct ctl_table *, int, struct file *,
#include <linux/topology.h>
/* Returns the number of the current Node. */
-#define numa_node_id() (cpu_to_node(_smp_processor_id()))
+#define numa_node_id() (cpu_to_node(raw_smp_processor_id()))
-#ifndef CONFIG_DISCONTIGMEM
+#ifndef CONFIG_NEED_MULTIPLE_NODES
extern struct pglist_data contig_page_data;
#define NODE_DATA(nid) (&contig_page_data)
@@ -391,36 +416,177 @@ extern struct pglist_data contig_page_data;
#define MAX_NODES_SHIFT 1
#define pfn_to_nid(pfn) (0)
-#else /* CONFIG_DISCONTIGMEM */
+#else /* CONFIG_NEED_MULTIPLE_NODES */
#include <asm/mmzone.h>
+#endif /* !CONFIG_NEED_MULTIPLE_NODES */
+
+#ifdef CONFIG_SPARSEMEM
+#include <asm/sparsemem.h>
+#endif
+
#if BITS_PER_LONG == 32 || defined(ARCH_HAS_ATOMIC_UNSIGNED)
/*
* with 32 bit page->flags field, we reserve 8 bits for node/zone info.
* there are 3 zones (2 bits) and this leaves 8-2=6 bits for nodes.
*/
-#define MAX_NODES_SHIFT 6
+#define FLAGS_RESERVED 8
+
#elif BITS_PER_LONG == 64
/*
* with 64 bit flags field, there's plenty of room.
*/
-#define MAX_NODES_SHIFT 10
+#define FLAGS_RESERVED 32
+
+#else
+
+#error BITS_PER_LONG not defined
+
#endif
-#endif /* !CONFIG_DISCONTIGMEM */
+#ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
+#define early_pfn_to_nid(nid) (0UL)
+#endif
+
+#define pfn_to_section_nr(pfn) ((pfn) >> PFN_SECTION_SHIFT)
+#define section_nr_to_pfn(sec) ((sec) << PFN_SECTION_SHIFT)
+
+#ifdef CONFIG_SPARSEMEM
+
+/*
+ * SECTION_SHIFT #bits space required to store a section #
+ *
+ * PA_SECTION_SHIFT physical address to/from section number
+ * PFN_SECTION_SHIFT pfn to/from section number
+ */
+#define SECTIONS_SHIFT (MAX_PHYSMEM_BITS - SECTION_SIZE_BITS)
+
+#define PA_SECTION_SHIFT (SECTION_SIZE_BITS)
+#define PFN_SECTION_SHIFT (SECTION_SIZE_BITS - PAGE_SHIFT)
+
+#define NR_MEM_SECTIONS (1UL << SECTIONS_SHIFT)
+
+#define PAGES_PER_SECTION (1UL << PFN_SECTION_SHIFT)
+#define PAGE_SECTION_MASK (~(PAGES_PER_SECTION-1))
+
+#if (MAX_ORDER - 1 + PAGE_SHIFT) > SECTION_SIZE_BITS
+#error Allocator MAX_ORDER exceeds SECTION_SIZE
+#endif
+
+struct page;
+struct mem_section {
+ /*
+ * This is, logically, a pointer to an array of struct
+ * pages. However, it is stored with some other magic.
+ * (see sparse.c::sparse_init_one_section())
+ *
+ * Making it a UL at least makes someone do a cast
+ * before using it wrong.
+ */
+ unsigned long section_mem_map;
+};
+
+extern struct mem_section mem_section[NR_MEM_SECTIONS];
+
+static inline struct mem_section *__nr_to_section(unsigned long nr)
+{
+ return &mem_section[nr];
+}
+
+/*
+ * We use the lower bits of the mem_map pointer to store
+ * a little bit of information. There should be at least
+ * 3 bits here due to 32-bit alignment.
+ */
+#define SECTION_MARKED_PRESENT (1UL<<0)
+#define SECTION_HAS_MEM_MAP (1UL<<1)
+#define SECTION_MAP_LAST_BIT (1UL<<2)
+#define SECTION_MAP_MASK (~(SECTION_MAP_LAST_BIT-1))
+
+static inline struct page *__section_mem_map_addr(struct mem_section *section)
+{
+ unsigned long map = section->section_mem_map;
+ map &= SECTION_MAP_MASK;
+ return (struct page *)map;
+}
+
+static inline int valid_section(struct mem_section *section)
+{
+ return (section->section_mem_map & SECTION_MARKED_PRESENT);
+}
+
+static inline int section_has_mem_map(struct mem_section *section)
+{
+ return (section->section_mem_map & SECTION_HAS_MEM_MAP);
+}
+
+static inline int valid_section_nr(unsigned long nr)
+{
+ return valid_section(__nr_to_section(nr));
+}
-#if NODES_SHIFT > MAX_NODES_SHIFT
-#error NODES_SHIFT > MAX_NODES_SHIFT
+/*
+ * Given a kernel address, find the home node of the underlying memory.
+ */
+#define kvaddr_to_nid(kaddr) pfn_to_nid(__pa(kaddr) >> PAGE_SHIFT)
+
+static inline struct mem_section *__pfn_to_section(unsigned long pfn)
+{
+ return __nr_to_section(pfn_to_section_nr(pfn));
+}
+
+#define pfn_to_page(pfn) \
+({ \
+ unsigned long __pfn = (pfn); \
+ __section_mem_map_addr(__pfn_to_section(__pfn)) + __pfn; \
+})
+#define page_to_pfn(page) \
+({ \
+ page - __section_mem_map_addr(__nr_to_section( \
+ page_to_section(page))); \
+})
+
+static inline int pfn_valid(unsigned long pfn)
+{
+ if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS)
+ return 0;
+ return valid_section(__nr_to_section(pfn_to_section_nr(pfn)));
+}
+
+/*
+ * These are _only_ used during initialisation, therefore they
+ * can use __initdata ... They could have names to indicate
+ * this restriction.
+ */
+#ifdef CONFIG_NUMA
+#define pfn_to_nid early_pfn_to_nid
#endif
-/* There are currently 3 zones: DMA, Normal & Highmem, thus we need 2 bits */
-#define MAX_ZONES_SHIFT 2
+#define pfn_to_pgdat(pfn) \
+({ \
+ NODE_DATA(pfn_to_nid(pfn)); \
+})
+
+#define early_pfn_valid(pfn) pfn_valid(pfn)
+void sparse_init(void);
+#else
+#define sparse_init() do {} while (0)
+#endif /* CONFIG_SPARSEMEM */
-#if ZONES_SHIFT > MAX_ZONES_SHIFT
-#error ZONES_SHIFT > MAX_ZONES_SHIFT
+#ifdef CONFIG_NODES_SPAN_OTHER_NODES
+#define early_pfn_in_nid(pfn, nid) (early_pfn_to_nid(pfn) == (nid))
+#else
+#define early_pfn_in_nid(pfn, nid) (1)
#endif
+#ifndef early_pfn_valid
+#define early_pfn_valid(pfn) (1)
+#endif
+
+void memory_present(int nid, unsigned long start, unsigned long end);
+unsigned long __init node_memmap_size_bytes(int, unsigned long, unsigned long);
+
#endif /* !__ASSEMBLY__ */
#endif /* __KERNEL__ */
#endif /* _LINUX_MMZONE_H */
diff --git a/include/linux/module.h b/include/linux/module.h
index 0e432a0f4ae..f05372b7fe7 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -51,6 +51,9 @@ struct module_attribute {
ssize_t (*show)(struct module_attribute *, struct module *, char *);
ssize_t (*store)(struct module_attribute *, struct module *,
const char *, size_t count);
+ void (*setup)(struct module *, const char *);
+ int (*test)(struct module *);
+ void (*free)(struct module *);
};
struct module_kobject
@@ -239,6 +242,8 @@ struct module
/* Sysfs stuff. */
struct module_kobject mkobj;
struct module_param_attrs *param_attrs;
+ const char *version;
+ const char *srcversion;
/* Exported symbols */
const struct kernel_symbol *syms;
diff --git a/include/linux/namespace.h b/include/linux/namespace.h
index 9eca1558d72..697991b69f9 100644
--- a/include/linux/namespace.h
+++ b/include/linux/namespace.h
@@ -12,7 +12,6 @@ struct namespace {
struct rw_semaphore sem;
};
-extern void umount_tree(struct vfsmount *);
extern int copy_namespace(int, struct task_struct *);
extern void __put_namespace(struct namespace *namespace);
diff --git a/include/linux/net.h b/include/linux/net.h
index 6d997ff3f10..20cb226b226 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -101,7 +101,6 @@ enum sock_type {
* @sk: internal networking protocol agnostic socket representation
* @wait: wait queue for several uses
* @type: socket type (%SOCK_STREAM, etc)
- * @passcred: credentials (used only in Unix Sockets (aka PF_LOCAL))
*/
struct socket {
socket_state state;
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index ac11d73be4c..3a0ed7f9e80 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -41,7 +41,7 @@
struct divert_blk;
struct vlan_group;
struct ethtool_ops;
-struct netpoll;
+struct netpoll_info;
/* source back-compat hooks */
#define SET_ETHTOOL_OPS(netdev,ops) \
( (netdev)->ethtool_ops = (ops) )
@@ -164,12 +164,6 @@ struct netif_rx_stats
unsigned total;
unsigned dropped;
unsigned time_squeeze;
- unsigned throttled;
- unsigned fastroute_hit;
- unsigned fastroute_success;
- unsigned fastroute_defer;
- unsigned fastroute_deferred_out;
- unsigned fastroute_latency_reduction;
unsigned cpu_collision;
};
@@ -204,7 +198,7 @@ struct hh_cache
/* cached hardware header; allow for machine alignment needs. */
#define HH_DATA_MOD 16
#define HH_DATA_OFF(__len) \
- (HH_DATA_MOD - ((__len) & (HH_DATA_MOD - 1)))
+ (HH_DATA_MOD - (((__len - 1) & (HH_DATA_MOD - 1)) + 1))
#define HH_DATA_ALIGN(__len) \
(((__len)+(HH_DATA_MOD-1))&~(HH_DATA_MOD - 1))
unsigned long hh_data[HH_DATA_ALIGN(LL_MAX_HEADER) / sizeof(long)];
@@ -401,7 +395,7 @@ struct net_device
} reg_state;
/* Net device features */
- int features;
+ unsigned long features;
#define NETIF_F_SG 1 /* Scatter/gather IO. */
#define NETIF_F_IP_CSUM 2 /* Can checksum only TCP/UDP over IPv4. */
#define NETIF_F_NO_CSUM 4 /* Does not require checksum. F.e. loopack. */
@@ -468,7 +462,7 @@ struct net_device
unsigned char *haddr);
int (*neigh_setup)(struct net_device *dev, struct neigh_parms *);
#ifdef CONFIG_NETPOLL
- struct netpoll *np;
+ struct netpoll_info *npinfo;
#endif
#ifdef CONFIG_NET_POLL_CONTROLLER
void (*poll_controller)(struct net_device *dev);
@@ -503,7 +497,7 @@ static inline void *netdev_priv(struct net_device *dev)
#define SET_NETDEV_DEV(net, pdev) ((net)->class_dev.dev = (pdev))
struct packet_type {
- unsigned short type; /* This is really htons(ether_type). */
+ __be16 type; /* This is really htons(ether_type). */
struct net_device *dev; /* NULL is wildcarded here */
int (*func) (struct sk_buff *, struct net_device *,
struct packet_type *);
@@ -562,12 +556,9 @@ static inline int unregister_gifconf(unsigned int family)
struct softnet_data
{
- int throttle;
- int cng_level;
- int avg_blog;
+ struct net_device *output_queue;
struct sk_buff_head input_pkt_queue;
struct list_head poll_list;
- struct net_device *output_queue;
struct sk_buff *completion_queue;
struct net_device backlog_dev; /* Sorry. 8) */
@@ -913,6 +904,7 @@ extern void dev_mc_discard(struct net_device *dev);
extern void dev_set_promiscuity(struct net_device *dev, int inc);
extern void dev_set_allmulti(struct net_device *dev, int inc);
extern void netdev_state_change(struct net_device *dev);
+extern void netdev_features_change(struct net_device *dev);
/* Load a device via the kmod */
extern void dev_load(const char *name);
extern void dev_mcast_init(void);
@@ -924,10 +916,6 @@ extern int skb_checksum_help(struct sk_buff *skb, int inward);
extern void net_enable_timestamp(void);
extern void net_disable_timestamp(void);
-#ifdef CONFIG_SYSCTL
-extern char *net_sysctl_strdup(const char *s);
-#endif
-
#endif /* __KERNEL__ */
#endif /* _LINUX_DEV_H */
diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h
index 9e5750079e0..3ebc36afae1 100644
--- a/include/linux/netfilter_ipv4.h
+++ b/include/linux/netfilter_ipv4.h
@@ -75,12 +75,6 @@ enum nf_ip_hook_priorities {
#define SO_ORIGINAL_DST 80
#ifdef __KERNEL__
-#ifdef CONFIG_NETFILTER_DEBUG
-void nf_debug_ip_local_deliver(struct sk_buff *skb);
-void nf_debug_ip_loopback_xmit(struct sk_buff *newskb);
-void nf_debug_ip_finish_output2(struct sk_buff *skb);
-#endif /*CONFIG_NETFILTER_DEBUG*/
-
extern int ip_route_me_harder(struct sk_buff **pskb);
/* Call this before modifying an existing IP packet: ensures it is
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_core.h b/include/linux/netfilter_ipv4/ip_conntrack_core.h
index d84be02cb4f..694aec9b478 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_core.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_core.h
@@ -1,7 +1,6 @@
#ifndef _IP_CONNTRACK_CORE_H
#define _IP_CONNTRACK_CORE_H
#include <linux/netfilter.h>
-#include <linux/netfilter_ipv4/lockhelp.h>
/* This header is used to share core functionality between the
standalone connection tracking module, and the compatibility layer's use
@@ -47,6 +46,6 @@ static inline int ip_conntrack_confirm(struct sk_buff **pskb)
extern struct list_head *ip_conntrack_hash;
extern struct list_head ip_conntrack_expect_list;
-DECLARE_RWLOCK_EXTERN(ip_conntrack_lock);
+extern rwlock_t ip_conntrack_lock;
#endif /* _IP_CONNTRACK_CORE_H */
diff --git a/include/linux/netfilter_ipv4/ip_nat.h b/include/linux/netfilter_ipv4/ip_nat.h
index 2b72b86176f..e201ec6e990 100644
--- a/include/linux/netfilter_ipv4/ip_nat.h
+++ b/include/linux/netfilter_ipv4/ip_nat.h
@@ -50,10 +50,9 @@ struct ip_nat_multi_range_compat
#ifdef __KERNEL__
#include <linux/list.h>
-#include <linux/netfilter_ipv4/lockhelp.h>
/* Protects NAT hash tables, and NAT-private part of conntracks. */
-DECLARE_RWLOCK_EXTERN(ip_nat_lock);
+extern rwlock_t ip_nat_lock;
/* The structure embedded in the conntrack structure. */
struct ip_nat_info
diff --git a/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h b/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h
index baa83e75715..d9bceedfb3d 100644
--- a/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h
+++ b/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h
@@ -18,7 +18,6 @@ struct clusterip_config;
struct ipt_clusterip_tgt_info {
u_int32_t flags;
- struct clusterip_config *config;
/* only relevant for new ones */
u_int8_t clustermac[6];
@@ -27,6 +26,8 @@ struct ipt_clusterip_tgt_info {
u_int16_t local_nodes[CLUSTERIP_MAX_NODES];
enum clusterip_hashmode hash_mode;
u_int32_t hash_initval;
+
+ struct clusterip_config *config;
};
#endif /*_IPT_CLUSTERIP_H_target*/
diff --git a/include/linux/netfilter_ipv4/listhelp.h b/include/linux/netfilter_ipv4/listhelp.h
index f2ae7c5e57b..360429f4873 100644
--- a/include/linux/netfilter_ipv4/listhelp.h
+++ b/include/linux/netfilter_ipv4/listhelp.h
@@ -2,7 +2,6 @@
#define _LISTHELP_H
#include <linux/config.h>
#include <linux/list.h>
-#include <linux/netfilter_ipv4/lockhelp.h>
/* Header to do more comprehensive job than linux/list.h; assume list
is first entry in structure. */
diff --git a/include/linux/netfilter_ipv4/lockhelp.h b/include/linux/netfilter_ipv4/lockhelp.h
deleted file mode 100644
index a3288633ab4..00000000000
--- a/include/linux/netfilter_ipv4/lockhelp.h
+++ /dev/null
@@ -1,129 +0,0 @@
-#ifndef _LOCKHELP_H
-#define _LOCKHELP_H
-#include <linux/config.h>
-
-#include <linux/spinlock.h>
-#include <asm/atomic.h>
-#include <linux/interrupt.h>
-#include <linux/smp.h>
-
-/* Header to do help in lock debugging. */
-
-#ifdef CONFIG_NETFILTER_DEBUG
-struct spinlock_debug
-{
- spinlock_t l;
- atomic_t locked_by;
-};
-
-struct rwlock_debug
-{
- rwlock_t l;
- long read_locked_map;
- long write_locked_map;
-};
-
-#define DECLARE_LOCK(l) \
-struct spinlock_debug l = { SPIN_LOCK_UNLOCKED, ATOMIC_INIT(-1) }
-#define DECLARE_LOCK_EXTERN(l) \
-extern struct spinlock_debug l
-#define DECLARE_RWLOCK(l) \
-struct rwlock_debug l = { RW_LOCK_UNLOCKED, 0, 0 }
-#define DECLARE_RWLOCK_EXTERN(l) \
-extern struct rwlock_debug l
-
-#define MUST_BE_LOCKED(l) \
-do { if (atomic_read(&(l)->locked_by) != smp_processor_id()) \
- printk("ASSERT %s:%u %s unlocked\n", __FILE__, __LINE__, #l); \
-} while(0)
-
-#define MUST_BE_UNLOCKED(l) \
-do { if (atomic_read(&(l)->locked_by) == smp_processor_id()) \
- printk("ASSERT %s:%u %s locked\n", __FILE__, __LINE__, #l); \
-} while(0)
-
-/* Write locked OK as well. */
-#define MUST_BE_READ_LOCKED(l) \
-do { if (!((l)->read_locked_map & (1UL << smp_processor_id())) \
- && !((l)->write_locked_map & (1UL << smp_processor_id()))) \
- printk("ASSERT %s:%u %s not readlocked\n", __FILE__, __LINE__, #l); \
-} while(0)
-
-#define MUST_BE_WRITE_LOCKED(l) \
-do { if (!((l)->write_locked_map & (1UL << smp_processor_id()))) \
- printk("ASSERT %s:%u %s not writelocked\n", __FILE__, __LINE__, #l); \
-} while(0)
-
-#define MUST_BE_READ_WRITE_UNLOCKED(l) \
-do { if ((l)->read_locked_map & (1UL << smp_processor_id())) \
- printk("ASSERT %s:%u %s readlocked\n", __FILE__, __LINE__, #l); \
- else if ((l)->write_locked_map & (1UL << smp_processor_id())) \
- printk("ASSERT %s:%u %s writelocked\n", __FILE__, __LINE__, #l); \
-} while(0)
-
-#define LOCK_BH(lk) \
-do { \
- MUST_BE_UNLOCKED(lk); \
- spin_lock_bh(&(lk)->l); \
- atomic_set(&(lk)->locked_by, smp_processor_id()); \
-} while(0)
-
-#define UNLOCK_BH(lk) \
-do { \
- MUST_BE_LOCKED(lk); \
- atomic_set(&(lk)->locked_by, -1); \
- spin_unlock_bh(&(lk)->l); \
-} while(0)
-
-#define READ_LOCK(lk) \
-do { \
- MUST_BE_READ_WRITE_UNLOCKED(lk); \
- read_lock_bh(&(lk)->l); \
- set_bit(smp_processor_id(), &(lk)->read_locked_map); \
-} while(0)
-
-#define WRITE_LOCK(lk) \
-do { \
- MUST_BE_READ_WRITE_UNLOCKED(lk); \
- write_lock_bh(&(lk)->l); \
- set_bit(smp_processor_id(), &(lk)->write_locked_map); \
-} while(0)
-
-#define READ_UNLOCK(lk) \
-do { \
- if (!((lk)->read_locked_map & (1UL << smp_processor_id()))) \
- printk("ASSERT: %s:%u %s not readlocked\n", \
- __FILE__, __LINE__, #lk); \
- clear_bit(smp_processor_id(), &(lk)->read_locked_map); \
- read_unlock_bh(&(lk)->l); \
-} while(0)
-
-#define WRITE_UNLOCK(lk) \
-do { \
- MUST_BE_WRITE_LOCKED(lk); \
- clear_bit(smp_processor_id(), &(lk)->write_locked_map); \
- write_unlock_bh(&(lk)->l); \
-} while(0)
-
-#else
-#define DECLARE_LOCK(l) spinlock_t l = SPIN_LOCK_UNLOCKED
-#define DECLARE_LOCK_EXTERN(l) extern spinlock_t l
-#define DECLARE_RWLOCK(l) rwlock_t l = RW_LOCK_UNLOCKED
-#define DECLARE_RWLOCK_EXTERN(l) extern rwlock_t l
-
-#define MUST_BE_LOCKED(l)
-#define MUST_BE_UNLOCKED(l)
-#define MUST_BE_READ_LOCKED(l)
-#define MUST_BE_WRITE_LOCKED(l)
-#define MUST_BE_READ_WRITE_UNLOCKED(l)
-
-#define LOCK_BH(l) spin_lock_bh(l)
-#define UNLOCK_BH(l) spin_unlock_bh(l)
-
-#define READ_LOCK(l) read_lock_bh(l)
-#define WRITE_LOCK(l) write_lock_bh(l)
-#define READ_UNLOCK(l) read_unlock_bh(l)
-#define WRITE_UNLOCK(l) write_unlock_bh(l)
-#endif /*CONFIG_NETFILTER_DEBUG*/
-
-#endif /* _LOCKHELP_H */
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index b2738ac8bc9..3029cad63a0 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -14,6 +14,7 @@
#define NETLINK_SELINUX 7 /* SELinux event notifications */
#define NETLINK_ARPD 8
#define NETLINK_AUDIT 9 /* auditing */
+#define NETLINK_FIB_LOOKUP 10
#define NETLINK_ROUTE6 11 /* af_inet6 route comm channel */
#define NETLINK_IP6_FW 13
#define NETLINK_DNRTMSG 14 /* DECnet routing messages */
@@ -146,7 +147,7 @@ struct netlink_callback
int (*dump)(struct sk_buff * skb, struct netlink_callback *cb);
int (*done)(struct netlink_callback *cb);
int family;
- long args[4];
+ long args[5];
};
struct netlink_notify
@@ -156,7 +157,7 @@ struct netlink_notify
};
static __inline__ struct nlmsghdr *
-__nlmsg_put(struct sk_buff *skb, u32 pid, u32 seq, int type, int len)
+__nlmsg_put(struct sk_buff *skb, u32 pid, u32 seq, int type, int len, int flags)
{
struct nlmsghdr *nlh;
int size = NLMSG_LENGTH(len);
@@ -164,15 +165,31 @@ __nlmsg_put(struct sk_buff *skb, u32 pid, u32 seq, int type, int len)
nlh = (struct nlmsghdr*)skb_put(skb, NLMSG_ALIGN(size));
nlh->nlmsg_type = type;
nlh->nlmsg_len = size;
- nlh->nlmsg_flags = 0;
+ nlh->nlmsg_flags = flags;
nlh->nlmsg_pid = pid;
nlh->nlmsg_seq = seq;
return nlh;
}
+#define NLMSG_NEW(skb, pid, seq, type, len, flags) \
+({ if (skb_tailroom(skb) < (int)NLMSG_SPACE(len)) \
+ goto nlmsg_failure; \
+ __nlmsg_put(skb, pid, seq, type, len, flags); })
+
#define NLMSG_PUT(skb, pid, seq, type, len) \
-({ if (skb_tailroom(skb) < (int)NLMSG_SPACE(len)) goto nlmsg_failure; \
- __nlmsg_put(skb, pid, seq, type, len); })
+ NLMSG_NEW(skb, pid, seq, type, len, 0)
+
+#define NLMSG_NEW_ANSWER(skb, cb, type, len, flags) \
+ NLMSG_NEW(skb, NETLINK_CB((cb)->skb).pid, \
+ (cb)->nlh->nlmsg_seq, type, len, flags)
+
+#define NLMSG_END(skb, nlh) \
+({ (nlh)->nlmsg_len = (skb)->tail - (unsigned char *) (nlh); \
+ (skb)->len; })
+
+#define NLMSG_CANCEL(skb, nlh) \
+({ skb_trim(skb, (unsigned char *) (nlh) - (skb)->data); \
+ -1; })
extern int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
struct nlmsghdr *nlh,
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h
index c0d8b90c520..bcd0ac33f59 100644
--- a/include/linux/netpoll.h
+++ b/include/linux/netpoll.h
@@ -16,14 +16,19 @@ struct netpoll;
struct netpoll {
struct net_device *dev;
char dev_name[16], *name;
- int rx_flags;
void (*rx_hook)(struct netpoll *, int, char *, int);
void (*drop)(struct sk_buff *skb);
u32 local_ip, remote_ip;
u16 local_port, remote_port;
unsigned char local_mac[6], remote_mac[6];
+};
+
+struct netpoll_info {
spinlock_t poll_lock;
int poll_owner;
+ int rx_flags;
+ spinlock_t rx_lock;
+ struct netpoll *rx_np; /* netpoll that registered an rx_hook */
};
void netpoll_poll(struct netpoll *np);
@@ -39,22 +44,35 @@ void netpoll_queue(struct sk_buff *skb);
#ifdef CONFIG_NETPOLL
static inline int netpoll_rx(struct sk_buff *skb)
{
- return skb->dev->np && skb->dev->np->rx_flags && __netpoll_rx(skb);
+ struct netpoll_info *npinfo = skb->dev->npinfo;
+ unsigned long flags;
+ int ret = 0;
+
+ if (!npinfo || (!npinfo->rx_np && !npinfo->rx_flags))
+ return 0;
+
+ spin_lock_irqsave(&npinfo->rx_lock, flags);
+ /* check rx_flags again with the lock held */
+ if (npinfo->rx_flags && __netpoll_rx(skb))
+ ret = 1;
+ spin_unlock_irqrestore(&npinfo->rx_lock, flags);
+
+ return ret;
}
static inline void netpoll_poll_lock(struct net_device *dev)
{
- if (dev->np) {
- spin_lock(&dev->np->poll_lock);
- dev->np->poll_owner = smp_processor_id();
+ if (dev->npinfo) {
+ spin_lock(&dev->npinfo->poll_lock);
+ dev->npinfo->poll_owner = smp_processor_id();
}
}
static inline void netpoll_poll_unlock(struct net_device *dev)
{
- if (dev->np) {
- spin_unlock(&dev->np->poll_lock);
- dev->np->poll_owner = -1;
+ if (dev->npinfo) {
+ dev->npinfo->poll_owner = -1;
+ spin_unlock(&dev->npinfo->poll_lock);
}
}
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index 5ca8a8d8ccd..0c1c306cdae 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -28,7 +28,7 @@
#define NFS4_ACCESS_DELETE 0x0010
#define NFS4_ACCESS_EXECUTE 0x0020
-#define NFS4_FH_PERISTENT 0x0000
+#define NFS4_FH_PERSISTENT 0x0000
#define NFS4_FH_NOEXPIRE_WITH_OPEN 0x0001
#define NFS4_FH_VOLATILE_ANY 0x0002
#define NFS4_FH_VOL_MIGRATION 0x0004
@@ -382,6 +382,8 @@ enum {
NFSPROC4_CLNT_READDIR,
NFSPROC4_CLNT_SERVER_CAPS,
NFSPROC4_CLNT_DELEGRETURN,
+ NFSPROC4_CLNT_GETACL,
+ NFSPROC4_CLNT_SETACL,
};
#endif
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index dbac7f363e5..8ea249110fb 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -15,7 +15,6 @@
#include <linux/pagemap.h>
#include <linux/rwsem.h>
#include <linux/wait.h>
-#include <linux/uio.h>
#include <linux/nfs_fs_sb.h>
@@ -29,7 +28,6 @@
#include <linux/nfs4.h>
#include <linux/nfs_xdr.h>
#include <linux/rwsem.h>
-#include <linux/workqueue.h>
#include <linux/mempool.h>
/*
@@ -44,13 +42,6 @@
#define NFS_DEF_FILE_IO_BUFFER_SIZE 4096
/*
- * The upper limit on timeouts for the exponential backoff algorithm.
- */
-#define NFS_WRITEBACK_DELAY (5*HZ)
-#define NFS_WRITEBACK_LOCKDELAY (60*HZ)
-#define NFS_COMMIT_DELAY (5*HZ)
-
-/*
* superblock magic number for NFS
*/
#define NFS_SUPER_MAGIC 0x6969
@@ -60,9 +51,6 @@
*/
#define NFS_RPC_SWAPFLAGS (RPC_TASK_SWAPPER|RPC_TASK_ROOTCREDS)
-#define NFS_RW_SYNC 0x0001 /* O_SYNC handling */
-#define NFS_RW_SWAP 0x0002 /* This is a swap request */
-
/*
* When flushing a cluster of dirty pages, there can be different
* strategies:
@@ -96,7 +84,8 @@ struct nfs_open_context {
int error;
struct list_head list;
- wait_queue_head_t waitq;
+
+ __u64 dir_cookie;
};
/*
@@ -104,6 +93,8 @@ struct nfs_open_context {
*/
struct nfs_delegation;
+struct posix_acl;
+
/*
* nfs fs inode data in memory
*/
@@ -140,7 +131,6 @@ struct nfs_inode {
*
* mtime != read_cache_mtime
*/
- unsigned long readdir_timestamp;
unsigned long read_cache_jiffies;
unsigned long attrtimeo;
unsigned long attrtimeo_timestamp;
@@ -158,6 +148,10 @@ struct nfs_inode {
atomic_t data_updates;
struct nfs_access_entry cache_access;
+#ifdef CONFIG_NFS_V3_ACL
+ struct posix_acl *acl_access;
+ struct posix_acl *acl_default;
+#endif
/*
* This is the cookie verifier used for NFSv3 readdir
@@ -183,13 +177,13 @@ struct nfs_inode {
wait_queue_head_t nfs_i_wait;
#ifdef CONFIG_NFS_V4
+ struct nfs4_cached_acl *nfs4_acl;
/* NFSv4 state */
struct list_head open_states;
struct nfs_delegation *delegation;
int delegation_state;
struct rw_semaphore rwsem;
#endif /* CONFIG_NFS_V4*/
-
struct inode vfs_inode;
};
@@ -203,6 +197,8 @@ struct nfs_inode {
#define NFS_INO_INVALID_DATA 0x0010 /* cached data is invalid */
#define NFS_INO_INVALID_ATIME 0x0020 /* cached atime is invalid */
#define NFS_INO_INVALID_ACCESS 0x0040 /* cached access cred invalid */
+#define NFS_INO_INVALID_ACL 0x0080 /* cached acls are invalid */
+#define NFS_INO_REVAL_PAGECACHE 0x1000 /* must revalidate pagecache */
static inline struct nfs_inode *NFS_I(struct inode *inode)
{
@@ -294,12 +290,12 @@ extern int nfs_release(struct inode *, struct file *);
extern int nfs_attribute_timeout(struct inode *inode);
extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode);
extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
+extern void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping);
extern int nfs_setattr(struct dentry *, struct iattr *);
extern void nfs_begin_attr_update(struct inode *);
extern void nfs_end_attr_update(struct inode *);
extern void nfs_begin_data_update(struct inode *);
extern void nfs_end_data_update(struct inode *);
-extern void nfs_end_data_update_defer(struct inode *);
extern struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rpc_cred *cred);
extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx);
extern void put_nfs_open_context(struct nfs_open_context *ctx);
@@ -314,6 +310,9 @@ extern u32 root_nfs_parse_addr(char *name); /*__init*/
* linux/fs/nfs/file.c
*/
extern struct inode_operations nfs_file_inode_operations;
+#ifdef CONFIG_NFS_V3
+extern struct inode_operations nfs3_file_inode_operations;
+#endif /* CONFIG_NFS_V3 */
extern struct file_operations nfs_file_operations;
extern struct address_space_operations nfs_file_aops;
@@ -329,6 +328,22 @@ static inline struct rpc_cred *nfs_file_cred(struct file *file)
}
/*
+ * linux/fs/nfs/xattr.c
+ */
+#ifdef CONFIG_NFS_V3_ACL
+extern ssize_t nfs3_listxattr(struct dentry *, char *, size_t);
+extern ssize_t nfs3_getxattr(struct dentry *, const char *, void *, size_t);
+extern int nfs3_setxattr(struct dentry *, const char *,
+ const void *, size_t, int);
+extern int nfs3_removexattr (struct dentry *, const char *name);
+#else
+# define nfs3_listxattr NULL
+# define nfs3_getxattr NULL
+# define nfs3_setxattr NULL
+# define nfs3_removexattr NULL
+#endif
+
+/*
* linux/fs/nfs/direct.c
*/
extern ssize_t nfs_direct_IO(int, struct kiocb *, const struct iovec *, loff_t,
@@ -342,6 +357,9 @@ extern ssize_t nfs_file_direct_write(struct kiocb *iocb, const char __user *buf,
* linux/fs/nfs/dir.c
*/
extern struct inode_operations nfs_dir_inode_operations;
+#ifdef CONFIG_NFS_V3
+extern struct inode_operations nfs3_dir_inode_operations;
+#endif /* CONFIG_NFS_V3 */
extern struct file_operations nfs_dir_operations;
extern struct dentry_operations nfs_dentry_operations;
@@ -377,10 +395,10 @@ extern void nfs_commit_done(struct rpc_task *);
*/
extern int nfs_sync_inode(struct inode *, unsigned long, unsigned int, int);
#if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
-extern int nfs_commit_inode(struct inode *, unsigned long, unsigned int, int);
+extern int nfs_commit_inode(struct inode *, int);
#else
static inline int
-nfs_commit_inode(struct inode *inode, unsigned long idx_start, unsigned int npages, int how)
+nfs_commit_inode(struct inode *inode, int how)
{
return 0;
}
@@ -434,11 +452,6 @@ static inline void nfs_writedata_free(struct nfs_write_data *p)
mempool_free(p, nfs_wdata_mempool);
}
-/* Hack for future NFS swap support */
-#ifndef IS_SWAPFILE
-# define IS_SWAPFILE(inode) (0)
-#endif
-
/*
* linux/fs/nfs/read.c
*/
@@ -468,6 +481,29 @@ static inline void nfs_readdata_free(struct nfs_read_data *p)
extern void nfs_readdata_release(struct rpc_task *task);
/*
+ * linux/fs/nfs3proc.c
+ */
+#ifdef CONFIG_NFS_V3_ACL
+extern struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type);
+extern int nfs3_proc_setacl(struct inode *inode, int type,
+ struct posix_acl *acl);
+extern int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode,
+ mode_t mode);
+extern void nfs3_forget_cached_acls(struct inode *inode);
+#else
+static inline int nfs3_proc_set_default_acl(struct inode *dir,
+ struct inode *inode,
+ mode_t mode)
+{
+ return 0;
+}
+
+static inline void nfs3_forget_cached_acls(struct inode *inode)
+{
+}
+#endif /* CONFIG_NFS_V3_ACL */
+
+/*
* linux/fs/mount_clnt.c
* (Used only by nfsroot module)
*/
@@ -515,230 +551,6 @@ extern void * nfs_root_data(void);
#define NFS_JUKEBOX_RETRY_TIME (5 * HZ)
-#ifdef CONFIG_NFS_V4
-
-struct idmap;
-
-/*
- * In a seqid-mutating op, this macro controls which error return
- * values trigger incrementation of the seqid.
- *
- * from rfc 3010:
- * The client MUST monotonically increment the sequence number for the
- * CLOSE, LOCK, LOCKU, OPEN, OPEN_CONFIRM, and OPEN_DOWNGRADE
- * operations. This is true even in the event that the previous
- * operation that used the sequence number received an error. The only
- * exception to this rule is if the previous operation received one of
- * the following errors: NFSERR_STALE_CLIENTID, NFSERR_STALE_STATEID,
- * NFSERR_BAD_STATEID, NFSERR_BAD_SEQID, NFSERR_BADXDR,
- * NFSERR_RESOURCE, NFSERR_NOFILEHANDLE.
- *
- */
-#define seqid_mutating_err(err) \
-(((err) != NFSERR_STALE_CLIENTID) && \
- ((err) != NFSERR_STALE_STATEID) && \
- ((err) != NFSERR_BAD_STATEID) && \
- ((err) != NFSERR_BAD_SEQID) && \
- ((err) != NFSERR_BAD_XDR) && \
- ((err) != NFSERR_RESOURCE) && \
- ((err) != NFSERR_NOFILEHANDLE))
-
-enum nfs4_client_state {
- NFS4CLNT_OK = 0,
-};
-
-/*
- * The nfs4_client identifies our client state to the server.
- */
-struct nfs4_client {
- struct list_head cl_servers; /* Global list of servers */
- struct in_addr cl_addr; /* Server identifier */
- u64 cl_clientid; /* constant */
- nfs4_verifier cl_confirm;
- unsigned long cl_state;
-
- u32 cl_lockowner_id;
-
- /*
- * The following rwsem ensures exclusive access to the server
- * while we recover the state following a lease expiration.
- */
- struct rw_semaphore cl_sem;
-
- struct list_head cl_delegations;
- struct list_head cl_state_owners;
- struct list_head cl_unused;
- int cl_nunused;
- spinlock_t cl_lock;
- atomic_t cl_count;
-
- struct rpc_clnt * cl_rpcclient;
- struct rpc_cred * cl_cred;
-
- struct list_head cl_superblocks; /* List of nfs_server structs */
-
- unsigned long cl_lease_time;
- unsigned long cl_last_renewal;
- struct work_struct cl_renewd;
- struct work_struct cl_recoverd;
-
- wait_queue_head_t cl_waitq;
- struct rpc_wait_queue cl_rpcwaitq;
-
- /* used for the setclientid verifier */
- struct timespec cl_boot_time;
-
- /* idmapper */
- struct idmap * cl_idmap;
-
- /* Our own IP address, as a null-terminated string.
- * This is used to generate the clientid, and the callback address.
- */
- char cl_ipaddr[16];
- unsigned char cl_id_uniquifier;
-};
-
-/*
- * NFS4 state_owners and lock_owners are simply labels for ordered
- * sequences of RPC calls. Their sole purpose is to provide once-only
- * semantics by allowing the server to identify replayed requests.
- *
- * The ->so_sema is held during all state_owner seqid-mutating operations:
- * OPEN, OPEN_DOWNGRADE, and CLOSE. Its purpose is to properly serialize
- * so_seqid.
- */
-struct nfs4_state_owner {
- struct list_head so_list; /* per-clientid list of state_owners */
- struct nfs4_client *so_client;
- u32 so_id; /* 32-bit identifier, unique */
- struct semaphore so_sema;
- u32 so_seqid; /* protected by so_sema */
- atomic_t so_count;
-
- struct rpc_cred *so_cred; /* Associated cred */
- struct list_head so_states;
- struct list_head so_delegations;
-};
-
-/*
- * struct nfs4_state maintains the client-side state for a given
- * (state_owner,inode) tuple (OPEN) or state_owner (LOCK).
- *
- * OPEN:
- * In order to know when to OPEN_DOWNGRADE or CLOSE the state on the server,
- * we need to know how many files are open for reading or writing on a
- * given inode. This information too is stored here.
- *
- * LOCK: one nfs4_state (LOCK) to hold the lock stateid nfs4_state(OPEN)
- */
-
-struct nfs4_lock_state {
- struct list_head ls_locks; /* Other lock stateids */
- fl_owner_t ls_owner; /* POSIX lock owner */
-#define NFS_LOCK_INITIALIZED 1
- int ls_flags;
- u32 ls_seqid;
- u32 ls_id;
- nfs4_stateid ls_stateid;
- atomic_t ls_count;
-};
-
-/* bits for nfs4_state->flags */
-enum {
- LK_STATE_IN_USE,
- NFS_DELEGATED_STATE,
-};
-
-struct nfs4_state {
- struct list_head open_states; /* List of states for the same state_owner */
- struct list_head inode_states; /* List of states for the same inode */
- struct list_head lock_states; /* List of subservient lock stateids */
-
- struct nfs4_state_owner *owner; /* Pointer to the open owner */
- struct inode *inode; /* Pointer to the inode */
-
- unsigned long flags; /* Do we hold any locks? */
- struct semaphore lock_sema; /* Serializes file locking operations */
- rwlock_t state_lock; /* Protects the lock_states list */
-
- nfs4_stateid stateid;
-
- unsigned int nreaders;
- unsigned int nwriters;
- int state; /* State on the server (R,W, or RW) */
- atomic_t count;
-};
-
-
-struct nfs4_exception {
- long timeout;
- int retry;
-};
-
-struct nfs4_state_recovery_ops {
- int (*recover_open)(struct nfs4_state_owner *, struct nfs4_state *);
- int (*recover_lock)(struct nfs4_state *, struct file_lock *);
-};
-
-extern struct dentry_operations nfs4_dentry_operations;
-extern struct inode_operations nfs4_dir_inode_operations;
-
-/* nfs4proc.c */
-extern int nfs4_map_errors(int err);
-extern int nfs4_proc_setclientid(struct nfs4_client *, u32, unsigned short);
-extern int nfs4_proc_setclientid_confirm(struct nfs4_client *);
-extern int nfs4_proc_async_renew(struct nfs4_client *);
-extern int nfs4_proc_renew(struct nfs4_client *);
-extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode);
-extern struct inode *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
-extern int nfs4_open_revalidate(struct inode *, struct dentry *, int);
-
-extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;
-extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops;
-
-/* nfs4renewd.c */
-extern void nfs4_schedule_state_renewal(struct nfs4_client *);
-extern void nfs4_renewd_prepare_shutdown(struct nfs_server *);
-extern void nfs4_kill_renewd(struct nfs4_client *);
-
-/* nfs4state.c */
-extern void init_nfsv4_state(struct nfs_server *);
-extern void destroy_nfsv4_state(struct nfs_server *);
-extern struct nfs4_client *nfs4_get_client(struct in_addr *);
-extern void nfs4_put_client(struct nfs4_client *clp);
-extern int nfs4_init_client(struct nfs4_client *clp);
-extern struct nfs4_client *nfs4_find_client(struct in_addr *);
-extern u32 nfs4_alloc_lockowner_id(struct nfs4_client *);
-
-extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *);
-extern void nfs4_put_state_owner(struct nfs4_state_owner *);
-extern void nfs4_drop_state_owner(struct nfs4_state_owner *);
-extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *);
-extern void nfs4_put_open_state(struct nfs4_state *);
-extern void nfs4_close_state(struct nfs4_state *, mode_t);
-extern struct nfs4_state *nfs4_find_state(struct inode *, struct rpc_cred *, mode_t mode);
-extern void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp);
-extern void nfs4_schedule_state_recovery(struct nfs4_client *);
-extern struct nfs4_lock_state *nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t);
-extern struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t);
-extern void nfs4_put_lock_state(struct nfs4_lock_state *state);
-extern void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *ls);
-extern void nfs4_notify_setlk(struct nfs4_state *, struct file_lock *, struct nfs4_lock_state *);
-extern void nfs4_notify_unlck(struct nfs4_state *, struct file_lock *, struct nfs4_lock_state *);
-extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t);
-
-
-
-struct nfs4_mount_data;
-#else
-#define init_nfsv4_state(server) do { } while (0)
-#define destroy_nfsv4_state(server) do { } while (0)
-#define nfs4_put_state_owner(inode, owner) do { } while (0)
-#define nfs4_put_open_state(state) do { } while (0)
-#define nfs4_close_state(a, b) do { } while (0)
-#define nfs4_renewd_prepare_shutdown(server) do { } while (0)
-#endif
-
#endif /* __KERNEL__ */
/*
diff --git a/include/linux/nfs_fs_i.h b/include/linux/nfs_fs_i.h
index e9a749588a7..e2c18dabff8 100644
--- a/include/linux/nfs_fs_i.h
+++ b/include/linux/nfs_fs_i.h
@@ -16,6 +16,11 @@ struct nfs_lock_info {
struct nlm_lockowner *owner;
};
+struct nfs4_lock_state;
+struct nfs4_lock_info {
+ struct nfs4_lock_state *owner;
+};
+
/*
* Lock flag values
*/
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index fc51645d61e..3d3a305488c 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -10,6 +10,7 @@
struct nfs_server {
struct rpc_clnt * client; /* RPC client handle */
struct rpc_clnt * client_sys; /* 2nd handle for FSINFO */
+ struct rpc_clnt * client_acl; /* ACL RPC client handle */
struct nfs_rpc_ops * rpc_ops; /* NFS protocol vector */
struct backing_dev_info backing_dev_info;
int flags; /* various flags */
diff --git a/include/linux/nfs_mount.h b/include/linux/nfs_mount.h
index 0071428231f..659c7543845 100644
--- a/include/linux/nfs_mount.h
+++ b/include/linux/nfs_mount.h
@@ -58,6 +58,7 @@ struct nfs_mount_data {
#define NFS_MOUNT_KERBEROS 0x0100 /* 3 */
#define NFS_MOUNT_NONLM 0x0200 /* 3 */
#define NFS_MOUNT_BROKEN_SUID 0x0400 /* 4 */
+#define NFS_MOUNT_NOACL 0x0800 /* 4 */
#define NFS_MOUNT_STRICTLOCK 0x1000 /* reserved for NFSv4 */
#define NFS_MOUNT_SECFLAVOUR 0x2000 /* 5 */
#define NFS_MOUNT_FLAGMASK 0xFFFF
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
index 39e4895bcdb..da2e077b65e 100644
--- a/include/linux/nfs_page.h
+++ b/include/linux/nfs_page.h
@@ -20,12 +20,19 @@
#include <asm/atomic.h>
/*
+ * Valid flags for the radix tree
+ */
+#define NFS_PAGE_TAG_DIRTY 0
+#define NFS_PAGE_TAG_WRITEBACK 1
+
+/*
* Valid flags for a dirty buffer
*/
#define PG_BUSY 0
#define PG_NEED_COMMIT 1
#define PG_NEED_RESCHED 2
+struct nfs_inode;
struct nfs_page {
struct list_head wb_list, /* Defines state of page: */
*wb_list_head; /* read/write/commit */
@@ -54,14 +61,17 @@ extern void nfs_clear_request(struct nfs_page *req);
extern void nfs_release_request(struct nfs_page *req);
-extern void nfs_list_add_request(struct nfs_page *, struct list_head *);
-
+extern int nfs_scan_lock_dirty(struct nfs_inode *nfsi, struct list_head *dst,
+ unsigned long idx_start, unsigned int npages);
extern int nfs_scan_list(struct list_head *, struct list_head *,
unsigned long, unsigned int);
extern int nfs_coalesce_requests(struct list_head *, struct list_head *,
unsigned int);
extern int nfs_wait_on_request(struct nfs_page *);
extern void nfs_unlock_request(struct nfs_page *req);
+extern int nfs_set_page_writeback_locked(struct nfs_page *req);
+extern void nfs_clear_page_writeback(struct nfs_page *req);
+
/*
* Lock the page of an asynchronous request without incrementing the wb_count
@@ -86,6 +96,18 @@ nfs_lock_request(struct nfs_page *req)
return 1;
}
+/**
+ * nfs_list_add_request - Insert a request into a list
+ * @req: request
+ * @head: head of list into which to insert the request.
+ */
+static inline void
+nfs_list_add_request(struct nfs_page *req, struct list_head *head)
+{
+ list_add_tail(&req->wb_list, head);
+ req->wb_list_head = head;
+}
+
/**
* nfs_list_remove_request - Remove a request from its wb_list
@@ -96,10 +118,6 @@ nfs_list_remove_request(struct nfs_page *req)
{
if (list_empty(&req->wb_list))
return;
- if (!NFS_WBACK_BUSY(req)) {
- printk(KERN_ERR "NFS: unlocked request attempted removed from list!\n");
- BUG();
- }
list_del_init(&req->wb_list);
req->wb_list_head = NULL;
}
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 47037d9521c..a2bf6914ff1 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -2,6 +2,7 @@
#define _LINUX_NFS_XDR_H
#include <linux/sunrpc/xprt.h>
+#include <linux/nfsacl.h>
struct nfs4_fsid {
__u64 major;
@@ -326,6 +327,20 @@ struct nfs_setattrargs {
const u32 * bitmask;
};
+struct nfs_setaclargs {
+ struct nfs_fh * fh;
+ size_t acl_len;
+ unsigned int acl_pgbase;
+ struct page ** acl_pages;
+};
+
+struct nfs_getaclargs {
+ struct nfs_fh * fh;
+ size_t acl_len;
+ unsigned int acl_pgbase;
+ struct page ** acl_pages;
+};
+
struct nfs_setattrres {
struct nfs_fattr * fattr;
const struct nfs_server * server;
@@ -354,6 +369,20 @@ struct nfs_readdirargs {
struct page ** pages;
};
+struct nfs3_getaclargs {
+ struct nfs_fh * fh;
+ int mask;
+ struct page ** pages;
+};
+
+struct nfs3_setaclargs {
+ struct inode * inode;
+ int mask;
+ struct posix_acl * acl_access;
+ struct posix_acl * acl_default;
+ struct page ** pages;
+};
+
struct nfs_diropok {
struct nfs_fh * fh;
struct nfs_fattr * fattr;
@@ -477,6 +506,15 @@ struct nfs3_readdirres {
int plus;
};
+struct nfs3_getaclres {
+ struct nfs_fattr * fattr;
+ int mask;
+ unsigned int acl_access_count;
+ unsigned int acl_default_count;
+ struct posix_acl * acl_access;
+ struct posix_acl * acl_default;
+};
+
#ifdef CONFIG_NFS_V4
typedef u64 clientid4;
@@ -667,6 +705,7 @@ struct nfs_rpc_ops {
int version; /* Protocol version */
struct dentry_operations *dentry_ops;
struct inode_operations *dir_inode_ops;
+ struct inode_operations *file_inode_ops;
int (*getroot) (struct nfs_server *, struct nfs_fh *,
struct nfs_fsinfo *);
@@ -713,6 +752,7 @@ struct nfs_rpc_ops {
int (*file_open) (struct inode *, struct file *);
int (*file_release) (struct inode *, struct file *);
int (*lock)(struct file *, int, struct file_lock *);
+ void (*clear_acl_cache)(struct inode *);
};
/*
@@ -732,4 +772,7 @@ extern struct rpc_version nfs_version2;
extern struct rpc_version nfs_version3;
extern struct rpc_version nfs_version4;
+extern struct rpc_version nfsacl_version3;
+extern struct rpc_program nfsacl_program;
+
#endif
diff --git a/include/linux/nfsacl.h b/include/linux/nfsacl.h
new file mode 100644
index 00000000000..54487a99beb
--- /dev/null
+++ b/include/linux/nfsacl.h
@@ -0,0 +1,58 @@
+/*
+ * File: linux/nfsacl.h
+ *
+ * (C) 2003 Andreas Gruenbacher <agruen@suse.de>
+ */
+#ifndef __LINUX_NFSACL_H
+#define __LINUX_NFSACL_H
+
+#define NFS_ACL_PROGRAM 100227
+
+#define ACLPROC2_GETACL 1
+#define ACLPROC2_SETACL 2
+#define ACLPROC2_GETATTR 3
+#define ACLPROC2_ACCESS 4
+
+#define ACLPROC3_GETACL 1
+#define ACLPROC3_SETACL 2
+
+
+/* Flags for the getacl/setacl mode */
+#define NFS_ACL 0x0001
+#define NFS_ACLCNT 0x0002
+#define NFS_DFACL 0x0004
+#define NFS_DFACLCNT 0x0008
+
+/* Flag for Default ACL entries */
+#define NFS_ACL_DEFAULT 0x1000
+
+#ifdef __KERNEL__
+
+#include <linux/posix_acl.h>
+
+/* Maximum number of ACL entries over NFS */
+#define NFS_ACL_MAX_ENTRIES 1024
+
+#define NFSACL_MAXWORDS (2*(2+3*NFS_ACL_MAX_ENTRIES))
+#define NFSACL_MAXPAGES ((2*(8+12*NFS_ACL_MAX_ENTRIES) + PAGE_SIZE-1) \
+ >> PAGE_SHIFT)
+
+static inline unsigned int
+nfsacl_size(struct posix_acl *acl_access, struct posix_acl *acl_default)
+{
+ unsigned int w = 16;
+ w += max(acl_access ? (int)acl_access->a_count : 3, 4) * 12;
+ if (acl_default)
+ w += max((int)acl_default->a_count, 4) * 12;
+ return w;
+}
+
+extern unsigned int
+nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode,
+ struct posix_acl *acl, int encode_entries, int typeflag);
+extern unsigned int
+nfsacl_decode(struct xdr_buf *buf, unsigned int base, unsigned int *aclcnt,
+ struct posix_acl **pacl);
+
+#endif /* __KERNEL__ */
+#endif /* __LINUX_NFSACL_H */
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index 8f85d9a5960..5791dfd30dd 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -15,6 +15,7 @@
#include <linux/unistd.h>
#include <linux/dirent.h>
#include <linux/fs.h>
+#include <linux/posix_acl.h>
#include <linux/mount.h>
#include <linux/nfsd/debug.h>
@@ -124,20 +125,39 @@ int nfsd_statfs(struct svc_rqst *, struct svc_fh *,
int nfsd_notify_change(struct inode *, struct iattr *);
int nfsd_permission(struct svc_export *, struct dentry *, int);
+#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
+#ifdef CONFIG_NFSD_V2_ACL
+extern struct svc_version nfsd_acl_version2;
+#else
+#define nfsd_acl_version2 NULL
+#endif
+#ifdef CONFIG_NFSD_V3_ACL
+extern struct svc_version nfsd_acl_version3;
+#else
+#define nfsd_acl_version3 NULL
+#endif
+struct posix_acl *nfsd_get_posix_acl(struct svc_fh *, int);
+int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *);
+#endif
+
/*
* NFSv4 State
*/
#ifdef CONFIG_NFSD_V4
-int nfs4_state_init(void);
+void nfs4_state_init(void);
+int nfs4_state_start(void);
void nfs4_state_shutdown(void);
time_t nfs4_lease_time(void);
void nfs4_reset_lease(time_t leasetime);
+int nfs4_reset_recoverydir(char *recdir);
#else
-static inline int nfs4_state_init(void){return 0;}
+static inline void nfs4_state_init(void){};
+static inline int nfs4_state_start(void){return 0;}
static inline void nfs4_state_shutdown(void){}
static inline time_t nfs4_lease_time(void){return 0;}
static inline void nfs4_reset_lease(time_t leasetime){}
+static inline int nfs4_reset_recoverydir(char *recdir) {return 0;}
#endif
/*
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index b6b2fe1e7c6..a84a3fa99be 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -61,11 +61,6 @@ typedef struct {
#define si_stateownerid si_opaque.so_stateownerid
#define si_fileid si_opaque.so_fileid
-extern stateid_t zerostateid;
-extern stateid_t onestateid;
-
-#define ZERO_STATEID(stateid) (!memcmp((stateid), &zerostateid, sizeof(stateid_t)))
-#define ONE_STATEID(stateid) (!memcmp((stateid), &onestateid, sizeof(stateid_t)))
struct nfs4_cb_recall {
u32 cbr_ident;
@@ -77,8 +72,8 @@ struct nfs4_cb_recall {
};
struct nfs4_delegation {
- struct list_head dl_del_perfile; /* nfs4_file->fi_del_perfile */
- struct list_head dl_del_perclnt; /* nfs4_client->cl_del_perclnt*/
+ struct list_head dl_perfile;
+ struct list_head dl_perclnt;
struct list_head dl_recall_lru; /* delegation recalled */
atomic_t dl_count; /* ref count */
struct nfs4_client *dl_client;
@@ -97,7 +92,6 @@ struct nfs4_delegation {
/* client delegation callback info */
struct nfs4_callback {
/* SETCLIENTID info */
- u32 cb_parsed; /* addr parsed */
u32 cb_addr;
unsigned short cb_port;
u32 cb_prog;
@@ -109,6 +103,8 @@ struct nfs4_callback {
struct rpc_clnt * cb_client;
};
+#define HEXDIR_LEN 33 /* hex version of 16 byte md5 of cl_name plus '\0' */
+
/*
* struct nfs4_client - one per client. Clientids live here.
* o Each nfs4_client is hashed by clientid.
@@ -122,10 +118,11 @@ struct nfs4_callback {
struct nfs4_client {
struct list_head cl_idhash; /* hash by cl_clientid.id */
struct list_head cl_strhash; /* hash by cl_name */
- struct list_head cl_perclient; /* list: stateowners */
- struct list_head cl_del_perclnt; /* list: delegations */
+ struct list_head cl_openowners;
+ struct list_head cl_delegations;
struct list_head cl_lru; /* tail queue */
struct xdr_netobj cl_name; /* id generated by client */
+ char cl_recdir[HEXDIR_LEN]; /* recovery dir */
nfs4_verifier cl_verifier; /* generated by client */
time_t cl_time; /* time of last lease renewal */
u32 cl_addr; /* client ipaddress */
@@ -134,6 +131,7 @@ struct nfs4_client {
nfs4_verifier cl_confirm; /* generated by server */
struct nfs4_callback cl_callback; /* callback info */
atomic_t cl_count; /* ref count */
+ u32 cl_firststate; /* recovery dir creation */
};
/* struct nfs4_client_reset
@@ -143,7 +141,7 @@ struct nfs4_client {
*/
struct nfs4_client_reclaim {
struct list_head cr_strhash; /* hash by cr_name */
- struct xdr_netobj cr_name; /* id generated by client */
+ char cr_recdir[HEXDIR_LEN]; /* recover dir */
};
static inline void
@@ -197,9 +195,9 @@ struct nfs4_stateowner {
struct kref so_ref;
struct list_head so_idhash; /* hash by so_id */
struct list_head so_strhash; /* hash by op_name */
- struct list_head so_perclient; /* nfs4_client->cl_perclient */
- struct list_head so_perfilestate; /* list: nfs4_stateid */
- struct list_head so_perlockowner; /* nfs4_stateid->st_perlockowner */
+ struct list_head so_perclient;
+ struct list_head so_stateids;
+ struct list_head so_perstateid; /* for lockowners only */
struct list_head so_close_lru; /* tail queue */
time_t so_time; /* time of placement on so_close_lru */
int so_is_open_owner; /* 1=openowner,0=lockowner */
@@ -217,9 +215,10 @@ struct nfs4_stateowner {
* share_acces, share_deny on the file.
*/
struct nfs4_file {
+ struct kref fi_ref;
struct list_head fi_hash; /* hash by "struct inode *" */
- struct list_head fi_perfile; /* list: nfs4_stateid */
- struct list_head fi_del_perfile; /* list: nfs4_delegation */
+ struct list_head fi_stateids;
+ struct list_head fi_delegations;
struct inode *fi_inode;
u32 fi_id; /* used with stateowner->so_id
* for stateid_hashtbl hash */
@@ -241,8 +240,8 @@ struct nfs4_file {
struct nfs4_stateid {
struct list_head st_hash;
struct list_head st_perfile;
- struct list_head st_perfilestate;
- struct list_head st_perlockowner;
+ struct list_head st_perstateowner;
+ struct list_head st_lockowners;
struct nfs4_stateowner * st_stateowner;
struct nfs4_file * st_file;
stateid_t st_stateid;
@@ -267,12 +266,9 @@ struct nfs4_stateid {
((err) != nfserr_stale_stateid) && \
((err) != nfserr_bad_stateid))
-extern time_t nfs4_laundromat(void);
extern int nfsd4_renew(clientid_t *clid);
extern int nfs4_preprocess_stateid_op(struct svc_fh *current_fh,
stateid_t *stateid, int flags, struct file **filp);
-extern int nfs4_share_conflict(struct svc_fh *current_fh,
- unsigned int deny_type);
extern void nfs4_lock_state(void);
extern void nfs4_unlock_state(void);
extern int nfs4_in_grace(void);
@@ -282,6 +278,15 @@ extern void nfs4_free_stateowner(struct kref *kref);
extern void nfsd4_probe_callback(struct nfs4_client *clp);
extern void nfsd4_cb_recall(struct nfs4_delegation *dp);
extern void nfs4_put_delegation(struct nfs4_delegation *dp);
+extern int nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname);
+extern void nfsd4_init_recdir(char *recdir_name);
+extern int nfsd4_recdir_load(void);
+extern void nfsd4_shutdown_recdir(void);
+extern int nfs4_client_to_reclaim(const char *name);
+extern int nfs4_has_reclaimed_state(const char *name);
+extern void nfsd4_recdir_purge_old(void);
+extern int nfsd4_create_clid_dir(struct nfs4_client *clp);
+extern void nfsd4_remove_clid_dir(struct nfs4_client *clp);
static inline void
nfs4_put_stateowner(struct nfs4_stateowner *so)
diff --git a/include/linux/nfsd/xdr.h b/include/linux/nfsd/xdr.h
index ecccef777da..130d4f588a3 100644
--- a/include/linux/nfsd/xdr.h
+++ b/include/linux/nfsd/xdr.h
@@ -169,4 +169,8 @@ int nfssvc_encode_entry(struct readdir_cd *, const char *name,
int nfssvc_release_fhandle(struct svc_rqst *, u32 *, struct nfsd_fhandle *);
+/* Helper functions for NFSv2 ACL code */
+u32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp);
+u32 *nfs2svc_decode_fh(u32 *p, struct svc_fh *fhp);
+
#endif /* LINUX_NFSD_H */
diff --git a/include/linux/nfsd/xdr3.h b/include/linux/nfsd/xdr3.h
index 0ae9e0ef5f6..21e18ce7ca6 100644
--- a/include/linux/nfsd/xdr3.h
+++ b/include/linux/nfsd/xdr3.h
@@ -110,6 +110,19 @@ struct nfsd3_commitargs {
__u32 count;
};
+struct nfsd3_getaclargs {
+ struct svc_fh fh;
+ int mask;
+};
+
+struct posix_acl;
+struct nfsd3_setaclargs {
+ struct svc_fh fh;
+ int mask;
+ struct posix_acl *acl_access;
+ struct posix_acl *acl_default;
+};
+
struct nfsd3_attrstat {
__u32 status;
struct svc_fh fh;
@@ -209,6 +222,14 @@ struct nfsd3_commitres {
struct svc_fh fh;
};
+struct nfsd3_getaclres {
+ __u32 status;
+ struct svc_fh fh;
+ int mask;
+ struct posix_acl *acl_access;
+ struct posix_acl *acl_default;
+};
+
/* dummy type for release */
struct nfsd3_fhandle_pair {
__u32 dummy;
@@ -241,6 +262,7 @@ union nfsd3_xdrstore {
struct nfsd3_fsinfores fsinfores;
struct nfsd3_pathconfres pathconfres;
struct nfsd3_commitres commitres;
+ struct nfsd3_getaclres getaclres;
};
#define NFS3_SVC_XDRSIZE sizeof(union nfsd3_xdrstore)
@@ -316,6 +338,10 @@ int nfs3svc_encode_entry(struct readdir_cd *, const char *name,
int nfs3svc_encode_entry_plus(struct readdir_cd *, const char *name,
int namlen, loff_t offset, ino_t ino,
unsigned int);
+/* Helper functions for NFSv3 ACL code */
+u32 *nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, u32 *p,
+ struct svc_fh *fhp);
+u32 *nfs3svc_decode_fh(u32 *p, struct svc_fh *fhp);
#endif /* _LINUX_NFSD_XDR3_H */
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index a1f5ad0be1b..4d24d65c0e8 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -210,6 +210,7 @@ struct nfsd4_open {
u32 op_share_access; /* request */
u32 op_share_deny; /* request */
stateid_t op_stateid; /* response */
+ u32 op_recall; /* recall */
struct nfsd4_change_info op_cinfo; /* response */
u32 op_rflags; /* response */
int op_truncate; /* used during processing */
diff --git a/include/linux/nfsd_idmap.h b/include/linux/nfsd_idmap.h
index 9bb7f30e923..e82746fcad1 100644
--- a/include/linux/nfsd_idmap.h
+++ b/include/linux/nfsd_idmap.h
@@ -43,8 +43,13 @@
/* XXX from linux/nfs_idmap.h */
#define IDMAP_NAMESZ 128
+#ifdef CONFIG_NFSD_V4
void nfsd_idmap_init(void);
void nfsd_idmap_shutdown(void);
+#else
+static inline void nfsd_idmap_init(void) {};
+static inline void nfsd_idmap_shutdown(void) {};
+#endif
int nfsd_map_name_to_uid(struct svc_rqst *, const char *, size_t, __u32 *);
int nfsd_map_name_to_gid(struct svc_rqst *, const char *, size_t, __u32 *);
diff --git a/include/linux/node.h b/include/linux/node.h
index 6e0a697e594..254dc3de650 100644
--- a/include/linux/node.h
+++ b/include/linux/node.h
@@ -27,6 +27,7 @@ struct node {
};
extern int register_node(struct node *, int, struct node *);
+extern void unregister_node(struct node *node);
#define to_node(sys_device) container_of(sys_device, struct node, sysdev)
diff --git a/include/linux/notifier.h b/include/linux/notifier.h
index 9303a003e9a..5937dd6053c 100644
--- a/include/linux/notifier.h
+++ b/include/linux/notifier.h
@@ -56,6 +56,7 @@ extern int notifier_call_chain(struct notifier_block **n, unsigned long val, voi
#define NETDEV_CHANGEADDR 0x0008
#define NETDEV_GOING_DOWN 0x0009
#define NETDEV_CHANGENAME 0x000A
+#define NETDEV_FEAT_CHANGE 0x000B
#define SYS_DOWN 0x0001 /* Notify of system down */
#define SYS_RESTART SYS_DOWN
diff --git a/include/linux/numa.h b/include/linux/numa.h
index bd0c8c4e9a9..f0c539bd3cf 100644
--- a/include/linux/numa.h
+++ b/include/linux/numa.h
@@ -3,7 +3,7 @@
#include <linux/config.h>
-#ifdef CONFIG_DISCONTIGMEM
+#ifndef CONFIG_FLATMEM
#include <asm/numnodes.h>
#endif
diff --git a/include/linux/nvram.h b/include/linux/nvram.h
index b031e41b5e0..9189829c131 100644
--- a/include/linux/nvram.h
+++ b/include/linux/nvram.h
@@ -20,8 +20,6 @@ extern void __nvram_write_byte(unsigned char c, int i);
extern void nvram_write_byte(unsigned char c, int i);
extern int __nvram_check_checksum(void);
extern int nvram_check_checksum(void);
-extern void __nvram_set_checksum(void);
-extern void nvram_set_checksum(void);
#endif
#endif /* _LINUX_NVRAM_H */
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 39ab8c6b565..f5a6695d4d2 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -61,21 +61,20 @@
#define PG_active 6
#define PG_slab 7 /* slab debug (Suparna wants this) */
-#define PG_highmem 8
-#define PG_checked 9 /* kill me in 2.5.<early>. */
-#define PG_arch_1 10
-#define PG_reserved 11
-
-#define PG_private 12 /* Has something at ->private */
-#define PG_writeback 13 /* Page is under writeback */
-#define PG_nosave 14 /* Used for system suspend/resume */
-#define PG_compound 15 /* Part of a compound page */
-
-#define PG_swapcache 16 /* Swap page: swp_entry_t in private */
-#define PG_mappedtodisk 17 /* Has blocks allocated on-disk */
-#define PG_reclaim 18 /* To be reclaimed asap */
-#define PG_nosave_free 19 /* Free, should not be written */
-#define PG_uncached 20 /* Page has been mapped as uncached */
+#define PG_checked 8 /* kill me in 2.5.<early>. */
+#define PG_arch_1 9
+#define PG_reserved 10
+#define PG_private 11 /* Has something at ->private */
+
+#define PG_writeback 12 /* Page is under writeback */
+#define PG_nosave 13 /* Used for system suspend/resume */
+#define PG_compound 14 /* Part of a compound page */
+#define PG_swapcache 15 /* Swap page: swp_entry_t in private */
+
+#define PG_mappedtodisk 16 /* Has blocks allocated on-disk */
+#define PG_reclaim 17 /* To be reclaimed asap */
+#define PG_nosave_free 18 /* Free, should not be written */
+#define PG_uncached 19 /* Page has been mapped as uncached */
/*
* Global page accounting. One instance per CPU. Only unsigned longs are
@@ -136,8 +135,8 @@ struct page_state {
extern void get_page_state(struct page_state *ret);
extern void get_full_page_state(struct page_state *ret);
-extern unsigned long __read_page_state(unsigned offset);
-extern void __mod_page_state(unsigned offset, unsigned long delta);
+extern unsigned long __read_page_state(unsigned long offset);
+extern void __mod_page_state(unsigned long offset, unsigned long delta);
#define read_page_state(member) \
__read_page_state(offsetof(struct page_state, member))
@@ -215,7 +214,7 @@ extern void __mod_page_state(unsigned offset, unsigned long delta);
#define TestSetPageSlab(page) test_and_set_bit(PG_slab, &(page)->flags)
#ifdef CONFIG_HIGHMEM
-#define PageHighMem(page) test_bit(PG_highmem, &(page)->flags)
+#define PageHighMem(page) is_highmem(page_zone(page))
#else
#define PageHighMem(page) 0 /* needed to optimize away at compile time */
#endif
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 0422031161b..d9a25647a29 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -52,12 +52,12 @@ void release_pages(struct page **pages, int nr, int cold);
static inline struct page *page_cache_alloc(struct address_space *x)
{
- return alloc_pages(mapping_gfp_mask(x), 0);
+ return alloc_pages(mapping_gfp_mask(x)|__GFP_NORECLAIM, 0);
}
static inline struct page *page_cache_alloc_cold(struct address_space *x)
{
- return alloc_pages(mapping_gfp_mask(x)|__GFP_COLD, 0);
+ return alloc_pages(mapping_gfp_mask(x)|__GFP_COLD|__GFP_NORECLAIM, 0);
}
typedef int filler_t(void *, struct page *);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index ae27792b5aa..bf608808a60 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -575,6 +575,7 @@
#define PCI_DEVICE_ID_CT_65550 0x00e0
#define PCI_DEVICE_ID_CT_65554 0x00e4
#define PCI_DEVICE_ID_CT_65555 0x00e5
+#define PCI_DEVICE_ID_CT_69000 0x00c0
#define PCI_VENDOR_ID_MIRO 0x1031
#define PCI_DEVICE_ID_MIRO_36050 0x5601
@@ -874,6 +875,7 @@
#define PCI_DEVICE_ID_APPLE_KL_USB_P 0x0026
#define PCI_DEVICE_ID_APPLE_UNI_N_AGP_P 0x0027
#define PCI_DEVICE_ID_APPLE_UNI_N_AGP15 0x002d
+#define PCI_DEVICE_ID_APPLE_UNI_N_PCI15 0x002e
#define PCI_DEVICE_ID_APPLE_UNI_N_FW2 0x0030
#define PCI_DEVICE_ID_APPLE_UNI_N_GMAC2 0x0032
#define PCI_DEVIEC_ID_APPLE_UNI_N_ATA 0x0033
@@ -1230,6 +1232,12 @@
#define PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL 0x0258
#define PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL 0x0259
#define PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL 0x025B
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE 0x0265
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA 0x0266
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2 0x0267
+#define PCI_DEVICE_ID_NVIDIA_NVENET_12 0x0268
+#define PCI_DEVICE_ID_NVIDIA_NVENET_13 0x0269
+#define PCI_DEVICE_ID_NVIDIA_MCP51_AUDIO 0x026B
#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800 0x0280
#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800_8X 0x0281
#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800SE 0x0282
@@ -1560,6 +1568,7 @@
#define PCI_DEVICE_ID_SERVERWORKS_OSB4USB 0x0220
#define PCI_DEVICE_ID_SERVERWORKS_CSB5USB PCI_DEVICE_ID_SERVERWORKS_OSB4USB
#define PCI_DEVICE_ID_SERVERWORKS_CSB6USB 0x0221
+#define PCI_DEVICE_ID_SERVERWORKS_CSB6LPC 0x0227
#define PCI_DEVICE_ID_SERVERWORKS_GCLE 0x0225
#define PCI_DEVICE_ID_SERVERWORKS_GCLE2 0x0227
#define PCI_DEVICE_ID_SERVERWORKS_CSB5ISA 0x0230
@@ -2064,12 +2073,14 @@
#define PCI_VENDOR_ID_BROADCOM 0x14e4
#define PCI_DEVICE_ID_TIGON3_5752 0x1600
+#define PCI_DEVICE_ID_TIGON3_5752M 0x1601
#define PCI_DEVICE_ID_TIGON3_5700 0x1644
#define PCI_DEVICE_ID_TIGON3_5701 0x1645
#define PCI_DEVICE_ID_TIGON3_5702 0x1646
#define PCI_DEVICE_ID_TIGON3_5703 0x1647
#define PCI_DEVICE_ID_TIGON3_5704 0x1648
#define PCI_DEVICE_ID_TIGON3_5704S_2 0x1649
+#define PCI_DEVICE_ID_NX2_5706 0x164a
#define PCI_DEVICE_ID_TIGON3_5702FE 0x164d
#define PCI_DEVICE_ID_TIGON3_5705 0x1653
#define PCI_DEVICE_ID_TIGON3_5705_2 0x1654
@@ -2089,6 +2100,7 @@
#define PCI_DEVICE_ID_TIGON3_5702X 0x16a6
#define PCI_DEVICE_ID_TIGON3_5703X 0x16a7
#define PCI_DEVICE_ID_TIGON3_5704S 0x16a8
+#define PCI_DEVICE_ID_NX2_5706S 0x16aa
#define PCI_DEVICE_ID_TIGON3_5702A3 0x16c6
#define PCI_DEVICE_ID_TIGON3_5703A3 0x16c7
#define PCI_DEVICE_ID_TIGON3_5781 0x16dd
@@ -2373,6 +2385,8 @@
#define PCI_DEVICE_ID_INTEL_82915G_IG 0x2582
#define PCI_DEVICE_ID_INTEL_82915GM_HB 0x2590
#define PCI_DEVICE_ID_INTEL_82915GM_IG 0x2592
+#define PCI_DEVICE_ID_INTEL_82945G_HB 0x2770
+#define PCI_DEVICE_ID_INTEL_82945G_IG 0x2772
#define PCI_DEVICE_ID_INTEL_ICH6_0 0x2640
#define PCI_DEVICE_ID_INTEL_ICH6_1 0x2641
#define PCI_DEVICE_ID_INTEL_ICH6_2 0x2642
diff --git a/include/linux/pfkeyv2.h b/include/linux/pfkeyv2.h
index e6b51922024..724066778af 100644
--- a/include/linux/pfkeyv2.h
+++ b/include/linux/pfkeyv2.h
@@ -245,6 +245,7 @@ struct sadb_x_nat_t_port {
/* Security Association flags */
#define SADB_SAFLAGS_PFS 1
+#define SADB_SAFLAGS_NOPMTUDISC 0x20000000
#define SADB_SAFLAGS_DECAP_DSCP 0x40000000
#define SADB_SAFLAGS_NOECN 0x80000000
diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h
index d2aa214d680..25d2d67c1fa 100644
--- a/include/linux/pkt_cls.h
+++ b/include/linux/pkt_cls.h
@@ -408,6 +408,7 @@ enum
TCF_EM_NBYTE,
TCF_EM_U32,
TCF_EM_META,
+ TCF_EM_TEXT,
__TCF_EM_MAX
};
diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
index 73d84c071cb..1d9da36eb9d 100644
--- a/include/linux/pkt_sched.h
+++ b/include/linux/pkt_sched.h
@@ -427,6 +427,7 @@ enum
TCA_NETEM_UNSPEC,
TCA_NETEM_CORR,
TCA_NETEM_DELAY_DIST,
+ TCA_NETEM_REORDER,
__TCA_NETEM_MAX,
};
@@ -437,7 +438,7 @@ struct tc_netem_qopt
__u32 latency; /* added delay (us) */
__u32 limit; /* fifo limit (packets) */
__u32 loss; /* random packet loss (0=none ~0=100%) */
- __u32 gap; /* re-ordering gap (0 for delay all) */
+ __u32 gap; /* re-ordering gap (0 for none) */
__u32 duplicate; /* random packet dup (0=none ~0=100%) */
__u32 jitter; /* random jitter in latency (us) */
};
@@ -449,6 +450,12 @@ struct tc_netem_corr
__u32 dup_corr; /* duplicate correlation */
};
+struct tc_netem_reorder
+{
+ __u32 probability;
+ __u32 correlation;
+};
+
#define NETEM_DIST_SCALE 8192
#endif
diff --git a/include/linux/pktcdvd.h b/include/linux/pktcdvd.h
index 4e2d2a942ec..4b32bce9a28 100644
--- a/include/linux/pktcdvd.h
+++ b/include/linux/pktcdvd.h
@@ -159,7 +159,7 @@ struct packet_iosched
struct bio *read_queue_tail;
struct bio *write_queue;
struct bio *write_queue_tail;
- int high_prio_read; /* An important read request has been queued */
+ sector_t last_write; /* The sector where the last write ended */
int successive_reads;
};
diff --git a/include/linux/pm.h b/include/linux/pm.h
index ed2b76e7519..14479325e3f 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -103,7 +103,8 @@ extern int pm_active;
/*
* Register a device with power management
*/
-struct pm_dev __deprecated *pm_register(pm_dev_t type, unsigned long id, pm_callback callback);
+struct pm_dev __deprecated *
+pm_register(pm_dev_t type, unsigned long id, pm_callback callback);
/*
* Unregister a device with power management
@@ -190,17 +191,18 @@ typedef u32 __bitwise pm_message_t;
/*
* There are 4 important states driver can be in:
* ON -- driver is working
- * FREEZE -- stop operations and apply whatever policy is applicable to a suspended driver
- * of that class, freeze queues for block like IDE does, drop packets for
- * ethernet, etc... stop DMA engine too etc... so a consistent image can be
- * saved; but do not power any hardware down.
- * SUSPEND - like FREEZE, but hardware is doing as much powersaving as possible. Roughly
- * pci D3.
+ * FREEZE -- stop operations and apply whatever policy is applicable to a
+ * suspended driver of that class, freeze queues for block like IDE
+ * does, drop packets for ethernet, etc... stop DMA engine too etc...
+ * so a consistent image can be saved; but do not power any hardware
+ * down.
+ * SUSPEND - like FREEZE, but hardware is doing as much powersaving as
+ * possible. Roughly pci D3.
*
- * Unfortunately, current drivers only recognize numeric values 0 (ON) and 3 (SUSPEND).
- * We'll need to fix the drivers. So yes, putting 3 to all diferent defines is intentional,
- * and will go away as soon as drivers are fixed. Also note that typedef is neccessary,
- * we'll probably want to switch to
+ * Unfortunately, current drivers only recognize numeric values 0 (ON) and 3
+ * (SUSPEND). We'll need to fix the drivers. So yes, putting 3 to all different
+ * defines is intentional, and will go away as soon as drivers are fixed. Also
+ * note that typedef is neccessary, we'll probably want to switch to
* typedef struct pm_message_t { int event; int flags; } pm_message_t
* or something similar soon.
*/
@@ -222,11 +224,18 @@ struct dev_pm_info {
extern void device_pm_set_parent(struct device * dev, struct device * parent);
-extern int device_suspend(pm_message_t state);
extern int device_power_down(pm_message_t state);
extern void device_power_up(void);
extern void device_resume(void);
+#ifdef CONFIG_PM
+extern int device_suspend(pm_message_t state);
+#else
+static inline int device_suspend(pm_message_t state)
+{
+ return 0;
+}
+#endif
#endif /* __KERNEL__ */
diff --git a/include/linux/posix_acl_xattr.h b/include/linux/posix_acl_xattr.h
index 5efd0a6dad9..6e53c34035c 100644
--- a/include/linux/posix_acl_xattr.h
+++ b/include/linux/posix_acl_xattr.h
@@ -23,13 +23,13 @@
#define ACL_UNDEFINED_ID (-1)
typedef struct {
- __u16 e_tag;
- __u16 e_perm;
- __u32 e_id;
+ __le16 e_tag;
+ __le16 e_perm;
+ __le32 e_id;
} posix_acl_xattr_entry;
typedef struct {
- __u32 a_version;
+ __le32 a_version;
posix_acl_xattr_entry a_entries[0];
} posix_acl_xattr_header;
@@ -52,4 +52,7 @@ posix_acl_xattr_count(size_t size)
return size / sizeof(posix_acl_xattr_entry);
}
+struct posix_acl *posix_acl_from_xattr(const void *value, size_t size);
+int posix_acl_to_xattr(const struct posix_acl *acl, void *buffer, size_t size);
+
#endif /* _POSIX_ACL_XATTR_H */
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 59e505261fd..0563581e3a0 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -74,6 +74,13 @@ struct kcore_list {
size_t size;
};
+struct vmcore {
+ struct list_head list;
+ unsigned long long paddr;
+ unsigned long size;
+ loff_t offset;
+};
+
#ifdef CONFIG_PROC_FS
extern struct proc_dir_entry proc_root;
diff --git a/include/linux/qnx4_fs.h b/include/linux/qnx4_fs.h
index 22ba580b0ae..fc610bb0f73 100644
--- a/include/linux/qnx4_fs.h
+++ b/include/linux/qnx4_fs.h
@@ -46,11 +46,11 @@ struct qnx4_inode_entry {
char di_fname[QNX4_SHORT_NAME_MAX];
qnx4_off_t di_size;
qnx4_xtnt_t di_first_xtnt;
- __u32 di_xblk;
- __s32 di_ftime;
- __s32 di_mtime;
- __s32 di_atime;
- __s32 di_ctime;
+ __le32 di_xblk;
+ __le32 di_ftime;
+ __le32 di_mtime;
+ __le32 di_atime;
+ __le32 di_ctime;
qnx4_nxtnt_t di_num_xtnts;
qnx4_mode_t di_mode;
qnx4_muid_t di_uid;
@@ -63,18 +63,18 @@ struct qnx4_inode_entry {
struct qnx4_link_info {
char dl_fname[QNX4_NAME_MAX];
- __u32 dl_inode_blk;
+ __le32 dl_inode_blk;
__u8 dl_inode_ndx;
__u8 dl_spare[10];
__u8 dl_status;
};
struct qnx4_xblk {
- __u32 xblk_next_xblk;
- __u32 xblk_prev_xblk;
+ __le32 xblk_next_xblk;
+ __le32 xblk_prev_xblk;
__u8 xblk_num_xtnts;
__u8 xblk_spare[3];
- __s32 xblk_num_blocks;
+ __le32 xblk_num_blocks;
qnx4_xtnt_t xblk_xtnts[QNX4_MAX_XTNTS_PER_XBLK];
char xblk_signature[8];
qnx4_xtnt_t xblk_first_xtnt;
diff --git a/include/linux/qnxtypes.h b/include/linux/qnxtypes.h
index fb518e318c7..a3eb1137857 100644
--- a/include/linux/qnxtypes.h
+++ b/include/linux/qnxtypes.h
@@ -12,18 +12,18 @@
#ifndef _QNX4TYPES_H
#define _QNX4TYPES_H
-typedef __u16 qnx4_nxtnt_t;
+typedef __le16 qnx4_nxtnt_t;
typedef __u8 qnx4_ftype_t;
typedef struct {
- __u32 xtnt_blk;
- __u32 xtnt_size;
+ __le32 xtnt_blk;
+ __le32 xtnt_size;
} qnx4_xtnt_t;
-typedef __u16 qnx4_mode_t;
-typedef __u16 qnx4_muid_t;
-typedef __u16 qnx4_mgid_t;
-typedef __u32 qnx4_off_t;
-typedef __u16 qnx4_nlink_t;
+typedef __le16 qnx4_mode_t;
+typedef __le16 qnx4_muid_t;
+typedef __le16 qnx4_mgid_t;
+typedef __le32 qnx4_off_t;
+typedef __le16 qnx4_nlink_t;
#endif
diff --git a/include/linux/quota.h b/include/linux/quota.h
index ac5b90f4f25..700ead45084 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -138,8 +138,11 @@ struct if_dqinfo {
#include <linux/dqblk_v2.h>
/* Maximal numbers of writes for quota operation (insert/delete/update)
- * (over all formats) - info block, 4 pointer blocks, data block */
-#define DQUOT_MAX_WRITES 6
+ * (over VFS all formats) */
+#define DQUOT_INIT_ALLOC max(V1_INIT_ALLOC, V2_INIT_ALLOC)
+#define DQUOT_INIT_REWRITE max(V1_INIT_REWRITE, V2_INIT_REWRITE)
+#define DQUOT_DEL_ALLOC max(V1_DEL_ALLOC, V2_DEL_ALLOC)
+#define DQUOT_DEL_REWRITE max(V1_DEL_REWRITE, V2_DEL_REWRITE)
/*
* Data for one user/group kept in memory
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index e57baa85e74..d211507ab24 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -39,7 +39,8 @@ extern int dquot_commit_info(struct super_block *sb, int type);
extern int dquot_mark_dquot_dirty(struct dquot *dquot);
extern int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path);
-extern int vfs_quota_on_mount(int type, int format_id, struct dentry *dentry);
+extern int vfs_quota_on_mount(struct super_block *sb, char *qf_name,
+ int format_id, int type);
extern int vfs_quota_off(struct super_block *sb, int type);
#define vfs_quota_off_mount(sb, type) vfs_quota_off(sb, type)
extern int vfs_quota_sync(struct super_block *sb, int type);
diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h
new file mode 100644
index 00000000000..e24b74b1115
--- /dev/null
+++ b/include/linux/raid/bitmap.h
@@ -0,0 +1,273 @@
+/*
+ * bitmap.h: Copyright (C) Peter T. Breuer (ptb@ot.uc3m.es) 2003
+ *
+ * additions: Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, Inc.
+ */
+#ifndef BITMAP_H
+#define BITMAP_H 1
+
+#define BITMAP_MAJOR 3
+#define BITMAP_MINOR 38
+
+/*
+ * in-memory bitmap:
+ *
+ * Use 16 bit block counters to track pending writes to each "chunk".
+ * The 2 high order bits are special-purpose, the first is a flag indicating
+ * whether a resync is needed. The second is a flag indicating whether a
+ * resync is active.
+ * This means that the counter is actually 14 bits:
+ *
+ * +--------+--------+------------------------------------------------+
+ * | resync | resync | counter |
+ * | needed | active | |
+ * | (0-1) | (0-1) | (0-16383) |
+ * +--------+--------+------------------------------------------------+
+ *
+ * The "resync needed" bit is set when:
+ * a '1' bit is read from storage at startup.
+ * a write request fails on some drives
+ * a resync is aborted on a chunk with 'resync active' set
+ * It is cleared (and resync-active set) when a resync starts across all drives
+ * of the chunk.
+ *
+ *
+ * The "resync active" bit is set when:
+ * a resync is started on all drives, and resync_needed is set.
+ * resync_needed will be cleared (as long as resync_active wasn't already set).
+ * It is cleared when a resync completes.
+ *
+ * The counter counts pending write requests, plus the on-disk bit.
+ * When the counter is '1' and the resync bits are clear, the on-disk
+ * bit can be cleared aswell, thus setting the counter to 0.
+ * When we set a bit, or in the counter (to start a write), if the fields is
+ * 0, we first set the disk bit and set the counter to 1.
+ *
+ * If the counter is 0, the on-disk bit is clear and the stipe is clean
+ * Anything that dirties the stipe pushes the counter to 2 (at least)
+ * and sets the on-disk bit (lazily).
+ * If a periodic sweep find the counter at 2, it is decremented to 1.
+ * If the sweep find the counter at 1, the on-disk bit is cleared and the
+ * counter goes to zero.
+ *
+ * Also, we'll hijack the "map" pointer itself and use it as two 16 bit block
+ * counters as a fallback when "page" memory cannot be allocated:
+ *
+ * Normal case (page memory allocated):
+ *
+ * page pointer (32-bit)
+ *
+ * [ ] ------+
+ * |
+ * +-------> [ ][ ]..[ ] (4096 byte page == 2048 counters)
+ * c1 c2 c2048
+ *
+ * Hijacked case (page memory allocation failed):
+ *
+ * hijacked page pointer (32-bit)
+ *
+ * [ ][ ] (no page memory allocated)
+ * counter #1 (16-bit) counter #2 (16-bit)
+ *
+ */
+
+#ifdef __KERNEL__
+
+#define PAGE_BITS (PAGE_SIZE << 3)
+#define PAGE_BIT_SHIFT (PAGE_SHIFT + 3)
+
+typedef __u16 bitmap_counter_t;
+#define COUNTER_BITS 16
+#define COUNTER_BIT_SHIFT 4
+#define COUNTER_BYTE_RATIO (COUNTER_BITS / 8)
+#define COUNTER_BYTE_SHIFT (COUNTER_BIT_SHIFT - 3)
+
+#define NEEDED_MASK ((bitmap_counter_t) (1 << (COUNTER_BITS - 1)))
+#define RESYNC_MASK ((bitmap_counter_t) (1 << (COUNTER_BITS - 2)))
+#define COUNTER_MAX ((bitmap_counter_t) RESYNC_MASK - 1)
+#define NEEDED(x) (((bitmap_counter_t) x) & NEEDED_MASK)
+#define RESYNC(x) (((bitmap_counter_t) x) & RESYNC_MASK)
+#define COUNTER(x) (((bitmap_counter_t) x) & COUNTER_MAX)
+
+/* how many counters per page? */
+#define PAGE_COUNTER_RATIO (PAGE_BITS / COUNTER_BITS)
+/* same, except a shift value for more efficient bitops */
+#define PAGE_COUNTER_SHIFT (PAGE_BIT_SHIFT - COUNTER_BIT_SHIFT)
+/* same, except a mask value for more efficient bitops */
+#define PAGE_COUNTER_MASK (PAGE_COUNTER_RATIO - 1)
+
+#define BITMAP_BLOCK_SIZE 512
+#define BITMAP_BLOCK_SHIFT 9
+
+/* how many blocks per chunk? (this is variable) */
+#define CHUNK_BLOCK_RATIO(bitmap) ((bitmap)->chunksize >> BITMAP_BLOCK_SHIFT)
+#define CHUNK_BLOCK_SHIFT(bitmap) ((bitmap)->chunkshift - BITMAP_BLOCK_SHIFT)
+#define CHUNK_BLOCK_MASK(bitmap) (CHUNK_BLOCK_RATIO(bitmap) - 1)
+
+/* when hijacked, the counters and bits represent even larger "chunks" */
+/* there will be 1024 chunks represented by each counter in the page pointers */
+#define PAGEPTR_BLOCK_RATIO(bitmap) \
+ (CHUNK_BLOCK_RATIO(bitmap) << PAGE_COUNTER_SHIFT >> 1)
+#define PAGEPTR_BLOCK_SHIFT(bitmap) \
+ (CHUNK_BLOCK_SHIFT(bitmap) + PAGE_COUNTER_SHIFT - 1)
+#define PAGEPTR_BLOCK_MASK(bitmap) (PAGEPTR_BLOCK_RATIO(bitmap) - 1)
+
+/*
+ * on-disk bitmap:
+ *
+ * Use one bit per "chunk" (block set). We do the disk I/O on the bitmap
+ * file a page at a time. There's a superblock at the start of the file.
+ */
+
+/* map chunks (bits) to file pages - offset by the size of the superblock */
+#define CHUNK_BIT_OFFSET(chunk) ((chunk) + (sizeof(bitmap_super_t) << 3))
+
+#endif
+
+/*
+ * bitmap structures:
+ */
+
+#define BITMAP_MAGIC 0x6d746962
+
+/* use these for bitmap->flags and bitmap->sb->state bit-fields */
+enum bitmap_state {
+ BITMAP_ACTIVE = 0x001, /* the bitmap is in use */
+ BITMAP_STALE = 0x002 /* the bitmap file is out of date or had -EIO */
+};
+
+/* the superblock at the front of the bitmap file -- little endian */
+typedef struct bitmap_super_s {
+ __u32 magic; /* 0 BITMAP_MAGIC */
+ __u32 version; /* 4 the bitmap major for now, could change... */
+ __u8 uuid[16]; /* 8 128 bit uuid - must match md device uuid */
+ __u64 events; /* 24 event counter for the bitmap (1)*/
+ __u64 events_cleared;/*32 event counter when last bit cleared (2) */
+ __u64 sync_size; /* 40 the size of the md device's sync range(3) */
+ __u32 state; /* 48 bitmap state information */
+ __u32 chunksize; /* 52 the bitmap chunk size in bytes */
+ __u32 daemon_sleep; /* 56 seconds between disk flushes */
+
+ __u8 pad[256 - 60]; /* set to zero */
+} bitmap_super_t;
+
+/* notes:
+ * (1) This event counter is updated before the eventcounter in the md superblock
+ * When a bitmap is loaded, it is only accepted if this event counter is equal
+ * to, or one greater than, the event counter in the superblock.
+ * (2) This event counter is updated when the other one is *if*and*only*if* the
+ * array is not degraded. As bits are not cleared when the array is degraded,
+ * this represents the last time that any bits were cleared.
+ * If a device is being added that has an event count with this value or
+ * higher, it is accepted as conforming to the bitmap.
+ * (3)This is the number of sectors represented by the bitmap, and is the range that
+ * resync happens across. For raid1 and raid5/6 it is the size of individual
+ * devices. For raid10 it is the size of the array.
+ */
+
+#ifdef __KERNEL__
+
+/* the in-memory bitmap is represented by bitmap_pages */
+struct bitmap_page {
+ /*
+ * map points to the actual memory page
+ */
+ char *map;
+ /*
+ * in emergencies (when map cannot be alloced), hijack the map
+ * pointer and use it as two counters itself
+ */
+ unsigned int hijacked:1;
+ /*
+ * count of dirty bits on the page
+ */
+ unsigned int count:31;
+};
+
+/* keep track of bitmap file pages that have pending writes on them */
+struct page_list {
+ struct list_head list;
+ struct page *page;
+};
+
+/* the main bitmap structure - one per mddev */
+struct bitmap {
+ struct bitmap_page *bp;
+ unsigned long pages; /* total number of pages in the bitmap */
+ unsigned long missing_pages; /* number of pages not yet allocated */
+
+ mddev_t *mddev; /* the md device that the bitmap is for */
+
+ int counter_bits; /* how many bits per block counter */
+
+ /* bitmap chunksize -- how much data does each bit represent? */
+ unsigned long chunksize;
+ unsigned long chunkshift; /* chunksize = 2^chunkshift (for bitops) */
+ unsigned long chunks; /* total number of data chunks for the array */
+
+ /* We hold a count on the chunk currently being synced, and drop
+ * it when the last block is started. If the resync is aborted
+ * midway, we need to be able to drop that count, so we remember
+ * the counted chunk..
+ */
+ unsigned long syncchunk;
+
+ __u64 events_cleared;
+
+ /* bitmap spinlock */
+ spinlock_t lock;
+
+ long offset; /* offset from superblock if file is NULL */
+ struct file *file; /* backing disk file */
+ struct page *sb_page; /* cached copy of the bitmap file superblock */
+ struct page **filemap; /* list of cache pages for the file */
+ unsigned long *filemap_attr; /* attributes associated w/ filemap pages */
+ unsigned long file_pages; /* number of pages in the file */
+
+ unsigned long flags;
+
+ /*
+ * the bitmap daemon - periodically wakes up and sweeps the bitmap
+ * file, cleaning up bits and flushing out pages to disk as necessary
+ */
+ unsigned long daemon_lastrun; /* jiffies of last run */
+ unsigned long daemon_sleep; /* how many seconds between updates? */
+
+ /*
+ * bitmap_writeback_daemon waits for file-pages that have been written,
+ * as there is no way to get a call-back when a page write completes.
+ */
+ mdk_thread_t *writeback_daemon;
+ spinlock_t write_lock;
+ wait_queue_head_t write_wait;
+ struct list_head complete_pages;
+ mempool_t *write_pool;
+};
+
+/* the bitmap API */
+
+/* these are used only by md/bitmap */
+int bitmap_create(mddev_t *mddev);
+void bitmap_destroy(mddev_t *mddev);
+int bitmap_active(struct bitmap *bitmap);
+
+char *file_path(struct file *file, char *buf, int count);
+void bitmap_print_sb(struct bitmap *bitmap);
+int bitmap_update_sb(struct bitmap *bitmap);
+
+int bitmap_setallbits(struct bitmap *bitmap);
+void bitmap_write_all(struct bitmap *bitmap);
+
+/* these are exported */
+int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors);
+void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors,
+ int success);
+int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks);
+void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int aborted);
+void bitmap_close_sync(struct bitmap *bitmap);
+
+int bitmap_unplug(struct bitmap *bitmap);
+int bitmap_daemon_work(struct bitmap *bitmap);
+#endif
+
+#endif
diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h
index a6a67d102bf..ffa316ce4dc 100644
--- a/include/linux/raid/md.h
+++ b/include/linux/raid/md.h
@@ -60,7 +60,14 @@
*/
#define MD_MAJOR_VERSION 0
#define MD_MINOR_VERSION 90
-#define MD_PATCHLEVEL_VERSION 1
+/*
+ * MD_PATCHLEVEL_VERSION indicates kernel functionality.
+ * >=1 means different superblock formats are selectable using SET_ARRAY_INFO
+ * and major_version/minor_version accordingly
+ * >=2 means that Internal bitmaps are supported by setting MD_SB_BITMAP_PRESENT
+ * in the super status byte
+ */
+#define MD_PATCHLEVEL_VERSION 2
extern int register_md_personality (int p_num, mdk_personality_t *p);
extern int unregister_md_personality (int p_num);
@@ -69,7 +76,7 @@ extern mdk_thread_t * md_register_thread (void (*run) (mddev_t *mddev),
extern void md_unregister_thread (mdk_thread_t *thread);
extern void md_wakeup_thread(mdk_thread_t *thread);
extern void md_check_recovery(mddev_t *mddev);
-extern void md_write_start(mddev_t *mddev);
+extern void md_write_start(mddev_t *mddev, struct bio *bi);
extern void md_write_end(mddev_t *mddev);
extern void md_handle_safemode(mddev_t *mddev);
extern void md_done_sync(mddev_t *mddev, int blocks, int ok);
@@ -78,6 +85,12 @@ extern void md_unplug_mddev(mddev_t *mddev);
extern void md_print_devices (void);
+extern void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
+ sector_t sector, int size, struct page *page);
+extern int sync_page_io(struct block_device *bdev, sector_t sector, int size,
+ struct page *page, int rw);
+
+
#define MD_BUG(x...) { printk("md: bug in file %s, line %d\n", __FILE__, __LINE__); md_print_devices(); }
#endif
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h
index c9a0d4013be..8c14ba565a4 100644
--- a/include/linux/raid/md_k.h
+++ b/include/linux/raid/md_k.h
@@ -15,6 +15,9 @@
#ifndef _MD_K_H
#define _MD_K_H
+/* and dm-bio-list.h is not under include/linux because.... ??? */
+#include "../../../drivers/md/dm-bio-list.h"
+
#define MD_RESERVED 0UL
#define LINEAR 1UL
#define RAID0 2UL
@@ -180,6 +183,10 @@ struct mdk_rdev_s
int desc_nr; /* descriptor index in the superblock */
int raid_disk; /* role of device in array */
+ int saved_raid_disk; /* role that device used to have in the
+ * array and could again if we did a partial
+ * resync from the bitmap
+ */
atomic_t nr_pending; /* number of pending requests.
* only maintained for arrays that
@@ -252,6 +259,11 @@ struct mddev_s
atomic_t recovery_active; /* blocks scheduled, but not written */
wait_queue_head_t recovery_wait;
sector_t recovery_cp;
+
+ spinlock_t write_lock;
+ wait_queue_head_t sb_wait; /* for waiting on superblock updates */
+ atomic_t pending_writes; /* number of active superblock writes */
+
unsigned int safemode; /* if set, update "clean" superblock
* when no writes pending.
*/
@@ -260,6 +272,13 @@ struct mddev_s
atomic_t writes_pending;
request_queue_t *queue; /* for plugging ... */
+ struct bitmap *bitmap; /* the bitmap for the device */
+ struct file *bitmap_file; /* the bitmap file */
+ long bitmap_offset; /* offset from superblock of
+ * start of bitmap. May be
+ * negative, but not '0'
+ */
+
struct list_head all_mddevs;
};
@@ -291,7 +310,7 @@ struct mdk_personality_s
int (*hot_add_disk) (mddev_t *mddev, mdk_rdev_t *rdev);
int (*hot_remove_disk) (mddev_t *mddev, int number);
int (*spare_active) (mddev_t *mddev);
- int (*sync_request)(mddev_t *mddev, sector_t sector_nr, int go_faster);
+ sector_t (*sync_request)(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster);
int (*resize) (mddev_t *mddev, sector_t sectors);
int (*reshape) (mddev_t *mddev, int raid_disks);
int (*reconfig) (mddev_t *mddev, int layout, int chunk_size);
@@ -334,6 +353,7 @@ typedef struct mdk_thread_s {
unsigned long flags;
struct completion *event;
struct task_struct *tsk;
+ unsigned long timeout;
const char *name;
} mdk_thread_t;
diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h
index 8ba95d67329..dc65cd43549 100644
--- a/include/linux/raid/md_p.h
+++ b/include/linux/raid/md_p.h
@@ -96,6 +96,7 @@ typedef struct mdp_device_descriptor_s {
#define MD_SB_CLEAN 0
#define MD_SB_ERRORS 1
+#define MD_SB_BITMAP_PRESENT 8 /* bitmap may be present nearby */
typedef struct mdp_superblock_s {
/*
* Constant generic information
@@ -184,7 +185,7 @@ struct mdp_superblock_1 {
/* constant array information - 128 bytes */
__u32 magic; /* MD_SB_MAGIC: 0xa92b4efc - little endian */
__u32 major_version; /* 1 */
- __u32 feature_map; /* 0 for now */
+ __u32 feature_map; /* bit 0 set if 'bitmap_offset' is meaningful */
__u32 pad0; /* always set to 0 when writing */
__u8 set_uuid[16]; /* user-space generated. */
@@ -197,7 +198,11 @@ struct mdp_superblock_1 {
__u32 chunksize; /* in 512byte sectors */
__u32 raid_disks;
- __u8 pad1[128-96]; /* set to 0 when written */
+ __u32 bitmap_offset; /* sectors after start of superblock that bitmap starts
+ * NOTE: signed, so bitmap can be before superblock
+ * only meaningful of feature_map[0] is set.
+ */
+ __u8 pad1[128-100]; /* set to 0 when written */
/* constant this-device information - 64 bytes */
__u64 data_offset; /* sector start of data, often 0 */
diff --git a/include/linux/raid/md_u.h b/include/linux/raid/md_u.h
index a2df5c2a42a..81da20ccec4 100644
--- a/include/linux/raid/md_u.h
+++ b/include/linux/raid/md_u.h
@@ -23,6 +23,7 @@
#define GET_DISK_INFO _IOR (MD_MAJOR, 0x12, mdu_disk_info_t)
#define PRINT_RAID_DEBUG _IO (MD_MAJOR, 0x13)
#define RAID_AUTORUN _IO (MD_MAJOR, 0x14)
+#define GET_BITMAP_FILE _IOR (MD_MAJOR, 0x15, mdu_bitmap_file_t)
/* configuration */
#define CLEAR_ARRAY _IO (MD_MAJOR, 0x20)
@@ -36,6 +37,7 @@
#define HOT_ADD_DISK _IO (MD_MAJOR, 0x28)
#define SET_DISK_FAULTY _IO (MD_MAJOR, 0x29)
#define HOT_GENERATE_ERROR _IO (MD_MAJOR, 0x2a)
+#define SET_BITMAP_FILE _IOW (MD_MAJOR, 0x2b, int)
/* usage */
#define RUN_ARRAY _IOW (MD_MAJOR, 0x30, mdu_param_t)
@@ -106,6 +108,11 @@ typedef struct mdu_start_info_s {
} mdu_start_info_t;
+typedef struct mdu_bitmap_file_s
+{
+ char pathname[4096];
+} mdu_bitmap_file_t;
+
typedef struct mdu_param_s
{
int personality; /* 1,2,3,4 */
diff --git a/include/linux/raid/raid1.h b/include/linux/raid/raid1.h
index abbfdd9afe1..9d93cf12e89 100644
--- a/include/linux/raid/raid1.h
+++ b/include/linux/raid/raid1.h
@@ -36,12 +36,21 @@ struct r1_private_data_s {
spinlock_t device_lock;
struct list_head retry_list;
+ /* queue pending writes and submit them on unplug */
+ struct bio_list pending_bio_list;
+ /* queue of writes that have been unplugged */
+ struct bio_list flushing_bio_list;
+
/* for use when syncing mirrors: */
spinlock_t resync_lock;
- int nr_pending;
- int barrier;
+ int nr_pending;
+ int barrier;
sector_t next_resync;
+ int fullsync; /* set to 1 if a full sync is needed,
+ * (fresh device added).
+ * Cleared when a sync completes.
+ */
wait_queue_head_t wait_idle;
wait_queue_head_t wait_resume;
@@ -85,14 +94,17 @@ struct r1bio_s {
int read_disk;
struct list_head retry_list;
+ struct bitmap_update *bitmap_update;
/*
* if the IO is in WRITE direction, then multiple bios are used.
* We choose the number when they are allocated.
*/
struct bio *bios[0];
+ /* DO NOT PUT ANY NEW FIELDS HERE - bios array is contiguously alloced*/
};
/* bits for r1bio.state */
#define R1BIO_Uptodate 0
#define R1BIO_IsSync 1
+#define R1BIO_Degraded 2
#endif
diff --git a/include/linux/reboot.h b/include/linux/reboot.h
index d60fafc8bdc..2d4dd23168d 100644
--- a/include/linux/reboot.h
+++ b/include/linux/reboot.h
@@ -51,6 +51,10 @@ extern void machine_restart(char *cmd);
extern void machine_halt(void);
extern void machine_power_off(void);
+extern void machine_shutdown(void);
+struct pt_regs;
+extern void machine_crash_shutdown(struct pt_regs *);
+
#endif
#endif /* _LINUX_REBOOT_H */
diff --git a/include/linux/reiserfs_acl.h b/include/linux/reiserfs_acl.h
index 2aef9c3f5ce..0760507a545 100644
--- a/include/linux/reiserfs_acl.h
+++ b/include/linux/reiserfs_acl.h
@@ -1,6 +1,5 @@
#include <linux/init.h>
#include <linux/posix_acl.h>
-#include <linux/xattr_acl.h>
#define REISERFS_ACL_VERSION 0x0001
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index 32148625fc2..4c7c5689ad9 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -1644,11 +1644,18 @@ struct reiserfs_journal_header {
#define JOURNAL_MAX_TRANS_AGE 30
#define JOURNAL_PER_BALANCE_CNT (3 * (MAX_HEIGHT-2) + 9)
#ifdef CONFIG_QUOTA
-#define REISERFS_QUOTA_TRANS_BLOCKS 2 /* We need to update data and inode (atime) */
-#define REISERFS_QUOTA_INIT_BLOCKS (DQUOT_MAX_WRITES*(JOURNAL_PER_BALANCE_CNT+2)+1) /* 1 balancing, 1 bitmap, 1 data per write + stat data update */
+/* We need to update data and inode (atime) */
+#define REISERFS_QUOTA_TRANS_BLOCKS(s) (REISERFS_SB(s)->s_mount_opt & (1<<REISERFS_QUOTA) ? 2 : 0)
+/* 1 balancing, 1 bitmap, 1 data per write + stat data update */
+#define REISERFS_QUOTA_INIT_BLOCKS(s) (REISERFS_SB(s)->s_mount_opt & (1<<REISERFS_QUOTA) ? \
+(DQUOT_INIT_ALLOC*(JOURNAL_PER_BALANCE_CNT+2)+DQUOT_INIT_REWRITE+1) : 0)
+/* same as with INIT */
+#define REISERFS_QUOTA_DEL_BLOCKS(s) (REISERFS_SB(s)->s_mount_opt & (1<<REISERFS_QUOTA) ? \
+(DQUOT_DEL_ALLOC*(JOURNAL_PER_BALANCE_CNT+2)+DQUOT_DEL_REWRITE+1) : 0)
#else
-#define REISERFS_QUOTA_TRANS_BLOCKS 0
-#define REISERFS_QUOTA_INIT_BLOCKS 0
+#define REISERFS_QUOTA_TRANS_BLOCKS(s) 0
+#define REISERFS_QUOTA_INIT_BLOCKS(s) 0
+#define REISERFS_QUOTA_DEL_BLOCKS(s) 0
#endif
/* both of these can be as low as 1, or as high as you want. The min is the
diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h
index 37a3a7afbec..31c709d0fe1 100644
--- a/include/linux/reiserfs_fs_sb.h
+++ b/include/linux/reiserfs_fs_sb.h
@@ -467,6 +467,8 @@ enum reiserfs_mount_options {
REISERFS_ERROR_RO,
REISERFS_ERROR_CONTINUE,
+ REISERFS_QUOTA, /* Some quota option specified */
+
REISERFS_TEST1,
REISERFS_TEST2,
REISERFS_TEST3,
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index 11b484e37ac..e80fb7ee6ef 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -93,6 +93,12 @@ int page_referenced(struct page *, int is_locked, int ignore_token);
int try_to_unmap(struct page *);
/*
+ * Called from mm/filemap_xip.c to unmap empty zero page
+ */
+pte_t *page_check_address(struct page *, struct mm_struct *, unsigned long);
+
+
+/*
* Used by swapoff to help locate where page is expected in vma.
*/
unsigned long page_address_in_vma(struct page *, struct vm_area_struct *);
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 91ac97c2077..d021888b58f 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -89,6 +89,13 @@ enum {
RTM_GETANYCAST = 62,
#define RTM_GETANYCAST RTM_GETANYCAST
+ RTM_NEWNEIGHTBL = 64,
+#define RTM_NEWNEIGHTBL RTM_NEWNEIGHTBL
+ RTM_GETNEIGHTBL = 66,
+#define RTM_GETNEIGHTBL RTM_GETNEIGHTBL
+ RTM_SETNEIGHTBL,
+#define RTM_SETNEIGHTBL RTM_SETNEIGHTBL
+
__RTM_MAX,
#define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1)
};
@@ -493,6 +500,106 @@ struct nda_cacheinfo
__u32 ndm_refcnt;
};
+
+/*****************************************************************
+ * Neighbour tables specific messages.
+ *
+ * To retrieve the neighbour tables send RTM_GETNEIGHTBL with the
+ * NLM_F_DUMP flag set. Every neighbour table configuration is
+ * spread over multiple messages to avoid running into message
+ * size limits on systems with many interfaces. The first message
+ * in the sequence transports all not device specific data such as
+ * statistics, configuration, and the default parameter set.
+ * This message is followed by 0..n messages carrying device
+ * specific parameter sets.
+ * Although the ordering should be sufficient, NDTA_NAME can be
+ * used to identify sequences. The initial message can be identified
+ * by checking for NDTA_CONFIG. The device specific messages do
+ * not contain this TLV but have NDTPA_IFINDEX set to the
+ * corresponding interface index.
+ *
+ * To change neighbour table attributes, send RTM_SETNEIGHTBL
+ * with NDTA_NAME set. Changeable attribute include NDTA_THRESH[1-3],
+ * NDTA_GC_INTERVAL, and all TLVs in NDTA_PARMS unless marked
+ * otherwise. Device specific parameter sets can be changed by
+ * setting NDTPA_IFINDEX to the interface index of the corresponding
+ * device.
+ ****/
+
+struct ndt_stats
+{
+ __u64 ndts_allocs;
+ __u64 ndts_destroys;
+ __u64 ndts_hash_grows;
+ __u64 ndts_res_failed;
+ __u64 ndts_lookups;
+ __u64 ndts_hits;
+ __u64 ndts_rcv_probes_mcast;
+ __u64 ndts_rcv_probes_ucast;
+ __u64 ndts_periodic_gc_runs;
+ __u64 ndts_forced_gc_runs;
+};
+
+enum {
+ NDTPA_UNSPEC,
+ NDTPA_IFINDEX, /* u32, unchangeable */
+ NDTPA_REFCNT, /* u32, read-only */
+ NDTPA_REACHABLE_TIME, /* u64, read-only, msecs */
+ NDTPA_BASE_REACHABLE_TIME, /* u64, msecs */
+ NDTPA_RETRANS_TIME, /* u64, msecs */
+ NDTPA_GC_STALETIME, /* u64, msecs */
+ NDTPA_DELAY_PROBE_TIME, /* u64, msecs */
+ NDTPA_QUEUE_LEN, /* u32 */
+ NDTPA_APP_PROBES, /* u32 */
+ NDTPA_UCAST_PROBES, /* u32 */
+ NDTPA_MCAST_PROBES, /* u32 */
+ NDTPA_ANYCAST_DELAY, /* u64, msecs */
+ NDTPA_PROXY_DELAY, /* u64, msecs */
+ NDTPA_PROXY_QLEN, /* u32 */
+ NDTPA_LOCKTIME, /* u64, msecs */
+ __NDTPA_MAX
+};
+#define NDTPA_MAX (__NDTPA_MAX - 1)
+
+struct ndtmsg
+{
+ __u8 ndtm_family;
+ __u8 ndtm_pad1;
+ __u16 ndtm_pad2;
+};
+
+struct ndt_config
+{
+ __u16 ndtc_key_len;
+ __u16 ndtc_entry_size;
+ __u32 ndtc_entries;
+ __u32 ndtc_last_flush; /* delta to now in msecs */
+ __u32 ndtc_last_rand; /* delta to now in msecs */
+ __u32 ndtc_hash_rnd;
+ __u32 ndtc_hash_mask;
+ __u32 ndtc_hash_chain_gc;
+ __u32 ndtc_proxy_qlen;
+};
+
+enum {
+ NDTA_UNSPEC,
+ NDTA_NAME, /* char *, unchangeable */
+ NDTA_THRESH1, /* u32 */
+ NDTA_THRESH2, /* u32 */
+ NDTA_THRESH3, /* u32 */
+ NDTA_CONFIG, /* struct ndt_config, read-only */
+ NDTA_PARMS, /* nested TLV NDTPA_* */
+ NDTA_STATS, /* struct ndt_stats, read-only */
+ NDTA_GC_INTERVAL, /* u64, msecs */
+ __NDTA_MAX
+};
+#define NDTA_MAX (__NDTA_MAX - 1)
+
+#define NDTA_RTA(r) ((struct rtattr*)(((char*)(r)) + \
+ NLMSG_ALIGN(sizeof(struct ndtmsg))))
+#define NDTA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndtmsg))
+
+
/****
* General form of address family dependent message.
****/
@@ -785,10 +892,82 @@ extern void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const voi
goto rtattr_failure; \
__rta_fill(skb, attrtype, attrlen, data); })
-#define RTA_PUT_NOHDR(skb, attrlen, data) \
+#define RTA_APPEND(skb, attrlen, data) \
({ if (unlikely(skb_tailroom(skb) < (int)(attrlen))) \
goto rtattr_failure; \
- memcpy(skb_put(skb, RTA_ALIGN(attrlen)), data, attrlen); })
+ memcpy(skb_put(skb, attrlen), data, attrlen); })
+
+#define RTA_PUT_NOHDR(skb, attrlen, data) \
+ RTA_APPEND(skb, RTA_ALIGN(attrlen), data)
+
+#define RTA_PUT_U8(skb, attrtype, value) \
+({ u8 _tmp = (value); \
+ RTA_PUT(skb, attrtype, sizeof(u8), &_tmp); })
+
+#define RTA_PUT_U16(skb, attrtype, value) \
+({ u16 _tmp = (value); \
+ RTA_PUT(skb, attrtype, sizeof(u16), &_tmp); })
+
+#define RTA_PUT_U32(skb, attrtype, value) \
+({ u32 _tmp = (value); \
+ RTA_PUT(skb, attrtype, sizeof(u32), &_tmp); })
+
+#define RTA_PUT_U64(skb, attrtype, value) \
+({ u64 _tmp = (value); \
+ RTA_PUT(skb, attrtype, sizeof(u64), &_tmp); })
+
+#define RTA_PUT_SECS(skb, attrtype, value) \
+ RTA_PUT_U64(skb, attrtype, (value) / HZ)
+
+#define RTA_PUT_MSECS(skb, attrtype, value) \
+ RTA_PUT_U64(skb, attrtype, jiffies_to_msecs(value))
+
+#define RTA_PUT_STRING(skb, attrtype, value) \
+ RTA_PUT(skb, attrtype, strlen(value) + 1, value)
+
+#define RTA_PUT_FLAG(skb, attrtype) \
+ RTA_PUT(skb, attrtype, 0, NULL);
+
+#define RTA_NEST(skb, type) \
+({ struct rtattr *__start = (struct rtattr *) (skb)->tail; \
+ RTA_PUT(skb, type, 0, NULL); \
+ __start; })
+
+#define RTA_NEST_END(skb, start) \
+({ (start)->rta_len = ((skb)->tail - (unsigned char *) (start)); \
+ (skb)->len; })
+
+#define RTA_NEST_CANCEL(skb, start) \
+({ if (start) \
+ skb_trim(skb, (unsigned char *) (start) - (skb)->data); \
+ -1; })
+
+#define RTA_GET_U8(rta) \
+({ if (!rta || RTA_PAYLOAD(rta) < sizeof(u8)) \
+ goto rtattr_failure; \
+ *(u8 *) RTA_DATA(rta); })
+
+#define RTA_GET_U16(rta) \
+({ if (!rta || RTA_PAYLOAD(rta) < sizeof(u16)) \
+ goto rtattr_failure; \
+ *(u16 *) RTA_DATA(rta); })
+
+#define RTA_GET_U32(rta) \
+({ if (!rta || RTA_PAYLOAD(rta) < sizeof(u32)) \
+ goto rtattr_failure; \
+ *(u32 *) RTA_DATA(rta); })
+
+#define RTA_GET_U64(rta) \
+({ u64 _tmp; \
+ if (!rta || RTA_PAYLOAD(rta) < sizeof(u64)) \
+ goto rtattr_failure; \
+ memcpy(&_tmp, RTA_DATA(rta), sizeof(_tmp)); \
+ _tmp; })
+
+#define RTA_GET_FLAG(rta) (!!(rta))
+
+#define RTA_GET_SECS(rta) ((unsigned long) RTA_GET_U64(rta) * HZ)
+#define RTA_GET_MSECS(rta) (msecs_to_jiffies((unsigned long) RTA_GET_U64(rta)))
static inline struct rtattr *
__rta_reserve(struct sk_buff *skb, int attrtype, int attrlen)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 4dbb109022f..9530b190316 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -201,8 +201,8 @@ extern unsigned long
arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
unsigned long len, unsigned long pgoff,
unsigned long flags);
-extern void arch_unmap_area(struct vm_area_struct *area);
-extern void arch_unmap_area_topdown(struct vm_area_struct *area);
+extern void arch_unmap_area(struct mm_struct *, unsigned long);
+extern void arch_unmap_area_topdown(struct mm_struct *, unsigned long);
#define set_mm_counter(mm, member, value) (mm)->_##member = (value)
#define get_mm_counter(mm, member) ((mm)->_##member)
@@ -218,9 +218,10 @@ struct mm_struct {
unsigned long (*get_unmapped_area) (struct file *filp,
unsigned long addr, unsigned long len,
unsigned long pgoff, unsigned long flags);
- void (*unmap_area) (struct vm_area_struct *area);
- unsigned long mmap_base; /* base of mmap area */
- unsigned long free_area_cache; /* first hole */
+ void (*unmap_area) (struct mm_struct *mm, unsigned long addr);
+ unsigned long mmap_base; /* base of mmap area */
+ unsigned long cached_hole_size; /* if non-zero, the largest hole below free_area_cache */
+ unsigned long free_area_cache; /* first hole of size cached_hole_size or larger */
pgd_t * pgd;
atomic_t mm_users; /* How many users with user space? */
atomic_t mm_count; /* How many references to "struct mm_struct" (users count as 1) */
@@ -245,7 +246,7 @@ struct mm_struct {
unsigned long saved_auxv[42]; /* for /proc/PID/auxv */
- unsigned dumpable:1;
+ unsigned dumpable:2;
cpumask_t cpu_vm_mask;
/* Architecture-specific MM context */
@@ -367,6 +368,11 @@ struct signal_struct {
#endif
};
+/* Context switch must be unlocked if interrupts are to be enabled */
+#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
+# define __ARCH_WANT_UNLOCKED_CTXSW
+#endif
+
/*
* Bits in flags field of signal_struct.
*/
@@ -459,10 +465,11 @@ enum idle_type
#define SD_LOAD_BALANCE 1 /* Do load balancing on this domain. */
#define SD_BALANCE_NEWIDLE 2 /* Balance when about to become idle */
#define SD_BALANCE_EXEC 4 /* Balance on exec */
-#define SD_WAKE_IDLE 8 /* Wake to idle CPU on task wakeup */
-#define SD_WAKE_AFFINE 16 /* Wake task to waking CPU */
-#define SD_WAKE_BALANCE 32 /* Perform balancing at task wakeup */
-#define SD_SHARE_CPUPOWER 64 /* Domain members share cpu power */
+#define SD_BALANCE_FORK 8 /* Balance on fork, clone */
+#define SD_WAKE_IDLE 16 /* Wake to idle CPU on task wakeup */
+#define SD_WAKE_AFFINE 32 /* Wake task to waking CPU */
+#define SD_WAKE_BALANCE 64 /* Perform balancing at task wakeup */
+#define SD_SHARE_CPUPOWER 128 /* Domain members share cpu power */
struct sched_group {
struct sched_group *next; /* Must be a circular list */
@@ -487,6 +494,11 @@ struct sched_domain {
unsigned long long cache_hot_time; /* Task considered cache hot (ns) */
unsigned int cache_nice_tries; /* Leave cache hot tasks for # tries */
unsigned int per_cpu_gain; /* CPU % gained by adding domain cpus */
+ unsigned int busy_idx;
+ unsigned int idle_idx;
+ unsigned int newidle_idx;
+ unsigned int wake_idx;
+ unsigned int forkexec_idx;
int flags; /* See SD_* */
/* Runtime fields. */
@@ -510,10 +522,16 @@ struct sched_domain {
unsigned long alb_failed;
unsigned long alb_pushed;
- /* sched_balance_exec() stats */
- unsigned long sbe_attempts;
+ /* SD_BALANCE_EXEC stats */
+ unsigned long sbe_cnt;
+ unsigned long sbe_balanced;
unsigned long sbe_pushed;
+ /* SD_BALANCE_FORK stats */
+ unsigned long sbf_cnt;
+ unsigned long sbf_balanced;
+ unsigned long sbf_pushed;
+
/* try_to_wake_up() stats */
unsigned long ttwu_wake_remote;
unsigned long ttwu_move_affine;
@@ -521,6 +539,8 @@ struct sched_domain {
#endif
};
+extern void partition_sched_domains(cpumask_t *partition1,
+ cpumask_t *partition2);
#ifdef ARCH_HAS_SCHED_DOMAIN
/* Useful helpers that arch setup code may use. Defined in kernel/sched.c */
extern cpumask_t cpu_isolated_map;
@@ -560,9 +580,10 @@ struct group_info {
groups_free(group_info); \
} while (0)
-struct group_info *groups_alloc(int gidsetsize);
-void groups_free(struct group_info *group_info);
-int set_current_groups(struct group_info *group_info);
+extern struct group_info *groups_alloc(int gidsetsize);
+extern void groups_free(struct group_info *group_info);
+extern int set_current_groups(struct group_info *group_info);
+extern int groups_search(struct group_info *group_info, gid_t grp);
/* access the groups "array" with this macro */
#define GROUP_AT(gi, i) \
((gi)->blocks[(i)/NGROUPS_PER_BLOCK][(i)%NGROUPS_PER_BLOCK])
@@ -580,6 +601,9 @@ struct task_struct {
int lock_depth; /* BKL lock depth */
+#if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW)
+ int oncpu;
+#endif
int prio, static_prio;
struct list_head run_list;
prio_array_t *array;
@@ -659,6 +683,7 @@ struct task_struct {
struct user_struct *user;
#ifdef CONFIG_KEYS
struct key *thread_keyring; /* keyring private to this thread */
+ unsigned char jit_keyring; /* default keyring to attach requested keys to */
#endif
int oomkilladj; /* OOM kill score adjustment (bit shift). */
char comm[TASK_COMM_LEN]; /* executable name excluding path
@@ -701,8 +726,6 @@ struct task_struct {
spinlock_t alloc_lock;
/* Protection of proc_dentry: nesting proc_lock, dcache_lock, write_lock_irq(&tasklist_lock); */
spinlock_t proc_lock;
-/* context-switch lock */
- spinlock_t switch_lock;
/* journalling filesystem info */
void *journal_info;
@@ -909,7 +932,7 @@ extern void FASTCALL(wake_up_new_task(struct task_struct * tsk,
#else
static inline void kick_process(struct task_struct *tsk) { }
#endif
-extern void FASTCALL(sched_fork(task_t * p));
+extern void FASTCALL(sched_fork(task_t * p, int clone_flags));
extern void FASTCALL(sched_exit(task_t * p));
extern int in_group_p(gid_t);
@@ -1242,33 +1265,78 @@ extern void normalize_rt_tasks(void);
#endif
-/* try_to_freeze
- *
- * Checks whether we need to enter the refrigerator
- * and returns 1 if we did so.
- */
#ifdef CONFIG_PM
-extern void refrigerator(unsigned long);
+/*
+ * Check if a process has been frozen
+ */
+static inline int frozen(struct task_struct *p)
+{
+ return p->flags & PF_FROZEN;
+}
+
+/*
+ * Check if there is a request to freeze a process
+ */
+static inline int freezing(struct task_struct *p)
+{
+ return p->flags & PF_FREEZE;
+}
+
+/*
+ * Request that a process be frozen
+ * FIXME: SMP problem. We may not modify other process' flags!
+ */
+static inline void freeze(struct task_struct *p)
+{
+ p->flags |= PF_FREEZE;
+}
+
+/*
+ * Wake up a frozen process
+ */
+static inline int thaw_process(struct task_struct *p)
+{
+ if (frozen(p)) {
+ p->flags &= ~PF_FROZEN;
+ wake_up_process(p);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * freezing is complete, mark process as frozen
+ */
+static inline void frozen_process(struct task_struct *p)
+{
+ p->flags = (p->flags & ~PF_FREEZE) | PF_FROZEN;
+}
+
+extern void refrigerator(void);
extern int freeze_processes(void);
extern void thaw_processes(void);
-static inline int try_to_freeze(unsigned long refrigerator_flags)
+static inline int try_to_freeze(void)
{
- if (unlikely(current->flags & PF_FREEZE)) {
- refrigerator(refrigerator_flags);
+ if (freezing(current)) {
+ refrigerator();
return 1;
} else
return 0;
}
#else
-static inline void refrigerator(unsigned long flag) {}
+static inline int frozen(struct task_struct *p) { return 0; }
+static inline int freezing(struct task_struct *p) { return 0; }
+static inline void freeze(struct task_struct *p) { BUG(); }
+static inline int thaw_process(struct task_struct *p) { return 1; }
+static inline void frozen_process(struct task_struct *p) { BUG(); }
+
+static inline void refrigerator(void) {}
static inline int freeze_processes(void) { BUG(); return 0; }
static inline void thaw_processes(void) {}
-static inline int try_to_freeze(unsigned long refrigerator_flags)
-{
- return 0;
-}
+static inline int try_to_freeze(void) { return 0; }
+
#endif /* CONFIG_PM */
#endif /* __KERNEL__ */
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index c3fb5984f25..d6025af7efa 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -479,6 +479,25 @@ uart_handle_cts_change(struct uart_port *port, unsigned int status)
}
}
+#include <linux/tty_flip.h>
+
+static inline void
+uart_insert_char(struct uart_port *port, unsigned int status,
+ unsigned int overrun, unsigned int ch, unsigned int flag)
+{
+ struct tty_struct *tty = port->info->tty;
+
+ if ((status & port->ignore_status_mask & ~overrun) == 0)
+ tty_insert_flip_char(tty, ch, flag);
+
+ /*
+ * Overrun is special. Since it's reported immediately,
+ * it doesn't affect the current character.
+ */
+ if (status & ~port->ignore_status_mask & overrun)
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+}
+
/*
* UART_ENABLE_MS - determine if port should enable modem status irqs
*/
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 0a98f5ec5ca..7be18b5e2fb 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -231,10 +231,8 @@ extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *);
extern long do_sigpending(void __user *, unsigned long);
extern int sigprocmask(int, sigset_t *, sigset_t *);
-#ifndef HAVE_ARCH_GET_SIGNAL_TO_DELIVER
struct pt_regs;
extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie);
-#endif
#endif /* __KERNEL__ */
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index cc04f5cd228..416a2e4024b 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -27,6 +27,7 @@
#include <linux/highmem.h>
#include <linux/poll.h>
#include <linux/net.h>
+#include <linux/textsearch.h>
#include <net/checksum.h>
#define HAVE_ALLOC_SKB /* For the drivers to know */
@@ -193,7 +194,6 @@ struct skb_shared_info {
* @nfcache: Cache info
* @nfct: Associated connection, if any
* @nfctinfo: Relationship of this skb to the connection
- * @nf_debug: Netfilter debugging
* @nf_bridge: Saved data about a bridged frame - see br_netfilter.c
* @private: Data which is private to the HIPPI implementation
* @tc_index: Traffic control index
@@ -264,9 +264,6 @@ struct sk_buff {
__u32 nfcache;
__u32 nfctinfo;
struct nf_conntrack *nfct;
-#ifdef CONFIG_NETFILTER_DEBUG
- unsigned int nf_debug;
-#endif
#ifdef CONFIG_BRIDGE_NETFILTER
struct nf_bridge_info *nf_bridge;
#endif
@@ -325,6 +322,28 @@ extern void skb_over_panic(struct sk_buff *skb, int len,
extern void skb_under_panic(struct sk_buff *skb, int len,
void *here);
+struct skb_seq_state
+{
+ __u32 lower_offset;
+ __u32 upper_offset;
+ __u32 frag_idx;
+ __u32 stepped_offset;
+ struct sk_buff *root_skb;
+ struct sk_buff *cur_skb;
+ __u8 *frag_data;
+};
+
+extern void skb_prepare_seq_read(struct sk_buff *skb,
+ unsigned int from, unsigned int to,
+ struct skb_seq_state *st);
+extern unsigned int skb_seq_read(unsigned int consumed, const u8 **data,
+ struct skb_seq_state *st);
+extern void skb_abort_seq_read(struct skb_seq_state *st);
+
+extern unsigned int skb_find_text(struct sk_buff *skb, unsigned int from,
+ unsigned int to, struct ts_config *config,
+ struct ts_state *state);
+
/* Internal */
#define skb_shinfo(SKB) ((struct skb_shared_info *)((SKB)->end))
@@ -1219,15 +1238,6 @@ static inline void nf_reset(struct sk_buff *skb)
{
nf_conntrack_put(skb->nfct);
skb->nfct = NULL;
-#ifdef CONFIG_NETFILTER_DEBUG
- skb->nf_debug = 0;
-#endif
-}
-static inline void nf_reset_debug(struct sk_buff *skb)
-{
-#ifdef CONFIG_NETFILTER_DEBUG
- skb->nf_debug = 0;
-#endif
}
#ifdef CONFIG_BRIDGE_NETFILTER
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 7d66385ae75..76cf7e60216 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -64,6 +64,7 @@ extern int kmem_cache_shrink(kmem_cache_t *);
extern void *kmem_cache_alloc(kmem_cache_t *, unsigned int __nocast);
extern void kmem_cache_free(kmem_cache_t *, void *);
extern unsigned int kmem_cache_size(kmem_cache_t *);
+extern const char *kmem_cache_name(kmem_cache_t *);
extern kmem_cache_t *kmem_find_general_cachep(size_t size, int gfpflags);
/* Size description struct for general caches. */
diff --git a/include/linux/smp.h b/include/linux/smp.h
index dcf1db3b35d..9dfa3ee769a 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -92,10 +92,7 @@ void smp_prepare_boot_cpu(void);
/*
* These macros fold the SMP functionality into a single CPU system
*/
-
-#if !defined(__smp_processor_id) || !defined(CONFIG_PREEMPT)
-# define smp_processor_id() 0
-#endif
+#define raw_smp_processor_id() 0
#define hard_smp_processor_id() 0
#define smp_call_function(func,info,retry,wait) ({ 0; })
#define on_each_cpu(func,info,retry,wait) ({ func(info); 0; })
@@ -106,30 +103,25 @@ static inline void smp_send_reschedule(int cpu) { }
#endif /* !SMP */
/*
- * DEBUG_PREEMPT support: check whether smp_processor_id() is being
- * used in a preemption-safe way.
+ * smp_processor_id(): get the current CPU ID.
*
- * An architecture has to enable this debugging code explicitly.
- * It can do so by renaming the smp_processor_id() macro to
- * __smp_processor_id(). This should only be done after some minimal
- * testing, because usually there are a number of false positives
- * that an architecture will trigger.
+ * if DEBUG_PREEMPT is enabled the we check whether it is
+ * used in a preemption-safe way. (smp_processor_id() is safe
+ * if it's used in a preemption-off critical section, or in
+ * a thread that is bound to the current CPU.)
*
- * To fix a false positive (i.e. smp_processor_id() use that the
- * debugging code reports but which use for some reason is legal),
- * change the smp_processor_id() reference to _smp_processor_id(),
- * which is the nondebug variant. NOTE: don't use this to hack around
- * real bugs.
+ * NOTE: raw_smp_processor_id() is for internal use only
+ * (smp_processor_id() is the preferred variant), but in rare
+ * instances it might also be used to turn off false positives
+ * (i.e. smp_processor_id() use that the debugging code reports but
+ * which use for some reason is legal). Don't use this to hack around
+ * the warning message, as your code might not work under PREEMPT.
*/
-#ifdef __smp_processor_id
-# if defined(CONFIG_PREEMPT) && defined(CONFIG_DEBUG_PREEMPT)
- extern unsigned int smp_processor_id(void);
-# else
-# define smp_processor_id() __smp_processor_id()
-# endif
-# define _smp_processor_id() __smp_processor_id()
+#ifdef CONFIG_DEBUG_PREEMPT
+ extern unsigned int debug_smp_processor_id(void);
+# define smp_processor_id() debug_smp_processor_id()
#else
-# define _smp_processor_id() smp_processor_id()
+# define smp_processor_id() raw_smp_processor_id()
#endif
#define get_cpu() ({ preempt_disable(); smp_processor_id(); })
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index e895f3eaf53..d6ba068719b 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -248,7 +248,7 @@ typedef struct {
#define _spin_trylock_bh(lock) ({preempt_disable(); local_bh_disable(); \
_raw_spin_trylock(lock) ? \
- 1 : ({preempt_enable(); local_bh_enable(); 0;});})
+ 1 : ({preempt_enable_no_resched(); local_bh_enable(); 0;});})
#define _spin_lock(lock) \
do { \
@@ -383,7 +383,7 @@ do { \
#define _spin_unlock_bh(lock) \
do { \
_raw_spin_unlock(lock); \
- preempt_enable(); \
+ preempt_enable_no_resched(); \
local_bh_enable(); \
__release(lock); \
} while (0)
@@ -391,7 +391,7 @@ do { \
#define _write_unlock_bh(lock) \
do { \
_raw_write_unlock(lock); \
- preempt_enable(); \
+ preempt_enable_no_resched(); \
local_bh_enable(); \
__release(lock); \
} while (0)
@@ -423,8 +423,8 @@ do { \
#define _read_unlock_bh(lock) \
do { \
_raw_read_unlock(lock); \
+ preempt_enable_no_resched(); \
local_bh_enable(); \
- preempt_enable(); \
__release(lock); \
} while (0)
diff --git a/include/linux/string.h b/include/linux/string.h
index b9fc5946995..93994c61309 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -88,6 +88,8 @@ extern int memcmp(const void *,const void *,__kernel_size_t);
extern void * memchr(const void *,int,__kernel_size_t);
#endif
+extern char *kstrdup(const char *s, int gfp);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 2709caf4d12..ab151bbb66d 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -111,6 +111,11 @@ struct rpc_procinfo {
struct rpc_clnt *rpc_create_client(struct rpc_xprt *xprt, char *servname,
struct rpc_program *info,
u32 version, rpc_authflavor_t authflavor);
+struct rpc_clnt *rpc_new_client(struct rpc_xprt *xprt, char *servname,
+ struct rpc_program *info,
+ u32 version, rpc_authflavor_t authflavor);
+struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *,
+ struct rpc_program *, int);
struct rpc_clnt *rpc_clone_client(struct rpc_clnt *);
int rpc_shutdown_client(struct rpc_clnt *);
int rpc_destroy_client(struct rpc_clnt *);
@@ -129,6 +134,7 @@ void rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset);
void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset);
void rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int);
size_t rpc_max_payload(struct rpc_clnt *);
+int rpc_ping(struct rpc_clnt *clnt, int flags);
static __inline__
int rpc_call(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags)
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 99d17ed7ceb..4d77e90d0b3 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -31,7 +31,6 @@ struct rpc_wait_queue;
struct rpc_wait {
struct list_head list; /* wait queue links */
struct list_head links; /* Links to related tasks */
- wait_queue_head_t waitq; /* sync: sleep on this q */
struct rpc_wait_queue * rpc_waitq; /* RPC wait queue we're on */
};
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 37003970cf2..5af8800e0ce 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -185,6 +185,17 @@ xdr_ressize_check(struct svc_rqst *rqstp, u32 *p)
return vec->iov_len <= PAGE_SIZE;
}
+static inline struct page *
+svc_take_res_page(struct svc_rqst *rqstp)
+{
+ if (rqstp->rq_arghi <= rqstp->rq_argused)
+ return NULL;
+ rqstp->rq_arghi--;
+ rqstp->rq_respages[rqstp->rq_resused] =
+ rqstp->rq_argpages[rqstp->rq_arghi];
+ return rqstp->rq_respages[rqstp->rq_resused++];
+}
+
static inline int svc_take_page(struct svc_rqst *rqstp)
{
if (rqstp->rq_arghi <= rqstp->rq_argused)
@@ -240,9 +251,10 @@ struct svc_deferred_req {
};
/*
- * RPC program
+ * List of RPC programs on the same transport endpoint
*/
struct svc_program {
+ struct svc_program * pg_next; /* other programs (same xprt) */
u32 pg_prog; /* program number */
unsigned int pg_lovers; /* lowest version */
unsigned int pg_hivers; /* lowest version */
diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
index 541dcf838ab..34ec3e8d99b 100644
--- a/include/linux/sunrpc/xdr.h
+++ b/include/linux/sunrpc/xdr.h
@@ -146,7 +146,8 @@ extern void xdr_shift_buf(struct xdr_buf *, size_t);
extern void xdr_buf_from_iov(struct kvec *, struct xdr_buf *);
extern int xdr_buf_subsegment(struct xdr_buf *, struct xdr_buf *, int, int);
extern int xdr_buf_read_netobj(struct xdr_buf *, struct xdr_netobj *, int);
-extern int read_bytes_from_xdr_buf(struct xdr_buf *buf, int base, void *obj, int len);
+extern int read_bytes_from_xdr_buf(struct xdr_buf *, int, void *, int);
+extern int write_bytes_to_xdr_buf(struct xdr_buf *, int, void *, int);
/*
* Helper structure for copying from an sk_buff.
@@ -160,7 +161,7 @@ typedef struct {
typedef size_t (*skb_read_actor_t)(skb_reader_t *desc, void *to, size_t len);
-extern void xdr_partial_copy_from_skb(struct xdr_buf *, unsigned int,
+extern ssize_t xdr_partial_copy_from_skb(struct xdr_buf *, unsigned int,
skb_reader_t *, skb_read_actor_t);
struct socket;
@@ -168,6 +169,22 @@ struct sockaddr;
extern int xdr_sendpages(struct socket *, struct sockaddr *, int,
struct xdr_buf *, unsigned int, int);
+extern int xdr_encode_word(struct xdr_buf *, int, u32);
+extern int xdr_decode_word(struct xdr_buf *, int, u32 *);
+
+struct xdr_array2_desc;
+typedef int (*xdr_xcode_elem_t)(struct xdr_array2_desc *desc, void *elem);
+struct xdr_array2_desc {
+ unsigned int elem_size;
+ unsigned int array_len;
+ xdr_xcode_elem_t xcode;
+};
+
+extern int xdr_decode_array2(struct xdr_buf *buf, unsigned int base,
+ struct xdr_array2_desc *desc);
+extern int xdr_encode_array2(struct xdr_buf *buf, unsigned int base,
+ struct xdr_array2_desc *desc);
+
/*
* Provide some simple tools for XDR buffer overflow-checking etc.
*/
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index 2bf0d5fabcd..f2e96fdfaae 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -58,7 +58,7 @@ static inline int software_suspend(void)
}
#endif
-#ifdef CONFIG_SMP
+#ifdef CONFIG_SUSPEND_SMP
extern void disable_nonboot_cpus(void);
extern void enable_nonboot_cpus(void);
#else
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 3bbc41be9bd..2343f999e6e 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -172,7 +172,8 @@ extern int rotate_reclaimable_page(struct page *page);
extern void swap_setup(void);
/* linux/mm/vmscan.c */
-extern int try_to_free_pages(struct zone **, unsigned int, unsigned int);
+extern int try_to_free_pages(struct zone **, unsigned int);
+extern int zone_reclaim(struct zone *, unsigned int, unsigned int);
extern int shrink_all_memory(int);
extern int vm_swappiness;
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index c39f6f72cbb..52830b6d94e 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -159,8 +159,9 @@ asmlinkage long sys_shutdown(int, int);
asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd,
void __user *arg);
asmlinkage long sys_restart_syscall(void);
-asmlinkage long sys_kexec_load(void *entry, unsigned long nr_segments,
- struct kexec_segment *segments, unsigned long flags);
+asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments,
+ struct kexec_segment __user *segments,
+ unsigned long flags);
asmlinkage long sys_exit(int error_code);
asmlinkage void sys_exit_group(int error_code);
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 772998147e3..ebfe1250f0a 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -136,6 +136,7 @@ enum
KERN_UNKNOWN_NMI_PANIC=66, /* int: unknown nmi panic flag */
KERN_BOOTLOADER_TYPE=67, /* int: boot loader type */
KERN_RANDOMIZE=68, /* int: randomize virtual address space */
+ KERN_SETUID_DUMPABLE=69, /* int: behaviour of dumps for setuid core */
};
@@ -242,6 +243,7 @@ enum
NET_CORE_MOD_CONG=16,
NET_CORE_DEV_WEIGHT=17,
NET_CORE_SOMAXCONN=18,
+ NET_CORE_BUDGET=19,
};
/* /proc/sys/net/ethernet */
@@ -332,20 +334,14 @@ enum
NET_TCP_FRTO=92,
NET_TCP_LOW_LATENCY=93,
NET_IPV4_IPFRAG_SECRET_INTERVAL=94,
- NET_TCP_WESTWOOD=95,
NET_IPV4_IGMP_MAX_MSF=96,
NET_TCP_NO_METRICS_SAVE=97,
- NET_TCP_VEGAS=98,
- NET_TCP_VEGAS_ALPHA=99,
- NET_TCP_VEGAS_BETA=100,
- NET_TCP_VEGAS_GAMMA=101,
- NET_TCP_BIC=102,
- NET_TCP_BIC_FAST_CONVERGENCE=103,
- NET_TCP_BIC_LOW_WINDOW=104,
NET_TCP_DEFAULT_WIN_SCALE=105,
NET_TCP_MODERATE_RCVBUF=106,
NET_TCP_TSO_WIN_DIVISOR=107,
NET_TCP_BIC_BETA=108,
+ NET_IPV4_ICMP_ERRORS_USE_INBOUND_IFADDR=109,
+ NET_TCP_CONG_CONTROL=110,
};
enum {
@@ -399,6 +395,7 @@ enum
NET_IPV4_CONF_FORCE_IGMP_VERSION=17,
NET_IPV4_CONF_ARP_ANNOUNCE=18,
NET_IPV4_CONF_ARP_IGNORE=19,
+ NET_IPV4_CONF_PROMOTE_SECONDARIES=20,
__NET_IPV4_CONF_MAX
};
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 38b58b30814..392da5a6dac 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -16,13 +16,13 @@ struct kobject;
struct module;
struct attribute {
- char * name;
+ const char * name;
struct module * owner;
mode_t mode;
};
struct attribute_group {
- char * name;
+ const char * name;
struct attribute ** attrs;
};
@@ -73,6 +73,7 @@ struct sysfs_dirent {
int s_type;
umode_t s_mode;
struct dentry * s_dentry;
+ struct iattr * s_iattr;
};
#define SYSFS_ROOT 0x0001
@@ -105,11 +106,11 @@ sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, mode_t mode);
extern void
sysfs_remove_file(struct kobject *, const struct attribute *);
-extern int
-sysfs_create_link(struct kobject * kobj, struct kobject * target, char * name);
+extern int
+sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name);
extern void
-sysfs_remove_link(struct kobject *, char * name);
+sysfs_remove_link(struct kobject *, const char * name);
int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr);
int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr);
@@ -153,12 +154,12 @@ static inline void sysfs_remove_file(struct kobject * k, const struct attribute
;
}
-static inline int sysfs_create_link(struct kobject * k, struct kobject * t, char * n)
+static inline int sysfs_create_link(struct kobject * k, struct kobject * t, const char * n)
{
return 0;
}
-static inline void sysfs_remove_link(struct kobject * k, char * name)
+static inline void sysfs_remove_link(struct kobject * k, const char * name)
{
;
}
diff --git a/include/linux/tc_ematch/tc_em_meta.h b/include/linux/tc_ematch/tc_em_meta.h
index aa6b48bb4dc..a6b2cc530af 100644
--- a/include/linux/tc_ematch/tc_em_meta.h
+++ b/include/linux/tc_ematch/tc_em_meta.h
@@ -56,6 +56,36 @@ enum
TCF_META_ID_TCCLASSID,
TCF_META_ID_RTCLASSID,
TCF_META_ID_RTIIF,
+ TCF_META_ID_SK_FAMILY,
+ TCF_META_ID_SK_STATE,
+ TCF_META_ID_SK_REUSE,
+ TCF_META_ID_SK_BOUND_IF,
+ TCF_META_ID_SK_REFCNT,
+ TCF_META_ID_SK_SHUTDOWN,
+ TCF_META_ID_SK_PROTO,
+ TCF_META_ID_SK_TYPE,
+ TCF_META_ID_SK_RCVBUF,
+ TCF_META_ID_SK_RMEM_ALLOC,
+ TCF_META_ID_SK_WMEM_ALLOC,
+ TCF_META_ID_SK_OMEM_ALLOC,
+ TCF_META_ID_SK_WMEM_QUEUED,
+ TCF_META_ID_SK_RCV_QLEN,
+ TCF_META_ID_SK_SND_QLEN,
+ TCF_META_ID_SK_ERR_QLEN,
+ TCF_META_ID_SK_FORWARD_ALLOCS,
+ TCF_META_ID_SK_SNDBUF,
+ TCF_META_ID_SK_ALLOCS,
+ TCF_META_ID_SK_ROUTE_CAPS,
+ TCF_META_ID_SK_HASHENT,
+ TCF_META_ID_SK_LINGERTIME,
+ TCF_META_ID_SK_ACK_BACKLOG,
+ TCF_META_ID_SK_MAX_ACK_BACKLOG,
+ TCF_META_ID_SK_PRIO,
+ TCF_META_ID_SK_RCVLOWAT,
+ TCF_META_ID_SK_RCVTIMEO,
+ TCF_META_ID_SK_SNDTIMEO,
+ TCF_META_ID_SK_SENDMSG_OFF,
+ TCF_META_ID_SK_WRITE_PENDING,
__TCF_META_ID_MAX
};
#define TCF_META_ID_MAX (__TCF_META_ID_MAX - 1)
diff --git a/include/linux/tc_ematch/tc_em_text.h b/include/linux/tc_ematch/tc_em_text.h
new file mode 100644
index 00000000000..7cd43e99c7f
--- /dev/null
+++ b/include/linux/tc_ematch/tc_em_text.h
@@ -0,0 +1,19 @@
+#ifndef __LINUX_TC_EM_TEXT_H
+#define __LINUX_TC_EM_TEXT_H
+
+#include <linux/pkt_cls.h>
+
+#define TC_EM_TEXT_ALGOSIZ 16
+
+struct tcf_em_text
+{
+ char algo[TC_EM_TEXT_ALGOSIZ];
+ __u16 from_offset;
+ __u16 to_offset;
+ __u16 pattern_len;
+ __u8 from_layer:4;
+ __u8 to_layer:4;
+ __u8 pad;
+};
+
+#endif
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 14a55e3e3a5..dfd93d03f5d 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -127,6 +127,7 @@ enum {
#define TCP_WINDOW_CLAMP 10 /* Bound advertised window */
#define TCP_INFO 11 /* Information about this connection. */
#define TCP_QUICKACK 12 /* Block/reenable quick acks */
+#define TCP_CONGESTION 13 /* Congestion control algorithm */
#define TCPI_OPT_TIMESTAMPS 1
#define TCPI_OPT_SACK 2
@@ -203,13 +204,6 @@ struct tcp_sack_block {
__u32 end_seq;
};
-enum tcp_congestion_algo {
- TCP_RENO=0,
- TCP_VEGAS,
- TCP_WESTWOOD,
- TCP_BIC,
-};
-
struct tcp_options_received {
/* PAWS/RTTM data */
long ts_recent_stamp;/* Time we stored ts_recent (for aging) */
@@ -230,6 +224,17 @@ struct tcp_options_received {
__u16 mss_clamp; /* Maximal mss, negotiated at connection setup */
};
+struct tcp_request_sock {
+ struct inet_request_sock req;
+ __u32 rcv_isn;
+ __u32 snt_isn;
+};
+
+static inline struct tcp_request_sock *tcp_rsk(const struct request_sock *req)
+{
+ return (struct tcp_request_sock *)req;
+}
+
struct tcp_sock {
/* inet_sock has to be the first member of tcp_sock */
struct inet_sock inet;
@@ -294,7 +299,7 @@ struct tcp_sock {
__u8 reordering; /* Packet reordering metric. */
__u8 frto_counter; /* Number of new acks after RTO */
- __u8 adv_cong; /* Using Vegas, Westwood, or BIC */
+ __u8 unused;
__u8 defer_accept; /* User waits for some data after accept() */
/* RTT measurement */
@@ -368,22 +373,7 @@ struct tcp_sock {
__u32 total_retrans; /* Total retransmits for entire connection */
- /* The syn_wait_lock is necessary only to avoid proc interface having
- * to grab the main lock sock while browsing the listening hash
- * (otherwise it's deadlock prone).
- * This lock is acquired in read mode only from listening_get_next()
- * and it's acquired in write mode _only_ from code that is actively
- * changing the syn_wait_queue. All readers that are holding
- * the master sock lock don't need to grab this lock in read mode
- * too as the syn_wait_queue writes are always protected from
- * the main sock lock.
- */
- rwlock_t syn_wait_lock;
- struct tcp_listen_opt *listen_opt;
-
- /* FIFO of established children */
- struct open_request *accept_queue;
- struct open_request *accept_queue_tail;
+ struct request_sock_queue accept_queue; /* FIFO of established children */
unsigned int keepalive_time; /* time before keep alive takes place */
unsigned int keepalive_intvl; /* time interval between keep alive probes */
@@ -405,37 +395,10 @@ struct tcp_sock {
__u32 time;
} rcvq_space;
-/* TCP Westwood structure */
- struct {
- __u32 bw_ns_est; /* first bandwidth estimation..not too smoothed 8) */
- __u32 bw_est; /* bandwidth estimate */
- __u32 rtt_win_sx; /* here starts a new evaluation... */
- __u32 bk;
- __u32 snd_una; /* used for evaluating the number of acked bytes */
- __u32 cumul_ack;
- __u32 accounted;
- __u32 rtt;
- __u32 rtt_min; /* minimum observed RTT */
- } westwood;
-
-/* Vegas variables */
- struct {
- __u32 beg_snd_nxt; /* right edge during last RTT */
- __u32 beg_snd_una; /* left edge during last RTT */
- __u32 beg_snd_cwnd; /* saves the size of the cwnd */
- __u8 doing_vegas_now;/* if true, do vegas for this RTT */
- __u16 cntRTT; /* # of RTTs measured within last RTT */
- __u32 minRTT; /* min of RTTs measured within last RTT (in usec) */
- __u32 baseRTT; /* the min of all Vegas RTT measurements seen (in usec) */
- } vegas;
-
- /* BI TCP Parameters */
- struct {
- __u32 cnt; /* increase cwnd by 1 after this number of ACKs */
- __u32 last_max_cwnd; /* last maximium snd_cwnd */
- __u32 last_cwnd; /* the last snd_cwnd */
- __u32 last_stamp; /* time when updated last_cwnd */
- } bictcp;
+ /* Pluggable TCP congestion control hook */
+ struct tcp_congestion_ops *ca_ops;
+ u32 ca_priv[16];
+#define TCP_CA_PRIV_SIZE (16*sizeof(u32))
};
static inline struct tcp_sock *tcp_sk(const struct sock *sk)
@@ -443,6 +406,11 @@ static inline struct tcp_sock *tcp_sk(const struct sock *sk)
return (struct tcp_sock *)sk;
}
+static inline void *tcp_ca(const struct tcp_sock *tp)
+{
+ return (void *) tp->ca_priv;
+}
+
#endif
#endif /* _LINUX_TCP_H */
diff --git a/include/linux/tcp_diag.h b/include/linux/tcp_diag.h
index ceee962e1d1..7a599674394 100644
--- a/include/linux/tcp_diag.h
+++ b/include/linux/tcp_diag.h
@@ -99,9 +99,10 @@ enum
TCPDIAG_MEMINFO,
TCPDIAG_INFO,
TCPDIAG_VEGASINFO,
+ TCPDIAG_CONG,
};
-#define TCPDIAG_MAX TCPDIAG_VEGASINFO
+#define TCPDIAG_MAX TCPDIAG_CONG
/* TCPDIAG_MEM */
@@ -123,5 +124,4 @@ struct tcpvegas_info {
__u32 tcpv_minrtt;
};
-
#endif /* _TCP_DIAG_H_ */
diff --git a/include/linux/textsearch.h b/include/linux/textsearch.h
new file mode 100644
index 00000000000..941f45ac117
--- /dev/null
+++ b/include/linux/textsearch.h
@@ -0,0 +1,180 @@
+#ifndef __LINUX_TEXTSEARCH_H
+#define __LINUX_TEXTSEARCH_H
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+
+struct ts_config;
+
+/**
+ * TS_AUTOLOAD - Automatically load textsearch modules when needed
+ */
+#define TS_AUTOLOAD 1
+
+/**
+ * struct ts_state - search state
+ * @offset: offset for next match
+ * @cb: control buffer, for persistant variables of get_next_block()
+ */
+struct ts_state
+{
+ unsigned int offset;
+ char cb[40];
+};
+
+/**
+ * struct ts_ops - search module operations
+ * @name: name of search algorithm
+ * @init: initialization function to prepare a search
+ * @find: find the next occurrence of the pattern
+ * @destroy: destroy algorithm specific parts of a search configuration
+ * @get_pattern: return head of pattern
+ * @get_pattern_len: return length of pattern
+ * @owner: module reference to algorithm
+ */
+struct ts_ops
+{
+ const char *name;
+ struct ts_config * (*init)(const void *, unsigned int, int);
+ unsigned int (*find)(struct ts_config *,
+ struct ts_state *);
+ void (*destroy)(struct ts_config *);
+ void * (*get_pattern)(struct ts_config *);
+ unsigned int (*get_pattern_len)(struct ts_config *);
+ struct module *owner;
+ struct list_head list;
+};
+
+/**
+ * struct ts_config - search configuration
+ * @ops: operations of chosen algorithm
+ * @get_next_block: callback to fetch the next block to search in
+ * @finish: callback to finalize a search
+ */
+struct ts_config
+{
+ struct ts_ops *ops;
+
+ /**
+ * get_next_block - fetch next block of data
+ * @consumed: number of bytes consumed by the caller
+ * @dst: destination buffer
+ * @conf: search configuration
+ * @state: search state
+ *
+ * Called repeatedly until 0 is returned. Must assign the
+ * head of the next block of data to &*dst and return the length
+ * of the block or 0 if at the end. consumed == 0 indicates
+ * a new search. May store/read persistant values in state->cb.
+ */
+ unsigned int (*get_next_block)(unsigned int consumed,
+ const u8 **dst,
+ struct ts_config *conf,
+ struct ts_state *state);
+
+ /**
+ * finish - finalize/clean a series of get_next_block() calls
+ * @conf: search configuration
+ * @state: search state
+ *
+ * Called after the last use of get_next_block(), may be used
+ * to cleanup any leftovers.
+ */
+ void (*finish)(struct ts_config *conf,
+ struct ts_state *state);
+};
+
+/**
+ * textsearch_next - continue searching for a pattern
+ * @conf: search configuration
+ * @state: search state
+ *
+ * Continues a search looking for more occurrences of the pattern.
+ * textsearch_find() must be called to find the first occurrence
+ * in order to reset the state.
+ *
+ * Returns the position of the next occurrence of the pattern or
+ * UINT_MAX if not match was found.
+ */
+static inline unsigned int textsearch_next(struct ts_config *conf,
+ struct ts_state *state)
+{
+ unsigned int ret = conf->ops->find(conf, state);
+
+ if (conf->finish)
+ conf->finish(conf, state);
+
+ return ret;
+}
+
+/**
+ * textsearch_find - start searching for a pattern
+ * @conf: search configuration
+ * @state: search state
+ *
+ * Returns the position of first occurrence of the pattern or
+ * UINT_MAX if no match was found.
+ */
+static inline unsigned int textsearch_find(struct ts_config *conf,
+ struct ts_state *state)
+{
+ state->offset = 0;
+ return textsearch_next(conf, state);
+}
+
+/**
+ * textsearch_get_pattern - return head of the pattern
+ * @conf: search configuration
+ */
+static inline void *textsearch_get_pattern(struct ts_config *conf)
+{
+ return conf->ops->get_pattern(conf);
+}
+
+/**
+ * textsearch_get_pattern_len - return length of the pattern
+ * @conf: search configuration
+ */
+static inline unsigned int textsearch_get_pattern_len(struct ts_config *conf)
+{
+ return conf->ops->get_pattern_len(conf);
+}
+
+extern int textsearch_register(struct ts_ops *);
+extern int textsearch_unregister(struct ts_ops *);
+extern struct ts_config *textsearch_prepare(const char *, const void *,
+ unsigned int, int, int);
+extern void textsearch_destroy(struct ts_config *conf);
+extern unsigned int textsearch_find_continuous(struct ts_config *,
+ struct ts_state *,
+ const void *, unsigned int);
+
+
+#define TS_PRIV_ALIGNTO 8
+#define TS_PRIV_ALIGN(len) (((len) + TS_PRIV_ALIGNTO-1) & ~(TS_PRIV_ALIGNTO-1))
+
+static inline struct ts_config *alloc_ts_config(size_t payload, int gfp_mask)
+{
+ struct ts_config *conf;
+
+ conf = kmalloc(TS_PRIV_ALIGN(sizeof(*conf)) + payload, gfp_mask);
+ if (conf == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ memset(conf, 0, TS_PRIV_ALIGN(sizeof(*conf)) + payload);
+ return conf;
+}
+
+static inline void *ts_config_priv(struct ts_config *conf)
+{
+ return ((u8 *) conf + TS_PRIV_ALIGN(sizeof(struct ts_config)));
+}
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/include/linux/textsearch_fsm.h b/include/linux/textsearch_fsm.h
new file mode 100644
index 00000000000..fdfa078c66e
--- /dev/null
+++ b/include/linux/textsearch_fsm.h
@@ -0,0 +1,48 @@
+#ifndef __LINUX_TEXTSEARCH_FSM_H
+#define __LINUX_TEXTSEARCH_FSM_H
+
+#include <linux/types.h>
+
+enum {
+ TS_FSM_SPECIFIC, /* specific character */
+ TS_FSM_WILDCARD, /* any character */
+ TS_FSM_DIGIT, /* isdigit() */
+ TS_FSM_XDIGIT, /* isxdigit() */
+ TS_FSM_PRINT, /* isprint() */
+ TS_FSM_ALPHA, /* isalpha() */
+ TS_FSM_ALNUM, /* isalnum() */
+ TS_FSM_ASCII, /* isascii() */
+ TS_FSM_CNTRL, /* iscntrl() */
+ TS_FSM_GRAPH, /* isgraph() */
+ TS_FSM_LOWER, /* islower() */
+ TS_FSM_UPPER, /* isupper() */
+ TS_FSM_PUNCT, /* ispunct() */
+ TS_FSM_SPACE, /* isspace() */
+ __TS_FSM_TYPE_MAX,
+};
+#define TS_FSM_TYPE_MAX (__TS_FSM_TYPE_MAX - 1)
+
+enum {
+ TS_FSM_SINGLE, /* 1 occurrence */
+ TS_FSM_PERHAPS, /* 1 or 0 occurrence */
+ TS_FSM_ANY, /* 0..n occurrences */
+ TS_FSM_MULTI, /* 1..n occurrences */
+ TS_FSM_HEAD_IGNORE, /* 0..n ignored occurrences at head */
+ __TS_FSM_RECUR_MAX,
+};
+#define TS_FSM_RECUR_MAX (__TS_FSM_RECUR_MAX - 1)
+
+/**
+ * struct ts_fsm_token - state machine token (state)
+ * @type: type of token
+ * @recur: number of recurrences
+ * @value: character value for TS_FSM_SPECIFIC
+ */
+struct ts_fsm_token
+{
+ __u16 type;
+ __u8 recur;
+ __u8 value;
+};
+
+#endif
diff --git a/include/linux/timer.h b/include/linux/timer.h
index 90db1cc62dd..221f81ac200 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -6,45 +6,33 @@
#include <linux/spinlock.h>
#include <linux/stddef.h>
-struct tvec_t_base_s;
+struct timer_base_s;
struct timer_list {
struct list_head entry;
unsigned long expires;
- spinlock_t lock;
unsigned long magic;
void (*function)(unsigned long);
unsigned long data;
- struct tvec_t_base_s *base;
+ struct timer_base_s *base;
};
#define TIMER_MAGIC 0x4b87ad6e
+extern struct timer_base_s __init_timer_base;
+
#define TIMER_INITIALIZER(_function, _expires, _data) { \
.function = (_function), \
.expires = (_expires), \
.data = (_data), \
- .base = NULL, \
+ .base = &__init_timer_base, \
.magic = TIMER_MAGIC, \
- .lock = SPIN_LOCK_UNLOCKED, \
}
-/***
- * init_timer - initialize a timer.
- * @timer: the timer to be initialized
- *
- * init_timer() must be done to a timer prior calling *any* of the
- * other timer functions.
- */
-static inline void init_timer(struct timer_list * timer)
-{
- timer->base = NULL;
- timer->magic = TIMER_MAGIC;
- spin_lock_init(&timer->lock);
-}
+void fastcall init_timer(struct timer_list * timer);
/***
* timer_pending - is a timer pending?
@@ -58,7 +46,7 @@ static inline void init_timer(struct timer_list * timer)
*/
static inline int timer_pending(const struct timer_list * timer)
{
- return timer->base != NULL;
+ return timer->entry.next != NULL;
}
extern void add_timer_on(struct timer_list *timer, int cpu);
@@ -88,13 +76,15 @@ static inline void add_timer(struct timer_list * timer)
}
#ifdef CONFIG_SMP
+ extern int try_to_del_timer_sync(struct timer_list *timer);
extern int del_timer_sync(struct timer_list *timer);
- extern int del_singleshot_timer_sync(struct timer_list *timer);
#else
-# define del_timer_sync(t) del_timer(t)
-# define del_singleshot_timer_sync(t) del_timer(t)
+# define try_to_del_timer_sync(t) del_timer(t)
+# define del_timer_sync(t) del_timer(t)
#endif
+#define del_singleshot_timer_sync(t) del_timer_sync(t)
+
extern void init_timers(void);
extern void run_local_timers(void);
extern void it_real_fn(unsigned long);
diff --git a/include/linux/topology.h b/include/linux/topology.h
index d70e8972c67..0320225e96d 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -89,6 +89,11 @@
.cache_hot_time = 0, \
.cache_nice_tries = 0, \
.per_cpu_gain = 25, \
+ .busy_idx = 0, \
+ .idle_idx = 0, \
+ .newidle_idx = 1, \
+ .wake_idx = 0, \
+ .forkexec_idx = 0, \
.flags = SD_LOAD_BALANCE \
| SD_BALANCE_NEWIDLE \
| SD_BALANCE_EXEC \
@@ -115,12 +120,15 @@
.cache_hot_time = (5*1000000/2), \
.cache_nice_tries = 1, \
.per_cpu_gain = 100, \
+ .busy_idx = 2, \
+ .idle_idx = 1, \
+ .newidle_idx = 2, \
+ .wake_idx = 1, \
+ .forkexec_idx = 1, \
.flags = SD_LOAD_BALANCE \
| SD_BALANCE_NEWIDLE \
| SD_BALANCE_EXEC \
- | SD_WAKE_AFFINE \
- | SD_WAKE_IDLE \
- | SD_WAKE_BALANCE, \
+ | SD_WAKE_AFFINE, \
.last_balance = jiffies, \
.balance_interval = 1, \
.nr_balance_failed = 0, \
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 1b76106272d..59ff42c629e 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -345,6 +345,7 @@ extern int tty_check_change(struct tty_struct * tty);
extern void stop_tty(struct tty_struct * tty);
extern void start_tty(struct tty_struct * tty);
extern int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc);
+extern int tty_unregister_ldisc(int disc);
extern int tty_register_driver(struct tty_driver *driver);
extern int tty_unregister_driver(struct tty_driver *driver);
extern void tty_register_device(struct tty_driver *driver, unsigned index, struct device *dev);
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 41d1a644c9d..eb282b58154 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -287,15 +287,14 @@ struct usb_bus {
struct dentry *usbfs_dentry; /* usbfs dentry entry for the bus */
- struct class_device class_dev; /* class device for this bus */
+ struct class_device *class_dev; /* class device for this bus */
+ struct kref kref; /* handles reference counting this bus */
void (*release)(struct usb_bus *bus); /* function to destroy this bus's memory */
-#if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)
+#if defined(CONFIG_USB_MON)
struct mon_bus *mon_bus; /* non-null when associated */
int monitored; /* non-zero when monitored */
#endif
};
-#define to_usb_bus(d) container_of(d, struct usb_bus, class_dev)
-
/* -------------------------------------------------------------------------- */
@@ -796,6 +795,10 @@ typedef void (*usb_complete_t)(struct urb *, struct pt_regs *);
* of the iso_frame_desc array, and the number of errors is reported in
* error_count. Completion callbacks for ISO transfers will normally
* (re)submit URBs to ensure a constant transfer rate.
+ *
+ * Note that even fields marked "public" should not be touched by the driver
+ * when the urb is owned by the hcd, that is, since the call to
+ * usb_submit_urb() till the entry into the completion routine.
*/
struct urb
{
@@ -803,12 +806,12 @@ struct urb
struct kref kref; /* reference count of the URB */
spinlock_t lock; /* lock for the URB */
void *hcpriv; /* private data for host controller */
- struct list_head urb_list; /* list pointer to all active urbs */
int bandwidth; /* bandwidth for INT/ISO request */
atomic_t use_count; /* concurrent submissions counter */
u8 reject; /* submissions will fail */
/* public, documented fields in the urb that can be used by drivers */
+ struct list_head urb_list; /* list head for use by the urb owner */
struct usb_device *dev; /* (in) pointer to associated device */
unsigned int pipe; /* (in) pipe information */
int status; /* (return) non-ISO status */
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 3a358c89518..6409d9cf596 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -41,6 +41,7 @@ extern struct vm_struct *get_vm_area(unsigned long size, unsigned long flags);
extern struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
unsigned long start, unsigned long end);
extern struct vm_struct *remove_vm_area(void *addr);
+extern struct vm_struct *__remove_vm_area(void *addr);
extern int map_vm_area(struct vm_struct *area, pgprot_t prot,
struct page ***pages);
extern void unmap_vm_area(struct vm_struct *area);
diff --git a/include/linux/wait.h b/include/linux/wait.h
index 17c874a8eb3..d38c9fecdc3 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -33,7 +33,7 @@ int default_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key
struct __wait_queue {
unsigned int flags;
#define WQ_FLAG_EXCLUSIVE 0x01
- struct task_struct * task;
+ void *private;
wait_queue_func_t func;
struct list_head task_list;
};
@@ -60,7 +60,7 @@ typedef struct __wait_queue_head wait_queue_head_t;
*/
#define __WAITQUEUE_INITIALIZER(name, tsk) { \
- .task = tsk, \
+ .private = tsk, \
.func = default_wake_function, \
.task_list = { NULL, NULL } }
@@ -86,7 +86,7 @@ static inline void init_waitqueue_head(wait_queue_head_t *q)
static inline void init_waitqueue_entry(wait_queue_t *q, struct task_struct *p)
{
q->flags = 0;
- q->task = p;
+ q->private = p;
q->func = default_wake_function;
}
@@ -94,7 +94,7 @@ static inline void init_waitqueue_func_entry(wait_queue_t *q,
wait_queue_func_t func)
{
q->flags = 0;
- q->task = NULL;
+ q->private = NULL;
q->func = func;
}
@@ -110,7 +110,7 @@ static inline int waitqueue_active(wait_queue_head_t *q)
* aio specifies a wait queue entry with an async notification
* callback routine, not associated with any task.
*/
-#define is_sync_wait(wait) (!(wait) || ((wait)->task))
+#define is_sync_wait(wait) (!(wait) || ((wait)->private))
extern void FASTCALL(add_wait_queue(wait_queue_head_t *q, wait_queue_t * wait));
extern void FASTCALL(add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t * wait));
@@ -384,18 +384,16 @@ int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
#define DEFINE_WAIT(name) \
wait_queue_t name = { \
- .task = current, \
+ .private = current, \
.func = autoremove_wake_function, \
- .task_list = { .next = &(name).task_list, \
- .prev = &(name).task_list, \
- }, \
+ .task_list = LIST_HEAD_INIT((name).task_list), \
}
#define DEFINE_WAIT_BIT(name, word, bit) \
struct wait_bit_queue name = { \
.key = __WAIT_BIT_KEY_INITIALIZER(word, bit), \
.wait = { \
- .task = current, \
+ .private = current, \
.func = wake_bit_function, \
.task_list = \
LIST_HEAD_INIT((name).wait.task_list), \
@@ -404,7 +402,7 @@ int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
#define init_wait(wait) \
do { \
- (wait)->task = current; \
+ (wait)->private = current; \
(wait)->func = autoremove_wake_function; \
INIT_LIST_HEAD(&(wait)->task_list); \
} while (0)
diff --git a/include/linux/wireless.h b/include/linux/wireless.h
index 2f51f2b6562..ae485f9c916 100644
--- a/include/linux/wireless.h
+++ b/include/linux/wireless.h
@@ -1,10 +1,10 @@
/*
* This file define a set of standard wireless extensions
*
- * Version : 17 21.6.04
+ * Version : 18 12.3.05
*
* Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
- * Copyright (c) 1997-2004 Jean Tourrilhes, All Rights Reserved.
+ * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved.
*/
#ifndef _LINUX_WIRELESS_H
@@ -82,7 +82,7 @@
* (there is some stuff that will be added in the future...)
* I just plan to increment with each new version.
*/
-#define WIRELESS_EXT 17
+#define WIRELESS_EXT 18
/*
* Changes :
@@ -182,6 +182,21 @@
* - Document (struct iw_quality *)->updated, add new flags (INVALID)
* - Wireless Event capability in struct iw_range
* - Add support for relative TxPower (yick !)
+ *
+ * V17 to V18 (From Jouni Malinen <jkmaline@cc.hut.fi>)
+ * ----------
+ * - Add support for WPA/WPA2
+ * - Add extended encoding configuration (SIOCSIWENCODEEXT and
+ * SIOCGIWENCODEEXT)
+ * - Add SIOCSIWGENIE/SIOCGIWGENIE
+ * - Add SIOCSIWMLME
+ * - Add SIOCSIWPMKSA
+ * - Add struct iw_range bit field for supported encoding capabilities
+ * - Add optional scan request parameters for SIOCSIWSCAN
+ * - Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA
+ * related parameters (extensible up to 4096 parameter values)
+ * - Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE,
+ * IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND
*/
/**************************** CONSTANTS ****************************/
@@ -256,6 +271,30 @@
#define SIOCSIWPOWER 0x8B2C /* set Power Management settings */
#define SIOCGIWPOWER 0x8B2D /* get Power Management settings */
+/* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM).
+ * This ioctl uses struct iw_point and data buffer that includes IE id and len
+ * fields. More than one IE may be included in the request. Setting the generic
+ * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers
+ * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers
+ * are required to report the used IE as a wireless event, e.g., when
+ * associating with an AP. */
+#define SIOCSIWGENIE 0x8B30 /* set generic IE */
+#define SIOCGIWGENIE 0x8B31 /* get generic IE */
+
+/* WPA : IEEE 802.11 MLME requests */
+#define SIOCSIWMLME 0x8B16 /* request MLME operation; uses
+ * struct iw_mlme */
+/* WPA : Authentication mode parameters */
+#define SIOCSIWAUTH 0x8B32 /* set authentication mode params */
+#define SIOCGIWAUTH 0x8B33 /* get authentication mode params */
+
+/* WPA : Extended version of encoding configuration */
+#define SIOCSIWENCODEEXT 0x8B34 /* set encoding token & mode */
+#define SIOCGIWENCODEEXT 0x8B35 /* get encoding token & mode */
+
+/* WPA2 : PMKSA cache management */
+#define SIOCSIWPMKSA 0x8B36 /* PMKSA cache operation */
+
/* -------------------- DEV PRIVATE IOCTL LIST -------------------- */
/* These 32 ioctl are wireless device private, for 16 commands.
@@ -297,6 +336,34 @@
#define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */
#define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */
#define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */
+#define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..)
+ * (scan results); This includes id and
+ * length fields. One IWEVGENIE may
+ * contain more than one IE. Scan
+ * results may contain one or more
+ * IWEVGENIE events. */
+#define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure
+ * (struct iw_michaelmicfailure)
+ */
+#define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request.
+ * The data includes id and length
+ * fields and may contain more than one
+ * IE. This event is required in
+ * Managed mode if the driver
+ * generates its own WPA/RSN IE. This
+ * should be sent just before
+ * IWEVREGISTERED event for the
+ * association. */
+#define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association
+ * Response. The data includes id and
+ * length fields and may contain more
+ * than one IE. This may be sent
+ * between IWEVASSOCREQIE and
+ * IWEVREGISTERED events for the
+ * association. */
+#define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN
+ * pre-authentication
+ * (struct iw_pmkid_cand) */
#define IWEVFIRST 0x8C00
@@ -432,12 +499,94 @@
#define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */
#define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */
#define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */
+/* struct iw_scan_req scan_type */
+#define IW_SCAN_TYPE_ACTIVE 0
+#define IW_SCAN_TYPE_PASSIVE 1
/* Maximum size of returned data */
#define IW_SCAN_MAX_DATA 4096 /* In bytes */
/* Max number of char in custom event - use multiple of them if needed */
#define IW_CUSTOM_MAX 256 /* In bytes */
+/* Generic information element */
+#define IW_GENERIC_IE_MAX 1024
+
+/* MLME requests (SIOCSIWMLME / struct iw_mlme) */
+#define IW_MLME_DEAUTH 0
+#define IW_MLME_DISASSOC 1
+
+/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */
+#define IW_AUTH_INDEX 0x0FFF
+#define IW_AUTH_FLAGS 0xF000
+/* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095)
+ * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the
+ * parameter that is being set/get to; value will be read/written to
+ * struct iw_param value field) */
+#define IW_AUTH_WPA_VERSION 0
+#define IW_AUTH_CIPHER_PAIRWISE 1
+#define IW_AUTH_CIPHER_GROUP 2
+#define IW_AUTH_KEY_MGMT 3
+#define IW_AUTH_TKIP_COUNTERMEASURES 4
+#define IW_AUTH_DROP_UNENCRYPTED 5
+#define IW_AUTH_80211_AUTH_ALG 6
+#define IW_AUTH_WPA_ENABLED 7
+#define IW_AUTH_RX_UNENCRYPTED_EAPOL 8
+#define IW_AUTH_ROAMING_CONTROL 9
+#define IW_AUTH_PRIVACY_INVOKED 10
+
+/* IW_AUTH_WPA_VERSION values (bit field) */
+#define IW_AUTH_WPA_VERSION_DISABLED 0x00000001
+#define IW_AUTH_WPA_VERSION_WPA 0x00000002
+#define IW_AUTH_WPA_VERSION_WPA2 0x00000004
+
+/* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */
+#define IW_AUTH_CIPHER_NONE 0x00000001
+#define IW_AUTH_CIPHER_WEP40 0x00000002
+#define IW_AUTH_CIPHER_TKIP 0x00000004
+#define IW_AUTH_CIPHER_CCMP 0x00000008
+#define IW_AUTH_CIPHER_WEP104 0x00000010
+
+/* IW_AUTH_KEY_MGMT values (bit field) */
+#define IW_AUTH_KEY_MGMT_802_1X 1
+#define IW_AUTH_KEY_MGMT_PSK 2
+
+/* IW_AUTH_80211_AUTH_ALG values (bit field) */
+#define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001
+#define IW_AUTH_ALG_SHARED_KEY 0x00000002
+#define IW_AUTH_ALG_LEAP 0x00000004
+
+/* IW_AUTH_ROAMING_CONTROL values */
+#define IW_AUTH_ROAMING_ENABLE 0 /* driver/firmware based roaming */
+#define IW_AUTH_ROAMING_DISABLE 1 /* user space program used for roaming
+ * control */
+
+/* SIOCSIWENCODEEXT definitions */
+#define IW_ENCODE_SEQ_MAX_SIZE 8
+/* struct iw_encode_ext ->alg */
+#define IW_ENCODE_ALG_NONE 0
+#define IW_ENCODE_ALG_WEP 1
+#define IW_ENCODE_ALG_TKIP 2
+#define IW_ENCODE_ALG_CCMP 3
+/* struct iw_encode_ext ->ext_flags */
+#define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001
+#define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002
+#define IW_ENCODE_EXT_GROUP_KEY 0x00000004
+#define IW_ENCODE_EXT_SET_TX_KEY 0x00000008
+
+/* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */
+#define IW_MICFAILURE_KEY_ID 0x00000003 /* Key ID 0..3 */
+#define IW_MICFAILURE_GROUP 0x00000004
+#define IW_MICFAILURE_PAIRWISE 0x00000008
+#define IW_MICFAILURE_STAKEY 0x00000010
+#define IW_MICFAILURE_COUNT 0x00000060 /* 1 or 2 (0 = count not supported)
+ */
+
+/* Bit field values for enc_capa in struct iw_range */
+#define IW_ENC_CAPA_WPA 0x00000001
+#define IW_ENC_CAPA_WPA2 0x00000002
+#define IW_ENC_CAPA_CIPHER_TKIP 0x00000004
+#define IW_ENC_CAPA_CIPHER_CCMP 0x00000008
+
/* Event capability macros - in (struct iw_range *)->event_capa
* Because we have more than 32 possible events, we use an array of
* 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */
@@ -546,6 +695,132 @@ struct iw_thrspy
struct iw_quality high; /* High threshold */
};
+/*
+ * Optional data for scan request
+ *
+ * Note: these optional parameters are controlling parameters for the
+ * scanning behavior, these do not apply to getting scan results
+ * (SIOCGIWSCAN). Drivers are expected to keep a local BSS table and
+ * provide a merged results with all BSSes even if the previous scan
+ * request limited scanning to a subset, e.g., by specifying an SSID.
+ * Especially, scan results are required to include an entry for the
+ * current BSS if the driver is in Managed mode and associated with an AP.
+ */
+struct iw_scan_req
+{
+ __u8 scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */
+ __u8 essid_len;
+ __u8 num_channels; /* num entries in channel_list;
+ * 0 = scan all allowed channels */
+ __u8 flags; /* reserved as padding; use zero, this may
+ * be used in the future for adding flags
+ * to request different scan behavior */
+ struct sockaddr bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or
+ * individual address of a specific BSS */
+
+ /*
+ * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using
+ * the current ESSID. This allows scan requests for specific ESSID
+ * without having to change the current ESSID and potentially breaking
+ * the current association.
+ */
+ __u8 essid[IW_ESSID_MAX_SIZE];
+
+ /*
+ * Optional parameters for changing the default scanning behavior.
+ * These are based on the MLME-SCAN.request from IEEE Std 802.11.
+ * TU is 1.024 ms. If these are set to 0, driver is expected to use
+ * reasonable default values. min_channel_time defines the time that
+ * will be used to wait for the first reply on each channel. If no
+ * replies are received, next channel will be scanned after this. If
+ * replies are received, total time waited on the channel is defined by
+ * max_channel_time.
+ */
+ __u32 min_channel_time; /* in TU */
+ __u32 max_channel_time; /* in TU */
+
+ struct iw_freq channel_list[IW_MAX_FREQUENCIES];
+};
+
+/* ------------------------- WPA SUPPORT ------------------------- */
+
+/*
+ * Extended data structure for get/set encoding (this is used with
+ * SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_*
+ * flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and
+ * only the data contents changes (key data -> this structure, including
+ * key data).
+ *
+ * If the new key is the first group key, it will be set as the default
+ * TX key. Otherwise, default TX key index is only changed if
+ * IW_ENCODE_EXT_SET_TX_KEY flag is set.
+ *
+ * Key will be changed with SIOCSIWENCODEEXT in all cases except for
+ * special "change TX key index" operation which is indicated by setting
+ * key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY.
+ *
+ * tx_seq/rx_seq are only used when respective
+ * IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal
+ * TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start
+ * TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally
+ * used only by an Authenticator (AP or an IBSS station) to get the
+ * current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and
+ * RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for
+ * debugging/testing.
+ */
+struct iw_encode_ext
+{
+ __u32 ext_flags; /* IW_ENCODE_EXT_* */
+ __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
+ __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
+ struct sockaddr addr; /* ff:ff:ff:ff:ff:ff for broadcast/multicast
+ * (group) keys or unicast address for
+ * individual keys */
+ __u16 alg; /* IW_ENCODE_ALG_* */
+ __u16 key_len;
+ __u8 key[0];
+};
+
+/* SIOCSIWMLME data */
+struct iw_mlme
+{
+ __u16 cmd; /* IW_MLME_* */
+ __u16 reason_code;
+ struct sockaddr addr;
+};
+
+/* SIOCSIWPMKSA data */
+#define IW_PMKSA_ADD 1
+#define IW_PMKSA_REMOVE 2
+#define IW_PMKSA_FLUSH 3
+
+#define IW_PMKID_LEN 16
+
+struct iw_pmksa
+{
+ __u32 cmd; /* IW_PMKSA_* */
+ struct sockaddr bssid;
+ __u8 pmkid[IW_PMKID_LEN];
+};
+
+/* IWEVMICHAELMICFAILURE data */
+struct iw_michaelmicfailure
+{
+ __u32 flags;
+ struct sockaddr src_addr;
+ __u8 tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
+};
+
+/* IWEVPMKIDCAND data */
+#define IW_PMKID_CAND_PREAUTH 0x00000001 /* RNS pre-authentication enabled */
+struct iw_pmkid_cand
+{
+ __u32 flags; /* IW_PMKID_CAND_* */
+ __u32 index; /* the smaller the index, the higher the
+ * priority */
+ struct sockaddr bssid;
+};
+
/* ------------------------ WIRELESS STATS ------------------------ */
/*
* Wireless statistics (used for /proc/net/wireless)
@@ -725,6 +1000,8 @@ struct iw_range
struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */
/* Note : this frequency list doesn't need to fit channel numbers,
* because each entry contain its channel index */
+
+ __u32 enc_capa; /* IW_ENC_CAPA_* bit field */
};
/*
diff --git a/include/linux/x25.h b/include/linux/x25.h
index 7531cfed588..16d44931afa 100644
--- a/include/linux/x25.h
+++ b/include/linux/x25.h
@@ -4,6 +4,8 @@
* History
* mar/20/00 Daniela Squassoni Disabling/enabling of facilities
* negotiation.
+ * apr/02/05 Shaun Pereira Selective sub address matching with
+ * call user data
*/
#ifndef X25_KERNEL_H
@@ -16,6 +18,9 @@
#define SIOCX25GCALLUSERDATA (SIOCPROTOPRIVATE + 4)
#define SIOCX25SCALLUSERDATA (SIOCPROTOPRIVATE + 5)
#define SIOCX25GCAUSEDIAG (SIOCPROTOPRIVATE + 6)
+#define SIOCX25SCUDMATCHLEN (SIOCPROTOPRIVATE + 7)
+#define SIOCX25CALLACCPTAPPRV (SIOCPROTOPRIVATE + 8)
+#define SIOCX25SENDCALLACCPT (SIOCPROTOPRIVATE + 9)
/*
* Values for {get,set}sockopt.
@@ -109,4 +114,11 @@ struct x25_causediag {
unsigned char diagnostic;
};
+/*
+ * Further optional call user data match length selection
+ */
+struct x25_subaddr {
+ unsigned int cudmatchlength;
+};
+
#endif
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index fd2ef742a9f..f0d423300d8 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -174,6 +174,8 @@ enum xfrm_attr_type_t {
XFRMA_ALG_COMP, /* struct xfrm_algo */
XFRMA_ENCAP, /* struct xfrm_algo + struct xfrm_encap_tmpl */
XFRMA_TMPL, /* 1 or more struct xfrm_user_tmpl */
+ XFRMA_SA,
+ XFRMA_POLICY,
__XFRMA_MAX
#define XFRMA_MAX (__XFRMA_MAX - 1)
@@ -194,6 +196,7 @@ struct xfrm_usersa_info {
__u8 flags;
#define XFRM_STATE_NOECN 1
#define XFRM_STATE_DECAP_DSCP 2
+#define XFRM_STATE_NOPMTUDISC 4
};
struct xfrm_usersa_id {
@@ -257,5 +260,7 @@ struct xfrm_usersa_flush {
#define XFRMGRP_ACQUIRE 1
#define XFRMGRP_EXPIRE 2
+#define XFRMGRP_SA 4
+#define XFRMGRP_POLICY 8
#endif /* _LINUX_XFRM_H */
diff --git a/include/media/audiochip.h b/include/media/audiochip.h
index d3e9e30608d..f345a61c3bd 100644
--- a/include/media/audiochip.h
+++ b/include/media/audiochip.h
@@ -1,3 +1,7 @@
+/*
+ * $Id: audiochip.h,v 1.3 2005/06/12 04:19:19 mchehab Exp $
+ */
+
#ifndef AUDIOCHIP_H
#define AUDIOCHIP_H
diff --git a/include/media/id.h b/include/media/id.h
index 1b0320dc8f7..a39a6423914 100644
--- a/include/media/id.h
+++ b/include/media/id.h
@@ -1,3 +1,7 @@
+/*
+ * $Id: id.h,v 1.4 2005/06/12 04:19:19 mchehab Exp $
+ */
+
/* FIXME: this temporarely, until these are included in linux/i2c-id.h */
/* drivers */
diff --git a/include/media/ir-common.h b/include/media/ir-common.h
index 62c963a52d8..698670547f1 100644
--- a/include/media/ir-common.h
+++ b/include/media/ir-common.h
@@ -1,5 +1,5 @@
/*
- * $Id: ir-common.h,v 1.8 2005/02/22 12:28:40 kraxel Exp $
+ * $Id: ir-common.h,v 1.9 2005/05/15 19:01:26 mchehab Exp $
*
* some common structs and functions to handle infrared remotes via
* input layer ...
@@ -50,6 +50,7 @@ extern IR_KEYTAB_TYPE ir_codes_rc5_tv[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE];
extern IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE];
void ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
int ir_type, IR_KEYTAB_TYPE *ir_codes);
diff --git a/include/media/tuner.h b/include/media/tuner.h
index 156a9c51ffe..2dd8310901e 100644
--- a/include/media/tuner.h
+++ b/include/media/tuner.h
@@ -25,6 +25,8 @@
#include "id.h"
+#define ADDR_UNSET (255)
+
#define TUNER_TEMIC_PAL 0 /* 4002 FH5 (3X 7756, 9483) */
#define TUNER_PHILIPS_PAL_I 1
#define TUNER_PHILIPS_NTSC 2
@@ -98,12 +100,23 @@
#define TUNER_PHILIPS_FQ1216AME_MK4 56 /* Hauppauge PVR-150 PAL */
#define TUNER_PHILIPS_FQ1236A_MK4 57 /* Hauppauge PVR-500MCE NTSC */
+#define TUNER_YMEC_TVF_8531MF 58
+#define TUNER_YMEC_TVF_5533MF 59 /* Pixelview Pro Ultra NTSC */
+#define TUNER_THOMSON_DTT7611 60
+#define TUNER_TENA_9533_DI 61
+#define TUNER_TEA5767 62 /* Only FM Radio Tuner */
+
+#define TEA5767_TUNER_NAME "Philips TEA5767HN FM Radio"
+
+#define TUNER_THOMSON_DTT7611 60
+
#define NOTUNER 0
#define PAL 1 /* PAL_BG */
#define PAL_I 2
#define NTSC 3
#define SECAM 4
#define ATSC 5
+#define RADIO 6
#define NoTuner 0
#define Philips 1
@@ -119,10 +132,20 @@
#define TCL 11
#define THOMSON 12
+enum v4l_radio_tuner {
+ TEA5767_LOW_LO_32768 = 0,
+ TEA5767_HIGH_LO_32768 = 1,
+ TEA5767_LOW_LO_13MHz = 2,
+ TEA5767_HIGH_LO_13MHz = 3,
+};
+
+
#define TUNER_SET_TYPE _IOW('t',1,int) /* set tuner type */
#define TUNER_SET_TVFREQ _IOW('t',2,int) /* set tv freq */
+#define TUNER_SET_TYPE_ADDR _IOW('T',3,int) /* set tuner type and I2C addr */
#define TDA9887_SET_CONFIG _IOW('t',5,int)
+
/* tv card specific */
# define TDA9887_PRESENT (1<<0)
# define TDA9887_PORT1_INACTIVE (1<<1)
@@ -143,6 +166,12 @@
#define I2C_ADDR_TDA8290 0x4b
#define I2C_ADDR_TDA8275 0x61
+struct tuner_addr {
+ enum v4l2_tuner_type v4l2_tuner;
+ unsigned int type;
+ unsigned short addr;
+};
+
struct tuner {
/* device */
struct i2c_client i2c;
diff --git a/include/media/tveeprom.h b/include/media/tveeprom.h
index 627603e561a..5c4fe30e8d1 100644
--- a/include/media/tveeprom.h
+++ b/include/media/tveeprom.h
@@ -1,3 +1,7 @@
+/*
+ * $Id: tveeprom.h,v 1.2 2005/06/12 04:19:19 mchehab Exp $
+ */
+
struct tveeprom {
u32 has_radio;
diff --git a/include/media/video-buf-dvb.h b/include/media/video-buf-dvb.h
index 94bd33619aa..ad0a07a3a89 100644
--- a/include/media/video-buf-dvb.h
+++ b/include/media/video-buf-dvb.h
@@ -16,7 +16,7 @@ struct videobuf_dvb {
int nfeeds;
/* videobuf_dvb_(un)register manges this */
- struct dvb_adapter *adapter;
+ struct dvb_adapter adapter;
struct dvb_demux demux;
struct dmxdev dmxdev;
struct dmx_frontend fe_hw;
diff --git a/include/net/act_generic.h b/include/net/act_generic.h
index 95b120781c1..c9daa7e5230 100644
--- a/include/net/act_generic.h
+++ b/include/net/act_generic.h
@@ -2,8 +2,8 @@
* include/net/act_generic.h
*
*/
-#ifndef ACT_GENERIC_H
-#define ACT_GENERIC_H
+#ifndef _NET_ACT_GENERIC_H
+#define _NET_ACT_GENERIC_H
static inline int tcf_defact_release(struct tcf_defact *p, int bind)
{
int ret = 0;
diff --git a/include/net/ax25.h b/include/net/ax25.h
index 9e6368a5454..828a3a93dda 100644
--- a/include/net/ax25.h
+++ b/include/net/ax25.h
@@ -220,7 +220,7 @@ static __inline__ void ax25_cb_put(ax25_cb *ax25)
}
}
-static inline unsigned short ax25_type_trans(struct sk_buff *skb, struct net_device *dev)
+static inline __be16 ax25_type_trans(struct sk_buff *skb, struct net_device *dev)
{
skb->dev = dev;
skb->pkt_type = PACKET_HOST;
diff --git a/include/net/ip.h b/include/net/ip.h
index 3f63992eb71..32360bbe143 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -163,6 +163,7 @@ DECLARE_SNMP_STAT(struct linux_mib, net_statistics);
extern int sysctl_local_port_range[2];
extern int sysctl_ip_default_ttl;
+extern int sysctl_ip_nonlocal_bind;
#ifdef CONFIG_INET
/* The function in 2.2 was invalid, producing wrong result for
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 31990451819..a66e9de16a6 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -167,14 +167,17 @@ extern int fib6_walk_continue(struct fib6_walker_t *w);
extern int fib6_add(struct fib6_node *root,
struct rt6_info *rt,
struct nlmsghdr *nlh,
- void *rtattr);
+ void *rtattr,
+ struct netlink_skb_parms *req);
extern int fib6_del(struct rt6_info *rt,
struct nlmsghdr *nlh,
- void *rtattr);
+ void *rtattr,
+ struct netlink_skb_parms *req);
extern void inet6_rt_notify(int event, struct rt6_info *rt,
- struct nlmsghdr *nlh);
+ struct nlmsghdr *nlh,
+ struct netlink_skb_parms *req);
extern void fib6_run_gc(unsigned long dummy);
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index d5d1dd10cdb..f920706d526 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -41,13 +41,16 @@ extern int ipv6_route_ioctl(unsigned int cmd, void __user *arg);
extern int ip6_route_add(struct in6_rtmsg *rtmsg,
struct nlmsghdr *,
- void *rtattr);
+ void *rtattr,
+ struct netlink_skb_parms *req);
extern int ip6_ins_rt(struct rt6_info *,
struct nlmsghdr *,
- void *rtattr);
+ void *rtattr,
+ struct netlink_skb_parms *req);
extern int ip6_del_rt(struct rt6_info *,
struct nlmsghdr *,
- void *rtattr);
+ void *rtattr,
+ struct netlink_skb_parms *req);
extern int ip6_rt_addr_add(struct in6_addr *addr,
struct net_device *dev,
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index e5a5f6b62f8..a4208a336ac 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -109,6 +109,20 @@ struct fib_result {
#endif
};
+struct fib_result_nl {
+ u32 fl_addr; /* To be looked up*/
+ u32 fl_fwmark;
+ unsigned char fl_tos;
+ unsigned char fl_scope;
+ unsigned char tb_id_in;
+
+ unsigned char tb_id; /* Results */
+ unsigned char prefixlen;
+ unsigned char nh_sel;
+ unsigned char type;
+ unsigned char scope;
+ int err;
+};
#ifdef CONFIG_IP_ROUTE_MULTIPATH
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 4f33bbc21e7..89809891e5a 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -65,11 +65,10 @@ struct neighbour;
struct neigh_parms
{
+ struct net_device *dev;
struct neigh_parms *next;
int (*neigh_setup)(struct neighbour *);
struct neigh_table *tbl;
- int entries;
- void *priv;
void *sysctl_table;
@@ -192,7 +191,6 @@ struct neigh_table
atomic_t entries;
rwlock_t lock;
unsigned long last_rand;
- struct neigh_parms *parms_list;
kmem_cache_t *kmem_cachep;
struct neigh_statistics *stats;
struct neighbour **hash_buckets;
@@ -252,6 +250,9 @@ extern int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
extern int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
extern void neigh_app_ns(struct neighbour *n);
+extern int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb);
+extern int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
+
extern void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie);
extern void __neigh_for_each_release(struct neigh_table *tbl, int (*cb)(struct neighbour *));
extern void pneigh_for_each(struct neigh_table *tbl, void (*cb)(struct pneigh_entry *));
diff --git a/include/net/request_sock.h b/include/net/request_sock.h
new file mode 100644
index 00000000000..72fd6f5e86b
--- /dev/null
+++ b/include/net/request_sock.h
@@ -0,0 +1,255 @@
+/*
+ * NET Generic infrastructure for Network protocols.
+ *
+ * Definitions for request_sock
+ *
+ * Authors: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * From code originally in include/net/tcp.h
+ *
+ * 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 _REQUEST_SOCK_H
+#define _REQUEST_SOCK_H
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <net/sock.h>
+
+struct request_sock;
+struct sk_buff;
+struct dst_entry;
+struct proto;
+
+struct request_sock_ops {
+ int family;
+ kmem_cache_t *slab;
+ int obj_size;
+ int (*rtx_syn_ack)(struct sock *sk,
+ struct request_sock *req,
+ struct dst_entry *dst);
+ void (*send_ack)(struct sk_buff *skb,
+ struct request_sock *req);
+ void (*send_reset)(struct sk_buff *skb);
+ void (*destructor)(struct request_sock *req);
+};
+
+/* struct request_sock - mini sock to represent a connection request
+ */
+struct request_sock {
+ struct request_sock *dl_next; /* Must be first member! */
+ u16 mss;
+ u8 retrans;
+ u8 __pad;
+ /* The following two fields can be easily recomputed I think -AK */
+ u32 window_clamp; /* window clamp at creation time */
+ u32 rcv_wnd; /* rcv_wnd offered first time */
+ u32 ts_recent;
+ unsigned long expires;
+ struct request_sock_ops *rsk_ops;
+ struct sock *sk;
+};
+
+static inline struct request_sock *reqsk_alloc(struct request_sock_ops *ops)
+{
+ struct request_sock *req = kmem_cache_alloc(ops->slab, SLAB_ATOMIC);
+
+ if (req != NULL)
+ req->rsk_ops = ops;
+
+ return req;
+}
+
+static inline void __reqsk_free(struct request_sock *req)
+{
+ kmem_cache_free(req->rsk_ops->slab, req);
+}
+
+static inline void reqsk_free(struct request_sock *req)
+{
+ req->rsk_ops->destructor(req);
+ __reqsk_free(req);
+}
+
+extern int sysctl_max_syn_backlog;
+
+/** struct listen_sock - listen state
+ *
+ * @max_qlen_log - log_2 of maximal queued SYNs/REQUESTs
+ */
+struct listen_sock {
+ u8 max_qlen_log;
+ /* 3 bytes hole, try to use */
+ int qlen;
+ int qlen_young;
+ int clock_hand;
+ u32 hash_rnd;
+ struct request_sock *syn_table[0];
+};
+
+/** struct request_sock_queue - queue of request_socks
+ *
+ * @rskq_accept_head - FIFO head of established children
+ * @rskq_accept_tail - FIFO tail of established children
+ * @syn_wait_lock - serializer
+ *
+ * %syn_wait_lock is necessary only to avoid proc interface having to grab the main
+ * lock sock while browsing the listening hash (otherwise it's deadlock prone).
+ *
+ * This lock is acquired in read mode only from listening_get_next() seq_file
+ * op and it's acquired in write mode _only_ from code that is actively
+ * changing rskq_accept_head. All readers that are holding the master sock lock
+ * don't need to grab this lock in read mode too as rskq_accept_head. writes
+ * are always protected from the main sock lock.
+ */
+struct request_sock_queue {
+ struct request_sock *rskq_accept_head;
+ struct request_sock *rskq_accept_tail;
+ rwlock_t syn_wait_lock;
+ struct listen_sock *listen_opt;
+};
+
+extern int reqsk_queue_alloc(struct request_sock_queue *queue,
+ const int nr_table_entries);
+
+static inline struct listen_sock *reqsk_queue_yank_listen_sk(struct request_sock_queue *queue)
+{
+ struct listen_sock *lopt;
+
+ write_lock_bh(&queue->syn_wait_lock);
+ lopt = queue->listen_opt;
+ queue->listen_opt = NULL;
+ write_unlock_bh(&queue->syn_wait_lock);
+
+ return lopt;
+}
+
+static inline void reqsk_queue_destroy(struct request_sock_queue *queue)
+{
+ kfree(reqsk_queue_yank_listen_sk(queue));
+}
+
+static inline struct request_sock *
+ reqsk_queue_yank_acceptq(struct request_sock_queue *queue)
+{
+ struct request_sock *req = queue->rskq_accept_head;
+
+ queue->rskq_accept_head = queue->rskq_accept_head = NULL;
+ return req;
+}
+
+static inline int reqsk_queue_empty(struct request_sock_queue *queue)
+{
+ return queue->rskq_accept_head == NULL;
+}
+
+static inline void reqsk_queue_unlink(struct request_sock_queue *queue,
+ struct request_sock *req,
+ struct request_sock **prev_req)
+{
+ write_lock(&queue->syn_wait_lock);
+ *prev_req = req->dl_next;
+ write_unlock(&queue->syn_wait_lock);
+}
+
+static inline void reqsk_queue_add(struct request_sock_queue *queue,
+ struct request_sock *req,
+ struct sock *parent,
+ struct sock *child)
+{
+ req->sk = child;
+ sk_acceptq_added(parent);
+
+ if (queue->rskq_accept_head == NULL)
+ queue->rskq_accept_head = req;
+ else
+ queue->rskq_accept_tail->dl_next = req;
+
+ queue->rskq_accept_tail = req;
+ req->dl_next = NULL;
+}
+
+static inline struct request_sock *reqsk_queue_remove(struct request_sock_queue *queue)
+{
+ struct request_sock *req = queue->rskq_accept_head;
+
+ BUG_TRAP(req != NULL);
+
+ queue->rskq_accept_head = req->dl_next;
+ if (queue->rskq_accept_head == NULL)
+ queue->rskq_accept_tail = NULL;
+
+ return req;
+}
+
+static inline struct sock *reqsk_queue_get_child(struct request_sock_queue *queue,
+ struct sock *parent)
+{
+ struct request_sock *req = reqsk_queue_remove(queue);
+ struct sock *child = req->sk;
+
+ BUG_TRAP(child != NULL);
+
+ sk_acceptq_removed(parent);
+ __reqsk_free(req);
+ return child;
+}
+
+static inline int reqsk_queue_removed(struct request_sock_queue *queue,
+ struct request_sock *req)
+{
+ struct listen_sock *lopt = queue->listen_opt;
+
+ if (req->retrans == 0)
+ --lopt->qlen_young;
+
+ return --lopt->qlen;
+}
+
+static inline int reqsk_queue_added(struct request_sock_queue *queue)
+{
+ struct listen_sock *lopt = queue->listen_opt;
+ const int prev_qlen = lopt->qlen;
+
+ lopt->qlen_young++;
+ lopt->qlen++;
+ return prev_qlen;
+}
+
+static inline int reqsk_queue_len(struct request_sock_queue *queue)
+{
+ return queue->listen_opt != NULL ? queue->listen_opt->qlen : 0;
+}
+
+static inline int reqsk_queue_len_young(struct request_sock_queue *queue)
+{
+ return queue->listen_opt->qlen_young;
+}
+
+static inline int reqsk_queue_is_full(struct request_sock_queue *queue)
+{
+ return queue->listen_opt->qlen >> queue->listen_opt->max_qlen_log;
+}
+
+static inline void reqsk_queue_hash_req(struct request_sock_queue *queue,
+ u32 hash, struct request_sock *req,
+ unsigned timeout)
+{
+ struct listen_sock *lopt = queue->listen_opt;
+
+ req->expires = jiffies + timeout;
+ req->retrans = 0;
+ req->sk = NULL;
+ req->dl_next = lopt->syn_table[hash];
+
+ write_lock(&queue->syn_wait_lock);
+ lopt->syn_table[hash] = req;
+ write_unlock(&queue->syn_wait_lock);
+}
+
+#endif /* _REQUEST_SOCK_H */
diff --git a/include/net/route.h b/include/net/route.h
index efe92b239ef..c3cd069a9ac 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -107,7 +107,7 @@ struct rt_cache_stat
extern struct rt_cache_stat *rt_cache_stat;
#define RT_CACHE_STAT_INC(field) \
- (per_cpu_ptr(rt_cache_stat, _smp_processor_id())->field++)
+ (per_cpu_ptr(rt_cache_stat, raw_smp_processor_id())->field++)
extern struct ip_rt_acct *ip_rt_acct;
@@ -181,9 +181,6 @@ static inline int ip_route_newports(struct rtable **rp, u16 sport, u16 dport,
memcpy(&fl, &(*rp)->fl, sizeof(fl));
fl.fl_ip_sport = sport;
fl.fl_ip_dport = dport;
-#if defined(CONFIG_IP_ROUTE_MULTIPATH_CACHED)
- fl.flags |= FLOWI_FLAG_MULTIPATHOLDROUTE;
-#endif
ip_rt_put(*rp);
*rp = NULL;
return ip_route_output_flow(rp, &fl, sk, 0);
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index c57504b3b51..7b97405e2db 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -172,4 +172,126 @@ tcf_destroy(struct tcf_proto *tp)
kfree(tp);
}
+static inline int __qdisc_enqueue_tail(struct sk_buff *skb, struct Qdisc *sch,
+ struct sk_buff_head *list)
+{
+ __skb_queue_tail(list, skb);
+ sch->qstats.backlog += skb->len;
+ sch->bstats.bytes += skb->len;
+ sch->bstats.packets++;
+
+ return NET_XMIT_SUCCESS;
+}
+
+static inline int qdisc_enqueue_tail(struct sk_buff *skb, struct Qdisc *sch)
+{
+ return __qdisc_enqueue_tail(skb, sch, &sch->q);
+}
+
+static inline struct sk_buff *__qdisc_dequeue_head(struct Qdisc *sch,
+ struct sk_buff_head *list)
+{
+ struct sk_buff *skb = __skb_dequeue(list);
+
+ if (likely(skb != NULL))
+ sch->qstats.backlog -= skb->len;
+
+ return skb;
+}
+
+static inline struct sk_buff *qdisc_dequeue_head(struct Qdisc *sch)
+{
+ return __qdisc_dequeue_head(sch, &sch->q);
+}
+
+static inline struct sk_buff *__qdisc_dequeue_tail(struct Qdisc *sch,
+ struct sk_buff_head *list)
+{
+ struct sk_buff *skb = __skb_dequeue_tail(list);
+
+ if (likely(skb != NULL))
+ sch->qstats.backlog -= skb->len;
+
+ return skb;
+}
+
+static inline struct sk_buff *qdisc_dequeue_tail(struct Qdisc *sch)
+{
+ return __qdisc_dequeue_tail(sch, &sch->q);
+}
+
+static inline int __qdisc_requeue(struct sk_buff *skb, struct Qdisc *sch,
+ struct sk_buff_head *list)
+{
+ __skb_queue_head(list, skb);
+ sch->qstats.backlog += skb->len;
+ sch->qstats.requeues++;
+
+ return NET_XMIT_SUCCESS;
+}
+
+static inline int qdisc_requeue(struct sk_buff *skb, struct Qdisc *sch)
+{
+ return __qdisc_requeue(skb, sch, &sch->q);
+}
+
+static inline void __qdisc_reset_queue(struct Qdisc *sch,
+ struct sk_buff_head *list)
+{
+ /*
+ * We do not know the backlog in bytes of this list, it
+ * is up to the caller to correct it
+ */
+ skb_queue_purge(list);
+}
+
+static inline void qdisc_reset_queue(struct Qdisc *sch)
+{
+ __qdisc_reset_queue(sch, &sch->q);
+ sch->qstats.backlog = 0;
+}
+
+static inline unsigned int __qdisc_queue_drop(struct Qdisc *sch,
+ struct sk_buff_head *list)
+{
+ struct sk_buff *skb = __qdisc_dequeue_tail(sch, list);
+
+ if (likely(skb != NULL)) {
+ unsigned int len = skb->len;
+ kfree_skb(skb);
+ return len;
+ }
+
+ return 0;
+}
+
+static inline unsigned int qdisc_queue_drop(struct Qdisc *sch)
+{
+ return __qdisc_queue_drop(sch, &sch->q);
+}
+
+static inline int qdisc_drop(struct sk_buff *skb, struct Qdisc *sch)
+{
+ kfree_skb(skb);
+ sch->qstats.drops++;
+
+ return NET_XMIT_DROP;
+}
+
+static inline int qdisc_reshape_fail(struct sk_buff *skb, struct Qdisc *sch)
+{
+ sch->qstats.drops++;
+
+#ifdef CONFIG_NET_CLS_POLICE
+ if (sch->reshape_fail == NULL || sch->reshape_fail(skb, sch))
+ goto drop;
+
+ return NET_XMIT_SUCCESS;
+
+drop:
+#endif
+ kfree_skb(skb);
+ return NET_XMIT_DROP;
+}
+
#endif
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
index ebc5282e6d5..dc107ffad48 100644
--- a/include/net/sctp/command.h
+++ b/include/net/sctp/command.h
@@ -65,9 +65,11 @@ typedef enum {
SCTP_CMD_TIMER_START, /* Start a timer. */
SCTP_CMD_TIMER_RESTART, /* Restart a timer. */
SCTP_CMD_TIMER_STOP, /* Stop a timer. */
- SCTP_CMD_COUNTER_RESET, /* Reset a counter. */
- SCTP_CMD_COUNTER_INC, /* Increment a counter. */
+ SCTP_CMD_INIT_CHOOSE_TRANSPORT, /* Choose transport for an INIT. */
+ SCTP_CMD_INIT_COUNTER_RESET, /* Reset init counter. */
+ SCTP_CMD_INIT_COUNTER_INC, /* Increment init counter. */
SCTP_CMD_INIT_RESTART, /* High level, do init timer work. */
+ SCTP_CMD_COOKIEECHO_RESTART, /* High level, do cookie-echo timer work. */
SCTP_CMD_INIT_FAILED, /* High level, do init failure work. */
SCTP_CMD_REPORT_DUP, /* Report a duplicate TSN. */
SCTP_CMD_STRIKE, /* Mark a strike against a transport. */
@@ -118,7 +120,6 @@ typedef union {
int error;
sctp_state_t state;
sctp_event_timeout_t to;
- sctp_counter_t counter;
void *ptr;
struct sctp_chunk *chunk;
struct sctp_association *asoc;
@@ -165,7 +166,6 @@ SCTP_ARG_CONSTRUCTOR(U16, __u16, u16)
SCTP_ARG_CONSTRUCTOR(U8, __u8, u8)
SCTP_ARG_CONSTRUCTOR(ERROR, int, error)
SCTP_ARG_CONSTRUCTOR(STATE, sctp_state_t, state)
-SCTP_ARG_CONSTRUCTOR(COUNTER, sctp_counter_t, counter)
SCTP_ARG_CONSTRUCTOR(TO, sctp_event_timeout_t, to)
SCTP_ARG_CONSTRUCTOR(PTR, void *, ptr)
SCTP_ARG_CONSTRUCTOR(CHUNK, struct sctp_chunk *, chunk)
diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h
index 2b76c0f4bab..4868c7f7749 100644
--- a/include/net/sctp/constants.h
+++ b/include/net/sctp/constants.h
@@ -263,13 +263,6 @@ enum { SCTP_MIN_PMTU = 576 };
enum { SCTP_MAX_DUP_TSNS = 16 };
enum { SCTP_MAX_GABS = 16 };
-typedef enum {
- SCTP_COUNTER_INIT_ERROR,
-} sctp_counter_t;
-
-/* How many counters does an association need? */
-#define SCTP_NUMBER_COUNTERS 5
-
/* Here we define the default timers. */
/* cookie timer def = ? seconds */
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 960abfa48d6..ef2738159ab 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -223,6 +223,22 @@ DECLARE_SNMP_STAT(struct sctp_mib, sctp_statistics);
extern int sctp_debug_flag;
#define SCTP_DEBUG_PRINTK(whatever...) \
((void) (sctp_debug_flag && printk(KERN_DEBUG whatever)))
+#define SCTP_DEBUG_PRINTK_IPADDR(lead, trail, leadparm, saddr, otherparms...) \
+ if (sctp_debug_flag) { \
+ if (saddr->sa.sa_family == AF_INET6) { \
+ printk(KERN_DEBUG \
+ lead "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x" trail, \
+ leadparm, \
+ NIP6(saddr->v6.sin6_addr), \
+ otherparms); \
+ } else { \
+ printk(KERN_DEBUG \
+ lead "%u.%u.%u.%u" trail, \
+ leadparm, \
+ NIPQUAD(saddr->v4.sin_addr.s_addr), \
+ otherparms); \
+ } \
+ }
#define SCTP_ENABLE_DEBUG { sctp_debug_flag = 1; }
#define SCTP_DISABLE_DEBUG { sctp_debug_flag = 0; }
@@ -236,6 +252,7 @@ extern int sctp_debug_flag;
#else /* SCTP_DEBUG */
#define SCTP_DEBUG_PRINTK(whatever...)
+#define SCTP_DEBUG_PRINTK_IPADDR(whatever...)
#define SCTP_ENABLE_DEBUG
#define SCTP_DISABLE_DEBUG
#define SCTP_ASSERT(expr, str, func)
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index f4fcee10470..88d9fe5975d 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -116,7 +116,8 @@ sctp_state_fn_t sctp_sf_eat_data_fast_4_4;
sctp_state_fn_t sctp_sf_eat_sack_6_2;
sctp_state_fn_t sctp_sf_tabort_8_4_8;
sctp_state_fn_t sctp_sf_operr_notify;
-sctp_state_fn_t sctp_sf_t1_timer_expire;
+sctp_state_fn_t sctp_sf_t1_init_timer_expire;
+sctp_state_fn_t sctp_sf_t1_cookie_timer_expire;
sctp_state_fn_t sctp_sf_t2_timer_expire;
sctp_state_fn_t sctp_sf_t4_timer_expire;
sctp_state_fn_t sctp_sf_t5_timer_expire;
@@ -130,7 +131,6 @@ sctp_state_fn_t sctp_sf_do_ecne;
sctp_state_fn_t sctp_sf_ootb;
sctp_state_fn_t sctp_sf_pdiscard;
sctp_state_fn_t sctp_sf_violation;
-sctp_state_fn_t sctp_sf_violation_chunklen;
sctp_state_fn_t sctp_sf_discard_chunk;
sctp_state_fn_t sctp_sf_do_5_2_1_siminit;
sctp_state_fn_t sctp_sf_do_5_2_2_dupinit;
@@ -258,8 +258,6 @@ struct sctp_chunk *sctp_make_fwdtsn(const struct sctp_association *asoc,
void sctp_chunk_assign_tsn(struct sctp_chunk *);
void sctp_chunk_assign_ssn(struct sctp_chunk *);
-void sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, __u16 error);
-
/* Prototypes for statetable processing. */
int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype,
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 6c24d9cd3d6..dfad4d3c581 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -867,10 +867,13 @@ struct sctp_transport {
*/
unsigned long last_time_ecne_reduced;
- /* active : The current active state of this destination,
- * : i.e. DOWN, UP, etc.
+ /* The number of times INIT has been sent on this transport. */
+ int init_sent_count;
+
+ /* state : The current state of this destination,
+ * : i.e. SCTP_ACTIVE, SCTP_INACTIVE, SCTP_UNKOWN.
*/
- int active;
+ int state;
/* hb_allowed : The current heartbeat state of this destination,
* : i.e. ALLOW-HB, NO-HEARTBEAT, etc.
@@ -1222,9 +1225,6 @@ struct sctp_endpoint {
/* sendbuf acct. policy. */
__u32 sndbuf_policy;
-
- /* Name for debugging output... */
- char *debug_name;
};
/* Recover the outter endpoint structure. */
@@ -1314,11 +1314,23 @@ struct sctp_association {
* : association. Normally this information is
* : hashed or keyed for quick lookup and access
* : of the TCB.
+ * : The list is also initialized with the list
+ * : of addresses passed with the sctp_connectx()
+ * : call.
*
* It is a list of SCTP_transport's.
*/
struct list_head transport_addr_list;
+ /* transport_count
+ *
+ * Peer : A count of the number of peer addresses
+ * Transport : in the Peer Transport Address List.
+ * Address :
+ * Count :
+ */
+ __u16 transport_count;
+
/* port
* The transport layer port number.
*/
@@ -1486,6 +1498,9 @@ struct sctp_association {
/* Transport to which SHUTDOWN chunk was last sent. */
struct sctp_transport *shutdown_last_sent_to;
+ /* Transport to which INIT chunk was last sent. */
+ struct sctp_transport *init_last_sent_to;
+
/* Next TSN : The next TSN number to be assigned to a new
* : DATA chunk. This is sent in the INIT or INIT
* : ACK chunk to the peer and incremented each
@@ -1549,8 +1564,11 @@ struct sctp_association {
/* The message size at which SCTP fragmentation will occur. */
__u32 frag_point;
- /* Currently only one counter is used to count INIT errors. */
- int counters[SCTP_NUMBER_COUNTERS];
+ /* Counter used to count INIT errors. */
+ int init_err_counter;
+
+ /* Count the number of INIT cycles (for doubling timeout). */
+ int init_cycle;
/* Default send parameters. */
__u16 default_stream;
@@ -1708,6 +1726,8 @@ void sctp_association_free(struct sctp_association *);
void sctp_association_put(struct sctp_association *);
void sctp_association_hold(struct sctp_association *);
+struct sctp_transport *sctp_assoc_choose_init_transport(
+ struct sctp_association *);
struct sctp_transport *sctp_assoc_choose_shutdown_transport(
struct sctp_association *);
void sctp_assoc_update_retran_path(struct sctp_association *);
@@ -1717,9 +1737,12 @@ int sctp_assoc_lookup_laddr(struct sctp_association *asoc,
const union sctp_addr *laddr);
struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *,
const union sctp_addr *address,
- const int gfp);
+ const int gfp,
+ const int peer_state);
void sctp_assoc_del_peer(struct sctp_association *asoc,
const union sctp_addr *addr);
+void sctp_assoc_rm_peer(struct sctp_association *asoc,
+ struct sctp_transport *peer);
void sctp_assoc_control_transport(struct sctp_association *,
struct sctp_transport *,
sctp_transport_cmd_t, sctp_sn_error_t);
diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h
index 2758e8ce4f2..f6328aeddcc 100644
--- a/include/net/sctp/user.h
+++ b/include/net/sctp/user.h
@@ -111,6 +111,8 @@ enum sctp_optname {
#define SCTP_GET_LOCAL_ADDRS_NUM SCTP_GET_LOCAL_ADDRS_NUM
SCTP_GET_LOCAL_ADDRS, /* Get all local addresss. */
#define SCTP_GET_LOCAL_ADDRS SCTP_GET_LOCAL_ADDRS
+ SCTP_SOCKOPT_CONNECTX, /* CONNECTX requests. */
+#define SCTP_SOCKOPT_CONNECTX SCTP_SOCKOPT_CONNECTX
};
/*
@@ -527,6 +529,7 @@ struct sctp_paddrinfo {
enum sctp_spinfo_state {
SCTP_INACTIVE,
SCTP_ACTIVE,
+ SCTP_UNKNOWN = 0xffff /* Value used for transport state unknown */
};
/*
diff --git a/include/net/snmp.h b/include/net/snmp.h
index a15ab256276..a36bed8ea21 100644
--- a/include/net/snmp.h
+++ b/include/net/snmp.h
@@ -128,18 +128,18 @@ struct linux_mib {
#define SNMP_STAT_USRPTR(name) (name[1])
#define SNMP_INC_STATS_BH(mib, field) \
- (per_cpu_ptr(mib[0], _smp_processor_id())->mibs[field]++)
+ (per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field]++)
#define SNMP_INC_STATS_OFFSET_BH(mib, field, offset) \
- (per_cpu_ptr(mib[0], _smp_processor_id())->mibs[field + (offset)]++)
+ (per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field + (offset)]++)
#define SNMP_INC_STATS_USER(mib, field) \
- (per_cpu_ptr(mib[1], _smp_processor_id())->mibs[field]++)
+ (per_cpu_ptr(mib[1], raw_smp_processor_id())->mibs[field]++)
#define SNMP_INC_STATS(mib, field) \
- (per_cpu_ptr(mib[!in_softirq()], _smp_processor_id())->mibs[field]++)
+ (per_cpu_ptr(mib[!in_softirq()], raw_smp_processor_id())->mibs[field]++)
#define SNMP_DEC_STATS(mib, field) \
- (per_cpu_ptr(mib[!in_softirq()], _smp_processor_id())->mibs[field]--)
+ (per_cpu_ptr(mib[!in_softirq()], raw_smp_processor_id())->mibs[field]--)
#define SNMP_ADD_STATS_BH(mib, field, addend) \
- (per_cpu_ptr(mib[0], _smp_processor_id())->mibs[field] += addend)
+ (per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field] += addend)
#define SNMP_ADD_STATS_USER(mib, field, addend) \
- (per_cpu_ptr(mib[1], _smp_processor_id())->mibs[field] += addend)
+ (per_cpu_ptr(mib[1], raw_smp_processor_id())->mibs[field] += addend)
#endif
diff --git a/include/net/sock.h b/include/net/sock.h
index a9ef3a6a13f..e593af5b1ec 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -484,6 +484,8 @@ extern void sk_stream_kill_queues(struct sock *sk);
extern int sk_wait_data(struct sock *sk, long *timeo);
+struct request_sock_ops;
+
/* Networking protocol blocks we attach to sockets.
* socket layer -> transport layer interface
* transport -> network interface is defined by struct inet_proto
@@ -547,6 +549,8 @@ struct proto {
kmem_cache_t *slab;
unsigned int obj_size;
+ struct request_sock_ops *rsk_prot;
+
struct module *owner;
char name[32];
diff --git a/include/net/tcp.h b/include/net/tcp.h
index e71f8ba3e10..ec9e20c2717 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -31,6 +31,7 @@
#include <linux/cache.h>
#include <linux/percpu.h>
#include <net/checksum.h>
+#include <net/request_sock.h>
#include <net/sock.h>
#include <net/snmp.h>
#include <net/ip.h>
@@ -504,25 +505,6 @@ static __inline__ int tcp_sk_listen_hashfn(struct sock *sk)
#else
# define TCP_TW_RECYCLE_TICK (12+2-TCP_TW_RECYCLE_SLOTS_LOG)
#endif
-
-#define BICTCP_BETA_SCALE 1024 /* Scale factor beta calculation
- * max_cwnd = snd_cwnd * beta
- */
-#define BICTCP_MAX_INCREMENT 32 /*
- * Limit on the amount of
- * increment allowed during
- * binary search.
- */
-#define BICTCP_FUNC_OF_MIN_INCR 11 /*
- * log(B/Smin)/log(B/(B-1))+1,
- * Smin:min increment
- * B:log factor
- */
-#define BICTCP_B 4 /*
- * In binary search,
- * go to point (max+min)/N
- */
-
/*
* TCP option
*/
@@ -563,7 +545,6 @@ static __inline__ int tcp_sk_listen_hashfn(struct sock *sk)
#define TCP_NAGLE_PUSH 4 /* Cork is overriden for already queued data */
/* sysctl variables for tcp */
-extern int sysctl_max_syn_backlog;
extern int sysctl_tcp_timestamps;
extern int sysctl_tcp_window_scaling;
extern int sysctl_tcp_sack;
@@ -596,16 +577,7 @@ extern int sysctl_tcp_adv_win_scale;
extern int sysctl_tcp_tw_reuse;
extern int sysctl_tcp_frto;
extern int sysctl_tcp_low_latency;
-extern int sysctl_tcp_westwood;
-extern int sysctl_tcp_vegas_cong_avoid;
-extern int sysctl_tcp_vegas_alpha;
-extern int sysctl_tcp_vegas_beta;
-extern int sysctl_tcp_vegas_gamma;
extern int sysctl_tcp_nometrics_save;
-extern int sysctl_tcp_bic;
-extern int sysctl_tcp_bic_fast_convergence;
-extern int sysctl_tcp_bic_low_window;
-extern int sysctl_tcp_bic_beta;
extern int sysctl_tcp_moderate_rcvbuf;
extern int sysctl_tcp_tso_win_divisor;
@@ -613,74 +585,6 @@ extern atomic_t tcp_memory_allocated;
extern atomic_t tcp_sockets_allocated;
extern int tcp_memory_pressure;
-struct open_request;
-
-struct or_calltable {
- int family;
- int (*rtx_syn_ack) (struct sock *sk, struct open_request *req, struct dst_entry*);
- void (*send_ack) (struct sk_buff *skb, struct open_request *req);
- void (*destructor) (struct open_request *req);
- void (*send_reset) (struct sk_buff *skb);
-};
-
-struct tcp_v4_open_req {
- __u32 loc_addr;
- __u32 rmt_addr;
- struct ip_options *opt;
-};
-
-#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-struct tcp_v6_open_req {
- struct in6_addr loc_addr;
- struct in6_addr rmt_addr;
- struct sk_buff *pktopts;
- int iif;
-};
-#endif
-
-/* this structure is too big */
-struct open_request {
- struct open_request *dl_next; /* Must be first member! */
- __u32 rcv_isn;
- __u32 snt_isn;
- __u16 rmt_port;
- __u16 mss;
- __u8 retrans;
- __u8 __pad;
- __u16 snd_wscale : 4,
- rcv_wscale : 4,
- tstamp_ok : 1,
- sack_ok : 1,
- wscale_ok : 1,
- ecn_ok : 1,
- acked : 1;
- /* The following two fields can be easily recomputed I think -AK */
- __u32 window_clamp; /* window clamp at creation time */
- __u32 rcv_wnd; /* rcv_wnd offered first time */
- __u32 ts_recent;
- unsigned long expires;
- struct or_calltable *class;
- struct sock *sk;
- union {
- struct tcp_v4_open_req v4_req;
-#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
- struct tcp_v6_open_req v6_req;
-#endif
- } af;
-};
-
-/* SLAB cache for open requests. */
-extern kmem_cache_t *tcp_openreq_cachep;
-
-#define tcp_openreq_alloc() kmem_cache_alloc(tcp_openreq_cachep, SLAB_ATOMIC)
-#define tcp_openreq_fastfree(req) kmem_cache_free(tcp_openreq_cachep, req)
-
-static inline void tcp_openreq_free(struct open_request *req)
-{
- req->class->destructor(req);
- tcp_openreq_fastfree(req);
-}
-
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
#define TCP_INET_FAMILY(fam) ((fam) == AF_INET)
#else
@@ -708,7 +612,7 @@ struct tcp_func {
struct sock * (*syn_recv_sock) (struct sock *sk,
struct sk_buff *skb,
- struct open_request *req,
+ struct request_sock *req,
struct dst_entry *dst);
int (*remember_stamp) (struct sock *sk);
@@ -852,8 +756,8 @@ extern enum tcp_tw_status tcp_timewait_state_process(struct tcp_tw_bucket *tw,
unsigned len);
extern struct sock * tcp_check_req(struct sock *sk,struct sk_buff *skb,
- struct open_request *req,
- struct open_request **prev);
+ struct request_sock *req,
+ struct request_sock **prev);
extern int tcp_child_process(struct sock *parent,
struct sock *child,
struct sk_buff *skb);
@@ -903,12 +807,12 @@ extern int tcp_v4_conn_request(struct sock *sk,
struct sk_buff *skb);
extern struct sock * tcp_create_openreq_child(struct sock *sk,
- struct open_request *req,
+ struct request_sock *req,
struct sk_buff *skb);
extern struct sock * tcp_v4_syn_recv_sock(struct sock *sk,
struct sk_buff *skb,
- struct open_request *req,
+ struct request_sock *req,
struct dst_entry *dst);
extern int tcp_v4_do_rcv(struct sock *sk,
@@ -922,7 +826,7 @@ extern int tcp_connect(struct sock *sk);
extern struct sk_buff * tcp_make_synack(struct sock *sk,
struct dst_entry *dst,
- struct open_request *req);
+ struct request_sock *req);
extern int tcp_disconnect(struct sock *sk, int flags);
@@ -1204,6 +1108,82 @@ static inline void tcp_packets_out_dec(struct tcp_sock *tp,
tp->packets_out -= tcp_skb_pcount(skb);
}
+/* Events passed to congestion control interface */
+enum tcp_ca_event {
+ CA_EVENT_TX_START, /* first transmit when no packets in flight */
+ CA_EVENT_CWND_RESTART, /* congestion window restart */
+ CA_EVENT_COMPLETE_CWR, /* end of congestion recovery */
+ CA_EVENT_FRTO, /* fast recovery timeout */
+ CA_EVENT_LOSS, /* loss timeout */
+ CA_EVENT_FAST_ACK, /* in sequence ack */
+ CA_EVENT_SLOW_ACK, /* other ack */
+};
+
+/*
+ * Interface for adding new TCP congestion control handlers
+ */
+#define TCP_CA_NAME_MAX 16
+struct tcp_congestion_ops {
+ struct list_head list;
+
+ /* initialize private data (optional) */
+ void (*init)(struct tcp_sock *tp);
+ /* cleanup private data (optional) */
+ void (*release)(struct tcp_sock *tp);
+
+ /* return slow start threshold (required) */
+ u32 (*ssthresh)(struct tcp_sock *tp);
+ /* lower bound for congestion window (optional) */
+ u32 (*min_cwnd)(struct tcp_sock *tp);
+ /* do new cwnd calculation (required) */
+ void (*cong_avoid)(struct tcp_sock *tp, u32 ack,
+ u32 rtt, u32 in_flight, int good_ack);
+ /* round trip time sample per acked packet (optional) */
+ void (*rtt_sample)(struct tcp_sock *tp, u32 usrtt);
+ /* call before changing ca_state (optional) */
+ void (*set_state)(struct tcp_sock *tp, u8 new_state);
+ /* call when cwnd event occurs (optional) */
+ void (*cwnd_event)(struct tcp_sock *tp, enum tcp_ca_event ev);
+ /* new value of cwnd after loss (optional) */
+ u32 (*undo_cwnd)(struct tcp_sock *tp);
+ /* hook for packet ack accounting (optional) */
+ void (*pkts_acked)(struct tcp_sock *tp, u32 num_acked);
+ /* get info for tcp_diag (optional) */
+ void (*get_info)(struct tcp_sock *tp, u32 ext, struct sk_buff *skb);
+
+ char name[TCP_CA_NAME_MAX];
+ struct module *owner;
+};
+
+extern int tcp_register_congestion_control(struct tcp_congestion_ops *type);
+extern void tcp_unregister_congestion_control(struct tcp_congestion_ops *type);
+
+extern void tcp_init_congestion_control(struct tcp_sock *tp);
+extern void tcp_cleanup_congestion_control(struct tcp_sock *tp);
+extern int tcp_set_default_congestion_control(const char *name);
+extern void tcp_get_default_congestion_control(char *name);
+extern int tcp_set_congestion_control(struct tcp_sock *tp, const char *name);
+
+extern struct tcp_congestion_ops tcp_init_congestion_ops;
+extern u32 tcp_reno_ssthresh(struct tcp_sock *tp);
+extern void tcp_reno_cong_avoid(struct tcp_sock *tp, u32 ack,
+ u32 rtt, u32 in_flight, int flag);
+extern u32 tcp_reno_min_cwnd(struct tcp_sock *tp);
+extern struct tcp_congestion_ops tcp_reno;
+
+static inline void tcp_set_ca_state(struct tcp_sock *tp, u8 ca_state)
+{
+ if (tp->ca_ops->set_state)
+ tp->ca_ops->set_state(tp, ca_state);
+ tp->ca_state = ca_state;
+}
+
+static inline void tcp_ca_event(struct tcp_sock *tp, enum tcp_ca_event event)
+{
+ if (tp->ca_ops->cwnd_event)
+ tp->ca_ops->cwnd_event(tp, event);
+}
+
/* This determines how many packets are "in the network" to the best
* of our knowledge. In many cases it is conservative, but where
* detailed information is available from the receiver (via SACK
@@ -1223,91 +1203,6 @@ static __inline__ unsigned int tcp_packets_in_flight(const struct tcp_sock *tp)
return (tp->packets_out - tp->left_out + tp->retrans_out);
}
-/*
- * Which congestion algorithim is in use on the connection.
- */
-#define tcp_is_vegas(__tp) ((__tp)->adv_cong == TCP_VEGAS)
-#define tcp_is_westwood(__tp) ((__tp)->adv_cong == TCP_WESTWOOD)
-#define tcp_is_bic(__tp) ((__tp)->adv_cong == TCP_BIC)
-
-/* Recalculate snd_ssthresh, we want to set it to:
- *
- * Reno:
- * one half the current congestion window, but no
- * less than two segments
- *
- * BIC:
- * behave like Reno until low_window is reached,
- * then increase congestion window slowly
- */
-static inline __u32 tcp_recalc_ssthresh(struct tcp_sock *tp)
-{
- if (tcp_is_bic(tp)) {
- if (sysctl_tcp_bic_fast_convergence &&
- tp->snd_cwnd < tp->bictcp.last_max_cwnd)
- tp->bictcp.last_max_cwnd = (tp->snd_cwnd *
- (BICTCP_BETA_SCALE
- + sysctl_tcp_bic_beta))
- / (2 * BICTCP_BETA_SCALE);
- else
- tp->bictcp.last_max_cwnd = tp->snd_cwnd;
-
- if (tp->snd_cwnd > sysctl_tcp_bic_low_window)
- return max((tp->snd_cwnd * sysctl_tcp_bic_beta)
- / BICTCP_BETA_SCALE, 2U);
- }
-
- return max(tp->snd_cwnd >> 1U, 2U);
-}
-
-/* Stop taking Vegas samples for now. */
-#define tcp_vegas_disable(__tp) ((__tp)->vegas.doing_vegas_now = 0)
-
-static inline void tcp_vegas_enable(struct tcp_sock *tp)
-{
- /* There are several situations when we must "re-start" Vegas:
- *
- * o when a connection is established
- * o after an RTO
- * o after fast recovery
- * o when we send a packet and there is no outstanding
- * unacknowledged data (restarting an idle connection)
- *
- * In these circumstances we cannot do a Vegas calculation at the
- * end of the first RTT, because any calculation we do is using
- * stale info -- both the saved cwnd and congestion feedback are
- * stale.
- *
- * Instead we must wait until the completion of an RTT during
- * which we actually receive ACKs.
- */
-
- /* Begin taking Vegas samples next time we send something. */
- tp->vegas.doing_vegas_now = 1;
-
- /* Set the beginning of the next send window. */
- tp->vegas.beg_snd_nxt = tp->snd_nxt;
-
- tp->vegas.cntRTT = 0;
- tp->vegas.minRTT = 0x7fffffff;
-}
-
-/* Should we be taking Vegas samples right now? */
-#define tcp_vegas_enabled(__tp) ((__tp)->vegas.doing_vegas_now)
-
-extern void tcp_ca_init(struct tcp_sock *tp);
-
-static inline void tcp_set_ca_state(struct tcp_sock *tp, u8 ca_state)
-{
- if (tcp_is_vegas(tp)) {
- if (ca_state == TCP_CA_Open)
- tcp_vegas_enable(tp);
- else
- tcp_vegas_disable(tp);
- }
- tp->ca_state = ca_state;
-}
-
/* If cwnd > ssthresh, we may raise ssthresh to be half-way to cwnd.
* The exception is rate halving phase, when cwnd is decreasing towards
* ssthresh.
@@ -1356,7 +1251,7 @@ static inline void tcp_cwnd_validate(struct sock *sk, struct tcp_sock *tp)
static inline void __tcp_enter_cwr(struct tcp_sock *tp)
{
tp->undo_marker = 0;
- tp->snd_ssthresh = tcp_recalc_ssthresh(tp);
+ tp->snd_ssthresh = tp->ca_ops->ssthresh(tp);
tp->snd_cwnd = min(tp->snd_cwnd,
tcp_packets_in_flight(tp) + 1U);
tp->snd_cwnd_cnt = 0;
@@ -1750,99 +1645,71 @@ static inline int tcp_full_space(const struct sock *sk)
return tcp_win_from_space(sk->sk_rcvbuf);
}
-static inline void tcp_acceptq_queue(struct sock *sk, struct open_request *req,
+static inline void tcp_acceptq_queue(struct sock *sk, struct request_sock *req,
struct sock *child)
{
- struct tcp_sock *tp = tcp_sk(sk);
-
- req->sk = child;
- sk_acceptq_added(sk);
-
- if (!tp->accept_queue_tail) {
- tp->accept_queue = req;
- } else {
- tp->accept_queue_tail->dl_next = req;
- }
- tp->accept_queue_tail = req;
- req->dl_next = NULL;
+ reqsk_queue_add(&tcp_sk(sk)->accept_queue, req, sk, child);
}
-struct tcp_listen_opt
-{
- u8 max_qlen_log; /* log_2 of maximal queued SYNs */
- int qlen;
- int qlen_young;
- int clock_hand;
- u32 hash_rnd;
- struct open_request *syn_table[TCP_SYNQ_HSIZE];
-};
-
static inline void
-tcp_synq_removed(struct sock *sk, struct open_request *req)
+tcp_synq_removed(struct sock *sk, struct request_sock *req)
{
- struct tcp_listen_opt *lopt = tcp_sk(sk)->listen_opt;
-
- if (--lopt->qlen == 0)
+ if (reqsk_queue_removed(&tcp_sk(sk)->accept_queue, req) == 0)
tcp_delete_keepalive_timer(sk);
- if (req->retrans == 0)
- lopt->qlen_young--;
}
static inline void tcp_synq_added(struct sock *sk)
{
- struct tcp_listen_opt *lopt = tcp_sk(sk)->listen_opt;
-
- if (lopt->qlen++ == 0)
+ if (reqsk_queue_added(&tcp_sk(sk)->accept_queue) == 0)
tcp_reset_keepalive_timer(sk, TCP_TIMEOUT_INIT);
- lopt->qlen_young++;
}
static inline int tcp_synq_len(struct sock *sk)
{
- return tcp_sk(sk)->listen_opt->qlen;
+ return reqsk_queue_len(&tcp_sk(sk)->accept_queue);
}
static inline int tcp_synq_young(struct sock *sk)
{
- return tcp_sk(sk)->listen_opt->qlen_young;
+ return reqsk_queue_len_young(&tcp_sk(sk)->accept_queue);
}
static inline int tcp_synq_is_full(struct sock *sk)
{
- return tcp_synq_len(sk) >> tcp_sk(sk)->listen_opt->max_qlen_log;
+ return reqsk_queue_is_full(&tcp_sk(sk)->accept_queue);
}
-static inline void tcp_synq_unlink(struct tcp_sock *tp, struct open_request *req,
- struct open_request **prev)
+static inline void tcp_synq_unlink(struct tcp_sock *tp, struct request_sock *req,
+ struct request_sock **prev)
{
- write_lock(&tp->syn_wait_lock);
- *prev = req->dl_next;
- write_unlock(&tp->syn_wait_lock);
+ reqsk_queue_unlink(&tp->accept_queue, req, prev);
}
-static inline void tcp_synq_drop(struct sock *sk, struct open_request *req,
- struct open_request **prev)
+static inline void tcp_synq_drop(struct sock *sk, struct request_sock *req,
+ struct request_sock **prev)
{
tcp_synq_unlink(tcp_sk(sk), req, prev);
tcp_synq_removed(sk, req);
- tcp_openreq_free(req);
+ reqsk_free(req);
}
-static __inline__ void tcp_openreq_init(struct open_request *req,
+static __inline__ void tcp_openreq_init(struct request_sock *req,
struct tcp_options_received *rx_opt,
struct sk_buff *skb)
{
+ struct inet_request_sock *ireq = inet_rsk(req);
+
req->rcv_wnd = 0; /* So that tcp_send_synack() knows! */
- req->rcv_isn = TCP_SKB_CB(skb)->seq;
+ tcp_rsk(req)->rcv_isn = TCP_SKB_CB(skb)->seq;
req->mss = rx_opt->mss_clamp;
req->ts_recent = rx_opt->saw_tstamp ? rx_opt->rcv_tsval : 0;
- req->tstamp_ok = rx_opt->tstamp_ok;
- req->sack_ok = rx_opt->sack_ok;
- req->snd_wscale = rx_opt->snd_wscale;
- req->wscale_ok = rx_opt->wscale_ok;
- req->acked = 0;
- req->ecn_ok = 0;
- req->rmt_port = skb->h.th->source;
+ ireq->tstamp_ok = rx_opt->tstamp_ok;
+ ireq->sack_ok = rx_opt->sack_ok;
+ ireq->snd_wscale = rx_opt->snd_wscale;
+ ireq->wscale_ok = rx_opt->wscale_ok;
+ ireq->acked = 0;
+ ireq->ecn_ok = 0;
+ ireq->rmt_port = skb->h.th->source;
}
extern void tcp_enter_memory_pressure(void);
@@ -1972,52 +1839,4 @@ struct tcp_iter_state {
extern int tcp_proc_register(struct tcp_seq_afinfo *afinfo);
extern void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo);
-/* TCP Westwood functions and constants */
-
-#define TCP_WESTWOOD_INIT_RTT (20*HZ) /* maybe too conservative?! */
-#define TCP_WESTWOOD_RTT_MIN (HZ/20) /* 50ms */
-
-static inline void tcp_westwood_update_rtt(struct tcp_sock *tp, __u32 rtt_seq)
-{
- if (tcp_is_westwood(tp))
- tp->westwood.rtt = rtt_seq;
-}
-
-static inline __u32 __tcp_westwood_bw_rttmin(const struct tcp_sock *tp)
-{
- return max((tp->westwood.bw_est) * (tp->westwood.rtt_min) /
- (__u32) (tp->mss_cache_std),
- 2U);
-}
-
-static inline __u32 tcp_westwood_bw_rttmin(const struct tcp_sock *tp)
-{
- return tcp_is_westwood(tp) ? __tcp_westwood_bw_rttmin(tp) : 0;
-}
-
-static inline int tcp_westwood_ssthresh(struct tcp_sock *tp)
-{
- __u32 ssthresh = 0;
-
- if (tcp_is_westwood(tp)) {
- ssthresh = __tcp_westwood_bw_rttmin(tp);
- if (ssthresh)
- tp->snd_ssthresh = ssthresh;
- }
-
- return (ssthresh != 0);
-}
-
-static inline int tcp_westwood_cwnd(struct tcp_sock *tp)
-{
- __u32 cwnd = 0;
-
- if (tcp_is_westwood(tp)) {
- cwnd = __tcp_westwood_bw_rttmin(tp);
- if (cwnd)
- tp->snd_cwnd = cwnd;
- }
-
- return (cwnd != 0);
-}
#endif /* _TCP_H */
diff --git a/include/net/tcp_ecn.h b/include/net/tcp_ecn.h
index dc1456389a9..64980ee8c92 100644
--- a/include/net/tcp_ecn.h
+++ b/include/net/tcp_ecn.h
@@ -2,6 +2,7 @@
#define _NET_TCP_ECN_H_ 1
#include <net/inet_ecn.h>
+#include <net/request_sock.h>
#define TCP_HP_BITS (~(TCP_RESERVED_BITS|TCP_FLAG_PSH))
@@ -38,9 +39,9 @@ static inline void TCP_ECN_send_syn(struct sock *sk, struct tcp_sock *tp,
}
static __inline__ void
-TCP_ECN_make_synack(struct open_request *req, struct tcphdr *th)
+TCP_ECN_make_synack(struct request_sock *req, struct tcphdr *th)
{
- if (req->ecn_ok)
+ if (inet_rsk(req)->ecn_ok)
th->ece = 1;
}
@@ -111,16 +112,16 @@ static inline int TCP_ECN_rcv_ecn_echo(struct tcp_sock *tp, struct tcphdr *th)
}
static inline void TCP_ECN_openreq_child(struct tcp_sock *tp,
- struct open_request *req)
+ struct request_sock *req)
{
- tp->ecn_flags = req->ecn_ok ? TCP_ECN_OK : 0;
+ tp->ecn_flags = inet_rsk(req)->ecn_ok ? TCP_ECN_OK : 0;
}
static __inline__ void
-TCP_ECN_create_request(struct open_request *req, struct tcphdr *th)
+TCP_ECN_create_request(struct request_sock *req, struct tcphdr *th)
{
if (sysctl_tcp_ecn && th->ece && th->cwr)
- req->ecn_ok = 1;
+ inet_rsk(req)->ecn_ok = 1;
}
#endif
diff --git a/include/net/x25.h b/include/net/x25.h
index 7a1ba5bbb86..8b39b98876e 100644
--- a/include/net/x25.h
+++ b/include/net/x25.h
@@ -79,6 +79,8 @@ enum {
#define X25_DEFAULT_PACKET_SIZE X25_PS128 /* Default Packet Size */
#define X25_DEFAULT_THROUGHPUT 0x0A /* Deafult Throughput */
#define X25_DEFAULT_REVERSE 0x00 /* Default Reverse Charging */
+#define X25_DENY_ACCPT_APPRV 0x01 /* Default value */
+#define X25_ALLOW_ACCPT_APPRV 0x00 /* Control enabled */
#define X25_SMODULUS 8
#define X25_EMODULUS 128
@@ -94,7 +96,7 @@ enum {
#define X25_FAC_CLASS_C 0x80
#define X25_FAC_CLASS_D 0xC0
-#define X25_FAC_REVERSE 0x01
+#define X25_FAC_REVERSE 0x01 /* also fast select */
#define X25_FAC_THROUGHPUT 0x02
#define X25_FAC_PACKET_SIZE 0x42
#define X25_FAC_WINDOW_SIZE 0x43
@@ -134,8 +136,8 @@ struct x25_sock {
struct sock sk;
struct x25_address source_addr, dest_addr;
struct x25_neigh *neighbour;
- unsigned int lci;
- unsigned char state, condition, qbitincl, intflag;
+ unsigned int lci, cudmatchlength;
+ unsigned char state, condition, qbitincl, intflag, accptapprv;
unsigned short vs, vr, va, vl;
unsigned long t2, t21, t22, t23;
unsigned short fraglen;
@@ -242,7 +244,6 @@ extern int x25_validate_nr(struct sock *, unsigned short);
extern void x25_write_internal(struct sock *, int);
extern int x25_decode(struct sock *, struct sk_buff *, int *, int *, int *, int *, int *);
extern void x25_disconnect(struct sock *, int, unsigned char, unsigned char);
-extern int x25_check_calluserdata(struct x25_calluserdata *,struct x25_calluserdata *);
/* x25_timer.c */
extern void x25_start_heartbeat(struct sock *);
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index e142a256d5d..029522a4ced 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -158,6 +158,20 @@ enum {
XFRM_STATE_DEAD
};
+/* callback structure passed from either netlink or pfkey */
+struct km_event
+{
+ union {
+ u32 hard;
+ u32 proto;
+ u32 byid;
+ } data;
+
+ u32 seq;
+ u32 pid;
+ u32 event;
+};
+
struct xfrm_type;
struct xfrm_dst;
struct xfrm_policy_afinfo {
@@ -179,6 +193,8 @@ struct xfrm_policy_afinfo {
extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo);
extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo);
+extern void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c);
+extern void km_state_notify(struct xfrm_state *x, struct km_event *c);
#define XFRM_ACQ_EXPIRES 30
@@ -188,6 +204,7 @@ struct xfrm_state_afinfo {
rwlock_t lock;
struct list_head *state_bydst;
struct list_head *state_byspi;
+ int (*init_flags)(struct xfrm_state *x);
void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl,
struct xfrm_tmpl *tmpl,
xfrm_address_t *daddr, xfrm_address_t *saddr);
@@ -209,7 +226,7 @@ struct xfrm_type
struct module *owner;
__u8 proto;
- int (*init_state)(struct xfrm_state *x, void *args);
+ int (*init_state)(struct xfrm_state *x);
void (*destructor)(struct xfrm_state *);
int (*input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb);
int (*post_input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb);
@@ -290,11 +307,11 @@ struct xfrm_mgr
{
struct list_head list;
char *id;
- int (*notify)(struct xfrm_state *x, int event);
+ int (*notify)(struct xfrm_state *x, struct km_event *c);
int (*acquire)(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp, int dir);
struct xfrm_policy *(*compile_policy)(u16 family, int opt, u8 *data, int len, int *dir);
int (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport);
- int (*notify_policy)(struct xfrm_policy *x, int dir, int event);
+ int (*notify_policy)(struct xfrm_policy *x, int dir, struct km_event *c);
};
extern int xfrm_register_km(struct xfrm_mgr *km);
@@ -515,6 +532,8 @@ struct xfrm_dst
struct dst_entry *route;
u32 route_mtu_cached;
u32 child_mtu_cached;
+ u32 route_cookie;
+ u32 path_cookie;
};
static inline void xfrm_dst_destroy(struct xfrm_dst *xdst)
@@ -654,7 +673,7 @@ static inline int xfrm_sk_clone_policy(struct sock *sk)
return 0;
}
-extern void xfrm_policy_delete(struct xfrm_policy *pol, int dir);
+extern int xfrm_policy_delete(struct xfrm_policy *pol, int dir);
static inline void xfrm_sk_free_policy(struct sock *sk)
{
@@ -815,12 +834,13 @@ extern int xfrm_state_add(struct xfrm_state *x);
extern int xfrm_state_update(struct xfrm_state *x);
extern struct xfrm_state *xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family);
extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
-extern void xfrm_state_delete(struct xfrm_state *x);
+extern int xfrm_state_delete(struct xfrm_state *x);
extern void xfrm_state_flush(u8 proto);
extern int xfrm_replay_check(struct xfrm_state *x, u32 seq);
extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq);
extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb);
extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
+extern int xfrm_init_state(struct xfrm_state *x);
extern int xfrm4_rcv(struct sk_buff *skb);
extern int xfrm4_output(struct sk_buff *skb);
extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h
index 6d3413a5670..67b867f31fe 100644
--- a/include/pcmcia/ss.h
+++ b/include/pcmcia/ss.h
@@ -77,6 +77,11 @@ extern socket_state_t dead_socket;
/* Use this just for bridge windows */
#define MAP_IOSPACE 0x20
+/* power hook operations */
+#define HOOK_POWER_PRE 0x01
+#define HOOK_POWER_POST 0x02
+
+
typedef struct pccard_io_map {
u_char map;
u_char flags;
@@ -222,6 +227,9 @@ struct pcmcia_socket {
/* Zoom video behaviour is so chip specific its not worth adding
this to _ops */
void (*zoom_video)(struct pcmcia_socket *, int);
+
+ /* so is power hook */
+ int (*power_hook)(struct pcmcia_socket *sock, int operation);
/* state thread */
struct semaphore skt_sem; /* protects socket h/w state */
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 659ecf48fb4..1fb23374151 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -41,6 +41,7 @@ extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];
#define FORMAT_UNIT 0x04
#define READ_BLOCK_LIMITS 0x05
#define REASSIGN_BLOCKS 0x07
+#define INITIALIZE_ELEMENT_STATUS 0x07
#define READ_6 0x08
#define WRITE_6 0x0a
#define SEEK_6 0x0b
@@ -65,6 +66,7 @@ extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];
#define READ_10 0x28
#define WRITE_10 0x2a
#define SEEK_10 0x2b
+#define POSITION_TO_ELEMENT 0x2b
#define WRITE_VERIFY 0x2e
#define VERIFY 0x2f
#define SEARCH_HIGH 0x30
@@ -97,6 +99,7 @@ extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];
#define PERSISTENT_RESERVE_OUT 0x5f
#define REPORT_LUNS 0xa0
#define MOVE_MEDIUM 0xa5
+#define EXCHANGE_MEDIUM 0xa6
#define READ_12 0xa8
#define WRITE_12 0xaa
#define WRITE_VERIFY_12 0xae
@@ -210,6 +213,7 @@ static inline int scsi_status_is_good(int status)
#define TYPE_COMM 0x09 /* Communications device */
#define TYPE_ENCLOSURE 0x0d /* Enclosure Services Device */
#define TYPE_RAID 0x0c
+#define TYPE_RBC 0x0e
#define TYPE_NO_LUN 0x7f
/*
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index c018020d916..63c91dd85ca 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -154,7 +154,9 @@ struct scsi_target {
unsigned int id; /* target id ... replace
* scsi_device.id eventually */
unsigned long create:1; /* signal that it needs to be added */
- unsigned long starget_data[0];
+ void *hostdata; /* available to low-level driver */
+ unsigned long starget_data[0]; /* for the transport */
+ /* starget_data must be the last element!!!! */
} __attribute__((aligned(sizeof(unsigned long))));
#define to_scsi_target(d) container_of(d, struct scsi_target, dev)
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 1cee1e10094..db9914adeac 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -10,6 +10,7 @@ struct block_device;
struct module;
struct scsi_cmnd;
struct scsi_device;
+struct scsi_target;
struct Scsi_Host;
struct scsi_host_cmd_pool;
struct scsi_transport_template;
@@ -228,6 +229,30 @@ struct scsi_host_template {
void (* slave_destroy)(struct scsi_device *);
/*
+ * Before the mid layer attempts to scan for a new device attached
+ * to a target where no target currently exists, it will call this
+ * entry in your driver. Should your driver need to allocate any
+ * structs or perform any other init items in order to send commands
+ * to a currently unused target, then this is where you can perform
+ * those allocations.
+ *
+ * Return values: 0 on success, non-0 on failure
+ *
+ * Status: OPTIONAL
+ */
+ int (* target_alloc)(struct scsi_target *);
+
+ /*
+ * Immediately prior to deallocating the target structure, and
+ * after all activity to attached scsi devices has ceased, the
+ * midlayer calls this point so that the driver may deallocate
+ * and terminate any references to the target.
+ *
+ * Status: OPTIONAL
+ */
+ void (* target_destroy)(struct scsi_target *);
+
+ /*
* fill in this function to allow the queue depth of this host
* to be changeable (on a per device basis). returns either
* the current queue depth setting (may be different from what
diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h
index 2dcee7a8475..a4f1837a33b 100644
--- a/include/scsi/scsi_transport.h
+++ b/include/scsi/scsi_transport.h
@@ -21,6 +21,7 @@
#define SCSI_TRANSPORT_H
#include <linux/transport_class.h>
+#include <scsi/scsi_host.h>
struct scsi_transport_template {
/* the attribute containers */
@@ -32,8 +33,11 @@ struct scsi_transport_template {
* space of this size will be left at the end of the
* scsi_* structure */
int device_size;
+ int device_private_offset;
int target_size;
+ int target_private_offset;
int host_size;
+ /* no private offset for the host; there's an alternative mechanism */
/*
* True if the transport wants to use a host-based work-queue
@@ -45,4 +49,38 @@ struct scsi_transport_template {
dev_to_shost((tc)->dev)
+/* Private area maintenance. The driver requested allocations come
+ * directly after the transport class allocations (if any). The idea
+ * is that you *must* call these only once. The code assumes that the
+ * initial values are the ones the transport specific code requires */
+static inline void
+scsi_transport_reserve_target(struct scsi_transport_template * t, int space)
+{
+ BUG_ON(t->target_private_offset != 0);
+ t->target_private_offset = ALIGN(t->target_size, sizeof(void *));
+ t->target_size = t->target_private_offset + space;
+}
+static inline void
+scsi_transport_reserve_device(struct scsi_transport_template * t, int space)
+{
+ BUG_ON(t->device_private_offset != 0);
+ t->device_private_offset = ALIGN(t->device_size, sizeof(void *));
+ t->device_size = t->device_private_offset + space;
+}
+static inline void *
+scsi_transport_target_data(struct scsi_target *starget)
+{
+ struct Scsi_Host *shost = dev_to_shost(&starget->dev);
+ return (u8 *)starget->starget_data
+ + shost->transportt->target_private_offset;
+
+}
+static inline void *
+scsi_transport_device_data(struct scsi_device *sdev)
+{
+ struct Scsi_Host *shost = sdev->host;
+ return (u8 *)sdev->sdev_data
+ + shost->transportt->device_private_offset;
+}
+
#endif /* SCSI_TRANSPORT_H */
diff --git a/include/scsi/scsi_transport_spi.h b/include/scsi/scsi_transport_spi.h
index 6dcf497bf46..a30d6cd4c0e 100644
--- a/include/scsi/scsi_transport_spi.h
+++ b/include/scsi/scsi_transport_spi.h
@@ -27,8 +27,11 @@ struct scsi_transport_template;
struct spi_transport_attrs {
int period; /* value in the PPR/SDTR command */
+ int min_period;
int offset;
+ int max_offset;
unsigned int width:1; /* 0 - narrow, 1 - wide */
+ unsigned int max_width:1;
unsigned int iu:1; /* Information Units enabled */
unsigned int dt:1; /* DT clocking enabled */
unsigned int qas:1; /* Quick Arbitration and Selection enabled */
@@ -63,8 +66,11 @@ struct spi_host_attrs {
/* accessor functions */
#define spi_period(x) (((struct spi_transport_attrs *)&(x)->starget_data)->period)
+#define spi_min_period(x) (((struct spi_transport_attrs *)&(x)->starget_data)->min_period)
#define spi_offset(x) (((struct spi_transport_attrs *)&(x)->starget_data)->offset)
+#define spi_max_offset(x) (((struct spi_transport_attrs *)&(x)->starget_data)->max_offset)
#define spi_width(x) (((struct spi_transport_attrs *)&(x)->starget_data)->width)
+#define spi_max_width(x) (((struct spi_transport_attrs *)&(x)->starget_data)->max_width)
#define spi_iu(x) (((struct spi_transport_attrs *)&(x)->starget_data)->iu)
#define spi_dt(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dt)
#define spi_qas(x) (((struct spi_transport_attrs *)&(x)->starget_data)->qas)
diff --git a/include/scsi/sg_request.h b/include/scsi/sg_request.h
new file mode 100644
index 00000000000..57ff525bdd3
--- /dev/null
+++ b/include/scsi/sg_request.h
@@ -0,0 +1,26 @@
+typedef struct scsi_request Scsi_Request;
+
+static Scsi_Request *dummy_cmdp; /* only used for sizeof */
+
+typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info */
+ unsigned short k_use_sg; /* Count of kernel scatter-gather pieces */
+ unsigned short sglist_len; /* size of malloc'd scatter-gather list ++ */
+ unsigned bufflen; /* Size of (aggregate) data buffer */
+ unsigned b_malloc_len; /* actual len malloc'ed in buffer */
+ void *buffer; /* Data buffer or scatter list (k_use_sg>0) */
+ char dio_in_use; /* 0->indirect IO (or mmap), 1->dio */
+ unsigned char cmd_opcode; /* first byte of command */
+} Sg_scatter_hold;
+
+typedef struct sg_request { /* SG_MAX_QUEUE requests outstanding per file */
+ Scsi_Request *my_cmdp; /* != 0 when request with lower levels */
+ struct sg_request *nextrp; /* NULL -> tail request (slist) */
+ struct sg_fd *parentfp; /* NULL -> not in use */
+ Sg_scatter_hold data; /* hold buffer, perhaps scatter list */
+ sg_io_hdr_t header; /* scsi command+info, see <scsi/sg.h> */
+ unsigned char sense_b[sizeof (dummy_cmdp->sr_sense_buffer)];
+ char res_used; /* 1 -> using reserve buffer, 0 -> not ... */
+ char orphan; /* 1 -> drop on sight, 0 -> normal */
+ char sg_io_owned; /* 1 -> packet belongs to SG_IO */
+ volatile char done; /* 0->before bh, 1->before read, 2->read */
+} Sg_request;
diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
index 2433e279e07..1309c12b8f7 100644
--- a/include/sound/ac97_codec.h
+++ b/include/sound/ac97_codec.h
@@ -437,6 +437,7 @@ struct snd_ac97_build_ops {
void (*suspend) (ac97_t *ac97);
void (*resume) (ac97_t *ac97);
#endif
+ void (*update_jacks) (ac97_t *ac97); /* for jack-sharing */
};
struct _snd_ac97_bus_ops {
@@ -516,6 +517,9 @@ struct _snd_ac97 {
} ad18xx;
unsigned int dev_flags; /* device specific */
} spec;
+ /* jack-sharing info */
+ unsigned char indep_surround;
+ unsigned char channel_mode;
};
/* conditions */
@@ -569,8 +573,8 @@ enum {
};
struct ac97_quirk {
- unsigned short vendor; /* PCI vendor id */
- unsigned short device; /* PCI device id */
+ unsigned short subvendor; /* PCI subsystem vendor id */
+ unsigned short subdevice; /* PCI sybsystem device id */
unsigned short mask; /* device id bit mask, 0 = accept all */
unsigned int codec_id; /* codec id (if any), 0 = accept all */
const char *name; /* name shown as info */
diff --git a/include/sound/asound.h b/include/sound/asound.h
index a4d149f3454..9974f83cca4 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -113,9 +113,10 @@ enum sndrv_hwdep_iface {
SNDRV_HWDEP_IFACE_BLUETOOTH, /* Bluetooth audio */
SNDRV_HWDEP_IFACE_USX2Y_PCM, /* Tascam US122, US224 & US428 rawusb pcm */
SNDRV_HWDEP_IFACE_PCXHR, /* Digigram PCXHR */
+ SNDRV_HWDEP_IFACE_SB_RC, /* SB Extigy/Audigy2NX remote control */
/* Don't forget to change the following: */
- SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_PCXHR
+ SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_SB_RC
};
struct sndrv_hwdep_info {
@@ -344,7 +345,7 @@ enum sndrv_pcm_hw_param {
SNDRV_PCM_HW_PARAM_LAST_INTERVAL = SNDRV_PCM_HW_PARAM_TICK_TIME
};
-#define SNDRV_PCM_HW_PARAMS_RUNTIME (1<<0)
+#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0) /* avoid rate resampling */
struct sndrv_interval {
unsigned int min, max;
@@ -559,7 +560,7 @@ enum {
* Timer section - /dev/snd/timer
*/
-#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 2)
+#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 4)
enum sndrv_timer_class {
SNDRV_TIMER_CLASS_NONE = -1,
@@ -672,10 +673,11 @@ enum {
SNDRV_TIMER_IOCTL_INFO = _IOR('T', 0x11, struct sndrv_timer_info),
SNDRV_TIMER_IOCTL_PARAMS = _IOW('T', 0x12, struct sndrv_timer_params),
SNDRV_TIMER_IOCTL_STATUS = _IOR('T', 0x14, struct sndrv_timer_status),
- SNDRV_TIMER_IOCTL_START = _IO('T', 0x20),
- SNDRV_TIMER_IOCTL_STOP = _IO('T', 0x21),
- SNDRV_TIMER_IOCTL_CONTINUE = _IO('T', 0x22),
- SNDRV_TIMER_IOCTL_PAUSE = _IO('T', 0x23),
+ /* The following four ioctls are changed since 1.0.9 due to confliction */
+ SNDRV_TIMER_IOCTL_START = _IO('T', 0xa0),
+ SNDRV_TIMER_IOCTL_STOP = _IO('T', 0xa1),
+ SNDRV_TIMER_IOCTL_CONTINUE = _IO('T', 0xa2),
+ SNDRV_TIMER_IOCTL_PAUSE = _IO('T', 0xa3),
};
struct sndrv_timer_read {
diff --git a/include/sound/control.h b/include/sound/control.h
index 7b9444cd02f..ef7903c7a32 100644
--- a/include/sound/control.h
+++ b/include/sound/control.h
@@ -106,7 +106,7 @@ typedef int (*snd_kctl_ioctl_func_t) (snd_card_t * card,
void snd_ctl_notify(snd_card_t * card, unsigned int mask, snd_ctl_elem_id_t * id);
snd_kcontrol_t *snd_ctl_new(snd_kcontrol_t * kcontrol, unsigned int access);
-snd_kcontrol_t *snd_ctl_new1(snd_kcontrol_new_t * kcontrolnew, void * private_data);
+snd_kcontrol_t *snd_ctl_new1(const snd_kcontrol_new_t * kcontrolnew, void * private_data);
void snd_ctl_free_one(snd_kcontrol_t * kcontrol);
int snd_ctl_add(snd_card_t * card, snd_kcontrol_t * kcontrol);
int snd_ctl_remove(snd_card_t * card, snd_kcontrol_t * kcontrol);
diff --git a/include/sound/core.h b/include/sound/core.h
index 9117c23e3a0..f8c4ef0aa35 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -292,6 +292,7 @@ void *snd_hidden_kcalloc(size_t n, size_t size, int flags);
void snd_hidden_kfree(const void *obj);
void *snd_hidden_vmalloc(unsigned long size);
void snd_hidden_vfree(void *obj);
+char *snd_hidden_kstrdup(const char *s, int flags);
#define kmalloc(size, flags) snd_hidden_kmalloc(size, flags)
#define kcalloc(n, size, flags) snd_hidden_kcalloc(n, size, flags)
#define kfree(obj) snd_hidden_kfree(obj)
@@ -301,6 +302,7 @@ void snd_hidden_vfree(void *obj);
#define vmalloc_nocheck(size) snd_wrapper_vmalloc(size)
#define kfree_nocheck(obj) snd_wrapper_kfree(obj)
#define vfree_nocheck(obj) snd_wrapper_vfree(obj)
+#define kstrdup(s, flags) snd_hidden_kstrdup(s, flags)
#else
#define snd_memory_init() /*NOP*/
#define snd_memory_done() /*NOP*/
@@ -311,7 +313,6 @@ void snd_hidden_vfree(void *obj);
#define kfree_nocheck(obj) kfree(obj)
#define vfree_nocheck(obj) vfree(obj)
#endif
-char *snd_kmalloc_strdup(const char *string, int flags);
int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size_t count);
int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size_t count);
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index 43b6786abae..c50b91958ff 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -83,7 +83,8 @@
#define IPR 0x08 /* Global interrupt pending register */
/* Clear pending interrupts by writing a 1 to */
/* the relevant bits and zero to the other bits */
-
+#define IPR_P16V 0x80000000 /* Bit set when the CA0151 P16V chip wishes
+ to interrupt */
#define IPR_GPIOMSG 0x20000000 /* GPIO message interrupt (RE'd, still not sure
which INTE bits enable it) */
@@ -746,6 +747,7 @@
/* Assumes sample lock */
/* These three bitfields apply to CDSRCS, GPSRCS, and (except as noted) ZVSRCS. */
+#define SRCS_SPDIFVALID 0x04000000 /* SPDIF stream valid */
#define SRCS_SPDIFLOCKED 0x02000000 /* SPDIF stream locked */
#define SRCS_RATELOCKED 0x01000000 /* Sample rate locked */
#define SRCS_ESTSAMPLERATE 0x0007ffff /* Do not modify this field. */
@@ -803,10 +805,26 @@
#define A_FXWC2 0x75 /* Selects 0x9f-0x80 for FX recording */
#define A_SPDIF_SAMPLERATE 0x76 /* Set the sample rate of SPDIF output */
-#define A_SPDIF_RATE_MASK 0x000000c0
+#define A_SAMPLE_RATE 0x76 /* Various sample rate settings. */
+#define A_SAMPLE_RATE_NOT_USED 0x0ffc111e /* Bits that are not used and cannot be set. */
+#define A_SAMPLE_RATE_UNKNOWN 0xf0030001 /* Bits that can be set, but have unknown use. */
+#define A_SPDIF_RATE_MASK 0x000000e0 /* Any other values for rates, just use 48000 */
#define A_SPDIF_48000 0x00000000
-#define A_SPDIF_44100 0x00000080
+#define A_SPDIF_192000 0x00000020
#define A_SPDIF_96000 0x00000040
+#define A_SPDIF_44100 0x00000080
+
+#define A_I2S_CAPTURE_RATE_MASK 0x00000e00 /* This sets the capture PCM rate, but it is */
+#define A_I2S_CAPTURE_48000 0x00000000 /* unclear if this sets the ADC rate as well. */
+#define A_I2S_CAPTURE_192000 0x00000200
+#define A_I2S_CAPTURE_96000 0x00000400
+#define A_I2S_CAPTURE_44100 0x00000800
+
+#define A_PCM_RATE_MASK 0x0000e000 /* This sets the playback PCM rate on the P16V */
+#define A_PCM_48000 0x00000000
+#define A_PCM_192000 0x00002000
+#define A_PCM_96000 0x00004000
+#define A_PCM_44100 0x00008000
/* 0x77,0x78,0x79 "something i2s-related" - default to 0x01080000 on my audigy 2 ZS --rlrevell */
/* 0x7a, 0x7b - lookup tables */
@@ -1039,28 +1057,28 @@ typedef struct {
u32 vendor;
u32 device;
u32 subsystem;
+ unsigned char revision;
unsigned char emu10k1_chip; /* Original SB Live. Not SB Live 24bit. */
unsigned char emu10k2_chip; /* Audigy 1 or Audigy 2. */
unsigned char ca0102_chip; /* Audigy 1 or Audigy 2. Not SB Audigy 2 Value. */
unsigned char ca0108_chip; /* Audigy 2 Value */
unsigned char ca0151_chip; /* P16V */
unsigned char spk71; /* Has 7.1 speakers */
+ unsigned char sblive51; /* SBLive! 5.1 - extout 0x11 -> center, 0x12 -> lfe */
unsigned char spdif_bug; /* Has Spdif phasing bug */
unsigned char ac97_chip; /* Has an AC97 chip */
unsigned char ecard; /* APS EEPROM */
- char * driver;
- char * name;
+ const char *driver;
+ const char *name;
+ const char *id; /* for backward compatibility - can be NULL if not needed */
} emu_chip_details_t;
struct _snd_emu10k1 {
int irq;
unsigned long port; /* I/O port number */
- unsigned int APS: 1, /* APS flag */
- no_ac97: 1, /* no AC'97 */
- tos_link: 1, /* tos link detected */
- rear_ac97: 1, /* rear channels are on AC'97 */
- spk71:1; /* 7.1 configuration (Audigy 2 ZS) */
+ unsigned int tos_link: 1, /* tos link detected */
+ rear_ac97: 1; /* rear channels are on AC'97 */
const emu_chip_details_t *card_capabilities; /* Contains profile of card capabilities */
unsigned int audigy; /* is Audigy? */
unsigned int revision; /* chip revision */
@@ -1109,7 +1127,10 @@ struct _snd_emu10k1 {
emu10k1_voice_t voices[NUM_G];
emu10k1_voice_t p16v_voices[4];
+ emu10k1_voice_t p16v_capture_voice;
int p16v_device_offset;
+ u32 p16v_capture_source;
+ u32 p16v_capture_channel;
emu10k1_pcm_mixer_t pcm_mixer[32];
emu10k1_pcm_mixer_t efx_pcm_mixer[NUM_EFX_PLAYBACK];
snd_kcontrol_t *ctl_send_routing;
@@ -1453,7 +1474,6 @@ int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu,
#endif
typedef struct {
- unsigned int card; /* card type */
unsigned int internal_tram_size; /* in samples */
unsigned int external_tram_size; /* in samples */
char fxbus_names[16][32]; /* names of FXBUSes */
diff --git a/include/sound/gus.h b/include/sound/gus.h
index 8b6287a6fff..b4b461ca173 100644
--- a/include/sound/gus.h
+++ b/include/sound/gus.h
@@ -526,9 +526,6 @@ extern void snd_gf1_adlib_write(snd_gus_card_t * gus, unsigned char reg, unsigne
extern void snd_gf1_dram_addr(snd_gus_card_t * gus, unsigned int addr);
extern void snd_gf1_poke(snd_gus_card_t * gus, unsigned int addr, unsigned char data);
extern unsigned char snd_gf1_peek(snd_gus_card_t * gus, unsigned int addr);
-extern void snd_gf1_pokew(snd_gus_card_t * gus, unsigned int addr, unsigned short data);
-extern unsigned short snd_gf1_peekw(snd_gus_card_t * gus, unsigned int addr);
-extern void snd_gf1_dram_setmem(snd_gus_card_t * gus, unsigned int addr, unsigned short value, unsigned int count);
extern void snd_gf1_write_addr(snd_gus_card_t * gus, unsigned char reg, unsigned int addr, short w_16bit);
extern unsigned int snd_gf1_read_addr(snd_gus_card_t * gus, unsigned char reg, short w_16bit);
extern void snd_gf1_i_ctrl_stop(snd_gus_card_t * gus, unsigned char reg);
@@ -544,9 +541,6 @@ extern inline unsigned short snd_gf1_i_read16(snd_gus_card_t * gus, unsigned cha
{
return snd_gf1_i_look16(gus, reg | 0x80);
}
-extern void snd_gf1_i_adlib_write(snd_gus_card_t * gus, unsigned char reg, unsigned char data);
-extern void snd_gf1_i_write_addr(snd_gus_card_t * gus, unsigned char reg, unsigned int addr, short w_16bit);
-extern unsigned int snd_gf1_i_read_addr(snd_gus_card_t * gus, unsigned char reg, short w_16bit);
extern void snd_gf1_select_active_voices(snd_gus_card_t * gus);
@@ -580,10 +574,6 @@ extern void snd_gf1_lfo_command(snd_gus_card_t * gus, int voice, unsigned char *
void snd_gf1_mem_lock(snd_gf1_mem_t * alloc, int xup);
int snd_gf1_mem_xfree(snd_gf1_mem_t * alloc, snd_gf1_mem_block_t * block);
-snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc,
- unsigned int address);
-snd_gf1_mem_block_t *snd_gf1_mem_share(snd_gf1_mem_t * alloc,
- unsigned int *share_id);
snd_gf1_mem_block_t *snd_gf1_mem_alloc(snd_gf1_mem_t * alloc, int owner,
char *name, int size, int w_16,
int align, unsigned int *share_id);
@@ -608,23 +598,13 @@ int snd_gf1_dma_transfer_block(snd_gus_card_t * gus,
/* gus_volume.c */
unsigned short snd_gf1_lvol_to_gvol_raw(unsigned int vol);
-unsigned int snd_gf1_gvol_to_lvol_raw(unsigned short gf1_vol);
-unsigned int snd_gf1_calc_ramp_rate(snd_gus_card_t * gus,
- unsigned short start,
- unsigned short end,
- unsigned int us);
unsigned short snd_gf1_translate_freq(snd_gus_card_t * gus, unsigned int freq2);
-unsigned short snd_gf1_compute_pitchbend(unsigned short pitchbend, unsigned short sens);
-unsigned short snd_gf1_compute_freq(unsigned int freq,
- unsigned int rate,
- unsigned short mix_rate);
/* gus_reset.c */
void snd_gf1_set_default_handlers(snd_gus_card_t * gus, unsigned int what);
void snd_gf1_smart_stop_voice(snd_gus_card_t * gus, unsigned short voice);
void snd_gf1_stop_voice(snd_gus_card_t * gus, unsigned short voice);
-void snd_gf1_clear_voices(snd_gus_card_t * gus, unsigned short v_min, unsigned short v_max);
void snd_gf1_stop_voices(snd_gus_card_t * gus, unsigned short v_min, unsigned short v_max);
snd_gus_voice_t *snd_gf1_alloc_voice(snd_gus_card_t * gus, int type, int client, int port);
void snd_gf1_free_voice(snd_gus_card_t * gus, snd_gus_voice_t *voice);
@@ -641,9 +621,6 @@ int snd_gf1_pcm_new(snd_gus_card_t * gus, int pcm_dev, int control_index, snd_pc
#ifdef CONFIG_SND_DEBUG
extern void snd_gf1_print_voice_registers(snd_gus_card_t * gus);
-extern void snd_gf1_print_global_registers(snd_gus_card_t * gus);
-extern void snd_gf1_print_setup_registers(snd_gus_card_t * gus);
-extern void snd_gf1_peek_print_block(snd_gus_card_t * gus, unsigned int addr, int count, int w_16bit);
#endif
/* gus.c */
diff --git a/include/sound/hdspm.h b/include/sound/hdspm.h
new file mode 100644
index 00000000000..c34427ccd0b
--- /dev/null
+++ b/include/sound/hdspm.h
@@ -0,0 +1,131 @@
+#ifndef __SOUND_HDSPM_H /* -*- linux-c -*- */
+#define __SOUND_HDSPM_H
+/*
+ * Copyright (C) 2003 Winfried Ritsch (IEM)
+ * based on hdsp.h from Thomas Charbonnel (thomas@undata.org)
+ *
+ *
+ * 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 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/* Maximum channels is 64 even on 56Mode you have 64playbacks to matrix */
+#define HDSPM_MAX_CHANNELS 64
+
+/* -------------------- IOCTL Peak/RMS Meters -------------------- */
+
+typedef struct _snd_hdspm_peak_rms hdspm_peak_rms_t;
+
+/* peam rms level structure like we get from hardware
+
+ maybe in future we can memory map it so I just copy it
+ to user on ioctl call now an dont change anything
+ rms are made out of low and high values
+ where (long) ????_rms = (????_rms_l >> 8) + ((????_rms_h & 0xFFFFFF00)<<24)
+ (i asume so from the code)
+*/
+
+struct _snd_hdspm_peak_rms {
+
+ unsigned int level_offset[1024];
+
+ unsigned int input_peak[64];
+ unsigned int playback_peak[64];
+ unsigned int output_peak[64];
+ unsigned int xxx_peak[64]; /* not used */
+
+ unsigned int reserved[256]; /* not used */
+
+ unsigned int input_rms_l[64];
+ unsigned int playback_rms_l[64];
+ unsigned int output_rms_l[64];
+ unsigned int xxx_rms_l[64]; /* not used */
+
+ unsigned int input_rms_h[64];
+ unsigned int playback_rms_h[64];
+ unsigned int output_rms_h[64];
+ unsigned int xxx_rms_h[64]; /* not used */
+};
+
+struct sndrv_hdspm_peak_rms_ioctl {
+ hdspm_peak_rms_t *peak;
+};
+
+/* use indirect access due to the limit of ioctl bit size */
+#define SNDRV_HDSPM_IOCTL_GET_PEAK_RMS _IOR('H', 0x40, struct sndrv_hdspm_peak_rms_ioctl)
+
+/* ------------ CONFIG block IOCTL ---------------------- */
+
+typedef struct _snd_hdspm_config_info hdspm_config_info_t;
+
+struct _snd_hdspm_config_info {
+ unsigned char pref_sync_ref;
+ unsigned char wordclock_sync_check;
+ unsigned char madi_sync_check;
+ unsigned int system_sample_rate;
+ unsigned int autosync_sample_rate;
+ unsigned char system_clock_mode;
+ unsigned char clock_source;
+ unsigned char autosync_ref;
+ unsigned char line_out;
+ unsigned int passthru;
+ unsigned int analog_out;
+};
+
+#define SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO _IOR('H', 0x41, hdspm_config_info_t)
+
+
+/* get Soundcard Version */
+
+typedef struct _snd_hdspm_version hdspm_version_t;
+
+struct _snd_hdspm_version {
+ unsigned short firmware_rev;
+};
+
+#define SNDRV_HDSPM_IOCTL_GET_VERSION _IOR('H', 0x43, hdspm_version_t)
+
+
+/* ------------- get Matrix Mixer IOCTL --------------- */
+
+/* MADI mixer: 64inputs+64playback in 64outputs = 8192 => *4Byte = 32768 Bytes */
+
+/* organisation is 64 channelfader in a continous memory block */
+/* equivalent to hardware definition, maybe for future feature of mmap of them */
+/* each of 64 outputs has 64 infader and 64 outfader:
+ Ins to Outs mixer[out].in[in], Outstreams to Outs mixer[out].pb[pb] */
+
+#define HDSPM_MIXER_CHANNELS HDSPM_MAX_CHANNELS
+
+typedef struct _snd_hdspm_channelfader snd_hdspm_channelfader_t;
+
+struct _snd_hdspm_channelfader {
+ unsigned int in[HDSPM_MIXER_CHANNELS];
+ unsigned int pb[HDSPM_MIXER_CHANNELS];
+};
+
+typedef struct _snd_hdspm_mixer hdspm_mixer_t;
+
+struct _snd_hdspm_mixer {
+ snd_hdspm_channelfader_t ch[HDSPM_MIXER_CHANNELS];
+};
+
+struct sndrv_hdspm_mixer_ioctl {
+ hdspm_mixer_t *mixer;
+};
+
+/* use indirect access due to the limit of ioctl bit size */
+#define SNDRV_HDSPM_IOCTL_GET_MIXER _IOR('H', 0x44, struct sndrv_hdspm_mixer_ioctl)
+
+#endif /* __SOUND_HDSPM_H */
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 53fc04d75ba..d935417575b 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -848,23 +848,6 @@ int snd_interval_ratnum(snd_interval_t *i,
void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params);
void _snd_pcm_hw_param_setempty(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var);
-int snd_pcm_hw_param_min(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *params,
- snd_pcm_hw_param_t var,
- unsigned int val, int *dir);
-int snd_pcm_hw_param_max(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *params,
- snd_pcm_hw_param_t var,
- unsigned int val, int *dir);
-int snd_pcm_hw_param_setinteger(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *params,
- snd_pcm_hw_param_t var);
-int snd_pcm_hw_param_first(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *params,
- snd_pcm_hw_param_t var, int *dir);
-int snd_pcm_hw_param_last(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *params,
- snd_pcm_hw_param_t var, int *dir);
int snd_pcm_hw_param_near(snd_pcm_substream_t *substream,
snd_pcm_hw_params_t *params,
snd_pcm_hw_param_t var,
@@ -876,7 +859,6 @@ int snd_pcm_hw_param_set(snd_pcm_substream_t *pcm,
int snd_pcm_hw_params_choose(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *params);
int snd_pcm_hw_refine(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *params);
-int snd_pcm_hw_params(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *params);
int snd_pcm_hw_constraints_init(snd_pcm_substream_t *substream);
int snd_pcm_hw_constraints_complete(snd_pcm_substream_t *substream);
@@ -922,8 +904,22 @@ int snd_pcm_format_unsigned(snd_pcm_format_t format);
int snd_pcm_format_linear(snd_pcm_format_t format);
int snd_pcm_format_little_endian(snd_pcm_format_t format);
int snd_pcm_format_big_endian(snd_pcm_format_t format);
+/**
+ * snd_pcm_format_cpu_endian - Check the PCM format is CPU-endian
+ * @format: the format to check
+ *
+ * Returns 1 if the given PCM format is CPU-endian, 0 if
+ * opposite, or a negative error code if endian not specified.
+ */
+/* int snd_pcm_format_cpu_endian(snd_pcm_format_t format); */
+#ifdef SNDRV_LITTLE_ENDIAN
+#define snd_pcm_format_cpu_endian snd_pcm_format_little_endian
+#else
+#define snd_pcm_format_cpu_endian snd_pcm_format_big_endian
+#endif
int snd_pcm_format_width(snd_pcm_format_t format); /* in bits */
int snd_pcm_format_physical_width(snd_pcm_format_t format); /* in bits */
+ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples);
const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format);
int snd_pcm_format_set_silence(snd_pcm_format_t format, void *buf, unsigned int frames);
snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian);
diff --git a/include/sound/seq_midi_event.h b/include/sound/seq_midi_event.h
index 4357cac0750..8857e2bd31a 100644
--- a/include/sound/seq_midi_event.h
+++ b/include/sound/seq_midi_event.h
@@ -41,9 +41,7 @@ struct snd_midi_event_t {
};
int snd_midi_event_new(int bufsize, snd_midi_event_t **rdev);
-int snd_midi_event_resize_buffer(snd_midi_event_t *dev, int bufsize);
void snd_midi_event_free(snd_midi_event_t *dev);
-void snd_midi_event_init(snd_midi_event_t *dev);
void snd_midi_event_reset_encode(snd_midi_event_t *dev);
void snd_midi_event_reset_decode(snd_midi_event_t *dev);
void snd_midi_event_no_status(snd_midi_event_t *dev, int on);
diff --git a/include/sound/seq_virmidi.h b/include/sound/seq_virmidi.h
index cf4e2388103..1ad27e859af 100644
--- a/include/sound/seq_virmidi.h
+++ b/include/sound/seq_virmidi.h
@@ -79,6 +79,5 @@ struct _snd_virmidi_dev {
#define SNDRV_VIRMIDI_SEQ_DISPATCH 2
int snd_virmidi_new(snd_card_t *card, int device, snd_rawmidi_t **rrmidi);
-int snd_virmidi_receive(snd_rawmidi_t *rmidi, snd_seq_event_t *ev);
#endif /* __SOUND_SEQ_VIRMIDI */
diff --git a/include/sound/timer.h b/include/sound/timer.h
index 57fde990606..1898511a0f3 100644
--- a/include/sound/timer.h
+++ b/include/sound/timer.h
@@ -152,6 +152,4 @@ extern int snd_timer_pause(snd_timer_instance_t * timeri);
extern void snd_timer_interrupt(snd_timer_t * timer, unsigned long ticks_left);
-extern unsigned int snd_timer_system_resolution(void);
-
#endif /* __SOUND_TIMER_H */
diff --git a/include/sound/version.h b/include/sound/version.h
index 98b4230778e..46acfa8c998 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
/* include/version.h. Generated by configure. */
-#define CONFIG_SND_VERSION "1.0.9rc2"
-#define CONFIG_SND_DATE " (Thu Mar 24 10:33:39 2005 UTC)"
+#define CONFIG_SND_VERSION "1.0.9"
+#define CONFIG_SND_DATE " (Sun May 29 07:31:02 2005 UTC)"
diff --git a/init/Kconfig b/init/Kconfig
index d920baed109..b1091d7542c 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -164,6 +164,7 @@ config SYSCTL
config AUDIT
bool "Auditing support"
+ depends on NET
default y if SECURITY_SELINUX
help
Enable auditing infrastructure that can be used with another
@@ -173,7 +174,7 @@ config AUDIT
config AUDITSYSCALL
bool "Enable system-call auditing support"
- depends on AUDIT && (X86 || PPC64 || ARCH_S390 || IA64 || UML)
+ depends on AUDIT && (X86 || PPC || PPC64 || ARCH_S390 || IA64 || UML)
default y if SECURITY_SELINUX
help
Enable low-overhead system-call auditing infrastructure that
@@ -442,7 +443,7 @@ config OBSOLETE_MODPARM
config MODVERSIONS
bool "Module versioning support (EXPERIMENTAL)"
- depends on MODULES && EXPERIMENTAL && !UML
+ depends on MODULES && EXPERIMENTAL
help
Usually, you have to use modules compiled with your kernel.
Saying Y here makes it sometimes possible to use modules
diff --git a/init/calibrate.c b/init/calibrate.c
index c698e04a3db..d206c7548fe 100644
--- a/init/calibrate.c
+++ b/init/calibrate.c
@@ -8,6 +8,8 @@
#include <linux/delay.h>
#include <linux/init.h>
+#include <asm/timex.h>
+
static unsigned long preset_lpj;
static int __init lpj_setup(char *str)
{
@@ -17,6 +19,92 @@ static int __init lpj_setup(char *str)
__setup("lpj=", lpj_setup);
+#ifdef ARCH_HAS_READ_CURRENT_TIMER
+
+/* This routine uses the read_current_timer() routine and gets the
+ * loops per jiffy directly, instead of guessing it using delay().
+ * Also, this code tries to handle non-maskable asynchronous events
+ * (like SMIs)
+ */
+#define DELAY_CALIBRATION_TICKS ((HZ < 100) ? 1 : (HZ/100))
+#define MAX_DIRECT_CALIBRATION_RETRIES 5
+
+static unsigned long __devinit calibrate_delay_direct(void)
+{
+ unsigned long pre_start, start, post_start;
+ unsigned long pre_end, end, post_end;
+ unsigned long start_jiffies;
+ unsigned long tsc_rate_min, tsc_rate_max;
+ unsigned long good_tsc_sum = 0;
+ unsigned long good_tsc_count = 0;
+ int i;
+
+ if (read_current_timer(&pre_start) < 0 )
+ return 0;
+
+ /*
+ * A simple loop like
+ * while ( jiffies < start_jiffies+1)
+ * start = read_current_timer();
+ * will not do. As we don't really know whether jiffy switch
+ * happened first or timer_value was read first. And some asynchronous
+ * event can happen between these two events introducing errors in lpj.
+ *
+ * So, we do
+ * 1. pre_start <- When we are sure that jiffy switch hasn't happened
+ * 2. check jiffy switch
+ * 3. start <- timer value before or after jiffy switch
+ * 4. post_start <- When we are sure that jiffy switch has happened
+ *
+ * Note, we don't know anything about order of 2 and 3.
+ * Now, by looking at post_start and pre_start difference, we can
+ * check whether any asynchronous event happened or not
+ */
+
+ for (i = 0; i < MAX_DIRECT_CALIBRATION_RETRIES; i++) {
+ pre_start = 0;
+ read_current_timer(&start);
+ start_jiffies = jiffies;
+ while (jiffies <= (start_jiffies + 1)) {
+ pre_start = start;
+ read_current_timer(&start);
+ }
+ read_current_timer(&post_start);
+
+ pre_end = 0;
+ end = post_start;
+ while (jiffies <=
+ (start_jiffies + 1 + DELAY_CALIBRATION_TICKS)) {
+ pre_end = end;
+ read_current_timer(&end);
+ }
+ read_current_timer(&post_end);
+
+ tsc_rate_max = (post_end - pre_start) / DELAY_CALIBRATION_TICKS;
+ tsc_rate_min = (pre_end - post_start) / DELAY_CALIBRATION_TICKS;
+
+ /*
+ * If the upper limit and lower limit of the tsc_rate is
+ * >= 12.5% apart, redo calibration.
+ */
+ if (pre_start != 0 && pre_end != 0 &&
+ (tsc_rate_max - tsc_rate_min) < (tsc_rate_max >> 3)) {
+ good_tsc_count++;
+ good_tsc_sum += tsc_rate_max;
+ }
+ }
+
+ if (good_tsc_count)
+ return (good_tsc_sum/good_tsc_count);
+
+ printk(KERN_WARNING "calibrate_delay_direct() failed to get a good "
+ "estimate for loops_per_jiffy.\nProbably due to long platform interrupts. Consider using \"lpj=\" boot option.\n");
+ return 0;
+}
+#else
+static unsigned long __devinit calibrate_delay_direct(void) {return 0;}
+#endif
+
/*
* This is the number of bits of precision for the loops_per_jiffy. Each
* bit takes on average 1.5/HZ seconds. This (like the original) is a little
@@ -35,6 +123,12 @@ void __devinit calibrate_delay(void)
"%lu.%02lu BogoMIPS preset\n",
loops_per_jiffy/(500000/HZ),
(loops_per_jiffy/(5000/HZ)) % 100);
+ } else if ((loops_per_jiffy = calibrate_delay_direct()) != 0) {
+ printk("Calibrating delay using timer specific routine.. ");
+ printk("%lu.%02lu BogoMIPS (lpj=%lu)\n",
+ loops_per_jiffy/(500000/HZ),
+ (loops_per_jiffy/(5000/HZ)) % 100,
+ loops_per_jiffy);
} else {
loops_per_jiffy = (1<<12);
diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c
index 07e7d31f2d0..4def882d0b3 100644
--- a/init/do_mounts_initrd.c
+++ b/init/do_mounts_initrd.c
@@ -41,7 +41,7 @@ static int __init do_linuxrc(void * shell)
static void __init handle_initrd(void)
{
int error;
- int i, pid;
+ int pid;
real_root_dev = new_encode_dev(ROOT_DEV);
create_dev("/dev/root.old", Root_RAM0, NULL);
@@ -58,7 +58,7 @@ static void __init handle_initrd(void)
pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
if (pid > 0) {
- while (pid != sys_wait4(-1, &i, 0, NULL))
+ while (pid != sys_wait4(-1, NULL, 0, NULL))
yield();
}
diff --git a/init/main.c b/init/main.c
index 40bf367ffdf..d324801729b 100644
--- a/init/main.c
+++ b/init/main.c
@@ -490,6 +490,7 @@ asmlinkage void __init start_kernel(void)
vfs_caches_init_early();
mem_init();
kmem_cache_init();
+ setup_per_cpu_pageset();
numa_policy_init();
if (late_time_init)
late_time_init();
diff --git a/ipc/sem.c b/ipc/sem.c
index 5ad7ac0ed60..7e8a25c82ef 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -1054,7 +1054,7 @@ asmlinkage long sys_semtimedop(int semid, struct sembuf __user *tsops,
struct sembuf fast_sops[SEMOPM_FAST];
struct sembuf* sops = fast_sops, *sop;
struct sem_undo *un;
- int undos = 0, decrease = 0, alter = 0, max;
+ int undos = 0, alter = 0, max;
struct sem_queue queue;
unsigned long jiffies_left = 0;
@@ -1089,13 +1089,10 @@ asmlinkage long sys_semtimedop(int semid, struct sembuf __user *tsops,
if (sop->sem_num >= max)
max = sop->sem_num;
if (sop->sem_flg & SEM_UNDO)
- undos++;
- if (sop->sem_op < 0)
- decrease = 1;
- if (sop->sem_op > 0)
+ undos = 1;
+ if (sop->sem_op != 0)
alter = 1;
}
- alter |= decrease;
retry_undos:
if (undos) {
diff --git a/kernel/Kconfig.hz b/kernel/Kconfig.hz
new file mode 100644
index 00000000000..248e1c396f8
--- /dev/null
+++ b/kernel/Kconfig.hz
@@ -0,0 +1,46 @@
+#
+# Timer Interrupt Frequency Configuration
+#
+
+choice
+ prompt "Timer frequency"
+ default HZ_250
+ help
+ Allows the configuration of the timer frequency. It is customary
+ to have the timer interrupt run at 1000 HZ but 100 HZ may be more
+ beneficial for servers and NUMA systems that do not need to have
+ a fast response for user interaction and that may experience bus
+ contention and cacheline bounces as a result of timer interrupts.
+ Note that the timer interrupt occurs on each processor in an SMP
+ environment leading to NR_CPUS * HZ number of timer interrupts
+ per second.
+
+
+ config HZ_100
+ bool "100 HZ"
+ help
+ 100 HZ is a typical choice for servers, SMP and NUMA systems
+ with lots of processors that may show reduced performance if
+ too many timer interrupts are occurring.
+
+ config HZ_250
+ bool "250 HZ"
+ help
+ 250 HZ is a good compromise choice allowing server performance
+ while also showing good interactive responsiveness even
+ on SMP and NUMA systems.
+
+ config HZ_1000
+ bool "1000 HZ"
+ help
+ 1000 HZ is the preferred choice for desktop systems and other
+ systems requiring fast interactive responses to events.
+
+endchoice
+
+config HZ
+ int
+ default 100 if HZ_100
+ default 250 if HZ_250
+ default 1000 if HZ_1000
+
diff --git a/kernel/Kconfig.preempt b/kernel/Kconfig.preempt
new file mode 100644
index 00000000000..0b46a5dff4c
--- /dev/null
+++ b/kernel/Kconfig.preempt
@@ -0,0 +1,65 @@
+
+choice
+ prompt "Preemption Model"
+ default PREEMPT_NONE
+
+config PREEMPT_NONE
+ bool "No Forced Preemption (Server)"
+ help
+ This is the traditional Linux preemption model, geared towards
+ throughput. It will still provide good latencies most of the
+ time, but there are no guarantees and occasional longer delays
+ are possible.
+
+ Select this option if you are building a kernel for a server or
+ scientific/computation system, or if you want to maximize the
+ raw processing power of the kernel, irrespective of scheduling
+ latencies.
+
+config PREEMPT_VOLUNTARY
+ bool "Voluntary Kernel Preemption (Desktop)"
+ help
+ This option reduces the latency of the kernel by adding more
+ "explicit preemption points" to the kernel code. These new
+ preemption points have been selected to reduce the maximum
+ latency of rescheduling, providing faster application reactions,
+ at the cost of slighly lower throughput.
+
+ This allows reaction to interactive events by allowing a
+ low priority process to voluntarily preempt itself even if it
+ is in kernel mode executing a system call. This allows
+ applications to run more 'smoothly' even when the system is
+ under load.
+
+ Select this if you are building a kernel for a desktop system.
+
+config PREEMPT
+ bool "Preemptible Kernel (Low-Latency Desktop)"
+ help
+ This option reduces the latency of the kernel by making
+ all kernel code (that is not executing in a critical section)
+ preemptible. This allows reaction to interactive events by
+ permitting a low priority process to be preempted involuntarily
+ even if it is in kernel mode executing a system call and would
+ otherwise not be about to reach a natural preemption point.
+ This allows applications to run more 'smoothly' even when the
+ system is under load, at the cost of slighly lower throughput
+ and a slight runtime overhead to kernel code.
+
+ Select this if you are building a kernel for a desktop or
+ embedded system with latency requirements in the milliseconds
+ range.
+
+endchoice
+
+config PREEMPT_BKL
+ bool "Preempt The Big Kernel Lock"
+ depends on SMP || PREEMPT
+ default y
+ help
+ This option reduces the latency of the kernel by making the
+ big kernel lock preemptible.
+
+ Say Y here if you are building a kernel for a desktop system.
+ Say N if you are unsure.
+
diff --git a/kernel/Makefile b/kernel/Makefile
index b01d26fe8db..cb05cd05d23 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_KALLSYMS) += kallsyms.o
obj-$(CONFIG_PM) += power/
obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
+obj-$(CONFIG_KEXEC) += kexec.o
obj-$(CONFIG_COMPAT) += compat.o
obj-$(CONFIG_CPUSETS) += cpuset.o
obj-$(CONFIG_IKCONFIG) += configs.o
@@ -27,6 +28,7 @@ obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
obj-$(CONFIG_KPROBES) += kprobes.o
obj-$(CONFIG_SYSFS) += ksysfs.o
obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
+obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_SECCOMP) += seccomp.o
ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y)
diff --git a/kernel/audit.c b/kernel/audit.c
index 9c4f1af0c79..ef35166fdc2 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -46,6 +46,8 @@
#include <asm/types.h>
#include <linux/mm.h>
#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/kthread.h>
#include <linux/audit.h>
@@ -68,7 +70,7 @@ static int audit_failure = AUDIT_FAIL_PRINTK;
/* If audit records are to be written to the netlink socket, audit_pid
* contains the (non-zero) pid. */
-static int audit_pid;
+int audit_pid;
/* If audit_limit is non-zero, limit the rate of sending audit records
* to that number per second. This prevents DoS attacks, but results in
@@ -77,7 +79,10 @@ static int audit_rate_limit;
/* Number of outstanding audit_buffers allowed. */
static int audit_backlog_limit = 64;
-static atomic_t audit_backlog = ATOMIC_INIT(0);
+
+/* The identity of the user shutting down the audit system. */
+uid_t audit_sig_uid = -1;
+pid_t audit_sig_pid = -1;
/* Records can be lost in several ways:
0) [suppressed in audit_alloc]
@@ -91,19 +96,17 @@ static atomic_t audit_lost = ATOMIC_INIT(0);
/* The netlink socket. */
static struct sock *audit_sock;
-/* There are two lists of audit buffers. The txlist contains audit
- * buffers that cannot be sent immediately to the netlink device because
- * we are in an irq context (these are sent later in a tasklet).
- *
- * The second list is a list of pre-allocated audit buffers (if more
+/* The audit_freelist is a list of pre-allocated audit buffers (if more
* than AUDIT_MAXFREE are in use, the audit buffer is freed instead of
* being placed on the freelist). */
-static DEFINE_SPINLOCK(audit_txlist_lock);
static DEFINE_SPINLOCK(audit_freelist_lock);
static int audit_freelist_count = 0;
-static LIST_HEAD(audit_txlist);
static LIST_HEAD(audit_freelist);
+static struct sk_buff_head audit_skb_queue;
+static struct task_struct *kauditd_task;
+static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait);
+
/* There are three lists of rules -- one to search at task creation
* time, one to search at syscall entry time, and another to search at
* syscall exit time. */
@@ -112,7 +115,7 @@ static LIST_HEAD(audit_entlist);
static LIST_HEAD(audit_extlist);
/* The netlink socket is only to be read by 1 CPU, which lets us assume
- * that list additions and deletions never happen simultaneiously in
+ * that list additions and deletions never happen simultaneously in
* auditsc.c */
static DECLARE_MUTEX(audit_netlink_sem);
@@ -132,21 +135,14 @@ static DECLARE_MUTEX(audit_netlink_sem);
* use simultaneously. */
struct audit_buffer {
struct list_head list;
- struct sk_buff_head sklist; /* formatted skbs ready to send */
+ struct sk_buff *skb; /* formatted skb ready to send */
struct audit_context *ctx; /* NULL or associated context */
- int len; /* used area of tmp */
- char tmp[AUDIT_BUFSIZ];
-
- /* Pointer to header and contents */
- struct nlmsghdr *nlh;
- int total;
- int type;
- int pid;
};
-void audit_set_type(struct audit_buffer *ab, int type)
+static void audit_set_pid(struct audit_buffer *ab, pid_t pid)
{
- ab->type = type;
+ struct nlmsghdr *nlh = (struct nlmsghdr *)ab->skb->data;
+ nlh->nlmsg_pid = pid;
}
struct audit_entry {
@@ -154,9 +150,6 @@ struct audit_entry {
struct audit_rule rule;
};
-static void audit_log_end_irq(struct audit_buffer *ab);
-static void audit_log_end_fast(struct audit_buffer *ab);
-
static void audit_panic(const char *message)
{
switch (audit_failure)
@@ -227,10 +220,8 @@ void audit_log_lost(const char *message)
if (print) {
printk(KERN_WARNING
- "audit: audit_lost=%d audit_backlog=%d"
- " audit_rate_limit=%d audit_backlog_limit=%d\n",
+ "audit: audit_lost=%d audit_rate_limit=%d audit_backlog_limit=%d\n",
atomic_read(&audit_lost),
- atomic_read(&audit_backlog),
audit_rate_limit,
audit_backlog_limit);
audit_panic(message);
@@ -242,7 +233,8 @@ static int audit_set_rate_limit(int limit, uid_t loginuid)
{
int old = audit_rate_limit;
audit_rate_limit = limit;
- audit_log(NULL, "audit_rate_limit=%d old=%d by auid %u",
+ audit_log(NULL, AUDIT_CONFIG_CHANGE,
+ "audit_rate_limit=%d old=%d by auid=%u",
audit_rate_limit, old, loginuid);
return old;
}
@@ -251,7 +243,8 @@ static int audit_set_backlog_limit(int limit, uid_t loginuid)
{
int old = audit_backlog_limit;
audit_backlog_limit = limit;
- audit_log(NULL, "audit_backlog_limit=%d old=%d by auid %u",
+ audit_log(NULL, AUDIT_CONFIG_CHANGE,
+ "audit_backlog_limit=%d old=%d by auid=%u",
audit_backlog_limit, old, loginuid);
return old;
}
@@ -262,8 +255,9 @@ static int audit_set_enabled(int state, uid_t loginuid)
if (state != 0 && state != 1)
return -EINVAL;
audit_enabled = state;
- audit_log(NULL, "audit_enabled=%d old=%d by auid %u",
- audit_enabled, old, loginuid);
+ audit_log(NULL, AUDIT_CONFIG_CHANGE,
+ "audit_enabled=%d old=%d by auid=%u",
+ audit_enabled, old, loginuid);
return old;
}
@@ -275,12 +269,44 @@ static int audit_set_failure(int state, uid_t loginuid)
&& state != AUDIT_FAIL_PANIC)
return -EINVAL;
audit_failure = state;
- audit_log(NULL, "audit_failure=%d old=%d by auid %u",
- audit_failure, old, loginuid);
+ audit_log(NULL, AUDIT_CONFIG_CHANGE,
+ "audit_failure=%d old=%d by auid=%u",
+ audit_failure, old, loginuid);
return old;
}
-#ifdef CONFIG_NET
+int kauditd_thread(void *dummy)
+{
+ struct sk_buff *skb;
+
+ while (1) {
+ skb = skb_dequeue(&audit_skb_queue);
+ if (skb) {
+ if (audit_pid) {
+ int err = netlink_unicast(audit_sock, skb, audit_pid, 0);
+ if (err < 0) {
+ BUG_ON(err != -ECONNREFUSED); /* Shoudn't happen */
+ printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n", audit_pid);
+ audit_pid = 0;
+ }
+ } else {
+ printk(KERN_ERR "%s\n", skb->data + NLMSG_SPACE(0));
+ kfree_skb(skb);
+ }
+ } else {
+ DECLARE_WAITQUEUE(wait, current);
+ set_current_state(TASK_INTERRUPTIBLE);
+ add_wait_queue(&kauditd_wait, &wait);
+
+ if (!skb_queue_len(&audit_skb_queue))
+ schedule();
+
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(&kauditd_wait, &wait);
+ }
+ }
+}
+
void audit_send_reply(int pid, int seq, int type, int done, int multi,
void *payload, int size)
{
@@ -293,13 +319,16 @@ void audit_send_reply(int pid, int seq, int type, int done, int multi,
skb = alloc_skb(len, GFP_KERNEL);
if (!skb)
- goto nlmsg_failure;
+ return;
- nlh = NLMSG_PUT(skb, pid, seq, t, len - sizeof(*nlh));
+ nlh = NLMSG_PUT(skb, pid, seq, t, size);
nlh->nlmsg_flags = flags;
data = NLMSG_DATA(nlh);
memcpy(data, payload, size);
- netlink_unicast(audit_sock, skb, pid, MSG_DONTWAIT);
+
+ /* Ignore failure. It'll only happen if the sender goes away,
+ because our timeout is set to infinite. */
+ netlink_unicast(audit_sock, skb, pid, 0);
return;
nlmsg_failure: /* Used by NLMSG_PUT */
@@ -321,10 +350,12 @@ static int audit_netlink_ok(kernel_cap_t eff_cap, u16 msg_type)
case AUDIT_SET:
case AUDIT_ADD:
case AUDIT_DEL:
+ case AUDIT_SIGNAL_INFO:
if (!cap_raised(eff_cap, CAP_AUDIT_CONTROL))
err = -EPERM;
break;
case AUDIT_USER:
+ case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG:
if (!cap_raised(eff_cap, CAP_AUDIT_WRITE))
err = -EPERM;
break;
@@ -344,11 +375,21 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
struct audit_buffer *ab;
u16 msg_type = nlh->nlmsg_type;
uid_t loginuid; /* loginuid of sender */
+ struct audit_sig_info sig_data;
err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, msg_type);
if (err)
return err;
+ /* As soon as there's any sign of userspace auditd, start kauditd to talk to it */
+ if (!kauditd_task)
+ kauditd_task = kthread_run(kauditd_thread, NULL, "kauditd");
+ if (IS_ERR(kauditd_task)) {
+ err = PTR_ERR(kauditd_task);
+ kauditd_task = NULL;
+ return err;
+ }
+
pid = NETLINK_CREDS(skb)->pid;
uid = NETLINK_CREDS(skb)->uid;
loginuid = NETLINK_CB(skb).loginuid;
@@ -363,7 +404,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
status_set.rate_limit = audit_rate_limit;
status_set.backlog_limit = audit_backlog_limit;
status_set.lost = atomic_read(&audit_lost);
- status_set.backlog = atomic_read(&audit_backlog);
+ status_set.backlog = skb_queue_len(&audit_skb_queue);
audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_GET, 0, 0,
&status_set, sizeof(status_set));
break;
@@ -382,7 +423,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
if (status_get->mask & AUDIT_STATUS_PID) {
int old = audit_pid;
audit_pid = status_get->pid;
- audit_log(NULL, "audit_pid=%d old=%d by auid %u",
+ audit_log(NULL, AUDIT_CONFIG_CHANGE,
+ "audit_pid=%d old=%d by auid=%u",
audit_pid, old, loginuid);
}
if (status_get->mask & AUDIT_STATUS_RATE_LIMIT)
@@ -392,18 +434,15 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
loginuid);
break;
case AUDIT_USER:
- ab = audit_log_start(NULL);
+ case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG:
+ ab = audit_log_start(NULL, msg_type);
if (!ab)
break; /* audit_panic has been called */
audit_log_format(ab,
- "user pid=%d uid=%d length=%d loginuid=%u"
+ "user pid=%d uid=%u auid=%u"
" msg='%.1024s'",
- pid, uid,
- (int)(nlh->nlmsg_len
- - ((char *)data - (char *)nlh)),
- loginuid, (char *)data);
- ab->type = AUDIT_USER;
- ab->pid = pid;
+ pid, uid, loginuid, (char *)data);
+ audit_set_pid(ab, pid);
audit_log_end(ab);
break;
case AUDIT_ADD:
@@ -412,12 +451,14 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
return -EINVAL;
/* fallthrough */
case AUDIT_LIST:
-#ifdef CONFIG_AUDITSYSCALL
err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
uid, seq, data, loginuid);
-#else
- err = -EOPNOTSUPP;
-#endif
+ break;
+ case AUDIT_SIGNAL_INFO:
+ sig_data.uid = audit_sig_uid;
+ sig_data.pid = audit_sig_pid;
+ audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_SIGNAL_INFO,
+ 0, 0, &sig_data, sizeof(sig_data));
break;
default:
err = -EINVAL;
@@ -467,87 +508,6 @@ static void audit_receive(struct sock *sk, int length)
up(&audit_netlink_sem);
}
-/* Move data from tmp buffer into an skb. This is an extra copy, and
- * that is unfortunate. However, the copy will only occur when a record
- * is being written to user space, which is already a high-overhead
- * operation. (Elimination of the copy is possible, for example, by
- * writing directly into a pre-allocated skb, at the cost of wasting
- * memory. */
-static void audit_log_move(struct audit_buffer *ab)
-{
- struct sk_buff *skb;
- char *start;
- int extra = ab->nlh ? 0 : NLMSG_SPACE(0);
-
- /* possible resubmission */
- if (ab->len == 0)
- return;
-
- skb = skb_peek_tail(&ab->sklist);
- if (!skb || skb_tailroom(skb) <= ab->len + extra) {
- skb = alloc_skb(2 * ab->len + extra, GFP_ATOMIC);
- if (!skb) {
- ab->len = 0; /* Lose information in ab->tmp */
- audit_log_lost("out of memory in audit_log_move");
- return;
- }
- __skb_queue_tail(&ab->sklist, skb);
- if (!ab->nlh)
- ab->nlh = (struct nlmsghdr *)skb_put(skb,
- NLMSG_SPACE(0));
- }
- start = skb_put(skb, ab->len);
- memcpy(start, ab->tmp, ab->len);
- ab->len = 0;
-}
-
-/* Iterate over the skbuff in the audit_buffer, sending their contents
- * to user space. */
-static inline int audit_log_drain(struct audit_buffer *ab)
-{
- struct sk_buff *skb;
-
- while ((skb = skb_dequeue(&ab->sklist))) {
- int retval = 0;
-
- if (audit_pid) {
- if (ab->nlh) {
- ab->nlh->nlmsg_len = ab->total;
- ab->nlh->nlmsg_type = ab->type;
- ab->nlh->nlmsg_flags = 0;
- ab->nlh->nlmsg_seq = 0;
- ab->nlh->nlmsg_pid = ab->pid;
- }
- skb_get(skb); /* because netlink_* frees */
- retval = netlink_unicast(audit_sock, skb, audit_pid,
- MSG_DONTWAIT);
- }
- if (retval == -EAGAIN &&
- (atomic_read(&audit_backlog)) < audit_backlog_limit) {
- skb_queue_head(&ab->sklist, skb);
- audit_log_end_irq(ab);
- return 1;
- }
- if (retval < 0) {
- if (retval == -ECONNREFUSED) {
- printk(KERN_ERR
- "audit: *NO* daemon at audit_pid=%d\n",
- audit_pid);
- audit_pid = 0;
- } else
- audit_log_lost("netlink socket too busy");
- }
- if (!audit_pid) { /* No daemon */
- int offset = ab->nlh ? NLMSG_SPACE(0) : 0;
- int len = skb->len - offset;
- skb->data[offset + len] = '\0';
- printk(KERN_ERR "%s\n", skb->data + offset);
- }
- kfree_skb(skb);
- ab->nlh = NULL;
- }
- return 0;
-}
/* Initialize audit support at boot time. */
static int __init audit_init(void)
@@ -558,40 +518,13 @@ static int __init audit_init(void)
if (!audit_sock)
audit_panic("cannot initialize netlink socket");
+ audit_sock->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
+ skb_queue_head_init(&audit_skb_queue);
audit_initialized = 1;
audit_enabled = audit_default;
- audit_log(NULL, "initialized");
- return 0;
-}
-
-#else
-/* Without CONFIG_NET, we have no skbuffs. For now, print what we have
- * in the buffer. */
-static void audit_log_move(struct audit_buffer *ab)
-{
- printk(KERN_ERR "%*.*s\n", ab->len, ab->len, ab->tmp);
- ab->len = 0;
-}
-
-static inline int audit_log_drain(struct audit_buffer *ab)
-{
- return 0;
-}
-
-/* Initialize audit support at boot time. */
-int __init audit_init(void)
-{
- printk(KERN_INFO "audit: initializing WITHOUT netlink support\n");
- audit_sock = NULL;
- audit_pid = 0;
-
- audit_initialized = 1;
- audit_enabled = audit_default;
- audit_log(NULL, "initialized");
+ audit_log(NULL, AUDIT_KERNEL, "initialized");
return 0;
}
-#endif
-
__initcall(audit_init);
/* Process kernel command-line parameter at boot time. audit=0 or audit=1. */
@@ -608,6 +541,102 @@ static int __init audit_enable(char *str)
__setup("audit=", audit_enable);
+static void audit_buffer_free(struct audit_buffer *ab)
+{
+ unsigned long flags;
+
+ if (!ab)
+ return;
+
+ if (ab->skb)
+ kfree_skb(ab->skb);
+
+ spin_lock_irqsave(&audit_freelist_lock, flags);
+ if (++audit_freelist_count > AUDIT_MAXFREE)
+ kfree(ab);
+ else
+ list_add(&ab->list, &audit_freelist);
+ spin_unlock_irqrestore(&audit_freelist_lock, flags);
+}
+
+static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx,
+ int gfp_mask, int type)
+{
+ unsigned long flags;
+ struct audit_buffer *ab = NULL;
+ struct nlmsghdr *nlh;
+
+ spin_lock_irqsave(&audit_freelist_lock, flags);
+ if (!list_empty(&audit_freelist)) {
+ ab = list_entry(audit_freelist.next,
+ struct audit_buffer, list);
+ list_del(&ab->list);
+ --audit_freelist_count;
+ }
+ spin_unlock_irqrestore(&audit_freelist_lock, flags);
+
+ if (!ab) {
+ ab = kmalloc(sizeof(*ab), gfp_mask);
+ if (!ab)
+ goto err;
+ }
+
+ ab->skb = alloc_skb(AUDIT_BUFSIZ, gfp_mask);
+ if (!ab->skb)
+ goto err;
+
+ ab->ctx = ctx;
+ nlh = (struct nlmsghdr *)skb_put(ab->skb, NLMSG_SPACE(0));
+ nlh->nlmsg_type = type;
+ nlh->nlmsg_flags = 0;
+ nlh->nlmsg_pid = 0;
+ nlh->nlmsg_seq = 0;
+ return ab;
+err:
+ audit_buffer_free(ab);
+ return NULL;
+}
+
+/* Compute a serial number for the audit record. Audit records are
+ * written to user-space as soon as they are generated, so a complete
+ * audit record may be written in several pieces. The timestamp of the
+ * record and this serial number are used by the user-space tools to
+ * determine which pieces belong to the same audit record. The
+ * (timestamp,serial) tuple is unique for each syscall and is live from
+ * syscall entry to syscall exit.
+ *
+ * Atomic values are only guaranteed to be 24-bit, so we count down.
+ *
+ * NOTE: Another possibility is to store the formatted records off the
+ * audit context (for those records that have a context), and emit them
+ * all at syscall exit. However, this could delay the reporting of
+ * significant errors until syscall exit (or never, if the system
+ * halts). */
+unsigned int audit_serial(void)
+{
+ static atomic_t serial = ATOMIC_INIT(0xffffff);
+ unsigned int a, b;
+
+ do {
+ a = atomic_read(&serial);
+ if (atomic_dec_and_test(&serial))
+ atomic_set(&serial, 0xffffff);
+ b = atomic_read(&serial);
+ } while (b != a - 1);
+
+ return 0xffffff - b;
+}
+
+static inline void audit_get_stamp(struct audit_context *ctx,
+ struct timespec *t, unsigned int *serial)
+{
+ if (ctx)
+ auditsc_get_stamp(ctx, t, serial);
+ else {
+ *t = CURRENT_TIME;
+ *serial = audit_serial();
+ }
+}
/* Obtain an audit buffer. This routine does locking to obtain the
* audit buffer, but then no locking is required for calls to
@@ -615,10 +644,9 @@ __setup("audit=", audit_enable);
* syscall, then the syscall is marked as auditable and an audit record
* will be written at syscall exit. If there is no associated task, tsk
* should be NULL. */
-struct audit_buffer *audit_log_start(struct audit_context *ctx)
+struct audit_buffer *audit_log_start(struct audit_context *ctx, int type)
{
struct audit_buffer *ab = NULL;
- unsigned long flags;
struct timespec t;
unsigned int serial;
@@ -626,57 +654,48 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx)
return NULL;
if (audit_backlog_limit
- && atomic_read(&audit_backlog) > audit_backlog_limit) {
+ && skb_queue_len(&audit_skb_queue) > audit_backlog_limit) {
if (audit_rate_check())
printk(KERN_WARNING
"audit: audit_backlog=%d > "
"audit_backlog_limit=%d\n",
- atomic_read(&audit_backlog),
+ skb_queue_len(&audit_skb_queue),
audit_backlog_limit);
audit_log_lost("backlog limit exceeded");
return NULL;
}
- spin_lock_irqsave(&audit_freelist_lock, flags);
- if (!list_empty(&audit_freelist)) {
- ab = list_entry(audit_freelist.next,
- struct audit_buffer, list);
- list_del(&ab->list);
- --audit_freelist_count;
- }
- spin_unlock_irqrestore(&audit_freelist_lock, flags);
-
- if (!ab)
- ab = kmalloc(sizeof(*ab), GFP_ATOMIC);
+ ab = audit_buffer_alloc(ctx, GFP_ATOMIC, type);
if (!ab) {
audit_log_lost("out of memory in audit_log_start");
return NULL;
}
- atomic_inc(&audit_backlog);
- skb_queue_head_init(&ab->sklist);
-
- ab->ctx = ctx;
- ab->len = 0;
- ab->nlh = NULL;
- ab->total = 0;
- ab->type = AUDIT_KERNEL;
- ab->pid = 0;
+ audit_get_stamp(ab->ctx, &t, &serial);
-#ifdef CONFIG_AUDITSYSCALL
- if (ab->ctx)
- audit_get_stamp(ab->ctx, &t, &serial);
- else
-#endif
- {
- t = CURRENT_TIME;
- serial = 0;
- }
audit_log_format(ab, "audit(%lu.%03lu:%u): ",
t.tv_sec, t.tv_nsec/1000000, serial);
return ab;
}
+/**
+ * audit_expand - expand skb in the audit buffer
+ * @ab: audit_buffer
+ *
+ * Returns 0 (no space) on failed expansion, or available space if
+ * successful.
+ */
+static inline int audit_expand(struct audit_buffer *ab, int extra)
+{
+ struct sk_buff *skb = ab->skb;
+ int ret = pskb_expand_head(skb, skb_headroom(skb), extra,
+ GFP_ATOMIC);
+ if (ret < 0) {
+ audit_log_lost("out of memory in audit_expand");
+ return 0;
+ }
+ return skb_tailroom(skb);
+}
/* Format an audit message into the audit buffer. If there isn't enough
* room in the audit buffer, more room will be allocated and vsnprint
@@ -686,26 +705,35 @@ static void audit_log_vformat(struct audit_buffer *ab, const char *fmt,
va_list args)
{
int len, avail;
+ struct sk_buff *skb;
+ va_list args2;
if (!ab)
return;
- avail = sizeof(ab->tmp) - ab->len;
- if (avail <= 0) {
- audit_log_move(ab);
- avail = sizeof(ab->tmp) - ab->len;
+ BUG_ON(!ab->skb);
+ skb = ab->skb;
+ avail = skb_tailroom(skb);
+ if (avail == 0) {
+ avail = audit_expand(ab, AUDIT_BUFSIZ);
+ if (!avail)
+ goto out;
}
- len = vsnprintf(ab->tmp + ab->len, avail, fmt, args);
+ va_copy(args2, args);
+ len = vsnprintf(skb->tail, avail, fmt, args);
if (len >= avail) {
/* The printk buffer is 1024 bytes long, so if we get
* here and AUDIT_BUFSIZ is at least 1024, then we can
* log everything that printk could have logged. */
- audit_log_move(ab);
- avail = sizeof(ab->tmp) - ab->len;
- len = vsnprintf(ab->tmp + ab->len, avail, fmt, args);
+ avail = audit_expand(ab, max_t(unsigned, AUDIT_BUFSIZ, 1+len-avail));
+ if (!avail)
+ goto out;
+ len = vsnprintf(skb->tail, avail, fmt, args2);
}
- ab->len += (len < avail) ? len : avail;
- ab->total += (len < avail) ? len : avail;
+ if (len > 0)
+ skb_put(skb, len);
+out:
+ return;
}
/* Format a message into the audit buffer. All the work is done in
@@ -721,20 +749,47 @@ void audit_log_format(struct audit_buffer *ab, const char *fmt, ...)
va_end(args);
}
-void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf, size_t len)
+/* This function will take the passed buf and convert it into a string of
+ * ascii hex digits. The new string is placed onto the skb. */
+void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf,
+ size_t len)
{
- int i;
+ int i, avail, new_len;
+ unsigned char *ptr;
+ struct sk_buff *skb;
+ static const unsigned char *hex = "0123456789ABCDEF";
+
+ BUG_ON(!ab->skb);
+ skb = ab->skb;
+ avail = skb_tailroom(skb);
+ new_len = len<<1;
+ if (new_len >= avail) {
+ /* Round the buffer request up to the next multiple */
+ new_len = AUDIT_BUFSIZ*(((new_len-avail)/AUDIT_BUFSIZ) + 1);
+ avail = audit_expand(ab, new_len);
+ if (!avail)
+ return;
+ }
- for (i=0; i<len; i++)
- audit_log_format(ab, "%02x", buf[i]);
+ ptr = skb->tail;
+ for (i=0; i<len; i++) {
+ *ptr++ = hex[(buf[i] & 0xF0)>>4]; /* Upper nibble */
+ *ptr++ = hex[buf[i] & 0x0F]; /* Lower nibble */
+ }
+ *ptr = 0;
+ skb_put(skb, len << 1); /* new string is twice the old string */
}
+/* This code will escape a string that is passed to it if the string
+ * contains a control character, unprintable character, double quote mark,
+ * or a space. Unescaped strings will start and end with a double quote mark.
+ * Strings that are escaped are printed in hex (2 digits per char). */
void audit_log_untrustedstring(struct audit_buffer *ab, const char *string)
{
const unsigned char *p = string;
while (*p) {
- if (*p == '"' || *p == ' ' || *p < 0x20 || *p > 0x7f) {
+ if (*p == '"' || *p < 0x21 || *p > 0x7f) {
audit_log_hex(ab, string, strlen(string));
return;
}
@@ -743,117 +798,63 @@ void audit_log_untrustedstring(struct audit_buffer *ab, const char *string)
audit_log_format(ab, "\"%s\"", string);
}
-
-/* This is a helper-function to print the d_path without using a static
- * buffer or allocating another buffer in addition to the one in
- * audit_buffer. */
+/* This is a helper-function to print the escaped d_path */
void audit_log_d_path(struct audit_buffer *ab, const char *prefix,
struct dentry *dentry, struct vfsmount *vfsmnt)
{
- char *p;
- int len, avail;
+ char *p, *path;
- if (prefix) audit_log_format(ab, " %s", prefix);
-
- if (ab->len > 128)
- audit_log_move(ab);
- avail = sizeof(ab->tmp) - ab->len;
- p = d_path(dentry, vfsmnt, ab->tmp + ab->len, avail);
- if (IS_ERR(p)) {
- /* FIXME: can we save some information here? */
- audit_log_format(ab, "<toolong>");
- } else {
- /* path isn't at start of buffer */
- len = (ab->tmp + sizeof(ab->tmp) - 1) - p;
- memmove(ab->tmp + ab->len, p, len);
- ab->len += len;
- ab->total += len;
- }
-}
-
-/* Remove queued messages from the audit_txlist and send them to userspace. */
-static void audit_tasklet_handler(unsigned long arg)
-{
- LIST_HEAD(list);
- struct audit_buffer *ab;
- unsigned long flags;
+ if (prefix)
+ audit_log_format(ab, " %s", prefix);
- spin_lock_irqsave(&audit_txlist_lock, flags);
- list_splice_init(&audit_txlist, &list);
- spin_unlock_irqrestore(&audit_txlist_lock, flags);
-
- while (!list_empty(&list)) {
- ab = list_entry(list.next, struct audit_buffer, list);
- list_del(&ab->list);
- audit_log_end_fast(ab);
+ /* We will allow 11 spaces for ' (deleted)' to be appended */
+ path = kmalloc(PATH_MAX+11, GFP_KERNEL);
+ if (!path) {
+ audit_log_format(ab, "<no memory>");
+ return;
}
+ p = d_path(dentry, vfsmnt, path, PATH_MAX+11);
+ if (IS_ERR(p)) { /* Should never happen since we send PATH_MAX */
+ /* FIXME: can we save some information here? */
+ audit_log_format(ab, "<too long>");
+ } else
+ audit_log_untrustedstring(ab, p);
+ kfree(path);
}
-static DECLARE_TASKLET(audit_tasklet, audit_tasklet_handler, 0);
-
/* The netlink_* functions cannot be called inside an irq context, so
* the audit buffer is places on a queue and a tasklet is scheduled to
* remove them from the queue outside the irq context. May be called in
* any context. */
-static void audit_log_end_irq(struct audit_buffer *ab)
-{
- unsigned long flags;
-
- if (!ab)
- return;
- spin_lock_irqsave(&audit_txlist_lock, flags);
- list_add_tail(&ab->list, &audit_txlist);
- spin_unlock_irqrestore(&audit_txlist_lock, flags);
-
- tasklet_schedule(&audit_tasklet);
-}
-
-/* Send the message in the audit buffer directly to user space. May not
- * be called in an irq context. */
-static void audit_log_end_fast(struct audit_buffer *ab)
+void audit_log_end(struct audit_buffer *ab)
{
- unsigned long flags;
-
- BUG_ON(in_irq());
if (!ab)
return;
if (!audit_rate_check()) {
audit_log_lost("rate limit exceeded");
} else {
- audit_log_move(ab);
- if (audit_log_drain(ab))
- return;
+ if (audit_pid) {
+ struct nlmsghdr *nlh = (struct nlmsghdr *)ab->skb->data;
+ nlh->nlmsg_len = ab->skb->len - NLMSG_SPACE(0);
+ skb_queue_tail(&audit_skb_queue, ab->skb);
+ ab->skb = NULL;
+ wake_up_interruptible(&kauditd_wait);
+ } else {
+ printk("%s\n", ab->skb->data + NLMSG_SPACE(0));
+ }
}
-
- atomic_dec(&audit_backlog);
- spin_lock_irqsave(&audit_freelist_lock, flags);
- if (++audit_freelist_count > AUDIT_MAXFREE)
- kfree(ab);
- else
- list_add(&ab->list, &audit_freelist);
- spin_unlock_irqrestore(&audit_freelist_lock, flags);
-}
-
-/* Send or queue the message in the audit buffer, depending on the
- * current context. (A convenience function that may be called in any
- * context.) */
-void audit_log_end(struct audit_buffer *ab)
-{
- if (in_irq())
- audit_log_end_irq(ab);
- else
- audit_log_end_fast(ab);
+ audit_buffer_free(ab);
}
/* Log an audit record. This is a convenience function that calls
* audit_log_start, audit_log_vformat, and audit_log_end. It may be
* called in any context. */
-void audit_log(struct audit_context *ctx, const char *fmt, ...)
+void audit_log(struct audit_context *ctx, int type, const char *fmt, ...)
{
struct audit_buffer *ab;
va_list args;
- ab = audit_log_start(ctx);
+ ab = audit_log_start(ctx, type);
if (ab) {
va_start(args, fmt);
audit_log_vformat(ab, fmt, args);
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 37b3ac94bc4..e75f84e1a1a 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -34,7 +34,8 @@
#include <asm/types.h>
#include <linux/mm.h>
#include <linux/module.h>
-
+#include <linux/mount.h>
+#include <linux/socket.h>
#include <linux/audit.h>
#include <linux/personality.h>
#include <linux/time.h>
@@ -112,6 +113,23 @@ struct audit_aux_data_ipcctl {
mode_t mode;
};
+struct audit_aux_data_socketcall {
+ struct audit_aux_data d;
+ int nargs;
+ unsigned long args[0];
+};
+
+struct audit_aux_data_sockaddr {
+ struct audit_aux_data d;
+ int len;
+ char a[0];
+};
+
+struct audit_aux_data_path {
+ struct audit_aux_data d;
+ struct dentry *dentry;
+ struct vfsmount *mnt;
+};
/* The per-task audit context. */
struct audit_context {
@@ -127,6 +145,8 @@ struct audit_context {
int auditable; /* 1 if record should be written */
int name_count;
struct audit_names names[AUDIT_NAMES];
+ struct dentry * pwd;
+ struct vfsmount * pwdmnt;
struct audit_context *previous; /* For nested syscalls */
struct audit_aux_data *aux;
@@ -157,6 +177,8 @@ struct audit_entry {
struct audit_rule rule;
};
+extern int audit_pid;
+
/* Check to see if two rules are identical. It is called from
* audit_del_rule during AUDIT_DEL. */
static int audit_compare_rule(struct audit_rule *a, struct audit_rule *b)
@@ -226,7 +248,6 @@ static inline int audit_del_rule(struct audit_rule *rule,
return -EFAULT; /* No matching rule */
}
-#ifdef CONFIG_NET
/* Copy rule from user-space to kernel-space. Called during
* AUDIT_ADD. */
static int audit_copy_rule(struct audit_rule *d, struct audit_rule *s)
@@ -287,7 +308,8 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
err = audit_add_rule(entry, &audit_entlist);
if (!err && (flags & AUDIT_AT_EXIT))
err = audit_add_rule(entry, &audit_extlist);
- audit_log(NULL, "auid %u added an audit rule\n", loginuid);
+ audit_log(NULL, AUDIT_CONFIG_CHANGE,
+ "auid=%u added an audit rule\n", loginuid);
break;
case AUDIT_DEL:
flags =((struct audit_rule *)data)->flags;
@@ -297,7 +319,8 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
err = audit_del_rule(data, &audit_entlist);
if (!err && (flags & AUDIT_AT_EXIT))
err = audit_del_rule(data, &audit_extlist);
- audit_log(NULL, "auid %u removed an audit rule\n", loginuid);
+ audit_log(NULL, AUDIT_CONFIG_CHANGE,
+ "auid=%u removed an audit rule\n", loginuid);
break;
default:
return -EINVAL;
@@ -305,7 +328,6 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
return err;
}
-#endif
/* Compare a task_struct with an audit_rule. Return 1 on match, 0
* otherwise. */
@@ -444,7 +466,7 @@ static enum audit_state audit_filter_task(struct task_struct *tsk)
/* At syscall entry and exit time, this filter is called if the
* audit_state is not low enough that auditing cannot take place, but is
- * also not high enough that we already know we have to write and audit
+ * also not high enough that we already know we have to write an audit
* record (i.e., the state is AUDIT_SETUP_CONTEXT or AUDIT_BUILD_CONTEXT).
*/
static enum audit_state audit_filter_syscall(struct task_struct *tsk,
@@ -532,6 +554,12 @@ static inline void audit_free_names(struct audit_context *context)
if (context->names[i].name)
__putname(context->names[i].name);
context->name_count = 0;
+ if (context->pwd)
+ dput(context->pwd);
+ if (context->pwdmnt)
+ mntput(context->pwdmnt);
+ context->pwd = NULL;
+ context->pwdmnt = NULL;
}
static inline void audit_free_aux(struct audit_context *context)
@@ -539,6 +567,11 @@ static inline void audit_free_aux(struct audit_context *context)
struct audit_aux_data *aux;
while ((aux = context->aux)) {
+ if (aux->type == AUDIT_AVC_PATH) {
+ struct audit_aux_data_path *axi = (void *)aux;
+ dput(axi->dentry);
+ mntput(axi->mnt);
+ }
context->aux = aux->next;
kfree(aux);
}
@@ -625,7 +658,8 @@ static void audit_log_task_info(struct audit_buffer *ab)
struct vm_area_struct *vma;
get_task_comm(name, current);
- audit_log_format(ab, " comm=%s", name);
+ audit_log_format(ab, " comm=");
+ audit_log_untrustedstring(ab, name);
if (!mm)
return;
@@ -649,23 +683,24 @@ static void audit_log_exit(struct audit_context *context)
{
int i;
struct audit_buffer *ab;
+ struct audit_aux_data *aux;
- ab = audit_log_start(context);
+ ab = audit_log_start(context, AUDIT_SYSCALL);
if (!ab)
return; /* audit_panic has been called */
- audit_log_format(ab, "syscall=%d", context->major);
+ audit_log_format(ab, "arch=%x syscall=%d",
+ context->arch, context->major);
if (context->personality != PER_LINUX)
audit_log_format(ab, " per=%lx", context->personality);
- audit_log_format(ab, " arch=%x", context->arch);
if (context->return_valid)
audit_log_format(ab, " success=%s exit=%ld",
(context->return_valid==AUDITSC_SUCCESS)?"yes":"no",
context->return_code);
audit_log_format(ab,
" a0=%lx a1=%lx a2=%lx a3=%lx items=%d"
- " pid=%d loginuid=%d uid=%d gid=%d"
- " euid=%d suid=%d fsuid=%d"
- " egid=%d sgid=%d fsgid=%d",
+ " pid=%d auid=%u uid=%u gid=%u"
+ " euid=%u suid=%u fsuid=%u"
+ " egid=%u sgid=%u fsgid=%u",
context->argv[0],
context->argv[1],
context->argv[2],
@@ -679,33 +714,57 @@ static void audit_log_exit(struct audit_context *context)
context->egid, context->sgid, context->fsgid);
audit_log_task_info(ab);
audit_log_end(ab);
- while (context->aux) {
- struct audit_aux_data *aux;
- ab = audit_log_start(context);
+ for (aux = context->aux; aux; aux = aux->next) {
+
+ ab = audit_log_start(context, aux->type);
if (!ab)
continue; /* audit_panic has been called */
- aux = context->aux;
- context->aux = aux->next;
-
- audit_log_format(ab, "auxitem=%d", aux->type);
switch (aux->type) {
- case AUDIT_AUX_IPCPERM: {
+ case AUDIT_IPC: {
struct audit_aux_data_ipcctl *axi = (void *)aux;
audit_log_format(ab,
- " qbytes=%lx uid=%d gid=%d mode=%x",
+ " qbytes=%lx iuid=%u igid=%u mode=%x",
axi->qbytes, axi->uid, axi->gid, axi->mode);
- }
+ break; }
+
+ case AUDIT_SOCKETCALL: {
+ int i;
+ struct audit_aux_data_socketcall *axs = (void *)aux;
+ audit_log_format(ab, "nargs=%d", axs->nargs);
+ for (i=0; i<axs->nargs; i++)
+ audit_log_format(ab, " a%d=%lx", i, axs->args[i]);
+ break; }
+
+ case AUDIT_SOCKADDR: {
+ struct audit_aux_data_sockaddr *axs = (void *)aux;
+
+ audit_log_format(ab, "saddr=");
+ audit_log_hex(ab, axs->a, axs->len);
+ break; }
+
+ case AUDIT_AVC_PATH: {
+ struct audit_aux_data_path *axi = (void *)aux;
+ audit_log_d_path(ab, "path=", axi->dentry, axi->mnt);
+ break; }
+
}
audit_log_end(ab);
- kfree(aux);
}
+ if (context->pwd && context->pwdmnt) {
+ ab = audit_log_start(context, AUDIT_CWD);
+ if (ab) {
+ audit_log_d_path(ab, "cwd=", context->pwd, context->pwdmnt);
+ audit_log_end(ab);
+ }
+ }
for (i = 0; i < context->name_count; i++) {
- ab = audit_log_start(context);
+ ab = audit_log_start(context, AUDIT_PATH);
if (!ab)
continue; /* audit_panic has been called */
+
audit_log_format(ab, "item=%d", i);
if (context->names[i].name) {
audit_log_format(ab, " name=");
@@ -713,7 +772,7 @@ static void audit_log_exit(struct audit_context *context)
}
if (context->names[i].ino != (unsigned long)-1)
audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#o"
- " uid=%d gid=%d rdev=%02x:%02x",
+ " ouid=%u ogid=%u rdev=%02x:%02x",
context->names[i].ino,
MAJOR(context->names[i].dev),
MINOR(context->names[i].dev),
@@ -741,42 +800,12 @@ void audit_free(struct task_struct *tsk)
/* Check for system calls that do not go through the exit
* function (e.g., exit_group), then free context block. */
- if (context->in_syscall && context->auditable)
+ if (context->in_syscall && context->auditable && context->pid != audit_pid)
audit_log_exit(context);
audit_free_context(context);
}
-/* Compute a serial number for the audit record. Audit records are
- * written to user-space as soon as they are generated, so a complete
- * audit record may be written in several pieces. The timestamp of the
- * record and this serial number are used by the user-space daemon to
- * determine which pieces belong to the same audit record. The
- * (timestamp,serial) tuple is unique for each syscall and is live from
- * syscall entry to syscall exit.
- *
- * Atomic values are only guaranteed to be 24-bit, so we count down.
- *
- * NOTE: Another possibility is to store the formatted records off the
- * audit context (for those records that have a context), and emit them
- * all at syscall exit. However, this could delay the reporting of
- * significant errors until syscall exit (or never, if the system
- * halts). */
-static inline unsigned int audit_serial(void)
-{
- static atomic_t serial = ATOMIC_INIT(0xffffff);
- unsigned int a, b;
-
- do {
- a = atomic_read(&serial);
- if (atomic_dec_and_test(&serial))
- atomic_set(&serial, 0xffffff);
- b = atomic_read(&serial);
- } while (b != a - 1);
-
- return 0xffffff - b;
-}
-
/* Fill in audit context at syscall entry. This only happens if the
* audit context was created when the task was created and the state or
* filters demand the audit context be built. If the state from the
@@ -876,7 +905,7 @@ void audit_syscall_exit(struct task_struct *tsk, int valid, long return_code)
if (likely(!context))
return;
- if (context->in_syscall && context->auditable)
+ if (context->in_syscall && context->auditable && context->pid != audit_pid)
audit_log_exit(context);
context->in_syscall = 0;
@@ -916,6 +945,13 @@ void audit_getname(const char *name)
context->names[context->name_count].name = name;
context->names[context->name_count].ino = (unsigned long)-1;
++context->name_count;
+ if (!context->pwd) {
+ read_lock(&current->fs->lock);
+ context->pwd = dget(current->fs->pwd);
+ context->pwdmnt = mntget(current->fs->pwdmnt);
+ read_unlock(&current->fs->lock);
+ }
+
}
/* Intercept a putname request. Called from
@@ -994,34 +1030,26 @@ void audit_inode(const char *name, const struct inode *inode)
context->names[idx].rdev = inode->i_rdev;
}
-void audit_get_stamp(struct audit_context *ctx,
- struct timespec *t, unsigned int *serial)
+void auditsc_get_stamp(struct audit_context *ctx,
+ struct timespec *t, unsigned int *serial)
{
- if (ctx) {
- t->tv_sec = ctx->ctime.tv_sec;
- t->tv_nsec = ctx->ctime.tv_nsec;
- *serial = ctx->serial;
- ctx->auditable = 1;
- } else {
- *t = CURRENT_TIME;
- *serial = 0;
- }
+ t->tv_sec = ctx->ctime.tv_sec;
+ t->tv_nsec = ctx->ctime.tv_nsec;
+ *serial = ctx->serial;
+ ctx->auditable = 1;
}
-extern int audit_set_type(struct audit_buffer *ab, int type);
-
int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
{
if (task->audit_context) {
struct audit_buffer *ab;
- ab = audit_log_start(NULL);
+ ab = audit_log_start(NULL, AUDIT_LOGIN);
if (ab) {
audit_log_format(ab, "login pid=%d uid=%u "
- "old loginuid=%u new loginuid=%u",
+ "old auid=%u new auid=%u",
task->pid, task->uid,
task->audit_context->loginuid, loginuid);
- audit_set_type(ab, AUDIT_LOGIN);
audit_log_end(ab);
}
task->audit_context->loginuid = loginuid;
@@ -1051,8 +1079,89 @@ int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
ax->gid = gid;
ax->mode = mode;
- ax->d.type = AUDIT_AUX_IPCPERM;
+ ax->d.type = AUDIT_IPC;
+ ax->d.next = context->aux;
+ context->aux = (void *)ax;
+ return 0;
+}
+
+int audit_socketcall(int nargs, unsigned long *args)
+{
+ struct audit_aux_data_socketcall *ax;
+ struct audit_context *context = current->audit_context;
+
+ if (likely(!context))
+ return 0;
+
+ ax = kmalloc(sizeof(*ax) + nargs * sizeof(unsigned long), GFP_KERNEL);
+ if (!ax)
+ return -ENOMEM;
+
+ ax->nargs = nargs;
+ memcpy(ax->args, args, nargs * sizeof(unsigned long));
+
+ ax->d.type = AUDIT_SOCKETCALL;
+ ax->d.next = context->aux;
+ context->aux = (void *)ax;
+ return 0;
+}
+
+int audit_sockaddr(int len, void *a)
+{
+ struct audit_aux_data_sockaddr *ax;
+ struct audit_context *context = current->audit_context;
+
+ if (likely(!context))
+ return 0;
+
+ ax = kmalloc(sizeof(*ax) + len, GFP_KERNEL);
+ if (!ax)
+ return -ENOMEM;
+
+ ax->len = len;
+ memcpy(ax->a, a, len);
+
+ ax->d.type = AUDIT_SOCKADDR;
ax->d.next = context->aux;
context->aux = (void *)ax;
return 0;
}
+
+int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt)
+{
+ struct audit_aux_data_path *ax;
+ struct audit_context *context = current->audit_context;
+
+ if (likely(!context))
+ return 0;
+
+ ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
+ if (!ax)
+ return -ENOMEM;
+
+ ax->dentry = dget(dentry);
+ ax->mnt = mntget(mnt);
+
+ ax->d.type = AUDIT_AVC_PATH;
+ ax->d.next = context->aux;
+ context->aux = (void *)ax;
+ return 0;
+}
+
+void audit_signal_info(int sig, struct task_struct *t)
+{
+ extern pid_t audit_sig_pid;
+ extern uid_t audit_sig_uid;
+
+ if (unlikely(audit_pid && t->pid == audit_pid)) {
+ if (sig == SIGTERM || sig == SIGHUP) {
+ struct audit_context *ctx = current->audit_context;
+ audit_sig_pid = current->pid;
+ if (ctx)
+ audit_sig_uid = ctx->loginuid;
+ else
+ audit_sig_uid = current->uid;
+ }
+ }
+}
+
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 628f4ccda12..53d8263ae12 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -63,19 +63,15 @@ static int take_cpu_down(void *unused)
{
int err;
- /* Take offline: makes arch_cpu_down somewhat easier. */
- cpu_clear(smp_processor_id(), cpu_online_map);
-
/* Ensure this CPU doesn't handle any more interrupts. */
err = __cpu_disable();
if (err < 0)
- cpu_set(smp_processor_id(), cpu_online_map);
- else
- /* Force idle task to run as soon as we yield: it should
- immediately notice cpu is offline and die quickly. */
- sched_idle_next();
+ return err;
- return err;
+ /* Force idle task to run as soon as we yield: it should
+ immediately notice cpu is offline and die quickly. */
+ sched_idle_next();
+ return 0;
}
int cpu_down(unsigned int cpu)
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 961d74044de..984c0bf3807 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -166,9 +166,8 @@ static struct super_block *cpuset_sb = NULL;
* The hooks from fork and exit, cpuset_fork() and cpuset_exit(), don't
* (usually) grab cpuset_sem. These are the two most performance
* critical pieces of code here. The exception occurs on exit(),
- * if the last task using a cpuset exits, and the cpuset was marked
- * notify_on_release. In that case, the cpuset_sem is taken, the
- * path to the released cpuset calculated, and a usermode call made
+ * when a task in a notify_on_release cpuset exits. Then cpuset_sem
+ * is taken, and if the cpuset count is zero, a usermode call made
* to /sbin/cpuset_release_agent with the name of the cpuset (path
* relative to the root of cpuset file system) as the argument.
*
@@ -229,13 +228,7 @@ static struct dentry_operations cpuset_dops = {
static struct dentry *cpuset_get_dentry(struct dentry *parent, const char *name)
{
- struct qstr qstr;
- struct dentry *d;
-
- qstr.name = name;
- qstr.len = strlen(name);
- qstr.hash = full_name_hash(name, qstr.len);
- d = lookup_hash(&qstr, parent);
+ struct dentry *d = lookup_one_len(name, parent, strlen(name));
if (!IS_ERR(d))
d->d_op = &cpuset_dops;
return d;
@@ -602,10 +595,62 @@ static int validate_change(const struct cpuset *cur, const struct cpuset *trial)
return 0;
}
+/*
+ * For a given cpuset cur, partition the system as follows
+ * a. All cpus in the parent cpuset's cpus_allowed that are not part of any
+ * exclusive child cpusets
+ * b. All cpus in the current cpuset's cpus_allowed that are not part of any
+ * exclusive child cpusets
+ * Build these two partitions by calling partition_sched_domains
+ *
+ * Call with cpuset_sem held. May nest a call to the
+ * lock_cpu_hotplug()/unlock_cpu_hotplug() pair.
+ */
+static void update_cpu_domains(struct cpuset *cur)
+{
+ struct cpuset *c, *par = cur->parent;
+ cpumask_t pspan, cspan;
+
+ if (par == NULL || cpus_empty(cur->cpus_allowed))
+ return;
+
+ /*
+ * Get all cpus from parent's cpus_allowed not part of exclusive
+ * children
+ */
+ pspan = par->cpus_allowed;
+ list_for_each_entry(c, &par->children, sibling) {
+ if (is_cpu_exclusive(c))
+ cpus_andnot(pspan, pspan, c->cpus_allowed);
+ }
+ if (is_removed(cur) || !is_cpu_exclusive(cur)) {
+ cpus_or(pspan, pspan, cur->cpus_allowed);
+ if (cpus_equal(pspan, cur->cpus_allowed))
+ return;
+ cspan = CPU_MASK_NONE;
+ } else {
+ if (cpus_empty(pspan))
+ return;
+ cspan = cur->cpus_allowed;
+ /*
+ * Get all cpus from current cpuset's cpus_allowed not part
+ * of exclusive children
+ */
+ list_for_each_entry(c, &cur->children, sibling) {
+ if (is_cpu_exclusive(c))
+ cpus_andnot(cspan, cspan, c->cpus_allowed);
+ }
+ }
+
+ lock_cpu_hotplug();
+ partition_sched_domains(&pspan, &cspan);
+ unlock_cpu_hotplug();
+}
+
static int update_cpumask(struct cpuset *cs, char *buf)
{
struct cpuset trialcs;
- int retval;
+ int retval, cpus_unchanged;
trialcs = *cs;
retval = cpulist_parse(buf, trialcs.cpus_allowed);
@@ -615,9 +660,13 @@ static int update_cpumask(struct cpuset *cs, char *buf)
if (cpus_empty(trialcs.cpus_allowed))
return -ENOSPC;
retval = validate_change(cs, &trialcs);
- if (retval == 0)
- cs->cpus_allowed = trialcs.cpus_allowed;
- return retval;
+ if (retval < 0)
+ return retval;
+ cpus_unchanged = cpus_equal(cs->cpus_allowed, trialcs.cpus_allowed);
+ cs->cpus_allowed = trialcs.cpus_allowed;
+ if (is_cpu_exclusive(cs) && !cpus_unchanged)
+ update_cpu_domains(cs);
+ return 0;
}
static int update_nodemask(struct cpuset *cs, char *buf)
@@ -653,7 +702,7 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf)
{
int turning_on;
struct cpuset trialcs;
- int err;
+ int err, cpu_exclusive_changed;
turning_on = (simple_strtoul(buf, NULL, 10) != 0);
@@ -664,13 +713,18 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf)
clear_bit(bit, &trialcs.flags);
err = validate_change(cs, &trialcs);
- if (err == 0) {
- if (turning_on)
- set_bit(bit, &cs->flags);
- else
- clear_bit(bit, &cs->flags);
- }
- return err;
+ if (err < 0)
+ return err;
+ cpu_exclusive_changed =
+ (is_cpu_exclusive(cs) != is_cpu_exclusive(&trialcs));
+ if (turning_on)
+ set_bit(bit, &cs->flags);
+ else
+ clear_bit(bit, &cs->flags);
+
+ if (cpu_exclusive_changed)
+ update_cpu_domains(cs);
+ return 0;
}
static int attach_task(struct cpuset *cs, char *buf)
@@ -1316,12 +1370,14 @@ static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry)
up(&cpuset_sem);
return -EBUSY;
}
- spin_lock(&cs->dentry->d_lock);
parent = cs->parent;
set_bit(CS_REMOVED, &cs->flags);
+ if (is_cpu_exclusive(cs))
+ update_cpu_domains(cs);
list_del(&cs->sibling); /* delete my sibling from parent->children */
if (list_empty(&parent->children))
check_for_release(parent);
+ spin_lock(&cs->dentry->d_lock);
d = dget(cs->dentry);
cs->dentry = NULL;
spin_unlock(&d->d_lock);
@@ -1404,6 +1460,18 @@ void cpuset_fork(struct task_struct *tsk)
*
* Description: Detach cpuset from @tsk and release it.
*
+ * Note that cpusets marked notify_on_release force every task
+ * in them to take the global cpuset_sem semaphore when exiting.
+ * This could impact scaling on very large systems. Be reluctant
+ * to use notify_on_release cpusets where very high task exit
+ * scaling is required on large systems.
+ *
+ * Don't even think about derefencing 'cs' after the cpuset use
+ * count goes to zero, except inside a critical section guarded
+ * by the cpuset_sem semaphore. If you don't hold cpuset_sem,
+ * then a zero cpuset use count is a license to any other task to
+ * nuke the cpuset immediately.
+ *
**/
void cpuset_exit(struct task_struct *tsk)
@@ -1415,10 +1483,13 @@ void cpuset_exit(struct task_struct *tsk)
tsk->cpuset = NULL;
task_unlock(tsk);
- if (atomic_dec_and_test(&cs->count)) {
+ if (notify_on_release(cs)) {
down(&cpuset_sem);
- check_for_release(cs);
+ if (atomic_dec_and_test(&cs->count))
+ check_for_release(cs);
up(&cpuset_sem);
+ } else {
+ atomic_dec(&cs->count);
}
}
diff --git a/kernel/crash_dump.c b/kernel/crash_dump.c
new file mode 100644
index 00000000000..459ba49e376
--- /dev/null
+++ b/kernel/crash_dump.c
@@ -0,0 +1,52 @@
+/*
+ * kernel/crash_dump.c - Memory preserving reboot related code.
+ *
+ * Created by: Hariprasad Nellitheertha (hari@in.ibm.com)
+ * Copyright (C) IBM Corporation, 2004. All rights reserved
+ */
+
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
+#include <linux/bootmem.h>
+#include <linux/highmem.h>
+#include <linux/crash_dump.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+/* Stores the physical address of elf header of crash image. */
+unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
+
+/*
+ * Copy a page from "oldmem". For this page, there is no pte mapped
+ * in the current kernel. We stitch up a pte, similar to kmap_atomic.
+ */
+ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
+ size_t csize, unsigned long offset, int userbuf)
+{
+ void *page, *vaddr;
+
+ if (!csize)
+ return 0;
+
+ page = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+
+ vaddr = kmap_atomic_pfn(pfn, KM_PTE0);
+ copy_page(page, vaddr);
+ kunmap_atomic(vaddr, KM_PTE0);
+
+ if (userbuf) {
+ if (copy_to_user(buf, (page + offset), csize)) {
+ kfree(page);
+ return -EFAULT;
+ }
+ } else {
+ memcpy(buf, (page + offset), csize);
+ }
+
+ kfree(page);
+ return csize;
+}
diff --git a/kernel/exit.c b/kernel/exit.c
index edaa50b5bbf..3ebcd60a19c 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -72,6 +72,11 @@ repeat:
BUG_ON(!list_empty(&p->ptrace_list) || !list_empty(&p->ptrace_children));
__exit_signal(p);
__exit_sighand(p);
+ /*
+ * Note that the fastpath in sys_times depends on __exit_signal having
+ * updated the counters before a task is removed from the tasklist of
+ * the process by __unhash_process.
+ */
__unhash_process(p);
/*
@@ -793,6 +798,17 @@ fastcall NORET_TYPE void do_exit(long code)
ptrace_notify((PTRACE_EVENT_EXIT << 8) | SIGTRAP);
}
+ /*
+ * We're taking recursive faults here in do_exit. Safest is to just
+ * leave this task alone and wait for reboot.
+ */
+ if (unlikely(tsk->flags & PF_EXITING)) {
+ printk(KERN_ALERT
+ "Fixing recursive fault but reboot is needed!\n");
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule();
+ }
+
tsk->flags |= PF_EXITING;
/*
@@ -811,10 +827,8 @@ fastcall NORET_TYPE void do_exit(long code)
acct_update_integrals(tsk);
update_mem_hiwater(tsk);
group_dead = atomic_dec_and_test(&tsk->signal->live);
- if (group_dead) {
- del_timer_sync(&tsk->signal->real_timer);
+ if (group_dead)
acct_process(code);
- }
exit_mm(tsk);
exit_sem(tsk);
diff --git a/kernel/fork.c b/kernel/fork.c
index f42a17f8869..2c7806873bf 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -194,6 +194,7 @@ static inline int dup_mmap(struct mm_struct * mm, struct mm_struct * oldmm)
mm->mmap = NULL;
mm->mmap_cache = NULL;
mm->free_area_cache = oldmm->mmap_base;
+ mm->cached_hole_size = ~0UL;
mm->map_count = 0;
set_mm_counter(mm, rss, 0);
set_mm_counter(mm, anon_rss, 0);
@@ -249,8 +250,9 @@ static inline int dup_mmap(struct mm_struct * mm, struct mm_struct * oldmm)
/*
* Link in the new vma and copy the page table entries:
- * link in first so that swapoff can see swap entries,
- * and try_to_unmap_one's find_vma find the new vma.
+ * link in first so that swapoff can see swap entries.
+ * Note that, exceptionally, here the vma is inserted
+ * without holding mm->mmap_sem.
*/
spin_lock(&mm->page_table_lock);
*pprev = tmp;
@@ -322,6 +324,7 @@ static struct mm_struct * mm_init(struct mm_struct * mm)
mm->ioctx_list = NULL;
mm->default_kioctx = (struct kioctx)INIT_KIOCTX(mm->default_kioctx, *mm);
mm->free_area_cache = TASK_UNMAPPED_BASE;
+ mm->cached_hole_size = ~0UL;
if (likely(!mm_alloc_pgd(mm))) {
mm->def_flags = 0;
@@ -1000,9 +1003,6 @@ static task_t *copy_process(unsigned long clone_flags,
p->pdeath_signal = 0;
p->exit_state = 0;
- /* Perform scheduler related setup */
- sched_fork(p);
-
/*
* Ok, make it visible to the rest of the system.
* We dont wake it up yet.
@@ -1011,18 +1011,24 @@ static task_t *copy_process(unsigned long clone_flags,
INIT_LIST_HEAD(&p->ptrace_children);
INIT_LIST_HEAD(&p->ptrace_list);
+ /* Perform scheduler related setup. Assign this task to a CPU. */
+ sched_fork(p, clone_flags);
+
/* Need tasklist lock for parent etc handling! */
write_lock_irq(&tasklist_lock);
/*
- * The task hasn't been attached yet, so cpus_allowed mask cannot
- * have changed. The cpus_allowed mask of the parent may have
- * changed after it was copied first time, and it may then move to
- * another CPU - so we re-copy it here and set the child's CPU to
- * the parent's CPU. This avoids alot of nasty races.
+ * The task hasn't been attached yet, so its cpus_allowed mask will
+ * not be changed, nor will its assigned CPU.
+ *
+ * The cpus_allowed mask of the parent may have changed after it was
+ * copied first time - so re-copy it here, then check the child's CPU
+ * to ensure it is on a valid CPU (and if not, just force it back to
+ * parent's CPU). This avoids alot of nasty races.
*/
p->cpus_allowed = current->cpus_allowed;
- set_task_cpu(p, smp_processor_id());
+ if (unlikely(!cpu_isset(task_cpu(p), p->cpus_allowed)))
+ set_task_cpu(p, smp_processor_id());
/*
* Check for pending SIGKILL! The new thread should not be allowed
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index 2fb0e46e11f..436c7d93c00 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -30,6 +30,7 @@
*/
irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = {
[0 ... NR_IRQS-1] = {
+ .status = IRQ_DISABLED,
.handler = &no_irq_type,
.lock = SPIN_LOCK_UNLOCKED
}
@@ -118,8 +119,6 @@ fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs *regs)
*/
desc->handler->ack(irq);
action_ret = handle_IRQ_event(irq, regs, desc->action);
- if (!noirqdebug)
- note_interrupt(irq, desc, action_ret);
desc->handler->end(irq);
return 1;
}
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 5202e4c4a5b..ac670098570 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -6,6 +6,7 @@
* This file contains driver APIs to the irq subsystem.
*/
+#include <linux/config.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/random.h>
@@ -255,6 +256,13 @@ void free_irq(unsigned int irq, void *dev_id)
/* Found it - now remove it from the list of entries */
*pp = action->next;
+
+ /* Currently used only by UML, might disappear one day.*/
+#ifdef CONFIG_IRQ_RELEASE_METHOD
+ if (desc->handler->release)
+ desc->handler->release(irq, dev_id);
+#endif
+
if (!desc->action) {
desc->status |= IRQ_DISABLED;
if (desc->handler->shutdown)
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c
index f6297c30690..ba039e827d5 100644
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -45,7 +45,7 @@ __report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
}
}
-void report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
+static void report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
{
static int count = 100;
diff --git a/kernel/kexec.c b/kernel/kexec.c
new file mode 100644
index 00000000000..7843548cf2d
--- /dev/null
+++ b/kernel/kexec.c
@@ -0,0 +1,1063 @@
+/*
+ * kexec.c - kexec system call
+ * Copyright (C) 2002-2004 Eric Biederman <ebiederm@xmission.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/mm.h>
+#include <linux/file.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/kexec.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/highmem.h>
+#include <linux/syscalls.h>
+#include <linux/reboot.h>
+#include <linux/syscalls.h>
+#include <linux/ioport.h>
+#include <linux/hardirq.h>
+
+#include <asm/page.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/semaphore.h>
+
+/* Location of the reserved area for the crash kernel */
+struct resource crashk_res = {
+ .name = "Crash kernel",
+ .start = 0,
+ .end = 0,
+ .flags = IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+int kexec_should_crash(struct task_struct *p)
+{
+ if (in_interrupt() || !p->pid || p->pid == 1 || panic_on_oops)
+ return 1;
+ return 0;
+}
+
+/*
+ * When kexec transitions to the new kernel there is a one-to-one
+ * mapping between physical and virtual addresses. On processors
+ * where you can disable the MMU this is trivial, and easy. For
+ * others it is still a simple predictable page table to setup.
+ *
+ * In that environment kexec copies the new kernel to its final
+ * resting place. This means I can only support memory whose
+ * physical address can fit in an unsigned long. In particular
+ * addresses where (pfn << PAGE_SHIFT) > ULONG_MAX cannot be handled.
+ * If the assembly stub has more restrictive requirements
+ * KEXEC_SOURCE_MEMORY_LIMIT and KEXEC_DEST_MEMORY_LIMIT can be
+ * defined more restrictively in <asm/kexec.h>.
+ *
+ * The code for the transition from the current kernel to the
+ * the new kernel is placed in the control_code_buffer, whose size
+ * is given by KEXEC_CONTROL_CODE_SIZE. In the best case only a single
+ * page of memory is necessary, but some architectures require more.
+ * Because this memory must be identity mapped in the transition from
+ * virtual to physical addresses it must live in the range
+ * 0 - TASK_SIZE, as only the user space mappings are arbitrarily
+ * modifiable.
+ *
+ * The assembly stub in the control code buffer is passed a linked list
+ * of descriptor pages detailing the source pages of the new kernel,
+ * and the destination addresses of those source pages. As this data
+ * structure is not used in the context of the current OS, it must
+ * be self-contained.
+ *
+ * The code has been made to work with highmem pages and will use a
+ * destination page in its final resting place (if it happens
+ * to allocate it). The end product of this is that most of the
+ * physical address space, and most of RAM can be used.
+ *
+ * Future directions include:
+ * - allocating a page table with the control code buffer identity
+ * mapped, to simplify machine_kexec and make kexec_on_panic more
+ * reliable.
+ */
+
+/*
+ * KIMAGE_NO_DEST is an impossible destination address..., for
+ * allocating pages whose destination address we do not care about.
+ */
+#define KIMAGE_NO_DEST (-1UL)
+
+static int kimage_is_destination_range(struct kimage *image,
+ unsigned long start, unsigned long end);
+static struct page *kimage_alloc_page(struct kimage *image,
+ unsigned int gfp_mask,
+ unsigned long dest);
+
+static int do_kimage_alloc(struct kimage **rimage, unsigned long entry,
+ unsigned long nr_segments,
+ struct kexec_segment __user *segments)
+{
+ size_t segment_bytes;
+ struct kimage *image;
+ unsigned long i;
+ int result;
+
+ /* Allocate a controlling structure */
+ result = -ENOMEM;
+ image = kmalloc(sizeof(*image), GFP_KERNEL);
+ if (!image)
+ goto out;
+
+ memset(image, 0, sizeof(*image));
+ image->head = 0;
+ image->entry = &image->head;
+ image->last_entry = &image->head;
+ image->control_page = ~0; /* By default this does not apply */
+ image->start = entry;
+ image->type = KEXEC_TYPE_DEFAULT;
+
+ /* Initialize the list of control pages */
+ INIT_LIST_HEAD(&image->control_pages);
+
+ /* Initialize the list of destination pages */
+ INIT_LIST_HEAD(&image->dest_pages);
+
+ /* Initialize the list of unuseable pages */
+ INIT_LIST_HEAD(&image->unuseable_pages);
+
+ /* Read in the segments */
+ image->nr_segments = nr_segments;
+ segment_bytes = nr_segments * sizeof(*segments);
+ result = copy_from_user(image->segment, segments, segment_bytes);
+ if (result)
+ goto out;
+
+ /*
+ * Verify we have good destination addresses. The caller is
+ * responsible for making certain we don't attempt to load
+ * the new image into invalid or reserved areas of RAM. This
+ * just verifies it is an address we can use.
+ *
+ * Since the kernel does everything in page size chunks ensure
+ * the destination addreses are page aligned. Too many
+ * special cases crop of when we don't do this. The most
+ * insidious is getting overlapping destination addresses
+ * simply because addresses are changed to page size
+ * granularity.
+ */
+ result = -EADDRNOTAVAIL;
+ for (i = 0; i < nr_segments; i++) {
+ unsigned long mstart, mend;
+
+ mstart = image->segment[i].mem;
+ mend = mstart + image->segment[i].memsz;
+ if ((mstart & ~PAGE_MASK) || (mend & ~PAGE_MASK))
+ goto out;
+ if (mend >= KEXEC_DESTINATION_MEMORY_LIMIT)
+ goto out;
+ }
+
+ /* Verify our destination addresses do not overlap.
+ * If we alloed overlapping destination addresses
+ * through very weird things can happen with no
+ * easy explanation as one segment stops on another.
+ */
+ result = -EINVAL;
+ for (i = 0; i < nr_segments; i++) {
+ unsigned long mstart, mend;
+ unsigned long j;
+
+ mstart = image->segment[i].mem;
+ mend = mstart + image->segment[i].memsz;
+ for (j = 0; j < i; j++) {
+ unsigned long pstart, pend;
+ pstart = image->segment[j].mem;
+ pend = pstart + image->segment[j].memsz;
+ /* Do the segments overlap ? */
+ if ((mend > pstart) && (mstart < pend))
+ goto out;
+ }
+ }
+
+ /* Ensure our buffer sizes are strictly less than
+ * our memory sizes. This should always be the case,
+ * and it is easier to check up front than to be surprised
+ * later on.
+ */
+ result = -EINVAL;
+ for (i = 0; i < nr_segments; i++) {
+ if (image->segment[i].bufsz > image->segment[i].memsz)
+ goto out;
+ }
+
+ result = 0;
+out:
+ if (result == 0)
+ *rimage = image;
+ else
+ kfree(image);
+
+ return result;
+
+}
+
+static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry,
+ unsigned long nr_segments,
+ struct kexec_segment __user *segments)
+{
+ int result;
+ struct kimage *image;
+
+ /* Allocate and initialize a controlling structure */
+ image = NULL;
+ result = do_kimage_alloc(&image, entry, nr_segments, segments);
+ if (result)
+ goto out;
+
+ *rimage = image;
+
+ /*
+ * Find a location for the control code buffer, and add it
+ * the vector of segments so that it's pages will also be
+ * counted as destination pages.
+ */
+ result = -ENOMEM;
+ image->control_code_page = kimage_alloc_control_pages(image,
+ get_order(KEXEC_CONTROL_CODE_SIZE));
+ if (!image->control_code_page) {
+ printk(KERN_ERR "Could not allocate control_code_buffer\n");
+ goto out;
+ }
+
+ result = 0;
+ out:
+ if (result == 0)
+ *rimage = image;
+ else
+ kfree(image);
+
+ return result;
+}
+
+static int kimage_crash_alloc(struct kimage **rimage, unsigned long entry,
+ unsigned long nr_segments,
+ struct kexec_segment *segments)
+{
+ int result;
+ struct kimage *image;
+ unsigned long i;
+
+ image = NULL;
+ /* Verify we have a valid entry point */
+ if ((entry < crashk_res.start) || (entry > crashk_res.end)) {
+ result = -EADDRNOTAVAIL;
+ goto out;
+ }
+
+ /* Allocate and initialize a controlling structure */
+ result = do_kimage_alloc(&image, entry, nr_segments, segments);
+ if (result)
+ goto out;
+
+ /* Enable the special crash kernel control page
+ * allocation policy.
+ */
+ image->control_page = crashk_res.start;
+ image->type = KEXEC_TYPE_CRASH;
+
+ /*
+ * Verify we have good destination addresses. Normally
+ * the caller is responsible for making certain we don't
+ * attempt to load the new image into invalid or reserved
+ * areas of RAM. But crash kernels are preloaded into a
+ * reserved area of ram. We must ensure the addresses
+ * are in the reserved area otherwise preloading the
+ * kernel could corrupt things.
+ */
+ result = -EADDRNOTAVAIL;
+ for (i = 0; i < nr_segments; i++) {
+ unsigned long mstart, mend;
+
+ mstart = image->segment[i].mem;
+ mend = mstart + image->segment[i].memsz - 1;
+ /* Ensure we are within the crash kernel limits */
+ if ((mstart < crashk_res.start) || (mend > crashk_res.end))
+ goto out;
+ }
+
+ /*
+ * Find a location for the control code buffer, and add
+ * the vector of segments so that it's pages will also be
+ * counted as destination pages.
+ */
+ result = -ENOMEM;
+ image->control_code_page = kimage_alloc_control_pages(image,
+ get_order(KEXEC_CONTROL_CODE_SIZE));
+ if (!image->control_code_page) {
+ printk(KERN_ERR "Could not allocate control_code_buffer\n");
+ goto out;
+ }
+
+ result = 0;
+out:
+ if (result == 0)
+ *rimage = image;
+ else
+ kfree(image);
+
+ return result;
+}
+
+static int kimage_is_destination_range(struct kimage *image,
+ unsigned long start,
+ unsigned long end)
+{
+ unsigned long i;
+
+ for (i = 0; i < image->nr_segments; i++) {
+ unsigned long mstart, mend;
+
+ mstart = image->segment[i].mem;
+ mend = mstart + image->segment[i].memsz;
+ if ((end > mstart) && (start < mend))
+ return 1;
+ }
+
+ return 0;
+}
+
+static struct page *kimage_alloc_pages(unsigned int gfp_mask,
+ unsigned int order)
+{
+ struct page *pages;
+
+ pages = alloc_pages(gfp_mask, order);
+ if (pages) {
+ unsigned int count, i;
+ pages->mapping = NULL;
+ pages->private = order;
+ count = 1 << order;
+ for (i = 0; i < count; i++)
+ SetPageReserved(pages + i);
+ }
+
+ return pages;
+}
+
+static void kimage_free_pages(struct page *page)
+{
+ unsigned int order, count, i;
+
+ order = page->private;
+ count = 1 << order;
+ for (i = 0; i < count; i++)
+ ClearPageReserved(page + i);
+ __free_pages(page, order);
+}
+
+static void kimage_free_page_list(struct list_head *list)
+{
+ struct list_head *pos, *next;
+
+ list_for_each_safe(pos, next, list) {
+ struct page *page;
+
+ page = list_entry(pos, struct page, lru);
+ list_del(&page->lru);
+ kimage_free_pages(page);
+ }
+}
+
+static struct page *kimage_alloc_normal_control_pages(struct kimage *image,
+ unsigned int order)
+{
+ /* Control pages are special, they are the intermediaries
+ * that are needed while we copy the rest of the pages
+ * to their final resting place. As such they must
+ * not conflict with either the destination addresses
+ * or memory the kernel is already using.
+ *
+ * The only case where we really need more than one of
+ * these are for architectures where we cannot disable
+ * the MMU and must instead generate an identity mapped
+ * page table for all of the memory.
+ *
+ * At worst this runs in O(N) of the image size.
+ */
+ struct list_head extra_pages;
+ struct page *pages;
+ unsigned int count;
+
+ count = 1 << order;
+ INIT_LIST_HEAD(&extra_pages);
+
+ /* Loop while I can allocate a page and the page allocated
+ * is a destination page.
+ */
+ do {
+ unsigned long pfn, epfn, addr, eaddr;
+
+ pages = kimage_alloc_pages(GFP_KERNEL, order);
+ if (!pages)
+ break;
+ pfn = page_to_pfn(pages);
+ epfn = pfn + count;
+ addr = pfn << PAGE_SHIFT;
+ eaddr = epfn << PAGE_SHIFT;
+ if ((epfn >= (KEXEC_CONTROL_MEMORY_LIMIT >> PAGE_SHIFT)) ||
+ kimage_is_destination_range(image, addr, eaddr)) {
+ list_add(&pages->lru, &extra_pages);
+ pages = NULL;
+ }
+ } while (!pages);
+
+ if (pages) {
+ /* Remember the allocated page... */
+ list_add(&pages->lru, &image->control_pages);
+
+ /* Because the page is already in it's destination
+ * location we will never allocate another page at
+ * that address. Therefore kimage_alloc_pages
+ * will not return it (again) and we don't need
+ * to give it an entry in image->segment[].
+ */
+ }
+ /* Deal with the destination pages I have inadvertently allocated.
+ *
+ * Ideally I would convert multi-page allocations into single
+ * page allocations, and add everyting to image->dest_pages.
+ *
+ * For now it is simpler to just free the pages.
+ */
+ kimage_free_page_list(&extra_pages);
+
+ return pages;
+}
+
+static struct page *kimage_alloc_crash_control_pages(struct kimage *image,
+ unsigned int order)
+{
+ /* Control pages are special, they are the intermediaries
+ * that are needed while we copy the rest of the pages
+ * to their final resting place. As such they must
+ * not conflict with either the destination addresses
+ * or memory the kernel is already using.
+ *
+ * Control pages are also the only pags we must allocate
+ * when loading a crash kernel. All of the other pages
+ * are specified by the segments and we just memcpy
+ * into them directly.
+ *
+ * The only case where we really need more than one of
+ * these are for architectures where we cannot disable
+ * the MMU and must instead generate an identity mapped
+ * page table for all of the memory.
+ *
+ * Given the low demand this implements a very simple
+ * allocator that finds the first hole of the appropriate
+ * size in the reserved memory region, and allocates all
+ * of the memory up to and including the hole.
+ */
+ unsigned long hole_start, hole_end, size;
+ struct page *pages;
+
+ pages = NULL;
+ size = (1 << order) << PAGE_SHIFT;
+ hole_start = (image->control_page + (size - 1)) & ~(size - 1);
+ hole_end = hole_start + size - 1;
+ while (hole_end <= crashk_res.end) {
+ unsigned long i;
+
+ if (hole_end > KEXEC_CONTROL_MEMORY_LIMIT)
+ break;
+ if (hole_end > crashk_res.end)
+ break;
+ /* See if I overlap any of the segments */
+ for (i = 0; i < image->nr_segments; i++) {
+ unsigned long mstart, mend;
+
+ mstart = image->segment[i].mem;
+ mend = mstart + image->segment[i].memsz - 1;
+ if ((hole_end >= mstart) && (hole_start <= mend)) {
+ /* Advance the hole to the end of the segment */
+ hole_start = (mend + (size - 1)) & ~(size - 1);
+ hole_end = hole_start + size - 1;
+ break;
+ }
+ }
+ /* If I don't overlap any segments I have found my hole! */
+ if (i == image->nr_segments) {
+ pages = pfn_to_page(hole_start >> PAGE_SHIFT);
+ break;
+ }
+ }
+ if (pages)
+ image->control_page = hole_end;
+
+ return pages;
+}
+
+
+struct page *kimage_alloc_control_pages(struct kimage *image,
+ unsigned int order)
+{
+ struct page *pages = NULL;
+
+ switch (image->type) {
+ case KEXEC_TYPE_DEFAULT:
+ pages = kimage_alloc_normal_control_pages(image, order);
+ break;
+ case KEXEC_TYPE_CRASH:
+ pages = kimage_alloc_crash_control_pages(image, order);
+ break;
+ }
+
+ return pages;
+}
+
+static int kimage_add_entry(struct kimage *image, kimage_entry_t entry)
+{
+ if (*image->entry != 0)
+ image->entry++;
+
+ if (image->entry == image->last_entry) {
+ kimage_entry_t *ind_page;
+ struct page *page;
+
+ page = kimage_alloc_page(image, GFP_KERNEL, KIMAGE_NO_DEST);
+ if (!page)
+ return -ENOMEM;
+
+ ind_page = page_address(page);
+ *image->entry = virt_to_phys(ind_page) | IND_INDIRECTION;
+ image->entry = ind_page;
+ image->last_entry = ind_page +
+ ((PAGE_SIZE/sizeof(kimage_entry_t)) - 1);
+ }
+ *image->entry = entry;
+ image->entry++;
+ *image->entry = 0;
+
+ return 0;
+}
+
+static int kimage_set_destination(struct kimage *image,
+ unsigned long destination)
+{
+ int result;
+
+ destination &= PAGE_MASK;
+ result = kimage_add_entry(image, destination | IND_DESTINATION);
+ if (result == 0)
+ image->destination = destination;
+
+ return result;
+}
+
+
+static int kimage_add_page(struct kimage *image, unsigned long page)
+{
+ int result;
+
+ page &= PAGE_MASK;
+ result = kimage_add_entry(image, page | IND_SOURCE);
+ if (result == 0)
+ image->destination += PAGE_SIZE;
+
+ return result;
+}
+
+
+static void kimage_free_extra_pages(struct kimage *image)
+{
+ /* Walk through and free any extra destination pages I may have */
+ kimage_free_page_list(&image->dest_pages);
+
+ /* Walk through and free any unuseable pages I have cached */
+ kimage_free_page_list(&image->unuseable_pages);
+
+}
+static int kimage_terminate(struct kimage *image)
+{
+ if (*image->entry != 0)
+ image->entry++;
+
+ *image->entry = IND_DONE;
+
+ return 0;
+}
+
+#define for_each_kimage_entry(image, ptr, entry) \
+ for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \
+ ptr = (entry & IND_INDIRECTION)? \
+ phys_to_virt((entry & PAGE_MASK)): ptr +1)
+
+static void kimage_free_entry(kimage_entry_t entry)
+{
+ struct page *page;
+
+ page = pfn_to_page(entry >> PAGE_SHIFT);
+ kimage_free_pages(page);
+}
+
+static void kimage_free(struct kimage *image)
+{
+ kimage_entry_t *ptr, entry;
+ kimage_entry_t ind = 0;
+
+ if (!image)
+ return;
+
+ kimage_free_extra_pages(image);
+ for_each_kimage_entry(image, ptr, entry) {
+ if (entry & IND_INDIRECTION) {
+ /* Free the previous indirection page */
+ if (ind & IND_INDIRECTION)
+ kimage_free_entry(ind);
+ /* Save this indirection page until we are
+ * done with it.
+ */
+ ind = entry;
+ }
+ else if (entry & IND_SOURCE)
+ kimage_free_entry(entry);
+ }
+ /* Free the final indirection page */
+ if (ind & IND_INDIRECTION)
+ kimage_free_entry(ind);
+
+ /* Handle any machine specific cleanup */
+ machine_kexec_cleanup(image);
+
+ /* Free the kexec control pages... */
+ kimage_free_page_list(&image->control_pages);
+ kfree(image);
+}
+
+static kimage_entry_t *kimage_dst_used(struct kimage *image,
+ unsigned long page)
+{
+ kimage_entry_t *ptr, entry;
+ unsigned long destination = 0;
+
+ for_each_kimage_entry(image, ptr, entry) {
+ if (entry & IND_DESTINATION)
+ destination = entry & PAGE_MASK;
+ else if (entry & IND_SOURCE) {
+ if (page == destination)
+ return ptr;
+ destination += PAGE_SIZE;
+ }
+ }
+
+ return 0;
+}
+
+static struct page *kimage_alloc_page(struct kimage *image,
+ unsigned int gfp_mask,
+ unsigned long destination)
+{
+ /*
+ * Here we implement safeguards to ensure that a source page
+ * is not copied to its destination page before the data on
+ * the destination page is no longer useful.
+ *
+ * To do this we maintain the invariant that a source page is
+ * either its own destination page, or it is not a
+ * destination page at all.
+ *
+ * That is slightly stronger than required, but the proof
+ * that no problems will not occur is trivial, and the
+ * implementation is simply to verify.
+ *
+ * When allocating all pages normally this algorithm will run
+ * in O(N) time, but in the worst case it will run in O(N^2)
+ * time. If the runtime is a problem the data structures can
+ * be fixed.
+ */
+ struct page *page;
+ unsigned long addr;
+
+ /*
+ * Walk through the list of destination pages, and see if I
+ * have a match.
+ */
+ list_for_each_entry(page, &image->dest_pages, lru) {
+ addr = page_to_pfn(page) << PAGE_SHIFT;
+ if (addr == destination) {
+ list_del(&page->lru);
+ return page;
+ }
+ }
+ page = NULL;
+ while (1) {
+ kimage_entry_t *old;
+
+ /* Allocate a page, if we run out of memory give up */
+ page = kimage_alloc_pages(gfp_mask, 0);
+ if (!page)
+ return 0;
+ /* If the page cannot be used file it away */
+ if (page_to_pfn(page) >
+ (KEXEC_SOURCE_MEMORY_LIMIT >> PAGE_SHIFT)) {
+ list_add(&page->lru, &image->unuseable_pages);
+ continue;
+ }
+ addr = page_to_pfn(page) << PAGE_SHIFT;
+
+ /* If it is the destination page we want use it */
+ if (addr == destination)
+ break;
+
+ /* If the page is not a destination page use it */
+ if (!kimage_is_destination_range(image, addr,
+ addr + PAGE_SIZE))
+ break;
+
+ /*
+ * I know that the page is someones destination page.
+ * See if there is already a source page for this
+ * destination page. And if so swap the source pages.
+ */
+ old = kimage_dst_used(image, addr);
+ if (old) {
+ /* If so move it */
+ unsigned long old_addr;
+ struct page *old_page;
+
+ old_addr = *old & PAGE_MASK;
+ old_page = pfn_to_page(old_addr >> PAGE_SHIFT);
+ copy_highpage(page, old_page);
+ *old = addr | (*old & ~PAGE_MASK);
+
+ /* The old page I have found cannot be a
+ * destination page, so return it.
+ */
+ addr = old_addr;
+ page = old_page;
+ break;
+ }
+ else {
+ /* Place the page on the destination list I
+ * will use it later.
+ */
+ list_add(&page->lru, &image->dest_pages);
+ }
+ }
+
+ return page;
+}
+
+static int kimage_load_normal_segment(struct kimage *image,
+ struct kexec_segment *segment)
+{
+ unsigned long maddr;
+ unsigned long ubytes, mbytes;
+ int result;
+ unsigned char *buf;
+
+ result = 0;
+ buf = segment->buf;
+ ubytes = segment->bufsz;
+ mbytes = segment->memsz;
+ maddr = segment->mem;
+
+ result = kimage_set_destination(image, maddr);
+ if (result < 0)
+ goto out;
+
+ while (mbytes) {
+ struct page *page;
+ char *ptr;
+ size_t uchunk, mchunk;
+
+ page = kimage_alloc_page(image, GFP_HIGHUSER, maddr);
+ if (page == 0) {
+ result = -ENOMEM;
+ goto out;
+ }
+ result = kimage_add_page(image, page_to_pfn(page)
+ << PAGE_SHIFT);
+ if (result < 0)
+ goto out;
+
+ ptr = kmap(page);
+ /* Start with a clear page */
+ memset(ptr, 0, PAGE_SIZE);
+ ptr += maddr & ~PAGE_MASK;
+ mchunk = PAGE_SIZE - (maddr & ~PAGE_MASK);
+ if (mchunk > mbytes)
+ mchunk = mbytes;
+
+ uchunk = mchunk;
+ if (uchunk > ubytes)
+ uchunk = ubytes;
+
+ result = copy_from_user(ptr, buf, uchunk);
+ kunmap(page);
+ if (result) {
+ result = (result < 0) ? result : -EIO;
+ goto out;
+ }
+ ubytes -= uchunk;
+ maddr += mchunk;
+ buf += mchunk;
+ mbytes -= mchunk;
+ }
+out:
+ return result;
+}
+
+static int kimage_load_crash_segment(struct kimage *image,
+ struct kexec_segment *segment)
+{
+ /* For crash dumps kernels we simply copy the data from
+ * user space to it's destination.
+ * We do things a page at a time for the sake of kmap.
+ */
+ unsigned long maddr;
+ unsigned long ubytes, mbytes;
+ int result;
+ unsigned char *buf;
+
+ result = 0;
+ buf = segment->buf;
+ ubytes = segment->bufsz;
+ mbytes = segment->memsz;
+ maddr = segment->mem;
+ while (mbytes) {
+ struct page *page;
+ char *ptr;
+ size_t uchunk, mchunk;
+
+ page = pfn_to_page(maddr >> PAGE_SHIFT);
+ if (page == 0) {
+ result = -ENOMEM;
+ goto out;
+ }
+ ptr = kmap(page);
+ ptr += maddr & ~PAGE_MASK;
+ mchunk = PAGE_SIZE - (maddr & ~PAGE_MASK);
+ if (mchunk > mbytes)
+ mchunk = mbytes;
+
+ uchunk = mchunk;
+ if (uchunk > ubytes) {
+ uchunk = ubytes;
+ /* Zero the trailing part of the page */
+ memset(ptr + uchunk, 0, mchunk - uchunk);
+ }
+ result = copy_from_user(ptr, buf, uchunk);
+ kunmap(page);
+ if (result) {
+ result = (result < 0) ? result : -EIO;
+ goto out;
+ }
+ ubytes -= uchunk;
+ maddr += mchunk;
+ buf += mchunk;
+ mbytes -= mchunk;
+ }
+out:
+ return result;
+}
+
+static int kimage_load_segment(struct kimage *image,
+ struct kexec_segment *segment)
+{
+ int result = -ENOMEM;
+
+ switch (image->type) {
+ case KEXEC_TYPE_DEFAULT:
+ result = kimage_load_normal_segment(image, segment);
+ break;
+ case KEXEC_TYPE_CRASH:
+ result = kimage_load_crash_segment(image, segment);
+ break;
+ }
+
+ return result;
+}
+
+/*
+ * Exec Kernel system call: for obvious reasons only root may call it.
+ *
+ * This call breaks up into three pieces.
+ * - A generic part which loads the new kernel from the current
+ * address space, and very carefully places the data in the
+ * allocated pages.
+ *
+ * - A generic part that interacts with the kernel and tells all of
+ * the devices to shut down. Preventing on-going dmas, and placing
+ * the devices in a consistent state so a later kernel can
+ * reinitialize them.
+ *
+ * - A machine specific part that includes the syscall number
+ * and the copies the image to it's final destination. And
+ * jumps into the image at entry.
+ *
+ * kexec does not sync, or unmount filesystems so if you need
+ * that to happen you need to do that yourself.
+ */
+struct kimage *kexec_image = NULL;
+static struct kimage *kexec_crash_image = NULL;
+/*
+ * A home grown binary mutex.
+ * Nothing can wait so this mutex is safe to use
+ * in interrupt context :)
+ */
+static int kexec_lock = 0;
+
+asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments,
+ struct kexec_segment __user *segments,
+ unsigned long flags)
+{
+ struct kimage **dest_image, *image;
+ int locked;
+ int result;
+
+ /* We only trust the superuser with rebooting the system. */
+ if (!capable(CAP_SYS_BOOT))
+ return -EPERM;
+
+ /*
+ * Verify we have a legal set of flags
+ * This leaves us room for future extensions.
+ */
+ if ((flags & KEXEC_FLAGS) != (flags & ~KEXEC_ARCH_MASK))
+ return -EINVAL;
+
+ /* Verify we are on the appropriate architecture */
+ if (((flags & KEXEC_ARCH_MASK) != KEXEC_ARCH) &&
+ ((flags & KEXEC_ARCH_MASK) != KEXEC_ARCH_DEFAULT))
+ return -EINVAL;
+
+ /* Put an artificial cap on the number
+ * of segments passed to kexec_load.
+ */
+ if (nr_segments > KEXEC_SEGMENT_MAX)
+ return -EINVAL;
+
+ image = NULL;
+ result = 0;
+
+ /* Because we write directly to the reserved memory
+ * region when loading crash kernels we need a mutex here to
+ * prevent multiple crash kernels from attempting to load
+ * simultaneously, and to prevent a crash kernel from loading
+ * over the top of a in use crash kernel.
+ *
+ * KISS: always take the mutex.
+ */
+ locked = xchg(&kexec_lock, 1);
+ if (locked)
+ return -EBUSY;
+
+ dest_image = &kexec_image;
+ if (flags & KEXEC_ON_CRASH)
+ dest_image = &kexec_crash_image;
+ if (nr_segments > 0) {
+ unsigned long i;
+
+ /* Loading another kernel to reboot into */
+ if ((flags & KEXEC_ON_CRASH) == 0)
+ result = kimage_normal_alloc(&image, entry,
+ nr_segments, segments);
+ /* Loading another kernel to switch to if this one crashes */
+ else if (flags & KEXEC_ON_CRASH) {
+ /* Free any current crash dump kernel before
+ * we corrupt it.
+ */
+ kimage_free(xchg(&kexec_crash_image, NULL));
+ result = kimage_crash_alloc(&image, entry,
+ nr_segments, segments);
+ }
+ if (result)
+ goto out;
+
+ result = machine_kexec_prepare(image);
+ if (result)
+ goto out;
+
+ for (i = 0; i < nr_segments; i++) {
+ result = kimage_load_segment(image, &image->segment[i]);
+ if (result)
+ goto out;
+ }
+ result = kimage_terminate(image);
+ if (result)
+ goto out;
+ }
+ /* Install the new kernel, and Uninstall the old */
+ image = xchg(dest_image, image);
+
+out:
+ xchg(&kexec_lock, 0); /* Release the mutex */
+ kimage_free(image);
+
+ return result;
+}
+
+#ifdef CONFIG_COMPAT
+asmlinkage long compat_sys_kexec_load(unsigned long entry,
+ unsigned long nr_segments,
+ struct compat_kexec_segment __user *segments,
+ unsigned long flags)
+{
+ struct compat_kexec_segment in;
+ struct kexec_segment out, __user *ksegments;
+ unsigned long i, result;
+
+ /* Don't allow clients that don't understand the native
+ * architecture to do anything.
+ */
+ if ((flags & KEXEC_ARCH_MASK) == KEXEC_ARCH_DEFAULT)
+ return -EINVAL;
+
+ if (nr_segments > KEXEC_SEGMENT_MAX)
+ return -EINVAL;
+
+ ksegments = compat_alloc_user_space(nr_segments * sizeof(out));
+ for (i=0; i < nr_segments; i++) {
+ result = copy_from_user(&in, &segments[i], sizeof(in));
+ if (result)
+ return -EFAULT;
+
+ out.buf = compat_ptr(in.buf);
+ out.bufsz = in.bufsz;
+ out.mem = in.mem;
+ out.memsz = in.memsz;
+
+ result = copy_to_user(&ksegments[i], &out, sizeof(out));
+ if (result)
+ return -EFAULT;
+ }
+
+ return sys_kexec_load(entry, nr_segments, ksegments, flags);
+}
+#endif
+
+void crash_kexec(struct pt_regs *regs)
+{
+ struct kimage *image;
+ int locked;
+
+
+ /* Take the kexec_lock here to prevent sys_kexec_load
+ * running on one cpu from replacing the crash kernel
+ * we are using after a panic on a different cpu.
+ *
+ * If the crash kernel was not located in a fixed area
+ * of memory the xchg(&kexec_crash_image) would be
+ * sufficient. But since I reuse the memory...
+ */
+ locked = xchg(&kexec_lock, 1);
+ if (!locked) {
+ image = xchg(&kexec_crash_image, NULL);
+ if (image) {
+ machine_crash_shutdown(regs);
+ machine_kexec(image);
+ }
+ xchg(&kexec_lock, 0);
+ }
+}
diff --git a/kernel/kmod.c b/kernel/kmod.c
index eed53d4f523..44166e3bb8a 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -120,6 +120,7 @@ struct subprocess_info {
char *path;
char **argv;
char **envp;
+ struct key *ring;
int wait;
int retval;
};
@@ -130,16 +131,21 @@ struct subprocess_info {
static int ____call_usermodehelper(void *data)
{
struct subprocess_info *sub_info = data;
+ struct key *old_session;
int retval;
- /* Unblock all signals. */
+ /* Unblock all signals and set the session keyring. */
+ key_get(sub_info->ring);
flush_signals(current);
spin_lock_irq(&current->sighand->siglock);
+ old_session = __install_session_keyring(current, sub_info->ring);
flush_signal_handlers(current, 1);
sigemptyset(&current->blocked);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
+ key_put(old_session);
+
/* We can run anywhere, unlike our parent keventd(). */
set_cpus_allowed(current, CPU_MASK_ALL);
@@ -211,10 +217,11 @@ static void __call_usermodehelper(void *data)
}
/**
- * call_usermodehelper - start a usermode application
+ * call_usermodehelper_keys - start a usermode application
* @path: pathname for the application
* @argv: null-terminated argument list
* @envp: null-terminated environment list
+ * @session_keyring: session keyring for process (NULL for an empty keyring)
* @wait: wait for the application to finish and return status.
*
* Runs a user-space application. The application is started
@@ -224,7 +231,8 @@ static void __call_usermodehelper(void *data)
* Must be called from process context. Returns a negative error code
* if program was not execed successfully, or 0.
*/
-int call_usermodehelper(char *path, char **argv, char **envp, int wait)
+int call_usermodehelper_keys(char *path, char **argv, char **envp,
+ struct key *session_keyring, int wait)
{
DECLARE_COMPLETION(done);
struct subprocess_info sub_info = {
@@ -232,6 +240,7 @@ int call_usermodehelper(char *path, char **argv, char **envp, int wait)
.path = path,
.argv = argv,
.envp = envp,
+ .ring = session_keyring,
.wait = wait,
.retval = 0,
};
@@ -247,7 +256,7 @@ int call_usermodehelper(char *path, char **argv, char **envp, int wait)
wait_for_completion(&done);
return sub_info.retval;
}
-EXPORT_SYMBOL(call_usermodehelper);
+EXPORT_SYMBOL(call_usermodehelper_keys);
void __init usermodehelper_init(void)
{
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 037142b72a4..334f37472c5 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -27,6 +27,9 @@
* interface to access function arguments.
* 2004-Sep Prasanna S Panchamukhi <prasanna@in.ibm.com> Changed Kprobes
* exceptions notifier to be first on the priority list.
+ * 2005-May Hien Nguyen <hien@us.ibm.com>, Jim Keniston
+ * <jkenisto@us.ibm.com> and Prasanna S Panchamukhi
+ * <prasanna@in.ibm.com> added function-return probes.
*/
#include <linux/kprobes.h>
#include <linux/spinlock.h>
@@ -41,6 +44,7 @@
#define KPROBE_TABLE_SIZE (1 << KPROBE_HASH_BITS)
static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
+static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
unsigned int kprobe_cpu = NR_CPUS;
static DEFINE_SPINLOCK(kprobe_lock);
@@ -78,22 +82,23 @@ struct kprobe *get_kprobe(void *addr)
* Aggregate handlers for multiple kprobes support - these handlers
* take care of invoking the individual kprobe handlers on p->list
*/
-int aggr_pre_handler(struct kprobe *p, struct pt_regs *regs)
+static int aggr_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
struct kprobe *kp;
list_for_each_entry(kp, &p->list, list) {
if (kp->pre_handler) {
curr_kprobe = kp;
- kp->pre_handler(kp, regs);
- curr_kprobe = NULL;
+ if (kp->pre_handler(kp, regs))
+ return 1;
}
+ curr_kprobe = NULL;
}
return 0;
}
-void aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
- unsigned long flags)
+static void aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
+ unsigned long flags)
{
struct kprobe *kp;
@@ -107,7 +112,8 @@ void aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
return;
}
-int aggr_fault_handler(struct kprobe *p, struct pt_regs *regs, int trapnr)
+static int aggr_fault_handler(struct kprobe *p, struct pt_regs *regs,
+ int trapnr)
{
/*
* if we faulted "during" the execution of a user specified
@@ -120,19 +126,191 @@ int aggr_fault_handler(struct kprobe *p, struct pt_regs *regs, int trapnr)
return 0;
}
+static int aggr_break_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ struct kprobe *kp = curr_kprobe;
+ if (curr_kprobe && kp->break_handler) {
+ if (kp->break_handler(kp, regs)) {
+ curr_kprobe = NULL;
+ return 1;
+ }
+ }
+ curr_kprobe = NULL;
+ return 0;
+}
+
+struct kprobe trampoline_p = {
+ .addr = (kprobe_opcode_t *) &kretprobe_trampoline,
+ .pre_handler = trampoline_probe_handler,
+ .post_handler = trampoline_post_handler
+};
+
+struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp)
+{
+ struct hlist_node *node;
+ struct kretprobe_instance *ri;
+ hlist_for_each_entry(ri, node, &rp->free_instances, uflist)
+ return ri;
+ return NULL;
+}
+
+static struct kretprobe_instance *get_used_rp_inst(struct kretprobe *rp)
+{
+ struct hlist_node *node;
+ struct kretprobe_instance *ri;
+ hlist_for_each_entry(ri, node, &rp->used_instances, uflist)
+ return ri;
+ return NULL;
+}
+
+struct kretprobe_instance *get_rp_inst(void *sara)
+{
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct task_struct *tsk;
+ struct kretprobe_instance *ri;
+
+ tsk = arch_get_kprobe_task(sara);
+ head = &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)];
+ hlist_for_each_entry(ri, node, head, hlist) {
+ if (ri->stack_addr == sara)
+ return ri;
+ }
+ return NULL;
+}
+
+void add_rp_inst(struct kretprobe_instance *ri)
+{
+ struct task_struct *tsk;
+ /*
+ * Remove rp inst off the free list -
+ * Add it back when probed function returns
+ */
+ hlist_del(&ri->uflist);
+ tsk = arch_get_kprobe_task(ri->stack_addr);
+ /* Add rp inst onto table */
+ INIT_HLIST_NODE(&ri->hlist);
+ hlist_add_head(&ri->hlist,
+ &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)]);
+
+ /* Also add this rp inst to the used list. */
+ INIT_HLIST_NODE(&ri->uflist);
+ hlist_add_head(&ri->uflist, &ri->rp->used_instances);
+}
+
+void recycle_rp_inst(struct kretprobe_instance *ri)
+{
+ /* remove rp inst off the rprobe_inst_table */
+ hlist_del(&ri->hlist);
+ if (ri->rp) {
+ /* remove rp inst off the used list */
+ hlist_del(&ri->uflist);
+ /* put rp inst back onto the free list */
+ INIT_HLIST_NODE(&ri->uflist);
+ hlist_add_head(&ri->uflist, &ri->rp->free_instances);
+ } else
+ /* Unregistering */
+ kfree(ri);
+}
+
+struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk)
+{
+ return &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)];
+}
+
+struct kretprobe_instance *get_rp_inst_tsk(struct task_struct *tk)
+{
+ struct task_struct *tsk;
+ struct hlist_head *head;
+ struct hlist_node *node;
+ struct kretprobe_instance *ri;
+
+ head = &kretprobe_inst_table[hash_ptr(tk, KPROBE_HASH_BITS)];
+
+ hlist_for_each_entry(ri, node, head, hlist) {
+ tsk = arch_get_kprobe_task(ri->stack_addr);
+ if (tsk == tk)
+ return ri;
+ }
+ return NULL;
+}
+
+/*
+ * This function is called from do_exit or do_execv when task tk's stack is
+ * about to be recycled. Recycle any function-return probe instances
+ * associated with this task. These represent probed functions that have
+ * been called but may never return.
+ */
+void kprobe_flush_task(struct task_struct *tk)
+{
+ unsigned long flags = 0;
+ spin_lock_irqsave(&kprobe_lock, flags);
+ arch_kprobe_flush_task(tk);
+ spin_unlock_irqrestore(&kprobe_lock, flags);
+}
+
+/*
+ * This kprobe pre_handler is registered with every kretprobe. When probe
+ * hits it will set up the return probe.
+ */
+static int pre_handler_kretprobe(struct kprobe *p, struct pt_regs *regs)
+{
+ struct kretprobe *rp = container_of(p, struct kretprobe, kp);
+
+ /*TODO: consider to only swap the RA after the last pre_handler fired */
+ arch_prepare_kretprobe(rp, regs);
+ return 0;
+}
+
+static inline void free_rp_inst(struct kretprobe *rp)
+{
+ struct kretprobe_instance *ri;
+ while ((ri = get_free_rp_inst(rp)) != NULL) {
+ hlist_del(&ri->uflist);
+ kfree(ri);
+ }
+}
+
+/*
+ * Keep all fields in the kprobe consistent
+ */
+static inline void copy_kprobe(struct kprobe *old_p, struct kprobe *p)
+{
+ memcpy(&p->opcode, &old_p->opcode, sizeof(kprobe_opcode_t));
+ memcpy(&p->ainsn, &old_p->ainsn, sizeof(struct arch_specific_insn));
+}
+
+/*
+* Add the new probe to old_p->list. Fail if this is the
+* second jprobe at the address - two jprobes can't coexist
+*/
+static int add_new_kprobe(struct kprobe *old_p, struct kprobe *p)
+{
+ struct kprobe *kp;
+
+ if (p->break_handler) {
+ list_for_each_entry(kp, &old_p->list, list) {
+ if (kp->break_handler)
+ return -EEXIST;
+ }
+ list_add_tail(&p->list, &old_p->list);
+ } else
+ list_add(&p->list, &old_p->list);
+ return 0;
+}
+
/*
* Fill in the required fields of the "manager kprobe". Replace the
* earlier kprobe in the hlist with the manager kprobe
*/
static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p)
{
+ copy_kprobe(p, ap);
ap->addr = p->addr;
- ap->opcode = p->opcode;
- memcpy(&ap->ainsn, &p->ainsn, sizeof(struct arch_specific_insn));
-
ap->pre_handler = aggr_pre_handler;
ap->post_handler = aggr_post_handler;
ap->fault_handler = aggr_fault_handler;
+ ap->break_handler = aggr_break_handler;
INIT_LIST_HEAD(&ap->list);
list_add(&p->list, &ap->list);
@@ -153,16 +331,16 @@ static int register_aggr_kprobe(struct kprobe *old_p, struct kprobe *p)
int ret = 0;
struct kprobe *ap;
- if (old_p->break_handler || p->break_handler) {
- ret = -EEXIST; /* kprobe and jprobe can't (yet) coexist */
- } else if (old_p->pre_handler == aggr_pre_handler) {
- list_add(&p->list, &old_p->list);
+ if (old_p->pre_handler == aggr_pre_handler) {
+ copy_kprobe(old_p, p);
+ ret = add_new_kprobe(old_p, p);
} else {
ap = kcalloc(1, sizeof(struct kprobe), GFP_ATOMIC);
if (!ap)
return -ENOMEM;
add_aggr_kprobe(ap, old_p);
- list_add(&p->list, &ap->list);
+ copy_kprobe(ap, p);
+ ret = add_new_kprobe(ap, p);
}
return ret;
}
@@ -170,10 +348,8 @@ static int register_aggr_kprobe(struct kprobe *old_p, struct kprobe *p)
/* kprobe removal house-keeping routines */
static inline void cleanup_kprobe(struct kprobe *p, unsigned long flags)
{
- *p->addr = p->opcode;
+ arch_disarm_kprobe(p);
hlist_del(&p->hlist);
- flush_icache_range((unsigned long) p->addr,
- (unsigned long) p->addr + sizeof(kprobe_opcode_t));
spin_unlock_irqrestore(&kprobe_lock, flags);
arch_remove_kprobe(p);
}
@@ -200,6 +376,7 @@ int register_kprobe(struct kprobe *p)
}
spin_lock_irqsave(&kprobe_lock, flags);
old_p = get_kprobe(p->addr);
+ p->nmissed = 0;
if (old_p) {
ret = register_aggr_kprobe(old_p, p);
goto out;
@@ -210,10 +387,8 @@ int register_kprobe(struct kprobe *p)
hlist_add_head(&p->hlist,
&kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]);
- p->opcode = *p->addr;
- *p->addr = BREAKPOINT_INSTRUCTION;
- flush_icache_range((unsigned long) p->addr,
- (unsigned long) p->addr + sizeof(kprobe_opcode_t));
+ arch_arm_kprobe(p);
+
out:
spin_unlock_irqrestore(&kprobe_lock, flags);
rm_kprobe:
@@ -257,16 +432,82 @@ void unregister_jprobe(struct jprobe *jp)
unregister_kprobe(&jp->kp);
}
+#ifdef ARCH_SUPPORTS_KRETPROBES
+
+int register_kretprobe(struct kretprobe *rp)
+{
+ int ret = 0;
+ struct kretprobe_instance *inst;
+ int i;
+
+ rp->kp.pre_handler = pre_handler_kretprobe;
+
+ /* Pre-allocate memory for max kretprobe instances */
+ if (rp->maxactive <= 0) {
+#ifdef CONFIG_PREEMPT
+ rp->maxactive = max(10, 2 * NR_CPUS);
+#else
+ rp->maxactive = NR_CPUS;
+#endif
+ }
+ INIT_HLIST_HEAD(&rp->used_instances);
+ INIT_HLIST_HEAD(&rp->free_instances);
+ for (i = 0; i < rp->maxactive; i++) {
+ inst = kmalloc(sizeof(struct kretprobe_instance), GFP_KERNEL);
+ if (inst == NULL) {
+ free_rp_inst(rp);
+ return -ENOMEM;
+ }
+ INIT_HLIST_NODE(&inst->uflist);
+ hlist_add_head(&inst->uflist, &rp->free_instances);
+ }
+
+ rp->nmissed = 0;
+ /* Establish function entry probe point */
+ if ((ret = register_kprobe(&rp->kp)) != 0)
+ free_rp_inst(rp);
+ return ret;
+}
+
+#else /* ARCH_SUPPORTS_KRETPROBES */
+
+int register_kretprobe(struct kretprobe *rp)
+{
+ return -ENOSYS;
+}
+
+#endif /* ARCH_SUPPORTS_KRETPROBES */
+
+void unregister_kretprobe(struct kretprobe *rp)
+{
+ unsigned long flags;
+ struct kretprobe_instance *ri;
+
+ unregister_kprobe(&rp->kp);
+ /* No race here */
+ spin_lock_irqsave(&kprobe_lock, flags);
+ free_rp_inst(rp);
+ while ((ri = get_used_rp_inst(rp)) != NULL) {
+ ri->rp = NULL;
+ hlist_del(&ri->uflist);
+ }
+ spin_unlock_irqrestore(&kprobe_lock, flags);
+}
+
static int __init init_kprobes(void)
{
int i, err = 0;
/* FIXME allocate the probe table, currently defined statically */
/* initialize all list heads */
- for (i = 0; i < KPROBE_TABLE_SIZE; i++)
+ for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
INIT_HLIST_HEAD(&kprobe_table[i]);
+ INIT_HLIST_HEAD(&kretprobe_inst_table[i]);
+ }
err = register_die_notifier(&kprobe_exceptions_nb);
+ /* Register the trampoline probe for return probe */
+ register_kprobe(&trampoline_p);
return err;
}
@@ -277,3 +518,6 @@ EXPORT_SYMBOL_GPL(unregister_kprobe);
EXPORT_SYMBOL_GPL(register_jprobe);
EXPORT_SYMBOL_GPL(unregister_jprobe);
EXPORT_SYMBOL_GPL(jprobe_return);
+EXPORT_SYMBOL_GPL(register_kretprobe);
+EXPORT_SYMBOL_GPL(unregister_kretprobe);
+
diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c
index 1f064a63f8c..015fb69ad94 100644
--- a/kernel/ksysfs.c
+++ b/kernel/ksysfs.c
@@ -30,6 +30,16 @@ static ssize_t hotplug_seqnum_show(struct subsystem *subsys, char *page)
KERNEL_ATTR_RO(hotplug_seqnum);
#endif
+#ifdef CONFIG_KEXEC
+#include <asm/kexec.h>
+
+static ssize_t crash_notes_show(struct subsystem *subsys, char *page)
+{
+ return sprintf(page, "%p\n", (void *)crash_notes);
+}
+KERNEL_ATTR_RO(crash_notes);
+#endif
+
decl_subsys(kernel, NULL, NULL);
EXPORT_SYMBOL_GPL(kernel_subsys);
@@ -37,6 +47,9 @@ static struct attribute * kernel_attrs[] = {
#ifdef CONFIG_HOTPLUG
&hotplug_seqnum_attr.attr,
#endif
+#ifdef CONFIG_KEXEC
+ &crash_notes_attr.attr,
+#endif
NULL
};
diff --git a/kernel/module.c b/kernel/module.c
index 5734ab09d3f..068e271ab3a 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -35,6 +35,7 @@
#include <linux/notifier.h>
#include <linux/stop_machine.h>
#include <linux/device.h>
+#include <linux/string.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
#include <asm/cacheflush.h>
@@ -370,6 +371,43 @@ static inline void percpu_modcopy(void *pcpudst, const void *src,
#endif /* CONFIG_SMP */
#ifdef CONFIG_MODULE_UNLOAD
+#define MODINFO_ATTR(field) \
+static void setup_modinfo_##field(struct module *mod, const char *s) \
+{ \
+ mod->field = kstrdup(s, GFP_KERNEL); \
+} \
+static ssize_t show_modinfo_##field(struct module_attribute *mattr, \
+ struct module *mod, char *buffer) \
+{ \
+ return sprintf(buffer, "%s\n", mod->field); \
+} \
+static int modinfo_##field##_exists(struct module *mod) \
+{ \
+ return mod->field != NULL; \
+} \
+static void free_modinfo_##field(struct module *mod) \
+{ \
+ kfree(mod->field); \
+ mod->field = NULL; \
+} \
+static struct module_attribute modinfo_##field = { \
+ .attr = { .name = __stringify(field), .mode = 0444, \
+ .owner = THIS_MODULE }, \
+ .show = show_modinfo_##field, \
+ .setup = setup_modinfo_##field, \
+ .test = modinfo_##field##_exists, \
+ .free = free_modinfo_##field, \
+};
+
+MODINFO_ATTR(version);
+MODINFO_ATTR(srcversion);
+
+static struct module_attribute *modinfo_attrs[] = {
+ &modinfo_version,
+ &modinfo_srcversion,
+ NULL,
+};
+
/* Init the unload section of the module. */
static void module_unload_init(struct module *mod)
{
@@ -379,7 +417,7 @@ static void module_unload_init(struct module *mod)
for (i = 0; i < NR_CPUS; i++)
local_set(&mod->ref[i].count, 0);
/* Hold reference count during initialization. */
- local_set(&mod->ref[_smp_processor_id()].count, 1);
+ local_set(&mod->ref[raw_smp_processor_id()].count, 1);
/* Backwards compatibility macros put refcount during init. */
mod->waiter = current;
}
@@ -692,7 +730,7 @@ static int obsparm_copy_string(const char *val, struct kernel_param *kp)
return 0;
}
-int set_obsolete(const char *val, struct kernel_param *kp)
+static int set_obsolete(const char *val, struct kernel_param *kp)
{
unsigned int min, max;
unsigned int size, maxsize;
@@ -1031,6 +1069,32 @@ static void module_remove_refcnt_attr(struct module *mod)
}
#endif
+#ifdef CONFIG_MODULE_UNLOAD
+static int module_add_modinfo_attrs(struct module *mod)
+{
+ struct module_attribute *attr;
+ int error = 0;
+ int i;
+
+ for (i = 0; (attr = modinfo_attrs[i]) && !error; i++) {
+ if (!attr->test ||
+ (attr->test && attr->test(mod)))
+ error = sysfs_create_file(&mod->mkobj.kobj,&attr->attr);
+ }
+ return error;
+}
+
+static void module_remove_modinfo_attrs(struct module *mod)
+{
+ struct module_attribute *attr;
+ int i;
+
+ for (i = 0; (attr = modinfo_attrs[i]); i++) {
+ sysfs_remove_file(&mod->mkobj.kobj,&attr->attr);
+ attr->free(mod);
+ }
+}
+#endif
static int mod_sysfs_setup(struct module *mod,
struct kernel_param *kparam,
@@ -1056,6 +1120,12 @@ static int mod_sysfs_setup(struct module *mod,
if (err)
goto out_unreg;
+#ifdef CONFIG_MODULE_UNLOAD
+ err = module_add_modinfo_attrs(mod);
+ if (err)
+ goto out_unreg;
+#endif
+
return 0;
out_unreg:
@@ -1066,6 +1136,9 @@ out:
static void mod_kobject_remove(struct module *mod)
{
+#ifdef CONFIG_MODULE_UNLOAD
+ module_remove_modinfo_attrs(mod);
+#endif
module_remove_refcnt_attr(mod);
module_param_sysfs_remove(mod);
@@ -1311,6 +1384,23 @@ static char *get_modinfo(Elf_Shdr *sechdrs,
return NULL;
}
+#ifdef CONFIG_MODULE_UNLOAD
+static void setup_modinfo(struct module *mod, Elf_Shdr *sechdrs,
+ unsigned int infoindex)
+{
+ struct module_attribute *attr;
+ int i;
+
+ for (i = 0; (attr = modinfo_attrs[i]); i++) {
+ if (attr->setup)
+ attr->setup(mod,
+ get_modinfo(sechdrs,
+ infoindex,
+ attr->attr.name));
+ }
+}
+#endif
+
#ifdef CONFIG_KALLSYMS
int is_exported(const char *name, const struct module *mod)
{
@@ -1615,6 +1705,11 @@ static struct module *load_module(void __user *umod,
/* Set up license info based on the info section */
set_license(mod, get_modinfo(sechdrs, infoindex, "license"));
+#ifdef CONFIG_MODULE_UNLOAD
+ /* Set up MODINFO_ATTR fields */
+ setup_modinfo(mod, sechdrs, infoindex);
+#endif
+
/* Fix up syms, so that st_value is a pointer to location. */
err = simplify_symbols(sechdrs, symindex, strtab, versindex, pcpuindex,
mod);
@@ -1758,6 +1853,7 @@ sys_init_module(void __user *umod,
const char __user *uargs)
{
struct module *mod;
+ mm_segment_t old_fs = get_fs();
int ret = 0;
/* Must have permission */
@@ -1775,6 +1871,9 @@ sys_init_module(void __user *umod,
return PTR_ERR(mod);
}
+ /* flush the icache in correct context */
+ set_fs(KERNEL_DS);
+
/* Flush the instruction cache, since we've played with text */
if (mod->module_init)
flush_icache_range((unsigned long)mod->module_init,
@@ -1783,6 +1882,8 @@ sys_init_module(void __user *umod,
flush_icache_range((unsigned long)mod->module_core,
(unsigned long)mod->module_core + mod->core_size);
+ set_fs(old_fs);
+
/* Now sew it into the lists. They won't access us, since
strong_try_module_get() will fail. */
stop_machine_run(__link_module, mod, NR_CPUS);
diff --git a/kernel/panic.c b/kernel/panic.c
index 081f7465fc8..74ba5f3e46c 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -18,6 +18,7 @@
#include <linux/sysrq.h>
#include <linux/interrupt.h>
#include <linux/nmi.h>
+#include <linux/kexec.h>
int panic_timeout;
int panic_on_oops;
@@ -63,6 +64,13 @@ NORET_TYPE void panic(const char * fmt, ...)
unsigned long caller = (unsigned long) __builtin_return_address(0);
#endif
+ /*
+ * It's possible to come here directly from a panic-assertion and not
+ * have preempt disabled. Some functions called from here want
+ * preempt to be disabled. No point enabling it later though...
+ */
+ preempt_disable();
+
bust_spinlocks(1);
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
@@ -70,7 +78,19 @@ NORET_TYPE void panic(const char * fmt, ...)
printk(KERN_EMERG "Kernel panic - not syncing: %s\n",buf);
bust_spinlocks(0);
+ /*
+ * If we have crashed and we have a crash kernel loaded let it handle
+ * everything else.
+ * Do we want to call this before we try to display a message?
+ */
+ crash_kexec(NULL);
+
#ifdef CONFIG_SMP
+ /*
+ * Note smp_send_stop is the usual smp shutdown function, which
+ * unfortunately means it may not be hardened to work in a panic
+ * situation.
+ */
smp_send_stop();
#endif
@@ -79,8 +99,7 @@ NORET_TYPE void panic(const char * fmt, ...)
if (!panic_blink)
panic_blink = no_blink;
- if (panic_timeout > 0)
- {
+ if (panic_timeout > 0) {
/*
* Delay timeout seconds before rebooting the machine.
* We can't use the "normal" timers since we just panicked..
diff --git a/kernel/params.c b/kernel/params.c
index 5513844bec1..d586c35ef8f 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -629,7 +629,7 @@ static ssize_t module_attr_show(struct kobject *kobj,
mk = to_module_kobject(kobj);
if (!attribute->show)
- return -EPERM;
+ return -EIO;
if (!try_module_get(mk->mod))
return -ENODEV;
@@ -653,7 +653,7 @@ static ssize_t module_attr_store(struct kobject *kobj,
mk = to_module_kobject(kobj);
if (!attribute->store)
- return -EPERM;
+ return -EIO;
if (!try_module_get(mk->mod))
return -ENODEV;
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index fd316c27226..5b7b4736d82 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -89,23 +89,6 @@ static struct idr posix_timers_id;
static DEFINE_SPINLOCK(idr_lock);
/*
- * Just because the timer is not in the timer list does NOT mean it is
- * inactive. It could be in the "fire" routine getting a new expire time.
- */
-#define TIMER_INACTIVE 1
-
-#ifdef CONFIG_SMP
-# define timer_active(tmr) \
- ((tmr)->it.real.timer.entry.prev != (void *)TIMER_INACTIVE)
-# define set_timer_inactive(tmr) \
- do { \
- (tmr)->it.real.timer.entry.prev = (void *)TIMER_INACTIVE; \
- } while (0)
-#else
-# define timer_active(tmr) BARFY // error to use outside of SMP
-# define set_timer_inactive(tmr) do { } while (0)
-#endif
-/*
* we assume that the new SIGEV_THREAD_ID shares no bits with the other
* SIGEV values. Here we put out an error if this assumption fails.
*/
@@ -226,7 +209,6 @@ static inline int common_timer_create(struct k_itimer *new_timer)
init_timer(&new_timer->it.real.timer);
new_timer->it.real.timer.data = (unsigned long) new_timer;
new_timer->it.real.timer.function = posix_timer_fn;
- set_timer_inactive(new_timer);
return 0;
}
@@ -480,7 +462,6 @@ static void posix_timer_fn(unsigned long __data)
int do_notify = 1;
spin_lock_irqsave(&timr->it_lock, flags);
- set_timer_inactive(timr);
if (!list_empty(&timr->it.real.abs_timer_entry)) {
spin_lock(&abs_list.lock);
do {
@@ -983,8 +964,8 @@ common_timer_set(struct k_itimer *timr, int flags,
* careful here. If smp we could be in the "fire" routine which will
* be spinning as we hold the lock. But this is ONLY an SMP issue.
*/
+ if (try_to_del_timer_sync(&timr->it.real.timer) < 0) {
#ifdef CONFIG_SMP
- if (timer_active(timr) && !del_timer(&timr->it.real.timer))
/*
* It can only be active if on an other cpu. Since
* we have cleared the interval stuff above, it should
@@ -994,11 +975,9 @@ common_timer_set(struct k_itimer *timr, int flags,
* a "retry" exit status.
*/
return TIMER_RETRY;
-
- set_timer_inactive(timr);
-#else
- del_timer(&timr->it.real.timer);
#endif
+ }
+
remove_from_abslist(timr);
timr->it_requeue_pending = (timr->it_requeue_pending + 2) &
@@ -1083,8 +1062,9 @@ retry:
static inline int common_timer_del(struct k_itimer *timer)
{
timer->it.real.incr = 0;
+
+ if (try_to_del_timer_sync(&timer->it.real.timer) < 0) {
#ifdef CONFIG_SMP
- if (timer_active(timer) && !del_timer(&timer->it.real.timer))
/*
* It can only be active if on an other cpu. Since
* we have cleared the interval stuff above, it should
@@ -1094,9 +1074,9 @@ static inline int common_timer_del(struct k_itimer *timer)
* a "retry" exit status.
*/
return TIMER_RETRY;
-#else
- del_timer(&timer->it.real.timer);
#endif
+ }
+
remove_from_abslist(timer);
return 0;
@@ -1197,6 +1177,7 @@ void exit_itimers(struct signal_struct *sig)
tmr = list_entry(sig->posix_timers.next, struct k_itimer, list);
itimer_delete(tmr);
}
+ del_timer_sync(&sig->real_timer);
}
/*
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 696387ffe49..2c7121d9bff 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -27,8 +27,8 @@ config PM_DEBUG
like suspend support.
config SOFTWARE_SUSPEND
- bool "Software Suspend (EXPERIMENTAL)"
- depends on EXPERIMENTAL && PM && SWAP
+ bool "Software Suspend"
+ depends on EXPERIMENTAL && PM && SWAP && ((X86 && SMP) || ((FVR || PPC32 || X86) && !SMP))
---help---
Enable the possibility of suspending the machine.
It doesn't need APM.
@@ -72,3 +72,7 @@ config PM_STD_PARTITION
suspended image to. It will simply pick the first available swap
device.
+config SUSPEND_SMP
+ bool
+ depends on HOTPLUG_CPU && X86 && PM
+ default y
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index fbdc634135a..2f438d0eaa1 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -3,9 +3,9 @@ ifeq ($(CONFIG_PM_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
endif
-swsusp-smp-$(CONFIG_SMP) += smp.o
-
obj-y := main.o process.o console.o pm.o
-obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o $(swsusp-smp-y) disk.o
+obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o disk.o
+
+obj-$(CONFIG_SUSPEND_SMP) += smp.o
obj-$(CONFIG_MAGIC_SYSRQ) += poweroff.o
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index 02b6764034d..fb8de63c291 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -117,8 +117,8 @@ static void finish(void)
{
device_resume();
platform_finish();
- enable_nonboot_cpus();
thaw_processes();
+ enable_nonboot_cpus();
pm_restore_console();
}
@@ -131,28 +131,35 @@ static int prepare_processes(void)
sys_sync();
+ disable_nonboot_cpus();
+
if (freeze_processes()) {
error = -EBUSY;
- return error;
+ goto thaw;
}
if (pm_disk_mode == PM_DISK_PLATFORM) {
if (pm_ops && pm_ops->prepare) {
if ((error = pm_ops->prepare(PM_SUSPEND_DISK)))
- return error;
+ goto thaw;
}
}
/* Free memory before shutting down devices. */
free_some_memory();
-
return 0;
+thaw:
+ thaw_processes();
+ enable_nonboot_cpus();
+ pm_restore_console();
+ return error;
}
static void unprepare_processes(void)
{
- enable_nonboot_cpus();
+ platform_finish();
thaw_processes();
+ enable_nonboot_cpus();
pm_restore_console();
}
@@ -160,15 +167,9 @@ static int prepare_devices(void)
{
int error;
- disable_nonboot_cpus();
- if ((error = device_suspend(PMSG_FREEZE))) {
+ if ((error = device_suspend(PMSG_FREEZE)))
printk("Some devices failed to suspend\n");
- platform_finish();
- enable_nonboot_cpus();
- return error;
- }
-
- return 0;
+ return error;
}
/**
@@ -185,9 +186,9 @@ int pm_suspend_disk(void)
int error;
error = prepare_processes();
- if (!error) {
- error = prepare_devices();
- }
+ if (error)
+ return error;
+ error = prepare_devices();
if (error) {
unprepare_processes();
@@ -250,7 +251,7 @@ static int software_resume(void)
if ((error = prepare_processes())) {
swsusp_close();
- goto Cleanup;
+ goto Done;
}
pr_debug("PM: Reading swsusp image.\n");
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 7960ddf04a5..c94cb9e9509 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -55,6 +55,13 @@ static int suspend_prepare(suspend_state_t state)
pm_prepare_console();
+ disable_nonboot_cpus();
+
+ if (num_online_cpus() != 1) {
+ error = -EPERM;
+ goto Enable_cpu;
+ }
+
if (freeze_processes()) {
error = -EAGAIN;
goto Thaw;
@@ -75,6 +82,8 @@ static int suspend_prepare(suspend_state_t state)
pm_ops->finish(state);
Thaw:
thaw_processes();
+ Enable_cpu:
+ enable_nonboot_cpus();
pm_restore_console();
return error;
}
@@ -113,6 +122,7 @@ static void suspend_finish(suspend_state_t state)
if (pm_ops && pm_ops->finish)
pm_ops->finish(state);
thaw_processes();
+ enable_nonboot_cpus();
pm_restore_console();
}
@@ -150,20 +160,14 @@ static int enter_state(suspend_state_t state)
goto Unlock;
}
- /* Suspend is hard to get right on SMP. */
- if (num_online_cpus() != 1) {
- error = -EPERM;
- goto Unlock;
- }
-
- pr_debug("PM: Preparing system for suspend\n");
+ pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]);
if ((error = suspend_prepare(state)))
goto Unlock;
- pr_debug("PM: Entering state.\n");
+ pr_debug("PM: Entering %s sleep\n", pm_states[state]);
error = suspend_enter(state);
- pr_debug("PM: Finishing up.\n");
+ pr_debug("PM: Finishing wakeup.\n");
suspend_finish(state);
Unlock:
up(&pm_sem);
diff --git a/kernel/power/process.c b/kernel/power/process.c
index 78d92dc6a1e..0a086640bcf 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -32,7 +32,7 @@ static inline int freezeable(struct task_struct * p)
}
/* Refrigerator is place where frozen processes are stored :-). */
-void refrigerator(unsigned long flag)
+void refrigerator(void)
{
/* Hmm, should we be allowed to suspend when there are realtime
processes around? */
@@ -41,14 +41,13 @@ void refrigerator(unsigned long flag)
current->state = TASK_UNINTERRUPTIBLE;
pr_debug("%s entered refrigerator\n", current->comm);
printk("=");
- current->flags &= ~PF_FREEZE;
+ frozen_process(current);
spin_lock_irq(&current->sighand->siglock);
recalc_sigpending(); /* We sent fake signal, clean it up */
spin_unlock_irq(&current->sighand->siglock);
- current->flags |= PF_FROZEN;
- while (current->flags & PF_FROZEN)
+ while (frozen(current))
schedule();
pr_debug("%s left refrigerator\n", current->comm);
current->state = save;
@@ -57,10 +56,10 @@ void refrigerator(unsigned long flag)
/* 0 = success, else # of processes that we failed to stop */
int freeze_processes(void)
{
- int todo;
- unsigned long start_time;
+ int todo;
+ unsigned long start_time;
struct task_struct *g, *p;
-
+
printk( "Stopping tasks: " );
start_time = jiffies;
do {
@@ -70,14 +69,12 @@ int freeze_processes(void)
unsigned long flags;
if (!freezeable(p))
continue;
- if ((p->flags & PF_FROZEN) ||
+ if ((frozen(p)) ||
(p->state == TASK_TRACED) ||
(p->state == TASK_STOPPED))
continue;
- /* FIXME: smp problem here: we may not access other process' flags
- without locking */
- p->flags |= PF_FREEZE;
+ freeze(p);
spin_lock_irqsave(&p->sighand->siglock, flags);
signal_wake_up(p, 0);
spin_unlock_irqrestore(&p->sighand->siglock, flags);
@@ -91,7 +88,7 @@ int freeze_processes(void)
return todo;
}
} while(todo);
-
+
printk( "|\n" );
BUG_ON(in_atomic());
return 0;
@@ -106,10 +103,7 @@ void thaw_processes(void)
do_each_thread(g, p) {
if (!freezeable(p))
continue;
- if (p->flags & PF_FROZEN) {
- p->flags &= ~PF_FROZEN;
- wake_up_process(p);
- } else
+ if (!thaw_process(p))
printk(KERN_INFO " Strange, %s not stopped\n", p->comm );
} while_each_thread(g, p);
diff --git a/kernel/power/smp.c b/kernel/power/smp.c
index cba3584b80f..bbe23079c62 100644
--- a/kernel/power/smp.c
+++ b/kernel/power/smp.c
@@ -13,73 +13,52 @@
#include <linux/interrupt.h>
#include <linux/suspend.h>
#include <linux/module.h>
+#include <linux/cpu.h>
#include <asm/atomic.h>
#include <asm/tlbflush.h>
-static atomic_t cpu_counter, freeze;
-
-
-static void smp_pause(void * data)
-{
- struct saved_context ctxt;
- __save_processor_state(&ctxt);
- printk("Sleeping in:\n");
- dump_stack();
- atomic_inc(&cpu_counter);
- while (atomic_read(&freeze)) {
- /* FIXME: restore takes place at random piece inside this.
- This should probably be written in assembly, and
- preserve general-purpose registers, too
-
- What about stack? We may need to move to new stack here.
-
- This should better be ran with interrupts disabled.
- */
- cpu_relax();
- barrier();
- }
- atomic_dec(&cpu_counter);
- __restore_processor_state(&ctxt);
-}
-
-static cpumask_t oldmask;
+/* This is protected by pm_sem semaphore */
+static cpumask_t frozen_cpus;
void disable_nonboot_cpus(void)
{
- oldmask = current->cpus_allowed;
- set_cpus_allowed(current, cpumask_of_cpu(0));
- printk("Freezing CPUs (at %d)", _smp_processor_id());
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(HZ);
- printk("...");
- BUG_ON(_smp_processor_id() != 0);
-
- /* FIXME: for this to work, all the CPUs must be running
- * "idle" thread (or we deadlock). Is that guaranteed? */
+ int cpu, error;
- atomic_set(&cpu_counter, 0);
- atomic_set(&freeze, 1);
- smp_call_function(smp_pause, NULL, 0, 0);
- while (atomic_read(&cpu_counter) < (num_online_cpus() - 1)) {
- cpu_relax();
- barrier();
+ error = 0;
+ cpus_clear(frozen_cpus);
+ printk("Freezing cpus ...\n");
+ for_each_online_cpu(cpu) {
+ if (cpu == 0)
+ continue;
+ error = cpu_down(cpu);
+ if (!error) {
+ cpu_set(cpu, frozen_cpus);
+ printk("CPU%d is down\n", cpu);
+ continue;
+ }
+ printk("Error taking cpu %d down: %d\n", cpu, error);
}
- printk("ok\n");
+ BUG_ON(smp_processor_id() != 0);
+ if (error)
+ panic("cpus not sleeping");
}
void enable_nonboot_cpus(void)
{
- printk("Restarting CPUs");
- atomic_set(&freeze, 0);
- while (atomic_read(&cpu_counter)) {
- cpu_relax();
- barrier();
- }
- printk("...");
- set_cpus_allowed(current, oldmask);
- schedule();
- printk("ok\n");
+ int cpu, error;
+ printk("Thawing cpus ...\n");
+ for_each_cpu_mask(cpu, frozen_cpus) {
+ error = smp_prepare_cpu(cpu);
+ if (!error)
+ error = cpu_up(cpu);
+ if (!error) {
+ printk("CPU%d is up\n", cpu);
+ continue;
+ }
+ printk("Error taking cpu %d up: %d\n", cpu, error);
+ panic("Not enough cpus");
+ }
+ cpus_clear(frozen_cpus);
}
-
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index 90b3b68dee3..c285fc5a232 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -10,12 +10,12 @@
* This file is released under the GPLv2.
*
* I'd like to thank the following people for their work:
- *
+ *
* Pavel Machek <pavel@ucw.cz>:
* Modifications, defectiveness pointing, being with me at the very beginning,
* suspend to swap space, stop all tasks. Port to 2.4.18-ac and 2.5.17.
*
- * Steve Doddi <dirk@loth.demon.co.uk>:
+ * Steve Doddi <dirk@loth.demon.co.uk>:
* Support the possibility of hardware state restoring.
*
* Raph <grey.havens@earthling.net>:
@@ -81,14 +81,14 @@ static int nr_copy_pages_check;
extern char resume_file[];
/* Local variables that should not be affected by save */
-unsigned int nr_copy_pages __nosavedata = 0;
+static unsigned int nr_copy_pages __nosavedata = 0;
/* Suspend pagedir is allocated before final copy, therefore it
- must be freed after resume
+ must be freed after resume
Warning: this is evil. There are actually two pagedirs at time of
resume. One is "pagedir_save", which is empty frame allocated at
- time of suspend, that must be freed. Second is "pagedir_nosave",
+ time of suspend, that must be freed. Second is "pagedir_nosave",
allocated at time of resume, that travels through memory not to
collide with anything.
@@ -132,7 +132,7 @@ static int mark_swapfiles(swp_entry_t prev)
{
int error;
- rw_swap_page_sync(READ,
+ rw_swap_page_sync(READ,
swp_entry(root_swap, 0),
virt_to_page((unsigned long)&swsusp_header));
if (!memcmp("SWAP-SPACE",swsusp_header.sig, 10) ||
@@ -140,7 +140,7 @@ static int mark_swapfiles(swp_entry_t prev)
memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10);
memcpy(swsusp_header.sig,SWSUSP_SIG, 10);
swsusp_header.swsusp_info = prev;
- error = rw_swap_page_sync(WRITE,
+ error = rw_swap_page_sync(WRITE,
swp_entry(root_swap, 0),
virt_to_page((unsigned long)
&swsusp_header));
@@ -174,22 +174,22 @@ static int is_resume_device(const struct swap_info_struct *swap_info)
static int swsusp_swap_check(void) /* This is called before saving image */
{
int i, len;
-
+
len=strlen(resume_file);
root_swap = 0xFFFF;
-
+
swap_list_lock();
- for(i=0; i<MAX_SWAPFILES; i++) {
+ for (i=0; i<MAX_SWAPFILES; i++) {
if (swap_info[i].flags == 0) {
swapfile_used[i]=SWAPFILE_UNUSED;
} else {
- if(!len) {
+ if (!len) {
printk(KERN_WARNING "resume= option should be used to set suspend device" );
- if(root_swap == 0xFFFF) {
+ if (root_swap == 0xFFFF) {
swapfile_used[i] = SWAPFILE_SUSPEND;
root_swap = i;
} else
- swapfile_used[i] = SWAPFILE_IGNORED;
+ swapfile_used[i] = SWAPFILE_IGNORED;
} else {
/* we ignore all swap devices that are not the resume_file */
if (is_resume_device(&swap_info[i])) {
@@ -209,15 +209,15 @@ static int swsusp_swap_check(void) /* This is called before saving image */
* This is called after saving image so modification
* will be lost after resume... and that's what we want.
* we make the device unusable. A new call to
- * lock_swapdevices can unlock the devices.
+ * lock_swapdevices can unlock the devices.
*/
static void lock_swapdevices(void)
{
int i;
swap_list_lock();
- for(i = 0; i< MAX_SWAPFILES; i++)
- if(swapfile_used[i] == SWAPFILE_IGNORED) {
+ for (i = 0; i< MAX_SWAPFILES; i++)
+ if (swapfile_used[i] == SWAPFILE_IGNORED) {
swap_info[i].flags ^= 0xFF;
}
swap_list_unlock();
@@ -229,7 +229,7 @@ static void lock_swapdevices(void)
* @loc: Place to store the entry we used.
*
* Allocate a new swap entry and 'sync' it. Note we discard -EIO
- * errors. That is an artifact left over from swsusp. It did not
+ * errors. That is an artifact left over from swsusp. It did not
* check the return of rw_swap_page_sync() at all, since most pages
* written back to swap would return -EIO.
* This is a partial improvement, since we will at least return other
@@ -241,7 +241,7 @@ static int write_page(unsigned long addr, swp_entry_t * loc)
int error = 0;
entry = get_swap_page();
- if (swp_offset(entry) &&
+ if (swp_offset(entry) &&
swapfile_used[swp_type(entry)] == SWAPFILE_SUSPEND) {
error = rw_swap_page_sync(WRITE, entry,
virt_to_page(addr));
@@ -257,7 +257,7 @@ static int write_page(unsigned long addr, swp_entry_t * loc)
/**
* data_free - Free the swap entries used by the saved image.
*
- * Walk the list of used swap entries and free each one.
+ * Walk the list of used swap entries and free each one.
* This is only used for cleanup when suspend fails.
*/
static void data_free(void)
@@ -290,7 +290,7 @@ static int data_write(void)
mod = 1;
printk( "Writing data to swap (%d pages)... ", nr_copy_pages );
- for_each_pbe(p, pagedir_nosave) {
+ for_each_pbe (p, pagedir_nosave) {
if (!(i%mod))
printk( "\b\b\b\b%3d%%", i / mod );
if ((error = write_page(p->address, &(p->swap_address))))
@@ -335,7 +335,7 @@ static int close_swap(void)
dump_info();
error = write_page((unsigned long)&swsusp_info, &entry);
- if (!error) {
+ if (!error) {
printk( "S" );
error = mark_swapfiles(entry);
printk( "|\n" );
@@ -370,7 +370,7 @@ static int write_pagedir(void)
struct pbe * pbe;
printk( "Writing pagedir...");
- for_each_pb_page(pbe, pagedir_nosave) {
+ for_each_pb_page (pbe, pagedir_nosave) {
if ((error = write_page((unsigned long)pbe, &swsusp_info.pagedir[n++])))
return error;
}
@@ -472,7 +472,7 @@ static int save_highmem(void)
int res = 0;
pr_debug("swsusp: Saving Highmem\n");
- for_each_zone(zone) {
+ for_each_zone (zone) {
if (is_highmem(zone))
res = save_highmem_zone(zone);
if (res)
@@ -547,7 +547,7 @@ static void count_data_pages(void)
nr_copy_pages = 0;
- for_each_zone(zone) {
+ for_each_zone (zone) {
if (is_highmem(zone))
continue;
mark_free_pages(zone);
@@ -562,9 +562,9 @@ static void copy_data_pages(void)
struct zone *zone;
unsigned long zone_pfn;
struct pbe * pbe = pagedir_nosave;
-
+
pr_debug("copy_data_pages(): pages to copy: %d\n", nr_copy_pages);
- for_each_zone(zone) {
+ for_each_zone (zone) {
if (is_highmem(zone))
continue;
mark_free_pages(zone);
@@ -702,7 +702,7 @@ static void free_image_pages(void)
{
struct pbe * p;
- for_each_pbe(p, pagedir_save) {
+ for_each_pbe (p, pagedir_save) {
if (p->address) {
ClearPageNosave(virt_to_page(p->address));
free_page(p->address);
@@ -719,7 +719,7 @@ static int alloc_image_pages(void)
{
struct pbe * p;
- for_each_pbe(p, pagedir_save) {
+ for_each_pbe (p, pagedir_save) {
p->address = get_zeroed_page(GFP_ATOMIC | __GFP_COLD);
if (!p->address)
return -ENOMEM;
@@ -740,7 +740,7 @@ void swsusp_free(void)
/**
* enough_free_mem - Make sure we enough free memory to snapshot.
*
- * Returns TRUE or FALSE after checking the number of available
+ * Returns TRUE or FALSE after checking the number of available
* free pages.
*/
@@ -758,11 +758,11 @@ static int enough_free_mem(void)
/**
* enough_swap - Make sure we have enough swap to save the image.
*
- * Returns TRUE or FALSE after checking the total amount of swap
+ * Returns TRUE or FALSE after checking the total amount of swap
* space avaiable.
*
* FIXME: si_swapinfo(&i) returns all swap devices information.
- * We should only consider resume_device.
+ * We should only consider resume_device.
*/
static int enough_swap(void)
@@ -781,18 +781,18 @@ static int swsusp_alloc(void)
{
int error;
+ pagedir_nosave = NULL;
+ nr_copy_pages = calc_nr(nr_copy_pages);
+
pr_debug("suspend: (pages needed: %d + %d free: %d)\n",
nr_copy_pages, PAGES_FOR_IO, nr_free_pages());
- pagedir_nosave = NULL;
if (!enough_free_mem())
return -ENOMEM;
if (!enough_swap())
return -ENOSPC;
- nr_copy_pages = calc_nr(nr_copy_pages);
-
if (!(pagedir_save = alloc_pagedir(nr_copy_pages))) {
printk(KERN_ERR "suspend: Allocating pagedir failed.\n");
return -ENOMEM;
@@ -827,8 +827,8 @@ static int suspend_prepare_image(void)
error = swsusp_alloc();
if (error)
return error;
-
- /* During allocating of suspend pagedir, new cold pages may appear.
+
+ /* During allocating of suspend pagedir, new cold pages may appear.
* Kill them.
*/
drain_local_pages();
@@ -929,21 +929,6 @@ int swsusp_resume(void)
return error;
}
-/* More restore stuff */
-
-/*
- * Returns true if given address/order collides with any orig_address
- */
-static int does_collide_order(unsigned long addr, int order)
-{
- int i;
-
- for (i=0; i < (1<<order); i++)
- if (!PageNosaveFree(virt_to_page(addr + i * PAGE_SIZE)))
- return 1;
- return 0;
-}
-
/**
* On resume, for storing the PBE list and the image,
* we can only use memory pages that do not conflict with the pages
@@ -973,7 +958,7 @@ static unsigned long get_usable_page(unsigned gfp_mask)
unsigned long m;
m = get_zeroed_page(gfp_mask);
- while (does_collide_order(m, 0)) {
+ while (!PageNosaveFree(virt_to_page(m))) {
eat_page((void *)m);
m = get_zeroed_page(gfp_mask);
if (!m)
@@ -1045,7 +1030,7 @@ static struct pbe * swsusp_pagedir_relocate(struct pbe *pblist)
/* Set page flags */
- for_each_zone(zone) {
+ for_each_zone (zone) {
for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn)
SetPageNosaveFree(pfn_to_page(zone_pfn +
zone->zone_start_pfn));
@@ -1061,7 +1046,7 @@ static struct pbe * swsusp_pagedir_relocate(struct pbe *pblist)
/* Relocate colliding pages */
for_each_pb_page (pbpage, pblist) {
- if (does_collide_order((unsigned long)pbpage, 0)) {
+ if (!PageNosaveFree(virt_to_page((unsigned long)pbpage))) {
m = (void *)get_usable_page(GFP_ATOMIC | __GFP_COLD);
if (!m) {
error = -ENOMEM;
@@ -1193,8 +1178,10 @@ static const char * sanity_check(void)
return "version";
if (strcmp(swsusp_info.uts.machine,system_utsname.machine))
return "machine";
+#if 0
if(swsusp_info.cpus != num_online_cpus())
return "number of cpus";
+#endif
return NULL;
}
diff --git a/kernel/printk.c b/kernel/printk.c
index 290a07ce2c8..5092397fac2 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -160,42 +160,6 @@ static int __init console_setup(char *str)
__setup("console=", console_setup);
-/**
- * add_preferred_console - add a device to the list of preferred consoles.
- *
- * The last preferred console added will be used for kernel messages
- * and stdin/out/err for init. Normally this is used by console_setup
- * above to handle user-supplied console arguments; however it can also
- * be used by arch-specific code either to override the user or more
- * commonly to provide a default console (ie from PROM variables) when
- * the user has not supplied one.
- */
-int __init add_preferred_console(char *name, int idx, char *options)
-{
- struct console_cmdline *c;
- int i;
-
- /*
- * See if this tty is not yet registered, and
- * if we have a slot free.
- */
- for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
- if (strcmp(console_cmdline[i].name, name) == 0 &&
- console_cmdline[i].index == idx) {
- selected_console = i;
- return 0;
- }
- if (i == MAX_CMDLINECONSOLES)
- return -E2BIG;
- selected_console = i;
- c = &console_cmdline[i];
- memcpy(c->name, name, sizeof(c->name));
- c->name[sizeof(c->name) - 1] = 0;
- c->options = options;
- c->index = idx;
- return 0;
-}
-
static int __init log_buf_len_setup(char *str)
{
unsigned long size = memparse(str, &str);
@@ -624,8 +588,7 @@ asmlinkage int vprintk(const char *fmt, va_list args)
log_level_unknown = 1;
}
- if (!cpu_online(smp_processor_id()) &&
- system_state != SYSTEM_RUNNING) {
+ if (!cpu_online(smp_processor_id())) {
/*
* Some console drivers may assume that per-cpu resources have
* been allocated. So don't allow them to be called by this
@@ -671,6 +634,42 @@ static void call_console_drivers(unsigned long start, unsigned long end) {}
#endif
/**
+ * add_preferred_console - add a device to the list of preferred consoles.
+ *
+ * The last preferred console added will be used for kernel messages
+ * and stdin/out/err for init. Normally this is used by console_setup
+ * above to handle user-supplied console arguments; however it can also
+ * be used by arch-specific code either to override the user or more
+ * commonly to provide a default console (ie from PROM variables) when
+ * the user has not supplied one.
+ */
+int __init add_preferred_console(char *name, int idx, char *options)
+{
+ struct console_cmdline *c;
+ int i;
+
+ /*
+ * See if this tty is not yet registered, and
+ * if we have a slot free.
+ */
+ for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
+ if (strcmp(console_cmdline[i].name, name) == 0 &&
+ console_cmdline[i].index == idx) {
+ selected_console = i;
+ return 0;
+ }
+ if (i == MAX_CMDLINECONSOLES)
+ return -E2BIG;
+ selected_console = i;
+ c = &console_cmdline[i];
+ memcpy(c->name, name, sizeof(c->name));
+ c->name[sizeof(c->name) - 1] = 0;
+ c->options = options;
+ c->index = idx;
+ return 0;
+}
+
+/**
* acquire_console_sem - lock the console system for exclusive use.
*
* Acquires a semaphore which guarantees that the caller has
@@ -876,8 +875,10 @@ void register_console(struct console * console)
break;
console->flags |= CON_ENABLED;
console->index = console_cmdline[i].index;
- if (i == preferred_console)
+ if (i == selected_console) {
console->flags |= CON_CONSDEV;
+ preferred_console = selected_console;
+ }
break;
}
@@ -897,6 +898,8 @@ void register_console(struct console * console)
if ((console->flags & CON_CONSDEV) || console_drivers == NULL) {
console->next = console_drivers;
console_drivers = console;
+ if (console->next)
+ console->next->flags &= ~CON_CONSDEV;
} else {
console->next = console_drivers->next;
console_drivers->next = console;
@@ -937,10 +940,14 @@ int unregister_console(struct console * console)
/* If last console is removed, we re-enable picking the first
* one that gets registered. Without that, pmac early boot console
* would prevent fbcon from taking over.
+ *
+ * If this isn't the last console and it has CON_CONSDEV set, we
+ * need to set it on the next preferred console.
*/
if (console_drivers == NULL)
preferred_console = selected_console;
-
+ else if (console->flags & CON_CONSDEV)
+ console_drivers->flags |= CON_CONSDEV;
release_console_sem();
return res;
diff --git a/kernel/profile.c b/kernel/profile.c
index 0221a50ca86..ad8cbb75ffa 100644
--- a/kernel/profile.c
+++ b/kernel/profile.c
@@ -49,15 +49,19 @@ static DECLARE_MUTEX(profile_flip_mutex);
static int __init profile_setup(char * str)
{
+ static char __initdata schedstr[] = "schedule";
int par;
- if (!strncmp(str, "schedule", 8)) {
+ if (!strncmp(str, schedstr, strlen(schedstr))) {
prof_on = SCHED_PROFILING;
- printk(KERN_INFO "kernel schedule profiling enabled\n");
- if (str[7] == ',')
- str += 8;
- }
- if (get_option(&str,&par)) {
+ if (str[strlen(schedstr)] == ',')
+ str += strlen(schedstr) + 1;
+ if (get_option(&str, &par))
+ prof_shift = par;
+ printk(KERN_INFO
+ "kernel schedule profiling enabled (shift: %ld)\n",
+ prof_shift);
+ } else if (get_option(&str, &par)) {
prof_shift = par;
prof_on = CPU_PROFILING;
printk(KERN_INFO "kernel profiling enabled (shift: %ld)\n",
diff --git a/kernel/resource.c b/kernel/resource.c
index 52f696f11ad..26967e04220 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -263,7 +263,7 @@ static int find_resource(struct resource *root, struct resource *new,
new->start = min;
if (new->end > max)
new->end = max;
- new->start = (new->start + align - 1) & ~(align - 1);
+ new->start = ALIGN(new->start, align);
if (alignf)
alignf(alignf_data, new, size, align);
if (new->start < new->end && new->end - new->start >= size - 1) {
diff --git a/kernel/sched.c b/kernel/sched.c
index 0dc3158667a..a07cff90d84 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -166,7 +166,7 @@
#define SCALE_PRIO(x, prio) \
max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO/2), MIN_TIMESLICE)
-static inline unsigned int task_timeslice(task_t *p)
+static unsigned int task_timeslice(task_t *p)
{
if (p->static_prio < NICE_TO_PRIO(0))
return SCALE_PRIO(DEF_TIMESLICE*4, p->static_prio);
@@ -206,7 +206,7 @@ struct runqueue {
*/
unsigned long nr_running;
#ifdef CONFIG_SMP
- unsigned long cpu_load;
+ unsigned long cpu_load[3];
#endif
unsigned long long nr_switches;
@@ -260,23 +260,87 @@ struct runqueue {
static DEFINE_PER_CPU(struct runqueue, runqueues);
+/*
+ * The domain tree (rq->sd) is protected by RCU's quiescent state transition.
+ * See detach_destroy_domains: synchronize_sched for details.
+ *
+ * The domain tree of any CPU may only be accessed from within
+ * preempt-disabled sections.
+ */
#define for_each_domain(cpu, domain) \
- for (domain = cpu_rq(cpu)->sd; domain; domain = domain->parent)
+for (domain = rcu_dereference(cpu_rq(cpu)->sd); domain; domain = domain->parent)
#define cpu_rq(cpu) (&per_cpu(runqueues, (cpu)))
#define this_rq() (&__get_cpu_var(runqueues))
#define task_rq(p) cpu_rq(task_cpu(p))
#define cpu_curr(cpu) (cpu_rq(cpu)->curr)
-/*
- * Default context-switch locking:
- */
#ifndef prepare_arch_switch
-# define prepare_arch_switch(rq, next) do { } while (0)
-# define finish_arch_switch(rq, next) spin_unlock_irq(&(rq)->lock)
-# define task_running(rq, p) ((rq)->curr == (p))
+# define prepare_arch_switch(next) do { } while (0)
+#endif
+#ifndef finish_arch_switch
+# define finish_arch_switch(prev) do { } while (0)
#endif
+#ifndef __ARCH_WANT_UNLOCKED_CTXSW
+static inline int task_running(runqueue_t *rq, task_t *p)
+{
+ return rq->curr == p;
+}
+
+static inline void prepare_lock_switch(runqueue_t *rq, task_t *next)
+{
+}
+
+static inline void finish_lock_switch(runqueue_t *rq, task_t *prev)
+{
+ spin_unlock_irq(&rq->lock);
+}
+
+#else /* __ARCH_WANT_UNLOCKED_CTXSW */
+static inline int task_running(runqueue_t *rq, task_t *p)
+{
+#ifdef CONFIG_SMP
+ return p->oncpu;
+#else
+ return rq->curr == p;
+#endif
+}
+
+static inline void prepare_lock_switch(runqueue_t *rq, task_t *next)
+{
+#ifdef CONFIG_SMP
+ /*
+ * We can optimise this out completely for !SMP, because the
+ * SMP rebalancing from interrupt is the only thing that cares
+ * here.
+ */
+ next->oncpu = 1;
+#endif
+#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
+ spin_unlock_irq(&rq->lock);
+#else
+ spin_unlock(&rq->lock);
+#endif
+}
+
+static inline void finish_lock_switch(runqueue_t *rq, task_t *prev)
+{
+#ifdef CONFIG_SMP
+ /*
+ * After ->oncpu is cleared, the task can be moved to a different CPU.
+ * We must ensure this doesn't happen until the switch is completely
+ * finished.
+ */
+ smp_wmb();
+ prev->oncpu = 0;
+#endif
+#ifndef __ARCH_WANT_INTERRUPTS_ON_CTXSW
+ local_irq_enable();
+#endif
+}
+#endif /* __ARCH_WANT_UNLOCKED_CTXSW */
+
/*
* task_rq_lock - lock the runqueue a given task resides on and disable
* interrupts. Note the ordering: we can safely lookup the task_rq without
@@ -309,7 +373,7 @@ static inline void task_rq_unlock(runqueue_t *rq, unsigned long *flags)
* bump this up when changing the output format or the meaning of an existing
* format, so that tools can adapt (or abort)
*/
-#define SCHEDSTAT_VERSION 11
+#define SCHEDSTAT_VERSION 12
static int show_schedstat(struct seq_file *seq, void *v)
{
@@ -338,6 +402,7 @@ static int show_schedstat(struct seq_file *seq, void *v)
#ifdef CONFIG_SMP
/* domain-specific stats */
+ preempt_disable();
for_each_domain(cpu, sd) {
enum idle_type itype;
char mask_str[NR_CPUS];
@@ -356,11 +421,13 @@ static int show_schedstat(struct seq_file *seq, void *v)
sd->lb_nobusyq[itype],
sd->lb_nobusyg[itype]);
}
- seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu %lu\n",
+ seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
sd->alb_cnt, sd->alb_failed, sd->alb_pushed,
- sd->sbe_pushed, sd->sbe_attempts,
+ sd->sbe_cnt, sd->sbe_balanced, sd->sbe_pushed,
+ sd->sbf_cnt, sd->sbf_balanced, sd->sbf_pushed,
sd->ttwu_wake_remote, sd->ttwu_move_affine, sd->ttwu_move_balance);
}
+ preempt_enable();
#endif
}
return 0;
@@ -414,22 +481,6 @@ static inline runqueue_t *this_rq_lock(void)
return rq;
}
-#ifdef CONFIG_SCHED_SMT
-static int cpu_and_siblings_are_idle(int cpu)
-{
- int sib;
- for_each_cpu_mask(sib, cpu_sibling_map[cpu]) {
- if (idle_cpu(sib))
- continue;
- return 0;
- }
-
- return 1;
-}
-#else
-#define cpu_and_siblings_are_idle(A) idle_cpu(A)
-#endif
-
#ifdef CONFIG_SCHEDSTATS
/*
* Called when a process is dequeued from the active array and given
@@ -622,7 +673,7 @@ static inline void __activate_idle_task(task_t *p, runqueue_t *rq)
rq->nr_running++;
}
-static void recalc_task_prio(task_t *p, unsigned long long now)
+static int recalc_task_prio(task_t *p, unsigned long long now)
{
/* Caller must always ensure 'now >= p->timestamp' */
unsigned long long __sleep_time = now - p->timestamp;
@@ -681,7 +732,7 @@ static void recalc_task_prio(task_t *p, unsigned long long now)
}
}
- p->prio = effective_prio(p);
+ return effective_prio(p);
}
/*
@@ -704,7 +755,7 @@ static void activate_task(task_t *p, runqueue_t *rq, int local)
}
#endif
- recalc_task_prio(p, now);
+ p->prio = recalc_task_prio(p, now);
/*
* This checks to make sure it's not an uninterruptible task
@@ -782,22 +833,12 @@ inline int task_curr(const task_t *p)
}
#ifdef CONFIG_SMP
-enum request_type {
- REQ_MOVE_TASK,
- REQ_SET_DOMAIN,
-};
-
typedef struct {
struct list_head list;
- enum request_type type;
- /* For REQ_MOVE_TASK */
task_t *task;
int dest_cpu;
- /* For REQ_SET_DOMAIN */
- struct sched_domain *sd;
-
struct completion done;
} migration_req_t;
@@ -819,7 +860,6 @@ static int migrate_task(task_t *p, int dest_cpu, migration_req_t *req)
}
init_completion(&req->done);
- req->type = REQ_MOVE_TASK;
req->task = p;
req->dest_cpu = dest_cpu;
list_add(&req->list, &rq->migration_queue);
@@ -886,26 +926,154 @@ void kick_process(task_t *p)
* We want to under-estimate the load of migration sources, to
* balance conservatively.
*/
-static inline unsigned long source_load(int cpu)
+static inline unsigned long source_load(int cpu, int type)
{
runqueue_t *rq = cpu_rq(cpu);
unsigned long load_now = rq->nr_running * SCHED_LOAD_SCALE;
+ if (type == 0)
+ return load_now;
- return min(rq->cpu_load, load_now);
+ return min(rq->cpu_load[type-1], load_now);
}
/*
* Return a high guess at the load of a migration-target cpu
*/
-static inline unsigned long target_load(int cpu)
+static inline unsigned long target_load(int cpu, int type)
{
runqueue_t *rq = cpu_rq(cpu);
unsigned long load_now = rq->nr_running * SCHED_LOAD_SCALE;
+ if (type == 0)
+ return load_now;
- return max(rq->cpu_load, load_now);
+ return max(rq->cpu_load[type-1], load_now);
}
-#endif
+/*
+ * find_idlest_group finds and returns the least busy CPU group within the
+ * domain.
+ */
+static struct sched_group *
+find_idlest_group(struct sched_domain *sd, struct task_struct *p, int this_cpu)
+{
+ struct sched_group *idlest = NULL, *this = NULL, *group = sd->groups;
+ unsigned long min_load = ULONG_MAX, this_load = 0;
+ int load_idx = sd->forkexec_idx;
+ int imbalance = 100 + (sd->imbalance_pct-100)/2;
+
+ do {
+ unsigned long load, avg_load;
+ int local_group;
+ int i;
+
+ local_group = cpu_isset(this_cpu, group->cpumask);
+ /* XXX: put a cpus allowed check */
+
+ /* Tally up the load of all CPUs in the group */
+ avg_load = 0;
+
+ for_each_cpu_mask(i, group->cpumask) {
+ /* Bias balancing toward cpus of our domain */
+ if (local_group)
+ load = source_load(i, load_idx);
+ else
+ load = target_load(i, load_idx);
+
+ avg_load += load;
+ }
+
+ /* Adjust by relative CPU power of the group */
+ avg_load = (avg_load * SCHED_LOAD_SCALE) / group->cpu_power;
+
+ if (local_group) {
+ this_load = avg_load;
+ this = group;
+ } else if (avg_load < min_load) {
+ min_load = avg_load;
+ idlest = group;
+ }
+ group = group->next;
+ } while (group != sd->groups);
+
+ if (!idlest || 100*this_load < imbalance*min_load)
+ return NULL;
+ return idlest;
+}
+
+/*
+ * find_idlest_queue - find the idlest runqueue among the cpus in group.
+ */
+static int find_idlest_cpu(struct sched_group *group, int this_cpu)
+{
+ unsigned long load, min_load = ULONG_MAX;
+ int idlest = -1;
+ int i;
+
+ for_each_cpu_mask(i, group->cpumask) {
+ load = source_load(i, 0);
+
+ if (load < min_load || (load == min_load && i == this_cpu)) {
+ min_load = load;
+ idlest = i;
+ }
+ }
+
+ return idlest;
+}
+
+/*
+ * sched_balance_self: balance the current task (running on cpu) in domains
+ * that have the 'flag' flag set. In practice, this is SD_BALANCE_FORK and
+ * SD_BALANCE_EXEC.
+ *
+ * Balance, ie. select the least loaded group.
+ *
+ * Returns the target CPU number, or the same CPU if no balancing is needed.
+ *
+ * preempt must be disabled.
+ */
+static int sched_balance_self(int cpu, int flag)
+{
+ struct task_struct *t = current;
+ struct sched_domain *tmp, *sd = NULL;
+
+ for_each_domain(cpu, tmp)
+ if (tmp->flags & flag)
+ sd = tmp;
+
+ while (sd) {
+ cpumask_t span;
+ struct sched_group *group;
+ int new_cpu;
+ int weight;
+
+ span = sd->span;
+ group = find_idlest_group(sd, t, cpu);
+ if (!group)
+ goto nextlevel;
+
+ new_cpu = find_idlest_cpu(group, cpu);
+ if (new_cpu == -1 || new_cpu == cpu)
+ goto nextlevel;
+
+ /* Now try balancing at a lower domain level */
+ cpu = new_cpu;
+nextlevel:
+ sd = NULL;
+ weight = cpus_weight(span);
+ for_each_domain(cpu, tmp) {
+ if (weight <= cpus_weight(tmp->span))
+ break;
+ if (tmp->flags & flag)
+ sd = tmp;
+ }
+ /* while loop will break here if sd == NULL */
+ }
+
+ return cpu;
+}
+
+#endif /* CONFIG_SMP */
/*
* wake_idle() will wake a task on an idle cpu if task->cpu is
@@ -927,14 +1095,14 @@ static int wake_idle(int cpu, task_t *p)
for_each_domain(cpu, sd) {
if (sd->flags & SD_WAKE_IDLE) {
- cpus_and(tmp, sd->span, cpu_online_map);
- cpus_and(tmp, tmp, p->cpus_allowed);
+ cpus_and(tmp, sd->span, p->cpus_allowed);
for_each_cpu_mask(i, tmp) {
if (idle_cpu(i))
return i;
}
}
- else break;
+ else
+ break;
}
return cpu;
}
@@ -967,7 +1135,7 @@ static int try_to_wake_up(task_t * p, unsigned int state, int sync)
runqueue_t *rq;
#ifdef CONFIG_SMP
unsigned long load, this_load;
- struct sched_domain *sd;
+ struct sched_domain *sd, *this_sd = NULL;
int new_cpu;
#endif
@@ -986,70 +1154,69 @@ static int try_to_wake_up(task_t * p, unsigned int state, int sync)
if (unlikely(task_running(rq, p)))
goto out_activate;
-#ifdef CONFIG_SCHEDSTATS
+ new_cpu = cpu;
+
schedstat_inc(rq, ttwu_cnt);
if (cpu == this_cpu) {
schedstat_inc(rq, ttwu_local);
- } else {
- for_each_domain(this_cpu, sd) {
- if (cpu_isset(cpu, sd->span)) {
- schedstat_inc(sd, ttwu_wake_remote);
- break;
- }
+ goto out_set_cpu;
+ }
+
+ for_each_domain(this_cpu, sd) {
+ if (cpu_isset(cpu, sd->span)) {
+ schedstat_inc(sd, ttwu_wake_remote);
+ this_sd = sd;
+ break;
}
}
-#endif
- new_cpu = cpu;
- if (cpu == this_cpu || unlikely(!cpu_isset(this_cpu, p->cpus_allowed)))
+ if (unlikely(!cpu_isset(this_cpu, p->cpus_allowed)))
goto out_set_cpu;
- load = source_load(cpu);
- this_load = target_load(this_cpu);
-
/*
- * If sync wakeup then subtract the (maximum possible) effect of
- * the currently running task from the load of the current CPU:
+ * Check for affine wakeup and passive balancing possibilities.
*/
- if (sync)
- this_load -= SCHED_LOAD_SCALE;
+ if (this_sd) {
+ int idx = this_sd->wake_idx;
+ unsigned int imbalance;
- /* Don't pull the task off an idle CPU to a busy one */
- if (load < SCHED_LOAD_SCALE/2 && this_load > SCHED_LOAD_SCALE/2)
- goto out_set_cpu;
+ imbalance = 100 + (this_sd->imbalance_pct - 100) / 2;
- new_cpu = this_cpu; /* Wake to this CPU if we can */
+ load = source_load(cpu, idx);
+ this_load = target_load(this_cpu, idx);
- /*
- * Scan domains for affine wakeup and passive balancing
- * possibilities.
- */
- for_each_domain(this_cpu, sd) {
- unsigned int imbalance;
- /*
- * Start passive balancing when half the imbalance_pct
- * limit is reached.
- */
- imbalance = sd->imbalance_pct + (sd->imbalance_pct - 100) / 2;
+ new_cpu = this_cpu; /* Wake to this CPU if we can */
- if ((sd->flags & SD_WAKE_AFFINE) &&
- !task_hot(p, rq->timestamp_last_tick, sd)) {
+ if (this_sd->flags & SD_WAKE_AFFINE) {
+ unsigned long tl = this_load;
/*
- * This domain has SD_WAKE_AFFINE and p is cache cold
- * in this domain.
+ * If sync wakeup then subtract the (maximum possible)
+ * effect of the currently running task from the load
+ * of the current CPU:
*/
- if (cpu_isset(cpu, sd->span)) {
- schedstat_inc(sd, ttwu_move_affine);
+ if (sync)
+ tl -= SCHED_LOAD_SCALE;
+
+ if ((tl <= load &&
+ tl + target_load(cpu, idx) <= SCHED_LOAD_SCALE) ||
+ 100*(tl + SCHED_LOAD_SCALE) <= imbalance*load) {
+ /*
+ * This domain has SD_WAKE_AFFINE and
+ * p is cache cold in this domain, and
+ * there is no bad imbalance.
+ */
+ schedstat_inc(this_sd, ttwu_move_affine);
goto out_set_cpu;
}
- } else if ((sd->flags & SD_WAKE_BALANCE) &&
- imbalance*this_load <= 100*load) {
- /*
- * This domain has SD_WAKE_BALANCE and there is
- * an imbalance.
- */
- if (cpu_isset(cpu, sd->span)) {
- schedstat_inc(sd, ttwu_move_balance);
+ }
+
+ /*
+ * Start passive balancing when half the imbalance_pct
+ * limit is reached.
+ */
+ if (this_sd->flags & SD_WAKE_BALANCE) {
+ if (imbalance*this_load <= 100*load) {
+ schedstat_inc(this_sd, ttwu_move_balance);
goto out_set_cpu;
}
}
@@ -1120,17 +1287,19 @@ int fastcall wake_up_state(task_t *p, unsigned int state)
return try_to_wake_up(p, state, 0);
}
-#ifdef CONFIG_SMP
-static int find_idlest_cpu(struct task_struct *p, int this_cpu,
- struct sched_domain *sd);
-#endif
-
/*
* Perform scheduler related setup for a newly forked process p.
* p is forked by current.
*/
-void fastcall sched_fork(task_t *p)
+void fastcall sched_fork(task_t *p, int clone_flags)
{
+ int cpu = get_cpu();
+
+#ifdef CONFIG_SMP
+ cpu = sched_balance_self(cpu, SD_BALANCE_FORK);
+#endif
+ set_task_cpu(p, cpu);
+
/*
* We mark the process as running here, but have not actually
* inserted it onto the runqueue yet. This guarantees that
@@ -1140,17 +1309,14 @@ void fastcall sched_fork(task_t *p)
p->state = TASK_RUNNING;
INIT_LIST_HEAD(&p->run_list);
p->array = NULL;
- spin_lock_init(&p->switch_lock);
#ifdef CONFIG_SCHEDSTATS
memset(&p->sched_info, 0, sizeof(p->sched_info));
#endif
+#if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW)
+ p->oncpu = 0;
+#endif
#ifdef CONFIG_PREEMPT
- /*
- * During context-switch we hold precisely one spinlock, which
- * schedule_tail drops. (in the common case it's this_rq()->lock,
- * but it also can be p->switch_lock.) So we compensate with a count
- * of 1. Also, we want to start with kernel preemption disabled.
- */
+ /* Want to start with kernel preemption disabled. */
p->thread_info->preempt_count = 1;
#endif
/*
@@ -1174,12 +1340,10 @@ void fastcall sched_fork(task_t *p)
* runqueue lock is not a problem.
*/
current->time_slice = 1;
- preempt_disable();
scheduler_tick();
- local_irq_enable();
- preempt_enable();
- } else
- local_irq_enable();
+ }
+ local_irq_enable();
+ put_cpu();
}
/*
@@ -1196,10 +1360,9 @@ void fastcall wake_up_new_task(task_t * p, unsigned long clone_flags)
runqueue_t *rq, *this_rq;
rq = task_rq_lock(p, &flags);
- cpu = task_cpu(p);
- this_cpu = smp_processor_id();
-
BUG_ON(p->state != TASK_RUNNING);
+ this_cpu = smp_processor_id();
+ cpu = task_cpu(p);
/*
* We decrease the sleep average of forking parents
@@ -1296,22 +1459,40 @@ void fastcall sched_exit(task_t * p)
}
/**
+ * prepare_task_switch - prepare to switch tasks
+ * @rq: the runqueue preparing to switch
+ * @next: the task we are going to switch to.
+ *
+ * This is called with the rq lock held and interrupts off. It must
+ * be paired with a subsequent finish_task_switch after the context
+ * switch.
+ *
+ * prepare_task_switch sets up locking and calls architecture specific
+ * hooks.
+ */
+static inline void prepare_task_switch(runqueue_t *rq, task_t *next)
+{
+ prepare_lock_switch(rq, next);
+ prepare_arch_switch(next);
+}
+
+/**
* finish_task_switch - clean up after a task-switch
* @prev: the thread we just switched away from.
*
- * We enter this with the runqueue still locked, and finish_arch_switch()
- * will unlock it along with doing any other architecture-specific cleanup
- * actions.
+ * finish_task_switch must be called after the context switch, paired
+ * with a prepare_task_switch call before the context switch.
+ * finish_task_switch will reconcile locking set up by prepare_task_switch,
+ * and do any other architecture-specific cleanup actions.
*
* Note that we may have delayed dropping an mm in context_switch(). If
* so, we finish that here outside of the runqueue lock. (Doing it
* with the lock held can cause deadlocks; see schedule() for
* details.)
*/
-static inline void finish_task_switch(task_t *prev)
+static inline void finish_task_switch(runqueue_t *rq, task_t *prev)
__releases(rq->lock)
{
- runqueue_t *rq = this_rq();
struct mm_struct *mm = rq->prev_mm;
unsigned long prev_task_flags;
@@ -1329,7 +1510,8 @@ static inline void finish_task_switch(task_t *prev)
* Manfred Spraul <manfred@colorfullife.com>
*/
prev_task_flags = prev->flags;
- finish_arch_switch(rq, prev);
+ finish_arch_switch(prev);
+ finish_lock_switch(rq, prev);
if (mm)
mmdrop(mm);
if (unlikely(prev_task_flags & PF_DEAD))
@@ -1343,8 +1525,12 @@ static inline void finish_task_switch(task_t *prev)
asmlinkage void schedule_tail(task_t *prev)
__releases(rq->lock)
{
- finish_task_switch(prev);
-
+ runqueue_t *rq = this_rq();
+ finish_task_switch(rq, prev);
+#ifdef __ARCH_WANT_UNLOCKED_CTXSW
+ /* In this case, finish_task_switch does not reenable preemption */
+ preempt_enable();
+#endif
if (current->set_child_tid)
put_user(current->pid, current->set_child_tid);
}
@@ -1494,51 +1680,6 @@ static void double_lock_balance(runqueue_t *this_rq, runqueue_t *busiest)
}
/*
- * find_idlest_cpu - find the least busy runqueue.
- */
-static int find_idlest_cpu(struct task_struct *p, int this_cpu,
- struct sched_domain *sd)
-{
- unsigned long load, min_load, this_load;
- int i, min_cpu;
- cpumask_t mask;
-
- min_cpu = UINT_MAX;
- min_load = ULONG_MAX;
-
- cpus_and(mask, sd->span, p->cpus_allowed);
-
- for_each_cpu_mask(i, mask) {
- load = target_load(i);
-
- if (load < min_load) {
- min_cpu = i;
- min_load = load;
-
- /* break out early on an idle CPU: */
- if (!min_load)
- break;
- }
- }
-
- /* add +1 to account for the new task */
- this_load = source_load(this_cpu) + SCHED_LOAD_SCALE;
-
- /*
- * Would with the addition of the new task to the
- * current CPU there be an imbalance between this
- * CPU and the idlest CPU?
- *
- * Use half of the balancing threshold - new-context is
- * a good opportunity to balance.
- */
- if (min_load*(100 + (sd->imbalance_pct-100)/2) < this_load*100)
- return min_cpu;
-
- return this_cpu;
-}
-
-/*
* If dest_cpu is allowed for this process, migrate the task to it.
* This is accomplished by forcing the cpu_allowed mask to only
* allow dest_cpu, which will force the cpu onto dest_cpu. Then
@@ -1571,37 +1712,16 @@ out:
}
/*
- * sched_exec(): find the highest-level, exec-balance-capable
- * domain and try to migrate the task to the least loaded CPU.
- *
- * execve() is a valuable balancing opportunity, because at this point
- * the task has the smallest effective memory and cache footprint.
+ * sched_exec - execve() is a valuable balancing opportunity, because at
+ * this point the task has the smallest effective memory and cache footprint.
*/
void sched_exec(void)
{
- struct sched_domain *tmp, *sd = NULL;
int new_cpu, this_cpu = get_cpu();
-
- /* Prefer the current CPU if there's only this task running */
- if (this_rq()->nr_running <= 1)
- goto out;
-
- for_each_domain(this_cpu, tmp)
- if (tmp->flags & SD_BALANCE_EXEC)
- sd = tmp;
-
- if (sd) {
- schedstat_inc(sd, sbe_attempts);
- new_cpu = find_idlest_cpu(current, this_cpu, sd);
- if (new_cpu != this_cpu) {
- schedstat_inc(sd, sbe_pushed);
- put_cpu();
- sched_migrate_task(current, new_cpu);
- return;
- }
- }
-out:
+ new_cpu = sched_balance_self(this_cpu, SD_BALANCE_EXEC);
put_cpu();
+ if (new_cpu != this_cpu)
+ sched_migrate_task(current, new_cpu);
}
/*
@@ -1632,7 +1752,7 @@ void pull_task(runqueue_t *src_rq, prio_array_t *src_array, task_t *p,
*/
static inline
int can_migrate_task(task_t *p, runqueue_t *rq, int this_cpu,
- struct sched_domain *sd, enum idle_type idle)
+ struct sched_domain *sd, enum idle_type idle, int *all_pinned)
{
/*
* We do not migrate tasks that are:
@@ -1640,23 +1760,24 @@ int can_migrate_task(task_t *p, runqueue_t *rq, int this_cpu,
* 2) cannot be migrated to this CPU due to cpus_allowed, or
* 3) are cache-hot on their current CPU.
*/
- if (task_running(rq, p))
- return 0;
if (!cpu_isset(this_cpu, p->cpus_allowed))
return 0;
+ *all_pinned = 0;
+
+ if (task_running(rq, p))
+ return 0;
/*
* Aggressive migration if:
- * 1) the [whole] cpu is idle, or
+ * 1) task is cache cold, or
* 2) too many balance attempts have failed.
*/
- if (cpu_and_siblings_are_idle(this_cpu) || \
- sd->nr_balance_failed > sd->cache_nice_tries)
+ if (sd->nr_balance_failed > sd->cache_nice_tries)
return 1;
if (task_hot(p, rq->timestamp_last_tick, sd))
- return 0;
+ return 0;
return 1;
}
@@ -1669,16 +1790,18 @@ int can_migrate_task(task_t *p, runqueue_t *rq, int this_cpu,
*/
static int move_tasks(runqueue_t *this_rq, int this_cpu, runqueue_t *busiest,
unsigned long max_nr_move, struct sched_domain *sd,
- enum idle_type idle)
+ enum idle_type idle, int *all_pinned)
{
prio_array_t *array, *dst_array;
struct list_head *head, *curr;
- int idx, pulled = 0;
+ int idx, pulled = 0, pinned = 0;
task_t *tmp;
- if (max_nr_move <= 0 || busiest->nr_running <= 1)
+ if (max_nr_move == 0)
goto out;
+ pinned = 1;
+
/*
* We first consider expired tasks. Those will likely not be
* executed in the near future, and they are most likely to
@@ -1717,7 +1840,7 @@ skip_queue:
curr = curr->prev;
- if (!can_migrate_task(tmp, busiest, this_cpu, sd, idle)) {
+ if (!can_migrate_task(tmp, busiest, this_cpu, sd, idle, &pinned)) {
if (curr != head)
goto skip_queue;
idx++;
@@ -1746,6 +1869,9 @@ out:
* inside pull_task().
*/
schedstat_add(sd, lb_gained[idle], pulled);
+
+ if (all_pinned)
+ *all_pinned = pinned;
return pulled;
}
@@ -1760,8 +1886,15 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
{
struct sched_group *busiest = NULL, *this = NULL, *group = sd->groups;
unsigned long max_load, avg_load, total_load, this_load, total_pwr;
+ int load_idx;
max_load = this_load = total_load = total_pwr = 0;
+ if (idle == NOT_IDLE)
+ load_idx = sd->busy_idx;
+ else if (idle == NEWLY_IDLE)
+ load_idx = sd->newidle_idx;
+ else
+ load_idx = sd->idle_idx;
do {
unsigned long load;
@@ -1776,9 +1909,9 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
for_each_cpu_mask(i, group->cpumask) {
/* Bias balancing toward cpus of our domain */
if (local_group)
- load = target_load(i);
+ load = target_load(i, load_idx);
else
- load = source_load(i);
+ load = source_load(i, load_idx);
avg_load += load;
}
@@ -1792,12 +1925,10 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
if (local_group) {
this_load = avg_load;
this = group;
- goto nextgroup;
} else if (avg_load > max_load) {
max_load = avg_load;
busiest = group;
}
-nextgroup:
group = group->next;
} while (group != sd->groups);
@@ -1870,15 +2001,9 @@ nextgroup:
/* Get rid of the scaling factor, rounding down as we divide */
*imbalance = *imbalance / SCHED_LOAD_SCALE;
-
return busiest;
out_balanced:
- if (busiest && (idle == NEWLY_IDLE ||
- (idle == SCHED_IDLE && max_load > SCHED_LOAD_SCALE)) ) {
- *imbalance = 1;
- return busiest;
- }
*imbalance = 0;
return NULL;
@@ -1894,7 +2019,7 @@ static runqueue_t *find_busiest_queue(struct sched_group *group)
int i;
for_each_cpu_mask(i, group->cpumask) {
- load = source_load(i);
+ load = source_load(i, 0);
if (load > max_load) {
max_load = load;
@@ -1906,6 +2031,12 @@ static runqueue_t *find_busiest_queue(struct sched_group *group)
}
/*
+ * Max backoff if we encounter pinned tasks. Pretty arbitrary value, but
+ * so long as it is large enough.
+ */
+#define MAX_PINNED_INTERVAL 512
+
+/*
* Check this_cpu to ensure it is balanced within domain. Attempt to move
* tasks if there is an imbalance.
*
@@ -1917,7 +2048,8 @@ static int load_balance(int this_cpu, runqueue_t *this_rq,
struct sched_group *group;
runqueue_t *busiest;
unsigned long imbalance;
- int nr_moved;
+ int nr_moved, all_pinned = 0;
+ int active_balance = 0;
spin_lock(&this_rq->lock);
schedstat_inc(sd, lb_cnt[idle]);
@@ -1934,15 +2066,7 @@ static int load_balance(int this_cpu, runqueue_t *this_rq,
goto out_balanced;
}
- /*
- * This should be "impossible", but since load
- * balancing is inherently racy and statistical,
- * it could happen in theory.
- */
- if (unlikely(busiest == this_rq)) {
- WARN_ON(1);
- goto out_balanced;
- }
+ BUG_ON(busiest == this_rq);
schedstat_add(sd, lb_imbalance[idle], imbalance);
@@ -1956,9 +2080,15 @@ static int load_balance(int this_cpu, runqueue_t *this_rq,
*/
double_lock_balance(this_rq, busiest);
nr_moved = move_tasks(this_rq, this_cpu, busiest,
- imbalance, sd, idle);
+ imbalance, sd, idle,
+ &all_pinned);
spin_unlock(&busiest->lock);
+
+ /* All tasks on this runqueue were pinned by CPU affinity */
+ if (unlikely(all_pinned))
+ goto out_balanced;
}
+
spin_unlock(&this_rq->lock);
if (!nr_moved) {
@@ -1966,36 +2096,38 @@ static int load_balance(int this_cpu, runqueue_t *this_rq,
sd->nr_balance_failed++;
if (unlikely(sd->nr_balance_failed > sd->cache_nice_tries+2)) {
- int wake = 0;
spin_lock(&busiest->lock);
if (!busiest->active_balance) {
busiest->active_balance = 1;
busiest->push_cpu = this_cpu;
- wake = 1;
+ active_balance = 1;
}
spin_unlock(&busiest->lock);
- if (wake)
+ if (active_balance)
wake_up_process(busiest->migration_thread);
/*
* We've kicked active balancing, reset the failure
* counter.
*/
- sd->nr_balance_failed = sd->cache_nice_tries;
+ sd->nr_balance_failed = sd->cache_nice_tries+1;
}
-
- /*
- * We were unbalanced, but unsuccessful in move_tasks(),
- * so bump the balance_interval to lessen the lock contention.
- */
- if (sd->balance_interval < sd->max_interval)
- sd->balance_interval++;
- } else {
+ } else
sd->nr_balance_failed = 0;
+ if (likely(!active_balance)) {
/* We were unbalanced, so reset the balancing interval */
sd->balance_interval = sd->min_interval;
+ } else {
+ /*
+ * If we've begun active balancing, start to back off. This
+ * case may not be covered by the all_pinned logic if there
+ * is only 1 task on the busy runqueue (because we don't call
+ * move_tasks).
+ */
+ if (sd->balance_interval < sd->max_interval)
+ sd->balance_interval *= 2;
}
return nr_moved;
@@ -2005,8 +2137,10 @@ out_balanced:
schedstat_inc(sd, lb_balanced[idle]);
+ sd->nr_balance_failed = 0;
/* tune up the balancing interval */
- if (sd->balance_interval < sd->max_interval)
+ if ((all_pinned && sd->balance_interval < MAX_PINNED_INTERVAL) ||
+ (sd->balance_interval < sd->max_interval))
sd->balance_interval *= 2;
return 0;
@@ -2030,31 +2164,36 @@ static int load_balance_newidle(int this_cpu, runqueue_t *this_rq,
schedstat_inc(sd, lb_cnt[NEWLY_IDLE]);
group = find_busiest_group(sd, this_cpu, &imbalance, NEWLY_IDLE);
if (!group) {
- schedstat_inc(sd, lb_balanced[NEWLY_IDLE]);
schedstat_inc(sd, lb_nobusyg[NEWLY_IDLE]);
- goto out;
+ goto out_balanced;
}
busiest = find_busiest_queue(group);
- if (!busiest || busiest == this_rq) {
- schedstat_inc(sd, lb_balanced[NEWLY_IDLE]);
+ if (!busiest) {
schedstat_inc(sd, lb_nobusyq[NEWLY_IDLE]);
- goto out;
+ goto out_balanced;
}
+ BUG_ON(busiest == this_rq);
+
/* Attempt to move tasks */
double_lock_balance(this_rq, busiest);
schedstat_add(sd, lb_imbalance[NEWLY_IDLE], imbalance);
nr_moved = move_tasks(this_rq, this_cpu, busiest,
- imbalance, sd, NEWLY_IDLE);
+ imbalance, sd, NEWLY_IDLE, NULL);
if (!nr_moved)
schedstat_inc(sd, lb_failed[NEWLY_IDLE]);
+ else
+ sd->nr_balance_failed = 0;
spin_unlock(&busiest->lock);
-
-out:
return nr_moved;
+
+out_balanced:
+ schedstat_inc(sd, lb_balanced[NEWLY_IDLE]);
+ sd->nr_balance_failed = 0;
+ return 0;
}
/*
@@ -2086,56 +2225,42 @@ static inline void idle_balance(int this_cpu, runqueue_t *this_rq)
static void active_load_balance(runqueue_t *busiest_rq, int busiest_cpu)
{
struct sched_domain *sd;
- struct sched_group *cpu_group;
runqueue_t *target_rq;
- cpumask_t visited_cpus;
- int cpu;
+ int target_cpu = busiest_rq->push_cpu;
+
+ if (busiest_rq->nr_running <= 1)
+ /* no task to move */
+ return;
+
+ target_rq = cpu_rq(target_cpu);
/*
- * Search for suitable CPUs to push tasks to in successively higher
- * domains with SD_LOAD_BALANCE set.
+ * This condition is "impossible", if it occurs
+ * we need to fix it. Originally reported by
+ * Bjorn Helgaas on a 128-cpu setup.
*/
- visited_cpus = CPU_MASK_NONE;
- for_each_domain(busiest_cpu, sd) {
- if (!(sd->flags & SD_LOAD_BALANCE))
- /* no more domains to search */
- break;
+ BUG_ON(busiest_rq == target_rq);
- schedstat_inc(sd, alb_cnt);
+ /* move a task from busiest_rq to target_rq */
+ double_lock_balance(busiest_rq, target_rq);
- cpu_group = sd->groups;
- do {
- for_each_cpu_mask(cpu, cpu_group->cpumask) {
- if (busiest_rq->nr_running <= 1)
- /* no more tasks left to move */
- return;
- if (cpu_isset(cpu, visited_cpus))
- continue;
- cpu_set(cpu, visited_cpus);
- if (!cpu_and_siblings_are_idle(cpu) || cpu == busiest_cpu)
- continue;
-
- target_rq = cpu_rq(cpu);
- /*
- * This condition is "impossible", if it occurs
- * we need to fix it. Originally reported by
- * Bjorn Helgaas on a 128-cpu setup.
- */
- BUG_ON(busiest_rq == target_rq);
-
- /* move a task from busiest_rq to target_rq */
- double_lock_balance(busiest_rq, target_rq);
- if (move_tasks(target_rq, cpu, busiest_rq,
- 1, sd, SCHED_IDLE)) {
- schedstat_inc(sd, alb_pushed);
- } else {
- schedstat_inc(sd, alb_failed);
- }
- spin_unlock(&target_rq->lock);
- }
- cpu_group = cpu_group->next;
- } while (cpu_group != sd->groups);
- }
+ /* Search for an sd spanning us and the target CPU. */
+ for_each_domain(target_cpu, sd)
+ if ((sd->flags & SD_LOAD_BALANCE) &&
+ cpu_isset(busiest_cpu, sd->span))
+ break;
+
+ if (unlikely(sd == NULL))
+ goto out;
+
+ schedstat_inc(sd, alb_cnt);
+
+ if (move_tasks(target_rq, target_cpu, busiest_rq, 1, sd, SCHED_IDLE, NULL))
+ schedstat_inc(sd, alb_pushed);
+ else
+ schedstat_inc(sd, alb_failed);
+out:
+ spin_unlock(&target_rq->lock);
}
/*
@@ -2156,18 +2281,23 @@ static void rebalance_tick(int this_cpu, runqueue_t *this_rq,
unsigned long old_load, this_load;
unsigned long j = jiffies + CPU_OFFSET(this_cpu);
struct sched_domain *sd;
+ int i;
- /* Update our load */
- old_load = this_rq->cpu_load;
this_load = this_rq->nr_running * SCHED_LOAD_SCALE;
- /*
- * Round up the averaging division if load is increasing. This
- * prevents us from getting stuck on 9 if the load is 10, for
- * example.
- */
- if (this_load > old_load)
- old_load++;
- this_rq->cpu_load = (old_load + this_load) / 2;
+ /* Update our load */
+ for (i = 0; i < 3; i++) {
+ unsigned long new_load = this_load;
+ int scale = 1 << i;
+ old_load = this_rq->cpu_load[i];
+ /*
+ * Round up the averaging division if load is increasing. This
+ * prevents us from getting stuck on 9 if the load is 10, for
+ * example.
+ */
+ if (new_load > old_load)
+ new_load += scale-1;
+ this_rq->cpu_load[i] = (old_load*(scale-1) + new_load) / scale;
+ }
for_each_domain(this_cpu, sd) {
unsigned long interval;
@@ -2447,11 +2577,15 @@ out:
#ifdef CONFIG_SCHED_SMT
static inline void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq)
{
- struct sched_domain *sd = this_rq->sd;
+ struct sched_domain *tmp, *sd = NULL;
cpumask_t sibling_map;
int i;
- if (!(sd->flags & SD_SHARE_CPUPOWER))
+ for_each_domain(this_cpu, tmp)
+ if (tmp->flags & SD_SHARE_CPUPOWER)
+ sd = tmp;
+
+ if (!sd)
return;
/*
@@ -2492,13 +2626,17 @@ static inline void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq)
static inline int dependent_sleeper(int this_cpu, runqueue_t *this_rq)
{
- struct sched_domain *sd = this_rq->sd;
+ struct sched_domain *tmp, *sd = NULL;
cpumask_t sibling_map;
prio_array_t *array;
int ret = 0, i;
task_t *p;
- if (!(sd->flags & SD_SHARE_CPUPOWER))
+ for_each_domain(this_cpu, tmp)
+ if (tmp->flags & SD_SHARE_CPUPOWER)
+ sd = tmp;
+
+ if (!sd)
return 0;
/*
@@ -2576,7 +2714,7 @@ void fastcall add_preempt_count(int val)
/*
* Underflow?
*/
- BUG_ON(((int)preempt_count() < 0));
+ BUG_ON((preempt_count() < 0));
preempt_count() += val;
/*
* Spinlock count overflowing soon?
@@ -2613,7 +2751,7 @@ asmlinkage void __sched schedule(void)
struct list_head *queue;
unsigned long long now;
unsigned long run_time;
- int cpu, idx;
+ int cpu, idx, new_prio;
/*
* Test if we are atomic. Since do_exit() needs to call into
@@ -2735,9 +2873,14 @@ go_idle:
delta = delta * (ON_RUNQUEUE_WEIGHT * 128 / 100) / 128;
array = next->array;
- dequeue_task(next, array);
- recalc_task_prio(next, next->timestamp + delta);
- enqueue_task(next, array);
+ new_prio = recalc_task_prio(next, next->timestamp + delta);
+
+ if (unlikely(next->prio != new_prio)) {
+ dequeue_task(next, array);
+ next->prio = new_prio;
+ enqueue_task(next, array);
+ } else
+ requeue_task(next, array);
}
next->activated = 0;
switch_tasks:
@@ -2761,11 +2904,15 @@ switch_tasks:
rq->curr = next;
++*switch_count;
- prepare_arch_switch(rq, next);
+ prepare_task_switch(rq, next);
prev = context_switch(rq, prev, next);
barrier();
-
- finish_task_switch(prev);
+ /*
+ * this_rq must be evaluated again because prev may have moved
+ * CPUs since it called schedule(), thus the 'rq' on its stack
+ * frame will be invalid.
+ */
+ finish_task_switch(this_rq(), prev);
} else
spin_unlock_irq(&rq->lock);
@@ -2869,7 +3016,7 @@ need_resched:
int default_wake_function(wait_queue_t *curr, unsigned mode, int sync, void *key)
{
- task_t *p = curr->task;
+ task_t *p = curr->private;
return try_to_wake_up(p, mode, sync);
}
@@ -3384,13 +3531,24 @@ recheck:
if ((policy == SCHED_NORMAL) != (param->sched_priority == 0))
return -EINVAL;
- if ((policy == SCHED_FIFO || policy == SCHED_RR) &&
- param->sched_priority > p->signal->rlim[RLIMIT_RTPRIO].rlim_cur &&
- !capable(CAP_SYS_NICE))
- return -EPERM;
- if ((current->euid != p->euid) && (current->euid != p->uid) &&
- !capable(CAP_SYS_NICE))
- return -EPERM;
+ /*
+ * Allow unprivileged RT tasks to decrease priority:
+ */
+ if (!capable(CAP_SYS_NICE)) {
+ /* can't change policy */
+ if (policy != p->policy)
+ return -EPERM;
+ /* can't increase priority */
+ if (policy != SCHED_NORMAL &&
+ param->sched_priority > p->rt_priority &&
+ param->sched_priority >
+ p->signal->rlim[RLIMIT_RTPRIO].rlim_cur)
+ return -EPERM;
+ /* can't change other user's priorities */
+ if ((current->euid != p->euid) &&
+ (current->euid != p->uid))
+ return -EPERM;
+ }
retval = security_task_setscheduler(p, policy, param);
if (retval)
@@ -3755,19 +3913,22 @@ EXPORT_SYMBOL(cond_resched);
*/
int cond_resched_lock(spinlock_t * lock)
{
+ int ret = 0;
+
if (need_lockbreak(lock)) {
spin_unlock(lock);
cpu_relax();
+ ret = 1;
spin_lock(lock);
}
if (need_resched()) {
_raw_spin_unlock(lock);
preempt_enable_no_resched();
__cond_resched();
+ ret = 1;
spin_lock(lock);
- return 1;
}
- return 0;
+ return ret;
}
EXPORT_SYMBOL(cond_resched_lock);
@@ -3811,7 +3972,7 @@ EXPORT_SYMBOL(yield);
*/
void __sched io_schedule(void)
{
- struct runqueue *rq = &per_cpu(runqueues, _smp_processor_id());
+ struct runqueue *rq = &per_cpu(runqueues, raw_smp_processor_id());
atomic_inc(&rq->nr_iowait);
schedule();
@@ -3822,7 +3983,7 @@ EXPORT_SYMBOL(io_schedule);
long __sched io_schedule_timeout(long timeout)
{
- struct runqueue *rq = &per_cpu(runqueues, _smp_processor_id());
+ struct runqueue *rq = &per_cpu(runqueues, raw_smp_processor_id());
long ret;
atomic_inc(&rq->nr_iowait);
@@ -4027,6 +4188,9 @@ void __devinit init_idle(task_t *idle, int cpu)
spin_lock_irqsave(&rq->lock, flags);
rq->curr = rq->idle = idle;
+#if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW)
+ idle->oncpu = 1;
+#endif
set_tsk_need_resched(idle);
spin_unlock_irqrestore(&rq->lock, flags);
@@ -4171,8 +4335,7 @@ static int migration_thread(void * data)
struct list_head *head;
migration_req_t *req;
- if (current->flags & PF_FREEZE)
- refrigerator(PF_FREEZE);
+ try_to_freeze();
spin_lock_irq(&rq->lock);
@@ -4197,17 +4360,9 @@ static int migration_thread(void * data)
req = list_entry(head->next, migration_req_t, list);
list_del_init(head->next);
- if (req->type == REQ_MOVE_TASK) {
- spin_unlock(&rq->lock);
- __migrate_task(req->task, cpu, req->dest_cpu);
- local_irq_enable();
- } else if (req->type == REQ_SET_DOMAIN) {
- rq->sd = req->sd;
- spin_unlock_irq(&rq->lock);
- } else {
- spin_unlock_irq(&rq->lock);
- WARN_ON(1);
- }
+ spin_unlock(&rq->lock);
+ __migrate_task(req->task, cpu, req->dest_cpu);
+ local_irq_enable();
complete(&req->done);
}
@@ -4243,7 +4398,7 @@ static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *tsk)
/* No more Mr. Nice Guy. */
if (dest_cpu == NR_CPUS) {
- tsk->cpus_allowed = cpuset_cpus_allowed(tsk);
+ cpus_setall(tsk->cpus_allowed);
dest_cpu = any_online_cpu(tsk->cpus_allowed);
/*
@@ -4438,7 +4593,6 @@ static int migration_call(struct notifier_block *nfb, unsigned long action,
migration_req_t *req;
req = list_entry(rq->migration_queue.next,
migration_req_t, list);
- BUG_ON(req->type != REQ_MOVE_TASK);
list_del_init(&req->list);
complete(&req->done);
}
@@ -4469,12 +4623,17 @@ int __init migration_init(void)
#endif
#ifdef CONFIG_SMP
-#define SCHED_DOMAIN_DEBUG
+#undef SCHED_DOMAIN_DEBUG
#ifdef SCHED_DOMAIN_DEBUG
static void sched_domain_debug(struct sched_domain *sd, int cpu)
{
int level = 0;
+ if (!sd) {
+ printk(KERN_DEBUG "CPU%d attaching NULL sched-domain.\n", cpu);
+ return;
+ }
+
printk(KERN_DEBUG "CPU%d attaching sched-domain:\n", cpu);
do {
@@ -4557,37 +4716,81 @@ static void sched_domain_debug(struct sched_domain *sd, int cpu)
#define sched_domain_debug(sd, cpu) {}
#endif
+static int sd_degenerate(struct sched_domain *sd)
+{
+ if (cpus_weight(sd->span) == 1)
+ return 1;
+
+ /* Following flags need at least 2 groups */
+ if (sd->flags & (SD_LOAD_BALANCE |
+ SD_BALANCE_NEWIDLE |
+ SD_BALANCE_FORK |
+ SD_BALANCE_EXEC)) {
+ if (sd->groups != sd->groups->next)
+ return 0;
+ }
+
+ /* Following flags don't use groups */
+ if (sd->flags & (SD_WAKE_IDLE |
+ SD_WAKE_AFFINE |
+ SD_WAKE_BALANCE))
+ return 0;
+
+ return 1;
+}
+
+static int sd_parent_degenerate(struct sched_domain *sd,
+ struct sched_domain *parent)
+{
+ unsigned long cflags = sd->flags, pflags = parent->flags;
+
+ if (sd_degenerate(parent))
+ return 1;
+
+ if (!cpus_equal(sd->span, parent->span))
+ return 0;
+
+ /* Does parent contain flags not in child? */
+ /* WAKE_BALANCE is a subset of WAKE_AFFINE */
+ if (cflags & SD_WAKE_AFFINE)
+ pflags &= ~SD_WAKE_BALANCE;
+ /* Flags needing groups don't count if only 1 group in parent */
+ if (parent->groups == parent->groups->next) {
+ pflags &= ~(SD_LOAD_BALANCE |
+ SD_BALANCE_NEWIDLE |
+ SD_BALANCE_FORK |
+ SD_BALANCE_EXEC);
+ }
+ if (~cflags & pflags)
+ return 0;
+
+ return 1;
+}
+
/*
* Attach the domain 'sd' to 'cpu' as its base domain. Callers must
* hold the hotplug lock.
*/
-void __devinit cpu_attach_domain(struct sched_domain *sd, int cpu)
+void cpu_attach_domain(struct sched_domain *sd, int cpu)
{
- migration_req_t req;
- unsigned long flags;
runqueue_t *rq = cpu_rq(cpu);
- int local = 1;
-
- sched_domain_debug(sd, cpu);
+ struct sched_domain *tmp;
- spin_lock_irqsave(&rq->lock, flags);
-
- if (cpu == smp_processor_id() || !cpu_online(cpu)) {
- rq->sd = sd;
- } else {
- init_completion(&req.done);
- req.type = REQ_SET_DOMAIN;
- req.sd = sd;
- list_add(&req.list, &rq->migration_queue);
- local = 0;
+ /* Remove the sched domains which do not contribute to scheduling. */
+ for (tmp = sd; tmp; tmp = tmp->parent) {
+ struct sched_domain *parent = tmp->parent;
+ if (!parent)
+ break;
+ if (sd_parent_degenerate(tmp, parent))
+ tmp->parent = parent->parent;
}
- spin_unlock_irqrestore(&rq->lock, flags);
+ if (sd && sd_degenerate(sd))
+ sd = sd->parent;
- if (!local) {
- wake_up_process(rq->migration_thread);
- wait_for_completion(&req.done);
- }
+ sched_domain_debug(sd, cpu);
+
+ rcu_assign_pointer(rq->sd, sd);
}
/* cpus with isolated domains */
@@ -4619,7 +4822,7 @@ __setup ("isolcpus=", isolated_cpu_setup);
* covered by the given span, and will set each group's ->cpumask correctly,
* and ->cpu_power to 0.
*/
-void __devinit init_sched_build_groups(struct sched_group groups[],
+void init_sched_build_groups(struct sched_group groups[],
cpumask_t span, int (*group_fn)(int cpu))
{
struct sched_group *first = NULL, *last = NULL;
@@ -4655,13 +4858,14 @@ void __devinit init_sched_build_groups(struct sched_group groups[],
#ifdef ARCH_HAS_SCHED_DOMAIN
-extern void __devinit arch_init_sched_domains(void);
-extern void __devinit arch_destroy_sched_domains(void);
+extern void build_sched_domains(const cpumask_t *cpu_map);
+extern void arch_init_sched_domains(const cpumask_t *cpu_map);
+extern void arch_destroy_sched_domains(const cpumask_t *cpu_map);
#else
#ifdef CONFIG_SCHED_SMT
static DEFINE_PER_CPU(struct sched_domain, cpu_domains);
static struct sched_group sched_group_cpus[NR_CPUS];
-static int __devinit cpu_to_cpu_group(int cpu)
+static int cpu_to_cpu_group(int cpu)
{
return cpu;
}
@@ -4669,7 +4873,7 @@ static int __devinit cpu_to_cpu_group(int cpu)
static DEFINE_PER_CPU(struct sched_domain, phys_domains);
static struct sched_group sched_group_phys[NR_CPUS];
-static int __devinit cpu_to_phys_group(int cpu)
+static int cpu_to_phys_group(int cpu)
{
#ifdef CONFIG_SCHED_SMT
return first_cpu(cpu_sibling_map[cpu]);
@@ -4682,7 +4886,7 @@ static int __devinit cpu_to_phys_group(int cpu)
static DEFINE_PER_CPU(struct sched_domain, node_domains);
static struct sched_group sched_group_nodes[MAX_NUMNODES];
-static int __devinit cpu_to_node_group(int cpu)
+static int cpu_to_node_group(int cpu)
{
return cpu_to_node(cpu);
}
@@ -4713,39 +4917,28 @@ static void check_sibling_maps(void)
#endif
/*
- * Set up scheduler domains and groups. Callers must hold the hotplug lock.
+ * Build sched domains for a given set of cpus and attach the sched domains
+ * to the individual cpus
*/
-static void __devinit arch_init_sched_domains(void)
+static void build_sched_domains(const cpumask_t *cpu_map)
{
int i;
- cpumask_t cpu_default_map;
-
-#if defined(CONFIG_SCHED_SMT) && defined(CONFIG_NUMA)
- check_sibling_maps();
-#endif
- /*
- * Setup mask for cpus without special case scheduling requirements.
- * For now this just excludes isolated cpus, but could be used to
- * exclude other special cases in the future.
- */
- cpus_complement(cpu_default_map, cpu_isolated_map);
- cpus_and(cpu_default_map, cpu_default_map, cpu_online_map);
/*
- * Set up domains. Isolated domains just stay on the dummy domain.
+ * Set up domains for cpus specified by the cpu_map.
*/
- for_each_cpu_mask(i, cpu_default_map) {
+ for_each_cpu_mask(i, *cpu_map) {
int group;
struct sched_domain *sd = NULL, *p;
cpumask_t nodemask = node_to_cpumask(cpu_to_node(i));
- cpus_and(nodemask, nodemask, cpu_default_map);
+ cpus_and(nodemask, nodemask, *cpu_map);
#ifdef CONFIG_NUMA
sd = &per_cpu(node_domains, i);
group = cpu_to_node_group(i);
*sd = SD_NODE_INIT;
- sd->span = cpu_default_map;
+ sd->span = *cpu_map;
sd->groups = &sched_group_nodes[group];
#endif
@@ -4763,7 +4956,7 @@ static void __devinit arch_init_sched_domains(void)
group = cpu_to_cpu_group(i);
*sd = SD_SIBLING_INIT;
sd->span = cpu_sibling_map[i];
- cpus_and(sd->span, sd->span, cpu_default_map);
+ cpus_and(sd->span, sd->span, *cpu_map);
sd->parent = p;
sd->groups = &sched_group_cpus[group];
#endif
@@ -4773,7 +4966,7 @@ static void __devinit arch_init_sched_domains(void)
/* Set up CPU (sibling) groups */
for_each_online_cpu(i) {
cpumask_t this_sibling_map = cpu_sibling_map[i];
- cpus_and(this_sibling_map, this_sibling_map, cpu_default_map);
+ cpus_and(this_sibling_map, this_sibling_map, *cpu_map);
if (i != first_cpu(this_sibling_map))
continue;
@@ -4786,7 +4979,7 @@ static void __devinit arch_init_sched_domains(void)
for (i = 0; i < MAX_NUMNODES; i++) {
cpumask_t nodemask = node_to_cpumask(i);
- cpus_and(nodemask, nodemask, cpu_default_map);
+ cpus_and(nodemask, nodemask, *cpu_map);
if (cpus_empty(nodemask))
continue;
@@ -4796,12 +4989,12 @@ static void __devinit arch_init_sched_domains(void)
#ifdef CONFIG_NUMA
/* Set up node groups */
- init_sched_build_groups(sched_group_nodes, cpu_default_map,
+ init_sched_build_groups(sched_group_nodes, *cpu_map,
&cpu_to_node_group);
#endif
/* Calculate CPU power for physical packages and nodes */
- for_each_cpu_mask(i, cpu_default_map) {
+ for_each_cpu_mask(i, *cpu_map) {
int power;
struct sched_domain *sd;
#ifdef CONFIG_SCHED_SMT
@@ -4825,7 +5018,7 @@ static void __devinit arch_init_sched_domains(void)
}
/* Attach the domains */
- for_each_online_cpu(i) {
+ for_each_cpu_mask(i, *cpu_map) {
struct sched_domain *sd;
#ifdef CONFIG_SCHED_SMT
sd = &per_cpu(cpu_domains, i);
@@ -4835,41 +5028,85 @@ static void __devinit arch_init_sched_domains(void)
cpu_attach_domain(sd, i);
}
}
+/*
+ * Set up scheduler domains and groups. Callers must hold the hotplug lock.
+ */
+static void arch_init_sched_domains(cpumask_t *cpu_map)
+{
+ cpumask_t cpu_default_map;
+
+#if defined(CONFIG_SCHED_SMT) && defined(CONFIG_NUMA)
+ check_sibling_maps();
+#endif
+ /*
+ * Setup mask for cpus without special case scheduling requirements.
+ * For now this just excludes isolated cpus, but could be used to
+ * exclude other special cases in the future.
+ */
+ cpus_andnot(cpu_default_map, *cpu_map, cpu_isolated_map);
+
+ build_sched_domains(&cpu_default_map);
+}
-#ifdef CONFIG_HOTPLUG_CPU
-static void __devinit arch_destroy_sched_domains(void)
+static void arch_destroy_sched_domains(const cpumask_t *cpu_map)
{
/* Do nothing: everything is statically allocated. */
}
-#endif
#endif /* ARCH_HAS_SCHED_DOMAIN */
/*
- * Initial dummy domain for early boot and for hotplug cpu. Being static,
- * it is initialized to zero, so all balancing flags are cleared which is
- * what we want.
+ * Detach sched domains from a group of cpus specified in cpu_map
+ * These cpus will now be attached to the NULL domain
*/
-static struct sched_domain sched_domain_dummy;
+static inline void detach_destroy_domains(const cpumask_t *cpu_map)
+{
+ int i;
+
+ for_each_cpu_mask(i, *cpu_map)
+ cpu_attach_domain(NULL, i);
+ synchronize_sched();
+ arch_destroy_sched_domains(cpu_map);
+}
+
+/*
+ * Partition sched domains as specified by the cpumasks below.
+ * This attaches all cpus from the cpumasks to the NULL domain,
+ * waits for a RCU quiescent period, recalculates sched
+ * domain information and then attaches them back to the
+ * correct sched domains
+ * Call with hotplug lock held
+ */
+void partition_sched_domains(cpumask_t *partition1, cpumask_t *partition2)
+{
+ cpumask_t change_map;
+
+ cpus_and(*partition1, *partition1, cpu_online_map);
+ cpus_and(*partition2, *partition2, cpu_online_map);
+ cpus_or(change_map, *partition1, *partition2);
+
+ /* Detach sched domains from all of the affected cpus */
+ detach_destroy_domains(&change_map);
+ if (!cpus_empty(*partition1))
+ build_sched_domains(partition1);
+ if (!cpus_empty(*partition2))
+ build_sched_domains(partition2);
+}
#ifdef CONFIG_HOTPLUG_CPU
/*
* Force a reinitialization of the sched domains hierarchy. The domains
* and groups cannot be updated in place without racing with the balancing
- * code, so we temporarily attach all running cpus to a "dummy" domain
+ * code, so we temporarily attach all running cpus to the NULL domain
* which will prevent rebalancing while the sched domains are recalculated.
*/
static int update_sched_domains(struct notifier_block *nfb,
unsigned long action, void *hcpu)
{
- int i;
-
switch (action) {
case CPU_UP_PREPARE:
case CPU_DOWN_PREPARE:
- for_each_online_cpu(i)
- cpu_attach_domain(&sched_domain_dummy, i);
- arch_destroy_sched_domains();
+ detach_destroy_domains(&cpu_online_map);
return NOTIFY_OK;
case CPU_UP_CANCELED:
@@ -4885,7 +5122,7 @@ static int update_sched_domains(struct notifier_block *nfb,
}
/* The hotplug lock is already held by cpu_up/cpu_down */
- arch_init_sched_domains();
+ arch_init_sched_domains(&cpu_online_map);
return NOTIFY_OK;
}
@@ -4894,7 +5131,7 @@ static int update_sched_domains(struct notifier_block *nfb,
void __init sched_init_smp(void)
{
lock_cpu_hotplug();
- arch_init_sched_domains();
+ arch_init_sched_domains(&cpu_online_map);
unlock_cpu_hotplug();
/* XXX: Theoretical race here - CPU may be hotplugged now */
hotcpu_notifier(update_sched_domains, 0);
@@ -4924,13 +5161,15 @@ void __init sched_init(void)
rq = cpu_rq(i);
spin_lock_init(&rq->lock);
+ rq->nr_running = 0;
rq->active = rq->arrays;
rq->expired = rq->arrays + 1;
rq->best_expired_prio = MAX_PRIO;
#ifdef CONFIG_SMP
- rq->sd = &sched_domain_dummy;
- rq->cpu_load = 0;
+ rq->sd = NULL;
+ for (j = 1; j < 3; j++)
+ rq->cpu_load[j] = 0;
rq->active_balance = 0;
rq->push_cpu = 0;
rq->migration_thread = NULL;
diff --git a/kernel/signal.c b/kernel/signal.c
index 8f3debc77c5..ca1186eef93 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -24,6 +24,7 @@
#include <linux/ptrace.h>
#include <linux/posix-timers.h>
#include <linux/signal.h>
+#include <linux/audit.h>
#include <asm/param.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
@@ -212,6 +213,7 @@ static inline int has_pending_signals(sigset_t *signal, sigset_t *blocked)
fastcall void recalc_sigpending_tsk(struct task_struct *t)
{
if (t->signal->group_stop_count > 0 ||
+ (freezing(t)) ||
PENDING(&t->pending, &t->blocked) ||
PENDING(&t->signal->shared_pending, &t->blocked))
set_tsk_thread_flag(t, TIF_SIGPENDING);
@@ -522,7 +524,16 @@ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
{
int sig = 0;
- sig = next_signal(pending, mask);
+ /* SIGKILL must have priority, otherwise it is quite easy
+ * to create an unkillable process, sending sig < SIGKILL
+ * to self */
+ if (unlikely(sigismember(&pending->signal, SIGKILL))) {
+ if (!sigismember(mask, SIGKILL))
+ sig = SIGKILL;
+ }
+
+ if (likely(!sig))
+ sig = next_signal(pending, mask);
if (sig) {
if (current->notifier) {
if (sigismember(current->notifier_mask, sig)) {
@@ -658,7 +669,11 @@ static int check_kill_permission(int sig, struct siginfo *info,
&& (current->uid ^ t->suid) && (current->uid ^ t->uid)
&& !capable(CAP_KILL))
return error;
- return security_task_kill(t, info, sig);
+
+ error = security_task_kill(t, info, sig);
+ if (!error)
+ audit_signal_info(sig, t); /* Let audit system see the signal */
+ return error;
}
/* forward decl */
@@ -2216,8 +2231,7 @@ sys_rt_sigtimedwait(const sigset_t __user *uthese,
current->state = TASK_INTERRUPTIBLE;
timeout = schedule_timeout(timeout);
- if (current->flags & PF_FREEZE)
- refrigerator(PF_FREEZE);
+ try_to_freeze();
spin_lock_irq(&current->sighand->siglock);
sig = dequeue_signal(current, &these, &info);
current->blocked = current->real_blocked;
diff --git a/kernel/spinlock.c b/kernel/spinlock.c
index e15ed17863f..0c3f9d8bbe1 100644
--- a/kernel/spinlock.c
+++ b/kernel/spinlock.c
@@ -294,7 +294,7 @@ EXPORT_SYMBOL(_spin_unlock_irq);
void __lockfunc _spin_unlock_bh(spinlock_t *lock)
{
_raw_spin_unlock(lock);
- preempt_enable();
+ preempt_enable_no_resched();
local_bh_enable();
}
EXPORT_SYMBOL(_spin_unlock_bh);
@@ -318,7 +318,7 @@ EXPORT_SYMBOL(_read_unlock_irq);
void __lockfunc _read_unlock_bh(rwlock_t *lock)
{
_raw_read_unlock(lock);
- preempt_enable();
+ preempt_enable_no_resched();
local_bh_enable();
}
EXPORT_SYMBOL(_read_unlock_bh);
@@ -342,7 +342,7 @@ EXPORT_SYMBOL(_write_unlock_irq);
void __lockfunc _write_unlock_bh(rwlock_t *lock)
{
_raw_write_unlock(lock);
- preempt_enable();
+ preempt_enable_no_resched();
local_bh_enable();
}
EXPORT_SYMBOL(_write_unlock_bh);
@@ -354,7 +354,7 @@ int __lockfunc _spin_trylock_bh(spinlock_t *lock)
if (_raw_spin_trylock(lock))
return 1;
- preempt_enable();
+ preempt_enable_no_resched();
local_bh_enable();
return 0;
}
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 6116b25aa7c..84a9d18aa8d 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -100,7 +100,7 @@ static int stop_machine(void)
stopmachine_state = STOPMACHINE_WAIT;
for_each_online_cpu(i) {
- if (i == _smp_processor_id())
+ if (i == raw_smp_processor_id())
continue;
ret = kernel_thread(stopmachine, (void *)(long)i,CLONE_KERNEL);
if (ret < 0)
@@ -182,7 +182,7 @@ struct task_struct *__stop_machine_run(int (*fn)(void *), void *data,
/* If they don't care which CPU fn runs on, bind to any online one. */
if (cpu == NR_CPUS)
- cpu = _smp_processor_id();
+ cpu = raw_smp_processor_id();
p = kthread_create(do_stop, &smdata, "kstopmachine");
if (!IS_ERR(p)) {
diff --git a/kernel/sys.c b/kernel/sys.c
index f006632c2ba..9a24374c23b 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -16,6 +16,8 @@
#include <linux/init.h>
#include <linux/highuid.h>
#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/kexec.h>
#include <linux/workqueue.h>
#include <linux/device.h>
#include <linux/key.h>
@@ -405,6 +407,7 @@ asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user
case LINUX_REBOOT_CMD_HALT:
notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL);
system_state = SYSTEM_HALT;
+ device_suspend(PMSG_SUSPEND);
device_shutdown();
printk(KERN_EMERG "System halted.\n");
machine_halt();
@@ -415,6 +418,7 @@ asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user
case LINUX_REBOOT_CMD_POWER_OFF:
notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL);
system_state = SYSTEM_POWER_OFF;
+ device_suspend(PMSG_SUSPEND);
device_shutdown();
printk(KERN_EMERG "Power down.\n");
machine_power_off();
@@ -431,11 +435,30 @@ asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user
notifier_call_chain(&reboot_notifier_list, SYS_RESTART, buffer);
system_state = SYSTEM_RESTART;
+ device_suspend(PMSG_FREEZE);
device_shutdown();
printk(KERN_EMERG "Restarting system with command '%s'.\n", buffer);
machine_restart(buffer);
break;
+#ifdef CONFIG_KEXEC
+ case LINUX_REBOOT_CMD_KEXEC:
+ {
+ struct kimage *image;
+ image = xchg(&kexec_image, 0);
+ if (!image) {
+ unlock_kernel();
+ return -EINVAL;
+ }
+ notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
+ system_state = SYSTEM_RESTART;
+ device_shutdown();
+ printk(KERN_EMERG "Starting new kernel\n");
+ machine_shutdown();
+ machine_kexec(image);
+ break;
+ }
+#endif
#ifdef CONFIG_SOFTWARE_SUSPEND
case LINUX_REBOOT_CMD_SW_SUSPEND:
{
@@ -525,7 +548,7 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
}
if (new_egid != old_egid)
{
- current->mm->dumpable = 0;
+ current->mm->dumpable = suid_dumpable;
smp_wmb();
}
if (rgid != (gid_t) -1 ||
@@ -556,7 +579,7 @@ asmlinkage long sys_setgid(gid_t gid)
{
if(old_egid != gid)
{
- current->mm->dumpable=0;
+ current->mm->dumpable = suid_dumpable;
smp_wmb();
}
current->gid = current->egid = current->sgid = current->fsgid = gid;
@@ -565,7 +588,7 @@ asmlinkage long sys_setgid(gid_t gid)
{
if(old_egid != gid)
{
- current->mm->dumpable=0;
+ current->mm->dumpable = suid_dumpable;
smp_wmb();
}
current->egid = current->fsgid = gid;
@@ -596,7 +619,7 @@ static int set_user(uid_t new_ruid, int dumpclear)
if(dumpclear)
{
- current->mm->dumpable = 0;
+ current->mm->dumpable = suid_dumpable;
smp_wmb();
}
current->uid = new_ruid;
@@ -653,7 +676,7 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
if (new_euid != old_euid)
{
- current->mm->dumpable=0;
+ current->mm->dumpable = suid_dumpable;
smp_wmb();
}
current->fsuid = current->euid = new_euid;
@@ -703,7 +726,7 @@ asmlinkage long sys_setuid(uid_t uid)
if (old_euid != uid)
{
- current->mm->dumpable = 0;
+ current->mm->dumpable = suid_dumpable;
smp_wmb();
}
current->fsuid = current->euid = uid;
@@ -748,7 +771,7 @@ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
if (euid != (uid_t) -1) {
if (euid != current->euid)
{
- current->mm->dumpable = 0;
+ current->mm->dumpable = suid_dumpable;
smp_wmb();
}
current->euid = euid;
@@ -798,7 +821,7 @@ asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
if (egid != (gid_t) -1) {
if (egid != current->egid)
{
- current->mm->dumpable = 0;
+ current->mm->dumpable = suid_dumpable;
smp_wmb();
}
current->egid = egid;
@@ -845,7 +868,7 @@ asmlinkage long sys_setfsuid(uid_t uid)
{
if (uid != old_fsuid)
{
- current->mm->dumpable = 0;
+ current->mm->dumpable = suid_dumpable;
smp_wmb();
}
current->fsuid = uid;
@@ -875,7 +898,7 @@ asmlinkage long sys_setfsgid(gid_t gid)
{
if (gid != old_fsgid)
{
- current->mm->dumpable = 0;
+ current->mm->dumpable = suid_dumpable;
smp_wmb();
}
current->fsgid = gid;
@@ -894,35 +917,69 @@ asmlinkage long sys_times(struct tms __user * tbuf)
*/
if (tbuf) {
struct tms tmp;
- struct task_struct *tsk = current;
- struct task_struct *t;
cputime_t utime, stime, cutime, cstime;
- read_lock(&tasklist_lock);
- utime = tsk->signal->utime;
- stime = tsk->signal->stime;
- t = tsk;
- do {
- utime = cputime_add(utime, t->utime);
- stime = cputime_add(stime, t->stime);
- t = next_thread(t);
- } while (t != tsk);
-
- /*
- * While we have tasklist_lock read-locked, no dying thread
- * can be updating current->signal->[us]time. Instead,
- * we got their counts included in the live thread loop.
- * However, another thread can come in right now and
- * do a wait call that updates current->signal->c[us]time.
- * To make sure we always see that pair updated atomically,
- * we take the siglock around fetching them.
- */
- spin_lock_irq(&tsk->sighand->siglock);
- cutime = tsk->signal->cutime;
- cstime = tsk->signal->cstime;
- spin_unlock_irq(&tsk->sighand->siglock);
- read_unlock(&tasklist_lock);
+#ifdef CONFIG_SMP
+ if (thread_group_empty(current)) {
+ /*
+ * Single thread case without the use of any locks.
+ *
+ * We may race with release_task if two threads are
+ * executing. However, release task first adds up the
+ * counters (__exit_signal) before removing the task
+ * from the process tasklist (__unhash_process).
+ * __exit_signal also acquires and releases the
+ * siglock which results in the proper memory ordering
+ * so that the list modifications are always visible
+ * after the counters have been updated.
+ *
+ * If the counters have been updated by the second thread
+ * but the thread has not yet been removed from the list
+ * then the other branch will be executing which will
+ * block on tasklist_lock until the exit handling of the
+ * other task is finished.
+ *
+ * This also implies that the sighand->siglock cannot
+ * be held by another processor. So we can also
+ * skip acquiring that lock.
+ */
+ utime = cputime_add(current->signal->utime, current->utime);
+ stime = cputime_add(current->signal->utime, current->stime);
+ cutime = current->signal->cutime;
+ cstime = current->signal->cstime;
+ } else
+#endif
+ {
+ /* Process with multiple threads */
+ struct task_struct *tsk = current;
+ struct task_struct *t;
+
+ read_lock(&tasklist_lock);
+ utime = tsk->signal->utime;
+ stime = tsk->signal->stime;
+ t = tsk;
+ do {
+ utime = cputime_add(utime, t->utime);
+ stime = cputime_add(stime, t->stime);
+ t = next_thread(t);
+ } while (t != tsk);
+
+ /*
+ * While we have tasklist_lock read-locked, no dying thread
+ * can be updating current->signal->[us]time. Instead,
+ * we got their counts included in the live thread loop.
+ * However, another thread can come in right now and
+ * do a wait call that updates current->signal->c[us]time.
+ * To make sure we always see that pair updated atomically,
+ * we take the siglock around fetching them.
+ */
+ spin_lock_irq(&tsk->sighand->siglock);
+ cutime = tsk->signal->cutime;
+ cstime = tsk->signal->cstime;
+ spin_unlock_irq(&tsk->sighand->siglock);
+ read_unlock(&tasklist_lock);
+ }
tmp.tms_utime = cputime_to_clock_t(utime);
tmp.tms_stime = cputime_to_clock_t(stime);
tmp.tms_cutime = cputime_to_clock_t(cutime);
@@ -1225,7 +1282,7 @@ static void groups_sort(struct group_info *group_info)
}
/* a simple bsearch */
-static int groups_search(struct group_info *group_info, gid_t grp)
+int groups_search(struct group_info *group_info, gid_t grp)
{
int left, right;
@@ -1652,7 +1709,7 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
error = 1;
break;
case PR_SET_DUMPABLE:
- if (arg2 != 0 && arg2 != 1) {
+ if (arg2 < 0 || arg2 > 2) {
error = -EINVAL;
break;
}
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 0dda70ed1f9..29196ce9b40 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -18,6 +18,8 @@ cond_syscall(sys_acct);
cond_syscall(sys_lookup_dcookie);
cond_syscall(sys_swapon);
cond_syscall(sys_swapoff);
+cond_syscall(sys_kexec_load);
+cond_syscall(compat_sys_kexec_load);
cond_syscall(sys_init_module);
cond_syscall(sys_delete_module);
cond_syscall(sys_socketpair);
@@ -77,6 +79,7 @@ cond_syscall(sys_request_key);
cond_syscall(sys_keyctl);
cond_syscall(compat_sys_keyctl);
cond_syscall(compat_sys_socketcall);
+cond_syscall(sys_set_zone_reclaim);
/* arch-specific weak syscall entries */
cond_syscall(sys_pciconfig_read);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 701d12c6306..270ee7fadbd 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -58,6 +58,7 @@ extern int sysctl_overcommit_ratio;
extern int max_threads;
extern int sysrq_enabled;
extern int core_uses_pid;
+extern int suid_dumpable;
extern char core_pattern[];
extern int cad_pid;
extern int pid_max;
@@ -950,6 +951,14 @@ static ctl_table fs_table[] = {
.proc_handler = &proc_dointvec,
},
#endif
+ {
+ .ctl_name = KERN_SETUID_DUMPABLE,
+ .procname = "suid_dumpable",
+ .data = &suid_dumpable,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
{ .ctl_name = 0 }
};
@@ -991,8 +1000,7 @@ int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *ol
int error = parse_table(name, nlen, oldval, oldlenp,
newval, newlen, head->ctl_table,
&context);
- if (context)
- kfree(context);
+ kfree(context);
if (error != -ENOTDIR)
return error;
tmp = tmp->next;
diff --git a/kernel/timer.c b/kernel/timer.c
index 207aa4f0aa1..f2a11887a72 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -57,6 +57,11 @@ static void time_interpolator_update(long delta_nsec);
#define TVN_MASK (TVN_SIZE - 1)
#define TVR_MASK (TVR_SIZE - 1)
+struct timer_base_s {
+ spinlock_t lock;
+ struct timer_list *running_timer;
+};
+
typedef struct tvec_s {
struct list_head vec[TVN_SIZE];
} tvec_t;
@@ -66,9 +71,8 @@ typedef struct tvec_root_s {
} tvec_root_t;
struct tvec_t_base_s {
- spinlock_t lock;
+ struct timer_base_s t_base;
unsigned long timer_jiffies;
- struct timer_list *running_timer;
tvec_root_t tv1;
tvec_t tv2;
tvec_t tv3;
@@ -77,18 +81,16 @@ struct tvec_t_base_s {
} ____cacheline_aligned_in_smp;
typedef struct tvec_t_base_s tvec_base_t;
+static DEFINE_PER_CPU(tvec_base_t, tvec_bases);
static inline void set_running_timer(tvec_base_t *base,
struct timer_list *timer)
{
#ifdef CONFIG_SMP
- base->running_timer = timer;
+ base->t_base.running_timer = timer;
#endif
}
-/* Fake initialization */
-static DEFINE_PER_CPU(tvec_base_t, tvec_bases) = { SPIN_LOCK_UNLOCKED };
-
static void check_timer_failed(struct timer_list *timer)
{
static int whine_count;
@@ -103,7 +105,6 @@ static void check_timer_failed(struct timer_list *timer)
/*
* Now fix it up
*/
- spin_lock_init(&timer->lock);
timer->magic = TIMER_MAGIC;
}
@@ -156,65 +157,113 @@ static void internal_add_timer(tvec_base_t *base, struct timer_list *timer)
list_add_tail(&timer->entry, vec);
}
+typedef struct timer_base_s timer_base_t;
+/*
+ * Used by TIMER_INITIALIZER, we can't use per_cpu(tvec_bases)
+ * at compile time, and we need timer->base to lock the timer.
+ */
+timer_base_t __init_timer_base
+ ____cacheline_aligned_in_smp = { .lock = SPIN_LOCK_UNLOCKED };
+EXPORT_SYMBOL(__init_timer_base);
+
+/***
+ * init_timer - initialize a timer.
+ * @timer: the timer to be initialized
+ *
+ * init_timer() must be done to a timer prior calling *any* of the
+ * other timer functions.
+ */
+void fastcall init_timer(struct timer_list *timer)
+{
+ timer->entry.next = NULL;
+ timer->base = &per_cpu(tvec_bases, raw_smp_processor_id()).t_base;
+ timer->magic = TIMER_MAGIC;
+}
+EXPORT_SYMBOL(init_timer);
+
+static inline void detach_timer(struct timer_list *timer,
+ int clear_pending)
+{
+ struct list_head *entry = &timer->entry;
+
+ __list_del(entry->prev, entry->next);
+ if (clear_pending)
+ entry->next = NULL;
+ entry->prev = LIST_POISON2;
+}
+
+/*
+ * We are using hashed locking: holding per_cpu(tvec_bases).t_base.lock
+ * means that all timers which are tied to this base via timer->base are
+ * locked, and the base itself is locked too.
+ *
+ * So __run_timers/migrate_timers can safely modify all timers which could
+ * be found on ->tvX lists.
+ *
+ * When the timer's base is locked, and the timer removed from list, it is
+ * possible to set timer->base = NULL and drop the lock: the timer remains
+ * locked.
+ */
+static timer_base_t *lock_timer_base(struct timer_list *timer,
+ unsigned long *flags)
+{
+ timer_base_t *base;
+
+ for (;;) {
+ base = timer->base;
+ if (likely(base != NULL)) {
+ spin_lock_irqsave(&base->lock, *flags);
+ if (likely(base == timer->base))
+ return base;
+ /* The timer has migrated to another CPU */
+ spin_unlock_irqrestore(&base->lock, *flags);
+ }
+ cpu_relax();
+ }
+}
+
int __mod_timer(struct timer_list *timer, unsigned long expires)
{
- tvec_base_t *old_base, *new_base;
+ timer_base_t *base;
+ tvec_base_t *new_base;
unsigned long flags;
int ret = 0;
BUG_ON(!timer->function);
-
check_timer(timer);
- spin_lock_irqsave(&timer->lock, flags);
+ base = lock_timer_base(timer, &flags);
+
+ if (timer_pending(timer)) {
+ detach_timer(timer, 0);
+ ret = 1;
+ }
+
new_base = &__get_cpu_var(tvec_bases);
-repeat:
- old_base = timer->base;
- /*
- * Prevent deadlocks via ordering by old_base < new_base.
- */
- if (old_base && (new_base != old_base)) {
- if (old_base < new_base) {
- spin_lock(&new_base->lock);
- spin_lock(&old_base->lock);
- } else {
- spin_lock(&old_base->lock);
- spin_lock(&new_base->lock);
- }
+ if (base != &new_base->t_base) {
/*
- * The timer base might have been cancelled while we were
- * trying to take the lock(s):
+ * We are trying to schedule the timer on the local CPU.
+ * However we can't change timer's base while it is running,
+ * otherwise del_timer_sync() can't detect that the timer's
+ * handler yet has not finished. This also guarantees that
+ * the timer is serialized wrt itself.
*/
- if (timer->base != old_base) {
- spin_unlock(&new_base->lock);
- spin_unlock(&old_base->lock);
- goto repeat;
- }
- } else {
- spin_lock(&new_base->lock);
- if (timer->base != old_base) {
- spin_unlock(&new_base->lock);
- goto repeat;
+ if (unlikely(base->running_timer == timer)) {
+ /* The timer remains on a former base */
+ new_base = container_of(base, tvec_base_t, t_base);
+ } else {
+ /* See the comment in lock_timer_base() */
+ timer->base = NULL;
+ spin_unlock(&base->lock);
+ spin_lock(&new_base->t_base.lock);
+ timer->base = &new_base->t_base;
}
}
- /*
- * Delete the previous timeout (if there was any), and install
- * the new one:
- */
- if (old_base) {
- list_del(&timer->entry);
- ret = 1;
- }
timer->expires = expires;
internal_add_timer(new_base, timer);
- timer->base = new_base;
-
- if (old_base && (new_base != old_base))
- spin_unlock(&old_base->lock);
- spin_unlock(&new_base->lock);
- spin_unlock_irqrestore(&timer->lock, flags);
+ spin_unlock_irqrestore(&new_base->t_base.lock, flags);
return ret;
}
@@ -232,15 +281,15 @@ void add_timer_on(struct timer_list *timer, int cpu)
{
tvec_base_t *base = &per_cpu(tvec_bases, cpu);
unsigned long flags;
-
+
BUG_ON(timer_pending(timer) || !timer->function);
check_timer(timer);
- spin_lock_irqsave(&base->lock, flags);
+ spin_lock_irqsave(&base->t_base.lock, flags);
+ timer->base = &base->t_base;
internal_add_timer(base, timer);
- timer->base = base;
- spin_unlock_irqrestore(&base->lock, flags);
+ spin_unlock_irqrestore(&base->t_base.lock, flags);
}
@@ -295,109 +344,84 @@ EXPORT_SYMBOL(mod_timer);
*/
int del_timer(struct timer_list *timer)
{
+ timer_base_t *base;
unsigned long flags;
- tvec_base_t *base;
+ int ret = 0;
check_timer(timer);
-repeat:
- base = timer->base;
- if (!base)
- return 0;
- spin_lock_irqsave(&base->lock, flags);
- if (base != timer->base) {
+ if (timer_pending(timer)) {
+ base = lock_timer_base(timer, &flags);
+ if (timer_pending(timer)) {
+ detach_timer(timer, 1);
+ ret = 1;
+ }
spin_unlock_irqrestore(&base->lock, flags);
- goto repeat;
}
- list_del(&timer->entry);
- /* Need to make sure that anybody who sees a NULL base also sees the list ops */
- smp_wmb();
- timer->base = NULL;
- spin_unlock_irqrestore(&base->lock, flags);
- return 1;
+ return ret;
}
EXPORT_SYMBOL(del_timer);
#ifdef CONFIG_SMP
-/***
- * del_timer_sync - deactivate a timer and wait for the handler to finish.
- * @timer: the timer to be deactivated
- *
- * This function only differs from del_timer() on SMP: besides deactivating
- * the timer it also makes sure the handler has finished executing on other
- * CPUs.
- *
- * Synchronization rules: callers must prevent restarting of the timer,
- * otherwise this function is meaningless. It must not be called from
- * interrupt contexts. The caller must not hold locks which would prevent
- * completion of the timer's handler. Upon exit the timer is not queued and
- * the handler is not running on any CPU.
- *
- * The function returns whether it has deactivated a pending timer or not.
+/*
+ * This function tries to deactivate a timer. Upon successful (ret >= 0)
+ * exit the timer is not queued and the handler is not running on any CPU.
*
- * del_timer_sync() is slow and complicated because it copes with timer
- * handlers which re-arm the timer (periodic timers). If the timer handler
- * is known to not do this (a single shot timer) then use
- * del_singleshot_timer_sync() instead.
+ * It must not be called from interrupt contexts.
*/
-int del_timer_sync(struct timer_list *timer)
+int try_to_del_timer_sync(struct timer_list *timer)
{
- tvec_base_t *base;
- int i, ret = 0;
+ timer_base_t *base;
+ unsigned long flags;
+ int ret = -1;
- check_timer(timer);
+ base = lock_timer_base(timer, &flags);
-del_again:
- ret += del_timer(timer);
+ if (base->running_timer == timer)
+ goto out;
- for_each_online_cpu(i) {
- base = &per_cpu(tvec_bases, i);
- if (base->running_timer == timer) {
- while (base->running_timer == timer) {
- cpu_relax();
- preempt_check_resched();
- }
- break;
- }
+ ret = 0;
+ if (timer_pending(timer)) {
+ detach_timer(timer, 1);
+ ret = 1;
}
- smp_rmb();
- if (timer_pending(timer))
- goto del_again;
+out:
+ spin_unlock_irqrestore(&base->lock, flags);
return ret;
}
-EXPORT_SYMBOL(del_timer_sync);
/***
- * del_singleshot_timer_sync - deactivate a non-recursive timer
+ * del_timer_sync - deactivate a timer and wait for the handler to finish.
* @timer: the timer to be deactivated
*
- * This function is an optimization of del_timer_sync for the case where the
- * caller can guarantee the timer does not reschedule itself in its timer
- * function.
+ * This function only differs from del_timer() on SMP: besides deactivating
+ * the timer it also makes sure the handler has finished executing on other
+ * CPUs.
*
* Synchronization rules: callers must prevent restarting of the timer,
* otherwise this function is meaningless. It must not be called from
- * interrupt contexts. The caller must not hold locks which wold prevent
- * completion of the timer's handler. Upon exit the timer is not queued and
- * the handler is not running on any CPU.
+ * interrupt contexts. The caller must not hold locks which would prevent
+ * completion of the timer's handler. The timer's handler must not call
+ * add_timer_on(). Upon exit the timer is not queued and the handler is
+ * not running on any CPU.
*
* The function returns whether it has deactivated a pending timer or not.
*/
-int del_singleshot_timer_sync(struct timer_list *timer)
+int del_timer_sync(struct timer_list *timer)
{
- int ret = del_timer(timer);
+ check_timer(timer);
- if (!ret) {
- ret = del_timer_sync(timer);
- BUG_ON(ret);
+ for (;;) {
+ int ret = try_to_del_timer_sync(timer);
+ if (ret >= 0)
+ return ret;
}
-
- return ret;
}
-EXPORT_SYMBOL(del_singleshot_timer_sync);
+
+EXPORT_SYMBOL(del_timer_sync);
#endif
static int cascade(tvec_base_t *base, tvec_t *tv, int index)
@@ -415,7 +439,7 @@ static int cascade(tvec_base_t *base, tvec_t *tv, int index)
struct timer_list *tmp;
tmp = list_entry(curr, struct timer_list, entry);
- BUG_ON(tmp->base != base);
+ BUG_ON(tmp->base != &base->t_base);
curr = curr->next;
internal_add_timer(base, tmp);
}
@@ -437,7 +461,7 @@ static inline void __run_timers(tvec_base_t *base)
{
struct timer_list *timer;
- spin_lock_irq(&base->lock);
+ spin_lock_irq(&base->t_base.lock);
while (time_after_eq(jiffies, base->timer_jiffies)) {
struct list_head work_list = LIST_HEAD_INIT(work_list);
struct list_head *head = &work_list;
@@ -453,8 +477,7 @@ static inline void __run_timers(tvec_base_t *base)
cascade(base, &base->tv5, INDEX(3));
++base->timer_jiffies;
list_splice_init(base->tv1.vec + index, &work_list);
-repeat:
- if (!list_empty(head)) {
+ while (!list_empty(head)) {
void (*fn)(unsigned long);
unsigned long data;
@@ -462,25 +485,26 @@ repeat:
fn = timer->function;
data = timer->data;
- list_del(&timer->entry);
set_running_timer(base, timer);
- smp_wmb();
- timer->base = NULL;
- spin_unlock_irq(&base->lock);
+ detach_timer(timer, 1);
+ spin_unlock_irq(&base->t_base.lock);
{
- u32 preempt_count = preempt_count();
+ int preempt_count = preempt_count();
fn(data);
if (preempt_count != preempt_count()) {
- printk("huh, entered %p with %08x, exited with %08x?\n", fn, preempt_count, preempt_count());
+ printk(KERN_WARNING "huh, entered %p "
+ "with preempt_count %08x, exited"
+ " with %08x?\n",
+ fn, preempt_count,
+ preempt_count());
BUG();
}
}
- spin_lock_irq(&base->lock);
- goto repeat;
+ spin_lock_irq(&base->t_base.lock);
}
}
set_running_timer(base, NULL);
- spin_unlock_irq(&base->lock);
+ spin_unlock_irq(&base->t_base.lock);
}
#ifdef CONFIG_NO_IDLE_HZ
@@ -499,7 +523,7 @@ unsigned long next_timer_interrupt(void)
int i, j;
base = &__get_cpu_var(tvec_bases);
- spin_lock(&base->lock);
+ spin_lock(&base->t_base.lock);
expires = base->timer_jiffies + (LONG_MAX >> 1);
list = 0;
@@ -547,7 +571,7 @@ found:
expires = nte->expires;
}
}
- spin_unlock(&base->lock);
+ spin_unlock(&base->t_base.lock);
return expires;
}
#endif
@@ -1286,9 +1310,9 @@ static void __devinit init_timers_cpu(int cpu)
{
int j;
tvec_base_t *base;
-
+
base = &per_cpu(tvec_bases, cpu);
- spin_lock_init(&base->lock);
+ spin_lock_init(&base->t_base.lock);
for (j = 0; j < TVN_SIZE; j++) {
INIT_LIST_HEAD(base->tv5.vec + j);
INIT_LIST_HEAD(base->tv4.vec + j);
@@ -1302,22 +1326,16 @@ static void __devinit init_timers_cpu(int cpu)
}
#ifdef CONFIG_HOTPLUG_CPU
-static int migrate_timer_list(tvec_base_t *new_base, struct list_head *head)
+static void migrate_timer_list(tvec_base_t *new_base, struct list_head *head)
{
struct timer_list *timer;
while (!list_empty(head)) {
timer = list_entry(head->next, struct timer_list, entry);
- /* We're locking backwards from __mod_timer order here,
- beware deadlock. */
- if (!spin_trylock(&timer->lock))
- return 0;
- list_del(&timer->entry);
+ detach_timer(timer, 0);
+ timer->base = &new_base->t_base;
internal_add_timer(new_base, timer);
- timer->base = new_base;
- spin_unlock(&timer->lock);
}
- return 1;
}
static void __devinit migrate_timers(int cpu)
@@ -1331,39 +1349,24 @@ static void __devinit migrate_timers(int cpu)
new_base = &get_cpu_var(tvec_bases);
local_irq_disable();
-again:
- /* Prevent deadlocks via ordering by old_base < new_base. */
- if (old_base < new_base) {
- spin_lock(&new_base->lock);
- spin_lock(&old_base->lock);
- } else {
- spin_lock(&old_base->lock);
- spin_lock(&new_base->lock);
- }
+ spin_lock(&new_base->t_base.lock);
+ spin_lock(&old_base->t_base.lock);
- if (old_base->running_timer)
+ if (old_base->t_base.running_timer)
BUG();
for (i = 0; i < TVR_SIZE; i++)
- if (!migrate_timer_list(new_base, old_base->tv1.vec + i))
- goto unlock_again;
- for (i = 0; i < TVN_SIZE; i++)
- if (!migrate_timer_list(new_base, old_base->tv2.vec + i)
- || !migrate_timer_list(new_base, old_base->tv3.vec + i)
- || !migrate_timer_list(new_base, old_base->tv4.vec + i)
- || !migrate_timer_list(new_base, old_base->tv5.vec + i))
- goto unlock_again;
- spin_unlock(&old_base->lock);
- spin_unlock(&new_base->lock);
+ migrate_timer_list(new_base, old_base->tv1.vec + i);
+ for (i = 0; i < TVN_SIZE; i++) {
+ migrate_timer_list(new_base, old_base->tv2.vec + i);
+ migrate_timer_list(new_base, old_base->tv3.vec + i);
+ migrate_timer_list(new_base, old_base->tv4.vec + i);
+ migrate_timer_list(new_base, old_base->tv5.vec + i);
+ }
+
+ spin_unlock(&old_base->t_base.lock);
+ spin_unlock(&new_base->t_base.lock);
local_irq_enable();
put_cpu_var(tvec_bases);
- return;
-
-unlock_again:
- /* Avoid deadlock with __mod_timer, by backing off. */
- spin_unlock(&old_base->lock);
- spin_unlock(&new_base->lock);
- cpu_relax();
- goto again;
}
#endif /* CONFIG_HOTPLUG_CPU */
@@ -1594,7 +1597,7 @@ void msleep(unsigned int msecs)
EXPORT_SYMBOL(msleep);
/**
- * msleep_interruptible - sleep waiting for waitqueue interruptions
+ * msleep_interruptible - sleep waiting for signals
* @msecs: Time in milliseconds to sleep for
*/
unsigned long msleep_interruptible(unsigned int msecs)
diff --git a/lib/Kconfig b/lib/Kconfig
index eeb45225248..eeb429a5215 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -40,6 +40,12 @@ config ZLIB_DEFLATE
tristate
#
+# Generic allocator support is selected if needed
+#
+config GENERIC_ALLOCATOR
+ boolean
+
+#
# reed solomon support is select'ed if needed
#
config REED_SOLOMON
@@ -57,5 +63,16 @@ config REED_SOLOMON_ENC16
config REED_SOLOMON_DEC16
boolean
-endmenu
+#
+# Textsearch support is select'ed if needed
+#
+config TEXTSEARCH
+ boolean
+
+config TEXTSEARCH_KMP
+ tristate
+config TEXTSEARCH_FSM
+ tristate
+
+endmenu
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index ac23847ce0e..0c421295e61 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -151,7 +151,8 @@ config DEBUG_FS
config FRAME_POINTER
bool "Compile the kernel with frame pointers"
- depends on DEBUG_KERNEL && ((X86 && !X86_64) || CRIS || M68K || M68KNOMMU || FRV)
+ depends on DEBUG_KERNEL && ((X86 && !X86_64) || CRIS || M68K || M68KNOMMU || FRV || UML)
+ default y if DEBUG_INFO && UML
help
If you say Y here the resulting kernel image will be slightly larger
and slower, but it will give very useful debugging information.
diff --git a/lib/Makefile b/lib/Makefile
index 7c70db79c0e..beed1585294 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -4,9 +4,10 @@
lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \
bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
- kobject.o kref.o idr.o div64.o int_sqrt.o \
- bitmap.o extable.o kobject_uevent.o prio_tree.o sha1.o \
- halfmd4.o
+ idr.o div64.o int_sqrt.o bitmap.o extable.o prio_tree.o \
+ sha1.o halfmd4.o
+
+lib-y += kobject.o kref.o kobject_uevent.o klist.o
obj-y += sort.o parser.o
@@ -19,6 +20,7 @@ lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o
obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
+obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o
ifneq ($(CONFIG_HAVE_DEC_LOCK),y)
lib-y += dec_and_lock.o
@@ -28,11 +30,16 @@ obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o
obj-$(CONFIG_CRC32) += crc32.o
obj-$(CONFIG_LIBCRC32C) += libcrc32c.o
obj-$(CONFIG_GENERIC_IOMAP) += iomap.o
+obj-$(CONFIG_GENERIC_ALLOCATOR) += genalloc.o
obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/
obj-$(CONFIG_REED_SOLOMON) += reed_solomon/
+obj-$(CONFIG_TEXTSEARCH) += textsearch.o
+obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o
+obj-$(CONFIG_TEXTSEARCH_FSM) += ts_fsm.o
+
hostprogs-y := gen_crc32table
clean-files := crc32table.h
diff --git a/lib/bitmap.c b/lib/bitmap.c
index d1388a5ce89..fb9371fdd44 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -289,7 +289,6 @@ EXPORT_SYMBOL(__bitmap_weight);
#define CHUNKSZ 32
#define nbits_to_hold_value(val) fls(val)
-#define roundup_power2(val,modulus) (((val) + (modulus) - 1) & ~((modulus) - 1))
#define unhex(c) (isdigit(c) ? (c - '0') : (toupper(c) - 'A' + 10))
#define BASEDEC 10 /* fancier cpuset lists input in decimal */
@@ -316,7 +315,7 @@ int bitmap_scnprintf(char *buf, unsigned int buflen,
if (chunksz == 0)
chunksz = CHUNKSZ;
- i = roundup_power2(nmaskbits, CHUNKSZ) - CHUNKSZ;
+ i = ALIGN(nmaskbits, CHUNKSZ) - CHUNKSZ;
for (; i >= 0; i -= CHUNKSZ) {
chunkmask = ((1ULL << chunksz) - 1);
word = i / BITS_PER_LONG;
diff --git a/lib/genalloc.c b/lib/genalloc.c
new file mode 100644
index 00000000000..d6d30d2e716
--- /dev/null
+++ b/lib/genalloc.c
@@ -0,0 +1,188 @@
+/*
+ * Basic general purpose allocator for managing special purpose memory
+ * not managed by the regular kmalloc/kfree interface.
+ * Uses for this includes on-device special memory, uncached memory
+ * etc.
+ *
+ * This code is based on the buddy allocator found in the sym53c8xx_2
+ * driver Copyright (C) 1999-2001 Gerard Roudier <groudier@free.fr>,
+ * and adapted for general purpose use.
+ *
+ * Copyright 2005 (C) Jes Sorensen <jes@trained-monkey.org>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2. See the file COPYING for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/spinlock.h>
+#include <linux/genalloc.h>
+
+#include <asm/page.h>
+
+
+struct gen_pool *gen_pool_create(int nr_chunks, int max_chunk_shift,
+ unsigned long (*fp)(struct gen_pool *),
+ unsigned long data)
+{
+ struct gen_pool *poolp;
+ unsigned long tmp;
+ int i;
+
+ /*
+ * This is really an arbitrary limit, +10 is enough for
+ * IA64_GRANULE_SHIFT, aka 16MB. If anyone needs a large limit
+ * this can be increased without problems.
+ */
+ if ((max_chunk_shift > (PAGE_SHIFT + 10)) ||
+ ((max_chunk_shift < ALLOC_MIN_SHIFT) && max_chunk_shift))
+ return NULL;
+
+ if (!max_chunk_shift)
+ max_chunk_shift = PAGE_SHIFT;
+
+ poolp = kmalloc(sizeof(struct gen_pool), GFP_KERNEL);
+ if (!poolp)
+ return NULL;
+ memset(poolp, 0, sizeof(struct gen_pool));
+ poolp->h = kmalloc(sizeof(struct gen_pool_link) *
+ (max_chunk_shift - ALLOC_MIN_SHIFT + 1),
+ GFP_KERNEL);
+ if (!poolp->h) {
+ printk(KERN_WARNING "gen_pool_alloc() failed to allocate\n");
+ kfree(poolp);
+ return NULL;
+ }
+ memset(poolp->h, 0, sizeof(struct gen_pool_link) *
+ (max_chunk_shift - ALLOC_MIN_SHIFT + 1));
+
+ spin_lock_init(&poolp->lock);
+ poolp->get_new_chunk = fp;
+ poolp->max_chunk_shift = max_chunk_shift;
+ poolp->private = data;
+
+ for (i = 0; i < nr_chunks; i++) {
+ tmp = poolp->get_new_chunk(poolp);
+ printk(KERN_INFO "allocated %lx\n", tmp);
+ if (!tmp)
+ break;
+ gen_pool_free(poolp, tmp, (1 << poolp->max_chunk_shift));
+ }
+
+ return poolp;
+}
+EXPORT_SYMBOL(gen_pool_create);
+
+
+/*
+ * Simple power of two buddy-like generic allocator.
+ * Provides naturally aligned memory chunks.
+ */
+unsigned long gen_pool_alloc(struct gen_pool *poolp, int size)
+{
+ int j, i, s, max_chunk_size;
+ unsigned long a, flags;
+ struct gen_pool_link *h = poolp->h;
+
+ max_chunk_size = 1 << poolp->max_chunk_shift;
+
+ if (size > max_chunk_size)
+ return 0;
+
+ i = 0;
+
+ size = max(size, 1 << ALLOC_MIN_SHIFT);
+ s = roundup_pow_of_two(size);
+
+ j = i;
+
+ spin_lock_irqsave(&poolp->lock, flags);
+ while (!h[j].next) {
+ if (s == max_chunk_size) {
+ struct gen_pool_link *ptr;
+ spin_unlock_irqrestore(&poolp->lock, flags);
+ ptr = (struct gen_pool_link *)poolp->get_new_chunk(poolp);
+ spin_lock_irqsave(&poolp->lock, flags);
+ h[j].next = ptr;
+ if (h[j].next)
+ h[j].next->next = NULL;
+ break;
+ }
+ j++;
+ s <<= 1;
+ }
+ a = (unsigned long) h[j].next;
+ if (a) {
+ h[j].next = h[j].next->next;
+ /*
+ * This should be split into a seperate function doing
+ * the chunk split in order to support custom
+ * handling memory not physically accessible by host
+ */
+ while (j > i) {
+ j -= 1;
+ s >>= 1;
+ h[j].next = (struct gen_pool_link *) (a + s);
+ h[j].next->next = NULL;
+ }
+ }
+ spin_unlock_irqrestore(&poolp->lock, flags);
+ return a;
+}
+EXPORT_SYMBOL(gen_pool_alloc);
+
+
+/*
+ * Counter-part of the generic allocator.
+ */
+void gen_pool_free(struct gen_pool *poolp, unsigned long ptr, int size)
+{
+ struct gen_pool_link *q;
+ struct gen_pool_link *h = poolp->h;
+ unsigned long a, b, flags;
+ int i, s, max_chunk_size;
+
+ max_chunk_size = 1 << poolp->max_chunk_shift;
+
+ if (size > max_chunk_size)
+ return;
+
+ i = 0;
+
+ size = max(size, 1 << ALLOC_MIN_SHIFT);
+ s = roundup_pow_of_two(size);
+
+ a = ptr;
+
+ spin_lock_irqsave(&poolp->lock, flags);
+ while (1) {
+ if (s == max_chunk_size) {
+ ((struct gen_pool_link *)a)->next = h[i].next;
+ h[i].next = (struct gen_pool_link *)a;
+ break;
+ }
+ b = a ^ s;
+ q = &h[i];
+
+ while (q->next && q->next != (struct gen_pool_link *)b)
+ q = q->next;
+
+ if (!q->next) {
+ ((struct gen_pool_link *)a)->next = h[i].next;
+ h[i].next = (struct gen_pool_link *)a;
+ break;
+ }
+ q->next = q->next->next;
+ a = a & b;
+ s <<= 1;
+ i++;
+ }
+ spin_unlock_irqrestore(&poolp->lock, flags);
+}
+EXPORT_SYMBOL(gen_pool_free);
diff --git a/lib/idr.c b/lib/idr.c
index 81fc430602e..c5be889de44 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -175,7 +175,7 @@ build_up:
* Add a new layer to the top of the tree if the requested
* id is larger than the currently allocated space.
*/
- while ((layers < MAX_LEVEL) && (id >= (1 << (layers*IDR_BITS)))) {
+ while ((layers < (MAX_LEVEL - 1)) && (id >= (1 << (layers*IDR_BITS)))) {
layers++;
if (!p->count)
continue;
diff --git a/lib/kernel_lock.c b/lib/kernel_lock.c
index 99b0ae3d51d..bd2bc5d887b 100644
--- a/lib/kernel_lock.c
+++ b/lib/kernel_lock.c
@@ -9,61 +9,6 @@
#include <linux/module.h>
#include <linux/kallsyms.h>
-#if defined(CONFIG_PREEMPT) && defined(__smp_processor_id) && \
- defined(CONFIG_DEBUG_PREEMPT)
-
-/*
- * Debugging check.
- */
-unsigned int smp_processor_id(void)
-{
- unsigned long preempt_count = preempt_count();
- int this_cpu = __smp_processor_id();
- cpumask_t this_mask;
-
- if (likely(preempt_count))
- goto out;
-
- if (irqs_disabled())
- goto out;
-
- /*
- * Kernel threads bound to a single CPU can safely use
- * smp_processor_id():
- */
- this_mask = cpumask_of_cpu(this_cpu);
-
- if (cpus_equal(current->cpus_allowed, this_mask))
- goto out;
-
- /*
- * It is valid to assume CPU-locality during early bootup:
- */
- if (system_state != SYSTEM_RUNNING)
- goto out;
-
- /*
- * Avoid recursion:
- */
- preempt_disable();
-
- if (!printk_ratelimit())
- goto out_enable;
-
- printk(KERN_ERR "BUG: using smp_processor_id() in preemptible [%08x] code: %s/%d\n", preempt_count(), current->comm, current->pid);
- print_symbol("caller is %s\n", (long)__builtin_return_address(0));
- dump_stack();
-
-out_enable:
- preempt_enable_no_resched();
-out:
- return this_cpu;
-}
-
-EXPORT_SYMBOL(smp_processor_id);
-
-#endif /* PREEMPT && __smp_processor_id && DEBUG_PREEMPT */
-
#ifdef CONFIG_PREEMPT_BKL
/*
* The 'big kernel semaphore'
diff --git a/lib/klist.c b/lib/klist.c
new file mode 100644
index 00000000000..738ab810160
--- /dev/null
+++ b/lib/klist.c
@@ -0,0 +1,265 @@
+/*
+ * klist.c - Routines for manipulating klists.
+ *
+ *
+ * This klist interface provides a couple of structures that wrap around
+ * struct list_head to provide explicit list "head" (struct klist) and
+ * list "node" (struct klist_node) objects. For struct klist, a spinlock
+ * is included that protects access to the actual list itself. struct
+ * klist_node provides a pointer to the klist that owns it and a kref
+ * reference count that indicates the number of current users of that node
+ * in the list.
+ *
+ * The entire point is to provide an interface for iterating over a list
+ * that is safe and allows for modification of the list during the
+ * iteration (e.g. insertion and removal), including modification of the
+ * current node on the list.
+ *
+ * It works using a 3rd object type - struct klist_iter - that is declared
+ * and initialized before an iteration. klist_next() is used to acquire the
+ * next element in the list. It returns NULL if there are no more items.
+ * Internally, that routine takes the klist's lock, decrements the reference
+ * count of the previous klist_node and increments the count of the next
+ * klist_node. It then drops the lock and returns.
+ *
+ * There are primitives for adding and removing nodes to/from a klist.
+ * When deleting, klist_del() will simply decrement the reference count.
+ * Only when the count goes to 0 is the node removed from the list.
+ * klist_remove() will try to delete the node from the list and block
+ * until it is actually removed. This is useful for objects (like devices)
+ * that have been removed from the system and must be freed (but must wait
+ * until all accessors have finished).
+ *
+ * Copyright (C) 2005 Patrick Mochel
+ *
+ * This file is released under the GPL v2.
+ */
+
+#include <linux/klist.h>
+#include <linux/module.h>
+
+
+/**
+ * klist_init - Initialize a klist structure.
+ * @k: The klist we're initializing.
+ */
+
+void klist_init(struct klist * k)
+{
+ INIT_LIST_HEAD(&k->k_list);
+ spin_lock_init(&k->k_lock);
+}
+
+EXPORT_SYMBOL_GPL(klist_init);
+
+
+static void add_head(struct klist * k, struct klist_node * n)
+{
+ spin_lock(&k->k_lock);
+ list_add(&n->n_node, &k->k_list);
+ spin_unlock(&k->k_lock);
+}
+
+static void add_tail(struct klist * k, struct klist_node * n)
+{
+ spin_lock(&k->k_lock);
+ list_add_tail(&n->n_node, &k->k_list);
+ spin_unlock(&k->k_lock);
+}
+
+
+static void klist_node_init(struct klist * k, struct klist_node * n)
+{
+ INIT_LIST_HEAD(&n->n_node);
+ init_completion(&n->n_removed);
+ kref_init(&n->n_ref);
+ n->n_klist = k;
+}
+
+
+/**
+ * klist_add_head - Initialize a klist_node and add it to front.
+ * @k: klist it's going on.
+ * @n: node we're adding.
+ */
+
+void klist_add_head(struct klist * k, struct klist_node * n)
+{
+ klist_node_init(k, n);
+ add_head(k, n);
+}
+
+EXPORT_SYMBOL_GPL(klist_add_head);
+
+
+/**
+ * klist_add_tail - Initialize a klist_node and add it to back.
+ * @k: klist it's going on.
+ * @n: node we're adding.
+ */
+
+void klist_add_tail(struct klist * k, struct klist_node * n)
+{
+ klist_node_init(k, n);
+ add_tail(k, n);
+}
+
+EXPORT_SYMBOL_GPL(klist_add_tail);
+
+
+static void klist_release(struct kref * kref)
+{
+ struct klist_node * n = container_of(kref, struct klist_node, n_ref);
+ list_del(&n->n_node);
+ complete(&n->n_removed);
+ n->n_klist = NULL;
+}
+
+static int klist_dec_and_del(struct klist_node * n)
+{
+ return kref_put(&n->n_ref, klist_release);
+}
+
+
+/**
+ * klist_del - Decrement the reference count of node and try to remove.
+ * @n: node we're deleting.
+ */
+
+void klist_del(struct klist_node * n)
+{
+ struct klist * k = n->n_klist;
+
+ spin_lock(&k->k_lock);
+ klist_dec_and_del(n);
+ spin_unlock(&k->k_lock);
+}
+
+EXPORT_SYMBOL_GPL(klist_del);
+
+
+/**
+ * klist_remove - Decrement the refcount of node and wait for it to go away.
+ * @n: node we're removing.
+ */
+
+void klist_remove(struct klist_node * n)
+{
+ struct klist * k = n->n_klist;
+ spin_lock(&k->k_lock);
+ klist_dec_and_del(n);
+ spin_unlock(&k->k_lock);
+ wait_for_completion(&n->n_removed);
+}
+
+EXPORT_SYMBOL_GPL(klist_remove);
+
+
+/**
+ * klist_node_attached - Say whether a node is bound to a list or not.
+ * @n: Node that we're testing.
+ */
+
+int klist_node_attached(struct klist_node * n)
+{
+ return (n->n_klist != NULL);
+}
+
+EXPORT_SYMBOL_GPL(klist_node_attached);
+
+
+/**
+ * klist_iter_init_node - Initialize a klist_iter structure.
+ * @k: klist we're iterating.
+ * @i: klist_iter we're filling.
+ * @n: node to start with.
+ *
+ * Similar to klist_iter_init(), but starts the action off with @n,
+ * instead of with the list head.
+ */
+
+void klist_iter_init_node(struct klist * k, struct klist_iter * i, struct klist_node * n)
+{
+ i->i_klist = k;
+ i->i_head = &k->k_list;
+ i->i_cur = n;
+}
+
+EXPORT_SYMBOL_GPL(klist_iter_init_node);
+
+
+/**
+ * klist_iter_init - Iniitalize a klist_iter structure.
+ * @k: klist we're iterating.
+ * @i: klist_iter structure we're filling.
+ *
+ * Similar to klist_iter_init_node(), but start with the list head.
+ */
+
+void klist_iter_init(struct klist * k, struct klist_iter * i)
+{
+ klist_iter_init_node(k, i, NULL);
+}
+
+EXPORT_SYMBOL_GPL(klist_iter_init);
+
+
+/**
+ * klist_iter_exit - Finish a list iteration.
+ * @i: Iterator structure.
+ *
+ * Must be called when done iterating over list, as it decrements the
+ * refcount of the current node. Necessary in case iteration exited before
+ * the end of the list was reached, and always good form.
+ */
+
+void klist_iter_exit(struct klist_iter * i)
+{
+ if (i->i_cur) {
+ klist_del(i->i_cur);
+ i->i_cur = NULL;
+ }
+}
+
+EXPORT_SYMBOL_GPL(klist_iter_exit);
+
+
+static struct klist_node * to_klist_node(struct list_head * n)
+{
+ return container_of(n, struct klist_node, n_node);
+}
+
+
+/**
+ * klist_next - Ante up next node in list.
+ * @i: Iterator structure.
+ *
+ * First grab list lock. Decrement the reference count of the previous
+ * node, if there was one. Grab the next node, increment its reference
+ * count, drop the lock, and return that next node.
+ */
+
+struct klist_node * klist_next(struct klist_iter * i)
+{
+ struct list_head * next;
+ struct klist_node * knode = NULL;
+
+ spin_lock(&i->i_klist->k_lock);
+ if (i->i_cur) {
+ next = i->i_cur->n_node.next;
+ klist_dec_and_del(i->i_cur);
+ } else
+ next = i->i_head->next;
+
+ if (next != i->i_head) {
+ knode = to_klist_node(next);
+ kref_get(&knode->n_ref);
+ }
+ i->i_cur = knode;
+ spin_unlock(&i->i_klist->k_lock);
+ return knode;
+}
+
+EXPORT_SYMBOL_GPL(klist_next);
+
+
diff --git a/lib/kobject.c b/lib/kobject.c
index 94048826624..dd0917dd9fa 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -279,7 +279,7 @@ EXPORT_SYMBOL(kobject_set_name);
* @new_name: object's new name
*/
-int kobject_rename(struct kobject * kobj, char *new_name)
+int kobject_rename(struct kobject * kobj, const char *new_name)
{
int error = 0;
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 2a4e7671eaf..8e49d21057e 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -197,7 +197,7 @@ void kobject_hotplug(struct kobject *kobj, enum kobject_action action)
int i = 0;
int retval;
char *kobj_path = NULL;
- char *name = NULL;
+ const char *name = NULL;
char *action_string;
u64 seq;
struct kobject *top_kobj = kobj;
@@ -246,10 +246,10 @@ void kobject_hotplug(struct kobject *kobj, enum kobject_action action)
if (hotplug_ops->name)
name = hotplug_ops->name(kset, kobj);
if (name == NULL)
- name = kset->kobj.name;
+ name = kobject_name(&kset->kobj);
argv [0] = hotplug_path;
- argv [1] = name;
+ argv [1] = (char *)name; /* won't be changed but 'const' has to go */
argv [2] = NULL;
/* minimal command environment */
diff --git a/lib/sha1.c b/lib/sha1.c
index 2f7f1148dfd..1cdabe3065f 100644
--- a/lib/sha1.c
+++ b/lib/sha1.c
@@ -41,7 +41,7 @@ void sha_transform(__u32 *digest, const char *in, __u32 *W)
__u32 a, b, c, d, e, t, i;
for (i = 0; i < 16; i++)
- W[i] = be32_to_cpu(((const __u32 *)in)[i]);
+ W[i] = be32_to_cpu(((const __be32 *)in)[i]);
for (i = 0; i < 64; i++)
W[i+16] = rol32(W[i+13] ^ W[i+8] ^ W[i+2] ^ W[i], 1);
diff --git a/lib/smp_processor_id.c b/lib/smp_processor_id.c
new file mode 100644
index 00000000000..42c08ef828c
--- /dev/null
+++ b/lib/smp_processor_id.c
@@ -0,0 +1,55 @@
+/*
+ * lib/smp_processor_id.c
+ *
+ * DEBUG_PREEMPT variant of smp_processor_id().
+ */
+#include <linux/module.h>
+#include <linux/kallsyms.h>
+
+unsigned int debug_smp_processor_id(void)
+{
+ unsigned long preempt_count = preempt_count();
+ int this_cpu = raw_smp_processor_id();
+ cpumask_t this_mask;
+
+ if (likely(preempt_count))
+ goto out;
+
+ if (irqs_disabled())
+ goto out;
+
+ /*
+ * Kernel threads bound to a single CPU can safely use
+ * smp_processor_id():
+ */
+ this_mask = cpumask_of_cpu(this_cpu);
+
+ if (cpus_equal(current->cpus_allowed, this_mask))
+ goto out;
+
+ /*
+ * It is valid to assume CPU-locality during early bootup:
+ */
+ if (system_state != SYSTEM_RUNNING)
+ goto out;
+
+ /*
+ * Avoid recursion:
+ */
+ preempt_disable();
+
+ if (!printk_ratelimit())
+ goto out_enable;
+
+ printk(KERN_ERR "BUG: using smp_processor_id() in preemptible [%08x] code: %s/%d\n", preempt_count(), current->comm, current->pid);
+ print_symbol("caller is %s\n", (long)__builtin_return_address(0));
+ dump_stack();
+
+out_enable:
+ preempt_enable_no_resched();
+out:
+ return this_cpu;
+}
+
+EXPORT_SYMBOL(debug_smp_processor_id);
+
diff --git a/lib/textsearch.c b/lib/textsearch.c
new file mode 100644
index 00000000000..1e934c196f0
--- /dev/null
+++ b/lib/textsearch.c
@@ -0,0 +1,317 @@
+/*
+ * lib/textsearch.c Generic text search interface
+ *
+ * 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.
+ *
+ * Authors: Thomas Graf <tgraf@suug.ch>
+ * Pablo Neira Ayuso <pablo@eurodev.net>
+ *
+ * ==========================================================================
+ *
+ * INTRODUCTION
+ *
+ * The textsearch infrastructure provides text searching facitilies for
+ * both linear and non-linear data. Individual search algorithms are
+ * implemented in modules and chosen by the user.
+ *
+ * ARCHITECTURE
+ *
+ * User
+ * +----------------+
+ * | finish()|<--------------(6)-----------------+
+ * |get_next_block()|<--------------(5)---------------+ |
+ * | | Algorithm | |
+ * | | +------------------------------+
+ * | | | init() find() destroy() |
+ * | | +------------------------------+
+ * | | Core API ^ ^ ^
+ * | | +---------------+ (2) (4) (8)
+ * | (1)|----->| prepare() |---+ | |
+ * | (3)|----->| find()/next() |-----------+ |
+ * | (7)|----->| destroy() |----------------------+
+ * +----------------+ +---------------+
+ *
+ * (1) User configures a search by calling _prepare() specifying the
+ * search parameters such as the pattern and algorithm name.
+ * (2) Core requests the algorithm to allocate and initialize a search
+ * configuration according to the specified parameters.
+ * (3) User starts the search(es) by calling _find() or _next() to
+ * fetch subsequent occurrences. A state variable is provided
+ * to the algorihtm to store persistant variables.
+ * (4) Core eventually resets the search offset and forwards the find()
+ * request to the algorithm.
+ * (5) Algorithm calls get_next_block() provided by the user continously
+ * to fetch the data to be searched in block by block.
+ * (6) Algorithm invokes finish() after the last call to get_next_block
+ * to clean up any leftovers from get_next_block. (Optional)
+ * (7) User destroys the configuration by calling _destroy().
+ * (8) Core notifies the algorithm to destroy algorithm specific
+ * allocations. (Optional)
+ *
+ * USAGE
+ *
+ * Before a search can be performed, a configuration must be created
+ * by calling textsearch_prepare() specyfing the searching algorithm and
+ * the pattern to look for. The returned configuration may then be used
+ * for an arbitary amount of times and even in parallel as long as a
+ * separate struct ts_state variable is provided to every instance.
+ *
+ * The actual search is performed by either calling textsearch_find_-
+ * continuous() for linear data or by providing an own get_next_block()
+ * implementation and calling textsearch_find(). Both functions return
+ * the position of the first occurrence of the patern or UINT_MAX if
+ * no match was found. Subsequent occurences can be found by calling
+ * textsearch_next() regardless of the linearity of the data.
+ *
+ * Once you're done using a configuration it must be given back via
+ * textsearch_destroy.
+ *
+ * EXAMPLE
+ *
+ * int pos;
+ * struct ts_config *conf;
+ * struct ts_state state;
+ * const char *pattern = "chicken";
+ * const char *example = "We dance the funky chicken";
+ *
+ * conf = textsearch_prepare("kmp", pattern, strlen(pattern),
+ * GFP_KERNEL, TS_AUTOLOAD);
+ * if (IS_ERR(conf)) {
+ * err = PTR_ERR(conf);
+ * goto errout;
+ * }
+ *
+ * pos = textsearch_find_continuous(conf, &state, example, strlen(example));
+ * if (pos != UINT_MAX)
+ * panic("Oh my god, dancing chickens at %d\n", pos);
+ *
+ * textsearch_destroy(conf);
+ *
+ * ==========================================================================
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/rcupdate.h>
+#include <linux/err.h>
+#include <linux/textsearch.h>
+
+static LIST_HEAD(ts_ops);
+static DEFINE_SPINLOCK(ts_mod_lock);
+
+static inline struct ts_ops *lookup_ts_algo(const char *name)
+{
+ struct ts_ops *o;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(o, &ts_ops, list) {
+ if (!strcmp(name, o->name)) {
+ if (!try_module_get(o->owner))
+ o = NULL;
+ rcu_read_unlock();
+ return o;
+ }
+ }
+ rcu_read_unlock();
+
+ return NULL;
+}
+
+/**
+ * textsearch_register - register a textsearch module
+ * @ops: operations lookup table
+ *
+ * This function must be called by textsearch modules to announce
+ * their presence. The specified &@ops must have %name set to a
+ * unique identifier and the callbacks find(), init(), get_pattern(),
+ * and get_pattern_len() must be implemented.
+ *
+ * Returns 0 or -EEXISTS if another module has already registered
+ * with same name.
+ */
+int textsearch_register(struct ts_ops *ops)
+{
+ int err = -EEXIST;
+ struct ts_ops *o;
+
+ if (ops->name == NULL || ops->find == NULL || ops->init == NULL ||
+ ops->get_pattern == NULL || ops->get_pattern_len == NULL)
+ return -EINVAL;
+
+ spin_lock(&ts_mod_lock);
+ list_for_each_entry(o, &ts_ops, list) {
+ if (!strcmp(ops->name, o->name))
+ goto errout;
+ }
+
+ list_add_tail_rcu(&ops->list, &ts_ops);
+ err = 0;
+errout:
+ spin_unlock(&ts_mod_lock);
+ return err;
+}
+
+/**
+ * textsearch_unregister - unregister a textsearch module
+ * @ops: operations lookup table
+ *
+ * This function must be called by textsearch modules to announce
+ * their disappearance for examples when the module gets unloaded.
+ * The &ops parameter must be the same as the one during the
+ * registration.
+ *
+ * Returns 0 on success or -ENOENT if no matching textsearch
+ * registration was found.
+ */
+int textsearch_unregister(struct ts_ops *ops)
+{
+ int err = 0;
+ struct ts_ops *o;
+
+ spin_lock(&ts_mod_lock);
+ list_for_each_entry(o, &ts_ops, list) {
+ if (o == ops) {
+ list_del_rcu(&o->list);
+ goto out;
+ }
+ }
+
+ err = -ENOENT;
+out:
+ spin_unlock(&ts_mod_lock);
+ return err;
+}
+
+struct ts_linear_state
+{
+ unsigned int len;
+ const void *data;
+};
+
+static unsigned int get_linear_data(unsigned int consumed, const u8 **dst,
+ struct ts_config *conf,
+ struct ts_state *state)
+{
+ struct ts_linear_state *st = (struct ts_linear_state *) state->cb;
+
+ if (likely(consumed < st->len)) {
+ *dst = st->data + consumed;
+ return st->len - consumed;
+ }
+
+ return 0;
+}
+
+/**
+ * textsearch_find_continuous - search a pattern in continuous/linear data
+ * @conf: search configuration
+ * @state: search state
+ * @data: data to search in
+ * @len: length of data
+ *
+ * A simplified version of textsearch_find() for continuous/linear data.
+ * Call textsearch_next() to retrieve subsequent matches.
+ *
+ * Returns the position of first occurrence of the pattern or
+ * UINT_MAX if no occurrence was found.
+ */
+unsigned int textsearch_find_continuous(struct ts_config *conf,
+ struct ts_state *state,
+ const void *data, unsigned int len)
+{
+ struct ts_linear_state *st = (struct ts_linear_state *) state->cb;
+
+ conf->get_next_block = get_linear_data;
+ st->data = data;
+ st->len = len;
+
+ return textsearch_find(conf, state);
+}
+
+/**
+ * textsearch_prepare - Prepare a search
+ * @algo: name of search algorithm
+ * @pattern: pattern data
+ * @len: length of pattern
+ * @gfp_mask: allocation mask
+ * @flags: search flags
+ *
+ * Looks up the search algorithm module and creates a new textsearch
+ * configuration for the specified pattern. Upon completion all
+ * necessary refcnts are held and the configuration must be put back
+ * using textsearch_put() after usage.
+ *
+ * Note: The format of the pattern may not be compatible between
+ * the various search algorithms.
+ *
+ * Returns a new textsearch configuration according to the specified
+ * parameters or a ERR_PTR().
+ */
+struct ts_config *textsearch_prepare(const char *algo, const void *pattern,
+ unsigned int len, int gfp_mask, int flags)
+{
+ int err = -ENOENT;
+ struct ts_config *conf;
+ struct ts_ops *ops;
+
+ ops = lookup_ts_algo(algo);
+#ifdef CONFIG_KMOD
+ /*
+ * Why not always autoload you may ask. Some users are
+ * in a situation where requesting a module may deadlock,
+ * especially when the module is located on a NFS mount.
+ */
+ if (ops == NULL && flags & TS_AUTOLOAD) {
+ request_module("ts_%s", algo);
+ ops = lookup_ts_algo(algo);
+ }
+#endif
+
+ if (ops == NULL)
+ goto errout;
+
+ conf = ops->init(pattern, len, gfp_mask);
+ if (IS_ERR(conf)) {
+ err = PTR_ERR(conf);
+ goto errout;
+ }
+
+ conf->ops = ops;
+ return conf;
+
+errout:
+ if (ops)
+ module_put(ops->owner);
+
+ return ERR_PTR(err);
+}
+
+/**
+ * textsearch_destroy - destroy a search configuration
+ * @conf: search configuration
+ *
+ * Releases all references of the configuration and frees
+ * up the memory.
+ */
+void textsearch_destroy(struct ts_config *conf)
+{
+ if (conf->ops) {
+ if (conf->ops->destroy)
+ conf->ops->destroy(conf);
+ module_put(conf->ops->owner);
+ }
+
+ kfree(conf);
+}
+
+EXPORT_SYMBOL(textsearch_register);
+EXPORT_SYMBOL(textsearch_unregister);
+EXPORT_SYMBOL(textsearch_prepare);
+EXPORT_SYMBOL(textsearch_find_continuous);
+EXPORT_SYMBOL(textsearch_destroy);
diff --git a/lib/ts_fsm.c b/lib/ts_fsm.c
new file mode 100644
index 00000000000..d27c0a07294
--- /dev/null
+++ b/lib/ts_fsm.c
@@ -0,0 +1,338 @@
+/*
+ * lib/ts_fsm.c A naive finite state machine text search approach
+ *
+ * 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.
+ *
+ * Authors: Thomas Graf <tgraf@suug.ch>
+ *
+ * ==========================================================================
+ *
+ * A finite state machine consists of n states (struct ts_fsm_token)
+ * representing the pattern as a finite automation. The data is read
+ * sequentially on a octet basis. Every state token specifies the number
+ * of recurrences and the type of value accepted which can be either a
+ * specific character or ctype based set of characters. The available
+ * type of recurrences include 1, (0|1), [0 n], and [1 n].
+ *
+ * The algorithm differs between strict/non-strict mode specyfing
+ * whether the pattern has to start at the first octect. Strict mode
+ * is enabled by default and can be disabled by inserting
+ * TS_FSM_HEAD_IGNORE as the first token in the chain.
+ *
+ * The runtime performance of the algorithm should be around O(n),
+ * however while in strict mode the average runtime can be better.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/textsearch.h>
+#include <linux/textsearch_fsm.h>
+
+struct ts_fsm
+{
+ unsigned int ntokens;
+ struct ts_fsm_token tokens[0];
+};
+
+/* other values derived from ctype.h */
+#define _A 0x100 /* ascii */
+#define _W 0x200 /* wildcard */
+
+/* Map to _ctype flags and some magic numbers */
+static u16 token_map[TS_FSM_TYPE_MAX+1] = {
+ [TS_FSM_SPECIFIC] = 0,
+ [TS_FSM_WILDCARD] = _W,
+ [TS_FSM_CNTRL] = _C,
+ [TS_FSM_LOWER] = _L,
+ [TS_FSM_UPPER] = _U,
+ [TS_FSM_PUNCT] = _P,
+ [TS_FSM_SPACE] = _S,
+ [TS_FSM_DIGIT] = _D,
+ [TS_FSM_XDIGIT] = _D | _X,
+ [TS_FSM_ALPHA] = _U | _L,
+ [TS_FSM_ALNUM] = _U | _L | _D,
+ [TS_FSM_PRINT] = _P | _U | _L | _D | _SP,
+ [TS_FSM_GRAPH] = _P | _U | _L | _D,
+ [TS_FSM_ASCII] = _A,
+};
+
+static u16 token_lookup_tbl[256] = {
+_W|_A|_C, _W|_A|_C, _W|_A|_C, _W|_A|_C, /* 0- 3 */
+_W|_A|_C, _W|_A|_C, _W|_A|_C, _W|_A|_C, /* 4- 7 */
+_W|_A|_C, _W|_A|_C|_S, _W|_A|_C|_S, _W|_A|_C|_S, /* 8- 11 */
+_W|_A|_C|_S, _W|_A|_C|_S, _W|_A|_C, _W|_A|_C, /* 12- 15 */
+_W|_A|_C, _W|_A|_C, _W|_A|_C, _W|_A|_C, /* 16- 19 */
+_W|_A|_C, _W|_A|_C, _W|_A|_C, _W|_A|_C, /* 20- 23 */
+_W|_A|_C, _W|_A|_C, _W|_A|_C, _W|_A|_C, /* 24- 27 */
+_W|_A|_C, _W|_A|_C, _W|_A|_C, _W|_A|_C, /* 28- 31 */
+_W|_A|_S|_SP, _W|_A|_P, _W|_A|_P, _W|_A|_P, /* 32- 35 */
+_W|_A|_P, _W|_A|_P, _W|_A|_P, _W|_A|_P, /* 36- 39 */
+_W|_A|_P, _W|_A|_P, _W|_A|_P, _W|_A|_P, /* 40- 43 */
+_W|_A|_P, _W|_A|_P, _W|_A|_P, _W|_A|_P, /* 44- 47 */
+_W|_A|_D, _W|_A|_D, _W|_A|_D, _W|_A|_D, /* 48- 51 */
+_W|_A|_D, _W|_A|_D, _W|_A|_D, _W|_A|_D, /* 52- 55 */
+_W|_A|_D, _W|_A|_D, _W|_A|_P, _W|_A|_P, /* 56- 59 */
+_W|_A|_P, _W|_A|_P, _W|_A|_P, _W|_A|_P, /* 60- 63 */
+_W|_A|_P, _W|_A|_U|_X, _W|_A|_U|_X, _W|_A|_U|_X, /* 64- 67 */
+_W|_A|_U|_X, _W|_A|_U|_X, _W|_A|_U|_X, _W|_A|_U, /* 68- 71 */
+_W|_A|_U, _W|_A|_U, _W|_A|_U, _W|_A|_U, /* 72- 75 */
+_W|_A|_U, _W|_A|_U, _W|_A|_U, _W|_A|_U, /* 76- 79 */
+_W|_A|_U, _W|_A|_U, _W|_A|_U, _W|_A|_U, /* 80- 83 */
+_W|_A|_U, _W|_A|_U, _W|_A|_U, _W|_A|_U, /* 84- 87 */
+_W|_A|_U, _W|_A|_U, _W|_A|_U, _W|_A|_P, /* 88- 91 */
+_W|_A|_P, _W|_A|_P, _W|_A|_P, _W|_A|_P, /* 92- 95 */
+_W|_A|_P, _W|_A|_L|_X, _W|_A|_L|_X, _W|_A|_L|_X, /* 96- 99 */
+_W|_A|_L|_X, _W|_A|_L|_X, _W|_A|_L|_X, _W|_A|_L, /* 100-103 */
+_W|_A|_L, _W|_A|_L, _W|_A|_L, _W|_A|_L, /* 104-107 */
+_W|_A|_L, _W|_A|_L, _W|_A|_L, _W|_A|_L, /* 108-111 */
+_W|_A|_L, _W|_A|_L, _W|_A|_L, _W|_A|_L, /* 112-115 */
+_W|_A|_L, _W|_A|_L, _W|_A|_L, _W|_A|_L, /* 116-119 */
+_W|_A|_L, _W|_A|_L, _W|_A|_L, _W|_A|_P, /* 120-123 */
+_W|_A|_P, _W|_A|_P, _W|_A|_P, _W|_A|_C, /* 124-127 */
+_W, _W, _W, _W, /* 128-131 */
+_W, _W, _W, _W, /* 132-135 */
+_W, _W, _W, _W, /* 136-139 */
+_W, _W, _W, _W, /* 140-143 */
+_W, _W, _W, _W, /* 144-147 */
+_W, _W, _W, _W, /* 148-151 */
+_W, _W, _W, _W, /* 152-155 */
+_W, _W, _W, _W, /* 156-159 */
+_W|_S|_SP, _W|_P, _W|_P, _W|_P, /* 160-163 */
+_W|_P, _W|_P, _W|_P, _W|_P, /* 164-167 */
+_W|_P, _W|_P, _W|_P, _W|_P, /* 168-171 */
+_W|_P, _W|_P, _W|_P, _W|_P, /* 172-175 */
+_W|_P, _W|_P, _W|_P, _W|_P, /* 176-179 */
+_W|_P, _W|_P, _W|_P, _W|_P, /* 180-183 */
+_W|_P, _W|_P, _W|_P, _W|_P, /* 184-187 */
+_W|_P, _W|_P, _W|_P, _W|_P, /* 188-191 */
+_W|_U, _W|_U, _W|_U, _W|_U, /* 192-195 */
+_W|_U, _W|_U, _W|_U, _W|_U, /* 196-199 */
+_W|_U, _W|_U, _W|_U, _W|_U, /* 200-203 */
+_W|_U, _W|_U, _W|_U, _W|_U, /* 204-207 */
+_W|_U, _W|_U, _W|_U, _W|_U, /* 208-211 */
+_W|_U, _W|_U, _W|_U, _W|_P, /* 212-215 */
+_W|_U, _W|_U, _W|_U, _W|_U, /* 216-219 */
+_W|_U, _W|_U, _W|_U, _W|_L, /* 220-223 */
+_W|_L, _W|_L, _W|_L, _W|_L, /* 224-227 */
+_W|_L, _W|_L, _W|_L, _W|_L, /* 228-231 */
+_W|_L, _W|_L, _W|_L, _W|_L, /* 232-235 */
+_W|_L, _W|_L, _W|_L, _W|_L, /* 236-239 */
+_W|_L, _W|_L, _W|_L, _W|_L, /* 240-243 */
+_W|_L, _W|_L, _W|_L, _W|_P, /* 244-247 */
+_W|_L, _W|_L, _W|_L, _W|_L, /* 248-251 */
+_W|_L, _W|_L, _W|_L, _W|_L}; /* 252-255 */
+
+static inline int match_token(struct ts_fsm_token *t, u8 d)
+{
+ if (t->type)
+ return (token_lookup_tbl[d] & t->type) != 0;
+ else
+ return t->value == d;
+}
+
+static unsigned int fsm_find(struct ts_config *conf, struct ts_state *state)
+{
+ struct ts_fsm *fsm = ts_config_priv(conf);
+ struct ts_fsm_token *cur = NULL, *next;
+ unsigned int match_start, block_idx = 0, tok_idx;
+ unsigned block_len = 0, strict, consumed = state->offset;
+ const u8 *data;
+
+#define GET_NEXT_BLOCK() \
+({ consumed += block_idx; \
+ block_idx = 0; \
+ block_len = conf->get_next_block(consumed, &data, conf, state); })
+
+#define TOKEN_MISMATCH() \
+ do { \
+ if (strict) \
+ goto no_match; \
+ block_idx++; \
+ goto startover; \
+ } while(0)
+
+#define end_of_data() unlikely(block_idx >= block_len && !GET_NEXT_BLOCK())
+
+ if (end_of_data())
+ goto no_match;
+
+ strict = fsm->tokens[0].recur != TS_FSM_HEAD_IGNORE;
+
+startover:
+ match_start = consumed + block_idx;
+
+ for (tok_idx = 0; tok_idx < fsm->ntokens; tok_idx++) {
+ cur = &fsm->tokens[tok_idx];
+
+ if (likely(tok_idx < (fsm->ntokens - 1)))
+ next = &fsm->tokens[tok_idx + 1];
+ else
+ next = NULL;
+
+ switch (cur->recur) {
+ case TS_FSM_SINGLE:
+ if (end_of_data())
+ goto no_match;
+
+ if (!match_token(cur, data[block_idx]))
+ TOKEN_MISMATCH();
+ break;
+
+ case TS_FSM_PERHAPS:
+ if (end_of_data() ||
+ !match_token(cur, data[block_idx]))
+ continue;
+ break;
+
+ case TS_FSM_MULTI:
+ if (end_of_data())
+ goto no_match;
+
+ if (!match_token(cur, data[block_idx]))
+ TOKEN_MISMATCH();
+
+ block_idx++;
+ /* fall through */
+
+ case TS_FSM_ANY:
+ if (next == NULL)
+ goto found_match;
+
+ if (end_of_data())
+ continue;
+
+ while (!match_token(next, data[block_idx])) {
+ if (!match_token(cur, data[block_idx]))
+ TOKEN_MISMATCH();
+ block_idx++;
+ if (end_of_data())
+ goto no_match;
+ }
+ continue;
+
+ /*
+ * Optimization: Prefer small local loop over jumping
+ * back and forth until garbage at head is munched.
+ */
+ case TS_FSM_HEAD_IGNORE:
+ if (end_of_data())
+ continue;
+
+ while (!match_token(next, data[block_idx])) {
+ /*
+ * Special case, don't start over upon
+ * a mismatch, give the user the
+ * chance to specify the type of data
+ * allowed to be ignored.
+ */
+ if (!match_token(cur, data[block_idx]))
+ goto no_match;
+
+ block_idx++;
+ if (end_of_data())
+ goto no_match;
+ }
+
+ match_start = consumed + block_idx;
+ continue;
+ }
+
+ block_idx++;
+ }
+
+ if (end_of_data())
+ goto found_match;
+
+no_match:
+ return UINT_MAX;
+
+found_match:
+ state->offset = consumed + block_idx;
+ return match_start;
+}
+
+static struct ts_config *fsm_init(const void *pattern, unsigned int len,
+ int gfp_mask)
+{
+ int i, err = -EINVAL;
+ struct ts_config *conf;
+ struct ts_fsm *fsm;
+ struct ts_fsm_token *tokens = (struct ts_fsm_token *) pattern;
+ unsigned int ntokens = len / sizeof(*tokens);
+ size_t priv_size = sizeof(*fsm) + len;
+
+ if (len % sizeof(struct ts_fsm_token) || ntokens < 1)
+ goto errout;
+
+ for (i = 0; i < ntokens; i++) {
+ struct ts_fsm_token *t = &tokens[i];
+
+ if (t->type > TS_FSM_TYPE_MAX || t->recur > TS_FSM_RECUR_MAX)
+ goto errout;
+
+ if (t->recur == TS_FSM_HEAD_IGNORE &&
+ (i != 0 || i == (ntokens - 1)))
+ goto errout;
+ }
+
+ conf = alloc_ts_config(priv_size, gfp_mask);
+ if (IS_ERR(conf))
+ return conf;
+
+ fsm = ts_config_priv(conf);
+ fsm->ntokens = ntokens;
+ memcpy(fsm->tokens, pattern, len);
+
+ for (i = 0; i < fsm->ntokens; i++) {
+ struct ts_fsm_token *t = &fsm->tokens[i];
+ t->type = token_map[t->type];
+ }
+
+ return conf;
+
+errout:
+ return ERR_PTR(err);
+}
+
+static void *fsm_get_pattern(struct ts_config *conf)
+{
+ struct ts_fsm *fsm = ts_config_priv(conf);
+ return fsm->tokens;
+}
+
+static unsigned int fsm_get_pattern_len(struct ts_config *conf)
+{
+ struct ts_fsm *fsm = ts_config_priv(conf);
+ return fsm->ntokens * sizeof(struct ts_fsm_token);
+}
+
+static struct ts_ops fsm_ops = {
+ .name = "fsm",
+ .find = fsm_find,
+ .init = fsm_init,
+ .get_pattern = fsm_get_pattern,
+ .get_pattern_len = fsm_get_pattern_len,
+ .owner = THIS_MODULE,
+ .list = LIST_HEAD_INIT(fsm_ops.list)
+};
+
+static int __init init_fsm(void)
+{
+ return textsearch_register(&fsm_ops);
+}
+
+static void __exit exit_fsm(void)
+{
+ textsearch_unregister(&fsm_ops);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(init_fsm);
+module_exit(exit_fsm);
diff --git a/lib/ts_kmp.c b/lib/ts_kmp.c
new file mode 100644
index 00000000000..73266b97558
--- /dev/null
+++ b/lib/ts_kmp.c
@@ -0,0 +1,145 @@
+/*
+ * lib/ts_kmp.c Knuth-Morris-Pratt text search implementation
+ *
+ * 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.
+ *
+ * Authors: Thomas Graf <tgraf@suug.ch>
+ *
+ * ==========================================================================
+ *
+ * Implements a linear-time string-matching algorithm due to Knuth,
+ * Morris, and Pratt [1]. Their algorithm avoids the explicit
+ * computation of the transition function DELTA altogether. Its
+ * matching time is O(n), for n being length(text), using just an
+ * auxiliary function PI[1..m], for m being length(pattern),
+ * precomputed from the pattern in time O(m). The array PI allows
+ * the transition function DELTA to be computed efficiently
+ * "on the fly" as needed. Roughly speaking, for any state
+ * "q" = 0,1,...,m and any character "a" in SIGMA, the value
+ * PI["q"] contains the information that is independent of "a" and
+ * is needed to compute DELTA("q", "a") [2]. Since the array PI
+ * has only m entries, whereas DELTA has O(m|SIGMA|) entries, we
+ * save a factor of |SIGMA| in the preprocessing time by computing
+ * PI rather than DELTA.
+ *
+ * [1] Cormen, Leiserson, Rivest, Stein
+ * Introdcution to Algorithms, 2nd Edition, MIT Press
+ * [2] See finite automation theory
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/textsearch.h>
+
+struct ts_kmp
+{
+ u8 * pattern;
+ unsigned int pattern_len;
+ unsigned int prefix_tbl[0];
+};
+
+static unsigned int kmp_find(struct ts_config *conf, struct ts_state *state)
+{
+ struct ts_kmp *kmp = ts_config_priv(conf);
+ unsigned int i, q = 0, text_len, consumed = state->offset;
+ const u8 *text;
+
+ for (;;) {
+ text_len = conf->get_next_block(consumed, &text, conf, state);
+
+ if (unlikely(text_len == 0))
+ break;
+
+ for (i = 0; i < text_len; i++) {
+ while (q > 0 && kmp->pattern[q] != text[i])
+ q = kmp->prefix_tbl[q - 1];
+ if (kmp->pattern[q] == text[i])
+ q++;
+ if (unlikely(q == kmp->pattern_len)) {
+ state->offset = consumed + i + 1;
+ return state->offset - kmp->pattern_len;
+ }
+ }
+
+ consumed += text_len;
+ }
+
+ return UINT_MAX;
+}
+
+static inline void compute_prefix_tbl(const u8 *pattern, unsigned int len,
+ unsigned int *prefix_tbl)
+{
+ unsigned int k, q;
+
+ for (k = 0, q = 1; q < len; q++) {
+ while (k > 0 && pattern[k] != pattern[q])
+ k = prefix_tbl[k-1];
+ if (pattern[k] == pattern[q])
+ k++;
+ prefix_tbl[q] = k;
+ }
+}
+
+static struct ts_config *kmp_init(const void *pattern, unsigned int len,
+ int gfp_mask)
+{
+ struct ts_config *conf;
+ struct ts_kmp *kmp;
+ unsigned int prefix_tbl_len = len * sizeof(unsigned int);
+ size_t priv_size = sizeof(*kmp) + len + prefix_tbl_len;
+
+ conf = alloc_ts_config(priv_size, gfp_mask);
+ if (IS_ERR(conf))
+ return conf;
+
+ kmp = ts_config_priv(conf);
+ kmp->pattern_len = len;
+ compute_prefix_tbl(pattern, len, kmp->prefix_tbl);
+ kmp->pattern = (u8 *) kmp->prefix_tbl + prefix_tbl_len;
+ memcpy(kmp->pattern, pattern, len);
+
+ return conf;
+}
+
+static void *kmp_get_pattern(struct ts_config *conf)
+{
+ struct ts_kmp *kmp = ts_config_priv(conf);
+ return kmp->pattern;
+}
+
+static unsigned int kmp_get_pattern_len(struct ts_config *conf)
+{
+ struct ts_kmp *kmp = ts_config_priv(conf);
+ return kmp->pattern_len;
+}
+
+static struct ts_ops kmp_ops = {
+ .name = "kmp",
+ .find = kmp_find,
+ .init = kmp_init,
+ .get_pattern = kmp_get_pattern,
+ .get_pattern_len = kmp_get_pattern_len,
+ .owner = THIS_MODULE,
+ .list = LIST_HEAD_INIT(kmp_ops.list)
+};
+
+static int __init init_kmp(void)
+{
+ return textsearch_register(&kmp_ops);
+}
+
+static void __exit exit_kmp(void)
+{
+ textsearch_unregister(&kmp_ops);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(init_kmp);
+module_exit(exit_kmp);
diff --git a/mm/Kconfig b/mm/Kconfig
new file mode 100644
index 00000000000..cd379936cac
--- /dev/null
+++ b/mm/Kconfig
@@ -0,0 +1,91 @@
+config SELECT_MEMORY_MODEL
+ def_bool y
+ depends on EXPERIMENTAL || ARCH_SELECT_MEMORY_MODEL
+
+choice
+ prompt "Memory model"
+ depends on SELECT_MEMORY_MODEL
+ default DISCONTIGMEM_MANUAL if ARCH_DISCONTIGMEM_DEFAULT
+ default SPARSEMEM_MANUAL if ARCH_SPARSEMEM_DEFAULT
+ default FLATMEM_MANUAL
+
+config FLATMEM_MANUAL
+ bool "Flat Memory"
+ depends on !ARCH_DISCONTIGMEM_ENABLE || ARCH_FLATMEM_ENABLE
+ help
+ This option allows you to change some of the ways that
+ Linux manages its memory internally. Most users will
+ only have one option here: FLATMEM. This is normal
+ and a correct option.
+
+ Some users of more advanced features like NUMA and
+ memory hotplug may have different options here.
+ DISCONTIGMEM is an more mature, better tested system,
+ but is incompatible with memory hotplug and may suffer
+ decreased performance over SPARSEMEM. If unsure between
+ "Sparse Memory" and "Discontiguous Memory", choose
+ "Discontiguous Memory".
+
+ If unsure, choose this option (Flat Memory) over any other.
+
+config DISCONTIGMEM_MANUAL
+ bool "Discontigious Memory"
+ depends on ARCH_DISCONTIGMEM_ENABLE
+ help
+ This option provides enhanced support for discontiguous
+ memory systems, over FLATMEM. These systems have holes
+ in their physical address spaces, and this option provides
+ more efficient handling of these holes. However, the vast
+ majority of hardware has quite flat address spaces, and
+ can have degraded performance from extra overhead that
+ this option imposes.
+
+ Many NUMA configurations will have this as the only option.
+
+ If unsure, choose "Flat Memory" over this option.
+
+config SPARSEMEM_MANUAL
+ bool "Sparse Memory"
+ depends on ARCH_SPARSEMEM_ENABLE
+ help
+ This will be the only option for some systems, including
+ memory hotplug systems. This is normal.
+
+ For many other systems, this will be an alternative to
+ "Discontigious Memory". This option provides some potential
+ performance benefits, along with decreased code complexity,
+ but it is newer, and more experimental.
+
+ If unsure, choose "Discontiguous Memory" or "Flat Memory"
+ over this option.
+
+endchoice
+
+config DISCONTIGMEM
+ def_bool y
+ depends on (!SELECT_MEMORY_MODEL && ARCH_DISCONTIGMEM_ENABLE) || DISCONTIGMEM_MANUAL
+
+config SPARSEMEM
+ def_bool y
+ depends on SPARSEMEM_MANUAL
+
+config FLATMEM
+ def_bool y
+ depends on (!DISCONTIGMEM && !SPARSEMEM) || FLATMEM_MANUAL
+
+config FLAT_NODE_MEM_MAP
+ def_bool y
+ depends on !SPARSEMEM
+
+#
+# Both the NUMA code and DISCONTIGMEM use arrays of pg_data_t's
+# to represent different areas of memory. This variable allows
+# those dependencies to exist individually.
+#
+config NEED_MULTIPLE_NODES
+ def_bool y
+ depends on DISCONTIGMEM || NUMA
+
+config HAVE_MEMORY_PRESENT
+ def_bool y
+ depends on ARCH_HAVE_MEMORY_PRESENT || SPARSEMEM
diff --git a/mm/Makefile b/mm/Makefile
index 097408064f6..4cd69e3ce42 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -15,6 +15,8 @@ obj-y := bootmem.o filemap.o mempool.o oom_kill.o fadvise.o \
obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o thrash.o
obj-$(CONFIG_HUGETLBFS) += hugetlb.o
obj-$(CONFIG_NUMA) += mempolicy.o
+obj-$(CONFIG_SPARSEMEM) += sparse.o
obj-$(CONFIG_SHMEM) += shmem.o
obj-$(CONFIG_TINY_SHMEM) += tiny-shmem.o
+obj-$(CONFIG_FS_XIP) += filemap_xip.o
diff --git a/mm/bootmem.c b/mm/bootmem.c
index 260e703850d..c1330cc1978 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -33,6 +33,14 @@ EXPORT_SYMBOL(max_pfn); /* This is exported so
* dma_get_required_mask(), which uses
* it, can be an inline function */
+#ifdef CONFIG_CRASH_DUMP
+/*
+ * If we have booted due to a crash, max_pfn will be a very low value. We need
+ * to know the amount of memory that the previous kernel used.
+ */
+unsigned long saved_max_pfn;
+#endif
+
/* return the number of _pages_ that will be allocated for the boot bitmap */
unsigned long __init bootmem_bootmap_pages (unsigned long pages)
{
@@ -57,7 +65,7 @@ static unsigned long __init init_bootmem_core (pg_data_t *pgdat,
pgdat->pgdat_next = pgdat_list;
pgdat_list = pgdat;
- mapsize = (mapsize + (sizeof(long) - 1UL)) & ~(sizeof(long) - 1UL);
+ mapsize = ALIGN(mapsize, sizeof(long));
bdata->node_bootmem_map = phys_to_virt(mapstart << PAGE_SHIFT);
bdata->node_boot_start = (start << PAGE_SHIFT);
bdata->node_low_pfn = end;
@@ -178,7 +186,7 @@ __alloc_bootmem_core(struct bootmem_data *bdata, unsigned long size,
} else
preferred = 0;
- preferred = ((preferred + align - 1) & ~(align - 1)) >> PAGE_SHIFT;
+ preferred = ALIGN(preferred, align) >> PAGE_SHIFT;
preferred += offset;
areasize = (size+PAGE_SIZE-1)/PAGE_SIZE;
incr = align >> PAGE_SHIFT ? : 1;
@@ -219,7 +227,7 @@ found:
*/
if (align < PAGE_SIZE &&
bdata->last_offset && bdata->last_pos+1 == start) {
- offset = (bdata->last_offset+align-1) & ~(align-1);
+ offset = ALIGN(bdata->last_offset, align);
BUG_ON(offset > PAGE_SIZE);
remaining_size = PAGE_SIZE-offset;
if (size < remaining_size) {
@@ -256,6 +264,7 @@ found:
static unsigned long __init free_all_bootmem_core(pg_data_t *pgdat)
{
struct page *page;
+ unsigned long pfn;
bootmem_data_t *bdata = pgdat->bdata;
unsigned long i, count, total = 0;
unsigned long idx;
@@ -266,7 +275,7 @@ static unsigned long __init free_all_bootmem_core(pg_data_t *pgdat)
count = 0;
/* first extant page of the node */
- page = virt_to_page(phys_to_virt(bdata->node_boot_start));
+ pfn = bdata->node_boot_start >> PAGE_SHIFT;
idx = bdata->node_low_pfn - (bdata->node_boot_start >> PAGE_SHIFT);
map = bdata->node_bootmem_map;
/* Check physaddr is O(LOG2(BITS_PER_LONG)) page aligned */
@@ -275,9 +284,11 @@ static unsigned long __init free_all_bootmem_core(pg_data_t *pgdat)
gofast = 1;
for (i = 0; i < idx; ) {
unsigned long v = ~map[i / BITS_PER_LONG];
+
if (gofast && v == ~0UL) {
int j, order;
+ page = pfn_to_page(pfn);
count += BITS_PER_LONG;
__ClearPageReserved(page);
order = ffs(BITS_PER_LONG) - 1;
@@ -292,6 +303,8 @@ static unsigned long __init free_all_bootmem_core(pg_data_t *pgdat)
page += BITS_PER_LONG;
} else if (v) {
unsigned long m;
+
+ page = pfn_to_page(pfn);
for (m = 1; m && i < idx; m<<=1, page++, i++) {
if (v & m) {
count++;
@@ -302,8 +315,8 @@ static unsigned long __init free_all_bootmem_core(pg_data_t *pgdat)
}
} else {
i+=BITS_PER_LONG;
- page += BITS_PER_LONG;
}
+ pfn += BITS_PER_LONG;
}
total += count;
diff --git a/mm/fadvise.c b/mm/fadvise.c
index 57264d74b8b..5f19e87bc5a 100644
--- a/mm/fadvise.c
+++ b/mm/fadvise.c
@@ -43,6 +43,10 @@ asmlinkage long sys_fadvise64_64(int fd, loff_t offset, loff_t len, int advice)
goto out;
}
+ if (mapping->a_ops->get_xip_page)
+ /* no bad return value, but ignore advice */
+ goto out;
+
/* Careful about overflows. Len == 0 means "as much as possible" */
endbyte = offset + len;
if (!len || endbyte < len)
diff --git a/mm/filemap.c b/mm/filemap.c
index 47263ac3e4e..c11418dd94e 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -28,6 +28,7 @@
#include <linux/blkdev.h>
#include <linux/security.h>
#include <linux/syscalls.h>
+#include "filemap.h"
/*
* FIXME: remove all knowledge of the buffer layer from the core VM
*/
@@ -1004,7 +1005,7 @@ __generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
if (pos < size) {
retval = generic_file_direct_IO(READ, iocb,
iov, pos, nr_segs);
- if (retval >= 0 && !is_sync_kiocb(iocb))
+ if (retval > 0 && !is_sync_kiocb(iocb))
retval = -EIOCBQUEUED;
if (retval > 0)
*ppos = pos + retval;
@@ -1714,32 +1715,7 @@ int remove_suid(struct dentry *dentry)
}
EXPORT_SYMBOL(remove_suid);
-/*
- * Copy as much as we can into the page and return the number of bytes which
- * were sucessfully copied. If a fault is encountered then clear the page
- * out to (offset+bytes) and return the number of bytes which were copied.
- */
-static inline size_t
-filemap_copy_from_user(struct page *page, unsigned long offset,
- const char __user *buf, unsigned bytes)
-{
- char *kaddr;
- int left;
-
- kaddr = kmap_atomic(page, KM_USER0);
- left = __copy_from_user_inatomic(kaddr + offset, buf, bytes);
- kunmap_atomic(kaddr, KM_USER0);
-
- if (left != 0) {
- /* Do it the slow way */
- kaddr = kmap(page);
- left = __copy_from_user(kaddr + offset, buf, bytes);
- kunmap(page);
- }
- return bytes - left;
-}
-
-static size_t
+size_t
__filemap_copy_from_user_iovec(char *vaddr,
const struct iovec *iov, size_t base, size_t bytes)
{
@@ -1767,52 +1743,6 @@ __filemap_copy_from_user_iovec(char *vaddr,
}
/*
- * This has the same sideeffects and return value as filemap_copy_from_user().
- * The difference is that on a fault we need to memset the remainder of the
- * page (out to offset+bytes), to emulate filemap_copy_from_user()'s
- * single-segment behaviour.
- */
-static inline size_t
-filemap_copy_from_user_iovec(struct page *page, unsigned long offset,
- const struct iovec *iov, size_t base, size_t bytes)
-{
- char *kaddr;
- size_t copied;
-
- kaddr = kmap_atomic(page, KM_USER0);
- copied = __filemap_copy_from_user_iovec(kaddr + offset, iov,
- base, bytes);
- kunmap_atomic(kaddr, KM_USER0);
- if (copied != bytes) {
- kaddr = kmap(page);
- copied = __filemap_copy_from_user_iovec(kaddr + offset, iov,
- base, bytes);
- kunmap(page);
- }
- return copied;
-}
-
-static inline void
-filemap_set_next_iovec(const struct iovec **iovp, size_t *basep, size_t bytes)
-{
- const struct iovec *iov = *iovp;
- size_t base = *basep;
-
- while (bytes) {
- int copy = min(bytes, iov->iov_len - base);
-
- bytes -= copy;
- base += copy;
- if (iov->iov_len == base) {
- iov++;
- base = 0;
- }
- }
- *iovp = iov;
- *basep = base;
-}
-
-/*
* Performs necessary checks before doing a write
*
* Can adjust writing position aor amount of bytes to write.
@@ -1827,12 +1757,6 @@ inline int generic_write_checks(struct file *file, loff_t *pos, size_t *count, i
if (unlikely(*pos < 0))
return -EINVAL;
- if (unlikely(file->f_error)) {
- int err = file->f_error;
- file->f_error = 0;
- return err;
- }
-
if (!isblk) {
/* FIXME: this is for backwards compatibility with 2.4 */
if (file->f_flags & O_APPEND)
@@ -1927,8 +1851,11 @@ generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
* i_sem is held, which protects generic_osync_inode() from
* livelocking.
*/
- if (written >= 0 && file->f_flags & O_SYNC)
- generic_osync_inode(inode, mapping, OSYNC_METADATA);
+ if (written >= 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
+ int err = generic_osync_inode(inode, mapping, OSYNC_METADATA);
+ if (err < 0)
+ written = err;
+ }
if (written == count && !is_sync_kiocb(iocb))
written = -EIOCBQUEUED;
return written;
@@ -1968,6 +1895,7 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
do {
unsigned long index;
unsigned long offset;
+ unsigned long maxlen;
size_t copied;
offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
@@ -1982,7 +1910,10 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
* same page as we're writing to, without it being marked
* up-to-date.
*/
- fault_in_pages_readable(buf, bytes);
+ maxlen = cur_iov->iov_len - iov_base;
+ if (maxlen > bytes)
+ maxlen = bytes;
+ fault_in_pages_readable(buf, maxlen);
page = __grab_cache_page(mapping,index,&cached_page,&lru_pvec);
if (!page) {
@@ -2023,7 +1954,11 @@ generic_file_buffered_write(struct kiocb *iocb, const struct iovec *iov,
if (unlikely(nr_segs > 1)) {
filemap_set_next_iovec(&cur_iov,
&iov_base, status);
- buf = cur_iov->iov_base + iov_base;
+ if (count)
+ buf = cur_iov->iov_base +
+ iov_base;
+ } else {
+ iov_base += status;
}
}
}
diff --git a/mm/filemap.h b/mm/filemap.h
new file mode 100644
index 00000000000..13793ba0ce1
--- /dev/null
+++ b/mm/filemap.h
@@ -0,0 +1,94 @@
+/*
+ * linux/mm/filemap.h
+ *
+ * Copyright (C) 1994-1999 Linus Torvalds
+ */
+
+#ifndef __FILEMAP_H
+#define __FILEMAP_H
+
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/uio.h>
+#include <linux/config.h>
+#include <asm/uaccess.h>
+
+size_t
+__filemap_copy_from_user_iovec(char *vaddr,
+ const struct iovec *iov,
+ size_t base,
+ size_t bytes);
+
+/*
+ * Copy as much as we can into the page and return the number of bytes which
+ * were sucessfully copied. If a fault is encountered then clear the page
+ * out to (offset+bytes) and return the number of bytes which were copied.
+ */
+static inline size_t
+filemap_copy_from_user(struct page *page, unsigned long offset,
+ const char __user *buf, unsigned bytes)
+{
+ char *kaddr;
+ int left;
+
+ kaddr = kmap_atomic(page, KM_USER0);
+ left = __copy_from_user_inatomic(kaddr + offset, buf, bytes);
+ kunmap_atomic(kaddr, KM_USER0);
+
+ if (left != 0) {
+ /* Do it the slow way */
+ kaddr = kmap(page);
+ left = __copy_from_user(kaddr + offset, buf, bytes);
+ kunmap(page);
+ }
+ return bytes - left;
+}
+
+/*
+ * This has the same sideeffects and return value as filemap_copy_from_user().
+ * The difference is that on a fault we need to memset the remainder of the
+ * page (out to offset+bytes), to emulate filemap_copy_from_user()'s
+ * single-segment behaviour.
+ */
+static inline size_t
+filemap_copy_from_user_iovec(struct page *page, unsigned long offset,
+ const struct iovec *iov, size_t base, size_t bytes)
+{
+ char *kaddr;
+ size_t copied;
+
+ kaddr = kmap_atomic(page, KM_USER0);
+ copied = __filemap_copy_from_user_iovec(kaddr + offset, iov,
+ base, bytes);
+ kunmap_atomic(kaddr, KM_USER0);
+ if (copied != bytes) {
+ kaddr = kmap(page);
+ copied = __filemap_copy_from_user_iovec(kaddr + offset, iov,
+ base, bytes);
+ kunmap(page);
+ }
+ return copied;
+}
+
+static inline void
+filemap_set_next_iovec(const struct iovec **iovp, size_t *basep, size_t bytes)
+{
+ const struct iovec *iov = *iovp;
+ size_t base = *basep;
+
+ while (bytes) {
+ int copy = min(bytes, iov->iov_len - base);
+
+ bytes -= copy;
+ base += copy;
+ if (iov->iov_len == base) {
+ iov++;
+ base = 0;
+ }
+ }
+ *iovp = iov;
+ *basep = base;
+}
+#endif
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
new file mode 100644
index 00000000000..3b6e384b98a
--- /dev/null
+++ b/mm/filemap_xip.c
@@ -0,0 +1,447 @@
+/*
+ * linux/mm/filemap_xip.c
+ *
+ * Copyright (C) 2005 IBM Corporation
+ * Author: Carsten Otte <cotte@de.ibm.com>
+ *
+ * derived from linux/mm/filemap.c - Copyright (C) Linus Torvalds
+ *
+ */
+
+#include <linux/fs.h>
+#include <linux/pagemap.h>
+#include <linux/module.h>
+#include <linux/uio.h>
+#include <linux/rmap.h>
+#include <asm/tlbflush.h>
+#include "filemap.h"
+
+/*
+ * This is a file read routine for execute in place files, and uses
+ * the mapping->a_ops->get_xip_page() function for the actual low-level
+ * stuff.
+ *
+ * Note the struct file* is not used at all. It may be NULL.
+ */
+static void
+do_xip_mapping_read(struct address_space *mapping,
+ struct file_ra_state *_ra,
+ struct file *filp,
+ loff_t *ppos,
+ read_descriptor_t *desc,
+ read_actor_t actor)
+{
+ struct inode *inode = mapping->host;
+ unsigned long index, end_index, offset;
+ loff_t isize;
+
+ BUG_ON(!mapping->a_ops->get_xip_page);
+
+ index = *ppos >> PAGE_CACHE_SHIFT;
+ offset = *ppos & ~PAGE_CACHE_MASK;
+
+ isize = i_size_read(inode);
+ if (!isize)
+ goto out;
+
+ end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
+ for (;;) {
+ struct page *page;
+ unsigned long nr, ret;
+
+ /* nr is the maximum number of bytes to copy from this page */
+ nr = PAGE_CACHE_SIZE;
+ if (index >= end_index) {
+ if (index > end_index)
+ goto out;
+ nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
+ if (nr <= offset) {
+ goto out;
+ }
+ }
+ nr = nr - offset;
+
+ page = mapping->a_ops->get_xip_page(mapping,
+ index*(PAGE_SIZE/512), 0);
+ if (!page)
+ goto no_xip_page;
+ if (unlikely(IS_ERR(page))) {
+ if (PTR_ERR(page) == -ENODATA) {
+ /* sparse */
+ page = virt_to_page(empty_zero_page);
+ } else {
+ desc->error = PTR_ERR(page);
+ goto out;
+ }
+ } else
+ BUG_ON(!PageUptodate(page));
+
+ /* If users can be writing to this page using arbitrary
+ * virtual addresses, take care about potential aliasing
+ * before reading the page on the kernel side.
+ */
+ if (mapping_writably_mapped(mapping))
+ flush_dcache_page(page);
+
+ /*
+ * Ok, we have the page, and it's up-to-date, so
+ * now we can copy it to user space...
+ *
+ * The actor routine returns how many bytes were actually used..
+ * NOTE! This may not be the same as how much of a user buffer
+ * we filled up (we may be padding etc), so we can only update
+ * "pos" here (the actor routine has to update the user buffer
+ * pointers and the remaining count).
+ */
+ ret = actor(desc, page, offset, nr);
+ offset += ret;
+ index += offset >> PAGE_CACHE_SHIFT;
+ offset &= ~PAGE_CACHE_MASK;
+
+ if (ret == nr && desc->count)
+ continue;
+ goto out;
+
+no_xip_page:
+ /* Did not get the page. Report it */
+ desc->error = -EIO;
+ goto out;
+ }
+
+out:
+ *ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
+ if (filp)
+ file_accessed(filp);
+}
+
+ssize_t
+xip_file_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
+{
+ read_descriptor_t desc;
+
+ if (!access_ok(VERIFY_WRITE, buf, len))
+ return -EFAULT;
+
+ desc.written = 0;
+ desc.arg.buf = buf;
+ desc.count = len;
+ desc.error = 0;
+
+ do_xip_mapping_read(filp->f_mapping, &filp->f_ra, filp,
+ ppos, &desc, file_read_actor);
+
+ if (desc.written)
+ return desc.written;
+ else
+ return desc.error;
+}
+EXPORT_SYMBOL_GPL(xip_file_read);
+
+ssize_t
+xip_file_sendfile(struct file *in_file, loff_t *ppos,
+ size_t count, read_actor_t actor, void *target)
+{
+ read_descriptor_t desc;
+
+ if (!count)
+ return 0;
+
+ desc.written = 0;
+ desc.count = count;
+ desc.arg.data = target;
+ desc.error = 0;
+
+ do_xip_mapping_read(in_file->f_mapping, &in_file->f_ra, in_file,
+ ppos, &desc, actor);
+ if (desc.written)
+ return desc.written;
+ return desc.error;
+}
+EXPORT_SYMBOL_GPL(xip_file_sendfile);
+
+/*
+ * __xip_unmap is invoked from xip_unmap and
+ * xip_write
+ *
+ * This function walks all vmas of the address_space and unmaps the
+ * empty_zero_page when found at pgoff. Should it go in rmap.c?
+ */
+static void
+__xip_unmap (struct address_space * mapping,
+ unsigned long pgoff)
+{
+ struct vm_area_struct *vma;
+ struct mm_struct *mm;
+ struct prio_tree_iter iter;
+ unsigned long address;
+ pte_t *pte;
+ pte_t pteval;
+
+ spin_lock(&mapping->i_mmap_lock);
+ vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) {
+ mm = vma->vm_mm;
+ address = vma->vm_start +
+ ((pgoff - vma->vm_pgoff) << PAGE_SHIFT);
+ BUG_ON(address < vma->vm_start || address >= vma->vm_end);
+ /*
+ * We need the page_table_lock to protect us from page faults,
+ * munmap, fork, etc...
+ */
+ pte = page_check_address(virt_to_page(empty_zero_page), mm,
+ address);
+ if (!IS_ERR(pte)) {
+ /* Nuke the page table entry. */
+ flush_cache_page(vma, address, pte_pfn(pte));
+ pteval = ptep_clear_flush(vma, address, pte);
+ BUG_ON(pte_dirty(pteval));
+ pte_unmap(pte);
+ spin_unlock(&mm->page_table_lock);
+ }
+ }
+ spin_unlock(&mapping->i_mmap_lock);
+}
+
+/*
+ * xip_nopage() is invoked via the vma operations vector for a
+ * mapped memory region to read in file data during a page fault.
+ *
+ * This function is derived from filemap_nopage, but used for execute in place
+ */
+static struct page *
+xip_file_nopage(struct vm_area_struct * area,
+ unsigned long address,
+ int *type)
+{
+ struct file *file = area->vm_file;
+ struct address_space *mapping = file->f_mapping;
+ struct inode *inode = mapping->host;
+ struct page *page;
+ unsigned long size, pgoff, endoff;
+
+ pgoff = ((address - area->vm_start) >> PAGE_CACHE_SHIFT)
+ + area->vm_pgoff;
+ endoff = ((area->vm_end - area->vm_start) >> PAGE_CACHE_SHIFT)
+ + area->vm_pgoff;
+
+ size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+ if (pgoff >= size) {
+ return NULL;
+ }
+
+ page = mapping->a_ops->get_xip_page(mapping, pgoff*(PAGE_SIZE/512), 0);
+ if (!IS_ERR(page)) {
+ BUG_ON(!PageUptodate(page));
+ return page;
+ }
+ if (PTR_ERR(page) != -ENODATA)
+ return NULL;
+
+ /* sparse block */
+ if ((area->vm_flags & (VM_WRITE | VM_MAYWRITE)) &&
+ (area->vm_flags & (VM_SHARED| VM_MAYSHARE)) &&
+ (!(mapping->host->i_sb->s_flags & MS_RDONLY))) {
+ /* maybe shared writable, allocate new block */
+ page = mapping->a_ops->get_xip_page (mapping,
+ pgoff*(PAGE_SIZE/512), 1);
+ if (IS_ERR(page))
+ return NULL;
+ BUG_ON(!PageUptodate(page));
+ /* unmap page at pgoff from all other vmas */
+ __xip_unmap(mapping, pgoff);
+ } else {
+ /* not shared and writable, use empty_zero_page */
+ page = virt_to_page(empty_zero_page);
+ }
+
+ return page;
+}
+
+static struct vm_operations_struct xip_file_vm_ops = {
+ .nopage = xip_file_nopage,
+};
+
+int xip_file_mmap(struct file * file, struct vm_area_struct * vma)
+{
+ BUG_ON(!file->f_mapping->a_ops->get_xip_page);
+
+ file_accessed(file);
+ vma->vm_ops = &xip_file_vm_ops;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(xip_file_mmap);
+
+static ssize_t
+__xip_file_write(struct file *filp, const char __user *buf,
+ size_t count, loff_t pos, loff_t *ppos)
+{
+ struct address_space * mapping = filp->f_mapping;
+ struct address_space_operations *a_ops = mapping->a_ops;
+ struct inode *inode = mapping->host;
+ long status = 0;
+ struct page *page;
+ size_t bytes;
+ ssize_t written = 0;
+
+ BUG_ON(!mapping->a_ops->get_xip_page);
+
+ do {
+ unsigned long index;
+ unsigned long offset;
+ size_t copied;
+
+ offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
+ index = pos >> PAGE_CACHE_SHIFT;
+ bytes = PAGE_CACHE_SIZE - offset;
+ if (bytes > count)
+ bytes = count;
+
+ /*
+ * Bring in the user page that we will copy from _first_.
+ * Otherwise there's a nasty deadlock on copying from the
+ * same page as we're writing to, without it being marked
+ * up-to-date.
+ */
+ fault_in_pages_readable(buf, bytes);
+
+ page = a_ops->get_xip_page(mapping,
+ index*(PAGE_SIZE/512), 0);
+ if (IS_ERR(page) && (PTR_ERR(page) == -ENODATA)) {
+ /* we allocate a new page unmap it */
+ page = a_ops->get_xip_page(mapping,
+ index*(PAGE_SIZE/512), 1);
+ if (!IS_ERR(page))
+ /* unmap page at pgoff from all other vmas */
+ __xip_unmap(mapping, index);
+ }
+
+ if (IS_ERR(page)) {
+ status = PTR_ERR(page);
+ break;
+ }
+
+ BUG_ON(!PageUptodate(page));
+
+ copied = filemap_copy_from_user(page, offset, buf, bytes);
+ flush_dcache_page(page);
+ if (likely(copied > 0)) {
+ status = copied;
+
+ if (status >= 0) {
+ written += status;
+ count -= status;
+ pos += status;
+ buf += status;
+ }
+ }
+ if (unlikely(copied != bytes))
+ if (status >= 0)
+ status = -EFAULT;
+ if (status < 0)
+ break;
+ } while (count);
+ *ppos = pos;
+ /*
+ * No need to use i_size_read() here, the i_size
+ * cannot change under us because we hold i_sem.
+ */
+ if (pos > inode->i_size) {
+ i_size_write(inode, pos);
+ mark_inode_dirty(inode);
+ }
+
+ return written ? written : status;
+}
+
+ssize_t
+xip_file_write(struct file *filp, const char __user *buf, size_t len,
+ loff_t *ppos)
+{
+ struct address_space *mapping = filp->f_mapping;
+ struct inode *inode = mapping->host;
+ size_t count;
+ loff_t pos;
+ ssize_t ret;
+
+ down(&inode->i_sem);
+
+ if (!access_ok(VERIFY_READ, buf, len)) {
+ ret=-EFAULT;
+ goto out_up;
+ }
+
+ pos = *ppos;
+ count = len;
+
+ vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
+
+ /* We can write back this queue in page reclaim */
+ current->backing_dev_info = mapping->backing_dev_info;
+
+ ret = generic_write_checks(filp, &pos, &count, S_ISBLK(inode->i_mode));
+ if (ret)
+ goto out_backing;
+ if (count == 0)
+ goto out_backing;
+
+ ret = remove_suid(filp->f_dentry);
+ if (ret)
+ goto out_backing;
+
+ inode_update_time(inode, 1);
+
+ ret = __xip_file_write (filp, buf, count, pos, ppos);
+
+ out_backing:
+ current->backing_dev_info = NULL;
+ out_up:
+ up(&inode->i_sem);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(xip_file_write);
+
+/*
+ * truncate a page used for execute in place
+ * functionality is analog to block_truncate_page but does use get_xip_page
+ * to get the page instead of page cache
+ */
+int
+xip_truncate_page(struct address_space *mapping, loff_t from)
+{
+ pgoff_t index = from >> PAGE_CACHE_SHIFT;
+ unsigned offset = from & (PAGE_CACHE_SIZE-1);
+ unsigned blocksize;
+ unsigned length;
+ struct page *page;
+ void *kaddr;
+
+ BUG_ON(!mapping->a_ops->get_xip_page);
+
+ blocksize = 1 << mapping->host->i_blkbits;
+ length = offset & (blocksize - 1);
+
+ /* Block boundary? Nothing to do */
+ if (!length)
+ return 0;
+
+ length = blocksize - length;
+
+ page = mapping->a_ops->get_xip_page(mapping,
+ index*(PAGE_SIZE/512), 0);
+ if (!page)
+ return -ENOMEM;
+ if (unlikely(IS_ERR(page))) {
+ if (PTR_ERR(page) == -ENODATA)
+ /* Hole? No need to truncate */
+ return 0;
+ else
+ return PTR_ERR(page);
+ } else
+ BUG_ON(!PageUptodate(page));
+ kaddr = kmap_atomic(page, KM_USER0);
+ memset(kaddr + offset, 0, length);
+ kunmap_atomic(kaddr, KM_USER0);
+
+ flush_dcache_page(page);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(xip_truncate_page);
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 4eb5ae3fbe1..fbd1111ea11 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -7,10 +7,14 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mm.h>
-#include <linux/hugetlb.h>
#include <linux/sysctl.h>
#include <linux/highmem.h>
#include <linux/nodemask.h>
+#include <linux/pagemap.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#include <linux/hugetlb.h>
const unsigned long hugetlb_zero = 0, hugetlb_infinity = ~0UL;
static unsigned long nr_huge_pages, free_huge_pages;
@@ -249,6 +253,72 @@ struct vm_operations_struct hugetlb_vm_ops = {
.nopage = hugetlb_nopage,
};
+static pte_t make_huge_pte(struct vm_area_struct *vma, struct page *page)
+{
+ pte_t entry;
+
+ if (vma->vm_flags & VM_WRITE) {
+ entry =
+ pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
+ } else {
+ entry = pte_wrprotect(mk_pte(page, vma->vm_page_prot));
+ }
+ entry = pte_mkyoung(entry);
+ entry = pte_mkhuge(entry);
+
+ return entry;
+}
+
+int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
+ struct vm_area_struct *vma)
+{
+ pte_t *src_pte, *dst_pte, entry;
+ struct page *ptepage;
+ unsigned long addr = vma->vm_start;
+ unsigned long end = vma->vm_end;
+
+ while (addr < end) {
+ dst_pte = huge_pte_alloc(dst, addr);
+ if (!dst_pte)
+ goto nomem;
+ src_pte = huge_pte_offset(src, addr);
+ BUG_ON(!src_pte || pte_none(*src_pte)); /* prefaulted */
+ entry = *src_pte;
+ ptepage = pte_page(entry);
+ get_page(ptepage);
+ add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
+ set_huge_pte_at(dst, addr, dst_pte, entry);
+ addr += HPAGE_SIZE;
+ }
+ return 0;
+
+nomem:
+ return -ENOMEM;
+}
+
+void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end)
+{
+ struct mm_struct *mm = vma->vm_mm;
+ unsigned long address;
+ pte_t pte;
+ struct page *page;
+
+ WARN_ON(!is_vm_hugetlb_page(vma));
+ BUG_ON(start & ~HPAGE_MASK);
+ BUG_ON(end & ~HPAGE_MASK);
+
+ for (address = start; address < end; address += HPAGE_SIZE) {
+ pte = huge_ptep_get_and_clear(mm, address, huge_pte_offset(mm, address));
+ if (pte_none(pte))
+ continue;
+ page = pte_page(pte);
+ put_page(page);
+ }
+ add_mm_counter(mm, rss, -((end - start) >> PAGE_SHIFT));
+ flush_tlb_range(vma, start, end);
+}
+
void zap_hugepage_range(struct vm_area_struct *vma,
unsigned long start, unsigned long length)
{
@@ -258,3 +328,108 @@ void zap_hugepage_range(struct vm_area_struct *vma,
unmap_hugepage_range(vma, start, start + length);
spin_unlock(&mm->page_table_lock);
}
+
+int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
+{
+ struct mm_struct *mm = current->mm;
+ unsigned long addr;
+ int ret = 0;
+
+ WARN_ON(!is_vm_hugetlb_page(vma));
+ BUG_ON(vma->vm_start & ~HPAGE_MASK);
+ BUG_ON(vma->vm_end & ~HPAGE_MASK);
+
+ hugetlb_prefault_arch_hook(mm);
+
+ spin_lock(&mm->page_table_lock);
+ for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
+ unsigned long idx;
+ pte_t *pte = huge_pte_alloc(mm, addr);
+ struct page *page;
+
+ if (!pte) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ if (! pte_none(*pte))
+ hugetlb_clean_stale_pgtable(pte);
+
+ idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
+ + (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
+ page = find_get_page(mapping, idx);
+ if (!page) {
+ /* charge the fs quota first */
+ if (hugetlb_get_quota(mapping)) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ page = alloc_huge_page();
+ if (!page) {
+ hugetlb_put_quota(mapping);
+ ret = -ENOMEM;
+ goto out;
+ }
+ ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
+ if (! ret) {
+ unlock_page(page);
+ } else {
+ hugetlb_put_quota(mapping);
+ free_huge_page(page);
+ goto out;
+ }
+ }
+ add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE);
+ set_huge_pte_at(mm, addr, pte, make_huge_pte(vma, page));
+ }
+out:
+ spin_unlock(&mm->page_table_lock);
+ return ret;
+}
+
+int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
+ struct page **pages, struct vm_area_struct **vmas,
+ unsigned long *position, int *length, int i)
+{
+ unsigned long vpfn, vaddr = *position;
+ int remainder = *length;
+
+ BUG_ON(!is_vm_hugetlb_page(vma));
+
+ vpfn = vaddr/PAGE_SIZE;
+ while (vaddr < vma->vm_end && remainder) {
+
+ if (pages) {
+ pte_t *pte;
+ struct page *page;
+
+ /* Some archs (sparc64, sh*) have multiple
+ * pte_ts to each hugepage. We have to make
+ * sure we get the first, for the page
+ * indexing below to work. */
+ pte = huge_pte_offset(mm, vaddr & HPAGE_MASK);
+
+ /* hugetlb should be locked, and hence, prefaulted */
+ WARN_ON(!pte || pte_none(*pte));
+
+ page = &pte_page(*pte)[vpfn % (HPAGE_SIZE/PAGE_SIZE)];
+
+ WARN_ON(!PageCompound(page));
+
+ get_page(page);
+ pages[i] = page;
+ }
+
+ if (vmas)
+ vmas[i] = vma;
+
+ vaddr += PAGE_SIZE;
+ ++vpfn;
+ --remainder;
+ ++i;
+ }
+
+ *length = remainder;
+ *position = vaddr;
+
+ return i;
+}
diff --git a/mm/madvise.c b/mm/madvise.c
index 944b5e52d81..73180a22877 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -8,17 +8,47 @@
#include <linux/mman.h>
#include <linux/pagemap.h>
#include <linux/syscalls.h>
+#include <linux/mempolicy.h>
#include <linux/hugetlb.h>
/*
* We can potentially split a vm area into separate
* areas, each area with its own behavior.
*/
-static long madvise_behavior(struct vm_area_struct * vma, unsigned long start,
- unsigned long end, int behavior)
+static long madvise_behavior(struct vm_area_struct * vma,
+ struct vm_area_struct **prev,
+ unsigned long start, unsigned long end, int behavior)
{
struct mm_struct * mm = vma->vm_mm;
int error = 0;
+ pgoff_t pgoff;
+ int new_flags = vma->vm_flags & ~VM_READHINTMASK;
+
+ switch (behavior) {
+ case MADV_SEQUENTIAL:
+ new_flags |= VM_SEQ_READ;
+ break;
+ case MADV_RANDOM:
+ new_flags |= VM_RAND_READ;
+ break;
+ default:
+ break;
+ }
+
+ if (new_flags == vma->vm_flags) {
+ *prev = vma;
+ goto success;
+ }
+
+ pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
+ *prev = vma_merge(mm, *prev, start, end, new_flags, vma->anon_vma,
+ vma->vm_file, pgoff, vma_policy(vma));
+ if (*prev) {
+ vma = *prev;
+ goto success;
+ }
+
+ *prev = vma;
if (start != vma->vm_start) {
error = split_vma(mm, vma, start, 1);
@@ -35,22 +65,12 @@ static long madvise_behavior(struct vm_area_struct * vma, unsigned long start,
/*
* vm_flags is protected by the mmap_sem held in write mode.
*/
- VM_ClearReadHint(vma);
-
- switch (behavior) {
- case MADV_SEQUENTIAL:
- vma->vm_flags |= VM_SEQ_READ;
- break;
- case MADV_RANDOM:
- vma->vm_flags |= VM_RAND_READ;
- break;
- default:
- break;
- }
+ vma->vm_flags = new_flags;
out:
if (error == -ENOMEM)
error = -EAGAIN;
+success:
return error;
}
@@ -58,6 +78,7 @@ out:
* Schedule all required I/O operations. Do not wait for completion.
*/
static long madvise_willneed(struct vm_area_struct * vma,
+ struct vm_area_struct ** prev,
unsigned long start, unsigned long end)
{
struct file *file = vma->vm_file;
@@ -65,6 +86,12 @@ static long madvise_willneed(struct vm_area_struct * vma,
if (!file)
return -EBADF;
+ if (file->f_mapping->a_ops->get_xip_page) {
+ /* no bad return value, but ignore advice */
+ return 0;
+ }
+
+ *prev = vma;
start = ((start - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
if (end > vma->vm_end)
end = vma->vm_end;
@@ -95,8 +122,10 @@ static long madvise_willneed(struct vm_area_struct * vma,
* dirty pages is already available as msync(MS_INVALIDATE).
*/
static long madvise_dontneed(struct vm_area_struct * vma,
+ struct vm_area_struct ** prev,
unsigned long start, unsigned long end)
{
+ *prev = vma;
if ((vma->vm_flags & VM_LOCKED) || is_vm_hugetlb_page(vma))
return -EINVAL;
@@ -111,8 +140,8 @@ static long madvise_dontneed(struct vm_area_struct * vma,
return 0;
}
-static long madvise_vma(struct vm_area_struct * vma, unsigned long start,
- unsigned long end, int behavior)
+static long madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev,
+ unsigned long start, unsigned long end, int behavior)
{
long error = -EBADF;
@@ -120,15 +149,15 @@ static long madvise_vma(struct vm_area_struct * vma, unsigned long start,
case MADV_NORMAL:
case MADV_SEQUENTIAL:
case MADV_RANDOM:
- error = madvise_behavior(vma, start, end, behavior);
+ error = madvise_behavior(vma, prev, start, end, behavior);
break;
case MADV_WILLNEED:
- error = madvise_willneed(vma, start, end);
+ error = madvise_willneed(vma, prev, start, end);
break;
case MADV_DONTNEED:
- error = madvise_dontneed(vma, start, end);
+ error = madvise_dontneed(vma, prev, start, end);
break;
default:
@@ -175,8 +204,8 @@ static long madvise_vma(struct vm_area_struct * vma, unsigned long start,
*/
asmlinkage long sys_madvise(unsigned long start, size_t len_in, int behavior)
{
- unsigned long end;
- struct vm_area_struct * vma;
+ unsigned long end, tmp;
+ struct vm_area_struct * vma, *prev;
int unmapped_error = 0;
int error = -EINVAL;
size_t len;
@@ -202,40 +231,42 @@ asmlinkage long sys_madvise(unsigned long start, size_t len_in, int behavior)
/*
* If the interval [start,end) covers some unmapped address
* ranges, just ignore them, but return -ENOMEM at the end.
+ * - different from the way of handling in mlock etc.
*/
- vma = find_vma(current->mm, start);
+ vma = find_vma_prev(current->mm, start, &prev);
+ if (!vma && prev)
+ vma = prev->vm_next;
for (;;) {
/* Still start < end. */
error = -ENOMEM;
if (!vma)
goto out;
- /* Here start < vma->vm_end. */
+ /* Here start < (end|vma->vm_end). */
if (start < vma->vm_start) {
unmapped_error = -ENOMEM;
start = vma->vm_start;
+ if (start >= end)
+ goto out;
}
- /* Here vma->vm_start <= start < vma->vm_end. */
- if (end <= vma->vm_end) {
- if (start < end) {
- error = madvise_vma(vma, start, end,
- behavior);
- if (error)
- goto out;
- }
- error = unmapped_error;
- goto out;
- }
+ /* Here vma->vm_start <= start < (end|vma->vm_end) */
+ tmp = vma->vm_end;
+ if (end < tmp)
+ tmp = end;
- /* Here vma->vm_start <= start < vma->vm_end < end. */
- error = madvise_vma(vma, start, vma->vm_end, behavior);
+ /* Here vma->vm_start <= start < tmp <= (end|vma->vm_end). */
+ error = madvise_vma(vma, &prev, start, tmp, behavior);
if (error)
goto out;
- start = vma->vm_end;
- vma = vma->vm_next;
+ start = tmp;
+ if (start < prev->vm_end)
+ start = prev->vm_end;
+ error = unmapped_error;
+ if (start >= end)
+ goto out;
+ vma = prev->vm_next;
}
-
out:
up_write(&current->mm->mmap_sem);
return error;
diff --git a/mm/memory.c b/mm/memory.c
index 6bad4c4064e..beabdefa625 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -58,7 +58,7 @@
#include <linux/swapops.h>
#include <linux/elf.h>
-#ifndef CONFIG_DISCONTIGMEM
+#ifndef CONFIG_NEED_MULTIPLE_NODES
/* use the per-pgdat data instead for discontigmem - mbligh */
unsigned long max_mapnr;
struct page *mem_map;
@@ -840,23 +840,8 @@ check_user_page_readable(struct mm_struct *mm, unsigned long address)
{
return __follow_page(mm, address, /*read*/1, /*write*/0) != NULL;
}
-
EXPORT_SYMBOL(check_user_page_readable);
-/*
- * Given a physical address, is there a useful struct page pointing to
- * it? This may become more complex in the future if we start dealing
- * with IO-aperture pages for direct-IO.
- */
-
-static inline struct page *get_page_map(struct page *page)
-{
- if (!pfn_valid(page_to_pfn(page)))
- return NULL;
- return page;
-}
-
-
static inline int
untouched_anonymous_page(struct mm_struct* mm, struct vm_area_struct *vma,
unsigned long address)
@@ -887,7 +872,6 @@ untouched_anonymous_page(struct mm_struct* mm, struct vm_area_struct *vma,
return 0;
}
-
int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
unsigned long start, int len, int write, int force,
struct page **pages, struct vm_area_struct **vmas)
@@ -951,21 +935,21 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
}
spin_lock(&mm->page_table_lock);
do {
- struct page *map;
+ struct page *page;
int lookup_write = write;
cond_resched_lock(&mm->page_table_lock);
- while (!(map = follow_page(mm, start, lookup_write))) {
+ while (!(page = follow_page(mm, start, lookup_write))) {
/*
* Shortcut for anonymous pages. We don't want
* to force the creation of pages tables for
- * insanly big anonymously mapped areas that
+ * insanely big anonymously mapped areas that
* nobody touched so far. This is important
* for doing a core dump for these mappings.
*/
if (!lookup_write &&
untouched_anonymous_page(mm,vma,start)) {
- map = ZERO_PAGE(start);
+ page = ZERO_PAGE(start);
break;
}
spin_unlock(&mm->page_table_lock);
@@ -994,30 +978,21 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
spin_lock(&mm->page_table_lock);
}
if (pages) {
- pages[i] = get_page_map(map);
- if (!pages[i]) {
- spin_unlock(&mm->page_table_lock);
- while (i--)
- page_cache_release(pages[i]);
- i = -EFAULT;
- goto out;
- }
- flush_dcache_page(pages[i]);
- if (!PageReserved(pages[i]))
- page_cache_get(pages[i]);
+ pages[i] = page;
+ flush_dcache_page(page);
+ if (!PageReserved(page))
+ page_cache_get(page);
}
if (vmas)
vmas[i] = vma;
i++;
start += PAGE_SIZE;
len--;
- } while(len && start < vma->vm_end);
+ } while (len && start < vma->vm_end);
spin_unlock(&mm->page_table_lock);
- } while(len);
-out:
+ } while (len);
return i;
}
-
EXPORT_SYMBOL(get_user_pages);
static int zeromap_pte_range(struct mm_struct *mm, pmd_t *pmd,
@@ -1164,7 +1139,7 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
{
pgd_t *pgd;
unsigned long next;
- unsigned long end = addr + size;
+ unsigned long end = addr + PAGE_ALIGN(size);
struct mm_struct *mm = vma->vm_mm;
int err;
@@ -1264,7 +1239,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
}
old_page = pfn_to_page(pfn);
- if (!TestSetPageLocked(old_page)) {
+ if (PageAnon(old_page) && !TestSetPageLocked(old_page)) {
int reuse = can_share_swap_page(old_page);
unlock_page(old_page);
if (reuse) {
@@ -1483,7 +1458,7 @@ restart:
* unmap_mapping_range - unmap the portion of all mmaps
* in the specified address_space corresponding to the specified
* page range in the underlying file.
- * @address_space: the address space containing mmaps to be unmapped.
+ * @mapping: the address space containing mmaps to be unmapped.
* @holebegin: byte in first page to unmap, relative to the start of
* the underlying file. This will be rounded down to a PAGE_SIZE
* boundary. Note that this is different from vmtruncate(), which
@@ -1701,19 +1676,16 @@ static int do_swap_page(struct mm_struct * mm,
spin_lock(&mm->page_table_lock);
page_table = pte_offset_map(pmd, address);
if (unlikely(!pte_same(*page_table, orig_pte))) {
- pte_unmap(page_table);
- spin_unlock(&mm->page_table_lock);
- unlock_page(page);
- page_cache_release(page);
ret = VM_FAULT_MINOR;
- goto out;
+ goto out_nomap;
+ }
+
+ if (unlikely(!PageUptodate(page))) {
+ ret = VM_FAULT_SIGBUS;
+ goto out_nomap;
}
/* The page isn't present yet, go ahead with the fault. */
-
- swap_free(entry);
- if (vm_swap_full())
- remove_exclusive_swap_page(page);
inc_mm_counter(mm, rss);
pte = mk_pte(page, vma->vm_page_prot);
@@ -1721,12 +1693,16 @@ static int do_swap_page(struct mm_struct * mm,
pte = maybe_mkwrite(pte_mkdirty(pte), vma);
write_access = 0;
}
- unlock_page(page);
flush_icache_page(vma, page);
set_pte_at(mm, address, page_table, pte);
page_add_anon_rmap(page, vma, address);
+ swap_free(entry);
+ if (vm_swap_full())
+ remove_exclusive_swap_page(page);
+ unlock_page(page);
+
if (write_access) {
if (do_wp_page(mm, vma, address,
page_table, pmd, pte) == VM_FAULT_OOM)
@@ -1741,6 +1717,12 @@ static int do_swap_page(struct mm_struct * mm,
spin_unlock(&mm->page_table_lock);
out:
return ret;
+out_nomap:
+ pte_unmap(page_table);
+ spin_unlock(&mm->page_table_lock);
+ unlock_page(page);
+ page_cache_release(page);
+ goto out;
}
/*
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 08c41da429c..cb41c31e7c8 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -238,46 +238,80 @@ static struct mempolicy *mpol_new(int mode, unsigned long *nodes)
}
/* Ensure all existing pages follow the policy. */
-static int
-verify_pages(struct mm_struct *mm,
- unsigned long addr, unsigned long end, unsigned long *nodes)
+static int check_pte_range(struct mm_struct *mm, pmd_t *pmd,
+ unsigned long addr, unsigned long end, unsigned long *nodes)
{
- while (addr < end) {
- struct page *p;
- pte_t *pte;
- pmd_t *pmd;
- pud_t *pud;
- pgd_t *pgd;
- pgd = pgd_offset(mm, addr);
- if (pgd_none(*pgd)) {
- unsigned long next = (addr + PGDIR_SIZE) & PGDIR_MASK;
- if (next > addr)
- break;
- addr = next;
+ pte_t *orig_pte;
+ pte_t *pte;
+
+ spin_lock(&mm->page_table_lock);
+ orig_pte = pte = pte_offset_map(pmd, addr);
+ do {
+ unsigned long pfn;
+ unsigned int nid;
+
+ if (!pte_present(*pte))
continue;
- }
- pud = pud_offset(pgd, addr);
- if (pud_none(*pud)) {
- addr = (addr + PUD_SIZE) & PUD_MASK;
+ pfn = pte_pfn(*pte);
+ if (!pfn_valid(pfn))
continue;
- }
- pmd = pmd_offset(pud, addr);
- if (pmd_none(*pmd)) {
- addr = (addr + PMD_SIZE) & PMD_MASK;
+ nid = pfn_to_nid(pfn);
+ if (!test_bit(nid, nodes))
+ break;
+ } while (pte++, addr += PAGE_SIZE, addr != end);
+ pte_unmap(orig_pte);
+ spin_unlock(&mm->page_table_lock);
+ return addr != end;
+}
+
+static inline int check_pmd_range(struct mm_struct *mm, pud_t *pud,
+ unsigned long addr, unsigned long end, unsigned long *nodes)
+{
+ pmd_t *pmd;
+ unsigned long next;
+
+ pmd = pmd_offset(pud, addr);
+ do {
+ next = pmd_addr_end(addr, end);
+ if (pmd_none_or_clear_bad(pmd))
continue;
- }
- p = NULL;
- pte = pte_offset_map(pmd, addr);
- if (pte_present(*pte))
- p = pte_page(*pte);
- pte_unmap(pte);
- if (p) {
- unsigned nid = page_to_nid(p);
- if (!test_bit(nid, nodes))
- return -EIO;
- }
- addr += PAGE_SIZE;
- }
+ if (check_pte_range(mm, pmd, addr, next, nodes))
+ return -EIO;
+ } while (pmd++, addr = next, addr != end);
+ return 0;
+}
+
+static inline int check_pud_range(struct mm_struct *mm, pgd_t *pgd,
+ unsigned long addr, unsigned long end, unsigned long *nodes)
+{
+ pud_t *pud;
+ unsigned long next;
+
+ pud = pud_offset(pgd, addr);
+ do {
+ next = pud_addr_end(addr, end);
+ if (pud_none_or_clear_bad(pud))
+ continue;
+ if (check_pmd_range(mm, pud, addr, next, nodes))
+ return -EIO;
+ } while (pud++, addr = next, addr != end);
+ return 0;
+}
+
+static inline int check_pgd_range(struct mm_struct *mm,
+ unsigned long addr, unsigned long end, unsigned long *nodes)
+{
+ pgd_t *pgd;
+ unsigned long next;
+
+ pgd = pgd_offset(mm, addr);
+ do {
+ next = pgd_addr_end(addr, end);
+ if (pgd_none_or_clear_bad(pgd))
+ continue;
+ if (check_pud_range(mm, pgd, addr, next, nodes))
+ return -EIO;
+ } while (pgd++, addr = next, addr != end);
return 0;
}
@@ -299,7 +333,7 @@ check_range(struct mm_struct *mm, unsigned long start, unsigned long end,
if (prev && prev->vm_end < vma->vm_start)
return ERR_PTR(-EFAULT);
if ((flags & MPOL_MF_STRICT) && !is_vm_hugetlb_page(vma)) {
- err = verify_pages(vma->vm_mm,
+ err = check_pgd_range(vma->vm_mm,
vma->vm_start, vma->vm_end, nodes);
if (err) {
first = ERR_PTR(err);
@@ -721,7 +755,7 @@ static struct page *alloc_page_interleave(unsigned int __nocast gfp, unsigned or
zl = NODE_DATA(nid)->node_zonelists + (gfp & GFP_ZONEMASK);
page = __alloc_pages(gfp, order, zl);
if (page && page_zone(page) == zl->zones[0]) {
- zl->zones[0]->pageset[get_cpu()].interleave_hit++;
+ zone_pcp(zl->zones[0],get_cpu())->interleave_hit++;
put_cpu();
}
return page;
diff --git a/mm/mempool.c b/mm/mempool.c
index c9f3d462042..9a72f7d918f 100644
--- a/mm/mempool.c
+++ b/mm/mempool.c
@@ -51,16 +51,23 @@ static void free_pool(mempool_t *pool)
* functions might sleep - as long as the mempool_alloc function is not called
* from IRQ contexts.
*/
-mempool_t * mempool_create(int min_nr, mempool_alloc_t *alloc_fn,
+mempool_t *mempool_create(int min_nr, mempool_alloc_t *alloc_fn,
mempool_free_t *free_fn, void *pool_data)
{
- mempool_t *pool;
+ return mempool_create_node(min_nr,alloc_fn,free_fn, pool_data,-1);
+}
+EXPORT_SYMBOL(mempool_create);
- pool = kmalloc(sizeof(*pool), GFP_KERNEL);
+mempool_t *mempool_create_node(int min_nr, mempool_alloc_t *alloc_fn,
+ mempool_free_t *free_fn, void *pool_data, int node_id)
+{
+ mempool_t *pool;
+ pool = kmalloc_node(sizeof(*pool), GFP_KERNEL, node_id);
if (!pool)
return NULL;
memset(pool, 0, sizeof(*pool));
- pool->elements = kmalloc(min_nr * sizeof(void *), GFP_KERNEL);
+ pool->elements = kmalloc_node(min_nr * sizeof(void *),
+ GFP_KERNEL, node_id);
if (!pool->elements) {
kfree(pool);
return NULL;
@@ -87,7 +94,7 @@ mempool_t * mempool_create(int min_nr, mempool_alloc_t *alloc_fn,
}
return pool;
}
-EXPORT_SYMBOL(mempool_create);
+EXPORT_SYMBOL(mempool_create_node);
/**
* mempool_resize - resize an existing memory pool
@@ -197,7 +204,7 @@ void * mempool_alloc(mempool_t *pool, unsigned int __nocast gfp_mask)
{
void *element;
unsigned long flags;
- DEFINE_WAIT(wait);
+ wait_queue_t wait;
int gfp_temp;
might_sleep_if(gfp_mask & __GFP_WAIT);
@@ -228,6 +235,7 @@ repeat_alloc:
/* Now start performing page reclaim */
gfp_temp = gfp_mask;
+ init_wait(&wait);
prepare_to_wait(&pool->wait, &wait, TASK_UNINTERRUPTIBLE);
smp_mb();
if (!pool->curr_nr)
diff --git a/mm/mmap.c b/mm/mmap.c
index 01f9793591f..da3fa90a0aa 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1175,7 +1175,12 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
(!vma || addr + len <= vma->vm_start))
return addr;
}
- start_addr = addr = mm->free_area_cache;
+ if (len > mm->cached_hole_size) {
+ start_addr = addr = mm->free_area_cache;
+ } else {
+ start_addr = addr = TASK_UNMAPPED_BASE;
+ mm->cached_hole_size = 0;
+ }
full_search:
for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
@@ -1186,7 +1191,9 @@ full_search:
* some holes.
*/
if (start_addr != TASK_UNMAPPED_BASE) {
- start_addr = addr = TASK_UNMAPPED_BASE;
+ addr = TASK_UNMAPPED_BASE;
+ start_addr = addr;
+ mm->cached_hole_size = 0;
goto full_search;
}
return -ENOMEM;
@@ -1198,19 +1205,22 @@ full_search:
mm->free_area_cache = addr + len;
return addr;
}
+ if (addr + mm->cached_hole_size < vma->vm_start)
+ mm->cached_hole_size = vma->vm_start - addr;
addr = vma->vm_end;
}
}
#endif
-void arch_unmap_area(struct vm_area_struct *area)
+void arch_unmap_area(struct mm_struct *mm, unsigned long addr)
{
/*
* Is this a new hole at the lowest possible address?
*/
- if (area->vm_start >= TASK_UNMAPPED_BASE &&
- area->vm_start < area->vm_mm->free_area_cache)
- area->vm_mm->free_area_cache = area->vm_start;
+ if (addr >= TASK_UNMAPPED_BASE && addr < mm->free_area_cache) {
+ mm->free_area_cache = addr;
+ mm->cached_hole_size = ~0UL;
+ }
}
/*
@@ -1240,17 +1250,26 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
return addr;
}
+ /* check if free_area_cache is useful for us */
+ if (len <= mm->cached_hole_size) {
+ mm->cached_hole_size = 0;
+ mm->free_area_cache = mm->mmap_base;
+ }
+
/* either no address requested or can't fit in requested address hole */
addr = mm->free_area_cache;
/* make sure it can fit in the remaining address space */
- if (addr >= len) {
+ if (addr > len) {
vma = find_vma(mm, addr-len);
if (!vma || addr <= vma->vm_start)
/* remember the address as a hint for next time */
return (mm->free_area_cache = addr-len);
}
+ if (mm->mmap_base < len)
+ goto bottomup;
+
addr = mm->mmap_base-len;
do {
@@ -1264,75 +1283,85 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
/* remember the address as a hint for next time */
return (mm->free_area_cache = addr);
+ /* remember the largest hole we saw so far */
+ if (addr + mm->cached_hole_size < vma->vm_start)
+ mm->cached_hole_size = vma->vm_start - addr;
+
/* try just below the current vma->vm_start */
addr = vma->vm_start-len;
- } while (len <= vma->vm_start);
+ } while (len < vma->vm_start);
+bottomup:
/*
* A failed mmap() very likely causes application failure,
* so fall back to the bottom-up function here. This scenario
* can happen with large stack limits and large mmap()
* allocations.
*/
- mm->free_area_cache = TASK_UNMAPPED_BASE;
+ mm->cached_hole_size = ~0UL;
+ mm->free_area_cache = TASK_UNMAPPED_BASE;
addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
/*
* Restore the topdown base:
*/
mm->free_area_cache = mm->mmap_base;
+ mm->cached_hole_size = ~0UL;
return addr;
}
#endif
-void arch_unmap_area_topdown(struct vm_area_struct *area)
+void arch_unmap_area_topdown(struct mm_struct *mm, unsigned long addr)
{
/*
* Is this a new hole at the highest possible address?
*/
- if (area->vm_end > area->vm_mm->free_area_cache)
- area->vm_mm->free_area_cache = area->vm_end;
+ if (addr > mm->free_area_cache)
+ mm->free_area_cache = addr;
/* dont allow allocations above current base */
- if (area->vm_mm->free_area_cache > area->vm_mm->mmap_base)
- area->vm_mm->free_area_cache = area->vm_mm->mmap_base;
+ if (mm->free_area_cache > mm->mmap_base)
+ mm->free_area_cache = mm->mmap_base;
}
unsigned long
get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
unsigned long pgoff, unsigned long flags)
{
- if (flags & MAP_FIXED) {
- unsigned long ret;
+ unsigned long ret;
- if (addr > TASK_SIZE - len)
- return -ENOMEM;
- if (addr & ~PAGE_MASK)
- return -EINVAL;
- if (file && is_file_hugepages(file)) {
- /*
- * Check if the given range is hugepage aligned, and
- * can be made suitable for hugepages.
- */
- ret = prepare_hugepage_range(addr, len);
- } else {
- /*
- * Ensure that a normal request is not falling in a
- * reserved hugepage range. For some archs like IA-64,
- * there is a separate region for hugepages.
- */
- ret = is_hugepage_only_range(current->mm, addr, len);
- }
- if (ret)
- return -EINVAL;
- return addr;
- }
+ if (!(flags & MAP_FIXED)) {
+ unsigned long (*get_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
- if (file && file->f_op && file->f_op->get_unmapped_area)
- return file->f_op->get_unmapped_area(file, addr, len,
- pgoff, flags);
+ get_area = current->mm->get_unmapped_area;
+ if (file && file->f_op && file->f_op->get_unmapped_area)
+ get_area = file->f_op->get_unmapped_area;
+ addr = get_area(file, addr, len, pgoff, flags);
+ if (IS_ERR_VALUE(addr))
+ return addr;
+ }
- return current->mm->get_unmapped_area(file, addr, len, pgoff, flags);
+ if (addr > TASK_SIZE - len)
+ return -ENOMEM;
+ if (addr & ~PAGE_MASK)
+ return -EINVAL;
+ if (file && is_file_hugepages(file)) {
+ /*
+ * Check if the given range is hugepage aligned, and
+ * can be made suitable for hugepages.
+ */
+ ret = prepare_hugepage_range(addr, len);
+ } else {
+ /*
+ * Ensure that a normal request is not falling in a
+ * reserved hugepage range. For some archs like IA-64,
+ * there is a separate region for hugepages.
+ */
+ ret = is_hugepage_only_range(current->mm, addr, len);
+ }
+ if (ret)
+ return -EINVAL;
+ return addr;
}
EXPORT_SYMBOL(get_unmapped_area);
@@ -1592,7 +1621,6 @@ static void unmap_vma(struct mm_struct *mm, struct vm_area_struct *area)
if (area->vm_flags & VM_LOCKED)
area->vm_mm->locked_vm -= len >> PAGE_SHIFT;
vm_stat_unaccount(area);
- area->vm_mm->unmap_area(area);
remove_vm_struct(area);
}
@@ -1646,6 +1674,7 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma,
{
struct vm_area_struct **insertion_point;
struct vm_area_struct *tail_vma = NULL;
+ unsigned long addr;
insertion_point = (prev ? &prev->vm_next : &mm->mmap);
do {
@@ -1656,6 +1685,11 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma,
} while (vma && vma->vm_start < end);
*insertion_point = vma;
tail_vma->vm_next = NULL;
+ if (mm->unmap_area == arch_unmap_area)
+ addr = prev ? prev->vm_end : mm->mmap_base;
+ else
+ addr = vma ? vma->vm_start : mm->mmap_base;
+ mm->unmap_area(mm, addr);
mm->mmap_cache = NULL; /* Kill the cache. */
}
diff --git a/mm/mremap.c b/mm/mremap.c
index 0dd7ace94e5..ec7238a78f3 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -224,6 +224,12 @@ static unsigned long move_vma(struct vm_area_struct *vma,
split = 1;
}
+ /*
+ * if we failed to move page tables we still do total_vm increment
+ * since do_munmap() will decrement it by old_len == new_len
+ */
+ mm->total_vm += new_len >> PAGE_SHIFT;
+
if (do_munmap(mm, old_addr, old_len) < 0) {
/* OOM: unable to split vma, just get accounts right */
vm_unacct_memory(excess >> PAGE_SHIFT);
@@ -237,7 +243,6 @@ static unsigned long move_vma(struct vm_area_struct *vma,
vma->vm_next->vm_flags |= VM_ACCOUNT;
}
- mm->total_vm += new_len >> PAGE_SHIFT;
__vm_stat_account(mm, vma->vm_flags, vma->vm_file, new_len>>PAGE_SHIFT);
if (vm_flags & VM_LOCKED) {
mm->locked_vm += new_len >> PAGE_SHIFT;
diff --git a/mm/msync.c b/mm/msync.c
index 090f426bca7..d0f5a1bce7c 100644
--- a/mm/msync.c
+++ b/mm/msync.c
@@ -34,6 +34,8 @@ static void sync_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
if (!pte_present(*pte))
continue;
+ if (!pte_maybe_dirty(*pte))
+ continue;
pfn = pte_pfn(*pte);
if (!pfn_valid(pfn))
continue;
diff --git a/mm/nommu.c b/mm/nommu.c
index b293ec1cc4e..ce74452c02d 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -150,7 +150,8 @@ void vfree(void *addr)
kfree(addr);
}
-void *__vmalloc(unsigned long size, int gfp_mask, pgprot_t prot)
+void *__vmalloc(unsigned long size, unsigned int __nocast gfp_mask,
+ pgprot_t prot)
{
/*
* kmalloc doesn't like __GFP_HIGHMEM for some reason
@@ -1066,7 +1067,7 @@ unsigned long arch_get_unmapped_area(struct file *file, unsigned long addr,
return -ENOMEM;
}
-void arch_unmap_area(struct vm_area_struct *area)
+void arch_unmap_area(struct mm_struct *mm, unsigned long addr)
{
}
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 4bbb1cb1049..59666d905f1 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -258,6 +258,10 @@ void out_of_memory(unsigned int __nocast gfp_mask)
struct mm_struct *mm = NULL;
task_t * p;
+ printk("oom-killer: gfp_mask=0x%x\n", gfp_mask);
+ /* print memory stats */
+ show_mem();
+
read_lock(&tasklist_lock);
retry:
p = select_bad_process();
@@ -268,12 +272,9 @@ retry:
/* Found nothing?!?! Either we hang forever, or we panic. */
if (!p) {
read_unlock(&tasklist_lock);
- show_free_areas();
panic("Out of memory and no killable processes...\n");
}
- printk("oom-killer: gfp_mask=0x%x\n", gfp_mask);
- show_free_areas();
mm = oom_kill_process(p);
if (!mm)
goto retry;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index b1061b1962f..7ee675ad101 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -68,7 +68,7 @@ EXPORT_SYMBOL(nr_swap_pages);
* Used by page_zone() to look up the address of the struct zone whose
* id is encoded in the upper bits of page->flags
*/
-struct zone *zone_table[1 << (ZONES_SHIFT + NODES_SHIFT)];
+struct zone *zone_table[1 << ZONETABLE_SHIFT];
EXPORT_SYMBOL(zone_table);
static char *zone_names[MAX_NR_ZONES] = { "DMA", "Normal", "HighMem" };
@@ -105,11 +105,13 @@ static void bad_page(const char *function, struct page *page)
printk(KERN_EMERG "Backtrace:\n");
dump_stack();
printk(KERN_EMERG "Trying to fix it up, but a reboot is needed\n");
- page->flags &= ~(1 << PG_private |
+ page->flags &= ~(1 << PG_lru |
+ 1 << PG_private |
1 << PG_locked |
- 1 << PG_lru |
1 << PG_active |
1 << PG_dirty |
+ 1 << PG_reclaim |
+ 1 << PG_slab |
1 << PG_swapcache |
1 << PG_writeback);
set_page_count(page, 0);
@@ -440,14 +442,17 @@ void set_page_refs(struct page *page, int order)
*/
static void prep_new_page(struct page *page, int order)
{
- if (page->mapping || page_mapcount(page) ||
- (page->flags & (
+ if ( page_mapcount(page) ||
+ page->mapping != NULL ||
+ page_count(page) != 0 ||
+ (page->flags & (
+ 1 << PG_lru |
1 << PG_private |
1 << PG_locked |
- 1 << PG_lru |
1 << PG_active |
1 << PG_dirty |
1 << PG_reclaim |
+ 1 << PG_slab |
1 << PG_swapcache |
1 << PG_writeback )))
bad_page(__FUNCTION__, page);
@@ -511,6 +516,36 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order,
return allocated;
}
+#ifdef CONFIG_NUMA
+/* Called from the slab reaper to drain remote pagesets */
+void drain_remote_pages(void)
+{
+ struct zone *zone;
+ int i;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ for_each_zone(zone) {
+ struct per_cpu_pageset *pset;
+
+ /* Do not drain local pagesets */
+ if (zone->zone_pgdat->node_id == numa_node_id())
+ continue;
+
+ pset = zone->pageset[smp_processor_id()];
+ for (i = 0; i < ARRAY_SIZE(pset->pcp); i++) {
+ struct per_cpu_pages *pcp;
+
+ pcp = &pset->pcp[i];
+ if (pcp->count)
+ pcp->count -= free_pages_bulk(zone, pcp->count,
+ &pcp->list, 0);
+ }
+ }
+ local_irq_restore(flags);
+}
+#endif
+
#if defined(CONFIG_PM) || defined(CONFIG_HOTPLUG_CPU)
static void __drain_pages(unsigned int cpu)
{
@@ -520,7 +555,7 @@ static void __drain_pages(unsigned int cpu)
for_each_zone(zone) {
struct per_cpu_pageset *pset;
- pset = &zone->pageset[cpu];
+ pset = zone_pcp(zone, cpu);
for (i = 0; i < ARRAY_SIZE(pset->pcp); i++) {
struct per_cpu_pages *pcp;
@@ -583,12 +618,12 @@ static void zone_statistics(struct zonelist *zonelist, struct zone *z)
local_irq_save(flags);
cpu = smp_processor_id();
- p = &z->pageset[cpu];
+ p = zone_pcp(z,cpu);
if (pg == orig) {
- z->pageset[cpu].numa_hit++;
+ p->numa_hit++;
} else {
p->numa_miss++;
- zonelist->zones[0]->pageset[cpu].numa_foreign++;
+ zone_pcp(zonelist->zones[0], cpu)->numa_foreign++;
}
if (pg == NODE_DATA(numa_node_id()))
p->local_node++;
@@ -615,12 +650,12 @@ static void fastcall free_hot_cold_page(struct page *page, int cold)
if (PageAnon(page))
page->mapping = NULL;
free_pages_check(__FUNCTION__, page);
- pcp = &zone->pageset[get_cpu()].pcp[cold];
+ pcp = &zone_pcp(zone, get_cpu())->pcp[cold];
local_irq_save(flags);
- if (pcp->count >= pcp->high)
- pcp->count -= free_pages_bulk(zone, pcp->batch, &pcp->list, 0);
list_add(&page->lru, &pcp->list);
pcp->count++;
+ if (pcp->count >= pcp->high)
+ pcp->count -= free_pages_bulk(zone, pcp->batch, &pcp->list, 0);
local_irq_restore(flags);
put_cpu();
}
@@ -659,7 +694,7 @@ buffered_rmqueue(struct zone *zone, int order, unsigned int __nocast gfp_flags)
if (order == 0) {
struct per_cpu_pages *pcp;
- pcp = &zone->pageset[get_cpu()].pcp[cold];
+ pcp = &zone_pcp(zone, get_cpu())->pcp[cold];
local_irq_save(flags);
if (pcp->count <= pcp->low)
pcp->count += rmqueue_bulk(zone, 0,
@@ -724,6 +759,16 @@ int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
return 1;
}
+static inline int
+should_reclaim_zone(struct zone *z, unsigned int gfp_mask)
+{
+ if (!z->reclaim_pages)
+ return 0;
+ if (gfp_mask & __GFP_NORECLAIM)
+ return 0;
+ return 1;
+}
+
/*
* This is the 'heart' of the zoned buddy allocator.
*/
@@ -760,17 +805,32 @@ __alloc_pages(unsigned int __nocast gfp_mask, unsigned int order,
classzone_idx = zone_idx(zones[0]);
- restart:
+restart:
/* Go through the zonelist once, looking for a zone with enough free */
for (i = 0; (z = zones[i]) != NULL; i++) {
-
- if (!zone_watermark_ok(z, order, z->pages_low,
- classzone_idx, 0, 0))
- continue;
+ int do_reclaim = should_reclaim_zone(z, gfp_mask);
if (!cpuset_zone_allowed(z))
continue;
+ /*
+ * If the zone is to attempt early page reclaim then this loop
+ * will try to reclaim pages and check the watermark a second
+ * time before giving up and falling back to the next zone.
+ */
+zone_reclaim_retry:
+ if (!zone_watermark_ok(z, order, z->pages_low,
+ classzone_idx, 0, 0)) {
+ if (!do_reclaim)
+ continue;
+ else {
+ zone_reclaim(z, gfp_mask, order);
+ /* Only try reclaim once */
+ do_reclaim = 0;
+ goto zone_reclaim_retry;
+ }
+ }
+
page = buffered_rmqueue(z, order, gfp_mask);
if (page)
goto got_pg;
@@ -829,7 +889,7 @@ rebalance:
reclaim_state.reclaimed_slab = 0;
p->reclaim_state = &reclaim_state;
- did_some_progress = try_to_free_pages(zones, gfp_mask, order);
+ did_some_progress = try_to_free_pages(zones, gfp_mask);
p->reclaim_state = NULL;
p->flags &= ~PF_MEMALLOC;
@@ -905,6 +965,7 @@ nopage:
" order:%d, mode:0x%x\n",
p->comm, order, gfp_mask);
dump_stack();
+ show_mem();
}
return NULL;
got_pg:
@@ -1114,7 +1175,7 @@ void get_full_page_state(struct page_state *ret)
__get_page_state(ret, sizeof(*ret) / sizeof(unsigned long));
}
-unsigned long __read_page_state(unsigned offset)
+unsigned long __read_page_state(unsigned long offset)
{
unsigned long ret = 0;
int cpu;
@@ -1128,7 +1189,7 @@ unsigned long __read_page_state(unsigned offset)
return ret;
}
-void __mod_page_state(unsigned offset, unsigned long delta)
+void __mod_page_state(unsigned long offset, unsigned long delta)
{
unsigned long flags;
void* ptr;
@@ -1237,22 +1298,23 @@ void show_free_areas(void)
if (!cpu_possible(cpu))
continue;
- pageset = zone->pageset + cpu;
+ pageset = zone_pcp(zone, cpu);
for (temperature = 0; temperature < 2; temperature++)
- printk("cpu %d %s: low %d, high %d, batch %d\n",
+ printk("cpu %d %s: low %d, high %d, batch %d used:%d\n",
cpu,
temperature ? "cold" : "hot",
pageset->pcp[temperature].low,
pageset->pcp[temperature].high,
- pageset->pcp[temperature].batch);
+ pageset->pcp[temperature].batch,
+ pageset->pcp[temperature].count);
}
}
get_page_state(&ps);
get_zone_counts(&active, &inactive, &free);
- printk("\nFree pages: %11ukB (%ukB HighMem)\n",
+ printk("Free pages: %11ukB (%ukB HighMem)\n",
K(nr_free_pages()),
K(nr_free_highpages()));
@@ -1587,11 +1649,17 @@ static void __init calculate_zone_totalpages(struct pglist_data *pgdat,
void __init memmap_init_zone(unsigned long size, int nid, unsigned long zone,
unsigned long start_pfn)
{
- struct page *start = pfn_to_page(start_pfn);
struct page *page;
+ unsigned long end_pfn = start_pfn + size;
+ unsigned long pfn;
- for (page = start; page < (start + size); page++) {
- set_page_zone(page, NODEZONE(nid, zone));
+ for (pfn = start_pfn; pfn < end_pfn; pfn++, page++) {
+ if (!early_pfn_valid(pfn))
+ continue;
+ if (!early_pfn_in_nid(pfn, nid))
+ continue;
+ page = pfn_to_page(pfn);
+ set_page_links(page, zone, nid, pfn);
set_page_count(page, 0);
reset_page_mapcount(page);
SetPageReserved(page);
@@ -1615,11 +1683,181 @@ void zone_init_free_lists(struct pglist_data *pgdat, struct zone *zone,
}
}
+#define ZONETABLE_INDEX(x, zone_nr) ((x << ZONES_SHIFT) | zone_nr)
+void zonetable_add(struct zone *zone, int nid, int zid, unsigned long pfn,
+ unsigned long size)
+{
+ unsigned long snum = pfn_to_section_nr(pfn);
+ unsigned long end = pfn_to_section_nr(pfn + size);
+
+ if (FLAGS_HAS_NODE)
+ zone_table[ZONETABLE_INDEX(nid, zid)] = zone;
+ else
+ for (; snum <= end; snum++)
+ zone_table[ZONETABLE_INDEX(snum, zid)] = zone;
+}
+
#ifndef __HAVE_ARCH_MEMMAP_INIT
#define memmap_init(size, nid, zone, start_pfn) \
memmap_init_zone((size), (nid), (zone), (start_pfn))
#endif
+static int __devinit zone_batchsize(struct zone *zone)
+{
+ int batch;
+
+ /*
+ * The per-cpu-pages pools are set to around 1000th of the
+ * size of the zone. But no more than 1/4 of a meg - there's
+ * no point in going beyond the size of L2 cache.
+ *
+ * OK, so we don't know how big the cache is. So guess.
+ */
+ batch = zone->present_pages / 1024;
+ if (batch * PAGE_SIZE > 256 * 1024)
+ batch = (256 * 1024) / PAGE_SIZE;
+ batch /= 4; /* We effectively *= 4 below */
+ if (batch < 1)
+ batch = 1;
+
+ /*
+ * Clamp the batch to a 2^n - 1 value. Having a power
+ * of 2 value was found to be more likely to have
+ * suboptimal cache aliasing properties in some cases.
+ *
+ * For example if 2 tasks are alternately allocating
+ * batches of pages, one task can end up with a lot
+ * of pages of one half of the possible page colors
+ * and the other with pages of the other colors.
+ */
+ batch = (1 << fls(batch + batch/2)) - 1;
+ return batch;
+}
+
+inline void setup_pageset(struct per_cpu_pageset *p, unsigned long batch)
+{
+ struct per_cpu_pages *pcp;
+
+ pcp = &p->pcp[0]; /* hot */
+ pcp->count = 0;
+ pcp->low = 2 * batch;
+ pcp->high = 6 * batch;
+ pcp->batch = max(1UL, 1 * batch);
+ INIT_LIST_HEAD(&pcp->list);
+
+ pcp = &p->pcp[1]; /* cold*/
+ pcp->count = 0;
+ pcp->low = 0;
+ pcp->high = 2 * batch;
+ pcp->batch = max(1UL, 1 * batch);
+ INIT_LIST_HEAD(&pcp->list);
+}
+
+#ifdef CONFIG_NUMA
+/*
+ * Boot pageset table. One per cpu which is going to be used for all
+ * zones and all nodes. The parameters will be set in such a way
+ * that an item put on a list will immediately be handed over to
+ * the buddy list. This is safe since pageset manipulation is done
+ * with interrupts disabled.
+ *
+ * Some NUMA counter updates may also be caught by the boot pagesets.
+ *
+ * The boot_pagesets must be kept even after bootup is complete for
+ * unused processors and/or zones. They do play a role for bootstrapping
+ * hotplugged processors.
+ *
+ * zoneinfo_show() and maybe other functions do
+ * not check if the processor is online before following the pageset pointer.
+ * Other parts of the kernel may not check if the zone is available.
+ */
+static struct per_cpu_pageset
+ boot_pageset[NR_CPUS];
+
+/*
+ * Dynamically allocate memory for the
+ * per cpu pageset array in struct zone.
+ */
+static int __devinit process_zones(int cpu)
+{
+ struct zone *zone, *dzone;
+
+ for_each_zone(zone) {
+
+ zone->pageset[cpu] = kmalloc_node(sizeof(struct per_cpu_pageset),
+ GFP_KERNEL, cpu_to_node(cpu));
+ if (!zone->pageset[cpu])
+ goto bad;
+
+ setup_pageset(zone->pageset[cpu], zone_batchsize(zone));
+ }
+
+ return 0;
+bad:
+ for_each_zone(dzone) {
+ if (dzone == zone)
+ break;
+ kfree(dzone->pageset[cpu]);
+ dzone->pageset[cpu] = NULL;
+ }
+ return -ENOMEM;
+}
+
+static inline void free_zone_pagesets(int cpu)
+{
+#ifdef CONFIG_NUMA
+ struct zone *zone;
+
+ for_each_zone(zone) {
+ struct per_cpu_pageset *pset = zone_pcp(zone, cpu);
+
+ zone_pcp(zone, cpu) = NULL;
+ kfree(pset);
+ }
+#endif
+}
+
+static int __devinit pageset_cpuup_callback(struct notifier_block *nfb,
+ unsigned long action,
+ void *hcpu)
+{
+ int cpu = (long)hcpu;
+ int ret = NOTIFY_OK;
+
+ switch (action) {
+ case CPU_UP_PREPARE:
+ if (process_zones(cpu))
+ ret = NOTIFY_BAD;
+ break;
+#ifdef CONFIG_HOTPLUG_CPU
+ case CPU_DEAD:
+ free_zone_pagesets(cpu);
+ break;
+#endif
+ default:
+ break;
+ }
+ return ret;
+}
+
+static struct notifier_block pageset_notifier =
+ { &pageset_cpuup_callback, NULL, 0 };
+
+void __init setup_per_cpu_pageset()
+{
+ int err;
+
+ /* Initialize per_cpu_pageset for cpu 0.
+ * A cpuup callback will do this for every cpu
+ * as it comes online
+ */
+ err = process_zones(smp_processor_id());
+ BUG_ON(err);
+ register_cpu_notifier(&pageset_notifier);
+}
+
+#endif
+
/*
* Set up the zone data structures:
* - mark all pages reserved
@@ -1643,7 +1881,6 @@ static void __init free_area_init_core(struct pglist_data *pgdat,
unsigned long size, realsize;
unsigned long batch;
- zone_table[NODEZONE(nid, j)] = zone;
realsize = size = zones_size[j];
if (zholes_size)
realsize -= zholes_size[j];
@@ -1662,48 +1899,16 @@ static void __init free_area_init_core(struct pglist_data *pgdat,
zone->temp_priority = zone->prev_priority = DEF_PRIORITY;
- /*
- * The per-cpu-pages pools are set to around 1000th of the
- * size of the zone. But no more than 1/4 of a meg - there's
- * no point in going beyond the size of L2 cache.
- *
- * OK, so we don't know how big the cache is. So guess.
- */
- batch = zone->present_pages / 1024;
- if (batch * PAGE_SIZE > 256 * 1024)
- batch = (256 * 1024) / PAGE_SIZE;
- batch /= 4; /* We effectively *= 4 below */
- if (batch < 1)
- batch = 1;
-
- /*
- * Clamp the batch to a 2^n - 1 value. Having a power
- * of 2 value was found to be more likely to have
- * suboptimal cache aliasing properties in some cases.
- *
- * For example if 2 tasks are alternately allocating
- * batches of pages, one task can end up with a lot
- * of pages of one half of the possible page colors
- * and the other with pages of the other colors.
- */
- batch = (1 << fls(batch + batch/2)) - 1;
+ batch = zone_batchsize(zone);
for (cpu = 0; cpu < NR_CPUS; cpu++) {
- struct per_cpu_pages *pcp;
-
- pcp = &zone->pageset[cpu].pcp[0]; /* hot */
- pcp->count = 0;
- pcp->low = 2 * batch;
- pcp->high = 6 * batch;
- pcp->batch = 1 * batch;
- INIT_LIST_HEAD(&pcp->list);
-
- pcp = &zone->pageset[cpu].pcp[1]; /* cold */
- pcp->count = 0;
- pcp->low = 0;
- pcp->high = 2 * batch;
- pcp->batch = 1 * batch;
- INIT_LIST_HEAD(&pcp->list);
+#ifdef CONFIG_NUMA
+ /* Early boot. Slab allocator not functional yet */
+ zone->pageset[cpu] = &boot_pageset[cpu];
+ setup_pageset(&boot_pageset[cpu],0);
+#else
+ setup_pageset(zone_pcp(zone,cpu), batch);
+#endif
}
printk(KERN_DEBUG " %s zone: %lu pages, LIFO batch:%lu\n",
zone_names[j], realsize, batch);
@@ -1713,6 +1918,7 @@ static void __init free_area_init_core(struct pglist_data *pgdat,
zone->nr_scan_inactive = 0;
zone->nr_active = 0;
zone->nr_inactive = 0;
+ atomic_set(&zone->reclaim_in_progress, -1);
if (!size)
continue;
@@ -1740,6 +1946,8 @@ static void __init free_area_init_core(struct pglist_data *pgdat,
memmap_init(size, nid, j, zone_start_pfn);
+ zonetable_add(zone, nid, j, zone_start_pfn, size);
+
zone_start_pfn += size;
zone_init_free_lists(pgdat, zone, zone->spanned_pages);
@@ -1748,24 +1956,30 @@ static void __init free_area_init_core(struct pglist_data *pgdat,
static void __init alloc_node_mem_map(struct pglist_data *pgdat)
{
- unsigned long size;
-
/* Skip empty nodes */
if (!pgdat->node_spanned_pages)
return;
+#ifdef CONFIG_FLAT_NODE_MEM_MAP
/* ia64 gets its own node_mem_map, before this, without bootmem */
if (!pgdat->node_mem_map) {
+ unsigned long size;
+ struct page *map;
+
size = (pgdat->node_spanned_pages + 1) * sizeof(struct page);
- pgdat->node_mem_map = alloc_bootmem_node(pgdat, size);
+ map = alloc_remap(pgdat->node_id, size);
+ if (!map)
+ map = alloc_bootmem_node(pgdat, size);
+ pgdat->node_mem_map = map;
}
-#ifndef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_FLATMEM
/*
* With no DISCONTIG, the global mem_map is just set as node 0's
*/
if (pgdat == NODE_DATA(0))
mem_map = NODE_DATA(0)->node_mem_map;
#endif
+#endif /* CONFIG_FLAT_NODE_MEM_MAP */
}
void __init free_area_init_node(int nid, struct pglist_data *pgdat,
@@ -1781,18 +1995,18 @@ void __init free_area_init_node(int nid, struct pglist_data *pgdat,
free_area_init_core(pgdat, zones_size, zholes_size);
}
-#ifndef CONFIG_DISCONTIGMEM
+#ifndef CONFIG_NEED_MULTIPLE_NODES
static bootmem_data_t contig_bootmem_data;
struct pglist_data contig_page_data = { .bdata = &contig_bootmem_data };
EXPORT_SYMBOL(contig_page_data);
+#endif
void __init free_area_init(unsigned long *zones_size)
{
- free_area_init_node(0, &contig_page_data, zones_size,
+ free_area_init_node(0, NODE_DATA(0), zones_size,
__pa(PAGE_OFFSET) >> PAGE_SHIFT, NULL);
}
-#endif
#ifdef CONFIG_PROC_FS
@@ -1853,6 +2067,115 @@ struct seq_operations fragmentation_op = {
.show = frag_show,
};
+/*
+ * Output information about zones in @pgdat.
+ */
+static int zoneinfo_show(struct seq_file *m, void *arg)
+{
+ pg_data_t *pgdat = arg;
+ struct zone *zone;
+ struct zone *node_zones = pgdat->node_zones;
+ unsigned long flags;
+
+ for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; zone++) {
+ int i;
+
+ if (!zone->present_pages)
+ continue;
+
+ spin_lock_irqsave(&zone->lock, flags);
+ seq_printf(m, "Node %d, zone %8s", pgdat->node_id, zone->name);
+ seq_printf(m,
+ "\n pages free %lu"
+ "\n min %lu"
+ "\n low %lu"
+ "\n high %lu"
+ "\n active %lu"
+ "\n inactive %lu"
+ "\n scanned %lu (a: %lu i: %lu)"
+ "\n spanned %lu"
+ "\n present %lu",
+ zone->free_pages,
+ zone->pages_min,
+ zone->pages_low,
+ zone->pages_high,
+ zone->nr_active,
+ zone->nr_inactive,
+ zone->pages_scanned,
+ zone->nr_scan_active, zone->nr_scan_inactive,
+ zone->spanned_pages,
+ zone->present_pages);
+ seq_printf(m,
+ "\n protection: (%lu",
+ zone->lowmem_reserve[0]);
+ for (i = 1; i < ARRAY_SIZE(zone->lowmem_reserve); i++)
+ seq_printf(m, ", %lu", zone->lowmem_reserve[i]);
+ seq_printf(m,
+ ")"
+ "\n pagesets");
+ for (i = 0; i < ARRAY_SIZE(zone->pageset); i++) {
+ struct per_cpu_pageset *pageset;
+ int j;
+
+ pageset = zone_pcp(zone, i);
+ for (j = 0; j < ARRAY_SIZE(pageset->pcp); j++) {
+ if (pageset->pcp[j].count)
+ break;
+ }
+ if (j == ARRAY_SIZE(pageset->pcp))
+ continue;
+ for (j = 0; j < ARRAY_SIZE(pageset->pcp); j++) {
+ seq_printf(m,
+ "\n cpu: %i pcp: %i"
+ "\n count: %i"
+ "\n low: %i"
+ "\n high: %i"
+ "\n batch: %i",
+ i, j,
+ pageset->pcp[j].count,
+ pageset->pcp[j].low,
+ pageset->pcp[j].high,
+ pageset->pcp[j].batch);
+ }
+#ifdef CONFIG_NUMA
+ seq_printf(m,
+ "\n numa_hit: %lu"
+ "\n numa_miss: %lu"
+ "\n numa_foreign: %lu"
+ "\n interleave_hit: %lu"
+ "\n local_node: %lu"
+ "\n other_node: %lu",
+ pageset->numa_hit,
+ pageset->numa_miss,
+ pageset->numa_foreign,
+ pageset->interleave_hit,
+ pageset->local_node,
+ pageset->other_node);
+#endif
+ }
+ seq_printf(m,
+ "\n all_unreclaimable: %u"
+ "\n prev_priority: %i"
+ "\n temp_priority: %i"
+ "\n start_pfn: %lu",
+ zone->all_unreclaimable,
+ zone->prev_priority,
+ zone->temp_priority,
+ zone->zone_start_pfn);
+ spin_unlock_irqrestore(&zone->lock, flags);
+ seq_putc(m, '\n');
+ }
+ return 0;
+}
+
+struct seq_operations zoneinfo_op = {
+ .start = frag_start, /* iterate over all zones. The same as in
+ * fragmentation. */
+ .next = frag_next,
+ .stop = frag_stop,
+ .show = zoneinfo_show,
+};
+
static char *vmstat_text[] = {
"nr_dirty",
"nr_writeback",
@@ -2058,10 +2381,10 @@ static void setup_per_zone_pages_min(void)
min_pages = 128;
zone->pages_min = min_pages;
} else {
- /* if it's a lowmem zone, reserve a number of pages
+ /* if it's a lowmem zone, reserve a number of pages
* proportionate to the zone's size.
*/
- zone->pages_min = (pages_min * zone->present_pages) /
+ zone->pages_min = (pages_min * zone->present_pages) /
lowmem_pages;
}
diff --git a/mm/page_io.c b/mm/page_io.c
index 667c76df1ec..2e605a19ce5 100644
--- a/mm/page_io.c
+++ b/mm/page_io.c
@@ -127,7 +127,7 @@ out:
return ret;
}
-#if defined(CONFIG_SOFTWARE_SUSPEND) || defined(CONFIG_PM_DISK)
+#ifdef CONFIG_SOFTWARE_SUSPEND
/*
* A scruffy utility function to read or write an arbitrary swap page
* and wait on the I/O. The caller must have a ref on the page.
diff --git a/mm/pdflush.c b/mm/pdflush.c
index 38ce279cc8c..d6781951267 100644
--- a/mm/pdflush.c
+++ b/mm/pdflush.c
@@ -105,7 +105,7 @@ static int __pdflush(struct pdflush_work *my_work)
spin_unlock_irq(&pdflush_lock);
schedule();
- if (try_to_freeze(PF_FREEZE)) {
+ if (try_to_freeze()) {
spin_lock_irq(&pdflush_lock);
continue;
}
diff --git a/mm/rmap.c b/mm/rmap.c
index 378de234c12..08ac5c7fa91 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -247,8 +247,8 @@ unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma)
*
* On success returns with mapped pte and locked mm->page_table_lock.
*/
-static pte_t *page_check_address(struct page *page, struct mm_struct *mm,
- unsigned long address)
+pte_t *page_check_address(struct page *page, struct mm_struct *mm,
+ unsigned long address)
{
pgd_t *pgd;
pud_t *pud;
@@ -539,27 +539,6 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma)
goto out_unmap;
}
- /*
- * Don't pull an anonymous page out from under get_user_pages.
- * GUP carefully breaks COW and raises page count (while holding
- * page_table_lock, as we have here) to make sure that the page
- * cannot be freed. If we unmap that page here, a user write
- * access to the virtual address will bring back the page, but
- * its raised count will (ironically) be taken to mean it's not
- * an exclusive swap page, do_wp_page will replace it by a copy
- * page, and the user never get to see the data GUP was holding
- * the original page for.
- *
- * This test is also useful for when swapoff (unuse_process) has
- * to drop page lock: its reference to the page stops existing
- * ptes from being unmapped, so swapoff can make progress.
- */
- if (PageSwapCache(page) &&
- page_count(page) != page_mapcount(page) + 2) {
- ret = SWAP_FAIL;
- goto out_unmap;
- }
-
/* Nuke the page table entry. */
flush_cache_page(vma, address, page_to_pfn(page));
pteval = ptep_clear_flush(vma, address, pte);
@@ -586,7 +565,7 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma)
dec_mm_counter(mm, anon_rss);
}
- inc_mm_counter(mm, rss);
+ dec_mm_counter(mm, rss);
page_remove_rmap(page);
page_cache_release(page);
@@ -626,7 +605,7 @@ static void try_to_unmap_cluster(unsigned long cursor,
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
- pte_t *pte;
+ pte_t *pte, *original_pte;
pte_t pteval;
struct page *page;
unsigned long address;
@@ -658,7 +637,7 @@ static void try_to_unmap_cluster(unsigned long cursor,
if (!pmd_present(*pmd))
goto out_unlock;
- for (pte = pte_offset_map(pmd, address);
+ for (original_pte = pte = pte_offset_map(pmd, address);
address < end; pte++, address += PAGE_SIZE) {
if (!pte_present(*pte))
@@ -694,7 +673,7 @@ static void try_to_unmap_cluster(unsigned long cursor,
(*mapcount)--;
}
- pte_unmap(pte);
+ pte_unmap(original_pte);
out_unlock:
spin_unlock(&mm->page_table_lock);
}
diff --git a/mm/shmem.c b/mm/shmem.c
index 61574b81d97..e64fa726a79 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -6,8 +6,8 @@
* 2000-2001 Christoph Rohland
* 2000-2001 SAP AG
* 2002 Red Hat Inc.
- * Copyright (C) 2002-2004 Hugh Dickins.
- * Copyright (C) 2002-2004 VERITAS Software Corporation.
+ * Copyright (C) 2002-2005 Hugh Dickins.
+ * Copyright (C) 2002-2005 VERITAS Software Corporation.
* Copyright (C) 2004 Andi Kleen, SuSE Labs
*
* Extended attribute support for tmpfs:
@@ -194,7 +194,7 @@ static DEFINE_SPINLOCK(shmem_swaplist_lock);
static void shmem_free_blocks(struct inode *inode, long pages)
{
struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
- if (sbinfo) {
+ if (sbinfo->max_blocks) {
spin_lock(&sbinfo->stat_lock);
sbinfo->free_blocks += pages;
inode->i_blocks -= pages*BLOCKS_PER_PAGE;
@@ -357,7 +357,7 @@ static swp_entry_t *shmem_swp_alloc(struct shmem_inode_info *info, unsigned long
* page (and perhaps indirect index pages) yet to allocate:
* a waste to allocate index if we cannot allocate data.
*/
- if (sbinfo) {
+ if (sbinfo->max_blocks) {
spin_lock(&sbinfo->stat_lock);
if (sbinfo->free_blocks <= 1) {
spin_unlock(&sbinfo->stat_lock);
@@ -677,8 +677,8 @@ static void shmem_delete_inode(struct inode *inode)
spin_unlock(&shmem_swaplist_lock);
}
}
- if (sbinfo) {
- BUG_ON(inode->i_blocks);
+ BUG_ON(inode->i_blocks);
+ if (sbinfo->max_inodes) {
spin_lock(&sbinfo->stat_lock);
sbinfo->free_inodes++;
spin_unlock(&sbinfo->stat_lock);
@@ -1080,7 +1080,7 @@ repeat:
} else {
shmem_swp_unmap(entry);
sbinfo = SHMEM_SB(inode->i_sb);
- if (sbinfo) {
+ if (sbinfo->max_blocks) {
spin_lock(&sbinfo->stat_lock);
if (sbinfo->free_blocks == 0 ||
shmem_acct_block(info->flags)) {
@@ -1269,7 +1269,7 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
struct shmem_inode_info *info;
struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
- if (sbinfo) {
+ if (sbinfo->max_inodes) {
spin_lock(&sbinfo->stat_lock);
if (!sbinfo->free_inodes) {
spin_unlock(&sbinfo->stat_lock);
@@ -1319,7 +1319,7 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
mpol_shared_policy_init(&info->policy);
break;
}
- } else if (sbinfo) {
+ } else if (sbinfo->max_inodes) {
spin_lock(&sbinfo->stat_lock);
sbinfo->free_inodes++;
spin_unlock(&sbinfo->stat_lock);
@@ -1328,31 +1328,6 @@ shmem_get_inode(struct super_block *sb, int mode, dev_t dev)
}
#ifdef CONFIG_TMPFS
-
-static int shmem_set_size(struct shmem_sb_info *sbinfo,
- unsigned long max_blocks, unsigned long max_inodes)
-{
- int error;
- unsigned long blocks, inodes;
-
- spin_lock(&sbinfo->stat_lock);
- blocks = sbinfo->max_blocks - sbinfo->free_blocks;
- inodes = sbinfo->max_inodes - sbinfo->free_inodes;
- error = -EINVAL;
- if (max_blocks < blocks)
- goto out;
- if (max_inodes < inodes)
- goto out;
- error = 0;
- sbinfo->max_blocks = max_blocks;
- sbinfo->free_blocks = max_blocks - blocks;
- sbinfo->max_inodes = max_inodes;
- sbinfo->free_inodes = max_inodes - inodes;
-out:
- spin_unlock(&sbinfo->stat_lock);
- return error;
-}
-
static struct inode_operations shmem_symlink_inode_operations;
static struct inode_operations shmem_symlink_inline_operations;
@@ -1607,15 +1582,17 @@ static int shmem_statfs(struct super_block *sb, struct kstatfs *buf)
buf->f_type = TMPFS_MAGIC;
buf->f_bsize = PAGE_CACHE_SIZE;
buf->f_namelen = NAME_MAX;
- if (sbinfo) {
- spin_lock(&sbinfo->stat_lock);
+ spin_lock(&sbinfo->stat_lock);
+ if (sbinfo->max_blocks) {
buf->f_blocks = sbinfo->max_blocks;
buf->f_bavail = buf->f_bfree = sbinfo->free_blocks;
+ }
+ if (sbinfo->max_inodes) {
buf->f_files = sbinfo->max_inodes;
buf->f_ffree = sbinfo->free_inodes;
- spin_unlock(&sbinfo->stat_lock);
}
/* else leave those fields 0 like simple_statfs */
+ spin_unlock(&sbinfo->stat_lock);
return 0;
}
@@ -1672,7 +1649,7 @@ static int shmem_link(struct dentry *old_dentry, struct inode *dir, struct dentr
* but each new link needs a new dentry, pinning lowmem, and
* tmpfs dentries cannot be pruned until they are unlinked.
*/
- if (sbinfo) {
+ if (sbinfo->max_inodes) {
spin_lock(&sbinfo->stat_lock);
if (!sbinfo->free_inodes) {
spin_unlock(&sbinfo->stat_lock);
@@ -1697,7 +1674,7 @@ static int shmem_unlink(struct inode *dir, struct dentry *dentry)
if (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode)) {
struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
- if (sbinfo) {
+ if (sbinfo->max_inodes) {
spin_lock(&sbinfo->stat_lock);
sbinfo->free_inodes++;
spin_unlock(&sbinfo->stat_lock);
@@ -1921,22 +1898,42 @@ bad_val:
static int shmem_remount_fs(struct super_block *sb, int *flags, char *data)
{
struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
- unsigned long max_blocks = 0;
- unsigned long max_inodes = 0;
+ unsigned long max_blocks = sbinfo->max_blocks;
+ unsigned long max_inodes = sbinfo->max_inodes;
+ unsigned long blocks;
+ unsigned long inodes;
+ int error = -EINVAL;
+
+ if (shmem_parse_options(data, NULL, NULL, NULL,
+ &max_blocks, &max_inodes))
+ return error;
- if (sbinfo) {
- max_blocks = sbinfo->max_blocks;
- max_inodes = sbinfo->max_inodes;
- }
- if (shmem_parse_options(data, NULL, NULL, NULL, &max_blocks, &max_inodes))
- return -EINVAL;
- /* Keep it simple: disallow limited <-> unlimited remount */
- if ((max_blocks || max_inodes) == !sbinfo)
- return -EINVAL;
- /* But allow the pointless unlimited -> unlimited remount */
- if (!sbinfo)
- return 0;
- return shmem_set_size(sbinfo, max_blocks, max_inodes);
+ spin_lock(&sbinfo->stat_lock);
+ blocks = sbinfo->max_blocks - sbinfo->free_blocks;
+ inodes = sbinfo->max_inodes - sbinfo->free_inodes;
+ if (max_blocks < blocks)
+ goto out;
+ if (max_inodes < inodes)
+ goto out;
+ /*
+ * Those tests also disallow limited->unlimited while any are in
+ * use, so i_blocks will always be zero when max_blocks is zero;
+ * but we must separately disallow unlimited->limited, because
+ * in that case we have no record of how much is already in use.
+ */
+ if (max_blocks && !sbinfo->max_blocks)
+ goto out;
+ if (max_inodes && !sbinfo->max_inodes)
+ goto out;
+
+ error = 0;
+ sbinfo->max_blocks = max_blocks;
+ sbinfo->free_blocks = max_blocks - blocks;
+ sbinfo->max_inodes = max_inodes;
+ sbinfo->free_inodes = max_inodes - inodes;
+out:
+ spin_unlock(&sbinfo->stat_lock);
+ return error;
}
#endif
@@ -1961,11 +1958,11 @@ static int shmem_fill_super(struct super_block *sb,
uid_t uid = current->fsuid;
gid_t gid = current->fsgid;
int err = -ENOMEM;
-
-#ifdef CONFIG_TMPFS
+ struct shmem_sb_info *sbinfo;
unsigned long blocks = 0;
unsigned long inodes = 0;
+#ifdef CONFIG_TMPFS
/*
* Per default we only allow half of the physical ram per
* tmpfs instance, limiting inodes to one per page of lowmem;
@@ -1976,34 +1973,34 @@ static int shmem_fill_super(struct super_block *sb,
inodes = totalram_pages - totalhigh_pages;
if (inodes > blocks)
inodes = blocks;
-
- if (shmem_parse_options(data, &mode,
- &uid, &gid, &blocks, &inodes))
+ if (shmem_parse_options(data, &mode, &uid, &gid,
+ &blocks, &inodes))
return -EINVAL;
}
-
- if (blocks || inodes) {
- struct shmem_sb_info *sbinfo;
- sbinfo = kmalloc(sizeof(struct shmem_sb_info), GFP_KERNEL);
- if (!sbinfo)
- return -ENOMEM;
- sb->s_fs_info = sbinfo;
- spin_lock_init(&sbinfo->stat_lock);
- sbinfo->max_blocks = blocks;
- sbinfo->free_blocks = blocks;
- sbinfo->max_inodes = inodes;
- sbinfo->free_inodes = inodes;
- }
- sb->s_xattr = shmem_xattr_handlers;
#else
sb->s_flags |= MS_NOUSER;
#endif
+ /* Round up to L1_CACHE_BYTES to resist false sharing */
+ sbinfo = kmalloc(max((int)sizeof(struct shmem_sb_info),
+ L1_CACHE_BYTES), GFP_KERNEL);
+ if (!sbinfo)
+ return -ENOMEM;
+
+ spin_lock_init(&sbinfo->stat_lock);
+ sbinfo->max_blocks = blocks;
+ sbinfo->free_blocks = blocks;
+ sbinfo->max_inodes = inodes;
+ sbinfo->free_inodes = inodes;
+
+ sb->s_fs_info = sbinfo;
sb->s_maxbytes = SHMEM_MAX_BYTES;
sb->s_blocksize = PAGE_CACHE_SIZE;
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
sb->s_magic = TMPFS_MAGIC;
sb->s_op = &shmem_ops;
+ sb->s_xattr = shmem_xattr_handlers;
+
inode = shmem_get_inode(sb, S_IFDIR | mode, 0);
if (!inode)
goto failed;
diff --git a/mm/slab.c b/mm/slab.c
index 84074264115..122d031baab 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -92,6 +92,7 @@
#include <linux/sysctl.h>
#include <linux/module.h>
#include <linux/rcupdate.h>
+#include <linux/string.h>
#include <asm/uaccess.h>
#include <asm/cacheflush.h>
@@ -2620,6 +2621,12 @@ unsigned int kmem_cache_size(kmem_cache_t *cachep)
}
EXPORT_SYMBOL(kmem_cache_size);
+const char *kmem_cache_name(kmem_cache_t *cachep)
+{
+ return cachep->name;
+}
+EXPORT_SYMBOL_GPL(kmem_cache_name);
+
struct ccupdate_struct {
kmem_cache_t *cachep;
struct array_cache *new[NR_CPUS];
@@ -2845,6 +2852,7 @@ next:
}
check_irq_on();
up(&cache_chain_sem);
+ drain_remote_pages();
/* Setup the next iteration */
schedule_delayed_work(&__get_cpu_var(reap_work), REAPTIMEOUT_CPUC + smp_processor_id());
}
@@ -3075,3 +3083,26 @@ unsigned int ksize(const void *objp)
return size;
}
+
+
+/*
+ * kstrdup - allocate space for and copy an existing string
+ *
+ * @s: the string to duplicate
+ * @gfp: the GFP mask used in the kmalloc() call when allocating memory
+ */
+char *kstrdup(const char *s, int gfp)
+{
+ size_t len;
+ char *buf;
+
+ if (!s)
+ return NULL;
+
+ len = strlen(s) + 1;
+ buf = kmalloc(len, gfp);
+ if (buf)
+ memcpy(buf, s, len);
+ return buf;
+}
+EXPORT_SYMBOL(kstrdup);
diff --git a/mm/sparse.c b/mm/sparse.c
new file mode 100644
index 00000000000..b54e304df4a
--- /dev/null
+++ b/mm/sparse.c
@@ -0,0 +1,137 @@
+/*
+ * sparse memory mappings.
+ */
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/mmzone.h>
+#include <linux/bootmem.h>
+#include <linux/module.h>
+#include <asm/dma.h>
+
+/*
+ * Permanent SPARSEMEM data:
+ *
+ * 1) mem_section - memory sections, mem_map's for valid memory
+ */
+struct mem_section mem_section[NR_MEM_SECTIONS];
+EXPORT_SYMBOL(mem_section);
+
+/* Record a memory area against a node. */
+void memory_present(int nid, unsigned long start, unsigned long end)
+{
+ unsigned long pfn;
+
+ start &= PAGE_SECTION_MASK;
+ for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) {
+ unsigned long section = pfn_to_section_nr(pfn);
+ if (!mem_section[section].section_mem_map)
+ mem_section[section].section_mem_map = SECTION_MARKED_PRESENT;
+ }
+}
+
+/*
+ * Only used by the i386 NUMA architecures, but relatively
+ * generic code.
+ */
+unsigned long __init node_memmap_size_bytes(int nid, unsigned long start_pfn,
+ unsigned long end_pfn)
+{
+ unsigned long pfn;
+ unsigned long nr_pages = 0;
+
+ for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
+ if (nid != early_pfn_to_nid(pfn))
+ continue;
+
+ if (pfn_valid(pfn))
+ nr_pages += PAGES_PER_SECTION;
+ }
+
+ return nr_pages * sizeof(struct page);
+}
+
+/*
+ * Subtle, we encode the real pfn into the mem_map such that
+ * the identity pfn - section_mem_map will return the actual
+ * physical page frame number.
+ */
+static unsigned long sparse_encode_mem_map(struct page *mem_map, unsigned long pnum)
+{
+ return (unsigned long)(mem_map - (section_nr_to_pfn(pnum)));
+}
+
+/*
+ * We need this if we ever free the mem_maps. While not implemented yet,
+ * this function is included for parity with its sibling.
+ */
+static __attribute((unused))
+struct page *sparse_decode_mem_map(unsigned long coded_mem_map, unsigned long pnum)
+{
+ return ((struct page *)coded_mem_map) + section_nr_to_pfn(pnum);
+}
+
+static int sparse_init_one_section(struct mem_section *ms,
+ unsigned long pnum, struct page *mem_map)
+{
+ if (!valid_section(ms))
+ return -EINVAL;
+
+ ms->section_mem_map |= sparse_encode_mem_map(mem_map, pnum);
+
+ return 1;
+}
+
+static struct page *sparse_early_mem_map_alloc(unsigned long pnum)
+{
+ struct page *map;
+ int nid = early_pfn_to_nid(section_nr_to_pfn(pnum));
+
+ map = alloc_remap(nid, sizeof(struct page) * PAGES_PER_SECTION);
+ if (map)
+ return map;
+
+ map = alloc_bootmem_node(NODE_DATA(nid),
+ sizeof(struct page) * PAGES_PER_SECTION);
+ if (map)
+ return map;
+
+ printk(KERN_WARNING "%s: allocation failed\n", __FUNCTION__);
+ mem_section[pnum].section_mem_map = 0;
+ return NULL;
+}
+
+/*
+ * Allocate the accumulated non-linear sections, allocate a mem_map
+ * for each and record the physical to section mapping.
+ */
+void sparse_init(void)
+{
+ unsigned long pnum;
+ struct page *map;
+
+ for (pnum = 0; pnum < NR_MEM_SECTIONS; pnum++) {
+ if (!valid_section_nr(pnum))
+ continue;
+
+ map = sparse_early_mem_map_alloc(pnum);
+ if (map)
+ sparse_init_one_section(&mem_section[pnum], pnum, map);
+ }
+}
+
+/*
+ * returns the number of sections whose mem_maps were properly
+ * set. If this is <=0, then that means that the passed-in
+ * map was not consumed and must be freed.
+ */
+int sparse_add_one_section(unsigned long start_pfn, int nr_pages, struct page *map)
+{
+ struct mem_section *ms = __pfn_to_section(start_pfn);
+
+ if (ms->section_mem_map & SECTION_MARKED_PRESENT)
+ return -EEXIST;
+
+ ms->section_mem_map |= SECTION_MARKED_PRESENT;
+
+ return sparse_init_one_section(ms, pfn_to_section_nr(start_pfn), map);
+}
diff --git a/mm/swapfile.c b/mm/swapfile.c
index a60e0075d55..60cd24a5520 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -79,7 +79,7 @@ void swap_unplug_io_fn(struct backing_dev_info *unused_bdi, struct page *page)
WARN_ON(page_count(page) <= 1);
bdi = bdev->bd_inode->i_mapping->backing_dev_info;
- bdi->unplug_io_fn(bdi, page);
+ blk_run_backing_dev(bdi, page);
}
up_read(&swap_unplug_sem);
}
@@ -276,61 +276,37 @@ void swap_free(swp_entry_t entry)
}
/*
- * Check if we're the only user of a swap page,
- * when the page is locked.
+ * How many references to page are currently swapped out?
*/
-static int exclusive_swap_page(struct page *page)
+static inline int page_swapcount(struct page *page)
{
- int retval = 0;
- struct swap_info_struct * p;
+ int count = 0;
+ struct swap_info_struct *p;
swp_entry_t entry;
entry.val = page->private;
p = swap_info_get(entry);
if (p) {
- /* Is the only swap cache user the cache itself? */
- if (p->swap_map[swp_offset(entry)] == 1) {
- /* Recheck the page count with the swapcache lock held.. */
- write_lock_irq(&swapper_space.tree_lock);
- if (page_count(page) == 2)
- retval = 1;
- write_unlock_irq(&swapper_space.tree_lock);
- }
+ /* Subtract the 1 for the swap cache itself */
+ count = p->swap_map[swp_offset(entry)] - 1;
swap_info_put(p);
}
- return retval;
+ return count;
}
/*
* We can use this swap cache entry directly
* if there are no other references to it.
- *
- * Here "exclusive_swap_page()" does the real
- * work, but we opportunistically check whether
- * we need to get all the locks first..
*/
int can_share_swap_page(struct page *page)
{
- int retval = 0;
+ int count;
- if (!PageLocked(page))
- BUG();
- switch (page_count(page)) {
- case 3:
- if (!PagePrivate(page))
- break;
- /* Fallthrough */
- case 2:
- if (!PageSwapCache(page))
- break;
- retval = exclusive_swap_page(page);
- break;
- case 1:
- if (PageReserved(page))
- break;
- retval = 1;
- }
- return retval;
+ BUG_ON(!PageLocked(page));
+ count = page_mapcount(page);
+ if (count <= 1 && PageSwapCache(page))
+ count += page_swapcount(page);
+ return count == 1;
}
/*
@@ -529,9 +505,10 @@ static int unuse_mm(struct mm_struct *mm,
if (!down_read_trylock(&mm->mmap_sem)) {
/*
- * Our reference to the page stops try_to_unmap_one from
- * unmapping its ptes, so swapoff can make progress.
+ * Activate page so shrink_cache is unlikely to unmap its
+ * ptes while lock is dropped, so swapoff can make progress.
*/
+ activate_page(page);
unlock_page(page);
down_read(&mm->mmap_sem);
lock_page(page);
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 2bd83e5c2bb..8ff16a1eee6 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -248,31 +248,20 @@ struct vm_struct *get_vm_area(unsigned long size, unsigned long flags)
return __get_vm_area(size, flags, VMALLOC_START, VMALLOC_END);
}
-/**
- * remove_vm_area - find and remove a contingous kernel virtual area
- *
- * @addr: base address
- *
- * Search for the kernel VM area starting at @addr, and remove it.
- * This function returns the found VM area, but using it is NOT safe
- * on SMP machines.
- */
-struct vm_struct *remove_vm_area(void *addr)
+/* Caller must hold vmlist_lock */
+struct vm_struct *__remove_vm_area(void *addr)
{
struct vm_struct **p, *tmp;
- write_lock(&vmlist_lock);
for (p = &vmlist ; (tmp = *p) != NULL ;p = &tmp->next) {
if (tmp->addr == addr)
goto found;
}
- write_unlock(&vmlist_lock);
return NULL;
found:
unmap_vm_area(tmp);
*p = tmp->next;
- write_unlock(&vmlist_lock);
/*
* Remove the guard page.
@@ -281,6 +270,24 @@ found:
return tmp;
}
+/**
+ * remove_vm_area - find and remove a contingous kernel virtual area
+ *
+ * @addr: base address
+ *
+ * Search for the kernel VM area starting at @addr, and remove it.
+ * This function returns the found VM area, but using it is NOT safe
+ * on SMP machines, except for its size or flags.
+ */
+struct vm_struct *remove_vm_area(void *addr)
+{
+ struct vm_struct *v;
+ write_lock(&vmlist_lock);
+ v = __remove_vm_area(addr);
+ write_unlock(&vmlist_lock);
+ return v;
+}
+
void __vunmap(void *addr, int deallocate_pages)
{
struct vm_struct *area;
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 269eded9b45..1fa312a8db7 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -74,6 +74,9 @@ struct scan_control {
int may_writepage;
+ /* Can pages be swapped as part of reclaim? */
+ int may_swap;
+
/* This context's SWAP_CLUSTER_MAX. If freeing memory for
* suspend, we effectively ignore SWAP_CLUSTER_MAX.
* In this context, it doesn't matter that we scan the
@@ -180,17 +183,20 @@ EXPORT_SYMBOL(remove_shrinker);
* `lru_pages' represents the number of on-LRU pages in all the zones which
* are eligible for the caller's allocation attempt. It is used for balancing
* slab reclaim versus page reclaim.
+ *
+ * Returns the number of slab objects which we shrunk.
*/
static int shrink_slab(unsigned long scanned, unsigned int gfp_mask,
unsigned long lru_pages)
{
struct shrinker *shrinker;
+ int ret = 0;
if (scanned == 0)
scanned = SWAP_CLUSTER_MAX;
if (!down_read_trylock(&shrinker_rwsem))
- return 0;
+ return 1; /* Assume we'll be able to shrink next time */
list_for_each_entry(shrinker, &shrinker_list, list) {
unsigned long long delta;
@@ -209,10 +215,14 @@ static int shrink_slab(unsigned long scanned, unsigned int gfp_mask,
while (total_scan >= SHRINK_BATCH) {
long this_scan = SHRINK_BATCH;
int shrink_ret;
+ int nr_before;
+ nr_before = (*shrinker->shrinker)(0, gfp_mask);
shrink_ret = (*shrinker->shrinker)(this_scan, gfp_mask);
if (shrink_ret == -1)
break;
+ if (shrink_ret < nr_before)
+ ret += nr_before - shrink_ret;
mod_page_state(slabs_scanned, this_scan);
total_scan -= this_scan;
@@ -222,7 +232,7 @@ static int shrink_slab(unsigned long scanned, unsigned int gfp_mask,
shrinker->nr += total_scan;
}
up_read(&shrinker_rwsem);
- return 0;
+ return ret;
}
/* Called without lock on whether page is mapped, so answer is unstable */
@@ -407,7 +417,7 @@ static int shrink_list(struct list_head *page_list, struct scan_control *sc)
* Anonymous process memory has backing store?
* Try to allocate it some swap space here.
*/
- if (PageAnon(page) && !PageSwapCache(page)) {
+ if (PageAnon(page) && !PageSwapCache(page) && sc->may_swap) {
if (!add_to_swap(page))
goto activate_locked;
}
@@ -890,7 +900,9 @@ shrink_caches(struct zone **zones, struct scan_control *sc)
if (zone->all_unreclaimable && sc->priority != DEF_PRIORITY)
continue; /* Let kswapd poll it */
+ atomic_inc(&zone->reclaim_in_progress);
shrink_zone(zone, sc);
+ atomic_dec(&zone->reclaim_in_progress);
}
}
@@ -907,8 +919,7 @@ shrink_caches(struct zone **zones, struct scan_control *sc)
* holds filesystem locks which prevent writeout this might not work, and the
* allocation attempt will fail.
*/
-int try_to_free_pages(struct zone **zones,
- unsigned int gfp_mask, unsigned int order)
+int try_to_free_pages(struct zone **zones, unsigned int gfp_mask)
{
int priority;
int ret = 0;
@@ -920,6 +931,7 @@ int try_to_free_pages(struct zone **zones,
sc.gfp_mask = gfp_mask;
sc.may_writepage = 0;
+ sc.may_swap = 1;
inc_page_state(allocstall);
@@ -1020,6 +1032,7 @@ loop_again:
total_reclaimed = 0;
sc.gfp_mask = GFP_KERNEL;
sc.may_writepage = 0;
+ sc.may_swap = 1;
sc.nr_mapped = read_page_state(nr_mapped);
inc_page_state(pageoutrun);
@@ -1079,6 +1092,7 @@ scan:
*/
for (i = 0; i <= end_zone; i++) {
struct zone *zone = pgdat->node_zones + i;
+ int nr_slab;
if (zone->present_pages == 0)
continue;
@@ -1098,16 +1112,19 @@ scan:
sc.nr_reclaimed = 0;
sc.priority = priority;
sc.swap_cluster_max = nr_pages? nr_pages : SWAP_CLUSTER_MAX;
+ atomic_inc(&zone->reclaim_in_progress);
shrink_zone(zone, &sc);
+ atomic_dec(&zone->reclaim_in_progress);
reclaim_state->reclaimed_slab = 0;
- shrink_slab(sc.nr_scanned, GFP_KERNEL, lru_pages);
+ nr_slab = shrink_slab(sc.nr_scanned, GFP_KERNEL,
+ lru_pages);
sc.nr_reclaimed += reclaim_state->reclaimed_slab;
total_reclaimed += sc.nr_reclaimed;
total_scanned += sc.nr_scanned;
if (zone->all_unreclaimable)
continue;
- if (zone->pages_scanned >= (zone->nr_active +
- zone->nr_inactive) * 4)
+ if (nr_slab == 0 && zone->pages_scanned >=
+ (zone->nr_active + zone->nr_inactive) * 4)
zone->all_unreclaimable = 1;
/*
* If we've done a decent amount of scanning and
@@ -1199,8 +1216,8 @@ static int kswapd(void *p)
order = 0;
for ( ; ; ) {
unsigned long new_order;
- if (current->flags & PF_FREEZE)
- refrigerator(PF_FREEZE);
+
+ try_to_freeze();
prepare_to_wait(&pgdat->kswapd_wait, &wait, TASK_INTERRUPTIBLE);
new_order = pgdat->kswapd_max_order;
@@ -1309,3 +1326,73 @@ static int __init kswapd_init(void)
}
module_init(kswapd_init)
+
+
+/*
+ * Try to free up some pages from this zone through reclaim.
+ */
+int zone_reclaim(struct zone *zone, unsigned int gfp_mask, unsigned int order)
+{
+ struct scan_control sc;
+ int nr_pages = 1 << order;
+ int total_reclaimed = 0;
+
+ /* The reclaim may sleep, so don't do it if sleep isn't allowed */
+ if (!(gfp_mask & __GFP_WAIT))
+ return 0;
+ if (zone->all_unreclaimable)
+ return 0;
+
+ sc.gfp_mask = gfp_mask;
+ sc.may_writepage = 0;
+ sc.may_swap = 0;
+ sc.nr_mapped = read_page_state(nr_mapped);
+ sc.nr_scanned = 0;
+ sc.nr_reclaimed = 0;
+ /* scan at the highest priority */
+ sc.priority = 0;
+
+ if (nr_pages > SWAP_CLUSTER_MAX)
+ sc.swap_cluster_max = nr_pages;
+ else
+ sc.swap_cluster_max = SWAP_CLUSTER_MAX;
+
+ /* Don't reclaim the zone if there are other reclaimers active */
+ if (!atomic_inc_and_test(&zone->reclaim_in_progress))
+ goto out;
+
+ shrink_zone(zone, &sc);
+ total_reclaimed = sc.nr_reclaimed;
+
+ out:
+ atomic_dec(&zone->reclaim_in_progress);
+ return total_reclaimed;
+}
+
+asmlinkage long sys_set_zone_reclaim(unsigned int node, unsigned int zone,
+ unsigned int state)
+{
+ struct zone *z;
+ int i;
+
+ if (node >= MAX_NUMNODES || !node_online(node))
+ return -EINVAL;
+
+ /* This will break if we ever add more zones */
+ if (!(zone & (1<<ZONE_DMA|1<<ZONE_NORMAL|1<<ZONE_HIGHMEM)))
+ return -EINVAL;
+
+ for (i = 0; i < MAX_NR_ZONES; i++) {
+ if (!(zone & 1<<i))
+ continue;
+
+ z = &NODE_DATA(node)->node_zones[i];
+
+ if (state)
+ z->reclaim_pages = 1;
+ else
+ z->reclaim_pages = 0;
+ }
+
+ return 0;
+}
diff --git a/net/802/tr.c b/net/802/tr.c
index 85293ccf7ef..a755e880f4b 100644
--- a/net/802/tr.c
+++ b/net/802/tr.c
@@ -47,12 +47,12 @@ static void rif_check_expire(unsigned long dummy);
* Each RIF entry we learn is kept this way
*/
-struct rif_cache_s {
+struct rif_cache {
unsigned char addr[TR_ALEN];
int iface;
- __u16 rcf;
- __u16 rseg[8];
- struct rif_cache_s *next;
+ __be16 rcf;
+ __be16 rseg[8];
+ struct rif_cache *next;
unsigned long last_used;
unsigned char local_ring;
};
@@ -64,7 +64,7 @@ struct rif_cache_s {
* up a lot.
*/
-static struct rif_cache_s *rif_table[RIF_TABLE_SIZE];
+static struct rif_cache *rif_table[RIF_TABLE_SIZE];
static DEFINE_SPINLOCK(rif_lock);
@@ -249,7 +249,7 @@ void tr_source_route(struct sk_buff *skb,struct trh_hdr *trh,struct net_device *
{
int slack;
unsigned int hash;
- struct rif_cache_s *entry;
+ struct rif_cache *entry;
unsigned char *olddata;
static const unsigned char mcast_func_addr[]
= {0xC0,0x00,0x00,0x04,0x00,0x00};
@@ -337,7 +337,7 @@ printk("source routing for %02X:%02X:%02X:%02X:%02X:%02X\n",trh->daddr[0],
static void tr_add_rif_info(struct trh_hdr *trh, struct net_device *dev)
{
unsigned int hash, rii_p = 0;
- struct rif_cache_s *entry;
+ struct rif_cache *entry;
spin_lock_bh(&rif_lock);
@@ -373,7 +373,7 @@ printk("adding rif_entry: addr:%02X:%02X:%02X:%02X:%02X:%02X rcf:%04X\n",
* FIXME: We ought to keep some kind of cache size
* limiting and adjust the timers to suit.
*/
- entry=kmalloc(sizeof(struct rif_cache_s),GFP_ATOMIC);
+ entry=kmalloc(sizeof(struct rif_cache),GFP_ATOMIC);
if(!entry)
{
@@ -435,7 +435,7 @@ static void rif_check_expire(unsigned long dummy)
spin_lock_bh(&rif_lock);
for(i =0; i < RIF_TABLE_SIZE; i++) {
- struct rif_cache_s *entry, **pentry;
+ struct rif_cache *entry, **pentry;
pentry = rif_table+i;
while((entry=*pentry) != NULL) {
@@ -467,10 +467,10 @@ static void rif_check_expire(unsigned long dummy)
#ifdef CONFIG_PROC_FS
-static struct rif_cache_s *rif_get_idx(loff_t pos)
+static struct rif_cache *rif_get_idx(loff_t pos)
{
int i;
- struct rif_cache_s *entry;
+ struct rif_cache *entry;
loff_t off = 0;
for(i = 0; i < RIF_TABLE_SIZE; i++)
@@ -493,7 +493,7 @@ static void *rif_seq_start(struct seq_file *seq, loff_t *pos)
static void *rif_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
int i;
- struct rif_cache_s *ent = v;
+ struct rif_cache *ent = v;
++*pos;
@@ -522,7 +522,7 @@ static void rif_seq_stop(struct seq_file *seq, void *v)
static int rif_seq_show(struct seq_file *seq, void *v)
{
int j, rcf_len, segment, brdgnmb;
- struct rif_cache_s *entry = v;
+ struct rif_cache *entry = v;
if (v == SEQ_START_TOKEN)
seq_puts(seq,
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c
index 54640c01b50..c34614ea5fc 100644
--- a/net/appletalk/aarp.c
+++ b/net/appletalk/aarp.c
@@ -35,6 +35,7 @@
#include <net/datalink.h>
#include <net/psnap.h>
#include <linux/atalk.h>
+#include <linux/delay.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
@@ -462,8 +463,7 @@ void aarp_probe_network(struct atalk_iface *atif)
aarp_send_probe(atif->dev, &atif->address);
/* Defer 1/10th */
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(HZ / 10);
+ msleep(100);
if (atif->status & ATIF_PROBE_FAIL)
break;
@@ -510,9 +510,8 @@ int aarp_proxy_probe_network(struct atalk_iface *atif, struct atalk_addr *sa)
aarp_send_probe(atif->dev, sa);
/* Defer 1/10th */
- current->state = TASK_INTERRUPTIBLE;
write_unlock_bh(&aarp_lock);
- schedule_timeout(HZ / 10);
+ msleep(100);
write_lock_bh(&aarp_lock);
if (entry->status & ATIF_PROBE_FAIL)
@@ -565,7 +564,7 @@ int aarp_send_ddp(struct net_device *dev, struct sk_buff *skb,
* numbers we just happen to need. Now put the
* length in the lower two.
*/
- *((__u16 *)skb->data) = htons(skb->len);
+ *((__be16 *)skb->data) = htons(skb->len);
ft = 1;
}
/*
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 876dbac7106..192b529f86a 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -401,7 +401,7 @@ out_err:
}
/* Find a match for a specific network:node pair */
-static struct atalk_iface *atalk_find_interface(int net, int node)
+static struct atalk_iface *atalk_find_interface(__be16 net, int node)
{
struct atalk_iface *iface;
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index d9b72fde433..f564ee99782 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -21,10 +21,7 @@
static struct net_device_stats *br_dev_get_stats(struct net_device *dev)
{
- struct net_bridge *br;
-
- br = dev->priv;
-
+ struct net_bridge *br = netdev_priv(dev);
return &br->statistics;
}
@@ -54,9 +51,11 @@ int br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
static int br_dev_open(struct net_device *dev)
{
- netif_start_queue(dev);
+ struct net_bridge *br = netdev_priv(dev);
- br_stp_enable_bridge(dev->priv);
+ br_features_recompute(br);
+ netif_start_queue(dev);
+ br_stp_enable_bridge(br);
return 0;
}
@@ -67,7 +66,7 @@ static void br_dev_set_multicast_list(struct net_device *dev)
static int br_dev_stop(struct net_device *dev)
{
- br_stp_disable_bridge(dev->priv);
+ br_stp_disable_bridge(netdev_priv(dev));
netif_stop_queue(dev);
@@ -76,7 +75,7 @@ static int br_dev_stop(struct net_device *dev)
static int br_change_mtu(struct net_device *dev, int new_mtu)
{
- if ((new_mtu < 68) || new_mtu > br_min_mtu(dev->priv))
+ if (new_mtu < 68 || new_mtu > br_min_mtu(netdev_priv(dev)))
return -EINVAL;
dev->mtu = new_mtu;
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index ef9f2095f96..069253f830c 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -57,9 +57,6 @@ int br_forward_finish(struct sk_buff *skb)
static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
{
skb->dev = to->dev;
-#ifdef CONFIG_NETFILTER_DEBUG
- skb->nf_debug = 0;
-#endif
NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
br_forward_finish);
}
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 69872bf3b87..91bb895375f 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -314,6 +314,28 @@ int br_min_mtu(const struct net_bridge *br)
return mtu;
}
+/*
+ * Recomputes features using slave's features
+ */
+void br_features_recompute(struct net_bridge *br)
+{
+ struct net_bridge_port *p;
+ unsigned long features, checksum;
+
+ features = NETIF_F_SG | NETIF_F_FRAGLIST
+ | NETIF_F_HIGHDMA | NETIF_F_TSO;
+ checksum = NETIF_F_IP_CSUM; /* least commmon subset */
+
+ list_for_each_entry(p, &br->port_list, list) {
+ if (!(p->dev->features
+ & (NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM)))
+ checksum = 0;
+ features &= p->dev->features;
+ }
+
+ br->dev->features = features | checksum | NETIF_F_LLTX;
+}
+
/* called with RTNL */
int br_add_if(struct net_bridge *br, struct net_device *dev)
{
@@ -368,6 +390,7 @@ int br_del_if(struct net_bridge *br, struct net_device *dev)
spin_lock_bh(&br->lock);
br_stp_recalculate_bridge_id(br);
+ br_features_recompute(br);
spin_unlock_bh(&br->lock);
return 0;
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 2b1cce46cab..9a45e6279c5 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -23,11 +23,7 @@ const unsigned char bridge_ula[6] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
static int br_pass_frame_up_finish(struct sk_buff *skb)
{
-#ifdef CONFIG_NETFILTER_DEBUG
- skb->nf_debug = 0;
-#endif
- netif_rx(skb);
-
+ netif_receive_skb(skb);
return 0;
}
@@ -54,6 +50,9 @@ int br_handle_frame_finish(struct sk_buff *skb)
struct net_bridge_fdb_entry *dst;
int passedup = 0;
+ /* insert into forwarding database after filtering to avoid spoofing */
+ br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
+
if (br->dev->flags & IFF_PROMISC) {
struct sk_buff *skb2;
@@ -108,8 +107,7 @@ int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb)
if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
goto err;
- if (p->state == BR_STATE_LEARNING ||
- p->state == BR_STATE_FORWARDING)
+ if (p->state == BR_STATE_LEARNING)
br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
if (p->br->stp_enabled &&
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index be03d3ad264..03ae4edddac 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -102,10 +102,6 @@ static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb)
{
struct nf_bridge_info *nf_bridge = skb->nf_bridge;
-#ifdef CONFIG_NETFILTER_DEBUG
- skb->nf_debug ^= (1 << NF_BR_PRE_ROUTING);
-#endif
-
if (nf_bridge->mask & BRNF_PKT_TYPE) {
skb->pkt_type = PACKET_OTHERHOST;
nf_bridge->mask ^= BRNF_PKT_TYPE;
@@ -182,10 +178,6 @@ static void __br_dnat_complain(void)
* --Bart, 20021007 (updated) */
static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb)
{
-#ifdef CONFIG_NETFILTER_DEBUG
- skb->nf_debug |= (1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_FORWARD);
-#endif
-
if (skb->pkt_type == PACKET_OTHERHOST) {
skb->pkt_type = PACKET_HOST;
skb->nf_bridge->mask |= BRNF_PKT_TYPE;
@@ -207,10 +199,6 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb)
struct iphdr *iph = skb->nh.iph;
struct nf_bridge_info *nf_bridge = skb->nf_bridge;
-#ifdef CONFIG_NETFILTER_DEBUG
- skb->nf_debug ^= (1 << NF_BR_PRE_ROUTING);
-#endif
-
if (nf_bridge->mask & BRNF_PKT_TYPE) {
skb->pkt_type = PACKET_OTHERHOST;
nf_bridge->mask ^= BRNF_PKT_TYPE;
@@ -382,9 +370,6 @@ static unsigned int br_nf_pre_routing_ipv6(unsigned int hook,
if (hdr->nexthdr == NEXTHDR_HOP && check_hbh_len(skb))
goto inhdr_error;
-#ifdef CONFIG_NETFILTER_DEBUG
- skb->nf_debug ^= (1 << NF_IP6_PRE_ROUTING);
-#endif
if ((nf_bridge = nf_bridge_alloc(skb)) == NULL)
return NF_DROP;
setup_pre_routing(skb);
@@ -468,9 +453,6 @@ static unsigned int br_nf_pre_routing(unsigned int hook, struct sk_buff **pskb,
skb->ip_summed = CHECKSUM_NONE;
}
-#ifdef CONFIG_NETFILTER_DEBUG
- skb->nf_debug ^= (1 << NF_IP_PRE_ROUTING);
-#endif
if ((nf_bridge = nf_bridge_alloc(skb)) == NULL)
return NF_DROP;
setup_pre_routing(skb);
@@ -517,10 +499,6 @@ static int br_nf_forward_finish(struct sk_buff *skb)
struct net_device *in;
struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
-#ifdef CONFIG_NETFILTER_DEBUG
- skb->nf_debug ^= (1 << NF_BR_FORWARD);
-#endif
-
if (skb->protocol != __constant_htons(ETH_P_ARP) && !IS_VLAN_ARP) {
in = nf_bridge->physindev;
if (nf_bridge->mask & BRNF_PKT_TYPE) {
@@ -566,9 +544,6 @@ static unsigned int br_nf_forward_ip(unsigned int hook, struct sk_buff **pskb,
(*pskb)->nh.raw += VLAN_HLEN;
}
-#ifdef CONFIG_NETFILTER_DEBUG
- skb->nf_debug ^= (1 << NF_BR_FORWARD);
-#endif
nf_bridge = skb->nf_bridge;
if (skb->pkt_type == PACKET_OTHERHOST) {
skb->pkt_type = PACKET_HOST;
@@ -605,10 +580,6 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb,
(*pskb)->nh.raw += VLAN_HLEN;
}
-#ifdef CONFIG_NETFILTER_DEBUG
- skb->nf_debug ^= (1 << NF_BR_FORWARD);
-#endif
-
if (skb->nh.arph->ar_pln != 4) {
if (IS_VLAN_ARP) {
skb_push(*pskb, VLAN_HLEN);
@@ -627,9 +598,6 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff **pskb,
/* PF_BRIDGE/LOCAL_OUT ***********************************************/
static int br_nf_local_out_finish(struct sk_buff *skb)
{
-#ifdef CONFIG_NETFILTER_DEBUG
- skb->nf_debug &= ~(1 << NF_BR_LOCAL_OUT);
-#endif
if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
skb_push(skb, VLAN_HLEN);
skb->nh.raw -= VLAN_HLEN;
@@ -731,10 +699,6 @@ static unsigned int br_nf_local_out(unsigned int hook, struct sk_buff **pskb,
realoutdev, br_nf_local_out_finish,
NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD + 1);
} else {
-#ifdef CONFIG_NETFILTER_DEBUG
- skb->nf_debug ^= (1 << NF_IP_LOCAL_OUT);
-#endif
-
NF_HOOK_THRESH(pf, NF_IP_LOCAL_OUT, skb, realindev,
realoutdev, br_nf_local_out_finish,
NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT + 1);
@@ -779,8 +743,6 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff **pskb,
printk(KERN_CRIT "br_netfilter: skb->dst == NULL.");
goto print_error;
}
-
- skb->nf_debug ^= (1 << NF_IP_POST_ROUTING);
#endif
/* We assume any code from br_dev_queue_push_xmit onwards doesn't care
diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c
index f8fb49e3476..917311c6828 100644
--- a/net/bridge/br_notify.c
+++ b/net/bridge/br_notify.c
@@ -65,6 +65,15 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
}
break;
+ case NETDEV_FEAT_CHANGE:
+ if (br->dev->flags & IFF_UP)
+ br_features_recompute(br);
+
+ /* could do recursive feature change notification
+ * but who would care??
+ */
+ break;
+
case NETDEV_DOWN:
if (br->dev->flags & IFF_UP)
br_stp_disable_port(p);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 54d63f1372a..bdf95a74d8c 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -174,6 +174,7 @@ extern int br_add_if(struct net_bridge *br,
extern int br_del_if(struct net_bridge *br,
struct net_device *dev);
extern int br_min_mtu(const struct net_bridge *br);
+extern void br_features_recompute(struct net_bridge *br);
/* br_input.c */
extern int br_handle_frame_finish(struct sk_buff *skb);
diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c
index b91a875aca0..d071f1c9ad0 100644
--- a/net/bridge/br_stp_bpdu.c
+++ b/net/bridge/br_stp_bpdu.c
@@ -140,6 +140,9 @@ int br_stp_handle_bpdu(struct sk_buff *skb)
struct net_bridge *br = p->br;
unsigned char *buf;
+ /* insert into forwarding database after filtering to avoid spoofing */
+ br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
+
/* need at least the 802 and STP headers */
if (!pskb_may_pull(skb, sizeof(header)+1) ||
memcmp(skb->data, header, sizeof(header)))
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 18ebc664769..c4540144f0f 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -859,8 +859,7 @@ static int translate_table(struct ebt_replace *repl,
if (repl->valid_hooks & (1 << i))
if (check_chainloops(newinfo->hook_entry[i],
cl_s, udc_cnt, i, newinfo->entries)) {
- if (cl_s)
- vfree(cl_s);
+ vfree(cl_s);
return -EINVAL;
}
@@ -883,8 +882,7 @@ static int translate_table(struct ebt_replace *repl,
EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
ebt_cleanup_entry, &i);
}
- if (cl_s)
- vfree(cl_s);
+ vfree(cl_s);
return ret;
}
@@ -1030,8 +1028,7 @@ static int do_replace(void __user *user, unsigned int len)
}
vfree(table);
- if (counterstmp)
- vfree(counterstmp);
+ vfree(counterstmp);
return ret;
free_unlock:
@@ -1040,8 +1037,7 @@ free_iterate:
EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
ebt_cleanup_entry, NULL);
free_counterstmp:
- if (counterstmp)
- vfree(counterstmp);
+ vfree(counterstmp);
/* can be initialized in translate_table() */
if (newinfo->chainstack) {
for (i = 0; i < num_possible_cpus(); i++)
@@ -1049,11 +1045,9 @@ free_counterstmp:
vfree(newinfo->chainstack);
}
free_entries:
- if (newinfo->entries)
- vfree(newinfo->entries);
+ vfree(newinfo->entries);
free_newinfo:
- if (newinfo)
- vfree(newinfo);
+ vfree(newinfo);
return ret;
}
@@ -1213,8 +1207,7 @@ void ebt_unregister_table(struct ebt_table *table)
down(&ebt_mutex);
LIST_DELETE(&ebt_tables, table);
up(&ebt_mutex);
- if (table->private->entries)
- vfree(table->private->entries);
+ vfree(table->private->entries);
if (table->private->chainstack) {
for (i = 0; i < num_possible_cpus(); i++)
vfree(table->private->chainstack[i]);
diff --git a/net/core/Makefile b/net/core/Makefile
index 81f03243fe2..5e0c56b7f60 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -2,7 +2,8 @@
# Makefile for the Linux networking core.
#
-obj-y := sock.o skbuff.o iovec.o datagram.o stream.o scm.o gen_stats.o gen_estimator.o
+obj-y := sock.o request_sock.o skbuff.o iovec.o datagram.o stream.o scm.o \
+ gen_stats.o gen_estimator.o
obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
diff --git a/net/core/dev.c b/net/core/dev.c
index d4d9e2680ad..7016e0c36b3 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -115,18 +115,6 @@
#endif /* CONFIG_NET_RADIO */
#include <asm/current.h>
-/* This define, if set, will randomly drop a packet when congestion
- * is more than moderate. It helps fairness in the multi-interface
- * case when one of them is a hog, but it kills performance for the
- * single interface case so it is off now by default.
- */
-#undef RAND_LIE
-
-/* Setting this will sample the queue lengths and thus congestion
- * via a timer instead of as each packet is received.
- */
-#undef OFFLINE_SAMPLE
-
/*
* The list of packet types we will receive (as opposed to discard)
* and the routines to invoke.
@@ -159,11 +147,6 @@ static DEFINE_SPINLOCK(ptype_lock);
static struct list_head ptype_base[16]; /* 16 way hashed list */
static struct list_head ptype_all; /* Taps */
-#ifdef OFFLINE_SAMPLE
-static void sample_queue(unsigned long dummy);
-static struct timer_list samp_timer = TIMER_INITIALIZER(sample_queue, 0, 0);
-#endif
-
/*
* The @dev_base list is protected by @dev_base_lock and the rtln
* semaphore.
@@ -215,7 +198,7 @@ static struct notifier_block *netdev_chain;
* Device drivers call our routines to queue packets here. We empty the
* queue in the local softnet handler.
*/
-DEFINE_PER_CPU(struct softnet_data, softnet_data) = { 0, };
+DEFINE_PER_CPU(struct softnet_data, softnet_data) = { NULL };
#ifdef CONFIG_SYSFS
extern int netdev_sysfs_init(void);
@@ -761,6 +744,18 @@ int dev_change_name(struct net_device *dev, char *newname)
}
/**
+ * netdev_features_change - device changes fatures
+ * @dev: device to cause notification
+ *
+ * Called to indicate a device has changed features.
+ */
+void netdev_features_change(struct net_device *dev)
+{
+ notifier_call_chain(&netdev_chain, NETDEV_FEAT_CHANGE, dev);
+}
+EXPORT_SYMBOL(netdev_features_change);
+
+/**
* netdev_state_change - device changes state
* @dev: device to cause notification
*
@@ -1351,71 +1346,13 @@ out:
Receiver routines
=======================================================================*/
-int netdev_max_backlog = 300;
+int netdev_max_backlog = 1000;
+int netdev_budget = 300;
int weight_p = 64; /* old backlog weight */
-/* These numbers are selected based on intuition and some
- * experimentatiom, if you have more scientific way of doing this
- * please go ahead and fix things.
- */
-int no_cong_thresh = 10;
-int no_cong = 20;
-int lo_cong = 100;
-int mod_cong = 290;
DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, };
-static void get_sample_stats(int cpu)
-{
-#ifdef RAND_LIE
- unsigned long rd;
- int rq;
-#endif
- struct softnet_data *sd = &per_cpu(softnet_data, cpu);
- int blog = sd->input_pkt_queue.qlen;
- int avg_blog = sd->avg_blog;
-
- avg_blog = (avg_blog >> 1) + (blog >> 1);
-
- if (avg_blog > mod_cong) {
- /* Above moderate congestion levels. */
- sd->cng_level = NET_RX_CN_HIGH;
-#ifdef RAND_LIE
- rd = net_random();
- rq = rd % netdev_max_backlog;
- if (rq < avg_blog) /* unlucky bastard */
- sd->cng_level = NET_RX_DROP;
-#endif
- } else if (avg_blog > lo_cong) {
- sd->cng_level = NET_RX_CN_MOD;
-#ifdef RAND_LIE
- rd = net_random();
- rq = rd % netdev_max_backlog;
- if (rq < avg_blog) /* unlucky bastard */
- sd->cng_level = NET_RX_CN_HIGH;
-#endif
- } else if (avg_blog > no_cong)
- sd->cng_level = NET_RX_CN_LOW;
- else /* no congestion */
- sd->cng_level = NET_RX_SUCCESS;
-
- sd->avg_blog = avg_blog;
-}
-
-#ifdef OFFLINE_SAMPLE
-static void sample_queue(unsigned long dummy)
-{
-/* 10 ms 0r 1ms -- i don't care -- JHS */
- int next_tick = 1;
- int cpu = smp_processor_id();
-
- get_sample_stats(cpu);
- next_tick += jiffies;
- mod_timer(&samp_timer, next_tick);
-}
-#endif
-
-
/**
* netif_rx - post buffer to the network code
* @skb: buffer to post
@@ -1436,7 +1373,6 @@ static void sample_queue(unsigned long dummy)
int netif_rx(struct sk_buff *skb)
{
- int this_cpu;
struct softnet_data *queue;
unsigned long flags;
@@ -1452,38 +1388,22 @@ int netif_rx(struct sk_buff *skb)
* short when CPU is congested, but is still operating.
*/
local_irq_save(flags);
- this_cpu = smp_processor_id();
queue = &__get_cpu_var(softnet_data);
__get_cpu_var(netdev_rx_stat).total++;
if (queue->input_pkt_queue.qlen <= netdev_max_backlog) {
if (queue->input_pkt_queue.qlen) {
- if (queue->throttle)
- goto drop;
-
enqueue:
dev_hold(skb->dev);
__skb_queue_tail(&queue->input_pkt_queue, skb);
-#ifndef OFFLINE_SAMPLE
- get_sample_stats(this_cpu);
-#endif
local_irq_restore(flags);
- return queue->cng_level;
+ return NET_RX_SUCCESS;
}
- if (queue->throttle)
- queue->throttle = 0;
-
netif_rx_schedule(&queue->backlog_dev);
goto enqueue;
}
- if (!queue->throttle) {
- queue->throttle = 1;
- __get_cpu_var(netdev_rx_stat).throttled++;
- }
-
-drop:
__get_cpu_var(netdev_rx_stat).dropped++;
local_irq_restore(flags);
@@ -1732,6 +1652,7 @@ static int process_backlog(struct net_device *backlog_dev, int *budget)
struct softnet_data *queue = &__get_cpu_var(softnet_data);
unsigned long start_time = jiffies;
+ backlog_dev->weight = weight_p;
for (;;) {
struct sk_buff *skb;
struct net_device *dev;
@@ -1767,8 +1688,6 @@ job_done:
smp_mb__before_clear_bit();
netif_poll_enable(backlog_dev);
- if (queue->throttle)
- queue->throttle = 0;
local_irq_enable();
return 0;
}
@@ -1777,8 +1696,7 @@ static void net_rx_action(struct softirq_action *h)
{
struct softnet_data *queue = &__get_cpu_var(softnet_data);
unsigned long start_time = jiffies;
- int budget = netdev_max_backlog;
-
+ int budget = netdev_budget;
local_irq_disable();
@@ -2042,15 +1960,9 @@ static int softnet_seq_show(struct seq_file *seq, void *v)
struct netif_rx_stats *s = v;
seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x %08x\n",
- s->total, s->dropped, s->time_squeeze, s->throttled,
- s->fastroute_hit, s->fastroute_success, s->fastroute_defer,
- s->fastroute_deferred_out,
-#if 0
- s->fastroute_latency_reduction
-#else
- s->cpu_collision
-#endif
- );
+ s->total, s->dropped, s->time_squeeze, 0,
+ 0, 0, 0, 0, /* was fastroute */
+ s->cpu_collision );
return 0;
}
@@ -3292,9 +3204,6 @@ static int __init net_dev_init(void)
queue = &per_cpu(softnet_data, i);
skb_queue_head_init(&queue->input_pkt_queue);
- queue->throttle = 0;
- queue->cng_level = 0;
- queue->avg_blog = 10; /* arbitrary non-zero */
queue->completion_queue = NULL;
INIT_LIST_HEAD(&queue->poll_list);
set_bit(__LINK_STATE_START, &queue->backlog_dev.state);
@@ -3303,11 +3212,6 @@ static int __init net_dev_init(void)
atomic_set(&queue->backlog_dev.refcnt, 1);
}
-#ifdef OFFLINE_SAMPLE
- samp_timer.expires = jiffies + (10 * HZ);
- add_timer(&samp_timer);
-#endif
-
dev_boot_phase = 0;
open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL);
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index f05fde97c43..a3eeb88e1c8 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -29,7 +29,7 @@ u32 ethtool_op_get_link(struct net_device *dev)
u32 ethtool_op_get_tx_csum(struct net_device *dev)
{
- return (dev->features & NETIF_F_IP_CSUM) != 0;
+ return (dev->features & (NETIF_F_IP_CSUM | NETIF_F_HW_CSUM)) != 0;
}
int ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
@@ -42,6 +42,15 @@ int ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
return 0;
}
+int ethtool_op_set_tx_hw_csum(struct net_device *dev, u32 data)
+{
+ if (data)
+ dev->features |= NETIF_F_HW_CSUM;
+ else
+ dev->features &= ~NETIF_F_HW_CSUM;
+
+ return 0;
+}
u32 ethtool_op_get_sg(struct net_device *dev)
{
return (dev->features & NETIF_F_SG) != 0;
@@ -347,7 +356,7 @@ static int ethtool_set_coalesce(struct net_device *dev, void __user *useraddr)
{
struct ethtool_coalesce coalesce;
- if (!dev->ethtool_ops->get_coalesce)
+ if (!dev->ethtool_ops->set_coalesce)
return -EOPNOTSUPP;
if (copy_from_user(&coalesce, useraddr, sizeof(coalesce)))
@@ -682,6 +691,7 @@ int dev_ethtool(struct ifreq *ifr)
void __user *useraddr = ifr->ifr_data;
u32 ethcmd;
int rc;
+ unsigned long old_features;
/*
* XXX: This can be pushed down into the ethtool_* handlers that
@@ -703,6 +713,8 @@ int dev_ethtool(struct ifreq *ifr)
if ((rc = dev->ethtool_ops->begin(dev)) < 0)
return rc;
+ old_features = dev->features;
+
switch (ethcmd) {
case ETHTOOL_GSET:
rc = ethtool_get_settings(dev, useraddr);
@@ -712,7 +724,6 @@ int dev_ethtool(struct ifreq *ifr)
break;
case ETHTOOL_GDRVINFO:
rc = ethtool_get_drvinfo(dev, useraddr);
-
break;
case ETHTOOL_GREGS:
rc = ethtool_get_regs(dev, useraddr);
@@ -801,6 +812,10 @@ int dev_ethtool(struct ifreq *ifr)
if(dev->ethtool_ops->complete)
dev->ethtool_ops->complete(dev);
+
+ if (old_features != dev->features)
+ netdev_features_change(dev);
+
return rc;
ioctl:
@@ -817,3 +832,4 @@ EXPORT_SYMBOL(ethtool_op_get_tx_csum);
EXPORT_SYMBOL(ethtool_op_set_sg);
EXPORT_SYMBOL(ethtool_op_set_tso);
EXPORT_SYMBOL(ethtool_op_set_tx_csum);
+EXPORT_SYMBOL(ethtool_op_set_tx_hw_csum);
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 43bdc521e20..851eb927ed9 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -32,6 +32,7 @@
#include <net/sock.h>
#include <linux/rtnetlink.h>
#include <linux/random.h>
+#include <linux/string.h>
#define NEIGH_DEBUG 1
@@ -1276,9 +1277,14 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
INIT_RCU_HEAD(&p->rcu_head);
p->reachable_time =
neigh_rand_reach_time(p->base_reachable_time);
- if (dev && dev->neigh_setup && dev->neigh_setup(dev, p)) {
- kfree(p);
- return NULL;
+ if (dev) {
+ if (dev->neigh_setup && dev->neigh_setup(dev, p)) {
+ kfree(p);
+ return NULL;
+ }
+
+ dev_hold(dev);
+ p->dev = dev;
}
p->sysctl_table = NULL;
write_lock_bh(&tbl->lock);
@@ -1309,6 +1315,8 @@ void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
*p = parms->next;
parms->dead = 1;
write_unlock_bh(&tbl->lock);
+ if (parms->dev)
+ dev_put(parms->dev);
call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
return;
}
@@ -1546,20 +1554,323 @@ out:
return err;
}
+static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
+{
+ struct rtattr *nest = NULL;
+
+ nest = RTA_NEST(skb, NDTA_PARMS);
+
+ if (parms->dev)
+ RTA_PUT_U32(skb, NDTPA_IFINDEX, parms->dev->ifindex);
+
+ RTA_PUT_U32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt));
+ RTA_PUT_U32(skb, NDTPA_QUEUE_LEN, parms->queue_len);
+ RTA_PUT_U32(skb, NDTPA_PROXY_QLEN, parms->proxy_qlen);
+ RTA_PUT_U32(skb, NDTPA_APP_PROBES, parms->app_probes);
+ RTA_PUT_U32(skb, NDTPA_UCAST_PROBES, parms->ucast_probes);
+ RTA_PUT_U32(skb, NDTPA_MCAST_PROBES, parms->mcast_probes);
+ RTA_PUT_MSECS(skb, NDTPA_REACHABLE_TIME, parms->reachable_time);
+ RTA_PUT_MSECS(skb, NDTPA_BASE_REACHABLE_TIME,
+ parms->base_reachable_time);
+ RTA_PUT_MSECS(skb, NDTPA_GC_STALETIME, parms->gc_staletime);
+ RTA_PUT_MSECS(skb, NDTPA_DELAY_PROBE_TIME, parms->delay_probe_time);
+ RTA_PUT_MSECS(skb, NDTPA_RETRANS_TIME, parms->retrans_time);
+ RTA_PUT_MSECS(skb, NDTPA_ANYCAST_DELAY, parms->anycast_delay);
+ RTA_PUT_MSECS(skb, NDTPA_PROXY_DELAY, parms->proxy_delay);
+ RTA_PUT_MSECS(skb, NDTPA_LOCKTIME, parms->locktime);
+
+ return RTA_NEST_END(skb, nest);
+
+rtattr_failure:
+ return RTA_NEST_CANCEL(skb, nest);
+}
+
+static int neightbl_fill_info(struct neigh_table *tbl, struct sk_buff *skb,
+ struct netlink_callback *cb)
+{
+ struct nlmsghdr *nlh;
+ struct ndtmsg *ndtmsg;
+
+ nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWNEIGHTBL, sizeof(struct ndtmsg),
+ NLM_F_MULTI);
+
+ ndtmsg = NLMSG_DATA(nlh);
+
+ read_lock_bh(&tbl->lock);
+ ndtmsg->ndtm_family = tbl->family;
+
+ RTA_PUT_STRING(skb, NDTA_NAME, tbl->id);
+ RTA_PUT_MSECS(skb, NDTA_GC_INTERVAL, tbl->gc_interval);
+ RTA_PUT_U32(skb, NDTA_THRESH1, tbl->gc_thresh1);
+ RTA_PUT_U32(skb, NDTA_THRESH2, tbl->gc_thresh2);
+ RTA_PUT_U32(skb, NDTA_THRESH3, tbl->gc_thresh3);
+
+ {
+ unsigned long now = jiffies;
+ unsigned int flush_delta = now - tbl->last_flush;
+ unsigned int rand_delta = now - tbl->last_rand;
+
+ struct ndt_config ndc = {
+ .ndtc_key_len = tbl->key_len,
+ .ndtc_entry_size = tbl->entry_size,
+ .ndtc_entries = atomic_read(&tbl->entries),
+ .ndtc_last_flush = jiffies_to_msecs(flush_delta),
+ .ndtc_last_rand = jiffies_to_msecs(rand_delta),
+ .ndtc_hash_rnd = tbl->hash_rnd,
+ .ndtc_hash_mask = tbl->hash_mask,
+ .ndtc_hash_chain_gc = tbl->hash_chain_gc,
+ .ndtc_proxy_qlen = tbl->proxy_queue.qlen,
+ };
+
+ RTA_PUT(skb, NDTA_CONFIG, sizeof(ndc), &ndc);
+ }
+
+ {
+ int cpu;
+ struct ndt_stats ndst;
+
+ memset(&ndst, 0, sizeof(ndst));
+
+ for (cpu = 0; cpu < NR_CPUS; cpu++) {
+ struct neigh_statistics *st;
+
+ if (!cpu_possible(cpu))
+ continue;
+
+ st = per_cpu_ptr(tbl->stats, cpu);
+ ndst.ndts_allocs += st->allocs;
+ ndst.ndts_destroys += st->destroys;
+ ndst.ndts_hash_grows += st->hash_grows;
+ ndst.ndts_res_failed += st->res_failed;
+ ndst.ndts_lookups += st->lookups;
+ ndst.ndts_hits += st->hits;
+ ndst.ndts_rcv_probes_mcast += st->rcv_probes_mcast;
+ ndst.ndts_rcv_probes_ucast += st->rcv_probes_ucast;
+ ndst.ndts_periodic_gc_runs += st->periodic_gc_runs;
+ ndst.ndts_forced_gc_runs += st->forced_gc_runs;
+ }
+
+ RTA_PUT(skb, NDTA_STATS, sizeof(ndst), &ndst);
+ }
+
+ BUG_ON(tbl->parms.dev);
+ if (neightbl_fill_parms(skb, &tbl->parms) < 0)
+ goto rtattr_failure;
+
+ read_unlock_bh(&tbl->lock);
+ return NLMSG_END(skb, nlh);
+
+rtattr_failure:
+ read_unlock_bh(&tbl->lock);
+ return NLMSG_CANCEL(skb, nlh);
+
+nlmsg_failure:
+ return -1;
+}
+
+static int neightbl_fill_param_info(struct neigh_table *tbl,
+ struct neigh_parms *parms,
+ struct sk_buff *skb,
+ struct netlink_callback *cb)
+{
+ struct ndtmsg *ndtmsg;
+ struct nlmsghdr *nlh;
+
+ nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWNEIGHTBL, sizeof(struct ndtmsg),
+ NLM_F_MULTI);
+
+ ndtmsg = NLMSG_DATA(nlh);
+
+ read_lock_bh(&tbl->lock);
+ ndtmsg->ndtm_family = tbl->family;
+ RTA_PUT_STRING(skb, NDTA_NAME, tbl->id);
+
+ if (neightbl_fill_parms(skb, parms) < 0)
+ goto rtattr_failure;
+
+ read_unlock_bh(&tbl->lock);
+ return NLMSG_END(skb, nlh);
+
+rtattr_failure:
+ read_unlock_bh(&tbl->lock);
+ return NLMSG_CANCEL(skb, nlh);
+
+nlmsg_failure:
+ return -1;
+}
+
+static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl,
+ int ifindex)
+{
+ struct neigh_parms *p;
+
+ for (p = &tbl->parms; p; p = p->next)
+ if ((p->dev && p->dev->ifindex == ifindex) ||
+ (!p->dev && !ifindex))
+ return p;
+
+ return NULL;
+}
+
+int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+{
+ struct neigh_table *tbl;
+ struct ndtmsg *ndtmsg = NLMSG_DATA(nlh);
+ struct rtattr **tb = arg;
+ int err = -EINVAL;
+
+ if (!tb[NDTA_NAME - 1] || !RTA_PAYLOAD(tb[NDTA_NAME - 1]))
+ return -EINVAL;
+
+ read_lock(&neigh_tbl_lock);
+ for (tbl = neigh_tables; tbl; tbl = tbl->next) {
+ if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
+ continue;
+
+ if (!rtattr_strcmp(tb[NDTA_NAME - 1], tbl->id))
+ break;
+ }
+
+ if (tbl == NULL) {
+ err = -ENOENT;
+ goto errout;
+ }
+
+ /*
+ * We acquire tbl->lock to be nice to the periodic timers and
+ * make sure they always see a consistent set of values.
+ */
+ write_lock_bh(&tbl->lock);
+
+ if (tb[NDTA_THRESH1 - 1])
+ tbl->gc_thresh1 = RTA_GET_U32(tb[NDTA_THRESH1 - 1]);
+
+ if (tb[NDTA_THRESH2 - 1])
+ tbl->gc_thresh2 = RTA_GET_U32(tb[NDTA_THRESH2 - 1]);
+
+ if (tb[NDTA_THRESH3 - 1])
+ tbl->gc_thresh3 = RTA_GET_U32(tb[NDTA_THRESH3 - 1]);
+
+ if (tb[NDTA_GC_INTERVAL - 1])
+ tbl->gc_interval = RTA_GET_MSECS(tb[NDTA_GC_INTERVAL - 1]);
+
+ if (tb[NDTA_PARMS - 1]) {
+ struct rtattr *tbp[NDTPA_MAX];
+ struct neigh_parms *p;
+ u32 ifindex = 0;
+
+ if (rtattr_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS - 1]) < 0)
+ goto rtattr_failure;
+
+ if (tbp[NDTPA_IFINDEX - 1])
+ ifindex = RTA_GET_U32(tbp[NDTPA_IFINDEX - 1]);
+
+ p = lookup_neigh_params(tbl, ifindex);
+ if (p == NULL) {
+ err = -ENOENT;
+ goto rtattr_failure;
+ }
+
+ if (tbp[NDTPA_QUEUE_LEN - 1])
+ p->queue_len = RTA_GET_U32(tbp[NDTPA_QUEUE_LEN - 1]);
+
+ if (tbp[NDTPA_PROXY_QLEN - 1])
+ p->proxy_qlen = RTA_GET_U32(tbp[NDTPA_PROXY_QLEN - 1]);
+
+ if (tbp[NDTPA_APP_PROBES - 1])
+ p->app_probes = RTA_GET_U32(tbp[NDTPA_APP_PROBES - 1]);
+
+ if (tbp[NDTPA_UCAST_PROBES - 1])
+ p->ucast_probes =
+ RTA_GET_U32(tbp[NDTPA_UCAST_PROBES - 1]);
+
+ if (tbp[NDTPA_MCAST_PROBES - 1])
+ p->mcast_probes =
+ RTA_GET_U32(tbp[NDTPA_MCAST_PROBES - 1]);
+
+ if (tbp[NDTPA_BASE_REACHABLE_TIME - 1])
+ p->base_reachable_time =
+ RTA_GET_MSECS(tbp[NDTPA_BASE_REACHABLE_TIME - 1]);
+
+ if (tbp[NDTPA_GC_STALETIME - 1])
+ p->gc_staletime =
+ RTA_GET_MSECS(tbp[NDTPA_GC_STALETIME - 1]);
+
+ if (tbp[NDTPA_DELAY_PROBE_TIME - 1])
+ p->delay_probe_time =
+ RTA_GET_MSECS(tbp[NDTPA_DELAY_PROBE_TIME - 1]);
+
+ if (tbp[NDTPA_RETRANS_TIME - 1])
+ p->retrans_time =
+ RTA_GET_MSECS(tbp[NDTPA_RETRANS_TIME - 1]);
+
+ if (tbp[NDTPA_ANYCAST_DELAY - 1])
+ p->anycast_delay =
+ RTA_GET_MSECS(tbp[NDTPA_ANYCAST_DELAY - 1]);
+
+ if (tbp[NDTPA_PROXY_DELAY - 1])
+ p->proxy_delay =
+ RTA_GET_MSECS(tbp[NDTPA_PROXY_DELAY - 1]);
+
+ if (tbp[NDTPA_LOCKTIME - 1])
+ p->locktime = RTA_GET_MSECS(tbp[NDTPA_LOCKTIME - 1]);
+ }
+
+ err = 0;
+
+rtattr_failure:
+ write_unlock_bh(&tbl->lock);
+errout:
+ read_unlock(&neigh_tbl_lock);
+ return err;
+}
+
+int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ int idx, family;
+ int s_idx = cb->args[0];
+ struct neigh_table *tbl;
+
+ family = ((struct rtgenmsg *)NLMSG_DATA(cb->nlh))->rtgen_family;
+
+ read_lock(&neigh_tbl_lock);
+ for (tbl = neigh_tables, idx = 0; tbl; tbl = tbl->next) {
+ struct neigh_parms *p;
+
+ if (idx < s_idx || (family && tbl->family != family))
+ continue;
+
+ if (neightbl_fill_info(tbl, skb, cb) <= 0)
+ break;
+
+ for (++idx, p = tbl->parms.next; p; p = p->next, idx++) {
+ if (idx < s_idx)
+ continue;
+
+ if (neightbl_fill_param_info(tbl, p, skb, cb) <= 0)
+ goto out;
+ }
+
+ }
+out:
+ read_unlock(&neigh_tbl_lock);
+ cb->args[0] = idx;
+
+ return skb->len;
+}
static int neigh_fill_info(struct sk_buff *skb, struct neighbour *n,
- u32 pid, u32 seq, int event)
+ u32 pid, u32 seq, int event, unsigned int flags)
{
unsigned long now = jiffies;
unsigned char *b = skb->tail;
struct nda_cacheinfo ci;
int locked = 0;
u32 probes;
- struct nlmsghdr *nlh = NLMSG_PUT(skb, pid, seq, event,
- sizeof(struct ndmsg));
+ struct nlmsghdr *nlh = NLMSG_NEW(skb, pid, seq, event,
+ sizeof(struct ndmsg), flags);
struct ndmsg *ndm = NLMSG_DATA(nlh);
- nlh->nlmsg_flags = pid ? NLM_F_MULTI : 0;
ndm->ndm_family = n->ops->family;
ndm->ndm_flags = n->flags;
ndm->ndm_type = n->type;
@@ -1609,7 +1920,8 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
continue;
if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq,
- RTM_NEWNEIGH) <= 0) {
+ RTM_NEWNEIGH,
+ NLM_F_MULTI) <= 0) {
read_unlock_bh(&tbl->lock);
rc = -1;
goto out;
@@ -2018,7 +2330,7 @@ void neigh_app_ns(struct neighbour *n)
if (!skb)
return;
- if (neigh_fill_info(skb, n, 0, 0, RTM_GETNEIGH) < 0) {
+ if (neigh_fill_info(skb, n, 0, 0, RTM_GETNEIGH, 0) < 0) {
kfree_skb(skb);
return;
}
@@ -2037,7 +2349,7 @@ static void neigh_app_notify(struct neighbour *n)
if (!skb)
return;
- if (neigh_fill_info(skb, n, 0, 0, RTM_NEWNEIGH) < 0) {
+ if (neigh_fill_info(skb, n, 0, 0, RTM_NEWNEIGH, 0) < 0) {
kfree_skb(skb);
return;
}
@@ -2281,7 +2593,7 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
t->neigh_vars[17].extra1 = dev;
}
- dev_name = net_sysctl_strdup(dev_name_source);
+ dev_name = kstrdup(dev_name_source, GFP_KERNEL);
if (!dev_name) {
err = -ENOBUFS;
goto free;
@@ -2352,6 +2664,8 @@ EXPORT_SYMBOL(neigh_update);
EXPORT_SYMBOL(neigh_update_hhs);
EXPORT_SYMBOL(pneigh_enqueue);
EXPORT_SYMBOL(pneigh_lookup);
+EXPORT_SYMBOL(neightbl_dump_info);
+EXPORT_SYMBOL(neightbl_set);
#ifdef CONFIG_ARPD
EXPORT_SYMBOL(neigh_app_ns);
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 060f703659e..e2137f3e489 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -21,6 +21,7 @@
#define to_net_dev(class) container_of(class, struct net_device, class_dev)
static const char fmt_hex[] = "%#x\n";
+static const char fmt_long_hex[] = "%#lx\n";
static const char fmt_dec[] = "%d\n";
static const char fmt_ulong[] = "%lu\n";
@@ -91,7 +92,7 @@ static CLASS_DEVICE_ATTR(field, S_IRUGO, show_##field, NULL) \
NETDEVICE_ATTR(addr_len, fmt_dec);
NETDEVICE_ATTR(iflink, fmt_dec);
NETDEVICE_ATTR(ifindex, fmt_dec);
-NETDEVICE_ATTR(features, fmt_hex);
+NETDEVICE_ATTR(features, fmt_long_hex);
NETDEVICE_ATTR(type, fmt_dec);
/* use same locking rules as GIFHWADDR ioctl's */
@@ -184,6 +185,22 @@ static ssize_t store_tx_queue_len(struct class_device *dev, const char *buf, siz
static CLASS_DEVICE_ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len,
store_tx_queue_len);
+NETDEVICE_SHOW(weight, fmt_dec);
+
+static int change_weight(struct net_device *net, unsigned long new_weight)
+{
+ net->weight = new_weight;
+ return 0;
+}
+
+static ssize_t store_weight(struct class_device *dev, const char *buf, size_t len)
+{
+ return netdev_store(dev, buf, len, change_weight);
+}
+
+static CLASS_DEVICE_ATTR(weight, S_IRUGO | S_IWUSR, show_weight,
+ store_weight);
+
static struct class_device_attribute *net_class_attributes[] = {
&class_device_attr_ifindex,
@@ -193,6 +210,7 @@ static struct class_device_attribute *net_class_attributes[] = {
&class_device_attr_features,
&class_device_attr_mtu,
&class_device_attr_flags,
+ &class_device_attr_weight,
&class_device_attr_type,
&class_device_attr_address,
&class_device_attr_broadcast,
diff --git a/net/core/netfilter.c b/net/core/netfilter.c
index 22a8f127c4a..076c156d5ed 100644
--- a/net/core/netfilter.c
+++ b/net/core/netfilter.c
@@ -141,136 +141,6 @@ void nf_unregister_sockopt(struct nf_sockopt_ops *reg)
up(&nf_sockopt_mutex);
}
-#ifdef CONFIG_NETFILTER_DEBUG
-#include <net/ip.h>
-#include <net/tcp.h>
-#include <linux/netfilter_ipv4.h>
-
-static void debug_print_hooks_ip(unsigned int nf_debug)
-{
- if (nf_debug & (1 << NF_IP_PRE_ROUTING)) {
- printk("PRE_ROUTING ");
- nf_debug ^= (1 << NF_IP_PRE_ROUTING);
- }
- if (nf_debug & (1 << NF_IP_LOCAL_IN)) {
- printk("LOCAL_IN ");
- nf_debug ^= (1 << NF_IP_LOCAL_IN);
- }
- if (nf_debug & (1 << NF_IP_FORWARD)) {
- printk("FORWARD ");
- nf_debug ^= (1 << NF_IP_FORWARD);
- }
- if (nf_debug & (1 << NF_IP_LOCAL_OUT)) {
- printk("LOCAL_OUT ");
- nf_debug ^= (1 << NF_IP_LOCAL_OUT);
- }
- if (nf_debug & (1 << NF_IP_POST_ROUTING)) {
- printk("POST_ROUTING ");
- nf_debug ^= (1 << NF_IP_POST_ROUTING);
- }
- if (nf_debug)
- printk("Crap bits: 0x%04X", nf_debug);
- printk("\n");
-}
-
-static void nf_dump_skb(int pf, struct sk_buff *skb)
-{
- printk("skb: pf=%i %s dev=%s len=%u\n",
- pf,
- skb->sk ? "(owned)" : "(unowned)",
- skb->dev ? skb->dev->name : "(no dev)",
- skb->len);
- switch (pf) {
- case PF_INET: {
- const struct iphdr *ip = skb->nh.iph;
- __u32 *opt = (__u32 *) (ip + 1);
- int opti;
- __u16 src_port = 0, dst_port = 0;
-
- if (ip->protocol == IPPROTO_TCP
- || ip->protocol == IPPROTO_UDP) {
- struct tcphdr *tcp=(struct tcphdr *)((__u32 *)ip+ip->ihl);
- src_port = ntohs(tcp->source);
- dst_port = ntohs(tcp->dest);
- }
-
- printk("PROTO=%d %u.%u.%u.%u:%hu %u.%u.%u.%u:%hu"
- " L=%hu S=0x%2.2hX I=%hu F=0x%4.4hX T=%hu",
- ip->protocol, NIPQUAD(ip->saddr),
- src_port, NIPQUAD(ip->daddr),
- dst_port,
- ntohs(ip->tot_len), ip->tos, ntohs(ip->id),
- ntohs(ip->frag_off), ip->ttl);
-
- for (opti = 0; opti < (ip->ihl - sizeof(struct iphdr) / 4); opti++)
- printk(" O=0x%8.8X", *opt++);
- printk("\n");
- }
- }
-}
-
-void nf_debug_ip_local_deliver(struct sk_buff *skb)
-{
- /* If it's a loopback packet, it must have come through
- * NF_IP_LOCAL_OUT, NF_IP_RAW_INPUT, NF_IP_PRE_ROUTING and
- * NF_IP_LOCAL_IN. Otherwise, must have gone through
- * NF_IP_RAW_INPUT and NF_IP_PRE_ROUTING. */
- if (!skb->dev) {
- printk("ip_local_deliver: skb->dev is NULL.\n");
- } else {
- if (skb->nf_debug != ((1<<NF_IP_PRE_ROUTING)
- | (1<<NF_IP_LOCAL_IN))) {
- printk("ip_local_deliver: bad skb: ");
- debug_print_hooks_ip(skb->nf_debug);
- nf_dump_skb(PF_INET, skb);
- }
- }
-}
-
-void nf_debug_ip_loopback_xmit(struct sk_buff *newskb)
-{
- if (newskb->nf_debug != ((1 << NF_IP_LOCAL_OUT)
- | (1 << NF_IP_POST_ROUTING))) {
- printk("ip_dev_loopback_xmit: bad owned skb = %p: ",
- newskb);
- debug_print_hooks_ip(newskb->nf_debug);
- nf_dump_skb(PF_INET, newskb);
- }
-}
-
-void nf_debug_ip_finish_output2(struct sk_buff *skb)
-{
- /* If it's owned, it must have gone through the
- * NF_IP_LOCAL_OUT and NF_IP_POST_ROUTING.
- * Otherwise, must have gone through
- * NF_IP_PRE_ROUTING, NF_IP_FORWARD and NF_IP_POST_ROUTING.
- */
- if (skb->sk) {
- if (skb->nf_debug != ((1 << NF_IP_LOCAL_OUT)
- | (1 << NF_IP_POST_ROUTING))) {
- printk("ip_finish_output: bad owned skb = %p: ", skb);
- debug_print_hooks_ip(skb->nf_debug);
- nf_dump_skb(PF_INET, skb);
- }
- } else {
- if (skb->nf_debug != ((1 << NF_IP_PRE_ROUTING)
- | (1 << NF_IP_FORWARD)
- | (1 << NF_IP_POST_ROUTING))) {
- /* Fragments, entunnelled packets, TCP RSTs
- generated by ipt_REJECT will have no
- owners, but still may be local */
- if (skb->nf_debug != ((1 << NF_IP_LOCAL_OUT)
- | (1 << NF_IP_POST_ROUTING))){
- printk("ip_finish_output:"
- " bad unowned skb = %p: ",skb);
- debug_print_hooks_ip(skb->nf_debug);
- nf_dump_skb(PF_INET, skb);
- }
- }
- }
-}
-#endif /*CONFIG_NETFILTER_DEBUG*/
-
/* Call get/setsockopt() */
static int nf_sockopt(struct sock *sk, int pf, int val,
char __user *opt, int *len, int get)
@@ -488,14 +358,6 @@ int nf_hook_slow(int pf, unsigned int hook, struct sk_buff **pskb,
/* We may already have this, but read-locks nest anyway */
rcu_read_lock();
-#ifdef CONFIG_NETFILTER_DEBUG
- if (unlikely((*pskb)->nf_debug & (1 << hook))) {
- printk("nf_hook: hook %i already set.\n", hook);
- nf_dump_skb(pf, *pskb);
- }
- (*pskb)->nf_debug |= (1 << hook);
-#endif
-
elem = &nf_hooks[pf][hook];
next_hook:
verdict = nf_iterate(&nf_hooks[pf][hook], pskb, hook, indev,
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index a119696d552..c327c9edadc 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -130,19 +130,20 @@ static int checksum_udp(struct sk_buff *skb, struct udphdr *uh,
*/
static void poll_napi(struct netpoll *np)
{
+ struct netpoll_info *npinfo = np->dev->npinfo;
int budget = 16;
if (test_bit(__LINK_STATE_RX_SCHED, &np->dev->state) &&
- np->poll_owner != smp_processor_id() &&
- spin_trylock(&np->poll_lock)) {
- np->rx_flags |= NETPOLL_RX_DROP;
+ npinfo->poll_owner != smp_processor_id() &&
+ spin_trylock(&npinfo->poll_lock)) {
+ npinfo->rx_flags |= NETPOLL_RX_DROP;
atomic_inc(&trapped);
np->dev->poll(np->dev, &budget);
atomic_dec(&trapped);
- np->rx_flags &= ~NETPOLL_RX_DROP;
- spin_unlock(&np->poll_lock);
+ npinfo->rx_flags &= ~NETPOLL_RX_DROP;
+ spin_unlock(&npinfo->poll_lock);
}
}
@@ -245,6 +246,7 @@ repeat:
static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
{
int status;
+ struct netpoll_info *npinfo;
repeat:
if(!np || !np->dev || !netif_running(np->dev)) {
@@ -253,8 +255,9 @@ repeat:
}
/* avoid recursion */
- if(np->poll_owner == smp_processor_id() ||
- np->dev->xmit_lock_owner == smp_processor_id()) {
+ npinfo = np->dev->npinfo;
+ if (npinfo->poll_owner == smp_processor_id() ||
+ np->dev->xmit_lock_owner == smp_processor_id()) {
if (np->drop)
np->drop(skb);
else
@@ -341,14 +344,22 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
static void arp_reply(struct sk_buff *skb)
{
+ struct netpoll_info *npinfo = skb->dev->npinfo;
struct arphdr *arp;
unsigned char *arp_ptr;
int size, type = ARPOP_REPLY, ptype = ETH_P_ARP;
u32 sip, tip;
+ unsigned long flags;
struct sk_buff *send_skb;
- struct netpoll *np = skb->dev->np;
+ struct netpoll *np = NULL;
+
+ spin_lock_irqsave(&npinfo->rx_lock, flags);
+ if (npinfo->rx_np && npinfo->rx_np->dev == skb->dev)
+ np = npinfo->rx_np;
+ spin_unlock_irqrestore(&npinfo->rx_lock, flags);
- if (!np) return;
+ if (!np)
+ return;
/* No arp on this interface */
if (skb->dev->flags & IFF_NOARP)
@@ -429,9 +440,9 @@ int __netpoll_rx(struct sk_buff *skb)
int proto, len, ulen;
struct iphdr *iph;
struct udphdr *uh;
- struct netpoll *np = skb->dev->np;
+ struct netpoll *np = skb->dev->npinfo->rx_np;
- if (!np->rx_hook)
+ if (!np)
goto out;
if (skb->dev->type != ARPHRD_ETHER)
goto out;
@@ -611,9 +622,8 @@ int netpoll_setup(struct netpoll *np)
{
struct net_device *ndev = NULL;
struct in_device *in_dev;
-
- np->poll_lock = SPIN_LOCK_UNLOCKED;
- np->poll_owner = -1;
+ struct netpoll_info *npinfo;
+ unsigned long flags;
if (np->dev_name)
ndev = dev_get_by_name(np->dev_name);
@@ -624,7 +634,17 @@ int netpoll_setup(struct netpoll *np)
}
np->dev = ndev;
- ndev->np = np;
+ if (!ndev->npinfo) {
+ npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL);
+ if (!npinfo)
+ goto release;
+
+ npinfo->rx_np = NULL;
+ npinfo->poll_lock = SPIN_LOCK_UNLOCKED;
+ npinfo->poll_owner = -1;
+ npinfo->rx_lock = SPIN_LOCK_UNLOCKED;
+ } else
+ npinfo = ndev->npinfo;
if (!ndev->poll_controller) {
printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n",
@@ -692,13 +712,20 @@ int netpoll_setup(struct netpoll *np)
np->name, HIPQUAD(np->local_ip));
}
- if(np->rx_hook)
- np->rx_flags = NETPOLL_RX_ENABLED;
+ if (np->rx_hook) {
+ spin_lock_irqsave(&npinfo->rx_lock, flags);
+ npinfo->rx_flags |= NETPOLL_RX_ENABLED;
+ npinfo->rx_np = np;
+ spin_unlock_irqrestore(&npinfo->rx_lock, flags);
+ }
+ /* last thing to do is link it to the net device structure */
+ ndev->npinfo = npinfo;
return 0;
release:
- ndev->np = NULL;
+ if (!ndev->npinfo)
+ kfree(npinfo);
np->dev = NULL;
dev_put(ndev);
return -1;
@@ -706,9 +733,20 @@ int netpoll_setup(struct netpoll *np)
void netpoll_cleanup(struct netpoll *np)
{
- if (np->dev)
- np->dev->np = NULL;
- dev_put(np->dev);
+ struct netpoll_info *npinfo;
+ unsigned long flags;
+
+ if (np->dev) {
+ npinfo = np->dev->npinfo;
+ if (npinfo && npinfo->rx_np == np) {
+ spin_lock_irqsave(&npinfo->rx_lock, flags);
+ npinfo->rx_np = NULL;
+ npinfo->rx_flags &= ~NETPOLL_RX_ENABLED;
+ spin_unlock_irqrestore(&npinfo->rx_lock, flags);
+ }
+ dev_put(np->dev);
+ }
+
np->dev = NULL;
}
diff --git a/net/core/request_sock.c b/net/core/request_sock.c
new file mode 100644
index 00000000000..bb55675f068
--- /dev/null
+++ b/net/core/request_sock.c
@@ -0,0 +1,64 @@
+/*
+ * NET Generic infrastructure for Network protocols.
+ *
+ * Authors: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * From code originally in include/net/tcp.h
+ *
+ * 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 <linux/module.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include <net/request_sock.h>
+
+/*
+ * Maximum number of SYN_RECV sockets in queue per LISTEN socket.
+ * One SYN_RECV socket costs about 80bytes on a 32bit machine.
+ * It would be better to replace it with a global counter for all sockets
+ * but then some measure against one socket starving all other sockets
+ * would be needed.
+ *
+ * It was 128 by default. Experiments with real servers show, that
+ * it is absolutely not enough even at 100conn/sec. 256 cures most
+ * of problems. This value is adjusted to 128 for very small machines
+ * (<=32Mb of memory) and to 1024 on normal or better ones (>=256Mb).
+ * Further increasing requires to change hash table size.
+ */
+int sysctl_max_syn_backlog = 256;
+EXPORT_SYMBOL(sysctl_max_syn_backlog);
+
+int reqsk_queue_alloc(struct request_sock_queue *queue,
+ const int nr_table_entries)
+{
+ const int lopt_size = sizeof(struct listen_sock) +
+ nr_table_entries * sizeof(struct request_sock *);
+ struct listen_sock *lopt = kmalloc(lopt_size, GFP_KERNEL);
+
+ if (lopt == NULL)
+ return -ENOMEM;
+
+ memset(lopt, 0, lopt_size);
+
+ for (lopt->max_qlen_log = 6;
+ (1 << lopt->max_qlen_log) < sysctl_max_syn_backlog;
+ lopt->max_qlen_log++);
+
+ get_random_bytes(&lopt->hash_rnd, sizeof(lopt->hash_rnd));
+ rwlock_init(&queue->syn_wait_lock);
+ queue->rskq_accept_head = queue->rskq_accept_head = NULL;
+
+ write_lock_bh(&queue->syn_wait_lock);
+ queue->listen_opt = lopt;
+ write_unlock_bh(&queue->syn_wait_lock);
+
+ return 0;
+}
+
+EXPORT_SYMBOL(reqsk_queue_alloc);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 00caf4b318b..e013d836a7a 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -100,6 +100,7 @@ static const int rtm_min[RTM_NR_FAMILIES] =
[RTM_FAM(RTM_NEWPREFIX)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
[RTM_FAM(RTM_GETMULTICAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
[RTM_FAM(RTM_GETANYCAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
+ [RTM_FAM(RTM_NEWNEIGHTBL)] = NLMSG_LENGTH(sizeof(struct ndtmsg)),
};
static const int rta_max[RTM_NR_FAMILIES] =
@@ -113,6 +114,7 @@ static const int rta_max[RTM_NR_FAMILIES] =
[RTM_FAM(RTM_NEWTCLASS)] = TCA_MAX,
[RTM_FAM(RTM_NEWTFILTER)] = TCA_MAX,
[RTM_FAM(RTM_NEWACTION)] = TCAA_MAX,
+ [RTM_FAM(RTM_NEWNEIGHTBL)] = NDTA_MAX,
};
void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data)
@@ -176,14 +178,14 @@ rtattr_failure:
static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
- int type, u32 pid, u32 seq, u32 change)
+ int type, u32 pid, u32 seq, u32 change,
+ unsigned int flags)
{
struct ifinfomsg *r;
struct nlmsghdr *nlh;
unsigned char *b = skb->tail;
- nlh = NLMSG_PUT(skb, pid, seq, type, sizeof(*r));
- if (pid) nlh->nlmsg_flags |= NLM_F_MULTI;
+ nlh = NLMSG_NEW(skb, pid, seq, type, sizeof(*r), flags);
r = NLMSG_DATA(nlh);
r->ifi_family = AF_UNSPEC;
r->ifi_type = dev->type;
@@ -273,7 +275,10 @@ static int rtnetlink_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *c
for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
if (idx < s_idx)
continue;
- if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, 0) <= 0)
+ if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK,
+ NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq, 0,
+ NLM_F_MULTI) <= 0)
break;
}
read_unlock(&dev_base_lock);
@@ -447,7 +452,7 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
if (!skb)
return;
- if (rtnetlink_fill_ifinfo(skb, dev, type, 0, 0, change) < 0) {
+ if (rtnetlink_fill_ifinfo(skb, dev, type, current->pid, 0, change, 0) < 0) {
kfree_skb(skb);
return;
}
@@ -649,14 +654,16 @@ static void rtnetlink_rcv(struct sock *sk, int len)
static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] =
{
- [RTM_GETLINK - RTM_BASE] = { .dumpit = rtnetlink_dump_ifinfo },
- [RTM_SETLINK - RTM_BASE] = { .doit = do_setlink },
- [RTM_GETADDR - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
- [RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
- [RTM_NEWNEIGH - RTM_BASE] = { .doit = neigh_add },
- [RTM_DELNEIGH - RTM_BASE] = { .doit = neigh_delete },
- [RTM_GETNEIGH - RTM_BASE] = { .dumpit = neigh_dump_info },
- [RTM_GETRULE - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
+ [RTM_GETLINK - RTM_BASE] = { .dumpit = rtnetlink_dump_ifinfo },
+ [RTM_SETLINK - RTM_BASE] = { .doit = do_setlink },
+ [RTM_GETADDR - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
+ [RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
+ [RTM_NEWNEIGH - RTM_BASE] = { .doit = neigh_add },
+ [RTM_DELNEIGH - RTM_BASE] = { .doit = neigh_delete },
+ [RTM_GETNEIGH - RTM_BASE] = { .dumpit = neigh_dump_info },
+ [RTM_GETRULE - RTM_BASE] = { .dumpit = rtnetlink_dump_all },
+ [RTM_GETNEIGHTBL - RTM_BASE] = { .dumpit = neightbl_dump_info },
+ [RTM_SETNEIGHTBL - RTM_BASE] = { .doit = neightbl_set },
};
static int rtnetlink_event(struct notifier_block *this, unsigned long event, void *ptr)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index f65b3de590a..bb73b2190ec 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -365,9 +365,6 @@ struct sk_buff *skb_clone(struct sk_buff *skb, int gfp_mask)
C(nfct);
nf_conntrack_get(skb->nfct);
C(nfctinfo);
-#ifdef CONFIG_NETFILTER_DEBUG
- C(nf_debug);
-#endif
#ifdef CONFIG_BRIDGE_NETFILTER
C(nf_bridge);
nf_bridge_get(skb->nf_bridge);
@@ -432,9 +429,6 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
new->nfct = old->nfct;
nf_conntrack_get(old->nfct);
new->nfctinfo = old->nfctinfo;
-#ifdef CONFIG_NETFILTER_DEBUG
- new->nf_debug = old->nf_debug;
-#endif
#ifdef CONFIG_BRIDGE_NETFILTER
new->nf_bridge = old->nf_bridge;
nf_bridge_get(old->nf_bridge);
@@ -1506,6 +1500,159 @@ void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len)
skb_split_no_header(skb, skb1, len, pos);
}
+/**
+ * skb_prepare_seq_read - Prepare a sequential read of skb data
+ * @skb: the buffer to read
+ * @from: lower offset of data to be read
+ * @to: upper offset of data to be read
+ * @st: state variable
+ *
+ * Initializes the specified state variable. Must be called before
+ * invoking skb_seq_read() for the first time.
+ */
+void skb_prepare_seq_read(struct sk_buff *skb, unsigned int from,
+ unsigned int to, struct skb_seq_state *st)
+{
+ st->lower_offset = from;
+ st->upper_offset = to;
+ st->root_skb = st->cur_skb = skb;
+ st->frag_idx = st->stepped_offset = 0;
+ st->frag_data = NULL;
+}
+
+/**
+ * skb_seq_read - Sequentially read skb data
+ * @consumed: number of bytes consumed by the caller so far
+ * @data: destination pointer for data to be returned
+ * @st: state variable
+ *
+ * Reads a block of skb data at &consumed relative to the
+ * lower offset specified to skb_prepare_seq_read(). Assigns
+ * the head of the data block to &data and returns the length
+ * of the block or 0 if the end of the skb data or the upper
+ * offset has been reached.
+ *
+ * The caller is not required to consume all of the data
+ * returned, i.e. &consumed is typically set to the number
+ * of bytes already consumed and the next call to
+ * skb_seq_read() will return the remaining part of the block.
+ *
+ * Note: The size of each block of data returned can be arbitary,
+ * this limitation is the cost for zerocopy seqeuental
+ * reads of potentially non linear data.
+ *
+ * Note: Fragment lists within fragments are not implemented
+ * at the moment, state->root_skb could be replaced with
+ * a stack for this purpose.
+ */
+unsigned int skb_seq_read(unsigned int consumed, const u8 **data,
+ struct skb_seq_state *st)
+{
+ unsigned int block_limit, abs_offset = consumed + st->lower_offset;
+ skb_frag_t *frag;
+
+ if (unlikely(abs_offset >= st->upper_offset))
+ return 0;
+
+next_skb:
+ block_limit = skb_headlen(st->cur_skb);
+
+ if (abs_offset < block_limit) {
+ *data = st->cur_skb->data + abs_offset;
+ return block_limit - abs_offset;
+ }
+
+ if (st->frag_idx == 0 && !st->frag_data)
+ st->stepped_offset += skb_headlen(st->cur_skb);
+
+ while (st->frag_idx < skb_shinfo(st->cur_skb)->nr_frags) {
+ frag = &skb_shinfo(st->cur_skb)->frags[st->frag_idx];
+ block_limit = frag->size + st->stepped_offset;
+
+ if (abs_offset < block_limit) {
+ if (!st->frag_data)
+ st->frag_data = kmap_skb_frag(frag);
+
+ *data = (u8 *) st->frag_data + frag->page_offset +
+ (abs_offset - st->stepped_offset);
+
+ return block_limit - abs_offset;
+ }
+
+ if (st->frag_data) {
+ kunmap_skb_frag(st->frag_data);
+ st->frag_data = NULL;
+ }
+
+ st->frag_idx++;
+ st->stepped_offset += frag->size;
+ }
+
+ if (st->cur_skb->next) {
+ st->cur_skb = st->cur_skb->next;
+ st->frag_idx = 0;
+ goto next_skb;
+ } else if (st->root_skb == st->cur_skb &&
+ skb_shinfo(st->root_skb)->frag_list) {
+ st->cur_skb = skb_shinfo(st->root_skb)->frag_list;
+ goto next_skb;
+ }
+
+ return 0;
+}
+
+/**
+ * skb_abort_seq_read - Abort a sequential read of skb data
+ * @st: state variable
+ *
+ * Must be called if skb_seq_read() was not called until it
+ * returned 0.
+ */
+void skb_abort_seq_read(struct skb_seq_state *st)
+{
+ if (st->frag_data)
+ kunmap_skb_frag(st->frag_data);
+}
+
+#define TS_SKB_CB(state) ((struct skb_seq_state *) &((state)->cb))
+
+static unsigned int skb_ts_get_next_block(unsigned int offset, const u8 **text,
+ struct ts_config *conf,
+ struct ts_state *state)
+{
+ return skb_seq_read(offset, text, TS_SKB_CB(state));
+}
+
+static void skb_ts_finish(struct ts_config *conf, struct ts_state *state)
+{
+ skb_abort_seq_read(TS_SKB_CB(state));
+}
+
+/**
+ * skb_find_text - Find a text pattern in skb data
+ * @skb: the buffer to look in
+ * @from: search offset
+ * @to: search limit
+ * @config: textsearch configuration
+ * @state: uninitialized textsearch state variable
+ *
+ * Finds a pattern in the skb data according to the specified
+ * textsearch configuration. Use textsearch_next() to retrieve
+ * subsequent occurrences of the pattern. Returns the offset
+ * to the first occurrence or UINT_MAX if no match was found.
+ */
+unsigned int skb_find_text(struct sk_buff *skb, unsigned int from,
+ unsigned int to, struct ts_config *config,
+ struct ts_state *state)
+{
+ config->get_next_block = skb_ts_get_next_block;
+ config->finish = skb_ts_finish;
+
+ skb_prepare_seq_read(skb, from, to, TS_SKB_CB(state));
+
+ return textsearch_find(config, state);
+}
+
void __init skb_init(void)
{
skbuff_head_cache = kmem_cache_create("skbuff_head_cache",
@@ -1544,3 +1691,7 @@ EXPORT_SYMBOL(skb_queue_tail);
EXPORT_SYMBOL(skb_unlink);
EXPORT_SYMBOL(skb_append);
EXPORT_SYMBOL(skb_split);
+EXPORT_SYMBOL(skb_prepare_seq_read);
+EXPORT_SYMBOL(skb_seq_read);
+EXPORT_SYMBOL(skb_abort_seq_read);
+EXPORT_SYMBOL(skb_find_text);
diff --git a/net/core/sock.c b/net/core/sock.c
index 96e00b08698..a6ec3ada7f9 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -118,6 +118,7 @@
#include <linux/netdevice.h>
#include <net/protocol.h>
#include <linux/skbuff.h>
+#include <net/request_sock.h>
#include <net/sock.h>
#include <net/xfrm.h>
#include <linux/ipsec.h>
@@ -1363,6 +1364,7 @@ static LIST_HEAD(proto_list);
int proto_register(struct proto *prot, int alloc_slab)
{
+ char *request_sock_slab_name;
int rc = -ENOBUFS;
if (alloc_slab) {
@@ -1374,6 +1376,25 @@ int proto_register(struct proto *prot, int alloc_slab)
prot->name);
goto out;
}
+
+ if (prot->rsk_prot != NULL) {
+ static const char mask[] = "request_sock_%s";
+
+ request_sock_slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL);
+ if (request_sock_slab_name == NULL)
+ goto out_free_sock_slab;
+
+ sprintf(request_sock_slab_name, mask, prot->name);
+ prot->rsk_prot->slab = kmem_cache_create(request_sock_slab_name,
+ prot->rsk_prot->obj_size, 0,
+ SLAB_HWCACHE_ALIGN, NULL, NULL);
+
+ if (prot->rsk_prot->slab == NULL) {
+ printk(KERN_CRIT "%s: Can't create request sock SLAB cache!\n",
+ prot->name);
+ goto out_free_request_sock_slab_name;
+ }
+ }
}
write_lock(&proto_list_lock);
@@ -1382,6 +1403,12 @@ int proto_register(struct proto *prot, int alloc_slab)
rc = 0;
out:
return rc;
+out_free_request_sock_slab_name:
+ kfree(request_sock_slab_name);
+out_free_sock_slab:
+ kmem_cache_destroy(prot->slab);
+ prot->slab = NULL;
+ goto out;
}
EXPORT_SYMBOL(proto_register);
@@ -1395,6 +1422,14 @@ void proto_unregister(struct proto *prot)
prot->slab = NULL;
}
+ if (prot->rsk_prot != NULL && prot->rsk_prot->slab != NULL) {
+ const char *name = kmem_cache_name(prot->rsk_prot->slab);
+
+ kmem_cache_destroy(prot->rsk_prot->slab);
+ kfree(name);
+ prot->rsk_prot->slab = NULL;
+ }
+
list_del(&prot->node);
write_unlock(&proto_list_lock);
}
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index c8be646cb19..8f817ad9f54 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -13,12 +13,8 @@
#ifdef CONFIG_SYSCTL
extern int netdev_max_backlog;
+extern int netdev_budget;
extern int weight_p;
-extern int no_cong_thresh;
-extern int no_cong;
-extern int lo_cong;
-extern int mod_cong;
-extern int netdev_fastroute;
extern int net_msg_cost;
extern int net_msg_burst;
@@ -35,19 +31,6 @@ extern int sysctl_somaxconn;
extern char sysctl_divert_version[];
#endif /* CONFIG_NET_DIVERT */
-/*
- * This strdup() is used for creating copies of network
- * device names to be handed over to sysctl.
- */
-
-char *net_sysctl_strdup(const char *s)
-{
- char *rv = kmalloc(strlen(s)+1, GFP_KERNEL);
- if (rv)
- strcpy(rv, s);
- return rv;
-}
-
ctl_table core_table[] = {
#ifdef CONFIG_NET
{
@@ -99,38 +82,6 @@ ctl_table core_table[] = {
.proc_handler = &proc_dointvec
},
{
- .ctl_name = NET_CORE_NO_CONG_THRESH,
- .procname = "no_cong_thresh",
- .data = &no_cong_thresh,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec
- },
- {
- .ctl_name = NET_CORE_NO_CONG,
- .procname = "no_cong",
- .data = &no_cong,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec
- },
- {
- .ctl_name = NET_CORE_LO_CONG,
- .procname = "lo_cong",
- .data = &lo_cong,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec
- },
- {
- .ctl_name = NET_CORE_MOD_CONG,
- .procname = "mod_cong",
- .data = &mod_cong,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec
- },
- {
.ctl_name = NET_CORE_MSG_COST,
.procname = "message_cost",
.data = &net_msg_cost,
@@ -174,9 +125,15 @@ ctl_table core_table[] = {
.mode = 0644,
.proc_handler = &proc_dointvec
},
+ {
+ .ctl_name = NET_CORE_BUDGET,
+ .procname = "netdev_budget",
+ .data = &netdev_budget,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec
+ },
{ .ctl_name = 0 }
};
-EXPORT_SYMBOL(net_sysctl_strdup);
-
#endif
diff --git a/net/core/wireless.c b/net/core/wireless.c
index 750cc5daeb0..b2fe378dfbf 100644
--- a/net/core/wireless.c
+++ b/net/core/wireless.c
@@ -2,7 +2,7 @@
* This file implement the Wireless Extensions APIs.
*
* Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
- * Copyright (c) 1997-2004 Jean Tourrilhes, All Rights Reserved.
+ * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved.
*
* (As all part of the Linux kernel, this file is GPL)
*/
@@ -187,6 +187,12 @@ static const struct iw_ioctl_description standard_ioctl[] = {
.header_type = IW_HEADER_TYPE_ADDR,
.flags = IW_DESCR_FLAG_DUMP,
},
+ [SIOCSIWMLME - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .min_tokens = sizeof(struct iw_mlme),
+ .max_tokens = sizeof(struct iw_mlme),
+ },
[SIOCGIWAPLIST - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
.token_size = sizeof(struct sockaddr) +
@@ -195,7 +201,10 @@ static const struct iw_ioctl_description standard_ioctl[] = {
.flags = IW_DESCR_FLAG_NOMAX,
},
[SIOCSIWSCAN - SIOCIWFIRST] = {
- .header_type = IW_HEADER_TYPE_PARAM,
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .min_tokens = 0,
+ .max_tokens = sizeof(struct iw_scan_req),
},
[SIOCGIWSCAN - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_POINT,
@@ -273,6 +282,42 @@ static const struct iw_ioctl_description standard_ioctl[] = {
[SIOCGIWPOWER - SIOCIWFIRST] = {
.header_type = IW_HEADER_TYPE_PARAM,
},
+ [SIOCSIWGENIE - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .max_tokens = IW_GENERIC_IE_MAX,
+ },
+ [SIOCGIWGENIE - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .max_tokens = IW_GENERIC_IE_MAX,
+ },
+ [SIOCSIWAUTH - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_PARAM,
+ },
+ [SIOCGIWAUTH - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_PARAM,
+ },
+ [SIOCSIWENCODEEXT - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .min_tokens = sizeof(struct iw_encode_ext),
+ .max_tokens = sizeof(struct iw_encode_ext) +
+ IW_ENCODING_TOKEN_MAX,
+ },
+ [SIOCGIWENCODEEXT - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .min_tokens = sizeof(struct iw_encode_ext),
+ .max_tokens = sizeof(struct iw_encode_ext) +
+ IW_ENCODING_TOKEN_MAX,
+ },
+ [SIOCSIWPMKSA - SIOCIWFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .min_tokens = sizeof(struct iw_pmksa),
+ .max_tokens = sizeof(struct iw_pmksa),
+ },
};
static const int standard_ioctl_num = (sizeof(standard_ioctl) /
sizeof(struct iw_ioctl_description));
@@ -299,6 +344,31 @@ static const struct iw_ioctl_description standard_event[] = {
[IWEVEXPIRED - IWEVFIRST] = {
.header_type = IW_HEADER_TYPE_ADDR,
},
+ [IWEVGENIE - IWEVFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .max_tokens = IW_GENERIC_IE_MAX,
+ },
+ [IWEVMICHAELMICFAILURE - IWEVFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .max_tokens = sizeof(struct iw_michaelmicfailure),
+ },
+ [IWEVASSOCREQIE - IWEVFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .max_tokens = IW_GENERIC_IE_MAX,
+ },
+ [IWEVASSOCRESPIE - IWEVFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .max_tokens = IW_GENERIC_IE_MAX,
+ },
+ [IWEVPMKIDCAND - IWEVFIRST] = {
+ .header_type = IW_HEADER_TYPE_POINT,
+ .token_size = 1,
+ .max_tokens = sizeof(struct iw_pmkid_cand),
+ },
};
static const int standard_event_num = (sizeof(standard_event) /
sizeof(struct iw_ioctl_description));
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index ee7bf46eb78..00233ecbc9c 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -716,13 +716,13 @@ static int dn_dev_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *a
}
static int dn_dev_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa,
- u32 pid, u32 seq, int event)
+ u32 pid, u32 seq, int event, unsigned int flags)
{
struct ifaddrmsg *ifm;
struct nlmsghdr *nlh;
unsigned char *b = skb->tail;
- nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ifm));
+ nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags);
ifm = NLMSG_DATA(nlh);
ifm->ifa_family = AF_DECnet;
@@ -755,7 +755,7 @@ static void rtmsg_ifa(int event, struct dn_ifaddr *ifa)
netlink_set_err(rtnl, 0, RTMGRP_DECnet_IFADDR, ENOBUFS);
return;
}
- if (dn_dev_fill_ifaddr(skb, ifa, 0, 0, event) < 0) {
+ if (dn_dev_fill_ifaddr(skb, ifa, 0, 0, event, 0) < 0) {
kfree_skb(skb);
netlink_set_err(rtnl, 0, RTMGRP_DECnet_IFADDR, EINVAL);
return;
@@ -790,7 +790,8 @@ static int dn_dev_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
if (dn_dev_fill_ifaddr(skb, ifa,
NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq,
- RTM_NEWADDR) <= 0)
+ RTM_NEWADDR,
+ NLM_F_MULTI) <= 0)
goto done;
}
}
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index f6dfe96f45b..f32dba9e26f 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -101,7 +101,6 @@ struct neigh_table dn_neigh_table = {
.id = "dn_neigh_cache",
.parms ={
.tbl = &dn_neigh_table,
- .entries = 0,
.base_reachable_time = 30 * HZ,
.retrans_time = 1 * HZ,
.gc_staletime = 60 * HZ,
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 1e7b5c3ea21..2399fa8a3f8 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -1465,7 +1465,8 @@ int dn_route_input(struct sk_buff *skb)
return dn_route_input_slow(skb);
}
-static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, int nowait)
+static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
+ int event, int nowait, unsigned int flags)
{
struct dn_route *rt = (struct dn_route *)skb->dst;
struct rtmsg *r;
@@ -1473,9 +1474,8 @@ static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, int
unsigned char *b = skb->tail;
struct rta_cacheinfo ci;
- nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*r));
+ nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags);
r = NLMSG_DATA(nlh);
- nlh->nlmsg_flags = (nowait && pid) ? NLM_F_MULTI : 0;
r->rtm_family = AF_DECnet;
r->rtm_dst_len = 16;
r->rtm_src_len = 0;
@@ -1596,7 +1596,7 @@ int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, void *arg)
NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
- err = dn_rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, RTM_NEWROUTE, 0);
+ err = dn_rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, RTM_NEWROUTE, 0, 0);
if (err == 0)
goto out_free;
@@ -1644,7 +1644,8 @@ int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb)
continue;
skb->dst = dst_clone(&rt->u.dst);
if (dn_rt_fill_info(skb, NETLINK_CB(cb->skb).pid,
- cb->nlh->nlmsg_seq, RTM_NEWROUTE, 1) <= 0) {
+ cb->nlh->nlmsg_seq, RTM_NEWROUTE,
+ 1, NLM_F_MULTI) <= 0) {
dst_release(xchg(&skb->dst, NULL));
rcu_read_unlock_bh();
goto done;
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
index 597587d170d..1060de70bc0 100644
--- a/net/decnet/dn_rules.c
+++ b/net/decnet/dn_rules.c
@@ -342,14 +342,15 @@ static struct notifier_block dn_fib_rules_notifier = {
.notifier_call = dn_fib_rules_event,
};
-static int dn_fib_fill_rule(struct sk_buff *skb, struct dn_fib_rule *r, struct netlink_callback *cb)
+static int dn_fib_fill_rule(struct sk_buff *skb, struct dn_fib_rule *r,
+ struct netlink_callback *cb, unsigned int flags)
{
struct rtmsg *rtm;
struct nlmsghdr *nlh;
unsigned char *b = skb->tail;
- nlh = NLMSG_PUT(skb, NETLINK_CREDS(cb->skb)->pid, cb->nlh->nlmsg_seq, RTM_NEWRULE, sizeof(*rtm));
+ nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWRULE, sizeof(*rtm), flags);
rtm = NLMSG_DATA(nlh);
rtm->rtm_family = AF_DECnet;
rtm->rtm_dst_len = r->r_dst_len;
@@ -394,7 +395,7 @@ int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
for(r = dn_fib_rules, idx = 0; r; r = r->r_next, idx++) {
if (idx < s_idx)
continue;
- if (dn_fib_fill_rule(skb, r, cb) < 0)
+ if (dn_fib_fill_rule(skb, r, cb, NLM_F_MULTI) < 0)
break;
}
read_unlock(&dn_fib_rules_lock);
diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c
index dad5603912b..28ba5777a25 100644
--- a/net/decnet/dn_table.c
+++ b/net/decnet/dn_table.c
@@ -270,13 +270,13 @@ static int dn_fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct dn_kern
static int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
u8 tb_id, u8 type, u8 scope, void *dst, int dst_len,
- struct dn_fib_info *fi)
+ struct dn_fib_info *fi, unsigned int flags)
{
struct rtmsg *rtm;
struct nlmsghdr *nlh;
unsigned char *b = skb->tail;
- nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*rtm));
+ nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*rtm), flags);
rtm = NLMSG_DATA(nlh);
rtm->rtm_family = AF_DECnet;
rtm->rtm_dst_len = dst_len;
@@ -345,7 +345,7 @@ static void dn_rtmsg_fib(int event, struct dn_fib_node *f, int z, int tb_id,
if (dn_fib_dump_info(skb, pid, nlh->nlmsg_seq, event, tb_id,
f->fn_type, f->fn_scope, &f->fn_key, z,
- DN_FIB_INFO(f)) < 0) {
+ DN_FIB_INFO(f), 0) < 0) {
kfree_skb(skb);
return;
}
@@ -377,7 +377,7 @@ static __inline__ int dn_hash_dump_bucket(struct sk_buff *skb,
tb->n,
(f->fn_state & DN_S_ZOMBIE) ? 0 : f->fn_type,
f->fn_scope, &f->fn_key, dz->dz_order,
- f->fn_info) < 0) {
+ f->fn_info, NLM_F_MULTI) < 0) {
cb->args[3] = i;
return -1;
}
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 6d3e8b1bd1f..34708343312 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -53,6 +53,44 @@ config IP_ADVANCED_ROUTER
If unsure, say N here.
+choice
+ prompt "Choose IP: FIB lookup algorithm (choose FIB_HASH if unsure)"
+ depends on IP_ADVANCED_ROUTER
+ default IP_FIB_HASH
+
+config IP_FIB_HASH
+ bool "FIB_HASH"
+ ---help---
+ Current FIB is very proven and good enough for most users.
+
+config IP_FIB_TRIE
+ bool "FIB_TRIE"
+ ---help---
+ Use new experimental LC-trie as FIB lookup algoritm.
+ This improves lookup performance if you have a large
+ number of routes.
+
+ LC-trie is a longest matching prefix lookup algorithm which
+ performs better than FIB_HASH for large routing tables.
+ But, it consumes more memory and is more complex.
+
+ LC-trie is described in:
+
+ IP-address lookup using LC-tries. Stefan Nilsson and Gunnar Karlsson
+ IEEE Journal on Selected Areas in Communications, 17(6):1083-1092, June 1999
+ An experimental study of compression methods for dynamic tries
+ Stefan Nilsson and Matti Tikkanen. Algorithmica, 33(1):19-33, 2002.
+ http://www.nada.kth.se/~snilsson/public/papers/dyntrie2/
+
+endchoice
+
+# If the user does not enable advanced routing, he gets the safe
+# default of the fib-hash algorithm.
+config IP_FIB_HASH
+ bool
+ depends on !IP_ADVANCED_ROUTER
+ default y
+
config IP_MULTIPLE_TABLES
bool "IP: policy routing"
depends on IP_ADVANCED_ROUTER
@@ -407,5 +445,113 @@ config IP_TCPDIAG
config IP_TCPDIAG_IPV6
def_bool (IP_TCPDIAG=y && IPV6=y) || (IP_TCPDIAG=m && IPV6)
+config TCP_CONG_ADVANCED
+ bool "TCP: advanced congestion control"
+ depends on INET
+ default y
+ ---help---
+ Support for selection of various TCP congestion control
+ modules.
+
+ Nearly all users can safely say no here, and a safe default
+ selection will be made (BIC-TCP with new Reno as a fallback).
+
+ If unsure, say N.
+
+# TCP Reno is builtin (required as fallback)
+menu "TCP congestion control"
+ depends on TCP_CONG_ADVANCED
+
+config TCP_CONG_BIC
+ tristate "Binary Increase Congestion (BIC) control"
+ depends on INET
+ default y
+ ---help---
+ BIC-TCP is a sender-side only change that ensures a linear RTT
+ fairness under large windows while offering both scalability and
+ bounded TCP-friendliness. The protocol combines two schemes
+ called additive increase and binary search increase. When the
+ congestion window is large, additive increase with a large
+ increment ensures linear RTT fairness as well as good
+ scalability. Under small congestion windows, binary search
+ increase provides TCP friendliness.
+ See http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/
+
+config TCP_CONG_WESTWOOD
+ tristate "TCP Westwood+"
+ depends on INET
+ default m
+ ---help---
+ TCP Westwood+ is a sender-side only modification of the TCP Reno
+ protocol stack that optimizes the performance of TCP congestion
+ control. It is based on end-to-end bandwidth estimation to set
+ congestion window and slow start threshold after a congestion
+ episode. Using this estimation, TCP Westwood+ adaptively sets a
+ slow start threshold and a congestion window which takes into
+ account the bandwidth used at the time congestion is experienced.
+ TCP Westwood+ significantly increases fairness wrt TCP Reno in
+ wired networks and throughput over wireless links.
+
+config TCP_CONG_HTCP
+ tristate "H-TCP"
+ depends on INET
+ default m
+ ---help---
+ H-TCP is a send-side only modifications of the TCP Reno
+ protocol stack that optimizes the performance of TCP
+ congestion control for high speed network links. It uses a
+ modeswitch to change the alpha and beta parameters of TCP Reno
+ based on network conditions and in a way so as to be fair with
+ other Reno and H-TCP flows.
+
+config TCP_CONG_HSTCP
+ tristate "High Speed TCP"
+ depends on INET && EXPERIMENTAL
+ default n
+ ---help---
+ Sally Floyd's High Speed TCP (RFC 3649) congestion control.
+ A modification to TCP's congestion control mechanism for use
+ with large congestion windows. A table indicates how much to
+ increase the congestion window by when an ACK is received.
+ For more detail see http://www.icir.org/floyd/hstcp.html
+
+config TCP_CONG_HYBLA
+ tristate "TCP-Hybla congestion control algorithm"
+ depends on INET && EXPERIMENTAL
+ default n
+ ---help---
+ TCP-Hybla is a sender-side only change that eliminates penalization of
+ long-RTT, large-bandwidth connections, like when satellite legs are
+ involved, expecially when sharing a common bottleneck with normal
+ terrestrial connections.
+
+config TCP_CONG_VEGAS
+ tristate "TCP Vegas"
+ depends on INET && EXPERIMENTAL
+ default n
+ ---help---
+ TCP Vegas is a sender-side only change to TCP that anticipates
+ the onset of congestion by estimating the bandwidth. TCP Vegas
+ adjusts the sending rate by modifying the congestion
+ window. TCP Vegas should provide less packet loss, but it is
+ not as aggressive as TCP Reno.
+
+config TCP_CONG_SCALABLE
+ tristate "Scalable TCP"
+ depends on INET && EXPERIMENTAL
+ default n
+ ---help---
+ Scalable TCP is a sender-side only change to TCP which uses a
+ MIMD congestion control algorithm which has some nice scaling
+ properties, though is known to have fairness issues.
+ See http://www-lce.eng.cam.ac.uk/~ctk21/scalable/
+
+endmenu
+
+config TCP_CONG_BIC
+ boolean
+ depends on !TCP_CONG_ADVANCED
+ default y
+
source "net/ipv4/ipvs/Kconfig"
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 8b379627ebb..5718cdb3a61 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -5,10 +5,13 @@
obj-y := utils.o route.o inetpeer.o protocol.o \
ip_input.o ip_fragment.o ip_forward.o ip_options.o \
ip_output.o ip_sockglue.o \
- tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o tcp_minisocks.o \
+ tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o \
+ tcp_minisocks.o tcp_cong.o \
datagram.o raw.o udp.o arp.o icmp.o devinet.o af_inet.o igmp.o \
- sysctl_net_ipv4.o fib_frontend.o fib_semantics.o fib_hash.o
+ sysctl_net_ipv4.o fib_frontend.o fib_semantics.o
+obj-$(CONFIG_IP_FIB_HASH) += fib_hash.o
+obj-$(CONFIG_IP_FIB_TRIE) += fib_trie.o
obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o
obj-$(CONFIG_IP_MROUTE) += ipmr.o
@@ -28,6 +31,13 @@ obj-$(CONFIG_NETFILTER) += netfilter/
obj-$(CONFIG_IP_VS) += ipvs/
obj-$(CONFIG_IP_TCPDIAG) += tcp_diag.o
obj-$(CONFIG_IP_ROUTE_MULTIPATH_CACHED) += multipath.o
+obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o
+obj-$(CONFIG_TCP_CONG_WESTWOOD) += tcp_westwood.o
+obj-$(CONFIG_TCP_CONG_HSTCP) += tcp_highspeed.o
+obj-$(CONFIG_TCP_CONG_HYBLA) += tcp_hybla.o
+obj-$(CONFIG_TCP_CONG_HTCP) += tcp_htcp.o
+obj-$(CONFIG_TCP_CONG_VEGAS) += tcp_vegas.o
+obj-$(CONFIG_TCP_CONG_SCALABLE) += tcp_scalable.o
obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
xfrm4_output.o
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index b3cb49ce5fa..658e7977924 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1119,6 +1119,10 @@ module_init(inet_init);
#ifdef CONFIG_PROC_FS
extern int fib_proc_init(void);
extern void fib_proc_exit(void);
+#ifdef CONFIG_IP_FIB_TRIE
+extern int fib_stat_proc_init(void);
+extern void fib_stat_proc_exit(void);
+#endif
extern int ip_misc_proc_init(void);
extern int raw_proc_init(void);
extern void raw_proc_exit(void);
@@ -1139,11 +1143,19 @@ static int __init ipv4_proc_init(void)
goto out_udp;
if (fib_proc_init())
goto out_fib;
+#ifdef CONFIG_IP_FIB_TRIE
+ if (fib_stat_proc_init())
+ goto out_fib_stat;
+ #endif
if (ip_misc_proc_init())
goto out_misc;
out:
return rc;
out_misc:
+#ifdef CONFIG_IP_FIB_TRIE
+ fib_stat_proc_exit();
+out_fib_stat:
+#endif
fib_proc_exit();
out_fib:
udp4_proc_exit();
@@ -1181,6 +1193,7 @@ EXPORT_SYMBOL(inet_stream_connect);
EXPORT_SYMBOL(inet_stream_ops);
EXPORT_SYMBOL(inet_unregister_protosw);
EXPORT_SYMBOL(net_statistics);
+EXPORT_SYMBOL(sysctl_ip_nonlocal_bind);
#ifdef INET_REFCNT_DEBUG
EXPORT_SYMBOL(inet_sock_nr);
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 0e98f2235b6..514c85b2631 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -200,7 +200,7 @@ static void ah4_err(struct sk_buff *skb, u32 info)
xfrm_state_put(x);
}
-static int ah_init_state(struct xfrm_state *x, void *args)
+static int ah_init_state(struct xfrm_state *x)
{
struct ah_data *ahp = NULL;
struct xfrm_algo_desc *aalg_desc;
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 3cc96730c4e..d8a10e3dd77 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -233,11 +233,14 @@ int inet_addr_onlink(struct in_device *in_dev, u32 a, u32 b)
static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
int destroy)
{
+ struct in_ifaddr *promote = NULL;
struct in_ifaddr *ifa1 = *ifap;
ASSERT_RTNL();
- /* 1. Deleting primary ifaddr forces deletion all secondaries */
+ /* 1. Deleting primary ifaddr forces deletion all secondaries
+ * unless alias promotion is set
+ **/
if (!(ifa1->ifa_flags & IFA_F_SECONDARY)) {
struct in_ifaddr *ifa;
@@ -251,11 +254,16 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
continue;
}
- *ifap1 = ifa->ifa_next;
+ if (!IN_DEV_PROMOTE_SECONDARIES(in_dev)) {
+ *ifap1 = ifa->ifa_next;
- rtmsg_ifa(RTM_DELADDR, ifa);
- notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa);
- inet_free_ifa(ifa);
+ rtmsg_ifa(RTM_DELADDR, ifa);
+ notifier_call_chain(&inetaddr_chain, NETDEV_DOWN, ifa);
+ inet_free_ifa(ifa);
+ } else {
+ promote = ifa;
+ break;
+ }
}
}
@@ -281,6 +289,13 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap,
if (!in_dev->ifa_list)
inetdev_destroy(in_dev);
}
+
+ if (promote && IN_DEV_PROMOTE_SECONDARIES(in_dev)) {
+ /* not sure if we should send a delete notify first? */
+ promote->ifa_flags &= ~IFA_F_SECONDARY;
+ rtmsg_ifa(RTM_NEWADDR, promote);
+ notifier_call_chain(&inetaddr_chain, NETDEV_UP, promote);
+ }
}
static int inet_insert_ifa(struct in_ifaddr *ifa)
@@ -1015,14 +1030,13 @@ static struct notifier_block ip_netdev_notifier = {
};
static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
- u32 pid, u32 seq, int event)
+ u32 pid, u32 seq, int event, unsigned int flags)
{
struct ifaddrmsg *ifm;
struct nlmsghdr *nlh;
unsigned char *b = skb->tail;
- nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ifm));
- if (pid) nlh->nlmsg_flags |= NLM_F_MULTI;
+ nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags);
ifm = NLMSG_DATA(nlh);
ifm->ifa_family = AF_INET;
ifm->ifa_prefixlen = ifa->ifa_prefixlen;
@@ -1075,7 +1089,7 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
continue;
if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq,
- RTM_NEWADDR) <= 0) {
+ RTM_NEWADDR, NLM_F_MULTI) <= 0) {
rcu_read_unlock();
goto done;
}
@@ -1098,7 +1112,7 @@ static void rtmsg_ifa(int event, struct in_ifaddr* ifa)
if (!skb)
netlink_set_err(rtnl, 0, RTMGRP_IPV4_IFADDR, ENOBUFS);
- else if (inet_fill_ifaddr(skb, ifa, 0, 0, event) < 0) {
+ else if (inet_fill_ifaddr(skb, ifa, current->pid, 0, event, 0) < 0) {
kfree_skb(skb);
netlink_set_err(rtnl, 0, RTMGRP_IPV4_IFADDR, EINVAL);
} else {
@@ -1384,6 +1398,15 @@ static struct devinet_sysctl_table {
.proc_handler = &ipv4_doint_and_flush,
.strategy = &ipv4_doint_and_flush_strategy,
},
+ {
+ .ctl_name = NET_IPV4_CONF_PROMOTE_SECONDARIES,
+ .procname = "promote_secondaries",
+ .data = &ipv4_devconf.promote_secondaries,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &ipv4_doint_and_flush,
+ .strategy = &ipv4_doint_and_flush_strategy,
+ },
},
.devinet_dev = {
{
@@ -1448,7 +1471,7 @@ static void devinet_sysctl_register(struct in_device *in_dev,
* by sysctl and we wouldn't want anyone to change it under our feet
* (see SIOCSIFNAME).
*/
- dev_name = net_sysctl_strdup(dev_name);
+ dev_name = kstrdup(dev_name, GFP_KERNEL);
if (!dev_name)
goto free;
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 053a883247b..ba57446d5d1 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -362,7 +362,7 @@ static void esp_destroy(struct xfrm_state *x)
kfree(esp);
}
-static int esp_init_state(struct xfrm_state *x, void *args)
+static int esp_init_state(struct xfrm_state *x)
{
struct esp_data *esp = NULL;
@@ -478,7 +478,7 @@ static int __init esp4_init(void)
{
struct xfrm_decap_state decap;
- if (sizeof(struct esp_decap_data) <
+ if (sizeof(struct esp_decap_data) >
sizeof(decap.decap_data)) {
extern void decap_data_too_small(void);
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 563e7d61270..cd8e45ab958 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -516,6 +516,60 @@ static void fib_del_ifaddr(struct in_ifaddr *ifa)
#undef BRD1_OK
}
+static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb )
+{
+
+ struct fib_result res;
+ struct flowi fl = { .nl_u = { .ip4_u = { .daddr = frn->fl_addr,
+ .fwmark = frn->fl_fwmark,
+ .tos = frn->fl_tos,
+ .scope = frn->fl_scope } } };
+ if (tb) {
+ local_bh_disable();
+
+ frn->tb_id = tb->tb_id;
+ frn->err = tb->tb_lookup(tb, &fl, &res);
+
+ if (!frn->err) {
+ frn->prefixlen = res.prefixlen;
+ frn->nh_sel = res.nh_sel;
+ frn->type = res.type;
+ frn->scope = res.scope;
+ }
+ local_bh_enable();
+ }
+}
+
+static void nl_fib_input(struct sock *sk, int len)
+{
+ struct sk_buff *skb = NULL;
+ struct nlmsghdr *nlh = NULL;
+ struct fib_result_nl *frn;
+ int err;
+ u32 pid;
+ struct fib_table *tb;
+
+ skb = skb_recv_datagram(sk, 0, 0, &err);
+ nlh = (struct nlmsghdr *)skb->data;
+
+ frn = (struct fib_result_nl *) NLMSG_DATA(nlh);
+ tb = fib_get_table(frn->tb_id_in);
+
+ nl_fib_lookup(frn, tb);
+
+ pid = nlh->nlmsg_pid; /*pid of sending process */
+ NETLINK_CB(skb).groups = 0; /* not in mcast group */
+ NETLINK_CB(skb).pid = 0; /* from kernel */
+ NETLINK_CB(skb).dst_pid = pid;
+ NETLINK_CB(skb).dst_groups = 0; /* unicast */
+ netlink_unicast(sk, skb, pid, MSG_DONTWAIT);
+}
+
+static void nl_fib_lookup_init(void)
+{
+ netlink_kernel_create(NETLINK_FIB_LOOKUP, nl_fib_input);
+}
+
static void fib_disable_ip(struct net_device *dev, int force)
{
if (fib_sync_down(0, dev, force))
@@ -604,6 +658,7 @@ void __init ip_fib_init(void)
register_netdevice_notifier(&fib_netdev_notifier);
register_inetaddr_notifier(&fib_inetaddr_notifier);
+ nl_fib_lookup_init();
}
EXPORT_SYMBOL(inet_addr_type);
diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c
index 6506dcc01b4..b10d6bb5ef3 100644
--- a/net/ipv4/fib_hash.c
+++ b/net/ipv4/fib_hash.c
@@ -703,7 +703,8 @@ fn_hash_dump_bucket(struct sk_buff *skb, struct netlink_callback *cb,
&f->fn_key,
fz->fz_order,
fa->fa_tos,
- fa->fa_info) < 0) {
+ fa->fa_info,
+ NLM_F_MULTI) < 0) {
cb->args[3] = i;
return -1;
}
diff --git a/net/ipv4/fib_lookup.h b/net/ipv4/fib_lookup.h
index ac4485f75e9..b729d97cfa9 100644
--- a/net/ipv4/fib_lookup.h
+++ b/net/ipv4/fib_lookup.h
@@ -30,7 +30,8 @@ extern int fib_nh_match(struct rtmsg *r, struct nlmsghdr *,
struct kern_rta *rta, struct fib_info *fi);
extern int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
u8 tb_id, u8 type, u8 scope, void *dst,
- int dst_len, u8 tos, struct fib_info *fi);
+ int dst_len, u8 tos, struct fib_info *fi,
+ unsigned int);
extern void rtmsg_fib(int event, u32 key, struct fib_alias *fa,
int z, int tb_id,
struct nlmsghdr *n, struct netlink_skb_parms *req);
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 39d0aadb9a2..0b298bbc151 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -367,13 +367,14 @@ static struct notifier_block fib_rules_notifier = {
static __inline__ int inet_fill_rule(struct sk_buff *skb,
struct fib_rule *r,
- struct netlink_callback *cb)
+ struct netlink_callback *cb,
+ unsigned int flags)
{
struct rtmsg *rtm;
struct nlmsghdr *nlh;
unsigned char *b = skb->tail;
- nlh = NLMSG_PUT(skb, NETLINK_CREDS(cb->skb)->pid, cb->nlh->nlmsg_seq, RTM_NEWRULE, sizeof(*rtm));
+ nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWRULE, sizeof(*rtm), flags);
rtm = NLMSG_DATA(nlh);
rtm->rtm_family = AF_INET;
rtm->rtm_dst_len = r->r_dst_len;
@@ -422,7 +423,7 @@ int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
for (r=fib_rules, idx=0; r; r = r->r_next, idx++) {
if (idx < s_idx)
continue;
- if (inet_fill_rule(skb, r, cb) < 0)
+ if (inet_fill_rule(skb, r, cb, NLM_F_MULTI) < 0)
break;
}
read_unlock(&fib_rules_lock);
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 029362d6613..c886b28ba9f 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -276,7 +276,7 @@ void rtmsg_fib(int event, u32 key, struct fib_alias *fa,
struct nlmsghdr *n, struct netlink_skb_parms *req)
{
struct sk_buff *skb;
- u32 pid = req ? req->pid : 0;
+ u32 pid = req ? req->pid : n->nlmsg_pid;
int size = NLMSG_SPACE(sizeof(struct rtmsg)+256);
skb = alloc_skb(size, GFP_KERNEL);
@@ -286,7 +286,7 @@ void rtmsg_fib(int event, u32 key, struct fib_alias *fa,
if (fib_dump_info(skb, pid, n->nlmsg_seq, event, tb_id,
fa->fa_type, fa->fa_scope, &key, z,
fa->fa_tos,
- fa->fa_info) < 0) {
+ fa->fa_info, 0) < 0) {
kfree_skb(skb);
return;
}
@@ -932,13 +932,13 @@ u32 __fib_res_prefsrc(struct fib_result *res)
int
fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
u8 tb_id, u8 type, u8 scope, void *dst, int dst_len, u8 tos,
- struct fib_info *fi)
+ struct fib_info *fi, unsigned int flags)
{
struct rtmsg *rtm;
struct nlmsghdr *nlh;
unsigned char *b = skb->tail;
- nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*rtm));
+ nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*rtm), flags);
rtm = NLMSG_DATA(nlh);
rtm->rtm_family = AF_INET;
rtm->rtm_dst_len = dst_len;
@@ -1035,7 +1035,7 @@ fib_convert_rtentry(int cmd, struct nlmsghdr *nl, struct rtmsg *rtm,
}
nl->nlmsg_flags = NLM_F_REQUEST;
- nl->nlmsg_pid = 0;
+ nl->nlmsg_pid = current->pid;
nl->nlmsg_seq = 0;
nl->nlmsg_len = NLMSG_LENGTH(sizeof(*rtm));
if (cmd == SIOCDELRT) {
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
new file mode 100644
index 00000000000..0671569ee6f
--- /dev/null
+++ b/net/ipv4/fib_trie.c
@@ -0,0 +1,2454 @@
+/*
+ * 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.
+ *
+ * Robert Olsson <robert.olsson@its.uu.se> Uppsala Universitet
+ * & Swedish University of Agricultural Sciences.
+ *
+ * Jens Laas <jens.laas@data.slu.se> Swedish University of
+ * Agricultural Sciences.
+ *
+ * Hans Liss <hans.liss@its.uu.se> Uppsala Universitet
+ *
+ * This work is based on the LPC-trie which is originally descibed in:
+ *
+ * An experimental study of compression methods for dynamic tries
+ * Stefan Nilsson and Matti Tikkanen. Algorithmica, 33(1):19-33, 2002.
+ * http://www.nada.kth.se/~snilsson/public/papers/dyntrie2/
+ *
+ *
+ * IP-address lookup using LC-tries. Stefan Nilsson and Gunnar Karlsson
+ * IEEE Journal on Selected Areas in Communications, 17(6):1083-1092, June 1999
+ *
+ * Version: $Id: fib_trie.c,v 1.3 2005/06/08 14:20:01 robert Exp $
+ *
+ *
+ * Code from fib_hash has been reused which includes the following header:
+ *
+ *
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * IPv4 FIB: lookup engine and maintenance routines.
+ *
+ *
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ * 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.
+ */
+
+#define VERSION "0.323"
+
+#include <linux/config.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/errno.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <net/route.h>
+#include <net/tcp.h>
+#include <net/sock.h>
+#include <net/ip_fib.h>
+#include "fib_lookup.h"
+
+#undef CONFIG_IP_FIB_TRIE_STATS
+#define MAX_CHILDS 16384
+
+#define EXTRACT(p, n, str) ((str)<<(p)>>(32-(n)))
+#define KEYLENGTH (8*sizeof(t_key))
+#define MASK_PFX(k, l) (((l)==0)?0:(k >> (KEYLENGTH-l)) << (KEYLENGTH-l))
+#define TKEY_GET_MASK(offset, bits) (((bits)==0)?0:((t_key)(-1) << (KEYLENGTH - bits) >> offset))
+
+static DEFINE_RWLOCK(fib_lock);
+
+typedef unsigned int t_key;
+
+#define T_TNODE 0
+#define T_LEAF 1
+#define NODE_TYPE_MASK 0x1UL
+#define NODE_PARENT(_node) \
+((struct tnode *)((_node)->_parent & ~NODE_TYPE_MASK))
+#define NODE_SET_PARENT(_node, _ptr) \
+((_node)->_parent = (((unsigned long)(_ptr)) | \
+ ((_node)->_parent & NODE_TYPE_MASK)))
+#define NODE_INIT_PARENT(_node, _type) \
+((_node)->_parent = (_type))
+#define NODE_TYPE(_node) \
+((_node)->_parent & NODE_TYPE_MASK)
+
+#define IS_TNODE(n) (!(n->_parent & T_LEAF))
+#define IS_LEAF(n) (n->_parent & T_LEAF)
+
+struct node {
+ t_key key;
+ unsigned long _parent;
+};
+
+struct leaf {
+ t_key key;
+ unsigned long _parent;
+ struct hlist_head list;
+};
+
+struct leaf_info {
+ struct hlist_node hlist;
+ int plen;
+ struct list_head falh;
+};
+
+struct tnode {
+ t_key key;
+ unsigned long _parent;
+ unsigned short pos:5; /* 2log(KEYLENGTH) bits needed */
+ unsigned short bits:5; /* 2log(KEYLENGTH) bits needed */
+ unsigned short full_children; /* KEYLENGTH bits needed */
+ unsigned short empty_children; /* KEYLENGTH bits needed */
+ struct node *child[0];
+};
+
+#ifdef CONFIG_IP_FIB_TRIE_STATS
+struct trie_use_stats {
+ unsigned int gets;
+ unsigned int backtrack;
+ unsigned int semantic_match_passed;
+ unsigned int semantic_match_miss;
+ unsigned int null_node_hit;
+};
+#endif
+
+struct trie_stat {
+ unsigned int totdepth;
+ unsigned int maxdepth;
+ unsigned int tnodes;
+ unsigned int leaves;
+ unsigned int nullpointers;
+ unsigned int nodesizes[MAX_CHILDS];
+};
+
+struct trie {
+ struct node *trie;
+#ifdef CONFIG_IP_FIB_TRIE_STATS
+ struct trie_use_stats stats;
+#endif
+ int size;
+ unsigned int revision;
+};
+
+static int trie_debug = 0;
+
+static int tnode_full(struct tnode *tn, struct node *n);
+static void put_child(struct trie *t, struct tnode *tn, int i, struct node *n);
+static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n, int wasfull);
+static int tnode_child_length(struct tnode *tn);
+static struct node *resize(struct trie *t, struct tnode *tn);
+static struct tnode *inflate(struct trie *t, struct tnode *tn);
+static struct tnode *halve(struct trie *t, struct tnode *tn);
+static void tnode_free(struct tnode *tn);
+static void trie_dump_seq(struct seq_file *seq, struct trie *t);
+extern struct fib_alias *fib_find_alias(struct list_head *fah, u8 tos, u32 prio);
+extern int fib_detect_death(struct fib_info *fi, int order,
+ struct fib_info **last_resort, int *last_idx, int *dflt);
+
+extern void rtmsg_fib(int event, u32 key, struct fib_alias *fa, int z, int tb_id,
+ struct nlmsghdr *n, struct netlink_skb_parms *req);
+
+static kmem_cache_t *fn_alias_kmem;
+static struct trie *trie_local = NULL, *trie_main = NULL;
+
+static void trie_bug(char *err)
+{
+ printk("Trie Bug: %s\n", err);
+ BUG();
+}
+
+static inline struct node *tnode_get_child(struct tnode *tn, int i)
+{
+ if (i >= 1<<tn->bits)
+ trie_bug("tnode_get_child");
+
+ return tn->child[i];
+}
+
+static inline int tnode_child_length(struct tnode *tn)
+{
+ return 1<<tn->bits;
+}
+
+/*
+ _________________________________________________________________
+ | i | i | i | i | i | i | i | N | N | N | S | S | S | S | S | C |
+ ----------------------------------------------------------------
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+
+ _________________________________________________________________
+ | C | C | C | u | u | u | u | u | u | u | u | u | u | u | u | u |
+ -----------------------------------------------------------------
+ 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+
+ tp->pos = 7
+ tp->bits = 3
+ n->pos = 15
+ n->bits=4
+ KEYLENGTH=32
+*/
+
+static inline t_key tkey_extract_bits(t_key a, int offset, int bits)
+{
+ if (offset < KEYLENGTH)
+ return ((t_key)(a << offset)) >> (KEYLENGTH - bits);
+ else
+ return 0;
+}
+
+static inline int tkey_equals(t_key a, t_key b)
+{
+ return a == b;
+}
+
+static inline int tkey_sub_equals(t_key a, int offset, int bits, t_key b)
+{
+ if (bits == 0 || offset >= KEYLENGTH)
+ return 1;
+ bits = bits > KEYLENGTH ? KEYLENGTH : bits;
+ return ((a ^ b) << offset) >> (KEYLENGTH - bits) == 0;
+}
+
+static inline int tkey_mismatch(t_key a, int offset, t_key b)
+{
+ t_key diff = a ^ b;
+ int i = offset;
+
+ if(!diff)
+ return 0;
+ while((diff << i) >> (KEYLENGTH-1) == 0)
+ i++;
+ return i;
+}
+
+/* Candiate for fib_semantics */
+
+static void fn_free_alias(struct fib_alias *fa)
+{
+ fib_release_info(fa->fa_info);
+ kmem_cache_free(fn_alias_kmem, fa);
+}
+
+/*
+ To understand this stuff, an understanding of keys and all their bits is
+ necessary. Every node in the trie has a key associated with it, but not
+ all of the bits in that key are significant.
+
+ Consider a node 'n' and its parent 'tp'.
+
+ If n is a leaf, every bit in its key is significant. Its presence is
+ necessitaded by path compression, since during a tree traversal (when
+ searching for a leaf - unless we are doing an insertion) we will completely
+ ignore all skipped bits we encounter. Thus we need to verify, at the end of
+ a potentially successful search, that we have indeed been walking the
+ correct key path.
+
+ Note that we can never "miss" the correct key in the tree if present by
+ following the wrong path. Path compression ensures that segments of the key
+ that are the same for all keys with a given prefix are skipped, but the
+ skipped part *is* identical for each node in the subtrie below the skipped
+ bit! trie_insert() in this implementation takes care of that - note the
+ call to tkey_sub_equals() in trie_insert().
+
+ if n is an internal node - a 'tnode' here, the various parts of its key
+ have many different meanings.
+
+ Example:
+ _________________________________________________________________
+ | i | i | i | i | i | i | i | N | N | N | S | S | S | S | S | C |
+ -----------------------------------------------------------------
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+
+ _________________________________________________________________
+ | C | C | C | u | u | u | u | u | u | u | u | u | u | u | u | u |
+ -----------------------------------------------------------------
+ 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
+
+ tp->pos = 7
+ tp->bits = 3
+ n->pos = 15
+ n->bits=4
+
+ First, let's just ignore the bits that come before the parent tp, that is
+ the bits from 0 to (tp->pos-1). They are *known* but at this point we do
+ not use them for anything.
+
+ The bits from (tp->pos) to (tp->pos + tp->bits - 1) - "N", above - are the
+ index into the parent's child array. That is, they will be used to find
+ 'n' among tp's children.
+
+ The bits from (tp->pos + tp->bits) to (n->pos - 1) - "S" - are skipped bits
+ for the node n.
+
+ All the bits we have seen so far are significant to the node n. The rest
+ of the bits are really not needed or indeed known in n->key.
+
+ The bits from (n->pos) to (n->pos + n->bits - 1) - "C" - are the index into
+ n's child array, and will of course be different for each child.
+
+ The rest of the bits, from (n->pos + n->bits) onward, are completely unknown
+ at this point.
+
+*/
+
+static void check_tnode(struct tnode *tn)
+{
+ if(tn && tn->pos+tn->bits > 32) {
+ printk("TNODE ERROR tn=%p, pos=%d, bits=%d\n", tn, tn->pos, tn->bits);
+ }
+}
+
+static int halve_threshold = 25;
+static int inflate_threshold = 50;
+
+static struct leaf *leaf_new(void)
+{
+ struct leaf *l = kmalloc(sizeof(struct leaf), GFP_KERNEL);
+ if(l) {
+ NODE_INIT_PARENT(l, T_LEAF);
+ INIT_HLIST_HEAD(&l->list);
+ }
+ return l;
+}
+
+static struct leaf_info *leaf_info_new(int plen)
+{
+ struct leaf_info *li = kmalloc(sizeof(struct leaf_info), GFP_KERNEL);
+ li->plen = plen;
+ INIT_LIST_HEAD(&li->falh);
+ return li;
+}
+
+static inline void free_leaf(struct leaf *l)
+{
+ kfree(l);
+}
+
+static inline void free_leaf_info(struct leaf_info *li)
+{
+ kfree(li);
+}
+
+static struct tnode* tnode_new(t_key key, int pos, int bits)
+{
+ int nchildren = 1<<bits;
+ int sz = sizeof(struct tnode) + nchildren * sizeof(struct node *);
+ struct tnode *tn = kmalloc(sz, GFP_KERNEL);
+
+ if(tn) {
+ memset(tn, 0, sz);
+ NODE_INIT_PARENT(tn, T_TNODE);
+ tn->pos = pos;
+ tn->bits = bits;
+ tn->key = key;
+ tn->full_children = 0;
+ tn->empty_children = 1<<bits;
+ }
+ if(trie_debug > 0)
+ printk("AT %p s=%u %u\n", tn, (unsigned int) sizeof(struct tnode),
+ (unsigned int) (sizeof(struct node) * 1<<bits));
+ return tn;
+}
+
+static void tnode_free(struct tnode *tn)
+{
+ if(!tn) {
+ trie_bug("tnode_free\n");
+ }
+ if(IS_LEAF(tn)) {
+ free_leaf((struct leaf *)tn);
+ if(trie_debug > 0 )
+ printk("FL %p \n", tn);
+ }
+ else if(IS_TNODE(tn)) {
+ kfree(tn);
+ if(trie_debug > 0 )
+ printk("FT %p \n", tn);
+ }
+ else {
+ trie_bug("tnode_free\n");
+ }
+}
+
+/*
+ * Check whether a tnode 'n' is "full", i.e. it is an internal node
+ * and no bits are skipped. See discussion in dyntree paper p. 6
+ */
+
+static inline int tnode_full(struct tnode *tn, struct node *n)
+{
+ if(n == NULL || IS_LEAF(n))
+ return 0;
+
+ return ((struct tnode *) n)->pos == tn->pos + tn->bits;
+}
+
+static inline void put_child(struct trie *t, struct tnode *tn, int i, struct node *n)
+{
+ tnode_put_child_reorg(tn, i, n, -1);
+}
+
+ /*
+ * Add a child at position i overwriting the old value.
+ * Update the value of full_children and empty_children.
+ */
+
+static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n, int wasfull)
+{
+ struct node *chi;
+ int isfull;
+
+ if(i >= 1<<tn->bits) {
+ printk("bits=%d, i=%d\n", tn->bits, i);
+ trie_bug("tnode_put_child_reorg bits");
+ }
+ write_lock_bh(&fib_lock);
+ chi = tn->child[i];
+
+ /* update emptyChildren */
+ if (n == NULL && chi != NULL)
+ tn->empty_children++;
+ else if (n != NULL && chi == NULL)
+ tn->empty_children--;
+
+ /* update fullChildren */
+ if (wasfull == -1)
+ wasfull = tnode_full(tn, chi);
+
+ isfull = tnode_full(tn, n);
+ if (wasfull && !isfull)
+ tn->full_children--;
+
+ else if (!wasfull && isfull)
+ tn->full_children++;
+ if(n)
+ NODE_SET_PARENT(n, tn);
+
+ tn->child[i] = n;
+ write_unlock_bh(&fib_lock);
+}
+
+static struct node *resize(struct trie *t, struct tnode *tn)
+{
+ int i;
+
+ if (!tn)
+ return NULL;
+
+ if(trie_debug)
+ printk("In tnode_resize %p inflate_threshold=%d threshold=%d\n",
+ tn, inflate_threshold, halve_threshold);
+
+ /* No children */
+ if (tn->empty_children == tnode_child_length(tn)) {
+ tnode_free(tn);
+ return NULL;
+ }
+ /* One child */
+ if (tn->empty_children == tnode_child_length(tn) - 1)
+ for (i = 0; i < tnode_child_length(tn); i++) {
+
+ write_lock_bh(&fib_lock);
+ if (tn->child[i] != NULL) {
+
+ /* compress one level */
+ struct node *n = tn->child[i];
+ if(n)
+ NODE_INIT_PARENT(n, NODE_TYPE(n));
+
+ write_unlock_bh(&fib_lock);
+ tnode_free(tn);
+ return n;
+ }
+ write_unlock_bh(&fib_lock);
+ }
+ /*
+ * Double as long as the resulting node has a number of
+ * nonempty nodes that are above the threshold.
+ */
+
+ /*
+ * From "Implementing a dynamic compressed trie" by Stefan Nilsson of
+ * the Helsinki University of Technology and Matti Tikkanen of Nokia
+ * Telecommunications, page 6:
+ * "A node is doubled if the ratio of non-empty children to all
+ * children in the *doubled* node is at least 'high'."
+ *
+ * 'high' in this instance is the variable 'inflate_threshold'. It
+ * is expressed as a percentage, so we multiply it with
+ * tnode_child_length() and instead of multiplying by 2 (since the
+ * child array will be doubled by inflate()) and multiplying
+ * the left-hand side by 100 (to handle the percentage thing) we
+ * multiply the left-hand side by 50.
+ *
+ * The left-hand side may look a bit weird: tnode_child_length(tn)
+ * - tn->empty_children is of course the number of non-null children
+ * in the current node. tn->full_children is the number of "full"
+ * children, that is non-null tnodes with a skip value of 0.
+ * All of those will be doubled in the resulting inflated tnode, so
+ * we just count them one extra time here.
+ *
+ * A clearer way to write this would be:
+ *
+ * to_be_doubled = tn->full_children;
+ * not_to_be_doubled = tnode_child_length(tn) - tn->empty_children -
+ * tn->full_children;
+ *
+ * new_child_length = tnode_child_length(tn) * 2;
+ *
+ * new_fill_factor = 100 * (not_to_be_doubled + 2*to_be_doubled) /
+ * new_child_length;
+ * if (new_fill_factor >= inflate_threshold)
+ *
+ * ...and so on, tho it would mess up the while() loop.
+ *
+ * anyway,
+ * 100 * (not_to_be_doubled + 2*to_be_doubled) / new_child_length >=
+ * inflate_threshold
+ *
+ * avoid a division:
+ * 100 * (not_to_be_doubled + 2*to_be_doubled) >=
+ * inflate_threshold * new_child_length
+ *
+ * expand not_to_be_doubled and to_be_doubled, and shorten:
+ * 100 * (tnode_child_length(tn) - tn->empty_children +
+ * tn->full_children ) >= inflate_threshold * new_child_length
+ *
+ * expand new_child_length:
+ * 100 * (tnode_child_length(tn) - tn->empty_children +
+ * tn->full_children ) >=
+ * inflate_threshold * tnode_child_length(tn) * 2
+ *
+ * shorten again:
+ * 50 * (tn->full_children + tnode_child_length(tn) -
+ * tn->empty_children ) >= inflate_threshold *
+ * tnode_child_length(tn)
+ *
+ */
+
+ check_tnode(tn);
+
+ while ((tn->full_children > 0 &&
+ 50 * (tn->full_children + tnode_child_length(tn) - tn->empty_children) >=
+ inflate_threshold * tnode_child_length(tn))) {
+
+ tn = inflate(t, tn);
+ }
+
+ check_tnode(tn);
+
+ /*
+ * Halve as long as the number of empty children in this
+ * node is above threshold.
+ */
+ while (tn->bits > 1 &&
+ 100 * (tnode_child_length(tn) - tn->empty_children) <
+ halve_threshold * tnode_child_length(tn))
+
+ tn = halve(t, tn);
+
+ /* Only one child remains */
+
+ if (tn->empty_children == tnode_child_length(tn) - 1)
+ for (i = 0; i < tnode_child_length(tn); i++) {
+
+ write_lock_bh(&fib_lock);
+ if (tn->child[i] != NULL) {
+ /* compress one level */
+ struct node *n = tn->child[i];
+
+ if(n)
+ NODE_INIT_PARENT(n, NODE_TYPE(n));
+
+ write_unlock_bh(&fib_lock);
+ tnode_free(tn);
+ return n;
+ }
+ write_unlock_bh(&fib_lock);
+ }
+
+ return (struct node *) tn;
+}
+
+static struct tnode *inflate(struct trie *t, struct tnode *tn)
+{
+ struct tnode *inode;
+ struct tnode *oldtnode = tn;
+ int olen = tnode_child_length(tn);
+ int i;
+
+ if(trie_debug)
+ printk("In inflate\n");
+
+ tn = tnode_new(oldtnode->key, oldtnode->pos, oldtnode->bits + 1);
+
+ if (!tn)
+ trie_bug("tnode_new failed");
+
+ for(i = 0; i < olen; i++) {
+ struct node *node = tnode_get_child(oldtnode, i);
+
+ /* An empty child */
+ if (node == NULL)
+ continue;
+
+ /* A leaf or an internal node with skipped bits */
+
+ if(IS_LEAF(node) || ((struct tnode *) node)->pos >
+ tn->pos + tn->bits - 1) {
+ if(tkey_extract_bits(node->key, tn->pos + tn->bits - 1,
+ 1) == 0)
+ put_child(t, tn, 2*i, node);
+ else
+ put_child(t, tn, 2*i+1, node);
+ continue;
+ }
+
+ /* An internal node with two children */
+ inode = (struct tnode *) node;
+
+ if (inode->bits == 1) {
+ put_child(t, tn, 2*i, inode->child[0]);
+ put_child(t, tn, 2*i+1, inode->child[1]);
+
+ tnode_free(inode);
+ }
+
+ /* An internal node with more than two children */
+ else {
+ struct tnode *left, *right;
+ int size, j;
+
+ /* We will replace this node 'inode' with two new
+ * ones, 'left' and 'right', each with half of the
+ * original children. The two new nodes will have
+ * a position one bit further down the key and this
+ * means that the "significant" part of their keys
+ * (see the discussion near the top of this file)
+ * will differ by one bit, which will be "0" in
+ * left's key and "1" in right's key. Since we are
+ * moving the key position by one step, the bit that
+ * we are moving away from - the bit at position
+ * (inode->pos) - is the one that will differ between
+ * left and right. So... we synthesize that bit in the
+ * two new keys.
+ * The mask 'm' below will be a single "one" bit at
+ * the position (inode->pos)
+ */
+
+ t_key m = TKEY_GET_MASK(inode->pos, 1);
+
+ /* Use the old key, but set the new significant
+ * bit to zero.
+ */
+ left = tnode_new(inode->key&(~m), inode->pos + 1,
+ inode->bits - 1);
+
+ if(!left)
+ trie_bug("tnode_new failed");
+
+
+ /* Use the old key, but set the new significant
+ * bit to one.
+ */
+ right = tnode_new(inode->key|m, inode->pos + 1,
+ inode->bits - 1);
+
+ if(!right)
+ trie_bug("tnode_new failed");
+
+ size = tnode_child_length(left);
+ for(j = 0; j < size; j++) {
+ put_child(t, left, j, inode->child[j]);
+ put_child(t, right, j, inode->child[j + size]);
+ }
+ put_child(t, tn, 2*i, resize(t, left));
+ put_child(t, tn, 2*i+1, resize(t, right));
+
+ tnode_free(inode);
+ }
+ }
+ tnode_free(oldtnode);
+ return tn;
+}
+
+static struct tnode *halve(struct trie *t, struct tnode *tn)
+{
+ struct tnode *oldtnode = tn;
+ struct node *left, *right;
+ int i;
+ int olen = tnode_child_length(tn);
+
+ if(trie_debug) printk("In halve\n");
+
+ tn=tnode_new(oldtnode->key, oldtnode->pos, oldtnode->bits - 1);
+
+ if(!tn)
+ trie_bug("tnode_new failed");
+
+ for(i = 0; i < olen; i += 2) {
+ left = tnode_get_child(oldtnode, i);
+ right = tnode_get_child(oldtnode, i+1);
+
+ /* At least one of the children is empty */
+ if (left == NULL) {
+ if (right == NULL) /* Both are empty */
+ continue;
+ put_child(t, tn, i/2, right);
+ } else if (right == NULL)
+ put_child(t, tn, i/2, left);
+
+ /* Two nonempty children */
+ else {
+ struct tnode *newBinNode =
+ tnode_new(left->key, tn->pos + tn->bits, 1);
+
+ if(!newBinNode)
+ trie_bug("tnode_new failed");
+
+ put_child(t, newBinNode, 0, left);
+ put_child(t, newBinNode, 1, right);
+ put_child(t, tn, i/2, resize(t, newBinNode));
+ }
+ }
+ tnode_free(oldtnode);
+ return tn;
+}
+
+static void *trie_init(struct trie *t)
+{
+ if(t) {
+ t->size = 0;
+ t->trie = NULL;
+ t->revision = 0;
+#ifdef CONFIG_IP_FIB_TRIE_STATS
+ memset(&t->stats, 0, sizeof(struct trie_use_stats));
+#endif
+ }
+ return t;
+}
+
+static struct leaf_info *find_leaf_info(struct hlist_head *head, int plen)
+{
+ struct hlist_node *node;
+ struct leaf_info *li;
+
+ hlist_for_each_entry(li, node, head, hlist) {
+
+ if ( li->plen == plen )
+ return li;
+ }
+ return NULL;
+}
+
+static inline struct list_head * get_fa_head(struct leaf *l, int plen)
+{
+ struct list_head *fa_head=NULL;
+ struct leaf_info *li = find_leaf_info(&l->list, plen);
+
+ if(li)
+ fa_head = &li->falh;
+
+ return fa_head;
+}
+
+static void insert_leaf_info(struct hlist_head *head, struct leaf_info *new)
+{
+ struct leaf_info *li=NULL, *last=NULL;
+ struct hlist_node *node, *tmp;
+
+ write_lock_bh(&fib_lock);
+
+ if(hlist_empty(head))
+ hlist_add_head(&new->hlist, head);
+ else {
+ hlist_for_each_entry_safe(li, node, tmp, head, hlist) {
+
+ if (new->plen > li->plen)
+ break;
+
+ last = li;
+ }
+ if(last)
+ hlist_add_after(&last->hlist, &new->hlist);
+ else
+ hlist_add_before(&new->hlist, &li->hlist);
+ }
+ write_unlock_bh(&fib_lock);
+}
+
+static struct leaf *
+fib_find_node(struct trie *t, u32 key)
+{
+ int pos;
+ struct tnode *tn;
+ struct node *n;
+
+ pos = 0;
+ n=t->trie;
+
+ while (n != NULL && NODE_TYPE(n) == T_TNODE) {
+ tn = (struct tnode *) n;
+
+ check_tnode(tn);
+
+ if(tkey_sub_equals(tn->key, pos, tn->pos-pos, key)) {
+ pos=tn->pos + tn->bits;
+ n = tnode_get_child(tn, tkey_extract_bits(key, tn->pos, tn->bits));
+ }
+ else
+ break;
+ }
+ /* Case we have found a leaf. Compare prefixes */
+
+ if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key)) {
+ struct leaf *l = (struct leaf *) n;
+ return l;
+ }
+ return NULL;
+}
+
+static struct node *trie_rebalance(struct trie *t, struct tnode *tn)
+{
+ int i = 0;
+ int wasfull;
+ t_key cindex, key;
+ struct tnode *tp = NULL;
+
+ if(!tn)
+ BUG();
+
+ key = tn->key;
+ i = 0;
+
+ while (tn != NULL && NODE_PARENT(tn) != NULL) {
+
+ if( i > 10 ) {
+ printk("Rebalance tn=%p \n", tn);
+ if(tn) printk("tn->parent=%p \n", NODE_PARENT(tn));
+
+ printk("Rebalance tp=%p \n", tp);
+ if(tp) printk("tp->parent=%p \n", NODE_PARENT(tp));
+ }
+
+ if( i > 12 ) BUG();
+ i++;
+
+ tp = NODE_PARENT(tn);
+ cindex = tkey_extract_bits(key, tp->pos, tp->bits);
+ wasfull = tnode_full(tp, tnode_get_child(tp, cindex));
+ tn = (struct tnode *) resize (t, (struct tnode *)tn);
+ tnode_put_child_reorg((struct tnode *)tp, cindex,(struct node*)tn, wasfull);
+
+ if(!NODE_PARENT(tn))
+ break;
+
+ tn = NODE_PARENT(tn);
+ }
+ /* Handle last (top) tnode */
+ if (IS_TNODE(tn))
+ tn = (struct tnode*) resize(t, (struct tnode *)tn);
+
+ return (struct node*) tn;
+}
+
+static struct list_head *
+fib_insert_node(struct trie *t, u32 key, int plen)
+{
+ int pos, newpos;
+ struct tnode *tp = NULL, *tn = NULL;
+ struct node *n;
+ struct leaf *l;
+ int missbit;
+ struct list_head *fa_head=NULL;
+ struct leaf_info *li;
+ t_key cindex;
+
+ pos = 0;
+ n=t->trie;
+
+ /* If we point to NULL, stop. Either the tree is empty and we should
+ * just put a new leaf in if, or we have reached an empty child slot,
+ * and we should just put our new leaf in that.
+ * If we point to a T_TNODE, check if it matches our key. Note that
+ * a T_TNODE might be skipping any number of bits - its 'pos' need
+ * not be the parent's 'pos'+'bits'!
+ *
+ * If it does match the current key, get pos/bits from it, extract
+ * the index from our key, push the T_TNODE and walk the tree.
+ *
+ * If it doesn't, we have to replace it with a new T_TNODE.
+ *
+ * If we point to a T_LEAF, it might or might not have the same key
+ * as we do. If it does, just change the value, update the T_LEAF's
+ * value, and return it.
+ * If it doesn't, we need to replace it with a T_TNODE.
+ */
+
+ while (n != NULL && NODE_TYPE(n) == T_TNODE) {
+ tn = (struct tnode *) n;
+
+ check_tnode(tn);
+
+ if(tkey_sub_equals(tn->key, pos, tn->pos-pos, key)) {
+ tp = tn;
+ pos=tn->pos + tn->bits;
+ n = tnode_get_child(tn, tkey_extract_bits(key, tn->pos, tn->bits));
+
+ if(n && NODE_PARENT(n) != tn) {
+ printk("BUG tn=%p, n->parent=%p\n", tn, NODE_PARENT(n));
+ BUG();
+ }
+ }
+ else
+ break;
+ }
+
+ /*
+ * n ----> NULL, LEAF or TNODE
+ *
+ * tp is n's (parent) ----> NULL or TNODE
+ */
+
+ if(tp && IS_LEAF(tp))
+ BUG();
+
+ t->revision++;
+
+ /* Case 1: n is a leaf. Compare prefixes */
+
+ if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key)) {
+ struct leaf *l = ( struct leaf *) n;
+
+ li = leaf_info_new(plen);
+
+ if(! li)
+ BUG();
+
+ fa_head = &li->falh;
+ insert_leaf_info(&l->list, li);
+ goto done;
+ }
+ t->size++;
+ l = leaf_new();
+
+ if(! l)
+ BUG();
+
+ l->key = key;
+ li = leaf_info_new(plen);
+
+ if(! li)
+ BUG();
+
+ fa_head = &li->falh;
+ insert_leaf_info(&l->list, li);
+
+ /* Case 2: n is NULL, and will just insert a new leaf */
+ if (t->trie && n == NULL) {
+
+ NODE_SET_PARENT(l, tp);
+
+ if (!tp)
+ BUG();
+
+ else {
+ cindex = tkey_extract_bits(key, tp->pos, tp->bits);
+ put_child(t, (struct tnode *)tp, cindex, (struct node *)l);
+ }
+ }
+ /* Case 3: n is a LEAF or a TNODE and the key doesn't match. */
+ else {
+ /*
+ * Add a new tnode here
+ * first tnode need some special handling
+ */
+
+ if (tp)
+ pos=tp->pos+tp->bits;
+ else
+ pos=0;
+ if(n) {
+ newpos = tkey_mismatch(key, pos, n->key);
+ tn = tnode_new(n->key, newpos, 1);
+ }
+ else {
+ newpos = 0;
+ tn = tnode_new(key, newpos, 1); /* First tnode */
+ }
+ if(!tn)
+ trie_bug("tnode_pfx_new failed");
+
+ NODE_SET_PARENT(tn, tp);
+
+ missbit=tkey_extract_bits(key, newpos, 1);
+ put_child(t, tn, missbit, (struct node *)l);
+ put_child(t, tn, 1-missbit, n);
+
+ if(tp) {
+ cindex = tkey_extract_bits(key, tp->pos, tp->bits);
+ put_child(t, (struct tnode *)tp, cindex, (struct node *)tn);
+ }
+ else {
+ t->trie = (struct node*) tn; /* First tnode */
+ tp = tn;
+ }
+ }
+ if(tp && tp->pos+tp->bits > 32) {
+ printk("ERROR tp=%p pos=%d, bits=%d, key=%0x plen=%d\n",
+ tp, tp->pos, tp->bits, key, plen);
+ }
+ /* Rebalance the trie */
+ t->trie = trie_rebalance(t, tp);
+done:;
+ return fa_head;
+}
+
+static int
+fn_trie_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
+ struct nlmsghdr *nlhdr, struct netlink_skb_parms *req)
+{
+ struct trie *t = (struct trie *) tb->tb_data;
+ struct fib_alias *fa, *new_fa;
+ struct list_head *fa_head=NULL;
+ struct fib_info *fi;
+ int plen = r->rtm_dst_len;
+ int type = r->rtm_type;
+ u8 tos = r->rtm_tos;
+ u32 key, mask;
+ int err;
+ struct leaf *l;
+
+ if (plen > 32)
+ return -EINVAL;
+
+ key = 0;
+ if (rta->rta_dst)
+ memcpy(&key, rta->rta_dst, 4);
+
+ key = ntohl(key);
+
+ if(trie_debug)
+ printk("Insert table=%d %08x/%d\n", tb->tb_id, key, plen);
+
+ mask = ntohl( inet_make_mask(plen) );
+
+ if(key & ~mask)
+ return -EINVAL;
+
+ key = key & mask;
+
+ if ((fi = fib_create_info(r, rta, nlhdr, &err)) == NULL)
+ goto err;
+
+ l = fib_find_node(t, key);
+ fa = NULL;
+
+ if(l) {
+ fa_head = get_fa_head(l, plen);
+ fa = fib_find_alias(fa_head, tos, fi->fib_priority);
+ }
+
+ /* Now fa, if non-NULL, points to the first fib alias
+ * with the same keys [prefix,tos,priority], if such key already
+ * exists or to the node before which we will insert new one.
+ *
+ * If fa is NULL, we will need to allocate a new one and
+ * insert to the head of f.
+ *
+ * If f is NULL, no fib node matched the destination key
+ * and we need to allocate a new one of those as well.
+ */
+
+ if (fa &&
+ fa->fa_info->fib_priority == fi->fib_priority) {
+ struct fib_alias *fa_orig;
+
+ err = -EEXIST;
+ if (nlhdr->nlmsg_flags & NLM_F_EXCL)
+ goto out;
+
+ if (nlhdr->nlmsg_flags & NLM_F_REPLACE) {
+ struct fib_info *fi_drop;
+ u8 state;
+
+ write_lock_bh(&fib_lock);
+
+ fi_drop = fa->fa_info;
+ fa->fa_info = fi;
+ fa->fa_type = type;
+ fa->fa_scope = r->rtm_scope;
+ state = fa->fa_state;
+ fa->fa_state &= ~FA_S_ACCESSED;
+
+ write_unlock_bh(&fib_lock);
+
+ fib_release_info(fi_drop);
+ if (state & FA_S_ACCESSED)
+ rt_cache_flush(-1);
+
+ goto succeeded;
+ }
+ /* Error if we find a perfect match which
+ * uses the same scope, type, and nexthop
+ * information.
+ */
+ fa_orig = fa;
+ list_for_each_entry(fa, fa_orig->fa_list.prev, fa_list) {
+ if (fa->fa_tos != tos)
+ break;
+ if (fa->fa_info->fib_priority != fi->fib_priority)
+ break;
+ if (fa->fa_type == type &&
+ fa->fa_scope == r->rtm_scope &&
+ fa->fa_info == fi) {
+ goto out;
+ }
+ }
+ if (!(nlhdr->nlmsg_flags & NLM_F_APPEND))
+ fa = fa_orig;
+ }
+ err = -ENOENT;
+ if (!(nlhdr->nlmsg_flags&NLM_F_CREATE))
+ goto out;
+
+ err = -ENOBUFS;
+ new_fa = kmem_cache_alloc(fn_alias_kmem, SLAB_KERNEL);
+ if (new_fa == NULL)
+ goto out;
+
+ new_fa->fa_info = fi;
+ new_fa->fa_tos = tos;
+ new_fa->fa_type = type;
+ new_fa->fa_scope = r->rtm_scope;
+ new_fa->fa_state = 0;
+#if 0
+ new_fa->dst = NULL;
+#endif
+ /*
+ * Insert new entry to the list.
+ */
+
+ if(!fa_head)
+ fa_head = fib_insert_node(t, key, plen);
+
+ write_lock_bh(&fib_lock);
+
+ list_add_tail(&new_fa->fa_list,
+ (fa ? &fa->fa_list : fa_head));
+
+ write_unlock_bh(&fib_lock);
+
+ rt_cache_flush(-1);
+ rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id, nlhdr, req);
+succeeded:
+ return 0;
+out:
+ fib_release_info(fi);
+err:;
+ return err;
+}
+
+static inline int check_leaf(struct trie *t, struct leaf *l, t_key key, int *plen, const struct flowi *flp,
+ struct fib_result *res, int *err)
+{
+ int i;
+ t_key mask;
+ struct leaf_info *li;
+ struct hlist_head *hhead = &l->list;
+ struct hlist_node *node;
+
+ hlist_for_each_entry(li, node, hhead, hlist) {
+
+ i = li->plen;
+ mask = ntohl(inet_make_mask(i));
+ if (l->key != (key & mask))
+ continue;
+
+ if (((*err) = fib_semantic_match(&li->falh, flp, res, l->key, mask, i)) == 0) {
+ *plen = i;
+#ifdef CONFIG_IP_FIB_TRIE_STATS
+ t->stats.semantic_match_passed++;
+#endif
+ return 1;
+ }
+#ifdef CONFIG_IP_FIB_TRIE_STATS
+ t->stats.semantic_match_miss++;
+#endif
+ }
+ return 0;
+}
+
+static int
+fn_trie_lookup(struct fib_table *tb, const struct flowi *flp, struct fib_result *res)
+{
+ struct trie *t = (struct trie *) tb->tb_data;
+ int plen, ret = 0;
+ struct node *n;
+ struct tnode *pn;
+ int pos, bits;
+ t_key key=ntohl(flp->fl4_dst);
+ int chopped_off;
+ t_key cindex = 0;
+ int current_prefix_length = KEYLENGTH;
+ n = t->trie;
+
+ read_lock(&fib_lock);
+ if(!n)
+ goto failed;
+
+#ifdef CONFIG_IP_FIB_TRIE_STATS
+ t->stats.gets++;
+#endif
+
+ /* Just a leaf? */
+ if (IS_LEAF(n)) {
+ if( check_leaf(t, (struct leaf *)n, key, &plen, flp, res, &ret) )
+ goto found;
+ goto failed;
+ }
+ pn = (struct tnode *) n;
+ chopped_off = 0;
+
+ while (pn) {
+
+ pos = pn->pos;
+ bits = pn->bits;
+
+ if(!chopped_off)
+ cindex = tkey_extract_bits(MASK_PFX(key, current_prefix_length), pos, bits);
+
+ n = tnode_get_child(pn, cindex);
+
+ if (n == NULL) {
+#ifdef CONFIG_IP_FIB_TRIE_STATS
+ t->stats.null_node_hit++;
+#endif
+ goto backtrace;
+ }
+
+ if (IS_TNODE(n)) {
+#define HL_OPTIMIZE
+#ifdef HL_OPTIMIZE
+ struct tnode *cn = (struct tnode *)n;
+ t_key node_prefix, key_prefix, pref_mismatch;
+ int mp;
+
+ /*
+ * It's a tnode, and we can do some extra checks here if we
+ * like, to avoid descending into a dead-end branch.
+ * This tnode is in the parent's child array at index
+ * key[p_pos..p_pos+p_bits] but potentially with some bits
+ * chopped off, so in reality the index may be just a
+ * subprefix, padded with zero at the end.
+ * We can also take a look at any skipped bits in this
+ * tnode - everything up to p_pos is supposed to be ok,
+ * and the non-chopped bits of the index (se previous
+ * paragraph) are also guaranteed ok, but the rest is
+ * considered unknown.
+ *
+ * The skipped bits are key[pos+bits..cn->pos].
+ */
+
+ /* If current_prefix_length < pos+bits, we are already doing
+ * actual prefix matching, which means everything from
+ * pos+(bits-chopped_off) onward must be zero along some
+ * branch of this subtree - otherwise there is *no* valid
+ * prefix present. Here we can only check the skipped
+ * bits. Remember, since we have already indexed into the
+ * parent's child array, we know that the bits we chopped of
+ * *are* zero.
+ */
+
+ /* NOTA BENE: CHECKING ONLY SKIPPED BITS FOR THE NEW NODE HERE */
+
+ if (current_prefix_length < pos+bits) {
+ if (tkey_extract_bits(cn->key, current_prefix_length,
+ cn->pos - current_prefix_length) != 0 ||
+ !(cn->child[0]))
+ goto backtrace;
+ }
+
+ /*
+ * If chopped_off=0, the index is fully validated and we
+ * only need to look at the skipped bits for this, the new,
+ * tnode. What we actually want to do is to find out if
+ * these skipped bits match our key perfectly, or if we will
+ * have to count on finding a matching prefix further down,
+ * because if we do, we would like to have some way of
+ * verifying the existence of such a prefix at this point.
+ */
+
+ /* The only thing we can do at this point is to verify that
+ * any such matching prefix can indeed be a prefix to our
+ * key, and if the bits in the node we are inspecting that
+ * do not match our key are not ZERO, this cannot be true.
+ * Thus, find out where there is a mismatch (before cn->pos)
+ * and verify that all the mismatching bits are zero in the
+ * new tnode's key.
+ */
+
+ /* Note: We aren't very concerned about the piece of the key
+ * that precede pn->pos+pn->bits, since these have already been
+ * checked. The bits after cn->pos aren't checked since these are
+ * by definition "unknown" at this point. Thus, what we want to
+ * see is if we are about to enter the "prefix matching" state,
+ * and in that case verify that the skipped bits that will prevail
+ * throughout this subtree are zero, as they have to be if we are
+ * to find a matching prefix.
+ */
+
+ node_prefix = MASK_PFX(cn->key, cn->pos);
+ key_prefix = MASK_PFX(key, cn->pos);
+ pref_mismatch = key_prefix^node_prefix;
+ mp = 0;
+
+ /* In short: If skipped bits in this node do not match the search
+ * key, enter the "prefix matching" state.directly.
+ */
+ if (pref_mismatch) {
+ while (!(pref_mismatch & (1<<(KEYLENGTH-1)))) {
+ mp++;
+ pref_mismatch = pref_mismatch <<1;
+ }
+ key_prefix = tkey_extract_bits(cn->key, mp, cn->pos-mp);
+
+ if (key_prefix != 0)
+ goto backtrace;
+
+ if (current_prefix_length >= cn->pos)
+ current_prefix_length=mp;
+ }
+#endif
+ pn = (struct tnode *)n; /* Descend */
+ chopped_off = 0;
+ continue;
+ }
+ if (IS_LEAF(n)) {
+ if( check_leaf(t, (struct leaf *)n, key, &plen, flp, res, &ret))
+ goto found;
+ }
+backtrace:
+ chopped_off++;
+
+ /* As zero don't change the child key (cindex) */
+ while ((chopped_off <= pn->bits) && !(cindex & (1<<(chopped_off-1)))) {
+ chopped_off++;
+ }
+
+ /* Decrease current_... with bits chopped off */
+ if (current_prefix_length > pn->pos + pn->bits - chopped_off)
+ current_prefix_length = pn->pos + pn->bits - chopped_off;
+
+ /*
+ * Either we do the actual chop off according or if we have
+ * chopped off all bits in this tnode walk up to our parent.
+ */
+
+ if(chopped_off <= pn->bits)
+ cindex &= ~(1 << (chopped_off-1));
+ else {
+ if( NODE_PARENT(pn) == NULL)
+ goto failed;
+
+ /* Get Child's index */
+ cindex = tkey_extract_bits(pn->key, NODE_PARENT(pn)->pos, NODE_PARENT(pn)->bits);
+ pn = NODE_PARENT(pn);
+ chopped_off = 0;
+
+#ifdef CONFIG_IP_FIB_TRIE_STATS
+ t->stats.backtrack++;
+#endif
+ goto backtrace;
+ }
+ }
+failed:
+ ret = 1;
+found:
+ read_unlock(&fib_lock);
+ return ret;
+}
+
+static int trie_leaf_remove(struct trie *t, t_key key)
+{
+ t_key cindex;
+ struct tnode *tp = NULL;
+ struct node *n = t->trie;
+ struct leaf *l;
+
+ if(trie_debug)
+ printk("entering trie_leaf_remove(%p)\n", n);
+
+ /* Note that in the case skipped bits, those bits are *not* checked!
+ * When we finish this, we will have NULL or a T_LEAF, and the
+ * T_LEAF may or may not match our key.
+ */
+
+ while (n != NULL && IS_TNODE(n)) {
+ struct tnode *tn = (struct tnode *) n;
+ check_tnode(tn);
+ n = tnode_get_child(tn ,tkey_extract_bits(key, tn->pos, tn->bits));
+
+ if(n && NODE_PARENT(n) != tn) {
+ printk("BUG tn=%p, n->parent=%p\n", tn, NODE_PARENT(n));
+ BUG();
+ }
+ }
+ l = (struct leaf *) n;
+
+ if(!n || !tkey_equals(l->key, key))
+ return 0;
+
+ /*
+ * Key found.
+ * Remove the leaf and rebalance the tree
+ */
+
+ t->revision++;
+ t->size--;
+
+ tp = NODE_PARENT(n);
+ tnode_free((struct tnode *) n);
+
+ if(tp) {
+ cindex = tkey_extract_bits(key, tp->pos, tp->bits);
+ put_child(t, (struct tnode *)tp, cindex, NULL);
+ t->trie = trie_rebalance(t, tp);
+ }
+ else
+ t->trie = NULL;
+
+ return 1;
+}
+
+static int
+fn_trie_delete(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
+ struct nlmsghdr *nlhdr, struct netlink_skb_parms *req)
+{
+ struct trie *t = (struct trie *) tb->tb_data;
+ u32 key, mask;
+ int plen = r->rtm_dst_len;
+ u8 tos = r->rtm_tos;
+ struct fib_alias *fa, *fa_to_delete;
+ struct list_head *fa_head;
+ struct leaf *l;
+
+ if (plen > 32)
+ return -EINVAL;
+
+ key = 0;
+ if (rta->rta_dst)
+ memcpy(&key, rta->rta_dst, 4);
+
+ key = ntohl(key);
+ mask = ntohl( inet_make_mask(plen) );
+
+ if(key & ~mask)
+ return -EINVAL;
+
+ key = key & mask;
+ l = fib_find_node(t, key);
+
+ if(!l)
+ return -ESRCH;
+
+ fa_head = get_fa_head(l, plen);
+ fa = fib_find_alias(fa_head, tos, 0);
+
+ if (!fa)
+ return -ESRCH;
+
+ if (trie_debug)
+ printk("Deleting %08x/%d tos=%d t=%p\n", key, plen, tos, t);
+
+ fa_to_delete = NULL;
+ fa_head = fa->fa_list.prev;
+ list_for_each_entry(fa, fa_head, fa_list) {
+ struct fib_info *fi = fa->fa_info;
+
+ if (fa->fa_tos != tos)
+ break;
+
+ if ((!r->rtm_type ||
+ fa->fa_type == r->rtm_type) &&
+ (r->rtm_scope == RT_SCOPE_NOWHERE ||
+ fa->fa_scope == r->rtm_scope) &&
+ (!r->rtm_protocol ||
+ fi->fib_protocol == r->rtm_protocol) &&
+ fib_nh_match(r, nlhdr, rta, fi) == 0) {
+ fa_to_delete = fa;
+ break;
+ }
+ }
+
+ if (fa_to_delete) {
+ int kill_li = 0;
+ struct leaf_info *li;
+
+ fa = fa_to_delete;
+ rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id, nlhdr, req);
+
+ l = fib_find_node(t, key);
+ li = find_leaf_info(&l->list, plen);
+
+ write_lock_bh(&fib_lock);
+
+ list_del(&fa->fa_list);
+
+ if(list_empty(fa_head)) {
+ hlist_del(&li->hlist);
+ kill_li = 1;
+ }
+ write_unlock_bh(&fib_lock);
+
+ if(kill_li)
+ free_leaf_info(li);
+
+ if(hlist_empty(&l->list))
+ trie_leaf_remove(t, key);
+
+ if (fa->fa_state & FA_S_ACCESSED)
+ rt_cache_flush(-1);
+
+ fn_free_alias(fa);
+ return 0;
+ }
+ return -ESRCH;
+}
+
+static int trie_flush_list(struct trie *t, struct list_head *head)
+{
+ struct fib_alias *fa, *fa_node;
+ int found = 0;
+
+ list_for_each_entry_safe(fa, fa_node, head, fa_list) {
+ struct fib_info *fi = fa->fa_info;
+
+ if (fi && (fi->fib_flags&RTNH_F_DEAD)) {
+
+ write_lock_bh(&fib_lock);
+ list_del(&fa->fa_list);
+ write_unlock_bh(&fib_lock);
+
+ fn_free_alias(fa);
+ found++;
+ }
+ }
+ return found;
+}
+
+static int trie_flush_leaf(struct trie *t, struct leaf *l)
+{
+ int found = 0;
+ struct hlist_head *lih = &l->list;
+ struct hlist_node *node, *tmp;
+ struct leaf_info *li = NULL;
+
+ hlist_for_each_entry_safe(li, node, tmp, lih, hlist) {
+
+ found += trie_flush_list(t, &li->falh);
+
+ if (list_empty(&li->falh)) {
+
+ write_lock_bh(&fib_lock);
+ hlist_del(&li->hlist);
+ write_unlock_bh(&fib_lock);
+
+ free_leaf_info(li);
+ }
+ }
+ return found;
+}
+
+static struct leaf *nextleaf(struct trie *t, struct leaf *thisleaf)
+{
+ struct node *c = (struct node *) thisleaf;
+ struct tnode *p;
+ int idx;
+
+ if(c == NULL) {
+ if(t->trie == NULL)
+ return NULL;
+
+ if (IS_LEAF(t->trie)) /* trie w. just a leaf */
+ return (struct leaf *) t->trie;
+
+ p = (struct tnode*) t->trie; /* Start */
+ }
+ else
+ p = (struct tnode *) NODE_PARENT(c);
+ while (p) {
+ int pos, last;
+
+ /* Find the next child of the parent */
+ if(c)
+ pos = 1 + tkey_extract_bits(c->key, p->pos, p->bits);
+ else
+ pos = 0;
+
+ last = 1 << p->bits;
+ for(idx = pos; idx < last ; idx++) {
+ if( p->child[idx]) {
+
+ /* Decend if tnode */
+
+ while (IS_TNODE(p->child[idx])) {
+ p = (struct tnode*) p->child[idx];
+ idx = 0;
+
+ /* Rightmost non-NULL branch */
+ if( p && IS_TNODE(p) )
+ while ( p->child[idx] == NULL && idx < (1 << p->bits) ) idx++;
+
+ /* Done with this tnode? */
+ if( idx >= (1 << p->bits) || p->child[idx] == NULL )
+ goto up;
+ }
+ return (struct leaf*) p->child[idx];
+ }
+ }
+up:
+ /* No more children go up one step */
+ c = (struct node*) p;
+ p = (struct tnode *) NODE_PARENT(p);
+ }
+ return NULL; /* Ready. Root of trie */
+}
+
+static int fn_trie_flush(struct fib_table *tb)
+{
+ struct trie *t = (struct trie *) tb->tb_data;
+ struct leaf *ll = NULL, *l = NULL;
+ int found = 0, h;
+
+ t->revision++;
+
+ for (h=0; (l = nextleaf(t, l)) != NULL; h++) {
+ found += trie_flush_leaf(t, l);
+
+ if (ll && hlist_empty(&ll->list))
+ trie_leaf_remove(t, ll->key);
+ ll = l;
+ }
+
+ if (ll && hlist_empty(&ll->list))
+ trie_leaf_remove(t, ll->key);
+
+ if(trie_debug)
+ printk("trie_flush found=%d\n", found);
+ return found;
+}
+
+static int trie_last_dflt=-1;
+
+static void
+fn_trie_select_default(struct fib_table *tb, const struct flowi *flp, struct fib_result *res)
+{
+ struct trie *t = (struct trie *) tb->tb_data;
+ int order, last_idx;
+ struct fib_info *fi = NULL;
+ struct fib_info *last_resort;
+ struct fib_alias *fa = NULL;
+ struct list_head *fa_head;
+ struct leaf *l;
+
+ last_idx = -1;
+ last_resort = NULL;
+ order = -1;
+
+ read_lock(&fib_lock);
+
+ l = fib_find_node(t, 0);
+ if(!l)
+ goto out;
+
+ fa_head = get_fa_head(l, 0);
+ if(!fa_head)
+ goto out;
+
+ if (list_empty(fa_head))
+ goto out;
+
+ list_for_each_entry(fa, fa_head, fa_list) {
+ struct fib_info *next_fi = fa->fa_info;
+
+ if (fa->fa_scope != res->scope ||
+ fa->fa_type != RTN_UNICAST)
+ continue;
+
+ if (next_fi->fib_priority > res->fi->fib_priority)
+ break;
+ if (!next_fi->fib_nh[0].nh_gw ||
+ next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK)
+ continue;
+ fa->fa_state |= FA_S_ACCESSED;
+
+ if (fi == NULL) {
+ if (next_fi != res->fi)
+ break;
+ } else if (!fib_detect_death(fi, order, &last_resort,
+ &last_idx, &trie_last_dflt)) {
+ if (res->fi)
+ fib_info_put(res->fi);
+ res->fi = fi;
+ atomic_inc(&fi->fib_clntref);
+ trie_last_dflt = order;
+ goto out;
+ }
+ fi = next_fi;
+ order++;
+ }
+ if (order <= 0 || fi == NULL) {
+ trie_last_dflt = -1;
+ goto out;
+ }
+
+ if (!fib_detect_death(fi, order, &last_resort, &last_idx, &trie_last_dflt)) {
+ if (res->fi)
+ fib_info_put(res->fi);
+ res->fi = fi;
+ atomic_inc(&fi->fib_clntref);
+ trie_last_dflt = order;
+ goto out;
+ }
+ if (last_idx >= 0) {
+ if (res->fi)
+ fib_info_put(res->fi);
+ res->fi = last_resort;
+ if (last_resort)
+ atomic_inc(&last_resort->fib_clntref);
+ }
+ trie_last_dflt = last_idx;
+ out:;
+ read_unlock(&fib_lock);
+}
+
+static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah, struct fib_table *tb,
+ struct sk_buff *skb, struct netlink_callback *cb)
+{
+ int i, s_i;
+ struct fib_alias *fa;
+
+ u32 xkey=htonl(key);
+
+ s_i=cb->args[3];
+ i = 0;
+
+ list_for_each_entry(fa, fah, fa_list) {
+ if (i < s_i) {
+ i++;
+ continue;
+ }
+ if (fa->fa_info->fib_nh == NULL) {
+ printk("Trie error _fib_nh=NULL in fa[%d] k=%08x plen=%d\n", i, key, plen);
+ i++;
+ continue;
+ }
+ if (fa->fa_info == NULL) {
+ printk("Trie error fa_info=NULL in fa[%d] k=%08x plen=%d\n", i, key, plen);
+ i++;
+ continue;
+ }
+
+ if (fib_dump_info(skb, NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq,
+ RTM_NEWROUTE,
+ tb->tb_id,
+ fa->fa_type,
+ fa->fa_scope,
+ &xkey,
+ plen,
+ fa->fa_tos,
+ fa->fa_info, 0) < 0) {
+ cb->args[3] = i;
+ return -1;
+ }
+ i++;
+ }
+ cb->args[3]=i;
+ return skb->len;
+}
+
+static int fn_trie_dump_plen(struct trie *t, int plen, struct fib_table *tb, struct sk_buff *skb,
+ struct netlink_callback *cb)
+{
+ int h, s_h;
+ struct list_head *fa_head;
+ struct leaf *l = NULL;
+ s_h=cb->args[2];
+
+ for (h=0; (l = nextleaf(t, l)) != NULL; h++) {
+
+ if (h < s_h)
+ continue;
+ if (h > s_h)
+ memset(&cb->args[3], 0,
+ sizeof(cb->args) - 3*sizeof(cb->args[0]));
+
+ fa_head = get_fa_head(l, plen);
+
+ if(!fa_head)
+ continue;
+
+ if(list_empty(fa_head))
+ continue;
+
+ if (fn_trie_dump_fa(l->key, plen, fa_head, tb, skb, cb)<0) {
+ cb->args[2]=h;
+ return -1;
+ }
+ }
+ cb->args[2]=h;
+ return skb->len;
+}
+
+static int fn_trie_dump(struct fib_table *tb, struct sk_buff *skb, struct netlink_callback *cb)
+{
+ int m, s_m;
+ struct trie *t = (struct trie *) tb->tb_data;
+
+ s_m = cb->args[1];
+
+ read_lock(&fib_lock);
+ for (m=0; m<=32; m++) {
+
+ if (m < s_m)
+ continue;
+ if (m > s_m)
+ memset(&cb->args[2], 0,
+ sizeof(cb->args) - 2*sizeof(cb->args[0]));
+
+ if (fn_trie_dump_plen(t, 32-m, tb, skb, cb)<0) {
+ cb->args[1] = m;
+ goto out;
+ }
+ }
+ read_unlock(&fib_lock);
+ cb->args[1] = m;
+ return skb->len;
+ out:
+ read_unlock(&fib_lock);
+ return -1;
+}
+
+/* Fix more generic FIB names for init later */
+
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+struct fib_table * fib_hash_init(int id)
+#else
+struct fib_table * __init fib_hash_init(int id)
+#endif
+{
+ struct fib_table *tb;
+ struct trie *t;
+
+ if (fn_alias_kmem == NULL)
+ fn_alias_kmem = kmem_cache_create("ip_fib_alias",
+ sizeof(struct fib_alias),
+ 0, SLAB_HWCACHE_ALIGN,
+ NULL, NULL);
+
+ tb = kmalloc(sizeof(struct fib_table) + sizeof(struct trie),
+ GFP_KERNEL);
+ if (tb == NULL)
+ return NULL;
+
+ tb->tb_id = id;
+ tb->tb_lookup = fn_trie_lookup;
+ tb->tb_insert = fn_trie_insert;
+ tb->tb_delete = fn_trie_delete;
+ tb->tb_flush = fn_trie_flush;
+ tb->tb_select_default = fn_trie_select_default;
+ tb->tb_dump = fn_trie_dump;
+ memset(tb->tb_data, 0, sizeof(struct trie));
+
+ t = (struct trie *) tb->tb_data;
+
+ trie_init(t);
+
+ if (id == RT_TABLE_LOCAL)
+ trie_local=t;
+ else if (id == RT_TABLE_MAIN)
+ trie_main=t;
+
+ if (id == RT_TABLE_LOCAL)
+ printk("IPv4 FIB: Using LC-trie version %s\n", VERSION);
+
+ return tb;
+}
+
+/* Trie dump functions */
+
+static void putspace_seq(struct seq_file *seq, int n)
+{
+ while (n--) seq_printf(seq, " ");
+}
+
+static void printbin_seq(struct seq_file *seq, unsigned int v, int bits)
+{
+ while (bits--)
+ seq_printf(seq, "%s", (v & (1<<bits))?"1":"0");
+}
+
+static void printnode_seq(struct seq_file *seq, int indent, struct node *n,
+ int pend, int cindex, int bits)
+{
+ putspace_seq(seq, indent);
+ if (IS_LEAF(n))
+ seq_printf(seq, "|");
+ else
+ seq_printf(seq, "+");
+ if (bits) {
+ seq_printf(seq, "%d/", cindex);
+ printbin_seq(seq, cindex, bits);
+ seq_printf(seq, ": ");
+ }
+ else
+ seq_printf(seq, "<root>: ");
+ seq_printf(seq, "%s:%p ", IS_LEAF(n)?"Leaf":"Internal node", n);
+
+ if (IS_LEAF(n))
+ seq_printf(seq, "key=%d.%d.%d.%d\n",
+ n->key >> 24, (n->key >> 16) % 256, (n->key >> 8) % 256, n->key % 256);
+ else {
+ int plen=((struct tnode *)n)->pos;
+ t_key prf=MASK_PFX(n->key, plen);
+ seq_printf(seq, "key=%d.%d.%d.%d/%d\n",
+ prf >> 24, (prf >> 16) % 256, (prf >> 8) % 256, prf % 256, plen);
+ }
+ if (IS_LEAF(n)) {
+ struct leaf *l=(struct leaf *)n;
+ struct fib_alias *fa;
+ int i;
+ for (i=32; i>=0; i--)
+ if(find_leaf_info(&l->list, i)) {
+
+ struct list_head *fa_head = get_fa_head(l, i);
+
+ if(!fa_head)
+ continue;
+
+ if(list_empty(fa_head))
+ continue;
+
+ putspace_seq(seq, indent+2);
+ seq_printf(seq, "{/%d...dumping}\n", i);
+
+
+ list_for_each_entry(fa, fa_head, fa_list) {
+ putspace_seq(seq, indent+2);
+ if (fa->fa_info->fib_nh == NULL) {
+ seq_printf(seq, "Error _fib_nh=NULL\n");
+ continue;
+ }
+ if (fa->fa_info == NULL) {
+ seq_printf(seq, "Error fa_info=NULL\n");
+ continue;
+ }
+
+ seq_printf(seq, "{type=%d scope=%d TOS=%d}\n",
+ fa->fa_type,
+ fa->fa_scope,
+ fa->fa_tos);
+ }
+ }
+ }
+ else if (IS_TNODE(n)) {
+ struct tnode *tn=(struct tnode *)n;
+ putspace_seq(seq, indent); seq_printf(seq, "| ");
+ seq_printf(seq, "{key prefix=%08x/", tn->key&TKEY_GET_MASK(0, tn->pos));
+ printbin_seq(seq, tkey_extract_bits(tn->key, 0, tn->pos), tn->pos);
+ seq_printf(seq, "}\n");
+ putspace_seq(seq, indent); seq_printf(seq, "| ");
+ seq_printf(seq, "{pos=%d", tn->pos);
+ seq_printf(seq, " (skip=%d bits)", tn->pos - pend);
+ seq_printf(seq, " bits=%d (%u children)}\n", tn->bits, (1 << tn->bits));
+ putspace_seq(seq, indent); seq_printf(seq, "| ");
+ seq_printf(seq, "{empty=%d full=%d}\n", tn->empty_children, tn->full_children);
+ }
+}
+
+static void trie_dump_seq(struct seq_file *seq, struct trie *t)
+{
+ struct node *n=t->trie;
+ int cindex=0;
+ int indent=1;
+ int pend=0;
+ int depth = 0;
+
+ read_lock(&fib_lock);
+
+ seq_printf(seq, "------ trie_dump of t=%p ------\n", t);
+ if (n) {
+ printnode_seq(seq, indent, n, pend, cindex, 0);
+ if (IS_TNODE(n)) {
+ struct tnode *tn=(struct tnode *)n;
+ pend = tn->pos+tn->bits;
+ putspace_seq(seq, indent); seq_printf(seq, "\\--\n");
+ indent += 3;
+ depth++;
+
+ while (tn && cindex < (1 << tn->bits)) {
+ if (tn->child[cindex]) {
+
+ /* Got a child */
+
+ printnode_seq(seq, indent, tn->child[cindex], pend, cindex, tn->bits);
+ if (IS_LEAF(tn->child[cindex])) {
+ cindex++;
+
+ }
+ else {
+ /*
+ * New tnode. Decend one level
+ */
+
+ depth++;
+ n=tn->child[cindex];
+ tn=(struct tnode *)n;
+ pend=tn->pos+tn->bits;
+ putspace_seq(seq, indent); seq_printf(seq, "\\--\n");
+ indent+=3;
+ cindex=0;
+ }
+ }
+ else
+ cindex++;
+
+ /*
+ * Test if we are done
+ */
+
+ while (cindex >= (1 << tn->bits)) {
+
+ /*
+ * Move upwards and test for root
+ * pop off all traversed nodes
+ */
+
+ if (NODE_PARENT(tn) == NULL) {
+ tn = NULL;
+ n = NULL;
+ break;
+ }
+ else {
+ cindex = tkey_extract_bits(tn->key, NODE_PARENT(tn)->pos, NODE_PARENT(tn)->bits);
+ tn = NODE_PARENT(tn);
+ cindex++;
+ n=(struct node *)tn;
+ pend=tn->pos+tn->bits;
+ indent-=3;
+ depth--;
+ }
+ }
+ }
+ }
+ else n = NULL;
+ }
+ else seq_printf(seq, "------ trie is empty\n");
+
+ read_unlock(&fib_lock);
+}
+
+static struct trie_stat *trie_stat_new(void)
+{
+ struct trie_stat *s = kmalloc(sizeof(struct trie_stat), GFP_KERNEL);
+ int i;
+
+ if(s) {
+ s->totdepth = 0;
+ s->maxdepth = 0;
+ s->tnodes = 0;
+ s->leaves = 0;
+ s->nullpointers = 0;
+
+ for(i=0; i< MAX_CHILDS; i++)
+ s->nodesizes[i] = 0;
+ }
+ return s;
+}
+
+static struct trie_stat *trie_collect_stats(struct trie *t)
+{
+ struct node *n=t->trie;
+ struct trie_stat *s = trie_stat_new();
+ int cindex = 0;
+ int indent = 1;
+ int pend = 0;
+ int depth = 0;
+
+ read_lock(&fib_lock);
+
+ if (s) {
+ if (n) {
+ if (IS_TNODE(n)) {
+ struct tnode *tn = (struct tnode *)n;
+ pend=tn->pos+tn->bits;
+ indent += 3;
+ s->nodesizes[tn->bits]++;
+ depth++;
+
+ while (tn && cindex < (1 << tn->bits)) {
+ if (tn->child[cindex]) {
+ /* Got a child */
+
+ if (IS_LEAF(tn->child[cindex])) {
+ cindex++;
+
+ /* stats */
+ if (depth > s->maxdepth)
+ s->maxdepth = depth;
+ s->totdepth += depth;
+ s->leaves++;
+ }
+
+ else {
+ /*
+ * New tnode. Decend one level
+ */
+
+ s->tnodes++;
+ s->nodesizes[tn->bits]++;
+ depth++;
+
+ n = tn->child[cindex];
+ tn = (struct tnode *)n;
+ pend = tn->pos+tn->bits;
+
+ indent += 3;
+ cindex = 0;
+ }
+ }
+ else {
+ cindex++;
+ s->nullpointers++;
+ }
+
+ /*
+ * Test if we are done
+ */
+
+ while (cindex >= (1 << tn->bits)) {
+
+ /*
+ * Move upwards and test for root
+ * pop off all traversed nodes
+ */
+
+
+ if (NODE_PARENT(tn) == NULL) {
+ tn = NULL;
+ n = NULL;
+ break;
+ }
+ else {
+ cindex = tkey_extract_bits(tn->key, NODE_PARENT(tn)->pos, NODE_PARENT(tn)->bits);
+ tn = NODE_PARENT(tn);
+ cindex++;
+ n = (struct node *)tn;
+ pend=tn->pos+tn->bits;
+ indent -= 3;
+ depth--;
+ }
+ }
+ }
+ }
+ else n = NULL;
+ }
+ }
+
+ read_unlock(&fib_lock);
+ return s;
+}
+
+#ifdef CONFIG_PROC_FS
+
+static struct fib_alias *fib_triestat_get_first(struct seq_file *seq)
+{
+ return NULL;
+}
+
+static struct fib_alias *fib_triestat_get_next(struct seq_file *seq)
+{
+ return NULL;
+}
+
+static void *fib_triestat_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ void *v = NULL;
+
+ if (ip_fib_main_table)
+ v = *pos ? fib_triestat_get_next(seq) : SEQ_START_TOKEN;
+ return v;
+}
+
+static void *fib_triestat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ ++*pos;
+ return v == SEQ_START_TOKEN ? fib_triestat_get_first(seq) : fib_triestat_get_next(seq);
+}
+
+static void fib_triestat_seq_stop(struct seq_file *seq, void *v)
+{
+
+}
+
+/*
+ * This outputs /proc/net/fib_triestats
+ *
+ * It always works in backward compatibility mode.
+ * The format of the file is not supposed to be changed.
+ */
+
+static void collect_and_show(struct trie *t, struct seq_file *seq)
+{
+ int bytes = 0; /* How many bytes are used, a ref is 4 bytes */
+ int i, max, pointers;
+ struct trie_stat *stat;
+ int avdepth;
+
+ stat = trie_collect_stats(t);
+
+ bytes=0;
+ seq_printf(seq, "trie=%p\n", t);
+
+ if (stat) {
+ if (stat->leaves)
+ avdepth=stat->totdepth*100 / stat->leaves;
+ else
+ avdepth=0;
+ seq_printf(seq, "Aver depth: %d.%02d\n", avdepth / 100, avdepth % 100 );
+ seq_printf(seq, "Max depth: %4d\n", stat->maxdepth);
+
+ seq_printf(seq, "Leaves: %d\n", stat->leaves);
+ bytes += sizeof(struct leaf) * stat->leaves;
+ seq_printf(seq, "Internal nodes: %d\n", stat->tnodes);
+ bytes += sizeof(struct tnode) * stat->tnodes;
+
+ max = MAX_CHILDS-1;
+
+ while (max >= 0 && stat->nodesizes[max] == 0)
+ max--;
+ pointers = 0;
+
+ for (i = 1; i <= max; i++)
+ if (stat->nodesizes[i] != 0) {
+ seq_printf(seq, " %d: %d", i, stat->nodesizes[i]);
+ pointers += (1<<i) * stat->nodesizes[i];
+ }
+ seq_printf(seq, "\n");
+ seq_printf(seq, "Pointers: %d\n", pointers);
+ bytes += sizeof(struct node *) * pointers;
+ seq_printf(seq, "Null ptrs: %d\n", stat->nullpointers);
+ seq_printf(seq, "Total size: %d kB\n", bytes / 1024);
+
+ kfree(stat);
+ }
+
+#ifdef CONFIG_IP_FIB_TRIE_STATS
+ seq_printf(seq, "Counters:\n---------\n");
+ seq_printf(seq,"gets = %d\n", t->stats.gets);
+ seq_printf(seq,"backtracks = %d\n", t->stats.backtrack);
+ seq_printf(seq,"semantic match passed = %d\n", t->stats.semantic_match_passed);
+ seq_printf(seq,"semantic match miss = %d\n", t->stats.semantic_match_miss);
+ seq_printf(seq,"null node hit= %d\n", t->stats.null_node_hit);
+#ifdef CLEAR_STATS
+ memset(&(t->stats), 0, sizeof(t->stats));
+#endif
+#endif /* CONFIG_IP_FIB_TRIE_STATS */
+}
+
+static int fib_triestat_seq_show(struct seq_file *seq, void *v)
+{
+ char bf[128];
+
+ if (v == SEQ_START_TOKEN) {
+ seq_printf(seq, "Basic info: size of leaf: %Zd bytes, size of tnode: %Zd bytes.\n",
+ sizeof(struct leaf), sizeof(struct tnode));
+ if (trie_local)
+ collect_and_show(trie_local, seq);
+
+ if (trie_main)
+ collect_and_show(trie_main, seq);
+ }
+ else {
+ snprintf(bf, sizeof(bf),
+ "*\t%08X\t%08X", 200, 400);
+
+ seq_printf(seq, "%-127s\n", bf);
+ }
+ return 0;
+}
+
+static struct seq_operations fib_triestat_seq_ops = {
+ .start = fib_triestat_seq_start,
+ .next = fib_triestat_seq_next,
+ .stop = fib_triestat_seq_stop,
+ .show = fib_triestat_seq_show,
+};
+
+static int fib_triestat_seq_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq;
+ int rc = -ENOMEM;
+
+ rc = seq_open(file, &fib_triestat_seq_ops);
+ if (rc)
+ goto out_kfree;
+
+ seq = file->private_data;
+out:
+ return rc;
+out_kfree:
+ goto out;
+}
+
+static struct file_operations fib_triestat_seq_fops = {
+ .owner = THIS_MODULE,
+ .open = fib_triestat_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release_private,
+};
+
+int __init fib_stat_proc_init(void)
+{
+ if (!proc_net_fops_create("fib_triestat", S_IRUGO, &fib_triestat_seq_fops))
+ return -ENOMEM;
+ return 0;
+}
+
+void __init fib_stat_proc_exit(void)
+{
+ proc_net_remove("fib_triestat");
+}
+
+static struct fib_alias *fib_trie_get_first(struct seq_file *seq)
+{
+ return NULL;
+}
+
+static struct fib_alias *fib_trie_get_next(struct seq_file *seq)
+{
+ return NULL;
+}
+
+static void *fib_trie_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ void *v = NULL;
+
+ if (ip_fib_main_table)
+ v = *pos ? fib_trie_get_next(seq) : SEQ_START_TOKEN;
+ return v;
+}
+
+static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ ++*pos;
+ return v == SEQ_START_TOKEN ? fib_trie_get_first(seq) : fib_trie_get_next(seq);
+}
+
+static void fib_trie_seq_stop(struct seq_file *seq, void *v)
+{
+
+}
+
+/*
+ * This outputs /proc/net/fib_trie.
+ *
+ * It always works in backward compatibility mode.
+ * The format of the file is not supposed to be changed.
+ */
+
+static int fib_trie_seq_show(struct seq_file *seq, void *v)
+{
+ char bf[128];
+
+ if (v == SEQ_START_TOKEN) {
+ if (trie_local)
+ trie_dump_seq(seq, trie_local);
+
+ if (trie_main)
+ trie_dump_seq(seq, trie_main);
+ }
+
+ else {
+ snprintf(bf, sizeof(bf),
+ "*\t%08X\t%08X", 200, 400);
+ seq_printf(seq, "%-127s\n", bf);
+ }
+
+ return 0;
+}
+
+static struct seq_operations fib_trie_seq_ops = {
+ .start = fib_trie_seq_start,
+ .next = fib_trie_seq_next,
+ .stop = fib_trie_seq_stop,
+ .show = fib_trie_seq_show,
+};
+
+static int fib_trie_seq_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq;
+ int rc = -ENOMEM;
+
+ rc = seq_open(file, &fib_trie_seq_ops);
+ if (rc)
+ goto out_kfree;
+
+ seq = file->private_data;
+out:
+ return rc;
+out_kfree:
+ goto out;
+}
+
+static struct file_operations fib_trie_seq_fops = {
+ .owner = THIS_MODULE,
+ .open = fib_trie_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release_private,
+};
+
+int __init fib_proc_init(void)
+{
+ if (!proc_net_fops_create("fib_trie", S_IRUGO, &fib_trie_seq_fops))
+ return -ENOMEM;
+ return 0;
+}
+
+void __init fib_proc_exit(void)
+{
+ proc_net_remove("fib_trie");
+}
+
+#endif /* CONFIG_PROC_FS */
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 85bf0d3e294..cb759484979 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -207,6 +207,7 @@ int sysctl_icmp_ignore_bogus_error_responses;
int sysctl_icmp_ratelimit = 1 * HZ;
int sysctl_icmp_ratemask = 0x1818;
+int sysctl_icmp_errors_use_inbound_ifaddr;
/*
* ICMP control array. This specifies what to do with each ICMP.
@@ -511,8 +512,12 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, u32 info)
*/
saddr = iph->daddr;
- if (!(rt->rt_flags & RTCF_LOCAL))
- saddr = 0;
+ if (!(rt->rt_flags & RTCF_LOCAL)) {
+ if (sysctl_icmp_errors_use_inbound_ifaddr)
+ saddr = inet_select_addr(skb_in->dev, 0, RT_SCOPE_LINK);
+ else
+ saddr = 0;
+ }
tos = icmp_pointers[type].error ? ((iph->tos & IPTOS_TOS_MASK) |
IPTOS_PREC_INTERNETCONTROL) :
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 4e47a2658c7..af2ec88bbb2 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -184,6 +184,7 @@ int ip_call_ra_chain(struct sk_buff *skb)
raw_rcv(last, skb2);
}
last = sk;
+ nf_reset(skb);
}
}
@@ -200,10 +201,6 @@ static inline int ip_local_deliver_finish(struct sk_buff *skb)
{
int ihl = skb->nh.iph->ihl*4;
-#ifdef CONFIG_NETFILTER_DEBUG
- nf_debug_ip_local_deliver(skb);
-#endif /*CONFIG_NETFILTER_DEBUG*/
-
__skb_pull(skb, ihl);
/* Free reference early: we don't need it any more, and it may
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index daebd93fd8a..ee07aec215a 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -107,10 +107,6 @@ static int ip_dev_loopback_xmit(struct sk_buff *newskb)
newskb->pkt_type = PACKET_LOOPBACK;
newskb->ip_summed = CHECKSUM_UNNECESSARY;
BUG_TRAP(newskb->dst);
-
-#ifdef CONFIG_NETFILTER_DEBUG
- nf_debug_ip_loopback_xmit(newskb);
-#endif
nf_reset(newskb);
netif_rx(newskb);
return 0;
@@ -192,10 +188,6 @@ static inline int ip_finish_output2(struct sk_buff *skb)
skb = skb2;
}
-#ifdef CONFIG_NETFILTER_DEBUG
- nf_debug_ip_finish_output2(skb);
-#endif /*CONFIG_NETFILTER_DEBUG*/
-
nf_reset(skb);
if (hh) {
@@ -415,9 +407,6 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
to->nf_bridge = from->nf_bridge;
nf_bridge_get(to->nf_bridge);
#endif
-#ifdef CONFIG_NETFILTER_DEBUG
- to->nf_debug = from->nf_debug;
-#endif
#endif
}
@@ -490,6 +479,14 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
/* Partially cloned skb? */
if (skb_shared(frag))
goto slow_path;
+
+ BUG_ON(frag->sk);
+ if (skb->sk) {
+ sock_hold(skb->sk);
+ frag->sk = skb->sk;
+ frag->destructor = sock_wfree;
+ skb->truesize -= frag->truesize;
+ }
}
/* Everything is OK. Generate! */
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 47012b93cad..f8b172f8981 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -360,14 +360,14 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len)
err = copied;
/* Reset and regenerate socket error */
- spin_lock_irq(&sk->sk_error_queue.lock);
+ spin_lock_bh(&sk->sk_error_queue.lock);
sk->sk_err = 0;
if ((skb2 = skb_peek(&sk->sk_error_queue)) != NULL) {
sk->sk_err = SKB_EXT_ERR(skb2)->ee.ee_errno;
- spin_unlock_irq(&sk->sk_error_queue.lock);
+ spin_unlock_bh(&sk->sk_error_queue.lock);
sk->sk_error_report(sk);
} else
- spin_unlock_irq(&sk->sk_error_queue.lock);
+ spin_unlock_bh(&sk->sk_error_queue.lock);
out_free_skb:
kfree_skb(skb);
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 1a23c5263b9..2065944fd9e 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -236,15 +236,10 @@ static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x)
t->props.mode = 1;
t->props.saddr.a4 = x->props.saddr.a4;
t->props.flags = x->props.flags;
-
- t->type = xfrm_get_type(IPPROTO_IPIP, t->props.family);
- if (t->type == NULL)
- goto error;
-
- if (t->type->init_state(t, NULL))
+
+ if (xfrm_init_state(t))
goto error;
- t->km.state = XFRM_STATE_VALID;
atomic_set(&t->tunnel_users, 1);
out:
return t;
@@ -422,7 +417,7 @@ static void ipcomp_destroy(struct xfrm_state *x)
kfree(ipcd);
}
-static int ipcomp_init_state(struct xfrm_state *x, void *args)
+static int ipcomp_init_state(struct xfrm_state *x)
{
int err;
struct ipcomp_data *ipcd;
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index e21c049ec62..e4f809a93f4 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -1350,6 +1350,7 @@ int ip_mr_input(struct sk_buff *skb)
*/
read_lock(&mrt_lock);
if (mroute_socket) {
+ nf_reset(skb);
raw_rcv(mroute_socket, skb);
read_unlock(&mrt_lock);
return 0;
diff --git a/net/ipv4/ipvs/Makefile b/net/ipv4/ipvs/Makefile
index a788461a40c..30e85de9fff 100644
--- a/net/ipv4/ipvs/Makefile
+++ b/net/ipv4/ipvs/Makefile
@@ -11,7 +11,7 @@ ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_AH) += ip_vs_proto_ah.o
ip_vs-objs := ip_vs_conn.o ip_vs_core.o ip_vs_ctl.o ip_vs_sched.o \
ip_vs_xmit.o ip_vs_app.o ip_vs_sync.o \
- ip_vs_est.o ip_vs_proto.o ip_vs_proto_icmp.o \
+ ip_vs_est.o ip_vs_proto.o \
$(ip_vs_proto-objs-y)
diff --git a/net/ipv4/ipvs/ip_vs_proto.c b/net/ipv4/ipvs/ip_vs_proto.c
index 253c46252bd..867d4e9c659 100644
--- a/net/ipv4/ipvs/ip_vs_proto.c
+++ b/net/ipv4/ipvs/ip_vs_proto.c
@@ -216,9 +216,6 @@ int ip_vs_protocol_init(void)
#ifdef CONFIG_IP_VS_PROTO_UDP
REGISTER_PROTOCOL(&ip_vs_protocol_udp);
#endif
-#ifdef CONFIG_IP_VS_PROTO_ICMP
- REGISTER_PROTOCOL(&ip_vs_protocol_icmp);
-#endif
#ifdef CONFIG_IP_VS_PROTO_AH
REGISTER_PROTOCOL(&ip_vs_protocol_ah);
#endif
diff --git a/net/ipv4/ipvs/ip_vs_proto_icmp.c b/net/ipv4/ipvs/ip_vs_proto_icmp.c
deleted file mode 100644
index 191e94aa1c1..00000000000
--- a/net/ipv4/ipvs/ip_vs_proto_icmp.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * ip_vs_proto_icmp.c: ICMP load balancing support for IP Virtual Server
- *
- * Authors: Julian Anastasov <ja@ssi.bg>, March 2002
- *
- * 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;
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/icmp.h>
-#include <linux/netfilter.h>
-#include <linux/netfilter_ipv4.h>
-
-#include <net/ip_vs.h>
-
-
-static int icmp_timeouts[1] = { 1*60*HZ };
-
-static char * icmp_state_name_table[1] = { "ICMP" };
-
-static struct ip_vs_conn *
-icmp_conn_in_get(const struct sk_buff *skb,
- struct ip_vs_protocol *pp,
- const struct iphdr *iph,
- unsigned int proto_off,
- int inverse)
-{
-#if 0
- struct ip_vs_conn *cp;
-
- if (likely(!inverse)) {
- cp = ip_vs_conn_in_get(iph->protocol,
- iph->saddr, 0,
- iph->daddr, 0);
- } else {
- cp = ip_vs_conn_in_get(iph->protocol,
- iph->daddr, 0,
- iph->saddr, 0);
- }
-
- return cp;
-
-#else
- return NULL;
-#endif
-}
-
-static struct ip_vs_conn *
-icmp_conn_out_get(const struct sk_buff *skb,
- struct ip_vs_protocol *pp,
- const struct iphdr *iph,
- unsigned int proto_off,
- int inverse)
-{
-#if 0
- struct ip_vs_conn *cp;
-
- if (likely(!inverse)) {
- cp = ip_vs_conn_out_get(iph->protocol,
- iph->saddr, 0,
- iph->daddr, 0);
- } else {
- cp = ip_vs_conn_out_get(IPPROTO_UDP,
- iph->daddr, 0,
- iph->saddr, 0);
- }
-
- return cp;
-#else
- return NULL;
-#endif
-}
-
-static int
-icmp_conn_schedule(struct sk_buff *skb, struct ip_vs_protocol *pp,
- int *verdict, struct ip_vs_conn **cpp)
-{
- *verdict = NF_ACCEPT;
- return 0;
-}
-
-static int
-icmp_csum_check(struct sk_buff *skb, struct ip_vs_protocol *pp)
-{
- if (!(skb->nh.iph->frag_off & __constant_htons(IP_OFFSET))) {
- if (skb->ip_summed != CHECKSUM_UNNECESSARY) {
- if (ip_vs_checksum_complete(skb, skb->nh.iph->ihl * 4)) {
- IP_VS_DBG_RL_PKT(0, pp, skb, 0, "Failed checksum for");
- return 0;
- }
- }
- }
- return 1;
-}
-
-static void
-icmp_debug_packet(struct ip_vs_protocol *pp,
- const struct sk_buff *skb,
- int offset,
- const char *msg)
-{
- char buf[256];
- struct iphdr _iph, *ih;
-
- ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
- if (ih == NULL)
- sprintf(buf, "%s TRUNCATED", pp->name);
- else if (ih->frag_off & __constant_htons(IP_OFFSET))
- sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u frag",
- pp->name, NIPQUAD(ih->saddr),
- NIPQUAD(ih->daddr));
- else {
- struct icmphdr _icmph, *ic;
-
- ic = skb_header_pointer(skb, offset + ih->ihl*4,
- sizeof(_icmph), &_icmph);
- if (ic == NULL)
- sprintf(buf, "%s TRUNCATED to %u bytes\n",
- pp->name, skb->len - offset);
- else
- sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u T:%d C:%d",
- pp->name, NIPQUAD(ih->saddr),
- NIPQUAD(ih->daddr),
- ic->type, ic->code);
- }
- printk(KERN_DEBUG "IPVS: %s: %s\n", msg, buf);
-}
-
-static int
-icmp_state_transition(struct ip_vs_conn *cp, int direction,
- const struct sk_buff *skb,
- struct ip_vs_protocol *pp)
-{
- cp->timeout = pp->timeout_table[IP_VS_ICMP_S_NORMAL];
- return 1;
-}
-
-static int
-icmp_set_state_timeout(struct ip_vs_protocol *pp, char *sname, int to)
-{
- int num;
- char **names;
-
- num = IP_VS_ICMP_S_LAST;
- names = icmp_state_name_table;
- return ip_vs_set_state_timeout(pp->timeout_table, num, names, sname, to);
-}
-
-
-static void icmp_init(struct ip_vs_protocol *pp)
-{
- pp->timeout_table = icmp_timeouts;
-}
-
-static void icmp_exit(struct ip_vs_protocol *pp)
-{
-}
-
-struct ip_vs_protocol ip_vs_protocol_icmp = {
- .name = "ICMP",
- .protocol = IPPROTO_ICMP,
- .dont_defrag = 0,
- .init = icmp_init,
- .exit = icmp_exit,
- .conn_schedule = icmp_conn_schedule,
- .conn_in_get = icmp_conn_in_get,
- .conn_out_get = icmp_conn_out_get,
- .snat_handler = NULL,
- .dnat_handler = NULL,
- .csum_check = icmp_csum_check,
- .state_transition = icmp_state_transition,
- .register_app = NULL,
- .unregister_app = NULL,
- .app_conn_bind = NULL,
- .debug_packet = icmp_debug_packet,
- .timeout_change = NULL,
- .set_state_timeout = icmp_set_state_timeout,
-};
diff --git a/net/ipv4/ipvs/ip_vs_xmit.c b/net/ipv4/ipvs/ip_vs_xmit.c
index faa6176bbeb..a8512a3fd08 100644
--- a/net/ipv4/ipvs/ip_vs_xmit.c
+++ b/net/ipv4/ipvs/ip_vs_xmit.c
@@ -127,7 +127,6 @@ ip_vs_dst_reset(struct ip_vs_dest *dest)
#define IP_VS_XMIT(skb, rt) \
do { \
- nf_reset_debug(skb); \
(skb)->nfcache |= NFC_IPVS_PROPERTY; \
(skb)->ip_summed = CHECKSUM_NONE; \
NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, (skb), NULL, \
@@ -508,7 +507,6 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
rc = NF_ACCEPT;
/* do not touch skb anymore */
atomic_inc(&cp->in_pkts);
- __ip_vs_conn_put(cp);
goto out;
}
diff --git a/net/ipv4/multipath_drr.c b/net/ipv4/multipath_drr.c
index 9349686131f..c9cf8726051 100644
--- a/net/ipv4/multipath_drr.c
+++ b/net/ipv4/multipath_drr.c
@@ -31,6 +31,7 @@
#include <linux/igmp.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <linux/module.h>
#include <linux/mroute.h>
#include <linux/init.h>
#include <net/ip.h>
@@ -57,7 +58,6 @@ struct multipath_device {
static struct multipath_device state[MULTIPATH_MAX_DEVICECANDIDATES];
static DEFINE_SPINLOCK(state_lock);
-static struct rtable *last_selection = NULL;
static int inline __multipath_findslot(void)
{
@@ -111,11 +111,6 @@ struct notifier_block drr_dev_notifier = {
.notifier_call = drr_dev_event,
};
-static void drr_remove(struct rtable *rt)
-{
- if (last_selection == rt)
- last_selection = NULL;
-}
static void drr_safe_inc(atomic_t *usecount)
{
@@ -144,14 +139,6 @@ static void drr_select_route(const struct flowi *flp,
int devidx = -1;
int cur_min_devidx = -1;
- /* if necessary and possible utilize the old alternative */
- if ((flp->flags & FLOWI_FLAG_MULTIPATHOLDROUTE) != 0 &&
- last_selection != NULL) {
- result = last_selection;
- *rp = result;
- return;
- }
-
/* 1. make sure all alt. nexthops have the same GC related data */
/* 2. determine the new candidate to be returned */
result = NULL;
@@ -229,12 +216,10 @@ static void drr_select_route(const struct flowi *flp,
}
*rp = result;
- last_selection = result;
}
static struct ip_mp_alg_ops drr_ops = {
.mp_alg_select_route = drr_select_route,
- .mp_alg_remove = drr_remove,
};
static int __init drr_init(void)
@@ -244,7 +229,7 @@ static int __init drr_init(void)
if (err)
return err;
- err = multipath_alg_register(&drr_ops, IP_MP_ALG_RR);
+ err = multipath_alg_register(&drr_ops, IP_MP_ALG_DRR);
if (err)
goto fail;
@@ -263,3 +248,4 @@ static void __exit drr_exit(void)
module_init(drr_init);
module_exit(drr_exit);
+MODULE_LICENSE("GPL");
diff --git a/net/ipv4/multipath_random.c b/net/ipv4/multipath_random.c
index 805a16e47de..5249dbe7c55 100644
--- a/net/ipv4/multipath_random.c
+++ b/net/ipv4/multipath_random.c
@@ -31,6 +31,7 @@
#include <linux/igmp.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <linux/module.h>
#include <linux/mroute.h>
#include <linux/init.h>
#include <net/ip.h>
@@ -126,3 +127,4 @@ static void __exit random_exit(void)
module_init(random_init);
module_exit(random_exit);
+MODULE_LICENSE("GPL");
diff --git a/net/ipv4/multipath_rr.c b/net/ipv4/multipath_rr.c
index 554a8256816..b6cd2870478 100644
--- a/net/ipv4/multipath_rr.c
+++ b/net/ipv4/multipath_rr.c
@@ -31,6 +31,7 @@
#include <linux/igmp.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <linux/module.h>
#include <linux/mroute.h>
#include <linux/init.h>
#include <net/ip.h>
@@ -47,29 +48,12 @@
#include <net/checksum.h>
#include <net/ip_mp_alg.h>
-#define MULTIPATH_MAX_CANDIDATES 40
-
-static struct rtable* last_used = NULL;
-
-static void rr_remove(struct rtable *rt)
-{
- if (last_used == rt)
- last_used = NULL;
-}
-
static void rr_select_route(const struct flowi *flp,
struct rtable *first, struct rtable **rp)
{
struct rtable *nh, *result, *min_use_cand = NULL;
int min_use = -1;
- /* if necessary and possible utilize the old alternative */
- if ((flp->flags & FLOWI_FLAG_MULTIPATHOLDROUTE) != 0 &&
- last_used != NULL) {
- result = last_used;
- goto out;
- }
-
/* 1. make sure all alt. nexthops have the same GC related data
* 2. determine the new candidate to be returned
*/
@@ -90,15 +74,12 @@ static void rr_select_route(const struct flowi *flp,
if (!result)
result = first;
-out:
- last_used = result;
result->u.dst.__use++;
*rp = result;
}
static struct ip_mp_alg_ops rr_ops = {
.mp_alg_select_route = rr_select_route,
- .mp_alg_remove = rr_remove,
};
static int __init rr_init(void)
@@ -113,3 +94,4 @@ static void __exit rr_exit(void)
module_init(rr_init);
module_exit(rr_exit);
+MODULE_LICENSE("GPL");
diff --git a/net/ipv4/multipath_wrandom.c b/net/ipv4/multipath_wrandom.c
index c3d2ca1a678..bd7d75b6abe 100644
--- a/net/ipv4/multipath_wrandom.c
+++ b/net/ipv4/multipath_wrandom.c
@@ -31,6 +31,7 @@
#include <linux/igmp.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <linux/module.h>
#include <linux/mroute.h>
#include <linux/init.h>
#include <net/ip.h>
@@ -342,3 +343,4 @@ static void __exit wrandom_exit(void)
module_init(wrandom_init);
module_exit(wrandom_exit);
+MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index df79f5ed6a0..fa163425668 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -60,7 +60,6 @@ static DECLARE_MUTEX(arpt_mutex);
#define ASSERT_READ_LOCK(x) ARP_NF_ASSERT(down_trylock(&arpt_mutex) != 0)
#define ASSERT_WRITE_LOCK(x) ARP_NF_ASSERT(down_trylock(&arpt_mutex) != 0)
-#include <linux/netfilter_ipv4/lockhelp.h>
#include <linux/netfilter_ipv4/listhelp.h>
struct arpt_table_info {
diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c
index 3dbddd06260..a78a320eee0 100644
--- a/net/ipv4/netfilter/ip_conntrack_amanda.c
+++ b/net/ipv4/netfilter/ip_conntrack_amanda.c
@@ -26,7 +26,6 @@
#include <net/checksum.h>
#include <net/udp.h>
-#include <linux/netfilter_ipv4/lockhelp.h>
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
#include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
@@ -42,7 +41,7 @@ static char *conns[] = { "DATA ", "MESG ", "INDEX " };
/* This is slow, but it's simple. --RR */
static char amanda_buffer[65536];
-static DECLARE_LOCK(amanda_buffer_lock);
+static DEFINE_SPINLOCK(amanda_buffer_lock);
unsigned int (*ip_nat_amanda_hook)(struct sk_buff **pskb,
enum ip_conntrack_info ctinfo,
@@ -76,7 +75,7 @@ static int help(struct sk_buff **pskb,
return NF_ACCEPT;
}
- LOCK_BH(&amanda_buffer_lock);
+ spin_lock_bh(&amanda_buffer_lock);
skb_copy_bits(*pskb, dataoff, amanda_buffer, (*pskb)->len - dataoff);
data = amanda_buffer;
data_limit = amanda_buffer + (*pskb)->len - dataoff;
@@ -134,7 +133,7 @@ static int help(struct sk_buff **pskb,
}
out:
- UNLOCK_BH(&amanda_buffer_lock);
+ spin_unlock_bh(&amanda_buffer_lock);
return ret;
}
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index 28d9425d5c3..4b78ebeb663 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -38,10 +38,10 @@
#include <linux/percpu.h>
#include <linux/moduleparam.h>
-/* This rwlock protects the main hash table, protocol/helper/expected
+/* ip_conntrack_lock protects the main hash table, protocol/helper/expected
registrations, conntrack timers*/
-#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock)
-#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_conntrack_lock)
+#define ASSERT_READ_LOCK(x)
+#define ASSERT_WRITE_LOCK(x)
#include <linux/netfilter_ipv4/ip_conntrack.h>
#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
@@ -57,7 +57,7 @@
#define DEBUGP(format, args...)
#endif
-DECLARE_RWLOCK(ip_conntrack_lock);
+DEFINE_RWLOCK(ip_conntrack_lock);
/* ip_conntrack_standalone needs this */
atomic_t ip_conntrack_count = ATOMIC_INIT(0);
@@ -147,7 +147,7 @@ static void destroy_expect(struct ip_conntrack_expect *exp)
static void unlink_expect(struct ip_conntrack_expect *exp)
{
- MUST_BE_WRITE_LOCKED(&ip_conntrack_lock);
+ ASSERT_WRITE_LOCK(&ip_conntrack_lock);
list_del(&exp->list);
/* Logically in destroy_expect, but we hold the lock here. */
exp->master->expecting--;
@@ -157,9 +157,9 @@ static void expectation_timed_out(unsigned long ul_expect)
{
struct ip_conntrack_expect *exp = (void *)ul_expect;
- WRITE_LOCK(&ip_conntrack_lock);
+ write_lock_bh(&ip_conntrack_lock);
unlink_expect(exp);
- WRITE_UNLOCK(&ip_conntrack_lock);
+ write_unlock_bh(&ip_conntrack_lock);
destroy_expect(exp);
}
@@ -209,7 +209,7 @@ clean_from_lists(struct ip_conntrack *ct)
unsigned int ho, hr;
DEBUGP("clean_from_lists(%p)\n", ct);
- MUST_BE_WRITE_LOCKED(&ip_conntrack_lock);
+ ASSERT_WRITE_LOCK(&ip_conntrack_lock);
ho = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
hr = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
@@ -240,7 +240,7 @@ destroy_conntrack(struct nf_conntrack *nfct)
if (ip_conntrack_destroyed)
ip_conntrack_destroyed(ct);
- WRITE_LOCK(&ip_conntrack_lock);
+ write_lock_bh(&ip_conntrack_lock);
/* Expectations will have been removed in clean_from_lists,
* except TFTP can create an expectation on the first packet,
* before connection is in the list, so we need to clean here,
@@ -254,7 +254,7 @@ destroy_conntrack(struct nf_conntrack *nfct)
}
CONNTRACK_STAT_INC(delete);
- WRITE_UNLOCK(&ip_conntrack_lock);
+ write_unlock_bh(&ip_conntrack_lock);
if (ct->master)
ip_conntrack_put(ct->master);
@@ -268,12 +268,12 @@ static void death_by_timeout(unsigned long ul_conntrack)
{
struct ip_conntrack *ct = (void *)ul_conntrack;
- WRITE_LOCK(&ip_conntrack_lock);
+ write_lock_bh(&ip_conntrack_lock);
/* Inside lock so preempt is disabled on module removal path.
* Otherwise we can get spurious warnings. */
CONNTRACK_STAT_INC(delete_list);
clean_from_lists(ct);
- WRITE_UNLOCK(&ip_conntrack_lock);
+ write_unlock_bh(&ip_conntrack_lock);
ip_conntrack_put(ct);
}
@@ -282,7 +282,7 @@ conntrack_tuple_cmp(const struct ip_conntrack_tuple_hash *i,
const struct ip_conntrack_tuple *tuple,
const struct ip_conntrack *ignored_conntrack)
{
- MUST_BE_READ_LOCKED(&ip_conntrack_lock);
+ ASSERT_READ_LOCK(&ip_conntrack_lock);
return tuplehash_to_ctrack(i) != ignored_conntrack
&& ip_ct_tuple_equal(tuple, &i->tuple);
}
@@ -294,7 +294,7 @@ __ip_conntrack_find(const struct ip_conntrack_tuple *tuple,
struct ip_conntrack_tuple_hash *h;
unsigned int hash = hash_conntrack(tuple);
- MUST_BE_READ_LOCKED(&ip_conntrack_lock);
+ ASSERT_READ_LOCK(&ip_conntrack_lock);
list_for_each_entry(h, &ip_conntrack_hash[hash], list) {
if (conntrack_tuple_cmp(h, tuple, ignored_conntrack)) {
CONNTRACK_STAT_INC(found);
@@ -313,11 +313,11 @@ ip_conntrack_find_get(const struct ip_conntrack_tuple *tuple,
{
struct ip_conntrack_tuple_hash *h;
- READ_LOCK(&ip_conntrack_lock);
+ read_lock_bh(&ip_conntrack_lock);
h = __ip_conntrack_find(tuple, ignored_conntrack);
if (h)
atomic_inc(&tuplehash_to_ctrack(h)->ct_general.use);
- READ_UNLOCK(&ip_conntrack_lock);
+ read_unlock_bh(&ip_conntrack_lock);
return h;
}
@@ -352,7 +352,7 @@ __ip_conntrack_confirm(struct sk_buff **pskb)
IP_NF_ASSERT(!is_confirmed(ct));
DEBUGP("Confirming conntrack %p\n", ct);
- WRITE_LOCK(&ip_conntrack_lock);
+ write_lock_bh(&ip_conntrack_lock);
/* See if there's one in the list already, including reverse:
NAT could have grabbed it without realizing, since we're
@@ -380,12 +380,12 @@ __ip_conntrack_confirm(struct sk_buff **pskb)
atomic_inc(&ct->ct_general.use);
set_bit(IPS_CONFIRMED_BIT, &ct->status);
CONNTRACK_STAT_INC(insert);
- WRITE_UNLOCK(&ip_conntrack_lock);
+ write_unlock_bh(&ip_conntrack_lock);
return NF_ACCEPT;
}
CONNTRACK_STAT_INC(insert_failed);
- WRITE_UNLOCK(&ip_conntrack_lock);
+ write_unlock_bh(&ip_conntrack_lock);
return NF_DROP;
}
@@ -398,9 +398,9 @@ ip_conntrack_tuple_taken(const struct ip_conntrack_tuple *tuple,
{
struct ip_conntrack_tuple_hash *h;
- READ_LOCK(&ip_conntrack_lock);
+ read_lock_bh(&ip_conntrack_lock);
h = __ip_conntrack_find(tuple, ignored_conntrack);
- READ_UNLOCK(&ip_conntrack_lock);
+ read_unlock_bh(&ip_conntrack_lock);
return h != NULL;
}
@@ -419,13 +419,13 @@ static int early_drop(struct list_head *chain)
struct ip_conntrack *ct = NULL;
int dropped = 0;
- READ_LOCK(&ip_conntrack_lock);
+ read_lock_bh(&ip_conntrack_lock);
h = LIST_FIND_B(chain, unreplied, struct ip_conntrack_tuple_hash *);
if (h) {
ct = tuplehash_to_ctrack(h);
atomic_inc(&ct->ct_general.use);
}
- READ_UNLOCK(&ip_conntrack_lock);
+ read_unlock_bh(&ip_conntrack_lock);
if (!ct)
return dropped;
@@ -508,7 +508,7 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
conntrack->timeout.data = (unsigned long)conntrack;
conntrack->timeout.function = death_by_timeout;
- WRITE_LOCK(&ip_conntrack_lock);
+ write_lock_bh(&ip_conntrack_lock);
exp = find_expectation(tuple);
if (exp) {
@@ -532,7 +532,7 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
list_add(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].list, &unconfirmed);
atomic_inc(&ip_conntrack_count);
- WRITE_UNLOCK(&ip_conntrack_lock);
+ write_unlock_bh(&ip_conntrack_lock);
if (exp) {
if (exp->expectfn)
@@ -723,17 +723,17 @@ void ip_conntrack_unexpect_related(struct ip_conntrack_expect *exp)
{
struct ip_conntrack_expect *i;
- WRITE_LOCK(&ip_conntrack_lock);
+ write_lock_bh(&ip_conntrack_lock);
/* choose the the oldest expectation to evict */
list_for_each_entry_reverse(i, &ip_conntrack_expect_list, list) {
if (expect_matches(i, exp) && del_timer(&i->timeout)) {
unlink_expect(i);
- WRITE_UNLOCK(&ip_conntrack_lock);
+ write_unlock_bh(&ip_conntrack_lock);
destroy_expect(i);
return;
}
}
- WRITE_UNLOCK(&ip_conntrack_lock);
+ write_unlock_bh(&ip_conntrack_lock);
}
struct ip_conntrack_expect *ip_conntrack_expect_alloc(void)
@@ -760,15 +760,11 @@ static void ip_conntrack_expect_insert(struct ip_conntrack_expect *exp)
exp->master->expecting++;
list_add(&exp->list, &ip_conntrack_expect_list);
- if (exp->master->helper->timeout) {
- init_timer(&exp->timeout);
- exp->timeout.data = (unsigned long)exp;
- exp->timeout.function = expectation_timed_out;
- exp->timeout.expires
- = jiffies + exp->master->helper->timeout * HZ;
- add_timer(&exp->timeout);
- } else
- exp->timeout.function = NULL;
+ init_timer(&exp->timeout);
+ exp->timeout.data = (unsigned long)exp;
+ exp->timeout.function = expectation_timed_out;
+ exp->timeout.expires = jiffies + exp->master->helper->timeout * HZ;
+ add_timer(&exp->timeout);
CONNTRACK_STAT_INC(expect_create);
}
@@ -808,7 +804,7 @@ int ip_conntrack_expect_related(struct ip_conntrack_expect *expect)
DEBUGP("tuple: "); DUMP_TUPLE(&expect->tuple);
DEBUGP("mask: "); DUMP_TUPLE(&expect->mask);
- WRITE_LOCK(&ip_conntrack_lock);
+ write_lock_bh(&ip_conntrack_lock);
list_for_each_entry(i, &ip_conntrack_expect_list, list) {
if (expect_matches(i, expect)) {
/* Refresh timer: if it's dying, ignore.. */
@@ -832,7 +828,7 @@ int ip_conntrack_expect_related(struct ip_conntrack_expect *expect)
ip_conntrack_expect_insert(expect);
ret = 0;
out:
- WRITE_UNLOCK(&ip_conntrack_lock);
+ write_unlock_bh(&ip_conntrack_lock);
return ret;
}
@@ -841,7 +837,7 @@ out:
void ip_conntrack_alter_reply(struct ip_conntrack *conntrack,
const struct ip_conntrack_tuple *newreply)
{
- WRITE_LOCK(&ip_conntrack_lock);
+ write_lock_bh(&ip_conntrack_lock);
/* Should be unconfirmed, so not in hash table yet */
IP_NF_ASSERT(!is_confirmed(conntrack));
@@ -851,15 +847,15 @@ void ip_conntrack_alter_reply(struct ip_conntrack *conntrack,
conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
if (!conntrack->master && conntrack->expecting == 0)
conntrack->helper = ip_ct_find_helper(newreply);
- WRITE_UNLOCK(&ip_conntrack_lock);
+ write_unlock_bh(&ip_conntrack_lock);
}
int ip_conntrack_helper_register(struct ip_conntrack_helper *me)
{
BUG_ON(me->timeout == 0);
- WRITE_LOCK(&ip_conntrack_lock);
+ write_lock_bh(&ip_conntrack_lock);
list_prepend(&helpers, me);
- WRITE_UNLOCK(&ip_conntrack_lock);
+ write_unlock_bh(&ip_conntrack_lock);
return 0;
}
@@ -878,7 +874,7 @@ void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me)
struct ip_conntrack_expect *exp, *tmp;
/* Need write lock here, to delete helper. */
- WRITE_LOCK(&ip_conntrack_lock);
+ write_lock_bh(&ip_conntrack_lock);
LIST_DELETE(&helpers, me);
/* Get rid of expectations */
@@ -893,7 +889,7 @@ void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me)
for (i = 0; i < ip_conntrack_htable_size; i++)
LIST_FIND_W(&ip_conntrack_hash[i], unhelp,
struct ip_conntrack_tuple_hash *, me);
- WRITE_UNLOCK(&ip_conntrack_lock);
+ write_unlock_bh(&ip_conntrack_lock);
/* Someone could be still looking at the helper in a bh. */
synchronize_net();
@@ -925,14 +921,14 @@ void ip_ct_refresh_acct(struct ip_conntrack *ct,
ct->timeout.expires = extra_jiffies;
ct_add_counters(ct, ctinfo, skb);
} else {
- WRITE_LOCK(&ip_conntrack_lock);
+ write_lock_bh(&ip_conntrack_lock);
/* Need del_timer for race avoidance (may already be dying). */
if (del_timer(&ct->timeout)) {
ct->timeout.expires = jiffies + extra_jiffies;
add_timer(&ct->timeout);
}
ct_add_counters(ct, ctinfo, skb);
- WRITE_UNLOCK(&ip_conntrack_lock);
+ write_unlock_bh(&ip_conntrack_lock);
}
}
@@ -940,37 +936,16 @@ void ip_ct_refresh_acct(struct ip_conntrack *ct,
struct sk_buff *
ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user)
{
- struct sock *sk = skb->sk;
-#ifdef CONFIG_NETFILTER_DEBUG
- unsigned int olddebug = skb->nf_debug;
-#endif
-
- if (sk) {
- sock_hold(sk);
- skb_orphan(skb);
- }
+ skb_orphan(skb);
local_bh_disable();
skb = ip_defrag(skb, user);
local_bh_enable();
- if (!skb) {
- if (sk)
- sock_put(sk);
- return skb;
- }
-
- if (sk) {
- skb_set_owner_w(skb, sk);
- sock_put(sk);
+ if (skb) {
+ ip_send_check(skb->nh.iph);
+ skb->nfcache |= NFC_ALTERED;
}
-
- ip_send_check(skb->nh.iph);
- skb->nfcache |= NFC_ALTERED;
-#ifdef CONFIG_NETFILTER_DEBUG
- /* Packet path as if nothing had happened. */
- skb->nf_debug = olddebug;
-#endif
return skb;
}
@@ -1009,7 +984,7 @@ get_next_corpse(int (*iter)(struct ip_conntrack *i, void *data),
{
struct ip_conntrack_tuple_hash *h = NULL;
- WRITE_LOCK(&ip_conntrack_lock);
+ write_lock_bh(&ip_conntrack_lock);
for (; *bucket < ip_conntrack_htable_size; (*bucket)++) {
h = LIST_FIND_W(&ip_conntrack_hash[*bucket], do_iter,
struct ip_conntrack_tuple_hash *, iter, data);
@@ -1021,7 +996,7 @@ get_next_corpse(int (*iter)(struct ip_conntrack *i, void *data),
struct ip_conntrack_tuple_hash *, iter, data);
if (h)
atomic_inc(&tuplehash_to_ctrack(h)->ct_general.use);
- WRITE_UNLOCK(&ip_conntrack_lock);
+ write_unlock_bh(&ip_conntrack_lock);
return h;
}
@@ -1213,14 +1188,14 @@ int __init ip_conntrack_init(void)
}
/* Don't NEED lock here, but good form anyway. */
- WRITE_LOCK(&ip_conntrack_lock);
+ write_lock_bh(&ip_conntrack_lock);
for (i = 0; i < MAX_IP_CT_PROTO; i++)
ip_ct_protos[i] = &ip_conntrack_generic_protocol;
/* Sew in builtin protocols. */
ip_ct_protos[IPPROTO_TCP] = &ip_conntrack_protocol_tcp;
ip_ct_protos[IPPROTO_UDP] = &ip_conntrack_protocol_udp;
ip_ct_protos[IPPROTO_ICMP] = &ip_conntrack_protocol_icmp;
- WRITE_UNLOCK(&ip_conntrack_lock);
+ write_unlock_bh(&ip_conntrack_lock);
for (i = 0; i < ip_conntrack_htable_size; i++)
INIT_LIST_HEAD(&ip_conntrack_hash[i]);
diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c
index dd86503aa78..fea6dd2a00b 100644
--- a/net/ipv4/netfilter/ip_conntrack_ftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_ftp.c
@@ -16,7 +16,6 @@
#include <net/checksum.h>
#include <net/tcp.h>
-#include <linux/netfilter_ipv4/lockhelp.h>
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
#include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
#include <linux/moduleparam.h>
@@ -28,7 +27,7 @@ MODULE_DESCRIPTION("ftp connection tracking helper");
/* This is slow, but it's simple. --RR */
static char ftp_buffer[65536];
-static DECLARE_LOCK(ip_ftp_lock);
+static DEFINE_SPINLOCK(ip_ftp_lock);
#define MAX_PORTS 8
static int ports[MAX_PORTS];
@@ -319,7 +318,7 @@ static int help(struct sk_buff **pskb,
}
datalen = (*pskb)->len - dataoff;
- LOCK_BH(&ip_ftp_lock);
+ spin_lock_bh(&ip_ftp_lock);
fb_ptr = skb_header_pointer(*pskb, dataoff,
(*pskb)->len - dataoff, ftp_buffer);
BUG_ON(fb_ptr == NULL);
@@ -442,7 +441,7 @@ out_update_nl:
if (ends_in_nl)
update_nl_seq(seq, ct_ftp_info,dir);
out:
- UNLOCK_BH(&ip_ftp_lock);
+ spin_unlock_bh(&ip_ftp_lock);
return ret;
}
diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c
index 33cc7348b6e..cd98772cc33 100644
--- a/net/ipv4/netfilter/ip_conntrack_irc.c
+++ b/net/ipv4/netfilter/ip_conntrack_irc.c
@@ -29,7 +29,6 @@
#include <net/checksum.h>
#include <net/tcp.h>
-#include <linux/netfilter_ipv4/lockhelp.h>
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
#include <linux/netfilter_ipv4/ip_conntrack_irc.h>
#include <linux/moduleparam.h>
@@ -41,7 +40,7 @@ static int max_dcc_channels = 8;
static unsigned int dcc_timeout = 300;
/* This is slow, but it's simple. --RR */
static char irc_buffer[65536];
-static DECLARE_LOCK(irc_buffer_lock);
+static DEFINE_SPINLOCK(irc_buffer_lock);
unsigned int (*ip_nat_irc_hook)(struct sk_buff **pskb,
enum ip_conntrack_info ctinfo,
@@ -141,7 +140,7 @@ static int help(struct sk_buff **pskb,
if (dataoff >= (*pskb)->len)
return NF_ACCEPT;
- LOCK_BH(&irc_buffer_lock);
+ spin_lock_bh(&irc_buffer_lock);
ib_ptr = skb_header_pointer(*pskb, dataoff,
(*pskb)->len - dataoff, irc_buffer);
BUG_ON(ib_ptr == NULL);
@@ -237,7 +236,7 @@ static int help(struct sk_buff **pskb,
} /* while data < ... */
out:
- UNLOCK_BH(&irc_buffer_lock);
+ spin_unlock_bh(&irc_buffer_lock);
return ret;
}
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
index ff8c34a860f..31d75390bf1 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
@@ -26,7 +26,6 @@
#include <linux/netfilter_ipv4/ip_conntrack.h>
#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
-#include <linux/netfilter_ipv4/lockhelp.h>
#if 0
#define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
@@ -35,7 +34,7 @@
#endif
/* Protects conntrack->proto.sctp */
-static DECLARE_RWLOCK(sctp_lock);
+static DEFINE_RWLOCK(sctp_lock);
/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
closely. They're more complex. --RR
@@ -199,9 +198,9 @@ static int sctp_print_conntrack(struct seq_file *s,
DEBUGP(__FUNCTION__);
DEBUGP("\n");
- READ_LOCK(&sctp_lock);
+ read_lock_bh(&sctp_lock);
state = conntrack->proto.sctp.state;
- READ_UNLOCK(&sctp_lock);
+ read_unlock_bh(&sctp_lock);
return seq_printf(s, "%s ", sctp_conntrack_names[state]);
}
@@ -343,13 +342,13 @@ static int sctp_packet(struct ip_conntrack *conntrack,
oldsctpstate = newconntrack = SCTP_CONNTRACK_MAX;
for_each_sctp_chunk (skb, sch, _sch, offset, count) {
- WRITE_LOCK(&sctp_lock);
+ write_lock_bh(&sctp_lock);
/* Special cases of Verification tag check (Sec 8.5.1) */
if (sch->type == SCTP_CID_INIT) {
/* Sec 8.5.1 (A) */
if (sh->vtag != 0) {
- WRITE_UNLOCK(&sctp_lock);
+ write_unlock_bh(&sctp_lock);
return -1;
}
} else if (sch->type == SCTP_CID_ABORT) {
@@ -357,7 +356,7 @@ static int sctp_packet(struct ip_conntrack *conntrack,
if (!(sh->vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
&& !(sh->vtag == conntrack->proto.sctp.vtag
[1 - CTINFO2DIR(ctinfo)])) {
- WRITE_UNLOCK(&sctp_lock);
+ write_unlock_bh(&sctp_lock);
return -1;
}
} else if (sch->type == SCTP_CID_SHUTDOWN_COMPLETE) {
@@ -366,13 +365,13 @@ static int sctp_packet(struct ip_conntrack *conntrack,
&& !(sh->vtag == conntrack->proto.sctp.vtag
[1 - CTINFO2DIR(ctinfo)]
&& (sch->flags & 1))) {
- WRITE_UNLOCK(&sctp_lock);
+ write_unlock_bh(&sctp_lock);
return -1;
}
} else if (sch->type == SCTP_CID_COOKIE_ECHO) {
/* Sec 8.5.1 (D) */
if (!(sh->vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
- WRITE_UNLOCK(&sctp_lock);
+ write_unlock_bh(&sctp_lock);
return -1;
}
}
@@ -384,7 +383,7 @@ static int sctp_packet(struct ip_conntrack *conntrack,
if (newconntrack == SCTP_CONNTRACK_MAX) {
DEBUGP("ip_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n",
CTINFO2DIR(ctinfo), sch->type, oldsctpstate);
- WRITE_UNLOCK(&sctp_lock);
+ write_unlock_bh(&sctp_lock);
return -1;
}
@@ -396,7 +395,7 @@ static int sctp_packet(struct ip_conntrack *conntrack,
ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t),
sizeof(_inithdr), &_inithdr);
if (ih == NULL) {
- WRITE_UNLOCK(&sctp_lock);
+ write_unlock_bh(&sctp_lock);
return -1;
}
DEBUGP("Setting vtag %x for dir %d\n",
@@ -405,7 +404,7 @@ static int sctp_packet(struct ip_conntrack *conntrack,
}
conntrack->proto.sctp.state = newconntrack;
- WRITE_UNLOCK(&sctp_lock);
+ write_unlock_bh(&sctp_lock);
}
ip_ct_refresh_acct(conntrack, ctinfo, skb, *sctp_timeouts[newconntrack]);
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
index 721ddbf522b..809dfed766d 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
@@ -36,7 +36,6 @@
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv4/ip_conntrack.h>
#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
-#include <linux/netfilter_ipv4/lockhelp.h>
#if 0
#define DEBUGP printk
@@ -46,7 +45,7 @@
#endif
/* Protects conntrack->proto.tcp */
-static DECLARE_RWLOCK(tcp_lock);
+static DEFINE_RWLOCK(tcp_lock);
/* "Be conservative in what you do,
be liberal in what you accept from others."
@@ -330,9 +329,9 @@ static int tcp_print_conntrack(struct seq_file *s,
{
enum tcp_conntrack state;
- READ_LOCK(&tcp_lock);
+ read_lock_bh(&tcp_lock);
state = conntrack->proto.tcp.state;
- READ_UNLOCK(&tcp_lock);
+ read_unlock_bh(&tcp_lock);
return seq_printf(s, "%s ", tcp_conntrack_names[state]);
}
@@ -738,14 +737,14 @@ void ip_conntrack_tcp_update(struct sk_buff *skb,
end = segment_seq_plus_len(ntohl(tcph->seq), skb->len, iph, tcph);
- WRITE_LOCK(&tcp_lock);
+ write_lock_bh(&tcp_lock);
/*
* We have to worry for the ack in the reply packet only...
*/
if (after(end, conntrack->proto.tcp.seen[dir].td_end))
conntrack->proto.tcp.seen[dir].td_end = end;
conntrack->proto.tcp.last_end = end;
- WRITE_UNLOCK(&tcp_lock);
+ write_unlock_bh(&tcp_lock);
DEBUGP("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i "
"receiver end=%u maxend=%u maxwin=%u scale=%i\n",
sender->td_end, sender->td_maxend, sender->td_maxwin,
@@ -857,7 +856,7 @@ static int tcp_packet(struct ip_conntrack *conntrack,
sizeof(_tcph), &_tcph);
BUG_ON(th == NULL);
- WRITE_LOCK(&tcp_lock);
+ write_lock_bh(&tcp_lock);
old_state = conntrack->proto.tcp.state;
dir = CTINFO2DIR(ctinfo);
index = get_conntrack_index(th);
@@ -879,7 +878,7 @@ static int tcp_packet(struct ip_conntrack *conntrack,
* that the client cannot but retransmit its SYN and
* thus initiate a clean new session.
*/
- WRITE_UNLOCK(&tcp_lock);
+ write_unlock_bh(&tcp_lock);
if (LOG_INVALID(IPPROTO_TCP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL,
"ip_ct_tcp: killing out of sync session ");
@@ -894,7 +893,7 @@ static int tcp_packet(struct ip_conntrack *conntrack,
conntrack->proto.tcp.last_end =
segment_seq_plus_len(ntohl(th->seq), skb->len, iph, th);
- WRITE_UNLOCK(&tcp_lock);
+ write_unlock_bh(&tcp_lock);
if (LOG_INVALID(IPPROTO_TCP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL,
"ip_ct_tcp: invalid packet ignored ");
@@ -904,7 +903,7 @@ static int tcp_packet(struct ip_conntrack *conntrack,
DEBUGP("ip_ct_tcp: Invalid dir=%i index=%u ostate=%u\n",
dir, get_conntrack_index(th),
old_state);
- WRITE_UNLOCK(&tcp_lock);
+ write_unlock_bh(&tcp_lock);
if (LOG_INVALID(IPPROTO_TCP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL,
"ip_ct_tcp: invalid state ");
@@ -918,13 +917,13 @@ static int tcp_packet(struct ip_conntrack *conntrack,
conntrack->proto.tcp.seen[dir].td_end)) {
/* Attempt to reopen a closed connection.
* Delete this connection and look up again. */
- WRITE_UNLOCK(&tcp_lock);
+ write_unlock_bh(&tcp_lock);
if (del_timer(&conntrack->timeout))
conntrack->timeout.function((unsigned long)
conntrack);
return -NF_REPEAT;
} else {
- WRITE_UNLOCK(&tcp_lock);
+ write_unlock_bh(&tcp_lock);
if (LOG_INVALID(IPPROTO_TCP))
nf_log_packet(PF_INET, 0, skb, NULL, NULL,
"ip_ct_tcp: invalid SYN");
@@ -949,7 +948,7 @@ static int tcp_packet(struct ip_conntrack *conntrack,
if (!tcp_in_window(&conntrack->proto.tcp, dir, index,
skb, iph, th)) {
- WRITE_UNLOCK(&tcp_lock);
+ write_unlock_bh(&tcp_lock);
return -NF_ACCEPT;
}
in_window:
@@ -972,7 +971,7 @@ static int tcp_packet(struct ip_conntrack *conntrack,
timeout = conntrack->proto.tcp.retrans >= ip_ct_tcp_max_retrans
&& *tcp_timeouts[new_state] > ip_ct_tcp_timeout_max_retrans
? ip_ct_tcp_timeout_max_retrans : *tcp_timeouts[new_state];
- WRITE_UNLOCK(&tcp_lock);
+ write_unlock_bh(&tcp_lock);
if (!test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
/* If only reply is a RST, we can consider ourselves not to
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_udp.c b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
index 5bc28a22462..8c1eaba098d 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_udp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
@@ -120,6 +120,7 @@ static int udp_error(struct sk_buff *skb, enum ip_conntrack_info *ctinfo,
* and moreover root might send raw packets.
* FIXME: Source route IP option packets --RR */
if (hooknum == NF_IP_PRE_ROUTING
+ && skb->ip_summed != CHECKSUM_UNNECESSARY
&& csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
skb->ip_summed == CHECKSUM_HW ? skb->csum
: skb_checksum(skb, iph->ihl*4, udplen, 0))) {
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 46ca45f74d8..42dc9510287 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -28,8 +28,8 @@
#include <net/checksum.h>
#include <net/ip.h>
-#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock)
-#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_conntrack_lock)
+#define ASSERT_READ_LOCK(x)
+#define ASSERT_WRITE_LOCK(x)
#include <linux/netfilter_ipv4/ip_conntrack.h>
#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
@@ -119,7 +119,7 @@ static struct list_head *ct_get_idx(struct seq_file *seq, loff_t pos)
static void *ct_seq_start(struct seq_file *seq, loff_t *pos)
{
- READ_LOCK(&ip_conntrack_lock);
+ read_lock_bh(&ip_conntrack_lock);
return ct_get_idx(seq, *pos);
}
@@ -131,7 +131,7 @@ static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos)
static void ct_seq_stop(struct seq_file *s, void *v)
{
- READ_UNLOCK(&ip_conntrack_lock);
+ read_unlock_bh(&ip_conntrack_lock);
}
static int ct_seq_show(struct seq_file *s, void *v)
@@ -140,7 +140,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
const struct ip_conntrack *conntrack = tuplehash_to_ctrack(hash);
struct ip_conntrack_protocol *proto;
- MUST_BE_READ_LOCKED(&ip_conntrack_lock);
+ ASSERT_READ_LOCK(&ip_conntrack_lock);
IP_NF_ASSERT(conntrack);
/* we only want to print DIR_ORIGINAL */
@@ -239,7 +239,7 @@ static void *exp_seq_start(struct seq_file *s, loff_t *pos)
/* strange seq_file api calls stop even if we fail,
* thus we need to grab lock since stop unlocks */
- READ_LOCK(&ip_conntrack_lock);
+ read_lock_bh(&ip_conntrack_lock);
if (list_empty(e))
return NULL;
@@ -256,6 +256,7 @@ static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos)
{
struct list_head *e = v;
+ ++*pos;
e = e->next;
if (e == &ip_conntrack_expect_list)
@@ -266,7 +267,7 @@ static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos)
static void exp_seq_stop(struct seq_file *s, void *v)
{
- READ_UNLOCK(&ip_conntrack_lock);
+ read_unlock_bh(&ip_conntrack_lock);
}
static int exp_seq_show(struct seq_file *s, void *v)
@@ -920,22 +921,22 @@ int ip_conntrack_protocol_register(struct ip_conntrack_protocol *proto)
{
int ret = 0;
- WRITE_LOCK(&ip_conntrack_lock);
+ write_lock_bh(&ip_conntrack_lock);
if (ip_ct_protos[proto->proto] != &ip_conntrack_generic_protocol) {
ret = -EBUSY;
goto out;
}
ip_ct_protos[proto->proto] = proto;
out:
- WRITE_UNLOCK(&ip_conntrack_lock);
+ write_unlock_bh(&ip_conntrack_lock);
return ret;
}
void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
{
- WRITE_LOCK(&ip_conntrack_lock);
+ write_lock_bh(&ip_conntrack_lock);
ip_ct_protos[proto->proto] = &ip_conntrack_generic_protocol;
- WRITE_UNLOCK(&ip_conntrack_lock);
+ write_unlock_bh(&ip_conntrack_lock);
/* Somebody could be still looking at the proto in bh. */
synchronize_net();
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
index 9fc6f93af0d..739b6dde1c8 100644
--- a/net/ipv4/netfilter/ip_nat_core.c
+++ b/net/ipv4/netfilter/ip_nat_core.c
@@ -22,8 +22,8 @@
#include <linux/udp.h>
#include <linux/jhash.h>
-#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock)
-#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock)
+#define ASSERT_READ_LOCK(x)
+#define ASSERT_WRITE_LOCK(x)
#include <linux/netfilter_ipv4/ip_conntrack.h>
#include <linux/netfilter_ipv4/ip_conntrack_core.h>
@@ -41,7 +41,7 @@
#define DEBUGP(format, args...)
#endif
-DECLARE_RWLOCK(ip_nat_lock);
+DEFINE_RWLOCK(ip_nat_lock);
/* Calculated at init based on memory size */
static unsigned int ip_nat_htable_size;
@@ -65,9 +65,9 @@ static void ip_nat_cleanup_conntrack(struct ip_conntrack *conn)
if (!(conn->status & IPS_NAT_DONE_MASK))
return;
- WRITE_LOCK(&ip_nat_lock);
+ write_lock_bh(&ip_nat_lock);
list_del(&conn->nat.info.bysource);
- WRITE_UNLOCK(&ip_nat_lock);
+ write_unlock_bh(&ip_nat_lock);
}
/* We do checksum mangling, so if they were wrong before they're still
@@ -142,7 +142,7 @@ find_appropriate_src(const struct ip_conntrack_tuple *tuple,
unsigned int h = hash_by_src(tuple);
struct ip_conntrack *ct;
- READ_LOCK(&ip_nat_lock);
+ read_lock_bh(&ip_nat_lock);
list_for_each_entry(ct, &bysource[h], nat.info.bysource) {
if (same_src(ct, tuple)) {
/* Copy source part from reply tuple. */
@@ -151,12 +151,12 @@ find_appropriate_src(const struct ip_conntrack_tuple *tuple,
result->dst = tuple->dst;
if (in_range(result, range)) {
- READ_UNLOCK(&ip_nat_lock);
+ read_unlock_bh(&ip_nat_lock);
return 1;
}
}
}
- READ_UNLOCK(&ip_nat_lock);
+ read_unlock_bh(&ip_nat_lock);
return 0;
}
@@ -297,9 +297,9 @@ ip_nat_setup_info(struct ip_conntrack *conntrack,
unsigned int srchash
= hash_by_src(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
.tuple);
- WRITE_LOCK(&ip_nat_lock);
+ write_lock_bh(&ip_nat_lock);
list_add(&info->bysource, &bysource[srchash]);
- WRITE_UNLOCK(&ip_nat_lock);
+ write_unlock_bh(&ip_nat_lock);
}
/* It's done. */
@@ -474,23 +474,23 @@ int ip_nat_protocol_register(struct ip_nat_protocol *proto)
{
int ret = 0;
- WRITE_LOCK(&ip_nat_lock);
+ write_lock_bh(&ip_nat_lock);
if (ip_nat_protos[proto->protonum] != &ip_nat_unknown_protocol) {
ret = -EBUSY;
goto out;
}
ip_nat_protos[proto->protonum] = proto;
out:
- WRITE_UNLOCK(&ip_nat_lock);
+ write_unlock_bh(&ip_nat_lock);
return ret;
}
/* Noone stores the protocol anywhere; simply delete it. */
void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)
{
- WRITE_LOCK(&ip_nat_lock);
+ write_lock_bh(&ip_nat_lock);
ip_nat_protos[proto->protonum] = &ip_nat_unknown_protocol;
- WRITE_UNLOCK(&ip_nat_lock);
+ write_unlock_bh(&ip_nat_lock);
/* Someone could be still looking at the proto in a bh. */
synchronize_net();
@@ -509,13 +509,13 @@ int __init ip_nat_init(void)
return -ENOMEM;
/* Sew in builtin protocols. */
- WRITE_LOCK(&ip_nat_lock);
+ write_lock_bh(&ip_nat_lock);
for (i = 0; i < MAX_IP_NAT_PROTO; i++)
ip_nat_protos[i] = &ip_nat_unknown_protocol;
ip_nat_protos[IPPROTO_TCP] = &ip_nat_protocol_tcp;
ip_nat_protos[IPPROTO_UDP] = &ip_nat_protocol_udp;
ip_nat_protos[IPPROTO_ICMP] = &ip_nat_protocol_icmp;
- WRITE_UNLOCK(&ip_nat_lock);
+ write_unlock_bh(&ip_nat_lock);
for (i = 0; i < ip_nat_htable_size; i++) {
INIT_LIST_HEAD(&bysource[i]);
diff --git a/net/ipv4/netfilter/ip_nat_helper.c b/net/ipv4/netfilter/ip_nat_helper.c
index 1637b96d8c0..158f34f32c0 100644
--- a/net/ipv4/netfilter/ip_nat_helper.c
+++ b/net/ipv4/netfilter/ip_nat_helper.c
@@ -28,8 +28,8 @@
#include <net/tcp.h>
#include <net/udp.h>
-#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock)
-#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock)
+#define ASSERT_READ_LOCK(x)
+#define ASSERT_WRITE_LOCK(x)
#include <linux/netfilter_ipv4/ip_conntrack.h>
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
@@ -47,7 +47,7 @@
#define DUMP_OFFSET(x)
#endif
-static DECLARE_LOCK(ip_nat_seqofs_lock);
+static DEFINE_SPINLOCK(ip_nat_seqofs_lock);
/* Setup TCP sequence correction given this change at this sequence */
static inline void
@@ -70,7 +70,7 @@ adjust_tcp_sequence(u32 seq,
DEBUGP("ip_nat_resize_packet: Seq_offset before: ");
DUMP_OFFSET(this_way);
- LOCK_BH(&ip_nat_seqofs_lock);
+ spin_lock_bh(&ip_nat_seqofs_lock);
/* SYN adjust. If it's uninitialized, or this is after last
* correction, record it: we don't handle more than one
@@ -82,7 +82,7 @@ adjust_tcp_sequence(u32 seq,
this_way->offset_before = this_way->offset_after;
this_way->offset_after += sizediff;
}
- UNLOCK_BH(&ip_nat_seqofs_lock);
+ spin_unlock_bh(&ip_nat_seqofs_lock);
DEBUGP("ip_nat_resize_packet: Seq_offset after: ");
DUMP_OFFSET(this_way);
@@ -142,9 +142,6 @@ static int enlarge_skb(struct sk_buff **pskb, unsigned int extra)
/* Transfer socket to new skb. */
if ((*pskb)->sk)
skb_set_owner_w(nskb, (*pskb)->sk);
-#ifdef CONFIG_NETFILTER_DEBUG
- nskb->nf_debug = (*pskb)->nf_debug;
-#endif
kfree_skb(*pskb);
*pskb = nskb;
return 1;
diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c
index 581f097f5a2..60d70fa41a1 100644
--- a/net/ipv4/netfilter/ip_nat_rule.c
+++ b/net/ipv4/netfilter/ip_nat_rule.c
@@ -19,8 +19,8 @@
#include <net/route.h>
#include <linux/bitops.h>
-#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock)
-#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock)
+#define ASSERT_READ_LOCK(x)
+#define ASSERT_WRITE_LOCK(x)
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ip_nat.h>
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index 79f56f662b3..bc59d0d6e89 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -31,8 +31,8 @@
#include <net/checksum.h>
#include <linux/spinlock.h>
-#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock)
-#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock)
+#define ASSERT_READ_LOCK(x)
+#define ASSERT_WRITE_LOCK(x)
#include <linux/netfilter_ipv4/ip_nat.h>
#include <linux/netfilter_ipv4/ip_nat_rule.h>
@@ -373,7 +373,6 @@ static int init_or_cleanup(int init)
cleanup_rule_init:
ip_nat_rule_cleanup();
cleanup_nothing:
- MUST_BE_READ_WRITE_UNLOCKED(&ip_nat_lock);
return ret;
}
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index e5746b67441..eda1fba431a 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -3,6 +3,7 @@
* communicating with userspace via netlink.
*
* (C) 2000-2002 James Morris <jmorris@intercode.com.au>
+ * (C) 2003-2005 Netfilter Core Team <coreteam@netfilter.org>
*
* 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
@@ -17,6 +18,7 @@
* 2005-01-10: Added /proc counter for dropped packets; fixed so
* packets aren't delivered to user space if they're going
* to be dropped.
+ * 2005-05-26: local_bh_{disable,enable} around nf_reinject (Harald Welte)
*
*/
#include <linux/module.h>
@@ -71,7 +73,15 @@ static DECLARE_MUTEX(ipqnl_sem);
static void
ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict)
{
+ /* TCP input path (and probably other bits) assume to be called
+ * from softirq context, not from syscall, like ipq_issue_verdict is
+ * called. TCP input path deadlocks with locks taken from timer
+ * softirq, e.g. We therefore emulate this by local_bh_disable() */
+
+ local_bh_disable();
nf_reinject(entry->skb, entry->info, verdict);
+ local_bh_enable();
+
kfree(entry);
}
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 8a54f92b849..c88dfcd38c5 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -67,7 +67,6 @@ static DECLARE_MUTEX(ipt_mutex);
/* Must have mutex */
#define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0)
#define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0)
-#include <linux/netfilter_ipv4/lockhelp.h>
#include <linux/netfilter_ipv4/listhelp.h>
#if 0
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 0f12e3a3dc7..9cde8c61f52 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -29,7 +29,6 @@
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_CLUSTERIP.h>
#include <linux/netfilter_ipv4/ip_conntrack.h>
-#include <linux/netfilter_ipv4/lockhelp.h>
#define CLUSTERIP_VERSION "0.6"
@@ -41,6 +40,8 @@
#define DEBUGP
#endif
+#define ASSERT_READ_LOCK(x)
+
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
MODULE_DESCRIPTION("iptables target for CLUSTERIP");
@@ -67,7 +68,7 @@ static LIST_HEAD(clusterip_configs);
/* clusterip_lock protects the clusterip_configs list _AND_ the configurable
* data within all structurses (num_local_nodes, local_nodes[]) */
-static DECLARE_RWLOCK(clusterip_lock);
+static DEFINE_RWLOCK(clusterip_lock);
#ifdef CONFIG_PROC_FS
static struct file_operations clusterip_proc_fops;
@@ -82,9 +83,9 @@ clusterip_config_get(struct clusterip_config *c) {
static inline void
clusterip_config_put(struct clusterip_config *c) {
if (atomic_dec_and_test(&c->refcount)) {
- WRITE_LOCK(&clusterip_lock);
+ write_lock_bh(&clusterip_lock);
list_del(&c->list);
- WRITE_UNLOCK(&clusterip_lock);
+ write_unlock_bh(&clusterip_lock);
dev_mc_delete(c->dev, c->clustermac, ETH_ALEN, 0);
dev_put(c->dev);
kfree(c);
@@ -97,7 +98,7 @@ __clusterip_config_find(u_int32_t clusterip)
{
struct list_head *pos;
- MUST_BE_READ_LOCKED(&clusterip_lock);
+ ASSERT_READ_LOCK(&clusterip_lock);
list_for_each(pos, &clusterip_configs) {
struct clusterip_config *c = list_entry(pos,
struct clusterip_config, list);
@@ -114,14 +115,14 @@ clusterip_config_find_get(u_int32_t clusterip)
{
struct clusterip_config *c;
- READ_LOCK(&clusterip_lock);
+ read_lock_bh(&clusterip_lock);
c = __clusterip_config_find(clusterip);
if (!c) {
- READ_UNLOCK(&clusterip_lock);
+ read_unlock_bh(&clusterip_lock);
return NULL;
}
atomic_inc(&c->refcount);
- READ_UNLOCK(&clusterip_lock);
+ read_unlock_bh(&clusterip_lock);
return c;
}
@@ -160,9 +161,9 @@ clusterip_config_init(struct ipt_clusterip_tgt_info *i, u_int32_t ip,
c->pde->data = c;
#endif
- WRITE_LOCK(&clusterip_lock);
+ write_lock_bh(&clusterip_lock);
list_add(&c->list, &clusterip_configs);
- WRITE_UNLOCK(&clusterip_lock);
+ write_unlock_bh(&clusterip_lock);
return c;
}
@@ -172,25 +173,25 @@ clusterip_add_node(struct clusterip_config *c, u_int16_t nodenum)
{
int i;
- WRITE_LOCK(&clusterip_lock);
+ write_lock_bh(&clusterip_lock);
if (c->num_local_nodes >= CLUSTERIP_MAX_NODES
|| nodenum > CLUSTERIP_MAX_NODES) {
- WRITE_UNLOCK(&clusterip_lock);
+ write_unlock_bh(&clusterip_lock);
return 1;
}
/* check if we alrady have this number in our array */
for (i = 0; i < c->num_local_nodes; i++) {
if (c->local_nodes[i] == nodenum) {
- WRITE_UNLOCK(&clusterip_lock);
+ write_unlock_bh(&clusterip_lock);
return 1;
}
}
c->local_nodes[c->num_local_nodes++] = nodenum;
- WRITE_UNLOCK(&clusterip_lock);
+ write_unlock_bh(&clusterip_lock);
return 0;
}
@@ -199,10 +200,10 @@ clusterip_del_node(struct clusterip_config *c, u_int16_t nodenum)
{
int i;
- WRITE_LOCK(&clusterip_lock);
+ write_lock_bh(&clusterip_lock);
if (c->num_local_nodes <= 1 || nodenum > CLUSTERIP_MAX_NODES) {
- WRITE_UNLOCK(&clusterip_lock);
+ write_unlock_bh(&clusterip_lock);
return 1;
}
@@ -211,12 +212,12 @@ clusterip_del_node(struct clusterip_config *c, u_int16_t nodenum)
int size = sizeof(u_int16_t)*(c->num_local_nodes-(i+1));
memmove(&c->local_nodes[i], &c->local_nodes[i+1], size);
c->num_local_nodes--;
- WRITE_UNLOCK(&clusterip_lock);
+ write_unlock_bh(&clusterip_lock);
return 0;
}
}
- WRITE_UNLOCK(&clusterip_lock);
+ write_unlock_bh(&clusterip_lock);
return 1;
}
@@ -286,21 +287,21 @@ clusterip_responsible(struct clusterip_config *config, u_int32_t hash)
{
int i;
- READ_LOCK(&clusterip_lock);
+ read_lock_bh(&clusterip_lock);
if (config->num_local_nodes == 0) {
- READ_UNLOCK(&clusterip_lock);
+ read_unlock_bh(&clusterip_lock);
return 0;
}
for (i = 0; i < config->num_local_nodes; i++) {
if (config->local_nodes[i] == hash) {
- READ_UNLOCK(&clusterip_lock);
+ read_unlock_bh(&clusterip_lock);
return 1;
}
}
- READ_UNLOCK(&clusterip_lock);
+ read_unlock_bh(&clusterip_lock);
return 0;
}
@@ -338,7 +339,7 @@ target(struct sk_buff **pskb,
* error messages (RELATED) and information requests (see below) */
if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP
&& (ctinfo == IP_CT_RELATED
- || ctinfo == IP_CT_IS_REPLY+IP_CT_IS_REPLY))
+ || ctinfo == IP_CT_RELATED+IP_CT_IS_REPLY))
return IPT_CONTINUE;
/* ip_conntrack_icmp guarantees us that we only have ICMP_ECHO,
@@ -578,7 +579,7 @@ static void *clusterip_seq_start(struct seq_file *s, loff_t *pos)
struct clusterip_config *c = pde->data;
unsigned int *nodeidx;
- READ_LOCK(&clusterip_lock);
+ read_lock_bh(&clusterip_lock);
if (*pos >= c->num_local_nodes)
return NULL;
@@ -608,7 +609,7 @@ static void clusterip_seq_stop(struct seq_file *s, void *v)
{
kfree(v);
- READ_UNLOCK(&clusterip_lock);
+ read_unlock_bh(&clusterip_lock);
}
static int clusterip_seq_show(struct seq_file *s, void *v)
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index 57e9f6cf1c3..91e74502c3d 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -33,7 +33,7 @@ MODULE_DESCRIPTION("iptables MASQUERADE target module");
#endif
/* Lock protects masq region inside conntrack */
-static DECLARE_RWLOCK(masq_lock);
+static DEFINE_RWLOCK(masq_lock);
/* FIXME: Multiple targets. --RR */
static int
@@ -103,9 +103,9 @@ masquerade_target(struct sk_buff **pskb,
return NF_DROP;
}
- WRITE_LOCK(&masq_lock);
+ write_lock_bh(&masq_lock);
ct->nat.masq_index = out->ifindex;
- WRITE_UNLOCK(&masq_lock);
+ write_unlock_bh(&masq_lock);
/* Transfer from original range. */
newrange = ((struct ip_nat_range)
@@ -122,9 +122,9 @@ device_cmp(struct ip_conntrack *i, void *ifindex)
{
int ret;
- READ_LOCK(&masq_lock);
+ read_lock_bh(&masq_lock);
ret = (i->nat.masq_index == (int)(long)ifindex);
- READ_UNLOCK(&masq_lock);
+ read_unlock_bh(&masq_lock);
return ret;
}
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 266d6497928..91569644602 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -104,10 +104,12 @@ static inline struct rtable *route_reverse(struct sk_buff *skb,
static void send_reset(struct sk_buff *oldskb, int hook)
{
struct sk_buff *nskb;
+ struct iphdr *iph = oldskb->nh.iph;
struct tcphdr _otcph, *oth, *tcph;
struct rtable *rt;
u_int16_t tmp_port;
u_int32_t tmp_addr;
+ unsigned int tcplen;
int needs_ack;
int hh_len;
@@ -124,7 +126,16 @@ static void send_reset(struct sk_buff *oldskb, int hook)
if (oth->rst)
return;
- /* FIXME: Check checksum --RR */
+ /* Check checksum */
+ tcplen = oldskb->len - iph->ihl * 4;
+ if (((hook != NF_IP_LOCAL_IN && oldskb->ip_summed != CHECKSUM_HW) ||
+ (hook == NF_IP_LOCAL_IN &&
+ oldskb->ip_summed != CHECKSUM_UNNECESSARY)) &&
+ csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP,
+ oldskb->ip_summed == CHECKSUM_HW ? oldskb->csum :
+ skb_checksum(oldskb, iph->ihl * 4, tcplen, 0)))
+ return;
+
if ((rt = route_reverse(oldskb, oth, hook)) == NULL)
return;
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index 6f2cefbe16c..52a0076302a 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -56,7 +56,6 @@
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_ULOG.h>
-#include <linux/netfilter_ipv4/lockhelp.h>
#include <net/sock.h>
#include <linux/bitops.h>
@@ -99,8 +98,8 @@ typedef struct {
static ulog_buff_t ulog_buffers[ULOG_MAXNLGROUPS]; /* array of buffers */
-static struct sock *nflognl; /* our socket */
-static DECLARE_LOCK(ulog_lock); /* spinlock */
+static struct sock *nflognl; /* our socket */
+static DEFINE_SPINLOCK(ulog_lock); /* spinlock */
/* send one ulog_buff_t to userspace */
static void ulog_send(unsigned int nlgroupnum)
@@ -135,9 +134,9 @@ static void ulog_timer(unsigned long data)
/* lock to protect against somebody modifying our structure
* from ipt_ulog_target at the same time */
- LOCK_BH(&ulog_lock);
+ spin_lock_bh(&ulog_lock);
ulog_send(data);
- UNLOCK_BH(&ulog_lock);
+ spin_unlock_bh(&ulog_lock);
}
static struct sk_buff *ulog_alloc_skb(unsigned int size)
@@ -193,7 +192,7 @@ static void ipt_ulog_packet(unsigned int hooknum,
ub = &ulog_buffers[groupnum];
- LOCK_BH(&ulog_lock);
+ spin_lock_bh(&ulog_lock);
if (!ub->skb) {
if (!(ub->skb = ulog_alloc_skb(size)))
@@ -278,7 +277,7 @@ static void ipt_ulog_packet(unsigned int hooknum,
ulog_send(groupnum);
}
- UNLOCK_BH(&ulog_lock);
+ spin_unlock_bh(&ulog_lock);
return;
@@ -288,7 +287,7 @@ nlmsg_failure:
alloc_failure:
PRINTR("ipt_ULOG: Error building netlink message\n");
- UNLOCK_BH(&ulog_lock);
+ spin_unlock_bh(&ulog_lock);
}
static unsigned int ipt_ulog_target(struct sk_buff **pskb,
diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c
index f1937190cd7..564b49bfebc 100644
--- a/net/ipv4/netfilter/ipt_hashlimit.c
+++ b/net/ipv4/netfilter/ipt_hashlimit.c
@@ -37,7 +37,6 @@
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_hashlimit.h>
-#include <linux/netfilter_ipv4/lockhelp.h>
/* FIXME: this is just for IP_NF_ASSERRT */
#include <linux/netfilter_ipv4/ip_conntrack.h>
@@ -92,7 +91,7 @@ struct ipt_hashlimit_htable {
struct hlist_head hash[0]; /* hashtable itself */
};
-static DECLARE_LOCK(hashlimit_lock); /* protects htables list */
+static DEFINE_SPINLOCK(hashlimit_lock); /* protects htables list */
static DECLARE_MUTEX(hlimit_mutex); /* additional checkentry protection */
static HLIST_HEAD(hashlimit_htables);
static kmem_cache_t *hashlimit_cachep;
@@ -233,9 +232,9 @@ static int htable_create(struct ipt_hashlimit_info *minfo)
hinfo->timer.function = htable_gc;
add_timer(&hinfo->timer);
- LOCK_BH(&hashlimit_lock);
+ spin_lock_bh(&hashlimit_lock);
hlist_add_head(&hinfo->node, &hashlimit_htables);
- UNLOCK_BH(&hashlimit_lock);
+ spin_unlock_bh(&hashlimit_lock);
return 0;
}
@@ -301,15 +300,15 @@ static struct ipt_hashlimit_htable *htable_find_get(char *name)
struct ipt_hashlimit_htable *hinfo;
struct hlist_node *pos;
- LOCK_BH(&hashlimit_lock);
+ spin_lock_bh(&hashlimit_lock);
hlist_for_each_entry(hinfo, pos, &hashlimit_htables, node) {
if (!strcmp(name, hinfo->pde->name)) {
atomic_inc(&hinfo->use);
- UNLOCK_BH(&hashlimit_lock);
+ spin_unlock_bh(&hashlimit_lock);
return hinfo;
}
}
- UNLOCK_BH(&hashlimit_lock);
+ spin_unlock_bh(&hashlimit_lock);
return NULL;
}
@@ -317,9 +316,9 @@ static struct ipt_hashlimit_htable *htable_find_get(char *name)
static void htable_put(struct ipt_hashlimit_htable *hinfo)
{
if (atomic_dec_and_test(&hinfo->use)) {
- LOCK_BH(&hashlimit_lock);
+ spin_lock_bh(&hashlimit_lock);
hlist_del(&hinfo->node);
- UNLOCK_BH(&hashlimit_lock);
+ spin_unlock_bh(&hashlimit_lock);
htable_destroy(hinfo);
}
}
diff --git a/net/ipv4/netfilter/ipt_helper.c b/net/ipv4/netfilter/ipt_helper.c
index 33fdf364d3d..3e7dd014de4 100644
--- a/net/ipv4/netfilter/ipt_helper.c
+++ b/net/ipv4/netfilter/ipt_helper.c
@@ -53,7 +53,7 @@ match(const struct sk_buff *skb,
return ret;
}
- READ_LOCK(&ip_conntrack_lock);
+ read_lock_bh(&ip_conntrack_lock);
if (!ct->master->helper) {
DEBUGP("ipt_helper: master ct %p has no helper\n",
exp->expectant);
@@ -69,7 +69,7 @@ match(const struct sk_buff *skb,
ret ^= !strncmp(ct->master->helper->name, info->name,
strlen(ct->master->helper->name));
out_unlock:
- READ_UNLOCK(&ip_conntrack_lock);
+ read_unlock_bh(&ip_conntrack_lock);
return ret;
}
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index 25ab9fabdcb..2d44b07688a 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -223,7 +223,7 @@ static int ip_recent_ctrl(struct file *file, const char __user *input, unsigned
curr_table->table[count].last_seen = 0;
curr_table->table[count].addr = 0;
curr_table->table[count].ttl = 0;
- memset(curr_table->table[count].last_pkts,0,ip_pkt_list_tot*sizeof(u_int32_t));
+ memset(curr_table->table[count].last_pkts,0,ip_pkt_list_tot*sizeof(unsigned long));
curr_table->table[count].oldest_pkt = 0;
curr_table->table[count].time_pos = 0;
curr_table->time_info[count].position = count;
@@ -502,7 +502,7 @@ match(const struct sk_buff *skb,
location = time_info[curr_table->time_pos].position;
hash_table[r_list[location].hash_entry] = -1;
hash_table[hash_result] = location;
- memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(u_int32_t));
+ memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(unsigned long));
r_list[location].time_pos = curr_table->time_pos;
r_list[location].addr = addr;
r_list[location].ttl = ttl;
@@ -631,7 +631,7 @@ match(const struct sk_buff *skb,
r_list[location].last_seen = 0;
r_list[location].addr = 0;
r_list[location].ttl = 0;
- memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(u_int32_t));
+ memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(unsigned long));
r_list[location].oldest_pkt = 0;
ans = !info->invert;
}
@@ -734,10 +734,10 @@ checkentry(const char *tablename,
memset(curr_table->table,0,sizeof(struct recent_ip_list)*ip_list_tot);
#ifdef DEBUG
if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: Allocating %d for pkt_list.\n",
- sizeof(u_int32_t)*ip_pkt_list_tot*ip_list_tot);
+ sizeof(unsigned long)*ip_pkt_list_tot*ip_list_tot);
#endif
- hold = vmalloc(sizeof(u_int32_t)*ip_pkt_list_tot*ip_list_tot);
+ hold = vmalloc(sizeof(unsigned long)*ip_pkt_list_tot*ip_list_tot);
#ifdef DEBUG
if(debug) printk(KERN_INFO RECENT_NAME ": checkentry: After pkt_list allocation.\n");
#endif
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 5b1ec586bae..d1835b1bc8c 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -259,7 +259,7 @@ int raw_rcv(struct sock *sk, struct sk_buff *skb)
return 0;
}
-static int raw_send_hdrinc(struct sock *sk, void *from, int length,
+static int raw_send_hdrinc(struct sock *sk, void *from, size_t length,
struct rtable *rt,
unsigned int flags)
{
@@ -298,7 +298,7 @@ static int raw_send_hdrinc(struct sock *sk, void *from, int length,
goto error_fault;
/* We don't modify invalid header */
- if (length >= sizeof(*iph) && iph->ihl * 4 <= length) {
+ if (length >= sizeof(*iph) && iph->ihl * 4U <= length) {
if (!iph->saddr)
iph->saddr = rt->rt_src;
iph->check = 0;
@@ -332,7 +332,7 @@ static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
u8 __user *type = NULL;
u8 __user *code = NULL;
int probed = 0;
- int i;
+ unsigned int i;
if (!msg->msg_iov)
return;
@@ -384,7 +384,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
int err;
err = -EMSGSIZE;
- if (len < 0 || len > 0xFFFF)
+ if (len > 0xFFFF)
goto out;
/*
@@ -514,7 +514,10 @@ done:
kfree(ipc.opt);
ip_rt_put(rt);
-out: return err < 0 ? err : len;
+out:
+ if (err < 0)
+ return err;
+ return len;
do_confirm:
dst_confirm(&rt->u.dst);
@@ -610,7 +613,10 @@ static int raw_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
copied = skb->len;
done:
skb_free_datagram(sk, skb);
-out: return err ? err : copied;
+out:
+ if (err)
+ return err;
+ return copied;
}
static int raw_init(struct sock *sk)
@@ -691,11 +697,11 @@ static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg)
struct sk_buff *skb;
int amount = 0;
- spin_lock_irq(&sk->sk_receive_queue.lock);
+ spin_lock_bh(&sk->sk_receive_queue.lock);
skb = skb_peek(&sk->sk_receive_queue);
if (skb != NULL)
amount = skb->len;
- spin_unlock_irq(&sk->sk_receive_queue.lock);
+ spin_unlock_bh(&sk->sk_receive_queue.lock);
return put_user(amount, (int __user *)arg);
}
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index a682d28e247..80cf633d9f4 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1767,7 +1767,7 @@ static inline int ip_mkroute_input_def(struct sk_buff *skb,
struct in_device *in_dev,
u32 daddr, u32 saddr, u32 tos)
{
- struct rtable* rth;
+ struct rtable* rth = NULL;
int err;
unsigned hash;
@@ -1794,7 +1794,7 @@ static inline int ip_mkroute_input(struct sk_buff *skb,
u32 daddr, u32 saddr, u32 tos)
{
#ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
- struct rtable* rth;
+ struct rtable* rth = NULL;
unsigned char hop, hopcount, lasthop;
int err = -EINVAL;
unsigned int hash;
@@ -2239,7 +2239,7 @@ static inline int ip_mkroute_output_def(struct rtable **rp,
struct net_device *dev_out,
unsigned flags)
{
- struct rtable *rth;
+ struct rtable *rth = NULL;
int err = __mkroute_output(&rth, res, fl, oldflp, dev_out, flags);
unsigned hash;
if (err == 0) {
@@ -2267,7 +2267,7 @@ static inline int ip_mkroute_output(struct rtable** rp,
unsigned char hop;
unsigned hash;
int err = -EINVAL;
- struct rtable *rth;
+ struct rtable *rth = NULL;
if (res->fi && res->fi->fib_nhs > 1) {
unsigned char hopcount = res->fi->fib_nhs;
@@ -2581,7 +2581,7 @@ int ip_route_output_key(struct rtable **rp, struct flowi *flp)
}
static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
- int nowait)
+ int nowait, unsigned int flags)
{
struct rtable *rt = (struct rtable*)skb->dst;
struct rtmsg *r;
@@ -2591,9 +2591,8 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
#ifdef CONFIG_IP_MROUTE
struct rtattr *eptr;
#endif
- nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*r));
+ nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags);
r = NLMSG_DATA(nlh);
- nlh->nlmsg_flags = (nowait && pid) ? NLM_F_MULTI : 0;
r->rtm_family = AF_INET;
r->rtm_dst_len = 32;
r->rtm_src_len = 0;
@@ -2744,7 +2743,7 @@ int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
err = rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,
- RTM_NEWROUTE, 0);
+ RTM_NEWROUTE, 0, 0);
if (!err)
goto out_free;
if (err < 0) {
@@ -2781,8 +2780,8 @@ int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb)
continue;
skb->dst = dst_clone(&rt->u.dst);
if (rt_fill_info(skb, NETLINK_CB(cb->skb).pid,
- cb->nlh->nlmsg_seq,
- RTM_NEWROUTE, 1) <= 0) {
+ cb->nlh->nlmsg_seq, RTM_NEWROUTE,
+ 1, NLM_F_MULTI) <= 0) {
dst_release(xchg(&skb->dst, NULL));
rcu_read_unlock_bh();
goto done;
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index e923d2f021a..72d01444218 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -169,10 +169,10 @@ static inline int cookie_check(struct sk_buff *skb, __u32 cookie)
return mssind < NUM_MSS ? msstab[mssind] + 1 : 0;
}
-extern struct or_calltable or_ipv4;
+extern struct request_sock_ops tcp_request_sock_ops;
static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,
- struct open_request *req,
+ struct request_sock *req,
struct dst_entry *dst)
{
struct tcp_sock *tp = tcp_sk(sk);
@@ -182,7 +182,7 @@ static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,
if (child)
tcp_acceptq_queue(sk, req, child);
else
- tcp_openreq_free(req);
+ reqsk_free(req);
return child;
}
@@ -190,10 +190,12 @@ static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,
struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
struct ip_options *opt)
{
+ struct inet_request_sock *ireq;
+ struct tcp_request_sock *treq;
struct tcp_sock *tp = tcp_sk(sk);
__u32 cookie = ntohl(skb->h.th->ack_seq) - 1;
struct sock *ret = sk;
- struct open_request *req;
+ struct request_sock *req;
int mss;
struct rtable *rt;
__u8 rcv_wscale;
@@ -209,19 +211,20 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESRECV);
- req = tcp_openreq_alloc();
ret = NULL;
+ req = reqsk_alloc(&tcp_request_sock_ops); /* for safety */
if (!req)
goto out;
- req->rcv_isn = htonl(skb->h.th->seq) - 1;
- req->snt_isn = cookie;
+ ireq = inet_rsk(req);
+ treq = tcp_rsk(req);
+ treq->rcv_isn = htonl(skb->h.th->seq) - 1;
+ treq->snt_isn = cookie;
req->mss = mss;
- req->rmt_port = skb->h.th->source;
- req->af.v4_req.loc_addr = skb->nh.iph->daddr;
- req->af.v4_req.rmt_addr = skb->nh.iph->saddr;
- req->class = &or_ipv4; /* for savety */
- req->af.v4_req.opt = NULL;
+ ireq->rmt_port = skb->h.th->source;
+ ireq->loc_addr = skb->nh.iph->daddr;
+ ireq->rmt_addr = skb->nh.iph->saddr;
+ ireq->opt = NULL;
/* We throwed the options of the initial SYN away, so we hope
* the ACK carries the same options again (see RFC1122 4.2.3.8)
@@ -229,17 +232,15 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
if (opt && opt->optlen) {
int opt_size = sizeof(struct ip_options) + opt->optlen;
- req->af.v4_req.opt = kmalloc(opt_size, GFP_ATOMIC);
- if (req->af.v4_req.opt) {
- if (ip_options_echo(req->af.v4_req.opt, skb)) {
- kfree(req->af.v4_req.opt);
- req->af.v4_req.opt = NULL;
- }
+ ireq->opt = kmalloc(opt_size, GFP_ATOMIC);
+ if (ireq->opt != NULL && ip_options_echo(ireq->opt, skb)) {
+ kfree(ireq->opt);
+ ireq->opt = NULL;
}
}
- req->snd_wscale = req->rcv_wscale = req->tstamp_ok = 0;
- req->wscale_ok = req->sack_ok = 0;
+ ireq->snd_wscale = ireq->rcv_wscale = ireq->tstamp_ok = 0;
+ ireq->wscale_ok = ireq->sack_ok = 0;
req->expires = 0UL;
req->retrans = 0;
@@ -253,15 +254,15 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
struct flowi fl = { .nl_u = { .ip4_u =
{ .daddr = ((opt && opt->srr) ?
opt->faddr :
- req->af.v4_req.rmt_addr),
- .saddr = req->af.v4_req.loc_addr,
+ ireq->rmt_addr),
+ .saddr = ireq->loc_addr,
.tos = RT_CONN_FLAGS(sk) } },
.proto = IPPROTO_TCP,
.uli_u = { .ports =
{ .sport = skb->h.th->dest,
.dport = skb->h.th->source } } };
if (ip_route_output_key(&rt, &fl)) {
- tcp_openreq_free(req);
+ reqsk_free(req);
goto out;
}
}
@@ -272,7 +273,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
&req->rcv_wnd, &req->window_clamp,
0, &rcv_wscale);
/* BTW win scale with syncookies is 0 by definition */
- req->rcv_wscale = rcv_wscale;
+ ireq->rcv_wscale = rcv_wscale;
ret = get_cookie_sock(sk, skb, req, &rt->u.dst);
out: return ret;
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 3aafb298c1c..e3289453241 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -23,6 +23,7 @@ extern int sysctl_ip_nonlocal_bind;
extern int sysctl_icmp_echo_ignore_all;
extern int sysctl_icmp_echo_ignore_broadcasts;
extern int sysctl_icmp_ignore_bogus_error_responses;
+extern int sysctl_icmp_errors_use_inbound_ifaddr;
/* From ip_fragment.c */
extern int sysctl_ipfrag_low_thresh;
@@ -117,6 +118,45 @@ static int ipv4_sysctl_forward_strategy(ctl_table *table,
return 1;
}
+static int proc_tcp_congestion_control(ctl_table *ctl, int write, struct file * filp,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ char val[TCP_CA_NAME_MAX];
+ ctl_table tbl = {
+ .data = val,
+ .maxlen = TCP_CA_NAME_MAX,
+ };
+ int ret;
+
+ tcp_get_default_congestion_control(val);
+
+ ret = proc_dostring(&tbl, write, filp, buffer, lenp, ppos);
+ if (write && ret == 0)
+ ret = tcp_set_default_congestion_control(val);
+ return ret;
+}
+
+int sysctl_tcp_congestion_control(ctl_table *table, int __user *name, int nlen,
+ void __user *oldval, size_t __user *oldlenp,
+ void __user *newval, size_t newlen,
+ void **context)
+{
+ char val[TCP_CA_NAME_MAX];
+ ctl_table tbl = {
+ .data = val,
+ .maxlen = TCP_CA_NAME_MAX,
+ };
+ int ret;
+
+ tcp_get_default_congestion_control(val);
+ ret = sysctl_string(&tbl, name, nlen, oldval, oldlenp, newval, newlen,
+ context);
+ if (ret == 0 && newval && newlen)
+ ret = tcp_set_default_congestion_control(val);
+ return ret;
+}
+
+
ctl_table ipv4_table[] = {
{
.ctl_name = NET_IPV4_TCP_TIMESTAMPS,
@@ -396,6 +436,14 @@ ctl_table ipv4_table[] = {
.proc_handler = &proc_dointvec
},
{
+ .ctl_name = NET_IPV4_ICMP_ERRORS_USE_INBOUND_IFADDR,
+ .procname = "icmp_errors_use_inbound_ifaddr",
+ .data = &sysctl_icmp_errors_use_inbound_ifaddr,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec
+ },
+ {
.ctl_name = NET_IPV4_ROUTE,
.procname = "route",
.maxlen = 0,
@@ -603,70 +651,6 @@ ctl_table ipv4_table[] = {
.proc_handler = &proc_dointvec,
},
{
- .ctl_name = NET_TCP_WESTWOOD,
- .procname = "tcp_westwood",
- .data = &sysctl_tcp_westwood,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_TCP_VEGAS,
- .procname = "tcp_vegas_cong_avoid",
- .data = &sysctl_tcp_vegas_cong_avoid,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_TCP_VEGAS_ALPHA,
- .procname = "tcp_vegas_alpha",
- .data = &sysctl_tcp_vegas_alpha,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_TCP_VEGAS_BETA,
- .procname = "tcp_vegas_beta",
- .data = &sysctl_tcp_vegas_beta,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_TCP_VEGAS_GAMMA,
- .procname = "tcp_vegas_gamma",
- .data = &sysctl_tcp_vegas_gamma,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_TCP_BIC,
- .procname = "tcp_bic",
- .data = &sysctl_tcp_bic,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_TCP_BIC_FAST_CONVERGENCE,
- .procname = "tcp_bic_fast_convergence",
- .data = &sysctl_tcp_bic_fast_convergence,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .ctl_name = NET_TCP_BIC_LOW_WINDOW,
- .procname = "tcp_bic_low_window",
- .data = &sysctl_tcp_bic_low_window,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
.ctl_name = NET_TCP_MODERATE_RCVBUF,
.procname = "tcp_moderate_rcvbuf",
.data = &sysctl_tcp_moderate_rcvbuf,
@@ -683,13 +667,14 @@ ctl_table ipv4_table[] = {
.proc_handler = &proc_dointvec,
},
{
- .ctl_name = NET_TCP_BIC_BETA,
- .procname = "tcp_bic_beta",
- .data = &sysctl_tcp_bic_beta,
- .maxlen = sizeof(int),
+ .ctl_name = NET_TCP_CONG_CONTROL,
+ .procname = "tcp_congestion_control",
.mode = 0644,
- .proc_handler = &proc_dointvec,
+ .maxlen = TCP_CA_NAME_MAX,
+ .proc_handler = &proc_tcp_congestion_control,
+ .strategy = &sysctl_tcp_congestion_control,
},
+
{ .ctl_name = 0 }
};
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index a037bafcba3..882436da9a3 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -271,7 +271,6 @@ int sysctl_tcp_fin_timeout = TCP_FIN_TIMEOUT;
DEFINE_SNMP_STAT(struct tcp_mib, tcp_statistics);
-kmem_cache_t *tcp_openreq_cachep;
kmem_cache_t *tcp_bucket_cachep;
kmem_cache_t *tcp_timewait_cachep;
@@ -317,7 +316,7 @@ EXPORT_SYMBOL(tcp_enter_memory_pressure);
static __inline__ unsigned int tcp_listen_poll(struct sock *sk,
poll_table *wait)
{
- return tcp_sk(sk)->accept_queue ? (POLLIN | POLLRDNORM) : 0;
+ return !reqsk_queue_empty(&tcp_sk(sk)->accept_queue) ? (POLLIN | POLLRDNORM) : 0;
}
/*
@@ -463,28 +462,15 @@ int tcp_listen_start(struct sock *sk)
{
struct inet_sock *inet = inet_sk(sk);
struct tcp_sock *tp = tcp_sk(sk);
- struct tcp_listen_opt *lopt;
+ int rc = reqsk_queue_alloc(&tp->accept_queue, TCP_SYNQ_HSIZE);
+
+ if (rc != 0)
+ return rc;
sk->sk_max_ack_backlog = 0;
sk->sk_ack_backlog = 0;
- tp->accept_queue = tp->accept_queue_tail = NULL;
- rwlock_init(&tp->syn_wait_lock);
tcp_delack_init(tp);
- lopt = kmalloc(sizeof(struct tcp_listen_opt), GFP_KERNEL);
- if (!lopt)
- return -ENOMEM;
-
- memset(lopt, 0, sizeof(struct tcp_listen_opt));
- for (lopt->max_qlen_log = 6; ; lopt->max_qlen_log++)
- if ((1 << lopt->max_qlen_log) >= sysctl_max_syn_backlog)
- break;
- get_random_bytes(&lopt->hash_rnd, 4);
-
- write_lock_bh(&tp->syn_wait_lock);
- tp->listen_opt = lopt;
- write_unlock_bh(&tp->syn_wait_lock);
-
/* There is race window here: we announce ourselves listening,
* but this transition is still not validated by get_port().
* It is OK, because this socket enters to hash table only
@@ -501,10 +487,7 @@ int tcp_listen_start(struct sock *sk)
}
sk->sk_state = TCP_CLOSE;
- write_lock_bh(&tp->syn_wait_lock);
- tp->listen_opt = NULL;
- write_unlock_bh(&tp->syn_wait_lock);
- kfree(lopt);
+ reqsk_queue_destroy(&tp->accept_queue);
return -EADDRINUSE;
}
@@ -516,25 +499,23 @@ int tcp_listen_start(struct sock *sk)
static void tcp_listen_stop (struct sock *sk)
{
struct tcp_sock *tp = tcp_sk(sk);
- struct tcp_listen_opt *lopt = tp->listen_opt;
- struct open_request *acc_req = tp->accept_queue;
- struct open_request *req;
+ struct listen_sock *lopt;
+ struct request_sock *acc_req;
+ struct request_sock *req;
int i;
tcp_delete_keepalive_timer(sk);
/* make all the listen_opt local to us */
- write_lock_bh(&tp->syn_wait_lock);
- tp->listen_opt = NULL;
- write_unlock_bh(&tp->syn_wait_lock);
- tp->accept_queue = tp->accept_queue_tail = NULL;
+ lopt = reqsk_queue_yank_listen_sk(&tp->accept_queue);
+ acc_req = reqsk_queue_yank_acceptq(&tp->accept_queue);
if (lopt->qlen) {
for (i = 0; i < TCP_SYNQ_HSIZE; i++) {
while ((req = lopt->syn_table[i]) != NULL) {
lopt->syn_table[i] = req->dl_next;
lopt->qlen--;
- tcp_openreq_free(req);
+ reqsk_free(req);
/* Following specs, it would be better either to send FIN
* (and enter FIN-WAIT-1, it is normal close)
@@ -574,7 +555,7 @@ static void tcp_listen_stop (struct sock *sk)
sock_put(child);
sk_acceptq_removed(sk);
- tcp_openreq_fastfree(req);
+ __reqsk_free(req);
}
BUG_TRAP(!sk->sk_ack_backlog);
}
@@ -1345,7 +1326,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
cleanup_rbuf(sk, copied);
- if (tp->ucopy.task == user_recv) {
+ if (!sysctl_tcp_low_latency && tp->ucopy.task == user_recv) {
/* Install new reader */
if (!user_recv && !(flags & (MSG_TRUNC | MSG_PEEK))) {
user_recv = current;
@@ -1868,11 +1849,11 @@ static int wait_for_connect(struct sock *sk, long timeo)
prepare_to_wait_exclusive(sk->sk_sleep, &wait,
TASK_INTERRUPTIBLE);
release_sock(sk);
- if (!tp->accept_queue)
+ if (reqsk_queue_empty(&tp->accept_queue))
timeo = schedule_timeout(timeo);
lock_sock(sk);
err = 0;
- if (tp->accept_queue)
+ if (!reqsk_queue_empty(&tp->accept_queue))
break;
err = -EINVAL;
if (sk->sk_state != TCP_LISTEN)
@@ -1895,7 +1876,6 @@ static int wait_for_connect(struct sock *sk, long timeo)
struct sock *tcp_accept(struct sock *sk, int flags, int *err)
{
struct tcp_sock *tp = tcp_sk(sk);
- struct open_request *req;
struct sock *newsk;
int error;
@@ -1906,37 +1886,31 @@ struct sock *tcp_accept(struct sock *sk, int flags, int *err)
*/
error = -EINVAL;
if (sk->sk_state != TCP_LISTEN)
- goto out;
+ goto out_err;
/* Find already established connection */
- if (!tp->accept_queue) {
+ if (reqsk_queue_empty(&tp->accept_queue)) {
long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
/* If this is a non blocking socket don't sleep */
error = -EAGAIN;
if (!timeo)
- goto out;
+ goto out_err;
error = wait_for_connect(sk, timeo);
if (error)
- goto out;
+ goto out_err;
}
- req = tp->accept_queue;
- if ((tp->accept_queue = req->dl_next) == NULL)
- tp->accept_queue_tail = NULL;
-
- newsk = req->sk;
- sk_acceptq_removed(sk);
- tcp_openreq_fastfree(req);
+ newsk = reqsk_queue_get_child(&tp->accept_queue, sk);
BUG_TRAP(newsk->sk_state != TCP_SYN_RECV);
- release_sock(sk);
- return newsk;
-
out:
release_sock(sk);
+ return newsk;
+out_err:
+ newsk = NULL;
*err = error;
- return NULL;
+ goto out;
}
/*
@@ -1953,6 +1927,25 @@ int tcp_setsockopt(struct sock *sk, int level, int optname, char __user *optval,
return tp->af_specific->setsockopt(sk, level, optname,
optval, optlen);
+ /* This is a string value all the others are int's */
+ if (optname == TCP_CONGESTION) {
+ char name[TCP_CA_NAME_MAX];
+
+ if (optlen < 1)
+ return -EINVAL;
+
+ val = strncpy_from_user(name, optval,
+ min(TCP_CA_NAME_MAX-1, optlen));
+ if (val < 0)
+ return -EFAULT;
+ name[val] = 0;
+
+ lock_sock(sk);
+ err = tcp_set_congestion_control(tp, name);
+ release_sock(sk);
+ return err;
+ }
+
if (optlen < sizeof(int))
return -EINVAL;
@@ -2237,6 +2230,16 @@ int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
case TCP_QUICKACK:
val = !tp->ack.pingpong;
break;
+
+ case TCP_CONGESTION:
+ if (get_user(len, optlen))
+ return -EFAULT;
+ len = min_t(unsigned int, len, TCP_CA_NAME_MAX);
+ if (put_user(len, optlen))
+ return -EFAULT;
+ if (copy_to_user(optval, tp->ca_ops->name, len))
+ return -EFAULT;
+ return 0;
default:
return -ENOPROTOOPT;
};
@@ -2250,7 +2253,7 @@ int tcp_getsockopt(struct sock *sk, int level, int optname, char __user *optval,
extern void __skb_cb_too_small_for_tcp(int, int);
-extern void tcpdiag_init(void);
+extern struct tcp_congestion_ops tcp_reno;
static __initdata unsigned long thash_entries;
static int __init set_thash_entries(char *str)
@@ -2271,13 +2274,6 @@ void __init tcp_init(void)
__skb_cb_too_small_for_tcp(sizeof(struct tcp_skb_cb),
sizeof(skb->cb));
- tcp_openreq_cachep = kmem_cache_create("tcp_open_request",
- sizeof(struct open_request),
- 0, SLAB_HWCACHE_ALIGN,
- NULL, NULL);
- if (!tcp_openreq_cachep)
- panic("tcp_init: Cannot alloc open_request cache.");
-
tcp_bucket_cachep = kmem_cache_create("tcp_bind_bucket",
sizeof(struct tcp_bind_bucket),
0, SLAB_HWCACHE_ALIGN,
@@ -2338,7 +2334,7 @@ void __init tcp_init(void)
(tcp_bhash_size * sizeof(struct tcp_bind_hashbucket));
order++)
;
- if (order > 4) {
+ if (order >= 4) {
sysctl_local_port_range[0] = 32768;
sysctl_local_port_range[1] = 61000;
sysctl_tcp_max_tw_buckets = 180000;
@@ -2366,6 +2362,8 @@ void __init tcp_init(void)
printk(KERN_INFO "TCP: Hash tables configured "
"(established %d bind %d)\n",
tcp_ehash_size << 1, tcp_bhash_size);
+
+ tcp_register_congestion_control(&tcp_reno);
}
EXPORT_SYMBOL(tcp_accept);
@@ -2374,7 +2372,6 @@ EXPORT_SYMBOL(tcp_destroy_sock);
EXPORT_SYMBOL(tcp_disconnect);
EXPORT_SYMBOL(tcp_getsockopt);
EXPORT_SYMBOL(tcp_ioctl);
-EXPORT_SYMBOL(tcp_openreq_cachep);
EXPORT_SYMBOL(tcp_poll);
EXPORT_SYMBOL(tcp_read_sock);
EXPORT_SYMBOL(tcp_recvmsg);
diff --git a/net/ipv4/tcp_bic.c b/net/ipv4/tcp_bic.c
new file mode 100644
index 00000000000..ec38d45d664
--- /dev/null
+++ b/net/ipv4/tcp_bic.c
@@ -0,0 +1,331 @@
+/*
+ * Binary Increase Congestion control for TCP
+ *
+ * This is from the implementation of BICTCP in
+ * Lison-Xu, Kahaled Harfoush, and Injong Rhee.
+ * "Binary Increase Congestion Control for Fast, Long Distance
+ * Networks" in InfoComm 2004
+ * Available from:
+ * http://www.csc.ncsu.edu/faculty/rhee/export/bitcp.pdf
+ *
+ * Unless BIC is enabled and congestion window is large
+ * this behaves the same as the original Reno.
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <net/tcp.h>
+
+
+#define BICTCP_BETA_SCALE 1024 /* Scale factor beta calculation
+ * max_cwnd = snd_cwnd * beta
+ */
+#define BICTCP_B 4 /*
+ * In binary search,
+ * go to point (max+min)/N
+ */
+
+static int fast_convergence = 1;
+static int max_increment = 32;
+static int low_window = 14;
+static int beta = 819; /* = 819/1024 (BICTCP_BETA_SCALE) */
+static int low_utilization_threshold = 153;
+static int low_utilization_period = 2;
+static int initial_ssthresh = 100;
+static int smooth_part = 20;
+
+module_param(fast_convergence, int, 0644);
+MODULE_PARM_DESC(fast_convergence, "turn on/off fast convergence");
+module_param(max_increment, int, 0644);
+MODULE_PARM_DESC(max_increment, "Limit on increment allowed during binary search");
+module_param(low_window, int, 0644);
+MODULE_PARM_DESC(low_window, "lower bound on congestion window (for TCP friendliness)");
+module_param(beta, int, 0644);
+MODULE_PARM_DESC(beta, "beta for multiplicative increase");
+module_param(low_utilization_threshold, int, 0644);
+MODULE_PARM_DESC(low_utilization_threshold, "percent (scaled by 1024) for low utilization mode");
+module_param(low_utilization_period, int, 0644);
+MODULE_PARM_DESC(low_utilization_period, "if average delay exceeds then goto to low utilization mode (seconds)");
+module_param(initial_ssthresh, int, 0644);
+MODULE_PARM_DESC(initial_ssthresh, "initial value of slow start threshold");
+module_param(smooth_part, int, 0644);
+MODULE_PARM_DESC(smooth_part, "log(B/(B*Smin))/log(B/(B-1))+B, # of RTT from Wmax-B to Wmax");
+
+
+/* BIC TCP Parameters */
+struct bictcp {
+ u32 cnt; /* increase cwnd by 1 after ACKs */
+ u32 last_max_cwnd; /* last maximum snd_cwnd */
+ u32 loss_cwnd; /* congestion window at last loss */
+ u32 last_cwnd; /* the last snd_cwnd */
+ u32 last_time; /* time when updated last_cwnd */
+ u32 delay_min; /* min delay */
+ u32 delay_max; /* max delay */
+ u32 last_delay;
+ u8 low_utilization;/* 0: high; 1: low */
+ u32 low_utilization_start; /* starting time of low utilization detection*/
+ u32 epoch_start; /* beginning of an epoch */
+#define ACK_RATIO_SHIFT 4
+ u32 delayed_ack; /* estimate the ratio of Packets/ACKs << 4 */
+};
+
+static inline void bictcp_reset(struct bictcp *ca)
+{
+ ca->cnt = 0;
+ ca->last_max_cwnd = 0;
+ ca->loss_cwnd = 0;
+ ca->last_cwnd = 0;
+ ca->last_time = 0;
+ ca->delay_min = 0;
+ ca->delay_max = 0;
+ ca->last_delay = 0;
+ ca->low_utilization = 0;
+ ca->low_utilization_start = 0;
+ ca->epoch_start = 0;
+ ca->delayed_ack = 2 << ACK_RATIO_SHIFT;
+}
+
+static void bictcp_init(struct tcp_sock *tp)
+{
+ bictcp_reset(tcp_ca(tp));
+ if (initial_ssthresh)
+ tp->snd_ssthresh = initial_ssthresh;
+}
+
+/*
+ * Compute congestion window to use.
+ */
+static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
+{
+ if (ca->last_cwnd == cwnd &&
+ (s32)(tcp_time_stamp - ca->last_time) <= HZ / 32)
+ return;
+
+ ca->last_cwnd = cwnd;
+ ca->last_time = tcp_time_stamp;
+
+ if (ca->epoch_start == 0) /* record the beginning of an epoch */
+ ca->epoch_start = tcp_time_stamp;
+
+ /* start off normal */
+ if (cwnd <= low_window) {
+ ca->cnt = cwnd;
+ return;
+ }
+
+ /* binary increase */
+ if (cwnd < ca->last_max_cwnd) {
+ __u32 dist = (ca->last_max_cwnd - cwnd)
+ / BICTCP_B;
+
+ if (dist > max_increment)
+ /* linear increase */
+ ca->cnt = cwnd / max_increment;
+ else if (dist <= 1U)
+ /* binary search increase */
+ ca->cnt = (cwnd * smooth_part) / BICTCP_B;
+ else
+ /* binary search increase */
+ ca->cnt = cwnd / dist;
+ } else {
+ /* slow start AMD linear increase */
+ if (cwnd < ca->last_max_cwnd + BICTCP_B)
+ /* slow start */
+ ca->cnt = (cwnd * smooth_part) / BICTCP_B;
+ else if (cwnd < ca->last_max_cwnd + max_increment*(BICTCP_B-1))
+ /* slow start */
+ ca->cnt = (cwnd * (BICTCP_B-1))
+ / cwnd-ca->last_max_cwnd;
+ else
+ /* linear increase */
+ ca->cnt = cwnd / max_increment;
+ }
+
+ /* if in slow start or link utilization is very low */
+ if ( ca->loss_cwnd == 0 ||
+ (cwnd > ca->loss_cwnd && ca->low_utilization)) {
+ if (ca->cnt > 20) /* increase cwnd 5% per RTT */
+ ca->cnt = 20;
+ }
+
+ ca->cnt = (ca->cnt << ACK_RATIO_SHIFT) / ca->delayed_ack;
+ if (ca->cnt == 0) /* cannot be zero */
+ ca->cnt = 1;
+}
+
+
+/* Detect low utilization in congestion avoidance */
+static inline void bictcp_low_utilization(struct tcp_sock *tp, int flag)
+{
+ struct bictcp *ca = tcp_ca(tp);
+ u32 dist, delay;
+
+ /* No time stamp */
+ if (!(tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr) ||
+ /* Discard delay samples right after fast recovery */
+ tcp_time_stamp < ca->epoch_start + HZ ||
+ /* this delay samples may not be accurate */
+ flag == 0) {
+ ca->last_delay = 0;
+ goto notlow;
+ }
+
+ delay = ca->last_delay<<3; /* use the same scale as tp->srtt*/
+ ca->last_delay = tcp_time_stamp - tp->rx_opt.rcv_tsecr;
+ if (delay == 0) /* no previous delay sample */
+ goto notlow;
+
+ /* first time call or link delay decreases */
+ if (ca->delay_min == 0 || ca->delay_min > delay) {
+ ca->delay_min = ca->delay_max = delay;
+ goto notlow;
+ }
+
+ if (ca->delay_max < delay)
+ ca->delay_max = delay;
+
+ /* utilization is low, if avg delay < dist*threshold
+ for checking_period time */
+ dist = ca->delay_max - ca->delay_min;
+ if (dist <= ca->delay_min>>6 ||
+ tp->srtt - ca->delay_min >= (dist*low_utilization_threshold)>>10)
+ goto notlow;
+
+ if (ca->low_utilization_start == 0) {
+ ca->low_utilization = 0;
+ ca->low_utilization_start = tcp_time_stamp;
+ } else if ((s32)(tcp_time_stamp - ca->low_utilization_start)
+ > low_utilization_period*HZ) {
+ ca->low_utilization = 1;
+ }
+
+ return;
+
+ notlow:
+ ca->low_utilization = 0;
+ ca->low_utilization_start = 0;
+
+}
+
+static void bictcp_cong_avoid(struct tcp_sock *tp, u32 ack,
+ u32 seq_rtt, u32 in_flight, int data_acked)
+{
+ struct bictcp *ca = tcp_ca(tp);
+
+ bictcp_low_utilization(tp, data_acked);
+
+ if (in_flight < tp->snd_cwnd)
+ return;
+
+ if (tp->snd_cwnd <= tp->snd_ssthresh) {
+ /* In "safe" area, increase. */
+ if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+ tp->snd_cwnd++;
+ } else {
+ bictcp_update(ca, tp->snd_cwnd);
+
+ /* In dangerous area, increase slowly.
+ * In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd
+ */
+ if (tp->snd_cwnd_cnt >= ca->cnt) {
+ if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+ tp->snd_cwnd++;
+ tp->snd_cwnd_cnt = 0;
+ } else
+ tp->snd_cwnd_cnt++;
+ }
+
+}
+
+/*
+ * behave like Reno until low_window is reached,
+ * then increase congestion window slowly
+ */
+static u32 bictcp_recalc_ssthresh(struct tcp_sock *tp)
+{
+ struct bictcp *ca = tcp_ca(tp);
+
+ ca->epoch_start = 0; /* end of epoch */
+
+ /* in case of wrong delay_max*/
+ if (ca->delay_min > 0 && ca->delay_max > ca->delay_min)
+ ca->delay_max = ca->delay_min
+ + ((ca->delay_max - ca->delay_min)* 90) / 100;
+
+ /* Wmax and fast convergence */
+ if (tp->snd_cwnd < ca->last_max_cwnd && fast_convergence)
+ ca->last_max_cwnd = (tp->snd_cwnd * (BICTCP_BETA_SCALE + beta))
+ / (2 * BICTCP_BETA_SCALE);
+ else
+ ca->last_max_cwnd = tp->snd_cwnd;
+
+ ca->loss_cwnd = tp->snd_cwnd;
+
+
+ if (tp->snd_cwnd <= low_window)
+ return max(tp->snd_cwnd >> 1U, 2U);
+ else
+ return max((tp->snd_cwnd * beta) / BICTCP_BETA_SCALE, 2U);
+}
+
+static u32 bictcp_undo_cwnd(struct tcp_sock *tp)
+{
+ struct bictcp *ca = tcp_ca(tp);
+
+ return max(tp->snd_cwnd, ca->last_max_cwnd);
+}
+
+static u32 bictcp_min_cwnd(struct tcp_sock *tp)
+{
+ return tp->snd_ssthresh;
+}
+
+static void bictcp_state(struct tcp_sock *tp, u8 new_state)
+{
+ if (new_state == TCP_CA_Loss)
+ bictcp_reset(tcp_ca(tp));
+}
+
+/* Track delayed acknowledgement ratio using sliding window
+ * ratio = (15*ratio + sample) / 16
+ */
+static void bictcp_acked(struct tcp_sock *tp, u32 cnt)
+{
+ if (cnt > 0 && tp->ca_state == TCP_CA_Open) {
+ struct bictcp *ca = tcp_ca(tp);
+ cnt -= ca->delayed_ack >> ACK_RATIO_SHIFT;
+ ca->delayed_ack += cnt;
+ }
+}
+
+
+static struct tcp_congestion_ops bictcp = {
+ .init = bictcp_init,
+ .ssthresh = bictcp_recalc_ssthresh,
+ .cong_avoid = bictcp_cong_avoid,
+ .set_state = bictcp_state,
+ .undo_cwnd = bictcp_undo_cwnd,
+ .min_cwnd = bictcp_min_cwnd,
+ .pkts_acked = bictcp_acked,
+ .owner = THIS_MODULE,
+ .name = "bic",
+};
+
+static int __init bictcp_register(void)
+{
+ BUG_ON(sizeof(struct bictcp) > TCP_CA_PRIV_SIZE);
+ return tcp_register_congestion_control(&bictcp);
+}
+
+static void __exit bictcp_unregister(void)
+{
+ tcp_unregister_congestion_control(&bictcp);
+}
+
+module_init(bictcp_register);
+module_exit(bictcp_unregister);
+
+MODULE_AUTHOR("Stephen Hemminger");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("BIC TCP");
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
new file mode 100644
index 00000000000..4970d10a778
--- /dev/null
+++ b/net/ipv4/tcp_cong.c
@@ -0,0 +1,237 @@
+/*
+ * Plugable TCP congestion control support and newReno
+ * congestion control.
+ * Based on ideas from I/O scheduler suport and Web100.
+ *
+ * Copyright (C) 2005 Stephen Hemminger <shemminger@osdl.org>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <net/tcp.h>
+
+static DEFINE_SPINLOCK(tcp_cong_list_lock);
+static LIST_HEAD(tcp_cong_list);
+
+/* Simple linear search, don't expect many entries! */
+static struct tcp_congestion_ops *tcp_ca_find(const char *name)
+{
+ struct tcp_congestion_ops *e;
+
+ list_for_each_entry_rcu(e, &tcp_cong_list, list) {
+ if (strcmp(e->name, name) == 0)
+ return e;
+ }
+
+ return NULL;
+}
+
+/*
+ * Attach new congestion control algorthim to the list
+ * of available options.
+ */
+int tcp_register_congestion_control(struct tcp_congestion_ops *ca)
+{
+ int ret = 0;
+
+ /* all algorithms must implement ssthresh and cong_avoid ops */
+ if (!ca->ssthresh || !ca->cong_avoid || !ca->min_cwnd) {
+ printk(KERN_ERR "TCP %s does not implement required ops\n",
+ ca->name);
+ return -EINVAL;
+ }
+
+ spin_lock(&tcp_cong_list_lock);
+ if (tcp_ca_find(ca->name)) {
+ printk(KERN_NOTICE "TCP %s already registered\n", ca->name);
+ ret = -EEXIST;
+ } else {
+ list_add_rcu(&ca->list, &tcp_cong_list);
+ printk(KERN_INFO "TCP %s registered\n", ca->name);
+ }
+ spin_unlock(&tcp_cong_list_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(tcp_register_congestion_control);
+
+/*
+ * Remove congestion control algorithm, called from
+ * the module's remove function. Module ref counts are used
+ * to ensure that this can't be done till all sockets using
+ * that method are closed.
+ */
+void tcp_unregister_congestion_control(struct tcp_congestion_ops *ca)
+{
+ spin_lock(&tcp_cong_list_lock);
+ list_del_rcu(&ca->list);
+ spin_unlock(&tcp_cong_list_lock);
+}
+EXPORT_SYMBOL_GPL(tcp_unregister_congestion_control);
+
+/* Assign choice of congestion control. */
+void tcp_init_congestion_control(struct tcp_sock *tp)
+{
+ struct tcp_congestion_ops *ca;
+
+ if (tp->ca_ops != &tcp_init_congestion_ops)
+ return;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(ca, &tcp_cong_list, list) {
+ if (try_module_get(ca->owner)) {
+ tp->ca_ops = ca;
+ break;
+ }
+
+ }
+ rcu_read_unlock();
+
+ if (tp->ca_ops->init)
+ tp->ca_ops->init(tp);
+}
+
+/* Manage refcounts on socket close. */
+void tcp_cleanup_congestion_control(struct tcp_sock *tp)
+{
+ if (tp->ca_ops->release)
+ tp->ca_ops->release(tp);
+ module_put(tp->ca_ops->owner);
+}
+
+/* Used by sysctl to change default congestion control */
+int tcp_set_default_congestion_control(const char *name)
+{
+ struct tcp_congestion_ops *ca;
+ int ret = -ENOENT;
+
+ spin_lock(&tcp_cong_list_lock);
+ ca = tcp_ca_find(name);
+#ifdef CONFIG_KMOD
+ if (!ca) {
+ spin_unlock(&tcp_cong_list_lock);
+
+ request_module("tcp_%s", name);
+ spin_lock(&tcp_cong_list_lock);
+ ca = tcp_ca_find(name);
+ }
+#endif
+
+ if (ca) {
+ list_move(&ca->list, &tcp_cong_list);
+ ret = 0;
+ }
+ spin_unlock(&tcp_cong_list_lock);
+
+ return ret;
+}
+
+/* Get current default congestion control */
+void tcp_get_default_congestion_control(char *name)
+{
+ struct tcp_congestion_ops *ca;
+ /* We will always have reno... */
+ BUG_ON(list_empty(&tcp_cong_list));
+
+ rcu_read_lock();
+ ca = list_entry(tcp_cong_list.next, struct tcp_congestion_ops, list);
+ strncpy(name, ca->name, TCP_CA_NAME_MAX);
+ rcu_read_unlock();
+}
+
+/* Change congestion control for socket */
+int tcp_set_congestion_control(struct tcp_sock *tp, const char *name)
+{
+ struct tcp_congestion_ops *ca;
+ int err = 0;
+
+ rcu_read_lock();
+ ca = tcp_ca_find(name);
+ if (ca == tp->ca_ops)
+ goto out;
+
+ if (!ca)
+ err = -ENOENT;
+
+ else if (!try_module_get(ca->owner))
+ err = -EBUSY;
+
+ else {
+ tcp_cleanup_congestion_control(tp);
+ tp->ca_ops = ca;
+ if (tp->ca_ops->init)
+ tp->ca_ops->init(tp);
+ }
+ out:
+ rcu_read_unlock();
+ return err;
+}
+
+/*
+ * TCP Reno congestion control
+ * This is special case used for fallback as well.
+ */
+/* This is Jacobson's slow start and congestion avoidance.
+ * SIGCOMM '88, p. 328.
+ */
+void tcp_reno_cong_avoid(struct tcp_sock *tp, u32 ack, u32 rtt, u32 in_flight,
+ int flag)
+{
+ if (in_flight < tp->snd_cwnd)
+ return;
+
+ if (tp->snd_cwnd <= tp->snd_ssthresh) {
+ /* In "safe" area, increase. */
+ if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+ tp->snd_cwnd++;
+ } else {
+ /* In dangerous area, increase slowly.
+ * In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd
+ */
+ if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
+ if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+ tp->snd_cwnd++;
+ tp->snd_cwnd_cnt = 0;
+ } else
+ tp->snd_cwnd_cnt++;
+ }
+}
+EXPORT_SYMBOL_GPL(tcp_reno_cong_avoid);
+
+/* Slow start threshold is half the congestion window (min 2) */
+u32 tcp_reno_ssthresh(struct tcp_sock *tp)
+{
+ return max(tp->snd_cwnd >> 1U, 2U);
+}
+EXPORT_SYMBOL_GPL(tcp_reno_ssthresh);
+
+/* Lower bound on congestion window. */
+u32 tcp_reno_min_cwnd(struct tcp_sock *tp)
+{
+ return tp->snd_ssthresh/2;
+}
+EXPORT_SYMBOL_GPL(tcp_reno_min_cwnd);
+
+struct tcp_congestion_ops tcp_reno = {
+ .name = "reno",
+ .owner = THIS_MODULE,
+ .ssthresh = tcp_reno_ssthresh,
+ .cong_avoid = tcp_reno_cong_avoid,
+ .min_cwnd = tcp_reno_min_cwnd,
+};
+
+/* Initial congestion control used (until SYN)
+ * really reno under another name so we can tell difference
+ * during tcp_set_default_congestion_control
+ */
+struct tcp_congestion_ops tcp_init_congestion_ops = {
+ .name = "",
+ .owner = THIS_MODULE,
+ .ssthresh = tcp_reno_ssthresh,
+ .cong_avoid = tcp_reno_cong_avoid,
+ .min_cwnd = tcp_reno_min_cwnd,
+};
+EXPORT_SYMBOL_GPL(tcp_init_congestion_ops);
diff --git a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c
index 8faa8948f75..f66945cb158 100644
--- a/net/ipv4/tcp_diag.c
+++ b/net/ipv4/tcp_diag.c
@@ -42,15 +42,8 @@ struct tcpdiag_entry
static struct sock *tcpnl;
-
#define TCPDIAG_PUT(skb, attrtype, attrlen) \
-({ int rtalen = RTA_LENGTH(attrlen); \
- struct rtattr *rta; \
- if (skb_tailroom(skb) < RTA_ALIGN(rtalen)) goto nlmsg_failure; \
- rta = (void*)__skb_put(skb, RTA_ALIGN(rtalen)); \
- rta->rta_type = attrtype; \
- rta->rta_len = rtalen; \
- RTA_DATA(rta); })
+ RTA_DATA(__RTA_PUT(skb, attrtype, attrlen))
static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk,
int ext, u32 pid, u32 seq, u16 nlmsg_flags)
@@ -61,7 +54,6 @@ static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk,
struct nlmsghdr *nlh;
struct tcp_info *info = NULL;
struct tcpdiag_meminfo *minfo = NULL;
- struct tcpvegas_info *vinfo = NULL;
unsigned char *b = skb->tail;
nlh = NLMSG_PUT(skb, pid, seq, TCPDIAG_GETSOCK, sizeof(*r));
@@ -73,9 +65,11 @@ static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk,
if (ext & (1<<(TCPDIAG_INFO-1)))
info = TCPDIAG_PUT(skb, TCPDIAG_INFO, sizeof(*info));
- if ((tcp_is_westwood(tp) || tcp_is_vegas(tp))
- && (ext & (1<<(TCPDIAG_VEGASINFO-1))))
- vinfo = TCPDIAG_PUT(skb, TCPDIAG_VEGASINFO, sizeof(*vinfo));
+ if (ext & (1<<(TCPDIAG_CONG-1))) {
+ size_t len = strlen(tp->ca_ops->name);
+ strcpy(TCPDIAG_PUT(skb, TCPDIAG_CONG, len+1),
+ tp->ca_ops->name);
+ }
}
r->tcpdiag_family = sk->sk_family;
r->tcpdiag_state = sk->sk_state;
@@ -166,23 +160,13 @@ static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk,
if (info)
tcp_get_info(sk, info);
- if (vinfo) {
- if (tcp_is_vegas(tp)) {
- vinfo->tcpv_enabled = tp->vegas.doing_vegas_now;
- vinfo->tcpv_rttcnt = tp->vegas.cntRTT;
- vinfo->tcpv_rtt = jiffies_to_usecs(tp->vegas.baseRTT);
- vinfo->tcpv_minrtt = jiffies_to_usecs(tp->vegas.minRTT);
- } else {
- vinfo->tcpv_enabled = 0;
- vinfo->tcpv_rttcnt = 0;
- vinfo->tcpv_rtt = jiffies_to_usecs(tp->westwood.rtt);
- vinfo->tcpv_minrtt = jiffies_to_usecs(tp->westwood.rtt_min);
- }
- }
+ if (sk->sk_state < TCP_TIME_WAIT && tp->ca_ops->get_info)
+ tp->ca_ops->get_info(tp, ext, skb);
nlh->nlmsg_len = skb->tail - b;
return skb->len;
+rtattr_failure:
nlmsg_failure:
skb_trim(skb, b - skb->data);
return -1;
@@ -455,9 +439,10 @@ static int tcpdiag_dump_sock(struct sk_buff *skb, struct sock *sk,
}
static int tcpdiag_fill_req(struct sk_buff *skb, struct sock *sk,
- struct open_request *req,
+ struct request_sock *req,
u32 pid, u32 seq)
{
+ const struct inet_request_sock *ireq = inet_rsk(req);
struct inet_sock *inet = inet_sk(sk);
unsigned char *b = skb->tail;
struct tcpdiagmsg *r;
@@ -482,9 +467,9 @@ static int tcpdiag_fill_req(struct sk_buff *skb, struct sock *sk,
tmo = 0;
r->id.tcpdiag_sport = inet->sport;
- r->id.tcpdiag_dport = req->rmt_port;
- r->id.tcpdiag_src[0] = req->af.v4_req.loc_addr;
- r->id.tcpdiag_dst[0] = req->af.v4_req.rmt_addr;
+ r->id.tcpdiag_dport = ireq->rmt_port;
+ r->id.tcpdiag_src[0] = ireq->loc_addr;
+ r->id.tcpdiag_dst[0] = ireq->rmt_addr;
r->tcpdiag_expires = jiffies_to_msecs(tmo),
r->tcpdiag_rqueue = 0;
r->tcpdiag_wqueue = 0;
@@ -493,9 +478,9 @@ static int tcpdiag_fill_req(struct sk_buff *skb, struct sock *sk,
#ifdef CONFIG_IP_TCPDIAG_IPV6
if (r->tcpdiag_family == AF_INET6) {
ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_src,
- &req->af.v6_req.loc_addr);
+ &tcp6_rsk(req)->loc_addr);
ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_dst,
- &req->af.v6_req.rmt_addr);
+ &tcp6_rsk(req)->rmt_addr);
}
#endif
nlh->nlmsg_len = skb->tail - b;
@@ -513,7 +498,7 @@ static int tcpdiag_dump_reqs(struct sk_buff *skb, struct sock *sk,
struct tcpdiag_entry entry;
struct tcpdiagreq *r = NLMSG_DATA(cb->nlh);
struct tcp_sock *tp = tcp_sk(sk);
- struct tcp_listen_opt *lopt;
+ struct listen_sock *lopt;
struct rtattr *bc = NULL;
struct inet_sock *inet = inet_sk(sk);
int j, s_j;
@@ -528,9 +513,9 @@ static int tcpdiag_dump_reqs(struct sk_buff *skb, struct sock *sk,
entry.family = sk->sk_family;
- read_lock_bh(&tp->syn_wait_lock);
+ read_lock_bh(&tp->accept_queue.syn_wait_lock);
- lopt = tp->listen_opt;
+ lopt = tp->accept_queue.listen_opt;
if (!lopt || !lopt->qlen)
goto out;
@@ -541,13 +526,15 @@ static int tcpdiag_dump_reqs(struct sk_buff *skb, struct sock *sk,
}
for (j = s_j; j < TCP_SYNQ_HSIZE; j++) {
- struct open_request *req, *head = lopt->syn_table[j];
+ struct request_sock *req, *head = lopt->syn_table[j];
reqnum = 0;
for (req = head; req; reqnum++, req = req->dl_next) {
+ struct inet_request_sock *ireq = inet_rsk(req);
+
if (reqnum < s_reqnum)
continue;
- if (r->id.tcpdiag_dport != req->rmt_port &&
+ if (r->id.tcpdiag_dport != ireq->rmt_port &&
r->id.tcpdiag_dport)
continue;
@@ -555,16 +542,16 @@ static int tcpdiag_dump_reqs(struct sk_buff *skb, struct sock *sk,
entry.saddr =
#ifdef CONFIG_IP_TCPDIAG_IPV6
(entry.family == AF_INET6) ?
- req->af.v6_req.loc_addr.s6_addr32 :
+ tcp6_rsk(req)->loc_addr.s6_addr32 :
#endif
- &req->af.v4_req.loc_addr;
+ &ireq->loc_addr;
entry.daddr =
#ifdef CONFIG_IP_TCPDIAG_IPV6
(entry.family == AF_INET6) ?
- req->af.v6_req.rmt_addr.s6_addr32 :
+ tcp6_rsk(req)->rmt_addr.s6_addr32 :
#endif
- &req->af.v4_req.rmt_addr;
- entry.dport = ntohs(req->rmt_port);
+ &ireq->rmt_addr;
+ entry.dport = ntohs(ireq->rmt_port);
if (!tcpdiag_bc_run(RTA_DATA(bc),
RTA_PAYLOAD(bc), &entry))
@@ -585,7 +572,7 @@ static int tcpdiag_dump_reqs(struct sk_buff *skb, struct sock *sk,
}
out:
- read_unlock_bh(&tp->syn_wait_lock);
+ read_unlock_bh(&tp->accept_queue.syn_wait_lock);
return err;
}
diff --git a/net/ipv4/tcp_highspeed.c b/net/ipv4/tcp_highspeed.c
new file mode 100644
index 00000000000..36c51f8136b
--- /dev/null
+++ b/net/ipv4/tcp_highspeed.c
@@ -0,0 +1,181 @@
+/*
+ * Sally Floyd's High Speed TCP (RFC 3649) congestion control
+ *
+ * See http://www.icir.org/floyd/hstcp.html
+ *
+ * John Heffner <jheffner@psc.edu>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <net/tcp.h>
+
+
+/* From AIMD tables from RFC 3649 appendix B,
+ * with fixed-point MD scaled <<8.
+ */
+static const struct hstcp_aimd_val {
+ unsigned int cwnd;
+ unsigned int md;
+} hstcp_aimd_vals[] = {
+ { 38, 128, /* 0.50 */ },
+ { 118, 112, /* 0.44 */ },
+ { 221, 104, /* 0.41 */ },
+ { 347, 98, /* 0.38 */ },
+ { 495, 93, /* 0.37 */ },
+ { 663, 89, /* 0.35 */ },
+ { 851, 86, /* 0.34 */ },
+ { 1058, 83, /* 0.33 */ },
+ { 1284, 81, /* 0.32 */ },
+ { 1529, 78, /* 0.31 */ },
+ { 1793, 76, /* 0.30 */ },
+ { 2076, 74, /* 0.29 */ },
+ { 2378, 72, /* 0.28 */ },
+ { 2699, 71, /* 0.28 */ },
+ { 3039, 69, /* 0.27 */ },
+ { 3399, 68, /* 0.27 */ },
+ { 3778, 66, /* 0.26 */ },
+ { 4177, 65, /* 0.26 */ },
+ { 4596, 64, /* 0.25 */ },
+ { 5036, 62, /* 0.25 */ },
+ { 5497, 61, /* 0.24 */ },
+ { 5979, 60, /* 0.24 */ },
+ { 6483, 59, /* 0.23 */ },
+ { 7009, 58, /* 0.23 */ },
+ { 7558, 57, /* 0.22 */ },
+ { 8130, 56, /* 0.22 */ },
+ { 8726, 55, /* 0.22 */ },
+ { 9346, 54, /* 0.21 */ },
+ { 9991, 53, /* 0.21 */ },
+ { 10661, 52, /* 0.21 */ },
+ { 11358, 52, /* 0.20 */ },
+ { 12082, 51, /* 0.20 */ },
+ { 12834, 50, /* 0.20 */ },
+ { 13614, 49, /* 0.19 */ },
+ { 14424, 48, /* 0.19 */ },
+ { 15265, 48, /* 0.19 */ },
+ { 16137, 47, /* 0.19 */ },
+ { 17042, 46, /* 0.18 */ },
+ { 17981, 45, /* 0.18 */ },
+ { 18955, 45, /* 0.18 */ },
+ { 19965, 44, /* 0.17 */ },
+ { 21013, 43, /* 0.17 */ },
+ { 22101, 43, /* 0.17 */ },
+ { 23230, 42, /* 0.17 */ },
+ { 24402, 41, /* 0.16 */ },
+ { 25618, 41, /* 0.16 */ },
+ { 26881, 40, /* 0.16 */ },
+ { 28193, 39, /* 0.16 */ },
+ { 29557, 39, /* 0.15 */ },
+ { 30975, 38, /* 0.15 */ },
+ { 32450, 38, /* 0.15 */ },
+ { 33986, 37, /* 0.15 */ },
+ { 35586, 36, /* 0.14 */ },
+ { 37253, 36, /* 0.14 */ },
+ { 38992, 35, /* 0.14 */ },
+ { 40808, 35, /* 0.14 */ },
+ { 42707, 34, /* 0.13 */ },
+ { 44694, 33, /* 0.13 */ },
+ { 46776, 33, /* 0.13 */ },
+ { 48961, 32, /* 0.13 */ },
+ { 51258, 32, /* 0.13 */ },
+ { 53677, 31, /* 0.12 */ },
+ { 56230, 30, /* 0.12 */ },
+ { 58932, 30, /* 0.12 */ },
+ { 61799, 29, /* 0.12 */ },
+ { 64851, 28, /* 0.11 */ },
+ { 68113, 28, /* 0.11 */ },
+ { 71617, 27, /* 0.11 */ },
+ { 75401, 26, /* 0.10 */ },
+ { 79517, 26, /* 0.10 */ },
+ { 84035, 25, /* 0.10 */ },
+ { 89053, 24, /* 0.10 */ },
+};
+
+#define HSTCP_AIMD_MAX ARRAY_SIZE(hstcp_aimd_vals)
+
+struct hstcp {
+ u32 ai;
+};
+
+static void hstcp_init(struct tcp_sock *tp)
+{
+ struct hstcp *ca = tcp_ca(tp);
+
+ ca->ai = 0;
+
+ /* Ensure the MD arithmetic works. This is somewhat pedantic,
+ * since I don't think we will see a cwnd this large. :) */
+ tp->snd_cwnd_clamp = min_t(u32, tp->snd_cwnd_clamp, 0xffffffff/128);
+}
+
+static void hstcp_cong_avoid(struct tcp_sock *tp, u32 adk, u32 rtt,
+ u32 in_flight, int good)
+{
+ struct hstcp *ca = tcp_ca(tp);
+
+ if (in_flight < tp->snd_cwnd)
+ return;
+
+ if (tp->snd_cwnd <= tp->snd_ssthresh) {
+ if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+ tp->snd_cwnd++;
+ } else {
+ /* Update AIMD parameters */
+ if (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd) {
+ while (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd &&
+ ca->ai < HSTCP_AIMD_MAX)
+ ca->ai++;
+ } else if (tp->snd_cwnd < hstcp_aimd_vals[ca->ai].cwnd) {
+ while (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd &&
+ ca->ai > 0)
+ ca->ai--;
+ }
+
+ /* Do additive increase */
+ if (tp->snd_cwnd < tp->snd_cwnd_clamp) {
+ tp->snd_cwnd_cnt += ca->ai;
+ if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
+ tp->snd_cwnd++;
+ tp->snd_cwnd_cnt -= tp->snd_cwnd;
+ }
+ }
+ }
+}
+
+static u32 hstcp_ssthresh(struct tcp_sock *tp)
+{
+ struct hstcp *ca = tcp_ca(tp);
+
+ /* Do multiplicative decrease */
+ return max(tp->snd_cwnd - ((tp->snd_cwnd * hstcp_aimd_vals[ca->ai].md) >> 8), 2U);
+}
+
+
+static struct tcp_congestion_ops tcp_highspeed = {
+ .init = hstcp_init,
+ .ssthresh = hstcp_ssthresh,
+ .cong_avoid = hstcp_cong_avoid,
+ .min_cwnd = tcp_reno_min_cwnd,
+
+ .owner = THIS_MODULE,
+ .name = "highspeed"
+};
+
+static int __init hstcp_register(void)
+{
+ BUG_ON(sizeof(struct hstcp) > TCP_CA_PRIV_SIZE);
+ return tcp_register_congestion_control(&tcp_highspeed);
+}
+
+static void __exit hstcp_unregister(void)
+{
+ tcp_unregister_congestion_control(&tcp_highspeed);
+}
+
+module_init(hstcp_register);
+module_exit(hstcp_unregister);
+
+MODULE_AUTHOR("John Heffner");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("High Speed TCP");
diff --git a/net/ipv4/tcp_htcp.c b/net/ipv4/tcp_htcp.c
new file mode 100644
index 00000000000..40168275acf
--- /dev/null
+++ b/net/ipv4/tcp_htcp.c
@@ -0,0 +1,289 @@
+/*
+ * H-TCP congestion control. The algorithm is detailed in:
+ * R.N.Shorten, D.J.Leith:
+ * "H-TCP: TCP for high-speed and long-distance networks"
+ * Proc. PFLDnet, Argonne, 2004.
+ * http://www.hamilton.ie/net/htcp3.pdf
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <net/tcp.h>
+
+#define ALPHA_BASE (1<<7) /* 1.0 with shift << 7 */
+#define BETA_MIN (1<<6) /* 0.5 with shift << 7 */
+#define BETA_MAX 102 /* 0.8 with shift << 7 */
+
+static int use_rtt_scaling = 1;
+module_param(use_rtt_scaling, int, 0644);
+MODULE_PARM_DESC(use_rtt_scaling, "turn on/off RTT scaling");
+
+static int use_bandwidth_switch = 1;
+module_param(use_bandwidth_switch, int, 0644);
+MODULE_PARM_DESC(use_bandwidth_switch, "turn on/off bandwidth switcher");
+
+struct htcp {
+ u16 alpha; /* Fixed point arith, << 7 */
+ u8 beta; /* Fixed point arith, << 7 */
+ u8 modeswitch; /* Delay modeswitch until we had at least one congestion event */
+ u8 ccount; /* Number of RTTs since last congestion event */
+ u8 undo_ccount;
+ u16 packetcount;
+ u32 minRTT;
+ u32 maxRTT;
+ u32 snd_cwnd_cnt2;
+
+ u32 undo_maxRTT;
+ u32 undo_old_maxB;
+
+ /* Bandwidth estimation */
+ u32 minB;
+ u32 maxB;
+ u32 old_maxB;
+ u32 Bi;
+ u32 lasttime;
+};
+
+static inline void htcp_reset(struct htcp *ca)
+{
+ ca->undo_ccount = ca->ccount;
+ ca->undo_maxRTT = ca->maxRTT;
+ ca->undo_old_maxB = ca->old_maxB;
+
+ ca->ccount = 0;
+ ca->snd_cwnd_cnt2 = 0;
+}
+
+static u32 htcp_cwnd_undo(struct tcp_sock *tp)
+{
+ struct htcp *ca = tcp_ca(tp);
+ ca->ccount = ca->undo_ccount;
+ ca->maxRTT = ca->undo_maxRTT;
+ ca->old_maxB = ca->undo_old_maxB;
+ return max(tp->snd_cwnd, (tp->snd_ssthresh<<7)/ca->beta);
+}
+
+static inline void measure_rtt(struct tcp_sock *tp)
+{
+ struct htcp *ca = tcp_ca(tp);
+ u32 srtt = tp->srtt>>3;
+
+ /* keep track of minimum RTT seen so far, minRTT is zero at first */
+ if (ca->minRTT > srtt || !ca->minRTT)
+ ca->minRTT = srtt;
+
+ /* max RTT */
+ if (tp->ca_state == TCP_CA_Open && tp->snd_ssthresh < 0xFFFF && ca->ccount > 3) {
+ if (ca->maxRTT < ca->minRTT)
+ ca->maxRTT = ca->minRTT;
+ if (ca->maxRTT < srtt && srtt <= ca->maxRTT+HZ/50)
+ ca->maxRTT = srtt;
+ }
+}
+
+static void measure_achieved_throughput(struct tcp_sock *tp, u32 pkts_acked)
+{
+ struct htcp *ca = tcp_ca(tp);
+ u32 now = tcp_time_stamp;
+
+ /* achieved throughput calculations */
+ if (tp->ca_state != TCP_CA_Open && tp->ca_state != TCP_CA_Disorder) {
+ ca->packetcount = 0;
+ ca->lasttime = now;
+ return;
+ }
+
+ ca->packetcount += pkts_acked;
+
+ if (ca->packetcount >= tp->snd_cwnd - (ca->alpha>>7? : 1)
+ && now - ca->lasttime >= ca->minRTT
+ && ca->minRTT > 0) {
+ __u32 cur_Bi = ca->packetcount*HZ/(now - ca->lasttime);
+ if (ca->ccount <= 3) {
+ /* just after backoff */
+ ca->minB = ca->maxB = ca->Bi = cur_Bi;
+ } else {
+ ca->Bi = (3*ca->Bi + cur_Bi)/4;
+ if (ca->Bi > ca->maxB)
+ ca->maxB = ca->Bi;
+ if (ca->minB > ca->maxB)
+ ca->minB = ca->maxB;
+ }
+ ca->packetcount = 0;
+ ca->lasttime = now;
+ }
+}
+
+static inline void htcp_beta_update(struct htcp *ca, u32 minRTT, u32 maxRTT)
+{
+ if (use_bandwidth_switch) {
+ u32 maxB = ca->maxB;
+ u32 old_maxB = ca->old_maxB;
+ ca->old_maxB = ca->maxB;
+
+ if (!between(5*maxB, 4*old_maxB, 6*old_maxB)) {
+ ca->beta = BETA_MIN;
+ ca->modeswitch = 0;
+ return;
+ }
+ }
+
+ if (ca->modeswitch && minRTT > max(HZ/100, 1) && maxRTT) {
+ ca->beta = (minRTT<<7)/maxRTT;
+ if (ca->beta < BETA_MIN)
+ ca->beta = BETA_MIN;
+ else if (ca->beta > BETA_MAX)
+ ca->beta = BETA_MAX;
+ } else {
+ ca->beta = BETA_MIN;
+ ca->modeswitch = 1;
+ }
+}
+
+static inline void htcp_alpha_update(struct htcp *ca)
+{
+ u32 minRTT = ca->minRTT;
+ u32 factor = 1;
+ u32 diff = ca->ccount * minRTT; /* time since last backoff */
+
+ if (diff > HZ) {
+ diff -= HZ;
+ factor = 1+ ( 10*diff + ((diff/2)*(diff/2)/HZ) )/HZ;
+ }
+
+ if (use_rtt_scaling && minRTT) {
+ u32 scale = (HZ<<3)/(10*minRTT);
+ scale = min(max(scale, 1U<<2), 10U<<3); /* clamping ratio to interval [0.5,10]<<3 */
+ factor = (factor<<3)/scale;
+ if (!factor)
+ factor = 1;
+ }
+
+ ca->alpha = 2*factor*((1<<7)-ca->beta);
+ if (!ca->alpha)
+ ca->alpha = ALPHA_BASE;
+}
+
+/* After we have the rtt data to calculate beta, we'd still prefer to wait one
+ * rtt before we adjust our beta to ensure we are working from a consistent
+ * data.
+ *
+ * This function should be called when we hit a congestion event since only at
+ * that point do we really have a real sense of maxRTT (the queues en route
+ * were getting just too full now).
+ */
+static void htcp_param_update(struct tcp_sock *tp)
+{
+ struct htcp *ca = tcp_ca(tp);
+ u32 minRTT = ca->minRTT;
+ u32 maxRTT = ca->maxRTT;
+
+ htcp_beta_update(ca, minRTT, maxRTT);
+ htcp_alpha_update(ca);
+
+ /* add slowly fading memory for maxRTT to accommodate routing changes etc */
+ if (minRTT > 0 && maxRTT > minRTT)
+ ca->maxRTT = minRTT + ((maxRTT-minRTT)*95)/100;
+}
+
+static u32 htcp_recalc_ssthresh(struct tcp_sock *tp)
+{
+ struct htcp *ca = tcp_ca(tp);
+ htcp_param_update(tp);
+ return max((tp->snd_cwnd * ca->beta) >> 7, 2U);
+}
+
+static void htcp_cong_avoid(struct tcp_sock *tp, u32 ack, u32 rtt,
+ u32 in_flight, int data_acked)
+{
+ struct htcp *ca = tcp_ca(tp);
+
+ if (in_flight < tp->snd_cwnd)
+ return;
+
+ if (tp->snd_cwnd <= tp->snd_ssthresh) {
+ /* In "safe" area, increase. */
+ if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+ tp->snd_cwnd++;
+ } else {
+ measure_rtt(tp);
+
+ /* keep track of number of round-trip times since last backoff event */
+ if (ca->snd_cwnd_cnt2++ > tp->snd_cwnd) {
+ ca->ccount++;
+ ca->snd_cwnd_cnt2 = 0;
+ htcp_alpha_update(ca);
+ }
+
+ /* In dangerous area, increase slowly.
+ * In theory this is tp->snd_cwnd += alpha / tp->snd_cwnd
+ */
+ if ((tp->snd_cwnd_cnt++ * ca->alpha)>>7 >= tp->snd_cwnd) {
+ if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+ tp->snd_cwnd++;
+ tp->snd_cwnd_cnt = 0;
+ ca->ccount++;
+ }
+ }
+}
+
+/* Lower bound on congestion window. */
+static u32 htcp_min_cwnd(struct tcp_sock *tp)
+{
+ return tp->snd_ssthresh;
+}
+
+
+static void htcp_init(struct tcp_sock *tp)
+{
+ struct htcp *ca = tcp_ca(tp);
+
+ memset(ca, 0, sizeof(struct htcp));
+ ca->alpha = ALPHA_BASE;
+ ca->beta = BETA_MIN;
+}
+
+static void htcp_state(struct tcp_sock *tp, u8 new_state)
+{
+ switch (new_state) {
+ case TCP_CA_CWR:
+ case TCP_CA_Recovery:
+ case TCP_CA_Loss:
+ htcp_reset(tcp_ca(tp));
+ break;
+ }
+}
+
+static struct tcp_congestion_ops htcp = {
+ .init = htcp_init,
+ .ssthresh = htcp_recalc_ssthresh,
+ .min_cwnd = htcp_min_cwnd,
+ .cong_avoid = htcp_cong_avoid,
+ .set_state = htcp_state,
+ .undo_cwnd = htcp_cwnd_undo,
+ .pkts_acked = measure_achieved_throughput,
+ .owner = THIS_MODULE,
+ .name = "htcp",
+};
+
+static int __init htcp_register(void)
+{
+ BUG_ON(sizeof(struct htcp) > TCP_CA_PRIV_SIZE);
+ BUILD_BUG_ON(BETA_MIN >= BETA_MAX);
+ if (!use_bandwidth_switch)
+ htcp.pkts_acked = NULL;
+ return tcp_register_congestion_control(&htcp);
+}
+
+static void __exit htcp_unregister(void)
+{
+ tcp_unregister_congestion_control(&htcp);
+}
+
+module_init(htcp_register);
+module_exit(htcp_unregister);
+
+MODULE_AUTHOR("Baruch Even");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("H-TCP");
diff --git a/net/ipv4/tcp_hybla.c b/net/ipv4/tcp_hybla.c
new file mode 100644
index 00000000000..13a66342c30
--- /dev/null
+++ b/net/ipv4/tcp_hybla.c
@@ -0,0 +1,187 @@
+/*
+ * TCP HYBLA
+ *
+ * TCP-HYBLA Congestion control algorithm, based on:
+ * C.Caini, R.Firrincieli, "TCP-Hybla: A TCP Enhancement
+ * for Heterogeneous Networks",
+ * International Journal on satellite Communications,
+ * September 2004
+ * Daniele Lacamera
+ * root at danielinux.net
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <net/tcp.h>
+
+/* Tcp Hybla structure. */
+struct hybla {
+ u8 hybla_en;
+ u32 snd_cwnd_cents; /* Keeps increment values when it is <1, <<7 */
+ u32 rho; /* Rho parameter, integer part */
+ u32 rho2; /* Rho * Rho, integer part */
+ u32 rho_3ls; /* Rho parameter, <<3 */
+ u32 rho2_7ls; /* Rho^2, <<7 */
+ u32 minrtt; /* Minimum smoothed round trip time value seen */
+};
+
+/* Hybla reference round trip time (default= 1/40 sec = 25 ms),
+ expressed in jiffies */
+static int rtt0 = 25;
+module_param(rtt0, int, 0644);
+MODULE_PARM_DESC(rtt0, "reference rout trip time (ms)");
+
+
+/* This is called to refresh values for hybla parameters */
+static inline void hybla_recalc_param (struct tcp_sock *tp)
+{
+ struct hybla *ca = tcp_ca(tp);
+
+ ca->rho_3ls = max_t(u32, tp->srtt / msecs_to_jiffies(rtt0), 8);
+ ca->rho = ca->rho_3ls >> 3;
+ ca->rho2_7ls = (ca->rho_3ls * ca->rho_3ls) << 1;
+ ca->rho2 = ca->rho2_7ls >>7;
+}
+
+static void hybla_init(struct tcp_sock *tp)
+{
+ struct hybla *ca = tcp_ca(tp);
+
+ ca->rho = 0;
+ ca->rho2 = 0;
+ ca->rho_3ls = 0;
+ ca->rho2_7ls = 0;
+ ca->snd_cwnd_cents = 0;
+ ca->hybla_en = 1;
+ tp->snd_cwnd = 2;
+ tp->snd_cwnd_clamp = 65535;
+
+ /* 1st Rho measurement based on initial srtt */
+ hybla_recalc_param(tp);
+
+ /* set minimum rtt as this is the 1st ever seen */
+ ca->minrtt = tp->srtt;
+ tp->snd_cwnd = ca->rho;
+}
+
+static void hybla_state(struct tcp_sock *tp, u8 ca_state)
+{
+ struct hybla *ca = tcp_ca(tp);
+
+ ca->hybla_en = (ca_state == TCP_CA_Open);
+}
+
+static inline u32 hybla_fraction(u32 odds)
+{
+ static const u32 fractions[] = {
+ 128, 139, 152, 165, 181, 197, 215, 234,
+ };
+
+ return (odds < ARRAY_SIZE(fractions)) ? fractions[odds] : 128;
+}
+
+/* TCP Hybla main routine.
+ * This is the algorithm behavior:
+ * o Recalc Hybla parameters if min_rtt has changed
+ * o Give cwnd a new value based on the model proposed
+ * o remember increments <1
+ */
+static void hybla_cong_avoid(struct tcp_sock *tp, u32 ack, u32 rtt,
+ u32 in_flight, int flag)
+{
+ struct hybla *ca = tcp_ca(tp);
+ u32 increment, odd, rho_fractions;
+ int is_slowstart = 0;
+
+ /* Recalculate rho only if this srtt is the lowest */
+ if (tp->srtt < ca->minrtt){
+ hybla_recalc_param(tp);
+ ca->minrtt = tp->srtt;
+ }
+
+ if (!ca->hybla_en)
+ return tcp_reno_cong_avoid(tp, ack, rtt, in_flight, flag);
+
+ if (in_flight < tp->snd_cwnd)
+ return;
+
+ if (ca->rho == 0)
+ hybla_recalc_param(tp);
+
+ rho_fractions = ca->rho_3ls - (ca->rho << 3);
+
+ if (tp->snd_cwnd < tp->snd_ssthresh) {
+ /*
+ * slow start
+ * INC = 2^RHO - 1
+ * This is done by splitting the rho parameter
+ * into 2 parts: an integer part and a fraction part.
+ * Inrement<<7 is estimated by doing:
+ * [2^(int+fract)]<<7
+ * that is equal to:
+ * (2^int) * [(2^fract) <<7]
+ * 2^int is straightly computed as 1<<int,
+ * while we will use hybla_slowstart_fraction_increment() to
+ * calculate 2^fract in a <<7 value.
+ */
+ is_slowstart = 1;
+ increment = ((1 << ca->rho) * hybla_fraction(rho_fractions))
+ - 128;
+ } else {
+ /*
+ * congestion avoidance
+ * INC = RHO^2 / W
+ * as long as increment is estimated as (rho<<7)/window
+ * it already is <<7 and we can easily count its fractions.
+ */
+ increment = ca->rho2_7ls / tp->snd_cwnd;
+ if (increment < 128)
+ tp->snd_cwnd_cnt++;
+ }
+
+ odd = increment % 128;
+ tp->snd_cwnd += increment >> 7;
+ ca->snd_cwnd_cents += odd;
+
+ /* check when fractions goes >=128 and increase cwnd by 1. */
+ while(ca->snd_cwnd_cents >= 128) {
+ tp->snd_cwnd++;
+ ca->snd_cwnd_cents -= 128;
+ tp->snd_cwnd_cnt = 0;
+ }
+
+ /* clamp down slowstart cwnd to ssthresh value. */
+ if (is_slowstart)
+ tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh);
+
+ tp->snd_cwnd = min_t(u32, tp->snd_cwnd, tp->snd_cwnd_clamp);
+}
+
+static struct tcp_congestion_ops tcp_hybla = {
+ .init = hybla_init,
+ .ssthresh = tcp_reno_ssthresh,
+ .min_cwnd = tcp_reno_min_cwnd,
+ .cong_avoid = hybla_cong_avoid,
+ .set_state = hybla_state,
+
+ .owner = THIS_MODULE,
+ .name = "hybla"
+};
+
+static int __init hybla_register(void)
+{
+ BUG_ON(sizeof(struct hybla) > TCP_CA_PRIV_SIZE);
+ return tcp_register_congestion_control(&tcp_hybla);
+}
+
+static void __exit hybla_unregister(void)
+{
+ tcp_unregister_congestion_control(&tcp_hybla);
+}
+
+module_init(hybla_register);
+module_exit(hybla_unregister);
+
+MODULE_AUTHOR("Daniele Lacamera");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TCP Hybla");
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 79835a67a27..7bbbbc33eb4 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -61,7 +61,6 @@
* Panu Kuhlberg: Experimental audit of TCP (re)transmission
* engine. Lots of bugs are found.
* Pasi Sarolahti: F-RTO for dealing with spurious RTOs
- * Angelo Dell'Aera: TCP Westwood+ support
*/
#include <linux/config.h>
@@ -88,23 +87,9 @@ int sysctl_tcp_rfc1337;
int sysctl_tcp_max_orphans = NR_FILE;
int sysctl_tcp_frto;
int sysctl_tcp_nometrics_save;
-int sysctl_tcp_westwood;
-int sysctl_tcp_vegas_cong_avoid;
int sysctl_tcp_moderate_rcvbuf = 1;
-/* Default values of the Vegas variables, in fixed-point representation
- * with V_PARAM_SHIFT bits to the right of the binary point.
- */
-#define V_PARAM_SHIFT 1
-int sysctl_tcp_vegas_alpha = 1<<V_PARAM_SHIFT;
-int sysctl_tcp_vegas_beta = 3<<V_PARAM_SHIFT;
-int sysctl_tcp_vegas_gamma = 1<<V_PARAM_SHIFT;
-int sysctl_tcp_bic = 1;
-int sysctl_tcp_bic_fast_convergence = 1;
-int sysctl_tcp_bic_low_window = 14;
-int sysctl_tcp_bic_beta = 819; /* = 819/1024 (BICTCP_BETA_SCALE) */
-
#define FLAG_DATA 0x01 /* Incoming frame contained data. */
#define FLAG_WIN_UPDATE 0x02 /* Incoming ACK was a window update. */
#define FLAG_DATA_ACKED 0x04 /* This ACK acknowledged new data. */
@@ -333,15 +318,6 @@ static void tcp_init_buffer_space(struct sock *sk)
tp->snd_cwnd_stamp = tcp_time_stamp;
}
-static void init_bictcp(struct tcp_sock *tp)
-{
- tp->bictcp.cnt = 0;
-
- tp->bictcp.last_max_cwnd = 0;
- tp->bictcp.last_cwnd = 0;
- tp->bictcp.last_stamp = 0;
-}
-
/* 5. Recalculate window clamp after socket hit its memory bounds. */
static void tcp_clamp_window(struct sock *sk, struct tcp_sock *tp)
{
@@ -558,45 +534,6 @@ static void tcp_event_data_recv(struct sock *sk, struct tcp_sock *tp, struct sk_
tcp_grow_window(sk, tp, skb);
}
-/* When starting a new connection, pin down the current choice of
- * congestion algorithm.
- */
-void tcp_ca_init(struct tcp_sock *tp)
-{
- if (sysctl_tcp_westwood)
- tp->adv_cong = TCP_WESTWOOD;
- else if (sysctl_tcp_bic)
- tp->adv_cong = TCP_BIC;
- else if (sysctl_tcp_vegas_cong_avoid) {
- tp->adv_cong = TCP_VEGAS;
- tp->vegas.baseRTT = 0x7fffffff;
- tcp_vegas_enable(tp);
- }
-}
-
-/* Do RTT sampling needed for Vegas.
- * Basically we:
- * o min-filter RTT samples from within an RTT to get the current
- * propagation delay + queuing delay (we are min-filtering to try to
- * avoid the effects of delayed ACKs)
- * o min-filter RTT samples from a much longer window (forever for now)
- * to find the propagation delay (baseRTT)
- */
-static inline void vegas_rtt_calc(struct tcp_sock *tp, __u32 rtt)
-{
- __u32 vrtt = rtt + 1; /* Never allow zero rtt or baseRTT */
-
- /* Filter to find propagation delay: */
- if (vrtt < tp->vegas.baseRTT)
- tp->vegas.baseRTT = vrtt;
-
- /* Find the min RTT during the last RTT to find
- * the current prop. delay + queuing delay:
- */
- tp->vegas.minRTT = min(tp->vegas.minRTT, vrtt);
- tp->vegas.cntRTT++;
-}
-
/* Called to compute a smoothed rtt estimate. The data fed to this
* routine either comes from timestamps, or from segments that were
* known _not_ to have been retransmitted [see Karn/Partridge
@@ -606,13 +543,10 @@ static inline void vegas_rtt_calc(struct tcp_sock *tp, __u32 rtt)
* To save cycles in the RFC 1323 implementation it was better to break
* it up into three procedures. -- erics
*/
-static void tcp_rtt_estimator(struct tcp_sock *tp, __u32 mrtt)
+static void tcp_rtt_estimator(struct tcp_sock *tp, __u32 mrtt, u32 *usrtt)
{
long m = mrtt; /* RTT */
- if (tcp_vegas_enabled(tp))
- vegas_rtt_calc(tp, mrtt);
-
/* The following amusing code comes from Jacobson's
* article in SIGCOMM '88. Note that rtt and mdev
* are scaled versions of rtt and mean deviation.
@@ -670,7 +604,8 @@ static void tcp_rtt_estimator(struct tcp_sock *tp, __u32 mrtt)
tp->rtt_seq = tp->snd_nxt;
}
- tcp_westwood_update_rtt(tp, tp->srtt >> 3);
+ if (tp->ca_ops->rtt_sample)
+ tp->ca_ops->rtt_sample(tp, *usrtt);
}
/* Calculate rto without backoff. This is the second half of Van Jacobson's
@@ -1185,8 +1120,8 @@ void tcp_enter_frto(struct sock *sk)
tp->snd_una == tp->high_seq ||
(tp->ca_state == TCP_CA_Loss && !tp->retransmits)) {
tp->prior_ssthresh = tcp_current_ssthresh(tp);
- if (!tcp_westwood_ssthresh(tp))
- tp->snd_ssthresh = tcp_recalc_ssthresh(tp);
+ tp->snd_ssthresh = tp->ca_ops->ssthresh(tp);
+ tcp_ca_event(tp, CA_EVENT_FRTO);
}
/* Have to clear retransmission markers here to keep the bookkeeping
@@ -1252,8 +1187,6 @@ static void tcp_enter_frto_loss(struct sock *sk)
tcp_set_ca_state(tp, TCP_CA_Loss);
tp->high_seq = tp->frto_highmark;
TCP_ECN_queue_cwr(tp);
-
- init_bictcp(tp);
}
void tcp_clear_retrans(struct tcp_sock *tp)
@@ -1283,7 +1216,8 @@ void tcp_enter_loss(struct sock *sk, int how)
if (tp->ca_state <= TCP_CA_Disorder || tp->snd_una == tp->high_seq ||
(tp->ca_state == TCP_CA_Loss && !tp->retransmits)) {
tp->prior_ssthresh = tcp_current_ssthresh(tp);
- tp->snd_ssthresh = tcp_recalc_ssthresh(tp);
+ tp->snd_ssthresh = tp->ca_ops->ssthresh(tp);
+ tcp_ca_event(tp, CA_EVENT_LOSS);
}
tp->snd_cwnd = 1;
tp->snd_cwnd_cnt = 0;
@@ -1596,28 +1530,14 @@ static inline void tcp_moderate_cwnd(struct tcp_sock *tp)
}
/* Decrease cwnd each second ack. */
-
static void tcp_cwnd_down(struct tcp_sock *tp)
{
int decr = tp->snd_cwnd_cnt + 1;
- __u32 limit;
-
- /*
- * TCP Westwood
- * Here limit is evaluated as BWestimation*RTTmin (for obtaining it
- * in packets we use mss_cache). If sysctl_tcp_westwood is off
- * tcp_westwood_bw_rttmin() returns 0. In such case snd_ssthresh is
- * still used as usual. It prevents other strange cases in which
- * BWE*RTTmin could assume value 0. It should not happen but...
- */
-
- if (!(limit = tcp_westwood_bw_rttmin(tp)))
- limit = tp->snd_ssthresh/2;
tp->snd_cwnd_cnt = decr&1;
decr >>= 1;
- if (decr && tp->snd_cwnd > limit)
+ if (decr && tp->snd_cwnd > tp->ca_ops->min_cwnd(tp))
tp->snd_cwnd -= decr;
tp->snd_cwnd = min(tp->snd_cwnd, tcp_packets_in_flight(tp)+1);
@@ -1654,8 +1574,8 @@ static void DBGUNDO(struct sock *sk, struct tcp_sock *tp, const char *msg)
static void tcp_undo_cwr(struct tcp_sock *tp, int undo)
{
if (tp->prior_ssthresh) {
- if (tcp_is_bic(tp))
- tp->snd_cwnd = max(tp->snd_cwnd, tp->bictcp.last_max_cwnd);
+ if (tp->ca_ops->undo_cwnd)
+ tp->snd_cwnd = tp->ca_ops->undo_cwnd(tp);
else
tp->snd_cwnd = max(tp->snd_cwnd, tp->snd_ssthresh<<1);
@@ -1767,11 +1687,9 @@ static int tcp_try_undo_loss(struct sock *sk, struct tcp_sock *tp)
static inline void tcp_complete_cwr(struct tcp_sock *tp)
{
- if (tcp_westwood_cwnd(tp))
- tp->snd_ssthresh = tp->snd_cwnd;
- else
- tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh);
+ tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh);
tp->snd_cwnd_stamp = tcp_time_stamp;
+ tcp_ca_event(tp, CA_EVENT_COMPLETE_CWR);
}
static void tcp_try_to_open(struct sock *sk, struct tcp_sock *tp, int flag)
@@ -1946,7 +1864,7 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
if (tp->ca_state < TCP_CA_CWR) {
if (!(flag&FLAG_ECE))
tp->prior_ssthresh = tcp_current_ssthresh(tp);
- tp->snd_ssthresh = tcp_recalc_ssthresh(tp);
+ tp->snd_ssthresh = tp->ca_ops->ssthresh(tp);
TCP_ECN_queue_cwr(tp);
}
@@ -1963,7 +1881,7 @@ tcp_fastretrans_alert(struct sock *sk, u32 prior_snd_una,
/* Read draft-ietf-tcplw-high-performance before mucking
* with this code. (Superceeds RFC1323)
*/
-static void tcp_ack_saw_tstamp(struct tcp_sock *tp, int flag)
+static void tcp_ack_saw_tstamp(struct tcp_sock *tp, u32 *usrtt, int flag)
{
__u32 seq_rtt;
@@ -1983,13 +1901,13 @@ static void tcp_ack_saw_tstamp(struct tcp_sock *tp, int flag)
* in window is lost... Voila. --ANK (010210)
*/
seq_rtt = tcp_time_stamp - tp->rx_opt.rcv_tsecr;
- tcp_rtt_estimator(tp, seq_rtt);
+ tcp_rtt_estimator(tp, seq_rtt, usrtt);
tcp_set_rto(tp);
tp->backoff = 0;
tcp_bound_rto(tp);
}
-static void tcp_ack_no_tstamp(struct tcp_sock *tp, u32 seq_rtt, int flag)
+static void tcp_ack_no_tstamp(struct tcp_sock *tp, u32 seq_rtt, u32 *usrtt, int flag)
{
/* We don't have a timestamp. Can only use
* packets that are not retransmitted to determine
@@ -2003,338 +1921,29 @@ static void tcp_ack_no_tstamp(struct tcp_sock *tp, u32 seq_rtt, int flag)
if (flag & FLAG_RETRANS_DATA_ACKED)
return;
- tcp_rtt_estimator(tp, seq_rtt);
+ tcp_rtt_estimator(tp, seq_rtt, usrtt);
tcp_set_rto(tp);
tp->backoff = 0;
tcp_bound_rto(tp);
}
static inline void tcp_ack_update_rtt(struct tcp_sock *tp,
- int flag, s32 seq_rtt)
+ int flag, s32 seq_rtt, u32 *usrtt)
{
/* Note that peer MAY send zero echo. In this case it is ignored. (rfc1323) */
if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr)
- tcp_ack_saw_tstamp(tp, flag);
+ tcp_ack_saw_tstamp(tp, usrtt, flag);
else if (seq_rtt >= 0)
- tcp_ack_no_tstamp(tp, seq_rtt, flag);
-}
-
-/*
- * Compute congestion window to use.
- *
- * This is from the implementation of BICTCP in
- * Lison-Xu, Kahaled Harfoush, and Injog Rhee.
- * "Binary Increase Congestion Control for Fast, Long Distance
- * Networks" in InfoComm 2004
- * Available from:
- * http://www.csc.ncsu.edu/faculty/rhee/export/bitcp.pdf
- *
- * Unless BIC is enabled and congestion window is large
- * this behaves the same as the original Reno.
- */
-static inline __u32 bictcp_cwnd(struct tcp_sock *tp)
-{
- /* orignal Reno behaviour */
- if (!tcp_is_bic(tp))
- return tp->snd_cwnd;
-
- if (tp->bictcp.last_cwnd == tp->snd_cwnd &&
- (s32)(tcp_time_stamp - tp->bictcp.last_stamp) <= (HZ>>5))
- return tp->bictcp.cnt;
-
- tp->bictcp.last_cwnd = tp->snd_cwnd;
- tp->bictcp.last_stamp = tcp_time_stamp;
-
- /* start off normal */
- if (tp->snd_cwnd <= sysctl_tcp_bic_low_window)
- tp->bictcp.cnt = tp->snd_cwnd;
-
- /* binary increase */
- else if (tp->snd_cwnd < tp->bictcp.last_max_cwnd) {
- __u32 dist = (tp->bictcp.last_max_cwnd - tp->snd_cwnd)
- / BICTCP_B;
-
- if (dist > BICTCP_MAX_INCREMENT)
- /* linear increase */
- tp->bictcp.cnt = tp->snd_cwnd / BICTCP_MAX_INCREMENT;
- else if (dist <= 1U)
- /* binary search increase */
- tp->bictcp.cnt = tp->snd_cwnd * BICTCP_FUNC_OF_MIN_INCR
- / BICTCP_B;
- else
- /* binary search increase */
- tp->bictcp.cnt = tp->snd_cwnd / dist;
- } else {
- /* slow start amd linear increase */
- if (tp->snd_cwnd < tp->bictcp.last_max_cwnd + BICTCP_B)
- /* slow start */
- tp->bictcp.cnt = tp->snd_cwnd * BICTCP_FUNC_OF_MIN_INCR
- / BICTCP_B;
- else if (tp->snd_cwnd < tp->bictcp.last_max_cwnd
- + BICTCP_MAX_INCREMENT*(BICTCP_B-1))
- /* slow start */
- tp->bictcp.cnt = tp->snd_cwnd * (BICTCP_B-1)
- / (tp->snd_cwnd-tp->bictcp.last_max_cwnd);
- else
- /* linear increase */
- tp->bictcp.cnt = tp->snd_cwnd / BICTCP_MAX_INCREMENT;
- }
- return tp->bictcp.cnt;
+ tcp_ack_no_tstamp(tp, seq_rtt, usrtt, flag);
}
-/* This is Jacobson's slow start and congestion avoidance.
- * SIGCOMM '88, p. 328.
- */
-static inline void reno_cong_avoid(struct tcp_sock *tp)
+static inline void tcp_cong_avoid(struct tcp_sock *tp, u32 ack, u32 rtt,
+ u32 in_flight, int good)
{
- if (tp->snd_cwnd <= tp->snd_ssthresh) {
- /* In "safe" area, increase. */
- if (tp->snd_cwnd < tp->snd_cwnd_clamp)
- tp->snd_cwnd++;
- } else {
- /* In dangerous area, increase slowly.
- * In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd
- */
- if (tp->snd_cwnd_cnt >= bictcp_cwnd(tp)) {
- if (tp->snd_cwnd < tp->snd_cwnd_clamp)
- tp->snd_cwnd++;
- tp->snd_cwnd_cnt=0;
- } else
- tp->snd_cwnd_cnt++;
- }
- tp->snd_cwnd_stamp = tcp_time_stamp;
-}
-
-/* This is based on the congestion detection/avoidance scheme described in
- * Lawrence S. Brakmo and Larry L. Peterson.
- * "TCP Vegas: End to end congestion avoidance on a global internet."
- * IEEE Journal on Selected Areas in Communication, 13(8):1465--1480,
- * October 1995. Available from:
- * ftp://ftp.cs.arizona.edu/xkernel/Papers/jsac.ps
- *
- * See http://www.cs.arizona.edu/xkernel/ for their implementation.
- * The main aspects that distinguish this implementation from the
- * Arizona Vegas implementation are:
- * o We do not change the loss detection or recovery mechanisms of
- * Linux in any way. Linux already recovers from losses quite well,
- * using fine-grained timers, NewReno, and FACK.
- * o To avoid the performance penalty imposed by increasing cwnd
- * only every-other RTT during slow start, we increase during
- * every RTT during slow start, just like Reno.
- * o Largely to allow continuous cwnd growth during slow start,
- * we use the rate at which ACKs come back as the "actual"
- * rate, rather than the rate at which data is sent.
- * o To speed convergence to the right rate, we set the cwnd
- * to achieve the right ("actual") rate when we exit slow start.
- * o To filter out the noise caused by delayed ACKs, we use the
- * minimum RTT sample observed during the last RTT to calculate
- * the actual rate.
- * o When the sender re-starts from idle, it waits until it has
- * received ACKs for an entire flight of new data before making
- * a cwnd adjustment decision. The original Vegas implementation
- * assumed senders never went idle.
- */
-static void vegas_cong_avoid(struct tcp_sock *tp, u32 ack, u32 seq_rtt)
-{
- /* The key players are v_beg_snd_una and v_beg_snd_nxt.
- *
- * These are so named because they represent the approximate values
- * of snd_una and snd_nxt at the beginning of the current RTT. More
- * precisely, they represent the amount of data sent during the RTT.
- * At the end of the RTT, when we receive an ACK for v_beg_snd_nxt,
- * we will calculate that (v_beg_snd_nxt - v_beg_snd_una) outstanding
- * bytes of data have been ACKed during the course of the RTT, giving
- * an "actual" rate of:
- *
- * (v_beg_snd_nxt - v_beg_snd_una) / (rtt duration)
- *
- * Unfortunately, v_beg_snd_una is not exactly equal to snd_una,
- * because delayed ACKs can cover more than one segment, so they
- * don't line up nicely with the boundaries of RTTs.
- *
- * Another unfortunate fact of life is that delayed ACKs delay the
- * advance of the left edge of our send window, so that the number
- * of bytes we send in an RTT is often less than our cwnd will allow.
- * So we keep track of our cwnd separately, in v_beg_snd_cwnd.
- */
-
- if (after(ack, tp->vegas.beg_snd_nxt)) {
- /* Do the Vegas once-per-RTT cwnd adjustment. */
- u32 old_wnd, old_snd_cwnd;
-
-
- /* Here old_wnd is essentially the window of data that was
- * sent during the previous RTT, and has all
- * been acknowledged in the course of the RTT that ended
- * with the ACK we just received. Likewise, old_snd_cwnd
- * is the cwnd during the previous RTT.
- */
- old_wnd = (tp->vegas.beg_snd_nxt - tp->vegas.beg_snd_una) /
- tp->mss_cache_std;
- old_snd_cwnd = tp->vegas.beg_snd_cwnd;
-
- /* Save the extent of the current window so we can use this
- * at the end of the next RTT.
- */
- tp->vegas.beg_snd_una = tp->vegas.beg_snd_nxt;
- tp->vegas.beg_snd_nxt = tp->snd_nxt;
- tp->vegas.beg_snd_cwnd = tp->snd_cwnd;
-
- /* Take into account the current RTT sample too, to
- * decrease the impact of delayed acks. This double counts
- * this sample since we count it for the next window as well,
- * but that's not too awful, since we're taking the min,
- * rather than averaging.
- */
- vegas_rtt_calc(tp, seq_rtt);
-
- /* We do the Vegas calculations only if we got enough RTT
- * samples that we can be reasonably sure that we got
- * at least one RTT sample that wasn't from a delayed ACK.
- * If we only had 2 samples total,
- * then that means we're getting only 1 ACK per RTT, which
- * means they're almost certainly delayed ACKs.
- * If we have 3 samples, we should be OK.
- */
-
- if (tp->vegas.cntRTT <= 2) {
- /* We don't have enough RTT samples to do the Vegas
- * calculation, so we'll behave like Reno.
- */
- if (tp->snd_cwnd > tp->snd_ssthresh)
- tp->snd_cwnd++;
- } else {
- u32 rtt, target_cwnd, diff;
-
- /* We have enough RTT samples, so, using the Vegas
- * algorithm, we determine if we should increase or
- * decrease cwnd, and by how much.
- */
-
- /* Pluck out the RTT we are using for the Vegas
- * calculations. This is the min RTT seen during the
- * last RTT. Taking the min filters out the effects
- * of delayed ACKs, at the cost of noticing congestion
- * a bit later.
- */
- rtt = tp->vegas.minRTT;
-
- /* Calculate the cwnd we should have, if we weren't
- * going too fast.
- *
- * This is:
- * (actual rate in segments) * baseRTT
- * We keep it as a fixed point number with
- * V_PARAM_SHIFT bits to the right of the binary point.
- */
- target_cwnd = ((old_wnd * tp->vegas.baseRTT)
- << V_PARAM_SHIFT) / rtt;
-
- /* Calculate the difference between the window we had,
- * and the window we would like to have. This quantity
- * is the "Diff" from the Arizona Vegas papers.
- *
- * Again, this is a fixed point number with
- * V_PARAM_SHIFT bits to the right of the binary
- * point.
- */
- diff = (old_wnd << V_PARAM_SHIFT) - target_cwnd;
-
- if (tp->snd_cwnd < tp->snd_ssthresh) {
- /* Slow start. */
- if (diff > sysctl_tcp_vegas_gamma) {
- /* Going too fast. Time to slow down
- * and switch to congestion avoidance.
- */
- tp->snd_ssthresh = 2;
-
- /* Set cwnd to match the actual rate
- * exactly:
- * cwnd = (actual rate) * baseRTT
- * Then we add 1 because the integer
- * truncation robs us of full link
- * utilization.
- */
- tp->snd_cwnd = min(tp->snd_cwnd,
- (target_cwnd >>
- V_PARAM_SHIFT)+1);
-
- }
- } else {
- /* Congestion avoidance. */
- u32 next_snd_cwnd;
-
- /* Figure out where we would like cwnd
- * to be.
- */
- if (diff > sysctl_tcp_vegas_beta) {
- /* The old window was too fast, so
- * we slow down.
- */
- next_snd_cwnd = old_snd_cwnd - 1;
- } else if (diff < sysctl_tcp_vegas_alpha) {
- /* We don't have enough extra packets
- * in the network, so speed up.
- */
- next_snd_cwnd = old_snd_cwnd + 1;
- } else {
- /* Sending just as fast as we
- * should be.
- */
- next_snd_cwnd = old_snd_cwnd;
- }
-
- /* Adjust cwnd upward or downward, toward the
- * desired value.
- */
- if (next_snd_cwnd > tp->snd_cwnd)
- tp->snd_cwnd++;
- else if (next_snd_cwnd < tp->snd_cwnd)
- tp->snd_cwnd--;
- }
- }
-
- /* Wipe the slate clean for the next RTT. */
- tp->vegas.cntRTT = 0;
- tp->vegas.minRTT = 0x7fffffff;
- }
-
- /* The following code is executed for every ack we receive,
- * except for conditions checked in should_advance_cwnd()
- * before the call to tcp_cong_avoid(). Mainly this means that
- * we only execute this code if the ack actually acked some
- * data.
- */
-
- /* If we are in slow start, increase our cwnd in response to this ACK.
- * (If we are not in slow start then we are in congestion avoidance,
- * and adjust our congestion window only once per RTT. See the code
- * above.)
- */
- if (tp->snd_cwnd <= tp->snd_ssthresh)
- tp->snd_cwnd++;
-
- /* to keep cwnd from growing without bound */
- tp->snd_cwnd = min_t(u32, tp->snd_cwnd, tp->snd_cwnd_clamp);
-
- /* Make sure that we are never so timid as to reduce our cwnd below
- * 2 MSS.
- *
- * Going below 2 MSS would risk huge delayed ACKs from our receiver.
- */
- tp->snd_cwnd = max(tp->snd_cwnd, 2U);
-
+ tp->ca_ops->cong_avoid(tp, ack, rtt, in_flight, good);
tp->snd_cwnd_stamp = tcp_time_stamp;
}
-static inline void tcp_cong_avoid(struct tcp_sock *tp, u32 ack, u32 seq_rtt)
-{
- if (tcp_vegas_enabled(tp))
- vegas_cong_avoid(tp, ack, seq_rtt);
- else
- reno_cong_avoid(tp);
-}
-
/* Restart timer after forward progress on connection.
* RFC2988 recommends to restart timer to now+rto.
*/
@@ -2415,13 +2024,18 @@ static int tcp_tso_acked(struct sock *sk, struct sk_buff *skb,
/* Remove acknowledged frames from the retransmission queue. */
-static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
+static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p, s32 *seq_usrtt)
{
struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *skb;
__u32 now = tcp_time_stamp;
int acked = 0;
__s32 seq_rtt = -1;
+ struct timeval usnow;
+ u32 pkts_acked = 0;
+
+ if (seq_usrtt)
+ do_gettimeofday(&usnow);
while ((skb = skb_peek(&sk->sk_write_queue)) &&
skb != sk->sk_send_head) {
@@ -2448,6 +2062,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
*/
if (!(scb->flags & TCPCB_FLAG_SYN)) {
acked |= FLAG_DATA_ACKED;
+ ++pkts_acked;
} else {
acked |= FLAG_SYN_ACKED;
tp->retrans_stamp = 0;
@@ -2461,6 +2076,10 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
seq_rtt = -1;
} else if (seq_rtt < 0)
seq_rtt = now - scb->when;
+ if (seq_usrtt)
+ *seq_usrtt = (usnow.tv_sec - skb->stamp.tv_sec) * 1000000
+ + (usnow.tv_usec - skb->stamp.tv_usec);
+
if (sacked & TCPCB_SACKED_ACKED)
tp->sacked_out -= tcp_skb_pcount(skb);
if (sacked & TCPCB_LOST)
@@ -2479,8 +2098,11 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
}
if (acked&FLAG_ACKED) {
- tcp_ack_update_rtt(tp, acked, seq_rtt);
+ tcp_ack_update_rtt(tp, acked, seq_rtt, seq_usrtt);
tcp_ack_packets_out(sk, tp);
+
+ if (tp->ca_ops->pkts_acked)
+ tp->ca_ops->pkts_acked(tp, pkts_acked);
}
#if FASTRETRANS_DEBUG > 0
@@ -2624,257 +2246,6 @@ static void tcp_process_frto(struct sock *sk, u32 prior_snd_una)
tp->frto_counter = (tp->frto_counter + 1) % 3;
}
-/*
- * TCP Westwood+
- */
-
-/*
- * @init_westwood
- * This function initializes fields used in TCP Westwood+. We can't
- * get no information about RTTmin at this time so we simply set it to
- * TCP_WESTWOOD_INIT_RTT. This value was chosen to be too conservative
- * since in this way we're sure it will be updated in a consistent
- * way as soon as possible. It will reasonably happen within the first
- * RTT period of the connection lifetime.
- */
-
-static void init_westwood(struct sock *sk)
-{
- struct tcp_sock *tp = tcp_sk(sk);
-
- tp->westwood.bw_ns_est = 0;
- tp->westwood.bw_est = 0;
- tp->westwood.accounted = 0;
- tp->westwood.cumul_ack = 0;
- tp->westwood.rtt_win_sx = tcp_time_stamp;
- tp->westwood.rtt = TCP_WESTWOOD_INIT_RTT;
- tp->westwood.rtt_min = TCP_WESTWOOD_INIT_RTT;
- tp->westwood.snd_una = tp->snd_una;
-}
-
-/*
- * @westwood_do_filter
- * Low-pass filter. Implemented using constant coeffients.
- */
-
-static inline __u32 westwood_do_filter(__u32 a, __u32 b)
-{
- return (((7 * a) + b) >> 3);
-}
-
-static void westwood_filter(struct sock *sk, __u32 delta)
-{
- struct tcp_sock *tp = tcp_sk(sk);
-
- tp->westwood.bw_ns_est =
- westwood_do_filter(tp->westwood.bw_ns_est,
- tp->westwood.bk / delta);
- tp->westwood.bw_est =
- westwood_do_filter(tp->westwood.bw_est,
- tp->westwood.bw_ns_est);
-}
-
-/*
- * @westwood_update_rttmin
- * It is used to update RTTmin. In this case we MUST NOT use
- * WESTWOOD_RTT_MIN minimum bound since we could be on a LAN!
- */
-
-static inline __u32 westwood_update_rttmin(const struct sock *sk)
-{
- const struct tcp_sock *tp = tcp_sk(sk);
- __u32 rttmin = tp->westwood.rtt_min;
-
- if (tp->westwood.rtt != 0 &&
- (tp->westwood.rtt < tp->westwood.rtt_min || !rttmin))
- rttmin = tp->westwood.rtt;
-
- return rttmin;
-}
-
-/*
- * @westwood_acked
- * Evaluate increases for dk.
- */
-
-static inline __u32 westwood_acked(const struct sock *sk)
-{
- const struct tcp_sock *tp = tcp_sk(sk);
-
- return tp->snd_una - tp->westwood.snd_una;
-}
-
-/*
- * @westwood_new_window
- * It evaluates if we are receiving data inside the same RTT window as
- * when we started.
- * Return value:
- * It returns 0 if we are still evaluating samples in the same RTT
- * window, 1 if the sample has to be considered in the next window.
- */
-
-static int westwood_new_window(const struct sock *sk)
-{
- const struct tcp_sock *tp = tcp_sk(sk);
- __u32 left_bound;
- __u32 rtt;
- int ret = 0;
-
- left_bound = tp->westwood.rtt_win_sx;
- rtt = max(tp->westwood.rtt, (u32) TCP_WESTWOOD_RTT_MIN);
-
- /*
- * A RTT-window has passed. Be careful since if RTT is less than
- * 50ms we don't filter but we continue 'building the sample'.
- * This minimum limit was choosen since an estimation on small
- * time intervals is better to avoid...
- * Obvioulsy on a LAN we reasonably will always have
- * right_bound = left_bound + WESTWOOD_RTT_MIN
- */
-
- if ((left_bound + rtt) < tcp_time_stamp)
- ret = 1;
-
- return ret;
-}
-
-/*
- * @westwood_update_window
- * It updates RTT evaluation window if it is the right moment to do
- * it. If so it calls filter for evaluating bandwidth.
- */
-
-static void __westwood_update_window(struct sock *sk, __u32 now)
-{
- struct tcp_sock *tp = tcp_sk(sk);
- __u32 delta = now - tp->westwood.rtt_win_sx;
-
- if (delta) {
- if (tp->westwood.rtt)
- westwood_filter(sk, delta);
-
- tp->westwood.bk = 0;
- tp->westwood.rtt_win_sx = tcp_time_stamp;
- }
-}
-
-
-static void westwood_update_window(struct sock *sk, __u32 now)
-{
- if (westwood_new_window(sk))
- __westwood_update_window(sk, now);
-}
-
-/*
- * @__tcp_westwood_fast_bw
- * It is called when we are in fast path. In particular it is called when
- * header prediction is successfull. In such case infact update is
- * straight forward and doesn't need any particular care.
- */
-
-static void __tcp_westwood_fast_bw(struct sock *sk, struct sk_buff *skb)
-{
- struct tcp_sock *tp = tcp_sk(sk);
-
- westwood_update_window(sk, tcp_time_stamp);
-
- tp->westwood.bk += westwood_acked(sk);
- tp->westwood.snd_una = tp->snd_una;
- tp->westwood.rtt_min = westwood_update_rttmin(sk);
-}
-
-static inline void tcp_westwood_fast_bw(struct sock *sk, struct sk_buff *skb)
-{
- if (tcp_is_westwood(tcp_sk(sk)))
- __tcp_westwood_fast_bw(sk, skb);
-}
-
-
-/*
- * @westwood_dupack_update
- * It updates accounted and cumul_ack when receiving a dupack.
- */
-
-static void westwood_dupack_update(struct sock *sk)
-{
- struct tcp_sock *tp = tcp_sk(sk);
-
- tp->westwood.accounted += tp->mss_cache_std;
- tp->westwood.cumul_ack = tp->mss_cache_std;
-}
-
-static inline int westwood_may_change_cumul(struct tcp_sock *tp)
-{
- return (tp->westwood.cumul_ack > tp->mss_cache_std);
-}
-
-static inline void westwood_partial_update(struct tcp_sock *tp)
-{
- tp->westwood.accounted -= tp->westwood.cumul_ack;
- tp->westwood.cumul_ack = tp->mss_cache_std;
-}
-
-static inline void westwood_complete_update(struct tcp_sock *tp)
-{
- tp->westwood.cumul_ack -= tp->westwood.accounted;
- tp->westwood.accounted = 0;
-}
-
-/*
- * @westwood_acked_count
- * This function evaluates cumul_ack for evaluating dk in case of
- * delayed or partial acks.
- */
-
-static inline __u32 westwood_acked_count(struct sock *sk)
-{
- struct tcp_sock *tp = tcp_sk(sk);
-
- tp->westwood.cumul_ack = westwood_acked(sk);
-
- /* If cumul_ack is 0 this is a dupack since it's not moving
- * tp->snd_una.
- */
- if (!(tp->westwood.cumul_ack))
- westwood_dupack_update(sk);
-
- if (westwood_may_change_cumul(tp)) {
- /* Partial or delayed ack */
- if (tp->westwood.accounted >= tp->westwood.cumul_ack)
- westwood_partial_update(tp);
- else
- westwood_complete_update(tp);
- }
-
- tp->westwood.snd_una = tp->snd_una;
-
- return tp->westwood.cumul_ack;
-}
-
-
-/*
- * @__tcp_westwood_slow_bw
- * It is called when something is going wrong..even if there could
- * be no problems! Infact a simple delayed packet may trigger a
- * dupack. But we need to be careful in such case.
- */
-
-static void __tcp_westwood_slow_bw(struct sock *sk, struct sk_buff *skb)
-{
- struct tcp_sock *tp = tcp_sk(sk);
-
- westwood_update_window(sk, tcp_time_stamp);
-
- tp->westwood.bk += westwood_acked_count(sk);
- tp->westwood.rtt_min = westwood_update_rttmin(sk);
-}
-
-static inline void tcp_westwood_slow_bw(struct sock *sk, struct sk_buff *skb)
-{
- if (tcp_is_westwood(tcp_sk(sk)))
- __tcp_westwood_slow_bw(sk, skb);
-}
-
/* This routine deals with incoming acks, but not outgoing ones. */
static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
{
@@ -2884,6 +2255,7 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
u32 ack = TCP_SKB_CB(skb)->ack_seq;
u32 prior_in_flight;
s32 seq_rtt;
+ s32 seq_usrtt = 0;
int prior_packets;
/* If the ack is newer than sent or older than previous acks
@@ -2902,9 +2274,10 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
*/
tcp_update_wl(tp, ack, ack_seq);
tp->snd_una = ack;
- tcp_westwood_fast_bw(sk, skb);
flag |= FLAG_WIN_UPDATE;
+ tcp_ca_event(tp, CA_EVENT_FAST_ACK);
+
NET_INC_STATS_BH(LINUX_MIB_TCPHPACKS);
} else {
if (ack_seq != TCP_SKB_CB(skb)->end_seq)
@@ -2920,7 +2293,7 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
if (TCP_ECN_rcv_ecn_echo(tp, skb->h.th))
flag |= FLAG_ECE;
- tcp_westwood_slow_bw(sk,skb);
+ tcp_ca_event(tp, CA_EVENT_SLOW_ACK);
}
/* We passed data and got it acked, remove any soft error
@@ -2935,22 +2308,20 @@ static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
prior_in_flight = tcp_packets_in_flight(tp);
/* See if we can take anything off of the retransmit queue. */
- flag |= tcp_clean_rtx_queue(sk, &seq_rtt);
+ flag |= tcp_clean_rtx_queue(sk, &seq_rtt,
+ tp->ca_ops->rtt_sample ? &seq_usrtt : NULL);
if (tp->frto_counter)
tcp_process_frto(sk, prior_snd_una);
if (tcp_ack_is_dubious(tp, flag)) {
/* Advanve CWND, if state allows this. */
- if ((flag & FLAG_DATA_ACKED) &&
- (tcp_vegas_enabled(tp) || prior_in_flight >= tp->snd_cwnd) &&
- tcp_may_raise_cwnd(tp, flag))
- tcp_cong_avoid(tp, ack, seq_rtt);
+ if ((flag & FLAG_DATA_ACKED) && tcp_may_raise_cwnd(tp, flag))
+ tcp_cong_avoid(tp, ack, seq_rtt, prior_in_flight, 0);
tcp_fastretrans_alert(sk, prior_snd_una, prior_packets, flag);
} else {
- if ((flag & FLAG_DATA_ACKED) &&
- (tcp_vegas_enabled(tp) || prior_in_flight >= tp->snd_cwnd))
- tcp_cong_avoid(tp, ack, seq_rtt);
+ if ((flag & FLAG_DATA_ACKED))
+ tcp_cong_avoid(tp, ack, seq_rtt, prior_in_flight, 1);
}
if ((flag & FLAG_FORWARD_PROGRESS) || !(flag&FLAG_NOT_DUP))
@@ -4355,16 +3726,7 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
goto no_ack;
}
- if (eaten) {
- if (tcp_in_quickack_mode(tp)) {
- tcp_send_ack(sk);
- } else {
- tcp_send_delayed_ack(sk);
- }
- } else {
- __tcp_ack_snd_check(sk, 0);
- }
-
+ __tcp_ack_snd_check(sk, 0);
no_ack:
if (eaten)
__kfree_skb(skb);
@@ -4561,6 +3923,8 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
tcp_init_metrics(sk);
+ tcp_init_congestion_control(tp);
+
/* Prevent spurious tcp_cwnd_restart() on first data
* packet.
*/
@@ -4717,9 +4081,6 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
if(tp->af_specific->conn_request(sk, skb) < 0)
return 1;
- init_westwood(sk);
- init_bictcp(tp);
-
/* Now we have several options: In theory there is
* nothing else in the frame. KA9Q has an option to
* send data with the syn, BSD accepts data with the
@@ -4741,9 +4102,6 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
goto discard;
case TCP_SYN_SENT:
- init_westwood(sk);
- init_bictcp(tp);
-
queued = tcp_rcv_synsent_state_process(sk, skb, th, len);
if (queued >= 0)
return queued;
@@ -4825,7 +4183,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
*/
if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr &&
!tp->srtt)
- tcp_ack_saw_tstamp(tp, 0);
+ tcp_ack_saw_tstamp(tp, 0, 0);
if (tp->rx_opt.tstamp_ok)
tp->advmss -= TCPOLEN_TSTAMP_ALIGNED;
@@ -4837,6 +4195,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
tcp_init_metrics(sk);
+ tcp_init_congestion_control(tp);
+
/* Prevent spurious tcp_cwnd_restart() on
* first data packet.
*/
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index dad98e4a504..ebf112347a9 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -36,7 +36,7 @@
* ACK bit.
* Andi Kleen : Implemented fast path mtu discovery.
* Fixed many serious bugs in the
- * open_request handling and moved
+ * request_sock handling and moved
* most of it into the af independent code.
* Added tail drop and some other bugfixes.
* Added new listen sematics.
@@ -869,21 +869,23 @@ static __inline__ u32 tcp_v4_synq_hash(u32 raddr, u16 rport, u32 rnd)
return (jhash_2words(raddr, (u32) rport, rnd) & (TCP_SYNQ_HSIZE - 1));
}
-static struct open_request *tcp_v4_search_req(struct tcp_sock *tp,
- struct open_request ***prevp,
+static struct request_sock *tcp_v4_search_req(struct tcp_sock *tp,
+ struct request_sock ***prevp,
__u16 rport,
__u32 raddr, __u32 laddr)
{
- struct tcp_listen_opt *lopt = tp->listen_opt;
- struct open_request *req, **prev;
+ struct listen_sock *lopt = tp->accept_queue.listen_opt;
+ struct request_sock *req, **prev;
for (prev = &lopt->syn_table[tcp_v4_synq_hash(raddr, rport, lopt->hash_rnd)];
(req = *prev) != NULL;
prev = &req->dl_next) {
- if (req->rmt_port == rport &&
- req->af.v4_req.rmt_addr == raddr &&
- req->af.v4_req.loc_addr == laddr &&
- TCP_INET_FAMILY(req->class->family)) {
+ const struct inet_request_sock *ireq = inet_rsk(req);
+
+ if (ireq->rmt_port == rport &&
+ ireq->rmt_addr == raddr &&
+ ireq->loc_addr == laddr &&
+ TCP_INET_FAMILY(req->rsk_ops->family)) {
BUG_TRAP(!req->sk);
*prevp = prev;
break;
@@ -893,21 +895,13 @@ static struct open_request *tcp_v4_search_req(struct tcp_sock *tp,
return req;
}
-static void tcp_v4_synq_add(struct sock *sk, struct open_request *req)
+static void tcp_v4_synq_add(struct sock *sk, struct request_sock *req)
{
struct tcp_sock *tp = tcp_sk(sk);
- struct tcp_listen_opt *lopt = tp->listen_opt;
- u32 h = tcp_v4_synq_hash(req->af.v4_req.rmt_addr, req->rmt_port, lopt->hash_rnd);
-
- req->expires = jiffies + TCP_TIMEOUT_INIT;
- req->retrans = 0;
- req->sk = NULL;
- req->dl_next = lopt->syn_table[h];
-
- write_lock(&tp->syn_wait_lock);
- lopt->syn_table[h] = req;
- write_unlock(&tp->syn_wait_lock);
+ struct listen_sock *lopt = tp->accept_queue.listen_opt;
+ u32 h = tcp_v4_synq_hash(inet_rsk(req)->rmt_addr, inet_rsk(req)->rmt_port, lopt->hash_rnd);
+ reqsk_queue_hash_req(&tp->accept_queue, h, req, TCP_TIMEOUT_INIT);
tcp_synq_added(sk);
}
@@ -1050,7 +1044,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info)
}
switch (sk->sk_state) {
- struct open_request *req, **prev;
+ struct request_sock *req, **prev;
case TCP_LISTEN:
if (sock_owned_by_user(sk))
goto out;
@@ -1065,7 +1059,7 @@ void tcp_v4_err(struct sk_buff *skb, u32 info)
*/
BUG_TRAP(!req->sk);
- if (seq != req->snt_isn) {
+ if (seq != tcp_rsk(req)->snt_isn) {
NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
goto out;
}
@@ -1254,28 +1248,29 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
tcp_tw_put(tw);
}
-static void tcp_v4_or_send_ack(struct sk_buff *skb, struct open_request *req)
+static void tcp_v4_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req)
{
- tcp_v4_send_ack(skb, req->snt_isn + 1, req->rcv_isn + 1, req->rcv_wnd,
+ tcp_v4_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd,
req->ts_recent);
}
static struct dst_entry* tcp_v4_route_req(struct sock *sk,
- struct open_request *req)
+ struct request_sock *req)
{
struct rtable *rt;
- struct ip_options *opt = req->af.v4_req.opt;
+ const struct inet_request_sock *ireq = inet_rsk(req);
+ struct ip_options *opt = inet_rsk(req)->opt;
struct flowi fl = { .oif = sk->sk_bound_dev_if,
.nl_u = { .ip4_u =
{ .daddr = ((opt && opt->srr) ?
opt->faddr :
- req->af.v4_req.rmt_addr),
- .saddr = req->af.v4_req.loc_addr,
+ ireq->rmt_addr),
+ .saddr = ireq->loc_addr,
.tos = RT_CONN_FLAGS(sk) } },
.proto = IPPROTO_TCP,
.uli_u = { .ports =
{ .sport = inet_sk(sk)->sport,
- .dport = req->rmt_port } } };
+ .dport = ireq->rmt_port } } };
if (ip_route_output_flow(&rt, &fl, sk, 0)) {
IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
@@ -1291,12 +1286,13 @@ static struct dst_entry* tcp_v4_route_req(struct sock *sk,
/*
* Send a SYN-ACK after having received an ACK.
- * This still operates on a open_request only, not on a big
+ * This still operates on a request_sock only, not on a big
* socket.
*/
-static int tcp_v4_send_synack(struct sock *sk, struct open_request *req,
+static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req,
struct dst_entry *dst)
{
+ const struct inet_request_sock *ireq = inet_rsk(req);
int err = -1;
struct sk_buff * skb;
@@ -1310,14 +1306,14 @@ static int tcp_v4_send_synack(struct sock *sk, struct open_request *req,
struct tcphdr *th = skb->h.th;
th->check = tcp_v4_check(th, skb->len,
- req->af.v4_req.loc_addr,
- req->af.v4_req.rmt_addr,
+ ireq->loc_addr,
+ ireq->rmt_addr,
csum_partial((char *)th, skb->len,
skb->csum));
- err = ip_build_and_send_pkt(skb, sk, req->af.v4_req.loc_addr,
- req->af.v4_req.rmt_addr,
- req->af.v4_req.opt);
+ err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr,
+ ireq->rmt_addr,
+ ireq->opt);
if (err == NET_XMIT_CN)
err = 0;
}
@@ -1328,12 +1324,12 @@ out:
}
/*
- * IPv4 open_request destructor.
+ * IPv4 request_sock destructor.
*/
-static void tcp_v4_or_free(struct open_request *req)
+static void tcp_v4_reqsk_destructor(struct request_sock *req)
{
- if (req->af.v4_req.opt)
- kfree(req->af.v4_req.opt);
+ if (inet_rsk(req)->opt)
+ kfree(inet_rsk(req)->opt);
}
static inline void syn_flood_warning(struct sk_buff *skb)
@@ -1349,7 +1345,7 @@ static inline void syn_flood_warning(struct sk_buff *skb)
}
/*
- * Save and compile IPv4 options into the open_request if needed.
+ * Save and compile IPv4 options into the request_sock if needed.
*/
static inline struct ip_options *tcp_v4_save_options(struct sock *sk,
struct sk_buff *skb)
@@ -1370,33 +1366,20 @@ static inline struct ip_options *tcp_v4_save_options(struct sock *sk,
return dopt;
}
-/*
- * Maximum number of SYN_RECV sockets in queue per LISTEN socket.
- * One SYN_RECV socket costs about 80bytes on a 32bit machine.
- * It would be better to replace it with a global counter for all sockets
- * but then some measure against one socket starving all other sockets
- * would be needed.
- *
- * It was 128 by default. Experiments with real servers show, that
- * it is absolutely not enough even at 100conn/sec. 256 cures most
- * of problems. This value is adjusted to 128 for very small machines
- * (<=32Mb of memory) and to 1024 on normal or better ones (>=256Mb).
- * Further increasing requires to change hash table size.
- */
-int sysctl_max_syn_backlog = 256;
-
-struct or_calltable or_ipv4 = {
+struct request_sock_ops tcp_request_sock_ops = {
.family = PF_INET,
+ .obj_size = sizeof(struct tcp_request_sock),
.rtx_syn_ack = tcp_v4_send_synack,
- .send_ack = tcp_v4_or_send_ack,
- .destructor = tcp_v4_or_free,
+ .send_ack = tcp_v4_reqsk_send_ack,
+ .destructor = tcp_v4_reqsk_destructor,
.send_reset = tcp_v4_send_reset,
};
int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
{
+ struct inet_request_sock *ireq;
struct tcp_options_received tmp_opt;
- struct open_request *req;
+ struct request_sock *req;
__u32 saddr = skb->nh.iph->saddr;
__u32 daddr = skb->nh.iph->daddr;
__u32 isn = TCP_SKB_CB(skb)->when;
@@ -1433,7 +1416,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
if (sk_acceptq_is_full(sk) && tcp_synq_young(sk) > 1)
goto drop;
- req = tcp_openreq_alloc();
+ req = reqsk_alloc(&tcp_request_sock_ops);
if (!req)
goto drop;
@@ -1461,10 +1444,10 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
tcp_openreq_init(req, &tmp_opt, skb);
- req->af.v4_req.loc_addr = daddr;
- req->af.v4_req.rmt_addr = saddr;
- req->af.v4_req.opt = tcp_v4_save_options(sk, skb);
- req->class = &or_ipv4;
+ ireq = inet_rsk(req);
+ ireq->loc_addr = daddr;
+ ireq->rmt_addr = saddr;
+ ireq->opt = tcp_v4_save_options(sk, skb);
if (!want_cookie)
TCP_ECN_create_request(req, skb->h.th);
@@ -1523,20 +1506,20 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
isn = tcp_v4_init_sequence(sk, skb);
}
- req->snt_isn = isn;
+ tcp_rsk(req)->snt_isn = isn;
if (tcp_v4_send_synack(sk, req, dst))
goto drop_and_free;
if (want_cookie) {
- tcp_openreq_free(req);
+ reqsk_free(req);
} else {
tcp_v4_synq_add(sk, req);
}
return 0;
drop_and_free:
- tcp_openreq_free(req);
+ reqsk_free(req);
drop:
TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS);
return 0;
@@ -1548,9 +1531,10 @@ drop:
* now create the new socket.
*/
struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
- struct open_request *req,
+ struct request_sock *req,
struct dst_entry *dst)
{
+ struct inet_request_sock *ireq;
struct inet_sock *newinet;
struct tcp_sock *newtp;
struct sock *newsk;
@@ -1570,11 +1554,12 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
newtp = tcp_sk(newsk);
newinet = inet_sk(newsk);
- newinet->daddr = req->af.v4_req.rmt_addr;
- newinet->rcv_saddr = req->af.v4_req.loc_addr;
- newinet->saddr = req->af.v4_req.loc_addr;
- newinet->opt = req->af.v4_req.opt;
- req->af.v4_req.opt = NULL;
+ ireq = inet_rsk(req);
+ newinet->daddr = ireq->rmt_addr;
+ newinet->rcv_saddr = ireq->loc_addr;
+ newinet->saddr = ireq->loc_addr;
+ newinet->opt = ireq->opt;
+ ireq->opt = NULL;
newinet->mc_index = tcp_v4_iif(skb);
newinet->mc_ttl = skb->nh.iph->ttl;
newtp->ext_header_len = 0;
@@ -1605,9 +1590,9 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
struct iphdr *iph = skb->nh.iph;
struct tcp_sock *tp = tcp_sk(sk);
struct sock *nsk;
- struct open_request **prev;
+ struct request_sock **prev;
/* Find possible connection requests. */
- struct open_request *req = tcp_v4_search_req(tp, &prev, th->source,
+ struct request_sock *req = tcp_v4_search_req(tp, &prev, th->source,
iph->saddr, iph->daddr);
if (req)
return tcp_check_req(sk, skb, req, prev);
@@ -2063,6 +2048,7 @@ static int tcp_v4_init_sock(struct sock *sk)
tp->mss_cache_std = tp->mss_cache = 536;
tp->reordering = sysctl_tcp_reordering;
+ tp->ca_ops = &tcp_init_congestion_ops;
sk->sk_state = TCP_CLOSE;
@@ -2085,6 +2071,8 @@ int tcp_v4_destroy_sock(struct sock *sk)
tcp_clear_xmit_timers(sk);
+ tcp_cleanup_congestion_control(tp);
+
/* Cleanup up the write buffer. */
sk_stream_writequeue_purge(sk);
@@ -2144,13 +2132,13 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
++st->num;
if (st->state == TCP_SEQ_STATE_OPENREQ) {
- struct open_request *req = cur;
+ struct request_sock *req = cur;
tp = tcp_sk(st->syn_wait_sk);
req = req->dl_next;
while (1) {
while (req) {
- if (req->class->family == st->family) {
+ if (req->rsk_ops->family == st->family) {
cur = req;
goto out;
}
@@ -2159,17 +2147,17 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
if (++st->sbucket >= TCP_SYNQ_HSIZE)
break;
get_req:
- req = tp->listen_opt->syn_table[st->sbucket];
+ req = tp->accept_queue.listen_opt->syn_table[st->sbucket];
}
sk = sk_next(st->syn_wait_sk);
st->state = TCP_SEQ_STATE_LISTENING;
- read_unlock_bh(&tp->syn_wait_lock);
+ read_unlock_bh(&tp->accept_queue.syn_wait_lock);
} else {
tp = tcp_sk(sk);
- read_lock_bh(&tp->syn_wait_lock);
- if (tp->listen_opt && tp->listen_opt->qlen)
+ read_lock_bh(&tp->accept_queue.syn_wait_lock);
+ if (reqsk_queue_len(&tp->accept_queue))
goto start_req;
- read_unlock_bh(&tp->syn_wait_lock);
+ read_unlock_bh(&tp->accept_queue.syn_wait_lock);
sk = sk_next(sk);
}
get_sk:
@@ -2179,8 +2167,8 @@ get_sk:
goto out;
}
tp = tcp_sk(sk);
- read_lock_bh(&tp->syn_wait_lock);
- if (tp->listen_opt && tp->listen_opt->qlen) {
+ read_lock_bh(&tp->accept_queue.syn_wait_lock);
+ if (reqsk_queue_len(&tp->accept_queue)) {
start_req:
st->uid = sock_i_uid(sk);
st->syn_wait_sk = sk;
@@ -2188,7 +2176,7 @@ start_req:
st->sbucket = 0;
goto get_req;
}
- read_unlock_bh(&tp->syn_wait_lock);
+ read_unlock_bh(&tp->accept_queue.syn_wait_lock);
}
if (++st->bucket < TCP_LHTABLE_SIZE) {
sk = sk_head(&tcp_listening_hash[st->bucket]);
@@ -2375,7 +2363,7 @@ static void tcp_seq_stop(struct seq_file *seq, void *v)
case TCP_SEQ_STATE_OPENREQ:
if (v) {
struct tcp_sock *tp = tcp_sk(st->syn_wait_sk);
- read_unlock_bh(&tp->syn_wait_lock);
+ read_unlock_bh(&tp->accept_queue.syn_wait_lock);
}
case TCP_SEQ_STATE_LISTENING:
if (v != SEQ_START_TOKEN)
@@ -2451,18 +2439,19 @@ void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo)
memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops));
}
-static void get_openreq4(struct sock *sk, struct open_request *req,
+static void get_openreq4(struct sock *sk, struct request_sock *req,
char *tmpbuf, int i, int uid)
{
+ const struct inet_request_sock *ireq = inet_rsk(req);
int ttd = req->expires - jiffies;
sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
" %02X %08X:%08X %02X:%08lX %08X %5d %8d %u %d %p",
i,
- req->af.v4_req.loc_addr,
+ ireq->loc_addr,
ntohs(inet_sk(sk)->sport),
- req->af.v4_req.rmt_addr,
- ntohs(req->rmt_port),
+ ireq->rmt_addr,
+ ntohs(ireq->rmt_port),
TCP_SYN_RECV,
0, 0, /* could print option size, but that is af dependent. */
1, /* timers active (only the expire timer) */
@@ -2618,6 +2607,7 @@ struct proto tcp_prot = {
.sysctl_rmem = sysctl_tcp_rmem,
.max_header = MAX_TCP_HEADER,
.obj_size = sizeof(struct tcp_sock),
+ .rsk_prot = &tcp_request_sock_ops,
};
@@ -2660,7 +2650,6 @@ EXPORT_SYMBOL(tcp_proc_register);
EXPORT_SYMBOL(tcp_proc_unregister);
#endif
EXPORT_SYMBOL(sysctl_local_port_range);
-EXPORT_SYMBOL(sysctl_max_syn_backlog);
EXPORT_SYMBOL(sysctl_tcp_low_latency);
EXPORT_SYMBOL(sysctl_tcp_tw_reuse);
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index eea1a17a9ac..f42a284164b 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -684,7 +684,7 @@ out:
* Actually, we could lots of memory writes here. tp of listening
* socket contains all necessary default parameters.
*/
-struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req, struct sk_buff *skb)
+struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, struct sk_buff *skb)
{
/* allocate the newsk from the same slab of the master sock,
* if not, at sk_free time we'll try to free it from the wrong
@@ -692,6 +692,8 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
struct sock *newsk = sk_alloc(PF_INET, GFP_ATOMIC, sk->sk_prot, 0);
if(newsk != NULL) {
+ struct inet_request_sock *ireq = inet_rsk(req);
+ struct tcp_request_sock *treq = tcp_rsk(req);
struct tcp_sock *newtp;
struct sk_filter *filter;
@@ -703,7 +705,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
tcp_sk(newsk)->bind_hash = NULL;
/* Clone the TCP header template */
- inet_sk(newsk)->dport = req->rmt_port;
+ inet_sk(newsk)->dport = ireq->rmt_port;
sock_lock_init(newsk);
bh_lock_sock(newsk);
@@ -739,14 +741,14 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
/* Now setup tcp_sock */
newtp = tcp_sk(newsk);
newtp->pred_flags = 0;
- newtp->rcv_nxt = req->rcv_isn + 1;
- newtp->snd_nxt = req->snt_isn + 1;
- newtp->snd_una = req->snt_isn + 1;
- newtp->snd_sml = req->snt_isn + 1;
+ newtp->rcv_nxt = treq->rcv_isn + 1;
+ newtp->snd_nxt = treq->snt_isn + 1;
+ newtp->snd_una = treq->snt_isn + 1;
+ newtp->snd_sml = treq->snt_isn + 1;
tcp_prequeue_init(newtp);
- tcp_init_wl(newtp, req->snt_isn, req->rcv_isn);
+ tcp_init_wl(newtp, treq->snt_isn, treq->rcv_isn);
newtp->retransmits = 0;
newtp->backoff = 0;
@@ -772,13 +774,15 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
newtp->frto_counter = 0;
newtp->frto_highmark = 0;
+ newtp->ca_ops = &tcp_reno;
+
tcp_set_ca_state(newtp, TCP_CA_Open);
tcp_init_xmit_timers(newsk);
skb_queue_head_init(&newtp->out_of_order_queue);
- newtp->rcv_wup = req->rcv_isn + 1;
- newtp->write_seq = req->snt_isn + 1;
+ newtp->rcv_wup = treq->rcv_isn + 1;
+ newtp->write_seq = treq->snt_isn + 1;
newtp->pushed_seq = newtp->write_seq;
- newtp->copied_seq = req->rcv_isn + 1;
+ newtp->copied_seq = treq->rcv_isn + 1;
newtp->rx_opt.saw_tstamp = 0;
@@ -788,10 +792,8 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
newtp->probes_out = 0;
newtp->rx_opt.num_sacks = 0;
newtp->urg_data = 0;
- newtp->listen_opt = NULL;
- newtp->accept_queue = newtp->accept_queue_tail = NULL;
- /* Deinitialize syn_wait_lock to trap illegal accesses. */
- memset(&newtp->syn_wait_lock, 0, sizeof(newtp->syn_wait_lock));
+ /* Deinitialize accept_queue to trap illegal accesses. */
+ memset(&newtp->accept_queue, 0, sizeof(newtp->accept_queue));
/* Back to base struct sock members. */
newsk->sk_err = 0;
@@ -808,18 +810,18 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
newsk->sk_socket = NULL;
newsk->sk_sleep = NULL;
- newtp->rx_opt.tstamp_ok = req->tstamp_ok;
- if((newtp->rx_opt.sack_ok = req->sack_ok) != 0) {
+ newtp->rx_opt.tstamp_ok = ireq->tstamp_ok;
+ if((newtp->rx_opt.sack_ok = ireq->sack_ok) != 0) {
if (sysctl_tcp_fack)
newtp->rx_opt.sack_ok |= 2;
}
newtp->window_clamp = req->window_clamp;
newtp->rcv_ssthresh = req->rcv_wnd;
newtp->rcv_wnd = req->rcv_wnd;
- newtp->rx_opt.wscale_ok = req->wscale_ok;
+ newtp->rx_opt.wscale_ok = ireq->wscale_ok;
if (newtp->rx_opt.wscale_ok) {
- newtp->rx_opt.snd_wscale = req->snd_wscale;
- newtp->rx_opt.rcv_wscale = req->rcv_wscale;
+ newtp->rx_opt.snd_wscale = ireq->snd_wscale;
+ newtp->rx_opt.rcv_wscale = ireq->rcv_wscale;
} else {
newtp->rx_opt.snd_wscale = newtp->rx_opt.rcv_wscale = 0;
newtp->window_clamp = min(newtp->window_clamp, 65535U);
@@ -842,8 +844,6 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
if (newtp->ecn_flags&TCP_ECN_OK)
sock_set_flag(newsk, SOCK_NO_LARGESEND);
- tcp_ca_init(newtp);
-
TCP_INC_STATS_BH(TCP_MIB_PASSIVEOPENS);
}
return newsk;
@@ -851,12 +851,12 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req,
/*
* Process an incoming packet for SYN_RECV sockets represented
- * as an open_request.
+ * as a request_sock.
*/
struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
- struct open_request *req,
- struct open_request **prev)
+ struct request_sock *req,
+ struct request_sock **prev)
{
struct tcphdr *th = skb->h.th;
struct tcp_sock *tp = tcp_sk(sk);
@@ -881,7 +881,7 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
}
/* Check for pure retransmitted SYN. */
- if (TCP_SKB_CB(skb)->seq == req->rcv_isn &&
+ if (TCP_SKB_CB(skb)->seq == tcp_rsk(req)->rcv_isn &&
flg == TCP_FLAG_SYN &&
!paws_reject) {
/*
@@ -901,7 +901,7 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
* Enforce "SYN-ACK" according to figure 8, figure 6
* of RFC793, fixed by RFC1122.
*/
- req->class->rtx_syn_ack(sk, req, NULL);
+ req->rsk_ops->rtx_syn_ack(sk, req, NULL);
return NULL;
}
@@ -959,7 +959,7 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
* Invalid ACK: reset will be sent by listening socket
*/
if ((flg & TCP_FLAG_ACK) &&
- (TCP_SKB_CB(skb)->ack_seq != req->snt_isn+1))
+ (TCP_SKB_CB(skb)->ack_seq != tcp_rsk(req)->snt_isn + 1))
return sk;
/* Also, it would be not so bad idea to check rcv_tsecr, which
@@ -970,10 +970,10 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
/* RFC793: "first check sequence number". */
if (paws_reject || !tcp_in_window(TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq,
- req->rcv_isn+1, req->rcv_isn+1+req->rcv_wnd)) {
+ tcp_rsk(req)->rcv_isn + 1, tcp_rsk(req)->rcv_isn + 1 + req->rcv_wnd)) {
/* Out of window: send ACK and drop. */
if (!(flg & TCP_FLAG_RST))
- req->class->send_ack(skb, req);
+ req->rsk_ops->send_ack(skb, req);
if (paws_reject)
NET_INC_STATS_BH(LINUX_MIB_PAWSESTABREJECTED);
return NULL;
@@ -981,12 +981,12 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
/* In sequence, PAWS is OK. */
- if (tmp_opt.saw_tstamp && !after(TCP_SKB_CB(skb)->seq, req->rcv_isn+1))
+ if (tmp_opt.saw_tstamp && !after(TCP_SKB_CB(skb)->seq, tcp_rsk(req)->rcv_isn + 1))
req->ts_recent = tmp_opt.rcv_tsval;
- if (TCP_SKB_CB(skb)->seq == req->rcv_isn) {
+ if (TCP_SKB_CB(skb)->seq == tcp_rsk(req)->rcv_isn) {
/* Truncate SYN, it is out of window starting
- at req->rcv_isn+1. */
+ at tcp_rsk(req)->rcv_isn + 1. */
flg &= ~TCP_FLAG_SYN;
}
@@ -1003,8 +1003,8 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
return NULL;
/* If TCP_DEFER_ACCEPT is set, drop bare ACK. */
- if (tp->defer_accept && TCP_SKB_CB(skb)->end_seq == req->rcv_isn+1) {
- req->acked = 1;
+ if (tp->defer_accept && TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) {
+ inet_rsk(req)->acked = 1;
return NULL;
}
@@ -1026,14 +1026,14 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
listen_overflow:
if (!sysctl_tcp_abort_on_overflow) {
- req->acked = 1;
+ inet_rsk(req)->acked = 1;
return NULL;
}
embryonic_reset:
NET_INC_STATS_BH(LINUX_MIB_EMBRYONICRSTS);
if (!(flg & TCP_FLAG_RST))
- req->class->send_reset(skb);
+ req->rsk_ops->send_reset(skb);
tcp_synq_drop(sk, req, prev);
return NULL;
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index fa24e7ae1f4..0e17c244875 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -111,8 +111,7 @@ static void tcp_cwnd_restart(struct tcp_sock *tp, struct dst_entry *dst)
u32 restart_cwnd = tcp_init_cwnd(tp, dst);
u32 cwnd = tp->snd_cwnd;
- if (tcp_is_vegas(tp))
- tcp_vegas_enable(tp);
+ tcp_ca_event(tp, CA_EVENT_CWND_RESTART);
tp->snd_ssthresh = tcp_current_ssthresh(tp);
restart_cwnd = min(restart_cwnd, cwnd);
@@ -280,6 +279,10 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb)
#define SYSCTL_FLAG_WSCALE 0x2
#define SYSCTL_FLAG_SACK 0x4
+ /* If congestion control is doing timestamping */
+ if (tp->ca_ops->rtt_sample)
+ do_gettimeofday(&skb->stamp);
+
sysctl_flags = 0;
if (tcb->flags & TCPCB_FLAG_SYN) {
tcp_header_size = sizeof(struct tcphdr) + TCPOLEN_MSS;
@@ -304,17 +307,8 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb)
(tp->rx_opt.eff_sacks * TCPOLEN_SACK_PERBLOCK));
}
- /*
- * If the connection is idle and we are restarting,
- * then we don't want to do any Vegas calculations
- * until we get fresh RTT samples. So when we
- * restart, we reset our Vegas state to a clean
- * slate. After we get acks for this flight of
- * packets, _then_ we can make Vegas calculations
- * again.
- */
- if (tcp_is_vegas(tp) && tcp_packets_in_flight(tp) == 0)
- tcp_vegas_enable(tp);
+ if (tcp_packets_in_flight(tp) == 0)
+ tcp_ca_event(tp, CA_EVENT_TX_START);
th = (struct tcphdr *) skb_push(skb, tcp_header_size);
skb->h.th = th;
@@ -521,6 +515,7 @@ static int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len)
* skbs, which it never sent before. --ANK
*/
TCP_SKB_CB(buff)->when = TCP_SKB_CB(skb)->when;
+ buff->stamp = skb->stamp;
if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) {
tp->lost_out -= tcp_skb_pcount(skb);
@@ -1356,8 +1351,9 @@ int tcp_send_synack(struct sock *sk)
* Prepare a SYN-ACK.
*/
struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
- struct open_request *req)
+ struct request_sock *req)
{
+ struct inet_request_sock *ireq = inet_rsk(req);
struct tcp_sock *tp = tcp_sk(sk);
struct tcphdr *th;
int tcp_header_size;
@@ -1373,47 +1369,47 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
skb->dst = dst_clone(dst);
tcp_header_size = (sizeof(struct tcphdr) + TCPOLEN_MSS +
- (req->tstamp_ok ? TCPOLEN_TSTAMP_ALIGNED : 0) +
- (req->wscale_ok ? TCPOLEN_WSCALE_ALIGNED : 0) +
+ (ireq->tstamp_ok ? TCPOLEN_TSTAMP_ALIGNED : 0) +
+ (ireq->wscale_ok ? TCPOLEN_WSCALE_ALIGNED : 0) +
/* SACK_PERM is in the place of NOP NOP of TS */
- ((req->sack_ok && !req->tstamp_ok) ? TCPOLEN_SACKPERM_ALIGNED : 0));
+ ((ireq->sack_ok && !ireq->tstamp_ok) ? TCPOLEN_SACKPERM_ALIGNED : 0));
skb->h.th = th = (struct tcphdr *) skb_push(skb, tcp_header_size);
memset(th, 0, sizeof(struct tcphdr));
th->syn = 1;
th->ack = 1;
if (dst->dev->features&NETIF_F_TSO)
- req->ecn_ok = 0;
+ ireq->ecn_ok = 0;
TCP_ECN_make_synack(req, th);
th->source = inet_sk(sk)->sport;
- th->dest = req->rmt_port;
- TCP_SKB_CB(skb)->seq = req->snt_isn;
+ th->dest = ireq->rmt_port;
+ TCP_SKB_CB(skb)->seq = tcp_rsk(req)->snt_isn;
TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + 1;
TCP_SKB_CB(skb)->sacked = 0;
skb_shinfo(skb)->tso_segs = 1;
skb_shinfo(skb)->tso_size = 0;
th->seq = htonl(TCP_SKB_CB(skb)->seq);
- th->ack_seq = htonl(req->rcv_isn + 1);
+ th->ack_seq = htonl(tcp_rsk(req)->rcv_isn + 1);
if (req->rcv_wnd == 0) { /* ignored for retransmitted syns */
__u8 rcv_wscale;
/* Set this up on the first call only */
req->window_clamp = tp->window_clamp ? : dst_metric(dst, RTAX_WINDOW);
/* tcp_full_space because it is guaranteed to be the first packet */
tcp_select_initial_window(tcp_full_space(sk),
- dst_metric(dst, RTAX_ADVMSS) - (req->tstamp_ok ? TCPOLEN_TSTAMP_ALIGNED : 0),
+ dst_metric(dst, RTAX_ADVMSS) - (ireq->tstamp_ok ? TCPOLEN_TSTAMP_ALIGNED : 0),
&req->rcv_wnd,
&req->window_clamp,
- req->wscale_ok,
+ ireq->wscale_ok,
&rcv_wscale);
- req->rcv_wscale = rcv_wscale;
+ ireq->rcv_wscale = rcv_wscale;
}
/* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */
th->window = htons(req->rcv_wnd);
TCP_SKB_CB(skb)->when = tcp_time_stamp;
- tcp_syn_build_options((__u32 *)(th + 1), dst_metric(dst, RTAX_ADVMSS), req->tstamp_ok,
- req->sack_ok, req->wscale_ok, req->rcv_wscale,
+ tcp_syn_build_options((__u32 *)(th + 1), dst_metric(dst, RTAX_ADVMSS), ireq->tstamp_ok,
+ ireq->sack_ok, ireq->wscale_ok, ireq->rcv_wscale,
TCP_SKB_CB(skb)->when,
req->ts_recent);
@@ -1448,7 +1444,6 @@ static inline void tcp_connect_init(struct sock *sk)
tp->window_clamp = dst_metric(dst, RTAX_WINDOW);
tp->advmss = dst_metric(dst, RTAX_ADVMSS);
tcp_initialize_rcv_mss(sk);
- tcp_ca_init(tp);
tcp_select_initial_window(tcp_full_space(sk),
tp->advmss - (tp->rx_opt.ts_recent_stamp ? tp->tcp_header_len - sizeof(struct tcphdr) : 0),
@@ -1502,7 +1497,6 @@ int tcp_connect(struct sock *sk)
TCP_SKB_CB(buff)->end_seq = tp->write_seq;
tp->snd_nxt = tp->write_seq;
tp->pushed_seq = tp->write_seq;
- tcp_ca_init(tp);
/* Send it off. */
TCP_SKB_CB(buff)->when = tcp_time_stamp;
diff --git a/net/ipv4/tcp_scalable.c b/net/ipv4/tcp_scalable.c
new file mode 100644
index 00000000000..70e108e15c7
--- /dev/null
+++ b/net/ipv4/tcp_scalable.c
@@ -0,0 +1,68 @@
+/* Tom Kelly's Scalable TCP
+ *
+ * See htt://www-lce.eng.cam.ac.uk/~ctk21/scalable/
+ *
+ * John Heffner <jheffner@sc.edu>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <net/tcp.h>
+
+/* These factors derived from the recommended values in the aer:
+ * .01 and and 7/8. We use 50 instead of 100 to account for
+ * delayed ack.
+ */
+#define TCP_SCALABLE_AI_CNT 50U
+#define TCP_SCALABLE_MD_SCALE 3
+
+static void tcp_scalable_cong_avoid(struct tcp_sock *tp, u32 ack, u32 rtt,
+ u32 in_flight, int flag)
+{
+ if (in_flight < tp->snd_cwnd)
+ return;
+
+ if (tp->snd_cwnd <= tp->snd_ssthresh) {
+ tp->snd_cwnd++;
+ } else {
+ tp->snd_cwnd_cnt++;
+ if (tp->snd_cwnd_cnt > min(tp->snd_cwnd, TCP_SCALABLE_AI_CNT)){
+ tp->snd_cwnd++;
+ tp->snd_cwnd_cnt = 0;
+ }
+ }
+ tp->snd_cwnd = min_t(u32, tp->snd_cwnd, tp->snd_cwnd_clamp);
+ tp->snd_cwnd_stamp = tcp_time_stamp;
+}
+
+static u32 tcp_scalable_ssthresh(struct tcp_sock *tp)
+{
+ return max(tp->snd_cwnd - (tp->snd_cwnd>>TCP_SCALABLE_MD_SCALE), 2U);
+}
+
+
+static struct tcp_congestion_ops tcp_scalable = {
+ .ssthresh = tcp_scalable_ssthresh,
+ .cong_avoid = tcp_scalable_cong_avoid,
+ .min_cwnd = tcp_reno_min_cwnd,
+
+ .owner = THIS_MODULE,
+ .name = "scalable",
+};
+
+static int __init tcp_scalable_register(void)
+{
+ return tcp_register_congestion_control(&tcp_scalable);
+}
+
+static void __exit tcp_scalable_unregister(void)
+{
+ tcp_unregister_congestion_control(&tcp_scalable);
+}
+
+module_init(tcp_scalable_register);
+module_exit(tcp_scalable_unregister);
+
+MODULE_AUTHOR("John Heffner");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Scalable TCP");
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index 799ebe061e2..b127b449856 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -464,11 +464,11 @@ out_unlock:
static void tcp_synack_timer(struct sock *sk)
{
struct tcp_sock *tp = tcp_sk(sk);
- struct tcp_listen_opt *lopt = tp->listen_opt;
+ struct listen_sock *lopt = tp->accept_queue.listen_opt;
int max_retries = tp->syn_retries ? : sysctl_tcp_synack_retries;
int thresh = max_retries;
unsigned long now = jiffies;
- struct open_request **reqp, *req;
+ struct request_sock **reqp, *req;
int i, budget;
if (lopt == NULL || lopt->qlen == 0)
@@ -513,8 +513,8 @@ static void tcp_synack_timer(struct sock *sk)
while ((req = *reqp) != NULL) {
if (time_after_eq(now, req->expires)) {
if ((req->retrans < thresh ||
- (req->acked && req->retrans < max_retries))
- && !req->class->rtx_syn_ack(sk, req, NULL)) {
+ (inet_rsk(req)->acked && req->retrans < max_retries))
+ && !req->rsk_ops->rtx_syn_ack(sk, req, NULL)) {
unsigned long timeo;
if (req->retrans++ == 0)
@@ -527,13 +527,9 @@ static void tcp_synack_timer(struct sock *sk)
}
/* Drop this request */
- write_lock(&tp->syn_wait_lock);
- *reqp = req->dl_next;
- write_unlock(&tp->syn_wait_lock);
- lopt->qlen--;
- if (req->retrans == 0)
- lopt->qlen_young--;
- tcp_openreq_free(req);
+ tcp_synq_unlink(tp, req, reqp);
+ reqsk_queue_removed(&tp->accept_queue, req);
+ reqsk_free(req);
continue;
}
reqp = &req->dl_next;
diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c
new file mode 100644
index 00000000000..9bd443db519
--- /dev/null
+++ b/net/ipv4/tcp_vegas.c
@@ -0,0 +1,411 @@
+/*
+ * TCP Vegas congestion control
+ *
+ * This is based on the congestion detection/avoidance scheme described in
+ * Lawrence S. Brakmo and Larry L. Peterson.
+ * "TCP Vegas: End to end congestion avoidance on a global internet."
+ * IEEE Journal on Selected Areas in Communication, 13(8):1465--1480,
+ * October 1995. Available from:
+ * ftp://ftp.cs.arizona.edu/xkernel/Papers/jsac.ps
+ *
+ * See http://www.cs.arizona.edu/xkernel/ for their implementation.
+ * The main aspects that distinguish this implementation from the
+ * Arizona Vegas implementation are:
+ * o We do not change the loss detection or recovery mechanisms of
+ * Linux in any way. Linux already recovers from losses quite well,
+ * using fine-grained timers, NewReno, and FACK.
+ * o To avoid the performance penalty imposed by increasing cwnd
+ * only every-other RTT during slow start, we increase during
+ * every RTT during slow start, just like Reno.
+ * o Largely to allow continuous cwnd growth during slow start,
+ * we use the rate at which ACKs come back as the "actual"
+ * rate, rather than the rate at which data is sent.
+ * o To speed convergence to the right rate, we set the cwnd
+ * to achieve the right ("actual") rate when we exit slow start.
+ * o To filter out the noise caused by delayed ACKs, we use the
+ * minimum RTT sample observed during the last RTT to calculate
+ * the actual rate.
+ * o When the sender re-starts from idle, it waits until it has
+ * received ACKs for an entire flight of new data before making
+ * a cwnd adjustment decision. The original Vegas implementation
+ * assumed senders never went idle.
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/tcp_diag.h>
+
+#include <net/tcp.h>
+
+/* Default values of the Vegas variables, in fixed-point representation
+ * with V_PARAM_SHIFT bits to the right of the binary point.
+ */
+#define V_PARAM_SHIFT 1
+static int alpha = 1<<V_PARAM_SHIFT;
+static int beta = 3<<V_PARAM_SHIFT;
+static int gamma = 1<<V_PARAM_SHIFT;
+
+module_param(alpha, int, 0644);
+MODULE_PARM_DESC(alpha, "lower bound of packets in network (scale by 2)");
+module_param(beta, int, 0644);
+MODULE_PARM_DESC(beta, "upper bound of packets in network (scale by 2)");
+module_param(gamma, int, 0644);
+MODULE_PARM_DESC(gamma, "limit on increase (scale by 2)");
+
+
+/* Vegas variables */
+struct vegas {
+ u32 beg_snd_nxt; /* right edge during last RTT */
+ u32 beg_snd_una; /* left edge during last RTT */
+ u32 beg_snd_cwnd; /* saves the size of the cwnd */
+ u8 doing_vegas_now;/* if true, do vegas for this RTT */
+ u16 cntRTT; /* # of RTTs measured within last RTT */
+ u32 minRTT; /* min of RTTs measured within last RTT (in usec) */
+ u32 baseRTT; /* the min of all Vegas RTT measurements seen (in usec) */
+};
+
+/* There are several situations when we must "re-start" Vegas:
+ *
+ * o when a connection is established
+ * o after an RTO
+ * o after fast recovery
+ * o when we send a packet and there is no outstanding
+ * unacknowledged data (restarting an idle connection)
+ *
+ * In these circumstances we cannot do a Vegas calculation at the
+ * end of the first RTT, because any calculation we do is using
+ * stale info -- both the saved cwnd and congestion feedback are
+ * stale.
+ *
+ * Instead we must wait until the completion of an RTT during
+ * which we actually receive ACKs.
+ */
+static inline void vegas_enable(struct tcp_sock *tp)
+{
+ struct vegas *vegas = tcp_ca(tp);
+
+ /* Begin taking Vegas samples next time we send something. */
+ vegas->doing_vegas_now = 1;
+
+ /* Set the beginning of the next send window. */
+ vegas->beg_snd_nxt = tp->snd_nxt;
+
+ vegas->cntRTT = 0;
+ vegas->minRTT = 0x7fffffff;
+}
+
+/* Stop taking Vegas samples for now. */
+static inline void vegas_disable(struct tcp_sock *tp)
+{
+ struct vegas *vegas = tcp_ca(tp);
+
+ vegas->doing_vegas_now = 0;
+}
+
+static void tcp_vegas_init(struct tcp_sock *tp)
+{
+ struct vegas *vegas = tcp_ca(tp);
+
+ vegas->baseRTT = 0x7fffffff;
+ vegas_enable(tp);
+}
+
+/* Do RTT sampling needed for Vegas.
+ * Basically we:
+ * o min-filter RTT samples from within an RTT to get the current
+ * propagation delay + queuing delay (we are min-filtering to try to
+ * avoid the effects of delayed ACKs)
+ * o min-filter RTT samples from a much longer window (forever for now)
+ * to find the propagation delay (baseRTT)
+ */
+static void tcp_vegas_rtt_calc(struct tcp_sock *tp, u32 usrtt)
+{
+ struct vegas *vegas = tcp_ca(tp);
+ u32 vrtt = usrtt + 1; /* Never allow zero rtt or baseRTT */
+
+ /* Filter to find propagation delay: */
+ if (vrtt < vegas->baseRTT)
+ vegas->baseRTT = vrtt;
+
+ /* Find the min RTT during the last RTT to find
+ * the current prop. delay + queuing delay:
+ */
+ vegas->minRTT = min(vegas->minRTT, vrtt);
+ vegas->cntRTT++;
+}
+
+static void tcp_vegas_state(struct tcp_sock *tp, u8 ca_state)
+{
+
+ if (ca_state == TCP_CA_Open)
+ vegas_enable(tp);
+ else
+ vegas_disable(tp);
+}
+
+/*
+ * If the connection is idle and we are restarting,
+ * then we don't want to do any Vegas calculations
+ * until we get fresh RTT samples. So when we
+ * restart, we reset our Vegas state to a clean
+ * slate. After we get acks for this flight of
+ * packets, _then_ we can make Vegas calculations
+ * again.
+ */
+static void tcp_vegas_cwnd_event(struct tcp_sock *tp, enum tcp_ca_event event)
+{
+ if (event == CA_EVENT_CWND_RESTART ||
+ event == CA_EVENT_TX_START)
+ tcp_vegas_init(tp);
+}
+
+static void tcp_vegas_cong_avoid(struct tcp_sock *tp, u32 ack,
+ u32 seq_rtt, u32 in_flight, int flag)
+{
+ struct vegas *vegas = tcp_ca(tp);
+
+ if (!vegas->doing_vegas_now)
+ return tcp_reno_cong_avoid(tp, ack, seq_rtt, in_flight, flag);
+
+ /* The key players are v_beg_snd_una and v_beg_snd_nxt.
+ *
+ * These are so named because they represent the approximate values
+ * of snd_una and snd_nxt at the beginning of the current RTT. More
+ * precisely, they represent the amount of data sent during the RTT.
+ * At the end of the RTT, when we receive an ACK for v_beg_snd_nxt,
+ * we will calculate that (v_beg_snd_nxt - v_beg_snd_una) outstanding
+ * bytes of data have been ACKed during the course of the RTT, giving
+ * an "actual" rate of:
+ *
+ * (v_beg_snd_nxt - v_beg_snd_una) / (rtt duration)
+ *
+ * Unfortunately, v_beg_snd_una is not exactly equal to snd_una,
+ * because delayed ACKs can cover more than one segment, so they
+ * don't line up nicely with the boundaries of RTTs.
+ *
+ * Another unfortunate fact of life is that delayed ACKs delay the
+ * advance of the left edge of our send window, so that the number
+ * of bytes we send in an RTT is often less than our cwnd will allow.
+ * So we keep track of our cwnd separately, in v_beg_snd_cwnd.
+ */
+
+ if (after(ack, vegas->beg_snd_nxt)) {
+ /* Do the Vegas once-per-RTT cwnd adjustment. */
+ u32 old_wnd, old_snd_cwnd;
+
+
+ /* Here old_wnd is essentially the window of data that was
+ * sent during the previous RTT, and has all
+ * been acknowledged in the course of the RTT that ended
+ * with the ACK we just received. Likewise, old_snd_cwnd
+ * is the cwnd during the previous RTT.
+ */
+ old_wnd = (vegas->beg_snd_nxt - vegas->beg_snd_una) /
+ tp->mss_cache;
+ old_snd_cwnd = vegas->beg_snd_cwnd;
+
+ /* Save the extent of the current window so we can use this
+ * at the end of the next RTT.
+ */
+ vegas->beg_snd_una = vegas->beg_snd_nxt;
+ vegas->beg_snd_nxt = tp->snd_nxt;
+ vegas->beg_snd_cwnd = tp->snd_cwnd;
+
+ /* Take into account the current RTT sample too, to
+ * decrease the impact of delayed acks. This double counts
+ * this sample since we count it for the next window as well,
+ * but that's not too awful, since we're taking the min,
+ * rather than averaging.
+ */
+ tcp_vegas_rtt_calc(tp, seq_rtt*1000);
+
+ /* We do the Vegas calculations only if we got enough RTT
+ * samples that we can be reasonably sure that we got
+ * at least one RTT sample that wasn't from a delayed ACK.
+ * If we only had 2 samples total,
+ * then that means we're getting only 1 ACK per RTT, which
+ * means they're almost certainly delayed ACKs.
+ * If we have 3 samples, we should be OK.
+ */
+
+ if (vegas->cntRTT <= 2) {
+ /* We don't have enough RTT samples to do the Vegas
+ * calculation, so we'll behave like Reno.
+ */
+ if (tp->snd_cwnd > tp->snd_ssthresh)
+ tp->snd_cwnd++;
+ } else {
+ u32 rtt, target_cwnd, diff;
+
+ /* We have enough RTT samples, so, using the Vegas
+ * algorithm, we determine if we should increase or
+ * decrease cwnd, and by how much.
+ */
+
+ /* Pluck out the RTT we are using for the Vegas
+ * calculations. This is the min RTT seen during the
+ * last RTT. Taking the min filters out the effects
+ * of delayed ACKs, at the cost of noticing congestion
+ * a bit later.
+ */
+ rtt = vegas->minRTT;
+
+ /* Calculate the cwnd we should have, if we weren't
+ * going too fast.
+ *
+ * This is:
+ * (actual rate in segments) * baseRTT
+ * We keep it as a fixed point number with
+ * V_PARAM_SHIFT bits to the right of the binary point.
+ */
+ target_cwnd = ((old_wnd * vegas->baseRTT)
+ << V_PARAM_SHIFT) / rtt;
+
+ /* Calculate the difference between the window we had,
+ * and the window we would like to have. This quantity
+ * is the "Diff" from the Arizona Vegas papers.
+ *
+ * Again, this is a fixed point number with
+ * V_PARAM_SHIFT bits to the right of the binary
+ * point.
+ */
+ diff = (old_wnd << V_PARAM_SHIFT) - target_cwnd;
+
+ if (tp->snd_cwnd < tp->snd_ssthresh) {
+ /* Slow start. */
+ if (diff > gamma) {
+ /* Going too fast. Time to slow down
+ * and switch to congestion avoidance.
+ */
+ tp->snd_ssthresh = 2;
+
+ /* Set cwnd to match the actual rate
+ * exactly:
+ * cwnd = (actual rate) * baseRTT
+ * Then we add 1 because the integer
+ * truncation robs us of full link
+ * utilization.
+ */
+ tp->snd_cwnd = min(tp->snd_cwnd,
+ (target_cwnd >>
+ V_PARAM_SHIFT)+1);
+
+ }
+ } else {
+ /* Congestion avoidance. */
+ u32 next_snd_cwnd;
+
+ /* Figure out where we would like cwnd
+ * to be.
+ */
+ if (diff > beta) {
+ /* The old window was too fast, so
+ * we slow down.
+ */
+ next_snd_cwnd = old_snd_cwnd - 1;
+ } else if (diff < alpha) {
+ /* We don't have enough extra packets
+ * in the network, so speed up.
+ */
+ next_snd_cwnd = old_snd_cwnd + 1;
+ } else {
+ /* Sending just as fast as we
+ * should be.
+ */
+ next_snd_cwnd = old_snd_cwnd;
+ }
+
+ /* Adjust cwnd upward or downward, toward the
+ * desired value.
+ */
+ if (next_snd_cwnd > tp->snd_cwnd)
+ tp->snd_cwnd++;
+ else if (next_snd_cwnd < tp->snd_cwnd)
+ tp->snd_cwnd--;
+ }
+ }
+
+ /* Wipe the slate clean for the next RTT. */
+ vegas->cntRTT = 0;
+ vegas->minRTT = 0x7fffffff;
+ }
+
+ /* The following code is executed for every ack we receive,
+ * except for conditions checked in should_advance_cwnd()
+ * before the call to tcp_cong_avoid(). Mainly this means that
+ * we only execute this code if the ack actually acked some
+ * data.
+ */
+
+ /* If we are in slow start, increase our cwnd in response to this ACK.
+ * (If we are not in slow start then we are in congestion avoidance,
+ * and adjust our congestion window only once per RTT. See the code
+ * above.)
+ */
+ if (tp->snd_cwnd <= tp->snd_ssthresh)
+ tp->snd_cwnd++;
+
+ /* to keep cwnd from growing without bound */
+ tp->snd_cwnd = min_t(u32, tp->snd_cwnd, tp->snd_cwnd_clamp);
+
+ /* Make sure that we are never so timid as to reduce our cwnd below
+ * 2 MSS.
+ *
+ * Going below 2 MSS would risk huge delayed ACKs from our receiver.
+ */
+ tp->snd_cwnd = max(tp->snd_cwnd, 2U);
+}
+
+/* Extract info for Tcp socket info provided via netlink. */
+static void tcp_vegas_get_info(struct tcp_sock *tp, u32 ext,
+ struct sk_buff *skb)
+{
+ const struct vegas *ca = tcp_ca(tp);
+ if (ext & (1<<(TCPDIAG_VEGASINFO-1))) {
+ struct tcpvegas_info *info;
+
+ info = RTA_DATA(__RTA_PUT(skb, TCPDIAG_VEGASINFO,
+ sizeof(*info)));
+
+ info->tcpv_enabled = ca->doing_vegas_now;
+ info->tcpv_rttcnt = ca->cntRTT;
+ info->tcpv_rtt = ca->baseRTT;
+ info->tcpv_minrtt = ca->minRTT;
+ rtattr_failure: ;
+ }
+}
+
+static struct tcp_congestion_ops tcp_vegas = {
+ .init = tcp_vegas_init,
+ .ssthresh = tcp_reno_ssthresh,
+ .cong_avoid = tcp_vegas_cong_avoid,
+ .min_cwnd = tcp_reno_min_cwnd,
+ .rtt_sample = tcp_vegas_rtt_calc,
+ .set_state = tcp_vegas_state,
+ .cwnd_event = tcp_vegas_cwnd_event,
+ .get_info = tcp_vegas_get_info,
+
+ .owner = THIS_MODULE,
+ .name = "vegas",
+};
+
+static int __init tcp_vegas_register(void)
+{
+ BUG_ON(sizeof(struct vegas) > TCP_CA_PRIV_SIZE);
+ tcp_register_congestion_control(&tcp_vegas);
+ return 0;
+}
+
+static void __exit tcp_vegas_unregister(void)
+{
+ tcp_unregister_congestion_control(&tcp_vegas);
+}
+
+module_init(tcp_vegas_register);
+module_exit(tcp_vegas_unregister);
+
+MODULE_AUTHOR("Stephen Hemminger");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TCP Vegas");
diff --git a/net/ipv4/tcp_westwood.c b/net/ipv4/tcp_westwood.c
new file mode 100644
index 00000000000..ef827242c94
--- /dev/null
+++ b/net/ipv4/tcp_westwood.c
@@ -0,0 +1,259 @@
+/*
+ * TCP Westwood+
+ *
+ * Angelo Dell'Aera: TCP Westwood+ support
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/tcp_diag.h>
+#include <net/tcp.h>
+
+/* TCP Westwood structure */
+struct westwood {
+ u32 bw_ns_est; /* first bandwidth estimation..not too smoothed 8) */
+ u32 bw_est; /* bandwidth estimate */
+ u32 rtt_win_sx; /* here starts a new evaluation... */
+ u32 bk;
+ u32 snd_una; /* used for evaluating the number of acked bytes */
+ u32 cumul_ack;
+ u32 accounted;
+ u32 rtt;
+ u32 rtt_min; /* minimum observed RTT */
+};
+
+
+/* TCP Westwood functions and constants */
+#define TCP_WESTWOOD_RTT_MIN (HZ/20) /* 50ms */
+#define TCP_WESTWOOD_INIT_RTT (20*HZ) /* maybe too conservative?! */
+
+/*
+ * @tcp_westwood_create
+ * This function initializes fields used in TCP Westwood+,
+ * it is called after the initial SYN, so the sequence numbers
+ * are correct but new passive connections we have no
+ * information about RTTmin at this time so we simply set it to
+ * TCP_WESTWOOD_INIT_RTT. This value was chosen to be too conservative
+ * since in this way we're sure it will be updated in a consistent
+ * way as soon as possible. It will reasonably happen within the first
+ * RTT period of the connection lifetime.
+ */
+static void tcp_westwood_init(struct tcp_sock *tp)
+{
+ struct westwood *w = tcp_ca(tp);
+
+ w->bk = 0;
+ w->bw_ns_est = 0;
+ w->bw_est = 0;
+ w->accounted = 0;
+ w->cumul_ack = 0;
+ w->rtt_min = w->rtt = TCP_WESTWOOD_INIT_RTT;
+ w->rtt_win_sx = tcp_time_stamp;
+ w->snd_una = tp->snd_una;
+}
+
+/*
+ * @westwood_do_filter
+ * Low-pass filter. Implemented using constant coefficients.
+ */
+static inline u32 westwood_do_filter(u32 a, u32 b)
+{
+ return (((7 * a) + b) >> 3);
+}
+
+static inline void westwood_filter(struct westwood *w, u32 delta)
+{
+ w->bw_ns_est = westwood_do_filter(w->bw_ns_est, w->bk / delta);
+ w->bw_est = westwood_do_filter(w->bw_est, w->bw_ns_est);
+}
+
+/*
+ * @westwood_pkts_acked
+ * Called after processing group of packets.
+ * but all westwood needs is the last sample of srtt.
+ */
+static void tcp_westwood_pkts_acked(struct tcp_sock *tp, u32 cnt)
+{
+ struct westwood *w = tcp_ca(tp);
+ if (cnt > 0)
+ w->rtt = tp->srtt >> 3;
+}
+
+/*
+ * @westwood_update_window
+ * It updates RTT evaluation window if it is the right moment to do
+ * it. If so it calls filter for evaluating bandwidth.
+ */
+static void westwood_update_window(struct tcp_sock *tp)
+{
+ struct westwood *w = tcp_ca(tp);
+ s32 delta = tcp_time_stamp - w->rtt_win_sx;
+
+ /*
+ * See if a RTT-window has passed.
+ * Be careful since if RTT is less than
+ * 50ms we don't filter but we continue 'building the sample'.
+ * This minimum limit was chosen since an estimation on small
+ * time intervals is better to avoid...
+ * Obviously on a LAN we reasonably will always have
+ * right_bound = left_bound + WESTWOOD_RTT_MIN
+ */
+ if (w->rtt && delta > max_t(u32, w->rtt, TCP_WESTWOOD_RTT_MIN)) {
+ westwood_filter(w, delta);
+
+ w->bk = 0;
+ w->rtt_win_sx = tcp_time_stamp;
+ }
+}
+
+/*
+ * @westwood_fast_bw
+ * It is called when we are in fast path. In particular it is called when
+ * header prediction is successful. In such case in fact update is
+ * straight forward and doesn't need any particular care.
+ */
+static inline void westwood_fast_bw(struct tcp_sock *tp)
+{
+ struct westwood *w = tcp_ca(tp);
+
+ westwood_update_window(tp);
+
+ w->bk += tp->snd_una - w->snd_una;
+ w->snd_una = tp->snd_una;
+ w->rtt_min = min(w->rtt, w->rtt_min);
+}
+
+/*
+ * @westwood_acked_count
+ * This function evaluates cumul_ack for evaluating bk in case of
+ * delayed or partial acks.
+ */
+static inline u32 westwood_acked_count(struct tcp_sock *tp)
+{
+ struct westwood *w = tcp_ca(tp);
+
+ w->cumul_ack = tp->snd_una - w->snd_una;
+
+ /* If cumul_ack is 0 this is a dupack since it's not moving
+ * tp->snd_una.
+ */
+ if (!w->cumul_ack) {
+ w->accounted += tp->mss_cache;
+ w->cumul_ack = tp->mss_cache;
+ }
+
+ if (w->cumul_ack > tp->mss_cache) {
+ /* Partial or delayed ack */
+ if (w->accounted >= w->cumul_ack) {
+ w->accounted -= w->cumul_ack;
+ w->cumul_ack = tp->mss_cache;
+ } else {
+ w->cumul_ack -= w->accounted;
+ w->accounted = 0;
+ }
+ }
+
+ w->snd_una = tp->snd_una;
+
+ return w->cumul_ack;
+}
+
+static inline u32 westwood_bw_rttmin(const struct tcp_sock *tp)
+{
+ struct westwood *w = tcp_ca(tp);
+ return max_t(u32, (w->bw_est * w->rtt_min) / tp->mss_cache, 2);
+}
+
+/*
+ * TCP Westwood
+ * Here limit is evaluated as Bw estimation*RTTmin (for obtaining it
+ * in packets we use mss_cache). Rttmin is guaranteed to be >= 2
+ * so avoids ever returning 0.
+ */
+static u32 tcp_westwood_cwnd_min(struct tcp_sock *tp)
+{
+ return westwood_bw_rttmin(tp);
+}
+
+static void tcp_westwood_event(struct tcp_sock *tp, enum tcp_ca_event event)
+{
+ struct westwood *w = tcp_ca(tp);
+
+ switch(event) {
+ case CA_EVENT_FAST_ACK:
+ westwood_fast_bw(tp);
+ break;
+
+ case CA_EVENT_COMPLETE_CWR:
+ tp->snd_cwnd = tp->snd_ssthresh = westwood_bw_rttmin(tp);
+ break;
+
+ case CA_EVENT_FRTO:
+ tp->snd_ssthresh = westwood_bw_rttmin(tp);
+ break;
+
+ case CA_EVENT_SLOW_ACK:
+ westwood_update_window(tp);
+ w->bk += westwood_acked_count(tp);
+ w->rtt_min = min(w->rtt, w->rtt_min);
+ break;
+
+ default:
+ /* don't care */
+ break;
+ }
+}
+
+
+/* Extract info for Tcp socket info provided via netlink. */
+static void tcp_westwood_info(struct tcp_sock *tp, u32 ext,
+ struct sk_buff *skb)
+{
+ const struct westwood *ca = tcp_ca(tp);
+ if (ext & (1<<(TCPDIAG_VEGASINFO-1))) {
+ struct rtattr *rta;
+ struct tcpvegas_info *info;
+
+ rta = __RTA_PUT(skb, TCPDIAG_VEGASINFO, sizeof(*info));
+ info = RTA_DATA(rta);
+ info->tcpv_enabled = 1;
+ info->tcpv_rttcnt = 0;
+ info->tcpv_rtt = jiffies_to_usecs(ca->rtt);
+ info->tcpv_minrtt = jiffies_to_usecs(ca->rtt_min);
+ rtattr_failure: ;
+ }
+}
+
+
+static struct tcp_congestion_ops tcp_westwood = {
+ .init = tcp_westwood_init,
+ .ssthresh = tcp_reno_ssthresh,
+ .cong_avoid = tcp_reno_cong_avoid,
+ .min_cwnd = tcp_westwood_cwnd_min,
+ .cwnd_event = tcp_westwood_event,
+ .get_info = tcp_westwood_info,
+ .pkts_acked = tcp_westwood_pkts_acked,
+
+ .owner = THIS_MODULE,
+ .name = "westwood"
+};
+
+static int __init tcp_westwood_register(void)
+{
+ BUG_ON(sizeof(struct westwood) > TCP_CA_PRIV_SIZE);
+ return tcp_register_congestion_control(&tcp_westwood);
+}
+
+static void __exit tcp_westwood_unregister(void)
+{
+ tcp_unregister_congestion_control(&tcp_westwood);
+}
+
+module_init(tcp_westwood_register);
+module_exit(tcp_westwood_unregister);
+
+MODULE_AUTHOR("Stephen Hemminger, Angelo Dell'Aera");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TCP Westwood+");
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 4a6952e3fee..7c24e64b443 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -738,7 +738,7 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
unsigned long amount;
amount = 0;
- spin_lock_irq(&sk->sk_receive_queue.lock);
+ spin_lock_bh(&sk->sk_receive_queue.lock);
skb = skb_peek(&sk->sk_receive_queue);
if (skb != NULL) {
/*
@@ -748,7 +748,7 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
*/
amount = skb->len - sizeof(struct udphdr);
}
- spin_unlock_irq(&sk->sk_receive_queue.lock);
+ spin_unlock_bh(&sk->sk_receive_queue.lock);
return put_user(amount, (int __user *)arg);
}
@@ -848,12 +848,12 @@ csum_copy_err:
/* Clear queue. */
if (flags&MSG_PEEK) {
int clear = 0;
- spin_lock_irq(&sk->sk_receive_queue.lock);
+ spin_lock_bh(&sk->sk_receive_queue.lock);
if (skb == skb_peek(&sk->sk_receive_queue)) {
__skb_unlink(skb, &sk->sk_receive_queue);
clear = 1;
}
- spin_unlock_irq(&sk->sk_receive_queue.lock);
+ spin_unlock_bh(&sk->sk_receive_queue.lock);
if (clear)
kfree_skb(skb);
}
@@ -1334,7 +1334,7 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
struct sk_buff_head *rcvq = &sk->sk_receive_queue;
struct sk_buff *skb;
- spin_lock_irq(&rcvq->lock);
+ spin_lock_bh(&rcvq->lock);
while ((skb = skb_peek(rcvq)) != NULL) {
if (udp_checksum_complete(skb)) {
UDP_INC_STATS_BH(UDP_MIB_INERRORS);
@@ -1345,7 +1345,7 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
break;
}
}
- spin_unlock_irq(&rcvq->lock);
+ spin_unlock_bh(&rcvq->lock);
/* nothing to see, move along */
if (skb == NULL)
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index af2392ae576..66620a95942 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -33,6 +33,7 @@ static void xfrm4_encap(struct sk_buff *skb)
struct dst_entry *dst = skb->dst;
struct xfrm_state *x = dst->xfrm;
struct iphdr *iph, *top_iph;
+ int flags;
iph = skb->nh.iph;
skb->h.ipiph = iph;
@@ -51,10 +52,13 @@ static void xfrm4_encap(struct sk_buff *skb)
/* DS disclosed */
top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos);
- if (x->props.flags & XFRM_STATE_NOECN)
+
+ flags = x->props.flags;
+ if (flags & XFRM_STATE_NOECN)
IP_ECN_clear(top_iph);
- top_iph->frag_off = iph->frag_off & htons(IP_DF);
+ top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
+ 0 : (iph->frag_off & htons(IP_DF));
if (!top_iph->frag_off)
__ip_select_ident(top_iph, dst, 0);
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
index 223a2e83853..050611d7a96 100644
--- a/net/ipv4/xfrm4_state.c
+++ b/net/ipv4/xfrm4_state.c
@@ -7,12 +7,20 @@
*
*/
+#include <net/ip.h>
#include <net/xfrm.h>
#include <linux/pfkeyv2.h>
#include <linux/ipsec.h>
static struct xfrm_state_afinfo xfrm4_state_afinfo;
+static int xfrm4_init_flags(struct xfrm_state *x)
+{
+ if (ipv4_config.no_pmtu_disc)
+ x->props.flags |= XFRM_STATE_NOPMTUDISC;
+ return 0;
+}
+
static void
__xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl,
struct xfrm_tmpl *tmpl,
@@ -109,6 +117,7 @@ __xfrm4_find_acq(u8 mode, u32 reqid, u8 proto,
static struct xfrm_state_afinfo xfrm4_state_afinfo = {
.family = AF_INET,
.lock = RW_LOCK_UNLOCKED,
+ .init_flags = xfrm4_init_flags,
.init_tempsel = __xfrm4_init_tempsel,
.state_lookup = __xfrm4_state_lookup,
.find_acq = __xfrm4_find_acq,
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index 413191f585f..e1fe360ed27 100644
--- a/net/ipv4/xfrm4_tunnel.c
+++ b/net/ipv4/xfrm4_tunnel.c
@@ -84,7 +84,7 @@ static void ipip_err(struct sk_buff *skb, u32 info)
handler->err_handler(skb, &arg);
}
-static int ipip_init_state(struct xfrm_state *x, void *args)
+static int ipip_init_state(struct xfrm_state *x)
{
if (!x->props.mode)
return -EINVAL;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 7744a259269..a54d4ef3fd3 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -57,6 +57,7 @@
#endif
#include <linux/delay.h>
#include <linux/notifier.h>
+#include <linux/string.h>
#include <net/sock.h>
#include <net/snmp.h>
@@ -131,7 +132,7 @@ static void addrconf_leave_anycast(struct inet6_ifaddr *ifp);
static int addrconf_ifdown(struct net_device *dev, int how);
-static void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags);
+static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags);
static void addrconf_dad_timer(unsigned long data);
static void addrconf_dad_completed(struct inet6_ifaddr *ifp);
static void addrconf_rs_timer(unsigned long data);
@@ -372,6 +373,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
ndev->regen_timer.data = (unsigned long) ndev;
if ((dev->flags&IFF_LOOPBACK) ||
dev->type == ARPHRD_TUNNEL ||
+ dev->type == ARPHRD_NONE ||
dev->type == ARPHRD_SIT) {
printk(KERN_INFO
"Disabled Privacy Extensions on device %p(%s)\n",
@@ -491,7 +493,7 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp)
static struct inet6_ifaddr *
ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
- int scope, unsigned flags)
+ int scope, u32 flags)
{
struct inet6_ifaddr *ifa = NULL;
struct rt6_info *rt;
@@ -694,7 +696,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
if (onlink == 0) {
- ip6_del_rt(rt, NULL, NULL);
+ ip6_del_rt(rt, NULL, NULL, NULL);
rt = NULL;
} else if (!(rt->rt6i_flags & RTF_EXPIRES)) {
rt->rt6i_expires = expires;
@@ -1319,7 +1321,7 @@ static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpad
static void
addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev,
- unsigned long expires, unsigned flags)
+ unsigned long expires, u32 flags)
{
struct in6_rtmsg rtmsg;
@@ -1339,7 +1341,7 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev,
if (dev->type == ARPHRD_SIT && (dev->flags&IFF_POINTOPOINT))
rtmsg.rtmsg_flags |= RTF_NONEXTHOP;
- ip6_route_add(&rtmsg, NULL, NULL);
+ ip6_route_add(&rtmsg, NULL, NULL, NULL);
}
/* Create "default" multicast route to the interface */
@@ -1356,7 +1358,7 @@ static void addrconf_add_mroute(struct net_device *dev)
rtmsg.rtmsg_ifindex = dev->ifindex;
rtmsg.rtmsg_flags = RTF_UP;
rtmsg.rtmsg_type = RTMSG_NEWROUTE;
- ip6_route_add(&rtmsg, NULL, NULL);
+ ip6_route_add(&rtmsg, NULL, NULL, NULL);
}
static void sit_route_add(struct net_device *dev)
@@ -1373,7 +1375,7 @@ static void sit_route_add(struct net_device *dev)
rtmsg.rtmsg_flags = RTF_UP|RTF_NONEXTHOP;
rtmsg.rtmsg_ifindex = dev->ifindex;
- ip6_route_add(&rtmsg, NULL, NULL);
+ ip6_route_add(&rtmsg, NULL, NULL, NULL);
}
static void addrconf_add_lroute(struct net_device *dev)
@@ -1466,7 +1468,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
if (rt->rt6i_flags&RTF_EXPIRES) {
if (valid_lft == 0) {
- ip6_del_rt(rt, NULL, NULL);
+ ip6_del_rt(rt, NULL, NULL, NULL);
rt = NULL;
} else {
rt->rt6i_expires = rt_expires;
@@ -2228,7 +2230,7 @@ out:
/*
* Duplicate Address Detection
*/
-static void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags)
+static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
{
struct inet6_dev *idev = ifp->idev;
struct net_device *dev = idev->dev;
@@ -2621,15 +2623,14 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
}
static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
- u32 pid, u32 seq, int event)
+ u32 pid, u32 seq, int event, unsigned int flags)
{
struct ifaddrmsg *ifm;
struct nlmsghdr *nlh;
struct ifa_cacheinfo ci;
unsigned char *b = skb->tail;
- nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ifm));
- if (pid) nlh->nlmsg_flags |= NLM_F_MULTI;
+ nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags);
ifm = NLMSG_DATA(nlh);
ifm->ifa_family = AF_INET6;
ifm->ifa_prefixlen = ifa->prefix_len;
@@ -2671,15 +2672,14 @@ rtattr_failure:
}
static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
- u32 pid, u32 seq, int event)
+ u32 pid, u32 seq, int event, u16 flags)
{
struct ifaddrmsg *ifm;
struct nlmsghdr *nlh;
struct ifa_cacheinfo ci;
unsigned char *b = skb->tail;
- nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ifm));
- if (pid) nlh->nlmsg_flags |= NLM_F_MULTI;
+ nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags);
ifm = NLMSG_DATA(nlh);
ifm->ifa_family = AF_INET6;
ifm->ifa_prefixlen = 128;
@@ -2708,15 +2708,14 @@ rtattr_failure:
}
static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca,
- u32 pid, u32 seq, int event)
+ u32 pid, u32 seq, int event, unsigned int flags)
{
struct ifaddrmsg *ifm;
struct nlmsghdr *nlh;
struct ifa_cacheinfo ci;
unsigned char *b = skb->tail;
- nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ifm));
- if (pid) nlh->nlmsg_flags |= NLM_F_MULTI;
+ nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags);
ifm = NLMSG_DATA(nlh);
ifm->ifa_family = AF_INET6;
ifm->ifa_prefixlen = 128;
@@ -2785,7 +2784,8 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
continue;
if ((err = inet6_fill_ifaddr(skb, ifa,
NETLINK_CB(cb->skb).pid,
- cb->nlh->nlmsg_seq, RTM_NEWADDR)) <= 0)
+ cb->nlh->nlmsg_seq, RTM_NEWADDR,
+ NLM_F_MULTI)) <= 0)
goto done;
}
/* temp addr */
@@ -2796,7 +2796,8 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
continue;
if ((err = inet6_fill_ifaddr(skb, ifa,
NETLINK_CB(cb->skb).pid,
- cb->nlh->nlmsg_seq, RTM_NEWADDR)) <= 0)
+ cb->nlh->nlmsg_seq, RTM_NEWADDR,
+ NLM_F_MULTI)) <= 0)
goto done;
}
#endif
@@ -2809,7 +2810,8 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
continue;
if ((err = inet6_fill_ifmcaddr(skb, ifmca,
NETLINK_CB(cb->skb).pid,
- cb->nlh->nlmsg_seq, RTM_GETMULTICAST)) <= 0)
+ cb->nlh->nlmsg_seq, RTM_GETMULTICAST,
+ NLM_F_MULTI)) <= 0)
goto done;
}
break;
@@ -2821,7 +2823,8 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
continue;
if ((err = inet6_fill_ifacaddr(skb, ifaca,
NETLINK_CB(cb->skb).pid,
- cb->nlh->nlmsg_seq, RTM_GETANYCAST)) <= 0)
+ cb->nlh->nlmsg_seq, RTM_GETANYCAST,
+ NLM_F_MULTI)) <= 0)
goto done;
}
break;
@@ -2871,7 +2874,7 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
netlink_set_err(rtnl, 0, RTMGRP_IPV6_IFADDR, ENOBUFS);
return;
}
- if (inet6_fill_ifaddr(skb, ifa, 0, 0, event) < 0) {
+ if (inet6_fill_ifaddr(skb, ifa, current->pid, 0, event, 0) < 0) {
kfree_skb(skb);
netlink_set_err(rtnl, 0, RTMGRP_IPV6_IFADDR, EINVAL);
return;
@@ -2906,7 +2909,7 @@ static void inline ipv6_store_devconf(struct ipv6_devconf *cnf,
}
static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
- u32 pid, u32 seq, int event)
+ u32 pid, u32 seq, int event, unsigned int flags)
{
struct net_device *dev = idev->dev;
__s32 *array = NULL;
@@ -2917,8 +2920,7 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
__u32 mtu = dev->mtu;
struct ifla_cacheinfo ci;
- nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*r));
- if (pid) nlh->nlmsg_flags |= NLM_F_MULTI;
+ nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags);
r = NLMSG_DATA(nlh);
r->ifi_family = AF_INET6;
r->ifi_type = dev->type;
@@ -2985,7 +2987,7 @@ static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
if ((idev = in6_dev_get(dev)) == NULL)
continue;
err = inet6_fill_ifinfo(skb, idev, NETLINK_CB(cb->skb).pid,
- cb->nlh->nlmsg_seq, RTM_NEWLINK);
+ cb->nlh->nlmsg_seq, RTM_NEWLINK, NLM_F_MULTI);
in6_dev_put(idev);
if (err <= 0)
break;
@@ -3007,7 +3009,7 @@ void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
netlink_set_err(rtnl, 0, RTMGRP_IPV6_IFINFO, ENOBUFS);
return;
}
- if (inet6_fill_ifinfo(skb, idev, 0, 0, event) < 0) {
+ if (inet6_fill_ifinfo(skb, idev, current->pid, 0, event, 0) < 0) {
kfree_skb(skb);
netlink_set_err(rtnl, 0, RTMGRP_IPV6_IFINFO, EINVAL);
return;
@@ -3017,18 +3019,15 @@ void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
}
static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev,
- struct prefix_info *pinfo, u32 pid, u32 seq, int event)
+ struct prefix_info *pinfo, u32 pid, u32 seq,
+ int event, unsigned int flags)
{
struct prefixmsg *pmsg;
struct nlmsghdr *nlh;
unsigned char *b = skb->tail;
struct prefix_cacheinfo ci;
- nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*pmsg));
-
- if (pid)
- nlh->nlmsg_flags |= NLM_F_MULTI;
-
+ nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*pmsg), flags);
pmsg = NLMSG_DATA(nlh);
pmsg->prefix_family = AF_INET6;
pmsg->prefix_ifindex = idev->dev->ifindex;
@@ -3067,7 +3066,7 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev,
netlink_set_err(rtnl, 0, RTMGRP_IPV6_PREFIX, ENOBUFS);
return;
}
- if (inet6_fill_prefix(skb, idev, pinfo, 0, 0, event) < 0) {
+ if (inet6_fill_prefix(skb, idev, pinfo, current->pid, 0, event, 0) < 0) {
kfree_skb(skb);
netlink_set_err(rtnl, 0, RTMGRP_IPV6_PREFIX, EINVAL);
return;
@@ -3096,7 +3095,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
switch (event) {
case RTM_NEWADDR:
dst_hold(&ifp->rt->u.dst);
- if (ip6_ins_rt(ifp->rt, NULL, NULL))
+ if (ip6_ins_rt(ifp->rt, NULL, NULL, NULL))
dst_release(&ifp->rt->u.dst);
if (ifp->idev->cnf.forwarding)
addrconf_join_anycast(ifp);
@@ -3106,7 +3105,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
addrconf_leave_anycast(ifp);
addrconf_leave_solict(ifp->idev, &ifp->addr);
dst_hold(&ifp->rt->u.dst);
- if (ip6_del_rt(ifp->rt, NULL, NULL))
+ if (ip6_del_rt(ifp->rt, NULL, NULL, NULL))
dst_free(&ifp->rt->u.dst);
else
dst_release(&ifp->rt->u.dst);
@@ -3439,7 +3438,7 @@ static void addrconf_sysctl_register(struct inet6_dev *idev, struct ipv6_devconf
* by sysctl and we wouldn't want anyone to change it under our feet
* (see SIOCSIFNAME).
*/
- dev_name = net_sysctl_strdup(dev_name);
+ dev_name = kstrdup(dev_name, GFP_KERNEL);
if (!dev_name)
goto free;
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index e3ecf626cbf..986fdfdccbc 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -339,7 +339,7 @@ static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
xfrm_state_put(x);
}
-static int ah6_init_state(struct xfrm_state *x, void *args)
+static int ah6_init_state(struct xfrm_state *x)
{
struct ah_data *ahp = NULL;
struct xfrm_algo_desc *aalg_desc;
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index 5d22ca3cca2..6b729404723 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -337,7 +337,7 @@ int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr)
write_unlock_bh(&idev->lock);
dst_hold(&rt->u.dst);
- if (ip6_ins_rt(rt, NULL, NULL))
+ if (ip6_ins_rt(rt, NULL, NULL, NULL))
dst_release(&rt->u.dst);
addrconf_join_solict(dev, &aca->aca_addr);
@@ -380,7 +380,7 @@ int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr)
addrconf_leave_solict(idev, &aca->aca_addr);
dst_hold(&aca->aca_rt->u.dst);
- if (ip6_del_rt(aca->aca_rt, NULL, NULL))
+ if (ip6_del_rt(aca->aca_rt, NULL, NULL, NULL))
dst_free(&aca->aca_rt->u.dst);
else
dst_release(&aca->aca_rt->u.dst);
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 65b9375df57..5229365cd8b 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -353,14 +353,14 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
err = copied;
/* Reset and regenerate socket error */
- spin_lock_irq(&sk->sk_error_queue.lock);
+ spin_lock_bh(&sk->sk_error_queue.lock);
sk->sk_err = 0;
if ((skb2 = skb_peek(&sk->sk_error_queue)) != NULL) {
sk->sk_err = SKB_EXT_ERR(skb2)->ee.ee_errno;
- spin_unlock_irq(&sk->sk_error_queue.lock);
+ spin_unlock_bh(&sk->sk_error_queue.lock);
sk->sk_error_report(sk);
} else {
- spin_unlock_irq(&sk->sk_error_queue.lock);
+ spin_unlock_bh(&sk->sk_error_queue.lock);
}
out_free_skb:
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index be7095d6bab..324db62515a 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -296,7 +296,7 @@ static void esp6_destroy(struct xfrm_state *x)
kfree(esp);
}
-static int esp6_init_state(struct xfrm_state *x, void *args)
+static int esp6_init_state(struct xfrm_state *x)
{
struct esp_data *esp = NULL;
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 8e0f569b883..ff3ec9822e3 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -277,8 +277,8 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
{
struct inet6_dev *idev = NULL;
struct ipv6hdr *hdr = skb->nh.ipv6h;
- struct sock *sk = icmpv6_socket->sk;
- struct ipv6_pinfo *np = inet6_sk(sk);
+ struct sock *sk;
+ struct ipv6_pinfo *np;
struct in6_addr *saddr = NULL;
struct dst_entry *dst;
struct icmp6hdr tmp_hdr;
@@ -358,6 +358,9 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
if (icmpv6_xmit_lock())
return;
+ sk = icmpv6_socket->sk;
+ np = inet6_sk(sk);
+
if (!icmpv6_xrlim_allow(sk, type, &fl))
goto out;
@@ -423,9 +426,9 @@ out:
static void icmpv6_echo_reply(struct sk_buff *skb)
{
- struct sock *sk = icmpv6_socket->sk;
+ struct sock *sk;
struct inet6_dev *idev;
- struct ipv6_pinfo *np = inet6_sk(sk);
+ struct ipv6_pinfo *np;
struct in6_addr *saddr = NULL;
struct icmp6hdr *icmph = (struct icmp6hdr *) skb->h.raw;
struct icmp6hdr tmp_hdr;
@@ -454,6 +457,9 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
if (icmpv6_xmit_lock())
return;
+ sk = icmpv6_socket->sk;
+ np = inet6_sk(sk);
+
if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
fl.oif = np->mcast_oif;
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 405740b75ab..1b354aa9793 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -394,7 +394,7 @@ insert_above:
*/
static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
- struct nlmsghdr *nlh)
+ struct nlmsghdr *nlh, struct netlink_skb_parms *req)
{
struct rt6_info *iter = NULL;
struct rt6_info **ins;
@@ -449,7 +449,7 @@ out:
*ins = rt;
rt->rt6i_node = fn;
atomic_inc(&rt->rt6i_ref);
- inet6_rt_notify(RTM_NEWROUTE, rt, nlh);
+ inet6_rt_notify(RTM_NEWROUTE, rt, nlh, req);
rt6_stats.fib_rt_entries++;
if ((fn->fn_flags & RTN_RTINFO) == 0) {
@@ -479,7 +479,8 @@ void fib6_force_start_gc(void)
* with source addr info in sub-trees
*/
-int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
+int fib6_add(struct fib6_node *root, struct rt6_info *rt,
+ struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req)
{
struct fib6_node *fn;
int err = -ENOMEM;
@@ -552,7 +553,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nlmsghdr *nlh,
}
#endif
- err = fib6_add_rt2node(fn, rt, nlh);
+ err = fib6_add_rt2node(fn, rt, nlh, req);
if (err == 0) {
fib6_start_gc(rt);
@@ -859,7 +860,7 @@ static struct fib6_node * fib6_repair_tree(struct fib6_node *fn)
}
static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
- struct nlmsghdr *nlh, void *_rtattr)
+ struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req)
{
struct fib6_walker_t *w;
struct rt6_info *rt = *rtp;
@@ -915,11 +916,11 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
if (atomic_read(&rt->rt6i_ref) != 1) BUG();
}
- inet6_rt_notify(RTM_DELROUTE, rt, nlh);
+ inet6_rt_notify(RTM_DELROUTE, rt, nlh, req);
rt6_release(rt);
}
-int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
+int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req)
{
struct fib6_node *fn = rt->rt6i_node;
struct rt6_info **rtp;
@@ -944,7 +945,7 @@ int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->u.next) {
if (*rtp == rt) {
- fib6_del_route(fn, rtp, nlh, _rtattr);
+ fib6_del_route(fn, rtp, nlh, _rtattr, req);
return 0;
}
}
@@ -1073,7 +1074,7 @@ static int fib6_clean_node(struct fib6_walker_t *w)
res = c->func(rt, c->arg);
if (res < 0) {
w->leaf = rt;
- res = fib6_del(rt, NULL, NULL);
+ res = fib6_del(rt, NULL, NULL, NULL);
if (res) {
#if RT6_DEBUG >= 2
printk(KERN_DEBUG "fib6_clean_node: del failed: rt=%p@%p err=%d\n", rt, rt->rt6i_node, res);
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index a93f6dc5197..0e5f7499deb 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -535,10 +535,12 @@ release:
if (err)
goto done;
- /* Do not check for fault */
- if (!freq.flr_label)
- copy_to_user(&((struct in6_flowlabel_req __user *) optval)->flr_label,
- &fl->label, sizeof(fl->label));
+ if (!freq.flr_label) {
+ if (copy_to_user(&((struct in6_flowlabel_req __user *) optval)->flr_label,
+ &fl->label, sizeof(fl->label))) {
+ /* Intentionally ignore fault. */
+ }
+ }
sfl1->fl = fl;
sfl1->next = np->ipv6_fl_list;
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 0f0711417c9..06e7cdaeedc 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -484,9 +484,6 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from)
to->nf_bridge = from->nf_bridge;
nf_bridge_get(to->nf_bridge);
#endif
-#ifdef CONFIG_NETFILTER_DEBUG
- to->nf_debug = from->nf_debug;
-#endif
#endif
}
@@ -552,13 +549,17 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
skb_headroom(frag) < hlen)
goto slow_path;
- /* Correct socket ownership. */
- if (frag->sk == NULL)
- goto slow_path;
-
/* Partially cloned skb? */
if (skb_shared(frag))
goto slow_path;
+
+ BUG_ON(frag->sk);
+ if (skb->sk) {
+ sock_hold(skb->sk);
+ frag->sk = skb->sk;
+ frag->destructor = sock_wfree;
+ skb->truesize -= frag->truesize;
+ }
}
err = 0;
@@ -1116,12 +1117,10 @@ int ip6_push_pending_frames(struct sock *sk)
tail_skb = &(tmp_skb->next);
skb->len += tmp_skb->len;
skb->data_len += tmp_skb->len;
-#if 0 /* Logically correct, but useless work, ip_fragment() will have to undo */
skb->truesize += tmp_skb->truesize;
__sock_put(tmp_skb->sk);
tmp_skb->destructor = NULL;
tmp_skb->sk = NULL;
-#endif
}
ipv6_addr_copy(final_dst, &fl->fl6_dst);
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 3b1c9fa184a..ba3b0c267f7 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -882,6 +882,7 @@ ip6ip6_tnl_change(struct ip6_tnl *t, struct ip6_tnl_parm *p)
t->parms.hop_limit = p->hop_limit;
t->parms.encap_limit = p->encap_limit;
t->parms.flowinfo = p->flowinfo;
+ t->parms.link = p->link;
ip6ip6_tnl_link_config(t);
return 0;
}
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 6cde5310cd7..423feb46ccc 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -234,14 +234,9 @@ static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x)
t->props.mode = 1;
memcpy(t->props.saddr.a6, x->props.saddr.a6, sizeof(struct in6_addr));
- t->type = xfrm_get_type(IPPROTO_IPV6, t->props.family);
- if (t->type == NULL)
+ if (xfrm_init_state(t))
goto error;
- if (t->type->init_state(t, NULL))
- goto error;
-
- t->km.state = XFRM_STATE_VALID;
atomic_set(&t->tunnel_users, 1);
out:
@@ -420,7 +415,7 @@ static void ipcomp6_destroy(struct xfrm_state *x)
xfrm6_tunnel_free_spi((xfrm_address_t *)&x->props.saddr);
}
-static int ipcomp6_init_state(struct xfrm_state *x, void *args)
+static int ipcomp6_init_state(struct xfrm_state *x)
{
int err;
struct ipcomp_data *ipcd;
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 279ab86be66..f3ef4c38d31 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -423,11 +423,12 @@ done:
psin6 = (struct sockaddr_in6 *)&greqs.gsr_group;
retv = ipv6_sock_mc_join(sk, greqs.gsr_interface,
&psin6->sin6_addr);
- if (retv)
+ /* prior join w/ different source is ok */
+ if (retv && retv != -EADDRINUSE)
break;
omode = MCAST_INCLUDE;
add = 1;
- } else /*IP_DROP_SOURCE_MEMBERSHIP */ {
+ } else /* MCAST_LEAVE_SOURCE_GROUP */ {
omode = MCAST_INCLUDE;
add = 0;
}
diff --git a/net/ipv6/ipv6_syms.c b/net/ipv6/ipv6_syms.c
index 2f4c91ddc9a..5ade5a5d199 100644
--- a/net/ipv6/ipv6_syms.c
+++ b/net/ipv6/ipv6_syms.c
@@ -37,5 +37,4 @@ EXPORT_SYMBOL(in6_dev_finish_destroy);
EXPORT_SYMBOL(xfrm6_rcv);
#endif
EXPORT_SYMBOL(rt6_lookup);
-EXPORT_SYMBOL(fl6_sock_lookup);
EXPORT_SYMBOL(ipv6_push_nfrag_opts);
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 393b6e6f50a..562fcd14fde 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -188,6 +188,16 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr)
if (!ipv6_addr_is_multicast(addr))
return -EINVAL;
+ read_lock_bh(&ipv6_sk_mc_lock);
+ for (mc_lst=np->ipv6_mc_list; mc_lst; mc_lst=mc_lst->next) {
+ if ((ifindex == 0 || mc_lst->ifindex == ifindex) &&
+ ipv6_addr_equal(&mc_lst->addr, addr)) {
+ read_unlock_bh(&ipv6_sk_mc_lock);
+ return -EADDRINUSE;
+ }
+ }
+ read_unlock_bh(&ipv6_sk_mc_lock);
+
mc_lst = sock_kmalloc(sk, sizeof(struct ipv6_mc_socklist), GFP_KERNEL);
if (mc_lst == NULL)
@@ -349,6 +359,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
struct ipv6_pinfo *inet6 = inet6_sk(sk);
struct ip6_sf_socklist *psl;
int i, j, rv;
+ int leavegroup = 0;
int err;
if (pgsr->gsr_group.ss_family != AF_INET6 ||
@@ -368,6 +379,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
err = -EADDRNOTAVAIL;
+ read_lock_bh(&ipv6_sk_mc_lock);
for (pmc=inet6->ipv6_mc_list; pmc; pmc=pmc->next) {
if (pgsr->gsr_interface && pmc->ifindex != pgsr->gsr_interface)
continue;
@@ -401,6 +413,12 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
if (rv) /* source not found */
goto done;
+ /* special case - (INCLUDE, empty) == LEAVE_GROUP */
+ if (psl->sl_count == 1 && omode == MCAST_INCLUDE) {
+ leavegroup = 1;
+ goto done;
+ }
+
/* update the interface filter */
ip6_mc_del_src(idev, group, omode, 1, source, 1);
@@ -453,9 +471,12 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
/* update the interface list */
ip6_mc_add_src(idev, group, omode, 1, source, 1);
done:
+ read_unlock_bh(&ipv6_sk_mc_lock);
read_unlock_bh(&idev->lock);
in6_dev_put(idev);
dev_put(dev);
+ if (leavegroup)
+ return ipv6_sock_mc_drop(sk, pgsr->gsr_interface, group);
return err;
}
@@ -1280,15 +1301,6 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size)
return NULL;
skb_reserve(skb, LL_RESERVED_SPACE(dev));
- if (dev->hard_header) {
- unsigned char ha[MAX_ADDR_LEN];
-
- ndisc_mc_map(&mld2_all_mcr, ha, dev, 1);
- if (dev->hard_header(skb, dev, ETH_P_IPV6,ha,NULL,size) < 0) {
- kfree_skb(skb);
- return NULL;
- }
- }
if (ipv6_get_lladdr(dev, &addr_buf)) {
/* <draft-ietf-magma-mld-source-05.txt>:
@@ -1312,6 +1324,30 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size)
return skb;
}
+static inline int mld_dev_queue_xmit2(struct sk_buff *skb)
+{
+ struct net_device *dev = skb->dev;
+
+ if (dev->hard_header) {
+ unsigned char ha[MAX_ADDR_LEN];
+ int err;
+
+ ndisc_mc_map(&skb->nh.ipv6h->daddr, ha, dev, 1);
+ err = dev->hard_header(skb, dev, ETH_P_IPV6, ha, NULL, skb->len);
+ if (err < 0) {
+ kfree_skb(skb);
+ return err;
+ }
+ }
+ return dev_queue_xmit(skb);
+}
+
+static inline int mld_dev_queue_xmit(struct sk_buff *skb)
+{
+ return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb, NULL, skb->dev,
+ mld_dev_queue_xmit2);
+}
+
static void mld_sendpack(struct sk_buff *skb)
{
struct ipv6hdr *pip6 = skb->nh.ipv6h;
@@ -1329,7 +1365,7 @@ static void mld_sendpack(struct sk_buff *skb)
pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen,
IPPROTO_ICMPV6, csum_partial(skb->h.raw, mldlen, 0));
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev,
- dev_queue_xmit);
+ mld_dev_queue_xmit);
if (!err) {
ICMP6_INC_STATS(idev,ICMP6_MIB_OUTMSGS);
IP6_INC_STATS(IPSTATS_MIB_OUTMCASTPKTS);
@@ -1635,12 +1671,6 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
}
skb_reserve(skb, LL_RESERVED_SPACE(dev));
- if (dev->hard_header) {
- unsigned char ha[MAX_ADDR_LEN];
- ndisc_mc_map(snd_addr, ha, dev, 1);
- if (dev->hard_header(skb, dev, ETH_P_IPV6, ha, NULL, full_len) < 0)
- goto out;
- }
if (ipv6_get_lladdr(dev, &addr_buf)) {
/* <draft-ietf-magma-mld-source-05.txt>:
@@ -1668,7 +1698,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
idev = in6_dev_get(skb->dev);
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev,
- dev_queue_xmit);
+ mld_dev_queue_xmit);
if (!err) {
if (type == ICMPV6_MGM_REDUCTION)
ICMP6_INC_STATS(idev, ICMP6_MIB_OUTGROUPMEMBREDUCTIONS);
@@ -1682,10 +1712,6 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
if (likely(idev != NULL))
in6_dev_put(idev);
return;
-
-out:
- IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS);
- kfree_skb(skb);
}
static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode,
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 7c291f4e9ed..7ae72d4c9bd 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -955,7 +955,7 @@ static void ndisc_recv_na(struct sk_buff *skb)
struct rt6_info *rt;
rt = rt6_get_dflt_router(saddr, dev);
if (rt)
- ip6_del_rt(rt, NULL, NULL);
+ ip6_del_rt(rt, NULL, NULL, NULL);
}
out:
@@ -1096,7 +1096,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
if (rt && lifetime == 0) {
neigh_clone(neigh);
- ip6_del_rt(rt, NULL, NULL);
+ ip6_del_rt(rt, NULL, NULL, NULL);
rt = NULL;
}
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index c735276fdd5..73034511c8d 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -71,7 +71,6 @@ static DECLARE_MUTEX(ip6t_mutex);
/* Must have mutex */
#define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0)
#define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0)
-#include <linux/netfilter_ipv4/lockhelp.h>
#include <linux/netfilter_ipv4/listhelp.h>
#if 0
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index bfc3d0185d1..c44685e391b 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -366,8 +366,6 @@ ip6t_log_packet(unsigned int hooknum,
const char *level_string,
const char *prefix)
{
- struct ipv6hdr *ipv6h = skb->nh.ipv6h;
-
spin_lock_bh(&log_lock);
printk(level_string);
printk("%sIN=%s OUT=%s ",
@@ -377,39 +375,25 @@ ip6t_log_packet(unsigned int hooknum,
if (in && !out) {
/* MAC logging for input chain only. */
printk("MAC=");
- if (skb->dev && skb->dev->hard_header_len && skb->mac.raw != (void*)ipv6h) {
- if (skb->dev->type != ARPHRD_SIT){
- int i;
- unsigned char *p = skb->mac.raw;
- for (i = 0; i < skb->dev->hard_header_len; i++,p++)
- printk("%02x%c", *p,
- i==skb->dev->hard_header_len - 1
- ? ' ':':');
- } else {
- int i;
- unsigned char *p = skb->mac.raw;
- if ( p - (ETH_ALEN*2+2) > skb->head ){
- p -= (ETH_ALEN+2);
- for (i = 0; i < (ETH_ALEN); i++,p++)
- printk("%02x%s", *p,
- i == ETH_ALEN-1 ? "->" : ":");
- p -= (ETH_ALEN*2);
- for (i = 0; i < (ETH_ALEN); i++,p++)
- printk("%02x%c", *p,
- i == ETH_ALEN-1 ? ' ' : ':');
- }
-
- if ((skb->dev->addr_len == 4) &&
- skb->dev->hard_header_len > 20){
- printk("TUNNEL=");
- p = skb->mac.raw + 12;
- for (i = 0; i < 4; i++,p++)
- printk("%3d%s", *p,
- i == 3 ? "->" : ".");
- for (i = 0; i < 4; i++,p++)
- printk("%3d%c", *p,
- i == 3 ? ' ' : '.');
- }
+ if (skb->dev && skb->dev->hard_header_len &&
+ skb->mac.raw != skb->nh.raw) {
+ unsigned char *p = skb->mac.raw;
+ int i;
+
+ if (skb->dev->type == ARPHRD_SIT &&
+ (p -= ETH_HLEN) < skb->head)
+ p = NULL;
+
+ if (p != NULL)
+ for (i = 0; i < skb->dev->hard_header_len; i++)
+ printk("%02x", p[i]);
+ printk(" ");
+
+ if (skb->dev->type == ARPHRD_SIT) {
+ struct iphdr *iph = (struct iphdr *)skb->mac.raw;
+ printk("TUNNEL=%u.%u.%u.%u->%u.%u.%u.%u ",
+ NIPQUAD(iph->saddr),
+ NIPQUAD(iph->daddr));
}
} else
printk(" ");
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index 71407beaf79..c2982efd14a 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -129,13 +129,15 @@ static struct nf_hook_ops ip6t_ops[] = {
.hook = ip6t_hook,
.pf = PF_INET6,
.hooknum = NF_IP6_PRE_ROUTING,
- .priority = NF_IP6_PRI_FIRST
+ .priority = NF_IP6_PRI_FIRST,
+ .owner = THIS_MODULE,
},
{
.hook = ip6t_hook,
.pf = PF_INET6,
.hooknum = NF_IP6_LOCAL_OUT,
- .priority = NF_IP6_PRI_FIRST
+ .priority = NF_IP6_PRI_FIRST,
+ .owner = THIS_MODULE,
},
};
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 617645bc5ed..e2b848ec985 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -434,12 +434,12 @@ csum_copy_err:
/* Clear queue. */
if (flags&MSG_PEEK) {
int clear = 0;
- spin_lock_irq(&sk->sk_receive_queue.lock);
+ spin_lock_bh(&sk->sk_receive_queue.lock);
if (skb == skb_peek(&sk->sk_receive_queue)) {
__skb_unlink(skb, &sk->sk_receive_queue);
clear = 1;
}
- spin_unlock_irq(&sk->sk_receive_queue.lock);
+ spin_unlock_bh(&sk->sk_receive_queue.lock);
if (clear)
kfree_skb(skb);
}
@@ -971,11 +971,11 @@ static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg)
struct sk_buff *skb;
int amount = 0;
- spin_lock_irq(&sk->sk_receive_queue.lock);
+ spin_lock_bh(&sk->sk_receive_queue.lock);
skb = skb_peek(&sk->sk_receive_queue);
if (skb != NULL)
amount = skb->tail - skb->h.raw;
- spin_unlock_irq(&sk->sk_receive_queue.lock);
+ spin_unlock_bh(&sk->sk_receive_queue.lock);
return put_user(amount, (int __user *)arg);
}
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 3bf8a0254f8..878789b3122 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -384,12 +384,13 @@ struct rt6_info *rt6_lookup(struct in6_addr *daddr, struct in6_addr *saddr,
be destroyed.
*/
-int ip6_ins_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
+int ip6_ins_rt(struct rt6_info *rt, struct nlmsghdr *nlh,
+ void *_rtattr, struct netlink_skb_parms *req)
{
int err;
write_lock_bh(&rt6_lock);
- err = fib6_add(&ip6_routing_table, rt, nlh, _rtattr);
+ err = fib6_add(&ip6_routing_table, rt, nlh, _rtattr, req);
write_unlock_bh(&rt6_lock);
return err;
@@ -400,7 +401,7 @@ int ip6_ins_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
*/
static struct rt6_info *rt6_cow(struct rt6_info *ort, struct in6_addr *daddr,
- struct in6_addr *saddr)
+ struct in6_addr *saddr, struct netlink_skb_parms *req)
{
int err;
struct rt6_info *rt;
@@ -432,7 +433,7 @@ static struct rt6_info *rt6_cow(struct rt6_info *ort, struct in6_addr *daddr,
dst_hold(&rt->u.dst);
- err = ip6_ins_rt(rt, NULL, NULL);
+ err = ip6_ins_rt(rt, NULL, NULL, req);
if (err == 0)
return rt;
@@ -491,7 +492,8 @@ restart:
read_unlock_bh(&rt6_lock);
nrt = rt6_cow(rt, &skb->nh.ipv6h->daddr,
- &skb->nh.ipv6h->saddr);
+ &skb->nh.ipv6h->saddr,
+ &NETLINK_CB(skb));
dst_release(&rt->u.dst);
rt = nrt;
@@ -551,7 +553,7 @@ restart:
dst_hold(&rt->u.dst);
read_unlock_bh(&rt6_lock);
- nrt = rt6_cow(rt, &fl->fl6_dst, &fl->fl6_src);
+ nrt = rt6_cow(rt, &fl->fl6_dst, &fl->fl6_src, NULL);
dst_release(&rt->u.dst);
rt = nrt;
@@ -598,7 +600,7 @@ static struct dst_entry *ip6_negative_advice(struct dst_entry *dst)
if (rt) {
if (rt->rt6i_flags & RTF_CACHE)
- ip6_del_rt(rt, NULL, NULL);
+ ip6_del_rt(rt, NULL, NULL, NULL);
else
dst_release(dst);
}
@@ -787,7 +789,8 @@ int ipv6_get_hoplimit(struct net_device *dev)
*
*/
-int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr)
+int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh,
+ void *_rtattr, struct netlink_skb_parms *req)
{
int err;
struct rtmsg *r;
@@ -974,7 +977,7 @@ install_route:
rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst));
rt->u.dst.dev = dev;
rt->rt6i_idev = idev;
- return ip6_ins_rt(rt, nlh, _rtattr);
+ return ip6_ins_rt(rt, nlh, _rtattr, req);
out:
if (dev)
@@ -986,7 +989,7 @@ out:
return err;
}
-int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
+int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req)
{
int err;
@@ -994,7 +997,7 @@ int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
rt6_reset_dflt_pointer(NULL);
- err = fib6_del(rt, nlh, _rtattr);
+ err = fib6_del(rt, nlh, _rtattr, req);
dst_release(&rt->u.dst);
write_unlock_bh(&rt6_lock);
@@ -1002,7 +1005,7 @@ int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
return err;
}
-static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr)
+static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req)
{
struct fib6_node *fn;
struct rt6_info *rt;
@@ -1029,7 +1032,7 @@ static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_r
dst_hold(&rt->u.dst);
read_unlock_bh(&rt6_lock);
- return ip6_del_rt(rt, nlh, _rtattr);
+ return ip6_del_rt(rt, nlh, _rtattr, req);
}
}
read_unlock_bh(&rt6_lock);
@@ -1136,11 +1139,11 @@ source_ok:
nrt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev);
nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&nrt->u.dst));
- if (ip6_ins_rt(nrt, NULL, NULL))
+ if (ip6_ins_rt(nrt, NULL, NULL, NULL))
goto out;
if (rt->rt6i_flags&RTF_CACHE) {
- ip6_del_rt(rt, NULL, NULL);
+ ip6_del_rt(rt, NULL, NULL, NULL);
return;
}
@@ -1204,7 +1207,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
2. It is gatewayed route or NONEXTHOP route. Action: clone it.
*/
if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) {
- nrt = rt6_cow(rt, daddr, saddr);
+ nrt = rt6_cow(rt, daddr, saddr, NULL);
if (!nrt->u.dst.error) {
nrt->u.dst.metrics[RTAX_MTU-1] = pmtu;
if (allfrag)
@@ -1232,7 +1235,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
nrt->u.dst.metrics[RTAX_MTU-1] = pmtu;
if (allfrag)
nrt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
- ip6_ins_rt(nrt, NULL, NULL);
+ ip6_ins_rt(nrt, NULL, NULL, NULL);
}
out:
@@ -1305,7 +1308,7 @@ struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr,
rtmsg.rtmsg_ifindex = dev->ifindex;
- ip6_route_add(&rtmsg, NULL, NULL);
+ ip6_route_add(&rtmsg, NULL, NULL, NULL);
return rt6_get_dflt_router(gwaddr, dev);
}
@@ -1323,7 +1326,7 @@ restart:
read_unlock_bh(&rt6_lock);
- ip6_del_rt(rt, NULL, NULL);
+ ip6_del_rt(rt, NULL, NULL, NULL);
goto restart;
}
@@ -1349,10 +1352,10 @@ int ipv6_route_ioctl(unsigned int cmd, void __user *arg)
rtnl_lock();
switch (cmd) {
case SIOCADDRT:
- err = ip6_route_add(&rtmsg, NULL, NULL);
+ err = ip6_route_add(&rtmsg, NULL, NULL, NULL);
break;
case SIOCDELRT:
- err = ip6_route_del(&rtmsg, NULL, NULL);
+ err = ip6_route_del(&rtmsg, NULL, NULL, NULL);
break;
default:
err = -EINVAL;
@@ -1546,7 +1549,7 @@ int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
if (inet6_rtm_to_rtmsg(r, arg, &rtmsg))
return -EINVAL;
- return ip6_route_del(&rtmsg, nlh, arg);
+ return ip6_route_del(&rtmsg, nlh, arg, &NETLINK_CB(skb));
}
int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
@@ -1556,7 +1559,7 @@ int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
if (inet6_rtm_to_rtmsg(r, arg, &rtmsg))
return -EINVAL;
- return ip6_route_add(&rtmsg, nlh, arg);
+ return ip6_route_add(&rtmsg, nlh, arg, &NETLINK_CB(skb));
}
struct rt6_rtnl_dump_arg
@@ -1566,11 +1569,9 @@ struct rt6_rtnl_dump_arg
};
static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
- struct in6_addr *dst,
- struct in6_addr *src,
- int iif,
- int type, u32 pid, u32 seq,
- struct nlmsghdr *in_nlh, int prefix)
+ struct in6_addr *dst, struct in6_addr *src,
+ int iif, int type, u32 pid, u32 seq,
+ int prefix, unsigned int flags)
{
struct rtmsg *rtm;
struct nlmsghdr *nlh;
@@ -1584,11 +1585,7 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
}
}
- if (!pid && in_nlh) {
- pid = in_nlh->nlmsg_pid;
- }
-
- nlh = NLMSG_PUT(skb, pid, seq, type, sizeof(*rtm));
+ nlh = NLMSG_NEW(skb, pid, seq, type, sizeof(*rtm), flags);
rtm = NLMSG_DATA(nlh);
rtm->rtm_family = AF_INET6;
rtm->rtm_dst_len = rt->rt6i_dst.plen;
@@ -1674,7 +1671,7 @@ static int rt6_dump_route(struct rt6_info *rt, void *p_arg)
return rt6_fill_node(arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE,
NETLINK_CB(arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq,
- NULL, prefix);
+ prefix, NLM_F_MULTI);
}
static int fib6_dump_node(struct fib6_walker_t *w)
@@ -1822,7 +1819,7 @@ int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
&fl.fl6_dst, &fl.fl6_src,
iif,
RTM_NEWROUTE, NETLINK_CB(in_skb).pid,
- nlh->nlmsg_seq, nlh, 0);
+ nlh->nlmsg_seq, 0, 0);
if (err < 0) {
err = -EMSGSIZE;
goto out_free;
@@ -1838,17 +1835,25 @@ out_free:
goto out;
}
-void inet6_rt_notify(int event, struct rt6_info *rt, struct nlmsghdr *nlh)
+void inet6_rt_notify(int event, struct rt6_info *rt, struct nlmsghdr *nlh,
+ struct netlink_skb_parms *req)
{
struct sk_buff *skb;
int size = NLMSG_SPACE(sizeof(struct rtmsg)+256);
+ u32 pid = current->pid;
+ u32 seq = 0;
+ if (req)
+ pid = req->pid;
+ if (nlh)
+ seq = nlh->nlmsg_seq;
+
skb = alloc_skb(size, gfp_any());
if (!skb) {
netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, ENOBUFS);
return;
}
- if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, 0, 0, nlh, 0) < 0) {
+ if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0) < 0) {
kfree_skb(skb);
netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, EINVAL);
return;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 0f69e800a0a..9dac7fdf472 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -65,7 +65,7 @@
#include <linux/seq_file.h>
static void tcp_v6_send_reset(struct sk_buff *skb);
-static void tcp_v6_or_send_ack(struct sk_buff *skb, struct open_request *req);
+static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req);
static void tcp_v6_send_check(struct sock *sk, struct tcphdr *th, int len,
struct sk_buff *skb);
@@ -394,24 +394,26 @@ static u32 tcp_v6_synq_hash(struct in6_addr *raddr, u16 rport, u32 rnd)
return c & (TCP_SYNQ_HSIZE - 1);
}
-static struct open_request *tcp_v6_search_req(struct tcp_sock *tp,
- struct open_request ***prevp,
+static struct request_sock *tcp_v6_search_req(struct tcp_sock *tp,
+ struct request_sock ***prevp,
__u16 rport,
struct in6_addr *raddr,
struct in6_addr *laddr,
int iif)
{
- struct tcp_listen_opt *lopt = tp->listen_opt;
- struct open_request *req, **prev;
+ struct listen_sock *lopt = tp->accept_queue.listen_opt;
+ struct request_sock *req, **prev;
for (prev = &lopt->syn_table[tcp_v6_synq_hash(raddr, rport, lopt->hash_rnd)];
(req = *prev) != NULL;
prev = &req->dl_next) {
- if (req->rmt_port == rport &&
- req->class->family == AF_INET6 &&
- ipv6_addr_equal(&req->af.v6_req.rmt_addr, raddr) &&
- ipv6_addr_equal(&req->af.v6_req.loc_addr, laddr) &&
- (!req->af.v6_req.iif || req->af.v6_req.iif == iif)) {
+ const struct tcp6_request_sock *treq = tcp6_rsk(req);
+
+ if (inet_rsk(req)->rmt_port == rport &&
+ req->rsk_ops->family == AF_INET6 &&
+ ipv6_addr_equal(&treq->rmt_addr, raddr) &&
+ ipv6_addr_equal(&treq->loc_addr, laddr) &&
+ (!treq->iif || treq->iif == iif)) {
BUG_TRAP(req->sk == NULL);
*prevp = prev;
return req;
@@ -906,9 +908,9 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
icmpv6_err_convert(type, code, &err);
- /* Might be for an open_request */
+ /* Might be for an request_sock */
switch (sk->sk_state) {
- struct open_request *req, **prev;
+ struct request_sock *req, **prev;
case TCP_LISTEN:
if (sock_owned_by_user(sk))
goto out;
@@ -923,7 +925,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
*/
BUG_TRAP(req->sk == NULL);
- if (seq != req->snt_isn) {
+ if (seq != tcp_rsk(req)->snt_isn) {
NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
goto out;
}
@@ -957,9 +959,10 @@ out:
}
-static int tcp_v6_send_synack(struct sock *sk, struct open_request *req,
+static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
struct dst_entry *dst)
{
+ struct tcp6_request_sock *treq = tcp6_rsk(req);
struct ipv6_pinfo *np = inet6_sk(sk);
struct sk_buff * skb;
struct ipv6_txoptions *opt = NULL;
@@ -969,19 +972,19 @@ static int tcp_v6_send_synack(struct sock *sk, struct open_request *req,
memset(&fl, 0, sizeof(fl));
fl.proto = IPPROTO_TCP;
- ipv6_addr_copy(&fl.fl6_dst, &req->af.v6_req.rmt_addr);
- ipv6_addr_copy(&fl.fl6_src, &req->af.v6_req.loc_addr);
+ ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
+ ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr);
fl.fl6_flowlabel = 0;
- fl.oif = req->af.v6_req.iif;
- fl.fl_ip_dport = req->rmt_port;
+ fl.oif = treq->iif;
+ fl.fl_ip_dport = inet_rsk(req)->rmt_port;
fl.fl_ip_sport = inet_sk(sk)->sport;
if (dst == NULL) {
opt = np->opt;
if (opt == NULL &&
np->rxopt.bits.srcrt == 2 &&
- req->af.v6_req.pktopts) {
- struct sk_buff *pktopts = req->af.v6_req.pktopts;
+ treq->pktopts) {
+ struct sk_buff *pktopts = treq->pktopts;
struct inet6_skb_parm *rxopt = IP6CB(pktopts);
if (rxopt->srcrt)
opt = ipv6_invert_rthdr(sk, (struct ipv6_rt_hdr*)(pktopts->nh.raw + rxopt->srcrt));
@@ -1008,10 +1011,10 @@ static int tcp_v6_send_synack(struct sock *sk, struct open_request *req,
struct tcphdr *th = skb->h.th;
th->check = tcp_v6_check(th, skb->len,
- &req->af.v6_req.loc_addr, &req->af.v6_req.rmt_addr,
+ &treq->loc_addr, &treq->rmt_addr,
csum_partial((char *)th, skb->len, skb->csum));
- ipv6_addr_copy(&fl.fl6_dst, &req->af.v6_req.rmt_addr);
+ ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
err = ip6_xmit(sk, skb, &fl, opt, 0);
if (err == NET_XMIT_CN)
err = 0;
@@ -1024,17 +1027,18 @@ done:
return err;
}
-static void tcp_v6_or_free(struct open_request *req)
+static void tcp_v6_reqsk_destructor(struct request_sock *req)
{
- if (req->af.v6_req.pktopts)
- kfree_skb(req->af.v6_req.pktopts);
+ if (tcp6_rsk(req)->pktopts)
+ kfree_skb(tcp6_rsk(req)->pktopts);
}
-static struct or_calltable or_ipv6 = {
+static struct request_sock_ops tcp6_request_sock_ops = {
.family = AF_INET6,
+ .obj_size = sizeof(struct tcp6_request_sock),
.rtx_syn_ack = tcp_v6_send_synack,
- .send_ack = tcp_v6_or_send_ack,
- .destructor = tcp_v6_or_free,
+ .send_ack = tcp_v6_reqsk_send_ack,
+ .destructor = tcp_v6_reqsk_destructor,
.send_reset = tcp_v6_send_reset
};
@@ -1219,15 +1223,15 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
tcp_tw_put(tw);
}
-static void tcp_v6_or_send_ack(struct sk_buff *skb, struct open_request *req)
+static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req)
{
- tcp_v6_send_ack(skb, req->snt_isn+1, req->rcv_isn+1, req->rcv_wnd, req->ts_recent);
+ tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent);
}
static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
{
- struct open_request *req, **prev;
+ struct request_sock *req, **prev;
struct tcphdr *th = skb->h.th;
struct tcp_sock *tp = tcp_sk(sk);
struct sock *nsk;
@@ -1260,21 +1264,13 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
return sk;
}
-static void tcp_v6_synq_add(struct sock *sk, struct open_request *req)
+static void tcp_v6_synq_add(struct sock *sk, struct request_sock *req)
{
struct tcp_sock *tp = tcp_sk(sk);
- struct tcp_listen_opt *lopt = tp->listen_opt;
- u32 h = tcp_v6_synq_hash(&req->af.v6_req.rmt_addr, req->rmt_port, lopt->hash_rnd);
-
- req->sk = NULL;
- req->expires = jiffies + TCP_TIMEOUT_INIT;
- req->retrans = 0;
- req->dl_next = lopt->syn_table[h];
-
- write_lock(&tp->syn_wait_lock);
- lopt->syn_table[h] = req;
- write_unlock(&tp->syn_wait_lock);
+ struct listen_sock *lopt = tp->accept_queue.listen_opt;
+ u32 h = tcp_v6_synq_hash(&tcp6_rsk(req)->rmt_addr, inet_rsk(req)->rmt_port, lopt->hash_rnd);
+ reqsk_queue_hash_req(&tp->accept_queue, h, req, TCP_TIMEOUT_INIT);
tcp_synq_added(sk);
}
@@ -1284,10 +1280,11 @@ static void tcp_v6_synq_add(struct sock *sk, struct open_request *req)
*/
static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
{
+ struct tcp6_request_sock *treq;
struct ipv6_pinfo *np = inet6_sk(sk);
struct tcp_options_received tmp_opt;
struct tcp_sock *tp = tcp_sk(sk);
- struct open_request *req = NULL;
+ struct request_sock *req = NULL;
__u32 isn = TCP_SKB_CB(skb)->when;
if (skb->protocol == htons(ETH_P_IP))
@@ -1308,7 +1305,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
if (sk_acceptq_is_full(sk) && tcp_synq_young(sk) > 1)
goto drop;
- req = tcp_openreq_alloc();
+ req = reqsk_alloc(&tcp6_request_sock_ops);
if (req == NULL)
goto drop;
@@ -1321,28 +1318,28 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
tmp_opt.tstamp_ok = tmp_opt.saw_tstamp;
tcp_openreq_init(req, &tmp_opt, skb);
- req->class = &or_ipv6;
- ipv6_addr_copy(&req->af.v6_req.rmt_addr, &skb->nh.ipv6h->saddr);
- ipv6_addr_copy(&req->af.v6_req.loc_addr, &skb->nh.ipv6h->daddr);
+ treq = tcp6_rsk(req);
+ ipv6_addr_copy(&treq->rmt_addr, &skb->nh.ipv6h->saddr);
+ ipv6_addr_copy(&treq->loc_addr, &skb->nh.ipv6h->daddr);
TCP_ECN_create_request(req, skb->h.th);
- req->af.v6_req.pktopts = NULL;
+ treq->pktopts = NULL;
if (ipv6_opt_accepted(sk, skb) ||
np->rxopt.bits.rxinfo ||
np->rxopt.bits.rxhlim) {
atomic_inc(&skb->users);
- req->af.v6_req.pktopts = skb;
+ treq->pktopts = skb;
}
- req->af.v6_req.iif = sk->sk_bound_dev_if;
+ treq->iif = sk->sk_bound_dev_if;
/* So that link locals have meaning */
if (!sk->sk_bound_dev_if &&
- ipv6_addr_type(&req->af.v6_req.rmt_addr) & IPV6_ADDR_LINKLOCAL)
- req->af.v6_req.iif = tcp_v6_iif(skb);
+ ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL)
+ treq->iif = tcp_v6_iif(skb);
if (isn == 0)
isn = tcp_v6_init_sequence(sk,skb);
- req->snt_isn = isn;
+ tcp_rsk(req)->snt_isn = isn;
if (tcp_v6_send_synack(sk, req, NULL))
goto drop;
@@ -1353,16 +1350,17 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
drop:
if (req)
- tcp_openreq_free(req);
+ reqsk_free(req);
TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS);
return 0; /* don't send reset */
}
static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
- struct open_request *req,
+ struct request_sock *req,
struct dst_entry *dst)
{
+ struct tcp6_request_sock *treq = tcp6_rsk(req);
struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
struct tcp6_sock *newtcp6sk;
struct inet_sock *newinet;
@@ -1426,10 +1424,10 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
goto out_overflow;
if (np->rxopt.bits.srcrt == 2 &&
- opt == NULL && req->af.v6_req.pktopts) {
- struct inet6_skb_parm *rxopt = IP6CB(req->af.v6_req.pktopts);
+ opt == NULL && treq->pktopts) {
+ struct inet6_skb_parm *rxopt = IP6CB(treq->pktopts);
if (rxopt->srcrt)
- opt = ipv6_invert_rthdr(sk, (struct ipv6_rt_hdr*)(req->af.v6_req.pktopts->nh.raw+rxopt->srcrt));
+ opt = ipv6_invert_rthdr(sk, (struct ipv6_rt_hdr *)(treq->pktopts->nh.raw + rxopt->srcrt));
}
if (dst == NULL) {
@@ -1438,16 +1436,16 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
memset(&fl, 0, sizeof(fl));
fl.proto = IPPROTO_TCP;
- ipv6_addr_copy(&fl.fl6_dst, &req->af.v6_req.rmt_addr);
+ ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
if (opt && opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
ipv6_addr_copy(&final, &fl.fl6_dst);
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
final_p = &final;
}
- ipv6_addr_copy(&fl.fl6_src, &req->af.v6_req.loc_addr);
+ ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr);
fl.oif = sk->sk_bound_dev_if;
- fl.fl_ip_dport = req->rmt_port;
+ fl.fl_ip_dport = inet_rsk(req)->rmt_port;
fl.fl_ip_sport = inet_sk(sk)->sport;
if (ip6_dst_lookup(sk, &dst, &fl))
@@ -1482,10 +1480,10 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
memcpy(newnp, np, sizeof(struct ipv6_pinfo));
- ipv6_addr_copy(&newnp->daddr, &req->af.v6_req.rmt_addr);
- ipv6_addr_copy(&newnp->saddr, &req->af.v6_req.loc_addr);
- ipv6_addr_copy(&newnp->rcv_saddr, &req->af.v6_req.loc_addr);
- newsk->sk_bound_dev_if = req->af.v6_req.iif;
+ ipv6_addr_copy(&newnp->daddr, &treq->rmt_addr);
+ ipv6_addr_copy(&newnp->saddr, &treq->loc_addr);
+ ipv6_addr_copy(&newnp->rcv_saddr, &treq->loc_addr);
+ newsk->sk_bound_dev_if = treq->iif;
/* Now IPv6 options...
@@ -1498,11 +1496,10 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
/* Clone pktoptions received with SYN */
newnp->pktoptions = NULL;
- if (req->af.v6_req.pktopts) {
- newnp->pktoptions = skb_clone(req->af.v6_req.pktopts,
- GFP_ATOMIC);
- kfree_skb(req->af.v6_req.pktopts);
- req->af.v6_req.pktopts = NULL;
+ if (treq->pktopts != NULL) {
+ newnp->pktoptions = skb_clone(treq->pktopts, GFP_ATOMIC);
+ kfree_skb(treq->pktopts);
+ treq->pktopts = NULL;
if (newnp->pktoptions)
skb_set_owner_r(newnp->pktoptions, newsk);
}
@@ -2028,7 +2025,7 @@ static int tcp_v6_init_sock(struct sock *sk)
sk->sk_state = TCP_CLOSE;
tp->af_specific = &ipv6_specific;
-
+ tp->ca_ops = &tcp_init_congestion_ops;
sk->sk_write_space = sk_stream_write_space;
sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
@@ -2050,7 +2047,7 @@ static int tcp_v6_destroy_sock(struct sock *sk)
/* Proc filesystem TCPv6 sock list dumping. */
static void get_openreq6(struct seq_file *seq,
- struct sock *sk, struct open_request *req, int i, int uid)
+ struct sock *sk, struct request_sock *req, int i, int uid)
{
struct in6_addr *dest, *src;
int ttd = req->expires - jiffies;
@@ -2058,8 +2055,8 @@ static void get_openreq6(struct seq_file *seq,
if (ttd < 0)
ttd = 0;
- src = &req->af.v6_req.loc_addr;
- dest = &req->af.v6_req.rmt_addr;
+ src = &tcp6_rsk(req)->loc_addr;
+ dest = &tcp6_rsk(req)->rmt_addr;
seq_printf(seq,
"%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
"%02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p\n",
@@ -2069,7 +2066,7 @@ static void get_openreq6(struct seq_file *seq,
ntohs(inet_sk(sk)->sport),
dest->s6_addr32[0], dest->s6_addr32[1],
dest->s6_addr32[2], dest->s6_addr32[3],
- ntohs(req->rmt_port),
+ ntohs(inet_rsk(req)->rmt_port),
TCP_SYN_RECV,
0,0, /* could print option size, but that is af dependent. */
1, /* timers active (only the expire timer) */
@@ -2239,6 +2236,7 @@ struct proto tcpv6_prot = {
.sysctl_rmem = sysctl_tcp_rmem,
.max_header = MAX_TCP_HEADER,
.obj_size = sizeof(struct tcp6_sock),
+ .rsk_prot = &tcp6_request_sock_ops,
};
static struct inet6_protocol tcpv6_protocol = {
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index e251d0ba4f3..eff050ac704 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -300,12 +300,12 @@ csum_copy_err:
/* Clear queue. */
if (flags&MSG_PEEK) {
int clear = 0;
- spin_lock_irq(&sk->sk_receive_queue.lock);
+ spin_lock_bh(&sk->sk_receive_queue.lock);
if (skb == skb_peek(&sk->sk_receive_queue)) {
__skb_unlink(skb, &sk->sk_receive_queue);
clear = 1;
}
- spin_unlock_irq(&sk->sk_receive_queue.lock);
+ spin_unlock_bh(&sk->sk_receive_queue.lock);
if (clear)
kfree_skb(skb);
}
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index 601a148f60f..6b9867717d1 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -84,6 +84,7 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb)
mtu = IPV6_MIN_MTU;
if (skb->len > mtu) {
+ skb->dev = dst->dev;
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, skb->dev);
ret = -EMSGSIZE;
}
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 4429b1a1fe5..cf1d91e74c8 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -113,6 +113,8 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
xdst = (struct xfrm_dst *)dst1;
xdst->route = &rt->u.dst;
+ if (rt->rt6i_node)
+ xdst->route_cookie = rt->rt6i_node->fn_sernum;
dst1->next = dst_prev;
dst_prev = dst1;
@@ -137,6 +139,8 @@ __xfrm6_bundle_create(struct xfrm_policy *policy, struct xfrm_state **xfrm, int
dst_prev->child = &rt->u.dst;
dst->path = &rt->u.dst;
+ if (rt->rt6i_node)
+ ((struct xfrm_dst *)dst)->path_cookie = rt->rt6i_node->fn_sernum;
*dst_p = dst;
dst = dst_prev;
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index ffcadd68b95..60c26c87277 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -466,7 +466,7 @@ static void xfrm6_tunnel_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
return;
}
-static int xfrm6_tunnel_init_state(struct xfrm_state *x, void *args)
+static int xfrm6_tunnel_init_state(struct xfrm_state *x)
{
if (!x->props.mode)
return -EINVAL;
diff --git a/net/key/af_key.c b/net/key/af_key.c
index ce980aa94ed..4879743b945 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -656,13 +656,18 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys,
sa->sadb_sa_exttype = SADB_EXT_SA;
sa->sadb_sa_spi = x->id.spi;
sa->sadb_sa_replay = x->props.replay_window;
- sa->sadb_sa_state = SADB_SASTATE_DYING;
- if (x->km.state == XFRM_STATE_VALID && !x->km.dying)
- sa->sadb_sa_state = SADB_SASTATE_MATURE;
- else if (x->km.state == XFRM_STATE_ACQ)
+ switch (x->km.state) {
+ case XFRM_STATE_VALID:
+ sa->sadb_sa_state = x->km.dying ?
+ SADB_SASTATE_DYING : SADB_SASTATE_MATURE;
+ break;
+ case XFRM_STATE_ACQ:
sa->sadb_sa_state = SADB_SASTATE_LARVAL;
- else if (x->km.state == XFRM_STATE_EXPIRED)
+ break;
+ default:
sa->sadb_sa_state = SADB_SASTATE_DEAD;
+ break;
+ }
sa->sadb_sa_auth = 0;
if (x->aalg) {
struct xfrm_algo_desc *a = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
@@ -685,6 +690,8 @@ static struct sk_buff * pfkey_xfrm_state2msg(struct xfrm_state *x, int add_keys,
sa->sadb_sa_flags |= SADB_SAFLAGS_NOECN;
if (x->props.flags & XFRM_STATE_DECAP_DSCP)
sa->sadb_sa_flags |= SADB_SAFLAGS_DECAP_DSCP;
+ if (x->props.flags & XFRM_STATE_NOPMTUDISC)
+ sa->sadb_sa_flags |= SADB_SAFLAGS_NOPMTUDISC;
/* hard time */
if (hsc & 2) {
@@ -969,6 +976,8 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,
x->props.flags |= XFRM_STATE_NOECN;
if (sa->sadb_sa_flags & SADB_SAFLAGS_DECAP_DSCP)
x->props.flags |= XFRM_STATE_DECAP_DSCP;
+ if (sa->sadb_sa_flags & SADB_SAFLAGS_NOPMTUDISC)
+ x->props.flags |= XFRM_STATE_NOPMTUDISC;
lifetime = (struct sadb_lifetime*) ext_hdrs[SADB_EXT_LIFETIME_HARD-1];
if (lifetime != NULL) {
@@ -1091,17 +1100,11 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,
}
}
- x->type = xfrm_get_type(proto, x->props.family);
- if (x->type == NULL) {
- err = -ENOPROTOOPT;
- goto out;
- }
- if (x->type->init_state(x, NULL)) {
- err = -EINVAL;
+ err = xfrm_init_state(x);
+ if (err)
goto out;
- }
+
x->km.seq = hdr->sadb_msg_seq;
- x->km.state = XFRM_STATE_VALID;
return x;
out:
@@ -1240,13 +1243,78 @@ static int pfkey_acquire(struct sock *sk, struct sk_buff *skb, struct sadb_msg *
return 0;
}
+static inline int event2poltype(int event)
+{
+ switch (event) {
+ case XFRM_MSG_DELPOLICY:
+ return SADB_X_SPDDELETE;
+ case XFRM_MSG_NEWPOLICY:
+ return SADB_X_SPDADD;
+ case XFRM_MSG_UPDPOLICY:
+ return SADB_X_SPDUPDATE;
+ case XFRM_MSG_POLEXPIRE:
+ // return SADB_X_SPDEXPIRE;
+ default:
+ printk("pfkey: Unknown policy event %d\n", event);
+ break;
+ }
+
+ return 0;
+}
+
+static inline int event2keytype(int event)
+{
+ switch (event) {
+ case XFRM_MSG_DELSA:
+ return SADB_DELETE;
+ case XFRM_MSG_NEWSA:
+ return SADB_ADD;
+ case XFRM_MSG_UPDSA:
+ return SADB_UPDATE;
+ case XFRM_MSG_EXPIRE:
+ return SADB_EXPIRE;
+ default:
+ printk("pfkey: Unknown SA event %d\n", event);
+ break;
+ }
+
+ return 0;
+}
+
+/* ADD/UPD/DEL */
+static int key_notify_sa(struct xfrm_state *x, struct km_event *c)
+{
+ struct sk_buff *skb;
+ struct sadb_msg *hdr;
+ int hsc = 3;
+
+ if (c->event == XFRM_MSG_DELSA)
+ hsc = 0;
+
+ skb = pfkey_xfrm_state2msg(x, 0, hsc);
+
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ hdr = (struct sadb_msg *) skb->data;
+ hdr->sadb_msg_version = PF_KEY_V2;
+ hdr->sadb_msg_type = event2keytype(c->event);
+ hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto);
+ hdr->sadb_msg_errno = 0;
+ hdr->sadb_msg_reserved = 0;
+ hdr->sadb_msg_seq = c->seq;
+ hdr->sadb_msg_pid = c->pid;
+
+ pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL);
+
+ return 0;
+}
static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
{
- struct sk_buff *out_skb;
- struct sadb_msg *out_hdr;
struct xfrm_state *x;
int err;
+ struct km_event c;
xfrm_probe_algs();
@@ -1254,6 +1322,7 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
if (IS_ERR(x))
return PTR_ERR(x);
+ xfrm_state_hold(x);
if (hdr->sadb_msg_type == SADB_ADD)
err = xfrm_state_add(x);
else
@@ -1262,30 +1331,26 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
if (err < 0) {
x->km.state = XFRM_STATE_DEAD;
xfrm_state_put(x);
- return err;
+ goto out;
}
- out_skb = pfkey_xfrm_state2msg(x, 0, 3);
- if (IS_ERR(out_skb))
- return PTR_ERR(out_skb); /* XXX Should we return 0 here ? */
-
- out_hdr = (struct sadb_msg *) out_skb->data;
- out_hdr->sadb_msg_version = hdr->sadb_msg_version;
- out_hdr->sadb_msg_type = hdr->sadb_msg_type;
- out_hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto);
- out_hdr->sadb_msg_errno = 0;
- out_hdr->sadb_msg_reserved = 0;
- out_hdr->sadb_msg_seq = hdr->sadb_msg_seq;
- out_hdr->sadb_msg_pid = hdr->sadb_msg_pid;
-
- pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, sk);
-
- return 0;
+ if (hdr->sadb_msg_type == SADB_ADD)
+ c.event = XFRM_MSG_NEWSA;
+ else
+ c.event = XFRM_MSG_UPDSA;
+ c.seq = hdr->sadb_msg_seq;
+ c.pid = hdr->sadb_msg_pid;
+ km_state_notify(x, &c);
+out:
+ xfrm_state_put(x);
+ return err;
}
static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
{
struct xfrm_state *x;
+ struct km_event c;
+ int err;
if (!ext_hdrs[SADB_EXT_SA-1] ||
!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
@@ -1301,13 +1366,19 @@ static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
return -EPERM;
}
- xfrm_state_delete(x);
- xfrm_state_put(x);
+ err = xfrm_state_delete(x);
+ if (err < 0) {
+ xfrm_state_put(x);
+ return err;
+ }
- pfkey_broadcast(skb_clone(skb, GFP_KERNEL), GFP_KERNEL,
- BROADCAST_ALL, sk);
+ c.seq = hdr->sadb_msg_seq;
+ c.pid = hdr->sadb_msg_pid;
+ c.event = XFRM_MSG_DELSA;
+ km_state_notify(x, &c);
+ xfrm_state_put(x);
- return 0;
+ return err;
}
static int pfkey_get(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
@@ -1445,28 +1516,42 @@ static int pfkey_register(struct sock *sk, struct sk_buff *skb, struct sadb_msg
return 0;
}
+static int key_notify_sa_flush(struct km_event *c)
+{
+ struct sk_buff *skb;
+ struct sadb_msg *hdr;
+
+ skb = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_ATOMIC);
+ if (!skb)
+ return -ENOBUFS;
+ hdr = (struct sadb_msg *) skb_put(skb, sizeof(struct sadb_msg));
+ hdr->sadb_msg_satype = pfkey_proto2satype(c->data.proto);
+ hdr->sadb_msg_seq = c->seq;
+ hdr->sadb_msg_pid = c->pid;
+ hdr->sadb_msg_version = PF_KEY_V2;
+ hdr->sadb_msg_errno = (uint8_t) 0;
+ hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
+
+ pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL);
+
+ return 0;
+}
+
static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
{
unsigned proto;
- struct sk_buff *skb_out;
- struct sadb_msg *hdr_out;
+ struct km_event c;
proto = pfkey_satype2proto(hdr->sadb_msg_satype);
if (proto == 0)
return -EINVAL;
- skb_out = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_KERNEL);
- if (!skb_out)
- return -ENOBUFS;
-
xfrm_state_flush(proto);
-
- hdr_out = (struct sadb_msg *) skb_put(skb_out, sizeof(struct sadb_msg));
- pfkey_hdr_dup(hdr_out, hdr);
- hdr_out->sadb_msg_errno = (uint8_t) 0;
- hdr_out->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
-
- pfkey_broadcast(skb_out, GFP_KERNEL, BROADCAST_ALL, NULL);
+ c.data.proto = proto;
+ c.seq = hdr->sadb_msg_seq;
+ c.pid = hdr->sadb_msg_pid;
+ c.event = XFRM_MSG_FLUSHSA;
+ km_state_notify(NULL, &c);
return 0;
}
@@ -1859,6 +1944,35 @@ static void pfkey_xfrm_policy2msg(struct sk_buff *skb, struct xfrm_policy *xp, i
hdr->sadb_msg_reserved = atomic_read(&xp->refcnt);
}
+static int key_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c)
+{
+ struct sk_buff *out_skb;
+ struct sadb_msg *out_hdr;
+ int err;
+
+ out_skb = pfkey_xfrm_policy2msg_prep(xp);
+ if (IS_ERR(out_skb)) {
+ err = PTR_ERR(out_skb);
+ goto out;
+ }
+ pfkey_xfrm_policy2msg(out_skb, xp, dir);
+
+ out_hdr = (struct sadb_msg *) out_skb->data;
+ out_hdr->sadb_msg_version = PF_KEY_V2;
+
+ if (c->data.byid && c->event == XFRM_MSG_DELPOLICY)
+ out_hdr->sadb_msg_type = SADB_X_SPDDELETE2;
+ else
+ out_hdr->sadb_msg_type = event2poltype(c->event);
+ out_hdr->sadb_msg_errno = 0;
+ out_hdr->sadb_msg_seq = c->seq;
+ out_hdr->sadb_msg_pid = c->pid;
+ pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, NULL);
+out:
+ return 0;
+
+}
+
static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
{
int err;
@@ -1866,8 +1980,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
struct sadb_address *sa;
struct sadb_x_policy *pol;
struct xfrm_policy *xp;
- struct sk_buff *out_skb;
- struct sadb_msg *out_hdr;
+ struct km_event c;
if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
ext_hdrs[SADB_EXT_ADDRESS_DST-1]) ||
@@ -1935,31 +2048,23 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
(err = parse_ipsecrequests(xp, pol)) < 0)
goto out;
- out_skb = pfkey_xfrm_policy2msg_prep(xp);
- if (IS_ERR(out_skb)) {
- err = PTR_ERR(out_skb);
- goto out;
- }
-
err = xfrm_policy_insert(pol->sadb_x_policy_dir-1, xp,
hdr->sadb_msg_type != SADB_X_SPDUPDATE);
if (err) {
- kfree_skb(out_skb);
- goto out;
+ kfree(xp);
+ return err;
}
- pfkey_xfrm_policy2msg(out_skb, xp, pol->sadb_x_policy_dir-1);
+ if (hdr->sadb_msg_type == SADB_X_SPDUPDATE)
+ c.event = XFRM_MSG_UPDPOLICY;
+ else
+ c.event = XFRM_MSG_NEWPOLICY;
- xfrm_pol_put(xp);
+ c.seq = hdr->sadb_msg_seq;
+ c.pid = hdr->sadb_msg_pid;
- out_hdr = (struct sadb_msg *) out_skb->data;
- out_hdr->sadb_msg_version = hdr->sadb_msg_version;
- out_hdr->sadb_msg_type = hdr->sadb_msg_type;
- out_hdr->sadb_msg_satype = 0;
- out_hdr->sadb_msg_errno = 0;
- out_hdr->sadb_msg_seq = hdr->sadb_msg_seq;
- out_hdr->sadb_msg_pid = hdr->sadb_msg_pid;
- pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, sk);
+ km_policy_notify(xp, pol->sadb_x_policy_dir-1, &c);
+ xfrm_pol_put(xp);
return 0;
out:
@@ -1973,9 +2078,8 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
struct sadb_address *sa;
struct sadb_x_policy *pol;
struct xfrm_policy *xp;
- struct sk_buff *out_skb;
- struct sadb_msg *out_hdr;
struct xfrm_selector sel;
+ struct km_event c;
if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
ext_hdrs[SADB_EXT_ADDRESS_DST-1]) ||
@@ -2010,25 +2114,40 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
err = 0;
+ c.seq = hdr->sadb_msg_seq;
+ c.pid = hdr->sadb_msg_pid;
+ c.event = XFRM_MSG_DELPOLICY;
+ km_policy_notify(xp, pol->sadb_x_policy_dir-1, &c);
+
+ xfrm_pol_put(xp);
+ return err;
+}
+
+static int key_pol_get_resp(struct sock *sk, struct xfrm_policy *xp, struct sadb_msg *hdr, int dir)
+{
+ int err;
+ struct sk_buff *out_skb;
+ struct sadb_msg *out_hdr;
+ err = 0;
+
out_skb = pfkey_xfrm_policy2msg_prep(xp);
if (IS_ERR(out_skb)) {
err = PTR_ERR(out_skb);
goto out;
}
- pfkey_xfrm_policy2msg(out_skb, xp, pol->sadb_x_policy_dir-1);
+ pfkey_xfrm_policy2msg(out_skb, xp, dir);
out_hdr = (struct sadb_msg *) out_skb->data;
out_hdr->sadb_msg_version = hdr->sadb_msg_version;
- out_hdr->sadb_msg_type = SADB_X_SPDDELETE;
+ out_hdr->sadb_msg_type = hdr->sadb_msg_type;
out_hdr->sadb_msg_satype = 0;
out_hdr->sadb_msg_errno = 0;
out_hdr->sadb_msg_seq = hdr->sadb_msg_seq;
out_hdr->sadb_msg_pid = hdr->sadb_msg_pid;
- pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, sk);
+ pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, sk);
err = 0;
out:
- xfrm_pol_put(xp);
return err;
}
@@ -2037,8 +2156,7 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
int err;
struct sadb_x_policy *pol;
struct xfrm_policy *xp;
- struct sk_buff *out_skb;
- struct sadb_msg *out_hdr;
+ struct km_event c;
if ((pol = ext_hdrs[SADB_X_EXT_POLICY-1]) == NULL)
return -EINVAL;
@@ -2050,24 +2168,16 @@ static int pfkey_spdget(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
err = 0;
- out_skb = pfkey_xfrm_policy2msg_prep(xp);
- if (IS_ERR(out_skb)) {
- err = PTR_ERR(out_skb);
- goto out;
+ c.seq = hdr->sadb_msg_seq;
+ c.pid = hdr->sadb_msg_pid;
+ if (hdr->sadb_msg_type == SADB_X_SPDDELETE2) {
+ c.data.byid = 1;
+ c.event = XFRM_MSG_DELPOLICY;
+ km_policy_notify(xp, pol->sadb_x_policy_dir-1, &c);
+ } else {
+ err = key_pol_get_resp(sk, xp, hdr, pol->sadb_x_policy_dir-1);
}
- pfkey_xfrm_policy2msg(out_skb, xp, pol->sadb_x_policy_dir-1);
- out_hdr = (struct sadb_msg *) out_skb->data;
- out_hdr->sadb_msg_version = hdr->sadb_msg_version;
- out_hdr->sadb_msg_type = hdr->sadb_msg_type;
- out_hdr->sadb_msg_satype = 0;
- out_hdr->sadb_msg_errno = 0;
- out_hdr->sadb_msg_seq = hdr->sadb_msg_seq;
- out_hdr->sadb_msg_pid = hdr->sadb_msg_pid;
- pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, sk);
- err = 0;
-
-out:
xfrm_pol_put(xp);
return err;
}
@@ -2102,22 +2212,34 @@ static int pfkey_spddump(struct sock *sk, struct sk_buff *skb, struct sadb_msg *
return xfrm_policy_walk(dump_sp, &data);
}
-static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+static int key_notify_policy_flush(struct km_event *c)
{
struct sk_buff *skb_out;
- struct sadb_msg *hdr_out;
+ struct sadb_msg *hdr;
- skb_out = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_KERNEL);
+ skb_out = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_ATOMIC);
if (!skb_out)
return -ENOBUFS;
+ hdr = (struct sadb_msg *) skb_put(skb_out, sizeof(struct sadb_msg));
+ hdr->sadb_msg_seq = c->seq;
+ hdr->sadb_msg_pid = c->pid;
+ hdr->sadb_msg_version = PF_KEY_V2;
+ hdr->sadb_msg_errno = (uint8_t) 0;
+ hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
+ pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL);
+ return 0;
- xfrm_policy_flush();
+}
- hdr_out = (struct sadb_msg *) skb_put(skb_out, sizeof(struct sadb_msg));
- pfkey_hdr_dup(hdr_out, hdr);
- hdr_out->sadb_msg_errno = (uint8_t) 0;
- hdr_out->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
- pfkey_broadcast(skb_out, GFP_KERNEL, BROADCAST_ALL, NULL);
+static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+{
+ struct km_event c;
+
+ xfrm_policy_flush();
+ c.event = XFRM_MSG_FLUSHPOLICY;
+ c.pid = hdr->sadb_msg_pid;
+ c.seq = hdr->sadb_msg_seq;
+ km_policy_notify(NULL, 0, &c);
return 0;
}
@@ -2317,11 +2439,23 @@ static void dump_esp_combs(struct sk_buff *skb, struct xfrm_tmpl *t)
}
}
-static int pfkey_send_notify(struct xfrm_state *x, int hard)
+static int key_notify_policy_expire(struct xfrm_policy *xp, struct km_event *c)
+{
+ return 0;
+}
+
+static int key_notify_sa_expire(struct xfrm_state *x, struct km_event *c)
{
struct sk_buff *out_skb;
struct sadb_msg *out_hdr;
- int hsc = (hard ? 2 : 1);
+ int hard;
+ int hsc;
+
+ hard = c->data.hard;
+ if (hard)
+ hsc = 2;
+ else
+ hsc = 1;
out_skb = pfkey_xfrm_state2msg(x, 0, hsc);
if (IS_ERR(out_skb))
@@ -2340,6 +2474,44 @@ static int pfkey_send_notify(struct xfrm_state *x, int hard)
return 0;
}
+static int pfkey_send_notify(struct xfrm_state *x, struct km_event *c)
+{
+ switch (c->event) {
+ case XFRM_MSG_EXPIRE:
+ return key_notify_sa_expire(x, c);
+ case XFRM_MSG_DELSA:
+ case XFRM_MSG_NEWSA:
+ case XFRM_MSG_UPDSA:
+ return key_notify_sa(x, c);
+ case XFRM_MSG_FLUSHSA:
+ return key_notify_sa_flush(c);
+ default:
+ printk("pfkey: Unknown SA event %d\n", c->event);
+ break;
+ }
+
+ return 0;
+}
+
+static int pfkey_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
+{
+ switch (c->event) {
+ case XFRM_MSG_POLEXPIRE:
+ return key_notify_policy_expire(xp, c);
+ case XFRM_MSG_DELPOLICY:
+ case XFRM_MSG_NEWPOLICY:
+ case XFRM_MSG_UPDPOLICY:
+ return key_notify_policy(xp, dir, c);
+ case XFRM_MSG_FLUSHPOLICY:
+ return key_notify_policy_flush(c);
+ default:
+ printk("pfkey: Unknown policy event %d\n", c->event);
+ break;
+ }
+
+ return 0;
+}
+
static u32 get_acqseq(void)
{
u32 res;
@@ -2856,6 +3028,7 @@ static struct xfrm_mgr pfkeyv2_mgr =
.acquire = pfkey_send_acquire,
.compile_policy = pfkey_compile_policy,
.new_mapping = pfkey_send_new_mapping,
+ .notify_policy = pfkey_send_policy_notify,
};
static void __exit ipsec_pfkey_exit(void)
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 733bf52cef3..70bcd4744d9 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -735,11 +735,15 @@ static inline int do_one_broadcast(struct sock *sk,
sock_hold(sk);
if (p->skb2 == NULL) {
- if (atomic_read(&p->skb->users) != 1) {
+ if (skb_shared(p->skb)) {
p->skb2 = skb_clone(p->skb, p->allocation);
} else {
- p->skb2 = p->skb;
- atomic_inc(&p->skb->users);
+ p->skb2 = skb_get(p->skb);
+ /*
+ * skb ownership may have been set when
+ * delivered to a previous socket.
+ */
+ skb_orphan(p->skb2);
}
}
if (p->skb2 == NULL) {
@@ -785,11 +789,12 @@ int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid,
sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list)
do_one_broadcast(sk, &info);
+ kfree_skb(skb);
+
netlink_unlock_table();
if (info.skb2)
kfree_skb(info.skb2);
- kfree_skb(skb);
if (info.delivered) {
if (info.congested && (allocation & __GFP_WAIT))
@@ -1090,8 +1095,7 @@ static int netlink_dump(struct sock *sk)
return 0;
}
- nlh = __nlmsg_put(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, NLMSG_DONE, sizeof(int));
- nlh->nlmsg_flags |= NLM_F_MULTI;
+ nlh = NLMSG_NEW_ANSWER(skb, cb, NLMSG_DONE, sizeof(len), NLM_F_MULTI);
memcpy(NLMSG_DATA(nlh), &len, sizeof(len));
skb_queue_tail(&sk->sk_receive_queue, skb);
sk->sk_data_ready(sk, skb->len);
@@ -1102,6 +1106,9 @@ static int netlink_dump(struct sock *sk)
netlink_destroy_callback(cb);
return 0;
+
+nlmsg_failure:
+ return -ENOBUFS;
}
int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
@@ -1173,7 +1180,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err)
}
rep = __nlmsg_put(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,
- NLMSG_ERROR, sizeof(struct nlmsgerr));
+ NLMSG_ERROR, sizeof(struct nlmsgerr), 0);
errmsg = NLMSG_DATA(rep);
errmsg->error = err;
memcpy(&errmsg->msg, nlh, err ? nlh->nlmsg_len : sizeof(struct nlmsghdr));
diff --git a/net/rxrpc/krxiod.c b/net/rxrpc/krxiod.c
index 2b537f425a1..dada34a77b2 100644
--- a/net/rxrpc/krxiod.c
+++ b/net/rxrpc/krxiod.c
@@ -138,7 +138,7 @@ static int rxrpc_krxiod(void *arg)
_debug("### End Work");
- try_to_freeze(PF_FREEZE);
+ try_to_freeze();
/* discard pending signals */
rxrpc_discard_my_signals();
diff --git a/net/rxrpc/krxsecd.c b/net/rxrpc/krxsecd.c
index 6020c89d922..1aadd026d35 100644
--- a/net/rxrpc/krxsecd.c
+++ b/net/rxrpc/krxsecd.c
@@ -107,7 +107,7 @@ static int rxrpc_krxsecd(void *arg)
_debug("### End Inbound Calls");
- try_to_freeze(PF_FREEZE);
+ try_to_freeze();
/* discard pending signals */
rxrpc_discard_my_signals();
diff --git a/net/rxrpc/krxtimod.c b/net/rxrpc/krxtimod.c
index 249c2b0290b..3ac81cdd121 100644
--- a/net/rxrpc/krxtimod.c
+++ b/net/rxrpc/krxtimod.c
@@ -90,7 +90,7 @@ static int krxtimod(void *arg)
complete_and_exit(&krxtimod_dead, 0);
}
- try_to_freeze(PF_FREEZE);
+ try_to_freeze();
/* discard pending signals */
rxrpc_discard_my_signals();
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index b0941186f86..7bac249258e 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -405,7 +405,7 @@ config NET_EMATCH_STACK
---help---
Size of the local stack variable used while evaluating the tree of
ematches. Limits the depth of the tree, i.e. the number of
- encapsulated precedences. Every level requires 4 bytes of addtional
+ encapsulated precedences. Every level requires 4 bytes of additional
stack space.
config NET_EMATCH_CMP
@@ -449,6 +449,19 @@ config NET_EMATCH_META
To compile this code as a module, choose M here: the
module will be called em_meta.
+config NET_EMATCH_TEXT
+ tristate "Textsearch"
+ depends on NET_EMATCH
+ select TEXTSEARCH
+ select TEXTSEARCH_KMP
+ select TEXTSEARCH_FSM
+ ---help---
+ Say Y here if you want to be ablt to classify packets based on
+ textsearch comparisons.
+
+ To compile this code as a module, choose M here: the
+ module will be called em_text.
+
config NET_CLS_ACT
bool "Packet ACTION"
depends on EXPERIMENTAL && NET_CLS && NET_QOS
diff --git a/net/sched/Makefile b/net/sched/Makefile
index eb3fe583eba..8f58cecd626 100644
--- a/net/sched/Makefile
+++ b/net/sched/Makefile
@@ -40,3 +40,4 @@ obj-$(CONFIG_NET_EMATCH_CMP) += em_cmp.o
obj-$(CONFIG_NET_EMATCH_NBYTE) += em_nbyte.o
obj-$(CONFIG_NET_EMATCH_U32) += em_u32.o
obj-$(CONFIG_NET_EMATCH_META) += em_meta.o
+obj-$(CONFIG_NET_EMATCH_TEXT) += em_text.o
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index cafcb084098..9594206e603 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -428,15 +428,15 @@ errout:
static int
tca_get_fill(struct sk_buff *skb, struct tc_action *a, u32 pid, u32 seq,
- unsigned flags, int event, int bind, int ref)
+ u16 flags, int event, int bind, int ref)
{
struct tcamsg *t;
struct nlmsghdr *nlh;
unsigned char *b = skb->tail;
struct rtattr *x;
- nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*t));
- nlh->nlmsg_flags = flags;
+ nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*t), flags);
+
t = NLMSG_DATA(nlh);
t->tca_family = AF_UNSPEC;
@@ -669,7 +669,7 @@ err:
}
static int tcf_add_notify(struct tc_action *a, u32 pid, u32 seq, int event,
- unsigned flags)
+ u16 flags)
{
struct tcamsg *t;
struct nlmsghdr *nlh;
@@ -684,8 +684,7 @@ static int tcf_add_notify(struct tc_action *a, u32 pid, u32 seq, int event,
b = (unsigned char *)skb->tail;
- nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*t));
- nlh->nlmsg_flags = flags;
+ nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*t), flags);
t = NLMSG_DATA(nlh);
t->tca_family = AF_UNSPEC;
@@ -881,7 +880,7 @@ static int __init tc_action_init(void)
link_p[RTM_GETACTION-RTM_BASE].dumpit = tc_dump_action;
}
- printk("TC classifier action (bugs to netdev@oss.sgi.com cc "
+ printk("TC classifier action (bugs to netdev@vger.kernel.org cc "
"hadi@cyberus.ca)\n");
return 0;
}
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 56e66c3fe0f..1616bf5c962 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -322,14 +322,13 @@ errout:
static int
tcf_fill_node(struct sk_buff *skb, struct tcf_proto *tp, unsigned long fh,
- u32 pid, u32 seq, unsigned flags, int event)
+ u32 pid, u32 seq, u16 flags, int event)
{
struct tcmsg *tcm;
struct nlmsghdr *nlh;
unsigned char *b = skb->tail;
- nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*tcm));
- nlh->nlmsg_flags = flags;
+ nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags);
tcm = NLMSG_DATA(nlh);
tcm->tcm_family = AF_UNSPEC;
tcm->tcm_ifindex = tp->q->dev->ifindex;
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index 0d2d4415f33..dfb300bb6ba 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -261,6 +261,9 @@ static int basic_dump(struct tcf_proto *tp, unsigned long fh,
rta = (struct rtattr *) b;
RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
+ if (f->res.classid)
+ RTA_PUT(skb, TCA_BASIC_CLASSID, sizeof(u32), &f->res.classid);
+
if (tcf_exts_dump(skb, &f->exts, &basic_ext_map) < 0 ||
tcf_em_tree_dump(skb, &f->ematches, TCA_BASIC_EMATCHES) < 0)
goto rtattr_failure;
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
index f1eeaf65cee..48bb23c2a35 100644
--- a/net/sched/em_meta.c
+++ b/net/sched/em_meta.c
@@ -32,7 +32,7 @@
* +-----------+ +-----------+
* | |
* ---> meta_ops[INT][INDEV](...) |
- * | |
+ * | |
* ----------- |
* V V
* +-----------+ +-----------+
@@ -70,6 +70,7 @@
#include <net/dst.h>
#include <net/route.h>
#include <net/pkt_cls.h>
+#include <net/sock.h>
struct meta_obj
{
@@ -284,6 +285,214 @@ META_COLLECTOR(int_rtiif)
}
/**************************************************************************
+ * Socket Attributes
+ **************************************************************************/
+
+#define SKIP_NONLOCAL(skb) \
+ if (unlikely(skb->sk == NULL)) { \
+ *err = -1; \
+ return; \
+ }
+
+META_COLLECTOR(int_sk_family)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = skb->sk->sk_family;
+}
+
+META_COLLECTOR(int_sk_state)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = skb->sk->sk_state;
+}
+
+META_COLLECTOR(int_sk_reuse)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = skb->sk->sk_reuse;
+}
+
+META_COLLECTOR(int_sk_bound_if)
+{
+ SKIP_NONLOCAL(skb);
+ /* No error if bound_dev_if is 0, legal userspace check */
+ dst->value = skb->sk->sk_bound_dev_if;
+}
+
+META_COLLECTOR(var_sk_bound_if)
+{
+ SKIP_NONLOCAL(skb);
+
+ if (skb->sk->sk_bound_dev_if == 0) {
+ dst->value = (unsigned long) "any";
+ dst->len = 3;
+ } else {
+ struct net_device *dev;
+
+ dev = dev_get_by_index(skb->sk->sk_bound_dev_if);
+ *err = var_dev(dev, dst);
+ if (dev)
+ dev_put(dev);
+ }
+}
+
+META_COLLECTOR(int_sk_refcnt)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = atomic_read(&skb->sk->sk_refcnt);
+}
+
+META_COLLECTOR(int_sk_rcvbuf)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = skb->sk->sk_rcvbuf;
+}
+
+META_COLLECTOR(int_sk_shutdown)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = skb->sk->sk_shutdown;
+}
+
+META_COLLECTOR(int_sk_proto)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = skb->sk->sk_protocol;
+}
+
+META_COLLECTOR(int_sk_type)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = skb->sk->sk_type;
+}
+
+META_COLLECTOR(int_sk_rmem_alloc)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = atomic_read(&skb->sk->sk_rmem_alloc);
+}
+
+META_COLLECTOR(int_sk_wmem_alloc)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = atomic_read(&skb->sk->sk_wmem_alloc);
+}
+
+META_COLLECTOR(int_sk_omem_alloc)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = atomic_read(&skb->sk->sk_omem_alloc);
+}
+
+META_COLLECTOR(int_sk_rcv_qlen)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = skb->sk->sk_receive_queue.qlen;
+}
+
+META_COLLECTOR(int_sk_snd_qlen)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = skb->sk->sk_write_queue.qlen;
+}
+
+META_COLLECTOR(int_sk_wmem_queued)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = skb->sk->sk_wmem_queued;
+}
+
+META_COLLECTOR(int_sk_fwd_alloc)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = skb->sk->sk_forward_alloc;
+}
+
+META_COLLECTOR(int_sk_sndbuf)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = skb->sk->sk_sndbuf;
+}
+
+META_COLLECTOR(int_sk_alloc)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = skb->sk->sk_allocation;
+}
+
+META_COLLECTOR(int_sk_route_caps)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = skb->sk->sk_route_caps;
+}
+
+META_COLLECTOR(int_sk_hashent)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = skb->sk->sk_hashent;
+}
+
+META_COLLECTOR(int_sk_lingertime)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = skb->sk->sk_lingertime / HZ;
+}
+
+META_COLLECTOR(int_sk_err_qlen)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = skb->sk->sk_error_queue.qlen;
+}
+
+META_COLLECTOR(int_sk_ack_bl)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = skb->sk->sk_ack_backlog;
+}
+
+META_COLLECTOR(int_sk_max_ack_bl)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = skb->sk->sk_max_ack_backlog;
+}
+
+META_COLLECTOR(int_sk_prio)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = skb->sk->sk_priority;
+}
+
+META_COLLECTOR(int_sk_rcvlowat)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = skb->sk->sk_rcvlowat;
+}
+
+META_COLLECTOR(int_sk_rcvtimeo)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = skb->sk->sk_rcvtimeo / HZ;
+}
+
+META_COLLECTOR(int_sk_sndtimeo)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = skb->sk->sk_sndtimeo / HZ;
+}
+
+META_COLLECTOR(int_sk_sendmsg_off)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = skb->sk->sk_sndmsg_off;
+}
+
+META_COLLECTOR(int_sk_write_pend)
+{
+ SKIP_NONLOCAL(skb);
+ dst->value = skb->sk->sk_write_pending;
+}
+
+/**************************************************************************
* Meta value collectors assignment table
**************************************************************************/
@@ -293,41 +502,75 @@ struct meta_ops
struct meta_value *, struct meta_obj *, int *);
};
+#define META_ID(name) TCF_META_ID_##name
+#define META_FUNC(name) { .get = meta_##name }
+
/* Meta value operations table listing all meta value collectors and
* assigns them to a type and meta id. */
static struct meta_ops __meta_ops[TCF_META_TYPE_MAX+1][TCF_META_ID_MAX+1] = {
[TCF_META_TYPE_VAR] = {
- [TCF_META_ID_DEV] = { .get = meta_var_dev },
- [TCF_META_ID_INDEV] = { .get = meta_var_indev },
- [TCF_META_ID_REALDEV] = { .get = meta_var_realdev }
+ [META_ID(DEV)] = META_FUNC(var_dev),
+ [META_ID(INDEV)] = META_FUNC(var_indev),
+ [META_ID(REALDEV)] = META_FUNC(var_realdev),
+ [META_ID(SK_BOUND_IF)] = META_FUNC(var_sk_bound_if),
},
[TCF_META_TYPE_INT] = {
- [TCF_META_ID_RANDOM] = { .get = meta_int_random },
- [TCF_META_ID_LOADAVG_0] = { .get = meta_int_loadavg_0 },
- [TCF_META_ID_LOADAVG_1] = { .get = meta_int_loadavg_1 },
- [TCF_META_ID_LOADAVG_2] = { .get = meta_int_loadavg_2 },
- [TCF_META_ID_DEV] = { .get = meta_int_dev },
- [TCF_META_ID_INDEV] = { .get = meta_int_indev },
- [TCF_META_ID_REALDEV] = { .get = meta_int_realdev },
- [TCF_META_ID_PRIORITY] = { .get = meta_int_priority },
- [TCF_META_ID_PROTOCOL] = { .get = meta_int_protocol },
- [TCF_META_ID_SECURITY] = { .get = meta_int_security },
- [TCF_META_ID_PKTTYPE] = { .get = meta_int_pkttype },
- [TCF_META_ID_PKTLEN] = { .get = meta_int_pktlen },
- [TCF_META_ID_DATALEN] = { .get = meta_int_datalen },
- [TCF_META_ID_MACLEN] = { .get = meta_int_maclen },
+ [META_ID(RANDOM)] = META_FUNC(int_random),
+ [META_ID(LOADAVG_0)] = META_FUNC(int_loadavg_0),
+ [META_ID(LOADAVG_1)] = META_FUNC(int_loadavg_1),
+ [META_ID(LOADAVG_2)] = META_FUNC(int_loadavg_2),
+ [META_ID(DEV)] = META_FUNC(int_dev),
+ [META_ID(INDEV)] = META_FUNC(int_indev),
+ [META_ID(REALDEV)] = META_FUNC(int_realdev),
+ [META_ID(PRIORITY)] = META_FUNC(int_priority),
+ [META_ID(PROTOCOL)] = META_FUNC(int_protocol),
+ [META_ID(SECURITY)] = META_FUNC(int_security),
+ [META_ID(PKTTYPE)] = META_FUNC(int_pkttype),
+ [META_ID(PKTLEN)] = META_FUNC(int_pktlen),
+ [META_ID(DATALEN)] = META_FUNC(int_datalen),
+ [META_ID(MACLEN)] = META_FUNC(int_maclen),
#ifdef CONFIG_NETFILTER
- [TCF_META_ID_NFMARK] = { .get = meta_int_nfmark },
+ [META_ID(NFMARK)] = META_FUNC(int_nfmark),
#endif
- [TCF_META_ID_TCINDEX] = { .get = meta_int_tcindex },
+ [META_ID(TCINDEX)] = META_FUNC(int_tcindex),
#ifdef CONFIG_NET_CLS_ACT
- [TCF_META_ID_TCVERDICT] = { .get = meta_int_tcverd },
- [TCF_META_ID_TCCLASSID] = { .get = meta_int_tcclassid },
+ [META_ID(TCVERDICT)] = META_FUNC(int_tcverd),
+ [META_ID(TCCLASSID)] = META_FUNC(int_tcclassid),
#endif
#ifdef CONFIG_NET_CLS_ROUTE
- [TCF_META_ID_RTCLASSID] = { .get = meta_int_rtclassid },
+ [META_ID(RTCLASSID)] = META_FUNC(int_rtclassid),
#endif
- [TCF_META_ID_RTIIF] = { .get = meta_int_rtiif }
+ [META_ID(RTIIF)] = META_FUNC(int_rtiif),
+ [META_ID(SK_FAMILY)] = META_FUNC(int_sk_family),
+ [META_ID(SK_STATE)] = META_FUNC(int_sk_state),
+ [META_ID(SK_REUSE)] = META_FUNC(int_sk_reuse),
+ [META_ID(SK_BOUND_IF)] = META_FUNC(int_sk_bound_if),
+ [META_ID(SK_REFCNT)] = META_FUNC(int_sk_refcnt),
+ [META_ID(SK_RCVBUF)] = META_FUNC(int_sk_rcvbuf),
+ [META_ID(SK_SNDBUF)] = META_FUNC(int_sk_sndbuf),
+ [META_ID(SK_SHUTDOWN)] = META_FUNC(int_sk_shutdown),
+ [META_ID(SK_PROTO)] = META_FUNC(int_sk_proto),
+ [META_ID(SK_TYPE)] = META_FUNC(int_sk_type),
+ [META_ID(SK_RMEM_ALLOC)] = META_FUNC(int_sk_rmem_alloc),
+ [META_ID(SK_WMEM_ALLOC)] = META_FUNC(int_sk_wmem_alloc),
+ [META_ID(SK_OMEM_ALLOC)] = META_FUNC(int_sk_omem_alloc),
+ [META_ID(SK_WMEM_QUEUED)] = META_FUNC(int_sk_wmem_queued),
+ [META_ID(SK_RCV_QLEN)] = META_FUNC(int_sk_rcv_qlen),
+ [META_ID(SK_SND_QLEN)] = META_FUNC(int_sk_snd_qlen),
+ [META_ID(SK_ERR_QLEN)] = META_FUNC(int_sk_err_qlen),
+ [META_ID(SK_FORWARD_ALLOCS)] = META_FUNC(int_sk_fwd_alloc),
+ [META_ID(SK_ALLOCS)] = META_FUNC(int_sk_alloc),
+ [META_ID(SK_ROUTE_CAPS)] = META_FUNC(int_sk_route_caps),
+ [META_ID(SK_HASHENT)] = META_FUNC(int_sk_hashent),
+ [META_ID(SK_LINGERTIME)] = META_FUNC(int_sk_lingertime),
+ [META_ID(SK_ACK_BACKLOG)] = META_FUNC(int_sk_ack_bl),
+ [META_ID(SK_MAX_ACK_BACKLOG)] = META_FUNC(int_sk_max_ack_bl),
+ [META_ID(SK_PRIO)] = META_FUNC(int_sk_prio),
+ [META_ID(SK_RCVLOWAT)] = META_FUNC(int_sk_rcvlowat),
+ [META_ID(SK_RCVTIMEO)] = META_FUNC(int_sk_rcvtimeo),
+ [META_ID(SK_SNDTIMEO)] = META_FUNC(int_sk_sndtimeo),
+ [META_ID(SK_SENDMSG_OFF)] = META_FUNC(int_sk_sendmsg_off),
+ [META_ID(SK_WRITE_PENDING)] = META_FUNC(int_sk_write_pend),
}
};
@@ -396,9 +639,9 @@ static int meta_int_compare(struct meta_obj *a, struct meta_obj *b)
/* Let gcc optimize it, the unlikely is not really based on
* some numbers but jump free code for mismatches seems
* more logical. */
- if (unlikely(a == b))
+ if (unlikely(a->value == b->value))
return 0;
- else if (a < b)
+ else if (a->value < b->value)
return -1;
else
return 1;
diff --git a/net/sched/em_text.c b/net/sched/em_text.c
new file mode 100644
index 00000000000..873840d8d07
--- /dev/null
+++ b/net/sched/em_text.c
@@ -0,0 +1,157 @@
+/*
+ * net/sched/em_text.c Textsearch ematch
+ *
+ * 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.
+ *
+ * Authors: Thomas Graf <tgraf@suug.ch>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/skbuff.h>
+#include <linux/textsearch.h>
+#include <linux/tc_ematch/tc_em_text.h>
+#include <net/pkt_cls.h>
+
+struct text_match
+{
+ u16 from_offset;
+ u16 to_offset;
+ u8 from_layer;
+ u8 to_layer;
+ struct ts_config *config;
+};
+
+#define EM_TEXT_PRIV(m) ((struct text_match *) (m)->data)
+
+static int em_text_match(struct sk_buff *skb, struct tcf_ematch *m,
+ struct tcf_pkt_info *info)
+{
+ struct text_match *tm = EM_TEXT_PRIV(m);
+ int from, to;
+ struct ts_state state;
+
+ from = tcf_get_base_ptr(skb, tm->from_layer) - skb->data;
+ from += tm->from_offset;
+
+ to = tcf_get_base_ptr(skb, tm->to_layer) - skb->data;
+ to += tm->to_offset;
+
+ return skb_find_text(skb, from, to, tm->config, &state) != UINT_MAX;
+}
+
+static int em_text_change(struct tcf_proto *tp, void *data, int len,
+ struct tcf_ematch *m)
+{
+ struct text_match *tm;
+ struct tcf_em_text *conf = data;
+ struct ts_config *ts_conf;
+ int flags = 0;
+
+ printk("Configuring text: %s from %d:%d to %d:%d len %d\n", conf->algo, conf->from_offset,
+ conf->from_layer, conf->to_offset, conf->to_layer, conf->pattern_len);
+
+ if (len < sizeof(*conf) || len < (sizeof(*conf) + conf->pattern_len))
+ return -EINVAL;
+
+ if (conf->from_layer > conf->to_layer)
+ return -EINVAL;
+
+ if (conf->from_layer == conf->to_layer &&
+ conf->from_offset > conf->to_offset)
+ return -EINVAL;
+
+retry:
+ ts_conf = textsearch_prepare(conf->algo, (u8 *) conf + sizeof(*conf),
+ conf->pattern_len, GFP_KERNEL, flags);
+
+ if (flags & TS_AUTOLOAD)
+ rtnl_lock();
+
+ if (IS_ERR(ts_conf)) {
+ if (PTR_ERR(ts_conf) == -ENOENT && !(flags & TS_AUTOLOAD)) {
+ rtnl_unlock();
+ flags |= TS_AUTOLOAD;
+ goto retry;
+ } else
+ return PTR_ERR(ts_conf);
+ } else if (flags & TS_AUTOLOAD) {
+ textsearch_destroy(ts_conf);
+ return -EAGAIN;
+ }
+
+ tm = kmalloc(sizeof(*tm), GFP_KERNEL);
+ if (tm == NULL) {
+ textsearch_destroy(ts_conf);
+ return -ENOBUFS;
+ }
+
+ tm->from_offset = conf->from_offset;
+ tm->to_offset = conf->to_offset;
+ tm->from_layer = conf->from_layer;
+ tm->to_layer = conf->to_layer;
+ tm->config = ts_conf;
+
+ m->datalen = sizeof(*tm);
+ m->data = (unsigned long) tm;
+
+ return 0;
+}
+
+static void em_text_destroy(struct tcf_proto *tp, struct tcf_ematch *m)
+{
+ textsearch_destroy(EM_TEXT_PRIV(m)->config);
+}
+
+static int em_text_dump(struct sk_buff *skb, struct tcf_ematch *m)
+{
+ struct text_match *tm = EM_TEXT_PRIV(m);
+ struct tcf_em_text conf;
+
+ strncpy(conf.algo, tm->config->ops->name, sizeof(conf.algo) - 1);
+ conf.from_offset = tm->from_offset;
+ conf.to_offset = tm->to_offset;
+ conf.from_layer = tm->from_layer;
+ conf.to_layer = tm->to_layer;
+ conf.pattern_len = textsearch_get_pattern_len(tm->config);
+ conf.pad = 0;
+
+ RTA_PUT_NOHDR(skb, sizeof(conf), &conf);
+ RTA_APPEND(skb, conf.pattern_len, textsearch_get_pattern(tm->config));
+ return 0;
+
+rtattr_failure:
+ return -1;
+}
+
+static struct tcf_ematch_ops em_text_ops = {
+ .kind = TCF_EM_TEXT,
+ .change = em_text_change,
+ .match = em_text_match,
+ .destroy = em_text_destroy,
+ .dump = em_text_dump,
+ .owner = THIS_MODULE,
+ .link = LIST_HEAD_INIT(em_text_ops.link)
+};
+
+static int __init init_em_text(void)
+{
+ return tcf_em_register(&em_text_ops);
+}
+
+static void __exit exit_em_text(void)
+{
+ tcf_em_unregister(&em_text_ops);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(init_em_text);
+module_exit(exit_em_text);
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 07977f8f267..97c1c75d5c7 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -760,15 +760,14 @@ graft:
}
static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,
- u32 pid, u32 seq, unsigned flags, int event)
+ u32 pid, u32 seq, u16 flags, int event)
{
struct tcmsg *tcm;
struct nlmsghdr *nlh;
unsigned char *b = skb->tail;
struct gnet_dump d;
- nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*tcm));
- nlh->nlmsg_flags = flags;
+ nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags);
tcm = NLMSG_DATA(nlh);
tcm->tcm_family = AF_UNSPEC;
tcm->tcm_ifindex = q->dev->ifindex;
@@ -997,7 +996,7 @@ out:
static int tc_fill_tclass(struct sk_buff *skb, struct Qdisc *q,
unsigned long cl,
- u32 pid, u32 seq, unsigned flags, int event)
+ u32 pid, u32 seq, u16 flags, int event)
{
struct tcmsg *tcm;
struct nlmsghdr *nlh;
@@ -1005,8 +1004,7 @@ static int tc_fill_tclass(struct sk_buff *skb, struct Qdisc *q,
struct gnet_dump d;
struct Qdisc_class_ops *cl_ops = q->ops->cl_ops;
- nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*tcm));
- nlh->nlmsg_flags = flags;
+ nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags);
tcm = NLMSG_DATA(nlh);
tcm->tcm_family = AF_UNSPEC;
tcm->tcm_ifindex = q->dev->ifindex;
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index 8a3db9d95ba..13e0e7b3856 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -18,7 +18,7 @@
#include <asm/byteorder.h>
-#if 1 /* control */
+#if 0 /* control */
#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
#else
#define DPRINTK(format,args...)
@@ -31,7 +31,7 @@
#endif
-#define PRIV(sch) qdisc_priv(sch)
+#define PRIV(sch) ((struct dsmark_qdisc_data *) qdisc_priv(sch))
/*
@@ -55,145 +55,163 @@
struct dsmark_qdisc_data {
struct Qdisc *q;
struct tcf_proto *filter_list;
- __u8 *mask; /* "owns" the array */
- __u8 *value;
- __u16 indices;
- __u32 default_index; /* index range is 0...0xffff */
+ u8 *mask; /* "owns" the array */
+ u8 *value;
+ u16 indices;
+ u32 default_index; /* index range is 0...0xffff */
int set_tc_index;
};
+static inline int dsmark_valid_indices(u16 indices)
+{
+ while (indices != 1) {
+ if (indices & 1)
+ return 0;
+ indices >>= 1;
+ }
+
+ return 1;
+}
-/* ------------------------- Class/flow operations ------------------------- */
+static inline int dsmark_valid_index(struct dsmark_qdisc_data *p, u16 index)
+{
+ return (index <= p->indices && index > 0);
+}
+/* ------------------------- Class/flow operations ------------------------- */
-static int dsmark_graft(struct Qdisc *sch,unsigned long arg,
- struct Qdisc *new,struct Qdisc **old)
+static int dsmark_graft(struct Qdisc *sch, unsigned long arg,
+ struct Qdisc *new, struct Qdisc **old)
{
struct dsmark_qdisc_data *p = PRIV(sch);
- DPRINTK("dsmark_graft(sch %p,[qdisc %p],new %p,old %p)\n",sch,p,new,
- old);
- if (!new)
- new = &noop_qdisc;
+ DPRINTK("dsmark_graft(sch %p,[qdisc %p],new %p,old %p)\n",
+ sch, p, new, old);
+
+ if (new == NULL) {
+ new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+ if (new == NULL)
+ new = &noop_qdisc;
+ }
+
sch_tree_lock(sch);
- *old = xchg(&p->q,new);
- if (*old)
- qdisc_reset(*old);
+ *old = xchg(&p->q, new);
+ qdisc_reset(*old);
sch->q.qlen = 0;
- sch_tree_unlock(sch); /* @@@ move up ? */
+ sch_tree_unlock(sch);
+
return 0;
}
-
static struct Qdisc *dsmark_leaf(struct Qdisc *sch, unsigned long arg)
{
- struct dsmark_qdisc_data *p = PRIV(sch);
-
- return p->q;
+ return PRIV(sch)->q;
}
-
-static unsigned long dsmark_get(struct Qdisc *sch,u32 classid)
+static unsigned long dsmark_get(struct Qdisc *sch, u32 classid)
{
- struct dsmark_qdisc_data *p __attribute__((unused)) = PRIV(sch);
+ DPRINTK("dsmark_get(sch %p,[qdisc %p],classid %x)\n",
+ sch, PRIV(sch), classid);
- DPRINTK("dsmark_get(sch %p,[qdisc %p],classid %x)\n",sch,p,classid);
- return TC_H_MIN(classid)+1;
+ return TC_H_MIN(classid) + 1;
}
-
static unsigned long dsmark_bind_filter(struct Qdisc *sch,
- unsigned long parent, u32 classid)
+ unsigned long parent, u32 classid)
{
- return dsmark_get(sch,classid);
+ return dsmark_get(sch, classid);
}
-
static void dsmark_put(struct Qdisc *sch, unsigned long cl)
{
}
-
static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent,
- struct rtattr **tca, unsigned long *arg)
+ struct rtattr **tca, unsigned long *arg)
{
struct dsmark_qdisc_data *p = PRIV(sch);
struct rtattr *opt = tca[TCA_OPTIONS-1];
struct rtattr *tb[TCA_DSMARK_MAX];
+ int err = -EINVAL;
+ u8 mask = 0;
DPRINTK("dsmark_change(sch %p,[qdisc %p],classid %x,parent %x),"
- "arg 0x%lx\n",sch,p,classid,parent,*arg);
- if (*arg > p->indices)
- return -ENOENT;
- if (!opt || rtattr_parse_nested(tb, TCA_DSMARK_MAX, opt))
- return -EINVAL;
- if (tb[TCA_DSMARK_MASK-1]) {
- if (!RTA_PAYLOAD(tb[TCA_DSMARK_MASK-1]))
- return -EINVAL;
- p->mask[*arg-1] = *(__u8 *) RTA_DATA(tb[TCA_DSMARK_MASK-1]);
- }
- if (tb[TCA_DSMARK_VALUE-1]) {
- if (!RTA_PAYLOAD(tb[TCA_DSMARK_VALUE-1]))
- return -EINVAL;
- p->value[*arg-1] = *(__u8 *) RTA_DATA(tb[TCA_DSMARK_VALUE-1]);
+ "arg 0x%lx\n", sch, p, classid, parent, *arg);
+
+ if (!dsmark_valid_index(p, *arg)) {
+ err = -ENOENT;
+ goto rtattr_failure;
}
- return 0;
-}
+ if (!opt || rtattr_parse_nested(tb, TCA_DSMARK_MAX, opt))
+ goto rtattr_failure;
+
+ if (tb[TCA_DSMARK_MASK-1])
+ mask = RTA_GET_U8(tb[TCA_DSMARK_MASK-1]);
+
+ if (tb[TCA_DSMARK_VALUE-1])
+ p->value[*arg-1] = RTA_GET_U8(tb[TCA_DSMARK_VALUE-1]);
+
+ if (tb[TCA_DSMARK_MASK-1])
+ p->mask[*arg-1] = mask;
-static int dsmark_delete(struct Qdisc *sch,unsigned long arg)
+ err = 0;
+
+rtattr_failure:
+ return err;
+}
+
+static int dsmark_delete(struct Qdisc *sch, unsigned long arg)
{
struct dsmark_qdisc_data *p = PRIV(sch);
- if (!arg || arg > p->indices)
+ if (!dsmark_valid_index(p, arg))
return -EINVAL;
+
p->mask[arg-1] = 0xff;
p->value[arg-1] = 0;
+
return 0;
}
-
static void dsmark_walk(struct Qdisc *sch,struct qdisc_walker *walker)
{
struct dsmark_qdisc_data *p = PRIV(sch);
int i;
- DPRINTK("dsmark_walk(sch %p,[qdisc %p],walker %p)\n",sch,p,walker);
+ DPRINTK("dsmark_walk(sch %p,[qdisc %p],walker %p)\n", sch, p, walker);
+
if (walker->stop)
return;
+
for (i = 0; i < p->indices; i++) {
if (p->mask[i] == 0xff && !p->value[i])
- continue;
+ goto ignore;
if (walker->count >= walker->skip) {
if (walker->fn(sch, i+1, walker) < 0) {
walker->stop = 1;
break;
}
}
- walker->count++;
+ignore:
+ walker->count++;
}
}
-
static struct tcf_proto **dsmark_find_tcf(struct Qdisc *sch,unsigned long cl)
{
- struct dsmark_qdisc_data *p = PRIV(sch);
-
- return &p->filter_list;
+ return &PRIV(sch)->filter_list;
}
-
/* --------------------------- Qdisc operations ---------------------------- */
-
static int dsmark_enqueue(struct sk_buff *skb,struct Qdisc *sch)
{
struct dsmark_qdisc_data *p = PRIV(sch);
- struct tcf_result res;
- int result;
- int ret = NET_XMIT_POLICED;
+ int err;
+
+ D2PRINTK("dsmark_enqueue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p);
- D2PRINTK("dsmark_enqueue(skb %p,sch %p,[qdisc %p])\n",skb,sch,p);
if (p->set_tc_index) {
/* FIXME: Safe with non-linear skbs? --RR */
switch (skb->protocol) {
@@ -210,17 +228,21 @@ static int dsmark_enqueue(struct sk_buff *skb,struct Qdisc *sch)
break;
};
}
- result = TC_POLICE_OK; /* be nice to gcc */
- if (TC_H_MAJ(skb->priority) == sch->handle) {
+
+ if (TC_H_MAJ(skb->priority) == sch->handle)
skb->tc_index = TC_H_MIN(skb->priority);
- } else {
- result = tc_classify(skb,p->filter_list,&res);
- D2PRINTK("result %d class 0x%04x\n",result,res.classid);
+ else {
+ struct tcf_result res;
+ int result = tc_classify(skb, p->filter_list, &res);
+
+ D2PRINTK("result %d class 0x%04x\n", result, res.classid);
+
switch (result) {
#ifdef CONFIG_NET_CLS_POLICE
case TC_POLICE_SHOT:
kfree_skb(skb);
- break;
+ sch->qstats.drops++;
+ return NET_XMIT_POLICED;
#if 0
case TC_POLICE_RECLASSIFY:
/* FIXME: what to do here ??? */
@@ -237,43 +259,45 @@ static int dsmark_enqueue(struct sk_buff *skb,struct Qdisc *sch)
break;
};
}
- if (
-#ifdef CONFIG_NET_CLS_POLICE
- result == TC_POLICE_SHOT ||
-#endif
- ((ret = p->q->enqueue(skb,p->q)) != 0)) {
+ err = p->q->enqueue(skb,p->q);
+ if (err != NET_XMIT_SUCCESS) {
sch->qstats.drops++;
- return ret;
+ return err;
}
+
sch->bstats.bytes += skb->len;
sch->bstats.packets++;
sch->q.qlen++;
- return ret;
-}
+ return NET_XMIT_SUCCESS;
+}
static struct sk_buff *dsmark_dequeue(struct Qdisc *sch)
{
struct dsmark_qdisc_data *p = PRIV(sch);
struct sk_buff *skb;
- int index;
+ u32 index;
+
+ D2PRINTK("dsmark_dequeue(sch %p,[qdisc %p])\n", sch, p);
- D2PRINTK("dsmark_dequeue(sch %p,[qdisc %p])\n",sch,p);
skb = p->q->ops->dequeue(p->q);
- if (!skb)
+ if (skb == NULL)
return NULL;
+
sch->q.qlen--;
- index = skb->tc_index & (p->indices-1);
- D2PRINTK("index %d->%d\n",skb->tc_index,index);
+
+ index = skb->tc_index & (p->indices - 1);
+ D2PRINTK("index %d->%d\n", skb->tc_index, index);
+
switch (skb->protocol) {
case __constant_htons(ETH_P_IP):
- ipv4_change_dsfield(skb->nh.iph,
- p->mask[index],p->value[index]);
+ ipv4_change_dsfield(skb->nh.iph, p->mask[index],
+ p->value[index]);
break;
case __constant_htons(ETH_P_IPV6):
- ipv6_change_dsfield(skb->nh.ipv6h,
- p->mask[index],p->value[index]);
+ ipv6_change_dsfield(skb->nh.ipv6h, p->mask[index],
+ p->value[index]);
break;
default:
/*
@@ -287,152 +311,162 @@ static struct sk_buff *dsmark_dequeue(struct Qdisc *sch)
htons(skb->protocol));
break;
};
+
return skb;
}
-
static int dsmark_requeue(struct sk_buff *skb,struct Qdisc *sch)
{
- int ret;
struct dsmark_qdisc_data *p = PRIV(sch);
+ int err;
- D2PRINTK("dsmark_requeue(skb %p,sch %p,[qdisc %p])\n",skb,sch,p);
- if ((ret = p->q->ops->requeue(skb, p->q)) == 0) {
- sch->q.qlen++;
- sch->qstats.requeues++;
- return 0;
+ D2PRINTK("dsmark_requeue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p);
+
+ err = p->q->ops->requeue(skb, p->q);
+ if (err != NET_XMIT_SUCCESS) {
+ sch->qstats.drops++;
+ return err;
}
- sch->qstats.drops++;
- return ret;
-}
+ sch->q.qlen++;
+ sch->qstats.requeues++;
+
+ return NET_XMIT_SUCCESS;
+}
static unsigned int dsmark_drop(struct Qdisc *sch)
{
struct dsmark_qdisc_data *p = PRIV(sch);
unsigned int len;
- DPRINTK("dsmark_reset(sch %p,[qdisc %p])\n",sch,p);
- if (!p->q->ops->drop)
- return 0;
- if (!(len = p->q->ops->drop(p->q)))
+ DPRINTK("dsmark_reset(sch %p,[qdisc %p])\n", sch, p);
+
+ if (p->q->ops->drop == NULL)
return 0;
- sch->q.qlen--;
+
+ len = p->q->ops->drop(p->q);
+ if (len)
+ sch->q.qlen--;
+
return len;
}
-
-static int dsmark_init(struct Qdisc *sch,struct rtattr *opt)
+static int dsmark_init(struct Qdisc *sch, struct rtattr *opt)
{
struct dsmark_qdisc_data *p = PRIV(sch);
struct rtattr *tb[TCA_DSMARK_MAX];
- __u16 tmp;
-
- DPRINTK("dsmark_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt);
- if (!opt ||
- rtattr_parse(tb,TCA_DSMARK_MAX,RTA_DATA(opt),RTA_PAYLOAD(opt)) < 0 ||
- !tb[TCA_DSMARK_INDICES-1] ||
- RTA_PAYLOAD(tb[TCA_DSMARK_INDICES-1]) < sizeof(__u16))
- return -EINVAL;
- p->indices = *(__u16 *) RTA_DATA(tb[TCA_DSMARK_INDICES-1]);
- if (!p->indices)
- return -EINVAL;
- for (tmp = p->indices; tmp != 1; tmp >>= 1) {
- if (tmp & 1)
- return -EINVAL;
- }
- p->default_index = NO_DEFAULT_INDEX;
- if (tb[TCA_DSMARK_DEFAULT_INDEX-1]) {
- if (RTA_PAYLOAD(tb[TCA_DSMARK_DEFAULT_INDEX-1]) < sizeof(__u16))
- return -EINVAL;
- p->default_index =
- *(__u16 *) RTA_DATA(tb[TCA_DSMARK_DEFAULT_INDEX-1]);
+ int err = -EINVAL;
+ u32 default_index = NO_DEFAULT_INDEX;
+ u16 indices;
+ u8 *mask;
+
+ DPRINTK("dsmark_init(sch %p,[qdisc %p],opt %p)\n", sch, p, opt);
+
+ if (!opt || rtattr_parse_nested(tb, TCA_DSMARK_MAX, opt) < 0)
+ goto errout;
+
+ indices = RTA_GET_U16(tb[TCA_DSMARK_INDICES-1]);
+ if (!indices || !dsmark_valid_indices(indices))
+ goto errout;
+
+ if (tb[TCA_DSMARK_DEFAULT_INDEX-1])
+ default_index = RTA_GET_U16(tb[TCA_DSMARK_DEFAULT_INDEX-1]);
+
+ mask = kmalloc(indices * 2, GFP_KERNEL);
+ if (mask == NULL) {
+ err = -ENOMEM;
+ goto errout;
}
- p->set_tc_index = !!tb[TCA_DSMARK_SET_TC_INDEX-1];
- p->mask = kmalloc(p->indices*2,GFP_KERNEL);
- if (!p->mask)
- return -ENOMEM;
- p->value = p->mask+p->indices;
- memset(p->mask,0xff,p->indices);
- memset(p->value,0,p->indices);
- if (!(p->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops)))
+
+ p->mask = mask;
+ memset(p->mask, 0xff, indices);
+
+ p->value = p->mask + indices;
+ memset(p->value, 0, indices);
+
+ p->indices = indices;
+ p->default_index = default_index;
+ p->set_tc_index = RTA_GET_FLAG(tb[TCA_DSMARK_SET_TC_INDEX-1]);
+
+ p->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+ if (p->q == NULL)
p->q = &noop_qdisc;
- DPRINTK("dsmark_init: qdisc %p\n",&p->q);
- return 0;
-}
+ DPRINTK("dsmark_init: qdisc %p\n", p->q);
+
+ err = 0;
+errout:
+rtattr_failure:
+ return err;
+}
static void dsmark_reset(struct Qdisc *sch)
{
struct dsmark_qdisc_data *p = PRIV(sch);
- DPRINTK("dsmark_reset(sch %p,[qdisc %p])\n",sch,p);
+ DPRINTK("dsmark_reset(sch %p,[qdisc %p])\n", sch, p);
qdisc_reset(p->q);
sch->q.qlen = 0;
}
-
static void dsmark_destroy(struct Qdisc *sch)
{
struct dsmark_qdisc_data *p = PRIV(sch);
struct tcf_proto *tp;
- DPRINTK("dsmark_destroy(sch %p,[qdisc %p])\n",sch,p);
+ DPRINTK("dsmark_destroy(sch %p,[qdisc %p])\n", sch, p);
+
while (p->filter_list) {
tp = p->filter_list;
p->filter_list = tp->next;
tcf_destroy(tp);
}
+
qdisc_destroy(p->q);
kfree(p->mask);
}
-
static int dsmark_dump_class(struct Qdisc *sch, unsigned long cl,
- struct sk_buff *skb, struct tcmsg *tcm)
+ struct sk_buff *skb, struct tcmsg *tcm)
{
struct dsmark_qdisc_data *p = PRIV(sch);
- unsigned char *b = skb->tail;
- struct rtattr *rta;
+ struct rtattr *opts = NULL;
+
+ DPRINTK("dsmark_dump_class(sch %p,[qdisc %p],class %ld\n", sch, p, cl);
- DPRINTK("dsmark_dump_class(sch %p,[qdisc %p],class %ld\n",sch,p,cl);
- if (!cl || cl > p->indices)
+ if (!dsmark_valid_index(p, cl))
return -EINVAL;
- tcm->tcm_handle = TC_H_MAKE(TC_H_MAJ(sch->handle),cl-1);
- rta = (struct rtattr *) b;
- RTA_PUT(skb,TCA_OPTIONS,0,NULL);
- RTA_PUT(skb,TCA_DSMARK_MASK,1,&p->mask[cl-1]);
- RTA_PUT(skb,TCA_DSMARK_VALUE,1,&p->value[cl-1]);
- rta->rta_len = skb->tail-b;
- return skb->len;
+
+ tcm->tcm_handle = TC_H_MAKE(TC_H_MAJ(sch->handle), cl-1);
+
+ opts = RTA_NEST(skb, TCA_OPTIONS);
+ RTA_PUT_U8(skb,TCA_DSMARK_MASK, p->mask[cl-1]);
+ RTA_PUT_U8(skb,TCA_DSMARK_VALUE, p->value[cl-1]);
+
+ return RTA_NEST_END(skb, opts);
rtattr_failure:
- skb_trim(skb,b-skb->data);
- return -1;
+ return RTA_NEST_CANCEL(skb, opts);
}
static int dsmark_dump(struct Qdisc *sch, struct sk_buff *skb)
{
struct dsmark_qdisc_data *p = PRIV(sch);
- unsigned char *b = skb->tail;
- struct rtattr *rta;
+ struct rtattr *opts = NULL;
- rta = (struct rtattr *) b;
- RTA_PUT(skb,TCA_OPTIONS,0,NULL);
- RTA_PUT(skb,TCA_DSMARK_INDICES,sizeof(__u16),&p->indices);
- if (p->default_index != NO_DEFAULT_INDEX) {
- __u16 tmp = p->default_index;
+ opts = RTA_NEST(skb, TCA_OPTIONS);
+ RTA_PUT_U16(skb, TCA_DSMARK_INDICES, p->indices);
+
+ if (p->default_index != NO_DEFAULT_INDEX)
+ RTA_PUT_U16(skb, TCA_DSMARK_DEFAULT_INDEX, p->default_index);
- RTA_PUT(skb,TCA_DSMARK_DEFAULT_INDEX, sizeof(__u16), &tmp);
- }
if (p->set_tc_index)
- RTA_PUT(skb, TCA_DSMARK_SET_TC_INDEX, 0, NULL);
- rta->rta_len = skb->tail-b;
- return skb->len;
+ RTA_PUT_FLAG(skb, TCA_DSMARK_SET_TC_INDEX);
+
+ return RTA_NEST_END(skb, opts);
rtattr_failure:
- skb_trim(skb,b-skb->data);
- return -1;
+ return RTA_NEST_CANCEL(skb, opts);
}
static struct Qdisc_class_ops dsmark_class_ops = {
@@ -470,10 +504,13 @@ static int __init dsmark_module_init(void)
{
return register_qdisc(&dsmark_qdisc_ops);
}
+
static void __exit dsmark_module_exit(void)
{
unregister_qdisc(&dsmark_qdisc_ops);
}
+
module_init(dsmark_module_init)
module_exit(dsmark_module_exit)
+
MODULE_LICENSE("GPL");
diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c
index 4888305c96d..033083bf0e7 100644
--- a/net/sched/sch_fifo.c
+++ b/net/sched/sch_fifo.c
@@ -11,131 +11,38 @@
#include <linux/config.h>
#include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
#include <linux/types.h>
#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <net/ip.h>
-#include <net/route.h>
#include <linux/skbuff.h>
-#include <net/sock.h>
#include <net/pkt_sched.h>
/* 1 band FIFO pseudo-"scheduler" */
struct fifo_sched_data
{
- unsigned limit;
+ u32 limit;
};
-static int
-bfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch)
+static int bfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch)
{
struct fifo_sched_data *q = qdisc_priv(sch);
- if (sch->qstats.backlog + skb->len <= q->limit) {
- __skb_queue_tail(&sch->q, skb);
- sch->qstats.backlog += skb->len;
- sch->bstats.bytes += skb->len;
- sch->bstats.packets++;
- return 0;
- }
- sch->qstats.drops++;
-#ifdef CONFIG_NET_CLS_POLICE
- if (sch->reshape_fail==NULL || sch->reshape_fail(skb, sch))
-#endif
- kfree_skb(skb);
- return NET_XMIT_DROP;
-}
-
-static int
-bfifo_requeue(struct sk_buff *skb, struct Qdisc* sch)
-{
- __skb_queue_head(&sch->q, skb);
- sch->qstats.backlog += skb->len;
- sch->qstats.requeues++;
- return 0;
-}
-
-static struct sk_buff *
-bfifo_dequeue(struct Qdisc* sch)
-{
- struct sk_buff *skb;
+ if (likely(sch->qstats.backlog + skb->len <= q->limit))
+ return qdisc_enqueue_tail(skb, sch);
- skb = __skb_dequeue(&sch->q);
- if (skb)
- sch->qstats.backlog -= skb->len;
- return skb;
+ return qdisc_reshape_fail(skb, sch);
}
-static unsigned int
-fifo_drop(struct Qdisc* sch)
-{
- struct sk_buff *skb;
-
- skb = __skb_dequeue_tail(&sch->q);
- if (skb) {
- unsigned int len = skb->len;
- sch->qstats.backlog -= len;
- kfree_skb(skb);
- return len;
- }
- return 0;
-}
-
-static void
-fifo_reset(struct Qdisc* sch)
-{
- skb_queue_purge(&sch->q);
- sch->qstats.backlog = 0;
-}
-
-static int
-pfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch)
+static int pfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch)
{
struct fifo_sched_data *q = qdisc_priv(sch);
- if (sch->q.qlen < q->limit) {
- __skb_queue_tail(&sch->q, skb);
- sch->bstats.bytes += skb->len;
- sch->bstats.packets++;
- return 0;
- }
- sch->qstats.drops++;
-#ifdef CONFIG_NET_CLS_POLICE
- if (sch->reshape_fail==NULL || sch->reshape_fail(skb, sch))
-#endif
- kfree_skb(skb);
- return NET_XMIT_DROP;
-}
-
-static int
-pfifo_requeue(struct sk_buff *skb, struct Qdisc* sch)
-{
- __skb_queue_head(&sch->q, skb);
- sch->qstats.requeues++;
- return 0;
-}
-
+ if (likely(skb_queue_len(&sch->q) < q->limit))
+ return qdisc_enqueue_tail(skb, sch);
-static struct sk_buff *
-pfifo_dequeue(struct Qdisc* sch)
-{
- return __skb_dequeue(&sch->q);
+ return qdisc_reshape_fail(skb, sch);
}
static int fifo_init(struct Qdisc *sch, struct rtattr *opt)
@@ -143,66 +50,59 @@ static int fifo_init(struct Qdisc *sch, struct rtattr *opt)
struct fifo_sched_data *q = qdisc_priv(sch);
if (opt == NULL) {
- unsigned int limit = sch->dev->tx_queue_len ? : 1;
+ u32 limit = sch->dev->tx_queue_len ? : 1;
if (sch->ops == &bfifo_qdisc_ops)
- q->limit = limit*sch->dev->mtu;
- else
- q->limit = limit;
+ limit *= sch->dev->mtu;
+
+ q->limit = limit;
} else {
struct tc_fifo_qopt *ctl = RTA_DATA(opt);
- if (opt->rta_len < RTA_LENGTH(sizeof(*ctl)))
+
+ if (RTA_PAYLOAD(opt) < sizeof(*ctl))
return -EINVAL;
+
q->limit = ctl->limit;
}
+
return 0;
}
static int fifo_dump(struct Qdisc *sch, struct sk_buff *skb)
{
struct fifo_sched_data *q = qdisc_priv(sch);
- unsigned char *b = skb->tail;
- struct tc_fifo_qopt opt;
+ struct tc_fifo_qopt opt = { .limit = q->limit };
- opt.limit = q->limit;
RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
-
return skb->len;
rtattr_failure:
- skb_trim(skb, b - skb->data);
return -1;
}
struct Qdisc_ops pfifo_qdisc_ops = {
- .next = NULL,
- .cl_ops = NULL,
.id = "pfifo",
.priv_size = sizeof(struct fifo_sched_data),
.enqueue = pfifo_enqueue,
- .dequeue = pfifo_dequeue,
- .requeue = pfifo_requeue,
- .drop = fifo_drop,
+ .dequeue = qdisc_dequeue_head,
+ .requeue = qdisc_requeue,
+ .drop = qdisc_queue_drop,
.init = fifo_init,
- .reset = fifo_reset,
- .destroy = NULL,
+ .reset = qdisc_reset_queue,
.change = fifo_init,
.dump = fifo_dump,
.owner = THIS_MODULE,
};
struct Qdisc_ops bfifo_qdisc_ops = {
- .next = NULL,
- .cl_ops = NULL,
.id = "bfifo",
.priv_size = sizeof(struct fifo_sched_data),
.enqueue = bfifo_enqueue,
- .dequeue = bfifo_dequeue,
- .requeue = bfifo_requeue,
- .drop = fifo_drop,
+ .dequeue = qdisc_dequeue_head,
+ .requeue = qdisc_requeue,
+ .drop = qdisc_queue_drop,
.init = fifo_init,
- .reset = fifo_reset,
- .destroy = NULL,
+ .reset = qdisc_reset_queue,
.change = fifo_init,
.dump = fifo_dump,
.owner = THIS_MODULE,
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 87e48a4e105..7683b34dc6a 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -243,31 +243,27 @@ static void dev_watchdog_down(struct net_device *dev)
cheaper.
*/
-static int
-noop_enqueue(struct sk_buff *skb, struct Qdisc * qdisc)
+static int noop_enqueue(struct sk_buff *skb, struct Qdisc * qdisc)
{
kfree_skb(skb);
return NET_XMIT_CN;
}
-static struct sk_buff *
-noop_dequeue(struct Qdisc * qdisc)
+static struct sk_buff *noop_dequeue(struct Qdisc * qdisc)
{
return NULL;
}
-static int
-noop_requeue(struct sk_buff *skb, struct Qdisc* qdisc)
+static int noop_requeue(struct sk_buff *skb, struct Qdisc* qdisc)
{
if (net_ratelimit())
- printk(KERN_DEBUG "%s deferred output. It is buggy.\n", skb->dev->name);
+ printk(KERN_DEBUG "%s deferred output. It is buggy.\n",
+ skb->dev->name);
kfree_skb(skb);
return NET_XMIT_CN;
}
struct Qdisc_ops noop_qdisc_ops = {
- .next = NULL,
- .cl_ops = NULL,
.id = "noop",
.priv_size = 0,
.enqueue = noop_enqueue,
@@ -285,8 +281,6 @@ struct Qdisc noop_qdisc = {
};
static struct Qdisc_ops noqueue_qdisc_ops = {
- .next = NULL,
- .cl_ops = NULL,
.id = "noqueue",
.priv_size = 0,
.enqueue = noop_enqueue,
@@ -311,97 +305,87 @@ static const u8 prio2band[TC_PRIO_MAX+1] =
generic prio+fifo combination.
*/
-static int
-pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc)
+#define PFIFO_FAST_BANDS 3
+
+static inline struct sk_buff_head *prio2list(struct sk_buff *skb,
+ struct Qdisc *qdisc)
{
struct sk_buff_head *list = qdisc_priv(qdisc);
+ return list + prio2band[skb->priority & TC_PRIO_MAX];
+}
- list += prio2band[skb->priority&TC_PRIO_MAX];
+static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc)
+{
+ struct sk_buff_head *list = prio2list(skb, qdisc);
- if (list->qlen < qdisc->dev->tx_queue_len) {
- __skb_queue_tail(list, skb);
+ if (skb_queue_len(list) < qdisc->dev->tx_queue_len) {
qdisc->q.qlen++;
- qdisc->bstats.bytes += skb->len;
- qdisc->bstats.packets++;
- return 0;
+ return __qdisc_enqueue_tail(skb, qdisc, list);
}
- qdisc->qstats.drops++;
- kfree_skb(skb);
- return NET_XMIT_DROP;
+
+ return qdisc_drop(skb, qdisc);
}
-static struct sk_buff *
-pfifo_fast_dequeue(struct Qdisc* qdisc)
+static struct sk_buff *pfifo_fast_dequeue(struct Qdisc* qdisc)
{
int prio;
struct sk_buff_head *list = qdisc_priv(qdisc);
- struct sk_buff *skb;
- for (prio = 0; prio < 3; prio++, list++) {
- skb = __skb_dequeue(list);
+ for (prio = 0; prio < PFIFO_FAST_BANDS; prio++, list++) {
+ struct sk_buff *skb = __qdisc_dequeue_head(qdisc, list);
if (skb) {
qdisc->q.qlen--;
return skb;
}
}
+
return NULL;
}
-static int
-pfifo_fast_requeue(struct sk_buff *skb, struct Qdisc* qdisc)
+static int pfifo_fast_requeue(struct sk_buff *skb, struct Qdisc* qdisc)
{
- struct sk_buff_head *list = qdisc_priv(qdisc);
-
- list += prio2band[skb->priority&TC_PRIO_MAX];
-
- __skb_queue_head(list, skb);
qdisc->q.qlen++;
- qdisc->qstats.requeues++;
- return 0;
+ return __qdisc_requeue(skb, qdisc, prio2list(skb, qdisc));
}
-static void
-pfifo_fast_reset(struct Qdisc* qdisc)
+static void pfifo_fast_reset(struct Qdisc* qdisc)
{
int prio;
struct sk_buff_head *list = qdisc_priv(qdisc);
- for (prio=0; prio < 3; prio++)
- skb_queue_purge(list+prio);
+ for (prio = 0; prio < PFIFO_FAST_BANDS; prio++)
+ __qdisc_reset_queue(qdisc, list + prio);
+
+ qdisc->qstats.backlog = 0;
qdisc->q.qlen = 0;
}
static int pfifo_fast_dump(struct Qdisc *qdisc, struct sk_buff *skb)
{
- unsigned char *b = skb->tail;
- struct tc_prio_qopt opt;
+ struct tc_prio_qopt opt = { .bands = PFIFO_FAST_BANDS };
- opt.bands = 3;
memcpy(&opt.priomap, prio2band, TC_PRIO_MAX+1);
RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
return skb->len;
rtattr_failure:
- skb_trim(skb, b - skb->data);
return -1;
}
static int pfifo_fast_init(struct Qdisc *qdisc, struct rtattr *opt)
{
- int i;
+ int prio;
struct sk_buff_head *list = qdisc_priv(qdisc);
- for (i=0; i<3; i++)
- skb_queue_head_init(list+i);
+ for (prio = 0; prio < PFIFO_FAST_BANDS; prio++)
+ skb_queue_head_init(list + prio);
return 0;
}
static struct Qdisc_ops pfifo_fast_ops = {
- .next = NULL,
- .cl_ops = NULL,
.id = "pfifo_fast",
- .priv_size = 3 * sizeof(struct sk_buff_head),
+ .priv_size = PFIFO_FAST_BANDS * sizeof(struct sk_buff_head),
.enqueue = pfifo_fast_enqueue,
.dequeue = pfifo_fast_dequeue,
.requeue = pfifo_fast_requeue,
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index e0c9fbe73b1..bb9bf8d5003 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -53,7 +53,6 @@
struct netem_sched_data {
struct Qdisc *qdisc;
- struct sk_buff_head delayed;
struct timer_list timer;
u32 latency;
@@ -63,11 +62,12 @@ struct netem_sched_data {
u32 gap;
u32 jitter;
u32 duplicate;
+ u32 reorder;
struct crndstate {
unsigned long last;
unsigned long rho;
- } delay_cor, loss_cor, dup_cor;
+ } delay_cor, loss_cor, dup_cor, reorder_cor;
struct disttable {
u32 size;
@@ -137,122 +137,68 @@ static long tabledist(unsigned long mu, long sigma,
return x / NETEM_DIST_SCALE + (sigma / NETEM_DIST_SCALE) * t + mu;
}
-/* Put skb in the private delayed queue. */
-static int netem_delay(struct Qdisc *sch, struct sk_buff *skb)
-{
- struct netem_sched_data *q = qdisc_priv(sch);
- psched_tdiff_t td;
- psched_time_t now;
-
- PSCHED_GET_TIME(now);
- td = tabledist(q->latency, q->jitter, &q->delay_cor, q->delay_dist);
-
- /* Always queue at tail to keep packets in order */
- if (likely(q->delayed.qlen < q->limit)) {
- struct netem_skb_cb *cb = (struct netem_skb_cb *)skb->cb;
-
- PSCHED_TADD2(now, td, cb->time_to_send);
-
- pr_debug("netem_delay: skb=%p now=%llu tosend=%llu\n", skb,
- now, cb->time_to_send);
-
- __skb_queue_tail(&q->delayed, skb);
- return NET_XMIT_SUCCESS;
- }
-
- pr_debug("netem_delay: queue over limit %d\n", q->limit);
- sch->qstats.overlimits++;
- kfree_skb(skb);
- return NET_XMIT_DROP;
-}
-
/*
- * Move a packet that is ready to send from the delay holding
- * list to the underlying qdisc.
+ * Insert one skb into qdisc.
+ * Note: parent depends on return value to account for queue length.
+ * NET_XMIT_DROP: queue length didn't change.
+ * NET_XMIT_SUCCESS: one skb was queued.
*/
-static int netem_run(struct Qdisc *sch)
-{
- struct netem_sched_data *q = qdisc_priv(sch);
- struct sk_buff *skb;
- psched_time_t now;
-
- PSCHED_GET_TIME(now);
-
- skb = skb_peek(&q->delayed);
- if (skb) {
- const struct netem_skb_cb *cb
- = (const struct netem_skb_cb *)skb->cb;
- long delay
- = PSCHED_US2JIFFIE(PSCHED_TDIFF(cb->time_to_send, now));
- pr_debug("netem_run: skb=%p delay=%ld\n", skb, delay);
-
- /* if more time remaining? */
- if (delay > 0) {
- mod_timer(&q->timer, jiffies + delay);
- return 1;
- }
-
- __skb_unlink(skb, &q->delayed);
-
- if (q->qdisc->enqueue(skb, q->qdisc)) {
- sch->q.qlen--;
- sch->qstats.drops++;
- }
- }
-
- return 0;
-}
-
static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
{
struct netem_sched_data *q = qdisc_priv(sch);
+ struct netem_skb_cb *cb = (struct netem_skb_cb *)skb->cb;
+ struct sk_buff *skb2;
int ret;
+ int count = 1;
pr_debug("netem_enqueue skb=%p\n", skb);
+ /* Random duplication */
+ if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor))
+ ++count;
+
/* Random packet drop 0 => none, ~0 => all */
- if (q->loss && q->loss >= get_crandom(&q->loss_cor)) {
- pr_debug("netem_enqueue: random loss\n");
+ if (q->loss && q->loss >= get_crandom(&q->loss_cor))
+ --count;
+
+ if (count == 0) {
sch->qstats.drops++;
kfree_skb(skb);
- return 0; /* lie about loss so TCP doesn't know */
+ return NET_XMIT_DROP;
}
- /* Random duplication */
- if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor)) {
- struct sk_buff *skb2;
-
- skb2 = skb_clone(skb, GFP_ATOMIC);
- if (skb2 && netem_delay(sch, skb2) == NET_XMIT_SUCCESS) {
- struct Qdisc *qp;
-
- /* Since one packet can generate two packets in the
- * queue, the parent's qlen accounting gets confused,
- * so fix it.
- */
- qp = qdisc_lookup(sch->dev, TC_H_MAJ(sch->parent));
- if (qp)
- qp->q.qlen++;
-
- sch->q.qlen++;
- sch->bstats.bytes += skb2->len;
- sch->bstats.packets++;
- } else
- sch->qstats.drops++;
+ /*
+ * If we need to duplicate packet, then re-insert at top of the
+ * qdisc tree, since parent queuer expects that only one
+ * skb will be queued.
+ */
+ if (count > 1 && (skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) {
+ struct Qdisc *rootq = sch->dev->qdisc;
+ u32 dupsave = q->duplicate; /* prevent duplicating a dup... */
+ q->duplicate = 0;
+
+ rootq->enqueue(skb2, rootq);
+ q->duplicate = dupsave;
}
- /* If doing simple delay then gap == 0 so all packets
- * go into the delayed holding queue
- * otherwise if doing out of order only "1 out of gap"
- * packets will be delayed.
- */
- if (q->counter < q->gap) {
+ if (q->gap == 0 /* not doing reordering */
+ || q->counter < q->gap /* inside last reordering gap */
+ || q->reorder < get_crandom(&q->reorder_cor)) {
+ psched_time_t now;
+ PSCHED_GET_TIME(now);
+ PSCHED_TADD2(now, tabledist(q->latency, q->jitter,
+ &q->delay_cor, q->delay_dist),
+ cb->time_to_send);
++q->counter;
ret = q->qdisc->enqueue(skb, q->qdisc);
} else {
+ /*
+ * Do re-ordering by putting one out of N packets at the front
+ * of the queue.
+ */
+ PSCHED_GET_TIME(cb->time_to_send);
q->counter = 0;
- ret = netem_delay(sch, skb);
- netem_run(sch);
+ ret = q->qdisc->ops->requeue(skb, q->qdisc);
}
if (likely(ret == NET_XMIT_SUCCESS)) {
@@ -296,22 +242,33 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)
{
struct netem_sched_data *q = qdisc_priv(sch);
struct sk_buff *skb;
- int pending;
-
- pending = netem_run(sch);
skb = q->qdisc->dequeue(q->qdisc);
if (skb) {
- pr_debug("netem_dequeue: return skb=%p\n", skb);
- sch->q.qlen--;
- sch->flags &= ~TCQ_F_THROTTLED;
- }
- else if (pending) {
- pr_debug("netem_dequeue: throttling\n");
+ const struct netem_skb_cb *cb
+ = (const struct netem_skb_cb *)skb->cb;
+ psched_time_t now;
+ long delay;
+
+ /* if more time remaining? */
+ PSCHED_GET_TIME(now);
+ delay = PSCHED_US2JIFFIE(PSCHED_TDIFF(cb->time_to_send, now));
+ pr_debug("netem_run: skb=%p delay=%ld\n", skb, delay);
+ if (delay <= 0) {
+ pr_debug("netem_dequeue: return skb=%p\n", skb);
+ sch->q.qlen--;
+ sch->flags &= ~TCQ_F_THROTTLED;
+ return skb;
+ }
+
+ mod_timer(&q->timer, jiffies + delay);
sch->flags |= TCQ_F_THROTTLED;
- }
- return skb;
+ if (q->qdisc->ops->requeue(skb, q->qdisc) != 0)
+ sch->qstats.drops++;
+ }
+
+ return NULL;
}
static void netem_watchdog(unsigned long arg)
@@ -328,8 +285,6 @@ static void netem_reset(struct Qdisc *sch)
struct netem_sched_data *q = qdisc_priv(sch);
qdisc_reset(q->qdisc);
- skb_queue_purge(&q->delayed);
-
sch->q.qlen = 0;
sch->flags &= ~TCQ_F_THROTTLED;
del_timer_sync(&q->timer);
@@ -397,6 +352,19 @@ static int get_correlation(struct Qdisc *sch, const struct rtattr *attr)
return 0;
}
+static int get_reorder(struct Qdisc *sch, const struct rtattr *attr)
+{
+ struct netem_sched_data *q = qdisc_priv(sch);
+ const struct tc_netem_reorder *r = RTA_DATA(attr);
+
+ if (RTA_PAYLOAD(attr) != sizeof(*r))
+ return -EINVAL;
+
+ q->reorder = r->probability;
+ init_crandom(&q->reorder_cor, r->correlation);
+ return 0;
+}
+
static int netem_change(struct Qdisc *sch, struct rtattr *opt)
{
struct netem_sched_data *q = qdisc_priv(sch);
@@ -417,9 +385,15 @@ static int netem_change(struct Qdisc *sch, struct rtattr *opt)
q->jitter = qopt->jitter;
q->limit = qopt->limit;
q->gap = qopt->gap;
+ q->counter = 0;
q->loss = qopt->loss;
q->duplicate = qopt->duplicate;
+ /* for compatiablity with earlier versions.
+ * if gap is set, need to assume 100% probablity
+ */
+ q->reorder = ~0;
+
/* Handle nested options after initial queue options.
* Should have put all options in nested format but too late now.
*/
@@ -441,6 +415,11 @@ static int netem_change(struct Qdisc *sch, struct rtattr *opt)
if (ret)
return ret;
}
+ if (tb[TCA_NETEM_REORDER-1]) {
+ ret = get_reorder(sch, tb[TCA_NETEM_REORDER-1]);
+ if (ret)
+ return ret;
+ }
}
@@ -455,11 +434,9 @@ static int netem_init(struct Qdisc *sch, struct rtattr *opt)
if (!opt)
return -EINVAL;
- skb_queue_head_init(&q->delayed);
init_timer(&q->timer);
q->timer.function = netem_watchdog;
q->timer.data = (unsigned long) sch;
- q->counter = 0;
q->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
if (!q->qdisc) {
@@ -491,6 +468,7 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
struct rtattr *rta = (struct rtattr *) b;
struct tc_netem_qopt qopt;
struct tc_netem_corr cor;
+ struct tc_netem_reorder reorder;
qopt.latency = q->latency;
qopt.jitter = q->jitter;
@@ -504,6 +482,11 @@ static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
cor.loss_corr = q->loss_cor.rho;
cor.dup_corr = q->dup_cor.rho;
RTA_PUT(skb, TCA_NETEM_CORR, sizeof(cor), &cor);
+
+ reorder.probability = q->reorder;
+ reorder.correlation = q->reorder_cor.rho;
+ RTA_PUT(skb, TCA_NETEM_REORDER, sizeof(reorder), &reorder);
+
rta->rta_len = skb->tail - b;
return skb->len;
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 663843d97a9..7ae6aa772da 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -191,10 +191,6 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
asoc->last_cwr_tsn = asoc->ctsn_ack_point;
asoc->unack_data = 0;
- SCTP_DEBUG_PRINTK("myctsnap for %s INIT as 0x%x.\n",
- asoc->ep->debug_name,
- asoc->ctsn_ack_point);
-
/* ADDIP Section 4.1 Asconf Chunk Procedures
*
* When an endpoint has an ASCONF signaled change to be sent to the
@@ -211,6 +207,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
/* Make an empty list of remote transport addresses. */
INIT_LIST_HEAD(&asoc->peer.transport_addr_list);
+ asoc->peer.transport_count = 0;
/* RFC 2960 5.1 Normal Establishment of an Association
*
@@ -288,6 +285,7 @@ struct sctp_association *sctp_association_new(const struct sctp_endpoint *ep,
asoc->base.malloced = 1;
SCTP_DBG_OBJCNT_INC(assoc);
+ SCTP_DEBUG_PRINTK("Created asoc %p\n", asoc);
return asoc;
@@ -356,6 +354,8 @@ void sctp_association_free(struct sctp_association *asoc)
sctp_transport_free(transport);
}
+ asoc->peer.transport_count = 0;
+
/* Free any cached ASCONF_ACK chunk. */
if (asoc->addip_last_asconf_ack)
sctp_chunk_free(asoc->addip_last_asconf_ack);
@@ -400,7 +400,7 @@ void sctp_assoc_set_primary(struct sctp_association *asoc,
/* If the primary path is changing, assume that the
* user wants to use this new path.
*/
- if (transport->active)
+ if (transport->state != SCTP_INACTIVE)
asoc->peer.active_path = transport;
/*
@@ -428,10 +428,58 @@ void sctp_assoc_set_primary(struct sctp_association *asoc,
transport->cacc.next_tsn_at_change = asoc->next_tsn;
}
+/* Remove a transport from an association. */
+void sctp_assoc_rm_peer(struct sctp_association *asoc,
+ struct sctp_transport *peer)
+{
+ struct list_head *pos;
+ struct sctp_transport *transport;
+
+ SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_rm_peer:association %p addr: ",
+ " port: %d\n",
+ asoc,
+ (&peer->ipaddr),
+ peer->ipaddr.v4.sin_port);
+
+ /* If we are to remove the current retran_path, update it
+ * to the next peer before removing this peer from the list.
+ */
+ if (asoc->peer.retran_path == peer)
+ sctp_assoc_update_retran_path(asoc);
+
+ /* Remove this peer from the list. */
+ list_del(&peer->transports);
+
+ /* Get the first transport of asoc. */
+ pos = asoc->peer.transport_addr_list.next;
+ transport = list_entry(pos, struct sctp_transport, transports);
+
+ /* Update any entries that match the peer to be deleted. */
+ if (asoc->peer.primary_path == peer)
+ sctp_assoc_set_primary(asoc, transport);
+ if (asoc->peer.active_path == peer)
+ asoc->peer.active_path = transport;
+ if (asoc->peer.last_data_from == peer)
+ asoc->peer.last_data_from = transport;
+
+ /* If we remove the transport an INIT was last sent to, set it to
+ * NULL. Combined with the update of the retran path above, this
+ * will cause the next INIT to be sent to the next available
+ * transport, maintaining the cycle.
+ */
+ if (asoc->init_last_sent_to == peer)
+ asoc->init_last_sent_to = NULL;
+
+ asoc->peer.transport_count--;
+
+ sctp_transport_free(peer);
+}
+
/* Add a transport address to an association. */
struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
const union sctp_addr *addr,
- int gfp)
+ const int gfp,
+ const int peer_state)
{
struct sctp_transport *peer;
struct sctp_sock *sp;
@@ -442,14 +490,25 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
/* AF_INET and AF_INET6 share common port field. */
port = addr->v4.sin_port;
+ SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_add_peer:association %p addr: ",
+ " port: %d state:%s\n",
+ asoc,
+ addr,
+ addr->v4.sin_port,
+ peer_state == SCTP_UNKNOWN?"UNKNOWN":"ACTIVE");
+
/* Set the port if it has not been set yet. */
if (0 == asoc->peer.port)
asoc->peer.port = port;
/* Check to see if this is a duplicate. */
peer = sctp_assoc_lookup_paddr(asoc, addr);
- if (peer)
+ if (peer) {
+ if (peer_state == SCTP_ACTIVE &&
+ peer->state == SCTP_UNKNOWN)
+ peer->state = SCTP_ACTIVE;
return peer;
+ }
peer = sctp_transport_new(addr, gfp);
if (!peer)
@@ -516,8 +575,12 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
/* Set the transport's RTO.initial value */
peer->rto = asoc->rto_initial;
+ /* Set the peer's active state. */
+ peer->state = peer_state;
+
/* Attach the remote transport to our asoc. */
list_add_tail(&peer->transports, &asoc->peer.transport_addr_list);
+ asoc->peer.transport_count++;
/* If we do not yet have a primary path, set one. */
if (!asoc->peer.primary_path) {
@@ -525,8 +588,9 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
asoc->peer.retran_path = peer;
}
- if (asoc->peer.active_path == asoc->peer.retran_path)
+ if (asoc->peer.active_path == asoc->peer.retran_path) {
asoc->peer.retran_path = peer;
+ }
return peer;
}
@@ -537,37 +601,16 @@ void sctp_assoc_del_peer(struct sctp_association *asoc,
{
struct list_head *pos;
struct list_head *temp;
- struct sctp_transport *peer = NULL;
struct sctp_transport *transport;
list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
transport = list_entry(pos, struct sctp_transport, transports);
if (sctp_cmp_addr_exact(addr, &transport->ipaddr)) {
- peer = transport;
- list_del(pos);
+ /* Do book keeping for removing the peer and free it. */
+ sctp_assoc_rm_peer(asoc, transport);
break;
}
}
-
- /* The address we want delete is not in the association. */
- if (!peer)
- return;
-
- /* Get the first transport of asoc. */
- pos = asoc->peer.transport_addr_list.next;
- transport = list_entry(pos, struct sctp_transport, transports);
-
- /* Update any entries that match the peer to be deleted. */
- if (asoc->peer.primary_path == peer)
- sctp_assoc_set_primary(asoc, transport);
- if (asoc->peer.active_path == peer)
- asoc->peer.active_path = transport;
- if (asoc->peer.retran_path == peer)
- asoc->peer.retran_path = transport;
- if (asoc->peer.last_data_from == peer)
- asoc->peer.last_data_from = transport;
-
- sctp_transport_free(peer);
}
/* Lookup a transport by address. */
@@ -608,12 +651,12 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
/* Record the transition on the transport. */
switch (command) {
case SCTP_TRANSPORT_UP:
- transport->active = SCTP_ACTIVE;
+ transport->state = SCTP_ACTIVE;
spc_state = SCTP_ADDR_AVAILABLE;
break;
case SCTP_TRANSPORT_DOWN:
- transport->active = SCTP_INACTIVE;
+ transport->state = SCTP_INACTIVE;
spc_state = SCTP_ADDR_UNREACHABLE;
break;
@@ -643,7 +686,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
list_for_each(pos, &asoc->peer.transport_addr_list) {
t = list_entry(pos, struct sctp_transport, transports);
- if (!t->active)
+ if (t->state == SCTP_INACTIVE)
continue;
if (!first || t->last_time_heard > first->last_time_heard) {
second = first;
@@ -663,7 +706,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
* [If the primary is active but not most recent, bump the most
* recently used transport.]
*/
- if (asoc->peer.primary_path->active &&
+ if (asoc->peer.primary_path->state != SCTP_INACTIVE &&
first != asoc->peer.primary_path) {
second = first;
first = asoc->peer.primary_path;
@@ -958,7 +1001,7 @@ void sctp_assoc_update(struct sctp_association *asoc,
transports);
if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr))
sctp_assoc_add_peer(asoc, &trans->ipaddr,
- GFP_ATOMIC);
+ GFP_ATOMIC, SCTP_ACTIVE);
}
asoc->ctsn_ack_point = asoc->next_tsn - 1;
@@ -998,7 +1041,7 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc)
/* Try to find an active transport. */
- if (t->active) {
+ if (t->state != SCTP_INACTIVE) {
break;
} else {
/* Keep track of the next transport in case
@@ -1019,6 +1062,40 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc)
}
asoc->peer.retran_path = t;
+
+ SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association"
+ " %p addr: ",
+ " port: %d\n",
+ asoc,
+ (&t->ipaddr),
+ t->ipaddr.v4.sin_port);
+}
+
+/* Choose the transport for sending a INIT packet. */
+struct sctp_transport *sctp_assoc_choose_init_transport(
+ struct sctp_association *asoc)
+{
+ struct sctp_transport *t;
+
+ /* Use the retran path. If the last INIT was sent over the
+ * retran path, update the retran path and use it.
+ */
+ if (!asoc->init_last_sent_to) {
+ t = asoc->peer.active_path;
+ } else {
+ if (asoc->init_last_sent_to == asoc->peer.retran_path)
+ sctp_assoc_update_retran_path(asoc);
+ t = asoc->peer.retran_path;
+ }
+
+ SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association"
+ " %p addr: ",
+ " port: %d\n",
+ asoc,
+ (&t->ipaddr),
+ t->ipaddr.v4.sin_port);
+
+ return t;
}
/* Choose the transport for sending a SHUTDOWN packet. */
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 334f61773e6..2ec0320fac3 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -134,7 +134,6 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
ep->last_key = ep->current_key = 0;
ep->key_changed_at = jiffies;
- ep->debug_name = "unnamedEndpoint";
return ep;
}
diff --git a/net/sctp/input.c b/net/sctp/input.c
index b719a77d66b..339f7acfdb6 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -178,6 +178,37 @@ int sctp_rcv(struct sk_buff *skb)
asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport);
+ if (!asoc)
+ ep = __sctp_rcv_lookup_endpoint(&dest);
+
+ /* Retrieve the common input handling substructure. */
+ rcvr = asoc ? &asoc->base : &ep->base;
+ sk = rcvr->sk;
+
+ /*
+ * If a frame arrives on an interface and the receiving socket is
+ * bound to another interface, via SO_BINDTODEVICE, treat it as OOTB
+ */
+ if (sk->sk_bound_dev_if && (sk->sk_bound_dev_if != af->skb_iif(skb)))
+ {
+ sock_put(sk);
+ if (asoc) {
+ sctp_association_put(asoc);
+ asoc = NULL;
+ } else {
+ sctp_endpoint_put(ep);
+ ep = NULL;
+ }
+ sk = sctp_get_ctl_sock();
+ ep = sctp_sk(sk)->ep;
+ sctp_endpoint_hold(ep);
+ sock_hold(sk);
+ rcvr = &ep->base;
+ }
+
+ if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf)
+ goto discard_release;
+
/*
* RFC 2960, 8.4 - Handle "Out of the blue" Packets.
* An SCTP packet is called an "out of the blue" (OOTB)
@@ -187,22 +218,12 @@ int sctp_rcv(struct sk_buff *skb)
* packet belongs.
*/
if (!asoc) {
- ep = __sctp_rcv_lookup_endpoint(&dest);
if (sctp_rcv_ootb(skb)) {
SCTP_INC_STATS_BH(SCTP_MIB_OUTOFBLUES);
goto discard_release;
}
}
- /* Retrieve the common input handling substructure. */
- rcvr = asoc ? &asoc->base : &ep->base;
- sk = rcvr->sk;
-
- if ((sk) && (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf)) {
- goto discard_release;
- }
-
-
/* SCTP seems to always need a timestamp right now (FIXME) */
if (skb->stamp.tv_sec == 0) {
do_gettimeofday(&skb->stamp);
@@ -265,13 +286,11 @@ discard_it:
discard_release:
/* Release any structures we may be holding. */
- if (asoc) {
- sock_put(asoc->base.sk);
+ sock_put(sk);
+ if (asoc)
sctp_association_put(asoc);
- } else {
- sock_put(ep->base.sk);
+ else
sctp_endpoint_put(ep);
- }
goto discard_it;
}
@@ -334,7 +353,7 @@ void sctp_icmp_proto_unreachable(struct sock *sk,
sctp_do_sm(SCTP_EVENT_T_OTHER,
SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH),
- asoc->state, asoc->ep, asoc, NULL,
+ asoc->state, asoc->ep, asoc, t,
GFP_ATOMIC);
}
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index c9d9ea06473..c7e42d125b9 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -812,26 +812,23 @@ static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr)
if (addr->sa.sa_family != AF_INET6)
af = sctp_get_af_specific(addr->sa.sa_family);
else {
- struct sock *sk;
int type = ipv6_addr_type(&addr->v6.sin6_addr);
- sk = sctp_opt2sk(opt);
+ struct net_device *dev;
+
if (type & IPV6_ADDR_LINKLOCAL) {
- /* Note: Behavior similar to af_inet6.c:
- * 1) Overrides previous bound_dev_if
- * 2) Destructive even if bind isn't successful.
- */
-
- if (addr->v6.sin6_scope_id)
- sk->sk_bound_dev_if = addr->v6.sin6_scope_id;
- if (!sk->sk_bound_dev_if)
+ if (!addr->v6.sin6_scope_id)
+ return 0;
+ dev = dev_get_by_index(addr->v6.sin6_scope_id);
+ if (!dev)
return 0;
+ dev_put(dev);
}
af = opt->pf->af;
}
return af->available(addr, opt);
}
-/* Verify that the provided sockaddr looks bindable. Common verification,
+/* Verify that the provided sockaddr looks sendable. Common verification,
* has already been taken care of.
*/
static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr)
@@ -842,19 +839,16 @@ static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr)
if (addr->sa.sa_family != AF_INET6)
af = sctp_get_af_specific(addr->sa.sa_family);
else {
- struct sock *sk;
int type = ipv6_addr_type(&addr->v6.sin6_addr);
- sk = sctp_opt2sk(opt);
+ struct net_device *dev;
+
if (type & IPV6_ADDR_LINKLOCAL) {
- /* Note: Behavior similar to af_inet6.c:
- * 1) Overrides previous bound_dev_if
- * 2) Destructive even if bind isn't successful.
- */
-
- if (addr->v6.sin6_scope_id)
- sk->sk_bound_dev_if = addr->v6.sin6_scope_id;
- if (!sk->sk_bound_dev_if)
+ if (!addr->v6.sin6_scope_id)
+ return 0;
+ dev = dev_get_by_index(addr->v6.sin6_scope_id);
+ if (!dev)
return 0;
+ dev_put(dev);
}
af = opt->pf->af;
}
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 1b2d4adc4dd..4eb81a1407b 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -682,9 +682,9 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
if (!new_transport) {
new_transport = asoc->peer.active_path;
- } else if (!new_transport->active) {
- /* If the chunk is Heartbeat or Heartbeat Ack,
- * send it to chunk->transport, even if it's
+ } else if (new_transport->state == SCTP_INACTIVE) {
+ /* If the chunk is Heartbeat or Heartbeat Ack,
+ * send it to chunk->transport, even if it's
* inactive.
*
* 3.3.6 Heartbeat Acknowledgement:
@@ -840,7 +840,8 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
* Otherwise, we want to use the active path.
*/
new_transport = chunk->transport;
- if (!new_transport || !new_transport->active)
+ if (!new_transport ||
+ new_transport->state == SCTP_INACTIVE)
new_transport = asoc->peer.active_path;
/* Change packets if necessary. */
@@ -1454,7 +1455,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,
/* Mark the destination transport address as
* active if it is not so marked.
*/
- if (!transport->active) {
+ if (transport->state == SCTP_INACTIVE) {
sctp_assoc_control_transport(
transport->asoc,
transport,
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index e42fd8c2916..98d49ec9b74 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -132,14 +132,25 @@ void sctp_snmp_proc_exit(void)
static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_common *epb)
{
struct list_head *pos;
+ struct sctp_association *asoc;
struct sctp_sockaddr_entry *laddr;
- union sctp_addr *addr;
+ struct sctp_transport *peer;
+ union sctp_addr *addr, *primary = NULL;
struct sctp_af *af;
+ if (epb->type == SCTP_EP_TYPE_ASSOCIATION) {
+ asoc = sctp_assoc(epb);
+ peer = asoc->peer.primary_path;
+ primary = &peer->saddr;
+ }
+
list_for_each(pos, &epb->bind_addr.address_list) {
laddr = list_entry(pos, struct sctp_sockaddr_entry, list);
addr = (union sctp_addr *)&laddr->a;
af = sctp_get_af_specific(addr->sa.sa_family);
+ if (primary && af->cmp_addr(addr, primary)) {
+ seq_printf(seq, "*");
+ }
af->seq_dump_addr(seq, addr);
}
}
@@ -149,17 +160,54 @@ static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_associa
{
struct list_head *pos;
struct sctp_transport *transport;
- union sctp_addr *addr;
+ union sctp_addr *addr, *primary;
struct sctp_af *af;
+ primary = &(assoc->peer.primary_addr);
list_for_each(pos, &assoc->peer.transport_addr_list) {
transport = list_entry(pos, struct sctp_transport, transports);
addr = (union sctp_addr *)&transport->ipaddr;
af = sctp_get_af_specific(addr->sa.sa_family);
+ if (af->cmp_addr(addr, primary)) {
+ seq_printf(seq, "*");
+ }
af->seq_dump_addr(seq, addr);
}
}
+static void * sctp_eps_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ if (*pos > sctp_ep_hashsize)
+ return NULL;
+
+ if (*pos < 0)
+ *pos = 0;
+
+ if (*pos == 0)
+ seq_printf(seq, " ENDPT SOCK STY SST HBKT LPORT UID INODE LADDRS\n");
+
+ ++*pos;
+
+ return (void *)pos;
+}
+
+static void sctp_eps_seq_stop(struct seq_file *seq, void *v)
+{
+ return;
+}
+
+
+static void * sctp_eps_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ if (*pos > sctp_ep_hashsize)
+ return NULL;
+
+ ++*pos;
+
+ return pos;
+}
+
+
/* Display sctp endpoints (/proc/net/sctp/eps). */
static int sctp_eps_seq_show(struct seq_file *seq, void *v)
{
@@ -167,38 +215,50 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v)
struct sctp_ep_common *epb;
struct sctp_endpoint *ep;
struct sock *sk;
- int hash;
-
- seq_printf(seq, " ENDPT SOCK STY SST HBKT LPORT LADDRS\n");
- for (hash = 0; hash < sctp_ep_hashsize; hash++) {
- head = &sctp_ep_hashtable[hash];
- read_lock(&head->lock);
- for (epb = head->chain; epb; epb = epb->next) {
- ep = sctp_ep(epb);
- sk = epb->sk;
- seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d ", ep, sk,
- sctp_sk(sk)->type, sk->sk_state, hash,
- epb->bind_addr.port);
- sctp_seq_dump_local_addrs(seq, epb);
- seq_printf(seq, "\n");
- }
- read_unlock(&head->lock);
+ int hash = *(int *)v;
+
+ if (hash > sctp_ep_hashsize)
+ return -ENOMEM;
+
+ head = &sctp_ep_hashtable[hash-1];
+ sctp_local_bh_disable();
+ read_lock(&head->lock);
+ for (epb = head->chain; epb; epb = epb->next) {
+ ep = sctp_ep(epb);
+ sk = epb->sk;
+ seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk,
+ sctp_sk(sk)->type, sk->sk_state, hash-1,
+ epb->bind_addr.port,
+ sock_i_uid(sk), sock_i_ino(sk));
+
+ sctp_seq_dump_local_addrs(seq, epb);
+ seq_printf(seq, "\n");
}
+ read_unlock(&head->lock);
+ sctp_local_bh_enable();
return 0;
}
+static struct seq_operations sctp_eps_ops = {
+ .start = sctp_eps_seq_start,
+ .next = sctp_eps_seq_next,
+ .stop = sctp_eps_seq_stop,
+ .show = sctp_eps_seq_show,
+};
+
+
/* Initialize the seq file operations for 'eps' object. */
static int sctp_eps_seq_open(struct inode *inode, struct file *file)
{
- return single_open(file, sctp_eps_seq_show, NULL);
+ return seq_open(file, &sctp_eps_ops);
}
static struct file_operations sctp_eps_seq_fops = {
.open = sctp_eps_seq_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = single_release,
+ .release = seq_release,
};
/* Set up the proc fs entry for 'eps' object. */
@@ -221,6 +281,40 @@ void sctp_eps_proc_exit(void)
remove_proc_entry("eps", proc_net_sctp);
}
+
+static void * sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ if (*pos > sctp_assoc_hashsize)
+ return NULL;
+
+ if (*pos < 0)
+ *pos = 0;
+
+ if (*pos == 0)
+ seq_printf(seq, " ASSOC SOCK STY SST ST HBKT ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT "
+ "RPORT LADDRS <-> RADDRS\n");
+
+ ++*pos;
+
+ return (void *)pos;
+}
+
+static void sctp_assocs_seq_stop(struct seq_file *seq, void *v)
+{
+ return;
+}
+
+
+static void * sctp_assocs_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ if (*pos > sctp_assoc_hashsize)
+ return NULL;
+
+ ++*pos;
+
+ return pos;
+}
+
/* Display sctp associations (/proc/net/sctp/assocs). */
static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
{
@@ -228,43 +322,57 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
struct sctp_ep_common *epb;
struct sctp_association *assoc;
struct sock *sk;
- int hash;
-
- seq_printf(seq, " ASSOC SOCK STY SST ST HBKT LPORT RPORT "
- "LADDRS <-> RADDRS\n");
- for (hash = 0; hash < sctp_assoc_hashsize; hash++) {
- head = &sctp_assoc_hashtable[hash];
- read_lock(&head->lock);
- for (epb = head->chain; epb; epb = epb->next) {
- assoc = sctp_assoc(epb);
- sk = epb->sk;
- seq_printf(seq,
- "%8p %8p %-3d %-3d %-2d %-4d %-5d %-5d ",
- assoc, sk, sctp_sk(sk)->type, sk->sk_state,
- assoc->state, hash, epb->bind_addr.port,
- assoc->peer.port);
- sctp_seq_dump_local_addrs(seq, epb);
- seq_printf(seq, "<-> ");
- sctp_seq_dump_remote_addrs(seq, assoc);
- seq_printf(seq, "\n");
- }
- read_unlock(&head->lock);
+ int hash = *(int *)v;
+
+ if (hash > sctp_assoc_hashsize)
+ return -ENOMEM;
+
+ head = &sctp_assoc_hashtable[hash-1];
+ sctp_local_bh_disable();
+ read_lock(&head->lock);
+ for (epb = head->chain; epb; epb = epb->next) {
+ assoc = sctp_assoc(epb);
+ sk = epb->sk;
+ seq_printf(seq,
+ "%8p %8p %-3d %-3d %-2d %-4d %4d %8d %8d %7d %5lu %-5d %5d ",
+ assoc, sk, sctp_sk(sk)->type, sk->sk_state,
+ assoc->state, hash-1, assoc->assoc_id,
+ (sk->sk_rcvbuf - assoc->rwnd),
+ assoc->sndbuf_used,
+ sock_i_uid(sk), sock_i_ino(sk),
+ epb->bind_addr.port,
+ assoc->peer.port);
+
+ seq_printf(seq, " ");
+ sctp_seq_dump_local_addrs(seq, epb);
+ seq_printf(seq, "<-> ");
+ sctp_seq_dump_remote_addrs(seq, assoc);
+ seq_printf(seq, "\n");
}
+ read_unlock(&head->lock);
+ sctp_local_bh_enable();
return 0;
}
+static struct seq_operations sctp_assoc_ops = {
+ .start = sctp_assocs_seq_start,
+ .next = sctp_assocs_seq_next,
+ .stop = sctp_assocs_seq_stop,
+ .show = sctp_assocs_seq_show,
+};
+
/* Initialize the seq file operations for 'assocs' object. */
static int sctp_assocs_seq_open(struct inode *inode, struct file *file)
{
- return single_open(file, sctp_assocs_seq_show, NULL);
+ return seq_open(file, &sctp_assoc_ops);
}
static struct file_operations sctp_assocs_seq_fops = {
.open = sctp_assocs_seq_open,
.read = seq_read,
.llseek = seq_lseek,
- .release = single_release,
+ .release = seq_release,
};
/* Set up the proc fs entry for 'assocs' object. */
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 2e1f9c3556f..5135e1a25d2 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -378,10 +378,13 @@ static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp)
{
int ret = inet_addr_type(addr->v4.sin_addr.s_addr);
- /* FIXME: ip_nonlocal_bind sysctl support. */
- if (addr->v4.sin_addr.s_addr != INADDR_ANY && ret != RTN_LOCAL)
+ if (addr->v4.sin_addr.s_addr != INADDR_ANY &&
+ ret != RTN_LOCAL &&
+ !sp->inet.freebind &&
+ !sysctl_ip_nonlocal_bind)
return 0;
+
return 1;
}
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 33ac8bf47b0..5baed9bb7de 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1830,7 +1830,7 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
* be a a better choice than any of the embedded addresses.
*/
if (peer_addr)
- if(!sctp_assoc_add_peer(asoc, peer_addr, gfp))
+ if(!sctp_assoc_add_peer(asoc, peer_addr, gfp, SCTP_ACTIVE))
goto nomem;
/* Process the initialization parameters. */
@@ -1841,6 +1841,14 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
goto clean_up;
}
+ /* Walk list of transports, removing transports in the UNKNOWN state. */
+ list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
+ transport = list_entry(pos, struct sctp_transport, transports);
+ if (transport->state == SCTP_UNKNOWN) {
+ sctp_assoc_rm_peer(asoc, transport);
+ }
+ }
+
/* The fixed INIT headers are always in network byte
* order.
*/
@@ -1906,7 +1914,8 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid,
* stream sequence number shall be set to 0.
*/
- /* Allocate storage for the negotiated streams if it is not a temporary * association.
+ /* Allocate storage for the negotiated streams if it is not a temporary
+ * association.
*/
if (!asoc->temp) {
int assoc_id;
@@ -1952,6 +1961,9 @@ clean_up:
list_del_init(pos);
sctp_transport_free(transport);
}
+
+ asoc->peer.transport_count = 0;
+
nomem:
return 0;
}
@@ -1995,7 +2007,7 @@ static int sctp_process_param(struct sctp_association *asoc,
af->from_addr_param(&addr, param.addr, asoc->peer.port, 0);
scope = sctp_scope(peer_addr);
if (sctp_in_scope(&addr, scope))
- if (!sctp_assoc_add_peer(asoc, &addr, gfp))
+ if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_ACTIVE))
return 0;
break;
@@ -2396,7 +2408,7 @@ static __u16 sctp_process_asconf_param(struct sctp_association *asoc,
* Due to Resource Shortage'.
*/
- peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC);
+ peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC, SCTP_ACTIVE);
if (!peer)
return SCTP_ERROR_RSRC_LOW;
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index f65fa441952..778639db125 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -414,11 +414,13 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc,
*/
asoc->overall_error_count++;
- if (transport->active &&
+ if (transport->state != SCTP_INACTIVE &&
(transport->error_count++ >= transport->max_retrans)) {
- SCTP_DEBUG_PRINTK("transport_strike: transport "
- "IP:%d.%d.%d.%d failed.\n",
- NIPQUAD(transport->ipaddr.v4.sin_addr));
+ SCTP_DEBUG_PRINTK_IPADDR("transport_strike:association %p",
+ " transport IP: port:%d failed.\n",
+ asoc,
+ (&transport->ipaddr),
+ transport->ipaddr.v4.sin_port);
sctp_assoc_control_transport(asoc, transport,
SCTP_TRANSPORT_DOWN,
SCTP_FAILED_THRESHOLD);
@@ -593,7 +595,7 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds,
/* Mark the destination transport address as active if it is not so
* marked.
*/
- if (!t->active)
+ if (t->state == SCTP_INACTIVE)
sctp_assoc_control_transport(asoc, t, SCTP_TRANSPORT_UP,
SCTP_HEARTBEAT_SUCCESS);
@@ -665,8 +667,11 @@ static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds,
asoc->state = state;
+ SCTP_DEBUG_PRINTK("sctp_cmd_new_state: asoc %p[%s]\n",
+ asoc, sctp_state_tbl[state]);
+
if (sctp_style(sk, TCP)) {
- /* Change the sk->sk_state of a TCP-style socket that has
+ /* Change the sk->sk_state of a TCP-style socket that has
* sucessfully completed a connect() call.
*/
if (sctp_state(asoc, ESTABLISHED) && sctp_sstate(sk, CLOSED))
@@ -678,6 +683,16 @@ static void sctp_cmd_new_state(sctp_cmd_seq_t *cmds,
sk->sk_shutdown |= RCV_SHUTDOWN;
}
+ if (sctp_state(asoc, COOKIE_WAIT)) {
+ /* Reset init timeouts since they may have been
+ * increased due to timer expirations.
+ */
+ asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
+ asoc->ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT];
+ asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] =
+ asoc->ep->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE];
+ }
+
if (sctp_state(asoc, ESTABLISHED) ||
sctp_state(asoc, CLOSED) ||
sctp_state(asoc, SHUTDOWN_RECEIVED)) {
@@ -1120,10 +1135,10 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
* to be executed only during failed attempts of
* association establishment.
*/
- if ((asoc->peer.retran_path !=
- asoc->peer.primary_path) &&
- (asoc->counters[SCTP_COUNTER_INIT_ERROR] > 0)) {
- sctp_add_cmd_sf(commands,
+ if ((asoc->peer.retran_path !=
+ asoc->peer.primary_path) &&
+ (asoc->init_err_counter > 0)) {
+ sctp_add_cmd_sf(commands,
SCTP_CMD_FORCE_PRIM_RETRAN,
SCTP_NULL());
}
@@ -1237,18 +1252,67 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
sctp_association_put(asoc);
break;
+ case SCTP_CMD_INIT_CHOOSE_TRANSPORT:
+ chunk = cmd->obj.ptr;
+ t = sctp_assoc_choose_init_transport(asoc);
+ asoc->init_last_sent_to = t;
+ chunk->transport = t;
+ t->init_sent_count++;
+ break;
+
case SCTP_CMD_INIT_RESTART:
/* Do the needed accounting and updates
* associated with restarting an initialization
- * timer.
+ * timer. Only multiply the timeout by two if
+ * all transports have been tried at the current
+ * timeout.
+ */
+ t = asoc->init_last_sent_to;
+ asoc->init_err_counter++;
+
+ if (t->init_sent_count > (asoc->init_cycle + 1)) {
+ asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] *= 2;
+ if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] >
+ asoc->max_init_timeo) {
+ asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
+ asoc->max_init_timeo;
+ }
+ asoc->init_cycle++;
+ SCTP_DEBUG_PRINTK(
+ "T1 INIT Timeout adjustment"
+ " init_err_counter: %d"
+ " cycle: %d"
+ " timeout: %d\n",
+ asoc->init_err_counter,
+ asoc->init_cycle,
+ asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]);
+ }
+
+ sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
+ SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
+ break;
+
+ case SCTP_CMD_COOKIEECHO_RESTART:
+ /* Do the needed accounting and updates
+ * associated with restarting an initialization
+ * timer. Only multiply the timeout by two if
+ * all transports have been tried at the current
+ * timeout.
*/
- asoc->counters[SCTP_COUNTER_INIT_ERROR]++;
- asoc->timeouts[cmd->obj.to] *= 2;
- if (asoc->timeouts[cmd->obj.to] >
+ asoc->init_err_counter++;
+
+ asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] *= 2;
+ if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] >
asoc->max_init_timeo) {
- asoc->timeouts[cmd->obj.to] =
+ asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] =
asoc->max_init_timeo;
}
+ SCTP_DEBUG_PRINTK(
+ "T1 COOKIE Timeout adjustment"
+ " init_err_counter: %d"
+ " timeout: %d\n",
+ asoc->init_err_counter,
+ asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]);
/* If we've sent any data bundled with
* COOKIE-ECHO we need to resend.
@@ -1261,7 +1325,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
sctp_add_cmd_sf(commands,
SCTP_CMD_TIMER_RESTART,
- SCTP_TO(cmd->obj.to));
+ SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));
break;
case SCTP_CMD_INIT_FAILED:
@@ -1273,12 +1337,13 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
subtype, chunk, cmd->obj.u32);
break;
- case SCTP_CMD_COUNTER_INC:
- asoc->counters[cmd->obj.counter]++;
+ case SCTP_CMD_INIT_COUNTER_INC:
+ asoc->init_err_counter++;
break;
- case SCTP_CMD_COUNTER_RESET:
- asoc->counters[cmd->obj.counter] = 0;
+ case SCTP_CMD_INIT_COUNTER_RESET:
+ asoc->init_err_counter = 0;
+ asoc->init_cycle = 0;
break;
case SCTP_CMD_REPORT_DUP:
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 8e01b8f09ac..86073df418f 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -92,6 +92,17 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
sctp_cmd_seq_t *commands);
static struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk);
+static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
+ __u16 error,
+ const struct sctp_association *asoc,
+ struct sctp_transport *transport);
+
+static sctp_disposition_t sctp_sf_violation_chunklen(
+ const struct sctp_endpoint *ep,
+ const struct sctp_association *asoc,
+ const sctp_subtype_t type,
+ void *arg,
+ sctp_cmd_seq_t *commands);
/* Small helper function that checks if the chunk length
* is of the appropriate length. The 'required_length' argument
@@ -533,6 +544,9 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_PEER_INIT,
SCTP_PEER_INIT(initchunk));
+ /* Reset init error count upon receipt of INIT-ACK. */
+ sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL());
+
/* 5.1 C) "A" shall stop the T1-init timer and leave
* COOKIE-WAIT state. "A" shall then ... start the T1-cookie
* timer, and enter the COOKIE-ECHOED state.
@@ -775,8 +789,7 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep,
* from the COOKIE-ECHOED state to the COOKIE-WAIT
* state is performed.
*/
- sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_RESET,
- SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR));
+ sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL());
/* RFC 2960 5.1 Normal Establishment of an Association
*
@@ -1019,10 +1032,22 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
link = sctp_assoc_lookup_paddr(asoc, &from_addr);
/* This should never happen, but lets log it if so. */
- if (!link) {
- printk(KERN_WARNING
- "%s: Could not find address %d.%d.%d.%d\n",
- __FUNCTION__, NIPQUAD(from_addr.v4.sin_addr));
+ if (unlikely(!link)) {
+ if (from_addr.sa.sa_family == AF_INET6) {
+ printk(KERN_WARNING
+ "%s association %p could not find address "
+ "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+ __FUNCTION__,
+ asoc,
+ NIP6(from_addr.v6.sin6_addr));
+ } else {
+ printk(KERN_WARNING
+ "%s association %p could not find address "
+ "%u.%u.%u.%u\n",
+ __FUNCTION__,
+ asoc,
+ NIPQUAD(from_addr.v4.sin_addr.s_addr));
+ }
return SCTP_DISPOSITION_DISCARD;
}
@@ -2095,9 +2120,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,
sctp_errhdr_t *err;
struct sctp_chunk *reply;
struct sctp_bind_addr *bp;
- int attempts;
-
- attempts = asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1;
+ int attempts = asoc->init_err_counter + 1;
if (attempts >= asoc->max_init_attempts) {
sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
@@ -2157,8 +2180,7 @@ static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,
/* Cast away the const modifier, as we want to just
* rerun it through as a sideffect.
*/
- sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_INC,
- SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR));
+ sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_INC, SCTP_NULL());
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));
@@ -2281,8 +2303,7 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep,
if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr))
error = ((sctp_errhdr_t *)chunk->skb->data)->cause;
- sctp_stop_t1_and_abort(commands, error);
- return SCTP_DISPOSITION_ABORT;
+ return sctp_stop_t1_and_abort(commands, error, asoc, chunk->transport);
}
/*
@@ -2294,8 +2315,8 @@ sctp_disposition_t sctp_sf_cookie_wait_icmp_abort(const struct sctp_endpoint *ep
void *arg,
sctp_cmd_seq_t *commands)
{
- sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR);
- return SCTP_DISPOSITION_ABORT;
+ return sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR, asoc,
+ (struct sctp_transport *)arg);
}
/*
@@ -2318,8 +2339,12 @@ sctp_disposition_t sctp_sf_cookie_echoed_abort(const struct sctp_endpoint *ep,
*
* This is common code called by several sctp_sf_*_abort() functions above.
*/
-void sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, __u16 error)
+static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
+ __u16 error,
+ const struct sctp_association *asoc,
+ struct sctp_transport *transport)
{
+ SCTP_DEBUG_PRINTK("ABORT received (INIT).\n");
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
SCTP_STATE(SCTP_STATE_CLOSED));
SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
@@ -2328,6 +2353,7 @@ void sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, __u16 error)
/* CMD_INIT_FAILED will DELETE_TCB. */
sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
SCTP_U32(error));
+ return SCTP_DISPOSITION_ABORT;
}
/*
@@ -3672,7 +3698,8 @@ sctp_disposition_t sctp_sf_violation(const struct sctp_endpoint *ep,
*
* Generate an ABORT chunk and terminate the association.
*/
-sctp_disposition_t sctp_sf_violation_chunklen(const struct sctp_endpoint *ep,
+static sctp_disposition_t sctp_sf_violation_chunklen(
+ const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
@@ -3805,6 +3832,10 @@ sctp_disposition_t sctp_sf_do_prm_asoc(const struct sctp_endpoint *ep,
sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC,
SCTP_ASOC((struct sctp_association *) asoc));
+ /* Choose transport for INIT. */
+ sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT,
+ SCTP_CHUNK(repl));
+
/* After sending the INIT, "A" starts the T1-init timer and
* enters the COOKIE-WAIT state.
*/
@@ -4589,7 +4620,7 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep,
}
/*
- * sctp_sf_t1_timer_expire
+ * sctp_sf_t1_init_timer_expire
*
* Section: 4 Note: 2
* Verification Tag:
@@ -4603,7 +4634,59 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep,
* endpoint MUST abort the initialization process and report the
* error to SCTP user.
*
- * 3) If the T1-cookie timer expires, the endpoint MUST retransmit
+ * Outputs
+ * (timers, events)
+ *
+ */
+sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep,
+ const struct sctp_association *asoc,
+ const sctp_subtype_t type,
+ void *arg,
+ sctp_cmd_seq_t *commands)
+{
+ struct sctp_chunk *repl = NULL;
+ struct sctp_bind_addr *bp;
+ int attempts = asoc->init_err_counter + 1;
+
+ SCTP_DEBUG_PRINTK("Timer T1 expired (INIT).\n");
+
+ if (attempts < asoc->max_init_attempts) {
+ bp = (struct sctp_bind_addr *) &asoc->base.bind_addr;
+ repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0);
+ if (!repl)
+ return SCTP_DISPOSITION_NOMEM;
+
+ /* Choose transport for INIT. */
+ sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT,
+ SCTP_CHUNK(repl));
+
+ /* Issue a sideeffect to do the needed accounting. */
+ sctp_add_cmd_sf(commands, SCTP_CMD_INIT_RESTART,
+ SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
+
+ sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
+ } else {
+ SCTP_DEBUG_PRINTK("Giving up on INIT, attempts: %d"
+ " max_init_attempts: %d\n",
+ attempts, asoc->max_init_attempts);
+ sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
+ SCTP_U32(SCTP_ERROR_NO_ERROR));
+ return SCTP_DISPOSITION_DELETE_TCB;
+ }
+
+ return SCTP_DISPOSITION_CONSUME;
+}
+
+/*
+ * sctp_sf_t1_cookie_timer_expire
+ *
+ * Section: 4 Note: 2
+ * Verification Tag:
+ * Inputs
+ * (endpoint, asoc)
+ *
+ * RFC 2960 Section 4 Notes
+ * 3) If the T1-cookie timer expires, the endpoint MUST retransmit
* COOKIE ECHO and re-start the T1-cookie timer without changing
* state. This MUST be repeated up to 'Max.Init.Retransmits' times.
* After that, the endpoint MUST abort the initialization process and
@@ -4613,46 +4696,26 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep,
* (timers, events)
*
*/
-sctp_disposition_t sctp_sf_t1_timer_expire(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands)
{
- struct sctp_chunk *repl;
- struct sctp_bind_addr *bp;
- sctp_event_timeout_t timer = (sctp_event_timeout_t) arg;
- int timeout;
- int attempts;
+ struct sctp_chunk *repl = NULL;
+ int attempts = asoc->init_err_counter + 1;
- timeout = asoc->timeouts[timer];
- attempts = asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1;
- repl = NULL;
-
- SCTP_DEBUG_PRINTK("Timer T1 expired.\n");
+ SCTP_DEBUG_PRINTK("Timer T1 expired (COOKIE-ECHO).\n");
if (attempts < asoc->max_init_attempts) {
- switch (timer) {
- case SCTP_EVENT_TIMEOUT_T1_INIT:
- bp = (struct sctp_bind_addr *) &asoc->base.bind_addr;
- repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0);
- break;
-
- case SCTP_EVENT_TIMEOUT_T1_COOKIE:
- repl = sctp_make_cookie_echo(asoc, NULL);
- break;
-
- default:
- BUG();
- break;
- };
-
+ repl = sctp_make_cookie_echo(asoc, NULL);
if (!repl)
- goto nomem;
+ return SCTP_DISPOSITION_NOMEM;
/* Issue a sideeffect to do the needed accounting. */
- sctp_add_cmd_sf(commands, SCTP_CMD_INIT_RESTART,
- SCTP_TO(timer));
+ sctp_add_cmd_sf(commands, SCTP_CMD_COOKIEECHO_RESTART,
+ SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));
+
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
} else {
sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
@@ -4661,9 +4724,6 @@ sctp_disposition_t sctp_sf_t1_timer_expire(const struct sctp_endpoint *ep,
}
return SCTP_DISPOSITION_CONSUME;
-
-nomem:
- return SCTP_DISPOSITION_NOMEM;
}
/* RFC2960 9.2 If the timer expires, the endpoint must re-send the SHUTDOWN
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c
index 8967846f69e..75ef1040876 100644
--- a/net/sctp/sm_statetable.c
+++ b/net/sctp/sm_statetable.c
@@ -783,7 +783,8 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_
/* SCTP_STATE_COOKIE_WAIT */ \
{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
- {.fn = sctp_sf_t1_timer_expire, .name = "sctp_sf_t1_timer_expire"}, \
+ {.fn = sctp_sf_t1_cookie_timer_expire, \
+ .name = "sctp_sf_t1_cookie_timer_expire"}, \
/* SCTP_STATE_ESTABLISHED */ \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_SHUTDOWN_PENDING */ \
@@ -802,7 +803,8 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_
/* SCTP_STATE_CLOSED */ \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_COOKIE_WAIT */ \
- {.fn = sctp_sf_t1_timer_expire, .name = "sctp_sf_t1_timer_expire"}, \
+ {.fn = sctp_sf_t1_init_timer_expire, \
+ .name = "sctp_sf_t1_init_timer_expire"}, \
/* SCTP_STATE_COOKIE_ECHOED */ \
{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
/* SCTP_STATE_ESTABLISHED */ \
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 0b338eca6dc..aad55dc3792 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -262,18 +262,18 @@ static struct sctp_transport *sctp_addr_id2transport(struct sock *sk,
* sockaddr_in6 [RFC 2553]),
* addr_len - the size of the address structure.
*/
-SCTP_STATIC int sctp_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+SCTP_STATIC int sctp_bind(struct sock *sk, struct sockaddr *addr, int addr_len)
{
int retval = 0;
sctp_lock_sock(sk);
- SCTP_DEBUG_PRINTK("sctp_bind(sk: %p, uaddr: %p, addr_len: %d)\n",
- sk, uaddr, addr_len);
+ SCTP_DEBUG_PRINTK("sctp_bind(sk: %p, addr: %p, addr_len: %d)\n",
+ sk, addr, addr_len);
/* Disallow binding twice. */
if (!sctp_sk(sk)->ep->base.bind_addr.port)
- retval = sctp_do_bind(sk, (union sctp_addr *)uaddr,
+ retval = sctp_do_bind(sk, (union sctp_addr *)addr,
addr_len);
else
retval = -EINVAL;
@@ -318,23 +318,27 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
unsigned short snum;
int ret = 0;
- SCTP_DEBUG_PRINTK("sctp_do_bind(sk: %p, newaddr: %p, len: %d)\n",
- sk, addr, len);
-
/* Common sockaddr verification. */
af = sctp_sockaddr_af(sp, addr, len);
- if (!af)
+ if (!af) {
+ SCTP_DEBUG_PRINTK("sctp_do_bind(sk: %p, newaddr: %p, len: %d) EINVAL\n",
+ sk, addr, len);
return -EINVAL;
+ }
+
+ snum = ntohs(addr->v4.sin_port);
+
+ SCTP_DEBUG_PRINTK_IPADDR("sctp_do_bind(sk: %p, new addr: ",
+ ", port: %d, new port: %d, len: %d)\n",
+ sk,
+ addr,
+ bp->port, snum,
+ len);
/* PF specific bind() address verification. */
if (!sp->pf->bind_verify(sp, addr))
return -EADDRNOTAVAIL;
- snum= ntohs(addr->v4.sin_port);
-
- SCTP_DEBUG_PRINTK("sctp_do_bind: port: %d, new port: %d\n",
- bp->port, snum);
-
/* We must either be unbound, or bind to the same port. */
if (bp->port && (snum != bp->port)) {
SCTP_DEBUG_PRINTK("sctp_do_bind:"
@@ -816,7 +820,8 @@ out:
*
* Basically do nothing but copying the addresses from user to kernel
* land and invoking either sctp_bindx_add() or sctp_bindx_rem() on the sk.
- * This is used for tunneling the sctp_bindx() request through sctp_setsockopt() * from userspace.
+ * This is used for tunneling the sctp_bindx() request through sctp_setsockopt()
+ * from userspace.
*
* We don't use copy_from_user() for optimization: we first do the
* sanity checks (buffer size -fast- and access check-healthy
@@ -913,6 +918,243 @@ out:
return err;
}
+/* __sctp_connect(struct sock* sk, struct sockaddr *kaddrs, int addrs_size)
+ *
+ * Common routine for handling connect() and sctp_connectx().
+ * Connect will come in with just a single address.
+ */
+static int __sctp_connect(struct sock* sk,
+ struct sockaddr *kaddrs,
+ int addrs_size)
+{
+ struct sctp_sock *sp;
+ struct sctp_endpoint *ep;
+ struct sctp_association *asoc = NULL;
+ struct sctp_association *asoc2;
+ struct sctp_transport *transport;
+ union sctp_addr to;
+ struct sctp_af *af;
+ sctp_scope_t scope;
+ long timeo;
+ int err = 0;
+ int addrcnt = 0;
+ int walk_size = 0;
+ struct sockaddr *sa_addr;
+ void *addr_buf;
+
+ sp = sctp_sk(sk);
+ ep = sp->ep;
+
+ /* connect() cannot be done on a socket that is already in ESTABLISHED
+ * state - UDP-style peeled off socket or a TCP-style socket that
+ * is already connected.
+ * It cannot be done even on a TCP-style listening socket.
+ */
+ if (sctp_sstate(sk, ESTABLISHED) ||
+ (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) {
+ err = -EISCONN;
+ goto out_free;
+ }
+
+ /* Walk through the addrs buffer and count the number of addresses. */
+ addr_buf = kaddrs;
+ while (walk_size < addrs_size) {
+ sa_addr = (struct sockaddr *)addr_buf;
+ af = sctp_get_af_specific(sa_addr->sa_family);
+
+ /* If the address family is not supported or if this address
+ * causes the address buffer to overflow return EINVAL.
+ */
+ if (!af || (walk_size + af->sockaddr_len) > addrs_size) {
+ err = -EINVAL;
+ goto out_free;
+ }
+
+ err = sctp_verify_addr(sk, (union sctp_addr *)sa_addr,
+ af->sockaddr_len);
+ if (err)
+ goto out_free;
+
+ memcpy(&to, sa_addr, af->sockaddr_len);
+ to.v4.sin_port = ntohs(to.v4.sin_port);
+
+ /* Check if there already is a matching association on the
+ * endpoint (other than the one created here).
+ */
+ asoc2 = sctp_endpoint_lookup_assoc(ep, &to, &transport);
+ if (asoc2 && asoc2 != asoc) {
+ if (asoc2->state >= SCTP_STATE_ESTABLISHED)
+ err = -EISCONN;
+ else
+ err = -EALREADY;
+ goto out_free;
+ }
+
+ /* If we could not find a matching association on the endpoint,
+ * make sure that there is no peeled-off association matching
+ * the peer address even on another socket.
+ */
+ if (sctp_endpoint_is_peeled_off(ep, &to)) {
+ err = -EADDRNOTAVAIL;
+ goto out_free;
+ }
+
+ if (!asoc) {
+ /* If a bind() or sctp_bindx() is not called prior to
+ * an sctp_connectx() call, the system picks an
+ * ephemeral port and will choose an address set
+ * equivalent to binding with a wildcard address.
+ */
+ if (!ep->base.bind_addr.port) {
+ if (sctp_autobind(sk)) {
+ err = -EAGAIN;
+ goto out_free;
+ }
+ }
+
+ scope = sctp_scope(&to);
+ asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL);
+ if (!asoc) {
+ err = -ENOMEM;
+ goto out_free;
+ }
+ }
+
+ /* Prime the peer's transport structures. */
+ transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL,
+ SCTP_UNKNOWN);
+ if (!transport) {
+ err = -ENOMEM;
+ goto out_free;
+ }
+
+ addrcnt++;
+ addr_buf += af->sockaddr_len;
+ walk_size += af->sockaddr_len;
+ }
+
+ err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL);
+ if (err < 0) {
+ goto out_free;
+ }
+
+ err = sctp_primitive_ASSOCIATE(asoc, NULL);
+ if (err < 0) {
+ goto out_free;
+ }
+
+ /* Initialize sk's dport and daddr for getpeername() */
+ inet_sk(sk)->dport = htons(asoc->peer.port);
+ af = sctp_get_af_specific(to.sa.sa_family);
+ af->to_sk_daddr(&to, sk);
+
+ timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK);
+ err = sctp_wait_for_connect(asoc, &timeo);
+
+ /* Don't free association on exit. */
+ asoc = NULL;
+
+out_free:
+
+ SCTP_DEBUG_PRINTK("About to exit __sctp_connect() free asoc: %p"
+ " kaddrs: %p err: %d\n",
+ asoc, kaddrs, err);
+ if (asoc)
+ sctp_association_free(asoc);
+ return err;
+}
+
+/* Helper for tunneling sctp_connectx() requests through sctp_setsockopt()
+ *
+ * API 8.9
+ * int sctp_connectx(int sd, struct sockaddr *addrs, int addrcnt);
+ *
+ * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses.
+ * If the sd is an IPv6 socket, the addresses passed can either be IPv4
+ * or IPv6 addresses.
+ *
+ * A single address may be specified as INADDR_ANY or IN6ADDR_ANY, see
+ * Section 3.1.2 for this usage.
+ *
+ * addrs is a pointer to an array of one or more socket addresses. Each
+ * address is contained in its appropriate structure (i.e. struct
+ * sockaddr_in or struct sockaddr_in6) the family of the address type
+ * must be used to distengish the address length (note that this
+ * representation is termed a "packed array" of addresses). The caller
+ * specifies the number of addresses in the array with addrcnt.
+ *
+ * On success, sctp_connectx() returns 0. On failure, sctp_connectx() returns
+ * -1, and sets errno to the appropriate error code.
+ *
+ * For SCTP, the port given in each socket address must be the same, or
+ * sctp_connectx() will fail, setting errno to EINVAL.
+ *
+ * An application can use sctp_connectx to initiate an association with
+ * an endpoint that is multi-homed. Much like sctp_bindx() this call
+ * allows a caller to specify multiple addresses at which a peer can be
+ * reached. The way the SCTP stack uses the list of addresses to set up
+ * the association is implementation dependant. This function only
+ * specifies that the stack will try to make use of all the addresses in
+ * the list when needed.
+ *
+ * Note that the list of addresses passed in is only used for setting up
+ * the association. It does not necessarily equal the set of addresses
+ * the peer uses for the resulting association. If the caller wants to
+ * find out the set of peer addresses, it must use sctp_getpaddrs() to
+ * retrieve them after the association has been set up.
+ *
+ * Basically do nothing but copying the addresses from user to kernel
+ * land and invoking either sctp_connectx(). This is used for tunneling
+ * the sctp_connectx() request through sctp_setsockopt() from userspace.
+ *
+ * We don't use copy_from_user() for optimization: we first do the
+ * sanity checks (buffer size -fast- and access check-healthy
+ * pointer); if all of those succeed, then we can alloc the memory
+ * (expensive operation) needed to copy the data to kernel. Then we do
+ * the copying without checking the user space area
+ * (__copy_from_user()).
+ *
+ * On exit there is no need to do sockfd_put(), sys_setsockopt() does
+ * it.
+ *
+ * sk The sk of the socket
+ * addrs The pointer to the addresses in user land
+ * addrssize Size of the addrs buffer
+ *
+ * Returns 0 if ok, <0 errno code on error.
+ */
+SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk,
+ struct sockaddr __user *addrs,
+ int addrs_size)
+{
+ int err = 0;
+ struct sockaddr *kaddrs;
+
+ SCTP_DEBUG_PRINTK("%s - sk %p addrs %p addrs_size %d\n",
+ __FUNCTION__, sk, addrs, addrs_size);
+
+ if (unlikely(addrs_size <= 0))
+ return -EINVAL;
+
+ /* Check the user passed a healthy pointer. */
+ if (unlikely(!access_ok(VERIFY_READ, addrs, addrs_size)))
+ return -EFAULT;
+
+ /* Alloc space for the address array in kernel memory. */
+ kaddrs = (struct sockaddr *)kmalloc(addrs_size, GFP_KERNEL);
+ if (unlikely(!kaddrs))
+ return -ENOMEM;
+
+ if (__copy_from_user(kaddrs, addrs, addrs_size)) {
+ err = -EFAULT;
+ } else {
+ err = __sctp_connect(sk, kaddrs, addrs_size);
+ }
+
+ kfree(kaddrs);
+ return err;
+}
+
/* API 3.1.4 close() - UDP Style Syntax
* Applications use close() to perform graceful shutdown (as described in
* Section 10.1 of [SCTP]) on ALL the associations currently represented
@@ -1095,7 +1337,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
sp = sctp_sk(sk);
ep = sp->ep;
- SCTP_DEBUG_PRINTK("Using endpoint: %s.\n", ep->debug_name);
+ SCTP_DEBUG_PRINTK("Using endpoint: %p.\n", ep);
/* We cannot send a message over a TCP-style listening socket. */
if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) {
@@ -1306,7 +1548,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
}
/* Prime the peer's transport structures. */
- transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL);
+ transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL, SCTP_UNKNOWN);
if (!transport) {
err = -ENOMEM;
goto out_free;
@@ -2208,6 +2450,12 @@ SCTP_STATIC int sctp_setsockopt(struct sock *sk, int level, int optname,
optlen, SCTP_BINDX_REM_ADDR);
break;
+ case SCTP_SOCKOPT_CONNECTX:
+ /* 'optlen' is the size of the addresses buffer. */
+ retval = sctp_setsockopt_connectx(sk, (struct sockaddr __user *)optval,
+ optlen);
+ break;
+
case SCTP_DISABLE_FRAGMENTS:
retval = sctp_setsockopt_disable_fragments(sk, optval, optlen);
break;
@@ -2283,112 +2531,29 @@ out_nounlock:
*
* len: the size of the address.
*/
-SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *uaddr,
+SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *addr,
int addr_len)
{
- struct sctp_sock *sp;
- struct sctp_endpoint *ep;
- struct sctp_association *asoc;
- struct sctp_transport *transport;
- union sctp_addr to;
- struct sctp_af *af;
- sctp_scope_t scope;
- long timeo;
int err = 0;
+ struct sctp_af *af;
sctp_lock_sock(sk);
- SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d)\n",
- __FUNCTION__, sk, uaddr, addr_len);
-
- sp = sctp_sk(sk);
- ep = sp->ep;
-
- /* connect() cannot be done on a socket that is already in ESTABLISHED
- * state - UDP-style peeled off socket or a TCP-style socket that
- * is already connected.
- * It cannot be done even on a TCP-style listening socket.
- */
- if (sctp_sstate(sk, ESTABLISHED) ||
- (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) {
- err = -EISCONN;
- goto out_unlock;
- }
-
- err = sctp_verify_addr(sk, (union sctp_addr *)uaddr, addr_len);
- if (err)
- goto out_unlock;
+ SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d\n",
+ __FUNCTION__, sk, addr, addr_len);
- if (addr_len > sizeof(to))
- addr_len = sizeof(to);
- memcpy(&to, uaddr, addr_len);
- to.v4.sin_port = ntohs(to.v4.sin_port);
-
- asoc = sctp_endpoint_lookup_assoc(ep, &to, &transport);
- if (asoc) {
- if (asoc->state >= SCTP_STATE_ESTABLISHED)
- err = -EISCONN;
- else
- err = -EALREADY;
- goto out_unlock;
- }
-
- /* If we could not find a matching association on the endpoint,
- * make sure that there is no peeled-off association matching the
- * peer address even on another socket.
- */
- if (sctp_endpoint_is_peeled_off(ep, &to)) {
- err = -EADDRNOTAVAIL;
- goto out_unlock;
- }
-
- /* If a bind() or sctp_bindx() is not called prior to a connect()
- * call, the system picks an ephemeral port and will choose an address
- * set equivalent to binding with a wildcard address.
- */
- if (!ep->base.bind_addr.port) {
- if (sctp_autobind(sk)) {
- err = -EAGAIN;
- goto out_unlock;
- }
- }
-
- scope = sctp_scope(&to);
- asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL);
- if (!asoc) {
- err = -ENOMEM;
- goto out_unlock;
- }
-
- /* Prime the peer's transport structures. */
- transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL);
- if (!transport) {
- sctp_association_free(asoc);
- goto out_unlock;
- }
- err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL);
- if (err < 0) {
- sctp_association_free(asoc);
- goto out_unlock;
- }
-
- err = sctp_primitive_ASSOCIATE(asoc, NULL);
- if (err < 0) {
- sctp_association_free(asoc);
- goto out_unlock;
+ /* Validate addr_len before calling common connect/connectx routine. */
+ af = sctp_get_af_specific(addr->sa_family);
+ if (!af || addr_len < af->sockaddr_len) {
+ err = -EINVAL;
+ } else {
+ /* Pass correct addr len to common routine (so it knows there
+ * is only one address being passed.
+ */
+ err = __sctp_connect(sk, addr, af->sockaddr_len);
}
- /* Initialize sk's dport and daddr for getpeername() */
- inet_sk(sk)->dport = htons(asoc->peer.port);
- af = sctp_get_af_specific(to.sa.sa_family);
- af->to_sk_daddr(&to, sk);
-
- timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK);
- err = sctp_wait_for_connect(asoc, &timeo);
-
-out_unlock:
sctp_release_sock(sk);
-
return err;
}
@@ -2677,12 +2842,15 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len,
/* Map ipv4 address into v4-mapped-on-v6 address. */
sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
(union sctp_addr *)&status.sstat_primary.spinfo_address);
- status.sstat_primary.spinfo_state = transport->active;
+ status.sstat_primary.spinfo_state = transport->state;
status.sstat_primary.spinfo_cwnd = transport->cwnd;
status.sstat_primary.spinfo_srtt = transport->srtt;
status.sstat_primary.spinfo_rto = jiffies_to_msecs(transport->rto);
status.sstat_primary.spinfo_mtu = transport->pmtu;
+ if (status.sstat_primary.spinfo_state == SCTP_UNKNOWN)
+ status.sstat_primary.spinfo_state = SCTP_ACTIVE;
+
if (put_user(len, optlen)) {
retval = -EFAULT;
goto out;
@@ -2733,12 +2901,15 @@ static int sctp_getsockopt_peer_addr_info(struct sock *sk, int len,
return -EINVAL;
pinfo.spinfo_assoc_id = sctp_assoc2id(transport->asoc);
- pinfo.spinfo_state = transport->active;
+ pinfo.spinfo_state = transport->state;
pinfo.spinfo_cwnd = transport->cwnd;
pinfo.spinfo_srtt = transport->srtt;
pinfo.spinfo_rto = jiffies_to_msecs(transport->rto);
pinfo.spinfo_mtu = transport->pmtu;
+ if (pinfo.spinfo_state == SCTP_UNKNOWN)
+ pinfo.spinfo_state = SCTP_ACTIVE;
+
if (put_user(len, optlen)) {
retval = -EFAULT;
goto out;
@@ -3591,7 +3762,8 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
int retval = 0;
int len;
- SCTP_DEBUG_PRINTK("sctp_getsockopt(sk: %p, ...)\n", sk);
+ SCTP_DEBUG_PRINTK("sctp_getsockopt(sk: %p... optname: %d)\n",
+ sk, optname);
/* I can hardly begin to describe how wrong this is. This is
* so broken as to be worse than useless. The API draft
@@ -4368,15 +4540,11 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags,
* However, this function was corrent in any case. 8)
*/
if (flags & MSG_PEEK) {
- unsigned long cpu_flags;
-
- sctp_spin_lock_irqsave(&sk->sk_receive_queue.lock,
- cpu_flags);
+ spin_lock_bh(&sk->sk_receive_queue.lock);
skb = skb_peek(&sk->sk_receive_queue);
if (skb)
atomic_inc(&skb->users);
- sctp_spin_unlock_irqrestore(&sk->sk_receive_queue.lock,
- cpu_flags);
+ spin_unlock_bh(&sk->sk_receive_queue.lock);
} else {
skb = skb_dequeue(&sk->sk_receive_queue);
}
@@ -4600,8 +4768,7 @@ out:
return err;
do_error:
- if (asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1 >=
- asoc->max_init_attempts)
+ if (asoc->init_err_counter + 1 >= asoc->max_init_attempts)
err = -ETIMEDOUT;
else
err = -ECONNREFUSED;
@@ -4686,6 +4853,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
struct sctp_endpoint *newep = newsp->ep;
struct sk_buff *skb, *tmp;
struct sctp_ulpevent *event;
+ int flags = 0;
/* Migrate socket buffer sizes and all the socket level options to the
* new socket.
@@ -4707,6 +4875,17 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
sctp_sk(newsk)->bind_hash = pp;
inet_sk(newsk)->num = inet_sk(oldsk)->num;
+ /* Copy the bind_addr list from the original endpoint to the new
+ * endpoint so that we can handle restarts properly
+ */
+ if (assoc->peer.ipv4_address)
+ flags |= SCTP_ADDR4_PEERSUPP;
+ if (assoc->peer.ipv6_address)
+ flags |= SCTP_ADDR6_PEERSUPP;
+ sctp_bind_addr_copy(&newsp->ep->base.bind_addr,
+ &oldsp->ep->base.bind_addr,
+ SCTP_SCOPE_GLOBAL, GFP_KERNEL, flags);
+
/* Move any messages in the old socket's receive queue that are for the
* peeled off association to the new socket's receive queue.
*/
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index f30882e1e96..0ec0fde6e6c 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -83,7 +83,9 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer,
peer->last_time_used = jiffies;
peer->last_time_ecne_reduced = jiffies;
- peer->active = SCTP_ACTIVE;
+ peer->init_sent_count = 0;
+
+ peer->state = SCTP_ACTIVE;
peer->hb_allowed = 0;
/* Initialize the default path max_retrans. */
diff --git a/net/socket.c b/net/socket.c
index cec0cb38b9c..6f2a1788197 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -81,6 +81,7 @@
#include <linux/syscalls.h>
#include <linux/compat.h>
#include <linux/kmod.h>
+#include <linux/audit.h>
#ifdef CONFIG_NET_RADIO
#include <linux/wireless.h> /* Note : will define WIRELESS_EXT */
@@ -226,7 +227,7 @@ int move_addr_to_kernel(void __user *uaddr, int ulen, void *kaddr)
return 0;
if(copy_from_user(kaddr,uaddr,ulen))
return -EFAULT;
- return 0;
+ return audit_sockaddr(ulen, kaddr);
}
/**
@@ -382,9 +383,8 @@ int sock_map_fd(struct socket *sock)
goto out;
}
- sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino);
+ this.len = sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino);
this.name = name;
- this.len = strlen(name);
this.hash = SOCK_INODE(sock)->i_ino;
file->f_dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this);
@@ -1906,7 +1906,11 @@ asmlinkage long sys_socketcall(int call, unsigned long __user *args)
/* copy_from_user should be SMP safe. */
if (copy_from_user(a, args, nargs[call]))
return -EFAULT;
-
+
+ err = audit_socketcall(nargs[call]/sizeof(unsigned long), a);
+ if (err)
+ return err;
+
a0=a[0];
a1=a[1];
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 9bcec9b927b..505e2d4b3d6 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -66,10 +66,10 @@ rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt)
u32 flavor = pseudoflavor_to_flavor(pseudoflavor);
if (flavor >= RPC_AUTH_MAXFLAVOR || !(ops = auth_flavors[flavor]))
- return NULL;
+ return ERR_PTR(-EINVAL);
auth = ops->create(clnt, pseudoflavor);
- if (!auth)
- return NULL;
+ if (IS_ERR(auth))
+ return auth;
if (clnt->cl_auth)
rpcauth_destroy(clnt->cl_auth);
clnt->cl_auth = auth;
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index a33b627cbef..2f7b867161d 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -660,14 +660,16 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
{
struct gss_auth *gss_auth;
struct rpc_auth * auth;
+ int err = -ENOMEM; /* XXX? */
dprintk("RPC: creating GSS authenticator for client %p\n",clnt);
if (!try_module_get(THIS_MODULE))
- return NULL;
+ return ERR_PTR(err);
if (!(gss_auth = kmalloc(sizeof(*gss_auth), GFP_KERNEL)))
goto out_dec;
gss_auth->client = clnt;
+ err = -EINVAL;
gss_auth->mech = gss_mech_get_by_pseudoflavor(flavor);
if (!gss_auth->mech) {
printk(KERN_WARNING "%s: Pseudoflavor %d not found!",
@@ -675,9 +677,8 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
goto err_free;
}
gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor);
- /* FIXME: Will go away once privacy support is merged in */
- if (gss_auth->service == RPC_GSS_SVC_PRIVACY)
- gss_auth->service = RPC_GSS_SVC_INTEGRITY;
+ if (gss_auth->service == 0)
+ goto err_put_mech;
INIT_LIST_HEAD(&gss_auth->upcalls);
spin_lock_init(&gss_auth->lock);
auth = &gss_auth->rpc_auth;
@@ -687,15 +688,18 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
auth->au_flavor = flavor;
atomic_set(&auth->au_count, 1);
- if (rpcauth_init_credcache(auth, GSS_CRED_EXPIRE) < 0)
+ err = rpcauth_init_credcache(auth, GSS_CRED_EXPIRE);
+ if (err)
goto err_put_mech;
snprintf(gss_auth->path, sizeof(gss_auth->path), "%s/%s",
clnt->cl_pathname,
gss_auth->mech->gm_name);
gss_auth->dentry = rpc_mkpipe(gss_auth->path, clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
- if (IS_ERR(gss_auth->dentry))
+ if (IS_ERR(gss_auth->dentry)) {
+ err = PTR_ERR(gss_auth->dentry);
goto err_put_mech;
+ }
return auth;
err_put_mech:
@@ -704,7 +708,7 @@ err_free:
kfree(gss_auth);
out_dec:
module_put(THIS_MODULE);
- return NULL;
+ return ERR_PTR(err);
}
static void
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 02bc029d46f..f17e6153b68 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -97,12 +97,13 @@ rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name)
* made to sleep too long.
*/
struct rpc_clnt *
-rpc_create_client(struct rpc_xprt *xprt, char *servname,
+rpc_new_client(struct rpc_xprt *xprt, char *servname,
struct rpc_program *program, u32 vers,
rpc_authflavor_t flavor)
{
struct rpc_version *version;
struct rpc_clnt *clnt = NULL;
+ struct rpc_auth *auth;
int err;
int len;
@@ -157,10 +158,11 @@ rpc_create_client(struct rpc_xprt *xprt, char *servname,
if (err < 0)
goto out_no_path;
- err = -ENOMEM;
- if (!rpcauth_create(flavor, clnt)) {
+ auth = rpcauth_create(flavor, clnt);
+ if (IS_ERR(auth)) {
printk(KERN_INFO "RPC: Couldn't create auth handle (flavor %u)\n",
flavor);
+ err = PTR_ERR(auth);
goto out_no_auth;
}
@@ -178,6 +180,37 @@ out_no_path:
kfree(clnt->cl_server);
kfree(clnt);
out_err:
+ xprt_destroy(xprt);
+ return ERR_PTR(err);
+}
+
+/**
+ * Create an RPC client
+ * @xprt - pointer to xprt struct
+ * @servname - name of server
+ * @info - rpc_program
+ * @version - rpc_program version
+ * @authflavor - rpc_auth flavour to use
+ *
+ * Creates an RPC client structure, then pings the server in order to
+ * determine if it is up, and if it supports this program and version.
+ *
+ * This function should never be called by asynchronous tasks such as
+ * the portmapper.
+ */
+struct rpc_clnt *rpc_create_client(struct rpc_xprt *xprt, char *servname,
+ struct rpc_program *info, u32 version, rpc_authflavor_t authflavor)
+{
+ struct rpc_clnt *clnt;
+ int err;
+
+ clnt = rpc_new_client(xprt, servname, info, version, authflavor);
+ if (IS_ERR(clnt))
+ return clnt;
+ err = rpc_ping(clnt, RPC_TASK_SOFT|RPC_TASK_NOINTR);
+ if (err == 0)
+ return clnt;
+ rpc_shutdown_client(clnt);
return ERR_PTR(err);
}
@@ -208,6 +241,8 @@ rpc_clone_client(struct rpc_clnt *clnt)
rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
if (new->cl_auth)
atomic_inc(&new->cl_auth->au_count);
+ new->cl_pmap = &new->cl_pmap_default;
+ rpc_init_wait_queue(&new->cl_pmap_default.pm_bindwait, "bindwait");
return new;
out_no_clnt:
printk(KERN_INFO "RPC: out of memory in %s\n", __FUNCTION__);
@@ -296,6 +331,44 @@ rpc_release_client(struct rpc_clnt *clnt)
rpc_destroy_client(clnt);
}
+/**
+ * rpc_bind_new_program - bind a new RPC program to an existing client
+ * @old - old rpc_client
+ * @program - rpc program to set
+ * @vers - rpc program version
+ *
+ * Clones the rpc client and sets up a new RPC program. This is mainly
+ * of use for enabling different RPC programs to share the same transport.
+ * The Sun NFSv2/v3 ACL protocol can do this.
+ */
+struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old,
+ struct rpc_program *program,
+ int vers)
+{
+ struct rpc_clnt *clnt;
+ struct rpc_version *version;
+ int err;
+
+ BUG_ON(vers >= program->nrvers || !program->version[vers]);
+ version = program->version[vers];
+ clnt = rpc_clone_client(old);
+ if (IS_ERR(clnt))
+ goto out;
+ clnt->cl_procinfo = version->procs;
+ clnt->cl_maxproc = version->nrprocs;
+ clnt->cl_protname = program->name;
+ clnt->cl_prog = program->number;
+ clnt->cl_vers = version->number;
+ clnt->cl_stats = program->stats;
+ err = rpc_ping(clnt, RPC_TASK_SOFT|RPC_TASK_NOINTR);
+ if (err != 0) {
+ rpc_shutdown_client(clnt);
+ clnt = ERR_PTR(err);
+ }
+out:
+ return clnt;
+}
+
/*
* Default callback for async RPC calls
*/
@@ -305,38 +378,41 @@ rpc_default_callback(struct rpc_task *task)
}
/*
- * Export the signal mask handling for aysnchronous code that
+ * Export the signal mask handling for synchronous code that
* sleeps on RPC calls
*/
+#define RPC_INTR_SIGNALS (sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGKILL))
+static void rpc_save_sigmask(sigset_t *oldset, int intr)
+{
+ unsigned long sigallow = 0;
+ sigset_t sigmask;
+
+ /* Block all signals except those listed in sigallow */
+ if (intr)
+ sigallow |= RPC_INTR_SIGNALS;
+ siginitsetinv(&sigmask, sigallow);
+ sigprocmask(SIG_BLOCK, &sigmask, oldset);
+}
+
+static inline void rpc_task_sigmask(struct rpc_task *task, sigset_t *oldset)
+{
+ rpc_save_sigmask(oldset, !RPC_TASK_UNINTERRUPTIBLE(task));
+}
+
+static inline void rpc_restore_sigmask(sigset_t *oldset)
+{
+ sigprocmask(SIG_SETMASK, oldset, NULL);
+}
+
void rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset)
{
- unsigned long sigallow = sigmask(SIGKILL);
- unsigned long irqflags;
-
- /* Turn off various signals */
- if (clnt->cl_intr) {
- struct k_sigaction *action = current->sighand->action;
- if (action[SIGINT-1].sa.sa_handler == SIG_DFL)
- sigallow |= sigmask(SIGINT);
- if (action[SIGQUIT-1].sa.sa_handler == SIG_DFL)
- sigallow |= sigmask(SIGQUIT);
- }
- spin_lock_irqsave(&current->sighand->siglock, irqflags);
- *oldset = current->blocked;
- siginitsetinv(&current->blocked, sigallow & ~oldset->sig[0]);
- recalc_sigpending();
- spin_unlock_irqrestore(&current->sighand->siglock, irqflags);
+ rpc_save_sigmask(oldset, clnt->cl_intr);
}
void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset)
{
- unsigned long irqflags;
-
- spin_lock_irqsave(&current->sighand->siglock, irqflags);
- current->blocked = *oldset;
- recalc_sigpending();
- spin_unlock_irqrestore(&current->sighand->siglock, irqflags);
+ rpc_restore_sigmask(oldset);
}
/*
@@ -354,26 +430,26 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
BUG_ON(flags & RPC_TASK_ASYNC);
- rpc_clnt_sigmask(clnt, &oldset);
-
status = -ENOMEM;
task = rpc_new_task(clnt, NULL, flags);
if (task == NULL)
goto out;
+ /* Mask signals on RPC calls _and_ GSS_AUTH upcalls */
+ rpc_task_sigmask(task, &oldset);
+
rpc_call_setup(task, msg, 0);
/* Set up the call info struct and execute the task */
- if (task->tk_status == 0)
+ if (task->tk_status == 0) {
status = rpc_execute(task);
- else {
+ } else {
status = task->tk_status;
rpc_release_task(task);
}
+ rpc_restore_sigmask(&oldset);
out:
- rpc_clnt_sigunmask(clnt, &oldset);
-
return status;
}
@@ -394,8 +470,6 @@ rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags,
flags |= RPC_TASK_ASYNC;
- rpc_clnt_sigmask(clnt, &oldset);
-
/* Create/initialize a new RPC task */
if (!callback)
callback = rpc_default_callback;
@@ -404,6 +478,9 @@ rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags,
goto out;
task->tk_calldata = data;
+ /* Mask signals on GSS_AUTH upcalls */
+ rpc_task_sigmask(task, &oldset);
+
rpc_call_setup(task, msg, 0);
/* Set up the call info struct and execute the task */
@@ -413,9 +490,8 @@ rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags,
else
rpc_release_task(task);
+ rpc_restore_sigmask(&oldset);
out:
- rpc_clnt_sigunmask(clnt, &oldset);
-
return status;
}
@@ -593,7 +669,7 @@ call_allocate(struct rpc_task *task)
return;
printk(KERN_INFO "RPC: buffer allocation failed for task %p\n", task);
- if (RPC_IS_ASYNC(task) || !(task->tk_client->cl_intr && signalled())) {
+ if (RPC_IS_ASYNC(task) || !signalled()) {
xprt_release(task);
task->tk_action = call_reserve;
rpc_delay(task, HZ>>4);
@@ -957,7 +1033,9 @@ call_header(struct rpc_task *task)
*p++ = htonl(clnt->cl_prog); /* program number */
*p++ = htonl(clnt->cl_vers); /* program version */
*p++ = htonl(task->tk_msg.rpc_proc->p_proc); /* procedure */
- return rpcauth_marshcred(task, p);
+ p = rpcauth_marshcred(task, p);
+ req->rq_slen = xdr_adjust_iovec(&req->rq_svec[0], p);
+ return p;
}
/*
@@ -986,10 +1064,11 @@ call_verify(struct rpc_task *task)
case RPC_AUTH_ERROR:
break;
case RPC_MISMATCH:
- printk(KERN_WARNING "%s: RPC call version mismatch!\n", __FUNCTION__);
- goto out_eio;
+ dprintk("%s: RPC call version mismatch!\n", __FUNCTION__);
+ error = -EPROTONOSUPPORT;
+ goto out_err;
default:
- printk(KERN_WARNING "%s: RPC call rejected, unknown error: %x\n", __FUNCTION__, n);
+ dprintk("%s: RPC call rejected, unknown error: %x\n", __FUNCTION__, n);
goto out_eio;
}
if (--len < 0)
@@ -1040,23 +1119,26 @@ call_verify(struct rpc_task *task)
case RPC_SUCCESS:
return p;
case RPC_PROG_UNAVAIL:
- printk(KERN_WARNING "RPC: call_verify: program %u is unsupported by server %s\n",
+ dprintk("RPC: call_verify: program %u is unsupported by server %s\n",
(unsigned int)task->tk_client->cl_prog,
task->tk_client->cl_server);
- goto out_eio;
+ error = -EPFNOSUPPORT;
+ goto out_err;
case RPC_PROG_MISMATCH:
- printk(KERN_WARNING "RPC: call_verify: program %u, version %u unsupported by server %s\n",
+ dprintk("RPC: call_verify: program %u, version %u unsupported by server %s\n",
(unsigned int)task->tk_client->cl_prog,
(unsigned int)task->tk_client->cl_vers,
task->tk_client->cl_server);
- goto out_eio;
+ error = -EPROTONOSUPPORT;
+ goto out_err;
case RPC_PROC_UNAVAIL:
- printk(KERN_WARNING "RPC: call_verify: proc %p unsupported by program %u, version %u on server %s\n",
+ dprintk("RPC: call_verify: proc %p unsupported by program %u, version %u on server %s\n",
task->tk_msg.rpc_proc,
task->tk_client->cl_prog,
task->tk_client->cl_vers,
task->tk_client->cl_server);
- goto out_eio;
+ error = -EOPNOTSUPP;
+ goto out_err;
case RPC_GARBAGE_ARGS:
dprintk("RPC: %4d %s: server saw garbage\n", task->tk_pid, __FUNCTION__);
break; /* retry */
@@ -1069,7 +1151,7 @@ out_retry:
task->tk_client->cl_stats->rpcgarbage++;
if (task->tk_garb_retry) {
task->tk_garb_retry--;
- dprintk(KERN_WARNING "RPC %s: retrying %4d\n", __FUNCTION__, task->tk_pid);
+ dprintk("RPC %s: retrying %4d\n", __FUNCTION__, task->tk_pid);
task->tk_action = call_bind;
return NULL;
}
@@ -1083,3 +1165,30 @@ out_overflow:
printk(KERN_WARNING "RPC %s: server reply was truncated.\n", __FUNCTION__);
goto out_retry;
}
+
+static int rpcproc_encode_null(void *rqstp, u32 *data, void *obj)
+{
+ return 0;
+}
+
+static int rpcproc_decode_null(void *rqstp, u32 *data, void *obj)
+{
+ return 0;
+}
+
+static struct rpc_procinfo rpcproc_null = {
+ .p_encode = rpcproc_encode_null,
+ .p_decode = rpcproc_decode_null,
+};
+
+int rpc_ping(struct rpc_clnt *clnt, int flags)
+{
+ struct rpc_message msg = {
+ .rpc_proc = &rpcproc_null,
+ };
+ int err;
+ msg.rpc_cred = authnull_ops.lookup_cred(NULL, NULL, 0);
+ err = rpc_call_sync(clnt, &msg, flags);
+ put_rpccred(msg.rpc_cred);
+ return err;
+}
diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c
index d0b1d2c34a4..4e81f276692 100644
--- a/net/sunrpc/pmap_clnt.c
+++ b/net/sunrpc/pmap_clnt.c
@@ -53,6 +53,9 @@ rpc_getport(struct rpc_task *task, struct rpc_clnt *clnt)
task->tk_pid, clnt->cl_server,
map->pm_prog, map->pm_vers, map->pm_prot);
+ /* Autobind on cloned rpc clients is discouraged */
+ BUG_ON(clnt->cl_parent != clnt);
+
spin_lock(&pmap_lock);
if (map->pm_binding) {
rpc_sleep_on(&map->pm_bindwait, task, NULL, NULL);
@@ -207,12 +210,10 @@ pmap_create(char *hostname, struct sockaddr_in *srvaddr, int proto)
xprt->addr.sin_port = htons(RPC_PMAP_PORT);
/* printk("pmap: create clnt\n"); */
- clnt = rpc_create_client(xprt, hostname,
+ clnt = rpc_new_client(xprt, hostname,
&pmap_program, RPC_PMAP_VERSION,
RPC_AUTH_UNIX);
- if (IS_ERR(clnt)) {
- xprt_destroy(xprt);
- } else {
+ if (!IS_ERR(clnt)) {
clnt->cl_softrtry = 1;
clnt->cl_chatty = 1;
clnt->cl_oneshot = 1;
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index c06614d0e31..2d9eb7fbd52 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -290,7 +290,7 @@ static void rpc_make_runnable(struct rpc_task *task)
return;
}
} else
- wake_up(&task->u.tk_wait.waitq);
+ wake_up_bit(&task->tk_runstate, RPC_TASK_QUEUED);
}
/*
@@ -555,6 +555,38 @@ __rpc_atrun(struct rpc_task *task)
}
/*
+ * Helper that calls task->tk_exit if it exists and then returns
+ * true if we should exit __rpc_execute.
+ */
+static inline int __rpc_do_exit(struct rpc_task *task)
+{
+ if (task->tk_exit != NULL) {
+ lock_kernel();
+ task->tk_exit(task);
+ unlock_kernel();
+ /* If tk_action is non-null, we should restart the call */
+ if (task->tk_action != NULL) {
+ if (!RPC_ASSASSINATED(task)) {
+ /* Release RPC slot and buffer memory */
+ xprt_release(task);
+ rpc_free(task);
+ return 0;
+ }
+ printk(KERN_ERR "RPC: dead task tried to walk away.\n");
+ }
+ }
+ return 1;
+}
+
+static int rpc_wait_bit_interruptible(void *word)
+{
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+ schedule();
+ return 0;
+}
+
+/*
* This is the RPC `scheduler' (or rather, the finite state machine).
*/
static int __rpc_execute(struct rpc_task *task)
@@ -566,8 +598,7 @@ static int __rpc_execute(struct rpc_task *task)
BUG_ON(RPC_IS_QUEUED(task));
- restarted:
- while (1) {
+ for (;;) {
/*
* Garbage collection of pending timers...
*/
@@ -600,11 +631,12 @@ static int __rpc_execute(struct rpc_task *task)
* by someone else.
*/
if (!RPC_IS_QUEUED(task)) {
- if (!task->tk_action)
+ if (task->tk_action != NULL) {
+ lock_kernel();
+ task->tk_action(task);
+ unlock_kernel();
+ } else if (__rpc_do_exit(task))
break;
- lock_kernel();
- task->tk_action(task);
- unlock_kernel();
}
/*
@@ -624,44 +656,26 @@ static int __rpc_execute(struct rpc_task *task)
/* sync task: sleep here */
dprintk("RPC: %4d sync task going to sleep\n", task->tk_pid);
- if (RPC_TASK_UNINTERRUPTIBLE(task)) {
- __wait_event(task->u.tk_wait.waitq, !RPC_IS_QUEUED(task));
- } else {
- __wait_event_interruptible(task->u.tk_wait.waitq, !RPC_IS_QUEUED(task), status);
+ /* Note: Caller should be using rpc_clnt_sigmask() */
+ status = out_of_line_wait_on_bit(&task->tk_runstate,
+ RPC_TASK_QUEUED, rpc_wait_bit_interruptible,
+ TASK_INTERRUPTIBLE);
+ if (status == -ERESTARTSYS) {
/*
* When a sync task receives a signal, it exits with
* -ERESTARTSYS. In order to catch any callbacks that
* clean up after sleeping on some queue, we don't
* break the loop here, but go around once more.
*/
- if (status == -ERESTARTSYS) {
- dprintk("RPC: %4d got signal\n", task->tk_pid);
- task->tk_flags |= RPC_TASK_KILLED;
- rpc_exit(task, -ERESTARTSYS);
- rpc_wake_up_task(task);
- }
+ dprintk("RPC: %4d got signal\n", task->tk_pid);
+ task->tk_flags |= RPC_TASK_KILLED;
+ rpc_exit(task, -ERESTARTSYS);
+ rpc_wake_up_task(task);
}
rpc_set_running(task);
dprintk("RPC: %4d sync task resuming\n", task->tk_pid);
}
- if (task->tk_exit) {
- lock_kernel();
- task->tk_exit(task);
- unlock_kernel();
- /* If tk_action is non-null, the user wants us to restart */
- if (task->tk_action) {
- if (!RPC_ASSASSINATED(task)) {
- /* Release RPC slot and buffer memory */
- if (task->tk_rqstp)
- xprt_release(task);
- rpc_free(task);
- goto restarted;
- }
- printk(KERN_ERR "RPC: dead task tries to walk away.\n");
- }
- }
-
dprintk("RPC: %4d exit() = %d\n", task->tk_pid, task->tk_status);
status = task->tk_status;
@@ -759,8 +773,6 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, rpc_action call
/* Initialize workqueue for async tasks */
task->tk_workqueue = rpciod_workqueue;
- if (!RPC_IS_ASYNC(task))
- init_waitqueue_head(&task->u.tk_wait.waitq);
if (clnt) {
atomic_inc(&clnt->cl_users);
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index d4f26bf9e73..62a07349527 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -41,7 +41,9 @@ EXPORT_SYMBOL(rpc_release_task);
/* RPC client functions */
EXPORT_SYMBOL(rpc_create_client);
+EXPORT_SYMBOL(rpc_new_client);
EXPORT_SYMBOL(rpc_clone_client);
+EXPORT_SYMBOL(rpc_bind_new_program);
EXPORT_SYMBOL(rpc_destroy_client);
EXPORT_SYMBOL(rpc_shutdown_client);
EXPORT_SYMBOL(rpc_release_client);
@@ -61,7 +63,6 @@ EXPORT_SYMBOL(rpc_mkpipe);
/* Client transport */
EXPORT_SYMBOL(xprt_create_proto);
-EXPORT_SYMBOL(xprt_destroy);
EXPORT_SYMBOL(xprt_set_timeout);
EXPORT_SYMBOL(xprt_udp_slot_table_entries);
EXPORT_SYMBOL(xprt_tcp_slot_table_entries);
@@ -129,6 +130,10 @@ EXPORT_SYMBOL(xdr_encode_netobj);
EXPORT_SYMBOL(xdr_encode_pages);
EXPORT_SYMBOL(xdr_inline_pages);
EXPORT_SYMBOL(xdr_shift_buf);
+EXPORT_SYMBOL(xdr_encode_word);
+EXPORT_SYMBOL(xdr_decode_word);
+EXPORT_SYMBOL(xdr_encode_array2);
+EXPORT_SYMBOL(xdr_decode_array2);
EXPORT_SYMBOL(xdr_buf_from_iov);
EXPORT_SYMBOL(xdr_buf_subsegment);
EXPORT_SYMBOL(xdr_buf_read_netobj);
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index bb2d99f3331..e9bd91265f7 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -35,20 +35,24 @@ svc_create(struct svc_program *prog, unsigned int bufsize)
if (!(serv = (struct svc_serv *) kmalloc(sizeof(*serv), GFP_KERNEL)))
return NULL;
memset(serv, 0, sizeof(*serv));
+ serv->sv_name = prog->pg_name;
serv->sv_program = prog;
serv->sv_nrthreads = 1;
serv->sv_stats = prog->pg_stats;
serv->sv_bufsz = bufsize? bufsize : 4096;
- prog->pg_lovers = prog->pg_nvers-1;
xdrsize = 0;
- for (vers=0; vers<prog->pg_nvers ; vers++)
- if (prog->pg_vers[vers]) {
- prog->pg_hivers = vers;
- if (prog->pg_lovers > vers)
- prog->pg_lovers = vers;
- if (prog->pg_vers[vers]->vs_xdrsize > xdrsize)
- xdrsize = prog->pg_vers[vers]->vs_xdrsize;
- }
+ while (prog) {
+ prog->pg_lovers = prog->pg_nvers-1;
+ for (vers=0; vers<prog->pg_nvers ; vers++)
+ if (prog->pg_vers[vers]) {
+ prog->pg_hivers = vers;
+ if (prog->pg_lovers > vers)
+ prog->pg_lovers = vers;
+ if (prog->pg_vers[vers]->vs_xdrsize > xdrsize)
+ xdrsize = prog->pg_vers[vers]->vs_xdrsize;
+ }
+ prog = prog->pg_next;
+ }
serv->sv_xdrsize = xdrsize;
INIT_LIST_HEAD(&serv->sv_threads);
INIT_LIST_HEAD(&serv->sv_sockets);
@@ -56,8 +60,6 @@ svc_create(struct svc_program *prog, unsigned int bufsize)
INIT_LIST_HEAD(&serv->sv_permsocks);
spin_lock_init(&serv->sv_lock);
- serv->sv_name = prog->pg_name;
-
/* Remove any stale portmap registrations */
svc_register(serv, 0, 0);
@@ -281,6 +283,7 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
rqstp->rq_res.len = 0;
rqstp->rq_res.page_base = 0;
rqstp->rq_res.page_len = 0;
+ rqstp->rq_res.buflen = PAGE_SIZE;
rqstp->rq_res.tail[0].iov_len = 0;
/* tcp needs a space for the record length... */
if (rqstp->rq_prot == IPPROTO_TCP)
@@ -338,7 +341,10 @@ svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
goto sendit;
}
- if (prog != progp->pg_prog)
+ for (progp = serv->sv_program; progp; progp = progp->pg_next)
+ if (prog == progp->pg_prog)
+ break;
+ if (progp == NULL)
goto err_bad_prog;
if (vers >= progp->pg_nvers ||
@@ -451,11 +457,7 @@ err_bad_auth:
goto sendit;
err_bad_prog:
-#ifdef RPC_PARANOIA
- if (prog != 100227 || progp->pg_prog != 100003)
- printk("svc: unknown program %d (me %d)\n", prog, progp->pg_prog);
- /* else it is just a Solaris client seeing if ACLs are supported */
-#endif
+ dprintk("svc: unknown program %d\n", prog);
serv->sv_stats->rpcbadfmt++;
svc_putu32(resv, rpc_prog_unavail);
goto sendit;
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 2b99b4028d3..d6baf6fdf8a 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -8,6 +8,7 @@
#include <linux/err.h>
#include <linux/seq_file.h>
#include <linux/hash.h>
+#include <linux/string.h>
#define RPCDBG_FACILITY RPCDBG_AUTH
@@ -20,14 +21,6 @@
*/
-static char *strdup(char *s)
-{
- char *rv = kmalloc(strlen(s)+1, GFP_KERNEL);
- if (rv)
- strcpy(rv, s);
- return rv;
-}
-
struct unix_domain {
struct auth_domain h;
int addr_changes;
@@ -55,7 +48,7 @@ struct auth_domain *unix_domain_find(char *name)
if (new == NULL)
return NULL;
cache_init(&new->h.h);
- new->h.name = strdup(name);
+ new->h.name = kstrdup(name, GFP_KERNEL);
new->h.flavour = RPC_AUTH_UNIX;
new->addr_changes = 0;
new->h.h.expiry_time = NEVER;
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 05907035bc9..56db8f13e6c 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -1185,8 +1185,8 @@ svc_recv(struct svc_serv *serv, struct svc_rqst *rqstp, long timeout)
arg->page_len = (pages-2)*PAGE_SIZE;
arg->len = (pages-1)*PAGE_SIZE;
arg->tail[0].iov_len = 0;
-
- try_to_freeze(PF_FREEZE);
+
+ try_to_freeze();
if (signalled())
return -EINTR;
@@ -1227,7 +1227,7 @@ svc_recv(struct svc_serv *serv, struct svc_rqst *rqstp, long timeout)
schedule_timeout(timeout);
- try_to_freeze(PF_FREEZE);
+ try_to_freeze();
spin_lock_bh(&serv->sv_lock);
remove_wait_queue(&rqstp->rq_wait, &wait);
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
index 67b9f035ba8..8a4d9c106af 100644
--- a/net/sunrpc/xdr.c
+++ b/net/sunrpc/xdr.c
@@ -176,21 +176,23 @@ xdr_inline_pages(struct xdr_buf *xdr, unsigned int offset,
xdr->buflen += len;
}
-void
+ssize_t
xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base,
skb_reader_t *desc,
skb_read_actor_t copy_actor)
{
struct page **ppage = xdr->pages;
unsigned int len, pglen = xdr->page_len;
+ ssize_t copied = 0;
int ret;
len = xdr->head[0].iov_len;
if (base < len) {
len -= base;
ret = copy_actor(desc, (char *)xdr->head[0].iov_base + base, len);
+ copied += ret;
if (ret != len || !desc->count)
- return;
+ goto out;
base = 0;
} else
base -= len;
@@ -210,6 +212,17 @@ xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base,
do {
char *kaddr;
+ /* ACL likes to be lazy in allocating pages - ACLs
+ * are small by default but can get huge. */
+ if (unlikely(*ppage == NULL)) {
+ *ppage = alloc_page(GFP_ATOMIC);
+ if (unlikely(*ppage == NULL)) {
+ if (copied == 0)
+ copied = -ENOMEM;
+ goto out;
+ }
+ }
+
len = PAGE_CACHE_SIZE;
kaddr = kmap_atomic(*ppage, KM_SKB_SUNRPC_DATA);
if (base) {
@@ -225,14 +238,17 @@ xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base,
}
flush_dcache_page(*ppage);
kunmap_atomic(kaddr, KM_SKB_SUNRPC_DATA);
+ copied += ret;
if (ret != len || !desc->count)
- return;
+ goto out;
ppage++;
} while ((pglen -= len) != 0);
copy_tail:
len = xdr->tail[0].iov_len;
if (base < len)
- copy_actor(desc, (char *)xdr->tail[0].iov_base + base, len - base);
+ copied += copy_actor(desc, (char *)xdr->tail[0].iov_base + base, len - base);
+out:
+ return copied;
}
@@ -616,12 +632,24 @@ xdr_shift_buf(struct xdr_buf *buf, size_t len)
void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, uint32_t *p)
{
struct kvec *iov = buf->head;
+ int scratch_len = buf->buflen - buf->page_len - buf->tail[0].iov_len;
+ BUG_ON(scratch_len < 0);
xdr->buf = buf;
xdr->iov = iov;
- xdr->end = (uint32_t *)((char *)iov->iov_base + iov->iov_len);
- buf->len = iov->iov_len = (char *)p - (char *)iov->iov_base;
- xdr->p = p;
+ xdr->p = (uint32_t *)((char *)iov->iov_base + iov->iov_len);
+ xdr->end = (uint32_t *)((char *)iov->iov_base + scratch_len);
+ BUG_ON(iov->iov_len > scratch_len);
+
+ if (p != xdr->p && p != NULL) {
+ size_t len;
+
+ BUG_ON(p < xdr->p || p > xdr->end);
+ len = (char *)p - (char *)xdr->p;
+ xdr->p = p;
+ buf->len += len;
+ iov->iov_len += len;
+ }
}
EXPORT_SYMBOL(xdr_init_encode);
@@ -859,8 +887,34 @@ out:
return status;
}
-static int
-read_u32_from_xdr_buf(struct xdr_buf *buf, int base, u32 *obj)
+/* obj is assumed to point to allocated memory of size at least len: */
+int
+write_bytes_to_xdr_buf(struct xdr_buf *buf, int base, void *obj, int len)
+{
+ struct xdr_buf subbuf;
+ int this_len;
+ int status;
+
+ status = xdr_buf_subsegment(buf, &subbuf, base, len);
+ if (status)
+ goto out;
+ this_len = min(len, (int)subbuf.head[0].iov_len);
+ memcpy(subbuf.head[0].iov_base, obj, this_len);
+ len -= this_len;
+ obj += this_len;
+ this_len = min(len, (int)subbuf.page_len);
+ if (this_len)
+ _copy_to_pages(subbuf.pages, subbuf.page_base, obj, this_len);
+ len -= this_len;
+ obj += this_len;
+ this_len = min(len, (int)subbuf.tail[0].iov_len);
+ memcpy(subbuf.tail[0].iov_base, obj, this_len);
+out:
+ return status;
+}
+
+int
+xdr_decode_word(struct xdr_buf *buf, int base, u32 *obj)
{
u32 raw;
int status;
@@ -872,6 +926,14 @@ read_u32_from_xdr_buf(struct xdr_buf *buf, int base, u32 *obj)
return 0;
}
+int
+xdr_encode_word(struct xdr_buf *buf, int base, u32 obj)
+{
+ u32 raw = htonl(obj);
+
+ return write_bytes_to_xdr_buf(buf, base, &raw, sizeof(obj));
+}
+
/* If the netobj starting offset bytes from the start of xdr_buf is contained
* entirely in the head or the tail, set object to point to it; otherwise
* try to find space for it at the end of the tail, copy it there, and
@@ -882,7 +944,7 @@ xdr_buf_read_netobj(struct xdr_buf *buf, struct xdr_netobj *obj, int offset)
u32 tail_offset = buf->head[0].iov_len + buf->page_len;
u32 obj_end_offset;
- if (read_u32_from_xdr_buf(buf, offset, &obj->len))
+ if (xdr_decode_word(buf, offset, &obj->len))
goto out;
obj_end_offset = offset + 4 + obj->len;
@@ -915,3 +977,219 @@ xdr_buf_read_netobj(struct xdr_buf *buf, struct xdr_netobj *obj, int offset)
out:
return -1;
}
+
+/* Returns 0 on success, or else a negative error code. */
+static int
+xdr_xcode_array2(struct xdr_buf *buf, unsigned int base,
+ struct xdr_array2_desc *desc, int encode)
+{
+ char *elem = NULL, *c;
+ unsigned int copied = 0, todo, avail_here;
+ struct page **ppages = NULL;
+ int err;
+
+ if (encode) {
+ if (xdr_encode_word(buf, base, desc->array_len) != 0)
+ return -EINVAL;
+ } else {
+ if (xdr_decode_word(buf, base, &desc->array_len) != 0 ||
+ (unsigned long) base + 4 + desc->array_len *
+ desc->elem_size > buf->len)
+ return -EINVAL;
+ }
+ base += 4;
+
+ if (!desc->xcode)
+ return 0;
+
+ todo = desc->array_len * desc->elem_size;
+
+ /* process head */
+ if (todo && base < buf->head->iov_len) {
+ c = buf->head->iov_base + base;
+ avail_here = min_t(unsigned int, todo,
+ buf->head->iov_len - base);
+ todo -= avail_here;
+
+ while (avail_here >= desc->elem_size) {
+ err = desc->xcode(desc, c);
+ if (err)
+ goto out;
+ c += desc->elem_size;
+ avail_here -= desc->elem_size;
+ }
+ if (avail_here) {
+ if (!elem) {
+ elem = kmalloc(desc->elem_size, GFP_KERNEL);
+ err = -ENOMEM;
+ if (!elem)
+ goto out;
+ }
+ if (encode) {
+ err = desc->xcode(desc, elem);
+ if (err)
+ goto out;
+ memcpy(c, elem, avail_here);
+ } else
+ memcpy(elem, c, avail_here);
+ copied = avail_here;
+ }
+ base = buf->head->iov_len; /* align to start of pages */
+ }
+
+ /* process pages array */
+ base -= buf->head->iov_len;
+ if (todo && base < buf->page_len) {
+ unsigned int avail_page;
+
+ avail_here = min(todo, buf->page_len - base);
+ todo -= avail_here;
+
+ base += buf->page_base;
+ ppages = buf->pages + (base >> PAGE_CACHE_SHIFT);
+ base &= ~PAGE_CACHE_MASK;
+ avail_page = min_t(unsigned int, PAGE_CACHE_SIZE - base,
+ avail_here);
+ c = kmap(*ppages) + base;
+
+ while (avail_here) {
+ avail_here -= avail_page;
+ if (copied || avail_page < desc->elem_size) {
+ unsigned int l = min(avail_page,
+ desc->elem_size - copied);
+ if (!elem) {
+ elem = kmalloc(desc->elem_size,
+ GFP_KERNEL);
+ err = -ENOMEM;
+ if (!elem)
+ goto out;
+ }
+ if (encode) {
+ if (!copied) {
+ err = desc->xcode(desc, elem);
+ if (err)
+ goto out;
+ }
+ memcpy(c, elem + copied, l);
+ copied += l;
+ if (copied == desc->elem_size)
+ copied = 0;
+ } else {
+ memcpy(elem + copied, c, l);
+ copied += l;
+ if (copied == desc->elem_size) {
+ err = desc->xcode(desc, elem);
+ if (err)
+ goto out;
+ copied = 0;
+ }
+ }
+ avail_page -= l;
+ c += l;
+ }
+ while (avail_page >= desc->elem_size) {
+ err = desc->xcode(desc, c);
+ if (err)
+ goto out;
+ c += desc->elem_size;
+ avail_page -= desc->elem_size;
+ }
+ if (avail_page) {
+ unsigned int l = min(avail_page,
+ desc->elem_size - copied);
+ if (!elem) {
+ elem = kmalloc(desc->elem_size,
+ GFP_KERNEL);
+ err = -ENOMEM;
+ if (!elem)
+ goto out;
+ }
+ if (encode) {
+ if (!copied) {
+ err = desc->xcode(desc, elem);
+ if (err)
+ goto out;
+ }
+ memcpy(c, elem + copied, l);
+ copied += l;
+ if (copied == desc->elem_size)
+ copied = 0;
+ } else {
+ memcpy(elem + copied, c, l);
+ copied += l;
+ if (copied == desc->elem_size) {
+ err = desc->xcode(desc, elem);
+ if (err)
+ goto out;
+ copied = 0;
+ }
+ }
+ }
+ if (avail_here) {
+ kunmap(*ppages);
+ ppages++;
+ c = kmap(*ppages);
+ }
+
+ avail_page = min(avail_here,
+ (unsigned int) PAGE_CACHE_SIZE);
+ }
+ base = buf->page_len; /* align to start of tail */
+ }
+
+ /* process tail */
+ base -= buf->page_len;
+ if (todo) {
+ c = buf->tail->iov_base + base;
+ if (copied) {
+ unsigned int l = desc->elem_size - copied;
+
+ if (encode)
+ memcpy(c, elem + copied, l);
+ else {
+ memcpy(elem + copied, c, l);
+ err = desc->xcode(desc, elem);
+ if (err)
+ goto out;
+ }
+ todo -= l;
+ c += l;
+ }
+ while (todo) {
+ err = desc->xcode(desc, c);
+ if (err)
+ goto out;
+ c += desc->elem_size;
+ todo -= desc->elem_size;
+ }
+ }
+ err = 0;
+
+out:
+ if (elem)
+ kfree(elem);
+ if (ppages)
+ kunmap(*ppages);
+ return err;
+}
+
+int
+xdr_decode_array2(struct xdr_buf *buf, unsigned int base,
+ struct xdr_array2_desc *desc)
+{
+ if (base >= buf->len)
+ return -EINVAL;
+
+ return xdr_xcode_array2(buf, base, desc, 0);
+}
+
+int
+xdr_encode_array2(struct xdr_buf *buf, unsigned int base,
+ struct xdr_array2_desc *desc)
+{
+ if ((unsigned long) base + 4 + desc->array_len * desc->elem_size >
+ buf->head->iov_len + buf->page_len + buf->tail->iov_len)
+ return -EINVAL;
+
+ return xdr_xcode_array2(buf, base, desc, 1);
+}
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index c74a6bb9407..269f217918a 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -569,8 +569,11 @@ void xprt_connect(struct rpc_task *task)
if (xprt->sock != NULL)
schedule_delayed_work(&xprt->sock_connect,
RPC_REESTABLISH_TIMEOUT);
- else
+ else {
schedule_work(&xprt->sock_connect);
+ if (!RPC_IS_ASYNC(task))
+ flush_scheduled_work();
+ }
}
return;
out_write:
@@ -725,7 +728,8 @@ csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
goto no_checksum;
desc.csum = csum_partial(skb->data, desc.offset, skb->csum);
- xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_and_csum_bits);
+ if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_and_csum_bits) < 0)
+ return -1;
if (desc.offset != skb->len) {
unsigned int csum2;
csum2 = skb_checksum(skb, desc.offset, skb->len - desc.offset, 0);
@@ -737,7 +741,8 @@ csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
return -1;
return 0;
no_checksum:
- xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_bits);
+ if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_bits) < 0)
+ return -1;
if (desc.count)
return -1;
return 0;
@@ -821,10 +826,15 @@ tcp_copy_data(skb_reader_t *desc, void *p, size_t len)
{
if (len > desc->count)
len = desc->count;
- if (skb_copy_bits(desc->skb, desc->offset, p, len))
+ if (skb_copy_bits(desc->skb, desc->offset, p, len)) {
+ dprintk("RPC: failed to copy %zu bytes from skb. %zu bytes remain\n",
+ len, desc->count);
return 0;
+ }
desc->offset += len;
desc->count -= len;
+ dprintk("RPC: copied %zu bytes from skb. %zu bytes remain\n",
+ len, desc->count);
return len;
}
@@ -863,6 +873,8 @@ tcp_read_fraghdr(struct rpc_xprt *xprt, skb_reader_t *desc)
static void
tcp_check_recm(struct rpc_xprt *xprt)
{
+ dprintk("RPC: xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u, tcp_flags = %lx\n",
+ xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen, xprt->tcp_flags);
if (xprt->tcp_offset == xprt->tcp_reclen) {
xprt->tcp_flags |= XPRT_COPY_RECM;
xprt->tcp_offset = 0;
@@ -907,6 +919,7 @@ tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc)
struct rpc_rqst *req;
struct xdr_buf *rcvbuf;
size_t len;
+ ssize_t r;
/* Find and lock the request corresponding to this xid */
spin_lock(&xprt->sock_lock);
@@ -927,15 +940,40 @@ tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc)
len = xprt->tcp_reclen - xprt->tcp_offset;
memcpy(&my_desc, desc, sizeof(my_desc));
my_desc.count = len;
- xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
+ r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
&my_desc, tcp_copy_data);
- desc->count -= len;
- desc->offset += len;
+ desc->count -= r;
+ desc->offset += r;
} else
- xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
+ r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
desc, tcp_copy_data);
- xprt->tcp_copied += len;
- xprt->tcp_offset += len;
+
+ if (r > 0) {
+ xprt->tcp_copied += r;
+ xprt->tcp_offset += r;
+ }
+ if (r != len) {
+ /* Error when copying to the receive buffer,
+ * usually because we weren't able to allocate
+ * additional buffer pages. All we can do now
+ * is turn off XPRT_COPY_DATA, so the request
+ * will not receive any additional updates,
+ * and time out.
+ * Any remaining data from this record will
+ * be discarded.
+ */
+ xprt->tcp_flags &= ~XPRT_COPY_DATA;
+ dprintk("RPC: XID %08x truncated request\n",
+ ntohl(xprt->tcp_xid));
+ dprintk("RPC: xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u\n",
+ xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen);
+ goto out;
+ }
+
+ dprintk("RPC: XID %08x read %Zd bytes\n",
+ ntohl(xprt->tcp_xid), r);
+ dprintk("RPC: xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u\n",
+ xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen);
if (xprt->tcp_copied == req->rq_private_buf.buflen)
xprt->tcp_flags &= ~XPRT_COPY_DATA;
@@ -944,6 +982,7 @@ tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc)
xprt->tcp_flags &= ~XPRT_COPY_DATA;
}
+out:
if (!(xprt->tcp_flags & XPRT_COPY_DATA)) {
dprintk("RPC: %4d received reply complete\n",
req->rq_task->tk_pid);
@@ -967,6 +1006,7 @@ tcp_read_discard(struct rpc_xprt *xprt, skb_reader_t *desc)
desc->count -= len;
desc->offset += len;
xprt->tcp_offset += len;
+ dprintk("RPC: discarded %Zu bytes\n", len);
tcp_check_recm(xprt);
}
@@ -1064,8 +1104,7 @@ tcp_state_change(struct sock *sk)
case TCP_SYN_RECV:
break;
default:
- if (xprt_test_and_clear_connected(xprt))
- rpc_wake_up_status(&xprt->pending, -ENOTCONN);
+ xprt_disconnect(xprt);
break;
}
out:
@@ -1203,6 +1242,8 @@ xprt_transmit(struct rpc_task *task)
list_add_tail(&req->rq_list, &xprt->recv);
spin_unlock_bh(&xprt->sock_lock);
xprt_reset_majortimeo(req);
+ /* Turn off autodisconnect */
+ del_singleshot_timer_sync(&xprt->timer);
}
} else if (!req->rq_bytes_sent)
return;
@@ -1333,8 +1374,6 @@ xprt_reserve(struct rpc_task *task)
spin_lock(&xprt->xprt_lock);
do_xprt_reserve(task);
spin_unlock(&xprt->xprt_lock);
- if (task->tk_rqstp)
- del_timer_sync(&xprt->timer);
}
}
@@ -1649,6 +1688,10 @@ xprt_shutdown(struct rpc_xprt *xprt)
rpc_wake_up(&xprt->backlog);
wake_up(&xprt->cong_wait);
del_timer_sync(&xprt->timer);
+
+ /* synchronously wait for connect worker to finish */
+ cancel_delayed_work(&xprt->sock_connect);
+ flush_scheduled_work();
}
/*
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index c478fc8db77..c420eba4876 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -770,33 +770,12 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
err = path_lookup(sunaddr->sun_path, LOOKUP_PARENT, &nd);
if (err)
goto out_mknod_parent;
- /*
- * Yucky last component or no last component at all?
- * (foo/., foo/.., /////)
- */
- err = -EEXIST;
- if (nd.last_type != LAST_NORM)
- goto out_mknod;
- /*
- * Lock the directory.
- */
- down(&nd.dentry->d_inode->i_sem);
- /*
- * Do the final lookup.
- */
- dentry = lookup_hash(&nd.last, nd.dentry);
+
+ dentry = lookup_create(&nd, 0);
err = PTR_ERR(dentry);
if (IS_ERR(dentry))
goto out_mknod_unlock;
- err = -ENOENT;
- /*
- * Special case - lookup gave negative, but... we had foo/bar/
- * From the vfs_mknod() POV we just have a negative dentry -
- * all is fine. Let's be bastards - you had / on the end, you've
- * been asking for (non-existent) directory. -ENOENT for you.
- */
- if (nd.last.name[nd.last.len] && !dentry->d_inode)
- goto out_mknod_dput;
+
/*
* All right, let's create it.
*/
@@ -845,7 +824,6 @@ out_mknod_dput:
dput(dentry);
out_mknod_unlock:
up(&nd.dentry->d_inode->i_sem);
-out_mknod:
path_release(&nd);
out_mknod_parent:
if (err==-EEXIST)
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 2a24b243b84..04bec047fa9 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -29,6 +29,10 @@
* 2000-11-14 Henner Eisen Closing datalink from NETDEV_GOING_DOWN
* 2002-10-06 Arnaldo C. Melo Get rid of cli/sti, move proc stuff to
* x25_proc.c, using seq_file
+ * 2005-04-02 Shaun Pereira Selective sub address matching
+ * with call user data
+ * 2005-04-15 Shaun Pereira Fast select with no restriction on
+ * response
*/
#include <linux/config.h>
@@ -219,7 +223,8 @@ static void x25_insert_socket(struct sock *sk)
* Note: if a listening socket has cud set it must only get calls
* with matching cud.
*/
-static struct sock *x25_find_listener(struct x25_address *addr, struct x25_calluserdata *calluserdata)
+static struct sock *x25_find_listener(struct x25_address *addr,
+ struct sk_buff *skb)
{
struct sock *s;
struct sock *next_best;
@@ -230,22 +235,23 @@ static struct sock *x25_find_listener(struct x25_address *addr, struct x25_callu
sk_for_each(s, node, &x25_list)
if ((!strcmp(addr->x25_addr,
- x25_sk(s)->source_addr.x25_addr) ||
- !strcmp(addr->x25_addr,
- null_x25_address.x25_addr)) &&
- s->sk_state == TCP_LISTEN) {
-
+ x25_sk(s)->source_addr.x25_addr) ||
+ !strcmp(addr->x25_addr,
+ null_x25_address.x25_addr)) &&
+ s->sk_state == TCP_LISTEN) {
/*
* Found a listening socket, now check the incoming
* call user data vs this sockets call user data
*/
- if (x25_check_calluserdata(&x25_sk(s)->calluserdata, calluserdata)) {
- sock_hold(s);
- goto found;
- }
- if (x25_sk(s)->calluserdata.cudlength == 0) {
+ if(skb->len > 0 && x25_sk(s)->cudmatchlength > 0) {
+ if((memcmp(x25_sk(s)->calluserdata.cuddata,
+ skb->data,
+ x25_sk(s)->cudmatchlength)) == 0) {
+ sock_hold(s);
+ goto found;
+ }
+ } else
next_best = s;
- }
}
if (next_best) {
s = next_best;
@@ -497,6 +503,9 @@ static int x25_create(struct socket *sock, int protocol)
x25->t23 = sysctl_x25_clear_request_timeout;
x25->t2 = sysctl_x25_ack_holdback_timeout;
x25->state = X25_STATE_0;
+ x25->cudmatchlength = 0;
+ x25->accptapprv = X25_DENY_ACCPT_APPRV; /* normally no cud */
+ /* on call accept */
x25->facilities.winsize_in = X25_DEFAULT_WINDOW_SIZE;
x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE;
@@ -545,6 +554,8 @@ static struct sock *x25_make_new(struct sock *osk)
x25->t2 = ox25->t2;
x25->facilities = ox25->facilities;
x25->qbitincl = ox25->qbitincl;
+ x25->cudmatchlength = ox25->cudmatchlength;
+ x25->accptapprv = ox25->accptapprv;
x25_init_timers(sk);
out:
@@ -822,7 +833,6 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
struct x25_sock *makex25;
struct x25_address source_addr, dest_addr;
struct x25_facilities facilities;
- struct x25_calluserdata calluserdata;
int len, rc;
/*
@@ -845,19 +855,10 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
skb_pull(skb,len);
/*
- * Incoming Call User Data.
- */
- if (skb->len >= 0) {
- memcpy(calluserdata.cuddata, skb->data, skb->len);
- calluserdata.cudlength = skb->len;
- }
-
- skb_push(skb,len);
-
- /*
* Find a listener for the particular address/cud pair.
*/
- sk = x25_find_listener(&source_addr,&calluserdata);
+ sk = x25_find_listener(&source_addr,skb);
+ skb_push(skb,len);
/*
* We can't accept the Call Request.
@@ -900,11 +901,23 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
makex25->neighbour = nb;
makex25->facilities = facilities;
makex25->vc_facil_mask = x25_sk(sk)->vc_facil_mask;
- makex25->calluserdata = calluserdata;
-
- x25_write_internal(make, X25_CALL_ACCEPTED);
+ /* ensure no reverse facil on accept */
+ makex25->vc_facil_mask &= ~X25_MASK_REVERSE;
+ makex25->cudmatchlength = x25_sk(sk)->cudmatchlength;
+
+ /* Normally all calls are accepted immediatly */
+ if(makex25->accptapprv & X25_DENY_ACCPT_APPRV) {
+ x25_write_internal(make, X25_CALL_ACCEPTED);
+ makex25->state = X25_STATE_3;
+ }
- makex25->state = X25_STATE_3;
+ /*
+ * Incoming Call User Data.
+ */
+ if (skb->len >= 0) {
+ memcpy(makex25->calluserdata.cuddata, skb->data, skb->len);
+ makex25->calluserdata.cudlength = skb->len;
+ }
sk->sk_ack_backlog++;
@@ -1288,7 +1301,8 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
if (facilities.throughput < 0x03 ||
facilities.throughput > 0xDD)
break;
- if (facilities.reverse && facilities.reverse != 1)
+ if (facilities.reverse &&
+ (facilities.reverse | 0x81)!= 0x81)
break;
x25->facilities = facilities;
rc = 0;
@@ -1325,6 +1339,44 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
break;
}
+ case SIOCX25SCUDMATCHLEN: {
+ struct x25_subaddr sub_addr;
+ rc = -EINVAL;
+ if(sk->sk_state != TCP_CLOSE)
+ break;
+ rc = -EFAULT;
+ if (copy_from_user(&sub_addr, argp,
+ sizeof(sub_addr)))
+ break;
+ rc = -EINVAL;
+ if(sub_addr.cudmatchlength > X25_MAX_CUD_LEN)
+ break;
+ x25->cudmatchlength = sub_addr.cudmatchlength;
+ rc = 0;
+ break;
+ }
+
+ case SIOCX25CALLACCPTAPPRV: {
+ rc = -EINVAL;
+ if (sk->sk_state != TCP_CLOSE)
+ break;
+ x25->accptapprv = X25_ALLOW_ACCPT_APPRV;
+ rc = 0;
+ break;
+ }
+
+ case SIOCX25SENDCALLACCPT: {
+ rc = -EINVAL;
+ if (sk->sk_state != TCP_ESTABLISHED)
+ break;
+ if (x25->accptapprv) /* must call accptapprv above */
+ break;
+ x25_write_internal(sk, X25_CALL_ACCEPTED);
+ x25->state = X25_STATE_3;
+ rc = 0;
+ break;
+ }
+
default:
rc = dev_ioctl(cmd, argp);
break;
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c
index a21bdb95f9a..54278b962f4 100644
--- a/net/x25/x25_facilities.c
+++ b/net/x25/x25_facilities.c
@@ -17,6 +17,8 @@
* X.25 001 Split from x25_subr.c
* mar/20/00 Daniela Squassoni Disabling/enabling of facilities
* negotiation.
+ * apr/14/05 Shaun Pereira - Allow fast select with no restriction
+ * on response.
*/
#include <linux/kernel.h>
@@ -43,9 +45,31 @@ int x25_parse_facilities(struct sk_buff *skb,
case X25_FAC_CLASS_A:
switch (*p) {
case X25_FAC_REVERSE:
- facilities->reverse = p[1] & 0x01;
- *vc_fac_mask |= X25_MASK_REVERSE;
- break;
+ if((p[1] & 0x81) == 0x81) {
+ facilities->reverse = p[1] & 0x81;
+ *vc_fac_mask |= X25_MASK_REVERSE;
+ break;
+ }
+
+ if((p[1] & 0x01) == 0x01) {
+ facilities->reverse = p[1] & 0x01;
+ *vc_fac_mask |= X25_MASK_REVERSE;
+ break;
+ }
+
+ if((p[1] & 0x80) == 0x80) {
+ facilities->reverse = p[1] & 0x80;
+ *vc_fac_mask |= X25_MASK_REVERSE;
+ break;
+ }
+
+ if(p[1] == 0x00) {
+ facilities->reverse
+ = X25_DEFAULT_REVERSE;
+ *vc_fac_mask |= X25_MASK_REVERSE;
+ break;
+ }
+
case X25_FAC_THROUGHPUT:
facilities->throughput = p[1];
*vc_fac_mask |= X25_MASK_THROUGHPUT;
@@ -122,7 +146,7 @@ int x25_create_facilities(unsigned char *buffer,
if (facilities->reverse && (facil_mask & X25_MASK_REVERSE)) {
*p++ = X25_FAC_REVERSE;
- *p++ = !!facilities->reverse;
+ *p++ = facilities->reverse;
}
if (facilities->throughput && (facil_mask & X25_MASK_THROUGHPUT)) {
@@ -171,7 +195,7 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk,
/*
* They want reverse charging, we won't accept it.
*/
- if (theirs.reverse && ours->reverse) {
+ if ((theirs.reverse & 0x01 ) && (ours->reverse & 0x01)) {
SOCK_DEBUG(sk, "X.25: rejecting reverse charging request");
return -1;
}
diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c
index 183fea3bba6..7fd872ad0c2 100644
--- a/net/x25/x25_subr.c
+++ b/net/x25/x25_subr.c
@@ -19,6 +19,8 @@
* mar/20/00 Daniela Squassoni Disabling/enabling of facilities
* negotiation.
* jun/24/01 Arnaldo C. Melo use skb_queue_purge, cleanups
+ * apr/04/15 Shaun Pereira Fast select with no
+ * restriction on response.
*/
#include <linux/kernel.h>
@@ -127,8 +129,12 @@ void x25_write_internal(struct sock *sk, int frametype)
len += 1 + X25_ADDR_LEN + X25_MAX_FAC_LEN +
X25_MAX_CUD_LEN;
break;
- case X25_CALL_ACCEPTED:
- len += 1 + X25_MAX_FAC_LEN + X25_MAX_CUD_LEN;
+ case X25_CALL_ACCEPTED: /* fast sel with no restr on resp */
+ if(x25->facilities.reverse & 0x80) {
+ len += 1 + X25_MAX_FAC_LEN + X25_MAX_CUD_LEN;
+ } else {
+ len += 1 + X25_MAX_FAC_LEN;
+ }
break;
case X25_CLEAR_REQUEST:
case X25_RESET_REQUEST:
@@ -203,9 +209,16 @@ void x25_write_internal(struct sock *sk, int frametype)
x25->vc_facil_mask);
dptr = skb_put(skb, len);
memcpy(dptr, facilities, len);
- dptr = skb_put(skb, x25->calluserdata.cudlength);
- memcpy(dptr, x25->calluserdata.cuddata,
- x25->calluserdata.cudlength);
+
+ /* fast select with no restriction on response
+ allows call user data. Userland must
+ ensure it is ours and not theirs */
+ if(x25->facilities.reverse & 0x80) {
+ dptr = skb_put(skb,
+ x25->calluserdata.cudlength);
+ memcpy(dptr, x25->calluserdata.cuddata,
+ x25->calluserdata.cudlength);
+ }
x25->calluserdata.cudlength = 0;
break;
@@ -354,21 +367,3 @@ void x25_check_rbuf(struct sock *sk)
}
}
-/*
- * Compare 2 calluserdata structures, used to find correct listening sockets
- * when call user data is used.
- */
-int x25_check_calluserdata(struct x25_calluserdata *ours, struct x25_calluserdata *theirs)
-{
- int i;
- if (ours->cudlength != theirs->cudlength)
- return 0;
-
- for (i=0;i<ours->cudlength;i++) {
- if (ours->cuddata[i] != theirs->cuddata[i]) {
- return 0;
- }
- }
- return 1;
-}
-
diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c
index 080aae243ce..2f4531fcaca 100644
--- a/net/xfrm/xfrm_algo.c
+++ b/net/xfrm/xfrm_algo.c
@@ -698,7 +698,7 @@ int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer)
return -ENOMEM;
if (skb1->sk)
- skb_set_owner_w(skb, skb1->sk);
+ skb_set_owner_w(skb2, skb1->sk);
/* Looking around. Are we still alive?
* OK, link new skb, drop old one */
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 55ed979db14..d65ed8684fc 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -118,7 +118,6 @@ retry:
xfrm_policy_put_afinfo(afinfo);
return type;
}
-EXPORT_SYMBOL(xfrm_get_type);
int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl,
unsigned short family)
@@ -216,8 +215,8 @@ out:
expired:
read_unlock(&xp->lock);
- km_policy_expired(xp, dir, 1);
- xfrm_policy_delete(xp, dir);
+ if (!xfrm_policy_delete(xp, dir))
+ km_policy_expired(xp, dir, 1);
xfrm_pol_put(xp);
}
@@ -555,7 +554,7 @@ static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol,
return NULL;
}
-void xfrm_policy_delete(struct xfrm_policy *pol, int dir)
+int xfrm_policy_delete(struct xfrm_policy *pol, int dir)
{
write_lock_bh(&xfrm_policy_lock);
pol = __xfrm_policy_unlink(pol, dir);
@@ -564,7 +563,9 @@ void xfrm_policy_delete(struct xfrm_policy *pol, int dir)
if (dir < XFRM_POLICY_MAX)
atomic_inc(&flow_cache_genid);
xfrm_policy_kill(pol);
+ return 0;
}
+ return -ENOENT;
}
int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol)
@@ -1136,7 +1137,7 @@ int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family)
struct xfrm_dst *last;
u32 mtu;
- if (!dst_check(dst->path, 0) ||
+ if (!dst_check(dst->path, ((struct xfrm_dst *)dst)->path_cookie) ||
(dst->dev && !netif_running(dst->dev)))
return 0;
@@ -1156,7 +1157,7 @@ int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family)
xdst->child_mtu_cached = mtu;
}
- if (!dst_check(xdst->route, 0))
+ if (!dst_check(xdst->route, xdst->route_cookie))
return 0;
mtu = dst_mtu(xdst->route);
if (xdst->route_mtu_cached != mtu) {
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index d11747c2a76..9d206c282cf 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -50,7 +50,7 @@ static DEFINE_SPINLOCK(xfrm_state_gc_lock);
static int xfrm_state_gc_flush_bundles;
-static void __xfrm_state_delete(struct xfrm_state *x);
+static int __xfrm_state_delete(struct xfrm_state *x);
static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family);
static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
@@ -154,6 +154,7 @@ static void xfrm_timer_handler(unsigned long data)
next = tmo;
}
+ x->km.dying = warn;
if (warn)
km_state_expired(x, 0);
resched:
@@ -169,9 +170,8 @@ expired:
next = 2;
goto resched;
}
- if (x->id.spi != 0)
+ if (!__xfrm_state_delete(x) && x->id.spi)
km_state_expired(x, 1);
- __xfrm_state_delete(x);
out:
spin_unlock(&x->lock);
@@ -215,8 +215,10 @@ void __xfrm_state_destroy(struct xfrm_state *x)
}
EXPORT_SYMBOL(__xfrm_state_destroy);
-static void __xfrm_state_delete(struct xfrm_state *x)
+static int __xfrm_state_delete(struct xfrm_state *x)
{
+ int err = -ESRCH;
+
if (x->km.state != XFRM_STATE_DEAD) {
x->km.state = XFRM_STATE_DEAD;
spin_lock(&xfrm_state_lock);
@@ -245,14 +247,21 @@ static void __xfrm_state_delete(struct xfrm_state *x)
* is what we are dropping here.
*/
atomic_dec(&x->refcnt);
+ err = 0;
}
+
+ return err;
}
-void xfrm_state_delete(struct xfrm_state *x)
+int xfrm_state_delete(struct xfrm_state *x)
{
+ int err;
+
spin_lock_bh(&x->lock);
- __xfrm_state_delete(x);
+ err = __xfrm_state_delete(x);
spin_unlock_bh(&x->lock);
+
+ return err;
}
EXPORT_SYMBOL(xfrm_state_delete);
@@ -557,16 +566,18 @@ int xfrm_state_check_expire(struct xfrm_state *x)
if (x->curlft.bytes >= x->lft.hard_byte_limit ||
x->curlft.packets >= x->lft.hard_packet_limit) {
- km_state_expired(x, 1);
- if (!mod_timer(&x->timer, jiffies + XFRM_ACQ_EXPIRES*HZ))
+ x->km.state = XFRM_STATE_EXPIRED;
+ if (!mod_timer(&x->timer, jiffies))
xfrm_state_hold(x);
return -EINVAL;
}
if (!x->km.dying &&
(x->curlft.bytes >= x->lft.soft_byte_limit ||
- x->curlft.packets >= x->lft.soft_packet_limit))
+ x->curlft.packets >= x->lft.soft_packet_limit)) {
+ x->km.dying = 1;
km_state_expired(x, 0);
+ }
return 0;
}
EXPORT_SYMBOL(xfrm_state_check_expire);
@@ -796,34 +807,56 @@ EXPORT_SYMBOL(xfrm_replay_advance);
static struct list_head xfrm_km_list = LIST_HEAD_INIT(xfrm_km_list);
static DEFINE_RWLOCK(xfrm_km_lock);
-static void km_state_expired(struct xfrm_state *x, int hard)
+void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
{
struct xfrm_mgr *km;
- if (hard)
- x->km.state = XFRM_STATE_EXPIRED;
- else
- x->km.dying = 1;
+ read_lock(&xfrm_km_lock);
+ list_for_each_entry(km, &xfrm_km_list, list)
+ if (km->notify_policy)
+ km->notify_policy(xp, dir, c);
+ read_unlock(&xfrm_km_lock);
+}
+void km_state_notify(struct xfrm_state *x, struct km_event *c)
+{
+ struct xfrm_mgr *km;
read_lock(&xfrm_km_lock);
list_for_each_entry(km, &xfrm_km_list, list)
- km->notify(x, hard);
+ if (km->notify)
+ km->notify(x, c);
read_unlock(&xfrm_km_lock);
+}
+
+EXPORT_SYMBOL(km_policy_notify);
+EXPORT_SYMBOL(km_state_notify);
+
+static void km_state_expired(struct xfrm_state *x, int hard)
+{
+ struct km_event c;
+
+ c.data.hard = hard;
+ c.event = XFRM_MSG_EXPIRE;
+ km_state_notify(x, &c);
if (hard)
wake_up(&km_waitq);
}
+/*
+ * We send to all registered managers regardless of failure
+ * We are happy with one success
+*/
static int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol)
{
- int err = -EINVAL;
+ int err = -EINVAL, acqret;
struct xfrm_mgr *km;
read_lock(&xfrm_km_lock);
list_for_each_entry(km, &xfrm_km_list, list) {
- err = km->acquire(x, t, pol, XFRM_POLICY_OUT);
- if (!err)
- break;
+ acqret = km->acquire(x, t, pol, XFRM_POLICY_OUT);
+ if (!acqret)
+ err = acqret;
}
read_unlock(&xfrm_km_lock);
return err;
@@ -848,13 +881,11 @@ EXPORT_SYMBOL(km_new_mapping);
void km_policy_expired(struct xfrm_policy *pol, int dir, int hard)
{
- struct xfrm_mgr *km;
+ struct km_event c;
- read_lock(&xfrm_km_lock);
- list_for_each_entry(km, &xfrm_km_list, list)
- if (km->notify_policy)
- km->notify_policy(pol, dir, hard);
- read_unlock(&xfrm_km_lock);
+ c.data.hard = hard;
+ c.event = XFRM_MSG_POLEXPIRE;
+ km_policy_notify(pol, dir, &c);
if (hard)
wake_up(&km_waitq);
@@ -1024,6 +1055,43 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu)
}
EXPORT_SYMBOL(xfrm_state_mtu);
+
+int xfrm_init_state(struct xfrm_state *x)
+{
+ struct xfrm_state_afinfo *afinfo;
+ int family = x->props.family;
+ int err;
+
+ err = -EAFNOSUPPORT;
+ afinfo = xfrm_state_get_afinfo(family);
+ if (!afinfo)
+ goto error;
+
+ err = 0;
+ if (afinfo->init_flags)
+ err = afinfo->init_flags(x);
+
+ xfrm_state_put_afinfo(afinfo);
+
+ if (err)
+ goto error;
+
+ err = -EPROTONOSUPPORT;
+ x->type = xfrm_get_type(x->id.proto, family);
+ if (x->type == NULL)
+ goto error;
+
+ err = x->type->init_state(x);
+ if (err)
+ goto error;
+
+ x->km.state = XFRM_STATE_VALID;
+
+error:
+ return err;
+}
+
+EXPORT_SYMBOL(xfrm_init_state);
void __init xfrm_state_init(void)
{
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 5ddda2c98af..ecade4893a1 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -34,14 +34,21 @@ static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type)
{
struct rtattr *rt = xfrma[type - 1];
struct xfrm_algo *algp;
+ int len;
if (!rt)
return 0;
- if ((rt->rta_len - sizeof(*rt)) < sizeof(*algp))
+ len = (rt->rta_len - sizeof(*rt)) - sizeof(*algp);
+ if (len < 0)
return -EINVAL;
algp = RTA_DATA(rt);
+
+ len -= (algp->alg_key_len + 7U) / 8;
+ if (len < 0)
+ return -EINVAL;
+
switch (type) {
case XFRMA_ALG_AUTH:
if (!algp->alg_key_len &&
@@ -162,6 +169,7 @@ static int attach_one_algo(struct xfrm_algo **algpp, u8 *props,
struct rtattr *rta = u_arg;
struct xfrm_algo *p, *ualg;
struct xfrm_algo_desc *algo;
+ int len;
if (!rta)
return 0;
@@ -173,11 +181,12 @@ static int attach_one_algo(struct xfrm_algo **algpp, u8 *props,
return -ENOSYS;
*props = algo->desc.sadb_alg_id;
- p = kmalloc(sizeof(*ualg) + ualg->alg_key_len, GFP_KERNEL);
+ len = sizeof(*ualg) + (ualg->alg_key_len + 7U) / 8;
+ p = kmalloc(len, GFP_KERNEL);
if (!p)
return -ENOMEM;
- memcpy(p, ualg, sizeof(*ualg) + ualg->alg_key_len);
+ memcpy(p, ualg, len);
*algpp = p;
return 0;
}
@@ -240,17 +249,10 @@ static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p,
if ((err = attach_encap_tmpl(&x->encap, xfrma[XFRMA_ENCAP-1])))
goto error;
- err = -ENOENT;
- x->type = xfrm_get_type(x->id.proto, x->props.family);
- if (x->type == NULL)
- goto error;
-
- err = x->type->init_state(x, NULL);
+ err = xfrm_init_state(x);
if (err)
goto error;
- x->curlft.add_time = (unsigned long) xtime.tv_sec;
- x->km.state = XFRM_STATE_VALID;
x->km.seq = p->seq;
return x;
@@ -268,6 +270,7 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
struct xfrm_usersa_info *p = NLMSG_DATA(nlh);
struct xfrm_state *x;
int err;
+ struct km_event c;
err = verify_newsa_info(p, (struct rtattr **) xfrma);
if (err)
@@ -277,6 +280,7 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
if (!x)
return err;
+ xfrm_state_hold(x);
if (nlh->nlmsg_type == XFRM_MSG_NEWSA)
err = xfrm_state_add(x);
else
@@ -285,14 +289,24 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
if (err < 0) {
x->km.state = XFRM_STATE_DEAD;
xfrm_state_put(x);
+ goto out;
}
+ c.seq = nlh->nlmsg_seq;
+ c.pid = nlh->nlmsg_pid;
+ c.event = nlh->nlmsg_type;
+
+ km_state_notify(x, &c);
+out:
+ xfrm_state_put(x);
return err;
}
static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
{
struct xfrm_state *x;
+ int err;
+ struct km_event c;
struct xfrm_usersa_id *p = NLMSG_DATA(nlh);
x = xfrm_state_lookup(&p->daddr, p->spi, p->proto, p->family);
@@ -304,10 +318,19 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
return -EPERM;
}
- xfrm_state_delete(x);
+ err = xfrm_state_delete(x);
+ if (err < 0) {
+ xfrm_state_put(x);
+ return err;
+ }
+
+ c.seq = nlh->nlmsg_seq;
+ c.pid = nlh->nlmsg_pid;
+ c.event = nlh->nlmsg_type;
+ km_state_notify(x, &c);
xfrm_state_put(x);
- return 0;
+ return err;
}
static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)
@@ -672,6 +695,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
{
struct xfrm_userpolicy_info *p = NLMSG_DATA(nlh);
struct xfrm_policy *xp;
+ struct km_event c;
int err;
int excl;
@@ -683,6 +707,10 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
if (!xp)
return err;
+ /* shouldnt excl be based on nlh flags??
+ * Aha! this is anti-netlink really i.e more pfkey derived
+ * in netlink excl is a flag and you wouldnt need
+ * a type XFRM_MSG_UPDPOLICY - JHS */
excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY;
err = xfrm_policy_insert(p->dir, xp, excl);
if (err) {
@@ -690,6 +718,11 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
return err;
}
+ c.event = nlh->nlmsg_type;
+ c.seq = nlh->nlmsg_seq;
+ c.pid = nlh->nlmsg_pid;
+ km_policy_notify(xp, p->dir, &c);
+
xfrm_pol_put(xp);
return 0;
@@ -807,6 +840,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
struct xfrm_policy *xp;
struct xfrm_userpolicy_id *p;
int err;
+ struct km_event c;
int delete;
p = NLMSG_DATA(nlh);
@@ -834,6 +868,12 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
NETLINK_CB(skb).pid,
MSG_DONTWAIT);
}
+ } else {
+ c.data.byid = p->index;
+ c.event = nlh->nlmsg_type;
+ c.seq = nlh->nlmsg_seq;
+ c.pid = nlh->nlmsg_pid;
+ km_policy_notify(xp, p->dir, &c);
}
xfrm_pol_put(xp);
@@ -843,15 +883,28 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
{
+ struct km_event c;
struct xfrm_usersa_flush *p = NLMSG_DATA(nlh);
xfrm_state_flush(p->proto);
+ c.data.proto = p->proto;
+ c.event = nlh->nlmsg_type;
+ c.seq = nlh->nlmsg_seq;
+ c.pid = nlh->nlmsg_pid;
+ km_state_notify(NULL, &c);
+
return 0;
}
static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
{
+ struct km_event c;
+
xfrm_policy_flush();
+ c.event = nlh->nlmsg_type;
+ c.seq = nlh->nlmsg_seq;
+ c.pid = nlh->nlmsg_pid;
+ km_policy_notify(NULL, 0, &c);
return 0;
}
@@ -1060,15 +1113,16 @@ nlmsg_failure:
return -1;
}
-static int xfrm_send_state_notify(struct xfrm_state *x, int hard)
+static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c)
{
struct sk_buff *skb;
+ int len = NLMSG_LENGTH(sizeof(struct xfrm_user_expire));
- skb = alloc_skb(sizeof(struct xfrm_user_expire) + 16, GFP_ATOMIC);
+ skb = alloc_skb(len, GFP_ATOMIC);
if (skb == NULL)
return -ENOMEM;
- if (build_expire(skb, x, hard) < 0)
+ if (build_expire(skb, x, c->data.hard) < 0)
BUG();
NETLINK_CB(skb).dst_groups = XFRMGRP_EXPIRE;
@@ -1076,6 +1130,131 @@ static int xfrm_send_state_notify(struct xfrm_state *x, int hard)
return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC);
}
+static int xfrm_notify_sa_flush(struct km_event *c)
+{
+ struct xfrm_usersa_flush *p;
+ struct nlmsghdr *nlh;
+ struct sk_buff *skb;
+ unsigned char *b;
+ int len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_flush));
+
+ skb = alloc_skb(len, GFP_ATOMIC);
+ if (skb == NULL)
+ return -ENOMEM;
+ b = skb->tail;
+
+ nlh = NLMSG_PUT(skb, c->pid, c->seq,
+ XFRM_MSG_FLUSHSA, sizeof(*p));
+ nlh->nlmsg_flags = 0;
+
+ p = NLMSG_DATA(nlh);
+ p->proto = c->data.proto;
+
+ nlh->nlmsg_len = skb->tail - b;
+
+ return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_SA, GFP_ATOMIC);
+
+nlmsg_failure:
+ kfree_skb(skb);
+ return -1;
+}
+
+static int inline xfrm_sa_len(struct xfrm_state *x)
+{
+ int l = 0;
+ if (x->aalg)
+ l += RTA_SPACE(sizeof(*x->aalg) + (x->aalg->alg_key_len+7)/8);
+ if (x->ealg)
+ l += RTA_SPACE(sizeof(*x->ealg) + (x->ealg->alg_key_len+7)/8);
+ if (x->calg)
+ l += RTA_SPACE(sizeof(*x->calg));
+ if (x->encap)
+ l += RTA_SPACE(sizeof(*x->encap));
+
+ return l;
+}
+
+static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c)
+{
+ struct xfrm_usersa_info *p;
+ struct xfrm_usersa_id *id;
+ struct nlmsghdr *nlh;
+ struct sk_buff *skb;
+ unsigned char *b;
+ int len = xfrm_sa_len(x);
+ int headlen;
+
+ headlen = sizeof(*p);
+ if (c->event == XFRM_MSG_DELSA) {
+ len += RTA_SPACE(headlen);
+ headlen = sizeof(*id);
+ }
+ len += NLMSG_SPACE(headlen);
+
+ skb = alloc_skb(len, GFP_ATOMIC);
+ if (skb == NULL)
+ return -ENOMEM;
+ b = skb->tail;
+
+ nlh = NLMSG_PUT(skb, c->pid, c->seq, c->event, headlen);
+ nlh->nlmsg_flags = 0;
+
+ p = NLMSG_DATA(nlh);
+ if (c->event == XFRM_MSG_DELSA) {
+ id = NLMSG_DATA(nlh);
+ memcpy(&id->daddr, &x->id.daddr, sizeof(id->daddr));
+ id->spi = x->id.spi;
+ id->family = x->props.family;
+ id->proto = x->id.proto;
+
+ p = RTA_DATA(__RTA_PUT(skb, XFRMA_SA, sizeof(*p)));
+ }
+
+ copy_to_user_state(x, p);
+
+ if (x->aalg)
+ RTA_PUT(skb, XFRMA_ALG_AUTH,
+ sizeof(*(x->aalg))+(x->aalg->alg_key_len+7)/8, x->aalg);
+ if (x->ealg)
+ RTA_PUT(skb, XFRMA_ALG_CRYPT,
+ sizeof(*(x->ealg))+(x->ealg->alg_key_len+7)/8, x->ealg);
+ if (x->calg)
+ RTA_PUT(skb, XFRMA_ALG_COMP, sizeof(*(x->calg)), x->calg);
+
+ if (x->encap)
+ RTA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap);
+
+ nlh->nlmsg_len = skb->tail - b;
+
+ return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_SA, GFP_ATOMIC);
+
+nlmsg_failure:
+rtattr_failure:
+ kfree_skb(skb);
+ return -1;
+}
+
+static int xfrm_send_state_notify(struct xfrm_state *x, struct km_event *c)
+{
+
+ switch (c->event) {
+ case XFRM_MSG_EXPIRE:
+ return xfrm_exp_state_notify(x, c);
+ case XFRM_MSG_DELSA:
+ case XFRM_MSG_UPDSA:
+ case XFRM_MSG_NEWSA:
+ return xfrm_notify_sa(x, c);
+ case XFRM_MSG_FLUSHSA:
+ return xfrm_notify_sa_flush(c);
+ default:
+ printk("xfrm_user: Unknown SA event %d\n", c->event);
+ break;
+ }
+
+ return 0;
+
+}
+
static int build_acquire(struct sk_buff *skb, struct xfrm_state *x,
struct xfrm_tmpl *xt, struct xfrm_policy *xp,
int dir)
@@ -1209,7 +1388,7 @@ nlmsg_failure:
return -1;
}
-static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, int hard)
+static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
{
struct sk_buff *skb;
size_t len;
@@ -1220,7 +1399,7 @@ static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, int hard)
if (skb == NULL)
return -ENOMEM;
- if (build_polexpire(skb, xp, dir, hard) < 0)
+ if (build_polexpire(skb, xp, dir, c->data.hard) < 0)
BUG();
NETLINK_CB(skb).dst_groups = XFRMGRP_EXPIRE;
@@ -1228,6 +1407,103 @@ static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, int hard)
return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC);
}
+static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c)
+{
+ struct xfrm_userpolicy_info *p;
+ struct xfrm_userpolicy_id *id;
+ struct nlmsghdr *nlh;
+ struct sk_buff *skb;
+ unsigned char *b;
+ int len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
+ int headlen;
+
+ headlen = sizeof(*p);
+ if (c->event == XFRM_MSG_DELPOLICY) {
+ len += RTA_SPACE(headlen);
+ headlen = sizeof(*id);
+ }
+ len += NLMSG_SPACE(headlen);
+
+ skb = alloc_skb(len, GFP_ATOMIC);
+ if (skb == NULL)
+ return -ENOMEM;
+ b = skb->tail;
+
+ nlh = NLMSG_PUT(skb, c->pid, c->seq, c->event, headlen);
+
+ p = NLMSG_DATA(nlh);
+ if (c->event == XFRM_MSG_DELPOLICY) {
+ id = NLMSG_DATA(nlh);
+ memset(id, 0, sizeof(*id));
+ id->dir = dir;
+ if (c->data.byid)
+ id->index = xp->index;
+ else
+ memcpy(&id->sel, &xp->selector, sizeof(id->sel));
+
+ p = RTA_DATA(__RTA_PUT(skb, XFRMA_POLICY, sizeof(*p)));
+ }
+
+ nlh->nlmsg_flags = 0;
+
+ copy_to_user_policy(xp, p, dir);
+ if (copy_to_user_tmpl(xp, skb) < 0)
+ goto nlmsg_failure;
+
+ nlh->nlmsg_len = skb->tail - b;
+
+ return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_POLICY, GFP_ATOMIC);
+
+nlmsg_failure:
+rtattr_failure:
+ kfree_skb(skb);
+ return -1;
+}
+
+static int xfrm_notify_policy_flush(struct km_event *c)
+{
+ struct nlmsghdr *nlh;
+ struct sk_buff *skb;
+ unsigned char *b;
+ int len = NLMSG_LENGTH(0);
+
+ skb = alloc_skb(len, GFP_ATOMIC);
+ if (skb == NULL)
+ return -ENOMEM;
+ b = skb->tail;
+
+
+ nlh = NLMSG_PUT(skb, c->pid, c->seq, XFRM_MSG_FLUSHPOLICY, 0);
+
+ nlh->nlmsg_len = skb->tail - b;
+
+ return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_POLICY, GFP_ATOMIC);
+
+nlmsg_failure:
+ kfree_skb(skb);
+ return -1;
+}
+
+static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
+{
+
+ switch (c->event) {
+ case XFRM_MSG_NEWPOLICY:
+ case XFRM_MSG_UPDPOLICY:
+ case XFRM_MSG_DELPOLICY:
+ return xfrm_notify_policy(xp, dir, c);
+ case XFRM_MSG_FLUSHPOLICY:
+ return xfrm_notify_policy_flush(c);
+ case XFRM_MSG_POLEXPIRE:
+ return xfrm_exp_policy_notify(xp, dir, c);
+ default:
+ printk("xfrm_user: Unknown Policy event %d\n", c->event);
+ }
+
+ return 0;
+
+}
+
static struct xfrm_mgr netlink_mgr = {
.id = "netlink",
.notify = xfrm_send_state_notify,
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 352d531ee3c..76ba6be3dfc 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -176,10 +176,10 @@ endif
define rule_cc_o_c
$(if $($(quiet)cmd_checksrc),echo ' $($(quiet)cmd_checksrc)';) \
$(cmd_checksrc) \
- $(if $($(quiet)cmd_cc_o_c),echo ' $($(quiet)cmd_cc_o_c)';) \
+ $(if $($(quiet)cmd_cc_o_c),echo ' $(subst ','\'',$($(quiet)cmd_cc_o_c))';) \
$(cmd_cc_o_c); \
$(cmd_modversions) \
- scripts/basic/fixdep $(depfile) $@ '$(cmd_cc_o_c)' > $(@D)/.$(@F).tmp; \
+ scripts/basic/fixdep $(depfile) $@ '$(subst ','\'',$(cmd_cc_o_c))' > $(@D)/.$(@F).tmp; \
rm -f $(depfile); \
mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd
endef
diff --git a/scripts/basic/docproc.c b/scripts/basic/docproc.c
index 8ca7ecdb68f..cb02baa6325 100644
--- a/scripts/basic/docproc.c
+++ b/scripts/basic/docproc.c
@@ -52,7 +52,7 @@ FILEONLY *internalfunctions;
FILEONLY *externalfunctions;
FILEONLY *symbolsonly;
-typedef void FILELINE(char * file, signed char * line);
+typedef void FILELINE(char * file, char * line);
FILELINE * singlefunctions;
FILELINE * entity_system;
@@ -148,9 +148,9 @@ struct symfile * filename_exist(char * filename)
* Files are separated by tabs.
*/
void adddep(char * file) { printf("\t%s", file); }
-void adddep2(char * file, signed char * line) { line = line; adddep(file); }
+void adddep2(char * file, char * line) { line = line; adddep(file); }
void noaction(char * line) { line = line; }
-void noaction2(char * file, signed char * line) { file = file; line = line; }
+void noaction2(char * file, char * line) { file = file; line = line; }
/* Echo the line without further action */
void printline(char * line) { printf("%s", line); }
@@ -179,8 +179,8 @@ void find_export_symbols(char * filename)
perror(real_filename);
}
while(fgets(line, MAXLINESZ, fp)) {
- signed char *p;
- signed char *e;
+ char *p;
+ char *e;
if (((p = strstr(line, "EXPORT_SYMBOL_GPL")) != 0) ||
((p = strstr(line, "EXPORT_SYMBOL")) != 0)) {
/* Skip EXPORT_SYMBOL{_GPL} */
@@ -253,7 +253,7 @@ void extfunc(char * filename) { docfunctions(filename, FUNCTION); }
* Call kernel-doc with the following parameters:
* kernel-doc -docbook -function function1 [-function function2]
*/
-void singfunc(char * filename, signed char * line)
+void singfunc(char * filename, char * line)
{
char *vec[200]; /* Enough for specific functions */
int i, idx = 0;
@@ -290,7 +290,7 @@ void singfunc(char * filename, signed char * line)
void parse_file(FILE *infile)
{
char line[MAXLINESZ];
- signed char * s;
+ char * s;
while(fgets(line, MAXLINESZ, infile)) {
if (line[0] == '!') {
s = line + 2;
diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c
index 7f42c5d8a5a..0b61bea869f 100644
--- a/scripts/basic/fixdep.c
+++ b/scripts/basic/fixdep.c
@@ -212,23 +212,23 @@ void use_config(char *m, int slen)
if (*p == '_')
*p = '/';
else
- *p = tolower((unsigned char)*p);
+ *p = tolower((int)*p);
}
printf(" $(wildcard include/config/%s.h) \\\n", s);
}
-void parse_config_file(signed char *map, size_t len)
+void parse_config_file(char *map, size_t len)
{
int *end = (int *) (map + len);
/* start at +1, so that p can never be < map */
int *m = (int *) map + 1;
- signed char *p, *q;
+ char *p, *q;
for (; m < end; m++) {
- if (*m == INT_CONF) { p = (signed char *) m ; goto conf; }
- if (*m == INT_ONFI) { p = (signed char *) m-1; goto conf; }
- if (*m == INT_NFIG) { p = (signed char *) m-2; goto conf; }
- if (*m == INT_FIG_) { p = (signed char *) m-3; goto conf; }
+ if (*m == INT_CONF) { p = (char *) m ; goto conf; }
+ if (*m == INT_ONFI) { p = (char *) m-1; goto conf; }
+ if (*m == INT_NFIG) { p = (char *) m-2; goto conf; }
+ if (*m == INT_FIG_) { p = (char *) m-3; goto conf; }
continue;
conf:
if (p > map + len - 7)
@@ -291,9 +291,9 @@ void do_config_file(char *filename)
void parse_dep_file(void *map, size_t len)
{
- signed char *m = map;
- signed char *end = m + len;
- signed char *p;
+ char *m = map;
+ char *end = m + len;
+ char *p;
char s[PATH_MAX];
p = strchr(m, ':');
diff --git a/scripts/basic/split-include.c b/scripts/basic/split-include.c
index 60fc4d8ebaa..459c45276cb 100644
--- a/scripts/basic/split-include.c
+++ b/scripts/basic/split-include.c
@@ -104,7 +104,7 @@ int main(int argc, const char * argv [])
/* Read config lines. */
while (fgets(line, buffer_size, fp_config))
{
- const signed char * str_config;
+ const char * str_config;
int is_same;
int itarget;
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 70e7264c694..bc20cab9d0d 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -31,14 +31,14 @@ char *defconfig_file;
static int indent = 1;
static int valid_stdin = 1;
static int conf_cnt;
-static signed char line[128];
+static char line[128];
static struct menu *rootEntry;
static char nohelp_text[] = N_("Sorry, no help available for this option yet.\n");
-static void strip(signed char *str)
+static void strip(char *str)
{
- signed char *p = str;
+ char *p = str;
int l;
while ((isspace(*p)))
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 2755c459d78..02f670cc6bb 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -27,10 +27,10 @@ const char *conf_confnames[] = {
NULL,
};
-static char *conf_expand_value(const signed char *in)
+static char *conf_expand_value(const char *in)
{
struct symbol *sym;
- const signed char *src;
+ const char *src;
static char res_value[SYMBOL_MAXLENGTH];
char *dst, name[SYMBOL_MAXLENGTH];
diff --git a/scripts/kconfig/gconf.glade b/scripts/kconfig/gconf.glade
index 1e1736d81ee..ace4706ab25 100644
--- a/scripts/kconfig/gconf.glade
+++ b/scripts/kconfig/gconf.glade
@@ -432,8 +432,8 @@
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
- <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
- <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
@@ -466,8 +466,8 @@
<child>
<widget class="GtkScrolledWindow" id="scrolledwindow2">
<property name="visible">True</property>
- <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
- <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
@@ -496,7 +496,7 @@
<widget class="GtkScrolledWindow" id="scrolledwindow3">
<property name="visible">True</property>
<property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
- <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
<property name="shadow_type">GTK_SHADOW_IN</property>
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index e5db10ca956..457bec29511 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -20,6 +20,7 @@
#include <string.h>
#include <termios.h>
#include <unistd.h>
+#include <locale.h>
#define LKC_DIRECT_LINK
#include "lkc.h"
@@ -254,8 +255,8 @@ search_help[] = N_(
" USB$ => find all CONFIG_ symbols ending with USB\n"
"\n");
-static signed char buf[4096], *bufptr = buf;
-static signed char input_buf[4096];
+static char buf[4096], *bufptr = buf;
+static char input_buf[4096];
static char filename[PATH_MAX+1] = ".config";
static char *args[1024], **argptr = args;
static int indent;
diff --git a/security/commoncap.c b/security/commoncap.c
index 849b8c338ee..04c12f58d65 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -149,7 +149,7 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
if (bprm->e_uid != current->uid || bprm->e_gid != current->gid ||
!cap_issubset (new_permitted, current->cap_permitted)) {
- current->mm->dumpable = 0;
+ current->mm->dumpable = suid_dumpable;
if (unsafe & ~LSM_UNSAFE_PTRACE_CAP) {
if (!capable(CAP_SETUID)) {
diff --git a/security/dummy.c b/security/dummy.c
index b32eff14654..6ff88758647 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -130,7 +130,7 @@ static void dummy_bprm_free_security (struct linux_binprm *bprm)
static void dummy_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
{
if (bprm->e_uid != current->uid || bprm->e_gid != current->gid) {
- current->mm->dumpable = 0;
+ current->mm->dumpable = suid_dumpable;
if ((unsafe & ~LSM_UNSAFE_PTRACE_CAP) && !capable(CAP_SETUID)) {
bprm->e_uid = current->uid;
diff --git a/security/keys/Makefile b/security/keys/Makefile
index ddb495d6506..c392d750b20 100644
--- a/security/keys/Makefile
+++ b/security/keys/Makefile
@@ -7,8 +7,9 @@ obj-y := \
keyring.o \
keyctl.o \
process_keys.o \
- user_defined.o \
- request_key.o
+ request_key.o \
+ request_key_auth.o \
+ user_defined.o
obj-$(CONFIG_KEYS_COMPAT) += compat.o
obj-$(CONFIG_PROC_FS) += proc.o
diff --git a/security/keys/compat.c b/security/keys/compat.c
index aff8b22dcb5..3303673c636 100644
--- a/security/keys/compat.c
+++ b/security/keys/compat.c
@@ -1,6 +1,6 @@
/* compat.c: 32-bit compatibility syscall for 64-bit systems
*
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
@@ -24,7 +24,7 @@
* - if you can, you should call sys_keyctl directly
*/
asmlinkage long compat_sys_keyctl(u32 option,
- u32 arg2, u32 arg3, u32 arg4, u32 arg5)
+ u32 arg2, u32 arg3, u32 arg4, u32 arg5)
{
switch (option) {
case KEYCTL_GET_KEYRING_ID:
@@ -71,6 +71,9 @@ asmlinkage long compat_sys_keyctl(u32 option,
case KEYCTL_NEGATE:
return keyctl_negate_key(arg2, arg3, arg4);
+ case KEYCTL_SET_REQKEY_KEYRING:
+ return keyctl_set_reqkey_keyring(arg2);
+
default:
return -EOPNOTSUPP;
}
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 67b2b93a748..46c8602661c 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -1,6 +1,6 @@
/* internal.h: authentication token and access key management internal defs
*
- * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2003-5 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
@@ -15,6 +15,16 @@
#include <linux/key.h>
#include <linux/key-ui.h>
+#if 0
+#define kenter(FMT, a...) printk("==> %s("FMT")\n",__FUNCTION__ , ## a)
+#define kleave(FMT, a...) printk("<== %s()"FMT"\n",__FUNCTION__ , ## a)
+#define kdebug(FMT, a...) printk(FMT"\n" , ## a)
+#else
+#define kenter(FMT, a...) do {} while(0)
+#define kleave(FMT, a...) do {} while(0)
+#define kdebug(FMT, a...) do {} while(0)
+#endif
+
extern struct key_type key_type_dead;
extern struct key_type key_type_user;
@@ -66,20 +76,46 @@ extern struct key *__keyring_search_one(struct key *keyring,
const char *description,
key_perm_t perm);
+extern struct key *keyring_search_instkey(struct key *keyring,
+ key_serial_t target_id);
+
typedef int (*key_match_func_t)(const struct key *, const void *);
extern struct key *keyring_search_aux(struct key *keyring,
+ struct task_struct *tsk,
struct key_type *type,
const void *description,
key_match_func_t match);
-extern struct key *search_process_keyrings_aux(struct key_type *type,
- const void *description,
- key_match_func_t match);
+extern struct key *search_process_keyrings(struct key_type *type,
+ const void *description,
+ key_match_func_t match,
+ struct task_struct *tsk);
extern struct key *find_keyring_by_name(const char *name, key_serial_t bound);
extern int install_thread_keyring(struct task_struct *tsk);
+extern int install_process_keyring(struct task_struct *tsk);
+
+extern struct key *request_key_and_link(struct key_type *type,
+ const char *description,
+ const char *callout_info,
+ struct key *dest_keyring);
+
+/*
+ * request_key authorisation
+ */
+struct request_key_auth {
+ struct key *target_key;
+ struct task_struct *context;
+ pid_t pid;
+};
+
+extern struct key_type key_type_request_key_auth;
+extern struct key *request_key_auth_new(struct key *target,
+ struct key **_rkakey);
+
+extern struct key *key_get_instantiation_authkey(key_serial_t target_id);
/*
* keyctl functions
@@ -100,6 +136,7 @@ extern long keyctl_setperm_key(key_serial_t, key_perm_t);
extern long keyctl_instantiate_key(key_serial_t, const void __user *,
size_t, key_serial_t);
extern long keyctl_negate_key(key_serial_t, unsigned, key_serial_t);
+extern long keyctl_set_reqkey_keyring(int);
/*
diff --git a/security/keys/key.c b/security/keys/key.c
index 59402c84320..fb89f984446 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -1,6 +1,6 @@
/* key.c: basic authentication token and access key management
*
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
@@ -294,7 +294,6 @@ struct key *key_alloc(struct key_type *type, const char *desc,
}
atomic_set(&key->usage, 1);
- rwlock_init(&key->lock);
init_rwsem(&key->sem);
key->type = type;
key->user = user;
@@ -308,7 +307,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
key->payload.data = NULL;
if (!not_in_quota)
- key->flags |= KEY_FLAG_IN_QUOTA;
+ key->flags |= 1 << KEY_FLAG_IN_QUOTA;
memset(&key->type_data, 0, sizeof(key->type_data));
@@ -359,7 +358,7 @@ int key_payload_reserve(struct key *key, size_t datalen)
key_check(key);
/* contemplate the quota adjustment */
- if (delta != 0 && key->flags & KEY_FLAG_IN_QUOTA) {
+ if (delta != 0 && test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
spin_lock(&key->user->lock);
if (delta > 0 &&
@@ -392,7 +391,8 @@ EXPORT_SYMBOL(key_payload_reserve);
static int __key_instantiate_and_link(struct key *key,
const void *data,
size_t datalen,
- struct key *keyring)
+ struct key *keyring,
+ struct key *instkey)
{
int ret, awaken;
@@ -405,27 +405,25 @@ static int __key_instantiate_and_link(struct key *key,
down_write(&key_construction_sem);
/* can't instantiate twice */
- if (!(key->flags & KEY_FLAG_INSTANTIATED)) {
+ if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
/* instantiate the key */
ret = key->type->instantiate(key, data, datalen);
if (ret == 0) {
/* mark the key as being instantiated */
- write_lock(&key->lock);
-
atomic_inc(&key->user->nikeys);
- key->flags |= KEY_FLAG_INSTANTIATED;
+ set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
- if (key->flags & KEY_FLAG_USER_CONSTRUCT) {
- key->flags &= ~KEY_FLAG_USER_CONSTRUCT;
+ if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags))
awaken = 1;
- }
-
- write_unlock(&key->lock);
/* and link it into the destination keyring */
if (keyring)
ret = __key_link(keyring, key);
+
+ /* disable the authorisation key */
+ if (instkey)
+ key_revoke(instkey);
}
}
@@ -446,19 +444,21 @@ static int __key_instantiate_and_link(struct key *key,
int key_instantiate_and_link(struct key *key,
const void *data,
size_t datalen,
- struct key *keyring)
+ struct key *keyring,
+ struct key *instkey)
{
int ret;
if (keyring)
down_write(&keyring->sem);
- ret = __key_instantiate_and_link(key, data, datalen, keyring);
+ ret = __key_instantiate_and_link(key, data, datalen, keyring, instkey);
if (keyring)
up_write(&keyring->sem);
return ret;
+
} /* end key_instantiate_and_link() */
EXPORT_SYMBOL(key_instantiate_and_link);
@@ -469,7 +469,8 @@ EXPORT_SYMBOL(key_instantiate_and_link);
*/
int key_negate_and_link(struct key *key,
unsigned timeout,
- struct key *keyring)
+ struct key *keyring,
+ struct key *instkey)
{
struct timespec now;
int ret, awaken;
@@ -486,26 +487,26 @@ int key_negate_and_link(struct key *key,
down_write(&key_construction_sem);
/* can't instantiate twice */
- if (!(key->flags & KEY_FLAG_INSTANTIATED)) {
+ if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
/* mark the key as being negatively instantiated */
- write_lock(&key->lock);
-
atomic_inc(&key->user->nikeys);
- key->flags |= KEY_FLAG_INSTANTIATED | KEY_FLAG_NEGATIVE;
+ set_bit(KEY_FLAG_NEGATIVE, &key->flags);
+ set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
now = current_kernel_time();
key->expiry = now.tv_sec + timeout;
- if (key->flags & KEY_FLAG_USER_CONSTRUCT) {
- key->flags &= ~KEY_FLAG_USER_CONSTRUCT;
+ if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags))
awaken = 1;
- }
- write_unlock(&key->lock);
ret = 0;
/* and link it into the destination keyring */
if (keyring)
ret = __key_link(keyring, key);
+
+ /* disable the authorisation key */
+ if (instkey)
+ key_revoke(instkey);
}
up_write(&key_construction_sem);
@@ -553,8 +554,10 @@ static void key_cleanup(void *data)
rb_erase(&key->serial_node, &key_serial_tree);
spin_unlock(&key_serial_lock);
+ key_check(key);
+
/* deal with the user's key tracking and quota */
- if (key->flags & KEY_FLAG_IN_QUOTA) {
+ if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
spin_lock(&key->user->lock);
key->user->qnkeys--;
key->user->qnbytes -= key->quotalen;
@@ -562,7 +565,7 @@ static void key_cleanup(void *data)
}
atomic_dec(&key->user->nkeys);
- if (key->flags & KEY_FLAG_INSTANTIATED)
+ if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
atomic_dec(&key->user->nikeys);
key_user_put(key->user);
@@ -631,9 +634,9 @@ struct key *key_lookup(key_serial_t id)
goto error;
found:
- /* pretent doesn't exist if it's dead */
+ /* pretend it doesn't exist if it's dead */
if (atomic_read(&key->usage) == 0 ||
- (key->flags & KEY_FLAG_DEAD) ||
+ test_bit(KEY_FLAG_DEAD, &key->flags) ||
key->type == &key_type_dead)
goto not_found;
@@ -708,12 +711,9 @@ static inline struct key *__key_update(struct key *key, const void *payload,
ret = key->type->update(key, payload, plen);
- if (ret == 0) {
+ if (ret == 0)
/* updating a negative key instantiates it */
- write_lock(&key->lock);
- key->flags &= ~KEY_FLAG_NEGATIVE;
- write_unlock(&key->lock);
- }
+ clear_bit(KEY_FLAG_NEGATIVE, &key->flags);
up_write(&key->sem);
@@ -793,7 +793,7 @@ struct key *key_create_or_update(struct key *keyring,
}
/* instantiate it and link it into the target keyring */
- ret = __key_instantiate_and_link(key, payload, plen, keyring);
+ ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL);
if (ret < 0) {
key_put(key);
key = ERR_PTR(ret);
@@ -841,12 +841,9 @@ int key_update(struct key *key, const void *payload, size_t plen)
down_write(&key->sem);
ret = key->type->update(key, payload, plen);
- if (ret == 0) {
+ if (ret == 0)
/* updating a negative key instantiates it */
- write_lock(&key->lock);
- key->flags &= ~KEY_FLAG_NEGATIVE;
- write_unlock(&key->lock);
- }
+ clear_bit(KEY_FLAG_NEGATIVE, &key->flags);
up_write(&key->sem);
}
@@ -892,10 +889,7 @@ struct key *key_duplicate(struct key *source, const char *desc)
goto error2;
atomic_inc(&key->user->nikeys);
-
- write_lock(&key->lock);
- key->flags |= KEY_FLAG_INSTANTIATED;
- write_unlock(&key->lock);
+ set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
error_k:
up_read(&key_types_sem);
@@ -922,9 +916,7 @@ void key_revoke(struct key *key)
/* make sure no one's trying to change or use the key when we mark
* it */
down_write(&key->sem);
- write_lock(&key->lock);
- key->flags |= KEY_FLAG_REVOKED;
- write_unlock(&key->lock);
+ set_bit(KEY_FLAG_REVOKED, &key->flags);
up_write(&key->sem);
} /* end key_revoke() */
@@ -975,24 +967,33 @@ void unregister_key_type(struct key_type *ktype)
/* withdraw the key type */
list_del_init(&ktype->link);
- /* need to withdraw all keys of this type */
+ /* mark all the keys of this type dead */
spin_lock(&key_serial_lock);
for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) {
key = rb_entry(_n, struct key, serial_node);
- if (key->type != ktype)
- continue;
+ if (key->type == ktype)
+ key->type = &key_type_dead;
+ }
+
+ spin_unlock(&key_serial_lock);
+
+ /* make sure everyone revalidates their keys */
+ synchronize_rcu();
- write_lock(&key->lock);
- key->type = &key_type_dead;
- write_unlock(&key->lock);
+ /* we should now be able to destroy the payloads of all the keys of
+ * this type with impunity */
+ spin_lock(&key_serial_lock);
+
+ for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) {
+ key = rb_entry(_n, struct key, serial_node);
- /* there shouldn't be anyone looking at the description or
- * payload now */
- if (ktype->destroy)
- ktype->destroy(key);
- memset(&key->payload, 0xbd, sizeof(key->payload));
+ if (key->type == ktype) {
+ if (ktype->destroy)
+ ktype->destroy(key);
+ memset(&key->payload, 0xbd, sizeof(key->payload));
+ }
}
spin_unlock(&key_serial_lock);
@@ -1037,4 +1038,5 @@ void __init key_init(void)
/* link the two root keyrings together */
key_link(&root_session_keyring, &root_user_keyring);
+
} /* end key_init() */
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index dc0011b3fac..fea262860ea 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -1,6 +1,6 @@
/* keyctl.c: userspace keyctl operations
*
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
@@ -49,6 +49,13 @@ asmlinkage long sys_add_key(const char __user *_type,
goto error;
type[31] = '\0';
+ if (!type[0])
+ goto error;
+
+ ret = -EPERM;
+ if (type[0] == '.')
+ goto error;
+
ret = -EFAULT;
dlen = strnlen_user(_description, PAGE_SIZE - 1);
if (dlen <= 0)
@@ -82,7 +89,7 @@ asmlinkage long sys_add_key(const char __user *_type,
}
/* find the target keyring (which must be writable) */
- keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE);
+ keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
if (IS_ERR(keyring)) {
ret = PTR_ERR(keyring);
goto error3;
@@ -181,7 +188,7 @@ asmlinkage long sys_request_key(const char __user *_type,
/* get the destination keyring if specified */
dest = NULL;
if (destringid) {
- dest = lookup_user_key(destringid, 1, 0, KEY_WRITE);
+ dest = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE);
if (IS_ERR(dest)) {
ret = PTR_ERR(dest);
goto error3;
@@ -196,23 +203,15 @@ asmlinkage long sys_request_key(const char __user *_type,
}
/* do the search */
- key = request_key(ktype, description, callout_info);
+ key = request_key_and_link(ktype, description, callout_info, dest);
if (IS_ERR(key)) {
ret = PTR_ERR(key);
goto error5;
}
- /* link the resulting key to the destination keyring */
- if (dest) {
- ret = key_link(dest, key);
- if (ret < 0)
- goto error6;
- }
-
ret = key->serial;
- error6:
- key_put(key);
+ key_put(key);
error5:
key_type_put(ktype);
error4:
@@ -237,7 +236,7 @@ long keyctl_get_keyring_ID(key_serial_t id, int create)
struct key *key;
long ret;
- key = lookup_user_key(id, create, 0, KEY_SEARCH);
+ key = lookup_user_key(NULL, id, create, 0, KEY_SEARCH);
if (IS_ERR(key)) {
ret = PTR_ERR(key);
goto error;
@@ -324,7 +323,7 @@ long keyctl_update_key(key_serial_t id,
}
/* find the target key (which must be writable) */
- key = lookup_user_key(id, 0, 0, KEY_WRITE);
+ key = lookup_user_key(NULL, id, 0, 0, KEY_WRITE);
if (IS_ERR(key)) {
ret = PTR_ERR(key);
goto error2;
@@ -352,7 +351,7 @@ long keyctl_revoke_key(key_serial_t id)
struct key *key;
long ret;
- key = lookup_user_key(id, 0, 0, KEY_WRITE);
+ key = lookup_user_key(NULL, id, 0, 0, KEY_WRITE);
if (IS_ERR(key)) {
ret = PTR_ERR(key);
goto error;
@@ -378,7 +377,7 @@ long keyctl_keyring_clear(key_serial_t ringid)
struct key *keyring;
long ret;
- keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE);
+ keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
if (IS_ERR(keyring)) {
ret = PTR_ERR(keyring);
goto error;
@@ -404,13 +403,13 @@ long keyctl_keyring_link(key_serial_t id, key_serial_t ringid)
struct key *keyring, *key;
long ret;
- keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE);
+ keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
if (IS_ERR(keyring)) {
ret = PTR_ERR(keyring);
goto error;
}
- key = lookup_user_key(id, 1, 0, KEY_LINK);
+ key = lookup_user_key(NULL, id, 1, 0, KEY_LINK);
if (IS_ERR(key)) {
ret = PTR_ERR(key);
goto error2;
@@ -438,13 +437,13 @@ long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid)
struct key *keyring, *key;
long ret;
- keyring = lookup_user_key(ringid, 0, 0, KEY_WRITE);
+ keyring = lookup_user_key(NULL, ringid, 0, 0, KEY_WRITE);
if (IS_ERR(keyring)) {
ret = PTR_ERR(keyring);
goto error;
}
- key = lookup_user_key(id, 0, 0, 0);
+ key = lookup_user_key(NULL, id, 0, 0, 0);
if (IS_ERR(key)) {
ret = PTR_ERR(key);
goto error2;
@@ -475,16 +474,29 @@ long keyctl_describe_key(key_serial_t keyid,
char __user *buffer,
size_t buflen)
{
- struct key *key;
+ struct key *key, *instkey;
char *tmpbuf;
long ret;
- key = lookup_user_key(keyid, 0, 1, KEY_VIEW);
+ key = lookup_user_key(NULL, keyid, 0, 1, KEY_VIEW);
if (IS_ERR(key)) {
+ /* viewing a key under construction is permitted if we have the
+ * authorisation token handy */
+ if (PTR_ERR(key) == -EACCES) {
+ instkey = key_get_instantiation_authkey(keyid);
+ if (!IS_ERR(instkey)) {
+ key_put(instkey);
+ key = lookup_user_key(NULL, keyid, 0, 1, 0);
+ if (!IS_ERR(key))
+ goto okay;
+ }
+ }
+
ret = PTR_ERR(key);
goto error;
}
+okay:
/* calculate how much description we're going to return */
ret = -ENOMEM;
tmpbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
@@ -568,7 +580,7 @@ long keyctl_keyring_search(key_serial_t ringid,
goto error2;
/* get the keyring at which to begin the search */
- keyring = lookup_user_key(ringid, 0, 0, KEY_SEARCH);
+ keyring = lookup_user_key(NULL, ringid, 0, 0, KEY_SEARCH);
if (IS_ERR(keyring)) {
ret = PTR_ERR(keyring);
goto error2;
@@ -577,7 +589,7 @@ long keyctl_keyring_search(key_serial_t ringid,
/* get the destination keyring if specified */
dest = NULL;
if (destringid) {
- dest = lookup_user_key(destringid, 1, 0, KEY_WRITE);
+ dest = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE);
if (IS_ERR(dest)) {
ret = PTR_ERR(dest);
goto error3;
@@ -656,24 +668,23 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen)
long ret;
/* find the key first */
- key = lookup_user_key(keyid, 0, 0, 0);
+ key = lookup_user_key(NULL, keyid, 0, 0, 0);
if (!IS_ERR(key)) {
/* see if we can read it directly */
if (key_permission(key, KEY_READ))
goto can_read_key;
- /* can't; see if it's searchable from this process's
- * keyrings */
- ret = -ENOKEY;
- if (key_permission(key, KEY_SEARCH)) {
- /* okay - we do have search permission on the key
- * itself, but do we have the key? */
- skey = search_process_keyrings_aux(key->type, key,
- keyctl_read_key_same);
- if (!IS_ERR(skey))
- goto can_read_key2;
- }
-
+ /* we can't; see if it's searchable from this process's
+ * keyrings
+ * - we automatically take account of the fact that it may be
+ * dangling off an instantiation key
+ */
+ skey = search_process_keyrings(key->type, key,
+ keyctl_read_key_same, current);
+ if (!IS_ERR(skey))
+ goto can_read_key2;
+
+ ret = PTR_ERR(skey);
goto error2;
}
@@ -719,7 +730,7 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
if (uid == (uid_t) -1 && gid == (gid_t) -1)
goto error;
- key = lookup_user_key(id, 1, 1, 0);
+ key = lookup_user_key(NULL, id, 1, 1, 0);
if (IS_ERR(key)) {
ret = PTR_ERR(key);
goto error;
@@ -728,7 +739,6 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
/* make the changes with the locks held to prevent chown/chown races */
ret = -EACCES;
down_write(&key->sem);
- write_lock(&key->lock);
if (!capable(CAP_SYS_ADMIN)) {
/* only the sysadmin can chown a key to some other UID */
@@ -755,7 +765,6 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
ret = 0;
no_access:
- write_unlock(&key->lock);
up_write(&key->sem);
key_put(key);
error:
@@ -778,32 +787,25 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm)
if (perm & ~(KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL))
goto error;
- key = lookup_user_key(id, 1, 1, 0);
+ key = lookup_user_key(NULL, id, 1, 1, 0);
if (IS_ERR(key)) {
ret = PTR_ERR(key);
goto error;
}
- /* make the changes with the locks held to prevent chown/chmod
- * races */
+ /* make the changes with the locks held to prevent chown/chmod races */
ret = -EACCES;
down_write(&key->sem);
- write_lock(&key->lock);
- /* if we're not the sysadmin, we can only chmod a key that we
- * own */
- if (!capable(CAP_SYS_ADMIN) && key->uid != current->fsuid)
- goto no_access;
-
- /* changing the permissions mask */
- key->perm = perm;
- ret = 0;
+ /* if we're not the sysadmin, we can only change a key that we own */
+ if (capable(CAP_SYS_ADMIN) || key->uid == current->fsuid) {
+ key->perm = perm;
+ ret = 0;
+ }
- no_access:
- write_unlock(&key->lock);
up_write(&key->sem);
key_put(key);
- error:
+error:
return ret;
} /* end keyctl_setperm_key() */
@@ -818,7 +820,8 @@ long keyctl_instantiate_key(key_serial_t id,
size_t plen,
key_serial_t ringid)
{
- struct key *key, *keyring;
+ struct request_key_auth *rka;
+ struct key *instkey, *keyring;
void *payload;
long ret;
@@ -840,18 +843,21 @@ long keyctl_instantiate_key(key_serial_t id,
goto error2;
}
- /* find the target key (which must be writable) */
- key = lookup_user_key(id, 0, 1, KEY_WRITE);
- if (IS_ERR(key)) {
- ret = PTR_ERR(key);
+ /* find the instantiation authorisation key */
+ instkey = key_get_instantiation_authkey(id);
+ if (IS_ERR(instkey)) {
+ ret = PTR_ERR(instkey);
goto error2;
}
- /* find the destination keyring if present (which must also be
- * writable) */
+ rka = instkey->payload.data;
+
+ /* find the destination keyring amongst those belonging to the
+ * requesting task */
keyring = NULL;
if (ringid) {
- keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE);
+ keyring = lookup_user_key(rka->context, ringid, 1, 0,
+ KEY_WRITE);
if (IS_ERR(keyring)) {
ret = PTR_ERR(keyring);
goto error3;
@@ -859,11 +865,12 @@ long keyctl_instantiate_key(key_serial_t id,
}
/* instantiate the key and link it into a keyring */
- ret = key_instantiate_and_link(key, payload, plen, keyring);
+ ret = key_instantiate_and_link(rka->target_key, payload, plen,
+ keyring, instkey);
key_put(keyring);
error3:
- key_put(key);
+ key_put(instkey);
error2:
kfree(payload);
error:
@@ -878,21 +885,24 @@ long keyctl_instantiate_key(key_serial_t id,
*/
long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid)
{
- struct key *key, *keyring;
+ struct request_key_auth *rka;
+ struct key *instkey, *keyring;
long ret;
- /* find the target key (which must be writable) */
- key = lookup_user_key(id, 0, 1, KEY_WRITE);
- if (IS_ERR(key)) {
- ret = PTR_ERR(key);
+ /* find the instantiation authorisation key */
+ instkey = key_get_instantiation_authkey(id);
+ if (IS_ERR(instkey)) {
+ ret = PTR_ERR(instkey);
goto error;
}
+ rka = instkey->payload.data;
+
/* find the destination keyring if present (which must also be
* writable) */
keyring = NULL;
if (ringid) {
- keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE);
+ keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
if (IS_ERR(keyring)) {
ret = PTR_ERR(keyring);
goto error2;
@@ -900,11 +910,11 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid)
}
/* instantiate the key and link it into a keyring */
- ret = key_negate_and_link(key, timeout, keyring);
+ ret = key_negate_and_link(rka->target_key, timeout, keyring, instkey);
key_put(keyring);
error2:
- key_put(key);
+ key_put(instkey);
error:
return ret;
@@ -912,6 +922,44 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid)
/*****************************************************************************/
/*
+ * set the default keyring in which request_key() will cache keys
+ * - return the old setting
+ */
+long keyctl_set_reqkey_keyring(int reqkey_defl)
+{
+ int ret;
+
+ switch (reqkey_defl) {
+ case KEY_REQKEY_DEFL_THREAD_KEYRING:
+ ret = install_thread_keyring(current);
+ if (ret < 0)
+ return ret;
+ goto set;
+
+ case KEY_REQKEY_DEFL_PROCESS_KEYRING:
+ ret = install_process_keyring(current);
+ if (ret < 0)
+ return ret;
+
+ case KEY_REQKEY_DEFL_DEFAULT:
+ case KEY_REQKEY_DEFL_SESSION_KEYRING:
+ case KEY_REQKEY_DEFL_USER_KEYRING:
+ case KEY_REQKEY_DEFL_USER_SESSION_KEYRING:
+ set:
+ current->jit_keyring = reqkey_defl;
+
+ case KEY_REQKEY_DEFL_NO_CHANGE:
+ return current->jit_keyring;
+
+ case KEY_REQKEY_DEFL_GROUP_KEYRING:
+ default:
+ return -EINVAL;
+ }
+
+} /* end keyctl_set_reqkey_keyring() */
+
+/*****************************************************************************/
+/*
* the key control system call
*/
asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3,
@@ -980,6 +1028,9 @@ asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3,
(unsigned) arg3,
(key_serial_t) arg4);
+ case KEYCTL_SET_REQKEY_KEYRING:
+ return keyctl_set_reqkey_keyring(arg2);
+
default:
return -EOPNOTSUPP;
}
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index e2ab4f8e748..90a551e4da6 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -1,6 +1,6 @@
/* keyring.c: keyring handling
*
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
@@ -132,10 +132,17 @@ static int keyring_duplicate(struct key *keyring, const struct key *source)
(PAGE_SIZE - sizeof(*klist)) / sizeof(struct key);
ret = 0;
- sklist = source->payload.subscriptions;
- if (sklist && sklist->nkeys > 0) {
+ /* find out how many keys are currently linked */
+ rcu_read_lock();
+ sklist = rcu_dereference(source->payload.subscriptions);
+ max = 0;
+ if (sklist)
max = sklist->nkeys;
+ rcu_read_unlock();
+
+ /* allocate a new payload and stuff load with key links */
+ if (max > 0) {
BUG_ON(max > limit);
max = (max + 3) & ~3;
@@ -148,6 +155,10 @@ static int keyring_duplicate(struct key *keyring, const struct key *source)
if (!klist)
goto error;
+ /* set links */
+ rcu_read_lock();
+ sklist = rcu_dereference(source->payload.subscriptions);
+
klist->maxkeys = max;
klist->nkeys = sklist->nkeys;
memcpy(klist->keys,
@@ -157,7 +168,9 @@ static int keyring_duplicate(struct key *keyring, const struct key *source)
for (loop = klist->nkeys - 1; loop >= 0; loop--)
atomic_inc(&klist->keys[loop]->usage);
- keyring->payload.subscriptions = klist;
+ rcu_read_unlock();
+
+ rcu_assign_pointer(keyring->payload.subscriptions, klist);
ret = 0;
}
@@ -192,7 +205,7 @@ static void keyring_destroy(struct key *keyring)
write_unlock(&keyring_name_lock);
}
- klist = keyring->payload.subscriptions;
+ klist = rcu_dereference(keyring->payload.subscriptions);
if (klist) {
for (loop = klist->nkeys - 1; loop >= 0; loop--)
key_put(klist->keys[loop]);
@@ -216,17 +229,20 @@ static void keyring_describe(const struct key *keyring, struct seq_file *m)
seq_puts(m, "[anon]");
}
- klist = keyring->payload.subscriptions;
+ rcu_read_lock();
+ klist = rcu_dereference(keyring->payload.subscriptions);
if (klist)
seq_printf(m, ": %u/%u", klist->nkeys, klist->maxkeys);
else
seq_puts(m, ": empty");
+ rcu_read_unlock();
} /* end keyring_describe() */
/*****************************************************************************/
/*
* read a list of key IDs from the keyring's contents
+ * - the keyring's semaphore is read-locked
*/
static long keyring_read(const struct key *keyring,
char __user *buffer, size_t buflen)
@@ -237,7 +253,7 @@ static long keyring_read(const struct key *keyring,
int loop, ret;
ret = 0;
- klist = keyring->payload.subscriptions;
+ klist = rcu_dereference(keyring->payload.subscriptions);
if (klist) {
/* calculate how much data we could return */
@@ -292,7 +308,7 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
uid, gid, KEY_USR_ALL, not_in_quota);
if (!IS_ERR(keyring)) {
- ret = key_instantiate_and_link(keyring, NULL, 0, dest);
+ ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL);
if (ret < 0) {
key_put(keyring);
keyring = ERR_PTR(ret);
@@ -310,17 +326,18 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
* - we only find keys on which we have search permission
* - we use the supplied match function to see if the description (or other
* feature of interest) matches
- * - we readlock the keyrings as we search down the tree
+ * - we rely on RCU to prevent the keyring lists from disappearing on us
* - we return -EAGAIN if we didn't find any matching key
* - we return -ENOKEY if we only found negative matching keys
*/
struct key *keyring_search_aux(struct key *keyring,
+ struct task_struct *context,
struct key_type *type,
const void *description,
key_match_func_t match)
{
struct {
- struct key *keyring;
+ struct keyring_list *keylist;
int kix;
} stack[KEYRING_SEARCH_MAX_DEPTH];
@@ -328,13 +345,15 @@ struct key *keyring_search_aux(struct key *keyring,
struct timespec now;
struct key *key;
long err;
- int sp, psp, kix;
+ int sp, kix;
key_check(keyring);
+ rcu_read_lock();
+
/* top keyring must have search permission to begin the search */
key = ERR_PTR(-EACCES);
- if (!key_permission(keyring, KEY_SEARCH))
+ if (!key_task_permission(keyring, context, KEY_SEARCH))
goto error;
key = ERR_PTR(-ENOTDIR);
@@ -347,11 +366,10 @@ struct key *keyring_search_aux(struct key *keyring,
/* start processing a new keyring */
descend:
- read_lock(&keyring->lock);
- if (keyring->flags & KEY_FLAG_REVOKED)
+ if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
goto not_this_keyring;
- keylist = keyring->payload.subscriptions;
+ keylist = rcu_dereference(keyring->payload.subscriptions);
if (!keylist)
goto not_this_keyring;
@@ -364,7 +382,7 @@ struct key *keyring_search_aux(struct key *keyring,
continue;
/* skip revoked keys and expired keys */
- if (key->flags & KEY_FLAG_REVOKED)
+ if (test_bit(KEY_FLAG_REVOKED, &key->flags))
continue;
if (key->expiry && now.tv_sec >= key->expiry)
@@ -375,11 +393,11 @@ struct key *keyring_search_aux(struct key *keyring,
continue;
/* key must have search permissions */
- if (!key_permission(key, KEY_SEARCH))
+ if (!key_task_permission(key, context, KEY_SEARCH))
continue;
/* we set a different error code if we find a negative key */
- if (key->flags & KEY_FLAG_NEGATIVE) {
+ if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) {
err = -ENOKEY;
continue;
}
@@ -390,48 +408,37 @@ struct key *keyring_search_aux(struct key *keyring,
/* search through the keyrings nested in this one */
kix = 0;
ascend:
- while (kix < keylist->nkeys) {
+ for (; kix < keylist->nkeys; kix++) {
key = keylist->keys[kix];
if (key->type != &key_type_keyring)
- goto next;
+ continue;
/* recursively search nested keyrings
* - only search keyrings for which we have search permission
*/
if (sp >= KEYRING_SEARCH_MAX_DEPTH)
- goto next;
-
- if (!key_permission(key, KEY_SEARCH))
- goto next;
+ continue;
- /* evade loops in the keyring tree */
- for (psp = 0; psp < sp; psp++)
- if (stack[psp].keyring == keyring)
- goto next;
+ if (!key_task_permission(key, context, KEY_SEARCH))
+ continue;
/* stack the current position */
- stack[sp].keyring = keyring;
+ stack[sp].keylist = keylist;
stack[sp].kix = kix;
sp++;
/* begin again with the new keyring */
keyring = key;
goto descend;
-
- next:
- kix++;
}
/* the keyring we're looking at was disqualified or didn't contain a
* matching key */
not_this_keyring:
- read_unlock(&keyring->lock);
-
if (sp > 0) {
/* resume the processing of a keyring higher up in the tree */
sp--;
- keyring = stack[sp].keyring;
- keylist = keyring->payload.subscriptions;
+ keylist = stack[sp].keylist;
kix = stack[sp].kix + 1;
goto ascend;
}
@@ -442,16 +449,9 @@ struct key *keyring_search_aux(struct key *keyring,
/* we found a viable match */
found:
atomic_inc(&key->usage);
- read_unlock(&keyring->lock);
-
- /* unwind the keyring stack */
- while (sp > 0) {
- sp--;
- read_unlock(&stack[sp].keyring->lock);
- }
-
key_check(key);
error:
+ rcu_read_unlock();
return key;
} /* end keyring_search_aux() */
@@ -469,7 +469,11 @@ struct key *keyring_search(struct key *keyring,
struct key_type *type,
const char *description)
{
- return keyring_search_aux(keyring, type, description, type->match);
+ if (!type->match)
+ return ERR_PTR(-ENOKEY);
+
+ return keyring_search_aux(keyring, current,
+ type, description, type->match);
} /* end keyring_search() */
@@ -489,15 +493,18 @@ struct key *__keyring_search_one(struct key *keyring,
struct key *key;
int loop;
- klist = keyring->payload.subscriptions;
+ rcu_read_lock();
+
+ klist = rcu_dereference(keyring->payload.subscriptions);
if (klist) {
for (loop = 0; loop < klist->nkeys; loop++) {
key = klist->keys[loop];
if (key->type == ktype &&
- key->type->match(key, description) &&
+ (!key->type->match ||
+ key->type->match(key, description)) &&
key_permission(key, perm) &&
- !(key->flags & KEY_FLAG_REVOKED)
+ !test_bit(KEY_FLAG_REVOKED, &key->flags)
)
goto found;
}
@@ -509,12 +516,58 @@ struct key *__keyring_search_one(struct key *keyring,
found:
atomic_inc(&key->usage);
error:
+ rcu_read_unlock();
return key;
} /* end __keyring_search_one() */
/*****************************************************************************/
/*
+ * search for an instantiation authorisation key matching a target key
+ * - the RCU read lock must be held by the caller
+ * - a target_id of zero specifies any valid token
+ */
+struct key *keyring_search_instkey(struct key *keyring,
+ key_serial_t target_id)
+{
+ struct request_key_auth *rka;
+ struct keyring_list *klist;
+ struct key *instkey;
+ int loop;
+
+ klist = rcu_dereference(keyring->payload.subscriptions);
+ if (klist) {
+ for (loop = 0; loop < klist->nkeys; loop++) {
+ instkey = klist->keys[loop];
+
+ if (instkey->type != &key_type_request_key_auth)
+ continue;
+
+ rka = instkey->payload.data;
+ if (target_id && rka->target_key->serial != target_id)
+ continue;
+
+ /* the auth key is revoked during instantiation */
+ if (!test_bit(KEY_FLAG_REVOKED, &instkey->flags))
+ goto found;
+
+ instkey = ERR_PTR(-EKEYREVOKED);
+ goto error;
+ }
+ }
+
+ instkey = ERR_PTR(-EACCES);
+ goto error;
+
+found:
+ atomic_inc(&instkey->usage);
+error:
+ return instkey;
+
+} /* end keyring_search_instkey() */
+
+/*****************************************************************************/
+/*
* find a keyring with the specified name
* - all named keyrings are searched
* - only find keyrings with search permission for the process
@@ -540,7 +593,7 @@ struct key *find_keyring_by_name(const char *name, key_serial_t bound)
&keyring_name_hash[bucket],
type_data.link
) {
- if (keyring->flags & KEY_FLAG_REVOKED)
+ if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
continue;
if (strcmp(keyring->description, name) != 0)
@@ -579,7 +632,7 @@ struct key *find_keyring_by_name(const char *name, key_serial_t bound)
static int keyring_detect_cycle(struct key *A, struct key *B)
{
struct {
- struct key *subtree;
+ struct keyring_list *keylist;
int kix;
} stack[KEYRING_SEARCH_MAX_DEPTH];
@@ -587,20 +640,21 @@ static int keyring_detect_cycle(struct key *A, struct key *B)
struct key *subtree, *key;
int sp, kix, ret;
+ rcu_read_lock();
+
ret = -EDEADLK;
if (A == B)
- goto error;
+ goto cycle_detected;
subtree = B;
sp = 0;
/* start processing a new keyring */
descend:
- read_lock(&subtree->lock);
- if (subtree->flags & KEY_FLAG_REVOKED)
+ if (test_bit(KEY_FLAG_REVOKED, &subtree->flags))
goto not_this_keyring;
- keylist = subtree->payload.subscriptions;
+ keylist = rcu_dereference(subtree->payload.subscriptions);
if (!keylist)
goto not_this_keyring;
kix = 0;
@@ -619,7 +673,7 @@ static int keyring_detect_cycle(struct key *A, struct key *B)
goto too_deep;
/* stack the current position */
- stack[sp].subtree = subtree;
+ stack[sp].keylist = keylist;
stack[sp].kix = kix;
sp++;
@@ -632,13 +686,10 @@ static int keyring_detect_cycle(struct key *A, struct key *B)
/* the keyring we're looking at was disqualified or didn't contain a
* matching key */
not_this_keyring:
- read_unlock(&subtree->lock);
-
if (sp > 0) {
/* resume the checking of a keyring higher up in the tree */
sp--;
- subtree = stack[sp].subtree;
- keylist = subtree->payload.subscriptions;
+ keylist = stack[sp].keylist;
kix = stack[sp].kix + 1;
goto ascend;
}
@@ -646,30 +697,36 @@ static int keyring_detect_cycle(struct key *A, struct key *B)
ret = 0; /* no cycles detected */
error:
+ rcu_read_unlock();
return ret;
too_deep:
ret = -ELOOP;
- goto error_unwind;
+ goto error;
+
cycle_detected:
ret = -EDEADLK;
- error_unwind:
- read_unlock(&subtree->lock);
-
- /* unwind the keyring stack */
- while (sp > 0) {
- sp--;
- read_unlock(&stack[sp].subtree->lock);
- }
-
goto error;
} /* end keyring_detect_cycle() */
/*****************************************************************************/
/*
+ * dispose of a keyring list after the RCU grace period
+ */
+static void keyring_link_rcu_disposal(struct rcu_head *rcu)
+{
+ struct keyring_list *klist =
+ container_of(rcu, struct keyring_list, rcu);
+
+ kfree(klist);
+
+} /* end keyring_link_rcu_disposal() */
+
+/*****************************************************************************/
+/*
* link a key into to a keyring
- * - must be called with the keyring's semaphore held
+ * - must be called with the keyring's semaphore write-locked
*/
int __key_link(struct key *keyring, struct key *key)
{
@@ -679,7 +736,7 @@ int __key_link(struct key *keyring, struct key *key)
int ret;
ret = -EKEYREVOKED;
- if (keyring->flags & KEY_FLAG_REVOKED)
+ if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
goto error;
ret = -ENOTDIR;
@@ -710,9 +767,10 @@ int __key_link(struct key *keyring, struct key *key)
/* there's sufficient slack space to add directly */
atomic_inc(&key->usage);
- write_lock(&keyring->lock);
- klist->keys[klist->nkeys++] = key;
- write_unlock(&keyring->lock);
+ klist->keys[klist->nkeys] = key;
+ smp_wmb();
+ klist->nkeys++;
+ smp_wmb();
ret = 0;
}
@@ -723,6 +781,8 @@ int __key_link(struct key *keyring, struct key *key)
max += klist->maxkeys;
ret = -ENFILE;
+ if (max > 65535)
+ goto error3;
size = sizeof(*klist) + sizeof(*key) * max;
if (size > PAGE_SIZE)
goto error3;
@@ -743,14 +803,13 @@ int __key_link(struct key *keyring, struct key *key)
/* add the key into the new space */
atomic_inc(&key->usage);
-
- write_lock(&keyring->lock);
- keyring->payload.subscriptions = nklist;
nklist->keys[nklist->nkeys++] = key;
- write_unlock(&keyring->lock);
+
+ rcu_assign_pointer(keyring->payload.subscriptions, nklist);
/* dispose of the old keyring list */
- kfree(klist);
+ if (klist)
+ call_rcu(&klist->rcu, keyring_link_rcu_disposal);
ret = 0;
}
@@ -791,11 +850,26 @@ EXPORT_SYMBOL(key_link);
/*****************************************************************************/
/*
+ * dispose of a keyring list after the RCU grace period, freeing the unlinked
+ * key
+ */
+static void keyring_unlink_rcu_disposal(struct rcu_head *rcu)
+{
+ struct keyring_list *klist =
+ container_of(rcu, struct keyring_list, rcu);
+
+ key_put(klist->keys[klist->delkey]);
+ kfree(klist);
+
+} /* end keyring_unlink_rcu_disposal() */
+
+/*****************************************************************************/
+/*
* unlink the first link to a key from a keyring
*/
int key_unlink(struct key *keyring, struct key *key)
{
- struct keyring_list *klist;
+ struct keyring_list *klist, *nklist;
int loop, ret;
key_check(keyring);
@@ -819,31 +893,45 @@ int key_unlink(struct key *keyring, struct key *key)
ret = -ENOENT;
goto error;
- key_is_present:
+key_is_present:
+ /* we need to copy the key list for RCU purposes */
+ nklist = kmalloc(sizeof(*klist) + sizeof(*key) * klist->maxkeys,
+ GFP_KERNEL);
+ if (!nklist)
+ goto nomem;
+ nklist->maxkeys = klist->maxkeys;
+ nklist->nkeys = klist->nkeys - 1;
+
+ if (loop > 0)
+ memcpy(&nklist->keys[0],
+ &klist->keys[0],
+ loop * sizeof(klist->keys[0]));
+
+ if (loop < nklist->nkeys)
+ memcpy(&nklist->keys[loop],
+ &klist->keys[loop + 1],
+ (nklist->nkeys - loop) * sizeof(klist->keys[0]));
+
/* adjust the user's quota */
key_payload_reserve(keyring,
keyring->datalen - KEYQUOTA_LINK_BYTES);
- /* shuffle down the key pointers
- * - it might be worth shrinking the allocated memory, but that runs
- * the risk of ENOMEM as we would have to copy
- */
- write_lock(&keyring->lock);
+ rcu_assign_pointer(keyring->payload.subscriptions, nklist);
- klist->nkeys--;
- if (loop < klist->nkeys)
- memcpy(&klist->keys[loop],
- &klist->keys[loop + 1],
- (klist->nkeys - loop) * sizeof(struct key *));
+ up_write(&keyring->sem);
- write_unlock(&keyring->lock);
+ /* schedule for later cleanup */
+ klist->delkey = loop;
+ call_rcu(&klist->rcu, keyring_unlink_rcu_disposal);
- up_write(&keyring->sem);
- key_put(key);
ret = 0;
- error:
+error:
return ret;
+nomem:
+ ret = -ENOMEM;
+ up_write(&keyring->sem);
+ goto error;
} /* end key_unlink() */
@@ -851,13 +939,32 @@ EXPORT_SYMBOL(key_unlink);
/*****************************************************************************/
/*
+ * dispose of a keyring list after the RCU grace period, releasing the keys it
+ * links to
+ */
+static void keyring_clear_rcu_disposal(struct rcu_head *rcu)
+{
+ struct keyring_list *klist;
+ int loop;
+
+ klist = container_of(rcu, struct keyring_list, rcu);
+
+ for (loop = klist->nkeys - 1; loop >= 0; loop--)
+ key_put(klist->keys[loop]);
+
+ kfree(klist);
+
+} /* end keyring_clear_rcu_disposal() */
+
+/*****************************************************************************/
+/*
* clear the specified process keyring
* - implements keyctl(KEYCTL_CLEAR)
*/
int keyring_clear(struct key *keyring)
{
struct keyring_list *klist;
- int loop, ret;
+ int ret;
ret = -ENOTDIR;
if (keyring->type == &key_type_keyring) {
@@ -870,20 +977,15 @@ int keyring_clear(struct key *keyring)
key_payload_reserve(keyring,
sizeof(struct keyring_list));
- write_lock(&keyring->lock);
- keyring->payload.subscriptions = NULL;
- write_unlock(&keyring->lock);
+ rcu_assign_pointer(keyring->payload.subscriptions,
+ NULL);
}
up_write(&keyring->sem);
/* free the keys after the locks have been dropped */
- if (klist) {
- for (loop = klist->nkeys - 1; loop >= 0; loop--)
- key_put(klist->keys[loop]);
-
- kfree(klist);
- }
+ if (klist)
+ call_rcu(&klist->rcu, keyring_clear_rcu_disposal);
ret = 0;
}
diff --git a/security/keys/proc.c b/security/keys/proc.c
index 91343b85c39..c55cf1fd082 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -140,7 +140,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
now = current_kernel_time();
- read_lock(&key->lock);
+ rcu_read_lock();
/* come up with a suitable timeout value */
if (key->expiry == 0) {
@@ -164,14 +164,17 @@ static int proc_keys_show(struct seq_file *m, void *v)
sprintf(xbuf, "%luw", timo / (60*60*24*7));
}
+#define showflag(KEY, LETTER, FLAG) \
+ (test_bit(FLAG, &(KEY)->flags) ? LETTER : '-')
+
seq_printf(m, "%08x %c%c%c%c%c%c %5d %4s %06x %5d %5d %-9.9s ",
key->serial,
- key->flags & KEY_FLAG_INSTANTIATED ? 'I' : '-',
- key->flags & KEY_FLAG_REVOKED ? 'R' : '-',
- key->flags & KEY_FLAG_DEAD ? 'D' : '-',
- key->flags & KEY_FLAG_IN_QUOTA ? 'Q' : '-',
- key->flags & KEY_FLAG_USER_CONSTRUCT ? 'U' : '-',
- key->flags & KEY_FLAG_NEGATIVE ? 'N' : '-',
+ showflag(key, 'I', KEY_FLAG_INSTANTIATED),
+ showflag(key, 'R', KEY_FLAG_REVOKED),
+ showflag(key, 'D', KEY_FLAG_DEAD),
+ showflag(key, 'Q', KEY_FLAG_IN_QUOTA),
+ showflag(key, 'U', KEY_FLAG_USER_CONSTRUCT),
+ showflag(key, 'N', KEY_FLAG_NEGATIVE),
atomic_read(&key->usage),
xbuf,
key->perm,
@@ -179,11 +182,13 @@ static int proc_keys_show(struct seq_file *m, void *v)
key->gid,
key->type->name);
+#undef showflag
+
if (key->type->describe)
key->type->describe(key, m);
seq_putc(m, '\n');
- read_unlock(&key->lock);
+ rcu_read_unlock();
return 0;
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 2eb0e471cd4..9b0369c5a22 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -1,6 +1,6 @@
/* process_keys.c: management of a process's keyrings
*
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
@@ -38,10 +38,9 @@ struct key root_user_keyring = {
.serial = 2,
.type = &key_type_keyring,
.user = &root_key_user,
- .lock = RW_LOCK_UNLOCKED,
.sem = __RWSEM_INITIALIZER(root_user_keyring.sem),
.perm = KEY_USR_ALL,
- .flags = KEY_FLAG_INSTANTIATED,
+ .flags = 1 << KEY_FLAG_INSTANTIATED,
.description = "_uid.0",
#ifdef KEY_DEBUGGING
.magic = KEY_DEBUG_MAGIC,
@@ -54,10 +53,9 @@ struct key root_session_keyring = {
.serial = 1,
.type = &key_type_keyring,
.user = &root_key_user,
- .lock = RW_LOCK_UNLOCKED,
.sem = __RWSEM_INITIALIZER(root_session_keyring.sem),
.perm = KEY_USR_ALL,
- .flags = KEY_FLAG_INSTANTIATED,
+ .flags = 1 << KEY_FLAG_INSTANTIATED,
.description = "_uid_ses.0",
#ifdef KEY_DEBUGGING
.magic = KEY_DEBUG_MAGIC,
@@ -167,7 +165,7 @@ int install_thread_keyring(struct task_struct *tsk)
/*
* make sure a process keyring is installed
*/
-static int install_process_keyring(struct task_struct *tsk)
+int install_process_keyring(struct task_struct *tsk)
{
unsigned long flags;
struct key *keyring;
@@ -183,7 +181,7 @@ static int install_process_keyring(struct task_struct *tsk)
goto error;
}
- /* attach or swap keyrings */
+ /* attach keyring */
spin_lock_irqsave(&tsk->sighand->siglock, flags);
if (!tsk->signal->process_keyring) {
tsk->signal->process_keyring = keyring;
@@ -229,12 +227,14 @@ static int install_session_keyring(struct task_struct *tsk,
/* install the keyring */
spin_lock_irqsave(&tsk->sighand->siglock, flags);
- old = tsk->signal->session_keyring;
- tsk->signal->session_keyring = keyring;
+ old = rcu_dereference(tsk->signal->session_keyring);
+ rcu_assign_pointer(tsk->signal->session_keyring, keyring);
spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
ret = 0;
+ /* we're using RCU on the pointer */
+ synchronize_rcu();
key_put(old);
error:
return ret;
@@ -247,8 +247,6 @@ static int install_session_keyring(struct task_struct *tsk,
*/
int copy_thread_group_keys(struct task_struct *tsk)
{
- unsigned long flags;
-
key_check(current->thread_group->session_keyring);
key_check(current->thread_group->process_keyring);
@@ -256,10 +254,10 @@ int copy_thread_group_keys(struct task_struct *tsk)
tsk->signal->process_keyring = NULL;
/* same session keyring */
- spin_lock_irqsave(&current->sighand->siglock, flags);
+ rcu_read_lock();
tsk->signal->session_keyring =
- key_get(current->signal->session_keyring);
- spin_unlock_irqrestore(&current->sighand->siglock, flags);
+ key_get(rcu_dereference(current->signal->session_keyring));
+ rcu_read_unlock();
return 0;
@@ -349,9 +347,7 @@ void key_fsuid_changed(struct task_struct *tsk)
/* update the ownership of the thread keyring */
if (tsk->thread_keyring) {
down_write(&tsk->thread_keyring->sem);
- write_lock(&tsk->thread_keyring->lock);
tsk->thread_keyring->uid = tsk->fsuid;
- write_unlock(&tsk->thread_keyring->lock);
up_write(&tsk->thread_keyring->sem);
}
@@ -366,9 +362,7 @@ void key_fsgid_changed(struct task_struct *tsk)
/* update the ownership of the thread keyring */
if (tsk->thread_keyring) {
down_write(&tsk->thread_keyring->sem);
- write_lock(&tsk->thread_keyring->lock);
tsk->thread_keyring->gid = tsk->fsgid;
- write_unlock(&tsk->thread_keyring->lock);
up_write(&tsk->thread_keyring->sem);
}
@@ -382,13 +376,13 @@ void key_fsgid_changed(struct task_struct *tsk)
* - we return -EAGAIN if we didn't find any matching key
* - we return -ENOKEY if we found only negative matching keys
*/
-struct key *search_process_keyrings_aux(struct key_type *type,
- const void *description,
- key_match_func_t match)
+struct key *search_process_keyrings(struct key_type *type,
+ const void *description,
+ key_match_func_t match,
+ struct task_struct *context)
{
- struct task_struct *tsk = current;
- unsigned long flags;
- struct key *key, *ret, *err, *tmp;
+ struct request_key_auth *rka;
+ struct key *key, *ret, *err, *instkey;
/* we want to return -EAGAIN or -ENOKEY if any of the keyrings were
* searchable, but we failed to find a key or we found a negative key;
@@ -402,9 +396,9 @@ struct key *search_process_keyrings_aux(struct key_type *type,
err = ERR_PTR(-EAGAIN);
/* search the thread keyring first */
- if (tsk->thread_keyring) {
- key = keyring_search_aux(tsk->thread_keyring, type,
- description, match);
+ if (context->thread_keyring) {
+ key = keyring_search_aux(context->thread_keyring,
+ context, type, description, match);
if (!IS_ERR(key))
goto found;
@@ -422,9 +416,9 @@ struct key *search_process_keyrings_aux(struct key_type *type,
}
/* search the process keyring second */
- if (tsk->signal->process_keyring) {
- key = keyring_search_aux(tsk->signal->process_keyring,
- type, description, match);
+ if (context->signal->process_keyring) {
+ key = keyring_search_aux(context->signal->process_keyring,
+ context, type, description, match);
if (!IS_ERR(key))
goto found;
@@ -441,52 +435,93 @@ struct key *search_process_keyrings_aux(struct key_type *type,
}
}
- /* search the session keyring last */
- spin_lock_irqsave(&tsk->sighand->siglock, flags);
+ /* search the session keyring */
+ if (context->signal->session_keyring) {
+ rcu_read_lock();
+ key = keyring_search_aux(
+ rcu_dereference(context->signal->session_keyring),
+ context, type, description, match);
+ rcu_read_unlock();
- tmp = tsk->signal->session_keyring;
- if (!tmp)
- tmp = tsk->user->session_keyring;
- atomic_inc(&tmp->usage);
+ if (!IS_ERR(key))
+ goto found;
- spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
+ switch (PTR_ERR(key)) {
+ case -EAGAIN: /* no key */
+ if (ret)
+ break;
+ case -ENOKEY: /* negative key */
+ ret = key;
+ break;
+ default:
+ err = key;
+ break;
+ }
+
+ /* if this process has a session keyring and that has an
+ * instantiation authorisation key in the bottom level, then we
+ * also search the keyrings of the process mentioned there */
+ if (context != current)
+ goto no_key;
+
+ rcu_read_lock();
+ instkey = __keyring_search_one(
+ rcu_dereference(context->signal->session_keyring),
+ &key_type_request_key_auth, NULL, 0);
+ rcu_read_unlock();
+
+ if (IS_ERR(instkey))
+ goto no_key;
+
+ rka = instkey->payload.data;
- key = keyring_search_aux(tmp, type, description, match);
- key_put(tmp);
- if (!IS_ERR(key))
- goto found;
+ key = search_process_keyrings(type, description, match,
+ rka->context);
+ key_put(instkey);
- switch (PTR_ERR(key)) {
- case -EAGAIN: /* no key */
- if (ret)
+ if (!IS_ERR(key))
+ goto found;
+
+ switch (PTR_ERR(key)) {
+ case -EAGAIN: /* no key */
+ if (ret)
+ break;
+ case -ENOKEY: /* negative key */
+ ret = key;
break;
- case -ENOKEY: /* negative key */
- ret = key;
- break;
- default:
- err = key;
- break;
+ default:
+ err = key;
+ break;
+ }
+ }
+ /* or search the user-session keyring */
+ else {
+ key = keyring_search_aux(context->user->session_keyring,
+ context, type, description, match);
+ if (!IS_ERR(key))
+ goto found;
+
+ switch (PTR_ERR(key)) {
+ case -EAGAIN: /* no key */
+ if (ret)
+ break;
+ case -ENOKEY: /* negative key */
+ ret = key;
+ break;
+ default:
+ err = key;
+ break;
+ }
}
+
+no_key:
/* no key - decide on the error we're going to go for */
key = ret ? ret : err;
- found:
+found:
return key;
-} /* end search_process_keyrings_aux() */
-
-/*****************************************************************************/
-/*
- * search the process keyrings for the first matching key
- * - we return -EAGAIN if we didn't find any matching key
- * - we return -ENOKEY if we found only negative matching keys
- */
-struct key *search_process_keyrings(struct key_type *type,
- const char *description)
-{
- return search_process_keyrings_aux(type, description, type->match);
-
} /* end search_process_keyrings() */
/*****************************************************************************/
@@ -495,72 +530,73 @@ struct key *search_process_keyrings(struct key_type *type,
* - don't create special keyrings unless so requested
* - partially constructed keys aren't found unless requested
*/
-struct key *lookup_user_key(key_serial_t id, int create, int partial,
- key_perm_t perm)
+struct key *lookup_user_key(struct task_struct *context, key_serial_t id,
+ int create, int partial, key_perm_t perm)
{
- struct task_struct *tsk = current;
- unsigned long flags;
struct key *key;
int ret;
+ if (!context)
+ context = current;
+
key = ERR_PTR(-ENOKEY);
switch (id) {
case KEY_SPEC_THREAD_KEYRING:
- if (!tsk->thread_keyring) {
+ if (!context->thread_keyring) {
if (!create)
goto error;
- ret = install_thread_keyring(tsk);
+ ret = install_thread_keyring(context);
if (ret < 0) {
key = ERR_PTR(ret);
goto error;
}
}
- key = tsk->thread_keyring;
+ key = context->thread_keyring;
atomic_inc(&key->usage);
break;
case KEY_SPEC_PROCESS_KEYRING:
- if (!tsk->signal->process_keyring) {
+ if (!context->signal->process_keyring) {
if (!create)
goto error;
- ret = install_process_keyring(tsk);
+ ret = install_process_keyring(context);
if (ret < 0) {
key = ERR_PTR(ret);
goto error;
}
}
- key = tsk->signal->process_keyring;
+ key = context->signal->process_keyring;
atomic_inc(&key->usage);
break;
case KEY_SPEC_SESSION_KEYRING:
- if (!tsk->signal->session_keyring) {
+ if (!context->signal->session_keyring) {
/* always install a session keyring upon access if one
* doesn't exist yet */
ret = install_session_keyring(
- tsk, tsk->user->session_keyring);
+ context, context->user->session_keyring);
if (ret < 0)
goto error;
}
- spin_lock_irqsave(&tsk->sighand->siglock, flags);
- key = tsk->signal->session_keyring;
+ rcu_read_lock();
+ key = rcu_dereference(context->signal->session_keyring);
atomic_inc(&key->usage);
- spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
+ rcu_read_unlock();
break;
case KEY_SPEC_USER_KEYRING:
- key = tsk->user->uid_keyring;
+ key = context->user->uid_keyring;
atomic_inc(&key->usage);
break;
case KEY_SPEC_USER_SESSION_KEYRING:
- key = tsk->user->session_keyring;
+ key = context->user->session_keyring;
atomic_inc(&key->usage);
break;
@@ -580,7 +616,7 @@ struct key *lookup_user_key(key_serial_t id, int create, int partial,
break;
}
- /* check the status and permissions */
+ /* check the status */
if (perm) {
ret = key_validate(key);
if (ret < 0)
@@ -588,11 +624,13 @@ struct key *lookup_user_key(key_serial_t id, int create, int partial,
}
ret = -EIO;
- if (!partial && !(key->flags & KEY_FLAG_INSTANTIATED))
+ if (!partial && !test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
goto invalid_key;
+ /* check the permissions */
ret = -EACCES;
- if (!key_permission(key, perm))
+
+ if (!key_task_permission(key, context, perm))
goto invalid_key;
error:
@@ -615,7 +653,6 @@ struct key *lookup_user_key(key_serial_t id, int create, int partial,
long join_session_keyring(const char *name)
{
struct task_struct *tsk = current;
- unsigned long flags;
struct key *keyring;
long ret;
@@ -625,9 +662,9 @@ long join_session_keyring(const char *name)
if (ret < 0)
goto error;
- spin_lock_irqsave(&tsk->sighand->siglock, flags);
- ret = tsk->signal->session_keyring->serial;
- spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
+ rcu_read_lock();
+ ret = rcu_dereference(tsk->signal->session_keyring)->serial;
+ rcu_read_unlock();
goto error;
}
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 9705b1aeba5..dfcd983af1f 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -1,6 +1,6 @@
/* request_key.c: request a key from userspace
*
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
@@ -13,6 +13,7 @@
#include <linux/sched.h>
#include <linux/kmod.h>
#include <linux/err.h>
+#include <linux/keyctl.h>
#include "internal.h"
struct key_construction {
@@ -27,18 +28,26 @@ DECLARE_WAIT_QUEUE_HEAD(request_key_conswq);
/*
* request userspace finish the construction of a key
* - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring> <info>"
- * - if callout_info is an empty string, it'll be rendered as a "-" instead
*/
static int call_request_key(struct key *key,
const char *op,
const char *callout_info)
{
struct task_struct *tsk = current;
- unsigned long flags;
key_serial_t prkey, sskey;
+ struct key *session_keyring, *rkakey;
char *argv[10], *envp[3], uid_str[12], gid_str[12];
char key_str[12], keyring_str[3][12];
- int i;
+ int ret, i;
+
+ kenter("{%d},%s,%s", key->serial, op, callout_info);
+
+ /* generate a new session keyring with an auth key in it */
+ session_keyring = request_key_auth_new(key, &rkakey);
+ if (IS_ERR(session_keyring)) {
+ ret = PTR_ERR(session_keyring);
+ goto error;
+ }
/* record the UID and GID */
sprintf(uid_str, "%d", current->fsuid);
@@ -55,17 +64,17 @@ static int call_request_key(struct key *key,
if (tsk->signal->process_keyring)
prkey = tsk->signal->process_keyring->serial;
- sskey = 0;
- spin_lock_irqsave(&tsk->sighand->siglock, flags);
- if (tsk->signal->session_keyring)
- sskey = tsk->signal->session_keyring->serial;
- spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
-
+ sprintf(keyring_str[1], "%d", prkey);
- if (!sskey)
+ if (tsk->signal->session_keyring) {
+ rcu_read_lock();
+ sskey = rcu_dereference(tsk->signal->session_keyring)->serial;
+ rcu_read_unlock();
+ }
+ else {
sskey = tsk->user->session_keyring->serial;
+ }
- sprintf(keyring_str[1], "%d", prkey);
sprintf(keyring_str[2], "%d", sskey);
/* set up a minimal environment */
@@ -84,11 +93,20 @@ static int call_request_key(struct key *key,
argv[i++] = keyring_str[0];
argv[i++] = keyring_str[1];
argv[i++] = keyring_str[2];
- argv[i++] = callout_info[0] ? (char *) callout_info : "-";
+ argv[i++] = (char *) callout_info;
argv[i] = NULL;
/* do it */
- return call_usermodehelper(argv[0], argv, envp, 1);
+ ret = call_usermodehelper_keys(argv[0], argv, envp, session_keyring, 1);
+
+ /* dispose of the special keys */
+ key_revoke(rkakey);
+ key_put(rkakey);
+ key_put(session_keyring);
+
+ error:
+ kleave(" = %d", ret);
+ return ret;
} /* end call_request_key() */
@@ -105,7 +123,9 @@ static struct key *__request_key_construction(struct key_type *type,
struct key_construction cons;
struct timespec now;
struct key *key;
- int ret, negative;
+ int ret, negated;
+
+ kenter("%s,%s,%s", type->name, description, callout_info);
/* create a key and add it to the queue */
key = key_alloc(type, description,
@@ -113,9 +133,7 @@ static struct key *__request_key_construction(struct key_type *type,
if (IS_ERR(key))
goto alloc_failed;
- write_lock(&key->lock);
- key->flags |= KEY_FLAG_USER_CONSTRUCT;
- write_unlock(&key->lock);
+ set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags);
cons.key = key;
list_add_tail(&cons.link, &key->user->consq);
@@ -130,7 +148,7 @@ static struct key *__request_key_construction(struct key_type *type,
/* if the key wasn't instantiated, then we want to give an error */
ret = -ENOKEY;
- if (!(key->flags & KEY_FLAG_INSTANTIATED))
+ if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
goto request_failed;
down_write(&key_construction_sem);
@@ -139,12 +157,13 @@ static struct key *__request_key_construction(struct key_type *type,
/* also give an error if the key was negatively instantiated */
check_not_negative:
- if (key->flags & KEY_FLAG_NEGATIVE) {
+ if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) {
key_put(key);
key = ERR_PTR(-ENOKEY);
}
out:
+ kleave(" = %p", key);
return key;
request_failed:
@@ -152,24 +171,23 @@ static struct key *__request_key_construction(struct key_type *type,
* - remove from construction queue
* - mark the key as dead
*/
- negative = 0;
+ negated = 0;
down_write(&key_construction_sem);
list_del(&cons.link);
- write_lock(&key->lock);
- key->flags &= ~KEY_FLAG_USER_CONSTRUCT;
-
/* check it didn't get instantiated between the check and the down */
- if (!(key->flags & KEY_FLAG_INSTANTIATED)) {
- key->flags |= KEY_FLAG_INSTANTIATED | KEY_FLAG_NEGATIVE;
- negative = 1;
+ if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
+ set_bit(KEY_FLAG_NEGATIVE, &key->flags);
+ set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
+ negated = 1;
}
- write_unlock(&key->lock);
+ clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags);
+
up_write(&key_construction_sem);
- if (!negative)
+ if (!negated)
goto check_not_negative; /* surprisingly, the key got
* instantiated */
@@ -178,13 +196,12 @@ static struct key *__request_key_construction(struct key_type *type,
key->expiry = now.tv_sec + key_negative_timeout;
if (current->signal->session_keyring) {
- unsigned long flags;
struct key *keyring;
- spin_lock_irqsave(&current->sighand->siglock, flags);
- keyring = current->signal->session_keyring;
+ rcu_read_lock();
+ keyring = rcu_dereference(current->signal->session_keyring);
atomic_inc(&keyring->usage);
- spin_unlock_irqrestore(&current->sighand->siglock, flags);
+ rcu_read_unlock();
key_link(keyring, key);
key_put(keyring);
@@ -220,6 +237,9 @@ static struct key *request_key_construction(struct key_type *type,
DECLARE_WAITQUEUE(myself, current);
+ kenter("%s,%s,{%d},%s",
+ type->name, description, user->uid, callout_info);
+
/* see if there's such a key under construction already */
down_write(&key_construction_sem);
@@ -236,6 +256,7 @@ static struct key *request_key_construction(struct key_type *type,
/* see about getting userspace to construct the key */
key = __request_key_construction(type, description, callout_info);
error:
+ kleave(" = %p", key);
return key;
/* someone else has the same key under construction
@@ -249,8 +270,10 @@ static struct key *request_key_construction(struct key_type *type,
add_wait_queue(&request_key_conswq, &myself);
for (;;) {
- set_current_state(TASK_UNINTERRUPTIBLE);
- if (!(ckey->flags & KEY_FLAG_USER_CONSTRUCT))
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (!test_bit(KEY_FLAG_USER_CONSTRUCT, &ckey->flags))
+ break;
+ if (signal_pending(current))
break;
schedule();
}
@@ -271,21 +294,83 @@ static struct key *request_key_construction(struct key_type *type,
/*****************************************************************************/
/*
+ * link a freshly minted key to an appropriate destination keyring
+ */
+static void request_key_link(struct key *key, struct key *dest_keyring)
+{
+ struct task_struct *tsk = current;
+ struct key *drop = NULL;
+
+ kenter("{%d},%p", key->serial, dest_keyring);
+
+ /* find the appropriate keyring */
+ if (!dest_keyring) {
+ switch (tsk->jit_keyring) {
+ case KEY_REQKEY_DEFL_DEFAULT:
+ case KEY_REQKEY_DEFL_THREAD_KEYRING:
+ dest_keyring = tsk->thread_keyring;
+ if (dest_keyring)
+ break;
+
+ case KEY_REQKEY_DEFL_PROCESS_KEYRING:
+ dest_keyring = tsk->signal->process_keyring;
+ if (dest_keyring)
+ break;
+
+ case KEY_REQKEY_DEFL_SESSION_KEYRING:
+ rcu_read_lock();
+ dest_keyring = key_get(
+ rcu_dereference(tsk->signal->session_keyring));
+ rcu_read_unlock();
+ drop = dest_keyring;
+
+ if (dest_keyring)
+ break;
+
+ case KEY_REQKEY_DEFL_USER_SESSION_KEYRING:
+ dest_keyring = current->user->session_keyring;
+ break;
+
+ case KEY_REQKEY_DEFL_USER_KEYRING:
+ dest_keyring = current->user->uid_keyring;
+ break;
+
+ case KEY_REQKEY_DEFL_GROUP_KEYRING:
+ default:
+ BUG();
+ }
+ }
+
+ /* and attach the key to it */
+ key_link(dest_keyring, key);
+
+ key_put(drop);
+
+ kleave("");
+
+} /* end request_key_link() */
+
+/*****************************************************************************/
+/*
* request a key
* - search the process's keyrings
* - check the list of keys being created or updated
- * - call out to userspace for a key if requested (supplementary info can be
- * passed)
+ * - call out to userspace for a key if supplementary info was provided
+ * - cache the key in an appropriate keyring
*/
-struct key *request_key(struct key_type *type,
- const char *description,
- const char *callout_info)
+struct key *request_key_and_link(struct key_type *type,
+ const char *description,
+ const char *callout_info,
+ struct key *dest_keyring)
{
struct key_user *user;
struct key *key;
+ kenter("%s,%s,%s,%p",
+ type->name, description, callout_info, dest_keyring);
+
/* search all the process keyrings for a key */
- key = search_process_keyrings_aux(type, description, type->match);
+ key = search_process_keyrings(type, description, type->match, current);
if (PTR_ERR(key) == -EAGAIN) {
/* the search failed, but the keyrings were searchable, so we
@@ -296,12 +381,13 @@ struct key *request_key(struct key_type *type,
/* - get hold of the user's construction queue */
user = key_user_lookup(current->fsuid);
- if (!user) {
- key = ERR_PTR(-ENOMEM);
- goto error;
- }
+ if (!user)
+ goto nomem;
+
+ do {
+ if (signal_pending(current))
+ goto interrupted;
- for (;;) {
/* ask userspace (returns NULL if it waited on a key
* being constructed) */
key = request_key_construction(type, description,
@@ -311,18 +397,46 @@ struct key *request_key(struct key_type *type,
/* someone else made the key we want, so we need to
* search again as it might now be available to us */
- key = search_process_keyrings_aux(type, description,
- type->match);
- if (PTR_ERR(key) != -EAGAIN)
- break;
- }
+ key = search_process_keyrings(type, description,
+ type->match, current);
+
+ } while (PTR_ERR(key) == -EAGAIN);
key_user_put(user);
+
+ /* link the new key into the appropriate keyring */
+ if (!PTR_ERR(key))
+ request_key_link(key, dest_keyring);
}
- error:
+error:
+ kleave(" = %p", key);
return key;
+nomem:
+ key = ERR_PTR(-ENOMEM);
+ goto error;
+
+interrupted:
+ key_user_put(user);
+ key = ERR_PTR(-EINTR);
+ goto error;
+
+} /* end request_key_and_link() */
+
+/*****************************************************************************/
+/*
+ * request a key
+ * - search the process's keyrings
+ * - check the list of keys being created or updated
+ * - call out to userspace for a key if supplementary info was provided
+ */
+struct key *request_key(struct key_type *type,
+ const char *description,
+ const char *callout_info)
+{
+ return request_key_and_link(type, description, callout_info, NULL);
+
} /* end request_key() */
EXPORT_SYMBOL(request_key);
@@ -339,7 +453,8 @@ int key_validate(struct key *key)
if (key) {
/* check it's still accessible */
ret = -EKEYREVOKED;
- if (key->flags & (KEY_FLAG_REVOKED | KEY_FLAG_DEAD))
+ if (test_bit(KEY_FLAG_REVOKED, &key->flags) ||
+ test_bit(KEY_FLAG_DEAD, &key->flags))
goto error;
/* check it hasn't expired */
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
new file mode 100644
index 00000000000..f2226463222
--- /dev/null
+++ b/security/keys/request_key_auth.c
@@ -0,0 +1,180 @@
+/* request_key_auth.c: request key authorisation controlling key def
+ *
+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.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.
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/seq_file.h>
+#include "internal.h"
+
+static int request_key_auth_instantiate(struct key *, const void *, size_t);
+static void request_key_auth_describe(const struct key *, struct seq_file *);
+static void request_key_auth_destroy(struct key *);
+
+/*
+ * the request-key authorisation key type definition
+ */
+struct key_type key_type_request_key_auth = {
+ .name = ".request_key_auth",
+ .def_datalen = sizeof(struct request_key_auth),
+ .instantiate = request_key_auth_instantiate,
+ .describe = request_key_auth_describe,
+ .destroy = request_key_auth_destroy,
+};
+
+/*****************************************************************************/
+/*
+ * instantiate a request-key authorisation record
+ */
+static int request_key_auth_instantiate(struct key *key,
+ const void *data,
+ size_t datalen)
+{
+ struct request_key_auth *rka, *irka;
+ struct key *instkey;
+ int ret;
+
+ ret = -ENOMEM;
+ rka = kmalloc(sizeof(*rka), GFP_KERNEL);
+ if (rka) {
+ /* see if the calling process is already servicing the key
+ * request of another process */
+ instkey = key_get_instantiation_authkey(0);
+ if (!IS_ERR(instkey)) {
+ /* it is - use that instantiation context here too */
+ irka = instkey->payload.data;
+ rka->context = irka->context;
+ rka->pid = irka->pid;
+ key_put(instkey);
+ }
+ else {
+ /* it isn't - use this process as the context */
+ rka->context = current;
+ rka->pid = current->pid;
+ }
+
+ rka->target_key = key_get((struct key *) data);
+ key->payload.data = rka;
+ ret = 0;
+ }
+
+ return ret;
+
+} /* end request_key_auth_instantiate() */
+
+/*****************************************************************************/
+/*
+ *
+ */
+static void request_key_auth_describe(const struct key *key,
+ struct seq_file *m)
+{
+ struct request_key_auth *rka = key->payload.data;
+
+ seq_puts(m, "key:");
+ seq_puts(m, key->description);
+ seq_printf(m, " pid:%d", rka->pid);
+
+} /* end request_key_auth_describe() */
+
+/*****************************************************************************/
+/*
+ * destroy an instantiation authorisation token key
+ */
+static void request_key_auth_destroy(struct key *key)
+{
+ struct request_key_auth *rka = key->payload.data;
+
+ kenter("{%d}", key->serial);
+
+ key_put(rka->target_key);
+
+} /* end request_key_auth_destroy() */
+
+/*****************************************************************************/
+/*
+ * create a session keyring to be for the invokation of /sbin/request-key and
+ * stick an authorisation token in it
+ */
+struct key *request_key_auth_new(struct key *target, struct key **_rkakey)
+{
+ struct key *keyring, *rkakey = NULL;
+ char desc[20];
+ int ret;
+
+ kenter("%d,", target->serial);
+
+ /* allocate a new session keyring */
+ sprintf(desc, "_req.%u", target->serial);
+
+ keyring = keyring_alloc(desc, current->fsuid, current->fsgid, 1, NULL);
+ if (IS_ERR(keyring)) {
+ kleave("= %ld", PTR_ERR(keyring));
+ return keyring;
+ }
+
+ /* allocate the auth key */
+ sprintf(desc, "%x", target->serial);
+
+ rkakey = key_alloc(&key_type_request_key_auth, desc,
+ current->fsuid, current->fsgid,
+ KEY_USR_VIEW, 1);
+ if (IS_ERR(rkakey)) {
+ key_put(keyring);
+ kleave("= %ld", PTR_ERR(rkakey));
+ return rkakey;
+ }
+
+ /* construct and attach to the keyring */
+ ret = key_instantiate_and_link(rkakey, target, 0, keyring, NULL);
+ if (ret < 0) {
+ key_revoke(rkakey);
+ key_put(rkakey);
+ key_put(keyring);
+ kleave("= %d", ret);
+ return ERR_PTR(ret);
+ }
+
+ *_rkakey = rkakey;
+ kleave(" = {%d} ({%d})", keyring->serial, rkakey->serial);
+ return keyring;
+
+} /* end request_key_auth_new() */
+
+/*****************************************************************************/
+/*
+ * get the authorisation key for instantiation of a specific key if attached to
+ * the current process's keyrings
+ * - this key is inserted into a keyring and that is set as /sbin/request-key's
+ * session keyring
+ * - a target_id of zero specifies any valid token
+ */
+struct key *key_get_instantiation_authkey(key_serial_t target_id)
+{
+ struct task_struct *tsk = current;
+ struct key *instkey;
+
+ /* we must have our own personal session keyring */
+ if (!tsk->signal->session_keyring)
+ return ERR_PTR(-EACCES);
+
+ /* and it must contain a suitable request authorisation key
+ * - lock RCU against session keyring changing
+ */
+ rcu_read_lock();
+
+ instkey = keyring_search_instkey(
+ rcu_dereference(tsk->signal->session_keyring), target_id);
+
+ rcu_read_unlock();
+ return instkey;
+
+} /* end key_get_instantiation_authkey() */
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
index 8d65b3a2812..e446acba73d 100644
--- a/security/keys/user_defined.c
+++ b/security/keys/user_defined.c
@@ -42,12 +42,21 @@ struct key_type key_type_user = {
.read = user_read,
};
+struct user_key_payload {
+ struct rcu_head rcu; /* RCU destructor */
+ unsigned short datalen; /* length of this data */
+ char data[0]; /* actual data */
+};
+
+EXPORT_SYMBOL_GPL(key_type_user);
+
/*****************************************************************************/
/*
* instantiate a user defined key
*/
static int user_instantiate(struct key *key, const void *data, size_t datalen)
{
+ struct user_key_payload *upayload;
int ret;
ret = -EINVAL;
@@ -58,13 +67,15 @@ static int user_instantiate(struct key *key, const void *data, size_t datalen)
if (ret < 0)
goto error;
- /* attach the data */
ret = -ENOMEM;
- key->payload.data = kmalloc(datalen, GFP_KERNEL);
- if (!key->payload.data)
+ upayload = kmalloc(sizeof(*upayload) + datalen, GFP_KERNEL);
+ if (!upayload)
goto error;
- memcpy(key->payload.data, data, datalen);
+ /* attach the data */
+ upayload->datalen = datalen;
+ memcpy(upayload->data, data, datalen);
+ rcu_assign_pointer(key->payload.data, upayload);
ret = 0;
error:
@@ -75,18 +86,25 @@ static int user_instantiate(struct key *key, const void *data, size_t datalen)
/*****************************************************************************/
/*
* duplicate a user defined key
+ * - both keys' semaphores are locked against further modification
+ * - the new key cannot yet be accessed
*/
static int user_duplicate(struct key *key, const struct key *source)
{
+ struct user_key_payload *upayload, *spayload;
int ret;
/* just copy the payload */
ret = -ENOMEM;
- key->payload.data = kmalloc(source->datalen, GFP_KERNEL);
+ upayload = kmalloc(sizeof(*upayload) + source->datalen, GFP_KERNEL);
+ if (upayload) {
+ spayload = rcu_dereference(source->payload.data);
+ BUG_ON(source->datalen != spayload->datalen);
+
+ upayload->datalen = key->datalen = spayload->datalen;
+ memcpy(upayload->data, spayload->data, key->datalen);
- if (key->payload.data) {
- key->datalen = source->datalen;
- memcpy(key->payload.data, source->payload.data, source->datalen);
+ key->payload.data = upayload;
ret = 0;
}
@@ -96,40 +114,54 @@ static int user_duplicate(struct key *key, const struct key *source)
/*****************************************************************************/
/*
+ * dispose of the old data from an updated user defined key
+ */
+static void user_update_rcu_disposal(struct rcu_head *rcu)
+{
+ struct user_key_payload *upayload;
+
+ upayload = container_of(rcu, struct user_key_payload, rcu);
+
+ kfree(upayload);
+
+} /* end user_update_rcu_disposal() */
+
+/*****************************************************************************/
+/*
* update a user defined key
+ * - the key's semaphore is write-locked
*/
static int user_update(struct key *key, const void *data, size_t datalen)
{
- void *new, *zap;
+ struct user_key_payload *upayload, *zap;
int ret;
ret = -EINVAL;
if (datalen <= 0 || datalen > 32767 || !data)
goto error;
- /* copy the data */
+ /* construct a replacement payload */
ret = -ENOMEM;
- new = kmalloc(datalen, GFP_KERNEL);
- if (!new)
+ upayload = kmalloc(sizeof(*upayload) + datalen, GFP_KERNEL);
+ if (!upayload)
goto error;
- memcpy(new, data, datalen);
+ upayload->datalen = datalen;
+ memcpy(upayload->data, data, datalen);
/* check the quota and attach the new data */
- zap = new;
- write_lock(&key->lock);
+ zap = upayload;
ret = key_payload_reserve(key, datalen);
if (ret == 0) {
/* attach the new data, displacing the old */
zap = key->payload.data;
- key->payload.data = new;
+ rcu_assign_pointer(key->payload.data, upayload);
key->expiry = 0;
}
- write_unlock(&key->lock);
- kfree(zap);
+ call_rcu(&zap->rcu, user_update_rcu_disposal);
error:
return ret;
@@ -152,13 +184,15 @@ static int user_match(const struct key *key, const void *description)
*/
static void user_destroy(struct key *key)
{
- kfree(key->payload.data);
+ struct user_key_payload *upayload = key->payload.data;
+
+ kfree(upayload);
} /* end user_destroy() */
/*****************************************************************************/
/*
- * describe the user
+ * describe the user key
*/
static void user_describe(const struct key *key, struct seq_file *m)
{
@@ -171,18 +205,23 @@ static void user_describe(const struct key *key, struct seq_file *m)
/*****************************************************************************/
/*
* read the key data
+ * - the key's semaphore is read-locked
*/
static long user_read(const struct key *key,
char __user *buffer, size_t buflen)
{
- long ret = key->datalen;
+ struct user_key_payload *upayload;
+ long ret;
+
+ upayload = rcu_dereference(key->payload.data);
+ ret = upayload->datalen;
/* we can return the data as is */
if (buffer && buflen > 0) {
- if (buflen > key->datalen)
- buflen = key->datalen;
+ if (buflen > upayload->datalen)
+ buflen = upayload->datalen;
- if (copy_to_user(buffer, key->payload.data, buflen) != 0)
+ if (copy_to_user(buffer, upayload->data, buflen) != 0)
ret = -EFAULT;
}
diff --git a/security/seclvl.c b/security/seclvl.c
index 8a0ab0d7949..c8e87b22c9b 100644
--- a/security/seclvl.c
+++ b/security/seclvl.c
@@ -155,7 +155,7 @@ seclvl_attr_store(struct kobject *kobj,
struct seclvl_obj *obj = container_of(kobj, struct seclvl_obj, kobj);
struct seclvl_attribute *attribute =
container_of(attr, struct seclvl_attribute, attr);
- return (attribute->store ? attribute->store(obj, buf, len) : 0);
+ return attribute->store ? attribute->store(obj, buf, len) : -EIO;
}
static ssize_t
@@ -164,7 +164,7 @@ seclvl_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
struct seclvl_obj *obj = container_of(kobj, struct seclvl_obj, kobj);
struct seclvl_attribute *attribute =
container_of(attr, struct seclvl_attribute, attr);
- return (attribute->show ? attribute->show(obj, buf) : 0);
+ return attribute->show ? attribute->show(obj, buf) : -EIO;
}
/**
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 85a6f66a873..451502467a9 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -242,7 +242,7 @@ void __init avc_init(void)
avc_node_cachep = kmem_cache_create("avc_node", sizeof(struct avc_node),
0, SLAB_PANIC, NULL, NULL);
- audit_log(current->audit_context, "AVC INITIALIZED\n");
+ audit_log(current->audit_context, AUDIT_KERNEL, "AVC INITIALIZED\n");
}
int avc_get_hash_stats(char *page)
@@ -532,6 +532,7 @@ void avc_audit(u32 ssid, u32 tsid,
u16 tclass, u32 requested,
struct av_decision *avd, int result, struct avc_audit_data *a)
{
+ struct task_struct *tsk = current;
struct inode *inode = NULL;
u32 denied, audited;
struct audit_buffer *ab;
@@ -549,12 +550,18 @@ void avc_audit(u32 ssid, u32 tsid,
return;
}
- ab = audit_log_start(current->audit_context);
+ ab = audit_log_start(current->audit_context, AUDIT_AVC);
if (!ab)
return; /* audit_panic has been called */
audit_log_format(ab, "avc: %s ", denied ? "denied" : "granted");
avc_dump_av(ab, tclass,audited);
audit_log_format(ab, " for ");
+ if (a && a->tsk)
+ tsk = a->tsk;
+ if (tsk && tsk->pid) {
+ audit_log_format(ab, " pid=%d comm=", tsk->pid);
+ audit_log_untrustedstring(ab, tsk->comm);
+ }
if (a) {
switch (a->type) {
case AVC_AUDIT_DATA_IPC:
@@ -566,21 +573,18 @@ void avc_audit(u32 ssid, u32 tsid,
case AVC_AUDIT_DATA_FS:
if (a->u.fs.dentry) {
struct dentry *dentry = a->u.fs.dentry;
- if (a->u.fs.mnt) {
- audit_log_d_path(ab, "path=", dentry,
- a->u.fs.mnt);
- } else {
- audit_log_format(ab, " name=%s",
- dentry->d_name.name);
- }
+ if (a->u.fs.mnt)
+ audit_avc_path(dentry, a->u.fs.mnt);
+ audit_log_format(ab, " name=");
+ audit_log_untrustedstring(ab, dentry->d_name.name);
inode = dentry->d_inode;
} else if (a->u.fs.inode) {
struct dentry *dentry;
inode = a->u.fs.inode;
dentry = d_find_alias(inode);
if (dentry) {
- audit_log_format(ab, " name=%s",
- dentry->d_name.name);
+ audit_log_format(ab, " name=");
+ audit_log_untrustedstring(ab, dentry->d_name.name);
dput(dentry);
}
}
@@ -623,22 +627,20 @@ void avc_audit(u32 ssid, u32 tsid,
case AF_UNIX:
u = unix_sk(sk);
if (u->dentry) {
- audit_log_d_path(ab, "path=",
- u->dentry, u->mnt);
+ audit_avc_path(u->dentry, u->mnt);
+ audit_log_format(ab, " name=");
+ audit_log_untrustedstring(ab, u->dentry->d_name.name);
break;
}
if (!u->addr)
break;
len = u->addr->len-sizeof(short);
p = &u->addr->name->sun_path[0];
+ audit_log_format(ab, " path=");
if (*p)
- audit_log_format(ab,
- "path=%*.*s", len,
- len, p);
+ audit_log_untrustedstring(ab, p);
else
- audit_log_format(ab,
- "path=@%*.*s", len-1,
- len-1, p+1);
+ audit_log_hex(ab, p, len);
break;
}
}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index aae1e794fe4..17a1189f1ff 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1658,9 +1658,8 @@ static int selinux_bprm_secureexec (struct linux_binprm *bprm)
static void selinux_bprm_free_security(struct linux_binprm *bprm)
{
- struct bprm_security_struct *bsec = bprm->security;
+ kfree(bprm->security);
bprm->security = NULL;
- kfree(bsec);
}
extern struct vfsmount *selinuxfs_mount;
@@ -1945,6 +1944,7 @@ static int selinux_sb_copy_data(struct file_system_type *type, void *orig, void
} while (*in_end++);
copy_page(in_save, nosec_save);
+ free_page((unsigned long)nosec_save);
out:
return rc;
}
@@ -2476,6 +2476,17 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
prot = reqprot;
#ifndef CONFIG_PPC32
+ if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXECUTABLE) &&
+ (vma->vm_start >= vma->vm_mm->start_brk &&
+ vma->vm_end <= vma->vm_mm->brk)) {
+ /*
+ * We are making an executable mapping in the brk region.
+ * This has an additional execheap check.
+ */
+ rc = task_has_perm(current, current, PROCESS__EXECHEAP);
+ if (rc)
+ return rc;
+ }
if (vma->vm_file != NULL && vma->anon_vma != NULL && (prot & PROT_EXEC)) {
/*
* We are making executable a file mapping that has
@@ -2487,6 +2498,16 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
if (rc)
return rc;
}
+ if (!vma->vm_file && (prot & PROT_EXEC) &&
+ vma->vm_start <= vma->vm_mm->start_stack &&
+ vma->vm_end >= vma->vm_mm->start_stack) {
+ /* Attempt to make the process stack executable.
+ * This has an additional execstack check.
+ */
+ rc = task_has_perm(current, current, PROCESS__EXECSTACK);
+ if (rc)
+ return rc;
+ }
#endif
return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
@@ -3419,7 +3440,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm);
if (err) {
if (err == -EINVAL) {
- audit_log(current->audit_context,
+ audit_log(current->audit_context, AUDIT_SELINUX_ERR,
"SELinux: unrecognized netlink message"
" type=%hu for sclass=%hu\n",
nlh->nlmsg_type, isec->sclass);
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
index 8928bb4d3c5..1deb59e1b76 100644
--- a/security/selinux/include/av_perm_to_string.h
+++ b/security/selinux/include/av_perm_to_string.h
@@ -70,6 +70,8 @@
S_(SECCLASS_PROCESS, PROCESS__DYNTRANSITION, "dyntransition")
S_(SECCLASS_PROCESS, PROCESS__SETCURRENT, "setcurrent")
S_(SECCLASS_PROCESS, PROCESS__EXECMEM, "execmem")
+ S_(SECCLASS_PROCESS, PROCESS__EXECSTACK, "execstack")
+ S_(SECCLASS_PROCESS, PROCESS__EXECHEAP, "execheap")
S_(SECCLASS_MSGQ, MSGQ__ENQUEUE, "enqueue")
S_(SECCLASS_MSG, MSG__SEND, "send")
S_(SECCLASS_MSG, MSG__RECEIVE, "receive")
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
index bdfce4ca8f8..a78b5d59c9f 100644
--- a/security/selinux/include/av_permissions.h
+++ b/security/selinux/include/av_permissions.h
@@ -465,6 +465,8 @@
#define PROCESS__DYNTRANSITION 0x00800000UL
#define PROCESS__SETCURRENT 0x01000000UL
#define PROCESS__EXECMEM 0x02000000UL
+#define PROCESS__EXECSTACK 0x04000000UL
+#define PROCESS__EXECHEAP 0x08000000UL
#define IPC__CREATE 0x00000001UL
#define IPC__DESTROY 0x00000002UL
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index b3adb481bc2..92b057becb4 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -63,6 +63,8 @@ static struct nlmsg_perm nlmsg_route_perms[] =
{ RTM_GETPREFIX, NETLINK_ROUTE_SOCKET__NLMSG_READ },
{ RTM_GETMULTICAST, NETLINK_ROUTE_SOCKET__NLMSG_READ },
{ RTM_GETANYCAST, NETLINK_ROUTE_SOCKET__NLMSG_READ },
+ { RTM_GETNEIGHTBL, NETLINK_ROUTE_SOCKET__NLMSG_READ },
+ { RTM_SETNEIGHTBL, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
};
static struct nlmsg_perm nlmsg_firewall_perms[] =
@@ -97,6 +99,7 @@ static struct nlmsg_perm nlmsg_audit_perms[] =
{ AUDIT_ADD, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
{ AUDIT_DEL, NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
{ AUDIT_USER, NETLINK_AUDIT_SOCKET__NLMSG_RELAY },
+ { AUDIT_SIGNAL_INFO, NETLINK_AUDIT_SOCKET__NLMSG_READ },
};
@@ -141,8 +144,13 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm)
break;
case SECCLASS_NETLINK_AUDIT_SOCKET:
- err = nlmsg_perm(nlmsg_type, perm, nlmsg_audit_perms,
- sizeof(nlmsg_audit_perms));
+ if (nlmsg_type >= AUDIT_FIRST_USER_MSG &&
+ nlmsg_type <= AUDIT_LAST_USER_MSG) {
+ *perm = NETLINK_AUDIT_SOCKET__NLMSG_RELAY;
+ } else {
+ err = nlmsg_perm(nlmsg_type, perm, nlmsg_audit_perms,
+ sizeof(nlmsg_audit_perms));
+ }
break;
/* No messaging from userspace, or class unknown/unhandled */
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 07221568b50..8eb140dd2e4 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -951,8 +951,7 @@ static int sel_make_bools(void)
u32 sid;
/* remove any existing files */
- if (bool_pending_values)
- kfree(bool_pending_values);
+ kfree(bool_pending_values);
sel_remove_bools(dir);
@@ -997,10 +996,8 @@ static int sel_make_bools(void)
out:
free_page((unsigned long)page);
if (names) {
- for (i = 0; i < num; i++) {
- if (names[i])
- kfree(names[i]);
- }
+ for (i = 0; i < num; i++)
+ kfree(names[i]);
kfree(names);
}
return ret;
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
index b53441184ac..e2057f5a411 100644
--- a/security/selinux/ss/conditional.c
+++ b/security/selinux/ss/conditional.c
@@ -166,16 +166,14 @@ static void cond_list_destroy(struct cond_node *list)
void cond_policydb_destroy(struct policydb *p)
{
- if (p->bool_val_to_struct != NULL)
- kfree(p->bool_val_to_struct);
+ kfree(p->bool_val_to_struct);
avtab_destroy(&p->te_cond_avtab);
cond_list_destroy(p->cond_list);
}
int cond_init_bool_indexes(struct policydb *p)
{
- if (p->bool_val_to_struct)
- kfree(p->bool_val_to_struct);
+ kfree(p->bool_val_to_struct);
p->bool_val_to_struct = (struct cond_bool_datum**)
kmalloc(p->p_bools.nprim * sizeof(struct cond_bool_datum*), GFP_KERNEL);
if (!p->bool_val_to_struct)
@@ -185,8 +183,7 @@ int cond_init_bool_indexes(struct policydb *p)
int cond_destroy_bool(void *key, void *datum, void *p)
{
- if (key)
- kfree(key);
+ kfree(key);
kfree(datum);
return 0;
}
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 14190efbf33..785c33cf486 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -590,17 +590,12 @@ void policydb_destroy(struct policydb *p)
hashtab_destroy(p->symtab[i].table);
}
- for (i = 0; i < SYM_NUM; i++) {
- if (p->sym_val_to_name[i])
- kfree(p->sym_val_to_name[i]);
- }
+ for (i = 0; i < SYM_NUM; i++)
+ kfree(p->sym_val_to_name[i]);
- if (p->class_val_to_struct)
- kfree(p->class_val_to_struct);
- if (p->role_val_to_struct)
- kfree(p->role_val_to_struct);
- if (p->user_val_to_struct)
- kfree(p->user_val_to_struct);
+ kfree(p->class_val_to_struct);
+ kfree(p->role_val_to_struct);
+ kfree(p->user_val_to_struct);
avtab_destroy(&p->te_avtab);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 5a820cf88c9..922bb45054a 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -365,7 +365,7 @@ static int security_validtrans_handle_fail(struct context *ocontext,
goto out;
if (context_struct_to_string(tcontext, &t, &tlen) < 0)
goto out;
- audit_log(current->audit_context,
+ audit_log(current->audit_context, AUDIT_SELINUX_ERR,
"security_validate_transition: denied for"
" oldcontext=%s newcontext=%s taskcontext=%s tclass=%s",
o, n, t, policydb.p_class_val_to_name[tclass-1]);
@@ -476,8 +476,8 @@ int security_compute_av(u32 ssid,
int rc = 0;
if (!ss_initialized) {
- avd->allowed = requested;
- avd->decided = requested;
+ avd->allowed = 0xffffffff;
+ avd->decided = 0xffffffff;
avd->auditallow = 0;
avd->auditdeny = 0xffffffff;
avd->seqno = latest_granting;
@@ -742,7 +742,7 @@ static int compute_sid_handle_invalid_context(
goto out;
if (context_struct_to_string(newcontext, &n, &nlen) < 0)
goto out;
- audit_log(current->audit_context,
+ audit_log(current->audit_context, AUDIT_SELINUX_ERR,
"security_compute_sid: invalid context %s"
" for scontext=%s"
" tcontext=%s"
@@ -1196,9 +1196,11 @@ int security_load_policy(void *data, size_t len)
}
policydb_loaded_version = policydb.policyvers;
ss_initialized = 1;
-
+ seqno = ++latest_granting;
LOAD_UNLOCK;
selinux_complete_init();
+ avc_ss_reset(seqno);
+ selnl_notify_policyload(seqno);
return 0;
}
@@ -1703,11 +1705,9 @@ out:
err:
if (*names) {
for (i = 0; i < *len; i++)
- if ((*names)[i])
- kfree((*names)[i]);
+ kfree((*names)[i]);
}
- if (*values)
- kfree(*values);
+ kfree(*values);
goto out;
}
diff --git a/sound/Kconfig b/sound/Kconfig
index 047d59ea057..ee794ae0604 100644
--- a/sound/Kconfig
+++ b/sound/Kconfig
@@ -42,6 +42,11 @@ menu "Advanced Linux Sound Architecture"
config SND
tristate "Advanced Linux Sound Architecture"
depends on SOUND
+ help
+ Say 'Y' or 'M' to enable ALSA (Advanced Linux Sound Architecture),
+ the new base sound system.
+
+ For more information, see <http://www.alsa-project.org/>
source "sound/core/Kconfig"
diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig
index cdacf4d3a38..34c1740aa6e 100644
--- a/sound/arm/Kconfig
+++ b/sound/arm/Kconfig
@@ -14,5 +14,11 @@ config SND_SA11XX_UDA1341
To compile this driver as a module, choose M here: the module
will be called snd-sa11xx-uda1341.
+config SND_ARMAACI
+ tristate "ARM PrimeCell PL041 AC Link support"
+ depends on SND && ARM_AMBA
+ select SND_PCM
+ select SND_AC97_CODEC
+
endmenu
diff --git a/sound/arm/Makefile b/sound/arm/Makefile
index d7e7dc0c3cd..f74ec28e106 100644
--- a/sound/arm/Makefile
+++ b/sound/arm/Makefile
@@ -6,3 +6,6 @@ snd-sa11xx-uda1341-objs := sa11xx-uda1341.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-sa11xx-uda1341.o
+
+obj-$(CONFIG_SND_ARMAACI) += snd-aaci.o
+snd-aaci-objs := aaci.o devdma.o
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
new file mode 100644
index 00000000000..08cc3ddca96
--- /dev/null
+++ b/sound/arm/aaci.c
@@ -0,0 +1,968 @@
+/*
+ * linux/sound/arm/aaci.c - ARM PrimeCell AACI PL041 driver
+ *
+ * Copyright (C) 2003 Deep Blue Solutions Ltd, 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 version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Documentation: ARM DDI 0173B
+ */
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/hardware/amba.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/ac97_codec.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+
+#include "aaci.h"
+#include "devdma.h"
+
+#define DRIVER_NAME "aaci-pl041"
+
+/*
+ * PM support is not complete. Turn it off.
+ */
+#undef CONFIG_PM
+
+static void aaci_ac97_select_codec(struct aaci *aaci, ac97_t *ac97)
+{
+ u32 v, maincr = aaci->maincr | MAINCR_SCRA(ac97->num);
+
+ /*
+ * Ensure that the slot 1/2 RX registers are empty.
+ */
+ v = readl(aaci->base + AACI_SLFR);
+ if (v & SLFR_2RXV)
+ readl(aaci->base + AACI_SL2RX);
+ if (v & SLFR_1RXV)
+ readl(aaci->base + AACI_SL1RX);
+
+ writel(maincr, aaci->base + AACI_MAINCR);
+}
+
+/*
+ * P29:
+ * The recommended use of programming the external codec through slot 1
+ * and slot 2 data is to use the channels during setup routines and the
+ * slot register at any other time. The data written into slot 1, slot 2
+ * and slot 12 registers is transmitted only when their corresponding
+ * SI1TxEn, SI2TxEn and SI12TxEn bits are set in the AACI_MAINCR
+ * register.
+ */
+static void aaci_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
+{
+ struct aaci *aaci = ac97->private_data;
+ u32 v;
+
+ if (ac97->num >= 4)
+ return;
+
+ down(&aaci->ac97_sem);
+
+ aaci_ac97_select_codec(aaci, ac97);
+
+ /*
+ * P54: You must ensure that AACI_SL2TX is always written
+ * to, if required, before data is written to AACI_SL1TX.
+ */
+ writel(val << 4, aaci->base + AACI_SL2TX);
+ writel(reg << 12, aaci->base + AACI_SL1TX);
+
+ /*
+ * Wait for the transmission of both slots to complete.
+ */
+ do {
+ v = readl(aaci->base + AACI_SLFR);
+ } while (v & (SLFR_1TXB|SLFR_2TXB));
+
+ up(&aaci->ac97_sem);
+}
+
+/*
+ * Read an AC'97 register.
+ */
+static unsigned short aaci_ac97_read(ac97_t *ac97, unsigned short reg)
+{
+ struct aaci *aaci = ac97->private_data;
+ u32 v;
+
+ if (ac97->num >= 4)
+ return ~0;
+
+ down(&aaci->ac97_sem);
+
+ aaci_ac97_select_codec(aaci, ac97);
+
+ /*
+ * Write the register address to slot 1.
+ */
+ writel((reg << 12) | (1 << 19), aaci->base + AACI_SL1TX);
+
+ /*
+ * Wait for the transmission to complete.
+ */
+ do {
+ v = readl(aaci->base + AACI_SLFR);
+ } while (v & SLFR_1TXB);
+
+ /*
+ * Give the AC'97 codec more than enough time
+ * to respond. (42us = ~2 frames at 48kHz.)
+ */
+ udelay(42);
+
+ /*
+ * Wait for slot 2 to indicate data.
+ */
+ do {
+ cond_resched();
+ v = readl(aaci->base + AACI_SLFR) & (SLFR_1RXV|SLFR_2RXV);
+ } while (v != (SLFR_1RXV|SLFR_2RXV));
+
+ v = readl(aaci->base + AACI_SL1RX) >> 12;
+ if (v == reg) {
+ v = readl(aaci->base + AACI_SL2RX) >> 4;
+ } else {
+ dev_err(&aaci->dev->dev,
+ "wrong ac97 register read back (%x != %x)\n",
+ v, reg);
+ v = ~0;
+ }
+
+ up(&aaci->ac97_sem);
+ return v;
+}
+
+static inline void aaci_chan_wait_ready(struct aaci_runtime *aacirun)
+{
+ u32 val;
+ int timeout = 5000;
+
+ do {
+ val = readl(aacirun->base + AACI_SR);
+ } while (val & (SR_TXB|SR_RXB) && timeout--);
+}
+
+
+
+/*
+ * Interrupt support.
+ */
+static void aaci_fifo_irq(struct aaci *aaci, u32 mask)
+{
+ if (mask & ISR_URINTR) {
+ writel(ICLR_TXUEC1, aaci->base + AACI_INTCLR);
+ }
+
+ if (mask & ISR_TXINTR) {
+ struct aaci_runtime *aacirun = &aaci->playback;
+ void *ptr;
+
+ if (!aacirun->substream || !aacirun->start) {
+ dev_warn(&aaci->dev->dev, "TX interrupt???");
+ writel(0, aacirun->base + AACI_IE);
+ return;
+ }
+
+ ptr = aacirun->ptr;
+ do {
+ unsigned int len = aacirun->fifosz;
+ u32 val;
+
+ if (aacirun->bytes <= 0) {
+ aacirun->bytes += aacirun->period;
+ aacirun->ptr = ptr;
+ spin_unlock(&aaci->lock);
+ snd_pcm_period_elapsed(aacirun->substream);
+ spin_lock(&aaci->lock);
+ }
+ if (!(aacirun->cr & TXCR_TXEN))
+ break;
+
+ val = readl(aacirun->base + AACI_SR);
+ if (!(val & SR_TXHE))
+ break;
+ if (!(val & SR_TXFE))
+ len >>= 1;
+
+ aacirun->bytes -= len;
+
+ /* writing 16 bytes at a time */
+ for ( ; len > 0; len -= 16) {
+ asm(
+ "ldmia %0!, {r0, r1, r2, r3}\n\t"
+ "stmia %1, {r0, r1, r2, r3}"
+ : "+r" (ptr)
+ : "r" (aacirun->fifo)
+ : "r0", "r1", "r2", "r3", "cc");
+
+ if (ptr >= aacirun->end)
+ ptr = aacirun->start;
+ }
+ } while (1);
+
+ aacirun->ptr = ptr;
+ }
+}
+
+static irqreturn_t aaci_irq(int irq, void *devid, struct pt_regs *regs)
+{
+ struct aaci *aaci = devid;
+ u32 mask;
+ int i;
+
+ spin_lock(&aaci->lock);
+ mask = readl(aaci->base + AACI_ALLINTS);
+ if (mask) {
+ u32 m = mask;
+ for (i = 0; i < 4; i++, m >>= 7) {
+ if (m & 0x7f) {
+ aaci_fifo_irq(aaci, m);
+ }
+ }
+ }
+ spin_unlock(&aaci->lock);
+
+ return mask ? IRQ_HANDLED : IRQ_NONE;
+}
+
+
+
+/*
+ * ALSA support.
+ */
+
+struct aaci_stream {
+ unsigned char codec_idx;
+ unsigned char rate_idx;
+};
+
+static struct aaci_stream aaci_streams[] = {
+ [ACSTREAM_FRONT] = {
+ .codec_idx = 0,
+ .rate_idx = AC97_RATES_FRONT_DAC,
+ },
+ [ACSTREAM_SURROUND] = {
+ .codec_idx = 0,
+ .rate_idx = AC97_RATES_SURR_DAC,
+ },
+ [ACSTREAM_LFE] = {
+ .codec_idx = 0,
+ .rate_idx = AC97_RATES_LFE_DAC,
+ },
+};
+
+static inline unsigned int aaci_rate_mask(struct aaci *aaci, int streamid)
+{
+ struct aaci_stream *s = aaci_streams + streamid;
+ return aaci->ac97_bus->codec[s->codec_idx]->rates[s->rate_idx];
+}
+
+static unsigned int rate_list[] = {
+ 5512, 8000, 11025, 16000, 22050, 32000, 44100,
+ 48000, 64000, 88200, 96000, 176400, 192000
+};
+
+/*
+ * Double-rate rule: we can support double rate iff channels == 2
+ * (unimplemented)
+ */
+static int
+aaci_rule_rate_by_channels(snd_pcm_hw_params_t *p, snd_pcm_hw_rule_t *rule)
+{
+ struct aaci *aaci = rule->private;
+ unsigned int rate_mask = SNDRV_PCM_RATE_8000_48000|SNDRV_PCM_RATE_5512;
+ snd_interval_t *c = hw_param_interval(p, SNDRV_PCM_HW_PARAM_CHANNELS);
+
+ switch (c->max) {
+ case 6:
+ rate_mask &= aaci_rate_mask(aaci, ACSTREAM_LFE);
+ case 4:
+ rate_mask &= aaci_rate_mask(aaci, ACSTREAM_SURROUND);
+ case 2:
+ rate_mask &= aaci_rate_mask(aaci, ACSTREAM_FRONT);
+ }
+
+ return snd_interval_list(hw_param_interval(p, rule->var),
+ ARRAY_SIZE(rate_list), rate_list,
+ rate_mask);
+}
+
+static snd_pcm_hardware_t aaci_hw_info = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_RESUME,
+
+ /*
+ * ALSA doesn't support 18-bit or 20-bit packed into 32-bit
+ * words. It also doesn't support 12-bit at all.
+ */
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+
+ /* should this be continuous or knot? */
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .rate_max = 48000,
+ .rate_min = 4000,
+ .channels_min = 2,
+ .channels_max = 6,
+ .buffer_bytes_max = 64 * 1024,
+ .period_bytes_min = 256,
+ .period_bytes_max = PAGE_SIZE,
+ .periods_min = 4,
+ .periods_max = PAGE_SIZE / 16,
+};
+
+static int aaci_pcm_open(struct aaci *aaci, snd_pcm_substream_t *substream,
+ struct aaci_runtime *aacirun)
+{
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ int ret;
+
+ aacirun->substream = substream;
+ runtime->private_data = aacirun;
+ runtime->hw = aaci_hw_info;
+
+ /*
+ * FIXME: ALSA specifies fifo_size in bytes. If we're in normal
+ * mode, each 32-bit word contains one sample. If we're in
+ * compact mode, each 32-bit word contains two samples, effectively
+ * halving the FIFO size. However, we don't know for sure which
+ * we'll be using at this point. We set this to the lower limit.
+ */
+ runtime->hw.fifo_size = aaci->fifosize * 2;
+
+ /*
+ * Add rule describing hardware rate dependency
+ * on the number of channels.
+ */
+ ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+ aaci_rule_rate_by_channels, aaci,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ SNDRV_PCM_HW_PARAM_RATE, -1);
+ if (ret)
+ goto out;
+
+ ret = request_irq(aaci->dev->irq[0], aaci_irq, SA_SHIRQ|SA_INTERRUPT,
+ DRIVER_NAME, aaci);
+ if (ret)
+ goto out;
+
+ return 0;
+
+ out:
+ return ret;
+}
+
+
+/*
+ * Common ALSA stuff
+ */
+static int aaci_pcm_close(snd_pcm_substream_t *substream)
+{
+ struct aaci *aaci = substream->private_data;
+ struct aaci_runtime *aacirun = substream->runtime->private_data;
+
+ WARN_ON(aacirun->cr & TXCR_TXEN);
+
+ aacirun->substream = NULL;
+ free_irq(aaci->dev->irq[0], aaci);
+
+ return 0;
+}
+
+static int aaci_pcm_hw_free(snd_pcm_substream_t *substream)
+{
+ struct aaci_runtime *aacirun = substream->runtime->private_data;
+
+ /*
+ * This must not be called with the device enabled.
+ */
+ WARN_ON(aacirun->cr & TXCR_TXEN);
+
+ if (aacirun->pcm_open)
+ snd_ac97_pcm_close(aacirun->pcm);
+ aacirun->pcm_open = 0;
+
+ /*
+ * Clear out the DMA and any allocated buffers.
+ */
+ devdma_hw_free(NULL, substream);
+
+ return 0;
+}
+
+static int aaci_pcm_hw_params(snd_pcm_substream_t *substream,
+ struct aaci_runtime *aacirun,
+ snd_pcm_hw_params_t *params)
+{
+ int err;
+
+ aaci_pcm_hw_free(substream);
+
+ err = devdma_hw_alloc(NULL, substream,
+ params_buffer_bytes(params));
+ if (err < 0)
+ goto out;
+
+ err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params),
+ params_channels(params),
+ aacirun->pcm->r[0].slots);
+ if (err)
+ goto out;
+
+ aacirun->pcm_open = 1;
+
+ out:
+ return err;
+}
+
+static int aaci_pcm_prepare(snd_pcm_substream_t *substream)
+{
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ struct aaci_runtime *aacirun = runtime->private_data;
+
+ aacirun->start = (void *)runtime->dma_area;
+ aacirun->end = aacirun->start + runtime->dma_bytes;
+ aacirun->ptr = aacirun->start;
+ aacirun->period =
+ aacirun->bytes = frames_to_bytes(runtime, runtime->period_size);
+
+ return 0;
+}
+
+static snd_pcm_uframes_t aaci_pcm_pointer(snd_pcm_substream_t *substream)
+{
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ struct aaci_runtime *aacirun = runtime->private_data;
+ ssize_t bytes = aacirun->ptr - aacirun->start;
+
+ return bytes_to_frames(runtime, bytes);
+}
+
+static int aaci_pcm_mmap(snd_pcm_substream_t *substream, struct vm_area_struct *vma)
+{
+ return devdma_mmap(NULL, substream, vma);
+}
+
+
+/*
+ * Playback specific ALSA stuff
+ */
+static const u32 channels_to_txmask[] = {
+ [2] = TXCR_TX3 | TXCR_TX4,
+ [4] = TXCR_TX3 | TXCR_TX4 | TXCR_TX7 | TXCR_TX8,
+ [6] = TXCR_TX3 | TXCR_TX4 | TXCR_TX7 | TXCR_TX8 | TXCR_TX6 | TXCR_TX9,
+};
+
+/*
+ * We can support two and four channel audio. Unfortunately
+ * six channel audio requires a non-standard channel ordering:
+ * 2 -> FL(3), FR(4)
+ * 4 -> FL(3), FR(4), SL(7), SR(8)
+ * 6 -> FL(3), FR(4), SL(7), SR(8), C(6), LFE(9) (required)
+ * FL(3), FR(4), C(6), SL(7), SR(8), LFE(9) (actual)
+ * This requires an ALSA configuration file to correct.
+ */
+static unsigned int channel_list[] = { 2, 4, 6 };
+
+static int
+aaci_rule_channels(snd_pcm_hw_params_t *p, snd_pcm_hw_rule_t *rule)
+{
+ struct aaci *aaci = rule->private;
+ unsigned int chan_mask = 1 << 0, slots;
+
+ /*
+ * pcms[0] is the our 5.1 PCM instance.
+ */
+ slots = aaci->ac97_bus->pcms[0].r[0].slots;
+ if (slots & (1 << AC97_SLOT_PCM_SLEFT)) {
+ chan_mask |= 1 << 1;
+ if (slots & (1 << AC97_SLOT_LFE))
+ chan_mask |= 1 << 2;
+ }
+
+ return snd_interval_list(hw_param_interval(p, rule->var),
+ ARRAY_SIZE(channel_list), channel_list,
+ chan_mask);
+}
+
+static int aaci_pcm_playback_open(snd_pcm_substream_t *substream)
+{
+ struct aaci *aaci = substream->private_data;
+ int ret;
+
+ /*
+ * Add rule describing channel dependency.
+ */
+ ret = snd_pcm_hw_rule_add(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ aaci_rule_channels, aaci,
+ SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+ if (ret)
+ return ret;
+
+ return aaci_pcm_open(aaci, substream, &aaci->playback);
+}
+
+static int aaci_pcm_playback_hw_params(snd_pcm_substream_t *substream,
+ snd_pcm_hw_params_t *params)
+{
+ struct aaci *aaci = substream->private_data;
+ struct aaci_runtime *aacirun = substream->runtime->private_data;
+ unsigned int channels = params_channels(params);
+ int ret;
+
+ WARN_ON(channels >= ARRAY_SIZE(channels_to_txmask) ||
+ !channels_to_txmask[channels]);
+
+ ret = aaci_pcm_hw_params(substream, aacirun, params);
+
+ /*
+ * Enable FIFO, compact mode, 16 bits per sample.
+ * FIXME: double rate slots?
+ */
+ if (ret >= 0) {
+ aacirun->cr = TXCR_FEN | TXCR_COMPACT | TXCR_TSZ16;
+ aacirun->cr |= channels_to_txmask[channels];
+
+ aacirun->fifosz = aaci->fifosize * 4;
+ if (aacirun->cr & TXCR_COMPACT)
+ aacirun->fifosz >>= 1;
+ }
+ return ret;
+}
+
+static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun)
+{
+ u32 ie;
+
+ ie = readl(aacirun->base + AACI_IE);
+ ie &= ~(IE_URIE|IE_TXIE);
+ writel(ie, aacirun->base + AACI_IE);
+ aacirun->cr &= ~TXCR_TXEN;
+ aaci_chan_wait_ready(aacirun);
+ writel(aacirun->cr, aacirun->base + AACI_TXCR);
+}
+
+static void aaci_pcm_playback_start(struct aaci_runtime *aacirun)
+{
+ u32 ie;
+
+ aaci_chan_wait_ready(aacirun);
+ aacirun->cr |= TXCR_TXEN;
+
+ ie = readl(aacirun->base + AACI_IE);
+ ie |= IE_URIE | IE_TXIE;
+ writel(ie, aacirun->base + AACI_IE);
+ writel(aacirun->cr, aacirun->base + AACI_TXCR);
+}
+
+static int aaci_pcm_playback_trigger(snd_pcm_substream_t *substream, int cmd)
+{
+ struct aaci *aaci = substream->private_data;
+ struct aaci_runtime *aacirun = substream->runtime->private_data;
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&aaci->lock, flags);
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ aaci_pcm_playback_start(aacirun);
+ break;
+
+ case SNDRV_PCM_TRIGGER_RESUME:
+ aaci_pcm_playback_start(aacirun);
+ break;
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ aaci_pcm_playback_stop(aacirun);
+ break;
+
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ aaci_pcm_playback_stop(aacirun);
+ break;
+
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ break;
+
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ break;
+
+ default:
+ ret = -EINVAL;
+ }
+ spin_unlock_irqrestore(&aaci->lock, flags);
+
+ return ret;
+}
+
+static snd_pcm_ops_t aaci_playback_ops = {
+ .open = aaci_pcm_playback_open,
+ .close = aaci_pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = aaci_pcm_playback_hw_params,
+ .hw_free = aaci_pcm_hw_free,
+ .prepare = aaci_pcm_prepare,
+ .trigger = aaci_pcm_playback_trigger,
+ .pointer = aaci_pcm_pointer,
+ .mmap = aaci_pcm_mmap,
+};
+
+
+
+/*
+ * Power Management.
+ */
+#ifdef CONFIG_PM
+static int aaci_do_suspend(snd_card_t *card, unsigned int state)
+{
+ struct aaci *aaci = card->private_data;
+ if (aaci->card->power_state != SNDRV_CTL_POWER_D3cold) {
+ snd_pcm_suspend_all(aaci->pcm);
+ snd_power_change_state(aaci->card, SNDRV_CTL_POWER_D3cold);
+ }
+ return 0;
+}
+
+static int aaci_do_resume(snd_card_t *card, unsigned int state)
+{
+ struct aaci *aaci = card->private_data;
+ if (aaci->card->power_state != SNDRV_CTL_POWER_D0) {
+ snd_power_change_state(aaci->card, SNDRV_CTL_POWER_D0);
+ }
+ return 0;
+}
+
+static int aaci_suspend(struct amba_device *dev, u32 state)
+{
+ snd_card_t *card = amba_get_drvdata(dev);
+ return card ? aaci_do_suspend(card) : 0;
+}
+
+static int aaci_resume(struct amba_device *dev)
+{
+ snd_card_t *card = amba_get_drvdata(dev);
+ return card ? aaci_do_resume(card) : 0;
+}
+#else
+#define aaci_do_suspend NULL
+#define aaci_do_resume NULL
+#define aaci_suspend NULL
+#define aaci_resume NULL
+#endif
+
+
+static struct ac97_pcm ac97_defs[] __devinitdata = {
+ [0] = { /* Front PCM */
+ .exclusive = 1,
+ .r = {
+ [0] = {
+ .slots = (1 << AC97_SLOT_PCM_LEFT) |
+ (1 << AC97_SLOT_PCM_RIGHT) |
+ (1 << AC97_SLOT_PCM_CENTER) |
+ (1 << AC97_SLOT_PCM_SLEFT) |
+ (1 << AC97_SLOT_PCM_SRIGHT) |
+ (1 << AC97_SLOT_LFE),
+ },
+ },
+ },
+ [1] = { /* PCM in */
+ .stream = 1,
+ .exclusive = 1,
+ .r = {
+ [0] = {
+ .slots = (1 << AC97_SLOT_PCM_LEFT) |
+ (1 << AC97_SLOT_PCM_RIGHT),
+ },
+ },
+ },
+ [2] = { /* Mic in */
+ .stream = 1,
+ .exclusive = 1,
+ .r = {
+ [0] = {
+ .slots = (1 << AC97_SLOT_MIC),
+ },
+ },
+ }
+};
+
+static ac97_bus_ops_t aaci_bus_ops = {
+ .write = aaci_ac97_write,
+ .read = aaci_ac97_read,
+};
+
+static int __devinit aaci_probe_ac97(struct aaci *aaci)
+{
+ ac97_template_t ac97_template;
+ ac97_bus_t *ac97_bus;
+ ac97_t *ac97;
+ int ret;
+
+ /*
+ * Assert AACIRESET for 2us
+ */
+ writel(0, aaci->base + AACI_RESET);
+ udelay(2);
+ writel(RESET_NRST, aaci->base + AACI_RESET);
+
+ /*
+ * Give the AC'97 codec more than enough time
+ * to wake up. (42us = ~2 frames at 48kHz.)
+ */
+ udelay(42);
+
+ ret = snd_ac97_bus(aaci->card, 0, &aaci_bus_ops, aaci, &ac97_bus);
+ if (ret)
+ goto out;
+
+ ac97_bus->clock = 48000;
+ aaci->ac97_bus = ac97_bus;
+
+ memset(&ac97_template, 0, sizeof(ac97_template_t));
+ ac97_template.private_data = aaci;
+ ac97_template.num = 0;
+ ac97_template.scaps = AC97_SCAP_SKIP_MODEM;
+
+ ret = snd_ac97_mixer(ac97_bus, &ac97_template, &ac97);
+ if (ret)
+ goto out;
+
+ /*
+ * Disable AC97 PC Beep input on audio codecs.
+ */
+ if (ac97_is_audio(ac97))
+ snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x801e);
+
+ ret = snd_ac97_pcm_assign(ac97_bus, ARRAY_SIZE(ac97_defs), ac97_defs);
+ if (ret)
+ goto out;
+
+ aaci->playback.pcm = &ac97_bus->pcms[0];
+
+ out:
+ return ret;
+}
+
+static void aaci_free_card(snd_card_t *card)
+{
+ struct aaci *aaci = card->private_data;
+ if (aaci->base)
+ iounmap(aaci->base);
+}
+
+static struct aaci * __devinit aaci_init_card(struct amba_device *dev)
+{
+ struct aaci *aaci;
+ snd_card_t *card;
+
+ card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+ THIS_MODULE, sizeof(struct aaci));
+ if (card == NULL)
+ return ERR_PTR(-ENOMEM);
+
+ card->private_free = aaci_free_card;
+ snd_card_set_pm_callback(card, aaci_do_suspend, aaci_do_resume, NULL);
+
+ strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver));
+ strlcpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname));
+ snprintf(card->longname, sizeof(card->longname),
+ "%s at 0x%08lx, irq %d",
+ card->shortname, dev->res.start, dev->irq[0]);
+
+ aaci = card->private_data;
+ init_MUTEX(&aaci->ac97_sem);
+ spin_lock_init(&aaci->lock);
+ aaci->card = card;
+ aaci->dev = dev;
+
+ /* Set MAINCR to allow slot 1 and 2 data IO */
+ aaci->maincr = MAINCR_IE | MAINCR_SL1RXEN | MAINCR_SL1TXEN |
+ MAINCR_SL2RXEN | MAINCR_SL2TXEN;
+
+ return aaci;
+}
+
+static int __devinit aaci_init_pcm(struct aaci *aaci)
+{
+ snd_pcm_t *pcm;
+ int ret;
+
+ ret = snd_pcm_new(aaci->card, "AACI AC'97", 0, 1, 0, &pcm);
+ if (ret == 0) {
+ aaci->pcm = pcm;
+ pcm->private_data = aaci;
+ pcm->info_flags = 0;
+
+ strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name));
+
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops);
+ }
+
+ return ret;
+}
+
+static unsigned int __devinit aaci_size_fifo(struct aaci *aaci)
+{
+ void *base = aaci->base + AACI_CSCH1;
+ int i;
+
+ writel(TXCR_FEN | TXCR_TSZ16 | TXCR_TXEN, base + AACI_TXCR);
+
+ for (i = 0; !(readl(base + AACI_SR) & SR_TXFF) && i < 4096; i++)
+ writel(0, aaci->base + AACI_DR1);
+
+ writel(0, base + AACI_TXCR);
+
+ /*
+ * Re-initialise the AACI after the FIFO depth test, to
+ * ensure that the FIFOs are empty. Unfortunately, merely
+ * disabling the channel doesn't clear the FIFO.
+ */
+ writel(aaci->maincr & ~MAINCR_IE, aaci->base + AACI_MAINCR);
+ writel(aaci->maincr, aaci->base + AACI_MAINCR);
+
+ /*
+ * If we hit 4096, we failed. Go back to the specified
+ * fifo depth.
+ */
+ if (i == 4096)
+ i = 8;
+
+ return i;
+}
+
+static int __devinit aaci_probe(struct amba_device *dev, void *id)
+{
+ struct aaci *aaci;
+ int ret, i;
+
+ ret = amba_request_regions(dev, NULL);
+ if (ret)
+ return ret;
+
+ aaci = aaci_init_card(dev);
+ if (IS_ERR(aaci)) {
+ ret = PTR_ERR(aaci);
+ goto out;
+ }
+
+ aaci->base = ioremap(dev->res.start, SZ_4K);
+ if (!aaci->base) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /*
+ * Playback uses AACI channel 0
+ */
+ aaci->playback.base = aaci->base + AACI_CSCH1;
+ aaci->playback.fifo = aaci->base + AACI_DR1;
+
+ for (i = 0; i < 4; i++) {
+ void *base = aaci->base + i * 0x14;
+
+ writel(0, base + AACI_IE);
+ writel(0, base + AACI_TXCR);
+ writel(0, base + AACI_RXCR);
+ }
+
+ writel(0x1fff, aaci->base + AACI_INTCLR);
+ writel(aaci->maincr, aaci->base + AACI_MAINCR);
+
+ /*
+ * Size the FIFOs.
+ */
+ aaci->fifosize = aaci_size_fifo(aaci);
+
+ ret = aaci_probe_ac97(aaci);
+ if (ret)
+ goto out;
+
+ ret = aaci_init_pcm(aaci);
+ if (ret)
+ goto out;
+
+ ret = snd_card_register(aaci->card);
+ if (ret == 0) {
+ dev_info(&dev->dev, "%s, fifo %d\n", aaci->card->longname,
+ aaci->fifosize);
+ amba_set_drvdata(dev, aaci->card);
+ return ret;
+ }
+
+ out:
+ if (aaci)
+ snd_card_free(aaci->card);
+ amba_release_regions(dev);
+ return ret;
+}
+
+static int __devexit aaci_remove(struct amba_device *dev)
+{
+ snd_card_t *card = amba_get_drvdata(dev);
+
+ amba_set_drvdata(dev, NULL);
+
+ if (card) {
+ struct aaci *aaci = card->private_data;
+ writel(0, aaci->base + AACI_MAINCR);
+
+ snd_card_free(card);
+ amba_release_regions(dev);
+ }
+
+ return 0;
+}
+
+static struct amba_id aaci_ids[] = {
+ {
+ .id = 0x00041041,
+ .mask = 0x000fffff,
+ },
+ { 0, 0 },
+};
+
+static struct amba_driver aaci_driver = {
+ .drv = {
+ .name = DRIVER_NAME,
+ },
+ .probe = aaci_probe,
+ .remove = __devexit_p(aaci_remove),
+ .suspend = aaci_suspend,
+ .resume = aaci_resume,
+ .id_table = aaci_ids,
+};
+
+static int __init aaci_init(void)
+{
+ return amba_driver_register(&aaci_driver);
+}
+
+static void __exit aaci_exit(void)
+{
+ amba_driver_unregister(&aaci_driver);
+}
+
+module_init(aaci_init);
+module_exit(aaci_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ARM PrimeCell PL041 Advanced Audio CODEC Interface driver");
diff --git a/sound/arm/aaci.h b/sound/arm/aaci.h
new file mode 100644
index 00000000000..d752e642689
--- /dev/null
+++ b/sound/arm/aaci.h
@@ -0,0 +1,246 @@
+/*
+ * linux/sound/arm/aaci.c - ARM PrimeCell AACI PL041 driver
+ *
+ * Copyright (C) 2003 Deep Blue Solutions, Ltd, 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef AACI_H
+#define AACI_H
+
+/*
+ * Control and status register offsets
+ * P39.
+ */
+#define AACI_CSCH1 0x000
+#define AACI_CSCH2 0x014
+#define AACI_CSCH3 0x028
+#define AACI_CSCH4 0x03c
+
+#define AACI_RXCR 0x000 /* 29 bits Control Rx FIFO */
+#define AACI_TXCR 0x004 /* 17 bits Control Tx FIFO */
+#define AACI_SR 0x008 /* 12 bits Status */
+#define AACI_ISR 0x00c /* 7 bits Int Status */
+#define AACI_IE 0x010 /* 7 bits Int Enable */
+
+/*
+ * Other registers
+ */
+#define AACI_SL1RX 0x050
+#define AACI_SL1TX 0x054
+#define AACI_SL2RX 0x058
+#define AACI_SL2TX 0x05c
+#define AACI_SL12RX 0x060
+#define AACI_SL12TX 0x064
+#define AACI_SLFR 0x068 /* slot flags */
+#define AACI_SLISTAT 0x06c /* slot interrupt status */
+#define AACI_SLIEN 0x070 /* slot interrupt enable */
+#define AACI_INTCLR 0x074 /* interrupt clear */
+#define AACI_MAINCR 0x078 /* main control */
+#define AACI_RESET 0x07c /* reset control */
+#define AACI_SYNC 0x080 /* sync control */
+#define AACI_ALLINTS 0x084 /* all fifo interrupt status */
+#define AACI_MAINFR 0x088 /* main flag register */
+#define AACI_DR1 0x090 /* data read/written fifo 1 */
+#define AACI_DR2 0x0b0 /* data read/written fifo 2 */
+#define AACI_DR3 0x0d0 /* data read/written fifo 3 */
+#define AACI_DR4 0x0f0 /* data read/written fifo 4 */
+
+/*
+ * transmit fifo control register. P48
+ */
+#define TXCR_FEN (1 << 16) /* fifo enable */
+#define TXCR_COMPACT (1 << 15) /* compact mode */
+#define TXCR_TSZ16 (0 << 13) /* 16 bits */
+#define TXCR_TSZ18 (1 << 13) /* 18 bits */
+#define TXCR_TSZ20 (2 << 13) /* 20 bits */
+#define TXCR_TSZ12 (3 << 13) /* 12 bits */
+#define TXCR_TX12 (1 << 12) /* transmits slot 12 */
+#define TXCR_TX11 (1 << 11) /* transmits slot 12 */
+#define TXCR_TX10 (1 << 10) /* transmits slot 12 */
+#define TXCR_TX9 (1 << 9) /* transmits slot 12 */
+#define TXCR_TX8 (1 << 8) /* transmits slot 12 */
+#define TXCR_TX7 (1 << 7) /* transmits slot 12 */
+#define TXCR_TX6 (1 << 6) /* transmits slot 12 */
+#define TXCR_TX5 (1 << 5) /* transmits slot 12 */
+#define TXCR_TX4 (1 << 4) /* transmits slot 12 */
+#define TXCR_TX3 (1 << 3) /* transmits slot 12 */
+#define TXCR_TX2 (1 << 2) /* transmits slot 12 */
+#define TXCR_TX1 (1 << 1) /* transmits slot 12 */
+#define TXCR_TXEN (1 << 0) /* transmit enable */
+
+/*
+ * status register bits. P49
+ */
+#define SR_RXTOFE (1 << 11) /* rx timeout fifo empty */
+#define SR_TXTO (1 << 10) /* rx timeout fifo nonempty */
+#define SR_TXU (1 << 9) /* tx underrun */
+#define SR_RXO (1 << 8) /* rx overrun */
+#define SR_TXB (1 << 7) /* tx busy */
+#define SR_RXB (1 << 6) /* rx busy */
+#define SR_TXFF (1 << 5) /* tx fifo full */
+#define SR_RXFF (1 << 4) /* rx fifo full */
+#define SR_TXHE (1 << 3) /* tx fifo half empty */
+#define SR_RXHF (1 << 2) /* rx fifo half full */
+#define SR_TXFE (1 << 1) /* tx fifo empty */
+#define SR_RXFE (1 << 0) /* rx fifo empty */
+
+/*
+ * interrupt status register bits.
+ */
+#define ISR_RXTOFEINTR (1 << 6) /* rx fifo empty */
+#define ISR_URINTR (1 << 5) /* tx underflow */
+#define ISR_ORINTR (1 << 4) /* rx overflow */
+#define ISR_RXINTR (1 << 3) /* rx fifo */
+#define ISR_TXINTR (1 << 2) /* tx fifo intr */
+#define ISR_RXTOINTR (1 << 1) /* tx timeout */
+#define ISR_TXCINTR (1 << 0) /* tx complete */
+
+/*
+ * interrupt enable register bits.
+ */
+#define IE_RXTOIE (1 << 6)
+#define IE_URIE (1 << 5)
+#define IE_ORIE (1 << 4)
+#define IE_RXIE (1 << 3)
+#define IE_TXIE (1 << 2)
+#define IE_RXTIE (1 << 1)
+#define IE_TXCIE (1 << 0)
+
+/*
+ * interrupt status. P51
+ */
+#define ISR_RXTOFE (1 << 6) /* rx timeout fifo empty */
+#define ISR_UR (1 << 5) /* tx fifo underrun */
+#define ISR_OR (1 << 4) /* rx fifo overrun */
+#define ISR_RX (1 << 3) /* rx interrupt status */
+#define ISR_TX (1 << 2) /* tx interrupt status */
+#define ISR_RXTO (1 << 1) /* rx timeout */
+#define ISR_TXC (1 << 0) /* tx complete */
+
+/*
+ * interrupt enable. P52
+ */
+#define IE_RXTOFE (1 << 6) /* rx timeout fifo empty */
+#define IE_UR (1 << 5) /* tx fifo underrun */
+#define IE_OR (1 << 4) /* rx fifo overrun */
+#define IE_RX (1 << 3) /* rx interrupt status */
+#define IE_TX (1 << 2) /* tx interrupt status */
+#define IE_RXTO (1 << 1) /* rx timeout */
+#define IE_TXC (1 << 0) /* tx complete */
+
+/*
+ * slot flag register bits. P56
+ */
+#define SLFR_RWIS (1 << 13) /* raw wake-up interrupt status */
+#define SLFR_RGPIOINTR (1 << 12) /* raw gpio interrupt */
+#define SLFR_12TXE (1 << 11) /* slot 12 tx empty */
+#define SLFR_12RXV (1 << 10) /* slot 12 rx valid */
+#define SLFR_2TXE (1 << 9) /* slot 2 tx empty */
+#define SLFR_2RXV (1 << 8) /* slot 2 rx valid */
+#define SLFR_1TXE (1 << 7) /* slot 1 tx empty */
+#define SLFR_1RXV (1 << 6) /* slot 1 rx valid */
+#define SLFR_12TXB (1 << 5) /* slot 12 tx busy */
+#define SLFR_12RXB (1 << 4) /* slot 12 rx busy */
+#define SLFR_2TXB (1 << 3) /* slot 2 tx busy */
+#define SLFR_2RXB (1 << 2) /* slot 2 rx busy */
+#define SLFR_1TXB (1 << 1) /* slot 1 tx busy */
+#define SLFR_1RXB (1 << 0) /* slot 1 rx busy */
+
+/*
+ * Interrupt clear register.
+ */
+#define ICLR_RXTOFEC4 (1 << 12)
+#define ICLR_RXTOFEC3 (1 << 11)
+#define ICLR_RXTOFEC2 (1 << 10)
+#define ICLR_RXTOFEC1 (1 << 9)
+#define ICLR_TXUEC4 (1 << 8)
+#define ICLR_TXUEC3 (1 << 7)
+#define ICLR_TXUEC2 (1 << 6)
+#define ICLR_TXUEC1 (1 << 5)
+#define ICLR_RXOEC4 (1 << 4)
+#define ICLR_RXOEC3 (1 << 3)
+#define ICLR_RXOEC2 (1 << 2)
+#define ICLR_RXOEC1 (1 << 1)
+#define ICLR_WISC (1 << 0)
+
+/*
+ * Main control register bits. P62
+ */
+#define MAINCR_SCRA(x) ((x) << 10) /* secondary codec reg access */
+#define MAINCR_DMAEN (1 << 9) /* dma enable */
+#define MAINCR_SL12TXEN (1 << 8) /* slot 12 transmit enable */
+#define MAINCR_SL12RXEN (1 << 7) /* slot 12 receive enable */
+#define MAINCR_SL2TXEN (1 << 6) /* slot 2 transmit enable */
+#define MAINCR_SL2RXEN (1 << 5) /* slot 2 receive enable */
+#define MAINCR_SL1TXEN (1 << 4) /* slot 1 transmit enable */
+#define MAINCR_SL1RXEN (1 << 3) /* slot 1 receive enable */
+#define MAINCR_LPM (1 << 2) /* low power mode */
+#define MAINCR_LOOPBK (1 << 1) /* loopback */
+#define MAINCR_IE (1 << 0) /* aaci interface enable */
+
+/*
+ * Reset register bits. P65
+ */
+#define RESET_NRST (1 << 0)
+
+/*
+ * Sync register bits. P65
+ */
+#define SYNC_FORCE (1 << 0)
+
+/*
+ * Main flag register bits. P66
+ */
+#define MAINFR_TXB (1 << 1) /* transmit busy */
+#define MAINFR_RXB (1 << 0) /* receive busy */
+
+
+
+struct aaci_runtime {
+ void *base;
+ void *fifo;
+
+ struct ac97_pcm *pcm;
+ int pcm_open;
+
+ u32 cr;
+ snd_pcm_substream_t *substream;
+
+ /*
+ * PIO support
+ */
+ void *start;
+ void *end;
+ void *ptr;
+ int bytes;
+ unsigned int period;
+ unsigned int fifosz;
+};
+
+struct aaci {
+ struct amba_device *dev;
+ snd_card_t *card;
+ void *base;
+ unsigned int fifosize;
+
+ /* AC'97 */
+ struct semaphore ac97_sem;
+ ac97_bus_t *ac97_bus;
+
+ u32 maincr;
+ spinlock_t lock;
+
+ struct aaci_runtime playback;
+ struct aaci_runtime capture;
+
+ snd_pcm_t *pcm;
+};
+
+#define ACSTREAM_FRONT 0
+#define ACSTREAM_SURROUND 1
+#define ACSTREAM_LFE 2
+
+#endif
diff --git a/sound/arm/devdma.c b/sound/arm/devdma.c
new file mode 100644
index 00000000000..60826a5324b
--- /dev/null
+++ b/sound/arm/devdma.c
@@ -0,0 +1,81 @@
+/*
+ * linux/sound/arm/devdma.c
+ *
+ * Copyright (C) 2003-2004 Russell King, 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 version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ARM DMA shim for ALSA.
+ */
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+
+#include "devdma.h"
+
+void devdma_hw_free(struct device *dev, snd_pcm_substream_t *substream)
+{
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_dma_buffer *buf = runtime->dma_buffer_p;
+
+ if (runtime->dma_area == NULL)
+ return;
+
+ if (buf != &substream->dma_buffer) {
+ dma_free_coherent(buf->dev.dev, buf->bytes, buf->area, buf->addr);
+ kfree(runtime->dma_buffer_p);
+ }
+
+ snd_pcm_set_runtime_buffer(substream, NULL);
+}
+
+int devdma_hw_alloc(struct device *dev, snd_pcm_substream_t *substream, size_t size)
+{
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ struct snd_dma_buffer *buf = runtime->dma_buffer_p;
+ int ret = 0;
+
+ if (buf) {
+ if (buf->bytes >= size)
+ goto out;
+ devdma_hw_free(dev, substream);
+ }
+
+ if (substream->dma_buffer.area != NULL && substream->dma_buffer.bytes >= size) {
+ buf = &substream->dma_buffer;
+ } else {
+ buf = kmalloc(sizeof(struct snd_dma_buffer), GFP_KERNEL);
+ if (!buf)
+ goto nomem;
+
+ buf->dev.type = SNDRV_DMA_TYPE_DEV;
+ buf->dev.dev = dev;
+ buf->area = dma_alloc_coherent(dev, size, &buf->addr, GFP_KERNEL);
+ buf->bytes = size;
+ buf->private_data = NULL;
+
+ if (!buf->area)
+ goto free;
+ }
+ snd_pcm_set_runtime_buffer(substream, buf);
+ ret = 1;
+ out:
+ runtime->dma_bytes = size;
+ return ret;
+
+ free:
+ kfree(buf);
+ nomem:
+ return -ENOMEM;
+}
+
+int devdma_mmap(struct device *dev, snd_pcm_substream_t *substream, struct vm_area_struct *vma)
+{
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ return dma_mmap_coherent(dev, vma, runtime->dma_area, runtime->dma_addr, runtime->dma_bytes);
+}
diff --git a/sound/arm/devdma.h b/sound/arm/devdma.h
new file mode 100644
index 00000000000..5a33b6bacc3
--- /dev/null
+++ b/sound/arm/devdma.h
@@ -0,0 +1,3 @@
+void devdma_hw_free(struct device *dev, snd_pcm_substream_t *substream);
+int devdma_hw_alloc(struct device *dev, snd_pcm_substream_t *substream, size_t size);
+int devdma_mmap(struct device *dev, snd_pcm_substream_t *substream, struct vm_area_struct *vma);
diff --git a/sound/core/control.c b/sound/core/control.c
index f4ea6bff1dd..227f3cf0277 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -215,7 +215,7 @@ snd_kcontrol_t *snd_ctl_new(snd_kcontrol_t * control, unsigned int access)
*
* Returns the pointer of the newly generated instance, or NULL on failure.
*/
-snd_kcontrol_t *snd_ctl_new1(snd_kcontrol_new_t * ncontrol, void *private_data)
+snd_kcontrol_t *snd_ctl_new1(const snd_kcontrol_new_t * ncontrol, void *private_data)
{
snd_kcontrol_t kctl;
unsigned int access;
@@ -1102,7 +1102,7 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg
}
}
up_read(&snd_ioctl_rwsem);
- snd_printd("unknown ioctl = 0x%x\n", cmd);
+ snd_printdd("unknown ioctl = 0x%x\n", cmd);
return -ENOTTY;
}
diff --git a/sound/core/info.c b/sound/core/info.c
index 31faffe01cb..5e122bbe7c9 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -24,6 +24,7 @@
#include <linux/vmalloc.h>
#include <linux/time.h>
#include <linux/smp_lock.h>
+#include <linux/string.h>
#include <sound/core.h>
#include <sound/minors.h>
#include <sound/info.h>
@@ -754,7 +755,7 @@ static snd_info_entry_t *snd_info_create_entry(const char *name)
entry = kcalloc(1, sizeof(*entry), GFP_KERNEL);
if (entry == NULL)
return NULL;
- entry->name = snd_kmalloc_strdup(name, GFP_KERNEL);
+ entry->name = kstrdup(name, GFP_KERNEL);
if (entry->name == NULL) {
kfree(entry);
return NULL;
diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c
index f9e4ce44345..12107968d40 100644
--- a/sound/core/info_oss.c
+++ b/sound/core/info_oss.c
@@ -22,6 +22,7 @@
#include <sound/driver.h>
#include <linux/slab.h>
#include <linux/time.h>
+#include <linux/string.h>
#include <sound/core.h>
#include <sound/minors.h>
#include <sound/info.h>
@@ -51,7 +52,7 @@ int snd_oss_info_register(int dev, int num, char *string)
x = NULL;
}
} else {
- x = snd_kmalloc_strdup(string, GFP_KERNEL);
+ x = kstrdup(string, GFP_KERNEL);
if (x == NULL) {
up(&strings);
return -ENOMEM;
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index 344a83fd7c2..dbc23e35fa0 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -28,6 +28,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/mm.h>
+#include <asm/uaccess.h>
#include <linux/dma-mapping.h>
#include <linux/moduleparam.h>
#include <asm/semaphore.h>
@@ -46,13 +47,6 @@ MODULE_LICENSE("GPL");
#define SNDRV_CARDS 8
#endif
-/* FIXME: so far only some PCI devices have the preallocation table */
-#ifdef CONFIG_PCI
-static int enable[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1};
-module_param_array(enable, bool, NULL, 0444);
-MODULE_PARM_DESC(enable, "Enable cards to allocate buffers.");
-#endif
-
/*
*/
@@ -451,9 +445,13 @@ size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id)
list_for_each(p, &mem_list_head) {
mem = list_entry(p, struct snd_mem_list, list);
if (mem->id == id &&
- ! memcmp(&mem->buffer.dev, &dmab->dev, sizeof(dmab->dev))) {
+ (mem->buffer.dev.dev == NULL || dmab->dev.dev == NULL ||
+ ! memcmp(&mem->buffer.dev, &dmab->dev, sizeof(dmab->dev)))) {
+ struct device *dev = dmab->dev.dev;
list_del(p);
*dmab = mem->buffer;
+ if (dmab->dev.dev == NULL)
+ dmab->dev.dev = dev;
kfree(mem);
up(&list_mutex);
return dmab->bytes;
@@ -508,91 +506,13 @@ static void free_all_reserved_pages(void)
}
-
-/*
- * allocation of buffers for pre-defined devices
- */
-
-#ifdef CONFIG_PCI
-/* FIXME: for pci only - other bus? */
-struct prealloc_dev {
- unsigned short vendor;
- unsigned short device;
- unsigned long dma_mask;
- unsigned int size;
- unsigned int buffers;
-};
-
-#define HAMMERFALL_BUFFER_SIZE (16*1024*4*(26+1)+0x10000)
-
-static struct prealloc_dev prealloc_devices[] __initdata = {
- {
- /* hammerfall */
- .vendor = 0x10ee,
- .device = 0x3fc4,
- .dma_mask = 0xffffffff,
- .size = HAMMERFALL_BUFFER_SIZE,
- .buffers = 2
- },
- {
- /* HDSP */
- .vendor = 0x10ee,
- .device = 0x3fc5,
- .dma_mask = 0xffffffff,
- .size = HAMMERFALL_BUFFER_SIZE,
- .buffers = 2
- },
- { }, /* terminator */
-};
-
-static void __init preallocate_cards(void)
-{
- struct pci_dev *pci = NULL;
- int card;
-
- card = 0;
-
- while ((pci = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pci)) != NULL) {
- struct prealloc_dev *dev;
- unsigned int i;
- if (card >= SNDRV_CARDS)
- break;
- for (dev = prealloc_devices; dev->vendor; dev++) {
- if (dev->vendor == pci->vendor && dev->device == pci->device)
- break;
- }
- if (! dev->vendor)
- continue;
- if (! enable[card++]) {
- printk(KERN_DEBUG "snd-page-alloc: skipping card %d, device %04x:%04x\n", card, pci->vendor, pci->device);
- continue;
- }
-
- if (pci_set_dma_mask(pci, dev->dma_mask) < 0 ||
- pci_set_consistent_dma_mask(pci, dev->dma_mask) < 0) {
- printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", dev->dma_mask, dev->vendor, dev->device);
- continue;
- }
- for (i = 0; i < dev->buffers; i++) {
- struct snd_dma_buffer dmab;
- memset(&dmab, 0, sizeof(dmab));
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
- dev->size, &dmab) < 0)
- printk(KERN_WARNING "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", dev->size);
- else
- snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci));
- }
- }
-}
-#else
-#define preallocate_cards() /* NOP */
-#endif
-
-
#ifdef CONFIG_PROC_FS
/*
* proc file interface
*/
+#define SND_MEM_PROC_FILE "driver/snd-page-alloc"
+struct proc_dir_entry *snd_mem_proc;
+
static int snd_mem_proc_read(char *page, char **start, off_t off,
int count, int *eof, void *data)
{
@@ -621,6 +541,97 @@ static int snd_mem_proc_read(char *page, char **start, off_t off,
up(&list_mutex);
return len;
}
+
+/* FIXME: for pci only - other bus? */
+#ifdef CONFIG_PCI
+#define gettoken(bufp) strsep(bufp, " \t\n")
+
+static int snd_mem_proc_write(struct file *file, const char __user *buffer,
+ unsigned long count, void *data)
+{
+ char buf[128];
+ char *token, *p;
+
+ if (count > ARRAY_SIZE(buf) - 1)
+ count = ARRAY_SIZE(buf) - 1;
+ if (copy_from_user(buf, buffer, count))
+ return -EFAULT;
+ buf[ARRAY_SIZE(buf) - 1] = '\0';
+
+ p = buf;
+ token = gettoken(&p);
+ if (! token || *token == '#')
+ return (int)count;
+ if (strcmp(token, "add") == 0) {
+ char *endp;
+ int vendor, device, size, buffers;
+ long mask;
+ int i, alloced;
+ struct pci_dev *pci;
+
+ if ((token = gettoken(&p)) == NULL ||
+ (vendor = simple_strtol(token, NULL, 0)) <= 0 ||
+ (token = gettoken(&p)) == NULL ||
+ (device = simple_strtol(token, NULL, 0)) <= 0 ||
+ (token = gettoken(&p)) == NULL ||
+ (mask = simple_strtol(token, NULL, 0)) < 0 ||
+ (token = gettoken(&p)) == NULL ||
+ (size = memparse(token, &endp)) < 64*1024 ||
+ size > 16*1024*1024 /* too big */ ||
+ (token = gettoken(&p)) == NULL ||
+ (buffers = simple_strtol(token, NULL, 0)) <= 0 ||
+ buffers > 4) {
+ printk(KERN_ERR "snd-page-alloc: invalid proc write format\n");
+ return (int)count;
+ }
+ vendor &= 0xffff;
+ device &= 0xffff;
+
+ alloced = 0;
+ pci = NULL;
+ while ((pci = pci_find_device(vendor, device, pci)) != NULL) {
+ if (mask > 0 && mask < 0xffffffff) {
+ if (pci_set_dma_mask(pci, mask) < 0 ||
+ pci_set_consistent_dma_mask(pci, mask) < 0) {
+ printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", mask, vendor, device);
+ return (int)count;
+ }
+ }
+ for (i = 0; i < buffers; i++) {
+ struct snd_dma_buffer dmab;
+ memset(&dmab, 0, sizeof(dmab));
+ if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+ size, &dmab) < 0) {
+ printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size);
+ return (int)count;
+ }
+ snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci));
+ }
+ alloced++;
+ }
+ if (! alloced) {
+ for (i = 0; i < buffers; i++) {
+ struct snd_dma_buffer dmab;
+ memset(&dmab, 0, sizeof(dmab));
+ /* FIXME: We can allocate only in ZONE_DMA
+ * without a device pointer!
+ */
+ if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, NULL,
+ size, &dmab) < 0) {
+ printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size);
+ break;
+ }
+ snd_dma_reserve_buf(&dmab, (unsigned int)((vendor << 16) | device));
+ }
+ }
+ } else if (strcmp(token, "erase") == 0)
+ /* FIXME: need for releasing each buffer chunk? */
+ free_all_reserved_pages();
+ else
+ printk(KERN_ERR "snd-page-alloc: invalid proc cmd\n");
+ return (int)count;
+}
+#endif /* CONFIG_PCI */
#endif /* CONFIG_PROC_FS */
/*
@@ -630,15 +641,21 @@ static int snd_mem_proc_read(char *page, char **start, off_t off,
static int __init snd_mem_init(void)
{
#ifdef CONFIG_PROC_FS
- create_proc_read_entry("driver/snd-page-alloc", 0, NULL, snd_mem_proc_read, NULL);
+ snd_mem_proc = create_proc_entry(SND_MEM_PROC_FILE, 0644, NULL);
+ if (snd_mem_proc) {
+ snd_mem_proc->read_proc = snd_mem_proc_read;
+#ifdef CONFIG_PCI
+ snd_mem_proc->write_proc = snd_mem_proc_write;
+#endif
+ }
#endif
- preallocate_cards();
return 0;
}
static void __exit snd_mem_exit(void)
{
- remove_proc_entry("driver/snd-page-alloc", NULL);
+ if (snd_mem_proc)
+ remove_proc_entry(SND_MEM_PROC_FILE, NULL);
free_all_reserved_pages();
if (snd_allocated_pages > 0)
printk(KERN_ERR "snd-malloc: Memory leak? pages not freed = %li\n", snd_allocated_pages);
diff --git a/sound/core/memory.c b/sound/core/memory.c
index 20860fec936..c1fb28e8433 100644
--- a/sound/core/memory.c
+++ b/sound/core/memory.c
@@ -184,6 +184,20 @@ void snd_hidden_vfree(void *obj)
snd_wrapper_vfree(obj);
}
+char *snd_hidden_kstrdup(const char *s, int flags)
+{
+ int len;
+ char *buf;
+
+ if (!s) return NULL;
+
+ len = strlen(s) + 1;
+ buf = _snd_kmalloc(len, flags);
+ if (buf)
+ memcpy(buf, s, len);
+ return buf;
+}
+
static void snd_memory_info_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
{
snd_iprintf(buffer, "kmalloc: %li bytes\n", snd_alloc_kmalloc);
@@ -214,36 +228,9 @@ int __exit snd_memory_info_done(void)
return 0;
}
-#else
-
-#define _snd_kmalloc kmalloc
-
#endif /* CONFIG_SND_DEBUG_MEMORY */
/**
- * snd_kmalloc_strdup - copy the string
- * @string: the original string
- * @flags: allocation conditions, GFP_XXX
- *
- * Allocates a memory chunk via kmalloc() and copies the string to it.
- *
- * Returns the pointer, or NULL if no enoguh memory.
- */
-char *snd_kmalloc_strdup(const char *string, int flags)
-{
- size_t len;
- char *ptr;
-
- if (!string)
- return NULL;
- len = strlen(string) + 1;
- ptr = _snd_kmalloc(len, flags);
- if (ptr)
- memcpy(ptr, string, len);
- return ptr;
-}
-
-/**
* copy_to_user_fromio - copy data from mmio-space to user-space
* @dst: the destination pointer on user-space
* @src: the source pointer on mmio
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 98ed9a9f0da..98fc0766f88 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -24,6 +24,7 @@
#include <linux/smp_lock.h>
#include <linux/slab.h>
#include <linux/time.h>
+#include <linux/string.h>
#include <sound/core.h>
#include <sound/minors.h>
#include <sound/control.h>
@@ -1137,7 +1138,7 @@ static void snd_mixer_oss_proc_write(snd_info_entry_t *entry,
goto __unlock;
}
tbl->oss_id = ch;
- tbl->name = snd_kmalloc_strdup(str, GFP_KERNEL);
+ tbl->name = kstrdup(str, GFP_KERNEL);
if (! tbl->name) {
kfree(tbl);
goto __unlock;
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 1a805020f57..de7444c586f 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -33,6 +33,7 @@
#include <linux/time.h>
#include <linux/vmalloc.h>
#include <linux/moduleparam.h>
+#include <linux/string.h>
#include <sound/core.h>
#include <sound/minors.h>
#include <sound/pcm.h>
@@ -125,17 +126,26 @@ int snd_pcm_plugin_append(snd_pcm_plugin_t *plugin)
static long snd_pcm_oss_bytes(snd_pcm_substream_t *substream, long frames)
{
snd_pcm_runtime_t *runtime = substream->runtime;
- snd_pcm_uframes_t buffer_size = snd_pcm_lib_buffer_bytes(substream);
- frames = frames_to_bytes(runtime, frames);
+ long buffer_size = snd_pcm_lib_buffer_bytes(substream);
+ long bytes = frames_to_bytes(runtime, frames);
if (buffer_size == runtime->oss.buffer_bytes)
- return frames;
- return (runtime->oss.buffer_bytes * frames) / buffer_size;
+ return bytes;
+#if BITS_PER_LONG >= 64
+ return runtime->oss.buffer_bytes * bytes / buffer_size;
+#else
+ {
+ u64 bsize = (u64)runtime->oss.buffer_bytes * (u64)bytes;
+ u32 rem;
+ div64_32(&bsize, buffer_size, &rem);
+ return (long)bsize;
+ }
+#endif
}
static long snd_pcm_alsa_frames(snd_pcm_substream_t *substream, long bytes)
{
snd_pcm_runtime_t *runtime = substream->runtime;
- snd_pcm_uframes_t buffer_size = snd_pcm_lib_buffer_bytes(substream);
+ long buffer_size = snd_pcm_lib_buffer_bytes(substream);
if (buffer_size == runtime->oss.buffer_bytes)
return bytes_to_frames(runtime, bytes);
return bytes_to_frames(runtime, (buffer_size * bytes) / runtime->oss.buffer_bytes);
@@ -464,7 +474,8 @@ static int snd_pcm_oss_change_params(snd_pcm_substream_t *substream)
sw_params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
sw_params->period_step = 1;
sw_params->sleep_min = 0;
- sw_params->avail_min = 1;
+ sw_params->avail_min = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
+ 1 : runtime->period_size;
sw_params->xfer_align = 1;
if (atomic_read(&runtime->mmap_count) ||
(substream->oss.setup && substream->oss.setup->nosilence)) {
@@ -1527,12 +1538,15 @@ static int snd_pcm_oss_get_ptr(snd_pcm_oss_file_t *pcm_oss_file, int stream, str
snd_pcm_oss_simulate_fill(substream, delay);
info.bytes = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr) & INT_MAX;
} else {
- delay = snd_pcm_oss_bytes(substream, delay) + fixup;
- info.blocks = delay / runtime->oss.period_bytes;
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ delay = snd_pcm_oss_bytes(substream, delay);
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes;
info.bytes = (runtime->oss.bytes - delay) & INT_MAX;
- else
+ } else {
+ delay += fixup;
+ info.blocks = delay / runtime->oss.period_bytes;
info.bytes = (runtime->oss.bytes + delay) & INT_MAX;
+ }
}
if (copy_to_user(_info, &info, sizeof(info)))
return -EFAULT;
@@ -2347,7 +2361,7 @@ static void snd_pcm_oss_proc_write(snd_info_entry_t *entry,
for (setup1 = pstr->oss.setup_list; setup1->next; setup1 = setup1->next);
setup1->next = setup;
}
- template.task_name = snd_kmalloc_strdup(task_name, GFP_KERNEL);
+ template.task_name = kstrdup(task_name, GFP_KERNEL);
} else {
buffer->error = -ENOMEM;
}
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
index 6bb31009f0b..6430410c6c0 100644
--- a/sound/core/oss/pcm_plugin.c
+++ b/sound/core/oss/pcm_plugin.c
@@ -663,10 +663,7 @@ static int snd_pcm_plug_playback_channels_mask(snd_pcm_plug_t *plug,
bitset_t *dstmask = bs;
int err;
bitset_one(dstmask, schannels);
- if (plugin == NULL) {
- bitset_and(client_vmask, dstmask, schannels);
- return 0;
- }
+
while (1) {
err = plugin->src_channels_mask(plugin, dstmask, &srcmask);
if (err < 0)
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 8d94325529a..9f4c9209b27 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -451,6 +451,7 @@ static int snd_pcm_stream_proc_init(snd_pcm_str_t *pstr)
entry->c.text.read = snd_pcm_xrun_debug_read;
entry->c.text.write_size = 64;
entry->c.text.write = snd_pcm_xrun_debug_write;
+ entry->mode |= S_IWUSR;
entry->private_data = pstr;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
@@ -1048,7 +1049,6 @@ EXPORT_SYMBOL(snd_pcm_release_substream);
EXPORT_SYMBOL(snd_pcm_format_name);
/* pcm_native.c */
EXPORT_SYMBOL(snd_pcm_link_rwlock);
-EXPORT_SYMBOL(snd_pcm_start);
#ifdef CONFIG_PM
EXPORT_SYMBOL(snd_pcm_suspend);
EXPORT_SYMBOL(snd_pcm_suspend_all);
@@ -1068,6 +1068,7 @@ EXPORT_SYMBOL(snd_pcm_format_little_endian);
EXPORT_SYMBOL(snd_pcm_format_big_endian);
EXPORT_SYMBOL(snd_pcm_format_width);
EXPORT_SYMBOL(snd_pcm_format_physical_width);
+EXPORT_SYMBOL(snd_pcm_format_size);
EXPORT_SYMBOL(snd_pcm_format_silence_64);
EXPORT_SYMBOL(snd_pcm_format_set_silence);
EXPORT_SYMBOL(snd_pcm_build_linear_format);
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 151fd99ca2c..c5bfd0918cf 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1143,7 +1143,8 @@ int snd_pcm_hw_constraint_pow2(snd_pcm_runtime_t *runtime,
#define INT_MIN ((int)((unsigned int)INT_MAX+1))
#endif
-void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var)
+static void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params,
+ snd_pcm_hw_param_t var)
{
if (hw_is_mask(var)) {
snd_mask_any(hw_param_mask(params, var));
@@ -1160,6 +1161,7 @@ void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var)
snd_BUG();
}
+#if 0
/**
* snd_pcm_hw_param_any
*/
@@ -1169,6 +1171,7 @@ int snd_pcm_hw_param_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
_snd_pcm_hw_param_any(params, var);
return snd_pcm_hw_refine(pcm, params);
}
+#endif /* 0 */
void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params)
{
@@ -1181,6 +1184,7 @@ void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params)
params->info = ~0U;
}
+#if 0
/**
* snd_pcm_hw_params_any
*
@@ -1191,6 +1195,7 @@ int snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
_snd_pcm_hw_params_any(params);
return snd_pcm_hw_refine(pcm, params);
}
+#endif /* 0 */
/**
* snd_pcm_hw_param_value
@@ -1198,8 +1203,8 @@ int snd_pcm_hw_params_any(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
* Return the value for field PAR if it's fixed in configuration space
* defined by PARAMS. Return -EINVAL otherwise
*/
-int snd_pcm_hw_param_value(const snd_pcm_hw_params_t *params,
- snd_pcm_hw_param_t var, int *dir)
+static int snd_pcm_hw_param_value(const snd_pcm_hw_params_t *params,
+ snd_pcm_hw_param_t var, int *dir)
{
if (hw_is_mask(var)) {
const snd_mask_t *mask = hw_param_mask_c(params, var);
@@ -1296,6 +1301,7 @@ int _snd_pcm_hw_param_setinteger(snd_pcm_hw_params_t *params,
return changed;
}
+#if 0
/**
* snd_pcm_hw_param_setinteger
*
@@ -1317,9 +1323,10 @@ int snd_pcm_hw_param_setinteger(snd_pcm_t *pcm,
}
return 0;
}
+#endif /* 0 */
-int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params,
- snd_pcm_hw_param_t var)
+static int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params,
+ snd_pcm_hw_param_t var)
{
int changed;
if (hw_is_mask(var))
@@ -1345,9 +1352,9 @@ int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params,
* values > minimum. Reduce configuration space accordingly.
* Return the minimum.
*/
-int snd_pcm_hw_param_first(snd_pcm_t *pcm,
- snd_pcm_hw_params_t *params,
- snd_pcm_hw_param_t var, int *dir)
+static int snd_pcm_hw_param_first(snd_pcm_t *pcm,
+ snd_pcm_hw_params_t *params,
+ snd_pcm_hw_param_t var, int *dir)
{
int changed = _snd_pcm_hw_param_first(params, var);
if (changed < 0)
@@ -1359,8 +1366,8 @@ int snd_pcm_hw_param_first(snd_pcm_t *pcm,
return snd_pcm_hw_param_value(params, var, dir);
}
-int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params,
- snd_pcm_hw_param_t var)
+static int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params,
+ snd_pcm_hw_param_t var)
{
int changed;
if (hw_is_mask(var))
@@ -1386,9 +1393,9 @@ int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params,
* values < maximum. Reduce configuration space accordingly.
* Return the maximum.
*/
-int snd_pcm_hw_param_last(snd_pcm_t *pcm,
- snd_pcm_hw_params_t *params,
- snd_pcm_hw_param_t var, int *dir)
+static int snd_pcm_hw_param_last(snd_pcm_t *pcm,
+ snd_pcm_hw_params_t *params,
+ snd_pcm_hw_param_t var, int *dir)
{
int changed = _snd_pcm_hw_param_last(params, var);
if (changed < 0)
@@ -1437,8 +1444,9 @@ int _snd_pcm_hw_param_min(snd_pcm_hw_params_t *params,
* values < VAL. Reduce configuration space accordingly.
* Return new minimum or -EINVAL if the configuration space is empty
*/
-int snd_pcm_hw_param_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
- snd_pcm_hw_param_t var, unsigned int val, int *dir)
+static int snd_pcm_hw_param_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
+ snd_pcm_hw_param_t var, unsigned int val,
+ int *dir)
{
int changed = _snd_pcm_hw_param_min(params, var, val, dir ? *dir : 0);
if (changed < 0)
@@ -1451,8 +1459,9 @@ int snd_pcm_hw_param_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
return snd_pcm_hw_param_value_min(params, var, dir);
}
-int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params,
- snd_pcm_hw_param_t var, unsigned int val, int dir)
+static int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params,
+ snd_pcm_hw_param_t var, unsigned int val,
+ int dir)
{
int changed;
int open = 0;
@@ -1490,8 +1499,9 @@ int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params,
* values >= VAL + 1. Reduce configuration space accordingly.
* Return new maximum or -EINVAL if the configuration space is empty
*/
-int snd_pcm_hw_param_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
- snd_pcm_hw_param_t var, unsigned int val, int *dir)
+static int snd_pcm_hw_param_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
+ snd_pcm_hw_param_t var, unsigned int val,
+ int *dir)
{
int changed = _snd_pcm_hw_param_max(params, var, val, dir ? *dir : 0);
if (changed < 0)
@@ -2564,9 +2574,6 @@ snd_pcm_sframes_t snd_pcm_lib_readv(snd_pcm_substream_t *substream,
EXPORT_SYMBOL(snd_interval_refine);
EXPORT_SYMBOL(snd_interval_list);
EXPORT_SYMBOL(snd_interval_ratnum);
-EXPORT_SYMBOL(snd_interval_muldivk);
-EXPORT_SYMBOL(snd_interval_mulkdiv);
-EXPORT_SYMBOL(snd_interval_div);
EXPORT_SYMBOL(_snd_pcm_hw_params_any);
EXPORT_SYMBOL(_snd_pcm_hw_param_min);
EXPORT_SYMBOL(_snd_pcm_hw_param_set);
@@ -2580,7 +2587,6 @@ EXPORT_SYMBOL(snd_pcm_hw_param_last);
EXPORT_SYMBOL(snd_pcm_hw_param_near);
EXPORT_SYMBOL(snd_pcm_hw_param_set);
EXPORT_SYMBOL(snd_pcm_hw_refine);
-EXPORT_SYMBOL(snd_pcm_hw_params);
EXPORT_SYMBOL(snd_pcm_hw_constraints_init);
EXPORT_SYMBOL(snd_pcm_hw_constraints_complete);
EXPORT_SYMBOL(snd_pcm_hw_constraint_list);
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index f1d5f7a6ee0..9a174fb9656 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -204,6 +204,7 @@ static int snd_pcm_lib_preallocate_pages1(snd_pcm_substream_t *substream,
entry->c.text.read = snd_pcm_lib_preallocate_proc_read;
entry->c.text.write_size = 64;
entry->c.text.write = snd_pcm_lib_preallocate_proc_write;
+ entry->mode |= S_IWUSR;
entry->private_data = substream;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
index 422b8db1415..1453743e4da 100644
--- a/sound/core/pcm_misc.c
+++ b/sound/core/pcm_misc.c
@@ -270,22 +270,6 @@ int snd_pcm_format_big_endian(snd_pcm_format_t format)
}
/**
- * snd_pcm_format_cpu_endian - Check the PCM format is CPU-endian
- * @format: the format to check
- *
- * Returns 1 if the given PCM format is CPU-endian, 0 if
- * opposite, or a negative error code if endian not specified.
- */
-int snd_pcm_format_cpu_endian(snd_pcm_format_t format)
-{
-#ifdef SNDRV_LITTLE_ENDIAN
- return snd_pcm_format_little_endian(format);
-#else
- return snd_pcm_format_big_endian(format);
-#endif
-}
-
-/**
* snd_pcm_format_width - return the bit-width of the format
* @format: the format to check
*
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index cad9bbde998..10c2c983264 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -337,8 +337,8 @@ out:
return err;
}
-int snd_pcm_hw_params(snd_pcm_substream_t *substream,
- snd_pcm_hw_params_t *params)
+static int snd_pcm_hw_params(snd_pcm_substream_t *substream,
+ snd_pcm_hw_params_t *params)
{
snd_pcm_runtime_t *runtime;
int err;
@@ -1368,43 +1368,32 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream)
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
- down_read(&snd_pcm_link_rwsem);
snd_power_lock(card);
if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile);
- if (result < 0)
- goto _unlock;
+ if (result < 0) {
+ snd_power_unlock(card);
+ return result;
+ }
}
/* allocate temporary record for drain sync */
+ down_read(&snd_pcm_link_rwsem);
if (snd_pcm_stream_linked(substream)) {
drec = kmalloc(substream->group->count * sizeof(*drec), GFP_KERNEL);
if (! drec) {
- result = -ENOMEM;
- goto _unlock;
+ up_read(&snd_pcm_link_rwsem);
+ snd_power_unlock(card);
+ return -ENOMEM;
}
} else
drec = &drec_tmp;
- snd_pcm_stream_lock_irq(substream);
- /* resume pause */
- if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
- snd_pcm_pause(substream, 0);
-
- /* pre-start/stop - all running streams are changed to DRAINING state */
- result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0);
- if (result < 0)
- goto _end;
-
- /* check streams with PLAYBACK & DRAINING */
+ /* count only playback streams */
num_drecs = 0;
snd_pcm_group_for_each(pos, substream) {
snd_pcm_substream_t *s = snd_pcm_group_substream_entry(pos);
runtime = s->runtime;
- if (runtime->status->state != SNDRV_PCM_STATE_DRAINING) {
- runtime->status->state = SNDRV_PCM_STATE_SETUP;
- continue;
- }
if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) {
d = &drec[num_drecs++];
d->substream = s;
@@ -1418,9 +1407,21 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream)
runtime->stop_threshold = runtime->buffer_size;
}
}
-
+ up_read(&snd_pcm_link_rwsem);
if (! num_drecs)
- goto _end;
+ goto _error;
+
+ snd_pcm_stream_lock_irq(substream);
+ /* resume pause */
+ if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
+ snd_pcm_pause(substream, 0);
+
+ /* pre-start/stop - all running streams are changed to DRAINING state */
+ result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0);
+ if (result < 0) {
+ snd_pcm_stream_unlock_irq(substream);
+ goto _error;
+ }
for (;;) {
long tout;
@@ -1428,6 +1429,15 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream)
result = -ERESTARTSYS;
break;
}
+ /* all finished? */
+ for (i = 0; i < num_drecs; i++) {
+ runtime = drec[i].substream->runtime;
+ if (runtime->status->state == SNDRV_PCM_STATE_DRAINING)
+ break;
+ }
+ if (i == num_drecs)
+ break; /* yes, all drained */
+
set_current_state(TASK_INTERRUPTIBLE);
snd_pcm_stream_unlock_irq(substream);
snd_power_unlock(card);
@@ -1444,15 +1454,11 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream)
}
break;
}
- /* all finished? */
- for (i = 0; i < num_drecs; i++) {
- runtime = drec[i].substream->runtime;
- if (runtime->status->state == SNDRV_PCM_STATE_DRAINING)
- break;
- }
- if (i == num_drecs)
- break;
}
+
+ snd_pcm_stream_unlock_irq(substream);
+
+ _error:
for (i = 0; i < num_drecs; i++) {
d = &drec[i];
runtime = d->substream->runtime;
@@ -1460,13 +1466,9 @@ static int snd_pcm_drain(snd_pcm_substream_t *substream)
runtime->stop_threshold = d->stop_threshold;
}
- _end:
- snd_pcm_stream_unlock_irq(substream);
if (drec != &drec_tmp)
kfree(drec);
- _unlock:
snd_power_unlock(card);
- up_read(&snd_pcm_link_rwsem);
return result;
}
diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
index 638cc148706..1a7736cbf3a 100644
--- a/sound/core/seq/oss/seq_oss_synth.c
+++ b/sound/core/seq/oss/seq_oss_synth.c
@@ -325,14 +325,10 @@ snd_seq_oss_synth_cleanup(seq_oss_devinfo_t *dp)
}
snd_use_lock_free(&rec->use_lock);
}
- if (info->sysex) {
- kfree(info->sysex);
- info->sysex = NULL;
- }
- if (info->ch) {
- kfree(info->ch);
- info->ch = NULL;
- }
+ kfree(info->sysex);
+ info->sysex = NULL;
+ kfree(info->ch);
+ info->ch = NULL;
}
dp->synth_opened = 0;
dp->max_synthdev = 0;
@@ -418,14 +414,10 @@ snd_seq_oss_synth_reset(seq_oss_devinfo_t *dp, int dev)
dp->file_mode) < 0) {
midi_synth_dev.opened--;
info->opened = 0;
- if (info->sysex) {
- kfree(info->sysex);
- info->sysex = NULL;
- }
- if (info->ch) {
- kfree(info->ch);
- info->ch = NULL;
- }
+ kfree(info->sysex);
+ info->sysex = NULL;
+ kfree(info->ch);
+ info->ch = NULL;
}
return;
}
diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c
index e88967c5b93..ea945a5d2a0 100644
--- a/sound/core/seq/seq_dummy.c
+++ b/sound/core/seq/seq_dummy.c
@@ -140,10 +140,7 @@ dummy_input(snd_seq_event_t *ev, int direct, void *private_data, int atomic, int
static void
dummy_free(void *private_data)
{
- snd_seq_dummy_port_t *p;
-
- p = private_data;
- kfree(p);
+ kfree(private_data);
}
/*
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
index 18247db45db..57be9155eb6 100644
--- a/sound/core/seq/seq_midi.c
+++ b/sound/core/seq/seq_midi.c
@@ -414,6 +414,8 @@ snd_seq_midisynth_register_port(snd_seq_device_t *dev)
if (newclient)
synths[card->number] = client;
up(&register_mutex);
+ kfree(info);
+ kfree(port);
return 0; /* success */
__nomem:
diff --git a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c
index 21e569062bc..df1e2bb3974 100644
--- a/sound/core/seq/seq_midi_event.c
+++ b/sound/core/seq/seq_midi_event.c
@@ -171,11 +171,13 @@ void snd_midi_event_reset_decode(snd_midi_event_t *dev)
spin_unlock_irqrestore(&dev->lock, flags);
}
+#if 0
void snd_midi_event_init(snd_midi_event_t *dev)
{
snd_midi_event_reset_encode(dev);
snd_midi_event_reset_decode(dev);
}
+#endif /* 0 */
void snd_midi_event_no_status(snd_midi_event_t *dev, int on)
{
@@ -185,6 +187,7 @@ void snd_midi_event_no_status(snd_midi_event_t *dev, int on)
/*
* resize buffer
*/
+#if 0
int snd_midi_event_resize_buffer(snd_midi_event_t *dev, int bufsize)
{
unsigned char *new_buf, *old_buf;
@@ -204,6 +207,7 @@ int snd_midi_event_resize_buffer(snd_midi_event_t *dev, int bufsize)
kfree(old_buf);
return 0;
}
+#endif /* 0 */
/*
* read bytes and encode to sequencer event if finished
@@ -517,8 +521,6 @@ static int extra_decode_xrpn(snd_midi_event_t *dev, unsigned char *buf, int coun
EXPORT_SYMBOL(snd_midi_event_new);
EXPORT_SYMBOL(snd_midi_event_free);
-EXPORT_SYMBOL(snd_midi_event_resize_buffer);
-EXPORT_SYMBOL(snd_midi_event_init);
EXPORT_SYMBOL(snd_midi_event_reset_encode);
EXPORT_SYMBOL(snd_midi_event_reset_decode);
EXPORT_SYMBOL(snd_midi_event_no_status);
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
index 3afc7cc0c9a..98de2e711fd 100644
--- a/sound/core/seq/seq_queue.c
+++ b/sound/core/seq/seq_queue.c
@@ -672,7 +672,8 @@ static void queue_broadcast_event(queue_t *q, snd_seq_event_t *ev, int atomic, i
* process a received queue-control event.
* this function is exported for seq_sync.c.
*/
-void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, int atomic, int hop)
+static void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev,
+ int atomic, int hop)
{
switch (ev->type) {
case SNDRV_SEQ_EVENT_START:
diff --git a/sound/core/seq/seq_queue.h b/sound/core/seq/seq_queue.h
index b1bf5519fb3..ea3c54216ea 100644
--- a/sound/core/seq/seq_queue.h
+++ b/sound/core/seq/seq_queue.h
@@ -111,7 +111,6 @@ int snd_seq_queue_use(int queueid, int client, int use);
int snd_seq_queue_is_used(int queueid, int client);
int snd_seq_control_queue(snd_seq_event_t *ev, int atomic, int hop);
-void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, int atomic, int hop);
/*
* 64bit division - for sync stuff..
diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c
index 753f1c0863c..a7f76fc9528 100644
--- a/sound/core/seq/seq_timer.c
+++ b/sound/core/seq/seq_timer.c
@@ -36,7 +36,8 @@ extern int seq_default_timer_resolution;
#define SKEW_BASE 0x10000 /* 16bit shift */
-void snd_seq_timer_set_tick_resolution(seq_timer_tick_t *tick, int tempo, int ppq, int nticks)
+static void snd_seq_timer_set_tick_resolution(seq_timer_tick_t *tick,
+ int tempo, int ppq, int nticks)
{
if (tempo < 1000000)
tick->resolution = (tempo * 1000) / ppq;
diff --git a/sound/core/seq/seq_timer.h b/sound/core/seq/seq_timer.h
index 4c0872df893..287ed68591d 100644
--- a/sound/core/seq/seq_timer.h
+++ b/sound/core/seq/seq_timer.h
@@ -64,8 +64,6 @@ extern seq_timer_t *snd_seq_timer_new(void);
/* delete timer (destructor) */
extern void snd_seq_timer_delete(seq_timer_t **tmr);
-void snd_seq_timer_set_tick_resolution(seq_timer_tick_t *tick, int tempo, int ppq, int nticks);
-
/* */
static inline void snd_seq_timer_update_tick(seq_timer_tick_t *tick, unsigned long resolution)
{
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
index 6b4e630ace5..a66484b5cf0 100644
--- a/sound/core/seq/seq_virmidi.c
+++ b/sound/core/seq/seq_virmidi.c
@@ -110,7 +110,7 @@ static int snd_virmidi_dev_receive_event(snd_virmidi_dev_t *rdev, snd_seq_event_
* handler of a remote port which is attached to the virmidi via
* SNDRV_VIRMIDI_SEQ_ATTACH.
*/
-/* exported */
+#if 0
int snd_virmidi_receive(snd_rawmidi_t *rmidi, snd_seq_event_t *ev)
{
snd_virmidi_dev_t *rdev;
@@ -118,6 +118,7 @@ int snd_virmidi_receive(snd_rawmidi_t *rmidi, snd_seq_event_t *ev)
rdev = rmidi->private_data;
return snd_virmidi_dev_receive_event(rdev, ev);
}
+#endif /* 0 */
/*
* event handler of virmidi port
@@ -384,7 +385,7 @@ static int snd_virmidi_dev_attach_seq(snd_virmidi_dev_t *rdev)
info->client = client;
info->type = KERNEL_CLIENT;
sprintf(info->name, "%s %d-%d", rdev->rmidi->name, rdev->card->number, rdev->device);
- snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &info);
+ snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, info);
/* create a port */
memset(pinfo, 0, sizeof(*pinfo));
@@ -405,7 +406,7 @@ static int snd_virmidi_dev_attach_seq(snd_virmidi_dev_t *rdev)
pcallbacks.unuse = snd_virmidi_unuse;
pcallbacks.event_input = snd_virmidi_event_input;
pinfo->kernel = &pcallbacks;
- err = snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, &pinfo);
+ err = snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, pinfo);
if (err < 0) {
snd_seq_delete_kernel_client(client);
rdev->client = -1;
@@ -548,4 +549,3 @@ module_init(alsa_virmidi_init)
module_exit(alsa_virmidi_exit)
EXPORT_SYMBOL(snd_virmidi_new);
-EXPORT_SYMBOL(snd_virmidi_receive);
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 88e052079f8..7612884f530 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -64,7 +64,7 @@ static struct list_head snd_minors_hash[SNDRV_CARDS];
static DECLARE_MUTEX(sound_mutex);
-extern struct class_simple *sound_class;
+extern struct class *sound_class;
#ifdef CONFIG_KMOD
@@ -231,7 +231,7 @@ int snd_register_device(int type, snd_card_t * card, int dev, snd_minor_t * reg,
devfs_mk_cdev(MKDEV(major, minor), S_IFCHR | device_mode, "snd/%s", name);
if (card)
device = card->dev;
- class_simple_device_add(sound_class, MKDEV(major, minor), device, name);
+ class_device_create(sound_class, MKDEV(major, minor), device, "%s", name);
up(&sound_mutex);
return 0;
@@ -263,7 +263,7 @@ int snd_unregister_device(int type, snd_card_t * card, int dev)
if (strncmp(mptr->name, "controlC", 8) || card->number >= cards_limit) /* created in sound.c */
devfs_remove("snd/%s", mptr->name);
- class_simple_device_remove(MKDEV(major, minor));
+ class_device_destroy(sound_class, MKDEV(major, minor));
list_del(&mptr->list);
up(&sound_mutex);
@@ -399,8 +399,8 @@ EXPORT_SYMBOL(snd_hidden_kcalloc);
EXPORT_SYMBOL(snd_hidden_kfree);
EXPORT_SYMBOL(snd_hidden_vmalloc);
EXPORT_SYMBOL(snd_hidden_vfree);
+EXPORT_SYMBOL(snd_hidden_kstrdup);
#endif
-EXPORT_SYMBOL(snd_kmalloc_strdup);
EXPORT_SYMBOL(copy_to_user_fromio);
EXPORT_SYMBOL(copy_from_user_toio);
/* init.c */
@@ -431,7 +431,6 @@ EXPORT_SYMBOL(snd_card_pci_resume);
EXPORT_SYMBOL(snd_device_new);
EXPORT_SYMBOL(snd_device_register);
EXPORT_SYMBOL(snd_device_free);
-EXPORT_SYMBOL(snd_device_free_all);
/* isadma.c */
#ifdef CONFIG_ISA
EXPORT_SYMBOL(snd_dma_program);
diff --git a/sound/core/timer.c b/sound/core/timer.c
index fa762ca439b..cfaccd415b3 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -26,6 +26,7 @@
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/moduleparam.h>
+#include <linux/string.h>
#include <sound/core.h>
#include <sound/timer.h>
#include <sound/control.h>
@@ -69,6 +70,7 @@ typedef struct {
struct timespec tstamp; /* trigger tstamp */
wait_queue_head_t qchange_sleep;
struct fasync_struct *fasync;
+ struct semaphore tread_sem;
} snd_timer_user_t;
/* list of timers */
@@ -99,7 +101,7 @@ static snd_timer_instance_t *snd_timer_instance_new(char *owner, snd_timer_t *ti
timeri = kcalloc(1, sizeof(*timeri), GFP_KERNEL);
if (timeri == NULL)
return NULL;
- timeri->owner = snd_kmalloc_strdup(owner, GFP_KERNEL);
+ timeri->owner = kstrdup(owner, GFP_KERNEL);
if (! timeri->owner) {
kfree(timeri);
return NULL;
@@ -844,7 +846,7 @@ int snd_timer_dev_register(snd_device_t *dev)
return 0;
}
-int snd_timer_unregister(snd_timer_t *timer)
+static int snd_timer_unregister(snd_timer_t *timer)
{
struct list_head *p, *n;
snd_timer_instance_t *ti;
@@ -945,11 +947,6 @@ struct snd_timer_system_private {
unsigned long correction;
};
-unsigned int snd_timer_system_resolution(void)
-{
- return 1000000000L / HZ;
-}
-
static void snd_timer_s_function(unsigned long data)
{
snd_timer_t *timer = (snd_timer_t *)data;
@@ -1208,6 +1205,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file)
return -ENOMEM;
spin_lock_init(&tu->qlock);
init_waitqueue_head(&tu->qchange_sleep);
+ init_MUTEX(&tu->tread_sem);
tu->ticks = 1;
tu->queue_size = 128;
tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL);
@@ -1454,46 +1452,51 @@ static int snd_timer_user_tselect(struct file *file, snd_timer_select_t __user *
snd_timer_user_t *tu;
snd_timer_select_t tselect;
char str[32];
- int err;
+ int err = 0;
tu = file->private_data;
- if (tu->timeri)
+ down(&tu->tread_sem);
+ if (tu->timeri) {
snd_timer_close(tu->timeri);
- if (copy_from_user(&tselect, _tselect, sizeof(tselect)))
- return -EFAULT;
+ tu->timeri = NULL;
+ }
+ if (copy_from_user(&tselect, _tselect, sizeof(tselect))) {
+ err = -EFAULT;
+ goto __err;
+ }
sprintf(str, "application %i", current->pid);
if (tselect.id.dev_class != SNDRV_TIMER_CLASS_SLAVE)
tselect.id.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION;
if ((err = snd_timer_open(&tu->timeri, str, &tselect.id, current->pid)) < 0)
- return err;
+ goto __err;
- if (tu->queue) {
- kfree(tu->queue);
- tu->queue = NULL;
- }
- if (tu->tqueue) {
- kfree(tu->tqueue);
- tu->tqueue = NULL;
- }
+ kfree(tu->queue);
+ tu->queue = NULL;
+ kfree(tu->tqueue);
+ tu->tqueue = NULL;
if (tu->tread) {
tu->tqueue = (snd_timer_tread_t *)kmalloc(tu->queue_size * sizeof(snd_timer_tread_t), GFP_KERNEL);
- if (tu->tqueue == NULL) {
- snd_timer_close(tu->timeri);
- return -ENOMEM;
- }
+ if (tu->tqueue == NULL)
+ err = -ENOMEM;
} else {
tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL);
- if (tu->queue == NULL) {
- snd_timer_close(tu->timeri);
- return -ENOMEM;
- }
+ if (tu->queue == NULL)
+ err = -ENOMEM;
}
- tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST;
- tu->timeri->callback = tu->tread ? snd_timer_user_tinterrupt : snd_timer_user_interrupt;
- tu->timeri->ccallback = snd_timer_user_ccallback;
- tu->timeri->callback_data = (void *)tu;
- return 0;
+ if (err < 0) {
+ snd_timer_close(tu->timeri);
+ tu->timeri = NULL;
+ } else {
+ tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST;
+ tu->timeri->callback = tu->tread ? snd_timer_user_tinterrupt : snd_timer_user_interrupt;
+ tu->timeri->ccallback = snd_timer_user_ccallback;
+ tu->timeri->callback_data = (void *)tu;
+ }
+
+ __err:
+ up(&tu->tread_sem);
+ return err;
}
static int snd_timer_user_info(struct file *file, snd_timer_info_t __user *_info)
@@ -1669,6 +1672,23 @@ static int snd_timer_user_continue(struct file *file)
return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0;
}
+static int snd_timer_user_pause(struct file *file)
+{
+ int err;
+ snd_timer_user_t *tu;
+
+ tu = file->private_data;
+ snd_assert(tu->timeri != NULL, return -ENXIO);
+ return (err = snd_timer_pause(tu->timeri)) < 0 ? err : 0;
+}
+
+enum {
+ SNDRV_TIMER_IOCTL_START_OLD = _IO('T', 0x20),
+ SNDRV_TIMER_IOCTL_STOP_OLD = _IO('T', 0x21),
+ SNDRV_TIMER_IOCTL_CONTINUE_OLD = _IO('T', 0x22),
+ SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23),
+};
+
static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
snd_timer_user_t *tu;
@@ -1685,11 +1705,17 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned l
{
int xarg;
- if (tu->timeri) /* too late */
+ down(&tu->tread_sem);
+ if (tu->timeri) { /* too late */
+ up(&tu->tread_sem);
return -EBUSY;
- if (get_user(xarg, p))
+ }
+ if (get_user(xarg, p)) {
+ up(&tu->tread_sem);
return -EFAULT;
+ }
tu->tread = xarg ? 1 : 0;
+ up(&tu->tread_sem);
return 0;
}
case SNDRV_TIMER_IOCTL_GINFO:
@@ -1707,11 +1733,17 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned l
case SNDRV_TIMER_IOCTL_STATUS:
return snd_timer_user_status(file, argp);
case SNDRV_TIMER_IOCTL_START:
+ case SNDRV_TIMER_IOCTL_START_OLD:
return snd_timer_user_start(file);
case SNDRV_TIMER_IOCTL_STOP:
+ case SNDRV_TIMER_IOCTL_STOP_OLD:
return snd_timer_user_stop(file);
case SNDRV_TIMER_IOCTL_CONTINUE:
+ case SNDRV_TIMER_IOCTL_CONTINUE_OLD:
return snd_timer_user_continue(file);
+ case SNDRV_TIMER_IOCTL_PAUSE:
+ case SNDRV_TIMER_IOCTL_PAUSE_OLD:
+ return snd_timer_user_pause(file);
}
return -ENOTTY;
}
@@ -1898,4 +1930,3 @@ EXPORT_SYMBOL(snd_timer_global_free);
EXPORT_SYMBOL(snd_timer_global_register);
EXPORT_SYMBOL(snd_timer_global_unregister);
EXPORT_SYMBOL(snd_timer_interrupt);
-EXPORT_SYMBOL(snd_timer_system_resolution);
diff --git a/sound/core/timer_compat.c b/sound/core/timer_compat.c
index 9fbc3957a22..3de552dfe80 100644
--- a/sound/core/timer_compat.c
+++ b/sound/core/timer_compat.c
@@ -106,8 +106,13 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, uns
case SNDRV_TIMER_IOCTL_SELECT:
case SNDRV_TIMER_IOCTL_PARAMS:
case SNDRV_TIMER_IOCTL_START:
+ case SNDRV_TIMER_IOCTL_START_OLD:
case SNDRV_TIMER_IOCTL_STOP:
+ case SNDRV_TIMER_IOCTL_STOP_OLD:
case SNDRV_TIMER_IOCTL_CONTINUE:
+ case SNDRV_TIMER_IOCTL_CONTINUE_OLD:
+ case SNDRV_TIMER_IOCTL_PAUSE:
+ case SNDRV_TIMER_IOCTL_PAUSE_OLD:
case SNDRV_TIMER_IOCTL_NEXT_DEVICE:
return snd_timer_user_ioctl(file, cmd, (unsigned long)argp);
case SNDRV_TIMER_IOCTL_INFO32:
diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c
index 98587176b32..af381b15fe5 100644
--- a/sound/drivers/vx/vx_pcm.c
+++ b/sound/drivers/vx/vx_pcm.c
@@ -1264,14 +1264,10 @@ static void snd_vx_pcm_free(snd_pcm_t *pcm)
{
vx_core_t *chip = pcm->private_data;
chip->pcm[pcm->device] = NULL;
- if (chip->playback_pipes) {
- kfree(chip->playback_pipes);
- chip->playback_pipes = NULL;
- }
- if (chip->capture_pipes) {
- kfree(chip->capture_pipes);
- chip->capture_pipes = NULL;
- }
+ kfree(chip->playback_pipes);
+ chip->playback_pipes = NULL;
+ kfree(chip->capture_pipes);
+ chip->capture_pipes = NULL;
}
/*
diff --git a/sound/i2c/tea6330t.c b/sound/i2c/tea6330t.c
index bb503e70b66..2da8d7f157f 100644
--- a/sound/i2c/tea6330t.c
+++ b/sound/i2c/tea6330t.c
@@ -266,8 +266,7 @@ TEA6330T_TREBLE("Tone Control - Treble", 0)
static void snd_tea6330_free(snd_i2c_device_t *device)
{
- tea6330t_t *tea = device->private_data;
- kfree(tea);
+ kfree(device->private_data);
}
int snd_tea6330t_update_mixer(snd_card_t * card,
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index 3a3228b1872..148a856a43a 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -179,6 +179,7 @@ config SND_INTERWAVE_STB
select SND_RAWMIDI
select SND_CS4231_LIB
select SND_GUS_SYNTH
+ select ISAPNP
help
Say Y here to include support for AMD InterWave based
soundcards with a TEA6330T bass and treble regulator
diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c
index 9fa7a78da6c..563296d0289 100644
--- a/sound/isa/ad1816a/ad1816a.c
+++ b/sound/isa/ad1816a/ad1816a.c
@@ -83,6 +83,8 @@ struct snd_card_ad1816a {
static struct pnp_card_device_id snd_ad1816a_pnpids[] = {
/* Analog Devices AD1815 */
{ .id = "ADS7150", .devs = { { .id = "ADS7150" }, { .id = "ADS7151" } } },
+ /* Analog Device AD1816? */
+ { .id = "ADS7180", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
/* Analog Devices AD1816A - added by Kenneth Platz <kxp@atl.hp.com> */
{ .id = "ADS7181", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
/* Analog Devices AD1816A - Aztech/Newcom SC-16 3D */
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index e745a54e00a..39f4eff44f5 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -349,8 +349,7 @@ static int __devinit snd_card_cs4236_pnp(int dev, struct snd_card_cs4236 *acard,
pnp_init_resource_table(cfg);
if (mpu_port[dev] != SNDRV_AUTO_PORT)
pnp_resource_change(&cfg->port_resource[0], mpu_port[dev], 2);
- if (mpu_irq[dev] != SNDRV_AUTO_IRQ && mpu_irq[dev] >= 0 &&
- pnp_irq_valid(pdev, 0))
+ if (mpu_irq[dev] != SNDRV_AUTO_IRQ && mpu_irq[dev] >= 0)
pnp_resource_change(&cfg->irq_resource[0], mpu_irq[dev], 1);
err = pnp_manual_config_dev(pdev, cfg, 0);
if (err < 0)
diff --git a/sound/isa/gus/gus_io.c b/sound/isa/gus/gus_io.c
index f0570f2bf75..337b0e2a8a3 100644
--- a/sound/isa/gus/gus_io.c
+++ b/sound/isa/gus/gus_io.c
@@ -244,6 +244,8 @@ unsigned short snd_gf1_i_look16(snd_gus_card_t * gus, unsigned char reg)
return res;
}
+#if 0
+
void snd_gf1_i_adlib_write(snd_gus_card_t * gus,
unsigned char reg,
unsigned char data)
@@ -265,6 +267,8 @@ void snd_gf1_i_write_addr(snd_gus_card_t * gus, unsigned char reg,
spin_unlock_irqrestore(&gus->reg_lock, flags);
}
+#endif /* 0 */
+
unsigned int snd_gf1_i_read_addr(snd_gus_card_t * gus,
unsigned char reg, short w_16bit)
{
@@ -329,6 +333,8 @@ unsigned char snd_gf1_peek(snd_gus_card_t * gus, unsigned int addr)
return res;
}
+#if 0
+
void snd_gf1_pokew(snd_gus_card_t * gus, unsigned int addr, unsigned short data)
{
unsigned long flags;
@@ -405,9 +411,7 @@ void snd_gf1_dram_setmem(snd_gus_card_t * gus, unsigned int addr,
spin_unlock_irqrestore(&gus->reg_lock, flags);
}
-/*
-
- */
+#endif /* 0 */
void snd_gf1_select_active_voices(snd_gus_card_t * gus)
{
@@ -469,6 +473,8 @@ void snd_gf1_print_voice_registers(snd_gus_card_t * gus)
printk(" -%i- GF1 pan = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x0c));
}
+#if 0
+
void snd_gf1_print_global_registers(snd_gus_card_t * gus)
{
unsigned char global_mode = 0x00;
@@ -528,4 +534,6 @@ void snd_gf1_peek_print_block(snd_gus_card_t * gus, unsigned int addr, int count
}
}
+#endif /* 0 */
+
#endif
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c
index 73f81c14f76..94bbd344be5 100644
--- a/sound/isa/gus/gus_main.c
+++ b/sound/isa/gus/gus_main.c
@@ -459,7 +459,6 @@ EXPORT_SYMBOL(snd_gf1_write16);
EXPORT_SYMBOL(snd_gf1_look16);
EXPORT_SYMBOL(snd_gf1_i_write8);
EXPORT_SYMBOL(snd_gf1_i_look8);
-EXPORT_SYMBOL(snd_gf1_i_write16);
EXPORT_SYMBOL(snd_gf1_i_look16);
EXPORT_SYMBOL(snd_gf1_dram_addr);
EXPORT_SYMBOL(snd_gf1_write_addr);
@@ -470,8 +469,6 @@ EXPORT_SYMBOL(snd_gf1_alloc_voice);
EXPORT_SYMBOL(snd_gf1_free_voice);
EXPORT_SYMBOL(snd_gf1_ctrl_stop);
EXPORT_SYMBOL(snd_gf1_stop_voice);
-EXPORT_SYMBOL(snd_gf1_start);
-EXPORT_SYMBOL(snd_gf1_stop);
/* gus_mixer.c */
EXPORT_SYMBOL(snd_gf1_new_mixer);
/* gus_pcm.c */
diff --git a/sound/isa/gus/gus_mem.c b/sound/isa/gus/gus_mem.c
index bfc2b91001d..5eb766dd564 100644
--- a/sound/isa/gus/gus_mem.c
+++ b/sound/isa/gus/gus_mem.c
@@ -21,6 +21,7 @@
#include <sound/driver.h>
#include <linux/slab.h>
+#include <linux/string.h>
#include <sound/core.h>
#include <sound/gus.h>
#include <sound/info.h>
@@ -39,8 +40,8 @@ void snd_gf1_mem_lock(snd_gf1_mem_t * alloc, int xup)
}
}
-snd_gf1_mem_block_t *snd_gf1_mem_xalloc(snd_gf1_mem_t * alloc,
- snd_gf1_mem_block_t * block)
+static snd_gf1_mem_block_t *snd_gf1_mem_xalloc(snd_gf1_mem_t * alloc,
+ snd_gf1_mem_block_t * block)
{
snd_gf1_mem_block_t *pblock, *nblock;
@@ -105,8 +106,8 @@ int snd_gf1_mem_xfree(snd_gf1_mem_t * alloc, snd_gf1_mem_block_t * block)
return 0;
}
-snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc,
- unsigned int address)
+static snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc,
+ unsigned int address)
{
snd_gf1_mem_block_t *block;
@@ -118,8 +119,8 @@ snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc,
return NULL;
}
-snd_gf1_mem_block_t *snd_gf1_mem_share(snd_gf1_mem_t * alloc,
- unsigned int *share_id)
+static snd_gf1_mem_block_t *snd_gf1_mem_share(snd_gf1_mem_t * alloc,
+ unsigned int *share_id)
{
snd_gf1_mem_block_t *block;
@@ -213,7 +214,7 @@ snd_gf1_mem_block_t *snd_gf1_mem_alloc(snd_gf1_mem_t * alloc, int owner,
if (share_id != NULL)
memcpy(&block.share_id, share_id, sizeof(block.share_id));
block.owner = owner;
- block.name = snd_kmalloc_strdup(name, GFP_KERNEL);
+ block.name = kstrdup(name, GFP_KERNEL);
nblock = snd_gf1_mem_xalloc(alloc, &block);
snd_gf1_mem_lock(alloc, 1);
return nblock;
@@ -253,13 +254,13 @@ int snd_gf1_mem_init(snd_gus_card_t * gus)
if (gus->gf1.enh_mode) {
block.ptr = 0;
block.size = 1024;
- block.name = snd_kmalloc_strdup("InterWave LFOs", GFP_KERNEL);
+ block.name = kstrdup("InterWave LFOs", GFP_KERNEL);
if (snd_gf1_mem_xalloc(alloc, &block) == NULL)
return -ENOMEM;
}
block.ptr = gus->gf1.default_voice_address;
block.size = 4;
- block.name = snd_kmalloc_strdup("Voice default (NULL's)", GFP_KERNEL);
+ block.name = kstrdup("Voice default (NULL's)", GFP_KERNEL);
if (snd_gf1_mem_xalloc(alloc, &block) == NULL)
return -ENOMEM;
#ifdef CONFIG_SND_DEBUG
diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c
index 8995ad9c516..b75066ab46f 100644
--- a/sound/isa/gus/gus_pcm.c
+++ b/sound/isa/gus/gus_pcm.c
@@ -656,8 +656,7 @@ static snd_pcm_hardware_t snd_gf1_pcm_capture =
static void snd_gf1_pcm_playback_free(snd_pcm_runtime_t *runtime)
{
- gus_pcm_private_t * pcmp = runtime->private_data;
- kfree(pcmp);
+ kfree(runtime->private_data);
}
static int snd_gf1_pcm_playback_open(snd_pcm_substream_t *substream)
diff --git a/sound/isa/gus/gus_reset.c b/sound/isa/gus/gus_reset.c
index b4e66f6a10a..ef687abc707 100644
--- a/sound/isa/gus/gus_reset.c
+++ b/sound/isa/gus/gus_reset.c
@@ -161,7 +161,8 @@ void snd_gf1_stop_voice(snd_gus_card_t * gus, unsigned short voice)
#endif
}
-void snd_gf1_clear_voices(snd_gus_card_t * gus, unsigned short v_min, unsigned short v_max)
+static void snd_gf1_clear_voices(snd_gus_card_t * gus, unsigned short v_min,
+ unsigned short v_max)
{
unsigned long flags;
unsigned int daddr;
diff --git a/sound/isa/gus/gus_synth.c b/sound/isa/gus/gus_synth.c
index 66552e6013a..f51c386ee19 100644
--- a/sound/isa/gus/gus_synth.c
+++ b/sound/isa/gus/gus_synth.c
@@ -99,7 +99,8 @@ static void snd_gus_synth_free_private_instruments(snd_gus_port_t *p, int client
snd_seq_instr_list_free_cond(p->gus->gf1.ilist, &ifree, client, 0);
}
-int snd_gus_synth_event_input(snd_seq_event_t *ev, int direct, void *private_data, int atomic, int hop)
+static int snd_gus_synth_event_input(snd_seq_event_t *ev, int direct,
+ void *private_data, int atomic, int hop)
{
snd_gus_port_t * p = (snd_gus_port_t *) private_data;
diff --git a/sound/isa/gus/gus_tables.h b/sound/isa/gus/gus_tables.h
index ed8e9d85ad3..4adf098d326 100644
--- a/sound/isa/gus/gus_tables.h
+++ b/sound/isa/gus/gus_tables.h
@@ -23,6 +23,8 @@
#ifdef __GUS_TABLES_ALLOC__
+#if 0
+
unsigned int snd_gf1_scale_table[SNDRV_GF1_SCALE_TABLE_SIZE] =
{
8372, 8870, 9397, 9956, 10548, 11175,
@@ -49,6 +51,8 @@ unsigned int snd_gf1_scale_table[SNDRV_GF1_SCALE_TABLE_SIZE] =
12123977, 12844906
};
+#endif /* 0 */
+
unsigned short snd_gf1_atten_table[SNDRV_GF1_ATTEN_TABLE_SIZE] = {
4095 /* 0 */,1789 /* 1 */,1533 /* 2 */,1383 /* 3 */,1277 /* 4 */,
1195 /* 5 */,1127 /* 6 */,1070 /* 7 */,1021 /* 8 */,978 /* 9 */,
diff --git a/sound/isa/gus/gus_volume.c b/sound/isa/gus/gus_volume.c
index b72bcfb2861..3d36f6c8ee6 100644
--- a/sound/isa/gus/gus_volume.c
+++ b/sound/isa/gus/gus_volume.c
@@ -55,6 +55,8 @@ unsigned short snd_gf1_lvol_to_gvol_raw(unsigned int vol)
return (e << 8) | m;
}
+#if 0
+
unsigned int snd_gf1_gvol_to_lvol_raw(unsigned short gf1_vol)
{
unsigned int rvol;
@@ -108,6 +110,8 @@ unsigned int snd_gf1_calc_ramp_rate(snd_gus_card_t * gus,
return (range << 6) | (increment & 0x3f);
}
+#endif /* 0 */
+
unsigned short snd_gf1_translate_freq(snd_gus_card_t * gus, unsigned int freq16)
{
freq16 >>= 3;
@@ -120,6 +124,8 @@ unsigned short snd_gf1_translate_freq(snd_gus_card_t * gus, unsigned int freq16)
return ((freq16 << 9) + (gus->gf1.playback_freq >> 1)) / gus->gf1.playback_freq;
}
+#if 0
+
short snd_gf1_compute_vibrato(short cents, unsigned short fc_register)
{
static short vibrato_table[] =
@@ -208,3 +214,5 @@ unsigned short snd_gf1_compute_freq(unsigned int freq,
}
return (unsigned short) fc;
}
+
+#endif /* 0 */
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig
index a9602f89d6b..3b1fafc8f4f 100644
--- a/sound/oss/Kconfig
+++ b/sound/oss/Kconfig
@@ -6,7 +6,7 @@
# Prompt user for primary drivers.
config SOUND_BT878
tristate "BT878 audio dma"
- depends on SOUND_PRIME!=n && SOUND
+ depends on SOUND_PRIME
---help---
Audio DMA support for bt878 based grabber boards. As you might have
already noticed, bt878 is listed with two functions in /proc/pci.
@@ -22,7 +22,7 @@ config SOUND_BT878
config SOUND_CMPCI
tristate "C-Media PCI (CMI8338/8738)"
- depends on SOUND_PRIME!=n && SOUND && PCI
+ depends on SOUND_PRIME && PCI
help
Say Y or M if you have a PCI sound card using the CMI8338
or the CMI8738 chipset. Data on these chips are available at
@@ -61,7 +61,7 @@ config SOUND_CMPCI_JOYSTICK
config SOUND_EMU10K1
tristate "Creative SBLive! (EMU10K1)"
- depends on SOUND_PRIME!=n && SOUND && PCI
+ depends on SOUND_PRIME && PCI
---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.
@@ -87,7 +87,7 @@ config MIDI_EMU10K1
config SOUND_FUSION
tristate "Crystal SoundFusion (CS4280/461x)"
- depends on SOUND_PRIME!=n && SOUND
+ depends on SOUND_PRIME
help
This module drives the Crystal SoundFusion devices (CS4280/46xx
series) when wired as native sound drivers with AC97 codecs. If
@@ -95,14 +95,14 @@ config SOUND_FUSION
config SOUND_CS4281
tristate "Crystal Sound CS4281"
- depends on SOUND_PRIME!=n && SOUND
+ depends on SOUND_PRIME
help
Picture and feature list at
<http://www.pcbroker.com/crystal4281.html>.
config SOUND_BCM_CS4297A
tristate "Crystal Sound CS4297a (for Swarm)"
- depends on SOUND_PRIME!=n && SIBYTE_SWARM && SOUND
+ depends on SOUND_PRIME && SIBYTE_SWARM
help
The BCM91250A has a Crystal CS4297a on synchronous serial
port B (in addition to the DB-9 serial port). Say Y or M
@@ -112,7 +112,7 @@ config SOUND_BCM_CS4297A
config SOUND_ES1370
tristate "Ensoniq AudioPCI (ES1370)"
- depends on SOUND_PRIME!=n && SOUND && PCI && SOUND_GAMEPORT
+ depends on SOUND_PRIME && PCI
help
Say Y or M if you have a PCI sound card utilizing the Ensoniq
ES1370 chipset, such as Ensoniq's AudioPCI (non-97). To find
@@ -125,7 +125,7 @@ config SOUND_ES1370
config SOUND_ES1371
tristate "Creative Ensoniq AudioPCI 97 (ES1371)"
- depends on SOUND_PRIME!=n && SOUND && PCI && SOUND_GAMEPORT
+ depends on SOUND_PRIME && PCI
help
Say Y or M if you have a PCI sound card utilizing the Ensoniq
ES1371 chipset, such as Ensoniq's AudioPCI97. To find out if
@@ -138,7 +138,7 @@ config SOUND_ES1371
config SOUND_ESSSOLO1
tristate "ESS Technology Solo1"
- depends on SOUND_PRIME!=n && SOUND && SOUND_GAMEPORT && PCI
+ depends on SOUND_PRIME && PCI
help
Say Y or M if you have a PCI sound card utilizing the ESS Technology
Solo1 chip. To find out if your sound card uses a
@@ -149,7 +149,7 @@ config SOUND_ESSSOLO1
config SOUND_MAESTRO
tristate "ESS Maestro, Maestro2, Maestro2E driver"
- depends on SOUND_PRIME!=n && SOUND && PCI
+ depends on SOUND_PRIME && PCI
help
Say Y or M if you have a sound system driven by ESS's Maestro line
of PCI sound chips. These include the Maestro 1, Maestro 2, and
@@ -158,28 +158,28 @@ config SOUND_MAESTRO
config SOUND_MAESTRO3
tristate "ESS Maestro3/Allegro driver (EXPERIMENTAL)"
- depends on SOUND_PRIME!=n && SOUND && PCI && EXPERIMENTAL
+ depends on SOUND_PRIME && PCI && EXPERIMENTAL
help
Say Y or M if you have a sound system driven by ESS's Maestro 3
PCI sound chip.
config SOUND_ICH
tristate "Intel ICH (i8xx) audio support"
- depends on SOUND_PRIME!=n && PCI
+ depends on SOUND_PRIME && PCI
help
Support for integral audio in Intel's I/O Controller Hub (ICH)
chipset, as used on the 810/820/840 motherboards.
config SOUND_HARMONY
tristate "PA Harmony audio driver"
- depends on GSC_LASI && SOUND_PRIME!=n
+ depends on GSC_LASI && SOUND_PRIME
help
Say 'Y' or 'M' to include support for Harmony soundchip
on HP 712, 715/new and many other GSC based machines.
config SOUND_SONICVIBES
tristate "S3 SonicVibes"
- depends on SOUND_PRIME!=n && SOUND && SOUND_GAMEPORT
+ depends on SOUND_PRIME
help
Say Y or M if you have a PCI sound card utilizing the S3
SonicVibes chipset. To find out if your sound card uses a
@@ -190,7 +190,7 @@ config SOUND_SONICVIBES
config SOUND_VWSND
tristate "SGI Visual Workstation Sound"
- depends on SOUND_PRIME!=n && X86_VISWS && SOUND
+ depends on SOUND_PRIME && X86_VISWS
help
Say Y or M if you have an SGI Visual Workstation and you want to be
able to use its on-board audio. Read
@@ -199,18 +199,18 @@ config SOUND_VWSND
config SOUND_HAL2
tristate "SGI HAL2 sound (EXPERIMENTAL)"
- depends on SOUND_PRIME!=n && SOUND && SGI_IP22 && EXPERIMENTAL
+ depends on SOUND_PRIME && SGI_IP22 && EXPERIMENTAL
help
Say Y or M if you have an SGI Indy system and want to be able to
use it's on-board A2 audio system.
config SOUND_IT8172
tristate "IT8172G Sound"
- depends on SOUND_PRIME!=n && (MIPS_ITE8172 || MIPS_IVR) && SOUND
+ depends on SOUND_PRIME && (MIPS_ITE8172 || MIPS_IVR)
config SOUND_VRC5477
tristate "NEC Vrc5477 AC97 sound"
- depends on SOUND_PRIME!=n && DDB5477 && SOUND
+ depends on SOUND_PRIME && DDB5477
help
Say Y here to enable sound support for the NEC Vrc5477 chip, an
integrated, multi-function controller chip for MIPS CPUs. Works
@@ -218,15 +218,15 @@ config SOUND_VRC5477
config SOUND_AU1000
tristate "Au1000 Sound"
- depends on SOUND_PRIME!=n && (SOC_AU1000 || SOC_AU1100 || SOC_AU1500) && SOUND
+ depends on SOUND_PRIME && (SOC_AU1000 || SOC_AU1100 || SOC_AU1500)
config SOUND_AU1550_AC97
tristate "Au1550 AC97 Sound"
- depends on SOUND_PRIME!=n && SOC_AU1550 && SOUND
+ depends on SOUND_PRIME && SOC_AU1550
config SOUND_TRIDENT
tristate "Trident 4DWave DX/NX, SiS 7018 or ALi 5451 PCI Audio Core"
- depends on SOUND_PRIME!=n && SOUND && SOUND_GAMEPORT
+ depends on SOUND_PRIME
---help---
Say Y or M if you have a PCI sound card utilizing the Trident
4DWave-DX/NX chipset or your mother board chipset has SiS 7018
@@ -267,7 +267,7 @@ config SOUND_TRIDENT
config SOUND_MSNDCLAS
tristate "Support for Turtle Beach MultiSound Classic, Tahiti, Monterey"
- depends on SOUND_PRIME!=n && SOUND && (m || !STANDALONE)
+ depends on SOUND_PRIME && (m || !STANDALONE)
help
Say M here if you have a Turtle Beach MultiSound Classic, Tahiti or
Monterey (not for the Pinnacle or Fiji).
@@ -331,7 +331,7 @@ config MSNDCLAS_IO
config SOUND_MSNDPIN
tristate "Support for Turtle Beach MultiSound Pinnacle, Fiji"
- depends on SOUND_PRIME!=n && SOUND && (m || !STANDALONE)
+ depends on SOUND_PRIME && (m || !STANDALONE)
help
Say M here if you have a Turtle Beach MultiSound Pinnacle or Fiji.
See <file:Documentation/sound/oss/MultiSound> for important information
@@ -492,7 +492,7 @@ config MSND_FIFOSIZE
config SOUND_VIA82CXXX
tristate "VIA 82C686 Audio Codec"
- depends on SOUND_PRIME!=n && PCI
+ depends on SOUND_PRIME && PCI
help
Say Y here to include support for the audio codec found on VIA
82Cxxx-based chips. Typically these are built into a motherboard.
@@ -512,7 +512,7 @@ config MIDI_VIA82CXXX
config SOUND_OSS
tristate "OSS sound modules"
- depends on SOUND_PRIME!=n && SOUND
+ depends on SOUND_PRIME
help
OSS is the Open Sound System suite of sound card drivers. They make
sound programming easier since they provide a common API. Say Y or
@@ -739,7 +739,7 @@ config SOUND_NM256
config SOUND_MAD16
tristate "OPTi MAD16 and/or Mozart based cards"
- depends on SOUND_OSS && SOUND_GAMEPORT
+ depends on SOUND_OSS
---help---
Answer Y if your card has a Mozart (OAK OTI-601) or MAD16 (OPTi
82C928 or 82C929 or 82C931) audio interface chip. These chips are
@@ -1077,7 +1077,7 @@ config SOUND_WAVEARTIST
config SOUND_TVMIXER
tristate "TV card (bt848) mixer support"
- depends on SOUND_PRIME!=n && SOUND && I2C
+ depends on SOUND_PRIME && I2C
help
Support for audio mixer facilities on the BT848 TV frame-grabber
card.
@@ -1088,11 +1088,11 @@ config SOUND_KAHLUA
config SOUND_ALI5455
tristate "ALi5455 audio support"
- depends on SOUND_PRIME!=n && PCI
+ depends on SOUND_PRIME && PCI
config SOUND_FORTE
tristate "ForteMedia FM801 driver"
- depends on SOUND_PRIME!=n && PCI
+ depends on SOUND_PRIME && PCI
help
Say Y or M if you want driver support for the ForteMedia FM801 PCI
audio controller (Abit AU10, Genius Sound Maker, HP Workstation
@@ -1100,7 +1100,7 @@ config SOUND_FORTE
config SOUND_RME96XX
tristate "RME Hammerfall (RME96XX) support"
- depends on SOUND_PRIME!=n && PCI
+ depends on SOUND_PRIME && PCI
help
Say Y or M if you have a Hammerfall or Hammerfall light
multichannel card from RME. If you want to access advanced
@@ -1108,11 +1108,11 @@ config SOUND_RME96XX
config SOUND_AD1980
tristate "AD1980 front/back switch plugin"
- depends on SOUND_PRIME!=n
+ depends on SOUND_PRIME
config SOUND_SH_DAC_AUDIO
tristate "SuperH DAC audio support"
- depends on SOUND_PRIME!=n && SOUND && CPU_SH3
+ depends on SOUND_PRIME && CPU_SH3
config SOUND_SH_DAC_AUDIO_CHANNEL
int " DAC channel"
diff --git a/sound/oss/ad1816.c b/sound/oss/ad1816.c
index 22dae5d0fda..95586de0202 100644
--- a/sound/oss/ad1816.c
+++ b/sound/oss/ad1816.c
@@ -592,7 +592,7 @@ typedef struct mixer_def mixer_ent;
{{reg_l, pola_l, pos_l, len_l}, {reg_r, pola_r, pos_r, len_r}}
-mixer_ent mix_devices[SOUND_MIXER_NRDEVICES][2] = {
+static mixer_ent mix_devices[SOUND_MIXER_NRDEVICES][2] = {
MIX_ENT(SOUND_MIXER_VOLUME, 14, 1, 8, 5, 14, 1, 0, 5),
MIX_ENT(SOUND_MIXER_BASS, 0, 0, 0, 0, 0, 0, 0, 0),
MIX_ENT(SOUND_MIXER_TREBLE, 0, 0, 0, 0, 0, 0, 0, 0),
diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c
index 4384dac3f79..7c835abd99b 100644
--- a/sound/oss/ad1848.c
+++ b/sound/oss/ad1848.c
@@ -2178,8 +2178,7 @@ void ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int
if (devc != NULL)
{
- if(audio_devs[dev]->portc!=NULL)
- kfree(audio_devs[dev]->portc);
+ kfree(audio_devs[dev]->portc);
release_region(devc->base, 4);
if (!share_dma)
diff --git a/sound/oss/ad1889.c b/sound/oss/ad1889.c
index b767c621fd0..2cfd214e4c2 100644
--- a/sound/oss/ad1889.c
+++ b/sound/oss/ad1889.c
@@ -277,8 +277,7 @@ static void ad1889_free_dev(ad1889_dev_t *dev)
for (j = 0; j < AD_MAX_STATES; j++) {
dmabuf = &dev->state[j].dmabuf;
- if (dmabuf->rawbuf != NULL)
- kfree(dmabuf->rawbuf);
+ kfree(dmabuf->rawbuf);
}
kfree(dev);
diff --git a/sound/oss/cmpci.c b/sound/oss/cmpci.c
index 34720e66dae..74dcca78c6c 100644
--- a/sound/oss/cmpci.c
+++ b/sound/oss/cmpci.c
@@ -123,6 +123,7 @@
#include <linux/smp_lock.h>
#include <linux/bitops.h>
#include <linux/wait.h>
+#include <linux/dma-mapping.h>
#include <asm/io.h>
#include <asm/page.h>
@@ -3058,7 +3059,7 @@ static int __devinit cm_probe(struct pci_dev *pcidev, const struct pci_device_id
return -ENODEV;
if (pcidev->irq == 0)
return -ENODEV;
- i = pci_set_dma_mask(pcidev, 0xffffffff);
+ i = pci_set_dma_mask(pcidev, DMA_32BIT_MASK);
if (i) {
printk(KERN_WARNING "cmpci: architecture does not support 32bit PCI busmaster DMA\n");
return i;
diff --git a/sound/oss/dmasound/dmasound_awacs.c b/sound/oss/dmasound/dmasound_awacs.c
index 5281b88987f..33108661e67 100644
--- a/sound/oss/dmasound/dmasound_awacs.c
+++ b/sound/oss/dmasound/dmasound_awacs.c
@@ -671,14 +671,10 @@ static void PMacIrqCleanup(void)
release_OF_resource(awacs_node, 1);
release_OF_resource(awacs_node, 2);
- if (awacs_tx_cmd_space)
- kfree(awacs_tx_cmd_space);
- if (awacs_rx_cmd_space)
- kfree(awacs_rx_cmd_space);
- if (beep_dbdma_cmd_space)
- kfree(beep_dbdma_cmd_space);
- if (beep_buf)
- kfree(beep_buf);
+ kfree(awacs_tx_cmd_space);
+ kfree(awacs_rx_cmd_space);
+ kfree(beep_dbdma_cmd_space);
+ kfree(beep_buf);
#ifdef CONFIG_PMAC_PBOOK
pmu_unregister_sleep_notifier(&awacs_sleep_notifier);
#endif
@@ -2301,8 +2297,7 @@ if (count <= 0)
#endif
if ((write_sq.max_count + 1) > number_of_tx_cmd_buffers) {
- if (awacs_tx_cmd_space)
- kfree(awacs_tx_cmd_space);
+ kfree(awacs_tx_cmd_space);
number_of_tx_cmd_buffers = 0;
/* we need nbufs + 1 (for the loop) and we should request + 1
@@ -2360,8 +2355,7 @@ if (count <= 0)
#endif
if ((read_sq.max_count+1) > number_of_rx_cmd_buffers ) {
- if (awacs_rx_cmd_space)
- kfree(awacs_rx_cmd_space);
+ kfree(awacs_rx_cmd_space);
number_of_rx_cmd_buffers = 0;
/* we need nbufs + 1 (for the loop) and we should request + 1 again
@@ -2805,7 +2799,7 @@ __init setup_beep(void)
beep_buf = (short *) kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL);
if (beep_buf == NULL) {
printk(KERN_ERR "dmasound_pmac: no memory for beep buffer\n");
- if( beep_dbdma_cmd_space ) kfree(beep_dbdma_cmd_space) ;
+ kfree(beep_dbdma_cmd_space) ;
return -ENOMEM ;
}
return 0 ;
diff --git a/sound/oss/emu10k1/midi.c b/sound/oss/emu10k1/midi.c
index 33dea3d56c1..b40b5f97aac 100644
--- a/sound/oss/emu10k1/midi.c
+++ b/sound/oss/emu10k1/midi.c
@@ -523,10 +523,8 @@ void emu10k1_seq_midi_close(int dev)
card = midi_devs[dev]->devc;
emu10k1_mpuout_close(card);
- if (card->seq_mididev) {
- kfree(card->seq_mididev);
- card->seq_mididev = NULL;
- }
+ kfree(card->seq_mididev);
+ card->seq_mididev = NULL;
}
int emu10k1_seq_midi_out(int dev, unsigned char midi_byte)
diff --git a/sound/oss/emu10k1/passthrough.c b/sound/oss/emu10k1/passthrough.c
index 4094be55f3b..4e3baca7d41 100644
--- a/sound/oss/emu10k1/passthrough.c
+++ b/sound/oss/emu10k1/passthrough.c
@@ -213,8 +213,7 @@ void emu10k1_pt_stop(struct emu10k1_card *card)
sblive_writeptr(card, SPCS0 + i, 0, pt->old_spcs[i]);
}
pt->state = PT_STATE_INACTIVE;
- if(pt->buf)
- kfree(pt->buf);
+ kfree(pt->buf);
}
}
diff --git a/sound/oss/es1370.c b/sound/oss/es1370.c
index 056091cff26..886f61c1c34 100644
--- a/sound/oss/es1370.c
+++ b/sound/oss/es1370.c
@@ -156,6 +156,7 @@
#include <linux/spinlock.h>
#include <linux/gameport.h>
#include <linux/wait.h>
+#include <linux/dma-mapping.h>
#include <asm/io.h>
#include <asm/page.h>
@@ -2569,7 +2570,7 @@ static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_devic
return -ENODEV;
if (pcidev->irq == 0)
return -ENODEV;
- i = pci_set_dma_mask(pcidev, 0xffffffff);
+ i = pci_set_dma_mask(pcidev, DMA_32BIT_MASK);
if (i) {
printk(KERN_WARNING "es1370: architecture does not support 32bit PCI busmaster DMA\n");
return i;
diff --git a/sound/oss/es1371.c b/sound/oss/es1371.c
index a50fddaeea2..9266b777387 100644
--- a/sound/oss/es1371.c
+++ b/sound/oss/es1371.c
@@ -128,6 +128,7 @@
#include <linux/ac97_codec.h>
#include <linux/gameport.h>
#include <linux/wait.h>
+#include <linux/dma-mapping.h>
#include <asm/io.h>
#include <asm/page.h>
@@ -2804,7 +2805,7 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic
return -ENODEV;
if (pcidev->irq == 0)
return -ENODEV;
- i = pci_set_dma_mask(pcidev, 0xffffffff);
+ i = pci_set_dma_mask(pcidev, DMA_32BIT_MASK);
if (i) {
printk(KERN_WARNING "es1371: architecture does not support 32bit PCI busmaster DMA\n");
return i;
diff --git a/sound/oss/esssolo1.c b/sound/oss/esssolo1.c
index 6b3b9a99579..fb09065d07c 100644
--- a/sound/oss/esssolo1.c
+++ b/sound/oss/esssolo1.c
@@ -104,6 +104,7 @@
#include <linux/smp_lock.h>
#include <linux/gameport.h>
#include <linux/wait.h>
+#include <linux/dma-mapping.h>
#include <asm/io.h>
#include <asm/page.h>
@@ -2326,7 +2327,7 @@ static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device
* to 24 bits first, then 32 bits (playback only) if that fails.
*/
if (pci_set_dma_mask(pcidev, 0x00ffffff) &&
- pci_set_dma_mask(pcidev, 0xffffffff)) {
+ pci_set_dma_mask(pcidev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "solo1: architecture does not support 24bit or 32bit PCI busmaster DMA\n");
return -ENODEV;
}
diff --git a/sound/oss/maestro.c b/sound/oss/maestro.c
index 52d2db4bc31..3dce504e6d6 100644
--- a/sound/oss/maestro.c
+++ b/sound/oss/maestro.c
@@ -2356,7 +2356,7 @@ ess_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
}
rec_return_free:
- if(combbuf) kfree(combbuf);
+ kfree(combbuf);
return ret;
}
diff --git a/sound/oss/mpu401.c b/sound/oss/mpu401.c
index b66f53fa8db..0aac54c68f0 100644
--- a/sound/oss/mpu401.c
+++ b/sound/oss/mpu401.c
@@ -1240,8 +1240,7 @@ void unload_mpu401(struct address_info *hw_config)
p=mpu401_synth_operations[n];
sound_unload_mididev(n);
sound_unload_timerdev(hw_config->slots[2]);
- if(p)
- kfree(p);
+ kfree(p);
}
}
diff --git a/sound/oss/nm256.h b/sound/oss/nm256.h
index eae7d99d682..21e07b5081f 100644
--- a/sound/oss/nm256.h
+++ b/sound/oss/nm256.h
@@ -128,9 +128,6 @@ struct nm256_info
struct nm256_info *next_card;
};
-/* Debug flag--bigger numbers mean more output. */
-extern int nm256_debug;
-
/* The BIOS signature. */
#define NM_SIGNATURE 0x4e4d0000
/* Signature mask. */
@@ -284,7 +281,7 @@ nm256_readBuffer8 (struct nm256_info *card, u8 *dst, int port, int offset,
}
/* Returns a non-zero value if we should use the coefficient cache. */
-extern int nm256_cachedCoefficients (struct nm256_info *card);
+static int nm256_cachedCoefficients (struct nm256_info *card);
#endif
diff --git a/sound/oss/nm256_audio.c b/sound/oss/nm256_audio.c
index f9166e13519..66970062eb3 100644
--- a/sound/oss/nm256_audio.c
+++ b/sound/oss/nm256_audio.c
@@ -28,12 +28,13 @@
#include <linux/delay.h>
#include <linux/spinlock.h>
#include "sound_config.h"
-#include "nm256.h"
-#include "nm256_coeff.h"
-int nm256_debug;
+static int nm256_debug;
static int force_load;
+#include "nm256.h"
+#include "nm256_coeff.h"
+
/*
* The size of the playback reserve. When the playback buffer has less
* than NM256_PLAY_WMARK_SIZE bytes to output, we request a new
@@ -138,7 +139,7 @@ static int usecache;
static int buffertop;
/* Check to see if we're using the bank of cached coefficients. */
-int
+static int
nm256_cachedCoefficients (struct nm256_info *card)
{
return usecache;
diff --git a/sound/oss/nm256_coeff.h b/sound/oss/nm256_coeff.h
index 0ceecc20077..6fc07f3cb33 100644
--- a/sound/oss/nm256_coeff.h
+++ b/sound/oss/nm256_coeff.h
@@ -4650,7 +4650,7 @@ nm256_loadAllCoefficients (struct nm256_info *card)
card->coeffsCurrent = 1;
}
-void
+static void
nm256_loadCoefficient (struct nm256_info *card, int which, int number)
{
static u16 addrs[3] = { 0x1c, 0x21c, 0x408 };
diff --git a/sound/oss/rme96xx.c b/sound/oss/rme96xx.c
index 76774bbc143..7609c68a89f 100644
--- a/sound/oss/rme96xx.c
+++ b/sound/oss/rme96xx.c
@@ -807,7 +807,7 @@ static void* busmaster_malloc(int size) {
struct page* page, *last_page;
page = virt_to_page(buf);
- last_page = virt_to_page(buf + (1 << pg));
+ last_page = page + (1 << pg);
DBG(printk("setting reserved bit\n"));
while (page < last_page) {
SetPageReserved(page);
@@ -1750,9 +1750,7 @@ static unsigned int rme96xx_poll(struct file *file, struct poll_table_struct *wa
static struct file_operations rme96xx_audio_fops = {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
.owner = THIS_MODULE,
-#endif
.read = rme96xx_read,
.write = rme96xx_write,
.poll = rme96xx_poll,
@@ -1852,9 +1850,7 @@ static int rme96xx_mixer_release(struct inode *inode, struct file *file)
}
static /*const*/ struct file_operations rme96xx_mixer_fops = {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
.owner = THIS_MODULE,
-#endif
.ioctl = rme96xx_mixer_ioctl,
.open = rme96xx_mixer_open,
.release = rme96xx_mixer_release,
diff --git a/sound/oss/sb_common.c b/sound/oss/sb_common.c
index ce359e6c933..5f955e3d2e2 100644
--- a/sound/oss/sb_common.c
+++ b/sound/oss/sb_common.c
@@ -915,8 +915,8 @@ void sb_dsp_unload(struct address_info *hw_config, int sbmpu)
}
else
release_region(hw_config->io_base, 16);
- if(detected_devc)
- kfree(detected_devc);
+
+ kfree(detected_devc);
}
/*
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c
index de91c90a011..a686be936af 100644
--- a/sound/oss/soundcard.c
+++ b/sound/oss/soundcard.c
@@ -73,7 +73,7 @@ static char dma_alloc_map[MAX_DMA_CHANNELS];
unsigned long seq_time = 0; /* Time for /dev/sequencer */
-extern struct class_simple *sound_class;
+extern struct class *sound_class;
/*
* Table for configurable mixer volume handling
@@ -567,9 +567,9 @@ static int __init oss_init(void)
devfs_mk_cdev(MKDEV(SOUND_MAJOR, dev_list[i].minor),
S_IFCHR | dev_list[i].mode,
"sound/%s", dev_list[i].name);
- class_simple_device_add(sound_class,
- MKDEV(SOUND_MAJOR, dev_list[i].minor),
- NULL, "%s", dev_list[i].name);
+ class_device_create(sound_class,
+ MKDEV(SOUND_MAJOR, dev_list[i].minor),
+ NULL, "%s", dev_list[i].name);
if (!dev_list[i].num)
continue;
@@ -579,10 +579,9 @@ static int __init oss_init(void)
dev_list[i].minor + (j*0x10)),
S_IFCHR | dev_list[i].mode,
"sound/%s%d", dev_list[i].name, j);
- class_simple_device_add(sound_class,
- MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)),
- NULL,
- "%s%d", dev_list[i].name, j);
+ class_device_create(sound_class,
+ MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)),
+ NULL, "%s%d", dev_list[i].name, j);
}
}
@@ -598,12 +597,12 @@ static void __exit oss_cleanup(void)
for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) {
devfs_remove("sound/%s", dev_list[i].name);
- class_simple_device_remove(MKDEV(SOUND_MAJOR, dev_list[i].minor));
+ class_device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor));
if (!dev_list[i].num)
continue;
for (j = 1; j < *dev_list[i].num; j++) {
devfs_remove("sound/%s%d", dev_list[i].name, j);
- class_simple_device_remove(MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)));
+ class_device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)));
}
}
diff --git a/sound/oss/sscape.c b/sound/oss/sscape.c
index 50ca6462945..9ed5211c316 100644
--- a/sound/oss/sscape.c
+++ b/sound/oss/sscape.c
@@ -991,7 +991,6 @@ static void __init sscape_pnp_init_hw(sscape_info* devc)
unsigned i;
static char code_file_name[23] = "/sndscape/sndscape.cox";
- int sscape_sb_enable = 0;
int sscape_joystic_enable = 0x7f;
int sscape_mic_enable = 0;
int sscape_ext_midi = 0;
@@ -1015,14 +1014,9 @@ static void __init sscape_pnp_init_hw(sscape_info* devc)
sscape_write( devc, 2, devc->ic_type == IC_ODIE ? 0x70 : 0x40);
sscape_write( devc, 3, ( devc -> dma << 4) | 0x80);
- if ( sscape_sb_enable )
- sscape_write (devc, 4, 0xF0 | (sb_irq << 2) | midi_irq);
- else
- sscape_write (devc, 4, 0xF0 | (midi_irq<<2) | midi_irq);
+ sscape_write (devc, 4, 0xF0 | (midi_irq<<2) | midi_irq);
i = 0x10; //sscape_read(devc, 9) & (devc->ic_type == IC_ODIE ? 0xf0 : 0xc0);
- if ( sscape_sb_enable )
- i |= devc->ic_type == IC_ODIE ? 0x05 : 0x07;
if (sscape_joystic_enable) i |= 8;
sscape_write (devc, 9, i);
diff --git a/sound/oss/v_midi.c b/sound/oss/v_midi.c
index 077b7679766..a7ef04fab07 100644
--- a/sound/oss/v_midi.c
+++ b/sound/oss/v_midi.c
@@ -39,8 +39,6 @@ static void *midi_mem = NULL;
*/
-void (*midi_input_intr) (int dev, unsigned char data);
-
static int v_midi_open (int dev, int mode,
void (*input) (int dev, unsigned char data),
void (*output) (int dev)
diff --git a/sound/oss/wavfront.c b/sound/oss/wavfront.c
index cce1278dc48..b92ba892163 100644
--- a/sound/oss/wavfront.c
+++ b/sound/oss/wavfront.c
@@ -151,11 +151,11 @@ static int (*midi_load_patch) (int devno, int format, const char __user *addr,
/*** Module-accessible parameters ***************************************/
-int wf_raw; /* we normally check for "raw state" to firmware
- loading. if set, then during driver loading, the
- state of the board is ignored, and we reset the
- board and load the firmware anyway.
- */
+static int wf_raw; /* we normally check for "raw state" to firmware
+ loading. if set, then during driver loading, the
+ state of the board is ignored, and we reset the
+ board and load the firmware anyway.
+ */
static int fx_raw = 1; /* if this is zero, we'll leave the FX processor in
whatever state it is when the driver is loaded.
@@ -2911,7 +2911,7 @@ int __init detect_wffx (void)
return 0;
}
-void
+static void
wffx_mute (int onoff)
{
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 428efdbd70a..6d7a00f34d8 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -274,6 +274,19 @@ config SND_HDSP
To compile this driver as a module, choose M here: the module
will be called snd-hdsp.
+config SND_HDSPM
+ tristate "RME Hammerfall DSP MADI"
+ depends on SND
+ select SND_HWDEP
+ select SND_RAWMIDI
+ select SND_PCM
+ help
+ Say Y here to include support for RME Hammerfall DSP MADI
+ soundcards.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-hdspm.
+
config SND_TRIDENT
tristate "Trident 4D-Wave DX/NX; SiS 7018"
depends on SND
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index 0b024ec1f70..a4b72cd2eea 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -120,6 +120,7 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
{ 0x414c4770, 0xfffffff0, "ALC203", NULL, NULL },
{ 0x434d4941, 0xffffffff, "CMI9738", patch_cm9738, NULL },
{ 0x434d4961, 0xffffffff, "CMI9739", patch_cm9739, NULL },
+{ 0x434d4969, 0xffffffff, "CMI9780", patch_cm9780, NULL },
{ 0x434d4978, 0xffffffff, "CMI9761", patch_cm9761, NULL },
{ 0x434d4982, 0xffffffff, "CMI9761", patch_cm9761, NULL },
{ 0x434d4983, 0xffffffff, "CMI9761", patch_cm9761, NULL },
@@ -149,7 +150,7 @@ static const ac97_codec_id_t snd_ac97_codec_ids[] = {
{ 0x4e534331, 0xffffffff, "LM4549", NULL, NULL },
{ 0x4e534350, 0xffffffff, "LM4550", NULL, NULL },
{ 0x50534304, 0xffffffff, "UCB1400", NULL, NULL },
-{ 0x53494c20, 0xffffffe0, "Si3036,8", NULL, mpatch_si3036 },
+{ 0x53494c20, 0xffffffe0, "Si3036,8", mpatch_si3036, mpatch_si3036, AC97_MODEM_PATCH },
{ 0x54524102, 0xffffffff, "TR28022", NULL, NULL },
{ 0x54524106, 0xffffffff, "TR28026", NULL, NULL },
{ 0x54524108, 0xffffffff, "TR28028", patch_tritech_tr28028, NULL }, // added by xin jin [07/09/99]
@@ -462,12 +463,14 @@ int snd_ac97_get_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * u
{
ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value;
- unsigned short val;
+ unsigned short val, bitmask;
+ for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
+ ;
val = snd_ac97_read_cache(ac97, e->reg);
- ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (e->mask - 1);
+ ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1);
if (e->shift_l != e->shift_r)
- ucontrol->value.enumerated.item[1] = (val >> e->shift_r) & (e->mask - 1);
+ ucontrol->value.enumerated.item[1] = (val >> e->shift_r) & (bitmask - 1);
return 0;
}
@@ -477,17 +480,19 @@ int snd_ac97_put_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * u
ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value;
unsigned short val;
- unsigned short mask;
+ unsigned short mask, bitmask;
+ for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
+ ;
if (ucontrol->value.enumerated.item[0] > e->mask - 1)
return -EINVAL;
val = ucontrol->value.enumerated.item[0] << e->shift_l;
- mask = (e->mask - 1) << e->shift_l;
+ mask = (bitmask - 1) << e->shift_l;
if (e->shift_l != e->shift_r) {
if (ucontrol->value.enumerated.item[1] > e->mask - 1)
return -EINVAL;
val |= ucontrol->value.enumerated.item[1] << e->shift_r;
- mask |= (e->mask - 1) << e->shift_r;
+ mask |= (bitmask - 1) << e->shift_r;
}
return snd_ac97_update_bits(ac97, e->reg, mask, val);
}
@@ -658,14 +663,14 @@ AC97_SINGLE("LFE Playback Switch", AC97_CENTER_LFE_MASTER, 15, 1, 1),
AC97_SINGLE("LFE Playback Volume", AC97_CENTER_LFE_MASTER, 8, 31, 1)
};
-static const snd_kcontrol_new_t snd_ac97_controls_surround[2] = {
-AC97_DOUBLE("Surround Playback Switch", AC97_SURROUND_MASTER, 15, 7, 1, 1),
-AC97_DOUBLE("Surround Playback Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1),
-};
-
static const snd_kcontrol_new_t snd_ac97_control_eapd =
AC97_SINGLE("External Amplifier", AC97_POWERDOWN, 15, 1, 1);
+static const snd_kcontrol_new_t snd_ac97_controls_modem_switches[2] = {
+AC97_SINGLE("Off-hook Switch", AC97_GPIO_STATUS, 0, 1, 0),
+AC97_SINGLE("Caller ID Switch", AC97_GPIO_STATUS, 2, 1, 0)
+};
+
/* change the existing EAPD control as inverted */
static void set_inv_eapd(ac97_t *ac97, snd_kcontrol_t *kctl)
{
@@ -1072,9 +1077,9 @@ static void check_volume_resolution(ac97_t *ac97, int reg, unsigned char *lo_max
unsigned short val;
snd_ac97_write(ac97, reg, 0x8080 | cbit[i] | (cbit[i] << 8));
val = snd_ac97_read(ac97, reg);
- if (! *lo_max && (val & cbit[i]))
+ if (! *lo_max && (val & 0x7f) == cbit[i])
*lo_max = max[i];
- if (! *hi_max && (val & (cbit[i] << 8)))
+ if (! *hi_max && ((val >> 8) & 0x7f) == cbit[i])
*hi_max = max[i];
if (*lo_max && *hi_max)
break;
@@ -1526,13 +1531,25 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
static int snd_ac97_modem_build(snd_card_t * card, ac97_t * ac97)
{
- /* TODO */
+ int err, idx;
+
//printk("AC97_GPIO_CFG = %x\n",snd_ac97_read(ac97,AC97_GPIO_CFG));
snd_ac97_write(ac97, AC97_GPIO_CFG, 0xffff & ~(AC97_GPIO_LINE1_OH));
snd_ac97_write(ac97, AC97_GPIO_POLARITY, 0xffff & ~(AC97_GPIO_LINE1_OH));
snd_ac97_write(ac97, AC97_GPIO_STICKY, 0xffff);
snd_ac97_write(ac97, AC97_GPIO_WAKEUP, 0x0);
snd_ac97_write(ac97, AC97_MISC_AFE, 0x0);
+
+ /* build modem switches */
+ for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_modem_switches); idx++)
+ if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_modem_switches[idx], ac97))) < 0)
+ return err;
+
+ /* build chip specific controls */
+ if (ac97->build_ops->build_specific)
+ if ((err = ac97->build_ops->build_specific(ac97)) < 0)
+ return err;
+
return 0;
}
@@ -1872,7 +1889,11 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97)
goto __access_ok;
}
- snd_ac97_write(ac97, AC97_RESET, 0); /* reset to defaults */
+ /* reset to defaults */
+ if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO))
+ snd_ac97_write(ac97, AC97_RESET, 0);
+ if (!(ac97->scaps & AC97_SCAP_SKIP_MODEM))
+ snd_ac97_write(ac97, AC97_EXTENDED_MID, 0);
if (bus->ops->wait)
bus->ops->wait(ac97);
else {
@@ -1964,21 +1985,21 @@ int snd_ac97_mixer(ac97_bus_t *bus, ac97_template_t *template, ac97_t **rac97)
/* note: it's important to set the rate at first */
tmp = AC97_MEA_GPIO;
if (ac97->ext_mid & AC97_MEI_LINE1) {
- snd_ac97_write_cache(ac97, AC97_LINE1_RATE, 12000);
+ snd_ac97_write_cache(ac97, AC97_LINE1_RATE, 8000);
tmp |= AC97_MEA_ADC1 | AC97_MEA_DAC1;
}
if (ac97->ext_mid & AC97_MEI_LINE2) {
- snd_ac97_write_cache(ac97, AC97_LINE2_RATE, 12000);
+ snd_ac97_write_cache(ac97, AC97_LINE2_RATE, 8000);
tmp |= AC97_MEA_ADC2 | AC97_MEA_DAC2;
}
if (ac97->ext_mid & AC97_MEI_HANDSET) {
- snd_ac97_write_cache(ac97, AC97_HANDSET_RATE, 12000);
+ snd_ac97_write_cache(ac97, AC97_HANDSET_RATE, 8000);
tmp |= AC97_MEA_HADC | AC97_MEA_HDAC;
}
- snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xff00 & ~(tmp << 8));
+ snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0);
udelay(100);
/* nothing should be in powerdown mode */
- snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xff00 & ~(tmp << 8));
+ snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0);
end_time = jiffies + (HZ / 10);
do {
if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp)
@@ -2521,11 +2542,11 @@ int snd_ac97_tune_hardware(ac97_t *ac97, struct ac97_quirk *quirk, const char *o
return result;
}
- for (; quirk->vendor; quirk++) {
- if (quirk->vendor != ac97->subsystem_vendor)
+ for (; quirk->subvendor; quirk++) {
+ if (quirk->subvendor != ac97->subsystem_vendor)
continue;
- if ((! quirk->mask && quirk->device == ac97->subsystem_device) ||
- quirk->device == (quirk->mask & ac97->subsystem_device)) {
+ if ((! quirk->mask && quirk->subdevice == ac97->subsystem_device) ||
+ quirk->subdevice == (quirk->mask & ac97->subsystem_device)) {
if (quirk->codec_id && quirk->codec_id != ac97->id)
continue;
snd_printdd("ac97 quirk for %s (%04x:%04x)\n", quirk->name, ac97->subsystem_vendor, ac97->subsystem_device);
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index 13c34a5d820..a15eb8522b7 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -64,6 +64,116 @@ static int ac97_update_bits_page(ac97_t *ac97, unsigned short reg, unsigned shor
return ret;
}
+/*
+ * shared line-in/mic controls
+ */
+static int ac97_enum_text_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo,
+ const char **texts, unsigned int nums)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = nums;
+ if (uinfo->value.enumerated.item > nums - 1)
+ uinfo->value.enumerated.item = nums - 1;
+ strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int ac97_surround_jack_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+ static const char *texts[] = { "Shared", "Independent" };
+ return ac97_enum_text_info(kcontrol, uinfo, texts, 2);
+}
+
+static int ac97_surround_jack_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.enumerated.item[0] = ac97->indep_surround;
+ return 0;
+}
+
+static int ac97_surround_jack_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ unsigned char indep = !!ucontrol->value.enumerated.item[0];
+
+ if (indep != ac97->indep_surround) {
+ ac97->indep_surround = indep;
+ if (ac97->build_ops->update_jacks)
+ ac97->build_ops->update_jacks(ac97);
+ return 1;
+ }
+ return 0;
+}
+
+static int ac97_channel_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+ static const char *texts[] = { "2ch", "4ch", "6ch" };
+ if (kcontrol->private_value)
+ return ac97_enum_text_info(kcontrol, uinfo, texts, 2); /* 4ch only */
+ return ac97_enum_text_info(kcontrol, uinfo, texts, 3);
+}
+
+static int ac97_channel_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.enumerated.item[0] = ac97->channel_mode;
+ return 0;
+}
+
+static int ac97_channel_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+ unsigned char mode = ucontrol->value.enumerated.item[0];
+
+ if (mode != ac97->channel_mode) {
+ ac97->channel_mode = mode;
+ if (ac97->build_ops->update_jacks)
+ ac97->build_ops->update_jacks(ac97);
+ return 1;
+ }
+ return 0;
+}
+
+#define AC97_SURROUND_JACK_MODE_CTL \
+ { \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = "Surround Jack Mode", \
+ .info = ac97_surround_jack_mode_info, \
+ .get = ac97_surround_jack_mode_get, \
+ .put = ac97_surround_jack_mode_put, \
+ }
+#define AC97_CHANNEL_MODE_CTL \
+ { \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = "Channel Mode", \
+ .info = ac97_channel_mode_info, \
+ .get = ac97_channel_mode_get, \
+ .put = ac97_channel_mode_put, \
+ }
+#define AC97_CHANNEL_MODE_4CH_CTL \
+ { \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = "Channel Mode", \
+ .info = ac97_channel_mode_info, \
+ .get = ac97_channel_mode_get, \
+ .put = ac97_channel_mode_put, \
+ .private_value = 1, \
+ }
+
+static inline int is_shared_linein(ac97_t *ac97)
+{
+ return ! ac97->indep_surround && ac97->channel_mode >= 1;
+}
+
+static inline int is_shared_micin(ac97_t *ac97)
+{
+ return ! ac97->indep_surround && ac97->channel_mode >= 2;
+}
+
+
/* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */
/* It is possible to indicate to the Yamaha YMF753 the type of speakers being used. */
@@ -1390,6 +1500,16 @@ static int snd_ac97_ad1888_downmix_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_va
AC97_AD198X_DMIX0 | AC97_AD198X_DMIX1, val);
}
+static void ad1888_update_jacks(ac97_t *ac97)
+{
+ /* shared Line-In */
+ snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 12,
+ is_shared_linein(ac97) ? 0 : 1 << 12);
+ /* shared Mic */
+ snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 11,
+ is_shared_micin(ac97) ? 0 : 1 << 11);
+}
+
static const snd_kcontrol_new_t snd_ac97_ad1888_controls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -1406,8 +1526,8 @@ static const snd_kcontrol_new_t snd_ac97_ad1888_controls[] = {
.get = snd_ac97_ad1888_downmix_get,
.put = snd_ac97_ad1888_downmix_put
},
- AC97_SINGLE("Surround Jack as Input", AC97_AD_MISC, 12, 1, 0),
- AC97_SINGLE("Center/LFE Jack as Input", AC97_AD_MISC, 11, 1, 0),
+ AC97_SURROUND_JACK_MODE_CTL,
+ AC97_CHANNEL_MODE_CTL,
};
static int patch_ad1888_specific(ac97_t *ac97)
@@ -1422,8 +1542,9 @@ static struct snd_ac97_build_ops patch_ad1888_build_ops = {
.build_post_spdif = patch_ad198x_post_spdif,
.build_specific = patch_ad1888_specific,
#ifdef CONFIG_PM
- .resume = ad18xx_resume
+ .resume = ad18xx_resume,
#endif
+ .update_jacks = ad1888_update_jacks,
};
int patch_ad1888(ac97_t * ac97)
@@ -1459,8 +1580,9 @@ static struct snd_ac97_build_ops patch_ad1980_build_ops = {
.build_post_spdif = patch_ad198x_post_spdif,
.build_specific = patch_ad1980_specific,
#ifdef CONFIG_PM
- .resume = ad18xx_resume
+ .resume = ad18xx_resume,
#endif
+ .update_jacks = ad1888_update_jacks,
};
int patch_ad1980(ac97_t * ac97)
@@ -1471,10 +1593,21 @@ int patch_ad1980(ac97_t * ac97)
}
static const snd_kcontrol_new_t snd_ac97_ad1985_controls[] = {
- AC97_SINGLE("Center/LFE Jack as Mic", AC97_AD_SERIAL_CFG, 9, 1, 0),
AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0)
};
+static void ad1985_update_jacks(ac97_t *ac97)
+{
+ /* shared Line-In */
+ snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 12,
+ is_shared_linein(ac97) ? 0 : 1 << 12);
+ /* shared Mic */
+ snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 11,
+ is_shared_micin(ac97) ? 0 : 1 << 11);
+ snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 1 << 9,
+ is_shared_micin(ac97) ? 0 : 1 << 9);
+}
+
static int patch_ad1985_specific(ac97_t *ac97)
{
int err;
@@ -1488,8 +1621,9 @@ static struct snd_ac97_build_ops patch_ad1985_build_ops = {
.build_post_spdif = patch_ad198x_post_spdif,
.build_specific = patch_ad1985_specific,
#ifdef CONFIG_PM
- .resume = ad18xx_resume
+ .resume = ad18xx_resume,
#endif
+ .update_jacks = ad1985_update_jacks,
};
int patch_ad1985(ac97_t * ac97)
@@ -1521,31 +1655,25 @@ int patch_ad1985(ac97_t * ac97)
/*
* realtek ALC65x/850 codecs
*/
-static int snd_ac97_alc650_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- ucontrol->value.integer.value[0] = (ac97->regs[AC97_ALC650_MULTICH] >> 10) & 1;
- return 0;
-}
-
-static int snd_ac97_alc650_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+static void alc650_update_jacks(ac97_t *ac97)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- int change, val;
- val = !!(snd_ac97_read(ac97, AC97_ALC650_MULTICH) & (1 << 10));
- change = (ucontrol->value.integer.value[0] != val);
- if (change) {
- /* disable/enable vref */
- snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
- ucontrol->value.integer.value[0] ? (1 << 12) : 0);
- /* turn on/off center-on-mic */
- snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
- ucontrol->value.integer.value[0] ? (1 << 10) : 0);
- /* GPIO0 high for mic */
- snd_ac97_update_bits(ac97, AC97_ALC650_GPIO_STATUS, 0x100,
- ucontrol->value.integer.value[0] ? 0 : 0x100);
- }
- return change;
+ int shared;
+
+ /* shared Line-In */
+ shared = is_shared_linein(ac97);
+ snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 9,
+ shared ? (1 << 9) : 0);
+ /* update shared Mic */
+ shared = is_shared_micin(ac97);
+ /* disable/enable vref */
+ snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
+ shared ? (1 << 12) : 0);
+ /* turn on/off center-on-mic */
+ snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
+ shared ? (1 << 10) : 0);
+ /* GPIO0 high for mic */
+ snd_ac97_update_bits(ac97, AC97_ALC650_GPIO_STATUS, 0x100,
+ shared ? 0 : 0x100);
}
static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = {
@@ -1558,8 +1686,8 @@ static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = {
/* 6: Independent Master Volume Right */
/* 7: Independent Master Volume Left */
/* 8: reserved */
- AC97_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0),
- /* 10: mic, see below */
+ /* 9: Line-In/Surround share */
+ /* 10: Mic/CLFE share */
/* 11-13: in IEC958 controls */
AC97_SINGLE("Swap Surround Slot", AC97_ALC650_MULTICH, 14, 1, 0),
#if 0 /* always set in patch_alc650 */
@@ -1570,14 +1698,8 @@ static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = {
AC97_SINGLE("Center/LFE DAC Switch", AC97_ALC650_LFE_DAC_VOL, 15, 1, 1),
AC97_DOUBLE("Center/LFE DAC Volume", AC97_ALC650_LFE_DAC_VOL, 8, 0, 31, 1),
#endif
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Mic As Center/LFE",
- .info = snd_ac97_info_volsw,
- .get = snd_ac97_alc650_mic_get,
- .put = snd_ac97_alc650_mic_put,
- .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
- },
+ AC97_SURROUND_JACK_MODE_CTL,
+ AC97_CHANNEL_MODE_CTL,
};
static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc650[] = {
@@ -1601,7 +1723,8 @@ static int patch_alc650_specific(ac97_t * ac97)
}
static struct snd_ac97_build_ops patch_alc650_ops = {
- .build_specific = patch_alc650_specific
+ .build_specific = patch_alc650_specific,
+ .update_jacks = alc650_update_jacks
};
int patch_alc650(ac97_t * ac97)
@@ -1659,37 +1782,27 @@ int patch_alc650(ac97_t * ac97)
return 0;
}
-static int snd_ac97_alc655_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- ucontrol->value.integer.value[0] = (ac97->regs[AC97_ALC650_MULTICH] >> 10) & 1;
- return 0;
-}
-
-static int snd_ac97_alc655_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+static void alc655_update_jacks(ac97_t *ac97)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-
+ int shared;
+
+ /* shared Line-In */
+ shared = is_shared_linein(ac97);
+ ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 9,
+ shared ? (1 << 9) : 0, 0);
+ /* update shared mic */
+ shared = is_shared_micin(ac97);
/* misc control; vrefout disable */
snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
- ucontrol->value.integer.value[0] ? (1 << 12) : 0);
- return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 10,
- ucontrol->value.integer.value[0] ? (1 << 10) : 0,
- 0);
+ shared ? (1 << 12) : 0);
+ ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 10,
+ shared ? (1 << 10) : 0, 0);
}
-
static const snd_kcontrol_new_t snd_ac97_controls_alc655[] = {
AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
- AC97_PAGE_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0, 0),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Mic As Center/LFE",
- .info = snd_ac97_info_volsw,
- .get = snd_ac97_alc655_mic_get,
- .put = snd_ac97_alc655_mic_put,
- .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
- },
+ AC97_SURROUND_JACK_MODE_CTL,
+ AC97_CHANNEL_MODE_CTL,
};
static int alc655_iec958_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
@@ -1759,7 +1872,8 @@ static int patch_alc655_specific(ac97_t * ac97)
}
static struct snd_ac97_build_ops patch_alc655_ops = {
- .build_specific = patch_alc655_specific
+ .build_specific = patch_alc655_specific,
+ .update_jacks = alc655_update_jacks
};
int patch_alc655(ac97_t * ac97)
@@ -1798,63 +1912,33 @@ int patch_alc655(ac97_t * ac97)
#define AC97_ALC850_JACK_SELECT 0x76
#define AC97_ALC850_MISC1 0x7a
-static int ac97_alc850_surround_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- ucontrol->value.integer.value[0] = ((ac97->regs[AC97_ALC850_JACK_SELECT] >> 12) & 7) == 2;
- return 0;
-}
-
-static int ac97_alc850_surround_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+static void alc850_update_jacks(ac97_t *ac97)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-
+ int shared;
+
+ /* shared Line-In */
+ shared = is_shared_linein(ac97);
/* SURR 1kOhm (bit4), Amp (bit5) */
snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5),
- ucontrol->value.integer.value[0] ? (1<<5) : (1<<4));
+ shared ? (1<<5) : (1<<4));
/* LINE-IN = 0, SURROUND = 2 */
- return snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12,
- ucontrol->value.integer.value[0] ? (2<<12) : (0<<12));
-}
-
-static int ac97_alc850_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- ucontrol->value.integer.value[0] = ((ac97->regs[AC97_ALC850_JACK_SELECT] >> 4) & 7) == 2;
- return 0;
-}
-
-static int ac97_alc850_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-
+ snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12,
+ shared ? (2<<12) : (0<<12));
+ /* update shared mic */
+ shared = is_shared_micin(ac97);
/* Vref disable (bit12), 1kOhm (bit13) */
snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13),
- ucontrol->value.integer.value[0] ? (1<<12) : (1<<13));
+ shared ? (1<<12) : (1<<13));
/* MIC-IN = 1, CENTER-LFE = 2 */
- return snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4,
- ucontrol->value.integer.value[0] ? (2<<4) : (1<<4));
+ snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4,
+ shared ? (2<<4) : (1<<4));
}
static const snd_kcontrol_new_t snd_ac97_controls_alc850[] = {
AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Line-In As Surround",
- .info = snd_ac97_info_volsw,
- .get = ac97_alc850_surround_get,
- .put = ac97_alc850_surround_put,
- .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Mic As Center/LFE",
- .info = snd_ac97_info_volsw,
- .get = ac97_alc850_mic_get,
- .put = ac97_alc850_mic_put,
- .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
- },
-
+ AC97_SINGLE("Mic Front Input Switch", AC97_ALC850_JACK_SELECT, 15, 1, 1),
+ AC97_SURROUND_JACK_MODE_CTL,
+ AC97_CHANNEL_MODE_CTL,
};
static int patch_alc850_specific(ac97_t *ac97)
@@ -1871,7 +1955,8 @@ static int patch_alc850_specific(ac97_t *ac97)
}
static struct snd_ac97_build_ops patch_alc850_ops = {
- .build_specific = patch_alc850_specific
+ .build_specific = patch_alc850_specific,
+ .update_jacks = alc850_update_jacks
};
int patch_alc850(ac97_t *ac97)
@@ -1911,9 +1996,17 @@ int patch_alc850(ac97_t *ac97)
/*
* C-Media CM97xx codecs
*/
+static void cm9738_update_jacks(ac97_t *ac97)
+{
+ /* shared Line-In */
+ snd_ac97_update_bits(ac97, AC97_CM9738_VENDOR_CTRL, 1 << 10,
+ is_shared_linein(ac97) ? (1 << 10) : 0);
+}
+
static const snd_kcontrol_new_t snd_ac97_cm9738_controls[] = {
- AC97_SINGLE("Line-In As Surround", AC97_CM9738_VENDOR_CTRL, 10, 1, 0),
AC97_SINGLE("Duplicate Front", AC97_CM9738_VENDOR_CTRL, 13, 1, 0),
+ AC97_SURROUND_JACK_MODE_CTL,
+ AC97_CHANNEL_MODE_4CH_CTL,
};
static int patch_cm9738_specific(ac97_t * ac97)
@@ -1922,7 +2015,8 @@ static int patch_cm9738_specific(ac97_t * ac97)
}
static struct snd_ac97_build_ops patch_cm9738_ops = {
- .build_specific = patch_cm9738_specific
+ .build_specific = patch_cm9738_specific,
+ .update_jacks = cm9738_update_jacks
};
int patch_cm9738(ac97_t * ac97)
@@ -1986,34 +2080,19 @@ static const snd_kcontrol_new_t snd_ac97_cm9739_controls_spdif[] = {
/* BIT 8: SPD32 - 32bit SPDIF - not supported yet */
};
-static int snd_ac97_cm9739_center_mic_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x1000)
- ucontrol->value.integer.value[0] = 1;
- else
- ucontrol->value.integer.value[0] = 0;
- return 0;
-}
-
-static int snd_ac97_cm9739_center_mic_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static void cm9739_update_jacks(ac97_t *ac97)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000,
- ucontrol->value.integer.value[0] ?
- 0x1000 : 0x2000);
+ /* shared Line-In */
+ snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 1 << 10,
+ is_shared_linein(ac97) ? (1 << 10) : 0);
+ /* shared Mic */
+ snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000,
+ is_shared_micin(ac97) ? 0x1000 : 0x2000);
}
static const snd_kcontrol_new_t snd_ac97_cm9739_controls[] = {
- AC97_SINGLE("Line-In As Surround", AC97_CM9739_MULTI_CHAN, 10, 1, 0),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Mic As Center/LFE",
- .info = snd_ac97_info_volsw,
- .get = snd_ac97_cm9739_center_mic_get,
- .put = snd_ac97_cm9739_center_mic_put,
- .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
- },
+ AC97_SURROUND_JACK_MODE_CTL,
+ AC97_CHANNEL_MODE_CTL,
};
static int patch_cm9739_specific(ac97_t * ac97)
@@ -2028,7 +2107,8 @@ static int patch_cm9739_post_spdif(ac97_t * ac97)
static struct snd_ac97_build_ops patch_cm9739_ops = {
.build_specific = patch_cm9739_specific,
- .build_post_spdif = patch_cm9739_post_spdif
+ .build_post_spdif = patch_cm9739_post_spdif,
+ .update_jacks = cm9739_update_jacks
};
int patch_cm9739(ac97_t * ac97)
@@ -2087,71 +2167,97 @@ int patch_cm9739(ac97_t * ac97)
}
#define AC97_CM9761_MULTI_CHAN 0x64
+#define AC97_CM9761_FUNC 0x66
#define AC97_CM9761_SPDIF_CTRL 0x6c
-static int snd_ac97_cm9761_linein_rear_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x0400)
- ucontrol->value.integer.value[0] = 1;
- else
- ucontrol->value.integer.value[0] = 0;
- return 0;
-}
-
-static int snd_ac97_cm9761_linein_rear_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static void cm9761_update_jacks(ac97_t *ac97)
{
- ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- unsigned short vals[2][2] = {
+ unsigned short surr_vals[2][2] = {
{ 0x0008, 0x0400 }, /* off, on */
{ 0x0000, 0x0408 }, /* off, on (9761-82 rev.B) */
};
- return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x0408,
- vals[ac97->spec.dev_flags][!!ucontrol->value.integer.value[0]]);
+ unsigned short clfe_vals[2][2] = {
+ { 0x2000, 0x1880 }, /* off, on */
+ { 0x1000, 0x2880 }, /* off, on (9761-82 rev.B) */
+ };
+
+ /* shared Line-In */
+ snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x0408,
+ surr_vals[ac97->spec.dev_flags][is_shared_linein(ac97)]);
+ /* shared Mic */
+ snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x3880,
+ clfe_vals[ac97->spec.dev_flags][is_shared_micin(ac97)]);
+}
+
+static const snd_kcontrol_new_t snd_ac97_cm9761_controls[] = {
+ AC97_SURROUND_JACK_MODE_CTL,
+ AC97_CHANNEL_MODE_CTL,
+};
+
+static int cm9761_spdif_out_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+ static char *texts[] = { "AC-Link", "ADC", "SPDIF-In" };
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 3;
+ if (uinfo->value.enumerated.item > 2)
+ uinfo->value.enumerated.item = 2;
+ strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+ return 0;
}
-static int snd_ac97_cm9761_center_mic_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int cm9761_spdif_out_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x1000)
- ucontrol->value.integer.value[0] = 1;
+
+ if (ac97->regs[AC97_CM9761_FUNC] & 0x1)
+ ucontrol->value.enumerated.item[0] = 2; /* SPDIF-loopback */
+ else if (ac97->regs[AC97_CM9761_SPDIF_CTRL] & 0x2)
+ ucontrol->value.enumerated.item[0] = 1; /* ADC loopback */
else
- ucontrol->value.integer.value[0] = 0;
- if (ac97->spec.dev_flags) /* 9761-82 rev.B */
- ucontrol->value.integer.value[0] = !ucontrol->value.integer.value[0];
+ ucontrol->value.enumerated.item[0] = 0; /* AC-link */
return 0;
}
-static int snd_ac97_cm9761_center_mic_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int cm9761_spdif_out_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
- unsigned short vals[2][2] = {
- { 0x2000, 0x1880 }, /* off, on */
- { 0x1000, 0x2880 }, /* off, on (9761-82 rev.B) */
- };
- return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3880,
- vals[ac97->spec.dev_flags][!!ucontrol->value.integer.value[0]]);
+
+ if (ucontrol->value.enumerated.item[0] == 2)
+ return snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0x1);
+ snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0);
+ return snd_ac97_update_bits(ac97, AC97_CM9761_SPDIF_CTRL, 0x2,
+ ucontrol->value.enumerated.item[0] == 1 ? 0x2 : 0);
}
-static const snd_kcontrol_new_t snd_ac97_cm9761_controls[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Line-In As Surround",
- .info = snd_ac97_info_volsw,
- .get = snd_ac97_cm9761_linein_rear_get,
- .put = snd_ac97_cm9761_linein_rear_put,
- .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Mic As Center/LFE",
- .info = snd_ac97_info_volsw,
- .get = snd_ac97_cm9761_center_mic_get,
- .put = snd_ac97_cm9761_center_mic_put,
- .private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
+static const char *cm9761_dac_clock[] = { "AC-Link", "SPDIF-In", "Both" };
+static const struct ac97_enum cm9761_dac_clock_enum =
+ AC97_ENUM_SINGLE(AC97_CM9761_SPDIF_CTRL, 9, 3, cm9761_dac_clock);
+
+static const snd_kcontrol_new_t snd_ac97_cm9761_controls_spdif[] = {
+ { /* BIT 1: SPDIFS */
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
+ .info = cm9761_spdif_out_source_info,
+ .get = cm9761_spdif_out_source_get,
+ .put = cm9761_spdif_out_source_put,
},
+ /* BIT 2: IG_SPIV */
+ AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9761_SPDIF_CTRL, 2, 1, 0),
+ /* BIT 3: SPI2F */
+ AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9761_SPDIF_CTRL, 3, 1, 0),
+ /* BIT 4: SPI2SDI */
+ AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9761_SPDIF_CTRL, 4, 1, 0),
+ /* BIT 9-10: DAC_CTL */
+ AC97_ENUM("DAC Clock Source", cm9761_dac_clock_enum),
};
+static int patch_cm9761_post_spdif(ac97_t * ac97)
+{
+ return patch_build_controls(ac97, snd_ac97_cm9761_controls_spdif, ARRAY_SIZE(snd_ac97_cm9761_controls_spdif));
+}
+
static int patch_cm9761_specific(ac97_t * ac97)
{
return patch_build_controls(ac97, snd_ac97_cm9761_controls, ARRAY_SIZE(snd_ac97_cm9761_controls));
@@ -2159,7 +2265,8 @@ static int patch_cm9761_specific(ac97_t * ac97)
static struct snd_ac97_build_ops patch_cm9761_ops = {
.build_specific = patch_cm9761_specific,
- .build_post_spdif = patch_cm9739_post_spdif /* hope it's identical... */
+ .build_post_spdif = patch_cm9761_post_spdif,
+ .update_jacks = cm9761_update_jacks
};
int patch_cm9761(ac97_t *ac97)
@@ -2193,24 +2300,25 @@ int patch_cm9761(ac97_t *ac97)
/* to be sure: we overwrite the ext status bits */
snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, 0x05c0);
/* Don't set 0x0200 here. This results in the silent analog output */
- snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0009);
+ snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0001); /* enable spdif-in */
ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
/* set-up multi channel */
/* bit 15: pc master beep off
- * bit 14: ??
+ * bit 14: pin47 = EAPD/SPDIF
* bit 13: vref ctl [= cm9739]
- * bit 12: center/mic [= cm9739] (reverted on rev B)
- * bit 11: ?? (mic/center/lfe) (reverted on rev B)
- * bit 10: suddound/line [= cm9739]
- * bit 9: mix 2 surround
- * bit 8: ?
- * bit 7: ?? (mic/center/lfe)
- * bit 4: ?? (front)
- * bit 3: ?? (line-in/rear share) (revereted with rev B)
- * bit 2: ?? (surround)
- * bit 1: front mic
- * bit 0: mic boost
+ * bit 12: CLFE control (reverted on rev B)
+ * bit 11: Mic/center share (reverted on rev B)
+ * bit 10: suddound/line share
+ * bit 9: Analog-in mix -> surround
+ * bit 8: Analog-in mix -> CLFE
+ * bit 7: Mic/LFE share (mic/center/lfe)
+ * bit 5: vref select (9761A)
+ * bit 4: front control
+ * bit 3: surround control (revereted with rev B)
+ * bit 2: front mic
+ * bit 1: stereo mic
+ * bit 0: mic boost level (0=20dB, 1=30dB)
*/
#if 0
@@ -2230,6 +2338,47 @@ int patch_cm9761(ac97_t *ac97)
return 0;
}
+#define AC97_CM9780_SIDE 0x60
+#define AC97_CM9780_JACK 0x62
+#define AC97_CM9780_MIXER 0x64
+#define AC97_CM9780_MULTI_CHAN 0x66
+#define AC97_CM9780_SPDIF 0x6c
+
+static const char *cm9780_ch_select[] = { "Front", "Side", "Center/LFE", "Rear" };
+static const struct ac97_enum cm9780_ch_select_enum =
+ AC97_ENUM_SINGLE(AC97_CM9780_MULTI_CHAN, 6, 4, cm9780_ch_select);
+static const snd_kcontrol_new_t cm9780_controls[] = {
+ AC97_DOUBLE("Side Playback Switch", AC97_CM9780_SIDE, 15, 7, 1, 1),
+ AC97_DOUBLE("Side Playback Volume", AC97_CM9780_SIDE, 8, 0, 31, 0),
+ AC97_ENUM("Side Playback Route", cm9780_ch_select_enum),
+};
+
+static int patch_cm9780_specific(ac97_t *ac97)
+{
+ return patch_build_controls(ac97, cm9780_controls, ARRAY_SIZE(cm9780_controls));
+}
+
+static struct snd_ac97_build_ops patch_cm9780_ops = {
+ .build_specific = patch_cm9780_specific,
+ .build_post_spdif = patch_cm9761_post_spdif /* identical with CM9761 */
+};
+
+int patch_cm9780(ac97_t *ac97)
+{
+ unsigned short val;
+
+ ac97->build_ops = &patch_cm9780_ops;
+
+ /* enable spdif */
+ if (ac97->ext_id & AC97_EI_SPDIF) {
+ ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
+ val = snd_ac97_read(ac97, AC97_CM9780_SPDIF);
+ val |= 0x1; /* SPDI_EN */
+ snd_ac97_write_cache(ac97, AC97_CM9780_SPDIF, val);
+ }
+
+ return 0;
+}
/*
* VIA VT1616 codec
@@ -2263,9 +2412,21 @@ int patch_vt1616(ac97_t * ac97)
return 0;
}
+/*
+ */
+static void it2646_update_jacks(ac97_t *ac97)
+{
+ /* shared Line-In */
+ snd_ac97_update_bits(ac97, 0x76, 1 << 9,
+ is_shared_linein(ac97) ? (1<<9) : 0);
+ /* shared Mic */
+ snd_ac97_update_bits(ac97, 0x76, 1 << 10,
+ is_shared_micin(ac97) ? (1<<10) : 0);
+}
+
static const snd_kcontrol_new_t snd_ac97_controls_it2646[] = {
- AC97_SINGLE("Line-In As Surround", 0x76, 9, 1, 0),
- AC97_SINGLE("Mic As Center/LFE", 0x76, 10, 1, 0),
+ AC97_SURROUND_JACK_MODE_CTL,
+ AC97_CHANNEL_MODE_CTL,
};
static const snd_kcontrol_new_t snd_ac97_spdif_controls_it2646[] = {
@@ -2285,7 +2446,8 @@ static int patch_it2646_specific(ac97_t * ac97)
}
static struct snd_ac97_build_ops patch_it2646_ops = {
- .build_specific = patch_it2646_specific
+ .build_specific = patch_it2646_specific,
+ .update_jacks = it2646_update_jacks
};
int patch_it2646(ac97_t * ac97)
@@ -2297,12 +2459,29 @@ int patch_it2646(ac97_t * ac97)
return 0;
}
-/* Si3036/8 specific registers */
+/*
+ * Si3036 codec
+ */
+
#define AC97_SI3036_CHIP_ID 0x5a
+#define AC97_SI3036_LINE_CFG 0x5c
+
+static const snd_kcontrol_new_t snd_ac97_controls_si3036[] = {
+AC97_DOUBLE("Modem Speaker Volume", 0x5c, 14, 12, 3, 1)
+};
+
+static int patch_si3036_specific(ac97_t * ac97)
+{
+ return patch_build_controls(ac97, snd_ac97_controls_si3036, ARRAY_SIZE(snd_ac97_controls_si3036));
+}
+
+static struct snd_ac97_build_ops patch_si3036_ops = {
+ .build_specific = patch_si3036_specific,
+};
int mpatch_si3036(ac97_t * ac97)
{
- //printk("mpatch_si3036: chip id = %x\n", snd_ac97_read(ac97, 0x5a));
+ ac97->build_ops = &patch_si3036_ops;
snd_ac97_write_cache(ac97, 0x5c, 0xf210 );
snd_ac97_write_cache(ac97, 0x68, 0);
return 0;
diff --git a/sound/pci/ac97/ac97_patch.h b/sound/pci/ac97/ac97_patch.h
index 6db51c96f5d..7b7377d0f2a 100644
--- a/sound/pci/ac97/ac97_patch.h
+++ b/sound/pci/ac97/ac97_patch.h
@@ -54,6 +54,7 @@ int patch_alc850(ac97_t * ac97);
int patch_cm9738(ac97_t * ac97);
int patch_cm9739(ac97_t * ac97);
int patch_cm9761(ac97_t * ac97);
+int patch_cm9780(ac97_t * ac97);
int patch_vt1616(ac97_t * ac97);
int patch_it2646(ac97_t * ac97);
int mpatch_si3036(ac97_t * ac97);
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index 984d5d4ba4e..eb5c36d31a5 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -98,6 +98,8 @@ MODULE_PARM_DESC(spdif, "Support SPDIF I/O");
#define ALI_LEF_CHANNEL 23
#define ALI_SURR_LEFT_CHANNEL 26
#define ALI_SURR_RIGHT_CHANNEL 25
+#define ALI_MODEM_IN_CHANNEL 21
+#define ALI_MODEM_OUT_CHANNEL 20
#define SNDRV_ALI_VOICE_TYPE_PCM 01
#define SNDRV_ALI_VOICE_TYPE_OTH 02
@@ -122,7 +124,15 @@ MODULE_PARM_DESC(spdif, "Support SPDIF I/O");
#define ALI_SCTRL 0x48
#define ALI_SPDIF_OUT_ENABLE 0x20
+#define ALI_SCTRL_LINE_IN2 (1 << 9)
+#define ALI_SCTRL_GPIO_IN2 (1 << 13)
+#define ALI_SCTRL_LINE_OUT_EN (1 << 20)
+#define ALI_SCTRL_GPIO_OUT_EN (1 << 23)
+#define ALI_SCTRL_CODEC1_READY (1 << 24)
+#define ALI_SCTRL_CODEC2_READY (1 << 25)
#define ALI_AC97_GPIO 0x4c
+#define ALI_AC97_GPIO_ENABLE 0x8000
+#define ALI_AC97_GPIO_DATA_SHIFT 16
#define ALI_SPDIF_CS 0x70
#define ALI_SPDIF_CTRL 0x74
#define ALI_SPDIF_IN_FUNC_ENABLE 0x02
@@ -143,6 +153,7 @@ MODULE_PARM_DESC(spdif, "Support SPDIF I/O");
#define TARGET_REACHED 0x00008000
#define MIXER_OVERFLOW 0x00000800
#define MIXER_UNDERFLOW 0x00000400
+ #define GPIO_IRQ 0x01000000
#define ALI_SBBL_SBCL 0xc0
#define ALI_SBCTRL_SBE2R_SBDD 0xc4
#define ALI_STIMER 0xc8
@@ -162,6 +173,9 @@ MODULE_PARM_DESC(spdif, "Support SPDIF I/O");
#define ALI_REG(codec, x) ((codec)->port + x)
+#define MAX_CODECS 2
+
+
typedef struct snd_stru_ali ali_t;
typedef struct snd_ali_stru_voice snd_ali_voice_t;
@@ -245,7 +259,7 @@ struct snd_stru_ali {
struct pci_dev *pci_m7101;
snd_card_t *card;
- snd_pcm_t *pcm;
+ snd_pcm_t *pcm[MAX_CODECS];
alidev_t synth;
snd_ali_channel_control_t chregs;
@@ -255,8 +269,10 @@ struct snd_stru_ali {
unsigned int spurious_irq_count;
unsigned int spurious_irq_max_delta;
+ unsigned int num_of_codecs;
+
ac97_bus_t *ac97_bus;
- ac97_t *ac97;
+ ac97_t *ac97[MAX_CODECS];
unsigned short ac97_ext_id;
unsigned short ac97_ext_status;
@@ -489,7 +505,12 @@ static void snd_ali_codec_write(ac97_t *ac97,
ali_t *codec = ac97->private_data;
snd_ali_printk("codec_write: reg=%xh data=%xh.\n", reg, val);
- snd_ali_codec_poke(codec, 0, reg, val);
+ if(reg == AC97_GPIO_STATUS) {
+ outl((val << ALI_AC97_GPIO_DATA_SHIFT)|ALI_AC97_GPIO_ENABLE,
+ ALI_REG(codec, ALI_AC97_GPIO));
+ return;
+ }
+ snd_ali_codec_poke(codec, ac97->num, reg, val);
return ;
}
@@ -499,7 +520,7 @@ static unsigned short snd_ali_codec_read(ac97_t *ac97, unsigned short reg)
ali_t *codec = ac97->private_data;
snd_ali_printk("codec_read reg=%xh.\n", reg);
- return (snd_ali_codec_peek(codec, 0, reg));
+ return (snd_ali_codec_peek(codec, ac97->num, reg));
}
/*
@@ -1051,7 +1072,7 @@ static irqreturn_t snd_ali_card_interrupt(int irq,
}
-static snd_ali_voice_t *snd_ali_alloc_voice(ali_t * codec, int type, int rec)
+static snd_ali_voice_t *snd_ali_alloc_voice(ali_t * codec, int type, int rec, int channel)
{
snd_ali_voice_t *pvoice = NULL;
unsigned long flags;
@@ -1061,7 +1082,8 @@ static snd_ali_voice_t *snd_ali_alloc_voice(ali_t * codec, int type, int rec)
spin_lock_irqsave(&codec->voice_alloc, flags);
if (type == SNDRV_ALI_VOICE_TYPE_PCM) {
- idx = snd_ali_find_free_channel(codec,rec);
+ idx = channel > 0 ? snd_ali_alloc_pcm_channel(codec, channel) :
+ snd_ali_find_free_channel(codec,rec);
if(idx < 0) {
snd_printk("ali_alloc_voice: err.\n");
spin_unlock_irqrestore(&codec->voice_alloc, flags);
@@ -1297,7 +1319,7 @@ static int snd_ali_playback_hw_params(snd_pcm_substream_t * substream,
if (params_buffer_size(hw_params)/2 != params_period_size(hw_params)) {
if (evoice == NULL) {
- evoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 0);
+ evoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 0, -1);
if (evoice == NULL)
return -ENOMEM;
pvoice->extra = evoice;
@@ -1328,13 +1350,13 @@ static int snd_ali_playback_hw_free(snd_pcm_substream_t * substream)
return 0;
}
-static int snd_ali_capture_hw_params(snd_pcm_substream_t * substream,
+static int snd_ali_hw_params(snd_pcm_substream_t * substream,
snd_pcm_hw_params_t * hw_params)
{
return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
}
-static int snd_ali_capture_hw_free(snd_pcm_substream_t * substream)
+static int snd_ali_hw_free(snd_pcm_substream_t * substream)
{
return snd_pcm_lib_free_pages(substream);
}
@@ -1428,7 +1450,7 @@ static int snd_ali_playback_prepare(snd_pcm_substream_t * substream)
}
-static int snd_ali_capture_prepare(snd_pcm_substream_t * substream)
+static int snd_ali_prepare(snd_pcm_substream_t * substream)
{
ali_t *codec = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
@@ -1446,11 +1468,13 @@ static int snd_ali_capture_prepare(snd_pcm_substream_t * substream)
spin_lock_irqsave(&codec->reg_lock, flags);
- snd_ali_printk("capture_prepare...\n");
+ snd_ali_printk("ali_prepare...\n");
snd_ali_enable_special_channel(codec,pvoice->number);
- Delta = snd_ali_convert_rate(runtime->rate, 1);
+ Delta = (pvoice->number == ALI_MODEM_IN_CHANNEL ||
+ pvoice->number == ALI_MODEM_OUT_CHANNEL) ?
+ 0x1000 : snd_ali_convert_rate(runtime->rate, pvoice->mode);
// Prepare capture intr channel
if (pvoice->number == ALI_SPDIF_IN_CHANNEL) {
@@ -1534,7 +1558,7 @@ static snd_pcm_uframes_t snd_ali_playback_pointer(snd_pcm_substream_t *substream
}
-static snd_pcm_uframes_t snd_ali_capture_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_ali_pointer(snd_pcm_substream_t *substream)
{
ali_t *codec = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
@@ -1616,7 +1640,8 @@ static void snd_ali_pcm_free_substream(snd_pcm_runtime_t *runtime)
}
}
-static int snd_ali_playback_open(snd_pcm_substream_t * substream)
+static int snd_ali_open(snd_pcm_substream_t * substream, int rec, int channel,
+ snd_pcm_hardware_t *phw)
{
ali_t *codec = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
@@ -1624,7 +1649,7 @@ static int snd_ali_playback_open(snd_pcm_substream_t * substream)
unsigned long flags = 0;
spin_lock_irqsave(&codec->reg_lock, flags);
- pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 0);
+ pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, rec, channel);
if (pvoice == NULL) {
spin_unlock_irqrestore(&codec->reg_lock, flags);
return -EAGAIN;
@@ -1636,49 +1661,31 @@ static int snd_ali_playback_open(snd_pcm_substream_t * substream)
runtime->private_data = pvoice;
runtime->private_free = snd_ali_pcm_free_substream;
- runtime->hw = snd_ali_playback;
+ runtime->hw = *phw;
snd_pcm_set_sync(substream);
snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);
return 0;
}
+static int snd_ali_playback_open(snd_pcm_substream_t * substream)
+{
+ return snd_ali_open(substream, 0, -1, &snd_ali_playback);
+}
static int snd_ali_capture_open(snd_pcm_substream_t * substream)
{
- ali_t *codec = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_ali_voice_t *pvoice;
- unsigned long flags;
-
- spin_lock_irqsave(&codec->reg_lock, flags);
- pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 1);
- if (pvoice == NULL) {
- spin_unlock_irqrestore(&codec->reg_lock, flags);
- return -EAGAIN;
- }
- pvoice->codec = codec;
- spin_unlock_irqrestore(&codec->reg_lock, flags);
-
- pvoice->substream = substream;
- runtime->private_data = pvoice;
- runtime->private_free = snd_ali_pcm_free_substream;
- runtime->hw = snd_ali_capture;
- snd_pcm_set_sync(substream);
- snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);
- return 0;
+ return snd_ali_open(substream, 1, -1, &snd_ali_capture);
}
-
static int snd_ali_playback_close(snd_pcm_substream_t * substream)
{
return 0;
}
-static int snd_ali_capture_close(snd_pcm_substream_t * substream)
+static int snd_ali_close(snd_pcm_substream_t * substream)
{
ali_t *codec = snd_pcm_substream_chip(substream);
- snd_pcm_runtime_t *runtime = substream->runtime;
- snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data;
+ snd_ali_voice_t *pvoice = (snd_ali_voice_t *) substream->runtime->private_data;
snd_ali_disable_special_channel(codec,pvoice->number);
@@ -1698,29 +1705,121 @@ static snd_pcm_ops_t snd_ali_playback_ops = {
static snd_pcm_ops_t snd_ali_capture_ops = {
.open = snd_ali_capture_open,
- .close = snd_ali_capture_close,
+ .close = snd_ali_close,
.ioctl = snd_ali_ioctl,
- .hw_params = snd_ali_capture_hw_params,
- .hw_free = snd_ali_capture_hw_free,
- .prepare = snd_ali_capture_prepare,
+ .hw_params = snd_ali_hw_params,
+ .hw_free = snd_ali_hw_free,
+ .prepare = snd_ali_prepare,
+ .trigger = snd_ali_trigger,
+ .pointer = snd_ali_pointer,
+};
+
+/*
+ * Modem PCM
+ */
+
+static int snd_ali_modem_hw_params(snd_pcm_substream_t * substream,
+ snd_pcm_hw_params_t * hw_params)
+{
+ ali_t *chip = snd_pcm_substream_chip(substream);
+ unsigned int modem_num = chip->num_of_codecs - 1;
+ snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_RATE, params_rate(hw_params));
+ snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_LEVEL, 0);
+ return snd_ali_hw_params(substream, hw_params);
+}
+
+static snd_pcm_hardware_t snd_ali_modem =
+{
+ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_RESUME |
+ SNDRV_PCM_INFO_SYNC_START),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_KNOT|SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000,
+ .rate_min = 8000,
+ .rate_max = 16000,
+ .channels_min = 1,
+ .channels_max = 1,
+ .buffer_bytes_max = (256*1024),
+ .period_bytes_min = 64,
+ .period_bytes_max = (256*1024),
+ .periods_min = 1,
+ .periods_max = 1024,
+ .fifo_size = 0,
+};
+
+static int snd_ali_modem_open(snd_pcm_substream_t * substream, int rec, int channel)
+{
+ static unsigned int rates [] = {8000,9600,12000,16000};
+ static snd_pcm_hw_constraint_list_t hw_constraint_rates = {
+ .count = ARRAY_SIZE(rates),
+ .list = rates,
+ .mask = 0,
+ };
+ int err = snd_ali_open(substream, rec, channel, &snd_ali_modem);
+ if (err)
+ return err;
+ return snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE, &hw_constraint_rates);
+}
+
+static int snd_ali_modem_playback_open(snd_pcm_substream_t * substream)
+{
+ return snd_ali_modem_open(substream, 0, ALI_MODEM_OUT_CHANNEL);
+}
+
+static int snd_ali_modem_capture_open(snd_pcm_substream_t * substream)
+{
+ return snd_ali_modem_open(substream, 1, ALI_MODEM_IN_CHANNEL);
+}
+
+static snd_pcm_ops_t snd_ali_modem_playback_ops = {
+ .open = snd_ali_modem_playback_open,
+ .close = snd_ali_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_ali_modem_hw_params,
+ .hw_free = snd_ali_hw_free,
+ .prepare = snd_ali_prepare,
+ .trigger = snd_ali_trigger,
+ .pointer = snd_ali_pointer,
+};
+
+static snd_pcm_ops_t snd_ali_modem_capture_ops = {
+ .open = snd_ali_modem_capture_open,
+ .close = snd_ali_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_ali_modem_hw_params,
+ .hw_free = snd_ali_hw_free,
+ .prepare = snd_ali_prepare,
.trigger = snd_ali_trigger,
- .pointer = snd_ali_capture_pointer,
+ .pointer = snd_ali_pointer,
+};
+
+
+struct ali_pcm_description {
+ char *name;
+ unsigned int playback_num;
+ unsigned int capture_num;
+ snd_pcm_ops_t *playback_ops;
+ snd_pcm_ops_t *capture_ops;
};
static void snd_ali_pcm_free(snd_pcm_t *pcm)
{
ali_t *codec = pcm->private_data;
- codec->pcm = NULL;
+ codec->pcm[pcm->device] = NULL;
}
-static int __devinit snd_ali_pcm(ali_t * codec, int device, snd_pcm_t ** rpcm)
+
+static int __devinit snd_ali_pcm(ali_t * codec, int device, struct ali_pcm_description *desc)
{
snd_pcm_t *pcm;
int err;
- if (rpcm) *rpcm = NULL;
- err = snd_pcm_new(codec->card, "ALI 5451", device, ALI_CHANNELS, 1, &pcm);
+ err = snd_pcm_new(codec->card, desc->name, device,
+ desc->playback_num, desc->capture_num, &pcm);
if (err < 0) {
snd_printk("snd_ali_pcm: err called snd_pcm_new.\n");
return err;
@@ -1728,20 +1827,36 @@ static int __devinit snd_ali_pcm(ali_t * codec, int device, snd_pcm_t ** rpcm)
pcm->private_data = codec;
pcm->private_free = snd_ali_pcm_free;
pcm->info_flags = 0;
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ali_playback_ops);
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ali_capture_ops);
+ if (desc->playback_ops)
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, desc->playback_ops);
+ if (desc->capture_ops)
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, desc->capture_ops);
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
snd_dma_pci_data(codec->pci), 64*1024, 128*1024);
pcm->info_flags = 0;
pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
- strcpy(pcm->name, "ALI 5451");
- codec->pcm = pcm;
- if (rpcm) *rpcm = pcm;
+ strcpy(pcm->name, desc->name);
+ codec->pcm[0] = pcm;
return 0;
}
+struct ali_pcm_description ali_pcms[] = {
+ { "ALI 5451", ALI_CHANNELS, 1, &snd_ali_playback_ops, &snd_ali_capture_ops },
+ { "ALI 5451 modem", 1, 1, &snd_ali_modem_playback_ops, &snd_ali_modem_capture_ops }
+};
+
+static int __devinit snd_ali_build_pcms(ali_t *codec)
+{
+ int i, err;
+ for(i = 0 ; i < codec->num_of_codecs && i < ARRAY_SIZE(ali_pcms) ; i++)
+ if((err = snd_ali_pcm(codec, i, &ali_pcms[i])) < 0)
+ return err;
+ return 0;
+}
+
+
#define ALI5451_SPDIF(xname, xindex, value) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
.info = snd_ali5451_spdif_info, .get = snd_ali5451_spdif_get, \
@@ -1860,14 +1975,14 @@ static void snd_ali_mixer_free_ac97_bus(ac97_bus_t *bus)
static void snd_ali_mixer_free_ac97(ac97_t *ac97)
{
ali_t *codec = ac97->private_data;
- codec->ac97 = NULL;
+ codec->ac97[ac97->num] = NULL;
}
static int __devinit snd_ali_mixer(ali_t * codec)
{
ac97_template_t ac97;
unsigned int idx;
- int err;
+ int i, err;
static ac97_bus_ops_t ops = {
.write = snd_ali_codec_write,
.read = snd_ali_codec_read,
@@ -1880,10 +1995,16 @@ static int __devinit snd_ali_mixer(ali_t * codec)
memset(&ac97, 0, sizeof(ac97));
ac97.private_data = codec;
ac97.private_free = snd_ali_mixer_free_ac97;
- if ((err = snd_ac97_mixer(codec->ac97_bus, &ac97, &codec->ac97)) < 0) {
- snd_printk("ali mixer creating error.\n");
+
+ for ( i = 0 ; i < codec->num_of_codecs ; i++) {
+ ac97.num = i;
+ if ((err = snd_ac97_mixer(codec->ac97_bus, &ac97, &codec->ac97[i])) < 0) {
+ snd_printk("ali mixer %d creating error.\n", i);
+ if(i == 0)
return err;
}
+ }
+
if (codec->spdif_support) {
for(idx = 0; idx < ARRAY_SIZE(snd_ali5451_mixer_spdif); idx++) {
err=snd_ctl_add(codec->card, snd_ctl_new1(&snd_ali5451_mixer_spdif[idx], codec));
@@ -1904,8 +2025,12 @@ static int ali_suspend(snd_card_t *card, pm_message_t state)
if (! im)
return 0;
- snd_pcm_suspend_all(chip->pcm);
- snd_ac97_suspend(chip->ac97);
+ for(i = 0 ; i < chip->num_of_codecs ; i++) {
+ if (chip->pcm[i])
+ snd_pcm_suspend_all(chip->pcm[i]);
+ if(chip->ac97[i])
+ snd_ac97_suspend(chip->ac97[i]);
+ }
spin_lock_irq(&chip->reg_lock);
@@ -1969,7 +2094,9 @@ static int ali_resume(snd_card_t *card)
spin_unlock_irq(&chip->reg_lock);
- snd_ac97_resume(chip->ac97);
+ for(i = 0 ; i < chip->num_of_codecs ; i++)
+ if(chip->ac97[i])
+ snd_ac97_resume(chip->ac97[i]);
return 0;
}
@@ -2036,11 +2163,37 @@ static int snd_ali_chip_init(ali_t *codec)
codec->spdif_mask = 0x00000002;
}
+ codec->num_of_codecs = 1;
+
+ /* secondary codec - modem */
+ if (inl(ALI_REG(codec, ALI_SCTRL)) & ALI_SCTRL_CODEC2_READY) {
+ codec->num_of_codecs++;
+ outl(inl(ALI_REG(codec, ALI_SCTRL)) |
+ (ALI_SCTRL_LINE_IN2|ALI_SCTRL_GPIO_IN2|ALI_SCTRL_LINE_OUT_EN),
+ ALI_REG(codec, ALI_SCTRL));
+ }
+
snd_ali_printk("chip initialize succeed.\n");
return 0;
}
+/* proc for register dump */
+static void snd_ali_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buf)
+{
+ ali_t *codec = entry->private_data;
+ int i;
+ for(i = 0 ; i < 256 ; i+= 4)
+ snd_iprintf(buf, "%02x: %08x\n", i, inl(ALI_REG(codec, i)));
+}
+
+static void __devinit snd_ali_proc_init(ali_t *codec)
+{
+ snd_info_entry_t *entry;
+ if(!snd_card_proc_new(codec->card, "ali5451", &entry))
+ snd_info_set_text_ops(entry, codec, 1024, snd_ali_proc_read);
+}
+
static int __devinit snd_ali_resources(ali_t *codec)
{
int err;
@@ -2233,11 +2386,13 @@ static int __devinit snd_ali_probe(struct pci_dev *pci,
}
snd_ali_printk("pcm building ...\n");
- if ((err = snd_ali_pcm(codec, 0, NULL)) < 0) {
+ if ((err = snd_ali_build_pcms(codec)) < 0) {
snd_card_free(card);
return err;
}
+ snd_ali_proc_init(codec);
+
strcpy(card->driver, "ALI5451");
strcpy(card->shortname, "ALI 5451");
@@ -2270,7 +2425,7 @@ static struct pci_driver driver = {
static int __init alsa_card_ali_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_ali_exit(void)
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index f1a5f5723ee..ca28b229c70 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -367,7 +367,7 @@ static irqreturn_t snd_als4000_interrupt(int irq, void *dev_id, struct pt_regs *
if ((gcr_status & 0x40) && (chip->capture_substream)) /* capturing */
snd_pcm_period_elapsed(chip->capture_substream);
if ((gcr_status & 0x10) && (chip->rmidi)) /* MPU401 interrupt */
- snd_mpu401_uart_interrupt(irq, chip->rmidi, regs);
+ snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs);
/* release the gcr */
outb(gcr_status, chip->alt_port + 0xe);
@@ -777,7 +777,7 @@ static struct pci_driver driver = {
static int __init alsa_card_als4000_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_als4000_exit(void)
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 6b04c0acc6f..cafab4af5c5 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -1334,8 +1334,8 @@ static irqreturn_t snd_atiixp_interrupt(int irq, void *dev_id, struct pt_regs *r
static struct ac97_quirk ac97_quirks[] __devinitdata = {
{
- .vendor = 0x103c,
- .device = 0x006b,
+ .subvendor = 0x103c,
+ .subdevice = 0x006b,
.name = "HP Pavilion ZV5030US",
.type = AC97_TUNE_MUTE_LED
},
@@ -1645,7 +1645,7 @@ static struct pci_driver driver = {
static int __init alsa_card_atiixp_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_atiixp_exit(void)
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index fb7cecea846..a6b4b8d589f 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -463,6 +463,11 @@ static unsigned short snd_atiixp_ac97_read(ac97_t *ac97, unsigned short reg)
static void snd_atiixp_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
{
atiixp_t *chip = ac97->private_data;
+ if (reg == AC97_GPIO_STATUS) {
+ atiixp_write(chip, MODEM_OUT_GPIO,
+ (val << ATI_REG_MODEM_OUT_GPIO_DATA_SHIFT) | ATI_REG_MODEM_OUT_GPIO_EN);
+ return;
+ }
snd_atiixp_codec_write(chip, ac97->num, reg, val);
}
@@ -663,44 +668,33 @@ static int snd_atiixp_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
{
atiixp_t *chip = snd_pcm_substream_chip(substream);
atiixp_dma_t *dma = (atiixp_dma_t *)substream->runtime->private_data;
- unsigned int reg = 0;
- int i;
+ int err = 0;
snd_assert(dma->ops->enable_transfer && dma->ops->flush_dma, return -EINVAL);
- if (cmd != SNDRV_PCM_TRIGGER_START && cmd != SNDRV_PCM_TRIGGER_STOP)
- return -EINVAL;
-
spin_lock(&chip->reg_lock);
-
- /* hook off/on: via GPIO_OUT */
- for (i = 0; i < NUM_ATI_CODECS; i++) {
- if (chip->ac97[i]) {
- reg = snd_ac97_read(chip->ac97[i], AC97_GPIO_STATUS);
- break;
- }
- }
- if(cmd == SNDRV_PCM_TRIGGER_START)
- reg |= AC97_GPIO_LINE1_OH;
- else
- reg &= ~AC97_GPIO_LINE1_OH;
- reg = (reg << ATI_REG_MODEM_OUT_GPIO_DATA_SHIFT) | ATI_REG_MODEM_OUT_GPIO_EN ;
- atiixp_write(chip, MODEM_OUT_GPIO, reg);
-
- if (cmd == SNDRV_PCM_TRIGGER_START) {
+ switch(cmd) {
+ case SNDRV_PCM_TRIGGER_START:
dma->ops->enable_transfer(chip, 1);
dma->running = 1;
- } else {
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
dma->ops->enable_transfer(chip, 0);
dma->running = 0;
+ break;
+ default:
+ err = -EINVAL;
+ break;
}
+ if (! err) {
snd_atiixp_check_bus_busy(chip);
if (cmd == SNDRV_PCM_TRIGGER_STOP) {
dma->ops->flush_dma(chip);
snd_atiixp_check_bus_busy(chip);
}
+ }
spin_unlock(&chip->reg_lock);
- return 0;
+ return err;
}
@@ -1332,7 +1326,7 @@ static struct pci_driver driver = {
static int __init alsa_card_atiixp_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_atiixp_exit(void)
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index 889b4a1a51a..f6236c63aaa 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -375,7 +375,7 @@ static struct pci_driver driver = {
// initialization of the module
static int __init alsa_card_vortex_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
// clean up the module
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index b8ae534125c..72bba7b2d98 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -1520,7 +1520,7 @@ static int __init alsa_card_azf3328_init(void)
{
int err;
snd_azf3328_dbgcallenter();
- err = pci_module_init(&driver);
+ err = pci_register_driver(&driver);
snd_azf3328_dbgcallleave();
return err;
}
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index 89a7ffe5e7d..defdc5a459f 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -918,7 +918,7 @@ static int __init alsa_card_bt87x_init(void)
{
if (load_all)
driver.id_table = snd_bt87x_default_ids;
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_bt87x_exit(void)
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h
index deb02885105..da09cab405a 100644
--- a/sound/pci/ca0106/ca0106.h
+++ b/sound/pci/ca0106/ca0106.h
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
* Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
- * Version: 0.0.20
+ * Version: 0.0.21
*
* FEATURES currently supported:
* See ca0106_main.c for features.
@@ -45,6 +45,8 @@
* Added I2C and SPI registers. Filled in interrupt enable.
* 0.0.20
* Added GPIO info for SB Live 24bit.
+ * 0.0.21
+ * Implement support for Line-in capture on SB Live 24bit.
*
*
* This code was initally based on code from ALSA's emu10k1x.c which is:
@@ -152,7 +154,7 @@
* bit 9 0 = Mute / 1 = Analog out.
* bit 10 0 = Line-in / 1 = Mic-in.
* bit 11 0 = ? / 1 = ?
- * bit 12 0 = ? / 1 = ?
+ * bit 12 0 = 48 Khz / 1 = 96 Khz Analog out on SB Live 24bit.
* bit 13 0 = ? / 1 = ?
* bit 14 0 = Mute / 1 = Analog out
* bit 15 0 = ? / 1 = ?
@@ -475,9 +477,56 @@
/* Causes interrupts based on timer intervals. */
#define SPI 0x7a /* SPI: Serial Interface Register */
#define I2C_A 0x7b /* I2C Address. 32 bit */
-#define I2C_0 0x7c /* I2C Data Port 0. 32 bit */
-#define I2C_1 0x7d /* I2C Data Port 1. 32 bit */
+#define I2C_D0 0x7c /* I2C Data Port 0. 32 bit */
+#define I2C_D1 0x7d /* I2C Data Port 1. 32 bit */
+//I2C values
+#define I2C_A_ADC_ADD_MASK 0x000000fe //The address is a 7 bit address
+#define I2C_A_ADC_RW_MASK 0x00000001 //bit mask for R/W
+#define I2C_A_ADC_TRANS_MASK 0x00000010 //Bit mask for I2c address DAC value
+#define I2C_A_ADC_ABORT_MASK 0x00000020 //Bit mask for I2C transaction abort flag
+#define I2C_A_ADC_LAST_MASK 0x00000040 //Bit mask for Last word transaction
+#define I2C_A_ADC_BYTE_MASK 0x00000080 //Bit mask for Byte Mode
+#define I2C_A_ADC_ADD 0x00000034 //This is the Device address for ADC
+#define I2C_A_ADC_READ 0x00000001 //To perform a read operation
+#define I2C_A_ADC_START 0x00000100 //Start I2C transaction
+#define I2C_A_ADC_ABORT 0x00000200 //I2C transaction abort
+#define I2C_A_ADC_LAST 0x00000400 //I2C last transaction
+#define I2C_A_ADC_BYTE 0x00000800 //I2C one byte mode
+
+#define I2C_D_ADC_REG_MASK 0xfe000000 //ADC address register
+#define I2C_D_ADC_DAT_MASK 0x01ff0000 //ADC data register
+
+#define ADC_TIMEOUT 0x00000007 //ADC Timeout Clock Disable
+#define ADC_IFC_CTRL 0x0000000b //ADC Interface Control
+#define ADC_MASTER 0x0000000c //ADC Master Mode Control
+#define ADC_POWER 0x0000000d //ADC PowerDown Control
+#define ADC_ATTEN_ADCL 0x0000000e //ADC Attenuation ADCL
+#define ADC_ATTEN_ADCR 0x0000000f //ADC Attenuation ADCR
+#define ADC_ALC_CTRL1 0x00000010 //ADC ALC Control 1
+#define ADC_ALC_CTRL2 0x00000011 //ADC ALC Control 2
+#define ADC_ALC_CTRL3 0x00000012 //ADC ALC Control 3
+#define ADC_NOISE_CTRL 0x00000013 //ADC Noise Gate Control
+#define ADC_LIMIT_CTRL 0x00000014 //ADC Limiter Control
+#define ADC_MUX 0x00000015 //ADC Mux offset
+
+#if 0
+/* FIXME: Not tested yet. */
+#define ADC_GAIN_MASK 0x000000ff //Mask for ADC Gain
+#define ADC_ZERODB 0x000000cf //Value to set ADC to 0dB
+#define ADC_MUTE_MASK 0x000000c0 //Mask for ADC mute
+#define ADC_MUTE 0x000000c0 //Value to mute ADC
+#define ADC_OSR 0x00000008 //Mask for ADC oversample rate select
+#define ADC_TIMEOUT_DISABLE 0x00000008 //Value and mask to disable Timeout clock
+#define ADC_HPF_DISABLE 0x00000100 //Value and mask to disable High pass filter
+#define ADC_TRANWIN_MASK 0x00000070 //Mask for Length of Transient Window
+#endif
+
+#define ADC_MUX_MASK 0x0000000f //Mask for ADC Mux
+#define ADC_MUX_MIC 0x00000002 //Value to select Mic at ADC Mux
+#define ADC_MUX_LINEIN 0x00000004 //Value to select LineIn at ADC Mux
+#define ADC_MUX_PHONE 0x00000001 //Value to select TAD at ADC Mux (Not used)
+#define ADC_MUX_AUX 0x00000008 //Value to select Aux at ADC Mux
#define SET_CHANNEL 0 /* Testing channel outputs 0=Front, 1=Center/LFE, 2=Unknown, 3=Rear */
#define PCM_FRONT_CHANNEL 0
@@ -508,9 +557,18 @@ struct snd_ca0106_pcm {
unsigned short running;
};
+typedef struct {
+ u32 serial;
+ char * name;
+ int ac97;
+ int gpio_type;
+ int i2c_adc;
+} ca0106_details_t;
+
// definition of the chip-specific record
struct snd_ca0106 {
snd_card_t *card;
+ ca0106_details_t *details;
struct pci_dev *pci;
unsigned long port;
@@ -531,6 +589,7 @@ struct snd_ca0106 {
u32 spdif_bits[4]; /* s/pdif out setup */
int spdif_enable;
int capture_source;
+ int capture_mic_line_in;
struct snd_dma_buffer buffer;
};
@@ -547,3 +606,6 @@ void snd_ca0106_ptr_write(ca0106_t *emu,
unsigned int chn,
unsigned int data);
+int snd_ca0106_i2c_write(ca0106_t *emu, u32 reg, u32 value);
+
+
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 82533b45bc8..95c28928426 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
* Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
- * Version: 0.0.22
+ * Version: 0.0.23
*
* FEATURES currently supported:
* Front, Rear and Center/LFE.
@@ -77,6 +77,8 @@
* Add SPDIF capture using optional digital I/O module for SB Live 24bit. (Analog capture does not yet work.)
* 0.0.22
* Add support for MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97. From kiksen, bug #901
+ * 0.0.23
+ * Implement support for Line-in capture on SB Live 24bit.
*
* BUGS:
* Some stability problems when unloading the snd-ca0106 kernel module.
@@ -136,6 +138,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
@@ -161,18 +164,32 @@ MODULE_PARM_DESC(enable, "Enable the CA0106 soundcard.");
#include "ca0106.h"
-typedef struct {
- u32 serial;
- char * name;
-} ca0106_names_t;
-
-static ca0106_names_t ca0106_chip_names[] = {
- { 0x10021102, "AudigyLS [SB0310]"} ,
- { 0x10051102, "AudigyLS [SB0310b]"} , /* Unknown AudigyLS that also says SB0310 on it */
- { 0x10061102, "Live! 7.1 24bit [SB0410]"} , /* New Sound Blaster Live! 7.1 24bit. This does not have an AC97. 53SB041000001 */
- { 0x10071102, "Live! 7.1 24bit [SB0413]"} , /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97. */
- { 0x10091462, "MSI K8N Diamond MB [SB0438]"}, /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */
- { 0, "AudigyLS [Unknown]" }
+static ca0106_details_t ca0106_chip_details[] = {
+ /* AudigyLS[SB0310] */
+ { .serial = 0x10021102,
+ .name = "AudigyLS [SB0310]",
+ .ac97 = 1 } ,
+ /* Unknown AudigyLS that also says SB0310 on it */
+ { .serial = 0x10051102,
+ .name = "AudigyLS [SB0310b]",
+ .ac97 = 1 } ,
+ /* New Sound Blaster Live! 7.1 24bit. This does not have an AC97. 53SB041000001 */
+ { .serial = 0x10061102,
+ .name = "Live! 7.1 24bit [SB0410]",
+ .gpio_type = 1,
+ .i2c_adc = 1 } ,
+ /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97. */
+ { .serial = 0x10071102,
+ .name = "Live! 7.1 24bit [SB0413]",
+ .gpio_type = 1,
+ .i2c_adc = 1 } ,
+ /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */
+ { .serial = 0x10091462,
+ .name = "MSI K8N Diamond MB [SB0438]",
+ .gpio_type = 1,
+ .i2c_adc = 1 } ,
+ { .serial = 0,
+ .name = "AudigyLS [Unknown]" }
};
/* hardware definition */
@@ -200,10 +217,10 @@ static snd_pcm_hardware_t snd_ca0106_capture_hw = {
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID),
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- .rates = SNDRV_PCM_RATE_48000,
- .rate_min = 48000,
- .rate_max = 48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
+ .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000,
+ .rate_min = 44100,
+ .rate_max = 192000,
.channels_min = 2,
.channels_max = 2,
.buffer_bytes_max = ((65536 - 64) * 8),
@@ -246,6 +263,62 @@ void snd_ca0106_ptr_write(ca0106_t *emu,
spin_unlock_irqrestore(&emu->emu_lock, flags);
}
+int snd_ca0106_i2c_write(ca0106_t *emu,
+ u32 reg,
+ u32 value)
+{
+ u32 tmp;
+ int timeout=0;
+ int status;
+ int retry;
+ if ((reg > 0x7f) || (value > 0x1ff))
+ {
+ snd_printk("i2c_write: invalid values.\n");
+ return -EINVAL;
+ }
+
+ tmp = reg << 25 | value << 16;
+ /* Not sure what this I2C channel controls. */
+ /* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */
+
+ /* This controls the I2C connected to the WM8775 ADC Codec */
+ snd_ca0106_ptr_write(emu, I2C_D1, 0, tmp);
+
+ for(retry=0;retry<10;retry++)
+ {
+ /* Send the data to i2c */
+ tmp = snd_ca0106_ptr_read(emu, I2C_A, 0);
+ tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK);
+ tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD);
+ snd_ca0106_ptr_write(emu, I2C_A, 0, tmp);
+
+ /* Wait till the transaction ends */
+ while(1)
+ {
+ status = snd_ca0106_ptr_read(emu, I2C_A, 0);
+ //snd_printk("I2C:status=0x%x\n", status);
+ timeout++;
+ if((status & I2C_A_ADC_START)==0)
+ break;
+
+ if(timeout>1000)
+ break;
+ }
+ //Read back and see if the transaction is successful
+ if((status & I2C_A_ADC_ABORT)==0)
+ break;
+ }
+
+ if(retry==10)
+ {
+ snd_printk("Writing to ADC failed!\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
static void snd_ca0106_intr_enable(ca0106_t *emu, unsigned int intrenb)
{
unsigned long flags;
@@ -259,11 +332,7 @@ static void snd_ca0106_intr_enable(ca0106_t *emu, unsigned int intrenb)
static void snd_ca0106_pcm_free_substream(snd_pcm_runtime_t *runtime)
{
- ca0106_pcm_t *epcm = runtime->private_data;
-
- if (epcm) {
- kfree(epcm);
- }
+ kfree(runtime->private_data);
}
/* open_playback callback */
@@ -538,6 +607,61 @@ static int snd_ca0106_pcm_prepare_capture(snd_pcm_substream_t *substream)
snd_pcm_runtime_t *runtime = substream->runtime;
ca0106_pcm_t *epcm = runtime->private_data;
int channel = epcm->channel_id;
+ u32 hcfg_mask = HCFG_CAPTURE_S32_LE;
+ u32 hcfg_set = 0x00000000;
+ u32 hcfg;
+ u32 over_sampling=0x2;
+ u32 reg71_mask = 0x0000c000 ; /* Global. Set ADC rate. */
+ u32 reg71_set = 0;
+ u32 reg71;
+
+ //snd_printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, periods=%u, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1));
+ //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
+ //snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
+ /* reg71 controls ADC rate. */
+ switch (runtime->rate) {
+ case 44100:
+ reg71_set = 0x00004000;
+ break;
+ case 48000:
+ reg71_set = 0;
+ break;
+ case 96000:
+ reg71_set = 0x00008000;
+ over_sampling=0xa;
+ break;
+ case 192000:
+ reg71_set = 0x0000c000;
+ over_sampling=0xa;
+ break;
+ default:
+ reg71_set = 0;
+ break;
+ }
+ /* Format is a global setting */
+ /* FIXME: Only let the first channel accessed set this. */
+ switch (runtime->format) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ hcfg_set = 0;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ hcfg_set = HCFG_CAPTURE_S32_LE;
+ break;
+ default:
+ hcfg_set = 0;
+ break;
+ }
+ hcfg = inl(emu->port + HCFG) ;
+ hcfg = (hcfg & ~hcfg_mask) | hcfg_set;
+ outl(hcfg, emu->port + HCFG);
+ reg71 = snd_ca0106_ptr_read(emu, 0x71, 0);
+ reg71 = (reg71 & ~reg71_mask) | reg71_set;
+ snd_ca0106_ptr_write(emu, 0x71, 0, reg71);
+ if (emu->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
+ snd_ca0106_i2c_write(emu, ADC_MASTER, over_sampling); /* Adjust the over sampler to better suit the capture rate. */
+ }
+
+
//printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, frames_to_bytes(runtime, 1));
snd_ca0106_ptr_write(emu, 0x13, channel, 0);
snd_ca0106_ptr_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr);
@@ -810,6 +934,7 @@ static int snd_ca0106_ac97(ca0106_t *chip)
memset(&ac97, 0, sizeof(ac97));
ac97.private_data = chip;
+ ac97.scaps = AC97_SCAP_NO_SPDIF;
return snd_ac97_mixer(pbus, &ac97, &chip->ac97);
}
@@ -993,6 +1118,7 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
ca0106_t **rchip)
{
ca0106_t *chip;
+ ca0106_details_t *c;
int err;
int ch;
static snd_device_ops_t ops = {
@@ -1003,8 +1129,8 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
if ((err = pci_enable_device(pci)) < 0)
return err;
- if (pci_set_dma_mask(pci, 0xffffffffUL) < 0 ||
- pci_set_consistent_dma_mask(pci, 0xffffffffUL) < 0) {
+ if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) {
printk(KERN_ERR "error to set 32bit mask DMA\n");
pci_disable_device(pci);
return -ENXIO;
@@ -1054,6 +1180,15 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
printk(KERN_INFO "Model %04x Rev %08x Serial %08x\n", chip->model,
chip->revision, chip->serial);
#endif
+ strcpy(card->driver, "CA0106");
+ strcpy(card->shortname, "CA0106");
+
+ for (c=ca0106_chip_details; c->serial; c++) {
+ if (c->serial == chip->serial) break;
+ }
+ chip->details = c;
+ sprintf(card->longname, "%s at 0x%lx irq %i",
+ c->name, chip->port, chip->irq);
outl(0, chip->port + INTE);
@@ -1113,7 +1248,7 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
//snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); /* OSS drivers set this. */
/* Analog or Digital output */
snd_ca0106_ptr_write(chip, SPDIF_SELECT1, 0, 0xf);
- snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000b0000); /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers */
+ snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000f0000); /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers. Use 0x000f0000 for surround71 */
chip->spdif_enable = 0; /* Set digital SPDIF output off */
chip->capture_source = 3; /* Set CAPTURE_SOURCE */
//snd_ca0106_ptr_write(chip, 0x45, 0, 0); /* Analogue out */
@@ -1138,13 +1273,11 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC, Line in, TAD in, AUX in */
chip->capture_source = 3; /* Set CAPTURE_SOURCE */
- if ((chip->serial == 0x10061102) ||
- (chip->serial == 0x10071102) ||
- (chip->serial == 0x10091462)) { /* The SB0410 and SB0413 use GPIO differently. */
+ if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */
/* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
outl(0x0, chip->port+GPIO);
//outl(0x00f0e000, chip->port+GPIO); /* Analog */
- outl(0x005f4300, chip->port+GPIO); /* Analog */
+ outl(0x005f5301, chip->port+GPIO); /* Analog */
} else {
outl(0x0, chip->port+GPIO);
outl(0x005f03a3, chip->port+GPIO); /* Analog */
@@ -1157,6 +1290,10 @@ static int __devinit snd_ca0106_create(snd_card_t *card,
//outl(0x00000009, chip->port+HCFG);
outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */
+ if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
+ snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */
+ }
+
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
chip, &ops)) < 0) {
snd_ca0106_free(chip);
@@ -1172,7 +1309,6 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
static int dev;
snd_card_t *card;
ca0106_t *chip;
- ca0106_names_t *c;
int err;
if (dev >= SNDRV_CARDS)
@@ -1207,9 +1343,7 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
- if ((chip->serial != 0x10061102) &&
- (chip->serial != 0x10071102) &&
- (chip->serial != 0x10091462) ) { /* The SB0410 and SB0413 do not have an ac97 chip. */
+ if (chip->details->ac97 == 1) { /* The SB0410 and SB0413 do not have an AC97 chip. */
if ((err = snd_ca0106_ac97(chip)) < 0) {
snd_card_free(card);
return err;
@@ -1222,15 +1356,6 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
snd_ca0106_proc_init(chip);
- strcpy(card->driver, "CA0106");
- strcpy(card->shortname, "CA0106");
-
- for (c=ca0106_chip_names; c->serial; c++) {
- if (c->serial == chip->serial) break;
- }
- sprintf(card->longname, "%s at 0x%lx irq %i",
- c->name, chip->port, chip->irq);
-
if ((err = snd_card_register(card)) < 0) {
snd_card_free(card);
return err;
@@ -1267,7 +1392,7 @@ static int __init alsa_card_ca0106_init(void)
{
int err;
- if ((err = pci_module_init(&driver)) > 0)
+ if ((err = pci_register_driver(&driver)) > 0)
return err;
return 0;
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
index 97bed1b0899..0e5e9ce0ff2 100644
--- a/sound/pci/ca0106/ca0106_mixer.c
+++ b/sound/pci/ca0106/ca0106_mixer.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
* Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
- * Version: 0.0.16
+ * Version: 0.0.17
*
* FEATURES currently supported:
* See ca0106_main.c for features.
@@ -37,6 +37,8 @@
* Separated ca0106.c into separate functional .c files.
* 0.0.16
* Modified Copyright message.
+ * 0.0.17
+ * Implement Mic and Line in Capture.
*
* This code was initally based on code from ALSA's emu10k1x.c which is:
* Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
@@ -113,7 +115,7 @@ static int snd_ca0106_shared_spdif_put(snd_kcontrol_t * kcontrol,
} else {
/* Analog */
snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
- snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000b0000);
+ snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000);
snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0,
snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000);
mask = inl(emu->port + GPIO) | 0x101;
@@ -183,6 +185,65 @@ static snd_kcontrol_new_t snd_ca0106_capture_source __devinitdata =
.put = snd_ca0106_capture_source_put
};
+static int snd_ca0106_capture_mic_line_in_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+ static char *texts[2] = { "Line in", "Mic in" };
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 2;
+ if (uinfo->value.enumerated.item > 1)
+ uinfo->value.enumerated.item = 1;
+ strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int snd_ca0106_capture_mic_line_in_get(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ ca0106_t *emu = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.enumerated.item[0] = emu->capture_mic_line_in;
+ return 0;
+}
+
+static int snd_ca0106_capture_mic_line_in_put(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ ca0106_t *emu = snd_kcontrol_chip(kcontrol);
+ unsigned int val;
+ int change = 0;
+ u32 tmp;
+
+ val = ucontrol->value.enumerated.item[0] ;
+ change = (emu->capture_mic_line_in != val);
+ if (change) {
+ emu->capture_mic_line_in = val;
+ if (val) {
+ snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_PHONE); /* Mute input */
+ tmp = inl(emu->port+GPIO) & ~0x400;
+ tmp = tmp | 0x400;
+ outl(tmp, emu->port+GPIO);
+ snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC);
+ } else {
+ snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_PHONE); /* Mute input */
+ tmp = inl(emu->port+GPIO) & ~0x400;
+ outl(tmp, emu->port+GPIO);
+ snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN);
+ }
+ }
+ return change;
+}
+
+static snd_kcontrol_new_t snd_ca0106_capture_mic_line_in __devinitdata =
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Mic/Line in Capture",
+ .info = snd_ca0106_capture_mic_line_in_info,
+ .get = snd_ca0106_capture_mic_line_in_get,
+ .put = snd_ca0106_capture_mic_line_in_put
+};
+
static int snd_ca0106_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
@@ -437,7 +498,7 @@ static snd_kcontrol_new_t snd_ca0106_volume_control_analog_center_lfe =
static snd_kcontrol_new_t snd_ca0106_volume_control_analog_unknown =
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Analog Unknown Volume",
+ .name = "Analog Side Volume",
.info = snd_ca0106_volume_info,
.get = snd_ca0106_volume_get_analog_unknown,
.put = snd_ca0106_volume_put_analog_unknown
@@ -620,10 +681,11 @@ int __devinit snd_ca0106_mixer(ca0106_t *emu)
return -ENOMEM;
if ((err = snd_ctl_add(card, kctl)))
return err;
- if ((kctl = ctl_find(card, SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT))) != NULL) {
- /* already defined by ac97, remove it */
- /* FIXME: or do we need both controls? */
- remove_ctl(card, SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT));
+ if (emu->details->i2c_adc == 1) {
+ if ((kctl = snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu)) == NULL)
+ return -ENOMEM;
+ if ((err = snd_ctl_add(card, kctl)))
+ return err;
}
if ((kctl = snd_ctl_new1(&snd_ca0106_spdif_control, emu)) == NULL)
return -ENOMEM;
diff --git a/sound/pci/ca0106/ca0106_proc.c b/sound/pci/ca0106/ca0106_proc.c
index afb711421e4..1c9cc821d1b 100644
--- a/sound/pci/ca0106/ca0106_proc.c
+++ b/sound/pci/ca0106/ca0106_proc.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
* Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
- * Version: 0.0.17
+ * Version: 0.0.18
*
* FEATURES currently supported:
* See ca0106_main.c for features.
@@ -39,7 +39,9 @@
* Modified Copyright message.
* 0.0.17
* Add iec958 file in proc file system to show status of SPDIF in.
- *
+ * 0.0.18
+ * Implement support for Line-in capture on SB Live 24bit.
+ *
* This code was initally based on code from ALSA's emu10k1x.c which is:
* Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
*
@@ -95,7 +97,7 @@ static struct snd_ca0106_category_str snd_ca0106_con_category[] = {
};
-void snd_ca0106_proc_dump_iec958( snd_info_buffer_t *buffer, u32 value)
+static void snd_ca0106_proc_dump_iec958( snd_info_buffer_t *buffer, u32 value)
{
int i;
u32 status[4];
@@ -407,6 +409,20 @@ static void snd_ca0106_proc_reg_write(snd_info_entry_t *entry,
}
}
+static void snd_ca0106_proc_i2c_write(snd_info_entry_t *entry,
+ snd_info_buffer_t * buffer)
+{
+ ca0106_t *emu = entry->private_data;
+ char line[64];
+ unsigned int reg, val;
+ while (!snd_info_get_line(buffer, line, sizeof(line))) {
+ if (sscanf(line, "%x %x", &reg, &val) != 2)
+ continue;
+ if ((reg <= 0x7f) || (val <= 0x1ff)) {
+ snd_ca0106_i2c_write(emu, reg, val);
+ }
+ }
+}
int __devinit snd_ca0106_proc_init(ca0106_t * emu)
{
@@ -418,6 +434,7 @@ int __devinit snd_ca0106_proc_init(ca0106_t * emu)
snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read32);
entry->c.text.write_size = 64;
entry->c.text.write = snd_ca0106_proc_reg_write32;
+ entry->mode |= S_IWUSR;
}
if(! snd_card_proc_new(emu->card, "ca0106_reg16", &entry))
snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read16);
@@ -427,6 +444,14 @@ int __devinit snd_ca0106_proc_init(ca0106_t * emu)
snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read1);
entry->c.text.write_size = 64;
entry->c.text.write = snd_ca0106_proc_reg_write;
+ entry->mode |= S_IWUSR;
+// entry->private_data = emu;
+ }
+ if(! snd_card_proc_new(emu->card, "ca0106_i2c", &entry)) {
+ snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_i2c_write);
+ entry->c.text.write_size = 64;
+ entry->c.text.write = snd_ca0106_proc_i2c_write;
+ entry->mode |= S_IWUSR;
// entry->private_data = emu;
}
if(! snd_card_proc_new(emu->card, "ca0106_regs2", &entry))
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index 113208fbde1..b4503385ea6 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -519,40 +519,50 @@ inline static unsigned char snd_cmipci_read_b(cmipci_t *cm, unsigned int cmd)
}
/* bit operations for dword register */
-static void snd_cmipci_set_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag)
+static int snd_cmipci_set_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag)
{
- unsigned int val;
- val = inl(cm->iobase + cmd);
+ unsigned int val, oval;
+ val = oval = inl(cm->iobase + cmd);
val |= flag;
+ if (val == oval)
+ return 0;
outl(val, cm->iobase + cmd);
+ return 1;
}
-static void snd_cmipci_clear_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag)
+static int snd_cmipci_clear_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag)
{
- unsigned int val;
- val = inl(cm->iobase + cmd);
+ unsigned int val, oval;
+ val = oval = inl(cm->iobase + cmd);
val &= ~flag;
+ if (val == oval)
+ return 0;
outl(val, cm->iobase + cmd);
+ return 1;
}
-#if 0 // not used
/* bit operations for byte register */
-static void snd_cmipci_set_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag)
+static int snd_cmipci_set_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag)
{
- unsigned char val;
- val = inb(cm->iobase + cmd);
+ unsigned char val, oval;
+ val = oval = inb(cm->iobase + cmd);
val |= flag;
+ if (val == oval)
+ return 0;
outb(val, cm->iobase + cmd);
+ return 1;
}
-static void snd_cmipci_clear_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag)
+static int snd_cmipci_clear_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag)
{
- unsigned char val;
- val = inb(cm->iobase + cmd);
+ unsigned char val, oval;
+ val = oval = inb(cm->iobase + cmd);
val &= ~flag;
+ if (val == oval)
+ return 0;
outb(val, cm->iobase + cmd);
+ return 1;
}
-#endif
/*
@@ -2250,8 +2260,8 @@ DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, 0, 0, 0); /* rever
DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, CM_XCHGDAC, 0, 0);
#endif
DEFINE_BIT_SWITCH_ARG(fourch, CM_REG_MISC_CTRL, CM_N4SPK3D, 0, 0);
-DEFINE_BIT_SWITCH_ARG(line_rear, CM_REG_MIXER1, CM_SPK4, 1, 0);
-DEFINE_BIT_SWITCH_ARG(line_bass, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS, 0, 0);
+// DEFINE_BIT_SWITCH_ARG(line_rear, CM_REG_MIXER1, CM_SPK4, 1, 0);
+// DEFINE_BIT_SWITCH_ARG(line_bass, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS, 0, 0);
// DEFINE_BIT_SWITCH_ARG(joystick, CM_REG_FUNCTRL1, CM_JYSTK_EN, 0, 0); /* now module option */
DEFINE_SWITCH_ARG(modem, CM_REG_MISC_CTRL, CM_FLINKON|CM_FLINKOFF, CM_FLINKON, 0, 0);
@@ -2300,10 +2310,114 @@ static int snd_cmipci_spdout_enable_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_v
}
+static int snd_cmipci_line_in_mode_info(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_info_t *uinfo)
+{
+ cmipci_t *cm = snd_kcontrol_chip(kcontrol);
+ static char *texts[3] = { "Line-In", "Rear Output", "Bass Output" };
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = cm->chip_version >= 39 ? 3 : 2;
+ if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+ uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+ strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static inline unsigned int get_line_in_mode(cmipci_t *cm)
+{
+ unsigned int val;
+ if (cm->chip_version >= 39) {
+ val = snd_cmipci_read(cm, CM_REG_LEGACY_CTRL);
+ if (val & CM_LINE_AS_BASS)
+ return 2;
+ }
+ val = snd_cmipci_read_b(cm, CM_REG_MIXER1);
+ if (val & CM_SPK4)
+ return 1;
+ return 0;
+}
+
+static int snd_cmipci_line_in_mode_get(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_value_t *ucontrol)
+{
+ cmipci_t *cm = snd_kcontrol_chip(kcontrol);
+
+ spin_lock_irq(&cm->reg_lock);
+ ucontrol->value.enumerated.item[0] = get_line_in_mode(cm);
+ spin_unlock_irq(&cm->reg_lock);
+ return 0;
+}
+
+static int snd_cmipci_line_in_mode_put(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_value_t *ucontrol)
+{
+ cmipci_t *cm = snd_kcontrol_chip(kcontrol);
+ int change;
+
+ spin_lock_irq(&cm->reg_lock);
+ if (ucontrol->value.enumerated.item[0] == 2)
+ change = snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS);
+ else
+ change = snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS);
+ if (ucontrol->value.enumerated.item[0] == 1)
+ change |= snd_cmipci_set_bit_b(cm, CM_REG_MIXER1, CM_SPK4);
+ else
+ change |= snd_cmipci_clear_bit_b(cm, CM_REG_MIXER1, CM_SPK4);
+ spin_unlock_irq(&cm->reg_lock);
+ return change;
+}
+
+static int snd_cmipci_mic_in_mode_info(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_info_t *uinfo)
+{
+ static char *texts[2] = { "Mic-In", "Center/LFE Output" };
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 2;
+ if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+ uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+ strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int snd_cmipci_mic_in_mode_get(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_value_t *ucontrol)
+{
+ cmipci_t *cm = snd_kcontrol_chip(kcontrol);
+ /* same bit as spdi_phase */
+ spin_lock_irq(&cm->reg_lock);
+ ucontrol->value.enumerated.item[0] =
+ (snd_cmipci_read_b(cm, CM_REG_MISC) & CM_SPDIF_INVERSE) ? 1 : 0;
+ spin_unlock_irq(&cm->reg_lock);
+ return 0;
+}
+
+static int snd_cmipci_mic_in_mode_put(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_value_t *ucontrol)
+{
+ cmipci_t *cm = snd_kcontrol_chip(kcontrol);
+ int change;
+
+ spin_lock_irq(&cm->reg_lock);
+ if (ucontrol->value.enumerated.item[0])
+ change = snd_cmipci_set_bit_b(cm, CM_REG_MISC, CM_SPDIF_INVERSE);
+ else
+ change = snd_cmipci_clear_bit_b(cm, CM_REG_MISC, CM_SPDIF_INVERSE);
+ spin_unlock_irq(&cm->reg_lock);
+ return change;
+}
+
/* both for CM8338/8738 */
static snd_kcontrol_new_t snd_cmipci_mixer_switches[] __devinitdata = {
DEFINE_MIXER_SWITCH("Four Channel Mode", fourch),
- DEFINE_MIXER_SWITCH("Line-In As Rear", line_rear),
+ {
+ .name = "Line-In Mode",
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .info = snd_cmipci_line_in_mode_info,
+ .get = snd_cmipci_line_in_mode_get,
+ .put = snd_cmipci_line_in_mode_put,
+ },
};
/* for non-multichannel chips */
@@ -2341,10 +2455,15 @@ static snd_kcontrol_new_t snd_cmipci_old_mixer_switches[] __devinitdata = {
/* only for model 039 or later */
static snd_kcontrol_new_t snd_cmipci_extra_mixer_switches[] __devinitdata = {
- DEFINE_MIXER_SWITCH("Line-In As Bass", line_bass),
DEFINE_MIXER_SWITCH("IEC958 In Select", spdif_in_sel2),
DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase2),
- DEFINE_MIXER_SWITCH("Mic As Center/LFE", spdi_phase), /* same bit as spdi_phase */
+ {
+ .name = "Mic-In Mode",
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .info = snd_cmipci_mic_in_mode_info,
+ .get = snd_cmipci_mic_in_mode_get,
+ .put = snd_cmipci_mic_in_mode_put,
+ }
};
/* card control switches */
@@ -2944,7 +3063,7 @@ static struct pci_driver driver = {
static int __init alsa_card_cmipci_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_cmipci_exit(void)
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index d7e06b3caf9..b6e1854e938 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -206,7 +206,10 @@ MODULE_PARM_DESC(dual_codec, "Secondary Codec ID (0 = disabled).");
#define BA0_PMCS 0x0344 /* Power Management Control/Status */
#define BA0_CWPR 0x03e0 /* Configuration Write Protect */
+
#define BA0_EPPMC 0x03e4 /* Extended PCI Power Management Control */
+#define BA0_EPPMC_FPDN (1<<14) /* Full Power DowN */
+
#define BA0_GPIOR 0x03e8 /* GPIO Pin Interface Register */
#define BA0_SPMC 0x03ec /* Serial Port Power Management Control (& ASDIN2 enable) */
@@ -1461,6 +1464,11 @@ static int snd_cs4281_chip_init(cs4281_t *chip)
int timeout;
int retry_count = 2;
+ /* Having EPPMC.FPDN=1 prevent proper chip initialisation */
+ tmp = snd_cs4281_peekBA0(chip, BA0_EPPMC);
+ if (tmp & BA0_EPPMC_FPDN)
+ snd_cs4281_pokeBA0(chip, BA0_EPPMC, tmp & ~BA0_EPPMC_FPDN);
+
__retry:
tmp = snd_cs4281_peekBA0(chip, BA0_CFLR);
if (tmp != BA0_CFLR_DEFAULT) {
@@ -2124,7 +2132,7 @@ static struct pci_driver driver = {
static int __init alsa_card_cs4281_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_cs4281_exit(void)
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
index 25d6466a867..db212ecd792 100644
--- a/sound/pci/cs46xx/cs46xx.c
+++ b/sound/pci/cs46xx/cs46xx.c
@@ -171,7 +171,7 @@ static struct pci_driver driver = {
static int __init alsa_card_cs46xx_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_cs46xx_exit(void)
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 5f2ffb7efa0..fd4c50c88bc 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -1295,8 +1295,7 @@ static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = {
static void snd_cs46xx_pcm_free_substream(snd_pcm_runtime_t *runtime)
{
- cs46xx_pcm_t * cpcm = runtime->private_data;
- kfree(cpcm);
+ kfree(runtime->private_data);
}
static int _cs46xx_playback_open_channel (snd_pcm_substream_t * substream,int pcm_channel_id)
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index 6446afe19d8..2085a998eae 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -228,7 +228,7 @@ static struct pci_driver driver = {
static int __init alsa_card_emu10k1_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_emu10k1_exit(void)
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index c3c96f9f2c7..a341e758acd 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -170,7 +170,7 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir)
SPCS_GENERATIONSTATUS | 0x00001200 |
0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
- if (emu->audigy && emu->revision == 4) { /* audigy2 */
+ if (emu->card_capabilities->ca0151_chip) { /* audigy2 */
/* Hacks for Alice3 to work independent of haP16V driver */
u32 tmp;
@@ -189,7 +189,7 @@ static int __devinit snd_emu10k1_init(emu10k1_t * emu, int enable_ir)
/* Enabled Phased (8-channel) P16V playback */
outl(0x0201, emu->port + HCFG2);
/* Set playback routing. */
- snd_emu10k1_ptr_write(emu, CAPTURE_P16V_SOURCE, 0, 78e4);
+ snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, 0x78e4);
}
if (emu->audigy && (emu->serial == 0x10011102) ) { /* audigy2 Value */
/* Hacks for Alice3 to work independent of haP16V driver */
@@ -600,7 +600,7 @@ static int snd_emu10k1_free(emu10k1_t *emu)
if (emu->port)
pci_release_regions(emu->pci);
pci_disable_device(emu->pci);
- if (emu->audigy && emu->revision == 4) /* P16V */
+ if (emu->card_capabilities->ca0151_chip) /* P16V */
snd_p16v_free(emu);
kfree(emu);
return 0;
@@ -612,21 +612,24 @@ static int snd_emu10k1_dev_free(snd_device_t *device)
return snd_emu10k1_free(emu);
}
-/* vendor, device, subsystem, emu10k1_chip, emu10k2_chip, ca0102_chip, ca0108_chip, ca0151_chip, spk71, spdif_bug, ac97_chip, ecard, driver, name */
-
static emu_chip_details_t emu_chip_details[] = {
/* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/
{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102,
.driver = "Audigy2", .name = "Audigy 2 Value [SB0400]",
+ .id = "Audigy2",
.emu10k2_chip = 1,
.ca0108_chip = 1,
- .spk71 = 1} ,
+ .spk71 = 1,
+ .ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0008,
.driver = "Audigy2", .name = "Audigy 2 Value [Unknown]",
+ .id = "Audigy2",
.emu10k2_chip = 1,
- .ca0108_chip = 1} ,
+ .ca0108_chip = 1,
+ .ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102,
.driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]",
+ .id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.ca0151_chip = 1,
@@ -635,6 +638,7 @@ static emu_chip_details_t emu_chip_details[] = {
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20021102,
.driver = "Audigy2", .name = "Audigy 2 ZS [SB0350]",
+ .id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.ca0151_chip = 1,
@@ -643,6 +647,7 @@ static emu_chip_details_t emu_chip_details[] = {
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20011102,
.driver = "Audigy2", .name = "Audigy 2 ZS [2001]",
+ .id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.ca0151_chip = 1,
@@ -651,6 +656,7 @@ static emu_chip_details_t emu_chip_details[] = {
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10071102,
.driver = "Audigy2", .name = "Audigy 2 [SB0240]",
+ .id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.ca0151_chip = 1,
@@ -659,35 +665,165 @@ static emu_chip_details_t emu_chip_details[] = {
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102,
.driver = "Audigy2", .name = "Audigy 2 EX [1005]",
+ .id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.ca0151_chip = 1,
.spdif_bug = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102,
.driver = "Audigy2", .name = "Audigy 2 Platinum [SB0240P]",
+ .id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.ca0151_chip = 1,
.spk71 = 1,
.spdif_bug = 1,
.ac97_chip = 1} ,
+ {.vendor = 0x1102, .device = 0x0004, .revision = 0x04,
+ .driver = "Audigy2", .name = "Audigy 2 [Unknown]",
+ .id = "Audigy2",
+ .emu10k2_chip = 1,
+ .ca0102_chip = 1,
+ .ca0151_chip = 1,
+ .spdif_bug = 1,
+ .ac97_chip = 1} ,
+ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10020052,
+ .driver = "Audigy", .name = "Audigy 1 ES [SB0160]",
+ .id = "Audigy",
+ .emu10k2_chip = 1,
+ .ca0102_chip = 1,
+ .spdif_bug = 1,
+ .ac97_chip = 1} ,
+ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00531102,
+ .driver = "Audigy", .name = "Audigy 1 [SB0090]",
+ .id = "Audigy",
+ .emu10k2_chip = 1,
+ .ca0102_chip = 1,
+ .ac97_chip = 1} ,
+ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00511102,
+ .driver = "Audigy", .name = "Audigy 1 [SB0090]",
+ .id = "Audigy",
+ .emu10k2_chip = 1,
+ .ca0102_chip = 1,
+ .ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004,
- .driver = "Audigy", .name = "Audigy 1 or 2 [Unknown]",
+ .driver = "Audigy", .name = "Audigy 1 [Unknown]",
+ .id = "Audigy",
.emu10k2_chip = 1,
.ca0102_chip = 1,
- .spdif_bug = 1} ,
+ .ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x40011102,
.driver = "EMU10K1", .name = "E-mu APS [4001]",
+ .id = "APS",
.emu10k1_chip = 1,
.ecard = 1} ,
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102,
+ .driver = "EMU10K1", .name = "SBLive! Player 5.1 [SB0060]",
+ .id = "Live",
+ .emu10k1_chip = 1,
+ .ac97_chip = 1,
+ .sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80641102,
.driver = "EMU10K1", .name = "SB Live 5.1",
+ .id = "Live",
+ .emu10k1_chip = 1,
+ .ac97_chip = 1,
+ .sblive51 = 1} ,
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80401102,
+ .driver = "EMU10K1", .name = "SBLive! Platinum [CT4760P]",
+ .id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1} ,
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00211102,
+ .driver = "EMU10K1", .name = "SBLive! [CT4620]",
+ .id = "Live",
+ .emu10k1_chip = 1,
+ .ac97_chip = 1,
+ .sblive51 = 1} ,
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00201102,
+ .driver = "EMU10K1", .name = "SBLive! Value [CT4670]",
+ .id = "Live",
+ .emu10k1_chip = 1,
+ .ac97_chip = 1,
+ .sblive51 = 1} ,
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80221102,
+ .driver = "EMU10K1", .name = "SBLive! Value [CT4780]",
+ .id = "Live",
+ .emu10k1_chip = 1,
+ .ac97_chip = 1,
+ .sblive51 = 1} ,
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80231102,
+ .driver = "EMU10K1", .name = "SB PCI512 [CT4790]",
+ .id = "Live",
+ .emu10k1_chip = 1,
+ .ac97_chip = 1,
+ .sblive51 = 1} ,
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80261102,
+ .driver = "EMU10K1", .name = "SBLive! Value [CT4830]",
+ .id = "Live",
+ .emu10k1_chip = 1,
+ .ac97_chip = 1,
+ .sblive51 = 1} ,
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80311102,
+ .driver = "EMU10K1", .name = "SBLive! Value [CT4831]",
+ .id = "Live",
+ .emu10k1_chip = 1,
+ .ac97_chip = 1,
+ .sblive51 = 1} ,
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80271102,
+ .driver = "EMU10K1", .name = "SBLive! Value [CT4832]",
+ .id = "Live",
+ .emu10k1_chip = 1,
+ .ac97_chip = 1,
+ .sblive51 = 1} ,
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80511102,
+ .driver = "EMU10K1", .name = "SBLive! Value [CT4850]",
+ .id = "Live",
+ .emu10k1_chip = 1,
+ .ac97_chip = 1,
+ .sblive51 = 1} ,
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80281102,
+ .driver = "EMU10K1", .name = "SBLive! Value [CT4870]",
+ .id = "Live",
+ .emu10k1_chip = 1,
+ .ac97_chip = 1,
+ .sblive51 = 1} ,
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80321102,
+ .driver = "EMU10K1", .name = "SBLive! Value [CT4871]",
+ .id = "Live",
+ .emu10k1_chip = 1,
+ .ac97_chip = 1,
+ .sblive51 = 1} ,
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102,
+ .driver = "EMU10K1", .name = "SBLive! Value [SB0060]",
+ .id = "Live",
+ .emu10k1_chip = 1,
+ .ac97_chip = 1,
+ .sblive51 = 1} ,
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80691102,
+ .driver = "EMU10K1", .name = "SBLive! Value [SB0101]",
+ .id = "Live",
+ .emu10k1_chip = 1,
+ .ac97_chip = 1,
+ .sblive51 = 1} ,
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806A1102,
+ .driver = "EMU10K1", .name = "SBLive! Value [SB0103]",
+ .id = "Live",
+ .emu10k1_chip = 1,
+ .ac97_chip = 1,
+ .sblive51 = 1} ,
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806B1102,
+ .driver = "EMU10K1", .name = "SBLive! [SB0105]",
+ .id = "Live",
+ .emu10k1_chip = 1,
+ .ac97_chip = 1,
+ .sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002,
.driver = "EMU10K1", .name = "SB Live [Unknown]",
+ .id = "Live",
.emu10k1_chip = 1,
- .ac97_chip = 1} ,
+ .ac97_chip = 1,
+ .sblive51 = 1} ,
{ } /* terminator */
};
@@ -738,13 +874,15 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
emu->revision = revision;
pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial);
pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &emu->model);
- emu->card_type = EMU10K1_CARD_CREATIVE;
snd_printdd("vendor=0x%x, device=0x%x, subsystem_vendor_id=0x%x, subsystem_id=0x%x\n",pci->vendor, pci->device, emu->serial, emu->model);
for (c = emu_chip_details; c->vendor; c++) {
if (c->vendor == pci->vendor && c->device == pci->device) {
- if (c->subsystem == emu->serial) break;
- if (c->subsystem == 0) break;
+ if (c->subsystem && c->subsystem != emu->serial)
+ continue;
+ if (c->revision && c->revision != emu->revision)
+ continue;
+ break;
}
}
if (c->vendor == 0) {
@@ -759,6 +897,23 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
else
snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x\n", c->name, pci->vendor, pci->device, emu->serial);
+ if (!*card->id && c->id) {
+ int i, n = 0;
+ strlcpy(card->id, c->id, sizeof(card->id));
+ for (;;) {
+ for (i = 0; i < snd_ecards_limit; i++) {
+ if (snd_cards[i] && !strcmp(snd_cards[i]->id, card->id))
+ break;
+ }
+ if (i >= snd_ecards_limit)
+ break;
+ n++;
+ if (n >= SNDRV_CARDS)
+ break;
+ snprintf(card->id, sizeof(card->id), "%s_%d", c->id, n);
+ }
+ }
+
is_audigy = emu->audigy = c->emu10k2_chip;
/* set the DMA transfer mask */
@@ -816,15 +971,6 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
pci_set_master(pci);
- if (c->ecard) {
- emu->card_type = EMU10K1_CARD_EMUAPS;
- emu->APS = 1;
- }
- if (! c->ac97_chip)
- emu->no_ac97 = 1;
-
- emu->spk71 = c->spk71;
-
emu->fx8010.fxbus_mask = 0x303f;
if (extin_mask == 0)
extin_mask = 0x3fcf;
@@ -833,7 +979,7 @@ int __devinit snd_emu10k1_create(snd_card_t * card,
emu->fx8010.extin_mask = extin_mask;
emu->fx8010.extout_mask = extout_mask;
- if (emu->APS) {
+ if (emu->card_capabilities->ecard) {
if ((err = snd_emu10k1_ecard_init(emu)) < 0) {
snd_emu10k1_free(emu);
return err;
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 27dfd8ddddf..e90c5ddd1d1 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -361,10 +361,7 @@ static void snd_emu10k1x_gpio_write(emu10k1x_t *emu, unsigned int value)
static void snd_emu10k1x_pcm_free_substream(snd_pcm_runtime_t *runtime)
{
- emu10k1x_pcm_t *epcm = runtime->private_data;
-
- if (epcm)
- kfree(epcm);
+ kfree(runtime->private_data);
}
static void snd_emu10k1x_pcm_interrupt(emu10k1x_t *emu, emu10k1x_voice_t *voice)
@@ -1075,6 +1072,7 @@ static int __devinit snd_emu10k1x_proc_init(emu10k1x_t * emu)
snd_info_set_text_ops(entry, emu, 1024, snd_emu10k1x_proc_reg_read);
entry->c.text.write_size = 64;
entry->c.text.write = snd_emu10k1x_proc_reg_write;
+ entry->mode |= S_IWUSR;
entry->private_data = emu;
}
@@ -1627,7 +1625,7 @@ static int __init alsa_card_emu10k1x_init(void)
{
int err;
- if ((err = pci_module_init(&driver)) > 0)
+ if ((err = pci_register_driver(&driver)) > 0)
return err;
return 0;
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
index b9fa2e887fe..0529fb28112 100644
--- a/sound/pci/emu10k1/emufx.c
+++ b/sound/pci/emu10k1/emufx.c
@@ -1077,7 +1077,7 @@ static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu)
gpr += 2;
/* PCM Side Playback (independent from stereo mix) */
- if (emu->spk71) {
+ if (emu->card_capabilities->spk71) {
A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_SIDE));
A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_SIDE));
snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Side Playback Volume", gpr, 100);
@@ -1145,14 +1145,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_SPDIF_CD_L);
A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_SPDIF_CD_R);
snd_emu10k1_init_stereo_control(&controls[nctl++],
- emu->no_ac97 ? "CD Playback Volume" : "Audigy CD Playback Volume",
+ emu->card_capabilities->ac97_chip ? "Audigy CD Playback Volume" : "CD Playback Volume",
gpr, 0);
gpr += 2;
/* Audigy CD Capture Volume */
A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_SPDIF_CD_L);
A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_SPDIF_CD_R);
snd_emu10k1_init_stereo_control(&controls[nctl++],
- emu->no_ac97 ? "CD Capture Volume" : "Audigy CD Capture Volume",
+ emu->card_capabilities->ac97_chip ? "Audigy CD Capture Volume" : "CD Capture Volume",
gpr, 0);
gpr += 2;
@@ -1171,14 +1171,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_LINE2_L);
A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_LINE2_R);
snd_emu10k1_init_stereo_control(&controls[nctl++],
- emu->no_ac97 ? "Line Playback Volume" : "Line2 Playback Volume",
+ emu->card_capabilities->ac97_chip ? "Line2 Playback Volume" : "Line Playback Volume",
gpr, 0);
gpr += 2;
/* Line2 Capture Volume */
A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_LINE2_L);
A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_LINE2_R);
snd_emu10k1_init_stereo_control(&controls[nctl++],
- emu->no_ac97 ? "Line Capture Volume" : "Line2 Capture Volume",
+ emu->card_capabilities->ac97_chip ? "Line2 Capture Volume" : "Line Capture Volume",
gpr, 0);
gpr += 2;
@@ -1197,14 +1197,14 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AUX2_L);
A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_AUX2_R);
snd_emu10k1_init_stereo_control(&controls[nctl++],
- emu->no_ac97 ? "Aux Playback Volume" : "Aux2 Playback Volume",
+ emu->card_capabilities->ac97_chip ? "Aux2 Playback Volume" : "Aux Playback Volume",
gpr, 0);
gpr += 2;
/* Aux2 Capture Volume */
A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_AUX2_L);
A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_AUX2_R);
snd_emu10k1_init_stereo_control(&controls[nctl++],
- emu->no_ac97 ? "Aux Capture Volume" : "Aux2 Capture Volume",
+ emu->card_capabilities->ac97_chip ? "Aux2 Capture Volume" : "Aux Capture Volume",
gpr, 0);
gpr += 2;
@@ -1232,7 +1232,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
snd_emu10k1_init_mono_control(&controls[nctl++], "LFE Playback Volume", gpr, 0);
gpr++;
- if (emu->spk71) {
+ if (emu->card_capabilities->spk71) {
/* Stereo Mix Side Playback */
A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_GPR(playback+6), A_GPR(gpr), A_GPR(stereo_mix));
A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_GPR(playback+7), A_GPR(gpr+1), A_GPR(stereo_mix+1));
@@ -1266,7 +1266,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 3), A_GPR(playback + 3), A_C_00000000, A_C_00000000); /* rear right */
A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), A_GPR(playback + 4), A_C_00000000, A_C_00000000); /* center */
A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), A_GPR(playback + 5), A_C_00000000, A_C_00000000); /* LFE */
- if (emu->spk71) {
+ if (emu->card_capabilities->spk71) {
A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 6), A_GPR(playback + 6), A_C_00000000, A_C_00000000); /* side left */
A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 7), A_GPR(playback + 7), A_C_00000000, A_C_00000000); /* side right */
}
@@ -1359,7 +1359,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
A_PUT_STEREO_OUTPUT(A_EXTOUT_AREAR_L, A_EXTOUT_AREAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS);
A_PUT_OUTPUT(A_EXTOUT_ACENTER, playback+4 + SND_EMU10K1_PLAYBACK_CHANNELS);
A_PUT_OUTPUT(A_EXTOUT_ALFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS);
- if (emu->spk71)
+ if (emu->card_capabilities->spk71)
A_PUT_STEREO_OUTPUT(A_EXTOUT_ASIDE_L, A_EXTOUT_ASIDE_R, playback+6 + SND_EMU10K1_PLAYBACK_CHANNELS);
/* headphone */
@@ -1982,22 +1982,27 @@ static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_MIC_CAP), GPR(capture + 2), C_00000000, C_00000000);
/* EFX capture - capture the 16 EXTINS */
- OP(icode, &ptr, iACC3, FXBUS2(14), C_00000000, C_00000000, EXTIN(0));
- OP(icode, &ptr, iACC3, FXBUS2(15), C_00000000, C_00000000, EXTIN(1));
- OP(icode, &ptr, iACC3, FXBUS2(0), C_00000000, C_00000000, EXTIN(2));
- OP(icode, &ptr, iACC3, FXBUS2(3), C_00000000, C_00000000, EXTIN(3));
- /* Dont connect anything to FXBUS2 1 and 2. These are shared with
- * Center/LFE on the SBLive 5.1. The kX driver only changes the
- * routing when it detects an SBLive 5.1.
- *
- * Since only 14 of the 16 EXTINs are used, this is not a big problem.
- * We route AC97L and R to FX capture 14 and 15, SPDIF CD in to FX capture
- * 0 and 3, then the rest of the EXTINs to the corresponding FX capture
- * channel.
- */
- for (z = 4; z < 14; z++) {
- OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z));
+ if (emu->card_capabilities->sblive51) {
+ /* On the Live! 5.1, FXBUS2(1) and FXBUS(2) are shared with EXTOUT_ACENTER
+ * and EXTOUT_ALFE, so we can't connect inputs to them for multitrack recording.
+ *
+ * Since only 14 of the 16 EXTINs are used, this is not a big problem.
+ * We route AC97L and R to FX capture 14 and 15, SPDIF CD in to FX capture
+ * 0 and 3, then the rest of the EXTINs to the corresponding FX capture
+ * channel. Multitrack recorders will still see the center/lfe output signal
+ * on the second and third channels.
+ */
+ OP(icode, &ptr, iACC3, FXBUS2(14), C_00000000, C_00000000, EXTIN(0));
+ OP(icode, &ptr, iACC3, FXBUS2(15), C_00000000, C_00000000, EXTIN(1));
+ OP(icode, &ptr, iACC3, FXBUS2(0), C_00000000, C_00000000, EXTIN(2));
+ OP(icode, &ptr, iACC3, FXBUS2(3), C_00000000, C_00000000, EXTIN(3));
+ for (z = 4; z < 14; z++)
+ OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z));
+ } else {
+ for (z = 0; z < 16; z++)
+ OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z));
}
+
if (gpr > tmp) {
snd_BUG();
@@ -2128,7 +2133,6 @@ static int snd_emu10k1_fx8010_info(emu10k1_t *emu, emu10k1_fx8010_info_t *info)
int res;
memset(info, 0, sizeof(info));
- info->card = emu->card_type;
info->internal_tram_size = emu->fx8010.itram_size;
info->external_tram_size = emu->fx8010.etram_pages.bytes / 2;
fxbus = fxbuses;
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c
index 044663d31aa..6be82c5fe13 100644
--- a/sound/pci/emu10k1/emumixer.c
+++ b/sound/pci/emu10k1/emumixer.c
@@ -68,6 +68,7 @@ static int snd_emu10k1_spdif_get_mask(snd_kcontrol_t * kcontrol,
return 0;
}
+#if 0
static int snd_audigy_spdif_output_rate_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
static char *texts[] = {"44100", "48000", "96000"};
@@ -152,6 +153,7 @@ static snd_kcontrol_new_t snd_audigy_spdif_output_rate =
.get = snd_audigy_spdif_output_rate_get,
.put = snd_audigy_spdif_output_rate_put
};
+#endif
static int snd_emu10k1_spdif_put(snd_kcontrol_t * kcontrol,
snd_ctl_elem_value_t * ucontrol)
@@ -791,7 +793,7 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
NULL
};
- if (!emu->no_ac97) {
+ if (emu->card_capabilities->ac97_chip) {
ac97_bus_t *pbus;
ac97_template_t ac97;
static ac97_bus_ops_t ops = {
@@ -833,7 +835,7 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
for (; *c; c++)
remove_ctl(card, *c);
} else {
- if (emu->APS)
+ if (emu->card_capabilities->ecard)
strcpy(emu->card->mixername, "EMU APS");
else if (emu->audigy)
strcpy(emu->card->mixername, "SB Audigy");
@@ -918,7 +920,7 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
mix->attn[0] = 0xffff;
}
- if (! emu->APS) { /* FIXME: APS has these controls? */
+ if (! emu->card_capabilities->ecard) { /* FIXME: APS has these controls? */
/* sb live! and audigy */
if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL)
return -ENOMEM;
@@ -935,18 +937,20 @@ int __devinit snd_emu10k1_mixer(emu10k1_t *emu)
return -ENOMEM;
if ((err = snd_ctl_add(card, kctl)))
return err;
+#if 0
if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL)
return -ENOMEM;
if ((err = snd_ctl_add(card, kctl)))
return err;
- } else if (! emu->APS) {
+#endif
+ } else if (! emu->card_capabilities->ecard) {
/* sb live! */
if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL)
return -ENOMEM;
if ((err = snd_ctl_add(card, kctl)))
return err;
}
- if (emu->audigy && emu->revision == 4) { /* P16V */
+ if (emu->card_capabilities->ca0151_chip) { /* P16V */
if ((err = snd_p16v_mixer(emu)))
return err;
}
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index d1c2a02c486..520b99af5f5 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -262,7 +262,7 @@ static unsigned int emu10k1_select_interprom(unsigned int pitch_target)
*
* returns: cache invalidate size in samples
*/
-static int inline emu10k1_ccis(int stereo, int w_16)
+static inline int emu10k1_ccis(int stereo, int w_16)
{
if (w_16) {
return stereo ? 24 : 26;
@@ -991,9 +991,7 @@ static void snd_emu10k1_pcm_efx_mixer_notify(emu10k1_t *emu, int idx, int activa
static void snd_emu10k1_pcm_free_substream(snd_pcm_runtime_t *runtime)
{
- emu10k1_pcm_t *epcm = runtime->private_data;
-
- kfree(epcm);
+ kfree(runtime->private_data);
}
static int snd_emu10k1_efx_playback_close(snd_pcm_substream_t * substream)
diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c
index d990d5eb45a..cc22707c91f 100644
--- a/sound/pci/emu10k1/emuproc.c
+++ b/sound/pci/emu10k1/emuproc.c
@@ -30,6 +30,7 @@
#include <linux/init.h>
#include <sound/core.h>
#include <sound/emu10k1.h>
+#include "p16v.h"
static void snd_emu10k1_proc_spdif_status(emu10k1_t * emu,
snd_info_buffer_t * buffer,
@@ -44,28 +45,34 @@ static void snd_emu10k1_proc_spdif_status(emu10k1_t * emu,
unsigned int status, rate = 0;
status = snd_emu10k1_ptr_read(emu, status_reg, 0);
- if (rate_reg > 0)
- rate = snd_emu10k1_ptr_read(emu, rate_reg, 0);
snd_iprintf(buffer, "\n%s\n", title);
- snd_iprintf(buffer, "Professional Mode : %s\n", (status & SPCS_PROFESSIONAL) ? "yes" : "no");
- snd_iprintf(buffer, "Not Audio Data : %s\n", (status & SPCS_NOTAUDIODATA) ? "yes" : "no");
- snd_iprintf(buffer, "Copyright : %s\n", (status & SPCS_COPYRIGHT) ? "yes" : "no");
- snd_iprintf(buffer, "Emphasis : %s\n", emphasis[(status & SPCS_EMPHASISMASK) >> 3]);
- snd_iprintf(buffer, "Mode : %i\n", (status & SPCS_MODEMASK) >> 6);
- snd_iprintf(buffer, "Category Code : 0x%x\n", (status & SPCS_CATEGORYCODEMASK) >> 8);
- snd_iprintf(buffer, "Generation Status : %s\n", status & SPCS_GENERATIONSTATUS ? "original" : "copy");
- snd_iprintf(buffer, "Source Mask : %i\n", (status & SPCS_SOURCENUMMASK) >> 16);
- snd_iprintf(buffer, "Channel Number : %s\n", channel[(status & SPCS_CHANNELNUMMASK) >> 20]);
- snd_iprintf(buffer, "Sample Rate : %iHz\n", samplerate[(status & SPCS_SAMPLERATEMASK) >> 24]);
- snd_iprintf(buffer, "Clock Accuracy : %s\n", clkaccy[(status & SPCS_CLKACCYMASK) >> 28]);
-
- if (rate_reg > 0) {
- snd_iprintf(buffer, "S/PDIF Locked : %s\n", rate & SRCS_SPDIFLOCKED ? "on" : "off");
- snd_iprintf(buffer, "Rate Locked : %s\n", rate & SRCS_RATELOCKED ? "on" : "off");
- snd_iprintf(buffer, "Estimated Sample Rate : 0x%x\n", rate & SRCS_ESTSAMPLERATE);
+ if (status != 0xffffffff) {
+ snd_iprintf(buffer, "Professional Mode : %s\n", (status & SPCS_PROFESSIONAL) ? "yes" : "no");
+ snd_iprintf(buffer, "Not Audio Data : %s\n", (status & SPCS_NOTAUDIODATA) ? "yes" : "no");
+ snd_iprintf(buffer, "Copyright : %s\n", (status & SPCS_COPYRIGHT) ? "yes" : "no");
+ snd_iprintf(buffer, "Emphasis : %s\n", emphasis[(status & SPCS_EMPHASISMASK) >> 3]);
+ snd_iprintf(buffer, "Mode : %i\n", (status & SPCS_MODEMASK) >> 6);
+ snd_iprintf(buffer, "Category Code : 0x%x\n", (status & SPCS_CATEGORYCODEMASK) >> 8);
+ snd_iprintf(buffer, "Generation Status : %s\n", status & SPCS_GENERATIONSTATUS ? "original" : "copy");
+ snd_iprintf(buffer, "Source Mask : %i\n", (status & SPCS_SOURCENUMMASK) >> 16);
+ snd_iprintf(buffer, "Channel Number : %s\n", channel[(status & SPCS_CHANNELNUMMASK) >> 20]);
+ snd_iprintf(buffer, "Sample Rate : %iHz\n", samplerate[(status & SPCS_SAMPLERATEMASK) >> 24]);
+ snd_iprintf(buffer, "Clock Accuracy : %s\n", clkaccy[(status & SPCS_CLKACCYMASK) >> 28]);
+
+ if (rate_reg > 0) {
+ rate = snd_emu10k1_ptr_read(emu, rate_reg, 0);
+ snd_iprintf(buffer, "S/PDIF Valid : %s\n", rate & SRCS_SPDIFVALID ? "on" : "off");
+ snd_iprintf(buffer, "S/PDIF Locked : %s\n", rate & SRCS_SPDIFLOCKED ? "on" : "off");
+ snd_iprintf(buffer, "Rate Locked : %s\n", rate & SRCS_RATELOCKED ? "on" : "off");
+ /* From ((Rate * 48000 ) / 262144); */
+ snd_iprintf(buffer, "Estimated Sample Rate : %d\n", ((rate & 0xFFFFF ) * 375) >> 11);
+ }
+ } else {
+ snd_iprintf(buffer, "No signal detected.\n");
}
+
}
static void snd_emu10k1_proc_read(snd_info_entry_t *entry,
@@ -182,7 +189,7 @@ static void snd_emu10k1_proc_read(snd_info_entry_t *entry,
snd_iprintf(buffer, "EMU10K1\n\n");
snd_iprintf(buffer, "Card : %s\n",
- emu->audigy ? "Audigy" : (emu->APS ? "EMU APS" : "Creative"));
+ emu->audigy ? "Audigy" : (emu->card_capabilities->ecard ? "EMU APS" : "Creative"));
snd_iprintf(buffer, "Internal TRAM (words) : 0x%x\n", emu->fx8010.itram_size);
snd_iprintf(buffer, "External TRAM (words) : 0x%x\n", (int)emu->fx8010.etram_pages.bytes / 2);
snd_iprintf(buffer, "\n");
@@ -223,15 +230,35 @@ static void snd_emu10k1_proc_read(snd_info_entry_t *entry,
snd_iprintf(buffer, "\nAll FX Outputs :\n");
for (idx = 0; idx < (emu->audigy ? 64 : 32); idx++)
snd_iprintf(buffer, " Output %02i [%s]\n", idx, outputs[idx]);
- snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 0", SPCS0, -1);
- snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 1", SPCS1, -1);
- snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 2/3", SPCS2, -1);
- snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF", CDCS, CDSRCS);
- snd_emu10k1_proc_spdif_status(emu, buffer, "General purpose S/PDIF", GPSCS, GPSRCS);
+}
+
+static void snd_emu10k1_proc_spdif_read(snd_info_entry_t *entry,
+ snd_info_buffer_t * buffer)
+{
+ emu10k1_t *emu = entry->private_data;
+ snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF In", CDCS, CDSRCS);
+ snd_emu10k1_proc_spdif_status(emu, buffer, "Optical or Coax S/PDIF In", GPSCS, GPSRCS);
+#if 0
val = snd_emu10k1_ptr_read(emu, ZVSRCS, 0);
snd_iprintf(buffer, "\nZoomed Video\n");
snd_iprintf(buffer, "Rate Locked : %s\n", val & SRCS_RATELOCKED ? "on" : "off");
snd_iprintf(buffer, "Estimated Sample Rate : 0x%x\n", val & SRCS_ESTSAMPLERATE);
+#endif
+}
+
+static void snd_emu10k1_proc_rates_read(snd_info_entry_t *entry,
+ snd_info_buffer_t * buffer)
+{
+ static int samplerate[8] = { 44100, 48000, 96000, 192000, 4, 5, 6, 7 };
+ emu10k1_t *emu = entry->private_data;
+ unsigned int val, tmp, n;
+ val = snd_emu10k1_ptr20_read(emu, CAPTURE_RATE_STATUS, 0);
+ tmp = (val >> 16) & 0x8;
+ for (n=0;n<4;n++) {
+ tmp = val >> (16 + (n*4));
+ if (tmp & 0x8) snd_iprintf(buffer, "Channel %d: Rate=%d\n", n, samplerate[tmp & 0x7]);
+ else snd_iprintf(buffer, "Channel %d: No input\n", n);
+ }
}
static void snd_emu10k1_proc_acode_read(snd_info_entry_t *entry,
@@ -500,32 +527,46 @@ int __devinit snd_emu10k1_proc_init(emu10k1_t * emu)
snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_io_reg_read);
entry->c.text.write_size = 64;
entry->c.text.write = snd_emu_proc_io_reg_write;
+ entry->mode |= S_IWUSR;
}
if (! snd_card_proc_new(emu->card, "ptr_regs00a", &entry)) {
snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read00a);
entry->c.text.write_size = 64;
entry->c.text.write = snd_emu_proc_ptr_reg_write00;
+ entry->mode |= S_IWUSR;
}
if (! snd_card_proc_new(emu->card, "ptr_regs00b", &entry)) {
snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read00b);
entry->c.text.write_size = 64;
entry->c.text.write = snd_emu_proc_ptr_reg_write00;
+ entry->mode |= S_IWUSR;
}
if (! snd_card_proc_new(emu->card, "ptr_regs20a", &entry)) {
snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20a);
entry->c.text.write_size = 64;
entry->c.text.write = snd_emu_proc_ptr_reg_write20;
+ entry->mode |= S_IWUSR;
}
if (! snd_card_proc_new(emu->card, "ptr_regs20b", &entry)) {
snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20b);
entry->c.text.write_size = 64;
entry->c.text.write = snd_emu_proc_ptr_reg_write20;
+ entry->mode |= S_IWUSR;
}
#endif
if (! snd_card_proc_new(emu->card, "emu10k1", &entry))
snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_read);
+ if (emu->card_capabilities->emu10k2_chip) {
+ if (! snd_card_proc_new(emu->card, "spdif-in", &entry))
+ snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_spdif_read);
+ }
+ if (emu->card_capabilities->ca0151_chip) {
+ if (! snd_card_proc_new(emu->card, "capture-rates", &entry))
+ snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_rates_read);
+ }
+
if (! snd_card_proc_new(emu->card, "voices", &entry))
snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_voices_read);
diff --git a/sound/pci/emu10k1/irq.c b/sound/pci/emu10k1/irq.c
index b81a7cafff3..cd8460d5675 100644
--- a/sound/pci/emu10k1/irq.c
+++ b/sound/pci/emu10k1/irq.c
@@ -37,7 +37,7 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
int handled = 0;
while ((status = inl(emu->port + IPR)) != 0) {
- // printk("irq - status = 0x%x\n", status);
+ //printk("emu10k1 irq - status = 0x%x\n", status);
orig_status = status;
handled = 1;
if (status & IPR_PCIERROR) {
@@ -147,9 +147,36 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
snd_emu10k1_intr_disable(emu, INTE_FXDSPENABLE);
status &= ~IPR_FXDSP;
}
+ if (status & IPR_P16V) {
+ while ((status2 = inl(emu->port + IPR2)) != 0) {
+ u32 mask = INTE2_PLAYBACK_CH_0_LOOP; /* Full Loop */
+ emu10k1_voice_t *pvoice = &(emu->p16v_voices[0]);
+ emu10k1_voice_t *cvoice = &(emu->p16v_capture_voice);
+
+ //printk(KERN_INFO "status2=0x%x\n", status2);
+ orig_status2 = status2;
+ if(status2 & mask) {
+ if(pvoice->use) {
+ snd_pcm_period_elapsed(pvoice->epcm->substream);
+ } else {
+ snd_printk(KERN_ERR "p16v: status: 0x%08x, mask=0x%08x, pvoice=%p, use=%d\n", status2, mask, pvoice, pvoice->use);
+ }
+ }
+ if(status2 & 0x110000) {
+ //printk(KERN_INFO "capture int found\n");
+ if(cvoice->use) {
+ //printk(KERN_INFO "capture period_elapsed\n");
+ snd_pcm_period_elapsed(cvoice->epcm->substream);
+ }
+ }
+ outl(orig_status2, emu->port + IPR2); /* ack all */
+ }
+ status &= ~IPR_P16V;
+ }
+
if (status) {
unsigned int bits;
- //snd_printk(KERN_ERR "emu10k1: unhandled interrupt: 0x%08x\n", status);
+ snd_printk(KERN_ERR "emu10k1: unhandled interrupt: 0x%08x\n", status);
//make sure any interrupts we don't handle are disabled:
bits = INTE_FXDSPENABLE |
INTE_PCIERRORENABLE |
@@ -170,20 +197,5 @@ irqreturn_t snd_emu10k1_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
outl(orig_status, emu->port + IPR); /* ack all */
}
- if (emu->audigy && emu->revision == 4) { /* P16V */
- while ((status2 = inl(emu->port + IPR2)) != 0) {
- u32 mask = INTE2_PLAYBACK_CH_0_LOOP; /* Full Loop */
- emu10k1_voice_t *pvoice = &(emu->p16v_voices[0]);
- orig_status2 = status2;
- if(status2 & mask) {
- if(pvoice->use) {
- snd_pcm_period_elapsed(pvoice->epcm->substream);
- } else {
- snd_printk(KERN_ERR "p16v: status: 0x%08x, mask=0x%08x, pvoice=%p, use=%d\n", status2, mask, pvoice, pvoice->use);
- }
- }
- outl(orig_status2, emu->port + IPR2); /* ack all */
- }
- }
return IRQ_RETVAL(handled);
}
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c
index d03cb2fefc9..98f98018989 100644
--- a/sound/pci/emu10k1/p16v.c
+++ b/sound/pci/emu10k1/p16v.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk>
* Driver p16v chips
- * Version: 0.22
+ * Version: 0.25
*
* FEATURES currently supported:
* Output fixed at S32_LE, 2 channel to hw:0,0
@@ -41,7 +41,15 @@
* Integrated with snd-emu10k1 driver.
* 0.22
* Removed #if 0 ... #endif
- *
+ * 0.23
+ * Implement different capture rates.
+ * 0.24
+ * Implement different capture source channels.
+ * e.g. When HD Capture source is set to SPDIF,
+ * setting HD Capture channel to 0 captures from CDROM digital input.
+ * setting HD Capture channel to 1 captures from SPDIF in.
+ * 0.25
+ * Include capture buffer sizes.
*
* BUGS:
* Some stability problems when unloading the snd-p16v kernel module.
@@ -119,22 +127,41 @@ static snd_pcm_hardware_t snd_p16v_playback_hw = {
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID),
.formats = SNDRV_PCM_FMTBIT_S32_LE, /* Only supports 24-bit samples padded to 32 bits. */
- .rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 ,
- .rate_min = 48000,
+ .rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100,
+ .rate_min = 44100,
.rate_max = 192000,
.channels_min = 8,
.channels_max = 8,
- .buffer_bytes_max = (32*1024),
+ .buffer_bytes_max = ((65536 - 64) * 8),
.period_bytes_min = 64,
- .period_bytes_max = (16*1024),
+ .period_bytes_max = (65536 - 64),
.periods_min = 2,
.periods_max = 8,
.fifo_size = 0,
};
+static snd_pcm_hardware_t snd_p16v_capture_hw = {
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID),
+ .formats = SNDRV_PCM_FMTBIT_S32_LE,
+ .rates = SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100,
+ .rate_min = 44100,
+ .rate_max = 192000,
+ .channels_min = 2,
+ .channels_max = 2,
+ .buffer_bytes_max = (65536 - 64),
+ .period_bytes_min = 64,
+ .period_bytes_max = (65536 - 128) >> 1, /* size has to be N*64 bytes */
+ .periods_min = 2,
+ .periods_max = 2,
+ .fifo_size = 0,
+};
+
static void snd_p16v_pcm_free_substream(snd_pcm_runtime_t *runtime)
{
- snd_pcm_t *epcm = runtime->private_data;
+ emu10k1_pcm_t *epcm = runtime->private_data;
if (epcm) {
//snd_printk("epcm free: %p\n", epcm);
@@ -178,15 +205,63 @@ static int snd_p16v_pcm_open_playback_channel(snd_pcm_substream_t *substream, in
return 0;
}
+/* open_capture callback */
+static int snd_p16v_pcm_open_capture_channel(snd_pcm_substream_t *substream, int channel_id)
+{
+ emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ emu10k1_voice_t *channel = &(emu->p16v_capture_voice);
+ emu10k1_pcm_t *epcm;
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ int err;
+
+ epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+ //snd_printk("epcm kcalloc: %p\n", epcm);
+
+ if (epcm == NULL)
+ return -ENOMEM;
+ epcm->emu = emu;
+ epcm->substream = substream;
+ //snd_printk("epcm device=%d, channel_id=%d\n", substream->pcm->device, channel_id);
+
+ runtime->private_data = epcm;
+ runtime->private_free = snd_p16v_pcm_free_substream;
+
+ runtime->hw = snd_p16v_capture_hw;
+
+ channel->emu = emu;
+ channel->number = channel_id;
+
+ channel->use=1;
+ //snd_printk("p16v: open channel_id=%d, channel=%p, use=0x%x\n", channel_id, channel, channel->use);
+ //printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
+ //channel->interrupt = snd_p16v_pcm_channel_interrupt;
+ channel->epcm=epcm;
+ if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
+ return err;
+
+ return 0;
+}
+
/* close callback */
static int snd_p16v_pcm_close_playback(snd_pcm_substream_t *substream)
{
emu10k1_t *emu = snd_pcm_substream_chip(substream);
//snd_pcm_runtime_t *runtime = substream->runtime;
- //emu10k1_pcm_t *epcm = runtime->private_data;
- emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use=0;
-/* FIXME: maybe zero others */
+ //emu10k1_pcm_t *epcm = runtime->private_data;
+ emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use=0;
+ /* FIXME: maybe zero others */
+ return 0;
+}
+
+/* close callback */
+static int snd_p16v_pcm_close_capture(snd_pcm_substream_t *substream)
+{
+ emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ //snd_pcm_runtime_t *runtime = substream->runtime;
+ //emu10k1_pcm_t *epcm = runtime->private_data;
+ emu->p16v_capture_voice.use=0;
+ /* FIXME: maybe zero others */
return 0;
}
@@ -195,36 +270,55 @@ static int snd_p16v_pcm_open_playback_front(snd_pcm_substream_t *substream)
return snd_p16v_pcm_open_playback_channel(substream, PCM_FRONT_CHANNEL);
}
+static int snd_p16v_pcm_open_capture(snd_pcm_substream_t *substream)
+{
+ // Only using channel 0 for now, but the card has 2 channels.
+ return snd_p16v_pcm_open_capture_channel(substream, 0);
+}
+
/* hw_params callback */
static int snd_p16v_pcm_hw_params_playback(snd_pcm_substream_t *substream,
snd_pcm_hw_params_t * hw_params)
{
int result;
- //snd_printk("hw_params alloc: substream=%p\n", substream);
result = snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(hw_params));
- //snd_printk("hw_params alloc: result=%d\n", result);
- //dump_stack();
return result;
}
+/* hw_params callback */
+static int snd_p16v_pcm_hw_params_capture(snd_pcm_substream_t *substream,
+ snd_pcm_hw_params_t * hw_params)
+{
+ int result;
+ result = snd_pcm_lib_malloc_pages(substream,
+ params_buffer_bytes(hw_params));
+ return result;
+}
+
+
/* hw_free callback */
static int snd_p16v_pcm_hw_free_playback(snd_pcm_substream_t *substream)
{
int result;
- //snd_printk("hw_params free: substream=%p\n", substream);
result = snd_pcm_lib_free_pages(substream);
- //snd_printk("hw_params free: result=%d\n", result);
- //dump_stack();
return result;
}
+/* hw_free callback */
+static int snd_p16v_pcm_hw_free_capture(snd_pcm_substream_t *substream)
+{
+ int result;
+ result = snd_pcm_lib_free_pages(substream);
+ return result;
+}
+
+
/* prepare playback callback */
static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream)
{
emu10k1_t *emu = snd_pcm_substream_chip(substream);
snd_pcm_runtime_t *runtime = substream->runtime;
- //emu10k1_pcm_t *epcm = runtime->private_data;
int channel = substream->pcm->device - emu->p16v_device_offset;
u32 *table_base = (u32 *)(emu->p16v_buffer.area+(8*16*channel));
u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
@@ -237,23 +331,21 @@ static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream)
tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
switch (runtime->rate) {
case 44100:
- snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x8000); /* FIXME: This will change the capture rate as well! */
- break;
- case 48000:
- snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x0000); /* FIXME: This will change the capture rate as well! */
+ snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x8080);
break;
case 96000:
- snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x4000); /* FIXME: This will change the capture rate as well! */
+ snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x4040);
break;
case 192000:
- snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x2000); /* FIXME: This will change the capture rate as well! */
+ snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x2020);
break;
+ case 48000:
default:
- snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, 0x0000); /* FIXME: This will change the capture rate as well! */
+ snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x0000);
break;
}
/* FIXME: Check emu->buffer.size before actually writing to it. */
- for(i=0; i < runtime->periods; i++) {
+ for(i=0; i < runtime->periods; i++) {
table_base[i*2]=runtime->dma_addr+(i*period_size_bytes);
table_base[(i*2)+1]=period_size_bytes<<16;
}
@@ -262,7 +354,8 @@ static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream)
snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_PTR, channel, 0);
snd_emu10k1_ptr20_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
- snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes
+ //snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes
+ snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, 0); // buffer size in bytes
snd_emu10k1_ptr20_write(emu, PLAYBACK_POINTER, channel, 0);
snd_emu10k1_ptr20_write(emu, 0x07, channel, 0x0);
snd_emu10k1_ptr20_write(emu, 0x08, channel, 0);
@@ -270,6 +363,41 @@ static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream)
return 0;
}
+/* prepare capture callback */
+static int snd_p16v_pcm_prepare_capture(snd_pcm_substream_t *substream)
+{
+ emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ int channel = substream->pcm->device - emu->p16v_device_offset;
+ u32 tmp;
+ //printk("prepare capture:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, frames_to_bytes(runtime, 1));
+ tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
+ switch (runtime->rate) {
+ case 44100:
+ snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0800);
+ break;
+ case 96000:
+ snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0400);
+ break;
+ case 192000:
+ snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0200);
+ break;
+ case 48000:
+ default:
+ snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0000);
+ break;
+ }
+ /* FIXME: Check emu->buffer.size before actually writing to it. */
+ snd_emu10k1_ptr20_write(emu, 0x13, channel, 0);
+ snd_emu10k1_ptr20_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr);
+ snd_emu10k1_ptr20_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes
+ snd_emu10k1_ptr20_write(emu, CAPTURE_POINTER, channel, 0);
+ //snd_emu10k1_ptr20_write(emu, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC or Line in */
+ //snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) | (0x110000<<channel));
+
+ return 0;
+}
+
static void snd_p16v_intr_enable(emu10k1_t *emu, unsigned int intrenb)
{
unsigned long flags;
@@ -345,6 +473,36 @@ static int snd_p16v_pcm_trigger_playback(snd_pcm_substream_t *substream,
return result;
}
+/* trigger_capture callback */
+static int snd_p16v_pcm_trigger_capture(snd_pcm_substream_t *substream,
+ int cmd)
+{
+ emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ emu10k1_pcm_t *epcm = runtime->private_data;
+ int channel = 0;
+ int result = 0;
+ u32 inte = INTE2_CAPTURE_CH_0_LOOP | INTE2_CAPTURE_CH_0_HALF_LOOP;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ snd_p16v_intr_enable(emu, inte);
+ snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0)|(0x100<<channel));
+ epcm->running = 1;
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & ~(0x100<<channel));
+ snd_p16v_intr_disable(emu, inte);
+ //snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) & ~(0x110000<<channel));
+ epcm->running = 0;
+ break;
+ default:
+ result = -EINVAL;
+ break;
+ }
+ return result;
+}
+
/* pointer_playback callback */
static snd_pcm_uframes_t
snd_p16v_pcm_pointer_playback(snd_pcm_substream_t *substream)
@@ -370,6 +528,31 @@ snd_p16v_pcm_pointer_playback(snd_pcm_substream_t *substream)
return ptr;
}
+/* pointer_capture callback */
+static snd_pcm_uframes_t
+snd_p16v_pcm_pointer_capture(snd_pcm_substream_t *substream)
+{
+ emu10k1_t *emu = snd_pcm_substream_chip(substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ emu10k1_pcm_t *epcm = runtime->private_data;
+ snd_pcm_uframes_t ptr, ptr1, ptr2 = 0;
+ int channel = 0;
+
+ if (!epcm->running)
+ return 0;
+
+ ptr1 = snd_emu10k1_ptr20_read(emu, CAPTURE_POINTER, channel);
+ ptr2 = bytes_to_frames(runtime, ptr1);
+ ptr=ptr2;
+ if (ptr >= runtime->buffer_size) {
+ ptr -= runtime->buffer_size;
+ printk("buffer capture limited!\n");
+ }
+ //printk("ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", ptr1, ptr2, ptr, (int)runtime->buffer_size, (int)runtime->period_size, (int)runtime->frame_bits, (int)runtime->rate);
+
+ return ptr;
+}
+
/* operators */
static snd_pcm_ops_t snd_p16v_playback_front_ops = {
.open = snd_p16v_pcm_open_playback_front,
@@ -382,6 +565,18 @@ static snd_pcm_ops_t snd_p16v_playback_front_ops = {
.pointer = snd_p16v_pcm_pointer_playback,
};
+static snd_pcm_ops_t snd_p16v_capture_ops = {
+ .open = snd_p16v_pcm_open_capture,
+ .close = snd_p16v_pcm_close_capture,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_p16v_pcm_hw_params_capture,
+ .hw_free = snd_p16v_pcm_hw_free_capture,
+ .prepare = snd_p16v_pcm_prepare_capture,
+ .trigger = snd_p16v_pcm_trigger_capture,
+ .pointer = snd_p16v_pcm_pointer_capture,
+};
+
+
int snd_p16v_free(emu10k1_t *chip)
{
// release the data
@@ -405,20 +600,22 @@ int snd_p16v_pcm(emu10k1_t *emu, int device, snd_pcm_t **rpcm)
snd_pcm_t *pcm;
snd_pcm_substream_t *substream;
int err;
- int capture=0;
+ int capture=1;
//snd_printk("snd_p16v_pcm called. device=%d\n", device);
emu->p16v_device_offset = device;
if (rpcm)
*rpcm = NULL;
- //if (device == 0) capture=1;
+
if ((err = snd_pcm_new(emu->card, "p16v", device, 1, capture, &pcm)) < 0)
return err;
pcm->private_data = emu;
pcm->private_free = snd_p16v_pcm_free;
-
+ // Single playback 8 channel device.
+ // Single capture 2 channel device.
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_p16v_playback_front_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_p16v_capture_ops);
pcm->info_flags = 0;
pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
@@ -431,7 +628,7 @@ int snd_p16v_pcm(emu10k1_t *emu, int device, snd_pcm_t **rpcm)
if ((err = snd_pcm_lib_preallocate_pages(substream,
SNDRV_DMA_TYPE_DEV,
snd_dma_pci_data(emu->pci),
- 64*1024, 64*1024)) < 0) /* FIXME: 32*1024 for sound buffer, between 32and64 for Periods table. */
+ ((65536 - 64) * 8), ((65536 - 64) * 8))) < 0)
return err;
//snd_printk("preallocate playback substream: err=%d\n", err);
}
@@ -442,7 +639,7 @@ int snd_p16v_pcm(emu10k1_t *emu, int device, snd_pcm_t **rpcm)
if ((err = snd_pcm_lib_preallocate_pages(substream,
SNDRV_DMA_TYPE_DEV,
snd_dma_pci_data(emu->pci),
- 64*1024, 64*1024)) < 0)
+ 65536 - 64, 65536 - 64)) < 0)
return err;
//snd_printk("preallocate capture substream: err=%d\n", err);
}
@@ -694,6 +891,106 @@ static snd_kcontrol_new_t snd_p16v_volume_control_spdif_rear =
.put = snd_p16v_volume_put_spdif_rear
};
+static int snd_p16v_capture_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+ static char *texts[8] = { "SPDIF", "I2S", "SRC48", "SRCMulti_SPDIF", "SRCMulti_I2S", "CDIF", "FX", "AC97" };
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 8;
+ if (uinfo->value.enumerated.item > 7)
+ uinfo->value.enumerated.item = 7;
+ strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int snd_p16v_capture_source_get(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.enumerated.item[0] = emu->p16v_capture_source;
+ return 0;
+}
+
+static int snd_p16v_capture_source_put(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ unsigned int val;
+ int change = 0;
+ u32 mask;
+ u32 source;
+
+ val = ucontrol->value.enumerated.item[0] ;
+ change = (emu->p16v_capture_source != val);
+ if (change) {
+ emu->p16v_capture_source = val;
+ source = (val << 28) | (val << 24) | (val << 20) | (val << 16);
+ mask = snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & 0xffff;
+ snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, source | mask);
+ }
+ return change;
+}
+
+static snd_kcontrol_new_t snd_p16v_capture_source __devinitdata =
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "HD Capture source",
+ .info = snd_p16v_capture_source_info,
+ .get = snd_p16v_capture_source_get,
+ .put = snd_p16v_capture_source_put
+};
+
+static int snd_p16v_capture_channel_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+ static char *texts[4] = { "0", "1", "2", "3", };
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 4;
+ if (uinfo->value.enumerated.item > 3)
+ uinfo->value.enumerated.item = 3;
+ strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int snd_p16v_capture_channel_get(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.enumerated.item[0] = emu->p16v_capture_channel;
+ return 0;
+}
+
+static int snd_p16v_capture_channel_put(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+ unsigned int val;
+ int change = 0;
+ u32 tmp;
+
+ val = ucontrol->value.enumerated.item[0] ;
+ change = (emu->p16v_capture_channel != val);
+ if (change) {
+ emu->p16v_capture_channel = val;
+ tmp = snd_emu10k1_ptr20_read(emu, CAPTURE_P16V_SOURCE, 0) & 0xfffc;
+ snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, tmp | val);
+ }
+ return change;
+}
+
+static snd_kcontrol_new_t snd_p16v_capture_channel __devinitdata =
+{
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "HD Capture channel",
+ .info = snd_p16v_capture_channel_info,
+ .get = snd_p16v_capture_channel_get,
+ .put = snd_p16v_capture_channel_put
+};
+
int snd_p16v_mixer(emu10k1_t *emu)
{
int err;
@@ -731,6 +1028,14 @@ int snd_p16v_mixer(emu10k1_t *emu)
return -ENOMEM;
if ((err = snd_ctl_add(card, kctl)))
return err;
+ if ((kctl = snd_ctl_new1(&snd_p16v_capture_source, emu)) == NULL)
+ return -ENOMEM;
+ if ((err = snd_ctl_add(card, kctl)))
+ return err;
+ if ((kctl = snd_ctl_new1(&snd_p16v_capture_channel, emu)) == NULL)
+ return -ENOMEM;
+ if ((err = snd_ctl_add(card, kctl)))
+ return err;
return 0;
}
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index f910399db5c..4e63498a58b 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -2401,7 +2401,7 @@ static struct pci_driver driver = {
static int __init alsa_card_ens137x_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_ens137x_exit(void)
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index b4ca8adf393..b492777bc30 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -1761,7 +1761,7 @@ static struct pci_driver driver = {
static int __init alsa_card_es1938_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_es1938_exit(void)
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index faf63ff19c4..ea889b31139 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -2559,6 +2559,7 @@ static struct ess_device_list pm_whitelist[] __devinitdata = {
{ TYPE_MAESTRO2E, 0x103c },
{ TYPE_MAESTRO2E, 0x1179 },
{ TYPE_MAESTRO2E, 0x14c0 }, /* HP omnibook 4150 */
+ { TYPE_MAESTRO2E, 0x1558 },
};
static struct ess_device_list mpu_blacklist[] __devinitdata = {
@@ -2795,7 +2796,7 @@ static struct pci_driver driver = {
static int __init alsa_card_es1968_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_es1968_exit(void)
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index 08e7c5a296d..ff10e637a95 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -195,6 +195,7 @@ struct _snd_fm801 {
static struct pci_device_id snd_fm801_ids[] = {
{ 0x1319, 0x0801, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* FM801 */
+ { 0x5213, 0x0510, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* Gallant Odyssey Sound 4 */
{ 0, }
};
@@ -1468,7 +1469,7 @@ static struct pci_driver driver = {
static int __init alsa_card_fm801_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_fm801_exit(void)
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index 570a59d33b4..bd8cb33c4fb 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -1,5 +1,5 @@
snd-hda-intel-objs := hda_intel.o
-snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o
+snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o patch_sigmatel.o
ifdef CONFIG_PROC_FS
snd-hda-codec-objs += hda_proc.o
endif
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 9ed117ac0c0..e2cf0238728 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -49,8 +49,10 @@ struct hda_vendor_id {
/* codec vendor labels */
static struct hda_vendor_id hda_vendor_ids[] = {
{ 0x10ec, "Realtek" },
+ { 0x11d4, "Analog Devices" },
{ 0x13f6, "C-Media" },
{ 0x434d, "C-Media" },
+ { 0x8384, "SigmaTel" },
{} /* terminator */
};
@@ -508,7 +510,7 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
/* FIXME: support for multiple AFGs? */
codec->afg = look_for_afg_node(codec);
if (! codec->afg) {
- snd_printk(KERN_ERR "hda_codec: no AFG node found\n");
+ snd_printdd("hda_codec: no AFG node found\n");
snd_hda_codec_free(codec);
return -ENODEV;
}
@@ -548,6 +550,9 @@ int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stream_tag,
int channel_id, int format)
{
+ if (! nid)
+ return;
+
snd_printdd("hda_codec_setup_stream: NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
nid, stream_tag, channel_id, format);
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
@@ -561,9 +566,10 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stre
* amp access functions
*/
-#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + (idx) * 32 + (dir) * 64)
+/* FIXME: more better hash key? */
+#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
#define INFO_AMP_CAPS (1<<0)
-#define INFO_AMP_VOL (1<<1)
+#define INFO_AMP_VOL(ch) (1 << (1 + (ch)))
/* initialize the hash table */
static void init_amp_hash(struct hda_codec *codec)
@@ -622,28 +628,29 @@ static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
/*
* read the current volume to info
- * if the cache exists, read from the cache.
+ * if the cache exists, read the cache value.
*/
-static void get_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
+static unsigned int get_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
hda_nid_t nid, int ch, int direction, int index)
{
u32 val, parm;
- if (info->status & (INFO_AMP_VOL << ch))
- return;
+ if (info->status & INFO_AMP_VOL(ch))
+ return info->vol[ch];
parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
parm |= index;
val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, parm);
info->vol[ch] = val & 0xff;
- info->status |= INFO_AMP_VOL << ch;
+ info->status |= INFO_AMP_VOL(ch);
+ return info->vol[ch];
}
/*
- * write the current volume in info to the h/w
+ * write the current volume in info to the h/w and update the cache
*/
-static void put_vol_mute(struct hda_codec *codec,
+static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
hda_nid_t nid, int ch, int direction, int index, int val)
{
u32 parm;
@@ -653,30 +660,34 @@ static void put_vol_mute(struct hda_codec *codec,
parm |= index << AC_AMP_SET_INDEX_SHIFT;
parm |= val;
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
+ info->vol[ch] = val;
}
/*
- * read/write AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
+ * read AMP value. The volume is between 0 to 0x7f, 0x80 = mute bit.
*/
-int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int index)
+static int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int index)
{
struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
if (! info)
return 0;
- get_vol_mute(codec, info, nid, ch, direction, index);
- return info->vol[ch];
+ return get_vol_mute(codec, info, nid, ch, direction, index);
}
-int snd_hda_codec_amp_write(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int idx, int val)
+/*
+ * update the AMP value, mask = bit mask to set, val = the value
+ */
+static int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int idx, int mask, int val)
{
struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
+
if (! info)
return 0;
- get_vol_mute(codec, info, nid, ch, direction, idx);
+ val &= mask;
+ val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
if (info->vol[ch] == val && ! codec->in_resume)
return 0;
- put_vol_mute(codec, nid, ch, direction, idx, val);
- info->vol[ch] = val;
+ put_vol_mute(codec, info, nid, ch, direction, idx, val);
return 1;
}
@@ -735,21 +746,15 @@ int snd_hda_mixer_amp_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
int chs = get_amp_channels(kcontrol);
int dir = get_amp_direction(kcontrol);
int idx = get_amp_index(kcontrol);
- int val;
long *valp = ucontrol->value.integer.value;
int change = 0;
- if (chs & 1) {
- val = *valp & 0x7f;
- val |= snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x80;
- change = snd_hda_codec_amp_write(codec, nid, 0, dir, idx, val);
- valp++;
- }
- if (chs & 2) {
- val = *valp & 0x7f;
- val |= snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x80;
- change |= snd_hda_codec_amp_write(codec, nid, 1, dir, idx, val);
- }
+ if (chs & 1)
+ change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
+ 0x7f, *valp);
+ if (chs & 2)
+ change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
+ 0x7f, valp[1]);
return change;
}
@@ -788,21 +793,15 @@ int snd_hda_mixer_amp_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
int chs = get_amp_channels(kcontrol);
int dir = get_amp_direction(kcontrol);
int idx = get_amp_index(kcontrol);
- int val;
long *valp = ucontrol->value.integer.value;
int change = 0;
- if (chs & 1) {
- val = snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x7f;
- val |= *valp ? 0 : 0x80;
- change = snd_hda_codec_amp_write(codec, nid, 0, dir, idx, val);
- valp++;
- }
- if (chs & 2) {
- val = snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x7f;
- val |= *valp ? 0 : 0x80;
- change = snd_hda_codec_amp_write(codec, nid, 1, dir, idx, val);
- }
+ if (chs & 1)
+ change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
+ 0x80, *valp ? 0 : 0x80);
+ if (chs & 2)
+ change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
+ 0x80, valp[1] ? 0 : 0x80);
return change;
}
@@ -1448,10 +1447,6 @@ static int set_pcm_default_values(struct hda_codec *codec, struct hda_pcm_stream
snd_assert(info->nid, return -EINVAL);
info->ops.prepare = hda_pcm_default_prepare;
}
- if (info->ops.prepare == NULL) {
- snd_assert(info->nid, return -EINVAL);
- info->ops.prepare = hda_pcm_default_prepare;
- }
if (info->ops.cleanup == NULL) {
snd_assert(info->nid, return -EINVAL);
info->ops.cleanup = hda_pcm_default_cleanup;
@@ -1525,12 +1520,12 @@ int snd_hda_build_pcms(struct hda_bus *bus)
*
* If no entries are matching, the function returns a negative value.
*/
-int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config *tbl)
+int snd_hda_check_board_config(struct hda_codec *codec, const struct hda_board_config *tbl)
{
- struct hda_board_config *c;
+ const struct hda_board_config *c;
if (codec->bus->modelname) {
- for (c = tbl; c->modelname || c->pci_vendor; c++) {
+ for (c = tbl; c->modelname || c->pci_subvendor; c++) {
if (c->modelname &&
! strcmp(codec->bus->modelname, c->modelname)) {
snd_printd(KERN_INFO "hda_codec: model '%s' is selected\n", c->modelname);
@@ -1543,9 +1538,10 @@ int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config
u16 subsystem_vendor, subsystem_device;
pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_ID, &subsystem_device);
- for (c = tbl; c->modelname || c->pci_vendor; c++) {
- if (c->pci_vendor == subsystem_vendor &&
- c->pci_device == subsystem_device)
+ for (c = tbl; c->modelname || c->pci_subvendor; c++) {
+ if (c->pci_subvendor == subsystem_vendor &&
+ (! c->pci_subdevice /* all match */||
+ (c->pci_subdevice == subsystem_device)))
return c->config;
}
}
@@ -1687,11 +1683,12 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o
snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format);
/* surrounds */
for (i = 1; i < mout->num_dacs; i++) {
- if (i == HDA_REAR && chs == 2) /* copy front to rear */
- snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0, format);
- else if (chs >= (i + 1) * 2) /* independent out */
+ if (chs >= (i + 1) * 2) /* independent out */
snd_hda_codec_setup_stream(codec, nids[i], stream_tag, i * 2,
format);
+ else /* copy front */
+ snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0,
+ format);
}
return 0;
}
@@ -1717,6 +1714,105 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_o
return 0;
}
+/*
+ * Helper for automatic ping configuration
+ */
+/* parse all pin widgets and store the useful pin nids to cfg */
+int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg)
+{
+ hda_nid_t nid, nid_start;
+ int i, j, nodes;
+ short seq, sequences[4], assoc_line_out;
+
+ memset(cfg, 0, sizeof(*cfg));
+
+ memset(sequences, 0, sizeof(sequences));
+ assoc_line_out = 0;
+
+ nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid_start);
+ for (nid = nid_start; nid < nodes + nid_start; nid++) {
+ unsigned int wid_caps = snd_hda_param_read(codec, nid,
+ AC_PAR_AUDIO_WIDGET_CAP);
+ unsigned int wid_type = (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+ unsigned int def_conf;
+ short assoc, loc;
+
+ /* read all default configuration for pin complex */
+ if (wid_type != AC_WID_PIN)
+ continue;
+ def_conf = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+ if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
+ continue;
+ loc = get_defcfg_location(def_conf);
+ switch (get_defcfg_device(def_conf)) {
+ case AC_JACK_LINE_OUT:
+ case AC_JACK_SPEAKER:
+ seq = get_defcfg_sequence(def_conf);
+ assoc = get_defcfg_association(def_conf);
+ if (! assoc)
+ continue;
+ if (! assoc_line_out)
+ assoc_line_out = assoc;
+ else if (assoc_line_out != assoc)
+ continue;
+ if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
+ continue;
+ cfg->line_out_pins[cfg->line_outs] = nid;
+ sequences[cfg->line_outs] = seq;
+ cfg->line_outs++;
+ break;
+ case AC_JACK_HP_OUT:
+ cfg->hp_pin = nid;
+ break;
+ case AC_JACK_MIC_IN:
+ if (loc == AC_JACK_LOC_FRONT)
+ cfg->input_pins[AUTO_PIN_FRONT_MIC] = nid;
+ else
+ cfg->input_pins[AUTO_PIN_MIC] = nid;
+ break;
+ case AC_JACK_LINE_IN:
+ if (loc == AC_JACK_LOC_FRONT)
+ cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
+ else
+ cfg->input_pins[AUTO_PIN_LINE] = nid;
+ break;
+ case AC_JACK_CD:
+ cfg->input_pins[AUTO_PIN_CD] = nid;
+ break;
+ case AC_JACK_AUX:
+ cfg->input_pins[AUTO_PIN_AUX] = nid;
+ break;
+ case AC_JACK_SPDIF_OUT:
+ cfg->dig_out_pin = nid;
+ break;
+ case AC_JACK_SPDIF_IN:
+ cfg->dig_in_pin = nid;
+ break;
+ }
+ }
+
+ /* sort by sequence */
+ for (i = 0; i < cfg->line_outs; i++)
+ for (j = i + 1; j < cfg->line_outs; j++)
+ if (sequences[i] > sequences[j]) {
+ seq = sequences[i];
+ sequences[i] = sequences[j];
+ sequences[j] = seq;
+ nid = cfg->line_out_pins[i];
+ cfg->line_out_pins[i] = cfg->line_out_pins[j];
+ cfg->line_out_pins[j] = nid;
+ }
+
+ /* Swap surround and CLFE: the association order is front/CLFE/surr/back */
+ if (cfg->line_outs >= 3) {
+ nid = cfg->line_out_pins[1];
+ cfg->line_out_pins[1] = cfg->line_out_pins[2];
+ cfg->line_out_pins[2] = nid;
+ }
+
+ return 0;
+}
+
#ifdef CONFIG_PM
/*
* power management
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index c9e9dc9c7c9..59991560d49 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -75,6 +75,9 @@ enum {
#define AC_VERB_GET_DIGI_CONVERT 0x0f0d
#define AC_VERB_GET_VOLUME_KNOB_CONTROL 0x0f0f
/* f10-f1a: GPIO */
+#define AC_VERB_GET_GPIO_DATA 0x0f15
+#define AC_VERB_GET_GPIO_MASK 0x0f16
+#define AC_VERB_GET_GPIO_DIRECTION 0x0f17
#define AC_VERB_GET_CONFIG_DEFAULT 0x0f1c
/*
@@ -97,6 +100,9 @@ enum {
#define AC_VERB_SET_DIGI_CONVERT_1 0x70d
#define AC_VERB_SET_DIGI_CONVERT_2 0x70e
#define AC_VERB_SET_VOLUME_KNOB_CONTROL 0x70f
+#define AC_VERB_SET_GPIO_DATA 0x715
+#define AC_VERB_SET_GPIO_MASK 0x716
+#define AC_VERB_SET_GPIO_DIRECTION 0x717
#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 0x71c
#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_1 0x71d
#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_2 0x71e
@@ -176,16 +182,15 @@ enum {
#define AC_PINCAP_OUT (1<<4) /* output capable */
#define AC_PINCAP_IN (1<<5) /* input capable */
#define AC_PINCAP_BALANCE (1<<6) /* balanced I/O capable */
-#define AC_PINCAP_VREF (7<<8)
+#define AC_PINCAP_VREF (0x37<<8)
#define AC_PINCAP_VREF_SHIFT 8
#define AC_PINCAP_EAPD (1<<16) /* EAPD capable */
-/* Vref status (used in pin cap and pin ctl) */
-#define AC_PIN_VREF_HIZ (1<<0) /* Hi-Z */
-#define AC_PIN_VREF_50 (1<<1) /* 50% */
-#define AC_PIN_VREF_GRD (1<<2) /* ground */
-#define AC_PIN_VREF_80 (1<<4) /* 80% */
-#define AC_PIN_VREF_100 (1<<5) /* 100% */
-
+/* Vref status (used in pin cap) */
+#define AC_PINCAP_VREF_HIZ (1<<0) /* Hi-Z */
+#define AC_PINCAP_VREF_50 (1<<1) /* 50% */
+#define AC_PINCAP_VREF_GRD (1<<2) /* ground */
+#define AC_PINCAP_VREF_80 (1<<4) /* 80% */
+#define AC_PINCAP_VREF_100 (1<<5) /* 100% */
/* Amplifier capabilities */
#define AC_AMPCAP_OFFSET (0x7f<<0) /* 0dB offset */
@@ -248,6 +253,11 @@ enum {
/* Pin widget control - 8bit */
#define AC_PINCTL_VREFEN (0x7<<0)
+#define AC_PINCTL_VREF_HIZ 0 /* Hi-Z */
+#define AC_PINCTL_VREF_50 1 /* 50% */
+#define AC_PINCTL_VREF_GRD 2 /* ground */
+#define AC_PINCTL_VREF_80 4 /* 80% */
+#define AC_PINCTL_VREF_100 5 /* 100% */
#define AC_PINCTL_IN_EN (1<<5)
#define AC_PINCTL_OUT_EN (1<<6)
#define AC_PINCTL_HP_EN (1<<7)
@@ -255,7 +265,9 @@ enum {
/* configuration default - 32bit */
#define AC_DEFCFG_SEQUENCE (0xf<<0)
#define AC_DEFCFG_DEF_ASSOC (0xf<<4)
+#define AC_DEFCFG_ASSOC_SHIFT 4
#define AC_DEFCFG_MISC (0xf<<8)
+#define AC_DEFCFG_MISC_SHIFT 8
#define AC_DEFCFG_COLOR (0xf<<12)
#define AC_DEFCFG_COLOR_SHIFT 12
#define AC_DEFCFG_CONN_TYPE (0xf<<16)
@@ -413,7 +425,7 @@ struct hda_bus {
/* codec linked list */
struct list_head codec_list;
- struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS]; /* caddr -> codec */
+ struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1]; /* caddr -> codec */
struct semaphore cmd_mutex;
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 69f7b6c4cf8..2d046abb591 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -44,7 +44,7 @@ struct hda_gnode {
struct list_head list;
};
-/* pathc-specific record */
+/* patch-specific record */
struct hda_gspec {
struct hda_gnode *dac_node; /* DAC node */
struct hda_gnode *out_pin_node; /* Output pin (Line-Out) node */
@@ -68,8 +68,8 @@ struct hda_gspec {
/*
* retrieve the default device type from the default config value
*/
-#define get_defcfg_type(node) (((node)->def_cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
-#define get_defcfg_location(node) (((node)->def_cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT)
+#define defcfg_type(node) (((node)->def_cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
+#define defcfg_location(node) (((node)->def_cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT)
/*
* destructor
@@ -323,7 +323,7 @@ static struct hda_gnode *parse_output_jack(struct hda_codec *codec,
if (! (node->pin_caps & AC_PINCAP_OUT))
continue;
if (jack_type >= 0) {
- if (jack_type != get_defcfg_type(node))
+ if (jack_type != defcfg_type(node))
continue;
if (node->wid_caps & AC_WCAP_DIGITAL)
continue; /* skip SPDIF */
@@ -418,15 +418,15 @@ static int capture_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc
*/
static const char *get_input_type(struct hda_gnode *node, unsigned int *pinctl)
{
- unsigned int location = get_defcfg_location(node);
- switch (get_defcfg_type(node)) {
+ unsigned int location = defcfg_location(node);
+ switch (defcfg_type(node)) {
case AC_JACK_LINE_IN:
if ((location & 0x0f) == AC_JACK_LOC_FRONT)
return "Front Line";
return "Line";
case AC_JACK_CD:
if (pinctl)
- *pinctl |= AC_PIN_VREF_GRD;
+ *pinctl |= AC_PINCTL_VREF_GRD;
return "CD";
case AC_JACK_AUX:
if ((location & 0x0f) == AC_JACK_LOC_FRONT)
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 959953ca320..5e0cca36ed5 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -51,6 +51,7 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
static char *model[SNDRV_CARDS];
+static int position_fix[SNDRV_CARDS];
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for Intel HD audio interface.");
@@ -60,12 +61,17 @@ module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable Intel HD audio interface.");
module_param_array(model, charp, NULL, 0444);
MODULE_PARM_DESC(model, "Use the given board model.");
+module_param_array(position_fix, int, NULL, 0444);
+MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = FIFO size, 1 = none, 2 = POSBUF).");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
"{Intel, ICH6M},"
"{Intel, ICH7},"
- "{Intel, ESB2}}");
+ "{Intel, ESB2},"
+ "{ATI, SB450},"
+ "{VIA, VT8251},"
+ "{VIA, VT8237A}}");
MODULE_DESCRIPTION("Intel HDA driver");
#define SFX "hda-intel: "
@@ -150,7 +156,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
/* STATESTS int mask: SD2,SD1,SD0 */
#define STATESTS_INT_MASK 0x07
-#define AZX_MAX_CODECS 3
+#define AZX_MAX_CODECS 4
/* SD_CTL bits */
#define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */
@@ -183,6 +189,18 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define ICH6_MAX_CORB_ENTRIES 256
#define ICH6_MAX_RIRB_ENTRIES 256
+/* position fix mode */
+enum {
+ POS_FIX_FIFO,
+ POS_FIX_NONE,
+ POS_FIX_POSBUF
+};
+
+/* Defines for ATI HD Audio support in SB450 south bridge */
+#define ATI_SB450_HDAUDIO_PCI_DEVICE_ID 0x437b
+#define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR 0x42
+#define ATI_SB450_HDAUDIO_ENABLE_SNOOP 0x02
+
/*
* Use CORB/RIRB for communication from/to codecs.
@@ -191,12 +209,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define USE_CORB_RIRB
/*
- * Define this if use the position buffer instead of reading SD_LPIB
- * It's not used as default since SD_LPIB seems to give more accurate position
- */
-/* #define USE_POSBUF */
-
-/*
*/
typedef struct snd_azx azx_t;
@@ -271,6 +283,10 @@ struct snd_azx {
struct snd_dma_buffer bdl;
struct snd_dma_buffer rb;
struct snd_dma_buffer posbuf;
+
+ /* flags */
+ int position_fix;
+ unsigned int initialized: 1;
};
/*
@@ -638,7 +654,7 @@ static void azx_stream_stop(azx_t *chip, azx_dev_t *azx_dev)
*/
static void azx_init_chip(azx_t *chip)
{
- unsigned char tcsel_reg;
+ unsigned char tcsel_reg, ati_misc_cntl2;
/* Clear bits 0-2 of PCI register TCSEL (at offset 0x44)
* TCSEL == Traffic Class Select Register, which sets PCI express QOS
@@ -657,11 +673,20 @@ static void azx_init_chip(azx_t *chip)
/* initialize the codec command I/O */
azx_init_cmd_io(chip);
-#ifdef USE_POSBUF
- /* program the position buffer */
- azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
- azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr));
-#endif
+ if (chip->position_fix == POS_FIX_POSBUF) {
+ /* program the position buffer */
+ azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
+ azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr));
+ }
+
+ /* For ATI SB450 azalia HD audio, we need to enable snoop */
+ if (chip->pci->vendor == PCI_VENDOR_ID_ATI &&
+ chip->pci->device == ATI_SB450_HDAUDIO_PCI_DEVICE_ID) {
+ pci_read_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR,
+ &ati_misc_cntl2);
+ pci_write_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR,
+ (ati_misc_cntl2 & 0xf8) | ATI_SB450_HDAUDIO_ENABLE_SNOOP);
+ }
}
@@ -791,11 +816,12 @@ static int azx_setup_controller(azx_t *chip, azx_dev_t *azx_dev)
/* upper BDL address */
azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr));
-#ifdef USE_POSBUF
- /* enable the position buffer */
- if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
- azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
-#endif
+ if (chip->position_fix == POS_FIX_POSBUF) {
+ /* enable the position buffer */
+ if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
+ azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
+ }
+
/* set the interrupt enable bits in the descriptor control register */
azx_sd_writel(azx_dev, SD_CTL, azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK);
@@ -1036,16 +1062,20 @@ static int azx_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
static snd_pcm_uframes_t azx_pcm_pointer(snd_pcm_substream_t *substream)
{
+ struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
+ azx_t *chip = apcm->chip;
azx_dev_t *azx_dev = get_azx_dev(substream);
unsigned int pos;
-#ifdef USE_POSBUF
- /* use the position buffer */
- pos = *azx_dev->posbuf;
-#else
- /* read LPIB */
- pos = azx_sd_readl(azx_dev, SD_LPIB) + azx_dev->fifo_size;
-#endif
+ if (chip->position_fix == POS_FIX_POSBUF) {
+ /* use the position buffer */
+ pos = *azx_dev->posbuf;
+ } else {
+ /* read LPIB */
+ pos = azx_sd_readl(azx_dev, SD_LPIB);
+ if (chip->position_fix == POS_FIX_FIFO)
+ pos += azx_dev->fifo_size;
+ }
if (pos >= azx_dev->bufsize)
pos = 0;
return bytes_to_frames(substream->runtime, pos);
@@ -1155,9 +1185,8 @@ static int __devinit azx_init_stream(azx_t *chip)
azx_dev_t *azx_dev = &chip->azx_dev[i];
azx_dev->bdl = (u32 *)(chip->bdl.area + off);
azx_dev->bdl_addr = chip->bdl.addr + off;
-#ifdef USE_POSBUF
- azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8);
-#endif
+ if (chip->position_fix == POS_FIX_POSBUF)
+ azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8);
/* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80);
/* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */
@@ -1207,7 +1236,7 @@ static int azx_resume(snd_card_t *card)
*/
static int azx_free(azx_t *chip)
{
- if (chip->remap_addr) {
+ if (chip->initialized) {
int i;
for (i = 0; i < MAX_ICH6_DEV; i++)
@@ -1237,10 +1266,8 @@ static int azx_free(azx_t *chip)
snd_dma_free_pages(&chip->bdl);
if (chip->rb.area)
snd_dma_free_pages(&chip->rb);
-#ifdef USE_POSBUF
if (chip->posbuf.area)
snd_dma_free_pages(&chip->posbuf);
-#endif
pci_release_regions(chip->pci);
pci_disable_device(chip->pci);
kfree(chip);
@@ -1256,7 +1283,8 @@ static int azx_dev_free(snd_device_t *device)
/*
* constructor
*/
-static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, azx_t **rchip)
+static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci,
+ int posfix, azx_t **rchip)
{
azx_t *chip;
int err = 0;
@@ -1283,6 +1311,8 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, azx_t **r
chip->pci = pci;
chip->irq = -1;
+ chip->position_fix = posfix;
+
if ((err = pci_request_regions(pci, "ICH HD audio")) < 0) {
kfree(chip);
pci_disable_device(pci);
@@ -1314,14 +1344,14 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, azx_t **r
snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
goto errout;
}
-#ifdef USE_POSBUF
- /* allocate memory for the position buffer */
- if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
- MAX_ICH6_DEV * 8, &chip->posbuf)) < 0) {
- snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
- goto errout;
+ if (chip->position_fix == POS_FIX_POSBUF) {
+ /* allocate memory for the position buffer */
+ if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+ MAX_ICH6_DEV * 8, &chip->posbuf)) < 0) {
+ snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
+ goto errout;
+ }
}
-#endif
/* allocate CORB/RIRB */
if ((err = azx_alloc_cmd_io(chip)) < 0)
goto errout;
@@ -1332,6 +1362,8 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, azx_t **r
/* initialize chip */
azx_init_chip(chip);
+ chip->initialized = 1;
+
/* codec detection */
if (! chip->codec_mask) {
snd_printk(KERN_ERR SFX "no codecs found!\n");
@@ -1372,7 +1404,7 @@ static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id *
return -ENOMEM;
}
- if ((err = azx_create(card, pci, &chip)) < 0) {
+ if ((err = azx_create(card, pci, position_fix[dev], &chip)) < 0) {
snd_card_free(card);
return err;
}
@@ -1424,6 +1456,9 @@ static struct pci_device_id azx_ids[] = {
{ 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH6 */
{ 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH7 */
{ 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ESB2 */
+ { 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ATI SB450 */
+ { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* VIA VT8251/VT8237A */
+ { 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ALI 5461? */
{ 0, }
};
MODULE_DEVICE_TABLE(pci, azx_ids);
@@ -1439,7 +1474,7 @@ static struct pci_driver driver = {
static int __init alsa_card_azx_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_azx_exit(void)
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 7c7b849875a..810cfd2d9bb 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -126,11 +126,11 @@ static inline int snd_hda_codec_proc_new(struct hda_codec *codec) { return 0; }
struct hda_board_config {
const char *modelname;
int config;
- unsigned short pci_vendor;
- unsigned short pci_device;
+ unsigned short pci_subvendor;
+ unsigned short pci_subdevice;
};
-int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config *tbl);
+int snd_hda_check_board_config(struct hda_codec *codec, const struct hda_board_config *tbl);
int snd_hda_add_new_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew);
/*
@@ -158,4 +158,35 @@ struct hda_bus_unsolicited {
struct work_struct work;
};
+/*
+ * Helper for automatic ping configuration
+ */
+
+enum {
+ AUTO_PIN_MIC,
+ AUTO_PIN_FRONT_MIC,
+ AUTO_PIN_LINE,
+ AUTO_PIN_FRONT_LINE,
+ AUTO_PIN_CD,
+ AUTO_PIN_AUX,
+ AUTO_PIN_LAST
+};
+
+struct auto_pin_cfg {
+ int line_outs;
+ hda_nid_t line_out_pins[4]; /* sorted in the order of Front/Surr/CLFE/Side */
+ hda_nid_t hp_pin;
+ hda_nid_t input_pins[AUTO_PIN_LAST];
+ hda_nid_t dig_out_pin;
+ hda_nid_t dig_in_pin;
+};
+
+#define get_defcfg_connect(cfg) ((cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT)
+#define get_defcfg_association(cfg) ((cfg & AC_DEFCFG_DEF_ASSOC) >> AC_DEFCFG_ASSOC_SHIFT)
+#define get_defcfg_location(cfg) ((cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT)
+#define get_defcfg_sequence(cfg) (cfg & AC_DEFCFG_SEQUENCE)
+#define get_defcfg_device(cfg) ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
+
+int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg);
+
#endif /* __SOUND_HDA_LOCAL_H */
diff --git a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h
index cf6abce42bc..a5de684b694 100644
--- a/sound/pci/hda/hda_patch.h
+++ b/sound/pci/hda/hda_patch.h
@@ -8,10 +8,13 @@ extern struct hda_codec_preset snd_hda_preset_realtek[];
extern struct hda_codec_preset snd_hda_preset_cmedia[];
/* Analog Devices codecs */
extern struct hda_codec_preset snd_hda_preset_analog[];
+/* SigmaTel codecs */
+extern struct hda_codec_preset snd_hda_preset_sigmatel[];
static const struct hda_codec_preset *hda_preset_tables[] = {
snd_hda_preset_realtek,
snd_hda_preset_cmedia,
snd_hda_preset_analog,
+ snd_hda_preset_sigmatel,
NULL
};
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index 4d5db7faad8..de1217bd8e6 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -68,21 +68,27 @@ static void print_amp_caps(snd_info_buffer_t *buffer,
static void print_amp_vals(snd_info_buffer_t *buffer,
struct hda_codec *codec, hda_nid_t nid,
- int dir, int stereo)
+ int dir, int stereo, int indices)
{
unsigned int val;
- if (stereo) {
+ int i;
+
+ if (dir == HDA_OUTPUT)
+ dir = AC_AMP_GET_OUTPUT;
+ else
+ dir = AC_AMP_GET_INPUT;
+ for (i = 0; i < indices; i++) {
+ snd_iprintf(buffer, " [");
+ if (stereo) {
+ val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE,
+ AC_AMP_GET_LEFT | dir | i);
+ snd_iprintf(buffer, "0x%02x ", val);
+ }
val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE,
- AC_AMP_GET_LEFT |
- (dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT :
- AC_AMP_GET_INPUT));
- snd_iprintf(buffer, "0x%02x ", val);
+ AC_AMP_GET_RIGHT | dir | i);
+ snd_iprintf(buffer, "0x%02x]", val);
}
- val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE,
- AC_AMP_GET_RIGHT |
- (dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT :
- AC_AMP_GET_INPUT));
- snd_iprintf(buffer, "0x%02x\n", val);
+ snd_iprintf(buffer, "\n");
}
static void print_pcm_caps(snd_info_buffer_t *buffer,
@@ -157,6 +163,7 @@ static const char *get_jack_color(u32 cfg)
static void print_pin_caps(snd_info_buffer_t *buffer,
struct hda_codec *codec, hda_nid_t nid)
{
+ static char *jack_conns[4] = { "Jack", "N/A", "Fixed", "Both" };
static char *jack_types[16] = {
"Line Out", "Speaker", "HP Out", "CD",
"SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
@@ -176,7 +183,8 @@ static void print_pin_caps(snd_info_buffer_t *buffer,
snd_iprintf(buffer, " HP");
snd_iprintf(buffer, "\n");
caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
- snd_iprintf(buffer, " Pin Default 0x%08x: %s at %s %s\n", caps,
+ snd_iprintf(buffer, " Pin Default 0x%08x: [%s] %s at %s %s\n", caps,
+ jack_conns[(caps & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT],
jack_types[(caps & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT],
jack_locations[(caps >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3],
get_jack_location(caps));
@@ -215,6 +223,9 @@ static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
unsigned int wid_caps = snd_hda_param_read(codec, nid,
AC_PAR_AUDIO_WIDGET_CAP);
unsigned int wid_type = (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+ int conn_len = 0;
+ hda_nid_t conn[HDA_MAX_CONNECTIONS];
+
snd_iprintf(buffer, "Node 0x%02x [%s] wcaps 0x%x:", nid,
get_wid_type_name(wid_type), wid_caps);
if (wid_caps & AC_WCAP_STEREO)
@@ -229,19 +240,23 @@ static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
snd_iprintf(buffer, " Amp-Out");
snd_iprintf(buffer, "\n");
+ if (wid_caps & AC_WCAP_CONN_LIST)
+ conn_len = snd_hda_get_connections(codec, nid, conn,
+ HDA_MAX_CONNECTIONS);
+
if (wid_caps & AC_WCAP_IN_AMP) {
snd_iprintf(buffer, " Amp-In caps: ");
print_amp_caps(buffer, codec, nid, HDA_INPUT);
snd_iprintf(buffer, " Amp-In vals: ");
print_amp_vals(buffer, codec, nid, HDA_INPUT,
- wid_caps & AC_WCAP_STEREO);
+ wid_caps & AC_WCAP_STEREO, conn_len);
}
if (wid_caps & AC_WCAP_OUT_AMP) {
snd_iprintf(buffer, " Amp-Out caps: ");
print_amp_caps(buffer, codec, nid, HDA_OUTPUT);
snd_iprintf(buffer, " Amp-Out vals: ");
print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
- wid_caps & AC_WCAP_STEREO);
+ wid_caps & AC_WCAP_STEREO, 1);
}
if (wid_type == AC_WID_PIN) {
@@ -265,14 +280,17 @@ static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
}
if (wid_caps & AC_WCAP_CONN_LIST) {
- hda_nid_t conn[HDA_MAX_CONNECTIONS];
- int c, conn_len;
- conn_len = snd_hda_get_connections(codec, nid, conn,
- HDA_MAX_CONNECTIONS);
+ int c, curr = -1;
+ if (conn_len > 1 && wid_type != AC_WID_AUD_MIX)
+ curr = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_CONNECT_SEL, 0);
snd_iprintf(buffer, " Connection: %d\n", conn_len);
snd_iprintf(buffer, " ");
- for (c = 0; c < conn_len; c++)
+ for (c = 0; c < conn_len; c++) {
snd_iprintf(buffer, " 0x%02x", conn[c]);
+ if (c == curr)
+ snd_iprintf(buffer, "*");
+ }
snd_iprintf(buffer, "\n");
}
}
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 75d23849f71..2fd05bb8413 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -1,5 +1,5 @@
/*
- * HD audio interface patch for AD1986A
+ * HD audio interface patch for AD1981HD, AD1983, AD1986A
*
* Copyright (c) 2005 Takashi Iwai <tiwai@suse.de>
*
@@ -27,13 +27,239 @@
#include "hda_codec.h"
#include "hda_local.h"
-struct ad1986a_spec {
+struct ad198x_spec {
struct semaphore amp_mutex; /* PCM volume/mute control mutex */
struct hda_multi_out multiout; /* playback */
+ hda_nid_t adc_nid;
+ const struct hda_input_mux *input_mux;
unsigned int cur_mux; /* capture source */
+ unsigned int spdif_route;
+ snd_kcontrol_new_t *mixers;
+ const struct hda_verb *init_verbs;
struct hda_pcm pcm_rec[2]; /* PCM information */
};
+/*
+ * input MUX handling (common part)
+ */
+static int ad198x_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct ad198x_spec *spec = codec->spec;
+
+ return snd_hda_input_mux_info(spec->input_mux, uinfo);
+}
+
+static int ad198x_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct ad198x_spec *spec = codec->spec;
+
+ ucontrol->value.enumerated.item[0] = spec->cur_mux;
+ return 0;
+}
+
+static int ad198x_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct ad198x_spec *spec = codec->spec;
+
+ return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
+ spec->adc_nid, &spec->cur_mux);
+}
+
+/*
+ * initialization (common callbacks)
+ */
+static int ad198x_init(struct hda_codec *codec)
+{
+ struct ad198x_spec *spec = codec->spec;
+ snd_hda_sequence_write(codec, spec->init_verbs);
+ return 0;
+}
+
+static int ad198x_build_controls(struct hda_codec *codec)
+{
+ struct ad198x_spec *spec = codec->spec;
+ int err;
+
+ err = snd_hda_add_new_ctls(codec, spec->mixers);
+ if (err < 0)
+ return err;
+ if (spec->multiout.dig_out_nid)
+ err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
+ if (err < 0)
+ return err;
+ return 0;
+}
+
+/*
+ * Analog playback callbacks
+ */
+static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct ad198x_spec *spec = codec->spec;
+ return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+}
+
+static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ unsigned int stream_tag,
+ unsigned int format,
+ snd_pcm_substream_t *substream)
+{
+ struct ad198x_spec *spec = codec->spec;
+ return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
+ format, substream);
+}
+
+static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct ad198x_spec *spec = codec->spec;
+ return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
+}
+
+/*
+ * Digital out
+ */
+static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct ad198x_spec *spec = codec->spec;
+ return snd_hda_multi_out_dig_open(codec, &spec->multiout);
+}
+
+static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct ad198x_spec *spec = codec->spec;
+ return snd_hda_multi_out_dig_close(codec, &spec->multiout);
+}
+
+/*
+ * Analog capture
+ */
+static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ unsigned int stream_tag,
+ unsigned int format,
+ snd_pcm_substream_t *substream)
+{
+ struct ad198x_spec *spec = codec->spec;
+ snd_hda_codec_setup_stream(codec, spec->adc_nid, stream_tag, 0, format);
+ return 0;
+}
+
+static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct ad198x_spec *spec = codec->spec;
+ snd_hda_codec_setup_stream(codec, spec->adc_nid, 0, 0, 0);
+ return 0;
+}
+
+
+/*
+ */
+static struct hda_pcm_stream ad198x_pcm_analog_playback = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 6,
+ .nid = 0, /* fill later */
+ .ops = {
+ .open = ad198x_playback_pcm_open,
+ .prepare = ad198x_playback_pcm_prepare,
+ .cleanup = ad198x_playback_pcm_cleanup
+ },
+};
+
+static struct hda_pcm_stream ad198x_pcm_analog_capture = {
+ .substreams = 2,
+ .channels_min = 2,
+ .channels_max = 2,
+ .nid = 0, /* fill later */
+ .ops = {
+ .prepare = ad198x_capture_pcm_prepare,
+ .cleanup = ad198x_capture_pcm_cleanup
+ },
+};
+
+static struct hda_pcm_stream ad198x_pcm_digital_playback = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 2,
+ .nid = 0, /* fill later */
+ .ops = {
+ .open = ad198x_dig_playback_pcm_open,
+ .close = ad198x_dig_playback_pcm_close
+ },
+};
+
+static int ad198x_build_pcms(struct hda_codec *codec)
+{
+ struct ad198x_spec *spec = codec->spec;
+ struct hda_pcm *info = spec->pcm_rec;
+
+ codec->num_pcms = 1;
+ codec->pcm_info = info;
+
+ info->name = "AD198x Analog";
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
+ info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture;
+ info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nid;
+
+ if (spec->multiout.dig_out_nid) {
+ info++;
+ codec->num_pcms++;
+ info->name = "AD198x Digital";
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
+ }
+
+ return 0;
+}
+
+static void ad198x_free(struct hda_codec *codec)
+{
+ kfree(codec->spec);
+}
+
+#ifdef CONFIG_PM
+static int ad198x_resume(struct hda_codec *codec)
+{
+ struct ad198x_spec *spec = codec->spec;
+
+ ad198x_init(codec);
+ snd_hda_resume_ctls(codec, spec->mixers);
+ snd_hda_resume_spdif_out(codec);
+ return 0;
+}
+#endif
+
+static struct hda_codec_ops ad198x_patch_ops = {
+ .build_controls = ad198x_build_controls,
+ .build_pcms = ad198x_build_pcms,
+ .init = ad198x_init,
+ .free = ad198x_free,
+#ifdef CONFIG_PM
+ .resume = ad198x_resume,
+#endif
+};
+
+
+/*
+ * AD1986A specific
+ */
+
#define AD1986A_SPDIF_OUT 0x02
#define AD1986A_FRONT_DAC 0x03
#define AD1986A_SURR_DAC 0x04
@@ -68,7 +294,7 @@ static struct hda_input_mux ad1986a_capture_source = {
static int ad1986a_pcm_amp_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ad1986a_spec *ad = codec->spec;
+ struct ad198x_spec *ad = codec->spec;
down(&ad->amp_mutex);
snd_hda_mixer_amp_volume_get(kcontrol, ucontrol);
@@ -79,7 +305,7 @@ static int ad1986a_pcm_amp_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
static int ad1986a_pcm_amp_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ad1986a_spec *ad = codec->spec;
+ struct ad198x_spec *ad = codec->spec;
int i, change = 0;
down(&ad->amp_mutex);
@@ -92,12 +318,12 @@ static int ad1986a_pcm_amp_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_
return change;
}
-#define ad1986a_pcm_amp_sw_info snd_hda_mixer_amp_volume_info
+#define ad1986a_pcm_amp_sw_info snd_hda_mixer_amp_switch_info
static int ad1986a_pcm_amp_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ad1986a_spec *ad = codec->spec;
+ struct ad198x_spec *ad = codec->spec;
down(&ad->amp_mutex);
snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
@@ -108,7 +334,7 @@ static int ad1986a_pcm_amp_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
static int ad1986a_pcm_amp_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ad1986a_spec *ad = codec->spec;
+ struct ad198x_spec *ad = codec->spec;
int i, change = 0;
down(&ad->amp_mutex);
@@ -122,32 +348,6 @@ static int ad1986a_pcm_amp_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
}
/*
- * input MUX handling
- */
-static int ad1986a_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
-{
- return snd_hda_input_mux_info(&ad1986a_capture_source, uinfo);
-}
-
-static int ad1986a_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ad1986a_spec *spec = codec->spec;
-
- ucontrol->value.enumerated.item[0] = spec->cur_mux;
- return 0;
-}
-
-static int ad1986a_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct ad1986a_spec *spec = codec->spec;
-
- return snd_hda_input_mux_put(codec, &ad1986a_capture_source, ucontrol,
- AD1986A_ADC, &spec->cur_mux);
-}
-
-/*
* mixers
*/
static snd_kcontrol_new_t ad1986a_mixers[] = {
@@ -194,9 +394,9 @@ static snd_kcontrol_new_t ad1986a_mixers[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Capture Source",
- .info = ad1986a_mux_enum_info,
- .get = ad1986a_mux_enum_get,
- .put = ad1986a_mux_enum_put,
+ .info = ad198x_mux_enum_info,
+ .get = ad198x_mux_enum_get,
+ .put = ad198x_mux_enum_put,
},
HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
{ } /* end */
@@ -241,183 +441,328 @@ static struct hda_verb ad1986a_init_verbs[] = {
{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ /* HP Pin */
+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+ /* Front, Surround, CLFE Pins */
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ /* Mono Pin */
+ {0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ /* Mic Pin */
+ {0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+ /* Line, Aux, CD, Beep-In Pin */
+ {0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+ {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+ {0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+ {0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+ {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
{ } /* end */
};
-static int ad1986a_init(struct hda_codec *codec)
+static int patch_ad1986a(struct hda_codec *codec)
{
- snd_hda_sequence_write(codec, ad1986a_init_verbs);
- return 0;
-}
+ struct ad198x_spec *spec;
-static int ad1986a_build_controls(struct hda_codec *codec)
-{
- int err;
+ spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ if (spec == NULL)
+ return -ENOMEM;
+
+ init_MUTEX(&spec->amp_mutex);
+ codec->spec = spec;
+
+ spec->multiout.max_channels = 6;
+ spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
+ spec->multiout.dac_nids = ad1986a_dac_nids;
+ spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
+ spec->adc_nid = AD1986A_ADC;
+ spec->input_mux = &ad1986a_capture_source;
+ spec->mixers = ad1986a_mixers;
+ spec->init_verbs = ad1986a_init_verbs;
+
+ codec->patch_ops = ad198x_patch_ops;
- err = snd_hda_add_new_ctls(codec, ad1986a_mixers);
- if (err < 0)
- return err;
- err = snd_hda_create_spdif_out_ctls(codec, AD1986A_SPDIF_OUT);
- if (err < 0)
- return err;
return 0;
}
/*
- * Analog playback callbacks
+ * AD1983 specific
*/
-static int ad1986a_playback_pcm_open(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- snd_pcm_substream_t *substream)
-{
- struct ad1986a_spec *spec = codec->spec;
- return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
-}
-static int ad1986a_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- unsigned int stream_tag,
- unsigned int format,
- snd_pcm_substream_t *substream)
-{
- struct ad1986a_spec *spec = codec->spec;
- return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
- format, substream);
-}
+#define AD1983_SPDIF_OUT 0x02
+#define AD1983_DAC 0x03
+#define AD1983_ADC 0x04
-static int ad1986a_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- snd_pcm_substream_t *substream)
-{
- struct ad1986a_spec *spec = codec->spec;
- return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
-}
+static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
+
+static struct hda_input_mux ad1983_capture_source = {
+ .num_items = 4,
+ .items = {
+ { "Mic", 0x0 },
+ { "Line", 0x1 },
+ { "Mix", 0x2 },
+ { "Mix Mono", 0x3 },
+ },
+};
/*
- * Digital out
+ * SPDIF playback route
*/
-static int ad1986a_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- snd_pcm_substream_t *substream)
+static int ad1983_spdif_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
{
- struct ad1986a_spec *spec = codec->spec;
- return snd_hda_multi_out_dig_open(codec, &spec->multiout);
+ static char *texts[] = { "PCM", "ADC" };
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 2;
+ if (uinfo->value.enumerated.item > 1)
+ uinfo->value.enumerated.item = 1;
+ strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+ return 0;
}
-static int ad1986a_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- snd_pcm_substream_t *substream)
+static int ad1983_spdif_route_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
- struct ad1986a_spec *spec = codec->spec;
- return snd_hda_multi_out_dig_close(codec, &spec->multiout);
-}
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct ad198x_spec *spec = codec->spec;
-/*
- * Analog capture
- */
-static int ad1986a_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- unsigned int stream_tag,
- unsigned int format,
- snd_pcm_substream_t *substream)
-{
- snd_hda_codec_setup_stream(codec, AD1986A_ADC, stream_tag, 0, format);
+ ucontrol->value.enumerated.item[0] = spec->spdif_route;
return 0;
}
-static int ad1986a_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- snd_pcm_substream_t *substream)
+static int ad1983_spdif_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{
- snd_hda_codec_setup_stream(codec, AD1986A_ADC, 0, 0, 0);
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct ad198x_spec *spec = codec->spec;
+
+ if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
+ spec->spdif_route = ucontrol->value.enumerated.item[0];
+ snd_hda_codec_write(codec, spec->multiout.dig_out_nid, 0,
+ AC_VERB_SET_CONNECT_SEL, spec->spdif_route);
+ return 1;
+ }
return 0;
}
-
-/*
- */
-static struct hda_pcm_stream ad1986a_pcm_analog_playback = {
- .substreams = 1,
- .channels_min = 2,
- .channels_max = 6,
- .nid = AD1986A_FRONT_DAC, /* NID to query formats and rates */
- .ops = {
- .open = ad1986a_playback_pcm_open,
- .prepare = ad1986a_playback_pcm_prepare,
- .cleanup = ad1986a_playback_pcm_cleanup
+static snd_kcontrol_new_t ad1983_mixers[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x10, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x10, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Source",
+ .info = ad198x_mux_enum_info,
+ .get = ad198x_mux_enum_get,
+ .put = ad198x_mux_enum_put,
},
-};
-
-static struct hda_pcm_stream ad1986a_pcm_analog_capture = {
- .substreams = 2,
- .channels_min = 2,
- .channels_max = 2,
- .nid = AD1986A_ADC, /* NID to query formats and rates */
- .ops = {
- .prepare = ad1986a_capture_pcm_prepare,
- .cleanup = ad1986a_capture_pcm_cleanup
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "IEC958 Playback Route",
+ .info = ad1983_spdif_route_info,
+ .get = ad1983_spdif_route_get,
+ .put = ad1983_spdif_route_put,
},
+ { } /* end */
};
-static struct hda_pcm_stream ad1986a_pcm_digital_playback = {
- .substreams = 1,
- .channels_min = 2,
- .channels_max = 2,
- .nid = AD1986A_SPDIF_OUT,
- .ops = {
- .open = ad1986a_dig_playback_pcm_open,
- .close = ad1986a_dig_playback_pcm_close
- },
+static struct hda_verb ad1983_init_verbs[] = {
+ /* Front, HP, Mono; mute as default */
+ {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ /* Beep, PCM, Mic, Line-In: mute */
+ {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ /* Front, HP selectors; from Mix */
+ {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
+ {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
+ /* Mono selector; from Mix */
+ {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
+ /* Mic selector; Mic */
+ {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
+ /* Line-in selector: Line-in */
+ {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
+ /* Mic boost: 0dB */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* Record selector: mic */
+ {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ /* SPDIF route: PCM */
+ {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
+ /* Front Pin */
+ {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ /* HP Pin */
+ {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+ /* Mono Pin */
+ {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ /* Mic Pin */
+ {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+ /* Line Pin */
+ {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+ { } /* end */
};
-static int ad1986a_build_pcms(struct hda_codec *codec)
+static int patch_ad1983(struct hda_codec *codec)
{
- struct ad1986a_spec *spec = codec->spec;
- struct hda_pcm *info = spec->pcm_rec;
+ struct ad198x_spec *spec;
- codec->num_pcms = 2;
- codec->pcm_info = info;
+ spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ if (spec == NULL)
+ return -ENOMEM;
- info->name = "AD1986A Analog";
- info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad1986a_pcm_analog_playback;
- info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1986a_pcm_analog_capture;
- info++;
+ init_MUTEX(&spec->amp_mutex);
+ codec->spec = spec;
+
+ spec->multiout.max_channels = 2;
+ spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
+ spec->multiout.dac_nids = ad1983_dac_nids;
+ spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
+ spec->adc_nid = AD1983_ADC;
+ spec->input_mux = &ad1983_capture_source;
+ spec->mixers = ad1983_mixers;
+ spec->init_verbs = ad1983_init_verbs;
+ spec->spdif_route = 0;
- info->name = "AD1986A Digital";
- info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad1986a_pcm_digital_playback;
+ codec->patch_ops = ad198x_patch_ops;
return 0;
}
-static void ad1986a_free(struct hda_codec *codec)
-{
- kfree(codec->spec);
-}
-#ifdef CONFIG_PM
-static int ad1986a_resume(struct hda_codec *codec)
-{
- ad1986a_init(codec);
- snd_hda_resume_ctls(codec, ad1986a_mixers);
- snd_hda_resume_spdif_out(codec);
- return 0;
-}
-#endif
+/*
+ * AD1981 HD specific
+ */
-static struct hda_codec_ops ad1986a_patch_ops = {
- .build_controls = ad1986a_build_controls,
- .build_pcms = ad1986a_build_pcms,
- .init = ad1986a_init,
- .free = ad1986a_free,
-#ifdef CONFIG_PM
- .resume = ad1986a_resume,
-#endif
+#define AD1981_SPDIF_OUT 0x02
+#define AD1981_DAC 0x03
+#define AD1981_ADC 0x04
+
+static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
+
+/* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
+static struct hda_input_mux ad1981_capture_source = {
+ .num_items = 7,
+ .items = {
+ { "Front Mic", 0x0 },
+ { "Line", 0x1 },
+ { "Mix", 0x2 },
+ { "Mix Mono", 0x3 },
+ { "CD", 0x4 },
+ { "Mic", 0x6 },
+ { "Aux", 0x7 },
+ },
};
-static int patch_ad1986a(struct hda_codec *codec)
+static snd_kcontrol_new_t ad1981_mixers[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("PCM Playback Volume", 0x11, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("PCM Playback Switch", 0x11, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x0d, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Boost", 0x18, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_OUTPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Source",
+ .info = ad198x_mux_enum_info,
+ .get = ad198x_mux_enum_get,
+ .put = ad198x_mux_enum_put,
+ },
+ /* identical with AD1983 */
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "IEC958 Playback Route",
+ .info = ad1983_spdif_route_info,
+ .get = ad1983_spdif_route_get,
+ .put = ad1983_spdif_route_put,
+ },
+ { } /* end */
+};
+
+static struct hda_verb ad1981_init_verbs[] = {
+ /* Front, HP, Mono; mute as default */
+ {0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ /* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ /* Front, HP selectors; from Mix */
+ {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
+ {0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
+ /* Mono selector; from Mix */
+ {0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
+ /* Mic Mixer; select Front Mic */
+ {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ /* Mic boost: 0dB */
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ /* Record selector: Front mic */
+ {0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ /* SPDIF route: PCM */
+ {0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
+ /* Front Pin */
+ {0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ /* HP Pin */
+ {0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+ /* Mono Pin */
+ {0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ /* Front & Rear Mic Pins */
+ {0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+ /* Line Pin */
+ {0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+ /* Digital Beep */
+ {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
+ /* Line-Out as Input: disabled */
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ { } /* end */
+};
+
+static int patch_ad1981(struct hda_codec *codec)
{
- struct ad1986a_spec *spec;
+ struct ad198x_spec *spec;
spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
@@ -426,20 +771,28 @@ static int patch_ad1986a(struct hda_codec *codec)
init_MUTEX(&spec->amp_mutex);
codec->spec = spec;
- spec->multiout.max_channels = 6;
- spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
- spec->multiout.dac_nids = ad1986a_dac_nids;
- spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
+ spec->multiout.max_channels = 2;
+ spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
+ spec->multiout.dac_nids = ad1981_dac_nids;
+ spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
+ spec->adc_nid = AD1981_ADC;
+ spec->input_mux = &ad1981_capture_source;
+ spec->mixers = ad1981_mixers;
+ spec->init_verbs = ad1981_init_verbs;
+ spec->spdif_route = 0;
- codec->patch_ops = ad1986a_patch_ops;
+ codec->patch_ops = ad198x_patch_ops;
return 0;
}
+
/*
* patch entries
*/
struct hda_codec_preset snd_hda_preset_analog[] = {
+ { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
+ { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
{ .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
{} /* terminator */
};
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index b7cc8e4bffb..2d6e3e3d0a3 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -29,6 +29,7 @@
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
+#define NUM_PINS 11
/* board config type */
@@ -38,6 +39,7 @@ enum {
CMI_FULL, /* back 6-jack + front-panel 2-jack */
CMI_FULL_DIG, /* back 6-jack + front-panel 2-jack + digital I/O */
CMI_ALLOUT, /* back 5-jack + front-panel 2-jack + digital out */
+ CMI_AUTO, /* let driver guess it */
};
struct cmi_spec {
@@ -48,6 +50,8 @@ struct cmi_spec {
/* playback */
struct hda_multi_out multiout;
+ hda_nid_t dac_nids[4]; /* NID for each DAC */
+ int num_dacs;
/* capture */
hda_nid_t *adc_nids;
@@ -63,8 +67,30 @@ struct cmi_spec {
const struct cmi_channel_mode *channel_modes;
struct hda_pcm pcm_rec[2]; /* PCM information */
+
+ /* pin deafault configuration */
+ hda_nid_t pin_nid[NUM_PINS];
+ unsigned int def_conf[NUM_PINS];
+ unsigned int pin_def_confs;
+
+ /* multichannel pins */
+ hda_nid_t multich_pin[4]; /* max 8-channel */
+ struct hda_verb multi_init[9]; /* 2 verbs for each pin + terminator */
};
+/* amp values */
+#define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8))
+#define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8))
+#define AMP_OUT_MUTE 0xb080
+#define AMP_OUT_UNMUTE 0xb000
+#define AMP_OUT_ZERO 0xb000
+/* pinctl values */
+#define PIN_IN 0x20
+#define PIN_VREF80 0x24
+#define PIN_VREF50 0x21
+#define PIN_OUT 0x40
+#define PIN_HP 0xc0
+
/*
* input MUX
*/
@@ -102,9 +128,9 @@ static int cmi_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon
/* 3-stack / 2 channel */
static struct hda_verb cmi9880_ch2_init[] = {
/* set line-in PIN for input */
- { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+ { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
/* set mic PIN for input, also enable vref */
- { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+ { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
/* route front PCM (DAC1) to HP */
{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
{}
@@ -113,9 +139,9 @@ static struct hda_verb cmi9880_ch2_init[] = {
/* 3-stack / 6 channel */
static struct hda_verb cmi9880_ch6_init[] = {
/* set line-in PIN for output */
- { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
/* set mic PIN for output */
- { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
/* route front PCM (DAC1) to HP */
{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
{}
@@ -124,9 +150,9 @@ static struct hda_verb cmi9880_ch6_init[] = {
/* 3-stack+front / 8 channel */
static struct hda_verb cmi9880_ch8_init[] = {
/* set line-in PIN for output */
- { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
/* set mic PIN for output */
- { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+ { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
/* route rear-surround PCM (DAC4) to HP */
{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x03 },
{}
@@ -269,25 +295,27 @@ static hda_nid_t cmi9880_adc_nids[2] = {
*/
static struct hda_verb cmi9880_basic_init[] = {
/* port-D for line out (rear panel) */
- { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+ { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
/* port-E for HP out (front panel) */
- { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+ { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
/* route front PCM to HP */
{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
/* port-A for surround (rear panel) */
- { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+ { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
/* port-G for CLFE (rear panel) */
- { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+ { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
+ { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 },
/* port-H for side (rear panel) */
- { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+ { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
+ { 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 },
/* port-C for line-in (rear panel) */
- { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+ { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
/* port-B for mic-in (rear panel) with vref */
- { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+ { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
/* port-F for mic-in (front panel) with vref */
- { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+ { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
/* CD-in */
- { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+ { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
/* route front mic to ADC1/2 */
{ 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 },
{ 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 },
@@ -296,23 +324,27 @@ static struct hda_verb cmi9880_basic_init[] = {
static struct hda_verb cmi9880_allout_init[] = {
/* port-D for line out (rear panel) */
- { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+ { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
/* port-E for HP out (front panel) */
- { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+ { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
/* route front PCM to HP */
{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
/* port-A for side (rear panel) */
- { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+ { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
/* port-G for CLFE (rear panel) */
- { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+ { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
+ { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 },
+ /* port-H for side (rear panel) */
+ { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
+ { 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 },
/* port-C for surround (rear panel) */
- { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+ { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
/* port-B for mic-in (rear panel) with vref */
- { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+ { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
/* port-F for mic-in (front panel) with vref */
- { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+ { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
/* CD-in */
- { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+ { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
/* route front mic to ADC1/2 */
{ 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 },
{ 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 },
@@ -347,6 +379,81 @@ static int cmi9880_build_controls(struct hda_codec *codec)
return 0;
}
+/* fill in the multi_dac_nids table, which will decide
+ which audio widget to use for each channel */
+static int cmi9880_fill_multi_dac_nids(struct hda_codec *codec, const struct auto_pin_cfg *cfg)
+{
+ struct cmi_spec *spec = codec->spec;
+ hda_nid_t nid;
+ int assigned[4];
+ int i, j;
+
+ /* clear the table, only one c-media dac assumed here */
+ memset(spec->dac_nids, 0, sizeof(spec->dac_nids));
+ memset(assigned, 0, sizeof(assigned));
+ /* check the pins we found */
+ for (i = 0; i < cfg->line_outs; i++) {
+ nid = cfg->line_out_pins[i];
+ /* nid 0x0b~0x0e is hardwired to audio widget 0x3~0x6 */
+ if (nid >= 0x0b && nid <= 0x0e) {
+ spec->dac_nids[i] = (nid - 0x0b) + 0x03;
+ assigned[nid - 0x0b] = 1;
+ }
+ }
+ /* left pin can be connect to any audio widget */
+ for (i = 0; i < cfg->line_outs; i++) {
+ nid = cfg->line_out_pins[i];
+ if (nid <= 0x0e)
+ continue;
+ /* search for an empty channel */
+ for (j = 0; j < cfg->line_outs; j++) {
+ if (! assigned[j]) {
+ spec->dac_nids[i] = i + 0x03;
+ assigned[j] = 1;
+ break;
+ }
+ }
+ }
+ spec->num_dacs = cfg->line_outs;
+ return 0;
+}
+
+/* create multi_init table, which is used for multichannel initialization */
+static int cmi9880_fill_multi_init(struct hda_codec *codec, const struct auto_pin_cfg *cfg)
+{
+ struct cmi_spec *spec = codec->spec;
+ hda_nid_t nid;
+ int i, j, k, len;
+
+ /* clear the table, only one c-media dac assumed here */
+ memset(spec->multi_init, 0, sizeof(spec->multi_init));
+ for (j = 0, i = 0; i < cfg->line_outs; i++) {
+ hda_nid_t conn[4];
+ nid = cfg->line_out_pins[i];
+ /* set as output */
+ spec->multi_init[j].nid = nid;
+ spec->multi_init[j].verb = AC_VERB_SET_PIN_WIDGET_CONTROL;
+ spec->multi_init[j].param = PIN_OUT;
+ j++;
+ if (nid > 0x0e) {
+ /* set connection */
+ spec->multi_init[j].nid = nid;
+ spec->multi_init[j].verb = AC_VERB_SET_CONNECT_SEL;
+ spec->multi_init[j].param = 0;
+ /* find the index in connect list */
+ len = snd_hda_get_connections(codec, nid, conn, 4);
+ for (k = 0; k < len; k++)
+ if (conn[k] == spec->dac_nids[i]) {
+ spec->multi_init[j].param = j;
+ break;
+ }
+ j++;
+ break;
+ }
+ }
+ return 0;
+}
+
static int cmi9880_init(struct hda_codec *codec)
{
struct cmi_spec *spec = codec->spec;
@@ -354,6 +461,8 @@ static int cmi9880_init(struct hda_codec *codec)
snd_hda_sequence_write(codec, cmi9880_allout_init);
else
snd_hda_sequence_write(codec, cmi9880_basic_init);
+ if (spec->board_config == CMI_AUTO)
+ snd_hda_sequence_write(codec, spec->multi_init);
return 0;
}
@@ -540,6 +649,7 @@ static struct hda_board_config cmi9880_cfg_tbl[] = {
{ .modelname = "full", .config = CMI_FULL },
{ .modelname = "full_dig", .config = CMI_FULL_DIG },
{ .modelname = "allout", .config = CMI_ALLOUT },
+ { .modelname = "auto", .config = CMI_AUTO },
{} /* terminator */
};
@@ -564,10 +674,14 @@ static int patch_cmi9880(struct hda_codec *codec)
codec->spec = spec;
spec->board_config = snd_hda_check_board_config(codec, cmi9880_cfg_tbl);
if (spec->board_config < 0) {
- snd_printd(KERN_INFO "hda_codec: Unknown model for CMI9880\n");
- spec->board_config = CMI_FULL_DIG; /* try everything */
+ snd_printdd(KERN_INFO "hda_codec: Unknown model for CMI9880\n");
+ spec->board_config = CMI_AUTO; /* try everything */
}
+ /* copy default DAC NIDs */
+ memcpy(spec->dac_nids, cmi9880_dac_nids, sizeof(spec->dac_nids));
+ spec->num_dacs = 4;
+
switch (spec->board_config) {
case CMI_MINIMAL:
case CMI_MIN_FP:
@@ -599,10 +713,58 @@ static int patch_cmi9880(struct hda_codec *codec)
spec->input_mux = &cmi9880_no_line_mux;
spec->multiout.dig_out_nid = CMI_DIG_OUT_NID;
break;
+ case CMI_AUTO:
+ {
+ unsigned int port_e, port_f, port_g, port_h;
+ unsigned int port_spdifi, port_spdifo;
+ struct auto_pin_cfg cfg;
+
+ /* collect pin default configuration */
+ port_e = snd_hda_codec_read(codec, 0x0f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+ port_f = snd_hda_codec_read(codec, 0x10, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+ spec->front_panel = 1;
+ if (get_defcfg_connect(port_e) == AC_JACK_PORT_NONE ||
+ get_defcfg_connect(port_f) == AC_JACK_PORT_NONE) {
+ port_g = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+ port_h = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+ spec->surr_switch = 1;
+ /* no front panel */
+ if (get_defcfg_connect(port_g) == AC_JACK_PORT_NONE ||
+ get_defcfg_connect(port_h) == AC_JACK_PORT_NONE) {
+ /* no optional rear panel */
+ spec->board_config = CMI_MINIMAL;
+ spec->front_panel = 0;
+ spec->num_ch_modes = 2;
+ } else {
+ spec->board_config = CMI_MIN_FP;
+ spec->num_ch_modes = 3;
+ }
+ spec->channel_modes = cmi9880_channel_modes;
+ spec->input_mux = &cmi9880_basic_mux;
+ spec->multiout.max_channels = cmi9880_channel_modes[0].channels;
+ } else {
+ spec->input_mux = &cmi9880_basic_mux;
+ port_spdifi = snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+ port_spdifo = snd_hda_codec_read(codec, 0x12, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+ if (get_defcfg_connect(port_spdifo) != AC_JACK_PORT_NONE)
+ spec->multiout.dig_out_nid = CMI_DIG_OUT_NID;
+ if (get_defcfg_connect(port_spdifi) != AC_JACK_PORT_NONE)
+ spec->dig_in_nid = CMI_DIG_IN_NID;
+ spec->multiout.max_channels = 8;
+ }
+ snd_hda_parse_pin_def_config(codec, &cfg);
+ if (cfg.line_outs) {
+ spec->multiout.max_channels = cfg.line_outs * 2;
+ cmi9880_fill_multi_dac_nids(codec, &cfg);
+ cmi9880_fill_multi_init(codec, &cfg);
+ } else
+ snd_printd("patch_cmedia: cannot detect association in defcfg\n");
+ break;
+ }
}
- spec->multiout.num_dacs = 4;
- spec->multiout.dac_nids = cmi9880_dac_nids;
+ spec->multiout.num_dacs = spec->num_dacs;
+ spec->multiout.dac_nids = spec->dac_nids;
spec->adc_nids = cmi9880_adc_nids;
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 17c5062423a..bab89843d85 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -33,38 +33,73 @@
/* ALC880 board config type */
enum {
- ALC880_MINIMAL,
ALC880_3ST,
ALC880_3ST_DIG,
ALC880_5ST,
ALC880_5ST_DIG,
ALC880_W810,
+ ALC880_Z71V,
+ ALC880_AUTO,
+ ALC880_6ST_DIG,
+ ALC880_F1734,
+ ALC880_ASUS,
+ ALC880_ASUS_DIG,
+ ALC880_ASUS_W1V,
+ ALC880_UNIWILL_DIG,
+#ifdef CONFIG_SND_DEBUG
+ ALC880_TEST,
+#endif
+ ALC880_MODEL_LAST /* last tag */
+};
+
+/* ALC260 models */
+enum {
+ ALC260_BASIC,
+ ALC260_HP,
+ ALC260_MODEL_LAST /* last tag */
};
+/* amp values */
+#define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8))
+#define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8))
+#define AMP_OUT_MUTE 0xb080
+#define AMP_OUT_UNMUTE 0xb000
+#define AMP_OUT_ZERO 0xb000
+/* pinctl values */
+#define PIN_IN 0x20
+#define PIN_VREF80 0x24
+#define PIN_VREF50 0x21
+#define PIN_OUT 0x40
+#define PIN_HP 0xc0
+
struct alc_spec {
/* codec parameterization */
- unsigned int front_panel: 1;
-
- snd_kcontrol_new_t* mixers[2];
+ snd_kcontrol_new_t *mixers[3]; /* mixer arrays */
unsigned int num_mixers;
- struct hda_verb *init_verbs;
+ const struct hda_verb *init_verbs[3]; /* initialization verbs
+ * don't forget NULL termination!
+ */
+ unsigned int num_init_verbs;
- char* stream_name_analog;
+ char *stream_name_analog; /* analog PCM stream */
struct hda_pcm_stream *stream_analog_playback;
struct hda_pcm_stream *stream_analog_capture;
- char* stream_name_digital;
+ char *stream_name_digital; /* digital PCM stream */
struct hda_pcm_stream *stream_digital_playback;
struct hda_pcm_stream *stream_digital_capture;
/* playback */
- struct hda_multi_out multiout;
+ struct hda_multi_out multiout; /* playback set-up
+ * max_channels, dacs must be set
+ * dig_out_nid and hp_nid are optional
+ */
/* capture */
unsigned int num_adc_nids;
hda_nid_t *adc_nids;
- hda_nid_t dig_in_nid;
+ hda_nid_t dig_in_nid; /* digital-in NID; optional */
/* capture source */
const struct hda_input_mux *input_mux;
@@ -75,61 +110,17 @@ struct alc_spec {
int num_channel_mode;
/* PCM information */
- struct hda_pcm pcm_rec[2];
-};
-
-/* DAC/ADC assignment */
-
-static hda_nid_t alc880_dac_nids[4] = {
- /* front, rear, clfe, rear_surr */
- 0x02, 0x05, 0x04, 0x03
-};
-
-static hda_nid_t alc880_w810_dac_nids[3] = {
- /* front, rear/surround, clfe */
- 0x02, 0x03, 0x04
-};
-
-static hda_nid_t alc880_adc_nids[3] = {
- /* ADC0-2 */
- 0x07, 0x08, 0x09,
-};
-
-#define ALC880_DIGOUT_NID 0x06
-#define ALC880_DIGIN_NID 0x0a
+ struct hda_pcm pcm_rec[2]; /* used in alc_build_pcms() */
-static hda_nid_t alc260_dac_nids[1] = {
- /* front */
- 0x02,
-};
+ struct semaphore bind_mutex; /* for bound controls */
-static hda_nid_t alc260_adc_nids[2] = {
- /* ADC0-1 */
- 0x04, 0x05,
+ /* dynamic controls, init_verbs and input_mux */
+ struct auto_pin_cfg autocfg;
+ unsigned int num_kctl_alloc, num_kctl_used;
+ snd_kcontrol_new_t *kctl_alloc;
+ struct hda_input_mux private_imux;
};
-#define ALC260_DIGOUT_NID 0x03
-#define ALC260_DIGIN_NID 0x06
-
-static struct hda_input_mux alc880_capture_source = {
- .num_items = 4,
- .items = {
- { "Mic", 0x0 },
- { "Front Mic", 0x3 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- },
-};
-
-static struct hda_input_mux alc260_capture_source = {
- .num_items = 4,
- .items = {
- { "Mic", 0x0 },
- { "Front Mic", 0x1 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- },
-};
/*
* input MUX handling
@@ -160,6 +151,7 @@ static int alc_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon
spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
}
+
/*
* channel mode setting
*/
@@ -168,135 +160,18 @@ struct alc_channel_mode {
const struct hda_verb *sequence;
};
-
-/*
- * channel source setting (2/6 channel selection for 3-stack)
- */
-
-/*
- * set the path ways for 2 channel output
- * need to set the codec line out and mic 1 pin widgets to inputs
- */
-static struct hda_verb alc880_threestack_ch2_init[] = {
- /* set pin widget 1Ah (line in) for input */
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
- /* set pin widget 18h (mic1) for input, for mic also enable the vref */
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
- /* mute the output for Line In PW */
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
- /* mute for Mic1 PW */
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
- { } /* end */
-};
-
-/*
- * 6ch mode
- * need to set the codec line out and mic 1 pin widgets to outputs
- */
-static struct hda_verb alc880_threestack_ch6_init[] = {
- /* set pin widget 1Ah (line in) for output */
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
- /* set pin widget 18h (mic1) for output */
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
- /* unmute the output for Line In PW */
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
- /* unmute for Mic1 PW */
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
- /* for rear channel output using Line In 1
- * set select widget connection (nid = 0x12) - to summer node
- * for rear NID = 0x0f...offset 3 in connection list
- */
- { 0x12, AC_VERB_SET_CONNECT_SEL, 0x3 },
- /* for Mic1 - retask for center/lfe */
- /* set select widget connection (nid = 0x10) - to summer node for
- * front CLFE NID = 0x0e...offset 2 in connection list
- */
- { 0x10, AC_VERB_SET_CONNECT_SEL, 0x2 },
- { } /* end */
-};
-
-static struct alc_channel_mode alc880_threestack_modes[2] = {
- { 2, alc880_threestack_ch2_init },
- { 6, alc880_threestack_ch6_init },
-};
-
-
-/*
- * channel source setting (6/8 channel selection for 5-stack)
- */
-
-/* set the path ways for 6 channel output
- * need to set the codec line out and mic 1 pin widgets to inputs
- */
-static struct hda_verb alc880_fivestack_ch6_init[] = {
- /* set pin widget 1Ah (line in) for input */
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
- /* mute the output for Line In PW */
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
- { } /* end */
-};
-
-/* need to set the codec line out and mic 1 pin widgets to outputs */
-static struct hda_verb alc880_fivestack_ch8_init[] = {
- /* set pin widget 1Ah (line in) for output */
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
- /* unmute the output for Line In PW */
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
- /* output for surround channel output using Line In 1 */
- /* set select widget connection (nid = 0x12) - to summer node
- * for surr_rear NID = 0x0d...offset 1 in connection list
- */
- { 0x12, AC_VERB_SET_CONNECT_SEL, 0x1 },
- { } /* end */
-};
-
-static struct alc_channel_mode alc880_fivestack_modes[2] = {
- { 6, alc880_fivestack_ch6_init },
- { 8, alc880_fivestack_ch8_init },
-};
-
-/*
- * channel source setting for W810 system
- *
- * W810 has rear IO for:
- * Front (DAC 02)
- * Surround (DAC 03)
- * Center/LFE (DAC 04)
- * Digital out (06)
- *
- * The system also has a pair of internal speakers, and a headphone jack.
- * These are both connected to Line2 on the codec, hence to DAC 02.
- *
- * There is a variable resistor to control the speaker or headphone
- * volume. This is a hardware-only device without a software API.
- *
- * Plugging headphones in will disable the internal speakers. This is
- * implemented in hardware, not via the driver using jack sense. In
- * a similar fashion, plugging into the rear socket marked "front" will
- * disable both the speakers and headphones.
- *
- * For input, there's a microphone jack, and an "audio in" jack.
- * These may not do anything useful with this driver yet, because I
- * haven't setup any initialization verbs for these yet...
- */
-
-static struct alc_channel_mode alc880_w810_modes[1] = {
- { 6, NULL }
-};
-
-/*
- */
static int alc880_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct alc_spec *spec = codec->spec;
+ int items = kcontrol->private_value ? (int)kcontrol->private_value : 2;
snd_assert(spec->channel_mode, return -ENXIO);
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
- uinfo->value.enumerated.items = 2;
- if (uinfo->value.enumerated.item >= 2)
- uinfo->value.enumerated.item = 1;
+ uinfo->value.enumerated.items = items;
+ if (uinfo->value.enumerated.item >= items)
+ uinfo->value.enumerated.item = items - 1;
sprintf(uinfo->value.enumerated.name, "%dch",
spec->channel_mode[uinfo->value.enumerated.item].channels);
return 0;
@@ -306,10 +181,16 @@ static int alc880_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct alc_spec *spec = codec->spec;
+ int items = kcontrol->private_value ? (int)kcontrol->private_value : 2;
+ int i;
snd_assert(spec->channel_mode, return -ENXIO);
- ucontrol->value.enumerated.item[0] =
- (spec->multiout.max_channels == spec->channel_mode[0].channels) ? 0 : 1;
+ for (i = 0; i < items; i++) {
+ if (spec->multiout.max_channels == spec->channel_mode[i].channels) {
+ ucontrol->value.enumerated.item[0] = i;
+ break;
+ }
+ }
return 0;
}
@@ -335,21 +216,149 @@ static int alc880_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *uc
/*
+ * bound volume controls
+ *
+ * bind multiple volumes (# indices, from 0)
+ */
+
+#define AMP_VAL_IDX_SHIFT 19
+#define AMP_VAL_IDX_MASK (0x0f<<19)
+
+static int alc_bind_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct alc_spec *spec = codec->spec;
+ unsigned long pval;
+
+ down(&spec->bind_mutex);
+ pval = kcontrol->private_value;
+ kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
+ snd_hda_mixer_amp_switch_info(kcontrol, uinfo);
+ kcontrol->private_value = pval;
+ up(&spec->bind_mutex);
+ return 0;
+}
+
+static int alc_bind_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct alc_spec *spec = codec->spec;
+ unsigned long pval;
+
+ down(&spec->bind_mutex);
+ pval = kcontrol->private_value;
+ kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
+ snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
+ kcontrol->private_value = pval;
+ up(&spec->bind_mutex);
+ return 0;
+}
+
+static int alc_bind_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct alc_spec *spec = codec->spec;
+ unsigned long pval;
+ int i, indices, change = 0;
+
+ down(&spec->bind_mutex);
+ pval = kcontrol->private_value;
+ indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
+ for (i = 0; i < indices; i++) {
+ kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) | (i << AMP_VAL_IDX_SHIFT);
+ change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
+ }
+ kcontrol->private_value = pval;
+ up(&spec->bind_mutex);
+ return change;
+}
+
+#define ALC_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \
+ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
+ .info = alc_bind_switch_info, \
+ .get = alc_bind_switch_get, \
+ .put = alc_bind_switch_put, \
+ .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, indices, direction) }
+
+#define ALC_BIND_MUTE(xname,nid,indices,dir) ALC_BIND_MUTE_MONO(xname,nid,3,indices,dir)
+
+
+/*
+ * ALC880 3-stack model
+ *
+ * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
+ * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18, F-Mic = 0x1b
+ * HP = 0x19
*/
-/* 3-stack mode
- * Pin assignment: Front=0x14, Line-In/Rear=0x1a, Mic/CLFE=0x18, F-Mic=0x1b
- * HP=0x19
+static hda_nid_t alc880_dac_nids[4] = {
+ /* front, rear, clfe, rear_surr */
+ 0x02, 0x05, 0x04, 0x03
+};
+
+static hda_nid_t alc880_adc_nids[3] = {
+ /* ADC0-2 */
+ 0x07, 0x08, 0x09,
+};
+
+/* The datasheet says the node 0x07 is connected from inputs,
+ * but it shows zero connection in the real implementation on some devices.
*/
-static snd_kcontrol_new_t alc880_base_mixer[] = {
+static hda_nid_t alc880_adc_nids_alt[2] = {
+ /* ADC1-2 */
+ 0x08, 0x09,
+};
+
+#define ALC880_DIGOUT_NID 0x06
+#define ALC880_DIGIN_NID 0x0a
+
+static struct hda_input_mux alc880_capture_source = {
+ .num_items = 4,
+ .items = {
+ { "Mic", 0x0 },
+ { "Front Mic", 0x3 },
+ { "Line", 0x2 },
+ { "CD", 0x4 },
+ },
+};
+
+/* channel source setting (2/6 channel selection for 3-stack) */
+/* 2ch mode */
+static struct hda_verb alc880_threestack_ch2_init[] = {
+ /* set line-in to input, mute it */
+ { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+ { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+ /* set mic-in to input vref 80%, mute it */
+ { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+ { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+ { } /* end */
+};
+
+/* 6ch mode */
+static struct hda_verb alc880_threestack_ch6_init[] = {
+ /* set line-in to output, unmute it */
+ { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+ { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+ /* set mic-in to output, unmute it */
+ { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+ { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+ { } /* end */
+};
+
+static struct alc_channel_mode alc880_threestack_modes[2] = {
+ { 2, alc880_threestack_ch2_init },
+ { 6, alc880_threestack_ch6_init },
+};
+
+static snd_kcontrol_new_t alc880_three_stack_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Surround Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x18, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x18, 2, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+ ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
@@ -360,12 +369,25 @@ static snd_kcontrol_new_t alc880_base_mixer[] = {
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Channel Mode",
+ .info = alc880_ch_mode_info,
+ .get = alc880_ch_mode_get,
+ .put = alc880_ch_mode_put,
+ },
+ { } /* end */
+};
+
+/* capture mixer elements */
+static snd_kcontrol_new_t alc880_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
/* The multiple "Capture Source" controls confuse alsamixer
@@ -374,65 +396,125 @@ static snd_kcontrol_new_t alc880_base_mixer[] = {
*/
/* .name = "Capture Source", */
.name = "Input Source",
- .count = 2,
+ .count = 3,
.info = alc_mux_enum_info,
.get = alc_mux_enum_get,
.put = alc_mux_enum_put,
},
+ { } /* end */
+};
+
+/* capture mixer elements (in case NID 0x07 not available) */
+static snd_kcontrol_new_t alc880_capture_alt_mixer[] = {
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = alc880_ch_mode_info,
- .get = alc880_ch_mode_get,
- .put = alc880_ch_mode_put,
+ /* The multiple "Capture Source" controls confuse alsamixer
+ * So call somewhat different..
+ * FIXME: the controls appear in the "playback" view!
+ */
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 2,
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
},
{ } /* end */
};
-/* 5-stack mode
- * Pin assignment: Front=0x14, Rear=0x17, CLFE=0x16
- * Line-In/Side=0x1a, Mic=0x18, F-Mic=0x1b, HP=0x19
+
+
+/*
+ * ALC880 5-stack model
+ *
+ * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d), Side = 0x02 (0xd)
+ * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16
+ * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19
*/
+
+/* additional mixers to alc880_three_stack_mixer */
static snd_kcontrol_new_t alc880_five_stack_mixer[] = {
+ HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT),
+ { } /* end */
+};
+
+/* channel source setting (6/8 channel selection for 5-stack) */
+/* 6ch mode */
+static struct hda_verb alc880_fivestack_ch6_init[] = {
+ /* set line-in to input, mute it */
+ { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+ { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+ { } /* end */
+};
+
+/* 8ch mode */
+static struct hda_verb alc880_fivestack_ch8_init[] = {
+ /* set line-in to output, unmute it */
+ { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+ { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+ { } /* end */
+};
+
+static struct alc_channel_mode alc880_fivestack_modes[2] = {
+ { 6, alc880_fivestack_ch6_init },
+ { 8, alc880_fivestack_ch8_init },
+};
+
+
+/*
+ * ALC880 6-stack model
+ *
+ * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e), Side = 0x05 (0x0f)
+ * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17,
+ * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b
+ */
+
+static hda_nid_t alc880_6st_dac_nids[4] = {
+ /* front, rear, clfe, rear_surr */
+ 0x02, 0x03, 0x04, 0x05
+};
+
+static struct hda_input_mux alc880_6stack_capture_source = {
+ .num_items = 4,
+ .items = {
+ { "Mic", 0x0 },
+ { "Front Mic", 0x1 },
+ { "Line", 0x2 },
+ { "CD", 0x4 },
+ },
+};
+
+/* fixed 8-channels */
+static struct alc_channel_mode alc880_sixstack_modes[1] = {
+ { 8, NULL },
+};
+
+static snd_kcontrol_new_t alc880_six_stack_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Surround Playback Switch", 0x17, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Side Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+ ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
+ HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+ HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- /* The multiple "Capture Source" controls confuse alsamixer
- * So call somewhat different..
- * FIXME: the controls appear in the "playback" view!
- */
- /* .name = "Capture Source", */
- .name = "Input Source",
- .count = 2,
- .info = alc_mux_enum_info,
- .get = alc_mux_enum_get,
- .put = alc_mux_enum_put,
- },
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Channel Mode",
@@ -443,39 +525,169 @@ static snd_kcontrol_new_t alc880_five_stack_mixer[] = {
{ } /* end */
};
+
+/*
+ * ALC880 W810 model
+ *
+ * W810 has rear IO for:
+ * Front (DAC 02)
+ * Surround (DAC 03)
+ * Center/LFE (DAC 04)
+ * Digital out (06)
+ *
+ * The system also has a pair of internal speakers, and a headphone jack.
+ * These are both connected to Line2 on the codec, hence to DAC 02.
+ *
+ * There is a variable resistor to control the speaker or headphone
+ * volume. This is a hardware-only device without a software API.
+ *
+ * Plugging headphones in will disable the internal speakers. This is
+ * implemented in hardware, not via the driver using jack sense. In
+ * a similar fashion, plugging into the rear socket marked "front" will
+ * disable both the speakers and headphones.
+ *
+ * For input, there's a microphone jack, and an "audio in" jack.
+ * These may not do anything useful with this driver yet, because I
+ * haven't setup any initialization verbs for these yet...
+ */
+
+static hda_nid_t alc880_w810_dac_nids[3] = {
+ /* front, rear/surround, clfe */
+ 0x02, 0x03, 0x04
+};
+
+/* fixed 6 channels */
+static struct alc_channel_mode alc880_w810_modes[1] = {
+ { 6, NULL }
+};
+
+/* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */
static snd_kcontrol_new_t alc880_w810_base_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+ ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
+ { } /* end */
+};
+
+
+/*
+ * Z710V model
+ *
+ * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d)
+ * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?), Line = 0x1a
+ */
+
+static hda_nid_t alc880_z71v_dac_nids[1] = {
+ 0x02
+};
+#define ALC880_Z71V_HP_DAC 0x03
+
+/* fixed 2 channels */
+static struct alc_channel_mode alc880_2_jack_modes[1] = {
+ { 2, NULL }
+};
+
+static snd_kcontrol_new_t alc880_z71v_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ { } /* end */
+};
+
+
+/* FIXME! */
+/*
+ * ALC880 F1734 model
+ *
+ * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d)
+ * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18
+ */
+
+static hda_nid_t alc880_f1734_dac_nids[1] = {
+ 0x03
+};
+#define ALC880_F1734_HP_DAC 0x02
+
+static snd_kcontrol_new_t alc880_f1734_mixer[] = {
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE("Internal Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ { } /* end */
+};
+
+
+/* FIXME! */
+/*
+ * ALC880 ASUS model
+ *
+ * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
+ * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
+ * Mic = 0x18, Line = 0x1a
+ */
+
+#define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */
+#define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */
+
+static snd_kcontrol_new_t alc880_asus_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+ ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- /* The multiple "Capture Source" controls confuse alsamixer
- * So call somewhat different..
- * FIXME: the controls appear in the "playback" view!
- */
- /* .name = "Capture Source", */
- .name = "Input Source",
- .count = 3,
- .info = alc_mux_enum_info,
- .get = alc_mux_enum_get,
- .put = alc_mux_enum_put,
+ .name = "Channel Mode",
+ .info = alc880_ch_mode_info,
+ .get = alc880_ch_mode_get,
+ .put = alc880_ch_mode_put,
},
{ } /* end */
};
+/* FIXME! */
/*
+ * ALC880 ASUS W1V model
+ *
+ * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
+ * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
+ * Mic = 0x18, Line = 0x1a, Line2 = 0x1b
+ */
+
+/* additional mixers to alc880_asus_mixer */
+static snd_kcontrol_new_t alc880_asus_w1v_mixer[] = {
+ HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT),
+ HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT),
+ { } /* end */
+};
+
+
+/*
+ * build control elements
*/
static int alc_build_controls(struct hda_codec *codec)
{
@@ -502,227 +714,297 @@ static int alc_build_controls(struct hda_codec *codec)
return 0;
}
+
/*
* initialize the codec volumes, etc
*/
-static struct hda_verb alc880_init_verbs_three_stack[] = {
- /* Line In pin widget for input */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
- /* CD pin widget for input */
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
- /* Mic1 (rear panel) pin widget for input and vref at 80% */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
- /* Mic2 (front panel) pin widget for input and vref at 80% */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
- /* unmute amp left and right */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
- /* set connection select to line in (default select for this ADC) */
- {0x07, AC_VERB_SET_CONNECT_SEL, 0x02},
- /* unmute front mixer amp left (volume = 0) */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- /* mute pin widget amp left and right (no gain on this amp) */
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
- /* unmute rear mixer amp left and right (volume = 0) */
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- /* mute pin widget amp left and right (no gain on this amp) */
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
- /* unmute rear mixer amp left and right (volume = 0) */
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- /* mute pin widget amp left and right (no gain on this amp) */
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-
- /* using rear surround as the path for headphone output */
- /* unmute rear surround mixer amp left and right (volume = 0) */
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- /* PASD 3 stack boards use the Mic 2 as the headphone output */
- /* need to program the selector associated with the Mic 2 pin widget to
- * surround path (index 0x01) for headphone output */
- {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
- /* mute pin widget amp left and right (no gain on this amp) */
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
- /* need to retask the Mic 2 pin widget to output */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-
- /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer widget(nid=0x0B)
- * to support the input path of analog loopback
+/*
+ * generic initialization of ADC, input mixers and output mixers
+ */
+static struct hda_verb alc880_volume_init_verbs[] = {
+ /*
+ * Unmute ADC0-2 and set the default input to mic-in
+ */
+ {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+
+ /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+ * mixer widget
* Note: PASD motherboards uses the Line In 2 as the input for front panel
* mic (mic 2)
*/
- /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
- /* unmute CD */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
- /* unmute Line In */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
- /* unmute Mic 1 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- /* unmute Line In 2 (for PASD boards Mic 2) */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
-
- /* Unmute input amps for the line out paths to support the output path of
- * analog loopback
- * the mixers on the output path has 2 inputs, one from the DAC and one
- * from the mixer
+ /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+
+ /*
+ * Set up output mixers (0x0c - 0x0f)
*/
- /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
- /* Unmute Front out path */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
- /* Unmute Surround (used as HP) out path */
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
- /* Unmute C/LFE out path */
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, /* mute */
- /* Unmute rear Surround out path */
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ /* set vol=0 to output mixers */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ /* set up input amps for analog loopback */
+ /* Amp Indices: DAC = 0, mixer = 1 */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
{ }
};
-static struct hda_verb alc880_init_verbs_five_stack[] = {
- /* Line In pin widget for input */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
- /* CD pin widget for input */
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
- /* Mic1 (rear panel) pin widget for input and vref at 80% */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
- /* Mic2 (front panel) pin widget for input and vref at 80% */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
- /* unmute amp left and right */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
- /* set connection select to line in (default select for this ADC) */
- {0x07, AC_VERB_SET_CONNECT_SEL, 0x02},
- /* unmute front mixer amp left and right (volume = 0) */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- /* mute pin widget amp left and right (no gain on this amp) */
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
- /* five rear and clfe */
- /* unmute rear mixer amp left and right (volume = 0) */
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- /* mute pin widget amp left and right (no gain on this amp) */
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
- /* unmute clfe mixer amp left and right (volume = 0) */
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- /* mute pin widget amp left and right (no gain on this amp) */
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-
- /* using rear surround as the path for headphone output */
- /* unmute rear surround mixer amp left and right (volume = 0) */
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- /* PASD 3 stack boards use the Mic 2 as the headphone output */
- /* need to program the selector associated with the Mic 2 pin widget to
- * surround path (index 0x01) for headphone output
- */
- {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
- /* mute pin widget amp left and right (no gain on this amp) */
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
- /* need to retask the Mic 2 pin widget to output */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-
- /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer
- * widget(nid=0x0B) to support the input path of analog loopback
+/*
+ * 3-stack pin configuration:
+ * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
+ */
+static struct hda_verb alc880_pin_3stack_init_verbs[] = {
+ /*
+ * preset connection lists of input pins
+ * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
*/
- /* Note: PASD motherboards uses the Line In 2 as the input for front panel mic (mic 2) */
- /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03*/
- /* unmute CD */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
- /* unmute Line In */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
- /* unmute Mic 1 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- /* unmute Line In 2 (for PASD boards Mic 2) */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
-
- /* Unmute input amps for the line out paths to support the output path of
- * analog loopback
- * the mixers on the output path has 2 inputs, one from the DAC and
- * one from the mixer
+ {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
+ {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+ {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
+
+ /*
+ * Set pin mode and muting
*/
- /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
- /* Unmute Front out path */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
- /* Unmute Surround (used as HP) out path */
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
- /* Unmute C/LFE out path */
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, /* mute */
- /* Unmute rear Surround out path */
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ /* set front pin widgets 0x14 for output */
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* Mic1 (rear panel) pin widget for input and vref at 80% */
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ /* Mic2 (as headphone out) for HP output */
+ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* Line In pin widget for input */
+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ /* Line2 (as front mic) pin widget for input and vref at 80% */
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ /* CD pin widget for input */
+ {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{ }
};
-static struct hda_verb alc880_w810_init_verbs[] = {
- /* front channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
-
- /* front channel selector/amp: input 1: capture mix: muted, (no volume selection) */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
-
- /* front channel selector/amp: output 0: unmuted, max volume */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-
- /* front out pin: muted, (no volume selection) */
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-
- /* front out pin: NOT headphone enable, out enable, vref disabled */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+/*
+ * 5-stack pin configuration:
+ * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19,
+ * line-in/side = 0x1a, f-mic = 0x1b
+ */
+static struct hda_verb alc880_pin_5stack_init_verbs[] = {
+ /*
+ * preset connection lists of input pins
+ * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
+ */
+ {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+ {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */
+ /*
+ * Set pin mode and muting
+ */
+ /* set pin widgets 0x14-0x17 for output */
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ /* unmute pins for output (no gain on this amp) */
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* surround channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+ /* Mic1 (rear panel) pin widget for input and vref at 80% */
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ /* Mic2 (as headphone out) for HP output */
+ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* Line In pin widget for input */
+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ /* Line2 (as front mic) pin widget for input and vref at 80% */
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ /* CD pin widget for input */
+ {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- /* surround channel selector/amp: input 1: capture mix: muted, (no volume selection) */
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
+ { }
+};
- /* surround channel selector/amp: output 0: unmuted, max volume */
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+/*
+ * W810 pin configuration:
+ * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b
+ */
+static struct hda_verb alc880_pin_w810_init_verbs[] = {
+ /* hphone/speaker input selector: front DAC */
+ {0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
- /* surround out pin: muted, (no volume selection) */
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* surround out pin: NOT headphone enable, out enable, vref disabled */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ { }
+};
- /* c/lfe channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+/*
+ * Z71V pin configuration:
+ * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?)
+ */
+static struct hda_verb alc880_pin_z71v_init_verbs[] = {
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* c/lfe channel selector/amp: input 1: capture mix: muted, (no volume selection) */
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- /* c/lfe channel selector/amp: output 0: unmuted, max volume */
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+ { }
+};
- /* c/lfe out pin: muted, (no volume selection) */
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+/*
+ * 6-stack pin configuration:
+ * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18, f-mic = 0x19,
+ * line = 0x1a, HP = 0x1b
+ */
+static struct hda_verb alc880_pin_6stack_init_verbs[] = {
+ {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+
+ { }
+};
- /* c/lfe out pin: NOT headphone enable, out enable, vref disabled */
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+/* FIXME! */
+/*
+ * F1734 pin configuration:
+ * HP = 0x14, speaker-out = 0x15, mic = 0x18
+ */
+static struct hda_verb alc880_pin_f1734_init_verbs[] = {
+ {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
+ {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
+ {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ { }
+};
- /* hphone/speaker input selector: front DAC */
- {0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
+/* FIXME! */
+/*
+ * ASUS pin configuration:
+ * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a
+ */
+static struct hda_verb alc880_pin_asus_init_verbs[] = {
+ {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
+ {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
+ {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+
+ { }
+};
- /* hphone/speaker out pin: muted, (no volume selection) */
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+/* Enable GPIO mask and set output */
+static struct hda_verb alc880_gpio1_init_verbs[] = {
+ {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
+ {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
+ {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
+};
- /* hphone/speaker out pin: NOT headphone enable, out enable, vref disabled */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+/* Enable GPIO mask and set output */
+static struct hda_verb alc880_gpio2_init_verbs[] = {
+ {0x01, AC_VERB_SET_GPIO_MASK, 0x02},
+ {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
+ {0x01, AC_VERB_SET_GPIO_DATA, 0x02},
+};
- { }
-};
+/*
+ */
static int alc_init(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- snd_hda_sequence_write(codec, spec->init_verbs);
+ unsigned int i;
+
+ for (i = 0; i < spec->num_init_verbs; i++)
+ snd_hda_sequence_write(codec, spec->init_verbs[i]);
return 0;
}
@@ -736,9 +1018,8 @@ static int alc_resume(struct hda_codec *codec)
int i;
alc_init(codec);
- for (i = 0; i < spec->num_mixers; i++) {
+ for (i = 0; i < spec->num_mixers; i++)
snd_hda_resume_ctls(codec, spec->mixers[i]);
- }
if (spec->multiout.dig_out_nid)
snd_hda_resume_spdif_out(codec);
if (spec->dig_in_nid)
@@ -830,7 +1111,7 @@ static struct hda_pcm_stream alc880_pcm_analog_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 8,
- .nid = 0x02, /* NID to query formats and rates */
+ /* NID is set in alc_build_pcms */
.ops = {
.open = alc880_playback_pcm_open,
.prepare = alc880_playback_pcm_prepare,
@@ -842,7 +1123,7 @@ static struct hda_pcm_stream alc880_pcm_analog_capture = {
.substreams = 2,
.channels_min = 2,
.channels_max = 2,
- .nid = 0x07, /* NID to query formats and rates */
+ /* NID is set in alc_build_pcms */
.ops = {
.prepare = alc880_capture_pcm_prepare,
.cleanup = alc880_capture_pcm_cleanup
@@ -878,7 +1159,9 @@ static int alc_build_pcms(struct hda_codec *codec)
info->name = spec->stream_name_analog;
info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
+ info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
for (i = 0; i < spec->num_channel_mode; i++) {
@@ -906,7 +1189,18 @@ static int alc_build_pcms(struct hda_codec *codec)
static void alc_free(struct hda_codec *codec)
{
- kfree(codec->spec);
+ struct alc_spec *spec = codec->spec;
+ unsigned int i;
+
+ if (! spec)
+ return;
+
+ if (spec->kctl_alloc) {
+ for (i = 0; i < spec->num_kctl_used; i++)
+ kfree(spec->kctl_alloc[i].name);
+ kfree(spec->kctl_alloc);
+ }
+ kfree(spec);
}
/*
@@ -921,153 +1215,915 @@ static struct hda_codec_ops alc_patch_ops = {
#endif
};
+
+/*
+ * Test configuration for debugging
+ *
+ * Almost all inputs/outputs are enabled. I/O pins can be configured via
+ * enum controls.
+ */
+#ifdef CONFIG_SND_DEBUG
+static hda_nid_t alc880_test_dac_nids[4] = {
+ 0x02, 0x03, 0x04, 0x05
+};
+
+static struct hda_input_mux alc880_test_capture_source = {
+ .num_items = 5,
+ .items = {
+ { "In-1", 0x0 },
+ { "In-2", 0x1 },
+ { "In-3", 0x2 },
+ { "In-4", 0x3 },
+ { "CD", 0x4 },
+ },
+};
+
+static struct alc_channel_mode alc880_test_modes[4] = {
+ { 2, NULL },
+ { 4, NULL },
+ { 6, NULL },
+ { 8, NULL },
+};
+
+static int alc_test_pin_ctl_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+ static char *texts[] = {
+ "N/A", "Line Out", "HP Out",
+ "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"
+ };
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 8;
+ if (uinfo->value.enumerated.item >= 8)
+ uinfo->value.enumerated.item = 7;
+ strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int alc_test_pin_ctl_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
+ unsigned int pin_ctl, item = 0;
+
+ pin_ctl = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+ if (pin_ctl & AC_PINCTL_OUT_EN) {
+ if (pin_ctl & AC_PINCTL_HP_EN)
+ item = 2;
+ else
+ item = 1;
+ } else if (pin_ctl & AC_PINCTL_IN_EN) {
+ switch (pin_ctl & AC_PINCTL_VREFEN) {
+ case AC_PINCTL_VREF_HIZ: item = 3; break;
+ case AC_PINCTL_VREF_50: item = 4; break;
+ case AC_PINCTL_VREF_GRD: item = 5; break;
+ case AC_PINCTL_VREF_80: item = 6; break;
+ case AC_PINCTL_VREF_100: item = 7; break;
+ }
+ }
+ ucontrol->value.enumerated.item[0] = item;
+ return 0;
+}
+
+static int alc_test_pin_ctl_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
+ static unsigned int ctls[] = {
+ 0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN,
+ AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ,
+ AC_PINCTL_IN_EN | AC_PINCTL_VREF_50,
+ AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD,
+ AC_PINCTL_IN_EN | AC_PINCTL_VREF_80,
+ AC_PINCTL_IN_EN | AC_PINCTL_VREF_100,
+ };
+ unsigned int old_ctl, new_ctl;
+
+ old_ctl = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+ new_ctl = ctls[ucontrol->value.enumerated.item[0]];
+ if (old_ctl != new_ctl) {
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl);
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+ ucontrol->value.enumerated.item[0] >= 3 ? 0xb080 : 0xb000);
+ return 1;
+ }
+ return 0;
+}
+
+static int alc_test_pin_src_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+ static char *texts[] = {
+ "Front", "Surround", "CLFE", "Side"
+ };
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 4;
+ if (uinfo->value.enumerated.item >= 4)
+ uinfo->value.enumerated.item = 3;
+ strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int alc_test_pin_src_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
+ unsigned int sel;
+
+ sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0);
+ ucontrol->value.enumerated.item[0] = sel & 3;
+ return 0;
+}
+
+static int alc_test_pin_src_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
+ unsigned int sel;
+
+ sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3;
+ if (ucontrol->value.enumerated.item[0] != sel) {
+ sel = ucontrol->value.enumerated.item[0] & 3;
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, sel);
+ return 1;
+ }
+ return 0;
+}
+
+#define PIN_CTL_TEST(xname,nid) { \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = xname, \
+ .info = alc_test_pin_ctl_info, \
+ .get = alc_test_pin_ctl_get, \
+ .put = alc_test_pin_ctl_put, \
+ .private_value = nid \
+ }
+
+#define PIN_SRC_TEST(xname,nid) { \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = xname, \
+ .info = alc_test_pin_src_info, \
+ .get = alc_test_pin_src_get, \
+ .put = alc_test_pin_src_put, \
+ .private_value = nid \
+ }
+
+static snd_kcontrol_new_t alc880_test_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+ ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+ ALC_BIND_MUTE("CLFE Playback Volume", 0x0e, 2, HDA_INPUT),
+ ALC_BIND_MUTE("Side Playback Volume", 0x0f, 2, HDA_INPUT),
+ PIN_CTL_TEST("Front Pin Mode", 0x14),
+ PIN_CTL_TEST("Surround Pin Mode", 0x15),
+ PIN_CTL_TEST("CLFE Pin Mode", 0x16),
+ PIN_CTL_TEST("Side Pin Mode", 0x17),
+ PIN_CTL_TEST("In-1 Pin Mode", 0x18),
+ PIN_CTL_TEST("In-2 Pin Mode", 0x19),
+ PIN_CTL_TEST("In-3 Pin Mode", 0x1a),
+ PIN_CTL_TEST("In-4 Pin Mode", 0x1b),
+ PIN_SRC_TEST("In-1 Pin Source", 0x18),
+ PIN_SRC_TEST("In-2 Pin Source", 0x19),
+ PIN_SRC_TEST("In-3 Pin Source", 0x1a),
+ PIN_SRC_TEST("In-4 Pin Source", 0x1b),
+ HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT),
+ HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT),
+ HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT),
+ HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT),
+ HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT),
+ HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT),
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Input Source",
+ .count = 2,
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Channel Mode",
+ .info = alc880_ch_mode_info,
+ .get = alc880_ch_mode_get,
+ .put = alc880_ch_mode_put,
+ },
+ { } /* end */
+};
+
+static struct hda_verb alc880_test_init_verbs[] = {
+ /* Unmute inputs of 0x0c - 0x0f */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+ /* Vol output for 0x0c-0x0f */
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ /* Set output pins 0x14-0x17 */
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ /* Unmute output pins 0x14-0x17 */
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* Set input pins 0x18-0x1c */
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ /* Mute input pins 0x18-0x1b */
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ /* ADC set up */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+ /* Analog input/passthru */
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+ { }
+};
+#endif
+
/*
*/
static struct hda_board_config alc880_cfg_tbl[] = {
/* Back 3 jack, front 2 jack */
{ .modelname = "3stack", .config = ALC880_3ST },
- { .pci_vendor = 0x8086, .pci_device = 0xe200, .config = ALC880_3ST },
- { .pci_vendor = 0x8086, .pci_device = 0xe201, .config = ALC880_3ST },
- { .pci_vendor = 0x8086, .pci_device = 0xe202, .config = ALC880_3ST },
- { .pci_vendor = 0x8086, .pci_device = 0xe203, .config = ALC880_3ST },
- { .pci_vendor = 0x8086, .pci_device = 0xe204, .config = ALC880_3ST },
- { .pci_vendor = 0x8086, .pci_device = 0xe205, .config = ALC880_3ST },
- { .pci_vendor = 0x8086, .pci_device = 0xe206, .config = ALC880_3ST },
- { .pci_vendor = 0x8086, .pci_device = 0xe207, .config = ALC880_3ST },
- { .pci_vendor = 0x8086, .pci_device = 0xe208, .config = ALC880_3ST },
- { .pci_vendor = 0x8086, .pci_device = 0xe209, .config = ALC880_3ST },
- { .pci_vendor = 0x8086, .pci_device = 0xe20a, .config = ALC880_3ST },
- { .pci_vendor = 0x8086, .pci_device = 0xe20b, .config = ALC880_3ST },
- { .pci_vendor = 0x8086, .pci_device = 0xe20c, .config = ALC880_3ST },
- { .pci_vendor = 0x8086, .pci_device = 0xe20d, .config = ALC880_3ST },
- { .pci_vendor = 0x8086, .pci_device = 0xe20e, .config = ALC880_3ST },
- { .pci_vendor = 0x8086, .pci_device = 0xe20f, .config = ALC880_3ST },
- { .pci_vendor = 0x8086, .pci_device = 0xe210, .config = ALC880_3ST },
- { .pci_vendor = 0x8086, .pci_device = 0xe211, .config = ALC880_3ST },
- { .pci_vendor = 0x8086, .pci_device = 0xe214, .config = ALC880_3ST },
- { .pci_vendor = 0x8086, .pci_device = 0xe302, .config = ALC880_3ST },
- { .pci_vendor = 0x8086, .pci_device = 0xe303, .config = ALC880_3ST },
- { .pci_vendor = 0x8086, .pci_device = 0xe304, .config = ALC880_3ST },
- { .pci_vendor = 0x8086, .pci_device = 0xe306, .config = ALC880_3ST },
- { .pci_vendor = 0x8086, .pci_device = 0xe307, .config = ALC880_3ST },
- { .pci_vendor = 0x8086, .pci_device = 0xe404, .config = ALC880_3ST },
- { .pci_vendor = 0x8086, .pci_device = 0xa101, .config = ALC880_3ST },
- { .pci_vendor = 0x107b, .pci_device = 0x3031, .config = ALC880_3ST },
- { .pci_vendor = 0x107b, .pci_device = 0x4036, .config = ALC880_3ST },
- { .pci_vendor = 0x107b, .pci_device = 0x4037, .config = ALC880_3ST },
- { .pci_vendor = 0x107b, .pci_device = 0x4038, .config = ALC880_3ST },
- { .pci_vendor = 0x107b, .pci_device = 0x4040, .config = ALC880_3ST },
- { .pci_vendor = 0x107b, .pci_device = 0x4041, .config = ALC880_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe200, .config = ALC880_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe201, .config = ALC880_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe202, .config = ALC880_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe203, .config = ALC880_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe204, .config = ALC880_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe205, .config = ALC880_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe206, .config = ALC880_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe207, .config = ALC880_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe208, .config = ALC880_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe209, .config = ALC880_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20a, .config = ALC880_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20b, .config = ALC880_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20c, .config = ALC880_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20d, .config = ALC880_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20e, .config = ALC880_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20f, .config = ALC880_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe210, .config = ALC880_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe211, .config = ALC880_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe214, .config = ALC880_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe302, .config = ALC880_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe303, .config = ALC880_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe304, .config = ALC880_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe306, .config = ALC880_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe307, .config = ALC880_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe404, .config = ALC880_3ST },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xa101, .config = ALC880_3ST },
+ { .pci_subvendor = 0x107b, .pci_subdevice = 0x3031, .config = ALC880_3ST },
+ { .pci_subvendor = 0x107b, .pci_subdevice = 0x4036, .config = ALC880_3ST },
+ { .pci_subvendor = 0x107b, .pci_subdevice = 0x4037, .config = ALC880_3ST },
+ { .pci_subvendor = 0x107b, .pci_subdevice = 0x4038, .config = ALC880_3ST },
+ { .pci_subvendor = 0x107b, .pci_subdevice = 0x4040, .config = ALC880_3ST },
+ { .pci_subvendor = 0x107b, .pci_subdevice = 0x4041, .config = ALC880_3ST },
/* Back 3 jack, front 2 jack (Internal add Aux-In) */
- { .pci_vendor = 0x1025, .pci_device = 0xe310, .config = ALC880_3ST },
+ { .pci_subvendor = 0x1025, .pci_subdevice = 0xe310, .config = ALC880_3ST },
+ { .pci_subvendor = 0x104d, .pci_subdevice = 0x81d6, .config = ALC880_3ST },
/* Back 3 jack plus 1 SPDIF out jack, front 2 jack */
{ .modelname = "3stack-digout", .config = ALC880_3ST_DIG },
- { .pci_vendor = 0x8086, .pci_device = 0xe308, .config = ALC880_3ST_DIG },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe308, .config = ALC880_3ST_DIG },
/* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/
- { .pci_vendor = 0x8086, .pci_device = 0xe305, .config = ALC880_3ST_DIG },
- { .pci_vendor = 0x8086, .pci_device = 0xd402, .config = ALC880_3ST_DIG },
- { .pci_vendor = 0x1025, .pci_device = 0xe309, .config = ALC880_3ST_DIG },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe305, .config = ALC880_3ST_DIG },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xd402, .config = ALC880_3ST_DIG },
+ { .pci_subvendor = 0x1025, .pci_subdevice = 0xe309, .config = ALC880_3ST_DIG },
/* Back 5 jack, front 2 jack */
{ .modelname = "5stack", .config = ALC880_5ST },
- { .pci_vendor = 0x107b, .pci_device = 0x3033, .config = ALC880_5ST },
- { .pci_vendor = 0x107b, .pci_device = 0x4039, .config = ALC880_5ST },
- { .pci_vendor = 0x107b, .pci_device = 0x3032, .config = ALC880_5ST },
- { .pci_vendor = 0x103c, .pci_device = 0x2a09, .config = ALC880_5ST },
+ { .pci_subvendor = 0x107b, .pci_subdevice = 0x3033, .config = ALC880_5ST },
+ { .pci_subvendor = 0x107b, .pci_subdevice = 0x4039, .config = ALC880_5ST },
+ { .pci_subvendor = 0x107b, .pci_subdevice = 0x3032, .config = ALC880_5ST },
+ { .pci_subvendor = 0x103c, .pci_subdevice = 0x2a09, .config = ALC880_5ST },
+ { .pci_subvendor = 0x1043, .pci_subdevice = 0x814e, .config = ALC880_5ST },
/* Back 5 jack plus 1 SPDIF out jack, front 2 jack */
{ .modelname = "5stack-digout", .config = ALC880_5ST_DIG },
- { .pci_vendor = 0x8086, .pci_device = 0xe224, .config = ALC880_5ST_DIG },
- { .pci_vendor = 0x8086, .pci_device = 0xe400, .config = ALC880_5ST_DIG },
- { .pci_vendor = 0x8086, .pci_device = 0xe401, .config = ALC880_5ST_DIG },
- { .pci_vendor = 0x8086, .pci_device = 0xe402, .config = ALC880_5ST_DIG },
- { .pci_vendor = 0x8086, .pci_device = 0xd400, .config = ALC880_5ST_DIG },
- { .pci_vendor = 0x8086, .pci_device = 0xd401, .config = ALC880_5ST_DIG },
- { .pci_vendor = 0x8086, .pci_device = 0xa100, .config = ALC880_5ST_DIG },
- { .pci_vendor = 0x1565, .pci_device = 0x8202, .config = ALC880_5ST_DIG },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe224, .config = ALC880_5ST_DIG },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe400, .config = ALC880_5ST_DIG },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe401, .config = ALC880_5ST_DIG },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xe402, .config = ALC880_5ST_DIG },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xd400, .config = ALC880_5ST_DIG },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xd401, .config = ALC880_5ST_DIG },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0xa100, .config = ALC880_5ST_DIG },
+ { .pci_subvendor = 0x1565, .pci_subdevice = 0x8202, .config = ALC880_5ST_DIG },
+ { .pci_subvendor = 0x1019, .pci_subdevice = 0xa880, .config = ALC880_5ST_DIG },
+ { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_5ST_DIG },
+ { .pci_subvendor = 0x1695, .pci_subdevice = 0x400d, .config = ALC880_5ST_DIG },
+ { .pci_subvendor = 0x0000, .pci_subdevice = 0x8086, .config = ALC880_5ST_DIG },
{ .modelname = "w810", .config = ALC880_W810 },
- { .pci_vendor = 0x161f, .pci_device = 0x203d, .config = ALC880_W810 },
+ { .pci_subvendor = 0x161f, .pci_subdevice = 0x203d, .config = ALC880_W810 },
+
+ { .modelname = "z71v", .config = ALC880_Z71V },
+ { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_Z71V },
+
+ { .modelname = "6statack-digout", .config = ALC880_6ST_DIG },
+ { .pci_subvendor = 0x2668, .pci_subdevice = 0x8086, .config = ALC880_6ST_DIG },
+ { .pci_subvendor = 0x8086, .pci_subdevice = 0x2668, .config = ALC880_6ST_DIG },
+ { .pci_subvendor = 0x1462, .pci_subdevice = 0x1150, .config = ALC880_6ST_DIG },
+ { .pci_subvendor = 0xe803, .pci_subdevice = 0x1019, .config = ALC880_6ST_DIG },
+
+ { .modelname = "asus", .config = ALC880_ASUS },
+ { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_ASUS_DIG },
+ { .pci_subvendor = 0x1043, .pci_subdevice = 0x1973, .config = ALC880_ASUS_DIG },
+ { .pci_subvendor = 0x1043, .pci_subdevice = 0x19b3, .config = ALC880_ASUS_DIG },
+ { .pci_subvendor = 0x1043, .pci_subdevice = 0x1113, .config = ALC880_ASUS_DIG },
+ { .pci_subvendor = 0x1043, .pci_subdevice = 0x1993, .config = ALC880_ASUS },
+ { .pci_subvendor = 0x1043, .pci_subdevice = 0x10c3, .config = ALC880_ASUS_DIG },
+ { .pci_subvendor = 0x1043, .pci_subdevice = 0x1133, .config = ALC880_ASUS },
+ { .pci_subvendor = 0x1043, .pci_subdevice = 0x1123, .config = ALC880_ASUS_DIG },
+ { .pci_subvendor = 0x1043, .pci_subdevice = 0x1143, .config = ALC880_ASUS },
+ { .pci_subvendor = 0x1043, .pci_subdevice = 0x10b3, .config = ALC880_ASUS_W1V },
+
+ { .modelname = "uniwill", .config = ALC880_UNIWILL_DIG },
+ { .pci_subvendor = 0x1584, .pci_subdevice = 0x9050, .config = ALC880_UNIWILL_DIG },
+
+ { .modelname = "F1734", .config = ALC880_F1734 },
+ { .pci_subvendor = 0x1734, .pci_subdevice = 0x107c, .config = ALC880_F1734 },
+
+#ifdef CONFIG_SND_DEBUG
+ { .modelname = "test", .config = ALC880_TEST },
+#endif
{}
};
+/*
+ * configuration template - to be copied to the spec instance
+ */
+struct alc_config_preset {
+ snd_kcontrol_new_t *mixers[4];
+ const struct hda_verb *init_verbs[4];
+ unsigned int num_dacs;
+ hda_nid_t *dac_nids;
+ hda_nid_t dig_out_nid; /* optional */
+ hda_nid_t hp_nid; /* optional */
+ unsigned int num_adc_nids;
+ hda_nid_t *adc_nids;
+ unsigned int num_channel_mode;
+ const struct alc_channel_mode *channel_mode;
+ const struct hda_input_mux *input_mux;
+};
+
+static struct alc_config_preset alc880_presets[] = {
+ [ALC880_3ST] = {
+ .mixers = { alc880_three_stack_mixer },
+ .init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc880_dac_nids),
+ .dac_nids = alc880_dac_nids,
+ .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
+ .channel_mode = alc880_threestack_modes,
+ .input_mux = &alc880_capture_source,
+ },
+ [ALC880_3ST_DIG] = {
+ .mixers = { alc880_three_stack_mixer },
+ .init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc880_dac_nids),
+ .dac_nids = alc880_dac_nids,
+ .dig_out_nid = ALC880_DIGOUT_NID,
+ .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
+ .channel_mode = alc880_threestack_modes,
+ .input_mux = &alc880_capture_source,
+ },
+ [ALC880_5ST] = {
+ .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer},
+ .init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc880_dac_nids),
+ .dac_nids = alc880_dac_nids,
+ .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
+ .channel_mode = alc880_fivestack_modes,
+ .input_mux = &alc880_capture_source,
+ },
+ [ALC880_5ST_DIG] = {
+ .mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer },
+ .init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc880_dac_nids),
+ .dac_nids = alc880_dac_nids,
+ .dig_out_nid = ALC880_DIGOUT_NID,
+ .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
+ .channel_mode = alc880_fivestack_modes,
+ .input_mux = &alc880_capture_source,
+ },
+ [ALC880_6ST_DIG] = {
+ .mixers = { alc880_six_stack_mixer },
+ .init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
+ .dac_nids = alc880_6st_dac_nids,
+ .dig_out_nid = ALC880_DIGOUT_NID,
+ .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
+ .channel_mode = alc880_sixstack_modes,
+ .input_mux = &alc880_6stack_capture_source,
+ },
+ [ALC880_W810] = {
+ .mixers = { alc880_w810_base_mixer },
+ .init_verbs = { alc880_volume_init_verbs, alc880_pin_w810_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids),
+ .dac_nids = alc880_w810_dac_nids,
+ .dig_out_nid = ALC880_DIGOUT_NID,
+ .num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
+ .channel_mode = alc880_w810_modes,
+ .input_mux = &alc880_capture_source,
+ },
+ [ALC880_Z71V] = {
+ .mixers = { alc880_z71v_mixer },
+ .init_verbs = { alc880_volume_init_verbs, alc880_pin_z71v_init_verbs,
+ alc880_gpio2_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids),
+ .dac_nids = alc880_z71v_dac_nids,
+ .dig_out_nid = ALC880_DIGOUT_NID,
+ .hp_nid = 0x03,
+ .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
+ .channel_mode = alc880_2_jack_modes,
+ .input_mux = &alc880_capture_source,
+ },
+ [ALC880_F1734] = {
+ .mixers = { alc880_f1734_mixer },
+ .init_verbs = { alc880_volume_init_verbs, alc880_pin_f1734_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids),
+ .dac_nids = alc880_f1734_dac_nids,
+ .hp_nid = 0x02,
+ .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
+ .channel_mode = alc880_2_jack_modes,
+ .input_mux = &alc880_capture_source,
+ },
+ [ALC880_ASUS] = {
+ .mixers = { alc880_asus_mixer },
+ .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
+ alc880_gpio1_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
+ .dac_nids = alc880_asus_dac_nids,
+ .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
+ .channel_mode = alc880_asus_modes,
+ .input_mux = &alc880_capture_source,
+ },
+ [ALC880_ASUS_DIG] = {
+ .mixers = { alc880_asus_mixer },
+ .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
+ alc880_gpio1_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
+ .dac_nids = alc880_asus_dac_nids,
+ .dig_out_nid = ALC880_DIGOUT_NID,
+ .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
+ .channel_mode = alc880_asus_modes,
+ .input_mux = &alc880_capture_source,
+ },
+ [ALC880_ASUS_W1V] = {
+ .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer },
+ .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
+ alc880_gpio1_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
+ .dac_nids = alc880_asus_dac_nids,
+ .dig_out_nid = ALC880_DIGOUT_NID,
+ .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
+ .channel_mode = alc880_asus_modes,
+ .input_mux = &alc880_capture_source,
+ },
+ [ALC880_UNIWILL_DIG] = {
+ .mixers = { alc880_asus_mixer },
+ .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
+ .dac_nids = alc880_asus_dac_nids,
+ .dig_out_nid = ALC880_DIGOUT_NID,
+ .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
+ .channel_mode = alc880_asus_modes,
+ .input_mux = &alc880_capture_source,
+ },
+#ifdef CONFIG_SND_DEBUG
+ [ALC880_TEST] = {
+ .mixers = { alc880_test_mixer },
+ .init_verbs = { alc880_test_init_verbs },
+ .num_dacs = ARRAY_SIZE(alc880_test_dac_nids),
+ .dac_nids = alc880_test_dac_nids,
+ .dig_out_nid = ALC880_DIGOUT_NID,
+ .num_channel_mode = ARRAY_SIZE(alc880_test_modes),
+ .channel_mode = alc880_test_modes,
+ .input_mux = &alc880_test_capture_source,
+ },
+#endif
+};
+
+/*
+ * Automatic parse of I/O pins from the BIOS configuration
+ */
+
+#define NUM_CONTROL_ALLOC 32
+#define NUM_VERB_ALLOC 32
+
+enum {
+ ALC_CTL_WIDGET_VOL,
+ ALC_CTL_WIDGET_MUTE,
+ ALC_CTL_BIND_MUTE,
+};
+static snd_kcontrol_new_t alc880_control_templates[] = {
+ HDA_CODEC_VOLUME(NULL, 0, 0, 0),
+ HDA_CODEC_MUTE(NULL, 0, 0, 0),
+ ALC_BIND_MUTE(NULL, 0, 0, 0),
+};
+
+/* add dynamic controls */
+static int add_control(struct alc_spec *spec, int type, const char *name, unsigned long val)
+{
+ snd_kcontrol_new_t *knew;
+
+ if (spec->num_kctl_used >= spec->num_kctl_alloc) {
+ int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
+
+ knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */
+ if (! knew)
+ return -ENOMEM;
+ if (spec->kctl_alloc) {
+ memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc);
+ kfree(spec->kctl_alloc);
+ }
+ spec->kctl_alloc = knew;
+ spec->num_kctl_alloc = num;
+ }
+
+ knew = &spec->kctl_alloc[spec->num_kctl_used];
+ *knew = alc880_control_templates[type];
+ knew->name = kstrdup(name, GFP_KERNEL);
+ if (! knew->name)
+ return -ENOMEM;
+ knew->private_value = val;
+ spec->num_kctl_used++;
+ return 0;
+}
+
+#define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17)
+#define alc880_fixed_pin_idx(nid) ((nid) - 0x14)
+#define alc880_is_multi_pin(nid) ((nid) >= 0x18)
+#define alc880_multi_pin_idx(nid) ((nid) - 0x18)
+#define alc880_is_input_pin(nid) ((nid) >= 0x18)
+#define alc880_input_pin_idx(nid) ((nid) - 0x18)
+#define alc880_idx_to_dac(nid) ((nid) + 0x02)
+#define alc880_dac_to_idx(nid) ((nid) - 0x02)
+#define alc880_idx_to_mixer(nid) ((nid) + 0x0c)
+#define alc880_idx_to_selector(nid) ((nid) + 0x10)
+#define ALC880_PIN_CD_NID 0x1c
+
+/* fill in the dac_nids table from the parsed pin configuration */
+static int alc880_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
+{
+ hda_nid_t nid;
+ int assigned[4];
+ int i, j;
+
+ memset(assigned, 0, sizeof(assigned));
+
+ /* check the pins hardwired to audio widget */
+ for (i = 0; i < cfg->line_outs; i++) {
+ nid = cfg->line_out_pins[i];
+ if (alc880_is_fixed_pin(nid)) {
+ int idx = alc880_fixed_pin_idx(nid);
+ spec->multiout.dac_nids[i] = alc880_dac_to_idx(idx);
+ assigned[idx] = 1;
+ }
+ }
+ /* left pins can be connect to any audio widget */
+ for (i = 0; i < cfg->line_outs; i++) {
+ nid = cfg->line_out_pins[i];
+ if (alc880_is_fixed_pin(nid))
+ continue;
+ /* search for an empty channel */
+ for (j = 0; j < cfg->line_outs; j++) {
+ if (! assigned[j]) {
+ spec->multiout.dac_nids[i] = alc880_idx_to_dac(j);
+ assigned[j] = 1;
+ break;
+ }
+ }
+ }
+ spec->multiout.num_dacs = cfg->line_outs;
+ return 0;
+}
+
+/* add playback controls from the parsed DAC table */
+static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
+{
+ char name[32];
+ static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
+ hda_nid_t nid;
+ int i, err;
+
+ for (i = 0; i < cfg->line_outs; i++) {
+ if (! spec->multiout.dac_nids[i])
+ continue;
+ nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
+ if (i == 2) {
+ /* Center/LFE */
+ if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Center Playback Volume",
+ HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0)
+ return err;
+ if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "LFE Playback Volume",
+ HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
+ return err;
+ if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch",
+ HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT))) < 0)
+ return err;
+ if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch",
+ HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT))) < 0)
+ return err;
+ } else {
+ sprintf(name, "%s Playback Volume", chname[i]);
+ if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
+ HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
+ return err;
+ sprintf(name, "%s Playback Switch", chname[i]);
+ if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
+ HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+/* add playback controls for HP output */
+static int alc880_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin)
+{
+ hda_nid_t nid;
+ int err;
+
+ if (! pin)
+ return 0;
+
+ if (alc880_is_fixed_pin(pin)) {
+ nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
+ if (! spec->multiout.dac_nids[0]) {
+ /* use this as the primary output */
+ spec->multiout.dac_nids[0] = nid;
+ if (! spec->multiout.num_dacs)
+ spec->multiout.num_dacs = 1;
+ } else
+ /* specify the DAC as the extra HP output */
+ spec->multiout.hp_nid = nid;
+ /* control HP volume/switch on the output mixer amp */
+ nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin));
+ if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume",
+ HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
+ return err;
+ if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Headphone Playback Switch",
+ HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
+ return err;
+ } else if (alc880_is_multi_pin(pin)) {
+ /* set manual connection */
+ if (! spec->multiout.dac_nids[0]) {
+ /* use this as the primary output */
+ spec->multiout.dac_nids[0] = alc880_idx_to_dac(alc880_multi_pin_idx(pin));
+ if (! spec->multiout.num_dacs)
+ spec->multiout.num_dacs = 1;
+ }
+ /* we have only a switch on HP-out PIN */
+ if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
+ HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT))) < 0)
+ return err;
+ }
+ return 0;
+}
+
+/* create input playback/capture controls for the given pin */
+static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, const char *ctlname)
+{
+ char name[32];
+ int err, idx;
+
+ sprintf(name, "%s Playback Volume", ctlname);
+ idx = alc880_input_pin_idx(pin);
+ if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
+ HDA_COMPOSE_AMP_VAL(0x0b, 3, idx, HDA_INPUT))) < 0)
+ return err;
+ sprintf(name, "%s Playback Switch", ctlname);
+ if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
+ HDA_COMPOSE_AMP_VAL(0x0b, 3, idx, HDA_INPUT))) < 0)
+ return err;
+ return 0;
+}
+
+/* create playback/capture controls for input pins */
+static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
+{
+ static char *labels[AUTO_PIN_LAST] = {
+ "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
+ };
+ struct hda_input_mux *imux = &spec->private_imux;
+ int i, err;
+
+ for (i = 0; i < AUTO_PIN_LAST; i++) {
+ if (alc880_is_input_pin(cfg->input_pins[i])) {
+ err = new_analog_input(spec, cfg->input_pins[i], labels[i]);
+ if (err < 0)
+ return err;
+ imux->items[imux->num_items].label = labels[i];
+ imux->items[imux->num_items].index = alc880_input_pin_idx(cfg->input_pins[i]);
+ imux->num_items++;
+ }
+ }
+ return 0;
+}
+
+static void alc880_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid, int pin_type,
+ int dac_idx)
+{
+ /* set as output */
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+ /* need the manual connection? */
+ if (alc880_is_multi_pin(nid)) {
+ struct alc_spec *spec = codec->spec;
+ int idx = alc880_multi_pin_idx(nid);
+ snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0,
+ AC_VERB_SET_CONNECT_SEL,
+ alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx]));
+ }
+}
+
+static void alc880_auto_init_multi_out(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ int i;
+
+ for (i = 0; i < spec->autocfg.line_outs; i++) {
+ hda_nid_t nid = spec->autocfg.line_out_pins[i];
+ alc880_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
+ }
+}
+
+static void alc880_auto_init_hp_out(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ hda_nid_t pin;
+
+ pin = spec->autocfg.hp_pin;
+ if (pin) /* connect to front */
+ alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
+}
+
+static void alc880_auto_init_analog_input(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ int i;
+
+ for (i = 0; i < AUTO_PIN_LAST; i++) {
+ hda_nid_t nid = spec->autocfg.input_pins[i];
+ if (alc880_is_input_pin(nid)) {
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+ i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
+ if (nid != ALC880_PIN_CD_NID)
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+ AMP_OUT_MUTE);
+ }
+ }
+}
+
+/* parse the BIOS configuration and set up the alc_spec */
+/* return 1 if successful, 0 if the proper config is not found, or a negative error code */
+static int alc880_parse_auto_config(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ int err;
+
+ if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg)) < 0)
+ return err;
+ if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0)
+ return err;
+ if (! spec->autocfg.line_outs && ! spec->autocfg.hp_pin)
+ return 0; /* can't find valid BIOS pin config */
+ if ((err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
+ (err = alc880_auto_create_hp_ctls(spec, spec->autocfg.hp_pin)) < 0 ||
+ (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
+ return err;
+
+ spec->multiout.max_channels = spec->multiout.num_dacs * 2;
+
+ if (spec->autocfg.dig_out_pin)
+ spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
+ if (spec->autocfg.dig_in_pin)
+ spec->dig_in_nid = ALC880_DIGIN_NID;
+
+ if (spec->kctl_alloc)
+ spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+
+ spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs;
+
+ spec->input_mux = &spec->private_imux;
+
+ return 1;
+}
+
+/* init callback for auto-configuration model -- overriding the default init */
+static int alc880_auto_init(struct hda_codec *codec)
+{
+ alc_init(codec);
+ alc880_auto_init_multi_out(codec);
+ alc880_auto_init_hp_out(codec);
+ alc880_auto_init_analog_input(codec);
+ return 0;
+}
+
+/*
+ * OK, here we have finally the patch for ALC880
+ */
+
static int patch_alc880(struct hda_codec *codec)
{
struct alc_spec *spec;
int board_config;
+ int i, err;
spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
return -ENOMEM;
+ init_MUTEX(&spec->bind_mutex);
codec->spec = spec;
board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl);
- if (board_config < 0) {
- snd_printd(KERN_INFO "hda_codec: Unknown model for ALC880\n");
- board_config = ALC880_MINIMAL;
+ if (board_config < 0 || board_config >= ALC880_MODEL_LAST) {
+ printk(KERN_INFO "hda_codec: Unknown model for ALC880, trying auto-probe from BIOS...\n");
+ board_config = ALC880_AUTO;
}
- switch (board_config) {
- case ALC880_W810:
- spec->mixers[spec->num_mixers] = alc880_w810_base_mixer;
- spec->num_mixers++;
- break;
- case ALC880_5ST:
- case ALC880_5ST_DIG:
- spec->mixers[spec->num_mixers] = alc880_five_stack_mixer;
- spec->num_mixers++;
- break;
- default:
- spec->mixers[spec->num_mixers] = alc880_base_mixer;
- spec->num_mixers++;
- break;
+ if (board_config == ALC880_AUTO) {
+ /* automatic parse from the BIOS config */
+ err = alc880_parse_auto_config(codec);
+ if (err < 0) {
+ alc_free(codec);
+ return err;
+ } else if (! err) {
+ printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS. Using 3-stack mode...\n");
+ board_config = ALC880_3ST;
+ }
}
- switch (board_config) {
- case ALC880_3ST_DIG:
- case ALC880_5ST_DIG:
- case ALC880_W810:
- spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
- break;
- default:
- break;
- }
+ if (board_config != ALC880_AUTO) {
+ /* set up from the preset table */
+ const struct alc_config_preset *preset;
- switch (board_config) {
- case ALC880_3ST:
- case ALC880_3ST_DIG:
- case ALC880_5ST:
- case ALC880_5ST_DIG:
- case ALC880_W810:
- spec->front_panel = 1;
- break;
- default:
- break;
- }
+ preset = &alc880_presets[board_config];
- switch (board_config) {
- case ALC880_5ST:
- case ALC880_5ST_DIG:
- spec->init_verbs = alc880_init_verbs_five_stack;
- spec->channel_mode = alc880_fivestack_modes;
- spec->num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes);
- break;
- case ALC880_W810:
- spec->init_verbs = alc880_w810_init_verbs;
- spec->channel_mode = alc880_w810_modes;
- spec->num_channel_mode = ARRAY_SIZE(alc880_w810_modes);
- break;
- default:
- spec->init_verbs = alc880_init_verbs_three_stack;
- spec->channel_mode = alc880_threestack_modes;
- spec->num_channel_mode = ARRAY_SIZE(alc880_threestack_modes);
- break;
+ for (i = 0; preset->mixers[i]; i++) {
+ snd_assert(spec->num_mixers < ARRAY_SIZE(spec->mixers), break);
+ spec->mixers[spec->num_mixers++] = preset->mixers[i];
+ }
+ for (i = 0; preset->init_verbs[i]; i++) {
+ snd_assert(spec->num_init_verbs < ARRAY_SIZE(spec->init_verbs), break);
+ spec->init_verbs[spec->num_init_verbs++] = preset->init_verbs[i];
+ }
+
+ spec->channel_mode = preset->channel_mode;
+ spec->num_channel_mode = preset->num_channel_mode;
+
+ spec->multiout.max_channels = spec->channel_mode[0].channels;
+
+ spec->multiout.num_dacs = preset->num_dacs;
+ spec->multiout.dac_nids = preset->dac_nids;
+ spec->multiout.dig_out_nid = preset->dig_out_nid;
+ spec->multiout.hp_nid = preset->hp_nid;
+
+ spec->input_mux = preset->input_mux;
+
+ spec->num_adc_nids = preset->num_adc_nids;
+ spec->adc_nids = preset->adc_nids;
}
spec->stream_name_analog = "ALC880 Analog";
@@ -1078,34 +2134,64 @@ static int patch_alc880(struct hda_codec *codec)
spec->stream_digital_playback = &alc880_pcm_digital_playback;
spec->stream_digital_capture = &alc880_pcm_digital_capture;
- spec->multiout.max_channels = spec->channel_mode[0].channels;
-
- switch (board_config) {
- case ALC880_W810:
- spec->multiout.num_dacs = ARRAY_SIZE(alc880_w810_dac_nids);
- spec->multiout.dac_nids = alc880_w810_dac_nids;
- // No dedicated headphone socket - it's shared with built-in speakers.
- break;
- default:
- spec->multiout.num_dacs = ARRAY_SIZE(alc880_dac_nids);
- spec->multiout.dac_nids = alc880_dac_nids;
- spec->multiout.hp_nid = 0x03; /* rear-surround NID */
- break;
+ if (! spec->adc_nids && spec->input_mux) {
+ /* check whether NID 0x07 is valid */
+ unsigned int wcap = snd_hda_param_read(codec, alc880_adc_nids[0],
+ AC_PAR_AUDIO_WIDGET_CAP);
+ wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
+ if (wcap != AC_WID_AUD_IN) {
+ spec->adc_nids = alc880_adc_nids_alt;
+ spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt);
+ spec->mixers[spec->num_mixers] = alc880_capture_alt_mixer;
+ spec->num_mixers++;
+ } else {
+ spec->adc_nids = alc880_adc_nids;
+ spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
+ spec->mixers[spec->num_mixers] = alc880_capture_mixer;
+ spec->num_mixers++;
+ }
}
- spec->input_mux = &alc880_capture_source;
- spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
- spec->adc_nids = alc880_adc_nids;
-
codec->patch_ops = alc_patch_ops;
+ if (board_config == ALC880_AUTO)
+ codec->patch_ops.init = alc880_auto_init;
return 0;
}
+
/*
* ALC260 support
*/
+static hda_nid_t alc260_dac_nids[1] = {
+ /* front */
+ 0x02,
+};
+
+static hda_nid_t alc260_adc_nids[1] = {
+ /* ADC0 */
+ 0x04,
+};
+
+static hda_nid_t alc260_hp_adc_nids[1] = {
+ /* ADC1 */
+ 0x05,
+};
+
+#define ALC260_DIGOUT_NID 0x03
+#define ALC260_DIGIN_NID 0x06
+
+static struct hda_input_mux alc260_capture_source = {
+ .num_items = 4,
+ .items = {
+ { "Mic", 0x0 },
+ { "Front Mic", 0x1 },
+ { "Line", 0x2 },
+ { "CD", 0x4 },
+ },
+};
+
/*
* This is just place-holder, so there's something for alc_build_pcms to look
* at when it calculates the maximum number of channels. ALC260 has no mixer
@@ -1116,11 +2202,9 @@ static struct alc_channel_mode alc260_modes[1] = {
{ 2, NULL },
};
-snd_kcontrol_new_t alc260_base_mixer[] = {
+static snd_kcontrol_new_t alc260_base_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
- /* use LINE2 for the output */
- /* HDA_CODEC_MUTE("Front Playback Switch", 0x0f, 0x0, HDA_OUTPUT), */
- HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
@@ -1132,9 +2216,9 @@ snd_kcontrol_new_t alc260_base_mixer[] = {
HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT),
HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT),
HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x10, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_OUTPUT),
HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
{
@@ -1147,60 +2231,91 @@ snd_kcontrol_new_t alc260_base_mixer[] = {
{ } /* end */
};
+static snd_kcontrol_new_t alc260_hp_mixer[] = {
+ HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
+ HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
+ HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
+ HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
+ HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
+ HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Source",
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
+ },
+ { } /* end */
+};
+
static struct hda_verb alc260_init_verbs[] = {
/* Line In pin widget for input */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
/* CD pin widget for input */
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
/* Mic1 (rear panel) pin widget for input and vref at 80% */
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+ {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
/* Mic2 (front panel) pin widget for input and vref at 80% */
- {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+ {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
/* LINE-2 is used for line-out in rear */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
/* select line-out */
{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
/* LINE-OUT pin */
- {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
/* enable HP */
- {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+ {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
/* enable Mono */
- {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
- /* unmute amp left and right */
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+ {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ /* mute capture amp left and right */
+ {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
/* set connection select to line in (default select for this ADC) */
{0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
- /* unmute Line-Out mixer amp left and right (volume = 0) */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- /* mute pin widget amp left and right (no gain on this amp) */
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- /* unmute HP mixer amp left and right (volume = 0) */
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- /* mute pin widget amp left and right (no gain on this amp) */
- {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
- /* unmute Mono mixer amp left and right (volume = 0) */
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- /* mute pin widget amp left and right (no gain on this amp) */
- {0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
- /* mute LINE-2 out */
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+ /* mute capture amp left and right */
+ {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ /* set connection select to line in (default select for this ADC) */
+ {0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
+ /* set vol=0 Line-Out mixer amp left and right */
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ /* unmute pin widget amp left and right (no gain on this amp) */
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* set vol=0 HP mixer amp left and right */
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ /* unmute pin widget amp left and right (no gain on this amp) */
+ {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* set vol=0 Mono mixer amp left and right */
+ {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ /* unmute pin widget amp left and right (no gain on this amp) */
+ {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+ /* unmute LINE-2 out pin */
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
- /* unmute CD */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
- /* unmute Line In */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
- /* unmute Mic */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ /* mute CD */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+ /* mute Line In */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+ /* mute Mic */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
- /* Unmute Front out path */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
- /* Unmute Headphone out path */
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
- /* Unmute Mono out path */
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ /* mute Front out path */
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ /* mute Headphone out path */
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+ /* mute Mono out path */
+ {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
{ }
};
@@ -1208,30 +2323,52 @@ static struct hda_pcm_stream alc260_pcm_analog_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
- .nid = 0x2,
};
static struct hda_pcm_stream alc260_pcm_analog_capture = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
- .nid = 0x4,
+};
+
+static struct hda_board_config alc260_cfg_tbl[] = {
+ { .modelname = "hp", .config = ALC260_HP },
+ { .pci_subvendor = 0x103c, .config = ALC260_HP },
+ {}
};
static int patch_alc260(struct hda_codec *codec)
{
struct alc_spec *spec;
+ int board_config;
spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
return -ENOMEM;
+ init_MUTEX(&spec->bind_mutex);
codec->spec = spec;
- spec->mixers[spec->num_mixers] = alc260_base_mixer;
- spec->num_mixers++;
+ board_config = snd_hda_check_board_config(codec, alc260_cfg_tbl);
+ if (board_config < 0 || board_config >= ALC260_MODEL_LAST) {
+ snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260\n");
+ board_config = ALC260_BASIC;
+ }
+
+ switch (board_config) {
+ case ALC260_HP:
+ spec->mixers[spec->num_mixers] = alc260_hp_mixer;
+ spec->num_mixers++;
+ break;
+ default:
+ spec->mixers[spec->num_mixers] = alc260_base_mixer;
+ spec->num_mixers++;
+ break;
+ }
+
+ spec->init_verbs[0] = alc260_init_verbs;
+ spec->num_init_verbs = 1;
- spec->init_verbs = alc260_init_verbs;
spec->channel_mode = alc260_modes;
spec->num_channel_mode = ARRAY_SIZE(alc260_modes);
@@ -1244,14 +2381,23 @@ static int patch_alc260(struct hda_codec *codec)
spec->multiout.dac_nids = alc260_dac_nids;
spec->input_mux = &alc260_capture_source;
- spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
- spec->adc_nids = alc260_adc_nids;
+ switch (board_config) {
+ case ALC260_HP:
+ spec->num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids);
+ spec->adc_nids = alc260_hp_adc_nids;
+ break;
+ default:
+ spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
+ spec->adc_nids = alc260_adc_nids;
+ break;
+ }
codec->patch_ops = alc_patch_ops;
return 0;
}
+
/*
* ALC882 support
*
@@ -1324,15 +2470,15 @@ static int alc882_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *u
*/
static snd_kcontrol_new_t alc882_base_mixer[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+ ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_OUTPUT),
HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Side Playback Switch", 0x17, 0x0, HDA_OUTPUT),
+ ALC_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
@@ -1364,89 +2510,80 @@ static snd_kcontrol_new_t alc882_base_mixer[] = {
static struct hda_verb alc882_init_verbs[] = {
/* Front mixer: unmute input/output amp left and right (volume = 0) */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
/* Rear mixer */
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
/* CLFE mixer */
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
/* Side mixer */
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-
- /* Front Pin: to output mode */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
- /* Front Pin: mute amp left and right (no volume) */
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
- /* select Front mixer (0x0c, index 0) */
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+
+ /* Front Pin: output 0 (0x0c) */
+ {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* Rear Pin */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
- /* Rear Pin: mute amp left and right (no volume) */
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
- /* select Rear mixer (0x0d, index 1) */
+ /* Rear Pin: output 1 (0x0d) */
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
- /* CLFE Pin */
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
- /* CLFE Pin: mute amp left and right (no volume) */
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
- /* select CLFE mixer (0x0e, index 2) */
+ /* CLFE Pin: output 2 (0x0e) */
+ {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
- /* Side Pin */
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
- /* Side Pin: mute amp left and right (no volume) */
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
- /* select Side mixer (0x0f, index 3) */
+ /* Side Pin: output 3 (0x0f) */
+ {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+ {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
- /* Headphone Pin */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
- /* Headphone Pin: mute amp left and right (no volume) */
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
- /* select Front mixer (0x0c, index 0) */
+ /* Mic (rear) pin: input vref at 80% */
+ {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ /* Front Mic pin: input vref at 80% */
+ {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+ {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ /* Line In pin: input */
+ {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+ {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+ /* Line-2 In: Headphone output (output 0 - 0x0c) */
+ {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+ {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* Mic (rear) pin widget for input and vref at 80% */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
- /* Front Mic pin widget for input and vref at 80% */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
- /* Line In pin widget for input */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
/* CD pin widget for input */
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+ {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
/* FIXME: use matrix-type input source selection */
/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/* Input mixer2 */
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
/* Input mixer3 */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
- /* ADC1: unmute amp left and right */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
- /* ADC2: unmute amp left and right */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
- /* ADC3: unmute amp left and right */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
-
- /* Unmute front loopback */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
- /* Unmute rear loopback */
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
- /* Mute CLFE loopback */
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
- /* Unmute side loopback */
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+ {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+ /* ADC1: mute amp left and right */
+ {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+ /* ADC2: mute amp left and right */
+ {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+ /* ADC3: mute amp left and right */
+ {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+ {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
{ }
};
@@ -1459,6 +2596,7 @@ static int patch_alc882(struct hda_codec *codec)
if (spec == NULL)
return -ENOMEM;
+ init_MUTEX(&spec->bind_mutex);
codec->spec = spec;
spec->mixers[spec->num_mixers] = alc882_base_mixer;
@@ -1466,8 +2604,9 @@ static int patch_alc882(struct hda_codec *codec)
spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
spec->dig_in_nid = ALC880_DIGIN_NID;
- spec->front_panel = 1;
- spec->init_verbs = alc882_init_verbs;
+ spec->init_verbs[0] = alc882_init_verbs;
+ spec->num_init_verbs = 1;
+
spec->channel_mode = alc882_ch_modes;
spec->num_channel_mode = ARRAY_SIZE(alc882_ch_modes);
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
new file mode 100644
index 00000000000..013be2ea513
--- /dev/null
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -0,0 +1,666 @@
+/*
+ * Universal Interface for Intel High Definition Audio Codec
+ *
+ * HD audio interface patch for SigmaTel STAC92xx
+ *
+ * Copyright (c) 2005 Embedded Alley Solutions, Inc.
+ * <matt@embeddedalley.com>
+ *
+ * Based on patch_cmedia.c and patch_realtek.c
+ * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *
+ * This driver 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 driver 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 <sound/driver.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <sound/core.h>
+#include "hda_codec.h"
+#include "hda_local.h"
+
+#undef STAC_TEST
+
+struct sigmatel_spec {
+ /* playback */
+ struct hda_multi_out multiout;
+ hda_nid_t playback_nid;
+
+ /* capture */
+ hda_nid_t *adc_nids;
+ unsigned int num_adcs;
+ hda_nid_t *mux_nids;
+ unsigned int num_muxes;
+ hda_nid_t capture_nid;
+ hda_nid_t dig_in_nid;
+
+ /* power management*/
+ hda_nid_t *pstate_nids;
+ unsigned int num_pstates;
+
+ /* pin widgets */
+ hda_nid_t *pin_nids;
+ unsigned int num_pins;
+#ifdef STAC_TEST
+ unsigned int *pin_configs;
+#endif
+
+ /* codec specific stuff */
+ struct hda_verb *init;
+ snd_kcontrol_new_t *mixer;
+
+ /* capture source */
+ struct hda_input_mux input_mux;
+ char input_labels[HDA_MAX_NUM_INPUTS][16];
+ unsigned int cur_mux[2];
+
+ /* channel mode */
+ unsigned int num_ch_modes;
+ unsigned int cur_ch_mode;
+ const struct sigmatel_channel_mode *channel_modes;
+
+ struct hda_pcm pcm_rec[1]; /* PCM information */
+};
+
+static hda_nid_t stac9200_adc_nids[1] = {
+ 0x03,
+};
+
+static hda_nid_t stac9200_mux_nids[1] = {
+ 0x0c,
+};
+
+static hda_nid_t stac9200_dac_nids[1] = {
+ 0x02,
+};
+
+static hda_nid_t stac9200_pstate_nids[3] = {
+ 0x01, 0x02, 0x03,
+};
+
+static hda_nid_t stac9200_pin_nids[8] = {
+ 0x08, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
+};
+
+static hda_nid_t stac922x_adc_nids[2] = {
+ 0x06, 0x07,
+};
+
+static hda_nid_t stac922x_mux_nids[2] = {
+ 0x12, 0x13,
+};
+
+static hda_nid_t stac922x_dac_nids[4] = {
+ 0x02, 0x03, 0x04, 0x05,
+};
+
+static hda_nid_t stac922x_pstate_nids[8] = {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x11,
+};
+
+static hda_nid_t stac922x_pin_nids[10] = {
+ 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+ 0x0f, 0x10, 0x11, 0x15, 0x1b,
+};
+
+static int stac92xx_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct sigmatel_spec *spec = codec->spec;
+ return snd_hda_input_mux_info(&spec->input_mux, uinfo);
+}
+
+static int stac92xx_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct sigmatel_spec *spec = codec->spec;
+ unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+
+ ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
+ return 0;
+}
+
+static int stac92xx_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct sigmatel_spec *spec = codec->spec;
+ unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+
+ return snd_hda_input_mux_put(codec, &spec->input_mux, ucontrol,
+ spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]);
+}
+
+static struct hda_verb stac9200_ch2_init[] = {
+ /* set dac0mux for dac converter */
+ { 0x07, 0x701, 0x00},
+ {}
+};
+
+static struct hda_verb stac922x_ch2_init[] = {
+ /* set master volume and direct control */
+ { 0x16, 0x70f, 0xff},
+ {}
+};
+
+struct sigmatel_channel_mode {
+ unsigned int channels;
+ const struct hda_verb *sequence;
+};
+
+static snd_kcontrol_new_t stac9200_mixer[] = {
+ HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Input Source",
+ .count = 1,
+ .info = stac92xx_mux_enum_info,
+ .get = stac92xx_mux_enum_get,
+ .put = stac92xx_mux_enum_put,
+ },
+ HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME("Input Mux Volume", 0x0c, 0, HDA_OUTPUT),
+ { } /* end */
+};
+
+static snd_kcontrol_new_t stac922x_mixer[] = {
+ HDA_CODEC_VOLUME("PCM Playback Volume", 0x2, 0x0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("PCM Playback Switch", 0x2, 0x0, HDA_OUTPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Input Source",
+ .count = 1,
+ .info = stac92xx_mux_enum_info,
+ .get = stac92xx_mux_enum_get,
+ .put = stac92xx_mux_enum_put,
+ },
+ HDA_CODEC_VOLUME("Capture Volume", 0x17, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x17, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Mux Capture Volume", 0x12, 0x0, HDA_OUTPUT),
+ { } /* end */
+};
+
+static int stac92xx_build_controls(struct hda_codec *codec)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ int err;
+
+ err = snd_hda_add_new_ctls(codec, spec->mixer);
+ if (err < 0)
+ return err;
+ if (spec->multiout.dig_out_nid) {
+ err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
+ if (err < 0)
+ return err;
+ }
+ if (spec->dig_in_nid) {
+ err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
+ if (err < 0)
+ return err;
+ }
+ return 0;
+}
+
+#ifdef STAC_TEST
+static unsigned int stac9200_pin_configs[8] = {
+ 0x01c47010, 0x01447010, 0x0221401f, 0x01114010,
+ 0x02a19020, 0x01a19021, 0x90100140, 0x01813122,
+};
+
+static unsigned int stac922x_pin_configs[14] = {
+ 0x40000100, 0x40000100, 0x40000100, 0x01114010,
+ 0x01813122, 0x40000100, 0x01447010, 0x01c47010,
+ 0x40000100, 0x40000100,
+};
+
+static void stac92xx_set_config_regs(struct hda_codec *codec)
+{
+ int i;
+ struct sigmatel_spec *spec = codec->spec;
+ unsigned int pin_cfg;
+
+ for (i=0; i < spec->num_pins; i++) {
+ snd_hda_codec_write(codec, spec->pin_nids[i], 0,
+ AC_VERB_SET_CONFIG_DEFAULT_BYTES_0,
+ spec->pin_configs[i] & 0x000000ff);
+ snd_hda_codec_write(codec, spec->pin_nids[i], 0,
+ AC_VERB_SET_CONFIG_DEFAULT_BYTES_1,
+ (spec->pin_configs[i] & 0x0000ff00) >> 8);
+ snd_hda_codec_write(codec, spec->pin_nids[i], 0,
+ AC_VERB_SET_CONFIG_DEFAULT_BYTES_2,
+ (spec->pin_configs[i] & 0x00ff0000) >> 16);
+ snd_hda_codec_write(codec, spec->pin_nids[i], 0,
+ AC_VERB_SET_CONFIG_DEFAULT_BYTES_3,
+ spec->pin_configs[i] >> 24);
+ pin_cfg = snd_hda_codec_read(codec, spec->pin_nids[i], 0,
+ AC_VERB_GET_CONFIG_DEFAULT,
+ 0x00);
+ printk("pin nid %2.2x pin config %8.8x\n", spec->pin_nids[i], pin_cfg);
+ }
+}
+#endif
+
+static int stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, unsigned int value)
+{
+ unsigned int pin_ctl;
+
+ pin_ctl = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_PIN_WIDGET_CONTROL,
+ 0x00);
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+ pin_ctl | value);
+
+ return 0;
+}
+
+static int stac92xx_set_vref(struct hda_codec *codec, hda_nid_t nid)
+{
+ unsigned int vref_caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP) >> AC_PINCAP_VREF_SHIFT;
+ unsigned int vref_ctl = AC_PINCTL_VREF_HIZ;
+
+ if (vref_caps & AC_PINCAP_VREF_100)
+ vref_ctl = AC_PINCTL_VREF_100;
+ else if (vref_caps & AC_PINCAP_VREF_80)
+ vref_ctl = AC_PINCTL_VREF_80;
+ else if (vref_caps & AC_PINCAP_VREF_50)
+ vref_ctl = AC_PINCTL_VREF_50;
+ else if (vref_caps & AC_PINCAP_VREF_GRD)
+ vref_ctl = AC_PINCTL_VREF_GRD;
+
+ stac92xx_set_pinctl(codec, nid, vref_ctl);
+
+ return 0;
+}
+
+/*
+ * retrieve the default device type from the default config value
+ */
+#define get_defcfg_type(cfg) ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
+#define get_defcfg_location(cfg) ((cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT)
+
+static int stac92xx_config_pin(struct hda_codec *codec, hda_nid_t nid, unsigned int pin_cfg)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ u32 location = get_defcfg_location(pin_cfg);
+ char *label;
+ const char *type = NULL;
+ int ainput = 0;
+
+ switch(get_defcfg_type(pin_cfg)) {
+ case AC_JACK_HP_OUT:
+ /* Enable HP amp */
+ stac92xx_set_pinctl(codec, nid, AC_PINCTL_HP_EN);
+ /* Fall through */
+ case AC_JACK_SPDIF_OUT:
+ case AC_JACK_LINE_OUT:
+ case AC_JACK_SPEAKER:
+ /* Enable output */
+ stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);
+ break;
+ case AC_JACK_SPDIF_IN:
+ stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
+ break;
+ case AC_JACK_MIC_IN:
+ if ((location & 0x0f) == AC_JACK_LOC_FRONT)
+ type = "Front Mic";
+ else
+ type = "Mic";
+ ainput = 1;
+ /* Set vref */
+ stac92xx_set_vref(codec, nid);
+ stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
+ break;
+ case AC_JACK_CD:
+ type = "CD";
+ ainput = 1;
+ stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
+ break;
+ case AC_JACK_LINE_IN:
+ if ((location & 0x0f) == AC_JACK_LOC_FRONT)
+ type = "Front Line";
+ else
+ type = "Line";
+ ainput = 1;
+ stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
+ break;
+ case AC_JACK_AUX:
+ if ((location & 0x0f) == AC_JACK_LOC_FRONT)
+ type = "Front Aux";
+ else
+ type = "Aux";
+ ainput = 1;
+ stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
+ break;
+ }
+
+ if (ainput) {
+ hda_nid_t con_lst[HDA_MAX_NUM_INPUTS];
+ int i, j, num_cons, index = -1;
+ if (!type)
+ type = "Input";
+ label = spec->input_labels[spec->input_mux.num_items];
+ strcpy(label, type);
+ spec->input_mux.items[spec->input_mux.num_items].label = label;
+ for (i=0; i<spec->num_muxes; i++) {
+ num_cons = snd_hda_get_connections(codec, spec->mux_nids[i], con_lst, HDA_MAX_NUM_INPUTS);
+ for (j=0; j<num_cons; j++)
+ if (con_lst[j] == nid) {
+ index = j;
+ break;
+ }
+ if (index >= 0)
+ break;
+ }
+ spec->input_mux.items[spec->input_mux.num_items].index = index;
+ spec->input_mux.num_items++;
+ }
+
+ return 0;
+}
+
+static int stac92xx_config_pins(struct hda_codec *codec)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ int i;
+ unsigned int pin_cfg;
+
+ for (i=0; i < spec->num_pins; i++) {
+ /* Default to disabled */
+ snd_hda_codec_write(codec, spec->pin_nids[i], 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL,
+ 0x00);
+
+ pin_cfg = snd_hda_codec_read(codec, spec->pin_nids[i], 0,
+ AC_VERB_GET_CONFIG_DEFAULT,
+ 0x00);
+ if (((pin_cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT) == AC_JACK_PORT_NONE)
+ continue; /* Move on */
+
+ stac92xx_config_pin(codec, spec->pin_nids[i], pin_cfg);
+ }
+
+ return 0;
+}
+
+static int stac92xx_init(struct hda_codec *codec)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ int i;
+
+ for (i=0; i < spec->num_pstates; i++)
+ snd_hda_codec_write(codec, spec->pstate_nids[i], 0,
+ AC_VERB_SET_POWER_STATE, 0x00);
+
+ mdelay(100);
+
+ snd_hda_sequence_write(codec, spec->init);
+
+#ifdef STAC_TEST
+ stac92xx_set_config_regs(codec);
+#endif
+
+ stac92xx_config_pins(codec);
+
+ return 0;
+}
+
+/*
+ * Analog playback callbacks
+ */
+static int stac92xx_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+}
+
+static int stac92xx_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ unsigned int stream_tag,
+ unsigned int format,
+ snd_pcm_substream_t *substream)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
+ format, substream);
+}
+
+static int stac92xx_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
+}
+
+/*
+ * Digital playback callbacks
+ */
+static int stac92xx_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ return snd_hda_multi_out_dig_open(codec, &spec->multiout);
+}
+
+static int stac92xx_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ return snd_hda_multi_out_dig_close(codec, &spec->multiout);
+}
+
+
+/*
+ * Analog capture callbacks
+ */
+static int stac92xx_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ unsigned int stream_tag,
+ unsigned int format,
+ snd_pcm_substream_t *substream)
+{
+ struct sigmatel_spec *spec = codec->spec;
+
+ snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
+ stream_tag, 0, format);
+ return 0;
+}
+
+static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ snd_pcm_substream_t *substream)
+{
+ struct sigmatel_spec *spec = codec->spec;
+
+ snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
+ return 0;
+}
+
+static struct hda_pcm_stream stac92xx_pcm_digital_playback = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 2,
+ /* NID is set in stac92xx_build_pcms */
+ .ops = {
+ .open = stac92xx_dig_playback_pcm_open,
+ .close = stac92xx_dig_playback_pcm_close
+ },
+};
+
+static struct hda_pcm_stream stac92xx_pcm_digital_capture = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 2,
+ /* NID is set in stac92xx_build_pcms */
+};
+
+static struct hda_pcm_stream stac92xx_pcm_analog_playback = {
+ .substreams = 1,
+ .channels_min = 2,
+ .channels_max = 2,
+ .nid = 0x02, /* NID to query formats and rates */
+ .ops = {
+ .open = stac92xx_playback_pcm_open,
+ .prepare = stac92xx_playback_pcm_prepare,
+ .cleanup = stac92xx_playback_pcm_cleanup
+ },
+};
+
+static struct hda_pcm_stream stac92xx_pcm_analog_capture = {
+ .substreams = 2,
+ .channels_min = 2,
+ .channels_max = 2,
+ .nid = 0x06, /* NID to query formats and rates */
+ .ops = {
+ .prepare = stac92xx_capture_pcm_prepare,
+ .cleanup = stac92xx_capture_pcm_cleanup
+ },
+};
+
+static int stac92xx_build_pcms(struct hda_codec *codec)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ struct hda_pcm *info = spec->pcm_rec;
+
+ codec->num_pcms = 1;
+ codec->pcm_info = info;
+
+ info->name = "STAC92xx";
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->playback_nid;
+ info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture;
+ info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->capture_nid;
+
+ if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
+ codec->num_pcms++;
+ info++;
+ info->name = "STAC92xx Digital";
+ if (spec->multiout.dig_out_nid) {
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_digital_playback;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
+ }
+ if (spec->dig_in_nid) {
+ info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_digital_capture;
+ info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
+ }
+ }
+
+ return 0;
+}
+
+static void stac92xx_free(struct hda_codec *codec)
+{
+ kfree(codec->spec);
+}
+
+static struct hda_codec_ops stac92xx_patch_ops = {
+ .build_controls = stac92xx_build_controls,
+ .build_pcms = stac92xx_build_pcms,
+ .init = stac92xx_init,
+ .free = stac92xx_free,
+};
+
+static int patch_stac9200(struct hda_codec *codec)
+{
+ struct sigmatel_spec *spec;
+
+ spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ if (spec == NULL)
+ return -ENOMEM;
+
+ codec->spec = spec;
+
+ spec->multiout.max_channels = 2;
+ spec->multiout.num_dacs = 1;
+ spec->multiout.dac_nids = stac9200_dac_nids;
+ spec->multiout.dig_out_nid = 0x05;
+ spec->dig_in_nid = 0x04;
+ spec->adc_nids = stac9200_adc_nids;
+ spec->mux_nids = stac9200_mux_nids;
+ spec->num_muxes = 1;
+ spec->input_mux.num_items = 0;
+ spec->pstate_nids = stac9200_pstate_nids;
+ spec->num_pstates = 3;
+ spec->pin_nids = stac9200_pin_nids;
+#ifdef STAC_TEST
+ spec->pin_configs = stac9200_pin_configs;
+#endif
+ spec->num_pins = 8;
+ spec->init = stac9200_ch2_init;
+ spec->mixer = stac9200_mixer;
+ spec->playback_nid = 0x02;
+ spec->capture_nid = 0x03;
+
+ codec->patch_ops = stac92xx_patch_ops;
+
+ return 0;
+}
+
+static int patch_stac922x(struct hda_codec *codec)
+{
+ struct sigmatel_spec *spec;
+
+ spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+ if (spec == NULL)
+ return -ENOMEM;
+
+ codec->spec = spec;
+
+ spec->multiout.max_channels = 2;
+ spec->multiout.num_dacs = 4;
+ spec->multiout.dac_nids = stac922x_dac_nids;
+ spec->multiout.dig_out_nid = 0x08;
+ spec->dig_in_nid = 0x09;
+ spec->adc_nids = stac922x_adc_nids;
+ spec->mux_nids = stac922x_mux_nids;
+ spec->num_muxes = 2;
+ spec->input_mux.num_items = 0;
+ spec->pstate_nids = stac922x_pstate_nids;
+ spec->num_pstates = 8;
+ spec->pin_nids = stac922x_pin_nids;
+#ifdef STAC_TEST
+ spec->pin_configs = stac922x_pin_configs;
+#endif
+ spec->num_pins = 10;
+ spec->init = stac922x_ch2_init;
+ spec->mixer = stac922x_mixer;
+ spec->playback_nid = 0x02;
+ spec->capture_nid = 0x06;
+
+ codec->patch_ops = stac92xx_patch_ops;
+
+ return 0;
+}
+
+/*
+ * patch entries
+ */
+struct hda_codec_preset snd_hda_preset_sigmatel[] = {
+ { .id = 0x83847690, .name = "STAC9200", .patch = patch_stac9200 },
+ { .id = 0x83847882, .name = "STAC9220 A1", .patch = patch_stac922x },
+ { .id = 0x83847680, .name = "STAC9221 A1", .patch = patch_stac922x },
+ { .id = 0x83847880, .name = "STAC9220 A2", .patch = patch_stac922x },
+ { .id = 0x83847681, .name = "STAC9220D/9223D A2", .patch = patch_stac922x },
+ { .id = 0x83847682, .name = "STAC9221 A2", .patch = patch_stac922x },
+ { .id = 0x83847683, .name = "STAC9221D A2", .patch = patch_stac922x },
+ {} /* terminator */
+};
diff --git a/sound/pci/ice1712/amp.c b/sound/pci/ice1712/amp.c
index 779951725e1..289b0b5711e 100644
--- a/sound/pci/ice1712/amp.c
+++ b/sound/pci/ice1712/amp.c
@@ -30,16 +30,39 @@
#include <sound/core.h>
#include "ice1712.h"
+#include "envy24ht.h"
#include "amp.h"
+static void wm_put(ice1712_t *ice, int reg, unsigned short val)
+{
+ unsigned short cval;
+ cval = (reg << 9) | val;
+ snd_vt1724_write_i2c(ice, WM_DEV, cval >> 8, cval & 0xff);
+}
static int __devinit snd_vt1724_amp_init(ice1712_t *ice)
{
+ static unsigned short wm_inits[] = {
+ WM_ATTEN_L, 0x0000, /* 0 db */
+ WM_ATTEN_R, 0x0000, /* 0 db */
+ WM_DAC_CTRL, 0x0008, /* 24bit I2S */
+ WM_INT_CTRL, 0x0001, /* 24bit I2S */
+ };
+
+ unsigned int i;
+
/* only use basic functionality for now */
ice->num_total_dacs = 2; /* only PSDOUT0 is connected */
ice->num_total_adcs = 2;
+ /* Chaintech AV-710 has another codecs, which need initialization */
+ /* initialize WM8728 codec */
+ if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AV710) {
+ for (i = 0; i < ARRAY_SIZE(wm_inits); i += 2)
+ wm_put(ice, wm_inits[i], wm_inits[i+1]);
+ }
+
return 0;
}
@@ -54,6 +77,13 @@ static int __devinit snd_vt1724_amp_add_controls(ice1712_t *ice)
/* entry point */
struct snd_ice1712_card_info snd_vt1724_amp_cards[] __devinitdata = {
{
+ .subvendor = VT1724_SUBDEVICE_AV710,
+ .name = "Chaintech AV-710",
+ .model = "av710",
+ .chip_init = snd_vt1724_amp_init,
+ .build_controls = snd_vt1724_amp_add_controls,
+ },
+ {
.subvendor = VT1724_SUBDEVICE_AUDIO2000,
.name = "AMP Ltd AUDIO2000",
.model = "amp2000",
diff --git a/sound/pci/ice1712/amp.h b/sound/pci/ice1712/amp.h
index d58d43383e8..a0fc89b4812 100644
--- a/sound/pci/ice1712/amp.h
+++ b/sound/pci/ice1712/amp.h
@@ -24,9 +24,23 @@
*
*/
-#define AMP_AUDIO2000_DEVICE_DESC "{AMP Ltd,AUDIO2000},"
+#define AMP_AUDIO2000_DEVICE_DESC "{AMP Ltd,AUDIO2000},"\
+ "{Chaintech,AV-710},"
+#if 0
#define VT1724_SUBDEVICE_AUDIO2000 0x12142417 /* Advanced Micro Peripherals Ltd AUDIO2000 */
+#else
+#define VT1724_SUBDEVICE_AUDIO2000 0x00030003 /* a dummy ID for AMP Audio2000 */
+#endif
+#define VT1724_SUBDEVICE_AV710 0x12142417 /* AV710 - the same ID with Audio2000! */
+
+/* WM8728 on I2C for AV710 */
+#define WM_DEV 0x36
+
+#define WM_ATTEN_L 0x00
+#define WM_ATTEN_R 0x01
+#define WM_DAC_CTRL 0x02
+#define WM_INT_CTRL 0x03
extern struct snd_ice1712_card_info snd_vt1724_amp_cards[];
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index 79fba6be350..a2545a5b26c 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -2748,7 +2748,7 @@ static struct pci_driver driver = {
static int __init alsa_card_ice1712_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_ice1712_exit(void)
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
index 8bb1c58c26a..5ad4728daa7 100644
--- a/sound/pci/ice1712/ice1712.h
+++ b/sound/pci/ice1712/ice1712.h
@@ -373,6 +373,11 @@ struct _snd_ice1712 {
unsigned short master[2];
unsigned short vol[8];
} aureon;
+ /* AC97 register cache for Phase28 */
+ struct phase28_spec {
+ unsigned short master[2];
+ unsigned short vol[8];
+ } phase28;
/* Hoontech-specific setting */
struct hoontech_spec {
unsigned char boxbits[4];
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 95500f06f0c..79b5f12e06f 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -2328,7 +2328,7 @@ static struct pci_driver driver = {
static int __init alsa_card_ice1724_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_ice1724_exit(void)
diff --git a/sound/pci/ice1712/phase.c b/sound/pci/ice1712/phase.c
index d1f90832443..5bf734b04fa 100644
--- a/sound/pci/ice1712/phase.c
+++ b/sound/pci/ice1712/phase.c
@@ -45,6 +45,47 @@
#include "envy24ht.h"
#include "phase.h"
+/* WM8770 registers */
+#define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */
+#define WM_DAC_MASTER_ATTEN 0x08 /* DAC master analog attenuation */
+#define WM_DAC_DIG_ATTEN 0x09 /* DAC1-8 digital attenuation */
+#define WM_DAC_DIG_MASTER_ATTEN 0x11 /* DAC master digital attenuation */
+#define WM_PHASE_SWAP 0x12 /* DAC phase */
+#define WM_DAC_CTRL1 0x13 /* DAC control bits */
+#define WM_MUTE 0x14 /* mute controls */
+#define WM_DAC_CTRL2 0x15 /* de-emphasis and zefo-flag */
+#define WM_INT_CTRL 0x16 /* interface control */
+#define WM_MASTER 0x17 /* master clock and mode */
+#define WM_POWERDOWN 0x18 /* power-down controls */
+#define WM_ADC_GAIN 0x19 /* ADC gain L(19)/R(1a) */
+#define WM_ADC_MUX 0x1b /* input MUX */
+#define WM_OUT_MUX1 0x1c /* output MUX */
+#define WM_OUT_MUX2 0x1e /* output MUX */
+#define WM_RESET 0x1f /* software reset */
+
+
+/*
+ * Logarithmic volume values for WM8770
+ * Computed as 20 * Log10(255 / x)
+ */
+static unsigned char wm_vol[256] = {
+ 127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
+ 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
+ 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
+ 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0
+};
+
+#define WM_VOL_MAX (sizeof(wm_vol) - 1)
+#define WM_VOL_MUTE 0x8000
+
static akm4xxx_t akm_phase22 __devinitdata = {
.type = SND_AK4524,
.num_dacs = 2,
@@ -124,6 +165,684 @@ static unsigned char phase22_eeprom[] __devinitdata = {
0x00, /* GPIO_STATE2 */
};
+static unsigned char phase28_eeprom[] __devinitdata = {
+ 0x0b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
+ 0x80, /* ACLINK: I2S */
+ 0xfc, /* I2S: vol, 96k, 24bit, 192k */
+ 0xc3, /* SPDIF: out-en, out-int, spdif-in */
+ 0xff, /* GPIO_DIR */
+ 0xff, /* GPIO_DIR1 */
+ 0x5f, /* GPIO_DIR2 */
+ 0x00, /* GPIO_MASK */
+ 0x00, /* GPIO_MASK1 */
+ 0x00, /* GPIO_MASK2 */
+ 0x00, /* GPIO_STATE */
+ 0x00, /* GPIO_STATE1 */
+ 0x00, /* GPIO_STATE2 */
+};
+
+/*
+ * write data in the SPI mode
+ */
+static void phase28_spi_write(ice1712_t *ice, unsigned int cs, unsigned int data, int bits)
+{
+ unsigned int tmp;
+ int i;
+
+ tmp = snd_ice1712_gpio_read(ice);
+
+ snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RW|PHASE28_SPI_MOSI|PHASE28_SPI_CLK|
+ PHASE28_WM_CS));
+ tmp |= PHASE28_WM_RW;
+ tmp &= ~cs;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(1);
+
+ for (i = bits - 1; i >= 0; i--) {
+ tmp &= ~PHASE28_SPI_CLK;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(1);
+ if (data & (1 << i))
+ tmp |= PHASE28_SPI_MOSI;
+ else
+ tmp &= ~PHASE28_SPI_MOSI;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(1);
+ tmp |= PHASE28_SPI_CLK;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(1);
+ }
+
+ tmp &= ~PHASE28_SPI_CLK;
+ tmp |= cs;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(1);
+ tmp |= PHASE28_SPI_CLK;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(1);
+}
+
+/*
+ * get the current register value of WM codec
+ */
+static unsigned short wm_get(ice1712_t *ice, int reg)
+{
+ reg <<= 1;
+ return ((unsigned short)ice->akm[0].images[reg] << 8) |
+ ice->akm[0].images[reg + 1];
+}
+
+/*
+ * set the register value of WM codec
+ */
+static void wm_put_nocache(ice1712_t *ice, int reg, unsigned short val)
+{
+ phase28_spi_write(ice, PHASE28_WM_CS, (reg << 9) | (val & 0x1ff), 16);
+}
+
+/*
+ * set the register value of WM codec and remember it
+ */
+static void wm_put(ice1712_t *ice, int reg, unsigned short val)
+{
+ wm_put_nocache(ice, reg, val);
+ reg <<= 1;
+ ice->akm[0].images[reg] = val >> 8;
+ ice->akm[0].images[reg + 1] = val;
+}
+
+static void wm_set_vol(ice1712_t *ice, unsigned int index, unsigned short vol, unsigned short master)
+{
+ unsigned char nvol;
+
+ if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
+ nvol = 0;
+ else
+ nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
+
+ wm_put(ice, index, nvol);
+ wm_put_nocache(ice, index, 0x180 | nvol);
+}
+
+/*
+ * DAC mute control
+ */
+#define wm_pcm_mute_info phase28_mono_bool_info
+
+static int wm_pcm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+
+ down(&ice->gpio_mutex);
+ ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
+ up(&ice->gpio_mutex);
+ return 0;
+}
+
+static int wm_pcm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ unsigned short nval, oval;
+ int change;
+
+ snd_ice1712_save_gpio_status(ice);
+ oval = wm_get(ice, WM_MUTE);
+ nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
+ if ((change = (nval != oval)))
+ wm_put(ice, WM_MUTE, nval);
+ snd_ice1712_restore_gpio_status(ice);
+
+ return change;
+}
+
+/*
+ * Master volume attenuation mixer control
+ */
+static int wm_master_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 2;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = WM_VOL_MAX;
+ return 0;
+}
+
+static int wm_master_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ int i;
+ for (i=0; i<2; i++)
+ ucontrol->value.integer.value[i] = ice->spec.phase28.master[i] & ~WM_VOL_MUTE;
+ return 0;
+}
+
+static int wm_master_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ int ch, change = 0;
+
+ snd_ice1712_save_gpio_status(ice);
+ for (ch = 0; ch < 2; ch++) {
+ if (ucontrol->value.integer.value[ch] != ice->spec.phase28.master[ch]) {
+ int dac;
+ ice->spec.phase28.master[ch] &= WM_VOL_MUTE;
+ ice->spec.phase28.master[ch] |= ucontrol->value.integer.value[ch];
+ for (dac = 0; dac < ice->num_total_dacs; dac += 2)
+ wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
+ ice->spec.phase28.vol[dac + ch],
+ ice->spec.phase28.master[ch]);
+ change = 1;
+ }
+ }
+ snd_ice1712_restore_gpio_status(ice);
+ return change;
+}
+
+static int __devinit phase28_init(ice1712_t *ice)
+{
+ static unsigned short wm_inits_phase28[] = {
+ /* These come first to reduce init pop noise */
+ 0x1b, 0x044, /* ADC Mux (AC'97 source) */
+ 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
+ 0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
+
+ 0x18, 0x000, /* All power-up */
+
+ 0x16, 0x122, /* I2S, normal polarity, 24bit */
+ 0x17, 0x022, /* 256fs, slave mode */
+ 0x00, 0, /* DAC1 analog mute */
+ 0x01, 0, /* DAC2 analog mute */
+ 0x02, 0, /* DAC3 analog mute */
+ 0x03, 0, /* DAC4 analog mute */
+ 0x04, 0, /* DAC5 analog mute */
+ 0x05, 0, /* DAC6 analog mute */
+ 0x06, 0, /* DAC7 analog mute */
+ 0x07, 0, /* DAC8 analog mute */
+ 0x08, 0x100, /* master analog mute */
+ 0x09, 0xff, /* DAC1 digital full */
+ 0x0a, 0xff, /* DAC2 digital full */
+ 0x0b, 0xff, /* DAC3 digital full */
+ 0x0c, 0xff, /* DAC4 digital full */
+ 0x0d, 0xff, /* DAC5 digital full */
+ 0x0e, 0xff, /* DAC6 digital full */
+ 0x0f, 0xff, /* DAC7 digital full */
+ 0x10, 0xff, /* DAC8 digital full */
+ 0x11, 0x1ff, /* master digital full */
+ 0x12, 0x000, /* phase normal */
+ 0x13, 0x090, /* unmute DAC L/R */
+ 0x14, 0x000, /* all unmute */
+ 0x15, 0x000, /* no deemphasis, no ZFLG */
+ 0x19, 0x000, /* -12dB ADC/L */
+ 0x1a, 0x000, /* -12dB ADC/R */
+ (unsigned short)-1
+ };
+
+ unsigned int tmp;
+ akm4xxx_t *ak;
+ unsigned short *p;
+ int i;
+
+ ice->num_total_dacs = 8;
+ ice->num_total_adcs = 2;
+
+ // Initialize analog chips
+ ak = ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
+ if (!ak)
+ return -ENOMEM;
+ ice->akm_codecs = 1;
+
+ snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
+
+ /* reset the wm codec as the SPI mode */
+ snd_ice1712_save_gpio_status(ice);
+ snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RESET|PHASE28_WM_CS|PHASE28_HP_SEL));
+
+ tmp = snd_ice1712_gpio_read(ice);
+ tmp &= ~PHASE28_WM_RESET;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(1);
+ tmp |= PHASE28_WM_CS;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(1);
+ tmp |= PHASE28_WM_RESET;
+ snd_ice1712_gpio_write(ice, tmp);
+ udelay(1);
+
+ p = wm_inits_phase28;
+ for (; *p != (unsigned short)-1; p += 2)
+ wm_put(ice, p[0], p[1]);
+
+ snd_ice1712_restore_gpio_status(ice);
+
+ ice->spec.phase28.master[0] = WM_VOL_MUTE;
+ ice->spec.phase28.master[1] = WM_VOL_MUTE;
+ for (i = 0; i < ice->num_total_dacs; i++) {
+ ice->spec.phase28.vol[i] = WM_VOL_MUTE;
+ wm_set_vol(ice, i, ice->spec.phase28.vol[i], ice->spec.phase28.master[i % 2]);
+ }
+
+ return 0;
+}
+
+/*
+ * DAC volume attenuation mixer control
+ */
+static int wm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+ int voices = kcontrol->private_value >> 8;
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = voices;
+ uinfo->value.integer.min = 0; /* mute (-101dB) */
+ uinfo->value.integer.max = 0x7F; /* 0dB */
+ return 0;
+}
+
+static int wm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ int i, ofs, voices;
+
+ voices = kcontrol->private_value >> 8;
+ ofs = kcontrol->private_value & 0xff;
+ for (i = 0; i < voices; i++)
+ ucontrol->value.integer.value[i] = ice->spec.phase28.vol[ofs+i] & ~WM_VOL_MUTE;
+ return 0;
+}
+
+static int wm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ int i, idx, ofs, voices;
+ int change = 0;
+
+ voices = kcontrol->private_value >> 8;
+ ofs = kcontrol->private_value & 0xff;
+ snd_ice1712_save_gpio_status(ice);
+ for (i = 0; i < voices; i++) {
+ idx = WM_DAC_ATTEN + ofs + i;
+ if (ucontrol->value.integer.value[i] != ice->spec.phase28.vol[ofs+i]) {
+ ice->spec.phase28.vol[ofs+i] &= WM_VOL_MUTE;
+ ice->spec.phase28.vol[ofs+i] |= ucontrol->value.integer.value[i];
+ wm_set_vol(ice, idx, ice->spec.phase28.vol[ofs+i],
+ ice->spec.phase28.master[i]);
+ change = 1;
+ }
+ }
+ snd_ice1712_restore_gpio_status(ice);
+ return change;
+}
+
+/*
+ * WM8770 mute control
+ */
+static int wm_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = kcontrol->private_value >> 8;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+}
+
+static int wm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ int voices, ofs, i;
+
+ voices = kcontrol->private_value >> 8;
+ ofs = kcontrol->private_value & 0xFF;
+
+ for (i = 0; i < voices; i++)
+ ucontrol->value.integer.value[i] = (ice->spec.phase28.vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1;
+ return 0;
+}
+
+static int wm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ int change = 0, voices, ofs, i;
+
+ voices = kcontrol->private_value >> 8;
+ ofs = kcontrol->private_value & 0xFF;
+
+ snd_ice1712_save_gpio_status(ice);
+ for (i = 0; i < voices; i++) {
+ int val = (ice->spec.phase28.vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
+ if (ucontrol->value.integer.value[i] != val) {
+ ice->spec.phase28.vol[ofs + i] &= ~WM_VOL_MUTE;
+ ice->spec.phase28.vol[ofs + i] |=
+ ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
+ wm_set_vol(ice, ofs + i, ice->spec.phase28.vol[ofs + i],
+ ice->spec.phase28.master[i]);
+ change = 1;
+ }
+ }
+ snd_ice1712_restore_gpio_status(ice);
+
+ return change;
+}
+
+/*
+ * WM8770 master mute control
+ */
+static int wm_master_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 2;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+}
+
+static int wm_master_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.integer.value[0] = (ice->spec.phase28.master[0] & WM_VOL_MUTE) ? 0 : 1;
+ ucontrol->value.integer.value[1] = (ice->spec.phase28.master[1] & WM_VOL_MUTE) ? 0 : 1;
+ return 0;
+}
+
+static int wm_master_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+ ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ int change = 0, i;
+
+ snd_ice1712_save_gpio_status(ice);
+ for (i = 0; i < 2; i++) {
+ int val = (ice->spec.phase28.master[i] & WM_VOL_MUTE) ? 0 : 1;
+ if (ucontrol->value.integer.value[i] != val) {
+ int dac;
+ ice->spec.phase28.master[i] &= ~WM_VOL_MUTE;
+ ice->spec.phase28.master[i] |=
+ ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
+ for (dac = 0; dac < ice->num_total_dacs; dac += 2)
+ wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
+ ice->spec.phase28.vol[dac + i],
+ ice->spec.phase28.master[i]);
+ change = 1;
+ }
+ }
+ snd_ice1712_restore_gpio_status(ice);
+
+ return change;
+}
+
+/* digital master volume */
+#define PCM_0dB 0xff
+#define PCM_RES 128 /* -64dB */
+#define PCM_MIN (PCM_0dB - PCM_RES)
+static int wm_pcm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0; /* mute (-64dB) */
+ uinfo->value.integer.max = PCM_RES; /* 0dB */
+ return 0;
+}
+
+static int wm_pcm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ unsigned short val;
+
+ down(&ice->gpio_mutex);
+ val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
+ val = val > PCM_MIN ? (val - PCM_MIN) : 0;
+ ucontrol->value.integer.value[0] = val;
+ up(&ice->gpio_mutex);
+ return 0;
+}
+
+static int wm_pcm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ unsigned short ovol, nvol;
+ int change = 0;
+
+ snd_ice1712_save_gpio_status(ice);
+ nvol = ucontrol->value.integer.value[0];
+ nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
+ ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
+ if (ovol != nvol) {
+ wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
+ wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
+ change = 1;
+ }
+ snd_ice1712_restore_gpio_status(ice);
+ return change;
+}
+
+/*
+ */
+static int phase28_mono_bool_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+}
+
+/*
+ * Deemphasis
+ */
+#define phase28_deemp_info phase28_mono_bool_info
+
+static int phase28_deemp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
+ return 0;
+}
+
+static int phase28_deemp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ int temp, temp2;
+ temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
+ if (ucontrol->value.integer.value[0])
+ temp |= 0xf;
+ else
+ temp &= ~0xf;
+ if (temp != temp2) {
+ wm_put(ice, WM_DAC_CTRL2, temp);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * ADC Oversampling
+ */
+static int phase28_oversampling_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
+{
+ static char *texts[2] = { "128x", "64x" };
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 2;
+
+ if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+ uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+ strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+
+ return 0;
+}
+
+static int phase28_oversampling_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+ ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
+ return 0;
+}
+
+static int phase28_oversampling_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ int temp, temp2;
+ ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+
+ temp2 = temp = wm_get(ice, WM_MASTER);
+
+ if (ucontrol->value.enumerated.item[0])
+ temp |= 0x8;
+ else
+ temp &= ~0x8;
+
+ if (temp != temp2) {
+ wm_put(ice, WM_MASTER, temp);
+ return 1;
+ }
+ return 0;
+}
+
+static snd_kcontrol_new_t phase28_dac_controls[] __devinitdata = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Master Playback Switch",
+ .info = wm_master_mute_info,
+ .get = wm_master_mute_get,
+ .put = wm_master_mute_put
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Master Playback Volume",
+ .info = wm_master_vol_info,
+ .get = wm_master_vol_get,
+ .put = wm_master_vol_put
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Front Playback Switch",
+ .info = wm_mute_info,
+ .get = wm_mute_get,
+ .put = wm_mute_put,
+ .private_value = (2 << 8) | 0
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Front Playback Volume",
+ .info = wm_vol_info,
+ .get = wm_vol_get,
+ .put = wm_vol_put,
+ .private_value = (2 << 8) | 0
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Rear Playback Switch",
+ .info = wm_mute_info,
+ .get = wm_mute_get,
+ .put = wm_mute_put,
+ .private_value = (2 << 8) | 2
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Rear Playback Volume",
+ .info = wm_vol_info,
+ .get = wm_vol_get,
+ .put = wm_vol_put,
+ .private_value = (2 << 8) | 2
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Center Playback Switch",
+ .info = wm_mute_info,
+ .get = wm_mute_get,
+ .put = wm_mute_put,
+ .private_value = (1 << 8) | 4
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Center Playback Volume",
+ .info = wm_vol_info,
+ .get = wm_vol_get,
+ .put = wm_vol_put,
+ .private_value = (1 << 8) | 4
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "LFE Playback Switch",
+ .info = wm_mute_info,
+ .get = wm_mute_get,
+ .put = wm_mute_put,
+ .private_value = (1 << 8) | 5
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "LFE Playback Volume",
+ .info = wm_vol_info,
+ .get = wm_vol_get,
+ .put = wm_vol_put,
+ .private_value = (1 << 8) | 5
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Side Playback Switch",
+ .info = wm_mute_info,
+ .get = wm_mute_get,
+ .put = wm_mute_put,
+ .private_value = (2 << 8) | 6
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Side Playback Volume",
+ .info = wm_vol_info,
+ .get = wm_vol_get,
+ .put = wm_vol_put,
+ .private_value = (2 << 8) | 6
+ }
+};
+
+static snd_kcontrol_new_t wm_controls[] __devinitdata = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "PCM Playback Switch",
+ .info = wm_pcm_mute_info,
+ .get = wm_pcm_mute_get,
+ .put = wm_pcm_mute_put
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "PCM Playback Volume",
+ .info = wm_pcm_vol_info,
+ .get = wm_pcm_vol_get,
+ .put = wm_pcm_vol_put
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "DAC Deemphasis Switch",
+ .info = phase28_deemp_info,
+ .get = phase28_deemp_get,
+ .put = phase28_deemp_put
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "ADC Oversampling",
+ .info = phase28_oversampling_info,
+ .get = phase28_oversampling_get,
+ .put = phase28_oversampling_put
+ }
+};
+
+static int __devinit phase28_add_controls(ice1712_t *ice)
+{
+ unsigned int i, counts;
+ int err;
+
+ counts = ARRAY_SIZE(phase28_dac_controls);
+ for (i = 0; i < counts; i++) {
+ err = snd_ctl_add(ice->card, snd_ctl_new1(&phase28_dac_controls[i], ice));
+ if (err < 0)
+ return err;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
+ err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = {
{
.subvendor = VT1724_SUBDEVICE_PHASE22,
@@ -134,5 +853,14 @@ struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = {
.eeprom_size = sizeof(phase22_eeprom),
.eeprom_data = phase22_eeprom,
},
+ {
+ .subvendor = VT1724_SUBDEVICE_PHASE28,
+ .name = "Terratec PHASE 28",
+ .model = "phase28",
+ .chip_init = phase28_init,
+ .build_controls = phase28_add_controls,
+ .eeprom_size = sizeof(phase28_eeprom),
+ .eeprom_data = phase28_eeprom,
+ },
{ } /* terminator */
};
diff --git a/sound/pci/ice1712/phase.h b/sound/pci/ice1712/phase.h
index 6230cf16989..13e841b5548 100644
--- a/sound/pci/ice1712/phase.h
+++ b/sound/pci/ice1712/phase.h
@@ -24,11 +24,28 @@
*
*/
-#define PHASE_DEVICE_DESC "{Terratec,Phase 22},"
+#define PHASE_DEVICE_DESC "{Terratec,Phase 22},"\
+ "{Terratec,Phase 28},"
#define VT1724_SUBDEVICE_PHASE22 0x3b155011
+#define VT1724_SUBDEVICE_PHASE28 0x3b154911
/* entry point */
extern struct snd_ice1712_card_info snd_vt1724_phase_cards[];
+/* PHASE28 GPIO bits */
+#define PHASE28_SPI_MISO (1 << 21)
+#define PHASE28_WM_RESET (1 << 20)
+#define PHASE28_SPI_CLK (1 << 19)
+#define PHASE28_SPI_MOSI (1 << 18)
+#define PHASE28_WM_RW (1 << 17)
+#define PHASE28_AC97_RESET (1 << 16)
+#define PHASE28_DIGITAL_SEL1 (1 << 15)
+#define PHASE28_HP_SEL (1 << 14)
+#define PHASE28_WM_CS (1 << 12)
+#define PHASE28_AC97_COMMIT (1 << 11)
+#define PHASE28_AC97_ADDR (1 << 10)
+#define PHASE28_AC97_DATA_LOW (1 << 9)
+#define PHASE28_AC97_DATA_HIGH (1 << 8)
+#define PHASE28_AC97_DATA_MASK 0xFF
#endif /* __SOUND_PHASE */
diff --git a/sound/pci/ice1712/vt1720_mobo.c b/sound/pci/ice1712/vt1720_mobo.c
index 3bd92627231..ab61e383024 100644
--- a/sound/pci/ice1712/vt1720_mobo.c
+++ b/sound/pci/ice1712/vt1720_mobo.c
@@ -110,6 +110,15 @@ struct snd_ice1712_card_info snd_vt1720_mobo_cards[] __devinitdata = {
.eeprom_size = sizeof(k8x800_eeprom),
.eeprom_data = k8x800_eeprom,
},
+ {
+ .subvendor = VT1720_SUBDEVICE_SN25P,
+ .name = "Shuttle SN25P",
+ /* identical with k8x800 */
+ .chip_init = k8x800_init,
+ .build_controls = k8x800_add_controls,
+ .eeprom_size = sizeof(k8x800_eeprom),
+ .eeprom_data = k8x800_eeprom,
+ },
{ } /* terminator */
};
diff --git a/sound/pci/ice1712/vt1720_mobo.h b/sound/pci/ice1712/vt1720_mobo.h
index f949eb804ca..0b1b0ee1bea 100644
--- a/sound/pci/ice1712/vt1720_mobo.h
+++ b/sound/pci/ice1712/vt1720_mobo.h
@@ -27,12 +27,14 @@
#define VT1720_MOBO_DEVICE_DESC "{Albatron,K8X800 Pro II},"\
"{Chaintech,ZNF3-150},"\
"{Chaintech,ZNF3-250},"\
- "{Chaintech,9CJS},"
+ "{Chaintech,9CJS},"\
+ "{Shuttle,SN25P},"
#define VT1720_SUBDEVICE_K8X800 0xf217052c
#define VT1720_SUBDEVICE_ZNF3_150 0x0f2741f6
#define VT1720_SUBDEVICE_ZNF3_250 0x0f2745f6
#define VT1720_SUBDEVICE_9CJS 0x0f272327
+#define VT1720_SUBDEVICE_SN25P 0x97123650
extern struct snd_ice1712_card_info snd_vt1720_mobo_cards[];
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 8b33b12fa5d..cc16f95f9ce 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -1725,229 +1725,235 @@ static struct ac97_pcm ac97_pcm_defs[] __devinitdata = {
static struct ac97_quirk ac97_quirks[] __devinitdata = {
{
- .vendor = 0x0e11,
- .device = 0x008a,
+ .subvendor = 0x0e11,
+ .subdevice = 0x008a,
.name = "Compaq Evo W4000", /* AD1885 */
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x0e11,
- .device = 0x00b8,
+ .subvendor = 0x0e11,
+ .subdevice = 0x00b8,
.name = "Compaq Evo D510C",
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x0e11,
- .device = 0x0860,
+ .subvendor = 0x0e11,
+ .subdevice = 0x0860,
.name = "HP/Compaq nx7010",
.type = AC97_TUNE_MUTE_LED
},
{
- .vendor = 0x1014,
- .device = 0x1f00,
+ .subvendor = 0x1014,
+ .subdevice = 0x1f00,
.name = "MS-9128",
.type = AC97_TUNE_ALC_JACK
},
{
- .vendor = 0x1028,
- .device = 0x00d8,
+ .subvendor = 0x1028,
+ .subdevice = 0x00d8,
.name = "Dell Precision 530", /* AD1885 */
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x1028,
- .device = 0x010d,
+ .subvendor = 0x1028,
+ .subdevice = 0x010d,
.name = "Dell", /* which model? AD1885 */
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x1028,
- .device = 0x0126,
+ .subvendor = 0x1028,
+ .subdevice = 0x0126,
.name = "Dell Optiplex GX260", /* AD1981A */
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x1028,
- .device = 0x012c,
+ .subvendor = 0x1028,
+ .subdevice = 0x012c,
.name = "Dell Precision 650", /* AD1981A */
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x1028,
- .device = 0x012d,
+ .subvendor = 0x1028,
+ .subdevice = 0x012d,
.name = "Dell Precision 450", /* AD1981B*/
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x1028,
- .device = 0x0147,
+ .subvendor = 0x1028,
+ .subdevice = 0x0147,
.name = "Dell", /* which model? AD1981B*/
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x1028,
- .device = 0x0163,
+ .subvendor = 0x1028,
+ .subdevice = 0x0163,
.name = "Dell Unknown", /* STAC9750/51 */
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x103c,
- .device = 0x006d,
+ .subvendor = 0x103c,
+ .subdevice = 0x006d,
.name = "HP zv5000",
.type = AC97_TUNE_MUTE_LED /*AD1981B*/
},
{ /* FIXME: which codec? */
- .vendor = 0x103c,
- .device = 0x00c3,
+ .subvendor = 0x103c,
+ .subdevice = 0x00c3,
.name = "HP xw6000",
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x103c,
- .device = 0x088c,
+ .subvendor = 0x103c,
+ .subdevice = 0x088c,
.name = "HP nc8000",
.type = AC97_TUNE_MUTE_LED
},
{
- .vendor = 0x103c,
- .device = 0x0890,
+ .subvendor = 0x103c,
+ .subdevice = 0x0890,
.name = "HP nc6000",
.type = AC97_TUNE_MUTE_LED
},
{
- .vendor = 0x103c,
- .device = 0x129d,
+ .subvendor = 0x103c,
+ .subdevice = 0x129d,
.name = "HP xw8000",
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x103c,
- .device = 0x12f1,
+ .subvendor = 0x103c,
+ .subdevice = 0x12f1,
.name = "HP xw8200", /* AD1981B*/
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x103c,
- .device = 0x12f2,
+ .subvendor = 0x103c,
+ .subdevice = 0x12f2,
.name = "HP xw6200",
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x103c,
- .device = 0x3008,
+ .subvendor = 0x103c,
+ .subdevice = 0x3008,
.name = "HP xw4200", /* AD1981B*/
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x104d,
- .device = 0x8197,
+ .subvendor = 0x104d,
+ .subdevice = 0x8197,
.name = "Sony S1XP",
.type = AC97_TUNE_INV_EAPD
},
{
- .vendor = 0x1043,
- .device = 0x80f3,
+ .subvendor = 0x1043,
+ .subdevice = 0x80f3,
.name = "ASUS ICH5/AD1985",
.type = AC97_TUNE_AD_SHARING
},
{
- .vendor = 0x10cf,
- .device = 0x11c3,
+ .subvendor = 0x10cf,
+ .subdevice = 0x11c3,
.name = "Fujitsu-Siemens E4010",
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x10cf,
- .device = 0x1253,
+ .subvendor = 0x10cf,
+ .subdevice = 0x1225,
+ .name = "Fujitsu-Siemens T3010",
+ .type = AC97_TUNE_HP_ONLY
+ },
+ {
+ .subvendor = 0x10cf,
+ .subdevice = 0x1253,
.name = "Fujitsu S6210", /* STAC9750/51 */
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x10f1,
- .device = 0x2665,
+ .subvendor = 0x10f1,
+ .subdevice = 0x2665,
.name = "Fujitsu-Siemens Celsius", /* AD1981? */
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x10f1,
- .device = 0x2885,
+ .subvendor = 0x10f1,
+ .subdevice = 0x2885,
.name = "AMD64 Mobo", /* ALC650 */
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x110a,
- .device = 0x0056,
+ .subvendor = 0x110a,
+ .subdevice = 0x0056,
.name = "Fujitsu-Siemens Scenic", /* AD1981? */
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x11d4,
- .device = 0x5375,
+ .subvendor = 0x11d4,
+ .subdevice = 0x5375,
.name = "ADI AD1985 (discrete)",
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x1462,
- .device = 0x5470,
+ .subvendor = 0x1462,
+ .subdevice = 0x5470,
.name = "MSI P4 ATX 645 Ultra",
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x1734,
- .device = 0x0088,
+ .subvendor = 0x1734,
+ .subdevice = 0x0088,
.name = "Fujitsu-Siemens D1522", /* AD1981 */
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x8086,
- .device = 0x2000,
+ .subvendor = 0x8086,
+ .subdevice = 0x2000,
.mask = 0xfff0,
.name = "Intel ICH5/AD1985",
.type = AC97_TUNE_AD_SHARING
},
{
- .vendor = 0x8086,
- .device = 0x4000,
+ .subvendor = 0x8086,
+ .subdevice = 0x4000,
.mask = 0xfff0,
.name = "Intel ICH5/AD1985",
.type = AC97_TUNE_AD_SHARING
},
{
- .vendor = 0x8086,
- .device = 0x4856,
+ .subvendor = 0x8086,
+ .subdevice = 0x4856,
.name = "Intel D845WN (82801BA)",
.type = AC97_TUNE_SWAP_HP
},
{
- .vendor = 0x8086,
- .device = 0x4d44,
+ .subvendor = 0x8086,
+ .subdevice = 0x4d44,
.name = "Intel D850EMV2", /* AD1885 */
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x8086,
- .device = 0x4d56,
+ .subvendor = 0x8086,
+ .subdevice = 0x4d56,
.name = "Intel ICH/AD1885",
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x8086,
- .device = 0x6000,
+ .subvendor = 0x8086,
+ .subdevice = 0x6000,
.mask = 0xfff0,
.name = "Intel ICH5/AD1985",
.type = AC97_TUNE_AD_SHARING
},
{
- .vendor = 0x8086,
- .device = 0xe000,
+ .subvendor = 0x8086,
+ .subdevice = 0xe000,
.mask = 0xfff0,
.name = "Intel ICH5/AD1985",
.type = AC97_TUNE_AD_SHARING
},
#if 0 /* FIXME: this seems wrong on most boards */
{
- .vendor = 0x8086,
- .device = 0xa000,
+ .subvendor = 0x8086,
+ .subdevice = 0xa000,
.mask = 0xfff0,
.name = "Intel ICH5/AD1985",
.type = AC97_TUNE_HP_ONLY
@@ -2849,7 +2855,7 @@ static struct pci_driver driver = {
static int __init alsa_card_intel8x0_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_intel8x0_exit(void)
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index 67da096d659..bb758c77d21 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -35,7 +35,6 @@
#include <sound/pcm.h>
#include <sound/ac97_codec.h>
#include <sound/info.h>
-#include <sound/control.h>
#include <sound/initval.h>
MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
@@ -292,60 +291,9 @@ static struct pci_device_id snd_intel8x0m_ids[] = {
#endif
{ 0, }
};
-static int snd_intel8x0m_switch_default_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol);
-static int snd_intel8x0m_switch_default_put(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol);
-static int snd_intel8x0m_switch_default_info(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo);
-
-#define PRIVATE_VALUE_INITIALIZER(r,m) (((r) & 0xffff) << 16 | ((m) & 0xffff))
-#define PRIVATE_VALUE_MASK(control) ((control)->private_value & 0xffff)
-#define PRIVATE_VALUE_REG(control) (((control)->private_value >> 16) & 0xffff)
-
-static snd_kcontrol_new_t snd_intel8x0m_mixer_switches[] __devinitdata = {
- { .name = "Off-hook Switch",
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .info = snd_intel8x0m_switch_default_info,
- .get = snd_intel8x0m_switch_default_get,
- .put = snd_intel8x0m_switch_default_put,
- .private_value = PRIVATE_VALUE_INITIALIZER(AC97_GPIO_STATUS,AC97_GPIO_LINE1_OH)
- }
-};
MODULE_DEVICE_TABLE(pci, snd_intel8x0m_ids);
-static int snd_intel8x0m_switch_default_info(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_info_t *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 1;
- return 0;
-}
-
-static int snd_intel8x0m_switch_default_get(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
-{
- unsigned short mask = PRIVATE_VALUE_MASK(kcontrol);
- unsigned short reg = PRIVATE_VALUE_REG(kcontrol);
- intel8x0_t *chip = snd_kcontrol_chip(kcontrol);
- unsigned int status;
- status = snd_ac97_read(chip->ac97, reg) & mask ? 1 : 0;
- ucontrol->value.integer.value[0] = status;
- return 0;
-}
-static int snd_intel8x0m_switch_default_put(snd_kcontrol_t *kcontrol,
- snd_ctl_elem_value_t *ucontrol)
-{
- unsigned short mask = PRIVATE_VALUE_MASK(kcontrol);
- unsigned short reg = PRIVATE_VALUE_REG(kcontrol);
- intel8x0_t *chip = snd_kcontrol_chip(kcontrol);
- unsigned short new_status = ucontrol->value.integer.value[0] ? mask : ~mask;
- return snd_ac97_update_bits(chip->ac97, reg,
- mask, new_status);
-}
/*
* Lowlevel I/O - busmaster
*/
@@ -500,6 +448,8 @@ static unsigned short snd_intel8x0_codec_read(ac97_t *ac97,
res = 0xffff;
}
}
+ if (reg == AC97_GPIO_STATUS)
+ iagetword(chip, 0); /* clear semaphore */
return res;
}
@@ -698,21 +648,6 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(snd_pcm_substream_t * substrea
return bytes_to_frames(substream->runtime, ptr);
}
-static int snd_intel8x0m_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
-{
- /* hook off/on on start/stop */
- /* Moved this to mixer control */
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- break;
- default:
- return -EINVAL;
- }
- return snd_intel8x0_pcm_trigger(substream,cmd);
-}
-
static int snd_intel8x0m_pcm_prepare(snd_pcm_substream_t * substream)
{
intel8x0_t *chip = snd_pcm_substream_chip(substream);
@@ -808,7 +743,7 @@ static snd_pcm_ops_t snd_intel8x0m_playback_ops = {
.hw_params = snd_intel8x0_hw_params,
.hw_free = snd_intel8x0_hw_free,
.prepare = snd_intel8x0m_pcm_prepare,
- .trigger = snd_intel8x0m_pcm_trigger,
+ .trigger = snd_intel8x0_pcm_trigger,
.pointer = snd_intel8x0_pcm_pointer,
};
@@ -819,7 +754,7 @@ static snd_pcm_ops_t snd_intel8x0m_capture_ops = {
.hw_params = snd_intel8x0_hw_params,
.hw_free = snd_intel8x0_hw_free,
.prepare = snd_intel8x0m_pcm_prepare,
- .trigger = snd_intel8x0m_pcm_trigger,
+ .trigger = snd_intel8x0_pcm_trigger,
.pointer = snd_intel8x0_pcm_pointer,
};
@@ -947,7 +882,6 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
ac97_t *x97;
int err;
unsigned int glob_sta = 0;
- unsigned int idx;
static ac97_bus_ops_t ops = {
.write = snd_intel8x0_codec_write,
.read = snd_intel8x0_codec_read,
@@ -983,10 +917,6 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock)
chip->ichd[ICHD_MDMIN].ac97 = x97;
chip->ichd[ICHD_MDMOUT].ac97 = x97;
}
- for (idx = 0; idx < ARRAY_SIZE(snd_intel8x0m_mixer_switches); idx++) {
- if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_intel8x0m_mixer_switches[idx], chip))) < 0)
- goto __err;
- }
chip->in_ac97_init = 0;
return 0;
@@ -1450,7 +1380,7 @@ static struct pci_driver driver = {
static int __init alsa_card_intel8x0m_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_intel8x0m_exit(void)
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index bb1de200817..79d8eda54f0 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -2541,7 +2541,7 @@ static struct pci_driver driver = {
static int __init alsa_card_korg1212_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_korg1212_exit(void)
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 2cf33083d7c..096f1513285 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -779,6 +779,12 @@ struct m3_quirk {
(e.g. for IrDA on Dell Inspirons) */
};
+struct m3_hv_quirk {
+ u16 vendor, device, subsystem_vendor, subsystem_device;
+ u32 config; /* ALLEGRO_CONFIG hardware volume bits */
+ int is_omnibook; /* Do HP OmniBook GPIO magic? */
+};
+
struct m3_list {
int curlen;
int mem_addr;
@@ -828,6 +834,7 @@ struct snd_m3 {
struct pci_dev *pci;
struct m3_quirk *quirk;
+ struct m3_hv_quirk *hv_quirk;
int dacs_active;
int timer_users;
@@ -851,6 +858,11 @@ struct snd_m3 {
m3_dma_t *substreams;
spinlock_t reg_lock;
+ spinlock_t ac97_lock;
+
+ snd_kcontrol_t *master_switch;
+ snd_kcontrol_t *master_volume;
+ struct tasklet_struct hwvol_tq;
#ifdef CONFIG_PM
u16 *suspend_mem;
@@ -968,6 +980,71 @@ static struct m3_quirk m3_quirk_list[] = {
{ NULL }
};
+/* These values came from the Windows driver. */
+static struct m3_hv_quirk m3_hv_quirk_list[] = {
+ /* Allegro chips */
+ { 0x125D, 0x1988, 0x0E11, 0x002E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+ { 0x125D, 0x1988, 0x0E11, 0x0094, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+ { 0x125D, 0x1988, 0x0E11, 0xB112, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+ { 0x125D, 0x1988, 0x0E11, 0xB114, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+ { 0x125D, 0x1988, 0x103C, 0x0012, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+ { 0x125D, 0x1988, 0x103C, 0x0018, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+ { 0x125D, 0x1988, 0x103C, 0x001C, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+ { 0x125D, 0x1988, 0x103C, 0x001D, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+ { 0x125D, 0x1988, 0x103C, 0x001E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+ { 0x125D, 0x1988, 0x107B, 0x3350, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+ { 0x125D, 0x1988, 0x10F7, 0x8338, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+ { 0x125D, 0x1988, 0x10F7, 0x833C, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+ { 0x125D, 0x1988, 0x10F7, 0x833D, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+ { 0x125D, 0x1988, 0x10F7, 0x833E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+ { 0x125D, 0x1988, 0x10F7, 0x833F, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+ { 0x125D, 0x1988, 0x13BD, 0x1018, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+ { 0x125D, 0x1988, 0x13BD, 0x1019, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+ { 0x125D, 0x1988, 0x13BD, 0x101A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+ { 0x125D, 0x1988, 0x14FF, 0x0F03, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+ { 0x125D, 0x1988, 0x14FF, 0x0F04, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+ { 0x125D, 0x1988, 0x14FF, 0x0F05, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+ { 0x125D, 0x1988, 0x156D, 0xB400, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+ { 0x125D, 0x1988, 0x156D, 0xB795, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+ { 0x125D, 0x1988, 0x156D, 0xB797, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+ { 0x125D, 0x1988, 0x156D, 0xC700, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+ { 0x125D, 0x1988, 0x1033, 0x80F1, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+ { 0x125D, 0x1988, 0x103C, 0x001A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, /* HP OmniBook 6100 */
+ { 0x125D, 0x1988, 0x107B, 0x340A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+ { 0x125D, 0x1988, 0x107B, 0x3450, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+ { 0x125D, 0x1988, 0x109F, 0x3134, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+ { 0x125D, 0x1988, 0x109F, 0x3161, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+ { 0x125D, 0x1988, 0x144D, 0x3280, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+ { 0x125D, 0x1988, 0x144D, 0x3281, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+ { 0x125D, 0x1988, 0x144D, 0xC002, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+ { 0x125D, 0x1988, 0x144D, 0xC003, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+ { 0x125D, 0x1988, 0x1509, 0x1740, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+ { 0x125D, 0x1988, 0x1610, 0x0010, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+ { 0x125D, 0x1988, 0x1042, 0x1042, HV_CTRL_ENABLE, 0 },
+ { 0x125D, 0x1988, 0x107B, 0x9500, HV_CTRL_ENABLE, 0 },
+ { 0x125D, 0x1988, 0x14FF, 0x0F06, HV_CTRL_ENABLE, 0 },
+ { 0x125D, 0x1988, 0x1558, 0x8586, HV_CTRL_ENABLE, 0 },
+ { 0x125D, 0x1988, 0x161F, 0x2011, HV_CTRL_ENABLE, 0 },
+ /* Maestro3 chips */
+ { 0x125D, 0x1998, 0x103C, 0x000E, HV_CTRL_ENABLE, 0 },
+ { 0x125D, 0x1998, 0x103C, 0x0010, HV_CTRL_ENABLE, 1 }, /* HP OmniBook 6000 */
+ { 0x125D, 0x1998, 0x103C, 0x0011, HV_CTRL_ENABLE, 1 }, /* HP OmniBook 500 */
+ { 0x125D, 0x1998, 0x103C, 0x001B, HV_CTRL_ENABLE, 0 },
+ { 0x125D, 0x1998, 0x104D, 0x80A6, HV_CTRL_ENABLE, 0 },
+ { 0x125D, 0x1998, 0x104D, 0x80AA, HV_CTRL_ENABLE, 0 },
+ { 0x125D, 0x1998, 0x107B, 0x5300, HV_CTRL_ENABLE, 0 },
+ { 0x125D, 0x1998, 0x110A, 0x1998, HV_CTRL_ENABLE, 0 },
+ { 0x125D, 0x1998, 0x13BD, 0x1015, HV_CTRL_ENABLE, 0 },
+ { 0x125D, 0x1998, 0x13BD, 0x101C, HV_CTRL_ENABLE, 0 },
+ { 0x125D, 0x1998, 0x13BD, 0x1802, HV_CTRL_ENABLE, 0 },
+ { 0x125D, 0x1998, 0x1599, 0x0715, HV_CTRL_ENABLE, 0 },
+ { 0x125D, 0x1998, 0x5643, 0x5643, HV_CTRL_ENABLE, 0 },
+ { 0x125D, 0x199A, 0x144D, 0x3260, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 },
+ { 0x125D, 0x199A, 0x144D, 0x3261, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 },
+ { 0x125D, 0x199A, 0x144D, 0xC000, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 },
+ { 0x125D, 0x199A, 0x144D, 0xC001, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 },
+ { 0 }
+};
/*
* lowlevel functions
@@ -1565,6 +1642,68 @@ static void snd_m3_update_ptr(m3_t *chip, m3_dma_t *s)
}
}
+static void snd_m3_update_hw_volume(unsigned long private_data)
+{
+ m3_t *chip = (m3_t *) private_data;
+ int x, val;
+ unsigned long flags;
+
+ /* Figure out which volume control button was pushed,
+ based on differences from the default register
+ values. */
+ x = inb(chip->iobase + SHADOW_MIX_REG_VOICE) & 0xee;
+
+ /* Reset the volume control registers. */
+ outb(0x88, chip->iobase + SHADOW_MIX_REG_VOICE);
+ outb(0x88, chip->iobase + HW_VOL_COUNTER_VOICE);
+ outb(0x88, chip->iobase + SHADOW_MIX_REG_MASTER);
+ outb(0x88, chip->iobase + HW_VOL_COUNTER_MASTER);
+
+ if (!chip->master_switch || !chip->master_volume)
+ return;
+
+ /* FIXME: we can't call snd_ac97_* functions since here is in tasklet. */
+ spin_lock_irqsave(&chip->ac97_lock, flags);
+
+ val = chip->ac97->regs[AC97_MASTER_VOL];
+ switch (x) {
+ case 0x88:
+ /* mute */
+ val ^= 0x8000;
+ chip->ac97->regs[AC97_MASTER_VOL] = val;
+ outw(val, chip->iobase + CODEC_DATA);
+ outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND);
+ snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &chip->master_switch->id);
+ break;
+ case 0xaa:
+ /* volume up */
+ if ((val & 0x7f) > 0)
+ val--;
+ if ((val & 0x7f00) > 0)
+ val -= 0x0100;
+ chip->ac97->regs[AC97_MASTER_VOL] = val;
+ outw(val, chip->iobase + CODEC_DATA);
+ outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND);
+ snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &chip->master_volume->id);
+ break;
+ case 0x66:
+ /* volume down */
+ if ((val & 0x7f) < 0x1f)
+ val++;
+ if ((val & 0x7f00) < 0x1f00)
+ val += 0x0100;
+ chip->ac97->regs[AC97_MASTER_VOL] = val;
+ outw(val, chip->iobase + CODEC_DATA);
+ outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND);
+ snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &chip->master_volume->id);
+ break;
+ }
+ spin_unlock_irqrestore(&chip->ac97_lock, flags);
+}
+
static irqreturn_t
snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
@@ -1576,7 +1715,10 @@ snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (status == 0xff)
return IRQ_NONE;
-
+
+ if (status & HV_INT_PENDING)
+ tasklet_hi_schedule(&chip->hwvol_tq);
+
/*
* ack an assp int if its running
* and has an int pending
@@ -1605,7 +1747,7 @@ snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
#endif
/* ack ints */
- snd_m3_outw(chip, HOST_INT_STATUS, status);
+ outb(status, chip->iobase + HOST_INT_STATUS);
return IRQ_HANDLED;
}
@@ -1842,24 +1984,32 @@ static unsigned short
snd_m3_ac97_read(ac97_t *ac97, unsigned short reg)
{
m3_t *chip = ac97->private_data;
+ unsigned long flags;
+ unsigned short data;
if (snd_m3_ac97_wait(chip))
return 0xffff;
+ spin_lock_irqsave(&chip->ac97_lock, flags);
snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND);
if (snd_m3_ac97_wait(chip))
return 0xffff;
- return snd_m3_inw(chip, CODEC_DATA);
+ data = snd_m3_inw(chip, CODEC_DATA);
+ spin_unlock_irqrestore(&chip->ac97_lock, flags);
+ return data;
}
static void
snd_m3_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
{
m3_t *chip = ac97->private_data;
+ unsigned long flags;
if (snd_m3_ac97_wait(chip))
return;
+ spin_lock_irqsave(&chip->ac97_lock, flags);
snd_m3_outw(chip, val, CODEC_DATA);
snd_m3_outb(chip, reg & 0x7f, CODEC_COMMAND);
+ spin_unlock_irqrestore(&chip->ac97_lock, flags);
}
@@ -1968,6 +2118,7 @@ static int __devinit snd_m3_mixer(m3_t *chip)
{
ac97_bus_t *pbus;
ac97_template_t ac97;
+ snd_ctl_elem_id_t id;
int err;
static ac97_bus_ops_t ops = {
.write = snd_m3_ac97_write,
@@ -1988,6 +2139,15 @@ static int __devinit snd_m3_mixer(m3_t *chip)
schedule_timeout(HZ / 10);
snd_ac97_write(chip->ac97, AC97_PCM, 0);
+ memset(&id, 0, sizeof(id));
+ id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ strcpy(id.name, "Master Playback Switch");
+ chip->master_switch = snd_ctl_find_id(chip->card, &id);
+ memset(&id, 0, sizeof(id));
+ id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ strcpy(id.name, "Master Playback Volume");
+ chip->master_volume = snd_ctl_find_id(chip->card, &id);
+
return 0;
}
@@ -2293,6 +2453,7 @@ static int
snd_m3_chip_init(m3_t *chip)
{
struct pci_dev *pcidev = chip->pci;
+ unsigned long io = chip->iobase;
u32 n;
u16 w;
u8 t; /* makes as much sense as 'n', no? */
@@ -2303,8 +2464,27 @@ snd_m3_chip_init(m3_t *chip)
DISABLE_LEGACY);
pci_write_config_word(pcidev, PCI_LEGACY_AUDIO_CTRL, w);
+ if (chip->hv_quirk && chip->hv_quirk->is_omnibook) {
+ /*
+ * Volume buttons on some HP OmniBook laptops don't work
+ * correctly. This makes them work for the most part.
+ *
+ * Volume up and down buttons on the laptop side work.
+ * Fn+cursor_up (volme up) works.
+ * Fn+cursor_down (volume down) doesn't work.
+ * Fn+F7 (mute) works acts as volume up.
+ */
+ outw(~(GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_MASK);
+ outw(inw(io + GPIO_DIRECTION) & ~(GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_DIRECTION);
+ outw((GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_DATA);
+ outw(0xffff, io + GPIO_MASK);
+ }
pci_read_config_dword(pcidev, PCI_ALLEGRO_CONFIG, &n);
- n &= REDUCED_DEBOUNCE;
+ n &= ~(HV_CTRL_ENABLE | REDUCED_DEBOUNCE | HV_BUTTON_FROM_GD);
+ if (chip->hv_quirk)
+ n |= chip->hv_quirk->config;
+ /* For some reason we must always use reduced debounce. */
+ n |= REDUCED_DEBOUNCE;
n |= PM_CTRL_ENABLE | CLK_DIV_BY_49 | USE_PCI_TIMING;
pci_write_config_dword(pcidev, PCI_ALLEGRO_CONFIG, n);
@@ -2332,6 +2512,12 @@ snd_m3_chip_init(m3_t *chip)
outb(RUN_ASSP, chip->iobase + ASSP_CONTROL_B);
+ outb(0x00, io + HARDWARE_VOL_CTRL);
+ outb(0x88, io + SHADOW_MIX_REG_VOICE);
+ outb(0x88, io + HW_VOL_COUNTER_VOICE);
+ outb(0x88, io + SHADOW_MIX_REG_MASTER);
+ outb(0x88, io + HW_VOL_COUNTER_MASTER);
+
return 0;
}
@@ -2341,7 +2527,7 @@ snd_m3_enable_ints(m3_t *chip)
unsigned long io = chip->iobase;
/* TODO: MPU401 not supported yet */
- outw(ASSP_INT_ENABLE /*| MPU401_INT_ENABLE*/, io + HOST_INT_CTRL);
+ outw(ASSP_INT_ENABLE | HV_INT_ENABLE /*| MPU401_INT_ENABLE*/, io + HOST_INT_CTRL);
outb(inb(io + ASSP_CONTROL_C) | ASSP_HOST_INT_ENABLE,
io + ASSP_CONTROL_C);
}
@@ -2367,7 +2553,7 @@ static int snd_m3_free(m3_t *chip)
kfree(chip->substreams);
}
if (chip->iobase) {
- snd_m3_outw(chip, HOST_INT_CTRL, 0); /* disable ints */
+ outw(0, chip->iobase + HOST_INT_CTRL); /* disable ints */
}
#ifdef CONFIG_PM
@@ -2486,7 +2672,7 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
m3_t *chip;
int i, err;
struct m3_quirk *quirk;
- u16 subsystem_vendor, subsystem_device;
+ struct m3_hv_quirk *hv_quirk;
static snd_device_ops_t ops = {
.dev_free = snd_m3_dev_free,
};
@@ -2524,18 +2710,25 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
chip->pci = pci;
chip->irq = -1;
- pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
- pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device);
-
for (quirk = m3_quirk_list; quirk->vendor; quirk++) {
- if (subsystem_vendor == quirk->vendor &&
- subsystem_device == quirk->device) {
+ if (pci->subsystem_vendor == quirk->vendor &&
+ pci->subsystem_device == quirk->device) {
printk(KERN_INFO "maestro3: enabled hack for '%s'\n", quirk->name);
chip->quirk = quirk;
break;
}
}
+ for (hv_quirk = m3_hv_quirk_list; hv_quirk->vendor; hv_quirk++) {
+ if (pci->vendor == hv_quirk->vendor &&
+ pci->device == hv_quirk->device &&
+ pci->subsystem_vendor == hv_quirk->subsystem_vendor &&
+ pci->subsystem_device == hv_quirk->subsystem_device) {
+ chip->hv_quirk = hv_quirk;
+ break;
+ }
+ }
+
chip->external_amp = enable_amp;
if (amp_gpio >= 0 && amp_gpio <= 0x0f)
chip->amp_gpio = amp_gpio;
@@ -2593,6 +2786,9 @@ snd_m3_create(snd_card_t *card, struct pci_dev *pci,
return err;
}
+ spin_lock_init(&chip->ac97_lock);
+ tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip);
+
if ((err = snd_m3_mixer(chip)) < 0)
return err;
@@ -2702,7 +2898,7 @@ static struct pci_driver driver = {
static int __init alsa_card_m3_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_m3_exit(void)
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index 65bb0f47af2..082c0d0f73d 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -1431,7 +1431,7 @@ static struct pci_driver driver = {
static int __init alsa_card_mixart_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_mixart_exit(void)
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index 356fbeac6f9..8a52091f855 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -1645,7 +1645,7 @@ static struct pci_driver driver = {
static int __init alsa_card_nm256_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_nm256_exit(void)
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index b96acd5a57d..b7b554df670 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -2031,7 +2031,7 @@ static struct pci_driver driver = {
static int __init alsa_card_rme32_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_rme32_exit(void)
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index 8e2666841d2..10c4f45a913 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -2437,7 +2437,7 @@ static struct pci_driver driver = {
static int __init alsa_card_rme96_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_rme96_exit(void)
diff --git a/sound/pci/rme9652/Makefile b/sound/pci/rme9652/Makefile
index 917374c9cd4..d2c294e136f 100644
--- a/sound/pci/rme9652/Makefile
+++ b/sound/pci/rme9652/Makefile
@@ -5,7 +5,9 @@
snd-rme9652-objs := rme9652.o
snd-hdsp-objs := hdsp.o
+snd-hdspm-objs := hdspm.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_RME9652) += snd-rme9652.o
obj-$(CONFIG_SND_HDSP) += snd-hdsp.o
+obj-$(CONFIG_SND_HDSPM) +=snd-hdspm.o
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 12efbf0fab5..a673cc438b9 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -559,18 +559,22 @@ static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer
{
dmab->dev.type = SNDRV_DMA_TYPE_DEV;
dmab->dev.dev = snd_dma_pci_data(pci);
- if (! snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
- size, dmab) < 0)
- return -ENOMEM;
+ if (snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
+ if (dmab->bytes >= size)
+ return 0;
}
+ if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+ size, dmab) < 0)
+ return -ENOMEM;
return 0;
}
static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
{
- if (dmab->area)
+ if (dmab->area) {
+ dmab->dev.dev = NULL; /* make it anonymous */
snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci));
+ }
}
@@ -4912,19 +4916,9 @@ static int __devinit hdsp_request_fw_loader(hdsp_t *hdsp)
release_firmware(fw);
return -EINVAL;
}
-#ifdef SNDRV_BIG_ENDIAN
- {
- int i;
- u32 *src = (u32*)fw->data;
- for (i = 0; i < ARRAY_SIZE(hdsp->firmware_cache); i++, src++)
- hdsp->firmware_cache[i] = ((*src & 0x000000ff) << 16) |
- ((*src & 0x0000ff00) << 8) |
- ((*src & 0x00ff0000) >> 8) |
- ((*src & 0xff000000) >> 16);
- }
-#else
+
memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache));
-#endif
+
release_firmware(fw);
hdsp->state |= HDSP_FirmwareCached;
@@ -5194,7 +5188,7 @@ static struct pci_driver driver = {
static int __init alsa_card_hdsp_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_hdsp_exit(void)
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
new file mode 100644
index 00000000000..9e86d0eb41c
--- /dev/null
+++ b/sound/pci/rme9652/hdspm.c
@@ -0,0 +1,3671 @@
+/* -*- linux-c -*-
+ *
+ * ALSA driver for RME Hammerfall DSP MADI audio interface(s)
+ *
+ * Copyright (c) 2003 Winfried Ritsch (IEM)
+ * code based on hdsp.c Paul Davis
+ * Marcus Andersson
+ * Thomas Charbonnel
+ *
+ * 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 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 <sound/driver.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/moduleparam.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/info.h>
+#include <sound/asoundef.h>
+#include <sound/rawmidi.h>
+#include <sound/hwdep.h>
+#include <sound/initval.h>
+
+#include <sound/hdspm.h>
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
+
+/* Disable precise pointer at start */
+static int precise_ptr[SNDRV_CARDS];
+
+/* Send all playback to line outs */
+static int line_outs_monitor[SNDRV_CARDS];
+
+/* Enable Analog Outs on Channel 63/64 by default */
+static int enable_monitor[SNDRV_CARDS];
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for RME HDSPM interface.");
+
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for RME HDSPM interface.");
+
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards.");
+
+module_param_array(precise_ptr, bool, NULL, 0444);
+MODULE_PARM_DESC(precise_ptr, "Enable precise pointer, or disable.");
+
+module_param_array(line_outs_monitor, bool, NULL, 0444);
+MODULE_PARM_DESC(line_outs_monitor,
+ "Send playback streams to analog outs by default.");
+
+module_param_array(enable_monitor, bool, NULL, 0444);
+MODULE_PARM_DESC(enable_monitor,
+ "Enable Analog Out on Channel 63/64 by default.");
+
+MODULE_AUTHOR
+ ("Winfried Ritsch <ritsch_AT_iem.at>, Paul Davis <paul@linuxaudiosystems.com>, "
+ "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>");
+MODULE_DESCRIPTION("RME HDSPM");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
+
+/* --- Write registers. ---
+ These are defined as byte-offsets from the iobase value. */
+
+#define HDSPM_controlRegister 64
+#define HDSPM_interruptConfirmation 96
+#define HDSPM_control2Reg 256 /* not in specs ???????? */
+#define HDSPM_midiDataOut0 352 /* just believe in old code */
+#define HDSPM_midiDataOut1 356
+
+/* DMA enable for 64 channels, only Bit 0 is relevant */
+#define HDSPM_outputEnableBase 512 /* 512-767 input DMA */
+#define HDSPM_inputEnableBase 768 /* 768-1023 output DMA */
+
+/* 16 page addresses for each of the 64 channels DMA buffer in and out
+ (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */
+#define HDSPM_pageAddressBufferOut 8192
+#define HDSPM_pageAddressBufferIn (HDSPM_pageAddressBufferOut+64*16*4)
+
+#define HDSPM_MADI_mixerBase 32768 /* 32768-65535 for 2x64x64 Fader */
+
+#define HDSPM_MATRIX_MIXER_SIZE 8192 /* = 2*64*64 * 4 Byte => 32kB */
+
+/* --- Read registers. ---
+ These are defined as byte-offsets from the iobase value */
+#define HDSPM_statusRegister 0
+#define HDSPM_statusRegister2 96
+
+#define HDSPM_midiDataIn0 360
+#define HDSPM_midiDataIn1 364
+
+/* status is data bytes in MIDI-FIFO (0-128) */
+#define HDSPM_midiStatusOut0 384
+#define HDSPM_midiStatusOut1 388
+#define HDSPM_midiStatusIn0 392
+#define HDSPM_midiStatusIn1 396
+
+
+/* the meters are regular i/o-mapped registers, but offset
+ considerably from the rest. the peak registers are reset
+ when read; the least-significant 4 bits are full-scale counters;
+ the actual peak value is in the most-significant 24 bits.
+*/
+#define HDSPM_MADI_peakrmsbase 4096 /* 4096-8191 2x64x32Bit Meters */
+
+/* --- Control Register bits --------- */
+#define HDSPM_Start (1<<0) /* start engine */
+
+#define HDSPM_Latency0 (1<<1) /* buffer size = 2^n */
+#define HDSPM_Latency1 (1<<2) /* where n is defined */
+#define HDSPM_Latency2 (1<<3) /* by Latency{2,1,0} */
+
+#define HDSPM_ClockModeMaster (1<<4) /* 1=Master, 0=Slave/Autosync */
+
+#define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */
+
+#define HDSPM_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */
+#define HDSPM_Frequency1 (1<<7) /* 0=32kHz/64kHz */
+#define HDSPM_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */
+#define HDSPM_QuadSpeed (1<<31) /* quad speed bit, not implemented now */
+
+#define HDSPM_TX_64ch (1<<10) /* Output 64channel MODE=1,
+ 56channelMODE=0 */
+
+#define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode,
+ 0=off, 1=on */
+
+#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax */
+#define HDSPM_InputSelect1 (1<<15) /* should be 0 */
+
+#define HDSPM_SyncRef0 (1<<16) /* 0=WOrd, 1=MADI */
+#define HDSPM_SyncRef1 (1<<17) /* should be 0 */
+
+#define HDSPM_clr_tms (1<<19) /* clear track marker, do not use
+ AES additional bits in
+ lower 5 Audiodatabits ??? */
+
+#define HDSPM_Midi0InterruptEnable (1<<22)
+#define HDSPM_Midi1InterruptEnable (1<<23)
+
+#define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */
+
+
+/* --- bit helper defines */
+#define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2)
+#define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1)
+#define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1)
+#define HDSPM_InputOptical 0
+#define HDSPM_InputCoaxial (HDSPM_InputSelect0)
+#define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1)
+#define HDSPM_SyncRef_Word 0
+#define HDSPM_SyncRef_MADI (HDSPM_SyncRef0)
+
+#define HDSPM_SYNC_FROM_WORD 0 /* Preferred sync reference */
+#define HDSPM_SYNC_FROM_MADI 1 /* choices - used by "pref_sync_ref" */
+
+#define HDSPM_Frequency32KHz HDSPM_Frequency0
+#define HDSPM_Frequency44_1KHz HDSPM_Frequency1
+#define HDSPM_Frequency48KHz (HDSPM_Frequency1|HDSPM_Frequency0)
+#define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0)
+#define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1)
+#define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|HDSPM_Frequency0)
+
+/* --- for internal discrimination */
+#define HDSPM_CLOCK_SOURCE_AUTOSYNC 0 /* Sample Clock Sources */
+#define HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ 1
+#define HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ 2
+#define HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ 3
+#define HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ 4
+#define HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ 5
+#define HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ 6
+#define HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ 7
+#define HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ 8
+#define HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ 9
+
+/* Synccheck Status */
+#define HDSPM_SYNC_CHECK_NO_LOCK 0
+#define HDSPM_SYNC_CHECK_LOCK 1
+#define HDSPM_SYNC_CHECK_SYNC 2
+
+/* AutoSync References - used by "autosync_ref" control switch */
+#define HDSPM_AUTOSYNC_FROM_WORD 0
+#define HDSPM_AUTOSYNC_FROM_MADI 1
+#define HDSPM_AUTOSYNC_FROM_NONE 2
+
+/* Possible sources of MADI input */
+#define HDSPM_OPTICAL 0 /* optical */
+#define HDSPM_COAXIAL 1 /* BNC */
+
+#define hdspm_encode_latency(x) (((x)<<1) & HDSPM_LatencyMask)
+#define hdspm_decode_latency(x) (((x) & HDSPM_LatencyMask)>>1)
+
+#define hdspm_encode_in(x) (((x)&0x3)<<14)
+#define hdspm_decode_in(x) (((x)>>14)&0x3)
+
+/* --- control2 register bits --- */
+#define HDSPM_TMS (1<<0)
+#define HDSPM_TCK (1<<1)
+#define HDSPM_TDI (1<<2)
+#define HDSPM_JTAG (1<<3)
+#define HDSPM_PWDN (1<<4)
+#define HDSPM_PROGRAM (1<<5)
+#define HDSPM_CONFIG_MODE_0 (1<<6)
+#define HDSPM_CONFIG_MODE_1 (1<<7)
+/*#define HDSPM_VERSION_BIT (1<<8) not defined any more*/
+#define HDSPM_BIGENDIAN_MODE (1<<9)
+#define HDSPM_RD_MULTIPLE (1<<10)
+
+/* --- Status Register bits --- */
+#define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */
+#define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn. MODE=0 */
+#define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1 (like inp0) */
+#define HDSPM_madiLock (1<<3) /* MADI Locked =1, no=0 */
+
+#define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
+ /* since 64byte accurate last 6 bits
+ are not used */
+
+#define HDSPM_madiSync (1<<18) /* MADI is in sync */
+#define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */
+
+#define HDSPM_madiFreq0 (1<<22) /* system freq 0=error */
+#define HDSPM_madiFreq1 (1<<23) /* 1=32, 2=44.1 3=48 */
+#define HDSPM_madiFreq2 (1<<24) /* 4=64, 5=88.2 6=96 */
+#define HDSPM_madiFreq3 (1<<25) /* 7=128, 8=176.4 9=192 */
+
+#define HDSPM_BufferID (1<<26) /* (Double)Buffer ID toggles with Interrupt */
+#define HDSPM_midi0IRQPending (1<<30) /* MIDI IRQ is pending */
+#define HDSPM_midi1IRQPending (1<<31) /* and aktiv */
+
+/* --- status bit helpers */
+#define HDSPM_madiFreqMask (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2|HDSPM_madiFreq3)
+#define HDSPM_madiFreq32 (HDSPM_madiFreq0)
+#define HDSPM_madiFreq44_1 (HDSPM_madiFreq1)
+#define HDSPM_madiFreq48 (HDSPM_madiFreq0|HDSPM_madiFreq1)
+#define HDSPM_madiFreq64 (HDSPM_madiFreq2)
+#define HDSPM_madiFreq88_2 (HDSPM_madiFreq0|HDSPM_madiFreq2)
+#define HDSPM_madiFreq96 (HDSPM_madiFreq1|HDSPM_madiFreq2)
+#define HDSPM_madiFreq128 (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2)
+#define HDSPM_madiFreq176_4 (HDSPM_madiFreq3)
+#define HDSPM_madiFreq192 (HDSPM_madiFreq3|HDSPM_madiFreq0)
+
+/* Status2 Register bits */
+
+#define HDSPM_version0 (1<<0) /* not realy defined but I guess */
+#define HDSPM_version1 (1<<1) /* in former cards it was ??? */
+#define HDSPM_version2 (1<<2)
+
+#define HDSPM_wcLock (1<<3) /* Wordclock is detected and locked */
+#define HDSPM_wcSync (1<<4) /* Wordclock is in sync with systemclock */
+
+#define HDSPM_wc_freq0 (1<<5) /* input freq detected via autosync */
+#define HDSPM_wc_freq1 (1<<6) /* 001=32, 010==44.1, 011=48, */
+#define HDSPM_wc_freq2 (1<<7) /* 100=64, 101=88.2, 110=96, */
+/* missing Bit for 111=128, 1000=176.4, 1001=192 */
+
+#define HDSPM_SelSyncRef0 (1<<8) /* Sync Source in slave mode */
+#define HDSPM_SelSyncRef1 (1<<9) /* 000=word, 001=MADI, */
+#define HDSPM_SelSyncRef2 (1<<10) /* 111=no valid signal */
+
+#define HDSPM_wc_valid (HDSPM_wcLock|HDSPM_wcSync)
+
+#define HDSPM_wcFreqMask (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2)
+#define HDSPM_wcFreq32 (HDSPM_wc_freq0)
+#define HDSPM_wcFreq44_1 (HDSPM_wc_freq1)
+#define HDSPM_wcFreq48 (HDSPM_wc_freq0|HDSPM_wc_freq1)
+#define HDSPM_wcFreq64 (HDSPM_wc_freq2)
+#define HDSPM_wcFreq88_2 (HDSPM_wc_freq0|HDSPM_wc_freq2)
+#define HDSPM_wcFreq96 (HDSPM_wc_freq1|HDSPM_wc_freq2)
+
+
+#define HDSPM_SelSyncRefMask (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2)
+#define HDSPM_SelSyncRef_WORD 0
+#define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0)
+#define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2)
+
+/* Mixer Values */
+#define UNITY_GAIN 32768 /* = 65536/2 */
+#define MINUS_INFINITY_GAIN 0
+
+/* PCI info */
+#ifndef PCI_VENDOR_ID_XILINX
+#define PCI_VENDOR_ID_XILINX 0x10ee
+#endif
+#ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP
+#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5
+#endif
+#ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI
+#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI 0x3fc6
+#endif
+
+
+/* Number of channels for different Speed Modes */
+#define MADI_SS_CHANNELS 64
+#define MADI_DS_CHANNELS 32
+#define MADI_QS_CHANNELS 16
+
+/* the size of a substream (1 mono data stream) */
+#define HDSPM_CHANNEL_BUFFER_SAMPLES (16*1024)
+#define HDSPM_CHANNEL_BUFFER_BYTES (4*HDSPM_CHANNEL_BUFFER_SAMPLES)
+
+/* the size of the area we need to allocate for DMA transfers. the
+ size is the same regardless of the number of channels, and
+ also the latency to use.
+ for one direction !!!
+*/
+#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
+#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
+
+typedef struct _hdspm hdspm_t;
+typedef struct _hdspm_midi hdspm_midi_t;
+
+struct _hdspm_midi {
+ hdspm_t *hdspm;
+ int id;
+ snd_rawmidi_t *rmidi;
+ snd_rawmidi_substream_t *input;
+ snd_rawmidi_substream_t *output;
+ char istimer; /* timer in use */
+ struct timer_list timer;
+ spinlock_t lock;
+ int pending;
+};
+
+struct _hdspm {
+ spinlock_t lock;
+ snd_pcm_substream_t *capture_substream; /* only one playback */
+ snd_pcm_substream_t *playback_substream; /* and/or capture stream */
+
+ char *card_name; /* for procinfo */
+ unsigned short firmware_rev; /* dont know if relevant */
+
+ int precise_ptr; /* use precise pointers, to be tested */
+ int monitor_outs; /* set up monitoring outs init flag */
+
+ u32 control_register; /* cached value */
+ u32 control2_register; /* cached value */
+
+ hdspm_midi_t midi[2];
+ struct tasklet_struct midi_tasklet;
+
+ size_t period_bytes;
+ unsigned char ss_channels; /* channels of card in single speed */
+ unsigned char ds_channels; /* Double Speed */
+ unsigned char qs_channels; /* Quad Speed */
+
+ unsigned char *playback_buffer; /* suitably aligned address */
+ unsigned char *capture_buffer; /* suitably aligned address */
+
+ pid_t capture_pid; /* process id which uses capture */
+ pid_t playback_pid; /* process id which uses capture */
+ int running; /* running status */
+
+ int last_external_sample_rate; /* samplerate mystic ... */
+ int last_internal_sample_rate;
+ int system_sample_rate;
+
+ char *channel_map; /* channel map for DS and Quadspeed */
+
+ int dev; /* Hardware vars... */
+ int irq;
+ unsigned long port;
+ void __iomem *iobase;
+
+ int irq_count; /* for debug */
+
+ snd_card_t *card; /* one card */
+ snd_pcm_t *pcm; /* has one pcm */
+ snd_hwdep_t *hwdep; /* and a hwdep for additional ioctl */
+ struct pci_dev *pci; /* and an pci info */
+
+ /* Mixer vars */
+ snd_kcontrol_t *playback_mixer_ctls[HDSPM_MAX_CHANNELS]; /* fast alsa mixer */
+ snd_kcontrol_t *input_mixer_ctls[HDSPM_MAX_CHANNELS]; /* but input to much, so not used */
+ hdspm_mixer_t *mixer; /* full mixer accessable over mixer ioctl or hwdep-device */
+
+};
+
+/* These tables map the ALSA channels 1..N to the channels that we
+ need to use in order to find the relevant channel buffer. RME
+ refer to this kind of mapping as between "the ADAT channel and
+ the DMA channel." We index it using the logical audio channel,
+ and the value is the DMA channel (i.e. channel buffer number)
+ where the data for that channel can be read/written from/to.
+*/
+
+static char channel_map_madi_ss[HDSPM_MAX_CHANNELS] = {
+ 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55,
+ 56, 57, 58, 59, 60, 61, 62, 63
+};
+
+static char channel_map_madi_ds[HDSPM_MAX_CHANNELS] = {
+ 0, 2, 4, 6, 8, 10, 12, 14,
+ 16, 18, 20, 22, 24, 26, 28, 30,
+ 32, 34, 36, 38, 40, 42, 44, 46,
+ 48, 50, 52, 54, 56, 58, 60, 62,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+static char channel_map_madi_qs[HDSPM_MAX_CHANNELS] = {
+ 0, 4, 8, 12, 16, 20, 24, 28,
+ 32, 36, 40, 44, 48, 52, 56, 60
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+
+static struct pci_device_id snd_hdspm_ids[] = {
+ {
+ .vendor = PCI_VENDOR_ID_XILINX,
+ .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .class = 0,
+ .class_mask = 0,
+ .driver_data = 0},
+ {0,}
+};
+
+MODULE_DEVICE_TABLE(pci, snd_hdspm_ids);
+
+/* prototypes */
+static int __devinit snd_hdspm_create_alsa_devices(snd_card_t * card,
+ hdspm_t * hdspm);
+static int __devinit snd_hdspm_create_pcm(snd_card_t * card,
+ hdspm_t * hdspm);
+
+static inline void snd_hdspm_initialize_midi_flush(hdspm_t * hdspm);
+static int hdspm_update_simple_mixer_controls(hdspm_t * hdspm);
+static int hdspm_autosync_ref(hdspm_t * hdspm);
+static int snd_hdspm_set_defaults(hdspm_t * hdspm);
+static void hdspm_set_sgbuf(hdspm_t * hdspm, struct snd_sg_buf *sgbuf,
+ unsigned int reg, int channels);
+
+/* Write/read to/from HDSPM with Adresses in Bytes
+ not words but only 32Bit writes are allowed */
+
+static inline void hdspm_write(hdspm_t * hdspm, unsigned int reg,
+ unsigned int val)
+{
+ writel(val, hdspm->iobase + reg);
+}
+
+static inline unsigned int hdspm_read(hdspm_t * hdspm, unsigned int reg)
+{
+ return readl(hdspm->iobase + reg);
+}
+
+/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader
+ mixer is write only on hardware so we have to cache him for read
+ each fader is a u32, but uses only the first 16 bit */
+
+static inline int hdspm_read_in_gain(hdspm_t * hdspm, unsigned int chan,
+ unsigned int in)
+{
+ if (chan > HDSPM_MIXER_CHANNELS || in > HDSPM_MIXER_CHANNELS)
+ return 0;
+
+ return hdspm->mixer->ch[chan].in[in];
+}
+
+static inline int hdspm_read_pb_gain(hdspm_t * hdspm, unsigned int chan,
+ unsigned int pb)
+{
+ if (chan > HDSPM_MIXER_CHANNELS || pb > HDSPM_MIXER_CHANNELS)
+ return 0;
+ return hdspm->mixer->ch[chan].pb[pb];
+}
+
+static inline int hdspm_write_in_gain(hdspm_t * hdspm, unsigned int chan,
+ unsigned int in, unsigned short data)
+{
+ if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
+ return -1;
+
+ hdspm_write(hdspm,
+ HDSPM_MADI_mixerBase +
+ ((in + 128 * chan) * sizeof(u32)),
+ (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF));
+ return 0;
+}
+
+static inline int hdspm_write_pb_gain(hdspm_t * hdspm, unsigned int chan,
+ unsigned int pb, unsigned short data)
+{
+ if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
+ return -1;
+
+ hdspm_write(hdspm,
+ HDSPM_MADI_mixerBase +
+ ((64 + pb + 128 * chan) * sizeof(u32)),
+ (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF));
+ return 0;
+}
+
+
+/* enable DMA for specific channels, now available for DSP-MADI */
+static inline void snd_hdspm_enable_in(hdspm_t * hdspm, int i, int v)
+{
+ hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v);
+}
+
+static inline void snd_hdspm_enable_out(hdspm_t * hdspm, int i, int v)
+{
+ hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v);
+}
+
+/* check if same process is writing and reading */
+static inline int snd_hdspm_use_is_exclusive(hdspm_t * hdspm)
+{
+ unsigned long flags;
+ int ret = 1;
+
+ spin_lock_irqsave(&hdspm->lock, flags);
+ if ((hdspm->playback_pid != hdspm->capture_pid) &&
+ (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) {
+ ret = 0;
+ }
+ spin_unlock_irqrestore(&hdspm->lock, flags);
+ return ret;
+}
+
+/* check for external sample rate */
+static inline int hdspm_external_sample_rate(hdspm_t * hdspm)
+{
+ unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+ unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
+ unsigned int rate_bits;
+ int rate = 0;
+
+ /* if wordclock has synced freq and wordclock is valid */
+ if ((status2 & HDSPM_wcLock) != 0 &&
+ (status & HDSPM_SelSyncRef0) == 0) {
+
+ rate_bits = status2 & HDSPM_wcFreqMask;
+
+ switch (rate_bits) {
+ case HDSPM_wcFreq32:
+ rate = 32000;
+ break;
+ case HDSPM_wcFreq44_1:
+ rate = 44100;
+ break;
+ case HDSPM_wcFreq48:
+ rate = 48000;
+ break;
+ case HDSPM_wcFreq64:
+ rate = 64000;
+ break;
+ case HDSPM_wcFreq88_2:
+ rate = 88200;
+ break;
+ case HDSPM_wcFreq96:
+ rate = 96000;
+ break;
+ /* Quadspeed Bit missing ???? */
+ default:
+ rate = 0;
+ break;
+ }
+ }
+
+ /* if rate detected and Syncref is Word than have it, word has priority to MADI */
+ if (rate != 0
+ && (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
+ return rate;
+
+ /* maby a madi input (which is taken if sel sync is madi) */
+ if (status & HDSPM_madiLock) {
+ rate_bits = status & HDSPM_madiFreqMask;
+
+ switch (rate_bits) {
+ case HDSPM_madiFreq32:
+ rate = 32000;
+ break;
+ case HDSPM_madiFreq44_1:
+ rate = 44100;
+ break;
+ case HDSPM_madiFreq48:
+ rate = 48000;
+ break;
+ case HDSPM_madiFreq64:
+ rate = 64000;
+ break;
+ case HDSPM_madiFreq88_2:
+ rate = 88200;
+ break;
+ case HDSPM_madiFreq96:
+ rate = 96000;
+ break;
+ case HDSPM_madiFreq128:
+ rate = 128000;
+ break;
+ case HDSPM_madiFreq176_4:
+ rate = 176400;
+ break;
+ case HDSPM_madiFreq192:
+ rate = 192000;
+ break;
+ default:
+ rate = 0;
+ break;
+ }
+ }
+ return rate;
+}
+
+/* Latency function */
+static inline void hdspm_compute_period_size(hdspm_t * hdspm)
+{
+ hdspm->period_bytes =
+ 1 << ((hdspm_decode_latency(hdspm->control_register) + 8));
+}
+
+static snd_pcm_uframes_t hdspm_hw_pointer(hdspm_t * hdspm)
+{
+ int position;
+
+ position = hdspm_read(hdspm, HDSPM_statusRegister);
+
+ if (!hdspm->precise_ptr) {
+ return (position & HDSPM_BufferID) ? (hdspm->period_bytes /
+ 4) : 0;
+ }
+
+ /* hwpointer comes in bytes and is 64Bytes accurate (by docu since PCI Burst)
+ i have experimented that it is at most 64 Byte to much for playing
+ so substraction of 64 byte should be ok for ALSA, but use it only
+ for application where you know what you do since if you come to
+ near with record pointer it can be a disaster */
+
+ position &= HDSPM_BufferPositionMask;
+ position = ((position - 64) % (2 * hdspm->period_bytes)) / 4;
+
+ return position;
+}
+
+
+static inline void hdspm_start_audio(hdspm_t * s)
+{
+ s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start);
+ hdspm_write(s, HDSPM_controlRegister, s->control_register);
+}
+
+static inline void hdspm_stop_audio(hdspm_t * s)
+{
+ s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable);
+ hdspm_write(s, HDSPM_controlRegister, s->control_register);
+}
+
+/* should I silence all or only opened ones ? doit all for first even is 4MB*/
+static inline void hdspm_silence_playback(hdspm_t * hdspm)
+{
+ int i;
+ int n = hdspm->period_bytes;
+ void *buf = hdspm->playback_buffer;
+
+ snd_assert(buf != NULL, return);
+
+ for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
+ memset(buf, 0, n);
+ buf += HDSPM_CHANNEL_BUFFER_BYTES;
+ }
+}
+
+static int hdspm_set_interrupt_interval(hdspm_t * s, unsigned int frames)
+{
+ int n;
+
+ spin_lock_irq(&s->lock);
+
+ frames >>= 7;
+ n = 0;
+ while (frames) {
+ n++;
+ frames >>= 1;
+ }
+ s->control_register &= ~HDSPM_LatencyMask;
+ s->control_register |= hdspm_encode_latency(n);
+
+ hdspm_write(s, HDSPM_controlRegister, s->control_register);
+
+ hdspm_compute_period_size(s);
+
+ spin_unlock_irq(&s->lock);
+
+ return 0;
+}
+
+
+/* dummy set rate lets see what happens */
+static int hdspm_set_rate(hdspm_t * hdspm, int rate, int called_internally)
+{
+ int reject_if_open = 0;
+ int current_rate;
+ int rate_bits;
+ int not_set = 0;
+
+ /* ASSUMPTION: hdspm->lock is either set, or there is no need for
+ it (e.g. during module initialization).
+ */
+
+ if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
+
+ /* SLAVE --- */
+ if (called_internally) {
+
+ /* request from ctl or card initialization
+ just make a warning an remember setting
+ for future master mode switching */
+
+ snd_printk
+ (KERN_WARNING "HDSPM: Warning: device is not running as a clock master.\n");
+ not_set = 1;
+ } else {
+
+ /* hw_param request while in AutoSync mode */
+ int external_freq =
+ hdspm_external_sample_rate(hdspm);
+
+ if ((hdspm_autosync_ref(hdspm) ==
+ HDSPM_AUTOSYNC_FROM_NONE)) {
+
+ snd_printk(KERN_WARNING "HDSPM: Detected no Externel Sync \n");
+ not_set = 1;
+
+ } else if (rate != external_freq) {
+
+ snd_printk
+ (KERN_WARNING "HDSPM: Warning: No AutoSync source for requested rate\n");
+ not_set = 1;
+ }
+ }
+ }
+
+ current_rate = hdspm->system_sample_rate;
+
+ /* Changing between Singe, Double and Quad speed is not
+ allowed if any substreams are open. This is because such a change
+ causes a shift in the location of the DMA buffers and a reduction
+ in the number of available buffers.
+
+ Note that a similar but essentially insoluble problem exists for
+ externally-driven rate changes. All we can do is to flag rate
+ changes in the read/write routines.
+ */
+
+ switch (rate) {
+ case 32000:
+ if (current_rate > 48000) {
+ reject_if_open = 1;
+ }
+ rate_bits = HDSPM_Frequency32KHz;
+ break;
+ case 44100:
+ if (current_rate > 48000) {
+ reject_if_open = 1;
+ }
+ rate_bits = HDSPM_Frequency44_1KHz;
+ break;
+ case 48000:
+ if (current_rate > 48000) {
+ reject_if_open = 1;
+ }
+ rate_bits = HDSPM_Frequency48KHz;
+ break;
+ case 64000:
+ if (current_rate <= 48000) {
+ reject_if_open = 1;
+ }
+ rate_bits = HDSPM_Frequency64KHz;
+ break;
+ case 88200:
+ if (current_rate <= 48000) {
+ reject_if_open = 1;
+ }
+ rate_bits = HDSPM_Frequency88_2KHz;
+ break;
+ case 96000:
+ if (current_rate <= 48000) {
+ reject_if_open = 1;
+ }
+ rate_bits = HDSPM_Frequency96KHz;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (reject_if_open
+ && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {
+ snd_printk
+ (KERN_ERR "HDSPM: cannot change between single- and double-speed mode (capture PID = %d, playback PID = %d)\n",
+ hdspm->capture_pid, hdspm->playback_pid);
+ return -EBUSY;
+ }
+
+ hdspm->control_register &= ~HDSPM_FrequencyMask;
+ hdspm->control_register |= rate_bits;
+ hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+ if (rate > 64000)
+ hdspm->channel_map = channel_map_madi_qs;
+ else if (rate > 48000)
+ hdspm->channel_map = channel_map_madi_ds;
+ else
+ hdspm->channel_map = channel_map_madi_ss;
+
+ hdspm->system_sample_rate = rate;
+
+ if (not_set != 0)
+ return -1;
+
+ return 0;
+}
+
+/* mainly for init to 0 on load */
+static void all_in_all_mixer(hdspm_t * hdspm, int sgain)
+{
+ int i, j;
+ unsigned int gain =
+ (sgain > UNITY_GAIN) ? UNITY_GAIN : (sgain < 0) ? 0 : sgain;
+
+ for (i = 0; i < HDSPM_MIXER_CHANNELS; i++)
+ for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) {
+ hdspm_write_in_gain(hdspm, i, j, gain);
+ hdspm_write_pb_gain(hdspm, i, j, gain);
+ }
+}
+
+/*----------------------------------------------------------------------------
+ MIDI
+ ----------------------------------------------------------------------------*/
+
+static inline unsigned char snd_hdspm_midi_read_byte (hdspm_t *hdspm, int id)
+{
+ /* the hardware already does the relevant bit-mask with 0xff */
+ if (id)
+ return hdspm_read(hdspm, HDSPM_midiDataIn1);
+ else
+ return hdspm_read(hdspm, HDSPM_midiDataIn0);
+}
+
+static inline void snd_hdspm_midi_write_byte (hdspm_t *hdspm, int id, int val)
+{
+ /* the hardware already does the relevant bit-mask with 0xff */
+ if (id)
+ return hdspm_write(hdspm, HDSPM_midiDataOut1, val);
+ else
+ return hdspm_write(hdspm, HDSPM_midiDataOut0, val);
+}
+
+static inline int snd_hdspm_midi_input_available (hdspm_t *hdspm, int id)
+{
+ if (id)
+ return (hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff);
+ else
+ return (hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff);
+}
+
+static inline int snd_hdspm_midi_output_possible (hdspm_t *hdspm, int id)
+{
+ int fifo_bytes_used;
+
+ if (id)
+ fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xff;
+ else
+ fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xff;
+
+ if (fifo_bytes_used < 128)
+ return 128 - fifo_bytes_used;
+ else
+ return 0;
+}
+
+static inline void snd_hdspm_flush_midi_input (hdspm_t *hdspm, int id)
+{
+ while (snd_hdspm_midi_input_available (hdspm, id))
+ snd_hdspm_midi_read_byte (hdspm, id);
+}
+
+static int snd_hdspm_midi_output_write (hdspm_midi_t *hmidi)
+{
+ unsigned long flags;
+ int n_pending;
+ int to_write;
+ int i;
+ unsigned char buf[128];
+
+ /* Output is not interrupt driven */
+
+ spin_lock_irqsave (&hmidi->lock, flags);
+ if (hmidi->output) {
+ if (!snd_rawmidi_transmit_empty (hmidi->output)) {
+ if ((n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm, hmidi->id)) > 0) {
+ if (n_pending > (int)sizeof (buf))
+ n_pending = sizeof (buf);
+
+ if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) {
+ for (i = 0; i < to_write; ++i)
+ snd_hdspm_midi_write_byte (hmidi->hdspm, hmidi->id, buf[i]);
+ }
+ }
+ }
+ }
+ spin_unlock_irqrestore (&hmidi->lock, flags);
+ return 0;
+}
+
+static int snd_hdspm_midi_input_read (hdspm_midi_t *hmidi)
+{
+ unsigned char buf[128]; /* this buffer is designed to match the MIDI input FIFO size */
+ unsigned long flags;
+ int n_pending;
+ int i;
+
+ spin_lock_irqsave (&hmidi->lock, flags);
+ if ((n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id)) > 0) {
+ if (hmidi->input) {
+ if (n_pending > (int)sizeof (buf)) {
+ n_pending = sizeof (buf);
+ }
+ for (i = 0; i < n_pending; ++i) {
+ buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm, hmidi->id);
+ }
+ if (n_pending) {
+ snd_rawmidi_receive (hmidi->input, buf, n_pending);
+ }
+ } else {
+ /* flush the MIDI input FIFO */
+ while (n_pending--) {
+ snd_hdspm_midi_read_byte (hmidi->hdspm, hmidi->id);
+ }
+ }
+ }
+ hmidi->pending = 0;
+ if (hmidi->id) {
+ hmidi->hdspm->control_register |= HDSPM_Midi1InterruptEnable;
+ } else {
+ hmidi->hdspm->control_register |= HDSPM_Midi0InterruptEnable;
+ }
+ hdspm_write(hmidi->hdspm, HDSPM_controlRegister, hmidi->hdspm->control_register);
+ spin_unlock_irqrestore (&hmidi->lock, flags);
+ return snd_hdspm_midi_output_write (hmidi);
+}
+
+static void snd_hdspm_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
+{
+ hdspm_t *hdspm;
+ hdspm_midi_t *hmidi;
+ unsigned long flags;
+ u32 ie;
+
+ hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
+ hdspm = hmidi->hdspm;
+ ie = hmidi->id ? HDSPM_Midi1InterruptEnable : HDSPM_Midi0InterruptEnable;
+ spin_lock_irqsave (&hdspm->lock, flags);
+ if (up) {
+ if (!(hdspm->control_register & ie)) {
+ snd_hdspm_flush_midi_input (hdspm, hmidi->id);
+ hdspm->control_register |= ie;
+ }
+ } else {
+ hdspm->control_register &= ~ie;
+ }
+
+ hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+ spin_unlock_irqrestore (&hdspm->lock, flags);
+}
+
+static void snd_hdspm_midi_output_timer(unsigned long data)
+{
+ hdspm_midi_t *hmidi = (hdspm_midi_t *) data;
+ unsigned long flags;
+
+ snd_hdspm_midi_output_write(hmidi);
+ spin_lock_irqsave (&hmidi->lock, flags);
+
+ /* this does not bump hmidi->istimer, because the
+ kernel automatically removed the timer when it
+ expired, and we are now adding it back, thus
+ leaving istimer wherever it was set before.
+ */
+
+ if (hmidi->istimer) {
+ hmidi->timer.expires = 1 + jiffies;
+ add_timer(&hmidi->timer);
+ }
+
+ spin_unlock_irqrestore (&hmidi->lock, flags);
+}
+
+static void snd_hdspm_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
+{
+ hdspm_midi_t *hmidi;
+ unsigned long flags;
+
+ hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
+ spin_lock_irqsave (&hmidi->lock, flags);
+ if (up) {
+ if (!hmidi->istimer) {
+ init_timer(&hmidi->timer);
+ hmidi->timer.function = snd_hdspm_midi_output_timer;
+ hmidi->timer.data = (unsigned long) hmidi;
+ hmidi->timer.expires = 1 + jiffies;
+ add_timer(&hmidi->timer);
+ hmidi->istimer++;
+ }
+ } else {
+ if (hmidi->istimer && --hmidi->istimer <= 0) {
+ del_timer (&hmidi->timer);
+ }
+ }
+ spin_unlock_irqrestore (&hmidi->lock, flags);
+ if (up)
+ snd_hdspm_midi_output_write(hmidi);
+}
+
+static int snd_hdspm_midi_input_open(snd_rawmidi_substream_t * substream)
+{
+ hdspm_midi_t *hmidi;
+
+ hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
+ spin_lock_irq (&hmidi->lock);
+ snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);
+ hmidi->input = substream;
+ spin_unlock_irq (&hmidi->lock);
+
+ return 0;
+}
+
+static int snd_hdspm_midi_output_open(snd_rawmidi_substream_t * substream)
+{
+ hdspm_midi_t *hmidi;
+
+ hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
+ spin_lock_irq (&hmidi->lock);
+ hmidi->output = substream;
+ spin_unlock_irq (&hmidi->lock);
+
+ return 0;
+}
+
+static int snd_hdspm_midi_input_close(snd_rawmidi_substream_t * substream)
+{
+ hdspm_midi_t *hmidi;
+
+ snd_hdspm_midi_input_trigger (substream, 0);
+
+ hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
+ spin_lock_irq (&hmidi->lock);
+ hmidi->input = NULL;
+ spin_unlock_irq (&hmidi->lock);
+
+ return 0;
+}
+
+static int snd_hdspm_midi_output_close(snd_rawmidi_substream_t * substream)
+{
+ hdspm_midi_t *hmidi;
+
+ snd_hdspm_midi_output_trigger (substream, 0);
+
+ hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
+ spin_lock_irq (&hmidi->lock);
+ hmidi->output = NULL;
+ spin_unlock_irq (&hmidi->lock);
+
+ return 0;
+}
+
+snd_rawmidi_ops_t snd_hdspm_midi_output =
+{
+ .open = snd_hdspm_midi_output_open,
+ .close = snd_hdspm_midi_output_close,
+ .trigger = snd_hdspm_midi_output_trigger,
+};
+
+snd_rawmidi_ops_t snd_hdspm_midi_input =
+{
+ .open = snd_hdspm_midi_input_open,
+ .close = snd_hdspm_midi_input_close,
+ .trigger = snd_hdspm_midi_input_trigger,
+};
+
+static int __devinit snd_hdspm_create_midi (snd_card_t *card, hdspm_t *hdspm, int id)
+{
+ int err;
+ char buf[32];
+
+ hdspm->midi[id].id = id;
+ hdspm->midi[id].rmidi = NULL;
+ hdspm->midi[id].input = NULL;
+ hdspm->midi[id].output = NULL;
+ hdspm->midi[id].hdspm = hdspm;
+ hdspm->midi[id].istimer = 0;
+ hdspm->midi[id].pending = 0;
+ spin_lock_init (&hdspm->midi[id].lock);
+
+ sprintf (buf, "%s MIDI %d", card->shortname, id+1);
+ if ((err = snd_rawmidi_new (card, buf, id, 1, 1, &hdspm->midi[id].rmidi)) < 0)
+ return err;
+
+ sprintf (hdspm->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1);
+ hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
+
+ snd_rawmidi_set_ops (hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_hdspm_midi_output);
+ snd_rawmidi_set_ops (hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_hdspm_midi_input);
+
+ hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
+ SNDRV_RAWMIDI_INFO_INPUT |
+ SNDRV_RAWMIDI_INFO_DUPLEX;
+
+ return 0;
+}
+
+
+static void hdspm_midi_tasklet(unsigned long arg)
+{
+ hdspm_t *hdspm = (hdspm_t *)arg;
+
+ if (hdspm->midi[0].pending)
+ snd_hdspm_midi_input_read (&hdspm->midi[0]);
+ if (hdspm->midi[1].pending)
+ snd_hdspm_midi_input_read (&hdspm->midi[1]);
+}
+
+
+/*-----------------------------------------------------------------------------
+ Status Interface
+ ----------------------------------------------------------------------------*/
+
+/* get the system sample rate which is set */
+
+#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+ .name = xname, \
+ .index = xindex, \
+ .access = SNDRV_CTL_ELEM_ACCESS_READ, \
+ .info = snd_hdspm_info_system_sample_rate, \
+ .get = snd_hdspm_get_system_sample_rate \
+}
+
+static int snd_hdspm_info_system_sample_rate(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_info_t * uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ return 0;
+}
+
+static int snd_hdspm_get_system_sample_rate(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t *
+ ucontrol)
+{
+ hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.enumerated.item[0] = hdspm->system_sample_rate;
+ return 0;
+}
+
+#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, \
+ .name = xname, \
+ .index = xindex, \
+ .access = SNDRV_CTL_ELEM_ACCESS_READ, \
+ .info = snd_hdspm_info_autosync_sample_rate, \
+ .get = snd_hdspm_get_autosync_sample_rate \
+}
+
+static int snd_hdspm_info_autosync_sample_rate(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_info_t * uinfo)
+{
+ static char *texts[] = { "32000", "44100", "48000",
+ "64000", "88200", "96000",
+ "128000", "176400", "192000",
+ "None"
+ };
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 10;
+ if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+ uinfo->value.enumerated.item =
+ uinfo->value.enumerated.items - 1;
+ strcpy(uinfo->value.enumerated.name,
+ texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int snd_hdspm_get_autosync_sample_rate(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t *
+ ucontrol)
+{
+ hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+ switch (hdspm_external_sample_rate(hdspm)) {
+ case 32000:
+ ucontrol->value.enumerated.item[0] = 0;
+ break;
+ case 44100:
+ ucontrol->value.enumerated.item[0] = 1;
+ break;
+ case 48000:
+ ucontrol->value.enumerated.item[0] = 2;
+ break;
+ case 64000:
+ ucontrol->value.enumerated.item[0] = 3;
+ break;
+ case 88200:
+ ucontrol->value.enumerated.item[0] = 4;
+ break;
+ case 96000:
+ ucontrol->value.enumerated.item[0] = 5;
+ break;
+ case 128000:
+ ucontrol->value.enumerated.item[0] = 6;
+ break;
+ case 176400:
+ ucontrol->value.enumerated.item[0] = 7;
+ break;
+ case 192000:
+ ucontrol->value.enumerated.item[0] = 8;
+ break;
+
+ default:
+ ucontrol->value.enumerated.item[0] = 9;
+ }
+ return 0;
+}
+
+#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+ .name = xname, \
+ .index = xindex, \
+ .access = SNDRV_CTL_ELEM_ACCESS_READ, \
+ .info = snd_hdspm_info_system_clock_mode, \
+ .get = snd_hdspm_get_system_clock_mode, \
+}
+
+
+
+static int hdspm_system_clock_mode(hdspm_t * hdspm)
+{
+ /* Always reflect the hardware info, rme is never wrong !!!! */
+
+ if (hdspm->control_register & HDSPM_ClockModeMaster)
+ return 0;
+ return 1;
+}
+
+static int snd_hdspm_info_system_clock_mode(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_info_t * uinfo)
+{
+ static char *texts[] = { "Master", "Slave" };
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 2;
+ if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+ uinfo->value.enumerated.item =
+ uinfo->value.enumerated.items - 1;
+ strcpy(uinfo->value.enumerated.name,
+ texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int snd_hdspm_get_system_clock_mode(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.enumerated.item[0] =
+ hdspm_system_clock_mode(hdspm);
+ return 0;
+}
+
+#define HDSPM_CLOCK_SOURCE(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, \
+ .name = xname, \
+ .index = xindex, \
+ .info = snd_hdspm_info_clock_source, \
+ .get = snd_hdspm_get_clock_source, \
+ .put = snd_hdspm_put_clock_source \
+}
+
+static int hdspm_clock_source(hdspm_t * hdspm)
+{
+ if (hdspm->control_register & HDSPM_ClockModeMaster) {
+ switch (hdspm->system_sample_rate) {
+ case 32000:
+ return 1;
+ case 44100:
+ return 2;
+ case 48000:
+ return 3;
+ case 64000:
+ return 4;
+ case 88200:
+ return 5;
+ case 96000:
+ return 6;
+ case 128000:
+ return 7;
+ case 176400:
+ return 8;
+ case 192000:
+ return 9;
+ default:
+ return 3;
+ }
+ } else {
+ return 0;
+ }
+}
+
+static int hdspm_set_clock_source(hdspm_t * hdspm, int mode)
+{
+ int rate;
+ switch (mode) {
+
+ case HDSPM_CLOCK_SOURCE_AUTOSYNC:
+ if (hdspm_external_sample_rate(hdspm) != 0) {
+ hdspm->control_register &= ~HDSPM_ClockModeMaster;
+ hdspm_write(hdspm, HDSPM_controlRegister,
+ hdspm->control_register);
+ return 0;
+ }
+ return -1;
+ case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
+ rate = 32000;
+ break;
+ case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
+ rate = 44100;
+ break;
+ case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
+ rate = 48000;
+ break;
+ case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
+ rate = 64000;
+ break;
+ case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
+ rate = 88200;
+ break;
+ case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
+ rate = 96000;
+ break;
+ case HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ:
+ rate = 128000;
+ break;
+ case HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ:
+ rate = 176400;
+ break;
+ case HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ:
+ rate = 192000;
+ break;
+
+ default:
+ rate = 44100;
+ }
+ hdspm->control_register |= HDSPM_ClockModeMaster;
+ hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+ hdspm_set_rate(hdspm, rate, 1);
+ return 0;
+}
+
+static int snd_hdspm_info_clock_source(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_info_t * uinfo)
+{
+ static char *texts[] = { "AutoSync",
+ "Internal 32.0 kHz", "Internal 44.1 kHz",
+ "Internal 48.0 kHz",
+ "Internal 64.0 kHz", "Internal 88.2 kHz",
+ "Internal 96.0 kHz",
+ "Internal 128.0 kHz", "Internal 176.4 kHz",
+ "Internal 192.0 kHz"
+ };
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 10;
+
+ if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+ uinfo->value.enumerated.item =
+ uinfo->value.enumerated.items - 1;
+
+ strcpy(uinfo->value.enumerated.name,
+ texts[uinfo->value.enumerated.item]);
+
+ return 0;
+}
+
+static int snd_hdspm_get_clock_source(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm);
+ return 0;
+}
+
+static int snd_hdspm_put_clock_source(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ int change;
+ int val;
+
+ if (!snd_hdspm_use_is_exclusive(hdspm))
+ return -EBUSY;
+ val = ucontrol->value.enumerated.item[0];
+ if (val < 0)
+ val = 0;
+ if (val > 6)
+ val = 6;
+ spin_lock_irq(&hdspm->lock);
+ if (val != hdspm_clock_source(hdspm))
+ change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0;
+ else
+ change = 0;
+ spin_unlock_irq(&hdspm->lock);
+ return change;
+}
+
+#define HDSPM_PREF_SYNC_REF(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+ .name = xname, \
+ .index = xindex, \
+ .info = snd_hdspm_info_pref_sync_ref, \
+ .get = snd_hdspm_get_pref_sync_ref, \
+ .put = snd_hdspm_put_pref_sync_ref \
+}
+
+static int hdspm_pref_sync_ref(hdspm_t * hdspm)
+{
+ /* Notice that this looks at the requested sync source,
+ not the one actually in use.
+ */
+ switch (hdspm->control_register & HDSPM_SyncRefMask) {
+ case HDSPM_SyncRef_Word:
+ return HDSPM_SYNC_FROM_WORD;
+ case HDSPM_SyncRef_MADI:
+ return HDSPM_SYNC_FROM_MADI;
+ }
+
+ return HDSPM_SYNC_FROM_WORD;
+}
+
+static int hdspm_set_pref_sync_ref(hdspm_t * hdspm, int pref)
+{
+ hdspm->control_register &= ~HDSPM_SyncRefMask;
+
+ switch (pref) {
+ case HDSPM_SYNC_FROM_MADI:
+ hdspm->control_register |= HDSPM_SyncRef_MADI;
+ break;
+ case HDSPM_SYNC_FROM_WORD:
+ hdspm->control_register |= HDSPM_SyncRef_Word;
+ break;
+ default:
+ return -1;
+ }
+ hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+ return 0;
+}
+
+static int snd_hdspm_info_pref_sync_ref(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_info_t * uinfo)
+{
+ static char *texts[] = { "Word", "MADI" };
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+
+ uinfo->value.enumerated.items = 2;
+
+ if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+ uinfo->value.enumerated.item =
+ uinfo->value.enumerated.items - 1;
+ strcpy(uinfo->value.enumerated.name,
+ texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int snd_hdspm_get_pref_sync_ref(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm);
+ return 0;
+}
+
+static int snd_hdspm_put_pref_sync_ref(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ int change, max;
+ unsigned int val;
+
+ max = 2;
+
+ if (!snd_hdspm_use_is_exclusive(hdspm))
+ return -EBUSY;
+
+ val = ucontrol->value.enumerated.item[0] % max;
+
+ spin_lock_irq(&hdspm->lock);
+ change = (int) val != hdspm_pref_sync_ref(hdspm);
+ hdspm_set_pref_sync_ref(hdspm, val);
+ spin_unlock_irq(&hdspm->lock);
+ return change;
+}
+
+#define HDSPM_AUTOSYNC_REF(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+ .name = xname, \
+ .index = xindex, \
+ .access = SNDRV_CTL_ELEM_ACCESS_READ, \
+ .info = snd_hdspm_info_autosync_ref, \
+ .get = snd_hdspm_get_autosync_ref, \
+}
+
+static int hdspm_autosync_ref(hdspm_t * hdspm)
+{
+ /* This looks at the autosync selected sync reference */
+ unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+
+ switch (status2 & HDSPM_SelSyncRefMask) {
+
+ case HDSPM_SelSyncRef_WORD:
+ return HDSPM_AUTOSYNC_FROM_WORD;
+
+ case HDSPM_SelSyncRef_MADI:
+ return HDSPM_AUTOSYNC_FROM_MADI;
+
+ case HDSPM_SelSyncRef_NVALID:
+ return HDSPM_AUTOSYNC_FROM_NONE;
+
+ default:
+ return 0;
+ }
+
+ return 0;
+}
+
+static int snd_hdspm_info_autosync_ref(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_info_t * uinfo)
+{
+ static char *texts[] = { "WordClock", "MADI", "None" };
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 3;
+ if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+ uinfo->value.enumerated.item =
+ uinfo->value.enumerated.items - 1;
+ strcpy(uinfo->value.enumerated.name,
+ texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int snd_hdspm_get_autosync_ref(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm);
+ return 0;
+}
+
+#define HDSPM_LINE_OUT(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+ .name = xname, \
+ .index = xindex, \
+ .info = snd_hdspm_info_line_out, \
+ .get = snd_hdspm_get_line_out, \
+ .put = snd_hdspm_put_line_out \
+}
+
+static int hdspm_line_out(hdspm_t * hdspm)
+{
+ return (hdspm->control_register & HDSPM_LineOut) ? 1 : 0;
+}
+
+
+static int hdspm_set_line_output(hdspm_t * hdspm, int out)
+{
+ if (out)
+ hdspm->control_register |= HDSPM_LineOut;
+ else
+ hdspm->control_register &= ~HDSPM_LineOut;
+ hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+ return 0;
+}
+
+static int snd_hdspm_info_line_out(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_info_t * uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+}
+
+static int snd_hdspm_get_line_out(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+ spin_lock_irq(&hdspm->lock);
+ ucontrol->value.integer.value[0] = hdspm_line_out(hdspm);
+ spin_unlock_irq(&hdspm->lock);
+ return 0;
+}
+
+static int snd_hdspm_put_line_out(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ int change;
+ unsigned int val;
+
+ if (!snd_hdspm_use_is_exclusive(hdspm))
+ return -EBUSY;
+ val = ucontrol->value.integer.value[0] & 1;
+ spin_lock_irq(&hdspm->lock);
+ change = (int) val != hdspm_line_out(hdspm);
+ hdspm_set_line_output(hdspm, val);
+ spin_unlock_irq(&hdspm->lock);
+ return change;
+}
+
+#define HDSPM_TX_64(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+ .name = xname, \
+ .index = xindex, \
+ .info = snd_hdspm_info_tx_64, \
+ .get = snd_hdspm_get_tx_64, \
+ .put = snd_hdspm_put_tx_64 \
+}
+
+static int hdspm_tx_64(hdspm_t * hdspm)
+{
+ return (hdspm->control_register & HDSPM_TX_64ch) ? 1 : 0;
+}
+
+static int hdspm_set_tx_64(hdspm_t * hdspm, int out)
+{
+ if (out)
+ hdspm->control_register |= HDSPM_TX_64ch;
+ else
+ hdspm->control_register &= ~HDSPM_TX_64ch;
+ hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+ return 0;
+}
+
+static int snd_hdspm_info_tx_64(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_info_t * uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+}
+
+static int snd_hdspm_get_tx_64(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+ spin_lock_irq(&hdspm->lock);
+ ucontrol->value.integer.value[0] = hdspm_tx_64(hdspm);
+ spin_unlock_irq(&hdspm->lock);
+ return 0;
+}
+
+static int snd_hdspm_put_tx_64(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ int change;
+ unsigned int val;
+
+ if (!snd_hdspm_use_is_exclusive(hdspm))
+ return -EBUSY;
+ val = ucontrol->value.integer.value[0] & 1;
+ spin_lock_irq(&hdspm->lock);
+ change = (int) val != hdspm_tx_64(hdspm);
+ hdspm_set_tx_64(hdspm, val);
+ spin_unlock_irq(&hdspm->lock);
+ return change;
+}
+
+#define HDSPM_C_TMS(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+ .name = xname, \
+ .index = xindex, \
+ .info = snd_hdspm_info_c_tms, \
+ .get = snd_hdspm_get_c_tms, \
+ .put = snd_hdspm_put_c_tms \
+}
+
+static int hdspm_c_tms(hdspm_t * hdspm)
+{
+ return (hdspm->control_register & HDSPM_clr_tms) ? 1 : 0;
+}
+
+static int hdspm_set_c_tms(hdspm_t * hdspm, int out)
+{
+ if (out)
+ hdspm->control_register |= HDSPM_clr_tms;
+ else
+ hdspm->control_register &= ~HDSPM_clr_tms;
+ hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+ return 0;
+}
+
+static int snd_hdspm_info_c_tms(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_info_t * uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+}
+
+static int snd_hdspm_get_c_tms(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+ spin_lock_irq(&hdspm->lock);
+ ucontrol->value.integer.value[0] = hdspm_c_tms(hdspm);
+ spin_unlock_irq(&hdspm->lock);
+ return 0;
+}
+
+static int snd_hdspm_put_c_tms(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ int change;
+ unsigned int val;
+
+ if (!snd_hdspm_use_is_exclusive(hdspm))
+ return -EBUSY;
+ val = ucontrol->value.integer.value[0] & 1;
+ spin_lock_irq(&hdspm->lock);
+ change = (int) val != hdspm_c_tms(hdspm);
+ hdspm_set_c_tms(hdspm, val);
+ spin_unlock_irq(&hdspm->lock);
+ return change;
+}
+
+#define HDSPM_SAFE_MODE(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+ .name = xname, \
+ .index = xindex, \
+ .info = snd_hdspm_info_safe_mode, \
+ .get = snd_hdspm_get_safe_mode, \
+ .put = snd_hdspm_put_safe_mode \
+}
+
+static int hdspm_safe_mode(hdspm_t * hdspm)
+{
+ return (hdspm->control_register & HDSPM_AutoInp) ? 1 : 0;
+}
+
+static int hdspm_set_safe_mode(hdspm_t * hdspm, int out)
+{
+ if (out)
+ hdspm->control_register |= HDSPM_AutoInp;
+ else
+ hdspm->control_register &= ~HDSPM_AutoInp;
+ hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+ return 0;
+}
+
+static int snd_hdspm_info_safe_mode(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_info_t * uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+}
+
+static int snd_hdspm_get_safe_mode(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+ spin_lock_irq(&hdspm->lock);
+ ucontrol->value.integer.value[0] = hdspm_safe_mode(hdspm);
+ spin_unlock_irq(&hdspm->lock);
+ return 0;
+}
+
+static int snd_hdspm_put_safe_mode(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ int change;
+ unsigned int val;
+
+ if (!snd_hdspm_use_is_exclusive(hdspm))
+ return -EBUSY;
+ val = ucontrol->value.integer.value[0] & 1;
+ spin_lock_irq(&hdspm->lock);
+ change = (int) val != hdspm_safe_mode(hdspm);
+ hdspm_set_safe_mode(hdspm, val);
+ spin_unlock_irq(&hdspm->lock);
+ return change;
+}
+
+#define HDSPM_INPUT_SELECT(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+ .name = xname, \
+ .index = xindex, \
+ .info = snd_hdspm_info_input_select, \
+ .get = snd_hdspm_get_input_select, \
+ .put = snd_hdspm_put_input_select \
+}
+
+static int hdspm_input_select(hdspm_t * hdspm)
+{
+ return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0;
+}
+
+static int hdspm_set_input_select(hdspm_t * hdspm, int out)
+{
+ if (out)
+ hdspm->control_register |= HDSPM_InputSelect0;
+ else
+ hdspm->control_register &= ~HDSPM_InputSelect0;
+ hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+ return 0;
+}
+
+static int snd_hdspm_info_input_select(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_info_t * uinfo)
+{
+ static char *texts[] = { "optical", "coaxial" };
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 2;
+
+ if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+ uinfo->value.enumerated.item =
+ uinfo->value.enumerated.items - 1;
+ strcpy(uinfo->value.enumerated.name,
+ texts[uinfo->value.enumerated.item]);
+
+ return 0;
+}
+
+static int snd_hdspm_get_input_select(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+ spin_lock_irq(&hdspm->lock);
+ ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm);
+ spin_unlock_irq(&hdspm->lock);
+ return 0;
+}
+
+static int snd_hdspm_put_input_select(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ int change;
+ unsigned int val;
+
+ if (!snd_hdspm_use_is_exclusive(hdspm))
+ return -EBUSY;
+ val = ucontrol->value.integer.value[0] & 1;
+ spin_lock_irq(&hdspm->lock);
+ change = (int) val != hdspm_input_select(hdspm);
+ hdspm_set_input_select(hdspm, val);
+ spin_unlock_irq(&hdspm->lock);
+ return change;
+}
+
+/* Simple Mixer
+ deprecated since to much faders ???
+ MIXER interface says output (source, destination, value)
+ where source > MAX_channels are playback channels
+ on MADICARD
+ - playback mixer matrix: [channelout+64] [output] [value]
+ - input(thru) mixer matrix: [channelin] [output] [value]
+ (better do 2 kontrols for seperation ?)
+*/
+
+#define HDSPM_MIXER(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+ .name = xname, \
+ .index = xindex, \
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+ .info = snd_hdspm_info_mixer, \
+ .get = snd_hdspm_get_mixer, \
+ .put = snd_hdspm_put_mixer \
+}
+
+static int snd_hdspm_info_mixer(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_info_t * uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 3;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 65535;
+ uinfo->value.integer.step = 1;
+ return 0;
+}
+
+static int snd_hdspm_get_mixer(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ int source;
+ int destination;
+
+ source = ucontrol->value.integer.value[0];
+ if (source < 0)
+ source = 0;
+ else if (source >= 2 * HDSPM_MAX_CHANNELS)
+ source = 2 * HDSPM_MAX_CHANNELS - 1;
+
+ destination = ucontrol->value.integer.value[1];
+ if (destination < 0)
+ destination = 0;
+ else if (destination >= HDSPM_MAX_CHANNELS)
+ destination = HDSPM_MAX_CHANNELS - 1;
+
+ spin_lock_irq(&hdspm->lock);
+ if (source >= HDSPM_MAX_CHANNELS)
+ ucontrol->value.integer.value[2] =
+ hdspm_read_pb_gain(hdspm, destination,
+ source - HDSPM_MAX_CHANNELS);
+ else
+ ucontrol->value.integer.value[2] =
+ hdspm_read_in_gain(hdspm, destination, source);
+
+ spin_unlock_irq(&hdspm->lock);
+
+ return 0;
+}
+
+static int snd_hdspm_put_mixer(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ int change;
+ int source;
+ int destination;
+ int gain;
+
+ if (!snd_hdspm_use_is_exclusive(hdspm))
+ return -EBUSY;
+
+ source = ucontrol->value.integer.value[0];
+ destination = ucontrol->value.integer.value[1];
+
+ if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS)
+ return -1;
+ if (destination < 0 || destination >= HDSPM_MAX_CHANNELS)
+ return -1;
+
+ gain = ucontrol->value.integer.value[2];
+
+ spin_lock_irq(&hdspm->lock);
+
+ if (source >= HDSPM_MAX_CHANNELS)
+ change = gain != hdspm_read_pb_gain(hdspm, destination,
+ source -
+ HDSPM_MAX_CHANNELS);
+ else
+ change =
+ gain != hdspm_read_in_gain(hdspm, destination, source);
+
+ if (change) {
+ if (source >= HDSPM_MAX_CHANNELS)
+ hdspm_write_pb_gain(hdspm, destination,
+ source - HDSPM_MAX_CHANNELS,
+ gain);
+ else
+ hdspm_write_in_gain(hdspm, destination, source,
+ gain);
+ }
+ spin_unlock_irq(&hdspm->lock);
+
+ return change;
+}
+
+/* The simple mixer control(s) provide gain control for the
+ basic 1:1 mappings of playback streams to output
+ streams.
+*/
+
+#define HDSPM_PLAYBACK_MIXER \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+ .info = snd_hdspm_info_playback_mixer, \
+ .get = snd_hdspm_get_playback_mixer, \
+ .put = snd_hdspm_put_playback_mixer \
+}
+
+static int snd_hdspm_info_playback_mixer(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_info_t * uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 65536;
+ uinfo->value.integer.step = 1;
+ return 0;
+}
+
+static int snd_hdspm_get_playback_mixer(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ int channel;
+ int mapped_channel;
+
+ channel = ucontrol->id.index - 1;
+
+ snd_assert(channel >= 0
+ || channel < HDSPM_MAX_CHANNELS, return -EINVAL);
+
+ if ((mapped_channel = hdspm->channel_map[channel]) < 0)
+ return -EINVAL;
+
+ spin_lock_irq(&hdspm->lock);
+ ucontrol->value.integer.value[0] =
+ hdspm_read_pb_gain(hdspm, mapped_channel, mapped_channel);
+ spin_unlock_irq(&hdspm->lock);
+
+ /* snd_printdd("get pb mixer index %d, channel %d, mapped_channel %d, value %d\n",
+ ucontrol->id.index, channel, mapped_channel, ucontrol->value.integer.value[0]);
+ */
+
+ return 0;
+}
+
+static int snd_hdspm_put_playback_mixer(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+ int change;
+ int channel;
+ int mapped_channel;
+ int gain;
+
+ if (!snd_hdspm_use_is_exclusive(hdspm))
+ return -EBUSY;
+
+ channel = ucontrol->id.index - 1;
+
+ snd_assert(channel >= 0
+ || channel < HDSPM_MAX_CHANNELS, return -EINVAL);
+
+ if ((mapped_channel = hdspm->channel_map[channel]) < 0)
+ return -EINVAL;
+
+ gain = ucontrol->value.integer.value[0];
+
+ spin_lock_irq(&hdspm->lock);
+ change =
+ gain != hdspm_read_pb_gain(hdspm, mapped_channel,
+ mapped_channel);
+ if (change)
+ hdspm_write_pb_gain(hdspm, mapped_channel, mapped_channel,
+ gain);
+ spin_unlock_irq(&hdspm->lock);
+ return change;
+}
+
+#define HDSPM_WC_SYNC_CHECK(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+ .name = xname, \
+ .index = xindex, \
+ .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+ .info = snd_hdspm_info_sync_check, \
+ .get = snd_hdspm_get_wc_sync_check \
+}
+
+static int snd_hdspm_info_sync_check(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_info_t * uinfo)
+{
+ static char *texts[] = { "No Lock", "Lock", "Sync" };
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 3;
+ if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+ uinfo->value.enumerated.item =
+ uinfo->value.enumerated.items - 1;
+ strcpy(uinfo->value.enumerated.name,
+ texts[uinfo->value.enumerated.item]);
+ return 0;
+}
+
+static int hdspm_wc_sync_check(hdspm_t * hdspm)
+{
+ int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+ if (status2 & HDSPM_wcLock) {
+ if (status2 & HDSPM_wcSync)
+ return 2;
+ else
+ return 1;
+ }
+ return 0;
+}
+
+static int snd_hdspm_get_wc_sync_check(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t * ucontrol)
+{
+ hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.enumerated.item[0] = hdspm_wc_sync_check(hdspm);
+ return 0;
+}
+
+
+#define HDSPM_MADI_SYNC_CHECK(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+ .name = xname, \
+ .index = xindex, \
+ .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+ .info = snd_hdspm_info_sync_check, \
+ .get = snd_hdspm_get_madisync_sync_check \
+}
+
+static int hdspm_madisync_sync_check(hdspm_t * hdspm)
+{
+ int status = hdspm_read(hdspm, HDSPM_statusRegister);
+ if (status & HDSPM_madiLock) {
+ if (status & HDSPM_madiSync)
+ return 2;
+ else
+ return 1;
+ }
+ return 0;
+}
+
+static int snd_hdspm_get_madisync_sync_check(snd_kcontrol_t * kcontrol,
+ snd_ctl_elem_value_t *
+ ucontrol)
+{
+ hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.enumerated.item[0] =
+ hdspm_madisync_sync_check(hdspm);
+ return 0;
+}
+
+
+
+
+static snd_kcontrol_new_t snd_hdspm_controls[] = {
+
+ HDSPM_MIXER("Mixer", 0),
+/* 'Sample Clock Source' complies with the alsa control naming scheme */
+ HDSPM_CLOCK_SOURCE("Sample Clock Source", 0),
+
+ HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
+ HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
+ HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
+ HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
+/* 'External Rate' complies with the alsa control naming scheme */
+ HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
+ HDSPM_WC_SYNC_CHECK("Word Clock Lock Status", 0),
+ HDSPM_MADI_SYNC_CHECK("MADI Sync Lock Status", 0),
+ HDSPM_LINE_OUT("Line Out", 0),
+ HDSPM_TX_64("TX 64 channels mode", 0),
+ HDSPM_C_TMS("Clear Track Marker", 0),
+ HDSPM_SAFE_MODE("Safe Mode", 0),
+ HDSPM_INPUT_SELECT("Input Select", 0),
+};
+
+static snd_kcontrol_new_t snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
+
+
+static int hdspm_update_simple_mixer_controls(hdspm_t * hdspm)
+{
+ int i;
+
+ for (i = hdspm->ds_channels; i < hdspm->ss_channels; ++i) {
+ if (hdspm->system_sample_rate > 48000) {
+ hdspm->playback_mixer_ctls[i]->vd[0].access =
+ SNDRV_CTL_ELEM_ACCESS_INACTIVE |
+ SNDRV_CTL_ELEM_ACCESS_READ |
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE;
+ } else {
+ hdspm->playback_mixer_ctls[i]->vd[0].access =
+ SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE;
+ }
+ snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE |
+ SNDRV_CTL_EVENT_MASK_INFO,
+ &hdspm->playback_mixer_ctls[i]->id);
+ }
+
+ return 0;
+}
+
+
+static int snd_hdspm_create_controls(snd_card_t * card, hdspm_t * hdspm)
+{
+ unsigned int idx, limit;
+ int err;
+ snd_kcontrol_t *kctl;
+
+ /* add control list first */
+
+ for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls); idx++) {
+ if ((err =
+ snd_ctl_add(card, kctl =
+ snd_ctl_new1(&snd_hdspm_controls[idx],
+ hdspm))) < 0) {
+ return err;
+ }
+ }
+
+ /* Channel playback mixer as default control
+ Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats to big for any alsamixer
+ they are accesible via special IOCTL on hwdep
+ and the mixer 2dimensional mixer control */
+
+ snd_hdspm_playback_mixer.name = "Chn";
+ limit = HDSPM_MAX_CHANNELS;
+
+ /* The index values are one greater than the channel ID so that alsamixer
+ will display them correctly. We want to use the index for fast lookup
+ of the relevant channel, but if we use it at all, most ALSA software
+ does the wrong thing with it ...
+ */
+
+ for (idx = 0; idx < limit; ++idx) {
+ snd_hdspm_playback_mixer.index = idx + 1;
+ if ((err = snd_ctl_add(card,
+ kctl =
+ snd_ctl_new1
+ (&snd_hdspm_playback_mixer,
+ hdspm)))) {
+ return err;
+ }
+ hdspm->playback_mixer_ctls[idx] = kctl;
+ }
+
+ return 0;
+}
+
+/*------------------------------------------------------------
+ /proc interface
+ ------------------------------------------------------------*/
+
+static void
+snd_hdspm_proc_read(snd_info_entry_t * entry, snd_info_buffer_t * buffer)
+{
+ hdspm_t *hdspm = (hdspm_t *) entry->private_data;
+ unsigned int status;
+ unsigned int status2;
+ char *pref_sync_ref;
+ char *autosync_ref;
+ char *system_clock_mode;
+ char *clock_source;
+ char *insel;
+ char *syncref;
+ int x, x2;
+
+ status = hdspm_read(hdspm, HDSPM_statusRegister);
+ status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+
+ snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
+ hdspm->card_name, hdspm->card->number + 1,
+ hdspm->firmware_rev,
+ (status2 & HDSPM_version0) |
+ (status2 & HDSPM_version1) | (status2 &
+ HDSPM_version2));
+
+ snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
+ hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
+
+ snd_iprintf(buffer, "--- System ---\n");
+
+ snd_iprintf(buffer,
+ "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
+ status & HDSPM_audioIRQPending,
+ (status & HDSPM_midi0IRQPending) ? 1 : 0,
+ (status & HDSPM_midi1IRQPending) ? 1 : 0,
+ hdspm->irq_count);
+ snd_iprintf(buffer,
+ "HW pointer: id = %d, rawptr = %d (%d->%d) estimated= %ld (bytes)\n",
+ ((status & HDSPM_BufferID) ? 1 : 0),
+ (status & HDSPM_BufferPositionMask),
+ (status & HDSPM_BufferPositionMask) % (2 *
+ (int)hdspm->
+ period_bytes),
+ ((status & HDSPM_BufferPositionMask) -
+ 64) % (2 * (int)hdspm->period_bytes),
+ (long) hdspm_hw_pointer(hdspm) * 4);
+
+ snd_iprintf(buffer,
+ "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
+ hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
+ hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
+ hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
+ hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
+ snd_iprintf(buffer,
+ "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, status2=0x%x\n",
+ hdspm->control_register, hdspm->control2_register,
+ status, status2);
+
+ snd_iprintf(buffer, "--- Settings ---\n");
+
+ x = 1 << (6 +
+ hdspm_decode_latency(hdspm->
+ control_register &
+ HDSPM_LatencyMask));
+
+ snd_iprintf(buffer,
+ "Size (Latency): %d samples (2 periods of %lu bytes)\n",
+ x, (unsigned long) hdspm->period_bytes);
+
+ snd_iprintf(buffer, "Line out: %s, Precise Pointer: %s\n",
+ (hdspm->
+ control_register & HDSPM_LineOut) ? "on " : "off",
+ (hdspm->precise_ptr) ? "on" : "off");
+
+ switch (hdspm->control_register & HDSPM_InputMask) {
+ case HDSPM_InputOptical:
+ insel = "Optical";
+ break;
+ case HDSPM_InputCoaxial:
+ insel = "Coaxial";
+ break;
+ default:
+ insel = "Unkown";
+ }
+
+ switch (hdspm->control_register & HDSPM_SyncRefMask) {
+ case HDSPM_SyncRef_Word:
+ syncref = "WordClock";
+ break;
+ case HDSPM_SyncRef_MADI:
+ syncref = "MADI";
+ break;
+ default:
+ syncref = "Unkown";
+ }
+ snd_iprintf(buffer, "Inputsel = %s, SyncRef = %s\n", insel,
+ syncref);
+
+ snd_iprintf(buffer,
+ "ClearTrackMarker = %s, Transmit in %s Channel Mode, Auto Input %s\n",
+ (hdspm->
+ control_register & HDSPM_clr_tms) ? "on" : "off",
+ (hdspm->
+ control_register & HDSPM_TX_64ch) ? "64" : "56",
+ (hdspm->
+ control_register & HDSPM_AutoInp) ? "on" : "off");
+
+ switch (hdspm_clock_source(hdspm)) {
+ case HDSPM_CLOCK_SOURCE_AUTOSYNC:
+ clock_source = "AutoSync";
+ break;
+ case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
+ clock_source = "Internal 32 kHz";
+ break;
+ case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
+ clock_source = "Internal 44.1 kHz";
+ break;
+ case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
+ clock_source = "Internal 48 kHz";
+ break;
+ case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
+ clock_source = "Internal 64 kHz";
+ break;
+ case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
+ clock_source = "Internal 88.2 kHz";
+ break;
+ case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
+ clock_source = "Internal 96 kHz";
+ break;
+ default:
+ clock_source = "Error";
+ }
+ snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source);
+ if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
+ system_clock_mode = "Slave";
+ } else {
+ system_clock_mode = "Master";
+ }
+ snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode);
+
+ switch (hdspm_pref_sync_ref(hdspm)) {
+ case HDSPM_SYNC_FROM_WORD:
+ pref_sync_ref = "Word Clock";
+ break;
+ case HDSPM_SYNC_FROM_MADI:
+ pref_sync_ref = "MADI Sync";
+ break;
+ default:
+ pref_sync_ref = "XXXX Clock";
+ break;
+ }
+ snd_iprintf(buffer, "Preferred Sync Reference: %s\n",
+ pref_sync_ref);
+
+ snd_iprintf(buffer, "System Clock Frequency: %d\n",
+ hdspm->system_sample_rate);
+
+
+ snd_iprintf(buffer, "--- Status:\n");
+
+ x = status & HDSPM_madiSync;
+ x2 = status2 & HDSPM_wcSync;
+
+ snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n",
+ (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") :
+ "NoLock",
+ (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") :
+ "NoLock");
+
+ switch (hdspm_autosync_ref(hdspm)) {
+ case HDSPM_AUTOSYNC_FROM_WORD:
+ autosync_ref = "Word Clock";
+ break;
+ case HDSPM_AUTOSYNC_FROM_MADI:
+ autosync_ref = "MADI Sync";
+ break;
+ case HDSPM_AUTOSYNC_FROM_NONE:
+ autosync_ref = "Input not valid";
+ break;
+ default:
+ autosync_ref = "---";
+ break;
+ }
+ snd_iprintf(buffer,
+ "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n",
+ autosync_ref, hdspm_external_sample_rate(hdspm),
+ (status & HDSPM_madiFreqMask) >> 22,
+ (status2 & HDSPM_wcFreqMask) >> 5);
+
+ snd_iprintf(buffer, "Input: %s, Mode=%s\n",
+ (status & HDSPM_AB_int) ? "Coax" : "Optical",
+ (status & HDSPM_RX_64ch) ? "64 channels" :
+ "56 channels");
+
+ snd_iprintf(buffer, "\n");
+}
+
+static void __devinit snd_hdspm_proc_init(hdspm_t * hdspm)
+{
+ snd_info_entry_t *entry;
+
+ if (!snd_card_proc_new(hdspm->card, "hdspm", &entry))
+ snd_info_set_text_ops(entry, hdspm, 1024,
+ snd_hdspm_proc_read);
+}
+
+/*------------------------------------------------------------
+ hdspm intitialize
+ ------------------------------------------------------------*/
+
+static int snd_hdspm_set_defaults(hdspm_t * hdspm)
+{
+ unsigned int i;
+
+ /* ASSUMPTION: hdspm->lock is either held, or there is no need to
+ hold it (e.g. during module initalization).
+ */
+
+ /* set defaults: */
+
+ hdspm->control_register = HDSPM_ClockModeMaster | /* Master Cloack Mode on */
+ hdspm_encode_latency(7) | /* latency maximum = 8192 samples */
+ HDSPM_InputCoaxial | /* Input Coax not Optical */
+ HDSPM_SyncRef_MADI | /* Madi is syncclock */
+ HDSPM_LineOut | /* Analog output in */
+ HDSPM_TX_64ch | /* transmit in 64ch mode */
+ HDSPM_AutoInp; /* AutoInput chossing (takeover) */
+
+ /* ! HDSPM_Frequency0|HDSPM_Frequency1 = 44.1khz */
+ /* ! HDSPM_DoubleSpeed HDSPM_QuadSpeed = normal speed */
+ /* ! HDSPM_clr_tms = do not clear bits in track marks */
+
+ hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+#ifdef SNDRV_BIG_ENDIAN
+ hdspm->control2_register = HDSPM_BIGENDIAN_MODE;
+#else
+ hdspm->control2_register = 0;
+#endif
+
+ hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register);
+ hdspm_compute_period_size(hdspm);
+
+ /* silence everything */
+
+ all_in_all_mixer(hdspm, 0 * UNITY_GAIN);
+
+ if (line_outs_monitor[hdspm->dev]) {
+
+ snd_printk(KERN_INFO "HDSPM: sending all playback streams to line outs.\n");
+
+ for (i = 0; i < HDSPM_MIXER_CHANNELS; i++) {
+ if (hdspm_write_pb_gain(hdspm, i, i, UNITY_GAIN))
+ return -EIO;
+ }
+ }
+
+ /* set a default rate so that the channel map is set up. */
+ hdspm->channel_map = channel_map_madi_ss;
+ hdspm_set_rate(hdspm, 44100, 1);
+
+ return 0;
+}
+
+
+/*------------------------------------------------------------
+ interupt
+ ------------------------------------------------------------*/
+
+static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ hdspm_t *hdspm = (hdspm_t *) dev_id;
+ unsigned int status;
+ int audio;
+ int midi0;
+ int midi1;
+ unsigned int midi0status;
+ unsigned int midi1status;
+ int schedule = 0;
+
+ status = hdspm_read(hdspm, HDSPM_statusRegister);
+
+ audio = status & HDSPM_audioIRQPending;
+ midi0 = status & HDSPM_midi0IRQPending;
+ midi1 = status & HDSPM_midi1IRQPending;
+
+ if (!audio && !midi0 && !midi1)
+ return IRQ_NONE;
+
+ hdspm_write(hdspm, HDSPM_interruptConfirmation, 0);
+ hdspm->irq_count++;
+
+ midi0status = hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff;
+ midi1status = hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff;
+
+ if (audio) {
+
+ if (hdspm->capture_substream)
+ snd_pcm_period_elapsed(hdspm->pcm->
+ streams
+ [SNDRV_PCM_STREAM_CAPTURE].
+ substream);
+
+ if (hdspm->playback_substream)
+ snd_pcm_period_elapsed(hdspm->pcm->
+ streams
+ [SNDRV_PCM_STREAM_PLAYBACK].
+ substream);
+ }
+
+ if (midi0 && midi0status) {
+ /* we disable interrupts for this input until processing is done */
+ hdspm->control_register &= ~HDSPM_Midi0InterruptEnable;
+ hdspm_write(hdspm, HDSPM_controlRegister,
+ hdspm->control_register);
+ hdspm->midi[0].pending = 1;
+ schedule = 1;
+ }
+ if (midi1 && midi1status) {
+ /* we disable interrupts for this input until processing is done */
+ hdspm->control_register &= ~HDSPM_Midi1InterruptEnable;
+ hdspm_write(hdspm, HDSPM_controlRegister,
+ hdspm->control_register);
+ hdspm->midi[1].pending = 1;
+ schedule = 1;
+ }
+ if (schedule)
+ tasklet_hi_schedule(&hdspm->midi_tasklet);
+ return IRQ_HANDLED;
+}
+
+/*------------------------------------------------------------
+ pcm interface
+ ------------------------------------------------------------*/
+
+
+static snd_pcm_uframes_t snd_hdspm_hw_pointer(snd_pcm_substream_t *
+ substream)
+{
+ hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+ return hdspm_hw_pointer(hdspm);
+}
+
+static char *hdspm_channel_buffer_location(hdspm_t * hdspm,
+ int stream, int channel)
+{
+ int mapped_channel;
+
+ snd_assert(channel >= 0
+ || channel < HDSPM_MAX_CHANNELS, return NULL);
+
+ if ((mapped_channel = hdspm->channel_map[channel]) < 0)
+ return NULL;
+
+ if (stream == SNDRV_PCM_STREAM_CAPTURE) {
+ return hdspm->capture_buffer +
+ mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
+ } else {
+ return hdspm->playback_buffer +
+ mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
+ }
+}
+
+
+/* dont know why need it ??? */
+static int snd_hdspm_playback_copy(snd_pcm_substream_t * substream,
+ int channel, snd_pcm_uframes_t pos,
+ void __user *src, snd_pcm_uframes_t count)
+{
+ hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+ char *channel_buf;
+
+ snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4,
+ return -EINVAL);
+
+ channel_buf = hdspm_channel_buffer_location(hdspm,
+ substream->pstr->
+ stream, channel);
+
+ snd_assert(channel_buf != NULL, return -EIO);
+
+ return copy_from_user(channel_buf + pos * 4, src, count * 4);
+}
+
+static int snd_hdspm_capture_copy(snd_pcm_substream_t * substream,
+ int channel, snd_pcm_uframes_t pos,
+ void __user *dst, snd_pcm_uframes_t count)
+{
+ hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+ char *channel_buf;
+
+ snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4,
+ return -EINVAL);
+
+ channel_buf = hdspm_channel_buffer_location(hdspm,
+ substream->pstr->
+ stream, channel);
+ snd_assert(channel_buf != NULL, return -EIO);
+ return copy_to_user(dst, channel_buf + pos * 4, count * 4);
+}
+
+static int snd_hdspm_hw_silence(snd_pcm_substream_t * substream,
+ int channel, snd_pcm_uframes_t pos,
+ snd_pcm_uframes_t count)
+{
+ hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+ char *channel_buf;
+
+ channel_buf =
+ hdspm_channel_buffer_location(hdspm, substream->pstr->stream,
+ channel);
+ snd_assert(channel_buf != NULL, return -EIO);
+ memset(channel_buf + pos * 4, 0, count * 4);
+ return 0;
+}
+
+static int snd_hdspm_reset(snd_pcm_substream_t * substream)
+{
+ snd_pcm_runtime_t *runtime = substream->runtime;
+ hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+ snd_pcm_substream_t *other;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ other = hdspm->capture_substream;
+ else
+ other = hdspm->playback_substream;
+
+ if (hdspm->running)
+ runtime->status->hw_ptr = hdspm_hw_pointer(hdspm);
+ else
+ runtime->status->hw_ptr = 0;
+ if (other) {
+ struct list_head *pos;
+ snd_pcm_substream_t *s;
+ snd_pcm_runtime_t *oruntime = other->runtime;
+ snd_pcm_group_for_each(pos, substream) {
+ s = snd_pcm_group_substream_entry(pos);
+ if (s == other) {
+ oruntime->status->hw_ptr =
+ runtime->status->hw_ptr;
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+static int snd_hdspm_hw_params(snd_pcm_substream_t * substream,
+ snd_pcm_hw_params_t * params)
+{
+ hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+ int err;
+ int i;
+ pid_t this_pid;
+ pid_t other_pid;
+ struct snd_sg_buf *sgbuf;
+
+
+ spin_lock_irq(&hdspm->lock);
+
+ if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ this_pid = hdspm->playback_pid;
+ other_pid = hdspm->capture_pid;
+ } else {
+ this_pid = hdspm->capture_pid;
+ other_pid = hdspm->playback_pid;
+ }
+
+ if ((other_pid > 0) && (this_pid != other_pid)) {
+
+ /* The other stream is open, and not by the same
+ task as this one. Make sure that the parameters
+ that matter are the same.
+ */
+
+ if (params_rate(params) != hdspm->system_sample_rate) {
+ spin_unlock_irq(&hdspm->lock);
+ _snd_pcm_hw_param_setempty(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+ return -EBUSY;
+ }
+
+ if (params_period_size(params) != hdspm->period_bytes / 4) {
+ spin_unlock_irq(&hdspm->lock);
+ _snd_pcm_hw_param_setempty(params,
+ SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
+ return -EBUSY;
+ }
+
+ }
+ /* We're fine. */
+ spin_unlock_irq(&hdspm->lock);
+
+ /* how to make sure that the rate matches an externally-set one ? */
+
+ spin_lock_irq(&hdspm->lock);
+ if ((err = hdspm_set_rate(hdspm, params_rate(params), 0)) < 0) {
+ spin_unlock_irq(&hdspm->lock);
+ _snd_pcm_hw_param_setempty(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+ return err;
+ }
+ spin_unlock_irq(&hdspm->lock);
+
+ if ((err =
+ hdspm_set_interrupt_interval(hdspm,
+ params_period_size(params))) <
+ 0) {
+ _snd_pcm_hw_param_setempty(params,
+ SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
+ return err;
+ }
+
+ /* Memory allocation, takashi's method, dont know if we should spinlock */
+ /* malloc all buffer even if not enabled to get sure */
+ /* malloc only needed bytes */
+ err =
+ snd_pcm_lib_malloc_pages(substream,
+ HDSPM_CHANNEL_BUFFER_BYTES *
+ params_channels(params));
+ if (err < 0)
+ return err;
+
+ sgbuf = snd_pcm_substream_sgbuf(substream);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+
+ hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferOut,
+ params_channels(params));
+
+ for (i = 0; i < params_channels(params); ++i)
+ snd_hdspm_enable_out(hdspm, i, 1);
+
+ hdspm->playback_buffer =
+ (unsigned char *) substream->runtime->dma_area;
+ } else {
+ hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferIn,
+ params_channels(params));
+
+ for (i = 0; i < params_channels(params); ++i)
+ snd_hdspm_enable_in(hdspm, i, 1);
+
+ hdspm->capture_buffer =
+ (unsigned char *) substream->runtime->dma_area;
+ }
+ return 0;
+}
+
+static int snd_hdspm_hw_free(snd_pcm_substream_t * substream)
+{
+ int i;
+ hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+
+ /* params_channels(params) should be enough,
+ but to get sure in case of error */
+ for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
+ snd_hdspm_enable_out(hdspm, i, 0);
+
+ hdspm->playback_buffer = NULL;
+ } else {
+ for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
+ snd_hdspm_enable_in(hdspm, i, 0);
+
+ hdspm->capture_buffer = NULL;
+
+ }
+
+ snd_pcm_lib_free_pages(substream);
+
+ return 0;
+}
+
+static int snd_hdspm_channel_info(snd_pcm_substream_t * substream,
+ snd_pcm_channel_info_t * info)
+{
+ hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+ int mapped_channel;
+
+ snd_assert(info->channel < HDSPM_MAX_CHANNELS, return -EINVAL);
+
+ if ((mapped_channel = hdspm->channel_map[info->channel]) < 0)
+ return -EINVAL;
+
+ info->offset = mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
+ info->first = 0;
+ info->step = 32;
+ return 0;
+}
+
+static int snd_hdspm_ioctl(snd_pcm_substream_t * substream,
+ unsigned int cmd, void *arg)
+{
+ switch (cmd) {
+ case SNDRV_PCM_IOCTL1_RESET:
+ {
+ return snd_hdspm_reset(substream);
+ }
+
+ case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
+ {
+ snd_pcm_channel_info_t *info = arg;
+ return snd_hdspm_channel_info(substream, info);
+ }
+ default:
+ break;
+ }
+
+ return snd_pcm_lib_ioctl(substream, cmd, arg);
+}
+
+static int snd_hdspm_trigger(snd_pcm_substream_t * substream, int cmd)
+{
+ hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+ snd_pcm_substream_t *other;
+ int running;
+
+ spin_lock(&hdspm->lock);
+ running = hdspm->running;
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ running |= 1 << substream->stream;
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ running &= ~(1 << substream->stream);
+ break;
+ default:
+ snd_BUG();
+ spin_unlock(&hdspm->lock);
+ return -EINVAL;
+ }
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ other = hdspm->capture_substream;
+ else
+ other = hdspm->playback_substream;
+
+ if (other) {
+ struct list_head *pos;
+ snd_pcm_substream_t *s;
+ snd_pcm_group_for_each(pos, substream) {
+ s = snd_pcm_group_substream_entry(pos);
+ if (s == other) {
+ snd_pcm_trigger_done(s, substream);
+ if (cmd == SNDRV_PCM_TRIGGER_START)
+ running |= 1 << s->stream;
+ else
+ running &= ~(1 << s->stream);
+ goto _ok;
+ }
+ }
+ if (cmd == SNDRV_PCM_TRIGGER_START) {
+ if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK))
+ && substream->stream ==
+ SNDRV_PCM_STREAM_CAPTURE)
+ hdspm_silence_playback(hdspm);
+ } else {
+ if (running &&
+ substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ hdspm_silence_playback(hdspm);
+ }
+ } else {
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ hdspm_silence_playback(hdspm);
+ }
+ _ok:
+ snd_pcm_trigger_done(substream, substream);
+ if (!hdspm->running && running)
+ hdspm_start_audio(hdspm);
+ else if (hdspm->running && !running)
+ hdspm_stop_audio(hdspm);
+ hdspm->running = running;
+ spin_unlock(&hdspm->lock);
+
+ return 0;
+}
+
+static int snd_hdspm_prepare(snd_pcm_substream_t * substream)
+{
+ return 0;
+}
+
+static unsigned int period_sizes[] =
+ { 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
+
+static snd_pcm_hardware_t snd_hdspm_playback_subinfo = {
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_NONINTERLEAVED |
+ SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE),
+ .formats = SNDRV_PCM_FMTBIT_S32_LE,
+ .rates = (SNDRV_PCM_RATE_32000 |
+ SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_48000 |
+ SNDRV_PCM_RATE_64000 |
+ SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000),
+ .rate_min = 32000,
+ .rate_max = 96000,
+ .channels_min = 1,
+ .channels_max = HDSPM_MAX_CHANNELS,
+ .buffer_bytes_max =
+ HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
+ .period_bytes_min = (64 * 4),
+ .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
+ .periods_min = 2,
+ .periods_max = 2,
+ .fifo_size = 0
+};
+
+static snd_pcm_hardware_t snd_hdspm_capture_subinfo = {
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_NONINTERLEAVED |
+ SNDRV_PCM_INFO_SYNC_START),
+ .formats = SNDRV_PCM_FMTBIT_S32_LE,
+ .rates = (SNDRV_PCM_RATE_32000 |
+ SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_48000 |
+ SNDRV_PCM_RATE_64000 |
+ SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000),
+ .rate_min = 32000,
+ .rate_max = 96000,
+ .channels_min = 1,
+ .channels_max = HDSPM_MAX_CHANNELS,
+ .buffer_bytes_max =
+ HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
+ .period_bytes_min = (64 * 4),
+ .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
+ .periods_min = 2,
+ .periods_max = 2,
+ .fifo_size = 0
+};
+
+static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = {
+ .count = ARRAY_SIZE(period_sizes),
+ .list = period_sizes,
+ .mask = 0
+};
+
+
+static int snd_hdspm_hw_rule_channels_rate(snd_pcm_hw_params_t * params,
+ snd_pcm_hw_rule_t * rule)
+{
+ hdspm_t *hdspm = rule->private;
+ snd_interval_t *c =
+ hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+ snd_interval_t *r =
+ hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+
+ if (r->min > 48000) {
+ snd_interval_t t = {
+ .min = 1,
+ .max = hdspm->ds_channels,
+ .integer = 1,
+ };
+ return snd_interval_refine(c, &t);
+ } else if (r->max < 64000) {
+ snd_interval_t t = {
+ .min = 1,
+ .max = hdspm->ss_channels,
+ .integer = 1,
+ };
+ return snd_interval_refine(c, &t);
+ }
+ return 0;
+}
+
+static int snd_hdspm_hw_rule_rate_channels(snd_pcm_hw_params_t * params,
+ snd_pcm_hw_rule_t * rule)
+{
+ hdspm_t *hdspm = rule->private;
+ snd_interval_t *c =
+ hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+ snd_interval_t *r =
+ hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+
+ if (c->min <= hdspm->ss_channels) {
+ snd_interval_t t = {
+ .min = 32000,
+ .max = 48000,
+ .integer = 1,
+ };
+ return snd_interval_refine(r, &t);
+ } else if (c->max > hdspm->ss_channels) {
+ snd_interval_t t = {
+ .min = 64000,
+ .max = 96000,
+ .integer = 1,
+ };
+
+ return snd_interval_refine(r, &t);
+ }
+ return 0;
+}
+
+static int snd_hdspm_playback_open(snd_pcm_substream_t * substream)
+{
+ hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+
+ snd_printdd("Open device substream %d\n", substream->stream);
+
+ spin_lock_irq(&hdspm->lock);
+
+ snd_pcm_set_sync(substream);
+
+ runtime->hw = snd_hdspm_playback_subinfo;
+
+ if (hdspm->capture_substream == NULL)
+ hdspm_stop_audio(hdspm);
+
+ hdspm->playback_pid = current->pid;
+ hdspm->playback_substream = substream;
+
+ spin_unlock_irq(&hdspm->lock);
+
+ snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
+
+ snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+ &hw_constraints_period_sizes);
+
+ snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+ snd_hdspm_hw_rule_channels_rate, hdspm,
+ SNDRV_PCM_HW_PARAM_RATE, -1);
+
+ snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+ snd_hdspm_hw_rule_rate_channels, hdspm,
+ SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+
+ return 0;
+}
+
+static int snd_hdspm_playback_release(snd_pcm_substream_t * substream)
+{
+ hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+
+ spin_lock_irq(&hdspm->lock);
+
+ hdspm->playback_pid = -1;
+ hdspm->playback_substream = NULL;
+
+ spin_unlock_irq(&hdspm->lock);
+
+ return 0;
+}
+
+
+static int snd_hdspm_capture_open(snd_pcm_substream_t * substream)
+{
+ hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+ snd_pcm_runtime_t *runtime = substream->runtime;
+
+ spin_lock_irq(&hdspm->lock);
+ snd_pcm_set_sync(substream);
+ runtime->hw = snd_hdspm_capture_subinfo;
+
+ if (hdspm->playback_substream == NULL)
+ hdspm_stop_audio(hdspm);
+
+ hdspm->capture_pid = current->pid;
+ hdspm->capture_substream = substream;
+
+ spin_unlock_irq(&hdspm->lock);
+
+ snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
+ snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+ &hw_constraints_period_sizes);
+
+ snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+ snd_hdspm_hw_rule_channels_rate, hdspm,
+ SNDRV_PCM_HW_PARAM_RATE, -1);
+
+ snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+ snd_hdspm_hw_rule_rate_channels, hdspm,
+ SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+ return 0;
+}
+
+static int snd_hdspm_capture_release(snd_pcm_substream_t * substream)
+{
+ hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+
+ spin_lock_irq(&hdspm->lock);
+
+ hdspm->capture_pid = -1;
+ hdspm->capture_substream = NULL;
+
+ spin_unlock_irq(&hdspm->lock);
+ return 0;
+}
+
+static int snd_hdspm_hwdep_dummy_op(snd_hwdep_t * hw, struct file *file)
+{
+ /* we have nothing to initialize but the call is required */
+ return 0;
+}
+
+
+static int snd_hdspm_hwdep_ioctl(snd_hwdep_t * hw, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ hdspm_t *hdspm = (hdspm_t *) hw->private_data;
+ struct sndrv_hdspm_mixer_ioctl mixer;
+ hdspm_config_info_t info;
+ hdspm_version_t hdspm_version;
+ struct sndrv_hdspm_peak_rms_ioctl rms;
+
+ switch (cmd) {
+
+
+ case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS:
+ if (copy_from_user(&rms, (void __user *)arg, sizeof(rms)))
+ return -EFAULT;
+ /* maybe there is a chance to memorymap in future so dont touch just copy */
+ if(copy_to_user_fromio((void __user *)rms.peak,
+ hdspm->iobase+HDSPM_MADI_peakrmsbase,
+ sizeof(hdspm_peak_rms_t)) != 0 )
+ return -EFAULT;
+
+ break;
+
+
+ case SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO:
+
+ spin_lock_irq(&hdspm->lock);
+ info.pref_sync_ref =
+ (unsigned char) hdspm_pref_sync_ref(hdspm);
+ info.wordclock_sync_check =
+ (unsigned char) hdspm_wc_sync_check(hdspm);
+
+ info.system_sample_rate = hdspm->system_sample_rate;
+ info.autosync_sample_rate =
+ hdspm_external_sample_rate(hdspm);
+ info.system_clock_mode =
+ (unsigned char) hdspm_system_clock_mode(hdspm);
+ info.clock_source =
+ (unsigned char) hdspm_clock_source(hdspm);
+ info.autosync_ref =
+ (unsigned char) hdspm_autosync_ref(hdspm);
+ info.line_out = (unsigned char) hdspm_line_out(hdspm);
+ info.passthru = 0;
+ spin_unlock_irq(&hdspm->lock);
+ if (copy_to_user((void __user *) arg, &info, sizeof(info)))
+ return -EFAULT;
+ break;
+
+ case SNDRV_HDSPM_IOCTL_GET_VERSION:
+ hdspm_version.firmware_rev = hdspm->firmware_rev;
+ if (copy_to_user((void __user *) arg, &hdspm_version,
+ sizeof(hdspm_version)))
+ return -EFAULT;
+ break;
+
+ case SNDRV_HDSPM_IOCTL_GET_MIXER:
+ if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer)))
+ return -EFAULT;
+ if (copy_to_user
+ ((void __user *)mixer.mixer, hdspm->mixer, sizeof(hdspm_mixer_t)))
+ return -EFAULT;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static snd_pcm_ops_t snd_hdspm_playback_ops = {
+ .open = snd_hdspm_playback_open,
+ .close = snd_hdspm_playback_release,
+ .ioctl = snd_hdspm_ioctl,
+ .hw_params = snd_hdspm_hw_params,
+ .hw_free = snd_hdspm_hw_free,
+ .prepare = snd_hdspm_prepare,
+ .trigger = snd_hdspm_trigger,
+ .pointer = snd_hdspm_hw_pointer,
+ .copy = snd_hdspm_playback_copy,
+ .silence = snd_hdspm_hw_silence,
+ .page = snd_pcm_sgbuf_ops_page,
+};
+
+static snd_pcm_ops_t snd_hdspm_capture_ops = {
+ .open = snd_hdspm_capture_open,
+ .close = snd_hdspm_capture_release,
+ .ioctl = snd_hdspm_ioctl,
+ .hw_params = snd_hdspm_hw_params,
+ .hw_free = snd_hdspm_hw_free,
+ .prepare = snd_hdspm_prepare,
+ .trigger = snd_hdspm_trigger,
+ .pointer = snd_hdspm_hw_pointer,
+ .copy = snd_hdspm_capture_copy,
+ .page = snd_pcm_sgbuf_ops_page,
+};
+
+static int __devinit snd_hdspm_create_hwdep(snd_card_t * card,
+ hdspm_t * hdspm)
+{
+ snd_hwdep_t *hw;
+ int err;
+
+ if ((err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw)) < 0)
+ return err;
+
+ hdspm->hwdep = hw;
+ hw->private_data = hdspm;
+ strcpy(hw->name, "HDSPM hwdep interface");
+
+ hw->ops.open = snd_hdspm_hwdep_dummy_op;
+ hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
+ hw->ops.release = snd_hdspm_hwdep_dummy_op;
+
+ return 0;
+}
+
+
+/*------------------------------------------------------------
+ memory interface
+ ------------------------------------------------------------*/
+static int __devinit snd_hdspm_preallocate_memory(hdspm_t * hdspm)
+{
+ int err;
+ snd_pcm_t *pcm;
+ size_t wanted;
+
+ pcm = hdspm->pcm;
+
+ wanted = HDSPM_DMA_AREA_BYTES + 4096; /* dont know why, but it works */
+
+ if ((err =
+ snd_pcm_lib_preallocate_pages_for_all(pcm,
+ SNDRV_DMA_TYPE_DEV_SG,
+ snd_dma_pci_data(hdspm->pci),
+ wanted,
+ wanted)) < 0) {
+ snd_printdd("Could not preallocate %d Bytes\n", wanted);
+
+ return err;
+ } else
+ snd_printdd(" Preallocated %d Bytes\n", wanted);
+
+ return 0;
+}
+
+static int snd_hdspm_memory_free(hdspm_t * hdspm)
+{
+ snd_printdd("memory_free_for_all %p\n", hdspm->pcm);
+
+ snd_pcm_lib_preallocate_free_for_all(hdspm->pcm);
+ return 0;
+}
+
+
+static void hdspm_set_sgbuf(hdspm_t * hdspm, struct snd_sg_buf *sgbuf,
+ unsigned int reg, int channels)
+{
+ int i;
+ for (i = 0; i < (channels * 16); i++)
+ hdspm_write(hdspm, reg + 4 * i,
+ snd_pcm_sgbuf_get_addr(sgbuf,
+ (size_t) 4096 * i));
+}
+
+/* ------------- ALSA Devices ---------------------------- */
+static int __devinit snd_hdspm_create_pcm(snd_card_t * card,
+ hdspm_t * hdspm)
+{
+ snd_pcm_t *pcm;
+ int err;
+
+ if ((err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm)) < 0)
+ return err;
+
+ hdspm->pcm = pcm;
+ pcm->private_data = hdspm;
+ strcpy(pcm->name, hdspm->card_name);
+
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ &snd_hdspm_playback_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+ &snd_hdspm_capture_ops);
+
+ pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
+
+ if ((err = snd_hdspm_preallocate_memory(hdspm)) < 0)
+ return err;
+
+ return 0;
+}
+
+static inline void snd_hdspm_initialize_midi_flush(hdspm_t * hdspm)
+{
+ snd_hdspm_flush_midi_input(hdspm, 0);
+ snd_hdspm_flush_midi_input(hdspm, 1);
+}
+
+static int __devinit snd_hdspm_create_alsa_devices(snd_card_t * card,
+ hdspm_t * hdspm)
+{
+ int err;
+
+ snd_printdd("Create card...\n");
+ if ((err = snd_hdspm_create_pcm(card, hdspm)) < 0)
+ return err;
+
+ if ((err = snd_hdspm_create_midi(card, hdspm, 0)) < 0)
+ return err;
+
+ if ((err = snd_hdspm_create_midi(card, hdspm, 1)) < 0)
+ return err;
+
+ if ((err = snd_hdspm_create_controls(card, hdspm)) < 0)
+ return err;
+
+ if ((err = snd_hdspm_create_hwdep(card, hdspm)) < 0)
+ return err;
+
+ snd_printdd("proc init...\n");
+ snd_hdspm_proc_init(hdspm);
+
+ hdspm->system_sample_rate = -1;
+ hdspm->last_external_sample_rate = -1;
+ hdspm->last_internal_sample_rate = -1;
+ hdspm->playback_pid = -1;
+ hdspm->capture_pid = -1;
+ hdspm->capture_substream = NULL;
+ hdspm->playback_substream = NULL;
+
+ snd_printdd("Set defaults...\n");
+ if ((err = snd_hdspm_set_defaults(hdspm)) < 0)
+ return err;
+
+ snd_printdd("Update mixer controls...\n");
+ hdspm_update_simple_mixer_controls(hdspm);
+
+ snd_printdd("Initializeing complete ???\n");
+
+ if ((err = snd_card_register(card)) < 0) {
+ snd_printk(KERN_ERR "HDSPM: error registering card\n");
+ return err;
+ }
+
+ snd_printdd("... yes now\n");
+
+ return 0;
+}
+
+static int __devinit snd_hdspm_create(snd_card_t * card, hdspm_t * hdspm,
+ int precise_ptr, int enable_monitor)
+{
+ struct pci_dev *pci = hdspm->pci;
+ int err;
+ int i;
+
+ unsigned long io_extent;
+
+ hdspm->irq = -1;
+ hdspm->irq_count = 0;
+
+ hdspm->midi[0].rmidi = NULL;
+ hdspm->midi[1].rmidi = NULL;
+ hdspm->midi[0].input = NULL;
+ hdspm->midi[1].input = NULL;
+ hdspm->midi[0].output = NULL;
+ hdspm->midi[1].output = NULL;
+ spin_lock_init(&hdspm->midi[0].lock);
+ spin_lock_init(&hdspm->midi[1].lock);
+ hdspm->iobase = NULL;
+ hdspm->control_register = 0;
+ hdspm->control2_register = 0;
+
+ hdspm->playback_buffer = NULL;
+ hdspm->capture_buffer = NULL;
+
+ for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
+ hdspm->playback_mixer_ctls[i] = NULL;
+ hdspm->mixer = NULL;
+
+ hdspm->card = card;
+
+ spin_lock_init(&hdspm->lock);
+
+ tasklet_init(&hdspm->midi_tasklet,
+ hdspm_midi_tasklet, (unsigned long) hdspm);
+
+ pci_read_config_word(hdspm->pci,
+ PCI_CLASS_REVISION, &hdspm->firmware_rev);
+
+ strcpy(card->driver, "HDSPM");
+ strcpy(card->mixername, "Xilinx FPGA");
+ hdspm->card_name = "RME HDSPM MADI";
+
+ if ((err = pci_enable_device(pci)) < 0)
+ return err;
+
+ pci_set_master(hdspm->pci);
+
+ if ((err = pci_request_regions(pci, "hdspm")) < 0)
+ return err;
+
+ hdspm->port = pci_resource_start(pci, 0);
+ io_extent = pci_resource_len(pci, 0);
+
+ snd_printdd("grabbed memory region 0x%lx-0x%lx\n",
+ hdspm->port, hdspm->port + io_extent - 1);
+
+
+ if ((hdspm->iobase = ioremap_nocache(hdspm->port, io_extent)) == NULL) {
+ snd_printk(KERN_ERR "HDSPM: unable to remap region 0x%lx-0x%lx\n",
+ hdspm->port, hdspm->port + io_extent - 1);
+ return -EBUSY;
+ }
+ snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n",
+ (unsigned long)hdspm->iobase, hdspm->port,
+ hdspm->port + io_extent - 1);
+
+ if (request_irq(pci->irq, snd_hdspm_interrupt,
+ SA_INTERRUPT | SA_SHIRQ, "hdspm",
+ (void *) hdspm)) {
+ snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq);
+ return -EBUSY;
+ }
+
+ snd_printdd("use IRQ %d\n", pci->irq);
+
+ hdspm->irq = pci->irq;
+ hdspm->precise_ptr = precise_ptr;
+
+ hdspm->monitor_outs = enable_monitor;
+
+ snd_printdd("kmalloc Mixer memory of %d Bytes\n",
+ sizeof(hdspm_mixer_t));
+ if ((hdspm->mixer =
+ (hdspm_mixer_t *) kmalloc(sizeof(hdspm_mixer_t), GFP_KERNEL))
+ == NULL) {
+ snd_printk(KERN_ERR "HDSPM: unable to kmalloc Mixer memory of %d Bytes\n",
+ (int)sizeof(hdspm_mixer_t));
+ return err;
+ }
+
+ hdspm->ss_channels = MADI_SS_CHANNELS;
+ hdspm->ds_channels = MADI_DS_CHANNELS;
+ hdspm->qs_channels = MADI_QS_CHANNELS;
+
+ snd_printdd("create alsa devices.\n");
+ if ((err = snd_hdspm_create_alsa_devices(card, hdspm)) < 0)
+ return err;
+
+ snd_hdspm_initialize_midi_flush(hdspm);
+
+ return 0;
+}
+
+static int snd_hdspm_free(hdspm_t * hdspm)
+{
+
+ if (hdspm->port) {
+
+ /* stop th audio, and cancel all interrupts */
+ hdspm->control_register &=
+ ~(HDSPM_Start | HDSPM_AudioInterruptEnable
+ | HDSPM_Midi0InterruptEnable |
+ HDSPM_Midi1InterruptEnable);
+ hdspm_write(hdspm, HDSPM_controlRegister,
+ hdspm->control_register);
+ }
+
+ if (hdspm->irq >= 0)
+ free_irq(hdspm->irq, (void *) hdspm);
+
+
+ if (hdspm->mixer)
+ kfree(hdspm->mixer);
+
+ if (hdspm->iobase)
+ iounmap(hdspm->iobase);
+
+ snd_hdspm_memory_free(hdspm);
+
+ if (hdspm->port)
+ pci_release_regions(hdspm->pci);
+
+ pci_disable_device(hdspm->pci);
+ return 0;
+}
+
+static void snd_hdspm_card_free(snd_card_t * card)
+{
+ hdspm_t *hdspm = (hdspm_t *) card->private_data;
+
+ if (hdspm)
+ snd_hdspm_free(hdspm);
+}
+
+static int __devinit snd_hdspm_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
+{
+ static int dev;
+ hdspm_t *hdspm;
+ snd_card_t *card;
+ int err;
+
+ if (dev >= SNDRV_CARDS)
+ return -ENODEV;
+ if (!enable[dev]) {
+ dev++;
+ return -ENOENT;
+ }
+
+ if (!(card = snd_card_new(index[dev], id[dev],
+ THIS_MODULE, sizeof(hdspm_t))))
+ return -ENOMEM;
+
+ hdspm = (hdspm_t *) card->private_data;
+ card->private_free = snd_hdspm_card_free;
+ hdspm->dev = dev;
+ hdspm->pci = pci;
+
+ if ((err =
+ snd_hdspm_create(card, hdspm, precise_ptr[dev],
+ enable_monitor[dev])) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+
+ strcpy(card->shortname, "HDSPM MADI");
+ sprintf(card->longname, "%s at 0x%lx, irq %d", hdspm->card_name,
+ hdspm->port, hdspm->irq);
+
+ if ((err = snd_card_register(card)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+
+ pci_set_drvdata(pci, card);
+
+ dev++;
+ return 0;
+}
+
+static void __devexit snd_hdspm_remove(struct pci_dev *pci)
+{
+ snd_card_free(pci_get_drvdata(pci));
+ pci_set_drvdata(pci, NULL);
+}
+
+static struct pci_driver driver = {
+ .name = "RME Hammerfall DSP MADI",
+ .id_table = snd_hdspm_ids,
+ .probe = snd_hdspm_probe,
+ .remove = __devexit_p(snd_hdspm_remove),
+};
+
+
+static int __init alsa_card_hdspm_init(void)
+{
+ return pci_register_driver(&driver);
+}
+
+static void __exit alsa_card_hdspm_exit(void)
+{
+ pci_unregister_driver(&driver);
+}
+
+module_init(alsa_card_hdspm_init)
+module_exit(alsa_card_hdspm_exit)
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index 69cd81eaa11..f3037402d58 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -303,18 +303,22 @@ static int snd_hammerfall_get_buffer(struct pci_dev *pci, struct snd_dma_buffer
{
dmab->dev.type = SNDRV_DMA_TYPE_DEV;
dmab->dev.dev = snd_dma_pci_data(pci);
- if (! snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
- size, dmab) < 0)
- return -ENOMEM;
+ if (snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
+ if (dmab->bytes >= size)
+ return 0;
}
+ if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+ size, dmab) < 0)
+ return -ENOMEM;
return 0;
}
static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
{
- if (dmab->area)
+ if (dmab->area) {
+ dmab->dev.dev = NULL; /* make it anonymous */
snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci));
+ }
}
@@ -2664,7 +2668,7 @@ static struct pci_driver driver = {
static int __init alsa_card_hammerfall_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_hammerfall_exit(void)
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index cfd2c5fd6dd..60ecb2bdb65 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -1522,7 +1522,7 @@ static struct pci_driver driver = {
static int __init alsa_card_sonicvibes_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_sonicvibes_exit(void)
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
index ad58e08d66e..940d531575c 100644
--- a/sound/pci/trident/trident.c
+++ b/sound/pci/trident/trident.c
@@ -143,7 +143,8 @@ static int __devinit snd_trident_probe(struct pci_dev *pci,
return err;
}
}
- if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE,
+ if (trident->device != TRIDENT_DEVICE_ID_SI7018 &&
+ (err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE,
trident->midi_port, 1,
trident->irq, 0, &trident->rmidi)) < 0) {
snd_card_free(card);
@@ -184,7 +185,7 @@ static struct pci_driver driver = {
static int __init alsa_card_trident_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_trident_exit(void)
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 9b4d74d49f9..42c48f0ce8e 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -101,7 +101,7 @@ MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz).");
module_param_array(ac97_quirk, charp, NULL, 0444);
MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
module_param_array(dxs_support, int, NULL, 0444);
-MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA)");
+MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA, 5 = enable any sample rate)");
/* pci ids */
@@ -302,6 +302,7 @@ DEFINE_VIA_REGSET(CAPTURE_8233, 0x60);
#define VIA_DXS_DISABLE 2
#define VIA_DXS_48K 3
#define VIA_DXS_NO_VRA 4
+#define VIA_DXS_SRC 5
/*
@@ -380,6 +381,7 @@ struct _snd_via82xx {
struct via_rate_lock rates[2]; /* playback and capture */
unsigned int dxs_fixed: 1; /* DXS channel accepts only 48kHz */
unsigned int no_vra: 1; /* no need to set VRA on DXS channels */
+ unsigned int dxs_src: 1; /* use full SRC capabilities of DXS */
unsigned int spdif_on: 1; /* only spdif rates work to external DACs */
snd_pcm_t *pcms[2];
@@ -489,10 +491,8 @@ static int clean_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
snd_dma_free_pages(&dev->table);
dev->table.area = NULL;
}
- if (dev->idx_table) {
- kfree(dev->idx_table);
- dev->idx_table = NULL;
- }
+ kfree(dev->idx_table);
+ dev->idx_table = NULL;
return 0;
}
@@ -924,15 +924,17 @@ static int snd_via8233_playback_prepare(snd_pcm_substream_t *substream)
via82xx_t *chip = snd_pcm_substream_chip(substream);
viadev_t *viadev = (viadev_t *)substream->runtime->private_data;
snd_pcm_runtime_t *runtime = substream->runtime;
+ int ac97_rate = chip->dxs_src ? 48000 : runtime->rate;
int rate_changed;
u32 rbits;
- if ((rate_changed = via_lock_rate(&chip->rates[0], runtime->rate)) < 0)
+ if ((rate_changed = via_lock_rate(&chip->rates[0], ac97_rate)) < 0)
return rate_changed;
if (rate_changed) {
snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE,
chip->no_vra ? 48000 : runtime->rate);
- snd_ac97_set_rate(chip->ac97, AC97_SPDIF, runtime->rate);
+ snd_ac97_set_rate(chip->ac97, AC97_SPDIF,
+ chip->no_vra ? 48000 : runtime->rate);
}
if (runtime->rate == 48000)
rbits = 0xfffff;
@@ -1074,6 +1076,12 @@ static int snd_via82xx_pcm_open(via82xx_t *chip, viadev_t *viadev, snd_pcm_subst
/* fixed DXS playback rate */
runtime->hw.rates = SNDRV_PCM_RATE_48000;
runtime->hw.rate_min = runtime->hw.rate_max = 48000;
+ } else if (chip->dxs_src && viadev->reg_offset < 0x40) {
+ /* use full SRC capabilities of DXS */
+ runtime->hw.rates = (SNDRV_PCM_RATE_CONTINUOUS |
+ SNDRV_PCM_RATE_8000_48000);
+ runtime->hw.rate_min = 8000;
+ runtime->hw.rate_max = 48000;
} else if (! ratep->rate) {
int idx = viadev->direction ? AC97_RATES_ADC : AC97_RATES_FRONT_DAC;
runtime->hw.rates = chip->ac97->rates[idx];
@@ -1550,51 +1558,51 @@ static void snd_via82xx_mixer_free_ac97(ac97_t *ac97)
static struct ac97_quirk ac97_quirks[] = {
{
- .vendor = 0x1106,
- .device = 0x4161,
+ .subvendor = 0x1106,
+ .subdevice = 0x4161,
.codec_id = 0x56494161, /* VT1612A */
.name = "Soltek SL-75DRV5",
.type = AC97_TUNE_NONE
},
{ /* FIXME: which codec? */
- .vendor = 0x1106,
- .device = 0x4161,
+ .subvendor = 0x1106,
+ .subdevice = 0x4161,
.name = "ASRock K7VT2",
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x1019,
- .device = 0x0a81,
+ .subvendor = 0x1019,
+ .subdevice = 0x0a81,
.name = "ECS K7VTA3",
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x1019,
- .device = 0x0a85,
+ .subvendor = 0x1019,
+ .subdevice = 0x0a85,
.name = "ECS L7VMM2",
.type = AC97_TUNE_HP_ONLY
},
{
- .vendor = 0x1849,
- .device = 0x3059,
+ .subvendor = 0x1849,
+ .subdevice = 0x3059,
.name = "ASRock K7VM2",
.type = AC97_TUNE_HP_ONLY /* VT1616 */
},
{
- .vendor = 0x14cd,
- .device = 0x7002,
+ .subvendor = 0x14cd,
+ .subdevice = 0x7002,
.name = "Unknown",
.type = AC97_TUNE_ALC_JACK
},
{
- .vendor = 0x1071,
- .device = 0x8590,
+ .subvendor = 0x1071,
+ .subdevice = 0x8590,
.name = "Mitac Mobo",
.type = AC97_TUNE_ALC_JACK
},
{
- .vendor = 0x161f,
- .device = 0x202b,
+ .subvendor = 0x161f,
+ .subdevice = 0x202b,
.name = "Arima Notebook",
.type = AC97_TUNE_HP_ONLY,
},
@@ -2132,8 +2140,8 @@ static struct via823x_info via823x_cards[] __devinitdata = {
* auto detection of DXS channel supports.
*/
struct dxs_whitelist {
- unsigned short vendor;
- unsigned short device;
+ unsigned short subvendor;
+ unsigned short subdevice;
unsigned short mask;
short action; /* new dxs_support value */
};
@@ -2141,38 +2149,44 @@ struct dxs_whitelist {
static int __devinit check_dxs_list(struct pci_dev *pci)
{
static struct dxs_whitelist whitelist[] = {
- { .vendor = 0x1005, .device = 0x4710, .action = VIA_DXS_ENABLE }, /* Avance Logic Mobo */
- { .vendor = 0x1019, .device = 0x0996, .action = VIA_DXS_48K },
- { .vendor = 0x1019, .device = 0x0a81, .action = VIA_DXS_NO_VRA }, /* ECS K7VTA3 v8.0 */
- { .vendor = 0x1019, .device = 0x0a85, .action = VIA_DXS_NO_VRA }, /* ECS L7VMM2 */
- { .vendor = 0x1025, .device = 0x0033, .action = VIA_DXS_NO_VRA }, /* Acer Inspire 1353LM */
- { .vendor = 0x1043, .device = 0x8095, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8X (FIXME: possibly VIA_DXS_ENABLE?)*/
- { .vendor = 0x1043, .device = 0x80a1, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8-X */
- { .vendor = 0x1043, .device = 0x80b0, .action = VIA_DXS_NO_VRA }, /* ASUS A7V600 & K8V*/
- { .vendor = 0x1071, .device = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */
- { .vendor = 0x10cf, .device = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */
- { .vendor = 0x1106, .device = 0x4161, .action = VIA_DXS_NO_VRA }, /* ASRock K7VT2 */
- { .vendor = 0x1106, .device = 0x4552, .action = VIA_DXS_NO_VRA }, /* QDI Kudoz 7X/600-6AL */
- { .vendor = 0x1106, .device = 0xaa01, .action = VIA_DXS_NO_VRA }, /* EPIA MII */
- { .vendor = 0x1297, .device = 0xa232, .action = VIA_DXS_ENABLE }, /* Shuttle ?? */
- { .vendor = 0x1297, .device = 0xc160, .action = VIA_DXS_ENABLE }, /* Shuttle SK41G */
- { .vendor = 0x1458, .device = 0xa002, .action = VIA_DXS_ENABLE }, /* Gigabyte GA-7VAXP */
- { .vendor = 0x1462, .device = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */
- { .vendor = 0x1462, .device = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */
- { .vendor = 0x1462, .device = 0x7023, .action = VIA_DXS_NO_VRA }, /* MSI K8T Neo2-FI */
- { .vendor = 0x1462, .device = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */
- { .vendor = 0x147b, .device = 0x1401, .action = VIA_DXS_ENABLE }, /* ABIT KD7(-RAID) */
- { .vendor = 0x147b, .device = 0x1411, .action = VIA_DXS_ENABLE }, /* ABIT VA-20 */
- { .vendor = 0x147b, .device = 0x1413, .action = VIA_DXS_ENABLE }, /* ABIT KV8 Pro */
- { .vendor = 0x147b, .device = 0x1415, .action = VIA_DXS_NO_VRA }, /* Abit AV8 */
- { .vendor = 0x14ff, .device = 0x0403, .action = VIA_DXS_ENABLE }, /* Twinhead mobo */
- { .vendor = 0x1584, .device = 0x8120, .action = VIA_DXS_ENABLE }, /* Gericom/Targa/Vobis/Uniwill laptop */
- { .vendor = 0x1584, .device = 0x8123, .action = VIA_DXS_NO_VRA }, /* Uniwill (Targa Visionary XP-210) */
- { .vendor = 0x161f, .device = 0x202b, .action = VIA_DXS_NO_VRA }, /* Amira Note book */
- { .vendor = 0x161f, .device = 0x2032, .action = VIA_DXS_48K }, /* m680x machines */
- { .vendor = 0x1631, .device = 0xe004, .action = VIA_DXS_ENABLE }, /* Easy Note 3174, Packard Bell */
- { .vendor = 0x1695, .device = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */
- { .vendor = 0x1849, .device = 0x3059, .action = VIA_DXS_NO_VRA }, /* ASRock K7VM2 */
+ { .subvendor = 0x1005, .subdevice = 0x4710, .action = VIA_DXS_ENABLE }, /* Avance Logic Mobo */
+ { .subvendor = 0x1019, .subdevice = 0x0996, .action = VIA_DXS_48K },
+ { .subvendor = 0x1019, .subdevice = 0x0a81, .action = VIA_DXS_NO_VRA }, /* ECS K7VTA3 v8.0 */
+ { .subvendor = 0x1019, .subdevice = 0x0a85, .action = VIA_DXS_NO_VRA }, /* ECS L7VMM2 */
+ { .subvendor = 0x1025, .subdevice = 0x0033, .action = VIA_DXS_NO_VRA }, /* Acer Inspire 1353LM */
+ { .subvendor = 0x1043, .subdevice = 0x8095, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8X (FIXME: possibly VIA_DXS_ENABLE?)*/
+ { .subvendor = 0x1043, .subdevice = 0x80a1, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8-X */
+ { .subvendor = 0x1043, .subdevice = 0x80b0, .action = VIA_DXS_NO_VRA }, /* ASUS A7V600 & K8V*/
+ { .subvendor = 0x1043, .subdevice = 0x812a, .action = VIA_DXS_SRC }, /* ASUS A8V Deluxe */
+ { .subvendor = 0x1071, .subdevice = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */
+ { .subvendor = 0x1071, .subdevice = 0x8399, .action = VIA_DXS_NO_VRA }, /* Umax AB 595T (VIA K8N800A - VT8237) */
+ { .subvendor = 0x10cf, .subdevice = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */
+ { .subvendor = 0x1106, .subdevice = 0x4161, .action = VIA_DXS_NO_VRA }, /* ASRock K7VT2 */
+ { .subvendor = 0x1106, .subdevice = 0x4552, .action = VIA_DXS_NO_VRA }, /* QDI Kudoz 7X/600-6AL */
+ { .subvendor = 0x1106, .subdevice = 0xaa01, .action = VIA_DXS_NO_VRA }, /* EPIA MII */
+ { .subvendor = 0x1106, .subdevice = 0xc001, .action = VIA_DXS_SRC }, /* Insight P4-ITX */
+ { .subvendor = 0x1297, .subdevice = 0xa232, .action = VIA_DXS_ENABLE }, /* Shuttle ?? */
+ { .subvendor = 0x1297, .subdevice = 0xc160, .action = VIA_DXS_ENABLE }, /* Shuttle SK41G */
+ { .subvendor = 0x1458, .subdevice = 0xa002, .action = VIA_DXS_ENABLE }, /* Gigabyte GA-7VAXP */
+ { .subvendor = 0x1462, .subdevice = 0x0080, .action = VIA_DXS_SRC }, /* MSI K8T Neo-FIS2R */
+ { .subvendor = 0x1462, .subdevice = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */
+ { .subvendor = 0x1462, .subdevice = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */
+ { .subvendor = 0x1462, .subdevice = 0x7023, .action = VIA_DXS_NO_VRA }, /* MSI K8T Neo2-FI */
+ { .subvendor = 0x1462, .subdevice = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */
+ { .subvendor = 0x147b, .subdevice = 0x1401, .action = VIA_DXS_ENABLE }, /* ABIT KD7(-RAID) */
+ { .subvendor = 0x147b, .subdevice = 0x1411, .action = VIA_DXS_ENABLE }, /* ABIT VA-20 */
+ { .subvendor = 0x147b, .subdevice = 0x1413, .action = VIA_DXS_ENABLE }, /* ABIT KV8 Pro */
+ { .subvendor = 0x147b, .subdevice = 0x1415, .action = VIA_DXS_NO_VRA }, /* Abit AV8 */
+ { .subvendor = 0x14ff, .subdevice = 0x0403, .action = VIA_DXS_ENABLE }, /* Twinhead mobo */
+ { .subvendor = 0x14ff, .subdevice = 0x0408, .action = VIA_DXS_NO_VRA }, /* Twinhead mobo */
+ { .subvendor = 0x1584, .subdevice = 0x8120, .action = VIA_DXS_ENABLE }, /* Gericom/Targa/Vobis/Uniwill laptop */
+ { .subvendor = 0x1584, .subdevice = 0x8123, .action = VIA_DXS_NO_VRA }, /* Uniwill (Targa Visionary XP-210) */
+ { .subvendor = 0x161f, .subdevice = 0x202b, .action = VIA_DXS_NO_VRA }, /* Amira Note book */
+ { .subvendor = 0x161f, .subdevice = 0x2032, .action = VIA_DXS_48K }, /* m680x machines */
+ { .subvendor = 0x1631, .subdevice = 0xe004, .action = VIA_DXS_ENABLE }, /* Easy Note 3174, Packard Bell */
+ { .subvendor = 0x1695, .subdevice = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */
+ { .subvendor = 0x1849, .subdevice = 0x3059, .action = VIA_DXS_NO_VRA }, /* ASRock K7VM2 */
+ { .subvendor = 0x1919, .subdevice = 0x200a, .action = VIA_DXS_NO_VRA }, /* Soltek SL-K8Tpro-939 */
{ } /* terminator */
};
struct dxs_whitelist *w;
@@ -2182,14 +2196,14 @@ static int __devinit check_dxs_list(struct pci_dev *pci)
pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device);
- for (w = whitelist; w->vendor; w++) {
- if (w->vendor != subsystem_vendor)
+ for (w = whitelist; w->subvendor; w++) {
+ if (w->subvendor != subsystem_vendor)
continue;
if (w->mask) {
- if ((w->mask & subsystem_device) == w->device)
+ if ((w->mask & subsystem_device) == w->subdevice)
return w->action;
} else {
- if (subsystem_device == w->device)
+ if (subsystem_device == w->subdevice)
return w->action;
}
}
@@ -2198,8 +2212,9 @@ static int __devinit check_dxs_list(struct pci_dev *pci)
* not detected, try 48k rate only to be sure.
*/
printk(KERN_INFO "via82xx: Assuming DXS channels with 48k fixed sample rate.\n");
- printk(KERN_INFO " Please try dxs_support=1 or dxs_support=4 option\n");
+ printk(KERN_INFO " Please try dxs_support=5 option\n");
printk(KERN_INFO " and report if it works on your machine.\n");
+ printk(KERN_INFO " For more details, read ALSA-Configuration.txt.\n");
return VIA_DXS_48K;
};
@@ -2288,6 +2303,10 @@ static int __devinit snd_via82xx_probe(struct pci_dev *pci,
chip->dxs_fixed = 1;
else if (dxs_support[dev] == VIA_DXS_NO_VRA)
chip->no_vra = 1;
+ else if (dxs_support[dev] == VIA_DXS_SRC) {
+ chip->no_vra = 1;
+ chip->dxs_src = 1;
+ }
}
if ((err = snd_via8233_init_misc(chip, dev)) < 0)
goto __error;
@@ -2334,7 +2353,7 @@ static struct pci_driver driver = {
static int __init alsa_card_via82xx_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_via82xx_exit(void)
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index ea5c6f64015..5896d289f9a 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -352,10 +352,8 @@ static int clean_via_table(viadev_t *dev, snd_pcm_substream_t *substream,
snd_dma_free_pages(&dev->table);
dev->table.area = NULL;
}
- if (dev->idx_table) {
- kfree(dev->idx_table);
- dev->idx_table = NULL;
- }
+ kfree(dev->idx_table);
+ dev->idx_table = NULL;
return 0;
}
@@ -420,7 +418,10 @@ static void snd_via82xx_codec_write(ac97_t *ac97,
{
via82xx_t *chip = ac97->private_data;
unsigned int xval;
-
+ if(reg == AC97_GPIO_STATUS) {
+ outl(val, VIAREG(chip, GPI_STATUS));
+ return;
+ }
xval = !ac97->num ? VIA_REG_AC97_CODEC_ID_PRIMARY : VIA_REG_AC97_CODEC_ID_SECONDARY;
xval <<= VIA_REG_AC97_CODEC_ID_SHIFT;
xval |= reg << VIA_REG_AC97_CMD_SHIFT;
@@ -544,25 +545,6 @@ static int snd_via82xx_pcm_trigger(snd_pcm_substream_t * substream, int cmd)
return 0;
}
-static int snd_via82xx_modem_pcm_trigger(snd_pcm_substream_t * substream, int cmd)
-{
- via82xx_t *chip = snd_pcm_substream_chip(substream);
- unsigned int val = 0;
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- val = snd_ac97_read(chip->ac97, AC97_GPIO_STATUS);
- outl(val|AC97_GPIO_LINE1_OH, VIAREG(chip, GPI_STATUS));
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- val = snd_ac97_read(chip->ac97, AC97_GPIO_STATUS);
- outl(val&~AC97_GPIO_LINE1_OH, VIAREG(chip, GPI_STATUS));
- break;
- default:
- break;
- }
- return snd_via82xx_pcm_trigger(substream, cmd);
-}
-
/*
* pointer callbacks
*/
@@ -806,7 +788,7 @@ static snd_pcm_ops_t snd_via686_playback_ops = {
.hw_params = snd_via82xx_hw_params,
.hw_free = snd_via82xx_hw_free,
.prepare = snd_via82xx_pcm_prepare,
- .trigger = snd_via82xx_modem_pcm_trigger,
+ .trigger = snd_via82xx_pcm_trigger,
.pointer = snd_via686_pcm_pointer,
.page = snd_pcm_sgbuf_ops_page,
};
@@ -819,7 +801,7 @@ static snd_pcm_ops_t snd_via686_capture_ops = {
.hw_params = snd_via82xx_hw_params,
.hw_free = snd_via82xx_hw_free,
.prepare = snd_via82xx_pcm_prepare,
- .trigger = snd_via82xx_modem_pcm_trigger,
+ .trigger = snd_via82xx_pcm_trigger,
.pointer = snd_via686_pcm_pointer,
.page = snd_pcm_sgbuf_ops_page,
};
@@ -938,7 +920,7 @@ static void __devinit snd_via82xx_proc_init(via82xx_t *chip)
*
*/
-static int __devinit snd_via82xx_chip_init(via82xx_t *chip)
+static int snd_via82xx_chip_init(via82xx_t *chip)
{
unsigned int val;
int max_count;
@@ -1233,7 +1215,7 @@ static struct pci_driver driver = {
static int __init alsa_card_via82xx_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_via82xx_exit(void)
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
index 4ffbb25658a..dca6bd2c758 100644
--- a/sound/pci/vx222/vx222.c
+++ b/sound/pci/vx222/vx222.c
@@ -260,7 +260,7 @@ static struct pci_driver driver = {
static int __init alsa_card_vx222_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_vx222_exit(void)
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
index 9f3ef22df08..5b5b624b47d 100644
--- a/sound/pci/ymfpci/ymfpci.c
+++ b/sound/pci/ymfpci/ymfpci.c
@@ -360,7 +360,7 @@ static struct pci_driver driver = {
static int __init alsa_card_ymfpci_init(void)
{
- return pci_module_init(&driver);
+ return pci_register_driver(&driver);
}
static void __exit alsa_card_ymfpci_exit(void)
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index 05f1629760b..2ae79610ecb 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -829,9 +829,7 @@ static snd_pcm_hardware_t snd_ymfpci_capture =
static void snd_ymfpci_pcm_free_substream(snd_pcm_runtime_t *runtime)
{
- ymfpci_pcm_t *ypcm = runtime->private_data;
-
- kfree(ypcm);
+ kfree(runtime->private_data);
}
static int snd_ymfpci_playback_open_1(snd_pcm_substream_t * substream)
@@ -1421,17 +1419,15 @@ static snd_kcontrol_new_t snd_ymfpci_drec_source __devinitdata = {
static int snd_ymfpci_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
- unsigned int mask = 1;
-
switch (kcontrol->private_value) {
case YDSXGR_SPDIFOUTCTRL: break;
case YDSXGR_SPDIFINCTRL: break;
default: return -EINVAL;
}
- uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
uinfo->value.integer.min = 0;
- uinfo->value.integer.max = mask;
+ uinfo->value.integer.max = 1;
return 0;
}
@@ -1439,7 +1435,7 @@ static int snd_ymfpci_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
{
ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value;
- unsigned int shift = 0, mask = 1, invert = 0;
+ unsigned int shift = 0, mask = 1;
switch (kcontrol->private_value) {
case YDSXGR_SPDIFOUTCTRL: break;
@@ -1447,8 +1443,6 @@ static int snd_ymfpci_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
default: return -EINVAL;
}
ucontrol->value.integer.value[0] = (snd_ymfpci_readl(chip, reg) >> shift) & mask;
- if (invert)
- ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
return 0;
}
@@ -1456,7 +1450,7 @@ static int snd_ymfpci_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
{
ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
int reg = kcontrol->private_value;
- unsigned int shift = 0, mask = 1, invert = 0;
+ unsigned int shift = 0, mask = 1;
int change;
unsigned int val, oval;
@@ -1466,8 +1460,6 @@ static int snd_ymfpci_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
default: return -EINVAL;
}
val = (ucontrol->value.integer.value[0] & mask);
- if (invert)
- val = mask - val;
val <<= shift;
spin_lock_irq(&chip->reg_lock);
oval = snd_ymfpci_readl(chip, reg);
@@ -1487,14 +1479,13 @@ static int snd_ymfpci_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
static int snd_ymfpci_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{
unsigned int reg = kcontrol->private_value;
- unsigned int mask = 16383;
if (reg < 0x80 || reg >= 0xc0)
return -EINVAL;
- uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
uinfo->value.integer.min = 0;
- uinfo->value.integer.max = mask;
+ uinfo->value.integer.max = 16383;
return 0;
}
@@ -1502,7 +1493,7 @@ static int snd_ymfpci_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
{
ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
unsigned int reg = kcontrol->private_value;
- unsigned int shift_left = 0, shift_right = 16, mask = 16383, invert = 0;
+ unsigned int shift_left = 0, shift_right = 16, mask = 16383;
unsigned int val;
if (reg < 0x80 || reg >= 0xc0)
@@ -1512,10 +1503,6 @@ static int snd_ymfpci_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
spin_unlock_irq(&chip->reg_lock);
ucontrol->value.integer.value[0] = (val >> shift_left) & mask;
ucontrol->value.integer.value[1] = (val >> shift_right) & mask;
- if (invert) {
- ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
- ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
- }
return 0;
}
@@ -1523,7 +1510,7 @@ static int snd_ymfpci_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
{
ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
unsigned int reg = kcontrol->private_value;
- unsigned int shift_left = 0, shift_right = 16, mask = 16383, invert = 0;
+ unsigned int shift_left = 0, shift_right = 16, mask = 16383;
int change;
unsigned int val1, val2, oval;
@@ -1531,10 +1518,6 @@ static int snd_ymfpci_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t
return -EINVAL;
val1 = ucontrol->value.integer.value[0] & mask;
val2 = ucontrol->value.integer.value[1] & mask;
- if (invert) {
- val1 = mask - val1;
- val2 = mask - val2;
- }
val1 <<= shift_left;
val2 <<= shift_right;
spin_lock_irq(&chip->reg_lock);
diff --git a/sound/pcmcia/vx/vx_entry.c b/sound/pcmcia/vx/vx_entry.c
index 53d8172c52a..332bbca3dfc 100644
--- a/sound/pcmcia/vx/vx_entry.c
+++ b/sound/pcmcia/vx/vx_entry.c
@@ -68,8 +68,7 @@ static int snd_vxpocket_free(vx_core_t *chip)
if (hw)
hw->card_list[vxp->index] = NULL;
chip->card = NULL;
- if (chip->dev)
- kfree(chip->dev);
+ kfree(chip->dev);
snd_vx_free_firmware(chip);
kfree(chip);
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index 32d94754acf..080ef392846 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -876,7 +876,7 @@ static void __init detect_byte_swap(pmac_t *chip)
*/
static int __init snd_pmac_detect(pmac_t *chip)
{
- struct device_node *sound;
+ struct device_node *sound = NULL;
unsigned int *prop, l;
struct macio_chip* macio;
@@ -906,20 +906,22 @@ static int __init snd_pmac_detect(pmac_t *chip)
chip->is_pbook_G3 = 1;
chip->node = find_devices("awacs");
if (chip->node)
- return 0; /* ok */
+ sound = chip->node;
/*
* powermac G3 models have a node called "davbus"
* with a child called "sound".
*/
- chip->node = find_devices("davbus");
+ if (!chip->node)
+ chip->node = find_devices("davbus");
/*
* if we didn't find a davbus device, try 'i2s-a' since
* this seems to be what iBooks have
*/
if (! chip->node) {
chip->node = find_devices("i2s-a");
- if (chip->node && chip->node->parent && chip->node->parent->parent) {
+ if (chip->node && chip->node->parent &&
+ chip->node->parent->parent) {
if (device_is_compatible(chip->node->parent->parent,
"K2-Keylargo"))
chip->is_k2 = 1;
@@ -928,9 +930,11 @@ static int __init snd_pmac_detect(pmac_t *chip)
if (! chip->node)
return -ENODEV;
- sound = find_devices("sound");
- while (sound && sound->parent != chip->node)
- sound = sound->next;
+ if (!sound) {
+ sound = find_devices("sound");
+ while (sound && sound->parent != chip->node)
+ sound = sound->next;
+ }
if (! sound)
return -ENODEV;
prop = (unsigned int *) get_property(sound, "sub-frame", NULL);
@@ -1019,7 +1023,8 @@ static int __init snd_pmac_detect(pmac_t *chip)
}
}
if (chip->pdev == NULL)
- printk(KERN_WARNING "snd-powermac: can't locate macio PCI device !\n");
+ printk(KERN_WARNING "snd-powermac: can't locate macio PCI"
+ " device !\n");
detect_byte_swap(chip);
@@ -1027,7 +1032,8 @@ static int __init snd_pmac_detect(pmac_t *chip)
are available */
prop = (unsigned int *) get_property(sound, "sample-rates", &l);
if (! prop)
- prop = (unsigned int *) get_property(sound, "output-frame-rates", &l);
+ prop = (unsigned int *) get_property(sound,
+ "output-frame-rates", &l);
if (prop) {
int i;
chip->freqs_ok = 0;
@@ -1054,7 +1060,8 @@ static int __init snd_pmac_detect(pmac_t *chip)
/*
* exported - boolean info callbacks for ease of programming
*/
-int snd_pmac_boolean_stereo_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+int snd_pmac_boolean_stereo_info(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_info_t *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 2;
@@ -1063,7 +1070,8 @@ int snd_pmac_boolean_stereo_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *
return 0;
}
-int snd_pmac_boolean_mono_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+int snd_pmac_boolean_mono_info(snd_kcontrol_t *kcontrol,
+ snd_ctl_elem_info_t *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
uinfo->count = 1;
diff --git a/sound/sound_core.c b/sound/sound_core.c
index 30f75c9288c..21a69e09622 100644
--- a/sound/sound_core.c
+++ b/sound/sound_core.c
@@ -65,7 +65,7 @@ extern int msnd_classic_init(void);
extern int msnd_pinnacle_init(void);
#endif
-struct class_simple *sound_class;
+struct class *sound_class;
EXPORT_SYMBOL(sound_class);
/*
@@ -174,7 +174,7 @@ static int sound_insert_unit(struct sound_unit **list, struct file_operations *f
devfs_mk_cdev(MKDEV(SOUND_MAJOR, s->unit_minor),
S_IFCHR | mode, s->name);
- class_simple_device_add(sound_class, MKDEV(SOUND_MAJOR, s->unit_minor),
+ class_device_create(sound_class, MKDEV(SOUND_MAJOR, s->unit_minor),
NULL, s->name+6);
return r;
@@ -198,7 +198,7 @@ static void sound_remove_unit(struct sound_unit **list, int unit)
spin_unlock(&sound_loader_lock);
if (p) {
devfs_remove(p->name);
- class_simple_device_remove(MKDEV(SOUND_MAJOR, p->unit_minor));
+ class_device_destroy(sound_class, MKDEV(SOUND_MAJOR, p->unit_minor));
kfree(p);
}
}
@@ -562,7 +562,7 @@ static void __exit cleanup_soundcore(void)
empty */
unregister_chrdev(SOUND_MAJOR, "sound");
devfs_remove("sound");
- class_simple_destroy(sound_class);
+ class_destroy(sound_class);
}
static int __init init_soundcore(void)
@@ -572,7 +572,7 @@ static int __init init_soundcore(void)
return -EBUSY;
}
devfs_mk_dir ("sound");
- sound_class = class_simple_create(THIS_MODULE, "sound");
+ sound_class = class_create(THIS_MODULE, "sound");
if (IS_ERR(sound_class))
return PTR_ERR(sound_class);
diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c
index 16f3b461627..60d0b2c6669 100644
--- a/sound/synth/emux/emux.c
+++ b/sound/synth/emux/emux.c
@@ -22,6 +22,7 @@
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/slab.h>
+#include <linux/string.h>
#include <sound/core.h>
#include <sound/emux_synth.h>
#include <linux/init.h>
@@ -76,7 +77,7 @@ int snd_emux_register(snd_emux_t *emu, snd_card_t *card, int index, char *name)
snd_assert(name != NULL, return -EINVAL);
emu->card = card;
- emu->name = snd_kmalloc_strdup(name, GFP_KERNEL);
+ emu->name = kstrdup(name, GFP_KERNEL);
emu->voices = kcalloc(emu->max_voices, sizeof(snd_emux_voice_t), GFP_KERNEL);
if (emu->voices == NULL)
return -ENOMEM;
diff --git a/sound/synth/emux/emux_effect.c b/sound/synth/emux/emux_effect.c
index ec3fc1ba7fc..4764940f11a 100644
--- a/sound/synth/emux/emux_effect.c
+++ b/sound/synth/emux/emux_effect.c
@@ -291,10 +291,8 @@ snd_emux_create_effect(snd_emux_port_t *p)
void
snd_emux_delete_effect(snd_emux_port_t *p)
{
- if (p->effect) {
- kfree(p->effect);
- p->effect = NULL;
- }
+ kfree(p->effect);
+ p->effect = NULL;
}
void
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
index 9329e992c84..f05d02f5b69 100644
--- a/sound/usb/Kconfig
+++ b/sound/usb/Kconfig
@@ -6,6 +6,7 @@ menu "USB devices"
config SND_USB_AUDIO
tristate "USB Audio/MIDI driver"
depends on SND && USB
+ select SND_HWDEP
select SND_RAWMIDI
select SND_PCM
help
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 84b0bbddbd2..a75695045f2 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -98,7 +98,7 @@ MODULE_PARM_DESC(async_unlink, "Use async unlink mode.");
#define MAX_PACKS 10
#define MAX_PACKS_HS (MAX_PACKS * 8) /* in high speed mode */
#define MAX_URBS 5 /* max. 20ms long packets */
-#define SYNC_URBS 2 /* always two urbs for sync */
+#define SYNC_URBS 4 /* always four urbs for sync */
#define MIN_PACKS_URB 1 /* minimum 1 packet per urb */
typedef struct snd_usb_substream snd_usb_substream_t;
@@ -177,7 +177,7 @@ struct snd_usb_substream {
unsigned int nurbs; /* # urbs */
snd_urb_ctx_t dataurb[MAX_URBS]; /* data urb table */
snd_urb_ctx_t syncurb[SYNC_URBS]; /* sync urb table */
- char syncbuf[SYNC_URBS * MAX_PACKS * 4]; /* sync buffer; it's so small - let's get static */
+ char syncbuf[SYNC_URBS * 4]; /* sync buffer; it's so small - let's get static */
char *tmpbuf; /* temporary buffer for playback */
u64 formats; /* format bitmasks (all or'ed) */
@@ -251,17 +251,13 @@ static int prepare_capture_sync_urb(snd_usb_substream_t *subs,
{
unsigned char *cp = urb->transfer_buffer;
snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
- int i, offs;
- urb->number_of_packets = ctx->packets;
urb->dev = ctx->subs->dev; /* we need to set this at each time */
- for (i = offs = 0; i < urb->number_of_packets; i++, offs += 4, cp += 4) {
- urb->iso_frame_desc[i].length = 3;
- urb->iso_frame_desc[i].offset = offs;
- cp[0] = subs->freqn >> 2;
- cp[1] = subs->freqn >> 10;
- cp[2] = subs->freqn >> 18;
- }
+ urb->iso_frame_desc[0].length = 3;
+ urb->iso_frame_desc[0].offset = 0;
+ cp[0] = subs->freqn >> 2;
+ cp[1] = subs->freqn >> 10;
+ cp[2] = subs->freqn >> 18;
return 0;
}
@@ -277,18 +273,14 @@ static int prepare_capture_sync_urb_hs(snd_usb_substream_t *subs,
{
unsigned char *cp = urb->transfer_buffer;
snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
- int i, offs;
- urb->number_of_packets = ctx->packets;
urb->dev = ctx->subs->dev; /* we need to set this at each time */
- for (i = offs = 0; i < urb->number_of_packets; i++, offs += 4, cp += 4) {
- urb->iso_frame_desc[i].length = 4;
- urb->iso_frame_desc[i].offset = offs;
- cp[0] = subs->freqn;
- cp[1] = subs->freqn >> 8;
- cp[2] = subs->freqn >> 16;
- cp[3] = subs->freqn >> 24;
- }
+ urb->iso_frame_desc[0].length = 4;
+ urb->iso_frame_desc[0].offset = 0;
+ cp[0] = subs->freqn;
+ cp[1] = subs->freqn >> 8;
+ cp[2] = subs->freqn >> 16;
+ cp[3] = subs->freqn >> 24;
return 0;
}
@@ -418,15 +410,11 @@ static int prepare_playback_sync_urb(snd_usb_substream_t *subs,
snd_pcm_runtime_t *runtime,
struct urb *urb)
{
- int i, offs;
snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
- urb->number_of_packets = ctx->packets;
urb->dev = ctx->subs->dev; /* we need to set this at each time */
- for (i = offs = 0; i < urb->number_of_packets; i++, offs += 4) {
- urb->iso_frame_desc[i].length = 3;
- urb->iso_frame_desc[i].offset = offs;
- }
+ urb->iso_frame_desc[0].length = 3;
+ urb->iso_frame_desc[0].offset = 0;
return 0;
}
@@ -440,15 +428,11 @@ static int prepare_playback_sync_urb_hs(snd_usb_substream_t *subs,
snd_pcm_runtime_t *runtime,
struct urb *urb)
{
- int i, offs;
snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
- urb->number_of_packets = ctx->packets;
urb->dev = ctx->subs->dev; /* we need to set this at each time */
- for (i = offs = 0; i < urb->number_of_packets; i++, offs += 4) {
- urb->iso_frame_desc[i].length = 4;
- urb->iso_frame_desc[i].offset = offs;
- }
+ urb->iso_frame_desc[0].length = 4;
+ urb->iso_frame_desc[0].offset = 0;
return 0;
}
@@ -462,31 +446,17 @@ static int retire_playback_sync_urb(snd_usb_substream_t *subs,
snd_pcm_runtime_t *runtime,
struct urb *urb)
{
- int i;
- unsigned int f, found;
- unsigned char *cp = urb->transfer_buffer;
+ unsigned int f;
unsigned long flags;
- found = 0;
- for (i = 0; i < urb->number_of_packets; i++, cp += 4) {
- if (urb->iso_frame_desc[i].status ||
- urb->iso_frame_desc[i].actual_length < 3)
- continue;
- f = combine_triple(cp) << 2;
-#if 0
- if (f < subs->freqn - (subs->freqn>>3) || f > subs->freqmax) {
- snd_printd(KERN_WARNING "requested frequency %d (%u,%03uHz) out of range (current nominal %d (%u,%03uHz))\n",
- f, f >> 14, (f & ((1 << 14) - 1) * 1000) / ((1 << 14) - 1),
- subs->freqn, subs->freqn >> 14, (subs->freqn & ((1 << 14) - 1) * 1000) / ((1 << 14) - 1));
- continue;
+ if (urb->iso_frame_desc[0].status == 0 &&
+ urb->iso_frame_desc[0].actual_length == 3) {
+ f = combine_triple((u8*)urb->transfer_buffer) << 2;
+ if (f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax) {
+ spin_lock_irqsave(&subs->lock, flags);
+ subs->freqm = f;
+ spin_unlock_irqrestore(&subs->lock, flags);
}
-#endif
- found = f;
- }
- if (found) {
- spin_lock_irqsave(&subs->lock, flags);
- subs->freqm = found;
- spin_unlock_irqrestore(&subs->lock, flags);
}
return 0;
@@ -502,22 +472,17 @@ static int retire_playback_sync_urb_hs(snd_usb_substream_t *subs,
snd_pcm_runtime_t *runtime,
struct urb *urb)
{
- int i;
- unsigned int found;
- unsigned char *cp = urb->transfer_buffer;
+ unsigned int f;
unsigned long flags;
- found = 0;
- for (i = 0; i < urb->number_of_packets; i++, cp += 4) {
- if (urb->iso_frame_desc[i].status ||
- urb->iso_frame_desc[i].actual_length < 4)
- continue;
- found = combine_quad(cp) & 0x0fffffff;
- }
- if (found) {
- spin_lock_irqsave(&subs->lock, flags);
- subs->freqm = found;
- spin_unlock_irqrestore(&subs->lock, flags);
+ if (urb->iso_frame_desc[0].status == 0 &&
+ urb->iso_frame_desc[0].actual_length == 4) {
+ f = combine_quad((u8*)urb->transfer_buffer) & 0x0fffffff;
+ if (f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax) {
+ spin_lock_irqsave(&subs->lock, flags);
+ subs->freqm = f;
+ spin_unlock_irqrestore(&subs->lock, flags);
+ }
}
return 0;
@@ -600,6 +565,8 @@ static int prepare_playback_urb(snd_usb_substream_t *subs,
/* set the buffer pointer */
urb->transfer_buffer = runtime->dma_area + subs->hwptr * stride;
subs->hwptr += offs;
+ if (subs->hwptr == runtime->buffer_size)
+ subs->hwptr = 0;
}
spin_unlock_irqrestore(&subs->lock, flags);
urb->transfer_buffer_length = offs * stride;
@@ -892,10 +859,8 @@ static void release_urb_ctx(snd_urb_ctx_t *u)
usb_free_urb(u->urb);
u->urb = NULL;
}
- if (u->buf) {
- kfree(u->buf);
- u->buf = NULL;
- }
+ kfree(u->buf);
+ u->buf = NULL;
}
/*
@@ -913,10 +878,8 @@ static void release_substream_urbs(snd_usb_substream_t *subs, int force)
release_urb_ctx(&subs->dataurb[i]);
for (i = 0; i < SYNC_URBS; i++)
release_urb_ctx(&subs->syncurb[i]);
- if (subs->tmpbuf) {
- kfree(subs->tmpbuf);
- subs->tmpbuf = NULL;
- }
+ kfree(subs->tmpbuf);
+ subs->tmpbuf = NULL;
subs->nurbs = 0;
}
@@ -1039,22 +1002,19 @@ static int init_substream_urbs(snd_usb_substream_t *subs, unsigned int period_by
snd_urb_ctx_t *u = &subs->syncurb[i];
u->index = i;
u->subs = subs;
- u->packets = nrpacks;
- u->urb = usb_alloc_urb(u->packets, GFP_KERNEL);
+ u->packets = 1;
+ u->urb = usb_alloc_urb(1, GFP_KERNEL);
if (! u->urb) {
release_substream_urbs(subs, 0);
return -ENOMEM;
}
- u->urb->transfer_buffer = subs->syncbuf + i * nrpacks * 4;
- u->urb->transfer_buffer_length = nrpacks * 4;
+ u->urb->transfer_buffer = subs->syncbuf + i * 4;
+ u->urb->transfer_buffer_length = 4;
u->urb->dev = subs->dev;
u->urb->pipe = subs->syncpipe;
u->urb->transfer_flags = URB_ISO_ASAP;
- u->urb->number_of_packets = u->packets;
- if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH)
- u->urb->interval = 8;
- else
- u->urb->interval = 1;
+ u->urb->number_of_packets = 1;
+ u->urb->interval = 1 << subs->syncinterval;
u->urb->context = u;
u->urb->complete = snd_usb_complete_callback(snd_complete_sync_urb);
}
@@ -1272,7 +1232,17 @@ static int set_format(snd_usb_substream_t *subs, struct audioformat *fmt)
subs->syncpipe = usb_rcvisocpipe(dev, ep);
else
subs->syncpipe = usb_sndisocpipe(dev, ep);
- subs->syncinterval = get_endpoint(alts, 1)->bRefresh;
+ if (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
+ get_endpoint(alts, 1)->bRefresh >= 1 &&
+ get_endpoint(alts, 1)->bRefresh <= 9)
+ subs->syncinterval = get_endpoint(alts, 1)->bRefresh;
+ else if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
+ subs->syncinterval = 1;
+ else if (get_endpoint(alts, 1)->bInterval >= 1 &&
+ get_endpoint(alts, 1)->bInterval <= 16)
+ subs->syncinterval = get_endpoint(alts, 1)->bInterval - 1;
+ else
+ subs->syncinterval = 3;
}
/* always fill max packet size */
@@ -1990,10 +1960,11 @@ static void proc_dump_substream_status(snd_usb_substream_t *subs, snd_info_buffe
snd_iprintf(buffer, "%d ", subs->dataurb[i].packets);
snd_iprintf(buffer, "]\n");
snd_iprintf(buffer, " Packet Size = %d\n", subs->curpacksize);
- snd_iprintf(buffer, " Momentary freq = %u Hz\n",
+ snd_iprintf(buffer, " Momentary freq = %u Hz (%#x.%04x)\n",
snd_usb_get_speed(subs->dev) == USB_SPEED_FULL
? get_full_speed_hz(subs->freqm)
- : get_high_speed_hz(subs->freqm));
+ : get_high_speed_hz(subs->freqm),
+ subs->freqm >> 16, subs->freqm & 0xffff);
} else {
snd_iprintf(buffer, " Status: Stop\n");
}
@@ -2183,17 +2154,15 @@ static int add_audio_endpoint(snd_usb_audio_t *chip, int stream, struct audiofor
/*
* check if the device uses big-endian samples
*/
-static int is_big_endian_format(struct usb_device *dev, struct audioformat *fp)
+static int is_big_endian_format(snd_usb_audio_t *chip, struct audioformat *fp)
{
- /* M-Audio */
- if (le16_to_cpu(dev->descriptor.idVendor) == 0x0763) {
- /* Quattro: captured data only */
- if (le16_to_cpu(dev->descriptor.idProduct) == 0x2001 &&
- fp->endpoint & USB_DIR_IN)
- return 1;
- /* Audiophile USB */
- if (le16_to_cpu(dev->descriptor.idProduct) == 0x2003)
+ switch (chip->usb_id) {
+ case USB_ID(0x0763, 0x2001): /* M-Audio Quattro: captured data only */
+ if (fp->endpoint & USB_DIR_IN)
return 1;
+ break;
+ case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
+ return 1;
}
return 0;
}
@@ -2207,7 +2176,7 @@ static int is_big_endian_format(struct usb_device *dev, struct audioformat *fp)
* @format: the format tag (wFormatTag)
* @fmt: the format type descriptor
*/
-static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat *fp,
+static int parse_audio_format_i_type(snd_usb_audio_t *chip, struct audioformat *fp,
int format, unsigned char *fmt)
{
int pcm_format;
@@ -2220,12 +2189,12 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat
switch (format) {
case 0: /* some devices don't define this correctly... */
snd_printdd(KERN_INFO "%d:%u:%d : format type 0 is detected, processed as PCM\n",
- dev->devnum, fp->iface, fp->altsetting);
+ chip->dev->devnum, fp->iface, fp->altsetting);
/* fall-through */
case USB_AUDIO_FORMAT_PCM:
if (sample_width > sample_bytes * 8) {
snd_printk(KERN_INFO "%d:%u:%d : sample bitwidth %d in over sample bytes %d\n",
- dev->devnum, fp->iface, fp->altsetting,
+ chip->dev->devnum, fp->iface, fp->altsetting,
sample_width, sample_bytes);
}
/* check the format byte size */
@@ -2234,13 +2203,13 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat
pcm_format = SNDRV_PCM_FORMAT_S8;
break;
case 2:
- if (is_big_endian_format(dev, fp))
+ if (is_big_endian_format(chip, fp))
pcm_format = SNDRV_PCM_FORMAT_S16_BE; /* grrr, big endian!! */
else
pcm_format = SNDRV_PCM_FORMAT_S16_LE;
break;
case 3:
- if (is_big_endian_format(dev, fp))
+ if (is_big_endian_format(chip, fp))
pcm_format = SNDRV_PCM_FORMAT_S24_3BE; /* grrr, big endian!! */
else
pcm_format = SNDRV_PCM_FORMAT_S24_3LE;
@@ -2250,14 +2219,14 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat
break;
default:
snd_printk(KERN_INFO "%d:%u:%d : unsupported sample bitwidth %d in %d bytes\n",
- dev->devnum, fp->iface, fp->altsetting, sample_width, sample_bytes);
+ chip->dev->devnum, fp->iface,
+ fp->altsetting, sample_width, sample_bytes);
break;
}
break;
case USB_AUDIO_FORMAT_PCM8:
/* Dallas DS4201 workaround */
- if (le16_to_cpu(dev->descriptor.idVendor) == 0x04fa &&
- le16_to_cpu(dev->descriptor.idProduct) == 0x4201)
+ if (chip->usb_id == USB_ID(0x04fa, 0x4201))
pcm_format = SNDRV_PCM_FORMAT_S8;
else
pcm_format = SNDRV_PCM_FORMAT_U8;
@@ -2273,7 +2242,7 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat
break;
default:
snd_printk(KERN_INFO "%d:%u:%d : unsupported format type %d\n",
- dev->devnum, fp->iface, fp->altsetting, format);
+ chip->dev->devnum, fp->iface, fp->altsetting, format);
break;
}
return pcm_format;
@@ -2290,13 +2259,13 @@ static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat
* @offset: the start offset of descriptor pointing the rate type
* (7 for type I and II, 8 for type II)
*/
-static int parse_audio_format_rates(struct usb_device *dev, struct audioformat *fp,
+static int parse_audio_format_rates(snd_usb_audio_t *chip, struct audioformat *fp,
unsigned char *fmt, int offset)
{
int nr_rates = fmt[offset];
if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) {
snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n",
- dev->devnum, fp->iface, fp->altsetting);
+ chip->dev->devnum, fp->iface, fp->altsetting);
return -1;
}
@@ -2343,7 +2312,7 @@ static int parse_audio_format_rates(struct usb_device *dev, struct audioformat *
/*
* parse the format type I and III descriptors
*/
-static int parse_audio_format_i(struct usb_device *dev, struct audioformat *fp,
+static int parse_audio_format_i(snd_usb_audio_t *chip, struct audioformat *fp,
int format, unsigned char *fmt)
{
int pcm_format;
@@ -2355,7 +2324,7 @@ static int parse_audio_format_i(struct usb_device *dev, struct audioformat *fp,
*/
pcm_format = SNDRV_PCM_FORMAT_S16_LE;
} else {
- pcm_format = parse_audio_format_i_type(dev, fp, format, fmt);
+ pcm_format = parse_audio_format_i_type(chip, fp, format, fmt);
if (pcm_format < 0)
return -1;
}
@@ -2363,16 +2332,16 @@ static int parse_audio_format_i(struct usb_device *dev, struct audioformat *fp,
fp->channels = fmt[4];
if (fp->channels < 1) {
snd_printk(KERN_ERR "%d:%u:%d : invalid channels %d\n",
- dev->devnum, fp->iface, fp->altsetting, fp->channels);
+ chip->dev->devnum, fp->iface, fp->altsetting, fp->channels);
return -1;
}
- return parse_audio_format_rates(dev, fp, fmt, 7);
+ return parse_audio_format_rates(chip, fp, fmt, 7);
}
/*
* prase the format type II descriptor
*/
-static int parse_audio_format_ii(struct usb_device *dev, struct audioformat *fp,
+static int parse_audio_format_ii(snd_usb_audio_t *chip, struct audioformat *fp,
int format, unsigned char *fmt)
{
int brate, framesize;
@@ -2387,7 +2356,7 @@ static int parse_audio_format_ii(struct usb_device *dev, struct audioformat *fp,
break;
default:
snd_printd(KERN_INFO "%d:%u:%d : unknown format tag 0x%x is detected. processed as MPEG.\n",
- dev->devnum, fp->iface, fp->altsetting, format);
+ chip->dev->devnum, fp->iface, fp->altsetting, format);
fp->format = SNDRV_PCM_FORMAT_MPEG;
break;
}
@@ -2396,10 +2365,10 @@ static int parse_audio_format_ii(struct usb_device *dev, struct audioformat *fp,
framesize = combine_word(&fmt[6]); /* fmt[6,7]: wSamplesPerFrame */
snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize);
fp->frame_size = framesize;
- return parse_audio_format_rates(dev, fp, fmt, 8); /* fmt[8..] sample rates */
+ return parse_audio_format_rates(chip, fp, fmt, 8); /* fmt[8..] sample rates */
}
-static int parse_audio_format(struct usb_device *dev, struct audioformat *fp,
+static int parse_audio_format(snd_usb_audio_t *chip, struct audioformat *fp,
int format, unsigned char *fmt, int stream)
{
int err;
@@ -2407,29 +2376,30 @@ static int parse_audio_format(struct usb_device *dev, struct audioformat *fp,
switch (fmt[3]) {
case USB_FORMAT_TYPE_I:
case USB_FORMAT_TYPE_III:
- err = parse_audio_format_i(dev, fp, format, fmt);
+ err = parse_audio_format_i(chip, fp, format, fmt);
break;
case USB_FORMAT_TYPE_II:
- err = parse_audio_format_ii(dev, fp, format, fmt);
+ err = parse_audio_format_ii(chip, fp, format, fmt);
break;
default:
snd_printd(KERN_INFO "%d:%u:%d : format type %d is not supported yet\n",
- dev->devnum, fp->iface, fp->altsetting, fmt[3]);
+ chip->dev->devnum, fp->iface, fp->altsetting, fmt[3]);
return -1;
}
fp->fmt_type = fmt[3];
if (err < 0)
return err;
#if 1
- /* FIXME: temporary hack for extigy */
+ /* FIXME: temporary hack for extigy/audigy 2 nx */
/* extigy apparently supports sample rates other than 48k
* but not in ordinary way. so we enable only 48k atm.
*/
- if (le16_to_cpu(dev->descriptor.idVendor) == 0x041e &&
- le16_to_cpu(dev->descriptor.idProduct) == 0x3000) {
+ if (chip->usb_id == USB_ID(0x041e, 0x3000) ||
+ chip->usb_id == USB_ID(0x041e, 0x3020)) {
if (fmt[3] == USB_FORMAT_TYPE_I &&
stream == SNDRV_PCM_STREAM_PLAYBACK &&
- fp->rates != SNDRV_PCM_RATE_48000)
+ fp->rates != SNDRV_PCM_RATE_48000 &&
+ fp->rates != SNDRV_PCM_RATE_96000)
return -1; /* use 48k only */
}
#endif
@@ -2528,40 +2498,35 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no)
/* some quirks for attributes here */
- /* workaround for AudioTrak Optoplay */
- if (le16_to_cpu(dev->descriptor.idVendor) == 0x0a92 &&
- le16_to_cpu(dev->descriptor.idProduct) == 0x0053) {
+ switch (chip->usb_id) {
+ case USB_ID(0x0a92, 0x0053): /* AudioTrak Optoplay */
/* Optoplay sets the sample rate attribute although
* it seems not supporting it in fact.
*/
fp->attributes &= ~EP_CS_ATTR_SAMPLE_RATE;
- }
-
- /* workaround for M-Audio Audiophile USB */
- if (le16_to_cpu(dev->descriptor.idVendor) == 0x0763 &&
- le16_to_cpu(dev->descriptor.idProduct) == 0x2003) {
+ break;
+ case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */
+ case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
/* doesn't set the sample rate attribute, but supports it */
fp->attributes |= EP_CS_ATTR_SAMPLE_RATE;
- }
-
+ break;
+ case USB_ID(0x047f, 0x0ca1): /* plantronics headset */
+ case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is
+ an older model 77d:223) */
/*
* plantronics headset and Griffin iMic have set adaptive-in
* although it's really not...
*/
- if ((le16_to_cpu(dev->descriptor.idVendor) == 0x047f &&
- le16_to_cpu(dev->descriptor.idProduct) == 0x0ca1) ||
- /* Griffin iMic (note that there is an older model 77d:223) */
- (le16_to_cpu(dev->descriptor.idVendor) == 0x077d &&
- le16_to_cpu(dev->descriptor.idProduct) == 0x07af)) {
fp->ep_attr &= ~EP_ATTR_MASK;
if (stream == SNDRV_PCM_STREAM_PLAYBACK)
fp->ep_attr |= EP_ATTR_ADAPTIVE;
else
fp->ep_attr |= EP_ATTR_SYNC;
+ break;
}
/* ok, let's parse further... */
- if (parse_audio_format(dev, fp, format, fmt, stream) < 0) {
+ if (parse_audio_format(chip, fp, format, fmt, stream) < 0) {
kfree(fp->rate_table);
kfree(fp);
continue;
@@ -2587,7 +2552,7 @@ static int parse_audio_endpoints(snd_usb_audio_t *chip, int iface_no)
* disconnect streams
* called from snd_usb_audio_disconnect()
*/
-static void snd_usb_stream_disconnect(struct list_head *head, struct usb_driver *driver)
+static void snd_usb_stream_disconnect(struct list_head *head)
{
int idx;
snd_usb_stream_t *as;
@@ -2796,7 +2761,7 @@ static int create_ua700_ua25_quirk(snd_usb_audio_t *chip,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
.data = &ua25_ep
};
- if (le16_to_cpu(chip->dev->descriptor.idProduct) == 0x002b)
+ if (chip->usb_id == USB_ID(0x0582, 0x002b))
return snd_usb_create_midi_interface(chip, iface,
&ua700_quirk);
else
@@ -2959,6 +2924,25 @@ static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interfac
return 0;
}
+static int snd_usb_audigy2nx_boot_quirk(struct usb_device *dev)
+{
+#if 0
+ /* TODO: enable this when high speed synchronization actually works */
+ u8 buf = 1;
+
+ snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), 0x2a,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER,
+ 0, 0, &buf, 1, 1000);
+ if (buf == 0) {
+ snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 0x29,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
+ 1, 2000, NULL, 0, 1000);
+ return -ENODEV;
+ }
+#endif
+ return 0;
+}
+
/*
* audio-interface quirks
@@ -3015,8 +2999,8 @@ static void proc_audio_usbid_read(snd_info_entry_t *entry, snd_info_buffer_t *bu
snd_usb_audio_t *chip = entry->private_data;
if (! chip->shutdown)
snd_iprintf(buffer, "%04x:%04x\n",
- le16_to_cpu(chip->dev->descriptor.idVendor),
- le16_to_cpu(chip->dev->descriptor.idProduct));
+ USB_ID_VENDOR(chip->usb_id),
+ USB_ID_PRODUCT(chip->usb_id));
}
static void snd_usb_audio_create_proc(snd_usb_audio_t *chip)
@@ -3086,8 +3070,11 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
chip->index = idx;
chip->dev = dev;
chip->card = card;
+ chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
INIT_LIST_HEAD(&chip->pcm_list);
INIT_LIST_HEAD(&chip->midi_list);
+ INIT_LIST_HEAD(&chip->mixer_list);
if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
snd_usb_audio_free(chip);
@@ -3097,8 +3084,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
strcpy(card->driver, "USB-Audio");
sprintf(component, "USB%04x:%04x",
- le16_to_cpu(dev->descriptor.idVendor),
- le16_to_cpu(dev->descriptor.idProduct));
+ USB_ID_VENDOR(chip->usb_id), USB_ID_PRODUCT(chip->usb_id));
snd_component_add(card, component);
/* retrieve the device string as shortname */
@@ -3110,8 +3096,8 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
card->shortname, sizeof(card->shortname)) <= 0) {
/* no name available from anywhere, so use ID */
sprintf(card->shortname, "USB Device %#04x:%#04x",
- le16_to_cpu(dev->descriptor.idVendor),
- le16_to_cpu(dev->descriptor.idProduct));
+ USB_ID_VENDOR(chip->usb_id),
+ USB_ID_PRODUCT(chip->usb_id));
}
}
@@ -3142,8 +3128,6 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
snd_usb_audio_create_proc(chip);
- snd_card_set_dev(card, &dev->dev);
-
*rchip = chip;
return 0;
}
@@ -3169,21 +3153,28 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
snd_usb_audio_t *chip;
struct usb_host_interface *alts;
int ifnum;
+ u32 id;
alts = &intf->altsetting[0];
ifnum = get_iface_desc(alts)->bInterfaceNumber;
+ id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
+ le16_to_cpu(dev->descriptor.idProduct));
if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum)
goto __err_val;
/* SB Extigy needs special boot-up sequence */
/* if more models come, this will go to the quirk list. */
- if (le16_to_cpu(dev->descriptor.idVendor) == 0x041e &&
- le16_to_cpu(dev->descriptor.idProduct) == 0x3000) {
+ if (id == USB_ID(0x041e, 0x3000)) {
if (snd_usb_extigy_boot_quirk(dev, intf) < 0)
goto __err_val;
config = dev->actconfig;
}
+ /* SB Audigy 2 NX needs its own boot-up magic, too */
+ if (id == USB_ID(0x041e, 0x3020)) {
+ if (snd_usb_audigy2nx_boot_quirk(dev) < 0)
+ goto __err_val;
+ }
/*
* found a config. now register to ALSA
@@ -3213,11 +3204,12 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
}
for (i = 0; i < SNDRV_CARDS; i++)
if (enable[i] && ! usb_chip[i] &&
- (vid[i] == -1 || vid[i] == le16_to_cpu(dev->descriptor.idVendor)) &&
- (pid[i] == -1 || pid[i] == le16_to_cpu(dev->descriptor.idProduct))) {
+ (vid[i] == -1 || vid[i] == USB_ID_VENDOR(id)) &&
+ (pid[i] == -1 || pid[i] == USB_ID_PRODUCT(id))) {
if (snd_usb_audio_create(dev, i, quirk, &chip) < 0) {
goto __error;
}
+ snd_card_set_dev(chip->card, &intf->dev);
break;
}
if (! chip) {
@@ -3281,15 +3273,19 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, void *ptr)
snd_card_disconnect(card);
/* release the pcm resources */
list_for_each(p, &chip->pcm_list) {
- snd_usb_stream_disconnect(p, &usb_audio_driver);
+ snd_usb_stream_disconnect(p);
}
/* release the midi resources */
list_for_each(p, &chip->midi_list) {
- snd_usbmidi_disconnect(p, &usb_audio_driver);
+ snd_usbmidi_disconnect(p);
+ }
+ /* release mixer resources */
+ list_for_each(p, &chip->mixer_list) {
+ snd_usb_mixer_disconnect(p);
}
usb_chip[chip->index] = NULL;
up(&register_mutex);
- snd_card_free_in_thread(card);
+ snd_card_free(card);
} else {
up(&register_mutex);
}
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index eecbf19fcb6..aedb42aaa74 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -118,6 +118,11 @@
/* maximum number of endpoints per interface */
#define MIDI_MAX_ENDPOINTS 2
+/* handling of USB vendor/product ID pairs as 32-bit numbers */
+#define USB_ID(vendor, product) (((vendor) << 16) | (product))
+#define USB_ID_VENDOR(id) ((id) >> 16)
+#define USB_ID_PRODUCT(id) ((u16)(id))
+
/*
*/
@@ -127,6 +132,7 @@ struct snd_usb_audio {
int index;
struct usb_device *dev;
snd_card_t *card;
+ u32 usb_id;
int shutdown;
int num_interfaces;
@@ -136,7 +142,7 @@ struct snd_usb_audio {
struct list_head midi_list; /* list of midi interfaces */
int next_midi_device;
- unsigned int ignore_ctl_error; /* for mixer */
+ struct list_head mixer_list; /* list of mixer interfaces */
};
/*
@@ -219,11 +225,12 @@ void *snd_usb_find_csint_desc(void *descstart, int desclen, void *after, u8 dsub
int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout);
int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif);
+void snd_usb_mixer_disconnect(struct list_head *p);
int snd_usb_create_midi_interface(snd_usb_audio_t *chip, struct usb_interface *iface, const snd_usb_audio_quirk_t *quirk);
void snd_usbmidi_input_stop(struct list_head* p);
void snd_usbmidi_input_start(struct list_head* p);
-void snd_usbmidi_disconnect(struct list_head *p, struct usb_driver *driver);
+void snd_usbmidi_disconnect(struct list_head *p);
/*
* retrieve usb_interface descriptor from the host interface
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index 5d32857ff95..bee70068dce 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -912,7 +912,7 @@ static void snd_usbmidi_free(snd_usb_midi_t* umidi)
/*
* Unlinks all URBs (must be done before the usb_device is deleted).
*/
-void snd_usbmidi_disconnect(struct list_head* p, struct usb_driver *driver)
+void snd_usbmidi_disconnect(struct list_head* p)
{
snd_usb_midi_t* umidi;
int i;
@@ -955,88 +955,87 @@ static snd_rawmidi_substream_t* snd_usbmidi_find_substream(snd_usb_midi_t* umidi
* such as internal control or synthesizer ports.
*/
static struct {
- __u16 vendor;
- __u16 product;
+ u32 id;
int port;
const char *name_format;
} snd_usbmidi_port_names[] = {
/* Roland UA-100 */
- {0x0582, 0x0000, 2, "%s Control"},
+ { USB_ID(0x0582, 0x0000), 2, "%s Control" },
/* Roland SC-8850 */
- {0x0582, 0x0003, 0, "%s Part A"},
- {0x0582, 0x0003, 1, "%s Part B"},
- {0x0582, 0x0003, 2, "%s Part C"},
- {0x0582, 0x0003, 3, "%s Part D"},
- {0x0582, 0x0003, 4, "%s MIDI 1"},
- {0x0582, 0x0003, 5, "%s MIDI 2"},
+ { USB_ID(0x0582, 0x0003), 0, "%s Part A" },
+ { USB_ID(0x0582, 0x0003), 1, "%s Part B" },
+ { USB_ID(0x0582, 0x0003), 2, "%s Part C" },
+ { USB_ID(0x0582, 0x0003), 3, "%s Part D" },
+ { USB_ID(0x0582, 0x0003), 4, "%s MIDI 1" },
+ { USB_ID(0x0582, 0x0003), 5, "%s MIDI 2" },
/* Roland U-8 */
- {0x0582, 0x0004, 0, "%s MIDI"},
- {0x0582, 0x0004, 1, "%s Control"},
+ { USB_ID(0x0582, 0x0004), 0, "%s MIDI" },
+ { USB_ID(0x0582, 0x0004), 1, "%s Control" },
/* Roland SC-8820 */
- {0x0582, 0x0007, 0, "%s Part A"},
- {0x0582, 0x0007, 1, "%s Part B"},
- {0x0582, 0x0007, 2, "%s MIDI"},
+ { USB_ID(0x0582, 0x0007), 0, "%s Part A" },
+ { USB_ID(0x0582, 0x0007), 1, "%s Part B" },
+ { USB_ID(0x0582, 0x0007), 2, "%s MIDI" },
/* Roland SK-500 */
- {0x0582, 0x000b, 0, "%s Part A"},
- {0x0582, 0x000b, 1, "%s Part B"},
- {0x0582, 0x000b, 2, "%s MIDI"},
+ { USB_ID(0x0582, 0x000b), 0, "%s Part A" },
+ { USB_ID(0x0582, 0x000b), 1, "%s Part B" },
+ { USB_ID(0x0582, 0x000b), 2, "%s MIDI" },
/* Roland SC-D70 */
- {0x0582, 0x000c, 0, "%s Part A"},
- {0x0582, 0x000c, 1, "%s Part B"},
- {0x0582, 0x000c, 2, "%s MIDI"},
+ { USB_ID(0x0582, 0x000c), 0, "%s Part A" },
+ { USB_ID(0x0582, 0x000c), 1, "%s Part B" },
+ { USB_ID(0x0582, 0x000c), 2, "%s MIDI" },
/* Edirol UM-880 */
- {0x0582, 0x0014, 8, "%s Control"},
+ { USB_ID(0x0582, 0x0014), 8, "%s Control" },
/* Edirol SD-90 */
- {0x0582, 0x0016, 0, "%s Part A"},
- {0x0582, 0x0016, 1, "%s Part B"},
- {0x0582, 0x0016, 2, "%s MIDI 1"},
- {0x0582, 0x0016, 3, "%s MIDI 2"},
+ { USB_ID(0x0582, 0x0016), 0, "%s Part A" },
+ { USB_ID(0x0582, 0x0016), 1, "%s Part B" },
+ { USB_ID(0x0582, 0x0016), 2, "%s MIDI 1" },
+ { USB_ID(0x0582, 0x0016), 3, "%s MIDI 2" },
/* Edirol UM-550 */
- {0x0582, 0x0023, 5, "%s Control"},
+ { USB_ID(0x0582, 0x0023), 5, "%s Control" },
/* Edirol SD-20 */
- {0x0582, 0x0027, 0, "%s Part A"},
- {0x0582, 0x0027, 1, "%s Part B"},
- {0x0582, 0x0027, 2, "%s MIDI"},
+ { USB_ID(0x0582, 0x0027), 0, "%s Part A" },
+ { USB_ID(0x0582, 0x0027), 1, "%s Part B" },
+ { USB_ID(0x0582, 0x0027), 2, "%s MIDI" },
/* Edirol SD-80 */
- {0x0582, 0x0029, 0, "%s Part A"},
- {0x0582, 0x0029, 1, "%s Part B"},
- {0x0582, 0x0029, 2, "%s MIDI 1"},
- {0x0582, 0x0029, 3, "%s MIDI 2"},
+ { USB_ID(0x0582, 0x0029), 0, "%s Part A" },
+ { USB_ID(0x0582, 0x0029), 1, "%s Part B" },
+ { USB_ID(0x0582, 0x0029), 2, "%s MIDI 1" },
+ { USB_ID(0x0582, 0x0029), 3, "%s MIDI 2" },
/* Edirol UA-700 */
- {0x0582, 0x002b, 0, "%s MIDI"},
- {0x0582, 0x002b, 1, "%s Control"},
+ { USB_ID(0x0582, 0x002b), 0, "%s MIDI" },
+ { USB_ID(0x0582, 0x002b), 1, "%s Control" },
/* Roland VariOS */
- {0x0582, 0x002f, 0, "%s MIDI"},
- {0x0582, 0x002f, 1, "%s External MIDI"},
- {0x0582, 0x002f, 2, "%s Sync"},
+ { USB_ID(0x0582, 0x002f), 0, "%s MIDI" },
+ { USB_ID(0x0582, 0x002f), 1, "%s External MIDI" },
+ { USB_ID(0x0582, 0x002f), 2, "%s Sync" },
/* Edirol PCR */
- {0x0582, 0x0033, 0, "%s MIDI"},
- {0x0582, 0x0033, 1, "%s 1"},
- {0x0582, 0x0033, 2, "%s 2"},
+ { USB_ID(0x0582, 0x0033), 0, "%s MIDI" },
+ { USB_ID(0x0582, 0x0033), 1, "%s 1" },
+ { USB_ID(0x0582, 0x0033), 2, "%s 2" },
/* BOSS GS-10 */
- {0x0582, 0x003b, 0, "%s MIDI"},
- {0x0582, 0x003b, 1, "%s Control"},
+ { USB_ID(0x0582, 0x003b), 0, "%s MIDI" },
+ { USB_ID(0x0582, 0x003b), 1, "%s Control" },
/* Edirol UA-1000 */
- {0x0582, 0x0044, 0, "%s MIDI"},
- {0x0582, 0x0044, 1, "%s Control"},
+ { USB_ID(0x0582, 0x0044), 0, "%s MIDI" },
+ { USB_ID(0x0582, 0x0044), 1, "%s Control" },
/* Edirol UR-80 */
- {0x0582, 0x0048, 0, "%s MIDI"},
- {0x0582, 0x0048, 1, "%s 1"},
- {0x0582, 0x0048, 2, "%s 2"},
+ { USB_ID(0x0582, 0x0048), 0, "%s MIDI" },
+ { USB_ID(0x0582, 0x0048), 1, "%s 1" },
+ { USB_ID(0x0582, 0x0048), 2, "%s 2" },
/* Edirol PCR-A */
- {0x0582, 0x004d, 0, "%s MIDI"},
- {0x0582, 0x004d, 1, "%s 1"},
- {0x0582, 0x004d, 2, "%s 2"},
+ { USB_ID(0x0582, 0x004d), 0, "%s MIDI" },
+ { USB_ID(0x0582, 0x004d), 1, "%s 1" },
+ { USB_ID(0x0582, 0x004d), 2, "%s 2" },
/* M-Audio MidiSport 8x8 */
- {0x0763, 0x1031, 8, "%s Control"},
- {0x0763, 0x1033, 8, "%s Control"},
+ { USB_ID(0x0763, 0x1031), 8, "%s Control" },
+ { USB_ID(0x0763, 0x1033), 8, "%s Control" },
/* MOTU Fastlane */
- {0x07fd, 0x0001, 0, "%s MIDI A"},
- {0x07fd, 0x0001, 1, "%s MIDI B"},
+ { USB_ID(0x07fd, 0x0001), 0, "%s MIDI A" },
+ { USB_ID(0x07fd, 0x0001), 1, "%s MIDI B" },
/* Emagic Unitor8/AMT8/MT4 */
- {0x086a, 0x0001, 8, "%s Broadcast"},
- {0x086a, 0x0002, 8, "%s Broadcast"},
- {0x086a, 0x0003, 4, "%s Broadcast"},
+ { USB_ID(0x086a, 0x0001), 8, "%s Broadcast" },
+ { USB_ID(0x086a, 0x0002), 8, "%s Broadcast" },
+ { USB_ID(0x086a, 0x0003), 4, "%s Broadcast" },
};
static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi,
@@ -1044,7 +1043,6 @@ static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi,
snd_rawmidi_substream_t** rsubstream)
{
int i;
- __u16 vendor, product;
const char *name_format;
snd_rawmidi_substream_t* substream = snd_usbmidi_find_substream(umidi, stream, number);
@@ -1055,11 +1053,8 @@ static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi,
/* TODO: read port name from jack descriptor */
name_format = "%s MIDI %d";
- vendor = le16_to_cpu(umidi->chip->dev->descriptor.idVendor);
- product = le16_to_cpu(umidi->chip->dev->descriptor.idProduct);
for (i = 0; i < ARRAY_SIZE(snd_usbmidi_port_names); ++i) {
- if (snd_usbmidi_port_names[i].vendor == vendor &&
- snd_usbmidi_port_names[i].product == product &&
+ if (snd_usbmidi_port_names[i].id == umidi->chip->usb_id &&
snd_usbmidi_port_names[i].port == number) {
name_format = snd_usbmidi_port_names[i].name_format;
break;
@@ -1226,9 +1221,12 @@ static int snd_usbmidi_detect_endpoints(snd_usb_midi_t* umidi,
struct usb_endpoint_descriptor* epd;
int i, out_eps = 0, in_eps = 0;
- if (le16_to_cpu(umidi->chip->dev->descriptor.idVendor) == 0x0582)
+ if (USB_ID_VENDOR(umidi->chip->usb_id) == 0x0582)
snd_usbmidi_switch_roland_altsetting(umidi);
+ if (endpoint[0].out_ep || endpoint[0].in_ep)
+ return 0;
+
intf = umidi->iface;
if (!intf || intf->num_altsetting < 1)
return -ENOENT;
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index 5f1906915aa..e73c1c9d3e7 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -35,10 +35,11 @@
#include <linux/usb.h>
#include <sound/core.h>
#include <sound/control.h>
+#include <sound/hwdep.h>
+#include <sound/info.h>
#include "usbaudio.h"
-
/*
*/
@@ -50,6 +51,31 @@ typedef struct usb_audio_term usb_audio_term_t;
typedef struct usb_mixer_elem_info usb_mixer_elem_info_t;
+struct usb_mixer_interface {
+ snd_usb_audio_t *chip;
+ unsigned int ctrlif;
+ struct list_head list;
+ unsigned int ignore_ctl_error;
+ struct urb *urb;
+ usb_mixer_elem_info_t **id_elems; /* array[256], indexed by unit id */
+
+ /* Sound Blaster remote control stuff */
+ enum {
+ RC_NONE,
+ RC_EXTIGY,
+ RC_AUDIGY2NX,
+ } rc_type;
+ unsigned long rc_hwdep_open;
+ u32 rc_code;
+ wait_queue_head_t rc_waitq;
+ struct urb *rc_urb;
+ struct usb_ctrlrequest *rc_setup_packet;
+ u8 rc_buffer[6];
+
+ u8 audigy2nx_leds[3];
+};
+
+
struct usb_audio_term {
int id;
int type;
@@ -62,26 +88,26 @@ struct usbmix_name_map;
struct usb_mixer_build {
snd_usb_audio_t *chip;
+ struct usb_mixer_interface *mixer;
unsigned char *buffer;
unsigned int buflen;
- unsigned int ctrlif;
- unsigned short vendor;
- unsigned short product;
- DECLARE_BITMAP(unitbitmap, 32*32);
+ DECLARE_BITMAP(unitbitmap, 256);
usb_audio_term_t oterm;
const struct usbmix_name_map *map;
+ const struct usbmix_selector_map *selector_map;
};
struct usb_mixer_elem_info {
- snd_usb_audio_t *chip;
- unsigned int ctrlif;
+ struct usb_mixer_interface *mixer;
+ usb_mixer_elem_info_t *next_id_elem; /* list of controls with same id */
+ snd_ctl_elem_id_t *elem_id;
unsigned int id;
unsigned int control; /* CS or ICN (high byte) */
unsigned int cmask; /* channel mask bitmap: 0 = master */
int channels;
int val_type;
int min, max, res;
- unsigned int initialized: 1;
+ u8 initialized;
};
@@ -187,6 +213,21 @@ static int check_ignored_ctl(mixer_build_t *state, int unitid, int control)
return 0;
}
+/* get the mapped selector source name */
+static int check_mapped_selector_name(mixer_build_t *state, int unitid,
+ int index, char *buf, int buflen)
+{
+ const struct usbmix_selector_map *p;
+
+ if (! state->selector_map)
+ return 0;
+ for (p = state->selector_map; p->id; p++) {
+ if (p->id == unitid && index < p->count)
+ return strlcpy(buf, p->names[index], buflen);
+ }
+ return 0;
+}
+
/*
* find an audio control unit with the given unit id
*/
@@ -301,16 +342,18 @@ static int get_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, i
int timeout = 10;
while (timeout-- > 0) {
- if (snd_usb_ctl_msg(cval->chip->dev, usb_rcvctrlpipe(cval->chip->dev, 0),
+ if (snd_usb_ctl_msg(cval->mixer->chip->dev,
+ usb_rcvctrlpipe(cval->mixer->chip->dev, 0),
request,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
- validx, cval->ctrlif | (cval->id << 8),
+ validx, cval->mixer->ctrlif | (cval->id << 8),
buf, val_len, 100) >= 0) {
*value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len));
return 0;
}
}
- snd_printdd(KERN_ERR "cannot get ctl value: req = 0x%x, wValue = 0x%x, wIndex = 0x%x, type = %d\n", request, validx, cval->ctrlif | (cval->id << 8), cval->val_type);
+ snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
+ request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type);
return -EINVAL;
}
@@ -339,13 +382,15 @@ static int set_ctl_value(usb_mixer_elem_info_t *cval, int request, int validx, i
buf[0] = value_set & 0xff;
buf[1] = (value_set >> 8) & 0xff;
while (timeout -- > 0)
- if (snd_usb_ctl_msg(cval->chip->dev, usb_sndctrlpipe(cval->chip->dev, 0),
+ if (snd_usb_ctl_msg(cval->mixer->chip->dev,
+ usb_sndctrlpipe(cval->mixer->chip->dev, 0),
request,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
- validx, cval->ctrlif | (cval->id << 8),
+ validx, cval->mixer->ctrlif | (cval->id << 8),
buf, val_len, 100) >= 0)
return 0;
- snd_printdd(KERN_ERR "cannot set ctl value: req = 0x%x, wValue = 0x%x, wIndex = 0x%x, type = %d, data = 0x%x/0x%x\n", request, validx, cval->ctrlif | (cval->id << 8), cval->val_type, buf[0], buf[1]);
+ snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n",
+ request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type, buf[0], buf[1]);
return -EINVAL;
}
@@ -385,16 +430,22 @@ static int check_matrix_bitmap(unsigned char *bmap, int ich, int och, int num_ou
* if failed, give up and free the control instance.
*/
-static int add_control_to_empty(snd_card_t *card, snd_kcontrol_t *kctl)
+static int add_control_to_empty(mixer_build_t *state, snd_kcontrol_t *kctl)
{
+ usb_mixer_elem_info_t *cval = kctl->private_data;
int err;
- while (snd_ctl_find_id(card, &kctl->id))
+
+ while (snd_ctl_find_id(state->chip->card, &kctl->id))
kctl->id.index++;
- if ((err = snd_ctl_add(card, kctl)) < 0) {
+ if ((err = snd_ctl_add(state->chip->card, kctl)) < 0) {
snd_printd(KERN_ERR "cannot add control (err = %d)\n", err);
snd_ctl_free_one(kctl);
+ return err;
}
- return err;
+ cval->elem_id = &kctl->id;
+ cval->next_id_elem = state->mixer->id_elems[cval->id];
+ state->mixer->id_elems[cval->id] = cval;
+ return 0;
}
@@ -572,10 +623,8 @@ static struct usb_feature_control_info audio_feature_info[] = {
/* private_free callback */
static void usb_mixer_elem_free(snd_kcontrol_t *kctl)
{
- if (kctl->private_data) {
- kfree(kctl->private_data);
- kctl->private_data = NULL;
- }
+ kfree(kctl->private_data);
+ kctl->private_data = NULL;
}
@@ -608,7 +657,8 @@ static int get_min_max(usb_mixer_elem_info_t *cval, int default_min)
}
if (get_ctl_value(cval, GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 ||
get_ctl_value(cval, GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) {
- snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n", cval->id, cval->ctrlif, cval->control, cval->id);
+ snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n",
+ cval->id, cval->mixer->ctrlif, cval->control, cval->id);
return -EINVAL;
}
if (get_ctl_value(cval, GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) {
@@ -668,7 +718,7 @@ static int mixer_ctl_feature_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
if (cval->cmask & (1 << c)) {
err = get_cur_mix_value(cval, c + 1, &val);
if (err < 0) {
- if (cval->chip->ignore_ctl_error) {
+ if (cval->mixer->ignore_ctl_error) {
ucontrol->value.integer.value[0] = cval->min;
return 0;
}
@@ -684,7 +734,7 @@ static int mixer_ctl_feature_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
/* master channel */
err = get_cur_mix_value(cval, 0, &val);
if (err < 0) {
- if (cval->chip->ignore_ctl_error) {
+ if (cval->mixer->ignore_ctl_error) {
ucontrol->value.integer.value[0] = cval->min;
return 0;
}
@@ -710,7 +760,7 @@ static int mixer_ctl_feature_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
if (cval->cmask & (1 << c)) {
err = get_cur_mix_value(cval, c + 1, &oval);
if (err < 0) {
- if (cval->chip->ignore_ctl_error)
+ if (cval->mixer->ignore_ctl_error)
return 0;
return err;
}
@@ -727,7 +777,7 @@ static int mixer_ctl_feature_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
} else {
/* master channel */
err = get_cur_mix_value(cval, 0, &oval);
- if (err < 0 && cval->chip->ignore_ctl_error)
+ if (err < 0 && cval->mixer->ignore_ctl_error)
return 0;
if (err < 0)
return err;
@@ -779,8 +829,7 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc,
snd_printk(KERN_ERR "cannot malloc kcontrol\n");
return;
}
- cval->chip = state->chip;
- cval->ctrlif = state->ctrlif;
+ cval->mixer = state->mixer;
cval->id = unitid;
cval->control = control;
cval->cmask = ctl_mask;
@@ -855,16 +904,21 @@ static void build_feature_ctl(mixer_build_t *state, unsigned char *desc,
/* note that detection between firmware 2.1.1.7 (N101) and later 2.1.1.21 */
/* is not very clear from datasheets */
/* I hope that the min value is -15360 for newer firmware --jk */
- if (((state->vendor == 0x471 && (state->product == 0x104 || state->product == 0x105 || state->product == 0x101)) ||
- (state->vendor == 0x672 && state->product == 0x1041)) && !strcmp(kctl->id.name, "PCM Playback Volume") &&
- cval->min == -15616) {
- snd_printk("USB Audio: using volume control quirk for the UDA1321/N101 chip\n");
- cval->max = -256;
+ switch (state->chip->usb_id) {
+ case USB_ID(0x0471, 0x0101):
+ case USB_ID(0x0471, 0x0104):
+ case USB_ID(0x0471, 0x0105):
+ case USB_ID(0x0672, 0x1041):
+ if (!strcmp(kctl->id.name, "PCM Playback Volume") &&
+ cval->min == -15616) {
+ snd_printk("using volume control quirk for the UDA1321/N101 chip\n");
+ cval->max = -256;
+ }
}
snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res);
- add_control_to_empty(state->chip->card, kctl);
+ add_control_to_empty(state, kctl);
}
@@ -947,8 +1001,7 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc,
if (! cval)
return;
- cval->chip = state->chip;
- cval->ctrlif = state->ctrlif;
+ cval->mixer = state->mixer;
cval->id = unitid;
cval->control = in_ch + 1; /* based on 1 */
cval->val_type = USB_MIXER_S16;
@@ -979,7 +1032,7 @@ static void build_mixer_unit_ctl(mixer_build_t *state, unsigned char *desc,
snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n",
cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
- add_control_to_empty(state->chip->card, kctl);
+ add_control_to_empty(state, kctl);
}
@@ -1042,7 +1095,7 @@ static int mixer_ctl_procunit_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
int err, val;
err = get_cur_ctl_value(cval, cval->control << 8, &val);
- if (err < 0 && cval->chip->ignore_ctl_error) {
+ if (err < 0 && cval->mixer->ignore_ctl_error) {
ucontrol->value.integer.value[0] = cval->min;
return 0;
}
@@ -1061,7 +1114,7 @@ static int mixer_ctl_procunit_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
err = get_cur_ctl_value(cval, cval->control << 8, &oval);
if (err < 0) {
- if (cval->chip->ignore_ctl_error)
+ if (cval->mixer->ignore_ctl_error)
return 0;
return err;
}
@@ -1179,9 +1232,6 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char
}
type = combine_word(&dsc[4]);
- if (! type)
- return 0; /* undefined? */
-
for (info = list; info && info->type; info++)
if (info->type == type)
break;
@@ -1199,8 +1249,7 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char
snd_printk(KERN_ERR "cannot malloc kcontrol\n");
return -ENOMEM;
}
- cval->chip = state->chip;
- cval->ctrlif = state->ctrlif;
+ cval->mixer = state->mixer;
cval->id = unitid;
cval->control = valinfo->control;
cval->val_type = valinfo->val_type;
@@ -1241,7 +1290,7 @@ static int build_audio_procunit(mixer_build_t *state, int unitid, unsigned char
snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n",
cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
- if ((err = add_control_to_empty(state->chip->card, kctl)) < 0)
+ if ((err = add_control_to_empty(state, kctl)) < 0)
return err;
}
return 0;
@@ -1289,7 +1338,7 @@ static int mixer_ctl_selector_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
err = get_cur_ctl_value(cval, 0, &val);
if (err < 0) {
- if (cval->chip->ignore_ctl_error) {
+ if (cval->mixer->ignore_ctl_error) {
ucontrol->value.enumerated.item[0] = 0;
return 0;
}
@@ -1308,7 +1357,7 @@ static int mixer_ctl_selector_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
err = get_cur_ctl_value(cval, 0, &oval);
if (err < 0) {
- if (cval->chip->ignore_ctl_error)
+ if (cval->mixer->ignore_ctl_error)
return 0;
return err;
}
@@ -1386,8 +1435,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned
snd_printk(KERN_ERR "cannot malloc kcontrol\n");
return -ENOMEM;
}
- cval->chip = state->chip;
- cval->ctrlif = state->ctrlif;
+ cval->mixer = state->mixer;
cval->id = unitid;
cval->val_type = USB_MIXER_U8;
cval->channels = 1;
@@ -1415,7 +1463,9 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned
kfree(cval);
return -ENOMEM;
}
- if (check_input_term(state, desc[5 + i], &iterm) >= 0)
+ len = check_mapped_selector_name(state, unitid, i, namelist[i],
+ MAX_ITEM_NAME_LEN);
+ if (! len && check_input_term(state, desc[5 + i], &iterm) >= 0)
len = get_term_name(state, &iterm, namelist[i], MAX_ITEM_NAME_LEN, 0);
if (! len)
sprintf(namelist[i], "Input %d", i);
@@ -1450,7 +1500,7 @@ static int parse_audio_selector_unit(mixer_build_t *state, int unitid, unsigned
snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n",
cval->id, kctl->id.name, num_ins);
- if ((err = add_control_to_empty(state->chip->card, kctl)) < 0)
+ if ((err = add_control_to_empty(state, kctl)) < 0)
return err;
return 0;
@@ -1493,41 +1543,55 @@ static int parse_audio_unit(mixer_build_t *state, int unitid)
}
}
+static void snd_usb_mixer_free(struct usb_mixer_interface *mixer)
+{
+ kfree(mixer->id_elems);
+ if (mixer->urb) {
+ kfree(mixer->urb->transfer_buffer);
+ usb_free_urb(mixer->urb);
+ }
+ if (mixer->rc_urb)
+ usb_free_urb(mixer->rc_urb);
+ kfree(mixer->rc_setup_packet);
+ kfree(mixer);
+}
+
+static int snd_usb_mixer_dev_free(snd_device_t *device)
+{
+ struct usb_mixer_interface *mixer = device->device_data;
+ snd_usb_mixer_free(mixer);
+ return 0;
+}
+
/*
* create mixer controls
*
* walk through all OUTPUT_TERMINAL descriptors to search for mixers
*/
-int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif)
+static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
{
unsigned char *desc;
mixer_build_t state;
int err;
const struct usbmix_ctl_map *map;
- struct usb_device_descriptor *dev = &chip->dev->descriptor;
- struct usb_host_interface *hostif = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0];
-
- strcpy(chip->card->mixername, "USB Mixer");
+ struct usb_host_interface *hostif;
+ hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0];
memset(&state, 0, sizeof(state));
- state.chip = chip;
+ state.chip = mixer->chip;
+ state.mixer = mixer;
state.buffer = hostif->extra;
state.buflen = hostif->extralen;
- state.ctrlif = ctrlif;
- state.vendor = le16_to_cpu(dev->idVendor);
- state.product = le16_to_cpu(dev->idProduct);
/* check the mapping table */
- for (map = usbmix_ctl_maps; map->vendor; map++) {
- if (map->vendor == state.vendor && map->product == state.product) {
+ for (map = usbmix_ctl_maps; map->id; map++) {
+ if (map->id == state.chip->usb_id) {
state.map = map->map;
- chip->ignore_ctl_error = map->ignore_ctl_error;
+ state.selector_map = map->selector_map;
+ mixer->ignore_ctl_error = map->ignore_ctl_error;
break;
}
}
-#ifdef IGNORE_CTL_ERROR
- chip->ignore_ctl_error = 1;
-#endif
desc = NULL;
while ((desc = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, desc, OUTPUT_TERMINAL)) != NULL) {
@@ -1543,3 +1607,393 @@ int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif)
}
return 0;
}
+
+static void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer,
+ int unitid)
+{
+ usb_mixer_elem_info_t *info;
+
+ for (info = mixer->id_elems[unitid]; info; info = info->next_id_elem)
+ snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ info->elem_id);
+}
+
+static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer,
+ int unitid)
+{
+ if (mixer->rc_type == RC_NONE)
+ return;
+ /* unit ids specific to Extigy/Audigy 2 NX: */
+ switch (unitid) {
+ case 0: /* remote control */
+ mixer->rc_urb->dev = mixer->chip->dev;
+ usb_submit_urb(mixer->rc_urb, GFP_ATOMIC);
+ break;
+ case 4: /* digital in jack */
+ case 7: /* line in jacks */
+ case 19: /* speaker out jacks */
+ case 20: /* headphones out jack */
+ break;
+ default:
+ snd_printd(KERN_DEBUG "memory change in unknown unit %d\n", unitid);
+ break;
+ }
+}
+
+static void snd_usb_mixer_status_complete(struct urb *urb, struct pt_regs *regs)
+{
+ struct usb_mixer_interface *mixer = urb->context;
+
+ if (urb->status == 0) {
+ u8 *buf = urb->transfer_buffer;
+ int i;
+
+ for (i = urb->actual_length; i >= 2; buf += 2, i -= 2) {
+ snd_printd(KERN_DEBUG "status interrupt: %02x %02x\n",
+ buf[0], buf[1]);
+ /* ignore any notifications not from the control interface */
+ if ((buf[0] & 0x0f) != 0)
+ continue;
+ if (!(buf[0] & 0x40))
+ snd_usb_mixer_notify_id(mixer, buf[1]);
+ else
+ snd_usb_mixer_memory_change(mixer, buf[1]);
+ }
+ }
+ if (urb->status != -ENOENT && urb->status != -ECONNRESET) {
+ urb->dev = mixer->chip->dev;
+ usb_submit_urb(urb, GFP_ATOMIC);
+ }
+}
+
+/* create the handler for the optional status interrupt endpoint */
+static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
+{
+ struct usb_host_interface *hostif;
+ struct usb_endpoint_descriptor *ep;
+ void *transfer_buffer;
+ int buffer_length;
+ unsigned int epnum;
+
+ hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0];
+ /* we need one interrupt input endpoint */
+ if (get_iface_desc(hostif)->bNumEndpoints < 1)
+ return 0;
+ ep = get_endpoint(hostif, 0);
+ if ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_IN ||
+ (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
+ return 0;
+
+ epnum = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+ buffer_length = le16_to_cpu(ep->wMaxPacketSize);
+ transfer_buffer = kmalloc(buffer_length, GFP_KERNEL);
+ if (!transfer_buffer)
+ return -ENOMEM;
+ mixer->urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!mixer->urb) {
+ kfree(transfer_buffer);
+ return -ENOMEM;
+ }
+ usb_fill_int_urb(mixer->urb, mixer->chip->dev,
+ usb_rcvintpipe(mixer->chip->dev, epnum),
+ transfer_buffer, buffer_length,
+ snd_usb_mixer_status_complete, mixer, ep->bInterval);
+ usb_submit_urb(mixer->urb, GFP_KERNEL);
+ return 0;
+}
+
+static void snd_usb_soundblaster_remote_complete(struct urb *urb,
+ struct pt_regs *regs)
+{
+ struct usb_mixer_interface *mixer = urb->context;
+ /*
+ * format of remote control data:
+ * Extigy: xx 00
+ * Audigy 2 NX: 06 80 xx 00 00 00
+ */
+ int offset = mixer->rc_type == RC_EXTIGY ? 0 : 2;
+ u32 code;
+
+ if (urb->status < 0 || urb->actual_length <= offset)
+ return;
+ code = mixer->rc_buffer[offset];
+ /* the Mute button actually changes the mixer control */
+ if (code == 13)
+ snd_usb_mixer_notify_id(mixer, 18);
+ mixer->rc_code = code;
+ wmb();
+ wake_up(&mixer->rc_waitq);
+}
+
+static int snd_usb_sbrc_hwdep_open(snd_hwdep_t *hw, struct file *file)
+{
+ struct usb_mixer_interface *mixer = hw->private_data;
+
+ if (test_and_set_bit(0, &mixer->rc_hwdep_open))
+ return -EBUSY;
+ return 0;
+}
+
+static int snd_usb_sbrc_hwdep_release(snd_hwdep_t *hw, struct file *file)
+{
+ struct usb_mixer_interface *mixer = hw->private_data;
+
+ clear_bit(0, &mixer->rc_hwdep_open);
+ smp_mb__after_clear_bit();
+ return 0;
+}
+
+static long snd_usb_sbrc_hwdep_read(snd_hwdep_t *hw, char __user *buf,
+ long count, loff_t *offset)
+{
+ struct usb_mixer_interface *mixer = hw->private_data;
+ int err;
+ u32 rc_code;
+
+ if (count != 1 && count != 4)
+ return -EINVAL;
+ err = wait_event_interruptible(mixer->rc_waitq,
+ (rc_code = xchg(&mixer->rc_code, 0)) != 0);
+ if (err == 0) {
+ if (count == 1)
+ err = put_user(rc_code, buf);
+ else
+ err = put_user(rc_code, (u32 __user *)buf);
+ }
+ return err < 0 ? err : count;
+}
+
+static unsigned int snd_usb_sbrc_hwdep_poll(snd_hwdep_t *hw, struct file *file,
+ poll_table *wait)
+{
+ struct usb_mixer_interface *mixer = hw->private_data;
+
+ poll_wait(file, &mixer->rc_waitq, wait);
+ return mixer->rc_code ? POLLIN | POLLRDNORM : 0;
+}
+
+static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer)
+{
+ snd_hwdep_t *hwdep;
+ int err, len;
+
+ switch (mixer->chip->usb_id) {
+ case USB_ID(0x041e, 0x3000):
+ mixer->rc_type = RC_EXTIGY;
+ len = 2;
+ break;
+ case USB_ID(0x041e, 0x3020):
+ mixer->rc_type = RC_AUDIGY2NX;
+ len = 6;
+ break;
+ default:
+ return 0;
+ }
+
+ init_waitqueue_head(&mixer->rc_waitq);
+ err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep);
+ if (err < 0)
+ return err;
+ snprintf(hwdep->name, sizeof(hwdep->name),
+ "%s remote control", mixer->chip->card->shortname);
+ hwdep->iface = SNDRV_HWDEP_IFACE_SB_RC;
+ hwdep->private_data = mixer;
+ hwdep->ops.read = snd_usb_sbrc_hwdep_read;
+ hwdep->ops.open = snd_usb_sbrc_hwdep_open;
+ hwdep->ops.release = snd_usb_sbrc_hwdep_release;
+ hwdep->ops.poll = snd_usb_sbrc_hwdep_poll;
+
+ mixer->rc_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!mixer->rc_urb)
+ return -ENOMEM;
+ mixer->rc_setup_packet = kmalloc(sizeof(*mixer->rc_setup_packet), GFP_KERNEL);
+ if (!mixer->rc_setup_packet) {
+ usb_free_urb(mixer->rc_urb);
+ mixer->rc_urb = NULL;
+ return -ENOMEM;
+ }
+ mixer->rc_setup_packet->bRequestType =
+ USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+ mixer->rc_setup_packet->bRequest = GET_MEM;
+ mixer->rc_setup_packet->wValue = cpu_to_le16(0);
+ mixer->rc_setup_packet->wIndex = cpu_to_le16(0);
+ mixer->rc_setup_packet->wLength = cpu_to_le16(len);
+ usb_fill_control_urb(mixer->rc_urb, mixer->chip->dev,
+ usb_rcvctrlpipe(mixer->chip->dev, 0),
+ (u8*)mixer->rc_setup_packet, mixer->rc_buffer, len,
+ snd_usb_soundblaster_remote_complete, mixer);
+ return 0;
+}
+
+static int snd_audigy2nx_led_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ return 0;
+}
+
+static int snd_audigy2nx_led_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
+ int index = kcontrol->private_value;
+
+ ucontrol->value.integer.value[0] = mixer->audigy2nx_leds[index];
+ return 0;
+}
+
+static int snd_audigy2nx_led_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+ struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
+ int index = kcontrol->private_value;
+ int value = ucontrol->value.integer.value[0];
+ int err, changed;
+
+ if (value > 1)
+ return -EINVAL;
+ changed = value != mixer->audigy2nx_leds[index];
+ err = snd_usb_ctl_msg(mixer->chip->dev,
+ usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
+ value, index + 2, NULL, 0, 100);
+ if (err < 0)
+ return err;
+ mixer->audigy2nx_leds[index] = value;
+ return changed;
+}
+
+static snd_kcontrol_new_t snd_audigy2nx_controls[] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "CMSS LED Switch",
+ .info = snd_audigy2nx_led_info,
+ .get = snd_audigy2nx_led_get,
+ .put = snd_audigy2nx_led_put,
+ .private_value = 0,
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Power LED Switch",
+ .info = snd_audigy2nx_led_info,
+ .get = snd_audigy2nx_led_get,
+ .put = snd_audigy2nx_led_put,
+ .private_value = 1,
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Dolby Digital LED Switch",
+ .info = snd_audigy2nx_led_info,
+ .get = snd_audigy2nx_led_get,
+ .put = snd_audigy2nx_led_put,
+ .private_value = 2,
+ },
+};
+
+static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer)
+{
+ int i, err;
+
+ for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) {
+ err = snd_ctl_add(mixer->chip->card,
+ snd_ctl_new1(&snd_audigy2nx_controls[i], mixer));
+ if (err < 0)
+ return err;
+ }
+ mixer->audigy2nx_leds[1] = 1; /* Power LED is on by default */
+ return 0;
+}
+
+static void snd_audigy2nx_proc_read(snd_info_entry_t *entry,
+ snd_info_buffer_t *buffer)
+{
+ static const struct {
+ int unitid;
+ const char *name;
+ } jacks[] = {
+ {4, "dig in "},
+ {7, "line in"},
+ {19, "spk out"},
+ {20, "hph out"},
+ };
+ struct usb_mixer_interface *mixer = entry->private_data;
+ int i, err;
+ u8 buf[3];
+
+ snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname);
+ for (i = 0; i < ARRAY_SIZE(jacks); ++i) {
+ snd_iprintf(buffer, "%s: ", jacks[i].name);
+ err = snd_usb_ctl_msg(mixer->chip->dev,
+ usb_rcvctrlpipe(mixer->chip->dev, 0),
+ GET_MEM, USB_DIR_IN | USB_TYPE_CLASS |
+ USB_RECIP_INTERFACE, 0,
+ jacks[i].unitid << 8, buf, 3, 100);
+ if (err == 3 && buf[0] == 3)
+ snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]);
+ else
+ snd_iprintf(buffer, "?\n");
+ }
+}
+
+int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif)
+{
+ static snd_device_ops_t dev_ops = {
+ .dev_free = snd_usb_mixer_dev_free
+ };
+ struct usb_mixer_interface *mixer;
+ int err;
+
+ strcpy(chip->card->mixername, "USB Mixer");
+
+ mixer = kcalloc(1, sizeof(*mixer), GFP_KERNEL);
+ if (!mixer)
+ return -ENOMEM;
+ mixer->chip = chip;
+ mixer->ctrlif = ctrlif;
+#ifdef IGNORE_CTL_ERROR
+ mixer->ignore_ctl_error = 1;
+#endif
+ mixer->id_elems = kcalloc(256, sizeof(*mixer->id_elems), GFP_KERNEL);
+ if (!mixer->id_elems) {
+ kfree(mixer);
+ return -ENOMEM;
+ }
+
+ if ((err = snd_usb_mixer_controls(mixer)) < 0 ||
+ (err = snd_usb_mixer_status_create(mixer)) < 0)
+ goto _error;
+
+ if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0)
+ goto _error;
+
+ if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020)) {
+ snd_info_entry_t *entry;
+
+ if ((err = snd_audigy2nx_controls_create(mixer)) < 0)
+ goto _error;
+ if (!snd_card_proc_new(chip->card, "audigy2nx", &entry))
+ snd_info_set_text_ops(entry, mixer, 1024,
+ snd_audigy2nx_proc_read);
+ }
+
+ err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops);
+ if (err < 0)
+ goto _error;
+ list_add(&mixer->list, &chip->mixer_list);
+ return 0;
+
+_error:
+ snd_usb_mixer_free(mixer);
+ return err;
+}
+
+void snd_usb_mixer_disconnect(struct list_head *p)
+{
+ struct usb_mixer_interface *mixer;
+
+ mixer = list_entry(p, struct usb_mixer_interface, list);
+ if (mixer->urb)
+ usb_kill_urb(mixer->urb);
+ if (mixer->rc_urb)
+ usb_kill_urb(mixer->rc_urb);
+}
diff --git a/sound/usb/usbmixer_maps.c b/sound/usb/usbmixer_maps.c
index c69b4b0875f..f05500b05ec 100644
--- a/sound/usb/usbmixer_maps.c
+++ b/sound/usb/usbmixer_maps.c
@@ -26,10 +26,16 @@ struct usbmix_name_map {
int control;
};
+struct usbmix_selector_map {
+ int id;
+ int count;
+ const char **names;
+};
+
struct usbmix_ctl_map {
- int vendor;
- int product;
+ u32 id;
const struct usbmix_name_map *map;
+ const struct usbmix_selector_map *selector_map;
int ignore_ctl_error;
};
@@ -91,6 +97,96 @@ static struct usbmix_name_map extigy_map[] = {
{ 0 } /* terminator */
};
+/* Sound Blaster MP3+ controls mapping
+ * The default mixer channels have totally misleading names,
+ * e.g. no Master and fake PCM volume
+ * Pavel Mihaylov <bin@bash.info>
+ */
+static struct usbmix_name_map mp3plus_map[] = {
+ /* 1: IT pcm */
+ /* 2: IT mic */
+ /* 3: IT line */
+ /* 4: IT digital in */
+ /* 5: OT digital out */
+ /* 6: OT speaker */
+ /* 7: OT pcm capture */
+ { 8, "Capture Input Source" }, /* FU, default PCM Capture Source */
+ /* (Mic, Input 1 = Line input, Input 2 = Optical input) */
+ { 9, "Master Playback" }, /* FU, default Speaker 1 */
+ /* { 10, "Mic Capture", 1 }, */ /* FU, Mic Capture */
+ /* { 10, "Mic Capture", 2 }, */ /* FU, Mic Capture */
+ { 10, "Mic Boost", 7 }, /* FU, default Auto Gain Input */
+ { 11, "Line Capture" }, /* FU, default PCM Capture */
+ { 12, "Digital In Playback" }, /* FU, default PCM 1 */
+ /* { 13, "Mic Playback" }, */ /* FU, default Mic Playback */
+ { 14, "Line Playback" }, /* FU, default Speaker */
+ /* 15: MU */
+ { 0 } /* terminator */
+};
+
+/* Topology of SB Audigy 2 NX
+
+ +----------------------------->EU[27]--+
+ | v
+ | +----------------------------------->SU[29]---->FU[22]-->Dig_OUT[24]
+ | | ^
+USB_IN[1]-+------------+ +->EU[17]->+->FU[11]-+
+ | v | v |
+Dig_IN[4]---+->FU[6]-->MU[16]->FU[18]-+->EU[21]->SU[31]----->FU[30]->Hph_OUT[20]
+ | ^ | |
+Lin_IN[7]-+--->FU[8]---+ +->EU[23]->FU[28]------------->Spk_OUT[19]
+ | | v
+ +--->FU[12]------------------------------------->SU[14]--->USB_OUT[15]
+ | ^
+ +->FU[13]--------------------------------------+
+*/
+static struct usbmix_name_map audigy2nx_map[] = {
+ /* 1: IT pcm playback */
+ /* 4: IT digital in */
+ { 6, "Digital In Playback" }, /* FU */
+ /* 7: IT line in */
+ { 8, "Line Playback" }, /* FU */
+ { 11, "What-U-Hear Capture" }, /* FU */
+ { 12, "Line Capture" }, /* FU */
+ { 13, "Digital In Capture" }, /* FU */
+ { 14, "Capture Source" }, /* SU */
+ /* 15: OT pcm capture */
+ /* 16: MU w/o controls */
+ { 17, NULL }, /* DISABLED: EU (for what?) */
+ { 18, "Master Playback" }, /* FU */
+ /* 19: OT speaker */
+ /* 20: OT headphone */
+ { 21, NULL }, /* DISABLED: EU (for what?) */
+ { 22, "Digital Out Playback" }, /* FU */
+ { 23, NULL }, /* DISABLED: EU (for what?) */
+ /* 24: OT digital out */
+ { 27, NULL }, /* DISABLED: EU (for what?) */
+ { 28, "Speaker Playback" }, /* FU */
+ { 29, "Digital Out Source" }, /* SU */
+ { 30, "Headphone Playback" }, /* FU */
+ { 31, "Headphone Source" }, /* SU */
+ { 0 } /* terminator */
+};
+
+static struct usbmix_selector_map audigy2nx_selectors[] = {
+ {
+ .id = 14, /* Capture Source */
+ .count = 3,
+ .names = (const char*[]) {"Line", "Digital In", "What-U-Hear"}
+ },
+ {
+ .id = 29, /* Digital Out Source */
+ .count = 3,
+ .names = (const char*[]) {"Front", "PCM", "Digital In"}
+ },
+ {
+ .id = 31, /* Headphone Source */
+ .count = 2,
+ .names = (const char*[]) {"Front", "Side"}
+ },
+ { 0 } /* terminator */
+};
+
/* LineX FM Transmitter entry - needed to bypass controls bug */
static struct usbmix_name_map linex_map[] = {
/* 1: IT pcm */
@@ -127,9 +223,29 @@ static struct usbmix_name_map justlink_map[] = {
*/
static struct usbmix_ctl_map usbmix_ctl_maps[] = {
- { 0x41e, 0x3000, extigy_map, 1 },
- { 0x8bb, 0x2702, linex_map, 1 },
- { 0xc45, 0x1158, justlink_map, 0 },
+ {
+ .id = USB_ID(0x041e, 0x3000),
+ .map = extigy_map,
+ .ignore_ctl_error = 1,
+ },
+ {
+ .id = USB_ID(0x041e, 0x3010),
+ .map = mp3plus_map,
+ },
+ {
+ .id = USB_ID(0x041e, 0x3020),
+ .map = audigy2nx_map,
+ .selector_map = audigy2nx_selectors,
+ },
+ {
+ .id = USB_ID(0x08bb, 0x2702),
+ .map = linex_map,
+ .ignore_ctl_error = 1,
+ },
+ {
+ .id = USB_ID(0x0c45, 0x1158),
+ .map = justlink_map,
+ },
{ 0 } /* terminator */
};
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index 88bbd944d4b..f5135641b3e 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -203,11 +203,28 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "EDIROL",
.product_name = "UM-4",
- .ifnum = 2,
- .type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
- .out_cables = 0x000f,
- .in_cables = 0x000f
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = (const snd_usb_audio_quirk_t[]) {
+ {
+ .ifnum = 0,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 1,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 2,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x000f,
+ .in_cables = 0x000f
+ }
+ },
+ {
+ .ifnum = -1
+ }
}
}
},
@@ -216,11 +233,28 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Roland",
.product_name = "SC-8850",
- .ifnum = 2,
- .type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
- .out_cables = 0x003f,
- .in_cables = 0x003f
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = (const snd_usb_audio_quirk_t[]) {
+ {
+ .ifnum = 0,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 1,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 2,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x003f,
+ .in_cables = 0x003f
+ }
+ },
+ {
+ .ifnum = -1
+ }
}
}
},
@@ -229,11 +263,28 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Roland",
.product_name = "U-8",
- .ifnum = 2,
- .type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
- .out_cables = 0x0005,
- .in_cables = 0x0005
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = (const snd_usb_audio_quirk_t[]) {
+ {
+ .ifnum = 0,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 1,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 2,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x0005,
+ .in_cables = 0x0005
+ }
+ },
+ {
+ .ifnum = -1
+ }
}
}
},
@@ -242,11 +293,28 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "EDIROL",
.product_name = "UM-2",
- .ifnum = 2,
- .type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
- .out_cables = 0x0003,
- .in_cables = 0x0003
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = (const snd_usb_audio_quirk_t[]) {
+ {
+ .ifnum = 0,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 1,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 2,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x0003,
+ .in_cables = 0x0003
+ }
+ },
+ {
+ .ifnum = -1
+ }
}
}
},
@@ -255,11 +323,28 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Roland",
.product_name = "SC-8820",
- .ifnum = 2,
- .type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
- .out_cables = 0x0013,
- .in_cables = 0x0013
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = (const snd_usb_audio_quirk_t[]) {
+ {
+ .ifnum = 0,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 1,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 2,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x0013,
+ .in_cables = 0x0013
+ }
+ },
+ {
+ .ifnum = -1
+ }
}
}
},
@@ -268,11 +353,28 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Roland",
.product_name = "PC-300",
- .ifnum = 2,
- .type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
- .out_cables = 0x0001,
- .in_cables = 0x0001
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = (const snd_usb_audio_quirk_t[]) {
+ {
+ .ifnum = 0,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 1,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 2,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x0001,
+ .in_cables = 0x0001
+ }
+ },
+ {
+ .ifnum = -1
+ }
}
}
},
@@ -281,11 +383,28 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "EDIROL",
.product_name = "UM-1",
- .ifnum = 2,
- .type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
- .out_cables = 0x0001,
- .in_cables = 0x0001
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = (const snd_usb_audio_quirk_t[]) {
+ {
+ .ifnum = 0,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 1,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 2,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x0001,
+ .in_cables = 0x0001
+ }
+ },
+ {
+ .ifnum = -1
+ }
}
}
},
@@ -294,11 +413,28 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Roland",
.product_name = "SK-500",
- .ifnum = 2,
- .type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
- .out_cables = 0x0013,
- .in_cables = 0x0013
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = (const snd_usb_audio_quirk_t[]) {
+ {
+ .ifnum = 0,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 1,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 2,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x0013,
+ .in_cables = 0x0013
+ }
+ },
+ {
+ .ifnum = -1
+ }
}
}
},
@@ -421,11 +557,28 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "EDIROL",
.product_name = "SD-90",
- .ifnum = 2,
- .type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
- .out_cables = 0x000f,
- .in_cables = 0x000f
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = (const snd_usb_audio_quirk_t[]) {
+ {
+ .ifnum = 0,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 1,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 2,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x000f,
+ .in_cables = 0x000f
+ }
+ },
+ {
+ .ifnum = -1
+ }
}
}
},
@@ -434,11 +587,28 @@ YAMAHA_DEVICE(0x7010, "UB99"),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "Roland",
.product_name = "MMP-2",
- .ifnum = 2,
- .type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
- .out_cables = 0x0001,
- .in_cables = 0x0001
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = (const snd_usb_audio_quirk_t[]) {
+ {
+ .ifnum = 0,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 1,
+ .type = QUIRK_IGNORE_INTERFACE
+ },
+ {
+ .ifnum = 2,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const snd_usb_midi_endpoint_info_t) {
+ .out_cables = 0x0001,
+ .in_cables = 0x0001
+ }
+ },
+ {
+ .ifnum = -1
+ }
}
}
},
@@ -609,15 +779,33 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
{
+ /*
+ * This quirk is for the "Advanced Driver" mode. If off, the GS-10
+ * has ID 0x003c and is standard compliant, but has only 16-bit PCM
+ * and no MIDI.
+ */
USB_DEVICE_VENDOR_SPEC(0x0582, 0x003b),
.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
.vendor_name = "BOSS",
.product_name = "GS-10",
- .ifnum = 3,
- .type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const snd_usb_midi_endpoint_info_t) {
- .out_cables = 0x0003,
- .in_cables = 0x0003
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = & (const snd_usb_audio_quirk_t[]) {
+ {
+ .ifnum = 1,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ },
+ {
+ .ifnum = 2,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ },
+ {
+ .ifnum = 3,
+ .type = QUIRK_MIDI_STANDARD_INTERFACE
+ },
+ {
+ .ifnum = -1
+ }
}
}
},
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
index b06a267e5da..e6e6da15967 100644
--- a/sound/usb/usx2y/usbusx2y.c
+++ b/sound/usb/usx2y/usbusx2y.c
@@ -1,6 +1,11 @@
/*
* usbusy2y.c - ALSA USB US-428 Driver
*
+2005-04-14 Karsten Wiese
+ Version 0.8.7.2:
+ Call snd_card_free() instead of snd_card_free_in_thread() to prevent oops with dead keyboard symptom.
+ Tested ok with kernel 2.6.12-rc2.
+
2004-12-14 Karsten Wiese
Version 0.8.7.1:
snd_pcm_open for rawusb pcm-devices now returns -EBUSY if called without rawusb's hwdep device being open.
@@ -143,7 +148,7 @@
MODULE_AUTHOR("Karsten Wiese <annabellesgarden@yahoo.de>");
-MODULE_DESCRIPTION("TASCAM "NAME_ALLCAPS" Version 0.8.7.1");
+MODULE_DESCRIPTION("TASCAM "NAME_ALLCAPS" Version 0.8.7.2");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{TASCAM(0x1604), "NAME_ALLCAPS"(0x8001)(0x8005)(0x8007) }}");
@@ -430,8 +435,6 @@ static void usX2Y_usb_disconnect(struct usb_device* device, void* ptr)
if (ptr) {
usX2Ydev_t* usX2Y = usX2Y((snd_card_t*)ptr);
struct list_head* p;
- if (usX2Y->chip_status == USX2Y_STAT_CHIP_HUP) // on 2.6.1 kernel snd_usbmidi_disconnect()
- return; // calls us back. better leave :-) .
usX2Y->chip.shutdown = 1;
usX2Y->chip_status = USX2Y_STAT_CHIP_HUP;
usX2Y_unlinkSeq(&usX2Y->AS04);
@@ -439,11 +442,11 @@ static void usX2Y_usb_disconnect(struct usb_device* device, void* ptr)
snd_card_disconnect((snd_card_t*)ptr);
/* release the midi resources */
list_for_each(p, &usX2Y->chip.midi_list) {
- snd_usbmidi_disconnect(p, &snd_usX2Y_usb_driver);
+ snd_usbmidi_disconnect(p);
}
if (usX2Y->us428ctls_sharedmem)
wake_up(&usX2Y->us428ctls_wait_queue_head);
- snd_card_free_in_thread((snd_card_t*)ptr);
+ snd_card_free((snd_card_t*)ptr);
}
}
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
index 4c292e09006..62dfd28b3b0 100644
--- a/sound/usb/usx2y/usbusx2yaudio.c
+++ b/sound/usb/usx2y/usbusx2yaudio.c
@@ -401,10 +401,8 @@ static void usX2Y_urbs_release(snd_usX2Y_substream_t *subs)
for (i = 0; i < NRURBS; i++)
usX2Y_urb_release(subs->urb + i, subs != subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]);
- if (subs->tmpbuf) {
- kfree(subs->tmpbuf);
- subs->tmpbuf = NULL;
- }
+ kfree(subs->tmpbuf);
+ subs->tmpbuf = NULL;
}
/*
* initialize a substream's urbs